Repository: mc-server/MCServer Branch: master Commit: 7fd3fa5c9345 Files: 1280 Total size: 16.2 MB Directory structure: gitextract_eeezw5ae/ ├── .clang-format ├── .clang-tidy ├── .editorconfig ├── .gitattributes ├── .github/ │ ├── FUNDING.yml │ ├── ISSUE_TEMPLATE/ │ │ ├── config.yml │ │ └── issue-template.md │ └── workflows/ │ ├── Build.yml │ └── StyleCheck.yml ├── .gitignore ├── .gitmodules ├── BACKERS ├── CMake/ │ ├── AddDependencies.cmake │ ├── Fixups.cmake │ ├── GenerateBindings.cmake │ ├── GroupSources.cmake │ └── StampBuild.cmake ├── CMakeLists.txt ├── COMPILING.md ├── CONTRIBUTING.md ├── CONTRIBUTORS ├── CheckLua.cmake ├── Doxyfile ├── GETTING-STARTED.md ├── Jenkinsfile ├── LICENSE ├── README.md ├── Server/ │ ├── .gitignore │ ├── Install/ │ │ ├── .gitignore │ │ ├── Cuberite_high_detail_debug.cmd │ │ ├── Cuberite_medium_detail_debug.cmd │ │ ├── PackWindowsExecutables.cmd │ │ ├── ThirdPartyLicenses/ │ │ │ ├── LibEvent-LICENSE.txt │ │ │ ├── Lua-LICENSE.txt │ │ │ ├── LuaExpat-license.html │ │ │ ├── LuaSQLite3-LICENSE.txt │ │ │ ├── MersenneTwister-LICENSE.txt │ │ │ ├── SQLiteCpp-LICENSE.txt │ │ │ └── fmt-LICENSE.rst │ │ ├── UnixExecutables.list │ │ ├── WindowsExecutables.list │ │ └── WindowsPDBs.list │ ├── Plugins/ │ │ ├── .gitignore │ │ ├── APIDump/ │ │ │ ├── APIDesc.lua │ │ │ ├── Classes/ │ │ │ │ ├── BlockArea.lua │ │ │ │ ├── BlockEntities.lua │ │ │ │ ├── Geometry.lua │ │ │ │ ├── Network.lua │ │ │ │ ├── Plugins.lua │ │ │ │ ├── Projectiles.lua │ │ │ │ ├── RankManager.lua │ │ │ │ ├── WebAdmin.lua │ │ │ │ └── World.lua │ │ │ ├── Hooks/ │ │ │ │ ├── OnBlockSpread.lua │ │ │ │ ├── OnBlockToPickups.lua │ │ │ │ ├── OnBrewingCompleted.lua │ │ │ │ ├── OnBrewingCompleting.lua │ │ │ │ ├── OnChat.lua │ │ │ │ ├── OnChunkAvailable.lua │ │ │ │ ├── OnChunkGenerated.lua │ │ │ │ ├── OnChunkGenerating.lua │ │ │ │ ├── OnChunkUnloaded.lua │ │ │ │ ├── OnChunkUnloading.lua │ │ │ │ ├── OnCollectingPickup.lua │ │ │ │ ├── OnCraftingNoRecipe.lua │ │ │ │ ├── OnDisconnect.lua │ │ │ │ ├── OnDropSpense.lua │ │ │ │ ├── OnEntityAddEffect.lua │ │ │ │ ├── OnEntityChangedWorld.lua │ │ │ │ ├── OnEntityChangingWorld.lua │ │ │ │ ├── OnEntityTeleport.lua │ │ │ │ ├── OnExecuteCommand.lua │ │ │ │ ├── OnExploded.lua │ │ │ │ ├── OnExploding.lua │ │ │ │ ├── OnHandshake.lua │ │ │ │ ├── OnHopperPullingItem.lua │ │ │ │ ├── OnHopperPushingItem.lua │ │ │ │ ├── OnKilled.lua │ │ │ │ ├── OnKilling.lua │ │ │ │ ├── OnLogin.lua │ │ │ │ ├── OnPlayerAnimation.lua │ │ │ │ ├── OnPlayerBreakingBlock.lua │ │ │ │ ├── OnPlayerBrokenBlock.lua │ │ │ │ ├── OnPlayerCrouched.lua │ │ │ │ ├── OnPlayerDestroyed.lua │ │ │ │ ├── OnPlayerEating.lua │ │ │ │ ├── OnPlayerFished.lua │ │ │ │ ├── OnPlayerFishing.lua │ │ │ │ ├── OnPlayerFoodLevelChange.lua │ │ │ │ ├── OnPlayerJoined.lua │ │ │ │ ├── OnPlayerLeftClick.lua │ │ │ │ ├── OnPlayerMoving.lua │ │ │ │ ├── OnPlayerOpeningWindow.lua │ │ │ │ ├── OnPlayerPlacedBlock.lua │ │ │ │ ├── OnPlayerPlacingBlock.lua │ │ │ │ ├── OnPlayerRightClick.lua │ │ │ │ ├── OnPlayerRightClickingEntity.lua │ │ │ │ ├── OnPlayerShooting.lua │ │ │ │ ├── OnPlayerSpawned.lua │ │ │ │ ├── OnPlayerTossingItem.lua │ │ │ │ ├── OnPlayerUsedBlock.lua │ │ │ │ ├── OnPlayerUsedItem.lua │ │ │ │ ├── OnPlayerUsingBlock.lua │ │ │ │ ├── OnPlayerUsingItem.lua │ │ │ │ ├── OnPluginMessage.lua │ │ │ │ ├── OnPluginsLoaded.lua │ │ │ │ ├── OnPostCrafting.lua │ │ │ │ ├── OnPreCrafting.lua │ │ │ │ ├── OnProjectileHitBlock.lua │ │ │ │ ├── OnProjectileHitEntity.lua │ │ │ │ ├── OnServerPing.lua │ │ │ │ ├── OnSpawnedEntity.lua │ │ │ │ ├── OnSpawnedMonster.lua │ │ │ │ ├── OnSpawningEntity.lua │ │ │ │ ├── OnSpawningMonster.lua │ │ │ │ ├── OnTakeDamage.lua │ │ │ │ ├── OnTick.lua │ │ │ │ ├── OnUpdatedSign.lua │ │ │ │ ├── OnUpdatingSign.lua │ │ │ │ ├── OnWeatherChanged.lua │ │ │ │ ├── OnWeatherChanging.lua │ │ │ │ ├── OnWorldStarted.lua │ │ │ │ └── OnWorldTick.lua │ │ │ ├── InfoFile.html │ │ │ ├── LICENSE-prettify.txt │ │ │ ├── SettingUpDecoda.html │ │ │ ├── SettingUpLuaLanguageServer.html │ │ │ ├── SettingUpZeroBrane.html │ │ │ ├── Static/ │ │ │ │ └── .gitignore │ │ │ ├── UsingChunkStays.html │ │ │ ├── WebWorldThreads.html │ │ │ ├── Writing-a-Cuberite-plugin.html │ │ │ ├── _preload.lua │ │ │ ├── lang-lua.js │ │ │ ├── lualanguageserver.lua │ │ │ ├── main.css │ │ │ ├── main_APIDump.lua │ │ │ ├── prettify.css │ │ │ └── prettify.js │ │ ├── Debuggers/ │ │ │ ├── Debuggers.lua │ │ │ ├── Info.lua │ │ │ └── Inject.lua │ │ ├── DumpInfo/ │ │ │ └── Init.lua │ │ ├── HookNotify/ │ │ │ └── HookNotify.lua │ │ ├── InfoDump.lua │ │ ├── InfoReg.lua │ │ ├── NetworkTest/ │ │ │ ├── Info.lua │ │ │ ├── NetworkTest.lua │ │ │ └── splashes.txt │ │ └── TestLuaRocks/ │ │ └── TestLuaRocks.lua │ ├── Prefabs/ │ │ ├── PieceStructures/ │ │ │ ├── NetherFort.cubeset │ │ │ ├── RainbowRoad.cubeset │ │ │ ├── TestRails.cubeset │ │ │ ├── TreePaths.cubeset │ │ │ └── UnderwaterBase.cubeset │ │ ├── SinglePieceStructures/ │ │ │ ├── DesertPyramid.cubeset │ │ │ ├── DesertWell.cubeset │ │ │ ├── JungleTemple.cubeset │ │ │ └── WitchHut.cubeset │ │ └── Villages/ │ │ ├── AlchemistVillage.cubeset │ │ ├── JapaneseVillage.cubeset │ │ ├── PlainsVillage.cubeset │ │ ├── SandFlatRoofVillage.cubeset │ │ └── SandVillage.cubeset │ ├── Protocol/ │ │ ├── 1.12.2/ │ │ │ └── base.recipes.txt │ │ ├── 1.13/ │ │ │ └── base.btp.txt │ │ ├── 1.14.4/ │ │ │ └── base.btp.txt │ │ └── UpgradeBlockTypePalette.txt │ ├── README.txt │ ├── brewing.txt │ ├── delete_windows_service.cmd │ ├── furnace.txt │ ├── hg │ ├── hg.supp │ ├── install_windows_service.cmd │ ├── vg │ ├── vg.supp │ └── webadmin/ │ ├── GenerateSelfSignedHTTPSCertUsingOpenssl.cmd │ ├── GenerateSelfSignedHTTPSCertUsingOpenssl.sh │ ├── files/ │ │ ├── guest.html │ │ └── style.css │ ├── login_template.html │ └── template.lua ├── SetFlags.cmake ├── TESTING.md ├── Tools/ │ ├── .gitignore │ ├── AnvilStats/ │ │ ├── .gitignore │ │ ├── AnvilStats.cpp │ │ ├── AnvilStats.txt │ │ ├── BiomeMap.cpp │ │ ├── BiomeMap.h │ │ ├── CMakeLists.txt │ │ ├── Callback.h │ │ ├── ChunkExtract.cpp │ │ ├── ChunkExtract.h │ │ ├── Globals.cpp │ │ ├── Globals.h │ │ ├── HeightBiomeMap.cpp │ │ ├── HeightBiomeMap.h │ │ ├── HeightMap.cpp │ │ ├── HeightMap.h │ │ ├── ImageComposingCallback.cpp │ │ ├── ImageComposingCallback.h │ │ ├── Processor.cpp │ │ ├── Processor.h │ │ ├── SpringStats.cpp │ │ ├── SpringStats.h │ │ ├── Statistics.cpp │ │ ├── Statistics.h │ │ ├── Utils.cpp │ │ ├── Utils.h │ │ └── profile_run.cmd │ ├── BlockTypePaletteGenerator/ │ │ ├── .gitignore │ │ ├── Generator.lua │ │ ├── UpgradeGenerator.lua │ │ └── UpgradePaletteCheck.lua │ ├── BlockZapper/ │ │ ├── .gitignore │ │ ├── BlockZapper.cpp │ │ ├── BlockZapper.txt │ │ ├── GNUmakefile │ │ ├── Globals.cpp │ │ ├── Globals.h │ │ ├── Regions.cpp │ │ ├── Regions.h │ │ ├── Zapper.cpp │ │ └── Zapper.h │ ├── GeneratorPerformanceTest/ │ │ ├── CMakeLists.txt │ │ └── GeneratorPerformanceTest.cpp │ ├── GrownBiomeGenVisualiser/ │ │ ├── .gitignore │ │ ├── CMakeLists.txt │ │ ├── Globals.cpp │ │ ├── Globals.h │ │ ├── GrownBiomeGenVisualiser.cpp │ │ └── README.md │ ├── MCADefrag/ │ │ ├── .gitignore │ │ ├── CMakeLists.txt │ │ ├── MCADefrag.cpp │ │ └── MCADefrag.h │ ├── MemDumpAnalysis/ │ │ ├── .gitignore │ │ ├── Globals.cpp │ │ ├── Globals.h │ │ ├── MemDumpAnalysis.cpp │ │ └── targetver.h │ ├── NoiseSpeedTest/ │ │ ├── CMakeLists.txt │ │ ├── NoiseSpeedTest.cpp │ │ ├── NoiseSpeedTest.h │ │ └── SimplexNoise.h │ ├── ProtoProxy/ │ │ ├── .gitignore │ │ ├── CMakeLists.txt │ │ ├── Connection.cpp │ │ ├── Connection.h │ │ ├── ProtoProxy.cpp │ │ ├── ProtoProxy.txt │ │ ├── Server.cpp │ │ └── Server.h │ ├── QtBiomeVisualiser/ │ │ ├── .gitignore │ │ ├── BiomeView.cpp │ │ ├── BiomeView.h │ │ ├── ChunkSource.cpp │ │ ├── ChunkSource.h │ │ ├── GeneratorSetup.cpp │ │ ├── GeneratorSetup.h │ │ ├── Globals.h │ │ ├── MainWindow.cpp │ │ ├── MainWindow.h │ │ ├── QtBiomeVisualiser.cpp │ │ ├── QtBiomeVisualiser.pro │ │ ├── QtChunk.cpp │ │ ├── QtChunk.h │ │ ├── Region.cpp │ │ ├── Region.h │ │ ├── RegionCache.cpp │ │ ├── RegionCache.h │ │ ├── RegionLoader.cpp │ │ └── RegionLoader.h │ ├── RCONClient/ │ │ ├── .gitignore │ │ ├── Globals.cpp │ │ ├── Globals.h │ │ └── RCONClient.cpp │ └── ToLuaDoxy/ │ ├── Doxyfile │ ├── Globals.cpp │ ├── Globals.h │ └── ToLuaDoxy.cpp ├── android/ │ ├── .gitignore │ ├── CMakeLists.txt │ └── compile.sh ├── app.yml ├── appveyor.yml ├── cibuild.sh ├── clang-tidy.sh ├── cloc-exclude.txt ├── compile.sh ├── dev-docs/ │ ├── .gitignore │ ├── API class inheritance - blockentities.gv │ ├── API class inheritance - entities.gv │ ├── Cubeset file format.html │ ├── ExportingAPI.html │ ├── Generator.html │ ├── Login sequence.txt │ ├── NBT Examples/ │ │ ├── single chunk NBT data.txt │ │ └── tile entities.txt │ ├── Object ownership.gv │ ├── Plugin API.md │ ├── SocketThreads states.gv │ ├── Springs.ods │ ├── _files.txt │ ├── js/ │ │ ├── ValueMap.js │ │ └── grown.js │ └── style.css ├── easyinstall.sh ├── nightlybuild.sh ├── src/ │ ├── Bindings/ │ │ ├── .gitignore │ │ ├── AllToLua.bat │ │ ├── AllToLua.pkg │ │ ├── AllToLua.sh │ │ ├── AllToLua_lua.bat │ │ ├── BindingsProcessor.lua │ │ ├── BlockState.cpp │ │ ├── BlockState.h │ │ ├── BlockTypePalette.cpp │ │ ├── BlockTypePalette.h │ │ ├── BlockTypeRegistry.cpp │ │ ├── BlockTypeRegistry.h │ │ ├── CMakeLists.txt │ │ ├── CheckBindingsDependencies.lua │ │ ├── DeprecatedBindings.cpp │ │ ├── DeprecatedBindings.h │ │ ├── DiffAPIDesc.lua │ │ ├── LuaChunkStay.cpp │ │ ├── LuaChunkStay.h │ │ ├── LuaFunctions.h │ │ ├── LuaJson.cpp │ │ ├── LuaJson.h │ │ ├── LuaNameLookup.cpp │ │ ├── LuaNameLookup.h │ │ ├── LuaServerHandle.cpp │ │ ├── LuaServerHandle.h │ │ ├── LuaState.cpp │ │ ├── LuaState.h │ │ ├── LuaTCPLink.cpp │ │ ├── LuaTCPLink.h │ │ ├── LuaUDPEndpoint.cpp │ │ ├── LuaUDPEndpoint.h │ │ ├── LuaWindow.cpp │ │ ├── LuaWindow.h │ │ ├── ManualBindings.cpp │ │ ├── ManualBindings.h │ │ ├── ManualBindings_BlockArea.cpp │ │ ├── ManualBindings_Network.cpp │ │ ├── ManualBindings_RankManager.cpp │ │ ├── ManualBindings_World.cpp │ │ ├── Plugin.cpp │ │ ├── Plugin.h │ │ ├── PluginLua.cpp │ │ ├── PluginLua.h │ │ ├── PluginManager.cpp │ │ ├── PluginManager.h │ │ └── tolua++.h │ ├── BiomeDef.cpp │ ├── BiomeDef.h │ ├── BlockArea.cpp │ ├── BlockArea.h │ ├── BlockEntities/ │ │ ├── BannerEntity.cpp │ │ ├── BannerEntity.h │ │ ├── BeaconEntity.cpp │ │ ├── BeaconEntity.h │ │ ├── BedEntity.cpp │ │ ├── BedEntity.h │ │ ├── BlockEntity.cpp │ │ ├── BlockEntity.h │ │ ├── BlockEntityWithItems.cpp │ │ ├── BlockEntityWithItems.h │ │ ├── BrewingstandEntity.cpp │ │ ├── BrewingstandEntity.h │ │ ├── CMakeLists.txt │ │ ├── ChestEntity.cpp │ │ ├── ChestEntity.h │ │ ├── CommandBlockEntity.cpp │ │ ├── CommandBlockEntity.h │ │ ├── DispenserEntity.cpp │ │ ├── DispenserEntity.h │ │ ├── DropSpenserEntity.cpp │ │ ├── DropSpenserEntity.h │ │ ├── DropperEntity.cpp │ │ ├── DropperEntity.h │ │ ├── EnchantingTableEntity.cpp │ │ ├── EnchantingTableEntity.h │ │ ├── EndPortalEntity.cpp │ │ ├── EndPortalEntity.h │ │ ├── EnderChestEntity.cpp │ │ ├── EnderChestEntity.h │ │ ├── FlowerPotEntity.cpp │ │ ├── FlowerPotEntity.h │ │ ├── FurnaceEntity.cpp │ │ ├── FurnaceEntity.h │ │ ├── HopperEntity.cpp │ │ ├── HopperEntity.h │ │ ├── JukeboxEntity.cpp │ │ ├── JukeboxEntity.h │ │ ├── MobHeadEntity.cpp │ │ ├── MobHeadEntity.h │ │ ├── MobSpawnerEntity.cpp │ │ ├── MobSpawnerEntity.h │ │ ├── NoteEntity.cpp │ │ ├── NoteEntity.h │ │ ├── SignEntity.cpp │ │ └── SignEntity.h │ ├── BlockInServerPluginInterface.h │ ├── BlockInfo.cpp │ ├── BlockInfo.h │ ├── BlockState.h │ ├── BlockTracer.h │ ├── BlockType.cpp │ ├── BlockType.h │ ├── Blocks/ │ │ ├── BlockAir.h │ │ ├── BlockAnvil.h │ │ ├── BlockBed.cpp │ │ ├── BlockBed.h │ │ ├── BlockBigFlower.h │ │ ├── BlockBookShelf.h │ │ ├── BlockBrewingStand.h │ │ ├── BlockButton.h │ │ ├── BlockCactus.h │ │ ├── BlockCake.h │ │ ├── BlockCarpet.h │ │ ├── BlockCauldron.h │ │ ├── BlockChest.h │ │ ├── BlockCloth.h │ │ ├── BlockCobWeb.h │ │ ├── BlockCocoaPod.h │ │ ├── BlockCommandBlock.h │ │ ├── BlockComparator.h │ │ ├── BlockConcretePowder.h │ │ ├── BlockCrops.h │ │ ├── BlockDaylightSensor.h │ │ ├── BlockDeadBush.h │ │ ├── BlockDefaultBlock.h │ │ ├── BlockDirt.h │ │ ├── BlockDoor.cpp │ │ ├── BlockDoor.h │ │ ├── BlockDropSpenser.h │ │ ├── BlockEnchantingTable.h │ │ ├── BlockEndPortalFrame.h │ │ ├── BlockEnderChest.h │ │ ├── BlockEntity.h │ │ ├── BlockFarmland.h │ │ ├── BlockFence.h │ │ ├── BlockFenceGate.h │ │ ├── BlockFire.h │ │ ├── BlockFlower.h │ │ ├── BlockFlowerPot.h │ │ ├── BlockFluid.h │ │ ├── BlockFurnace.h │ │ ├── BlockGlass.h │ │ ├── BlockGlazedTerracotta.h │ │ ├── BlockGlowstone.h │ │ ├── BlockGrass.h │ │ ├── BlockGravel.h │ │ ├── BlockHandler.cpp │ │ ├── BlockHandler.h │ │ ├── BlockHopper.h │ │ ├── BlockHugeMushroom.h │ │ ├── BlockIce.h │ │ ├── BlockInfested.h │ │ ├── BlockJukebox.h │ │ ├── BlockLadder.h │ │ ├── BlockLeaves.h │ │ ├── BlockLever.h │ │ ├── BlockLilypad.h │ │ ├── BlockMelon.h │ │ ├── BlockMobHead.h │ │ ├── BlockMobSpawner.h │ │ ├── BlockMushroom.h │ │ ├── BlockMycelium.h │ │ ├── BlockNetherWart.h │ │ ├── BlockNetherrack.h │ │ ├── BlockNoteBlock.h │ │ ├── BlockObserver.h │ │ ├── BlockOre.h │ │ ├── BlockPackedIce.h │ │ ├── BlockPiston.cpp │ │ ├── BlockPiston.h │ │ ├── BlockPlanks.h │ │ ├── BlockPlant.h │ │ ├── BlockPluginInterface.h │ │ ├── BlockPortal.h │ │ ├── BlockPressurePlate.h │ │ ├── BlockPumpkin.h │ │ ├── BlockQuartz.h │ │ ├── BlockRail.h │ │ ├── BlockRedstoneLamp.h │ │ ├── BlockRedstoneOre.h │ │ ├── BlockRedstoneRepeater.h │ │ ├── BlockRedstoneWire.h │ │ ├── BlockSand.h │ │ ├── BlockSapling.h │ │ ├── BlockSeaLantern.h │ │ ├── BlockSideways.h │ │ ├── BlockSignPost.h │ │ ├── BlockSlab.h │ │ ├── BlockSlime.h │ │ ├── BlockSnow.h │ │ ├── BlockSponge.h │ │ ├── BlockStairs.h │ │ ├── BlockStandingBanner.h │ │ ├── BlockStems.h │ │ ├── BlockStone.h │ │ ├── BlockSugarCane.h │ │ ├── BlockTNT.h │ │ ├── BlockTallGrass.h │ │ ├── BlockTorch.h │ │ ├── BlockTrapdoor.h │ │ ├── BlockTripwire.h │ │ ├── BlockTripwireHook.h │ │ ├── BlockVines.h │ │ ├── BlockWallBanner.h │ │ ├── BlockWallSign.h │ │ ├── BlockWorkbench.h │ │ ├── BroadcastInterface.h │ │ ├── CMakeLists.txt │ │ ├── ChunkInterface.cpp │ │ ├── ChunkInterface.h │ │ ├── GetHandlerCompileTimeTemplate.h │ │ ├── Mixins/ │ │ │ ├── DirtLikeUnderneath.h │ │ │ ├── Mixins.h │ │ │ └── SolidSurfaceUnderneath.h │ │ └── WorldInterface.h │ ├── BoundingBox.cpp │ ├── BoundingBox.h │ ├── BrewingRecipes.cpp │ ├── BrewingRecipes.h │ ├── Broadcaster.cpp │ ├── BuildInfo.h.cmake │ ├── ByteBuffer.cpp │ ├── ByteBuffer.h │ ├── CMakeLists.txt │ ├── ChatColor.cpp │ ├── ChatColor.h │ ├── CheckBasicStyle.lua │ ├── Chunk.cpp │ ├── Chunk.h │ ├── ChunkData.cpp │ ├── ChunkData.h │ ├── ChunkDataCallback.h │ ├── ChunkDef.h │ ├── ChunkGeneratorThread.cpp │ ├── ChunkGeneratorThread.h │ ├── ChunkMap.cpp │ ├── ChunkMap.h │ ├── ChunkSender.cpp │ ├── ChunkSender.h │ ├── ChunkStay.cpp │ ├── ChunkStay.h │ ├── CircularBufferCompressor.cpp │ ├── CircularBufferCompressor.h │ ├── ClientHandle.cpp │ ├── ClientHandle.h │ ├── Color.cpp │ ├── Color.h │ ├── CommandOutput.cpp │ ├── CommandOutput.h │ ├── CompositeChat.cpp │ ├── CompositeChat.h │ ├── CraftingRecipes.cpp │ ├── CraftingRecipes.h │ ├── Cuboid.cpp │ ├── Cuboid.h │ ├── DeadlockDetect.cpp │ ├── DeadlockDetect.h │ ├── Defines.cpp │ ├── Defines.h │ ├── EffectID.h │ ├── Enchantments.cpp │ ├── Enchantments.h │ ├── Endianness.h │ ├── Entities/ │ │ ├── ArrowEntity.cpp │ │ ├── ArrowEntity.h │ │ ├── Boat.cpp │ │ ├── Boat.h │ │ ├── CMakeLists.txt │ │ ├── EnderCrystal.cpp │ │ ├── EnderCrystal.h │ │ ├── Entity.cpp │ │ ├── Entity.h │ │ ├── EntityEffect.cpp │ │ ├── EntityEffect.h │ │ ├── ExpBottleEntity.cpp │ │ ├── ExpBottleEntity.h │ │ ├── ExpOrb.cpp │ │ ├── ExpOrb.h │ │ ├── FallingBlock.cpp │ │ ├── FallingBlock.h │ │ ├── FireChargeEntity.cpp │ │ ├── FireChargeEntity.h │ │ ├── FireworkEntity.cpp │ │ ├── FireworkEntity.h │ │ ├── Floater.cpp │ │ ├── Floater.h │ │ ├── GhastFireballEntity.cpp │ │ ├── GhastFireballEntity.h │ │ ├── HangingEntity.cpp │ │ ├── HangingEntity.h │ │ ├── ItemFrame.cpp │ │ ├── ItemFrame.h │ │ ├── LeashKnot.cpp │ │ ├── LeashKnot.h │ │ ├── Minecart.cpp │ │ ├── Minecart.h │ │ ├── Painting.cpp │ │ ├── Painting.h │ │ ├── Pawn.cpp │ │ ├── Pawn.h │ │ ├── Pickup.cpp │ │ ├── Pickup.h │ │ ├── Player.cpp │ │ ├── Player.h │ │ ├── ProjectileEntity.cpp │ │ ├── ProjectileEntity.h │ │ ├── SplashPotionEntity.cpp │ │ ├── SplashPotionEntity.h │ │ ├── TNTEntity.cpp │ │ ├── TNTEntity.h │ │ ├── ThrownEggEntity.cpp │ │ ├── ThrownEggEntity.h │ │ ├── ThrownEnderPearlEntity.cpp │ │ ├── ThrownEnderPearlEntity.h │ │ ├── ThrownSnowballEntity.cpp │ │ ├── ThrownSnowballEntity.h │ │ ├── WitherSkullEntity.cpp │ │ └── WitherSkullEntity.h │ ├── FastRandom.cpp │ ├── FastRandom.h │ ├── ForEachChunkProvider.h │ ├── FunctionRef.h │ ├── FurnaceRecipe.cpp │ ├── FurnaceRecipe.h │ ├── Generating/ │ │ ├── BioGen.cpp │ │ ├── BioGen.h │ │ ├── CMakeLists.txt │ │ ├── Caves.cpp │ │ ├── Caves.h │ │ ├── ChunkDesc.cpp │ │ ├── ChunkDesc.h │ │ ├── ChunkGenerator.cpp │ │ ├── ChunkGenerator.h │ │ ├── CompoGen.cpp │ │ ├── CompoGen.h │ │ ├── CompoGenBiomal.cpp │ │ ├── CompoGenBiomal.h │ │ ├── ComposableGenerator.cpp │ │ ├── ComposableGenerator.h │ │ ├── CompositedHeiGen.h │ │ ├── DistortedHeightmap.cpp │ │ ├── DistortedHeightmap.h │ │ ├── DungeonRoomsFinisher.cpp │ │ ├── DungeonRoomsFinisher.h │ │ ├── EndGen.cpp │ │ ├── EndGen.h │ │ ├── EnderDragonFightStructuresGen.cpp │ │ ├── EnderDragonFightStructuresGen.h │ │ ├── FinishGen.cpp │ │ ├── FinishGen.h │ │ ├── GridStructGen.cpp │ │ ├── GridStructGen.h │ │ ├── HeiGen.cpp │ │ ├── HeiGen.h │ │ ├── IntGen.h │ │ ├── MineShafts.cpp │ │ ├── MineShafts.h │ │ ├── Noise3DGenerator.cpp │ │ ├── Noise3DGenerator.h │ │ ├── PieceGeneratorBFSTree.cpp │ │ ├── PieceGeneratorBFSTree.h │ │ ├── PieceModifier.cpp │ │ ├── PieceModifier.h │ │ ├── PiecePool.cpp │ │ ├── PiecePool.h │ │ ├── PieceStructuresGen.cpp │ │ ├── PieceStructuresGen.h │ │ ├── Prefab.cpp │ │ ├── Prefab.h │ │ ├── PrefabPiecePool.cpp │ │ ├── PrefabPiecePool.h │ │ ├── PrefabStructure.cpp │ │ ├── PrefabStructure.h │ │ ├── ProtIntGen.h │ │ ├── Ravines.cpp │ │ ├── Ravines.h │ │ ├── RoughRavines.cpp │ │ ├── RoughRavines.h │ │ ├── ShapeGen.cpp │ │ ├── SinglePieceStructuresGen.cpp │ │ ├── SinglePieceStructuresGen.h │ │ ├── StructGen.cpp │ │ ├── StructGen.h │ │ ├── Trees.cpp │ │ ├── Trees.h │ │ ├── TwoHeights.cpp │ │ ├── TwoHeights.h │ │ ├── VerticalLimit.cpp │ │ ├── VerticalLimit.h │ │ ├── VerticalStrategy.cpp │ │ ├── VerticalStrategy.h │ │ ├── VillageGen.cpp │ │ └── VillageGen.h │ ├── Globals.cpp │ ├── Globals.h │ ├── HTTP/ │ │ ├── CMakeLists.txt │ │ ├── EnvelopeParser.cpp │ │ ├── EnvelopeParser.h │ │ ├── HTTPFormParser.cpp │ │ ├── HTTPFormParser.h │ │ ├── HTTPMessage.cpp │ │ ├── HTTPMessage.h │ │ ├── HTTPMessageParser.cpp │ │ ├── HTTPMessageParser.h │ │ ├── HTTPServer.cpp │ │ ├── HTTPServer.h │ │ ├── HTTPServerConnection.cpp │ │ ├── HTTPServerConnection.h │ │ ├── MultipartParser.cpp │ │ ├── MultipartParser.h │ │ ├── NameValueParser.cpp │ │ ├── NameValueParser.h │ │ ├── SslHTTPServerConnection.cpp │ │ ├── SslHTTPServerConnection.h │ │ ├── TransferEncodingParser.cpp │ │ ├── TransferEncodingParser.h │ │ ├── UrlClient.cpp │ │ ├── UrlClient.h │ │ ├── UrlParser.cpp │ │ └── UrlParser.h │ ├── IniFile.cpp │ ├── IniFile.h │ ├── Inventory.cpp │ ├── Inventory.h │ ├── Item.cpp │ ├── Item.h │ ├── ItemGrid.cpp │ ├── ItemGrid.h │ ├── Items/ │ │ ├── CMakeLists.txt │ │ ├── ItemAnvil.h │ │ ├── ItemArmor.h │ │ ├── ItemAxe.h │ │ ├── ItemBanner.h │ │ ├── ItemBed.h │ │ ├── ItemBigFlower.h │ │ ├── ItemBoat.h │ │ ├── ItemBottle.h │ │ ├── ItemBow.h │ │ ├── ItemBucket.h │ │ ├── ItemButton.h │ │ ├── ItemChest.h │ │ ├── ItemChorusFruit.h │ │ ├── ItemCloth.h │ │ ├── ItemComparator.h │ │ ├── ItemCookedFish.h │ │ ├── ItemDefaultItem.h │ │ ├── ItemDoor.h │ │ ├── ItemDropSpenser.h │ │ ├── ItemDye.h │ │ ├── ItemEmptyMap.h │ │ ├── ItemEnchantingTable.h │ │ ├── ItemEndCrystal.h │ │ ├── ItemEndPortalFrame.h │ │ ├── ItemEnderChest.h │ │ ├── ItemEyeOfEnder.h │ │ ├── ItemFenceGate.h │ │ ├── ItemFishingRod.h │ │ ├── ItemFood.h │ │ ├── ItemFoodSeeds.h │ │ ├── ItemFurnace.h │ │ ├── ItemGlazedTerracotta.h │ │ ├── ItemGoldenApple.h │ │ ├── ItemHandler.cpp │ │ ├── ItemHandler.h │ │ ├── ItemHoe.h │ │ ├── ItemHopper.h │ │ ├── ItemItemFrame.h │ │ ├── ItemJackOLantern.h │ │ ├── ItemLadder.h │ │ ├── ItemLeaves.h │ │ ├── ItemLever.h │ │ ├── ItemLighter.h │ │ ├── ItemLilypad.h │ │ ├── ItemMap.h │ │ ├── ItemMilk.h │ │ ├── ItemMinecart.h │ │ ├── ItemMobHead.h │ │ ├── ItemNetherWart.h │ │ ├── ItemObserver.h │ │ ├── ItemPainting.h │ │ ├── ItemPickaxe.h │ │ ├── ItemPiston.h │ │ ├── ItemPlanks.h │ │ ├── ItemPoisonousPotato.h │ │ ├── ItemPotion.h │ │ ├── ItemPumpkin.h │ │ ├── ItemQuartz.h │ │ ├── ItemRail.h │ │ ├── ItemRawChicken.h │ │ ├── ItemRawFish.h │ │ ├── ItemRedstoneDust.h │ │ ├── ItemRedstoneRepeater.h │ │ ├── ItemRottenFlesh.h │ │ ├── ItemSapling.h │ │ ├── ItemSeeds.h │ │ ├── ItemShears.h │ │ ├── ItemShovel.h │ │ ├── ItemSideways.h │ │ ├── ItemSign.h │ │ ├── ItemSlab.h │ │ ├── ItemSnow.h │ │ ├── ItemSoup.h │ │ ├── ItemSpawnEgg.h │ │ ├── ItemSpiderEye.h │ │ ├── ItemStairs.h │ │ ├── ItemSword.h │ │ ├── ItemThrowable.h │ │ ├── ItemTorch.h │ │ ├── ItemTrapdoor.h │ │ ├── ItemTripwireHook.h │ │ ├── ItemVines.h │ │ └── SimplePlaceableItemHandler.h │ ├── JsonUtils.cpp │ ├── JsonUtils.h │ ├── LazyArray.h │ ├── LightingThread.cpp │ ├── LightingThread.h │ ├── LineBlockTracer.cpp │ ├── LineBlockTracer.h │ ├── LinearInterpolation.cpp │ ├── LinearInterpolation.h │ ├── LinearUpscale.h │ ├── Logger.cpp │ ├── Logger.h │ ├── LoggerListeners.cpp │ ├── LoggerListeners.h │ ├── LoggerSimple.h │ ├── Map.cpp │ ├── Map.h │ ├── MapManager.cpp │ ├── MapManager.h │ ├── Matrix4.h │ ├── MemorySettingsRepository.cpp │ ├── MemorySettingsRepository.h │ ├── MobCensus.cpp │ ├── MobCensus.h │ ├── MobFamilyCollecter.cpp │ ├── MobFamilyCollecter.h │ ├── MobProximityCounter.cpp │ ├── MobProximityCounter.h │ ├── MobSpawner.cpp │ ├── MobSpawner.h │ ├── Mobs/ │ │ ├── AggressiveMonster.cpp │ │ ├── AggressiveMonster.h │ │ ├── Bat.cpp │ │ ├── Bat.h │ │ ├── Blaze.cpp │ │ ├── Blaze.h │ │ ├── CMakeLists.txt │ │ ├── CaveSpider.cpp │ │ ├── CaveSpider.h │ │ ├── Chicken.cpp │ │ ├── Chicken.h │ │ ├── Cow.cpp │ │ ├── Cow.h │ │ ├── Creeper.cpp │ │ ├── Creeper.h │ │ ├── EnderDragon.cpp │ │ ├── EnderDragon.h │ │ ├── Enderman.cpp │ │ ├── Enderman.h │ │ ├── Endermite.cpp │ │ ├── Endermite.h │ │ ├── Ghast.cpp │ │ ├── Ghast.h │ │ ├── Giant.cpp │ │ ├── Giant.h │ │ ├── Guardian.cpp │ │ ├── Guardian.h │ │ ├── Horse.cpp │ │ ├── Horse.h │ │ ├── IncludeAllMonsters.h │ │ ├── IronGolem.cpp │ │ ├── IronGolem.h │ │ ├── MagmaCube.cpp │ │ ├── MagmaCube.h │ │ ├── Monster.cpp │ │ ├── Monster.h │ │ ├── MonsterTypes.h │ │ ├── Mooshroom.cpp │ │ ├── Mooshroom.h │ │ ├── Ocelot.cpp │ │ ├── Ocelot.h │ │ ├── PassiveAggressiveMonster.cpp │ │ ├── PassiveAggressiveMonster.h │ │ ├── PassiveMonster.cpp │ │ ├── PassiveMonster.h │ │ ├── Path.cpp │ │ ├── Path.h │ │ ├── PathFinder.cpp │ │ ├── PathFinder.h │ │ ├── Pig.cpp │ │ ├── Pig.h │ │ ├── Rabbit.cpp │ │ ├── Rabbit.h │ │ ├── Sheep.cpp │ │ ├── Sheep.h │ │ ├── Silverfish.cpp │ │ ├── Silverfish.h │ │ ├── Skeleton.cpp │ │ ├── Skeleton.h │ │ ├── Slime.cpp │ │ ├── Slime.h │ │ ├── SnowGolem.cpp │ │ ├── SnowGolem.h │ │ ├── Spider.cpp │ │ ├── Spider.h │ │ ├── Squid.cpp │ │ ├── Squid.h │ │ ├── Villager.cpp │ │ ├── Villager.h │ │ ├── Witch.cpp │ │ ├── Witch.h │ │ ├── Wither.cpp │ │ ├── Wither.h │ │ ├── WitherSkeleton.cpp │ │ ├── WitherSkeleton.h │ │ ├── Wolf.cpp │ │ ├── Wolf.h │ │ ├── Zombie.cpp │ │ ├── Zombie.h │ │ ├── ZombiePigman.cpp │ │ ├── ZombiePigman.h │ │ ├── ZombieVillager.cpp │ │ └── ZombieVillager.h │ ├── MonsterConfig.cpp │ ├── MonsterConfig.h │ ├── NetherPortalScanner.cpp │ ├── NetherPortalScanner.h │ ├── Noise/ │ │ ├── CMakeLists.txt │ │ ├── InterpolNoise.h │ │ ├── Noise.cpp │ │ ├── Noise.h │ │ ├── OctavedNoise.h │ │ └── RidgedNoise.h │ ├── OSSupport/ │ │ ├── AtomicUniquePtr.h │ │ ├── CMakeLists.txt │ │ ├── ConsoleSignalHandler.h │ │ ├── CriticalSection.cpp │ │ ├── CriticalSection.h │ │ ├── Event.cpp │ │ ├── Event.h │ │ ├── File.cpp │ │ ├── File.h │ │ ├── GZipFile.cpp │ │ ├── GZipFile.h │ │ ├── GetAddressInfoError.h │ │ ├── HostnameLookup.cpp │ │ ├── HostnameLookup.h │ │ ├── IPLookup.cpp │ │ ├── IPLookup.h │ │ ├── IsThread.cpp │ │ ├── IsThread.h │ │ ├── MiniDumpWriter.h │ │ ├── Network.h │ │ ├── NetworkInterfaceEnum.cpp │ │ ├── NetworkLookup.cpp │ │ ├── NetworkLookup.h │ │ ├── NetworkSingleton.cpp │ │ ├── NetworkSingleton.h │ │ ├── Queue.h │ │ ├── ServerHandleImpl.cpp │ │ ├── ServerHandleImpl.h │ │ ├── SleepResolutionBooster.h │ │ ├── StackTrace.cpp │ │ ├── StackTrace.h │ │ ├── StartAsService.h │ │ ├── Stopwatch.h │ │ ├── TCPLinkImpl.cpp │ │ ├── TCPLinkImpl.h │ │ ├── UDPEndpointImpl.cpp │ │ ├── UDPEndpointImpl.h │ │ ├── WinStackWalker.cpp │ │ └── WinStackWalker.h │ ├── OpaqueWorld.h │ ├── OverridesSettingsRepository.cpp │ ├── OverridesSettingsRepository.h │ ├── PalettedBlockArea.cpp │ ├── PalettedBlockArea.h │ ├── Physics/ │ │ ├── CMakeLists.txt │ │ ├── Explodinator.cpp │ │ └── Explodinator.h │ ├── ProbabDistrib.cpp │ ├── ProbabDistrib.h │ ├── Protocol/ │ │ ├── Authenticator.cpp │ │ ├── Authenticator.h │ │ ├── CMakeLists.txt │ │ ├── ChunkDataSerializer.cpp │ │ ├── ChunkDataSerializer.h │ │ ├── ForgeHandshake.cpp │ │ ├── ForgeHandshake.h │ │ ├── MojangAPI.cpp │ │ ├── MojangAPI.h │ │ ├── Packetizer.cpp │ │ ├── Packetizer.h │ │ ├── Palettes/ │ │ │ ├── CMakeLists.txt │ │ │ ├── Palette_1_13.cpp │ │ │ ├── Palette_1_13.h │ │ │ ├── Palette_1_13_1.cpp │ │ │ ├── Palette_1_13_1.h │ │ │ ├── Palette_1_14.cpp │ │ │ ├── Palette_1_14.h │ │ │ ├── Palette_1_15.cpp │ │ │ ├── Palette_1_15.h │ │ │ ├── Palette_1_16.cpp │ │ │ ├── Palette_1_16.h │ │ │ ├── Upgrade.cpp │ │ │ └── Upgrade.h │ │ ├── Protocol.h │ │ ├── ProtocolRecognizer.cpp │ │ ├── ProtocolRecognizer.h │ │ ├── Protocol_1_10.cpp │ │ ├── Protocol_1_10.h │ │ ├── Protocol_1_11.cpp │ │ ├── Protocol_1_11.h │ │ ├── Protocol_1_12.cpp │ │ ├── Protocol_1_12.h │ │ ├── Protocol_1_13.cpp │ │ ├── Protocol_1_13.h │ │ ├── Protocol_1_14.cpp │ │ ├── Protocol_1_14.h │ │ ├── Protocol_1_8.cpp │ │ ├── Protocol_1_8.h │ │ ├── Protocol_1_9.cpp │ │ ├── Protocol_1_9.h │ │ ├── RecipeMapper.cpp │ │ └── RecipeMapper.h │ ├── RCONServer.cpp │ ├── RCONServer.h │ ├── RankManager.cpp │ ├── RankManager.h │ ├── Registries/ │ │ ├── BlockStates.cpp │ │ ├── BlockStates.h │ │ ├── BlockTypes.h │ │ ├── CMakeLists.txt │ │ ├── CustomStatistics.h │ │ └── Items.h │ ├── Resources/ │ │ └── Cuberite.rc │ ├── Root.cpp │ ├── Root.h │ ├── Scoreboard.cpp │ ├── Scoreboard.h │ ├── Server.cpp │ ├── Server.h │ ├── SetChunkData.cpp │ ├── SetChunkData.h │ ├── SettingsRepositoryInterface.h │ ├── Simulator/ │ │ ├── CMakeLists.txt │ │ ├── DelayedFluidSimulator.cpp │ │ ├── DelayedFluidSimulator.h │ │ ├── FireSimulator.cpp │ │ ├── FireSimulator.h │ │ ├── FloodyFluidSimulator.cpp │ │ ├── FloodyFluidSimulator.h │ │ ├── FluidSimulator.cpp │ │ ├── FluidSimulator.h │ │ ├── IncrementalRedstoneSimulator/ │ │ │ ├── CMakeLists.txt │ │ │ ├── CommandBlockHandler.h │ │ │ ├── DaylightSensorHandler.h │ │ │ ├── DoorHandler.h │ │ │ ├── DropSpenserHandler.h │ │ │ ├── ForEachSourceCallback.cpp │ │ │ ├── ForEachSourceCallback.h │ │ │ ├── HopperHandler.h │ │ │ ├── IncrementalRedstoneSimulator.cpp │ │ │ ├── IncrementalRedstoneSimulator.h │ │ │ ├── NoteBlockHandler.h │ │ │ ├── ObserverHandler.h │ │ │ ├── PistonHandler.h │ │ │ ├── PoweredRailHandler.h │ │ │ ├── PressurePlateHandler.h │ │ │ ├── RedstoneBlockHandler.h │ │ │ ├── RedstoneComparatorHandler.h │ │ │ ├── RedstoneDataHelper.h │ │ │ ├── RedstoneHandler.cpp │ │ │ ├── RedstoneHandler.h │ │ │ ├── RedstoneLampHandler.h │ │ │ ├── RedstoneRepeaterHandler.h │ │ │ ├── RedstoneSimulatorChunkData.h │ │ │ ├── RedstoneToggleHandler.h │ │ │ ├── RedstoneTorchHandler.h │ │ │ ├── RedstoneWireHandler.h │ │ │ ├── SmallGateHandler.h │ │ │ ├── TNTHandler.h │ │ │ ├── TrappedChestHandler.h │ │ │ └── TripwireHookHandler.h │ │ ├── NoopFluidSimulator.h │ │ ├── NoopRedstoneSimulator.h │ │ ├── RedstoneSimulator.h │ │ ├── SandSimulator.cpp │ │ ├── SandSimulator.h │ │ ├── Simulator.cpp │ │ ├── Simulator.h │ │ ├── SimulatorManager.cpp │ │ ├── SimulatorManager.h │ │ ├── VanillaFluidSimulator.cpp │ │ ├── VanillaFluidSimulator.h │ │ ├── VaporizeFluidSimulator.cpp │ │ └── VaporizeFluidSimulator.h │ ├── SpawnPrepare.cpp │ ├── SpawnPrepare.h │ ├── StatisticsManager.cpp │ ├── StatisticsManager.h │ ├── StringCompression.cpp │ ├── StringCompression.h │ ├── StringUtils.cpp │ ├── StringUtils.h │ ├── UI/ │ │ ├── AnvilWindow.cpp │ │ ├── AnvilWindow.h │ │ ├── BeaconWindow.cpp │ │ ├── BeaconWindow.h │ │ ├── BrewingstandWindow.cpp │ │ ├── BrewingstandWindow.h │ │ ├── CMakeLists.txt │ │ ├── ChestWindow.cpp │ │ ├── ChestWindow.h │ │ ├── CraftingWindow.cpp │ │ ├── CraftingWindow.h │ │ ├── DropSpenserWindow.cpp │ │ ├── DropSpenserWindow.h │ │ ├── EnchantingWindow.cpp │ │ ├── EnchantingWindow.h │ │ ├── EnderChestWindow.cpp │ │ ├── EnderChestWindow.h │ │ ├── FurnaceWindow.cpp │ │ ├── FurnaceWindow.h │ │ ├── HopperWindow.cpp │ │ ├── HopperWindow.h │ │ ├── HorseWindow.cpp │ │ ├── HorseWindow.h │ │ ├── InventoryWindow.cpp │ │ ├── InventoryWindow.h │ │ ├── MinecartWithChestWindow.h │ │ ├── SlotArea.cpp │ │ ├── SlotArea.h │ │ ├── Window.cpp │ │ ├── Window.h │ │ └── WindowOwner.h │ ├── UUID.cpp │ ├── UUID.h │ ├── Vector3.h │ ├── VoronoiMap.cpp │ ├── VoronoiMap.h │ ├── WebAdmin.cpp │ ├── WebAdmin.h │ ├── World.cpp │ ├── World.h │ ├── WorldStorage/ │ │ ├── CMakeLists.txt │ │ ├── EnchantmentSerializer.cpp │ │ ├── EnchantmentSerializer.h │ │ ├── FastNBT.cpp │ │ ├── FastNBT.h │ │ ├── FireworksSerializer.cpp │ │ ├── FireworksSerializer.h │ │ ├── MapSerializer.cpp │ │ ├── MapSerializer.h │ │ ├── NBTChunkSerializer.cpp │ │ ├── NBTChunkSerializer.h │ │ ├── NamespaceSerializer.cpp │ │ ├── NamespaceSerializer.h │ │ ├── SchematicFileSerializer.cpp │ │ ├── SchematicFileSerializer.h │ │ ├── ScoreboardSerializer.cpp │ │ ├── ScoreboardSerializer.h │ │ ├── StatisticsSerializer.cpp │ │ ├── StatisticsSerializer.h │ │ ├── WSSAnvil.cpp │ │ ├── WSSAnvil.h │ │ ├── WorldStorage.cpp │ │ └── WorldStorage.h │ ├── XMLParser.h │ ├── fmt.h │ ├── main.cpp │ ├── main.h │ └── mbedTLS++/ │ ├── AesCfb128Decryptor.cpp │ ├── AesCfb128Decryptor.h │ ├── AesCfb128Encryptor.cpp │ ├── AesCfb128Encryptor.h │ ├── BlockingSslClientSocket.cpp │ ├── BlockingSslClientSocket.h │ ├── BufferedSslContext.cpp │ ├── BufferedSslContext.h │ ├── CMakeLists.txt │ ├── CallbackSslContext.cpp │ ├── CallbackSslContext.h │ ├── CryptoKey.cpp │ ├── CryptoKey.h │ ├── CtrDrbgContext.cpp │ ├── CtrDrbgContext.h │ ├── EntropyContext.cpp │ ├── EntropyContext.h │ ├── ErrorCodes.h │ ├── RsaPrivateKey.cpp │ ├── RsaPrivateKey.h │ ├── Sha1Checksum.cpp │ ├── Sha1Checksum.h │ ├── SslConfig.cpp │ ├── SslConfig.h │ ├── SslContext.cpp │ ├── SslContext.h │ ├── X509Cert.cpp │ └── X509Cert.h ├── stats.cmd └── tests/ ├── BlockTypeRegistry/ │ ├── BlockStateTest.cpp │ ├── BlockTypePaletteTest.cpp │ ├── BlockTypeRegistryTest.cpp │ ├── CMakeLists.txt │ └── PalettedBlockAreaTest.cpp ├── BoundingBox/ │ ├── BoundingBoxTest.cpp │ └── CMakeLists.txt ├── ByteBuffer/ │ ├── ByteBufferTest.cpp │ ├── CMakeLists.txt │ └── Stubs.cpp ├── CMakeLists.txt ├── ChunkData/ │ ├── ArraytoCoord.cpp │ ├── CMakeLists.txt │ ├── Coordinates.cpp │ ├── Copies.cpp │ └── Creatable.cpp ├── CompositeChat/ │ ├── CMakeLists.txt │ ├── ClientHandle.cpp │ └── CompositeChatTest.cpp ├── ConsoleColors/ │ └── ConsoleColors.cpp ├── FastRandom/ │ ├── CMakeLists.txt │ └── FastRandomTest.cpp ├── Generating/ │ ├── BasicGeneratorTest.cpp │ ├── Bindings.h │ ├── CMakeLists.txt │ ├── LoadablePieces.cpp │ ├── LuaState_Declaration.inc │ ├── LuaState_Typedefs.inc │ ├── PieceGeneratorBFSTreeTest.cpp │ ├── PieceRotationTest.cpp │ ├── Stubs.cpp │ ├── Test.cubeset │ └── Test1.schematic ├── HTTP/ │ ├── CMakeLists.txt │ ├── HTTPMessageParser_file.cpp │ ├── HTTPRequest1.data │ ├── HTTPRequest2.data │ ├── HTTPRequestParser_file.cpp │ ├── HTTPResponse1.data │ ├── HTTPResponse2.data │ ├── HTTPResponseParser_file.cpp │ └── UrlClientTest.cpp ├── LoadablePieces/ │ └── CMakeLists.txt ├── LuaThreadStress/ │ ├── Bindings.h │ ├── CMakeLists.txt │ ├── LuaState_Declaration.inc │ ├── LuaState_Typedefs.inc │ ├── LuaThreadStress.cpp │ ├── Stubs.cpp │ └── Test.lua ├── Network/ │ ├── CMakeLists.txt │ ├── EchoServer.cpp │ ├── EnumInterfaces.cpp │ ├── Google.cpp │ └── NameLookup.cpp ├── NoiseTest/ │ ├── GNUmakefile │ └── NoiseTest.cpp ├── OSSupport/ │ ├── CMakeLists.txt │ └── StressEvent.cpp ├── SchematicFileSerializer/ │ ├── CMakeLists.txt │ ├── SchematicFileSerializerTest.cpp │ └── Stubs.cpp ├── TestHelpers.h └── UUID/ ├── CMakeLists.txt └── UUIDTest.cpp ================================================ FILE CONTENTS ================================================ ================================================ FILE: .clang-format ================================================ # Not the exact style guide but enough for basic clang-tidy fix-its Language: Cpp BasedOnStyle: LLVM AlignAfterOpenBracket: AlwaysBreak BreakConstructorInitializers: AfterColon ConstructorInitializerAllOnOneLineOrOnePerLine: true PointerAlignment: Middle SortIncludes: false SpacesBeforeTrailingComments: 2 UseTab: Always MaxEmptyLinesToKeep: 5 TabWidth: 4 ConstructorInitializerIndentWidth: 4 ContinuationIndentWidth: 4 IndentWidth: 4 IndentCaseLabels: true BreakBeforeBraces: Custom BraceWrapping: AfterClass: true AfterControlStatement: true AfterEnum: true AfterExternBlock: true AfterFunction: true AfterNamespace: true AfterStruct: true AfterUnion: true BeforeCatch: true BeforeElse: true IndentBraces: false SplitEmptyFunction: true SplitEmptyRecord: true # Always include globals first IncludeCategories: - Regex: 'Globals.h' Priority: -1 ================================================ FILE: .clang-tidy ================================================ Checks: >- -*, readability-identifier-naming, readability-redundant-string-cstr, readability-redundant-string-init, readability-simplify-boolean-expr, performance-unnecessary-value-param, performance-unnecessary-copy-initialization, performance-for-range-copy, performance-implicit-conversion-in-loop, CheckOptions: - key: readability-identifier-naming.PrivateMemberPrefix value: 'm_' - key: readability-identifier-naming.ClassConstantCase value: aNy_CasE # an empty *Prefix needs a *Case to work - key: readability-identifier-naming.ClassConstantPrefix value: '' #- key: readability-identifier-naming.PrivateMemberCase # value: CamelCase #- key: readability-identifier-naming.FunctionCase # value: CamelCase #- key: readability-identifier-naming.EnumCase # value: camelBack - key: performance-unnecessary-value-param.AllowedTypes value: 'cEntityEffect;cNoise' WarningsAsErrors: '*' HeaderFilterRegex: '/cuberite/src/\.?[^\.]' FormatStyle: 'file' ================================================ FILE: .editorconfig ================================================ root = true [*] charset = utf-8 indent_style = tab insert_final_newline = true trim_trailing_whitespace = true ================================================ FILE: .gitattributes ================================================ # Set the *.data files to be checked out as binary files. # Used for the HTTP test data files, they need to have the CRLF line endings # even on Linux, because they're HTTP protocol dumps. *.data binary ================================================ FILE: .github/FUNDING.yml ================================================ liberapay: Cuberite ================================================ FILE: .github/ISSUE_TEMPLATE/config.yml ================================================ blank_issues_enabled: false ================================================ FILE: .github/ISSUE_TEMPLATE/issue-template.md ================================================ --- name: Issue Template about: Report a bug, feature request or another sort of issue title: '' labels: '' assignees: '' --- Client version: x.x.x Server OS: Windows/Linux/macOS/BSD/... Cuberite Commit id: (Found at the top of the server's console output) ### Expected behavior ### Actual behavior ### Steps to reproduce the behavior ### Server log ``` Relevant part of server log ``` ================================================ FILE: .github/workflows/Build.yml ================================================ # This starter workflow is for a CMake project running on multiple platforms. There is a different starter workflow if you just want a single platform. # See: https://github.com/actions/starter-workflows/blob/main/ci/cmake-single-platform.yml name: Build on: push: tags-ignore: - release-* branches: - '**' pull_request: branches: - '**' jobs: build: timeout-minutes: 60 permissions: {} runs-on: ${{ matrix.os }} strategy: # Set fail-fast to false to ensure that feedback is delivered for all matrix combinations. Consider changing this to true when your workflow is stable. fail-fast: false # Set up a matrix to run the following 3 configurations: # 1. # 2. # 3. # # To add more build types (Release, Debug, RelWithDebInfo, etc.) customize the build_type list. # The excluded ones are needed so some configs don't run. # The included ones are needed because the cpp_compiler field is not set otherwise, leading CMake to fail. matrix: os: [ubuntu-latest, windows-latest] build_type: [Release] c_compiler: [gcc, clang, cl] include: - os: windows-latest c_compiler: cl cpp_compiler: cl - os: ubuntu-latest c_compiler: gcc cpp_compiler: g++ - os: ubuntu-latest c_compiler: clang cpp_compiler: clang++ exclude: - os: windows-latest c_compiler: gcc - os: windows-latest c_compiler: clang - os: ubuntu-latest c_compiler: cl steps: - uses: actions/checkout@v4 with: submodules: 'recursive' - name: Set reusable strings # Turn repeated input strings (such as the build output directory) into step outputs. These step outputs can be used throughout the workflow file. id: strings shell: bash run: | echo "build-output-dir=${{ github.workspace }}/build" >> "$GITHUB_OUTPUT" - name: Configure CMake # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make. # See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type run: > cmake -B ${{ steps.strings.outputs.build-output-dir }} -DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }} -DCMAKE_C_COMPILER=${{ matrix.c_compiler }} -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DBUILD_TOOLS=Yes -DSELF_TEST=Yes -S ${{ github.workspace }} - name: Build # Build your program with the given configuration. Note that --config is needed because the default Windows generator is a multi-config generator (Visual Studio generator). run: cmake --build ${{ steps.strings.outputs.build-output-dir }} --config ${{ matrix.build_type }} - if: runner.os == 'Windows' name: Create Zip Windows run: powershell Compress-Archive build/Server Cuberite-${{ matrix.os }}-${{ matrix.c_compiler }}-${{ matrix.build_type }}.zip - if: runner.os != 'Windows' name: Create Zip Linux run: zip -r Cuberite-${{ matrix.os }}-${{ matrix.c_compiler }}-${{ matrix.build_type }}.zip build/Server - name: Test working-directory: ${{ steps.strings.outputs.build-output-dir }} # Execute tests defined by the CMake configuration. Note that --build-config is needed because the default Windows generator is a multi-config generator (Visual Studio generator). # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail run: ctest --build-config ${{ matrix.build_type }} --output-on-failure - if: runner.os != 'Windows' name: Docs run: | cd build/Server touch apiCheckFailed.flag ./Cuberite <<- EOF load APIDump api apicheck restart stop EOF if [ -f ./NewlyUndocumented.lua ]; then echo "ERROR: Newly undocumented API symbols found:" cat ./NewlyUndocumented.lua exit 1 fi if [ -f ./DuplicateDocs.txt ]; then echo "ERROR: API documentation has duplicate symbol warnings:" cat ./DuplicateDocs.txt exit 1 fi if [ -f ./apiCheckFailed.flag ]; then echo "ERROR: API check has failed with an unknown error" exit 1 fi - name: Extract branch name shell: bash run: echo "branch=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}" >> $GITHUB_OUTPUT id: extract_branch - if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/experimental' name: Upload artifact uses: actions/upload-artifact@v4 with: if-no-files-found: 'error' name: Cuberite-${{ matrix.os }}-${{ matrix.c_compiler }}-${{ matrix.build_type }} path: Cuberite-${{ matrix.os }}-${{ matrix.c_compiler }}-${{ matrix.build_type }}.zip upload_release: # Disable the job until a proper release process is made if: (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/experimental') && false permissions: contents: write needs: build timeout-minutes: 60 runs-on: ubuntu-latest steps: - name: Extract branch name shell: bash run: echo "branch=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}" >> $GITHUB_OUTPUT id: extract_branch - name: Download Artifacts uses: actions/download-artifact@v4 with: merge-multiple: true - name: Create GitHub Release uses: softprops/action-gh-release@v2 with: tag_name: release-${{ steps.extract_branch.outputs.branch }} name: Release ${{ steps.extract_branch.outputs.branch }} body: Automatically uploaded release by GitHub actions fail_on_unmatched_files: true files: | ${{ github.workspace }}/Cuberite-ubuntu-latest-clang-Release.zip ${{ github.workspace }}/Cuberite-ubuntu-latest-gcc-Release.zip ${{ github.workspace }}/Cuberite-windows-latest-cl-Release.zip prerelease: true # Taken from here https://stackoverflow.com/questions/68895194/github-actions-create-or-update-a-git-tag - if: ${{ success() }} name: Fix tag uses: actions/github-script@v7 with: script: | github.rest.git.createRef({ owner: context.repo.owner, repo: context.repo.repo, ref: 'refs/tags/release-${{ steps.extract_branch.outputs.branch }}', sha: context.sha }).catch(err => { if (err.status !== 422) throw err; github.rest.git.updateRef({ owner: context.repo.owner, repo: context.repo.repo, ref: 'tags/release-${{ steps.extract_branch.outputs.branch }}', sha: context.sha }); }) ================================================ FILE: .github/workflows/StyleCheck.yml ================================================ name: Style Check permissions: {} on: push: tags-ignore: - release-* branches: - '**' pull_request: branches: - '**' jobs: build: timeout-minutes: 60 runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: leafo/gh-actions-lua@v11 - name: Find Files run: cd src && find . -name "*.cpp" -or -name "*.h" > AllFiles.lst - name: Check Basic Style run: cd src && lua CheckBasicStyle.lua - name: Check Bindings and Deps run: cd src/Bindings && lua CheckBindingsDependencies.lua ================================================ FILE: .gitignore ================================================ build/ build*/ nbproject/ ipch/ Win32/ MCServer Server/Cuberite Server/buildinfo Server/CONTRIBUTORS Server/LICENSE Server/Licenses Server/itemblacklist Tools/MCADefrag/MCADefrag Tools/ProtoProxy/ProtoProxy Testing/ ChunkWorxSave.ini doxy/ .vscode/ Profiling Symbols cloc-ignored.txt cloc.xml cloc.xsl *.ncb *.user *.suo *.sqlite /EveryNight.cmd /UploadLuaAPI.cmd GPUCache AllFiles.lst GPUCache # IDE Stuff ## Sublime Text *.sublime-* ## emacs *.*~ *~ *.orig ## CLion .idea ## Eclipse .cproject .project *.cbp ## KDevelop *.kdev* ## Vim .cache/ # world inside source ChunkWorx.ini groups.ini items.ini monsters.ini settings.ini terrain.ini users.ini webadmin.ini world.ini crafting.txt motd.txt logs players world world_nether # cmake stuff CMakeFiles/ cmake_install.cmake CMakeCache.txt CTestTestfile.cmake Makefile *.a *.d *.so tests/*/*-exe CMakeCache.txt CMakeFiles Makefile cmake_install.cmake install_mainfest.txt src/Cuberite lib/tolua++/tolua src/Bindings/Bindings.* src/Bindings/BindingDependencies.txt Cuberite.dir/ src/AllFiles.lst # win32 cmake stuff *.vcxproj *.vcproj *.vcxproj.filters *.opensdf *.sdf *.sln *.VC.opendb *.VC.db *.idb .vs/ # cmake output folders and files ZERO_CHECK.dir/ Debug/ DebugProfile/ Release/ ReleaseProfile/ *.dir/ CPackConfig.cmake CPackSourceConfig.cmake cmake-build-* # APIDump-generated status files: Server/cuberite_api.lua Server/official_undocumented.lua Server/NewlyUndocumented.lua Server/.luacheckrc compile_commands.json # compile.sh folder build-cuberite # clang-tidy tidy-build run-clang-tidy.py # ctags output tags # mac things .DS_Store ================================================ FILE: .gitmodules ================================================ [submodule "Server/Plugins/Core"] path = Server/Plugins/Core url = https://github.com/cuberite/Core.git [submodule "Server/Plugins/ProtectionAreas"] path = Server/Plugins/ProtectionAreas url = https://github.com/cuberite/ProtectionAreas.git [submodule "Server/Plugins/ChatLog"] path = Server/Plugins/ChatLog url = https://github.com/cuberite/ChatLog.git [submodule "lib/mbedtls"] path = lib/mbedtls url = https://github.com/cuberite/polarssl.git ignore = dirty [submodule "lib/SQLiteCpp"] path = lib/SQLiteCpp url = https://github.com/cuberite/SQLiteCpp.git ignore = dirty [submodule "lib/libevent"] path = lib/libevent url = https://github.com/cuberite/libevent.git ignore = dirty [submodule "lib/jsoncpp"] path = lib/jsoncpp url = https://github.com/open-source-parsers/jsoncpp.git ignore = dirty [submodule "lib/TCLAP"] path = lib/TCLAP url = https://github.com/cuberite/TCLAP.git ignore = dirty [submodule "lib/cmake-coverage"] path = lib/cmake-coverage url = https://github.com/cuberite/cmake-coverage.git ignore = dirty [submodule "lib/expat"] path = lib/expat url = https://github.com/cuberite/expat.git ignore = dirty [submodule "lib/lua"] path = lib/lua url = https://github.com/cuberite/lua.git ignore = dirty [submodule "lib/luaexpat"] path = lib/luaexpat url = https://github.com/cuberite/luaexpat.git ignore = dirty [submodule "lib/luaproxy"] path = lib/luaproxy url = https://github.com/cuberite/luaproxy.git ignore = dirty [submodule "lib/sqlite"] path = lib/sqlite url = https://github.com/cuberite/sqlite.git ignore = dirty [submodule "lib/tolua++"] path = lib/tolua++ url = https://github.com/cuberite/toluapp.git ignore = dirty [submodule "lib/fmt"] path = lib/fmt url = https://github.com/fmtlib/fmt.git ignore = dirty [submodule "Tools/BlockTypePaletteGenerator/lib/lunajson"] path = Tools/BlockTypePaletteGenerator/lib/lunajson url = https://github.com/grafi-tt/lunajson.git [submodule "lib/libdeflate"] path = lib/libdeflate url = https://github.com/cuberite/libdeflate ================================================ FILE: BACKERS ================================================ Thanks to the following people for supporting the Cuberite project with a donation: - Alvin - Anonymous - chrobione - DrMasik - Fllamber - JimSVMI83 - Lordake - ltdTM - Phillip Inman - PureTryOut - Robert Cringely - spekdrum - SphinxC0re - TooAngel - Utking - VaiN474 If you enjoy Cuberite, feel free to donate to the project on Liberapay: https://liberapay.com/Cuberite ================================================ FILE: CMake/AddDependencies.cmake ================================================ function(build_dependencies) # Set options for SQLiteCpp, disable all their lints and other features we don't need: set(SQLITE_ENABLE_COLUMN_METADATA OFF CACHE BOOL "Enable Column::getColumnOriginName(). Require support from sqlite3 library.") set(SQLITE_ENABLE_JSON1 OFF CACHE BOOL "Enable JSON1 extension when building internal sqlite3 library.") set(SQLITECPP_INCLUDE_SCRIPT OFF CACHE BOOL "Include config & script files.") set(SQLITECPP_RUN_CPPCHECK OFF CACHE BOOL "Run cppcheck C++ static analysis tool.") set(SQLITECPP_RUN_CPPLINT OFF CACHE BOOL "Run cpplint.py tool for Google C++ StyleGuide.") set(SQLITECPP_USE_STACK_PROTECTION OFF CACHE BOOL "USE Stack Protection hardening.") set(SQLITECPP_USE_STATIC_RUNTIME OFF CACHE BOOL "Use MSVC static runtime (default for internal googletest).") # Set options for LibEvent, disable all their tests and benchmarks: set(EVENT__DISABLE_OPENSSL YES CACHE BOOL "Disable OpenSSL in LibEvent") set(EVENT__DISABLE_BENCHMARK YES CACHE BOOL "Disable LibEvent benchmarks") set(EVENT__DISABLE_TESTS YES CACHE BOOL "Disable LibEvent tests") set(EVENT__DISABLE_REGRESS YES CACHE BOOL "Disable LibEvent regression tests") set(EVENT__DISABLE_SAMPLES YES CACHE BOOL "Disable LibEvent samples") set(EVENT__LIBRARY_TYPE "STATIC" CACHE STRING "Use static LibEvent libraries") # Set options for JsonCPP, disabling all of their tests: set(JSONCPP_WITH_TESTS OFF CACHE BOOL "Compile and (for jsoncpp_check) run JsonCpp test executables") set(JSONCPP_WITH_POST_BUILD_UNITTEST OFF CACHE BOOL "Automatically run unit-tests as a post build step") set(JSONCPP_WITH_PKGCONFIG_SUPPORT OFF CACHE BOOL "Generate and install .pc files") set(JSONCPP_WITH_CMAKE_PACKAGE OFF CACHE BOOL "Generate and install cmake package files") set(BUILD_SHARED_LIBS OFF CACHE BOOL "Build jsoncpp_lib as a shared library.") set(BUILD_OBJECT_LIBS OFF CACHE BOOL "Build jsoncpp_lib as a object library.") # Set options for mbedtls: set(ENABLE_PROGRAMS OFF CACHE BOOL "Build mbed TLS programs.") set(ENABLE_TESTING OFF CACHE BOOL "Build mbed TLS tests.") # Enumerate all submodule libraries # SQLiteCpp needs to be included before sqlite so the lsqlite target is available: set(DEPENDENCIES expat fmt jsoncpp libdeflate libevent lua luaexpat mbedtls SQLiteCpp sqlite tolua++) foreach(DEPENDENCY ${DEPENDENCIES}) # Check that the libraries are present: if (NOT EXISTS "${PROJECT_SOURCE_DIR}/lib/${DEPENDENCY}/CMakeLists.txt") message(FATAL_ERROR "${DEPENDENCY} is missing in folder lib/${DEPENDENCY}. Have you initialized and updated the submodules / downloaded the extra libraries?") endif() # Include all the libraries # We use EXCLUDE_FROM_ALL so that only the explicit dependencies are compiled # (mbedTLS also has test and example programs in their CMakeLists.txt, we don't want those): add_subdirectory("lib/${DEPENDENCY}" EXCLUDE_FROM_ALL) endforeach() if (WIN32) add_subdirectory(lib/luaproxy) endif() endfunction() function(link_dependencies TARGET) # Add required includes: target_include_directories( ${TARGET} SYSTEM PRIVATE lib/mbedtls/include lib/TCLAP/include lib # TODO fix files including zlib/x instead of x ) # Link dependencies as private: target_link_libraries( ${TARGET} PRIVATE event_core event_extra fmt::fmt jsoncpp_static libdeflate lsqlite lualib luaexpat mbedtls SQLiteCpp tolualib ) # Link process information, multimedia (for sleep resolution) libraries: if (WIN32) target_link_libraries(${TARGET} PRIVATE Psapi.lib Winmm.lib) endif() # Special case handling for libevent pthreads: if(NOT WIN32) target_link_libraries(${TARGET} PRIVATE event_pthreads) endif() # Prettify jsoncpp_static name in VS solution explorer: set_property(TARGET jsoncpp_static PROPERTY PROJECT_LABEL "jsoncpp") if(${CMAKE_SYSTEM_NAME} MATCHES FreeBSD) target_link_libraries(${TARGET} PRIVATE kvm) endif() endfunction() ================================================ FILE: CMake/Fixups.cmake ================================================ function(emit_fixups) if(NOT MSVC AND "${CMAKE_SYSTEM_PROCESSOR}" MATCHES "arm") # mbed TLS uses the frame pointer's register in inline assembly for its bignum implementation: # https://tls.mbed.org/kb/development/arm-thumb-error-r7-cannot-be-used-in-asm-here target_compile_options(mbedcrypto PRIVATE -fomit-frame-pointer) endif() if(UNIX) execute_process(COMMAND ldd OUTPUT_VARIABLE LDD_OUTPUT ERROR_VARIABLE LDD_OUTPUT) if (LDD_OUTPUT MATCHES musl) # Bring musl stack size in line with other platforms: target_link_options(${CMAKE_PROJECT_NAME} PRIVATE "-Wl,-z,stack-size=1048576") endif() endif() endfunction() ================================================ FILE: CMake/GenerateBindings.cmake ================================================ function(enable_bindings_generation) # Enumerate every Lua-exported class. # Changes to these files will cause binding regen: set(BINDING_DEPENDENCIES Bindings/AllToLua.pkg Bindings/BindingsProcessor.lua Bindings/LuaFunctions.h Bindings/LuaWindow.h Bindings/Plugin.h Bindings/PluginLua.h Bindings/PluginManager.h BiomeDef.h BlockArea.h BlockEntities/BeaconEntity.h BlockEntities/BedEntity.h BlockEntities/BlockEntity.h BlockEntities/BlockEntityWithItems.h BlockEntities/BrewingstandEntity.h BlockEntities/ChestEntity.h BlockEntities/CommandBlockEntity.h BlockEntities/DispenserEntity.h BlockEntities/DropSpenserEntity.h BlockEntities/DropperEntity.h BlockEntities/FurnaceEntity.h BlockEntities/HopperEntity.h BlockEntities/JukeboxEntity.h BlockEntities/MobSpawnerEntity.h BlockEntities/NoteEntity.h BlockEntities/SignEntity.h BlockEntities/MobHeadEntity.h BlockEntities/FlowerPotEntity.h BlockType.h BlockInfo.h BoundingBox.h ChatColor.h ChunkDef.h ClientHandle.h Color.h CompositeChat.h CraftingRecipes.h Cuboid.h Defines.h EffectID.h Enchantments.h Entities/Boat.h Entities/ArrowEntity.h Entities/Entity.h Entities/ExpOrb.h Entities/EnderCrystal.h Entities/EntityEffect.h Entities/ExpBottleEntity.h Entities/FallingBlock.h Entities/FireChargeEntity.h Entities/FireworkEntity.h Entities/Floater.h Entities/GhastFireballEntity.h Entities/HangingEntity.h Entities/ItemFrame.h Entities/LeashKnot.h Entities/Pawn.h Entities/Player.h Entities/Painting.h Entities/Pickup.h Entities/ProjectileEntity.h Entities/SplashPotionEntity.h Entities/ThrownEggEntity.h Entities/ThrownEnderPearlEntity.h Entities/ThrownSnowballEntity.h Entities/TNTEntity.h Entities/WitherSkullEntity.h Generating/ChunkDesc.h IniFile.h Inventory.h Item.h ItemGrid.h Map.h MapManager.h Mobs/Monster.h Mobs/MonsterTypes.h OSSupport/File.h Protocol/MojangAPI.h Registries/CustomStatistics.h Root.h Scoreboard.h Server.h StatisticsManager.h StringUtils.h UI/Window.h UUID.h Vector3.h WebAdmin.h World.h ) # List all the files that are generated as part of the Bindings build process: set(BINDING_OUTPUTS Bindings.cpp Bindings.h LuaState_Declaration.inc LuaState_Implementation.cpp LuaState_Typedefs.inc ) # Make the file paths absolute and pointing to the bindings folder: set(BINDINGS_FOLDER "${PROJECT_SOURCE_DIR}/src/Bindings/") list(TRANSFORM BINDING_OUTPUTS PREPEND ${BINDINGS_FOLDER}) list(TRANSFORM BINDING_DEPENDENCIES PREPEND "${PROJECT_SOURCE_DIR}/src/") # Generate the bindings: add_custom_command( OUTPUT ${BINDING_OUTPUTS} COMMAND lua BindingsProcessor.lua WORKING_DIRECTORY ${BINDINGS_FOLDER} DEPENDS ${BINDING_DEPENDENCIES} ) endfunction() ================================================ FILE: CMake/GroupSources.cmake ================================================ function(group_sources) # Enable the support for solution folders in MSVC set_property(GLOBAL PROPERTY USE_FOLDERS ON) # Put projects into solution folders in MSVC: set_target_properties( event_core_static event_extra_static expat fmt jsoncpp_static libdeflate lualib luaexpat mbedcrypto mbedtls mbedx509 lsqlite sqlite3 SQLiteCpp tolualib PROPERTIES FOLDER Libraries ) # luaproxy not generated on anything else if(WIN32) set_target_properties( luaproxy PROPERTIES FOLDER Support ) endif() if(${BUILD_TOOLS}) set_target_properties( MCADefrag ProtoProxy PROPERTIES FOLDER Tools ) endif() # Put all files into one project, separate by the folders: get_property(TARGET_SOURCE_FILES TARGET ${CMAKE_PROJECT_NAME} PROPERTY SOURCES) source_group(TREE "${PROJECT_SOURCE_DIR}/src" FILES ${TARGET_SOURCE_FILES}) endfunction() ================================================ FILE: CMake/StampBuild.cmake ================================================ # These env variables are used for configuring Travis CI builds. if(DEFINED ENV{TRAVIS_CUBERITE_FORCE32}) set(FORCE32 $ENV{TRAVIS_CUBERITE_FORCE32}) endif() if(DEFINED ENV{TRAVIS_BUILD_WITH_COVERAGE}) set(BUILD_WITH_COVERAGE $ENV{TRAVIS_BUILD_WITH_COVERAGE}) endif() if(DEFINED ENV{CUBERITE_BUILD_ID}) # The build info is defined by the build system (Travis / Jenkins) set(BUILD_ID $ENV{CUBERITE_BUILD_ID}) set(BUILD_SERIES_NAME $ENV{CUBERITE_BUILD_SERIES_NAME}) set(BUILD_DATETIME $ENV{CUBERITE_BUILD_DATETIME}) if(DEFINED ENV{CUBERITE_BUILD_COMMIT_ID}) set(BUILD_COMMIT_ID $ENV{CUBERITE_BUILD_COMMIT_ID}) else() message("Commit id not set, attempting to determine id from git") execute_process( COMMAND git rev-parse HEAD WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} RESULT_VARIABLE GIT_EXECUTED OUTPUT_VARIABLE BUILD_COMMIT_ID ) string(STRIP ${BUILD_COMMIT_ID} BUILD_COMMIT_ID) if (NOT (GIT_EXECUTED EQUAL 0)) message(FATAL_ERROR "Could not identifiy git commit id") endif() endif() else() # This is a local build, stuff in some basic info: set(BUILD_ID "Unknown") set(BUILD_SERIES_NAME "local build") execute_process( COMMAND git rev-parse HEAD WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} RESULT_VARIABLE GIT_EXECUTED OUTPUT_VARIABLE BUILD_COMMIT_ID ) if (NOT(GIT_EXECUTED EQUAL 0)) set(BUILD_COMMIT_ID "Unknown") endif() string(STRIP ${BUILD_COMMIT_ID} BUILD_COMMIT_ID) execute_process( COMMAND git log -1 --date=iso --pretty=format:%ai WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} RESULT_VARIABLE GIT_EXECUTED OUTPUT_VARIABLE BUILD_DATETIME ) if (NOT(GIT_EXECUTED EQUAL 0)) set(BUILD_DATETIME "Unknown") endif() string(STRIP ${BUILD_DATETIME} BUILD_DATETIME) # The BUILD_COMMIT_ID and BUILD_DATETIME aren't updated on each repo pull # They are only updated when cmake re-configures the project # Therefore mark them as "approx: " set(BUILD_COMMIT_ID "approx: ${BUILD_COMMIT_ID}") set(BUILD_DATETIME "approx: ${BUILD_DATETIME}") endif() ================================================ FILE: CMakeLists.txt ================================================ # This is the top-level CMakeLists.txt file for the Cuberite project # # Use CMake to generate the build files for your platform cmake_minimum_required (VERSION 3.13) cmake_policy(VERSION 3.13...3.17.2) project( Cuberite DESCRIPTION "A lightweight, fast and extensible game server for Minecraft" HOMEPAGE_URL "https://cuberite.org" LANGUAGES C CXX ) option(BUILD_TOOLS "Sets up additional executables to be built along with the server" OFF) option(BUILD_UNSTABLE_TOOLS "Sets up yet more executables to be built, these can be broken and generally are obsolete" OFF) option(NO_NATIVE_OPTIMIZATION "Disables CPU-specific optimisations for the current machine, allows use on other CPUs of the same platform" OFF) option(PRECOMPILE_HEADERS "Enable precompiled headers for faster builds" ON) option(SELF_TEST "Enables testing code to be built" OFF) option(UNITY_BUILDS "Enables source aggregation for faster builds" ON) option(WHOLE_PROGRAM_OPTIMISATION "Enables link time optimisation for Release" ON) include("CMake/AddDependencies.cmake") include("CMake/Fixups.cmake") include("CMake/GenerateBindings.cmake") include("CMake/GroupSources.cmake") include("SetFlags.cmake") # Add build timestamp and details: include("CMake/StampBuild.cmake") # We need C++17 features: set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) # Static CRT: set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") # TODO: set_build_stamp() set_global_flags() build_dependencies() add_executable(${CMAKE_PROJECT_NAME}) add_subdirectory(src) set_exe_flags(${CMAKE_PROJECT_NAME}) link_dependencies(${CMAKE_PROJECT_NAME}) # Set the startup project to Cuberite, and the debugger dir: set_property(DIRECTORY PROPERTY VS_STARTUP_PROJECT ${CMAKE_PROJECT_NAME}) set_target_properties(${CMAKE_PROJECT_NAME} PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/Server") # Enable PCH and jumbo builds on supporting CMake: if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.16") if (PRECOMPILE_HEADERS) target_precompile_headers(${CMAKE_PROJECT_NAME} PRIVATE src/Globals.h) endif() set_target_properties(${CMAKE_PROJECT_NAME} PROPERTIES UNITY_BUILD ${UNITY_BUILDS}) else() message(WARNING "Precompiled headers for FASTER BUILDS not enabled, upgrade to CMake 3.16 or newer!") endif() # Selectively disable warnings in the level where the target is created: if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") # Generated file has old-style casts, missing prototypes, and deprecated declarations set_source_files_properties("${PROJECT_SOURCE_DIR}/src/Bindings/Bindings.cpp" PROPERTIES COMPILE_OPTIONS -Wno-everything) # File failed to follow NHS guidelines on handwashing and has not maintained good hygiene set_source_files_properties("${PROJECT_SOURCE_DIR}/src/IniFile.cpp" PROPERTIES COMPILE_OPTIONS -Wno-header-hygiene) elseif (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") set_source_files_properties("${PROJECT_SOURCE_DIR}/src/Bindings/Bindings.cpp" PROPERTIES COMPILE_OPTIONS -w) endif() if(BUILD_TOOLS) message(STATUS "Building tools") add_subdirectory(Tools/GrownBiomeGenVisualiser/) add_subdirectory(Tools/MCADefrag/) add_subdirectory(Tools/NoiseSpeedTest/) add_subdirectory(Tools/ProtoProxy/) endif() if(BUILD_UNSTABLE_TOOLS) message(STATUS "Building unstable tools") add_subdirectory(Tools/GeneratorPerformanceTest/) endif() # Self Test Mode enables extra checks at startup if(SELF_TEST) message(STATUS "Tests enabled") enable_testing() add_subdirectory(tests) endif() # The need for speed (in Release): if(WHOLE_PROGRAM_OPTIMISATION) include(CheckIPOSupported) check_ipo_supported(RESULT IPO_SUPPORTED OUTPUT IPO_CHECK_OUTPUT) if(IPO_SUPPORTED) set_property(TARGET ${CMAKE_PROJECT_NAME} PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) else() message(WARNING "IPO is not supported: ${IPO_CHECK_OUTPUT}") endif() endif() emit_fixups() group_sources() enable_bindings_generation() ================================================ FILE: COMPILING.md ================================================ Compiling Cuberite ================== To compile Cuberite from source, you need the following set of software: - CMake - Platform-specific make tool (Windows would be MSVC, Linux/macOS GNU make, etc.) - C compiler - Modern C++17 capable compiler and linker To contribute code, you also need a Git client. Windows ------- We use Microsoft Visual Studio for Windows compilation. It is possible to use other toolchains, but we don't test against them and they aren't supported. Visual Studio 2017 Community and above are being actively used for development. You can find download links for VS2019 Community [here][1]. Next, you need to download and install [CMake][2]. You should download a full installation package, so that the installer will set everything up for you (especially the paths). To contribute your changes to the source back to the repository, you need a Git client. Options are: - [Git for Windows][3] - [GitHub Desktop][4] - [TortoiseGit][5] Alternatively, if you want only to compile the source, without contributing, you can [download the sources in a ZIP file directly from GitHub][6]. If you're using Git to get the source, use the following command to set up the local workspace correctly: ``` git clone --recursive https://github.com/cuberite/cuberite.git ``` Now that you have the source, it's time to prepare the project files for your favorite compiler. Open a command window in the folder with the source and type in: ``` mkdir build cd build cmake .. ``` This creates a `build` folder where the build will take place, then runs CMake, which will auto-detect your Visual Studio version and produce the appropriate project and solution files. Finally, open the newly created file, `Cuberite.sln`, in your Visual Studio. If you want to run Cuberite from within VS, you need to first make sure that it will be run with the correct home folder. Normally this happens automatically, but for some Visual Studio versions the process doesn't stick. Right-click on the Cuberite project in the Solution Explorer tool window, and select Properties. In the dialog, navigate to Configuration properties -> Debugging in the tree on the left, then make sure the value `Working Directory` is set to `../Server`. If you don't do this, the server won't be able to find crafting recipes, item names or plugins. ### Release Configuration To make Visual Studio produce the version with the best performance, you will need to select a Release configuration. Go to menu Build -> Configuration Manager, and in the opened dialog, change the top left combo box (Active solution configuration) to Release. Close the dialog and build the solution. The resulting executable is called `Cuberite.exe` in the `Server` folder. ### Debug Configuration In order to tinker with the code, you'll more than likely need to use the debugging features of your IDE. To make them the easiest to use, you should switch to the Debug configuration - this provides the highest level of information while debugging, for the price of the executable being 2 - 10 times slower. Go to menu Build -> Configuration Manager, and in the opened dialog, change the top left combo box (Active solution configuration) to Debug. Close the dialog and build the solution. The resulting executable is called `Cuberite_debug.exe` in the `Server` folder. macOS ----- - Install git from its [website][7] or homebrew: `brew install git`. - Install Xcode (commandline tools are recommended) from the App Store or [the website][8]. - Install CMake from its [website][9] or homebrew: `brew install cmake`. Cuberite requires Xcode 11.3 or newer. ### Getting the Source ``` git clone --recursive https://github.com/cuberite/cuberite.git ``` ### Building Follow the instructions at [CMake on Unix-based platforms](#cmake-on-unix-based-platforms), using Xcode as cmake's generator. If no generator is specified, CMake will use the Makefile generator, in which case you must build with the `make` command. After doing so, run the command `xcodebuild lib/polarssl/POLARSSL.xcodeproj` in the build directory, in order to build polarssl, a library that is required by Cuberite. Lastly, run the command `xcodebuild` to build Cuberite. Optionally, you may open the project files for polarssl and then Cuberite in Xcode and build there. Linux, FreeBSD etc. ------------------- Install git, make, cmake and clang (or gcc), using your platform's package manager. Debian/Ubuntu: ``` sudo apt-get install git make cmake clang ``` Ensure that you have modern C++ compiler and linker (Clang 7.0+, GCC 7.4+, or VS 2017+). Cuberite also requires CMake 3.13 or newer. You might find that your distribution defaults are too out of date, in which case you may need to add a new `apt` source, or download directly from the projects' websites: - [Clang][Clang-download] - [CMake][2] ### Getting the Source ``` git clone --recursive https://github.com/cuberite/cuberite.git ``` ### Building Run the following commands to build Cuberite: ``` mkdir Release cd Release cmake -DCMAKE_BUILD_TYPE=RELEASE .. make -j`nproc` ``` This will build Cuberite in release mode, which is better for almost all cases. For more `cmake` options, or for building in debug mode, see [CMake on Unix-based platforms](#cmake-on-unix-based-platforms). Android ------- It is required that users obtain the latest copies of: - [The Android Native Development Kit (NDK)][10] - [Lua (download a binary)][11] Windows users may optionally install the [Ninja build system][12] for improved build speeds. ### Getting the Source ``` git clone --recursive https://github.com/cuberite/cuberite.git ``` ### Configuration From the `android` subdirectory: ``` cmake . -DCMAKE_SYSTEM_NAME=Android -DCMAKE_SYSTEM_VERSION=16 -DCMAKE_BUILD_TYPE=Release -DCMAKE_ANDROID_ARCH_ABI=armeabi -DCMAKE_ANDROID_NDK="" ``` where `CMAKE_ANDROID_NDK` should be the absolute path to where the Android NDK is installed. #### Generators to Use On Linux, the default Make is suggested. No additional parameters are required for this option. Windows users may make use of Visual Studio to compile for Android, but CMake requires the presence of Nvidia CodeWorks/Nsight Tegra, which can be a hassle to install. The easiest generator to use seems to be the NDK-bundled Make, to be specified: * `-G "MinGW Makefiles" -DCMAKE_MAKE_PROGRAM=""` where `CMAKE_MAKE_PROGRAM` should be the absolute path to the `make` program, found under the `prebuilt/windows-*/bin` subdirectory in the NDK folder. The next easiest generator is Ninja, which additionally offers multithreaded builds, to be specified: * `-G "Ninja"` #### Additional ABI Options For additional ABI options, visit: https://cmake.org/cmake/help/latest/variable/CMAKE_ANDROID_ARCH_ABI.html Please note that certain ABIs require specific [API levels](#api-level-requirements). #### API Level Requirements The minimum API level is 16 in the verbatim copy of this folder, due to the inclusion of position independent compilation. Additonally, API level 21 or higher is needed for 64 bit ABIs as earlier versions have no support for this architecture. To lower these requirements to run on very old devices, it is necessary to select a compatible ABI, and disable position independent code generation. ### Building From the `android` subdirectory: ``` cmake --build . ``` If the build succeeded, an Android-launchable binary will have been generated under the `Server` directory. However, since this directory does not have any supporting files, they must be copied from the parent folder's `Server` directory. To use it in the official Android app, compress the aforementioned `Server` directory into a Zip file, and transfer it to the phone on which the app is installed. #### Using the Compile Script on Linux Linux users are entitled to use the compile script, which provides some easy to use options and also contains instructions for using the binaries in the official Android app. When running the compile script, make sure to have the necessary build tools installed and run the compile script as following: ``` NDK="path/to/ndk/root" CMAKE="path/to/cmake/executable" android/compile.sh ``` The NDK variable must be set to the path to the NDK root, CMAKE to a call of the cmake binary used for compiling. If the cmake binary is in the PATH, a simple `CMAKE=cmake` is enough. As last parameter you either have to enter a correct ABI (see https://cmake.org/cmake/help/latest/variable/CMAKE_ANDROID_ARCH_ABI.html) or either all or clean. Clean will cause the script to remove the android-build directory, all will compile and zip all Cuberite for all 7 ABIs and create a zip archive of the android/Server direcory for use in the official Android app. If you are unsure which ABI is required for your phone, open the official Android app and navigate to "Settings" and "Install". It will show you the required ABI. Additional parameters may be given through environment variables, namely TYPE="" as Release or Debug (defaults to Release) and THREADS="4" as the number of threads used for compilation (defaults to 4). ### Running the Executables on a Device Note the locations to which the Zip files were transferred. Open the official Android app, and select "Settings", then "Install", and finally select the Zip files. Cuberite for Android is now ready to use. CMake on Unix-based platforms ----------------------------- ### Release Mode Release mode is preferred for almost all cases, it has much better speed and less console spam. However, if you are developing Cuberite actively, debug mode might be better. Assuming you are in the Cuberite folder created in the initial setup step, you need to run these commands: ``` mkdir Release cd Release cmake -DCMAKE_BUILD_TYPE=RELEASE .. ``` NOTE: CMake can generate project files for many different programs, such as Xcode, eclipse, and ninja. To use a different generator, first type `cmake --help`, and at the end, cmake will output the different generators that are available. To specify one, add `-G` followed by the name of the generator, in the `cmake` command. Note that the name is case-sensitive. The executable will be built in the `cuberite/Server` folder and will be named `Cuberite`. ### Debug Mode Debug mode is useful if you want more debugging information about Cuberite while it's running or if you want to use a debugger like GDB to debug issues and crashes. Assuming you are in the Cuberite folder created in the Getting the sources step, you need to run these commands: ``` mkdir Debug cd Debug cmake -DCMAKE_BUILD_TYPE=DEBUG .. ``` NOTE: CMake can generate project files for many different programs, such as Xcode, eclipse, and ninja. To use a different generator, first type `cmake --help`, and at the end, cmake will output the different generators that are available. To specify one, add `-G` followed by the name of the generator, in the `cmake` command. Note that the name is case-sensitive. The executable will be built in the `cuberite/Server` folder and will be named `Cuberite_debug`. ### 32 Bit Mode Switch This is useful if you want to compile Cuberite on an x64 (64-bit Intel) machine but want to use on an x86 (32-bit Intel) machine. This switch can be used with debug or release mode. Simply add: -DFORCE_32=1 to your cmake command and 32 bit will be forced. ### Compiling for Another Computer of the Same Architecture When cross-compiling for another computer of the same architecture it is important to set the NO_NATIVE_OPTIMIZATION flag. This tells the compiler not to optimise for your machine. This switch can be used with debug or release mode. To enable, simply add: -DNO_NATIVE_OPTIMIZATION=1 to your cmake command. ### List of All Build Flags Cuberite's build process supports a large number of flags for customising the builds. Use these flags by adding `-DFlag_name=Value` to the cmake configuration command. For example to enable test generation using the `SELF_TEST` flag add: `-DSELF_TEST=ON` ###### BUILD_TOOLS Adds the Cuberite tools to the build. At the moment only MCADefrag and ProtoProxy are added. Define as ON to enable. Define as OFF to disable. ###### BUILD_UNSTABLE_TOOLS Adds tools that are not working yet to the build. Currently this is only the Generator Performance Test. Used for developing these tools. Define as ON to enable. Define as OFF to disable. ###### SELF_TEST Enables generation of tests and self-test startup code. Tests can be run with ctest and with makefiles make test. Define as ON to enable. Define as OFF to disable. ###### FORCE_32 Forces the build to use 32 bit builds on *nix systems. Define as ON to enable. Define as OFF to disable. ###### NO_NATIVE_OPTIMIZATION Disables optimizations for the build host. This is important when building on a different machine from the one you will run Cuberite on as the build machine may support instructions the final machine does not. This flag only has any effect on linux. Define as ON to enable. Define as OFF to disable. ###### DISABLE_SYSTEM_LUA Disables use of the system lua, uses a compiled version instead. Useful if compiling on a system that doesn't already have lua installed. This option is incompatible with cross-compilation. ###### UNITY_BUILDS Controls use of unity builds, an optimisation that improves compile times at the expense of system compatibility and error message utility. Some systems may need to have this disabled in order to compile properly. Unity builds are only supported on CMake versions >= 3.16, if you have an old version unity builds will always be disabled and this flag has no effect. ###### PRECOMPILE_HEADERS Controls use of precompiled headers, an optimisation that improves compile times at the expense of system compatibility. Some systems may need to have this disabled in order to compile properly. Precompiled headers are only supported on CMake versions >= 3.16, if you have an old version precompiled headers will always be disabled and this flag has no effect. ###### WHOLE_PROGRAM_OPTIMISATION Controls use of link time optimisation (LTO), which slightly improves the generated binary file at the expense of compilation speed and system compatibility. Some systems may need to have this disabled in order to compile properly. [1]: https://www.visualstudio.com/downloads/ [2]: https://cmake.org/download/ [3]: https://git-for-windows.github.io/ [4]: https://desktop.github.com/ [5]: https://tortoisegit.org/ [6]: https://github.com/cuberite/cuberite/archive/master.zip [7]: https://git-scm.com/ [8]: https://developer.apple.com/downloads [9]: https://cmake.org/ [10]: https://developer.android.com/ndk/downloads/index.html [11]: https://www.lua.org/download.html [12]: https://github.com/ninja-build/ninja/releases [clang-download]: https://releases.llvm.org/download.html ================================================ FILE: CONTRIBUTING.md ================================================ How to Contribute to Cuberite ============================= Thank you for your interest in Cuberite. Contributing to Cuberite is easy, just fork the project on GitHub, make your changes and submit a pull request to get your code merged. That's all there is to it. Check out [GETTING-STARTED.md][1] for more information about setting up the development environment for Cuberite, finding issues to work on, etc... If you are new to open source and/or GitHub, or just aren't sure about some details in the contribution process, here's a tutorial to get you started: [How to Contribute to an Open Source Project on GitHub][2] Code Conventions ---------------- When contributing, you must follow our code conventions. Otherwise, CI builds will automatically fail and your PR will not be merged until the non-conforming code is fixed. Due to this, we strongly advise you to run `src/CheckBasicStyle.lua` before committing, it will perform various code style checks and warn you if your code does not conform to our conventions. `CheckBasicStyle.lua` can be configured to run automatically before every commit via a pre-commit hook, **this is highly recommended**. There are instructions on how to achieve this at the bottom of this file. Here are the conventions: - We use C++17. - Please use **tabs for indentation and spaces for alignment**. This means that if it's at line start, it's a tab; if it's in the middle of a line, it's a space. - All functions in all classes need documenting comments on what they do and what behavior they follow, use doxy-comments formatted as `/** Description */`. Do not use asterisks on additional lines in multi-line comments. - Use spaces after the comment markers: `// Comment` instead of `//Comment`. A comment must be prefixed with two spaces if it's on the same line with code: - `SomeFunction()//Note the two spaces prefixed to me and the space after the slashes.` - All variable names and function names use CamelCase style, with the exception of single letter variables. - `ThisIsAProperFunction()` `This_is_bad()` `this_is_bad()` `GoodVariableName` `badVariableName`. - All private member variables start with `m_`, function parameters start with `a_`, class names start with `c`. - `class cMonster { int m_Health; int DecreaseHealth(int a_Amount); }` - Put spaces after commas. `Vector3d(1, 2, 3)` instead of `Vector3d(1,2,3)` - Put spaces before and after every operator, except unary operators. - `a = b + c;` - `if (a == b)` - `++itr` - Keep individual functions spaced out by 5 empty lines, this enhances readability and makes navigation in the source file easier. - Add those extra parentheses to conditions, especially in C++: - `if ((a == 1) && ((b == 2) || (c == 3)))` instead of ambiguous `if (a == 1 && b == 2 || c == 3)` - This helps prevent mistakes such as `if (a & 1 == 0)` - Alpha-sort stuff that makes sense alpha-sorting—long lists of similar items etc. - White space is free, so use it freely. - "freely" as in "plentifully", not "arbitrarily". - All `case` statements inside a `switch` need an extra indent. - Each and every control statement deserves its braces. This helps maintainability later on when the file is edited, lines added or removed - the control logic doesn't break so easily. - The only exception: a `switch` statement with all `case` statements being a single short statement is allowed to use the short brace-less form. - These two rules really mean that indent is governed by braces. - Function parameters that are coordinates should be passed using an appropriate storage container, and not as three separate arguments. - e.g. for a block position, Vector3i. For an entity position, Vector3d. For a chunk coordinate, cChunkCoords. - For a 3-dimensional box of blocks, use cCuboid. For an axis-aligned bounding box, use cBoundingBox. - Parameters smaller than 4 elements (e.g. Vector3, cChunkCoords) should be passed by value. All other parameters should be passed by const reference, where applicable. - `Foo(Vector3d a_Param1, const cCuboid & a_Param2)` - See the discussion in issue #3853 - Use the provided wrappers for OS stuff: - Threading is done by inheriting from `cIsThread`, thread synchronization through `cCriticalSection` and `cEvent`, file access and filesystem operations through the `cFile` class, high-precision timing through `cStopwatch` - No magic numbers, use named constants: - `E_ITEM_XXX`, `E_BLOCK_XXX` and `E_META_XXX` for items and blocks. - `cEntity::etXXX` for entity types, `cMonster::mtXXX` for mob types. - `dimNether`, `dimOverworld` and `dimEnd` for world dimension. - `gmSurvival`, `gmCreative`, `gmAdventure` for game modes. - `wSunny`, `wRain`, `wThunderstorm` for weather. - `cChunkDef::Width`, `cChunkDef::Height` for chunk dimensions (C++). - etc. - Instead of checking for a specific value, use an `IsXXX` function, if available: - `cPlayer:IsGameModeCreative()` instead of` (cPlayer:GetGameMode() == gmCreative)` (the player can also inherit the gamemode from the world, which the value-d condition doesn't catch). - All `#include` directives are specified relative to the root source directory. - Add an empty last line in all source files (GCC and Git can complain otherwise). Pre-commit Hook --------------- When contributing, the code conventions above *must* be followed. Otherwise, the CI builds will automatically fail and your PR will not be merged until the non-conforming code is fixed. It is highly recommended to set up a pre-commit hook which will check your code style before every commit. Here is how to do that: - Clone the repository as usual. - Go to your `/.git/hooks` folder, create a text file named "pre-commit" there with the following contents: ``` #!/bin/sh src/CheckBasicStyle.lua 1>&2 -g ``` - If on Linux/Unix, you need to give the newly created file an execute permission: `chmod +x .git/hooks/pre-commit` - Lua must be installed. - You're done. Now, `src/CheckBasicStyle.lua` will check the changed files before every commit. If a problem is found, it will point you to that problem and will cancel the commit. Note that the check script is not smart enough to catch everything, so not having any warnings does not necessarily imply that you followed the conventions fully. The other humans working on this will perform more checks before merging. Github-related conventions -------------------------- The following rules are not strictly enforced, but if you follow them, you will make it easier for us to review your changes. - Use good short title for your PRs. `Store Health as float` is good, `Fix #4024` is not good. - If a PR fixes an issue, mention it in the PR description, but **not** in the commits themselves. Typically, we add the line `Fixes #007` to the bottom of the PR description, this makes Github link the PR to the issue, auto-close the issue when the PR is merged, and also is included in the merge message. - Focus on one thing only. Each PR should avoid making unrelated changes - those makes the history more difficult to understand later on, and they make the review a headache. - Feel free to rebase, amend or otherwise manipulate the commits in the PR (of course, as long as you're the only one working on the PR). We mostly squash-merge PRs, so your internal commit structure will not be important in the end. - If the PR is about one change, but it makes sense to keep the change broken into several commits, make sure each such commit is compilable, encapsulated, and possibly add a note to the PR description so that we consider this. Copyright --------- Your must either place your work in the public domain or licensed it under the Apache License 2.0, and if so you must add yourself to the contributors file to show that you accept the publication of your work under the license. **PLUGINS ONLY**: If your plugin is not licensed under the Apache License 2.0, then it must be compatible and marked as such. This is only valid for the plugins included within the Cuberite source; plugins developed on separate repositories can use whatever license they want. [1]: https://github.com/cuberite/cuberite/blob/master/GETTING-STARTED.md [2]: https://egghead.io/courses/how-to-contribute-to-an-open-source-project-on-github ================================================ FILE: CONTRIBUTORS ================================================ This file contains all known copyright holders of this software, as far as is practically possible to ascertain. If you contribute to this software you must add yourself to this file, to indicate your agreement to license your contributions according to the license as provided in the LICENSE file. 12xx12 9caihezi AirOne01 Altenius anguslmm (Angus McLean) ashquarky BasedDoge (Donated AlchemistVillage prefabs) bearbin (Alexander Harkness) beeduck bibo38 birkett (Anthony Birkett) Bond_009 changyongGuo Cocosushi6 CoolPuppyKid DarkoGNU derouinw dImrich (Damian Imrich) Diusrex Duralex dyexlzc Earboxer (Zach DeCook) FakeTruth (founder) feyokorenhof Gareth Nelson GefaketHD Griezn (Seppe Degryse) HaoTNN havel06 (Michal Havlíček) hle0 Howaner ion232 (Arran Ireland) jan64 jasperarmstrong jclever77 (Jon Clever) JK2K kevinr (Kevin Riggle) keyboard KingCol13 Lapayo linnemannr (Reid Linnemann) LittleBigBug (Ethan Jones) lkolbly LogicParrot Luksor M10360 marmot21 Masy98 mathiascode maxluchterhand1 MaxwellScroggs mborland mBornand mcfadyeni MeMuXin mgueydan MikeHunsinger mjagdis (Mike Jagdis) Morritz (TJ) morsmordere (Anzhelika Iugai) mtilden nesco NiLSPACE (formerly STR_Warrior) npresley0506 p-mcgowan Persson-dev plan1231 pokechu22 ProjectBM pwnOrbitals Rodarg Rorkh rs2k SamJBarney Schwertspize Seadragon91 (Lukas Pioch) sleirsgoevy (Sergey Lisov) Sofapriester solvictor Spekdrum (Pablo Beltran) SphinxC0re Spongecade (Updated wiki links) steve-nzr structinf (xdot) sweetgiorni SuperEwald Sxw1212 Taugeshtu TheHyper45 theophriene tigerw (Tiger Wang) tonibm19 tonitch (Debucquoy Anthony) TooAngel tympaniplayer (Nate Palmer) UltraCoderRU Warmist WebFreak001 williamhatcher (Helped with API documentation updates and bug fixes) worktycho Xenoxis xoft (Mattes Dolak/madmaxoft on GH) Yeeeeezus (Donated AlchemistVillage prefabs) ================================================ FILE: CheckLua.cmake ================================================ # CheckLua.cmake # Checks whether the Lua standalone interpreter is installed on the host system # If found, sets HAS_LUA_INTERPRETER to 1 and LUA_INTERPRETER_VERSION to the version reported ("5.1" etc.) # If not found, unsets HAS_LUA_INTERPRETER execute_process( COMMAND lua -e "io.stdout:write(string.match(_VERSION, '%d+%.%d+'))" RESULT_VARIABLE LUA_EXECUTED OUTPUT_VARIABLE LUA_INTERPRETER_VERSION ) if ("${LUA_EXECUTED}" STREQUAL "0") set(HAS_LUA_INTERPRETER 1) else() unset(HAS_LUA_INTERPRETER) unset(LUA_INTERPRETER_VERSION) endif() unset(LUA_EXECUTED) ================================================ FILE: Doxyfile ================================================ # Doxyfile 1.8.1.2 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project # # All text after a hash (#) is considered a comment and will be ignored # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" ") #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file # that follow. The default is UTF-8 which is also the encoding used for all # text before the first occurrence of this tag. Doxygen uses libiconv (or the # iconv built into libc) for the transcoding. See # https://www.gnu.org/software/libiconv for the list of possible encodings. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or sequence of words) that should # identify the project. Note that if you do not use Doxywizard you need # to put quotes around the project name if it contains spaces. PROJECT_NAME = Cuberite # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer # a quick idea about the purpose of the project. Keep the description short. PROJECT_BRIEF = "A lightweight, fast and extensible game server for Minecraft" # With the PROJECT_LOGO tag one can specify an logo or icon that is # included in the documentation. The maximum height of the logo should not # exceed 55 pixels and the maximum width should not exceed 200 pixels. # Doxygen will copy the logo to the output directory. PROJECT_LOGO = Server/favicon.png # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = doxy # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output # format and will distribute the generated files over these directories. # Enabling this option can be useful when feeding doxygen a huge amount of # source files, where putting all generated files in the same directory would # otherwise cause performance problems for the file system. CREATE_SUBDIRS = YES # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, # Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, # Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English # messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, # Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, # Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will # include brief member descriptions after the members that are listed in # the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # the brief description of a member or function before the detailed description. # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator # that is used to form the text in various listings. Each string # in this list, if found as the leading text of the brief description, will be # stripped from the text and the result after processing the whole list, is # used as the annotated text. Otherwise, the brief description is used as-is. # If left blank, the following values are used ("$name" is automatically # replaced with the name of the entity): "The $name class" "The $name widget" # "The $name file" "is" "provides" "specifies" "contains" # "represents" "a" "an" "the" ABBREVIATE_BRIEF = "The $name class" \ "The $name widget" \ "The $name file" \ is \ provides \ specifies \ contains \ represents \ a \ an \ the # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full # path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = YES # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag # can be used to strip a user-defined part of the path. Stripping is # only done if one of the specified strings matches the left-hand part of # the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the # path to strip. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells # the reader which header file to include in order to use a class. # If left blank only the name of the header file containing the class # definition is used. Otherwise one should specify the include paths that # are normally passed to the compiler using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful if your file system # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = YES # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style # comment as the brief description. If set to NO, the JavaDoc # comments will behave just like regular Qt-style comments # (thus requiring an explicit @brief command for a brief description.) JAVADOC_AUTOBRIEF = YES # If the QT_AUTOBRIEF tag is set to YES then Doxygen will # interpret the first line (until the first dot) of a Qt-style # comment as the brief description. If set to NO, the comments # will behave just like regular Qt-style comments (thus requiring # an explicit \brief command for a brief description.) QT_AUTOBRIEF = YES # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen # treat a multi-line C++ special comment block (i.e. a block of //! or /// # comments) as a brief description. This used to be the default behaviour. # The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = NO # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # re-implements. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce # a new page for each member. If set to NO, the documentation of a member will # be part of the file/class/namespace that contains it. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 4 # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" will allow you to # put the command \sideeffect (or @sideeffect) in the documentation, which # will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. ALIASES = # This tag can be used to specify a number of word-keyword mappings (TCL only). # A mapping has the form "name=value". For example adding # "class=itcl::class" will allow you to use the command class in the # itcl::class meaning. TCL_SUBST = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C # sources only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = NO # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java # sources only. Doxygen will then generate output that is more tailored for # Java. For instance, namespaces will be presented as packages, qualified # scopes will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources only. Doxygen will then generate output that is more tailored for # Fortran. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for # VHDL. OPTIMIZE_OUTPUT_VHDL = NO # Doxygen selects the parser to use depending on the extension of the files it # parses. With this tag you can assign which parser to use for a given extension. # Doxygen has a built-in mapping, but you can override or extend it using this # tag. The format is ext=language, where ext is a file extension, and language # is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, # C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make # doxygen treat .inc files as Fortran files (default is PHP), and .f files as C # (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions # you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. EXTENSION_MAPPING = # If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all # comments according to the Markdown format, which allows for more readable # documentation. See https://daringfireball.net/projects/markdown/ for details. # The output of markdown processing is further processed by doxygen, so you # can mix doxygen, HTML, and XML commands with Markdown formatting. # Disable only in case of backward compatibilities issues. MARKDOWN_SUPPORT = YES # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should # set this tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); v.s. # func(std::string) {}). This also makes the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. BUILTIN_STL_SUPPORT = NO # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. # Doxygen will parse them like normal C++ but will assume all classes use public # instead of private inheritance when no explicit protection keyword is present. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate getter # and setter methods for a property. Setting this option to YES (the default) # will make doxygen replace the get and set methods by a property in the # documentation. This will only work if the methods are indeed getting or # setting a simple type. If this is not the case, or you want to show the # methods anyway, you should set this option to NO. IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = NO # Set the SUBGROUPING tag to YES (the default) to allow class member groups of # the same type (for instance a group of public functions) to be put as a # subgroup of that type (e.g. under the Public Functions section). Set it to # NO to prevent subgrouping. Alternatively, this can be done per class using # the \nosubgrouping command. SUBGROUPING = YES # When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and # unions are shown inside the group in which they are included (e.g. using # @ingroup) instead of on a separate page (for HTML and Man pages) or # section (for LaTeX and RTF). INLINE_GROUPED_CLASSES = NO # When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and # unions with only public data fields will be shown inline in the documentation # of the scope in which they are defined (i.e. file, namespace, or group # documentation), provided this scope is documented. If set to NO (the default), # structs, classes, and unions are shown on a separate page (for HTML and Man # pages) or section (for LaTeX and RTF). INLINE_SIMPLE_STRUCTS = NO # When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum # is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically # be useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. TYPEDEF_HIDES_STRUCT = NO # The SYMBOL_CACHE_SIZE determines the size of the internal cache use to # determine which symbols to keep in memory and which to flush to disk. # When the cache is full, less often used symbols will be written to disk. # For small to medium size projects (<1000 input files) the default value is # probably good enough. For larger projects a too small cache size can cause # doxygen to be busy swapping symbols to and from disk most of the time # causing a significant performance penalty. # If the system has enough physical memory increasing the cache will improve the # performance by keeping more symbols in memory. Note that the value works on # a logarithmic scale so increasing the size by one will roughly double the # memory usage. The cache size is given by this formula: # 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, # corresponding to a cache size of 2^16 = 65536 symbols. SYMBOL_CACHE_SIZE = 0 # Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be # set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given # their name and scope. Since this can be an expensive process and often the # same symbol appear multiple times in the code, doxygen keeps a cache of # pre-resolved symbols. If the cache is too small doxygen will become slower. # If the cache is too large, memory is wasted. The cache size is given by this # formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0, # corresponding to a cache size of 2^16 = 65536 symbols. LOOKUP_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES EXTRACT_ALL = YES # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = YES # If the EXTRACT_PACKAGE tag is set to YES all members with package or internal # scope will be included in the documentation. EXTRACT_PACKAGE = NO # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = YES # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. When set to YES local # methods, which are defined in the implementation section but not in # the interface are included in the documentation. # If set to NO (the default) only methods in the interface are included. EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base # name of the file that contains the anonymous namespace. By default # anonymous namespaces are hidden. EXTRACT_ANON_NSPACES = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) these members will be included in the # various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. # If set to NO (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all # friend (class|struct|union) declarations. # If set to NO (the default) these declarations will be included in the # documentation. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any # documentation blocks found inside the body of a function. # If set to NO (the default) these blocks will be appended to the # function's detailed documentation block. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation # that is typed after a \internal command is included. If the tag is set # to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. CASE_SENSE_NAMES = NO # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = YES # If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen # will list include files with double quotes in the documentation # rather than with sharp brackets. FORCE_LOCAL_INCLUDES = NO # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen # will sort the (detailed) documentation of file and class members # alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the # brief documentation of file, namespace and class members alphabetically # by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = YES # If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen # will sort the (brief and detailed) documentation of class members so that # constructors and destructors are listed first. If set to NO (the default) # the constructors will appear in the respective orders defined by # SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. # This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO # and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. SORT_MEMBERS_CTORS_1ST = NO # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the # hierarchy of group names into alphabetical order. If set to NO (the default) # the group names will appear in their defined order. SORT_GROUP_NAMES = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be # sorted by fully-qualified names, including namespaces. If set to # NO (the default), the class list will be sorted only by class name, # not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the # alphabetical list. SORT_BY_SCOPE_NAME = NO # If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to # do proper type resolution of all parameters of a function it will reject a # match between the prototype and the implementation of a member function even # if there is only one candidate or it is obvious which candidate to choose # by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen # will still accept a match between prototype and implementation in such cases. STRICT_PROTO_MATCHING = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or # disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or macro consists of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. # The appearance of the initializer of individual variables and macros in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated # at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = YES # Set the SHOW_FILES tag to NO to disable the generation of the Files page. # This will remove the Files entry from the Quick Index and from the # Folder Tree View (if specified). The default is YES. SHOW_FILES = YES # Set the SHOW_NAMESPACES tag to NO to disable the generation of the # Namespaces page. This will remove the Namespaces entry from the Quick Index # and from the Folder Tree View (if specified). The default is YES. SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command , where is the value of # the FILE_VERSION_FILTER tag, and is the name of an input file # provided by doxygen. Whatever the program writes to standard output # is used as the file version. See the manual for examples. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed # by doxygen. The layout file controls the global structure of the generated # output files in an output format independent way. To create the layout file # that represents doxygen's defaults, run doxygen with the -l option. # You can optionally specify a file name after the option, if omitted # DoxygenLayout.xml will be used as the name of the layout file. LAYOUT_FILE = # The CITE_BIB_FILES tag can be used to specify one or more bib files # containing the references data. This must be a list of .bib files. The # .bib extension is automatically appended if omitted. Using this command # requires the bibtex tool to be installed. See also # https://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style # of the bibliography can be controlled using LATEX_BIB_STYLE. To use this # feature you need bibtex and perl available in the search path. CITE_BIB_FILES = #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings # for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = YES # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some # parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES # The WARN_NO_PARAMDOC option can be enabled to get warnings for # functions that are documented, but have no documentation for their parameters # or return value. If set to NO (the default) doxygen will only warn about # wrong or incomplete parameter documentation, but not about the absence of # documentation. WARN_NO_PARAMDOC = NO # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text # tags, which will be replaced by the file and line number from which the # warning originated and the warning text. Optionally the format may contain # $version, which will be replaced by the version of the file (if it could # be obtained via FILE_VERSION_FILTER) WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written # to stderr. WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be used to specify the files and/or directories that contain # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # with spaces. INPUT = src # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is # also the default input encoding. Doxygen uses libiconv (or the iconv built # into libc) for the transcoding. See https://www.gnu.org/software/libiconv for # the list of possible encodings. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh # *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py # *.f90 *.f *.for *.vhd *.vhdl FILE_PATTERNS = *.c \ *.cc \ *.cxx \ *.cpp \ *.c++ \ *.d \ *.java \ *.ii \ *.ixx \ *.ipp \ *.i++ \ *.inl \ *.h \ *.hh \ *.hxx \ *.hpp \ *.h++ \ *.idl \ *.odl \ *.cs \ *.php \ *.php3 \ *.inc \ *.m \ *.markdown \ *.md \ *.mm \ *.dox \ *.py \ *.f90 \ *.f \ *.for \ *.vhd \ *.vhdl # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = YES # The EXCLUDE tag can be used to specify files and/or directories that should be # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. # Note that relative paths are relative to the directory from which doxygen is # run. EXCLUDE = source/SQLite \ source/squirrelbindings # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded # from the input. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. Note that the wildcards are matched # against the file with absolute path, so to exclude all test directories # for example use the pattern */test/* EXCLUDE_PATTERNS = *StackWalker.* \ *LeakFinder.* \ *Bindings.* \ *ManualBindings.* # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test EXCLUDE_SYMBOLS = _* \ __* \ abstract # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. EXAMPLE_PATTERNS = * # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command , where # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. If FILTER_PATTERNS is specified, this tag will be # ignored. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. Doxygen will compare the file name with each pattern and apply the # filter if there is a match. The filters are a list of the form: # pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further # info on how filters are used. If FILTER_PATTERNS is empty or if # non of the patterns match the file name, INPUT_FILTER is applied. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO # The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file # pattern. A pattern will override the setting for FILTER_PATTERN (if any) # and it is also possible to disable source filtering for a specific pattern # using *.ext= (so without naming a filter). This option only has effect when # FILTER_SOURCE_FILES is enabled. FILTER_SOURCE_PATTERNS = #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. # Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. SOURCE_BROWSER = YES # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C, C++ and Fortran comments will always remain visible. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = NO # If the REFERENCES_RELATION tag is set to YES # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = NO # If the REFERENCES_LINK_SOURCE tag is set to YES (the default) # and SOURCE_BROWSER tag is set to YES, then the hyperlinks from # functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will # link to the source code. Otherwise they will link to the documentation. REFERENCES_LINK_SOURCE = YES # If the USE_HTAGS tag is set to YES then the references to source code # will point to the HTML generated by the htags(1) tool instead of doxygen # built-in source browser. The htags tool is part of GNU's global source # tagging system (see https://www.gnu.org/software/global/global.html). You # will need version 4.8.6 or higher. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen # will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = YES # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = c #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. Note that when using a custom header you are responsible # for the proper inclusion of any scripts and style sheets that doxygen # needs, which is dependent on the configuration options used. # It is advised to generate a default header using "doxygen -w html # header.html footer.html stylesheet.css YourConfigFile" and then modify # that header. Note that the header is subject to change so you typically # have to redo this when upgrading to a newer version of doxygen or when # changing the value of configuration settings such as GENERATE_TREEVIEW! HTML_HEADER = # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If the tag is left blank doxygen # will generate a default style sheet. Note that doxygen will try to copy # the style sheet file to the HTML output directory, so don't put your own # style sheet in the HTML output directory as well, or it will be erased! HTML_STYLESHEET = # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the HTML output directory. Note # that these files will be copied to the base HTML output directory. Use the # $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these # files. In the HTML_STYLESHEET file, use the file name only. Also note that # the files will be copied as-is; there are no commands or markers available. HTML_EXTRA_FILES = # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. # Doxygen will adjust the colors in the style sheet and background images # according to this color. Hue is specified as an angle on a colorwheel, # see https://en.wikipedia.org/wiki/Hue for more information. # For instance the value 0 represents red, 60 is yellow, 120 is green, # 180 is cyan, 240 is blue, 300 purple, and 360 is red again. # The allowed range is 0 to 359. HTML_COLORSTYLE_HUE = 220 # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of # the colors in the HTML output. For a value of 0 the output will use # grayscales only. A value of 255 will produce the most vivid colors. HTML_COLORSTYLE_SAT = 100 # The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to # the luminance component of the colors in the HTML output. Values below # 100 gradually make the output lighter, whereas values above 100 make # the output darker. The value divided by 100 is the actual gamma applied, # so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, # and 100 does not change the gamma. HTML_COLORSTYLE_GAMMA = 80 # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML # page will contain the date and time when the page was generated. Setting # this to NO can help when comparing the output of multiple runs. HTML_TIMESTAMP = YES # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. HTML_DYNAMIC_SECTIONS = NO # With HTML_INDEX_NUM_ENTRIES one can control the preferred number of # entries shown in the various tree structured indices initially; the user # can expand and collapse entries dynamically later on. Doxygen will expand # the tree to such a level that at most the specified number of entries are # visible (unless a fully collapsed tree already exceeds this amount). # So setting the number of entries 1 will produce a full collapsed tree by # default. 0 is a special value representing an infinite number of entries # and will result in a full expanded tree by default. HTML_INDEX_NUM_ENTRIES = 100 # If the GENERATE_DOCSET tag is set to YES, additional index files # will be generated that can be used as input for Apple's Xcode 3 # integrated development environment, introduced with OSX 10.5 (Leopard). # To create a documentation set, doxygen will generate a Makefile in the # HTML output directory. Running make will produce the docset in that # directory and running "make install" will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find # it at startup. # See https://developer.apple.com/tools/creatingdocsetswithdoxygen.html # for more information. GENERATE_DOCSET = NO # When GENERATE_DOCSET tag is set to YES, this tag determines the name of the # feed. A documentation feed provides an umbrella under which multiple # documentation sets from a single provider (such as a company or product suite) # can be grouped. DOCSET_FEEDNAME = "Doxygen generated docs" # When GENERATE_DOCSET tag is set to YES, this tag specifies a string that # should uniquely identify the documentation set bundle. This should be a # reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen # will append .docset to the name. DOCSET_BUNDLE_ID = org.doxygen.Project # When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify # the documentation publisher. This should be a reverse domain-name style # string, e.g. com.mycompany.MyDocSet.documentation. DOCSET_PUBLISHER_ID = org.doxygen.Publisher # The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. DOCSET_PUBLISHER_NAME = Publisher # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compiled HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You # can add a path in front of the file if the result should not be # written to the html output directory. CHM_FILE = # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can # be used to specify the location (absolute path including file name) of # the HTML help compiler (hhc.exe). If non-empty doxygen will try to run # the HTML help compiler on the generated index.hhp. HHC_LOCATION = # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING # is used to encode HtmlHelp index (hhk), content (hhc) and project file # content. CHM_INDEX_ENCODING = # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = NO # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and # QHP_VIRTUAL_FOLDER are set, an additional index file will be generated # that can be used as input for Qt's qhelpgenerator to generate a # Qt Compressed Help (.qch) of the generated HTML documentation. GENERATE_QHP = NO # If the QHG_LOCATION tag is specified, the QCH_FILE tag can # be used to specify the file name of the resulting .qch file. # The path specified is relative to the HTML output folder. QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # https://doc.qt.io/qt-5/qthelpproject.html#namespace QHP_NAMESPACE = org.doxygen.Project # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # https://doc.qt.io/qt-5/qthelpproject.html#virtual-folders QHP_VIRTUAL_FOLDER = doc # If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to # add. For more information please see # https://doc.qt.io/qt-5/qthelpproject.html#custom-filters QHP_CUST_FILTER_NAME = # The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the # custom filter to add. For more information please see # # Qt Help Project / Custom Filters. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # project's # filter section matches. # # Qt Help Project / Filter Attributes. QHP_SECT_FILTER_ATTRS = # If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can # be used to specify the location of Qt's qhelpgenerator. # If non-empty doxygen will try to run qhelpgenerator on the generated # .qhp file. QHG_LOCATION = # If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files # will be generated, which together with the HTML files, form an Eclipse help # plugin. To install this plugin and make it available under the help contents # menu in Eclipse, the contents of the directory containing the HTML and XML # files needs to be copied into the plugins directory of eclipse. The name of # the directory within the plugins directory should be the same as # the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before # the help appears. GENERATE_ECLIPSEHELP = NO # A unique identifier for the eclipse help plugin. When installing the plugin # the directory name containing the HTML and XML files should also have # this name. ECLIPSE_DOC_ID = org.doxygen.Project # The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) # at top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. Since the tabs have the same information as the # navigation tree you can set this option to NO if you already set # GENERATE_TREEVIEW to YES. DISABLE_INDEX = NO # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. # If the tag value is set to YES, a side panel will be generated # containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). # Windows users are probably better off using the HTML help feature. # Since the tree basically has the same information as the tab index you # could consider to set DISABLE_INDEX to NO when enabling this option. GENERATE_TREEVIEW = NO # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values # (range [0,1..20]) that doxygen will group on one line in the generated HTML # documentation. Note that a value of 0 will completely suppress the enum # values from appearing in the overview section. ENUM_VALUES_PER_LINE = 4 # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 # When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open # links to external symbols imported via tag files in a separate window. EXT_LINKS_IN_WINDOW = NO # Use this tag to change the font size of Latex formulas included # as images in the HTML documentation. The default is 10. Note that # when you change the font size after a successful doxygen run you need # to manually remove any form_*.png images from the HTML output directory # to force them to be regenerated. FORMULA_FONTSIZE = 10 # Use the FORMULA_TRANPARENT tag to determine whether or not the images # generated for formulas are transparent PNGs. Transparent PNGs are # not supported properly for IE 6.0, but are supported on all modern browsers. # Note that when changing this option you need to delete any form_*.png files # in the HTML output before the changes have effect. FORMULA_TRANSPARENT = YES # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax # (see https://www.mathjax.org) which uses client side Javascript for the # rendering instead of using prerendered bitmaps. Use this if you do not # have LaTeX installed or if you want to formulas look prettier in the HTML # output. When enabled you may also need to install MathJax separately and # configure the path to it using the MATHJAX_RELPATH option. USE_MATHJAX = NO # When MathJax is enabled you need to specify the location relative to the # HTML output directory using the MATHJAX_RELPATH option. The destination # directory should contain the MathJax.js script. For instance, if the mathjax # directory is located at the same level as the HTML output directory, then # MATHJAX_RELPATH should be ../mathjax. The default value points to # the MathJax Content Delivery Network so you can quickly see the result without # installing MathJax. However, it is strongly recommended to install a local # copy of MathJax from https://www.mathjax.org before deployment. MATHJAX_RELPATH = https://cdn.mathjax.org/mathjax/latest # The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension # names that should be enabled during MathJax rendering. MATHJAX_EXTENSIONS = # When the SEARCHENGINE tag is enabled doxygen will generate a search box # for the HTML output. The underlying search engine uses javascript # and DHTML and should work on any modern browser. Note that when using # HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets # (GENERATE_DOCSET) there is already a search function so this one should # typically be disabled. For large projects the javascript based search engine # can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. SEARCHENGINE = NO # When the SERVER_BASED_SEARCH tag is enabled the search engine will be # implemented using a PHP enabled web server instead of at the web client # using Javascript. Doxygen will generate the search PHP script and index # file to put on the web server. The advantage of the server # based approach is that it scales better to large projects and allows # full text search. The disadvantages are that it is more difficult to setup # and does not have live searching capabilities. SERVER_BASED_SEARCH = NO #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = NO # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. # Note that when enabling USE_PDFLATEX this option is only used for # generating bitmaps for formulas in the HTML output, but not in the # Makefile that is written to the output directory. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4 # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = # The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for # the generated latex document. The footer should contain everything after # the last chapter. If it is left blank doxygen will generate a # standard footer. Notice: only use this tag if you know what you are doing! LATEX_FOOTER = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = YES # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = YES # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO # If LATEX_HIDE_INDICES is set to YES then doxygen will not # include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = NO # If LATEX_SOURCE_CODE is set to YES then doxygen will include # source code with syntax highlighting in the LaTeX output. # Note that which sources are shown also depends on other settings # such as SOURCE_BROWSER. LATEX_SOURCE_CODE = NO # The LATEX_BIB_STYLE tag can be used to specify the style to use for the # bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See # https://en.wikipedia.org/wiki/BibTeX for more info. LATEX_BIB_STYLE = plain #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load style sheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = NO # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = NO # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml # The XML_SCHEMA tag can be used to specify an XML schema, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- # If the GENERATE_PERLMOD tag is set to YES Doxygen will # generate a Perl module file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO # If the PERLMOD_LATEX tag is set to YES Doxygen will generate # the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be # nicely formatted so it can be parsed by a human reader. This is useful # if you want to understand what is going on. On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES # The names of the make variables in the generated doxyrules.make file # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. # This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = NO # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_DEFINED tags. EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # pointed to by INCLUDE_PATH will be searched when a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. To prevent a macro definition from being # undefined via #undef or recursively expanded use the := operator # instead of the = operator. PREDEFINED = # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition that # overrules the definition found in the source code. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all references to function-like macros # that are alone on a line, have an all uppercase name, and do not end with a # semicolon, because these will confuse the parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # The TAGFILES option can be used to specify one or more tagfiles. For each # tag file the location of the external documentation should be added. The # format of a tag file without this location is as follows: # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # TAGFILES = file1=loc1 "file2 = loc2" ... # where "loc1" and "loc2" can be relative or absolute paths # or URLs. Note that each tag file must have a unique name (where the name does # NOT include the path). If a tag file is not located in the directory in which # doxygen is run, you must also specify the path to the tagfile here. TAGFILES = # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base # or super classes. Setting the tag to NO turns the diagrams off. Note that # this option also works with HAVE_DOT disabled, but it is recommended to # install and use dot, since it yields more powerful graphs. CLASS_DIAGRAMS = YES # You can define message sequence charts within doxygen comments using the \msc # command. Doxygen will then run the mscgen tool (see # http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the # documentation. The MSCGEN_PATH tag allows you to specify the directory where # the mscgen tool resides. If left empty the tool is assumed to be found in the # default search path. MSCGEN_PATH = # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = YES # The DOT_NUM_THREADS specifies the number of dot invocations doxygen is # allowed to run in parallel. When set to 0 (the default) doxygen will # base this on the number of processors available in the system. You can set it # explicitly to a value larger than 0 to get control over the balance # between CPU load and processing speed. DOT_NUM_THREADS = 12 # By default doxygen will use the Helvetica font for all dot files that # doxygen generates. When you want a differently looking font you can specify # the font name using DOT_FONTNAME. You need to make sure dot is able to find # the font, which can be done by putting it in a standard location or by setting # the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the # directory containing the font. DOT_FONTNAME = Helvetica # The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. # The default size is 10pt. DOT_FONTSIZE = 10 # By default doxygen will tell dot to use the Helvetica font. # If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to # set the path where dot can find it. DOT_FONTPATH = # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = YES # If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen # will generate a graph for groups, showing the direct groups dependencies GROUP_GRAPHS = YES # If the UML_LOOK tag is set to YES doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = NO # If the UML_LOOK tag is enabled, the fields and methods are shown inside # the class node. If there are many fields or methods and many nodes the # graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS # threshold limits the number of items for each type to make the size more # managable. Set this to 0 for no limit. Note that the threshold may be # exceeded by 50% before the limit is enforced. UML_LIMIT_NUM_FIELDS = 10 # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = NO # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES # If the CALL_GRAPH and HAVE_DOT options are set to YES then # doxygen will generate a call dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable call graphs # for selected functions only using the \callgraph command. CALL_GRAPH = NO # If the CALLER_GRAPH and HAVE_DOT tags are set to YES then # doxygen will generate a caller dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable caller # graphs for selected functions only using the \callergraph command. CALLER_GRAPH = NO # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will generate a graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES # If the DIRECTORY_GRAPH and HAVE_DOT tags are set to YES # then doxygen will show the dependencies a directory has on other directories # in a graphical way. The dependency relations are determined by the #include # relations between the files in the directories. DIRECTORY_GRAPH = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are svg, png, jpg, or gif. # If left blank png will be used. If you choose svg you need to set # HTML_FILE_EXTENSION to xhtml in order to make the SVG files # visible in IE 9+ (other browsers do not have this requirement). DOT_IMAGE_FORMAT = png # If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to # enable generation of interactive SVG images that allow zooming and panning. # Note that this requires a modern browser other than Internet Explorer. # Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you # need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files # visible. Older versions of IE do not have SVG support. INTERACTIVE_SVG = NO # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found in the path. DOT_PATH = # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The MSCFILE_DIRS tag can be used to specify one or more directories that # contain msc files that are included in the documentation (see the # \mscfile command). MSCFILE_DIRS = # The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of # nodes that will be shown in the graph. If the number of nodes in a graph # becomes larger than this value, doxygen will truncate the graph, which is # visualized by representing a node as a red box. Note that doxygen if the # number of direct children of the root node in a graph is already larger than # DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note # that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. DOT_GRAPH_MAX_NODES = 500 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the # graphs generated by dot. A depth value of 3 means that only nodes reachable # from the root by following a path via at most 3 edges will be shown. Nodes # that lay further from the root node will be omitted. Note that setting this # option to 1 or 2 may greatly reduce the computation time needed for large # code bases. Also note that the size of a graph can be further restricted by # DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. MAX_DOT_GRAPH_DEPTH = 0 # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent # background. This is disabled by default, because dot on Windows does not # seem to support this out of the box. Warning: Depending on the platform used, # enabling this option may lead to badly anti-aliased labels on the edges of # a graph (i.e. they become hard to read). DOT_TRANSPARENT = NO # Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output # files in one run (i.e. multiple -o and -T options on the command line). This # makes dot run faster, but since only newer versions of dot (>1.8.10) # support this, this feature is disabled by default. DOT_MULTI_TARGETS = YES # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES ================================================ FILE: GETTING-STARTED.md ================================================ Getting Started =============== Hello! Thanks for wanting to work on this project :smile:, and I hope that this file will help you somewhat in getting all set up and running. I'll go through the basics of getting the project environment set up, the code organization and style, and general development practices. I'll also show you some good issues to start off working on to get yourself familiarised with the code. Note that this document is about contributing code for Cuberite. - If you are looking for usage instructions, see the [User's Manual][1] instead. - If you would like to help but you are not a programmer, you can still help with testing! Please see the [TESTING.md][2] file. Minecraft Basics ---------------- If you don't play Minecraft or don't have a great knowledge of the basic systems, you should get to know them. The [Minecraft Wiki][3] is quite useful for this task, although some youtubers are also fairly good at teaching the basics and just playing is quite good too. It is possible to contribute without knowing minecraft in detail though, or even owning a license. I'd say that the important topics are: - Different types of blocks and how they act. - Mobs, what they do and how. - Redstone, pistons, and automation. - Farming. - Fighting, health and the hunger system. Useful Resources ---------------- - [Minecraft Wiki](https://minecraft.wiki/w/Minecraft_Wiki) - [Minecraft Protocol Wiki](http://wiki.vg/Main_Page) - [Lua API Documentation](https://api.cuberite.org/) - [Visual Studio Community Edition Download](https://www.visualstudio.com/downloads/) Setting up a Dev Environment ============================ Requirements ------------ ### Linux/BSD/Solaris/macOS You'll need the basic C++ build tools: - gcc (or clang or another C compiler) - g++ (or clang++ or another C++ compiler) - make You'll also need CMake to generate the makefile to build from. ### Windows If you use Windows, your best bet is the Microsoft Visual Studio, available as a free download in the Community edition from Microsoft. You'll also need CMake to generate the project files. Setting up the Repo ------------------- Next, you'll need to set up the repo. You should make a fork and work on that, then create a Pull Request so that we can review and merge your code. After you've "earned" an honorable status, we'll give you write access to the repository, so that you can work on branches in the main repo here (still use PRs though, they're great tools for review and discussion). Once you've cloned, you need to pull down the submodules: git submodule init git submodule update After that they should come down automatically when you pull but it's not bad to refresh every once in a while. Repo Arrangement ---------------- The Cuberite repo has recently been rearranged for better code separation and other things, but basically it's split into a few areas: - `src` This holds all of the Cuberite source code, and is where most development takes place. It's split into logical areas for blocks, the protocol handling and other things. - `lib` This holds all the 3rd party libraries for Cuberite. You basically don't need to touch these, just make sure they are present (git submodules) - `Server` This contains the default plugins and environment to actually run the server. This folder's contents are linked into the executable output folder for each build flavor. In the `Plugins` folder there are the default plugins. The config files are also stored here. Config files with `.example.ini` on the end are generated by the server or source control and should be left alone, instead you should copy them to a file without the `example` in the name which will be prioritised over the generated ones. Code Style ---------- You should follow the code style guidelines in [CONTRIBUTING.md][4], as well as other C++ best practices. Note that there is a script file, $/src/CheckBasicStyle.lua, that can check some common violations of the coding style. You should run this file to check your code regularly. This script is run during the integration builds and if it fails, the build will fail. Note that you need Lua installed in order to run this script. It is recommended to set this up as a pre-commit hook and doing so is covered in CONTRIBUTING.md. How to Build ------------ ### Linux/BSD/Solaris/macOS Follow the instructions in [COMPILING.md][5]. You probably want to build in debug mode (when you're developing) for console alerts and debugging capability, even though it's much slower for everyday use. Basically, the process is: cmake . -DCMAKE_BUILD_TYPE=DEBUG && make ### Windows You need to first generate a solution file by executing CMake. At the top-level folder of the repository: ``` mkdir VS2017-x64 cd VS2017-x64 cmake -DBUILD_TOOLS=1 -DSELF_TEST=1 .. ``` Then just open the solution file in MSVC and build. Note that the first time after generating the solution, you will need to do extra setup in order to be able to fully debug in MSVC: - Set the startup project to Cuberite: right-click the Cuberite project in the Solution Explorer and choose "Set as Startup Project". - Set the debugging folder: right-click the Cuberite project in the Solution Explorer, choose "Properties". In the dialog, browse to "Configuration Properties" -> "Debugging" and set "Working Directory" to "../Server". How to Run ---------- The server can be run (on *nix) by a simple `./Cuberite` in the `Server` directory. On first run it will generate the world and start a server on the default port (configurable in `settings.ini`) so you can connect in Minecraft via `localhost`. Where to Get Started -------------------- Issues that should be easy to get started with are tagged as [easy][6] in GitHub issues. Other good places to get started are: - Cleaning up some of the compiler warnings. Check [our CI][7] for a list of them. - Writing some plugins: They are written in lua, with excellent API documentation available via [APIDump][8]. The [Core plugin][9] should also help quite a bit here. Special Things -------------- - Make yourself familiar with the community. Visit the forums: https://forum.cuberite.org/ - Ask questions as much as you like, we're here to help :smiley: [1]: https://book.cuberite.org/ [2]: https://github.com/cuberite/cuberite/blob/master/TESTING.md [3]: https://minecraft.wiki/w/Minecraft_Wiki [4]: https://github.com/cuberite/cuberite/blob/master/CONTRIBUTING.md [5]: https://github.com/cuberite/cuberite/blob/master/COMPILING.md [6]: https://github.com/cuberite/cuberite/issues?q=is%3Aopen+is%3Aissue+label%3Aeffort%2Feasy [7]: https://builds.cuberite.org/job/cuberite/job/master/lastSuccessfulBuild/console [8]: https://api.cuberite.org/ [9]: https://github.com/cuberite/Core ================================================ FILE: Jenkinsfile ================================================ pipeline { options { timeout(time: 1, unit: 'HOURS') } agent { docker 'cuberite/docker-ci/minimal:latest' } stages { stage("Prepare") { steps { sh 'git submodule update --init' } } stage("Check") { parallel { stage("CheckBasicStyle") { steps { dir("src") { sh 'find . -name \\*.cpp -or -name \\*.h > AllFiles.lst' sh 'lua CheckBasicStyle.lua' sh 'cd Bindings && lua CheckBindingsDependencies.lua' } } } stage("clang-tidy") { steps { sh './clang-tidy.sh -j 4' } } } } stage("Build") { parallel { stage("gcc") { environment { CI_CUBERITE_BUILD_TYPE = 'Release' CI_JOB_NUMBER = "{$env.BUILD_ID}" CC = "gcc" CXX = "g++" } steps { sh 'bash ./cibuild.sh' } } stage("clang") { environment { CI_CUBERITE_BUILD_TYPE = 'Debug' CI_JOB_NUMBER = "{$env.BUILD_ID}" CC = "clang" CXX = "clang++" } steps { sh 'bash ./cibuild.sh' } } } } stage("Artifacts") { when { branch 'master' } steps { archiveArtifacts artifacts: 'gcc_Release/Server/.luacheckrc' } } } post { always { cleanWs() } } } ================================================ FILE: LICENSE ================================================ Cuberite: A lightweight, fast and extensible game server for Minecraft www: https://cuberite.org Copyright 2011-2025 Cuberite Contributors A full list of known copyright holders can be found in the CONTRIBUTORS file to be distributed with all copies of this software. ------ Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ================================================ FILE: README.md ================================================ # Cuberite [![Jenkins Build Status](https://img.shields.io/jenkins/build?jobUrl=https%3A%2F%2Fbuilds.cuberite.org%2Fjob%2Fcuberite%2Fjob%2Fmaster&label=Jenkins)](https://builds.cuberite.org/job/cuberite/job/master/) [![AppVeyor Build Status](https://img.shields.io/appveyor/ci/cuberite/cuberite/master.svg?label=AppVeyor)](https://ci.appveyor.com/project/cuberite/cuberite) Cuberite is a Minecraft-compatible multiplayer game server that is written in C++ and designed to be efficient with memory and CPU, as well as having a flexible Lua Plugin API. Cuberite is compatible with the Java Edition Minecraft client. Cuberite runs on Windows, *nix and Android operating systems. This includes Android phones and tablets as well as Raspberry Pis; support for small embedded devices is experimental. Currently we support Release 1.8 - 1.12.2 Minecraft protocol versions. Subscribe to [the newsletter][1] for important updates and project news. ## Installation There are several ways to obtain Cuberite. ### Binaries - The easiest method is downloading for Windows or Linux from the [website][2]. - You can use the EasyInstall script for Linux and macOS, which automatically downloads the correct binary. The script is described below. #### The EasyInstall script This script will download the correct binary from the project site. curl -sSfL https://download.cuberite.org | sh ### Compiling - You can compile automatically for Linux, macOS and FreeBSD with the `compile.sh` script. The script is described below. - You can also compile manually. See [COMPILING.md][4]. Compiling may provide better performance (1.5-3x as fast) and it supports more operating systems. #### The compile.sh script This script downloads the source code and compiles it. The script is smart enough to notify you of missing dependencies and instructing you on how to install them. The script doesn't work for Windows. Using curl: sh -c "$(curl -sSfL -o - https://compile.cuberite.org)" Or using wget: sh -c "$(wget -O - https://compile.cuberite.org)" ### Hosted services - Hosted Cuberite is available via [Gamocosm][5]. ## Contributing Cuberite is licensed under the Apache License V2, and we welcome anybody to fork and submit a Pull Request back with their changes, and if you want to join as a permanent member we can add you to the team. Cuberite is developed in C++ and Lua. To contribute code, please check out [GETTING-STARTED.md][6] and [CONTRIBUTING.md][7] for more details. Plugins are written in Lua. You can contribute by developing plugins and submitting them to the [plugin repository][8] or the [forum][9]. Please check out our [plugin introduction guide][10] for more info. If you are not a programmer, you can help by testing Cuberite and reporting bugs. See [TESTING.md][11] for details. You can also help with documentation by contributing to the [User's Manual][12]. ## Other Stuff For other stuff, check out the [homepage][13], the [Users' Manual][14], the [forums][15], and the [Plugin API][16]. Support the Cuberite development team on [Liberapay][17] [1]: https://cuberite.org/news/#subscribe [2]: https://cuberite.org/ [4]: https://github.com/cuberite/cuberite/blob/master/COMPILING.md [5]: https://gamocosm.com/ [6]: https://github.com/cuberite/cuberite/blob/master/GETTING-STARTED.md [7]: https://github.com/cuberite/cuberite/blob/master/CONTRIBUTING.md [8]: https://plugins.cuberite.org/ [9]: https://forum.cuberite.org/forum-2.html [10]: https://api.cuberite.org/Writing-a-Cuberite-plugin.html [11]: https://github.com/cuberite/cuberite/blob/master/TESTING.md [12]: https://github.com/cuberite/users-manual [13]: https://cuberite.org/ [14]: https://book.cuberite.org/ [15]: https://forum.cuberite.org/ [16]: https://api.cuberite.org/ [17]: https://liberapay.com/Cuberite ================================================ FILE: Server/.gitignore ================================================ *.exe *.dll *.exp *.lib *.ini Cuberite Cuberite_debug luaexe CommLogs/ GalExports/ GalExportWeb/ GalleryWeb/ logs players world* API/ API.txt API_wiki.txt *.dat schematics *.schematic *.ilk *.pdb memdump* *.grab *.cfg *.sqlite helgrind.log valgrind.log motd.txt *.deuser *.dmp *.xml mcserver_api.lua cuberite_api.lua DuplicateDocs.txt # Ignore the webadmin certs / privkey, so that no-one commits theirs by accident: webadmin/httpscert.crt webadmin/httpskey.pem ================================================ FILE: Server/Install/.gitignore ================================================ *.tag *.example.ini ================================================ FILE: Server/Install/Cuberite_high_detail_debug.cmd ================================================ Cuberite --crash-dump-full ================================================ FILE: Server/Install/Cuberite_medium_detail_debug.cmd ================================================ Cuberite --crash-dump-globals ================================================ FILE: Server/Install/PackWindowsExecutables.cmd ================================================ @echo off :: This script is run in the Appveyor CI builds to pack up the artifacts :: It is expected to be run with the Server folder as the current working dir @echo on :: Only test that the server runs for pull requests :: Don't upload any artifacts until it's merged into master if defined APPVEYOR_PULL_REQUEST_NUMBER ( echo stop 1>>cmds.txt Cuberite --port 32767 0buildinfo.txt 7z a -tzip -y Cuberite.zip -scsWIN -i@Install\WindowsExecutables.list -xr!*.git* 7z a -tzip -y PDBs.zip -scsWIN -i@Install/WindowsPDBs.list -xr!*.git* :: Generate API documentation git clone https://github.com/madmaxoft/ManualApiDump Plugins/ManualApiDump echo load ManualApiDump 1>cmds.txt echo manualapi 1>>cmds.txt echo load APIDump 1>>cmds.txt echo api 1>>cmds.txt echo stop 1>>cmds.txt Cuberite --port 32767 0 Copyright (c) 2007-2012 Niels Provos and Nick Mathewson Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ============================== Portions of Libevent are based on works by others, also made available by them under the three-clause BSD license above. The copyright notices are available in the corresponding source files; the license is as above. Here's a list: log.c: Copyright (c) 2000 Dug Song Copyright (c) 1993 The Regents of the University of California. strlcpy.c: Copyright (c) 1998 Todd C. Miller win32select.c: Copyright (c) 2003 Michael A. Davis evport.c: Copyright (c) 2007 Sun Microsystems ht-internal.h: Copyright (c) 2002 Christopher Clark minheap-internal.h: Copyright (c) 2006 Maxim Yegorushkin ============================== The arc4module is available under the following, sometimes called the "OpenBSD" license: Copyright (c) 1996, David Mazieres Copyright (c) 2008, Damien Miller Permission to use, copy, modify, and distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ============================== The Windows timer code is based on code from libutp, which is distributed under this license, sometimes called the "MIT" license. Copyright (c) 2010 BitTorrent, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 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 AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: Server/Install/ThirdPartyLicenses/Lua-LICENSE.txt ================================================ Copyright (C) 1994-2008 Lua.org, PUC-Rio. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 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 AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: Server/Install/ThirdPartyLicenses/LuaExpat-license.html ================================================ LuaExpat: XML Expat parsing for the Lua programming language
LuaExpat
XML Expat parsing for the Lua programming language

License

LuaExpat is free software: it can be used for both academic and commercial purposes at absolutely no cost. There are no royalties or GNU-like "copyleft" restrictions. LuaExpat qualifies as Open Source software. Its licenses are compatible with GPL. LuaExpat is not in the public domain and the Kepler Project keep its copyright. The legal details are below.

The spirit of the license is that you are free to use LuaExpat for any purpose at no cost without having to ask us. The only requirement is that if you do use LuaExpat, then you should give us credit by including the appropriate copyright notice somewhere in your product or its documentation.

The LuaExpat library is designed and implemented by Roberto Ierusalimschy. The implementation is not derived from licensed software.


Copyright © 2003-2007 The Kepler Project.

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

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 AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Valid XHTML 1.0!

$Id: license.html,v 1.9 2007/06/05 20:03:12 carregal Exp $

================================================ FILE: Server/Install/ThirdPartyLicenses/LuaSQLite3-LICENSE.txt ================================================ /************************************************************************ * lsqlite3 * * Copyright (C) 2002-2013 Tiago Dionizio, Doug Currie * * All rights reserved. * * Author : Tiago Dionizio * * Author : Doug Currie * * Library : lsqlite3 - a SQLite 3 database binding for Lua 5 * * * * Permission is hereby granted, free of charge, to any person obtaining * * a copy of this software and associated documentation files (the * * "Software"), to deal in the Software without restriction, including * * without limitation the rights to use, copy, modify, merge, publish, * * distribute, sublicense, and/or sell copies of the Software, and to * * permit persons to whom the Software is furnished to do so, subject to * * the following conditions: * * * * The above copyright notice and this permission notice shall be * * included in all copies or substantial portions of the Software. * * * * 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 AND NONINFRINGEMENT.* * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY * * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ************************************************************************/ ================================================ FILE: Server/Install/ThirdPartyLicenses/MersenneTwister-LICENSE.txt ================================================ // The Mersenne Twister is an algorithm for generating random numbers. It // was designed with consideration of the flaws in various other generators. // The period, 2^19937-1, and the order of equidistribution, 623 dimensions, // are far greater. The generator is also fast; it avoids multiplication and // division, and it benefits from caches and pipelines. For more information // see the inventors' web page at // http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html // Reference // M. Matsumoto and T. Nishimura, "Mersenne Twister: A 623-Dimensionally // Equidistributed Uniform Pseudo-Random Number Generator", ACM Transactions on // Modeling and Computer Simulation, Vol. 8, No. 1, January 1998, pp 3-30. // Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, // Copyright (C) 2000 - 2009, Richard J. Wagner // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // 1. Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // 2. Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // 3. The names of its contributors may not be used to endorse or promote // products derived from this software without specific prior written // permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. ================================================ FILE: Server/Install/ThirdPartyLicenses/SQLiteCpp-LICENSE.txt ================================================ The MIT License (MIT) Copyright (c) 2012-2014 Sebastien Rombauts (sebastien.rombauts@gmail.com) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 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 AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: Server/Install/ThirdPartyLicenses/fmt-LICENSE.rst ================================================ Copyright (c) 2012 - 2016, Victor Zverovich All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================ FILE: Server/Install/UnixExecutables.list ================================================ Cuberite Plugins Prefabs Protocol webadmin BACKERS brewing.txt crafting.txt furnace.txt items.ini monsters.ini buildinfo.txt README.txt favicon.png CONTRIBUTORS LICENSE ThirdPartyLicenses ================================================ FILE: Server/Install/WindowsExecutables.list ================================================ Cuberite.exe *.dll Plugins Prefabs Protocol webadmin BACKERS brewing.txt crafting.txt furnace.txt items.ini monsters.ini buildinfo.txt README.txt favicon.png CONTRIBUTORS LICENSE Cuberite*debug.cmd *.example.ini ThirdPartyLicenses ================================================ FILE: Server/Install/WindowsPDBs.list ================================================ *.pdb buildinfo.txt ================================================ FILE: Server/Plugins/.gitignore ================================================ /* !/APIDump !/Debuggers !/DumpInfo !/HookNotify !/NetworkTest !/TestLuaRocks ================================================ FILE: Server/Plugins/APIDump/APIDesc.lua ================================================ return { Classes = { --[[ -- What the APIDump plugin understands / how to document stuff: ExampleClassName = { Desc = "Description, exported as the first paragraph of the class page. Usually enclosed within double brackets." Functions = { FunctionName = { { Params = { { Name = "BuiltInType", Type = "number"}, { Name = "ClassEnum", Type = "cClass#eEnum"}, { Name = "GlobalEnum", Type = "eEnum"}, }, Returns = { { Type = "number" }, { Type = "self" }, -- Returns the same object on which it was called }, Notes = "Notes 1" }, { Params = {...}, Returns = {...}, Notes = "Notes 2", }, }, } , Constants = { ConstantName = { Notes = "Notes about the constant" }, } , ConstantGroups = { eEnum = -- also used as the HTML anchor name { Include = {"constant1", "constant2", "const_.*"}, -- Constants to include in this group, array of identifiers, accepts wildcards TextBefore = "This text will be written in front of the constant list", TextAfter = "This text will be written after the constant list", ShowInDescendants = false, -- If false, descendant classes won't list these constants } }, Variables = { VariableName = { Type = "string", Notes = "Notes about the variable" }, } , AdditionalInfo = -- Paragraphs to be exported after the function definitions table { { Header = "Header 1", Contents = "Contents of the additional section 1", }, { Header = "Header 2", Contents = "Contents of the additional section 2", } }, Inherits = "ParentClassName", -- Only present if the class inherits from another API class }, --]] cBlockInfo = { Desc = [[ This class is used to query block properties. ]], Functions = { CanBeTerraformed = { IsStatic = true, Params = { { Name = "BlockType", Type = "number", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if the block is suitable to be changed by a generator", }, FullyOccupiesVoxel = { IsStatic = true, Params = { { Name = "BlockType", Type = "number", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns whether the specified block fully occupies its voxel.", }, GetHardness = { IsStatic = true, Params = { { Name = "BlockType", Type = "number", }, }, Returns = { { Type = "number", }, }, Notes = "Returns the block's hardness. The bigger the harder the block.", }, GetBlockHeight = { IsStatic = true, Params = { { Name = "BlockType", Type = "number", }, }, Returns = { { Type = "number", }, }, Notes = "Returns the block's hitbox height.", }, GetLightValue = { IsStatic = true, Params = { { Name = "BlockType", Type = "number", }, }, Returns = { { Type = "number", }, }, Notes = "Returns how much light the specified block emits on its own.", }, GetPlaceSound = { IsStatic = true, Params = { { Name = "BlockType", Type = "number", }, }, Returns = { { Type = "string", }, }, Notes = "(DEPRECATED) Not used by cuberite internally and always returns an empty string.", }, GetSpreadLightFalloff = { IsStatic = true, Params = { { Name = "BlockType", Type = "number", }, }, Returns = { { Type = "number", }, }, Notes = "Returns how much light the specified block type consumes.", }, IsClickedThrough = { IsStatic = true, Params = { { Name = "BlockType", Type = "number", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if the specified block type is ignored by the client on left and right clicks, that is, treated as if it were air.", }, IsOneHitDig = { IsStatic = true, Params = { { Name = "BlockType", Type = "number", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if the specified block type will be destroyed after a single hit.", }, IsPistonBreakable = { IsStatic = true, Params = { { Name = "BlockType", Type = "number", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if a piston can break the specified block type.", }, IsRainBlocker = { IsStatic = true, Params = { { Name = "BlockType", Type = "number", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if the specified block type blocks rain from passing through.", }, IsSkylightDispersant = { IsStatic = true, Params = { { Name = "BlockType", Type = "number", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if skylight is impeded by passage through a block of the specified type.", }, IsSnowable = { IsStatic = true, Params = { { Name = "BlockType", Type = "number", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns whether the specified block type can hold snow atop.", }, IsSolid = { IsStatic = true, Params = { { Name = "BlockType", Type = "number", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns whether the specified block type is solid.", }, IsTransparent = { IsStatic = true, Params = { { Name = "BlockType", Type = "number", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns whether the specified block is transparent.", }, IsUseableBySpectator = { IsStatic = true, Params = { { Name = "BlockType", Type = "number", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns whether a spectator can interact with the specified block.", }, }, Variables = { m_BlockHeight = { Type = "number", Notes = "The height of the block, a value between 0.0 and 1.0. OBSOLETE, use cBlockInfo:GetBlockHeight() instead.", }, m_CanBeTerraformed = { Type = "bool", Notes = "Is this block suited to be terraformed? OBSOLETE, use cBlockInfo:CanBeTerraformed() instead.", }, m_FullyOccupiesVoxel = { Type = "bool", Notes = "Does this block fully occupy its voxel - is it a 'full' block? OBSOLETE, use cBlockInfo:FullyOccupiesVoxel() instead.", }, m_Hardness = { Type = "number", Notes = "The greater the value the longer the player needs to break the block. OBSOLETE, use cBlockInfo:GetHardness() instead.", }, m_IsSnowable = { Type = "bool", Notes = "Can this block hold snow atop? OBSOLETE, use cBlockInfo:IsSnowable() instead", }, m_IsSolid = { Type = "bool", Notes = "Is this block solid (player cannot walk through)? OBSOLETE, use cBlockInfo:IsSolid() instead.", }, m_LightValue = { Type = "number", Notes = "How much light do the blocks emit on their own? OBSOLETE, use cBlockInfo:GetLightValue() instead.", }, m_OneHitDig = { Type = "bool", Notes = "Is a block destroyed after a single hit? OBSOLETE, use cBlockInfo:IsOneHitDig() instead.", }, m_PistonBreakable = { Type = "bool", Notes = "Can a piston break this block? OBSOLETE, use cBlockInfo:IsPistonBreakable instead.", }, m_SpreadLightFalloff = { Type = "number", Notes = "How much light do the blocks consume? OBSOLETE, use cBlockInfo:GetSpreadLightFalloff() instead.", }, m_Transparent = { Type = "bool", Notes = "Is a block completely transparent? (light doesn't get decreased(?)). OBSOLETE, use cBlockInfo:IsTransparent() instead.", }, }, }, cChatColor = { Desc = [[ A wrapper class for constants representing colors or effects. ]], Functions = { }, Constants = { Black = { Notes = "", }, Blue = { Notes = "", }, Bold = { Notes = "", }, Color = { Notes = "The first character of the color-code-sequence, §", }, DarkPurple = { Notes = "", }, Delimiter = { Notes = "The first character of the color-code-sequence, §", }, Gold = { Notes = "", }, Gray = { Notes = "", }, Green = { Notes = "", }, Italic = { Notes = "", }, LightBlue = { Notes = "", }, LightGray = { Notes = "", }, LightGreen = { Notes = "", }, LightPurple = { Notes = "", }, Navy = { Notes = "", }, Plain = { Notes = "Resets all formatting to normal", }, Purple = { Notes = "", }, Random = { Notes = "Random letters and symbols animate instead of the text", }, Red = { Notes = "", }, Rose = { Notes = "", }, Strikethrough = { Notes = "", }, Underlined = { Notes = "", }, White = { Notes = "", }, Yellow = { Notes = "", }, }, }, cChunkDesc = { Desc = [[ The cChunkDesc class is a container for chunk data while the chunk is being generated. As such, it is only used as a parameter for the {{OnChunkGenerating|OnChunkGenerating}} and {{OnChunkGenerated|OnChunkGenerated}} hooks and cannot be constructed on its own. Plugins can use this class in both those hooks to manipulate generated chunks. Calls to any setter of this class will not trigger simulator updates (lava, water, redstone). ]], Functions = { FillBlocks = { Params = { { Name = "BlockType", Type = "number", }, { Name = "BlockMeta", Type = "number", }, }, Notes = "Fills the entire chunk with the specified blocks", }, FillRelCuboid = { { Params = { { Name = "RelCuboid", Type = "cCuboid", }, { Name = "BlockType", Type = "number", }, { Name = "BlockMeta", Type = "number", }, }, Notes = "Fills the cuboid, specified in relative coords, by the specified block type and block meta. The cuboid may reach outside of the chunk, only the part intersecting with this chunk is filled.", }, { Params = { { Name = "MinRelX", Type = "number", }, { Name = "MaxRelX", Type = "number", }, { Name = "MinRelY", Type = "number", }, { Name = "MaxRelY", Type = "number", }, { Name = "MinRelZ", Type = "number", }, { Name = "MaxRelZ", Type = "number", }, { Name = "BlockType", Type = "number", }, { Name = "BlockMeta", Type = "number", }, }, Notes = "Fills the cuboid, specified in relative coords, by the specified block type and block meta. The cuboid may reach outside of the chunk, only the part intersecting with this chunk is filled.", }, }, FloorRelCuboid = { { Params = { { Name = "RelCuboid", Type = "cCuboid", }, { Name = "BlockType", Type = "number", }, { Name = "BlockMeta", Type = "number", }, }, Notes = "Fills those blocks of the cuboid (specified in relative coords) that are considered non-floor (air, water) with the specified block type and meta. Cuboid may reach outside the chunk, only the part intersecting with this chunk is filled.", }, { Params = { { Name = "MinRelX", Type = "number", }, { Name = "MaxRelX", Type = "number", }, { Name = "MinRelY", Type = "number", }, { Name = "MaxRelY", Type = "number", }, { Name = "MinRelZ", Type = "number", }, { Name = "MaxRelZ", Type = "number", }, { Name = "BlockType", Type = "number", }, { Name = "BlockMeta", Type = "number", }, }, Notes = "Fills those blocks of the cuboid (specified in relative coords) that are considered non-floor (air, water) with the specified block type and meta. Cuboid may reach outside the chunk, only the part intersecting with this chunk is filled.", }, }, GetBiome = { Params = { { Name = "RelX", Type = "number", }, { Name = "RelZ", Type = "number", }, }, Returns = { { Type = "EMCSBiome", }, }, Notes = "Returns the biome at the specified relative coords", }, GetBlockEntity = { Params = { { Name = "RelX", Type = "number", }, { Name = "RelY", Type = "number", }, { Name = "RelZ", Type = "number", }, }, Returns = { { Type = "cBlockEntity", }, }, Notes = "Returns the block entity for the block at the specified coords. Creates it if it doesn't exist. Returns nil if the block has no block entity capability.", }, GetBlockMeta = { Params = { { Name = "RelX", Type = "number", }, { Name = "RelY", Type = "number", }, { Name = "RelZ", Type = "number", }, }, Returns = { { Name = "NIBBLETYPE", Type = "number", }, }, Notes = "Returns the block meta at the specified relative coords", }, GetBlockType = { Params = { { Name = "RelX", Type = "number", }, { Name = "RelY", Type = "number", }, { Name = "RelZ", Type = "number", }, }, Returns = { { Name = "BLOCKTYPE", Type = "number", }, }, Notes = "Returns the block type at the specified relative coords", }, GetBlockTypeMeta = { Params = { { Name = "RelX", Type = "number", }, { Name = "RelY", Type = "number", }, { Name = "RelZ", Type = "number", }, }, Returns = { { Name = "BLOCKTYPE", Type = "number", }, { Name = "NIBBLETYPE", Type = "number", }, }, Notes = "Returns the block type and meta at the specified relative coords", }, GetChunkX = { Returns = { { Type = "number", }, }, Notes = "Returns the X coord of the chunk contained.", }, GetChunkZ = { Returns = { { Type = "number", }, }, Notes = "Returns the Z coord of the chunk contained.", }, GetHeight = { Params = { { Name = "RelX", Type = "number", }, { Name = "RelZ", Type = "number", }, }, Returns = { { Type = "number", }, }, Notes = "Returns the height at the specified relative coords", }, GetMaxHeight = { Returns = { { Type = "number", }, }, Notes = "Returns the maximum height contained in the heightmap.", }, GetMinHeight = { Returns = { { Type = "number", }, }, Notes = "Returns the minimum height value in the heightmap.", }, IsUsingDefaultBiomes = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the chunk is set to use default biome generator", }, IsUsingDefaultComposition = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the chunk is set to use default composition generator", }, IsUsingDefaultFinish = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the chunk is set to use default finishers", }, IsUsingDefaultHeight = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the chunk is set to use default height generator", }, RandomFillRelCuboid = { { Params = { { Name = "RelCuboid", Type = "cCuboid", }, { Name = "BlockType", Type = "number", }, { Name = "BlockMeta", Type = "number", }, { Name = "RandomSeed", Type = "number", }, { Name = "ChanceOutOf10k", Type = "number", }, }, Notes = "Fills the specified relative cuboid with block type and meta in random locations. RandomSeed is used for the random number genertion (same seed produces same results); ChanceOutOf10k specifies the density (how many out of every 10000 blocks should be filled). Cuboid may reach outside the chunk, only the part intersecting with this chunk is filled.", }, { Params = { { Name = "MinRelX", Type = "number", }, { Name = "ChanceOutOf10k", Type = "number", }, { Name = "MaxRelX", Type = "number", }, { Name = "MinRelY", Type = "number", }, { Name = "MaxRelY", Type = "number", }, { Name = "MinRelZ", Type = "number", }, { Name = "MaxRelZ", Type = "number", }, { Name = "BlockType", Type = "number", }, { Name = "BlockMeta", Type = "number", }, { Name = "RandomSeed", Type = "number", }, }, Notes = "Fills the specified relative cuboid with block type and meta in random locations. RandomSeed is used for the random number genertion (same seed produces same results); ChanceOutOf10k specifies the density (how many out of every 10000 blocks should be filled). Cuboid may reach outside the chunk, only the part intersecting with this chunk is filled.", }, }, ReadBlockArea = { Params = { { Name = "BlockArea", Type = "cBlockArea", }, { Name = "MinRelX", Type = "number", }, { Name = "MaxRelX", Type = "number", }, { Name = "MinRelY", Type = "number", }, { Name = "MaxRelY", Type = "number", }, { Name = "MinRelZ", Type = "number", }, { Name = "MaxRelZ", Type = "number", }, }, Notes = "Reads data from the chunk into the block area object. Block types and metas are processed.", }, ReplaceRelCuboid = { { Params = { { Name = "RelCuboid", Type = "cCuboid", }, { Name = "SrcBlockType", Type = "number", }, { Name = "SrcBlockMeta", Type = "number", }, { Name = "DstBlockType", Type = "number", }, { Name = "DstBlockMeta", Type = "number", }, }, Notes = "Replaces all SrcBlockType + SrcBlockMeta blocks in the cuboid (specified in relative coords) with DstBlockType + DstBlockMeta blocks. Cuboid may reach outside the chunk, only the part intersecting with this chunk is filled.", }, { Params = { { Name = "MinRelX", Type = "number", }, { Name = "MaxRelX", Type = "number", }, { Name = "MinRelY", Type = "number", }, { Name = "MaxRelY", Type = "number", }, { Name = "MinRelZ", Type = "number", }, { Name = "MaxRelZ", Type = "number", }, { Name = "SrcBlockType", Type = "number", }, { Name = "SrcBlockMeta", Type = "number", }, { Name = "DstBlockType", Type = "number", }, { Name = "DstBlockMeta", Type = "number", }, }, Notes = "Replaces all SrcBlockType + SrcBlockMeta blocks in the cuboid (specified in relative coords) with DstBlockType + DstBlockMeta blocks. Cuboid may reach outside the chunk, only the part intersecting with this chunk is filled.", }, }, SetBiome = { Params = { { Name = "RelX", Type = "number", }, { Name = "RelZ", Type = "number", }, { Name = "Biome", Type = "EMCSBiome", }, }, Notes = "Sets the biome at the specified relative coords.", }, SetBlockMeta = { Params = { { Name = "RelX", Type = "number", }, { Name = "RelY", Type = "number", }, { Name = "RelZ", Type = "number", }, { Name = "BlockMeta", Type = "number", }, }, Notes = "Sets the block meta at the specified relative coords.", }, SetBlockType = { Params = { { Name = "RelX", Type = "number", }, { Name = "RelY", Type = "number", }, { Name = "RelZ", Type = "number", }, { Name = "BlockType", Type = "number", }, }, Notes = "Sets the block type at the specified relative coords", }, SetBlockTypeMeta = { Params = { { Name = "RelX", Type = "number", }, { Name = "RelY", Type = "number", }, { Name = "RelZ", Type = "number", }, { Name = "BlockType", Type = "number", }, { Name = "BlockMeta", Type = "number", }, }, Notes = "Sets the block type and meta at the specified relative coords", }, SetHeight = { Params = { { Name = "RelX", Type = "number", }, { Name = "RelZ", Type = "number", }, { Name = "Height", Type = "number", }, }, Notes = "Sets the height at the specified relative coords", }, SetUseDefaultBiomes = { Params = { { Name = "ShouldUseDefaultBiomes", Type = "boolean", }, }, Notes = "Sets the chunk to use default biome generator or not", }, SetUseDefaultComposition = { Params = { { Name = "ShouldUseDefaultComposition", Type = "boolean", }, }, Notes = "Sets the chunk to use default composition generator or not", }, SetUseDefaultFinish = { Params = { { Name = "ShouldUseDefaultFinish", Type = "boolean", }, }, Notes = "Sets the chunk to use default finishers or not", }, SetUseDefaultHeight = { Params = { { Name = "ShouldUseDefaultHeight", Type = "boolean", }, }, Notes = "Sets the chunk to use default height generator or not", }, UpdateHeightmap = { Notes = "Updates the heightmap to match current contents. The plugins should do that if they modify the contents and don't modify the heightmap accordingly; Cuberite expects (and checks in Debug mode) that the heightmap matches the contents when the cChunkDesc is returned from a plugin.", }, WriteBlockArea = { Params = { { Name = "BlockArea", Type = "cBlockArea", }, { Name = "MinRelX", Type = "number", }, { Name = "MinRelY", Type = "number", }, { Name = "MinRelZ", Type = "number", }, { Name = "MergeStrategy", Type = "cBlockArea", IsOptional = true, }, }, Notes = "Writes data from the block area into the chunk", }, }, AdditionalInfo = { { Header = "Manipulating block entities", Contents = [[ To manipulate block entities while the chunk is generated, first use SetBlockTypeMeta() to set the correct block type and meta at the position. Then use the GetBlockEntity() to create and return the correct block entity instance. Finally, use {{tolua}}.cast() to cast to the proper type.

Note that you don't need to check if a block entity has previously existed at the place, because GetBlockEntity() will automatically re-create the correct type for you.

The following code is taken from the Debuggers plugin, it creates a sign at each chunk's [0, 0] coords, with the text being the chunk coords:

function OnChunkGenerated(a_World, a_ChunkX, a_ChunkZ, a_ChunkDesc)
	-- Get the topmost block coord:
	local Height = a_ChunkDesc:GetHeight(0, 0);

	-- Create a sign there:
	a_ChunkDesc:SetBlockTypeMeta(0, Height + 1, 0, E_BLOCK_SIGN_POST, 0);
	local BlockEntity = a_ChunkDesc:GetBlockEntity(0, Height + 1, 0);
	if (BlockEntity ~= nil) then
		LOG("Setting sign lines...");
		local SignEntity = tolua.cast(BlockEntity, "cSignEntity");
		SignEntity:SetLines("Chunk:", tonumber(a_ChunkX) .. ", " .. tonumber(a_ChunkZ), "", "(Debuggers)");
	end

	-- Update the heightmap:
	a_ChunkDesc:SetHeight(0, 0, Height + 1);
end
]], }, }, }, cClientHandle = { Desc = [[ A cClientHandle represents the technical aspect of a connected player - their game client connection. Internally, it handles all the incoming and outgoing packets, the chunks that are to be sent to the client, ping times etc. ]], Functions = { GenerateOfflineUUID = { IsStatic = true, Params = { { Name = "Username", Type = "string", }, }, Returns = { { Type = "string", }, }, Notes = "Generates an UUID based on the player name provided. This is used for the offline (non-auth) mode, when there's no UUID source. Each username generates a unique and constant UUID, so that when the player reconnects with the same name, their UUID is the same. Returns a 32-char UUID (no dashes).", }, GetClientBrand = { Returns = { { Type = "string", }, }, Notes = "Returns the brand that the client has sent in their MC|Brand plugin message.", }, GetForgeMods = { Returns = { { Type = "table", }, }, Notes = "Returns the Forge mods installed on the client.", }, GetIPString = { Returns = { { Type = "string", }, }, Notes = "Returns the IP address of the connection, as a string. Only the address part is returned, without the port number.", }, GetLocale = { Returns = { { Name = "Locale", Type = "string", }, }, Notes = "Returns the locale string that the client sends as part of the protocol handshake. Can be used to provide localized strings.", }, GetPing = { Returns = { { Type = "number", }, }, Notes = "Returns the ping time, in ms", }, GetPlayer = { Returns = { { Type = "cPlayer", }, }, Notes = "Returns the player object connected to this client. Note that this may be nil, for example if the player object is not yet spawned.", }, GetProtocolVersion = { Returns = { { Type = "number", }, }, Notes = "Returns the protocol version number of the protocol that the client is talking. Returns zero if the protocol version is not (yet) known.", }, GetRequestedViewDistance = { Returns = { { Type = "number", }, }, Notes = "Returns the view distance that the player request, not the used view distance.", }, GetUniqueID = { Returns = { { Type = "number", }, }, Notes = "Returns the UniqueID of the client used to identify the client in the server", }, GetUsername = { Returns = { { Type = "string", }, }, Notes = "Returns the username that the client has provided", }, GetUUID = { Returns = { { Type = "string", }, }, Notes = "Returns the authentication-based UUID of the client. This UUID should be used to identify the player when persisting any player-related data. Returns a 32-char UUID (no dashes)", }, GetViewDistance = { Returns = { { Type = "number", }, }, Notes = "Returns the viewdistance (number of chunks loaded for the player in each direction)", }, HasPluginChannel = { Params = { { Name = "ChannelName", Type = "string", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if the client has registered to receive messages on the specified plugin channel.", }, IsForgeClient = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the client is modded with Forge.", }, IsUUIDOnline = { IsStatic = true, Params = { { Name = "UUID", Type = "cUUID", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if the UUID is generated by online auth, false if it is an offline-generated UUID. We use Version-3 UUIDs for offline UUIDs, online UUIDs are Version-4, thus we can tell them apart. Accepts both 32-char and 36-char UUIDs (with and without dashes).", }, Kick = { Params = { { Name = "Reason", Type = "string", }, }, Notes = "Kicks the user with the specified reason", }, SendBlockBreakAnim = { Params = { { Name = "EntityID", Type = "number", }, { Name = "BlockX", Type = "number", }, { Name = "BlockY", Type = "number", }, { Name = "BlockZ", Type = "number", }, { Name = "Stage", Type = "number", }, }, Notes = "Sends a BlockBreakAnim packet to the client. Only one block can be broken at a time with the same UUID (the other will be reset). You can counter this using random values. The breaking stage ranges between 0 (first stage) and 9 (almost destroyed). Use -1 to reset the destruction.", }, SendBlockChange = { Params = { { Name = "BlockX", Type = "number", }, { Name = "BlockY", Type = "number", }, { Name = "BlockZ", Type = "number", }, { Name = "BlockType", Type = "number", }, { Name = "BlockMeta", Type = "number", }, }, Notes = "Sends a BlockChange packet to the client. This can be used to create fake blocks only for that player.", }, SendBossBarAdd = { Params = { { Name = "UniqueID", Type = "number", }, { Name = "Title", Type = "cCompositeChat", }, { Name = "FractionFilled", Type = "number", }, { Name = "Colour", Type = "BossBarColor", }, { Name = "DivisionType", Type = "BossBarDivisionType", }, { Name = "DarkenSky", Type = "boolean", }, { Name = "PlayEndMusic", Type = "boolean", }, { Name = "CreateFog", Type = "boolean", }, }, Notes = "Creates a boss bar on the client's UI. The boss bar is independent of any entity and has a lifetime and properties fully controlled by the plugin. Plugins are responsible for assigning a unique ID and removal.", }, SendBossBarUpdateFlags = { Params = { { Name = "UniqueID", Type = "number", }, { Name = "DarkenSky", Type = "boolean", }, { Name = "PlayEndMusic", Type = "boolean", }, { Name = "CreateFog", Type = "boolean", }, }, Notes = "Updates a boss bar on the client's UI. Only updates some meta flags for additional effects.", }, SendBossBarUpdateStyle = { Params = { { Name = "UniqueID", Type = "number", }, { Name = "Color", Type = "BossBarColor", }, { Name = "DivisionType", Type = "BossBarDivisionType", }, }, Notes = "Updates a boss bar on the client's UI. Only updates the visuals of the Boss Bar.", }, SendBossBarUpdateTitle = { Params = { { Name = "UniqueID", Type = "number", }, { Name = "Title", Type = "cCompositeChat", }, }, Notes = "Updates a boss bar on the client's UI. Only Updates the text at the top.", }, SendBossBarRemove = { Params = { { Name = "UniqueID", Type = "number", }, }, Notes = "Removes the boss bar with the given ID from the client's UI.", }, SendBossBarUpdateHealth = { Params = { { Name = "UniqueID", Type = "number", }, { Name = "FractionFilled", Type = "number", }, }, Notes = "Updates the health displayed by the boss bar with the given ID.", }, SendCollectEntity = { Params = { { Name = "Entity", Type = "cEntity", }, { Name = "Collector", Type = "cEntity", }, }, Notes = "Sends the CollectEntity packet to the client. This fakes item collecting.", }, SendDestroyEntity = { Params = { { Name = "Entity", Type = "cEntity", }, }, Notes = "Sends the DestroyEntity packet to the client. This tells the client to remove the entity from the world.", }, SendDetachEntity = { Params = { { Name = "Entity", Type = "cEntity", }, }, Notes = "Sends the DetachEntity packet to the client. This drop entities riding another one (boat, minecarts, pigs, horses...).", }, SendEditSign = { Params = { { Name = "BlockX", Type = "number", }, { Name = "BlockY", Type = "number", }, { Name = "BlockZ", Type = "number", }, }, Notes = "Sends the EditSign packet to the client. This opens the sign editor GUI.", }, SendEntityAnimation = { Params = { { Name = "Entity", Type = "cEntity", }, { Name = "AnimationNumber", Type = "number", }, }, Notes = "Sends the specified animation of the specified entity to the client. The AnimationNumber is protocol-specific.", }, SendPlayerListHeaderFooter = { Params = { { Type = "cCompositeChat", Name = "Header", }, { Type = "cCompositeChat", Name = "Footer", }, }, Desc = "Sends the header and footer of the player list to the client.", }, SendHideTitle = { Notes = "Hides the title. This makes the title and subtitle disappear, but if you call SendTitleTimes() the same title and subtitle will appear again." }, SendLeashEntity = { Params = { { Name = "Entity", Type = "cEntity", }, { Name = "EntityLeashedTo", Type = "cEntity", }, }, Notes = "Sends the LeashEntity packet to the client. Leashes entities together. Leashing to the player, the leash will appear on the player's hand", }, SendPluginMessage = { Params = { { Name = "Channel", Type = "string", }, { Name = "Message", Type = "string", }, }, Notes = "Sends the plugin message on the specified channel.", }, SendResetTitle = { Notes = "Resets and hides the title but not the subtitle." }, SendResourcePack = { Params = { { Name = "ResourcePackURL", Type = "string", }, }, Notes = "Sends the ResourcePack packet to the client. The client will request the resource pack from the given URL. If the url is blank, the resource pack will be reset.", }, SendSetSubTitle = { Params = { { Name = "SubTitle", Type = "cCompositeChat", }, }, Notes = "Sends the subtitle to the client. Doesn't make the client display it yet, use SendTitleTimes() to show both the title and the subtitle." }, SendSetRawSubTitle = { Params = { { Name = "SubTitle", Type = "string", }, }, Notes = "Sends the raw subtitle to the client. Doesn't make the client display it yet, use SendTitleTimes() to show both the title and the subtitle." }, SendSetTitle = { Params = { { Name = "Title", Type = "cCompositeChat", }, }, Notes = "Sends the title to the client. Doesn't make the client display it yet, use SendTitleTimes() to show both the title and the subtitle." }, SendSetRawTitle = { Params = { { Name = "Title", Type = "string", }, }, Notes = "Sends the raw title to the client. Doesn't make the client display it yet, use SendTitleTimes() to show both the title and the subtitle." }, SendSoundEffect = { Params = { { Name = "SoundName", Type = "string", }, { Name = "Position", Type = "Vector3d", }, { Name = "Volume", Type = "number", }, { Name = "Pitch", Type = "number", }, }, Notes = "Sends a sound effect request to the client. The sound is played at the specified coords, with the specified volume (a float, 1.0 is full volume, can be more) and pitch (0-255, 63 is 100%)", }, SendSoundEffect = { Params = { { Name = "SoundName", Type = "string", }, { Name = "X", Type = "number", }, { Name = "Y", Type = "number", }, { Name = "Z", Type = "number", }, { Name = "Volume", Type = "number", }, { Name = "Pitch", Type = "number", }, }, Notes = "Sends a sound effect request to the client. The sound is played at the specified coords, with the specified volume (a float, 1.0 is full volume, can be more) and pitch (0-255, 63 is 100%) (DEPRECATED, use vector-parametered version instead)", }, SendThunderbolt = { Params = { { Name = "BlockX", Type = "number", }, { Name = "BlockY", Type = "number", }, { Name = "BlockZ", Type = "number", }, }, Notes = "Sends the thunderbolt at the specified coords to the client. The client will display the effect without any sound.", }, SendTitleTimes = { Params = { { Name = "FadeInTicks", Type = "number", }, { Name = "DisplayTicks", Type = "number", }, { Name = "FadeOutTicks", Type = "number", }, }, Notes = "Sends the request to display the title and subtitle, previously set with SendSetTitle, SendSetRawTitle, SendSetSubTitle and SendSetRawSubTitle, to the client." }, SendTimeUpdate = { Params = { { Name = "WorldAge", Type = "number", }, { Name = "WorldDate", Type = "number", }, { Name = "DoDaylightCycle", Type = "boolean", }, }, Notes = "Sends the specified time update to the client. WorldAge is the total age of the world, in ticks. WorldDate is the current date, in ticks, and is used by the client to calculate the days elapsed (F3 debug overlay's day count) and the time of day (rendered sun position). DoDaylightCycle is a bool that specifies whether the client should automatically move the sun (true) or keep it in the same place (false).", }, SendUnleashEntity = { Params = { { Name = "EntityID", Type = "number", }, }, Notes = "Sends the UnleashEntity packet to the client. The client will remove any leashes related to the entity.", }, SetClientBrand = { Params = { { Name = "ClientBrand", Type = "string", }, }, Notes = "Sets the value of the client's brand. Normally this value is received from the client by a MC|Brand plugin message, this function lets plugins overwrite the value.", }, SetLocale = { Params = { { Name = "Locale", Type = "string", }, }, Notes = "Sets the locale that Cuberite keeps on record. Initially the locale is initialized in protocol handshake, this function allows plugins to override the stored value (but only server-side and only until the user disconnects).", }, SetViewDistance = { Params = { { Name = "ViewDistance", Type = "number", }, }, Notes = "Sets the viewdistance (number of chunks loaded for the player in each direction)", }, }, Constants = { MAX_VIEW_DISTANCE = { Notes = "The maximum value of the view distance", }, MIN_VIEW_DISTANCE = { Notes = "The minimum value of the view distance", }, }, }, cColor = { Desc = [[ Encapsulates a RGB color, e.g. for armor. ]], Functions = { Clear = { Notes = "Resets the color to uninitialized." }, constructor = { { Returns = { {Type="cColor"} }, Notes = "Creates an uninitialized cColor. Each component must be between 0 and 255, inclusive.", }, { Params = { { Name = "Red", Type = "number", }, { Name = "Green", Type = "number", }, { Name = "Blue", Type = "number", }, }, Returns = { {Type="cColor"} }, Notes = "Creates the specified cColor. All components must be between 0 and 255, inclusive.", }, }, GetColor = { Returns = { { Name = "Red", Type = "number", }, { Name = "Green", Type = "number", }, { Name = "Blue", Type = "number", }, }, Notes = "Returns the color's red, green, and blue components, respectively." }, GetRed = { Returns = { { Name = "Red", Type = "number", }, }, Notes = "Returns the color's red component." }, GetGreen = { Returns = { { Name = "Green", Type = "number", }, }, Notes = "Returns the color's green component." }, GetBlue = { Returns = { { Name = "Blue", Type = "number", }, }, Notes = "Returns the color's blue component." }, IsValid = { Returns = { { Type = "boolean" }, }, Notes = "True if the color is valid, false if the color has not been set yet." }, SetColor = { Params = { { Name = "Red", Type = "number" }, { Name = "Green", Type = "number" }, { Name = "Blue", Type = "number" }, }, Notes = "Sets the color's red, green, and blue components. Values range from 0 to 255." }, SetRed = { Params = { { Name = "Red", Type = "number", }, }, Notes = "Sets the color's red component. Must be between 0 and 255, inclusive." }, SetGreen = { Params = { { Name = "Green", Type = "number", }, }, Notes = "Sets the color's green component. Must be between 0 and 255, inclusive." }, SetBlue = { Params = { { Name = "Blue", Type = "number", }, }, Notes = "Sets the color's blue component. Must be between 0 and 255, inclusive." }, }, Constants = { COLOR_LIMIT = { Notes = "The upper bound (exclusive) for a color component", }, COLOR_MAX = { Notes = "The maximum value for a color component", }, COLOR_MIN = { Notes = "The minimum value for a color component", }, COLOR_NONE = { Notes = "A constant denoting the color is invalid (note: use IsValid)", }, }, }, cCompositeChat = { Desc = [[ Encapsulates a chat message that can contain various formatting, URLs, commands executed on click and commands suggested on click. The chat message can be sent by the regular chat-sending functions, {{cPlayer}}:SendMessage(), {{cWorld}}:BroadcastChat() and {{cRoot}}:BroadcastChat().

Note that most of the functions in this class are so-called chaining modifiers - they modify the object and then return the object itself, so that they can be chained one after another. See the Chaining example below for details.

Each part of the composite chat message takes a "Style" parameter, this is a string that describes the formatting. It uses the "standard" minecraft format code without the '&' symbole, concatenated together:
StringStyle
lBold text
oItalic text
nUnderlined text
mStrikethrough text
kObfuscated text
rReset Style
[0-9a-f]colors
You can escape the '&' character with an antislash in front of it. as follow: `I love Choco\&chips` The following picture, taken from the Minecraft Wiki, illustrates the color codes:

]], Functions = { AddRunCommandPart = { Params = { { Name = "Text", Type = "string", }, { Name = "Command", Type = "string", }, { Name = "Style", Type = "string", IsOptional = true, }, }, Returns = { { Type = "self", }, }, Notes = "Adds a text which, when clicked, runs the specified command. Chaining.", }, AddShowAchievementPart = { Params = { { Name = "PlayerName", Type = "string", }, { Name = "AchievementName", Type = "string", }, { Name = "Style", Type = "string", IsOptional = true, }, }, Notes = "Adds a text that represents the 'Achievement get' message.", }, AddSuggestCommandPart = { Params = { { Name = "Text", Type = "string", }, { Name = "Command", Type = "string", }, { Name = "Style", Type = "string", IsOptional = true, }, }, Returns = { { Type = "self", }, }, Notes = "Adds a text which, when clicked, puts the specified command into the player's chat input area. Chaining.", }, AddTextPart = { Params = { { Name = "Text", Type = "string", }, { Name = "Style", Type = "string", IsOptional = true, }, }, Returns = { { Type = "self", }, }, Notes = "Adds a regular text. Chaining.", }, AddUrlPart = { Params = { { Name = "Text", Type = "string", }, { Name = "Url", Type = "string", }, { Name = "Style", Type = "string", IsOptional = true, }, }, Returns = { { Type = "self", }, }, Notes = "Adds a text which, when clicked, opens up a browser at the specified URL. Chaining.", }, Clear = { Returns = { { Type = "self", }, }, Notes = "Removes all parts from this object", }, constructor = { { Returns = { {Type = "cCompositeChat"} }, Notes = "Creates an empty chat message", }, { Params = { { Name = "Text", Type = "string", }, { Name = "MessageType", Type = "eMessageType", IsOptional = true, }, }, Returns = { {Type = "cCompositeChat"} }, Notes = "Creates a chat message containing the specified text, parsed by the ParseText() function. This allows easy migration from old chat messages.", }, }, CreateJsonString = { Params = { { Name = "AddPrefixes", Type = "boolean", IsOptional = true, }, }, Returns = { { Type = "string", }, }, Notes = "Returns the entire object serialized into JSON, as it would be sent to a client. AddPrefixes specifies whether the chat prefixes should be prepended to the message, true by default.", }, ExtractText = { Returns = { { Type = "string", }, }, Notes = "Returns the text from the parts that comprises the human-readable data. Used for older protocols that don't support composite chat, and for console-logging.", }, GetAdditionalMessageTypeData = { Returns = { { Type = "string", }, }, Notes = "Returns the AdditionalData associated with the message, such as the sender's name for mtPrivateMessage", }, GetMessageType = { Returns = { { Type = "eMessageType", }, }, Notes = "Returns the MessageType (mtXXX constant) that is associated with this message. When sent to a player, the message will be formatted according to this message type and the player's settings (adding \"[INFO]\" prefix etc.)", }, ParseText = { Params = { { Name = "Text", Type = "string", }, }, Returns = { { Type = "self", }, }, Notes = "Adds text, while recognizing http and https URLs and old-style formatting codes (\"@2\"). Chaining.", }, SetMessageType = { Params = { { Name = "MessageType", Type = "eMessageType", }, { Name = "AdditionalData", Type = "string", IsOptional = true, }, }, Returns = { { Type = "self", }, }, Notes = "Sets the MessageType (mtXXX constant) that is associated with this message. Also sets the additional data (string) associated with the message, which is specific for the message type - such as the sender's name for mtPrivateMessage. When sent to a player, the message will be formatted according to this message type and the player's settings (adding \"[INFO]\" prefix etc.). Chaining.", }, UnderlineUrls = { Returns = { { Type = "self", }, }, Notes = "Makes all URL parts contained in the message underlined. Doesn't affect parts added in the future. Chaining.", }, }, AdditionalInfo = { { Header = "Chaining example", Contents = [[ Sending a chat message that is composed of multiple different parts has been made easy thanks to chaining. Consider the following example that shows how a message containing all kinds of parts is sent (adapted from the Debuggers plugin):
function OnPlayerJoined(a_Player)
	-- Send an example composite chat message to the player:
	a_Player:SendMessage(cCompositeChat()
		:AddTextPart("Hello, ")
		:AddUrlPart(a_Player:GetName(), "https://cuberite.org", "u@2")  -- Colored underlined link
		:AddSuggestCommandPart(", and welcome.", "/help", "u")       -- Underlined suggest-command
		:AddRunCommandPart(" SetDay", "/time set 0")                 -- Regular text that will execute command when clicked
		:SetMessageType(mtJoin)                                      -- It is a join-message
	)
end
]], }, }, }, cCraftingGrid = { Desc = [[ cCraftingGrid represents the player's crafting grid. It is used in {{OnCraftingNoRecipe|OnCraftingNoRecipe}}, {{OnPostCrafting|OnPostCrafting}} and {{OnPreCrafting|OnPreCrafting}} hooks. Plugins may use it to inspect the items the player placed on their crafting grid.

Also, an object of this type is used in {{cCraftingRecipe}}'s ConsumeIngredients() function for specifying the exact number of ingredients to consume in that recipe; plugins may use this to apply the crafting recipe.

]], Functions = { Clear = { Notes = "Clears the entire grid", }, constructor = { Params = { { Name = "Width", Type = "number", }, { Name = "Height", Type = "number", }, }, Returns = { { Type = "cCraftingGrid", }, }, Notes = "Creates a new CraftingGrid object. This new crafting grid is not related to any player, but may be needed for {{cCraftingRecipe}}'s ConsumeIngredients function.", }, ConsumeGrid = { Params = { { Name = "CraftingGrid", Type = "cCraftingGrid", }, }, Notes = "Consumes items specified in CraftingGrid from the current contents. Used internally by {{cCraftingRecipe}}'s ConsumeIngredients() function, but available to plugins, too.", }, Dump = { Notes = "DEBUG build: Dumps the contents of the grid to the log. RELEASE build: no action", }, GetHeight = { Returns = { { Type = "number", }, }, Notes = "Returns the height of the grid", }, GetItem = { Params = { { Name = "x", Type = "number", }, { Name = "y", Type = "number", }, }, Returns = { { Type = "cItem", }, }, Notes = "Returns the item at the specified coords", }, GetWidth = { Returns = { { Type = "number", }, }, Notes = "Returns the width of the grid", }, SetItem = { { Params = { { Name = "x", Type = "number", }, { Name = "y", Type = "number", }, { Name = "cItem", Type = "cItem", }, }, Notes = "Sets the item at the specified coords", }, { Params = { { Name = "x", Type = "number", }, { Name = "y", Type = "number", }, { Name = "ItemType", Type = "number", }, { Name = "ItemCount", Type = "number", }, { Name = "ItemDamage", Type = "number", }, }, Notes = "Sets the item at the specified coords", }, }, }, }, cCraftingRecipe = { Desc = [[ This class is used to represent a crafting recipe, either a built-in one, or one created dynamically in a plugin. It is used only as a parameter for {{OnCraftingNoRecipe|OnCraftingNoRecipe}}, {{OnPostCrafting|OnPostCrafting}} and {{OnPreCrafting|OnPreCrafting}} hooks. Plugins may use it to inspect or modify a crafting recipe that a player views in their crafting window, either at a crafting table or the survival inventory screen.

Internally, the class contains a {{cCraftingGrid}} for the ingredients and a {{cItem}} for the result. ]], Functions = { Clear = { Notes = "Clears the entire recipe, both ingredients and results", }, ConsumeIngredients = { Params = { { Name = "CraftingGrid", Type = "cCraftingGrid", }, }, Notes = "Consumes ingredients specified in the given {{cCraftingGrid|cCraftingGrid}} class", }, Dump = { Notes = "DEBUG build: dumps ingredients and result into server log. RELEASE build: no action", }, GetIngredient = { Params = { { Name = "x", Type = "number", }, { Name = "y", Type = "number", }, }, Returns = { { Type = "cItem", }, }, Notes = "Returns the ingredient stored in the recipe at the specified coords", }, GetIngredientsHeight = { Returns = { { Type = "number", }, }, Notes = "Returns the height of the ingredients' grid", }, GetIngredientsWidth = { Returns = { { Type = "number", }, }, Notes = "Returns the width of the ingredients' grid", }, GetResult = { Returns = { { Type = "cItem", }, }, Notes = "Returns the result of the recipe", }, SetIngredient = { { Params = { { Name = "x", Type = "number", }, { Name = "y", Type = "number", }, { Name = "cItem", Type = "cItem", }, }, Notes = "Sets the ingredient at the specified coords", }, { Params = { { Name = "x", Type = "number", }, { Name = "y", Type = "number", }, { Name = "ItemType", Type = "number", }, { Name = "ItemCount", Type = "number", }, { Name = "ItemDamage", Type = "number", }, }, Notes = "Sets the ingredient at the specified coords", }, }, SetResult = { { Params = { { Name = "cItem", Type = "cItem", }, }, Notes = "Sets the result item", }, { Params = { { Name = "ItemType", Type = "number", }, { Name = "ItemCount", Type = "number", }, { Name = "ItemDamage", Type = "number", }, }, Notes = "Sets the result item", }, }, }, }, cCryptoHash = { Desc = [[ Provides functions for generating cryptographic hashes.

Note that all functions in this class are super-static, so they are to be called in the dot convention:

local Hash = cCryptoHash.sha1HexString("DataToHash")

Each cryptographic hash has two variants, one returns the hash as a raw binary string, the other returns the hash as a hex-encoded string twice as long as the binary string. ]], Functions = { md5 = { IsStatic = true, IsGlobal = true, Params = { { Name = "Data", Type = "string", }, }, Returns = { { Type = "string", }, }, Notes = "Calculates the md5 hash of the data, returns it as a raw (binary) string of 16 characters.", }, md5HexString = { IsStatic = true, IsGlobal = true, Params = { { Name = "Data", Type = "string", }, }, Returns = { { Type = "string", }, }, Notes = "Calculates the md5 hash of the data, returns it as a hex-encoded string of 32 characters.", }, sha1 = { IsStatic = true, IsGlobal = true, Params = { { Name = "Data", Type = "string", }, }, Returns = { { Type = "string", }, }, Notes = "Calculates the sha1 hash of the data, returns it as a raw (binary) string of 20 characters.", }, sha1HexString = { IsStatic = true, IsGlobal = true, Params = { { Name = "Data", Type = "string", }, }, Returns = { { Type = "string", }, }, Notes = "Calculates the sha1 hash of the data, returns it as a hex-encoded string of 40 characters.", }, }, }, cEnchantments = { Desc = [[ This class is the storage for enchantments for a single {{cItem|cItem}} object, through its m_Enchantments member variable. Although it is possible to create a standalone object of this class, it is not yet used in any API directly.

Enchantments can be initialized either programmatically by calling the individual functions (SetLevel()), or by using a string description of the enchantment combination. This string description is in the form "id=lvl;id=lvl;...;id=lvl;", where id is either a numerical ID of the enchantment, or its textual representation from the table below, and lvl is the desired enchantment level. The class can also create its string description from its current contents; however that string description will only have the numerical IDs.

See the {{cItem}} class for usage examples. ]], Functions = { Add = { Params = { { Name = "Other", Type = "cEnchantments", }, }, Notes = "Adds the enchantments contained in Other into this object. Existing enchantments are preserved, unless Other specifies a different level, in which case the level is changed to the Other's one.", }, AddFromString = { Params = { { Name = "StringSpec", Type = "string", }, }, Notes = "Adds the enchantments in the string description into the object. If a specified enchantment already existed, it is overwritten.", }, Clear = { Notes = "Removes all enchantments", }, constructor = { { Returns = { { Type = "cEnchantments", }, }, Notes = "Creates a new empty cEnchantments object", }, { Params = { { Name = "StringSpec", Type = "string", }, }, Returns = { { Type = "cEnchantments", }, }, Notes = "Creates a new cEnchantments object filled with enchantments based on the string description", }, }, Count = { Returns = { { Type = "number", }, }, Notes = "Get the count of enchantments contained within the class", }, GetLevel = { Params = { { Name = "EnchantmentNumID", Type = "number", }, }, Returns = { { Type = "number", }, }, Notes = "Returns the level of the specified enchantment stored in this object; 0 if not stored", }, CanAddEnchantment = { Params = { { Name = "EnchantmentNumID", Type = "number", }, }, Returns = { { Type = "boolean" }, }, Notes = "Returns true if the specified enchantment is not mutually exclusive with any of the enchantments stored by the object.", }, IsEmpty = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the object stores no enchantments", }, operator_eq = { Params = { { Name = "OtherEnchantments", Type = "cEnchantments", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if this enchantments object has the same enchantments as OtherEnchantments.", }, SetLevel = { Params = { { Name = "EnchantmentNumID", Type = "number", }, { Name = "Level", Type = "number", }, }, Notes = "Sets the level for the specified enchantment, adding it if not stored before, or removing it if Level < = 0", }, StringToEnchantmentID = { IsStatic = true, Params = { { Name = "EnchantmentName", Type = "string", }, }, Returns = { { Type = "number", }, }, Notes = "Returns the enchantment numerical ID, -1 if not understood. Case insensitive. Also understands plain numbers.", }, ToString = { Returns = { { Type = "string", }, }, Notes = "Returns the string description of all the enchantments stored in this object, in numerical-ID form", }, }, Constants = { enchAquaAffinity = { Notes = "", }, enchBaneOfArthropods = { Notes = "", }, enchBlastProtection = { Notes = "", }, enchEfficiency = { Notes = "", }, enchFeatherFalling = { Notes = "", }, enchFireAspect = { Notes = "", }, enchFireProtection = { Notes = "", }, enchFlame = { Notes = "", }, enchFortune = { Notes = "", }, enchInfinity = { Notes = "", }, enchKnockback = { Notes = "", }, enchLooting = { Notes = "", }, enchLuckOfTheSea = { Notes = "", }, enchLure = { Notes = "", }, enchPower = { Notes = "", }, enchProjectileProtection = { Notes = "", }, enchProtection = { Notes = "", }, enchPunch = { Notes = "", }, enchRespiration = { Notes = "", }, enchSharpness = { Notes = "", }, enchSilkTouch = { Notes = "", }, enchSmite = { Notes = "", }, enchThorns = { Notes = "", }, enchUnbreaking = { Notes = "", }, }, }, cEntity = { Desc = [[ A cEntity object represents an object in the world, it has a position and orientation. cEntity is an abstract class, and can not be instantiated directly, instead, all entities are implemented as subclasses. The cEntity class works as the common interface for the operations that all (most) entities support.

All cEntity objects have an Entity Type so it can be determined what kind of entity it is efficiently. Entities also have a class inheritance awareness, they know their class name, their parent class' name and can decide if there is a class within their inheritance chain. Since these functions operate on strings, they are slightly slower than checking the entity type directly, on the other hand, they are more specific directly. To check if the entity is a spider, you need to call IsMob(), then cast the object to {{cMonster}} and finally compare {{cMonster}}:GetMonsterType() to mtSpider. GetClass(), on the other hand, returns "cSpider" directly.

Note that you should not store a cEntity object between two hooks' calls, because Cuberite may despawn / remove that entity in between the calls. If you need to refer to an entity later, use its UniqueID and {{cWorld|cWorld}}'s entity manipulation functions DoWithEntityByID(), ForEachEntity() or ForEachEntityInChunk() to access the entity again.

]], Functions = { AddPosition = { { Params = { { Name = "OffsetX", Type = "number", }, { Name = "OffsetY", Type = "number", }, { Name = "OffsetZ", Type = "number", }, }, Notes = "Moves the entity by the specified amount in each axis direction", }, { Params = { { Name = "Offset", Type = "Vector3d", }, }, Notes = "Moves the entity by the specified amount in each direction", }, }, AddPosX = { Params = { { Name = "OffsetX", Type = "number", }, }, Notes = "Moves the entity by the specified amount in the X axis direction", }, AddPosY = { Params = { { Name = "OffsetY", Type = "number", }, }, Notes = "Moves the entity by the specified amount in the Y axis direction", }, AddPosZ = { Params = { { Name = "OffsetZ", Type = "number", }, }, Notes = "Moves the entity by the specified amount in the Z axis direction", }, AddSpeed = { { Params = { { Name = "AddX", Type = "number", }, { Name = "AddY", Type = "number", }, { Name = "AddZ", Type = "number", }, }, Notes = "Adds the specified amount of speed in each axis direction.", }, { Params = { { Name = "Add", Type = "Vector3d", }, }, Notes = "Adds the specified amount of speed in each axis direction.", }, }, AddSpeedX = { Params = { { Name = "AddX", Type = "number", }, }, Notes = "Adds the specified amount of speed in the X axis direction.", }, AddSpeedY = { Params = { { Name = "AddY", Type = "number", }, }, Notes = "Adds the specified amount of speed in the Y axis direction.", }, AddSpeedZ = { Params = { { Name = "AddZ", Type = "number", }, }, Notes = "Adds the specified amount of speed in the Z axis direction.", }, ApplyArmorDamage = { Params = { { Name = "DamageBlocked", Type = "number", }, }, Notes = "Lowers armor durability, as if the armor blocked the given amount of damage.", }, ArmorCoversAgainst = { Params = { { Name = "DamageType", Type = "eDamageType", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns whether armor will protect against the specified damage type", }, Destroy = { Params = { { Name = "ShouldBroadcast (DEPRECATED)", Type = "boolean", IsOptional = true, }, }, Notes = "Schedules the entity to be destroyed; broadcasts the DestroyEntity packet", }, DoesPreventBlockPlacement = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if this entity doesn't allow blocks to be placed intersecting the entity.", }, GetAirLevel = { Returns = { { Type = "number", }, }, Notes = "Returns the air level (number of ticks of air left). Note, this function is only updated with mobs or players.", }, GetArmorCoverAgainst = { Params = { { Name = "AttackerEntity", Type = "cEntity", }, { Name = "DamageType", Type = "eDamageType", }, { Name = "RawDamage", Type = "number", }, }, Returns = { { Type = "number", }, }, Notes = "Returns the number of hitpoints out of RawDamage that the currently equipped armor would cover. See {{TakeDamageInfo}} for more information on attack damage.", }, GetBoundingBox = { Returns = { { Type = "cBoundingBox", }, }, Notes = "Returns the bounding box of the entity, which has width and height corresponding to the entity, and is aligned with the block grid.", }, GetChunkX = { Returns = { { Type = "number", }, }, Notes = "Returns the X-coord of the chunk in which the entity is placed", }, GetChunkZ = { Returns = { { Type = "number", }, }, Notes = "Returns the Z-coord of the chunk in which the entity is placed", }, GetClass = { Returns = { { Type = "string", }, }, Notes = "Returns the classname of the entity, such as \"cSpider\" or \"cPickup\"", }, GetClassStatic = { IsStatic = true, Returns = { { Type = "string", }, }, Notes = "Returns the entity classname that this class implements. Each descendant overrides this function.", }, GetEnchantmentBlastKnockbackReduction = { Returns = { { Type = "number", }, }, Notes = "Returns explosion knock back reduction percent from blast protection level.", }, GetEnchantmentCoverAgainst = { Params = { { Name = "AttackerEntity", Type = "cEntity", }, { Name = "DamageType", Type = "eDamageType", }, { Name = "RawDamage", Type = "number", }, }, Returns = { { Type = "number", }, }, Notes = "Returns the number of hitpoints out of RawDamage that the enchantments on the currently equipped armor would cover. See {{TakeDamageInfo}} for more information on attack damage.", }, GetEntityType = { Returns = { { Name = "EntityType", Type = "cEntity#eEntityType", }, }, Notes = "Returns the type of the entity, one of the {{cEntity#eEntityType|etXXX}} constants. Note that to check specific entity type, you should use one of the IsXXX functions instead of comparing the value returned by this call.", }, GetEquippedBoots = { Returns = { { Type = "cItem", }, }, Notes = "Returns the boots that the entity has equipped. Returns an empty cItem if no boots equipped or not applicable.", }, GetEquippedChestplate = { Returns = { { Type = "cItem", }, }, Notes = "Returns the chestplate that the entity has equipped. Returns an empty cItem if no chestplate equipped or not applicable.", }, GetEquippedHelmet = { Returns = { { Type = "cItem", }, }, Notes = "Returns the helmet that the entity has equipped. Returns an empty cItem if no helmet equipped or not applicable.", }, GetEquippedLeggings = { Returns = { { Type = "cItem", }, }, Notes = "Returns the leggings that the entity has equipped. Returns an empty cItem if no leggings equipped or not applicable.", }, GetEquippedWeapon = { Returns = { { Type = "cItem", }, }, Notes = "Returns the weapon that the entity has equipped. Returns an empty cItem if no weapon equipped or not applicable.", }, GetOffHandEquipedItem = { Returns = { { Type = "cItem", }, }, Notes = "Returns the item that the entity has equipped on off-hand. Returns an empty cItem if no item equipped or not applicable.", }, GetGravity = { Returns = { { Type = "number", }, }, Notes = "Returns the number that is used as the gravity for physics simulation. 1G (9.78) by default.", }, GetHeadYaw = { Returns = { { Type = "number", }, }, Notes = "Returns the pitch of the entity's head (FIXME: Rename to GetHeadPitch() ).", }, GetHealth = { Returns = { { Type = "number", }, }, Notes = "Returns the current health of the entity.", }, GetHeight = { Returns = { { Type = "number", }, }, Notes = "Returns the height (Y size) of the entity", }, GetInvulnerableTicks = { Returns = { { Type = "number", }, }, Notes = "Returns the number of ticks that this entity will be invulnerable for. This is used for after-hit recovery - the entities are invulnerable for half a second after being hit.", }, GetKnockbackAmountAgainst = { Params = { { Name = "ReceiverEntity", Type = "cEntity", }, }, Returns = { { Type = "number", }, }, Notes = "Returns the amount of knockback that the currently equipped items would cause when attacking the ReceiverEntity.", }, GetLookVector = { Returns = { { Type = "Vector3f", }, }, Notes = "Returns the vector that defines the direction in which the entity is looking", }, GetMass = { Returns = { { Type = "number", }, }, Notes = "Returns the mass of the entity. Currently unused.", }, GetMaxHealth = { Returns = { { Type = "number", }, }, Notes = "Returns the maximum number of hitpoints this entity is allowed to have.", }, GetParentClass = { Returns = { { Type = "string", }, }, Notes = "Returns the name of the direct parent class for this entity", }, GetPitch = { Returns = { { Type = "number", }, }, Notes = "Returns the pitch (nose-down rotation) of the entity. Measured in degrees, normal values range from -90 to +90. +90 means looking down, 0 means looking straight ahead, -90 means looking up.", }, GetPosition = { Returns = { { Type = "Vector3d", }, }, Notes = "Returns the entity's pivot position as a 3D vector", }, GetPosX = { Returns = { { Type = "number", }, }, Notes = "Returns the X-coord of the entity's pivot", }, GetPosY = { Returns = { { Type = "number", }, }, Notes = "Returns the Y-coord of the entity's pivot", }, GetPosZ = { Returns = { { Type = "number", }, }, Notes = "Returns the Z-coord of the entity's pivot", }, GetRawDamageAgainst = { Params = { { Name = "ReceiverEntity", Type = "cEntity", }, }, Returns = { { Type = "number", }, }, Notes = "Returns the raw damage that this entity's equipment would cause when attacking the ReceiverEntity. This includes this entity's weapon {{cEnchantments|enchantments}}, but excludes the receiver's armor or potion effects. See {{TakeDamageInfo}} for more information on attack damage.", }, GetRoll = { Returns = { { Type = "number", }, }, Notes = "Returns the roll (sideways rotation) of the entity. Currently unused.", }, GetSpeed = { Returns = { { Type = "Vector3d", }, }, Notes = "Returns the complete speed vector of the entity", }, GetSpeedX = { Returns = { { Type = "number", }, }, Notes = "Returns the X-part of the speed vector", }, GetSpeedY = { Returns = { { Type = "number", }, }, Notes = "Returns the Y-part of the speed vector", }, GetSpeedZ = { Returns = { { Type = "number", }, }, Notes = "Returns the Z-part of the speed vector", }, GetTicksAlive = { Returns = { { Type = "number", }, }, Notes = "Returns the number of ticks that this entity has been alive for.", }, GetUniqueID = { Returns = { { Type = "number", }, }, Notes = "Returns the ID that uniquely identifies the entity within the running server. Note that this ID is not persisted to the data files.", }, GetWidth = { Returns = { { Type = "number", }, }, Notes = "Returns the width (X and Z size) of the entity.", }, GetWorld = { Returns = { { Type = "cWorld", }, }, Notes = "Returns the world where the entity resides", }, GetYaw = { Returns = { { Type = "number", }, }, Notes = "Returns the yaw (direction) of the entity. Measured in degrees, values range from -180 to +180. 0 means ZP, 90 means XM, -180 means ZM, -90 means XP.", }, HandleSpeedFromAttachee = { Params = { { Name = "ForwardAmount", Type = "number", }, { Name = "SidewaysAmount", Type = "number", }, }, Notes = "Updates the entity's speed based on the attachee exerting the specified force forward and sideways. Used for entities being driven by other entities attached to them - usually players driving minecarts and boats.", }, Heal = { Params = { { Name = "Hitpoints", Type = "number", }, }, Notes = "Heals the specified number of hitpoints. Hitpoints is expected to be a positive number.", }, IsA = { Params = { { Name = "ClassName", Type = "string", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if the entity class is a descendant of the specified class name, or the specified class itself", }, IsArrow = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the entity is an arrow.", }, IsBoat = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the entity is a {{cBoat|boat}}.", }, IsCrouched = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the entity is crouched. Always false for entities that don't support crouching.", }, IsDestroyed = { Returns = { { Type = "boolean", }, }, Notes = "(DEPRECATED) Please use cEntity:IsTicking().", }, IsElytraFlying = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the entity is flying with an elytra. Entities that cannot fly with an elytra return always false.", }, IsEnderCrystal = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the entity is an ender crystal.", }, IsExpOrb = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the entity represents an experience orb", }, IsFallingBlock = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the entity represents a {{cFallingBlock}} entity.", }, IsFireproof = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the entity takes no damage from being on fire.", }, IsFloater = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the entity represents a fishing rod floater", }, IsHeadInWater = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the entity's head is in a water block", }, IsInvisible = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the entity is invisible.", }, IsInFire = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if any part of the entity is in a fire block", }, IsInLava = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if any part of the entity is in a lava block", }, IsInWater = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if any part of the entity is in a water block", }, IsItemFrame = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the entity is an item frame.", }, IsLeashKnot = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the entity is a leash knot.", }, IsMinecart = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the entity represents a {{cMinecart|minecart}}", }, IsMob = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the entity represents any {{cMonster|mob}}.", }, IsOnFire = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the entity is on fire", }, IsOnGround = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the entity is on ground (not falling, not jumping, not flying)", }, IsPainting = { Returns = { { Type = "boolean", }, }, Notes = "Returns if this entity is a painting.", }, IsPawn = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the entity is a {{cPawn}} descendant.", }, IsPickup = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the entity represents a {{cPickup|pickup}}.", }, IsPlayer = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the entity represents a {{cPlayer|player}}", }, IsProjectile = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the entity is a {{cProjectileEntity}} descendant.", }, IsRclking = { Returns = { { Type = "boolean", }, }, Notes = "Currently unimplemented", }, IsRiding = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the entity is attached to (riding) another entity.", }, IsSprinting = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the entity is sprinting. Entities that cannot sprint return always false", }, IsSubmerged = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the entity's head is in a water block Currently deprecated in favour of IsHeadInWater()", }, IsSwimming = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if any part of the entity is in a water block. Note, this function is only updated with mobs or players. Currently deprecated in favour of IsInWater()", }, IsTicking = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the entity is valid and ticking. Returns false if the entity is not ticking and is about to leave its current world either via teleportation or destruction. If this returns false, you must stop using the cEntity pointer you have.", }, IsTNT = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the entity represents a {{cTNTEntity|TNT entity}}", }, Killed = { Params = { { Name = "Victim", Type = "cEntity", }, }, Notes = "This entity has killed another entity (the Victim). For players, adds the scoreboard statistics about the kill.", }, MoveToWorld = { { Params = { { Name = "World", Type = "cWorld", }, { Name = "ShouldSendRespawn", Type = "boolean", IsOptional = true, }, }, Returns = { { Type = "boolean", }, }, Notes = "Removes the entity from this world and starts moving it to the specified world's spawn point. Note that to avoid deadlocks, the move is asynchronous - the entity is moved into a queue and will be moved from that queue into the destination world at some (unpredictable) time in the future. ShouldSendRespawn is used only for players, it specifies whether the player should be sent a Respawn packet upon leaving the world (The client handles respawns only between different dimensions).", }, { Params = { { Name = "WorldName", Type = "string", }, { Name = "ShouldSendRespawn", Type = "boolean", IsOptional = true, }, }, Returns = { { Type = "boolean", }, }, Notes = "Removes the entity from this world and starts moving it to the specified world's spawn point. Note that to avoid deadlocks, the move is asynchronous - the entity is moved into a queue and will be moved from that queue into the destination world at some (unpredictable) time in the future. ShouldSendRespawn is used only for players, it specifies whether the player should be sent a Respawn packet upon leaving the world (The client handles respawns only between different dimensions).", }, { Params = { { Name = "World", Type = "cWorld", }, { Name = "ShouldSendRespawn", Type = "boolean", }, { Name = "Position", Type = "Vector3d", }, }, Returns = { { Type = "boolean", }, }, Notes = "Removes the entity from this world and starts moving it to the specified world. Note that to avoid deadlocks, the move is asynchronous - the entity is moved into a queue and will be moved from that queue into the destination world at some (unpredictable) time in the future. ShouldSendRespawn is used only for players, it specifies whether the player should be sent a Respawn packet upon leaving the world (The client handles respawns only between different dimensions). The Position parameter specifies the location that the entity should be placed in, in the new world.", }, { Params = { { Name = "World", Type = "cWorld", }, { Name = "Position", Type = "Vector3d", }, { Name = "ShouldSetPortalCooldown", Type = "boolean", IsOptional = true, }, { Name = "ShouldSendRespawn", Type = "boolean", IsOptional = true, }, }, Returns = { { Type = "boolean", }, }, Notes = "Removes the entity from this world and starts moving it to the specified world. Note that to avoid deadlocks, the move is asynchronous - the entity is moved into a queue and will be moved from that queue into the destination world at some (unpredictable) time in the future. If ShouldSetPortalCooldown is false (default), doesn't set any portal cooldown, if it is true, the default portal cooldown is applied to the entity. ShouldSendRespawn is used only for players, it specifies whether the player should be sent a Respawn packet upon leaving the world (The client handles respawns only between different dimensions). The Position parameter specifies the location that the entity should be placed in, in the new world.", }, }, SetGravity = { Params = { { Name = "Gravity", Type = "number", }, }, Notes = "Sets the number that is used as the gravity for physics simulation. 1G (9.78) by default.", }, SetHeadYaw = { Params = { { Name = "HeadPitch", Type = "number", }, }, Notes = "Sets the head pitch (FIXME: Rename to SetHeadPitch() ).", }, SetHealth = { Params = { { Name = "Hitpoints", Type = "number", }, }, Notes = "Sets the entity's health to the specified amount of hitpoints. Doesn't broadcast any hurt animation. Doesn't kill the entity if health drops below zero. Use the TakeDamage() function instead for taking damage.", }, SetInvulnerableTicks = { Params = { { Name = "NumTicks", Type = "number", }, }, Notes = "Sets the amount of ticks for which the entity will not receive any damage from other entities.", }, SetIsFireproof = { Params = { { Name = "IsFireproof", Type = "boolean", }, }, Notes = "Sets whether the entity receives damage from being on fire.", }, SetMass = { Params = { { Name = "Mass", Type = "number", }, }, Notes = "Sets the mass of the entity. Currently unused.", }, SetMaxHealth = { Params = { { Name = "MaxHitpoints", Type = "number", }, }, Notes = "Sets the maximum hitpoints of the entity. If current health is above MaxHitpoints, it is capped to MaxHitpoints.", }, SetPitch = { Params = { { Name = "Pitch", Type = "number", }, }, Notes = "Sets the pitch (nose-down rotation) of the entity", }, SetPitchFromSpeed = { Notes = "Sets the entity pitch to match its speed (entity looking forwards as it moves)", }, SetPosition = { { Params = { { Name = "PosX", Type = "number", }, { Name = "PosY", Type = "number", }, { Name = "PosZ", Type = "number", }, }, Notes = "Sets all three coords of the entity's pivot", }, { Params = { { Name = "Vector3d", Type = "Vector3d", }, }, Notes = "Sets all three coords of the entity's pivot", }, }, SetPosX = { Params = { { Name = "PosX", Type = "number", }, }, Notes = "Sets the X-coord of the entity's pivot", }, SetPosY = { Params = { { Name = "PosY", Type = "number", }, }, Notes = "Sets the Y-coord of the entity's pivot", }, SetPosZ = { Params = { { Name = "PosZ", Type = "number", }, }, Notes = "Sets the Z-coord of the entity's pivot", }, SetRoll = { Params = { { Name = "Roll", Type = "number", }, }, Notes = "Sets the roll (sideways rotation) of the entity. Currently unused.", }, SetSpeed = { { Params = { { Name = "SpeedX", Type = "number", }, { Name = "SpeedY", Type = "number", }, { Name = "SpeedZ", Type = "number", }, }, Notes = "Sets the current speed of the entity", }, { Params = { { Name = "Speed", Type = "Vector3d", }, }, Notes = "Sets the current speed of the entity", }, }, SetSpeedX = { Params = { { Name = "SpeedX", Type = "number", }, }, Notes = "Sets the X component of the entity speed", }, SetSpeedY = { Params = { { Name = "SpeedY", Type = "number", }, }, Notes = "Sets the Y component of the entity speed", }, SetSpeedZ = { Params = { { Name = "SpeedZ", Type = "number", }, }, Notes = "Sets the Z component of the entity speed", }, SetYaw = { Params = { { Name = "Yaw", Type = "number", }, }, Notes = "Sets the yaw (direction) of the entity.", }, SetYawFromSpeed = { Notes = "Sets the entity's yaw to match its current speed (entity looking forwards as it moves).", }, StartBurning = { Params = { { Name = "NumTicks", Type = "number", }, }, Notes = "Sets the entity on fire for the specified number of ticks. If entity is on fire already, makes it burn for either NumTicks or the number of ticks left from the previous fire, whichever is larger.", }, SteerVehicle = { Params = { { Name = "ForwardAmount", Type = "number", }, { Name = "SidewaysAmount", Type = "number", }, }, Notes = "Applies the specified steering to the vehicle this entity is attached to. Ignored if not attached to any entity.", }, StopBurning = { Notes = "Extinguishes the entity fire, cancels all fire timers.", }, TakeDamage = { { Params = { { Name = "AttackerEntity", Type = "cEntity", }, }, Notes = "Causes this entity to take damage that AttackerEntity would inflict. Includes their weapon and this entity's armor.", }, { Params = { { Name = "DamageType", Type = "eDamageType", }, { Name = "AttackerEntity", Type = "cEntity", }, { Name = "RawDamage", Type = "number", }, { Name = "KnockbackAmount", Type = "number", }, }, Notes = "Causes this entity to take damage of the specified type, from the specified attacker (may be nil). The final damage is calculated from RawDamage using the currently equipped armor.", }, { Params = { { Name = "DamageType", Type = "eDamageType", }, { Name = "AttackerEntity", Type = "cEntity", }, { Name = "RawDamage", Type = "number", }, { Name = "FinalDamage", Type = "number", }, { Name = "KnockbackAmount", Type = "number", }, }, Notes = "Causes this entity to take damage of the specified type, from the specified attacker (may be nil). The values are wrapped into a {{TakeDamageInfo}} structure and applied directly.", }, }, TeleportToCoords = { Params = { { Name = "PosX", Type = "number", }, { Name = "PosY", Type = "number", }, { Name = "PosZ", Type = "number", }, }, Notes = "Teleports the entity to the specified coords. Asks plugins if the teleport is allowed.", }, TeleportToEntity = { Params = { { Name = "DestEntity", Type = "cEntity", }, }, Notes = "Teleports this entity to the specified destination entity. Asks plugins if the teleport is allowed.", }, }, Constants = { INVALID_ID = { Notes = "Special value of an entity ID, indicating a failure. Used primarily in functions that create entities when the entity cannot be created.", }, etBoat = { Notes = "The entity is a {{cBoat}}", }, etEnderCrystal = { Notes = "The entity is a {{cEnderCrystal}}", }, etEntity = { Notes = "No further specialization available", }, etExpOrb = { Notes = "The entity is a {{cExpOrb}}", }, etFallingBlock = { Notes = "The entity is a {{cFallingBlock}}", }, etFloater = { Notes = "The entity is a fishing rod floater", }, etItemFrame = { Notes = "The entity is an item frame", }, etLeashKnot = { Notes = "The entity is a leash knot", }, etMinecart = { Notes = "The entity is a {{cMinecart}} descendant", }, etMob = { Notes = "The entity is a {{cMonster}} descendant", }, etMonster = { Notes = "The entity is a {{cMonster}} descendant", }, etPainting = { Notes = "The entity is a {{cPainting}}", }, etPickup = { Notes = "The entity is a {{cPickup}}", }, etPlayer = { Notes = "The entity is a {{cPlayer}}", }, etProjectile = { Notes = "The entity is a {{cProjectileEntity}} descendant", }, etTNT = { Notes = "The entity is a {{cTNTEntity}}", }, }, ConstantGroups = { eEntityType = { Include = "et.*", TextBefore = "The following constants are used to distinguish between different entity types:", }, }, }, cEntityEffect = { Functions = { GetPotionColor = { IsStatic = true, Params = { { Name = "ItemDamage", Type = "number", }, }, Returns = { { Type = "number", }, }, Notes = "Returns the potion color (used by the client for visuals), based on the potion's damage value", }, GetPotionEffectDuration = { IsStatic = true, Params = { { Name = "ItemDamage", Type = "number", }, }, Returns = { { Type = "number", }, }, Notes = "Returns the effect duration, in ticks, based on the potion's damage value", }, GetPotionEffectIntensity = { IsStatic = true, Params = { { Name = "ItemDamage", Type = "number", }, }, Returns = { { Name = "short", Type = "number", }, }, Notes = "Retrieves the intensity level from the potion's damage value. Returns 0 for level I potions, 1 for level II potions.", }, GetPotionEffectType = { IsStatic = true, Params = { { Name = "ItemDamage", Type = "number", }, }, Returns = { { Name = "eType", Type = "cEntityEffect#eType", }, }, Notes = "Translates the potion's damage value into the entity effect that the potion gives", }, IsPotionDrinkable = { IsStatic = true, Params = { { Name = "ItemDamage", Type = "number", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if the potion with the given damage is drinkable", }, }, -- Functions ConstantGroups = { eType = { Include = { "eff.*" }, }, }, -- ConstantGroups }, -- cEntityEffect cFile = { Desc = [[ Provides helper functions for manipulating and querying the filesystem. Most functions are static, so they should be called directly on the cFile class itself:
cFile:DeleteFile("/usr/bin/virus.exe");

]], Functions = { ChangeFileExt = { IsStatic = true, Params = { { Name = "FileName", Type = "string", }, { Name = "NewExt", Type = "string", }, }, Returns = { { Type = "string", }, }, Notes = "Returns FileName with its extension changed to NewExt. NewExt may begin with a dot, but needn't, the result is the same in both cases (the first dot, if present, is ignored). FileName may contain path elements, extension is recognized as the last dot after the last path separator in the string.", }, Copy = { IsStatic = true, Params = { { Name = "SrcFileName", Type = "string", }, { Name = "DstFileName", Type = "string", }, }, Returns = { { Name = "IsSuccess", Type = "boolean", }, }, Notes = "Copies a single file to a new destination. Returns true if successful. Fails if the destination already exists.", }, CreateFolder = { IsStatic = true, Params = { { Name = "FolderPath", Type = "string", }, }, Returns = { { Name = "IsSuccess", Type = "boolean", }, }, Notes = "Creates a new folder. Returns true if successful. Only a single level can be created at a time, use CreateFolderRecursive() to create multiple levels of folders at once.", }, CreateFolderRecursive = { IsStatic = true, Params = { { Name = "FolderPath", Type = "string", }, }, Returns = { { Name = "IsSuccess", Type = "boolean", }, }, Notes = "Creates a new folder, creating its parents if needed. Returns true if successful.", }, Delete = { IsStatic = true, Params = { { Name = "Path", Type = "string", }, }, Returns = { { Name = "IsSuccess", Type = "boolean", }, }, Notes = "Deletes the specified file or folder. Returns true if successful. Only deletes folders that are empty.
NOTE: If you already know if the object is a file or folder, use DeleteFile() or DeleteFolder() explicitly.", }, DeleteFile = { IsStatic = true, Params = { { Name = "FilePath", Type = "string", }, }, Returns = { { Name = "IsSuccess", Type = "boolean", }, }, Notes = "Deletes the specified file. Returns true if successful.", }, DeleteFolder = { IsStatic = true, Params = { { Name = "FolderPath", Type = "string", }, }, Returns = { { Name = "IsSuccess", Type = "boolean", }, }, Notes = "Deletes the specified file or folder. Returns true if successful. Only deletes folders that are empty.", }, DeleteFolderContents = { IsStatic = true, Params = { { Name = "FolderPath", Type = "string", }, }, Returns = { { Name = "IsSuccess", Type = "boolean", }, }, Notes = "Deletes everything from the specified folder, recursively. The specified folder stays intact. Returns true if successful.", }, Exists = { IsStatic = true, Params = { { Name = "Path", Type = "string", }, }, Returns = { { Name = "Exists", Type = "boolean", }, }, Notes = "Returns true if the specified file or folder exists.
OBSOLETE, use IsFile() or IsFolder() instead", }, GetExecutableExt = { IsStatic = true, Returns = { { Type = "string", }, }, Notes = "Returns the customary executable extension (including the dot) used by the current platform (\".exe\" on Windows, empty string on Linux). ", }, GetFolderContents = { IsStatic = true, Params = { { Name = "FolderName", Type = "string", }, }, Returns = { { Type = "table", }, }, Notes = "Returns the contents of the specified folder, as an array table of strings. Each filesystem object is listed. Use the IsFile() and IsFolder() functions to determine the object type. Note that \".\" and \"..\" are NOT returned. The order of the names is arbitrary (as returned by OS, no sorting).", }, GetLastModificationTime = { IsStatic = true, Params = { { Name = "Path", Type = "string", }, }, Returns = { { Type = "number", }, }, Notes = "Returns the last modification time (in current timezone) of the specified file or folder. Returns zero if file not found / not accessible. The returned value is in the same units as values returned by os.time().", }, GetPathSeparator = { IsStatic = true, Returns = { { Type = "string", }, }, Notes = "Returns the primary path separator used by the current platform. Returns \"\\\" on Windows and \"/\" on Linux. Note that the platform or CRT may support additional path separators, those are not reported.", }, GetSize = { IsStatic = true, Params = { { Name = "FileName", Type = "string", }, }, Returns = { { Type = "number", }, }, Notes = "Returns the size of the file, or -1 on failure.", }, IsFile = { IsStatic = true, Params = { { Name = "Path", Type = "string", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if the specified path points to an existing file.", }, IsFolder = { IsStatic = true, Params = { { Name = "Path", Type = "string", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if the specified path points to an existing folder.", }, ReadWholeFile = { IsStatic = true, Params = { { Name = "FileName", Type = "string", }, }, Returns = { { Type = "string", }, }, Notes = "Returns the entire contents of the specified file. Returns an empty string if the file cannot be opened.", }, Rename = { IsStatic = true, Params = { { Name = "OrigPath", Type = "string", }, { Name = "NewPath", Type = "string", }, }, Returns = { { Name = "IsSuccess", Type = "boolean", }, }, Notes = "Renames a file or a folder. Returns true if successful. Undefined result if NewPath already exists.", }, }, }, cFloater = { Desc = [[ Manages the floater created when a player uses their fishing rod. ]], Functions = { CanPickup = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the floater gives an item when the player right clicks.", }, GetAttachedMobID = { Returns = { { Name = "EntityID", Type = "number", }, }, Notes = "Returns the EntityID of a mob that this floater is attached to. Returns -1 if not attached to any mob.", }, GetOwnerID = { Returns = { { Name = "EntityID", Type = "number", }, }, Notes = "Returns the EntityID of the player who owns the floater.", }, GetBitePos = { Returns = { Name = "BitePosition", Type = "Vector3d", }, Notes = "Returns the position of the floater just before a fish bites. If a fish hasn't bitten the floater, this function returns the position the floater was cast from.", }, }, Inherits = "cEntity", }, cHangingEntity = { Functions = { GetFacing = { Returns = { { Name = "BlockFace", Type = "eBlockFace", }, }, Notes = "Returns the direction in which the entity is facing.", }, IsValidSupportBlock = { IsStatic = true, Params = { { Name = "BlockType", Type = "number", }, }, Returns = { { Type = "boolean", } }, Notes = "Returns true if the specified block type can support a hanging entity. This means that paintings and item frames can be placed on such a block.", }, SetFacing = { Params = { { Name = "BlockFace", Type = "eBlockFace", }, }, Notes = "Set the direction in which the entity is facing.", }, }, Inherits = "cEntity", }, cIniFile = { Desc = [[ This class implements a simple name-value storage represented on disk by an INI file. These files are suitable for low-volume high-latency human-readable information storage, such as for configuration. Cuberite itself uses INI files for settings and options.

The INI files follow this basic structure:

; Header comment line
[KeyName0]
; Key comment line 0
ValueName0=Value0
ValueName1=Value1

[KeyName1]
; Key comment line 0
; Key comment line 1
ValueName0=SomeOtherValue
The cIniFile object stores all the objects in numbered arrays and provides access to the information either based on names (KeyName, ValueName) or zero-based indices.

The objects of this class are created empty. You need to either load a file using ReadFile(), or insert values by hand. Then you can store the object's contents to a disk file using WriteFile(), or just forget everything by destroying the object. Note that the file operations are quite slow.

Cuberite will write the characters '\n' in place of line breaks in the values of the cIniFile when it is being stored into a file. It will also replace '\n' with line breaks when it reads an INI file.

For storing high-volume low-latency data, use the {{sqlite3}} class. For storing hierarchically-structured data, use the XML format, using the LuaExpat parser in the {{lxp}} class. ]], Functions = { AddHeaderComment = { Params = { { Name = "Comment", Type = "string", }, }, Notes = "Adds a comment to be stored in the file header.", }, AddKeyComment = { { Params = { { Name = "KeyID", Type = "number", }, { Name = "Comment", Type = "string", }, }, Notes = "Adds a comment to be stored in the file under the specified key", }, { Params = { { Name = "KeyName", Type = "string", }, { Name = "Comment", Type = "string", }, }, Notes = "Adds a comment to be stored in the file under the specified key", }, }, AddKeyName = { Params = { { Name = "KeyName", Type = "string", }, }, Returns = { { Type = "number", }, }, Notes = "Adds a new key of the specified name. Returns the KeyID of the new key.", }, AddValue = { Params = { { Name = "KeyName", Type = "string", }, { Name = "ValueName", Type = "string", }, { Name = "Value", Type = "string", }, }, Notes = "Adds a new value of the specified name to the specified key. If another value of the same name exists in the key, both are kept (nonstandard INI file)", }, AddValueB = { Params = { { Name = "KeyName", Type = "string", }, { Name = "ValueName", Type = "string", }, { Name = "Value", Type = "boolean", }, }, Notes = "Adds a new bool value of the specified name to the specified key. If another value of the same name exists in the key, both are kept (nonstandard INI file)", }, AddValueF = { Params = { { Name = "KeyName", Type = "string", }, { Name = "ValueName", Type = "string", }, { Name = "Value", Type = "number", }, }, Notes = "Adds a new float value of the specified name to the specified key. If another value of the same name exists in the key, both are kept (nonstandard INI file)", }, AddValueI = { Params = { { Name = "KeyName", Type = "string", }, { Name = "ValueName", Type = "string", }, { Name = "Value", Type = "number", }, }, Notes = "Adds a new integer value of the specified name to the specified key. If another value of the same name exists in the key, both are kept (nonstandard INI file)", }, CaseInsensitive = { Notes = "Sets key names' and value names' comparisons to case insensitive (default).", }, CaseSensitive = { Notes = "Sets key names and value names comparisons to case sensitive.", }, Clear = { Notes = "Removes all the in-memory data. Note that , like all the other operations, this doesn't affect any file data.", }, constructor = { Returns = { { Type = "cIniFile", }, }, Notes = "Creates a new empty cIniFile object.", }, DeleteHeaderComment = { Params = { { Name = "CommentID", Type = "number", }, }, Returns = { { Name = "IsSuccess", Type = "boolean", }, }, Notes = "Deletes the specified header comment. Returns true if successful.", }, DeleteHeaderComments = { Notes = "Deletes all headers comments.", }, DeleteKey = { Params = { { Name = "KeyName", Type = "string", }, }, Returns = { { Name = "IsSuccess", Type = "boolean", }, }, Notes = "Deletes the specified key, and all values in that key. Returns true if successful.", }, DeleteKeyComment = { { Params = { { Name = "KeyID", Type = "number", }, { Name = "CommentID", Type = "number", }, }, Returns = { { Name = "IsSuccess", Type = "boolean", }, }, Notes = "Deletes the specified key comment. Returns true if successful.", }, { Params = { { Name = "KeyName", Type = "string", }, { Name = "CommentID", Type = "number", }, }, Returns = { { Name = "IsSuccess", Type = "boolean", }, }, Notes = "Deletes the specified key comment. Returns true if successful.", }, }, DeleteKeyComments = { { Params = { { Name = "KeyID", Type = "number", }, }, Returns = { { Name = "IsSuccess", Type = "boolean", }, }, Notes = "Deletes all comments for the specified key. Returns true if successful.", }, { Params = { { Name = "KeyName", Type = "string", }, }, Returns = { { Name = "IsSuccess", Type = "boolean", }, }, Notes = "Deletes all comments for the specified key. Returns true if successful.", }, }, DeleteValue = { Params = { { Name = "KeyName", Type = "string", }, { Name = "ValueName", Type = "string", }, }, Returns = { { Name = "IsSuccess", Type = "boolean", }, }, Notes = "Deletes the specified value. Returns true if successful.", }, DeleteValueByID = { Params = { { Name = "KeyID", Type = "number", }, { Name = "ValueID", Type = "number", }, }, Returns = { { Name = "IsSuccess", Type = "boolean", }, }, Notes = "Deletes the specified value. Returns true if successful.", }, FindKey = { Params = { { Name = "KeyName", Type = "string", }, }, Returns = { { Type = "number", }, }, Notes = "Returns the KeyID for the specified key name, or the noID constant if the key doesn't exist.", }, FindValue = { Params = { { Name = "KeyID", Type = "number", }, { Name = "ValueName", Type = "string", }, }, Returns = { { Name = "ValueID", Type = "number", }, }, Notes = "Returns the ValueID for the specified value name, or the noID constant if the specified key doesn't contain a value of that name.", }, Flush = { Returns = { { Type = "boolean", }, }, Notes = "Writes the data stored in the object to the file that was last associated with the object (ReadFile() or WriteFile()). Returns true on success, false on failure.", }, GetHeaderComment = { Params = { { Name = "CommentID", Type = "number", }, }, Returns = { { Type = "string", }, }, Notes = "Returns the specified header comment, or an empty string if such comment doesn't exist", }, GetKeyComment = { { Params = { { Name = "KeyID", Type = "number", }, { Name = "CommentID", Type = "number", }, }, Returns = { { Type = "string", }, }, Notes = "Returns the specified key comment, or an empty string if such a comment doesn't exist", }, { Params = { { Name = "KeyName", Type = "string", }, { Name = "CommentID", Type = "number", }, }, Returns = { { Type = "string", }, }, Notes = "Returns the specified key comment, or an empty string if such a comment doesn't exist", }, }, GetKeyName = { Params = { { Name = "KeyID", Type = "number", }, }, Returns = { { Type = "string", }, }, Notes = "Returns the key name for the specified key ID. Inverse for FindKey().", }, GetNumHeaderComments = { Returns = { { Type = "number", }, }, Notes = "Retuns the number of header comments.", }, GetNumKeyComments = { { Params = { { Name = "KeyID", Type = "number", }, }, Returns = { { Type = "number", }, }, Notes = "Returns the number of comments under the specified key", }, { Params = { { Name = "KeyName", Type = "string", }, }, Returns = { { Type = "number", }, }, Notes = "Returns the number of comments under the specified key", }, }, GetNumKeys = { Returns = { { Type = "number", }, }, Notes = "Returns the total number of keys. This is the range for the KeyID (0 .. GetNumKeys() - 1)", }, GetNumValues = { { Params = { { Name = "KeyID", Type = "number", }, }, Returns = { { Type = "number", }, }, Notes = "Returns the number of values stored under the specified key.", }, { Params = { { Name = "KeyName", Type = "string", }, }, Returns = { { Type = "number", }, }, Notes = "Returns the number of values stored under the specified key.", }, }, GetValue = { { Params = { { Name = "KeyName", Type = "string", }, { Name = "ValueName", Type = "string", }, { Name = "DefaultValue", Type = "string", IsOptional = true, }, }, Returns = { { Type = "string", }, }, Notes = "Returns the value of the specified name under the specified key. Returns DefaultValue (empty string if not given) if the value doesn't exist.", }, { Params = { { Name = "KeyID", Type = "number", }, { Name = "ValueID", Type = "number", }, { Name = "DefaultValue", Type = "string", IsOptional = true, }, }, Returns = { { Type = "string", }, }, Notes = "Returns the value of the specified name under the specified key. Returns DefaultValue (empty string if not given) if the value doesn't exist.", }, }, GetValueB = { Params = { { Name = "KeyName", Type = "string", }, { Name = "ValueName", Type = "string", }, { Name = "DefaultValue", Type = "boolean", IsOptional = true, }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns the value of the specified name under the specified key, as a bool. Returns DefaultValue (false if not given) if the value doesn't exist.", }, GetValueF = { Params = { { Name = "KeyName", Type = "string", }, { Name = "ValueName", Type = "string", }, { Name = "DefaultValue", Type = "number", IsOptional = true, }, }, Returns = { { Type = "number", }, }, Notes = "Returns the value of the specified name under the specified key, as a floating-point number. Returns DefaultValue (zero if not given) if the value doesn't exist.", }, GetValueI = { Params = { { Name = "KeyName", Type = "string", }, { Name = "ValueName", Type = "string", }, { Name = "DefaultValue", Type = "number", IsOptional = true, }, }, Returns = { { Type = "number", }, }, Notes = "Returns the value of the specified name under the specified key, as an integer. Returns DefaultValue (zero if not given) if the value doesn't exist.", }, GetValueName = { { Params = { { Name = "KeyID", Type = "number", }, { Name = "ValueID", Type = "number", }, }, Returns = { { Type = "string", }, }, Notes = "Returns the name of the value specified by its ID. Inverse for FindValue().", }, { Params = { { Name = "KeyName", Type = "string", }, { Name = "ValueID", Type = "number", }, }, Returns = { { Type = "string", }, }, Notes = "Returns the name of the value specified by its ID. Inverse for FindValue().", }, }, GetValueSet = { Params = { { Name = "KeyName", Type = "string", }, { Name = "ValueName", Type = "string", }, { Name = "DefaultValue", Type = "string", IsOptional = true, }, }, Returns = { { Type = "string", }, }, Notes = "Returns the value of the specified name under the specified key. If the value doesn't exist, creates it with the specified default (empty string if not given).", }, GetValueSetB = { Params = { { Name = "KeyName", Type = "string", }, { Name = "ValueName", Type = "string", }, { Name = "DefaultValue", Type = "boolean", IsOptional = true, }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns the value of the specified name under the specified key, as a bool. If the value doesn't exist, creates it with the specified default (false if not given).", }, GetValueSetF = { Params = { { Name = "KeyName", Type = "string", }, { Name = "ValueName", Type = "string", }, { Name = "DefaultValue", Type = "number", IsOptional = true, }, }, Returns = { { Type = "number", }, }, Notes = "Returns the value of the specified name under the specified key, as a floating-point number. If the value doesn't exist, creates it with the specified default (zero if not given).", }, GetValueSetI = { Params = { { Name = "KeyName", Type = "string", }, { Name = "ValueName", Type = "string", }, { Name = "DefaultValue", Type = "number", IsOptional = true, }, }, Returns = { { Type = "number", }, }, Notes = "Returns the value of the specified name under the specified key, as an integer. If the value doesn't exist, creates it with the specified default (zero if not given).", }, HasValue = { Params = { { Name = "KeyName", Type = "string", }, { Name = "ValueName", Type = "string", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if the specified value is present.", }, ReadFile = { Params = { { Name = "FileName", Type = "string", }, { Name = "AllowExampleFallback", Type = "boolean", IsOptional = true, }, }, Returns = { { Name = "IsSuccess", Type = "boolean", }, }, Notes = "Reads the values from the specified file. Previous in-memory contents are lost. If the file cannot be opened, and AllowExample is true, another file, \"filename.example.ini\", is loaded and then saved as \"filename.ini\". Returns true if successful, false if not.", }, SetValue = { { Params = { { Name = "KeyID", Type = "number", }, { Name = "ValueID", Type = "number", }, { Name = "NewValue", Type = "string", }, }, Returns = { { Name = "IsSuccess", Type = "boolean", }, }, Notes = "Overwrites the specified value with a new value. If the specified value doesn't exist, returns false (doesn't add).", }, { Params = { { Name = "KeyName", Type = "string", }, { Name = "ValueName", Type = "string", }, { Name = "NewValue", Type = "string", }, { Name = "CreateIfNotExists", Type = "boolean", IsOptional = true, }, }, Returns = { { Name = "IsSuccess", Type = "boolean", }, }, Notes = "Overwrites the specified value with a new value. If CreateIfNotExists is true (default) and the value doesn't exist, it is first created. Returns true if the value was successfully set, false if not (didn't exists, CreateIfNotExists false).", }, }, SetValueB = { Params = { { Name = "KeyName", Type = "string", }, { Name = "ValueName", Type = "string", }, { Name = "NewValue", Type = "boolean", }, { Name = "CreateIfNotExists", Type = "boolean", IsOptional = true, }, }, Returns = { { Name = "IsSuccess", Type = "boolean", }, }, Notes = "Overwrites the specified value with a new bool value. If CreateIfNotExists is true (default) and the value doesn't exist, it is first created. Returns true if the value was successfully set, false if not (didn't exists, CreateIfNotExists false).", }, SetValueF = { Params = { { Name = "KeyName", Type = "string", }, { Name = "ValueName", Type = "string", }, { Name = "NewValue", Type = "number", }, { Name = "CreateIfNotExists", Type = "boolean", IsOptional = true, }, }, Returns = { { Name = "IsSuccess", Type = "boolean", }, }, Notes = "Overwrites the specified value with a new floating-point number value. If CreateIfNotExists is true (default) and the value doesn't exist, it is first created. Returns true if the value was successfully set, false if not (didn't exists, CreateIfNotExists false).", }, SetValueI = { Params = { { Name = "KeyName", Type = "string", }, { Name = "ValueName", Type = "string", }, { Name = "NewValue", Type = "number", }, { Name = "CreateIfNotExists", Type = "boolean", IsOptional = true, }, }, Returns = { { Name = "IsSuccess", Type = "boolean", }, }, Notes = "Overwrites the specified value with a new integer value. If CreateIfNotExists is true (default) and the value doesn't exist, it is first created. Returns true if the value was successfully set, false if not (didn't exists, CreateIfNotExists false).", }, WriteFile = { Params = { { Name = "FileName", Type = "string", }, }, Returns = { { Name = "IsSuccess", Type = "boolean", }, }, Notes = "Writes the current in-memory data into the specified file. Returns true if successful, false if not.", }, }, Constants = { noID = { Notes = "", }, }, AdditionalInfo = { { Header = "Code example: Reading a simple value", Contents = [[ cIniFile is very easy to use. For example, you can find out what port the server is supposed to use according to settings.ini by using this little snippet:

local IniFile = cIniFile();
if (IniFile:ReadFile("settings.ini")) then
	ServerPort = IniFile:GetValueI("Server", "Port");
end
]], }, { Header = "Code example: Enumerating all objects in a file", Contents = [[ To enumerate all keys in a file, you need to query the total number of keys, using GetNumKeys(), and then query each key's name using GetKeyName(). Similarly, to enumerate all values under a key, you need to query the total number of values using GetNumValues() and then query each value's name using GetValueName().

The following code logs all keynames and their valuenames into the server log:

local IniFile = cIniFile();
IniFile:ReadFile("somefile.ini")
local NumKeys = IniFile:GetNumKeys();
for k = 0, (NumKeys - 1) do
	local NumValues = IniFile:GetNumValues(k);
	LOG("key \"" .. IniFile:GetKeyName(k) .. "\" has " .. NumValues .. " values:");
	for v = 0, (NumValues - 1) do
		LOG("  value \"" .. IniFile:GetValueName(k, v) .. "\".");
	end
end
]], }, }, }, cInventory = { Desc = [[ This object is used to store the items that a {{cPlayer|cPlayer}} has. It also keeps track of what item the player has currently selected in their hotbar. Internally, the class uses three {{cItemGrid|cItemGrid}} objects to store the contents:
  • Armor
  • Inventory
  • Hotbar
  • These ItemGrids are available in the API and can be manipulated by the plugins, too.

    When using the raw slot access functions, such as GetSlot() and SetSlot(), the slots are numbered consecutively, each ItemGrid has its offset and count. To future-proff your plugins, use the named constants instead of hard-coded numbers. ]], Functions = { AddItem = { Params = { { Name = "cItem", Type = "cItem", }, { Name = "AllowNewStacks", Type = "boolean", IsOptional = true, }, }, Returns = { { Type = "number", }, }, Notes = "Adds an item to the storage; if AllowNewStacks is true (default), will also create new stacks in empty slots. Fills existing stacks first and fills the hotbar before the main inventory. Returns the number of items added", }, AddItems = { Params = { { Name = "cItems", Type = "cItems", }, { Name = "AllowNewStacks", Type = "boolean", IsOptional = true, }, }, Returns = { { Type = "number", }, }, Notes = "Same as AddItem, but for several items at once", }, ChangeSlotCount = { Params = { { Name = "SlotNum", Type = "number", }, { Name = "AddToCount", Type = "number", }, }, Returns = { { Type = "number", }, }, Notes = "Adds AddToCount to the count of items in the specified slot. If the slot was empty, ignores the call. Returns the new count in the slot, or -1 if invalid SlotNum", }, Clear = { Notes = "Empties all slots", }, CopyToItems = { Params = { { Name = "cItems", Type = "cItems", }, }, Notes = "Copies all non-empty slots into the cItems object provided; original cItems contents are preserved", }, DamageEquippedItem = { Params = { { Name = "DamageAmount", Type = "number", IsOptional = true, }, }, Returns = { { Name = "HasDestroyed", Type = "boolean", }, }, Notes = "Adds the specified damage (1 by default) to the currently equipped item. Removes the item and returns true if the item reached its max damage and was destroyed.", }, DamageItem = { Params = { { Name = "SlotNum", Type = "number", }, { Name = "DamageAmount", Type = "number", IsOptional = true, }, }, Returns = { { Name = "HasDestroyed", Type = "boolean", }, }, Notes = "Adds the specified damage (1 by default) to the specified item. Removes the item and returns true if the item reached its max damage and was destroyed.", }, FindItem = { Params = { { Name = "RecipeItem", Type = "cItem", }, }, Returns = { { Type = "cItem", }, }, Notes = "Finds an item in the shield, hotbar and inventory slots matching `ItemType` and `ItemDamage`. The actual item is returned, if none is found `nullptr`. This can be used to validate that the player has a specific type of item.", }, GetArmorGrid = { Returns = { { Type = "cItemGrid", }, }, Notes = "Returns the ItemGrid representing the armor grid (1 x 4 slots)", }, GetArmorSlot = { Params = { { Name = "ArmorSlotNum", Type = "number", }, }, Returns = { { Type = "cItem", }, }, Notes = "Returns the specified armor slot contents. Note that the returned item is read-only", }, GetEquippedBoots = { Returns = { { Type = "cItem", }, }, Notes = "Returns the item in the \"boots\" slot of the armor grid. Note that the returned item is read-only", }, GetEquippedChestplate = { Returns = { { Type = "cItem", }, }, Notes = "Returns the item in the \"chestplate\" slot of the armor grid. Note that the returned item is read-only", }, GetEquippedHelmet = { Returns = { { Type = "cItem", }, }, Notes = "Returns the item in the \"helmet\" slot of the armor grid. Note that the returned item is read-only", }, GetEquippedItem = { Returns = { { Type = "cItem", }, }, Notes = "Returns the currently selected item from the hotbar. Note that the returned item is read-only. Also note that the returned item is bound to the actual inventory slot - if a player moves another item into the slot, this object will update to the new item. Use a {{cItem}} constructor to make a copy if you need to store the contents of the slot.", }, GetEquippedLeggings = { Returns = { { Type = "cItem", }, }, Notes = "Returns the item in the \"leggings\" slot of the armor grid. Note that the returned item is read-only", }, GetEquippedSlotNum = { Returns = { { Type = "number", }, }, Notes = "Returns the hotbar slot number for the currently selected item", }, GetHotbarGrid = { Returns = { { Type = "cItemGrid", }, }, Notes = "Returns the ItemGrid representing the hotbar grid (9 x 1 slots)", }, GetHotbarSlot = { Params = { { Name = "HotBarSlotNum", Type = "number", }, }, Returns = { { Type = "cItem", }, }, Notes = "Returns the specified hotbar slot contents. Note that the returned item is read-only", }, GetShieldSlot = { Returns = { { Type = "cItem", }, }, Notes = "Returns current item in shield slot.", }, GetInventoryGrid = { Returns = { { Type = "cItemGrid", }, }, Notes = "Returns the ItemGrid representing the main inventory (9 x 3 slots)", }, GetInventorySlot = { Params = { { Name = "InventorySlotNum", Type = "number", }, }, Returns = { { Type = "cItem", }, }, Notes = "Returns the specified main inventory slot contents. Note that the returned item is read-only", }, GetOwner = { Returns = { { Type = "cPlayer", }, }, Notes = "Returns the player whose inventory this object represents", }, GetSlot = { Params = { { Name = "SlotNum", Type = "number", }, }, Returns = { { Type = "cItem", }, }, Notes = "Returns the contents of the specified slot. Note that the returned item is read-only", }, HasItems = { Params = { { Name = "cItem", Type = "cItem", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if there are at least as many items of the specified type as in the parameter", }, HowManyCanFit = { { Params = { { Name = "ItemStack", Type = "cItem", }, { Name = "AllowNewStacks", Type = "boolean", IsOptional = true, }, }, Returns = { { Type = "number", }, }, Notes = "Returns number of items out of a_ItemStack that can fit in the storage. If AllowNewStacks is false, only considers slots already containing the specified item. AllowNewStacks defaults to true if not given.", }, { Params = { { Name = "ItemStack", Type = "cItem", }, { Name = "BeginSlotNum", Type = "number", }, { Name = "EndSlotNum", Type = "number", }, { Name = "AllowNewStacks", Type = "boolean", IsOptional = true, }, }, Returns = { { Type = "number", }, }, Notes = "Returns how many items of the specified type would fit into the slot range specified. If AllowNewStacks is false, only considers slots already containing the specified item. AllowNewStacks defaults to true if not given.", }, }, HowManyItems = { Params = { { Name = "cItem", Type = "cItem", }, }, Returns = { { Type = "number", }, }, Notes = "Returns the number of the specified items that are currently stored", }, RemoveItem = { Params = { { Name = "cItem", Type = "cItem", }, }, Returns = { { Type = "number", }, }, Notes = "Removes the specified item from the inventory, as many as possible, up to the item's m_ItemCount. Returns the number of items that were removed.", }, RemoveOneEquippedItem = { Returns = { { Type = "boolean", }, }, Notes = "Removes one item from the hotbar's currently selected slot. Returns true on success.", }, ReplaceOneEquippedItem = { Params = { { Name = "Item", Type = "cItem", }, { Name = "TryOtherSlots", Type = "boolean", IsOptional = true, }, }, Returns = { { Type = "number", }, }, Notes = "Removes one item from the the current equipped item stack, and attempts to add the specified item stack back to the same slot. If it is not possible to place the item in the same slot, optionally (default true) tries to place the specified item elsewhere in the inventory. Returns the number of items successfully added. If the currently equipped slot is empty, its contents are simply set to the given Item.", }, SendEquippedSlot = { Notes = "Sends the equipped item slot to the client", }, SetArmorSlot = { Params = { { Name = "ArmorSlotNum", Type = "number", }, { Name = "cItem", Type = "cItem", }, }, Notes = "Sets the specified armor slot contents", }, SetEquippedSlotNum = { Params = { { Name = "EquippedSlotNum", Type = "number", }, }, Notes = "Sets the currently selected hotbar slot number", }, SetHotbarSlot = { Params = { { Name = "HotbarSlotNum", Type = "number", }, { Name = "cItem", Type = "cItem", }, }, Notes = "Sets the specified hotbar slot contents", }, SetInventorySlot = { Params = { { Name = "InventorySlotNum", Type = "number", }, { Name = "cItem", Type = "cItem", }, }, Notes = "Sets the specified main inventory slot contents", }, SetShieldSlot = { Params = { { Name = "Item", Type = "cItem", }, }, Notes = "Sets the shield slot content", }, SetSlot = { Params = { { Name = "SlotNum", Type = "number", }, { Name = "cItem", Type = "cItem", }, }, Notes = "Sets the specified slot contents", }, SetEquippedItem = { Params = { { Name = "Item", Type = "cItem", }, }, Notes = "Sets current item in the equipped hotbar slot", }, }, Constants = { invArmorCount = { Notes = "Number of slots in the Armor part", }, invArmorOffset = { Notes = "Starting slot number of the Armor part", }, invHotbarCount = { Notes = "Number of slots in the Hotbar part", }, invHotbarOffset = { Notes = "Starting slot number of the Hotbar part", }, invInventoryCount = { Notes = "Number of slots in the main inventory part", }, invInventoryOffset = { Notes = "Starting slot number of the main inventory part", }, invShieldCount = { Notes = "Number of slots in the Shield part", }, invShieldOffset = { Notes = "Starting slot number of the Shield part", }, invNumSlots = { Notes = "Total number of slots in a cInventory", }, }, ConstantGroups = { SlotIndices = { Include = "inv.*", TextBefore = [[ Rather than hardcoding numbers, use the following constants for slot indices and counts: ]], }, }, }, cItem = { Desc = [[ cItem is what defines an item or stack of items in the game, it contains the item ID, damage, quantity and enchantments. Each slot in a {{cInventory}} class or a {{cItemGrid}} class is a cItem and each {{cPickup}} contains a cItem. The enchantments are contained in a separate {{cEnchantments}} class and are accessible through the m_Enchantments variable.

    To test if a cItem object represents an empty item, do not compare the item type nor the item count, but rather use the IsEmpty() function.

    To translate from a cItem to its string representation, use the {{Globals#functions|global function}} ItemToString(), ItemTypeToString() or ItemToFullString(). To translate from a string to a cItem, use the StringToItem() global function. ]], Functions = { AddCount = { Params = { { Name = "AmountToAdd", Type = "number", }, }, Returns = { { Type = "cItem", }, }, Notes = "Adds the specified amount to the item count. Returns self (useful for chaining).", }, AddEnchantment = { Params = { { Name = "Enchantment ID", Type = "number", }, { Name = "Level", Type = "number", }, { Name = "FromBook", Type = "boolean", }, }, Returns = { { Type = "number", }, }, Notes = "Adds the given enchantment at the given level to this item, following anvil enchantment combining rules. Returns the XP level cost of the addition. FromBook specifies whether to use the XP multiplier for books or the multiplier used for other items, if true it uses the multiplier for books.", }, AddEnchantmentsFromItem = { Params = { { Name = "Additive", Type = "cItem", }, }, Returns = { { Name = "LevelCost", Type = "number", }, }, Notes = "Adds the enchantments from the specified item to this item, returning the cost as if this were an anvil.", }, Clear = { Notes = "Resets the instance to an empty item", }, constructor = { { Returns = { { Type = "cItem", }, }, Notes = "Creates a new empty cItem object", }, { Params = { { Name = "ItemType", Type = "number", }, { Name = "Count", Type = "number", IsOptional = true, }, { Name = "Damage", Type = "number", IsOptional = true, }, { Name = "EnchantmentString", Type = "string", IsOptional = true, }, { Name = "CustomName", Type = "string", IsOptional = true, }, { Name = "Lore", Type = "table", IsOptional = true, }, }, Returns = { { Type = "cItem", }, }, Notes = "Creates a new cItem object of the specified type, count (1 by default), damage (0 by default), enchantments (non-enchanted by default), CustomName (empty by default) and Lore (string, empty by default)", }, { Params = { { Name = "cItem", Type = "cItem", }, }, Returns = { { Type = "cItem", }, }, Notes = "Creates an exact copy of the cItem object in the parameter", }, }, CopyOne = { Returns = { { Type = "cItem", }, }, Notes = "Creates a copy of this object, with its count set to 1", }, DamageItem = { Params = { { Name = "Amount", Type = "number", IsOptional = true, }, }, Returns = { { Name = "HasReachedMaxDamage", Type = "boolean", }, }, Notes = "Adds the specified damage. Returns true when damage reaches max value and the item should be destroyed (but doesn't destroy the item)", }, Empty = { Notes = "Resets the instance to an empty item", }, EnchantByXPLevels = { Params = { { Name = "NumXPLevels", Type = "number", }, }, Returns = { { Name = "HasEnchanted", Type = "boolean", }, }, Notes = "Randomly enchants the item using the specified number of XP levels. Returns true if the item was enchanted, false if not (not enchantable / too many enchantments already).", }, GetEnchantability = { Returns = { { Type = "number", }, }, Notes = "Returns the enchantability of the item. Returns zero if the item doesn't have enchantability.", }, GetMaxDamage = { Returns = { { Type = "number", }, }, Notes = "Returns the maximum value for damage that this item can get before breaking; zero if damage is not accounted for for this item type", }, GetMaxStackSize = { Returns = { { Type = "number", }, }, Notes = "Returns the maximum stack size for this item.", }, IsBothNameAndLoreEmpty = { Returns = { { Type = "boolean", }, }, Notes = "Returns if both the custom name and lore are not set.", }, IsCustomNameEmpty = { Returns = { { Type = "boolean", }, }, Notes = "Returns if the custom name is empty.", }, IsDamageable = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if this item does account for its damage", }, IsEmpty = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if this object represents an empty item (zero count or invalid ItemType)", }, IsEnchantable = { IsStatic = true, Params = { { Name = "ItemType", Type = "number", }, { Name = "FromBook", Type = "boolean", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if the specified item type is enchantable. If FromBook is true, the function is used in the anvil inventory with book enchantments. So it checks the \"only book enchantments\" too. Example: You can only enchant a hoe with a book.", }, IsEqual = { Params = { { Name = "OtherItem", Type = "cItem", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if the item in the parameter is the same as the one stored in the object (type, damage, lore, name and enchantments)", }, IsFullStack = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the item is stacked up to its maximum stacking", }, IsLoreEmpty = { Notes = "Returns if the lore of the cItem is empty.", Returns = { { Type = "boolean", }, }, }, IsSameType = { Params = { { Name = "OtherItem", Type = "cItem", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if the item in the parameter is of the same ItemType as the one stored in the object. This is true even if the two items have different enchantments", }, }, Variables = { m_CustomName = { Type = "string", Notes = "The custom name for an item.", }, m_Enchantments = { Type = "{{cEnchantments|cEnchantments}}}", Notes = "The enchantments of the item.", }, m_ItemCount = { Type = "number", Notes = "Number of items in this stack", }, m_ItemDamage = { Type = "number", Notes = "The damage of the item. Zero means no damage. Maximum damage can be queried with GetMaxDamage()", }, m_ItemType = { Type = "number", Notes = "The item type. One of E_ITEM_ or E_BLOCK_ constants", }, m_LoreTable = { Type = "table", Notes = "The lore for an item. Represented as an array table of lines.", }, m_RepairCost = { Type = "number", Notes = "The repair cost of the item. The anvil need this value", }, }, AdditionalInfo = { { Header = "Usage notes", Contents = [[ Note that the object contained in a cItem class is quite complex and quite often new Minecraft versions add more stuff. Therefore it is recommended to copy cItem objects using the copy-constructor ("local copy = cItem(original);"), this is the only way that guarantees that the object will be copied at full, even with future versions of Cuberite. ]], }, { Header = "Example code", Contents = [[ The following code shows how to create items in several different ways (adapted from the Debuggers plugin):

    -- empty item:
    local Item1 = cItem();
    
    -- enchanted sword, enchantment given as numeric string (bad style; see Item5):
    local Item2 = cItem(E_ITEM_DIAMOND_SWORD, 1, 0, "1=1");
    
    -- 1 undamaged shovel, no enchantment:
    local Item3 = cItem(E_ITEM_DIAMOND_SHOVEL);
    
    -- Add the Unbreaking enchantment. Note that Vanilla's levelcap isn't enforced:
    Item3.m_Enchantments:SetLevel(cEnchantments.enchUnbreaking, 4);
    
    -- 1 undamaged pickaxe, no enchantment:
    local Item4 = cItem(E_ITEM_DIAMOND_PICKAXE);
    
    -- Add multiple enchantments:
    Item4.m_Enchantments:SetLevel(cEnchantments.enchUnbreaking, 5);
    Item4.m_Enchantments:SetLevel(cEnchantments.enchEfficiency, 3);
    
    -- enchanted chestplate, enchantment given as textual stringdesc (good style)
    local Item5 = cItem(E_ITEM_DIAMOND_CHESTPLATE, 1, 0, "thorns=1;unbreaking=3");
    
    ]], }, }, }, cItemFrame = { Functions = { GetItem = { Returns = { { Type = "cItem", IsConst = true, }, }, Notes = "Returns the item in the frame (readonly object, do not modify)", }, GetItemRotation = { Returns = { { Type = "number", }, }, Notes = "Returns the rotation from the item in the frame", }, SetItem = { Params = { { Name = "Item", Type = "cItem", }, }, Notes = "Set the item in the frame", }, SetItemRotation = { Params = { { Name = "ItemRotation", Type = "number", }, }, Notes = "Set the rotation from the item in the frame", }, }, }, cItemGrid = { Desc = [[ This class represents a 2D array of items. It is used as the underlying storage and API for all cases that use a grid of items:
  • {{cChestEntity|Chest}} contents
  • (TODO) Chest minecart contents
  • {{cDispenserEntity|Dispenser}} contents
  • {{cDropperEntity|Dropper}} contents
  • {{cFurnaceEntity|Furnace}} contents (?)
  • {{cHopperEntity|Hopper}} contents
  • (TODO) Hopper minecart contents
  • {{cPlayer|Player}} Inventory areas
  • (TODO) Trapped chest contents
  • The items contained in this object are accessed either by a pair of XY coords, or a slot number (x + Width * y). There are functions available for converting between the two formats. ]], Functions = { AddItem = { Params = { { Name = "ItemStack", Type = "cItem", }, { Name = "AllowNewStacks", Type = "boolean", IsOptional = true, }, { Name = "PrioritySlot", Type = "number", IsOptional = true, }, }, Returns = { { Type = "number", }, }, Notes = "Adds as many items out of ItemStack as can fit. If AllowNewStacks is set to false, only existing stacks can be topped up. If AllowNewStacks is set to true (default), empty slots can be used for the rest. If PrioritySlot is set to a non-negative value, then the corresponding slot will be used first (if empty or compatible with added items). If PrioritySlot is set to -1 (default), regular order applies. Returns the number of items that fit.", }, AddItems = { Params = { { Name = "ItemStackList", Type = "cItems", }, { Name = "AllowNewStacks", Type = "boolean", IsOptional = true, }, { Name = "PrioritySlot", Type = "number", IsOptional = true, }, }, Returns = { { Type = "number", }, }, Notes = "Same as AddItem, but works on an entire list of item stacks. The a_ItemStackList is modified to reflect the leftover items. If a_AllowNewStacks is set to false, only existing stacks can be topped up. If AllowNewStacks is set to true, empty slots can be used for the rest. If PrioritySlot is set to a non-negative value, then the corresponding slot will be used first (if empty or compatible with added items). If PrioritySlot is set to -1 (default), regular order applies. Returns the total number of items that fit.", }, ChangeSlotCount = { { Params = { { Name = "SlotNum", Type = "number", }, { Name = "AddToCount", Type = "number", }, }, Returns = { { Type = "number", }, }, Notes = "Adds AddToCount to the count of items in the specified slot. If the slot was empty, ignores the call. Returns the new count in the slot, or -1 if invalid SlotNum", }, { Params = { { Name = "X", Type = "number", }, { Name = "Y", Type = "number", }, { Name = "AddToCount", Type = "number", }, }, Returns = { { Type = "number", }, }, Notes = "Adds AddToCount to the count of items in the specified slot. If the slot was empty, ignores the call. Returns the new count in the slot, or -1 if invalid slot coords", }, }, Clear = { Notes = "Empties all slots", }, CopyToItems = { Params = { { Name = "cItems", Type = "cItems", }, }, Notes = "Copies all non-empty slots into the {{cItems}} object provided; original cItems contents are preserved as well.", }, DamageItem = { { Params = { { Name = "SlotNum", Type = "number", }, { Name = "DamageAmount", Type = "number", IsOptional = true, }, }, Returns = { { Name = "HasReachedMaxDamage", Type = "boolean", }, }, Notes = "Adds the specified damage (1 by default) to the specified item, returns true if the item reached its max damage and should be destroyed (but doesn't destroy the item).", }, { Params = { { Name = "X", Type = "number", }, { Name = "Y", Type = "number", }, { Name = "DamageAmount", Type = "number", IsOptional = true, }, }, Returns = { { Name = "HasReachedMaxDamage", Type = "boolean", }, }, Notes = "Adds the specified damage (1 by default) to the specified item, returns true if the item reached its max damage and should be destroyed (but doesn't destroy the item).", }, }, EmptySlot = { { Params = { { Name = "SlotNum", Type = "number", }, }, Notes = "Destroys the item in the specified slot", }, { Params = { { Name = "X", Type = "number", }, { Name = "Y", Type = "number", }, }, Notes = "Destroys the item in the specified slot", }, }, FindItem = { Params = { { Name = "RecipeItem", Type = "cItem", }, }, Returns = { { Type = "cItem", }, }, Notes = "Finds an item within the grid matching `ItemType` and `ItemDamage`. The actual item is returned, if none is found `nullptr`.", }, GetFirstEmptySlot = { Returns = { { Type = "number", }, }, Notes = "Returns the SlotNumber of the first empty slot, -1 if all slots are full", }, GetFirstUsedSlot = { Returns = { { Type = "number", }, }, Notes = "Returns the SlotNumber of the first non-empty slot, -1 if all slots are empty", }, GetHeight = { Returns = { { Type = "number", }, }, Notes = "Returns the Y dimension of the grid", }, GetLastEmptySlot = { Returns = { { Type = "number", }, }, Notes = "Returns the SlotNumber of the last empty slot, -1 if all slots are full", }, GetLastUsedSlot = { Returns = { { Type = "number", }, }, Notes = "Returns the SlotNumber of the last non-empty slot, -1 if all slots are empty", }, GetNextEmptySlot = { Params = { { Name = "StartFrom", Type = "number", }, }, Returns = { { Type = "number", }, }, Notes = "Returns the SlotNumber of the first empty slot following StartFrom, -1 if all the following slots are full", }, GetNextUsedSlot = { Params = { { Name = "StartFrom", Type = "number", }, }, Returns = { { Type = "number", }, }, Notes = "Returns the SlotNumber of the first non-empty slot following StartFrom, -1 if all the following slots are full", }, GetNumSlots = { Returns = { { Type = "number", }, }, Notes = "Returns the total number of slots in the grid (Width * Height)", }, GetSlot = { { Params = { { Name = "SlotNumber", Type = "number", }, }, Returns = { { Type = "cItem", }, }, Notes = "Returns the item in the specified slot. Note that the item is read-only", }, { Params = { { Name = "X", Type = "number", }, { Name = "Y", Type = "number", }, }, Returns = { { Type = "cItem", }, }, Notes = "Returns the item in the specified slot. Note that the item is read-only", }, }, GetSlotCoords = { Params = { { Name = "SlotNum", Type = "number", }, }, Returns = { { Type = "number", }, { Type = "number", }, }, Notes = "Returns the X and Y coords for the specified SlotNumber. Returns \"-1, -1\" on invalid SlotNumber", }, GetSlotNum = { Params = { { Name = "X", Type = "number", }, { Name = "Y", Type = "number", }, }, Returns = { { Type = "number", }, }, Notes = "Returns the SlotNumber for the specified slot coords. Returns -1 on invalid coords", }, GetWidth = { Returns = { { Type = "number", }, }, Notes = "Returns the X dimension of the grid", }, HasItems = { Params = { { Name = "ItemStack", Type = "cItem", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if there are at least as many items of the specified type as in the parameter", }, HowManyCanFit = { Params = { { Name = "ItemStack", Type = "cItem", }, { Name = "AllowNewStacks", Type = "boolean", IsOptional = true, }, }, Returns = { { Type = "number", }, }, Notes = "Returns the number of the specified items that can fit in the storage. If AllowNewStacks is true (default), includes empty slots in the returned count.", }, HowManyItems = { Params = { { Name = "Item", Type = "cItem", }, }, Returns = { { Type = "number", }, }, Notes = "Returns the number of the specified item that are currently stored", }, IsSlotEmpty = { { Params = { { Name = "SlotNum", Type = "number", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if the specified slot is empty, or an invalid slot is specified", }, { Params = { { Name = "X", Type = "number", }, { Name = "Y", Type = "number", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if the specified slot is empty, or an invalid slot is specified", }, }, RemoveItem = { Params = { { Name = "ItemStack", Type = "cItem", }, }, Returns = { { Type = "number", }, }, Notes = "Removes the specified item from the grid, as many as possible, up to ItemStack's m_ItemCount. Returns the number of items that were removed.", }, RemoveOneItem = { { Params = { { Name = "SlotNum", Type = "number", }, }, Returns = { { Type = "cItem", }, }, Notes = "Removes one item from the stack in the specified slot and returns it as a single cItem. Empty slots are skipped and an empty item is returned", }, { Params = { { Name = "X", Type = "number", }, { Name = "Y", Type = "number", }, }, Returns = { { Type = "cItem", }, }, Notes = "Removes one item from the stack in the specified slot and returns it as a single cItem. Empty slots are skipped and an empty item is returned", }, }, SetSlot = { { Params = { { Name = "SlotNum", Type = "number", }, { Name = "cItem", Type = "cItem", }, }, Notes = "Sets the specified slot to the specified item", }, { Params = { { Name = "SlotNum", Type = "number", }, { Name = "ItemType", Type = "number", }, { Name = "ItemCount", Type = "number", }, { Name = "ItemDamage", Type = "number", }, }, Notes = "Sets the specified slot to the specified item", }, { Params = { { Name = "X", Type = "number", }, { Name = "Y", Type = "number", }, { Name = "cItem", Type = "cItem", }, }, Notes = "Sets the specified slot to the specified item", }, { Params = { { Name = "X", Type = "number", }, { Name = "Y", Type = "number", }, { Name = "ItemType", Type = "number", }, { Name = "ItemCount", Type = "number", }, { Name = "ItemDamage", Type = "number", }, }, Notes = "Sets the specified slot to the specified item", }, }, }, AdditionalInfo = { { Header = "Code example: Add items to player inventory", Contents = [[ The following code tries to add 32 sticks to a player's main inventory:

    local Items = cItem(E_ITEM_STICK, 32);
    local PlayerInventory = Player:GetInventory();
    local PlayerMainInventory = PlayerInventory:GetInventoryGrid();  -- PlayerMainInventory is of type cItemGrid
    local NumAdded = PlayerMainInventory:AddItem(Items);
    if (NumAdded == Items.m_ItemCount) then
      -- All the sticks did fit
      LOG("Added 32 sticks");
    else
      -- Some (or all) of the sticks didn't fit
      LOG("Tried to add 32 sticks, but only " .. NumAdded .. " could fit");
    end
    
    ]], }, { Header = "Code example: Damage an item", Contents = [[ The following code damages the helmet in the player's armor and destroys it if it reaches max damage:
    local PlayerInventory = Player:GetInventory();
    local PlayerArmor = PlayerInventory:GetArmorGrid();  -- PlayerArmor is of type cItemGrid
    if (PlayerArmor:DamageItem(0)) then  -- Helmet is at SlotNum 0
      -- The helmet has reached max damage, destroy it:
      PlayerArmor:EmptySlot(0);
    end
    
    ]], }, }, }, cItems = { Desc = [[ This class represents a numbered collection (array) of {{cItem}} objects. The array indices start at zero, each consecutive item gets a consecutive index. This class is used for spawning multiple pickups or for mass manipulating an inventory. ]], Functions = { Add = { { Params = { { Name = "cItem", Type = "cItem", }, }, Notes = "Adds a new item to the end of the collection", }, { Params = { { Name = "ItemType", Type = "number", }, { Name = "ItemCount", Type = "number", }, { Name = "ItemDamage", Type = "number", }, }, Notes = "Adds a new item to the end of the collection", }, }, AddItemGrid = { Params = { { Name = "ItemGrid", Type = "cItemGrid", }, }, Notes = "Adds a copy of each item in the specified {{cItemGrid|ItemGrid}}.", }, Clear = { Notes = "Removes all items from the collection", }, constructor = { Returns = { { Type = "cItems", }, }, Notes = "Creates a new empty cItems object", }, Contains = { Params = { { Name = "Item", Type = "cItem", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if the collection contains an item that is fully equivalent to the parameter", }, ContainsType = { Params = { { Name = "Item", Type = "cItem", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if the collection contains an item that is the same type as the parameter", }, Delete = { Params = { { Name = "Index", Type = "number", }, }, Notes = "Deletes item at the specified index", }, Get = { Params = { { Name = "Index", Type = "number", }, }, Returns = { { Type = "cItem", }, }, Notes = "Returns the item at the specified index", }, Set = { { Params = { { Name = "Index", Type = "number", }, { Name = "cItem", Type = "cItem", }, }, Notes = "Sets the item at the specified index to the specified item", }, { Params = { { Name = "Index", Type = "number", }, { Name = "ItemType", Type = "number", }, { Name = "ItemCount", Type = "number", }, { Name = "ItemDamage", Type = "number", }, }, Notes = "Sets the item at the specified index to the specified item", }, }, Size = { Returns = { { Type = "number", }, }, Notes = "Returns the number of items in the collection", }, }, }, cJson = { Desc = [[ Exposes the Json parser and serializer available in the server. Plugins can parse Json strings into Lua tables, and serialize Lua tables into Json strings easily. ]], Functions = { Parse = { IsStatic = true, Params = { { Name = "InputString", Type = "string", }, }, Returns = { { Type = "table", }, }, Notes = "Parses the Json in the input string into a Lua table. Returns nil and detailed error message if parsing fails.", }, Serialize = { IsStatic = true, Params = { { Name = "table", Type = "table", }, { Name = "options", Type = "table", IsOptional = true, }, }, Returns = { { Type = "string", }, }, Notes = "Serializes the input table into a Json string. The options table, if present, is used to adjust the formatting of the serialized string, see below for details.
    Returns nil and error message if the table cannot be serialized (eg. contains both an array part and a dictionary part).", }, }, AdditionalInfo = { { Header = "Serializer options", Contents = [[ The "options" parameter given to the cJson:Serialize() function is a dictionary-table of "option name" -> "option value". The serializer warns if any unknown options are used; the following options are recognized:

    • commentStyle - either "All" or "None", specifies whether comments are written to the output. Currently unused since comments cannot be represented in a Lua table
    • indentation - the string that is repeated for each level of indentation of the output. If empty, the Json is compressed (without linebreaks).
    • enableYAMLCompatibility - bool manipulating the whitespace around the colons.
    • dropNullPlaceholders - bool specifying whether null placeholders should be dropped from the output
    ]], }, { Header = "Code example: Parsing a Json string", Contents = [==[ The following code, adapted from the Debuggers plugin, parses a simple Json string and verifies the results:
    local t1 = cJson:Parse([[{"a": 1, "b": "2", "c": [3, "4", 5]}]])
    assert(t1.a == 1)
    assert(t1.b == "2")
    assert(t1.c[1] == 3)
    assert(t1.c[2] == "4")
    assert(t1.c[3] == 5)
    
    ]==], }, { Header = "Code example: Serializing into a Json string", Contents = [[ The following code, adapted from the Debuggers plugin, serializes a simple Lua table into a string, using custom indentation:
    local s1 = cJson:Serialize({a = 1, b = "2", c = {3, "4", 5}}, {indentation = "  "})
    LOG("Serialization result: " .. (s1 or ""))
    
    ]], }, }, }, cLuaWindow = { Desc = [[ This class is used by plugins wishing to display a custom window to the player, unrelated to block entities or entities near the player. The window can be of any type and have any contents that the plugin defines. Callbacks for when the player modifies the window contents and when the player closes the window can be set.

    This class inherits from the {{cWindow|cWindow}} class, so all cWindow's functions and constants can be used, in addition to the cLuaWindow-specific functions listed below.

    The contents of this window are represented by a {{cWindow|cWindow}}:GetSlot() etc. or {{cPlayer|cPlayer}}:GetInventory() to access the player inventory.

    When creating a new cLuaWindow object, you need to specify both the window type and the contents' width and height. Note that Cuberite accepts any combination of these, but opening a window for a player may crash their client if the contents' dimensions don't match the client's expectations.

    To open the window for a player, call {{cPlayer|cPlayer}}:OpenWindow(). Multiple players can open window of the same cLuaWindow object. All players see the same items in the window's contents (like chest, unlike crafting table). ]], Functions = { constructor = { Params = { { Name = "WindowType", Type = "cWindow#WindowType", }, { Name = "ContentsWidth", Type = "number", }, { Name = "ContentsHeight", Type = "number", }, { Name = "Title", Type = "string", }, }, Notes = "Creates a new object of this class. The window is not shown to any player yet.", }, GetContents = { Returns = { { Type = "cItemGrid", }, }, Notes = "Returns the cItemGrid object representing the internal storage in this window", }, SetOnClicked = { Params = { { Name = "OnClickedCallback", Type = "function", }, }, Notes = "Sets the function that the window will call when it is about to process a click from a player. See {{#additionalinfo_1|below}} for the signature of the callback function.", }, SetOnClosing = { Params = { { Name = "OnClosingCallback", Type = "function", }, }, Notes = "Sets the function that the window will call when it is about to be closed by a player", }, SetOnSlotChanged = { Params = { { Name = "OnSlotChangedCallback", Type = "function", }, }, Notes = "Sets the function that the window will call when a slot is changed by a player", }, }, AdditionalInfo = { { Header = "Callbacks", Contents = [[ The object calls the following functions at the appropriate time: ]], }, { Header = "OnClicked Callback", Contents = [[ This callback, settable via the SetOnClicked() function, will be called when the player clicks a slot in the window. The callback can cancel the click.

    function OnWindowClicked(a_Window, a_Player, a_SlotNum, a_ClickAction, a_ClickedItem)
    

    The a_Window parameter is the cLuaWindow object representing the window, a_Player is the player who made the click, a_SlotNum is the slot the player clicked, a_ClickAction is the type of click the player made, and a_ClickedItem is the item the player clicked on, if applicable. If the function returns true, the click is cancelled (internally, the server resends the window slots to the player to keep the player in sync). ]], }, { Header = "OnClosing Callback", Contents = [[ This callback, settable via the SetOnClosing() function, will be called when the player tries to close the window, or the window is closed for any other reason (such as a player disconnecting).

    function OnWindowClosing(a_Window, a_Player, a_CanRefuse)
    

    The a_Window parameter is the cLuaWindow object representing the window, a_Player is the player for whom the window is about to close. a_CanRefuse specifies whether the callback can refuse the closing. If the callback returns true and a_CanRefuse is true, the window is not closed (internally, the server sends a new OpenWindow packet to the client). ]], }, { Header = "OnSlotChanged Callback", Contents = [[ This callback, settable via the SetOnSlotChanged() function, will be called whenever the contents of any slot in the window's contents (i. e. NOT in the player inventory!) changes.

    function OnWindowSlotChanged(a_Window, a_SlotNum)
    

    The a_Window parameter is the cLuaWindow object representing the window, a_SlotNum is the slot number. There is no reference to a {{cPlayer}}, because the slot change needn't originate from the player action. To get or set the slot, you'll need to retrieve a cPlayer object, for example by calling {{cWorld|cWorld}}:DoWithPlayer().

    Any returned values are ignored. ]], }, { Header = "Example", Contents = [[ This example is taken from the Debuggers plugin, used to test the API functionality. It opens a window and refuse to close it 3 times. It also logs slot changes to the server console and prevents shift-clicking in the window.

    -- Callback that refuses to close the window twice, then allows:
    local Attempt = 1;
    local OnClosing = function(Window, Player, CanRefuse)
    	Player:SendMessage("Window closing attempt #" .. Attempt .. "; CanRefuse = " .. tostring(CanRefuse));
    	Attempt = Attempt + 1;
    	return CanRefuse and (Attempt <= 3);  -- refuse twice, then allow, unless CanRefuse is set to true
    end
    
    -- Log the slot changes:
    local OnSlotChanged = function(Window, SlotNum)
    	LOG("Window \"" .. Window:GetWindowTitle() .. "\" slot " .. SlotNum .. " changed.");
    end
    
    -- Prevent shift-clicking:
    local OnClicked = function(Window, ClickingPlayer, SlotNum, ClickAction, ClickedItem)
    	if ClickAction == caShiftLeftClick then
    		return true
    	end
    end
    
    -- Set window contents:
    -- a_Player is a cPlayer object received from the outside of this code fragment
    local Window = cLuaWindow(cWindow.wtHopper, 3, 3, "TestWnd");
    Window:SetSlot(a_Player, 0, cItem(E_ITEM_DIAMOND, 64));
    Window:SetOnClicked(OnClicked);
    Window:SetOnClosing(OnClosing);
    Window:SetOnSlotChanged(OnSlotChanged);
    
    -- Open the window:
    a_Player:OpenWindow(Window);
    
    ]], }, }, Inherits = "cWindow", }, cMap = { Desc = [[ This class encapsulates a single in-game colored map.

    The contents (i.e. pixel data) of a cMap are dynamically updated by each tracked {{cPlayer}} instance. Furthermore, a cMap maintains and periodically updates a list of map decorators, which are objects drawn on the map that can freely move (e.g. Player and item frame pointers). ]], Functions = { GetCenterX = { Returns = { { Type = "number", }, }, Notes = "Returns the X coord of the map's center.", }, GetCenterZ = { Returns = { { Type = "number", }, }, Notes = "Returns the Y coord of the map's center.", }, GetDimension = { Returns = { { Type = "eDimension", }, }, Notes = "Returns the dimension of the associated world.", }, GetHeight = { Returns = { { Type = "number", }, }, Notes = "Returns the height of the map.", }, GetID = { Returns = { { Type = "number", }, }, Notes = "Returns the numerical ID of the map. (The item damage value)", }, GetName = { Returns = { { Type = "string", }, }, Notes = "Returns the name of the map.", }, GetNumPixels = { Returns = { { Type = "number", }, }, Notes = "Returns the number of pixels in this map.", }, GetPixel = { Params = { { Name = "PixelX", Type = "number", }, { Name = "PixelZ", Type = "number", }, }, Returns = { { Name = "ColorID", Type = "number", }, }, Notes = "Returns the color of the specified pixel.", }, GetPixelWidth = { Returns = { { Type = "number", }, }, Notes = "Returns the width of a single pixel in blocks.", }, GetScale = { Returns = { { Type = "number", }, }, Notes = "Returns the scale of the map. Range: [0,4]", }, GetWidth = { Returns = { { Type = "number", }, }, Notes = "Returns the width of the map.", }, GetWorld = { Returns = { { Type = "cWorld", }, }, Notes = "Returns the associated world.", }, Resize = { Params = { { Name = "Width", Type = "number", }, { Name = "Height", Type = "number", }, }, Notes = "Resizes the map. WARNING: This will erase the pixel data.", }, SetPixel = { Params = { { Name = "PixelX", Type = "number", }, { Name = "PixelZ", Type = "number", }, { Name = "ColorID", Type = "number", }, }, Returns = { { Name = "IsSuccess", Type = "boolean", }, }, Notes = "Sets the color of the specified pixel. Returns false on error (Out of range).", }, SetPosition = { Params = { { Name = "CenterX", Type = "number", }, { Name = "CenterZ", Type = "number", }, }, Notes = "Relocates the map. The pixel data will not be modified.", }, SetScale = { Params = { { Name = "Scale", Type = "number", }, }, Notes = "Rescales the map. The pixel data will not be modified.", }, }, Constants = { E_BASE_COLOR_BLUE = { Notes = "", }, E_BASE_COLOR_BROWN = { Notes = "", }, E_BASE_COLOR_DARK_BROWN = { Notes = "", }, E_BASE_COLOR_DARK_GRAY = { Notes = "", }, E_BASE_COLOR_DARK_GREEN = { Notes = "", }, E_BASE_COLOR_GRAY_1 = { Notes = "", }, E_BASE_COLOR_GRAY_2 = { Notes = "", }, E_BASE_COLOR_LIGHT_BROWN = { Notes = "", }, E_BASE_COLOR_LIGHT_GRAY = { Notes = "", }, E_BASE_COLOR_LIGHT_GREEN = { Notes = "", }, E_BASE_COLOR_PALE_BLUE = { Notes = "", }, E_BASE_COLOR_RED = { Notes = "", }, E_BASE_COLOR_TRANSPARENT = { Notes = "", }, E_BASE_COLOR_WHITE = { Notes = "", }, }, }, cMapManager = { Desc = [[ This class is associated with a single {{cWorld}} instance and manages a list of maps. ]], Functions = { DoWithMap = { Params = { { Name = "MapID", Type = "number", }, { Name = "CallbackFunction", Type = "function", }, }, Returns = { { Type = "boolean", }, }, Notes = "If a map with the specified ID exists, calls the CallbackFunction for that map. The CallbackFunction has the following signature:

    function Callback({{cMap|Map}})
    Returns true if the map was found and the callback called, false if map not found.", }, }, }, cMojangAPI = { Desc = [[ Provides interface to various API functions that Mojang provides through their servers. Note that some of these calls will wait for a response from the network, and so shouldn't be used while the server is fully running (or at least when there are players connected) to avoid percepted lag.

    All the functions are static, call them using the cMojangAPI:Function() convention.

    Mojang uses two formats for UUIDs, short and dashed. Cuberite will accept either format for any functions taking a UUID. The MakeUUIDShort() and MakeUUIDDashed() functions are provided for plugins to use for conversion between the two formats.

    This class will cache values returned by the API service. The cache will hold the values for 7 days by default, after that, they will no longer be available. This is in order to not let the server get banned from using the API service, since they are rate-limited to 600 queries per 10 minutes. The cache contents also gets updated whenever a player successfully joins, since that makes the server contact the API service, too, and retrieve the relevant data.

    ]], Functions = { AddPlayerNameToUUIDMapping = { IsStatic = true, Params = { { Name = "PlayerName", Type = "string", }, { Name = "UUID", Type = "cUUID", }, }, Notes = "Adds the specified PlayerName-to-UUID mapping into the cache, with current timestamp.", }, GetPlayerNameFromUUID = { IsStatic = true, Params = { { Name = "UUID", Type = "cUUID", }, { Name = "UseOnlyCached", Type = "boolean", IsOptional = true, }, }, Returns = { { Name = "PlayerName", Type = "string", }, }, Notes = "Returns the playername that corresponds to the given UUID, or an empty string on error. If UseOnlyCached is false (the default), queries the Mojang servers if the UUID is not in the cache. The UUID can be either short or dashed.
    WARNING: Do NOT use this function with UseOnlyCached set to false while the server is running. Only use it when the server is starting up (inside the Initialize() method), otherwise you will lag the server severely.", }, GetUUIDFromPlayerName = { IsStatic = true, Params = { { Name = "PlayerName", Type = "string", }, { Name = "UseOnlyCached", Type = "boolean", IsOptional = true, }, }, Returns = { { Name = "UUID", Type = "string", }, }, Notes = "Returns the (short) UUID that corresponds to the given playername, or an empty string on error. If UseOnlyCached is false (the default), queries the Mojang servers if the playername is not in the cache.
    WARNING: Do NOT use this function with UseOnlyCached set to false while the server is running. Only use it when the server is starting up (inside the Initialize() method), otherwise you will lag the server severely.", }, GetUUIDsFromPlayerNames = { IsStatic = true, Params = { { Name = "PlayerNames", Type = "string", }, { Name = "UseOnlyCached", Type = "boolean", IsOptional = true, }, }, Returns = { { Type = "table", }, }, Notes = "Returns a table that contains the map, 'PlayerName' -> '(short) UUID', for all valid playernames in the input array-table. PlayerNames not recognized will not be set in the returned map. If UseOnlyCached is false (the default), queries the Mojang servers for the results that are not in the cache.
    WARNING: Do NOT use this function with UseOnlyCached set to false while the server is running. Only use it when the server is starting up (inside the Initialize() method), otherwise you will lag the server severely.", }, MakeUUIDDashed = { IsStatic = true, Params = { { Name = "UUID", Type = "cUUID", }, }, Returns = { { Name = "DashedUUID", Type = "string", }, }, Notes = "Converts the UUID to a dashed format (\"01234567-8901-2345-6789-012345678901\"). An alias for cUUID:ToLongString()", }, MakeUUIDShort = { IsStatic = true, Params = { { Name = "UUID", Type = "cUUID", }, }, Returns = { { Name = "ShortUUID", Type = "string", }, }, Notes = "Converts the UUID to a short format (without dashes, \"01234567890123456789012345678901\"). An alias for cUUID:ToShortString()", }, }, }, cMonster = { Desc = [[ This class is the base class for all computer-controlled mobs in the game.

    To spawn a mob in a world, use the {{cWorld}}:SpawnMob() function. ]], Functions = { BurnsInDaylight = { Returns = { { Type = "boolean", }, }, Notes = "Returns whether the mob burns in daylight.", }, CanBeLeashed = { Returns = { { Type = "boolean", }, }, Notes = "Returns whether the mob can be leashed.", }, FamilyFromType = { IsStatic = true, Params = { { Name = "MobType", Type = "eMonsterType", }, }, Returns = { { Name = "MobFamily", Type = "cMonster#eFamily", }, }, Notes = "Returns the mob family ({{cMonster#eFamily|mfXXX}} constants) based on the mob type ({{Globals#eMonsterType|mtXXX}} constants)", }, GetAge = { Returns = { { Type = "number", }, }, Notes = "Returns the age of the monster", }, GetCustomName = { Returns = { { Type = "string", }, }, Notes = "Gets the custom name of the monster. If no custom name is set, the function returns an empty string.", }, GetLeashedTo = { Returns = { { Name = "LeashedTo", Type = "cEntity", }, }, Notes = "Returns the entity to where this mob is leashed, returns nil if it's not leashed", }, GetMobFamily = { Returns = { { Name = "MobFamily", Type = "cMonster#eFamily", }, }, Notes = "Returns this mob's family ({{cMonster#eFamily|mfXXX}} constant)", }, GetMobType = { Returns = { { Name = "MobType", Type = "eMonsterType", }, }, Notes = "Returns the type of this mob ({{Globals#eMonsterType|mtXXX}} constant)", }, GetRelativeWalkSpeed = { Returns = { { Type = "number", }, }, Notes = "Returns the walk speed multiplier of this mob. Base is set in monsters.ini (will default to 1 if not set).", }, HasCustomName = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the monster has a custom name.", }, IsBaby = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the monster is a baby", }, IsCustomNameAlwaysVisible = { Returns = { { Type = "boolean", }, }, Notes = "Is the custom name of this monster always visible? If not, you only see the name when you sight the mob.", }, IsLeashed = { Returns = { { Type = "boolean", }, }, Notes = "Returns whether the monster is leashed to an entity.", }, LeashTo = { Params = { { Name = "Entity", Type = "cEntity", } }, Notes = "Leash the monster to an entity.", }, MobTypeToString = { IsStatic = true, Params = { { Name = "MobType", Type = "eMonsterType", }, }, Returns = { { Type = "string", }, }, Notes = "Returns the string representing the given mob type ({{Globals#eMonsterType|mtXXX}} constant), or empty string if unknown type.", }, MobTypeToVanillaName = { IsStatic = true, Params = { { Name = "MobType", Type = "eMonsterType", }, }, Returns = { { Type = "string", }, }, Notes = "Returns the vanilla name of the given mob type, or empty string if unknown type.", }, MoveToPosition = { Params = { { Name = "Position", Type = "Vector3d", }, }, Notes = "Start moving (using a pathfinder) towards the specified position", }, SetAge = { Params = { { Name = "Age", Type = "number", }, }, Notes = "Sets the age of the monster", }, SetBurnsInDaylight = { Params = { { Name = "BurnsInDaylight", Type = "boolean", }, }, Notes = "Sets whether the mob burns in daylight. Only evaluated at next burn-decision tick", }, SetCanBeLeashed = { Params = { { Name = "CanBeLeashed", Type = "boolean", } }, Notes = "Sets whether the mob can be leashed, for extensibility in plugins" }, SetCustomName = { Params = { { Name = "CustomName", Type = "string", }, }, Notes = "Sets the custom name of the monster. You see the name over the monster. If you want to disable the custom name, simply set an empty string.", }, SetCustomNameAlwaysVisible = { Params = { { Name = "IsCustomNameAlwaysVisible", Type = "boolean", }, }, Notes = "Sets the custom name visiblity of this monster. If it's false, you only see the name when you sight the mob. If it's true, you always see the custom name.", }, SetRelativeWalkSpeed = { Params = { { Name = "RelativeWalkSpeed", Type = "number", }, }, Notes = "Sets the walk speed multiplier of this mob. Base is set in monsters.ini (will default to 1 if not set).", }, StringToMobType = { IsStatic = true, Params = { { Name = "MobTypeString", Type = "string", }, }, Returns = { { Name = "MobType", Type = "eMonsterType", }, }, Notes = "Returns the mob type ({{Globals#eMonsterType|mtXXX}} constant) parsed from the string type (\"creeper\"), or mtInvalidType if unrecognized.", }, Unleash = { Params = { { Name = "ShouldDropLeashPickup", Type = "boolean", }, }, Notes = "Unleash the monster.", }, }, Constants = { mfAmbient = { Notes = "Family: ambient (bat)", }, mfHostile = { Notes = "Family: hostile (blaze, cavespider, creeper, enderdragon, enderman, ghast, giant, magmacube, silverfish, skeleton, slime, spider, witch, wither, zombie, zombiepigman)", }, mfPassive = { Notes = "Family: passive (chicken, cow, horse, irongolem, mooshroom, ocelot, pig, sheep, snowgolem, villager, wolf)", }, mfWater = { Notes = "Family: water (squid)", }, }, ConstantGroups = { eFamily = { Include = "mf.*", TextBefore = [[ Mobs are divided into families. The following constants are used for individual family types: ]], }, }, Inherits = "cPawn", }, cObjective = { Desc = [[ This class represents a single scoreboard objective. ]], Functions = { AddScore = { Params = { { Name = "string", Type = "string", }, { Name = "number", Type = "number", }, }, Returns = { { Name = "Score", Type = "", }, }, Notes = "Adds a value to the score of the specified player and returns the new value.", }, GetDisplayName = { Returns = { { Type = "string", }, }, Notes = "Returns the display name of the objective. This name will be shown to the connected players.", }, GetName = { Returns = { { Type = "string", }, }, Notes = "Returns the internal name of the objective.", }, GetScore = { Params = { { Name = "string", Type = "string", }, }, Returns = { { Name = "Score", Type = "", }, }, Notes = "Returns the score of the specified player.", }, GetType = { Returns = { { Name = "eType", Type = "", }, }, Notes = "Returns the type of the objective. (i.e what is being tracked)", }, Reset = { Notes = "Resets the scores of the tracked players.", }, ResetScore = { Params = { { Name = "string", Type = "string", }, }, Notes = "Reset the score of the specified player.", }, SetDisplayName = { Params = { { Name = "string", Type = "string", }, }, Notes = "Sets the display name of the objective.", }, SetScore = { Params = { { Name = "string", Type = "string", }, { Name = "Score", Type = "", }, }, Notes = "Sets the score of the specified player.", }, SubScore = { Params = { { Name = "string", Type = "string", }, { Name = "number", Type = "number", }, }, Returns = { { Name = "Score", Type = "", }, }, Notes = "Subtracts a value from the score of the specified player and returns the new value.", }, }, Constants = { otAchievement = { Notes = "", }, otDeathCount = { Notes = "", }, otDummy = { Notes = "", }, otHealth = { Notes = "", }, otPlayerKillCount = { Notes = "", }, otStat = { Notes = "", }, otStatBlockMine = { Notes = "", }, otStatEntityKill = { Notes = "", }, otStatEntityKilledBy = { Notes = "", }, otStatItemBreak = { Notes = "", }, otStatItemCraft = { Notes = "", }, otStatItemUse = { Notes = "", }, otTotalKillCount = { Notes = "", }, }, }, cPainting = { Desc = "This class represents a painting in the world. These paintings are special and different from Vanilla in that they can be critical-hit.", Functions = { GetName = { Returns = { { Type = "string", }, }, Notes = "Returns the name of the painting", }, }, }, cPawn = { Desc = "cPawn is a controllable pawn object, controlled by either AI or a player. cPawn inherits all functions and members of {{cEntity}}\ ", Functions = { AddEntityEffect = { Params = { { Name = "EffectType", Type = "cEntityEffect#eType", }, { Name = "EffectDurationTicks", Type = "number", }, { Name = "EffectIntensity", Type = "number", }, { Name = "DistanceModifier", Type = "number", }, }, Notes = "Applies an entity effect. Checks with plugins if they allow the addition. EffectIntensity is the level of the effect (0 = Potion I, 1 = Potion II, etc). DistanceModifier is the scalar multiplied to the potion duration (only applies to splash potions).", }, ClearEntityEffects = { Notes = "Removes all currently applied entity effects", }, FindTeleportDestination = { { Params = { { Name = "World", Type = "cWorld", }, { Name = "HeightRequired", Type = "number", }, { Name = "NumTries", Type = "number", }, { Name = "Destination", Type = "Vector3d", }, { Name = "MinBoxCorner", Type = "Vector3i", }, { Name = "MaxBoxCorner", Type = "Vector3i", }, }, Notes = "Function to find suitable teleport destination in or below box. Returns true and places result in Destination if found, otherwise returns false. Details at: {{https://minecraft.wiki/w/Enderman#Teleportation}}.", }, { Params = { { Name = "World", Type = "cWorld", }, { Name = "HeightRequired", Type = "number", }, { Name = "NumTries", Type = "number", }, { Name = "Destination", Type = "Vector3d", }, { Name = "BoundingBox", Type = "cBoundingBox", }, }, Notes = "Function to find suitable teleport destination in or below box. Returns true and places result in Destination if found, otherwise returns false. Details at: {{https://minecraft.wiki/w/Enderman#Teleportation}}.", }, { Params = { { Name = "World", Type = "cWorld", }, { Name = "HeightRequired", Type = "number", }, { Name = "NumTries", Type = "number", }, { Name = "Centre", Type = "Vector3i", }, { Name = "HalfCubeWidth", Type = "number", }, }, Notes = "Function to find suitable teleport destination in or below box. Returns true and places result in Destination if found, otherwise returns false. Details at: {{https://minecraft.wiki/w/Enderman#Teleportation}}.", }, }, HasEntityEffect = { Params = { { Name = "EffectType", Type = "cEntityEffect#eType", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true, if the supplied entity effect type is currently applied", }, RemoveEntityEffect = { Params = { { Name = "EffectType", Type = "cEntityEffect#eType", }, }, Notes = "Removes a currently applied entity effect", }, }, Inherits = "cEntity", }, cEnderCrystal = { Desc = [[ This class represents an ender crystal. This entity can be spawned by using {{cWorld#SpawnEnderCrystal_1|cWorld:SpawnEnderCrystal}}. ]], Functions = { DisplaysBeam = { Returns = { { Type = "boolean", }, Notes = "Returns true if the ender crystal displays its beam.", }, }, GetBeamTarget = { Returns = { { Type = "Vector3i", }, }, Notes = "Returns the Block position the beam is pointing to.", }, SetBeamTarget = { Params = { { Name = "BeamTarget", Type = "Vector3i", }, }, Notes = "Sets the target of the beam of this ender crystal.", }, SetDisplayBeam = { Params = { { Name = "DisplaysBeam", Type = "boolean", }, Notes = "Sets if the ender crystal should display its beam.", }, }, SetShowBottom = { Params = { { Name = "ShowsBottom", Type = "boolean", }, Notes = "Sets if the ender crystal should broadcast its bedrock base.", }, }, ShowsBottom = { Returns = { { Type = "boolean", }, Notes = "Returns true if the bedrock base is displayed.", }, }, }, Inherits = "cEntity", }, cExpOrb = { Desc = [[ This class represents an experience orb. This entity can be spawned by using {{cWorld#SpawnExperienceOrb_1|cWorld:SpawnExperienceOrb}}. It's also spawned when a monster is killed or a player is mining coal. The default lifetime of an experience orb is 5 mins. ]], Functions = { GetAge = { Returns = { { Type = "number" }, }, Notes = "Returns the number of ticks that this experience orb has existed.", }, SetAge = { Params = { { Type = "number", }, }, Notes = "Sets the experience orb's age, in ticks.", }, GetReward = { Returns = { { Type = "number", }, }, Notes = "Returns the experience amount.", }, SetReward = { Params = { { Type = "number", }, }, Notes = "Sets the experience amount.", }, }, Inherits = "cEntity", }, cFallingBlock = { Desc = [[ This class represents a falling block. This entity can be spawned by using {{cWorld#SpawnFallingBlock_1|cWorld:SpawnFallingBlock}}. ]], Functions = { GetBlockType = { Returns = { { Name = "BlockType", Type = "number", } }, Notes = "Returns the block type of the falling block.", }, GetBlockMeta = { Returns = { { Name = "BlockMeta", Type = "number", } }, Notes = "Returns the block meta of the falling block.", }, }, Inherits = "cEntity", }, cBoat = { Desc = [[ This class represents a boat. This entity can be spawned by using {{cWorld#SpawnBoat_1|cWorld:SpawnBoat}}. ]], Functions = { GetMaterial = { Returns = { { Name = "Material", Type = "cBoat#eMaterial", }, }, Notes = "Returns the material of the boat.", }, MaterialToString = { IsStatic = true, Params = { { Name = "Material", Type = "cBoat#eMaterial", }, }, Returns = { { Name = "Material", Type = "string", }, }, Notes = "Returns the boat material as a string.", }, ItemToMaterial = { IsStatic = true, Params = { { Name = "Item", Type = "cItem", }, }, Returns = { { Name = "Material", Type = "cBoat#eMaterial", }, }, Notes = "Returns the eMaterial that should be used for a boat created from the specified item. Returns bmOak if not a boat item.", }, MaterialToItem = { IsStatic = true, Params = { { Name = "Material", Type = "cBoat#eMaterial", }, }, Returns = { { Name = "Item", Type = "cItem", }, }, Notes = "Returns the boat item of the boat material", }, StringToMaterial = { IsStatic = true, Params = { { Name = "Material", Type = "string", }, }, Returns = { { Name = "Material", Type = "cBoat#eMaterial", }, }, Notes = "Returns the boat material for the passed string. Returns oak if not valid.", }, SetMaterial = { Params = { { Name = "Material", Type = "cBoat#eMaterial", }, }, Notes = "Set the material of the boat.", }, }, Constants = { bmOak = { Notes = "", }, bmSpruce = { Notes = "", }, bmBirch = { Notes = "", }, bmJungle = { Notes = "", }, bmAcacia = { Notes = "", }, bmDarkOak = { Notes = "", }, }, ConstantGroups = { eMaterial = { Include = "bm.*", TextBefore = "These constans are the different wood materials of the boat.", }, }, Inherits = "cEntity", }, cPickup = { Desc = [[ This class represents a pickup entity (an item that the player or mobs can pick up). It is also commonly known as "drops". With this class you could create your own "drop" or modify those created automatically. The default lifetime of a pickup is 5 mins. ]], Functions = { CanCombine = { Returns = { { Type = "boolean" } }, Notes = "Returns whether this pickup is allowed to combine with other similar pickups.", }, CollectedBy = { Params = { { Name = "Entity", Type = "cEntity", }, }, Returns = { { Name = "WasCollected", Type = "boolean", }, }, Notes = "Tries to make the entity collect the pickup. Returns true if the pickup was collected, at least partially.", }, GetAge = { Returns = { { Type = "number", }, }, Notes = "Returns the number of ticks that the pickup has existed.", }, GetItem = { Returns = { { Type = "cItem", }, }, Notes = "Returns the item represented by this pickup", }, GetLifetime = { Returns = { { Type = "number", }, }, Notes = "Returns the total length of this pickup's lifespan, in ticks.", }, IsCollected = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if this pickup has already been collected (is waiting to be destroyed)", }, IsPlayerCreated = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the pickup was created by a player", }, SetAge = { Params = { { Name = "AgeTicks", Type = "number", }, }, Notes = "Sets the pickup's age, in ticks.", }, SetCanCombine = { Params = { { Name = "CanCombine", Type = "boolean", }, }, Notes = "Sets whether this pickup is allowed to combine with other similar pickups.", }, SetLifetime = { Params = { { Name = "LifeTimeInTicks", Type = "number", }, }, Notes = "Sets the total lifespan of this pickup before it despawns, in ticks. Does not reset the age of the pickup, use SetAge(0). If new lifetime is less than the current age, pickup will despawn.", }, }, Inherits = "cEntity", }, cPlayer = { Desc = [[ This class describes a player in the server. cPlayer inherits all functions and members of {{cPawn|cPawn}}. It handles all the aspects of the gameplay, such as hunger, sprinting, inventory etc. ]], Functions = { AddFoodExhaustion = { Params = { { Name = "Exhaustion", Type = "number", }, }, Notes = "Adds the specified number to the food exhaustion. Only positive numbers expected.", }, CalcLevelFromXp = { IsStatic = true, Params = { { Name = "XPAmount", Type = "number", }, }, Returns = { { Type = "number", }, }, Notes = "Returns the level which is reached with the specified amount of XP. Inverse of XpForLevel().", }, CanFly = { Returns = { { Type = "boolean", }, }, Notes = "Returns if the player is able to fly.", }, CanMobsTarget = { Returns = { { Type = "boolean", }, }, Notes = "Returns if the player can be targeted by mobs.", }, CloseWindow = { Params = { { Name = "CanRefuse", Type = "boolean", IsOptional = true, }, }, Notes = "Closes the currently open UI window. If CanRefuse is true (default), the window may refuse the closing.", }, CloseWindowIfID = { Params = { { Name = "WindowID", Type = "number", }, { Name = "CanRefuse", Type = "boolean", IsOptional = true, }, }, Notes = "Closes the currently open UI window if its ID matches the given ID. If CanRefuse is true (default), the window may refuse the closing.", }, DeltaExperience = { Params = { { Name = "DeltaXP", Type = "number", }, }, Returns = { { Type = "number", }, }, Notes = "Adds or removes XP from the current XP amount. Won't allow XP to go negative. Returns the new experience, -1 on error (XP overflow).", }, Feed = { Params = { { Name = "AddFood", Type = "number", }, { Name = "AddSaturation", Type = "number", }, }, Returns = { { Type = "boolean", }, }, Notes = "Tries to add the specified amounts to food level and food saturation level (only positive amounts expected). Returns true if player was hungry and the food was consumed, false if too satiated.", }, ForceSetSpeed = { Params = { { Name = "Direction", Type = "Vector3d", }, }, Notes = "Forces the player to move to the given direction.", }, Freeze = { Params = { { Name = "Location", Type = "Vector3d", }, }, Notes = "Teleports the player to \"Location\" and prevents them from moving, locking them in place until unfreeze() is called", }, GetClientHandle = { Returns = { { Type = "cClientHandle", }, }, Notes = "Returns the client handle representing the player's connection. May be nil (AI players).", }, GetColor = { Returns = { { Type = "string", }, }, Notes = "Returns the full color code to be used for this player's messages (based on their rank). Prefix player messages with this code.", }, GetCurrentXp = { Returns = { { Type = "number", }, }, Notes = "Returns the current amount of XP", }, GetCustomName = { Returns = { { Type = "string", }, }, Notes = "Returns the custom name of this player. If the player hasn't a custom name, it will return an empty string.", }, GetDraggingItem = { Returns = { { Type = "cItem", }, }, Notes = "Returns the item the player is dragging in a UI window." }, GetEffectiveGameMode = { Returns = { { Name = "GameMode", Type = "eGameMode", }, }, Notes = "(OBSOLETE) Returns the current resolved game mode of the player. If the player is set to inherit the world's gamemode, returns that instead. See also GetGameMode() and IsGameModeXXX() functions. Note that this function is the same as GetGameMode(), use that function instead.", }, GetEquippedItem = { Returns = { { Type = "cItem", }, }, Notes = "Returns the item that the player is currently holding; empty item if holding nothing.", }, GetEyeHeight = { Returns = { { Type = "number", }, }, Notes = "Returns the height of the player's eyes, in absolute coords", }, GetEyePosition = { Returns = { { Name = "EyePositionVector", Type = "Vector3d", }, }, Notes = "Returns the position of the player's eyes, as a {{Vector3d}}", }, GetFloaterID = { Returns = { { Type = "number", }, }, Notes = "Returns the Entity ID of the fishing hook floater that belongs to the player. Returns -1 if no floater is associated with the player. FIXME: Undefined behavior when the player has used multiple fishing rods simultanously.", }, GetFlyingMaxSpeed = { Returns = { { Type = "number", }, }, Notes = "Returns the maximum flying speed, relative to the default game flying speed. Defaults to 1, but plugins may modify it for faster or slower flying.", }, GetFoodExhaustionLevel = { Returns = { { Type = "number", }, }, Notes = "Returns the food exhaustion level", }, GetFoodLevel = { Returns = { { Type = "number", }, }, Notes = "Returns the food level (number of half-drumsticks on-screen)", }, GetFoodSaturationLevel = { Returns = { { Type = "number", }, }, Notes = "Returns the food saturation (overcharge of the food level, is depleted before food level)", }, GetFoodTickTimer = { Returns = { { Type = "number", }, }, Notes = "Returns the number of ticks past the last food-based heal or damage action; when this timer reaches 80, a new heal / damage is applied.", }, GetGameMode = { Returns = { { Name = "GameMode", Type = "eGameMode", }, }, Notes = "Returns the player's gamemode. The player may have their gamemode unassigned, in which case they inherit the gamemode from the current {{cWorld|world}}.
    NOTE: Instead of comparing the value returned by this function to the gmXXX constants, use the IsGameModeXXX() functions. These functions handle the gamemode inheritance automatically.", }, GetInventory = { Returns = { { Name = "Inventory", Type = "cInventory", }, }, Notes = "Returns the player's inventory", }, GetIP = { Returns = { { Type = "string", }, }, Notes = "Returns the IP address of the player, if available. Returns an empty string if there's no IP to report.", }, GetLastBedPos = { Returns = { { Type = "Vector3i", }, }, Notes = "Returns the player's respawn position. The player is guaranteed to respawn from death here if {{cPlayer}}:IsRespawnPointForced is true or if a bed exists at this position.", }, GetMaxSpeed = { Returns = { { Type = "number", }, }, Notes = "Returns the player's current maximum speed, relative to the game default speed. Takes into account the sprinting / flying status.", }, GetName = { Returns = { { Type = "string", }, }, Notes = "Returns the player's name", }, GetNormalMaxSpeed = { Returns = { { Type = "number", }, }, Notes = "Returns the player's maximum walking speed, relative to the game default speed. Defaults to 1, but plugins may modify it for faster or slower walking.", }, GetPermissions = { Returns = { { Type = "table", }, }, Notes = "Returns an array-table of all permissions (strings) that the player has assigned to them through their rank.", }, GetPlayerListName = { Returns = { { Type = "string", }, }, Notes = "Returns the name that is used in the playerlist.", }, GetPrefix = { Returns = { { Type = "string", }, }, Notes = "Returns the prefix to player names for messages (based on their rank), may contain @ format codes.", }, GetRestrictions = { Returns = { { Type = "table", }, }, Notes = "Returns an array-table of all the restrictions that the player has assigned to them.", }, GetSprintingMaxSpeed = { Returns = { { Type = "number", }, }, Notes = "Returns the player's maximum sprinting speed, relative to the game default speed. Defaults to 1.3, but plugins may modify it for faster or slower sprinting.", }, GetSkinParts = { Returns = { { Type = "number", }, }, Notes = "Returns the player's current set of skin part flags. This is a bitwise OR of various {{Globals#eSkinPart|eSkinPart}} constants. Note that HasSkinPart may be easier to use in most situations.", }, GetStatistics = { Returns = { { Type = "StatisticsManager", }, }, Notes = "Returns the player's statistics manager." }, GetSuffix = { Returns = { { Type = "string", }, }, Notes = "Returns the suffix to player names for messages (based on their rank), may contain @ format codes.", }, GetTeam = { Returns = { { Type = "cTeam", }, }, Notes = "Returns the team that the player belongs to, or nil if none.", }, GetThrowSpeed = { Params = { { Name = "SpeedCoeff", Type = "number", }, }, Returns = { { Type = "Vector3d", }, }, Notes = "Returns the speed vector for an object thrown with the specified speed coeff. Basically returns the normalized look vector multiplied by the coeff, with a slight random variation.", }, GetThrowStartPos = { Returns = { { Type = "Vector3d", }, }, Notes = "Returns the position where the projectiles should start when thrown by this player.", }, GetUUID = { Returns = { { Type = "string", }, }, Notes = "Returns the (short) UUID that the player is using. Could be empty string for players that don't have a Mojang account assigned to them (in the future, bots for example).", }, GetWindow = { Returns = { { Type = "cWindow", }, }, Notes = "Returns the currently open UI window. If the player doesn't have any UI window open, returns the inventory window.", }, GetXpLevel = { Returns = { { Type = "number", }, }, Notes = "Returns the current XP level (based on current XP amount).", }, GetXpLifetimeTotal = { Returns = { { Type = "number", }, }, Notes = "Returns the amount of XP that has been accumulated throughout the player's lifetime.", }, GetXpPercentage = { Returns = { { Type = "number", }, }, Notes = "Returns the percentage of the experience bar - the amount of XP towards the next XP level. Between 0 and 1.", }, HasCustomName = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the player has a custom name.", }, HasPermission = { Params = { { Name = "PermissionString", Type = "string", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if the player has the specified permission", }, HasSkinPart = { Params = { { Name = "Part", Type = "eSkinPart", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if the player has the specified skin part enabled", }, Heal = { Params = { { Name = "HitPoints", Type = "number", }, }, Notes = "Heals the player by the specified amount of HPs. Only positive amounts are expected. Sends a health update to the client.", }, IsEating = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the player is currently eating the item in their hand.", }, IsFireproof = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if a player is fireproof. This is when the flag has been explicitly set, or the player is in creative or spectator mode.", }, IsFishing = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the player is currently fishing", }, IsFlying = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the player is flying.", }, IsFrozen = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the player is frozen. See Freeze()", }, IsGameModeAdventure = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the player is in the gmAdventure gamemode, or has their gamemode unset and the world is a gmAdventure world.", }, IsGameModeCreative = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the player is in the gmCreative gamemode, or has their gamemode unset and the world is a gmCreative world.", }, IsGameModeSpectator = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the player is in the gmSpectator gamemode, or has their gamemode unset and the world is a gmSpectator world.", }, IsGameModeSurvival = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the player is in the gmSurvival gamemode, or has their gamemode unset and the world is a gmSurvival world.", }, IsInBed = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the player is currently lying in a bed.", }, IsLeftHanded = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the player's left hand is dominant.", }, IsRespawnPointForced = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the player unconditionally respawns from death at the position given by {{cPlayer}}:GetLastBedPos with no bed checks performed.", }, IsSatiated = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the player is satiated (cannot eat).", }, LoadRank = { Notes = "Reloads the player's rank, message visuals and permissions from the {{cRankManager}}, based on the player's current rank.", }, OpenWindow = { Params = { { Name = "Window", Type = "cWindow", }, }, Notes = "Opens the specified UI window for the player.", }, PermissionMatches = { IsStatic = true, Params = { { Name = "Permission", Type = "string", }, { Name = "Template", Type = "string", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if the specified permission matches the specified template. The template may contain asterisk as a wildcard for any word.", }, PlaceBlock = { Params = { { Name = "BlockPos", Type = "Vector3i", }, { Name = "BlockType", Type = "number", }, { Name = "BlockMeta", Type = "number", }, }, Returns = { { Type = "boolean", }, }, Notes = "Places a block while impersonating the player. The {{OnPlayerPlacingBlock|HOOK_PLAYER_PLACING_BLOCK}} hook is called before the placement, and if it succeeds, the block is placed and the {{OnPlayerPlacedBlock|HOOK_PLAYER_PLACED_BLOCK}} hook is called. Returns true iff the block is successfully placed.", }, ReplaceOneEquippedItemTossRest = { Params = { { Name = "Item", Type = "cItem", }, }, Notes = "Removes one item from the the current equipped item stack, and attempts to add the specified item stack back to the same slot. If it is not possible to place the item in the same slot, tries to place the specified item elsewhere in the inventory. If this is not possible, then any remaining items are tossed. If the currently equipped slot is empty, its contents are simply set to the given Item.", }, Respawn = { Notes = "Restores the health, extinguishes fire, makes visible and sends the Respawn packet.", }, SendAboveActionBarMessage = { Params = { { Name = "Message", Type = "string", }, }, Notes = "Sends the specified message to the player (shows above action bar).", }, SendBlocksAround = { Params = { { Name = "BlockX", Type = "number", }, { Name = "BlockY", Type = "number", }, { Name = "BlockZ", Type = "number", }, { Name = "BlockRange", Type = "number", IsOptional = true, }, }, Notes = "Sends all the world's blocks in BlockRange from the specified coords to the player, as a BlockChange packet. Range defaults to 1 (only one block sent).", }, SendMessage = { { Params = { { Name = "Message", Type = "string", }, }, Notes = "Sends the specified message to the player.", }, { Params = { { Name = "Message", Type = "cCompositeChat", }, }, Notes = "Sends the {{cCompositeChat}} to the player, using a severity defined by the CompositeChat's MessageType.", }, }, SendMessageRaw = { Params = { { Name = "Json", Type = "string", }, { Name = "eChatType", Type = "number", IsOptional = true, } }, Notes = "Sends the specified json string to the player. The optional value eChatType (default ctChatBox) can be ctChatBox, ctSystem or ctAboveActionBar. You can use {{cJson}} to build a json string.", }, SendMessageFailure = { Params = { { Name = "Message", Type = "string", }, }, Notes = "Prepends Rose [INFO] / colours entire text (depending on ShouldUseChatPrefixes()) and sends message to player. For a command that failed to run because of insufficient permissions, etc.", }, SendMessageFatal = { Params = { { Name = "Message", Type = "string", }, }, Notes = "Prepends Red [FATAL] / colours entire text (depending on ShouldUseChatPrefixes()) and sends message to player. For something serious, such as a plugin crash, etc.", }, SendMessageInfo = { Params = { { Name = "Message", Type = "string", }, }, Notes = "Prepends Yellow [INFO] / colours entire text (depending on ShouldUseChatPrefixes()) and sends message to player. Informational message, such as command usage, etc.", }, SendMessagePrivateMsg = { Params = { { Name = "Message", Type = "string", }, { Name = "SenderName", Type = "string", }, }, Notes = "Prepends Light Blue [MSG: *SenderName*] / prepends SenderName and colours entire text (depending on ShouldUseChatPrefixes()) and sends message to player. For private messaging.", }, SendMessageSuccess = { Params = { { Name = "Message", Type = "string", }, }, Notes = "Prepends Green [INFO] / colours entire text (depending on ShouldUseChatPrefixes()) and sends message to player. Success notification.", }, SendMessageWarning = { Params = { { Name = "Message", Type = "string", }, }, Notes = "Prepends Rose [WARN] / colours entire text (depending on ShouldUseChatPrefixes()) and sends message to player. Denotes that something concerning, such as plugin reload, is about to happen.", }, SendRotation = { Params = { { Name = "YawDegrees", Type = "number", }, { Name = "PitchDegrees", Type = "number", }, }, Notes = "Sends the specified rotation to the player, forcing them to look that way", }, SendSystemMessage = { Params = { { Name = "Message", Type = "string", }, }, Notes = "Sends the specified message to the player.", }, SetBedPos = { Params = { { Name = "Position", Type = "Vector3i", }, { Name = "World", Type = "cWorld", IsOptional = true, }, }, Notes = "Sets the position and world of the player's bed. If the world is not specified, it is set to the player's current world. The player will respawn at this position and world upon death if there is a bed there.", }, SetCanFly = { Params = { { Name = "CanFly", Type = "boolean", }, }, Notes = "Sets if the player can fly or not.", }, SetCrouch = { Params = { { Name = "IsCrouched", Type = "boolean", }, }, Notes = "Sets the crouch state, broadcasts the change to other players.", }, SetCurrentExperience = { Params = { { Name = "XPAmount", Type = "number", }, }, Returns = { { Type = "boolean", }, }, Notes = "Sets the current amount of experience (and indirectly, the XP level).", }, SetCustomName = { Params = { { Name = "CustomName", Type = "string", }, }, Notes = "Sets the custom name for this player. If you want to disable the custom name, simply set an empty string. The custom name will be used in the tab-list, in the player nametag and in the tab-completion.", }, SetDraggingItem = { Params = { { Name = "Item", Type = "cItem", }, }, Notes = "Sets the item that the player is dragging in a UI window. If no UI window is open, this function does nothing." }, SetElytraFlight = { Params = { { Name = "IsElytraFlying", Type = "boolean", }, }, Notes = "Sets whether the player is elytra flying or not.", }, SetFlying = { Params = { { Name = "IsFlying", Type = "boolean", }, }, Notes = "Sets if the player is flying or not.", }, SetFlyingMaxSpeed = { Params = { { Name = "FlyingMaxSpeed", Type = "number", }, }, Notes = "Sets the flying maximum speed, relative to the game default speed. The default value is 1. Sends the updated speed to the client.", }, SetFoodExhaustionLevel = { Params = { { Name = "ExhaustionLevel", Type = "number", }, }, Notes = "Sets the food exhaustion to the specified level.", }, SetFoodLevel = { Params = { { Name = "FoodLevel", Type = "number", }, }, Notes = "Sets the food level (number of half-drumsticks on-screen)", }, SetFoodSaturationLevel = { Params = { { Name = "FoodSaturationLevel", Type = "number", }, }, Notes = "Sets the food saturation (overcharge of the food level).", }, SetFoodTickTimer = { Params = { { Name = "FoodTickTimer", Type = "number", }, }, Notes = "Sets the number of ticks past the last food-based heal or damage action; when this timer reaches 80, a new heal / damage is applied.", }, SetGameMode = { Params = { { Name = "NewGameMode", Type = "eGameMode", }, }, Notes = "Sets the gamemode for the player. The new gamemode overrides the world's default gamemode, unless it is set to gmInherit.", }, SetIsFishing = { Params = { { Name = "IsFishing", Type = "boolean", }, { Name = "FloaterEntityID", Type = "number", IsOptional = true, }, }, Notes = "Sets the 'IsFishing' flag for the player. The floater entity ID is expected for the true variant, it can be omitted when IsFishing is false. FIXME: Undefined behavior when multiple fishing rods are used simultanously", }, SetLeftHanded = { Params = { { Name = "IsLeftHanded", Type = "boolean", }, }, Notes = "Sets the dominant hand of the player.", }, SetNormalMaxSpeed = { Params = { { Name = "NormalMaxSpeed", Type = "number", }, }, Notes = "Sets the normal (walking) maximum speed, relative to the game default speed. The default value is 1. Sends the updated speed to the client, if appropriate.", }, SetRespawnPosition = { Params = { { Name = "Position", Type = "Vector3i", }, { Name = "World", Type = "cWorld", }, }, Notes = "Sets the position and world of the player's respawn point. The player will respawn at this position and world upon death.", }, SetSprint = { Params = { { Name = "IsSprinting", Type = "boolean", }, }, Notes = "Sets whether the player is sprinting or not.", }, SetSkinParts = { Params = { { Name = "Parts", Type = "number", }, }, Notes = "Sets the skin part flags of the player. The value should be a bitwise OR of several {{Globals#eSkinPart|eSkinPart}} constants.", }, SetSprintingMaxSpeed = { Params = { { Name = "SprintingMaxSpeed", Type = "number", }, }, Notes = "Sets the sprinting maximum speed, relative to the game default speed. The default value is 1.3. Sends the updated speed to the client, if appropriate.", }, SetTeam = { Params = { { Name = "Team", Type = "cTeam", }, }, Notes = "Moves the player to the specified team.", }, SetVisible = { Params = { { Name = "IsVisible", Type = "boolean", }, }, Notes = "Sets the player visibility to other players", }, SpectateEntity = { Params = { { Name = "Target", Type = "cEntity", }, }, Notes = "Spectates the target entity. Does not change the player's gamemode to spectator mode. When called with self or nil as the target, resets the spectation.", }, TossEquippedItem = { Params = { { Name = "Amount", Type = "number", IsOptional = true, }, }, Notes = "Tosses the item that the player has selected in their hotbar. Amount defaults to 1.", }, TossHeldItem = { Params = { { Name = "Amount", Type = "number", IsOptional = true, }, }, Notes = "Tosses the item held by the cursor, when the player is in a UI window. Amount defaults to 1.", }, TossPickup = { Params = { { Name = "Item", Type = "cItem", }, }, Notes = "Tosses a pickup newly created from the specified item.", }, Unfreeze = { Notes = "Allows the player to move again, canceling the effects of Freeze()", }, XpForLevel = { IsStatic = true, Params = { { Name = "XPLevel", Type = "number", }, }, Returns = { { Type = "number", }, }, Notes = "Returns the total amount of XP needed for the specified XP level. Inverse of CalcLevelFromXp().", }, }, Constants = { MAX_FOOD_LEVEL = { Notes = "The maximum food level value. When the food level is at this value, the player cannot eat.", }, MAX_HEALTH = { Notes = "The maximum health value", }, }, Inherits = "cPawn", }, -- cPlayer cRoot = { Desc = [[ This class represents the root of Cuberite's object hierarchy. There is always only one cRoot object. It manages and allows querying all the other objects, such as {{cServer}}, {{cPluginManager}}, individual {{cWorld|worlds}} etc.

    To get the singleton instance of this object, you call the cRoot:Get() function. Then you can call the individual functions on this object. Note that some of the functions are static and don't need the instance, they are to be called directly on the cRoot class, such as cRoot:GetPhysicalRAMUsage() ]], Functions = { BroadcastChat = { { Params = { { Name = "MessageText", Type = "string", }, { Name = "MessageType", Type = "eMessageType", }, }, Notes = "Broadcasts a message to all players, with its message type set to MessageType (default: mtCustom).", }, { Params = { { Name = "CompositeChat", Type = "cCompositeChat", }, }, Notes = "Broadcasts a {{cCompositeChat|composite chat message}} to all players.", }, }, BroadcastChatDeath = { Params = { { Name = "MessageText", Type = "string", }, }, Notes = "Broadcasts the specified message to all players, with its message type set to mtDeath. Use for when a player has died.", }, BroadcastChatFailure = { Params = { { Name = "MessageText", Type = "string", }, }, Notes = "Broadcasts the specified message to all players, with its message type set to mtFailure. Use for a command that failed to run because of insufficient permissions, etc.", }, BroadcastChatFatal = { Params = { { Name = "MessageText", Type = "string", }, }, Notes = "Broadcasts the specified message to all players, with its message type set to mtFatal. Use for a plugin that crashed, or similar.", }, BroadcastChatInfo = { Params = { { Name = "MessageText", Type = "string", }, }, Notes = "Broadcasts the specified message to all players, with its message type set to mtInfo. Use for informational messages, such as command usage.", }, BroadcastChatJoin = { Params = { { Name = "MessageText", Type = "string", }, }, Notes = "Broadcasts the specified message to all players, with its message type set to mtJoin. Use for players joining the server.", }, BroadcastChatLeave = { Params = { { Name = "MessageText", Type = "string", }, }, Notes = "Broadcasts the specified message to all players, with its message type set to mtLeave. Use for players leaving the server.", }, BroadcastChatSuccess = { Params = { { Name = "MessageText", Type = "string", }, }, Notes = "Broadcasts the specified message to all players, with its message type set to mtSuccess. Use for success messages.", }, BroadcastChatWarning = { Params = { { Name = "MessageText", Type = "string", }, }, Notes = "Broadcasts the specified message to all players, with its message type set to mtWarning. Use for concerning events, such as plugin reload etc.", }, BroadcastPlayerListsHeaderFooter = { Params = { { Type = "cCompositeChat", Name = "Header", }, { Type = "cCompositeChat", Name = "Footer", }, }, Desc = "Broadcasts the header and footer of the player list to all players.", }, DoWithPlayerByUUID = { Params = { { Name = "PlayerUUID", Type = "cUUID", }, { Name = "CallbackFunction", Type = "function", }, }, Returns = { { Type = "boolean", }, }, Notes = "If there is the player with the uuid, calls the CallbackFunction with the {{cPlayer}} parameter representing the player. The CallbackFunction has the following signature:

    function Callback({{cPlayer|Player}})
    The function returns false if the player was not found, or whatever bool value the callback returned if the player was found.", }, FindAndDoWithPlayer = { Params = { { Name = "PlayerName", Type = "string", }, { Name = "CallbackFunction", Type = "function", }, }, Returns = { { Type = "boolean", }, }, Notes = "Calls the given callback function for the player with the name best matching the name string provided.
    This function is case-insensitive and will match partial names.
    Returns false if player not found or there is ambiguity, true otherwise. The CallbackFunction has the following signature:
    function Callback({{cPlayer|Player}})
    ", }, ForEachPlayer = { Params = { { Name = "CallbackFunction", Type = "function", }, }, Returns = { { Type = "boolean", }, }, Notes = "Calls the given callback function for each player. The callback function has the following signature:
    function Callback({{cPlayer|cPlayer}})
    ", }, ForEachWorld = { Params = { { Name = "CallbackFunction", Type = "function", }, }, Returns = { { Type = "boolean", }, }, Notes = "Calls the given callback function for each world. The callback function has the following signature:
    function Callback({{cWorld|cWorld}})
    . Returns false if a callback aborts, otherwise true.", }, Get = { IsStatic = true, Returns = { { Type = "cRoot", }, }, Notes = "Returns the one and only cRoot object.", }, GetBrewingRecipe = { IsStatic = true, Params = { { Name = "Bottle", Type = "cItem", }, { Name = "Ingredient", Type = "cItem", }, }, Returns = { { Type = "cItem", }, }, Notes = "Returns the result item, if a recipe has been found to brew the Ingredient into Bottle. If no recipe is found, returns no value.", }, GetBuildCommitID = { IsStatic = true, Returns = { { Type = "string", }, }, Notes = "For official builds (Travis CI / Jenkins) it returns the exact commit hash used for the build. For unofficial local builds, returns the approximate commit hash (since the true one cannot be determined), formatted as \"approx: <CommitHash>\".", }, GetBuildDateTime = { IsStatic = true, Returns = { { Type = "string", }, }, Notes = "For official builds (Travic CI / Jenkins) it returns the date and time of the build. For unofficial local builds, returns the approximate datetime of the commit (since the true one cannot be determined), formatted as \"approx: <DateTime-iso8601>\".", }, GetBuildID = { IsStatic = true, Returns = { { Type = "string", }, }, Notes = "For official builds (Travis CI / Jenkins) it returns the unique ID of the build, as recognized by the build system. For unofficial local builds, returns the string \"Unknown\".", }, GetBuildSeriesName = { IsStatic = true, Returns = { { Type = "string", }, }, Notes = "For official builds (Travis CI / Jenkins) it returns the series name of the build (for example \"Cuberite Windows x64 Master\"). For unofficial local builds, returns the string \"local build\".", }, GetCraftingRecipes = { Returns = { { Type = "cCraftingRecipe", }, }, Notes = "Returns the CraftingRecipes object", }, GetDefaultWorld = { Returns = { { Type = "cWorld", }, }, Notes = "Returns the world object from the default world.", }, GetFurnaceFuelBurnTime = { IsStatic = true, Params = { { Name = "Fuel", Type = "cItem", }, }, Returns = { { Type = "number", }, }, Notes = "Returns the number of ticks for how long the item would fuel a furnace. Returns zero if not a fuel.", }, GetFurnaceRecipe = { IsStatic = true, Params = { { Name = "InItem", Type = "cItem", }, }, Returns = { { Name = "OutItem", Type = "cItem", }, { Name = "NumTicks", Type = "number", }, { Name = "InItem", Type = "cItem", }, }, Notes = "Returns the furnace recipe for smelting the specified input. If a recipe is found, returns the smelted result, the number of ticks required for the smelting operation, and the input consumed (note that Cuberite supports smelting M items into N items and different smelting rates). If no recipe is found, returns no value.", }, GetPhysicalRAMUsage = { IsStatic = true, Returns = { { Type = "number", }, }, Notes = "Returns the amount of physical RAM that the entire Cuberite process is using, in KiB. Negative if the OS doesn't support this query.", }, GetPluginManager = { Returns = { { Type = "cPluginManager", }, }, Notes = "Returns the cPluginManager object.", }, GetProtocolVersionTextFromInt = { IsStatic = true, Params = { { Name = "ProtocolVersionNumber", Type = "number", }, }, Returns = { { Type = "string", }, }, Notes = "Returns the Minecraft client version from the given Protocol version number. If there is no version found, it returns 'Unknown protocol (Number)'", }, GetServer = { Returns = { { Type = "cServer", }, }, Notes = "Returns the cServer object.", }, GetServerUpTime = { Returns = { { Type = "number", }, }, Notes = "Returns the uptime of the server in seconds.", }, GetTotalChunkCount = { Returns = { { Type = "number", }, }, Notes = "Returns the amount of loaded chunks.", }, GetVirtualRAMUsage = { IsStatic = true, Returns = { { Type = "number", }, }, Notes = "Returns the amount of virtual RAM that the entire Cuberite process is using, in KiB. Negative if the OS doesn't support this query.", }, GetWebAdmin = { Returns = { { Type = "cWebAdmin", }, }, Notes = "Returns the cWebAdmin object.", }, GetWorld = { Params = { { Name = "WorldName", Type = "string", }, }, Returns = { { Type = "cWorld", }, }, Notes = "Returns the cWorld object of the given world. It returns nil if there is no world with the given name.", }, QueueExecuteConsoleCommand = { Params = { { Name = "Message", Type = "string", }, }, Notes = "Queues a console command for execution through the cServer class. The command will be executed in the tick thread. The command's output will be sent to console.", }, SaveAllChunks = { Notes = "Saves all the chunks in all the worlds. Note that the saving is queued on each world's tick thread and this functions returns before the chunks are actually saved.", }, SetSavingEnabled = { Params = { { Name = "SavingEnabled", Type = "boolean", }, }, Notes = "Sets whether saving chunk data is enabled for all worlds. If disabled, dirty chunks will stay in memory forever, which can cause performance and stability issues.", }, }, AdditionalInfo = { { Header = "Querying a furnace recipe", Contents = [[ To find the furnace recipe for an item, use the following code (adapted from the Debuggers plugin's /fr command):
    local HeldItem = a_Player:GetEquippedItem();
    local Out, NumTicks, In = cRoot:GetFurnaceRecipe(HeldItem);  -- Note STATIC call - no need for a Get()
    if (Out ~= nil) then
    	-- There is a recipe, list it:
    	a_Player:SendMessage(
    		"Furnace turns " .. ItemToFullString(In) ..
    		" to " .. ItemToFullString(Out) ..
    		" in " .. NumTicks .. " ticks (" ..
    		tostring(NumTicks / 20) .. " seconds)."
    	);
    else
    	-- No recipe found
    	a_Player:SendMessage("There is no furnace recipe that would smelt " .. ItemToString(HeldItem));
    end
    
    ]], }, }, }, cScoreboard = { Desc = [[ This class manages the objectives and teams of a single world. ]], Functions = { AddPlayerScore = { Params = { { Name = "Name", Type = "string", }, { Name = "Type", Type = "", }, { Name = "Value", Type = "", }, }, Notes = "Adds a value to all player scores of the specified objective type.", }, ForEachObjective = { Params = { { Name = "CallbackFunction", Type = "function", }, }, Returns = { { Type = "boolean", }, }, Notes = "Calls the specified callback for each objective in the scoreboard. Returns true if all objectives have been processed (including when there are zero objectives), or false if the callback function has aborted the enumeration by returning true. The callback function has the following signature:
    function Callback({{cObjective|Objective}})
    The callback should return false or no value to continue with the next objective, or true to abort the enumeration.", }, ForEachTeam = { Params = { { Name = "CallbackFunction", Type = "function", }, }, Returns = { { Type = "boolean", }, }, Notes = "Calls the specified callback for each team in the scoreboard. Returns true if all teams have been processed (including when there are zero teams), or false if the callback function has aborted the enumeration by returning true. The callback function has the following signature:
    function Callback({{cObjective|Objective}})
    The callback should return false or no value to continue with the next team, or true to abort the enumeration.", }, GetNumObjectives = { Returns = { { Type = "number", }, }, Notes = "Returns the nuber of registered objectives.", }, GetNumTeams = { Returns = { { Type = "number", }, }, Notes = "Returns the number of registered teams.", }, GetObjective = { Params = { { Name = "string", Type = "string", }, }, Returns = { { Type = "cObjective", }, }, Notes = "Returns the objective with the specified name.", }, GetObjectiveIn = { Params = { { Name = "DisplaySlot", Type = "", }, }, Returns = { { Type = "cObjective", }, }, Notes = "Returns the objective in the specified display slot. Can be nil.", }, GetTeam = { Params = { { Name = "TeamName", Type = "string", }, }, Returns = { { Type = "cTeam", }, }, Notes = "Returns the team with the specified name.", }, GetTeamNames = { Returns = { { Type = "table", }, }, Notes = "Returns the names of all teams, as an array-table of strings", }, RegisterObjective = { Params = { { Name = "Name", Type = "string", }, { Name = "DisplayName", Type = "string", }, { Name = "Type", Type = "", }, }, Returns = { { Type = "cObjective", }, }, Notes = "Registers a new scoreboard objective. Returns the {{cObjective}} instance, nil on error.", }, RegisterTeam = { Params = { { Name = "Name", Type = "string", }, { Name = "DisplayName", Type = "string", }, { Name = "Prefix", Type = "", }, { Name = "Suffix", Type = "", }, }, Returns = { { Type = "cTeam", }, }, Notes = "Registers a new team. Returns the {{cTeam}} instance, nil on error. For example if the team already exists.", }, RemoveObjective = { Params = { { Name = "Name", Type = "string", }, }, Returns = { { Type = "boolean", }, }, Notes = "Removes the objective with the specified name. Returns true if operation was successful.", }, RemoveTeam = { Params = { { Name = "TeamName", Type = "string", }, }, Returns = { { Type = "boolean", }, }, Notes = "Removes the team with the specified name. Returns true if operation was successful.", }, SetDisplay = { Params = { { Name = "Name", Type = "string", }, { Name = "DisplaySlot", Type = "", }, }, Notes = "Updates the currently displayed objective.", }, }, Constants = { dsCount = { Notes = "", }, dsList = { Notes = "", }, dsName = { Notes = "", }, dsSidebar = { Notes = "", }, }, }, cServer = { Desc = [[ This class manages all the client connections internally. In the API layer, it allows to get and set the general properties of the server, such as the description and max players.

    It used to support broadcasting chat messages to all players, this functionality has been moved to {{cRoot}}:BroadcastChat(). ]], Functions = { DoesAllowMultiLogin = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if players can log in multiple times from the same account (normally used for debugging), false if only one player per name is allowed.", }, GetDescription = { Returns = { { Type = "string", }, }, Notes = "Returns the server description set in the settings.ini.", }, GetShutdownMessage = { Returns = { { Type = "string", }, }, Notes = "Returns the shutdown message set in the settings.ini.", }, GetMaxPlayers = { Returns = { { Type = "number", }, }, Notes = "Returns the max amount of players who can join the server.", }, GetNumPlayers = { Returns = { { Type = "number", }, }, Notes = "Returns the amount of players online.", }, GetServerID = { Returns = { { Type = "string", }, }, Notes = "Returns the ID of the server?", }, IsHardcore = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the server is hardcore (players get banned on death).", }, IsPlayerInQueue = { Params = { { Name = "Username", Type = "string", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if the specified player is queued to be transferred to a World.", }, RegisterForgeMod = { Params = { { Name = "ModName", Type = "string", }, { Name = "ModVersion", Type = "string", }, { Name = "ProtocolVersionNumber", Type = "number", }, }, Notes = "Add a Forge mod name/version to the server ping list.", }, ScheduleTask = { Params = { { Name = "DelayTicks", Type = "number", }, { Name = "TaskFunction", Type = "function", }, }, Notes = "Queues the specified function to be executed in the server's tick thread after a the specified number of ticks. This enables operations to be queued for execution in the future. The function signature is

    function({{cServer|Server}})
    All return values from the function are ignored. Note that it is unsafe to store references to Cuberite objects, such as entities, across from the caller to the task handler function; store the EntityID instead.", }, SetMaxPlayers = { Params = { { Name = "MaxPlayers", Type = "number", }, }, Notes = "Sets the max amount of players who can join.", }, ShouldAuthenticate = { Returns = { { Type = "boolean", }, }, Notes = "Returns true iff the server is set to authenticate players (\"online mode\").", }, UnregisterForgeMod = { Params = { { Name = "ModName", Type = "string", }, { Name = "ProtocolVersionNumber", Type = "number", }, }, Notes = "Remove a Forge mod name/version from the server ping list.", }, }, }, cStringCompression = { Desc = [[ Provides functions to compress or decompress string

    All functions in this class are static, so they should be called in the dot convention:

    local CompressedString = cStringCompression.CompressStringGZIP("DataToCompress")
    
    ]], Functions = { CompressStringGZIP = { IsStatic = true, Params = { { Name = "Data", Type = "string", }, }, Returns = { { Type = "string", }, }, Notes = "Compresses data in a string using GZIP", }, CompressStringZLIB = { IsStatic = true, Params = { { Name = "Data", Type = "string", }, { Name = "factor", Type = "number", }, }, Returns = { { Type = "string", }, }, Notes = "Compresses data in a string using ZLIB. Factor 0 is no compression and factor 9 is maximum compression.", }, InflateString = { IsStatic = true, Params = { { Name = "Data", Type = "string", }, }, Returns = { { Type = "string", }, }, Notes = "Uncompresses a string using Inflate", }, UncompressStringGZIP = { IsStatic = true, Params = { { Name = "Data", Type = "string", }, }, Returns = { { Type = "string", }, }, Notes = "Uncompress a string using GZIP", }, UncompressStringZLIB = { IsStatic = true, Params = { { Name = "Data", Type = "string", }, { Name = "UncompressedLength", Type = "number", }, }, Returns = { { Type = "string", }, }, Notes = "Uncompresses Data using ZLIB", }, }, }, cTeam = { Desc = [[ This class manages a single player team. ]], Functions = { AddPlayer = { Params = { { Name = "PlayerName", Type = "string", }, }, Returns = { { Type = "boolean", }, }, Notes = "Adds a player to this team. Returns true if the operation was successful.", }, AllowsFriendlyFire = { Returns = { { Type = "boolean", }, }, Notes = "Returns whether team friendly fire is allowed.", }, CanSeeFriendlyInvisible = { Returns = { { Type = "boolean", }, }, Notes = "Returns whether players can see invisible teammates.", }, GetDisplayName = { Returns = { { Type = "string", }, }, Notes = "Returns the display name of the team.", }, GetName = { Returns = { { Type = "string", }, }, Notes = "Returns the internal name of the team.", }, GetNumPlayers = { Returns = { { Type = "number", }, }, Notes = "Returns the number of registered players.", }, GetPrefix = { Returns = { { Type = "string", }, }, Notes = "Returns the prefix prepended to the names of the members of this team.", }, GetSuffix = { Returns = { { Type = "string", }, }, Notes = "Returns the suffix appended to the names of the members of this team.", }, HasPlayer = { Params = { { Name = "PlayerName", Type = "string", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns whether the specified player is a member of this team.", }, RemovePlayer = { Params = { { Name = "PlayerName", Type = "string", }, }, Returns = { { Type = "boolean", }, }, Notes = "Removes the player with the specified name from this team. Returns true if the operation was successful.", }, Reset = { Notes = "Removes all players from this team.", }, SetCanSeeFriendlyInvisible = { Params = { { Name = "CanSeeFriendlyInvisible", Type = "boolean", }, }, Notes = "Set whether players can see invisible teammates.", }, SetDisplayName = { Params = { { Name = "DisplayName", Type = "string", }, }, Notes = "Sets the display name of this team. (i.e. what will be shown to the players)", }, SetFriendlyFire = { Params = { { Name = "AllowFriendlyFire", Type = "boolean", }, }, Notes = "Sets whether team friendly fire is allowed.", }, SetPrefix = { Params = { { Name = "Prefix", Type = "string", }, }, Notes = "Sets the prefix prepended to the names of the members of this team.", }, SetSuffix = { Params = { { Name = "Suffix", Type = "string", }, }, Notes = "Sets the suffix appended to the names of the members of this team.", }, }, }, cTNTEntity = { Desc = "This class manages a TNT entity.", Functions = { Explode = { Notes = "Explode the tnt.", }, GetFuseTicks = { Returns = { { Type = "number", }, }, Notes = "Returns the fuse ticks - the number of game ticks until the tnt explodes.", }, SetFuseTicks = { Params = { { Name = "TicksUntilExplosion", Type = "number", }, }, Notes = "Set the fuse ticks until the tnt will explode.", }, }, Inherits = "cEntity", }, cUrlParser = { Desc = [[ Provides a parser for generic URLs that returns the individual components of the URL.

    Note that all functions are static. Call them by using "cUrlParser:Parse(...)" etc. ]], Functions = { GetDefaultPort = { IsStatic = true, Params = { { Name = "Scheme", Type = "string", }, }, Returns = { { Type = "number", }, }, Notes = "Returns the default port that should be used for the given scheme (protocol). Returns zero if the scheme is not known.", }, IsKnownScheme = { IsStatic = true, Params = { { Name = "Scheme", Type = "string", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if the scheme (protocol) is recognized by the parser.", }, Parse = { IsStatic = true, Params = { { Name = "URL", Type = "string", }, }, Returns = { { Name = "Scheme", Type = "string", }, { Name = "Username", Type = "string", }, { Name = "Password", Type = "string", }, { Name = "Host", Type = "string", }, { Name = "Port", Type = "number", }, { Name = "Path", Type = "string", }, { Name = "Query", Type = "string", }, { Name = "Fragment", Type = "string", }, }, Notes = "Returns the individual parts of the URL. Parts that are not explicitly specified in the URL are empty, the default port for the scheme is used. If parsing fails, the function returns nil and an error message.", }, ParseAuthorityPart = { IsStatic = true, Params = { { Name = "AuthPart", Type = "string", }, }, Returns = { { Name = "Username", Type = "string", }, { Name = "Password", Type = "string", }, { Name = "Host", Type = "string", }, { Name = "Port", Type = "number", }, }, Notes = "Parses the Authority part of the URL. Parts that are not explicitly specified in the AuthPart are returned empty, the port is returned zero. If parsing fails, the function returns nil and an error message.", }, UrlDecode = { IsStatic = true, Params = { { Name = "Text", Type = "string", }, }, Returns = { { Name = "Decoded", Type = "string", }, }, Notes = "Returns the Text, URL-decoded. Returns nil if there is a problem while decoding (invalid input).", }, UrlEncode = { IsStatic = true, Params = { { Name = "Text", Type = "string", }, }, Returns = { { Name = "Encoded", Type = "string", }, }, Notes = "Returns the Text, URL-encoded.", }, }, AdditionalInfo = { { Header = "Code example", Contents = [[ The following code fragment uses the cUrlParser to parse an URL string into its components, and prints those components out:

    local Scheme, Username, Password, Host, Port, Path, Query, Fragment = cUrlParser:Parse(
    	"http://anonymous:user@example.com@ftp.cuberite.org:9921/releases/2015/?sort=date#files"
    )
    if not(Scheme) then
    	-- Parsing failed, the second returned value (in Username) is the error message:
    	LOG("  Error: " .. (Username or ""))
    else
    	LOG("  Scheme   = " .. Scheme)    -- "http"
    	LOG("  Username = " .. Username)  -- "anonymous"
    	LOG("  Password = " .. Password)  -- "user@example.com"
    	LOG("  Host     = " .. Host)      -- "ftp.cuberite.org"
    	LOG("  Port     = " .. Port)      -- 9921
    	LOG("  Path     = " .. Path)      -- "releases/2015/"
    	LOG("  Query    = " .. Query)     -- "sort=date"
    	LOG("  Fragment = " .. Fragment)  -- "files"
    end
    
    ]], }, }, }, cUUID = { Desc = [[ Class representing a Universally Unique Identifier. Note that all Cuberite's API functions that take a cUUID parameter will also accept a string in its place, as long as that string can be converted to a cUUID (using the {{#FromString_1|cUUID:FromString}} function). ]], Functions = { constructor = { Returns = { { Type = "cUUID", }, }, Notes = "Constructs a nil-valued UUID (all zeros)", }, Compare = { Params = { { Name = "Other", Type = "cUUID", }, }, Returns = { { Type = "number", }, }, Notes = [[ Compares this UUID with the specified Other UUID, Returns: 0 when equal to Other, < 0 when less than Other, > 0 when greater than Other ]], }, IsNil = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if this contains the \"nil\" UUID with all bits set to 0", }, FromString = { Params = { { Name = "StringUUID", Type = "string", }, }, Returns = { { Type = "boolean", }, }, Notes = "Tries to interpret the string as a short or long form UUID and assign from it. On error, returns false and does not set the value.", }, ToShortString = { Returns = { { Type = "string", }, }, Notes = "Converts the UUID to a short form string (i.e without dashes).", }, ToLongString = { Returns = { { Type = "string", }, }, Notes = "Converts the UUID to a long form string (i.e with dashes).", }, Version = { Returns = { { Type = "number", }, }, Notes = "Returns the version number of the UUID.", }, Variant = { Returns = { { Type = "number", }, }, Notes = "Returns the variant number of the UUID", }, GenerateVersion3 = { IsStatic = true, Params = { { Name = "Name", Type = "string", }, }, Returns = { { Type = "cUUID", }, }, Notes = "Generates a version 3, variant 1 UUID based on the md5 hash of Name." }, }, }, cWindow = { Desc = [[ This class is the common ancestor for all window classes used by Cuberite. It is inherited by the {{cLuaWindow|cLuaWindow}} class that plugins use for opening custom windows. It is planned to be used for window-related hooks in the future. It implements the basic functionality of any window.

    Note that one cWindow object can be used for multiple players at the same time, and therefore the slot contents are player-specific (e. g. crafting grid, or player inventory). Thus the GetSlot() and SetSlot() functions need to have the {{cPlayer|cPlayer}} parameter that specifies the player for whom the contents are to be queried.

    Windows also have numeric properties, these are used to set the progressbars for furnaces or the XP costs for enchantment tables. ]], Functions = { GetSlot = { Params = { { Name = "Player", Type = "cPlayer", }, { Name = "SlotNumber", Type = "number", }, }, Returns = { { Type = "cItem", }, }, Notes = "Returns the item at the specified slot for the specified player. Returns nil and logs to server console on error.", }, GetWindowID = { Returns = { { Type = "number", }, }, Notes = "Returns the ID of the window, as used by the network protocol", }, GetWindowTitle = { Returns = { { Type = "string", }, }, Notes = "Returns the window title that will be displayed to the player", }, GetWindowType = { Returns = { { Type = "number", }, }, Notes = "Returns the type of the window, one of the constants in the table above", }, GetWindowTypeName = { Returns = { { Type = "string", }, }, Notes = "Returns the textual representation of the window's type, such as \"minecraft:chest\".", }, IsSlotInPlayerHotbar = { Params = { { Name = "SlotNum", Type = "number", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if the specified slot number is in the player hotbar", }, IsSlotInPlayerInventory = { Params = { { Name = "SlotNum", Type = "number", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if the specified slot number is in the player's main inventory or in the hotbar. Note that this returns false for armor slots!", }, IsSlotInPlayerMainInventory = { Params = { { Name = "SlotNum", Type = "number", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if the specified slot number is in the player's main inventory", }, SetProperty = { Params = { { Name = "PropertyID", Type = "number", }, { Name = "PropertyValue", Type = "number", }, { Name = "Player", Type = "cPlayer", IsOptional = true, }, }, Notes = "Updates a numerical property associated with the window. Typically used for furnace progressbars. Sends the UpdateWindowProperty packet to the specified Player, or to all current clients of the window if Player is not specified.", }, SetSlot = { Params = { { Name = "Player", Type = "cPlayer", }, { Name = "SlotNum", Type = "number", }, { Name = "cItem", Type = "cItem", }, }, Notes = "Sets the contents of the specified slot for the specified player. Ignored if the slot number is invalid", }, SetWindowTitle = { Params = { { Name = "WindowTitle", Type = "string", }, }, Notes = "Sets the window title that will be displayed to the player", }, }, Constants = { wtAnimalChest = { Notes = "A horse or donkey window", }, wtAnvil = { Notes = "An anvil window", }, wtBeacon = { Notes = "A beacon window", }, wtBrewery = { Notes = "A brewing stand window", }, wtChest = { Notes = "A {{cChestEntity|chest}} or doublechest window", }, wtDropSpenser = { Notes = "A {{cDropperEntity|dropper}} or a {{cDispenserEntity|dispenser}} window", }, wtEnchantment = { Notes = "An enchantment table window", }, wtFurnace = { Notes = "A {{cFurnaceEntity|furnace}} window", }, wtHopper = { Notes = "A {{cHopperEntity|hopper}} window", }, wtInventory = { Notes = "An inventory window", }, wtNPCTrade = { Notes = "A villager trade window", }, wtWorkbench = { Notes = "A workbench (crafting table) window", }, }, -- Constants ConstantGroups = { WindowType = { Include = { "wt.*" }, } }, -- ConstantGroups }, StatisticsManager = { Desc = [[ This class provides a store for various types of player statistics. The store will be read and sent to the client when the Statistics button is pressed. ]], Variables = { Custom = { Type = "Map of {{CustomStatistic}} to number", Notes = "Gets or sets the value of a custom statistic.", }, }, AdditionalInfo = { { Header = "Example usage", Contents = [[ Each store is a table, keyed by the statistic that the entry tracks, with value typically representing the number of times the event happened:

    function ModifyPlayerFurnaceInteractions(Player)
    	local Statistics = Player:GetStatistics()
    
    	if (Statistics.Custom[CustomStatistic.WalkOneCm] > 10) then
    		Statistics.Custom[CustomStatistic.InteractWithFurnace] = 1337
    	end
    
    	-- Next time the player presses Statistics they will see the updated value for furnace interactions.
    end
    
    ]], }, }, }, BannerPattern = { Desc = [[ An enumeration of banner patterns. ]], Constants = { BottomStripe = { Notes = "A base pattern." }, TopStripe = { Notes = "A chief pattern." }, LeftStripe = { Notes = "A pale dexter pattern." }, RightStripe = { Notes = "A pale sinister pattern." }, CenterStripeVertical = { Notes = "A pale pattern." }, MiddleStripeHorizontal = { Notes = "A fess pattern." }, DownRightStripe = { Notes = "A bend pattern." }, DownLeftStripe = { Notes = "A bend sinister pattern." }, SmallVerticalStripes = { Notes = "A paly pattern." }, DiagonalCross = { Notes = "A saltire pattern." }, SquareCross = { Notes = "A cross pattern." }, LeftOfDiagonal = { Notes = "A per bend sinister pattern." }, RightOfUpsideDownDiagonal = { Notes = "A per bend pattern." }, LeftOfUpsideDownDiagonal = { Notes = "A per bend inverted pattern." }, RightOfDiagonal = { Notes = "A per bend sinister inverted pattern." }, VerticalHalfLeft = { Notes = "A per pale pattern." }, VerticalHalfRight = { Notes = "A per pale inverted pattern." }, HorizontalHalfTop = { Notes = "A per fess pattern." }, HorizontalHalfBottom = { Notes = "A per fess inverted pattern." }, BottomLeftCorner = { Notes = "A base dexter canton pattern." }, BottomRightCorner = { Notes = "A base sinister canton pattern." }, TopLeftCorner = { Notes = "A chief dexter canton pattern." }, TopRightCorner = { Notes = "A chief sinister canton pattern." }, BottomTriangle = { Notes = "A chevron pattern." }, TopTriangle = { Notes = "An inverted chevron pattern." }, BottomTriangleSawtooth = { Notes = "A base indented pattern." }, TopTriangleSawtooth = { Notes = "A chief indented pattern." }, MiddleCircle = { Notes = "A roundel pattern." }, MiddleRhombus = { Notes = "A lozenge pattern." }, Border = { Notes = "A bordure pattern." }, CurlyBorder = { Notes = "A bordure indented pattern." }, Brick = { Notes = "A field masoned pattern." }, Gradient = { Notes = "A gradient pattern." }, GradientUpsideDown = { Notes = "A base gradient pattern." }, Creeper = { Notes = "A creeper charge pattern." }, Skull = { Notes = "A skull charge pattern." }, Flower = { Notes = "A flower charge pattern." }, Mojang = { Notes = "A... thing." }, Globe = { Notes = "A globe." }, Piglin = { Notes = "A snoot." }, }, }, BossBarColor = { Desc = [[ An enumeration of boss bar display colours which can be used with {{cClientHandle#SendBossBarAdd|SendBossBarAdd}}. ]], Constants = { Pink = { Notes = "A pink boss bar." }, Blue = { Notes = "A blue boss bar." }, Red = { Notes = "A red boss bar." }, Green = { Notes = "A green boss bar." }, Yellow = { Notes = "A yellow boss bar." }, Purple = { Notes = "A purple boss bar." }, White = { Notes = "A white boss bar." }, }, }, BossBarDivisionType = { Desc = [[ An enumeration of boss bar division types which can be used with {{cClientHandle#SendBossBarAdd|SendBossBarAdd}}. These constants control the number of notches the bar itself renders with. ]], Constants = { None = { Notes = "A completely smooth boss bar." }, SixNotches = { Notes = "A six-notch'd boss bar." }, TenNotches = { Notes = "A ten-notch'd boss bar." }, TwelveNotches = { Notes = "A twelve notch'd boss bar." }, TwentyNotches = { Notes = "A twenty notch'd boss bar." }, }, }, EffectID = { Desc = [[ An enumeration of sound and particle effects which can be used with {{cWorld#BroadcastSoundParticleEffect|BroadcastSoundParticleEffect}}. ]], Constants = { SFX_RANDOM_DISPENSER_DISPENSE = { Notes = "Sound of droper/dispenser releasing an item", }, SFX_RANDOM_DISPENSER_DISPENSE_FAIL = { Notes = "Sound of a droper/dispenser activated without items", }, SFX_RANDOM_DISPENSER_SHOOT = { Notes = "Sound of a dispenser shooting", }, SFX_RANDOM_ENDER_EYE_LAUNCH = { Notes = "Sound of an ender eye launch" }, SFX_RANDOM_FIREWORK_SHOT = { Notes = "Sound of a firework shot", }, SFX_RANDOM_IRON_DOOR_OPEN = { Notes = "Sound of an iron door opening", }, SFX_RANDOM_WOODEN_DOOR_OPEN = { Notes = "Sound of a wooden door opening" }, SFX_RANDOM_WOODEN_TRAPDOOR_OPEN = { Notes = "Sound of a wooden trapdoor opening" }, SFX_RANDOM_FENCE_GATE_OPEN = { Notes = "Sound of a fence gate opening", }, SFX_RANDOM_FIRE_EXTINGUISH = { Notes = "Sound of a fire extinguishing", }, SFX_RANDOM_PLAY_MUSIC_DISC = { Notes = "Starts playing a music disc. Needs an accompanting music disc ID", }, SFX_RANDOM_IRON_DOOR_CLOSE = { Notes = "Sound of an iron door closing", }, SFX_RANDOM_WOODEN_DOOR_CLOSE = { Notes = "Sound of a wooden door closing", }, SFX_RANDOM_WOODEN_TRAPDOOR_CLOSE = { Notes = "Sound of a trapdoor closing", }, SFX_RANDOM_FENCE_GATE_CLOSE = { Notes = "Sound of a fence gate closing", }, SFX_MOB_GHAST_WARN = { Notes = "Sound of a ghast warning cry", }, SFX_MOB_GHAST_SHOOT = { Notes = "Sound of a ghast shooting", }, SFX_MOB_ENDERDRAGON_SHOOT = { Notes = "Sound of the enderdragon shooting", }, SFX_MOB_BLAZE_SHOOT = { Notes = "Sound of a blaze shooting", }, SFX_MOB_ZOMBIE_WOOD = { Notes = "Sound of a zombie attacking a wooden door", }, SFX_MOB_ZOMBIE_METAL = { Notes = "Sound of a zombie attacking a metal door", }, SFX_MOB_ZOMBIE_WOOD_BREAK = { Notes = "Sound of a zombie breaking a wooden door", }, SFX_MOB_WITHER_BREAK_BLOCK = { Notes = "Sound of a wither breaking blocks", }, SFX_MOB_WITHER_SPAWN = { Notes = "Sound of a wither spawning", }, SFX_MOB_WITHER_SHOOT = { Notes = "Sound of a wither shooting", }, SFX_MOB_BAT_TAKEOFF = { Notes = "Sound of a bat taking off", }, SFX_MOB_ZOMBIE_INFECT = { Notes = "Sound of a zombie infecting a villager", }, SFX_MOB_ZOMBIE_UNFECT = { Notes = "Sound of a zombie villager converting to villager", }, SFX_MOB_ENDERDRAGON_DEATH = { Notes = "Sound of the dragon releasing dragon breath", }, SFX_RANDOM_ANVIL_BREAK = { Notes = "Sound of an anvil breaking", }, SFX_RANDOM_ANVIL_USE = { Notes = "Sound of using an anvil", }, SFX_RANDOM_ANVIL_LAND = { Notes = "Sound of a falling anvil landing", }, SFX_RANDOM_PORTAL_TRAVEL = { Notes = "Sound of travelling through a portal", }, SFX_RANDOM_CHORUS_FLOWER_GROW = { Notes = "Sound of a growing chorus flower", }, SFX_RANDOM_CHORUS_FLOWER_DEATH = { Notes = "Sound of a dieing chorus flower", }, SFX_RANDOM_BREWING_STAND_BREW = { Notes = "Sound of an active brewing stand", }, SFX_RANDOM_IRON_TRAPDOOR_OPEN = { Notes = "Sound of an iron trapdoor opening", }, SFX_RANDOM_IRON_TRAPDOOR_CLOSE = { Notes = "Sound of an iron trapdoor closing", }, PARTICLE_SMOKE = { Notes = "Spawns 10 smoke particles, e.g. from a fire. Needs a {{SmokeDirection|SmokeDirection}}", }, PARTICLE_BLOCK_BREAK = { Notes = "Block break particle and sound. Needs a BlockID", }, PARTICLE_SPLASH_POTION = { Notes = "Splash potion particles and glass break sound. Needs a PotionID", }, PARTICLE_EYE_OF_ENDER = { Notes = "Eye of ender entity break particles and sound", }, PARTICLE_MOBSPAWN = { Notes = "Mob spawn particle effect: smoke and flames", }, PARTICLE_HAPPY_VILLAGER = { Notes = "Happy villager/bonemeal particles. Number of particles may be given or 0 for default of 15", }, PARTICLE_DRAGON_BREATH = { Notes = "Dragon breath particle effect", }, PARTICLE_END_GATEWAY_SPAWN = { Notes = "End gateway spawn particle effect", }, PARTICLE_ENDERDRAGON_GROWL = { Notes = "Ender dragon growl particle effect", }, }, }, SmokeDirection = { Desc = [[ An enumeration of the direction spawned smoke will drift in as it floats up. ]], Constants = { SOUTH_EAST = { Notes = "Smoke drifts south-east", }, SOUTH = { Notes = "Smoke drifts south", }, SOUTH_WEST = { Notes = "Smoke drifts south-west", }, EAST = { Notes = "Smoke drifts east", }, CENTRE = { Notes = "Smoke does not drift", }, WEST = { Notes = "Smoke drifts west", }, NORTH_EAST = { Notes = "Smoke drifts north-east", }, NORTH = { Notes = "Smoke drifts north", }, NORTH_WEST = { Notes = "Smoke drifts west", }, } }, CustomStatistic = { Desc = [[ An enumeration of statistics of the custom type to be used with the {{StatisticsManager#Custom|Custom}} statistics store. ]], Constants = { AnimalsBred = { Notes = "The number of times the player bred two mobs.", }, AviateOneCm = { Notes = "The total distance travelled by elytra.", }, BellRing = { Notes = "The number of times the player has rung a bell.", }, BoatOneCm = { Notes = "The total distance travelled by boats.", }, CleanArmor = { Notes = "The number of dyed leather armors washed with a cauldron.", }, CleanBanner = { Notes = "The number of banner patterns washed with a cauldron.", }, CleanShulkerBox = { Notes = "The number of times the player has washed a Shulker Box with a cauldron.", }, ClimbOneCm = { Notes = "The total distance travelled up ladders or vines.", }, CrouchOneCm = { Notes = "The total distance walked while sneaking.", }, DamageAbsorbed = { Notes = "The amount of damage the player has absorbed in tenths of 1.", }, DamageBlockedByShield = { Notes = "The amount of damage the player has blocked with a shield in tenths of 1.", }, DamageDealt = { Notes = "The amount of damage the player has dealt in tenths 1. Includes only melee attacks.", }, DamageDealtAbsorbed = { Notes = "The amount of damage the player has dealt that was absorbed, in tenths of 1.", }, DamageDealtResisted = { Notes = "The amount of damage the player has dealt that was resisted, in tenths of 1.", }, DamageResisted = { Notes = "The amount of damage the player has resisted in tenths of 1.", }, DamageTaken = { Notes = "The amount of damage the player has taken in tenths of 1.", }, Deaths = { Notes = "The number of times the player died.", }, Drop = { Notes = "The number of items the drop key was pressed.", }, EatCakeSlice = { Notes = "The number of cake slices eaten.", }, EnchantItem = { Notes = "The number of items enchanted.", }, FallOneCm = { Notes = "The total distance fallen.", }, FillCauldron = { Notes = "The number of times the player filled cauldrons with water buckets.", }, FishCaught = { Notes = "The number of fish caught.", }, FlyOneCm = { Notes = "The total distance flown.", }, HorseOneCm = { Notes = "The total distance travelled by horses.", }, InspectDispenser = { Notes = "The number of times interacted with dispensers.", }, InspectDropper = { Notes = "The number of times interacted with droppers.", }, InspectHopper = { Notes = "The number of times interacted with hoppers.", }, InteractWithAnvil = { Notes = "The number of times interacted with anvils.", }, InteractWithBeacon = { Notes = "The number of times interacted with beacons.", }, InteractWithBlastFurnace = { Notes = "The number of times interacted with Blast Furnaces.", }, InteractWithBrewingstand = { Notes = "The number of times interacted with brewing stands.", }, InteractWithCampfire = { Notes = "The number of times interacted with campfires.", }, InteractWithCartographyTable = { Notes = "The number of times interacted with cartography tables.", }, InteractWithCraftingTable = { Notes = "The number of times interacted with crafting tables.", }, InteractWithFurnace = { Notes = "The number of times interacted with furnaces.", }, InteractWithGrindstone = { Notes = "The number of times interacted with grindstones.", }, InteractWithLectern = { Notes = "The number of times interacted with lecterns.", }, InteractWithLoom = { Notes = "The number of times interacted with looms.", }, InteractWithSmithingTable = { Notes = "The number of times interacted with smithing tables.", }, InteractWithSmoker = { Notes = "The number of times interacted with smokers.", }, InteractWithStonecutter = { Notes = "The number of times interacted with stonecutters.", }, JunkFished = { Notes = "The amount of junk fished.", }, Jump = { Notes = "The number of jumps performed.", }, LeaveGame = { Notes = "The number of times disconnected from the server.", }, MinecartOneCm = { Notes = "The total distance travelled by minecarts.", }, MobKills = { Notes = "The number of mobs the player killed.", }, OpenBarrel = { Notes = "The number of times the player has opened a barrel.", }, OpenChest = { Notes = "The number of times the player opened chests.", }, OpenEnderchest = { Notes = "The number of times the player opened ender chests.", }, OpenShulkerBox = { Notes = "The number of times the player has opened a shulker box.", }, PigOneCm = { Notes = "The total distance travelled by pigs via saddles.", }, PlayNoteblock = { Notes = "The number of note blocks hit.", }, PlayOneMinute = { Notes = "The total time played.", }, PlayRecord = { Notes = "The number of music discs played on a jukebox.", }, PlayerKills = { Notes = "The number of players the player directly killed.", }, PotFlower = { Notes = "The number of plants potted into flower pots.", }, RaidTrigger = { Notes = "The number of times the player has triggered a raid.", }, RaidWin = { Notes = "The number of times the player has won a raid.", }, SleepInBed = { Notes = "The number of times the player has slept in a bed.", }, SneakTime = { Notes = "The time the player has held down the sneak button.", }, SprintOneCm = { Notes = "The total distance sprinted.", }, StriderOneCm = { Notes = "The total distance travelled by striders via saddles.", }, SwimOneCm = { Notes = "The total distance swum.", }, TalkedToVillager = { Notes = "The number of times interacted with villagers (opened the trading GUI).", }, TargetHit = { Notes = "The number of times the player has shot a target block.", }, TimeSinceDeath = { Notes = "The time since the player's last death.", }, TimeSinceRest = { Notes = "The time since the player's last rest. This is used to spawn phantoms.", }, TradedWithVillager = { Notes = "The number of times traded with villagers.", }, TreasureFished = { Notes = "The number of treasures fished.", }, TriggerTrappedChest = { Notes = "The number of times the player opened trapped chests.", }, TuneNoteblock = { Notes = "The number of times interacted with note blocks.", }, UseCauldron = { Notes = "The number of times the player took water from cauldrons with glass bottles.", }, WalkOnWaterOneCm = { Notes = "The distance covered while bobbing up and down over water.", }, WalkOneCm = { Notes = "The total distance walked.", }, WalkUnderWaterOneCm = { Notes = "The total distance walked underwater.", }, }, }, Globals = { Desc = [[ These functions are available directly, without a class instance. Any plugin can call them at any time. ]], Functions = { AddFaceDirection = { { Params = { { Name = "BlockX", Type = "number", }, { Name = "BlockY", Type = "number", }, { Name = "BlockZ", Type = "number", }, { Name = "BlockFace", Type = "eBlockFace", }, { Name = "IsInverse", Type = "boolean", IsOptional = true, }, }, Returns = { { Name = "BlockX", Type = "number", }, { Name = "BlockY", Type = "number", }, { Name = "BlockZ", Type = "number", }, }, Notes = "OBSOLETE, use the vector version instead.", }, { Params = { { Name = "Position", Type = "Vector3i", }, { Name = "BlockFace", Type = "eBlockFace", }, { Name = "InvertDirection", Type = "boolean", IsOptional = true, }, }, Returns = { { Type = "Vector3i", }, }, Notes = "By default, returns the coordinates adjacent to the specified block through the specified face. If inverted, returns the coordinates adjacent to the opposite face.", }, }, Base64Decode = { Params = { { Name = "Input", Type = "string", }, }, Returns = { { Type = "string" }, }, Notes = "Decodes a Base64-encoded string into the raw data.", }, Base64Encode = { Params = { { Name = "Input", Type = "string", }, }, Returns = { { Type = "string" }, }, Notes = "Encodes a string into Base64.", }, BiomeToString = { Params = { { Name = "Biome", Type = "EMCSBiome", }, }, Returns = { { Type = "string" }, }, Notes = "Translates biome enum into biome string. Returns empty string on failure (unknown biome).", }, BlockFaceToString = { Params = { { Name = "eBlockFace", Type = "eBlockFace", }, }, Returns = { { Type = "string", }, }, Notes = "Returns the string representation of the {{Globals#BlockFaces|eBlockFace}} constant. Uses the axis-direction-based names, such as BLOCK_FACE_XP.", }, BlockStringToType = { Params = { { Name = "BlockTypeString", Type = "string", }, }, Returns = { { Name = "BLOCKTYPE", Type = "number", }, }, Notes = "Returns the block type parsed from the given string", }, Clamp = { Params = { { Name = "Number", Type = "number", }, { Name = "Min", Type = "number", }, { Name = "Max", Type = "number", }, }, Returns = { { Type = "number", }, }, Notes = "Clamp the number to the specified range.", }, ClickActionToString = { Params = { { Name = "ClickAction", Type = "eClickAction", }, }, Returns = { { Type = "string", }, }, Notes = "Returns a string description of the ClickAction enumerated value", }, DamageTypeToString = { Params = { { Name = "DamageType", Type = "eDamageType", }, }, Returns = { { Type = "string", }, }, Notes = "Converts the {{Globals#eDamageType|DamageType}} to a string representation ", }, DimensionToString = { Params = { { Name = "Dimension", Type = "eDimension", }, }, Returns = { { Type = "string", }, }, Notes = "Converts an {{Globals#eDimension|eDimension}} to a string value. Returns Overworld on failure.", }, EscapeString = { Params = { { Name = "Input", Type = "string", }, }, Returns = { { Type = "string", }, }, Notes = "Returns a copy of the string with all quotes and backslashes escaped by a backslash", }, GetIniItemSet = { Params = { { Name = "IniFile", Type = "cIniFile", }, { Name = "SectionName", Type = "string", }, { Name = "KeyName", Type = "string", }, { Name = "DefaultValue", Type = "string", }, }, Returns = { { Type = "cItem", }, }, Notes = "Returns the item that has been read from the specified INI file value. If the value is not present in the INI file, the DefaultValue is stored in the file and parsed as the result. Returns empty item if the value cannot be parsed. ", }, GetSnowStartHeight = { Params = { { Name = "Biome", Type = "EMCSBiome", }, }, Returns = { { Type = "number" }, }, Notes = "Returns the height at which snow will start falling in the {{Globals#EMCSBiome|Biome}}. Check functions IsBiomeCold and IsBiomeVeryCold for more informations.", }, GetTime = { Returns = { { Type = "number", }, }, Notes = "Returns the current OS time, as a unix time stamp (number of seconds since Jan 1, 1970)", }, IsBiomeCold = { Params = { { Name = "Biome", Type = "EMCSBiome", }, }, Returns = { { Type = "boolean" }, }, Notes = "Returns true if the biome is cold (has snow and snowfall at higher elevations but not at regular heights). Doesn't report Very Cold biomes, use IsBiomeVeryCold() for those.", }, IsBiomeNoDownfall = { Params = { { Name = "Biome", Type = "EMCSBiome", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if the biome is 'dry', that is, there is no precipitation during rains and storms.", }, IsBiomeOcean = { Params = { { Name = "Biome", Type = "EMCSBiome", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if the biome is an ocean biome.", }, IsBiomeVeryCold = { Params = { { Name = "Biome", Type = "EMCSBiome", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if the biome is very cold (has snow on ground everywhere, turns top water to ice, has snowfall instead of rain everywhere). Doesn't report mildly cold biomes (where it snows above certain elevation), use IsBiomeCold() for those.", }, IsBiomeMountain = { Params = { { Name = "Biome", Type = "EMCSBiome", } }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if the biome is mountainous (mutations of the extreme hills biome)." }, IsBiomeMesa = { Params = { { Name = "Biome", Type = "EMCSBiome", } }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if the biome is a type of Mesa (mutations of the Mesa biome)." }, IsValidBlock = { Params = { { Name = "BlockType", Type = "number", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if BlockType is a known block type", }, IsValidItem = { Params = { { Name = "ItemType", Type = "number", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if ItemType is a known item type", }, ItemToFullString = { Params = { { Name = "cItem", Type = "cItem", }, }, Returns = { { Type = "string", }, }, Notes = "Returns the string representation of the item, in the format 'ItemTypeText:ItemDamage * Count'", }, ItemToString = { Params = { { Name = "cItem", Type = "cItem", }, }, Returns = { { Type = "string", }, }, Notes = "Returns the string representation of the item type", }, ItemTypeToString = { Params = { { Name = "ItemType", Type = "number", }, }, Returns = { { Type = "string", }, }, Notes = "Returns the string representation of ItemType ", }, LOG = { { Params = { { Name = "Message", Type = "string", }, { Name = "SuppressPluginNamePrefix", Type = "boolean", IsOptional = true, }, }, Notes = "Logs a text into the server console and logfile using 'normal' severity (gray text).", }, { Params = { { Name = "Message", Type = "cCompositeChat", }, { Name = "SuppressPluginNamePrefix", Type = "boolean", IsOptional = true, }, }, Notes = "Logs the {{cCompositeChat}}'s human-readable text into the server console, using a severity defined by the CompositeChat's MessageType.", }, }, LOGERROR = { Params = { { Name = "Message", Type = "string", }, { Name = "SuppressPluginNamePrefix", Type = "boolean", IsOptional = true, }, }, Notes = "Logs a text into the server console and logfile using 'error' severity (black text on red background).", }, LOGINFO = { Params = { { Name = "Message", Type = "string", }, { Name = "SuppressPluginNamePrefix", Type = "boolean", IsOptional = true, }, }, Notes = "Logs a text into the server console and logfile using 'info' severity (yellow text).", }, LOGWARN = { Params = { { Name = "Message", Type = "string", }, { Name = "SuppressPluginNamePrefix", Type = "boolean", IsOptional = true, }, }, Notes = "Logs a text into the server console and logfile using 'warning' severity (red text); OBSOLETE, use LOGWARNING() instead.", }, LOGWARNING = { Params = { { Name = "Message", Type = "string", }, { Name = "SuppressPluginNamePrefix", Type = "boolean", IsOptional = true, }, }, Notes = "Logs a text into the server console and logfile using 'warning' severity (red text).", }, md5 = { Params = { { Name = "Data", Type = "string", }, }, Returns = { { Type = "string", }, }, Notes = "OBSOLETE, use the {{cCryptoHash}} functions instead.
    Converts a string to a raw binary md5 hash.", }, MirrorBlockFaceY = { Params = { { Name = "eBlockFace", Type = "eBlockFace", }, }, Returns = { { Type = "eBlockFace", }, }, Notes = "Returns the {{Globals#BlockFaces|eBlockFace}} that corresponds to the given {{Globals#BlockFaces|eBlockFace}} after mirroring it around the Y axis (or rotating 180 degrees around it).", }, NoCaseCompare = { Params = { { Name = "Value1", Type = "string", }, { Name = "Value2", Type = "string", }, }, Returns = { { Type = "number", }, }, Notes = "Case-insensitive string comparison; returns 0 if the strings are the same, -1 if Value1 is smaller and 1 if Value2 is smaller", }, NormalizeAngleDegrees = { Params = { { Name = "AngleDegrees", Type = "number", }, }, Returns = { { Name = "AngleDegrees", Type = "number", }, }, Notes = "Returns the angle, wrapped into the [-180, +180) range.", }, ReplaceString = { Params = { { Name = "full-string", Type = "string", }, { Name = "to-be-replaced-string", Type = "string", }, { Name = "to-replace-string", Type = "string", }, }, Returns = { { Type = "string", }, }, Notes = "Replaces *each* occurence of to-be-replaced-string in full-string with to-replace-string", }, ReverseBlockFace = { Params = { { Name = "BlockFace", Type = "eBlockFace", }, }, Returns = { { Type = "eBlockFace", }, }, Notes = "Returns the reversed {{Globals#eBlockFace|eBlockFace}}.", }, RotateBlockFaceCCW = { Params = { { Name = "eBlockFace", Type = "eBlockFace", }, }, Returns = { { Type = "eBlockFace", }, }, Notes = "Returns the {{Globals#BlockFaces|eBlockFace}} that corresponds to the given {{Globals#BlockFaces|eBlockFace}} after rotating it around the Y axis 90 degrees counter-clockwise.", }, RotateBlockFaceCW = { Params = { { Name = "eBlockFace", Type = "eBlockFace", }, }, Returns = { { Type = "eBlockFace", }, }, Notes = "Returns the {{Globals#BlockFaces|eBlockFace}} that corresponds to the given {{Globals#BlockFaces|eBlockFace}} after rotating it around the Y axis 90 degrees clockwise.", }, StringSplit = { Params = { { Name = "Input", Type = "string", }, { Name = "SeperatorsString", Type = "string", }, }, Returns = { { Type = "table", }, }, Notes = "Seperates string into multiple by splitting every time any of the characters in SeperatorsString is encountered. Returns and array-table of strings.", }, StringSplitAndTrim = { Params = { { Name = "Input", Type = "string", }, { Name = "SeperatorsString", Type = "string", }, }, Returns = { { Type = "table", }, }, Notes = "Seperates string into multiple by splitting every time any of the characters in SeperatorsString is encountered. Each of the separate strings is trimmed (whitespace removed from the beginning and end of the string). Returns an array-table of strings.", }, StringSplitWithQuotes = { Params = { { Name = "Input", Type = "string", }, { Name = "SeperatorsString", Type = "string", }, }, Returns = { { Type = "table", }, }, Notes = "Seperates string into multiple by splitting every time any of the characters in SeperatorsString is encountered. Whitespace wrapped with single or double quotes will be ignored. Returns an array-table of strings.", }, StringToBiome = { Params = { { Name = "Input", Type = "string", }, }, Returns = { { Name = "BiomeType", Type = "EMCSBiome", }, }, Notes = "Converts a string representation to a {{Globals#BiomeTypes|BiomeType}} enumerated value. Returns biInvalidBiome if the input is not a recognized biome.", }, StringToDamageType = { Params = { { Name = "Input", Type = "string", }, }, Returns = { { Name = "DamageType", Type = "eDamageType", }, }, Notes = "Converts a string representation to a {{Globals#DamageType|DamageType}} enumerated value. Returns -1 if the inupt is not a recognized damage type.", }, StringToDimension = { Params = { { Name = "Input", Type = "string", }, }, Returns = { { Name = "Dimension", Type = "eDimension", }, }, Notes = "Converts a string representation to a {{Globals#eDimension|eDimension}} enumerated value. Returns dimNotSet if the input is not a recognized dimension.", }, StringToItem = { Params = { { Name = "StringToParse", Type = "string", }, { Name = "DestItem", Type = "cItem", }, }, Returns = { { Type = "boolean", }, }, Notes = "Parses the item specification in the given string and sets it into DestItem; returns true if successful", }, StringToMobType = { Params = { { Name = "MobTypeString", Type = "string", }, }, Returns = { { Name = "MobType", Type = "eMonsterType", }, }, Notes = "(DEPRECATED!) Please use cMonster:StringToMobType(). Converts a string representation to an {{Globals#eMonsterType|eMonsterType}} enumerated value", }, StripColorCodes = { Params = { { Name = "Input", Type = "string", }, }, Returns = { { Type = "string", }, }, Notes = "Removes all control codes used by MC for colors and styles", }, TrimString = { Params = { { Name = "Input", Type = "string", }, }, Returns = { { Type = "string", }, }, Notes = "Removes whitespace at both ends of the string", }, }, Constants = { caLeftClick = { Notes = "Left click on a slot", }, caRightClick = { Notes = "Right click on a slot", }, caShiftLeftClick = { Notes = "Shift + left click on a slot", }, caShiftRightClick = { Notes = "Shift + right click on a slot", }, caNumber1 = { Notes = "Number key 1", }, caNumber2 = { Notes = "Number key 2", }, caNumber3 = { Notes = "Number key 3", }, caNumber4 = { Notes = "Number key 4", }, caNumber5 = { Notes = "Number key 5", }, caNumber6 = { Notes = "Number key 6", }, caNumber7 = { Notes = "Number key 7", }, caNumber8 = { Notes = "Number key 8", }, caNumber9 = { Notes = "Number key 9", }, caMiddleClick = { Notes = "Middle click, only valid for creative players", }, caDropKey = { Notes = "Drop a single item", }, caCtrlDropKey = { Notes = "Drop a full stack", }, caLeftClickOutside = { Notes = "Left click outside of inventory", }, caRightClickOutside = { Notes = "Right click outside of inventory", }, caLeftClickOutsideHoldNothing = { Notes = "Left click outside inventory holding nothing", }, caRightClickOutsideHoldNothing = { Notes = "Right click outside inventory holding nothing", }, caLeftPaintBegin = { Notes = "Begining of left click paint drag action", }, caRightPaintBegin = { Notes = "Begining of right click paint drag action", }, caMiddlePaintBegin = { Notes = "Begining of middle click paint drag action, only valid for creative players", }, caLeftPaintProgress = { Notes = "Add slot for left click paint drag action", }, caRightPaintProgress = { Notes = "Add slot for right click paint drag action", }, caMiddlePaintProgress = { Notes = "Add slot for middle click paint drag action, only valid for creative players", }, caLeftPaintEnd = { Notes = "End of left click paint drag action", }, caRightPaintEnd = { Notes = "End of right click paint drag action", }, caMiddlePaintEnd = { Notes = "End of middle click paint drag action, only valid for creative players", }, caDblClick = { Notes = "Double click action", }, caUnknown = { Notes = "Unknown click action" }, dtAdmin = { Notes = "Damage applied by an admin command" }, dtArrow = { Notes = "Damage received by being attacked by a projectile, possibly from a mob" }, dtArrowAttack = { Notes = "Damage received by being attacked by a projectile, possibly from a mob" }, dtAttack = { Notes = "Damage recieved by being attacked by a mob" }, dtBurning = { Notes = "Damage from being on fire" }, dtCacti = { Notes = "Damage from contact with a cactus block" }, dtCactus = { Notes = "Damage from contact with a cactus block" }, dtCactusContact = { Notes = "Damage from contact with a cactus block" }, dtCactuses = { Notes = "Damage from contact with a cactus block" }, dtMagmaContact = { Notes = "Damage from contact with a magma block" }, dtMagma = { Notes = "Damage from contact with a magma block" }, dtDrown = { Notes = "Damage received by drowning in water / lava" }, dtDrowning = { Notes = "Damage received by drowning in water / lava" }, dtEnderPearl = { Notes = "Damage received by throwing an ender pearl and being teleported by it" }, dtEntityAttack = { Notes = "Damage recieved by being attacked by a mob" }, dtEnvironment = { Notes = "Damage dealt to mobs from environment: enderman in rain, snow golem in desert" }, dtExplosion = { Notes = "Damage applied by an explosion" }, dtFall = { Notes = "Damage from falling down. Dealt when hitting the ground" }, dtFalling = { Notes = "Damage from falling down. Dealt when hitting the ground" }, dtFireContact = { Notes = "Damage received by standing inside a fire block" }, dtHunger = { Notes = "Damage received from hunger" }, dtInFire = { Notes = "Damage received by standing inside a fire block" }, dtInVoid = { Notes = "Damage received by falling into the Void (Y < 0)" }, dtLava = { Notes = "Damage received by a contact with a lava block" }, dtLavaContact = { Notes = "Damage received by a contact with a lava block" }, dtLightning = { Notes = "Damage from being hit by a lightning strike" }, dtMob = { Notes = "Damage received by being attacked by a mob" }, dtMobAttack = { Notes = "Damage received by being attacked by a mob" }, dtOnFire = { Notes = "Damage from being on fire" }, dtPawnAttack = { Notes = "Damage received by being attacked by a mob" }, dtPlugin = { Notes = "Damage applied by an admin command" }, dtPoison = { Notes = "Damage applied by the poison effect" }, dtPoisoning = { Notes = "Damage applied by the poison effect" }, dtPotionOfHarming = { Notes = "Damage applied by the potion of harming" }, dtProjectile = { Notes = "Damage received by being attacked by a projectile, possibly from a mob" }, dtRangedAttack = { Notes = "Damage received by being attacked by a projectile, possibly from a mob" }, dtStarvation = { Notes = "Damage received from hunger" }, dtStarving = { Notes = "Damage received from hunger" }, dtSuffocating = { Notes = "Damage from suffocating inside a block" }, dtSuffocation = { Notes = "Damage from suffocating inside a block" }, dtWither = { Notes = "Damage from the wither effect" }, dtWithering = { Notes = "Damage from the wither effect" }, E_BLOCK_ACACIA_DOOR = { Notes = "The blocktype for acacia door" }, E_BLOCK_ACACIA_FENCE = { Notes = "The blocktype for acacia fence" }, E_BLOCK_ACACIA_FENCE_GATE = { Notes = "The blocktype for acacia fence gate" }, E_BLOCK_ACACIA_WOOD_STAIRS = { Notes = "The blocktype for acacia wood stairs" }, E_BLOCK_ACTIVATOR_RAIL = { Notes = "The blocktype for activator rail" }, E_BLOCK_ACTIVE_COMPARATOR = { Notes = "The blocktype for active comparator" }, E_BLOCK_AIR = { Notes = "The blocktype for air" }, E_BLOCK_ANVIL = { Notes = "The blocktype for anvil" }, E_BLOCK_ANVIL_HIGH_DAMAGE = { Notes = "The blocktype for anvil high damage" }, E_BLOCK_ANVIL_LOW_DAMAGE = { Notes = "The blocktype for anvil low damage" }, E_BLOCK_ANVIL_NO_DAMAGE = { Notes = "The blocktype for anvil no damage" }, E_BLOCK_ANVIL_X = { Notes = "The blocktype for anvil x" }, E_BLOCK_ANVIL_Z = { Notes = "The blocktype for anvil z" }, E_BLOCK_BARRIER = { Notes = "The blocktype for barrier" }, E_BLOCK_BEACON = { Notes = "The blocktype for beacon" }, E_BLOCK_BED = { Notes = "The blocktype for bed" }, E_BLOCK_BEDROCK = { Notes = "The blocktype for bedrock" }, E_BLOCK_BED_BED_HEAD = { Notes = "The blocktype for bed bed head" }, E_BLOCK_BED_OCCUPIED = { Notes = "The blocktype for bed occupied" }, E_BLOCK_BED_XM = { Notes = "The blocktype for bed xm" }, E_BLOCK_BED_XP = { Notes = "The blocktype for bed xp" }, E_BLOCK_BED_ZM = { Notes = "The blocktype for bed zm" }, E_BLOCK_BED_ZP = { Notes = "The blocktype for bed zp" }, E_BLOCK_BEETROOTS = { Notes = "The blocktype for beetroots" }, E_BLOCK_BIG_FLOWER = { Notes = "The blocktype for big flower" }, E_BLOCK_BIRCH_DOOR = { Notes = "The blocktype for birch door" }, E_BLOCK_BIRCH_FENCE = { Notes = "The blocktype for birch fence" }, E_BLOCK_BIRCH_FENCE_GATE = { Notes = "The blocktype for birch fence gate" }, E_BLOCK_BIRCH_WOOD_STAIRS = { Notes = "The blocktype for birch wood stairs" }, E_BLOCK_BLACK_GLAZED_TERRACOTTA = { Notes = "The blocktype for black terracotta" }, E_BLOCK_BLACK_SHULKER_BOX = { Notes = "The blocktype for black shulker box" }, E_BLOCK_BLOCK_OF_COAL = { Notes = "The blocktype for block of coal" }, E_BLOCK_BLOCK_OF_REDSTONE = { Notes = "The blocktype for block of redstone" }, E_BLOCK_BLUE_GLAZED_TERRACOTTA = { Notes = "The blocktype for blue glazed terracotta" }, E_BLOCK_BLUE_SHULKER_BOX = { Notes = "The blocktype for blue shulker box" }, E_BLOCK_BONE_BLOCK = { Notes = "The blocktype for bone block" }, E_BLOCK_BOOKCASE = { Notes = "The blocktype for bookcase" }, E_BLOCK_BREWING_STAND = { Notes = "The blocktype for brewing stand" }, E_BLOCK_BRICK = { Notes = "The blocktype for brick" }, E_BLOCK_BRICK_STAIRS = { Notes = "The blocktype for brick stairs" }, E_BLOCK_BROWN_GLAZED_TERRACOTTA = { Notes = "The blocktype for brown glazed terracotta" }, E_BLOCK_BROWN_MUSHROOM = { Notes = "The blocktype for brown mushroom" }, E_BLOCK_BROWN_SHULKER_BOX = { Notes = "The blocktype for brown shulker box" }, E_BLOCK_BURNING_FURNACE = { Notes = "The blocktype for burning furnace" }, E_BLOCK_BUTTON_PRESSED = { Notes = "The blocktype for button pressed" }, E_BLOCK_BUTTON_XM = { Notes = "The blocktype for button xm" }, E_BLOCK_BUTTON_XP = { Notes = "The blocktype for button xp" }, E_BLOCK_BUTTON_YM = { Notes = "The blocktype for button ym" }, E_BLOCK_BUTTON_YP = { Notes = "The blocktype for button yp" }, E_BLOCK_BUTTON_ZM = { Notes = "The blocktype for button zm" }, E_BLOCK_BUTTON_ZP = { Notes = "The blocktype for button zp" }, E_BLOCK_CACTUS = { Notes = "The blocktype for cactus" }, E_BLOCK_CAKE = { Notes = "The blocktype for cake" }, E_BLOCK_CARPET = { Notes = "The blocktype for carpet" }, E_BLOCK_CARROTS = { Notes = "The blocktype for carrots" }, E_BLOCK_CAULDRON = { Notes = "The blocktype for cauldron" }, E_BLOCK_CHAIN_COMMAND_BLOCK = { Notes = "The blocktype for chain command block" }, E_BLOCK_CHEST = { Notes = "The blocktype for chest" }, E_BLOCK_CHORUS_FLOWER = { Notes = "The blocktype for chorus flower" }, E_BLOCK_CHORUS_PLANT = { Notes = "The blocktype for chorus plant" }, E_BLOCK_CLAY = { Notes = "The blocktype for clay" }, E_BLOCK_COAL_ORE = { Notes = "The blocktype for coal ore" }, E_BLOCK_COBBLESTONE = { Notes = "The blocktype for cobblestone" }, E_BLOCK_COBBLESTONE_STAIRS = { Notes = "The blocktype for cobblestone stairs" }, E_BLOCK_COBBLESTONE_WALL = { Notes = "The blocktype for cobblestone wall" }, E_BLOCK_COBWEB = { Notes = "The blocktype for cobweb" }, E_BLOCK_COCOA_POD = { Notes = "The blocktype for cocoa pod" }, E_BLOCK_COMMAND_BLOCK = { Notes = "The blocktype for command block" }, E_BLOCK_CONCRETE = { Notes = "The blocktype for concrete" }, E_BLOCK_CONCRETE_POWDER = { Notes = "The blocktype for concrete powder" }, E_BLOCK_CRAFTING_TABLE = { Notes = "The blocktype for crafting table" }, E_BLOCK_CROPS = { Notes = "The blocktype for crops" }, E_BLOCK_CYAN_GLAZED_TERRACOTTA = { Notes = "The blocktype for cyan glazed terracotta" }, E_BLOCK_CYAN_SHULKER_BOX = { Notes = "The blocktype for cyan shulker box" }, E_BLOCK_DANDELION = { Notes = "The blocktype for dandelion" }, E_BLOCK_DARK_OAK_DOOR = { Notes = "The blocktype for dark oak door" }, E_BLOCK_DARK_OAK_FENCE = { Notes = "The blocktype for dark oak fence" }, E_BLOCK_DARK_OAK_FENCE_GATE = { Notes = "The blocktype for dark oak fence gate" }, E_BLOCK_DARK_OAK_WOOD_STAIRS = { Notes = "The blocktype for dark oak wood stairs" }, E_BLOCK_DAYLIGHT_SENSOR = { Notes = "The blocktype for daylight sensor" }, E_BLOCK_DEAD_BUSH = { Notes = "The blocktype for dead bush" }, E_BLOCK_DETECTOR_RAIL = { Notes = "The blocktype for detector rail" }, E_BLOCK_DIAMOND_BLOCK = { Notes = "The blocktype for diamond block" }, E_BLOCK_DIAMOND_ORE = { Notes = "The blocktype for diamond ore" }, E_BLOCK_DIRT = { Notes = "The blocktype for dirt" }, E_BLOCK_DISPENSER = { Notes = "The blocktype for dispenser" }, E_BLOCK_DOUBLE_RED_SANDSTONE_SLAB = { Notes = "The blocktype for double red sandstone slab" }, E_BLOCK_DOUBLE_STONE_SLAB = { Notes = "The blocktype for double stone slab" }, E_BLOCK_DOUBLE_WOODEN_SLAB = { Notes = "The blocktype for double wooden slab" }, E_BLOCK_DRAGON_EGG = { Notes = "The blocktype for dragon egg" }, E_BLOCK_DROPPER = { Notes = "The blocktype for dropper" }, E_BLOCK_EMERALD_BLOCK = { Notes = "The blocktype for emerald block" }, E_BLOCK_EMERALD_ORE = { Notes = "The blocktype for emerald ore" }, E_BLOCK_ENCHANTMENT_TABLE = { Notes = "The blocktype for enchantment table" }, E_BLOCK_ENDER_CHEST = { Notes = "The blocktype for ender chest" }, E_BLOCK_END_BRICKS = { Notes = "The blocktype for end bricks" }, E_BLOCK_END_GATEWAY = { Notes = "The blocktype for end gateway" }, E_BLOCK_END_PORTAL = { Notes = "The blocktype for end portal" }, E_BLOCK_END_PORTAL_FRAME = { Notes = "The blocktype for end portal frame" }, E_BLOCK_END_ROD = { Notes = "The blocktype for end rod" }, E_BLOCK_END_STONE = { Notes = "The blocktype for end stone" }, E_BLOCK_FARMLAND = { Notes = "The blocktype for farmland" }, E_BLOCK_FENCE = { Notes = "The blocktype for fence" }, E_BLOCK_FENCE_GATE = { Notes = "The blocktype for fence gate" }, E_BLOCK_FIRE = { Notes = "The blocktype for fire" }, E_BLOCK_FLOWER = { Notes = "The blocktype for flower" }, E_BLOCK_FLOWER_POT = { Notes = "The blocktype for flower pot" }, E_BLOCK_FROSTED_ICE = { Notes = "The blocktype for frosted ice" }, E_BLOCK_FURNACE = { Notes = "The blocktype for furnace" }, E_BLOCK_GLASS = { Notes = "The blocktype for glass" }, E_BLOCK_GLASS_PANE = { Notes = "The blocktype for glass pane" }, E_BLOCK_GLOWSTONE = { Notes = "The blocktype for glowstone" }, E_BLOCK_GOLD_BLOCK = { Notes = "The blocktype for gold block" }, E_BLOCK_GOLD_ORE = { Notes = "The blocktype for gold ore" }, E_BLOCK_GRASS = { Notes = "The blocktype for grass" }, E_BLOCK_GRASS_PATH = { Notes = "The blocktype for grass path" }, E_BLOCK_GRAVEL = { Notes = "The blocktype for gravel" }, E_BLOCK_GRAY_GLAZED_TERRACOTTA = { Notes = "The blocktype for gray glazed terracotta" }, E_BLOCK_GRAY_SHULKER_BOX = { Notes = "The blocktype for gray shulker box" }, E_BLOCK_GREEN_GLAZED_TERRACOTTA = { Notes = "The blocktype for green glazed terracotta" }, E_BLOCK_GREEN_SHULKER_BOX = { Notes = "The blocktype for green shulker box" }, E_BLOCK_HARDENED_CLAY = { Notes = "The blocktype for hardened clay" }, E_BLOCK_HAY_BALE = { Notes = "The blocktype for hay bale" }, E_BLOCK_HEAD = { Notes = "The blocktype for head" }, E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE = { Notes = "The blocktype for heavy weighted pressure plate" }, E_BLOCK_HOPPER = { Notes = "The blocktype for hopper" }, E_BLOCK_HUGE_BROWN_MUSHROOM = { Notes = "The blocktype for huge brown mushroom" }, E_BLOCK_HUGE_RED_MUSHROOM = { Notes = "The blocktype for huge red mushroom" }, E_BLOCK_ICE = { Notes = "The blocktype for ice" }, E_BLOCK_INACTIVE_COMPARATOR = { Notes = "The blocktype for inactive comparator" }, E_BLOCK_INVERTED_DAYLIGHT_SENSOR = { Notes = "The blocktype for inverted daylight sensor" }, E_BLOCK_IRON_BARS = { Notes = "The blocktype for iron bars" }, E_BLOCK_IRON_BLOCK = { Notes = "The blocktype for iron block" }, E_BLOCK_IRON_DOOR = { Notes = "The blocktype for iron door" }, E_BLOCK_IRON_ORE = { Notes = "The blocktype for iron ore" }, E_BLOCK_IRON_TRAPDOOR = { Notes = "The blocktype for iron trapdoor" }, E_BLOCK_JACK_O_LANTERN = { Notes = "The blocktype for jack o lantern" }, E_BLOCK_JUKEBOX = { Notes = "The blocktype for jukebox" }, E_BLOCK_JUNGLE_DOOR = { Notes = "The blocktype for jungle door" }, E_BLOCK_JUNGLE_FENCE = { Notes = "The blocktype for jungle fence" }, E_BLOCK_JUNGLE_FENCE_GATE = { Notes = "The blocktype for jungle fence gate" }, E_BLOCK_JUNGLE_WOOD_STAIRS = { Notes = "The blocktype for jungle wood stairs" }, E_BLOCK_LADDER = { Notes = "The blocktype for ladder" }, E_BLOCK_LAPIS_BLOCK = { Notes = "The blocktype for lapis block" }, E_BLOCK_LAPIS_ORE = { Notes = "The blocktype for lapis ore" }, E_BLOCK_LAVA = { Notes = "The blocktype for lava" }, E_BLOCK_LEAVES = { Notes = "The blocktype for leaves" }, E_BLOCK_LEVER = { Notes = "The blocktype for lever" }, E_BLOCK_LIGHT_BLUE_GLAZED_TERRACOTTA = { Notes = "The blocktype for light blue glazed terracotta" }, E_BLOCK_LIGHT_BLUE_SHULKER_BOX = { Notes = "The blocktype for light blue shulker box" }, E_BLOCK_LIGHT_GRAY_GLAZED_TERRACOTTA = { Notes = "The blocktype for light gray glazed terracotta" }, E_BLOCK_LIGHT_GRAY_SHULKER_BOX = { Notes = "The blocktype for light gray shulker box" }, E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE = { Notes = "The blocktype for light weighted pressure plate" }, E_BLOCK_LILY_PAD = { Notes = "The blocktype for lily pad" }, E_BLOCK_LIME_GLAZED_TERRACOTTA = { Notes = "The blocktype for lime glazed terracotta" }, E_BLOCK_LIME_SHULKER_BOX = { Notes = "The blocktype for lime shulker box" }, E_BLOCK_LIT_FURNACE = { Notes = "The blocktype for lit furnace" }, E_BLOCK_LOG = { Notes = "The blocktype for log" }, E_BLOCK_MAGENTA_GLAZED_TERRACOTTA = { Notes = "The blocktype for magenta glazed terracotta" }, E_BLOCK_MAGENTA_SHULKER_BOX = { Notes = "The blocktype for magenta shulker box" }, E_BLOCK_MAGMA = { Notes = "The blocktype for magma" }, E_BLOCK_MAX_TYPE_ID = { Notes = "The blocktype for max type id" }, E_BLOCK_MELON = { Notes = "The blocktype for melon" }, E_BLOCK_MELON_STEM = { Notes = "The blocktype for melon stem" }, E_BLOCK_MINECART_TRACKS = { Notes = "The blocktype for minecart tracks" }, E_BLOCK_MOB_SPAWNER = { Notes = "The blocktype for mob spawner" }, E_BLOCK_MOSSY_COBBLESTONE = { Notes = "The blocktype for mossy cobblestone" }, E_BLOCK_MYCELIUM = { Notes = "The blocktype for mycelium" }, E_BLOCK_NETHERRACK = { Notes = "The blocktype for netherrack" }, E_BLOCK_NETHER_BRICK = { Notes = "The blocktype for nether brick" }, E_BLOCK_NETHER_BRICK_FENCE = { Notes = "The blocktype for nether brick fence" }, E_BLOCK_NETHER_BRICK_STAIRS = { Notes = "The blocktype for nether brick stairs" }, E_BLOCK_NETHER_PORTAL = { Notes = "The blocktype for nether portal" }, E_BLOCK_NETHER_QUARTZ_ORE = { Notes = "The blocktype for nether quartz ore" }, E_BLOCK_NETHER_WART = { Notes = "The blocktype for nether wart" }, E_BLOCK_NETHER_WART_BLOCK = { Notes = "The blocktype for nether wart block" }, E_BLOCK_NEW_LEAVES = { Notes = "The blocktype for new leaves" }, E_BLOCK_NEW_LOG = { Notes = "The blocktype for new log" }, E_BLOCK_NOTE_BLOCK = { Notes = "The blocktype for note block" }, E_BLOCK_NUMBER_OF_TYPES = { Notes = "The blocktype for number of types" }, E_BLOCK_OAK_DOOR = { Notes = "The blocktype for oak door" }, E_BLOCK_OAK_FENCE_GATE = { Notes = "The blocktype for oak fence gate" }, E_BLOCK_OAK_WOOD_STAIRS = { Notes = "The blocktype for oak wood stairs" }, E_BLOCK_OBSERVER = { Notes = "The blocktype for observer" }, E_BLOCK_OBSIDIAN = { Notes = "The blocktype for obsidian" }, E_BLOCK_ORANGE_GLAZED_TERRACOTTA = { Notes = "The blocktype for orange glazed terracota" }, E_BLOCK_ORANGE_SHULKER_BOX = { Notes = "The blocktype for orange shulker box" }, E_BLOCK_PACKED_ICE = { Notes = "The blocktype for packed ice" }, E_BLOCK_PINK_GLAZED_TERRACOTTA = { Notes = "The blocktype for pink glazed terracotta" }, E_BLOCK_PINK_SHULKER_BOX = { Notes = "The blocktype for pink shulker box" }, E_BLOCK_PISTON = { Notes = "The blocktype for piston" }, E_BLOCK_PISTON_EXTENSION = { Notes = "The blocktype for piston extension" }, E_BLOCK_PISTON_MOVED_BLOCK = { Notes = "The blocktype for piston moved block" }, E_BLOCK_PLANKS = { Notes = "The blocktype for planks" }, E_BLOCK_POTATOES = { Notes = "The blocktype for potatoes" }, E_BLOCK_POWERED_RAIL = { Notes = "The blocktype for powered rail" }, E_BLOCK_PRISMARINE_BLOCK = { Notes = "The blocktype for prismarine block" }, E_BLOCK_PUMPKIN = { Notes = "The blocktype for pumpkin" }, E_BLOCK_PUMPKIN_STEM = { Notes = "The blocktype for pumpkin stem" }, E_BLOCK_PURPLE_GLAZED_TERRACOTTA = { Notes = "The blocktype for purple glazed terracotta" }, E_BLOCK_PURPLE_SHULKER_BOX = { Notes = "The blocktype for purple shulker box" }, E_BLOCK_PURPUR_BLOCK = { Notes = "The blocktype for purpur block" }, E_BLOCK_PURPUR_DOUBLE_SLAB = { Notes = "The blocktype for purpur double slab" }, E_BLOCK_PURPUR_PILLAR = { Notes = "The blocktype for purpur pillar" }, E_BLOCK_PURPUR_SLAB = { Notes = "The blocktype for purpur slab" }, E_BLOCK_PURPUR_STAIRS = { Notes = "The blocktype for purpur stairs" }, E_BLOCK_QUARTZ_BLOCK = { Notes = "The blocktype for quartz block" }, E_BLOCK_QUARTZ_STAIRS = { Notes = "The blocktype for quartz stairs" }, E_BLOCK_RAIL = { Notes = "The blocktype for rail" }, E_BLOCK_REDSTONE_LAMP_OFF = { Notes = "The blocktype for redstone lamp off" }, E_BLOCK_REDSTONE_LAMP_ON = { Notes = "The blocktype for redstone lamp on" }, E_BLOCK_REDSTONE_ORE = { Notes = "The blocktype for redstone ore" }, E_BLOCK_REDSTONE_ORE_GLOWING = { Notes = "The blocktype for redstone ore glowing" }, E_BLOCK_REDSTONE_REPEATER_OFF = { Notes = "The blocktype for redstone repeater off" }, E_BLOCK_REDSTONE_REPEATER_ON = { Notes = "The blocktype for redstone repeater on" }, E_BLOCK_REDSTONE_TORCH_OFF = { Notes = "The blocktype for redstone torch off" }, E_BLOCK_REDSTONE_TORCH_ON = { Notes = "The blocktype for redstone torch on" }, E_BLOCK_REDSTONE_WIRE = { Notes = "The blocktype for redstone wire" }, E_BLOCK_RED_GLAZED_TERRACOTTA = { Notes = "The blocktype for red glazed terracotta" }, E_BLOCK_RED_MUSHROOM = { Notes = "The blocktype for red mushroom" }, E_BLOCK_RED_NETHER_BRICK = { Notes = "The blocktype for red nether brick" }, E_BLOCK_RED_ROSE = { Notes = "The blocktype for red rose" }, E_BLOCK_RED_SANDSTONE = { Notes = "The blocktype for red sandstone" }, E_BLOCK_RED_SANDSTONE_SLAB = { Notes = "The blocktype for red sandstone slab" }, E_BLOCK_RED_SANDSTONE_STAIRS = { Notes = "The blocktype for red sandstone stairs" }, E_BLOCK_RED_SHULKER_BOX = { Notes = "The blocktype for red shulker box" }, E_BLOCK_REEDS = { Notes = "The blocktype for reeds" }, E_BLOCK_REPEATING_COMMAND_BLOCK = { Notes = "The blocktype for repeating command block" }, E_BLOCK_SAND = { Notes = "The blocktype for sand" }, E_BLOCK_SANDSTONE = { Notes = "The blocktype for sandstone" }, E_BLOCK_SANDSTONE_STAIRS = { Notes = "The blocktype for sandstone stairs" }, E_BLOCK_SAPLING = { Notes = "The blocktype for sapling" }, E_BLOCK_SEA_LANTERN = { Notes = "The blocktype for sea lantern" }, E_BLOCK_SIGN_POST = { Notes = "The blocktype for sign post" }, E_BLOCK_SILVERFISH_EGG = { Notes = "The blocktype for silverfish egg" }, E_BLOCK_SLIME_BLOCK = { Notes = "The blocktype for slime block" }, E_BLOCK_SNOW = { Notes = "The blocktype for snow" }, E_BLOCK_SNOW_BLOCK = { Notes = "The blocktype for snow block" }, E_BLOCK_SOULSAND = { Notes = "The blocktype for soulsand" }, E_BLOCK_SPONGE = { Notes = "The blocktype for sponge" }, E_BLOCK_SPRUCE_DOOR = { Notes = "The blocktype for spruce door" }, E_BLOCK_SPRUCE_FENCE = { Notes = "The blocktype for spruce fence" }, E_BLOCK_SPRUCE_FENCE_GATE = { Notes = "The blocktype for spruce fence gate" }, E_BLOCK_SPRUCE_WOOD_STAIRS = { Notes = "The blocktype for spruce wood stairs" }, E_BLOCK_STAINED_CLAY = { Notes = "The blocktype for stained clay" }, E_BLOCK_STAINED_GLASS = { Notes = "The blocktype for stained glass" }, E_BLOCK_STAINED_GLASS_PANE = { Notes = "The blocktype for stained glass pane" }, E_BLOCK_STAIRS_UPSIDE_DOWN = { Notes = "The blocktype for stairs upside down" }, E_BLOCK_STAIRS_XM = { Notes = "The blocktype for stairs xm" }, E_BLOCK_STAIRS_XP = { Notes = "The blocktype for stairs xp" }, E_BLOCK_STAIRS_ZM = { Notes = "The blocktype for stairs zm" }, E_BLOCK_STAIRS_ZP = { Notes = "The blocktype for stairs zp" }, E_BLOCK_STANDING_BANNER = { Notes = "The blocktype for standing banner" }, E_BLOCK_STATIONARY_LAVA = { Notes = "The blocktype for stationary lava" }, E_BLOCK_STATIONARY_WATER = { Notes = "The blocktype for stationary water" }, E_BLOCK_STICKY_PISTON = { Notes = "The blocktype for sticky piston" }, E_BLOCK_STONE = { Notes = "The blocktype for stone" }, E_BLOCK_STONE_BRICKS = { Notes = "The blocktype for stone bricks" }, E_BLOCK_STONE_BRICK_STAIRS = { Notes = "The blocktype for stone brick stairs" }, E_BLOCK_STONE_BUTTON = { Notes = "The blocktype for stone button" }, E_BLOCK_STONE_PRESSURE_PLATE = { Notes = "The blocktype for stone pressure plate" }, E_BLOCK_STONE_SLAB = { Notes = "The blocktype for stone slab" }, E_BLOCK_STRUCTURE_BLOCK = { Notes = "The blocktype for structure block" }, E_BLOCK_STRUCTURE_VOID = { Notes = "The blocktype for structure void" }, E_BLOCK_SUGARCANE = { Notes = "The blocktype for sugarcane" }, E_BLOCK_TALL_GRASS = { Notes = "The blocktype for tall grass" }, E_BLOCK_TERRACOTTA = { Notes = "The blocktype for terracotta (synonym for E_BLOCK_STAINED_CLAY)", }, E_BLOCK_TNT = { Notes = "The blocktype for tnt" }, E_BLOCK_TORCH = { Notes = "The blocktype for torch" }, E_BLOCK_TRAPDOOR = { Notes = "The blocktype for trapdoor" }, E_BLOCK_TRAPPED_CHEST = { Notes = "The blocktype for trapped chest" }, E_BLOCK_TRIPWIRE = { Notes = "The blocktype for tripwire" }, E_BLOCK_TRIPWIRE_HOOK = { Notes = "The blocktype for tripwire hook" }, E_BLOCK_UNFINISHED = { Notes = "Internal blocktype for unfinished block handlers", }, E_BLOCK_VINES = { Notes = "The blocktype for vines" }, E_BLOCK_WALLSIGN = { Notes = "The blocktype for wallsign" }, E_BLOCK_WALL_BANNER = { Notes = "The blocktype for wall banner" }, E_BLOCK_WATER = { Notes = "The blocktype for water" }, E_BLOCK_WHITE_GLAZED_TERRACOTTA = { Notes = "The blocktype for white glazed terracotta" }, E_BLOCK_WHITE_SHULKER_BOX = { Notes = "The blocktype for white shulker box" }, E_BLOCK_WOODEN_BUTTON = { Notes = "The blocktype for wooden button" }, E_BLOCK_WOODEN_DOOR = { Notes = "The blocktype for wooden door" }, E_BLOCK_WOODEN_PRESSURE_PLATE = { Notes = "The blocktype for wooden pressure plate" }, E_BLOCK_WOODEN_SLAB = { Notes = "The blocktype for wooden slab" }, E_BLOCK_WOODEN_STAIRS = { Notes = "The blocktype for wooden stairs" }, E_BLOCK_WOOL = { Notes = "The blocktype for wool" }, E_BLOCK_WORKBENCH = { Notes = "The blocktype for workbench" }, E_BLOCK_YELLOW_FLOWER = { Notes = "The blocktype for yellow flower" }, E_BLOCK_YELLOW_GLAZED_TERRACOTTA = { Notes = "The blocktype for yellow glazed terracotta" }, E_BLOCK_YELLOW_SHULKER_BOX = { Notes = "The blocktype for yellow shulker box" }, E_ITEM_11_DISC = { Notes = "The itemtype for 11 disc" }, E_ITEM_13_DISC = { Notes = "The itemtype for 13 disc" }, E_ITEM_ACACIA_BOAT = { Notes = "The itemtype for acacia boat" }, E_ITEM_ACACIA_DOOR = { Notes = "The itemtype for acacia door" }, E_ITEM_ARMOR_STAND = { Notes = "The itemtype for armor stand" }, E_ITEM_ARROW = { Notes = "The itemtype for arrow" }, E_ITEM_BAKED_POTATO = { Notes = "The itemtype for baked potato" }, E_ITEM_BANNER = { Notes = "The itemtype for banner" }, E_ITEM_BED = { Notes = "The itemtype for bed" }, E_ITEM_BEETROOT = { Notes = "The itemtype for beetroot" }, E_ITEM_BEETROOT_SEEDS = { Notes = "The itemtype for beetroot seeds" }, E_ITEM_BEETROOT_SOUP = { Notes = "The itemtype for betroot soup" }, E_ITEM_BIRCH_BOAT = { Notes = "The itemtype for birch boat" }, E_ITEM_BIRCH_DOOR = { Notes = "The itemtype for birch door" }, E_ITEM_BLAZE_POWDER = { Notes = "The itemtype for blaze powder" }, E_ITEM_BLAZE_ROD = { Notes = "The itemtype for blaze rod" }, E_ITEM_BLOCKS_DISC = { Notes = "The itemtype for blocks disc" }, E_ITEM_BOAT = { Notes = "The itemtype for boat" }, E_ITEM_BONE = { Notes = "The itemtype for bone" }, E_ITEM_BOOK = { Notes = "The itemtype for book" }, E_ITEM_BOOK_AND_QUILL = { Notes = "The itemtype for book and quill" }, E_ITEM_BOTTLE_O_ENCHANTING = { Notes = "The itemtype for bottle o enchanting" }, E_ITEM_BOW = { Notes = "The itemtype for bow" }, E_ITEM_BOWL = { Notes = "The itemtype for bowl" }, E_ITEM_BREAD = { Notes = "The itemtype for bread" }, E_ITEM_BREWING_STAND = { Notes = "The itemtype for brewing stand" }, E_ITEM_BUCKET = { Notes = "The itemtype for bucket" }, E_ITEM_CAKE = { Notes = "The itemtype for cake" }, E_ITEM_CARROT = { Notes = "The itemtype for carrot" }, E_ITEM_CARROT_ON_STICK = { Notes = "The itemtype for carrot on stick" }, E_ITEM_CAT_DISC = { Notes = "The itemtype for cat disc" }, E_ITEM_CAULDRON = { Notes = "The itemtype for cauldron" }, E_ITEM_CHAIN_BOOTS = { Notes = "The itemtype for chain boots" }, E_ITEM_CHAIN_CHESTPLATE = { Notes = "The itemtype for chain chestplate" }, E_ITEM_CHAIN_HELMET = { Notes = "The itemtype for chain helmet" }, E_ITEM_CHAIN_LEGGINGS = { Notes = "The itemtype for chain leggings" }, E_ITEM_CHEST_MINECART = { Notes = "The itemtype for chest minecart" }, E_ITEM_CHIRP_DISC = { Notes = "The itemtype for chirp disc" }, E_ITEM_CHORUS_FRUIT = { Notes = "The itemtype for chorus fruit" }, E_ITEM_CLAY = { Notes = "The itemtype for clay" }, E_ITEM_CLAY_BRICK = { Notes = "The itemtype for clay brick" }, E_ITEM_CLOCK = { Notes = "The itemtype for clock" }, E_ITEM_COAL = { Notes = "The itemtype for coal" }, E_ITEM_COMPARATOR = { Notes = "The itemtype for comparator" }, E_ITEM_COMPASS = { Notes = "The itemtype for compass" }, E_ITEM_COOKED_CHICKEN = { Notes = "The itemtype for cooked chicken" }, E_ITEM_COOKED_FISH = { Notes = "The itemtype for cooked fish" }, E_ITEM_COOKED_MUTTON = { Notes = "The itemtype for cooked mutton" }, E_ITEM_COOKED_PORKCHOP = { Notes = "The itemtype for cooked porkchop" }, E_ITEM_COOKED_RABBIT = { Notes = "The itemtype for cooked rabbit" }, E_ITEM_COOKIE = { Notes = "The itemtype for cookie" }, E_ITEM_DARK_OAK_BOAT = { Notes = "The itemtype for dark oak boat" }, E_ITEM_DARK_OAK_DOOR = { Notes = "The itemtype for dark oak door" }, E_ITEM_DIAMOND = { Notes = "The itemtype for diamond" }, E_ITEM_DIAMOND_AXE = { Notes = "The itemtype for diamond axe" }, E_ITEM_DIAMOND_BOOTS = { Notes = "The itemtype for diamond boots" }, E_ITEM_DIAMOND_CHESTPLATE = { Notes = "The itemtype for diamond chestplate" }, E_ITEM_DIAMOND_HELMET = { Notes = "The itemtype for diamond helmet" }, E_ITEM_DIAMOND_HOE = { Notes = "The itemtype for diamond hoe" }, E_ITEM_DIAMOND_HORSE_ARMOR = { Notes = "The itemtype for diamond horse armor" }, E_ITEM_DIAMOND_LEGGINGS = { Notes = "The itemtype for diamond leggings" }, E_ITEM_DIAMOND_PICKAXE = { Notes = "The itemtype for diamond pickaxe" }, E_ITEM_DIAMOND_SHOVEL = { Notes = "The itemtype for diamond shovel" }, E_ITEM_DIAMOND_SWORD = { Notes = "The itemtype for diamond sword" }, E_ITEM_DRAGON_BREATH = { Notes = "The itemtype for dragon breath" }, E_ITEM_DYE = { Notes = "The itemtype for dye" }, E_ITEM_EGG = { Notes = "The itemtype for egg" }, E_ITEM_ELYTRA = { Notes = "The itemtype for elytra" }, E_ITEM_EMERALD = { Notes = "The itemtype for emerald" }, E_ITEM_EMPTY = { Notes = "The itemtype for empty" }, E_ITEM_EMPTY_MAP = { Notes = "The itemtype for empty map" }, E_ITEM_ENCHANTED_BOOK = { Notes = "The itemtype for enchanted book" }, E_ITEM_END_CRYSTAL = { Notes = "The itemtype for end crystal" }, E_ITEM_ENDER_PEARL = { Notes = "The itemtype for ender pearl" }, E_ITEM_EYE_OF_ENDER = { Notes = "The itemtype for eye of ender" }, E_ITEM_FAR_DISC = { Notes = "The itemtype for far disc" }, E_ITEM_FEATHER = { Notes = "The itemtype for feather" }, E_ITEM_FERMENTED_SPIDER_EYE = { Notes = "The itemtype for fermented spider eye" }, E_ITEM_FIREWORK_ROCKET = { Notes = "The itemtype for firework rocket" }, E_ITEM_FIREWORK_STAR = { Notes = "The itemtype for firework star" }, E_ITEM_FIRE_CHARGE = { Notes = "The itemtype for fire charge" }, E_ITEM_FIRST = { Notes = "The itemtype for first" }, E_ITEM_FIRST_DISC = { Notes = "The itemtype for first disc" }, E_ITEM_FISHING_ROD = { Notes = "The itemtype for fishing rod" }, E_ITEM_FLINT = { Notes = "The itemtype for flint" }, E_ITEM_FLINT_AND_STEEL = { Notes = "The itemtype for flint and steel" }, E_ITEM_FLOWER_POT = { Notes = "The itemtype for flower pot" }, E_ITEM_FURNACE_MINECART = { Notes = "The itemtype for furnace minecart" }, E_ITEM_GHAST_TEAR = { Notes = "The itemtype for ghast tear" }, E_ITEM_GLASS_BOTTLE = { Notes = "The itemtype for glass bottle" }, E_ITEM_GLISTERING_MELON = { Notes = "The itemtype for glistering melon" }, E_ITEM_GLOWSTONE_DUST = { Notes = "The itemtype for glowstone dust" }, E_ITEM_GOLD = { Notes = "The itemtype for gold" }, E_ITEM_GOLDEN_APPLE = { Notes = "The itemtype for golden apple" }, E_ITEM_GOLDEN_CARROT = { Notes = "The itemtype for golden carrot" }, E_ITEM_GOLD_AXE = { Notes = "The itemtype for gold axe" }, E_ITEM_GOLD_BOOTS = { Notes = "The itemtype for gold boots" }, E_ITEM_GOLD_CHESTPLATE = { Notes = "The itemtype for gold chestplate" }, E_ITEM_GOLD_HELMET = { Notes = "The itemtype for gold helmet" }, E_ITEM_GOLD_HOE = { Notes = "The itemtype for gold hoe" }, E_ITEM_GOLD_HORSE_ARMOR = { Notes = "The itemtype for gold horse armor" }, E_ITEM_GOLD_LEGGINGS = { Notes = "The itemtype for gold leggings" }, E_ITEM_GOLD_NUGGET = { Notes = "The itemtype for gold nugget" }, E_ITEM_GOLD_PICKAXE = { Notes = "The itemtype for gold pickaxe" }, E_ITEM_GOLD_SHOVEL = { Notes = "The itemtype for gold shovel" }, E_ITEM_GOLD_SWORD = { Notes = "The itemtype for gold sword" }, E_ITEM_GUNPOWDER = { Notes = "The itemtype for gunpowder" }, E_ITEM_HEAD = { Notes = "The itemtype for head" }, E_ITEM_IRON = { Notes = "The itemtype for iron" }, E_ITEM_IRON_AXE = { Notes = "The itemtype for iron axe" }, E_ITEM_IRON_BOOTS = { Notes = "The itemtype for iron boots" }, E_ITEM_IRON_CHESTPLATE = { Notes = "The itemtype for iron chestplate" }, E_ITEM_IRON_DOOR = { Notes = "The itemtype for iron door" }, E_ITEM_IRON_HELMET = { Notes = "The itemtype for iron helmet" }, E_ITEM_IRON_HOE = { Notes = "The itemtype for iron hoe" }, E_ITEM_IRON_HORSE_ARMOR = { Notes = "The itemtype for iron horse armor" }, E_ITEM_IRON_LEGGINGS = { Notes = "The itemtype for iron leggings" }, E_ITEM_IRON_NUGGET = { Notes = "The itemtype for iron nugget" }, E_ITEM_IRON_PICKAXE = { Notes = "The itemtype for iron pickaxe" }, E_ITEM_IRON_SHOVEL = { Notes = "The itemtype for iron shovel" }, E_ITEM_IRON_SWORD = { Notes = "The itemtype for iron sword" }, E_ITEM_ITEM_FRAME = { Notes = "The itemtype for item frame" }, E_ITEM_JUNGLE_BOAT = { Notes = "The itemtype for jungle boat" }, E_ITEM_JUNGLE_DOOR = { Notes = "The itemtype for jungle door" }, E_ITEM_LAST = { Notes = "The itemtype for last" }, E_ITEM_LAST_DISC = { Notes = "The itemtype for last disc" }, E_ITEM_LAST_DISC_PLUS_ONE = { Notes = "The itemtype for last disc plus one" }, E_ITEM_LAVA_BUCKET = { Notes = "The itemtype for lava bucket" }, E_ITEM_LEAD = { Notes = "The itemtype for lead" }, E_ITEM_LEASH = { Notes = "The itemtype for lead (E_ITEM_LEAD synonym)" }, E_ITEM_LEATHER = { Notes = "The itemtype for leather" }, E_ITEM_LEATHER_BOOTS = { Notes = "The itemtype for leather boots" }, E_ITEM_LEATHER_CAP = { Notes = "The itemtype for leather cap" }, E_ITEM_LEATHER_PANTS = { Notes = "The itemtype for leather pants" }, E_ITEM_LEATHER_TUNIC = { Notes = "The itemtype for leather tunic" }, E_ITEM_LINGERING_POTION = { Notes = "The itemtype for lingering potion" }, E_ITEM_MAGMA_CREAM = { Notes = "The itemtype for magma cream" }, E_ITEM_MALL_DISC = { Notes = "The itemtype for mall disc" }, E_ITEM_MAP = { Notes = "The itemtype for map" }, E_ITEM_MAX_CONSECUTIVE_TYPE_ID = { Notes = "The itemtype for max consecutive type id" }, E_ITEM_MELLOHI_DISC = { Notes = "The itemtype for mellohi disc" }, E_ITEM_MELON_SEEDS = { Notes = "The itemtype for melon seeds" }, E_ITEM_MELON_SLICE = { Notes = "The itemtype for melon slice" }, E_ITEM_MILK = { Notes = "The itemtype for milk" }, E_ITEM_MINECART = { Notes = "The itemtype for minecart" }, E_ITEM_MINECART_WITH_COMMAND_BLOCK = { Notes = "The itemtype for minecart with command block" }, E_ITEM_MINECART_WITH_HOPPER = { Notes = "The itemtype for minecart with hopper" }, E_ITEM_MINECART_WITH_TNT = { Notes = "The itemtype for minecart with tnt" }, E_ITEM_MUSHROOM_SOUP = { Notes = "The itemtype for mushroom soup" }, E_ITEM_NAME_TAG = { Notes = "The itemtype for name tag" }, E_ITEM_NETHER_BRICK = { Notes = "The itemtype for nether brick" }, E_ITEM_NETHER_QUARTZ = { Notes = "The itemtype for nether quartz" }, E_ITEM_NETHER_STAR = { Notes = "The itemtype for nether star" }, E_ITEM_NETHER_WART = { Notes = "The itemtype for nether wart" }, E_ITEM_NUMBER_OF_CONSECUTIVE_TYPES = { Notes = "The itemtype for number of consecutive types" }, E_ITEM_PAINTING = { Notes = "The itemtype for painting" }, E_ITEM_PAPER = { Notes = "The itemtype for paper" }, E_ITEM_POISONOUS_POTATO = { Notes = "The itemtype for poisonous potato" }, E_ITEM_POPPED_CHORUS_FRUIT = { Notes = "The itemtype for popped chorus fruit" }, E_ITEM_POTATO = { Notes = "The itemtype for potato" }, E_ITEM_POTION = { Notes = "The itemtype for potion" }, E_ITEM_POTIONS = { Notes = "The itemtype for potion (obsolete, use E_ITEM_POTION instead)" }, E_ITEM_PRISMARINE_CRYSTALS = { Notes = "The itemtype for prismarine crystals" }, E_ITEM_PRISMARINE_SHARD = { Notes = "The itemtype for prismarine shard" }, E_ITEM_PUMPKIN_PIE = { Notes = "The itemtype for pumpkin pie" }, E_ITEM_PUMPKIN_SEEDS = { Notes = "The itemtype for pumpkin seeds" }, E_ITEM_RABBITS_FOOT = { Notes = "The itemtype for rabbits foot" }, E_ITEM_RABBIT_HIDE = { Notes = "The itemtype for rabbit hide" }, E_ITEM_RABBIT_STEW = { Notes = "The itemtype for rabbit stew" }, E_ITEM_RAW_BEEF = { Notes = "The itemtype for raw beef" }, E_ITEM_RAW_CHICKEN = { Notes = "The itemtype for raw chicken" }, E_ITEM_RAW_FISH = { Notes = "The itemtype for raw fish" }, E_ITEM_RAW_MUTTON = { Notes = "The itemtype for raw mutton" }, E_ITEM_RAW_PORKCHOP = { Notes = "The itemtype for raw porkchop" }, E_ITEM_RAW_RABBIT = { Notes = "The itemtype for raw rabbit" }, E_ITEM_REDSTONE_DUST = { Notes = "The itemtype for redstone dust" }, E_ITEM_REDSTONE_REPEATER = { Notes = "The itemtype for redstone repeater" }, E_ITEM_RED_APPLE = { Notes = "The itemtype for red apple" }, E_ITEM_ROTTEN_FLESH = { Notes = "The itemtype for rotten flesh" }, E_ITEM_SADDLE = { Notes = "The itemtype for saddle" }, E_ITEM_SEEDS = { Notes = "The itemtype for seeds" }, E_ITEM_SHEARS = { Notes = "The itemtype for shears" }, E_ITEM_SHIELD = { Notes = "The itemtype for shield" }, E_ITEM_SHULKER_SHELL = { Notes = "The itemtype for shulker shell" }, E_ITEM_SIGN = { Notes = "The itemtype for sign" }, E_ITEM_SLIMEBALL = { Notes = "The itemtype for slimeball" }, E_ITEM_SNOWBALL = { Notes = "The itemtype for snowball" }, E_ITEM_SPAWN_EGG = { Notes = "The itemtype for spawn egg" }, E_ITEM_SPECTRAL_ARROW = { Notes = "The itemtype for spectral arrow" }, E_ITEM_SPIDER_EYE = { Notes = "The itemtype for spider eye" }, E_ITEM_SPLASH_POTION = { Notes = "The itemtype for splash potion" }, E_ITEM_SPRUCE_BOAT = { Notes = "The itemtype for spruce boat" }, E_ITEM_SPRUCE_DOOR = { Notes = "The itemtype for spruce door" }, E_ITEM_STAL_DISC = { Notes = "The itemtype for stal disc" }, E_ITEM_STEAK = { Notes = "The itemtype for steak" }, E_ITEM_STICK = { Notes = "The itemtype for stick" }, E_ITEM_STONE_AXE = { Notes = "The itemtype for stone axe" }, E_ITEM_STONE_HOE = { Notes = "The itemtype for stone hoe" }, E_ITEM_STONE_PICKAXE = { Notes = "The itemtype for stone pickaxe" }, E_ITEM_STONE_SHOVEL = { Notes = "The itemtype for stone shovel" }, E_ITEM_STONE_SWORD = { Notes = "The itemtype for stone sword" }, E_ITEM_STRAD_DISC = { Notes = "The itemtype for strad disc" }, E_ITEM_STRING = { Notes = "The itemtype for string" }, E_ITEM_SUGAR = { Notes = "The itemtype for sugar" }, E_ITEM_SUGARCANE = { Notes = "The itemtype for sugarcane" }, E_ITEM_SUGAR_CANE = { Notes = "The itemtype for sugar cane" }, E_ITEM_TIPPED_ARROW = { Notes = "The itemtype for tipped arrow" }, E_ITEM_TOTEM_OF_UNDYING = { Notes = "The itemtype for totem of undying" }, E_ITEM_WAIT_DISC = { Notes = "The itemtype for wait disc" }, E_ITEM_WARD_DISC = { Notes = "The itemtype for ward disc" }, E_ITEM_WATER_BUCKET = { Notes = "The itemtype for water bucket" }, E_ITEM_WHEAT = { Notes = "The itemtype for wheat" }, E_ITEM_WOODEN_AXE = { Notes = "The itemtype for wooden axe" }, E_ITEM_WOODEN_DOOR = { Notes = "The itemtype for wooden door" }, E_ITEM_WOODEN_HOE = { Notes = "The itemtype for wooden hoe" }, E_ITEM_WOODEN_PICKAXE = { Notes = "The itemtype for wooden pickaxe" }, E_ITEM_WOODEN_SHOVEL = { Notes = "The itemtype for wooden shovel" }, E_ITEM_WOODEN_SWORD = { Notes = "The itemtype for wooden sword" }, E_ITEM_WRITTEN_BOOK = { Notes = "The itemtype for written book" }, BLOCK_FACE_BOTTOM = { Notes = "Please use BLOCK_FACE_YM instead. Interacting with the bottom face of the block.", }, BLOCK_FACE_EAST = { Notes = "Please use BLOCK_FACE_XM instead. Interacting with the eastern face of the block.", }, BLOCK_FACE_MAX = { Notes = "Used for range checking - highest legal value for an {{Globals#eBlockFace|eBlockFace}}", }, BLOCK_FACE_MIN = { Notes = "Used for range checking - lowest legal value for an {{Globals#eBlockFace|eBlockFace}}", }, BLOCK_FACE_NONE = { Notes = "Interacting with no block face - swinging the item in the air", }, BLOCK_FACE_NORTH = { Notes = "Please use BLOCK_FACE_ZM instead. Interacting with the northern face of the block.", }, BLOCK_FACE_SOUTH = { Notes = "Please use BLOCK_FACE_ZP instead. Interacting with the southern face of the block.", }, BLOCK_FACE_TOP = { Notes = "Please use BLOCK_FACE_YP instead. Interacting with the top face of the block.", }, BLOCK_FACE_WEST = { Notes = "Please use BLOCK_FACE_XP instead. Interacting with the western face of the block.", }, BLOCK_FACE_XM = { Notes = "Interacting with the X- face of the block", }, BLOCK_FACE_XP = { Notes = "Interacting with the X+ face of the block", }, BLOCK_FACE_YM = { Notes = "Interacting with the Y- face of the block", }, BLOCK_FACE_YP = { Notes = "Interacting with the Y+ face of the block", }, BLOCK_FACE_ZM = { Notes = "Interacting with the Z- face of the block", }, BLOCK_FACE_ZP = { Notes = "Interacting with the Z+ face of the block", }, DIG_STATUS_CANCELLED = { Notes = "The player has let go of the mine block key before finishing mining the block", }, DIG_STATUS_DROP_HELD = { Notes = "The player has dropped a single item using the Drop Item key (default: Q)", }, DIG_STATUS_DROP_STACK = { Notes = "The player has dropped a full stack of items using the Drop Item key (default: Q) while holding down a specific modifier key (in windows, control)", }, DIG_STATUS_FINISHED = { Notes = "The player thinks that it has finished mining a block", }, DIG_STATUS_SHOOT_EAT = { Notes = "The player has finished shooting a bow or finished eating", }, DIG_STATUS_STARTED = { Notes = "The player has started digging", }, DIG_STATUS_SWAP_ITEM_IN_HAND = { Notes = "The player has swapped their held item with the item in their offhand slot (1.9)", }, E_META_BIG_FLOWER_TOP = { Notes = "The metadata of a big flower block that indicates it is the top block.", }, E_META_CONCRETE_BLACK = { Notes = "A flag in the metadata of concete that indicates that the concrete is black.", }, E_META_CONCRETE_BLUE = { Notes = "A flag in the metadata of concete that indicates that the concrete is blue.", }, E_META_CONCRETE_BROWN = { Notes = "A flag in the metadata of concete that indicates that the concrete is brown.", }, E_META_CONCRETE_CYAN = { Notes = "A flag in the metadata of concete that indicates that the concrete is cyan.", }, E_META_CONCRETE_GRAY = { Notes = "A flag in the metadata of concete that indicates that the concrete is gray.", }, E_META_CONCRETE_GREEN = { Notes = "A flag in the metadata of concete that indicates that the concrete is green.", }, E_META_CONCRETE_LIGHTBLUE = { Notes = "A flag in the metadata of concete that indicates that the concrete is light blue.", }, E_META_CONCRETE_LIGHTGRAY = { Notes = "A flag in the metadata of concete that indicates that the concrete is light gray.", }, E_META_CONCRETE_LIGHTGREEN = { Notes = "A flag in the metadata of concete that indicates that the concrete is light green.", }, E_META_CONCRETE_MAGENTA = { Notes = "A flag in the metadata of concete that indicates that the concrete is magenta.", }, E_META_CONCRETE_ORANGE = { Notes = "A flag in the metadata of concete that indicates that the concrete is orange.", }, E_META_CONCRETE_PINK = { Notes = "A flag in the metadata of concete that indicates that the concrete is pink.", }, E_META_CONCRETE_POWDER_BLACK = { Notes = "A flag in the metadata of concete powder that indicates that the concrete powder is black.", }, E_META_CONCRETE_POWDER_BLUE = { Notes = "A flag in the metadata of concete powder that indicates that the concrete powder is blue.", }, E_META_CONCRETE_POWDER_BROWN = { Notes = "A flag in the metadata of concete powder that indicates that the concrete powder is brown.", }, E_META_CONCRETE_POWDER_CYAN = { Notes = "A flag in the metadata of concete powder that indicates that the concrete powder is cyan.", }, E_META_CONCRETE_POWDER_GRAY = { Notes = "A flag in the metadata of concete powder that indicates that the concrete powder is gray.", }, E_META_CONCRETE_POWDER_GREEN = { Notes = "A flag in the metadata of concete powder that indicates that the concrete powder is green.", }, E_META_CONCRETE_POWDER_LIGHTBLUE = { Notes = "A flag in the metadata of concete powder that indicates that the concrete powder is light blue.", }, E_META_CONCRETE_POWDER_LIGHTGRAY = { Notes = "A flag in the metadata of concete powder that indicates that the concrete powder is light gray.", }, E_META_CONCRETE_POWDER_LIGHTGREEN = { Notes = "A flag in the metadata of concete powder that indicates that the concrete powder is light green.", }, E_META_CONCRETE_POWDER_MAGENTA = { Notes = "A flag in the metadata of concete powder that indicates that the concrete powder is magenta.", }, E_META_CONCRETE_POWDER_ORANGE = { Notes = "A flag in the metadata of concete powder that indicates that the concrete powder is orange.", }, E_META_CONCRETE_POWDER_PINK = { Notes = "A flag in the metadata of concete powder that indicates that the concrete powder is pink.", }, E_META_CONCRETE_POWDER_PURPLE = { Notes = "A flag in the metadata of concete powder that indicates that the concrete powder is purple.", }, E_META_CONCRETE_POWDER_RED = { Notes = "A flag in the metadata of concete powder that indicates that the concrete powder is red.", }, E_META_CONCRETE_POWDER_WHITE = { Notes = "A flag in the metadata of concete powder that indicates that the concrete powder is white.", }, E_META_CONCRETE_POWDER_YELLOW = { Notes = "A flag in the metadata of concete powder that indicates that the concrete powder is yellow.", }, E_META_CONCRETE_PURPLE = { Notes = "A flag in the metadata of concete that indicates that the concrete is purple.", }, E_META_CONCRETE_RED = { Notes = "A flag in the metadata of concete that indicates that the concrete is red.", }, E_META_CONCRETE_WHITE = { Notes = "A flag in the metadata of concete that indicates that the concrete is white.", }, E_META_CONCRETE_YELLOW = { Notes = "A flag in the metadata of concete that indicates that the concrete is yellow.", }, E_META_DROPSPENSER_ACTIVATED = { Notes = "A flag in the metadata of droppers and dispensers that indicates that the dropper or dispenser is currently activated. If this flag is set, the block must be unpowered first and powered again to shoot the next item.", }, E_META_DROPSPENSER_FACING_MASK = { Notes = "A mask that indicates the bits of the metadata that specify the facing of droppers and dispensers.", }, E_META_DROPSPENSER_FACING_XM = { Notes = "A flag in the metadata of droppers and dispensers that indicates that the dropper or dispenser is looking in the negative X direction.", }, E_META_DROPSPENSER_FACING_XP = { Notes = "A flag in the metadata of droppers and dispensers that indicates that the dropper or dispenser is looking in the positive X direction.", }, E_META_DROPSPENSER_FACING_YM = { Notes = "A flag in the metadata of droppers and dispensers that indicates that the dropper or dispenser is looking in the negative Y direction.", }, E_META_DROPSPENSER_FACING_YP = { Notes = "A flag in the metadata of droppers and dispensers that indicates that the dropper or dispenser is looking in the positive Y direction.", }, E_META_DROPSPENSER_FACING_ZM = { Notes = "A flag in the metadata of droppers and dispensers that indicates that the dropper or dispenser is looking in the negative Z direction.", }, E_META_DROPSPENSER_FACING_ZP = { Notes = "A flag in the metadata of droppers and dispensers that indicates that the dropper or dispenser is looking in the positive Z direction.", }, E_META_END_PORTAL_FRAME_EYE = { Notes = "A flag in the metadata of end portal frames that indicates that the portal frame has an eye in it.", }, E_META_END_PORTAL_FRAME_NO_EYE = { Notes = "The lack of the flag in the metadata of end portal frames indicating that the portal frame has an eye in it.", }, E_META_END_PORTAL_FRAME_XM = { Notes = "A flag in the metadata of end portal frames that indicates that the portal frame is facing the negative X direction.", }, E_META_END_PORTAL_FRAME_XP = { Notes = "A flag in the metadata of end portal frames that indicates that the portal frame is facing the positive X direction.", }, E_META_END_PORTAL_FRAME_ZM = { Notes = "A flag in the metadata of end portal frames that indicates that the portal frame is facing the negative Z direction.", }, E_META_END_PORTAL_FRAME_ZP = { Notes = "A flag in the metadata of end portal frames that indicates that the portal frame is facing the positive Z direction.", }, E_META_END_PORTAL_FRAME_XM_EYE = { Notes = "A flag in the metadata of end portal frames that indicates that the portal frame is facing the negative X direction and has an ender eye in it.", }, E_META_END_PORTAL_FRAME_XP_EYE = { Notes = "A flag in the metadata of end portal frames that indicates that the portal frame is facing the positive X direction and has an ender eye in it.", }, E_META_END_PORTAL_FRAME_ZM_EYE = { Notes = "A flag in the metadata of end portal frames that indicates that the portal frame is facing the negative Z direction and has an ender eye in it.", }, E_META_END_PORTAL_FRAME_ZP_EYE = { Notes = "A flag in the metadata of end portal frames that indicates that the portal frame is facing the positive Z direction and has an ender eye in it.", }, E_META_HEAD_CREEPER = { Notes = "A flag in the metadata of heads that indicates that the head is a creeper head.", }, E_META_HEAD_DRAGON = { Notes = "A flag in the metadata of heads that indicates that the head is a dragon head.", }, E_META_HEAD_PLAYER = { Notes = "A flag in the metadata of heads that indicates that the head is a player head.", }, E_META_HEAD_SKELETON = { Notes = "A flag in the metadata of heads that indicates that the head is a skeleton head.", }, E_META_HEAD_WITHER = { Notes = "A flag in the metadata of heads that indicates that the head is a wither head.", }, E_META_HEAD_ZOMBIE = { Notes = "A flag in the metadata of heads that indicates that the head is a zombie head.", }, E_META_REDSTONE_REPEATER_FACING_ZM = { Notes = "A flag in the metadata of redstone repeaters that indicates that the repeater is looking in the negative Z direction.", }, E_META_REDSTONE_REPEATER_FACING_XP = { Notes = "A flag in the metadata of redstone repeaters that indicates that the repeater is looking in the positive X direction.", }, E_META_REDSTONE_REPEATER_FACING_ZP = { Notes = "A flag in the metadata of redstone repeaters that indicates that the repeater is looking in the positive Z direction.", }, E_META_REDSTONE_REPEATER_FACING_XM = { Notes = "A flag in the metadata of redstone repeaters that indicates that the repeater is looking in the negative X direction.", }, E_META_REDSTONE_REPEATER_FACING_MASK = { Notes = "A mask that indicates the bits of the metadata that specify the facing of redstone repeaters.", }, E_META_SPAWN_EGG_ENDERMITE = { Notes = "", }, E_META_SPAWN_EGG_WITHER_SKELETON = { Notes = "" }, E_META_SILVERFISH_EGG_CHISELED_STONE_BRICK = { Notes = "A flag in the metadata of the silverfish egg that the block is made from chiseled stone bricks" }, E_META_SILVERFISH_EGG_CRACKED_STONE_BRICK = { Notes = "A flag in the metadata of the silverfish egg that the block is made from cracked stone bricks" }, E_META_SILVERFISH_EGG_MOSSY_STONE_BRICK = { Notes = "A flag in the metadata of the silverfish egg that the block is made from mossy stone bricks" }, E_META_SPONGE_DRY = { Notes = "A flag in the metadata of sponges that indicates that the sponge is dry.", }, E_META_SPONGE_WET = { Notes = "A flag in the metadata of sponges that indicates that the sponge is wet.", }, E_META_MUSHROOM_ALL_SIDES = { Notes = "A flag in the metadata of mushroom blocks to display the outside texture on all sides.", }, E_META_MUSHROOM_NORTH_WEST = { Notes = "A flag in the metadata of mushroom blocks to display the pore texture on north and west side.", }, E_META_MUSHROOM_NORTH = { Notes = "A flag in the metadata of mushroom blocks to display the outside texture on north side.", }, E_META_MUSHROOM_NORTH_EAST = { Notes = "A flag in the metadata of mushroom blocks to display the outside texture on north and east side.", }, E_META_MUSHROOM_WEST = { Notes = "A flag in the metadata of mushroom blocks to display the outside texture on west side.", }, E_META_MUSHROOM_CENTER = { Notes = "A flag in the metadata of mushroom blocks to display the outside texture on top.", }, E_META_MUSHROOM_EAST = { Notes = "A flag in the metadata of mushroom blocks to display the outside texture on east side.", }, E_META_MUSHROOM_SOUTH_WEST = { Notes = "A flag in the metadata of mushroom blocks to display the outside texture on south and west side.", }, E_META_MUSHROOM_SOUTH = { Notes = "A flag in the metadata of mushroom blocks to display the outside texture on south side.", }, E_META_MUSHROOM_SOUTH_EAST = { Notes = "A flag in the metadata of mushroom blocks to display the outside texture on south and east side.", }, E_META_MUSHROOM_STEM = { Notes = "A flag in the metadata of mushroom blocks to display the stem texture on all sides but not on top and bottom.", }, E_META_MUSHROOM_CAP = { Notes = "A flag in the metadata of mushroom blocks to display the outside texture on all sides.", }, E_META_MUSHROOM_FULL_STEM = { Notes = "A flag in the metadata of mushroom blocks to display the stem texture on all sides.", }, esBed = { Notes = "A bed explosion. The SourceData param is the {{Vector3i|position}} of the bed.", }, esEnderCrystal = { Notes = "An ender crystal entity explosion. The SourceData param is the {{cEntity|ender crystal entity}} object.", }, esGhastFireball = { Notes = "A ghast fireball explosion. The SourceData param is the {{cGhastFireballEntity|ghast fireball entity}} object.", }, esMonster = { Notes = "A monster explosion (creeper). The SourceData param is the {{cMonster|monster entity}} object.", }, esOther = { Notes = "Any other explosion. The SourceData param is unused.", }, esPlugin = { Notes = "An explosion started by a plugin, without any further information. The SourceData param is unused. ", }, esPrimedTNT = { Notes = "A TNT explosion. The SourceData param is the {{cTNTEntity|TNT entity}} object.", }, esTNTMinecart = { Notes = "A TNT minecart explosion. The SourceData param is the {{cMinecartWithTNT|Minecart with TNT entity}} object.", }, esWitherBirth = { Notes = "An explosion at a wither's birth. The SourceData param is the {{cMonster|wither entity}} object.", }, esWitherSkull = { Notes = "A wither skull explosion. The SourceData param is the {{cWitherSkullEntity|wither skull entity}} object.", }, -- eMonsterType: mtBat = { Notes = "", }, mtBlaze = { Notes = "", }, mtCaveSpider = { Notes = "", }, mtCat = { Notes = "", }, mtChicken = { Notes = "", }, mtCod = { Notes = "", }, mtCow = { Notes = "", }, mtCreeper = { Notes = "", }, mtDolphin = { Notes = "", }, mtDonkey = { Notes = "", }, mtDrowned = { Notes = "", }, mtElderGuardian = { Notes = "", }, mtEnderDragon = { Notes = "", }, mtEnderman = { Notes = "", }, mtEndermite = { Notes = "", }, mtEvoker = { Notes = "", }, mtFox = { Notes = "", }, mtGhast = { Notes = "", }, mtGiant = { Notes = "", }, mtHoglin = { Notes = "", }, mtHorse = { Notes = "", }, mtHusk = { Notes = "", }, mtIllusioner = { Notes = "", }, mtInvalidType = { Notes = "Invalid monster type. Returned when monster type not recognized", }, mtIronGolem = { Notes = "", }, mtLlama = { Notes = "", }, mtMagmaCube = { Notes = "", }, mtMooshroom = { Notes = "", }, mtMule = { Notes = "", }, mtOcelot = { Notes = "", }, mtPanda = { Notes = "", }, mtParrot = { Notes = "", }, mtPhantom = { Notes = "", }, mtPig = { Notes = "", }, mtPiglin = { Notes = "", }, mtPiglinBrute = { Notes = "", }, mtPillager = { Notes = "", }, mtPolarBear = { Notes = "", }, mtPufferfish = { Notes = "", }, mtRavager = { Notes = "", }, mtSalmon = { Notes = "", }, mtSheep = { Notes = "", }, mtShulker = { Notes = "", }, mtSilverfish = { Notes = "", }, mtSkeleton = { Notes = "", }, mtSkeletonHorse = { Notes = "", }, mtSlime = { Notes = "", }, mtStray = { Notes = "", }, mtStrider = { Notes = "", }, mtSnowGolem = { Notes = "", }, mtSpider = { Notes = "", }, mtSquid = { Notes = "", }, mtTraderLlama = { Notes = "", }, mtTropicalFish = { Notes = "", }, mtTurtle = { Notes = "", }, mtVex = { Notes = "", }, mtVillager = { Notes = "", }, mtVindicator = { Notes = "", }, mtWanderingTrader = { Notes = "", }, mtWitch = { Notes = "", }, mtWither = { Notes = "", }, mtWitherSkeleton = { Notes = "", }, mtWolf = { Notes = "", }, mtZoglin = { Notes = "", }, mtZombie = { Notes = "", }, mtZombieHorse = { Notes = "", }, mtZombiePigman = { Notes = "", }, mtZombifiedPiglin = { Notes = "", }, mtZombieVillager = { Notes = "", }, -- eMessageType: mtCustom = { Notes = "Send raw data without any processing", }, mtDeath = { Notes = "Denotes death of player", }, mtError = { Notes = "Something could not be done (i.e. command not executed due to insufficient privilege)", }, mtFail = { Notes = "Something could not be done (i.e. command not executed due to insufficient privilege)", }, mtFailure = { Notes = "Something could not be done (i.e. command not executed due to insufficient privilege)", }, mtFatal = { Notes = "Something catastrophic occured (i.e. plugin crash)", }, mtInfo = { Notes = "Informational message (i.e. command usage)", }, mtInformation = { Notes = "Informational message (i.e. command usage)", }, mtJoin = { Notes = "A player has joined the server", }, mtLeave = { Notes = "A player has left the server", }, mtMaxPlusOne = { Notes = "The first invalid type, used for checking on LuaAPI boundaries", }, mtPM = { Notes = "Player to player messaging identifier", }, mtPrivateMessage = { Notes = "Player to player messaging identifier", }, mtSuccess = { Notes = "Something executed successfully", }, mtWarning = { Notes = "Something concerning (i.e. reload) is about to happen", }, mtWitherSkeleton = { Notes = "" }, SKULL_TYPE_CREEPER = { Notes = "A creeper skull", }, SKULL_TYPE_DRAGON = { Notes = "A dragon skull", }, SKULL_TYPE_PLAYER = { Notes = "A player skull", }, SKULL_TYPE_SKELETON = { Notes = "A skeleton skull", }, SKULL_TYPE_WITHER = { Notes = "A wither skull", }, SKULL_TYPE_ZOMBIE = { Notes = "A zombie skull", }, spCape = { Notes = "The cape skin part", }, spJacket = { Notes = "The jacket skin part", }, spLeftSleeve = { Notes = "The left sleeve skin part", }, spRightSleeve = { Notes = "The right sleeve skin part", }, spLeftPants = { Notes = "The left pants leg skin part", }, spRightPants = { Notes = "The right pants leg skin part", }, spHat = { Notes = "The hat/head skin part", }, spMask = { Notes = "A mask of all valid skin parts combined", }, }, ConstantGroups = { eBlockFace = { Include = "^BLOCK_FACE_.*", TextBefore = [[ These constants are used to describe individual faces of the block. They are used when the client is interacting with a block in the {{OnPlayerBreakingBlock|HOOK_PLAYER_BREAKING_BLOCK}}, {{OnPlayerBrokenBlock|HOOK_PLAYER_BROKEN_BLOCK}}, {{OnPlayerLeftClick|HOOK_PLAYER_LEFT_CLICK}}, {{OnPlayerPlacedBlock|HOOK_PLAYER_PLACED_BLOCK}}, {{OnPlayerPlacingBlock|HOOK_PLAYER_PLACING_BLOCK}}, {{OnPlayerRightClick|HOOK_PLAYER_RIGHT_CLICK}}, {{OnPlayerUsedBlock|HOOK_PLAYER_USED_BLOCK}}, {{OnPlayerUsedItem|HOOK_PLAYER_USED_ITEM}}, {{OnPlayerUsingBlock|HOOK_PLAYER_USING_BLOCK}}, and {{OnPlayerUsingItem|HOOK_PLAYER_USING_ITEM}} hooks, or when the {{cLineBlockTracer}} hits a block, etc. ]], }, eBlockType = { Include = "^E_BLOCK_.*", TextBefore = [[ These constants are used for block types. They correspond directly with MineCraft's data values for blocks. ]], }, eClickAction = { Include = "^ca.*", TextBefore = [[ These constants are used to signalize various interactions that the user can do with the {{cWindow|UI windows}}. The server translates the protocol events into these constants. Note that there is a global ClickActionToString() function that can translate these constants into their textual representation. ]], }, eDamageType = { Include = "^dt.*", TextBefore = [[ These constants are used for specifying the cause of damage to entities. They are used in the {{TakeDamageInfo}} structure, as well as in {{cEntity}}'s damage-related API functions. ]], }, DigStatuses = { Include = "^DIG_STATUS_.*", TextBefore = [[ These constants are used to describe digging statuses, but in reality cover several more cases. They are used with {{OnPlayerLeftClick|HOOK_PLAYER_LEFT_CLICK}}. ]], }, eDimension = { Include = "^dim.*", TextBefore = [[ These constants represent dimension of a world. In Cuberite, the dimension is only reflected in the world's overall tint - overworld gets sky-like colors and dark shades, the nether gets reddish haze and the end gets dark haze. World generator is not directly affected by the dimension, same as fluid simulators; those only default to the expected values if not set specifically otherwise in the world.ini file. ]], }, eExplosionSource = { Include = "^es.*", TextBefore = [[ These constants are used to differentiate the various sources of explosions. They are used in the {{OnExploded|HOOK_EXPLODED}} hook, {{OnExploding|HOOK_EXPLODING}} hook and in the {{cWorld}}:DoExplosionAt() function. These constants also dictate the type of the additional data provided with the explosions, such as the exploding creeper {{cEntity|entity}} or the {{Vector3i|coords}} of the exploding bed. ]], }, eGameMode = { Include = { "^gm.*", "^eGameMode_.*", }, TextBefore = [[ The following constants are used for the gamemode - survival, creative or adventure. Use the gmXXX constants, the eGameMode_ constants are deprecated and will be removed from the API. ]], }, EMCSBiome = { Include = "^bi.*", TextBefore = [[ These constants represent the biomes that the server understands. Note that there is a global StringToBiome() function that can convert a string into one of these constants. ]], }, eMessageType = { -- Need to be specified explicitly, because there's also eMonsterType using the same "mt" prefix Include = { "mtCustom", "mtDeath", "mtError", "mtFail", "mtFailure", "mtFatal", "mtInfo", "mtInformation", "mtJoin", "mtLeave", "mtMaxPlusOne", "mtPrivateMessage", "mtPM", "mtSuccess", "mtWarning", }, TextBefore = [[ These constants are used together with messaging functions and classes, they specify the type of message being sent. The server can be configured to modify the message text (add prefixes) based on the message's type. ]], }, eMobHeadType = { Include = "SKULL_TYPE_.*", }, eMobHeadRotation = { Include = "SKULL_ROTATION_.*", }, eMonsterType = { Include = { "mtInvalidType", "mtBat", "mtBlaze", "mtCaveSpider", "mtChicken", "mtCow", "mtCreeper", "mtEnderDragon", "mtEnderman", "mtGhast", "mtGiant", "mtGuardian", "mtHorse", "mtIronGolem", "mtMagmaCube", "mtMooshroom", "mtOcelot", "mtPig", "mtRabbit", "mtSheep", "mtSilverfish", "mtSkeleton", "mtSlime", "mtSnowGolem", "mtSpider", "mtSquid", "mtVillager", "mtWitch", "mtWither", "mtWitherSkeleton", "mtWolf", "mtZombie", "mtZombiePigman", "mtZombieVillager", "mtMax", }, TextBefore = [[ The following constants are used for distinguishing between the individual mob types: ]], }, eShrapnelLevel = { Include = "^sl.*", TextBefore = [[ The following constants define the block types that are propelled outwards after an explosion. ]], }, eSkinPart = { Include = { "^sp.*", }, TextBefore = [[ These constants represent various skin part flags. ]], }, eSpreadSource = { Include = "^ss.*", TextBefore = [[ These constants are used to differentiate the various sources of spreads, such as grass growing. They are used in the {{OnBlockSpread|HOOK_BLOCK_SPREAD}} hook. ]], }, eWeather = { Include = { "^eWeather_.*", "wSunny", "wRain", "wStorm", "wThunderstorm", }, TextBefore = [[ These constants represent the weather in the world. Note that unlike vanilla, Cuberite allows different weathers even in non-overworld {{Globals#eDimension|dimensions}}. ]], }, ItemTypes = { Include = "^E_ITEM_.*", TextBefore = [[ These constants are used for item types. They correspond directly with MineCraft's data values for items. ]], }, MetaValues = { Include = "^E_META_.*", }, }, }, ItemCategory = { Desc = [[ This class contains static functions for determining item categories. All of the functions are called directly on the class table, unlike most other object, which require an instance first. ]], Functions = { IsArmor = { IsStatic = true, Params = { { Name = "ItemType", Type = "number", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if the specified item type is any kind of an armor.", }, IsAxe = { IsStatic = true, Params = { { Name = "ItemType", Type = "number", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if the specified item type is any kind of an axe.", }, IsBoots = { IsStatic = true, Params = { { Name = "ItemType", Type = "number", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if the specified item type is any kind of boots.", }, IsChestPlate = { IsStatic = true, Params = { { Name = "ItemType", Type = "number", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if the specified item type is any kind of a chestplate.", }, IsHelmet = { IsStatic = true, Params = { { Name = "ItemType", Type = "number", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if the specified item type is any kind of a helmet.", }, IsHoe = { IsStatic = true, Params = { { Name = "ItemType", Type = "number", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if the specified item type is any kind of a hoe.", }, IsHorseArmor= { IsStatic = true, Params = { { Name = "ItemType", Type = "number", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if the specified item type is any kind of a horse armor.", }, IsLeggings = { IsStatic = true, Params = { { Name = "ItemType", Type = "number", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if the specified item type is any kind of a leggings.", }, IsMinecart = { IsStatic = true, Params = { { Name = "ItemType", Type = "number", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if the specified item type is any kind of a minecart.", }, IsPickaxe = { IsStatic = true, Params = { { Name = "ItemType", Type = "number", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if the specified item type is any kind of a pickaxe.", }, IsShovel = { IsStatic = true, Params = { { Name = "ItemType", Type = "number", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if the specified item type is any kind of a shovel.", }, IsSword = { IsStatic = true, Params = { { Name = "ItemType", Type = "number", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if the specified item type is any kind of a sword.", }, IsTool = { IsStatic = true, Params = { { Name = "ItemType", Type = "number", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if the specified item type is any kind of a tool (axe, hoe, pickaxe, shovel or FIXME: sword)", }, IsVillagerFood = { IsStatic = true, Params = { { Name = "ItemType", Type = "number", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if the specified item type is any kind of a pickable food by a villager (potato, carrot, wheat, bread and any kind of seeds).", } }, AdditionalInfo = { { Header = "Code example", Contents = [[ The following code snippet checks if the player holds a shovel.
    -- a_Player is a {{cPlayer}} object, possibly received as a hook param
    local HeldItem = a_Player:GetEquippedItem()
    if (ItemCategory.IsShovel(HeldItem.m_ItemType)) then
    	-- It's a shovel
    end
    
    ]], }, }, }, lxp = { Desc = [[ This class provides an interface to the XML parser, {{https://matthewwild.co.uk/projects/luaexpat/|LuaExpat}}. It provides a SAX interface with an incremental XML parser.

    With an event-based API like SAX the XML document can be fed to the parser in chunks, and the parsing begins as soon as the parser receives the first document chunk. LuaExpat reports parsing events (such as the start and end of elements) directly to the application through callbacks. The parsing of huge documents can benefit from this piecemeal operation.

    See the online {{https://matthewwild.co.uk/projects/luaexpat/manual.html#parser|LuaExpat documentation}} for details on how to work with this parser. The code examples below should provide some basic help, too. ]], Functions = { new = { Params = { { Name = "CallbacksTable", Type = "table", }, { Name = "SeparatorChar", Type = "string", IsOptional = true, }, }, Returns = { { Name = "XMLParser object", Type = "table", }, }, Notes = "Creates a new XML parser object, with the specified callbacks table and optional separator character.", }, }, Constants = { _COPYRIGHT = { Notes = "", }, _DESCRIPTION = { Notes = "", }, _VERSION = { Notes = "", }, }, AdditionalInfo = { { Header = "Parser callbacks", Contents = [[ The callbacks table passed to the new() function specifies the Lua functions that the parser calls upon various events. The following table lists the most common functions used, for a complete list see the online {{https://matthewwild.co.uk/projects/luaexpat/manual.html#parser|LuaExpat documentation}}.

    Function nameParametersNotes
    CharacterDataParser, stringCalled when the parser recognizes a raw string inside the element
    EndElementParser, ElementNameCalled when the parser detects the ending of an XML element
    StartElementParser, ElementName, AttributesTableCalled when the parser detects the start of an XML element. The AttributesTable is a Lua table containing all the element's attributes, both in the array section (in the order received) and in the dictionary section.
    ]], }, { Header = "XMLParser object", Contents = [[ The XMLParser object returned by lxp.new provides the functions needed to parse the XML. The following list provides the most commonly used ones, for a complete list see the online {{https://matthewwild.co.uk/projects/luaexpat/manual.html#parser|LuaExpat documentation}}.
    • close() - closes the parser, freeing all memory used by it.
    • getCallbacks() - returns the callbacks table for this parser.
    • parse(string) - parses more document data. the string contains the next part (or possibly all) of the document. Returns non-nil for success or nil, msg, line, col, pos for error.
    • stop() - aborts parsing (can be called from within the parser callbacks).
    ]], }, { Header = "Code example", Contents = [[ The following code reads an entire XML file and outputs its logical structure into the console:
    local Depth = 0;
    
    -- Define the callbacks:
    local Callbacks = {
    	CharacterData = function(a_Parser, a_String)
    		LOG(string.rep(" ", Depth) .. "* " .. a_String);
    	end
    
    	EndElement = function(a_Parser, a_ElementName)
    		Depth = Depth - 1;
    		LOG(string.rep(" ", Depth) .. "- " .. a_ElementName);
    	end
    
    	StartElement = function(a_Parser, a_ElementName, a_Attribs)
    		LOG(string.rep(" ", Depth) .. "+ " .. a_ElementName);
    		Depth = Depth + 1;
    	end
    }
    
    -- Create the parser:
    local Parser = lxp.new(Callbacks);
    
    -- Parse the XML file:
    local f = io.open("file.xml", "rb");
    while (true) do
    	local block = f:read(128 * 1024);  -- Use a 128KiB buffer for reading
    	if (block == nil) then
    		-- End of file
    		break;
    	end
    	Parser:parse(block);
    end
    
    -- Signalize to the parser that no more data is coming
    Parser:parse();
    
    -- Close the parser:
    Parser:close();
    
    ]], }, }, }, sqlite3 = { Desc = [[ ]], Functions = { complete = { IsStatic = true, IsGlobal = true, -- Emulate a global function without a self parameter - this is called with a dot convention Params = { { Name = "SQL", Type = "string", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if the input string comprises one or more complete SQL statements.", }, open = { IsStatic = true, IsGlobal = true, -- Emulate a global function without a self parameter - this is called with a dot convention Params = { { Name = "FileName", Type = "string", }, }, Returns = { { Name = "DBClass", Type = "SQLite DB object", }, }, Notes = [[ Opens (or creates if it does not exist) an SQLite database with name filename and returns its handle (the returned object should be used for all further method calls in connection with this specific database, see {{http://lua.sqlite.org/index.cgi/doc/tip/doc/lsqlite3.wiki#database_methods|Database methods}}). Example:
    -- open the database:
    myDB = sqlite3.open('MyDatabaseFile.sqlite3')
    
    -- do some database calls...
    
    -- Close the database:
    myDB:close()
    
    ]], }, open_memory = { IsStatic = true, IsGlobal = true, -- Emulate a global function without a self parameter - this is called with a dot convention Returns = { { Name = "DBClass", Type = "SQLite DB object", }, }, Notes = "Opens an SQLite database in memory and returns its handle. In case of an error, the function returns nil, an error code and an error message. (In-memory databases are volatile as they are never stored on disk.)", }, version = { IsStatic = true, IsGlobal = true, -- Emulate a global function without a self parameter - this is called with a dot convention Returns = { { Type = "string", }, }, Notes = "Returns a string with SQLite version information, in the form 'x.y[.z]'.", }, }, }, TakeDamageInfo = { Desc = [[ This class contains the amount of damage, and the entity that caused the damage. It is used in the {{OnTakeDamage|HOOK_TAKE_DAMAGE}} hook and in the {{cEntity}}'s TakeDamage() function. ]], Variables = { Attacker = { Type = "{{cEntity}}", Notes = "The entity who is attacking. Only valid if dtAttack.", }, DamageType = { Type = "eDamageType", Notes = "Source of the damage. One of the dtXXX constants.", }, FinalDamage = { Type = "number", Notes = "The final amount of damage that will be applied to the Receiver. It is the RawDamage minus any Receiver's armor-protection.", }, Knockback = { Type = "{{Vector3d}}", Notes = "Vector specifying the amount and direction of knockback that will be applied to the Receiver ", }, RawDamage = { Type = "number", Notes = "Amount of damage that the attack produces on the Receiver, including the Attacker's equipped weapon, but excluding the Receiver's armor.", }, }, AdditionalInfo = { { Header = "", Contents = [[ The TDI is passed as the second parameter in the HOOK_TAKE_DAMAGE hook, and can be used to modify the damage before it is applied to the receiver:
    function OnTakeDamage(Receiver, TDI)
    	LOG("Damage: Raw ".. TDI.RawDamage .. ", Final:" .. TDI.FinalDamage);
    
    	-- If the attacker is a spider, make it deal 999 points of damage (insta-death spiders):
    	if ((TDI.Attacker ~= nil) and TDI.Attacker:IsA("cSpider")) then
    		TDI.FinalDamage = 999;
    	end
    end
    
    ]], }, }, }, tolua = { Desc = [[ This class represents the tolua bridge between the Lua API and Cuberite. It supports some low level operations and queries on the objects. See also the tolua++'s documentation at {{https://www8.cs.umu.se/kurser/TDBD12/VT04/lab/lua/tolua++.html#utilities}}. Normally you shouldn't use any of these functions except for type() ]], Functions = { cast = { IsStatic = true, IsGlobal = true, -- Emulate a global function without a self parameter - this is called with a dot convention Params = { { Name = "Object", Type = "any", }, { Name = "TypeStr", Type = "string", }, }, Returns = { { Name = "Object", Type = "any", }, }, Notes = "Casts the object to the specified type.
    Note: This is a potentially unsafe operation and it could crash the server. There is normally no need to use this function at all, so don't use it unless you know exactly what you're doing.", }, getpeer = { Notes = "", }, inherit = { Notes = "", }, releaseownership = { Notes = "", }, setpeer = { Notes = "", }, takeownership = { Notes = "", }, type = { IsStatic = true, IsGlobal = true, -- Emulate a global function without a self parameter - this is called with a dot convention Params = { { Name = "Object", Type = "any", }, }, Returns = { { Name = "TypeStr", Type = "string", }, }, Notes = "Returns a string representing the type of the object. This works similar to Lua's built-in type() function, but recognizes the underlying C++ classes, too.", }, }, }, }, ExtraPages = { { FileName = "Writing-a-Cuberite-plugin.html", Title = "Writing a Cuberite plugin", }, { FileName = "InfoFile.html", Title = "Using the Info.lua file", }, { FileName = "SettingUpDecoda.html", Title = "Setting up the Decoda Lua IDE", }, { FileName = "SettingUpZeroBrane.html", Title = "Setting up the ZeroBrane Studio Lua IDE", }, { FileName = "SettingUpLuaLanguageServer.html", Title = "Setting up Lua-Language-Server (VSCode/Emacs)" }, { FileName = "UsingChunkStays.html", Title = "Using ChunkStays", }, { FileName = "WebWorldThreads.html", Title = "Webserver vs World threads", }, }, IgnoreClasses = { "^coroutine$", "^g_TrackedPages$", "^debug$", "^io$", "^math$", "^package$", "^os$", "^string$", "^table$", "^g_Stats$", }, IgnoreFunctions = { "Globals.assert", "%a+%.delete", "CreateAPITables", "DumpAPIHtml", "DumpAPITxt", "Initialize", "LinkifyString", "ListMissingPages", "ListUndocumentedObjects", "ListUnexportedObjects", "LoadAPIFiles", "Globals.collectgarbage", "ReadDescriptions", "ReadHooks", "WriteHtmlClass", "WriteHtmlHook", "WriteStats", "Globals.xpcall", "Globals.decoda_output", "sqlite3.__newindex", "%a+%.__%a+", "%a+%.%.collector", "%a+%.new", "%a+%.new_local", }, IgnoreConstants = { "cChestEntity.__cBlockEntityWindowOwner__", "cDropSpenserEntity.__cBlockEntityWindowOwner__", "cFurnaceEntity.__cBlockEntityWindowOwner__", "cHopperEntity.__cBlockEntityWindowOwner__", "cLuaWindow.__cItemGrid__cListener__", "Globals._CuberiteInternal_.*", "Globals.esMax", "Globals.E_BLOCK_*", }, IgnoreVariables = { "__.*__", }, } ================================================ FILE: Server/Plugins/APIDump/Classes/BlockArea.lua ================================================ return { cBlockArea = { Desc = [[ This class is used when multiple adjacent blocks are to be manipulated. Because of chunking and multithreading, manipulating single blocks using {{cWorld|cWorld:SetBlock}}() is a rather time-consuming operation (locks for exclusive access need to be obtained, chunk lookup is done for each block), so whenever you need to manipulate multiple adjacent blocks, it's better to wrap the operation into a cBlockArea access. cBlockArea is capable of reading / writing across chunk boundaries, has no chunk lookups for get and set operations and is not subject to multithreading locking (because it is not shared among threads).

    cBlockArea remembers its origin (MinX, MinY, MinZ coords in the Read() call) and therefore supports absolute as well as relative get / set operations. Despite that, the contents of a cBlockArea can be written back into the world at any coords. Most functions in this class come in pair, one that works with the absolute coords (what the coords would have been in the original world the area was read from) and one (usually with "Rel" in their name) that work on the relative coords (those range from zero to Size - 1). Also note that most functions will raise an error if an out-of-range coord is supplied to them.

    cBlockArea can hold any combination of the following datatypes:

    • block types
    • block metas
    • blocklight
    • skylight
    • block entities (only together with block types)
    Read() and Write() functions have parameters that tell the class which datatypes to read / write. Note that a datatype that has not been read cannot be written.

    Block entities stored inside a cBlockArea object have their position set to the relative position within the area.

    Typical usage:

    • Create cBlockArea object
    • Read an area from the world / load from file / create anew
    • Modify blocks inside cBlockArea
    • Write the area back to a world / save to file

    Calls to any setter of this class will not trigger simulator updates (lava, water, redstone).

    ]], Functions = { Clear = { Notes = "Clears the object, resets it to zero size", }, constructor = { Returns = { { Type = "cBlockArea", }, }, Notes = "Creates a new empty cBlockArea object", }, CopyFrom = { Params = { { Name = "BlockAreaSrc", Type = "cBlockArea", }, }, Notes = "Copies contents from BlockAreaSrc into self", }, CopyTo = { Params = { { Name = "BlockAreaDst", Type = "cBlockArea", }, }, Notes = "Copies contents from self into BlockAreaDst.", }, CountNonAirBlocks = { Returns = { { Type = "number", }, }, Notes = "Returns the count of blocks that are not air. Returns 0 if blocktypes not available. Block metas are ignored (if present, air with any meta is still considered air).", }, CountSpecificBlocks = { { Params = { { Name = "BlockType", Type = "number", }, }, Returns = { { Type = "number", }, }, Notes = "Counts the number of occurences of the specified blocktype contained in the area.", }, { Params = { { Name = "BlockType", Type = "number", }, { Name = "BlockMeta", Type = "number", }, }, Returns = { { Type = "number", }, }, Notes = "Counts the number of occurrences of the specified blocktype + blockmeta combination contained in the area.", }, }, Create = { { Params = { { Name = "SizeX", Type = "number", }, { Name = "SizeY", Type = "number", }, { Name = "SizeZ", Type = "number", }, }, Notes = "Initializes this BlockArea to an empty area of the specified size and origin of {0, 0, 0}. Datatypes are set to baTypes + baMetas. Any previous contents are lost.", }, { Params = { { Name = "SizeX", Type = "number", }, { Name = "SizeY", Type = "number", }, { Name = "SizeZ", Type = "number", }, { Name = "DataTypes", Type = "number", }, }, Notes = "Initializes this BlockArea to an empty area of the specified size and origin of {0, 0, 0}. Any previous contents are lost.", }, { Params = { { Name = "Size", Type = "Vector3i", }, }, Notes = "Creates a new area of the specified size. Datatypes are set to baTypes + baMetas. Origin is set to all zeroes. BlockTypes are set to air, block metas to zero, blocklights to zero and skylights to full light.", }, { Params = { { Name = "Size", Type = "Vector3i", }, { Name = "DataTypes", Type = "number", }, }, Notes = "Creates a new area of the specified size and contents. Origin is set to all zeroes. BlockTypes are set to air, block metas to zero, blocklights to zero and skylights to full light.", }, }, Crop = { Params = { { Name = "AddMinX", Type = "number", }, { Name = "SubMaxX", Type = "number", }, { Name = "AddMinY", Type = "number", }, { Name = "SubMaxY", Type = "number", }, { Name = "AddMinZ", Type = "number", }, { Name = "SubMaxZ", Type = "number", }, }, Notes = "Crops the specified number of blocks from each border. Modifies the size of this blockarea object.", }, -- Crop DoWithBlockEntityAt = { { Params = { { Name = "BlockX", Type = "number", }, { Name = "BlockY", Type = "number", }, { Name = "BlockZ", Type = "number", }, { Name = "Callback", Type = "function", }, }, Returns = { Name = "HasCalled", Type = "boolean", }, Notes = "Calls the specified callback with the block entity at the specified absolute coords. The CallbackFunction has the following signature:
    function Callback({{cBlockEntity|BlockEntity}})
    Returns false if there's no block entity at the specified coords. Returns the value that the callback has returned otherwise.", }, { Params = { { Name = "Coords", Type = "Vector3i", }, { Name = "Callback", Type = "function", }, }, Returns = { Name = "HasCalled", Type = "boolean", }, Notes = "Calls the specified callback with the block entity at the specified absolute coords. The CallbackFunction has the following signature:
    function Callback({{cBlockEntity|BlockEntity}})
    Returns false if there's no block entity at the specified coords. Returns the value that the callback has returned otherwise.", }, }, -- DoWithBlockEntityAt DoWithBlockEntityRelAt = { { Params = { { Name = "RelX", Type = "number", }, { Name = "RelY", Type = "number", }, { Name = "RelZ", Type = "number", }, { Name = "Callback", Type = "function", }, }, Returns = { Name = "HasCalled", Type = "boolean", }, Notes = "Calls the specified callback with the block entity at the specified relative coords. The CallbackFunction has the following signature:
    function Callback({{cBlockEntity|BlockEntity}})
    Returns false if there's no block entity at the specified coords. Returns the value that the callback has returned otherwise.", }, { Params = { { Name = "RelCoords", Type = "Vector3i", }, { Name = "Callback", Type = "function", }, }, Returns = { Name = "HasCalled", Type = "boolean", }, Notes = "Calls the specified callback with the block entity at the specified relative coords. The CallbackFunction has the following signature:
    function Callback({{cBlockEntity|BlockEntity}})
    Returns false if there's no block entity at the specified coords. Returns the value that the callback has returned otherwise.", }, }, -- DoWithBlockEntityRelAt DumpToRawFile = { Params = { { Name = "FileName", Type = "string", }, }, Notes = "Dumps the raw data into a file. For debugging purposes only.", }, Expand = { Params = { { Name = "SubMinX", Type = "number", }, { Name = "AddMaxX", Type = "number", }, { Name = "SubMinY", Type = "number", }, { Name = "AddMaxY", Type = "number", }, { Name = "SubMinZ", Type = "number", }, { Name = "AddMaxZ", Type = "number", }, }, Notes = "Expands the specified number of blocks from each border. Modifies the size of this blockarea object. New blocks created with this operation are filled with zeroes.", }, Fill = { Params = { { Name = "DataTypes", Type = "number", }, { Name = "BlockType", Type = "number", }, { Name = "BlockMeta", Type = "number", IsOptional = true, }, { Name = "BlockLight", Type = "number", IsOptional = true, }, { Name = "BlockSkyLight", Type = "number", IsOptional = true, }, }, Notes = "Fills the entire block area with the same values, specified. Uses the DataTypes param to determine which content types are modified.", }, FillRelCuboid = { { Params = { { Name = "RelCuboid", Type = "cCuboid", }, { Name = "DataTypes", Type = "number", }, { Name = "BlockType", Type = "number", }, { Name = "BlockMeta", Type = "number", IsOptional = true, }, { Name = "BlockLight", Type = "number", IsOptional = true, }, { Name = "BlockSkyLight", Type = "number", IsOptional = true, }, }, Notes = "Fills the specified cuboid (in relative coords) with the same values (like Fill() ).", }, { Params = { { Name = "MinRelX", Type = "number", }, { Name = "MaxRelX", Type = "number", }, { Name = "MinRelY", Type = "number", }, { Name = "MaxRelY", Type = "number", }, { Name = "MinRelZ", Type = "number", }, { Name = "MaxRelZ", Type = "number", }, { Name = "DataTypes", Type = "number", }, { Name = "BlockType", Type = "number", }, { Name = "BlockMeta", Type = "number", IsOptional = true, }, { Name = "BlockLight", Type = "number", IsOptional = true, }, { Name = "BlockSkyLight", Type = "number", IsOptional = true, }, }, Notes = "Fills the specified cuboid with the same values (like Fill() ).", }, }, ForEachBlockEntity = { Params = { { Name = "Coords", Type = "Vector3i", }, { Name = "Callback", Type = "function", }, }, Returns = { Name = "HasProcessedAll", Type = "boolean", }, Notes = "Calls the specified callback with the block entity for each block entity contained in the object. Returns true if all block entities have been processed (including when there are zero block entities), or false if the callback has aborted the enumeration by returning true. The CallbackFunction has the following signature:
    function Callback({{cBlockEntity|BlockEntity}})
    The callback should return false or no value to continue with the next block entity, or true to abort the enumeration.", }, -- ForEachBlockEntity GetBlockLight = { Params = { { Name = "BlockX", Type = "number", }, { Name = "BlockY", Type = "number", }, { Name = "BlockZ", Type = "number", }, }, Returns = { { Name = "BlockLight", Type = "number", }, }, Notes = "Returns the blocklight (emissive light) at the specified absolute coords", }, GetBlockMeta = { Params = { { Name = "BlockX", Type = "number", }, { Name = "BlockY", Type = "number", }, { Name = "BlockZ", Type = "number", }, }, Returns = { { Name = "BlockMeta", Type = "number", }, }, Notes = "Returns the block meta at the specified absolute coords", }, GetBlockSkyLight = { Params = { { Name = "BlockX", Type = "number", }, { Name = "BlockY", Type = "number", }, { Name = "BlockZ", Type = "number", }, }, Returns = { { Name = "BlockSkyLight", Type = "number", }, }, Notes = "Returns the skylight at the specified absolute coords", }, GetBlockType = { Params = { { Name = "BlockX", Type = "number", }, { Name = "BlockY", Type = "number", }, { Name = "BlockZ", Type = "number", }, }, Returns = { { Name = "BLOCKTYPE", Type = "number", }, }, Notes = "Returns the block type at the specified absolute coords", }, GetBlockTypeMeta = { Params = { { Name = "BlockX", Type = "number", }, { Name = "BlockY", Type = "number", }, { Name = "BlockZ", Type = "number", }, }, Returns = { { Name = "BlockType", Type = "number", }, { Name = "BlockMeta", Type = "number", }, }, Notes = "Returns the block type and meta at the specified absolute coords", }, GetBounds = { Params = {}, Returns = { { Name = "Bounds", Type = "cCuboid", } }, Notes = "Returns the {{cCuboid|cuboid}} that specifies the original coords of the world from which the area was read. Basically constructs a {{cCuboid}} out of GetOrigin() and GetOrigin() + GetCoordRange().", }, GetCoordRange = { Returns = { { Name = "MaxX", Type = "number", }, { Name = "MaxY", Type = "number", }, { Name = "MaxZ", Type = "number", }, }, Notes = "Returns the maximum relative coords in all 3 axes. See also GetSize().", }, GetDataTypes = { Returns = { { Type = "number", }, }, Notes = "Returns the mask of datatypes (ba* constants added together) that the object is currently holding.", }, GetNonAirCropRelCoords = { Params = { { Name = "IgnoredBlockType", Type = "number", IsOptional = true, }, }, Returns = { { Name = "MinRelX", Type = "number", }, { Name = "MinRelY", Type = "number", }, { Name = "MinRelZ", Type = "number", }, { Name = "MaxRelX", Type = "number", }, { Name = "MaxRelY", Type = "number", }, { Name = "MaxRelZ", Type = "number", }, }, Notes = "Returns the minimum and maximum coords in each direction for the first block in each direction of type different to IgnoredBlockType (E_BLOCK_AIR by default). If there are no non-ignored blocks within the area, or blocktypes are not present, the returned values are reverse-ranges (MinX <- m_RangeX, MaxX <- 0 etc.). IgnoreBlockType defaults to air.", }, GetOrigin = { Returns = { { Name = "OriginX", Type = "number", }, { Name = "OriginY", Type = "number", }, { Name = "OriginZ", Type = "number", }, }, Notes = "Returns the origin coords of where the area was read from.", }, GetOriginX = { Returns = { { Type = "number", }, }, Notes = "Returns the origin x-coord", }, GetOriginY = { Returns = { { Type = "number", }, }, Notes = "Returns the origin y-coord", }, GetOriginZ = { Returns = { { Type = "number", }, }, Notes = "Returns the origin z-coord", }, GetRelBlockLight = { Params = { { Name = "RelBlockX", Type = "number", }, { Name = "RelBlockY", Type = "number", }, { Name = "RelBlockZ", Type = "number", }, }, Returns = { { Name = "NIBBLETYPE", Type = "number", }, }, Notes = "Returns the blocklight at the specified relative coords", }, GetRelBlockMeta = { Params = { { Name = "RelBlockX", Type = "number", }, { Name = "RelBlockY", Type = "number", }, { Name = "RelBlockZ", Type = "number", }, }, Returns = { { Name = "NIBBLETYPE", Type = "number", }, }, Notes = "Returns the block meta at the specified relative coords", }, GetRelBlockSkyLight = { Params = { { Name = "RelBlockX", Type = "number", }, { Name = "RelBlockY", Type = "number", }, { Name = "RelBlockZ", Type = "number", }, }, Returns = { { Name = "NIBBLETYPE", Type = "number", }, }, Notes = "Returns the skylight at the specified relative coords", }, GetRelBlockType = { Params = { { Name = "RelBlockX", Type = "number", }, { Name = "RelBlockY", Type = "number", }, { Name = "RelBlockZ", Type = "number", }, }, Returns = { { Name = "BLOCKTYPE", Type = "number", }, }, Notes = "Returns the block type at the specified relative coords", }, GetRelBlockTypeMeta = { Params = { { Name = "RelBlockX", Type = "number", }, { Name = "RelBlockY", Type = "number", }, { Name = "RelBlockZ", Type = "number", }, }, Returns = { { Name = "BLOCKTYPE", Type = "number", }, { Name = "NIBBLETYPE", Type = "number", }, }, Notes = "Returns the block type and meta at the specified relative coords", }, GetSize = { Returns = { { Name = "SizeX", Type = "number", }, { Name = "SizeY", Type = "number", }, { Name = "SizeZ", Type = "number", }, }, Notes = "Returns the size of the area in all 3 axes. See also GetCoordRange().", }, GetSizeX = { Returns = { { Type = "number", }, }, Notes = "Returns the size of the held data in the x-axis", }, GetSizeY = { Returns = { { Type = "number", }, }, Notes = "Returns the size of the held data in the y-axis", }, GetSizeZ = { Returns = { { Type = "number", }, }, Notes = "Returns the size of the held data in the z-axis", }, GetVolume = { Returns = { { Type = "number", }, }, Notes = "Returns the volume of the area - the total number of blocks stored within.", }, GetWEOffset = { Returns = { { Type = "Vector3i", }, }, Notes = "Returns the WE offset, a data value sometimes stored in the schematic files. Cuberite doesn't use this value, but provides access to it using this method. The default is {0, 0, 0}.", }, HasBlockEntities = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if current datatypes include block entities.", }, HasBlockLights = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if current datatypes include blocklight", }, HasBlockMetas = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if current datatypes include block metas", }, HasBlockSkyLights = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if current datatypes include skylight", }, HasBlockTypes = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if current datatypes include block types", }, IsValidCoords = { { Params = { { Name = "BlockX", Type = "number", }, { Name = "BlockY", Type = "number", }, { Name = "BlockZ", Type = "number", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if the specified absolute coords are within the area.", }, { Params = { { Name = "Coords", Type = "Vector3i", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if the specified absolute coords are within the area.", }, }, -- IsValidCoords IsValidDataTypeCombination = { IsStatic = true, Params = { { Name = "DataTypes", Type = "number", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if the specified combination of datatypes (ba* constants added together) is valid. Most combinations are valid, but for example baBlockEntities without baTypes is an invalid combination.", }, -- IsValidDataTypeCombination IsValidRelCoords = { { Params = { { Name = "RelBlockX", Type = "number", }, { Name = "RelBlockY", Type = "number", }, { Name = "RelBlockZ", Type = "number", }, }, Returns = { { Type = "boolean", } }, Notes = "Returns true if the specified relative coords are within the area.", }, { Params = { { Name = "RelCoords", Type = "Vector3i", }, }, Returns = { { Type = "boolean", } }, Notes = "Returns true if the specified relative coords are within the area.", }, }, -- IsValidRelCoords LoadFromSchematicFile = { Params = { { Name = "FileName", Type = "string", }, }, Returns = { { Type = "boolean" }, }, Notes = "Clears current content and loads new content from the specified schematic file. Returns true if successful. Returns false and logs error if unsuccessful, old content is preserved in such a case.", }, LoadFromSchematicString = { Params = { { Name = "SchematicData", Type = "string", }, }, Returns = { { Type = "boolean" }, }, Notes = "Clears current content and loads new content from the specified string (assumed to contain .schematic data). Returns true if successful. Returns false and logs error if unsuccessful, old content is preserved in such a case.", }, Merge = { { Params = { { Name = "BlockAreaSrc", Type = "cBlockArea", }, { Name = "RelMinCoords", Type = "number", }, { Name = "Strategy", Type = "string", }, }, Notes = "Merges BlockAreaSrc into this object at the specified relative coords, using the specified strategy", }, { Params = { { Name = "BlockAreaSrc", Type = "cBlockArea", }, { Name = "RelX", Type = "number", }, { Name = "RelY", Type = "number", }, { Name = "RelZ", Type = "number", }, { Name = "Strategy", Type = "string", }, }, Notes = "Merges BlockAreaSrc into this object at the specified relative coords, using the specified strategy", }, }, MirrorXY = { Notes = "Mirrors this block area around the XY plane. Modifies blocks' metas (if present) to match (i. e. furnaces facing the opposite direction).", }, MirrorXYNoMeta = { Notes = "Mirrors this block area around the XY plane. Doesn't modify blocks' metas.", }, MirrorXZ = { Notes = "Mirrors this block area around the XZ plane. Modifies blocks' metas (if present)", }, MirrorXZNoMeta = { Notes = "Mirrors this block area around the XZ plane. Doesn't modify blocks' metas.", }, MirrorYZ = { Notes = "Mirrors this block area around the YZ plane. Modifies blocks' metas (if present)", }, MirrorYZNoMeta = { Notes = "Mirrors this block area around the YZ plane. Doesn't modify blocks' metas.", }, Read = { { Params = { { Name = "World", Type = "cWorld", }, { Name = "Cuboid", Type = "cCuboid", }, }, Returns = { { Name = "IsSuccess", Type = "boolean", }, }, Notes = "Reads the area from World, returns true if successful. baTypes and baMetas are read.", }, { Params = { { Name = "World", Type = "cWorld", }, { Name = "Cuboid", Type = "cCuboid", }, { Name = "DataTypes", Type = "number", }, }, Returns = { { Name = "IsSuccess", Type = "boolean", }, }, Notes = "Reads the area from World, returns true if successful. DataTypes is the sum of baXXX datatypes to be read", }, { Params = { { Name = "World", Type = "cWorld", }, { Name = "Point1", Type = "Vector3i", }, { Name = "Point2", Type = "Vector3i", }, }, Returns = { { Name = "IsSuccess", Type = "boolean", }, }, Notes = "Reads the area from World, returns true if successful. baTypes and baMetas are read.", }, { Params = { { Name = "World", Type = "cWorld", }, { Name = "Point1", Type = "Vector3i", }, { Name = "Point2", Type = "Vector3i", }, { Name = "DataTypes", Type = "number", }, }, Returns = { { Name = "IsSuccess", Type = "boolean", }, }, Notes = "Reads the area from World, returns true if successful. DataTypes is a sum of baXXX datatypes to be read.", }, { Params = { { Name = "World", Type = "cWorld", }, { Name = "MinX", Type = "number", }, { Name = "MaxX", Type = "number", }, { Name = "MinY", Type = "number", }, { Name = "MaxY", Type = "number", }, { Name = "MinZ", Type = "number", }, { Name = "MaxZ", Type = "number", }, }, Returns = { { Type = "boolean", }, }, Notes = "Reads the area from World, returns true if successful. baTypes and baMetas are read.", }, { Params = { { Name = "World", Type = "cWorld", }, { Name = "MinX", Type = "number", }, { Name = "MaxX", Type = "number", }, { Name = "MinY", Type = "number", }, { Name = "MaxY", Type = "number", }, { Name = "MinZ", Type = "number", }, { Name = "MaxZ", Type = "number", }, { Name = "DataTypes", Type = "number", }, }, Returns = { { Type = "boolean", }, }, Notes = "Reads the area from World, returns true if successful. DataTypes is a sum of baXXX datatypes to read.", }, }, RelLine = { { Params = { { Name = "RelPoint1", Type = "Vector3i", }, { Name = "RelPoint2", Type = "Vector3i", }, { Name = "DataTypes", Type = "number", }, { Name = "BlockType", Type = "number", }, { Name = "BlockMeta", Type = "number", IsOptional = true, }, { Name = "BlockLight", Type = "number", IsOptional = true, }, { Name = "BlockSkyLight", Type = "number", IsOptional = true, }, }, Notes = "Draws a line between the two specified points. Sets only datatypes specified by DataTypes (baXXX constants).", }, { Params = { { Name = "RelX1", Type = "number", }, { Name = "RelY1", Type = "number", }, { Name = "RelZ1", Type = "number", }, { Name = "RelX2", Type = "number", }, { Name = "RelY2", Type = "number", }, { Name = "RelZ2", Type = "number", }, { Name = "DataTypes", Type = "number", }, { Name = "BlockType", Type = "number", }, { Name = "BlockMeta", Type = "number", IsOptional = true, }, { Name = "BlockLight", Type = "number", IsOptional = true, }, { Name = "BlockSkyLight", Type = "number", IsOptional = true, }, }, Notes = "Draws a line between the two specified points. Sets only datatypes specified by DataTypes (baXXX constants).", }, }, RotateCCW = { Notes = "Rotates the block area around the Y axis, counter-clockwise (east -> north). Modifies blocks' metas (if present) to match.", }, RotateCCWNoMeta = { Notes = "Rotates the block area around the Y axis, counter-clockwise (east -> north). Doesn't modify blocks' metas.", }, RotateCW = { Notes = "Rotates the block area around the Y axis, clockwise (north -> east). Modifies blocks' metas (if present) to match.", }, RotateCWNoMeta = { Notes = "Rotates the block area around the Y axis, clockwise (north -> east). Doesn't modify blocks' metas.", }, SaveToSchematicFile = { Params = { { Name = "FileName", Type = "string", }, }, Returns = { { Type = "boolean", }, }, Notes = "Saves the current contents to a schematic file. Returns true if successful.", }, SaveToSchematicString = { Returns = { { Type = "string", }, }, Notes = "Saves the current contents to a string (in a .schematic file format). Returns the data if successful, nil if failed.", }, SetBlockLight = { Params = { { Name = "BlockX", Type = "number", }, { Name = "BlockY", Type = "number", }, { Name = "BlockZ", Type = "number", }, { Name = "BlockLight", Type = "number", }, }, Notes = "Sets the blocklight at the specified absolute coords", }, SetBlockMeta = { Params = { { Name = "BlockX", Type = "number", }, { Name = "BlockY", Type = "number", }, { Name = "BlockZ", Type = "number", }, { Name = "BlockMeta", Type = "number", }, }, Notes = "Sets the block meta at the specified absolute coords.", }, SetBlockSkyLight = { Params = { { Name = "BlockX", Type = "number", }, { Name = "BlockY", Type = "number", }, { Name = "BlockZ", Type = "number", }, { Name = "BlockSkyLight", Type = "number", }, }, Notes = "Sets the skylight at the specified absolute coords", }, SetBlockType = { Params = { { Name = "BlockX", Type = "number", }, { Name = "BlockY", Type = "number", }, { Name = "BlockZ", Type = "number", }, { Name = "BlockType", Type = "number", }, }, Notes = "Sets the block type at the specified absolute coords", }, SetBlockTypeMeta = { Params = { { Name = "BlockX", Type = "number", }, { Name = "BlockY", Type = "number", }, { Name = "BlockZ", Type = "number", }, { Name = "BlockType", Type = "number", }, { Name = "BlockMeta", Type = "number", }, }, Notes = "Sets the block type and meta at the specified absolute coords", }, SetOrigin = { { Params = { { Name = "Origin", Type = "Vector3i", }, }, Notes = "Resets the origin for the absolute coords. Only affects how absolute coords are translated into relative coords.", }, { Params = { { Name = "OriginX", Type = "number", }, { Name = "OriginY", Type = "number", }, { Name = "OriginZ", Type = "number", }, }, Notes = "Resets the origin for the absolute coords. Only affects how absolute coords are translated into relative coords.", }, }, SetRelBlockLight = { Params = { { Name = "RelBlockX", Type = "number", }, { Name = "RelBlockY", Type = "number", }, { Name = "RelBlockZ", Type = "number", }, { Name = "BlockLight", Type = "number", }, }, Notes = "Sets the blocklight at the specified relative coords", }, SetRelBlockMeta = { Params = { { Name = "RelBlockX", Type = "number", }, { Name = "RelBlockY", Type = "number", }, { Name = "RelBlockZ", Type = "number", }, { Name = "BlockMeta", Type = "number", }, }, Notes = "Sets the block meta at the specified relative coords", }, SetRelBlockSkyLight = { Params = { { Name = "RelBlockX", Type = "number", }, { Name = "RelBlockY", Type = "number", }, { Name = "RelBlockZ", Type = "number", }, { Name = "BlockSkyLight", Type = "number", }, }, Notes = "Sets the skylight at the specified relative coords", }, SetRelBlockType = { Params = { { Name = "RelBlockX", Type = "number", }, { Name = "RelBlockY", Type = "number", }, { Name = "RelBlockZ", Type = "number", }, { Name = "BlockType", Type = "number", }, }, Notes = "Sets the block type at the specified relative coords", }, SetRelBlockTypeMeta = { Params = { { Name = "RelBlockX", Type = "number", }, { Name = "RelBlockY", Type = "number", }, { Name = "RelBlockZ", Type = "number", }, { Name = "BlockType", Type = "number", }, { Name = "BlockMeta", Type = "number", }, }, Notes = "Sets the block type and meta at the specified relative coords", }, SetWEOffset = { { Params = { { Name = "Offset", Type = "Vector3i", }, }, Notes = "Sets the WE offset, a data value sometimes stored in the schematic files. Mostly used for WorldEdit. Cuberite doesn't use this value, but provides access to it using this method.", }, { Params = { { Name = "OffsetX", Type = "number", }, { Name = "OffsetY", Type = "number", }, { Name = "OffsetZ", Type = "number", }, }, Notes = "Sets the WE offset, a data value sometimes stored in the schematic files. Mostly used for WorldEdit. Cuberite doesn't use this value, but provides access to it using this method.", }, }, Write = { { Params = { { Name = "World", Type = "cWorld", }, { Name = "MinPoint", Type = "Vector3i", }, }, Returns = { { Name = "IsSuccess", Type = "boolean", }, }, Notes = "Writes the area into World at the specified coords, returns true if successful. All present data types are written.", }, { Params = { { Name = "World", Type = "cWorld", }, { Name = "MinPoint", Type = "Vector3i", }, { Name = "DataTypes", Type = "number", }, }, Returns = { { Name = "IsSuccess", Type = "boolean", }, }, Notes = "Writes the area into World at the specified coords, returns true if successful. DataTypes is the sum of baXXX datatypes to write.", }, { Params = { { Name = "World", Type = "cWorld", }, { Name = "MinX", Type = "number", }, { Name = "MinY", Type = "number", }, { Name = "MinZ", Type = "number", }, }, Returns = { { Name = "IsSuccess", Type = "boolean", }, }, Notes = "Writes the area into World at the specified coords, returns true if successful. All present data types are written.", }, { Params = { { Name = "World", Type = "cWorld", }, { Name = "MinX", Type = "number", }, { Name = "MinY", Type = "number", }, { Name = "MinZ", Type = "number", }, { Name = "DataTypes", Type = "number", }, }, Returns = { { Name = "IsSuccess", Type = "boolean", }, }, Notes = "Writes the area into World at the specified coords, returns true if successful. DataTypes is the sum of baXXX datatypes to write.", }, }, }, Constants = { baBlockEntities = { Notes = "Operations should work on block entities. Note that this flag is invalid without baTypes.", }, baLight = { Notes = "Operations should work on block (emissive) light", }, baMetas = { Notes = "Operations should work on block metas", }, baSkyLight = { Notes = "Operations should work on skylight", }, baTypes = { Notes = "Operation should work on block types", }, msDifference = { Notes = "Block becomes air if 'self' and src are the same. Otherwise it becomes the src block.", }, msFillAir = { Notes = "'self' is overwritten by Src only where 'self' has air blocks", }, msImprint = { Notes = "Src overwrites 'self' anywhere where 'self' has non-air blocks", }, msLake = { Notes = "Special mode for merging lake images", }, msMask = { Notes = "The blocks that are exactly the same are kept in 'self', all differing blocks are replaced by air", }, msOverwrite = { Notes = "Src overwrites anything in 'self'", }, msSimpleCompare = { Notes = "The blocks that are exactly the same are replaced with air, all differing blocks are replaced by stone", }, msSpongePrint = { Notes = "Similar to msImprint, sponge block doesn't overwrite anything, all other blocks overwrite everything", }, }, ConstantGroups = { BATypes = { Include = "ba.*", TextBefore = [[ The following constants are used to signalize the datatype to read or write: ]], }, eMergeStrategy = { Include = "ms.*", TextAfter = "See below for a detailed explanation of the individual merge strategies.", TextBefore = [[ The Merge() function can use different strategies to combine the source and destination blocks. The following constants are used: ]], }, }, AdditionalInfo = { { Header = "Merge strategies", Contents = [[

    The strategy parameter specifies how individual blocks are combined together, using the table below.

    area blockresult
    this Src msOverwrite msFillAir msImprint
    air air air air air
    A air air A A
    air B B B B
    A B B A B
    A A A A A

    So to sum up:

    1. msOverwrite completely overwrites all blocks with the Src's blocks
    2. msFillAir overwrites only those blocks that were air
    3. msImprint overwrites with only those blocks that are non-air

    Special strategies

    For each strategy, evaluate the table rows from top downwards, the first match wins.

    msDifference - changes all the blocks which are the same to air. Otherwise the source block gets placed.

    area block Notes
    * B B The blocks are different so we use block B
    B B Air The blocks are the same so we get air.

    msLake - used for merging areas with lava and water lakes, in the appropriate generator.

    area block Notes
    self Src result
    A sponge A Sponge is the NOP block
    * air air Air always gets hollowed out, even under the oceans
    water * water Water is never overwritten
    lava * lava Lava is never overwritten
    * water water Water always overwrites anything
    * lava lava Lava always overwrites anything
    dirt stone stone Stone overwrites dirt
    grass stone stone ... and grass
    mycelium stone stone ... and mycelium
    A stone A ... but nothing else
    A * A Everything else is left as it is

    msSpongePrint - used for most prefab-generators to merge the prefabs. Similar to msImprint, but uses the sponge block as the NOP block instead, so that the prefabs may carve out air pockets, too.

    area block Notes
    self Src result
    A sponge A Sponge is the NOP block
    * B B Everything else overwrites anything

    msMask - the blocks that are the same in the other area are kept, all the differing blocks are replaced with air. Meta is used in the comparison, too, two blocks of the same type but different meta are considered different and thus replaced with air.

    area block Notes
    self Src result
    A A A Same blocks are kept
    A non-A air Differing blocks are replaced with air

    msDifference - the blocks that are the same in both areas are replaced with air, all the differing blocks are kept from the first area. Meta is used in the comparison, too, two blocks of the same type but different meta are considered different.

    area block Notes
    self Src result
    A A air Same blocks are replaced with air
    A non-A A Differing blocks are kept from 'self'

    msSimpleCompare - the blocks that are the same in both areas are replaced with air, all the differing blocks are replaced with stone. Meta is used in the comparison, too, two blocks of the same type but different meta are considered different.

    area block Notes
    self Src result
    A A air Same blocks are replaced with air
    A non-A stone Differing blocks are replaced with stone
    ]], }, }, }, } ================================================ FILE: Server/Plugins/APIDump/Classes/BlockEntities.lua ================================================ return { cBeaconEntity = { Desc = [[ A beacon entity is a {{cBlockEntityWithItems}} descendant that represents a beacon in the world. ]], Functions = { CalculatePyramidLevel = { Returns = { { Type = "number", }, }, Notes = "Calculate the amount of layers the pyramid below the beacon has.", }, GetBeaconLevel = { Returns = { { Type = "number", }, }, Notes = "Returns the beacon level. (0 - 4)", }, GetPrimaryEffect = { Returns = { { Name = "EffectType", Type = "cEntityEffect#eType", }, }, Notes = "Returns the primary effect.", }, GetSecondaryEffect = { Returns = { { Name = "EffectType", Type = "cEntityEffect#eType", }, }, Notes = "Returns the secondary effect.", }, GiveEffects = { Notes = "Give the near-players the effects.", }, IsActive = { Returns = { { Type = "boolean", }, }, Notes = "Is the beacon active?", }, IsBeaconBlocked = { Returns = { { Type = "boolean", }, }, Notes = "Is the beacon blocked by non-transparent blocks that are higher than the beacon?", }, IsMineralBlock = { IsStatic = true, Params = { { Name = "BlockType", Type = "number", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if the block is a diamond block, a golden block, an iron block or an emerald block.", }, IsValidEffect = { IsStatic = true, Params = { { Name = "EffectType", Type = "cEntityEffect#eType", }, { Name = "BeaconLevel", Type = "number", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if the effect can be used.", }, SetPrimaryEffect = { Params = { { Name = "EffectType", Type = "cEntityEffect#eType", }, }, Returns = { { Type = "boolean", }, }, Notes = "Select the primary effect. Returns false when the effect is invalid.", }, SetSecondaryEffect = { Params = { { Name = "EffectType", Type = "cEntityEffect#eType", }, }, Returns = { { Type = "boolean", }, }, Notes = "Select the secondary effect. Returns false when the effect is invalid.", }, UpdateBeacon = { Notes = "Update the beacon.", }, }, Inherits = "cBlockEntityWithItems", }, cBedEntity = { Desc = [[ A bed entity is a {{cBlockEntity}} descendant that represents a bed in the world. ]], Functions = { GetColor = { Returns = { { Type = "number", }, }, Notes = "Returns the color of the bed.", }, SetColor = { Params = { { Type = "number", }, }, Notes = "Set the color of the bed. A value between 0 - 15. The wool meta color values can be used.", }, IsPillowBlock = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if this is the pillow block, it has then the meta 8.", }, }, Inherits = "cBlockEntity", }, cBlockEntity = { Desc = [[ Block entities are simply blocks in the world that have persistent data, such as the text for a sign or contents of a chest. All block entities are also saved in the chunk data of the chunk they reside in. The cBlockEntity class acts as a common ancestor for all the individual block entities. ]], Functions = { GetBlockType = { Returns = { { Name = "BLOCKTYPE", Type = "number", }, }, Notes = "Returns the blocktype which is represented by this blockentity. This is the primary means of type-identification", }, GetChunkX = { Returns = { { Type = "number", }, }, Notes = "Returns the chunk X-coord of the block entity's chunk", }, GetChunkZ = { Returns = { { Type = "number", }, }, Notes = "Returns the chunk Z-coord of the block entity's chunk", }, GetPos = { Returns = { { Type = "Vector3i", }, }, Notes = "Returns the name of the parent class, or empty string if no parent class.", }, GetPosX = { Returns = { { Type = "number", }, }, Notes = "Returns the block X-coord of the block entity's block", }, GetPosY = { Returns = { { Type = "number", }, }, Notes = "Returns the block Y-coord of the block entity's block", }, GetPosZ = { Returns = { { Type = "number", }, }, Notes = "Returns the block Z-coord of the block entity's block", }, GetRelPos = { Returns = { { Type = "Vector3i", }, }, Notes = "Returns the relative coords of the block entity's block within its chunk", }, GetRelX = { Returns = { { Type = "number", }, }, Notes = "Returns the relative X coord of the block entity's block within the chunk", }, GetRelZ = { Returns = { { Type = "number", }, }, Notes = "Returns the relative Z coord of the block entity's block within the chunk", }, GetWorld = { Returns = { { Type = "cWorld", }, }, Notes = "Returns the world to which the block entity belongs", }, }, }, cBlockEntityWithItems = { Desc = [[ This class is a common ancestor for all {{cBlockEntity|block entities}} that provide item storage. Internally, the object has a {{cItemGrid|cItemGrid}} object for storing the items; this ItemGrid is accessible through the API. The storage is a grid of items, items in it can be addressed either by a slot number, or by XY coords within the grid. If a UI window is opened for this block entity, the item storage is monitored for changes and the changes are immediately sent to clients of the UI window. ]], Functions = { GetContents = { Returns = { { Type = "cItemGrid", }, }, Notes = "Returns the cItemGrid object representing the items stored within this block entity", }, GetSlot = { { Params = { { Name = "SlotNum", Type = "number", }, }, Returns = { { Type = "cItem", }, }, Notes = "Returns the cItem for the specified slot number. Returns nil for invalid slot numbers", }, { Params = { { Name = "X", Type = "number", }, { Name = "Y", Type = "number", }, }, Returns = { { Type = "cItem", }, }, Notes = "Returns the cItem for the specified slot coords. Returns nil for invalid slot coords", }, }, SetSlot = { { Params = { { Name = "SlotNum", Type = "number", }, { Name = "cItem", Type = "cItem", }, }, Notes = "Sets the cItem for the specified slot number. Ignored if invalid slot number", }, { Params = { { Name = "X", Type = "number", }, { Name = "Y", Type = "number", }, { Name = "cItem", Type = "cItem", }, }, Notes = "Sets the cItem for the specified slot coords. Ignored if invalid slot coords", }, }, }, Inherits = "cBlockEntity", }, cBrewingstandEntity = { Desc = [[ This class represents a brewingstand entity in the world.

    See also the {{cRoot}}:GetBrewingRecipe() function. ]], Functions = { GetBrewingTimeLeft = { Returns = { { Type = "number", }, }, Notes = "Returns the time until the current items finishes brewing, in ticks", }, GetIndgredientSlot = { Returns = { { Type = "cItem", }, }, Notes = "Returns the item in the ingredient slot", }, GetLeftBottleSlot = { Returns = { { Type = "cItem", }, }, Notes = "Returns the item in the left bottle slot", }, GetMiddleBottleSlot = { Returns = { { Type = "cItem", }, }, Notes = "Returns the item in the middle bottle slot", }, GetResultItem = { Params = { { Name = "SlotNumber", Type = "number", }, }, Returns = { { Type = "cItem", }, }, Notes = "Returns the expected result item for the given slot number.", }, GetRightBottleSlot = { Returns = { { Type = "cItem", }, }, Notes = "Returns the item in the right bottle slot", }, GetFuelSlot = { Returns = { { Type = "cItem", }, }, Notes = "Returns the item in the top left fuel slot", }, GetRemainingFuel = { Returns = { { Type = "number", }, }, Notes = "Returns the remaining fuel that is left. It's the amount of brewing operations that can be done (20 for one blaze powder).", }, GetTimeBrewed = { Returns = { { Type = "number", }, }, Notes = "Returns the time that the current items has been brewing, in ticks", }, SetIngredientSlot = { Params = { { Name = "Ingredient", Type = "cItem", }, }, Notes = "Sets the item in the ingredient bottle slot", }, SetLeftBottleSlot = { Params = { { Name = "LeftSlot", Type = "cItem", }, }, Notes = "Sets the item in the left bottle slot", }, SetMiddleBottleSlot = { Params = { { Name = "MiddleSlot", Type = "cItem", }, }, Notes = "Sets the item in the middle bottle slot", }, SetRightBottleSlot = { Params = { { Name = "RightSlot", Type = "cItem", }, }, Notes = "Sets the item in the right bottle slot", }, SetFuelSlot = { Params = { { Name = "FuelSlot", Type = "cItem", }, }, Notes = "Sets the item in the top left fuel slot", }, }, Constants = { bsIngredient = { Notes = "Index of the ingredient slot", }, bsLeftBottle = { Notes = "Index of the left bottle slot", }, bsMiddleBottle = { Notes = "Index of the middle bottle slot", }, bsRightBottle = { Notes = "Index of the right bottle slot", }, bsFuel = { Notes = "Index of the top left fuel slot", }, ContentsHeight = { Notes = "Height (Y) of the {{cItemGrid|cItemGrid}} representing the contents", }, ContentsWidth = { Notes = "Width (X) of the {{cItemGrid|cItemGrid}} representing the contents", }, }, ConstantGroups = { SlotIndices = { Include = "bs.*", TextBefore = "When using the GetSlot() or SetSlot() function, use these constants for slot index:", }, }, Inherits = "cBlockEntityWithItems", }, cChestEntity = { Desc = [[ A chest entity is a {{cBlockEntityWithItems|cBlockEntityWithItems}} descendant that represents a chest in the world. Note that doublechests consist of two separate cChestEntity objects, they do not collaborate in any way.

    To manipulate a chest already in the game, you need to use {{cWorld}}'s callback mechanism with either DoWithChestAt() or ForEachChestInChunk() function. See the code example below ]], Constants = { ContentsHeight = { Notes = "Height of the contents' {{cItemGrid|ItemGrid}}, as required by the parent class, {{cBlockEntityWithItems}}", }, ContentsWidth = { Notes = "Width of the contents' {{cItemGrid|ItemGrid}}, as required by the parent class, {{cBlockEntityWithItems}}", }, }, AdditionalInfo = { { Header = "Code example", Contents = [[ The following example code sets the top-left item of each chest in the same chunk as Player to 64 * diamond:

    -- Player is a {{cPlayer}} object instance
    local World = Player:GetWorld();
    World:ForEachChestInChunk(Player:GetChunkX(), Player:GetChunkZ(),
    	function (ChestEntity)
    		ChestEntity:SetSlot(0, 0, cItem(E_ITEM_DIAMOND, 64));
    	end
    );
    
    ]], }, }, Inherits = "cBlockEntityWithItems", }, cCommandBlockEntity = { Functions = { Activate = { Notes = "Sets the command block to execute a command in the next tick", }, GetCommand = { Returns = { { Type = "string", }, }, Notes = "Retrieves stored command", }, GetLastOutput = { Returns = { { Type = "string", }, }, Notes = "Retrieves the last line of output generated by the command block", }, GetResult = { Returns = { { Type = "number", }, }, Notes = "Retrieves the result (signal strength) of the last operation", }, SetCommand = { Params = { { Name = "Command", Type = "string", }, }, Notes = "Sets the command", }, }, Inherits = "cBlockEntity", }, cDispenserEntity = { Desc = [[ This class represents a dispenser block entity in the world. Most of this block entity's functionality is implemented in the {{cDropSpenserEntity}} class that represents the behavior common with the {{cDropperEntity|dropper}} block entity. ]], Functions = { GetShootVector = { IsStatic = true, Params = { { Name = "BlockMeta", Type = "number", }, }, Returns = { { Type = "Vector3d", }, }, Notes = "Returns a unit vector in the cardinal direction of where the dispenser with the specified meta would be facing.", }, SpawnProjectileFromDispenser = { Params = { { Name = "BlockX", Type = "number", }, { Name = "BlockY", Type = "number", }, { Name = "BlockZ", Type = "number", }, { Name = "Kind", Type = "cProjectileEntity#eKind", }, { Name = "Speed", Type = "Vector3d", }, { Name = "Item", Type = "cItem", }, }, Returns = { { Type = "number", }, }, Notes = "Spawns a projectile of the given kind in front of the dispenser with the specified speed. Returns the UniqueID of the spawned projectile, or {{cEntity#INVALID_ID|cEntity.INVALID_ID}} on failure.", }, }, Inherits = "cDropSpenserEntity", }, cDropperEntity = { Desc = [[ This class represents a dropper block entity in the world. Most of this block entity's functionality is implemented in the {{cDropSpenserEntity|cDropSpenserEntity}} class that represents the behavior common with the {{cDispenserEntity|dispenser}} entity.

    An object of this class can be created from scratch when generating chunks ({{OnChunkGenerated|OnChunkGenerated}} and {{OnChunkGenerating|OnChunkGenerating}} hooks). ]], Inherits = "cDropSpenserEntity", }, cDropSpenserEntity = { Desc = [[ This is a class that implements behavior common to both {{cDispenserEntity|dispensers}} and {{cDropperEntity|droppers}}. ]], Functions = { Activate = { Notes = "Sets the block entity to dropspense an item in the next tick", }, AddDropSpenserDir = { Params = { { Name = "BlockPos", Type = "Vector3i", }, { Name = "BlockMeta", Type = "number", }, }, Notes = "Adjusts the block coords to where the dropspenser items materialize", }, }, Constants = { ContentsHeight = { Notes = "Height (Y) of the {{cItemGrid}} representing the contents", }, ContentsWidth = { Notes = "Width (X) of the {{cItemGrid}} representing the contents", }, }, Inherits = "cBlockEntityWithItems", }, cFlowerPotEntity = { Desc = [[ This class represents a flower pot entity in the world. ]], Functions = { GetItem = { Returns = { { Name = "Item", Type = "cItem", }, }, Notes = "Returns the item in the flower pot.", }, IsItemInPot = { Returns = { { Type = "boolean", }, }, Notes = "Is a flower in the pot?", }, SetItem = { Params = { { Name = "Item", Type = "cItem", }, }, Notes = "Set the item in the flower pot", }, }, Inherits = "cBlockEntity", }, cFurnaceEntity = { Desc = [[ This class represents a furnace block entity in the world.

    See also {{cRoot}}'s GetFurnaceRecipe() and GetFurnaceFuelBurnTime() functions ]], Functions = { GetCookTimeLeft = { Returns = { { Type = "number", }, }, Notes = "Returns the time until the current item finishes cooking, in ticks", }, GetFuelBurnTimeLeft = { Returns = { { Type = "number", }, }, Notes = "Returns the time until the current fuel is depleted, in ticks", }, GetFuelSlot = { Returns = { { Type = "cItem", }, }, Notes = "Returns the item in the fuel slot", }, GetInputSlot = { Returns = { { Type = "cItem", }, }, Notes = "Returns the item in the input slot", }, GetOutputSlot = { Returns = { { Type = "cItem", }, }, Notes = "Returns the item in the output slot", }, GetTimeCooked = { Returns = { { Type = "number", }, }, Notes = "Returns the time that the current item has been cooking, in ticks", }, HasFuelTimeLeft = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if there's time before the current fuel is depleted", }, GetAndResetReward = { Returns = { { Type = "number", }, }, Notes = "Calculates, resets, and returns the experience reward in this furnace", }, SetFuelSlot = { Params = { { Name = "Fuel", Type = "cItem", }, }, Notes = "Sets the item in the fuel slot", }, SetInputSlot = { Params = { { Name = "Input", Type = "cItem", }, }, Notes = "Sets the item in the input slot", }, SetOutputSlot = { Params = { { Name = "Output", Type = "cItem", }, }, Notes = "Sets the item in the output slot", }, }, Constants = { ContentsHeight = { Notes = "Height (Y) of the {{cItemGrid|cItemGrid}} representing the contents", }, ContentsWidth = { Notes = "Width (X) of the {{cItemGrid|cItemGrid}} representing the contents", }, fsFuel = { Notes = "Index of the fuel slot", }, fsInput = { Notes = "Index of the input slot", }, fsOutput = { Notes = "Index of the output slot", }, }, ConstantGroups = { SlotIndices = { Include = "fs.*", TextBefore = "When using the GetSlot() or SetSlot() function, use these constants for slot index:", }, }, Inherits = "cBlockEntityWithItems", }, cHopperEntity = { Desc = [[ This class represents a hopper block entity in the world. ]], Functions = { GetOutputBlockPos = { Params = { { Name = "BlockMeta", Type = "number", }, }, Returns = { { Name = "IsAttached", Type = "boolean", }, { Name = "BlockX", Type = "number", }, { Name = "BlockY", Type = "number", }, { Name = "BlockZ", Type = "number", }, }, Notes = "Returns whether the hopper is attached, and if so, the block coords of the block receiving the output items, based on the given meta.", }, }, Constants = { ContentsHeight = { Notes = "Height (Y) of the internal {{cItemGrid}} representing the hopper contents.", }, ContentsWidth = { Notes = "Width (X) of the internal {{cItemGrid}} representing the hopper contents.", }, }, Inherits = "cBlockEntityWithItems", }, cJukeboxEntity = { Desc = [[ This class represents a jukebox in the world. It can play the records, either when the {{cPlayer|player}} uses the record on the jukebox, or when a plugin instructs it to play. ]], Functions = { EjectRecord = { Returns = { { Type = "boolean", }, }, Notes = "Ejects the current record as a {{cPickup|pickup}}. No action if there's no current record. To remove record without generating the pickup, use SetRecord(0). Returns true if pickup ejected.", }, GetRecord = { Returns = { { Type = "number", }, }, Notes = "Returns the record currently present. Zero for no record, E_ITEM_*_DISC for records.", }, IsPlayingRecord = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the jukebox is playing a record.", }, IsRecordItem = { IsStatic = true, Params = { { Name = "ItemType", Type = "number", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if the specified item is a record that can be played.", }, PlayRecord = { Params = { { Name = "RecordItemType", Type = "number", }, }, Returns = { { Type = "boolean", }, }, Notes = "Plays the specified Record. Return false if the parameter isn't a playable Record (E_ITEM_XXX_DISC). If there is a record already playing, ejects it first.", }, SetRecord = { Params = { { Name = "RecordItemType", Type = "number", }, }, Notes = "Sets the currently present record. Use zero for no record, or E_ITEM_*_DISC for records.", }, }, Inherits = "cBlockEntity", }, cMobHeadEntity = { Desc = [[ This class represents a mob head block entity in the world. ]], Functions = { GetOwnerName = { Returns = { { Type = "string", }, }, Notes = "Returns the player name of the mob head", }, GetOwnerTexture = { Returns = { { Type = "string", }, }, Notes = "Returns the player texture of the mob head", }, GetOwnerTextureSignature = { Returns = { { Type = "string", }, }, Notes = "Returns the signature of the player texture of the mob head", }, GetOwnerUUID = { Returns = { { Type = "string", }, }, Notes = "Returns the player UUID of the mob head", }, GetRotation = { Returns = { { Type = "eMobHeadRotation", }, }, Notes = "Returns the rotation of the mob head", }, GetType = { Returns = { { Type = "eMobHeadType", }, }, Notes = "Returns the type of the mob head", }, SetOwner = { { Params = { { Name = "cPlayer", Type = "cPlayer", }, }, Notes = "Set the {{cPlayer|player}} for mob heads with player type", }, { Params = { { Name = "OwnerUUID", Type = "string", }, { Name = "OwnerName", Type = "string", }, { Name = "OwnerTexture", Type = "string", }, { Name = "OwnerTextureSignature", Type = "string", }, }, Notes = "Sets the player components for the mob heads with player type", }, }, SetRotation = { Params = { { Name = "Rotation", Type = "eMobHeadRotation", }, }, Notes = "Sets the rotation of the mob head.", }, SetType = { Params = { { Name = "HeadType", Type = "eMobHeadType", }, }, Notes = "Set the type of the mob head", }, }, Inherits = "cBlockEntity", }, cMobSpawnerEntity = { Desc = [[ This class represents a mob spawner block entity in the world. ]], Functions = { GetEntity = { Returns = { { Name = "MobType", Type = "eMonsterType", }, }, Notes = "Returns the entity type that will be spawn by this mob spawner.", }, GetNearbyMonsterNum = { Params = { { Name = "MobType", Type = "eMonsterType", }, }, Returns = { { Type = "number", }, }, Notes = "Returns the amount of this monster type in a radius defined by SetSpawnRange (Y: 4-block radius).", }, GetNearbyPlayersNum = { Returns = { { Type = "number", }, }, Notes = "Returns the amount of the nearby players in a 16-block radius.", }, GetSpawnCount = { Returns = { { Type = "number", } }, Notes = "Returns the number of entities the spawner will try to spawn on each activation.", }, GetSpawnRange = { Returns = { { Type = "number", } }, Notes = "Returns half the length of the square the spawner tries to spawn entities in.", }, GetSpawnDelay = { Returns = { { Type = "number", }, }, Notes = "Returns the spawn delay. This is the tick delay that is needed to spawn new monsters.", }, GetMinSpawnDelay = { Returns = { { Type = "number", } }, Notes = "Returns the minimum number of ticks the spawner waits until spawning new entities automatically.", }, GetMaxSpawnDelay = { Returns = { { Type = "number", } }, Notes = "Returns the maximum number of ticks the spawner waits until spawning new entities automatically.", }, GetMaxNearbyEntities = { Returns = { { Type = "number", } }, Notes = "Returns the maximum number of entities of the same type that can be present before the spawner cannot spawn more entities.", }, GetRequiredPlayerRange = { Returns = { { Type = "number" } }, Notes = "Returns the maximum euclidean distance from a player where the spawner can be activated.", }, ResetTimer = { Notes = "Sets the spawn delay to a new random value.", }, SetEntity = { Params = { { Name = "MobType", Type = "eMonsterType", }, }, Notes = "Sets the type of the mob that will be spawned by this mob spawner.", }, SetSpawnDelay = { Params = { { Name = "SpawnDelayTicks", Type = "number", }, }, Notes = "Sets the spawn delay.", }, SetSpawnCount = { Params = { { Name = "SpawnCount", Type = "number", }, }, Notes = "Sets the number of entities the spawner will try to spawn in each activation. Might not spawn all of them due to spawn limitations of the entity.", }, SetSpawnRange = { Params = { { Name = "SpawnRange", Type = "number", }, }, Notes = "Sets half the length of the square the spawner will try to spawn entities in.", }, SetMinSpawnDelay = { Params = { { Name = "MinSpawnDelay", Type = "number", }, }, Notes = "Sets the minimum amount of ticks the spawner will wait before spawning new entities.", }, SetMaxSpawnDelay = { Params = { { Name = "MaxSpawnDelay", Type = "number", }, }, Notes = "Sets the maximum amount of ticks the spawner will wait before spawning new entities.", }, SetMaxNearbyEntities = { Params = { { Name = "MaxNearbyEntities", Type = "number", }, }, Notes = "Sets the maximum amount of nearby entities until the spawner will stop spawning this entity type.", }, SetRequiredPlayerRange = { Params = { { Name = "RequiredPlayerRange", Type = "number", }, }, Notes = "Sets the maximum euclidean distance from a player where the spawner can be activated.", }, SpawnEntity = { Notes = "Spawns the entity. NOTE: This function resets the delay before the next automatic activation of the spawner.", }, UpdateActiveState = { Notes = "Update the active flag from the mob spawner. This function is called every 5 seconds from the Tick() function.", }, }, Inherits = "cBlockEntity", }, cNoteEntity = { Desc = [[ This class represents a note block entity in the world. It takes care of the note block's note, and also can play the sound, either when the {{cPlayer|player}} right-clicks it, redstone activates it, or upon a plugin's request.

    The note is stored as an integer between 0 and 24. ]], Functions = { GetNote = { Returns = { { Type = "number", }, }, Notes = "Returns the current note set for the block", }, IncrementNote = { Notes = "Adds 1 to the current note. Wraps around to 0 when the note cannot go any higher.", }, MakeSound = { Notes = "Plays the sound for all {{cClientHandle|clients}} near this block.", }, SetNote = { Params = { { Name = "Note", Type = "number", }, }, Notes = "Sets a new note for the block.", }, GetPitch = { Returns = { { Type = "number", }, }, Notes = "(DEPRECATED) Please use cNoteEntity:GetNote. Returns the current pitch set for the block", }, IncrementPitch = { Notes = "(DEPRECATED) Please use cNoteEntity:IncrementNote. Adds 1 to the current pitch. Wraps around to 0 when the pitch cannot go any higher.", }, MakeSound = { Notes = "Plays the sound for all {{cClientHandle|clients}} near this block.", }, SetPitch = { Params = { { Name = "Pitch", Type = "number", }, }, Notes = "(DEPRECATED) Please use cNoteEntity:SetNote. Sets a new note for the block.", }, }, Inherits = "cBlockEntity", }, cSignEntity = { Desc = [[ A sign entity represents a sign in the world. This class is only used when generating chunks, so that the plugins may generate signs within new chunks. See the code example in {{cChunkDesc}}. ]], Functions = { GetLine = { Params = { { Name = "LineIndex", Type = "number", }, }, Returns = { { Type = "string", }, }, Notes = "Returns the specified line. LineIndex is expected between 0 and 3. Returns empty string and logs to server console when LineIndex is invalid.", }, SetLine = { Params = { { Name = "LineIndex", Type = "number", }, { Name = "LineText", Type = "string", }, }, Notes = "Sets the specified line. LineIndex is expected between 0 and 3. Logs to server console when LineIndex is invalid.", }, SetLines = { Params = { { Name = "Line1", Type = "string", }, { Name = "Line2", Type = "string", }, { Name = "Line3", Type = "string", }, { Name = "Line4", Type = "string", }, }, Notes = "Sets all the sign's lines at once. Note that plugins should prefer to use {{cWorld}}:SetSignLines(), so that they can specify the player on whose behalf the sign is being set.", }, }, Inherits = "cBlockEntity", }, } ================================================ FILE: Server/Plugins/APIDump/Classes/Geometry.lua ================================================ -- Geometry.lua -- Defines the documentation for geometry-related classes: -- cBoundingBox, cCuboid, cLineBlockTracer, Vector3X return { cBoundingBox = { Desc = [[ Represents two sets of coordinates, minimum and maximum for each direction; thus defining an axis-aligned cuboid with floating-point boundaries. It supports operations changing the size and position of the box, as well as querying whether a point or another BoundingBox is inside the box.

    All the points within the coordinate limits (inclusive the edges) are considered "inside" the box. However, for intersection purposes, if the intersection is "sharp" in any coord (min1 == max2, i. e. zero volume), the boxes are considered non-intersecting.

    ]], Functions = { CalcLineIntersection = { { Params = { { Name = "LineStart", Type = "Vector3d", }, { Name = "LinePt2", Type = "Vector3d", }, }, Returns = { { Name = "DoesIntersect", Type = "boolean", }, { Name = "LineCoeff", Type = "number", IsOptional = true, }, { Name = "Face", Type = "eBlockFace", IsOptional = true, }, }, Notes = "Calculates the intersection of a ray (half-line), given by two of its points, with the bounding box. Returns false if the line doesn't intersect the bounding box, or true, together with coefficient of the intersection (how much of the difference between the two ray points is needed to reach the intersection), and the face of the box which is intersected.", }, { IsStatic = true, Params = { { Name = "BoxMin", Type = "Vector3d", }, { Name = "BoxMax", Type = "Vector3d", }, { Name = "LineStart", Type = "Vector3d", }, { Name = "LinePt2", Type = "Vector3d", }, }, Returns = { { Name = "DoesIntersect", Type = "boolean", }, { Name = "LineCoeff", Type = "number", IsOptional = true, }, { Name = "Face", Type = "eBlockFace", IsOptional = true, }, }, Notes = "Calculates the intersection of a ray (half-line), given by two of its points, with the bounding box specified as its minimum and maximum coords. Returns false if the line doesn't intersect the bounding box, or true, together with coefficient of the intersection (how much of the difference between the two ray points is needed to reach the intersection), and the face of the box which is intersected.", }, }, constructor = { { Params = { { Name = "MinX", Type = "number", }, { Name = "MaxX", Type = "number", }, { Name = "MinY", Type = "number", }, { Name = "MaxY", Type = "number", }, { Name = "MinZ", Type = "number", }, { Name = "MaxZ", Type = "number", }, }, Returns = { { Type = "cBoundingBox", }, }, Notes = "Creates a new bounding box with the specified edges", }, { Params = { { Name = "Min", Type = "Vector3d", }, { Name = "Max", Type = "Vector3d", }, }, Returns = { { Type = "cBoundingBox", }, }, Notes = "Creates a new bounding box with the coords specified as two vectors", }, { Params = { { Name = "Pos", Type = "Vector3d", }, { Name = "Radius", Type = "number", }, { Name = "Height", Type = "number", }, }, Returns = { { Type = "cBoundingBox", }, }, Notes = "Creates a new bounding box from the position given and radius (X/Z) and height. Radius is added from X/Z to calculate the maximum coords and subtracted from X/Z to get the minimum; minimum Y is set to Pos.y and maxumim Y to Pos.y plus Height. This corresponds with how {{cEntity|entities}} are represented in Minecraft.", }, { Params = { { Name = "OtherBoundingBox", Type = "cBoundingBox", }, }, Returns = { { Type = "cBoundingBox", }, }, Notes = "Creates a new copy of the given bounding box. Same result can be achieved by using a simple assignment.", }, { Params = { { Name = "Pos", Type = "Vector3d", }, { Name = "CubeSideLength", Type = "number", }, }, Returns = { { Type = "cBoundingBox", }, }, Notes = "Creates a new bounding box as a cube with the specified side length centered around the specified point.", }, }, DoesIntersect = { Params = { { Name = "OtherBoundingBox", Type = "cBoundingBox", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if the two bounding boxes have an intersection of nonzero volume.", }, Expand = { Params = { { Name = "ExpandX", Type = "number", }, { Name = "ExpandY", Type = "number", }, { Name = "ExpandZ", Type = "number", }, }, Notes = "Expands this bounding box by the specified amount in each direction (so the box becomes larger by 2 * Expand in each axis).", }, GetMax = { Returns = { { Name = "Point", Type = "Vector3d", }, }, Notes = "Returns the boundary point with the maximum coords", }, GetMaxX = { Returns = { { Type = "number", }, }, Notes = "Returns the maximum X coord of the bounding box", }, GetMaxY = { Returns = { { Type = "number", }, }, Notes = "Returns the maximum Y coord of the bounding box", }, GetMaxZ = { Returns = { { Type = "number", }, }, Notes = "Returns the maximum Z coord of the bounding box", }, GetMin = { Returns = { { Name = "Point", Type = "Vector3d", }, }, Notes = "Returns the boundary point with the minimum coords", }, GetMinX = { Returns = { { Type = "number", }, }, Notes = "Returns the minimum X coord of the bounding box", }, GetMinY = { Returns = { { Type = "number", }, }, Notes = "Returns the minimum Y coord of the bounding box", }, GetMinZ = { Returns = { { Type = "number", }, }, Notes = "Returns the minimum Z coord of the bounding box", }, Intersect = { Params = { { Name = "OtherBbox", Type = "cBoundingBox", }, }, Returns = { { Type = "boolean", }, { Name = "Intersection", Type = "cBoundingBox", IsOptional = true, }, }, Notes = "Checks if the intersection between this bounding box and another one is non-empty. Returns false if the intersection is empty, true and a new cBoundingBox representing the intersection of the two boxes.", }, IsInside = { { Params = { { Name = "Point", Type = "Vector3d", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if the specified point is inside (including on the edge) of the box.", }, { Params = { { Name = "PointX", Type = "number", }, { Name = "PointY", Type = "number", }, { Name = "PointZ", Type = "number", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if the specified point is inside (including on the edge) of the box.", }, { Params = { { Name = "OtherBoundingBox", Type = "cBoundingBox", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if OtherBoundingBox is inside of this box.", }, { Params = { { Name = "OtherBoxMin", Type = "Vector3d", }, { Name = "OtherBoxMax", Type = "Vector3d", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if the other bounding box, specified by its 2 corners, is inside of this box.", }, { IsStatic = true, Params = { { Name = "Min", Type = "Vector3d", }, { Name = "Max", Type = "Vector3d", }, { Name = "Point", Type = "Vector3d", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if the specified point is inside the bounding box specified by its min / max corners", }, { IsStatic = true, Params = { { Name = "Min", Type = "Vector3d", }, { Name = "Max", Type = "Vector3d", }, { Name = "X", Type = "number", }, { Name = "Y", Type = "number", }, { Name = "Z", Type = "number", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if the specified point is inside the bounding box specified by its min / max corners", }, }, Move = { { Params = { { Name = "OffsetX", Type = "number", }, { Name = "OffsetY", Type = "number", }, { Name = "OffsetZ", Type = "number", }, }, Notes = "Moves the bounding box by the specified offset in each axis", }, { Params = { { Name = "Offset", Type = "Vector3d", }, }, Notes = "Moves the bounding box by the specified offset in each axis", }, }, Union = { Params = { { Name = "OtherBoundingBox", Type = "cBoundingBox", }, }, Returns = { { Type = "cBoundingBox", }, }, Notes = "Returns the smallest bounding box that contains both OtherBoundingBox and this bounding box. Note that unlike the strict geometrical meaning of \"union\", this operation actually returns a cBoundingBox.", }, }, }, cCuboid = { Desc = [[ cCuboid offers some native support for integral-boundary cuboids. A cuboid internally consists of two {{Vector3i}}-s. By default the cuboid doesn't make any assumptions about the defining points, but for most of the operations in the cCuboid class, the p1 member variable is expected to be the minima and the p2 variable the maxima. The Sort() function guarantees this condition.

    The Cuboid considers both its edges inclusive.

    ]], Functions = { Assign = { { Params = { { Name = "SrcCuboid", Type = "cCuboid", }, }, Notes = "Copies all the coords from the src cuboid to this cuboid. Sort-state is ignored.", }, { Params = { { Name = "Point1", Type = "Vector3i", }, { Name = "Point2", Type = "Vector3i", }, }, Notes = "Assigns all the coords to the specified values. Sort-state is ignored.", }, }, Clamp = { Params = { { Name = "Limits", Type = "cCuboid", }, }, Notes = "Clamps this cuboid, so that it doesn't reach outside of Limits in any direction. Assumes both cuboids are sorted.", }, ClampSize = { Params = { { Name = "MaxSize", Type = "Vector3i", }, }, Notes = "Clamps this cuboid's p2 so that the cuboid's size doesn't exceed the specified max size. Assumes the cuboid is sorted.", }, ClampX = { Params = { { Name = "MinX", Type = "number", }, { Name = "MaxX", Type = "number", }, }, Notes = "Clamps both X coords into the range provided. Sortedness-agnostic.", }, ClampY = { Params = { { Name = "MinY", Type = "number", }, { Name = "MaxY", Type = "number", }, }, Notes = "Clamps both Y coords into the range provided. Sortedness-agnostic.", }, ClampZ = { Params = { { Name = "MinZ", Type = "number", }, { Name = "MaxZ", Type = "number", }, }, Notes = "Clamps both Z coords into the range provided. Sortedness-agnostic.", }, constructor = { { Returns = { { Type = "cCuboid", }, }, Notes = "Creates a new Cuboid object with all-zero coords", }, { Params = { { Name = "OtherCuboid", Type = "cCuboid", }, }, Returns = { { Type = "cCuboid", }, }, Notes = "Creates a new Cuboid object as a copy of OtherCuboid", }, { Params = { { Name = "Point1", Type = "Vector3i", }, { Name = "Point2", Type = "Vector3i", }, }, Returns = { { Type = "cCuboid", }, }, Notes = "Creates a new Cuboid object with the specified points as its corners.", }, { Params = { { Name = "X", Type = "number", }, { Name = "Y", Type = "number", }, { Name = "Z", Type = "number", }, }, Returns = { { Type = "cCuboid", }, }, Notes = "Creates a new Cuboid object with the specified point as both its corners (the cuboid has a size of 1 in each direction).", }, }, DifX = { Returns = { { Type = "number", }, }, Notes = "Returns the difference between the two X coords (X-size minus 1). Assumes sorted.", }, DifY = { Returns = { { Type = "number", }, }, Notes = "Returns the difference between the two Y coords (Y-size minus 1). Assumes sorted.", }, DifZ = { Returns = { { Type = "number", }, }, Notes = "Returns the difference between the two Z coords (Z-size minus 1). Assumes sorted.", }, DoesIntersect = { Params = { { Name = "OtherCuboid", Type = "cCuboid", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if this cuboid has at least one voxel in common with OtherCuboid. Note that edges are considered inclusive. Assumes both sorted.", }, Engulf = { Params = { { Name = "Point", Type = "Vector3i", }, }, Notes = "If needed, expands the cuboid to include the specified point. Doesn't shrink. Assumes sorted. ", }, Expand = { Params = { { Name = "SubMinX", Type = "number", }, { Name = "AddMaxX", Type = "number", }, { Name = "SubMinY", Type = "number", }, { Name = "AddMaxY", Type = "number", }, { Name = "SubMinZ", Type = "number", }, { Name = "AddMaxZ", Type = "number", }, }, Notes = "Expands the cuboid by the specified amount in each direction. Works on unsorted cuboids as well. NOTE: this function doesn't check for underflows.", }, GetVolume = { Returns = { { Type = "number", }, }, Notes = "Returns the volume of the cuboid, in blocks. Note that the volume considers both coords inclusive. Works on unsorted cuboids, too.", }, IsCompletelyInside = { Params = { { Name = "OuterCuboid", Type = "cCuboid", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if this cuboid is completely inside (in all directions) in OuterCuboid. Assumes both sorted.", }, IsInside = { { Params = { { Name = "Point", Type = "Vector3i", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if the specified point (integral coords) is inside this cuboid. Assumes sorted.", }, { Params = { { Name = "Point", Type = "Vector3d", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if the specified point (floating-point coords) is inside this cuboid. Assumes sorted.", }, }, IsSorted = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if this cuboid is sorted", }, Move = { Params = { { Name = "Offset", Type = "Vector3i", }, }, Notes = "Adds the specified offsets to each respective coord, effectively moving the Cuboid. Sort-state is ignored and preserved.", }, Sort = { Notes = "Sorts the internal representation so that p1 contains the lesser coords and p2 contains the greater coords.", }, }, Variables = { p1 = { Type = "{{Vector3i}}", Notes = "The first corner. Usually the lesser of the two coords in each set", }, p2 = { Type = "{{Vector3i}}", Notes = "The second corner. Usually the larger of the two coords in each set", }, }, }, cLineBlockTracer = { Desc = [[ This class provides an easy-to-use interface for tracing lines through individual blocks in the world. It can either be used to call the provided callbacks according to what events it encounters along the way, or there are shortcut functions used for the most popular tracing reasons - line of sight and solid hits. ]], Functions = { FirstSolidHitTrace = { { IsStatic = true, Params = { { Name = "World", Type = "cWorld" }, { Name = "StartX", Type = "number" }, { Name = "StartY", Type = "number" }, { Name = "StartZ", Type = "number" }, { Name = "EndX", Type = "number" }, { Name = "EndY", Type = "number" }, { Name = "EndZ", Type = "number" }, }, Returns = { { Name = "HasHitSolid", Type = "boolean" }, { Name = "HitCoords", Type = "Vector3d" }, { Name = "HitBlockCoords", Type = "Vector3i" }, { Name = "HitBlockFace", Type = "eBlockFace" }, }, Notes = "If the specified line hits a solid block, return true and the coordinates / face of the first such solid block hit. Returns false if there's no solid block on that line.", }, { IsStatic = true, Params = { { Name = "World", Type = "cWorld" }, { Name = "Start", Type = "Vector3d" }, { Name = "End", Type = "Vector3d" }, }, Returns = { { Name = "HasHitSolid", Type = "boolean" }, { Name = "HitCoords", Type = "Vector3d" }, { Name = "HitBlockCoords", Type = "Vector3i" }, { Name = "HitBlockFace", Type = "eBlockFace" }, }, Notes = "If the specified line hits a solid block, return true and the coordinates / face of the first such solid block hit. Returns false if there's no solid block on that line.", }, }, -- FirstSolidHitTrace LineOfSightTrace = { { IsStatic = true, Params = { { Name = "World", Type = "cWorld" }, { Name = "StartX", Type = "number" }, { Name = "StartY", Type = "number" }, { Name = "StartZ", Type = "number" }, { Name = "EndX", Type = "number" }, { Name = "EndY", Type = "number" }, { Name = "EndZ", Type = "number" }, { Name = "Sight", Type = "number" }, }, Returns = { { Name = "CanSee", Type = "boolean" }, }, Notes = "Returns true if the two points specified are within line of sight of each other. The Sight parameter specifies which blocks are considered transparent for the trace, it is a combination of {{cLineBlockTracer#eLineOfSight|losXXX}} values added together." }, { IsStatic = true, Params = { { Name = "World", Type = "cWorld" }, { Name = "Start", Type = "Vector3d" }, { Name = "End", Type = "Vector3d" }, { Name = "Sight", Type = "number" }, }, Returns = { { Name = "CanSee", Type = "boolean" }, }, Notes = "Returns true if the two points specified are within line of sight of each other. The Sight parameter specifies which blocks are considered transparent for the trace, it is a combination of {{cLineBlockTracer#eLineOfSight|losXXX}} values added together." }, }, -- LineOfSightTrace Trace = { { IsStatic = true, Params = { { Name = "World", Type = "cWorld" }, { Name = "Callbacks", Type = "table" }, { Name = "StartX", Type = "number" }, { Name = "StartY", Type = "number" }, { Name = "StartZ", Type = "number" }, { Name = "EndX", Type = "number" }, { Name = "EndY", Type = "number" }, { Name = "EndZ", Type = "number" }, }, Returns = { { Type = "boolean", }, }, Notes = "(OBSOLETE, use the Vector3-based overload instead) Performs the trace on the specified line. Returns true if the entire trace was processed (no callback returned true)", }, { IsStatic = true, Params = { { Name = "World", Type = "cWorld" }, { Name = "Callbacks", Type = "table" }, { Name = "Start", Type = "Vector3d" }, { Name = "End", Type = "Vector3d" }, }, Returns = { { Type = "boolean", }, }, Notes = "Performs the trace on the specified line. Returns true if the entire trace was processed (no callback returned true)", }, }, }, Constants = { losAir = { Notes = "LineOfSight tracing can 'see' through air blocks.", }, losWater = { Notes = "LineOfSight tracing can 'see' through water blocks.", }, losLava = { Notes = "LineOfSight tracing can 'see' through lava blocks.", }, }, ConstantGroups = { eLineOfSight = { Include = "los.*", TextBefore = "The following constants are used to speficy which blocks are see-through when tracing a LineOfSight trace. Add them together to make up the Sight parameter.", }, }, AdditionalInfo = { { Header = "Callbacks", Contents = [[ The Callbacks in the Trace() function is a table that contains named functions. Cuberite will call individual functions from that table for the events that occur on the line - hitting a block, going out of valid world data etc. The following table lists all the available callbacks. If the callback function is not defined, Cuberite skips it. Each function can return a bool value, if it returns true, the tracing is aborted and Trace() returns false.
    Note: The folowing can only be used when using the Vector3-based Trace() function. When using the number-based overload, the callbacks receive number-based coordinates (see Deprecated Callbacks below).

    NameParametersNotes
    OnNextBlockBlockPos, BlockType, BlockMeta, EntryFace Called when the ray hits a new valid block. The block type and meta is given. EntryFace is one of the BLOCK_FACE_ constants indicating which "side" of the block got hit by the ray.
    OnNextBlockNoDataBlockPos, EntryFace Called when the ray hits a new block, but the block is in an unloaded chunk - no valid data is available. Only the coords and the entry face are given.
    OnOutOfWorldBlockPos Called when the ray goes outside of the world (Y-wise); the coords specify the exact exit point. Note that for other paths than lines (considered for future implementations) the path may leave the world and go back in again later, in such a case this callback is followed by OnIntoWorld() and further OnNextBlock() calls.
    OnIntoWorldBlockPos Called when the ray enters the world (Y-wise); the coords specify the exact entry point.
    OnNoMoreHits  Called when the path is sure not to hit any more blocks. This is the final callback, no more callbacks are called after this function. Unlike the other callbacks, this function doesn't have a return value.
    OnNoChunk  Called when the ray enters a chunk that is not loaded. This usually means that the tracing is aborted. Unlike the other callbacks, this function doesn't have a return value.
    ]], }, { Header = "Deprecated Callbacks", Contents = [[ When using the deprecated number-based Trace function, Cuberite will instead assume the following signatures for the callbacks:

    NameParametersNotes
    OnNextBlockBlockX, BlockY, BlockZ, BlockType, BlockMeta, EntryFace Called when the ray hits a new valid block. The block type and meta is given. EntryFace is one of the BLOCK_FACE_ constants indicating which "side" of the block got hit by the ray.
    OnNextBlockNoDataBlockX, BlockY, BlockZ, EntryFace Called when the ray hits a new block, but the block is in an unloaded chunk - no valid data is available. Only the coords and the entry face are given.
    OnOutOfWorldX, Y, Z Called when the ray goes outside of the world (Y-wise); the coords specify the exact exit point. Note that for other paths than lines (considered for future implementations) the path may leave the world and go back in again later, in such a case this callback is followed by OnIntoWorld() and further OnNextBlock() calls.
    OnIntoWorldX, Y, Z Called when the ray enters the world (Y-wise); the coords specify the exact entry point.
    ]], }, { Header = "Example", Contents = [[

    The following example is taken from the Debuggers plugin. It is a command handler function for the "/spidey" command that creates a line of cobweb blocks from the player's eyes up to 50 blocks away in the direction they're looking, but only through the air.

    function HandleSpideyCmd(a_Split, a_Player)
    	local World = a_Player:GetWorld();
    
    	local Callbacks = {
    		OnNextBlock = function(a_BlockPos, a_BlockType, a_BlockMeta)
    			if (a_BlockType ~= E_BLOCK_AIR) then
    				-- abort the trace
    				return true;
    			end
    			World:SetBlock(a_BlockPos, E_BLOCK_COBWEB, 0);
    		end
    	};
    
    	local EyePos = a_Player:GetEyePosition();
    	local LookVector = a_Player:GetLookVector();
    	LookVector:Normalize();  -- Make the vector 1 m long
    
    	-- Start cca 2 blocks away from the eyes
    	local Start = EyePos + LookVector + LookVector;
    	local End = EyePos + LookVector * 50;
    
    	cLineBlockTracer.Trace(World, Callbacks, Start, End);
    
    	return true;
    end
    

    ]], }, }, }, Vector3d = { Desc = [[ A Vector3d object uses double precision floating point values to describe a point in 3D space.

    See also {{Vector3f}} for single-precision floating point 3D coords and {{Vector3i}} for integer 3D coords. ]], Functions = { Abs = { Notes = "Updates each coord to its absolute value.", }, addedX = { Params = { { Name = "ofs", Type = "number", }, }, Returns = { { Type = "Vector3d", }, }, Notes = "Returns a copy of the vector, moved by the specified offset on the X axis", }, addedXZ = { Params = { { Name = "ofsX", Type = "number", }, { Name = "ofsZ", Type = "number", }, }, Returns = { { Type = "Vector3d", }, }, Notes = "Returns a copy of the vector, moved by the specified offsets on the X and Z axes", }, addedY = { Params = { { Name = "ofs", Type = "number", }, }, Returns = { { Type = "Vector3d", }, }, Notes = "Returns a copy of the vector, moved by the specified offset on the Y axis", }, addedZ = { Params = { { Name = "ofs", Type = "number", }, }, Returns = { { Type = "Vector3d", }, }, Notes = "Returns a copy of the vector, moved by the specified offset on the Z axis", }, Ceil = { Returns = { { Type = "Vector3i", }, }, Notes = "Returns a new {{Vector3i}} object with coords set to math.ceil of this vector's coords.", }, Clamp = { Params = { { Name = "min", Type = "number", }, { Name = "max", Type = "number", }, }, Notes = "Clamps each coord into the specified range.", }, constructor = { { Params = { { Name = "Vector", Type = "Vector3f", }, }, Returns = { { Type = "Vector3d", }, }, Notes = "Creates a new Vector3d object by copying the coords from the given Vector3f.", }, { Returns = { { Type = "Vector3d", }, }, Notes = "Creates a new Vector3d object with all its coords set to 0.", }, { Params = { { Name = "X", Type = "number", }, { Name = "Y", Type = "number", }, { Name = "Z", Type = "number", }, }, Returns = { { Type = "Vector3d", }, }, Notes = "Creates a new Vector3d object with its coords set to the specified values.", }, }, Cross = { Params = { { Name = "Other", Type = "Vector3d", }, }, Returns = { { Type = "Vector3d", }, }, Notes = "Returns a new Vector3d that is a {{https://en.wikipedia.org/wiki/Cross_product|cross product}} of this vector and the specified vector.", }, Dot = { Params = { { Name = "Other", Type = "Vector3d", }, }, Returns = { { Type = "number", }, }, Notes = "Returns the dot product of this vector and the specified vector.", }, Equals = { Params = { { Name = "AnotherVector", Type = "Vector3d", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if this vector is exactly equal to the specified vector. Note that this is subject to (possibly imprecise) floating point math.", }, EqualsEps = { Params = { { Name = "AnotherVector", Type = "Vector3d", }, { Name = "Eps", Type = "number", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if the differences between each corresponding coords of this vector and the one specified are less than the specified Eps.", }, Floor = { Returns = { { Type = "Vector3i", }, }, Notes = "Returns a new {{Vector3i}} object with coords set to math.floor of this vector's coords.", }, HasNonZeroLength = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the vector has at least one coord non-zero. Note that this is subject to (possibly imprecise) floating point math.", }, Length = { Returns = { { Type = "number", }, }, Notes = "Returns the (euclidean) length of the vector.", }, LineCoeffToXYPlane = { Params = { { Name = "Vector3d", Type = "Vector3d", }, { Name = "Z", Type = "number", }, }, Returns = { { Type = "number", }, }, Notes = "Returns the coefficient for the line from the specified vector through this vector to reach the specified Z coord. The result satisfies the following equation: (this + Result * (Param - this)).z = Z. Returns the NO_INTERSECTION constant if there's no intersection.", }, LineCoeffToXZPlane = { Params = { { Name = "Vector3d", Type = "Vector3d", }, { Name = "Y", Type = "number", }, }, Returns = { { Type = "number", }, }, Notes = "Returns the coefficient for the line from the specified vector through this vector to reach the specified Y coord. The result satisfies the following equation: (this + Result * (Param - this)).y = Y. Returns the NO_INTERSECTION constant if there's no intersection.", }, LineCoeffToYZPlane = { Params = { { Name = "Vector3d", Type = "Vector3d", }, { Name = "X", Type = "number", }, }, Returns = { { Type = "number", }, }, Notes = "Returns the coefficient for the line from the specified vector through this vector to reach the specified X coord. The result satisfies the following equation: (this + Result * (Param - this)).x = X. Returns the NO_INTERSECTION constant if there's no intersection.", }, Move = { { Params = { { Name = "X", Type = "number", }, { Name = "Y", Type = "number", }, { Name = "Z", Type = "number", }, }, Notes = "Adds the specified offsets to each coord, effectively moving the vector by the specified coord offsets.", }, { Params = { { Name = "Diff", Type = "Vector3d", }, }, Notes = "Adds the specified vector to this vector. Is slightly better performant than adding with a \"+\" because this doesn't create a new object for the result.", }, }, Normalize = { Notes = "Changes this vector so that it keeps current direction but is exactly 1 unit long. FIXME: Fails for a zero vector.", }, NormalizeCopy = { Returns = { { Type = "Vector3d", }, }, Notes = "Returns a new vector that has the same direction as this but is exactly 1 unit long. FIXME: Fails for a zero vector.", }, operator_div = { { Params = { { Name = "ParCoordDivisors", Type = "Vector3d", }, }, Returns = { { Type = "Vector3d", }, }, Notes = "Returns a new Vector3d object with each coord divided by the corresponding coord from the given vector.", }, { Params = { { Name = "Divisor", Type = "number", }, }, Returns = { { Type = "Vector3d", }, }, Notes = "Returns a new Vector3d object with each coord divided by the specified number.", }, }, operator_mul = { { Params = { { Name = "PerCoordMultiplier", Type = "Vector3d", }, }, Returns = { { Type = "Vector3d", }, }, Notes = "Returns a new Vector3d object with each coord multiplied by the corresponding coord from the given vector.", }, { Params = { { Name = "Multiplier", Type = "number", }, }, Returns = { { Type = "Vector3d", }, }, Notes = "Returns a new Vector3d object with each coord multiplied.", }, }, operator_plus = { Params = { { Name = "Addend", Type = "Vector3d", }, }, Returns = { { Type = "Vector3d", }, }, Notes = "Returns a new Vector3d containing the sum of this vector and the specified vector", }, operator_sub = { { Params = { { Name = "Subtrahend", Type = "Vector3d", }, }, Returns = { { Type = "Vector3d", }, }, Notes = "Returns a new Vector3d object containing the difference between this object and the specified vector.", }, { Returns = { { Type = "Vector3d", }, }, Notes = "Returns a new Vector3d object that is a negative of this vector (all coords multiplied by -1).", }, }, Set = { Params = { { Name = "X", Type = "number", }, { Name = "Y", Type = "number", }, { Name = "Z", Type = "number", }, }, Notes = "Sets all the coords in this object.", }, SqrLength = { Returns = { { Type = "number", }, }, Notes = "Returns the (euclidean) length of this vector, squared. This operation is slightly less computationally expensive than Length(), while it conserves some properties of Length(), such as comparison. ", }, TurnCCW = { Notes = "Rotates the vector 90 degrees counterclockwise around the vertical axis. Note that this is specific to minecraft's axis ordering, which is X+ left, Z+ down.", }, TurnCW = { Notes = "Rotates the vector 90 degrees clockwise around the vertical axis. Note that this is specific to minecraft's axis ordering, which is X+ left, Z+ down.", }, }, Constants = { EPS = { Notes = "The max difference between two coords for which the coords are assumed equal (in LineCoeffToXYPlane() et al).", }, NO_INTERSECTION = { Notes = "Special return value for the LineCoeffToXYPlane() et al meaning that there's no intersection with the plane.", }, }, Variables = { x = { Type = "number", Notes = "The X coord of the vector.", }, y = { Type = "number", Notes = "The Y coord of the vector.", }, z = { Type = "number", Notes = "The Z coord of the vector.", }, }, }, Vector3f = { Desc = [[ A Vector3f object uses floating point values to describe a point in space.

    See also {{Vector3d}} for double-precision floating point 3D coords and {{Vector3i}} for integer 3D coords. ]], Functions = { Abs = { Notes = "Updates each coord to its absolute value.", }, addedX = { Params = { { Name = "ofs", Type = "number", }, }, Returns = { { Type = "Vector3f", }, }, Notes = "Returns a copy of the vector, moved by the specified offset on the X axis", }, addedXZ = { Params = { { Name = "ofsX", Type = "number", }, { Name = "ofsZ", Type = "number", }, }, Returns = { { Type = "Vector3f", }, }, Notes = "Returns a copy of the vector, moved by the specified offsets on the X and Z axes", }, addedY = { Params = { { Name = "ofs", Type = "number", }, }, Returns = { { Type = "Vector3f", }, }, Notes = "Returns a copy of the vector, moved by the specified offset on the Y axis", }, addedZ = { Params = { { Name = "ofs", Type = "number", }, }, Returns = { { Type = "Vector3f", }, }, Notes = "Returns a copy of the vector, moved by the specified offset on the Z axis", }, Ceil = { Returns = { { Type = "Vector3i", }, }, Notes = "Returns a new {{Vector3i}} object with coords set to math.ceil of this vector's coords.", }, Clamp = { Params = { { Name = "min", Type = "number", }, { Name = "max", Type = "number", }, }, Notes = "Clamps each coord into the specified range.", }, constructor = { { Returns = { { Type = "Vector3f", }, }, Notes = "Creates a new Vector3f object with zero coords", }, { Params = { { Name = "x", Type = "number", }, { Name = "y", Type = "number", }, { Name = "z", Type = "number", }, }, Returns = { { Type = "Vector3f", }, }, Notes = "Creates a new Vector3f object with the specified coords", }, { Params = { { Name = "Vector3f", Type = "Vector3f", }, }, Returns = { { Type = "Vector3f", }, }, Notes = "Creates a new Vector3f object as a copy of the specified vector", }, { Params = { { Name = "Vector3d", Type = "Vector3d", }, }, Returns = { { Type = "Vector3f", }, }, Notes = "Creates a new Vector3f object as a copy of the specified {{Vector3d}}", }, { Params = { { Name = "Vector3i", Type = "Vector3i", }, }, Returns = { { Type = "Vector3f", }, }, Notes = "Creates a new Vector3f object as a copy of the specified {{Vector3i}}", }, }, Cross = { Params = { { Name = "Other", Type = "Vector3f", }, }, Returns = { { Type = "Vector3f", }, }, Notes = "Returns a new Vector3f object that holds the cross product of this vector and the specified vector.", }, Dot = { Params = { { Name = "Other", Type = "Vector3f", }, }, Returns = { { Type = "number", }, }, Notes = "Returns the dot product of this vector and the specified vector.", }, Equals = { Params = { { Name = "Other", Type = "Vector3f", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if the specified vector is exactly equal to this vector. Note that this is subject to (possibly imprecise) floating point math.", }, EqualsEps = { Params = { { Name = "Other", Type = "Vector3f", }, { Name = "Eps", Type = "number", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if the differences between each corresponding coords of this vector and the one specified, are less than the specified Eps.", }, Floor = { Returns = { { Type = "Vector3i", }, }, Notes = "Returns a new {{Vector3i}} object with coords set to math.floor of this vector's coords.", }, HasNonZeroLength = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the vector has at least one coord non-zero. Note that this is subject to (possibly imprecise) floating point math.", }, Length = { Returns = { { Type = "number", }, }, Notes = "Returns the (euclidean) length of this vector", }, LineCoeffToXYPlane = { Params = { { Name = "Vector3f", Type = "Vector3f", }, { Name = "Z", Type = "number", }, }, Returns = { { Type = "number", }, }, Notes = "Returns the coefficient for the line from the specified vector through this vector to reach the specified Z coord. The result satisfies the following equation: (this + Result * (Param - this)).z = Z. Returns the NO_INTERSECTION constant if there's no intersection.", }, LineCoeffToXZPlane = { Params = { { Name = "Vector3f", Type = "Vector3f", }, { Name = "Y", Type = "number", }, }, Returns = { { Type = "number", }, }, Notes = "Returns the coefficient for the line from the specified vector through this vector to reach the specified Y coord. The result satisfies the following equation: (this + Result * (Param - this)).y = Y. Returns the NO_INTERSECTION constant if there's no intersection.", }, LineCoeffToYZPlane = { Params = { { Name = "Vector3f", Type = "Vector3f", }, { Name = "X", Type = "number", }, }, Returns = { { Type = "number", }, }, Notes = "Returns the coefficient for the line from the specified vector through this vector to reach the specified X coord. The result satisfies the following equation: (this + Result * (Param - this)).x = X. Returns the NO_INTERSECTION constant if there's no intersection.", }, Move = { { Params = { { Name = "X", Type = "number", }, { Name = "Y", Type = "number", }, { Name = "Z", Type = "number", }, }, Notes = "Adds the specified offsets to each coord, effectively moving the vector by the specified coord offsets.", }, { Params = { { Name = "Diff", Type = "Vector3f", }, }, Notes = "Adds the specified vector to this vector. Is slightly better performant than adding with a \"+\" because this doesn't create a new object for the result.", }, }, Normalize = { Notes = "Normalizes this vector (makes it 1 unit long while keeping the direction). FIXME: Fails for zero vectors.", }, NormalizeCopy = { Returns = { { Type = "Vector3f", }, }, Notes = "Returns a copy of this vector that is normalized (1 unit long while keeping the same direction). FIXME: Fails for zero vectors.", }, operator_div = { { Params = { { Name = "PerCoordDivisor", Type = "Vector3f", }, }, Returns = { { Type = "Vector3f", }, }, Notes = "Returns a new Vector3f object with each coord divided by the corresponding coord from the given vector.", }, { Params = { { Name = "Divisor", Type = "number", }, }, Returns = { { Type = "Vector3f", }, }, Notes = "Returns a new Vector3f object with each coord divided by the specified number.", }, }, operator_mul = { { Params = { { Name = "PerCoordMultiplier", Type = "number", }, }, Returns = { { Type = "Vector3f", }, }, Notes = "Returns a new Vector3f object that has each of its coords multiplied by the specified number", }, { Params = { { Name = "Multiplier", Type = "Vector3f", }, }, Returns = { { Type = "Vector3f", }, }, Notes = "Returns a new Vector3f object that has each of its coords multiplied by the respective coord of the specified vector.", }, }, operator_plus = { Params = { { Name = "Other", Type = "Vector3f", }, }, Returns = { { Type = "Vector3f", }, }, Notes = "Returns a new Vector3f object that holds the vector sum of this vector and the specified vector.", }, operator_sub = { { Params = { { Name = "Subtrahend", Type = "Vector3f", }, }, Returns = { { Type = "Vector3f", }, }, Notes = "Returns a new Vector3f object that holds the vector differrence between this vector and the specified vector.", }, { Returns = { { Type = "Vector3f", }, }, Notes = "Returns a new Vector3f that is a negative of this vector (all coords multiplied by -1).", }, }, Set = { Params = { { Name = "x", Type = "number", }, { Name = "y", Type = "number", }, { Name = "z", Type = "number", }, }, Notes = "Sets all the coords of the vector at once.", }, SqrLength = { Returns = { { Type = "number", }, }, Notes = "Returns the (euclidean) length of this vector, squared. This operation is slightly less computationally expensive than Length(), while it conserves some properties of Length(), such as comparison.", }, TurnCCW = { Notes = "Rotates the vector 90 degrees counterclockwise around the vertical axis. Note that this is specific to minecraft's axis ordering, which is X+ left, Z+ down.", }, TurnCW = { Notes = "Rotates the vector 90 degrees clockwise around the vertical axis. Note that this is specific to minecraft's axis ordering, which is X+ left, Z+ down.", }, }, Constants = { EPS = { Notes = "The max difference between two coords for which the coords are assumed equal (in LineCoeffToXYPlane() et al).", }, NO_INTERSECTION = { Notes = "Special return value for the LineCoeffToXYPlane() et al meaning that there's no intersection with the plane.", }, }, Variables = { x = { Type = "number", Notes = "The X coord of the vector.", }, y = { Type = "number", Notes = "The Y coord of the vector.", }, z = { Type = "number", Notes = "The Z coord of the vector.", }, }, }, Vector3i = { Desc = [[ A Vector3i object uses integer values to describe a point in space.

    See also {{Vector3d}} for double-precision floating point 3D coords and {{Vector3f}} for single-precision floating point 3D coords. ]], Functions = { Abs = { Notes = "Updates each coord to its absolute value.", }, addedX = { Params = { { Name = "ofs", Type = "number", }, }, Returns = { { Type = "Vector3i", }, }, Notes = "Returns a copy of the vector, moved by the specified offset on the X axis", }, addedXZ = { Params = { { Name = "ofsX", Type = "number", }, { Name = "ofsZ", Type = "number", }, }, Returns = { { Type = "Vector3i", }, }, Notes = "Returns a copy of the vector, moved by the specified offsets on the X and Z axes", }, addedY = { Params = { { Name = "ofs", Type = "number", }, }, Returns = { { Type = "Vector3i", }, }, Notes = "Returns a copy of the vector, moved by the specified offset on the Y axis", }, addedZ = { Params = { { Name = "ofs", Type = "number", }, }, Returns = { { Type = "Vector3i", }, }, Notes = "Returns a copy of the vector, moved by the specified offset on the Z axis", }, Ceil = { Returns = { { Type = "Vector3i", }, }, Notes = "Returns a new {{Vector3i}} object with coords set to math.ceil of this vector's coords. Normally not too useful with integer-only vectors, but still included for API completeness.", }, Clamp = { Params = { { Name = "min", Type = "number", }, { Name = "max", Type = "number", }, }, Notes = "Clamps each coord into the specified range.", }, constructor = { { Returns = { { Type = "Vector3i", }, }, Notes = "Creates a new Vector3i object with zero coords.", }, { Params = { { Name = "x", Type = "number", }, { Name = "y", Type = "number", }, { Name = "z", Type = "number", }, }, Returns = { { Type = "Vector3i", }, }, Notes = "Creates a new Vector3i object with the specified coords.", }, { Params = { { Name = "Vector3d", Type = "Vector3d", }, }, Returns = { { Type = "Vector3i", }, }, Notes = "Creates a new Vector3i object with coords copied and floor()-ed from the specified {{Vector3d}}.", }, }, Cross = { Params = { { Name = "Other", Type = "Vector3i", }, }, Returns = { { Type = "Vector3i", }, }, Notes = "Returns a new Vector3i that is a {{https://en.wikipedia.org/wiki/Cross_product|cross product}} of this vector and the specified vector.", }, Dot = { Params = { { Name = "Other", Type = "Vector3i", }, }, Returns = { { Type = "number", }, }, Notes = "Returns the dot product of this vector and the specified vector.", }, Equals = { Params = { { Name = "Other", Type = "Vector3i", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if this vector is exactly the same as the specified vector.", }, EqualsEps = { Params = { { Name = "Other", Type = "Vector3i", }, { Name = "Eps", Type = "number", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if the differences between each corresponding coords of this vector and the one specified, are less than the specified Eps. Normally not too useful for integer-only vectors, but still included for API completeness.", }, Floor = { Returns = { { Type = "Vector3i", }, }, Notes = "Returns a new {{Vector3i}} object with coords set to math.floor of this vector's coords. Normally not too useful with integer-only vectors, but still included for API completeness.", }, HasNonZeroLength = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the vector has at least one coord non-zero.", }, Length = { Returns = { { Type = "number", }, }, Notes = "Returns the (euclidean) length of this vector.", }, LineCoeffToXYPlane = { Params = { { Name = "Vector3i", Type = "Vector3i", }, { Name = "Z", Type = "number", }, }, Returns = { { Type = "number", }, }, Notes = "Returns the coefficient for the line from the specified vector through this vector to reach the specified Z coord. The result satisfies the following equation: (this + Result * (Param - this)).z = Z. Returns the NO_INTERSECTION constant if there's no intersection.", }, LineCoeffToXZPlane = { Params = { { Name = "Vector3i", Type = "Vector3i", }, { Name = "Y", Type = "number", }, }, Returns = { { Type = "number", }, }, Notes = "Returns the coefficient for the line from the specified vector through this vector to reach the specified Y coord. The result satisfies the following equation: (this + Result * (Param - this)).y = Y. Returns the NO_INTERSECTION constant if there's no intersection.", }, LineCoeffToYZPlane = { Params = { { Name = "Vector3i", Type = "Vector3i", }, { Name = "X", Type = "number", }, }, Returns = { { Type = "number", }, }, Notes = "Returns the coefficient for the line from the specified vector through this vector to reach the specified X coord. The result satisfies the following equation: (this + Result * (Param - this)).x = X. Returns the NO_INTERSECTION constant if there's no intersection.", }, Move = { { Params = { { Name = "x", Type = "number", }, { Name = "y", Type = "number", }, { Name = "z", Type = "number", }, }, Notes = "Moves the vector by the specified amount in each axis direction.", }, { Params = { { Name = "Diff", Type = "Vector3i", }, }, Notes = "Adds the specified vector to this vector. Is slightly better performant than adding with a \"+\" because this doesn't create a new object for the result.", }, }, Normalize = { Notes = "Normalizes this vector (makes it 1 unit long while keeping the direction). Quite useless for integer-only vectors, since the normalized vector will almost always truncate to zero vector. FIXME: Fails for zero vectors.", }, NormalizeCopy = { Returns = { { Type = "Vector3f", }, }, Notes = "Returns a copy of this vector that is normalized (1 unit long while keeping the same direction). Quite useless for integer-only vectors, since the normalized vector will almost always truncate to zero vector. FIXME: Fails for zero vectors.", }, operator_div = { { Params = { { Name = "Divisor", Type = "number", }, }, Returns = { { Type = "Vector3i", }, }, Notes = "Returns a new Vector3i object that has each of its coords divided by the specified number", }, { Params = { { Name = "PerCoordDivisors", Type = "Vector3i", }, }, Returns = { { Type = "Vector3i", }, }, Notes = "Returns a new Vector3i object that has each of its coords divided by the respective coord of the specified vector.", }, }, operator_mul = { { Params = { { Name = "Multiplier", Type = "number", }, }, Returns = { { Type = "Vector3i", }, }, Notes = "Returns a new Vector3i object that has each of its coords multiplied by the specified number", }, { Params = { { Name = "PerCoordMultipliers", Type = "Vector3i", }, }, Returns = { { Type = "Vector3i", }, }, Notes = "Returns a new Vector3i object that has each of its coords multiplied by the respective coord of the specified vector.", }, }, operator_plus = { Params = { { Name = "Addend", Type = "Vector3i", }, }, Returns = { { Type = "Vector3i", }, }, Notes = "Returns a new Vector3f object that holds the vector sum of this vector and the specified vector.", }, operator_sub = { { Params = { { Name = "Subtrahend", Type = "Vector3i", }, }, Returns = { { Type = "Vector3i", }, }, Notes = "Returns a new Vector3i object that holds the vector differrence between this vector and the specified vector.", }, { Returns = { { Type = "Vector3i", }, }, Notes = "Returns a new Vector3i that is a negative of this vector (all coords multiplied by -1).", }, }, Set = { Params = { { Name = "x", Type = "number", }, { Name = "y", Type = "number", }, { Name = "z", Type = "number", }, }, Notes = "Sets all the coords of the vector at once", }, SqrLength = { Returns = { { Type = "number", }, }, Notes = "Returns the (euclidean) length of this vector, squared. This operation is slightly less computationally expensive than Length(), while it conserves some properties of Length(), such as comparison.", }, TurnCCW = { Notes = "Rotates the vector 90 degrees counterclockwise around the vertical axis. Note that this is specific to minecraft's axis ordering, which is X+ left, Z+ down.", }, TurnCW = { Notes = "Rotates the vector 90 degrees clockwise around the vertical axis. Note that this is specific to minecraft's axis ordering, which is X+ left, Z+ down.", }, }, Constants = { EPS = { Notes = "The max difference between two coords for which the coords are assumed equal (in LineCoeffToXYPlane() et al). Quite useless with integer-only vector.", }, NO_INTERSECTION = { Notes = "Special return value for the LineCoeffToXYPlane() et al meaning that there's no intersection with the plane.", }, }, Variables = { x = { Type = "number", Notes = "The X coord of the vector.", }, y = { Type = "number", Notes = "The Y coord of the vector.", }, z = { Type = "number", Notes = "The Z coord of the vector.", }, }, }, } ================================================ FILE: Server/Plugins/APIDump/Classes/Network.lua ================================================ -- Network.lua -- Defines the documentation for the cNetwork-related classes and cUrlClient return { cNetwork = { Desc = [[ This is the namespace for high-level network-related operations. Allows plugins to make TCP connections to the outside world using a callback-based API.

    All functions in this namespace are static, they should be called on the cNetwork class itself:

    local Server = cNetwork:Listen(1024, ListenCallbacks);
    

    ]], Functions = { Connect = { IsStatic = true, Params = { { Name = "Host", Type = "string", }, { Name = "Port", Type = "number", }, { Name = "LinkCallbacks", Type = "table", }, }, Returns = { { Type = "boolean", }, }, Notes = "Begins establishing a (client) TCP connection to the specified host. Uses the LinkCallbacks table to report progress, success, errors and incoming data. Returns false if it fails immediately (bad port value, bad hostname format), true otherwise. Host can be either an IP address or a hostname.", }, CreateUDPEndpoint = { IsStatic = true, Params = { { Name = "Port", Type = "number", }, { Name = "UDPCallbacks", Type = "table", }, }, Returns = { { Type = "cUDPEndpoint", }, }, Notes = "Creates a UDP endpoint that listens for incoming datagrams on the specified port, and can be used to send or broadcast datagrams. Uses the UDPCallbacks to report incoming datagrams or errors. If the endpoint cannot be created, the OnError callback is called with the error details and the returned endpoint will report IsOpen() == false. The plugin needs to store the returned endpoint object for as long as it needs the UDP port open; if the endpoint is garbage-collected by Lua, the socket will be closed and no more incoming data will be reported.
    If the Port is zero, the OS chooses an available UDP port for the endpoint; use {{cUDPEndpoint}}:GetPort() to query the port number in such case.", }, EnumLocalIPAddresses = { IsStatic = true, Returns = { { Type = "table", }, }, Notes = "Returns all local IP addresses for network interfaces currently available on the machine, as an array-table of strings.", }, HostnameToIP = { IsStatic = true, Params = { { Name = "Host", Type = "string", }, { Name = "LookupCallbacks", Type = "table", }, }, Returns = { { Type = "boolean", }, }, Notes = "Begins a DNS lookup to find the IP address(es) for the specified host. Uses the LookupCallbacks table to report progress, success or errors. Returns false if it fails immediately (bad hostname format), true if the lookup started successfully. Host can be either a hostname or an IP address.", }, IPToHostname = { IsStatic = true, Params = { { Name = "Address", Type = "string", }, { Name = "LookupCallbacks", Type = "table", }, }, Returns = { { Type = "boolean", }, }, Notes = "Begins a reverse-DNS lookup to find out the hostname for the specified IP address. Uses the LookupCallbacks table to report progress, success or errors. Returns false if it fails immediately (bad address format), true if the lookup started successfully.", }, Listen = { IsStatic = true, Params = { { Name = "Port", Type = "number", }, { Name = "ListenCallbacks", Type = "table", }, }, Returns = { { Type = "cServerHandle", }, }, Notes = "Starts listening on the specified port. Uses the ListenCallbacks to report incoming connections or errors. Returns a {{cServerHandle}} object representing the server. If the listen operation failed, the OnError callback is called with the error details and the returned server handle will report IsListening() == false. The plugin needs to store the server handle object for as long as it needs the server running, if the server handle is garbage-collected by Lua, the listening socket will be closed and all current connections dropped.", }, }, AdditionalInfo = { { Header = "Using callbacks", Contents = [[ The entire Networking API is callback-based. Whenever an event happens on the network object, a specific plugin-provided function is called. The callbacks are stored in tables which are passed to the API functions, each table contains multiple callbacks for the various situations.

    There are four different callback variants used: LinkCallbacks, LookupCallbacks, ListenCallbacks and UDPCallbacks. Each is used in the situation appropriate by its name - LinkCallbacks are used for handling the traffic on a single network link (plus additionally creation of such link when connecting as a client), LookupCallbacks are used when doing DNS and reverse-DNS lookups, ListenCallbacks are used for handling incoming connections as a server and UDPCallbacks are used for incoming UDP datagrams.

    LinkCallbacks have the following structure:

    local LinkCallbacks =
    {
    	OnConnected = function ({{cTCPLink|a_TCPLink}})
    		-- The specified {{cTCPLink|link}} has succeeded in connecting to the remote server.
    		-- Only called if the link is being connected as a client (using cNetwork:Connect() )
    		-- Not used for incoming server links
    		-- All returned values are ignored
    	end,
    
    	OnError = function ({{cTCPLink|a_TCPLink}}, a_ErrorCode, a_ErrorMsg)
    		-- The specified error has occured on the {{cTCPLink|link}}
    		-- No other callback will be called for this link from now on
    		-- For a client link being connected, this reports a connection error (destination unreachable etc.)
    		-- It is an Undefined Behavior to send data to a_TCPLink in or after this callback
    		-- All returned values are ignored
    	end,
    
    	OnReceivedData = function ({{cTCPLink|a_TCPLink}}, a_Data)
    		-- Data has been received on the {{cTCPLink|link}}
    		-- Will get called whenever there's new data on the {{cTCPLink|link}}
    		-- a_Data contains the raw received data, as a string
    		-- All returned values are ignored
    	end,
    
    	OnRemoteClosed = function ({{cTCPLink|a_TCPLink}})
    		-- The remote peer has closed the {{cTCPLink|link}}
    		-- The link is already closed, any data sent to it now will be lost
    		-- No other callback will be called for this link from now on
    		-- All returned values are ignored
    	end,
    }
    

    LookupCallbacks have the following structure:

    local LookupCallbacks =
    {
    	OnError = function (a_Query, a_ErrorCode, a_ErrorMsg)
    		-- The specified error has occured while doing the lookup
    		-- a_Query is the hostname or IP being looked up
    		-- No other callback will be called for this lookup from now on
    		-- All returned values are ignored
    	end,
    
    	OnFinished = function (a_Query)
    		-- There are no more DNS records for this query
    		-- a_Query is the hostname or IP being looked up
    		-- No other callback will be called for this lookup from now on
    		-- All returned values are ignored
    	end,
    
    	OnNameResolved = function (a_Hostname, a_IP)
    		-- A DNS record has been found, the specified hostname resolves to the IP
    		-- Called for both Hostname -> IP and IP -> Hostname lookups
    		-- May be called multiple times if a hostname resolves to multiple IPs
    		-- All returned values are ignored
    	end,
    }
    

    ListenCallbacks have the following structure:

    local ListenCallbacks =
    {
    	OnAccepted = function ({{cTCPLink|a_TCPLink}})
    		-- A new connection has been accepted and a {{cTCPLink|Link}} for it created
    		-- It is safe to send data to the link now
    		-- All returned values are ignored
    	end,
    
    	OnError = function (a_ErrorCode, a_ErrorMsg)
    		-- The specified error has occured while trying to listen
    		-- No other callback will be called for this server handle from now on
    		-- This callback is called before the cNetwork:Listen() call returns
    		-- All returned values are ignored
    	end,
    
    	OnIncomingConnection = function (a_RemoteIP, a_RemotePort, a_LocalPort)
    		-- A new connection is being accepted, from the specified remote peer
    		-- This function needs to return either nil to drop the connection,
    		-- or valid LinkCallbacks to use for the new connection's {{cTCPLink|TCPLink}} object
    		return SomeLinkCallbacks
    	end,
    }
    

    UDPCallbacks have the following structure:

    local UDPCallbacks =
    {
    	OnError = function (a_ErrorCode, a_ErrorMsg)
    		-- The specified error has occured when trying to listen for incoming UDP datagrams
    		-- No other callback will be called for this endpoint from now on
    		-- This callback is called before the cNetwork:CreateUDPEndpoint() call returns
    		-- All returned values are ignored
    	end,
    
    	OnReceivedData = function ({{cUDPEndpoint|a_UDPEndpoint}}, a_Data, a_RemotePeer, a_RemotePort)
    		-- A datagram has been received on the {{cUDPEndpoint|endpoint}} from the specified remote peer
    		-- a_Data contains the raw received data, as a string
    		-- All returned values are ignored
    	end,
    }
    
    ]], }, { Header = "Example client connection", Contents = [[ The following example, adapted from the NetworkTest plugin, shows a simple example of a client connection using the cNetwork API. It connects to www.google.com on port 80 (http) and sends a http request for the front page. It dumps the received data to the console.

    First, the callbacks are defined in a table. The OnConnected() callback takes care of sending the http request once the socket is connected. The OnReceivedData() callback sends all data to the console. The OnError() callback logs any errors. Then, the connection is initiated using the cNetwork::Connect() API function.

    -- Define the callbacks to use for the client connection:
    local ConnectCallbacks =
    {
    	OnConnected = function (a_Link)
    		-- Connection succeeded, send the http request:
    		a_Link:Send("GET / HTTP/1.0\r\nHost: www.google.com\r\n\r\n")
    	end,
    
    	OnError = function (a_Link, a_ErrorCode, a_ErrorMsg)
    		-- Log the error to console:
    		LOG("An error has occurred while talking to google.com: " .. a_ErrorCode .. " (" .. a_ErrorMsg .. ")")
    	end,
    
    	OnReceivedData = function (a_Link, a_Data)
    		-- Log the received data to console:
    		LOG("Incoming http data:\r\n" .. a_Data)
    	end,
    
    	OnRemoteClosed = function (a_Link)
    		-- Log the event into the console:
    		LOG("Connection to www.google.com closed")
    	end,
    }
    
    -- Connect:
    if not(cNetwork:Connect("www.google.com", 80, ConnectCallbacks)) then
    	-- Highly unlikely, but better check for errors
    	LOG("Cannot queue connection to www.google.com")
    end
    -- Note that the connection is being made on the background,
    -- there's no guarantee that it's already connected at this point in code
    
    ]], }, { Header = "Example server implementation", Contents = [[ The following example, adapted from the NetworkTest plugin, shows a simple example of creating a server listening on a TCP port using the cNetwork API. The server listens on port 9876 and for each incoming connection it sends a welcome message and then echoes back whatever the client has sent ("echo server").

    First, the callbacks for the listening server are defined. The most important of those is the OnIncomingConnection() callback that must return the LinkCallbacks that will be used for the new connection. In our simple scenario each connection uses the same callbacks, so a predefined callbacks table is returned; it is, however, possible to define different callbacks for each connection. This allows the callbacks to be "personalised", for example by the remote IP or the time of connection. The OnAccepted() and OnError() callbacks only log that they occurred, there's no processing needed for them.

    Finally, the cNetwork:Listen() API function is used to create the listening server. The status of the server is checked and if it is successfully listening, it is stored in a global variable, so that Lua doesn't garbage-collect it until we actually want the server closed.

    -- Define the callbacks used for the incoming connections:
    local EchoLinkCallbacks =
    {
    	OnConnected = function (a_Link)
    		-- This will not be called for a server connection, ever
    		assert(false, "Unexpected Connect callback call")
    	end,
    
    	OnError = function (a_Link, a_ErrorCode, a_ErrorMsg)
    		-- Log the error to console:
    		local RemoteName = "'" .. a_Link:GetRemoteIP() .. ":" .. a_Link:GetRemotePort() .. "'"
    		LOG("An error has occurred while talking to " .. RemoteName .. ": " .. a_ErrorCode .. " (" .. a_ErrorMsg .. ")")
    	end,
    
    	OnReceivedData = function (a_Link, a_Data)
    		-- Send the received data back to the remote peer
    		a_Link:Send(Data)
    	end,
    
    	OnRemoteClosed = function (a_Link)
    		-- Log the event into the console:
    		local RemoteName = "'" .. a_Link:GetRemoteIP() .. ":" .. a_Link:GetRemotePort() .. "'"
    		LOG("Connection to '" .. RemoteName .. "' closed")
    	end,
    }
    
    -- Define the callbacks used by the server:
    local ListenCallbacks =
    {
    	OnAccepted = function (a_Link)
    		-- No processing needed, just log that this happened:
    		LOG("OnAccepted callback called")
    	end,
    
    	OnError = function (a_ErrorCode, a_ErrorMsg)
    		-- An error has occured while listening for incoming connections, log it:
    		LOG("Cannot listen, error " .. a_ErrorCode .. " (" .. a_ErrorMsg .. ")"
    	end,
    
    	OnIncomingConnection = function (a_RemoteIP, a_RemotePort, a_LocalPort)
    		-- A new connection is being accepted, give it the EchoCallbacks
    		return EchoLinkCallbacks
    	end,
    }
    
    -- Start the server:
    local Server = cNetwork:Listen(9876, ListenCallbacks)
    if not(Server:IsListening()) then
    	-- The error has been already printed in the OnError() callbacks
    	-- Just bail out
    	return;
    end
    
    -- Store the server globally, so that it stays open:
    g_Server = Server
    
    ...
    
    -- Elsewhere in the code, when terminating:
    -- Close the server and let it be garbage-collected:
    g_Server:Close()
    g_Server = nil
    
    ]], }, }, }, cServerHandle = { Desc = [[ This class provides an interface for TCP sockets listening for a connection. In order to listen, the plugin needs to use the {{cNetwork}}:Listen() function to create the listening socket.

    Note that when Lua garbage-collects this class, the listening socket is closed. Therefore the plugin should keep it referenced in a global variable for as long as it wants the server running. ]], Functions = { Close = { Notes = "Closes the listening socket. No more connections will be accepted, and all current connections will be closed.", }, IsListening = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the socket is listening.", }, }, }, cTCPLink = { Desc = [[ This class wraps a single TCP connection, that has been established. Plugins can create these by calling {{cNetwork}}:Connect() to connect to a remote server, or by listening using {{cNetwork}}:Listen() and accepting incoming connections. The links are callback-based - when an event such as incoming data or remote disconnect happens on the link, a specific callback is called. See the additional information in {{cNetwork}} documentation for details.

    The link can also optionally perform TLS encryption. Plugins can use the StartTLSClient() function to start the TLS handshake as the client side. Since that call, the OnReceivedData() callback is overridden internally so that the data is first routed through the TLS decryptor, and the plugin's callback is only called for the decrypted data, once it starts arriving. The Send function changes its behavior so that the data written by the plugin is first encrypted and only then sent over the network. Note that calling Send() before the TLS handshake finishes is supported, but the data is queued internally and only sent once the TLS handshake is completed. ]], Functions = { Close = { Notes = "Closes the link forcefully (TCP RST). There's no guarantee that the last sent data is even being delivered. See also the Shutdown() method.", }, GetLocalIP = { Returns = { { Type = "string", }, }, Notes = "Returns the IP address of the local endpoint of the TCP connection.", }, GetLocalPort = { Returns = { { Type = "number", }, }, Notes = "Returns the port of the local endpoint of the TCP connection.", }, GetRemoteIP = { Returns = { { Type = "string", }, }, Notes = "Returns the IP address of the remote endpoint of the TCP connection.", }, GetRemotePort = { Returns = { { Type = "number", }, }, Notes = "Returns the port of the remote endpoint of the TCP connection.", }, Send = { Params = { { Name = "Data", Type = "string", }, }, Notes = "Sends the data (raw string) to the remote peer. The data is sent asynchronously and there is no report on the success of the send operation, other than the connection being closed or reset by the underlying OS.", }, Shutdown = { Notes = "Shuts the socket down for sending data. Notifies the remote peer that there will be no more data coming from us (TCP FIN). The data that is in flight will still be delivered. The underlying socket will be closed when the remote end shuts down as well, or after a timeout.", }, StartTLSClient = { Params = { { Name = "OwnCert", Type = "string", }, { Name = "OwnPrivateKey", Type = "string", }, { Name = "OwnPrivateKeyPassword", Type = "string", }, { Name = "TrustedRootCAs", Type = "string", }, }, Returns = { { Name = "IsSuccess", Type = "boolean", }, { Name = "ErrorMessage", Type = "string", IsOptional = true, }, }, Notes = "Starts a TLS handshake on the link, as a client side of the TLS. The Own___ parameters specify the client certificate and its corresponding private key and password; all three parameters are optional and no client certificate is presented to the remote peer if they are not used or all empty. Once the TLS handshake is started by this call, all incoming data is first decrypted before being sent to the OnReceivedData callback, and all outgoing data is queued until the TLS handshake completes, and then sent encrypted over the link. Returns true on success, nil and optional error message on immediate failure.
    The TrustedRootCAs is a string containing all certificates that should be trusted, in PEM format, concatenated and separated by a newline.NOTE: If TrustedRootCAs is empty or nil, the server's certificate will NOT be verified, which is UNSAFE!", }, StartTLSServer = { Params = { { Name = "Certificate", Type = "string", }, { Name = "PrivateKey", Type = "string", }, { Name = "PrivateKeyPassword", Type = "string", }, { Name = "StartTLSData", Type = "string", }, }, Returns = { { Name = "IsSuccess", Type = "boolean", }, { Name = "ErrorMessage", Type = "string", IsOptional = true, }, }, Notes = "Starts a TLS handshake on the link, as a server side of the TLS. The plugin needs to specify the server certificate and its corresponding private key and password. The StartTLSData can contain data that the link has already reported as received but it should be used as part of the TLS handshake. Once the TLS handshake is started by this call, all incoming data is first decrypted before being sent to the OnReceivedData callback, and all outgoing data is queued until the TLS handshake completes, and then sent encrypted over the link. Returns true on success, nil and optional error message on immediate failure.
    NOTE: The TLS support in the API is currently experimental and shouldn't be considered safe - there's no peer certificate verification and the error reporting is only basic.", }, }, }, cUDPEndpoint = { Desc = [[ Represents a UDP socket that is listening for incoming datagrams on a UDP port and can send or broadcast datagrams to other peers on the network. Plugins can create an instance of the endpoint by calling {{cNetwork}}:CreateUDPEndpoint(). The endpoints are callback-based - when a datagram is read from the network, the OnRececeivedData() callback is called with details about the datagram. See the additional information in {{cNetwork}} documentation for details.

    Note that when Lua garbage-collects this class, the listening socket is closed. Therefore the plugin should keep this object referenced in a global variable for as long as it wants the endpoint open. ]], Functions = { Close = { Notes = "Closes the UDP endpoint. No more datagrams will be reported through the callbacks, the UDP port will be closed.", }, EnableBroadcasts = { Notes = "Some OSes need this call before they allow UDP broadcasts on an endpoint.", }, GetPort = { Returns = { { Type = "number", }, }, Notes = "Returns the local port number of the UDP endpoint listening for incoming datagrams. Especially useful if the UDP endpoint was created with auto-assign port (0).", }, IsOpen = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the UDP endpoint is listening for incoming datagrams.", }, Send = { Params = { { Name = "RawData", Type = "string", }, { Name = "RemoteHost", Type = "string", }, { Name = "RemotePort", Type = "number", }, }, Returns = { { Type = "boolean", }, }, Notes = "Sends the specified raw data (string) to the specified remote host. The RemoteHost can be either a hostname or an IP address; if it is a hostname, the endpoint will queue a DNS lookup first, if it is an IP address, the send operation is executed immediately. Returns true if there was no immediate error, false on any failure. Note that the return value needn't represent whether the packet was actually sent, only if it was successfully queued.", }, }, }, cUrlClient = { Desc = [[ Implements high-level asynchronous access to URLs, such as downloading webpages over HTTP(S).

    Note that unlike other languages' URL access libraries, this class implements asynchronous requests. This means that the functions only start a request and return immediately. The request is then fulfilled in the background, while the server continues to run. The response is delivered back to the plugin using callbacks. This allows the plugin to start requests and not block the server until the response is received.

    The functions that make network requests are all static and have a dual interface. Either you can use a single callback function, which gets called once the entire response is received or an error is encountered. Or you can use a table of callback functions, each function being called whenever the specific event happens during the request and response lifetime. See the Simple Callback and Callback Table chapters later on this page for details and examples.

    All the request function also support optional parameters for further customization of the request - the Headers parameter specifies additional HTTP headers that are to be sent (as a dictionary-table of key -> value), the RequestBody parameter specifying the optional body of the request (used mainly for POST and PUT requests), and an Options parameter specifying additional options specific to the protocol used. ]], Functions = { Delete = { { IsStatic = true, Params = { { Name = "URL", Type = "string", }, { Name = "Callbacks", Type = "table", }, { Name = "Headers", Type = "table", IsOptional = true, }, { Name = "RequestBody", Type = "string", IsOptional = true, }, { Name = "Options", Type = "table", IsOptional = true, }, }, Returns = { { Name = "IsSuccess", Type = "boolean", }, { Name = "ErrorMessagge", Type = "string", IsOptional = true, }, }, Notes = "Starts a HTTP DELETE request. Alias for Request(\"DELETE\", ...). Returns true on succes, false and error message on immediate failure (unparsable URL etc.).", }, { IsStatic = true, Params = { { Name = "URL", Type = "string", }, { Name = "Callbacks", Type = "function", }, }, Returns = { { Name = "IsSuccess", Type = "boolean", }, { Name = "ErrorMessagge", Type = "string", IsOptional = true, }, }, Notes = "Starts a HTTP DELETE request. Alias for Request(\"DELETE\", ...). Returns true on succes, false and error message on immediate failure (unparsable URL etc.).", }, }, Get = { { IsStatic = true, Params = { { Name = "URL", Type = "string", }, { Name = "Callbacks", Type = "table", }, { Name = "Headers", Type = "table", IsOptional = true, }, { Name = "RequestBody", Type = "string", IsOptional = true, }, { Name = "Options", Type = "table", IsOptional = true, }, }, Returns = { { Name = "IsSuccess", Type = "boolean", }, { Name = "ErrMsg", Type = "string", IsOptional = true, }, }, Notes = "Starts a HTTP GET request. Alias for Request(\"GET\", ...). Returns true on succes, false and error message on immediate failure (unparsable URL etc.).", }, { IsStatic = true, Params = { { Name = "URL", Type = "string", }, { Name = "Callbacks", Type = "function", }, }, Returns = { { Name = "IsSuccess", Type = "boolean", }, { Name = "ErrMsg", Type = "string", IsOptional = true, }, }, Notes = "Starts a HTTP GET request. Alias for Request(\"GET\", ...). Returns true on succes, false and error message on immediate failure (unparsable URL etc.).", } }, Post = { { IsStatic = true, Params = { { Name = "URL", Type = "string", }, { Name = "Callbacks", Type = "table", }, { Name = "Headers", Type = "table", IsOptional = true, }, { Name = "RequestBody", Type = "string", IsOptional = true, }, { Name = "Options", Type = "table", IsOptional = true, }, }, Returns = { { Name = "IsSuccess", Type = "boolean", }, { Name = "ErrMsg", Type = "string", IsOptional = true, }, }, Notes = "Starts a HTTP POST request. Alias for Request(\"POST\", ...). Returns true on succes, false and error message on immediate failure (unparsable URL etc.).", }, { IsStatic = true, Params = { { Name = "URL", Type = "string", }, { Name = "Callbacks", Type = "function", }, }, Returns = { { Name = "IsSuccess", Type = "boolean", }, { Name = "ErrMsg", Type = "string", IsOptional = true, }, }, Notes = "Starts a HTTP POST request. Alias for Request(\"POST\", ...). Returns true on succes, false and error message on immediate failure (unparsable URL etc.).", }, }, Put = { { IsStatic = true, Params = { { Name = "URL", Type = "string", }, { Name = "Callbacks", Type = "table", }, { Name = "Headers", Type = "table", IsOptional = true, }, { Name = "RequestBody", Type = "string", IsOptional = true, }, { Name = "Options", Type = "table", IsOptional = true, }, }, Returns = { { Name = "IsSuccess", Type = "boolean", }, { Name = "ErrMsg", Type = "string", IsOptional = true, }, }, Notes = "Starts a HTTP PUT request. Alias for Request(\"PUT\", ...). Returns true on succes, false and error message on immediate failure (unparsable URL etc.).", }, { IsStatic = true, Params = { { Name = "URL", Type = "string", }, { Name = "Callbacks", Type = "function", }, }, Returns = { { Name = "IsSuccess", Type = "boolean", }, { Name = "ErrMsg", Type = "string", IsOptional = true, }, }, Notes = "Starts a HTTP PUT request. Alias for Request(\"PUT\", ...). Returns true on succes, false and error message on immediate failure (unparsable URL etc.).", }, }, Request = { IsStatic = true, Params = { { Name = "Method", Type = "string", }, { Name = "URL", Type = "string", }, { Name = "Callbacks", Type = "table", }, { Name = "Headers", Type = "table", IsOptional = true, }, { Name = "RequestBody", Type = "string", IsOptional = true, }, { Name = "Options", Type = "table", IsOptional = true, }, }, Returns = { { Name = "IsSuccess", Type = "boolean", }, { Name = "ErrMsg", Type = "string", IsOptional = true, }, }, Notes = "Starts a request with the specified Method. Returns true on succes, false and error message on immediate failure (unparsable URL etc.).", }, }, AdditionalInfo = { { Header = "Simple Callback", Contents = [[ When you don't need fine control for receiving the requests and are interested only in the result, you can use the simple callback approach. Pass a single function as the Callback parameter, the function will get called when the response is fully processed, either with the body of the response, or with an error message:

    cUrlClient:Get(url,
    	function (a_Body, a_Data)
    		if (a_Body) then
    			-- Response received correctly, a_Body contains the entire response body,
    			-- a_Data is a dictionary-table of the response's HTTP headers
    		else
    			-- There was an error, a_Data is the error message string
    		end
    	end
    )
    
    ]], }, { Header = "Callback Table", Contents = [[ To provide complete control over the request and response handling, Cuberite allows plugins to pass a table of callbacks as the Callback parameter. Then the respective functions are called for their respective events during the lifetime of the request and response. This way it is possible to process huge downloads that wouldn't fit into memory otherwise, or display detailed progress.

    Each callback function receives a "self" as its first parameter, this allows the functions to access the Callback table and any of its other members, allowing the use of Lua object idiom for the table. See this forum post for an example.

    The following callback functions are used by Cuberite. Any callback that is not assigned is silently ignored. The table may also contain other functions and other values, those are silently ignored.

    CallbackParamsNotes
    OnConnectedself, {{cTCPLink}}, RemoteIP, RemotePortCalled when the connection to the remote host is established. Note that current implementation doesn't provide the {{cTCPLink}} parameter and passes nil instead.
    OnCertificateReceivedselfCalled for HTTPS URLs when the server's certificate is received. If the callback returns anything else than true, the connection is aborted. Note that the current implementation doesn't provide the certificate because there is no representation for the cert in Lua.
    OnTlsHandshakeCompletedselfCalled for HTTPS URLs when the TLS is established on the connection.
    OnRequestSentselfCalled after the entire request is sent to the server.
    OnStatusLineself, HttpVersion, StatusCode, RestThe initial line of the response has been parsed. HttpVersion is typically "HTTP/1.1", StatusCode is the numerical HTTP status code reported by the server (200 being OK), Rest is the rest of the line, usually a short message in case of an error.
    OnHeaderself, Name, ValueA new HTTP response header line has been received.
    OnHeadersFinishedself, AllHeadersAll HTTP response headers have been parsed. AllHeaders is a dictionary-table containing all the headers received.
    OnBodyDataself, DataA piece of the response body has been received. This callback is called repeatedly until the entire body is reported through its Data parameter.
    OnBodyFinishedselfThe entire response body has been reported by OnBodyData(), the response has finished.
    OnErrorself, ErrorMsgCalled whenever an error is detected. After this call, no other callback will get called.
    OnRedirectingself, NewUrlCalled if the server returned a valid redirection HTTP status code and a Location header, and redirection is allowed by the Options.

    The following example is adapted from the Debuggers plugin's "download" command, it downloads the contents of an URL into a file.

    function HandleConsoleDownload(a_Split)  -- Console command handler
    	-- Read the params from the command:
    	local url = a_Split[2]
    	local fnam = a_Split[3]
    	if (not(url) or not(fnam)) then
    		return true, "Missing parameters. Usage: download  "
    	end
    
    	-- Define the cUrlClient callbacks
    	local callbacks =
    	{
    		OnStatusLine = function (self, a_HttpVersion, a_Status, a_Rest)
    			-- Only open the output file if the server reports a success:
    			if (a_Status ~= 200) then
    				LOG("Cannot download " .. url .. ", HTTP error code " .. a_Status)
    				return
    			end
    			local f, err = io.open(fnam, "wb")
    			if not(f) then
    				LOG("Cannot download " .. url .. ", error opening the file " .. fnam .. ": " .. (err or ""))
    				return
    			end
    			self.m_File = f
    		end,
    
    		OnBodyData = function (self, a_Data)
    			-- If the file has been opened, write the data:
    			if (self.m_File) then
    				self.m_File:write(a_Data)
    			end
    		end,
    
    		OnBodyFinished = function (self)
    			-- If the file has been opened, close it and report success
    			if (self.m_File) then
    				self.m_File:close()
    				LOG("File " .. fnam .. " has been downloaded.")
    			end
    		end,
    	}
    
    	-- Start the URL download:
    	local isSuccess, msg = cUrlClient:Get(url, callbacks)
    	if not(isSuccess) then
    		LOG("Cannot start an URL download: " .. (msg or ""))
    		return true
    	end
    	return true
    end
    
    ]], }, { Header = "Options", Contents = [[ The requests support the following options, specified in the optional Options table parameter:
    Option nameDescription
    MaxRedirectsMaximum number of HTTP redirects that the cUrlClient will follow. If the server still reports a redirect after reaching this many redirects, the cUrlClient reports an error. May be specified as either a number or a string parsable into a number. Default: 30.
    OwnCertThe client certificate to use, if requested by the server. A string containing a PEM- or DER-encoded cert is expected.
    OwnPrivKeyThe private key appropriate for OwnCert. A string containing a PEM- or DER-encoded private key is expected.
    OwnPrivKeyPasswordThe password for OwnPrivKey. If not present or empty, no password is assumed.
    TrustedRootCAsThe certificates of the Root CAs that are to be trusted, encoded in PEM format. Multiple certificates can be used by concatenating the certificates, separating them by newlines. If this option is not present or empty, the request will NOT check the server's certificate, which is UNSAFE!

    Redirection:

    • If a redirect is received, and redirection is allowed by MaxRedirects, the redirection is reported via OnRedirecting() callback and the request is restarted at the redirect URL, without reporting any of the redirect's headers nor body.
    • If a redirect is received and redirection is not allowed (maximum redirection attempts have been reached), the OnRedirecting() callback is called with the redirect URL and then the request terminates with an OnError() callback, without reporting the redirect's headers nor body.
    ]], }, }, }, } ================================================ FILE: Server/Plugins/APIDump/Classes/Plugins.lua ================================================ return { cPlugin = { Desc = "cPlugin describes a Lua plugin. Each plugin has its own cPlugin object.", Functions = { GetDirectory = { Returns = { { Type = "string", }, }, Notes = "OBSOLETE, use GetFolderName() instead!", }, GetFolderName = { Returns = { { Type = "string", }, }, Notes = "Returns the name of the folder where the plugin's files are. (APIDump)", }, GetLoadError = { Returns = { { Type = "string", }, }, Notes = "If the plugin failed to load, returns the error message for the failure.", }, GetLocalDirectory = { Notes = "OBSOLETE, use GetLocalFolder instead.", }, GetLocalFolder = { Returns = { { Type = "string", }, }, Notes = "Returns the path where the plugin's files are. (Plugins/APIDump)", }, GetName = { Returns = { { Type = "string", }, }, Notes = "Returns the name of the plugin.", }, GetStatus = { Returns = { { Name = "PluginStatus", Type = "cPluginManager#ePluginStatus", }, }, Notes = "Returns the status of the plugin (loaded, disabled, unloaded, error, not found)", }, GetVersion = { Returns = { { Type = "number", }, }, Notes = "Returns the version of the plugin.", }, IsLoaded = { Notes = "", Returns = { { Type = "boolean", }, }, }, SetName = { Params = { { Name = "PluginApiName", Type = "string", }, }, Notes = "Sets the API name of the Plugin that is used by {{cPluginManager}}:CallPlugin() to identify the plugin.", }, SetVersion = { Params = { { Name = "PluginApiVersion", Type = "number", }, }, Notes = "Sets the API version of the plugin. Currently unused.", }, }, }, -- cPlugin cPluginLua = { Desc = "(OBSOLETE) This class is no longer useful in the API and will be removed as soon as all core plugins are migrated away from it. The {{cPlugin}} class serves as the main plugin instance's interface.", Functions = { AddWebTab = { Params = { { Name = "Title", Type = "string", }, { Name = "HandlerFn", Type = "function", }, }, Notes = "OBSOLETE - Use {{cWebAdmin}}:AddWebTab() instead.", }, }, Inherits = "cPlugin", }, -- cPluginLua cPluginManager = { Desc = [[ This class is used for generic plugin-related functionality. The plugin manager has a list of all plugins, can enable or disable plugins, manages hooks and in-game console commands.

    Plugins can be identified by either the PluginFolder or PluginName. Note that these two can differ, refer to the forum for detailed discussion.

    There is one instance of cPluginManager in Cuberite, to get it, call either {{cRoot|cRoot}}:Get():GetPluginManager() or cPluginManager:Get() function.

    Note that some functions are "static", that means that they are called using a dot operator instead of the colon operator. For example:

    cPluginManager.AddHook(cPluginManager.HOOK_CHAT, OnChatMessage);
    

    ]], Functions = { AddHook = { { IsStatic = true, Params = { { Name = "HookType", Type = "cPluginManager#PluginHook", }, { Name = "Callback", Type = "function", IsOptional = true, }, }, Notes = "Informs the plugin manager that it should call the specified function when the specified hook event occurs. If a function is not specified, a default global function name is looked up, based on the hook type", }, }, BindCommand = { { Params = { { Name = "Command", Type = "string", }, { Name = "Permission", Type = "string", }, { Name = "Callback", Type = "function", }, { Name = "HelpString", Type = "string", }, }, Returns = { { Type = "boolean", }, }, Notes = "Binds an in-game command with the specified callback function, permission and help string. By common convention, providing an empty string for HelpString will hide the command from the /help display. Returns true if successful, logs to console and returns no value on error. The callback uses the following signature:
    function(Split, {{cPlayer|Player}})
    The Split parameter contains an array-table of the words that the player has sent, Player is the {{cPlayer}} object representing the player who sent the command. If the callback returns true, the command is assumed to have executed successfully; in all other cases the server sends a warning to the player that the command is unknown (this is so that subcommands can be implemented).", }, { IsStatic = true, Params = { { Name = "Command", Type = "string", }, { Name = "Permission", Type = "string", }, { Name = "Callback", Type = "function", }, { Name = "HelpString", Type = "string", }, }, Returns = { { Type = "boolean", }, }, Notes = "Binds an in-game command with the specified callback function, permission and help string. By common convention, providing an empty string for HelpString will hide the command from the /help display. Returns true if successful, logs to console and returns no value on error. The callback uses the following signature:
    function(Split, {{cPlayer|Player}})
    The Split parameter contains an array-table of the words that the player has sent, Player is the {{cPlayer}} object representing the player who sent the command. If the callback returns true, the command is assumed to have executed successfully; in all other cases the server sends a warning to the player that the command is unknown (this is so that subcommands can be implemented).", }, }, BindConsoleCommand = { { IsStatic = true, Params = { { Name = "Command", Type = "string", }, { Name = "Callback", Type = "function", }, { Name = "HelpString", Type = "string", }, }, Returns = { { Type = "boolean", IsOptional = true, }, }, Notes = "Binds a console command with the specified callback function and help string. By common convention, providing an empty string for HelpString will hide the command from the \"help\" console command. Returns true if successful, logs to console and returns no value on error. The callback uses the following signature:
    function(Split)
    The Split parameter contains an array-table of the words that the admin has typed. If the callback returns true, the command is assumed to have executed successfully; in all other cases the server issues a warning to the console that the command is unknown (this is so that subcommands can be implemented).", }, { Params = { { Name = "Command", Type = "string", }, { Name = "Callback", Type = "function", }, { Name = "HelpString", Type = "string", }, }, Returns = { { Type = "boolean", IsOptional = true, }, }, Notes = "Binds a console command with the specified callback function and help string. By common convention, providing an empty string for HelpString will hide the command from the \"help\" console command. Returns true if successful, logs to console and returns no value on error. The callback uses the following signature:
    function(Split)
    The Split parameter contains an array-table of the words that the admin has typed. If the callback returns true, the command is assumed to have executed successfully; in all other cases the server issues a warning to the console that the command is unknown (this is so that subcommands can be implemented).", }, }, CallPlugin = { IsStatic = true, Params = { { Name = "PluginName", Type = "string", }, { Name = "FunctionName", Type = "string", }, { Name = "FunctionArgs...", Type = "...", IsOptional = true, }, }, Returns = { { Name = "FunctionRets", Type = "...", IsOptional = true, }, }, Notes = "Calls the specified function in the specified plugin, passing all the given arguments to it. If it succeeds, it returns all the values returned by that function. If it fails, returns no value at all. Note that only strings, numbers, bools, nils, API classes and simple tables can be used for parameters and return values; functions cannot be copied across plugins.", }, DoWithPlugin = { IsStatic = true, Params = { { Name = "PluginName", Type = "string", }, { Name = "CallbackFn", Type = "function", }, }, Returns = { { Type = "boolean", }, }, Notes = "Calls the CallbackFn for the specified plugin, if found. A plugin can be found even if it is currently unloaded, disabled or errored, the callback should check the plugin status. If the plugin is not found, this function returns false, otherwise it returns the bool value that the callback has returned. The CallbackFn has the following signature:
    function ({{cPlugin|Plugin}})
    ", }, ExecuteCommand = { Params = { { Name = "Player", Type = "cPlayer", }, { Name = "CommandStr", Type = "string", }, }, Returns = { { Name = "CommandResult", Type = "cPluginManager#CommandResult", }, }, Notes = "Executes the command as if given by the specified Player. Checks permissions.", }, ExecuteConsoleCommand = { Params = { { Name = "CommandStr", Type = "string", }, }, Returns = { { Type = "boolean", }, { Type = "string", }, }, Notes = "Executes the console command as if given by the admin on the console. If the command is successfully executed, returns true and the text that would be output to the console normally. On error it returns false and an error message.", }, FindPlugins = { Notes = "OBSOLETE, use RefreshPluginList() instead", }, ForceExecuteCommand = { Params = { { Name = "Player", Type = "cPlayer", }, { Name = "CommandStr", Type = "string", }, }, Returns = { { Name = "CommandResult", Type = "cPluginManager#CommandResult", }, }, Notes = "Same as ExecuteCommand, but doesn't check permissions", }, ForEachCommand = { Params = { { Name = "CallbackFn", Type = "function", }, }, Returns = { { Type = "boolean", }, }, Notes = "Calls the CallbackFn function for each command that has been bound using BindCommand(). The CallbackFn has the following signature:
    function(Command, Permission, HelpString)
    If the callback returns true, the enumeration is aborted and this API function returns false; if it returns false or no value, the enumeration continues with the next command, and the API function returns true.", }, ForEachConsoleCommand = { Params = { { Name = "CallbackFn", Type = "function", }, }, Returns = { { Type = "boolean", }, }, Notes = "Calls the CallbackFn function for each command that has been bound using BindConsoleCommand(). The CallbackFn has the following signature:
    function (Command, HelpString)
    If the callback returns true, the enumeration is aborted and this API function returns false; if it returns false or no value, the enumeration continues with the next command, and the API function returns true.", }, ForEachPlugin = { { IsStatic = true, Params = { { Name = "CallbackFn", Type = "function", }, }, Returns = { { Type = "boolean", }, }, Notes = "Calls the CallbackFn function for each plugin that is currently discovered by Cuberite (including disabled, unloaded and errrored plugins). The CallbackFn has the following signature:
    function ({{cPlugin|Plugin}})
    If the callback returns true, the enumeration is aborted and this API function returns false; if it returns false or no value, the enumeration continues with the next command, and the API function returns true.", }, { Params = { { Name = "CallbackFn", Type = "function", }, }, Returns = { { Type = "boolean", }, }, Notes = "Calls the CallbackFn function for each plugin that is currently discovered by Cuberite (including disabled, unloaded and errrored plugins). The CallbackFn has the following signature:
    function ({{cPlugin|Plugin}})
    If the callback returns true, the enumeration is aborted and this API function returns false; if it returns false or no value, the enumeration continues with the next command, and the API function returns true.", } }, Get = { IsStatic = true, Returns = { { Type = "cPluginManager", }, }, Notes = "Returns the single instance of the plugin manager", }, GetAllPlugins = { Returns = { { Type = "table", }, }, Notes = "Returns a table (dictionary) of all plugins, [name => value], where value is a valid {{cPlugin}} if the plugin is loaded, or the bool value false if the plugin is not loaded.", }, GetCommandPermission = { Params = { { Name = "Command", Type = "string", }, }, Returns = { { Name = "Permission", Type = "string", }, }, Notes = "Returns the permission needed for executing the specified command", }, GetCurrentPlugin = { Returns = { { Type = "cPlugin", }, }, Notes = "Returns the {{cPlugin}} object for the calling plugin. This is the same object that the Initialize function receives as the argument.", }, GetNumLoadedPlugins = { Returns = { { Type = "number", }, }, Notes = "Returns the number of loaded plugins (psLoaded only)", }, GetNumPlugins = { Returns = { { Type = "number", }, }, Notes = "Returns the number of plugins, including the disabled, errored, unloaded and not-found ones", }, GetPlugin = { Params = { { Name = "PluginName", Type = "string", }, }, Returns = { { Type = "cPlugin", }, }, Notes = "(DEPRECATED, UNSAFE) Returns a plugin handle of the specified plugin, or nil if such plugin is not loaded. Note thatdue to multithreading the handle is not guaranteed to be safe for use when stored - a single-plugin reload may have been triggered in the mean time for the requested plugin.", }, GetPluginFolderName = { Params = { { Name = "PluginName", Type = "string", }, }, Returns = { { Type = "string", }, }, Notes = "Returns the name of the folder from which the plugin was loaded (without the \"Plugins\" part). Used as a plugin's display name.", }, GetPluginsPath = { IsStatic = true, Returns = { { Type = "string", }, }, Notes = "Returns the path where the individual plugin folders are located. Doesn't include the path separator at the end of the returned string.", }, IsCommandBound = { Params = { { Name = "Command", Type = "string", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if in-game Command is already bound (by any plugin)", }, IsConsoleCommandBound = { Params = { { Name = "Command", Type = "string", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if console Command is already bound (by any plugin)", }, IsPluginLoaded = { Params = { { Name = "PluginName", Type = "string", }, }, Notes = "Returns true if the specified plugin is loaded.", }, LoadPlugin = { Params = { { Name = "PluginFolder", Type = "string", }, }, Notes = "(DEPRECATED) Loads a plugin from the specified folder. NOTE: Loading plugins may be an unsafe operation and may result in a deadlock or a crash. This API is deprecated and might be removed.", }, LogStackTrace = { IsStatic = true, Notes = "Logs a current stack trace of the Lua engine to the server console log. Same format as is used when the plugin fails.", }, RefreshPluginList = { Notes = "Refreshes the list of plugins to include all folders inside the Plugins folder (potentially new disabled plugins)", }, ReloadPlugins = { Notes = "Reloads all active plugins", }, UnloadPlugin = { Params = { { Name = "PluginName", Type = "string", }, }, Notes = "Queues the specified plugin to be unloaded. To avoid deadlocks, the unloading happens in the main tick thread asynchronously.", }, ReloadPlugin = { Params = { { Name = "PluginName", Type = "string", }, }, Notes = "Queues the specified plugin to be reloaded. To avoid deadlocks, the reloading happens in the main tick thread asynchronously.", } }, Constants = { crBlocked = { Notes = "When a plugin stopped the command using the OnExecuteCommand hook", }, crError = { Notes = "When the command handler for the given command results in an error", }, crExecuted = { Notes = "When the command is successfully executed.", }, crNoPermission = { Notes = "When the player doesn't have permission to execute the given command.", }, crUnknownCommand = { Notes = "When the given command doesn't exist.", }, HOOK_BLOCK_SPREAD = { Notes = "Called when a block spreads based on world conditions", }, HOOK_BLOCK_TO_PICKUPS = { Notes = "Called when a block has been dug and is being converted to pickups. The server has provided the default pickups and the plugins may modify them.", }, HOOK_BREWING_COMPLETED = { Notes = "Called when a brewing stand completed a brewing process.", }, HOOK_BREWING_COMPLETING = { Notes = "Called before a brewing stand completes a brewing process.", }, HOOK_CHAT = { Notes = "Called when a client sends a chat message that is not a command. The plugin may modify the chat message", }, HOOK_CHUNK_AVAILABLE = { Notes = "Called when a chunk is loaded or generated and becomes available in the {{cWorld|world}}.", }, HOOK_CHUNK_GENERATED = { Notes = "Called after a chunk is generated. A plugin may do last modifications on the generated chunk before it is handed of to the {{cWorld|world}}.", }, HOOK_CHUNK_GENERATING = { Notes = "Called before a chunk is generated. A plugin may override some parts of the generation algorithm.", }, HOOK_CHUNK_UNLOADED = { Notes = "Called after a chunk has been unloaded from a {{cWorld|world}}.", }, HOOK_CHUNK_UNLOADING = { Notes = "Called before a chunk is unloaded from a {{cWorld|world}}. The chunk has already been saved.", }, HOOK_COLLECTING_PICKUP = { Notes = "Called when a player is about to collect a pickup.", }, HOOK_CRAFTING_NO_RECIPE = { Notes = "Called when a player has items in the crafting slots and the server cannot locate any recipe. Plugin may provide a recipe.", }, HOOK_DISCONNECT = { Notes = "Called after the player has disconnected.", }, HOOK_ENTITY_ADD_EFFECT = { Notes = "Called when an effect is being added to an {{cEntity|entity}}. Plugin may refuse the effect.", }, HOOK_ENTITY_CHANGED_WORLD = { Notes = "Called after a entity has changed the world.", }, HOOK_ENTITY_CHANGING_WORLD = { Notes = "Called before a entity has changed the world. Plugin may disallow a entity to change the world.", }, HOOK_ENTITY_TELEPORT = { Notes = "Called when an {{cEntity|entity}} is being teleported. Plugin may refuse the teleportation.", }, HOOK_EXECUTE_COMMAND = { Notes = "Called when a client sends a chat message that is recognized as a command, before handing that command to the regular command handler. A plugin may stop the command from being handled. This hook is called even when the player doesn't have permissions for the command.", }, HOOK_EXPLODED = { Notes = "Called after an explosion has been processed in a {{cWorld|world}}.", }, HOOK_EXPLODING = { Notes = "Called before an explosion is processed in a {{cWorld|world}}. A plugin may alter the explosion parameters or cancel the explosion altogether.", }, HOOK_HANDSHAKE = { Notes = "Called when a Handshake packet is received from a client.", }, HOOK_HOPPER_PULLING_ITEM = { Notes = "Called when a hopper is pulling an item from the container above it.", }, HOOK_HOPPER_PUSHING_ITEM = { Notes = "Called when a hopper is pushing an item into the container it is aimed at.", }, HOOK_DROPSPENSE = { Notes = "Called when a {{cDropSpenserEntity|DropSpenser}} is dropspensing an {{cItem|item}}.", }, HOOK_KILLED = { Notes = "Called when an entity has been killed.", }, HOOK_KILLING = { Notes = "Called when an entity has just been killed. A plugin may resurrect the entity by setting its health to above zero.", }, HOOK_LOGIN = { Notes = "Called when a Login packet is sent to the client, before the client is queued for authentication.", }, HOOK_LOGIN_FORGE = { Notes = "Called when a Forge client has sent its ModList to the server, during the login handshake.", }, HOOK_PLAYER_ANIMATION = { Notes = "Called when a client send the Animation packet.", }, HOOK_PLAYER_BREAKING_BLOCK = { Notes = "Called when a player is about to break a block. A plugin may cancel the event.", }, HOOK_PLAYER_BROKEN_BLOCK = { Notes = "Called after a player has broken a block.", }, HOOK_PLAYER_CROUCHED = { Notes = "Called when a player crouches.", }, HOOK_PLAYER_DESTROYED = { Notes = "Called when the {{cPlayer}} object is destroyed - a player has disconnected.", }, HOOK_PLAYER_EATING = { Notes = "Called when the player starts eating a held item. Plugins may abort the eating.", }, HOOK_PLAYER_FISHED = { Notes = "Called when the player reels the fishing rod back in, after the server decides the player's fishing reward and the experience to grant.", }, HOOK_PLAYER_FISHING = { Notes = "Called when the player reels the fishing rod back in, plugins may alter the fishing reward and the experience granted to the player.", }, HOOK_PLAYER_FOOD_LEVEL_CHANGE = { Notes = "Called when the player's food level is changing. Plugins may refuse the change.", }, HOOK_PLAYER_JOINED = { Notes = "Called when the player entity has been created. It has not yet been fully initialized.", }, HOOK_PLAYER_LEFT_CLICK = { Notes = "Called when the client sends the LeftClick packet.", }, HOOK_PLAYER_MOVING = { Notes = "Called when the player has moved and the movement is now being applied.", }, HOOK_PLAYER_OPENING_WINDOW = { Notes = "Called when the player is about to open a window. The plugin can return true to cancel the window opening.", }, HOOK_PLAYER_PLACED_BLOCK = { Notes = "Called when the player has just placed a block", }, HOOK_PLAYER_PLACING_BLOCK = { Notes = "Called when the player is about to place a block. A plugin may cancel the event.", }, HOOK_PLAYER_RIGHT_CLICK = { Notes = "Called when the client sends the RightClick packet.", }, HOOK_PLAYER_RIGHT_CLICKING_ENTITY = { Notes = "Called when the client sends the UseEntity packet.", }, HOOK_PLAYER_SHOOTING = { Notes = "Called when the player releases the mouse button to fire their bow.", }, HOOK_PLAYER_SPAWNED = { Notes = "Called after the player entity has been created. The entity is fully initialized and is spawning in the {{cWorld|world}}.", }, HOOK_PLAYER_TOSSING_ITEM = { Notes = "Called when the player is tossing the held item (keypress Q)", }, HOOK_PLAYER_USED_BLOCK = { Notes = "Called after the player has right-clicked a block", }, HOOK_PLAYER_USED_ITEM = { Notes = "Called after the player has right-clicked with a usable item in their hand.", }, HOOK_PLAYER_USING_BLOCK = { Notes = "Called when the player is about to use (right-click) a block", }, HOOK_PLAYER_USING_ITEM = { Notes = "Called when the player is about to right-click with a usable item in their hand.", }, HOOK_PLUGIN_MESSAGE = { Notes = "Called when a PluginMessage packet is received from a client.", }, HOOK_PLUGINS_LOADED = { Notes = "Called after all plugins have loaded.", }, HOOK_POST_CRAFTING = { Notes = "Called after a valid recipe has been chosen for the current contents of the crafting grid. Plugins may modify the recipe.", }, HOOK_PRE_CRAFTING = { Notes = "Called before a recipe is searched for the current contents of the crafting grid. Plugins may provide a recipe and cancel the built-in search.", }, HOOK_PROJECTILE_HIT_BLOCK = { Notes = "Called when a {{cProjectileEntity|projectile}} hits a block.", }, HOOK_PROJECTILE_HIT_ENTITY = { Notes = "Called when a {{cProjectileEntity|projectile}} hits an {{cEntity|entity}}.", }, HOOK_SERVER_PING = { Notes = "Called when a client pings the server from the server list. Plugins may change the favicon, server description, players online and maximum players values.", }, HOOK_SPAWNED_ENTITY = { Notes = "Called after an entity is spawned in a {{cWorld|world}}. The entity is already part of the world.", }, HOOK_SPAWNED_MONSTER = { Notes = "Called after a mob is spawned in a {{cWorld|world}}. The mob is already part of the world.", }, HOOK_SPAWNING_ENTITY = { Notes = "Called just before an entity is spawned in a {{cWorld|world}}.", }, HOOK_SPAWNING_MONSTER = { Notes = "Called just before a mob is spawned in a {{cWorld|world}}.", }, HOOK_TAKE_DAMAGE = { Notes = "Called when an entity is taking any kind of damage. Plugins may modify the damage value, effects, source or cancel the damage.", }, HOOK_TICK = { Notes = "Called when the main server thread ticks - 20 times a second.", }, HOOK_UPDATED_SIGN = { Notes = "Called after a {{cSignEntity|sign}} text has been updated, either by a player or by any external means.", }, HOOK_UPDATING_SIGN = { Notes = "Called before a {{cSignEntity|sign}} text is updated, either by a player or by any external means.", }, HOOK_WEATHER_CHANGED = { Notes = "Called after the weather has changed.", }, HOOK_WEATHER_CHANGING = { Notes = "Called just before the weather changes", }, HOOK_WORLD_STARTED = { Notes = "Called when a world has been started.", }, HOOK_WORLD_TICK = { Notes = "Called in each world's tick thread when the game logic is about to tick (20 times a second).", }, psDisabled = { Notes = "The plugin is not enabled in settings.ini", }, psError = { Notes = "The plugin is enabled in settings.ini, but it has run into an error while loading. Use {{cPlugin}}:GetLoadError() to identify the error.", }, psLoaded = { Notes = "The plugin is enabled and loaded.", }, psNotFound = { Notes = "The plugin has been loaded, but is no longer present on disk.", }, psUnloaded = { Notes = "The plugin is enabled in settings.ini, but it has been unloaded (by a command).", }, }, ConstantGroups = { CommandResult = { Include = { "^cr.*", }, TextBefore = "Results that the (Force)ExecuteCommand functions return. This gives information whether the command was executed or not, and the reason.", }, PluginHook = { Include = { "HOOK_.*", }, TextBefore = [[ These constants identify individual hooks. To register the plugin to receive notifications on hooks, use the cPluginManager:AddHook() function. For detailed description of each hook, see the hooks reference.]], }, ePluginStatus = { Include = { "ps.*", }, TextBefore = [[ These constants are used to report status of individual plugins. Use {{cPlugin}}:GetStatus() to query the status of a plugin; use cPluginManager::ForEachPlugin() to iterate over plugins.]], }, }, }, } ================================================ FILE: Server/Plugins/APIDump/Classes/Projectiles.lua ================================================ return { cArrowEntity = { Desc = [[ Represents the arrow when it is shot from the bow. A subclass of the {{cProjectileEntity}}. ]], Functions = { CanPickup = { Params = { { Name = "Player", Type = "cPlayer", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if the specified player can pick the arrow when it's on the ground", }, GetBlockHit = { Notes = "Returns the coords of the block into which the arrow is stuck. Undefined if the arrow is still moving.", Returns = { { Type = "Vector3i", }, }, }, GetDamageCoeff = { Returns = { { Type = "number", }, }, Notes = "Returns the damage coefficient stored within the arrow. The damage dealt by this arrow is multiplied by this coeff", }, GetPickupState = { Returns = { { Type = "cArrowEntity#ePickupState", }, }, Notes = "Returns the pickup state (one of the psXXX constants, above)", }, IsCritical = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the arrow should deal critical damage. Based on the bow charge when the arrow was shot.", }, SetDamageCoeff = { Params = { { Name = "DamageCoeff", Type = "number", }, }, Notes = "Sets the damage coefficient. The damage dealt by this arrow is multiplied by this coeff", }, SetIsCritical = { Params = { { Name = "IsCritical", Type = "boolean", }, }, Notes = "Sets the IsCritical flag on the arrow. Critical arrow deal additional damage", }, SetPickupState = { Params = { { Name = "PickupState", Type = "cArrowEntity#ePickupState", }, }, Notes = "Sets the pickup state (one of the psXXX constants, above)", }, }, Constants = { psInCreative = { Notes = "The arrow can be picked up only by players in creative gamemode", }, psInSurvivalOrCreative = { Notes = "The arrow can be picked up by players in survival or creative gamemode", }, psNoPickup = { Notes = "The arrow cannot be picked up at all", }, }, ConstantGroups = { ePickupState = { Include = "ps.*", TextBefore = [[ The following constants are used to signalize whether the arrow, once it lands, can be picked by players: ]], }, }, Inherits = "cProjectileEntity", }, cExpBottleEntity = { Desc = [[ Represents a thrown ExpBottle. A subclass of the {{cProjectileEntity}}. ]], Functions = { }, Inherits = "cProjectileEntity", }, cFireChargeEntity = { Desc = [[ Represents a fire charge that has been shot by a Blaze or a {{cDispenserEntity|Dispenser}}. A subclass of the {{cProjectileEntity}}. ]], Functions = { }, Inherits = "cProjectileEntity", }, cFireworkEntity = { Desc = [[ Represents a firework rocket. ]], Functions = { GetItem = { Returns = { { Type = "cItem", }, }, Notes = "Returns the item that has been used to create the firework rocket. The item's m_FireworkItem member contains all the firework-related data.", }, GetTicksToExplosion = { Returns = { { Type = "number", }, }, Notes = "Returns the number of ticks left until the firework explodes.", }, SetItem = { Params = { { Name = "FireworkItem", Type = "cItem", }, }, Notes = "Sets a new item to be used for the firework.", }, SetTicksToExplosion = { Params = { { Name = "NumTicks", Type = "number", }, }, Notes = "Sets the number of ticks left until the firework explodes.", }, }, Inherits = "cProjectileEntity", }, cGhastFireballEntity = { Desc = "", Functions = { }, Inherits = "cProjectileEntity", }, cProjectileEntity = { Desc = "Base class for all projectiles, such as arrows and fireballs.", Functions = { GetCreatorName = { Returns = { { Type = "string", }, }, Notes = "Returns the name of the player that created the projectile. Will be empty for non-player creators", }, GetCreatorUniqueID = { Returns = { { Type = "number", }, }, Notes = "Returns the unique ID of the entity who created this projectile, or {{cEntity#INVALID_ID|cEntity.INVALID_ID}} if the projectile wasn't created by an entity.", }, GetMCAClassName = { Returns = { { Type = "string", }, }, Notes = "Returns the string that identifies the projectile type (class name) in MCA files", }, GetProjectileKind = { Returns = { { Type = "cProjectileEntity#eKind", }, }, Notes = "Returns the kind of this projectile (pkXXX constant)", }, IsInGround = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if this projectile has hit the ground.", }, }, Constants = { pkArrow = { Notes = "The projectile is an {{cArrowEntity|arrow}}", }, pkEgg = { Notes = "The projectile is a {{cThrownEggEntity|thrown egg}}", }, pkEnderPearl = { Notes = "The projectile is a {{cThrownEnderPearlEntity|thrown enderpearl}}", }, pkExpBottle = { Notes = "The projectile is a {{cExpBottleEntity|thrown exp bottle}}", }, pkFireCharge = { Notes = "The projectile is a {{cFireChargeEntity|fire charge}}", }, pkFirework = { Notes = "The projectile is a (flying) {{cFireworkEntity|firework}}", }, pkGhastFireball = { Notes = "The projectile is a {{cGhastFireballEntity|ghast fireball}}", }, pkSnowball = { Notes = "The projectile is a {{cThrownSnowballEntity|thrown snowball}}", }, pkSplashPotion = { Notes = "The projectile is a {{cSplashPotionEntity|thrown splash potion}}", }, pkWitherSkull = { Notes = "The projectile is a {{cWitherSkullEntity|wither skull}}", }, }, ConstantGroups = { eKind = { Include = "pk.*", TextBefore = "The following constants are used to distinguish between the different projectile kinds:", }, }, Inherits = "cEntity", }, cSplashPotionEntity = { Desc = [[ Represents a thrown splash potion. ]], Functions = { GetEntityEffectType = { Returns = { { Type = "cEntityEffect#eType", }, }, Notes = "Returns the effect type of this potion", }, GetItem = { Returns = { { Type = "cItem", }, }, Notes = "Gets the potion item that was thrown.", }, GetPotionColor = { Returns = { { Type = "number", }, }, Notes = "Returns the color index of the particles emitted by this potion", }, SetEntityEffectType = { Params = { { Name = "EntityEffectType", Type = "cEntityEffect#eType", }, }, Notes = "Sets the effect type of this potion", }, SetPotionColor = { Params = { { Name = "PotionColor", Type = "number", }, }, Notes = "Sets the color index of the particles for this potion", }, }, Inherits = "cProjectileEntity", }, cThrownEggEntity = { Desc = [[ Represents a thrown egg. ]], Functions = { }, Inherits = "cProjectileEntity", }, cThrownEnderPearlEntity = { Desc = "Represents a thrown ender pearl.", Functions = { }, Inherits = "cProjectileEntity", }, cThrownSnowballEntity = { Desc = "Represents a thrown snowball.", Functions = { }, Inherits = "cProjectileEntity", }, cWitherSkullEntity = { Desc = "Represents a wither skull being shot.", Functions = { }, Inherits = "cProjectileEntity", }, } ================================================ FILE: Server/Plugins/APIDump/Classes/RankManager.lua ================================================ -- Describes the cRankManager class API return { cRankManager = { Desc = [[ Manages the players' permissions. The players are assigned a single rank, which contains groups of permissions and restrictions. The functions in this class query or modify these.

    All the functions are static, call them using the cRankManager:Function() convention.

    The players are identified by their UUID, to support player renaming.

    The rank also contains specific "mesage visuals" - bits that are used for formatting messages from the players. There's a message prefix, which is put in front of every message the player sends, and the message suffix that is appended to each message. There's also a PlayerNameColorCode, which holds the color that is used for the player's name in the messages.

    Each rank can contain any number of permission groups. These groups allow for an easier setup of the permissions - you can share groups among ranks, so the usual approach is to group similar permissions together and add that group to any rank that should use those permissions.

    Permissions are added to individual groups. Each group can support unlimited permissions. Note that adding a permission to a group will make the permission available to all the ranks that contain that permission group.

    One rank is reserved as the Default rank. All players that don't have an explicit rank assigned to them will behave as if assigned to this rank. The default rank can be changed to any other rank at any time. Note that the default rank cannot be removed from the RankManager - RemoveRank() will change the default rank to the replacement rank, if specified, and fail if no replacement rank is specified. Renaming the default rank using RenameRank() will change the default rank to the new name. ]], Functions = { AddGroup = { IsStatic = true, Params = { { Name = "GroupName", Type = "string", }, }, Notes = "Adds the group of the specified name. Logs a warning and does nothing if the group already exists.", }, AddGroupToRank = { IsStatic = true, Params = { { Name = "GroupName", Type = "string", }, { Name = "RankName", Type = "string", }, }, Returns = { { Type = "boolean", }, }, Notes = "Adds the specified group to the specified rank. Returns true on success, false on failure - if the group name or the rank name is not found.", }, AddPermissionToGroup = { IsStatic = true, Params = { { Name = "Permission", Type = "string", }, { Name = "GroupName", Type = "string", }, }, Returns = { { Type = "boolean", }, }, Notes = "Adds the specified permission to the specified group. Returns true on success, false on failure - if the group name is not found.", }, AddRank = { IsStatic = true, Params = { { Name = "RankName", Type = "string", }, { Name = "MsgPrefix", Type = "string", }, { Name = "MsgSuffix", Type = "string", }, { Name = "MsgNameColorCode", Type = "string", }, }, Notes = "Adds a new rank of the specified name and with the specified message visuals. Logs an info message and does nothing if the rank already exists.", }, AddRestrictionToGroup = { IsStatic = true, Params = { { Name = "Permission", Type = "string", }, { Name = "GroupName", Type = "string", }, }, Returns = { { Type = "boolean" }, }, Notes = "Adds a new restriction to the specified group. Returns true if successful, false if it fails (no such group). No action if the group already has the restriction.", }, ClearPlayerRanks = { IsStatic = true, Notes = "Removes all player ranks from the database. Note that this doesn't change the cPlayer instances for the already connected players, you need to update all the instances manually.", }, GetAllGroups = { IsStatic = true, Returns = { { Type = "table", }, }, Notes = "Returns an array-table containing the names of all the groups that are known to the manager.", }, GetAllPermissions = { IsStatic = true, Returns = { { Type = "table", }, }, Notes = "Returns an array-table containing all the permissions that are known to the manager.", }, GetAllPermissionsRestrictions = { IsStatic = true, Returns = { { Type = "table", }, }, Notes = "Returns an array-table containing all the permissions and restrictions (intermixed together) that are known to the manager.", }, GetAllPlayerUUIDs = { IsStatic = true, Returns = { { Type = "table", }, }, Notes = "Returns the short uuids of all players stored in the rank DB, sorted by the players' names (case insensitive).", }, GetAllRanks = { IsStatic = true, Returns = { { Type = "table", }, }, Notes = "Returns an array-table containing the names of all the ranks that are known to the manager.", }, GetAllRestrictions = { IsStatic = true, Returns = { { Type = "table", }, }, Notes = "Returns an array-table containing all the restrictions that are known to the manager.", }, GetDefaultRank = { IsStatic = true, Returns = { { Type = "string", }, }, Notes = "Returns the name of the default rank. ", }, GetGroupPermissions = { IsStatic = true, Params = { { Name = "GroupName", Type = "string", }, }, Returns = { { Type = "table", }, }, Notes = "Returns an array-table containing the permissions that the specified group contains.", }, GetGroupRestrictions = { IsStatic = true, Params = { { Name = "GroupName", Type = "string", }, }, Returns = { { Type = "table", }, }, Notes = "Returns an array-table containing the restrictions that the specified group contains.", }, GetPlayerGroups = { IsStatic = true, Params = { { Name = "PlayerUUID", Type = "cUUID", }, }, Returns = { { Type = "table", }, }, Notes = "Returns an array-table of the names of the groups that are assigned to the specified player through their rank. Returns an empty table if the player is not known or has no rank or groups assigned to them.", }, GetPlayerMsgVisuals = { IsStatic = true, Params = { { Name = "PlayerUUID", Type = "cUUID", }, }, Returns = { { Name = "MsgPrefix", Type = "string", }, { Name = "MsgSuffix", Type = "string", }, { Name = "MsgNameColorCode", Type = "string", }, }, Notes = "Returns the message visuals assigned to the player. If the player is not explicitly assigned a rank, the default rank's visuals are returned. If there is an error, no value is returned at all.", }, GetPlayerName = { IsStatic = true, Params = { { Name = "PlayerUUID", Type = "cUUID", }, }, Returns = { { Name = "PlayerName", Type = "string", }, }, Notes = "Returns the last name that the specified player has, for a player in the ranks database. An empty string is returned if the player isn't in the database.", }, GetPlayerPermissions = { IsStatic = true, Params = { { Name = "PlayerUUID", Type = "cUUID", }, }, Returns = { { Type = "table", }, }, Notes = "Returns an array-table containing all permissions that the specified player is assigned through their rank. Returns the default rank's permissions if the player has no explicit rank assigned to them. Returns an empty array on error.", }, GetPlayerRankName = { IsStatic = true, Params = { { Name = "PlayerUUID", Type = "cUUID", }, }, Returns = { { Name = "RankName", Type = "string", }, }, Notes = "Returns the name of the rank that is assigned to the specified player. An empty string (NOT the default rank) is returned if the player has no rank assigned to them.", }, GetRankGroups = { IsStatic = true, Params = { { Name = "RankName", Type = "string", }, }, Returns = { { Type = "table", }, }, Notes = "Returns an array-table of the names of all the groups that are assigned to the specified rank. Returns an empty table if there is no such rank.", }, GetRankPermissions = { IsStatic = true, Params = { { Name = "RankName", Type = "string", }, }, Returns = { { Type = "table", }, }, Notes = "Returns an array-table of all the permissions that are assigned to the specified rank through its groups. Returns an empty table if there is no such rank.", }, GetRankRestrictions = { IsStatic = true, Params = { { Name = "RankName", Type = "string", }, }, Returns = { { Type = "table", }, }, Notes = "Returns an array-table of all the restrictions that are assigned to the specified rank through its groups. Returns an empty table if there is no such rank.", }, GetRankVisuals = { IsStatic = true, Params = { { Name = "RankName", Type = "string", }, }, Returns = { { Name = "MsgPrefix", Type = "string", }, { Name = "MsgSuffix", Type = "string", }, { Name = "MsgNameColorCode", Type = "string", }, }, Notes = "Returns the message visuals for the specified rank. Returns no value if the specified rank does not exist.", }, GroupExists = { IsStatic = true, Params = { { Name = "GroupName", Type = "string", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true iff the specified group exists.", }, IsGroupInRank = { IsStatic = true, Params = { { Name = "GroupName", Type = "string", }, { Name = "RankName", Type = "string", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true iff the specified group is assigned to the specified rank.", }, IsPermissionInGroup = { IsStatic = true, Params = { { Name = "Permission", Type = "string", }, { Name = "GroupName", Type = "string", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true iff the specified permission is assigned to the specified group.", }, IsPlayerRankSet = { IsStatic = true, Params = { { Name = "PlayerUUID", Type = "cUUID", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true iff the specified player has a rank assigned to them.", }, IsRestrictionInGroup = { IsStatic = true, Params = { { Name = "Restriction", Type = "string", }, { Name = "GroupName", Type = "string", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true iff the specified restriction is assigned to the specified group.", }, RankExists = { IsStatic = true, Params = { { Name = "RankName", Type = "string", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true iff the specified rank exists.", }, RemoveGroup = { IsStatic = true, Params = { { Name = "GroupName", Type = "string", }, }, Notes = "Removes the specified group completely. The group will be removed from all the ranks using it and then erased from the manager. Logs an info message and does nothing if the group doesn't exist.", }, RemoveGroupFromRank = { IsStatic = true, Params = { { Name = "GroupName", Type = "string", }, { Name = "RankName", Type = "string", }, }, Notes = "Removes the specified group from the specified rank. The group will still exist, even if it isn't assigned to any rank. Logs an info message and does nothing if the group or rank doesn't exist.", }, RemovePermissionFromGroup = { IsStatic = true, Params = { { Name = "Permission", Type = "string", }, { Name = "GroupName", Type = "string", }, }, Notes = "Removes the specified permission from the specified group. Logs an info message and does nothing if the group doesn't exist.", }, RemovePlayerRank = { IsStatic = true, Params = { { Name = "PlayerUUID", Type = "cUUID", }, }, Notes = "Removes the player's rank; the player's left without a rank. Note that this doesn't change the {{cPlayer}} instances for the already connected players, you need to update all the instances manually. No action if the player has no rank assigned to them already.", }, RemoveRank = { IsStatic = true, Params = { { Name = "RankName", Type = "string", }, { Name = "ReplacementRankName", Type = "string", IsOptional = true, }, }, Notes = "Removes the specified rank. If ReplacementRankName is given, the players that have RankName will get their rank set to ReplacementRankName. If it isn't given, or is an invalid rank, the players will be removed from the manager, their ranks will be unset completely. Logs an info message and does nothing if the rank is not found.", }, RemoveRestrictionFromGroup = { IsStatic = true, Params = { { Name = "Restriction", Type = "string", }, { Name = "GroupName", Type = "string", }, }, Notes = "Removes the specified restriction from the specified group.", }, RenameGroup = { IsStatic = true, Params = { { Name = "OldName", Type = "string", }, { Name = "NewName", Type = "string", }, }, Notes = "Renames the specified group. Logs an info message and does nothing if the group is not found or the new name is already used.", }, RenameRank = { IsStatic = true, Params = { { Name = "OldName", Type = "string", }, { Name = "NewName", Type = "string", }, }, Notes = "Renames the specified rank. Logs an info message and does nothing if the rank is not found or the new name is already used.", }, SetDefaultRank = { IsStatic = true, Params = { { Name = "RankName", Type = "string", }, }, Returns = { { Type = "boolean", }, }, Notes = "Sets the specified rank as the default rank. Returns true on success, false on failure (rank doesn't exist).", }, SetPlayerRank = { IsStatic = true, Params = { { Name = "PlayerUUID", Type = "cUUID", }, { Name = "PlayerName", Type = "string", }, { Name = "RankName", Type = "string", }, }, Notes = "Updates the rank for the specified player. The player name is provided for reference, the UUID is used for identification. Logs a warning and does nothing if the rank is not found.", }, SetRankVisuals = { IsStatic = true, Params = { { Name = "RankName", Type = "string", }, { Name = "MsgPrefix", Type = "string", }, { Name = "MsgSuffix", Type = "string", }, { Name = "MsgNameColorCode", Type = "string", }, }, Notes = "Updates the rank's message visuals. Logs an info message and does nothing if rank not found.", }, }, }, } ================================================ FILE: Server/Plugins/APIDump/Classes/WebAdmin.lua ================================================ return { cWebAdmin = { Desc = "", Functions = { AddWebTab = { IsStatic = true, Params = { { Name = "Title", Type = "string", }, { Name = "UrlPath", Type = "string", }, { Name = "HandlerFn", Type = "function", }, }, Notes = "Adds a new web tab to webadmin. The tab uses \"Title\" as its display string and is identified in the URL using the UrlPath (https://server.domain.com/webadmin/{PluginName}/{UrlPath}). The HandlerFn is the callback function that is called when the admin accesses the page, it has the following signature:

    function ({{HTTPRequest|a_Request}}, a_UrlPath)
    return Content, ContentType
    end
    URLPath must not contain a '/', the recommendation is to use only 7-bit-clean ASCII character set.", }, GetAllWebTabs = { IsStatic = true, Returns = { { Type = "table", }, }, Notes = "Returns an array-table with each item describing a web tab, for all web tabs registered in the WebAdmin, for all plugins. The returned table has the following format:
    {
    {
    PluginName = \"Plugin's API name\",
    UrlPath = \"UrlPath given to AddWebTab\",
    Title = \"Title given to AddWebTab\",
    },
    ...
    }", }, GetBaseURL = { IsStatic = true, Params = { { Name = "URL", Type = "string", }, }, Returns = { { Type = "string", }, }, Notes = "Returns the string that is the path of the base webadmin (\"../../../webadmin\") relative to the given URL.", }, GetContentTypeFromFileExt = { IsStatic = true, Params = { { Name = "FileExt", Type = "string", }, }, Returns = { { Type = "string", }, }, Notes = "Returns the content-type that should be used for files with the specified extension (without the dot), such as \"text/plain\" for the \"txt\" extension. If the extension is not known, returns an empty string.", }, GetHTMLEscapedString = { IsStatic = true, Params = { { Name = "Input", Type = "string", }, }, Returns = { { Type = "string", }, }, Notes = "Gets the HTML-escaped representation of a requested string. This is useful for user input and game data that is not guaranteed to be escaped already.", }, GetPage = { IsStatic = true, Params = { { Name = "Request", Type = "HTTPRequest", }, }, Returns = { { Type = "table", }, }, Notes = "Returns the (inner HTML) page contents for the specified request. Calls the appropriate WebTab handler registered via AddWebTab() and returns the information from that plugin wrapped in a table with the following structure:
    {
    Content = \"\", -- Content returned by the plugin
    ContentType = \"\", -- Content type returned by the plugin, or \"text/html\" if none returned
    UrlPath = \"\", -- UrlPath decoded from the request
    TabTitle = \"\", -- Title of the tab that handled the request, as given to AddWebTab()
    PluginName = \"\", -- API name of the plugin that handled the request
    PluginFolder = \"\", -- Folder name (= display name) of the plugin that handled the request
    }
    This function is mainly used in the webadmin template file.", }, GetPorts = { Returns = { { Type = "string", }, }, Notes = "Returns a comma-separated list of ports on which the webadmin is configured to listen. Note that this list does include ports that may currently be unavailable (another server was already listening on them prior to launching Cuberite).", }, GetURLEncodedString = { IsStatic = true, ObsoletedBy = "cUrlParser:UrlEncode", Params = { { Name = "Input", Type = "string", }, }, Returns = { { Type = "string", }, }, Notes = "OBSOLETE - use {{cUrlParser}}:UrlEncode() instead.
    Returns the string given to it escaped by URL encoding, which makes the string suitable for transmission in an URL. Invalid characters are turned into \"%xy\" values.", }, Reload = { Notes = "Reloads the webadmin's config - the allowed logins, the template script and the login page. Note that reloading will not change the \"enabled\" state of the server, and it will not update listening ports. Existing WebTabs will be kept registered even after the reload.", }, }, }, HTTPFormData = { Desc = "This class stores data for one form element for a {{HTTPRequest|HTTP request}}.", Variables = { Name = { Type = "string", Notes = "Name of the form element", }, Type = { Type = "string", Notes = "Type of the data (usually empty)", }, Value = { Type = "string", Notes = "Value of the form element. Contains the raw data as sent by the browser.", }, }, }, HTTPRequest = { Desc = [[ This class encapsulates all the data that is sent to the WebAdmin through one HTTP request. Plugins receive this class as a parameter to the function handling the web requests, as registered in the {{cPluginLua}}:AddWebPage(). ]], Constants = { Params = { Notes = "Map-table of parameters given to the request in the URL (?param=value); if a form uses GET method, this is the same as FormData. For each parameter given as \"param=value\", there is an entry in the table with \"param\" as its key and \"value\" as its value.", }, FormData = { Notes = "Array-table of {{HTTPFormData}}, contains the values of individual form elements submitted by the client", }, PostParams = { Notes = "Map-table of data posted through a FORM - either a GET or POST method. Logically the same as FormData, but in a map-table format (for each parameter given as \"param=value\", there is an entry in the table with \"param\" as its key and \"value\" as its value).", }, }, Variables = { Method = { Type = "string", Notes = "The HTTP method used to make the request. Usually GET or POST.", }, Path = { Type = "string", Notes = "The Path part of the URL (excluding the parameters)", }, URL = { Type = "string", Notes = "The entire URL used for the request.", }, Username = { Type = "string", Notes = "Name of the logged-in user.", }, }, }, HTTPTemplateRequest = { Desc = [[ This class is used only in the WebAdmin template script as the parameter to the function that provides the template. ]], Variables = { Request = { Type = "HTTPRequest", Notes = "The request for which the template is being built.", }, }, }, } ================================================ FILE: Server/Plugins/APIDump/Classes/World.lua ================================================ -- Describes the cWorld class API return { cWorld = { Desc = [[ cWorld is the game world. It is the hub of all the information managed by individual classes, providing convenient access to them. Cuberite supports multiple worlds in any combination of world types. You can have two overworlds, three nethers etc. To enumerate all world the server provides, use the {{cRoot}}:ForEachWorld() function.

    The world data is held in individual chunks. Each chunk consists of 16 (x) * 16 (z) * 256 (y) blocks, each block is specified by its block type (8-bit) and block metadata (4-bit). Additionally, each block has two light values calculated - skylight (how much daylight it receives) and blocklight (how much light from light-emissive blocks it receives), both 4-bit.

    Each world runs several separate threads used for various housekeeping purposes, the most important of those is the Tick thread. This thread updates the game logic 20 times per second, and it is the thread where all the gameplay actions are evaluated. Liquid physics, entity interactions, player movement etc., all are applied in this thread.

    Additional threads include the generation thread (generates new chunks as needed, storage thread (saves and loads chunk from the disk), lighting thread (updates block light values) and the chunksender thread (compresses chunks to send to the clients).

    The world provides access to all its {{cPlayer|players}}, {{cEntity|entities}} and {{cBlockEntity|block entities}}. Because of multithreading issues, individual objects cannot be retrieved for indefinite handling, but rather must be modified in callbacks, within which they are guaranteed to stay valid.

    Physics for individual blocks are handled by the simulators. These will fire in each tick for all blocks that have been scheduled for simulator update ("simulator wakeup"). The simulators include liquid physics, falling blocks, fire spreading and extinguishing and redstone.

    Game time is also handled by the world. It provides the time-of-day and the total world age. ]], Functions = { AreCommandBlocksEnabled = { Returns = { { Type = "boolean", }, }, Notes = "Returns whether command blocks are enabled on the (entire) server", }, BroadcastBlockAction = { Params = { { Name = "BlockPos", Type = "Vector3i", }, { Name = "ActionByte1", Type = "number", }, { Name = "ActionByte2", Type = "number", }, { Name = "BlockType", Type = "number", }, { Name = "ExcludeClient", Type = "cClientHandle", IsOptional = true, }, }, Notes = "Broadcasts the BlockAction packet to all clients who have the appropriate chunk loaded (except ExcludeClient). The contents of the packet are specified by the parameters for the call, the blocktype needn't match the actual block that is present in the world data at the specified location.", }, BroadcastBlockAction = { Params = { { Name = "BlockX", Type = "number", }, { Name = "BlockY", Type = "number", }, { Name = "BlockZ", Type = "number", }, { Name = "ActionByte1", Type = "number", }, { Name = "ActionByte2", Type = "number", }, { Name = "BlockType", Type = "number", }, { Name = "ExcludeClient", Type = "cClientHandle", IsOptional = true, }, }, Notes = "Broadcasts the BlockAction packet to all clients who have the appropriate chunk loaded (except ExcludeClient). The contents of the packet are specified by the parameters for the call, the blocktype needn't match the actual block that is present in the world data at the specified location. (DEPRECATED)", }, BroadcastChat = { Params = { { Name = "Message", Type = "string", }, { Name = "ExcludeClient", Type = "cClientHandle", IsOptional = true, }, { Name = "ChatPrefix", Type = "eMessageType", IsOptional = true, }, }, Notes = "Sends the Message to all players in this world, except the optional ExcludeClient. No formatting is done by the server.", }, BroadcastChatDeath = { Params = { { Name = "Message", Type = "string", }, { Name = "ExcludeClient", Type = "cClientHandle", IsOptional = true, }, }, Notes = "Prepends Gray [DEATH] / colours entire text (depending on ShouldUseChatPrefixes()) and broadcasts message. For when a player dies.", }, BroadcastChatFailure = { Params = { { Name = "Message", Type = "string", }, { Name = "ExcludeClient", Type = "cClientHandle", IsOptional = true, }, }, Notes = "Prepends Rose [INFO] / colours entire text (depending on ShouldUseChatPrefixes()) and broadcasts message. For a command that failed to run because of insufficient permissions, etc.", }, BroadcastChatFatal = { Params = { { Name = "Message", Type = "string", }, { Name = "ExcludeClient", Type = "cClientHandle", IsOptional = true, }, }, Notes = "Prepends Red [FATAL] / colours entire text (depending on ShouldUseChatPrefixes()) and broadcasts message. For a plugin that crashed, or similar.", }, BroadcastChatInfo = { Params = { { Name = "Message", Type = "string", }, { Name = "ExcludeClient", Type = "cClientHandle", IsOptional = true, }, }, Notes = "Prepends Yellow [INFO] / colours entire text (depending on ShouldUseChatPrefixes()) and broadcasts message. For informational messages, such as command usage.", }, BroadcastChatSuccess = { Params = { { Name = "Message", Type = "string", }, { Name = "ExcludeClient", Type = "cClientHandle", IsOptional = true, }, }, Notes = "Prepends Green [INFO] / colours entire text (depending on ShouldUseChatPrefixes()) and broadcasts message. For success messages.", }, BroadcastChatWarning = { Params = { { Name = "Message", Type = "string", }, { Name = "ExcludeClient", Type = "cClientHandle", IsOptional = true, }, }, Notes = "Prepends Rose [WARN] / colours entire text (depending on ShouldUseChatPrefixes()) and broadcasts message. For concerning events, such as plugin reload etc.", }, BroadcastEntityAnimation = { Params = { { Name = "TargetEntity", Type = "cEntity", }, { Name = "Animation", Type = "number", }, { Name = "ExcludeClient", Type = "cClientHandle", IsOptional = true, }, }, Notes = "Sends an animation of an entity to all clienthandles (except ExcludeClient if given)", }, BroadcastParticleEffect = { Params = { { Name = "ParticleName", Type = "string", }, { Name = "X", Type = "number", }, { Name = "Y", Type = "number", }, { Name = "Z", Type = "number", }, { Name = "OffsetX", Type = "number", }, { Name = "OffsetY", Type = "number", }, { Name = "OffsetZ", Type = "number", }, { Name = "ParticleData", Type = "number", }, { Name = "ParticleAmount", Type = "number", }, { Name = "ExcludeClient", Type = "cClientHandle", IsOptional = true, }, }, Notes = "Spawns the specified particles to all players in the world exept the optional ExeptClient. A list of available particles by thinkofdeath can be found {{https://gist.github.com/thinkofdeath/5110835|Here}}. OBSOLETE, use the vector-based overload instead", }, BroadcastParticleEffect = { Params = { { Name = "ParticleName", Type = "string", }, { Name = "SourcePos", Type = "Vector3f" }, { Name = "Offset", Type = "Vector3f", }, { Name = "ParticleData", Type = "number", }, { Name = "ParticleAmount", Type = "number", }, { Name = "ExcludeClient", Type = "cClientHandle", IsOptional = true, }, }, Notes = "Spawns the specified particles to all players in the world exept the optional ExeptClient. A list of available particles by thinkofdeath can be found {{https://gist.github.com/thinkofdeath/5110835|Here}}", }, BroadcastPlayerListHeaderFooter = { Params = { { Type = "cCompositeChat", Name = "Header", }, { Type = "cCompositeChat", Name = "Footer", }, }, Desc = "Broadcasts the header and footer of the player list to all players in the world.", }, BroadcastSoundEffect = { Params = { { Name = "SoundName", Type = "string", }, { Name = "Position", Type = "Vector3d", }, { Name = "Volume", Type = "number", }, { Name = "Pitch", Type = "number", }, { Name = "ExcludeClient", Type = "cClientHandle", IsOptional = true, }, }, Notes = "Sends the specified sound effect to all players in this world, except the optional ExceptClient", }, BroadcastSoundEffect = { Params = { { Name = "SoundName", Type = "string", }, { Name = "X", Type = "number", }, { Name = "Y", Type = "number", }, { Name = "Z", Type = "number", }, { Name = "Volume", Type = "number", }, { Name = "Pitch", Type = "number", }, { Name = "ExcludeClient", Type = "cClientHandle", IsOptional = true, }, }, Notes = "Sends the specified sound effect to all players in this world, except the optional ExceptClient (DEPRECATED, use vector-parametered version instead)", }, BroadcastSoundParticleEffect = { Params = { { Name = "EffectID", Type = "number", }, { Name = "X", Type = "number", }, { Name = "Y", Type = "number", }, { Name = "Z", Type = "number", }, { Name = "EffectData", Type = "string", }, { Name = "ExcludeClient", Type = "cClientHandle", IsOptional = true, }, }, Notes = "Sends the specified effect to all players in this world, except the optional ExceptClient. OBSOLETE, use the vector overload instead", }, BroadcastSoundParticleEffect = { Params = { { Name = "EffectID", Type = "number", }, { Name = "SourcePos", Type = "Vector3i" }, { Name = "EffectData", Type = "string", }, { Name = "ExcludeClient", Type = "cClientHandle", IsOptional = true, }, }, Notes = "Sends the specified effect to all players in this world, except the optional ExceptClient", }, CastThunderbolt = { Params = { { Name = "Position", Type = "Vector3d", }, }, Notes = "Creates a thunderbolt at the specified coords", }, CastThunderbolt = { Params = { { Name = "X", Type = "number", }, { Name = "Y", Type = "number", }, { Name = "Z", Type = "number", }, }, Notes = "Creates a thunderbolt at the specified coords (DEPRECATED, use vector-parametered version instead)", }, ChangeWeather = { Notes = "Forces the weather to change in the next game tick. Weather is changed according to the normal rules: wSunny <-> wRain <-> wStorm", }, ChunkStay = { Params = { { Name = "ChunkCoordTable", Type = "table", }, { Name = "OnChunkAvailable", Type = "function", IsOptional = true, }, { Name = "OnAllChunksAvailable", Type = "function", IsOptional = true, }, }, Notes = "Queues the specified chunks to be loaded or generated and calls the specified callbacks once they are loaded. ChunkCoordTable is an arra-table of chunk coords, each coord being a table of 2 numbers: { {Chunk1x, Chunk1z}, {Chunk2x, Chunk2z}, ...}. When any of those chunks are made available (including being available at the start of this call), the OnChunkAvailable() callback is called. When all the chunks are available, the OnAllChunksAvailable() callback is called. The function signatures are:

    function OnChunkAvailable(ChunkX, ChunkZ)\
    function OnAllChunksAvailable()
    All return values from the callbacks are ignored.", }, CreateProjectile = { Params = { { Name = "X", Type = "number", }, { Name = "Y", Type = "number", }, { Name = "Z", Type = "number", }, { Name = "ProjectileKind", Type = "cProjectileEntity#eKind", }, { Name = "Creator", Type = "cEntity", }, { Name = "Originating Item", Type = "cItem", }, { Name = "Speed", Type = "Vector3d", IsOptional = true, }, }, Notes = "Creates a new projectile of the specified kind at the specified coords. The projectile's creator is set to Creator (may be nil). The item that created the projectile entity, commonly the {{cPlayer|player}}'s currently equipped item, is used at present for fireworks to correctly set their entity metadata. It is not used for any other projectile. Optional speed indicates the initial speed for the projectile.", }, DigBlock = { { Params = { { Name = "X", Type = "number", }, { Name = "Y", Type = "number", }, { Name = "Z", Type = "number", }, { Name = "Digger", Type = "cEntity", IsOptional = true, }, }, Returns = { { Type = "boolean", }, }, Notes = "Replaces the specified block with air, without dropping the usual pickups for the block. Wakes up the simulators for the block and its neighbors. The optional Digger parameter specifies the entity who dug the block, usually a player. Returns true on success, or false if the chunk is not loaded or invalid coords. See also DropBlockAsPickups() for the version that drops pickups.", }, { Params = { { Name = "BlockPos", Type = "Vector3i", }, { Name = "Digger", Type = "cEntity", IsOptional = true, }, }, Returns = { { Type = "boolean", }, }, Notes = "Replaces the specified block with air, without dropping the usual pickups for the block. Wakes up the simulators for the block and its neighbors. The optional Digger parameter specifies the entity who dug the block, usually a player. Returns true on success, or false if the chunk is not loaded or invalid coords. See also DropBlockAsPickups() for the version that drops pickups.", }, }, DoExplosionAt = { Params = { { Name = "Force", Type = "number", }, { Name = "X", Type = "number", }, { Name = "Y", Type = "number", }, { Name = "Z", Type = "number", }, { Name = "CanCauseFire", Type = "boolean", }, { Name = "Source", Type = "eExplosionSource", }, { Name = "SourceData", Type = "any", }, }, Notes = "Creates an explosion of the specified relative force in the specified position. If CanCauseFire is set, the explosion will set blocks on fire, too. The Source parameter specifies the source of the explosion, one of the esXXX constants. The SourceData parameter is specific to each source type, usually it provides more info about the source.", }, DoWithBeaconAt = { Params = { { Name = "BlockX", Type = "number", }, { Name = "BlockY", Type = "number", }, { Name = "BlockZ", Type = "number", }, { Name = "CallbackFunction", Type = "function", }, }, Returns = { { Type = "boolean", }, }, Notes = "If there is a beacon at the specified coords, calls the CallbackFunction with the {{cBeaconEntity}} parameter representing the beacon. The CallbackFunction has the following signature:
    function Callback({{cBeaconEntity|BeaconEntity}})
    The function returns false if there is no beacon, or if there is, it returns the bool value that the callback has returned.", }, DoWithBedAt = { Params = { { Name = "BlockX", Type = "number", }, { Name = "BlockY", Type = "number", }, { Name = "BlockZ", Type = "number", }, { Name = "CallbackFunction", Type = "function", }, }, Returns = { { Type = "boolean", }, }, Notes = "If there is a bed at the specified coords, calls the CallbackFunction with the {{cBedEntity}} parameter representing the bed. The CallbackFunction has the following signature:
    function Callback({{cBedEntity|cBedEntity}})
    The function returns false if there is no bed, or if there is, it returns the bool value that the callback has returned.", }, DoWithBlockEntityAt = { Params = { { Name = "BlockX", Type = "number", }, { Name = "BlockY", Type = "number", }, { Name = "BlockZ", Type = "number", }, { Name = "CallbackFunction", Type = "function", }, }, Returns = { { Type = "boolean", }, }, Notes = "If there is a block entity at the specified coords, calls the CallbackFunction with the {{cBlockEntity}} parameter representing the block entity. The CallbackFunction has the following signature:
    function Callback({{cBlockEntity|BlockEntity}})
    The function returns false if there is no block entity, or if there is, it returns the bool value that the callback has returned.", }, DoWithBrewingstandAt = { Params = { { Name = "BlockX", Type = "number", }, { Name = "BlockY", Type = "number", }, { Name = "BlockZ", Type = "number", }, { Name = "CallbackFunction", Type = "function", }, }, Returns = { { Type = "boolean", }, }, Notes = "If there is a brewingstand at the specified coords, calls the CallbackFunction with the {{cBrewingstandEntity}} parameter representing the brewingstand. The CallbackFunction has the following signature:
    function Callback({{cBrewingstandEntity|cBrewingstandEntity}})
    The function returns false if there is no brewingstand, or if there is, it returns the bool value that the callback has returned.", }, DoWithChestAt = { Params = { { Name = "BlockX", Type = "number", }, { Name = "BlockY", Type = "number", }, { Name = "BlockZ", Type = "number", }, { Name = "CallbackFunction", Type = "function", }, }, Returns = { { Type = "boolean", }, }, Notes = "If there is a chest at the specified coords, calls the CallbackFunction with the {{cChestEntity}} parameter representing the chest. The CallbackFunction has the following signature:
    function Callback({{cChestEntity|ChestEntity}})
    The function returns false if there is no chest, or if there is, it returns the bool value that the callback has returned.", }, DoWithCommandBlockAt = { Params = { { Name = "BlockX", Type = "number", }, { Name = "BlockY", Type = "number", }, { Name = "BlockZ", Type = "number", }, { Name = "CallbackFunction", Type = "function", }, }, Returns = { { Type = "boolean", }, }, Notes = "If there is a command block at the specified coords, calls the CallbackFunction with the {{cCommandBlockEntity}} parameter representing the command block. The CallbackFunction has the following signature:
    function Callback({{cCommandBlockEntity|CommandBlockEntity}})
    The function returns false if there is no command block, or if there is, it returns the bool value that the callback has returned.", }, DoWithDispenserAt = { Params = { { Name = "BlockX", Type = "number", }, { Name = "BlockY", Type = "number", }, { Name = "BlockZ", Type = "number", }, { Name = "CallbackFunction", Type = "function", }, }, Returns = { { Type = "boolean", }, }, Notes = "If there is a dispenser at the specified coords, calls the CallbackFunction with the {{cDispenserEntity}} parameter representing the dispenser. The CallbackFunction has the following signature:
    function Callback({{cDispenserEntity|DispenserEntity}})
    The function returns false if there is no dispenser, or if there is, it returns the bool value that the callback has returned.", }, DoWithDropperAt = { Params = { { Name = "BlockX", Type = "number", }, { Name = "BlockY", Type = "number", }, { Name = "BlockZ", Type = "number", }, { Name = "CallbackFunction", Type = "function", }, }, Returns = { { Type = "boolean", }, }, Notes = "If there is a dropper at the specified coords, calls the CallbackFunction with the {{cDropperEntity}} parameter representing the dropper. The CallbackFunction has the following signature:
    function Callback({{cDropperEntity|DropperEntity}})
    The function returns false if there is no dropper, or if there is, it returns the bool value that the callback has returned.", }, DoWithDropSpenserAt = { Params = { { Name = "BlockX", Type = "number", }, { Name = "BlockY", Type = "number", }, { Name = "BlockZ", Type = "number", }, { Name = "CallbackFunction", Type = "function", }, }, Returns = { { Type = "boolean", }, }, Notes = "If there is a dropper or a dispenser at the specified coords, calls the CallbackFunction with the {{cDropSpenserEntity}} parameter representing the dropper or dispenser. The CallbackFunction has the following signature:
    function Callback({{cDropSpenserEntity|DropSpenserEntity}})
    Note that this can be used to access both dispensers and droppers in a similar way. The function returns false if there is neither dispenser nor dropper, or if there is, it returns the bool value that the callback has returned.", }, DoWithEntityByID = { Params = { { Name = "EntityID", Type = "number", }, { Name = "CallbackFunction", Type = "function", }, }, Returns = { { Type = "boolean", }, }, Notes = "If an entity with the specified ID exists, calls the callback with the {{cEntity}} parameter representing the entity. The CallbackFunction has the following signature:
    function Callback({{cEntity|Entity}})
    The function returns false if the entity was not found, and it returns the same bool value that the callback has returned if the entity was found.", }, DoWithFlowerPotAt = { Params = { { Name = "BlockX", Type = "number", }, { Name = "BlockY", Type = "number", }, { Name = "BlockZ", Type = "number", }, { Name = "CallbackFunction", Type = "function", }, }, Returns = { { Type = "boolean", }, }, Notes = "If there is a flower pot at the specified coords, calls the CallbackFunction with the {{cFlowerPotEntity}} parameter representing the flower pot. The CallbackFunction has the following signature:
    function Callback({{cFlowerPotEntity|FlowerPotEntity}})
    The function returns false if there is no flower pot, or if there is, it returns the bool value that the callback has returned.", }, DoWithFurnaceAt = { Params = { { Name = "BlockX", Type = "number", }, { Name = "BlockY", Type = "number", }, { Name = "BlockZ", Type = "number", }, { Name = "CallbackFunction", Type = "function", }, }, Returns = { { Type = "boolean", }, }, Notes = "If there is a furnace at the specified coords, calls the CallbackFunction with the {{cFurnaceEntity}} parameter representing the furnace. The CallbackFunction has the following signature:
    function Callback({{cFurnaceEntity|FurnaceEntity}})
    The function returns false if there is no furnace, or if there is, it returns the bool value that the callback has returned.", }, DoWithHopperAt = { Params = { { Name = "BlockX", Type = "number", }, { Name = "BlockY", Type = "number", }, { Name = "BlockZ", Type = "number", }, { Name = "CallbackFunction", Type = "function", }, }, Returns = { { Type = "boolean", }, }, Notes = "If there is a hopper at the specified coords, calls the CallbackFunction with the {{cHopperEntity}} parameter representing the hopper. The CallbackFunction has the following signature:
    function Callback({{cHopperEntity|cHopperEntity}})
    The function returns false if there is no hopper, or if there is, it returns the bool value that the callback has returned.", }, DoWithMobHeadAt = { Params = { { Name = "BlockX", Type = "number", }, { Name = "BlockY", Type = "number", }, { Name = "BlockZ", Type = "number", }, { Name = "CallbackFunction", Type = "function", }, }, Returns = { { Type = "boolean", }, }, Notes = "If there is a mob head at the specified coords, calls the CallbackFunction with the {{cMobHeadEntity}} parameter representing the furnace. The CallbackFunction has the following signature:
    function Callback({{cMobHeadEntity|MobHeadEntity}})
    The function returns false if there is no mob head, or if there is, it returns the bool value that the callback has returned.", }, DoWithNearestPlayer = { Params = { { Name = "Position", Type = "Vector3d", }, { Name = "RangeLimit", Type = "number", }, { Name = "CallbackFunction", Type = "function", }, { Name = "CheckLineOfSight", Type = "boolean", }, { Name = "IgnoreSpectator", Type = "boolean", }, }, Returns = { { Type = "boolean", }, }, Notes = "Calls the specified callback function with the {{cPlayer|player}} nearest to the specified position as its parameter, if they are still within the range limit. The CallbackFunction has the following signature:
    function Callback({{cPlayer|Player}})
    The function returns false if the player was not found, or whatever bool value the callback returned if the player was found.", }, DoWithNoteBlockAt = { Params = { { Name = "BlockX", Type = "number", }, { Name = "BlockY", Type = "number", }, { Name = "BlockZ", Type = "number", }, { Name = "CallbackFunction", Type = "function", }, }, Returns = { { Type = "boolean", }, }, Notes = "If there is a note block at the specified coords, calls the CallbackFunction with the {{cNoteEntity}} parameter representing the note block. The CallbackFunction has the following signature:
    function Callback({{cNoteEntity|NoteEntity}})
    The function returns false if there is no note block, or if there is, it returns the bool value that the callback has returned.", }, DoWithPlayer = { Params = { { Name = "PlayerName", Type = "string", }, { Name = "CallbackFunction", Type = "function", }, }, Returns = { { Type = "boolean", }, }, Notes = "If there is a player of the specified name (exact match), calls the CallbackFunction with the {{cPlayer}} parameter representing the player. The CallbackFunction has the following signature:
    function Callback({{cPlayer|Player}})
    The function returns false if the player was not found, or whatever bool value the callback returned if the player was found.", }, DoWithPlayerByUUID = { Params = { { Name = "PlayerUUID", Type = "cUUID", }, { Name = "CallbackFunction", Type = "function", }, }, Returns = { { Type = "boolean", }, }, Notes = "If there is the player with the uuid, calls the CallbackFunction with the {{cPlayer}} parameter representing the player. The CallbackFunction has the following signature:
    function Callback({{cPlayer|Player}})
    The function returns false if the player was not found, or whatever bool value the callback returned if the player was found.", }, DropBlockAsPickups = { Params = { { Name = "BlockPos", Type = "Vector3i", }, { Name = "Digger", Type = "cEntity", IsOptional = true, }, { Name = "Tool", Type = "cItem", IsOptional = true, }, }, Returns = { { Name = "IsSuccess", Type = "boolean", } }, Notes = "Digs up the specified block and spawns the appropriate pickups for it. The optional Digger parameter specifies the {{cEntity|entity}} who dug the block, usually a {{cPlayer|player}}. The optional Tool parameter specifies the tool used to dig the block, not present means an empty hand. Returns true on success, false if the chunk is not present. See also DigBlock() for the pickup-less version.", }, FastSetBlock = { { Params = { { Name = "BlockX", Type = "number", }, { Name = "BlockY", Type = "number", }, { Name = "BlockZ", Type = "number", }, { Name = "BlockType", Type = "number", }, { Name = "BlockMeta", Type = "number", }, }, Notes = "Sets the block at the specified coords, without waking up the simulators or replacing the block entities for the previous block type. Do not use if the block being replaced has a block entity tied to it! OBSOLETE, use the vector-based overload instead.", }, { Params = { { Name = "BlockCoords", Type = "Vector3i", }, { Name = "BlockType", Type = "number", }, { Name = "BlockMeta", Type = "number", }, }, Notes = "Sets the block at the specified coords, without waking up the simulators or replacing the block entities for the previous block type. Do not use if the block being replaced has a block entity tied to it!", }, }, FindAndDoWithPlayer = { Params = { { Name = "PlayerName", Type = "string", }, { Name = "CallbackFunction", Type = "function", }, }, Returns = { { Type = "boolean", }, }, Notes = "Calls the given callback function for the player with the name best matching the name string provided.
    This function is case-insensitive and will match partial names.
    Returns false if player not found or there is ambiguity, true otherwise. The CallbackFunction has the following signature:
    function Callback({{cPlayer|Player}})
    ", }, ForEachBlockEntityInChunk = { Params = { { Name = "ChunkX", Type = "number", }, { Name = "ChunkZ", Type = "number", }, { Name = "CallbackFunction", Type = "function", }, }, Returns = { { Type = "boolean", }, }, Notes = "Calls the specified callback for each block entity in the chunk. Returns true if all block entities in the chunk have been processed (including when there are zero block entities), or false if the callback has aborted the enumeration by returning true. The CallbackFunction has the following signature:
    function Callback({{cBlockEntity|BlockEntity}})
    The callback should return false or no value to continue with the next block entity, or true to abort the enumeration.", }, ForEachBrewingstandInChunk = { Params = { { Name = "ChunkX", Type = "number", }, { Name = "ChunkZ", Type = "number", }, { Name = "CallbackFunction", Type = "function", }, }, Returns = { { Type = "boolean", }, }, Notes = "Calls the specified callback for each brewingstand in the chunk. Returns true if all brewingstands in the chunk have been processed (including when there are zero brewingstands), or false if the callback has aborted the enumeration by returning true. The CallbackFunction has the following signature:
    function Callback({{cBrewingstandEntity|cBrewingstandEntity}})
    The callback should return false or no value to continue with the next brewingstand, or true to abort the enumeration.", }, ForEachChestInChunk = { Params = { { Name = "ChunkX", Type = "number", }, { Name = "ChunkZ", Type = "number", }, { Name = "CallbackFunction", Type = "function", }, }, Returns = { { Type = "boolean", }, }, Notes = "Calls the specified callback for each chest in the chunk. Returns true if all chests in the chunk have been processed (including when there are zero chests), or false if the callback has aborted the enumeration by returning true. The CallbackFunction has the following signature:
    function Callback({{cChestEntity|ChestEntity}})
    The callback should return false or no value to continue with the next chest, or true to abort the enumeration.", }, ForEachEntity = { Params = { { Name = "CallbackFunction", Type = "function", }, }, Returns = { { Type = "boolean", }, }, Notes = "Calls the specified callback for each entity in the loaded world. Returns true if all the entities have been processed (including when there are zero entities), or false if the callback function has aborted the enumeration by returning true. The callback function has the following signature:
    function Callback({{cEntity|Entity}})
    The callback should return false or no value to continue with the next entity, or true to abort the enumeration.", }, ForEachEntityInBox = { Params = { { Name = "Box", Type = "cBoundingBox", }, { Name = "CallbackFunction", Type = "function", }, }, Returns = { { Type = "boolean", }, }, Notes = "Calls the specified callback for each entity in the specified bounding box. Returns true if all the entities have been processed (including when there are zero entities), or false if the callback function has aborted the enumeration by returning true. If any chunk within the bounding box is not valid, it is silently skipped without any notification. The callback function has the following signature:
    function Callback({{cEntity|Entity}})
    The callback should return false or no value to continue with the next entity, or true to abort the enumeration.", }, ForEachEntityInChunk = { Params = { { Name = "ChunkX", Type = "number", }, { Name = "ChunkZ", Type = "number", }, { Name = "CallbackFunction", Type = "function", }, }, Returns = { { Type = "boolean", }, }, Notes = "Calls the specified callback for each entity in the specified chunk. Returns true if all the entities have been processed (including when there are zero entities), or false if the chunk is not loaded or the callback function has aborted the enumeration by returning true. The callback function has the following signature:
    function Callback({{cEntity|Entity}})
    The callback should return false or no value to continue with the next entity, or true to abort the enumeration.", }, ForEachFurnaceInChunk = { Params = { { Name = "ChunkX", Type = "number", }, { Name = "ChunkZ", Type = "number", }, { Name = "CallbackFunction", Type = "function", }, }, Returns = { { Type = "boolean", }, }, Notes = "Calls the specified callback for each furnace in the chunk. Returns true if all furnaces in the chunk have been processed (including when there are zero furnaces), or false if the callback has aborted the enumeration by returning true. The CallbackFunction has the following signature:
    function Callback({{cFurnaceEntity|FurnaceEntity}})
    The callback should return false or no value to continue with the next furnace, or true to abort the enumeration.", }, ForEachLoadedChunk = { Params = { { Name = "CallbackFunction", Type = "function", }, }, Returns = { { Type = "boolean", }, }, Notes = "Calls the specified callback for each loaded chunk in the world. Returns true if all chunks have been processed, or false if the callback has aborted the enumeration by returning true. The CallbackFunction has the following signature:
    function Callback(ChunkX, ChunkZ)
    The callback should return false or no value to continue with the next chunk, or true to abort the enumeration.", }, ForEachPlayer = { Params = { { Name = "CallbackFunction", Type = "function", }, }, Returns = { { Type = "boolean", }, }, Notes = "Calls the specified callback for each player in the loaded world. Returns true if all the players have been processed (including when there are zero players), or false if the callback function has aborted the enumeration by returning true. The callback function has the following signature:
    function Callback({{cPlayer|Player}})
    The callback should return false or no value to continue with the next player, or true to abort the enumeration.", }, GenerateChunk = { Params = { { Name = "ChunkX", Type = "number", }, { Name = "ChunkZ", Type = "number", }, }, Notes = "Queues the specified chunk in the chunk generator. Ignored if the chunk is already generated (use RegenerateChunk() to force chunk re-generation).", }, GetBiomeAt = { Params = { { Name = "BlockX", Type = "number", }, { Name = "BlockZ", Type = "number", }, }, Returns = { { Name = "eBiome", Type = "EMCSBiome", }, }, Notes = "Returns the biome at the specified coords. Reads the biome from the chunk, if it is loaded, otherwise it uses the chunk generator to provide the biome value.", }, GetBlock = { { Params = { { Name = "BlockX", Type = "number", }, { Name = "BlockY", Type = "number", }, { Name = "BlockZ", Type = "number", }, }, Returns = { { Name = "BLOCKTYPE", Type = "number", }, }, Notes = "Returns the block type of the block at the specified coords, or 0 if the appropriate chunk is not loaded. OBSOLETE, use the vector-based overload instead.", }, { Params = { { Name = "BlockCoords", Type = "Vector3i", }, }, Returns = { { Name = "BLOCKTYPE", Type = "number", }, }, Notes = "Returns the block type of the block at the specified coords, or 0 if the appropriate chunk is not loaded.", }, }, GetBlockBlockLight = { { Params = { { Name = "BlockX", Type = "number", }, { Name = "BlockY", Type = "number", }, { Name = "BlockZ", Type = "number", }, }, Returns = { { Type = "number", }, }, Notes = "Returns the amount of block light at the specified coords, or 0 if the appropriate chunk is not loaded. OBSOLETE, use the vector-based overload instead.", }, { Params = { { Name = "Pos", Type = "Vector3i", }, }, Returns = { { Type = "number", }, }, Notes = "Returns the amount of block light at the specified coords, or 0 if the appropriate chunk is not loaded.", }, }, GetBlockInfo = { Params = { { Name = "BlockX", Type = "number", }, { Name = "BlockY", Type = "number", }, { Name = "BlockZ", Type = "number", }, }, Returns = { { Name = "IsBlockValid", Type = "boolean", }, { Name = "BlockType", Type = "number", }, { Name = "BlockMeta", Type = "number", }, { Name = "BlockSkyLight", Type = "number", }, { Name = "BlockBlockLight", Type = "number", }, }, Notes = "Returns the complete block info for the block at the specified coords. The first value specifies if the block is in a valid loaded chunk, the other values are valid only if BlockValid is true.", }, GetBlockMeta = { { Params = { { Name = "BlockX", Type = "number", }, { Name = "BlockY", Type = "number", }, { Name = "BlockZ", Type = "number", }, }, Returns = { { Type = "number", }, }, Notes = "Returns the block metadata of the block at the specified coords, or 0 if the appropriate chunk is not loaded. OBSOLETE, use the vector-based overload instead.", }, { Params = { { Name = "BlockCoords", Type = "Vector3i", }, }, Returns = { { Type = "number", }, }, Notes = "Returns the block metadata of the block at the specified coords, or 0 if the appropriate chunk is not loaded.", }, }, GetBlockSkyLight = { Params = { { Name = "BlockX", Type = "number", }, { Name = "BlockY", Type = "number", }, { Name = "BlockZ", Type = "number", }, }, Returns = { { Type = "number", }, }, Notes = "Returns the block skylight of the block at the specified coords, or 0 if the appropriate chunk is not loaded.", }, GetBlockTypeMeta = { Params = { { Name = "BlockX", Type = "number", }, { Name = "BlockY", Type = "number", }, { Name = "BlockZ", Type = "number", }, }, Returns = { { Name = "IsBlockValid", Type = "boolean", }, { Name = "BlockType", Type = "number", }, { Name = "BlockMeta", Type = "number", }, }, Notes = "Returns the block type and metadata for the block at the specified coords. The first value specifies if the block is in a valid loaded chunk, the other values are valid only if BlockValid is true.", }, GetDataPath = { Returns = { { Type = "string", }, }, Notes = "Returns the path to the root of the world data.", }, GetDefaultWeatherInterval = { Params = { { Name = "Weather", Type = "eWeather", }, }, Returns = { { Type = "number", }, }, Notes = "Returns the default weather interval for the specific weather type. Returns -1 for any unknown weather.", }, GetDimension = { Returns = { { Type = "eDimension", }, }, Notes = "Returns the dimension of the world - dimOverworld, dimNether or dimEnd.", }, GetGameMode = { Returns = { { Type = "eGameMode", }, }, Notes = "Returns the gamemode of the world - gmSurvival, gmCreative or gmAdventure.", }, GetGeneratorQueueLength = { Returns = { { Type = "number", }, }, Notes = "Returns the number of chunks that are queued in the chunk generator.", }, GetHeight = { Params = { { Name = "BlockX", Type = "number", }, { Name = "BlockZ", Type = "number", }, }, Returns = { { Type = "number", }, }, Notes = "DEPRECATED, use TryGetHeight instead. Returns the maximum height of the particular block column in the world. If the chunk is not loaded, this function used to block until the chunk was loaded, leading to possible deadlock. Now it returns 0 instead.", }, GetIniFileName = { Returns = { { Type = "string", }, }, Notes = "Returns the name of the world.ini file that the world uses to store the information.", }, GetLightingQueueLength = { Returns = { { Type = "number", }, }, Notes = "Returns the number of chunks in the lighting thread's queue.", }, GetLinkedEndWorldName = { Returns = { { Type = "string", }, }, Notes = "Returns the name of the end world this world is linked to.", }, GetLinkedNetherWorldName = { Returns = { { Type = "string", }, }, Notes = "Returns the name of the Netherworld linked to this world.", }, GetLinkedOverworldName = { Returns = { { Type = "string", }, }, Notes = "Returns the name of the world this world is linked to.", }, GetMapManager = { Returns = { { Type = "cMapManager", }, }, Notes = "Returns the {{cMapManager|MapManager}} object used by this world.", }, GetMaxCactusHeight = { Returns = { { Type = "number", }, }, Notes = "Returns the configured maximum height to which cacti will grow naturally.", }, GetMaxNetherPortalHeight = { Returns = { { Type = "number", }, }, Notes = "Returns the maximum height for a nether portal", }, GetMaxNetherPortalWidth = { Returns = { { Type = "number", }, }, Notes = "Returns the maximum width for a nether portal", }, GetMaxSugarcaneHeight = { Returns = { { Type = "number", }, }, Notes = "Returns the configured maximum height to which sugarcane will grow naturally.", }, GetMaxViewDistance = { Returns = { { Type = "number", }, }, Notes = "Returns the maximum viewdistance that players can see in this world. The view distance is the amount of chunks around the player that the player can see.", }, GetMinNetherPortalHeight = { Returns = { { Type = "number", }, }, Notes = "Returns the minimum height for a nether portal", }, GetMinNetherPortalWidth = { Returns = { { Type = "number", }, }, Notes = "Returns the minimum width for a nether portal", }, GetName = { Returns = { { Type = "string", }, }, Notes = "Returns the name of the world, as specified in the settings.ini file.", }, GetNumChunks = { Returns = { { Type = "number", }, }, Notes = "Returns the number of chunks currently loaded.", }, GetNumUnusedDirtyChunks = { Returns = { { Type = "number", }, }, Notes = "Returns the number of unused dirty chunks. That's the number of chunks that we can save and then unload.", }, GetScoreBoard = { Returns = { { Type = "cScoreboard", }, }, Notes = "Returns the {{cScoreboard|Scoreboard}} object used by this world. ", }, GetSeed = { Returns = { { Type = "number", }, }, Notes = "Returns the seed of the world.", }, GetSignLines = { Params = { { Name = "BlockX", Type = "number", }, { Name = "BlockY", Type = "number", }, { Name = "BlockZ", Type = "number", }, }, Returns = { { Name = "IsValid", Type = "boolean", }, { Name = "Line1", Type = "string", IsOptional = true, }, { Name = "Line2", Type = "string", IsOptional = true, }, { Name = "Line3", Type = "string", IsOptional = true, }, { Name = "Line4", Type = "string", IsOptional = true, }, }, Notes = "Returns true and the lines of a sign at the specified coords, or false if there is no sign at the coords.", }, GetSpawnX = { Returns = { { Type = "number", }, }, Notes = "Returns the X coord of the default spawn", }, GetSpawnY = { Returns = { { Type = "number", }, }, Notes = "Returns the Y coord of the default spawn", }, GetSpawnZ = { Returns = { { Type = "number", }, }, Notes = "Returns the Z coord of the default spawn", }, GetSpawnPos = { Returns = { { Type = "Vector3d" }, }, Notes = "Returns the default spawn position", }, GetStorageLoadQueueLength = { Returns = { { Type = "number", }, }, Notes = "Returns the number of chunks queued up for loading", }, GetStorageSaveQueueLength = { Returns = { { Type = "number", }, }, Notes = "Returns the number of chunks queued up for saving", }, GetTicksUntilWeatherChange = { Returns = { { Type = "number", }, }, Notes = "Returns the number of ticks that will pass before the weather is changed", }, GetTimeOfDay = { Returns = { { Type = "number", }, }, Notes = "Returns the number of ticks that have passed from the sunrise, 0 .. 24000.", }, GetTNTShrapnelLevel = { Returns = { { Name = "ShrapnelLevel", Type = "eShrapnelLevel", }, }, Notes = "Returns the shrapnel level, representing the block types that are propelled outwards following an explosion. Based on this value and a random picker, blocks are selectively converted to physics entities (FallingSand) and flung outwards.", }, GetWeather = { Returns = { { Type = "eWeather", }, }, Notes = "Returns the current weather in the world (wSunny, wRain, wStorm). To check for weather, use IsWeatherXXX() functions instead.", }, GetWorldAge = { Returns = { { Type = "number", }, }, Notes = "Returns the total age of the world, in ticks. The age always grows, cannot be set by plugins and is unrelated to TimeOfDay.", }, GrowPlantAt = { Params = { { Name = "BlockPos", Type = "Vector3i", }, { Name = "NumStages", Type = "number", }, }, Returns = { { Type = "number", }, }, Notes = "Grows the plant at the specified block by the specified number of stages. Returns the number of stages actually grown. Returns zero for non-growable blocks.", }, GrowRipePlant = { Params = { { Name = "BlockPos", Type = "Vector3i", }, }, Returns = { { Type = "boolean", }, }, Notes = "Grows the plant at the specified coords to maturity. Returns true if the plant was grown, false if not.", }, GrowTree = { Params = { { Name = "BlockPos", Type = "Vector3i", }, }, Returns = { { Type = "boolean", }, }, Notes = "Grows a tree based at the specified coords. If there is a sapling there, grows the tree based on that sapling, otherwise chooses a tree image based on the biome. Returns true if the tree was grown, false if not (invalid chunk, insufficient space)", }, GrowTreeByBiome = { Params = { { Name = "BlockPos", Type = "Vector3i", }, }, Returns = { { Type = "boolean", }, }, Notes = "Grows a tree based at the specified coords. The tree type is picked from types available for the biome at those coords. Returns true if the tree was grown, false if not (invalid chunk, insufficient space)", }, GrowTreeFromSapling = { Params = { { Name = "BlockPos", Type = "Vector3i", }, }, Returns = { { Type = "boolean", }, }, Notes = "Grows a tree based at the specified coords. The tree type is determined from the sapling meta. If the sapling is part of a 2x2 sapling area, grows a large tree. Returns true if the tree was grown, false if not (invalid chunk, insufficient space)", }, IsBlockDirectlyWatered = { Params = { { Name = "BlockX", Type = "number", }, { Name = "BlockY", Type = "number", }, { Name = "BlockZ", Type = "number", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if the specified block has a water block right next to it (on the X/Z axes)", }, IsDaylightCycleEnabled = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the daylight cycle is enabled.", }, IsDeepSnowEnabled = { Returns = { { Type = "boolean", }, }, Notes = "Returns whether the configuration has DeepSnow enabled.", }, IsFarmlandTramplingEnabled = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if farmland trampling is enabled.", }, IsGameModeAdventure = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the current gamemode is gmAdventure.", }, IsGameModeCreative = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the current gamemode is gmCreative.", }, IsGameModeSpectator = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the current gamemode is gmSpectator.", }, IsGameModeSurvival = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the current gamemode is gmSurvival.", }, IsPVPEnabled = { Returns = { { Type = "boolean", }, }, Notes = "Returns whether PVP is enabled in the world settings.", }, IsSavingEnabled = { Returns = { { Type = "boolean", }, }, Notes = "Returns whether or not saving chunk data is enabled. If disabled, the world will keep dirty chunks in memory forever, and will simply regenerate non-dirty chunks that are unloaded.", }, IsSlimeChunk = { Params = { { Name = "ChunkX", Type = "number", }, { Name = "ChunkZ", Type = "number", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns whether slimes can spawn in the chunk.", }, IsTrapdoorOpen = { Params = { { Name = "BlockX", Type = "number", }, { Name = "BlockY", Type = "number", }, { Name = "BlockZ", Type = "number", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns false if there is no trapdoor there or if the block isn't a trapdoor or if the chunk wasn't loaded. Returns true if trapdoor is open.", }, IsWeatherRain = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the current weather is rainy.", }, IsWeatherRainAt = { Params = { { Name = "BlockX", Type = "number", }, { Name = "BlockZ", Type = "number", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if it is rainy at the specified location. This takes into account biomes.", }, IsWeatherStorm = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the current weather is stormy.", }, IsWeatherStormAt = { Params = { { Name = "BlockX", Type = "number", }, { Name = "BlockZ", Type = "number", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if it is stormy at the specified location. This takes into account biomes.", }, IsWeatherSunny = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the current weather is sunny.", }, IsWeatherSunnyAt = { Params = { { Name = "BlockX", Type = "number", }, { Name = "BlockZ", Type = "number", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if it is sunny at the specified location. This takes into account biomes.", }, IsWeatherWet = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the world currently has any precipitation - rain, storm or snow.", }, IsWeatherWetAt = { Params = { { Name = "BlockX", Type = "number", }, { Name = "BlockZ", Type = "number", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if it is raining or storming at the specified location. This takes into account biomes.", }, IsWeatherWetAtXYZ = { Params = { { Name = "Pos", Type = "Vector3i", }, }, Returns = { { Type = "boolean", }, }, Notes = "Returns true if the specified location has wet weather (rain or storm), using the same logic as IsWeatherWetAt, except that any rain-blocking blocks above the specified position will block the precipitation and this function will return false. Note if the chunk is unloaded then the weather state for the world will be returned.", }, PickupsFromBlock = { Params = { { Name = "BlockPos", Type = "Vector3i", }, { Name = "Digger", Type = "cEntity", IsOptional = true, }, { Name = "Tool", Type = "cItem", IsOptional = true, }, }, Returns = { { Name = "Items", Type = "cItems", }, }, Notes = "Returns all the pickups that would result if the Digger dug up the block at BlockPos using Tool. Digger is usually a {{cPlayer}}, but can be nil for natural causes. Tool is usually the equipped {{cItem|item}}, can be nil for empty hand. Returns an empty {{cItems}} object if the chunk is not present." }, PrepareChunk = { Params = { { Name = "ChunkX", Type = "number", }, { Name = "ChunkZ", Type = "number", }, { Name = "Callback", Type = "function", IsOptional = true, }, }, Notes = "Queues the chunk for preparing - making sure that it's generated and lit. It is legal to call with no callback. The callback function has the following signature:
    function Callback(ChunkX, ChunkZ)
    ", }, QueueBlockForTick = { Params = { { Name = "BlockX", Type = "number", }, { Name = "BlockY", Type = "number", }, { Name = "BlockZ", Type = "number", }, { Name = "TicksToWait", Type = "number", }, }, Notes = "Queues the specified block to be ticked after the specified number of gameticks.", }, QueueSaveAllChunks = { Notes = "Queues all chunks to be saved in the world storage thread", }, QueueTask = { Params = { { Name = "TaskFunction", Type = "function", }, }, Notes = [[ Queues the specified function to be executed in the tick thread. This is the primary means of interaction with a cWorld from the WebAdmin page handlers (see {{WebWorldThreads}}). The function signature is
    function({{cWorld|World}})
    All return values from the function are ignored. Note that this function is actually called *after* the QueueTask() function returns. Note that it is unsafe to store references to Cuberite objects, such as entities, across from the caller to the task handler function; store the EntityID instead. ]], }, QueueUnloadUnusedChunks = { Notes = "Queues a cTask that unloads chunks that are no longer needed and are saved.", }, RegenerateChunk = { Params = { { Name = "ChunkX", Type = "number", }, { Name = "ChunkZ", Type = "number", }, }, Notes = "Queues the specified chunk to be re-generated, overwriting the current data. To queue a chunk for generating only if it doesn't exist, use the GenerateChunk() instead.", }, ScheduleTask = { Params = { { Name = "DelayTicks", Type = "number", }, { Name = "TaskFunction", Type = "function", }, }, Notes = "Queues the specified function to be executed in the world's tick thread after a the specified number of ticks. This enables operations to be queued for execution in the future. The function signature is
    function({{cWorld|World}})
    All return values from the function are ignored. Note that it is unsafe to store references to Cuberite objects, such as entities, across from the caller to the task handler function; store the EntityID instead.", }, SendBlockTo = { Params = { { Name = "BlockX", Type = "number", }, { Name = "BlockY", Type = "number", }, { Name = "BlockZ", Type = "number", }, { Name = "Player", Type = "cPlayer", }, }, Notes = "Sends the block at the specified coords to the specified player's client, as an UpdateBlock packet.", }, SetAreaBiome = { { Params = { { Name = "MinX", Type = "number", }, { Name = "MaxX", Type = "number", }, { Name = "MinZ", Type = "number", }, { Name = "MaxZ", Type = "number", }, { Name = "Biome", Type = "EMCSBiome", }, }, Returns = { { Type = "boolean", }, }, Notes = "Sets the biome in the rectangular area specified. Returns true if successful, false if any of the chunks were unloaded.", }, { Params = { { Name = "Cuboid", Type = "cCuboid", }, { Name = "Biome", Type = "EMCSBiome", }, }, Returns = { { Type = "boolean", }, }, Notes = "Sets the biome in the cuboid specified. Returns true if successful, false if any of the chunks were unloaded. The cuboid needn't be sorted.", }, }, SetBiomeAt = { Params = { { Name = "BlockX", Type = "number", }, { Name = "BlockZ", Type = "number", }, { Name = "Biome", Type = "EMCSBiome", }, }, Returns = { { Type = "boolean", }, }, Notes = "Sets the biome at the specified block coords. Returns true if successful, false otherwise.", }, SetBlock = { Params = { { Name = "BlockX", Type = "number", }, { Name = "BlockY", Type = "number", }, { Name = "BlockZ", Type = "number", }, { Name = "BlockType", Type = "number", }, { Name = "BlockMeta", Type = "number", }, }, Notes = "Sets the block at the specified coords, replaces the block entities for the previous block type, creates a new block entity for the new block, if appropriate, and wakes up the simulators. This is the preferred way to set blocks, as opposed to FastSetBlock(), which is only to be used under special circumstances.", }, SetBlockMeta = { { Params = { { Name = "BlockX", Type = "number", }, { Name = "BlockY", Type = "number", }, { Name = "BlockZ", Type = "number", }, { Name = "BlockMeta", Type = "number", }, }, Notes = "Sets the meta for the block at the specified coords. Any call to SetBlockMeta will not generate a simulator update (water, lava, redstone), consider using SetBlock instead.", }, { Params = { { Name = "BlockCoords", Type = "Vector3i", }, { Name = "BlockMeta", Type = "number", }, }, Notes = "Sets the meta for the block at the specified coords. Any call to SetBlockMeta will not generate a simulator update (water, lava, redstone), consider using SetBlock instead.", }, }, SetChunkAlwaysTicked = { Params = { { Name = "ChunkX", Type = "number", }, { Name = "ChunkZ", Type = "number", }, { Name = "IsAlwaysTicked", Type = "boolean", }, }, Notes = "Sets the chunk to always be ticked and loaded even when it doesn't contain any clients. IsAlwaysTicked set to true turns forced ticking on, set to false turns it off. Every call with 'true' should be paired with a later call with 'false', otherwise the ticking won't stop. Multiple actions can request ticking independently, the ticking will continue until the last call with 'false'." }, SetCommandBlockCommand = { Params = { { Name = "BlockX", Type = "number", }, { Name = "BlockY", Type = "number", }, { Name = "BlockZ", Type = "number", }, { Name = "Command", Type = "string", }, }, Returns = { { Type = "boolean", }, }, Notes = "Sets the command to be executed in a command block at the specified coordinates. Returns if command was changed.", }, SetCommandBlocksEnabled = { Params = { { Name = "AreEnabled", Type = "boolean", }, }, Notes = "Sets whether command blocks should be enabled on the (entire) server.", }, SetDaylightCycleEnabled = { Params = { { Name = "IsEnabled", Type = "boolean", }, }, Notes = "Starts or stops the daylight cycle.", }, SetLinkedEndWorldName = { Params = { { Name = "WorldName", Type = "string", }, }, Notes = "Sets the name of the world that the end portal should link to.", }, SetLinkedNetherWorldName = { Params = { { Name = "WorldName", Type = "string", }, }, Notes = "Sets the name of the world that the nether portal should link to.", }, SetLinkedOverworldName = { Params = { { Name = "WorldName", Type = "string", }, }, Notes = "Sets the name of the world that the nether portal should link to?", }, SetMaxNetherPortalHeight = { Params = { { Name = "Height", Type = "number", }, }, Notes = "Sets the maximum height for a nether portal", }, SetMaxNetherPortalWidth = { Params = { { Name = "Width", Type = "number", }, }, Notes = "Sets the maximum width for a nether portal", }, SetMaxViewDistance = { Params = { { Name = "MaxViewDistance", Type = "number", }, }, Notes = "Sets the maximum viewdistance of the players in the world. This maximum takes precedence over each player's ViewDistance setting.", }, SetMinNetherPortalHeight = { Params = { { Name = "Height", Type = "number", }, }, Notes = "Sets the minimum height for a nether portal", }, SetMinNetherPortalWidth = { Params = { { Name = "Width", Type = "number", }, }, Notes = "Sets the minimum width for a nether portal", }, SetNextBlockTick = { Params = { { Name = "BlockX", Type = "number", }, { Name = "BlockY", Type = "number", }, { Name = "BlockZ", Type = "number", }, }, Notes = "DEPRECATED, use SetNextBlockToTick() instead.", }, SetNextBlockToTick = { Params = { { Name = "BlockPos", Type = "Vector3i", }, }, Notes = "Requests that the specified block be ticked at the start of the next world tick. Only one block per chunk can be queued this way; a second call to the same chunk overwrites the previous call.", }, SetSavingEnabled = { Params = { { Name = "SavingEnabled", Type = "boolean", }, }, Notes = "Sets whether saving chunk data is enabled. If disabled, dirty chunks will stay in memory forever, which may cause performance and stability issues.", }, SetShouldUseChatPrefixes = { Params = { { Name = "ShouldUseChatPrefixes", Type = "boolean", }, }, Notes = "Sets whether coloured chat prefixes such as [INFO] is used with the SendMessageXXX() or BroadcastChatXXX(), or simply the entire message is coloured in the respective colour.", }, SetSignLines = { Params = { { Name = "BlockX", Type = "number", }, { Name = "BlockY", Type = "number", }, { Name = "BlockZ", Type = "number", }, { Name = "Line1", Type = "string", }, { Name = "Line2", Type = "string", }, { Name = "Line3", Type = "string", }, { Name = "Line4", Type = "string", }, { Name = "Player", Type = "cPlayer", IsOptional = true, }, }, Notes = "Sets the sign text at the specified coords. The sign-updating hooks are called for the change. The Player parameter is used to indicate the player from whom the change has come, it may be nil.", }, SetSpawn = { Params = { { Name = "X", Type = "number", }, { Name = "Y", Type = "number", }, { Name = "Z", Type = "number", }, }, Returns = { { Type = "boolean", }, }, Notes = "Sets the default spawn at the specified coords. Returns false if the new spawn couldn't be stored in the INI file.", }, SetTicksUntilWeatherChange = { Params = { { Name = "NumTicks", Type = "number", }, }, Notes = "Sets the number of ticks after which the weather will be changed.", }, SetTimeOfDay = { Params = { { Name = "TimeOfDayTicks", Type = "number", }, }, Notes = "Sets the time of day, expressed as number of ticks past sunrise, in the range 0 .. 24000.", }, SetTNTShrapnelLevel = { Params = { { Name = "ShrapnelLevel", Type = "eShrapnelLevel", }, }, Notes = "Sets the Shrapnel level of the world.", }, SetTrapdoorOpen = { Params = { { Name = "BlockX", Type = "number", }, { Name = "BlockY", Type = "number", }, { Name = "BlockZ", Type = "number", }, { Name = "IsOpen", Type = "boolean", }, }, Returns = { { Type = "boolean", }, }, Notes = "Opens or closes a trapdoor at the specific coordinates. Returns true on success, false if there is no trapdoor or it's already in the requested state.", }, SetWeather = { Params = { { Name = "Weather", Type = "eWeather", }, }, Notes = "Sets the current weather (wSunny, wRain, wStorm) and resets the TicksUntilWeatherChange to the default value for the new weather. The normal weather-changing hooks are called for the change.", }, ShouldBroadcastAchievementMessages = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the server should broadcast achievement messages in this world.", }, ShouldBroadcastDeathMessages = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the server should broadcast death messages in this world.", }, ShouldLavaSpawnFire = { Returns = { { Type = "boolean", }, }, Notes = "Returns true if the world is configured to spawn fires near lava (world.ini: [Physics].ShouldLavaSpawnFire value)", }, ShouldUseChatPrefixes = { Returns = { { Type = "boolean", }, }, Notes = "Returns whether coloured chat prefixes are prepended to chat messages or the entire message is simply coloured.", }, SpawnBoat = { { Params = { { Name = "Position", Type = "Vector3d", }, { Name = "Material", Type = "cBoat#eMaterial", }, }, Returns = { { Name = "EntityID", Type = "number", }, }, Notes = "Spawns a {{cBoat|boat}} at the specific coordinates. Returns the EntityID of the new boat, or {{cEntity#INVALID_ID|cEntity#INVALID_ID}} if no boat was created.", }, { Params = { { Name = "X", Type = "number", }, { Name = "Y", Type = "number", }, { Name = "Z", Type = "number", }, { Name = "Material", Type = "cBoat#eMaterial", }, }, Returns = { { Name = "EntityID", Type = "number", }, }, Notes = "Spawns a {{cBoat|boat}} at the specific coordinates. Returns the EntityID of the new boat, or {{cEntity#INVALID_ID|cEntity#INVALID_ID}} if no boat was created. (DEPRECATED, use vector-parametered version)", }, }, SpawnEnderCrystal = { Params = { { Name = "Pos", Type = "Vector3d", }, { Name = "ShowBottom", Type = "boolean", }, }, Returns = { { Name = "EntityID", Type = "number", }, }, Notes = "Spawns an {{cEnderCrystal|ender crystal}} at the specified coords. Returns the EntityID of the new ender crystal, or {{cEntity#INVALID_ID|cEntity#INVALID_ID}} if no ender crystal was created.", }, SpawnExperienceOrb = { Params = { { Name = "X", Type = "number", }, { Name = "Y", Type = "number", }, { Name = "Z", Type = "number", }, { Name = "Reward", Type = "number", }, }, Returns = { { Name = "EntityID", Type = "number", }, }, Notes = "Spawns an {{cExpOrb|experience orb}} at the specified coords, with the given reward. Returns the EntityID of the new experience orb, or {{cEntity#INVALID_ID|cEntity#INVALID_ID}} if no experience orb was created.", }, SpawnFallingBlock = { { Params = { { Name = "X", Type = "number", }, { Name = "Y", Type = "number", }, { Name = "Z", Type = "number", }, { Name = "BlockType", Type = "number", }, { Name = "BlockMeta", Type = "number", }, }, Returns = { { Name = "EntityID", Type = "number", }, }, Notes = "OBSOLETE, use the Vector3-based overloads instead. Spawns a {{cFallingBlock|Falling Block}} entity at the specified coords with the given block type/meta. Returns the EntityID of the new falling block, or {{cEntity#INVALID_ID|cEntity#INVALID_ID}} if no falling block was created.", }, { Params = { { Name = "BlockPos", Type = "Vector3i", }, { Name = "BlockType", Type = "number", }, { Name = "BlockMeta", Type = "number", }, }, Returns = { { Name = "EntityID", Type = "number", }, }, Notes = "Spawns a {{cFallingBlock|Falling Block}} entity in the middle of the specified block, with the given block type/meta. Returns the EntityID of the new falling block, or {{cEntity#INVALID_ID|cEntity#INVALID_ID}} if no falling block was created.", }, { Params = { { Name = "Pos", Type = "Vector3d", }, { Name = "BlockType", Type = "number", }, { Name = "BlockMeta", Type = "number", }, }, Returns = { { Name = "EntityID", Type = "number", }, }, Notes = "Spawns a {{cFallingBlock|Falling Block}} entity at exactly the specified coords, with the given block type/meta. Returns the EntityID of the new falling block, or {{cEntity#INVALID_ID|cEntity#INVALID_ID}} if no falling block was created.", }, }, SpawnItemPickup = { Params = { { Name = "PosX", Type = "number", }, { Name = "PosY", Type = "number", }, { Name = "PosZ", Type = "number", }, { Name = "Item", Type = "cItem", }, { Name = "SpeedX", Type = "number", IsOptional = true, Notes = "Speed along X coordinate to spawn with. Default is 0.", }, { Name = "SpeedY", Type = "number", IsOptional = true, Notes = "Speed along Y coordinate to spawn with. Default is 0.", }, { Name = "SpeedZ", Type = "number", IsOptional = true, Notes = "Speed along Z coordinate to spawn with. Default is 0.", }, { Name = "LifetimeTicks", Type = "number", IsOptional = true, Notes = "Length of the pickups lifetime, in ticks. Default 5 minutes (6000 ticks)", }, { Name = "CanCombine", Type = "boolean", IsOptional = true, Notes = "Whether this pickup is allowed to combine with other similar pickups.", }, }, Returns = { { Name = "EntityID", Type = "number", } }, Notes = "Creates a single pickup entity of the given item at the given position with the given speed, and returns the entities unique ID." }, SpawnItemPickups = { { Params = { { Name = "Pickups", Type = "cItems", }, { Name = "X", Type = "number", }, { Name = "Y", Type = "number", }, { Name = "Z", Type = "number", }, { Name = "FlyAwaySpeed", Type = "number", IsOptional = true, }, { Name = "IsPlayerCreated", Type = "boolean", IsOptional = true, }, }, Notes = "Spawns the specified pickups at the position specified. The FlyAwaySpeed is a coefficient (default: 1) used to initialize the random speed in which the pickups fly away from the spawn position. The IsPlayerCreated parameter (default: false) is used to initialize the created {{cPickup}} object's IsPlayerCreated value.", }, { Params = { { Name = "Pickups", Type = "cItems", }, { Name = "X", Type = "number", }, { Name = "Y", Type = "number", }, { Name = "Z", Type = "number", }, { Name = "SpeedX", Type = "number", }, { Name = "SpeedY", Type = "number", }, { Name = "SpeedZ", Type = "number", }, { Name = "IsPlayerCreated", Type = "boolean", IsOptional = true, }, }, Notes = "Spawns the specified pickups at the position specified. All the pickups fly away from the spawn position using the specified speed. The IsPlayerCreated parameter (default: false) is used to initialize the created {{cPickup}} object's IsPlayerCreated value.", }, }, SpawnMinecart = { Params = { { Name = "X", Type = "number", }, { Name = "Y", Type = "number", }, { Name = "Z", Type = "number", }, { Name = "MinecartType", Type = "number", }, { Name = "Item", Type = "cItem", IsOptional = true, }, { Name = "BlockHeight", Type = "number", IsOptional = true, }, }, Returns = { { Name = "EntityID", Type = "number", }, }, Notes = "Spawns a minecart at the specific coordinates. MinecartType is the item type of the minecart. If the minecart is an empty minecart then the given Item (default: empty) is the block to be displayed inside the minecart, and BlockHeight (default: 1) is the relative distance of the block from the minecart. Returns the EntityID of the new minecart, or {{cEntity#INVALID_ID|cEntity#INVALID_ID}} if no minecart was created.", }, SpawnMob = { Params = { { Name = "X", Type = "number", }, { Name = "Y", Type = "number", }, { Name = "Z", Type = "number", }, { Name = "MonsterType", Type = "eMonsterType", }, { Name = "IsBaby", Type = "boolean", IsOptional = true, }, }, Returns = { { Name = "EntityID", Type = "number", }, }, Notes = "Spawns the specified type of mob at the specified coords. If the Baby parameter is true, the mob will be a baby. Returns the EntityID of the created entity, or {{cEntity#INVALID_ID|cEntity#INVALID_ID}} on failure.", }, SpawnPrimedTNT = { { Params = { { Name = "Position", Type = "Vector3d", }, { Name = "FuseTicks", Type = "number", }, { Name = "InitialVelocityCoeff", Type = "number", }, { Name = "ShouldPlayFuseSound", Type = "boolean", }, }, Returns = { { Name = "EntityID", Type = "number", }, }, Notes = "Spawns a {{cTNTEntity|primed TNT entity}} at the specified coords, with the given fuse ticks. The entity gets a random speed multiplied by the InitialVelocityCoeff, 1 being the default value. Returns the EntityID of the new spawned primed tnt, or {{cEntity#INVALID_ID|cEntity#INVALID_ID}} if no primed tnt was created.", }, { Params = { { Name = "X", Type = "number", }, { Name = "Y", Type = "number", }, { Name = "Z", Type = "number", }, { Name = "FuseTicks", Type = "number", }, { Name = "InitialVelocityCoeff", Type = "number", }, }, Returns = { { Name = "EntityID", Type = "number", }, }, Notes = "Spawns a {{cTNTEntity|primed TNT entity}} at the specified coords, with the given fuse ticks. The entity gets a random speed multiplied by the InitialVelocityCoeff, 1 being the default value. Returns the EntityID of the new spawned primed tnt, or {{cEntity#INVALID_ID|cEntity#INVALID_ID}} if no primed tnt was created. (DEPRECATED, use vector-parametered version)", }, }, SpawnSplitExperienceOrbs = { Params = { { Name = "Position", Type = "Vector3d", }, { Name = "Reward", Type = "number", }, }, Returns = { { Name = "EntityID", Type = "table", }, }, Notes = "Spawns experience orbs of the specified total value at the given location. The orbs' values are split according to regular Minecraft rules. Returns an array-table of UniqueID of all the orbs.", }, TryGetHeight = { Params = { { Name = "BlockX", Type = "number", }, { Name = "BlockZ", Type = "number", }, }, Returns = { { Name = "IsValid", Type = "boolean", }, { Name = "Height", Type = "number", }, }, Notes = "Returns true and height of the highest non-air block if the chunk is loaded, or false otherwise.", }, UpdateSign = { Params = { { Name = "BlockX", Type = "number", }, { Name = "BlockY", Type = "number", }, { Name = "BlockZ", Type = "number", }, { Name = "Line1", Type = "string", }, { Name = "Line2", Type = "string", }, { Name = "Line3", Type = "string", }, { Name = "Line4", Type = "string", }, { Name = "Player", Type = "cPlayer", IsOptional = true, }, }, Notes = "(DEPRECATED) Please use SetSignLines().", }, UseBlockEntity = { Params = { { Name = "Player", Type = "cPlayer", }, { Name = "BlockX", Type = "number", }, { Name = "BlockY", Type = "number", }, { Name = "BlockZ", Type = "number", }, }, Notes = "Makes the specified Player use the block entity at the specified coords (open chest UI, etc.) If the cords are in an unloaded chunk or there's no block entity, ignores the call.", }, VillagersShouldHarvestCrops = { Notes = "Returns true if villagers can harvest crops.", Returns = { { Type = "boolean", }, }, }, WakeUpSimulators = { Params = { { Name = "Block", Type = "Vector3i", }, }, Notes = "Wakes up the simulators for the specified block.", }, WakeUpSimulatorsInArea = { Params = { { Name = "Area", Type = "cCuboid", }, }, Notes = "Wakes up the simulators for all the blocks in the specified area (edges inclusive).", }, }, AdditionalInfo = { { Header = "Using callbacks", Contents = [[ To avoid problems with stale objects, the cWorld class will not let plugins get a direct pointer to an {{cEntity|entity}}, {{cBlockEntity|block entity}} or a {{cPlayer|player}}. Such an object could be modified or even destroyed by another thread while the plugin holds it, so it would be rather unsafe.

    Instead, the cWorld provides access to these objects using callbacks. The plugin provides a function that is called and receives the object as a parameter; cWorld guarantees that while the callback is executing, the object will stay valid. If a plugin needs to "remember" the object outside of the callback, it needs to store the entity ID, blockentity coords or player name.

    The following code examples show how to use the callbacks

    This code teleports player Player to another player named ToName in the same world:

    -- Player is a cPlayer object
    -- ToName is a string
    -- World is a cWorld object
    World:ForEachPlayer(
    	function (a_OtherPlayer)
    	if (a_OtherPlayer:GetName() == ToName) then
    		Player:TeleportToEntity(a_OtherPlayer);
    	end
    );
    

    This code fills each furnace in the chunk with 64 coals:

    -- Player is a cPlayer object
    -- World is a cWorld object
    World:ForEachFurnaceInChunk(Player:GetChunkX(), Player:GetChunkZ(),
    	function (a_Furnace)
    		a_Furnace:SetFuelSlot(cItem(E_ITEM_COAL, 64));
    	end
    );
    

    This code teleports all spiders up by 100 blocks:

    -- World is a cWorld object
    World:ForEachEntity(
    	function (a_Entity)
    		if not(a_Entity:IsMob()) then
    			return;
    		end
    
    		-- Now that we know the entity represents a mob, we can use cMonster functions:
    		if (a_Entity:GetMobType() == mtSpider) then
    			a_Entity:TeleportToCoords(a_Entity:GetPosX(), a_Entity:GetPosY() + 100, a_Entity:GetPosZ());
    		end
    	end
    );
    

    ]], }, }, }, } ================================================ FILE: Server/Plugins/APIDump/Hooks/OnBlockSpread.lua ================================================ return { HOOK_BLOCK_SPREAD = { CalledWhen = "Called when a block spreads based on world conditions", DefaultFnName = "OnBlockSpread", -- also used as pagename Desc = [[ This hook is called when a block spreads.

    The spread carries with it the type of its source - whether it's a block spreads. It also carries the identification of the actual source. The exact type of the identification depends on the source kind:
    SourceNotes
    ssFireSpreadFire spreading
    ssGrassSpreadGrass spreading
    ssMushroomSpreadMushroom spreading
    ssMycelSpreadMycel spreading
    ssVineSpreadVine spreading

    ]], Params = { { Name = "World", Type = "{{cWorld}}", Notes = "The world in which the block resides" }, { Name = "BlockX", Type = "number", Notes = "X-coord of the block" }, { Name = "BlockY", Type = "number", Notes = "Y-coord of the block" }, { Name = "BlockZ", Type = "number", Notes = "Z-coord of the block" }, { Name = "Source", Type = "eSpreadSource", Notes = "Source of the spread. See the table above." }, }, Returns = [[ If the function returns false or no value, the next plugin's callback is called, and finally Cuberite will process the spread. If the function returns true, no other callback is called for this event and the spread will not occur. ]], Examples = { { Title = "Stop fire spreading", Desc = "Stops fire from spreading, but does not remove any player-placed fire.", Code = [[ function OnBlockSpread(World, BlockX, Blocky, BlockZ, source) if (source == ssFireSpread) then -- Return true to block the fire spreading. return true end -- We don't care about any other events, let them continue. return false end -- Add the callback. cPluginManager:AddHook(cPluginManager.HOOK_BLOCK_SPREAD, OnBlockSpread); ]], }, }, }, -- HOOK_BLOCK_SPREAD } ================================================ FILE: Server/Plugins/APIDump/Hooks/OnBlockToPickups.lua ================================================ return { HOOK_BLOCK_TO_PICKUPS = { CalledWhen = "A block is about to be dug ({{cPlayer|player}}, {{cEntity|entity}} or natural reason), plugins may override what pickups that will produce.", DefaultFnName = "OnBlockToPickups", -- also used as pagename Desc = [[ This callback gets called whenever a block is about to be dug. This includes {{cPlayer|players}} digging blocks, entities causing blocks to disappear ({{cTNTEntity|TNT}}, Endermen) and natural causes (water washing away a block). Plugins may override the amount and kinds of pickups this action produces. ]], Params = { { Name = "World", Type = "{{cWorld}}", Notes = "The world in which the block resides" }, { Name = "Digger", Type = "{{cEntity}} descendant", Notes = "The entity causing the digging. May be a {{cPlayer}}, {{cTNTEntity}} or even nil (natural causes)" }, { Name = "BlockX", Type = "number", Notes = "X-coord of the block" }, { Name = "BlockY", Type = "number", Notes = "Y-coord of the block" }, { Name = "BlockZ", Type = "number", Notes = "Z-coord of the block" }, { Name = "BlockType", Type = "BLOCKTYPE", Notes = "Block type of the block" }, { Name = "BlockMeta", Type = "NIBBLETYPE", Notes = "Block meta of the block" }, { Name = "Pickups", Type = "{{cItems}}", Notes = "Items that will be spawned as pickups" }, }, Returns = [[ If the function returns false or no value, the next callback in the hook chain will be called. If the function returns true, no other callbacks in the chain will be called.

    Either way, the server will then spawn pickups specified in the Pickups parameter, so to disable pickups, you need to Clear the object first, then return true. ]], CodeExamples = { { Title = "Modify pickups", Desc = "This example callback function makes tall grass drop diamonds when digged by natural causes (washed away by water).", Code = [[ function OnBlockToPickups(a_World, a_Digger, a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta, a_Pickups) if (a_Digger ~= nil) then -- Not a natural cause return false; end if (a_BlockType ~= E_BLOCK_TALL_GRASS) then -- Not a tall grass being washed away return false; end -- Remove all pickups suggested by Cuberite: a_Pickups:Clear(); -- Drop a diamond: a_Pickups:Add(cItem(E_ITEM_DIAMOND)); return true; end; ]], }, } , -- CodeExamples }, -- HOOK_BLOCK_TO_PICKUPS } ================================================ FILE: Server/Plugins/APIDump/Hooks/OnBrewingCompleted.lua ================================================ return { HOOK_BREWING_COMPLETED = { CalledWhen = "A brewing process is completed.", DefaultFnName = "OnBrewingCompleted", -- also used as pagename Desc = [[ This hook is called whenever a {{cBrewingstandEntity|brewing stand}} has completed the brewing process. See also the {{OnBrewingCompleting|HOOK_BREWING_COMPLETING}} hook for a similar hook, is called when a brewing process is completing. ]], Params = { { Name = "World", Type = "{{cWorld}}", Notes = "World where the brewing stand resides." }, { Name = "Brewingstand", Type = "{{cBrewingstandEntity}}", Notes = "The brewing stand that completed the brewing process." }, }, Returns = [[ If the function returns false or no value, Cuberite calls other plugins with this event. If the function returns true, no other plugin is called for this event.

    ]], }, -- HOOK_BREWING_COMPLETED } ================================================ FILE: Server/Plugins/APIDump/Hooks/OnBrewingCompleting.lua ================================================ return { HOOK_BREWING_COMPLETING = { CalledWhen = "A brewing process is completing.", DefaultFnName = "OnBrewingCompleting", -- also used as pagename Desc = [[ This hook is called whenever a {{cBrewingstandEntity|brewing stand}} is completing the brewing process. Plugins may refuse the completing of the brewing process.

    See also the {{OnBrewingCompleted|HOOK_BREWING_COMPLETED}} hook for a similar hook, is called after the brewing process has been completed. ]], Params = { { Name = "World", Type = "{{cWorld}}", Notes = "World where the brewing stand resides." }, { Name = "Brewingstand", Type = "{{cBrewingstandEntity}}", Notes = "The brewing stand that completes the brewing process." }, }, Returns = [[ If the function returns false or no value, Cuberite calls other plugins with this event. If the function returns true, no other plugin's callback is called and the brewing process is canceled.

    ]], }, -- HOOK_BREWING_COMPLETING } ================================================ FILE: Server/Plugins/APIDump/Hooks/OnChat.lua ================================================ return { HOOK_CHAT = { CalledWhen = "Player sends a chat message", DefaultFnName = "OnChat", -- also used as pagename Desc = [[ A plugin may implement an OnChat() function and register it as a Hook to process chat messages from the players. The function is then called for every in-game message sent from any player. Note that registered in-game commands are not sent through this hook. Use the {{OnExecuteCommand|HOOK_EXECUTE_COMMAND}} to intercept registered in-game commands. ]], Params = { { Name = "Player", Type = "{{cPlayer}}", Notes = "The player who sent the message" }, { Name = "Message", Type = "string", Notes = "The message" }, }, Returns = [[ The plugin may return 2 values. The first is a boolean specifying whether the hook handling is to be stopped or not. If it is false, the message is broadcast to all players in the world. If it is true, no message is broadcast and no further action is taken.

    The second value is specifies the message to broadcast. This way, plugins may modify the message. If the second value is not provided, the original message is used. ]], }, -- HOOK_CHAT } ================================================ FILE: Server/Plugins/APIDump/Hooks/OnChunkAvailable.lua ================================================ return { HOOK_CHUNK_AVAILABLE = { CalledWhen = "A chunk has just been added to world, either generated or loaded. ", DefaultFnName = "OnChunkAvailable", -- also used as pagename Desc = [[ This hook is called after a chunk is either generated or loaded from the disk. The chunk is already available for manipulation using the {{cWorld}} API. This is a notification-only callback, there is no behavior that plugins could override. ]], Params = { { Name = "World", Type = "{{cWorld}}", Notes = "The world to which the chunk belongs" }, { Name = "ChunkX", Type = "number", Notes = "X-coord of the chunk" }, { Name = "ChunkZ", Type = "number", Notes = "Z-coord of the chunk" }, }, Returns = [[ If the function returns false or no value, the next plugin's callback is called. If the function returns true, no other callback is called for this event. ]], }, -- HOOK_CHUNK_AVAILABLE } ================================================ FILE: Server/Plugins/APIDump/Hooks/OnChunkGenerated.lua ================================================ return { HOOK_CHUNK_GENERATED = { CalledWhen = "After a chunk was generated. Notification only.", DefaultFnName = "OnChunkGenerated", -- also used as pagename Desc = [[ This hook is called when world generator finished its work on a chunk. The chunk data has already been generated and is about to be stored in the {{cWorld|world}}. A plugin may provide some last-minute finishing touches to the generated data. Note that the chunk is not yet stored in the world, so regular {{cWorld}} block API will not work! Instead, use the {{cChunkDesc}} object received as the parameter.

    See also the {{OnChunkGenerating|HOOK_CHUNK_GENERATING}} hook. ]], Params = { { Name = "World", Type = "{{cWorld}}", Notes = "The world to which the chunk will be added" }, { Name = "ChunkX", Type = "number", Notes = "X-coord of the chunk" }, { Name = "ChunkZ", Type = "number", Notes = "Z-coord of the chunk" }, { Name = "ChunkDesc", Type = "{{cChunkDesc}}", Notes = "Generated chunk data. Plugins may still modify the chunk data contained." }, }, Returns = [[ If the plugin returns false or no value, Cuberite will call other plugins' callbacks for this event. If a plugin returns true, no other callback is called for this event.

    In either case, Cuberite will then store the data from ChunkDesc as the chunk's contents in the world. ]], CodeExamples = { { Title = "Generate emerald ore", Desc = "This example callback function generates one block of emerald ore in each chunk, under the condition that the randomly chosen location is in an ExtremeHills biome.", Code = [[ function OnChunkGenerated(a_World, a_ChunkX, a_ChunkZ, a_ChunkDesc) -- Generate a psaudorandom value that is always the same for the same X/Z pair, but is otherwise random enough: -- This is actually similar to how Cuberite does its noise functions local PseudoRandom = (a_ChunkX * 57 + a_ChunkZ) * 57 + 19785486 PseudoRandom = PseudoRandom * 8192 + PseudoRandom; PseudoRandom = ((PseudoRandom * (PseudoRandom * PseudoRandom * 15731 + 789221) + 1376312589) % 0x7fffffff; PseudoRandom = PseudoRandom / 7; -- Based on the PseudoRandom value, choose a location for the ore: local OreX = PseudoRandom % 16; local OreY = 2 + ((PseudoRandom / 16) % 20); local OreZ = (PseudoRandom / 320) % 16; -- Check if the location is in ExtremeHills: if (a_ChunkDesc:GetBiome(OreX, OreZ) ~= biExtremeHills) then return false; end -- Only replace allowed blocks with the ore: local CurrBlock = a_ChunDesc:GetBlockType(OreX, OreY, OreZ); if ( (CurrBlock == E_BLOCK_STONE) or (CurrBlock == E_BLOCK_DIRT) or (CurrBlock == E_BLOCK_GRAVEL) ) then a_ChunkDesc:SetBlockTypeMeta(OreX, OreY, OreZ, E_BLOCK_EMERALD_ORE, 0); end end; ]], }, } , -- CodeExamples }, -- HOOK_CHUNK_GENERATED } ================================================ FILE: Server/Plugins/APIDump/Hooks/OnChunkGenerating.lua ================================================ return { HOOK_CHUNK_GENERATING = { CalledWhen = "A chunk is about to be generated. Plugin can override the built-in generator.", DefaultFnName = "OnChunkGenerating", -- also used as pagename Desc = [[ This hook is called before the world generator starts generating a chunk. The plugin may provide some or all parts of the generation, by-passing the built-in generator. The function is given access to the {{cChunkDesc|ChunkDesc}} object representing the contents of the chunk. It may override parts of the built-in generator by using the object's SetUseDefaultXXX(false) functions. After all the callbacks for a chunk have been processed, the server will generate the chunk based on the {{cChunkDesc|ChunkDesc}} description - those parts that are set for generating (by default everything) are generated, the rest are read from the ChunkDesc object.

    See also the {{OnChunkGenerated|HOOK_CHUNK_GENERATED}} hook. ]], Params = { { Name = "World", Type = "{{cWorld}}", Notes = "The world to which the chunk will be added" }, { Name = "ChunkX", Type = "number", Notes = "X-coord of the chunk" }, { Name = "ChunkZ", Type = "number", Notes = "Z-coord of the chunk" }, { Name = "ChunkDesc", Type = "{{cChunkDesc}}", Notes = "Generated chunk data." }, }, Returns = [[ If this function returns true, the server will not call any other plugin with the same chunk. If this function returns false, the server will call the rest of the plugins with the same chunk, possibly overwriting the ChunkDesc's contents. ]], }, -- HOOK_CHUNK_GENERATING } ================================================ FILE: Server/Plugins/APIDump/Hooks/OnChunkUnloaded.lua ================================================ return { HOOK_CHUNK_UNLOADED = { CalledWhen = "A chunk has been unloaded from the memory.", DefaultFnName = "OnChunkUnloaded", -- also used as pagename Desc = [[ This hook is called when a chunk is unloaded from the memory. Though technically still in memory, the plugin should behave as if the chunk was already not present. In particular, {{cWorld}} block API should not be used in the area of the specified chunk. ]], Params = { { Name = "World", Type = "{{cWorld}}", Notes = "The world from which the chunk is unloading" }, { Name = "ChunkX", Type = "number", Notes = "X-coord of the chunk" }, { Name = "ChunkZ", Type = "number", Notes = "Z-coord of the chunk" }, }, Returns = [[ If the function returns false or no value, the next plugin's callback is called. If the function returns true, no other callback is called for this event. There is no behavior that plugins could override. ]], }, -- HOOK_CHUNK_UNLOADED } ================================================ FILE: Server/Plugins/APIDump/Hooks/OnChunkUnloading.lua ================================================ return { HOOK_CHUNK_UNLOADING = { CalledWhen = " A chunk is about to be unloaded from the memory. Plugins may refuse the unload.", DefaultFnName = "OnChunkUnloading", -- also used as pagename Desc = [[ Cuberite calls this function when a chunk is about to be unloaded from the memory. A plugin may force Cuberite to keep the chunk in memory by returning true.

    CAUTION: Preventing the server from unloading chunks can cause the server to use too much RAM, which will adversely affect both performance and stability (i.e. your computer will get slow and crash). Return true sparingly. ]], Params = { { Name = "World", Type = "{{cWorld}}", Notes = "The world from which the chunk is unloading" }, { Name = "ChunkX", Type = "number", Notes = "X-coord of the chunk" }, { Name = "ChunkZ", Type = "number", Notes = "Z-coord of the chunk" }, }, Returns = [[ If the function returns false or no value, the next plugin's callback is called and finally Cuberite unloads the chunk. If the function returns true, no other callback is called for this event and the chunk is left in the memory. ]], }, -- HOOK_CHUNK_UNLOADING } ================================================ FILE: Server/Plugins/APIDump/Hooks/OnCollectingPickup.lua ================================================ return { HOOK_COLLECTING_PICKUP = { CalledWhen = "Player is about to collect a pickup. Plugin can refuse / override behavior. ", DefaultFnName = "OnCollectingPickup", -- also used as pagename Desc = [[ This hook is called when a player is about to collect a pickup. Plugins may refuse the action.

    Pickup collection happens within the world tick, so if the collecting is refused, it will be tried again in the next world tick, as long as the player is within reach of the pickup.

    FIXME: There is no OnCollectedPickup() callback.

    FIXME: This callback is called even if the pickup doesn't fit into the player's inventory.

    ]], Params = { { Name = "Player", Type = "{{cPlayer}}", Notes = "The player who's collecting the pickup" }, { Name = "Pickup", Type = "{{cPickup}}", Notes = "The pickup being collected" }, }, Returns = [[ If the function returns false or no value, Cuberite calls other plugins' callbacks and finally the pickup is collected. If the function returns true, no other plugins are called for this event and the pickup is not collected. ]], }, -- HOOK_COLLECTING_PICKUP } ================================================ FILE: Server/Plugins/APIDump/Hooks/OnCraftingNoRecipe.lua ================================================ return { HOOK_CRAFTING_NO_RECIPE = { CalledWhen = " No built-in crafting recipe is found. Plugin may provide a recipe.", DefaultFnName = "OnCraftingNoRecipe", -- also used as pagename Desc = [[ This callback is called when a player places items in their {{cCraftingGrid|crafting grid}} and Cuberite cannot find a built-in {{cCraftingRecipe|recipe}} for the combination. Plugins may provide a recipe for the ingredients given. ]], Params = { { Name = "Player", Type = "{{cPlayer}}", Notes = "The player whose crafting is reported in this hook" }, { Name = "Grid", Type = "{{cCraftingGrid}}", Notes = "Contents of the player's crafting grid" }, { Name = "Recipe", Type = "{{cCraftingRecipe}}", Notes = "The recipe that will be used (can be filled by plugins)" }, }, Returns = [[ If the function returns false or no value, no recipe will be used. If the function returns true, no other plugin will have their callback called for this event and Cuberite will use the crafting recipe in Recipe.

    FIXME: To allow plugins give suggestions and overwrite other plugins' suggestions, we should change the behavior with returning false, so that the recipe will still be used, but fill the recipe with empty values by default. ]], }, -- HOOK_CRAFTING_NO_RECIPE } ================================================ FILE: Server/Plugins/APIDump/Hooks/OnDisconnect.lua ================================================ return { HOOK_DISCONNECT = { CalledWhen = [[ A client has disconnected, either by explicitly sending the disconnect packet (in older protocols) or their connection was terminated ]], DefaultFnName = "OnDisconnect", -- also used as pagename Desc = [[ This hook is called when a client has disconnected from the server, for whatever reason. It is also called when the client sends the Disconnect packet (only in pre-1.7 protocols). This hook is not called for server ping connections.

    Note that the hook is called even for connections to players who failed to auth. In such a case there's no {{cPlayer}} object associated with the client.

    See also the {{OnHandshake|HOOK_HANDSHAKE}} hook which is called when the client connects (and presents a handshake message, so that they are not just status-pinging). If you need to store a per-player object, use the {{OnPlayerJoined|HOOK_PLAYER_JOINED}} and {{OnPlayerDestroyed|HOOK_PLAYER_DESTROYED}} hooks instead, those are guaranteed to have the {{cPlayer}} object associated. ]], Params = { { Name = "Client", Type = "{{cClientHandle}}", Notes = "The client who has disconnected" }, { Name = "Reason", Type = "string", Notes = "The reason that the client has sent in the disconnect packet" }, }, Returns = [[ If the function returns false or no value, Cuberite calls other plugins' callbacks for this event. If the function returns true, no other plugins are called for this event. In either case, the client is disconnected. ]], }, -- HOOK_DISCONNECT } ================================================ FILE: Server/Plugins/APIDump/Hooks/OnDropSpense.lua ================================================ return { HOOK_DROPSPENSE = { CalledWhen = "A dispenser or dropper is about to dispense/drop an item.", DefaultFnName = "OnDropSpense", -- also used as pagename Desc = [[ This callback is called whenever a {{cDropSpenserEntity|dropspenser}} dropspenses an {{cItem|item}}. A plugin may decide to disallow the move by returning true. ]], Params = { { Name = "World", Type = "{{cWorld}}", Notes = "World where the dropspenser resides" }, { Name = "DropSpenser", Type = "{{cDropSpenserEntity}}", Notes = "The dropspenser that is pulling the item" }, { Name = "SlotNum", Type = "number", Notes = "The slot of the dropspensed item in the dropspenser's {{cItemGrid|internal storage}}" }, }, Returns = [[ If the function returns false or no value, the next plugin's callback is called. If the function returns true, no other callback is called for this event and the dropspenser will not dropspense the item. ]], }, -- HOOK_DROPSPENSE } ================================================ FILE: Server/Plugins/APIDump/Hooks/OnEntityAddEffect.lua ================================================ return { HOOK_ENTITY_ADD_EFFECT = { CalledWhen = "An entity effect is about to get added to an entity.", DefaultFnName = "OnEntityAddEffect", -- also used as pagename Desc = [[ This hook is called whenever an entity effect is about to be added to an entity. The plugin may disallow the addition by returning true.

    Note that this hook only fires for adding the effect, but not for the actual effect application. See also the {{OnEntityRemoveEffect|HOOK_ENTITY_REMOVE_EFFECT}} for notification about effects expiring / removing, and {{OnEntityApplyEffect|HOOK_ENTITY_APPLY_EFFECT}} for the actual effect application to the entity. ]], Params = { { Name = "Entity", Type = "{{cEntity}}", Notes = "The entity to which the effect is about to be added" }, { Name = "EffectType", Type = "number", Notes = "The type of the effect to be added. One of the effXXX constants." }, { Name = "EffectDuration", Type = "number", Notes = "The duration of the effect to be added, in ticks." }, { Name = "EffectIntensity", Type = "number", Notes = "The intensity (level) of the effect to be added. " }, { Name = "DistanceModifier", Type = "number", Notes = "The modifier for the effect intensity, based on distance. Used mainly for splash potions." }, }, Returns = [[ If the plugin returns true, the effect will not be added and none of the remaining hook handlers will be called. If the plugin returns false, Cuberite calls all the remaining hook handlers and finally the effect is added to the entity. ]], }, -- HOOK_EXECUTE_COMMAND } ================================================ FILE: Server/Plugins/APIDump/Hooks/OnEntityChangedWorld.lua ================================================ return { HOOK_ENTITY_CHANGED_WORLD = { CalledWhen = "After a entity has changed the world.", DefaultFnName = "OnEntityChangedWorld", -- also used as pagename Desc = [[ This hook is called after the server has moved the {{cEntity|entity}} to the given world. This is an information-only callback, the entity is already in the new world.

    See also the {{OnEntityChangingWorld|HOOK_ENTITY_CHANGING_WORLD}} hook for a similar hook called before the entity is moved to the new world. ]], Params = { { Name = "Entity", Type = "{{cEntity}}", Notes = "The entity that has changed the world" }, { Name = "World", Type = "{{cWorld}}", Notes = "The world from which the entity has come" }, }, Returns = [[ If the function returns false or no value, the next plugin's callback is called. If the function returns true, no other callback is called for this event. ]], }, -- HOOK_ENTITY_CHANGED_WORLD } ================================================ FILE: Server/Plugins/APIDump/Hooks/OnEntityChangingWorld.lua ================================================ return { HOOK_ENTITY_CHANGING_WORLD = { CalledWhen = "Before a entity is changing the world.", DefaultFnName = "OnEntityChangingWorld", -- also used as pagename Desc = [[ This hook is called before the server moves the {{cEntity|entity}} to the given world. Plugins may refuse the changing of the entity to the new world.

    See also the {{OnEntityChangedWorld|HOOK_ENTITY_CHANGED_WORLD}} hook for a similar hook is called after the entity has been moved to the world. ]], Params = { { Name = "Entity", Type = "{{cEntity}}", Notes = "The entity that wants to change the world" }, { Name = "World", Type = "{{cWorld}}", Notes = "The world to which the entity wants to change" }, }, Returns = [[ If the function returns false or no value, the next plugin's callback is called. If the function returns true, no other callback is called for this event and the change of the entity to the world is cancelled. ]], }, -- HOOK_ENTITY_CHANGING_WORLD } ================================================ FILE: Server/Plugins/APIDump/Hooks/OnEntityTeleport.lua ================================================ return { HOOK_ENTITY_TELEPORT = { CalledWhen = "Any entity teleports. Plugin may refuse teleport.", DefaultFnName = "OnEntityTeleport", -- also used as pagename Desc = [[ This function is called in each server tick for each {{cEntity|Entity}} that has teleported. Plugins may refuse the teleport. ]], Params = { { Name = "Entity", Type = "{{cEntity}}", Notes = "The entity who has teleported. New position is set in the object after successfull teleport" }, { Name = "OldPosition", Type = "{{Vector3d}}", Notes = "The old position." }, { Name = "NewPosition", Type = "{{Vector3d}}", Notes = "The new position." }, }, Returns = [[ If the function returns true, teleport is prohibited.

    If the function returns false or no value, other plugins' callbacks are called and finally the new position is permanently stored in the cEntity object.

    ]], }, -- HOOK_ENTITY_TELEPORT } ================================================ FILE: Server/Plugins/APIDump/Hooks/OnExecuteCommand.lua ================================================ return { HOOK_EXECUTE_COMMAND = { CalledWhen = [[ A player executes an in-game command, or the admin issues a console command. Note that built-in console commands are exempt to this hook - they are always performed and the hook is not called. ]], DefaultFnName = "OnExecuteCommand", -- also used as pagename Desc = [[ A plugin may implement a callback for this hook to intercept both in-game commands executed by the players and console commands executed by the server admin. The function is called for every in-game command sent from any player and for those server console commands that are not built in in the server.

    If the command is in-game, the first parameter to the hook function is the {{cPlayer|player}} who's executing the command. If the command comes from the server console, the first parameter is nil.

    The server calls this hook even for unregistered (unknown) console commands. It also calls the hook for unknown in-game commands, as long as they begin with a slash ('/'). If a plugin needs to intercept in-game chat messages not beginning with a slash, it should use the {{OnChat|HOOK_CHAT}} hook. ]], Params = { { Name = "Player", Type = "{{cPlayer}}", Notes = "For in-game commands, the player who has sent the message. For console commands, nil" }, { Name = "CommandSplit", Type = "array-table of strings", Notes = "The command and its parameters, broken into a table by spaces" }, { Name = "EntireCommand", Type = "string", Notes = "The entire command as a single string" }, }, Returns = [[ If the plugin returns false, Cuberite calls all the remaining hook handlers and finally the command will be executed. If the plugin returns true, the none of the remaining hook handlers will be called. In this case the plugin can return a second value, specifying whether what the command result should be set to, one of the {{cPluginManager#CommandResult|CommandResult}} constants. If not provided, the value defaults to crBlocked. ]], }, -- HOOK_EXECUTE_COMMAND } ================================================ FILE: Server/Plugins/APIDump/Hooks/OnExploded.lua ================================================ return { HOOK_EXPLODED = { CalledWhen = "An explosion has happened", DefaultFnName = "OnExploded", -- also used as pagename Desc = [[ This hook is called after an explosion has been processed in a world.

    See also {{OnExploding|HOOK_EXPLODING}} for a similar hook called before the explosion.

    The explosion carries with it the type of its source - whether it's a creeper exploding, or TNT, etc. It also carries the identification of the actual source. The exact type of the identification depends on the source kind, see the {{Globals#ExplosionSource|esXXX}} constants' descriptions for details. ]], Params = { { Name = "World", Type = "{{cWorld}}", Notes = "The world where the explosion happened" }, { Name = "ExplosionSize", Type = "number", Notes = "The relative explosion size" }, { Name = "CanCauseFire", Type = "bool", Notes = "True if the explosion has turned random air blocks to fire (such as a ghast fireball)" }, { Name = "X", Type = "number", Notes = "X-coord of the explosion center" }, { Name = "Y", Type = "number", Notes = "Y-coord of the explosion center" }, { Name = "Z", Type = "number", Notes = "Z-coord of the explosion center" }, { Name = "Source", Type = "eExplosionSource", Notes = "Source of the explosion. See the table above." }, { Name = "SourceData", Type = "varies", Notes = "Additional data for the source. The exact type varies by the source. See the {{Globals#ExplosionSource|esXXX}} constants' descriptions." }, }, Returns = [[ If the function returns false or no value, the next plugin's callback is called. If the function returns true, no other callback is called for this event. There is no overridable behaviour. ]], }, -- HOOK_EXPLODED } ================================================ FILE: Server/Plugins/APIDump/Hooks/OnExploding.lua ================================================ return { HOOK_EXPLODING = { CalledWhen = "An explosion is about to be processed", DefaultFnName = "OnExploding", -- also used as pagename Desc = [[ This hook is called before an explosion has been processed in a world.

    See also {{OnExploded|HOOK_EXPLODED}} for a similar hook called after the explosion.

    The explosion carries with it the type of its source - whether it's a creeper exploding, or TNT, etc. It also carries the identification of the actual source. The exact type of the identification depends on the source kind, see the {{Globals#ExplosionSource|esXXX}} constants' descriptions for details ]], Params = { { Name = "World", Type = "{{cWorld}}", Notes = "The world where the explosion happens" }, { Name = "ExplosionSize", Type = "number", Notes = "The relative explosion size" }, { Name = "CanCauseFire", Type = "bool", Notes = "True if the explosion will turn random air blocks to fire (such as a ghast fireball)" }, { Name = "X", Type = "number", Notes = "X-coord of the explosion center" }, { Name = "Y", Type = "number", Notes = "Y-coord of the explosion center" }, { Name = "Z", Type = "number", Notes = "Z-coord of the explosion center" }, { Name = "Source", Type = "eExplosionSource", Notes = "Source of the explosion. See the table above." }, { Name = "SourceData", Type = "varies", Notes = "Additional data for the source. The exact type varies by the source. See the {{Globals#ExplosionSource|esXXX}} constants' description." }, }, Returns = [[ If the function returns false or no value, the next plugin's callback is called, and finally Cuberite will process the explosion - destroy blocks and push + hurt entities. If the function returns true, no other callback is called for this event and the explosion will not occur.

    The hook handler may return up to two more values after the initial bool. The second returned value overrides the CanCauseFire parameter for subsequent hook calls and the final explosion, the third returned value overrides the ExplosionSize parameter for subsequent hook calls and the final explosion. ]], }, -- HOOK_EXPLODING } ================================================ FILE: Server/Plugins/APIDump/Hooks/OnHandshake.lua ================================================ return { HOOK_HANDSHAKE = { CalledWhen = "A client is connecting.", DefaultFnName = "OnHandshake", -- also used as pagename Desc = [[ This hook is called when a client sends the Handshake packet. At this stage, only the client IP and (unverified) username are known. Plugins may refuse access to the server based on this information.

    Note that the username is not authenticated - the authentication takes place only after this hook is processed. ]], Params = { { Name = "Client", Type = "{{cClientHandle}}", Notes = "The client handle representing the connection. Note that there's no {{cPlayer}} object for this client yet." }, { Name = "UserName", Type = "string", Notes = "The username presented in the packet. Note that this username is unverified." }, }, Returns = [[ If the function returns false, the user is let in to the server. If the function returns true, no other plugin's callback is called, the user is kicked and the connection is closed. ]], }, -- HOOK_HANDSHAKE } ================================================ FILE: Server/Plugins/APIDump/Hooks/OnHopperPullingItem.lua ================================================ return { HOOK_HOPPER_PULLING_ITEM = { CalledWhen = "A hopper is pulling an item from another block entity.", DefaultFnName = "OnHopperPullingItem", -- also used as pagename Desc = [[ This callback is called whenever a {{cHopperEntity|hopper}} transfers an {{cItem|item}} from another block entity into its own internal storage. A plugin may decide to disallow the move by returning true. Note that in such a case, the hook may be called again for the same hopper, with different slot numbers. ]], Params = { { Name = "World", Type = "{{cWorld}}", Notes = "World where the hopper resides" }, { Name = "Hopper", Type = "{{cHopperEntity}}", Notes = "The hopper that is pulling the item" }, { Name = "DstSlot", Type = "number", Notes = "The destination slot in the hopper's {{cItemGrid|internal storage}}" }, { Name = "SrcBlockEntity", Type = "{{cBlockEntityWithItems}}", Notes = "The block entity that is losing the item" }, { Name = "SrcSlot", Type = "number", Notes = "Slot in SrcBlockEntity from which the item will be pulled" }, }, Returns = [[ If the function returns false or no value, the next plugin's callback is called. If the function returns true, no other callback is called for this event and the hopper will not pull the item. ]], }, -- HOOK_HOPPER_PULLING_ITEM } ================================================ FILE: Server/Plugins/APIDump/Hooks/OnHopperPushingItem.lua ================================================ return { HOOK_HOPPER_PUSHING_ITEM = { CalledWhen = "A hopper is pushing an item into another block entity. ", DefaultFnName = "OnHopperPushingItem", -- also used as pagename Desc = [[ This hook is called whenever a {{cHopperEntity|hopper}} transfers an {{cItem|item}} from its own internal storage into another block entity. A plugin may decide to disallow the move by returning true. Note that in such a case, the hook may be called again for the same hopper and block, with different slot numbers. ]], Params = { { Name = "World", Type = "{{cWorld}}", Notes = "World where the hopper resides" }, { Name = "Hopper", Type = "{{cHopperEntity}}", Notes = "The hopper that is pushing the item" }, { Name = "SrcSlot", Type = "number", Notes = "Slot in the hopper that will lose the item" }, { Name = "DstBlockEntity", Type = "{{cBlockEntityWithItems}}", Notes = " The block entity that will receive the item" }, { Name = "DstSlot", Type = "number", Notes = " Slot in DstBlockEntity's internal storage where the item will be stored" }, }, Returns = [[ If the function returns false or no value, the next plugin's callback is called. If the function returns true, no other callback is called for this event and the hopper will not push the item. ]], }, -- HOOK_HOPPER_PUSHING_ITEM } ================================================ FILE: Server/Plugins/APIDump/Hooks/OnKilled.lua ================================================ return { HOOK_KILLED = { CalledWhen = "A player or a mob died.", DefaultFnName = "OnKilled", Desc = [[ This hook is called whenever player or a mob dies. It can be used to change the death message. ]], Params = { { Name = "Victim", Type = "{{cEntity}}", Notes = "The player or mob that died" }, { Name = "TDI", Type = "{{TakeDamageInfo}}", Notes = "Informations about the death" }, { Name = "DeathMessage", Type = "string", Notes = "The default death message. An empty string if the victim is not a player" }, }, Returns = [[ The function may return two values. The first value is a boolean specifying whether other plugins should be called. If it is true, the other plugins won't get notified of the death. If it is false, the other plugins will get notified.

    The second value is a string containing the death message. If the victim is a player, this death message is broadcasted instead of the default death message. If it is empty, no death message is broadcasted. If it is nil, the message is left unchanged. If the victim is not a player, the death message is never broadcasted.

    In either case, the victim is dead. ]], }, -- HOOK_KILLED } ================================================ FILE: Server/Plugins/APIDump/Hooks/OnKilling.lua ================================================ return { HOOK_KILLING = { CalledWhen = "A player or a mob is dying.", DefaultFnName = "OnKilling", -- also used as pagename Desc = [[ This hook is called whenever a {{cPawn|pawn}}'s (a player's or a mob's) health reaches zero. This means that the pawn is about to be killed, unless a plugin "revives" them by setting their health back to a positive value. ]], Params = { { Name = "Victim", Type = "{{cPawn}}", Notes = "The player or mob that is about to be killed" }, { Name = "Killer", Type = "{{cEntity}}", Notes = "The entity that has caused the victim to lose the last point of health. May be nil for environment damage" }, { Name = "TDI", Type = "{{TakeDamageInfo}}", Notes = "The damage type, cause and effects." }, }, Returns = [[ If the function returns false or no value, Cuberite calls other plugins with this event. If the function returns true, no other plugin is called for this event.

    In either case, the victim's health is then re-checked and if it is greater than zero, the victim is "revived" with that health amount. If the health is less or equal to zero, the victim is killed. ]], }, -- HOOK_KILLING } ================================================ FILE: Server/Plugins/APIDump/Hooks/OnLogin.lua ================================================ return { HOOK_LOGIN = { CalledWhen = "Right before player authentication. If auth is disabled, right after the player sends their name.", DefaultFnName = "OnLogin", -- also used as pagename Desc = [[ This hook is called whenever a client logs in. It is called right before the client's name is sent to be authenticated. Plugins may refuse the client from accessing the server. Note that when this callback is called, the {{cPlayer}} object for this client doesn't exist yet - the client has no representation in any world. To process new players when their world is known, use a later callback, such as {{OnPlayerJoined|HOOK_PLAYER_JOINED}} or {{OnPlayerSpawned|HOOK_PLAYER_SPAWNED}}. ]], Params = { { Name = "Client", Type = "{{cClientHandle}}", Notes = "The client handle representing the connection" }, { Name = "ProtocolVersion", Type = "number", Notes = "Versio of the protocol that the client is talking" }, { Name = "UserName", Type = "string", Notes = "The name that the client has presented for authentication. This name will be given to the {{cPlayer}} object when it is created for this client." }, }, Returns = [[ If the function returns true, no other plugins are called for this event and the client is kicked. If the function returns false or no value, Cuberite calls other plugins' callbacks and finally sends an authentication request for the client's username to the auth server. If the auth server is disabled in the server settings, the player object is immediately created. ]], }, -- HOOK_LOGIN } ================================================ FILE: Server/Plugins/APIDump/Hooks/OnPlayerAnimation.lua ================================================ return { HOOK_PLAYER_ANIMATION = { CalledWhen = "A client has sent an Animation packet", DefaultFnName = "OnPlayerAnimation", -- also used as pagename Desc = [[ This hook is called when the server receives an Animation packet from the client.

    For the list of animations that are sent by the client, see the Protocol wiki. ]], Params = { { Name = "Player", Type = "{{cPlayer}}", Notes = "The player from whom the packet was received" }, { Name = "Animation", Type = "number", Notes = "The kind of animation" }, }, Returns = [[ If the function returns false or no value, the next plugin's callback is called. Afterwards, the server broadcasts the animation packet to all nearby clients. If the function returns true, no other callback is called for this event and the packet is not broadcasted. ]], }, -- HOOK_PLAYER_ANIMATION } ================================================ FILE: Server/Plugins/APIDump/Hooks/OnPlayerBreakingBlock.lua ================================================ return { HOOK_PLAYER_BREAKING_BLOCK = { CalledWhen = "Just before a player breaks a block. Plugin may override / refuse. ", DefaultFnName = "OnPlayerBreakingBlock", -- also used as pagename Desc = [[ This hook is called when a {{cPlayer|player}} breaks a block, before the block is actually broken in the {{cWorld|World}}. Plugins may refuse the breaking.

    See also the {{OnPlayerBrokenBlock|HOOK_PLAYER_BROKEN_BLOCK}} hook for a similar hook called after the block is broken. ]], Params = { { Name = "Player", Type = "{{cPlayer}}", Notes = "The player who is digging the block" }, { Name = "BlockX", Type = "number", Notes = "X-coord of the block" }, { Name = "BlockY", Type = "number", Notes = "Y-coord of the block" }, { Name = "BlockZ", Type = "number", Notes = "Z-coord of the block" }, { Name = "BlockFace", Type = "number", Notes = "Face of the block upon which the player is acting. One of the BLOCK_FACE_ constants" }, { Name = "BlockType", Type = "BLOCKTYPE", Notes = "The block type of the block being broken" }, { Name = "BlockMeta", Type = "NIBBLETYPE", Notes = "The block meta of the block being broken " }, }, Returns = [[ If the function returns false or no value, other plugins' callbacks are called, and then the block is broken. If the function returns true, no other plugin's callback is called and the block breaking is cancelled. The server re-sends the block back to the player to replace it (the player's client already thinks the block was broken). ]], }, -- HOOK_PLAYER_BREAKING_BLOCK } ================================================ FILE: Server/Plugins/APIDump/Hooks/OnPlayerBrokenBlock.lua ================================================ return { HOOK_PLAYER_BROKEN_BLOCK = { CalledWhen = "After a player has broken a block. Notification only.", DefaultFnName = "OnPlayerBrokenBlock", -- also used as pagename Desc = [[ This function is called after a {{cPlayer|player}} breaks a block. The block is already removed from the {{cWorld|world}} and {{cPickup|pickups}} have been spawned. To get the world in which the block has been dug, use the {{cPlayer}}:GetWorld() function.

    See also the {{OnPlayerBreakingBlock|HOOK_PLAYER_BREAKING_BLOCK}} hook for a similar hook called before the block is broken. To intercept the creation of pickups, see the {{OnBlockToPickups|HOOK_BLOCK_TO_PICKUPS}} hook. ]], Params = { { Name = "Player", Type = "{{cPlayer}}", Notes = "The player who broke the block" }, { Name = "BlockX", Type = "number", Notes = "X-coord of the block" }, { Name = "BlockY", Type = "number", Notes = "Y-coord of the block" }, { Name = "BlockZ", Type = "number", Notes = "Z-coord of the block" }, { Name = "BlockFace", Type = "number", Notes = "Face of the block upon which the player interacted. One of the BLOCK_FACE_ constants" }, { Name = "BlockType", Type = "BLOCKTYPE", Notes = "The block type of the block" }, { Name = "BlockMeta", Type = "NIBBLETYPE", Notes = "The block meta of the block" }, }, Returns = [[ If the function returns false or no value, the next plugin's callback is called. If the function returns true, no other callback is called for this event. ]], }, -- HOOK_PLAYER_BROKEN_BLOCK } ================================================ FILE: Server/Plugins/APIDump/Hooks/OnPlayerCrouched.lua ================================================ return { HOOK_PLAYER_CROUCHED = { CalledWhen = "Player crouched in the tick being currently processed.", DefaultFnName = "OnPlayerCrouched", -- also used as pagename Desc = [[ This function is called in each server tick for each {{cPlayer|player}} that has crouched. ]], Params = { { Name = "Player", Type = "{{cPlayer}}", Notes = "The player who has crouched." }, }, Returns = [[ If the function returns false or no value, other plugins callbacks are called.

    ]], }, -- HOOK_PLAYER_CROUCHED } ================================================ FILE: Server/Plugins/APIDump/Hooks/OnPlayerDestroyed.lua ================================================ return { HOOK_PLAYER_DESTROYED = { CalledWhen = "A player object is about to be destroyed.", DefaultFnName = "OnPlayerDestroyed", -- also used as pagename Desc = [[ This function is called before a {{cPlayer|player}} is about to be destroyed. The player has disconnected for whatever reason and is no longer in the server. If a plugin returns true, a leave message is not broadcast, and vice versa. However, whatever the return value, the player object is removed from memory. ]], Params = { { Name = "Player", Type = "{{cPlayer}}", Notes = "The destroyed player" }, }, Returns = [[ If the function returns false or no value, other plugins' callbacks are called and a leave message is broadcast. If the function returns true, no other callbacks are called for this event and no leave message appears. Either way the player is removed internally. ]], }, -- HOOK_PLAYER_DESTROYED } ================================================ FILE: Server/Plugins/APIDump/Hooks/OnPlayerEating.lua ================================================ return { HOOK_PLAYER_EATING = { CalledWhen = "When the player starts eating", DefaultFnName = "OnPlayerEating", -- also used as pagename Desc = [[ This hook gets called when the {{cPlayer|player}} starts eating, after the server checks that the player can indeed eat (is not satiated and is holding food). Plugins may still refuse the eating by returning true. ]], Params = { { Name = "Player", Type = "{{cPlayer}}", Notes = "The player who started eating" }, }, Returns = [[ If the function returns false or no value, the server calls the next plugin handler, and finally lets the player eat. If the function returns true, the server doesn't call any more callbacks for this event and aborts the eating. A "disallow" packet is sent to the client. ]], }, -- HOOK_PLAYER_EATING } ================================================ FILE: Server/Plugins/APIDump/Hooks/OnPlayerFished.lua ================================================ return { HOOK_PLAYER_FISHED = { CalledWhen = "A player gets a reward from fishing.", DefaultFnName = "OnPlayerFished", -- also used as pagename Desc = [[ This hook gets called after a player reels in the fishing rod. This is a notification-only hook, the reward has already been decided. If a plugin needs to modify the reward, use the {{OnPlayerFishing|HOOK_PLAYER_FISHING}} hook. ]], Params = { { Name = "Player", Type = "{{cPlayer}}", Notes = "The player who pulled the fish in." }, { Name = "Reward", Type = "{{cItems}}", Notes = "The reward the player gets. It can be a fish, treasure and junk." }, }, Returns = [[ If the function returns false or no value, the next plugin's callback is called. If the function returns true, no other callback is called for this event. ]], }, -- HOOK_PLAYER_FISHED }; ================================================ FILE: Server/Plugins/APIDump/Hooks/OnPlayerFishing.lua ================================================ return { HOOK_PLAYER_FISHING = { CalledWhen = "A player is about to get a reward from fishing.", DefaultFnName = "OnPlayerFishing", -- also used as pagename Desc = [[ This hook gets called when a player right clicks with a fishing rod while the floater is under water. The reward is already descided, but the plugin may change it. ]], Params = { { Name = "Player", Type = "{{cPlayer}}", Notes = "The player who pulled the fish in." }, { Name = "Reward", Type = "{{cItems}}", Notes = "The reward the player gets. It can be a fish, treasure and junk." }, }, Returns = [[ If the function returns false or no value, the next plugin's callback is called. Afterwards, the server gives the player his reward. If the function returns true, no other callback is called for this event and the player doesn't get his reward. ]], }, -- HOOK_PLAYER_FISHING }; ================================================ FILE: Server/Plugins/APIDump/Hooks/OnPlayerFoodLevelChange.lua ================================================ return { HOOK_PLAYER_FOOD_LEVEL_CHANGE = { CalledWhen = "Called before the player food level changed. Plugin may override", DefaultFnName = "OnPlayerFoodLevelChange", -- also used as pagename Desc = [[ This hook is called before the food level changes. The food level is not changed yet, plugins may choose to refuse the change. ]], Params = { { Name = "Player", Type = "{{cPlayer}}", Notes = "The player who changes the food level." }, { Name = "NewFoodLevel", Type = "number", Notes = "The new food level." }, }, Returns = [[ If the function returns false or no value, the next plugin's callback is called. Afterwards, the server changes the food level of the player. If the function returns true, no other callback is called for this event and the player's food level doesn't change. ]], }, -- HOOK_PLAYER_FOOD_LEVEL_CHANGE }; ================================================ FILE: Server/Plugins/APIDump/Hooks/OnPlayerJoined.lua ================================================ return { HOOK_PLAYER_JOINED = { CalledWhen = "After Login and before Spawned, before being added to world. ", DefaultFnName = "OnPlayerJoined", -- also used as pagename Desc = [[ This hook is called whenever a {{cPlayer|player}} has completely logged in. If authentication is enabled, this function is called after their name has been authenticated. It is called after {{OnLogin|HOOK_LOGIN}} and before {{OnPlayerSpawned|HOOK_PLAYER_SPAWNED}}, right after the player's entity is created, but not added to the world yet. The player is not yet visible to other players. Returning true will block a join message from being broadcast, but otherwise, the player is still allowed to join. Plugins wishing to refuse player's entry should kick the player using the {{cPlayer}}:Kick() function. ]], Params = { { Name = "Player", Type = "{{cPlayer}}", Notes = "The player who has joined the game" }, }, Returns = [[ If the function returns false or no value, other plugins' callbacks are called and a join message is broadcast. If the function returns true, no other callbacks are called for this event and a join message is not sent. Either way the player is let in. ]], }, -- HOOK_PLAYER_JOINED } ================================================ FILE: Server/Plugins/APIDump/Hooks/OnPlayerLeftClick.lua ================================================ return { HOOK_PLAYER_LEFT_CLICK = { CalledWhen = "A left-click packet is received from the client. Plugin may override / refuse.", DefaultFnName = "OnPlayerLeftClick", -- also used as pagename Desc = [[ This hook is called when Cuberite receives a left-click packet from the {{cClientHandle|client}}. It is called before any processing whatsoever is performed on the packet, meaning that hacked / malicious clients may be trigerring this event very often and with unchecked parameters. Therefore plugin authors are advised to use extreme caution with this callback.

    Plugins may refuse the default processing for the packet, causing Cuberite to behave as if the packet has never arrived. This may, however, create inconsistencies in the client - the client may think that they broke a block, while the server didn't process the breaking, etc. For this reason, if a plugin refuses the processing, Cuberite sends the block specified in the packet back to the client (as if placed anew), if the status code specified a block-break action. For other actions, plugins must rectify the situation on their own.

    The client sends the left-click packet for several other occasions, such as dropping the held item (Q keypress) or shooting an arrow. This is reflected in the Status code. Consult the protocol documentation for details on the actions. ]], Params = { { Name = "Player", Type = "{{cPlayer}}", Notes = "The player whose client sent the packet" }, { Name = "BlockX", Type = "number", Notes = "X-coord of the block" }, { Name = "BlockY", Type = "number", Notes = "Y-coord of the block" }, { Name = "BlockZ", Type = "number", Notes = "Z-coord of the block" }, { Name = "BlockFace", Type = "number", Notes = "Face of the block upon which the player interacted. One of the BLOCK_FACE_ constants" }, { Name = "Action", Type = "number", Notes = "Action to be performed on the block (\"status\" in the protocol docs)" }, }, Returns = [[ If the function returns false or no value, Cuberite calls other plugins' callbacks and finally sends the packet for further processing.

    If the function returns true, no other plugins are called, processing is halted. If the action was a block dig, Cuberite sends the block specified in the coords back to the client. The packet is dropped. ]], }, -- HOOK_PLAYER_LEFT_CLICK } ================================================ FILE: Server/Plugins/APIDump/Hooks/OnPlayerMoving.lua ================================================ return { HOOK_PLAYER_MOVING = { CalledWhen = "Player tried to move in the tick being currently processed. Plugin may refuse movement.", DefaultFnName = "OnPlayerMoving", -- also used as pagename Desc = [[ This function is called in each server tick for each {{cPlayer|player}} that has sent any of the player-move packets. Plugins may refuse the movement. ]], Params = { { Name = "Player", Type = "{{cPlayer}}", Notes = "The player who has moved. The object already has the new position stored in it." }, { Name = "OldPosition", Type = "{{Vector3d}}", Notes = "The old position." }, { Name = "NewPosition", Type = "{{Vector3d}}", Notes = "The new position." }, { Name = "PreviousIsOnGround", Type = "{{boolean}}", Notes = "Specifies if the player was standing on a solid block." }, }, Returns = [[ If the function returns true, movement is prohibited.

    If the function returns false or no value, other plugins' callbacks are called and finally the new position is permanently stored in the cPlayer object.

    ]], }, -- HOOK_PLAYER_MOVING } ================================================ FILE: Server/Plugins/APIDump/Hooks/OnPlayerOpeningWindow.lua ================================================ return { HOOK_PLAYER_OPENING_WINDOW = { CalledWhen = "Called when a player is about to open a window", DefaultFnName = "OnPlayerOpeningWindow", -- also used as pagename Desc = [[ This hook is called when a player is about to open a window, e.g. when they click on a chest or a furnace. ]], Params = { { Name = "Player", Type = "{{cPlayer}}", Notes = "The player who is opening the window" }, { Name = "Window", Type = "{{cWindow}}", Notes = "The window that is being opened" }, }, Returns = [[ If the function returns false or no value, the next plugin's callback is called, and finally Cuberite will process the opening window. If the function returns true, no other callback is called for this event. ]], }, -- HOOK_PLAYER_OPENING_WINDOW } ================================================ FILE: Server/Plugins/APIDump/Hooks/OnPlayerPlacedBlock.lua ================================================ return { HOOK_PLAYER_PLACED_BLOCK = { CalledWhen = "After a player has placed a block. Notification only.", DefaultFnName = "OnPlayerPlacedBlock", -- also used as pagename Desc = [[ This hook is called after a {{cPlayer|player}} has placed a block in the {{cWorld|world}}. The block is already added to the world and the corresponding item removed from player's {{cInventory|inventory}}.

    Use the {{cPlayer}}:GetWorld() function to get the world to which the block belongs.

    See also the {{OnPlayerPlacingBlock|HOOK_PLAYER_PLACING_BLOCK}} hook for a similar hook called before the placement.

    If the client action results in multiple blocks being placed (such as a bed or a door), each separate block is reported through this hook. All the blocks are already present in the world before the first instance of this hook is called. ]], Params = { { Name = "Player", Type = "{{cPlayer}}", Notes = "The player who placed the block" }, { Name = "BlockX", Type = "number", Notes = "X-coord of the block" }, { Name = "BlockY", Type = "number", Notes = "Y-coord of the block" }, { Name = "BlockZ", Type = "number", Notes = "Z-coord of the block" }, { Name = "BlockType", Type = "BLOCKTYPE", Notes = "The block type of the block" }, { Name = "BlockMeta", Type = "NIBBLETYPE", Notes = "The block meta of the block" }, }, Returns = [[ If this function returns false or no value, Cuberite calls other plugins with the same event. If this function returns true, no other plugin is called for this event. ]], }, -- HOOK_PLAYER_PLACED_BLOCK } ================================================ FILE: Server/Plugins/APIDump/Hooks/OnPlayerPlacingBlock.lua ================================================ return { HOOK_PLAYER_PLACING_BLOCK = { CalledWhen = "Just before a player places a block. Plugin may override / refuse.", DefaultFnName = "OnPlayerPlacingBlock", -- also used as pagename Desc = [[ This hook is called just before a {{cPlayer|player}} places a block in the {{cWorld|world}}. The block is not yet placed, plugins may choose to override the default behavior or refuse the placement at all.

    Note that the client already expects that the block has been placed. For that reason, if a plugin refuses the placement, Cuberite sends the old block at the provided coords to the client.

    Use the {{cPlayer}}:GetWorld() function to get the world to which the block belongs.

    See also the {{OnPlayerPlacedBlock|HOOK_PLAYER_PLACED_BLOCK}} hook for a similar hook called after the placement.

    If the client action results in multiple blocks being placed (such as a bed or a door), each separate block is reported through this hook and only if all of them succeed, all the blocks are placed. If any one of the calls are refused by the plugin, all the blocks are refused and reverted on the client. ]], Params = { { Name = "Player", Type = "{{cPlayer}}", Notes = "The player who is placing the block" }, { Name = "BlockX", Type = "number", Notes = "X-coord of the block" }, { Name = "BlockY", Type = "number", Notes = "Y-coord of the block" }, { Name = "BlockZ", Type = "number", Notes = "Z-coord of the block" }, { Name = "BlockType", Type = "BLOCKTYPE", Notes = "The block type of the block" }, { Name = "BlockMeta", Type = "NIBBLETYPE", Notes = "The block meta of the block" }, }, Returns = [[ If this function returns false or no value, Cuberite calls other plugins with the same event and finally places the block and removes the corresponding item from player's inventory. If this function returns true, no other plugin is called for this event, Cuberite sends the old block at the specified coords to the client and drops the packet. ]], }, -- HOOK_PLAYER_PLACING_BLOCK } ================================================ FILE: Server/Plugins/APIDump/Hooks/OnPlayerRightClick.lua ================================================ return { HOOK_PLAYER_RIGHT_CLICK = { CalledWhen = "A right-click packet is received from the client. Plugin may override / refuse.", DefaultFnName = "OnPlayerRightClick", -- also used as pagename Desc = [[ This hook is called when Cuberite receives a right-click packet from the {{cClientHandle|client}}. It is called before any processing whatsoever is performed on the packet, meaning that hacked / malicious clients may be trigerring this event very often and with unchecked parameters. Therefore plugin authors are advised to use extreme caution with this callback.

    Plugins may refuse the default processing for the packet, causing Cuberite to behave as if the packet has never arrived. This may, however, create inconsistencies in the client - the client may think that they placed a block, while the server didn't process the placing, etc. ]], Params = { { Name = "Player", Type = "{{cPlayer}}", Notes = "The player whose client sent the packet" }, { Name = "BlockX", Type = "number", Notes = "X-coord of the block" }, { Name = "BlockY", Type = "number", Notes = "Y-coord of the block" }, { Name = "BlockZ", Type = "number", Notes = "Z-coord of the block" }, { Name = "BlockFace", Type = "number", Notes = "Face of the block upon which the player interacted. One of the BLOCK_FACE_ constants" }, { Name = "CursorX", Type = "number", Notes = "X-coord of the mouse crosshair on the block" }, { Name = "CursorY", Type = "number", Notes = "Y-coord of the mouse crosshair on the block" }, { Name = "CursorZ", Type = "number", Notes = "Z-coord of the mouse crosshair on the block" }, }, Returns = [[ If the function returns false or no value, Cuberite calls other plugins' callbacks and finally sends the packet for further processing.

    If the function returns true, no other plugins are called, processing is halted. ]], }, -- HOOK_PLAYER_RIGHT_CLICK } ================================================ FILE: Server/Plugins/APIDump/Hooks/OnPlayerRightClickingEntity.lua ================================================ return { HOOK_PLAYER_RIGHT_CLICKING_ENTITY = { CalledWhen = "A player has right-clicked an entity. Plugins may override / refuse.", DefaultFnName = "OnPlayerRightClickingEntity", -- also used as pagename Desc = [[ This hook is called when the {{cPlayer|player}} right-clicks an {{cEntity|entity}}. Plugins may override the default behavior or even cancel the default processing. ]], Params = { { Name = "Player", Type = "{{cPlayer}}", Notes = "The player who has right-clicked the entity" }, { Name = "Entity", Type = "{{cEntity}} descendant", Notes = "The entity that has been right-clicked" }, }, Returns = [[ If the functino returns false or no value, Cuberite calls other plugins' callbacks and finally does the default processing for the right-click. If the function returns true, no other callbacks are called and the default processing is skipped. ]], }, -- HOOK_PLAYER_RIGHT_CLICKING_ENTITY } ================================================ FILE: Server/Plugins/APIDump/Hooks/OnPlayerShooting.lua ================================================ return { HOOK_PLAYER_SHOOTING = { CalledWhen = "When the player releases the bow, shooting an arrow (other projectiles: unknown)", DefaultFnName = "OnPlayerShooting", -- also used as pagename Desc = [[ This hook is called when the {{cPlayer|player}} shoots their bow. It is called for the actual release of the {{cArrowEntity|arrow}}. FIXME: It is currently unknown whether other {{cProjectileEntity|projectiles}} (snowballs, eggs) trigger this hook.

    To get the player's position and direction, use the {{cPlayer}}:GetEyePosition() and cPlayer:GetLookVector() functions. Note that for shooting a bow, the position for the arrow creation is not at the eye pos, some adjustments are required. FIXME: Export the {{cPlayer}} function for this adjustment. ]], Params = { { Name = "Player", Type = "{{cPlayer}}", Notes = "The player shooting" }, }, Returns = [[ If the function returns false or no value, the next plugin's callback is called, and finally Cuberite creates the projectile. If the functino returns true, no other callback is called and no projectile is created. ]], }, -- HOOK_PLAYER_SHOOTING } ================================================ FILE: Server/Plugins/APIDump/Hooks/OnPlayerSpawned.lua ================================================ return { HOOK_PLAYER_SPAWNED = { CalledWhen = "After a player (re)spawns in the world to which they belong to.", DefaultFnName = "OnPlayerSpawned", -- also used as pagename Desc = [[ This hook is called after a {{cPlayer|player}} has spawned in the world. It is called after {{OnLogin|HOOK_LOGIN}} and {{OnPlayerJoined|HOOK_PLAYER_JOINED}}, after the player name has been authenticated, the initial worldtime, inventory and health have been sent to the player and the player spawn packet has been broadcast to all players near enough to the player spawn place. This is a notification-only event, plugins wishing to refuse player's entry should kick the player using the {{cPlayer}}:Kick() function.

    This hook is also called when the player respawns after death (and a respawn packet is received from the client, meaning the player has already clicked the Respawn button). ]], Params = { { Name = "Player", Type = "{{cPlayer}}", Notes = "The player who has (re)spawned" }, }, Returns = [[ If the function returns false or no value, other plugins' callbacks are called. If the function returns true, no other callbacks are called for this event. There is no overridable behavior. ]], }, -- HOOK_PLAYER_SPAWNED } ================================================ FILE: Server/Plugins/APIDump/Hooks/OnPlayerTossingItem.lua ================================================ return { HOOK_PLAYER_TOSSING_ITEM = { CalledWhen = "A player is tossing an item. Plugin may override / refuse.", DefaultFnName = "OnPlayerTossingItem", -- also used as pagename Desc = [[ This hook is called when a {{cPlayer|player}} has tossed an item. The {{cPickup|pickup}} has not been spawned yet. Plugins may disallow the tossing, but in that case they need to clean up - the player's client already thinks the item has been tossed so the {{cInventory|inventory}} needs to be re-sent to the player.

    To get the item that is about to be tossed, call the {{cPlayer}}:GetEquippedItem() function. ]], Params = { { Name = "Player", Type = "{{cPlayer}}", Notes = "The player tossing an item" }, }, Returns = [[ If the function returns false or no value, other plugins' callbacks are called and finally Cuberite creates the pickup for the item and tosses it, using {{cPlayer}}:TossHeldItem, {{cPlayer}}:TossEquippedItem, or {{cPlayer}}:TossPickup. If the function returns true, no other callbacks are called for this event and Cuberite doesn't toss the item. ]], }, -- HOOK_PLAYER_TOSSING_ITEM } ================================================ FILE: Server/Plugins/APIDump/Hooks/OnPlayerUsedBlock.lua ================================================ return { HOOK_PLAYER_USED_BLOCK = { CalledWhen = "A player has just used a block (chest, furnace...). Notification only.", DefaultFnName = "OnPlayerUsedBlock", -- also used as pagename Desc = [[ This hook is called after a {{cPlayer|player}} has right-clicked a block that can be used, such as a {{cChestEntity|chest}} or a lever. It is called after Cuberite processes the usage (sends the UI handling packets / toggles redstone). Note that for UI-related blocks, the player is most likely still using the UI. This is a notification-only event.

    Note that the block coords given in this callback are for the (solid) block that is being clicked, not the air block between it and the player.

    To get the world at which the right-click occurred, use the {{cPlayer}}:GetWorld() function.

    See also the {{OnPlayerUsingBlock|HOOK_PLAYER_USING_BLOCK}} for a similar hook called before the use, the {{OnPlayerUsingItem|HOOK_PLAYER_USING_ITEM}} and {{OnPlayerUsedItem|HOOK_PLAYER_USED_ITEM}} for similar hooks called when a player interacts with any block with a usable item in hand, such as a bucket. ]], Params = { { Name = "Player", Type = "{{cPlayer}}", Notes = "The player who used the block" }, { Name = "BlockX", Type = "number", Notes = "X-coord of the clicked block" }, { Name = "BlockY", Type = "number", Notes = "Y-coord of the clicked block" }, { Name = "BlockZ", Type = "number", Notes = "Z-coord of the clicked block" }, { Name = "BlockFace", Type = "number", Notes = "Face of clicked block which has been clicked. One of the BLOCK_FACE_ constants" }, { Name = "CursorX", Type = "number", Notes = "X-coord of the cursor crosshair on the block being clicked" }, { Name = "CursorY", Type = "number", Notes = "Y-coord of the cursor crosshair on the block being clicked" }, { Name = "CursorZ", Type = "number", Notes = "Z-coord of the cursor crosshair on the block being clicked" }, { Name = "BlockType", Type = "number", Notes = "Block type of the clicked block" }, { Name = "BlockMeta", Type = "number", Notes = "Block meta of the clicked block" }, }, Returns = [[ If the function returns false or no value, other plugins' callbacks are called. If the function returns true, no other callbacks are called for this event. ]], }, -- HOOK_PLAYER_USED_BLOCK } ================================================ FILE: Server/Plugins/APIDump/Hooks/OnPlayerUsedItem.lua ================================================ return { HOOK_PLAYER_USED_ITEM = { CalledWhen = "A player has used an item in hand (bucket...)", DefaultFnName = "OnPlayerUsedItem", -- also used as pagename Desc = [[ This hook is called after a {{cPlayer|player}} has right-clicked a block with an {{cItem|item}} that can be used (is not placeable, is not food and clicked block is not use-able), such as a bucket or a hoe. It is called after Cuberite processes the usage (places fluid / turns dirt to farmland). This is an information-only hook, there is no way to cancel the event anymore.

    Note that the block coords given in this callback are for the (solid) block that is being clicked, not the air block between it and the player.

    To get the world at which the right-click occurred, use the {{cPlayer}}:GetWorld() function. To get the item that the player is using, use the {{cPlayer}}:GetEquippedItem() function.

    See also the {{OnPlayerUsingItem|HOOK_PLAYER_USING_ITEM}} for a similar hook called before the use, the {{OnPlayerUsingBlock|HOOK_PLAYER_USING_BLOCK}} and {{OnPlayerUsedBlock|HOOK_PLAYER_USED_BLOCK}} for similar hooks called when a player interacts with a block, such as a chest. ]], Params = { { Name = "Player", Type = "{{cPlayer}}", Notes = "The player who used the item" }, { Name = "BlockX", Type = "number", Notes = "X-coord of the clicked block" }, { Name = "BlockY", Type = "number", Notes = "Y-coord of the clicked block" }, { Name = "BlockZ", Type = "number", Notes = "Z-coord of the clicked block" }, { Name = "BlockFace", Type = "number", Notes = "Face of clicked block which has been clicked. One of the BLOCK_FACE_ constants" }, { Name = "CursorX", Type = "number", Notes = "X-coord of the cursor crosshair on the block being clicked" }, { Name = "CursorY", Type = "number", Notes = "Y-coord of the cursor crosshair on the block being clicked" }, { Name = "CursorZ", Type = "number", Notes = "Z-coord of the cursor crosshair on the block being clicked" }, }, Returns = [[ If the function returns false or no value, other plugins' callbacks are called. If the function returns true, no other callbacks are called for this event. ]], }, -- HOOK_PLAYER_USED_ITEM } ================================================ FILE: Server/Plugins/APIDump/Hooks/OnPlayerUsingBlock.lua ================================================ return { HOOK_PLAYER_USING_BLOCK = { CalledWhen = "Just before a player uses a block (chest, furnace...). Plugin may override / refuse.", DefaultFnName = "OnPlayerUsingBlock", -- also used as pagename Desc = [[ This hook is called when a {{cPlayer|player}} has right-clicked a block that can be used, such as a {{cChestEntity|chest}} or a lever. It is called before Cuberite processes the usage (sends the UI handling packets / toggles redstone). Plugins may refuse the interaction by returning true.

    Note that the block coords given in this callback are for the (solid) block that is being clicked, not the air block between it and the player.

    To get the world at which the right-click occurred, use the {{cPlayer}}:GetWorld() function.

    See also the {{OnPlayerUsedBlock|HOOK_PLAYER_USED_BLOCK}} for a similar hook called after the use, the {{OnPlayerUsingItem|HOOK_PLAYER_USING_ITEM}} and {{OnPlayerUsedItem|HOOK_PLAYER_USED_ITEM}} for similar hooks called when a player interacts with any block with a usable item in hand, such as a bucket. ]], Params = { { Name = "Player", Type = "{{cPlayer}}", Notes = "The player who is using the block" }, { Name = "BlockX", Type = "number", Notes = "X-coord of the clicked block" }, { Name = "BlockY", Type = "number", Notes = "Y-coord of the clicked block" }, { Name = "BlockZ", Type = "number", Notes = "Z-coord of the clicked block" }, { Name = "BlockFace", Type = "number", Notes = "Face of clicked block which has been clicked. One of the BLOCK_FACE_ constants" }, { Name = "CursorX", Type = "number", Notes = "X-coord of the cursor crosshair on the block being clicked" }, { Name = "CursorY", Type = "number", Notes = "Y-coord of the cursor crosshair on the block being clicked" }, { Name = "CursorZ", Type = "number", Notes = "Z-coord of the cursor crosshair on the block being clicked" }, { Name = "BlockType", Type = "number", Notes = "Block type of the clicked block" }, { Name = "BlockMeta", Type = "number", Notes = "Block meta of the clicked block" }, }, Returns = [[ If the function returns false or no value, other plugins' callbacks are called and then Cuberite processes the interaction. If the function returns true, no other callbacks are called for this event and the block is treated like any other block (i.e. if it's possible to place a torch on, it will be placed, and so on.) ]], }, -- HOOK_PLAYER_USING_BLOCK } ================================================ FILE: Server/Plugins/APIDump/Hooks/OnPlayerUsingItem.lua ================================================ return { HOOK_PLAYER_USING_ITEM = { CalledWhen = "Just before a player uses an item in hand (bucket...). Plugin may override / refuse.", DefaultFnName = "OnPlayerUsingItem", -- also used as pagename Desc = [[ This hook is called when a {{cPlayer|player}} has right-clicked a block with an {{cItem|item}} that can be used (is not placeable, is not food and clicked block is not use-able), such as a bucket or a hoe. It is called before Cuberite processes the usage (places fluid / turns dirt to farmland). Plugins may refuse the interaction by returning true.

    Note that the block coords given in this callback are for the (solid) block that is being clicked, not the air block between it and the player.

    To get the world at which the right-click occurred, use the {{cPlayer}}:GetWorld() function. To get the item that the player is using, use the {{cPlayer}}:GetEquippedItem() function.

    See also the {{OnPlayerUsedItem|HOOK_PLAYER_USED_ITEM}} for a similar hook called after the use, the {{OnPlayerUsingBlock|HOOK_PLAYER_USING_BLOCK}} and {{OnPlayerUsedBlock|HOOK_PLAYER_USED_BLOCK}} for similar hooks called when a player interacts with a block, such as a chest. ]], Params = { { Name = "Player", Type = "{{cPlayer}}", Notes = "The player who is using the item" }, { Name = "BlockX", Type = "number", Notes = "X-coord of the clicked block" }, { Name = "BlockY", Type = "number", Notes = "Y-coord of the clicked block" }, { Name = "BlockZ", Type = "number", Notes = "Z-coord of the clicked block" }, { Name = "BlockFace", Type = "number", Notes = "Face of clicked block which has been clicked. One of the BLOCK_FACE_ constants" }, { Name = "CursorX", Type = "number", Notes = "X-coord of the cursor crosshair on the block being clicked" }, { Name = "CursorY", Type = "number", Notes = "Y-coord of the cursor crosshair on the block being clicked" }, { Name = "CursorZ", Type = "number", Notes = "Z-coord of the cursor crosshair on the block being clicked" }, }, Returns = [[ If the function returns false or no value, other plugins' callbacks are called and then Cuberite processes the interaction. If the function returns true, no other callbacks are called for this event and the interaction is silently dropped. ]], }, -- HOOK_PLAYER_USING_ITEM } ================================================ FILE: Server/Plugins/APIDump/Hooks/OnPluginMessage.lua ================================================ return { HOOK_PLUGIN_MESSAGE = { CalledWhen = "The server receives a plugin message from a client", DefaultFnName = "OnPluginMessage", -- also used as pagename Desc = [[ A plugin may implement an OnPluginMessage() function and register it as a Hook to process plugin messages from the players. The function is then called for every plugin message sent from any player. ]], Params = { { Name = "Client", Type = "{{cClientHandle}}", Notes = "The client who sent the plugin message" }, { Name = "Channel", Type = "string", Notes = "The channel on which the message was sent" }, { Name = "Message", Type = "string", Notes = "The message's payload" }, }, Returns = [[ If the function returns false or no value, other plugins' callbacks are called. If the function returns true, no other callbacks are called for this event. ]], }, -- HOOK_CHAT } ================================================ FILE: Server/Plugins/APIDump/Hooks/OnPluginsLoaded.lua ================================================ return { HOOK_PLUGINS_LOADED = { CalledWhen = "All the enabled plugins have been loaded", DefaultFnName = "OnPluginsLoaded", -- also used as pagename Desc = [[ This callback gets called when the server finishes loading and initializing plugins. This is the perfect occasion for a plugin to query other plugins through {{cPluginManager}}:GetPlugin() and possibly start communicating with them using the {{cPlugin}}:Call() function. ]], Params = {}, Returns = [[ The return value is ignored, all registered callbacks are called. ]], CodeExamples = { { Title = "CoreMessaging", Desc = [[ This example shows how to implement the CoreMessaging functionality - messages to players will be sent through the Core plugin, formatted by that plugin. As a fallback for when the Core plugin is not present, the messages are sent directly by this code, unformatted. ]], Code = [[ -- These are the fallback functions used when the Core is not present: local function SendMessageFallback(a_Player, a_Message) a_Player:SendMessage(a_Message); end local function SendMessageSuccessFallback(a_Player, a_Message) a_Player:SendMessage(a_Message); end local function SendMessageFailureFallback(a_Player, a_Message) a_Player:SendMessage(a_Message); end -- These three "variables" will hold the actual functions to call. -- By default they are initialized to the Fallback variants, -- but will be redirected to Core when all plugins load SendMessage = SendMessageFallback; SendMessageSuccess = SendMessageSuccessFallback; SendMessageFailure = SendMessageFailureFallback; -- The callback tries to connect to the Core -- If successful, overwrites the three functions with Core ones local function OnPluginsLoaded() local CorePlugin = cPluginManager:Get():GetPlugin("Core"); if (CorePlugin == nil) then -- The Core is not loaded, keep the Fallback functions return; end -- Overwrite the three functions with Core functionality: SendMessage = function(a_Player, a_Message) CorePlugin:Call("SendMessage", a_Player, a_Message); end SendMessageSuccess = function(a_Player, a_Message) CorePlugin:Call("SendMessageSuccess", a_Player, a_Message); end SendMessageFailure = function(a_Player, a_Message) CorePlugin:Call("SendMessageFailure", a_Player, a_Message); end end -- Global scope, register the callback: cPluginManager.AddHook(cPluginManager.HOOK_PLUGINS_LOADED, CoreMessagingPluginsLoaded); -- Usage, anywhere else in the plugin: SendMessageFailure( a_Player, "Cannot teleport to player, the destination player " .. PlayerName .. " was not found" ); ]], }, } , -- CodeExamples }, -- HOOK_PLUGINS_LOADED } ================================================ FILE: Server/Plugins/APIDump/Hooks/OnPostCrafting.lua ================================================ return { HOOK_POST_CRAFTING = { CalledWhen = "After the built-in recipes are checked and a recipe was found.", DefaultFnName = "OnPostCrafting", -- also used as pagename Desc = [[ This hook is called when a {{cPlayer|player}} changes contents of their {{cCraftingGrid|crafting grid}}, after the recipe has been established by Cuberite. Plugins may use this to modify the resulting recipe or provide an alternate recipe.

    If a plugin implements custom recipes, it should do so using the {{OnPreCrafting|HOOK_PRE_CRAFTING}} hook, because that will save the server from going through the built-in recipes. The HOOK_POST_CRAFTING hook is intended as a notification, with a chance to tweak the result.

    Note that this hook is not called if a built-in recipe is not found; {{OnCraftingNoRecipe|HOOK_CRAFTING_NO_RECIPE}} is called instead in such a case. ]], Params = { { Name = "Player", Type = "{{cPlayer}}", Notes = "The player who has changed their crafting grid contents" }, { Name = "Grid", Type = "{{cCraftingGrid}}", Notes = "The new crafting grid contents" }, { Name = "Recipe", Type = "{{cCraftingRecipe}}", Notes = "The recipe that Cuberite has decided to use (can be tweaked by plugins)" }, }, Returns = [[ If the function returns false or no value, other plugins' callbacks are called. If the function returns true, no other callbacks are called for this event. In either case, Cuberite uses the value of Recipe as the recipe to be presented to the player. ]], }, -- HOOK_POST_CRAFTING } ================================================ FILE: Server/Plugins/APIDump/Hooks/OnPreCrafting.lua ================================================ return { HOOK_PRE_CRAFTING = { CalledWhen = "Before the built-in recipes are checked.", DefaultFnName = "OnPreCrafting", -- also used as pagename Desc = [[ This hook is called when a {{cPlayer|player}} changes contents of their {{cCraftingGrid|crafting grid}}, before the built-in recipes are searched for a match by Cuberite. Plugins may use this hook to provide a custom recipe.

    If you intend to tweak built-in recipes, use the {{OnPostCrafting|HOOK_POST_CRAFTING}} hook, because that will be called once the built-in recipe is matched.

    Also note a third hook, {{OnCraftingNoRecipe|HOOK_CRAFTING_NO_RECIPE}}, that is called when Cuberite cannot find any built-in recipe for the given ingredients. ]], Params = { { Name = "Player", Type = "{{cPlayer}}", Notes = "The player who has changed their crafting grid contents" }, { Name = "Grid", Type = "{{cCraftingGrid}}", Notes = "The new crafting grid contents" }, { Name = "Recipe", Type = "{{cCraftingRecipe}}", Notes = "The recipe that Cuberite will use. Modify this object to change the recipe" }, }, Returns = [[ If the function returns false or no value, other plugins' callbacks are called and then Cuberite searches the built-in recipes. The Recipe output parameter is ignored in this case.

    If the function returns true, no other callbacks are called for this event and Cuberite uses the recipe stored in the Recipe output parameter. ]], }, -- HOOK_PRE_CRAFTING } ================================================ FILE: Server/Plugins/APIDump/Hooks/OnProjectileHitBlock.lua ================================================ return { HOOK_PROJECTILE_HIT_BLOCK = { CalledWhen = "A projectile hits a solid block.", DefaultFnName = "OnProjectileHitBlock", -- also used as pagename Desc = [[ This hook is called when a {{cProjectileEntity|projectile}} hits a solid block.. ]], Params = { { Name = "ProjectileEntity", Type = "{{cProjectileEntity}}", Notes = "The projectile that hit an entity." }, { Name = "BlockX", Type = "number", Notes = "The X-coord where the projectile hit." }, { Name = "BlockY", Type = "number", Notes = "The Y-coord where the projectile hit." }, { Name = "BlockZ", Type = "number", Notes = "The Z-coord where the projectile hit." }, { Name = "BlockFace", Type = "number", Notes = "The side of the block where the projectile hit." }, { Name = "BlockHitPos", Type = "Vector3d", Notes = "The exact position where the projectile hit." }, }, Returns = [[ If the function returns false or no value, the next plugin's callback is called. If the function returns true, no other callback is called for this event and the projectile flies through block.. ]], }, -- HOOK_PROJECTILE_HIT_BLOCK } ================================================ FILE: Server/Plugins/APIDump/Hooks/OnProjectileHitEntity.lua ================================================ return { HOOK_PROJECTILE_HIT_ENTITY = { CalledWhen = "A projectile hits another entity.", DefaultFnName = "OnProjectileHitEntity", -- also used as pagename Desc = [[ This hook is called when a {{cProjectileEntity|projectile}} hits another entity. ]], Params = { { Name = "ProjectileEntity", Type = "{{cProjectileEntity}}", Notes = "The projectile that hit an entity." }, { Name = "Entity", Type = "{{cEntity}}", Notes = "The entity wich was hit." }, }, Returns = [[ If the function returns false or no value, the next plugin's callback is called. If the function returns true, no other callback is called for this event and the projectile flies through the entity. ]], }, -- HOOK_PROJECTILE_HIT_ENTITY } ================================================ FILE: Server/Plugins/APIDump/Hooks/OnServerPing.lua ================================================ return { HOOK_SERVER_PING = { CalledWhen = "Client pings the server from the server list.", DefaultFnName = "OnServerPing", -- also used as pagename Desc = [[ A plugin may implement an OnServerPing() function and register it as a Hook to process pings from clients in the server server list. It can change the logged in players and player capacity, as well as the server description and the favicon, that are displayed to the client in the server list.

    The client handle already has its protocol version assigned to it, so the plugin can check that; however, there's no username associated with the client yet, and no player object. ]], Params = { { Name = "ClientHandle", Type = "{{cClientHandle}}", Notes = "The client handle that pinged the server" }, { Name = "ServerDescription", Type = "string", Notes = "The server description" }, { Name = "OnlinePlayersCount", Type = "number", Notes = "The number of players currently on the server" }, { Name = "MaxPlayersCount", Type = "number", Notes = "The current player cap for the server" }, { Name = "Favicon", Type = "string", Notes = "The base64 encoded favicon to be displayed in the server list for compatible clients" }, }, Returns = [[ The plugin can return whether to continue processing of the hook with other plugins, the server description to be displayed to the client, the currently online players, the player cap and the base64/png favicon data, in that order. ]], CodeExamples = { { Title = "Change information returned to the player", Desc = "Tells the client that the server description is 'test', there are one more players online than there actually are, and that the player cap is zero. It also changes the favicon data.", Code = [[ function OnServerPing(ClientHandle, ServerDescription, OnlinePlayers, MaxPlayers, Favicon) -- Change Server Description ServerDescription = "Test" -- Change online / max players OnlinePlayers = OnlinePlayers + 1 MaxPlayers = 0 -- Change favicon if cFile:IsFile("my-favicon.png") then local FaviconData = cFile:ReadWholeFile("my-favicon.png") if (FaviconData ~= "") and (FaviconData ~= nil) then Favicon = Base64Encode(FaviconData) end end return false, ServerDescription, OnlinePlayers, MaxPlayers, Favicon end ]], }, }, }, -- HOOK_SERVER_PING } ================================================ FILE: Server/Plugins/APIDump/Hooks/OnSpawnedEntity.lua ================================================ return { HOOK_SPAWNED_ENTITY = { CalledWhen = "After an entity is spawned in the world.", DefaultFnName = "OnSpawnedEntity", -- also used as pagename Desc = [[ This hook is called after the server spawns an {{cEntity|entity}}. This is an information-only callback, the entity is already spawned by the time it is called. If the entity spawned is a {{cMonster|monster}}, the {{OnSpawnedMonster|HOOK_SPAWNED_MONSTER}} hook is called before this hook.

    See also the {{OnSpawningEntity|HOOK_SPAWNING_ENTITY}} hook for a similar hook called before the entity is spawned. ]], Params = { { Name = "World", Type = "{{cWorld}}", Notes = "The world in which the entity has spawned" }, { Name = "Entity", Type = "{{cEntity}} descentant", Notes = "The entity that has spawned" }, }, Returns = [[ If the function returns false or no value, the next plugin's callback is called. If the function returns true, no other callback is called for this event. ]], }, -- HOOK_SPAWNED_ENTITY } ================================================ FILE: Server/Plugins/APIDump/Hooks/OnSpawnedMonster.lua ================================================ return { HOOK_SPAWNED_MONSTER = { CalledWhen = "After a monster is spawned in the world", DefaultFnName = "OnSpawnedMonster", -- also used as pagename Desc = [[ This hook is called after the server spawns a {{cMonster|monster}}. This is an information-only callback, the monster is already spawned by the time it is called. After this hook is called, the {{OnSpawnedEntity|HOOK_SPAWNED_ENTITY}} is called for the monster entity.

    See also the {{OnSpawningMonster|HOOK_SPAWNING_MONSTER}} hook for a similar hook called before the monster is spawned. ]], Params = { { Name = "World", Type = "{{cWorld}}", Notes = "The world in which the monster has spawned" }, { Name = "Monster", Type = "{{cMonster}} descendant", Notes = "The monster that has spawned" }, }, Returns = [[ If the function returns false or no value, the next plugin's callback is called. If the function returns true, no other callback is called for this event. ]], }, -- HOOK_SPAWNED_MONSTER } ================================================ FILE: Server/Plugins/APIDump/Hooks/OnSpawningEntity.lua ================================================ return { HOOK_SPAWNING_ENTITY = { CalledWhen = "Before an entity is spawned in the world.", DefaultFnName = "OnSpawningEntity", -- also used as pagename Desc = [[ This hook is called before the server spawns an {{cEntity|entity}}. The plugin can either modify the entity before it is spawned, or disable the spawning altogether. You can't disable the spawning if the entity is a player. If the entity spawning is a monster, the {{OnSpawningMonster|HOOK_SPAWNING_MONSTER}} hook is called before this hook.

    See also the {{OnSpawnedEntity|HOOK_SPAWNED_ENTITY}} hook for a similar hook called after the entity is spawned. ]], Params = { { Name = "World", Type = "{{cWorld}}", Notes = "The world in which the entity will spawn" }, { Name = "Entity", Type = "{{cEntity}} descentant", Notes = "The entity that will spawn" }, }, Returns = [[ If the function returns false or no value, the next plugin's callback is called. Finally, the server spawns the entity with whatever parameters have been set on the {{cEntity}} object by the callbacks. If the function returns true, no other callback is called for this event and the entity is not spawned. ]], }, -- HOOK_SPAWNING_ENTITY } ================================================ FILE: Server/Plugins/APIDump/Hooks/OnSpawningMonster.lua ================================================ return { HOOK_SPAWNING_MONSTER = { CalledWhen = "Before a monster is spawned in the world.", DefaultFnName = "OnSpawningMonster", -- also used as pagename Desc = [[ This hook is called before the server spawns a {{cMonster|monster}}. The plugins may modify the monster's parameters in the {{cMonster}} class, or disallow the spawning altogether. This hook is called before the {{OnSpawningEntity|HOOK_SPAWNING_ENTITY}} is called for the monster entity.

    See also the {{OnSpawnedMonster|HOOK_SPAWNED_MONSTER}} hook for a similar hook called after the monster is spawned. ]], Params = { { Name = "World", Type = "{{cWorld}}", Notes = "The world in which the entity will spawn" }, { Name = "Monster", Type = "{{cMonster}} descentant", Notes = "The monster that will spawn" }, }, Returns = [[ If the function returns false or no value, the next plugin's callback is called. Finally, the server spawns the monster with whatever parameters the plugins set in the cMonster parameter.

    If the function returns true, no other callback is called for this event and the monster won't spawn. ]], }, -- HOOK_SPAWNING_MONSTER } ================================================ FILE: Server/Plugins/APIDump/Hooks/OnTakeDamage.lua ================================================ return { HOOK_TAKE_DAMAGE = { CalledWhen = "An {{cEntity|entity}} is taking any kind of damage", DefaultFnName = "OnTakeDamage", -- also used as pagename Desc = [[ This hook is called when any {{cEntity}} descendant, such as a {{cPlayer|player}} or a {{cMonster|mob}}, takes any kind of damage. The plugins may modify the amount of damage or effects with this hook by editting the {{TakeDamageInfo}} object passed.

    This hook is called after the final damage is calculated, including all the possible weapon {{cEnchantments|enchantments}}, armor protection and potion effects. ]], Params = { { Name = "Receiver", Type = "{{cEntity}} descendant", Notes = "The entity taking damage" }, { Name = "TDI", Type = "{{TakeDamageInfo}}", Notes = "The damage type, cause and effects. Plugins may modify this object to alter the final damage applied." }, }, Returns = [[ If the function returns false or no value, other plugins' callbacks are called and then the server applies the final values from the TDI object to Receiver. If the function returns true, no other callbacks are called, and no damage nor effects are applied. ]], }, -- HOOK_TAKE_DAMAGE } ================================================ FILE: Server/Plugins/APIDump/Hooks/OnTick.lua ================================================ return { HOOK_TICK = { CalledWhen = "Every server tick (approximately 20 times per second)", DefaultFnName = "OnTick", -- also used as pagename Desc = [[ This hook is called every game tick (50 msec, or 20 times a second). If the server is overloaded, the interval is larger, which is indicated by the TimeDelta parameter.

    This hook is called in the context of the server-tick thread, that is, the thread that takes care of {{cClientHandle|client connections}} before they're assigned to {{cPlayer|player entities}}, and processing console commands. ]], Params = { { Name = "TimeDelta", Type = "number", Notes = "The number of milliseconds elapsed since the last server tick. Will not be less than 50 msec." }, }, Returns = [[ If the function returns false or no value, other plugins' callbacks are called. If the function returns true, no other callbacks are called. There is no overridable behavior. ]], }, -- HOOK_TICK } ================================================ FILE: Server/Plugins/APIDump/Hooks/OnUpdatedSign.lua ================================================ return { HOOK_UPDATED_SIGN = { CalledWhen = "After the sign text is updated. Notification only.", DefaultFnName = "OnUpdatedSign", -- also used as pagename Desc = [[ This hook is called after a sign has had its text updated. The text is already updated at this point.

    The update may have been caused either by a {{cPlayer|player}} directly updating the sign, or by a plugin changing the sign text using the API.

    See also the {{OnUpdatingSign|HOOK_UPDATING_SIGN}} hook for a similar hook called before the update, with a chance to modify the text. ]], Params = { { Name = "World", Type = "{{cWorld}}", Notes = "The world in which the sign resides" }, { Name = "BlockX", Type = "number", Notes = "X-coord of the sign" }, { Name = "BlockY", Type = "number", Notes = "Y-coord of the sign" }, { Name = "BlockZ", Type = "number", Notes = "Z-coord of the sign" }, { Name = "Line1", Type = "string", Notes = "1st line of the new text" }, { Name = "Line2", Type = "string", Notes = "2nd line of the new text" }, { Name = "Line3", Type = "string", Notes = "3rd line of the new text" }, { Name = "Line4", Type = "string", Notes = "4th line of the new text" }, { Name = "Player", Type = "{{cPlayer}}", Notes = "The player who is changing the text. May be nil for non-player updates." } }, Returns = [[ If the function returns false or no value, other plugins' callbacks are called. If the function returns true, no other callbacks are called. There is no overridable behavior. ]], }, -- HOOK_UPDATED_SIGN } ================================================ FILE: Server/Plugins/APIDump/Hooks/OnUpdatingSign.lua ================================================ return { HOOK_UPDATING_SIGN = { CalledWhen = "Before the sign text is updated. Plugin may modify the text / refuse.", DefaultFnName = "OnUpdatingSign", -- also used as pagename Desc = [[ This hook is called when a sign text is about to be updated, either as a result of player's manipulation or any other event, such as a plugin setting the sign text. Plugins may modify the text or refuse the update altogether.

    See also the {{OnUpdatedSign|HOOK_UPDATED_SIGN}} hook for a similar hook called after the update. ]], Params = { { Name = "World", Type = "{{cWorld}}", Notes = "The world in which the sign resides" }, { Name = "BlockX", Type = "number", Notes = "X-coord of the sign" }, { Name = "BlockY", Type = "number", Notes = "Y-coord of the sign" }, { Name = "BlockZ", Type = "number", Notes = "Z-coord of the sign" }, { Name = "Line1", Type = "string", Notes = "1st line of the new text" }, { Name = "Line2", Type = "string", Notes = "2nd line of the new text" }, { Name = "Line3", Type = "string", Notes = "3rd line of the new text" }, { Name = "Line4", Type = "string", Notes = "4th line of the new text" }, { Name = "Player", Type = "{{cPlayer}}", Notes = "The player who is changing the text. May be nil for non-player updates." } }, Returns = [[ The function may return up to five values. If the function returns true as the first value, no other callbacks are called for this event and the sign is not updated. If the function returns no value or false as its first value, other plugins' callbacks are called.

    The other up to four values returned are used to update the sign text, line by line, respectively. Note that other plugins may again update the texts (if the first value returned is false). ]], CodeExamples = { { Title = "Add player signature", Desc = "The following example appends a player signature to the last line, if the sign is updated by a player:", Code = [[ function OnUpdatingSign(World, BlockX, BlockY, BlockZ, Line1, Line2, Line3, Line4, Player) if (Player == nil) then -- Not changed by a player return false; end -- Sign with playername, allow other plugins to interfere: return false, Line1, Line2, Line3, Line4 .. Player:GetName(); end ]], } } , }, -- HOOK_UPDATING_SIGN } ================================================ FILE: Server/Plugins/APIDump/Hooks/OnWeatherChanged.lua ================================================ return { HOOK_WEATHER_CHANGED = { CalledWhen = "The weather has changed", DefaultFnName = "OnWeatherChanged", -- also used as pagename Desc = [[ This hook is called after the weather has changed in a {{cWorld|world}}. The new weather has already been sent to the clients.

    See also the {{OnWeatherChanging|HOOK_WEATHER_CHANGING}} hook for a similar hook called before the change. ]], Params = { { Name = "World", Type = "{{cWorld}}", Notes = "World for which the weather has changed" }, }, Returns = [[ If the function returns false or no value, the next plugin's callback is called. If the function returns true, no other callback is called for this event. There is no overridable behavior. ]], }, -- HOOK_WEATHER_CHANGED } ================================================ FILE: Server/Plugins/APIDump/Hooks/OnWeatherChanging.lua ================================================ return { HOOK_WEATHER_CHANGING = { CalledWhen = "The weather is about to change", DefaultFnName = "OnWeatherChanging", -- also used as pagename Desc = [[ This hook is called when the current weather has expired and a new weather is selected. Plugins may override the new weather being set.

    The new weather setting is sent to the clients only after this hook has been processed.

    See also the {{OnWeatherChanged|HOOK_WEATHER_CHANGED}} hook for a similar hook called after the change. ]], Params = { { Name = "World", Type = "{{cWorld}}", Notes = "World for which the weather is changing" }, { Name = "Weather", Type = "number", Notes = "The newly selected weather. One of wSunny, wRain, wStorm" }, }, Returns = [[ The hook handler can return up to two values. If the first value is false or not present, the server calls other plugins' callbacks and finally sets the weather. If it is true, the server doesn't call any more callbacks for this hook. The second value returned is used as the new weather. If no value is given, the weather from the parameters is used as the weather. Returning false as the first value and a specific weather constant as the second value makes the server call the rest of the hook handlers with the new weather value. ]], }, -- HOOK_WEATHER_CHANGING } ================================================ FILE: Server/Plugins/APIDump/Hooks/OnWorldStarted.lua ================================================ return { HOOK_WORLD_STARTED = { CalledWhen = "A {{cWorld|world}} is initialized", DefaultFnName = "OnWorldStarted", -- also used as pagename Desc = [[ This hook is called whenever a {{cWorld|world}} is initialized. ]], Params = { { Name = "World", Type = "{{cWorld}}", Notes = "World that is started" }, }, Returns = [[ If the function returns false or no value, the next plugin's callback is called. If the function returns true, no other callback is called for this event. There is no overridable behavior. ]], }, -- HOOK_WORLD_STARTED } ================================================ FILE: Server/Plugins/APIDump/Hooks/OnWorldTick.lua ================================================ return { HOOK_WORLD_TICK = { CalledWhen = "Every world tick (about 20 times per second), separately for each world", DefaultFnName = "OnWorldTick", -- also used as pagename Desc = [[ This hook is called for each {{cWorld|world}} every tick (50 msec, or 20 times a second). If the world is overloaded, the interval is larger, which is indicated by the TimeDelta parameter.

    This hook is called in the world's tick thread context and thus has access to all world data guaranteed without blocking. ]], Params = { { Name = "World", Type = "{{cWorld}}", Notes = "World that is ticking" }, { Name = "TimeDelta", Type = "number", Notes = "The number of milliseconds since the previous game tick. Will not be less than 50 msec" }, }, Returns = [[ If the function returns false or no value, the next plugin's callback is called. If the function returns true, no other callback is called for this event. There is no overridable behavior. ]], }, -- HOOK_WORLD_TICK } ================================================ FILE: Server/Plugins/APIDump/InfoFile.html ================================================ Cuberite - Info.lua file

    Info.lua file

    Contents


    Introduction

    For a long time Cuberite plugins were plagued by poor documentation. The plugins worked, people who wrote them knew how to use them, but for anyone new to the plugin it was a terrible ordeal learning how to use it. Most of the times, the plugin authors only wrote what commands the plugin supported, sometimes not even that. Then, there was a call to action to put an end to this, to make documenting the plugins easy and at the same time centralized. Thus, the Info.lua file was born.

    Most plugins have some parts that are the same across all the plugins. These are commands, console commands and their permissions. If a plugin implemented a command, it would practically copy & paste the same code over and over again. So it makes sense to extract only unique information, centralize it and automate all the parts around it. This was another reason for the Info.lua file - it is a central hub of commands, console commands and their permissions.

    Last, but not least, we want to make a plugin repository on the web in the future, a repository that would store plugins, their descriptions, comments. It makes sense that the centralized information can be parsed by the repository automatically, so that advanced things, such as searching for a plugin based on a command, or determining whether two plugins collide command-wise, are possible.

    A tool has been written that allows for an easy generation of the documentation for the plugin in various formats. It outputs the documentation in a format that is perfect for pasting into the forum. It generates documentation in a Markup format to use in README.md on GitHub and similar sites. The clever thing is that you don't need to keep all those formats in sync manually - you edit the Info.lua file and this tool will re-generate the documentation for you.
    To generate documentation for the plugin, activate the DumpInfo plugin on a cuberite server with your plugin installed, and use the webadmin interface to "Dump" the plugin information. This will create a README.md suitable for uploading to your git repo, and a forum_info.txt, which can be copy-pasted into a forum post.

    So to sum up, the Info.lua file contains the plugins' commands, console commands, their permissions and possibly the overall plugin documentation, in a structured manner that can be parsed by a program, yet is human readable and editable.


    The overall structure

    The file consist of a declaration of a single Lua table, g_PluginInfo. This table contains all the information, structured, as its members. Each member can be a structure by itself. The entire file is a valid Lua source file, so any tool that syntax-checks Lua source can syntax-check this file. The file is somewhat forward- and backward- compatible, in the sense that it can be extended in any way without breaking.

    Here's a skeleton of the file:

    g_PluginInfo =
    {
    	Name = "Example Plugin",
    	Date = "2014-06-12",
    	Description = "This is an example plugin that shows how to use the Info.lua file",
    
    	-- The following members will be documented in greater detail later:
    	AdditionalInfo = {},
    	Commands = {},
    	ConsoleCommands = {},
    	Permissions = {},
    	Categories = {},
    }
    

    As you can see, the structure is pretty straightforward. Note that the order of the elements inside the table is not important (Lua property).

    The first few elements are for book-keeping. They declare the plugin's name, the date in ISO-format, representing the version of the plugin, and the description. The idea is that the description sums up what the plugin is all about, within some two or three sentences.


    AdditionalInfo table

    This table is used for more detailed description of the plugin. If there is any non-trivial setup process, dependencies, describe them here. This is where the description should get detailed. Don't worry about using several paragraphs of text here, if it makes the plugin easier to understand.

    The table should have the following layout:

    AdditionalInfo =
    {
    	{
    		Title = "Chapter 1",
    		Contents = "Describe one big aspect of the plugin here",
    	},
    	{
    		Title = "Chapter 2",
    		Contents = "Describe another big topic",
    	},
    }
    

    The idea here is that the tool that is used to generate the documentation from the Info.lua file will create a linkified table of contents and then each of the information elements' contents. This information should be all that is needed to successfully configure, run and manage the plugin.


    Commands table

    The commands table lists all the commands that the plugin implements, together with their handler functions, required permissions, help strings and further information. The table supports recursion, which allows plugins to create multi-word commands easily (such as "//schematic load" and "//schematic save"), each having its own separate handler.

    The table uses structure similar to the following:

    Commands =
    {
    	["/cmd1"] =
    	{
    		HelpString = "Performs the first action",
    		Permission = "firstplugin.cmds.1",
    		Alias = "/c1",
    		Handler = HandleCmd1,
    		ParameterCombinations =
    		{
    			{
    				Params = "x y z",
    				Help = "Performs the first action at the specified coordinates",
    			},
    			{
    				Params = "-p",
    				Help = "Performs the first action at the player's coordinates",
    			}
    		},
    	},
    	["/cmd2"] =
    	{
    		Alias = {"/c2", "//c2" },
    		Category = "Something",
    		Subcommands =
    		{
    			sub1 =  -- This declares a "/cmd2 sub1" command
    			{
    				HelpString = "Performs the second action's first subcommand",
    				Permission = "firstplugin.cmds.2.1",
    				Alias = "1",
    				Handler = HandleCmd2Sub1,
    				ParameterCombinations =
    				{
    					{
    						Params = "x y z",
    						Help = "Performs the second action's first subcommand at the specified coordinates",
    					},
    					{
    						Params = "-p",
    						Help = "Performs the second action's first subcommand at the player's coordinates",
    					}
    				},
    			},
    			sub2 =  -- Declares a "/cmd2 sub2" command
    			{
    				HelpString = "Performs the second action's second subcommand",
    				Permission = "firstplugin.cmds.2.2",
    				Handler = HandleCmd2Sub2,
    			},
    		},
    	},
    }
    

    Although it may seem overwhelming at first, there is a "method to this madness". Each element of the Commands table defines one command. Most commands start with a slash, so the special Lua syntax for table elements with non-standard names needs to be applied (["/cmd1"] =). The command can either specify subcommands, or a handler function (specifying both is UndefinedBehavior). Subcommands uses the same structure as the entire Commands table, recursively.

    The permission element specifies that the command is only available with the specified permission. Note that the permission for subcommand's parent isn't checked when the subcommand is called. This means that specifying the permission for a command that has subcommands has no effect whatsoever, but is discouraged because we may add processing for that in the future.

    The optional Categories table provides descriptions for command categories in the generated documentation. The documentation generator will group the commands by their specified Category ("General" by default) and each category will have the specified description written to it.

    The ParameterCombinations table is used only for generating the documentation, it lists the various combinations of parameters that the command supports. It's worth specifying even if the command supports only one combination, because that combination will get documented this way.

    The Alias member specifies any possible aliases for the command. Each alias is registered separately and if there is a subcommand table, it is applied to all aliases, just as one would expect. You can specify either a single string as the value (if there's only one alias), or a table of strings for multiple aliases. Commands with no aliases do not need to specify this member at all.


    ConsoleCommands table

    This table serves a purpose similar to that of the Commands table, only these commands are provided for the server console. Therefore, there are no permissions specified for these commands. Since most console commands don't use a leading slash, the command names don't need the special syntax. Also, the handler function doesn't receive the Player parameter.

    Here's an example of a ConsoleCommands table:

    ConsoleCommands =
    {
    	concmd =
    	{
    		HelpString = "Performs the console action",
    		Subcommands =
    		{
    			sub1 =
    			{
    				HelpString = "Performs the console action's first subcommand",
    				Handler = HandleConCmdSub1,
    				ParameterCombinations =
    				{
    					{
    						Params = "x y z",
    						Help = "Performs the console action's first subcommand at the specified coordinates",
    					},
    				},
    			},
    			sub2 =
    			{
    				HelpString = "Performs the console action's second subcommand",
    				Handler = HandleConCmdSub2,
    			},
    		},
    	},
    }
    

    Permissions table

    The purpose of this table is to document permissions that the plugin uses. The documentation generator automatically collects the permissions specified in the Command table; the Permissions table adds a description for these permissions and may declare other permissions that aren't specifically included in the Command table.

    Permissions =
    {
    	["firstplugin.cmd.1.1"] =
    	{
    		Description = "Allows the players to build high towers using the first action.",
    		RecommendedGroups = "players",
    	},
    	["firstplugin.cmd.2.1"] =
    	{
    		Description = "Allows the players to kill entities using the second action. Note that this may be misused to kill other players, too.",
    		RecommendedGroups = "admins, mods",
    	},
    }
    

    The RecommendedGroup element lists, in plain English, the intended groups for which the permission should be enabled on a typical server. Plugin authors are advised to create reasonable defaults, prefering security to openness, so that admins using these settings blindly don't expose their servers to malicious users.


    Categories

    The optional Categories table provides descriptions for categories in the generated documentation. Commands can have categories with or without category descriptions in this table. The documentation generator will output a table of listed categories along with their description.

    Categories = 
    {
    	General =
    	{
    		Description = "A general, yet somehow vague description of the default category."
    	},
    	Something =
    	{
    		Description = "Some descriptive words which form sentences pertaining to this set of commands use and goals."
    	},
    },
    

    Using the file in code

    Just writing the Info.lua file and saving it to the plugin folder is not enough for it to actually be used. Your plugin needs to include the following boilerplate code, preferably in its Initialize() function:

    -- Use the InfoReg shared library to process the Info.lua file:
    dofile(cPluginManager:GetPluginsPath() .. "/InfoReg.lua")
    RegisterPluginInfoCommands()
    RegisterPluginInfoConsoleCommands()
    

    Of course, if your plugin doesn't have any console commands, it doesn't need to call the RegisterPluginInfoConsoleCommands() function, and similarly if it doesn't have any in-game commands, it doesn't need to call the RegisterPluginInfoCommands() function.


    Examples

    There are several plugins that already implement this approach. You can visit them for inspiration and to see what the generated documentation looks like:

    ================================================ FILE: Server/Plugins/APIDump/LICENSE-prettify.txt ================================================ Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS Copyright 2011 Mike Samuel et al Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ================================================ FILE: Server/Plugins/APIDump/SettingUpDecoda.html ================================================ Cuberite - Setting up Decoda

    Setting up the Decoda IDE

    This article will explain how to set up Decoda, an IDE for writing Lua code, so that you can develop Cuberite plugins with the comfort of an IDE.

    About Decoda

    To quickly introduce Decoda, it is an IDE for writing Lua code. It has the basic features expected of an IDE - you can group files into project, you can edit multiple files in a tabbed editor, the code is syntax-highlighted. Code completion, symbol browsing, and more. It also features a Lua debugger that allows you to debug your Lua code within any application that embeds the Lua runtime or uses Lua as a dynamic-link library (DLL). Although it is written using the multiplatform WxWidgets toolkit, it hasn't yet been ported to any platform other than 32-bit Windows. This unfortunately means that Linux users will not be able to use it. It can be used on 64-bit Windows, but the debugger only works for 32-bit programs.

    Here's a screenshot of a default Decoda window with the debugger stepping through the code (scaled down):

    As you can see, you can set breakpoints in the code, inspect variables' values, view both the Lua and native (C++) call-stacks. Decoda also breaks program execution when a faulty Lua script is executed, providing a detailed error message and pointing you directly to the faulting code. It is even possible to attach a C++ debugger to a process that is being debugged by Decoda, this way you can trap both C++ and Lua errors.

    Decoda is open-source, the sources are on GitHub: https://github.com/unknownworlds/decoda. You can download a compiled binary from the creators' site, https://unknownworlds.com/decoda/.

    Project management

    To begin using Decoda, you need to create a project, or load an existing one. Decoda projects have a .deproj extension, and are simply a list of Lua files that are to be opened. You can create a project through menu Project -> New Project. Save your project first, so that Decoda knows what relative paths to use for the files. Then either add existing Lua files or create new one, through menu Project -> Add Add New File / Add Existing File.

    Next you need to set up the executable that Decoda will run when debugging your files. Select menu Project -> Settings. A new dialog will open:

    In the debugging section, fill in the full path to Cuberite.exe, or click the triple-dot button to browse for the file. Note that the Working directory will be automatically filled in for you with the folder where the executable is (until the last backslash). This is how it's supposed to work, don't change it; if it for some reason doesn't update, copy and paste the folder name from the Command edit box. All done, you can close this dialog now.

    Debugging

    You are now ready to debug your code. Before doing that, though, don't forget to save your project file. If you haven't done so already, enable your plugin in the settings.ini file. If you want the program to break at a certain line, it is best to set the breakpoint before starting the program. Set the cursor on the line and hit F9 (or use menu Debug -> Toggle Breakpoint) to toggle a breakpoint on that line. Finally, hit F5, or select menu Debug -> Start to launch Cuberite under the debugger. The Cuberite window comes up and loads your plugin. If Decoda displays the Project Settings dialog instead, you haven't set up the executable to run, see the Project management section for instructions.

    At this point you will see that Decoda starts adding new items to your project. All the files for all plugins are added temporarily. Don't worry, they are only temporary, they will be removed again once the debugging session finishes. You can tell the temporary files from the regular files by their icon, it's faded out. Decoda handles all the files that Cuberite loads, so you can actually debug any of those faded files, too.

    If there's an error in the code, the Decoda window will flash and a dialog box will come up, describing the error and taking you to the line where it occured. Note that the execution is paused in the thread executing the plugin, so until you select Debug -> Continue from the menu (F5), Cuberite won't be fully running. You can fix the error and issue a "reload" command in Cuberite console to reload the plugin code anew (Cuberite doesn't detect changes in plugin code automatically).

    If the execution hits a breakpoint, the Decoda window will flash and a yellow arrow is displayed next to the line. You can step through the code using F10 and F11, just like in MSVS. You can also use the Watch window to inspect variable values, or simply hover your mouse over a variable to display its value in the tooltip.

    Limitations

    So far everything seems wonderful. Unfortunately, it doesn't always go as easy. There are several limits to what Decoda can do:

    • When the program encounters a logical bug (using a nil value, calling a non-existent function etc.), Decoda will break, but usually the Watch window and the tooltips are showing nonsense values. You shouldn't trust them in such a case, if you kep running into such a problem regularly, put console logging functions (LOG) in the code to print out any info you need prior to the failure.
    • Sometimes breakpoints just don't work. This is especially true if there are multiple plugins that have files of the same name. Breakpoints will never work after changing the code and reloading the plugin in Cuberite; you need to stop the server and start again to reenable breakpoints.
    • Most weirdly, sometimes Decoda reports an error, but instead of opening the current version of the file, opens up another window with old contents of the file. Watch for this, because you could overwrite your new code if you saved this file over your newer file. Fortunately enough, Decoda will always ask you for a filename before saving such a file.
    • Decoda stores the project in two files. The .deproj file has the file list, and should be put into version control systems. The .deuser file has the settings (debugged application etc.) and is per-user specific. This file shouldn't go to version control systems, because each user may have different paths for the debuggee.
    • Unfortunately for us Windows users, the Decoda project file uses Unix-lineends (CR only). This makes it problematic when checking the file into a version control system, since those usually expect windows (CRLF) lineends; I personally convert the lineends each time I edit the project file using TED Notepad.
    ================================================ FILE: Server/Plugins/APIDump/SettingUpLuaLanguageServer.html ================================================ Cuberite - Setting up the Lua-Language-Server (VSCode)

    Setting up the Lua-Language-Server (VSCode)

    This article will explain how to configure an IDE that is able to use the Lua-Language-Server. This article will show how it's done using Visual Studio Code, but it should work with any IDE that supports language servers.

    About Language Servers

    IDE's in the past always implemented every programming language they supported on their own, it was baked in. Because of this everyone supported different features. With language servers this all changes. A single language server can be created with a community which can be shared across any number of IDE's which support the protocol. To learn more about language servers and IDE's that support them see langserver.org

    First-time setup

    Visual Studio Code doesn't support Lua by default. Instead it has a marketplace where extensions can be downloaded from. In this example we're going to use the Lua extension by Sumneko who also created the language server.

    Libraries

    The extension doesn't know the Cuberite API by default. The extension, or rather the language server, supports the inclusion of libraries. In order to generate the definitions required by the language server you have to activate the APIDump plugin in Cuberite which is included by default but not enabled. When the plugin is enabled the entire API can be exported by using the 'api' command in the console. Once this has completed there is a new folder next to the Cuberite executable called LLS.

    In order to use these definition files you need to create a settings.json file in the plugin folder you're developing for. This file should be in a folder called '.vscode'. If it doesn't exist yet you have to create it yourself. There are two important settings to configure:

    • Lua.runtime.version which has to be set to "Lua 5.1". Cuberite only supports Lua 5.1.
    • Lua.workspace.library which is an array containing all libraries used in the project. In this case it needs to point to the newly generated definition files. If you're developing your plugin using the same Cuberite instance as where you generated the definitions using the APIDump plugin you can set this to "../../LLS/cuberite/library". If your definitions are on a different location you will have to point to it yourself. Absolute paths are also supported.

    After configuring your settings.json file would something like this:

    After saving the settings.json file the IDE should recognize Cuberite's API.

    ================================================ FILE: Server/Plugins/APIDump/SettingUpZeroBrane.html ================================================ Cuberite - Setting up ZeroBrane Studio

    Setting up the ZeroBrane Studio IDE

    This article will explain how to set up ZeroBrane Studio, an IDE for writing Lua code, so that you can develop Cuberite plugins with the comfort of an IDE.

    About ZeroBrane Studio

    To quickly introduce ZeroBrane Studio, it is an IDE for writing Lua code. It has the basic features expected of an IDE - it allows you to manage groups of files as a project, you can edit multiple files in a tabbed editor, the code is syntax-highlighted. Code completion, symbol browsing, and more. It also features a Lua debugger that allows you to debug your Lua code within any application that uses Lua and can load Lua packages. It is written using the multiplatform WxWidgets toolkit, and runs on multiple platforms, including Windows, Linux and MacOS.

    Here's a screenshot of a default ZBS window with the debugger stepping through the code (scaled down):

    As you can see, you can set breakpoints in the code, inspect variables' values, view the Lua call-stacks.

    ZBS is open-source, the sources are on GitHub: https://github.com/pkulchenko/ZeroBraneStudio. The project's homepage is at https://studio.zerobrane.com/.

    First-time setup

    Since ZBS is a universal Lua IDE, you need to first set it up so that it is ready for Cuberite plugin development. For that, you need to download one file, cuberite.lua from the ZBS's plugin repository. Place that file in the "packages" folder inside your ZBS's folder. Note that there are other useful plugins in the repository and you may want to have a look there later on to further customize your ZBS. To install them, simply save them into the same folder.

    Next you should install the code-completion support specific for Cuberite. You should repeat this step from time to time, because the API evolves in time so new functions and classes are added to it quite often. You should have an APIDump plugin in your Cuberite installation. Enable the APIDump plugin in the server settings, it's very cheap to keep it enabled and it doesn't cost any performance during normal gameplay. To generate the code-completion support file, enter the api command into the server console. This will create a new file, "cuberite_api.lua", next to the Cuberite executable. Move that file into the "api/lua" subfolder inside your ZBS's folder. (Note that if you had the "mcserver_api.lua" file from previous versions, you should remove it)

    After you download the cuberite.lua file and install the completion support, you need to restart ZBS in order for the plugin to load. If there are no errors, you should see two new items in the Project -> Lua Interpreter submenu: "Cuberite - debug mode" and "Cuberite - release mode". The only difference between the two is which filename they use to launch Cuberite - cuberite_debug(.exe) for the debug option and "cuberite(.exe)" for the release option. If you built your own Cuberite executable and you built it in debug mode, you should select the debug mode option. In all other cases, including if you downloaded the already-compiled Cuberite executable from the internet, you should select the release mode option.

    For a first time user, it might be a bit overwhelming that there are no GUI settings in the ZBS, yet the IDE is very configurable. There are two files that you edit in order to change settings, either system-wide (all users of the computer share those settings) or user-wide (the settings are only for a specific user of the computer). Those files are regular Lua sources and you can quickly locate them and edit them from within the IDE itself, select Edit -> Preferences -> Settings: XYZ from the menu, with XYZ being either System or User.

    There is a documentation on most of the settings on ZBS's webpage, have a look at https://studio.zerobrane.com/documentation.html, especially the Preferences section. Personally I recommend setting editor.usetabs to true and possibly adjusting the editor.tabwidth, turn off the editor.smartindent feature and for debugging the option debugger.alloweditting should be set to true unless you feel like punishing yourself.

    Project management

    ZBS works with projects, it considers all files and subfolder in a specific folder to be a project. There's no need for a special project file nor for adding individual files to the workspace, all files are added automatically. To open a Cuberite plugin as the project, click the triple-dot button in the Project pane, or select Project -> Project directory -> Choose... from the menu. Browse and select the Cuberite plugin's folder. ZBS will load all the files in the plugin's folder and you can start editting code.

    Note that although ZBS allows you to work with subfolders in your plugins (and you should, especially with larger plugins), the current Cuberite ZBS plugin will not be able to start debugging unless you have a file open in the editor that is at the root level of the Cuberite plugin's folder.

    Debugging

    You are now ready to debug your code. Before doing that, though, don't forget to save your project files. If you haven't done so already, enable your plugin in the settings.ini file. If you want the program to break at a certain line, it is best to set the breakpoint before starting the program. Set the cursor on the line and hit F9 (or use menu Project -> Toggle Breakpoint) to toggle a breakpoint on that line. Finally, hit F5, or select menu Project -> Start Debugging to launch Cuberite under the debugger. The Cuberite window comes up and loads your plugin. If the window doesn't come up, inspect the Output pane in ZBS, there are usually two reasons for failure:

    • Your code in the currently open file has a hard syntax error. These are reported as "Compilation error" in the Output pane, double-click the line to go to the error
    • ZBS cannot find the Cuberite executable. Make sure you are editting a file two or three levels down the folder hierarchy from the Cuberite executable and that the Cuberite executable is named properly (cuberite[.exe] or cuberite_debug[.exe]). Also make sure you have selected the right Interpreter (menu Project -> Lua Interpreter).

    Once running, if the execution hits a breakpoint, the ZBS window will come up and a green arrow is displayed next to the breakpoint line. You can step through the code using F10 (Step Into) and Shift+F10 (Step Over). You can also use the Watch window to inspect variable values, or simply hover your mouse over a variable to display its value in the tooltip. Use the Remote console pane to execute commands directly *inside* the Cuberite's plugin context.

    You can also use the Project -> Break menu item to break into the debugger as soon as possible. You can also set breakpoints while the Cuberite plugin is running. Note that due to the way in which the debugger is implemented, Cuberite may execute some more Lua code before the break / breakpoint comes into effect. If Cuberite is not executing any Lua code in your plugin, it will not break until the plugin code kicks in again. This may result in missed breakpoints and delays before the Break command becomes effective. Therefore it's best to set breakpoints before running the program, or while the program is waiting in another breakpoint.

    ================================================ FILE: Server/Plugins/APIDump/Static/.gitignore ================================================ ================================================ FILE: Server/Plugins/APIDump/UsingChunkStays.html ================================================ Cuberite - Using ChunkStays

    Using ChunkStays

    A plugin may need to manipulate data in arbitrary chunks, and it needs a way to make the server guarantee that the chunks are available in memory.

    The problem

    Usually when plugins want to manipulate larger areas of world data, they need to make sure that the server has the appropriate chunks loaded in the memory. When the data being manipulated can be further away from the connected players, or the data is being manipulated from a console handler, there is a real chance that the chunks are not loaded.

    This gets even more important when using the cBlockArea class for reading and writing. Those functions will fail when any of the required chunks aren't valid. This means that either the block area has incomplete data (Read() failed) or incomplete data has been written to the world (Write() failed). Recovery from this is near impossible - you can't simply read or write again later, because the world may have changed in the meantime.

    The solution

    The naive solution would be to monitor chunk loads and unloads, and postpone the operations until all the chunks are available. This would be quite ineffective and also very soon it would become very difficult to maintain, if there were multiple code paths requiring this handling.

    An alternate approach has been implemented, accessible through a single (somewhat hidden) function call: cWorld:ChunkStay(). All that this call basically does is, it tells the server "Load these chunks for me, and call this callback function once you have them all." And the server does exactly that - it remembers the callback and asks the world loader / generator to provide the chunks. Once the chunks become available, it calls the callback function for the plugin.

    There are a few gotcha-s, though. If the code that was requesting the read or write had access to some of the volatile objects, such as cPlayer or cEntity objects, those cannot be accessed by the callback anymore, because they may have become invalid in the meantime - the player may have disconnected, the entity may have despawned. So the callback must use the longer way to access such objects, such as calling cWorld:DoWithEntityByID() or cWorld:DoWithPlayer().

    The example

    As a simple example, consider a theoretical plugin that allows a player to save the immediate surroundings of the spawn into a schematic file. The player issues a command to initiate the save, and the plugin reads a 50 x 50 x 50 block area around the spawn into a cBlockArea and saves it on the disk as "_spawn.schematic". When it's done with the saving, it wants to send a message to the player to let them know the command has succeeded.

    The first attempt shows the naive approach. It simply reads the block area and saves it, then sends the message. I'll repeat once more, this code is the wrong way to do it!

    function HandleCommandSaveSpawn(a_Split, a_Player)
    	-- Get the coords for the spawn:
    	local SpawnX = a_Player:GetWorld():GetSpawnX()
    	local SpawnY = a_Player:GetWorld():GetSpawnY()
    	local SpawnZ = a_Player:GetWorld():GetSpawnZ()
    	local Bounds = cCuboid(SpawnX - 25, SpawnY - 25, SpawnZ - 25, SpawnX + 25, SpawnY + 25, SpawnZ + 25)
    	Bounds:ClampY(0, 255)
    
    	-- Read the area around spawn into a cBlockArea, save to file:
    	local Area = cBlockArea()
    	local FileName = a_Player:GetName() .. "_spawn.schematic"
    	Area:Read(a_Player:GetWorld(), Bounds, cBlockArea.baTypes + cBlockArea.baMetas)
    	Area:SaveToSchematicFile(FileName)
    
    	-- Notify the player:
    	a_Player:SendMessage(cCompositeChat("The spawn has been saved", mtInfo))
    	return true
    end
    

    Now if the player goes exploring far and uses the command to save their spawn, the chunks aren't loaded, so the BlockArea reading fails, the BlockArea contains bad data. Note that the plugin fails to do any error checking and if the area isn't read from the world, it happily saves the incomplete data and says "hey, everything's right", althought it has just trashed any previous backup of the spawn schematic with nonsense data.


    The following script uses the ChunkStay method to alleviate chunk-related problems. This is the right way of doing it:

    function HandleCommandSaveSpawn(a_Split, a_Player)
    	-- Get the coords for the spawn:
    	local SpawnX = a_Player:GetWorld():GetSpawnX()
    	local SpawnY = a_Player:GetWorld():GetSpawnY()
    	local SpawnZ = a_Player:GetWorld():GetSpawnZ()
    	local Bounds = cCuboid(SpawnX - 25, SpawnY - 25, SpawnZ - 25, SpawnX + 25, SpawnY + 25, SpawnZ + 25)
    	Bounds:ClampY(0, 255)
    
    	-- Get a list of chunks that we need loaded:
    	local MinChunkX = math.floor((SpawnX - 25) / 16)
    	local MaxChunkX = math.ceil ((SpawnX + 25) / 16)
    	local MinChunkZ = math.floor((SpawnZ - 25) / 16)
    	local MaxChunkZ = math.ceil ((SpawnZ + 25) / 16)
    	local Chunks = {}
    	for x = MinChunkX, MaxChunkX do
    		for z = MinChunkZ, MaxChunkZ do
    			table.insert(Chunks, {x, z})
    		end
    	end  -- for x
    
    	-- Store the player's name and world to use in the callback, because the a_Player object may no longer be valid:
    	local PlayerName = a_Player:GetName()
    	local World = a_Player:GetWorld()
    
    	-- This is the callback that is executed once all the chunks are loaded:
    	local OnAllChunksAvailable = function()
    		-- Read the area around spawn into a cBlockArea, save to file:
    		local Area = cBlockArea()
    		local FileName = PlayerName .. "_spawn.schematic"
    		if (Area:Read(World, Bounds, cBlockArea.baTypes + cBlockArea.baMetas)) then
    			Area:SaveToSchematicFile(FileName)
    			Msg = cCompositeChat("The spawn has been saved", mtInfo)
    		else
    			Msg = cCompositeChat("Cannot save the spawn", mtFailure)
    		end
    
    		-- Notify the player:
    		-- Note that we cannot use a_Player here, because it may no longer be valid (if the player disconnected before the command completes)
    		World:DoWithPlayer(PlayerName,
    			function (a_CBPlayer)
    				a_CBPlayer:SendMessage(Msg)
    			end
    		)
    	end
    
    	-- Ask the server to load our chunks and notify us once it's done:
    	World:ChunkStay(Chunks, nil, OnAllChunksAvailable)
    
    	-- Note that code here may get executed before the callback is called!
    	-- The ChunkStay says "once you have the chunks", not "wait until you have the chunks"
    	-- So you can't notify the player here, because the saving needn't have occurred yet.
    
    	return true
    end
    

    Note that this code does its error checking of the Area:Read() function, and it will not overwrite the previous file unless it actually has the correct data. If you're wondering how the reading could fail when we've got the chunks loaded, there's still the issue of free RAM - if the memory for the area cannot be allocated, it cannot be read even with all the chunks present. So we still do need that check.

    The conclusion

    Although it makes the code a little bit longer and is a bit more difficult to grasp at first, the ChunkStay is a useful technique to add to your repertoire. It is to be used whenever you need access to chunks that may potentially be inaccessible, and you really need the data.

    Possibly the biggest hurdle in using the ChunkStay is the fact that it does its work in the background, thus invalidating all cPlayer and cEntity objects your function may hold, so you need to re-acquire them from their IDs and names. This is the penalty for using multi-threaded code.

    ================================================ FILE: Server/Plugins/APIDump/WebWorldThreads.html ================================================ Cuberite - Webserver vs World threads

    Webserver vs World threads

    This article will explain the threading issues that arise between the webserver and world threads are of concern to plugin authors.

    Generally, plugins that provide webadmin pages should be quite careful about their interactions. Most operations on Cuberite objects requires synchronization, that Cuberite provides automatically and transparently to plugins - when a block is written, the chunkmap is locked, or when an entity is being manipulated, the entity list is locked. Each plugin also has a mutex lock, so that only one thread at a time may be executing plugin code.

    This locking can be a source of deadlocks for plugins that are not written carefully.

    Example scenario

    Consider the following example. A plugin provides a webadmin page that allows the admin to kick players off the server. When the admin presses the "Kick" button, the plugin calls cWorld:DoWithPlayer() with a callback to kick the player. Everything seems to be working fine now.

    A new feature is developed in the plugin, now the plugin adds a new in-game command so that the admins can kick players while they're playing the game. The plugin registers a command callback with cPluginManager.AddCommand(). Now there are problems bound to happen.

    Suppose that two admins are in, one is using the webadmin and the other is in-game. Both try to kick a player at the same time. The webadmin locks the plugin, so that it can execute the plugin code, but right at this moment the OS switches threads. The world thread locks the world so that it can access the list of in-game commands, receives the in-game command, it tries to lock the plugin. The plugin is already locked, so the world thread is put on hold. After a while, the webadmin thread is woken up again and continues processing. It tries to lock the world so that it can traverse the playerlist, but the lock is already held by the world thread. Now both threads are holding one lock each and trying to grab the other lock, and are therefore deadlocked.

    How to avoid the deadlock

    There are two main ways to avoid such a deadlock. The first approach is using tasks: Everytime you need to execute a task inside a world, instead of executing it, queue it, using cWorld:QueueTask(). This handy utility can will call the given function inside the world's TickThread, thus eliminating the deadlock, because now there's only one thread. However, this approach will not let you get data back. You cannot query the player list, or the entities, or anything - because when the task runs, the webadmin page has already been served to the browser.

    To accommodate this, you'll need to use the second approach - preparing and caching data in the tick thread, possibly using callbacks. This means that the plugin will have global variables that will store the data, and update those variables when the data changes; then the webserver thread will only read those variables, instead of calling the world functions. For example, if a webpage was to display the list of currently connected players, the plugin should maintain a global variable, g_WorldPlayers, which would be a table of worlds, each item being a list of currently connected players. The webadmin handler would read this variable and create the page from it; the plugin would use HOOK_PLAYER_JOINED and HOOK_DISCONNECT to update the variable.

    What to avoid

    Now that we know what the danger is and how to avoid it, how do we know if our code is susceptible?

    The general rule of thumb is to avoid calling any functions that read or write lists of things in the webserver thread. This means most ForEach() and DoWith() functions. Only cRoot:ForEachWorld() is safe - because the list of worlds is not expected to change, so it is not guarded by a mutex. Getting and setting world's blocks is, naturally, unsafe, as is calling other plugins, or creating entities.

    Example

    The Core has the facility to kick players using the web interface. It used the following code for the kicking (inside the webadmin handler):
    local KickPlayerName = Request.Params["players-kick"]
    local FoundPlayerCallback = function(Player)
    	if (Player:GetName() == KickPlayerName) then
    	Player:GetClientHandle():Kick("You were kicked from the game!")
    	end
    end
    cRoot:Get():FindAndDoWithPlayer(KickPlayerName, FoundPlayerCallback)
    
    The cRoot:FindAndDoWithPlayer() is unsafe and could have caused a deadlock. The new solution is queue a task; but since we don't know in which world the player is, we need to queue the task to all worlds:
    cRoot:Get():ForEachWorld(    -- For each world...
    	function(World)
    	World:QueueTask(         -- ... queue a task...
    		function(a_World)
    		a_World:DoWithPlayer(KickPlayerName,  -- ... to walk the playerlist...
    			function (a_Player)
    			a_Player:GetClientHandle():Kick("You were kicked from the game!")  -- ... and kick the player
    			end
    		)
    		end
    	)
    	end
    )
    
    ================================================ FILE: Server/Plugins/APIDump/Writing-a-Cuberite-plugin.html ================================================ Cuberite Plugin Tutorial

    Writing a Cuberite plugin

    This article will explain how to write a basic plugin. It details basic requirements for a plugin, explains how to register a hook and bind a command, and gives plugin standards details.

    Let us begin. In order to begin development, we must firstly obtain a compiled copy of Cuberite, and make sure that the Core plugin is within the Plugins folder, and activated. Core handles much of the Cuberite end-user experience and gameplay will be very bland without it.

    Creating the basic template

    Plugins are written in Lua. Therefore, create a new Lua file. You can create as many files as you wish, with any filename - Cuberite bungs them all together at runtime, however, let us create a file called main.lua for now. Format it like so:

    PLUGIN = nil
    
    function Initialize(Plugin)
    	Plugin:SetName("NewPlugin")
    	Plugin:SetVersion(1)
    
    	-- Hooks
    
    	PLUGIN = Plugin -- NOTE: only needed if you want OnDisable() to use GetName() or something like that
    
    	-- Command Bindings
    
    	LOG("Initialised version " .. Plugin:GetVersion())
    	return true
    end
    
    function OnDisable()
    	LOG("Shutting down...")
    end
    			

    Now for an explanation of the basics.

    • function Initialize is called on plugin startup. It is the place where the plugin is set up.
    • Plugin:SetName sets the name of the plugin.
    • Plugin:SetVersion sets the revision number of the plugin. This must be an integer.
    • LOG logs to console a message, in this case, it prints that the plugin was initialised. This will add a prefix with the name of your plugin.
    • The PLUGIN variable just stores this plugin's object, so GetName() can be called in OnDisable (as no Plugin parameter is passed there, contrary to Initialize). This global variable is only needed if you want to know the plugin details (name, etc.) when shutting down.
    • function OnDisable is called when the plugin is disabled, commonly when the server is shutting down. Perform cleanup and logging here.
    Be sure to return true for this function, else Cuberite thinks you plugin had failed to initialise and prints a stacktrace with an error message.

    Registering hooks

    Hooks are things that Cuberite calls when an internal event occurs. For example, a hook is fired when a player places a block, moves, logs on, eats, and many other things. For a full list, see the API documentation.

    A hook can be either informative or overridable. In any case, returning false will not trigger a response, but returning true will cancel the hook and prevent it from being propagated further to other plugins. An overridable hook simply means that there is visible behaviour to a hook's cancellation, such as a chest being prevented from being opened. There are some exceptions to this where only changing the value the hook passes has an effect, and not the actual return value, an example being the HOOK_KILLING hook. See the API docs for details.

    To register a hook, insert the following code template into the "-- Hooks" area in the previous code example.

    cPluginManager.AddHook(cPluginManager.HOOK_NAME_HERE, FunctionNameToBeCalled)
    			

    What does this code do?

    • cPluginManager.AddHook registers the hook. The hook name is the second parameter. See the previous API documentation link for a list of all hooks.
    What about the third parameter, you ask? Well, it is the name of the function that Cuberite calls when the hook fires. It is in this function that you should handle or cancel the hook.

    So in total, this is a working representation of what we have so far covered.

    function Initialize(Plugin)
    	Plugin:SetName("DerpyPlugin")
    	Plugin:SetVersion(1)
    
    	cPluginManager.AddHook(cPluginManager.HOOK_PLAYER_MOVING, OnPlayerMoving)
    
    	LOG("Initialised " .. Plugin:GetName() .. " v." .. Plugin:GetVersion())
    	return true
    end
    
    function OnPlayerMoving(Player) -- See API docs for parameters of all hooks
    	return true -- Prohibit player movement, see docs for whether a hook is cancellable
    end
    			

    So, that code stops the player from moving. Not particularly helpful, but yes :P. Note that ALL documentation is available on the main API docs page, so if ever in doubt, go there.

    Binding a command

    Format

    So now we know how to hook into Cuberite, how do we bind a command, such as /explode, for a player to type? That is more complicated. We firstly add this template to the "-- Command bindings" section of the initial example:

    -- ADD THIS IF COMMAND DOES NOT REQUIRE A PARAMETER (/explode)
    cPluginManager.BindCommand("/commandname", "permissionnode", FunctionToCall, " - Description of command")
    
    -- ADD THIS IF COMMAND DOES REQUIRE A PARAMETER (/explode Notch)
    cPluginManager.BindCommand("/commandname", "permissionnode", FunctionToCall, " ~ Description of command and parameter(s)")
    			

    What does it do, and why are there two?

    • PluginManager:BindCommand binds a command. It takes the command name (with a slash), the permission a player needs to execute the command, the function to call when the command is executed, and a description of the command.
    The command name is pretty self explanatory. The permission node is basically just a string that the player's group needs to have, so you can have anything in there, though we recommend a style such as "derpyplugin.explode". The function to call is like the ones with Hooks, but with some fixed parameters which we will come on to later, and the description is a description of the command which is shown when "/help" is typed.

    So why are there two? Standards. A plugin that accepts a parameter MUST use a format for the description of " ~ Description of command and parms" whereas a command that doesn't accept parameters MUST use " - Description of command" instead. Be sure to put a space before the tildes or dashes. Additionally, try to keep the description brief and on one line on the client.

    Parameters

    What parameters are in the function Cuberite calls when the command is executed? A 'Split' array and a 'Player' object.

    The Split Array

    The Split array is an array of all text submitted to the server, including the actual command. Cuberite automatically splits the text into the array, so plugin authors do not need to worry about that. An example of a Split array passed for the command, "/derp zubby explode" would be:

       /derp (Split[1])
       zubby (Split[2])
       explode (Split[3])

       The total amount of parameters passed were: 3 (#Split)

    The Player Object and sending them messages

    The Player object is basically a pointer to the player that has executed the command. You can do things with them, but most common is sending a message. Again, see the API documentation for fuller details. But, you ask, how do we send a message to the client?

    There are dedicated functions used for sending a player formatted messages. By format, I refer to coloured prefixes/coloured text (depending on configuration) that clearly categorise what type of message a player is being sent. For example, an informational message has a yellow coloured [INFO] prefix, and a warning message has a rose coloured [WARNING] prefix. A few of the most used functions are listed here, but see the API docs for more details. Look in the cRoot, cWorld, and cPlayer sections for functions that broadcast to the entire server, the whole world, and a single player, respectively.

    -- Format: §yellow[INFO] §white%text% (yellow [INFO], white text following it)
    -- Use: Informational message, such as instructions for usage of a command
    Player:SendMessageInfo("Usage: /explode [player]")
    
    -- Format: §green[INFO] §white%text% (green [INFO] etc.)
    -- Use: Success message, like when a command executes successfully
    Player:SendMessageSuccess("Notch was blown up!")
    
    -- Format: §rose[INFO] §white%text% (rose coloured [INFO] etc.)
    -- Use: Failure message, like when a command was entered correctly but failed to run, such as when the destination player wasn't found in a /tp command
    Player:SendMessageFailure("Player Salted was not found")
    			

    Those are the basics. If you want to output text to the player for a reason other than the three listed above, and you want to colour the text, simply concatenate "cChatColor.*colorhere*" with your desired text, concatenate being "..". See the API docs for more details of all colours, as well as details on logging to console with LOG("Text").

    Final example and conclusion

    So, a working example that checks the validity of a command, and blows up a player, and also refuses pickup collection to players with >100ms ping.

    function Initialize(Plugin)
    	Plugin:SetName("DerpyPluginThatBlowsPeopleUp")
    	Plugin:SetVersion(9001)
    
    	cPluginManager.BindCommand("/explode", "derpyplugin.explode", Explode, " ~ Explode a player");
    
    	cPluginManager:AddHook(cPluginManager.HOOK_COLLECTING_PICKUP, OnCollectingPickup)
    
    	LOG("Initialised " .. Plugin:GetName() .. " v." .. Plugin:GetVersion())
    	return true
    end
    
    function Explode(Split, Player)
    	if (#Split ~= 2) then
    		-- There was more or less than one argument (excluding the "/explode" bit)
    		-- Send the proper usage to the player and exit
    		Player:SendMessage("Usage: /explode [playername]")
    		return true
    	end
    
    	-- Create a callback ExplodePlayer with parameter Explodee, which Cuberite calls for every player on the server
    	local HasExploded = false
    	local ExplodePlayer = function(Explodee)
    		-- If the player name matches exactly
    		if (Explodee:GetName() == Split[2]) then
    			-- Create an explosion of force level 2 at the same position as they are
    			-- see API docs for further details of this function
    			Player:GetWorld():DoExplosionAt(2, Explodee:GetPosX(), Explodee:GetPosY(), Explodee:GetPosZ(), false, esPlugin)
    			Player:SendMessageSuccess(Split[2] .. " was successfully exploded")
    			HasExploded = true;
    			return true -- Signalize to Cuberite that we do not need to call this callback for any more players
    		end
    	end
    
    	-- Tell Cuberite to loop through all players and call the callback above with the Player object it has found
    	cRoot:Get():FindAndDoWithPlayer(Split[2], ExplodePlayer)
    
    	if not(HasExploded) then
    		-- We have not broken out so far, therefore, the player must not exist, send failure
    		Player:SendMessageFailure(Split[2] .. " was not found")
    	end
    
    	return true
    end
    
    function OnCollectingPickup(Player, Pickup) -- Again, see the API docs for parameters of all hooks. In this case, it is a Player and Pickup object
    	if (Player:GetClientHandle():GetPing() > 100) then -- Get ping of player, in milliseconds
    		return true -- Discriminate against high latency - you don't get drops :D
    	else
    		return false -- You do get the drops! Yay~
    	end
    end
    			

    Make sure to read the comments for a description of what everything does. Also be sure to return true for all command handlers, unless you want Cuberite to print out an "Unknown command" message when the command gets executed :P. Make sure to follow standards - use CoreMessaging.lua functions for messaging, dashes for no parameter commands and tildes for vice versa, and finally, the API documentation is your friend!

    Happy coding ;)

    ================================================ FILE: Server/Plugins/APIDump/_preload.lua ================================================ -- _preload.lua -- First thing executed when the plugin loads. Replaces the global environment (_G) with an empty table -- with __index set to the old environment. This way any function or variable that is created globally by the plugin -- won't be reported as new or undocumented. local newEnv, oldEnv = {}, _G local setmetatable = setmetatable for k, v in pairs(_G) do newEnv[k] = v; oldEnv[k] = nil; end _G = setmetatable(oldEnv, {__index = newEnv}); ================================================ FILE: Server/Plugins/APIDump/lang-lua.js ================================================ PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r \u00a0"],["str",/^(?:"(?:[^"\\]|\\[\S\s])*(?:"|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$))/,null,"\"'"]],[["com",/^--(?:\[(=*)\[[\S\s]*?(?:]\1]|$)|[^\n\r]*)/],["str",/^\[(=*)\[[\S\s]*?(?:]\1]|$)/],["kwd",/^(?:and|break|do|else|elseif|end|false|for|function|if|in|local|nil|not|or|repeat|return|then|true|until|while)\b/,null],["lit",/^[+-]?(?:0x[\da-f]+|(?:\.\d+|\d+(?:\.\d*)?)(?:e[+-]?\d+)?)/i], ["pln",/^[_a-z]\w*/i],["pun",/^[^\w\t\n\r \xa0][^\w\t\n\r "'+=\xa0-]*/]]),["lua"]); ================================================ FILE: Server/Plugins/APIDump/lualanguageserver.lua ================================================ -- lualanguageserver.lua -- Implements the code for exporting definition files which can be used by a Lua-Language-Server --- Cleans up the name of a parameter so it can be used in a definition file --- Removes anything containing brackets and removes dashes and spaces. local function CleanupParameterName(paramName) paramName = paramName:gsub("[%- ]", "") :gsub("<.->.-", ''); return paramName end --- Cleans up a description so it can be used in a definition file. --- Uses the standard cleanup function but also removes any newlines. local function CleanUpDescriptionLLS(a_Desc) return CleanUpDescription(a_Desc) :gsub("\n", " ") end --- Writes a list of methods into the specified file in LLS format local function WriteLLSMethods(f, a_NameSpace, a_Methods) for _, func in ipairs(a_Methods or {}) do f:write("\n---\n") f:write("---", CleanUpDescriptionLLS(func.Notes or ""), "\n"); f:write("---\n"); local parameterList = {} if (func.Params) then local paramNr = 0; for _, param in ipairs(func.Params) do paramNr = paramNr + 1; local paramName = CleanupParameterName(param.Name or ("param" .. paramNr)); if (paramName:find("%.%.%.")) then paramName = "..." end table.insert(parameterList, paramName) if (param.IsOptional and paramName ~= "...") then paramName = paramName .. "?" end local paramType = param.Type; if (paramType:find("%#")) then paramType = paramType:match("%#(.+)"); end f:write("---@param ", paramName, " ", paramType, "\n"); end f:write("---\n"); end if (func.Returns) then for _, ret in ipairs(func.Returns) do f:write("---@return ", ret.Type, "\n"); end f:write("---\n"); end local name = func.Name:find("constructor") and "__call" or func.Name; name = name:find("operator") and "__meta" or name local parameters = table.concat(parameterList, ", "); f:write("function ") if (a_NameSpace) then f:write(a_NameSpace, ":") end f:write(name, "(", parameters, ") end\n\n"); end end --- Writes the list of constants. If the value is an enum the value is set from that enum. --- This is a bit of a hack because Cuberite exports allot of enums as a constant inside --- a class or global but documents them as if they are in their own table. local function WriteLLSConstants(f, a_NameSpace, a_Constants, a_Enum) if (not a_Constants) then return; end local prefix = "" if (a_NameSpace) then prefix = a_NameSpace .. "."; end for _, const in pairs(a_Constants) do f:write(prefix) if (a_Enum) then f:write(const.Name, " = ", prefix, a_Enum, ".", const.Name, "\n") else local constValue = tostring(const.Value):match("[%w%d]+") or "nil"; f:write(const.Name, " = ", constValue, "\n") end end end --- Writes a list of constants into the specified file in LLS format local function WriteLLSEnums(f, a_NameSpace, a_ConstantGroups) if (not a_ConstantGroups) then return; end local prefix = ""; if (a_NameSpace) then prefix = a_NameSpace .. "." end for _, group in pairs(a_ConstantGroups) do f:write("---@enum ", group.Name, "\n"); f:write(prefix, group.Name, " = {\n") for _, const in pairs(group.Constants) do local constValue = tostring(const.Value):match("[%w%d]+") or "nil"; f:write("\t", const.Name, " = ", constValue, ",\n") end f:write("}\n") WriteLLSConstants(f, a_NameSpace, group.Constants, group.Name); end end --- Writes all the fields which a class has. ---@param f file* ---@param a_Variables table local function WriteLLSVariables(f, a_Variables) for _, variable in ipairs(a_Variables or {}) do f:write("---@field ", variable.Name) if (variable.Type) then local type = variable.Type:match("%w+") f:write(" ", type) end if (variable.Notes) then f:write(" ", variable.Notes) end f:write("\n"); end end --- Writes one Cuberite class definition into the specified file in LLS format local function WriteLLSClass(a_Class) assert(type(a_Class) == "table") local f = io.open("LLS/cuberite/library/" .. a_Class.Name .. ".lua", "w"); f:write("---@meta\n"); f:write("\n\n---\n---The ", a_Class.Name, " namespace\n"); local inherit = ""; if (a_Class.Inherits) then inherit = ": " .. a_Class.Inherits.Name end f:write("---@class ", a_Class.Name, inherit, "\n"); WriteLLSVariables(f, a_Class.Variables); for _, func in pairs(a_Class.Functions or {}) do if (func.Name:find("constructor")) then local parameters = {}; for _, param in ipairs(func.Parameters or {}) do table.insert(parameters, param.Type); end f:write("---@operator call(", table.concat(parameters, ","), "):" .. a_Class.Name, "\n") end end f:write("", a_Class.Name, " = {}\n"); -- Export methods and constants: WriteLLSEnums(f, a_Class.Name, a_Class.ConstantGroups); WriteLLSConstants(f, a_Class.Name, a_Class.Constants); WriteLLSMethods(f, a_Class.Name, a_Class.Functions); f:close(); end --- Dumps the entire API table into a file in the LLS format function DumpAPILLS(a_API) LOG("Dumping LLS API description...") cFile:CreateFolderRecursive("LLS/cuberite/library"); -- Export each class except Globals, store those aside: local Globals for _, cls in ipairs(a_API) do if (cls.Name ~= "Globals") then WriteLLSClass(cls) else Globals = cls end end -- Export the globals: if (Globals) then local f = io.open("LLS/cuberite/library/Globals.lua", "w"); f:write("---@meta\n\n"); WriteLLSMethods(f, nil, Globals.Functions) WriteLLSEnums(f, nil, Globals.ConstantGroups) f:close(); end -- Finish the file: LOG("LLS API dumped...") end ================================================ FILE: Server/Plugins/APIDump/main.css ================================================ html { background-color: #C0C0C0; } table { background-color: #fff; border-spacing: 0px; border-collapse: collapse; border-color: gray; } tr { display: table-row; vertical-align: inherit; border-color: inherit; } td, th { display: table-cell; vertical-align: inherit; padding: 3px; border: 1px solid #ccc; } pre { border: 1px solid #ccc; background-color: #eee; -moz-tab-size: 2; -o-tab-size: 2; -webkit-tab-size: 2; -ms-tab-size: 2; tab-size: 2; } body { min-width: 400px; max-width: 1200px; width: 95%; margin: 10px auto; background-color: white; border: 4px #FF8C00 solid; border-radius: 20px; font-family: Calibri, Trebuchet MS; } header { text-align: center; font-family: Segoe UI Light, Helvetica; } footer { text-align: center; font-family: Segoe UI Light, Helvetica; } #content, #timestamp { padding: 0px 25px 25px 25px; } ================================================ FILE: Server/Plugins/APIDump/main_APIDump.lua ================================================ -- main.lua -- Implements the plugin entrypoint (in this case the entire plugin) -- Global variables: local g_Plugin = nil local g_PluginFolder = "" local g_Stats = {} local g_TrackedPages = {} local function LoadAPIFiles(a_Folder, a_DstTable) assert(type(a_Folder) == "string") assert(type(a_DstTable) == "table") local Folder = g_PluginFolder .. a_Folder; for _, fnam in ipairs(cFile:GetFolderContents(Folder)) do local FileName = Folder .. fnam; -- We only want .lua files from the folder: if (cFile:IsFile(FileName) and fnam:match(".*%.lua$")) then local TablesFn = assert(loadfile(FileName)) local Tables = TablesFn() if (type(Tables) ~= "table") then error("Cannot load API descriptions from " .. FileName .. ", returned object is not a table (" .. type(Tables) .. ").") break end for k, cls in pairs(Tables) do if (a_DstTable[k]) then -- The class is documented in two files, warn and store into a file (so that CIs can mark build as failure): LOGWARNING(string.format( "Warning: class %s is documented at two places, the documentation in file %s will overwrite the previously loaded one!", k, FileName )) local f = io.open("DuplicateDocs.txt", "a") f:write(k, "\t", FileName) f:close() end a_DstTable[k] = cls end end -- if (is lua file) end -- for fnam - Folder[] end --- Returns the API currently detected from the global environment local function CreateAPITables() --[[ We want an API table of the following shape: local API = { { Name = "cCuboid", Functions = { {Name = "Sort"}, {Name = "IsInside"} }, Constants = { }, Variables = { }, Descendants = {}, -- Will be filled by ReadDescriptions(), array of class APIs (references to other member in the tree) }, { Name = "cBlockArea", Functions = { {Name = "Clear"}, {Name = "CopyFrom"}, ... }, Constants = { {Name = "baTypes", Value = 0}, {Name = "baMetas", Value = 1}, ... }, Variables = { }, ... }, cCuboid = {} -- Each array item also has the map item by its name }; local Globals = { Functions = { ... }, Constants = { ... } }; --]] local Globals = {Functions = {}, Constants = {}, Variables = {}, Descendants = {}}; local API = {}; local function Add(a_APIContainer, a_ObjName, a_ObjValue) if (type(a_ObjValue) == "function") then table.insert(a_APIContainer.Functions, {Name = a_ObjName}); elseif ( (type(a_ObjValue) == "number") or (type(a_ObjValue) == "string") ) then table.insert(a_APIContainer.Constants, {Name = a_ObjName, Value = a_ObjValue}); end end local function ParseClass(a_ClassName, a_ClassObj) local res = {Name = a_ClassName, Functions = {}, Constants = {}, Variables = {}, Descendants = {}}; -- Add functions and constants: for i, v in pairs(a_ClassObj) do Add(res, i, v); end -- Member variables: local GetField = a_ClassObj[".get"]; local SetField = a_ClassObj[".set"] or {}; if ((GetField ~= nil) and (type(GetField) == "table")) then for k, v in pairs(GetField) do if ((SetField[k] == nil) and ((type(v) ~= "table") or (v["__newindex"] == nil))) then -- It is a read-only variable or array, add it as a constant: table.insert(res.Constants, {Name = k, Value = ""}); else -- It is a read-write variable or array, add it as a variable: table.insert(res.Variables, { Name = k }); end end end return res; end for i, v in pairs(getmetatable(_G).__index) do if ( (v ~= _G) and -- don't want the global namespace (v ~= _G.packages) and -- don't want any packages (v ~= _G[".get"]) ) then if (type(v) == "table") then local cls = ParseClass(i, v) table.insert(API, cls); API[cls.Name] = cls else Add(Globals, i, v); end end end -- Remove the built-in Lua libraries: API.debug = nil API.io = nil API.string = nil API.table = nil return API, Globals; end --- Returns the timestamp in HTML format -- The timestamp will be inserted to all generated HTML files local function GetHtmlTimestamp() return string.format("
    Generated by APIDump on %s, Build ID %s, Commit %s
    ", os.date("%Y-%m-%d %H:%M:%S"), cRoot:GetBuildID(), cRoot:GetBuildCommitID() ) end --- Writes links to articles in a bullet format into the output HTML file -- f is the output file stream -- a_APIDesc is the API description as read from APIDesc.lua local function WriteArticles(f, a_APIDesc) f:write([[

    Articles

    The following articles provide various extra information on plugin development

      ]]); for _, extra in ipairs(a_APIDesc.ExtraPages) do local SrcFileName = g_PluginFolder .. "/" .. extra.FileName; if (cFile:IsFile(SrcFileName)) then local DstFileName = "API/" .. extra.FileName; cFile:Delete(DstFileName); cFile:Copy(SrcFileName, DstFileName); f:write("
    • " .. extra.Title .. "
    • \n"); else f:write("
    • " .. extra.Title .. " (file is missing)
    • \n"); end end f:write("

    "); end -- Make a link out of anything with the special linkifying syntax {{link|title}} local function LinkifyString(a_String, a_Referrer, a_API) assert(a_Referrer ~= nil); assert(a_Referrer ~= ""); -- If the string is a known class, return a direct link to it: if (a_API[a_String]) then return "" .. a_String .. "" end --- Adds a page to the list of tracked pages (to be checked for existence at the end) local function AddTrackedPage(a_PageName) local Pg = (g_TrackedPages[a_PageName] or {}); table.insert(Pg, a_Referrer); g_TrackedPages[a_PageName] = Pg; end --- Creates the HTML for the specified link and title local function CreateLink(Link, Title) if ((Link:sub(1, 7) == "http://") or (Link:sub(1, 8) == "https://")) then -- The link is a full absolute URL, do not modify, do not track: return "" .. Title .. ""; end local idxHash = Link:find("#"); if (idxHash ~= nil) then -- The link contains an anchor: if (idxHash == 1) then -- Anchor in the current page, no need to track: return "" .. Title .. ""; end -- Anchor in another page: local PageName = Link:sub(1, idxHash - 1); AddTrackedPage(PageName); return "" .. Title .. ""; end -- Link without anchor: AddTrackedPage(Link); return "" .. Title .. ""; end -- Linkify the strings using the CreateLink() function: local txt = a_String:gsub("{{([^|}]*)|([^}]*)}}", CreateLink) -- {{link|title}} txt = txt:gsub("{{([^|}]*)}}", -- {{LinkAndTitle}} function(LinkAndTitle) local idxHash = LinkAndTitle:find("#"); if (idxHash ~= nil) then -- The LinkAndTitle contains a hash, remove the hashed part from the title: return CreateLink(LinkAndTitle, LinkAndTitle:sub(1, idxHash - 1)); end return CreateLink(LinkAndTitle, LinkAndTitle); end ); return txt; end local function WriteHtmlHook(a_Hook, a_HookNav, a_API) local fnam = "API/" .. a_Hook.DefaultFnName .. ".html"; local f, error = io.open(fnam, "w"); if (f == nil) then LOG("Cannot write \"" .. fnam .. "\": \"" .. error .. "\"."); return; end local HookName = a_Hook.DefaultFnName; f:write([[ Cuberite API - ]], HookName, [[ Hook

    ]], a_Hook.Name, [[


    Index:
    Articles
    Classes
    Hooks

    Quick navigation:
    ]]); f:write(a_HookNav); f:write([[

    ]]); f:write(LinkifyString(a_Hook.Desc, HookName, a_API)); f:write("

    \n

    Callback function

    \n

    The default name for the callback function is "); f:write(a_Hook.DefaultFnName, ". It has the following signature:\n"); f:write("

    function My", HookName, "(");
    	if (a_Hook.Params == nil) then
    		a_Hook.Params = {};
    	end
    	for i, param in ipairs(a_Hook.Params) do
    		if (i > 1) then
    			f:write(", ");
    		end
    		f:write(param.Name);
    	end
    	f:write(")
    \n

    Parameters:

    \n\n"); for _, param in ipairs(a_Hook.Params) do f:write("\n"); end f:write("
    NameTypeNotes
    ", param.Name, "", LinkifyString(param.Type, HookName, a_API), "", LinkifyString(param.Notes, HookName, a_API), "
    \n

    " .. LinkifyString(a_Hook.Returns or "", HookName, a_API) .. "

    \n\n"); f:write([[

    Code examples

    Registering the callback

    ]]); f:write("
    \n");
    	f:write([[cPluginManager:AddHook(cPluginManager.]] .. a_Hook.Name .. ", My" .. a_Hook.DefaultFnName .. [[);]]);
    	f:write("
    \n\n"); local Examples = a_Hook.CodeExamples or {}; for _, example in ipairs(Examples) do f:write("

    ", (example.Title or "missing Title"), "

    \n"); f:write("

    ", (example.Desc or "missing Desc"), "

    \n"); f:write("
    ", (example.Code or "missing Code"), "\n
    \n\n"); end f:write([[
    ]]) f:write(GetHtmlTimestamp()) f:write([[]]) f:close(); end --- Writes all hooks into HTML output file as links in a sorted bullet list, as well as the individual hook HTML files -- f is the output HTML index file -- a_Hooks is an array of hook descriptions -- a_UndocumentedHooks is a table that will be filled with the names of hooks that are not documented -- a_HookNav is the HTML code for the menu on the left that is constant for all hook pages local function WriteHooks(f, a_Hooks, a_UndocumentedHooks, a_HookNav, a_API) f:write([[

    Hooks

    A plugin can register to be called whenever an "interesting event" occurs. It does so by calling cPluginManager's AddHook() function and implementing a callback function to handle the event.

    A plugin can decide whether it will let the event pass through to the rest of the plugins, or hide it from them. This is determined by the return value from the hook callback function. If the function returns false or no value, the event is propagated further. If the function returns true, the processing is stopped, no other plugin receives the notification (and possibly Cuberite disables the default behavior for the event). See each hook's details to see the exact behavior.

    ]]); for _, hook in ipairs(a_Hooks) do if (hook.DefaultFnName == nil) then -- The hook is not documented yet f:write(" \n \n \n \n"); table.insert(a_UndocumentedHooks, hook.Name); else f:write(" \n \n \n \n"); WriteHtmlHook(hook, a_HookNav, a_API); end end f:write([[
    Hook name Called when
    " .. hook.Name .. "(No documentation yet)
    " .. hook.Name .. "" .. LinkifyString(hook.CalledWhen, hook.Name, a_API) .. "

    ]]); end --- Fills the API in a_API table with descriptions from a_Desc -- a_API is the API detected from current global environment -- a_Desc is the description loaded from APIDesc.lua and Classes files local function ReadDescriptions(a_API, a_Desc) -- Returns true if the class of the specified name is to be ignored local function IsClassIgnored(a_ClsName) if (a_Desc.IgnoreClasses == nil) then return false; end for _, name in ipairs(a_Desc.IgnoreClasses) do if (a_ClsName:match(name)) then return true; end end return false; end -- Returns true if the function is to be ignored local function IsFunctionIgnored(a_ClassName, a_FnName) if (a_Desc.IgnoreFunctions == nil) then return false; end if (((a_Desc.Classes[a_ClassName] or {}).Functions or {})[a_FnName] ~= nil) then -- The function is documented, don't ignore return false; end local FnName = a_ClassName .. "." .. a_FnName; for _, name in ipairs(a_Desc.IgnoreFunctions) do if (FnName:match(name)) then return true; end end return false; end -- Returns true if the constant (specified by its fully qualified name) is to be ignored local function IsConstantIgnored(a_CnName) if (a_Desc.IgnoreConstants == nil) then return false; end; for _, name in ipairs(a_Desc.IgnoreConstants) do if (a_CnName:match(name)) then return true; end end return false; end -- Returns true if the member variable (specified by its fully qualified name) is to be ignored local function IsVariableIgnored(a_VarName) if (a_Desc.IgnoreVariables == nil) then return false; end; for _, name in ipairs(a_Desc.IgnoreVariables) do if (a_VarName:match(name)) then return true; end end return false; end -- Remove ignored classes from a_API: local APICopy = {}; for _, cls in ipairs(a_API) do if not(IsClassIgnored(cls.Name)) then table.insert(APICopy, cls); end end for i = 1, #a_API do a_API[i] = APICopy[i]; end; -- Process the documentation for each class: for _, cls in ipairs(a_API) do -- Initialize default values for each class: cls.ConstantGroups = {}; cls.NumConstantsInGroups = 0; cls.NumConstantsInGroupsForDescendants = 0; -- Rename special functions: for _, fn in ipairs(cls.Functions) do if (fn.Name == ".call") then fn.DocID = "constructor"; fn.Name = "() (constructor)"; elseif (fn.Name == ".add") then fn.DocID = "operator_plus"; fn.Name = "operator +"; elseif (fn.Name == ".div") then fn.DocID = "operator_div"; fn.Name = "operator /"; elseif (fn.Name == ".mul") then fn.DocID = "operator_mul"; fn.Name = "operator *"; elseif (fn.Name == ".sub") then fn.DocID = "operator_sub"; fn.Name = "operator -"; elseif (fn.Name == ".eq") then fn.DocID = "operator_eq"; fn.Name = "operator =="; end end local APIDesc = a_Desc.Classes[cls.Name]; if (APIDesc ~= nil) then APIDesc.IsExported = true; cls.Desc = APIDesc.Desc; cls.AdditionalInfo = APIDesc.AdditionalInfo; -- Process inheritance: if (APIDesc.Inherits ~= nil) then for _, icls in ipairs(a_API) do if (icls.Name == APIDesc.Inherits) then table.insert(icls.Descendants, cls); cls.Inherits = icls; end end end cls.UndocumentedFunctions = {}; -- This will contain names of all the functions that are not documented cls.UndocumentedConstants = {}; -- This will contain names of all the constants that are not documented cls.UndocumentedVariables = {}; -- This will contain names of all the variables that are not documented local DoxyFunctions = {}; -- This will contain all the API functions together with their documentation local function AddFunction(a_Name, a_Params, a_Returns, a_IsStatic, a_Notes) table.insert(DoxyFunctions, {Name = a_Name, Params = a_Params, Returns = a_Returns, IsStatic = a_IsStatic, Notes = a_Notes}); end if (APIDesc.Functions ~= nil) then -- Assign function descriptions: for _, func in ipairs(cls.Functions) do local FnName = func.DocID or func.Name; local FnDesc = APIDesc.Functions[FnName]; if (FnDesc == nil) then -- No description for this API function AddFunction(func.Name); if not(IsFunctionIgnored(cls.Name, FnName)) then table.insert(cls.UndocumentedFunctions, FnName); end else -- Description is available if (FnDesc[1] == nil) then -- Single function definition AddFunction(func.Name, FnDesc.Params, FnDesc.Returns, FnDesc.IsStatic, FnDesc.Notes); else -- Multiple function overloads for _, desc in ipairs(FnDesc) do AddFunction(func.Name, desc.Params, desc.Returns, desc.IsStatic, desc.Notes); end -- for k, desc - FnDesc[] end FnDesc.IsExported = true; end end -- for j, func -- Replace functions with their described and overload-expanded versions: cls.Functions = DoxyFunctions; else -- if (APIDesc.Functions ~= nil) for _, func in ipairs(cls.Functions) do local FnName = func.DocID or func.Name; if not(IsFunctionIgnored(cls.Name, FnName)) then table.insert(cls.UndocumentedFunctions, FnName); end end end -- if (APIDesc.Functions ~= nil) if (APIDesc.Constants ~= nil) then -- Assign constant descriptions: for _, cons in ipairs(cls.Constants) do local CnDesc = APIDesc.Constants[cons.Name]; if (CnDesc == nil) then -- Not documented if not(IsConstantIgnored(cls.Name .. "." .. cons.Name)) then table.insert(cls.UndocumentedConstants, cons.Name); end else cons.Notes = CnDesc.Notes; CnDesc.IsExported = true; end end -- for j, cons else -- if (APIDesc.Constants ~= nil) for _, cons in ipairs(cls.Constants) do if not(IsConstantIgnored(cls.Name .. "." .. cons.Name)) then table.insert(cls.UndocumentedConstants, cons.Name); end end end -- else if (APIDesc.Constants ~= nil) -- Assign member variables' descriptions: if (APIDesc.Variables ~= nil) then for _, var in ipairs(cls.Variables) do local VarDesc = APIDesc.Variables[var.Name]; if (VarDesc == nil) then -- Not documented if not(IsVariableIgnored(cls.Name .. "." .. var.Name)) then table.insert(cls.UndocumentedVariables, var.Name); end else -- Copy all documentation: for k, v in pairs(VarDesc) do var[k] = v end end end -- for j, var else -- if (APIDesc.Variables ~= nil) for _, var in ipairs(cls.Variables) do if not(IsVariableIgnored(cls.Name .. "." .. var.Name)) then table.insert(cls.UndocumentedVariables, var.Name); end end end -- else if (APIDesc.Variables ~= nil) if (APIDesc.ConstantGroups ~= nil) then -- Create links between the constants and the groups: local NumInGroups = 0; local NumInDescendantGroups = 0; for j, group in pairs(APIDesc.ConstantGroups) do group.Name = j; group.Constants = {}; if (type(group.Include) == "string") then group.Include = { group.Include }; end local NumInGroup = 0; for _, incl in ipairs(group.Include or {}) do for _, cons in ipairs(cls.Constants) do if ((cons.Group == nil) and cons.Name:match(incl)) then cons.Group = group; table.insert(group.Constants, cons); NumInGroup = NumInGroup + 1; end end -- for cidx - cls.Constants[] end -- for idx - group.Include[] NumInGroups = NumInGroups + NumInGroup; if (group.ShowInDescendants) then NumInDescendantGroups = NumInDescendantGroups + NumInGroup; end -- Sort the constants: table.sort(group.Constants, function(c1, c2) return (c1.Name < c2.Name); end ); end -- for j - APIDesc.ConstantGroups[] cls.ConstantGroups = APIDesc.ConstantGroups; cls.NumConstantsInGroups = NumInGroups; cls.NumConstantsInGroupsForDescendants = NumInDescendantGroups; -- Remove grouped constants from the normal list: local NewConstants = {}; for _, cons in ipairs(cls.Constants) do if (cons.Group == nil) then table.insert(NewConstants, cons); end end cls.Constants = NewConstants; end -- if (ConstantGroups ~= nil) else -- if (APIDesc ~= nil) -- Class is not documented at all, add all its members to Undocumented lists: cls.UndocumentedFunctions = {}; cls.UndocumentedConstants = {}; cls.UndocumentedVariables = {}; cls.Variables = cls.Variables or {}; g_Stats.NumUndocumentedClasses = g_Stats.NumUndocumentedClasses + 1; for _, func in ipairs(cls.Functions) do local FnName = func.DocID or func.Name; if not(IsFunctionIgnored(cls.Name, FnName)) then table.insert(cls.UndocumentedFunctions, FnName); end end -- for j, func - cls.Functions[] for _, cons in ipairs(cls.Constants) do if not(IsConstantIgnored(cls.Name .. "." .. cons.Name)) then table.insert(cls.UndocumentedConstants, cons.Name); end end -- for j, cons - cls.Constants[] for _, var in ipairs(cls.Variables) do if not(IsConstantIgnored(cls.Name .. "." .. var.Name)) then table.insert(cls.UndocumentedVariables, var.Name); end end -- for j, var - cls.Variables[] end -- else if (APIDesc ~= nil) -- Remove ignored functions: local NewFunctions = {}; for _, fn in ipairs(cls.Functions) do if (not(IsFunctionIgnored(cls.Name, fn.Name))) then table.insert(NewFunctions, fn); end end -- for j, fn cls.Functions = NewFunctions; -- Sort the functions (they may have been renamed): table.sort(cls.Functions, function(f1, f2) return (f1.Name < f2.Name); end ); -- Remove ignored constants: local NewConstants = {}; for _, cn in ipairs(cls.Constants) do if (not(IsFunctionIgnored(cls.Name, cn.Name))) then table.insert(NewConstants, cn); end end -- for j, cn cls.Constants = NewConstants; -- Sort the constants: table.sort(cls.Constants, function(c1, c2) return (c1.Name < c2.Name); end ); -- Remove ignored member variables: local NewVariables = {}; for _, var in ipairs(cls.Variables) do if (not(IsVariableIgnored(cls.Name .. "." .. var.Name))) then table.insert(NewVariables, var); end end -- for j, var cls.Variables = NewVariables; -- Sort the member variables: table.sort(cls.Variables, function(v1, v2) return (v1.Name < v2.Name); end ); end -- for i, cls -- Sort the descendants lists: for _, cls in ipairs(a_API) do table.sort(cls.Descendants, function(c1, c2) return (c1.Name < c2.Name); end ); end -- for i, cls end --- Fills the hooks in a_Hooks with their descriptions from a_Descs -- a_Hooks is an array of hooks detected from current global environment -- a_Descs is the description read from APIDesc.lua and Hooks files local function ReadHooks(a_Hooks, a_Descs) --[[ a_Hooks = { { Name = "HOOK_1"}, { Name = "HOOK_2"}, ... }; We want to add hook descriptions to each hook in this array --]] for _, hook in ipairs(a_Hooks) do local HookDesc = a_Descs.Hooks[hook.Name]; if (HookDesc ~= nil) then for key, val in pairs(HookDesc) do hook[key] = val; end end end -- for i, hook - a_Hooks[] g_Stats.NumTotalHooks = #a_Hooks; end --- Returns a HTML string describing the (parameter) type, linking to the type's documentation, if available -- a_Type is the string containing the type (such as "cPlugin" or "number"), or nil -- a_API is the complete API description (used for searching the classnames) local function LinkifyType(a_Type, a_API) -- Check params: assert(type(a_Type) == "string") assert(type(a_API) == "table") -- If the type is a known class, return a direct link to it: if (a_API[a_Type]) then return "" .. a_Type .. "" end -- If the type has a hash sign, it's a child enum of a class: local idxColon = a_Type:find("#") if (idxColon) then local classType = a_Type:sub(1, idxColon - 1) if (a_API[classType]) then local enumType = a_Type:sub(idxColon + 1) return "" .. enumType .. "" end end -- If the type is a ConstantGroup within the Globals, it's a global enum: if ((a_API.Globals.ConstantGroups or {})[a_Type]) then return "" .. a_Type .. "" end -- Unknown or built-in type, output just text: return a_Type end --- Returns an HTML string describing all function parameters (or return values) -- a_FnParams is an array-table or string description of the parameters -- a_ClassName is the name of the class for which the function is being documented (for Linkification) -- a_API is the complete API description (for cross-type linkification) local function CreateFunctionParamsDescription(a_FnParams, a_ClassName, a_API) local pt = type(a_FnParams) assert((pt == "string") or (pt == "table")) assert(type(a_ClassName) == "string") assert(type(a_API) == "table") -- If the params description is a string (old format), just linkify it: if (pt == "string") then return LinkifyString(a_FnParams, a_ClassName, a_API) end -- If the params description is an empty table, give no description at all: if not(a_FnParams[1]) then return "" end -- The params description is a table, output the full desc: local res = {""} local idx = 2 for _, param in ipairs(a_FnParams) do res[idx] = "" idx = idx + 5 end res[idx] = "
    " res[idx + 1] = param.Name or "" res[idx + 2] = "" res[idx + 3] = LinkifyType(param.Type, a_API) res[idx + 4] = "
    " return table.concat(res) end --- Writes an HTML file containing the class API description for the given class -- a_ClassAPI is the API description of the class to output -- a_ClassMenu is the HTML string containing the code for the menu sidebar -- a_API is the complete API (for cross-type linkification) local function WriteHtmlClass(a_ClassAPI, a_ClassMenu, a_API) -- Check params: assert(type(a_ClassAPI) == "table") assert(type(a_ClassMenu) == "string") assert(type(a_API) == "table") local cf, err = io.open("API/" .. a_ClassAPI.Name .. ".html", "w"); if (cf == nil) then LOGINFO("Cannot write HTML API for class " .. a_ClassAPI.Name .. ": " .. err) return; end -- Writes a table containing all functions in the specified list, with an optional "inherited from" header when a_InheritedName is valid local function WriteFunctions(a_Functions, a_InheritedName) if not(a_Functions[1]) then -- No functions to write return; end if (a_InheritedName) then cf:write("

    Functions inherited from ", a_InheritedName, "

    \n"); end cf:write("\n\n"); -- Store all function names, to create unique anchor names for all functions local TableOverloadedFunctions = {} for _, func in ipairs(a_Functions) do local StaticClause = "" if (func.IsStatic) then StaticClause = "(STATIC) " end -- Increase number by one TableOverloadedFunctions[func.Name] = (TableOverloadedFunctions[func.Name] or 0) + 1 -- Add the anchor names as a title cf:write("\n"); cf:write("\n"); cf:write("\n"); cf:write("\n"); end cf:write("
    NameParametersReturn valueNotes
    ", func.Name, "", CreateFunctionParamsDescription(func.Params or {}, a_InheritedName or a_ClassAPI.Name, a_API), "", CreateFunctionParamsDescription(func.Returns or {}, a_InheritedName or a_ClassAPI.Name, a_API), "", StaticClause .. LinkifyString(func.Notes or "(undocumented)", (a_InheritedName or a_ClassAPI.Name), a_API), "
    \n"); end local function WriteConstantTable(a_Constants, a_Source) cf:write("\n\n"); for _, cons in ipairs(a_Constants) do cf:write("\n"); cf:write("\n"); cf:write("\n"); end cf:write("
    NameValueNotes
    ", cons.Name, "", cons.Value, "", LinkifyString(cons.Notes or "", a_Source, a_API), "
    \n\n"); end local function WriteConstants(a_Constants, a_ConstantGroups, a_NumConstantGroups, a_InheritedName) if ((#a_Constants == 0) and (a_NumConstantGroups == 0)) then return; end local Source = a_ClassAPI.Name if (a_InheritedName ~= nil) then cf:write("

    Constants inherited from ", a_InheritedName, "

    \n"); Source = a_InheritedName; end if (#a_Constants > 0) then WriteConstantTable(a_Constants, Source); end for _, group in pairs(a_ConstantGroups) do if ((a_InheritedName == nil) or group.ShowInDescendants) then cf:write("

    "); cf:write(LinkifyString(group.TextBefore or "", Source, a_API)); WriteConstantTable(group.Constants, a_InheritedName or a_ClassAPI.Name); cf:write(LinkifyString(group.TextAfter or "", Source, a_API), "


    "); end end end local function WriteVariables(a_Variables, a_InheritedName) if (#a_Variables == 0) then return; end if (a_InheritedName ~= nil) then cf:write("

    Member variables inherited from ", a_InheritedName, "

    \n"); end cf:write("\n"); for _, var in ipairs(a_Variables) do cf:write("\n"); cf:write("\n"); cf:write("\n \n"); end cf:write("
    NameTypeNotes
    ", var.Name, "", LinkifyString(var.Type or "(undocumented)", a_InheritedName or a_ClassAPI.Name, a_API), "", LinkifyString(var.Notes or "", a_InheritedName or a_ClassAPI.Name, a_API), "
    \n\n"); end local function WriteDescendants(a_Descendants) if (#a_Descendants == 0) then return; end cf:write("
      "); for _, desc in ipairs(a_Descendants) do cf:write("
    • ", desc.Name, ""); WriteDescendants(desc.Descendants); cf:write("
    • \n"); end cf:write("
    \n"); end local ClassName = a_ClassAPI.Name; -- Build an array of inherited classes chain: local InheritanceChain = {}; local CurrInheritance = a_ClassAPI.Inherits; while (CurrInheritance ~= nil) do table.insert(InheritanceChain, CurrInheritance); CurrInheritance = CurrInheritance.Inherits; end cf:write([[ Cuberite API - ]], a_ClassAPI.Name, [[ Class

    ]], a_ClassAPI.Name, [[


    Index:
    Articles
    Classes
    Hooks

    Quick navigation:
    ]]); cf:write(a_ClassMenu); cf:write([[

    Contents

      ]]); local HasInheritance = ((#a_ClassAPI.Descendants > 0) or (a_ClassAPI.Inherits ~= nil)); local HasConstants = (#a_ClassAPI.Constants > 0) or (a_ClassAPI.NumConstantsInGroups > 0); local HasFunctions = (#a_ClassAPI.Functions > 0); local HasVariables = (#a_ClassAPI.Variables > 0); for _, cls in ipairs(InheritanceChain) do HasConstants = HasConstants or (#cls.Constants > 0) or (cls.NumConstantsInGroupsForDescendants > 0); HasFunctions = HasFunctions or (#cls.Functions > 0); HasVariables = HasVariables or (#cls.Variables > 0); end -- Write the table of contents: if (HasInheritance) then cf:write("
    • Inheritance
    • \n"); end if (HasConstants) then cf:write("
    • Constants
    • \n"); end if (HasVariables) then cf:write("
    • Member variables
    • \n"); end if (HasFunctions) then cf:write("
    • Functions
    • \n"); end if (a_ClassAPI.AdditionalInfo ~= nil) then for i, additional in ipairs(a_ClassAPI.AdditionalInfo) do cf:write("
    • ", (additional.Header or "(No header)"), "
    • \n"); end end cf:write("

    \n"); -- Write the class description: cf:write("

    ", ClassName, " class

    \n"); if (a_ClassAPI.Desc ~= nil) then cf:write("

    "); cf:write(LinkifyString(a_ClassAPI.Desc, ClassName, a_API)); cf:write("

    \n\n"); end; -- Write the inheritance, if available: if (HasInheritance) then cf:write("

    Inheritance

    \n"); if (#InheritanceChain > 0) then cf:write("

    This class inherits from the following parent classes:

      \n"); for _, cls in ipairs(InheritanceChain) do cf:write("
    • ", cls.Name, "
    • \n"); end cf:write("

    \n"); end if (#a_ClassAPI.Descendants > 0) then cf:write("

    This class has the following descendants:\n"); WriteDescendants(a_ClassAPI.Descendants); cf:write("

    \n\n"); end end -- Write the constants: if (HasConstants) then cf:write("

    Constants

    \n"); WriteConstants(a_ClassAPI.Constants, a_ClassAPI.ConstantGroups, a_ClassAPI.NumConstantsInGroups, nil); g_Stats.NumTotalConstants = g_Stats.NumTotalConstants + #a_ClassAPI.Constants + (a_ClassAPI.NumConstantsInGroups or 0); for _, cls in ipairs(InheritanceChain) do WriteConstants(cls.Constants, cls.ConstantGroups, cls.NumConstantsInGroupsForDescendants, cls.Name); end; end; -- Write the member variables: if (HasVariables) then cf:write("

    Member variables

    \n"); WriteVariables(a_ClassAPI.Variables, nil); g_Stats.NumTotalVariables = g_Stats.NumTotalVariables + #a_ClassAPI.Variables; for _, cls in ipairs(InheritanceChain) do WriteVariables(cls.Variables, cls.Name); end; end -- Write the functions, including the inherited ones: if (HasFunctions) then cf:write("

    Functions

    \n"); WriteFunctions(a_ClassAPI.Functions, nil); g_Stats.NumTotalFunctions = g_Stats.NumTotalFunctions + #a_ClassAPI.Functions; for _, cls in ipairs(InheritanceChain) do WriteFunctions(cls.Functions, cls.Name); end end -- Write the additional infos: if (a_ClassAPI.AdditionalInfo ~= nil) then for i, additional in ipairs(a_ClassAPI.AdditionalInfo) do cf:write("

    ", additional.Header, "

    \n"); cf:write(LinkifyString(additional.Contents, ClassName, a_API)); end end cf:write([[
    ]]) cf:write(GetHtmlTimestamp()) cf:write([[]]) cf:close() end --- Writes all classes into HTML output file as links in a sorted bullet list, as well as the individual class HTML files -- f is the output file -- a_API is the API detected from current environment enriched with descriptions -- a_ClassMenu is the HTML code for the menu on the left that is constant for all class pages local function WriteClasses(f, a_API, a_ClassMenu) f:write([[

    Class index

    The following classes are available in the Cuberite Lua scripting language:

      ]]); for _, cls in ipairs(a_API) do f:write("
    • ", cls.Name, "
    • \n"); WriteHtmlClass(cls, a_ClassMenu, a_API); end f:write([[


    ]]); end --- Writes a list of undocumented objects into a file local function ListUndocumentedObjects(API, UndocumentedHooks) local f = io.open("API/_undocumented.lua", "w"); if (f ~= nil) then f:write("\n-- This is the list of undocumented API objects, automatically generated by APIDump\n\n"); f:write("return\n{\n\tClasses =\n\t{\n"); for _, cls in ipairs(API) do local HasFunctions = ((cls.UndocumentedFunctions ~= nil) and (#cls.UndocumentedFunctions > 0)); local HasConstants = ((cls.UndocumentedConstants ~= nil) and (#cls.UndocumentedConstants > 0)); local HasVariables = ((cls.UndocumentedVariables ~= nil) and (#cls.UndocumentedVariables > 0)); g_Stats.NumUndocumentedFunctions = g_Stats.NumUndocumentedFunctions + #cls.UndocumentedFunctions; g_Stats.NumUndocumentedConstants = g_Stats.NumUndocumentedConstants + #cls.UndocumentedConstants; g_Stats.NumUndocumentedVariables = g_Stats.NumUndocumentedVariables + #cls.UndocumentedVariables; if (HasFunctions or HasConstants or HasVariables) then f:write("\t\t" .. cls.Name .. " =\n\t\t{\n"); if ((cls.Desc == nil) or (cls.Desc == "")) then f:write("\t\t\tDesc = \"\",\n"); end end if (HasFunctions) then f:write("\t\t\tFunctions =\n\t\t\t{\n"); table.sort(cls.UndocumentedFunctions); for _, fn in ipairs(cls.UndocumentedFunctions) do f:write("\t\t\t\t" .. fn .. " = { Params = \"\", Return = \"\", Notes = \"\" },\n"); end -- for j, fn - cls.UndocumentedFunctions[] f:write("\t\t\t},\n\n"); end if (HasConstants) then f:write("\t\t\tConstants =\n\t\t\t{\n"); table.sort(cls.UndocumentedConstants); for _, cn in ipairs(cls.UndocumentedConstants) do f:write("\t\t\t\t" .. cn .. " = { Notes = \"\" },\n"); end -- for j, fn - cls.UndocumentedConstants[] f:write("\t\t\t},\n\n"); end if (HasVariables) then f:write("\t\t\tVariables =\n\t\t\t{\n"); table.sort(cls.UndocumentedVariables); for _, vn in ipairs(cls.UndocumentedVariables) do f:write("\t\t\t\t" .. vn .. " = { Type = \"\", Notes = \"\" },\n"); end -- for j, fn - cls.UndocumentedVariables[] f:write("\t\t\t},\n\n"); end if (HasFunctions or HasConstants or HasVariables) then f:write("\t\t},\n\n"); end end -- for i, cls - API[] f:write("\t},\n"); if (#UndocumentedHooks > 0) then f:write("\n\tHooks =\n\t{\n"); for i, hook in ipairs(UndocumentedHooks) do if (i > 1) then f:write("\n"); end f:write("\t\t" .. hook .. " =\n\t\t{\n"); f:write("\t\t\tCalledWhen = \"\",\n"); f:write("\t\t\tDefaultFnName = \"On\", -- also used as pagename\n"); f:write("\t\t\tDesc = [[\n\t\t\t\t\n\t\t\t]],\n"); f:write("\t\t\tParams =\n\t\t\t{\n"); f:write("\t\t\t\t{ Name = \"\", Type = \"\", Notes = \"\" },\n"); f:write("\t\t\t\t{ Name = \"\", Type = \"\", Notes = \"\" },\n"); f:write("\t\t\t\t{ Name = \"\", Type = \"\", Notes = \"\" },\n"); f:write("\t\t\t\t{ Name = \"\", Type = \"\", Notes = \"\" },\n"); f:write("\t\t\t\t{ Name = \"\", Type = \"\", Notes = \"\" },\n"); f:write("\t\t\t\t{ Name = \"\", Type = \"\", Notes = \"\" },\n"); f:write("\t\t\t\t{ Name = \"\", Type = \"\", Notes = \"\" },\n"); f:write("\t\t\t\t{ Name = \"\", Type = \"\", Notes = \"\" },\n"); f:write("\t\t\t},\n"); f:write("\t\t\tReturns = [[\n\t\t\t\t\n\t\t\t]],\n"); f:write("\t\t}, -- " .. hook .. "\n"); end f:write("\t},\n"); end f:write("}\n\n\n\n"); f:close(); end g_Stats.NumUndocumentedHooks = #UndocumentedHooks; end --- Lists the API objects that are documented but not available in the API: local function ListUnexportedObjects(a_APIDesc) f = io.open("API/_unexported-documented.txt", "w"); if (f ~= nil) then for clsname, cls in pairs(a_APIDesc.Classes) do if not(cls.IsExported) then -- The whole class is not exported f:write("class\t" .. clsname .. "\n"); else if (cls.Functions ~= nil) then for fnname, fnapi in pairs(cls.Functions) do if not(fnapi.IsExported) then f:write("func\t" .. clsname .. "." .. fnname .. "\n"); end end -- for j, fn - cls.Functions[] end if (cls.Constants ~= nil) then for cnname, cnapi in pairs(cls.Constants) do if not(cnapi.IsExported) then f:write("const\t" .. clsname .. "." .. cnname .. "\n"); end end -- for j, fn - cls.Functions[] end end end -- for i, cls - a_APIDesc.Classes[] f:close(); end end local function ListMissingPages() local MissingPages = {}; local NumLinks = 0; for PageName, Referrers in pairs(g_TrackedPages) do NumLinks = NumLinks + 1; if not(cFile:IsFile("API/" .. PageName .. ".html")) then table.insert(MissingPages, {Name = PageName, Refs = Referrers} ); end end; g_Stats.NumTrackedLinks = NumLinks; g_TrackedPages = {}; if (#MissingPages == 0) then -- No missing pages, congratulations! return; end -- Sort the pages by name: table.sort(MissingPages, function (Page1, Page2) return (Page1.Name < Page2.Name); end ); -- Output the pages: local f, err = io.open("API/_missingPages.txt", "w"); if (f == nil) then LOGWARNING("Cannot open _missingPages.txt for writing: '" .. err .. "'. There are " .. #MissingPages .. " pages missing."); return; end for _, pg in ipairs(MissingPages) do f:write(pg.Name .. ":\n"); -- Sort and output the referrers: table.sort(pg.Refs); f:write("\t" .. table.concat(pg.Refs, "\n\t")); f:write("\n\n"); end f:close(); g_Stats.NumInvalidLinks = #MissingPages; end --- Writes the documentation statistics (in g_Stats) into the given HTML file local function WriteStats(f) local function ExportMeter(a_Percent) local Color; if (a_Percent > 99) then Color = "green"; elseif (a_Percent > 50) then Color = "orange"; else Color = "red"; end local meter = { "\n", "
    \n", "
    \n", string.format("%.2f", a_Percent), " %", }; return table.concat(meter, ""); end f:write([[

    Documentation statistics

    ]]); f:write("\n"); f:write("\n"); f:write("\n"); f:write("\n"); f:write("\n"); f:write([[
    ObjectTotalDocumentedUndocumentedDocumented %
    Classes", g_Stats.NumTotalClasses); f:write("", g_Stats.NumTotalClasses - g_Stats.NumUndocumentedClasses); f:write("", g_Stats.NumUndocumentedClasses); f:write("", ExportMeter(100 * (g_Stats.NumTotalClasses - g_Stats.NumUndocumentedClasses) / g_Stats.NumTotalClasses)); f:write("
    Functions", g_Stats.NumTotalFunctions); f:write("", g_Stats.NumTotalFunctions - g_Stats.NumUndocumentedFunctions); f:write("", g_Stats.NumUndocumentedFunctions); f:write("", ExportMeter(100 * (g_Stats.NumTotalFunctions - g_Stats.NumUndocumentedFunctions) / g_Stats.NumTotalFunctions)); f:write("
    Member variables", g_Stats.NumTotalVariables); f:write("", g_Stats.NumTotalVariables - g_Stats.NumUndocumentedVariables); f:write("", g_Stats.NumUndocumentedVariables); f:write("", ExportMeter(100 * (g_Stats.NumTotalVariables - g_Stats.NumUndocumentedVariables) / g_Stats.NumTotalVariables)); f:write("
    Constants", g_Stats.NumTotalConstants); f:write("", g_Stats.NumTotalConstants - g_Stats.NumUndocumentedConstants); f:write("", g_Stats.NumUndocumentedConstants); f:write("", ExportMeter(100 * (g_Stats.NumTotalConstants - g_Stats.NumUndocumentedConstants) / g_Stats.NumTotalConstants)); f:write("
    Hooks", g_Stats.NumTotalHooks); f:write("", g_Stats.NumTotalHooks - g_Stats.NumUndocumentedHooks); f:write("", g_Stats.NumUndocumentedHooks); f:write("", ExportMeter(100 * (g_Stats.NumTotalHooks - g_Stats.NumUndocumentedHooks) / g_Stats.NumTotalHooks)); f:write("

    There are ]], g_Stats.NumTrackedLinks, " internal links, ", g_Stats.NumInvalidLinks, " of them are invalid.

    " ); end local function DumpAPIHtml(a_API, a_Descs) LOG("Dumping all available functions and constants to API subfolder..."); -- Create the output folder if not(cFile:IsFolder("API")) then cFile:CreateFolder("API"); end LOG("Copying static files.."); cFile:CreateFolder("API/Static"); local localFolder = g_Plugin:GetLocalFolder(); for _, fnam in ipairs(cFile:GetFolderContents(localFolder .. "/Static")) do cFile:Delete("API/Static/" .. fnam); cFile:Copy(localFolder .. "/Static/" .. fnam, "API/Static/" .. fnam); end -- Extract hook constants: local Hooks = {}; local UndocumentedHooks = {}; for name, obj in pairs(cPluginManager) do if ( (type(obj) == "number") and name:match("HOOK_.*") and (name ~= "HOOK_MAX") and (name ~= "HOOK_NUM_HOOKS") ) then table.insert(Hooks, { Name = name }); end end table.sort(Hooks, function(Hook1, Hook2) return (Hook1.Name < Hook2.Name); end ); ReadHooks(Hooks, a_Descs); -- Create a "class index" file, write each class as a link to that file, -- then dump class contents into class-specific file LOG("Writing HTML files..."); local f, err = io.open("API/index.html", "w"); if (f == nil) then LOGINFO("Cannot output HTML API: " .. err); return; end -- Create a class navigation menu that will be inserted into each class file for faster navigation (#403) local ClassMenuTab = {}; for _, cls in ipairs(a_API) do table.insert(ClassMenuTab, ""); table.insert(ClassMenuTab, cls.Name); table.insert(ClassMenuTab, "
    "); end local ClassMenu = table.concat(ClassMenuTab, ""); -- Create a hook navigation menu that will be inserted into each hook file for faster navigation(#403) local HookNavTab = {}; for _, hook in ipairs(Hooks) do table.insert(HookNavTab, ""); table.insert(HookNavTab, (hook.Name:gsub("^HOOK_", ""))); -- remove the "HOOK_" part of the name table.insert(HookNavTab, "
    "); end local HookNav = table.concat(HookNavTab, ""); -- Write the HTML file: f:write([[ Cuberite API - Index

    Cuberite API - Index


    The API reference is divided into the following sections:


    ]]); WriteArticles(f, a_Descs); WriteClasses(f, a_API, ClassMenu); WriteHooks(f, Hooks, UndocumentedHooks, HookNav, a_API); -- Copy the static files to the output folder: local StaticFiles = { "main.css", "prettify.js", "prettify.css", "lang-lua.js", }; for _, fnam in ipairs(StaticFiles) do cFile:Delete("API/" .. fnam); cFile:Copy(g_Plugin:GetLocalFolder() .. "/" .. fnam, "API/" .. fnam); end -- List the documentation problems: LOG("Listing leftovers..."); ListUndocumentedObjects(a_API, UndocumentedHooks); ListUnexportedObjects(a_Descs); ListMissingPages(); WriteStats(f); f:write([[
    ]]) f:write(GetHtmlTimestamp()) f:write([[]]) f:close() LOG("API subfolder written"); end --- Returns the string with extra tabs and CR/LFs removed function CleanUpDescription(a_Desc) -- Get rid of indent and newlines, normalize whitespace: local res = a_Desc:gsub("[\n\t]", "") res = a_Desc:gsub("%s%s+", " ") -- Replace paragraph marks with newlines: res = res:gsub("

    ", "\n") res = res:gsub("

    ", "") -- Replace list items with dashes: res = res:gsub("", "") res = res:gsub("
  • ", "\n - ") res = res:gsub("
  • ", "") return res end --- Writes a list of methods into the specified file in ZBS format local function WriteZBSMethods(f, a_Methods) for _, func in ipairs(a_Methods or {}) do f:write("\t\t\t[\"", func.Name, "\"] =\n") f:write("\t\t\t{\n") f:write("\t\t\t\ttype = \"method\",\n") -- No way to indicate multiple signatures to ZBS, so don't output any params at all if ((func.Notes ~= nil) and (func.Notes ~= "")) then f:write("\t\t\t\tdescription = [[", CleanUpDescription(func.Notes or ""), " ]],\n") end f:write("\t\t\t},\n") end end --- Writes a list of constants into the specified file in ZBS format local function WriteZBSConstants(f, a_Constants) for _, cons in ipairs(a_Constants or {}) do f:write("\t\t\t[\"", cons.Name, "\"] =\n") f:write("\t\t\t{\n") f:write("\t\t\t\ttype = \"value\",\n") if ((cons.Desc ~= nil) and (cons.Desc ~= "")) then f:write("\t\t\t\tdescription = [[", CleanUpDescription(cons.Desc or ""), " ]],\n") end f:write("\t\t\t},\n") end end --- Writes one Cuberite class definition into the specified file in ZBS format local function WriteZBSClass(f, a_Class) assert(type(a_Class) == "table") -- Write class header: f:write("\t", a_Class.Name, " =\n\t{\n") f:write("\t\ttype = \"class\",\n") f:write("\t\tdescription = [[", CleanUpDescription(a_Class.Desc or ""), " ]],\n") f:write("\t\tchilds =\n") f:write("\t\t{\n") -- Export methods and constants: WriteZBSMethods(f, a_Class.Functions) WriteZBSConstants(f, a_Class.Constants) -- Finish the class definition: f:write("\t\t},\n") f:write("\t},\n\n") end --- Dumps the entire API table into a file in the ZBS format local function DumpAPIZBS(a_API) LOG("Dumping ZBS API description...") local f, err = io.open("cuberite_api.lua", "w") if (f == nil) then LOG("Cannot open cuberite_api.lua for writing, ZBS API will not be dumped. " .. err) return end -- Write the file header: f:write("-- This is a Cuberite API file automatically generated by the APIDump plugin\n") f:write("-- Note that any manual changes will be overwritten by the next dump\n\n") f:write("return {\n") -- Export each class except Globals, store those aside: local Globals for _, cls in ipairs(a_API) do if (cls.Name ~= "Globals") then WriteZBSClass(f, cls) else Globals = cls end end -- Export the globals: if (Globals) then WriteZBSMethods(f, Globals.Functions) WriteZBSConstants(f, Globals.Constants) end -- Finish the file: f:write("}\n") f:close() LOG("ZBS API dumped...") end local function DumpLuaCheck(a_API) LOG("Creating file .luacheckrc...") local file = io.open(".luacheckrc", "w") file:write([[ -- This file is the config file for the tool named Luacheck -- Documentation: https://luacheck.readthedocs.io/en/stable/index.html -- Ignore unused function and loop arguments unused_args = false -- Allow self defined globals allow_defined = true -- Ignore this functions ignore = { "Initialize", -- Plugin "OnDisable", -- Plugin "RegisterPluginInfoCommands", -- InfoReg.lua "RegisterPluginInfoConsoleCommands", -- InfoReg.lua "g_PluginInfo", -- Info.lua } -- Ignore files / directories exclude_files = { "tests/" -- CuberitePluginChecker } -- All globals from cuberite (classes, enums, functions) globals = { ]]) -- Export all global symbols for _, cls in ipairs(a_API) do if cls.Name == "Globals" then -- Global functions for _, func in ipairs(cls.Functions) do file:write("\t\"", func.Name, "\",\n") end -- Global constants for _, const in ipairs(cls.Constants) do file:write("\t\"", const.Name, "\",\n") end -- Global constants from all groups for _, group in pairs(cls.ConstantGroups) do for _, const in pairs(group.Constants) do file:write("\t\"", const.Name, "\",\n") end end else file:write("\t\"", cls.Name, "\",\n") end end file:write("}\n\n") -- Add merge code file:write([[ -- ## Main ## -- Load plugins's luacheck local FilePluginLuacheck = loadfile(".luacheckrc_plugin") if FilePluginLuacheck ~= nil then local PluginLuacheck = {} setfenv(FilePluginLuacheck, PluginLuacheck) FilePluginLuacheck() for Option, Value in pairs(PluginLuacheck) do if (type(Value) == "table") and not(getfenv(1)[Option] == nil) then -- Merge tables together for _ , Entry in ipairs(Value) do table.insert(getfenv(1)[Option], Entry) end else -- Add a option, table or overwrite a option getfenv(1)[Option] = Value end end end ]]) file:close() LOG("Config file .luacheckrc created...") end --- Returns true if a_Descendant is declared to be a (possibly indirect) descendant of a_Base local function IsDeclaredDescendant(a_DescendantName, a_BaseName, a_API) -- Check params: assert(type(a_DescendantName) == "string") assert(type(a_BaseName) == "string") assert(type(a_API) == "table") if not(a_API[a_BaseName]) then return false end assert(type(a_API[a_BaseName]) == "table", "Not a class name: " .. a_BaseName) assert(type(a_API[a_BaseName].Descendants) == "table") -- Check direct inheritance: for _, desc in ipairs(a_API[a_BaseName].Descendants) do if (desc.Name == a_DescendantName) then return true end end -- for desc - a_BaseName's descendants -- Check indirect inheritance: for _, desc in ipairs(a_API[a_BaseName].Descendants) do if (IsDeclaredDescendant(a_DescendantName, desc.Name, a_API)) then return true end end -- for desc - a_BaseName's descendants return false end --- Checks the specified class' inheritance -- Reports any problems as new items in the a_Report table local function CheckClassInheritance(a_Class, a_API, a_Report) -- Check params: assert(type(a_Class) == "table") assert(type(a_API) == "table") assert(type(a_Report) == "table") -- Check that the declared descendants are really descendants: local registry = debug.getregistry() for _, desc in ipairs(a_Class.Descendants or {}) do local isParent = false local parents = registry["tolua_super"][_G[desc.Name]] if not(parents[a_Class.Name]) then table.insert(a_Report, desc.Name .. " is not a descendant of " .. a_Class.Name) end end -- for desc - a_Class.Descendants[] -- Check that all inheritance is listed for the class: local parents = registry["tolua_super"][_G[a_Class.Name]] -- map of "classname" -> true for each class that a_Class inherits for clsName, isParent in pairs(parents or {}) do if ((clsName ~= "") and not(clsName:match("const .*"))) then if not(IsDeclaredDescendant(a_Class.Name, clsName, a_API)) then table.insert(a_Report, a_Class.Name .. " inherits from " .. clsName .. " but this isn't documented") end end end end --- Checks each class's declared inheritance versus the actual inheritance local function CheckAPIDescendants(a_API) -- Check each class: local report = {} for _, cls in ipairs(a_API) do if (cls.Name ~= "Globals") then CheckClassInheritance(cls, a_API, report) end end -- If there's anything to report, output it to a file: if (report[1] ~= nil) then LOG("There are inheritance errors in the API description:") for _, msg in ipairs(report) do LOG(" " .. msg) end local f, err = io.open("API/_inheritance_errors.txt", "w") if (f == nil) then LOG("Cannot report inheritance problems to a file: " .. tostring(err)) return end f:write(table.concat(report, "\n")) f:close() end end --- Prepares the API and Globals tables containing the documentation -- Returns the API and Globals desc table, containing the Classes and Hooks subtables with descriptions, -- and the apiDesc table containing the descriptions only in their original format. local function PrepareApi() -- Load the API descriptions from the Classes and Hooks subfolders: -- This needs to be done each time the command is invoked because the export modifies the tables' contents local apiDesc = dofile(g_PluginFolder .. "/APIDesc.lua") apiDesc.Classes = apiDesc.Classes or {} apiDesc.Hooks = apiDesc.Hooks or {} LoadAPIFiles("/Classes/", apiDesc.Classes) LoadAPIFiles("/Hooks/", apiDesc.Hooks) -- Reset the stats: g_TrackedPages = {}; -- List of tracked pages, to be checked later whether they exist. Each item is an array of referring pagenames. g_Stats = -- Statistics about the documentation { NumTotalClasses = 0, NumUndocumentedClasses = 0, NumTotalFunctions = 0, NumUndocumentedFunctions = 0, NumTotalConstants = 0, NumUndocumentedConstants = 0, NumTotalVariables = 0, NumUndocumentedVariables = 0, NumTotalHooks = 0, NumUndocumentedHooks = 0, NumTrackedLinks = 0, NumInvalidLinks = 0, } -- Create the API tables: local API, Globals = CreateAPITables(); -- Sort the classes by name: table.sort(API, function (c1, c2) return (string.lower(c1.Name) < string.lower(c2.Name)); end ); g_Stats.NumTotalClasses = #API; -- Add Globals into the API: Globals.Name = "Globals"; table.insert(API, Globals); API.Globals = Globals -- Read in the descriptions: LOG("Reading descriptions..."); ReadDescriptions(API, apiDesc); return API, Globals, apiDesc end local function DumpApi() LOG("Dumping the API...") -- Match the currently exported API with the available documentation: local API, Globals, descs = PrepareApi() -- Check that the API lists the inheritance properly, report any problems to a file: CheckAPIDescendants(API) -- Dump all available API objects in HTML format into a subfolder: DumpAPIHtml(API, descs); -- Dump all available API objects in format used by ZeroBraneStudio API descriptions: DumpAPIZBS(API) -- Dump all available API objects in format used by Lua-Language-Server API descriptions: DumpAPILLS(API); -- Export the API in a format used by LuaCheck DumpLuaCheck(API) LOG("APIDump finished"); return true end --- Checks the currently undocumented symbols against an "official" undocumented symbol list -- Returns an array-table of strings representing the newly-undocumented symbol names -- If no newly undocumented symbols are found, returns no value. -- If an error occurs, returns true and error message. local function CheckNewUndocumentedSymbols() -- Download the official API stats on undocumented stuff: -- (We need a blocking downloader, which is impossible with the current cNetwork API) assert(os.execute("wget -q -O official_undocumented.lua https://api.cuberite.org/_undocumented.lua")) local OfficialStats = cFile:ReadWholeFile("official_undocumented.lua") if (OfficialStats == "") then return true, "Cannot load official stats" end -- Load the API stats as a Lua file, process into usable dictionary: -- The _undocumented.lua file format has changed from "g_APIDesc = {}" to "return {}" -- To support both versions, we execute the function in a sandbox and check both its return value and the sandbox globals local Loaded, Msg = loadstring(OfficialStats) if not(Loaded) then return true, "Cannot load official stats: " .. (Msg or "") end local sandbox = {} setfenv(Loaded, sandbox) local IsSuccess, OfficialUndocumented = pcall(Loaded) if not(IsSuccess) then return true, "Cannot parse official stats: " .. tostring(OfficialUndocumented or "") end local Parsed = {} for clsK, clsV in pairs((sandbox.g_APIDesc or OfficialUndocumented).Classes) do -- Check return value OR sandbox global, whichever is present local cls = { Desc = not(clsV.Desc), -- set to true if the Desc was not documented in the official docs Functions = {}, Constants = {} } for funK, _ in pairs(clsV.Functions or {}) do cls.Functions[funK] = true end for conK, _ in pairs(clsV.Constants or {}) do cls.Constants[conK] = true end Parsed[clsK] = cls end -- Get the current API's undocumented stats: local API = PrepareApi() -- Compare the two sets of undocumented stats, list anything extra in current: local res = {} local ins = table.insert for _, cls in ipairs(API) do local ParsedOfficial = Parsed[cls.Name] or {} if (not(cls.Desc) and ParsedOfficial.Desc) then ins(res, cls.Name .. ".Desc") end local ParsedOfficialFns = ParsedOfficial.Functions or {} for _, funK in ipairs(cls.UndocumentedFunctions or {}) do if not(ParsedOfficialFns[funK]) then ins(res, cls.Name .. "." .. funK .. " (function)") end end local ParsedOfficialCons = ParsedOfficial.Constants or {} for _, conK in ipairs(cls.UndocumentedConstants or {}) do if not(ParsedOfficialCons[conK]) then ins(res, cls.Name .. "." .. conK .. " (constant)") end end end table.sort(res) -- Bail out if no items found: if not(res[1]) then return end -- Save any found items to a file: local f = io.open("NewlyUndocumented.lua", "w") f:write(table.concat(res, "\n")) f:write("\n") f:close() return res end --- Checks the API description for unknown types listed in Params or Returns -- Returns an array-table of { Location = "cClass:function(), param #1", Type = "UnknownType" } -- Returns nil if no unknown types are found local function CheckBadTypes() -- Load the API and preprocess known types: local api = PrepareApi() local knownTypes = { string = true, number = true, boolean = true, any = true, self = true, table = true, ["function"] = true, ["..."] = true, ["SQLite DB object"] = true, [""] = true, -- Allow "" types, for now, until the API is properly documented } for _, clsDesc in ipairs(api) do knownTypes[clsDesc.Name] = true -- The class is a known type for grpName, _ in pairs(clsDesc.ConstantGroups or {}) do -- All class' enums are known types (with namespacing) knownTypes[clsDesc.Name .. "#" .. grpName] = true end if (clsDesc.Name == "Globals") then for grpName, _ in pairs(clsDesc.ConstantGroups or {}) do -- All Globals' enums are known types without namespacing, too knownTypes[grpName] = true end end end -- for cls - classes -- Check types: local res = {} for _, clsDesc in ipairs(api) do for _, fnDesc in ipairs(clsDesc.Functions or {}) do local fnName = fnDesc.Name local fn = fnDesc[1] and fnDesc or { fnDesc } -- Unify the format, fn is an array of function signatures for idxS, signature in ipairs(fn) do for idxP, param in ipairs(signature.Params or {}) do if not(knownTypes[param.Type]) then table.insert(res, { Location = string.format("%s:%s(), signature #%d, param #%d", clsDesc.Name, fnName, idxS, idxP), Type = param.Type, }) end end -- for param if (type(signature.Returns) == "table") then for idxR, ret in ipairs(signature.Returns) do if not(knownTypes[ret.Type]) then table.insert(res, { Location = string.format("%s:%s(), signature #%d, return #%d", clsDesc.Name, fnName, idxS, idxR), Type = ret.Type, }) end end -- for ret elseif not(signature.Returns) then else table.insert(res, { Location = string.format("%s:%s(), signature #%d, return string", clsDesc.Name, fnName, idxS), Type = tostring(signature.Returns), }) end end -- for signature end -- for fn - functions end -- for cls - classes -- If no problems found, bail out: if not(res[1]) then return end -- Write the problems into a file: local f = io.open("UnknownTypes.lua", "w") f:write("return\n{\n") for _, item in ipairs(res) do f:write("\t{ ", string.format("{ Location = %q, Type = %q", item.Location, item.Type), "},\n") end f:write("}\n") f:close() return res end --- Checks if any functions that are documented are present in the API -- Returns an array-table of strings representing the unexported symbol names -- If no unexported are found, returns no value. -- If an error occurs, returns true and error message. local function CheckUnexportedFunctions() local res = {} local API, Globals, Desc = PrepareApi() for clsname, cls in pairs(Desc.Classes) do if not(cls.IsExported) then -- The whole class is not exported table.insert(res, "class\t" .. clsname .. "\n"); else if (cls.Functions ~= nil) then for fnname, fnapi in pairs(cls.Functions) do if not(fnapi.IsExported) then table.insert(res, "func\t" .. clsname .. "." .. fnname); end end -- for j, fn - cls.Functions[] end if (cls.Constants ~= nil) then for cnname, cnapi in pairs(cls.Constants) do if not(cnapi.IsExported) then table.insert(res, "const\t" .. clsname .. "." .. cnname); end end -- for j, fn - cls.Functions[] end end end -- for i, cls - a_APIDesc.Classes[] table.sort(res) -- Bail out if no items found: if not(res[1]) then return end -- Save any found items to a file: local f = io.open("Unexported.lua", "w") f:write(table.concat(res, "\n")) f:write("\n") f:close() return res end local function HandleWebAdminDump(a_Request) if (a_Request.PostParams["Dump"] ~= nil) then DumpApi() end return [[

    Pressing the button will generate the API dump on the server. Note that this can take some time.

    ]] end local function HandleCmdApi(a_Split) DumpApi() return true end local function HandleCmdApiShow(a_Split, a_EntireCmd) os.execute("API" .. cFile:GetPathSeparator() .. "index.html") return true, "Launching the browser to show the API docs..." end local function HandleCmdApiCheck(a_Split, a_EntireCmd) -- Check the Params and Returns types: LOG("Checking API for bad types...") local badTypes = CheckBadTypes() if (badTypes) then -- Serialize into descriptions: local descs = {} for idx, t in ipairs(badTypes) do descs[idx] = string.format("Location %q, type %q", t.Location, t.Type) end return true, "Found bad types:\n" .. table.concat(descs, "\n") end -- Check for new symbols that are not documented: LOG("Checking API for newly undocumented symbols...") local newUndocumented, msg = CheckNewUndocumentedSymbols() if (newUndocumented) then if (newUndocumented == true) then LOGERROR("Cannot check for new undocumented symbols: " .. (msg or "")) return true else LOGERROR("Found new undocumented symbols:\n" .. table.concat(newUndocumented, "\n")) return true end end LOG("Checking for unexported Objects...") local unexported, msg = CheckUnexportedFunctions() if (unexported) then if (unexported == true) then LOGERROR("Cannot check for unexported symbols: " .. (msg or "")) return true else LOGERROR("Found unexported symbols:\n" .. table.concat(unexported, "\n")) return true end end -- The check completed successfully, remove the "test failed" flag from the filesystem: cFile:DeleteFile("apiCheckFailed.flag") return true, "API check completed successfully" end function Initialize(Plugin) g_Plugin = Plugin; g_PluginFolder = Plugin:GetLocalFolder(); LOG("Initialising v." .. Plugin:GetVersion()) -- Bind a console command to dump the API: cPluginManager:BindConsoleCommand("api", HandleCmdApi, "Dumps the Lua API docs into the API/ subfolder") cPluginManager:BindConsoleCommand("apicheck", HandleCmdApiCheck, "Checks the Lua API documentation stats against the official stats") cPluginManager:BindConsoleCommand("apishow", HandleCmdApiShow, "Runs the default browser to show the API docs") -- Add a WebAdmin tab that has a Dump button g_Plugin:AddWebTab("APIDump", HandleWebAdminDump) return true end ================================================ FILE: Server/Plugins/APIDump/prettify.css ================================================ .pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee} ================================================ FILE: Server/Plugins/APIDump/prettify.js ================================================ !function(){var q=null;window.PR_SHOULD_USE_CONTINUATION=!0; (function(){function S(a){function d(e){var b=e.charCodeAt(0);if(b!==92)return b;var a=e.charAt(1);return(b=r[a])?b:"0"<=a&&a<="7"?parseInt(e.substring(1),8):a==="u"||a==="x"?parseInt(e.substring(2),16):e.charCodeAt(1)}function g(e){if(e<32)return(e<16?"\\x0":"\\x")+e.toString(16);e=String.fromCharCode(e);return e==="\\"||e==="-"||e==="]"||e==="^"?"\\"+e:e}function b(e){var b=e.substring(1,e.length-1).match(/\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\[0-3][0-7]{0,2}|\\[0-7]{1,2}|\\[\S\s]|[^\\]/g),e=[],a= b[0]==="^",c=["["];a&&c.push("^");for(var a=a?1:0,f=b.length;a122||(l<65||h>90||e.push([Math.max(65,h)|32,Math.min(l,90)|32]),l<97||h>122||e.push([Math.max(97,h)&-33,Math.min(l,122)&-33]))}}e.sort(function(e,a){return e[0]-a[0]||a[1]-e[1]});b=[];f=[];for(a=0;ah[0]&&(h[1]+1>h[0]&&c.push("-"),c.push(g(h[1])));c.push("]");return c.join("")}function s(e){for(var a=e.source.match(/\[(?:[^\\\]]|\\[\S\s])*]|\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\\d+|\\[^\dux]|\(\?[!:=]|[()^]|[^()[\\^]+/g),c=a.length,d=[],f=0,h=0;f=2&&e==="["?a[f]=b(l):e!=="\\"&&(a[f]=l.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return a.join("")}for(var x=0,m=!1,j=!1,k=0,c=a.length;k=5&&"lang-"===w.substring(0,5))&&!(t&&typeof t[1]==="string"))f=!1,w="src";f||(r[z]=w)}h=c;c+=z.length;if(f){f=t[1];var l=z.indexOf(f),B=l+f.length;t[2]&&(B=z.length-t[2].length,l=B-f.length);w=w.substring(5);H(j+h,z.substring(0,l),g,k);H(j+h+l,f,I(w,f),k);H(j+h+B,z.substring(B),g,k)}else k.push(j+h,w)}a.g=k}var b={},s;(function(){for(var g=a.concat(d),j=[],k={},c=0,i=g.length;c=0;)b[n.charAt(e)]=r;r=r[1];n=""+r;k.hasOwnProperty(n)||(j.push(r),k[n]=q)}j.push(/[\S\s]/);s=S(j)})();var x=d.length;return g}function v(a){var d=[],g=[];a.tripleQuotedStrings?d.push(["str",/^(?:'''(?:[^'\\]|\\[\S\s]|''?(?=[^']))*(?:'''|$)|"""(?:[^"\\]|\\[\S\s]|""?(?=[^"]))*(?:"""|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$))/,q,"'\""]):a.multiLineStrings?d.push(["str",/^(?:'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$)|`(?:[^\\`]|\\[\S\s])*(?:`|$))/, q,"'\"`"]):d.push(["str",/^(?:'(?:[^\n\r'\\]|\\.)*(?:'|$)|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,q,"\"'"]);a.verbatimStrings&&g.push(["str",/^@"(?:[^"]|"")*(?:"|$)/,q]);var b=a.hashComments;b&&(a.cStyleComments?(b>1?d.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,q,"#"]):d.push(["com",/^#(?:(?:define|e(?:l|nd)if|else|error|ifn?def|include|line|pragma|undef|warning)\b|[^\n\r]*)/,q,"#"]),g.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h(?:h|pp|\+\+)?|[a-z]\w*)>/,q])):d.push(["com", /^#[^\n\r]*/,q,"#"]));a.cStyleComments&&(g.push(["com",/^\/\/[^\n\r]*/,q]),g.push(["com",/^\/\*[\S\s]*?(?:\*\/|$)/,q]));if(b=a.regexLiterals){var s=(b=b>1?"":"\n\r")?".":"[\\S\\s]";g.push(["lang-regex",RegExp("^(?:^^\\.?|[+-]|[!=]=?=?|\\#|%=?|&&?=?|\\(|\\*=?|[+\\-]=|->|\\/=?|::?|<>?>?=?|,|;|\\?|@|\\[|~|{|\\^\\^?=?|\\|\\|?=?|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*("+("/(?=[^/*"+b+"])(?:[^/\\x5B\\x5C"+b+"]|\\x5C"+s+"|\\x5B(?:[^\\x5C\\x5D"+b+"]|\\x5C"+ s+")*(?:\\x5D|$))+/")+")")])}(b=a.types)&&g.push(["typ",b]);b=(""+a.keywords).replace(/^ | $/g,"");b.length&&g.push(["kwd",RegExp("^(?:"+b.replace(/[\s,]+/g,"|")+")\\b"),q]);d.push(["pln",/^\s+/,q," \r\n\t\u00a0"]);b="^.[^\\s\\w.$@'\"`/\\\\]*";a.regexLiterals&&(b+="(?!s*/)");g.push(["lit",/^@[$_a-z][\w$@]*/i,q],["typ",/^(?:[@_]?[A-Z]+[a-z][\w$@]*|\w+_t\b)/,q],["pln",/^[$_a-z][\w$@]*/i,q],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,q,"0123456789"],["pln",/^\\[\S\s]?/, q],["pun",RegExp(b),q]);return C(d,g)}function J(a,d,g){function b(a){var c=a.nodeType;if(c==1&&!x.test(a.className))if("br"===a.nodeName)s(a),a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)b(a);else if((c==3||c==4)&&g){var d=a.nodeValue,i=d.match(m);if(i)c=d.substring(0,i.index),a.nodeValue=c,(d=d.substring(i.index+i[0].length))&&a.parentNode.insertBefore(j.createTextNode(d),a.nextSibling),s(a),c||a.parentNode.removeChild(a)}}function s(a){function b(a,c){var d= c?a.cloneNode(!1):a,e=a.parentNode;if(e){var e=b(e,1),g=a.nextSibling;e.appendChild(d);for(var i=g;i;i=g)g=i.nextSibling,e.appendChild(i)}return d}for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),d;(d=a.parentNode)&&d.nodeType===1;)a=d;c.push(a)}for(var x=/(?:^|\s)nocode(?:\s|$)/,m=/\r\n?|\n/,j=a.ownerDocument,k=j.createElement("li");a.firstChild;)k.appendChild(a.firstChild);for(var c=[k],i=0;i=0;){var b=d[g];F.hasOwnProperty(b)?D.console&&console.warn("cannot override language handler %s",b):F[b]=a}}function I(a,d){if(!a||!F.hasOwnProperty(a))a=/^\s*=l&&(b+=2);g>=B&&(r+=2)}}finally{if(f)f.style.display=h}}catch(u){D.console&&console.log(u&&u.stack||u)}}var D=window,y=["break,continue,do,else,for,if,return,while"],E=[[y,"auto,case,char,const,default,double,enum,extern,float,goto,inline,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"], "catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],M=[E,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,delegate,dynamic_cast,explicit,export,friend,generic,late_check,mutable,namespace,nullptr,property,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],N=[E,"abstract,assert,boolean,byte,extends,final,finally,implements,import,instanceof,interface,null,native,package,strictfp,super,synchronized,throws,transient"], O=[N,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,internal,into,is,let,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var,virtual,where"],E=[E,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"],P=[y,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"], Q=[y,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],W=[y,"as,assert,const,copy,drop,enum,extern,fail,false,fn,impl,let,log,loop,match,mod,move,mut,priv,pub,pure,ref,self,static,struct,true,trait,type,unsafe,use"],y=[y,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],R=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)\b/, V=/\S/,X=v({keywords:[M,O,E,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",P,Q,y],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),F={};p(X,["default-code"]);p(C([],[["pln",/^[^]*(?:>|$)/],["com",/^<\!--[\S\s]*?(?:--\>|$)/],["lang-",/^<\?([\S\s]+?)(?:\?>|$)/],["lang-",/^<%([\S\s]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-", /^]*>([\S\s]+?)<\/xmp\b[^>]*>/i],["lang-js",/^]*>([\S\s]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\S\s]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),["default-markup","htm","html","mxml","xhtml","xml","xsl"]);p(C([["pln",/^\s+/,q," \t\r\n"],["atv",/^(?:"[^"]*"?|'[^']*'?)/,q,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^\s"'>]*(?:[^\s"'/>]|\/(?=\s)))/],["pun",/^[/<->]+/], ["lang-js",/^on\w+\s*=\s*"([^"]+)"/i],["lang-js",/^on\w+\s*=\s*'([^']+)'/i],["lang-js",/^on\w+\s*=\s*([^\s"'>]+)/i],["lang-css",/^style\s*=\s*"([^"]+)"/i],["lang-css",/^style\s*=\s*'([^']+)'/i],["lang-css",/^style\s*=\s*([^\s"'>]+)/i]]),["in.tag"]);p(C([],[["atv",/^[\S\s]+/]]),["uq.val"]);p(v({keywords:M,hashComments:!0,cStyleComments:!0,types:R}),["c","cc","cpp","cxx","cyc","m"]);p(v({keywords:"null,true,false"}),["json"]);p(v({keywords:O,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:R}), ["cs"]);p(v({keywords:N,cStyleComments:!0}),["java"]);p(v({keywords:y,hashComments:!0,multiLineStrings:!0}),["bash","bsh","csh","sh"]);p(v({keywords:P,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}),["cv","py","python"]);p(v({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:2}),["perl","pl","pm"]);p(v({keywords:Q, hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb","ruby"]);p(v({keywords:E,cStyleComments:!0,regexLiterals:!0}),["javascript","js"]);p(v({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,throw,true,try,unless,until,when,while,yes",hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);p(v({keywords:W,cStyleComments:!0,multilineStrings:!0}),["rc","rs","rust"]); p(C([],[["str",/^[\S\s]+/]]),["regex"]);var Y=D.PR={createSimpleLexer:C,registerLangHandler:p,sourceDecorator:v,PR_ATTRIB_NAME:"atn",PR_ATTRIB_VALUE:"atv",PR_COMMENT:"com",PR_DECLARATION:"dec",PR_KEYWORD:"kwd",PR_LITERAL:"lit",PR_NOCODE:"nocode",PR_PLAIN:"pln",PR_PUNCTUATION:"pun",PR_SOURCE:"src",PR_STRING:"str",PR_TAG:"tag",PR_TYPE:"typ",prettyPrintOne:D.prettyPrintOne=function(a,d,g){var b=document.createElement("div");b.innerHTML="
    "+a+"
    ";b=b.firstChild;g&&J(b,g,!0);K({h:d,j:g,c:b,i:1}); return b.innerHTML},prettyPrint:D.prettyPrint=function(a,d){function g(){for(var b=D.PR_SHOULD_USE_CONTINUATION?c.now()+250:Infinity;i\nnext line\nanother line"); p:parse("text\n"); p:parse("\n"); p:parse("more text"); p:parse(""); p:parse("\n"); p:parse(); -- finishes the document p:close(); -- closes the parser LOG("Expat bindings test ended"); end function OnUsingBlazeRod(Player, BlockX, BlockY, BlockZ, BlockFace, CursorX, CursorY, CursorZ) -- Magic rod of query: show block types and metas for both neighbors of the pointed face local Valid, Type, Meta = Player:GetWorld():GetBlockTypeMeta(BlockX, BlockY, BlockZ); if (Type == E_BLOCK_AIR) then Player:SendMessage(cChatColor.LightGray .. "Block {" .. BlockX .. ", " .. BlockY .. ", " .. BlockZ .. "}: air:" .. Meta); else local TempItem = cItem(Type, 1, Meta); Player:SendMessage(cChatColor.LightGray .. "Block {" .. BlockX .. ", " .. BlockY .. ", " .. BlockZ .. "}: " .. ItemToFullString(TempItem) .. " (" .. Type .. ":" .. Meta .. ")"); end local X, Y, Z = AddFaceDirection(BlockX, BlockY, BlockZ, BlockFace); Valid, Type, Meta = Player:GetWorld():GetBlockTypeMeta(X, Y, Z); if (Type == E_BLOCK_AIR) then Player:SendMessage(cChatColor.LightGray .. "Block {" .. X .. ", " .. Y .. ", " .. Z .. "}: air:" .. Meta); else local TempItem = cItem(Type, 1, Meta); Player:SendMessage(cChatColor.LightGray .. "Block {" .. X .. ", " .. Y .. ", " .. Z .. "}: " .. ItemToFullString(TempItem) .. " (" .. Type .. ":" .. Meta .. ")"); end return false; end function OnUsingDiamond(Player, BlockX, BlockY, BlockZ, BlockFace, CursorX, CursorY, CursorZ) -- Rclk with a diamond to test block area cropping and expanding local Area = cBlockArea(); Area:Read(Player:GetWorld(), BlockX - 19, BlockX + 19, BlockY - 7, BlockY + 7, BlockZ - 19, BlockZ + 19 ); LOG("Size before cropping: " .. Area:GetSizeX() .. " x " .. Area:GetSizeY() .. " x " .. Area:GetSizeZ()); Area:DumpToRawFile("crop0.dat"); Area:Crop(2, 3, 0, 0, 0, 0); LOG("Size after cropping 1: " .. Area:GetSizeX() .. " x " .. Area:GetSizeY() .. " x " .. Area:GetSizeZ()); Area:DumpToRawFile("crop1.dat"); Area:Crop(2, 3, 0, 0, 0, 0); LOG("Size after cropping 2: " .. Area:GetSizeX() .. " x " .. Area:GetSizeY() .. " x " .. Area:GetSizeZ()); Area:DumpToRawFile("crop2.dat"); Area:Expand(2, 3, 0, 0, 0, 0); LOG("Size after expanding 1: " .. Area:GetSizeX() .. " x " .. Area:GetSizeY() .. " x " .. Area:GetSizeZ()); Area:DumpToRawFile("expand1.dat"); Area:Expand(3, 2, 1, 1, 0, 0); LOG("Size after expanding 2: " .. Area:GetSizeX() .. " x " .. Area:GetSizeY() .. " x " .. Area:GetSizeZ()); Area:DumpToRawFile("expand2.dat"); Area:Crop(0, 0, 0, 0, 3, 2); LOG("Size after cropping 3: " .. Area:GetSizeX() .. " x " .. Area:GetSizeY() .. " x " .. Area:GetSizeZ()); Area:DumpToRawFile("crop3.dat"); Area:Crop(0, 0, 3, 2, 0, 0); LOG("Size after cropping 4: " .. Area:GetSizeX() .. " x " .. Area:GetSizeY() .. " x " .. Area:GetSizeZ()); Area:DumpToRawFile("crop4.dat"); LOG("Crop test done"); Player:SendMessage("Crop / expand test done."); return false; end function OnUsingEyeOfEnder(Player, BlockX, BlockY, BlockZ) -- Rclk with an eye of ender places a predefined schematic at the cursor local Area = cBlockArea(); if not(Area:LoadFromSchematicFile("schematics/test.schematic")) then LOG("Loading failed"); return false; end LOG("Schematic loaded, placing now."); Area:Write(Player:GetWorld(), BlockX, BlockY, BlockZ); LOG("Done."); return false; end function OnUsingEnderPearl(Player, BlockX, BlockY, BlockZ, BlockFace, CursorX, CursorY, CursorZ) -- Rclk with an ender pearl saves a predefined area around the cursor into a .schematic file. Also tests area copying local Area = cBlockArea(); if not(Area:Read(Player:GetWorld(), BlockX - 8, BlockX + 8, BlockY - 8, BlockY + 8, BlockZ - 8, BlockZ + 8) ) then LOG("LUA: Area couldn't be read"); return false; end LOG("LUA: Area read, copying now."); local Area2 = cBlockArea(); Area2:CopyFrom(Area); LOG("LUA: Copied, now saving."); if not(Area2:SaveToSchematicFile("schematics/test.schematic")) then LOG("LUA: Cannot save schematic file."); return false; end LOG("LUA: Done."); return false; end function OnUsingRedstoneTorch(Player, BlockX, BlockY, BlockZ, BlockFace, CursorX, CursorY, CursorZ) -- Redstone torch activates a rapid dispenser / dropper discharge (at every tick): local BlockType = Player:GetWorld():GetBlock(BlockX, BlockY, BlockZ); if (BlockType == E_BLOCK_DISPENSER) then table.insert(g_DropSpensersToActivate, {World = Player:GetWorld(), x = BlockX, y = BlockY, z = BlockZ}); Player:SendMessage("Dispenser at {" .. BlockX .. ", " .. BlockY .. ", " .. BlockZ .. "} discharging"); return true; elseif (BlockType == E_BLOCK_DROPPER) then table.insert(g_DropSpensersToActivate, {World = Player:GetWorld(), x = BlockX, y = BlockY, z = BlockZ}); Player:SendMessage("Dropper at {" .. BlockX .. ", " .. BlockY .. ", " .. BlockZ .. "} discharging"); return true; else Player:SendMessage("Neither a dispenser nor a dropper at {" .. BlockX .. ", " .. BlockY .. ", " .. BlockZ .. "}: " .. BlockType); end return false; end function OnPlayerUsingItem(Player, BlockX, BlockY, BlockZ, BlockFace, CursorX, CursorY, CursorZ) -- dont check if the direction is in the air if (BlockFace == BLOCK_FACE_NONE) then return false end local HeldItem = Player:GetEquippedItem(); local HeldItemType = HeldItem.m_ItemType; if (HeldItemType == E_ITEM_STICK) then -- Magic sTick of ticking: set the pointed block for ticking at the next tick Player:SendMessage(cChatColor.LightGray .. "Setting next block tick to {" .. BlockX .. ", " .. BlockY .. ", " .. BlockZ .. "}") Player:GetWorld():SetNextBlockToTick(Vector3i(BlockX, BlockY, BlockZ)); return true elseif (HeldItemType == E_ITEM_BLAZE_ROD) then return OnUsingBlazeRod(Player, BlockX, BlockY, BlockZ, BlockFace, CursorX, CursorY, CursorZ); elseif (HeldItemType == E_ITEM_DIAMOND) then return OnUsingDiamond(Player, BlockX, BlockY, BlockZ, BlockFace, CursorX, CursorY, CursorZ); elseif (HeldItemType == E_ITEM_EYE_OF_ENDER) then return OnUsingEyeOfEnder(Player, BlockX, BlockY, BlockZ, BlockFace, CursorX, CursorY, CursorZ); elseif (HeldItemType == E_ITEM_ENDER_PEARL) then return OnUsingEnderPearl(Player, BlockX, BlockY, BlockZ, BlockFace, CursorX, CursorY, CursorZ); end return false; end function OnPlayerUsingBlock(Player, BlockX, BlockY, BlockZ, BlockFace, CursorX, CursorY, CursorZ, BlockType, BlockMeta) -- dont check if the direction is in the air if (BlockFace == BLOCK_FACE_NONE) then return false end local HeldItem = Player:GetEquippedItem(); local HeldItemType = HeldItem.m_ItemType; if (HeldItemType == E_BLOCK_REDSTONE_TORCH_ON) then return OnUsingRedstoneTorch(Player, BlockX, BlockY, BlockZ, BlockFace, CursorX, CursorY, CursorZ); end end function OnTakeDamage(Receiver, TDI) -- Receiver is cPawn -- TDI is TakeDamageInfo -- LOG(Receiver:GetClass() .. " was dealt " .. DamageTypeToString(TDI.DamageType) .. " damage: Raw " .. TDI.RawDamage .. ", Final " .. TDI.FinalDamage .. " (" .. (TDI.RawDamage - TDI.FinalDamage) .. " covered by armor)"); return false; end function OnTick1() -- For testing multiple hook handlers per plugin LOGINFO("Tick1"); end function OnTick2() -- For testing multiple hook handlers per plugin LOGINFO("Tick2"); end --- When set to a positive number, the following OnTick() will perform GC and decrease until 0 again GCOnTick = 0; function OnTick() -- Activate all dropspensers in the g_DropSpensersToActivate list: local ActivateDrSp = function(DropSpenser) if (DropSpenser:GetContents():GetFirstUsedSlot() == -1) then return true; end DropSpenser:Activate(); return false; end -- Walk the list backwards, because we're removing some items local idx = #g_DropSpensersToActivate; for i = idx, 1, -1 do local DrSp = g_DropSpensersToActivate[i]; if not(DrSp.World:DoWithDropSpenserAt(DrSp.x, DrSp.y, DrSp.z, ActivateDrSp)) then table.remove(g_DropSpensersToActivate, i); end end -- If GCOnTick > 0, do a garbage-collect and decrease by one if (GCOnTick > 0) then collectgarbage(); GCOnTick = GCOnTick - 1; end return false; end function OnWorldTick(a_World, a_Dt) -- Report food stats, if switched on: local Tick = a_World:GetWorldAge(); if (not(g_ShowFoodStats) or (math.mod(Tick, 10) ~= 0)) then return false; end a_World:ForEachPlayer( function(a_Player) a_Player:SendMessage( tostring(Tick / 10) .. " > FS: fl " .. a_Player:GetFoodLevel() .. "; sat " .. a_Player:GetFoodSaturationLevel() .. "; exh " .. a_Player:GetFoodExhaustionLevel() ); end ); end function OnChat(a_Player, a_Message) return false, "blabla " .. a_Message; end function OnPlayerRightClick(a_Player) -- If the player is holding a cake item, make them throw a cake block, using a FallingBlock entity: if (a_Player:GetInventory():GetEquippedItem().m_ItemType == E_ITEM_CAKE) then local World = a_Player:GetWorld() local Position = a_Player:GetPosition() + Vector3d(0, 1.5, 0) local EntityID = World:SpawnFallingBlock(Vector3i(Position), E_BLOCK_CAKE, 0) World:DoWithEntityByID(EntityID, function (Entity) Entity:TeleportToCoords(Position.x, Position.y, Position.z) Entity:SetSpeed(a_Player:GetLookVector() * 30) end ) end end function OnPlayerRightClickingEntity(a_Player, a_Entity) LOG("Player " .. a_Player:GetName() .. " right-clicking entity ID " .. a_Entity:GetUniqueID() .. ", a " .. a_Entity:GetClass()); return false; end function OnPluginsLoaded() LOG("All plugins loaded"); end function OnChunkGenerated(a_World, a_ChunkX, a_ChunkZ, a_ChunkDesc) -- Get the topmost block coord: local Height = a_ChunkDesc:GetHeight(0, 0); -- Create a sign there: a_ChunkDesc:SetBlockTypeMeta(0, Height + 1, 0, E_BLOCK_SIGN_POST, 0); local BlockEntity = a_ChunkDesc:GetBlockEntity(0, Height + 1, 0); if (BlockEntity ~= nil) then local SignEntity = tolua.cast(BlockEntity, "cSignEntity"); SignEntity:SetLines("Chunk:", tonumber(a_ChunkX) .. ", " .. tonumber(a_ChunkZ), "", "(Debuggers)"); end -- Update the heightmap: a_ChunkDesc:SetHeight(0, 0, Height + 1); end -- Function "round" copied from http://lua-users.org/wiki/SimpleRound function round(num, idp) local mult = 10^(idp or 0) if num >= 0 then return math.floor(num * mult + 0.5) / mult else return math.ceil(num * mult - 0.5) / mult end end function HandleNickCmd(Split, Player) if (Split[2] == nil) then Player:SendMessage("Usage: /nick [CustomName]"); return true; end Player:SetCustomName(Split[2]); Player:SendMessageSuccess("Custom name setted to " .. Player:GetCustomName() .. "!") return true end function HandleListEntitiesCmd(Split, Player) local NumEntities = 0; local ListEntity = function(Entity) if (Entity:IsDestroyed()) then -- The entity has already been destroyed, don't list it return false; end; local cls = Entity:GetClass(); Player:SendMessage(" " .. Entity:GetUniqueID() .. ": " .. cls .. " {" .. round(Entity:GetPosX(), 2) .. ", " .. round(Entity:GetPosY(), 2) .. ", " .. round(Entity:GetPosZ(), 2) .."}"); if (cls == "cPickup") then local Pickup = Entity; tolua.cast(Pickup, "cPickup"); Player:SendMessage(" Age: " .. Pickup:GetAge() .. ", IsCollected: " .. tostring(Pickup:IsCollected())); end NumEntities = NumEntities + 1; end Player:SendMessage("Listing all entities..."); Player:GetWorld():ForEachEntity(ListEntity); Player:SendMessage("List finished, " .. NumEntities .. " entities listed"); return true; end function HandleKillEntitiesCmd(Split, Player) local NumEntities = 0; local KillEntity = function(Entity) -- kill everything except for players: if (Entity:GetEntityType() ~= cEntity.etPlayer) then Entity:Destroy(); NumEntities = NumEntities + 1; end; end Player:SendMessage("Killing all entities..."); Player:GetWorld():ForEachEntity(KillEntity); Player:SendMessage("Killed " .. NumEntities .. " entities."); return true; end function HandleWoolCmd(Split, Player) local Wool = cItem(E_BLOCK_WOOL, 1, E_META_WOOL_BLUE); Player:GetInventory():SetArmorSlot(0, Wool); Player:GetInventory():SetArmorSlot(1, Wool); Player:GetInventory():SetArmorSlot(2, Wool); Player:GetInventory():SetArmorSlot(3, Wool); Player:SendMessage("You have been bluewooled :)"); return true; end function HandleTestWndCmd(a_Split, a_Player) local WindowType = cWindow.wtHopper; local WindowSizeX = 5; local WindowSizeY = 1; if (#a_Split == 4) then WindowType = tonumber(a_Split[2]); WindowSizeX = tonumber(a_Split[3]); WindowSizeY = tonumber(a_Split[4]); elseif (#a_Split ~= 1) then a_Player:SendMessage("Usage: /testwnd [WindowType WindowSizeX WindowSizeY]"); return true; end -- Test out the OnClosing callback's ability to refuse to close the window local attempt = 1; local OnClosing = function(Window, Player, CanRefuse) Player:SendMessage("Window closing attempt #" .. attempt .. "; CanRefuse = " .. tostring(CanRefuse)); attempt = attempt + 1; return CanRefuse and (attempt <= 3); -- refuse twice, then allow, unless CanRefuse is set to true end -- Log the slot changes local OnSlotChanged = function(Window, SlotNum) LOG("Window \"" .. Window:GetWindowTitle() .. "\" slot " .. SlotNum .. " changed."); end local Window = cLuaWindow(WindowType, WindowSizeX, WindowSizeY, "TestWnd"); local Item2 = cItem(E_ITEM_DIAMOND_SWORD, 1, 0, "1=1"); local Item3 = cItem(E_ITEM_DIAMOND_SHOVEL); Item3.m_Enchantments:SetLevel(cEnchantments.enchUnbreaking, 4); local Item4 = cItem(Item3); -- Copy Item4.m_Enchantments:SetLevel(cEnchantments.enchEfficiency, 3); -- Add enchantment Item4.m_Enchantments:SetLevel(cEnchantments.enchUnbreaking, 5); -- Overwrite existing level local Item5 = cItem(E_ITEM_DIAMOND_CHESTPLATE, 1, 0, "thorns=1;unbreaking=3"); Window:SetSlot(a_Player, 0, cItem(E_ITEM_DIAMOND, 64)); Window:SetSlot(a_Player, 1, Item2); Window:SetSlot(a_Player, 2, Item3); Window:SetSlot(a_Player, 3, Item4); Window:SetSlot(a_Player, 4, Item5); Window:SetOnClosing(OnClosing); Window:SetOnSlotChanged(OnSlotChanged); a_Player:OpenWindow(Window); -- To make sure that the object has the correct life-management in Lua, -- let's garbage-collect in the following few ticks GCOnTick = 10; return true; end function HandleGCCmd(a_Split, a_Player) collectgarbage(); return true; end function HandleFastCmd(a_Split, a_Player) if (a_Player:GetNormalMaxSpeed() <= 0.11) then -- The player has normal speed, set double speed: a_Player:SetNormalMaxSpeed(0.2); a_Player:SendMessage("You are now fast"); else -- The player has fast speed, set normal speed: a_Player:SetNormalMaxSpeed(0.1); a_Player:SendMessage("Back to normal speed"); end return true; end function HandleDashCmd(a_Split, a_Player) if (a_Player:GetSprintingMaxSpeed() <= 0.14) then -- The player has normal sprinting speed, set double Sprintingspeed: a_Player:SetSprintingMaxSpeed(0.4); a_Player:SendMessage("You can now sprint very fast"); else -- The player has fast sprinting speed, set normal sprinting speed: a_Player:SetSprintingMaxSpeed(0.13); a_Player:SendMessage("Back to normal sprinting"); end return true; end; function HandleGenRailsCmd(a_Split, a_Player) local MAX_RAIL_META = 9 local pos = a_Player:GetPosition() local ba = cBlockArea:new() ba:Create(2 * MAX_RAIL_META + 3, 4, 3, cBlockArea.baTypes + cBlockArea.baMetas) ba:FillRelCuboid(0, 2 * MAX_RAIL_META + 2, 0, 0, 0, 2, cBlockArea.baTypes, E_BLOCK_STONE) ba:FillRelCuboid(0, 2 * MAX_RAIL_META + 2, 1, 3, 0, 2, cBlockArea.baTypes, E_BLOCK_AIR) for x = 0, MAX_RAIL_META do ba:SetRelBlockTypeMeta(2 * x + 1, 1, 1, E_BLOCK_RAIL, x) end ba:Write(a_Player:GetWorld(), pos:Floor()) return true end function HandleGetCustomNameCmd(a_Split, a_Player) local item = a_Player:GetInventory():GetEquippedItem() if (not(item.m_CustomName) or (item.m_CustomName == "")) then a_Player:SendMessage("The custom name is empty") return true end local dispCN = string.gsub(item.m_CustomName, ".", function(a_Char) if (a_Char < " ") then return string.byte(a_Char) end return a_Char end ) a_Player:SendMessage(string.format("The custom name is %d bytes: %s", string.len(item.m_CustomName), dispCN)) return true end function HandleGetLoreCmd(a_Split, a_Player) local item = a_Player:GetInventory():GetEquippedItem() if (not(item.m_Lore) or (item.m_Lore == "")) then a_Player:SendMessage("The lore is empty") return true end local dispLore = string.gsub(item.m_Lore, ".", function(a_Char) if (a_Char < " ") then return string.byte(a_Char) end return a_Char end ) a_Player:SendMessage(string.format("The lore is %d bytes: %s", string.len(item.m_Lore), dispLore)) return true end function HandleGetPropCmd(a_Split, a_Player) local item = a_Player:GetInventory():GetEquippedItem() if not(item.m_DebuggersCustomProp) then a_Player:SendMessage("The custom property is not set.") return true end local dispValue = string.gsub(item.m_DebuggersCustomProp, ".", function(a_Char) if (a_Char < " ") then return string.byte(a_Char) end return a_Char end ) a_Player:SendMessage(string.format("The custom property value is %d bytes: %s", string.len(item.m_DebuggersCustomProp), dispValue)) return true end function HandleHungerCmd(a_Split, a_Player) a_Player:SendMessage("FoodLevel: " .. a_Player:GetFoodLevel()); a_Player:SendMessage("FoodSaturationLevel: " .. a_Player:GetFoodSaturationLevel()); a_Player:SendMessage("FoodTickTimer: " .. a_Player:GetFoodTickTimer()); a_Player:SendMessage("FoodExhaustionLevel: " .. a_Player:GetFoodExhaustionLevel()); a_Player:SendMessage("FoodPoisonedTicksRemaining: " .. a_Player:GetFoodPoisonedTicksRemaining()); return true; end function HandlePoisonCmd(a_Split, a_Player) a_Player:FoodPoison(15 * 20); return true; end function HandleStarveCmd(a_Split, a_Player) a_Player:SetFoodLevel(0); a_Player:SendMessage("You are now starving"); return true; end function HandleFoodLevelCmd(a_Split, a_Player) if (#a_Split ~= 2) then a_Player:SendMessage("Missing an argument: the food level to set"); return true; end a_Player:SetFoodLevel(tonumber(a_Split[2])); a_Player:SetFoodSaturationLevel(5); a_Player:SetFoodExhaustionLevel(0); a_Player:SendMessage( "Food level set to " .. a_Player:GetFoodLevel() .. ", saturation reset to " .. a_Player:GetFoodSaturationLevel() .. " and exhaustion reset to " .. a_Player:GetFoodExhaustionLevel() ); return true; end function HandleSetCustomNameCmd(a_Split, a_Player, a_EntireCmd) if not(a_Split[2]) then a_Player:SendMessageFatal("Missing an argument: the custom name to set"); return true end local nameToSet = a_EntireCmd:match("/setcustomname%s(.*)") if not(nameToSet) then a_Player:SendMessageFatal("Failed to extract the custom name to set") return true end nameToSet = nameToSet:gsub("\\([0-9][0-9][0-9])", string.char) local inv = a_Player:GetInventory() local slotNum = inv:GetEquippedSlotNum() local item = cItem(inv:GetEquippedItem()) -- Make a copy of the item item.m_CustomName = nameToSet inv:SetHotbarSlot(slotNum, item) a_Player:SendMessage("Custom name set to " .. nameToSet) return true end function HandleSetPropCmd(a_Split, a_Player, a_EntireCmd) if not(a_Split[2]) then a_Player:SendMessageFatal("Missing an argument: the property value to set"); return true end local valueToSet = a_EntireCmd:match("/setprop%s(.*)") if not(valueToSet) then a_Player:SendMessageFatal("Failed to extract the property value to set") return true end valueToSet = valueToSet:gsub("\\([0-9][0-9][0-9])", string.char) local inv = a_Player:GetInventory() local slotNum = inv:GetEquippedSlotNum() local item = inv:GetEquippedItem() item.m_DebuggersCustomProp = valueToSet inv:SetHotbarSlot(slotNum, item) a_Player:SendMessage("Custom property set to " .. valueToSet) return true end function HandleSetLoreCmd(a_Split, a_Player, a_EntireCmd) if not(a_Split[2]) then a_Player:SendMessageFatal("Missing an argument: the lore to set"); return true end local loreToSet = a_EntireCmd:match("/setlore%s(.*)") if not(loreToSet) then a_Player:SendMessageFatal("Failed to extract the lore to set") return true end loreToSet = loreToSet:gsub("\\([0-9][0-9][0-9])", string.char) local inv = a_Player:GetInventory() local slotNum = inv:GetEquippedSlotNum() local item = cItem(inv:GetEquippedItem()) -- Make a copy of the item local oldLore = item.m_Lore item.m_Lore = loreToSet inv:SetHotbarSlot(slotNum, item) a_Player:SendMessage("Lore set to " .. loreToSet) return true end function HandleSpideyCmd(a_Split, a_Player) -- Place a line of cobwebs from the player's eyes until non-air block, in the line-of-sight of the player local World = a_Player:GetWorld(); local Callbacks = { OnNextBlock = function(a_BlockPos, a_BlockType, a_BlockMeta) if (a_BlockType ~= E_BLOCK_AIR) then -- abort the trace return true; end World:SetBlock(a_BlockPos, E_BLOCK_COBWEB, 0); end }; local EyePos = a_Player:GetEyePosition(); local LookVector = a_Player:GetLookVector(); LookVector:Normalize(); -- Start cca 2 blocks away from the eyes local Start = EyePos + LookVector + LookVector; local End = EyePos + LookVector * 50; cLineBlockTracer.Trace(World, Callbacks, Start, End); return true; end function HandleEnchCmd(a_Split, a_Player) local Wnd = cLuaWindow(cWindow.wtEnchantment, 1, 1, "Ench"); a_Player:OpenWindow(Wnd); Wnd:SetProperty(0, 10); Wnd:SetProperty(1, 15); Wnd:SetProperty(2, 25); return true; end function HandleFoodStatsCmd(a_Split, a_Player) g_ShowFoodStats = not(g_ShowFoodStats); return true; end function HandleArrowCmd(a_Split, a_Player) local World = a_Player:GetWorld(); local Pos = a_Player:GetEyePosition(); local Speed = a_Player:GetLookVector(); Speed:Normalize(); Pos = Pos + Speed; World:CreateProjectile(Pos.x, Pos.y, Pos.z, cProjectileEntity.pkArrow, a_Player, Speed * 10); return true; end function HandleFireballCmd(a_Split, a_Player) local World = a_Player:GetWorld(); local Pos = a_Player:GetEyePosition(); local Speed = a_Player:GetLookVector(); Speed:Normalize(); Pos = Pos + Speed * 2; World:CreateProjectile(Pos.x, Pos.y, Pos.z, cProjectileEntity.pkGhastFireball, a_Player, Speed * 10); return true; end function HandleAddExperience(a_Split, a_Player) a_Player:DeltaExperience(200); return true; end function HandleRemoveXp(a_Split, a_Player) a_Player:SetCurrentExperience(0); return true; end function HandleFill(a_Split, a_Player) local World = a_Player:GetWorld(); local ChunkX = a_Player:GetChunkX(); local ChunkZ = a_Player:GetChunkZ(); World:ForEachBlockEntityInChunk(ChunkX, ChunkZ, function(a_BlockEntity) local BlockType = a_BlockEntity:GetBlockType(); if ( (BlockType == E_BLOCK_CHEST) or (BlockType == E_BLOCK_DISPENSER) or (BlockType == E_BLOCK_DROPPER) or (BlockType == E_BLOCK_FURNACE) or (BlockType == E_BLOCK_HOPPER) ) then -- This block entity has items (inherits from cBlockEntityWithItems), fill it: -- Note that we're not touching lit furnaces, don't wanna mess them up local EntityWithItems = tolua.cast(a_BlockEntity, "cBlockEntityWithItems"); local ItemGrid = EntityWithItems:GetContents(); local NumSlots = ItemGrid:GetNumSlots(); local ItemToSet = cItem(E_ITEM_GOLD_NUGGET); for i = 0, NumSlots - 1 do if (ItemGrid:GetSlot(i):IsEmpty()) then ItemGrid:SetSlot(i, ItemToSet); end end end end ); return true; end function HandleFurnaceRecipe(a_Split, a_Player) local HeldItem = a_Player:GetEquippedItem(); local Out, NumTicks, In = cRoot:GetFurnaceRecipe(HeldItem); if (Out ~= nil) then a_Player:SendMessage( "Furnace turns " .. ItemToFullString(In) .. " to " .. ItemToFullString(Out) .. " in " .. NumTicks .. " ticks (" .. tostring(NumTicks / 20) .. " seconds)." ); else a_Player:SendMessage("There is no furnace recipe that would smelt " .. ItemToString(HeldItem)); end return true; end function HandleFurnaceFuel(a_Split, a_Player) local HeldItem = a_Player:GetEquippedItem(); local NumTicks = cRoot:GetFurnaceFuelBurnTime(HeldItem); if (NumTicks > 0) then a_Player:SendMessage( ItemToFullString(HeldItem) .. " would power a furnace for " .. NumTicks .. " ticks (" .. tostring(NumTicks / 20) .. " seconds)." ); else a_Player:SendMessage(ItemToString(HeldItem) .. " will not power furnaces."); end return true; end function HandleSched(a_Split, a_Player) local World = a_Player:GetWorld() -- Schedule a broadcast of a countdown message: for i = 1, 10 do World:ScheduleTask(i * 20, function(a_World) a_World:BroadcastChat("Countdown: " .. 11 - i) end ) end -- Schedule a broadcast of the final message and a note to the originating player -- Note that we CANNOT use the a_Player in the callback - what if the player disconnected? -- Therefore we store the player's EntityID local PlayerID = a_Player:GetUniqueID() World:ScheduleTask(220, function(a_World) a_World:BroadcastChat("Countdown: BOOM") a_World:DoWithEntityByID(PlayerID, function(a_Entity) if (a_Entity:IsPlayer()) then -- Although unlikely, it is possible that this player is not the originating player -- However, I leave this as an excercise to you to fix this "bug" local Player = tolua.cast(a_Entity, "cPlayer") Player:SendMessage("Countdown finished") end end ) end ) return true end function HandleRMItem(a_Split, a_Player) -- Check params: if (a_Split[2] == nil) then a_Player:SendMessage("Usage: /rmitem [Count]") return true end -- Parse the item type: local Item = cItem() if (not StringToItem(a_Split[2], Item)) then a_Player:SendMessageFailure(a_Split[2] .. " isn't a valid item") return true end -- Parse the optional item count if (a_Split[3] ~= nil) then local Count = tonumber(a_Split[3]) if (Count == nil) then a_Player:SendMessageFailure(a_Split[3] .. " isn't a valid number") return true end Item.m_ItemCount = Count end -- Remove the item: local NumRemovedItems = a_Player:GetInventory():RemoveItem(Item) a_Player:SendMessageSuccess("Removed " .. NumRemovedItems .. " Items!") return true end function HandleRequest_Debuggers(a_Request) local FolderContents = cFile:GetFolderContents("./"); return "

    The following objects have been returned by cFile:GetFolderContents():

    • " .. table.concat(FolderContents, "
    • ") .. "

    "; end local g_Counter = 0 local g_JavaScript = [[ ]] function HandleRequest_StressTest(a_Request) if (a_Request.PostParams["counter"]) then g_Counter = g_Counter + 1 return tostring(g_Counter) end return g_JavaScript .. "

    The counter below should be reloading as fast as possible

    0
    " end function OnPluginMessage(a_Client, a_Channel, a_Message) LOGINFO("Received a plugin message from client " .. a_Client:GetUsername() .. ": channel '" .. a_Channel .. "', message '" .. a_Message .. "'"); if (a_Channel == "REGISTER") then if (a_Message:find("WECUI")) then -- The client has WorldEditCUI mod installed, test the comm by sending a few WECUI messages: --[[ WECUI messages have the following generic format: | If shape is p (cuboid selection), the params are sent individually for each corner click and have the following format: |||| point-index is 0 or 1 (lclk / rclk) volume is the 3D volume of the current cuboid selected (all three coords' deltas multiplied), including the edge blocks; -1 if N/A --]] -- Select a 51 * 51 * 51 block cuboid: a_Client:SendPluginMessage("WECUI", "p|0|50|50|50|-1"); a_Client:SendPluginMessage("WECUI", "p|1|100|100|100|132651"); -- 132651 = 51 * 51 * 51 end end end function HandleChunkStay(a_Split, a_Player) -- As an example of using ChunkStay, this call will load 3x3 chunks around the specified chunk coords, -- then build an obsidian pillar in the middle of each one. -- Once complete, the player will be teleported to the middle pillar if (#a_Split ~= 3) then a_Player:SendMessageInfo("Usage: /cs ") return true end local ChunkX = tonumber(a_Split[2]) local ChunkZ = tonumber(a_Split[3]) if ((ChunkX == nil) or (ChunkZ == nil)) then a_Player:SendMessageFailure("Invalid chunk coords.") return true end local World = a_Player:GetWorld() local PlayerID = a_Player:GetUniqueID() a_Player:SendMessageInfo("Loading chunks, stand by..."); -- Set the wanted chunks: local Chunks = {} for z = -1, 1 do for x = -1, 1 do table.insert(Chunks, {ChunkX + x, ChunkZ + z}) end end -- The function that is called when all chunks are available -- Will perform the actual action with all those chunks -- Note that the player needs to be referenced using their EntityID - in case they disconnect before the chunks load local OnAllChunksAvailable = function() LOGINFO("ChunkStay all chunks now available") -- Build something on the neighboring chunks, to verify: for z = -1, 1 do for x = -1, 1 do local BlockX = (ChunkX + x) * 16 + 8 local BlockZ = (ChunkZ + z) * 16 + 8 for y = 20, 80 do World:SetBlock(BlockX, y, BlockZ, E_BLOCK_OBSIDIAN, 0) end end end -- Teleport the player there for visual inspection: World:DoWithEntityByID(PlayerID, function (a_CallbackPlayer) a_CallbackPlayer:TeleportToCoords(ChunkX * 16 + 8, 85, ChunkZ * 16 + 8) a_CallbackPlayer:SendMessageSuccess("ChunkStay fully available") end ) end -- This function will be called for each chunk that is made available -- Note that the player needs to be referenced using their EntityID - in case they disconnect before the chunks load local OnChunkAvailable = function(a_ChunkX, a_ChunkZ) LOGINFO("ChunkStay now has chunk [" .. a_ChunkX .. ", " .. a_ChunkZ .. "]") World:DoWithEntityByID(PlayerID, function (a_CallbackPlayer) a_CallbackPlayer:SendMessageInfo("ChunkStay now has chunk [" .. a_ChunkX .. ", " .. a_ChunkZ .. "]") end ) end -- Process the ChunkStay: World:ChunkStay(Chunks, OnChunkAvailable, OnAllChunksAvailable) return true end function HandleCakeCmd(a_Split, a_Player) local lookVector = a_Player:GetLookVector() local pos = a_Player:GetEyePosition() + lookVector local world = a_Player:GetWorld() local speed = lookVector * 10 local cakeID = world:SpawnFallingBlock(pos, E_BLOCK_CAKE, 0) world:DoWithEntityByID(cakeID, function(a_CBCake) a_CBCake:SetSpeed(speed) end ) a_Player:SendMessage("Your cake is served") return true end function HandleClientVersionCmd(a_Split, a_Player) a_Player:SendMessage("Your client version number is " .. a_Player:GetClientHandle():GetProtocolVersion() ..".") return true end function HandleComeCmd(a_Split, a_Player) -- Find the first solid block under the player (in case they are flying): local playerWorld = a_Player:GetWorld() local playerPos = a_Player:GetPosition() local toPos = Vector3i(playerPos) if (toPos.y < 1) then a_Player:SendMessageFailure("Cannot navigate to you, you're too low in the world") return true end while not(cBlockInfo:IsSolid(playerWorld:GetBlock(toPos.x, toPos.y, toPos.z))) do if (toPos.y <= 0) then a_Player:SendMessageFailure("Cannot navigate to you, there's no solid block below you") return true end toPos.y = toPos.y - 1 end -- Find the mob to navigate: local mob local playerLook = a_Player:GetLookVector():NormalizeCopy() local maxDot = 0 playerWorld:ForEachEntity( function (a_CBEntity) local dir = (a_CBEntity:GetPosition() - playerPos) dir:Normalize() local dot = dir:Dot(playerLook) if (dot > maxDot) then maxDot = dot mob = a_CBEntity end end ) if not(mob) then a_Player:SendMessageFailure("Cannot navigate to you, there's no mob this way") return true end mob:MoveToPosition(Vector3d(toPos)) a_Player:SendMessageSuccess(( string.format("Navigating the %s to position {%d, %d, %d}", cMonster:MobTypeToString(mob:GetMobType()), toPos.x, toPos.y, toPos.z ) )) return true end function HandleCompo(a_Split, a_Player) -- Send one composite message to self: local msg = cCompositeChat() msg:AddTextPart("Hello! ", "b@e") -- bold yellow msg:AddUrlPart("Cuberite", "https://cuberite.org") msg:AddTextPart(" rules! ") msg:AddRunCommandPart("Set morning", "/time set 0") a_Player:SendMessage(msg) -- Broadcast another one to the world: local msg2 = cCompositeChat() msg2:AddSuggestCommandPart(a_Player:GetName(), "/tell " .. a_Player:GetName() .. " ") msg2:AddTextPart(" knows how to use cCompositeChat!"); a_Player:GetWorld():BroadcastChat(msg2) return true end function HandleSetBiome(a_Split, a_Player) local Biome = biJungle local Size = 20 local SplitSize = #a_Split if (SplitSize > 3) then a_Player:SendMessage("Too many parameters. Usage: " .. a_Split[1] .. " ") return true end if (SplitSize >= 2) then Biome = StringToBiome(a_Split[2]) if (Biome == biInvalidBiome) then a_Player:SendMessage("Unknown biome: '" .. a_Split[2] .. "'. Command ignored.") return true end end if (SplitSize >= 3) then Size = tostring(a_Split[3]) if (Size == nil) then a_Player:SendMessage("Unknown size: '" .. a_Split[3] .. "'. Command ignored.") return true end end local BlockX = math.floor(a_Player:GetPosX()) local BlockZ = math.floor(a_Player:GetPosZ()) a_Player:GetWorld():SetAreaBiome(BlockX - Size, BlockX + Size, BlockZ - Size, BlockZ + Size, Biome) a_Player:SendMessage( "Blocks {" .. (BlockX - Size) .. ", " .. (BlockZ - Size) .. "} - {" .. (BlockX + Size) .. ", " .. (BlockZ + Size) .. "} set to biome #" .. tostring(Biome) .. "." ) return true end function HandleVectorCmd(a_Split, a_Player) a_Player:SendMessage("Testing the Vector3 APIs...") -- Test the Vector3 coercion in ManualBindings - any Vector3 type should be accepted for any Vector3 parameter: local pos = a_Player:GetPosition() local c = cCuboid:new() c:Assign(pos - Vector3d(2, 2, 2), pos + Vector3d(2, 2, 2)) assert(c:IsInside(Vector3d(pos))) assert(c:IsInside(Vector3f(pos))) assert(c:IsInside(Vector3i(pos))) assert(c:IsInside({pos.x, pos.y, pos.z})) a_Player:SendMessage("Test successful.") return true end function HandleWESel(a_Split, a_Player) -- Check if the selection is a cuboid: local IsCuboid = cPluginManager:CallPlugin("WorldEdit", "IsPlayerSelectionCuboid") if (IsCuboid == nil) then a_Player:SendMessage(cCompositeChat():SetMessageType(mtFailure):AddTextPart("Cannot adjust selection, WorldEdit is not loaded")) return true elseif (IsCuboid == false) then a_Player:SendMessage(cCompositeChat():SetMessageType(mtFailure):AddTextPart("Cannot adjust selection, the selection is not a cuboid")) return true end -- Get the selection: local SelCuboid = cCuboid() local IsSuccess = cPluginManager:CallPlugin("WorldEdit", "GetPlayerCuboidSelection", a_Player, SelCuboid) if not(IsSuccess) then a_Player:SendMessage(cCompositeChat():SetMessageType(mtFailure):AddTextPart("Cannot adjust selection, WorldEdit reported failure while getting current selection")) return true end -- Adjust the selection: local NumBlocks = tonumber(a_Split[2] or "1") or 1 SelCuboid:Expand(NumBlocks, NumBlocks, 0, 0, NumBlocks, NumBlocks) -- Set the selection: IsSuccess = cPluginManager:CallPlugin("WorldEdit", "SetPlayerCuboidSelection", a_Player, SelCuboid) if not(IsSuccess) then a_Player:SendMessage(cCompositeChat():SetMessageType(mtFailure):AddTextPart("Cannot adjust selection, WorldEdit reported failure while setting new selection")) return true end a_Player:SendMessage(cCompositeChat():SetMessageType(mtInformation):AddTextPart("Successfully adjusted the selection by " .. NumBlocks .. " block(s)")) return true end function OnPlayerJoined(a_Player) -- Test composite chat chaining: a_Player:SendMessage(cCompositeChat() :AddTextPart("Hello, ") :AddUrlPart(a_Player:GetName(), "https://cuberite.org", "u@2") :AddSuggestCommandPart(", and welcome.", "/help", "u") :AddRunCommandPart(" SetDay", "/time set 0") ) end function OnProjectileHitBlock(a_Projectile, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_BlockHitPos) -- Test projectile hooks by setting the blocks they hit on fire: local BlockX, BlockY, BlockZ = AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace) local World = a_Projectile:GetWorld() World:SetBlock(BlockX, BlockY, BlockZ, E_BLOCK_FIRE, 0) end function OnChunkUnloading(a_World, a_ChunkX, a_ChunkZ) -- Do not let chunk [0, 0] unload, so that it continues ticking [cWorld:SetChunkAlwaysTicked() test] if ((a_ChunkX == 0) and (a_ChunkZ == 0)) then return true end end function OnWorldStarted(a_World) -- Make the chunk [0, 0] in every world keep ticking [cWorld:SetChunkAlwaysTicked() test] a_World:ChunkStay({{0, 0}}, nil, function() -- The chunk is loaded, make it always tick: a_World:SetChunkAlwaysTicked(0, 0, true) end ) end function OnProjectileHitBlock(a_ProjectileEntity, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_BlockHitPos) -- This simple test is for testing issue #1326 - simply declaring this hook would crash the server upon call LOG("Projectile hit block") LOG(" Projectile EntityID: " .. a_ProjectileEntity:GetUniqueID()) LOG(" Block: {" .. a_BlockX .. ", " .. a_BlockY .. ", " .. a_BlockZ .. "}, face " .. a_BlockFace) LOG(" HitPos: {" .. a_BlockHitPos.x .. ", " .. a_BlockHitPos.y .. ", " .. a_BlockHitPos.z .. "}") end local PossibleItems = { cItem(E_ITEM_DIAMOND), cItem(E_ITEM_GOLD), cItem(E_ITEM_IRON), cItem(E_ITEM_DYE, 1, E_META_DYE_BLUE), -- Lapis lazuli cItem(E_ITEM_COAL), } function HandlePickups(a_Split, a_Player) local PlayerX = a_Player:GetPosX() local PlayerY = a_Player:GetPosY() local PlayerZ = a_Player:GetPosZ() local World = a_Player:GetWorld() local Range = 12 for x = 0, Range do for z = 0, Range do local px = PlayerX + x - Range / 2 local pz = PlayerZ + z - Range / 2 local Items = cItems() Items:Add(PossibleItems[math.random(#PossibleItems)]) World:SpawnItemPickups(Items, px, PlayerY, pz, 0) end end -- for z, for x return true end function HandlePlugMsg(a_Split, a_Player) local ch = a_Player:GetClientHandle() ch:SendPluginMessage("TestCh", "some\0string\1with\2funny\3chars") return true end function HandlePoof(a_Split, a_Player) local PlayerPos = Vector3d(a_Player:GetPosition()) -- Create a copy of the position PlayerPos.y = PlayerPos.y - 1 local Box = cBoundingBox(PlayerPos, 4, 2) local NumEntities = 0 a_Player:GetWorld():ForEachEntityInBox(Box, function (a_Entity) if not(a_Entity:IsPlayer()) then local AddSpeed = a_Entity:GetPosition() - PlayerPos -- Speed away from the player a_Entity:AddSpeed(AddSpeed * 32 / (AddSpeed:SqrLength() + 1)) -- The further away, the less speed to add NumEntities = NumEntities + 1 end end ) a_Player:SendMessage("Poof! (" .. NumEntities .. " entities)") return true end -- List of hashing functions to test: local HashFunctions = { {"md5", md5 }, {"cCryptoHash.md5", cCryptoHash.md5 }, {"cCryptoHash.md5HexString", cCryptoHash.md5HexString }, {"cCryptoHash.sha1", cCryptoHash.sha1 }, {"cCryptoHash.sha1HexString", cCryptoHash.sha1HexString }, } -- List of strings to try hashing: local HashExamples = { "", "\0", "test", } function HandleConsoleHash(a_Split) for _, str in ipairs(HashExamples) do LOG("Hashing string \"" .. str .. "\":") for _, hash in ipairs(HashFunctions) do if not(hash[2]) then LOG("Hash function " .. hash[1] .. " doesn't exist in the API!") else LOG(hash[1] .. "() = " .. hash[2](str)) end end -- for hash - HashFunctions[] end -- for str - HashExamples[] return true end function HandleConsoleHitTrace(a_Split) local world = cRoot:Get():GetDefaultWorld() local s = Vector3d(0, 70, 0) local e = Vector3d(100, 75, 100) if (tonumber(a_Split[2])) then s.x = tonumber(a_Split[2]) end if (tonumber(a_Split[3])) then s.y = tonumber(a_Split[3]) end if (tonumber(a_Split[4])) then s.z = tonumber(a_Split[4]) end if (tonumber(a_Split[5])) then e.x = tonumber(a_Split[5]) end if (tonumber(a_Split[6])) then e.y = tonumber(a_Split[6]) end if (tonumber(a_Split[7])) then e.z = tonumber(a_Split[7]) end local res, hitCoords, hitBlockCoords, hitBlockFace = cLineBlockTracer:FirstSolidHitTrace(world, s, e) if (res) then return true, string.format("The line hits block {%d, %d, %d} at point {%f, %f, %f}, face %s", hitBlockCoords.x, hitBlockCoords.y, hitBlockCoords.z, hitCoords.x, hitCoords.y, hitCoords.z, BlockFaceToString(hitBlockFace) ) else return true, "The two points specified don't have a solid block between them." end end --- Monitors the state of the "inh" entity-spawning hook -- if false, the hook is installed before the "inh" command processing local isInhHookInstalled = false function HandleConsoleInh(a_Split, a_FullCmd) -- Check the param: local kindStr = a_Split[2] or "pkArrow" local kind = cProjectileEntity[kindStr] if (kind == nil) then return true, "There's no projectile kind '" .. kindStr .. "'." end -- Get the world to test in: local world = cRoot:Get():GetDefaultWorld() if (world == nil) then return true, "Cannot test inheritance, no default world" end -- Install the hook, if needed: if not(isInhHookInstalled) then cPluginManager:AddHook(cPluginManager.HOOK_SPAWNING_ENTITY, function (a_CBWorld, a_CBEntity) LOG("New entity is spawning:") LOG(" Lua type: '" .. type(a_CBEntity) .. "'") LOG(" ToLua type: '" .. tolua.type(a_CBEntity) .. "'") LOG(" GetEntityType(): '" .. a_CBEntity:GetEntityType() .. "'") LOG(" GetClass(): '" .. a_CBEntity:GetClass() .. "'") end ) isInhHookInstalled = true end -- Create the projectile: LOG("Creating a " .. kindStr .. " projectile in world " .. world:GetName() .. "...") local msg world:ChunkStay({{0, 0}}, nil, function () -- Create a projectile at {8, 100, 8}: local entityID = world:CreateProjectile(8, 100, 8, kind, nil, nil) if (entityID < 0) then msg = "Cannot test inheritance, projectile creation failed." return end LOG("Entity created, ID #" .. entityID) -- Call a function on the newly created entity: local hasExecutedCallback = false world:DoWithEntityByID( entityID, function (a_CBEntity) LOG("Projectile created and found using the DoWithEntityByID() callback") LOG("Lua type: '" .. type(a_CBEntity) .. "'") LOG("ToLua type: '" .. tolua.type(a_CBEntity) .. "'") LOG("GetEntityType(): '" .. a_CBEntity:GetEntityType() .. "'") LOG("GetClass(): '" .. a_CBEntity:GetClass() .. "'") hasExecutedCallback = true end ) if not(hasExecutedCallback) then msg = "The callback failed to execute" return end msg = "Inheritance test finished" end ) return true, msg end function HandleConsoleLoadChunk(a_Split) -- Check params: local numParams = #a_Split if (numParams ~= 3) and (numParams ~= 4) then return true, "Usage: " .. a_Split[1] .. " []" end -- Get the chunk coords: local chunkX = tonumber(a_Split[2]) if (chunkX == nil) then return true, "Not a number: '" .. a_Split[2] .. "'" end local chunkZ = tonumber(a_Split[3]) if (chunkZ == nil) then return true, "Not a number: '" .. a_Split[3] .. "'" end -- Get the world: local world if (a_Split[4] == nil) then world = cRoot:Get():GetDefaultWorld() else world = cRoot:Get():GetWorld(a_Split[4]) if (world == nil) then return true, "There's no world named '" .. a_Split[4] .. "'." end end -- Queue a ChunkStay for the chunk, log a message when the chunk is loaded: world:ChunkStay({{chunkX, chunkZ}}, nil, function() LOG("Chunk [" .. chunkX .. ", " .. chunkZ .. "] is loaded") end ) return true end function HandleConsoleLosTrace(a_Split) local world = cRoot:Get():GetDefaultWorld() local s = Vector3d(0, 70, 0) local e = Vector3d(100, 75, 100) if (tonumber(a_Split[2])) then s.x = tonumber(a_Split[2]) end if (tonumber(a_Split[3])) then s.y = tonumber(a_Split[3]) end if (tonumber(a_Split[4])) then s.z = tonumber(a_Split[4]) end if (tonumber(a_Split[5])) then e.x = tonumber(a_Split[5]) end if (tonumber(a_Split[6])) then e.y = tonumber(a_Split[6]) end if (tonumber(a_Split[7])) then e.z = tonumber(a_Split[7]) end local res = cLineBlockTracer:LineOfSightTrace(world, s, e, cLineBlockTracer.losAir) if (res) then return true, "The two points can see each other." else return true, "The two points cannot see each other" end end function HandleConsolePluginStats(a_Split) cPluginManager:ForEachPlugin( function (a_CBPlugin) LOG("Plugin in " .. a_CBPlugin:GetFolderName() .. " has an API name of " .. a_CBPlugin:GetName() .. " and status " .. a_CBPlugin:GetStatus()) end ) return true end function HandleConsolePrepareChunk(a_Split) -- Check params: local numParams = #a_Split if (numParams ~= 3) and (numParams ~= 4) then return true, "Usage: " .. a_Split[1] .. " []" end -- Get the chunk coords: local chunkX = tonumber(a_Split[2]) if (chunkX == nil) then return true, "Not a number: '" .. a_Split[2] .. "'" end local chunkZ = tonumber(a_Split[3]) if (chunkZ == nil) then return true, "Not a number: '" .. a_Split[3] .. "'" end -- Get the world: local world if (a_Split[4] == nil) then world = cRoot:Get():GetDefaultWorld() else world = cRoot:Get():GetWorld(a_Split[4]) if (world == nil) then return true, "There's no world named '" .. a_Split[4] .. "'." end end -- Queue the chunk for preparing, log a message when prepared: world:PrepareChunk(chunkX, chunkZ, function(a_CBChunkX, a_CBChunkZ) LOG("Chunk [" .. chunkX .. ", " .. chunkZ .. "] has been prepared") end ) return true end function HandleConsoleSchedule(a_Split) local prev = os.clock() LOG("Scheduling a task for 5 seconds in the future (current os.clock is " .. prev .. ")") cRoot:Get():GetDefaultWorld():ScheduleTask(5 * 20, function () local current = os.clock() local diff = current - prev LOG("Scheduled function is called. Current os.clock is " .. current .. ", difference is " .. diff .. ")") end ) return true, "Task scheduled" end --- Returns the square of the distance from the specified point to the specified line local function SqDistPtFromLine(x, y, x1, y1, x2, y2) local dx = x - x1 local dy = y - y1 local px = x2 - x1 local py = y2 - y1 local ss = px * dx + py * dy local ds = px * px + py * py if (ss < 0) then -- Return sqdistance from point 1 return dx * dx + dy * dy end if (ss > ds) then -- Return sqdistance from point 2 return ((x2 - x) * (x2 - x) + (y2 - y) * (y2 - y)) end -- Return sqdistance from the line if ((px * px + py * py) == 0) then return dx * dx + dy * dy else return (py * dx - px * dy) * (py * dx - px * dy) / (px * px + py * py) end end function HandleConsoleTestBbox(a_Split, a_EntireCmd) -- Test bbox intersection: local bbox1 = cBoundingBox(0, 5, 0, 5, 0, 5) local bbox2 = cBoundingBox(bbox1) -- Make a copy bbox2:Move(20, 20, 20) local bbox3 = cBoundingBox(bbox1) -- Make a copy bbox3:Move(2, 2, 2) local doesIntersect, intersection = bbox1:Intersect(bbox2) LOG("Bbox 2 intersection: " .. tostring(doesIntersect)) LOG(" Intersection type: " .. type(intersection) .. " / " .. tolua.type(intersection)) if (intersection) then LOG(" {" .. intersection:GetMinX() .. ", " .. intersection:GetMinY() .. ", " .. intersection:GetMinZ() .. "}") LOG(" {" .. intersection:GetMaxX() .. ", " .. intersection:GetMaxY() .. ", " .. intersection:GetMaxZ() .. "}") end doesIntersect, intersection = bbox1:Intersect(bbox3) LOG("Bbox 3 intersection: " .. tostring(doesIntersect)) LOG(" Intersection type: " .. type(intersection) .. " / " .. tolua.type(intersection)) if (intersection) then LOG(" {" .. intersection:GetMinX() .. ", " .. intersection:GetMinY() .. ", " .. intersection:GetMinZ() .. "}") LOG(" {" .. intersection:GetMaxX() .. ", " .. intersection:GetMaxY() .. ", " .. intersection:GetMaxZ() .. "}") end -- Test line intersection: local lines = { { Vector3d(5, 0, 5), Vector3d(5, 1, 5) }, { Vector3d(0, 0, 0), Vector3d(0, 1, 0) }, } for idx, line in ipairs(lines) do local doesIntersect, coeff, face = bbox2:CalcLineIntersection(line[1], line[2]) LOG("Line " .. idx .. " intersection: " .. tostring(doesIntersect)) LOG(" Coeff: " .. tostring(coeff)) LOG(" Face: " .. tostring(face)) local doesIntersect2, coeff2, face2 = cBoundingBox:CalcLineIntersection(bbox2:GetMin(), bbox2:GetMax(), line[1], line[2]) assert(doesIntersect == doesIntersect2) assert(coeff == coeff2) assert(face == face2) end return true end function HandleConsoleTestCall(a_Split, a_EntireCmd) LOG("Testing inter-plugin calls") LOG("Note: These will fail if the Core plugin is not enabled") -- Test calling the HandleConsoleWeather handler: local pm = cPluginManager LOG("Calling Core's HandleConsoleWeather") local isSuccess = pm:CallPlugin("Core", "HandleConsoleWeather", { "/weather", "rain", } ) if (type(isSuccess) == "boolean") then LOG("Success") else LOG("FAILED") end -- Test injecting some code: LOG("Injecting code into the Core plugin") isSuccess = pm:CallPlugin("Core", "dofile", pm:GetCurrentPlugin():GetLocalFolder() .. "/Inject.lua") if (type(isSuccess) == "boolean") then LOG("Success") else LOG("FAILED") end -- Test the full capabilities of the table-passing API, using the injected function: LOG("Calling injected code") isSuccess = pm:CallPlugin("Core", "injectedPrintParams", { "test", nil, { "test", "test" }, [10] = "test", ["test"] = "test", [{"test"}] = "test", [true] = "test", } ) if (type(isSuccess) == "boolean") then LOG("Success") else LOG("FAILED") end return true end function HandleConsoleTestErr(a_Split, a_EntireCmd) cRoot:Get():GetDefaultWorld():ForEachEntity( function (a_CBEntity) error("This error should not abort the server") end ) end function HandleConsoleTestJson(a_Split, a_EntireCmd) LOG("Testing Json parsing...") local t1 = cJson:Parse([[{"a": 1, "b": "2", "c": [3, "4", 5], "d": true }]]) assert(t1.a == 1) assert(t1.b == "2") assert(t1.c[1] == 3) assert(t1.c[2] == "4") assert(t1.c[3] == 5) assert(t1.d == true) LOG("Json parsing example 1 successful") local t2, msg = cJson:Parse([[{"some": invalid, json}]]) assert(t2 == nil) assert(type(msg) == "string") LOG("Json parsing an invalid string: Error message returned: " .. msg) local isSuccess, t3 isSuccess, t3, msg = pcall(cJson.Parse, cJson, nil) if (isSuccess) then LOG(string.format("Json parsing a 'nil' produced a %s and a %s, msg is %s.", type(t3), type(msg), msg or "" )) else LOG("Json parsing a 'nil' raised an error") end LOG("Json parsing test succeeded") LOG("Testing Json serializing...") local s1, msg1 = cJson:Serialize({a = 1, b = "2", c = {3, "4", 5}, d = true}, {indentation = " "}) LOG("Serialization result: " .. (s1 or ("ERROR: " .. (msg1 or "")))) local s2, msg2 = cJson:Serialize({valueA = 1, valueB = {3, badValue = "4", 5}, d = true}, {indentation = " "}) assert(not(s2), "Serialization should have failed") LOG("Serialization correctly failed with message: " .. (msg2 or "")) LOG("Json serializing test succeeded") return true end function HandleConsoleTestTracer(a_Split, a_EntireCmd) -- Check required params: if not(a_Split[7]) then return true, "Usage: " .. a_Split[1] .. " []" end local Coords = {} for i = 1, 6 do local v = tonumber(a_Split[i + 1]) if not(v) then return true, "Parameter " .. (i + 1) .. " (" .. tostring(a_Split[i + 1]) .. ") not a number " end Coords[i] = v end -- Get the world in which to test: local World if (a_Split[8]) then World = cRoot:GetWorld(a_Split[2]) else World = cRoot:Get():GetDefaultWorld() end if not(World) then return true, "No such world" end -- Define the callbacks to use for tracing: local Callbacks = { OnNextBlock = function(a_BlockPos, a_BlockType, a_BlockMeta, a_EntryFace) LOG(string.format("{%d, %d, %d}: %s", a_Block.x, a_Block.y, a_Block.z, ItemToString(cItem(a_BlockType, 1, a_BlockMeta)))) end, OnNextBlockNoData = function(a_BlockPos, a_EntryFace) LOG(string.format("{%d, %d, %d} (no data)", a_Block.x, a_Block.y, a_Block.z)) end, OnNoChunk = function() LOG("Chunk not loaded") end, OnNoMoreHits = function() LOG("Trace finished") end, OnOutOfWorld = function() LOG("Out of world") end, OnIntoWorld = function() LOG("Into world") end, } -- Approximate the chunks needed for the trace by iterating over all chunks and measuring their center's distance from the traced line local Chunks = {} local sx = math.floor(Coords[1] / 16) local sz = math.floor(Coords[3] / 16) local ex = math.floor(Coords[4] / 16) local ez = math.floor(Coords[6] / 16) local sgnx = (sx < ex) and 1 or -1 local sgnz = (sz < ez) and 1 or -1 for z = sz, ez, sgnz do local ChunkCenterZ = z * 16 + 8 for x = sx, ex, sgnx do local ChunkCenterX = x * 16 + 8 local sqdist = SqDistPtFromLine(ChunkCenterX, ChunkCenterZ, Coords[1], Coords[3], Coords[4], Coords[6]) if (sqdist <= 128) then table.insert(Chunks, {x, z}) end end end -- Load the chunks and do the trace once loaded: local startPos = Vector3i(Coords[1], Coords[2], Coords[3]) local endPos = Vector3i(Coords[4], Coords[5], Coords[6]) World:ChunkStay(Chunks, nil, function() cLineBlockTracer:Trace(World, Callbacks, startPos, endPos) end ) return true end function HandleConsoleTestTracerDeprecated(a_Split, a_EntireCmd) -- Check required params: if not(a_Split[7]) then return true, "Usage: " .. a_Split[1] .. " []" end local Coords = {} for i = 1, 6 do local v = tonumber(a_Split[i + 1]) if not(v) then return true, "Parameter " .. (i + 1) .. " (" .. tostring(a_Split[i + 1]) .. ") not a number " end Coords[i] = v end -- Get the world in which to test: local World if (a_Split[8]) then World = cRoot:GetWorld(a_Split[2]) else World = cRoot:Get():GetDefaultWorld() end if not(World) then return true, "No such world" end -- Define the callbacks to use for tracing: local Callbacks = { OnNextBlock = function(a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta, a_EntryFace) LOG(string.format("{%d, %d, %d}: %s", a_BlockX, a_BlockY, a_BlockZ, ItemToString(cItem(a_BlockType, 1, a_BlockMeta)))) end, OnNextBlockNoData = function(a_BlockX, a_BlockY, a_BlockZ, a_EntryFace) LOG(string.format("{%d, %d, %d} (no data)", a_BlockX, a_BlockY, a_BlockZ)) end, OnNoChunk = function() LOG("Chunk not loaded") end, OnNoMoreHits = function() LOG("Trace finished") end, OnOutOfWorld = function() LOG("Out of world") end, OnIntoWorld = function() LOG("Into world") end, } -- Approximate the chunks needed for the trace by iterating over all chunks and measuring their center's distance from the traced line local Chunks = {} local sx = math.floor(Coords[1] / 16) local sz = math.floor(Coords[3] / 16) local ex = math.floor(Coords[4] / 16) local ez = math.floor(Coords[6] / 16) local sgnx = (sx < ex) and 1 or -1 local sgnz = (sz < ez) and 1 or -1 for z = sz, ez, sgnz do local ChunkCenterZ = z * 16 + 8 for x = sx, ex, sgnx do local ChunkCenterX = x * 16 + 8 local sqdist = SqDistPtFromLine(ChunkCenterX, ChunkCenterZ, Coords[1], Coords[3], Coords[4], Coords[6]) if (sqdist <= 128) then table.insert(Chunks, {x, z}) end end end -- Load the chunks and do the trace once loaded: World:ChunkStay(Chunks, nil, function() cLineBlockTracer:Trace(World, Callbacks, Coords[1], Coords[2], Coords[3], Coords[4], Coords[5], Coords[6]) end ) return true end function HandleConsoleTestUrlClient(a_Split, a_EntireCmd) local url = a_Split[2] or "https://github.com" local isSuccess, msg = cUrlClient:Get(url, function (a_Body, a_SecondParam) if not(a_Body) then -- An error has occurred, a_SecondParam is the error message LOG("Error while retrieving URL \"" .. url .. "\": " .. (a_SecondParam or "")) return end -- Body received, a_SecondParam is the HTTP headers dictionary-table assert(type(a_Body) == "string") assert(type(a_SecondParam) == "table") LOG("URL body received, length is " .. string.len(a_Body) .. " bytes and there are these headers:") for k, v in pairs(a_SecondParam) do LOG(" \"" .. k .. "\": \"" .. v .. "\"") end LOG("(headers list finished)") end ) if not(isSuccess) then LOG("cUrlClient request failed: " .. (msg or "")) end return true end function HandleConsoleTestUrlParser(a_Split, a_EntireCmd) LOG("Testing cUrlParser...") local UrlsToTest = { "invalid URL", "https://github.com", "ftp://anonymous:user@example.com@ftp.cuberite.org:9921/releases/2015/2015-12-25.zip", "ftp://anonymous:user:name:with:colons@example.com@ftp.cuberite.org:9921", "https://google.com/", "https://google.com/?q=cuberite", "https://google.com/search?q=cuberite", "https://google.com/some/search?q=cuberite#results", "https://google.com/?q=cuberite#results", "https://google.com/#results", "ftp://cuberite.org:9921/releases/2015/2015-12-25.zip", "mailto:support@cuberite.org", } for _, u in ipairs(UrlsToTest) do LOG("URL: " .. u) local scheme, username, password, host, port, path, query, fragment = cUrlParser:Parse(u) if not(scheme) then LOG(" Error: " .. (username or "")) else LOG(" Scheme = " .. scheme) LOG(" Username = " .. username) LOG(" Password = " .. password) LOG(" Host = " .. host) LOG(" Port = " .. port) LOG(" Path = " .. path) LOG(" Query = " .. query) LOG(" Fragment = " .. fragment) end end LOG("cUrlParser test complete") return true end function HandleConsoleUuid(a_Split, a_EntireCmd) -- Check params: local playerName = a_Split[2] if not(playerName) then return true, "Usage: uuid " end -- Query with cache: LOG("Player " .. playerName .. ":") local cachedUuid = cMojangAPI:GetUUIDFromPlayerName(playerName, true) if not(cachedUuid) then LOG(" - not in the UUID cache") else LOG(" - in the cache: \"" .. cachedUuid .. "\"") end -- Query online: local onlineUuid = cMojangAPI:GetUUIDFromPlayerName(playerName, false) if not(onlineUuid) then LOG(" - UUID not available online") else LOG(" - online: \"" .. onlineUuid .. "\"") end return true end function HandleConsoleBBox(a_Split) local bbox = cBoundingBox(0, 10, 0, 10, 0, 10) local v1 = Vector3d(1, 1, 1) local v2 = Vector3d(5, 5, 5) local v3 = Vector3d(11, 11, 11) if (bbox:IsInside(v1)) then LOG("v1 is inside bbox") else LOG("v1 is not inside bbox") end if (bbox:IsInside(v2)) then LOG("v2 is inside bbox") else LOG("v2 is not inside bbox") end if (bbox:IsInside(v3)) then LOG("v3 is inside bbox") else LOG("v3 is not inside bbox") end if (bbox:IsInside(v1, v2)) then LOG("v1*v2 is inside bbox") else LOG("v1*v2 is not inside bbox") end if (bbox:IsInside(v2, v1)) then LOG("v2*v1 is inside bbox") else LOG("v2*v1 is not inside bbox") end if (bbox:IsInside(v1, v3)) then LOG("v1*v3 is inside bbox") else LOG("v1*v3 is not inside bbox") end if (bbox:IsInside(v2, v3)) then LOG("v2*v3 is inside bbox") else LOG("v2*v3 is not inside bbox") end return true end function HandleConsoleDeadlock(a_Split) -- If given a parameter, assume it's a world name and simulate a deadlock in the world's tick thread if (a_Split[2]) then local world = cRoot:Get():GetWorld(a_Split[2]) if (world) then world:ScheduleTask(0, function() -- Make a live-lock: while (true) do end end ) return true, "Deadlock in world tick thread for world " .. a_Split[2] .. " has been scheduled." end LOG("Not a world name: " .. a_Split[2] .. "; simulating a deadlock in the command execution thread instead.") else LOG("Simulating a deadlock in the command execution thread.") end -- Make a live-lock in the command execution thread: while(true) do end end function HandleConsoleDownload(a_Split) -- Check params: local url = a_Split[2] local fnam = a_Split[3] if (not(url) or not(fnam)) then return true, "Missing parameters. Usage: download " end local callbacks = { OnStatusLine = function (self, a_HttpVersion, a_Status, a_Rest) if (a_Status ~= 200) then LOG("Cannot download " .. url .. ", HTTP error code " .. a_Status) return end local f, err = io.open(fnam, "wb") if not(f) then LOG("Cannot download " .. url .. ", error opening the file " .. fnam .. ": " .. (err or "")) return end self.m_File = f end, OnBodyData = function (self, a_Data) if (self.m_File) then self.m_File:write(a_Data) end end, OnBodyFinished = function (self) if (self.m_File) then self.m_File:close() LOG("File " .. fnam .. " has been downloaded.") end end, } local isSuccess, msg = cUrlClient:Get(url, callbacks) if not(isSuccess) then LOG("Cannot start an URL download: " .. (msg or "")) return true end return true end function HandleBlkCmd(a_Split, a_Player) -- Gets info about the block the player is looking at. local World = a_Player:GetWorld(); local Callbacks = { OnNextBlock = function(a_BlockPos, a_BlockType, a_BlockMeta) if (a_BlockType ~= E_BLOCK_AIR) then a_Player:SendMessage("Block at " .. a_BlockPos.x .. ", " .. a_BlockPos.y .. ", " .. a_BlockPos.z .. " is " .. a_BlockType .. ":" .. a_BlockMeta) return true; end end }; local EyePos = a_Player:GetEyePosition(); local LookVector = a_Player:GetLookVector(); LookVector:Normalize(); local End = EyePos + LookVector * 50; cLineBlockTracer.Trace(World, Callbacks, EyePos, End); return true; end function HandleBoomCmd(a_Split, a_Player) local playerPos = a_Player:GetPosition() a_Player:GetWorld():BroadcastParticleEffect("smoke", Vector3f(playerPos), Vector3f(), 0, 900) a_Player:GetWorld():BroadcastSoundEffect("entity.firework.large_blast", playerPos, 1, 1) a_Player:SendMessage("BOOM!") return true end function HandleTeamsCmd(a_Split, a_Player) local Scoreboard = a_Player:GetWorld():GetScoreBoard() a_Player:SendMessage("Teams: " .. table.concat(Scoreboard:GetTeamNames(), ", ")) return true end ================================================ FILE: Server/Plugins/Debuggers/Info.lua ================================================ -- Info.lua -- Implements the g_PluginInfo standard plugin description g_PluginInfo = { Name = "Debuggers", Version = "14", Date = "2014-12-11", Description = [[Contains code for testing and debugging the server. Should not be enabled on a production server!]], Commands = { ["/arr"] = { Permission = "debuggers", Handler = HandleArrowCmd, HelpString = "Creates an arrow going away from the player" }, ["/blk"] = { Permission = "debuggers", Handler = HandleBlkCmd, HelpString = "Gets info about the block you are looking at" }, ["/boom"] = { Permission = "debuggers", Handler = HandleBoomCmd, HelpString = "Playes a sound and displays an effect at the player's position", }, ["/cake"] = { Permission = "debuggers", Handler = HandleCakeCmd, HelpString = "Throws a cake in the direction the player's looking, in a slow arc.", }, ["/clientversion"] = { Permission = "debuggers", Handler = HandleClientVersionCmd, HelpString = "Shows your client's protocol version", }, ["/come"] = { Permission = "debuggers.come", Handler = HandleComeCmd, HelpString = "Instruct the mob you're looking at to navigate to your position", }, ["/compo"] = { Permission = "debuggers", Handler = HandleCompo, HelpString = "Tests the cCompositeChat bindings" }, ["/cstay"] = { Permission = "debuggers", Handler = HandleChunkStay, HelpString = "Tests the ChunkStay Lua integration for the specified chunk coords" }, ["/dash"] = { Permission = "debuggers", Handler = HandleDashCmd, HelpString = "Switches between fast and normal sprinting speed" }, ["/ench"] = { Permission = "debuggers", Handler = HandleEnchCmd, HelpString = "Provides an instant dummy enchantment window" }, ["/fast"] = { Permission = "debuggers", Handler = HandleFastCmd, HelpString = "Switches between fast and normal movement speed" }, ["/fb"] = { Permission = "debuggers", Handler = HandleFireballCmd, HelpString = "Creates a ghast fireball as if shot by the player" }, ["/ff"] = { Permission = "debuggers", Handler = HandleFurnaceFuel, HelpString = "Shows how long the currently held item would burn in a furnace" }, ["/fill"] = { Permission = "debuggers", Handler = HandleFill, HelpString = "Fills all block entities in current chunk with junk" }, ["/fl"] = { Permission = "debuggers", Handler = HandleFoodLevelCmd, HelpString = "Sets the food level to the given value" }, ["/fr"] = { Permission = "debuggers", Handler = HandleFurnaceRecipe, HelpString = "Shows the furnace recipe for the currently held item" }, ["/fs"] = { Permission = "debuggers", Handler = HandleFoodStatsCmd, HelpString = "Turns regular foodstats message on or off" }, ["/gc"] = { Permission = "debuggers", Handler = HandleGCCmd, HelpString = "Activates the Lua garbage collector" }, ["/genrails"] = { Permission = "debuggers", Handler = HandleGenRailsCmd, HelpString = "Generates rail blocks with all metas from current block towards X+", }, ["/getcustomname"] = { Permission = "debuggers", Handler = HandleGetCustomNameCmd, HelpString = "Displays the exact custom name of currently held item (including non-printables)", }, ["/getlore"] = { Permission = "debuggers", Handler = HandleGetLoreCmd, HelpString = "Displays the exact Lore of currently held item (including non-printables)", }, ["/getprop"] = { Permission = "debuggers", Handler = HandleGetPropCmd, HelpString = "Displays the custom cItem property of the currently held item", }, ["/hunger"] = { Permission = "debuggers", Handler = HandleHungerCmd, HelpString = "Lists the current hunger-related variables" }, ["/ke"] = { Permission = "debuggers", Handler = HandleKillEntitiesCmd, HelpString = "Kills all the loaded entities" }, ["/le"] = { Permission = "debuggers", Handler = HandleListEntitiesCmd, HelpString = "Shows a list of all the loaded entities" }, ["/nick"] = { Permission = "debuggers", Handler = HandleNickCmd, HelpString = "Gives you a custom name", }, ["/pickups"] = { Permission = "debuggers", Handler = HandlePickups, HelpString = "Spawns random pickups around you" }, ["/plugmsg"] = { Permission = "debuggers", Handler = HandlePlugMsg, HelpString = "Sends a test plugin message to the client", }, ["/poison"] = { Permission = "debuggers", Handler = HandlePoisonCmd, HelpString = "Sets food-poisoning for 15 seconds" }, ["/poof"] = { Permission = "debuggers", Handler = HandlePoof, HelpString = "Nudges pickups close to you away from you" }, ["/rmitem"] = { Permission = "debuggers", Handler = HandleRMItem, HelpString = "Remove the specified item from the inventory." }, ["/sb"] = { Permission = "debuggers", Handler = HandleSetBiome, HelpString = "Sets the biome around you to the specified one" }, ["/sched"] = { Permission = "debuggers", Handler = HandleSched, HelpString = "Schedules a simple countdown using cWorld:ScheduleTask()" }, ["/setcustomname"] = { Permission = "debuggers", Handler = HandleSetCustomNameCmd, HelpString = "Sets the custom name for the item currently in hand", }, ["/setlore"] = { Permission = "debuggers", Handler = HandleSetLoreCmd, HelpString = "Sets the lore for the item currently in hand", }, ["/setprop"] = { Permission = "debuggers", Handler = HandleSetPropCmd, HelpString = "Sets the custom property for the item currently in hand", }, ["/spidey"] = { Permission = "debuggers", Handler = HandleSpideyCmd, HelpString = "Shoots a line of web blocks until it hits non-air" }, ["/starve"] = { Permission = "debuggers", Handler = HandleStarveCmd, HelpString = "Sets the food level to zero" }, ["/teams"] = { Permission = "debuggers", Handler = HandleTeamsCmd, HelpString = "List the teams" }, ["/testwnd"] = { Permission = "debuggers", Handler = HandleTestWndCmd, HelpString = "Opens up a window using plugin API" }, ["/vector"] = { Permission = "debuggers", Handler = HandleVectorCmd, HelpString = "Tests the Vector3 API", }, ["/wesel"] = { Permission = "debuggers", Handler = HandleWESel, HelpString = "Expands the current WE selection by 1 block in X/Z" }, ["/wool"] = { Permission = "debuggers", Handler = HandleWoolCmd, HelpString = "Sets all your armor to blue wool" }, ["/xpa"] = { Permission = "debuggers", Handler = HandleAddExperience, HelpString = "Adds 200 experience to the player" }, ["/xpr"] = { Permission = "debuggers", Handler = HandleRemoveXp, HelpString = "Remove all xp" }, }, -- Commands ConsoleCommands = { ["bbox"] = { Handler = HandleConsoleBBox, HelpString = "Performs cBoundingBox API tests", }, ["deadlock"] = { Handler = HandleConsoleDeadlock, HelpString = "Simulates a deadlock, either on the command execution thread, or on a world tick thread", }, ["download"] = { Handler = HandleConsoleDownload, HelpString = "Downloads a file from a specified URL", }, ["hash"] = { Handler = HandleConsoleHash, HelpString = "Tests the crypto hashing functions", }, ["hittrace"] = { Handler = HandleConsoleHitTrace, HelpString = "Tests the FirstSolidHit trace", }, ["inh"] = { Handler = HandleConsoleInh, HelpString = "Tests the bindings of the cEntity inheritance", }, ["loadchunk"] = { Handler = HandleConsoleLoadChunk, HelpString = "Loads the specified chunk into memory", }, ["lostrace"] = { Handler = HandleConsoleLosTrace, HelpString = "Tests a LineOfSight trace", }, ["pluginstats"] = { Handler = HandleConsolePluginStats, HelpString = "Shows the stats for each plugin", }, ["preparechunk"] = { Handler = HandleConsolePrepareChunk, HelpString = "Prepares the specified chunk completely (load / gen / light)", }, ["sched"] = { Handler = HandleConsoleSchedule, HelpString = "Tests the world scheduling", }, ["testbbox"] = { Handler = HandleConsoleTestBbox, HelpString = "Tests cBoundingBox API" }, ["testcall"] = { Handler = HandleConsoleTestCall, HelpString = "Tests inter-plugin calls with various values" }, ["testerr"] = { Handler = HandleConsoleTestErr, HelpString = "Tests the server's ability to recover from errors in callbacks (GH #3733)", }, ["testjson"] = { Handler = HandleConsoleTestJson, HelpString = "Tests the cJson parser and serializer", }, ["testtracer"] = { Handler = HandleConsoleTestTracer, HelpString = "Tests the cLineBlockTracer", }, ["testtracerdeprecated"] = { Handler = HandleConsoleTestTracerDeprecated, HelpString = "Tests the cLineBlockTracer's deprecated API", }, ["testurlclient"] = { Handler = HandleConsoleTestUrlClient, HelpString = "Tests the cUrlClient", }, ["testurlparser"] = { Handler = HandleConsoleTestUrlParser, HelpString = "Tests the cUrlParser", }, ["uuid"] = { Handler = HandleConsoleUuid, HelpString = "Queries the cMojangAPI for a player's UUID", } }, -- ConsoleCommands } -- g_PluginInfo ================================================ FILE: Server/Plugins/Debuggers/Inject.lua ================================================ -- Inject.lua -- This file gets injected into the Core plugin when testing the inter-plugin calls with the "testcall" command -- However, since this is a .lua file, it also gets loaded into the Debuggers plugin, so we need to distinguish the two --- Prints the specified table to the log, using the specified indent -- Assumes there are no cycles in the table and all keys and values can be turned to strings local function printTable(a_Table, a_Indent) for k, v in pairs(a_Table) do LOG(a_Indent .. "k = " .. tostring(k)) if (type(k) == "table") then printTable(k, a_Indent .. " ") end LOG(a_Indent .. "v = " .. tostring(v)) if (type(v) == "table") then printTable(v, a_Indent .. " ") end end end local function printParams(...) LOG("printParams:") for idx, param in ipairs({...}) do LOG(" param" .. idx .. ": " .. tostring(param)) if (type(param) == "table") then printTable(param, " ") end end LOG("done") return true end local pluginName = cPluginManager:Get():GetCurrentPlugin():GetName() if (pluginName ~= "Debuggers") then -- We're in the destination plugin LOG("Loaded Inject.lua into " .. pluginName) injectedPrintParams = printParams return true else -- We're in the Debuggers plugin, do nothing end ================================================ FILE: Server/Plugins/DumpInfo/Init.lua ================================================ function Initialize(a_Plugin) a_Plugin:SetName("DumpInfo") a_Plugin:SetVersion(1) -- Check if the infodump file exists. if (not cFile:IsFile("Plugins/InfoDump.lua")) then LOGWARN("InfoDump.lua was not found.") return false end -- Add the webtab. a_Plugin:AddWebTab("DumpPlugin", HandleDumpPluginRequest) return true end function HandleDumpPluginRequest(a_Request) local Content = "" -- Check if it already was requested to dump a plugin. if (a_Request.PostParams["DumpInfo"] ~= nil) then local F = loadfile("Plugins/InfoDump.lua") F("Plugins/" .. cPluginManager:Get():GetPluginFolderName(a_Request.PostParams["DumpInfo"])) end Content = Content .. [[ ]] -- Loop through each plugin that is found. cPluginManager:Get():ForEachPlugin( function(a_Plugin) -- Check if there is a file called 'Info.lua' if (cFile:IsFile(a_Plugin:GetLocalFolder() .. "/Info.lua")) then Content = Content .. "\n\n" Content = Content .. "\t\n" Content = Content .. "\t\n" Content = Content .. "\n" end end ) Content = Content .. [[
    DumpInfo
    " .. a_Plugin:GetName() .. "
    ]] return Content end ================================================ FILE: Server/Plugins/HookNotify/HookNotify.lua ================================================ -- HookNotify.lua --[[ Implements the entire plugin NOTE: This plugin is not meant for production servers. It is used mainly by developers to verify that things are working properly when implementing Cuberite features. Do not enable this plugin on production servers! This plugin logs a notification for each hook that is being called by the server. The TICK and WORLD_TICK hooks are disabled because they produce too much output. --]] function Initialize(a_Plugin) -- Notify the admin that HookNotify is installed, this is not meant for production servers LOGINFO("HookNotify plugin is installed, beware, the log output may be quite large!"); LOGINFO("You want this plugin enabled only when developing another plugin, not for regular gameplay."); -- These hooks will not be notified: local hooksToIgnore = { ["HOOK_TICK"] = true, -- Too much spam ["HOOK_WORLD_TICK"] = true, -- Too much spam ["HOOK_TAKE_DAMAGE"] = true, -- Has a separate handler with more info logged ["HOOK_MAX"] = true, -- No such hook, placeholder only ["HOOK_NUM_HOOKS"] = true, -- No such hook, placeholder only } -- Add all hooks: for n, v in pairs(cPluginManager) do if (n:match("HOOK_.*")) then if not(hooksToIgnore[n]) then LOG("Adding notification for hook " .. n .. " (" .. v .. ").") cPluginManager.AddHook(v, function (...) LOG(n .. "(") for i, param in ipairs(arg) do LOG(" " .. i .. ": " .. tolua.type(param) .. ": " .. tostring(param)) end LOG(")"); end -- hook handler ) -- AddHook end -- not (ignore) end -- n matches "HOOK" end -- for cPluginManager{} -- OnTakeDamage has a special handler listing the details of the damage dealt: cPluginManager.AddHook(cPluginManager.HOOK_TAKE_DAMAGE, function (a_Receiver, a_TDI) -- a_Receiver is cPawn -- a_TDI is TakeDamageInfo LOG("OnTakeDamage(): " .. a_Receiver:GetClass() .. " was dealt RawDamage " .. a_TDI.RawDamage .. ", FinalDamage " .. a_TDI.FinalDamage .. " (that is, " .. (a_TDI.RawDamage - a_TDI.FinalDamage) .. " HPs covered by armor)"); end ) return true end ================================================ FILE: Server/Plugins/InfoDump.lua ================================================ #!/usr/bin/lua -- InfoDump.lua --[[ Loads plugins' Info.lua and dumps its g_PluginInfo (or gPluginInfo) into various text formats This is used for generating plugin documentation for the forum and for GitHub's INFO.md files This script can be used in two ways: Executing "lua InfoDump.lua" will go through all subfolders and dump each Info.lua file it can find Note that this mode of operation requires LuaRocks with LFS installed; instructions are printed when the prerequisites are not met. Executing "lua InfoDump.lua PluginName" will load the Info.lua file from PluginName's folder and dump only that one plugin's documentation. This mode of operation doesn't require LuaRocks --]] -- If this file is called using the loadfile function the arg variable isn't filled. We have to do it manualy then. local arg = arg or {...} -- Check Lua version. We use 5.1-specific construct when loading the plugin info, 5.2 is not compatible! if (_VERSION ~= "Lua 5.1") then print("Unsupported Lua version. This script requires Lua version 5.1, this Lua is version " .. (_VERSION or "")) return end --- Removes any whitespace at the beginning and end of the string local function TrimString(a_Str) return (string.match(a_Str, "^%s*(.-)%s*$")) end --- Replaces generic formatting with forum-specific formatting -- Also removes the single line-ends local function ForumizeString(a_Str) assert(type(a_Str) == "string") -- Remove the indentation, unless in the code tag: -- Only one code or /code tag per line is supported! local IsInCode = false local function RemoveIndentIfNotInCode(s) if (IsInCode) then -- we're in code section, check if this line terminates it IsInCode = (s:find("{%%/code}") ~= nil) return s .. "\n" else -- we're not in code section, check if this line starts it IsInCode = (s:find("{%%code}") ~= nil) return s:gsub("^%s*", "") .. "\n" end end a_Str = a_Str:gsub("(.-)\n", RemoveIndentIfNotInCode) -- Replace multiple line ends with {%p} and single line ends with a space, -- so that manual word-wrap in the Info.lua file doesn't wrap in the forum. a_Str = a_Str:gsub("\n\n", "{%%p}") a_Str = a_Str:gsub("\n", " ") -- Replace the generic formatting: a_Str = a_Str:gsub("{%%p}", "\n\n") a_Str = a_Str:gsub("{%%b}", "[b]"):gsub("{%%/b}", "[/b]") a_Str = a_Str:gsub("{%%i}", "[i]"):gsub("{%%/i}", "[/i]") a_Str = a_Str:gsub("{%%list}", "\n[list]"):gsub("{%%/list}", "[/list]") a_Str = a_Str:gsub("{%%li}", "\n[*]"):gsub("{%%/li}", "\n") -- Process links: {%a LinkDestination}LinkText{%/a} a_Str = a_Str:gsub("{%%a%s([^}]*)}([^{]*){%%/a}", "[url=%1]%2[/url]") -- TODO: Other formatting return a_Str end --- Replaces generic formatting with forum-specific formatting -- Also removes the single line-ends local function GithubizeString(a_Str) assert(type(a_Str) == "string") -- Remove the indentation, unless in the code tag: -- Only one code or /code tag per line is supported! local IsInCode = false local function RemoveIndentIfNotInCode(s) if (IsInCode) then -- we're in code section, check if this line terminates it IsInCode = (s:find("{%%/code}") ~= nil) return s .. "\n" else -- we're not in code section, check if this line starts it IsInCode = (s:find("{%%code}") ~= nil) return s:gsub("^%s*", "") .. "\n" end end a_Str = a_Str:gsub("(.-)\n", RemoveIndentIfNotInCode) -- Replace multiple line ends with {%p} and single line ends with a space, -- so that manual word-wrap in the Info.lua file doesn't wrap in the forum. a_Str = a_Str:gsub("\n\n", "{%%p}") a_Str = a_Str:gsub("\n", " ") -- Replace the generic formatting: a_Str = a_Str:gsub("{%%p}", "\n\n") a_Str = a_Str:gsub("{%%b}", "**"):gsub("{%%/b}", "**") a_Str = a_Str:gsub("{%%i}", "*"):gsub("{%%/i}", "*") a_Str = a_Str:gsub("{%%list}", "\n"):gsub("{%%/list}", "\n") a_Str = a_Str:gsub("{%%li}", "\n - "):gsub("{%%/li}", "") -- Process links: {%a LinkDestination}LinkText{%/a} a_Str = a_Str:gsub("{%%a%s([^}]*)}([^{]*){%%/a}", "[%2](%1)") -- TODO: Other formatting return a_Str end --- Builds an array of categories, each containing all the commands belonging to the category, -- and the category description, if available. -- Returns the array table, each item has the following format: -- { Name = "CategoryName", Description = "CategoryDescription", Commands = {{CommandString = "/cmd verb", Info = {...}}, ...}} local function BuildCategories(a_PluginInfo) -- The returned result -- This will contain both an array and a dict of the categories, to allow fast search local res = {} -- For each command add a reference to it into all of its categories: local function AddCommands(a_CmdPrefix, a_Commands) for cmd, info in pairs(a_Commands or {}) do local NewCmd = { CommandString = a_CmdPrefix .. cmd, Info = info, } if ((info.HelpString ~= nil) and (info.HelpString ~= "")) then -- Add to each specified category: local Category = info.Category if (type(Category) == "string") then Category = {Category} end for idx, cat in ipairs(Category or {""}) do local CatEntry = res[cat] if (CatEntry == nil) then -- First time we came across this category, create it: local NewCat = {Name = cat, Description = "", Commands = {NewCmd}} table.insert(res, NewCat) res[cat] = NewCat else -- We already have this category, just add the command to its list of commands: table.insert(CatEntry.Commands, NewCmd) end end -- for idx, cat - Category[] end -- if (HelpString valid) -- Recurse all subcommands: if (info.Subcommands ~= nil) then AddCommands(a_CmdPrefix .. cmd .. " ", info.Subcommands) end end -- for cmd, info - a_Commands[] end -- AddCommands() AddCommands("", a_PluginInfo.Commands) -- Assign descriptions to categories: for name, desc in pairs(a_PluginInfo.Categories or {}) do local CatEntry = res[name] if (CatEntry ~= nil) then -- The result has this category, add the description: CatEntry.Description = desc.Description end end -- Alpha-sort each category's command list: for idx, cat in ipairs(res) do table.sort(cat.Commands, function (cmd1, cmd2) return (string.lower(cmd1.CommandString) < string.lower(cmd2.CommandString)) end ) end return res end --- Returns a string specifying the command. -- If a_Command is a simple string, returns a_Command colorized to blue -- If a_Command is a table, expects members Name (full command name) and Params (command parameters), -- colorizes command name blue and params green local function GetCommandRefForum(a_Command) if (type(a_Command) == "string") then return "[color=blue]" .. a_Command .. "[/color]" end return "[color=blue]" .. a_Command.Name .. "[/color] [color=green]" .. (a_Command.Params or "") .. "[/color]" end --- Returns a string specifying the command. -- If a_CommandParams is nil, returns a_CommandName apostrophed -- If a_CommandParams is a string, apostrophes a_CommandName with a_CommandParams local function GetCommandRefGithub(a_CommandName, a_CommandParams) assert(type(a_CommandName) == "string") if (a_CommandParams == nil) then return "`" .. a_CommandName .. "`" end assert(type(a_CommandParams) == "table") if ((a_CommandParams.Params == nil) or (a_CommandParams.Params == "")) then return "`" .. a_CommandName .. "`" end assert(type(a_CommandParams.Params) == "string") return "`" .. a_CommandName .. " " .. a_CommandParams.Params .. "`" end --- Writes the specified command detailed help array to the output file, in the forum dump format local function WriteCommandParameterCombinationsForum(a_CmdString, a_ParameterCombinations, f) assert(type(a_CmdString) == "string") assert(type(a_ParameterCombinations) == "table") assert(f ~= nil) if (#a_ParameterCombinations == 0) then -- No explicit parameter combinations to write return end f:write("The following parameter combinations are recognized:\n") for idx, combination in ipairs(a_ParameterCombinations) do f:write("[color=blue]", a_CmdString, "[/color] [color=green]", combination.Params or "", "[/color]") if (combination.Help ~= nil) then f:write(" - ", ForumizeString(combination.Help)) end if (combination.Permission ~= nil) then f:write(" (Requires permission '[color=red]", combination.Permission, "[/color]')") end f:write("\n") end end --- Writes the specified command detailed help array to the output file, in the forum dump format local function WriteCommandParameterCombinationsGithub(a_CmdString, a_ParameterCombinations, f) assert(type(a_CmdString) == "string") assert(type(a_ParameterCombinations) == "table") assert(f ~= nil) if (#a_ParameterCombinations == 0) then -- No explicit parameter combinations to write return end f:write("The following parameter combinations are recognized:\n\n") for idx, combination in ipairs(a_ParameterCombinations) do f:write(GetCommandRefGithub(a_CmdString, combination)) if (combination.Help ~= nil) then f:write(" - ", GithubizeString(combination.Help)) end if (combination.Permission ~= nil) then f:write(" (Requires permission '**", combination.Permission, "**')") end f:write("\n") end end --- Writes all commands in the specified category to the output file, in the forum dump format local function WriteCommandsCategoryForum(a_Category, f) -- Write category name: local CategoryName = a_Category.Name if (CategoryName == "") then CategoryName = "General" end f:write("\n[size=large]", ForumizeString(a_Category.DisplayName or CategoryName), "[/size]\n") -- Write description: if (a_Category.Description ~= "") then f:write(ForumizeString(a_Category.Description), "\n") end -- Write commands: f:write("\n[list]") for idx2, cmd in ipairs(a_Category.Commands) do f:write("\n[b]", cmd.CommandString, "[/b] - ", ForumizeString(cmd.Info.HelpString or "UNDOCUMENTED"), "\n") if (cmd.Info.Permission ~= nil) then f:write("Permission required: [color=red]", cmd.Info.Permission, "[/color]\n") end if (cmd.Info.DetailedDescription ~= nil) then f:write(ForumizeString(cmd.Info.DetailedDescription)) end if (cmd.Info.ParameterCombinations ~= nil) then WriteCommandParameterCombinationsForum(cmd.CommandString, cmd.Info.ParameterCombinations, f) end end f:write("[/list]\n\n") end --- Writes all commands in the specified category to the output file, in the Github dump format local function WriteCommandsCategoryGithub(a_Category, f) -- Write category name: local CategoryName = a_Category.Name if (CategoryName == "") then CategoryName = "General" end f:write("\n### ", GithubizeString(a_Category.DisplayName or CategoryName), "\n") -- Write description: if (a_Category.Description ~= "") then f:write(GithubizeString(a_Category.Description), "\n\n") end f:write("| Command | Permission | Description |\n") f:write("| ------- | ---------- | ----------- |\n") -- Write commands: for idx2, cmd in ipairs(a_Category.Commands) do f:write("|", cmd.CommandString, " | ", cmd.Info.Permission or "", " | ", GithubizeString(cmd.Info.HelpString or "UNDOCUMENTED"), "|\n") end f:write("\n\n") end local function DumpCommandsForum(a_PluginInfo, f) -- Copy all Categories from a dictionary into an array: local Categories = BuildCategories(a_PluginInfo) -- Sort the categories by name: table.sort(Categories, function(cat1, cat2) return (string.lower(cat1.Name) < string.lower(cat2.Name)) end ) if (#Categories == 0) then return end f:write("\n[size=x-large]Commands[/size]\n") -- Dump per-category commands: for idx, cat in ipairs(Categories) do WriteCommandsCategoryForum(cat, f) end end local function DumpCommandsGithub(a_PluginInfo, f) -- Copy all Categories from a dictionary into an array: local Categories = BuildCategories(a_PluginInfo) -- Sort the categories by name: table.sort(Categories, function(cat1, cat2) return (string.lower(cat1.Name) < string.lower(cat2.Name)) end ) if (#Categories == 0) then return end f:write("\n# Commands\n") -- Dump per-category commands: for idx, cat in ipairs(Categories) do WriteCommandsCategoryGithub(cat, f) end end local function DumpAdditionalInfoForum(a_PluginInfo, f) local AInfo = a_PluginInfo.AdditionalInfo if (type(AInfo) ~= "table") then -- There is no AdditionalInfo in a_PluginInfo return end for idx, info in ipairs(a_PluginInfo.AdditionalInfo) do if ((info.Title ~= nil) and (info.Contents ~= nil)) then f:write("\n[size=x-large]", ForumizeString(info.Title), "[/size]\n") f:write(ForumizeString(info.Contents), "\n") end end end local function DumpAdditionalInfoGithub(a_PluginInfo, f) local AInfo = a_PluginInfo.AdditionalInfo if (type(AInfo) ~= "table") then -- There is no AdditionalInfo in a_PluginInfo return end for idx, info in ipairs(a_PluginInfo.AdditionalInfo) do if ((info.Title ~= nil) and (info.Contents ~= nil)) then f:write("\n# ", GithubizeString(info.Title), "\n") f:write(GithubizeString(info.Contents), "\n") end end end --- Collects all permissions mentioned in the info, returns them as a sorted array -- Each array item is {Name = "PermissionName", Info = { PermissionInfo }} local function BuildPermissions(a_PluginInfo) -- Collect all used permissions from Commands, reference the commands that use the permission: local Permissions = a_PluginInfo.Permissions or {} local function CollectPermissions(a_CmdPrefix, a_Commands) for cmd, info in pairs(a_Commands or {}) do CommandString = a_CmdPrefix .. cmd if ((info.Permission ~= nil) and (info.Permission ~= "")) then -- Add the permission to the list of permissions: local Permission = Permissions[info.Permission] or {} Permissions[info.Permission] = Permission -- Add the command to the list of commands using this permission: Permission.CommandsAffected = Permission.CommandsAffected or {} -- First, make sure that we don't already have this command in the list, -- it may have already been present in a_PluginInfo local NewCommand = true for _, existCmd in ipairs(Permission.CommandsAffected) do if CommandString == existCmd then NewCommand = false break end end if NewCommand then table.insert(Permission.CommandsAffected, CommandString) end end -- Process the command param combinations for permissions: local ParamCombinations = info.ParameterCombinations or {} for idx, comb in ipairs(ParamCombinations) do if ((comb.Permission ~= nil) and (comb.Permission ~= "")) then -- Add the permission to the list of permissions: local Permission = Permissions[comb.Permission] or {} Permissions[info.Permission] = Permission -- Add the command to the list of commands using this permission: Permission.CommandsAffected = Permission.CommandsAffected or {} table.insert(Permission.CommandsAffected, {Name = CommandString, Params = comb.Params}) end end -- Process subcommands: if (info.Subcommands ~= nil) then CollectPermissions(CommandString .. " ", info.Subcommands) end end end CollectPermissions("", a_PluginInfo.Commands) -- Copy the list of permissions to an array: local PermArray = {} for name, perm in pairs(Permissions) do table.insert(PermArray, {Name = name, Info = perm}) end -- Sort the permissions array: table.sort(PermArray, function(p1, p2) return (p1.Name < p2.Name) end ) return PermArray end local function DumpPermissionsForum(a_PluginInfo, f) -- Get the processed sorted array of permissions: local Permissions = BuildPermissions(a_PluginInfo) if ((Permissions == nil) or (#Permissions <= 0)) then return end -- Dump the permissions: f:write("\n[size=x-large]Permissions[/size]\n[list]\n") for idx, perm in ipairs(Permissions) do f:write(" - [color=red]", perm.Name, "[/color] - ") f:write(ForumizeString(perm.Info.Description or "")) local CommandsAffected = perm.Info.CommandsAffected or {} if (#CommandsAffected > 0) then f:write("\n[list] Commands affected:\n- ") local Affects = {} for idx2, cmd in ipairs(CommandsAffected) do table.insert(Affects, GetCommandRefForum(cmd)) end f:write(table.concat(Affects, "\n - ")) f:write("\n[/list]") end if (perm.Info.RecommendedGroups ~= nil) then f:write("\n[list] Recommended groups: ", perm.Info.RecommendedGroups, "[/list]") end f:write("\n") end f:write("[/list]") end local function DumpPermissionsGithub(a_PluginInfo, f) -- Get the processed sorted array of permissions: local Permissions = BuildPermissions(a_PluginInfo) if ((Permissions == nil) or (#Permissions <= 0)) then return end -- Dump the permissions: f:write("\n# Permissions\n") f:write("| Permissions | Description | Commands | Recommended groups |\n") f:write("| ----------- | ----------- | -------- | ------------------ |\n") for idx, perm in ipairs(Permissions) do f:write("| ", perm.Name, " | ") f:write(GithubizeString(perm.Info.Description or ""), " | ") local CommandsAffected = perm.Info.CommandsAffected or {} if (#CommandsAffected > 0) then local Affects = {} for idx2, cmd in ipairs(CommandsAffected) do if (type(cmd) == "string") then table.insert(Affects, GetCommandRefGithub(cmd)) else table.insert(Affects, GetCommandRefGithub(cmd.Name, cmd)) end end f:write(table.concat(Affects, ", ")) end f:write(" | ") if (perm.Info.RecommendedGroups ~= nil) then f:write(perm.Info.RecommendedGroups) end f:write(" |\n") end end local function DumpDependenciesForum(a_PluginInfo, f) if (not a_PluginInfo.Dependencies) then return end f:write("\n[size=x-large]Dependencies[/size]\n[list]") for idx, dependency in ipairs(a_PluginInfo.Dependencies) do f:write("\n\n [*] [b]", dependency.Name, "[/b]", dependency.Optional == true and " (Optional)" or " (Required)") if (dependency.Description) then f:write("\nDescription: ", ForumizeString(dependency.Description)) end if (dependency.Type) then f:write("\nType: ", dependency.Type) end if (dependency.Url) then f:write("\nUrl: ", dependency.Url) end end f:write("\n[/list]") end local function DumpDependenciesGithub(a_PluginInfo, f) if (not a_PluginInfo.Dependencies) then return end f:write("\n# Dependencies\n") for idx, dependency in ipairs(a_PluginInfo.Dependencies) do f:write("\n\n * **", dependency.Name, "** ", dependency.Optional == true and "(Optional)" or "(Required)") if (dependency.Description) then f:write("
    \nDescription: ", GithubizeString(dependency.Description)) end if (dependency.Type) then f:write("
    \nType: ", dependency.Type) end if (dependency.Url) then f:write("
    \nUrl: [", dependency.Url, "](", dependency.Url , ")") end end end --- Dumps the forum-format info for the plugin -- Returns true on success, nil and error message on failure local function DumpPluginInfoForum(a_PluginFolder, a_PluginInfo) -- Open the output file: local f, msg = io.open(a_PluginFolder .. "/forum_info.txt", "w") if (f == nil) then return nil, msg end -- Write the description: f:write(ForumizeString(a_PluginInfo.Description), "\n") DumpAdditionalInfoForum(a_PluginInfo, f) DumpCommandsForum(a_PluginInfo, f) DumpPermissionsForum(a_PluginInfo, f) DumpDependenciesForum(a_PluginInfo, f) if (a_PluginInfo.SourceLocation ~= nil) then f:write("\n[b]Source[/b]: ", a_PluginInfo.SourceLocation, "\n") end if (a_PluginInfo.DownloadLocation ~= nil) then f:write("[b]Download[/b]: ", a_PluginInfo.DownloadLocation) end f:close() return true end --- Dumps the README.md file into the plugin's folder with the GitHub Markdown format -- Returns true on success, nil and error message on failure local function DumpPluginInfoGithub(a_PluginFolder, a_PluginInfo) -- Check the params: assert(type(a_PluginFolder) == "string") assert(type(a_PluginInfo) == "table") -- Open the output file: local f, msg = io.open(a_PluginFolder .. "/README.md", "w") if (f == nil) then print("\tCannot dump github info for plugin " .. a_PluginFolder .. ": " .. msg) return nil, msg end -- Write the description: f:write(TrimString(GithubizeString(a_PluginInfo.Description)), "\n") DumpAdditionalInfoGithub(a_PluginInfo, f) DumpCommandsGithub(a_PluginInfo, f) DumpPermissionsGithub(a_PluginInfo, f) DumpDependenciesGithub(a_PluginInfo, f) f:close() return true end --- Tries to load the g_PluginInfo or gPluginInfo from the plugin's Info.lua file -- Returns the plugin info table on success, or nil and error message on failure local function LoadPluginInfo(a_FolderName) -- Load and compile the Info file: local cfg, err = loadfile(a_FolderName .. "/Info.lua") if (cfg == nil) then return nil, "Cannot open 'Info.lua': " .. err end -- Execute the loaded file in a sandbox: -- This is Lua-5.1-specific and won't work in Lua 5.2! local Sandbox = {} setfenv(cfg, Sandbox) local isSuccess, errMsg = pcall(cfg) if not(isSuccess) then return nil, "Cannot load Info.lua: " .. (errMsg or "") end if (Sandbox.g_PluginInfo) then return Sandbox.g_PluginInfo elseif (Sandbox.gPluginInfo) then return Sandbox.gPluginInfo end return nil, "Info.lua doesn't contain the g_PluginInfo declaration" end --- Processes the info for one plugin -- Returns true on success, nil and error message on failure local function ProcessPluginFolder(a_FolderName) -- Load the plugin info: local PluginInfo, Msg = LoadPluginInfo(a_FolderName) if (PluginInfo == nil) then return nil, "Cannot load info for plugin " .. a_FolderName .. ": " .. (Msg or "") end -- Dump the forum format: local isSuccess isSuccess, Msg = DumpPluginInfoForum(a_FolderName, PluginInfo) if not(isSuccess) then return nil, "Cannot dump forum info for plugin " .. a_FolderName .. ": " .. (Msg or "") end -- Dump the GitHub format: isSuccess, Msg = DumpPluginInfoGithub(a_FolderName, PluginInfo) if not(isSuccess) then return nil, "Cannot dump GitHub info for plugin " .. a_FolderName .. ": " .. (Msg or "") end -- All OK, return success return true end --- Tries to load LFS through LuaRocks, returns the LFS instance, or nil on error local function LoadLFS() -- Try to load lfs, do not abort if not found ... local lfs, err = pcall( function() return require("lfs") end ) -- ... rather, print a nice message with instructions: if not(lfs) then print([[ Cannot load LuaFileSystem Install it through luarocks by executing the following command: luarocks install luafilesystem (Windows) sudo luarocks install luafilesystem (*nix) If you don't have luarocks installed, you need to install them using your OS's package manager, usually: sudo apt-get install luarocks (Ubuntu / Debian) On windows, a binary distribution can be downloaded from the LuaRocks homepage, https://github.com/luarocks/luarocks/wiki/Download ]]) print("Original error text: ", err) return nil end -- We now know that LFS is present, get it normally: return require("lfs") end local Arg1 = arg[1] if ((Arg1 ~= nil) and (Arg1 ~= "")) then -- Called with a plugin folder name, export only that one local isSuccess, msg = ProcessPluginFolder(Arg1) if not(isSuccess) then print(msg or "") end else -- Called without any arguments, process all subfolders: local lfs = LoadLFS() if (lfs == nil) then -- LFS not loaded, error has already been printed, just bail out return end print("Processing plugin subfolders:") for fnam in lfs.dir(".") do if ((fnam ~= ".") and (fnam ~= "..")) then local Attributes = lfs.attributes(fnam) if (Attributes ~= nil) then if (Attributes.mode == "directory") then print(fnam) local isSuccess, msg = ProcessPluginFolder(fnam) if not(isSuccess) then print(" " .. (msg or "")) end end end end end end print("Done.") ================================================ FILE: Server/Plugins/InfoReg.lua ================================================ -- InfoReg.lua --[[ Implements functions that process the standard PluginInfo description and register command handlers. The description is either given as a parameter to the registration functions, or read from the standard names gPluginInfo or g_PluginInfo. --]] --- Lists all the subcommands that the player has permissions for local function ListSubcommands(a_Player, a_Subcommands, a_CmdString) if (a_Player == nil) then LOGINFO("The " .. a_CmdString .. " command requires another verb:") else a_Player:SendMessage("The " .. a_CmdString .. " command requires another verb:") end -- Enum all the subcommands: local Verbs = {} for cmd, info in pairs(a_Subcommands) do if ((a_Player == nil) or (a_Player:HasPermission(info.Permission or ""))) then table.insert(Verbs, a_CmdString .. " " .. cmd) end end table.sort(Verbs) -- Send the list: if (a_Player == nil) then for idx, verb in ipairs(Verbs) do LOGINFO(" " .. verb) end else for idx, verb in ipairs(Verbs) do a_Player:SendMessage(cCompositeChat(" ", mtInfo):AddSuggestCommandPart(verb, verb)) end end end --- This is a generic command callback used for handling multicommands' parent commands -- For example, if there are "/gal save" and "/gal load" commands, this callback handles the "/gal" command -- It is used for both console and in-game commands; the console version has a_Player set to nil local function MultiCommandHandler(a_Split, a_Player, a_CmdString, a_CmdInfo, a_Level, a_EntireCommand) local Verb = a_Split[a_Level + 1] if (Verb == nil) then -- No verb was specified. If there is a handler for the upper level command, call it: if (a_CmdInfo.Handler ~= nil) then return a_CmdInfo.Handler(a_Split, a_Player, a_EntireCommand) end -- Let the player know they need to give a subcommand: assert(type(a_CmdInfo.Subcommands) == "table", "Info.lua error: There is no handler for command \"" .. a_CmdString .. "\" and there are no subcommands defined at level " .. a_Level) ListSubcommands(a_Player, a_CmdInfo.Subcommands, a_CmdString) return true end -- A verb was specified, look it up in the subcommands table: local Subcommand = a_CmdInfo.Subcommands[Verb] if (Subcommand == nil) then if (a_Level + 1 > 1) then -- This is a true subcommand, display the message and make MCS think the command was handled -- Otherwise we get weird behavior: for "/cmd verb" we get "unknown command /cmd" although "/cmd" is valid if (a_Player == nil) then LOGWARNING("The " .. a_CmdString .. " command doesn't support verb " .. Verb) else a_Player:SendMessage("The " .. a_CmdString .. " command doesn't support verb " .. Verb) end return true end -- This is a top-level command, let MCS handle the unknown message return false; end -- Check the permission: if (a_Player ~= nil) then if not(a_Player:HasPermission(Subcommand.Permission or "")) then a_Player:SendMessage("You don't have permission to execute this command") return true end end -- First check if the subcommand has subcommands if (Subcommand.Subcommands ~= nil) then -- Next sublevel return MultiCommandHandler(a_Split, a_Player, a_CmdString .. " " .. Verb, Subcommand, a_Level + 1, a_EntireCommand) elseif (Subcommand.Handler == nil) then -- Subcommand has no subcommands and the handler is not found, report error LOGWARNING("Cannot find handler for command " .. a_CmdString .. " " .. Verb) return false end -- Execute: return Subcommand.Handler(a_Split, a_Player, a_EntireCommand) end --- Registers all commands specified in the aPluginInfo.Commands -- If aPluginInfo is not given, gPluginInfo or g_PluginInfo is used function RegisterPluginInfoCommands(aPluginInfo) -- If no info given, assume the default name for the global variable aPluginInfo = aPluginInfo or g_PluginInfo or gPluginInfo -- A sub-function that registers all subcommands of a single command, using the command's Subcommands table -- The a_Prefix param already contains the space after the previous command -- a_Level is the depth of the subcommands being registered, with 1 being the top level command local function RegisterSubcommands(a_Prefix, a_Subcommands, a_Level) assert(a_Subcommands ~= nil) -- A table that will hold aliases to subcommands temporarily, during subcommand iteration local AliasTable = {} -- Iterate through the subcommands, register them, and accumulate aliases: for cmd, info in pairs(a_Subcommands) do local CmdName = a_Prefix .. cmd local Handler = info.Handler -- Provide a special handler for multicommands: if (info.Subcommands ~= nil) then Handler = function(a_Split, a_Player, a_EntireCommand) return MultiCommandHandler(a_Split, a_Player, CmdName, info, a_Level, a_EntireCommand) end end if (Handler == nil) then LOGWARNING(aPluginInfo.Name .. ": Invalid handler for command " .. CmdName .. ", command will not be registered.") else local HelpString if (info.HelpString ~= nil) then HelpString = " - " .. info.HelpString else HelpString = "" end cPluginManager:BindCommand(CmdName, info.Permission or "", Handler, HelpString) -- Register all aliases for the command: if (info.Alias ~= nil) then if (type(info.Alias) == "string") then info.Alias = {info.Alias} end for idx, alias in ipairs(info.Alias) do cPluginManager:BindCommand(a_Prefix .. alias, info.Permission or "", Handler, HelpString) -- Also copy the alias's info table as a separate subcommand, -- so that MultiCommandHandler() handles it properly. Need to off-load into a separate table -- than the one we're currently iterating and join after the iterating. AliasTable[alias] = info end end end -- else (if Handler == nil) -- Recursively register any subcommands: if (info.Subcommands ~= nil) then RegisterSubcommands(a_Prefix .. cmd .. " ", info.Subcommands, a_Level + 1) end end -- for cmd, info - a_Subcommands[] -- Add the subcommand aliases that were off-loaded during registration: for alias, info in pairs(AliasTable) do a_Subcommands[alias] = info end AliasTable = {} end -- Loop through all commands in the plugin info, register each: if (aPluginInfo.Commands) then RegisterSubcommands("", aPluginInfo.Commands, 1) end end --- Registers all console commands specified in the aPluginInfo.ConsoleCommands -- If aPluginInfo is not given, gPluginInfo or g_PluginInfo is used function RegisterPluginInfoConsoleCommands(aPluginInfo) -- If no info given, assume the default name for the global variable aPluginInfo = aPluginInfo or g_PluginInfo or gPluginInfo -- A sub-function that registers all subcommands of a single command, using the command's Subcommands table -- The a_Prefix param already contains the space after the previous command local function RegisterSubcommands(a_Prefix, a_Subcommands, a_Level) assert(a_Subcommands ~= nil) for cmd, info in pairs(a_Subcommands) do local CmdName = a_Prefix .. cmd local Handler = info.Handler if (Handler == nil) then Handler = function(a_Split, a_EntireCommand) return MultiCommandHandler(a_Split, nil, CmdName, info, a_Level, a_EntireCommand) end end cPluginManager:BindConsoleCommand(CmdName, Handler, info.HelpString or "") -- Recursively register any subcommands: if (info.Subcommands ~= nil) then RegisterSubcommands(a_Prefix .. cmd .. " ", info.Subcommands, a_Level + 1) end end end -- Loop through all commands in the plugin info, register each: if (aPluginInfo.ConsoleCommands) then RegisterSubcommands("", aPluginInfo.ConsoleCommands, 1) end end ================================================ FILE: Server/Plugins/NetworkTest/Info.lua ================================================ -- Info.lua -- Implements the g_PluginInfo standard plugin description g_PluginInfo = { Name = "NetworkTest", Version = "1", Date = "2015-01-28", Description = [[Implements test code (and examples) for the cNetwork API]], Commands = { }, ConsoleCommands = { net = { Subcommands = { client = { HelpString = "Connects, as a client, to a specified webpage (google.com by default) and downloads its front page using HTTP", Handler = HandleConsoleNetClient, ParameterCombinations = { { Params = "", Help = "Connects, as a client, to google.com and downloads its front page using HTTP", }, { Params = "host [port]", Help = "Connects, as a client, to the specified host and downloads its front page using HTTP", }, }, -- ParameterCombinations }, -- client close = { HelpString = "Close a listening socket", Handler = HandleConsoleNetClose, ParameterCombinations = { { Params = "[Port]", Help = "Closes a socket listening on the specified port [1024]", }, }, -- ParameterCombinations }, -- close ips = { HelpString = "Prints all locally available IP addresses", Handler = HandleConsoleNetIps, }, -- ips listen = { HelpString = "Creates a new listening socket on the specified port with the specified service attached to it", Handler = HandleConsoleNetListen, ParameterCombinations = { { Params = "[Port] [Service]", Help = "Starts listening on the specified port [1024] providing the specified service [echo]", }, }, -- ParameterCombinations }, -- listen lookup = { HelpString = "Looks up the IP addresses corresponding to the given hostname (google.com by default)", Handler = HandleConsoleNetLookup, ParameterCombinations = { { Params = "", Help = "Looks up the IP addresses of google.com.", }, { Params = "Hostname", Help = "Looks up the IP addresses of the specified hostname.", }, { Params = "IP", Help = "Looks up the canonical name of the specified IP.", }, }, }, -- lookup sclient = { HelpString = "Connects, as an SSL client, to a specified webpage (github.com by default) and downloads its front page using HTTPS", Handler = HandleConsoleNetSClient, ParameterCombinations = { { Params = "", Help = "Connects, as an SSL client, to github.com and downloads its front page using HTTPS", }, { Params = "host [port]", Help = "Connects, as an SSL client, to the specified host and downloads its front page using HTTPS", }, }, -- ParameterCombinations }, -- sclient udp = { Subcommands = { close = { Handler = HandleConsoleNetUdpClose, ParameterCombinations = { { Params = "[Port]", Help = "Closes the UDP endpoint on the specified port [1024].", } }, }, -- close listen = { Handler = HandleConsoleNetUdpListen, ParameterCombinations = { { Params = "[Port]", Help = "Listens on the specified UDP port [1024], dumping the incoming datagrams into log", }, }, }, -- listen send = { Handler = HandleConsoleNetUdpSend, ParameterCombinations = { { Params = "[Host] [Port] [Message]", Help = "Sends the message [\"hello\"] through UDP to the specified host [localhost] and port [1024]", }, }, } -- send }, -- Subcommands ("net udp") }, -- udp wasc = { HelpString = "Requests the webadmin homepage using https", Handler = HandleConsoleNetWasc, }, -- wasc }, -- Subcommands }, -- net }, } ================================================ FILE: Server/Plugins/NetworkTest/NetworkTest.lua ================================================ -- NetworkTest.lua -- Implements a few tests for the cNetwork API --- Map of all servers currently open -- g_Servers[PortNum] = cServerHandle local g_Servers = {} --- Map of all UDP endpoints currently open -- g_UDPEndpoints[PortNum] = cUDPEndpoint local g_UDPEndpoints = {} --- List of fortune messages for the fortune server -- A random message is chosen for each incoming connection -- The contents are loaded from the splashes.txt file on plugin startup local g_Fortunes = { "Empty splashes.txt", } -- HTTPS certificate to be used for the SSL server: local g_HTTPSCert = [[ -----BEGIN CERTIFICATE----- MIIDfzCCAmegAwIBAgIJAOBHN+qOWodcMA0GCSqGSIb3DQEBBQUAMFYxCzAJBgNV BAYTAmN6MQswCQYDVQQIDAJjejEMMAoGA1UEBwwDbG9jMQswCQYDVQQKDAJfWDEL MAkGA1UECwwCT1UxEjAQBgNVBAMMCWxvY2FsaG9zdDAeFw0xNTAxMjQwODQ2MzFa Fw0yNTAxMjEwODQ2MzFaMFYxCzAJBgNVBAYTAmN6MQswCQYDVQQIDAJjejEMMAoG A1UEBwwDbG9jMQswCQYDVQQKDAJfWDELMAkGA1UECwwCT1UxEjAQBgNVBAMMCWxv Y2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJkFYSElu/jw nxqjimmj246DejKJK8uy/l9QQibb/Z4kO/3s0gVPOYo0mKv32xUFP7wYIE3XWT61 zyfvK+1jpnlQTCtM8T5xw/7CULKgLmuIzlQx5Dhy7d+tW46kOjFKwQajS9YzwqWu KBOPnFamQWz6vIzuM05+7aIMXbzamInvW/1x3klIrpGQgALwSB1N+oUzTInTBRKK 21pecUE9t3qrU40Cs5bN0fQBnBjLwbgmnTh6LEplfQZHG5wLvj0IeERVU9vH7luM e9/IxuEZluCiu5ViF3jqLPpjYOrkX7JDSKme64CCmNIf0KkrwtFjF104Qylike60 YD3+kw8Q+DECAwEAAaNQME4wHQYDVR0OBBYEFHHIDTc7mrLDXftjQ5ejU9Udfdyo MB8GA1UdIwQYMBaAFHHIDTc7mrLDXftjQ5ejU9UdfdyoMAwGA1UdEwQFMAMBAf8w DQYJKoZIhvcNAQEFBQADggEBAHxCJxZPmH9tvx8GKiDV3rgGY++sMItzrW5Uhf0/ bl3DPbVz51CYF8nXiWvSJJzxhH61hKpZiqvRlpyMuovV415dYQ+Xc2d2IrTX6e+d Z4Pmwfb4yaX+kYqIygjXMoyNxOJyhTnCbJzycV3v5tvncBWN9Wqez6ZonWDdFdAm J+Moty+atc4afT02sUg1xz+CDr1uMbt62tHwKYCdxXCwT//bOs6W21+mQJ5bEAyA YrHQPgX76uo8ed8rPf6y8Qj//lzq/+33EIWqf9pnbklQgIPXJU07h+5L+Y63RF4A ComLkzas+qnQLcEN28Dg8QElXop6hfiD0xq3K0ac2bDnjoU= -----END CERTIFICATE----- ]] local g_HTTPSPrivKey = [[ -----BEGIN PRIVATE KEY----- MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCZBWEhJbv48J8a o4ppo9uOg3oyiSvLsv5fUEIm2/2eJDv97NIFTzmKNJir99sVBT+8GCBN11k+tc8n 7yvtY6Z5UEwrTPE+ccP+wlCyoC5riM5UMeQ4cu3frVuOpDoxSsEGo0vWM8KlrigT j5xWpkFs+ryM7jNOfu2iDF282piJ71v9cd5JSK6RkIAC8EgdTfqFM0yJ0wUSitta XnFBPbd6q1ONArOWzdH0AZwYy8G4Jp04eixKZX0GRxucC749CHhEVVPbx+5bjHvf yMbhGZbgoruVYhd46iz6Y2Dq5F+yQ0ipnuuAgpjSH9CpK8LRYxddOEMpYpHutGA9 /pMPEPgxAgMBAAECggEAWxQ4m+I54BJYoSJ2YCqHpGvdb/b1emkvvsumlDqc2mP2 0U0ENOTS+tATj0gXvotBRFOX5r0nAYx1oO9a1hFaJRsGOz+w19ofLqO6JJfzCU6E gNixXmgJ7fjhZiWZ/XzhJ3JK0VQ9px/h+sKf63NJvfQABmJBZ5dlGe8CXEZARNin 03TnE3RUIEK+jEgwShN2OrGjwK9fjcnXMHwEnKZtCBiYEfD2N+pQmS20gIm13L1t +ZmObIC24NqllXxl4I821qzBdhmcT7+rGmKR0OT5YKbt6wFA5FPKD9dqlzXzlKck r2VAh+JlCtFKxcScmWtQOnVDtf5+mcKFbP4ck724AQKBgQDLk+RDhvE5ykin5R+B dehUQZgHb2pPL7N1DAZShfzwSmyZSOPQDFr7c0CMijn6G0Pw9VX6Vrln0crfTQYz Hli+zxlmcMAD/WC6VImM1LCUzouNRy37rSCnuPtngZyHdsyzfheGnjORH7HlPjtY JCTLaekg0ckQvt//HpRV3DCdaQKBgQDAbLmIOTyGfne74HLswWnY/kCOfFt6eO+E lZ724MWmVPWkxq+9rltC2CDx2i8jjdkm90dsgR5OG2EaLnUWldUpkE0zH0ATrZSV ezJWD9SsxTm8ksbThD+pJKAVPxDAboejF7kPvpaO2wY+bf0AbO3M24rJ2tccpMv8 AcfXBICDiQKBgQCSxp81/I3hf7HgszaC7ZLDZMOK4M6CJz847aGFUCtsyAwCfGYb 8zyJvK/WZDam14+lpA0IQAzPCJg/ZVZJ9uA/OivzCum2NrHNxfOiQRrLPxuokaBa q5k2tA02tGE53fJ6mze1DEzbnkFxqeu5gd2xdzvpOLfBxgzT8KU8PlQiuQKBgGn5 NvCj/QZhDhYFVaW4G1ArLmiKamL3yYluUV7LiW7CaYp29gBzzsTwfKxVqhJdo5NH KinCrmr7vy2JGmj22a+LTkjyU/rCZQsyDxXAoDMKZ3LILwH8WocPqa4pzlL8TGzw urXGE+rXCwhE0Mp0Mz7YRgZHJKMcy06duG5dh11pAoGBALHbsBIDihgHPyp2eKMP K1f42MdKrTBiIXV80hv2OnvWVRCYvnhrqpeRMzCR1pmVbh+QhnwIMAdWq9PAVTTn ypusoEsG8Y5fx8xhgjs0D2yMcrmi0L0kCgHIFNoym+4pI+sv6GgxpemfrmaPNcMx DXi9JpaquFRJLGJ7jMCDgotL -----END PRIVATE KEY----- ]] --- Map of all services that can be run as servers -- g_Services[ServiceName] = function() -> accept-callbacks local g_Services = { -- Echo service: each connection echoes back what has been sent to it echo = function (a_Port) return { -- A new connection has come, give it new link-callbacks: OnIncomingConnection = function (a_RemoteIP, a_RemotePort) return { OnError = function (a_Link, a_ErrorCode, a_ErrorMsg) LOG("EchoServer(" .. a_Port .. ": Connection to " .. a_Link:GetRemoteIP() .. ":" .. a_Link:GetRemotePort() .. " failed: " .. a_ErrorCode .. " (" .. a_ErrorMsg .. ")") end, OnReceivedData = function (a_Link, a_Data) -- Echo the received data back to the link: a_Link:Send(a_Data) end, OnRemoteClosed = function (a_Link) end } -- Link callbacks end, -- OnIncomingConnection() -- Send a welcome message to newly accepted connections: OnAccepted = function (a_Link) a_Link:Send("Hello, " .. a_Link:GetRemoteIP() .. ", welcome to the echo server @ Cuberite-Lua\r\n") end, -- OnAccepted() -- There was an error listening on the port: OnError = function (a_ErrorCode, a_ErrorMsg) LOGINFO("EchoServer(" .. a_Port .. ": Cannot listen: " .. a_ErrorCode .. " (" .. a_ErrorMsg .. ")") end, -- OnError() } -- Listen callbacks end, -- echo -- Fortune service: each incoming connection gets a welcome message plus a random fortune text; all communication is ignored afterwards fortune = function (a_Port) return { -- A new connection has come, give it new link-callbacks: OnIncomingConnection = function (a_RemoteIP, a_RemotePort) return { OnError = function (a_Link, a_ErrorCode, a_ErrorMsg) LOG("FortuneServer(" .. a_Port .. "): Connection to " .. a_Link:GetRemoteIP() .. ":" .. a_Link:GetRemotePort() .. " failed: " .. a_ErrorCode .. " (" .. a_ErrorMsg .. ")") end, OnReceivedData = function (a_Link, a_Data) -- Ignore any received data end, OnRemoteClosed = function (a_Link) end } -- Link callbacks end, -- OnIncomingConnection() -- Send a welcome message and the fortune to newly accepted connections: OnAccepted = function (a_Link) a_Link:Send("Hello, " .. a_Link:GetRemoteIP() .. ", welcome to the fortune server @ Cuberite-Lua\r\n\r\nYour fortune:\r\n") a_Link:Send(g_Fortunes[math.random(#g_Fortunes)] .. "\r\n") end, -- OnAccepted() -- There was an error listening on the port: OnError = function (a_ErrorCode, a_ErrorMsg) LOGINFO("FortuneServer(" .. a_Port .. "): Cannot listen: " .. a_ErrorCode .. " (" .. a_ErrorMsg .. ")") end, -- OnError() } -- Listen callbacks end, -- fortune -- HTTPS time - serves current time for each https request received httpstime = function (a_Port) return { -- A new connection has come, give it new link-callbacks: OnIncomingConnection = function (a_RemoteIP, a_RemotePort) local IncomingData = "" -- accumulator for the incoming data, until processed by the http return { OnError = function (a_Link, a_ErrorCode, a_ErrorMsg) LOG("https-time server(" .. a_Port .. "): Connection to " .. a_Link:GetRemoteIP() .. ":" .. a_Link:GetRemotePort() .. " failed: " .. a_ErrorCode .. " (" .. a_ErrorMsg .. ")") end, OnReceivedData = function (a_Link, a_Data) IncomingData = IncomingData .. a_Data if (IncomingData:find("\r\n\r\n")) then -- We have received the entire request headers, just send the response and shutdown the link: local Content = os.date() a_Link:Send("HTTP/1.0 200 OK\r\nContent-type: text/plain\r\nContent-length: " .. #Content .. "\r\n\r\n" .. Content) a_Link:Shutdown() end end, OnRemoteClosed = function (a_Link) LOG("httpstime: link closed by remote") end } -- Link callbacks end, -- OnIncomingConnection() -- Start TLS on the new link: OnAccepted = function (a_Link) local res, msg = a_Link:StartTLSServer(g_HTTPSCert, g_HTTPSPrivKey, "") if not(res) then LOG("https-time server(" .. a_Port .. "): Cannot start TLS server: " .. msg) a_Link:Close() end end, -- OnAccepted() -- There was an error listening on the port: OnError = function (a_ErrorCode, a_ErrorMsg) LOGINFO("https-time server(" .. a_Port .. "): Cannot listen: " .. a_ErrorCode .. " (" .. a_ErrorMsg .. ")") end, -- OnError() } -- Listen callbacks end, -- httpstime -- TODO: Other services (daytime, ...) } function Initialize(a_Plugin) -- Load the splashes.txt file into g_Fortunes, overwriting current content: local idx = 1 for line in io.lines(a_Plugin:GetLocalFolder() .. "/splashes.txt") do g_Fortunes[idx] = line idx = idx + 1 end -- Use the InfoReg shared library to process the Info.lua file: dofile(cPluginManager:GetPluginsPath() .. "/InfoReg.lua") RegisterPluginInfoCommands() RegisterPluginInfoConsoleCommands() -- Seed the random generator: math.randomseed(os.time()) return true end function HandleConsoleNetClient(a_Split) -- Get the address to connect to: local Host = a_Split[3] or "google.com" local Port = a_Split[4] or 80 -- Create the callbacks "personalised" for the address: local Callbacks = { OnConnected = function (a_Link) LOG("Connected to " .. Host .. ":" .. Port .. ".") LOG("Connection stats: Remote address: " .. a_Link:GetRemoteIP() .. ":" .. a_Link:GetRemotePort() .. ", Local address: " .. a_Link:GetLocalIP() .. ":" .. a_Link:GetLocalPort()) LOG("Sending HTTP request for front page.") a_Link:Send("GET / HTTP/1.0\r\nHost: " .. Host .. "\r\n\r\n") end, OnError = function (a_Link, a_ErrorCode, a_ErrorMsg) LOG("Connection to " .. Host .. ":" .. Port .. " failed: " .. a_ErrorCode .. " (" .. a_ErrorMsg .. ")") end, OnReceivedData = function (a_Link, a_Data) LOG("Received data from " .. Host .. ":" .. Port .. ":\r\n" .. a_Data) end, OnRemoteClosed = function (a_Link) LOG("Connection to " .. Host .. ":" .. Port .. " was closed by the remote peer.") end } -- Queue a connect request: local res = cNetwork:Connect(Host, Port, Callbacks) if not(res) then LOGWARNING("cNetwork:Connect call failed immediately") return true end return true, "Client connection request queued." end function HandleConsoleNetClose(a_Split) -- Get the port to close: local Port = tonumber(a_Split[3] or 1024) if not(Port) then return true, "Bad port number: \"" .. a_Split[3] .. "\"." end -- Close the server, if there is one: if not(g_Servers[Port]) then return true, "There is no server currently listening on port " .. Port .. "." end g_Servers[Port]:Close() g_Servers[Port] = nil return true, "Port " .. Port .. " closed." end function HandleConsoleNetIps(a_Split) local Addresses = cNetwork:EnumLocalIPAddresses() LOG("IP addresses enumerated, " .. #Addresses .. " found") for idx, addr in ipairs(Addresses) do LOG(" IP #" .. idx .. ": " .. addr) end return true end function HandleConsoleNetLookup(a_Split) -- Get the name to look up: local Addr = a_Split[3] or "google.com" -- Create the callbacks "personalised" for the host: local Callbacks = { OnNameResolved = function (a_Hostname, a_IP) LOG(a_Hostname .. " resolves to " .. a_IP) end, OnError = function (a_Query, a_ErrorCode, a_ErrorMsg) LOG("Failed to retrieve information for " .. a_Query .. ": " .. a_ErrorCode .. " (" .. a_ErrorMsg .. ")") assert(a_Query == Addr) end, OnFinished = function (a_Query) LOG("Resolving " .. a_Query .. " has finished.") assert(a_Query == Addr) end, } -- Queue both name and IP DNS queries; -- we don't distinguish between an IP and a hostname in this command so we don't know which one to use: local res = cNetwork:HostnameToIP(Addr, Callbacks) if not(res) then LOGWARNING("cNetwork:HostnameToIP call failed immediately") return true end res = cNetwork:IPToHostname(Addr, Callbacks) if not(res) then LOGWARNING("cNetwork:IPToHostname call failed immediately") return true end return true, "DNS query has been queued." end function HandleConsoleNetListen(a_Split) -- Get the params: local Port = tonumber(a_Split[3] or 1024) if not(Port) then return true, "Invalid port: \"" .. a_Split[3] .. "\"." end local Service = string.lower(a_Split[4] or "echo") -- Create the callbacks specific for the service: if (g_Services[Service] == nil) then return true, "No such service: " .. Service end local Callbacks = g_Services[Service](Port) -- Start the server: local srv = cNetwork:Listen(Port, Callbacks) if not(srv:IsListening()) then -- The error message has already been printed in the Callbacks.OnError() return true end g_Servers[Port] = srv return true, Service .. " server started on port " .. Port end function HandleConsoleNetSClient(a_Split) -- Get the address to connect to: local Host = a_Split[3] or "github.com" local Port = a_Split[4] or 443 -- Create the callbacks "personalised" for the address: local Callbacks = { OnConnected = function (a_Link) LOG("Connected to " .. Host .. ":" .. Port .. ".") LOG("Connection stats: Remote address: " .. a_Link:GetRemoteIP() .. ":" .. a_Link:GetRemotePort() .. ", Local address: " .. a_Link:GetLocalIP() .. ":" .. a_Link:GetLocalPort()) LOG("Sending HTTP request for front page.") a_Link:StartTLSClient() a_Link:Send("GET / HTTP/1.0\r\nHost: " .. Host .. "\r\n\r\n") end, OnError = function (a_Link, a_ErrorCode, a_ErrorMsg) LOG("Connection to " .. Host .. ":" .. Port .. " failed: " .. a_ErrorCode .. " (" .. a_ErrorMsg .. ")") end, OnReceivedData = function (a_Link, a_Data) LOG("Received data from " .. Host .. ":" .. Port .. ":\r\n" .. a_Data) end, OnRemoteClosed = function (a_Link) LOG("Connection to " .. Host .. ":" .. Port .. " was closed by the remote peer.") end } -- Queue a connect request: local res = cNetwork:Connect(Host, Port, Callbacks) if not(res) then LOGWARNING("cNetwork:Connect call failed immediately") return true end return true, "SSL Client connection request queued." end function HandleConsoleNetUdpClose(a_Split) -- Get the port to close: local Port = tonumber(a_Split[4] or 1024) if not(Port) then return true, "Bad port number: \"" .. a_Split[4] .. "\"." end -- Close the server, if there is one: if not(g_UDPEndpoints[Port]) then return true, "There is no UDP endpoint currently listening on port " .. Port .. "." end g_UDPEndpoints[Port]:Close() g_UDPEndpoints[Port] = nil return true, "UDP Port " .. Port .. " closed." end function HandleConsoleNetUdpListen(a_Split) -- Get the params: local Port = tonumber(a_Split[4] or 1024) if not(Port) then return true, "Invalid port: \"" .. a_Split[4] .. "\"." end local Callbacks = { OnReceivedData = function (a_Endpoint, a_Data, a_RemotePeer, a_RemotePort) LOG("Incoming UDP datagram from " .. a_RemotePeer .. " port " .. a_RemotePort .. ":\r\n" .. a_Data) end, OnError = function (a_Endpoint, a_ErrorCode, a_ErrorMsg) LOG("Error in UDP endpoint: " .. a_ErrorCode .. " (" .. a_ErrorMsg .. ")") end, } g_UDPEndpoints[Port] = cNetwork:CreateUDPEndpoint(Port, Callbacks) return true, "UDP listener on port " .. Port .. " started." end function HandleConsoleNetUdpSend(a_Split) -- Get the params: local Host = a_Split[4] or "localhost" local Port = tonumber(a_Split[5] or 1024) if not(Port) then return true, "Invalid port: \"" .. a_Split[5] .. "\"." end local Message if (a_Split[6]) then Message = table.concat(a_Split, " ", 6) else Message = "hello" end -- Define minimum callbacks for the UDP endpoint: local Callbacks = { OnError = function (a_Endpoint, a_ErrorCode, a_ErrorMsg) LOG("Error in UDP datagram sending: " .. a_ErrorCode .. " (" .. a_ErrorMsg .. ")") end, OnReceivedData = function () -- ignore end, } -- Send the data: local Endpoint = cNetwork:CreateUDPEndpoint(0, Callbacks) Endpoint:EnableBroadcasts() if not(Endpoint:Send(Message, Host, Port)) then Endpoint:Close() return true, "Sending UDP datagram failed" end Endpoint:Close() return true, "UDP datagram sent" end function HandleConsoleNetWasc(a_Split) local Callbacks = { OnConnected = function (a_Link) LOG("Connected to webadmin, starting TLS...") local res, msg = a_Link:StartTLSClient("", "", "") if not(res) then LOG("Failed to start TLS client: " .. msg) return end -- We need to send a keep-alive due to #1737 a_Link:Send("GET / HTTP/1.0\r\nHost: localhost\r\nConnection: keep-alive\r\n\r\n") end, OnError = function (a_Link, a_ErrorCode, a_ErrorMsg) LOG("Connection to webadmin failed: " .. a_ErrorCode .. " (" .. a_ErrorMsg .. ")") end, OnReceivedData = function (a_Link, a_Data) LOG("Received data from webadmin:\r\n" .. a_Data) -- Close the link once all the data is received: if (a_Data == "0\r\n\r\n") then -- Poor man's end-of-data detection; works on localhost -- TODO: The Close() method is not yet exported to Lua -- a_Link:Close() end end, OnRemoteClosed = function (a_Link) LOG("Connection to webadmin was closed") end, } if not(cNetwork:Connect("localhost", "8080", Callbacks)) then LOG("Canot connect to webadmin") end return true end ================================================ FILE: Server/Plugins/NetworkTest/splashes.txt ================================================ As seen on TV! Awesome! 100% pure! May contain nuts! Better than Prey! More polygons! Sexy! Limited edition! Flashing letters! Made by Notch! It's here! Best in class! It's finished! Kind of dragon free! Excitement! More than 500 sold! One of a kind! Heaps of hits on YouTube! Indev! Spiders everywhere! Check it out! Holy cow, man! It's a game! Made in Sweden! Uses LWJGL! Reticulating splines! Minecraft! Yaaay! Singleplayer! Keyboard compatible! Undocumented! Ingots! Exploding creepers! That's no moon! l33t! Create! Survive! Dungeon! Exclusive! The bee's knees! Down with O.P.P.! Closed source! Classy! Wow! Not on steam! Oh man! Awesome community! Pixels! Teetsuuuuoooo! Kaaneeeedaaaa! Now with difficulty! Enhanced! 90% bug free! Pretty! 12 herbs and spices! Fat free! Absolutely no memes! Free dental! Ask your doctor! Minors welcome! Cloud computing! Legal in Finland! Hard to label! Technically good! Bringing home the bacon! Indie! GOTY! Ceci n'est pas une title screen! Euclidian! Now in 3D! Inspirational! Herregud! Complex cellular automata! Yes, sir! Played by cowboys! OpenGL 2.1 (if supported)! Thousands of colors! Try it! Age of Wonders is better! Try the mushroom stew! Sensational! Hot tamale, hot hot tamale! Play him off, keyboard cat! Guaranteed! Macroscopic! Bring it on! Random splash! Call your mother! Monster infighting! Loved by millions! Ultimate edition! Freaky! You've got a brand new key! Water proof! Uninflammable! Whoa, dude! All inclusive! Tell your friends! NP is not in P! Notch <3 ez! Music by C418! Livestreamed! Haunted! Polynomial! Terrestrial! All is full of love! Full of stars! Scientific! Cooler than Spock! Collaborate and listen! Never dig down! Take frequent breaks! Not linear! Han shot first! Nice to meet you! Buckets of lava! Ride the pig! Larger than Earth! sqrt(-1) love you! Phobos anomaly! Punching wood! Falling off cliffs! 0% sugar! 150% hyperbole! Synecdoche! Let's danec! Seecret Friday update! Reference implementation! Lewd with two dudes with food! Kiss the sky! 20 GOTO 10! Verlet intregration! Peter Griffin! Do not distribute! Cogito ergo sum! 4815162342 lines of code! A skeleton popped out! The Work of Notch! The sum of its parts! BTAF used to be good! I miss ADOM! umop-apisdn! OICU812! Bring me Ray Cokes! Finger-licking! Thematic! Pneumatic! Sublime! Octagonal! Une baguette! Gargamel plays it! Rita is the new top dog! SWM forever! Representing Edsbyn! Matt Damon! Supercalifragilisticexpialidocious! Consummate V's! Cow Tools! Double buffered! Fan fiction! Flaxkikare! Jason! Jason! Jason! Hotter than the sun! Internet enabled! Autonomous! Engage! Fantasy! DRR! DRR! DRR! Kick it root down! Regional resources! Woo, facepunch! Woo, somethingawful! Woo, /v/! Woo, tigsource! Woo, minecraftforum! Woo, worldofminecraft! Woo, reddit! Woo, 2pp! Google anlyticsed! Now supports åäö! Give us Gordon! Tip your waiter! Very fun! 12345 is a bad password! Vote for net neutrality! Lives in a pineapple under the sea! MAP11 has two names! Omnipotent! Gasp! ...! Bees, bees, bees, bees! Jag känner en bot! This text is hard to read if you play the game at the default resolution, but at 1080p it's fine! Haha, LOL! Hampsterdance! Switches and ores! Menger sponge! idspispopd! Eple (original edit)! So fresh, so clean! Slow acting portals! Try the Nether! Don't look directly at the bugs! Oh, ok, Pigmen! Finally with ladders! Scary! Play Minecraft, Watch Topgear, Get Pig! Twittered about! Jump up, jump up, and get down! Joel is neat! A riddle, wrapped in a mystery! Huge tracts of land! Welcome to your Doom! Stay a while, stay forever! Stay a while and listen! Treatment for your rash! "Autological" is! Information wants to be free! "Almost never" is an interesting concept! Lots of truthiness! The creeper is a spy! Turing complete! It's groundbreaking! Let our battle's begin! The sky is the limit! Jeb has amazing hair! Ryan also has amazing hair! Casual gaming! Undefeated! Kinda like Lemmings! Follow the train, CJ! Leveraging synergy! This message will never appear on the splash screen, isn't that weird? DungeonQuest is unfair! 110813! 90210! Check out the far lands! Tyrion would love it! Also try VVVVVV! Also try Super Meat Boy! Also try Terraria! Also try Mount And Blade! Also try Project Zomboid! Also try World of Goo! Also try Limbo! Also try Pixeljunk Shooter! Also try Braid! That's super! Bread is pain! Read more books! Khaaaaaaaaan! Less addictive than TV Tropes! More addictive than lemonade! Bigger than a bread box! Millions of peaches! Fnord! This is my true form! Totally forgot about Dre! Don't bother with the clones! Pumpkinhead! Hobo humping slobo babe! Made by Jeb! Has an ending! Finally complete! Feature packed! Boots with the fur! Stop, hammertime! Testificates! Conventional! Homeomorphic to a 3-sphere! Doesn't avoid double negatives! Place ALL the blocks! Does barrel rolls! Meeting expectations! PC gaming since 1873! Ghoughpteighbteau tchoghs! Déjà vu! Déjà vu! Got your nose! Haley loves Elan! Afraid of the big, black bat! Doesn't use the U-word! Child's play! See you next Friday or so! From the streets of Södermalm! 150 bpm for 400000 minutes! Technologic! Funk soul brother! Pumpa kungen! 日本ハロー! 한국 안녕하세요! Helo Cymru! Cześć Polsko! 你好中国! Привет Россия! Γεια σου Ελλάδα! My life for Aiur! Lennart lennart = new Lennart(); I see your vocabulary has improved! Who put it there? You can't explain that! if not ok then return end §1C§2o§3l§4o§5r§6m§7a§8t§9i§ac §kFUNKY LOL SOPA means LOSER in Swedish! Big Pointy Teeth! Bekarton guards the gate! Mmmph, mmph! Don't feed avocados to parrots! Swords for everyone! Plz reply to my tweet! .party()! Take her pillow! Put that cookie down! Pretty scary! I have a suggestion. Now with extra hugs! Now Java 6! Woah. HURNERJSGER? What's up, Doc? Now contains 32 random daily cats! That's Numberwang! pls rt Do you want to join my server? Put a little fence around it! Throw a blanket over it! One day, somewhere in the future, my work will be quoted! Now with additional stuff! Extra things! Yay, puppies for everyone! So sweet, like a nice bon bon! Popping tags! Very influential in its circle! Now With Multiplayer! Rise from your grave! Warning! A huge battleship "STEVE" is approaching fast! Blue warrior shot the food! Run, coward! I hunger! Flavor with no seasoning! Strange, but not a stranger! Tougher than diamonds, rich like cream! Getting ready to show! Getting ready to know! Getting ready to drop! Getting ready to shock! Getting ready to freak! Getting ready to speak! It swings, it jives! Cruising streets for gold! Take an eggbeater and beat it against a skillet! Make me a table, a funky table! Take the elevator to the mezzanine! Stop being reasonable, this is the Internet! /give @a hugs 64 This is good for Realms. Any computer is a laptop if you're brave enough! ================================================ FILE: Server/Plugins/TestLuaRocks/TestLuaRocks.lua ================================================ -- TestLuaRocks.lua -- This is a mockup plugin that does a quick test of LuaRocks capability in Cuberite -- "Success" is when the plugin loads, downloads the forum webpage and displays the headers and length and then displays both libs as loaded. -- "Failure" usually manifests as one of the "require" lines failing, although you have the luarock installed. -- Note that the plugin deliberately never fully loads, so that it can be reloaded fast by pressing its Enable button in the webadmin's plugin list. local log30 = require("30log"); local socket = require("socket"); local http = require("socket.http"); LOGINFO("Trying to download a webpage...") local body, code, headers = http.request('https://forum.cuberite.org/') LOG("code: " .. tostring(code)) LOG("headers: ") for k, v in pairs(headers or {}) do LOG(" " .. k .. ": " .. v) end LOG("body length: " .. string.len(body)) function Initialize(a_Plugin) if (socket == nil) then LOGWARNING("LuaSocket not found") else LOG("LuaSocket loaded") end if (log30 == nil) then LOGWARNING("30log not found") else LOG("30log loaded") end LOGINFO("Reload plugin from console or webadmin to rerun tests.") return false end ================================================ FILE: Server/Prefabs/PieceStructures/NetherFort.cubeset ================================================ -- NetherFort.cubeset -- Defines the prefabs in the group NetherFort -- NOTE: This file has been generated automatically by GalExport! -- Any manual changes will be overwritten by the next automatic export! Cubeset = { Metadata = { CubesetFormatVersion = 1, ExportDate = "2016-11-30 13:45:43", ["GridSizeX"] = "512", ["GridSizeZ"] = "512", ["IntendedUse"] = "PieceStructures", ["MaxDepth"] = "12", ["MaxOffsetX"] = "128", ["MaxOffsetZ"] = "128", ["MaxStructureSizeX"] = "384", ["MaxStructureSizeZ"] = "384", }, Pieces = { { OriginData = { ExportName = "BridgeFunnelDown", Name = "Nether 0", GalleryName = "Nether", GalleryIndex = "0", ID = "2", CreatorName = "Aloe_vera", }, Size = { x = 15, y = 12, z = 12, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 14, MaxY = 21, MaxZ = 11, }, Connectors = { { Type = 0, RelX = 7, RelY = 4, RelZ = 11, Direction = 3, -- Z+ }, { Type = 0, RelX = 0, RelY = 9, RelZ = 2, Direction = 4, -- X- }, { Type = 0, RelX = 14, RelY = 9, RelZ = 2, Direction = 5, -- X+ }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "5", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a:112: 0", -- netherbrickblock "b:114: 6", -- netherbrickstairs "c:114: 4", -- netherbrickstairs "d:114: 5", -- netherbrickstairs "e: 44:14", -- stone_slab "f:114: 7", -- netherbrickstairs "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "mmmmmmmmmmmmmmm", -- 0 "aammmmmmmmmmmaa", -- 1 "aammmmmmmmmmmaa", -- 2 "aammmmmmmmmmmaa", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmmmmmmmmm", -- 5 "mmmmmmmmmmmmmmm", -- 6 "mmmmmmmmmmmmmmm", -- 7 "mmmmmmmmmmmmmmm", -- 8 "mmmmmmaaammmmmm", -- 9 "mmmmmmaaammmmmm", -- 10 "mmmmmmaaammmmmm", -- 11 -- Level 1 "mmmmmmmmmmmmmmm", -- 0 "aammmmmmmmmmmaa", -- 1 "aammmmmmmmmmmaa", -- 2 "aammmmmmmmmmmaa", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmmmmmmmmm", -- 5 "mmmmmmmmmmmmmmm", -- 6 "mmmmmmmmmmmmmmm", -- 7 "mmmmmmbbbmmmmmm", -- 8 "mmmmmmaaammmmmm", -- 9 "mmmmmmaaammmmmm", -- 10 "mmmmmmaaammmmmm", -- 11 -- Level 2 "mmmmmmmmmmmmmmm", -- 0 "aammmmmmmmmmmaa", -- 1 "aammmmmmmmmmmaa", -- 2 "aammmmmmmmmmmaa", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmmmmmmmmm", -- 5 "mmmmmmmmmmmmmmm", -- 6 "mmmmmcbbbdmmmmm", -- 7 "mmmmmcaaadmmmmm", -- 8 "mmmmmcaaadmmmmm", -- 9 "mmmmmcaaadmmmmm", -- 10 "mmmmmcaaadmmmmm", -- 11 -- Level 3 "mmmmmmmmmmmmmmm", -- 0 "aammmmmmmmmmmaa", -- 1 "aammmmmmmmmmmaa", -- 2 "aammmmmmmmmmmaa", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmmmmmmmmm", -- 5 "mmmmmmmmmmmmmmm", -- 6 "mmmmmaaaaammmmm", -- 7 "mmmmmaaaaammmmm", -- 8 "mmmmmaaaaammmmm", -- 9 "mmmmmaaaaammmmm", -- 10 "mmmmmaaaaammmmm", -- 11 -- Level 4 "mmmmmmmmmmmmmmm", -- 0 "aammmmmmmmmmmaa", -- 1 "aammmmmmmmmmmaa", -- 2 "aammmmmmmmmmmaa", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmmmmmmmmm", -- 5 "mmmmcbbbbbdmmmm", -- 6 "mmmmaaaaaaammmm", -- 7 "mmmma.....ammmm", -- 8 "mmmmaa...aammmm", -- 9 "mmmmma...ammmmm", -- 10 "mmmmma...ammmmm", -- 11 -- Level 5 "mmmmmmmmmmmmmmm", -- 0 "aadmmmmmmmmmcaa", -- 1 "aadmmmmmmmmmcaa", -- 2 "aadmmmmmmmmmcaa", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmcbbbbbbbdmmm", -- 5 "mmmaaaaaaaaaamm", -- 6 "mmma.......ammm", -- 7 "mmmaa.....aammm", -- 8 "mmmmam...mammmm", -- 9 "mmmmmm...mmmmmm", -- 10 "mmmmmm...mmmmmm", -- 11 -- Level 6 "mmmmmmmmmmmmmmm", -- 0 "aaademmmmmecaaa", -- 1 "aaademmmmmecaaa", -- 2 "aaademmmmmecaaa", -- 3 "mmaaabbbbbaaaam", -- 4 "mmaaaaaaaaaaaam", -- 5 "mma.........amm", -- 6 "mmaa.......aamm", -- 7 "mmmam.....mammm", -- 8 "mmmmmm...mmmmmm", -- 9 "mmmmmm...mmmmmm", -- 10 "mmmmmm...mmmmmm", -- 11 -- Level 7 "bbbbbbbbbbbbbbb", -- 0 "aaaaaaaaaaaaaaa", -- 1 "aaaaaaaaaaaaaaa", -- 2 "aaaaaaaaaaaaaaa", -- 3 "faaaaaaaaaaaaaa", -- 4 "ma...........am", -- 5 "maa.........aam", -- 6 "mmam.......mamm", -- 7 "mmmmm.....mmmmm", -- 8 "mmmmmmmmmmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 -- Level 8 "aaaaaaaaaaaaaaa", -- 0 "aaaaaaaaaaaaaaa", -- 1 "aaaaaaaaaaaaaaa", -- 2 "aaaaaaaaaaaaaaa", -- 3 "a.............a", -- 4 "aa...........aa", -- 5 "mam.........mam", -- 6 "mmmm.......mmmm", -- 7 "mmmmmmmmmmmmmmm", -- 8 "mmmmmmmmmmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 -- Level 9 "aaaaaaaaaaaaaaa", -- 0 "...............", -- 1 "...............", -- 2 "...............", -- 3 "a.............a", -- 4 "am............a", -- 5 "mmm.........mmm", -- 6 "mmmmmmmmmmmmmmm", -- 7 "mmmmmmmmmmmmmmm", -- 8 "mmmmmmmmmmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 -- Level 10 "mmmmmmmmmmmmmmm", -- 0 "...............", -- 1 "...............", -- 2 "...............", -- 3 "m.............m", -- 4 "mm............m", -- 5 "mmmmmmmmmmmmmmm", -- 6 "mmmmmmmmmmmmmmm", -- 7 "mmmmmmmmmmmmmmm", -- 8 "mmmmmmmmmmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 -- Level 11 "mmmmmmmmmmmmmmm", -- 0 "...............", -- 1 "...............", -- 2 "...............", -- 3 "m.............m", -- 4 "mmmmmmmmmmmmmmm", -- 5 "mmmmmmmmmmmmmmm", -- 6 "mmmmmmmmmmmmmmm", -- 7 "mmmmmmmmmmmmmmm", -- 8 "mmmmmmmmmmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 }, }, -- BridgeFunnelDown { OriginData = { ExportName = "DarkCorridor", Name = "Nether 3", GalleryName = "Nether", GalleryIndex = "3", ID = "30", CreatorName = "STR_Warrior", }, Size = { x = 14, y = 6, z = 5, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 13, MaxY = 5, MaxZ = 4, }, Connectors = { { Type = 1, RelX = 0, RelY = 1, RelZ = 2, Direction = 4, -- X- }, { Type = 1, RelX = 13, RelY = 1, RelZ = 2, Direction = 5, -- X+ }, { Type = -1, RelX = 0, RelY = 1, RelZ = 2, Direction = 4, -- X- }, { Type = -1, RelX = 13, RelY = 1, RelZ = 2, Direction = 5, -- X+ }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a:112: 0", -- netherbrickblock "b:113: 0", -- netherbrickfence "c:114: 2", -- netherbrickstairs "d:114: 3", -- netherbrickstairs "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "aaaaaaaaaaaaaa", -- 0 "aaaaaaaaaaaaaa", -- 1 "aaaaaaaaaaaaaa", -- 2 "aaaaaaaaaaaaaa", -- 3 "aaaaaaaaaaaaaa", -- 4 -- Level 1 "aaaaaaaaaaaaaa", -- 0 "..............", -- 1 "..............", -- 2 "..............", -- 3 "aaaaaaaaaaaaaa", -- 4 -- Level 2 "aabaaaaaaaabaa", -- 0 "..............", -- 1 "..............", -- 2 "..............", -- 3 "aabaaaaaaaabaa", -- 4 -- Level 3 "aabaaaaaaaabaa", -- 0 "..............", -- 1 "..............", -- 2 "..............", -- 3 "aabaaaaaaaabaa", -- 4 -- Level 4 "aabaaaaaaaabaa", -- 0 "..............", -- 1 "..............", -- 2 "..............", -- 3 "aabaaaaaaaabaa", -- 4 -- Level 5 "cccccccccccccc", -- 0 "aaaaaaaaaaaaaa", -- 1 "aaaaaaaaaaaaaa", -- 2 "aaaaaaaaaaaaaa", -- 3 "dddddddddddddd", -- 4 }, }, -- DarkCorridor { OriginData = { ExportName = "Turret", Name = "Nether 7", GalleryName = "Nether", GalleryIndex = "7", ID = "34", CreatorName = "xoft", }, Size = { x = 7, y = 7, z = 7, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 6, MaxY = 16, MaxZ = 6, }, Connectors = { { Type = 0, RelX = 0, RelY = 1, RelZ = 3, Direction = 4, -- X- }, { Type = 0, RelX = 3, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, { Type = 0, RelX = 6, RelY = 1, RelZ = 3, Direction = 5, -- X+ }, { Type = 0, RelX = 3, RelY = 1, RelZ = 6, Direction = 3, -- Z+ }, }, Metadata = { ["AddWeightIfSame"] = "-99", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a:112: 0", -- netherbrickblock "b:113: 0", -- netherbrickfence "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "aaaaaaa", -- 0 "aaaaaaa", -- 1 "aaaaaaa", -- 2 "aaaaaaa", -- 3 "aaaaaaa", -- 4 "aaaaaaa", -- 5 "aaaaaaa", -- 6 -- Level 1 "aa...aa", -- 0 "a.....a", -- 1 ".......", -- 2 ".......", -- 3 ".......", -- 4 "a.....a", -- 5 "aa...aa", -- 6 -- Level 2 "aa...aa", -- 0 "a.....a", -- 1 ".......", -- 2 ".......", -- 3 ".......", -- 4 "a.....a", -- 5 "aa...aa", -- 6 -- Level 3 "aa...aa", -- 0 "a.....a", -- 1 ".......", -- 2 ".......", -- 3 ".......", -- 4 "a.....a", -- 5 "aa...aa", -- 6 -- Level 4 "aabbbaa", -- 0 "a.....a", -- 1 "b.....b", -- 2 "b.....b", -- 3 "b.....b", -- 4 "a.....a", -- 5 "aabbbaa", -- 6 -- Level 5 "aaaaaaa", -- 0 "a.....a", -- 1 "a.....a", -- 2 "a.....a", -- 3 "a.....a", -- 4 "a.....a", -- 5 "aaaaaaa", -- 6 -- Level 6 ".......", -- 0 ".......", -- 1 ".......", -- 2 ".......", -- 3 ".......", -- 4 ".......", -- 5 ".......", -- 6 }, }, -- Turret { OriginData = { ExportName = "StairsToOpen2", Name = "Nether 8", GalleryName = "Nether", GalleryIndex = "8", ID = "35", CreatorName = "xoft", }, Size = { x = 7, y = 10, z = 7, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 6, MaxY = 19, MaxZ = 6, }, Connectors = { { Type = 0, RelX = 0, RelY = 7, RelZ = 3, Direction = 4, -- X- }, { Type = 0, RelX = 3, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "1:0|3:0|5:0|7:0|9:0|11:0|13:0|15:0", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a:112: 0", -- netherbrickblock "b:113: 0", -- netherbrickfence "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "aaaaaaa", -- 0 "aaaaaaa", -- 1 "aaaaaaa", -- 2 "aaaaaaa", -- 3 "aaaaaaa", -- 4 "aaaaaaa", -- 5 "aaaaaaa", -- 6 -- Level 1 "aa...aa", -- 0 "a.....a", -- 1 "a.....a", -- 2 "a.....a", -- 3 "a.....a", -- 4 "aaaaaaa", -- 5 "aaaaaaa", -- 6 -- Level 2 "aa...aa", -- 0 "a.....a", -- 1 "b.....b", -- 2 "a.....a", -- 3 "b.....b", -- 4 "a.aaaaa", -- 5 "aabaaba", -- 6 -- Level 3 "aa...aa", -- 0 "a.....a", -- 1 "b.....b", -- 2 "a.....a", -- 3 "b.....b", -- 4 "a..aaaa", -- 5 "aabaaba", -- 6 -- Level 4 "aabbbaa", -- 0 "a.....a", -- 1 "b.....b", -- 2 "a.....a", -- 3 "b.....b", -- 4 "a...aaa", -- 5 "aabaaba", -- 6 -- Level 5 "aaaaaaa", -- 0 "a.....a", -- 1 "a.....a", -- 2 "a.....a", -- 3 "a.....a", -- 4 "a....aa", -- 5 "aaaaaaa", -- 6 -- Level 6 "aaaaaaa", -- 0 "aaaaaaa", -- 1 "aaaaaaa", -- 2 "aaaaaaa", -- 3 "aaaaaaa", -- 4 "a.....a", -- 5 "aaaaaaa", -- 6 -- Level 7 "aaaaaaa", -- 0 "a.....a", -- 1 "......a", -- 2 "......a", -- 3 "......a", -- 4 "a.....a", -- 5 "aaaaaaa", -- 6 -- Level 8 "mmmmmmm", -- 0 "m.....m", -- 1 "......m", -- 2 "......m", -- 3 "......m", -- 4 "m.....m", -- 5 "mmmmmmm", -- 6 -- Level 9 "mmmmmmm", -- 0 "m.....m", -- 1 "......m", -- 2 "......m", -- 3 "......m", -- 4 "m.....m", -- 5 "mmmmmmm", -- 6 }, }, -- StairsToOpen2 { OriginData = { ExportName = "CorridorCorner5", Name = "Nether 10", GalleryName = "Nether", GalleryIndex = "10", ID = "40", CreatorName = "xoft", }, Size = { x = 11, y = 6, z = 11, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 10, MaxY = 5, MaxZ = 10, }, Connectors = { { Type = 1, RelX = 2, RelY = 1, RelZ = 10, Direction = 3, -- Z+ }, { Type = 1, RelX = 10, RelY = 1, RelZ = 2, Direction = 5, -- X+ }, { Type = -1, RelX = 2, RelY = 1, RelZ = 10, Direction = 3, -- Z+ }, { Type = -1, RelX = 10, RelY = 1, RelZ = 2, Direction = 5, -- X+ }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a:112: 0", -- netherbrickblock "b:113: 0", -- netherbrickfence "c:114: 2", -- netherbrickstairs "d:114: 0", -- netherbrickstairs "e:114: 3", -- netherbrickstairs "f:114: 1", -- netherbrickstairs "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "aaaaaaaaaaa", -- 0 "aaaaaaaaaaa", -- 1 "aaaaaaaaaaa", -- 2 "aaaaaaaaaaa", -- 3 "aaaaaaaaaaa", -- 4 "aaaaammmmmm", -- 5 "aaaaammmmmm", -- 6 "aaaaammmmmm", -- 7 "aaaaammmmmm", -- 8 "aaaaammmmmm", -- 9 "aaaaammmmmm", -- 10 -- Level 1 "aaaaaaaaaaa", -- 0 "a..........", -- 1 "a..........", -- 2 "a..........", -- 3 "a...aaaaaaa", -- 4 "a...ammmmmm", -- 5 "a...ammmmmm", -- 6 "a...ammmmmm", -- 7 "a...ammmmmm", -- 8 "a...ammmmmm", -- 9 "a...ammmmmm", -- 10 -- Level 2 "abababababa", -- 0 "b..........", -- 1 "a..........", -- 2 "b..........", -- 3 "a...abababa", -- 4 "b...bmmmmmm", -- 5 "a...ammmmmm", -- 6 "b...bmmmmmm", -- 7 "a...ammmmmm", -- 8 "b...bmmmmmm", -- 9 "a...ammmmmm", -- 10 -- Level 3 "abababababa", -- 0 "b..........", -- 1 "a..........", -- 2 "b..........", -- 3 "a...abababa", -- 4 "b...bmmmmmm", -- 5 "a...ammmmmm", -- 6 "b...bmmmmmm", -- 7 "a...ammmmmm", -- 8 "b...bmmmmmm", -- 9 "a...ammmmmm", -- 10 -- Level 4 "abababababa", -- 0 "b..........", -- 1 "a..........", -- 2 "b..........", -- 3 "a...abababa", -- 4 "b...bmmmmmm", -- 5 "a...ammmmmm", -- 6 "b...bmmmmmm", -- 7 "a...ammmmmm", -- 8 "b...bmmmmmm", -- 9 "a...ammmmmm", -- 10 -- Level 5 "ccccccccccc", -- 0 "daaaaaaaaaa", -- 1 "daaaaaaaaaa", -- 2 "daaaaaaaaaa", -- 3 "daaaeeeeeee", -- 4 "daaafmmmmmm", -- 5 "daaafmmmmmm", -- 6 "daaafmmmmmm", -- 7 "daaafmmmmmm", -- 8 "daaafmmmmmm", -- 9 "daaafmmmmmm", -- 10 }, }, -- CorridorCorner5 { OriginData = { ExportName = "CorridorStairs", Name = "Nether 12", GalleryName = "Nether", GalleryIndex = "12", ID = "42", CreatorName = "xoft", }, Size = { x = 9, y = 13, z = 5, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 8, MaxY = 12, MaxZ = 4, }, Connectors = { { Type = 1, RelX = 0, RelY = 1, RelZ = 2, Direction = 4, -- X- }, { Type = 1, RelX = 8, RelY = 8, RelZ = 2, Direction = 5, -- X+ }, { Type = -1, RelX = 0, RelY = 1, RelZ = 2, Direction = 4, -- X- }, { Type = -1, RelX = 8, RelY = 8, RelZ = 2, Direction = 5, -- X+ }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "1000", ["DepthWeight"] = "0:0|2:0|4:0|6:0|8:0|10:0|12:0|14:0|16:0|18:0", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a:112: 0", -- netherbrickblock "b:114: 0", -- netherbrickstairs "c:113: 0", -- netherbrickfence "d:114: 2", -- netherbrickstairs "e:114: 3", -- netherbrickstairs "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "aaaaaaaaa", -- 0 "aaaaaaaaa", -- 1 "aaaaaaaaa", -- 2 "aaaaaaaaa", -- 3 "aaaaaaaaa", -- 4 -- Level 1 "aaaaaaaaa", -- 0 ".baaaaaaa", -- 1 ".baaaaaaa", -- 2 ".baaaaaaa", -- 3 "aaaaaaaaa", -- 4 -- Level 2 "acaaaaaaa", -- 0 "..baaaaaa", -- 1 "..baaaaaa", -- 2 "..baaaaaa", -- 3 "acaaaaaaa", -- 4 -- Level 3 "acaaaaaaa", -- 0 "...baaaaa", -- 1 "...baaaaa", -- 2 "...baaaaa", -- 3 "acaaaaaaa", -- 4 -- Level 4 "acacaaaaa", -- 0 "....baaaa", -- 1 "....baaaa", -- 2 "....baaaa", -- 3 "acacaaaaa", -- 4 -- Level 5 "aaacaaaaa", -- 0 ".....baaa", -- 1 ".....baaa", -- 2 ".....baaa", -- 3 "aaacaaaaa", -- 4 -- Level 6 "daacacaaa", -- 0 "a.....baa", -- 1 "a.....baa", -- 2 "a.....baa", -- 3 "eaacacaaa", -- 4 -- Level 7 "mdaaacaaa", -- 0 "ma.....ba", -- 1 "ma.....ba", -- 2 "ma.....ba", -- 3 "meaaacaaa", -- 4 -- Level 8 "mmdaacaca", -- 0 "mma......", -- 1 "mma......", -- 2 "mma......", -- 3 "mmeaacaca", -- 4 -- Level 9 "mmmdaaaca", -- 0 "mmma.....", -- 1 "mmma.....", -- 2 "mmma.....", -- 3 "mmmeaaaca", -- 4 -- Level 10 "mmmmdaaca", -- 0 "mmmma....", -- 1 "mmmma....", -- 2 "mmmma....", -- 3 "mmmmeaaca", -- 4 -- Level 11 "mmmmmdaaa", -- 0 "mmmmma...", -- 1 "mmmmma...", -- 2 "mmmmma...", -- 3 "mmmmmeaaa", -- 4 -- Level 12 "mmmmmmddd", -- 0 "mmmmmmaaa", -- 1 "mmmmmmaaa", -- 2 "mmmmmmaaa", -- 3 "mmmmmmeee", -- 4 }, }, -- CorridorStairs { OriginData = { ExportName = "BridgeSegment", Name = "Nether 16", GalleryName = "Nether", GalleryIndex = "16", ID = "158", CreatorName = "Aloe_vera", }, Size = { x = 15, y = 8, z = 5, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 14, MaxY = 17, MaxZ = 4, }, Connectors = { { Type = 0, RelX = 0, RelY = 5, RelZ = 2, Direction = 4, -- X- }, { Type = 0, RelX = 14, RelY = 5, RelZ = 2, Direction = 5, -- X+ }, }, Metadata = { ["AddWeightIfSame"] = "1000", ["AllowedRotations"] = "7", ["DefaultWeight"] = "500", ["DepthWeight"] = "4:-3000|8:-3000|12:-3000|16:-3000|20:-3000", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a:112: 0", -- netherbrickblock "b:114: 5", -- netherbrickstairs "c:114: 4", -- netherbrickstairs "d: 44:14", -- stone_slab "e:114: 6", -- netherbrickstairs "f:114: 7", -- netherbrickstairs "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "mmmmmmmmmmmmmmm", -- 0 "aammmmmmmmmmmaa", -- 1 "aammmmmmmmmmmaa", -- 2 "aammmmmmmmmmmaa", -- 3 "mmmmmmmmmmmmmmm", -- 4 -- Level 1 "mmmmmmmmmmmmmmm", -- 0 "aabmmmmmmmmmcaa", -- 1 "aabmmmmmmmmmcaa", -- 2 "aabmmmmmmmmmcaa", -- 3 "mmmmmmmmmmmmmmm", -- 4 -- Level 2 "mmmmmmmmmmmmmmm", -- 0 "aaabdmmmmmdcaaa", -- 1 "aaabdmmmmmdcaaa", -- 2 "aaabdmmmmmdcaaa", -- 3 "mmmmmmmmmmmmmmm", -- 4 -- Level 3 "eeeeeeeeeeeeeee", -- 0 "aaaaaaaaaaaaaaa", -- 1 "aaaaaaaaaaaaaaa", -- 2 "aaaaaaaaaaaaaaa", -- 3 "fffffffffffffff", -- 4 -- Level 4 "aaaaaaaaaaaaaaa", -- 0 "aaaaaaaaaaaaaaa", -- 1 "aaaaaaaaaaaaaaa", -- 2 "aaaaaaaaaaaaaaa", -- 3 "aaaaaaaaaaaaaaa", -- 4 -- Level 5 "aaaaaaaaaaaaaaa", -- 0 "...............", -- 1 "...............", -- 2 "...............", -- 3 "aaaaaaaaaaaaaaa", -- 4 -- Level 6 "mmmmmmmmmmmmmmm", -- 0 "...............", -- 1 "...............", -- 2 "...............", -- 3 "mmmmmmmmmmmmmmm", -- 4 -- Level 7 "mmmmmmmmmmmmmmm", -- 0 "...............", -- 1 "...............", -- 2 "...............", -- 3 "mmmmmmmmmmmmmmm", -- 4 }, }, -- BridgeSegment { OriginData = { ExportName = "BridgeCrossing", Name = "Nether 17", GalleryName = "Nether", GalleryIndex = "17", ID = "159", CreatorName = "Aloe_vera", }, Size = { x = 15, y = 8, z = 15, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 14, MaxY = 17, MaxZ = 14, }, Connectors = { { Type = 0, RelX = 0, RelY = 5, RelZ = 7, Direction = 4, -- X- }, { Type = 0, RelX = 7, RelY = 5, RelZ = 0, Direction = 2, -- Z- }, { Type = 0, RelX = 7, RelY = 5, RelZ = 14, Direction = 3, -- Z+ }, { Type = 0, RelX = 14, RelY = 5, RelZ = 7, Direction = 5, -- X+ }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "10", ["DepthWeight"] = "1:1000", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a:112: 0", -- netherbrickblock "b:114: 7", -- netherbrickstairs "c:114: 5", -- netherbrickstairs "d:114: 4", -- netherbrickstairs "e:114: 6", -- netherbrickstairs "f: 44:14", -- stone_slab "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "mmmmmmaaammmmmm", -- 0 "mmmmmmaaammmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmmmmmmmmm", -- 5 "aammmmmmmmmmmaa", -- 6 "aammmmmmmmmmmaa", -- 7 "aammmmmmmmmmmaa", -- 8 "mmmmmmmmmmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmaaammmmmm", -- 13 "mmmmmmaaammmmmm", -- 14 -- Level 1 "mmmmmmaaammmmmm", -- 0 "mmmmmmaaammmmmm", -- 1 "mmmmmmbbbmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmmmmmmmmm", -- 5 "aacmmmmmmmmmdaa", -- 6 "aacmmmmmmmmmdaa", -- 7 "aacmmmmmmmmmdaa", -- 8 "mmmmmmmmmmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmeeemmmmmm", -- 12 "mmmmmmaaammmmmm", -- 13 "mmmmmmaaammmmmm", -- 14 -- Level 2 "mmmmmmaaammmmmm", -- 0 "mmmmmmaaammmmmm", -- 1 "mmmmmmaaammmmmm", -- 2 "mmmmmmbbbmmmmmm", -- 3 "mmmmmmfffmmmmmm", -- 4 "mmmmmmmmmmmmmmm", -- 5 "aaacfmmmmmfdaaa", -- 6 "aaacfmmmmmfdaaa", -- 7 "aaacfmmmmmfdaaa", -- 8 "mmmmmmmmmmmmmmm", -- 9 "mmmmmmfffmmmmmm", -- 10 "mmmmmmeeemmmmmm", -- 11 "mmmmmmaaammmmmm", -- 12 "mmmmmmaaammmmmm", -- 13 "mmmmmmaaammmmmm", -- 14 -- Level 3 "mmmmmdaaacmmmmm", -- 0 "mmmmmdaaacmmmmm", -- 1 "mmmmmdaaacmmmmm", -- 2 "mmmmmdaaacmmmmm", -- 3 "mmmmmdaaacmmmmm", -- 4 "eeeeeeaaaeeeeee", -- 5 "aaaaaaaaaaaaaaa", -- 6 "aaaaaaaaaaaaaaa", -- 7 "aaaaaaaaaaaaaaa", -- 8 "bbbbbdaaacbbbbb", -- 9 "mmmmmdaaacmmmmm", -- 10 "mmmmmdaaacmmmmm", -- 11 "mmmmmdaaacmmmmm", -- 12 "mmmmmdaaacmmmmm", -- 13 "mmmmmdaaacmmmmm", -- 14 -- Level 4 "mmmmmaaaaammmmm", -- 0 "mmmmmaaaaammmmm", -- 1 "mmmmmaaaaammmmm", -- 2 "mmmmmaaaaammmmm", -- 3 "mmmmmaaaaammmmm", -- 4 "aaaaaaaaaaaaaaa", -- 5 "aaaaaaaaaaaaaaa", -- 6 "aaaaaaaaaaaaaaa", -- 7 "aaaaaaaaaaaaaaa", -- 8 "aaaaaaaaaaaaaaa", -- 9 "mmmmmaaaaammmmm", -- 10 "mmmmmaaaaammmmm", -- 11 "mmmmmaaaaammmmm", -- 12 "mmmmmaaaaammmmm", -- 13 "mmmmmaaaaammmmm", -- 14 -- Level 5 "mmmmma...ammmmm", -- 0 "mmmmma...ammmmm", -- 1 "mmmmma...ammmmm", -- 2 "mmmmma...ammmmm", -- 3 "mmmmma...ammmmm", -- 4 "aaaaaa...aaaaaa", -- 5 "...............", -- 6 "...............", -- 7 "...............", -- 8 "aaaaaa...aaaaaa", -- 9 "mmmmma...ammmmm", -- 10 "mmmmma...ammmmm", -- 11 "mmmmma...ammmmm", -- 12 "mmmmma...ammmmm", -- 13 "mmmmma...ammmmm", -- 14 -- Level 6 "mmmmmm...mmmmmm", -- 0 "mmmmmm...mmmmmm", -- 1 "mmmmmm...mmmmmm", -- 2 "mmmmmm...mmmmmm", -- 3 "mmmmmm...mmmmmm", -- 4 "mmmmmm...mmmmmm", -- 5 "...............", -- 6 "...............", -- 7 "...............", -- 8 "mmmmmm...mmmmmm", -- 9 "mmmmmm...mmmmmm", -- 10 "mmmmmm...mmmmmm", -- 11 "mmmmmm...mmmmmm", -- 12 "mmmmmm...mmmmmm", -- 13 "mmmmmm...mmmmmm", -- 14 -- Level 7 "mmmmmm...mmmmmm", -- 0 "mmmmmm...mmmmmm", -- 1 "mmmmmm...mmmmmm", -- 2 "mmmmmm...mmmmmm", -- 3 "mmmmmm...mmmmmm", -- 4 "mmmmmm...mmmmmm", -- 5 "...............", -- 6 "...............", -- 7 "...............", -- 8 "mmmmmm...mmmmmm", -- 9 "mmmmmm...mmmmmm", -- 10 "mmmmmm...mmmmmm", -- 11 "mmmmmm...mmmmmm", -- 12 "mmmmmm...mmmmmm", -- 13 "mmmmmm...mmmmmm", -- 14 }, }, -- BridgeCrossing { OriginData = { ExportName = "BridgeCrumble2", Name = "Nether 18", GalleryName = "Nether", GalleryIndex = "18", ID = "160", CreatorName = "Aloe_vera", }, Size = { x = 13, y = 6, z = 5, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 12, MaxY = 15, MaxZ = 4, }, Connectors = { { Type = 0, RelX = 0, RelY = 5, RelZ = 2, Direction = 4, -- X- }, { Type = 1, RelX = 0, RelY = 5, RelZ = 2, Direction = 4, -- X- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "1:0|2:0|3:0|4:0|5:0", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a:112: 0", -- netherbrickblock "b:114: 5", -- netherbrickstairs "c: 44:14", -- stone_slab "d:114: 6", -- netherbrickstairs "e:114: 7", -- netherbrickstairs "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "mmmmmmmmmmmmm", -- 0 "aammmmmmmmmmm", -- 1 "aammmmmmmmmmm", -- 2 "aammmmmmmmmmm", -- 3 "mmmmmmmmmmmmm", -- 4 -- Level 1 "mmmmmmmmmmmmm", -- 0 "aabmmmmmmmmmm", -- 1 "aabmmmmmmmmmm", -- 2 "aabmmmmmmmmmm", -- 3 "mmmmmmmmmmmmm", -- 4 -- Level 2 "mmmmmmmmmmmmm", -- 0 "aaabcmmmmmmmm", -- 1 "aaabcmmmmmmmm", -- 2 "aaabcmmmmmmmm", -- 3 "mmmmmmmmmmmmm", -- 4 -- Level 3 "dddddddddmmmm", -- 0 "aaaaaaaaaaaaa", -- 1 "aaaaaaaaammmm", -- 2 "aaaaaaaaaaaam", -- 3 "eeeeeeeeemmmm", -- 4 -- Level 4 "aaaaaaaaaaaam", -- 0 "aaaaaaaaaammm", -- 1 "aaaaaaaaaaamm", -- 2 "aaaaaaaaammmm", -- 3 "aaaaaaaaaaaaa", -- 4 -- Level 5 "aaaaaaaaammmm", -- 0 "mmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmm", -- 3 "aaaaaaaaaammm", -- 4 }, }, -- BridgeCrumble2 { OriginData = { ExportName = "BridgeCrumble1", Name = "Nether 19", GalleryName = "Nether", GalleryIndex = "19", ID = "161", CreatorName = "Aloe_vera", }, Size = { x = 9, y = 6, z = 5, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 8, MaxY = 15, MaxZ = 4, }, Connectors = { { Type = 1, RelX = 0, RelY = 5, RelZ = 2, Direction = 4, -- X- }, { Type = 0, RelX = 0, RelY = 5, RelZ = 2, Direction = 4, -- X- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "1:0|2:0|3:0|4:0|5:0", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a:112: 0", -- netherbrickblock "b:114: 5", -- netherbrickstairs "c: 44:14", -- stone_slab "d:114: 6", -- netherbrickstairs "e:114: 7", -- netherbrickstairs "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "mmmmmmmmm", -- 0 "aammmmmmm", -- 1 "aammmmmmm", -- 2 "aammmmmmm", -- 3 "mmmmmmmmm", -- 4 -- Level 1 "mmmmmmmmm", -- 0 "aabmmmmmm", -- 1 "aabmmmmmm", -- 2 "aabmmmmmm", -- 3 "mmmmmmmmm", -- 4 -- Level 2 "mmmmmmmmm", -- 0 "aaabcmmmm", -- 1 "aaabcmmmm", -- 2 "aaabcmmmm", -- 3 "mmmmmmmmm", -- 4 -- Level 3 "dddddddmm", -- 0 "aaaaaaaam", -- 1 "aaaaaaaaa", -- 2 "aaaaaaamm", -- 3 "eeeeemmmm", -- 4 -- Level 4 "aaaaaaaaa", -- 0 "aaaaammmm", -- 1 "aaaaaammm", -- 2 "aaaaaammm", -- 3 "aaaaaaaam", -- 4 -- Level 5 "aaaaaammm", -- 0 "mmmmmmmmm", -- 1 "mmmmmmmmm", -- 2 "mmmmmmmmm", -- 3 "aaaaaaamm", -- 4 }, }, -- BridgeCrumble1 { OriginData = { ExportName = "BlazePlatformOverhang", Name = "Nether 20", GalleryName = "Nether", GalleryIndex = "20", ID = "162", CreatorName = "STR_Warrior", }, Size = { x = 14, y = 11, z = 7, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 13, MaxY = 20, MaxZ = 6, }, Connectors = { { Type = 0, RelX = 0, RelY = 5, RelZ = 3, Direction = 4, -- X- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "1:0|2:0|3:0|4:0|5:0", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a:112: 0", -- netherbrickblock "b:114: 5", -- netherbrickstairs "c: 44:14", -- stone_slab "d:114: 6", -- netherbrickstairs "e:114: 7", -- netherbrickstairs "f:114: 0", -- netherbrickstairs "g:114: 4", -- netherbrickstairs "h:113: 0", -- netherbrickfence "i: 52: 0", -- mobspawner "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "mmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmm", -- 1 "aammmmmmmmmmmm", -- 2 "aammmmmmmmmmmm", -- 3 "aammmmmmmmmmmm", -- 4 "mmmmmmmmmmmmmm", -- 5 "mmmmmmmmmmmmmm", -- 6 -- Level 1 "mmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmm", -- 1 "aabcmmmmmmmmmm", -- 2 "aabcmmmmmmmmmm", -- 3 "aabcmmmmmmmmmm", -- 4 "mmmmmmmmmmmmmm", -- 5 "mmmmmmmmmmmmmm", -- 6 -- Level 2 "mmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmm", -- 1 "aaaaabmmmmmmmm", -- 2 "aaaaabmmmmmmmm", -- 3 "aaaaabmmmmmmmm", -- 4 "mmmmmmmmmmmmmm", -- 5 "mmmmmmmmmmmmmm", -- 6 -- Level 3 "mmmmmmmmmmmmmm", -- 0 "dddddddmmmmmmm", -- 1 "aaaaaabmmmmmmm", -- 2 "aaaaaabmmmmmmm", -- 3 "aaaaaabmmmmmmm", -- 4 "eeeeeeemmmmmmm", -- 5 "mmmmmmmmmmmmmm", -- 6 -- Level 4 "mmmmmmmmmmmmmm", -- 0 "aaaaaaadmmmmmm", -- 1 "aaaaaaabmmmmmm", -- 2 "aaaaaaabmmmmmm", -- 3 "aaaaaaabmmmmmm", -- 4 "aaaaaaaemmmmmm", -- 5 "mmmmmmmmmmmmmm", -- 6 -- Level 5 "mmmmmmmmmmmmmm", -- 0 "aaaaaaaabddddm", -- 1 "......faaaaabm", -- 2 "......faaaaabm", -- 3 "......faaaaabm", -- 4 "aaaaaaaaabeebm", -- 5 "mmmmmmmmmmmmmm", -- 6 -- Level 6 "mmmmmmmmgdddbm", -- 0 "mmmmmmaaaaaaad", -- 1 ".......faaaaab", -- 2 ".......faaaaab", -- 3 ".......faaaaab", -- 4 "mmmmmmaaaaaaae", -- 5 "mmmmmmmmgeeebm", -- 6 -- Level 7 "mmmmmmmmaaaaam", -- 0 "mmmmmmhaa...aa", -- 1 ".............a", -- 2 "..........i..a", -- 3 ".............a", -- 4 "mmmmmmhaa...aa", -- 5 "mmmmmmmmaaaaam", -- 6 -- Level 8 "mmmmmmmmhhhhhm", -- 0 "mmmmmmhhh...hh", -- 1 "mm...........h", -- 2 "mm...........h", -- 3 "mm...........h", -- 4 "mmmmmmhhh...hh", -- 5 "mmmmmmmmhhhhhm", -- 6 -- Level 9 "mmmmmmmm.....m", -- 0 "mmmmmm........", -- 1 "mmmm..........", -- 2 "mmmm..........", -- 3 "mmmm..........", -- 4 "mmmmmm........", -- 5 "mmmmmmmm.....m", -- 6 -- Level 10 "mmmmmmmm.....m", -- 0 "mmmmmm........", -- 1 "mmmmmm........", -- 2 "mmmmmm........", -- 3 "mmmmmm........", -- 4 "mmmmmm........", -- 5 "mmmmmmmm.....m", -- 6 }, }, -- BlazePlatformOverhang { OriginData = { ExportName = "CentralRoom", Name = "Nether 22", GalleryName = "Nether", GalleryIndex = "22", ID = "164", CreatorName = "Aloe_vera", }, Size = { x = 13, y = 9, z = 13, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 12, MaxY = 8, MaxZ = 12, }, Connectors = { { Type = 0, RelX = 6, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, { Type = 1, RelX = 6, RelY = 1, RelZ = 12, Direction = 3, -- Z+ }, { Type = -1, RelX = 6, RelY = 1, RelZ = 12, Direction = 3, -- Z+ }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "1", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", ["VerticalStrategy"] = "Range|40|100", }, BlockDefinitions = { ".: 0: 0", -- air "a:112: 0", -- netherbrickblock "b: 10: 0", -- lava "c:113: 0", -- netherbrickfence "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "aaaaaaaaaaaaa", -- 0 "aaaaaaaaaaaaa", -- 1 "aaaaaaaaaaaaa", -- 2 "aaaaaaaaaaaaa", -- 3 "aaaaaaaaaaaaa", -- 4 "aaaaaaaaaaaaa", -- 5 "aaaaaaaaaaaaa", -- 6 "aaaaaaaaaaaaa", -- 7 "aaaaaaaaaaaaa", -- 8 "aaaaaaaaaaaaa", -- 9 "aaaaaaaaaaaaa", -- 10 "aaaaaaaaaaaaa", -- 11 "aaaaaaaaaaaaa", -- 12 -- Level 1 "aaaaa...aaaaa", -- 0 "aaaaa...aaaaa", -- 1 "aa.........aa", -- 2 "aa.........aa", -- 3 "aa.........aa", -- 4 "aa...aaa...aa", -- 5 "aa...aba...aa", -- 6 "aa...aaa...aa", -- 7 "aa.........aa", -- 8 "aa.........aa", -- 9 "aa.........aa", -- 10 "aaaaa...aaaaa", -- 11 "aaaaa...aaaaa", -- 12 -- Level 2 "aaaaa...aaaaa", -- 0 "aaaca...acaaa", -- 1 "aa.........aa", -- 2 "ac.........ca", -- 3 "aa.........aa", -- 4 "ac.........ca", -- 5 "aa.........aa", -- 6 "ac.........ca", -- 7 "aa.........aa", -- 8 "ac.........ca", -- 9 "aa.........aa", -- 10 "aaaca...acaaa", -- 11 "aaaaa...aaaaa", -- 12 -- Level 3 "aaaaa...aaaaa", -- 0 "aaaca...acaaa", -- 1 "aa.........aa", -- 2 "ac.........ca", -- 3 "aa.........aa", -- 4 "ac.........ca", -- 5 "aa.........aa", -- 6 "ac.........ca", -- 7 "aa.........aa", -- 8 "ac.........ca", -- 9 "aa.........aa", -- 10 "aaaca...acaaa", -- 11 "aaaaa...aaaaa", -- 12 -- Level 4 "acacacccacaca", -- 0 "caaaa...aaaac", -- 1 "aa.........aa", -- 2 "ca.........ac", -- 3 "aa.........aa", -- 4 "ca.........ac", -- 5 "aa.........aa", -- 6 "ca.........ac", -- 7 "aa.........aa", -- 8 "ca.........ac", -- 9 "aa.........aa", -- 10 "caaaa...aaaac", -- 11 "acaca...acaca", -- 12 -- Level 5 "acacaaaaacaca", -- 0 "caaaaaaaaaaac", -- 1 "aa.........aa", -- 2 "ca.........ac", -- 3 "aa.........aa", -- 4 "ca.........ac", -- 5 "aa.........aa", -- 6 "ca.........ac", -- 7 "aa.........aa", -- 8 "ca.........ac", -- 9 "aa.........aa", -- 10 "caaaaaaaaaaac", -- 11 "acacaaaaacaca", -- 12 -- Level 6 "aaaaaaaaaaaaa", -- 0 "aaaaaaaaaaaaa", -- 1 "aaaaaaaaaaaaa", -- 2 "aaaaaaaaaaaaa", -- 3 "aaaaaaaaaaaaa", -- 4 "aaaaaaaaaaaaa", -- 5 "aaaaaaaaaaaaa", -- 6 "aaaaaaaaaaaaa", -- 7 "aaaaaaaaaaaaa", -- 8 "aaaaaaaaaaaaa", -- 9 "aaaaaaaaaaaaa", -- 10 "aaaaaaaaaaaaa", -- 11 "aaaaaaaaaaaaa", -- 12 -- Level 7 "aaaaaaaaaaaaa", -- 0 "aaaaaaaaaaaaa", -- 1 "aaaaaaaaaaaaa", -- 2 "aaaaaaaaaaaaa", -- 3 "aaaaaaaaaaaaa", -- 4 "aaaaaaaaaaaaa", -- 5 "aaaaaaaaaaaaa", -- 6 "aaaaaaaaaaaaa", -- 7 "aaaaaaaaaaaaa", -- 8 "aaaaaaaaaaaaa", -- 9 "aaaaaaaaaaaaa", -- 10 "aaaaaaaaaaaaa", -- 11 "aaaaaaaaaaaaa", -- 12 -- Level 8 "cacacacacacac", -- 0 "a...........a", -- 1 "c...........c", -- 2 "a...........a", -- 3 "c...........c", -- 4 "a...........a", -- 5 "c...........c", -- 6 "a...........a", -- 7 "c...........c", -- 8 "a...........a", -- 9 "c...........c", -- 10 "a...........a", -- 11 "cacacacacacac", -- 12 }, }, -- CentralRoom { OriginData = { ExportName = "MidStaircase", Name = "Nether 23", GalleryName = "Nether", GalleryIndex = "23", ID = "165", CreatorName = "Aloe_vera", }, Size = { x = 13, y = 8, z = 13, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 12, MaxY = 7, MaxZ = 12, }, Connectors = { { Type = 1, RelX = 12, RelY = 1, RelZ = 6, Direction = 5, -- X+ }, { Type = 1, RelX = 0, RelY = 1, RelZ = 6, Direction = 4, -- X- }, { Type = -1, RelX = 12, RelY = 1, RelZ = 6, Direction = 5, -- X+ }, { Type = -1, RelX = 0, RelY = 1, RelZ = 6, Direction = 4, -- X- }, }, Metadata = { ["AddWeightIfSame"] = "-1000", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a:112: 0", -- netherbrickblock "b: 88: 0", -- soulsand "c:115: 3", -- 115 "d:114: 3", -- netherbrickstairs "e:114: 0", -- netherbrickstairs "f:114: 1", -- netherbrickstairs "g:114: 2", -- netherbrickstairs "h: 10: 0", -- lava "i:113: 0", -- netherbrickfence "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "aaaaaaaaaaaaa", -- 0 "aaaaaaaaaaaaa", -- 1 "aaaaaaaaaaaaa", -- 2 "aaaabbbbbaaaa", -- 3 "aaaabbbbbaaaa", -- 4 "aaaaaaaaaaaaa", -- 5 "aaaaaaaaaaaaa", -- 6 "aaaaaaaaaaaaa", -- 7 "aaaabbbbbaaaa", -- 8 "aaaabbbbbaaaa", -- 9 "aaaaaaaaaaaaa", -- 10 "aaaaaaaaaaaaa", -- 11 "aaaaaaaaaaaaa", -- 12 -- Level 1 "aaaaaaaaaaaaa", -- 0 "aaaaaaaaaaaaa", -- 1 "aaaaaaaaaaaaa", -- 2 "aaaacccccaaaa", -- 3 "addecccccfdda", -- 4 "...eaaaaad...", -- 5 "...eaaaaa....", -- 6 "...eaaaaag...", -- 7 "agggcccccfgga", -- 8 "aaaacccccaaaa", -- 9 "aaaaaaaaaaaaa", -- 10 "aaaaaaaaaaaaa", -- 11 "aaaaaaaaaaaaa", -- 12 -- Level 2 "aaaaaaaaaaaaa", -- 0 "aha.......aha", -- 1 "aaa.......aaa", -- 2 "a...........a", -- 3 "a...........a", -- 4 "....eaaaa....", -- 5 "....eaaaa....", -- 6 "....eaaaa....", -- 7 "a...........a", -- 8 "a...........a", -- 9 "aaa.......aaa", -- 10 "aha.......aha", -- 11 "aaaaaaaaaaaaa", -- 12 -- Level 3 "aaaiiaaaiiaaa", -- 0 "a...........a", -- 1 "a...........a", -- 2 "a...........a", -- 3 "a...........a", -- 4 ".....eaaa....", -- 5 ".....eaaa....", -- 6 ".....eaaa....", -- 7 "a...........a", -- 8 "a...........a", -- 9 "a...........a", -- 10 "a...........a", -- 11 "aaaiiaaaiiaaa", -- 12 -- Level 4 "aaaiiaaaiiaaa", -- 0 "a...........a", -- 1 "a...........a", -- 2 "a...........a", -- 3 "a...........a", -- 4 "......eaa....", -- 5 "......eaa....", -- 6 "......eaa....", -- 7 "a...........a", -- 8 "a...........a", -- 9 "a...........a", -- 10 "a...........a", -- 11 "aaaiiaaaiiaaa", -- 12 -- Level 5 "aaaaaaaaaaaaa", -- 0 "a...........a", -- 1 "a...........a", -- 2 "a...........a", -- 3 "a...........a", -- 4 "a......ea...a", -- 5 "a......ea...a", -- 6 "a......ea...a", -- 7 "a...........a", -- 8 "a...........a", -- 9 "a...........a", -- 10 "a...........a", -- 11 "aaaaaaaaaaaaa", -- 12 -- Level 6 "aaaaaaaaaaaaa", -- 0 "aaaaaaaaaaaaa", -- 1 "aaaaaaaaaaaaa", -- 2 "aaaaaaaaaaaaa", -- 3 "aaaaaaaaaaaaa", -- 4 "aaaa....eaaaa", -- 5 "aaaa....eaaaa", -- 6 "aaaa....eaaaa", -- 7 "aaaaaaaaaaaaa", -- 8 "aaaaaaaaaaaaa", -- 9 "aaaaaaaaaaaaa", -- 10 "aaaaaaaaaaaaa", -- 11 "aaaaaaaaaaaaa", -- 12 -- Level 7 "iaiaiaiaiaiai", -- 0 "a...........a", -- 1 "i...........i", -- 2 "a...........a", -- 3 "i...........i", -- 4 "a...........a", -- 5 "i...........i", -- 6 "a...........a", -- 7 "i...........i", -- 8 "a...........a", -- 9 "i...........i", -- 10 "a...........a", -- 11 "iaiaiaiaiaiai", -- 12 }, }, -- MidStaircase { OriginData = { ExportName = "BlazePlatform", Name = "Nether 26", GalleryName = "Nether", GalleryIndex = "26", ID = "276", CreatorName = "tonibm1999", }, Size = { x = 10, y = 7, z = 7, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 9, MaxY = 6, MaxZ = 6, }, Connectors = { { Type = 0, RelX = 0, RelY = 1, RelZ = 3, Direction = 4, -- X- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "1:0|2:0|3:0|4:0|5:0", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a:112: 0", -- netherbrickblock "b: 52: 0", -- mobspawner "c:113: 0", -- netherbrickfence "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "mmmmmmmmmm", -- 0 "aaaaaaaaaa", -- 1 "aaaaaaaaaa", -- 2 "aaaaaaaaaa", -- 3 "aaaaaaaaaa", -- 4 "aaaaaaaaaa", -- 5 "mmmmmmmmmm", -- 6 -- Level 1 "mmmmmmmmmm", -- 0 "aaaaaaaaaa", -- 1 "..aaaaaaaa", -- 2 "..aaaaaaaa", -- 3 "..aaaaaaaa", -- 4 "aaaaaaaaaa", -- 5 "mmmmmmmmmm", -- 6 -- Level 2 "mmmmaaaaaa", -- 0 "aaaaaaaaaa", -- 1 "...aaaaaaa", -- 2 "...aaaaaaa", -- 3 "...aaaaaaa", -- 4 "aaaaaaaaaa", -- 5 "mmmmaaaaaa", -- 6 -- Level 3 "mmmmaaaaaa", -- 0 "mmaaa....a", -- 1 ".........a", -- 2 "......b..a", -- 3 ".........a", -- 4 "mmaaa....a", -- 5 "mmmmaaaaaa", -- 6 -- Level 4 "mmmmcccccc", -- 0 "mmmcc....c", -- 1 ".........c", -- 2 ".........c", -- 3 ".........c", -- 4 "mmmcc....c", -- 5 "mmmmcccccc", -- 6 -- Level 5 "mmmmmmmmmm", -- 0 "mmmmm....c", -- 1 "m........c", -- 2 "m........c", -- 3 "m........c", -- 4 "mmmmm....c", -- 5 "mmmmmmmmmm", -- 6 -- Level 6 "mmmmmmmmmm", -- 0 "mmmmm....m", -- 1 "mm.......c", -- 2 "mm.......c", -- 3 "mm.......c", -- 4 "mmmmm....m", -- 5 "mmmmmmmmmm", -- 6 }, }, -- BlazePlatform { OriginData = { ExportName = "StairsToOpen1", Name = "Nether 27", GalleryName = "Nether", GalleryIndex = "27", ID = "277", CreatorName = "Aloe_vera", }, Size = { x = 7, y = 10, z = 7, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 6, MaxY = 19, MaxZ = 6, }, Connectors = { { Type = 0, RelX = 6, RelY = 7, RelZ = 3, Direction = 5, -- X+ }, { Type = 0, RelX = 3, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "1:0|3:0|5:0|7:0|9:0|11:0|13:0|15:0", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a:112: 0", -- netherbrickblock "b:113: 0", -- netherbrickfence "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "aaaaaaa", -- 0 "aaaaaaa", -- 1 "aaaaaaa", -- 2 "aaaaaaa", -- 3 "aaaaaaa", -- 4 "aaaaaaa", -- 5 "aaaaaaa", -- 6 -- Level 1 "aa...aa", -- 0 "a.....a", -- 1 "a.....a", -- 2 "a.....a", -- 3 "a.....a", -- 4 "aaaaaaa", -- 5 "aaaaaaa", -- 6 -- Level 2 "aa...aa", -- 0 "a.....a", -- 1 "b.....b", -- 2 "a.....a", -- 3 "b.....b", -- 4 "a.aaaaa", -- 5 "aabaaba", -- 6 -- Level 3 "aa...aa", -- 0 "a.....a", -- 1 "b.....b", -- 2 "a.....a", -- 3 "b.....b", -- 4 "a..aaaa", -- 5 "aabaaba", -- 6 -- Level 4 "aabbbaa", -- 0 "a.....a", -- 1 "b.....b", -- 2 "a.....a", -- 3 "b.....b", -- 4 "a...aaa", -- 5 "aabaaba", -- 6 -- Level 5 "aaaaaaa", -- 0 "a.....a", -- 1 "a.....a", -- 2 "a.....a", -- 3 "a.....a", -- 4 "a....aa", -- 5 "aaaaaaa", -- 6 -- Level 6 "aaaaaaa", -- 0 "aaaaaaa", -- 1 "aaaaaaa", -- 2 "aaaaaaa", -- 3 "aaaaaaa", -- 4 "a.....a", -- 5 "aaaaaaa", -- 6 -- Level 7 "aaaaaaa", -- 0 "a.....a", -- 1 "a......", -- 2 "a......", -- 3 "a......", -- 4 "a.....a", -- 5 "aaaaaaa", -- 6 -- Level 8 "mmmmmmm", -- 0 "m.....m", -- 1 "m......", -- 2 "m......", -- 3 "m......", -- 4 "m.....m", -- 5 "mmmmmmm", -- 6 -- Level 9 "mmmmmmm", -- 0 "m.....m", -- 1 "m......", -- 2 "m......", -- 3 "m......", -- 4 "m.....m", -- 5 "mmmmmmm", -- 6 }, }, -- StairsToOpen1 { OriginData = { ExportName = "LavaStaircase", Name = "Nether 28", GalleryName = "Nether", GalleryIndex = "28", ID = "278", CreatorName = "Aloe_vera", }, Size = { x = 15, y = 11, z = 15, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 14, MaxY = 10, MaxZ = 14, }, Connectors = { { Type = 1, RelX = 0, RelY = 6, RelZ = 7, Direction = 4, -- X- }, { Type = 1, RelX = 9, RelY = 1, RelZ = 14, Direction = 3, -- Z+ }, { Type = 1, RelX = 9, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, { Type = -1, RelX = 0, RelY = 6, RelZ = 7, Direction = 4, -- X- }, { Type = -1, RelX = 9, RelY = 1, RelZ = 14, Direction = 3, -- Z+ }, { Type = -1, RelX = 9, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "10", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a:112: 0", -- netherbrickblock "b:113: 0", -- netherbrickfence "c: 10: 0", -- lava "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "aaaaaaaaaaaaaaa", -- 0 "aaaaaaaaaaaaaaa", -- 1 "aaaaaaaaaaaaaaa", -- 2 "aaaaaaaaaaaaaaa", -- 3 "aaaaaaaaaaaaaaa", -- 4 "aaaaaaaaaaaaaaa", -- 5 "aaaaaaaaaaaaaaa", -- 6 "aaaaaaaaaaaaaaa", -- 7 "aaaaaaaaaaaaaaa", -- 8 "aaaaaaaaaaaaaaa", -- 9 "aaaaaaaaaaaaaaa", -- 10 "aaaaaaaaaaaaaaa", -- 11 "aaaaaaaaaaaaaaa", -- 12 "aaaaaaaaaaaaaaa", -- 13 "aaaaaaaaaaaaaaa", -- 14 -- Level 1 "aaaaaaaa...aaaa", -- 0 "aaaaa.........a", -- 1 "aaaaa.........a", -- 2 "aaaaab........a", -- 3 "accca...aaaa..a", -- 4 "accca...acca..a", -- 5 "acccaaaaacca..a", -- 6 "acccccccccca..a", -- 7 "acccaaaaacca..a", -- 8 "accca...acca..a", -- 9 "accca...aaaa..a", -- 10 "aaaaab........a", -- 11 "aaaaa.........a", -- 12 "aaaaa.........a", -- 13 "aaaaaaaa...aaaa", -- 14 -- Level 2 "aaaaaaaa...aaaa", -- 0 "aaaa..........a", -- 1 "aaaa..........a", -- 2 "aaaabb........a", -- 3 "aaaa..........a", -- 4 "a.............a", -- 5 "a.............a", -- 6 "a.............a", -- 7 "a.............a", -- 8 "a.............a", -- 9 "aaaa..........a", -- 10 "aaaabb........a", -- 11 "aaaa..........a", -- 12 "aaaa..........a", -- 13 "aaaaaaaa...aaaa", -- 14 -- Level 3 "aaaaaaaa...aaaa", -- 0 "a.............a", -- 1 "a.............a", -- 2 "a..bb.........a", -- 3 "aaaa..........a", -- 4 "aaaa..........a", -- 5 "a.............a", -- 6 "a.............a", -- 7 "a.............a", -- 8 "aaaa..........a", -- 9 "aaaa..........a", -- 10 "a..bb.........a", -- 11 "a.............a", -- 12 "a.............a", -- 13 "aaaaaaaa...aaaa", -- 14 -- Level 4 "aaaaaaaa...aaaa", -- 0 "a.............a", -- 1 "a.............a", -- 2 "a..b..........a", -- 3 "a..b..........a", -- 4 "aaaa..........a", -- 5 "aaaa..........a", -- 6 "a.............a", -- 7 "aaaa..........a", -- 8 "aaaa..........a", -- 9 "a..b..........a", -- 10 "a..b..........a", -- 11 "a.............a", -- 12 "a.............a", -- 13 "aaaaaaaa...aaaa", -- 14 -- Level 5 "aaaaaaaaaaaaaaa", -- 0 "a.............a", -- 1 "a.............a", -- 2 "a.............a", -- 3 "a..b..........a", -- 4 "a..b..........a", -- 5 "aaaa..........a", -- 6 "aaaa..........a", -- 7 "aaaa..........a", -- 8 "a..b..........a", -- 9 "a..b..........a", -- 10 "a.............a", -- 11 "a.............a", -- 12 "a.............a", -- 13 "aaaaaaaaaaaaaaa", -- 14 -- Level 6 "aaaaaaaaaaaaaaa", -- 0 "a.............a", -- 1 "a.............a", -- 2 "a.............a", -- 3 "a.............a", -- 4 "a..b..........a", -- 5 "...b..........a", -- 6 "...b..........a", -- 7 "...b..........a", -- 8 "a..b..........a", -- 9 "a.............a", -- 10 "a.............a", -- 11 "a.............a", -- 12 "a.............a", -- 13 "aaaaaaaaaaaaaaa", -- 14 -- Level 7 "aababababababaa", -- 0 "a.............a", -- 1 "b.............b", -- 2 "a.............a", -- 3 "b.............b", -- 4 "a.............a", -- 5 "..............b", -- 6 "..............a", -- 7 "..............b", -- 8 "a.............a", -- 9 "b.............b", -- 10 "a.............a", -- 11 "b.............b", -- 12 "a.............a", -- 13 "aababababababaa", -- 14 -- Level 8 "aababababababaa", -- 0 "a.............a", -- 1 "b.............b", -- 2 "a.............a", -- 3 "b.............b", -- 4 "a.............a", -- 5 "..............b", -- 6 "..............a", -- 7 "..............b", -- 8 "a.............a", -- 9 "b.............b", -- 10 "a.............a", -- 11 "b.............b", -- 12 "a.............a", -- 13 "aababababababaa", -- 14 -- Level 9 "aababababababaa", -- 0 "a.............a", -- 1 "b.............b", -- 2 "a.............a", -- 3 "b.............b", -- 4 "a.............a", -- 5 "..............b", -- 6 "..............a", -- 7 "..............b", -- 8 "a.............a", -- 9 "b.............b", -- 10 "a.............a", -- 11 "b.............b", -- 12 "a.............a", -- 13 "aababababababaa", -- 14 -- Level 10 "aaaaaaaaaaaaaaa", -- 0 "aaaaaaaaaaaaaaa", -- 1 "aaaaaaaaaaaaaaa", -- 2 "aaaaaaaaaaaaaaa", -- 3 "aaaaaaaaaaaaaaa", -- 4 "aaaaaaaaaaaaaaa", -- 5 "aaaaaaaaaaaaaaa", -- 6 "aaaaaaaaaaaaaaa", -- 7 "aaaaaaaaaaaaaaa", -- 8 "aaaaaaaaaaaaaaa", -- 9 "aaaaaaaaaaaaaaa", -- 10 "aaaaaaaaaaaaaaa", -- 11 "aaaaaaaaaaaaaaa", -- 12 "aaaaaaaaaaaaaaa", -- 13 "aaaaaaaaaaaaaaa", -- 14 }, }, -- LavaStaircase { OriginData = { ExportName = "LavaStairsBridge", Name = "Nether 30", GalleryName = "Nether", GalleryIndex = "30", ID = "281", CreatorName = "STR_Warrior", }, Size = { x = 16, y = 12, z = 15, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 15, MaxY = 11, MaxZ = 14, }, Connectors = { { Type = 1, RelX = 0, RelY = 6, RelZ = 7, Direction = 4, -- X- }, { Type = -1, RelX = 0, RelY = 6, RelZ = 7, Direction = 4, -- X- }, { Type = 1, RelX = 9, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, { Type = -1, RelX = 9, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, { Type = 1, RelX = 9, RelY = 1, RelZ = 14, Direction = 3, -- Z+ }, { Type = -1, RelX = 9, RelY = 1, RelZ = 14, Direction = 3, -- Z+ }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "10", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a:112: 0", -- netherbrickblock "b:113: 0", -- netherbrickfence "c: 10: 0", -- lava "d:114: 2", -- netherbrickstairs "e:114: 3", -- netherbrickstairs "f:114: 7", -- netherbrickstairs "g: 44:14", -- stone_slab "h:114: 6", -- netherbrickstairs "i: 44: 6", -- stone_slab "j:114: 0", -- netherbrickstairs "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "aaaaaaaaaaaaaaaa", -- 0 "aaaaaaaaaaaaaaaa", -- 1 "aaaaaaaaaaaaaaaa", -- 2 "aaaaaaaaaaaaaaaa", -- 3 "aaaaaaaaaaaaaaaa", -- 4 "aaaaaaaaaaaaaaaa", -- 5 "aaaaaaaaaaaaaaaa", -- 6 "aaaaaaaaaaaaaaaa", -- 7 "aaaaaaaaaaaaaaaa", -- 8 "aaaaaaaaaaaaaaaa", -- 9 "aaaaaaaaaaaaaaaa", -- 10 "aaaaaaaaaaaaaaaa", -- 11 "aaaaaaaaaaaaaaaa", -- 12 "aaaaaaaaaaaaaaaa", -- 13 "aaaaaaaaaaaaaaaa", -- 14 -- Level 1 "aaaaaaaa...aaaaa", -- 0 "aaaaa..........a", -- 1 "aaaaa..........a", -- 2 "aaaaab.........a", -- 3 "accca...ddd.aaaa", -- 4 "accca...aaa.acca", -- 5 "acccaaaaaaaaacca", -- 6 "acccccccccccccca", -- 7 "acccaaaaaaaaacca", -- 8 "accca...aaa.acca", -- 9 "accca...eee.aaaa", -- 10 "aaaaab.........a", -- 11 "aaaaa..........a", -- 12 "aaaaa..........a", -- 13 "aaaaaaaa...aaaaa", -- 14 -- Level 2 "aaaaaaaa...aaaaa", -- 0 "aaaa...........a", -- 1 "aaaa...........a", -- 2 "aaaabb.........a", -- 3 "aaaa........b..a", -- 4 "a.......ddd....a", -- 5 "a.......fff....a", -- 6 "a.......ggg....a", -- 7 "a.......hhh....a", -- 8 "a.......eee....a", -- 9 "aaaa........b..a", -- 10 "aaaabb.........a", -- 11 "aaaa...........a", -- 12 "aaaa...........a", -- 13 "aaaaaaaa...aaaaa", -- 14 -- Level 3 "aaaaaaaa...aaaaa", -- 0 "a..............a", -- 1 "a..............a", -- 2 "a..bb..........a", -- 3 "aaaa........b..a", -- 4 "aaaa...........a", -- 5 "a..............a", -- 6 "a..............a", -- 7 "a..............a", -- 8 "aaaa...........a", -- 9 "aaaa........b..a", -- 10 "a..bb..........a", -- 11 "a..............a", -- 12 "a..............a", -- 13 "aaaaaaaa...aaaaa", -- 14 -- Level 4 "aaaaaaaabbbaaaaa", -- 0 "a..............a", -- 1 "a..............a", -- 2 "a..b...........a", -- 3 "a..b........b..a", -- 4 "aaaa...........a", -- 5 "aaaa...........a", -- 6 "a..............a", -- 7 "aaaa...........a", -- 8 "aaaa...........a", -- 9 "a..b........b..a", -- 10 "a..b...........a", -- 11 "a..............a", -- 12 "a..............a", -- 13 "aaaaaaaabbbaaaaa", -- 14 -- Level 5 "aaaaaaaaaaaaaaaa", -- 0 "a..............a", -- 1 "a..............a", -- 2 "a...........ggga", -- 3 "a..b........iija", -- 4 "a..b........iija", -- 5 "aaaa........iija", -- 6 "aaaa........iija", -- 7 "aaaa........iija", -- 8 "a..b........iija", -- 9 "a..b........iija", -- 10 "a...........ggga", -- 11 "a..............a", -- 12 "a..............a", -- 13 "aaaaaaaaaaaaaaaa", -- 14 -- Level 6 "aaaaaaaaaaaaaaaa", -- 0 "a.............ga", -- 1 "a............iia", -- 2 "a..............a", -- 3 "a..............a", -- 4 "a..b...........a", -- 5 "...b...........a", -- 6 "...b...........a", -- 7 "...b...........a", -- 8 "a..b...........a", -- 9 "a..............a", -- 10 "a..............a", -- 11 "a............iia", -- 12 "a.............ga", -- 13 "aaaaaaaaaaaaaaaa", -- 14 -- Level 7 "aaaaaaaaaaaaaaaa", -- 0 "a..............a", -- 1 "a..............a", -- 2 "a..............a", -- 3 "a..............a", -- 4 "a..............a", -- 5 "...............a", -- 6 "...............a", -- 7 "...............a", -- 8 "a..............a", -- 9 "a..............a", -- 10 "a..............a", -- 11 "a..............a", -- 12 "a..............a", -- 13 "aaaaaaaaaaaaaaaa", -- 14 -- Level 8 "aaaaaaaaaaaaaaaa", -- 0 "a..............a", -- 1 "a..............a", -- 2 "a..............a", -- 3 "a..............a", -- 4 "a..............a", -- 5 "...............a", -- 6 "...............a", -- 7 "...............a", -- 8 "a..............a", -- 9 "a..............a", -- 10 "a..............a", -- 11 "a..............a", -- 12 "a..............a", -- 13 "aaaaaaaaaaaaaaaa", -- 14 -- Level 9 "aaaaaaaaaaaaaaaa", -- 0 "a..............a", -- 1 "a..............a", -- 2 "a..............a", -- 3 "a..............a", -- 4 "a..............a", -- 5 "a..............a", -- 6 "a..............a", -- 7 "a..............a", -- 8 "a..............a", -- 9 "a..............a", -- 10 "a..............a", -- 11 "a..............a", -- 12 "a..............a", -- 13 "aaaaaaaaaaaaaaaa", -- 14 -- Level 10 "aaaaaaaaaaaaaaaa", -- 0 "aaaaaaaaaaaaaaaa", -- 1 "aaaaaaaaaaaaaaaa", -- 2 "aaaaaaaaaaaaaaaa", -- 3 "aaaaaaaaaaaaaaaa", -- 4 "aaaaaaaaaaaaaaaa", -- 5 "aaaaaaaaaaaaaaaa", -- 6 "aaaaaaaaaaaaaaaa", -- 7 "aaaaaaaaaaaaaaaa", -- 8 "aaaaaaaaaaaaaaaa", -- 9 "aaaaaaaaaaaaaaaa", -- 10 "aaaaaaaaaaaaaaaa", -- 11 "aaaaaaaaaaaaaaaa", -- 12 "aaaaaaaaaaaaaaaa", -- 13 "aaaaaaaaaaaaaaaa", -- 14 -- Level 11 "abbaabbaabbaabba", -- 0 "b..............b", -- 1 "a..............a", -- 2 "b..............b", -- 3 "a..............a", -- 4 "b..............b", -- 5 "a..............a", -- 6 "b..............b", -- 7 "a..............a", -- 8 "b..............b", -- 9 "a..............a", -- 10 "b..............b", -- 11 "a..............a", -- 12 "b..............b", -- 13 "abbaabbaabbaabba", -- 14 }, }, -- LavaStairsBridge { OriginData = { ExportName = "LavaStaircaseBig", Name = "Nether 31", GalleryName = "Nether", GalleryIndex = "31", ID = "282", CreatorName = "STR_Warrior", }, Size = { x = 12, y = 15, z = 15, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 11, MaxY = 14, MaxZ = 14, }, Connectors = { { Type = 1, RelX = 11, RelY = 1, RelZ = 7, Direction = 5, -- X+ }, { Type = 1, RelX = 0, RelY = 9, RelZ = 7, Direction = 4, -- X- }, { Type = -1, RelX = 11, RelY = 1, RelZ = 7, Direction = 5, -- X+ }, { Type = -1, RelX = 0, RelY = 9, RelZ = 7, Direction = 4, -- X- }, }, Metadata = { ["AddWeightIfSame"] = "-1000", ["AllowedRotations"] = "7", ["DefaultWeight"] = "10", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a:112: 0", -- netherbrickblock "b: 10: 0", -- lava "c:113: 0", -- netherbrickfence "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "aaaaaaaaaaaa", -- 0 "aaaaaaaaaaaa", -- 1 "aaaaaaaaaaaa", -- 2 "aaaaaaaaaaaa", -- 3 "aaaaaaaaaaaa", -- 4 "aaaaaaaaaaaa", -- 5 "aaaaaaaaaaaa", -- 6 "aaaaaaaaaaaa", -- 7 "aaaaaaaaaaaa", -- 8 "aaaaaaaaaaaa", -- 9 "aaaaaaaaaaaa", -- 10 "aaaaaaaaaaaa", -- 11 "aaaaaaaaaaaa", -- 12 "aaaaaaaaaaaa", -- 13 "aaaaaaaaaaaa", -- 14 -- Level 1 "aaaaaaaaaaaa", -- 0 "aaaaaaaaaaaa", -- 1 "aaaaaaaaaaaa", -- 2 "aaaaaaaaaaaa", -- 3 "abbbbbaaaaaa", -- 4 "abbbbbbaaaaa", -- 5 "abbbbbba....", -- 6 "abbbbbba....", -- 7 "abbbbbba....", -- 8 "abbbbbbaaaaa", -- 9 "abbbbb.aaaaa", -- 10 "aaaaaaaaaaaa", -- 11 "aaaaaaaaaaaa", -- 12 "aaaaaaaaaaaa", -- 13 "aaaaaaaaaaaa", -- 14 -- Level 2 "aaaaaaaaaaaa", -- 0 "aaaaaaaaaaaa", -- 1 "aaaaaaaaaaaa", -- 2 "aaaaaaaaaaaa", -- 3 "abbbbbaaaaaa", -- 4 "abbbbbba...a", -- 5 "abbbbbba....", -- 6 "abbbbbba....", -- 7 "abbbbbba....", -- 8 "abbbbbba...a", -- 9 "abbbbb.aaaaa", -- 10 "aaaaaaaaaaaa", -- 11 "aaaaaaaaaaaa", -- 12 "aaaaaaaaaaaa", -- 13 "aaaaaaaaaaaa", -- 14 -- Level 3 "aaaaaaaaaaaa", -- 0 "aaaaaaaaaaaa", -- 1 "aaaaaaaaaaaa", -- 2 "aaaaaaaaaaaa", -- 3 "abbbbbaa...a", -- 4 "abbbbbba...a", -- 5 "abbbbbba....", -- 6 "abbbbbba....", -- 7 "abbbbbba....", -- 8 "abbbbbba...a", -- 9 "abbbbbaa...a", -- 10 "aaaaaaaaaaaa", -- 11 "aaaaaaaaaaaa", -- 12 "aaaaaaaaaaaa", -- 13 "aaaaaaaaaaaa", -- 14 -- Level 4 "aaaaaaaaaaaa", -- 0 "aaaaa......a", -- 1 "aaaaa......a", -- 2 "aaaaacc....a", -- 3 "a.....cc...a", -- 4 "a......c...a", -- 5 "a......c...a", -- 6 "a......c...a", -- 7 "a......c...a", -- 8 "a......c...a", -- 9 "a.....cc...a", -- 10 "aaaaacc....a", -- 11 "aaaaa......a", -- 12 "aaaaa......a", -- 13 "aaaaaaaaaaaa", -- 14 -- Level 5 "aaaaaaaaaaaa", -- 0 "aaaa.......a", -- 1 "aaaa.......a", -- 2 "aaaacc.....a", -- 3 "aaaa.......a", -- 4 "a..........a", -- 5 "a..........a", -- 6 "a..........a", -- 7 "a..........a", -- 8 "a..........a", -- 9 "aaaa.......a", -- 10 "aaaacc.....a", -- 11 "aaaa.......a", -- 12 "aaaa.......a", -- 13 "aaaaaaaaaaaa", -- 14 -- Level 6 "aaaaaaaaaaaa", -- 0 "a..........a", -- 1 "a..........a", -- 2 "a..cc......a", -- 3 "aaaa.......a", -- 4 "aaaa.......a", -- 5 "a..........a", -- 6 "a..........a", -- 7 "a..........a", -- 8 "aaaa.......a", -- 9 "aaaa.......a", -- 10 "a..cc......a", -- 11 "a..........a", -- 12 "a..........a", -- 13 "aaaaaaaaaaaa", -- 14 -- Level 7 "aaaaaaaaaaaa", -- 0 "a..........a", -- 1 "a..........a", -- 2 "a..c.......a", -- 3 "a..c.......a", -- 4 "aaaa.......a", -- 5 "aaaa.......a", -- 6 "a..........a", -- 7 "aaaa.......a", -- 8 "aaaa.......a", -- 9 "a..c.......a", -- 10 "a..c.......a", -- 11 "a..........a", -- 12 "a..........a", -- 13 "aaaaaaaaaaaa", -- 14 -- Level 8 "aaaaaaaaaaaa", -- 0 "a..........a", -- 1 "a..........a", -- 2 "a..........a", -- 3 "a..c.......a", -- 4 "a..c.......a", -- 5 "aaaa.......a", -- 6 "aaaa.......a", -- 7 "aaaa.......a", -- 8 "a..c.......a", -- 9 "a..c.......a", -- 10 "a..........a", -- 11 "a..........a", -- 12 "a..........a", -- 13 "aaaaaaaaaaaa", -- 14 -- Level 9 "aaaaaaaaaaaa", -- 0 "a..........a", -- 1 "a..........a", -- 2 "a..........a", -- 3 "a..........a", -- 4 "a..c.......a", -- 5 "...c.......a", -- 6 "...c.......a", -- 7 "...c.......a", -- 8 "a..c.......a", -- 9 "a..........a", -- 10 "a..........a", -- 11 "a..........a", -- 12 "a..........a", -- 13 "aaaaaaaaaaaa", -- 14 -- Level 10 "aaaaaaaaaaaa", -- 0 "a..........a", -- 1 "a..........a", -- 2 "a..........a", -- 3 "a..........a", -- 4 "a..........a", -- 5 "...........a", -- 6 "...........a", -- 7 "...........a", -- 8 "a..........a", -- 9 "a..........a", -- 10 "a..........a", -- 11 "a..........a", -- 12 "a..........a", -- 13 "aaaaaaaaaaaa", -- 14 -- Level 11 "aaaaaaaaaaaa", -- 0 "a..........a", -- 1 "a..........a", -- 2 "a..........a", -- 3 "a..........a", -- 4 "a..........a", -- 5 "...........a", -- 6 "...........a", -- 7 "...........a", -- 8 "a..........a", -- 9 "a..........a", -- 10 "a..........a", -- 11 "a..........a", -- 12 "a..........a", -- 13 "aaaaaaaaaaaa", -- 14 -- Level 12 "aaaaaaaaaaaa", -- 0 "a..........a", -- 1 "a..........a", -- 2 "a..........a", -- 3 "a..........a", -- 4 "a..........a", -- 5 "a..........a", -- 6 "a..........a", -- 7 "a..........a", -- 8 "a..........a", -- 9 "a..........a", -- 10 "a..........a", -- 11 "a..........a", -- 12 "a..........a", -- 13 "aaaaaaaaaaaa", -- 14 -- Level 13 "aaaaaaaaaaaa", -- 0 "aaaaaaaaaaaa", -- 1 "aaaaaaaaaaaa", -- 2 "aaaaaaaaaaaa", -- 3 "aaaaaaaaaaaa", -- 4 "aaaaaaaaaaaa", -- 5 "aaaaaaaaaaaa", -- 6 "aaaaaaaaaaaa", -- 7 "aaaaaaaaaaaa", -- 8 "aaaaaaaaaaaa", -- 9 "aaaaaaaaaaaa", -- 10 "aaaaaaaaaaaa", -- 11 "aaaaaaaaaaaa", -- 12 "aaaaaaaaaaaa", -- 13 "aaaaaaaaaaaa", -- 14 -- Level 14 "aaaaaaaaaaaa", -- 0 "abbbbbbbbbba", -- 1 "abbbbbbbbbba", -- 2 "abbbbbbbbbba", -- 3 "abbbbbbbbbba", -- 4 "abbbbbbbbbba", -- 5 "abbbbbbbbbba", -- 6 "abbbbbbbbbba", -- 7 "abbbbbbbbbba", -- 8 "abbbbbbbbbba", -- 9 "abbbbbbbbbba", -- 10 "abbbbbbbbbba", -- 11 "abbbbbbbbbba", -- 12 "abbbbbbbbbba", -- 13 "aaaaaaaaaaaa", -- 14 }, }, -- LavaStaircaseBig { OriginData = { ExportName = "Corridor13", Name = "Nether 35", GalleryName = "Nether", GalleryIndex = "35", ID = "286", CreatorName = "Aloe_vera", }, Size = { x = 13, y = 6, z = 5, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 12, MaxY = 5, MaxZ = 4, }, Connectors = { { Type = 1, RelX = 12, RelY = 1, RelZ = 2, Direction = 5, -- X+ }, { Type = 1, RelX = 0, RelY = 1, RelZ = 2, Direction = 4, -- X- }, { Type = -1, RelX = 12, RelY = 1, RelZ = 2, Direction = 5, -- X+ }, { Type = -1, RelX = 0, RelY = 1, RelZ = 2, Direction = 4, -- X- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "300", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a:112: 0", -- netherbrickblock "b:113: 0", -- netherbrickfence "c:114: 2", -- netherbrickstairs "d:114: 3", -- netherbrickstairs "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "aaaaaaaaaaaaa", -- 0 "aaaaaaaaaaaaa", -- 1 "aaaaaaaaaaaaa", -- 2 "aaaaaaaaaaaaa", -- 3 "aaaaaaaaaaaaa", -- 4 -- Level 1 "aaaaaaaaaaaaa", -- 0 ".............", -- 1 ".............", -- 2 ".............", -- 3 "aaaaaaaaaaaaa", -- 4 -- Level 2 "ababababababa", -- 0 ".............", -- 1 ".............", -- 2 ".............", -- 3 "ababababababa", -- 4 -- Level 3 "ababababababa", -- 0 ".............", -- 1 ".............", -- 2 ".............", -- 3 "ababababababa", -- 4 -- Level 4 "ababababababa", -- 0 ".............", -- 1 ".............", -- 2 ".............", -- 3 "ababababababa", -- 4 -- Level 5 "ccccccccccccc", -- 0 "aaaaaaaaaaaaa", -- 1 "aaaaaaaaaaaaa", -- 2 "aaaaaaaaaaaaa", -- 3 "ddddddddddddd", -- 4 }, }, -- Corridor13 { OriginData = { ExportName = "Corridor11", Name = "Nether 36", GalleryName = "Nether", GalleryIndex = "36", ID = "287", CreatorName = "Aloe_vera", }, Size = { x = 11, y = 6, z = 5, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 10, MaxY = 5, MaxZ = 4, }, Connectors = { { Type = 1, RelX = 10, RelY = 1, RelZ = 2, Direction = 5, -- X+ }, { Type = 1, RelX = 0, RelY = 1, RelZ = 2, Direction = 4, -- X- }, { Type = -1, RelX = 10, RelY = 1, RelZ = 2, Direction = 5, -- X+ }, { Type = -1, RelX = 0, RelY = 1, RelZ = 2, Direction = 4, -- X- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "300", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a:112: 0", -- netherbrickblock "b:113: 0", -- netherbrickfence "c:114: 2", -- netherbrickstairs "d:114: 3", -- netherbrickstairs "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "aaaaaaaaaaa", -- 0 "aaaaaaaaaaa", -- 1 "aaaaaaaaaaa", -- 2 "aaaaaaaaaaa", -- 3 "aaaaaaaaaaa", -- 4 -- Level 1 "aaaaaaaaaaa", -- 0 "...........", -- 1 "...........", -- 2 "...........", -- 3 "aaaaaaaaaaa", -- 4 -- Level 2 "abababababa", -- 0 "...........", -- 1 "...........", -- 2 "...........", -- 3 "abababababa", -- 4 -- Level 3 "abababababa", -- 0 "...........", -- 1 "...........", -- 2 "...........", -- 3 "abababababa", -- 4 -- Level 4 "abababababa", -- 0 "...........", -- 1 "...........", -- 2 "...........", -- 3 "abababababa", -- 4 -- Level 5 "ccccccccccc", -- 0 "aaaaaaaaaaa", -- 1 "aaaaaaaaaaa", -- 2 "aaaaaaaaaaa", -- 3 "ddddddddddd", -- 4 }, }, -- Corridor11 { OriginData = { ExportName = "BalconyCorridor", Name = "Nether 37", GalleryName = "Nether", GalleryIndex = "37", ID = "288", CreatorName = "Aloe_vera", }, Size = { x = 13, y = 7, z = 9, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 12, MaxY = 6, MaxZ = 8, }, Connectors = { { Type = 1, RelX = 12, RelY = 2, RelZ = 2, Direction = 5, -- X+ }, { Type = 1, RelX = 0, RelY = 2, RelZ = 2, Direction = 4, -- X- }, { Type = -1, RelX = 12, RelY = 2, RelZ = 2, Direction = 5, -- X+ }, { Type = -1, RelX = 0, RelY = 2, RelZ = 2, Direction = 4, -- X- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "20", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a:112: 0", -- netherbrickblock "b:114: 4", -- netherbrickstairs "c:114: 7", -- netherbrickstairs "d:114: 5", -- netherbrickstairs "e: 44: 6", -- stone_slab "f:113: 0", -- netherbrickfence "g:114: 2", -- netherbrickstairs "h:114: 3", -- netherbrickstairs "i:114: 0", -- netherbrickstairs "j:114: 1", -- netherbrickstairs "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "aaaaaaaaaaaaa", -- 0 "aaaaaaaaaaaaa", -- 1 "aaaaaaaaaaaaa", -- 2 "aaaaaaaaaaaaa", -- 3 "aaaaaaaaaaaaa", -- 4 "mmmmaaaaammmm", -- 5 "mmmmmmmmmmmmm", -- 6 "mmmmmmmmmmmmm", -- 7 "mmmmmmmmmmmmm", -- 8 -- Level 1 "aaaaaaaaaaaaa", -- 0 "aaaaaaaaaaaaa", -- 1 "aaaaaaaaaaaaa", -- 2 "aaaaaaaaaaaaa", -- 3 "aaaa.aaa.aaaa", -- 4 "mmbcaaaaacdmm", -- 5 "mmmbcccccdmmm", -- 6 "mmmmmmmmmmmmm", -- 7 "mmmmmmmmmmmmm", -- 8 -- Level 2 "aaaaaaaaaaaaa", -- 0 ".............", -- 1 ".............", -- 2 ".............", -- 3 "aaaa.eee.aaaa", -- 4 "mmaaaaaaaaamm", -- 5 "mmaaaaaaaaamm", -- 6 "mmaaaaaaaaamm", -- 7 "mmaaaaaaaaamm", -- 8 -- Level 3 "afafafafafafa", -- 0 ".............", -- 1 ".............", -- 2 ".............", -- 3 "afaa.....aafa", -- 4 "mmaaa...aaamm", -- 5 "mmf.......fmm", -- 6 "mmf.......fmm", -- 7 "mmfffffffffmm", -- 8 -- Level 4 "afafafafafafa", -- 0 ".............", -- 1 ".............", -- 2 ".............", -- 3 "afaa.....aafa", -- 4 "mmaaa...aaamm", -- 5 "mm.........mm", -- 6 "mm.........mm", -- 7 "mm.........mm", -- 8 -- Level 5 "afafafafafafa", -- 0 ".............", -- 1 ".............", -- 2 ".............", -- 3 "afaa.....aafa", -- 4 "mmaaa...aaamm", -- 5 "mm.........mm", -- 6 "mm.........mm", -- 7 "mm.........mm", -- 8 -- Level 6 "ggggggggggggg", -- 0 "aaaaaaaaaaaaa", -- 1 "aaaaaaaaaaaaa", -- 2 "aaaaaaaaaaaaa", -- 3 "hhiaaaaaaahhh", -- 4 "mmihhhhhhhjmm", -- 5 "mmmmmmmmmmmmm", -- 6 "mmmmmmmmmmmmm", -- 7 "mmmmmmmmmmmmm", -- 8 }, }, -- BalconyCorridor { OriginData = { ExportName = "BalconyTee2", Name = "Nether 38", GalleryName = "Nether", GalleryIndex = "38", ID = "289", CreatorName = "Aloe_vera", }, Size = { x = 13, y = 7, z = 11, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 12, MaxY = 6, MaxZ = 10, }, Connectors = { { Type = 1, RelX = 12, RelY = 2, RelZ = 4, Direction = 5, -- X+ }, { Type = 1, RelX = 6, RelY = 2, RelZ = 0, Direction = 2, -- Z- }, { Type = 1, RelX = 0, RelY = 2, RelZ = 4, Direction = 4, -- X- }, { Type = -1, RelX = 12, RelY = 2, RelZ = 4, Direction = 5, -- X+ }, { Type = -1, RelX = 6, RelY = 2, RelZ = 0, Direction = 2, -- Z- }, { Type = -1, RelX = 0, RelY = 2, RelZ = 4, Direction = 4, -- X- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "20", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a:112: 0", -- netherbrickblock "b:114: 4", -- netherbrickstairs "c:114: 7", -- netherbrickstairs "d:114: 5", -- netherbrickstairs "e: 44: 6", -- stone_slab "f:113: 0", -- netherbrickfence "g:114: 0", -- netherbrickstairs "h:114: 1", -- netherbrickstairs "i:114: 2", -- netherbrickstairs "j:114: 3", -- netherbrickstairs "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "mmmmaaaaammmm", -- 0 "mmmmaaaaammmm", -- 1 "aaaaaaaaaaaaa", -- 2 "aaaaaaaaaaaaa", -- 3 "aaaaaaaaaaaaa", -- 4 "aaaaaaaaaaaaa", -- 5 "aaaaaaaaaaaaa", -- 6 "mmmmaaaaammmm", -- 7 "mmmmmmmmmmmmm", -- 8 "mmmmmmmmmmmmm", -- 9 "mmmmmmmmmmmmm", -- 10 -- Level 1 "mmmmaaaaammmm", -- 0 "mmmmaaaaammmm", -- 1 "aaaaaaaaaaaaa", -- 2 "aaaaaaaaaaaaa", -- 3 "aaaaaaaaaaaaa", -- 4 "aaaaaaaaaaaaa", -- 5 "aaaa.aaa.aaaa", -- 6 "mmbcaaaaacdmm", -- 7 "mmmbcccccdmmm", -- 8 "mmmmmmmmmmmmm", -- 9 "mmmmmmmmmmmmm", -- 10 -- Level 2 "mmmma...ammmm", -- 0 "mmmma...ammmm", -- 1 "aaaaa...aaaaa", -- 2 ".............", -- 3 ".............", -- 4 ".............", -- 5 "aaaa.eee.aaaa", -- 6 "mmaaaaaaaaamm", -- 7 "mmaaaaaaaaamm", -- 8 "mmaaaaaaaaamm", -- 9 "mmaaaaaaaaamm", -- 10 -- Level 3 "mmmma...ammmm", -- 0 "mmmmf...fmmmm", -- 1 "afafa...afafa", -- 2 ".............", -- 3 ".............", -- 4 ".............", -- 5 "afaa.....aafa", -- 6 "mmaaa...aaamm", -- 7 "mmf.......fmm", -- 8 "mmf.......fmm", -- 9 "mmfffffffffmm", -- 10 -- Level 4 "mmmma...ammmm", -- 0 "mmmmf...fmmmm", -- 1 "afafa...afafa", -- 2 ".............", -- 3 ".............", -- 4 ".............", -- 5 "afaa.....aafa", -- 6 "mmaaa...aaamm", -- 7 "mm.........mm", -- 8 "mm.........mm", -- 9 "mm.........mm", -- 10 -- Level 5 "mmmma...ammmm", -- 0 "mmmmf...fmmmm", -- 1 "afafa...afafa", -- 2 ".............", -- 3 ".............", -- 4 ".............", -- 5 "afaa.....aafa", -- 6 "mmaaa...aaamm", -- 7 "mm.........mm", -- 8 "mm.........mm", -- 9 "mm.........mm", -- 10 -- Level 6 "mmmmgaaahmmmm", -- 0 "mmmmgaaahmmmm", -- 1 "iiiiiaaaiiiii", -- 2 "aaaaaaaaaaaaa", -- 3 "aaaaaaaaaaaaa", -- 4 "aaaaaaaaaaaaa", -- 5 "jjgaaaaaaajjj", -- 6 "mmgjjjjjjjhmm", -- 7 "mmmmmmmmmmmmm", -- 8 "mmmmmmmmmmmmm", -- 9 "mmmmmmmmmmmmm", -- 10 }, }, -- BalconyTee2 { OriginData = { ExportName = "BridgeTee", Name = "Nether 39", GalleryName = "Nether", GalleryIndex = "39", ID = "290", CreatorName = "STR_Warrior", }, Size = { x = 15, y = 8, z = 10, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 14, MaxY = 17, MaxZ = 9, }, Connectors = { { Type = 0, RelX = 0, RelY = 5, RelZ = 2, Direction = 4, -- X- }, { Type = 0, RelX = 7, RelY = 5, RelZ = 9, Direction = 3, -- Z+ }, { Type = 0, RelX = 14, RelY = 5, RelZ = 2, Direction = 5, -- X+ }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "10", ["DepthWeight"] = "1:500", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a:112: 0", -- netherbrickblock "b:114: 5", -- netherbrickstairs "c:114: 4", -- netherbrickstairs "d:114: 6", -- netherbrickstairs "e: 44:14", -- stone_slab "f:114: 7", -- netherbrickstairs "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "mmmmmmmmmmmmmmm", -- 0 "aammmmmmmmmmmaa", -- 1 "aammmmmmmmmmmaa", -- 2 "aammmmmmmmmmmaa", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmmmmmmmmm", -- 5 "mmmmmmmmmmmmmmm", -- 6 "mmmmmmmmmmmmmmm", -- 7 "mmmmmmaaammmmmm", -- 8 "mmmmmmaaammmmmm", -- 9 -- Level 1 "mmmmmmmmmmmmmmm", -- 0 "aabmmmmmmmmmcaa", -- 1 "aabmmmmmmmmmcaa", -- 2 "aabmmmmmmmmmcaa", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmmmmmmmmm", -- 5 "mmmmmmmmmmmmmmm", -- 6 "mmmmmmdddmmmmmm", -- 7 "mmmmmmaaammmmmm", -- 8 "mmmmmmaaammmmmm", -- 9 -- Level 2 "mmmmmmmmmmmmmmm", -- 0 "aaabemmmmmecaaa", -- 1 "aaabemmmmmecaaa", -- 2 "aaabemmmmmecaaa", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmeeemmmmmm", -- 5 "mmmmmmdddmmmmmm", -- 6 "mmmmmmaaammmmmm", -- 7 "mmmmmmaaammmmmm", -- 8 "mmmmmmaaammmmmm", -- 9 -- Level 3 "ddddddddddddddd", -- 0 "aaaaaaaaaaaaaaa", -- 1 "aaaaaaaaaaaaaaa", -- 2 "aaaaaaaaaaaaaaa", -- 3 "fffffcaaabfffff", -- 4 "mmmmmcaaabmmmmm", -- 5 "mmmmmcaaabmmmmm", -- 6 "mmmmmcaaabmmmmm", -- 7 "mmmmmcaaabmmmmm", -- 8 "mmmmmcaaabmmmmm", -- 9 -- Level 4 "aaaaaaaaaaaaaaa", -- 0 "aaaaaaaaaaaaaaa", -- 1 "aaaaaaaaaaaaaaa", -- 2 "aaaaaaaaaaaaaaa", -- 3 "aaaaaaaaaaaaaaa", -- 4 "mmmmmaaaaammmmm", -- 5 "mmmmmaaaaammmmm", -- 6 "mmmmmaaaaammmmm", -- 7 "mmmmmaaaaammmmm", -- 8 "mmmmmaaaaammmmm", -- 9 -- Level 5 "aaaaaaaaaaaaaaa", -- 0 "...............", -- 1 "...............", -- 2 "...............", -- 3 "aaaaaa...aaaaaa", -- 4 "mmmmma...ammmmm", -- 5 "mmmmma...ammmmm", -- 6 "mmmmma...ammmmm", -- 7 "mmmmma...ammmmm", -- 8 "mmmmma...ammmmm", -- 9 -- Level 6 "mmmmmmmmmmmmmmm", -- 0 "...............", -- 1 "...............", -- 2 "...............", -- 3 "mmmmmm...mmmmmm", -- 4 "mmmmmm...mmmmmm", -- 5 "mmmmmm...mmmmmm", -- 6 "mmmmmm...mmmmmm", -- 7 "mmmmmm...mmmmmm", -- 8 "mmmmmm...mmmmmm", -- 9 -- Level 7 "mmmmmmmmmmmmmmm", -- 0 "...............", -- 1 "...............", -- 2 "...............", -- 3 "mmmmmm...mmmmmm", -- 4 "mmmmmm...mmmmmm", -- 5 "mmmmmm...mmmmmm", -- 6 "mmmmmm...mmmmmm", -- 7 "mmmmmm...mmmmmm", -- 8 "mmmmmm...mmmmmm", -- 9 }, }, -- BridgeTee { OriginData = { ExportName = "Tee2x4", Name = "Nether 40", GalleryName = "Nether", GalleryIndex = "40", ID = "291", CreatorName = "Aloe_vera", }, Size = { x = 13, y = 6, z = 7, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 12, MaxY = 5, MaxZ = 6, }, Connectors = { { Type = 1, RelX = 0, RelY = 1, RelZ = 4, Direction = 4, -- X- }, { Type = 1, RelX = 6, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, { Type = 1, RelX = 12, RelY = 1, RelZ = 4, Direction = 5, -- X+ }, { Type = -1, RelX = 0, RelY = 1, RelZ = 4, Direction = 4, -- X- }, { Type = -1, RelX = 12, RelY = 1, RelZ = 4, Direction = 5, -- X+ }, { Type = -1, RelX = 6, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a:112: 0", -- netherbrickblock "b:113: 0", -- netherbrickfence "c:114: 0", -- netherbrickstairs "d:114: 1", -- netherbrickstairs "e:114: 2", -- netherbrickstairs "f:114: 3", -- netherbrickstairs "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "mmmmaaaaammmm", -- 0 "mmmmaaaaammmm", -- 1 "aaaaaaaaaaaaa", -- 2 "aaaaaaaaaaaaa", -- 3 "aaaaaaaaaaaaa", -- 4 "aaaaaaaaaaaaa", -- 5 "aaaaaaaaaaaaa", -- 6 -- Level 1 "mmmma...ammmm", -- 0 "mmmma...ammmm", -- 1 "aaaaa...aaaaa", -- 2 ".............", -- 3 ".............", -- 4 ".............", -- 5 "aaaaaaaaaaaaa", -- 6 -- Level 2 "mmmma...ammmm", -- 0 "mmmmb...bmmmm", -- 1 "ababa...ababa", -- 2 ".............", -- 3 ".............", -- 4 ".............", -- 5 "ababababababa", -- 6 -- Level 3 "mmmma...ammmm", -- 0 "mmmmb...bmmmm", -- 1 "ababa...ababa", -- 2 ".............", -- 3 ".............", -- 4 ".............", -- 5 "ababababababa", -- 6 -- Level 4 "mmmma...ammmm", -- 0 "mmmmb...bmmmm", -- 1 "ababa...ababa", -- 2 ".............", -- 3 ".............", -- 4 ".............", -- 5 "ababababababa", -- 6 -- Level 5 "mmmmcaaadmmmm", -- 0 "mmmmcaaadmmmm", -- 1 "eeeecaaadeeee", -- 2 "aaaaaaaaaaaaa", -- 3 "aaaaaaaaaaaaa", -- 4 "aaaaaaaaaaaaa", -- 5 "fffffffffffff", -- 6 }, }, -- Tee2x4 { OriginData = { ExportName = "Tee4x4", Name = "Nether 41", GalleryName = "Nether", GalleryIndex = "41", ID = "292", CreatorName = "Aloe_vera", }, Size = { x = 13, y = 6, z = 9, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 12, MaxY = 5, MaxZ = 8, }, Connectors = { { Type = 1, RelX = 0, RelY = 1, RelZ = 6, Direction = 4, -- X- }, { Type = 1, RelX = 6, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, { Type = 1, RelX = 12, RelY = 1, RelZ = 6, Direction = 5, -- X+ }, { Type = -1, RelX = 0, RelY = 1, RelZ = 6, Direction = 4, -- X- }, { Type = -1, RelX = 6, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, { Type = -1, RelX = 12, RelY = 1, RelZ = 6, Direction = 5, -- X+ }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a:112: 0", -- netherbrickblock "b:113: 0", -- netherbrickfence "c:114: 0", -- netherbrickstairs "d:114: 1", -- netherbrickstairs "e:114: 2", -- netherbrickstairs "f:114: 3", -- netherbrickstairs "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "mmmmaaaaammmm", -- 0 "mmmmaaaaammmm", -- 1 "mmmmaaaaammmm", -- 2 "mmmmaaaaammmm", -- 3 "aaaaaaaaaaaaa", -- 4 "aaaaaaaaaaaaa", -- 5 "aaaaaaaaaaaaa", -- 6 "aaaaaaaaaaaaa", -- 7 "aaaaaaaaaaaaa", -- 8 -- Level 1 "mmmma...ammmm", -- 0 "mmmma...ammmm", -- 1 "mmmma...ammmm", -- 2 "mmmma...ammmm", -- 3 "aaaaa...aaaaa", -- 4 ".............", -- 5 ".............", -- 6 ".............", -- 7 "aaaaaaaaaaaaa", -- 8 -- Level 2 "mmmma...ammmm", -- 0 "mmmmb...bmmmm", -- 1 "mmmma...ammmm", -- 2 "mmmmb...bmmmm", -- 3 "ababa...ababa", -- 4 ".............", -- 5 ".............", -- 6 ".............", -- 7 "ababababababa", -- 8 -- Level 3 "mmmma...ammmm", -- 0 "mmmmb...bmmmm", -- 1 "mmmma...ammmm", -- 2 "mmmmb...bmmmm", -- 3 "ababa...ababa", -- 4 ".............", -- 5 ".............", -- 6 ".............", -- 7 "ababababababa", -- 8 -- Level 4 "mmmma...ammmm", -- 0 "mmmmb...bmmmm", -- 1 "mmmma...ammmm", -- 2 "mmmmb...bmmmm", -- 3 "ababa...ababa", -- 4 ".............", -- 5 ".............", -- 6 ".............", -- 7 "ababababababa", -- 8 -- Level 5 "mmmmcaaadmmmm", -- 0 "mmmmcaaadmmmm", -- 1 "mmmmcaaadmmmm", -- 2 "mmmmcaaadmmmm", -- 3 "eeeecaaadeeee", -- 4 "aaaaaaaaaaaaa", -- 5 "aaaaaaaaaaaaa", -- 6 "aaaaaaaaaaaaa", -- 7 "fffffffffffff", -- 8 }, }, -- Tee4x4 { OriginData = { ExportName = "CorridorCornerChest5", Name = "Nether 42", GalleryName = "Nether", GalleryIndex = "42", ID = "293", CreatorName = "STR_Warrior", }, Size = { x = 11, y = 6, z = 11, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 10, MaxY = 5, MaxZ = 10, }, Connectors = { { Type = 1, RelX = 10, RelY = 1, RelZ = 2, Direction = 5, -- X+ }, { Type = 1, RelX = 2, RelY = 1, RelZ = 10, Direction = 3, -- Z+ }, { Type = -1, RelX = 2, RelY = 1, RelZ = 10, Direction = 3, -- Z+ }, { Type = -1, RelX = 10, RelY = 1, RelZ = 2, Direction = 5, -- X+ }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a:112: 0", -- netherbrickblock "b: 54: 5", -- chest "c:113: 0", -- netherbrickfence "d:114: 0", -- netherbrickstairs "e:114: 2", -- netherbrickstairs "f:114: 1", -- netherbrickstairs "g:114: 3", -- netherbrickstairs "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "aaaaaaaaaaa", -- 0 "aaaaaaaaaaa", -- 1 "aaaaaaaaaaa", -- 2 "aaaaaaaaaaa", -- 3 "aaaaaaaaaaa", -- 4 "aaaaammmmmm", -- 5 "aaaaammmmmm", -- 6 "aaaaammmmmm", -- 7 "aaaaammmmmm", -- 8 "aaaaammmmmm", -- 9 "aaaaammmmmm", -- 10 -- Level 1 "aaaaaaaaaaa", -- 0 "ab.........", -- 1 "a..........", -- 2 "a..........", -- 3 "a...aaaaaaa", -- 4 "a...ammmmmm", -- 5 "a...ammmmmm", -- 6 "a...ammmmmm", -- 7 "a...ammmmmm", -- 8 "a...ammmmmm", -- 9 "a...ammmmmm", -- 10 -- Level 2 "acacacacaca", -- 0 "c..........", -- 1 "a..........", -- 2 "c..........", -- 3 "a...acacaca", -- 4 "c...cmmmmmm", -- 5 "a...ammmmmm", -- 6 "c...cmmmmmm", -- 7 "a...ammmmmm", -- 8 "c...cmmmmmm", -- 9 "a...ammmmmm", -- 10 -- Level 3 "acacacacaca", -- 0 "c..........", -- 1 "a..........", -- 2 "c..........", -- 3 "a...acacaca", -- 4 "c...cmmmmmm", -- 5 "a...ammmmmm", -- 6 "c...cmmmmmm", -- 7 "a...ammmmmm", -- 8 "c...cmmmmmm", -- 9 "a...ammmmmm", -- 10 -- Level 4 "acacacacaca", -- 0 "c..........", -- 1 "a..........", -- 2 "c..........", -- 3 "a...acacaca", -- 4 "c...cmmmmmm", -- 5 "a...ammmmmm", -- 6 "c...cmmmmmm", -- 7 "a...ammmmmm", -- 8 "c...cmmmmmm", -- 9 "a...ammmmmm", -- 10 -- Level 5 "deeeeeeeeee", -- 0 "daaaaaaaaaa", -- 1 "daaaaaaaaaa", -- 2 "daaaaaaaaaa", -- 3 "daaafgggggg", -- 4 "daaafmmmmmm", -- 5 "daaafmmmmmm", -- 6 "daaafmmmmmm", -- 7 "daaafmmmmmm", -- 8 "daaafmmmmmm", -- 9 "daaafmmmmmm", -- 10 }, }, -- CorridorCornerChest5 { OriginData = { ExportName = "BridgeDoubleCrumble", Name = "Nether 46", GalleryName = "Nether", GalleryIndex = "46", ID = "305", CreatorName = "STR_Warrior", }, Size = { x = 5, y = 7, z = 16, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 4, MaxY = 16, MaxZ = 15, }, Connectors = { { Type = 0, RelX = 2, RelY = 4, RelZ = 0, Direction = 2, -- Z- }, { Type = 0, RelX = 2, RelY = 4, RelZ = 15, Direction = 3, -- Z+ }, }, Metadata = { ["AddWeightIfSame"] = "1000", ["AllowedRotations"] = "7", ["DefaultWeight"] = "10", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a:112: 0", -- netherbrickblock "b:114: 7", -- netherbrickstairs "c:114: 6", -- netherbrickstairs "d:114: 4", -- netherbrickstairs "e:114: 5", -- netherbrickstairs "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "maaam", -- 0 "maaam", -- 1 "mmmmm", -- 2 "mmmmm", -- 3 "mmmmm", -- 4 "mmmmm", -- 5 "mmmmm", -- 6 "mmmmm", -- 7 "mmmmm", -- 8 "mmmmm", -- 9 "mmmmm", -- 10 "mmmmm", -- 11 "mmmmm", -- 12 "mmmmm", -- 13 "maaam", -- 14 "maaam", -- 15 -- Level 1 "maaam", -- 0 "maaam", -- 1 "mbbbm", -- 2 "mmmmm", -- 3 "mmmmm", -- 4 "mmmmm", -- 5 "mmmmm", -- 6 "mmmmm", -- 7 "mmmmm", -- 8 "mmmmm", -- 9 "mmmmm", -- 10 "mmmmm", -- 11 "mmmmm", -- 12 "mcccm", -- 13 "maaam", -- 14 "maaam", -- 15 -- Level 2 "daaae", -- 0 "daaae", -- 1 "daaae", -- 2 "daaae", -- 3 "daaae", -- 4 "mamae", -- 5 "mmmam", -- 6 "mmmmm", -- 7 "mmmmm", -- 8 "mmmmm", -- 9 "mmmae", -- 10 "dmaae", -- 11 "daaae", -- 12 "daaae", -- 13 "daaae", -- 14 "daaae", -- 15 -- Level 3 "aaaaa", -- 0 "aaaaa", -- 1 "aaaaa", -- 2 "aaama", -- 3 "mamaa", -- 4 "mmmmm", -- 5 "mmmmm", -- 6 "mmmmm", -- 7 "mmmmm", -- 8 "mmmmm", -- 9 "mmmma", -- 10 "mmmaa", -- 11 "amaaa", -- 12 "aaaaa", -- 13 "aaaaa", -- 14 "aaaaa", -- 15 -- Level 4 "ammma", -- 0 "ammma", -- 1 "ammma", -- 2 "mmmma", -- 3 "mmmmm", -- 4 "mmmmm", -- 5 "mmmmm", -- 6 "mmmmm", -- 7 "mmmmm", -- 8 "mmmmm", -- 9 "mmmmm", -- 10 "mmmma", -- 11 "mmmmm", -- 12 "ammma", -- 13 "ammma", -- 14 "ammma", -- 15 -- Level 5 "mmmmm", -- 0 "mmmmm", -- 1 "mmmmm", -- 2 "mmmmm", -- 3 "mmmmm", -- 4 "mmmmm", -- 5 "mmmmm", -- 6 "mmmmm", -- 7 "mmmmm", -- 8 "mmmmm", -- 9 "mmmmm", -- 10 "mmmmm", -- 11 "mmmmm", -- 12 "mmmmm", -- 13 "mmmmm", -- 14 "mmmmm", -- 15 -- Level 6 "mmmmm", -- 0 "mmmmm", -- 1 "mmmmm", -- 2 "mmmmm", -- 3 "mmmmm", -- 4 "mmmmm", -- 5 "mmmmm", -- 6 "mmmmm", -- 7 "mmmmm", -- 8 "mmmmm", -- 9 "mmmmm", -- 10 "mmmmm", -- 11 "mmmmm", -- 12 "mmmmm", -- 13 "mmmmm", -- 14 "mmmmm", -- 15 }, }, -- BridgeDoubleCrumble { OriginData = { ExportName = "BridgeCircleCrossing", Name = "Nether 49", GalleryName = "Nether", GalleryIndex = "49", ID = "308", CreatorName = "Aloe_vera", }, Size = { x = 15, y = 8, z = 15, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 14, MaxY = 17, MaxZ = 14, }, Connectors = { { Type = 0, RelX = 0, RelY = 5, RelZ = 7, Direction = 4, -- X- }, { Type = 0, RelX = 7, RelY = 5, RelZ = 0, Direction = 2, -- Z- }, { Type = 0, RelX = 14, RelY = 5, RelZ = 7, Direction = 5, -- X+ }, { Type = 0, RelX = 7, RelY = 5, RelZ = 14, Direction = 3, -- Z+ }, }, Metadata = { ["AddWeightIfSame"] = "-1000", ["AllowedRotations"] = "7", ["DefaultWeight"] = "5", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a:112: 0", -- netherbrickblock "b:114: 7", -- netherbrickstairs "c:114: 5", -- netherbrickstairs "d:114: 4", -- netherbrickstairs "e:114: 6", -- netherbrickstairs "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "mmmmmmaaammmmmm", -- 0 "mmmmmmaaammmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmmmmmmmmm", -- 5 "aammmmmmmmmmmaa", -- 6 "aammmmmmmmmmmaa", -- 7 "aammmmmmmmmmmaa", -- 8 "mmmmmmmmmmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmaaammmmmm", -- 13 "mmmmmmaaammmmmm", -- 14 -- Level 1 "mmmmmmaaammmmmm", -- 0 "mmmmmmaaammmmmm", -- 1 "mmmmmmbbbmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmmmmmmmmm", -- 5 "aacmmmmmmmmmdaa", -- 6 "aacmmmmmmmmmdaa", -- 7 "aacmmmmmmmmmdaa", -- 8 "mmmmmmmmmmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmeeemmmmmm", -- 12 "mmmmmmaaammmmmm", -- 13 "mmmmmmaaammmmmm", -- 14 -- Level 2 "mmmmmmaaammmmmm", -- 0 "mmmmmeaaammmmmm", -- 1 "mmmmmdaaammmmmm", -- 2 "mmmmmdbbbmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mdeemmmmmmmeecm", -- 5 "aaacmmmmmmmdaaa", -- 6 "aaacmmmmmmmdaaa", -- 7 "aaacmmmmmmmdaaa", -- 8 "mdbcmmmmmmmbbcm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmdeeecmmmmm", -- 11 "mmmmmdaaacmmmmm", -- 12 "mmmmmbaaabmmmmm", -- 13 "mmmmmmaaammmmmm", -- 14 -- Level 3 "deeeedaaaceeeec", -- 0 "daaaaaaaaaaaaac", -- 1 "daaaaaaaaaaaaac", -- 2 "daaaaaaaaaaaaac", -- 3 "daaacbbaabdaaac", -- 4 "eaaacmmmmmdaaae", -- 5 "aaaacmmmmmdaaaa", -- 6 "aaaacmmmmmdaaaa", -- 7 "aaaacmmmmmdaaaa", -- 8 "baaacmmmmmdaaab", -- 9 "daaaceeeeedaaac", -- 10 "daaaaaaaaaaaaac", -- 11 "daaaaaaaaaaaaac", -- 12 "daaaaaaaaaaaaac", -- 13 "dbbbbdaaacbbbbb", -- 14 -- Level 4 "aaaaaaaaaaaaaaa", -- 0 "aaaaaaaaaaaaaaa", -- 1 "aaaaaaaaaaaaaaa", -- 2 "aaaaaaaaaaaaaaa", -- 3 "aaaaaaaaaaaaaaa", -- 4 "aaaaammmmmaaaaa", -- 5 "aaaaammmmmaaaaa", -- 6 "aaaaammmmmaaaaa", -- 7 "aaaaammmmmaaaaa", -- 8 "aaaaammmmmaaaaa", -- 9 "aaaaaaaaaaaaaaa", -- 10 "aaaaaaaaaaaaaaa", -- 11 "aaaaaaaaaaaaaaa", -- 12 "aaaaaaaaaaaaaaa", -- 13 "aaaaaaaaaaaaaaa", -- 14 -- Level 5 "aaaaaa...aaaaaa", -- 0 "a.............a", -- 1 "a.............a", -- 2 "a.............a", -- 3 "a...aaaaaaa...a", -- 4 "a...ammmmma...a", -- 5 "....ammmmma....", -- 6 "....ammmmma....", -- 7 "....ammmmma....", -- 8 "a...ammmmma...a", -- 9 "a...aaaaaaa...a", -- 10 "a.............a", -- 11 "a.............a", -- 12 "a.............a", -- 13 "aaaaaa...aaaaaa", -- 14 -- Level 6 "mmmmmm...mmmmmm", -- 0 "m.............m", -- 1 "m.............m", -- 2 "m.............m", -- 3 "m.............m", -- 4 "m....mmmmm....m", -- 5 ".....mmmmm.....", -- 6 ".....mmmmm.....", -- 7 ".....mmmmm.....", -- 8 "m....mmmmm....m", -- 9 "m.............m", -- 10 "m.............m", -- 11 "m.............m", -- 12 "m.............m", -- 13 "mmmmmm...mmmmmm", -- 14 -- Level 7 "mmmmmm...mmmmmm", -- 0 "m.............m", -- 1 "m.............m", -- 2 "m.............m", -- 3 "m.............m", -- 4 "m....mmmmm....m", -- 5 ".....mmmmm.....", -- 6 ".....mmmmm.....", -- 7 ".....mmmmm.....", -- 8 "m....mmmmm....m", -- 9 "m.............m", -- 10 "m.............m", -- 11 "m.............m", -- 12 "m.............m", -- 13 "mmmmmm...mmmmmm", -- 14 }, }, -- BridgeCircleCrossing { OriginData = { ExportName = "BridgeLevelCrossing", Name = "Nether 61", GalleryName = "Nether", GalleryIndex = "61", ID = "321", CreatorName = "Aloe_vera", }, Size = { x = 16, y = 14, z = 16, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 15, MaxY = 23, MaxZ = 15, }, Connectors = { { Type = 0, RelX = 0, RelY = 5, RelZ = 2, Direction = 4, -- X- }, { Type = 0, RelX = 15, RelY = 5, RelZ = 2, Direction = 5, -- X+ }, { Type = 0, RelX = 13, RelY = 11, RelZ = 0, Direction = 2, -- Z- }, { Type = 0, RelX = 13, RelY = 11, RelZ = 15, Direction = 3, -- Z+ }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "20", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a:112: 0", -- netherbrickblock "b:114: 5", -- netherbrickstairs "c:114: 4", -- netherbrickstairs "d: 44:14", -- stone_slab "e:114: 6", -- netherbrickstairs "f:114: 7", -- netherbrickstairs "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "mmmmmmmmmmmmmmmm", -- 0 "aammmmmmmmmmmmaa", -- 1 "aammmmmmmmmmmmaa", -- 2 "aammmmmmmmmmmmaa", -- 3 "mmmmmmmmmmmmmmmm", -- 4 "mmmmmmmmmmmmmmmm", -- 5 "mmmmmmmmmmmmmmmm", -- 6 "mmmmmmmmmmmmmmmm", -- 7 "mmmmmmmmmmmmmmmm", -- 8 "mmmmmmmmmmmmmmmm", -- 9 "mmmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmmm", -- 11 "maaammmmmmmmmmmm", -- 12 "maaammmmmmmmmmmm", -- 13 "maaammmmmmmmaaam", -- 14 "mmmmmmmmmmmmaaam", -- 15 -- Level 1 "mmmmmmmmmmmmmmmm", -- 0 "aabmmmmmmmmmmcaa", -- 1 "aabmmmmmmmmmmcaa", -- 2 "aabmmmmmmmmmmcaa", -- 3 "mmmmmmmmmmmmmmmm", -- 4 "mmmmmmmmmmmmmmmm", -- 5 "mmmmmmmmmmmmmmmm", -- 6 "mmmmmmmmmmmmmmmm", -- 7 "mmmmmmmmmmmmmmmm", -- 8 "mmmmmmmmmmmmmmmm", -- 9 "mmmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmmm", -- 11 "maaammmmmmmmmmmm", -- 12 "maaammmmmmmmmmmm", -- 13 "maaammmmmmmmaaam", -- 14 "mmmmmmmmmmmmaaam", -- 15 -- Level 2 "mmmmmmmmmmmmmmmm", -- 0 "aaabdmmmmmmdcaaa", -- 1 "aaabdmmmmmmdcaaa", -- 2 "aaabdmmmmmmdcaaa", -- 3 "mmmmmmmmmmmmmmmm", -- 4 "mmmmmmmmmmmmmmmm", -- 5 "mmmmmmmmmmmmmmmm", -- 6 "mmmmmmmmmmmmmmmm", -- 7 "mmmmmmmmmmmmmmmm", -- 8 "mmmmmmmmmmmmmmmm", -- 9 "mmmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmmm", -- 11 "maaammmmmmmmmmmm", -- 12 "maaammmmmmmmmmmm", -- 13 "maaammmmmmmmaaam", -- 14 "mmmmmmmmmmmmaaam", -- 15 -- Level 3 "eeeeeeeeeeeeeeee", -- 0 "aaaaaaaaaaaaaaaa", -- 1 "aaaaaaaaaaaaaaaa", -- 2 "aaaaaaaaaaaaaaaa", -- 3 "ffffffffffffffff", -- 4 "mmmmmmmmmmmmmmmm", -- 5 "mmmmmmmmmmmmmmmm", -- 6 "mmmmmmmmmmmmmmmm", -- 7 "mmmmmmmmmmmmmmmm", -- 8 "mmmmmmmmmmmmmmmm", -- 9 "mmmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmmm", -- 11 "maaammmmmmmmmmmm", -- 12 "maaammmmmmmmmmmm", -- 13 "maaammmmmmmmaaam", -- 14 "mmmmmmmmmmmmaaam", -- 15 -- Level 4 "aaaaaaaaaaaaaaaa", -- 0 "aaaaaaaaaaaaaaaa", -- 1 "aaaaaaaaaaaaaaaa", -- 2 "aaaaaaaaaaaaaaaa", -- 3 "aaaaaaaaaaaaaaaa", -- 4 "faaabmmmmmmmmmmm", -- 5 "caaabmmmmmmmmmmm", -- 6 "caaabmmmmmmmmmmm", -- 7 "mmmmmmmmmmmmmmmm", -- 8 "mmmmmmmmmmmmmmmm", -- 9 "mmmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmmm", -- 11 "maaammmmmmmmmmmm", -- 12 "maaammmmmmmmmmmm", -- 13 "maaammmmmmmmaaam", -- 14 "mmmmmmmmmmmmaaam", -- 15 -- Level 5 "aaaaaaaaaaaaaaaa", -- 0 "................", -- 1 "................", -- 2 "................", -- 3 "a...aaaaaaaaaaaa", -- 4 "a...ammmmmmmmmmm", -- 5 "aaaaammmmmmmmmmm", -- 6 "aaaaammmmmmmmmmm", -- 7 "caaabmmmmmmmmmmm", -- 8 "caaabmmmmmmmmmmm", -- 9 "mmmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmmm", -- 11 "maaammmmmmmmmmmm", -- 12 "maaammmmmmmmmmmm", -- 13 "maaammmmmmmmaaam", -- 14 "mmmmmmmmmmmmaaam", -- 15 -- Level 6 "mmmmmmmmmmmmaaam", -- 0 "................", -- 1 "................", -- 2 "................", -- 3 "m...mmmmmmmmaaam", -- 4 "a...ammmmmmmmmmm", -- 5 "a...ammmmmmmmmmm", -- 6 "a...ammmmmmmmmmm", -- 7 "aaaaammmmmmmmmmm", -- 8 "aaaaammmmmmmmmmm", -- 9 "caaabmmmmmmmmmmm", -- 10 "caaabmmmmmmmmmmm", -- 11 "maaabmmmmmmmmmmm", -- 12 "maaabmmmmmmmmmmm", -- 13 "maaafmmmmmmmaaam", -- 14 "mmmmmmmmmmmmaaam", -- 15 -- Level 7 "mmmmmmmmmmmmaaam", -- 0 "................", -- 1 "................", -- 2 "................", -- 3 "m...mmmmmmmmaaam", -- 4 "m...mmmmmmmmmmmm", -- 5 "m...mmmmmmmmmmmm", -- 6 "a...ammmmmmmmmmm", -- 7 "a...ammmmmmmmmmm", -- 8 "a...ammmmmmmmmmm", -- 9 "aaaaammmmmmmmmmm", -- 10 "aaaaaeemmmmmmmmm", -- 11 "caaaaaammmmmmmmm", -- 12 "caaaaaammmmmmmmm", -- 13 "caaaaaammmmmaaam", -- 14 "fffffffmmmmmaaam", -- 15 -- Level 8 "mmmmmmmmmmmmaaam", -- 0 "mmmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmmm", -- 3 "m...mmmmmmmmaaam", -- 4 "m...mmmmmmmmmmmm", -- 5 "m...mmmmmmmmmmmm", -- 6 "m...mmmmmmmmmmmm", -- 7 "m...mmmmmmmmmmmm", -- 8 "a...ammmmmmmmmmm", -- 9 "a...ammmmmmmmmmm", -- 10 "a...aaaeemmmmmmm", -- 11 "a.....aaammmmmmm", -- 12 "a.....aaammmmmmm", -- 13 "a.....aaammmaaam", -- 14 "aaaaaaaffmmmaaam", -- 15 -- Level 9 "mmmmmmmmmmmcaaab", -- 0 "mmmmmmmmmmmcaaab", -- 1 "mmmmmmmmmmmcaaab", -- 2 "mmmmmmmmmmmcaaab", -- 3 "mmmmmmmmmmmcaaab", -- 4 "mmmmmmmmmmmcaaab", -- 5 "m...mmmmmmmcaaab", -- 6 "m...mmmmmmmcaaab", -- 7 "m...mmmmmmmcaaab", -- 8 "m...mmmmmmmcaaab", -- 9 "m...mmmmmmmcaaab", -- 10 "m...maaaaeecaaab", -- 11 "m.......aaaaaaab", -- 12 "m.......aaaaaaab", -- 13 "m.......aaaaaaab", -- 14 "mmmmmaaaafffaaab", -- 15 -- Level 10 "mmmmmmmmmmmaaaaa", -- 0 "mmmmmmmmmmmaaaaa", -- 1 "mmmmmmmmmmmaaaaa", -- 2 "mmmmmmmmmmmaaaaa", -- 3 "mmmmmmmmmmmaaaaa", -- 4 "mmmmmmmmmmmaaaaa", -- 5 "mmmmmmmmmmmaaaaa", -- 6 "mmmmmmmmmmmaaaaa", -- 7 "m...mmmmmmmaaaaa", -- 8 "m...mmmmmmmaaaaa", -- 9 "m...mmmmmmmaaaaa", -- 10 "m...mmmaaaaaaaaa", -- 11 "m.........aaaaaa", -- 12 "m.........aaaaaa", -- 13 "m.........aaaaaa", -- 14 "mmmmmmmaaaaaaaaa", -- 15 -- Level 11 "mmmmmmmmmmma...a", -- 0 "mmmmmmmmmmma...a", -- 1 "mmmmmmmmmmma...a", -- 2 "mmmmmmmmmmma...a", -- 3 "mmmmmmmmmmma...a", -- 4 "mmmmmmmmmmma...a", -- 5 "mmmmmmmmmmma...a", -- 6 "mmmmmmmmmmma...a", -- 7 "mmmmmmmmmmma...a", -- 8 "mmmmmmmmmmma...a", -- 9 "mmmmmmmmmmma...a", -- 10 "mmmmmmmmmaaa...a", -- 11 "mmmm...........a", -- 12 "mmmm...........a", -- 13 "mmmm...........a", -- 14 "mmmmmmmmmaaa...a", -- 15 -- Level 12 "mmmmmmmmmmmm...m", -- 0 "mmmmmmmmmmmm...m", -- 1 "mmmmmmmmmmmm...m", -- 2 "mmmmmmmmmmmm...m", -- 3 "mmmmmmmmmmmm...m", -- 4 "mmmmmmmmmmmm...m", -- 5 "mmmmmmmmmmmm...m", -- 6 "mmmmmmmmmmmm...m", -- 7 "mmmmmmmmmmmm...m", -- 8 "mmmmmmmmmmmm...m", -- 9 "mmmmmmmmmmmm...m", -- 10 "mmmmmmmmmmmm...m", -- 11 "mmmmmm.........m", -- 12 "mmmmmm.........m", -- 13 "mmmmmm.........m", -- 14 "mmmmmmmmmmmm...m", -- 15 -- Level 13 "mmmmmmmmmmmm...m", -- 0 "mmmmmmmmmmmm...m", -- 1 "mmmmmmmmmmmm...m", -- 2 "mmmmmmmmmmmm...m", -- 3 "mmmmmmmmmmmm...m", -- 4 "mmmmmmmmmmmm...m", -- 5 "mmmmmmmmmmmm...m", -- 6 "mmmmmmmmmmmm...m", -- 7 "mmmmmmmmmmmm...m", -- 8 "mmmmmmmmmmmm...m", -- 9 "mmmmmmmmmmmm...m", -- 10 "mmmmmmmmmmmm...m", -- 11 "mmmmmmmm.......m", -- 12 "mmmmmmmm.......m", -- 13 "mmmmmmmm.......m", -- 14 "mmmmmmmmmmmm...m", -- 15 }, }, -- BridgeLevelCrossing { OriginData = { ExportName = "CorridorCrossing", Name = "Nether 63", GalleryName = "Nether", GalleryIndex = "63", ID = "328", CreatorName = "xoft", }, Size = { x = 9, y = 6, z = 9, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 8, MaxY = 5, MaxZ = 8, }, Connectors = { { Type = 1, RelX = 8, RelY = 1, RelZ = 4, Direction = 5, -- X+ }, { Type = 1, RelX = 4, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, { Type = 1, RelX = 4, RelY = 1, RelZ = 8, Direction = 3, -- Z+ }, { Type = 1, RelX = 0, RelY = 1, RelZ = 4, Direction = 4, -- X- }, { Type = -1, RelX = 8, RelY = 1, RelZ = 4, Direction = 5, -- X+ }, { Type = -1, RelX = 4, RelY = 1, RelZ = 8, Direction = 3, -- Z+ }, { Type = -1, RelX = 0, RelY = 1, RelZ = 4, Direction = 4, -- X- }, { Type = -1, RelX = 4, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "-50", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a:112: 0", -- netherbrickblock "b:113: 0", -- netherbrickfence "c:114: 0", -- netherbrickstairs "d:114: 1", -- netherbrickstairs "e:114: 2", -- netherbrickstairs "f:114: 3", -- netherbrickstairs "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "mmaaaaamm", -- 0 "mmaaaaamm", -- 1 "aaaaaaaaa", -- 2 "aaaaaaaaa", -- 3 "aaaaaaaaa", -- 4 "aaaaaaaaa", -- 5 "aaaaaaaaa", -- 6 "mmaaaaamm", -- 7 "mmaaaaamm", -- 8 -- Level 1 "mma...amm", -- 0 "mma...amm", -- 1 "aaa...aaa", -- 2 ".........", -- 3 ".........", -- 4 ".........", -- 5 "aaa...aaa", -- 6 "mma...amm", -- 7 "mma...amm", -- 8 -- Level 2 "mma...amm", -- 0 "mmb...bmm", -- 1 "aba...aba", -- 2 ".........", -- 3 ".........", -- 4 ".........", -- 5 "aba...aba", -- 6 "mmb...bmm", -- 7 "mma...amm", -- 8 -- Level 3 "mma...amm", -- 0 "mmb...bmm", -- 1 "aba...aba", -- 2 ".........", -- 3 ".........", -- 4 ".........", -- 5 "aba...aba", -- 6 "mmb...bmm", -- 7 "mma...amm", -- 8 -- Level 4 "mma...amm", -- 0 "mmb...bmm", -- 1 "aba...aba", -- 2 ".........", -- 3 ".........", -- 4 ".........", -- 5 "aba...aba", -- 6 "mmb...bmm", -- 7 "mma...amm", -- 8 -- Level 5 "mmcaaadmm", -- 0 "mmcaaadmm", -- 1 "eeeaaaeee", -- 2 "aaaaaaaaa", -- 3 "aaaaaaaaa", -- 4 "aaaaaaaaa", -- 5 "ffcaaadff", -- 6 "mmcaaadmm", -- 7 "mmcaaadmm", -- 8 }, }, -- CorridorCrossing { OriginData = { ExportName = "TinyCorridorCrossing", Name = "Nether 64", GalleryName = "Nether", GalleryIndex = "64", ID = "329", CreatorName = "xoft", }, Size = { x = 5, y = 6, z = 5, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 4, MaxY = 5, MaxZ = 4, }, Connectors = { { Type = 1, RelX = 4, RelY = 1, RelZ = 2, Direction = 5, -- X+ }, { Type = 1, RelX = 2, RelY = 1, RelZ = 4, Direction = 3, -- Z+ }, { Type = 1, RelX = 0, RelY = 1, RelZ = 2, Direction = 4, -- X- }, { Type = 1, RelX = 2, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, { Type = -1, RelX = 4, RelY = 1, RelZ = 2, Direction = 5, -- X+ }, { Type = -1, RelX = 2, RelY = 1, RelZ = 4, Direction = 3, -- Z+ }, { Type = -1, RelX = 0, RelY = 1, RelZ = 2, Direction = 4, -- X- }, { Type = -1, RelX = 2, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "-50", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "1:200|2:400|3:0|4:500", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a:112: 0", -- netherbrickblock "b:114: 2", -- netherbrickstairs "c:114: 0", -- netherbrickstairs "d:114: 1", -- netherbrickstairs "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "aaaaa", -- 0 "aaaaa", -- 1 "aaaaa", -- 2 "aaaaa", -- 3 "aaaaa", -- 4 -- Level 1 "a...a", -- 0 ".....", -- 1 ".....", -- 2 ".....", -- 3 "a...a", -- 4 -- Level 2 "a...a", -- 0 ".....", -- 1 ".....", -- 2 ".....", -- 3 "a...a", -- 4 -- Level 3 "a...a", -- 0 ".....", -- 1 ".....", -- 2 ".....", -- 3 "a...a", -- 4 -- Level 4 "a...a", -- 0 ".....", -- 1 ".....", -- 2 ".....", -- 3 "a...a", -- 4 -- Level 5 "baaab", -- 0 "aaaaa", -- 1 "aaaaa", -- 2 "aaaaa", -- 3 "caaad", -- 4 }, }, -- TinyCorridorCrossing { OriginData = { ExportName = "Corridor5", Name = "Nether 65", GalleryName = "Nether", GalleryIndex = "65", ID = "330", CreatorName = "xoft", }, Size = { x = 5, y = 6, z = 5, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 4, MaxY = 5, MaxZ = 4, }, Connectors = { { Type = 1, RelX = 4, RelY = 1, RelZ = 2, Direction = 5, -- X+ }, { Type = 1, RelX = 0, RelY = 1, RelZ = 2, Direction = 4, -- X- }, { Type = -1, RelX = 4, RelY = 1, RelZ = 2, Direction = 5, -- X+ }, { Type = -1, RelX = 0, RelY = 1, RelZ = 2, Direction = 4, -- X- }, }, Metadata = { ["AddWeightIfSame"] = "500", ["AllowedRotations"] = "7", ["DefaultWeight"] = "500", ["DepthWeight"] = "6:0|12:0|18:0", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a:112: 0", -- netherbrickblock "b:113: 0", -- netherbrickfence "c:114: 2", -- netherbrickstairs "d:114: 3", -- netherbrickstairs "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "aaaaa", -- 0 "aaaaa", -- 1 "aaaaa", -- 2 "aaaaa", -- 3 "aaaaa", -- 4 -- Level 1 "aaaaa", -- 0 ".....", -- 1 ".....", -- 2 ".....", -- 3 "aaaaa", -- 4 -- Level 2 "ababa", -- 0 ".....", -- 1 ".....", -- 2 ".....", -- 3 "ababa", -- 4 -- Level 3 "ababa", -- 0 ".....", -- 1 ".....", -- 2 ".....", -- 3 "ababa", -- 4 -- Level 4 "ababa", -- 0 ".....", -- 1 ".....", -- 2 ".....", -- 3 "ababa", -- 4 -- Level 5 "ccccc", -- 0 "aaaaa", -- 1 "aaaaa", -- 2 "aaaaa", -- 3 "ddddd", -- 4 }, }, -- Corridor5 { OriginData = { ExportName = "TinyCorridorCorner", Name = "Nether 66", GalleryName = "Nether", GalleryIndex = "66", ID = "331", CreatorName = "xoft", }, Size = { x = 5, y = 6, z = 5, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 4, MaxY = 5, MaxZ = 4, }, Connectors = { { Type = 1, RelX = 2, RelY = 1, RelZ = 4, Direction = 3, -- Z+ }, { Type = 1, RelX = 0, RelY = 1, RelZ = 2, Direction = 4, -- X- }, { Type = -1, RelX = 2, RelY = 1, RelZ = 4, Direction = 3, -- Z+ }, { Type = -1, RelX = 0, RelY = 1, RelZ = 2, Direction = 4, -- X- }, }, Metadata = { ["AddWeightIfSame"] = "-50", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a:112: 0", -- netherbrickblock "b:113: 0", -- netherbrickfence "c:114: 2", -- netherbrickstairs "d:114: 1", -- netherbrickstairs "e:114: 0", -- netherbrickstairs "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "aaaaa", -- 0 "aaaaa", -- 1 "aaaaa", -- 2 "aaaaa", -- 3 "aaaaa", -- 4 -- Level 1 "aaaaa", -- 0 "....a", -- 1 "....a", -- 2 "....a", -- 3 "a...a", -- 4 -- Level 2 "ababa", -- 0 "....b", -- 1 "....a", -- 2 "....b", -- 3 "a...a", -- 4 -- Level 3 "ababa", -- 0 "....b", -- 1 "....a", -- 2 "....b", -- 3 "a...a", -- 4 -- Level 4 "ababa", -- 0 "....b", -- 1 "....a", -- 2 "....b", -- 3 "a...a", -- 4 -- Level 5 "ccccc", -- 0 "aaaad", -- 1 "aaaad", -- 2 "aaaad", -- 3 "eaaad", -- 4 }, }, -- TinyCorridorCorner { OriginData = { ExportName = "TinyCorridorCornerChest", Name = "Nether 67", GalleryName = "Nether", GalleryIndex = "67", ID = "332", CreatorName = "Aloe_vera", }, Size = { x = 5, y = 6, z = 5, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 4, MaxY = 5, MaxZ = 4, }, Connectors = { { Type = 1, RelX = 2, RelY = 1, RelZ = 4, Direction = 3, -- Z+ }, { Type = 1, RelX = 0, RelY = 1, RelZ = 2, Direction = 4, -- X- }, { Type = -1, RelX = 2, RelY = 1, RelZ = 4, Direction = 3, -- Z+ }, { Type = -1, RelX = 0, RelY = 1, RelZ = 2, Direction = 4, -- X- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a:112: 0", -- netherbrickblock "b: 54: 4", -- chest "c:113: 0", -- netherbrickfence "d:114: 2", -- netherbrickstairs "e:114: 1", -- netherbrickstairs "f:114: 0", -- netherbrickstairs "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "aaaaa", -- 0 "aaaaa", -- 1 "aaaaa", -- 2 "aaaaa", -- 3 "aaaaa", -- 4 -- Level 1 "aaaaa", -- 0 "....a", -- 1 "...ba", -- 2 "....a", -- 3 "a...a", -- 4 -- Level 2 "acaca", -- 0 "....c", -- 1 "....a", -- 2 "....c", -- 3 "a...a", -- 4 -- Level 3 "acaca", -- 0 "....c", -- 1 "....a", -- 2 "....c", -- 3 "a...a", -- 4 -- Level 4 "acaca", -- 0 "....c", -- 1 "....a", -- 2 "....c", -- 3 "a...a", -- 4 -- Level 5 "ddddd", -- 0 "aaaae", -- 1 "aaaae", -- 2 "aaaae", -- 3 "faaae", -- 4 }, }, -- TinyCorridorCornerChest { OriginData = { ExportName = "BridgeDoubleStairs", Name = "Nether 115", GalleryName = "Nether", GalleryIndex = "115", ID = "810", CreatorName = "STR_Warrior", }, Size = { x = 15, y = 16, z = 16, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 14, MaxY = 15, MaxZ = 15, }, Connectors = { { Type = 0, RelX = 0, RelY = 13, RelZ = 13, Direction = 4, -- X- }, { Type = 0, RelX = 14, RelY = 13, RelZ = 13, Direction = 5, -- X+ }, { Type = 0, RelX = 0, RelY = 13, RelZ = 2, Direction = 4, -- X- }, { Type = 0, RelX = 14, RelY = 13, RelZ = 2, Direction = 5, -- X+ }, { Type = 0, RelX = 12, RelY = 7, RelZ = 15, Direction = 3, -- Z+ }, { Type = 0, RelX = 12, RelY = 7, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "20", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a:112: 0", -- netherbrickblock "b:114: 7", -- netherbrickstairs "c:114: 6", -- netherbrickstairs "d:114: 4", -- netherbrickstairs "e:114: 5", -- netherbrickstairs "f:114: 2", -- netherbrickstairs "g:114: 3", -- netherbrickstairs "h:114: 1", -- netherbrickstairs "i: 44:14", -- stone_slab "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "mmmmmmmmmmmaaam", -- 0 "aammmmmmmmmaaaa", -- 1 "aammmmmmmmmmmma", -- 2 "aammmmmmmmmmmma", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmmmmmmmmm", -- 5 "mmmmmmmmmmmmmmm", -- 6 "mmmmmmmmmmmmmmm", -- 7 "mmmmmmmmmmmmmmm", -- 8 "mmmmmmmmmmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "aammmmmmmmmmmma", -- 12 "aammmmmmmmmmmma", -- 13 "aammmmmmmmmaaaa", -- 14 "mmmmmmmmmmmaaam", -- 15 -- Level 1 "mmmmmmmmmmmaaam", -- 0 "aammmmmmmmmaaaa", -- 1 "aammmmmmmmmmmma", -- 2 "aammmmmmmmmmmma", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmmmmmmmmm", -- 5 "mmmmmmmmmmmmmmm", -- 6 "mmmmmmmmmmmmmmm", -- 7 "mmmmmmmmmmmmmmm", -- 8 "mmmmmmmmmmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "aammmmmmmmmmmma", -- 12 "aammmmmmmmmmmma", -- 13 "aammmmmmmmmaaaa", -- 14 "mmmmmmmmmmmaaam", -- 15 -- Level 2 "mmmmmmmmmmmaaam", -- 0 "aammmmmmmmmaaaa", -- 1 "aammmmmmmmmmmma", -- 2 "aammmmmmmmmmmma", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmmmmmmmmm", -- 5 "mmmmmmmmmmmmmmm", -- 6 "mmmmmmmmmmmmmmm", -- 7 "mmmmmmmmmmmmmmm", -- 8 "mmmmmmmmmmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "aammmmmmmmmmmma", -- 12 "aammmmmmmmmmmma", -- 13 "aammmmmmmmmaaaa", -- 14 "mmmmmmmmmmmaaam", -- 15 -- Level 3 "mmmmmmmmmmmaaam", -- 0 "aammmmmmmmmaaaa", -- 1 "aammmmmmmmmbbba", -- 2 "aammmmmmmmmmmma", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmmmmmmmmm", -- 5 "mmmmmmmmmmmmmmm", -- 6 "mmmmmmmmmmmmmmm", -- 7 "mmmmmmmmmmmmmmm", -- 8 "mmmmmmmmmmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "aammmmmmmmmmmma", -- 12 "aammmmmmmmmccca", -- 13 "aammmmmmmmmaaaa", -- 14 "mmmmmmmmmmmaaam", -- 15 -- Level 4 "mmmmmmmmmmmaaam", -- 0 "aammmmmmmmmaaaa", -- 1 "aammmmmmmmmaaaa", -- 2 "aammmmmmmmmbbba", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmmmmmmmmm", -- 5 "mmmmmmmmmmmmmmm", -- 6 "mmmmmmmmmmmmmmm", -- 7 "mmmmmmmmmmmmmmm", -- 8 "mmmmmmmmmmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "aammmmmmmmmccca", -- 12 "aammmmmmmmmaaaa", -- 13 "aammmmmmmmmaaaa", -- 14 "mmmmmmmmmmmaaam", -- 15 -- Level 5 "mmmmmmmmmmdaaae", -- 0 "aammmmmmmmdaaaa", -- 1 "aammmmmmmmdaaaa", -- 2 "aammmmmmmmdaaaa", -- 3 "mmmmmmmmmmdaaae", -- 4 "mmmmmmmmmmmmmmm", -- 5 "mmmmmmmmmmmmmmm", -- 6 "mmmmmmmmmmmmmmm", -- 7 "mmmmmmmmmmmmmmm", -- 8 "mmmmmmmmmmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmdaaae", -- 11 "aammmmmmmmdaaaa", -- 12 "aammmmmmmmdaaaa", -- 13 "aammmmmmmmdaaaa", -- 14 "mmmmmmmmmmdaaae", -- 15 -- Level 6 "mmmmmmmmmmaaaaa", -- 0 "aammmmmmmmaaaaa", -- 1 "aammmmmmmmaaaaa", -- 2 "aammmmmmmmaaaaa", -- 3 "mmmmmmmmmmaaaaa", -- 4 "mmmmmmmmmmdaaae", -- 5 "mmmmmmmmmmmmmmm", -- 6 "mmmmmmmmmmmmmmm", -- 7 "mmmmmmmmmmmmmmm", -- 8 "mmmmmmmmmmmmmmm", -- 9 "mmmmmmmmmmdaaae", -- 10 "mmmmmmmmmmaaaaa", -- 11 "aammmmmmmmaaaaa", -- 12 "aammmmmmmmaaaaa", -- 13 "aammmmmmmmaaaaa", -- 14 "mmmmmmmmmmaaaaa", -- 15 -- Level 7 "mmmmmmmmmma...a", -- 0 "aammmmmmmma...a", -- 1 "aammmmmmmma...a", -- 2 "aammmmmmmma...a", -- 3 "mmmmmmmmmmafffa", -- 4 "mmmmmmmmmaaaaaa", -- 5 "mmmmmmmmmaaaaae", -- 6 "mmmmmmmmmaaaaae", -- 7 "mmmmmmmmmaaaaae", -- 8 "mmmmmmmmmaaaaae", -- 9 "mmmmmmmmmaaaaaa", -- 10 "mmmmmmmmmmaggga", -- 11 "aammmmmmmma...a", -- 12 "aammmmmmmma...a", -- 13 "aammmmmmmma...a", -- 14 "mmmmmmmmmma...a", -- 15 -- Level 8 "mmmmmmmmmmm...m", -- 0 "aammmmmmmma...a", -- 1 "aammmmmmmma...a", -- 2 "aammmmmmmma...a", -- 3 "mmmmmmmmmma...a", -- 4 "mmmmmmmmmaafffa", -- 5 "mmmmmmmmaaaaaaa", -- 6 "mmmmmmmmaaaaaaa", -- 7 "mmmmmmmmaaaaaaa", -- 8 "mmmmmmmmaaaaaaa", -- 9 "mmmmmmmmmaaggga", -- 10 "mmmmmmmmmma...a", -- 11 "aammmmmmmma...a", -- 12 "aammmmmmmma...a", -- 13 "aammmmmmmma...a", -- 14 "mmmmmmmmmmm...m", -- 15 -- Level 9 "mmmmmmmmmmm...m", -- 0 "aaemmmmmmma...a", -- 1 "aaemmmmmmma...a", -- 2 "aaemmmmmmma...a", -- 3 "mmmmmmmmmma...a", -- 4 "mmmmmmmmmaa...a", -- 5 "mmmmaaaaah....a", -- 6 "mmmmaaaaah....a", -- 7 "mmmmaaaaah....a", -- 8 "mmmmaaaaah....a", -- 9 "mmmmmmmmmaa...a", -- 10 "mmmmmmmmmma...a", -- 11 "aaemmmmmmma...a", -- 12 "aaemmmmmmma...a", -- 13 "aaemmmmmmma...a", -- 14 "mmmmmmmmmmm...m", -- 15 -- Level 10 "mmmmmmmmmmmmmmm", -- 0 "aaaeimmmmmammma", -- 1 "aaaeimmmmmammma", -- 2 "aaaeimmmmma...a", -- 3 "mmmmmmmmmmm...m", -- 4 "mmmmaaaaaam...m", -- 5 "mmmmaaaah.....m", -- 6 "mmmmaaaah.....m", -- 7 "mmmmaaaah.....m", -- 8 "mmmmaaaah.....m", -- 9 "mmmmaaaaaam...m", -- 10 "mmmmmmmmmmm...m", -- 11 "aaaeimmmmma...a", -- 12 "aaaeimmmmmammma", -- 13 "aaaeimmmmmammma", -- 14 "mmmmmmmmmmmmmmm", -- 15 -- Level 11 "ccccccccccccccc", -- 0 "aaaaaaaaaaaaaaa", -- 1 "aaaaaaaaaaaaaaa", -- 2 "aaaaaaaaaaaaaaa", -- 3 "bbbbaaaaabbbbbb", -- 4 "mmmmagggamm...m", -- 5 "mmmma.........m", -- 6 "mmmma.........m", -- 7 "mmmma.........m", -- 8 "mmmma.........m", -- 9 "mmmmafffamm...m", -- 10 "ccccaaaahcccccc", -- 11 "aaaaaaaaaaaaaaa", -- 12 "aaaaaaaaaaaaaaa", -- 13 "aaaaaaaaaaaaaaa", -- 14 "bbbbbbbbbbbbbbb", -- 15 -- Level 12 "aaaaaaaaaaaaaaa", -- 0 "aaaaaaaaaaaaaaa", -- 1 "aaaaaaaaaaaaaaa", -- 2 "aaaaaaaaaaaaaaa", -- 3 "aaaaagggaaaaaaa", -- 4 "mmmma...ammmmmm", -- 5 "mmmma.........m", -- 6 "mmmmm.........m", -- 7 "mmmmm.........m", -- 8 "mmmma.........m", -- 9 "mmmma...ammmmmm", -- 10 "aaaaafffaaaaaaa", -- 11 "aaaaaaaaaaaaaaa", -- 12 "aaaaaaaaaaaaaaa", -- 13 "aaaaaaaaaaaaaaa", -- 14 "aaaaaaaaaaaaaaa", -- 15 -- Level 13 "aaaaaaaaaaaaaaa", -- 0 "...............", -- 1 "...............", -- 2 "...............", -- 3 "aaaaa...aaaaaaa", -- 4 "mmmma...ammmmmm", -- 5 "mmmmm.....mmmmm", -- 6 "mmmmm.....mmmmm", -- 7 "mmmmm.....mmmmm", -- 8 "mmmmm.....mmmmm", -- 9 "mmmma...ammmmmm", -- 10 "aaaaa...aaaaaaa", -- 11 "...............", -- 12 "...............", -- 13 "...............", -- 14 "aaaaaaaaaaaaaaa", -- 15 -- Level 14 "mmmmmmmmmmmmmmm", -- 0 "...............", -- 1 "...............", -- 2 "...............", -- 3 "mmmmm...mmmmmmm", -- 4 "mmmmm...mmmmmmm", -- 5 "mmmmm...mmmmmmm", -- 6 "mmmmm...mmmmmmm", -- 7 "mmmmm...mmmmmmm", -- 8 "mmmmm...mmmmmmm", -- 9 "mmmmm...mmmmmmm", -- 10 "mmmmm...mmmmmmm", -- 11 "...............", -- 12 "...............", -- 13 "...............", -- 14 "mmmmmmmmmmmmmmm", -- 15 -- Level 15 "mmmmmmmmmmmmmmm", -- 0 "...............", -- 1 "...............", -- 2 "...............", -- 3 "mmmmm...mmmmmmm", -- 4 "mmmmm...mmmmmmm", -- 5 "mmmmmmmmmmmmmmm", -- 6 "mmmmmmmmmmmmmmm", -- 7 "mmmmmmmmmmmmmmm", -- 8 "mmmmmmmmmmmmmmm", -- 9 "mmmmm...mmmmmmm", -- 10 "mmmmm...mmmmmmm", -- 11 "...............", -- 12 "...............", -- 13 "...............", -- 14 "mmmmmmmmmmmmmmm", -- 15 }, }, -- BridgeDoubleStairs { OriginData = { ExportName = "SlabbedBridgeStairs", Name = "Nether 116", GalleryName = "Nether", GalleryIndex = "116", ID = "811", CreatorName = "Aloe_vera", }, Size = { x = 16, y = 14, z = 16, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 15, MaxY = 13, MaxZ = 15, }, Connectors = { { Type = 0, RelX = 13, RelY = 11, RelZ = 0, Direction = 2, -- Z- }, { Type = 0, RelX = 13, RelY = 11, RelZ = 15, Direction = 3, -- Z+ }, { Type = 0, RelX = 0, RelY = 5, RelZ = 2, Direction = 4, -- X- }, { Type = 0, RelX = 15, RelY = 5, RelZ = 2, Direction = 5, -- X+ }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "20", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a:112: 0", -- netherbrickblock "b:114: 5", -- netherbrickstairs "c:114: 4", -- netherbrickstairs "d: 44:14", -- stone_slab "e:114: 6", -- netherbrickstairs "f:114: 7", -- netherbrickstairs "g: 44: 6", -- stone_slab "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "mmmmmmmmmmmmmmmm", -- 0 "aammmmmmmmmmmmaa", -- 1 "aammmmmmmmmmmmaa", -- 2 "aammmmmmmmmmmmaa", -- 3 "mmmmmmmmmmmmmmmm", -- 4 "mmmmmmmmmmmmmmmm", -- 5 "mmmmmmmmmmmmmmmm", -- 6 "mmmmmmmmmmmmmmmm", -- 7 "mmmmmmmmmmmmmmmm", -- 8 "mmmmmmmmmmmmmmmm", -- 9 "mmmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmmm", -- 11 "maaammmmmmmmmmmm", -- 12 "maaammmmmmmmmmmm", -- 13 "maaammmmmmmmaaam", -- 14 "mmmmmmmmmmmmaaam", -- 15 -- Level 1 "mmmmmmmmmmmmmmmm", -- 0 "aabmmmmmmmmmmcaa", -- 1 "aabmmmmmmmmmmcaa", -- 2 "aabmmmmmmmmmmcaa", -- 3 "mmmmmmmmmmmmmmmm", -- 4 "mmmmmmmmmmmmmmmm", -- 5 "mmmmmmmmmmmmmmmm", -- 6 "mmmmmmmmmmmmmmmm", -- 7 "mmmmmmmmmmmmmmmm", -- 8 "mmmmmmmmmmmmmmmm", -- 9 "mmmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmmm", -- 11 "maaammmmmmmmmmmm", -- 12 "maaammmmmmmmmmmm", -- 13 "maaammmmmmmmaaam", -- 14 "mmmmmmmmmmmmaaam", -- 15 -- Level 2 "mmmmmmmmmmmmmmmm", -- 0 "aaabdmmmmmmdcaaa", -- 1 "aaabdmmmmmmdcaaa", -- 2 "aaabdmmmmmmdcaaa", -- 3 "mmmmmmmmmmmmmmmm", -- 4 "mmmmmmmmmmmmmmmm", -- 5 "mmmmmmmmmmmmmmmm", -- 6 "mmmmmmmmmmmmmmmm", -- 7 "mmmmmmmmmmmmmmmm", -- 8 "mmmmmmmmmmmmmmmm", -- 9 "mmmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmmm", -- 11 "maaammmmmmmmmmmm", -- 12 "maaammmmmmmmmmmm", -- 13 "maaammmmmmmmaaam", -- 14 "mmmmmmmmmmmmaaam", -- 15 -- Level 3 "eeeeeeeeeeeeeeee", -- 0 "aaaaaaaaaaaaaaaa", -- 1 "aaaaaaaaaaaaaaaa", -- 2 "aaaaaaaaaaaaaaaa", -- 3 "ffffffffffffffff", -- 4 "mmmmmmmmmmmmmmmm", -- 5 "mmmmmmmmmmmmmmmm", -- 6 "mmmmmmmmmmmmmmmm", -- 7 "mmmmmmmmmmmmmmmm", -- 8 "mmmmmmmmmmmmmmmm", -- 9 "mmmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmmm", -- 11 "maaammmmmmmmmmmm", -- 12 "maaammmmmmmmmmmm", -- 13 "maaammmmmmmmaaam", -- 14 "mmmmmmmmmmmmaaam", -- 15 -- Level 4 "aaaaaaaaaaaaaaaa", -- 0 "aaaaaaaaaaaaaaaa", -- 1 "aaaaaaaaaaaaaaaa", -- 2 "aaaaaaaaaaaaaaaa", -- 3 "aaaaaaaaaaaaaaaa", -- 4 "faaabmmmmmmmmmmm", -- 5 "caaabmmmmmmmmmmm", -- 6 "caaabmmmmmmmmmmm", -- 7 "mmmmmmmmmmmmmmmm", -- 8 "mmmmmmmmmmmmmmmm", -- 9 "mmmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmmm", -- 11 "maaammmmmmmmmmmm", -- 12 "maaammmmmmmmmmmm", -- 13 "maaammmmmmmmaaam", -- 14 "mmmmmmmmmmmmaaam", -- 15 -- Level 5 "aaaaaaaaaaaaaaaa", -- 0 "................", -- 1 "................", -- 2 "................", -- 3 "a...aaaaaaaaaaaa", -- 4 "agggammmmmmmmmmm", -- 5 "aaaaammmmmmmmmmm", -- 6 "aaaaammmmmmmmmmm", -- 7 "caaabmmmmmmmmmmm", -- 8 "caaabmmmmmmmmmmm", -- 9 "mmmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmmm", -- 11 "maaammmmmmmmmmmm", -- 12 "maaammmmmmmmmmmm", -- 13 "maaammmmmmmmaaam", -- 14 "mmmmmmmmmmmmaaam", -- 15 -- Level 6 "mmmmmmmmmmmmaaam", -- 0 "................", -- 1 "................", -- 2 "................", -- 3 "m...mmmmmmmmaaam", -- 4 "a...ammmmmmmmmmm", -- 5 "a...ammmmmmmmmmm", -- 6 "agggammmmmmmmmmm", -- 7 "aaaaammmmmmmmmmm", -- 8 "aaaaammmmmmmmmmm", -- 9 "caaabmmmmmmmmmmm", -- 10 "caaabmmmmmmmmmmm", -- 11 "maaabmmmmmmmmmmm", -- 12 "maaabmmmmmmmmmmm", -- 13 "maaafmmmmmmmaaam", -- 14 "mmmmmmmmmmmmaaam", -- 15 -- Level 7 "mmmmmmmmmmmmaaam", -- 0 "................", -- 1 "................", -- 2 "................", -- 3 "m...mmmmmmmmaaam", -- 4 "m...mmmmmmmmmmmm", -- 5 "m...mmmmmmmmmmmm", -- 6 "a...ammmmmmmmmmm", -- 7 "a...ammmmmmmmmmm", -- 8 "agggammmmmmmmmmm", -- 9 "aaaaammmmmmmmmmm", -- 10 "aaaaaeemmmmmmmmm", -- 11 "caaaaaammmmmmmmm", -- 12 "caaaaaammmmmmmmm", -- 13 "caaaaaammmmmaaam", -- 14 "fffffffmmmmmaaam", -- 15 -- Level 8 "mmmmmmmmmmmmaaam", -- 0 "mmmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmmm", -- 3 "m...mmmmmmmmaaam", -- 4 "m...mmmmmmmmmmmm", -- 5 "m...mmmmmmmmmmmm", -- 6 "m...mmmmmmmmmmmm", -- 7 "m...mmmmmmmmmmmm", -- 8 "a...ammmmmmmmmmm", -- 9 "a...ammmmmmmmmmm", -- 10 "a...aaaeemmmmmmm", -- 11 "a....gaaammmmmmm", -- 12 "a....gaaammmmmmm", -- 13 "a....gaaammmaaam", -- 14 "aaaaaaaffmmmaaam", -- 15 -- Level 9 "mmmmmmmmmmmcaaab", -- 0 "mmmmmmmmmmmcaaab", -- 1 "mmmmmmmmmmmcaaab", -- 2 "mmmmmmmmmmmcaaab", -- 3 "mmmmmmmmmmmcaaab", -- 4 "mmmmmmmmmmmcaaab", -- 5 "m...mmmmmmmcaaab", -- 6 "m...mmmmmmmcaaab", -- 7 "m...mmmmmmmcaaab", -- 8 "m...mmmmmmmcaaab", -- 9 "m...mmmmmmmcaaab", -- 10 "m...maaaaeecaaab", -- 11 "m......gaaaaaaab", -- 12 "m......gaaaaaaab", -- 13 "m......gaaaaaaab", -- 14 "mmmmmaaaafffaaab", -- 15 -- Level 10 "mmmmmmmmmmmaaaaa", -- 0 "mmmmmmmmmmmaaaaa", -- 1 "mmmmmmmmmmmaaaaa", -- 2 "mmmmmmmmmmmaaaaa", -- 3 "mmmmmmmmmmmaaaaa", -- 4 "mmmmmmmmmmmaaaaa", -- 5 "mmmmmmmmmmmaaaaa", -- 6 "mmmmmmmmmmmaaaaa", -- 7 "m...mmmmmmmaaaaa", -- 8 "m...mmmmmmmaaaaa", -- 9 "m...mmmmmmmaaaaa", -- 10 "m...mmmaaaaaaaaa", -- 11 "m........gaaaaaa", -- 12 "m........gaaaaaa", -- 13 "m........gaaaaaa", -- 14 "mmmmmmmaaaaaaaaa", -- 15 -- Level 11 "mmmmmmmmmmma...a", -- 0 "mmmmmmmmmmma...a", -- 1 "mmmmmmmmmmma...a", -- 2 "mmmmmmmmmmma...a", -- 3 "mmmmmmmmmmma...a", -- 4 "mmmmmmmmmmma...a", -- 5 "mmmmmmmmmmma...a", -- 6 "mmmmmmmmmmma...a", -- 7 "mmmmmmmmmmma...a", -- 8 "mmmmmmmmmmma...a", -- 9 "mmmmmmmmmmma...a", -- 10 "mmmmmmmmmaaa...a", -- 11 "mmmm...........a", -- 12 "mmmm...........a", -- 13 "mmmm...........a", -- 14 "mmmmmmmmmaaa...a", -- 15 -- Level 12 "mmmmmmmmmmmm...m", -- 0 "mmmmmmmmmmmm...m", -- 1 "mmmmmmmmmmmm...m", -- 2 "mmmmmmmmmmmm...m", -- 3 "mmmmmmmmmmmm...m", -- 4 "mmmmmmmmmmmm...m", -- 5 "mmmmmmmmmmmm...m", -- 6 "mmmmmmmmmmmm...m", -- 7 "mmmmmmmmmmmm...m", -- 8 "mmmmmmmmmmmm...m", -- 9 "mmmmmmmmmmmm...m", -- 10 "mmmmmmmmmmmm...m", -- 11 "mmmmmm.........m", -- 12 "mmmmmm.........m", -- 13 "mmmmmm.........m", -- 14 "mmmmmmmmmmmm...m", -- 15 -- Level 13 "mmmmmmmmmmmm...m", -- 0 "mmmmmmmmmmmm...m", -- 1 "mmmmmmmmmmmm...m", -- 2 "mmmmmmmmmmmm...m", -- 3 "mmmmmmmmmmmm...m", -- 4 "mmmmmmmmmmmm...m", -- 5 "mmmmmmmmmmmm...m", -- 6 "mmmmmmmmmmmm...m", -- 7 "mmmmmmmmmmmm...m", -- 8 "mmmmmmmmmmmm...m", -- 9 "mmmmmmmmmmmm...m", -- 10 "mmmmmmmmmmmm...m", -- 11 "mmmmmmmm.......m", -- 12 "mmmmmmmm.......m", -- 13 "mmmmmmmm.......m", -- 14 "mmmmmmmmmmmm...m", -- 15 }, }, -- SlabbedBridgeStairs }, -- Pieces } ================================================ FILE: Server/Prefabs/PieceStructures/RainbowRoad.cubeset ================================================ -- RainbowRoad.cubeset -- Defines the prefabs in the group RainbowRoad -- NOTE: This file has been generated automatically by GalExport! -- Any manual changes will be overwritten by the next automatic export! Cubeset = { Metadata = { CubesetFormatVersion = 1, ExportDate = "2016-11-23 15:08:00", ["GridSizeX"] = "512", ["GridSizeZ"] = "512", ["IntendedUse"] = "PieceStructures", ["MaxDepth"] = "30", ["MaxOffsetX"] = "256", ["MaxOffsetZ"] = "256", ["MaxStructureSizeX"] = "256", ["MaxStructureSizeZ"] = "256", }, Pieces = { { OriginData = { ExportName = "StraightSingle", Name = "Cube 83", GalleryName = "Cube", GalleryIndex = "83", ID = "461", CreatorName = "Aloe_vera", }, Size = { x = 16, y = 1, z = 6, }, Hitbox = { MinX = 0, MinY = -2, MinZ = 0, MaxX = 15, MaxY = 2, MaxZ = 5, }, Connectors = { { Type = -1, RelX = 0, RelY = 1, RelZ = 5, Direction = 4, -- X- }, { Type = 1, RelX = 15, RelY = 1, RelZ = 5, Direction = 5, -- X+ }, }, Metadata = { ["AddWeightIfSame"] = "500", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "None", ["IsStarting"] = "1", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", ["VerticalStrategy"] = "Range|120|140", }, BlockDefinitions = { ".: 0: 0", -- air "a: 35:14", -- wool "b: 35: 1", -- wool "c: 35: 4", -- wool "d: 35: 5", -- wool "e: 35: 3", -- wool "f: 35:11", -- wool "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "aaaaaaaaaaaaaaaa", -- 0 "bbbbbbbbbbbbbbbb", -- 1 "cccccccccccccccc", -- 2 "dddddddddddddddd", -- 3 "eeeeeeeeeeeeeeee", -- 4 "ffffffffffffffff", -- 5 }, }, -- StraightSingle { OriginData = { ExportName = "CurveSingle", Name = "Cube 84", GalleryName = "Cube", GalleryIndex = "84", ID = "462", CreatorName = "Aloe_vera", }, Size = { x = 11, y = 1, z = 11, }, Hitbox = { MinX = 0, MinY = -2, MinZ = 0, MaxX = 10, MaxY = 2, MaxZ = 10, }, Connectors = { { Type = -1, RelX = 0, RelY = 1, RelZ = 5, Direction = 4, -- X- }, { Type = 1, RelX = 5, RelY = 1, RelZ = 10, Direction = 3, -- Z+ }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "None", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a: 35:14", -- wool "b: 35: 1", -- wool "c: 35: 4", -- wool "d: 35: 5", -- wool "e: 35: 3", -- wool "f: 35:11", -- wool "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "aaaaaa.....", -- 0 "bbbbbbaa...", -- 1 "cccccbbaa..", -- 2 "ddddcccbaa.", -- 3 "eeedddccba.", -- 4 "ffeeeddcbba", -- 5 ".fffeedccba", -- 6 "...ffeddcba", -- 7 "....feedcba", -- 8 "....ffedcba", -- 9 ".....fedcba", -- 10 }, }, -- CurveSingle { OriginData = { ExportName = "SlopeUpSingle", Name = "Cube 85", GalleryName = "Cube", GalleryIndex = "85", ID = "463", CreatorName = "Aloe_vera", }, Size = { x = 16, y = 8, z = 6, }, Hitbox = { MinX = 0, MinY = -2, MinZ = 0, MaxX = 15, MaxY = 9, MaxZ = 5, }, Connectors = { { Type = -1, RelX = 0, RelY = 1, RelZ = 5, Direction = 4, -- X- }, { Type = 1, RelX = 15, RelY = 8, RelZ = 5, Direction = 5, -- X+ }, }, Metadata = { ["AddWeightIfSame"] = "-1000", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "None", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a: 35:14", -- wool "b: 35: 1", -- wool "c: 35: 4", -- wool "d: 35: 5", -- wool "e: 35: 3", -- wool "f: 35:11", -- wool "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "aa..............", -- 0 "bb..............", -- 1 "cc..............", -- 2 "dd..............", -- 3 "ee..............", -- 4 "ff..............", -- 5 -- Level 1 "..aa............", -- 0 "..bb............", -- 1 "..cc............", -- 2 "..dd............", -- 3 "..ee............", -- 4 "..ff............", -- 5 -- Level 2 "....aa..........", -- 0 "....bb..........", -- 1 "....cc..........", -- 2 "....dd..........", -- 3 "....ee..........", -- 4 "....ff..........", -- 5 -- Level 3 "......aa........", -- 0 "......bb........", -- 1 "......cc........", -- 2 "......dd........", -- 3 "......ee........", -- 4 "......ff........", -- 5 -- Level 4 "........aa......", -- 0 "........bb......", -- 1 "........cc......", -- 2 "........dd......", -- 3 "........ee......", -- 4 "........ff......", -- 5 -- Level 5 "..........aa....", -- 0 "..........bb....", -- 1 "..........cc....", -- 2 "..........dd....", -- 3 "..........ee....", -- 4 "..........ff....", -- 5 -- Level 6 "............aa..", -- 0 "............bb..", -- 1 "............cc..", -- 2 "............dd..", -- 3 "............ee..", -- 4 "............ff..", -- 5 -- Level 7 "..............aa", -- 0 "..............bb", -- 1 "..............cc", -- 2 "..............dd", -- 3 "..............ee", -- 4 "..............ff", -- 5 }, }, -- SlopeUpSingle { OriginData = { ExportName = "CurveUpSingle", Name = "Cube 87", GalleryName = "Cube", GalleryIndex = "87", ID = "465", CreatorName = "Aloe_vera", }, Size = { x = 11, y = 8, z = 11, }, Hitbox = { MinX = 0, MinY = -2, MinZ = 0, MaxX = 10, MaxY = 9, MaxZ = 10, }, Connectors = { { Type = -1, RelX = 0, RelY = 1, RelZ = 5, Direction = 4, -- X- }, { Type = 1, RelX = 5, RelY = 8, RelZ = 10, Direction = 3, -- Z+ }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "None", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a: 35:14", -- wool "b: 35: 1", -- wool "c: 35: 4", -- wool "d: 35: 5", -- wool "e: 35: 3", -- wool "f: 35:11", -- wool "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "aaa........", -- 0 "bb.........", -- 1 "cc.........", -- 2 "dd.........", -- 3 "ee.........", -- 4 "f..........", -- 5 "...........", -- 6 "...........", -- 7 "...........", -- 8 "...........", -- 9 "...........", -- 10 -- Level 1 "...aaa.....", -- 0 "..bbb......", -- 1 ".cc........", -- 2 ".dd........", -- 3 ".ee........", -- 4 ".f.........", -- 5 ".ff........", -- 6 "...........", -- 7 "...........", -- 8 "...........", -- 9 "...........", -- 10 -- Level 2 "...........", -- 0 ".....baa...", -- 1 "...ccb.....", -- 2 "...dc......", -- 3 "...d.......", -- 4 "..ee.......", -- 5 "..ff.......", -- 6 "...........", -- 7 "...........", -- 8 "...........", -- 9 "...........", -- 10 -- Level 3 "...........", -- 0 "...........", -- 1 "......baa..", -- 2 ".....ccb...", -- 3 "....dd.....", -- 4 "....e......", -- 5 "...fe......", -- 6 "...ff......", -- 7 "...........", -- 8 "...........", -- 9 "...........", -- 10 -- Level 4 "...........", -- 0 "...........", -- 1 "...........", -- 2 "........aa.", -- 3 "......ccb..", -- 4 ".....dd....", -- 5 ".....e.....", -- 6 "....fe.....", -- 7 "....f......", -- 8 "...........", -- 9 "...........", -- 10 -- Level 5 "...........", -- 0 "...........", -- 1 "...........", -- 2 "...........", -- 3 ".........a.", -- 4 ".......cbba", -- 5 "......dc...", -- 6 "......d....", -- 7 ".....ee....", -- 8 "....ff.....", -- 9 "...........", -- 10 -- Level 6 "...........", -- 0 "...........", -- 1 "...........", -- 2 "...........", -- 3 "...........", -- 4 "...........", -- 5 "........cba", -- 6 ".......dcba", -- 7 ".......dcb.", -- 8 ".....fe....", -- 9 ".....f.....", -- 10 -- Level 7 "...........", -- 0 "...........", -- 1 "...........", -- 2 "...........", -- 3 "...........", -- 4 "...........", -- 5 "...........", -- 6 "...........", -- 7 "..........a", -- 8 ".......dcba", -- 9 ".....fedcba", -- 10 }, }, -- CurveUpSingle { OriginData = { ExportName = "StraightDouble", Name = "Cube 88", GalleryName = "Cube", GalleryIndex = "88", ID = "466", CreatorName = "Aloe_vera", }, Size = { x = 16, y = 1, z = 12, }, Hitbox = { MinX = 0, MinY = -2, MinZ = 0, MaxX = 15, MaxY = 2, MaxZ = 11, }, Connectors = { { Type = -2, RelX = 0, RelY = 1, RelZ = 11, Direction = 4, -- X- }, { Type = 2, RelX = 0, RelY = 1, RelZ = 0, Direction = 4, -- X- }, { Type = -2, RelX = 15, RelY = 1, RelZ = 0, Direction = 5, -- X+ }, { Type = 2, RelX = 15, RelY = 1, RelZ = 11, Direction = 5, -- X+ }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "None", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a: 35:11", -- wool "b: 35: 3", -- wool "c: 35: 5", -- wool "d: 35: 4", -- wool "e: 35: 1", -- wool "f: 35:14", -- wool "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "aaaaaaaaaaaaaaaa", -- 0 "bbbbbbbbbbbbbbbb", -- 1 "cccccccccccccccc", -- 2 "dddddddddddddddd", -- 3 "eeeeeeeeeeeeeeee", -- 4 "ffffffffffffffff", -- 5 "ffffffffffffffff", -- 6 "eeeeeeeeeeeeeeee", -- 7 "dddddddddddddddd", -- 8 "cccccccccccccccc", -- 9 "bbbbbbbbbbbbbbbb", -- 10 "aaaaaaaaaaaaaaaa", -- 11 }, }, -- StraightDouble { OriginData = { ExportName = "CurveDouble", Name = "Cube 89", GalleryName = "Cube", GalleryIndex = "89", ID = "467", CreatorName = "Aloe_vera", }, Size = { x = 14, y = 1, z = 14, }, Hitbox = { MinX = 0, MinY = -2, MinZ = 0, MaxX = 13, MaxY = 2, MaxZ = 13, }, Connectors = { { Type = 2, RelX = 2, RelY = 1, RelZ = 13, Direction = 3, -- Z+ }, { Type = 2, RelX = 0, RelY = 1, RelZ = 0, Direction = 4, -- X- }, { Type = -2, RelX = 0, RelY = 1, RelZ = 11, Direction = 4, -- X- }, { Type = -2, RelX = 13, RelY = 1, RelZ = 13, Direction = 3, -- Z+ }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "None", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a: 35:11", -- wool "b: 35: 3", -- wool "c: 35: 5", -- wool "d: 35: 4", -- wool "e: 35: 1", -- wool "f: 35:14", -- wool "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "aaaaaa........", -- 0 "bbbbbba.......", -- 1 "cccccbbaaa....", -- 2 "dddddccbbaa...", -- 3 "eeeeeddccbaa..", -- 4 "fffffeddccba..", -- 5 "ffffffeedcbaa.", -- 6 "eeeefffeddcba.", -- 7 "dddeefffedcbba", -- 8 "cccddefffedcba", -- 9 "bbccdeeffedcba", -- 10 "abbccdeffedcba", -- 11 ".abbcdeffedcba", -- 12 "..abcdeffedcba", -- 13 }, }, -- CurveDouble { OriginData = { ExportName = "SlopeUpDouble", Name = "Cube 90", GalleryName = "Cube", GalleryIndex = "90", ID = "468", CreatorName = "Aloe_vera", }, Size = { x = 16, y = 8, z = 12, }, Hitbox = { MinX = 0, MinY = -2, MinZ = 0, MaxX = 15, MaxY = 9, MaxZ = 11, }, Connectors = { { Type = -2, RelX = 0, RelY = 1, RelZ = 11, Direction = 4, -- X- }, { Type = 2, RelX = 0, RelY = 1, RelZ = 0, Direction = 4, -- X- }, { Type = -2, RelX = 15, RelY = 8, RelZ = 0, Direction = 5, -- X+ }, { Type = 2, RelX = 15, RelY = 8, RelZ = 11, Direction = 5, -- X+ }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "None", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a: 35:11", -- wool "b: 35: 3", -- wool "c: 35: 5", -- wool "d: 35: 4", -- wool "e: 35: 1", -- wool "f: 35:14", -- wool "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "aa..............", -- 0 "bb..............", -- 1 "cc..............", -- 2 "dd..............", -- 3 "ee..............", -- 4 "ff..............", -- 5 "ff..............", -- 6 "ee..............", -- 7 "dd..............", -- 8 "cc..............", -- 9 "bb..............", -- 10 "aa..............", -- 11 -- Level 1 "..aa............", -- 0 "..bb............", -- 1 "..cc............", -- 2 "..dd............", -- 3 "..ee............", -- 4 "..ff............", -- 5 "..ff............", -- 6 "..ee............", -- 7 "..dd............", -- 8 "..cc............", -- 9 "..bb............", -- 10 "..aa............", -- 11 -- Level 2 "....aa..........", -- 0 "....bb..........", -- 1 "....cc..........", -- 2 "....dd..........", -- 3 "....ee..........", -- 4 "....ff..........", -- 5 "....ff..........", -- 6 "....ee..........", -- 7 "....dd..........", -- 8 "....cc..........", -- 9 "....bb..........", -- 10 "....aa..........", -- 11 -- Level 3 "......aa........", -- 0 "......bb........", -- 1 "......cc........", -- 2 "......dd........", -- 3 "......ee........", -- 4 "......ff........", -- 5 "......ff........", -- 6 "......ee........", -- 7 "......dd........", -- 8 "......cc........", -- 9 "......bb........", -- 10 "......aa........", -- 11 -- Level 4 "........aa......", -- 0 "........bb......", -- 1 "........cc......", -- 2 "........dd......", -- 3 "........ee......", -- 4 "........ff......", -- 5 "........ff......", -- 6 "........ee......", -- 7 "........dd......", -- 8 "........cc......", -- 9 "........bb......", -- 10 "........aa......", -- 11 -- Level 5 "..........aa....", -- 0 "..........bb....", -- 1 "..........cc....", -- 2 "..........dd....", -- 3 "..........ee....", -- 4 "..........ff....", -- 5 "..........ff....", -- 6 "..........ee....", -- 7 "..........dd....", -- 8 "..........cc....", -- 9 "..........bb....", -- 10 "..........aa....", -- 11 -- Level 6 "............aa..", -- 0 "............bb..", -- 1 "............cc..", -- 2 "............dd..", -- 3 "............ee..", -- 4 "............ff..", -- 5 "............ff..", -- 6 "............ee..", -- 7 "............dd..", -- 8 "............cc..", -- 9 "............bb..", -- 10 "............aa..", -- 11 -- Level 7 "..............aa", -- 0 "..............bb", -- 1 "..............cc", -- 2 "..............dd", -- 3 "..............ee", -- 4 "..............ff", -- 5 "..............ff", -- 6 "..............ee", -- 7 "..............dd", -- 8 "..............cc", -- 9 "..............bb", -- 10 "..............aa", -- 11 }, }, -- SlopeUpDouble { OriginData = { ExportName = "CurveUpDouble", Name = "Cube 92", GalleryName = "Cube", GalleryIndex = "92", ID = "470", CreatorName = "Aloe_vera", }, Size = { x = 14, y = 8, z = 14, }, Hitbox = { MinX = 0, MinY = -2, MinZ = 0, MaxX = 13, MaxY = 9, MaxZ = 13, }, Connectors = { { Type = -2, RelX = 0, RelY = 1, RelZ = 11, Direction = 4, -- X- }, { Type = 2, RelX = 0, RelY = 1, RelZ = 0, Direction = 4, -- X- }, { Type = 2, RelX = 2, RelY = 8, RelZ = 13, Direction = 3, -- Z+ }, { Type = -2, RelX = 13, RelY = 8, RelZ = 13, Direction = 3, -- Z+ }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "None", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a: 35:11", -- wool "b: 35: 3", -- wool "c: 35: 5", -- wool "d: 35: 4", -- wool "e: 35: 1", -- wool "f: 35:14", -- wool "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "a.............", -- 0 "b.............", -- 1 "c.............", -- 2 "d.............", -- 3 "e.............", -- 4 "f.............", -- 5 "f.............", -- 6 "e.............", -- 7 "d.............", -- 8 "c.............", -- 9 "b.............", -- 10 "a.............", -- 11 "..............", -- 12 "..............", -- 13 -- Level 1 ".aa...........", -- 0 ".bb...........", -- 1 ".cc...........", -- 2 ".dd...........", -- 3 ".ee...........", -- 4 ".f............", -- 5 ".f............", -- 6 ".e............", -- 7 ".d............", -- 8 ".c............", -- 9 ".b............", -- 10 ".b............", -- 11 "..............", -- 12 "..............", -- 13 -- Level 2 "...aaa........", -- 0 "...bb.........", -- 1 "...cc.........", -- 2 "...dd.........", -- 3 "...ee.........", -- 4 "..ff..........", -- 5 "..ff..........", -- 6 "..ee..........", -- 7 "..de..........", -- 8 "..c...........", -- 9 ".b............", -- 10 ".b............", -- 11 "..............", -- 12 "..............", -- 13 -- Level 3 "..............", -- 0 ".....baa......", -- 1 ".....bbaaa....", -- 2 "....dccbba....", -- 3 "....eddcc.....", -- 4 "....fedd......", -- 5 "....ffee......", -- 6 "....ff........", -- 7 "....e.........", -- 8 "...dd.........", -- 9 "..cc..........", -- 10 "..b...........", -- 11 ".a............", -- 12 "..............", -- 13 -- Level 4 "..............", -- 0 "..............", -- 1 "..............", -- 2 "..........a...", -- 3 ".........ba...", -- 4 "........cc....", -- 5 ".......edc....", -- 6 "......fedd....", -- 7 ".....ff.......", -- 8 "....de........", -- 9 "...cde........", -- 10 "..b...........", -- 11 ".a............", -- 12 "..............", -- 13 -- Level 5 "..............", -- 0 "..............", -- 1 "..............", -- 2 "..............", -- 3 "...........a..", -- 4 "..........ba..", -- 5 "..........baa.", -- 6 "..........cba.", -- 7 ".......fedcb..", -- 8 "......fffed...", -- 9 ".....eef......", -- 10 "...ccd........", -- 11 "..b...........", -- 12 "..............", -- 13 -- Level 6 "..............", -- 0 "..............", -- 1 "..............", -- 2 "..............", -- 3 "..............", -- 4 "..............", -- 5 "..............", -- 6 "..............", -- 7 "............ba", -- 8 "...........cba", -- 9 "........fedcba", -- 10 "......effedc..", -- 11 "..bbcdef......", -- 12 "..a...........", -- 13 -- Level 7 "..............", -- 0 "..............", -- 1 "..............", -- 2 "..............", -- 3 "..............", -- 4 "..............", -- 5 "..............", -- 6 "..............", -- 7 "..............", -- 8 "..............", -- 9 "..............", -- 10 "............ba", -- 11 "........fedcba", -- 12 "..abcdeffedcba", -- 13 }, }, -- CurveUpDouble { OriginData = { ExportName = "SplitTee", Name = "Cube 93", GalleryName = "Cube", GalleryIndex = "93", ID = "471", CreatorName = "Aloe_vera", }, Size = { x = 16, y = 1, z = 14, }, Hitbox = { MinX = 0, MinY = -2, MinZ = 0, MaxX = 15, MaxY = 2, MaxZ = 13, }, Connectors = { { Type = -2, RelX = 0, RelY = 1, RelZ = 11, Direction = 4, -- X- }, { Type = 2, RelX = 0, RelY = 1, RelZ = 0, Direction = 4, -- X- }, { Type = -1, RelX = 15, RelY = 1, RelZ = 3, Direction = 5, -- X+ }, { Type = 1, RelX = 5, RelY = 1, RelZ = 13, Direction = 3, -- Z+ }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "None", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a: 35:11", -- wool "b: 35: 3", -- wool "c: 35: 5", -- wool "d: 35: 4", -- wool "e: 35: 1", -- wool "f: 35:14", -- wool "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "aaaaaa..........", -- 0 "bbbbbbaaa.......", -- 1 "ccccccbbbaaa....", -- 2 "ddddddcccbbbaaaa", -- 3 "eeeeeedddcccbbbb", -- 4 "ffffffeeedddcccc", -- 5 "fffffffffeeedddd", -- 6 "eeeeff...fffeeee", -- 7 "dddeeff.....ffff", -- 8 "cccddeff........", -- 9 "bbbccdeef.......", -- 10 "aaabbcddef......", -- 11 "...aabcddef.....", -- 12 ".....abcdef.....", -- 13 }, }, -- SplitTee { OriginData = { ExportName = "CurveSingleLeft", Name = "Cube 97", GalleryName = "Cube", GalleryIndex = "97", ID = "475", CreatorName = "Aloe_vera", }, Size = { x = 11, y = 1, z = 11, }, Hitbox = { MinX = 0, MinY = -2, MinZ = 0, MaxX = 10, MaxY = 2, MaxZ = 10, }, Connectors = { { Type = -1, RelX = 0, RelY = 1, RelZ = 10, Direction = 4, -- X- }, { Type = 1, RelX = 10, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "None", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a: 35:14", -- wool "b: 35: 1", -- wool "c: 35: 4", -- wool "d: 35: 5", -- wool "e: 35: 3", -- wool "f: 35:11", -- wool "m: 19: 0", -- sponge }, BlockData = { -- Level 0 ".....abcdef", -- 0 "....aabcdef", -- 1 "....abbcdef", -- 2 "...aabccdef", -- 3 ".aaabbcddef", -- 4 "aabbbccdeef", -- 5 "bbbcccddef.", -- 6 "ccccdddeff.", -- 7 "dddddeeff..", -- 8 "eeeeeeff...", -- 9 "ffffff.....", -- 10 }, }, -- CurveSingleLeft { OriginData = { ExportName = "SlopeDownFromTopSingle", Name = "Cube 98", GalleryName = "Cube", GalleryIndex = "98", ID = "476", CreatorName = "Aloe_vera", }, Size = { x = 16, y = 8, z = 6, }, Hitbox = { MinX = 0, MinY = -2, MinZ = 0, MaxX = 15, MaxY = 9, MaxZ = 5, }, Connectors = { { Type = -1, RelX = 0, RelY = 8, RelZ = 5, Direction = 4, -- X- }, { Type = 1, RelX = 15, RelY = 1, RelZ = 5, Direction = 5, -- X+ }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "None", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a: 35:14", -- wool "b: 35: 1", -- wool "c: 35: 4", -- wool "d: 35: 5", -- wool "e: 35: 3", -- wool "f: 35:11", -- wool "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "..............aa", -- 0 "..............bb", -- 1 "..............cc", -- 2 "..............dd", -- 3 "..............ee", -- 4 "..............ff", -- 5 -- Level 1 "............aa..", -- 0 "............bb..", -- 1 "............cc..", -- 2 "............dd..", -- 3 "............ee..", -- 4 "............ff..", -- 5 -- Level 2 "..........aa....", -- 0 "..........bb....", -- 1 "..........cc....", -- 2 "..........dd....", -- 3 "..........ee....", -- 4 "..........ff....", -- 5 -- Level 3 "........aa......", -- 0 "........bb......", -- 1 "........cc......", -- 2 "........dd......", -- 3 "........ee......", -- 4 "........ff......", -- 5 -- Level 4 "......aa........", -- 0 "......bb........", -- 1 "......cc........", -- 2 "......dd........", -- 3 "......ee........", -- 4 "......ff........", -- 5 -- Level 5 "....aa..........", -- 0 "....bb..........", -- 1 "....cc..........", -- 2 "....dd..........", -- 3 "....ee..........", -- 4 "....ff..........", -- 5 -- Level 6 "..aa............", -- 0 "..bb............", -- 1 "..cc............", -- 2 "..dd............", -- 3 "..ee............", -- 4 "..ff............", -- 5 -- Level 7 "aa..............", -- 0 "bb..............", -- 1 "cc..............", -- 2 "dd..............", -- 3 "ee..............", -- 4 "ff..............", -- 5 }, }, -- SlopeDownFromTopSingle { OriginData = { ExportName = "CurveDownFromTopSingle", Name = "Cube 100", GalleryName = "Cube", GalleryIndex = "100", ID = "478", CreatorName = "Aloe_vera", }, Size = { x = 11, y = 8, z = 11, }, Hitbox = { MinX = 0, MinY = -2, MinZ = 0, MaxX = 10, MaxY = 9, MaxZ = 10, }, Connectors = { { Type = -1, RelX = 0, RelY = 8, RelZ = 5, Direction = 4, -- X- }, { Type = 1, RelX = 5, RelY = 1, RelZ = 10, Direction = 3, -- Z+ }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "None", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a: 35:14", -- wool "b: 35: 5", -- wool "c: 35: 4", -- wool "d: 35: 1", -- wool "e: 35:11", -- wool "f: 35: 3", -- wool "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "...........", -- 0 "...........", -- 1 "...........", -- 2 "...........", -- 3 "...........", -- 4 "...........", -- 5 "...........", -- 6 "...........", -- 7 "..........a", -- 8 ".......bcda", -- 9 ".....efbcda", -- 10 -- Level 1 "...........", -- 0 "...........", -- 1 "...........", -- 2 "...........", -- 3 "...........", -- 4 "...........", -- 5 "........cda", -- 6 ".......bcda", -- 7 ".......bcd.", -- 8 ".....ef....", -- 9 "...........", -- 10 -- Level 2 "...........", -- 0 "...........", -- 1 "...........", -- 2 "...........", -- 3 ".........a.", -- 4 ".......cdda", -- 5 "......bc...", -- 6 "......b....", -- 7 ".....ff....", -- 8 "....ee.....", -- 9 "...........", -- 10 -- Level 3 "...........", -- 0 "...........", -- 1 "...........", -- 2 "........aa.", -- 3 "......ccd..", -- 4 ".....bb....", -- 5 ".....f.....", -- 6 "....ef.....", -- 7 "....e......", -- 8 "...........", -- 9 "...........", -- 10 -- Level 4 "...........", -- 0 "...........", -- 1 "......daa..", -- 2 ".....ccd...", -- 3 "....bb.....", -- 4 "....f......", -- 5 "...ef......", -- 6 "...ee......", -- 7 "...........", -- 8 "...........", -- 9 "...........", -- 10 -- Level 5 "...........", -- 0 ".....daa...", -- 1 "...ccd.....", -- 2 "...bc......", -- 3 "...b.......", -- 4 "..ff.......", -- 5 "..ee.......", -- 6 "...........", -- 7 "...........", -- 8 "...........", -- 9 "...........", -- 10 -- Level 6 "...aaa.....", -- 0 "..ddd......", -- 1 ".cc........", -- 2 ".bb........", -- 3 ".ff........", -- 4 ".e.........", -- 5 ".ee........", -- 6 "...........", -- 7 "...........", -- 8 "...........", -- 9 "...........", -- 10 -- Level 7 "aaa........", -- 0 "dd.........", -- 1 "cc.........", -- 2 "bb.........", -- 3 "ff.........", -- 4 "e..........", -- 5 "...........", -- 6 "...........", -- 7 "...........", -- 8 "...........", -- 9 "...........", -- 10 }, }, -- CurveDownFromTopSingle }, -- Pieces } ================================================ FILE: Server/Prefabs/PieceStructures/TestRails.cubeset ================================================ -- TestRails.cubeset -- Defines the prefabs in the group TestRails -- NOTE: This file has been generated automatically by GalExport! -- Any manual changes will be overwritten by the next automatic export! Cubeset = { Metadata = { CubesetFormatVersion = 1, ExportDate = "2016-12-03 15:53:05", ["GridSizeX"] = "10", ["GridSizeZ"] = "10", ["IntendedUse"] = "PieceStructures", ["MaxDepth"] = "0", ["MaxOffsetX"] = "1", ["MaxOffsetZ"] = "1", ["MaxStructureSizeX"] = "20", ["MaxStructureSizeZ"] = "20", }, Pieces = { { OriginData = { ExportName = "RegularRail", Name = "Plains 247", GalleryName = "Plains", GalleryIndex = "247", ID = "742", CreatorName = "Aloe_vera", }, Size = { x = 7, y = 3, z = 7, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 6, MaxY = 2, MaxZ = 6, }, Connectors = { { Type = 1, RelX = 6, RelY = 1, RelZ = 3, Direction = 5, -- X+ }, { Type = -1, RelX = 6, RelY = 1, RelZ = 3, Direction = 5, -- X+ }, { Type = 1, RelX = 3, RelY = 1, RelZ = 6, Direction = 3, -- Z+ }, { Type = -1, RelX = 3, RelY = 1, RelZ = 6, Direction = 3, -- Z+ }, { Type = 1, RelX = 0, RelY = 1, RelZ = 3, Direction = 4, -- X- }, { Type = -1, RelX = 0, RelY = 1, RelZ = 3, Direction = 4, -- X- }, { Type = 1, RelX = 3, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, { Type = -1, RelX = 3, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "None", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a: 1: 0", -- stone "b: 5: 0", -- planks "c: 66: 6", -- tracks "d: 66: 2", -- tracks "e: 66: 3", -- tracks "f: 66: 7", -- tracks "g: 66: 5", -- tracks "h: 50: 5", -- torch "i: 66: 4", -- tracks "j: 66: 9", -- tracks "k: 66: 8", -- tracks "l: 66: 1", -- tracks "m: 19: 0", -- sponge "n: 66: 0", -- tracks }, BlockData = { -- Level 0 "aaab...", -- 0 "abbbbb.", -- 1 "abbb.b.", -- 2 "bbbb.bb", -- 3 ".b...b.", -- 4 ".bbbbb.", -- 5 "...b...", -- 6 -- Level 1 ".......", -- 0 ".cdbef.", -- 1 ".gh..g.", -- 2 ".b.h.b.", -- 3 ".i...i.", -- 4 ".jdbek.", -- 5 ".......", -- 6 -- Level 2 ".......", -- 0 "...l...", -- 1 ".......", -- 2 ".n...n.", -- 3 ".......", -- 4 "...l...", -- 5 ".......", -- 6 }, }, -- RegularRail { OriginData = { ExportName = "PowerRail", Name = "Plains 248", GalleryName = "Plains", GalleryIndex = "248", ID = "743", CreatorName = "Aloe_vera", }, Size = { x = 7, y = 3, z = 7, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 6, MaxY = 2, MaxZ = 6, }, Connectors = { { Type = 1, RelX = 6, RelY = 1, RelZ = 3, Direction = 5, -- X+ }, { Type = -1, RelX = 6, RelY = 1, RelZ = 3, Direction = 5, -- X+ }, { Type = 1, RelX = 3, RelY = 1, RelZ = 6, Direction = 3, -- Z+ }, { Type = -1, RelX = 3, RelY = 1, RelZ = 6, Direction = 3, -- Z+ }, { Type = 1, RelX = 0, RelY = 1, RelZ = 3, Direction = 4, -- X- }, { Type = -1, RelX = 0, RelY = 1, RelZ = 3, Direction = 4, -- X- }, { Type = 1, RelX = 3, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, { Type = -1, RelX = 3, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, { Type = 1, RelX = 6, RelY = 1, RelZ = 3, Direction = 5, -- X+ }, { Type = -1, RelX = 6, RelY = 1, RelZ = 3, Direction = 5, -- X+ }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "None", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a: 1: 0", -- stone "b: 5: 0", -- planks "c: 27: 0", -- poweredrail "d: 27: 2", -- poweredrail "e: 27: 3", -- poweredrail "f: 27: 5", -- poweredrail "g: 50: 5", -- torch "h: 66: 0", -- tracks "i: 66: 1", -- tracks "j: 66: 8", -- tracks "k: 27: 4", -- poweredrail "l: 27: 1", -- poweredrail "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "aaab...", -- 0 "abbbbb.", -- 1 "abbb.b.", -- 2 "bbbb.bb", -- 3 ".b...b.", -- 4 ".bbbbb.", -- 5 "...b...", -- 6 -- Level 1 ".......", -- 0 ".cdbec.", -- 1 ".fgh.f.", -- 2 ".bij.b.", -- 3 ".k...k.", -- 4 ".cdbec.", -- 5 ".......", -- 6 -- Level 2 ".......", -- 0 "...l...", -- 1 ".......", -- 2 ".c...c.", -- 3 ".......", -- 4 "...l...", -- 5 ".......", -- 6 }, }, -- PowerRail { OriginData = { ExportName = "CentralPiece", Name = "Plains 249", GalleryName = "Plains", GalleryIndex = "249", ID = "744", CreatorName = "Aloe_vera", }, Size = { x = 6, y = 3, z = 6, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 5, MaxY = 2, MaxZ = 5, }, Connectors = { { Type = 1, RelX = 3, RelY = 1, RelZ = 6, Direction = 3, -- Z+ }, { Type = 1, RelX = 0, RelY = 1, RelZ = 3, Direction = 4, -- X- }, { Type = -1, RelX = 0, RelY = 1, RelZ = 3, Direction = 4, -- X- }, { Type = -1, RelX = 3, RelY = 1, RelZ = 6, Direction = 3, -- Z+ }, { Type = 1, RelX = 6, RelY = 1, RelZ = 3, Direction = 5, -- X+ }, { Type = -1, RelX = 6, RelY = 1, RelZ = 3, Direction = 5, -- X+ }, { Type = 1, RelX = 3, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, { Type = -1, RelX = 3, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillNonAir", ["IsStarting"] = "1", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", ["VerticalStrategy"] = "TerrainOrOceanTop|1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 1: 0", -- stone "b: 5: 0", -- planks "c: 66: 6", -- tracks "d: 66: 2", -- tracks "e: 66: 3", -- tracks "f: 66: 7", -- tracks "g: 66: 5", -- tracks "h: 50: 5", -- torch "i: 66: 0", -- tracks "j: 66: 1", -- tracks "k: 66: 8", -- tracks "l: 66: 4", -- tracks "m: 19: 0", -- sponge "n: 66: 9", -- tracks }, BlockData = { -- Level 0 "aaab..", -- 0 "abbbbb", -- 1 "abbb.b", -- 2 "bbbb.b", -- 3 ".b...b", -- 4 ".bbbbb", -- 5 -- Level 1 "......", -- 0 ".cdbef", -- 1 ".ghi.g", -- 2 ".bjk.b", -- 3 ".l...l", -- 4 ".ndbek", -- 5 -- Level 2 "......", -- 0 "...j..", -- 1 "......", -- 2 ".i...i", -- 3 "......", -- 4 "...j..", -- 5 }, }, -- CentralPiece { OriginData = { ExportName = "DetectorRail", Name = "Plains 250", GalleryName = "Plains", GalleryIndex = "250", ID = "745", CreatorName = "Aloe_vera", }, Size = { x = 7, y = 3, z = 7, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 6, MaxY = 2, MaxZ = 6, }, Connectors = { { Type = 1, RelX = 6, RelY = 1, RelZ = 3, Direction = 5, -- X+ }, { Type = -1, RelX = 6, RelY = 1, RelZ = 3, Direction = 5, -- X+ }, { Type = 1, RelX = 3, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, { Type = -1, RelX = 3, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, { Type = 1, RelX = 0, RelY = 1, RelZ = 3, Direction = 4, -- X- }, { Type = -1, RelX = 0, RelY = 1, RelZ = 3, Direction = 4, -- X- }, { Type = 1, RelX = 3, RelY = 1, RelZ = 6, Direction = 3, -- Z+ }, { Type = -1, RelX = 3, RelY = 1, RelZ = 6, Direction = 3, -- Z+ }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "None", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a: 1: 0", -- stone "b: 5: 0", -- planks "c: 28: 0", -- detectorrail "d: 28: 2", -- detectorrail "e: 28: 3", -- detectorrail "f: 28: 5", -- detectorrail "g: 50: 5", -- torch "h: 66: 0", -- tracks "i: 66: 1", -- tracks "j: 66: 8", -- tracks "k: 28: 4", -- detectorrail "l: 28: 1", -- detectorrail "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "aaab...", -- 0 "abbbbb.", -- 1 "abbb.b.", -- 2 "bbbb.bb", -- 3 ".b...b.", -- 4 ".bbbbb.", -- 5 "...b...", -- 6 -- Level 1 ".......", -- 0 ".cdbec.", -- 1 ".fgh.f.", -- 2 ".bij.b.", -- 3 ".k...k.", -- 4 ".cdbec.", -- 5 ".......", -- 6 -- Level 2 ".......", -- 0 "...l...", -- 1 ".......", -- 2 ".c...c.", -- 3 ".......", -- 4 "...l...", -- 5 ".......", -- 6 }, }, -- DetectorRail { OriginData = { ExportName = "ActivatorRail", Name = "Plains 251", GalleryName = "Plains", GalleryIndex = "251", ID = "746", CreatorName = "Aloe_vera", }, Size = { x = 7, y = 3, z = 7, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 6, MaxY = 2, MaxZ = 6, }, Connectors = { { Type = 1, RelX = 6, RelY = 1, RelZ = 3, Direction = 5, -- X+ }, { Type = -1, RelX = 6, RelY = 1, RelZ = 3, Direction = 5, -- X+ }, { Type = 1, RelX = 3, RelY = 1, RelZ = 6, Direction = 3, -- Z+ }, { Type = -1, RelX = 3, RelY = 1, RelZ = 6, Direction = 3, -- Z+ }, { Type = 1, RelX = 0, RelY = 1, RelZ = 3, Direction = 4, -- X- }, { Type = -1, RelX = 0, RelY = 1, RelZ = 3, Direction = 4, -- X- }, { Type = 1, RelX = 3, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, { Type = -1, RelX = 3, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "None", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a: 1: 0", -- stone "b: 5: 0", -- planks "c:157: 0", -- activatorrail "d:157: 2", -- activatorrail "e:157: 3", -- activatorrail "f:157: 5", -- activatorrail "g: 50: 5", -- torch "h: 66: 0", -- tracks "i: 66: 1", -- tracks "j: 66: 8", -- tracks "k:157: 4", -- activatorrail "l:157: 1", -- activatorrail "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "aaab...", -- 0 "abbbbb.", -- 1 "abbb.b.", -- 2 "bbbb.bb", -- 3 ".b...b.", -- 4 ".bbbbb.", -- 5 "...b...", -- 6 -- Level 1 ".......", -- 0 ".cdbec.", -- 1 ".fgh.f.", -- 2 ".bij.b.", -- 3 ".k...k.", -- 4 ".cdbec.", -- 5 ".......", -- 6 -- Level 2 ".......", -- 0 "...l...", -- 1 ".......", -- 2 ".c...c.", -- 3 ".......", -- 4 "...l...", -- 5 ".......", -- 6 }, }, -- ActivatorRail }, -- Pieces } ================================================ FILE: Server/Prefabs/PieceStructures/TreePaths.cubeset ================================================ -- TreePaths.cubeset -- Defines the prefabs in the group TreePaths -- NOTE: This file has been generated automatically by GalExport! -- Any manual changes will be overwritten by the next automatic export! Cubeset = { Metadata = { CubesetFormatVersion = 1, ExportDate = "2016-11-23 15:08:10", ["AllowedBiomes"] = "Jungle, JungleM, JungleHills, JungleEdge, JungleEdgeM", ["GridSizeX"] = "256", ["GridSizeZ"] = "256", ["IntendedUse"] = "PieceStructures", ["MaxDepth"] = "10", ["MaxOffsetX"] = "128", ["MaxOffsetZ"] = "128", ["MaxStructureSizeX"] = "256", ["MaxStructureSizeZ"] = "256", }, Pieces = { { OriginData = { ExportName = "CrossNoTop", Name = "Cube 140", GalleryName = "Cube", GalleryIndex = "140", ID = "1185", CreatorName = "xoft2", }, Size = { x = 15, y = 16, z = 15, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 14, MaxY = 15, MaxZ = 14, }, Connectors = { { Type = 0, RelX = 7, RelY = 7, RelZ = 0, Direction = 2, -- Z- }, { Type = 0, RelX = 0, RelY = 7, RelZ = 7, Direction = 4, -- X- }, { Type = 0, RelX = 7, RelY = 7, RelZ = 14, Direction = 3, -- Z+ }, { Type = 0, RelX = 14, RelY = 7, RelZ = 7, Direction = 5, -- X+ }, { Type = -2, RelX = 7, RelY = 15, RelZ = 7, Direction = 1, -- Y+ }, { Type = 1, RelX = 7, RelY = 0, RelZ = 7, Direction = 0, -- Y- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "2", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "None", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", ["VerticalLimit"] = "AboveTerrainAndOcean|20|60", }, BlockDefinitions = { ".: 0: 0", -- air "a: 65: 2", -- ladder "b: 17: 3", -- tree "c: 65: 4", -- ladder "d: 65: 5", -- ladder "e: 65: 3", -- ladder "f: 5: 3", -- planks "g:190: 0", -- junglefence "h: 50: 5", -- torch "i: 50: 4", -- torch "j: 50: 2", -- torch "k: 50: 1", -- torch "l: 50: 3", -- torch "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmammmmmmm", -- 5 "mmmmmmbbbmmmmmm", -- 6 "mmmmmcbbbdmmmmm", -- 7 "mmmmmmbbbmmmmmm", -- 8 "mmmmmmmemmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 1 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmammmmmmm", -- 5 "mmmmmmbbbmmmmmm", -- 6 "mmmmmcbbbdmmmmm", -- 7 "mmmmmmbbbmmmmmm", -- 8 "mmmmmmmemmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 2 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmammmmmmm", -- 5 "mmmmmmbbbmmmmmm", -- 6 "mmmmmcbbbdmmmmm", -- 7 "mmmmmmbbbmmmmmm", -- 8 "mmmmmmmemmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 3 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmammmmmmm", -- 5 "mmmmmmbbbmmmmmm", -- 6 "mmmmmcbbbdmmmmm", -- 7 "mmmmmmbbbmmmmmm", -- 8 "mmmmmmmemmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 4 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmammmmmmm", -- 5 "mmmmmmbbbmmmmmm", -- 6 "mmmmmcbbbdmmmmm", -- 7 "mmmmmmbbbmmmmmm", -- 8 "mmmmmmmemmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 5 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmammmmmmm", -- 5 "mmmmmmbbbmmmmmm", -- 6 "mmmmmcbbbdmmmmm", -- 7 "mmmmmmbbbmmmmmm", -- 8 "mmmmmmmemmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 6 "mmmmmmfffmmmmmm", -- 0 "mmmmmmfffmmmmmm", -- 1 "mmmmmmfffmmmmmm", -- 2 "mmmmfffffffmmmm", -- 3 "mmmfffffffffmmm", -- 4 "mmmffffaffffmmm", -- 5 "ffffffbbbffffff", -- 6 "fffffcbbbdfffff", -- 7 "ffffffbbbffffff", -- 8 "mmmffffeffffmmm", -- 9 "mmmfffffffffmmm", -- 10 "mmmmfffffffmmmm", -- 11 "mmmmmmfffmmmmmm", -- 12 "mmmmmmfffmmmmmm", -- 13 "mmmmmmfffmmmmmm", -- 14 -- Level 7 "mmmmmmg.gmmmmmm", -- 0 "mmmmmmg.gmmmmmm", -- 1 "mmmmmmg.gmmmmmm", -- 2 "mmmmggg.gggmmmm", -- 3 "mmmgg.....ggmmm", -- 4 "mmmg.......gmmm", -- 5 "gggg..bbb..gggg", -- 6 "......bbb......", -- 7 "gggg..bbb..gggg", -- 8 "mmmg.......gmmm", -- 9 "mmmgg.....ggmmm", -- 10 "mmmmggg.gggmmmm", -- 11 "mmmmmmg.gmmmmmm", -- 12 "mmmmmmg.gmmmmmm", -- 13 "mmmmmmg.gmmmmmm", -- 14 -- Level 8 "mmmmmm...mmmmmm", -- 0 "mmmmmm...mmmmmm", -- 1 "mmmmmm...mmmmmm", -- 2 "mmmm..h.h..mmmm", -- 3 "mmm.h.....h.mmm", -- 4 "mmm...i.i...mmm", -- 5 "...h.jbbbk.h...", -- 6 "......bbb......", -- 7 "...h.jbbbk.h...", -- 8 "mmm...l.l...mmm", -- 9 "mmm.h.....h.mmm", -- 10 "mmmm..h.h..mmmm", -- 11 "mmmmmm...mmmmmm", -- 12 "mmmmmm...mmmmmm", -- 13 "mmmmmm...mmmmmm", -- 14 -- Level 9 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmmmmmmmmm", -- 5 "mmmmmmbbbmmmmmm", -- 6 "mmmmmmbbbmmmmmm", -- 7 "mmmmmmbbbmmmmmm", -- 8 "mmmmmmmmmmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 10 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmmmmmmmmm", -- 5 "mmmmmmbbbmmmmmm", -- 6 "mmmmmmbbbmmmmmm", -- 7 "mmmmmmbbbmmmmmm", -- 8 "mmmmmmmmmmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 11 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmmmmmmmmm", -- 5 "mmmmmmbbbmmmmmm", -- 6 "mmmmmmbbbmmmmmm", -- 7 "mmmmmmbbbmmmmmm", -- 8 "mmmmmmmmmmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 12 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmmmmmmmmm", -- 5 "mmmmmmbbbmmmmmm", -- 6 "mmmmmmbbbmmmmmm", -- 7 "mmmmmmbbbmmmmmm", -- 8 "mmmmmmmmmmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 13 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmmmmmmmmm", -- 5 "mmmmmmbbbmmmmmm", -- 6 "mmmmmmbbbmmmmmm", -- 7 "mmmmmmbbbmmmmmm", -- 8 "mmmmmmmmmmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 14 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmmmmmmmmm", -- 5 "mmmmmmbbbmmmmmm", -- 6 "mmmmmmbbbmmmmmm", -- 7 "mmmmmmbbbmmmmmm", -- 8 "mmmmmmmmmmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 15 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmmmmmmmmm", -- 5 "mmmmmmbbbmmmmmm", -- 6 "mmmmmmbbbmmmmmm", -- 7 "mmmmmmbbbmmmmmm", -- 8 "mmmmmmmmmmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 }, }, -- CrossNoTop { OriginData = { ExportName = "Tee", Name = "Cube 141", GalleryName = "Cube", GalleryIndex = "141", ID = "1186", CreatorName = "xoft2", }, Size = { x = 15, y = 16, z = 12, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 14, MaxY = 15, MaxZ = 14, }, Connectors = { { Type = 0, RelX = 0, RelY = 7, RelZ = 7, Direction = 4, -- X- }, { Type = 0, RelX = 7, RelY = 7, RelZ = 0, Direction = 2, -- Z- }, { Type = 0, RelX = 14, RelY = 7, RelZ = 7, Direction = 5, -- X+ }, { Type = 1, RelX = 7, RelY = 0, RelZ = 7, Direction = 0, -- Y- }, { Type = -1, RelX = 7, RelY = 15, RelZ = 7, Direction = 1, -- Y+ }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "4", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "None", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", ["VerticalLimit"] = "AboveTerrainAndOcean|20|60", }, BlockDefinitions = { ".: 0: 0", -- air "a: 65: 2", -- ladder "b: 17: 3", -- tree "c: 65: 4", -- ladder "d: 65: 5", -- ladder "e: 65: 3", -- ladder "f: 5: 3", -- planks "g:190: 0", -- junglefence "h: 50: 5", -- torch "i: 50: 4", -- torch "j: 50: 2", -- torch "k: 50: 1", -- torch "l: 50: 3", -- torch "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmammmmmmm", -- 5 "mmmmmmbbbmmmmmm", -- 6 "mmmmmcbbbdmmmmm", -- 7 "mmmmmmbbbmmmmmm", -- 8 "mmmmmmmemmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 -- Level 1 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmammmmmmm", -- 5 "mmmmmmbbbmmmmmm", -- 6 "mmmmmcbbbdmmmmm", -- 7 "mmmmmmbbbmmmmmm", -- 8 "mmmmmmmemmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 -- Level 2 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmammmmmmm", -- 5 "mmmmmmbbbmmmmmm", -- 6 "mmmmmcbbbdmmmmm", -- 7 "mmmmmmbbbmmmmmm", -- 8 "mmmmmmmemmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 -- Level 3 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmammmmmmm", -- 5 "mmmmmmbbbmmmmmm", -- 6 "mmmmmcbbbdmmmmm", -- 7 "mmmmmmbbbmmmmmm", -- 8 "mmmmmmmemmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 -- Level 4 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmammmmmmm", -- 5 "mmmmmmbbbmmmmmm", -- 6 "mmmmmcbbbdmmmmm", -- 7 "mmmmmmbbbmmmmmm", -- 8 "mmmmmmmemmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 -- Level 5 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmammmmmmm", -- 5 "mmmmmmbbbmmmmmm", -- 6 "mmmmmcbbbdmmmmm", -- 7 "mmmmmmbbbmmmmmm", -- 8 "mmmmmmmemmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 -- Level 6 "mmmmmmfffmmmmmm", -- 0 "mmmmmmfffmmmmmm", -- 1 "mmmmmmfffmmmmmm", -- 2 "mmmmfffffffmmmm", -- 3 "mmmfffffffffmmm", -- 4 "mmmffffaffffmmm", -- 5 "ffffffbbbffffff", -- 6 "fffffcbbbdfffff", -- 7 "ffffffbbbffffff", -- 8 "mmmffffeffffmmm", -- 9 "mmmfffffffffmmm", -- 10 "mmmmfffffffmmmm", -- 11 -- Level 7 "mmmmmmg.gmmmmmm", -- 0 "mmmmmmg.gmmmmmm", -- 1 "mmmmmmg.gmmmmmm", -- 2 "mmmmggg.gggmmmm", -- 3 "mmmgg.....ggmmm", -- 4 "mmmg...a...gmmm", -- 5 "gggg..bbb..gggg", -- 6 ".....cbbbd.....", -- 7 "gggg..bbb..gggg", -- 8 "mmmg...e...gmmm", -- 9 "mmmgg.....ggmmm", -- 10 "mmmmgggggggmmmm", -- 11 -- Level 8 "mmmmmm...mmmmmm", -- 0 "mmmmmm...mmmmmm", -- 1 "mmmmmm...mmmmmm", -- 2 "mmmm..h.h..mmmm", -- 3 "mmm.h.....h.mmm", -- 4 "mmm...iai...mmm", -- 5 "...h.jbbbk.h...", -- 6 ".....cbbbd.....", -- 7 "...h.jbbbk.h...", -- 8 "mmm...lel...mmm", -- 9 "mmm.h.....h.mmm", -- 10 "mmmm..h.h..mmmm", -- 11 -- Level 9 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmammmmmmm", -- 5 "mmmmmmbbbmmmmmm", -- 6 "mmmmmcbbbdmmmmm", -- 7 "mmmmmmbbbmmmmmm", -- 8 "mmmmmmmemmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 -- Level 10 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmammmmmmm", -- 5 "mmmmmmbbbmmmmmm", -- 6 "mmmmmcbbbdmmmmm", -- 7 "mmmmmmbbbmmmmmm", -- 8 "mmmmmmmemmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 -- Level 11 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmammmmmmm", -- 5 "mmmmmmbbbmmmmmm", -- 6 "mmmmmcbbbdmmmmm", -- 7 "mmmmmmbbbmmmmmm", -- 8 "mmmmmmmemmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 -- Level 12 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmammmmmmm", -- 5 "mmmmmmbbbmmmmmm", -- 6 "mmmmmcbbbdmmmmm", -- 7 "mmmmmmbbbmmmmmm", -- 8 "mmmmmmmemmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 -- Level 13 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmammmmmmm", -- 5 "mmmmmmbbbmmmmmm", -- 6 "mmmmmcbbbdmmmmm", -- 7 "mmmmmmbbbmmmmmm", -- 8 "mmmmmmmemmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 -- Level 14 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmammmmmmm", -- 5 "mmmmmmbbbmmmmmm", -- 6 "mmmmmcbbbdmmmmm", -- 7 "mmmmmmbbbmmmmmm", -- 8 "mmmmmmmemmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 -- Level 15 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmammmmmmm", -- 5 "mmmmmmbbbmmmmmm", -- 6 "mmmmmcbbbdmmmmm", -- 7 "mmmmmmbbbmmmmmm", -- 8 "mmmmmmmemmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 }, }, -- Tee { OriginData = { ExportName = "Corner", Name = "Cube 142", GalleryName = "Cube", GalleryIndex = "142", ID = "1187", CreatorName = "xoft2", }, Size = { x = 12, y = 16, z = 12, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 14, MaxY = 15, MaxZ = 14, }, Connectors = { { Type = 0, RelX = 0, RelY = 7, RelZ = 7, Direction = 4, -- X- }, { Type = 0, RelX = 7, RelY = 7, RelZ = 0, Direction = 2, -- Z- }, { Type = -1, RelX = 7, RelY = 15, RelZ = 7, Direction = 1, -- Y+ }, { Type = 1, RelX = 7, RelY = 0, RelZ = 7, Direction = 0, -- Y- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "10", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "None", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", ["VerticalLimit"] = "AboveTerrainAndOcean|20|60", }, BlockDefinitions = { ".: 0: 0", -- air "a: 65: 2", -- ladder "b: 17: 3", -- tree "c: 65: 4", -- ladder "d: 65: 5", -- ladder "e: 65: 3", -- ladder "f: 5: 3", -- planks "g:190: 0", -- junglefence "h: 50: 5", -- torch "i: 50: 4", -- torch "j: 50: 2", -- torch "k: 50: 1", -- torch "l: 50: 3", -- torch "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "mmmmmmmmmmmm", -- 0 "mmmmmmmmmmmm", -- 1 "mmmmmmmmmmmm", -- 2 "mmmmmmmmmmmm", -- 3 "mmmmmmmmmmmm", -- 4 "mmmmmmmammmm", -- 5 "mmmmmmbbbmmm", -- 6 "mmmmmcbbbdmm", -- 7 "mmmmmmbbbmmm", -- 8 "mmmmmmmemmmm", -- 9 "mmmmmmmmmmmm", -- 10 "mmmmmmmmmmmm", -- 11 -- Level 1 "mmmmmmmmmmmm", -- 0 "mmmmmmmmmmmm", -- 1 "mmmmmmmmmmmm", -- 2 "mmmmmmmmmmmm", -- 3 "mmmmmmmmmmmm", -- 4 "mmmmmmmammmm", -- 5 "mmmmmmbbbmmm", -- 6 "mmmmmcbbbdmm", -- 7 "mmmmmmbbbmmm", -- 8 "mmmmmmmemmmm", -- 9 "mmmmmmmmmmmm", -- 10 "mmmmmmmmmmmm", -- 11 -- Level 2 "mmmmmmmmmmmm", -- 0 "mmmmmmmmmmmm", -- 1 "mmmmmmmmmmmm", -- 2 "mmmmmmmmmmmm", -- 3 "mmmmmmmmmmmm", -- 4 "mmmmmmmammmm", -- 5 "mmmmmmbbbmmm", -- 6 "mmmmmcbbbdmm", -- 7 "mmmmmmbbbmmm", -- 8 "mmmmmmmemmmm", -- 9 "mmmmmmmmmmmm", -- 10 "mmmmmmmmmmmm", -- 11 -- Level 3 "mmmmmmmmmmmm", -- 0 "mmmmmmmmmmmm", -- 1 "mmmmmmmmmmmm", -- 2 "mmmmmmmmmmmm", -- 3 "mmmmmmmmmmmm", -- 4 "mmmmmmmammmm", -- 5 "mmmmmmbbbmmm", -- 6 "mmmmmcbbbdmm", -- 7 "mmmmmmbbbmmm", -- 8 "mmmmmmmemmmm", -- 9 "mmmmmmmmmmmm", -- 10 "mmmmmmmmmmmm", -- 11 -- Level 4 "mmmmmmmmmmmm", -- 0 "mmmmmmmmmmmm", -- 1 "mmmmmmmmmmmm", -- 2 "mmmmmmmmmmmm", -- 3 "mmmmmmmmmmmm", -- 4 "mmmmmmmammmm", -- 5 "mmmmmmbbbmmm", -- 6 "mmmmmcbbbdmm", -- 7 "mmmmmmbbbmmm", -- 8 "mmmmmmmemmmm", -- 9 "mmmmmmmmmmmm", -- 10 "mmmmmmmmmmmm", -- 11 -- Level 5 "mmmmmmmmmmmm", -- 0 "mmmmmmmmmmmm", -- 1 "mmmmmmmmmmmm", -- 2 "mmmmmmmmmmmm", -- 3 "mmmmmmmmmmmm", -- 4 "mmmmmmmammmm", -- 5 "mmmmmmbbbmmm", -- 6 "mmmmmcbbbdmm", -- 7 "mmmmmmbbbmmm", -- 8 "mmmmmmmemmmm", -- 9 "mmmmmmmmmmmm", -- 10 "mmmmmmmmmmmm", -- 11 -- Level 6 "mmmmmmfffmmm", -- 0 "mmmmmmfffmmm", -- 1 "mmmmmmfffmmm", -- 2 "mmmmfffffffm", -- 3 "mmmfffffffff", -- 4 "mmmffffaffff", -- 5 "ffffffbbbfff", -- 6 "fffffcbbbdff", -- 7 "ffffffbbbfff", -- 8 "mmmffffeffff", -- 9 "mmmfffffffff", -- 10 "mmmmfffffffm", -- 11 -- Level 7 "mmmmmmg.gmmm", -- 0 "mmmmmmg.gmmm", -- 1 "mmmmmmg.gmmm", -- 2 "mmmmggg.gggm", -- 3 "mmmgg.....gg", -- 4 "mmmg...a...g", -- 5 "gggg..bbb..g", -- 6 ".....cbbbd.g", -- 7 "gggg..bbb..g", -- 8 "mmmg...e...g", -- 9 "mmmgg.....gg", -- 10 "mmmmgggggggm", -- 11 -- Level 8 "mmmmmm...mmm", -- 0 "mmmmmm...mmm", -- 1 "mmmmmm...mmm", -- 2 "mmmm..h.h..m", -- 3 "mmm.h.....h.", -- 4 "mmm...iai...", -- 5 "...h.jbbbk.h", -- 6 ".....cbbbd..", -- 7 "...h.jbbbk.h", -- 8 "mmm...lel...", -- 9 "mmm.h.....h.", -- 10 "mmmm..h.h..m", -- 11 -- Level 9 "mmmmmmmmmmmm", -- 0 "mmmmmmmmmmmm", -- 1 "mmmmmmmmmmmm", -- 2 "mmmmmmmmmmmm", -- 3 "mmmmmmmmmmmm", -- 4 "mmmmmmmammmm", -- 5 "mmmmmmbbbmmm", -- 6 "mmmmmcbbbdmm", -- 7 "mmmmmmbbbmmm", -- 8 "mmmmmmmemmmm", -- 9 "mmmmmmmmmmmm", -- 10 "mmmmmmmmmmmm", -- 11 -- Level 10 "mmmmmmmmmmmm", -- 0 "mmmmmmmmmmmm", -- 1 "mmmmmmmmmmmm", -- 2 "mmmmmmmmmmmm", -- 3 "mmmmmmmmmmmm", -- 4 "mmmmmmmammmm", -- 5 "mmmmmmbbbmmm", -- 6 "mmmmmcbbbdmm", -- 7 "mmmmmmbbbmmm", -- 8 "mmmmmmmemmmm", -- 9 "mmmmmmmmmmmm", -- 10 "mmmmmmmmmmmm", -- 11 -- Level 11 "mmmmmmmmmmmm", -- 0 "mmmmmmmmmmmm", -- 1 "mmmmmmmmmmmm", -- 2 "mmmmmmmmmmmm", -- 3 "mmmmmmmmmmmm", -- 4 "mmmmmmmammmm", -- 5 "mmmmmmbbbmmm", -- 6 "mmmmmcbbbdmm", -- 7 "mmmmmmbbbmmm", -- 8 "mmmmmmmemmmm", -- 9 "mmmmmmmmmmmm", -- 10 "mmmmmmmmmmmm", -- 11 -- Level 12 "mmmmmmmmmmmm", -- 0 "mmmmmmmmmmmm", -- 1 "mmmmmmmmmmmm", -- 2 "mmmmmmmmmmmm", -- 3 "mmmmmmmmmmmm", -- 4 "mmmmmmmammmm", -- 5 "mmmmmmbbbmmm", -- 6 "mmmmmcbbbdmm", -- 7 "mmmmmmbbbmmm", -- 8 "mmmmmmmemmmm", -- 9 "mmmmmmmmmmmm", -- 10 "mmmmmmmmmmmm", -- 11 -- Level 13 "mmmmmmmmmmmm", -- 0 "mmmmmmmmmmmm", -- 1 "mmmmmmmmmmmm", -- 2 "mmmmmmmmmmmm", -- 3 "mmmmmmmmmmmm", -- 4 "mmmmmmmammmm", -- 5 "mmmmmmbbbmmm", -- 6 "mmmmmcbbbdmm", -- 7 "mmmmmmbbbmmm", -- 8 "mmmmmmmemmmm", -- 9 "mmmmmmmmmmmm", -- 10 "mmmmmmmmmmmm", -- 11 -- Level 14 "mmmmmmmmmmmm", -- 0 "mmmmmmmmmmmm", -- 1 "mmmmmmmmmmmm", -- 2 "mmmmmmmmmmmm", -- 3 "mmmmmmmmmmmm", -- 4 "mmmmmmmammmm", -- 5 "mmmmmmbbbmmm", -- 6 "mmmmmcbbbdmm", -- 7 "mmmmmmbbbmmm", -- 8 "mmmmmmmemmmm", -- 9 "mmmmmmmmmmmm", -- 10 "mmmmmmmmmmmm", -- 11 -- Level 15 "mmmmmmmmmmmm", -- 0 "mmmmmmmmmmmm", -- 1 "mmmmmmmmmmmm", -- 2 "mmmmmmmmmmmm", -- 3 "mmmmmmmmmmmm", -- 4 "mmmmmmmammmm", -- 5 "mmmmmmbbbmmm", -- 6 "mmmmmcbbbdmm", -- 7 "mmmmmmbbbmmm", -- 8 "mmmmmmmemmmm", -- 9 "mmmmmmmmmmmm", -- 10 "mmmmmmmmmmmm", -- 11 }, }, -- Corner { OriginData = { ExportName = "TreeEnd", Name = "Cube 143", GalleryName = "Cube", GalleryIndex = "143", ID = "1188", CreatorName = "xoft2", }, Size = { x = 12, y = 16, z = 9, }, Hitbox = { MinX = 0, MinY = 0, MinZ = -3, MaxX = 14, MaxY = 15, MaxZ = 11, }, Connectors = { { Type = 0, RelX = 0, RelY = 7, RelZ = 4, Direction = 4, -- X- }, { Type = 1, RelX = 7, RelY = 0, RelZ = 4, Direction = 0, -- Y- }, { Type = -1, RelX = 7, RelY = 15, RelZ = 4, Direction = 1, -- Y+ }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "20", ["DepthWeight"] = "8:10000|9:10000", ["ExpandFloorStrategy"] = "None", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", ["VerticalLimit"] = "AboveTerrainAndOcean|10|70", }, BlockDefinitions = { ".: 0: 0", -- air "a: 65: 2", -- ladder "b: 17: 3", -- tree "c: 65: 4", -- ladder "d: 65: 5", -- ladder "e: 65: 3", -- ladder "f: 5: 3", -- planks "g:190: 0", -- junglefence "h: 50: 5", -- torch "i: 50: 4", -- torch "j: 50: 2", -- torch "k: 50: 1", -- torch "l: 50: 3", -- torch "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "mmmmmmmmmmmm", -- 0 "mmmmmmmmmmmm", -- 1 "mmmmmmmammmm", -- 2 "mmmmmmbbbmmm", -- 3 "mmmmmcbbbdmm", -- 4 "mmmmmmbbbmmm", -- 5 "mmmmmmmemmmm", -- 6 "mmmmmmmmmmmm", -- 7 "mmmmmmmmmmmm", -- 8 -- Level 1 "mmmmmmmmmmmm", -- 0 "mmmmmmmmmmmm", -- 1 "mmmmmmmammmm", -- 2 "mmmmmmbbbmmm", -- 3 "mmmmmcbbbdmm", -- 4 "mmmmmmbbbmmm", -- 5 "mmmmmmmemmmm", -- 6 "mmmmmmmmmmmm", -- 7 "mmmmmmmmmmmm", -- 8 -- Level 2 "mmmmmmmmmmmm", -- 0 "mmmmmmmmmmmm", -- 1 "mmmmmmmammmm", -- 2 "mmmmmmbbbmmm", -- 3 "mmmmmcbbbdmm", -- 4 "mmmmmmbbbmmm", -- 5 "mmmmmmmemmmm", -- 6 "mmmmmmmmmmmm", -- 7 "mmmmmmmmmmmm", -- 8 -- Level 3 "mmmmmmmmmmmm", -- 0 "mmmmmmmmmmmm", -- 1 "mmmmmmmammmm", -- 2 "mmmmmmbbbmmm", -- 3 "mmmmmcbbbdmm", -- 4 "mmmmmmbbbmmm", -- 5 "mmmmmmmemmmm", -- 6 "mmmmmmmmmmmm", -- 7 "mmmmmmmmmmmm", -- 8 -- Level 4 "mmmmmmmmmmmm", -- 0 "mmmmmmmmmmmm", -- 1 "mmmmmmmammmm", -- 2 "mmmmmmbbbmmm", -- 3 "mmmmmcbbbdmm", -- 4 "mmmmmmbbbmmm", -- 5 "mmmmmmmemmmm", -- 6 "mmmmmmmmmmmm", -- 7 "mmmmmmmmmmmm", -- 8 -- Level 5 "mmmmmmmmmmmm", -- 0 "mmmmmmmmmmmm", -- 1 "mmmmmmmammmm", -- 2 "mmmmmmbbbmmm", -- 3 "mmmmmcbbbdmm", -- 4 "mmmmmmbbbmmm", -- 5 "mmmmmmmemmmm", -- 6 "mmmmmmmmmmmm", -- 7 "mmmmmmmmmmmm", -- 8 -- Level 6 "mmmmfffffffm", -- 0 "mmmfffffffff", -- 1 "mmmffffaffff", -- 2 "ffffffbbbfff", -- 3 "fffffcbbbdff", -- 4 "ffffffbbbfff", -- 5 "mmmffffeffff", -- 6 "mmmfffffffff", -- 7 "mmmmfffffffm", -- 8 -- Level 7 "mmmmgggggggm", -- 0 "mmmgg.....gg", -- 1 "mmmg...a...g", -- 2 "gggg..bbb..g", -- 3 ".....cbbbd.g", -- 4 "gggg..bbb..g", -- 5 "mmmg...e...g", -- 6 "mmmgg.....gg", -- 7 "mmmmgggggggm", -- 8 -- Level 8 "mmmm..h.h..m", -- 0 "mmm.h.....h.", -- 1 "mmm...iai...", -- 2 "...h.jbbbk.h", -- 3 ".....cbbbd..", -- 4 "...h.jbbbk.h", -- 5 "mmm...lel...", -- 6 "mmm.h.....h.", -- 7 "mmmm..h.h..m", -- 8 -- Level 9 "mmmmmmmmmmmm", -- 0 "mmmmmmmmmmmm", -- 1 "mmmmmmmammmm", -- 2 "mmmmmmbbbmmm", -- 3 "mmmmmcbbbdmm", -- 4 "mmmmmmbbbmmm", -- 5 "mmmmmmmemmmm", -- 6 "mmmmmmmmmmmm", -- 7 "mmmmmmmmmmmm", -- 8 -- Level 10 "mmmmmmmmmmmm", -- 0 "mmmmmmmmmmmm", -- 1 "mmmmmmmammmm", -- 2 "mmmmmmbbbmmm", -- 3 "mmmmmcbbbdmm", -- 4 "mmmmmmbbbmmm", -- 5 "mmmmmmmemmmm", -- 6 "mmmmmmmmmmmm", -- 7 "mmmmmmmmmmmm", -- 8 -- Level 11 "mmmmmmmmmmmm", -- 0 "mmmmmmmmmmmm", -- 1 "mmmmmmmammmm", -- 2 "mmmmmmbbbmmm", -- 3 "mmmmmcbbbdmm", -- 4 "mmmmmmbbbmmm", -- 5 "mmmmmmmemmmm", -- 6 "mmmmmmmmmmmm", -- 7 "mmmmmmmmmmmm", -- 8 -- Level 12 "mmmmmmmmmmmm", -- 0 "mmmmmmmmmmmm", -- 1 "mmmmmmmammmm", -- 2 "mmmmmmbbbmmm", -- 3 "mmmmmcbbbdmm", -- 4 "mmmmmmbbbmmm", -- 5 "mmmmmmmemmmm", -- 6 "mmmmmmmmmmmm", -- 7 "mmmmmmmmmmmm", -- 8 -- Level 13 "mmmmmmmmmmmm", -- 0 "mmmmmmmmmmmm", -- 1 "mmmmmmmammmm", -- 2 "mmmmmmbbbmmm", -- 3 "mmmmmcbbbdmm", -- 4 "mmmmmmbbbmmm", -- 5 "mmmmmmmemmmm", -- 6 "mmmmmmmmmmmm", -- 7 "mmmmmmmmmmmm", -- 8 -- Level 14 "mmmmmmmmmmmm", -- 0 "mmmmmmmmmmmm", -- 1 "mmmmmmmammmm", -- 2 "mmmmmmbbbmmm", -- 3 "mmmmmcbbbdmm", -- 4 "mmmmmmbbbmmm", -- 5 "mmmmmmmemmmm", -- 6 "mmmmmmmmmmmm", -- 7 "mmmmmmmmmmmm", -- 8 -- Level 15 "mmmmmmmmmmmm", -- 0 "mmmmmmmmmmmm", -- 1 "mmmmmmmammmm", -- 2 "mmmmmmbbbmmm", -- 3 "mmmmmcbbbdmm", -- 4 "mmmmmmbbbmmm", -- 5 "mmmmmmmemmmm", -- 6 "mmmmmmmmmmmm", -- 7 "mmmmmmmmmmmm", -- 8 }, }, -- TreeEnd { OriginData = { ExportName = "TreeStraight", Name = "Cube 144", GalleryName = "Cube", GalleryIndex = "144", ID = "1189", CreatorName = "xoft2", }, Size = { x = 15, y = 16, z = 9, }, Hitbox = { MinX = 0, MinY = 0, MinZ = -3, MaxX = 14, MaxY = 15, MaxZ = 11, }, Connectors = { { Type = 0, RelX = 0, RelY = 7, RelZ = 4, Direction = 4, -- X- }, { Type = 0, RelX = 14, RelY = 7, RelZ = 4, Direction = 5, -- X+ }, { Type = -1, RelX = 7, RelY = 15, RelZ = 4, Direction = 1, -- Y+ }, { Type = 1, RelX = 7, RelY = 0, RelZ = 4, Direction = 0, -- Y- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "10", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "None", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", ["VerticalLimit"] = "AboveTerrainAndOcean|20|60", }, BlockDefinitions = { ".: 0: 0", -- air "a: 65: 2", -- ladder "b: 17: 3", -- tree "c: 65: 4", -- ladder "d: 65: 5", -- ladder "e: 65: 3", -- ladder "f: 5: 3", -- planks "g:190: 0", -- junglefence "h: 50: 5", -- torch "i: 50: 4", -- torch "j: 50: 2", -- torch "k: 50: 1", -- torch "l: 50: 3", -- torch "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmammmmmmm", -- 2 "mmmmmmbbbmmmmmm", -- 3 "mmmmmcbbbdmmmmm", -- 4 "mmmmmmbbbmmmmmm", -- 5 "mmmmmmmemmmmmmm", -- 6 "mmmmmmmmmmmmmmm", -- 7 "mmmmmmmmmmmmmmm", -- 8 -- Level 1 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmammmmmmm", -- 2 "mmmmmmbbbmmmmmm", -- 3 "mmmmmcbbbdmmmmm", -- 4 "mmmmmmbbbmmmmmm", -- 5 "mmmmmmmemmmmmmm", -- 6 "mmmmmmmmmmmmmmm", -- 7 "mmmmmmmmmmmmmmm", -- 8 -- Level 2 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmammmmmmm", -- 2 "mmmmmmbbbmmmmmm", -- 3 "mmmmmcbbbdmmmmm", -- 4 "mmmmmmbbbmmmmmm", -- 5 "mmmmmmmemmmmmmm", -- 6 "mmmmmmmmmmmmmmm", -- 7 "mmmmmmmmmmmmmmm", -- 8 -- Level 3 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmammmmmmm", -- 2 "mmmmmmbbbmmmmmm", -- 3 "mmmmmcbbbdmmmmm", -- 4 "mmmmmmbbbmmmmmm", -- 5 "mmmmmmmemmmmmmm", -- 6 "mmmmmmmmmmmmmmm", -- 7 "mmmmmmmmmmmmmmm", -- 8 -- Level 4 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmammmmmmm", -- 2 "mmmmmmbbbmmmmmm", -- 3 "mmmmmcbbbdmmmmm", -- 4 "mmmmmmbbbmmmmmm", -- 5 "mmmmmmmemmmmmmm", -- 6 "mmmmmmmmmmmmmmm", -- 7 "mmmmmmmmmmmmmmm", -- 8 -- Level 5 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmammmmmmm", -- 2 "mmmmmmbbbmmmmmm", -- 3 "mmmmmcbbbdmmmmm", -- 4 "mmmmmmbbbmmmmmm", -- 5 "mmmmmmmemmmmmmm", -- 6 "mmmmmmmmmmmmmmm", -- 7 "mmmmmmmmmmmmmmm", -- 8 -- Level 6 "mmmmfffffffmmmm", -- 0 "mmmfffffffffmmm", -- 1 "mmmffffaffffmmm", -- 2 "ffffffbbbffffff", -- 3 "fffffcbbbdfffff", -- 4 "ffffffbbbffffff", -- 5 "mmmffffeffffmmm", -- 6 "mmmfffffffffmmm", -- 7 "mmmmfffffffmmmm", -- 8 -- Level 7 "mmmmgggggggmmmm", -- 0 "mmmgg.....ggmmm", -- 1 "mmmg...a...gmmm", -- 2 "gggg..bbb..gggg", -- 3 ".....cbbbd.....", -- 4 "gggg..bbb..gggg", -- 5 "mmmg...e...gmmm", -- 6 "mmmgg.....ggmmm", -- 7 "mmmmgggggggmmmm", -- 8 -- Level 8 "mmmm..h.h..mmmm", -- 0 "mmm.h.....h.mmm", -- 1 "mmm...iai...mmm", -- 2 "...h.jbbbk.h...", -- 3 ".....cbbbd.....", -- 4 "...h.jbbbk.h...", -- 5 "mmm...lel...mmm", -- 6 "mmm.h.....h.mmm", -- 7 "mmmm..h.h..mmmm", -- 8 -- Level 9 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmammmmmmm", -- 2 "mmmmmmbbbmmmmmm", -- 3 "mmmmmcbbbdmmmmm", -- 4 "mmmmmmbbbmmmmmm", -- 5 "mmmmmmmemmmmmmm", -- 6 "mmmmmmmmmmmmmmm", -- 7 "mmmmmmmmmmmmmmm", -- 8 -- Level 10 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmammmmmmm", -- 2 "mmmmmmbbbmmmmmm", -- 3 "mmmmmcbbbdmmmmm", -- 4 "mmmmmmbbbmmmmmm", -- 5 "mmmmmmmemmmmmmm", -- 6 "mmmmmmmmmmmmmmm", -- 7 "mmmmmmmmmmmmmmm", -- 8 -- Level 11 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmammmmmmm", -- 2 "mmmmmmbbbmmmmmm", -- 3 "mmmmmcbbbdmmmmm", -- 4 "mmmmmmbbbmmmmmm", -- 5 "mmmmmmmemmmmmmm", -- 6 "mmmmmmmmmmmmmmm", -- 7 "mmmmmmmmmmmmmmm", -- 8 -- Level 12 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmammmmmmm", -- 2 "mmmmmmbbbmmmmmm", -- 3 "mmmmmcbbbdmmmmm", -- 4 "mmmmmmbbbmmmmmm", -- 5 "mmmmmmmemmmmmmm", -- 6 "mmmmmmmmmmmmmmm", -- 7 "mmmmmmmmmmmmmmm", -- 8 -- Level 13 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmammmmmmm", -- 2 "mmmmmmbbbmmmmmm", -- 3 "mmmmmcbbbdmmmmm", -- 4 "mmmmmmbbbmmmmmm", -- 5 "mmmmmmmemmmmmmm", -- 6 "mmmmmmmmmmmmmmm", -- 7 "mmmmmmmmmmmmmmm", -- 8 -- Level 14 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmammmmmmm", -- 2 "mmmmmmbbbmmmmmm", -- 3 "mmmmmcbbbdmmmmm", -- 4 "mmmmmmbbbmmmmmm", -- 5 "mmmmmmmemmmmmmm", -- 6 "mmmmmmmmmmmmmmm", -- 7 "mmmmmmmmmmmmmmm", -- 8 -- Level 15 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmammmmmmm", -- 2 "mmmmmmbbbmmmmmm", -- 3 "mmmmmcbbbdmmmmm", -- 4 "mmmmmmbbbmmmmmm", -- 5 "mmmmmmmemmmmmmm", -- 6 "mmmmmmmmmmmmmmm", -- 7 "mmmmmmmmmmmmmmm", -- 8 }, }, -- TreeStraight { OriginData = { ExportName = "TreePaths_1190", Name = "Cube 145", GalleryName = "Cube", GalleryIndex = "145", ID = "1190", CreatorName = "xoft2", }, Size = { x = 15, y = 4, z = 3, }, Hitbox = { MinX = 0, MinY = -4, MinZ = -3, MaxX = 14, MaxY = 7, MaxZ = 5, }, Connectors = { { Type = 0, RelX = 0, RelY = 2, RelZ = 1, Direction = 4, -- X- }, { Type = 0, RelX = 14, RelY = 2, RelZ = 1, Direction = 5, -- X+ }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "None", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a: 5: 3", -- planks "b:190: 0", -- junglefence "c: 50: 5", -- torch "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 -- Level 1 "aaaaaaaaaaaaaaa", -- 0 "aaaaaaaaaaaaaaa", -- 1 "aaaaaaaaaaaaaaa", -- 2 -- Level 2 "bbbbbbbbbbbbbbb", -- 0 "...............", -- 1 "bbbbbbbbbbbbbbb", -- 2 -- Level 3 "...c...c...c...", -- 0 "...............", -- 1 "...c...c...c...", -- 2 }, }, -- TreePaths_1190 { OriginData = { ExportName = "StartingCross", Name = "Cube 146", GalleryName = "Cube", GalleryIndex = "146", ID = "1191", CreatorName = "xoft2", }, Size = { x = 15, y = 16, z = 15, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 14, MaxY = 15, MaxZ = 14, }, Connectors = { { Type = 0, RelX = 0, RelY = 7, RelZ = 7, Direction = 4, -- X- }, { Type = 0, RelX = 7, RelY = 7, RelZ = 14, Direction = 3, -- Z+ }, { Type = 0, RelX = 14, RelY = 7, RelZ = 7, Direction = 5, -- X+ }, { Type = 0, RelX = 7, RelY = 7, RelZ = 0, Direction = 2, -- Z- }, { Type = 1, RelX = 7, RelY = 0, RelZ = 7, Direction = 0, -- Y- }, { Type = -1, RelX = 7, RelY = 15, RelZ = 7, Direction = 1, -- Y+ }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "None", ["IsStarting"] = "1", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", ["VerticalStrategy"] = "TerrainOrOceanTop|30|40", }, BlockDefinitions = { ".: 0: 0", -- air "a: 65: 2", -- ladder "b: 17: 3", -- tree "c: 65: 4", -- ladder "d: 65: 5", -- ladder "e: 65: 3", -- ladder "f: 5: 3", -- planks "g:190: 0", -- junglefence "h: 50: 5", -- torch "i: 50: 4", -- torch "j: 50: 2", -- torch "k: 50: 1", -- torch "l: 50: 3", -- torch "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmammmmmmm", -- 5 "mmmmmmbbbmmmmmm", -- 6 "mmmmmcbbbdmmmmm", -- 7 "mmmmmmbbbmmmmmm", -- 8 "mmmmmmmemmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 1 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmammmmmmm", -- 5 "mmmmmmbbbmmmmmm", -- 6 "mmmmmcbbbdmmmmm", -- 7 "mmmmmmbbbmmmmmm", -- 8 "mmmmmmmemmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 2 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmammmmmmm", -- 5 "mmmmmmbbbmmmmmm", -- 6 "mmmmmcbbbdmmmmm", -- 7 "mmmmmmbbbmmmmmm", -- 8 "mmmmmmmemmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 3 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmammmmmmm", -- 5 "mmmmmmbbbmmmmmm", -- 6 "mmmmmcbbbdmmmmm", -- 7 "mmmmmmbbbmmmmmm", -- 8 "mmmmmmmemmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 4 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmammmmmmm", -- 5 "mmmmmmbbbmmmmmm", -- 6 "mmmmmcbbbdmmmmm", -- 7 "mmmmmmbbbmmmmmm", -- 8 "mmmmmmmemmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 5 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmammmmmmm", -- 5 "mmmmmmbbbmmmmmm", -- 6 "mmmmmcbbbdmmmmm", -- 7 "mmmmmmbbbmmmmmm", -- 8 "mmmmmmmemmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 6 "mmmmmmfffmmmmmm", -- 0 "mmmmmmfffmmmmmm", -- 1 "mmmmmmfffmmmmmm", -- 2 "mmmmfffffffmmmm", -- 3 "mmmfffffffffmmm", -- 4 "mmmffffaffffmmm", -- 5 "ffffffbbbffffff", -- 6 "fffffcbbbdfffff", -- 7 "ffffffbbbffffff", -- 8 "mmmffffeffffmmm", -- 9 "mmmfffffffffmmm", -- 10 "mmmmfffffffmmmm", -- 11 "mmmmmmfffmmmmmm", -- 12 "mmmmmmfffmmmmmm", -- 13 "mmmmmmfffmmmmmm", -- 14 -- Level 7 "mmmmmmg.gmmmmmm", -- 0 "mmmmmmg.gmmmmmm", -- 1 "mmmmmmg.gmmmmmm", -- 2 "mmmmggg.gggmmmm", -- 3 "mmmgg.....ggmmm", -- 4 "mmmg...a...gmmm", -- 5 "gggg..bbb..gggg", -- 6 ".....cbbbd.....", -- 7 "gggg..bbb..gggg", -- 8 "mmmg...e...gmmm", -- 9 "mmmgg.....ggmmm", -- 10 "mmmmggg.gggmmmm", -- 11 "mmmmmmg.gmmmmmm", -- 12 "mmmmmmg.gmmmmmm", -- 13 "mmmmmmg.gmmmmmm", -- 14 -- Level 8 "mmmmmm...mmmmmm", -- 0 "mmmmmm...mmmmmm", -- 1 "mmmmmm...mmmmmm", -- 2 "mmmm..h.h..mmmm", -- 3 "mmm.h.....h.mmm", -- 4 "mmm...iai...mmm", -- 5 "...h.jbbbk.h...", -- 6 ".....cbbbd.....", -- 7 "...h.jbbbk.h...", -- 8 "mmm...lel...mmm", -- 9 "mmm.h.....h.mmm", -- 10 "mmmm..h.h..mmmm", -- 11 "mmmmmm...mmmmmm", -- 12 "mmmmmm...mmmmmm", -- 13 "mmmmmm...mmmmmm", -- 14 -- Level 9 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmammmmmmm", -- 5 "mmmmmmbbbmmmmmm", -- 6 "mmmmmcbbbdmmmmm", -- 7 "mmmmmmbbbmmmmmm", -- 8 "mmmmmmmemmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 10 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmammmmmmm", -- 5 "mmmmmmbbbmmmmmm", -- 6 "mmmmmcbbbdmmmmm", -- 7 "mmmmmmbbbmmmmmm", -- 8 "mmmmmmmemmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 11 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmammmmmmm", -- 5 "mmmmmmbbbmmmmmm", -- 6 "mmmmmcbbbdmmmmm", -- 7 "mmmmmmbbbmmmmmm", -- 8 "mmmmmmmemmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 12 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmammmmmmm", -- 5 "mmmmmmbbbmmmmmm", -- 6 "mmmmmcbbbdmmmmm", -- 7 "mmmmmmbbbmmmmmm", -- 8 "mmmmmmmemmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 13 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmammmmmmm", -- 5 "mmmmmmbbbmmmmmm", -- 6 "mmmmmcbbbdmmmmm", -- 7 "mmmmmmbbbmmmmmm", -- 8 "mmmmmmmemmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 14 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmammmmmmm", -- 5 "mmmmmmbbbmmmmmm", -- 6 "mmmmmcbbbdmmmmm", -- 7 "mmmmmmbbbmmmmmm", -- 8 "mmmmmmmemmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 15 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmammmmmmm", -- 5 "mmmmmmbbbmmmmmm", -- 6 "mmmmmcbbbdmmmmm", -- 7 "mmmmmmbbbmmmmmm", -- 8 "mmmmmmmemmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 }, }, -- StartingCross { OriginData = { ExportName = "CrossNoBottom", Name = "Cube 147", GalleryName = "Cube", GalleryIndex = "147", ID = "1192", CreatorName = "xoft2", }, Size = { x = 15, y = 16, z = 15, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 14, MaxY = 15, MaxZ = 14, }, Connectors = { { Type = 2, RelX = 7, RelY = 0, RelZ = 7, Direction = 0, -- Y- }, { Type = -1, RelX = 7, RelY = 15, RelZ = 7, Direction = 1, -- Y+ }, { Type = 0, RelX = 0, RelY = 7, RelZ = 7, Direction = 4, -- X- }, { Type = 0, RelX = 7, RelY = 7, RelZ = 14, Direction = 3, -- Z+ }, { Type = 0, RelX = 14, RelY = 7, RelZ = 7, Direction = 5, -- X+ }, { Type = 0, RelX = 7, RelY = 7, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "5", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "None", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", ["VerticalLimit"] = "AboveTerrainAndOcean|20|60", }, BlockDefinitions = { ".: 0: 0", -- air "a: 17: 3", -- tree "b: 5: 3", -- planks "c:190: 0", -- junglefence "d: 65: 2", -- ladder "e: 65: 4", -- ladder "f: 65: 5", -- ladder "g: 65: 3", -- ladder "h: 50: 5", -- torch "i: 50: 4", -- torch "j: 50: 2", -- torch "k: 50: 1", -- torch "l: 50: 3", -- torch "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmmmmmmmmm", -- 5 "mmmmmmaaammmmmm", -- 6 "mmmmmmaaammmmmm", -- 7 "mmmmmmaaammmmmm", -- 8 "mmmmmmmmmmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 1 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmmmmmmmmm", -- 5 "mmmmmmaaammmmmm", -- 6 "mmmmmmaaammmmmm", -- 7 "mmmmmmaaammmmmm", -- 8 "mmmmmmmmmmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 2 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmmmmmmmmm", -- 5 "mmmmmmaaammmmmm", -- 6 "mmmmmmaaammmmmm", -- 7 "mmmmmmaaammmmmm", -- 8 "mmmmmmmmmmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 3 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmmmmmmmmm", -- 5 "mmmmmmaaammmmmm", -- 6 "mmmmmmaaammmmmm", -- 7 "mmmmmmaaammmmmm", -- 8 "mmmmmmmmmmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 4 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmmmmmmmmm", -- 5 "mmmmmmaaammmmmm", -- 6 "mmmmmmaaammmmmm", -- 7 "mmmmmmaaammmmmm", -- 8 "mmmmmmmmmmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 5 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmmmmmmmmm", -- 5 "mmmmmmaaammmmmm", -- 6 "mmmmmmaaammmmmm", -- 7 "mmmmmmaaammmmmm", -- 8 "mmmmmmmmmmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 6 "mmmmmmbbbmmmmmm", -- 0 "mmmmmmbbbmmmmmm", -- 1 "mmmmmmbbbmmmmmm", -- 2 "mmmmbbbbbbbmmmm", -- 3 "mmmbbbbbbbbbmmm", -- 4 "mmmbbbbbbbbbmmm", -- 5 "bbbbbbaaabbbbbb", -- 6 "bbbbbbaaabbbbbb", -- 7 "bbbbbbaaabbbbbb", -- 8 "mmmbbbbbbbbbmmm", -- 9 "mmmbbbbbbbbbmmm", -- 10 "mmmmbbbbbbbmmmm", -- 11 "mmmmmmbbbmmmmmm", -- 12 "mmmmmmbbbmmmmmm", -- 13 "mmmmmmbbbmmmmmm", -- 14 -- Level 7 "mmmmmmc.cmmmmmm", -- 0 "mmmmmmc.cmmmmmm", -- 1 "mmmmmmc.cmmmmmm", -- 2 "mmmmccc.cccmmmm", -- 3 "mmmcc.....ccmmm", -- 4 "mmmc...d...cmmm", -- 5 "cccc..aaa..cccc", -- 6 ".....eaaaf.....", -- 7 "cccc..aaa..cccc", -- 8 "mmmc...g...cmmm", -- 9 "mmmcc.....ccmmm", -- 10 "mmmmccc.cccmmmm", -- 11 "mmmmmmc.cmmmmmm", -- 12 "mmmmmmc.cmmmmmm", -- 13 "mmmmmmc.cmmmmmm", -- 14 -- Level 8 "mmmmmm...mmmmmm", -- 0 "mmmmmm...mmmmmm", -- 1 "mmmmmm...mmmmmm", -- 2 "mmmm..h.h..mmmm", -- 3 "mmm.h.....h.mmm", -- 4 "mmm...idi...mmm", -- 5 "...h.jaaak.h...", -- 6 ".....eaaaf.....", -- 7 "...h.jaaak.h...", -- 8 "mmm...lgl...mmm", -- 9 "mmm.h.....h.mmm", -- 10 "mmmm..h.h..mmmm", -- 11 "mmmmmm...mmmmmm", -- 12 "mmmmmm...mmmmmm", -- 13 "mmmmmm...mmmmmm", -- 14 -- Level 9 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmdmmmmmmm", -- 5 "mmmmmmaaammmmmm", -- 6 "mmmmmeaaafmmmmm", -- 7 "mmmmmmaaammmmmm", -- 8 "mmmmmmmgmmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 10 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmdmmmmmmm", -- 5 "mmmmmmaaammmmmm", -- 6 "mmmmmeaaafmmmmm", -- 7 "mmmmmmaaammmmmm", -- 8 "mmmmmmmgmmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 11 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmdmmmmmmm", -- 5 "mmmmmmaaammmmmm", -- 6 "mmmmmeaaafmmmmm", -- 7 "mmmmmmaaammmmmm", -- 8 "mmmmmmmgmmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 12 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmdmmmmmmm", -- 5 "mmmmmmaaammmmmm", -- 6 "mmmmmeaaafmmmmm", -- 7 "mmmmmmaaammmmmm", -- 8 "mmmmmmmgmmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 13 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmdmmmmmmm", -- 5 "mmmmmmaaammmmmm", -- 6 "mmmmmeaaafmmmmm", -- 7 "mmmmmmaaammmmmm", -- 8 "mmmmmmmgmmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 14 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmdmmmmmmm", -- 5 "mmmmmmaaammmmmm", -- 6 "mmmmmeaaafmmmmm", -- 7 "mmmmmmaaammmmmm", -- 8 "mmmmmmmgmmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 15 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmdmmmmmmm", -- 5 "mmmmmmaaammmmmm", -- 6 "mmmmmeaaafmmmmm", -- 7 "mmmmmmaaammmmmm", -- 8 "mmmmmmmgmmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 }, }, -- CrossNoBottom { OriginData = { ExportName = "TreePaths_1193", Name = "Cube 148", GalleryName = "Cube", GalleryIndex = "148", ID = "1193", CreatorName = "xoft2", }, Size = { x = 11, y = 4, z = 3, }, Hitbox = { MinX = 0, MinY = -4, MinZ = -3, MaxX = 10, MaxY = 7, MaxZ = 5, }, Connectors = { { Type = 0, RelX = 0, RelY = 2, RelZ = 1, Direction = 4, -- X- }, { Type = 0, RelX = 10, RelY = 2, RelZ = 1, Direction = 5, -- X+ }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "500", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "None", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a: 5: 3", -- planks "b:190: 0", -- junglefence "c: 50: 5", -- torch "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "mmmmmmmmmmm", -- 0 "mmmmmmmmmmm", -- 1 "mmmmmmmmmmm", -- 2 -- Level 1 "aaaaaaaaaaa", -- 0 "aaaaaaaaaaa", -- 1 "aaaaaaaaaaa", -- 2 -- Level 2 "bbbbbbbbbbb", -- 0 "...........", -- 1 "bbbbbbbbbbb", -- 2 -- Level 3 "...c...c...", -- 0 "...........", -- 1 "...c...c...", -- 2 }, }, -- TreePaths_1193 { OriginData = { ExportName = "TreePaths_1194", Name = "Cube 149", GalleryName = "Cube", GalleryIndex = "149", ID = "1194", CreatorName = "xoft2", }, Size = { x = 7, y = 4, z = 3, }, Hitbox = { MinX = 0, MinY = -4, MinZ = -3, MaxX = 6, MaxY = 7, MaxZ = 5, }, Connectors = { { Type = 0, RelX = 0, RelY = 2, RelZ = 1, Direction = 4, -- X- }, { Type = 0, RelX = 6, RelY = 2, RelZ = 1, Direction = 5, -- X+ }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "None", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a: 5: 3", -- planks "b:190: 0", -- junglefence "c: 50: 5", -- torch "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "mmmmmmm", -- 0 "mmmmmmm", -- 1 "mmmmmmm", -- 2 -- Level 1 "aaaaaaa", -- 0 "aaaaaaa", -- 1 "aaaaaaa", -- 2 -- Level 2 "bbbbbbb", -- 0 ".......", -- 1 "bbbbbbb", -- 2 -- Level 3 "...c...", -- 0 ".......", -- 1 "...c...", -- 2 }, }, -- TreePaths_1194 { OriginData = { ExportName = "Curve", Name = "Cube 150", GalleryName = "Cube", GalleryIndex = "150", ID = "1195", CreatorName = "xoft2", }, Size = { x = 16, y = 4, z = 16, }, Hitbox = { MinX = 0, MinY = -4, MinZ = 0, MaxX = 15, MaxY = 7, MaxZ = 15, }, Connectors = { { Type = 0, RelX = 0, RelY = 2, RelZ = 1, Direction = 4, -- X- }, { Type = 0, RelX = 14, RelY = 2, RelZ = 15, Direction = 3, -- Z+ }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "None", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a: 5: 3", -- planks "b:190: 0", -- junglefence "c: 50: 5", -- torch "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "mmmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmmm", -- 4 "mmmmmmmmmmmmmmmm", -- 5 "mmmmmmmmmmmmmmmm", -- 6 "mmmmmmmmmmmmmmmm", -- 7 "mmmmmmmmmmmmmmmm", -- 8 "mmmmmmmmmmmmmmmm", -- 9 "mmmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmmm", -- 14 "mmmmmmmmmmmmmmmm", -- 15 -- Level 1 "aaaammmmmmmmmmmm", -- 0 "aaaaaammmmmmmmmm", -- 1 "aaaaaaaammmmmmmm", -- 2 "maaaaaaaammmmmmm", -- 3 "mmmaaaaaaammmmmm", -- 4 "mmmmmaaaaaammmmm", -- 5 "mmmmmmaaaaaammmm", -- 6 "mmmmmmmaaaaaammm", -- 7 "mmmmmmmmaaaaaamm", -- 8 "mmmmmmmmmaaaaamm", -- 9 "mmmmmmmmmmaaaaam", -- 10 "mmmmmmmmmmmaaaam", -- 11 "mmmmmmmmmmmaaaaa", -- 12 "mmmmmmmmmmmmaaaa", -- 13 "mmmmmmmmmmmmaaaa", -- 14 "mmmmmmmmmmmmmaaa", -- 15 -- Level 2 "bbbbmmmmmmmmmmmm", -- 0 "...bbbmmmmmmmmmm", -- 1 "bb...bbbmmmmmmmm", -- 2 "mbbb...bbmmmmmmm", -- 3 "mmmbbb..bbmmmmmm", -- 4 "mmmmmbb..bbmmmmm", -- 5 "mmmmmmbb..bbmmmm", -- 6 "mmmmmmmbb..bbmmm", -- 7 "mmmmmmmmbb..bbmm", -- 8 "mmmmmmmmmbb..bmm", -- 9 "mmmmmmmmmmbb.bbm", -- 10 "mmmmmmmmmmmb..bm", -- 11 "mmmmmmmmmmmbb.bb", -- 12 "mmmmmmmmmmmmb..b", -- 13 "mmmmmmmmmmmmbb.b", -- 14 "mmmmmmmmmmmmmb.b", -- 15 -- Level 3 "...cmmmmmmmmmmmm", -- 0 ".....cmmmmmmmmmm", -- 1 "........mmmmmmmm", -- 2 "mc......cmmmmmmm", -- 3 "mmmc......mmmmmm", -- 4 "mmmmmc...c.mmmmm", -- 5 "mmmmmm.....cmmmm", -- 6 "mmmmmmmc.....mmm", -- 7 "mmmmmmmm.....cmm", -- 8 "mmmmmmmmmc....mm", -- 9 "mmmmmmmmmm.....m", -- 10 "mmmmmmmmmmm....m", -- 11 "mmmmmmmmmmmc...c", -- 12 "mmmmmmmmmmmm....", -- 13 "mmmmmmmmmmmmc...", -- 14 "mmmmmmmmmmmmm...", -- 15 }, }, -- Curve { OriginData = { ExportName = "TreePaths_1196", Name = "Cube 151", GalleryName = "Cube", GalleryIndex = "151", ID = "1196", CreatorName = "xoft2", }, Size = { x = 6, y = 6, z = 3, }, Hitbox = { MinX = 0, MinY = -4, MinZ = -3, MaxX = 5, MaxY = 9, MaxZ = 5, }, Connectors = { { Type = 0, RelX = 5, RelY = 4, RelZ = 1, Direction = 5, -- X+ }, { Type = 0, RelX = 0, RelY = 2, RelZ = 1, Direction = 4, -- X- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "None", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", ["VerticalLimit"] = "AboveTerrainAndOcean|20|60", }, BlockDefinitions = { ".: 0: 0", -- air "a: 5: 3", -- planks "b:190: 0", -- junglefence "c: 50: 5", -- torch "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "mmmmmm", -- 0 "mmmmmm", -- 1 "mmmmmm", -- 2 -- Level 1 "aaammm", -- 0 "aaammm", -- 1 "aaammm", -- 2 -- Level 2 "bbaaam", -- 0 "..aaam", -- 1 "bbaaam", -- 2 -- Level 3 ".bbbaa", -- 0 "....aa", -- 1 ".bbbaa", -- 2 -- Level 4 ".c.bbb", -- 0 "......", -- 1 ".c.bbb", -- 2 -- Level 5 "...c..", -- 0 "......", -- 1 "...c..", -- 2 }, }, -- TreePaths_1196 { OriginData = { ExportName = "TreePaths_1197", Name = "Cube 152", GalleryName = "Cube", GalleryIndex = "152", ID = "1197", CreatorName = "xoft2", }, Size = { x = 8, y = 7, z = 3, }, Hitbox = { MinX = 0, MinY = -4, MinZ = -2, MaxX = 7, MaxY = 10, MaxZ = 4, }, Connectors = { { Type = 0, RelX = 0, RelY = 2, RelZ = 1, Direction = 4, -- X- }, { Type = 0, RelX = 7, RelY = 5, RelZ = 1, Direction = 5, -- X+ }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "None", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", ["VerticalLimit"] = "AboveTerrainAndOcean|20|60", }, BlockDefinitions = { ".: 0: 0", -- air "a: 5: 3", -- planks "b:190: 0", -- junglefence "c: 50: 5", -- torch "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "mmmmmmmm", -- 0 "mmmmmmmm", -- 1 "mmmmmmmm", -- 2 -- Level 1 "aaammmmm", -- 0 "aaammmmm", -- 1 "aaammmmm", -- 2 -- Level 2 "bbaaammm", -- 0 "..aaammm", -- 1 "bbaaammm", -- 2 -- Level 3 ".bbbaaam", -- 0 "....aaam", -- 1 ".bbbaaam", -- 2 -- Level 4 ".c.bbbaa", -- 0 "......aa", -- 1 ".c.bbbaa", -- 2 -- Level 5 "...c.bbb", -- 0 "........", -- 1 "...c.bbb", -- 2 -- Level 6 ".....c..", -- 0 "........", -- 1 ".....c..", -- 2 }, }, -- TreePaths_1197 { OriginData = { ExportName = "CrossTreetop", Name = "Cube 153", GalleryName = "Cube", GalleryIndex = "153", ID = "1198", CreatorName = "xoft2", }, Size = { x = 15, y = 19, z = 15, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 14, MaxY = 18, MaxZ = 14, }, Connectors = { { Type = 0, RelX = 7, RelY = 7, RelZ = 0, Direction = 2, -- Z- }, { Type = 0, RelX = 7, RelY = 7, RelZ = 14, Direction = 3, -- Z+ }, { Type = 0, RelX = 0, RelY = 7, RelZ = 7, Direction = 4, -- X- }, { Type = 0, RelX = 14, RelY = 7, RelZ = 7, Direction = 5, -- X+ }, { Type = 1, RelX = 7, RelY = 0, RelZ = 7, Direction = 0, -- Y- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "2", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "None", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a: 65: 2", -- ladder "b: 17: 3", -- tree "c: 65: 4", -- ladder "d: 65: 5", -- ladder "e: 65: 3", -- ladder "f: 5: 3", -- planks "g:190: 0", -- junglefence "h: 50: 5", -- torch "i: 50: 4", -- torch "j: 50: 2", -- torch "k: 50: 1", -- torch "l: 50: 3", -- torch "m: 19: 0", -- sponge "n: 18: 7", -- leaves "o: 18: 3", -- leaves "p: 18:11", -- leaves "q: 17:11", -- tree "r: 17: 7", -- tree }, BlockData = { -- Level 0 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmammmmmmm", -- 5 "mmmmmmbbbmmmmmm", -- 6 "mmmmmcbbbdmmmmm", -- 7 "mmmmmmbbbmmmmmm", -- 8 "mmmmmmmemmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 1 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmammmmmmm", -- 5 "mmmmmmbbbmmmmmm", -- 6 "mmmmmcbbbdmmmmm", -- 7 "mmmmmmbbbmmmmmm", -- 8 "mmmmmmmemmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 2 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmammmmmmm", -- 5 "mmmmmmbbbmmmmmm", -- 6 "mmmmmcbbbdmmmmm", -- 7 "mmmmmmbbbmmmmmm", -- 8 "mmmmmmmemmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 3 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmammmmmmm", -- 5 "mmmmmmbbbmmmmmm", -- 6 "mmmmmcbbbdmmmmm", -- 7 "mmmmmmbbbmmmmmm", -- 8 "mmmmmmmemmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 4 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmammmmmmm", -- 5 "mmmmmmbbbmmmmmm", -- 6 "mmmmmcbbbdmmmmm", -- 7 "mmmmmmbbbmmmmmm", -- 8 "mmmmmmmemmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 5 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmammmmmmm", -- 5 "mmmmmmbbbmmmmmm", -- 6 "mmmmmcbbbdmmmmm", -- 7 "mmmmmmbbbmmmmmm", -- 8 "mmmmmmmemmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 6 "mmmmmmfffmmmmmm", -- 0 "mmmmmmfffmmmmmm", -- 1 "mmmmmmfffmmmmmm", -- 2 "mmmmfffffffmmmm", -- 3 "mmmfffffffffmmm", -- 4 "mmmffffaffffmmm", -- 5 "ffffffbbbffffff", -- 6 "fffffcbbbdfffff", -- 7 "ffffffbbbffffff", -- 8 "mmmffffeffffmmm", -- 9 "mmmfffffffffmmm", -- 10 "mmmmfffffffmmmm", -- 11 "mmmmmmfffmmmmmm", -- 12 "mmmmmmfffmmmmmm", -- 13 "mmmmmmfffmmmmmm", -- 14 -- Level 7 "mmmmmmg.gmmmmmm", -- 0 "mmmmmmg.gmmmmmm", -- 1 "mmmmmmg.gmmmmmm", -- 2 "mmmmggg.gggmmmm", -- 3 "mmmgg.....ggmmm", -- 4 "mmmg.......gmmm", -- 5 "gggg..bbb..gggg", -- 6 "......bbb......", -- 7 "gggg..bbb..gggg", -- 8 "mmmg.......gmmm", -- 9 "mmmgg.....ggmmm", -- 10 "mmmmggg.gggmmmm", -- 11 "mmmmmmg.gmmmmmm", -- 12 "mmmmmmg.gmmmmmm", -- 13 "mmmmmmg.gmmmmmm", -- 14 -- Level 8 "mmmmmm...mmmmmm", -- 0 "mmmmmm...mmmmmm", -- 1 "mmmmmm...mmmmmm", -- 2 "mmmm..h.h..mmmm", -- 3 "mmm.h.....h.mmm", -- 4 "mmm...i.i...mmm", -- 5 "...h.jbbbk.h...", -- 6 "......bbb......", -- 7 "...h.jbbbk.h...", -- 8 "mmm...l.l...mmm", -- 9 "mmm.h.....h.mmm", -- 10 "mmmm..h.h..mmmm", -- 11 "mmmmmm...mmmmmm", -- 12 "mmmmmm...mmmmmm", -- 13 "mmmmmm...mmmmmm", -- 14 -- Level 9 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmnnnmmmmmm", -- 3 "mmmmnooooonmmmm", -- 4 "mmmmooooooommmm", -- 5 "mmmnoobbboonmmm", -- 6 "mmmnoobbboonmmm", -- 7 "mmmnoobbboonmmm", -- 8 "mmmmoopoooommmm", -- 9 "mmmmnoooopnmmmm", -- 10 "mmmmmmnnnmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 10 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmm.poo.mmmmm", -- 2 "mmmmnpooponmmmm", -- 3 "mmmnnopqoonnmmm", -- 4 "mm.ooooqoooo.mm", -- 5 "mmooopbbboooomm", -- 6 "mmoorrbbbrropmm", -- 7 "mmpoopbbboooomm", -- 8 "mm.poooqoooo.mm", -- 9 "mmmnnooqopnnmmm", -- 10 "mmmmnoopoonmmmm", -- 11 "mmmmm.ooo.mmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 11 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmm.ooo.mmmmm", -- 2 "mmm.ooooooo.mmm", -- 3 "mmmpooopooopmmm", -- 4 "mm.oobooobop.mm", -- 5 "mmooooobopopomm", -- 6 "mmpooobbboooomm", -- 7 "mmooopobooooomm", -- 8 "mm.ooboooboo.mm", -- 9 "mmmooooooooommm", -- 10 "mmm.ooooooo.mmm", -- 11 "mmmmm.opp.mmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 12 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmm.opoooop.mmm", -- 3 "mmmopooooopommm", -- 4 "mmmppooooooommm", -- 5 "mmmoooobooopmmm", -- 6 "mmmpopbbbopommm", -- 7 "mmmoooobpooommm", -- 8 "mmmooooooooommm", -- 9 "mmmooooooooommm", -- 10 "mmm.ooooooo.mmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 13 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmooooommmmm", -- 4 "mmmmooooooommmm", -- 5 "mmmmooobooommmm", -- 6 "mmmmoobbbopmmmm", -- 7 "mmmmooobooommmm", -- 8 "mmmmopooooommmm", -- 9 "mmmmmooooommmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 14 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmm.ooo.mmmmm", -- 3 "mmmmmooooommmmm", -- 4 "mmm.ooobooo.mmm", -- 5 "mmmoooopoooommm", -- 6 "mmmoobpboboommm", -- 7 "mmmooooooooommm", -- 8 "mmm.opobooo.mmm", -- 9 "mmmmmopoppmmmmm", -- 10 "mmmmm.ooo.mmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 15 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmm.ooo.mmmmm", -- 3 "mmmmmooooommmmm", -- 4 "mmm.pooopoo.mmm", -- 5 "mmmoooopoooommm", -- 6 "mmmopooboooommm", -- 7 "mmmooooooooommm", -- 8 "mmm.oooopoo.mmm", -- 9 "mmmmmpoooommmmm", -- 10 "mmmmm.ooo.mmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 16 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmommmmmmm", -- 4 "mmmmm.ooo.mmmmm", -- 5 "mmmmmopopommmmm", -- 6 "mmmmooobooommmm", -- 7 "mmmmmpoooommmmm", -- 8 "mmmmm.opo.mmmmm", -- 9 "mmmmmmmommmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 17 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmm.ooo.mmmmm", -- 5 "mmmmmooooommmmm", -- 6 "mmmmmpoooommmmm", -- 7 "mmmmmooppommmmm", -- 8 "mmmmm.ooo.mmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 18 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmmmmmmmmm", -- 5 "mmmmmmmommmmmmm", -- 6 "mmmmmmooommmmmm", -- 7 "mmmmmmmommmmmmm", -- 8 "mmmmmmmmmmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 }, }, -- CrossTreetop { OriginData = { ExportName = "LadderTreetop", Name = "Cube 154", GalleryName = "Cube", GalleryIndex = "154", ID = "1199", CreatorName = "xoft2", }, Size = { x = 11, y = 19, z = 11, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 10, MaxY = 18, MaxZ = 10, }, Connectors = { { Type = 1, RelX = 5, RelY = 0, RelZ = 5, Direction = 0, -- Y- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "10000", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "None", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a: 65: 2", -- ladder "b: 17: 3", -- tree "c: 65: 4", -- ladder "d: 65: 5", -- ladder "e: 65: 3", -- ladder "f: 18: 7", -- leaves "g: 18: 3", -- leaves "h: 18:11", -- leaves "i: 17:11", -- tree "j: 17: 7", -- tree "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "mmmmmmmmmmm", -- 0 "mmmmmmmmmmm", -- 1 "mmmmmmmmmmm", -- 2 "mmmmmammmmm", -- 3 "mmmmbbbmmmm", -- 4 "mmmcbbbdmmm", -- 5 "mmmmbbbmmmm", -- 6 "mmmmmemmmmm", -- 7 "mmmmmmmmmmm", -- 8 "mmmmmmmmmmm", -- 9 "mmmmmmmmmmm", -- 10 -- Level 1 "mmmmmmmmmmm", -- 0 "mmmmmmmmmmm", -- 1 "mmmmmmmmmmm", -- 2 "mmmmmammmmm", -- 3 "mmmmbbbmmmm", -- 4 "mmmcbbbdmmm", -- 5 "mmmmbbbmmmm", -- 6 "mmmmmemmmmm", -- 7 "mmmmmmmmmmm", -- 8 "mmmmmmmmmmm", -- 9 "mmmmmmmmmmm", -- 10 -- Level 2 "mmmmmmmmmmm", -- 0 "mmmmmmmmmmm", -- 1 "mmmmmmmmmmm", -- 2 "mmmmmammmmm", -- 3 "mmmmbbbmmmm", -- 4 "mmmcbbbdmmm", -- 5 "mmmmbbbmmmm", -- 6 "mmmmmemmmmm", -- 7 "mmmmmmmmmmm", -- 8 "mmmmmmmmmmm", -- 9 "mmmmmmmmmmm", -- 10 -- Level 3 "mmmmmmmmmmm", -- 0 "mmmmmmmmmmm", -- 1 "mmmmmmmmmmm", -- 2 "mmmmmammmmm", -- 3 "mmmmbbbmmmm", -- 4 "mmmcbbbdmmm", -- 5 "mmmmbbbmmmm", -- 6 "mmmmmemmmmm", -- 7 "mmmmmmmmmmm", -- 8 "mmmmmmmmmmm", -- 9 "mmmmmmmmmmm", -- 10 -- Level 4 "mmmmmmmmmmm", -- 0 "mmmmmmmmmmm", -- 1 "mmmmmmmmmmm", -- 2 "mmmmmammmmm", -- 3 "mmmmbbbmmmm", -- 4 "mmmcbbbdmmm", -- 5 "mmmmbbbmmmm", -- 6 "mmmmmemmmmm", -- 7 "mmmmmmmmmmm", -- 8 "mmmmmmmmmmm", -- 9 "mmmmmmmmmmm", -- 10 -- Level 5 "mmmmmmmmmmm", -- 0 "mmmmmmmmmmm", -- 1 "mmmmmmmmmmm", -- 2 "mmmmmammmmm", -- 3 "mmmmbbbmmmm", -- 4 "mmmcbbbdmmm", -- 5 "mmmmbbbmmmm", -- 6 "mmmmmemmmmm", -- 7 "mmmmmmmmmmm", -- 8 "mmmmmmmmmmm", -- 9 "mmmmmmmmmmm", -- 10 -- Level 6 "mmmmmmmmmmm", -- 0 "mmmmmmmmmmm", -- 1 "mmmmmmmmmmm", -- 2 "mmmmmammmmm", -- 3 "mmmmbbbmmmm", -- 4 "mmmcbbbdmmm", -- 5 "mmmmbbbmmmm", -- 6 "mmmmmemmmmm", -- 7 "mmmmmmmmmmm", -- 8 "mmmmmmmmmmm", -- 9 "mmmmmmmmmmm", -- 10 -- Level 7 "mmmmmmmmmmm", -- 0 "mmmmmmmmmmm", -- 1 "mmmmmmmmmmm", -- 2 "mmmmmmmmmmm", -- 3 "mmmmbbbmmmm", -- 4 "mmmmbbbmmmm", -- 5 "mmmmbbbmmmm", -- 6 "mmmmmmmmmmm", -- 7 "mmmmmmmmmmm", -- 8 "mmmmmmmmmmm", -- 9 "mmmmmmmmmmm", -- 10 -- Level 8 "mmmmmmmmmmm", -- 0 "mmmmmmmmmmm", -- 1 "mmmmmmmmmmm", -- 2 "mmmmmmmmmmm", -- 3 "mmmmbbbmmmm", -- 4 "mmmmbbbmmmm", -- 5 "mmmmbbbmmmm", -- 6 "mmmmmmmmmmm", -- 7 "mmmmmmmmmmm", -- 8 "mmmmmmmmmmm", -- 9 "mmmmmmmmmmm", -- 10 -- Level 9 "mmmmmmmmmmm", -- 0 "mmmmfffmmmm", -- 1 "mmfghhghfmm", -- 2 "mmghghhggmm", -- 3 "mfghbbbhhfm", -- 4 "mfghbbbhhfm", -- 5 "mfhhbbbhhfm", -- 6 "mmhgghhhgmm", -- 7 "mmfhhghhfmm", -- 8 "mmmmfffmmmm", -- 9 "mmmmmmmmmmm", -- 10 -- Level 10 "mmm.ghg.mmm", -- 0 "mmfhhhhgfmm", -- 1 "mffhgihgffm", -- 2 ".ggggihhhh.", -- 3 "hhhhbbbhhhh", -- 4 "hhjjbbbjjgg", -- 5 "hhghbbbghhh", -- 6 ".gghgighgh.", -- 7 "mffggihhffm", -- 8 "mmfgghhhfmm", -- 9 "mmm.hhh.mmm", -- 10 -- Level 11 "mmm.hhg.mmm", -- 0 "m.hhghhgg.m", -- 1 "mhghggghhhm", -- 2 ".hgbgggbhh.", -- 3 "hghghbhghhh", -- 4 "ghhhbbbhhhh", -- 5 "hhhhhbhhghh", -- 6 ".ggbhghbgh.", -- 7 "mhghhgghghm", -- 8 "m.hhhhghg.m", -- 9 "mmm.hhh.mmm", -- 10 -- Level 12 "mmmmmmmmmmm", -- 0 "m.ghghggg.m", -- 1 "mghhhgghhgm", -- 2 "mghhhghhhgm", -- 3 "mhghhbhghhm", -- 4 "mghgbbbghhm", -- 5 "mgghgbhhhhm", -- 6 "mhghhghhghm", -- 7 "mhghhhgghhm", -- 8 "m.gghghgh.m", -- 9 "mmmmmmmmmmm", -- 10 -- Level 13 "mmmmmmmmmmm", -- 0 "mmmmmmmmmmm", -- 1 "mmmhgghhmmm", -- 2 "mmggghhhgmm", -- 3 "mmghgbhghmm", -- 4 "mmggbbbghmm", -- 5 "mmgghbhhhmm", -- 6 "mmhghhhhhmm", -- 7 "mmmhhhhhmmm", -- 8 "mmmmmmmmmmm", -- 9 "mmmmmmmmmmm", -- 10 -- Level 14 "mmmmmmmmmmm", -- 0 "mmm.ghh.mmm", -- 1 "mmmhhghhmmm", -- 2 "m.hggbhgh.m", -- 3 "mghhhghhhhm", -- 4 "mhhbgbhbggm", -- 5 "mhhhghghhgm", -- 6 "m.hghbghh.m", -- 7 "mmmhhhggmmm", -- 8 "mmm.hhg.mmm", -- 9 "mmmmmmmmmmm", -- 10 -- Level 15 "mmmmmmmmmmm", -- 0 "mmm.ggh.mmm", -- 1 "mmmghghgmmm", -- 2 "m.ghghghh.m", -- 3 "mhghhhghhhm", -- 4 "mgghhbhhghm", -- 5 "mhhghhghhhm", -- 6 "m.ghgghhh.m", -- 7 "mmmhhhhhmmm", -- 8 "mmm.hhh.mmm", -- 9 "mmmmmmmmmmm", -- 10 -- Level 16 "mmmmmmmmmmm", -- 0 "mmmmmmmmmmm", -- 1 "mmmmmgmmmmm", -- 2 "mmm.hhh.mmm", -- 3 "mmmhhhhhmmm", -- 4 "mmgghbhhhmm", -- 5 "mmmhhhghmmm", -- 6 "mmm.hhg.mmm", -- 7 "mmmmmhmmmmm", -- 8 "mmmmmmmmmmm", -- 9 "mmmmmmmmmmm", -- 10 -- Level 17 "mmmmmmmmmmm", -- 0 "mmmmmmmmmmm", -- 1 "mmmmmmmmmmm", -- 2 "mmm.hhg.mmm", -- 3 "mmmghghgmmm", -- 4 "mmmhhghgmmm", -- 5 "mmmhhghgmmm", -- 6 "mmm.hhh.mmm", -- 7 "mmmmmmmmmmm", -- 8 "mmmmmmmmmmm", -- 9 "mmmmmmmmmmm", -- 10 -- Level 18 "mmmmmmmmmmm", -- 0 "mmmmmmmmmmm", -- 1 "mmmmmmmmmmm", -- 2 "mmmmmmmmmmm", -- 3 "mmmmmhmmmmm", -- 4 "mmmmhggmmmm", -- 5 "mmmmmgmmmmm", -- 6 "mmmmmmmmmmm", -- 7 "mmmmmmmmmmm", -- 8 "mmmmmmmmmmm", -- 9 "mmmmmmmmmmm", -- 10 }, }, -- LadderTreetop { OriginData = { ExportName = "BareTreetop", Name = "Cube 155", GalleryName = "Cube", GalleryIndex = "155", ID = "1200", CreatorName = "xoft2", }, Size = { x = 11, y = 19, z = 11, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 10, MaxY = 18, MaxZ = 10, }, Connectors = { { Type = 2, RelX = 5, RelY = 0, RelZ = 5, Direction = 0, -- Y- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "10000", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "None", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a: 17: 3", -- tree "b: 18: 7", -- leaves "c: 18:11", -- leaves "d: 18: 3", -- leaves "e: 17:11", -- tree "f: 17: 7", -- tree "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "mmmmmmmmmmm", -- 0 "mmmmmmmmmmm", -- 1 "mmmmmmmmmmm", -- 2 "mmmmm.mmmmm", -- 3 "mmmmaaammmm", -- 4 "mmm.aaa.mmm", -- 5 "mmmmaaammmm", -- 6 "mmmmm.mmmmm", -- 7 "mmmmmmmmmmm", -- 8 "mmmmmmmmmmm", -- 9 "mmmmmmmmmmm", -- 10 -- Level 1 "mmmmmmmmmmm", -- 0 "mmmmmmmmmmm", -- 1 "mmmmmmmmmmm", -- 2 "mmmmm.mmmmm", -- 3 "mmmmaaammmm", -- 4 "mmm.aaa.mmm", -- 5 "mmmmaaammmm", -- 6 "mmmmm.mmmmm", -- 7 "mmmmmmmmmmm", -- 8 "mmmmmmmmmmm", -- 9 "mmmmmmmmmmm", -- 10 -- Level 2 "mmmmmmmmmmm", -- 0 "mmmmmmmmmmm", -- 1 "mmmmmmmmmmm", -- 2 "mmmmm.mmmmm", -- 3 "mmmmaaammmm", -- 4 "mmm.aaa.mmm", -- 5 "mmmmaaammmm", -- 6 "mmmmm.mmmmm", -- 7 "mmmmmmmmmmm", -- 8 "mmmmmmmmmmm", -- 9 "mmmmmmmmmmm", -- 10 -- Level 3 "mmmmmmmmmmm", -- 0 "mmmmmmmmmmm", -- 1 "mmmmmmmmmmm", -- 2 "mmmmm.mmmmm", -- 3 "mmmmaaammmm", -- 4 "mmm.aaa.mmm", -- 5 "mmmmaaammmm", -- 6 "mmmmm.mmmmm", -- 7 "mmmmmmmmmmm", -- 8 "mmmmmmmmmmm", -- 9 "mmmmmmmmmmm", -- 10 -- Level 4 "mmmmmmmmmmm", -- 0 "mmmmmmmmmmm", -- 1 "mmmmmmmmmmm", -- 2 "mmmmm.mmmmm", -- 3 "mmmmaaammmm", -- 4 "mmm.aaa.mmm", -- 5 "mmmmaaammmm", -- 6 "mmmmm.mmmmm", -- 7 "mmmmmmmmmmm", -- 8 "mmmmmmmmmmm", -- 9 "mmmmmmmmmmm", -- 10 -- Level 5 "mmmmmmmmmmm", -- 0 "mmmmmmmmmmm", -- 1 "mmmmmmmmmmm", -- 2 "mmmmm.mmmmm", -- 3 "mmmmaaammmm", -- 4 "mmm.aaa.mmm", -- 5 "mmmmaaammmm", -- 6 "mmmmm.mmmmm", -- 7 "mmmmmmmmmmm", -- 8 "mmmmmmmmmmm", -- 9 "mmmmmmmmmmm", -- 10 -- Level 6 "mmmmmmmmmmm", -- 0 "mmmmmmmmmmm", -- 1 "mmmmmmmmmmm", -- 2 "mmmmm.mmmmm", -- 3 "mmmmaaammmm", -- 4 "mmm.aaa.mmm", -- 5 "mmmmaaammmm", -- 6 "mmmmm.mmmmm", -- 7 "mmmmmmmmmmm", -- 8 "mmmmmmmmmmm", -- 9 "mmmmmmmmmmm", -- 10 -- Level 7 "mmmmmmmmmmm", -- 0 "mmmmmmmmmmm", -- 1 "mmmmmmmmmmm", -- 2 "mmmmmmmmmmm", -- 3 "mmmmaaammmm", -- 4 "mmmmaaammmm", -- 5 "mmmmaaammmm", -- 6 "mmmmmmmmmmm", -- 7 "mmmmmmmmmmm", -- 8 "mmmmmmmmmmm", -- 9 "mmmmmmmmmmm", -- 10 -- Level 8 "mmmmmmmmmmm", -- 0 "mmmmmmmmmmm", -- 1 "mmmmmmmmmmm", -- 2 "mmmmmmmmmmm", -- 3 "mmmmaaammmm", -- 4 "mmmmaaammmm", -- 5 "mmmmaaammmm", -- 6 "mmmmmmmmmmm", -- 7 "mmmmmmmmmmm", -- 8 "mmmmmmmmmmm", -- 9 "mmmmmmmmmmm", -- 10 -- Level 9 "mmmmmmmmmmm", -- 0 "mmmmbbbmmmm", -- 1 "mmbcccccbmm", -- 2 "mmcccccccmm", -- 3 "mbdcaaacdbm", -- 4 "mbdcaaaccbm", -- 5 "mbccaaaccbm", -- 6 "mmccdcdccmm", -- 7 "mmbcdcdcbmm", -- 8 "mmmmbbbmmmm", -- 9 "mmmmmmmmmmm", -- 10 -- Level 10 "mmm.ccc.mmm", -- 0 "mmbccdccbmm", -- 1 "mbbcceccbbm", -- 2 ".cdccecccc.", -- 3 "ccccaaacccc", -- 4 "ccffaaaffcc", -- 5 "cdccaaaccdc", -- 6 ".ccccedccc.", -- 7 "mbbcceccbbm", -- 8 "mmbcccccbmm", -- 9 "mmm.ccd.mmm", -- 10 -- Level 11 "mmm.ccc.mmm", -- 0 "m.cccdccc.m", -- 1 "mccdccccccm", -- 2 ".ccacccacd.", -- 3 "cccccaccccc", -- 4 "ccccaaacccc", -- 5 "dccccaccccc", -- 6 ".dcacccacc.", -- 7 "mcdccdccccm", -- 8 "m.ccccccc.m", -- 9 "mmm.ccc.mmm", -- 10 -- Level 12 "mmmmmmmmmmm", -- 0 "m.ccccccd.m", -- 1 "mdcdccccccm", -- 2 "mcccccccccm", -- 3 "mccccaccccm", -- 4 "mdccaaacdcm", -- 5 "mccdcaccccm", -- 6 "mcccccccccm", -- 7 "mcdcccccccm", -- 8 "m.ccccccc.m", -- 9 "mmmmmmmmmmm", -- 10 -- Level 13 "mmmmmmmmmmm", -- 0 "mmmmmmmmmmm", -- 1 "mmmddccdmmm", -- 2 "mmccccccdmm", -- 3 "mmdccacccmm", -- 4 "mmccaaaccmm", -- 5 "mmcdcacccmm", -- 6 "mmcccccccmm", -- 7 "mmmcccccmmm", -- 8 "mmmmmmmmmmm", -- 9 "mmmmmmmmmmm", -- 10 -- Level 14 "mmmmmmmmmmm", -- 0 "mmm.ccd.mmm", -- 1 "mmmcdcccmmm", -- 2 "m.cccaccc.m", -- 3 "mdcccccdccm", -- 4 "mcdadacaccm", -- 5 "mccccccccdm", -- 6 "m.ccdaccc.m", -- 7 "mmmcccccmmm", -- 8 "mmm.ccc.mmm", -- 9 "mmmmmmmmmmm", -- 10 -- Level 15 "mmmmmmmmmmm", -- 0 "mmm.dcc.mmm", -- 1 "mmmcccccmmm", -- 2 "m.ccccccc.m", -- 3 "mcdcdcccccm", -- 4 "mccccacccdm", -- 5 "mcccccccccm", -- 6 "m.dcccccc.m", -- 7 "mmmcccdcmmm", -- 8 "mmm.ccc.mmm", -- 9 "mmmmmmmmmmm", -- 10 -- Level 16 "mmmmmmmmmmm", -- 0 "mmmmmmmmmmm", -- 1 "mmmmmcmmmmm", -- 2 "mmm.ccc.mmm", -- 3 "mmmcccccmmm", -- 4 "mmccdacccmm", -- 5 "mmmcdcccmmm", -- 6 "mmm.ccc.mmm", -- 7 "mmmmmcmmmmm", -- 8 "mmmmmmmmmmm", -- 9 "mmmmmmmmmmm", -- 10 -- Level 17 "mmmmmmmmmmm", -- 0 "mmmmmmmmmmm", -- 1 "mmmmmmmmmmm", -- 2 "mmm.ccc.mmm", -- 3 "mmmcccccmmm", -- 4 "mmmcccdcmmm", -- 5 "mmmcccccmmm", -- 6 "mmm.ccc.mmm", -- 7 "mmmmmmmmmmm", -- 8 "mmmmmmmmmmm", -- 9 "mmmmmmmmmmm", -- 10 -- Level 18 "mmmmmmmmmmm", -- 0 "mmmmmmmmmmm", -- 1 "mmmmmmmmmmm", -- 2 "mmmmmmmmmmm", -- 3 "mmmmmcmmmmm", -- 4 "mmmmcccmmmm", -- 5 "mmmmmcmmmmm", -- 6 "mmmmmmmmmmm", -- 7 "mmmmmmmmmmm", -- 8 "mmmmmmmmmmm", -- 9 "mmmmmmmmmmm", -- 10 }, }, -- BareTreetop }, -- Pieces } ================================================ FILE: Server/Prefabs/PieceStructures/UnderwaterBase.cubeset ================================================ -- UnderwaterBase.cubeset -- Defines the prefabs in the group UnderwaterBase -- NOTE: This file has been generated automatically by GalExport! -- Any manual changes will be overwritten by the next automatic export! Cubeset = { Metadata = { CubesetFormatVersion = 1, ExportDate = "2016-11-23 15:08:06", ["GridSizeX"] = "384", ["GridSizeZ"] = "384", ["IntendedUse"] = "PieceStructures", ["MaxDepth"] = "12", ["MaxOffsetX"] = "128", ["MaxOffsetZ"] = "128", ["MaxStructureSizeX"] = "128", ["MaxStructureSizeZ"] = "128", }, Pieces = { { OriginData = { ExportName = "CentralRoom", Name = "Water 24", GalleryName = "Water", GalleryIndex = "24", ID = "564", CreatorName = "xoft", }, Size = { x = 16, y = 7, z = 16, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 15, MaxY = 6, MaxZ = 15, }, Connectors = { { Type = 1, RelX = 0, RelY = 1, RelZ = 7, Direction = 4, -- X- }, { Type = -1, RelX = 0, RelY = 1, RelZ = 8, Direction = 4, -- X- }, { Type = -1, RelX = 7, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, { Type = 1, RelX = 8, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, { Type = 1, RelX = 15, RelY = 1, RelZ = 8, Direction = 5, -- X+ }, { Type = -1, RelX = 15, RelY = 1, RelZ = 7, Direction = 5, -- X+ }, { Type = 1, RelX = 7, RelY = 1, RelZ = 15, Direction = 3, -- Z+ }, { Type = -1, RelX = 8, RelY = 1, RelZ = 15, Direction = 3, -- Z+ }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "None", ["IsStarting"] = "1", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", ["VerticalStrategy"] = "TerrainOrOceanTop|-11", }, BlockDefinitions = { ".: 0: 0", -- air "a: 5: 5", -- planks "b: 5: 0", -- planks "c: 20: 0", -- glass "d: 64: 3", -- wooddoorblock "e: 64: 2", -- wooddoorblock "f: 64: 0", -- wooddoorblock "g: 64: 1", -- wooddoorblock "h: 64: 8", -- wooddoorblock "i: 64: 9", -- wooddoorblock "j: 76: 3", -- redstonetorchon "k: 76: 1", -- redstonetorchon "l: 76: 2", -- redstonetorchon "m: 19: 0", -- sponge "n: 76: 4", -- redstonetorchon "o:125: 8", -- woodendoubleslab }, BlockData = { -- Level 0 "mmmmmmmaammmmmmm", -- 0 "mmmmmmmbbmmmmmmm", -- 1 "mmmmmmmbbmmmmmmm", -- 2 "mmmmmmbbbbmmmmmm", -- 3 "mmmmmbbbbbbmmmmm", -- 4 "mmmmbbbccbbbmmmm", -- 5 "mmmbbbccccbbbmmm", -- 6 "abbbbccccccbbbba", -- 7 "abbbbccccccbbbba", -- 8 "mmmbbbccccbbbmmm", -- 9 "mmmmbbbccbbbmmmm", -- 10 "mmmmmbbbbbbmmmmm", -- 11 "mmmmmmbbbbmmmmmm", -- 12 "mmmmmmmbbmmmmmmm", -- 13 "mmmmmmmbbmmmmmmm", -- 14 "mmmmmmmaammmmmmm", -- 15 -- Level 1 "mmmmmmaddammmmmm", -- 0 "mmmmmmb..bmmmmmm", -- 1 "mmmmmmb..bmmmmmm", -- 2 "mmmmmbb..bbmmmmm", -- 3 "mmmmbb....bbmmmm", -- 4 "mmmbb......bbmmm", -- 5 "abbb........bbba", -- 6 "e..............f", -- 7 "e..............f", -- 8 "abbb........bbba", -- 9 "mmmbb......bbmmm", -- 10 "mmmmbb....bbmmmm", -- 11 "mmmmmbb..bbmmmmm", -- 12 "mmmmmmb..bmmmmmm", -- 13 "mmmmmmb..bmmmmmm", -- 14 "mmmmmmaggammmmmm", -- 15 -- Level 2 "mmmmmmahiammmmmm", -- 0 "mmmmmmb..bmmmmmm", -- 1 "mmmmmmb..bmmmmmm", -- 2 "mmmmmcc..ccmmmmm", -- 3 "mmmmcc....ccmmmm", -- 4 "mmmcc......ccmmm", -- 5 "abbc........cbba", -- 6 "i..............h", -- 7 "h..............i", -- 8 "abbc........cbba", -- 9 "mmmcc......ccmmm", -- 10 "mmmmcc....ccmmmm", -- 11 "mmmmmcc..ccmmmmm", -- 12 "mmmmmmb..bmmmmmm", -- 13 "mmmmmmb..bmmmmmm", -- 14 "mmmmmmaihammmmmm", -- 15 -- Level 3 "mmmmmmaaaammmmmm", -- 0 "mmmmmmbbbbmmmmmm", -- 1 "mmmmmmbbbbmmmmmm", -- 2 "mmmmmbb..bbmmmmm", -- 3 "mmmmbb....bbmmmm", -- 4 "mmmbb......bbmmm", -- 5 "abbb........bbba", -- 6 "abb..........bba", -- 7 "abb..........bba", -- 8 "abbb........bbba", -- 9 "mmmbb......bbmmm", -- 10 "mmmmbb....bbmmmm", -- 11 "mmmmmbb..bbmmmmm", -- 12 "mmmmmmbbbbmmmmmm", -- 13 "mmmmmmbbbbmmmmmm", -- 14 "mmmmmmaaaammmmmm", -- 15 -- Level 4 "mmmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmmm", -- 2 "mmmmmmmbbmmmmmmm", -- 3 "mmmmmmbjjbmmmmmm", -- 4 "mmmmmb....bmmmmm", -- 5 "mmmmb......bmmmm", -- 6 "mmmbk......lbmmm", -- 7 "mmmbk......lbmmm", -- 8 "mmmmb......bmmmm", -- 9 "mmmmmb....bmmmmm", -- 10 "mmmmmmbnnbmmmmmm", -- 11 "mmmmmmmbbmmmmmmm", -- 12 "mmmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmmm", -- 14 "mmmmmmmmmmmmmmmm", -- 15 -- Level 5 "mmmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmmm", -- 3 "mmmmmmmbbmmmmmmm", -- 4 "mmmmmmb..bmmmmmm", -- 5 "mmmmmb....bmmmmm", -- 6 "mmmmb......bmmmm", -- 7 "mmmmb......bmmmm", -- 8 "mmmmmb....bmmmmm", -- 9 "mmmmmmboobmmmmmm", -- 10 "mmmmmmmbbmmmmmmm", -- 11 "mmmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmmm", -- 14 "mmmmmmmmmmmmmmmm", -- 15 -- Level 6 "mmmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmmm", -- 4 "mmmmmmmbbmmmmmmm", -- 5 "mmmmmmbbbbmmmmmm", -- 6 "mmmmmbbccbbmmmmm", -- 7 "mmmmmbbccbbmmmmm", -- 8 "mmmmmmbbbbmmmmmm", -- 9 "mmmmmmmbbmmmmmmm", -- 10 "mmmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmmm", -- 14 "mmmmmmmmmmmmmmmm", -- 15 }, }, -- CentralRoom { OriginData = { ExportName = "Corridor16", Name = "Water 25", GalleryName = "Water", GalleryIndex = "25", ID = "566", CreatorName = "xoft", }, Size = { x = 16, y = 4, z = 4, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 15, MaxY = 3, MaxZ = 3, }, Connectors = { { Type = 1, RelX = 0, RelY = 1, RelZ = 1, Direction = 4, -- X- }, { Type = -1, RelX = 0, RelY = 1, RelZ = 2, Direction = 4, -- X- }, { Type = 1, RelX = 15, RelY = 1, RelZ = 2, Direction = 5, -- X+ }, { Type = -1, RelX = 15, RelY = 1, RelZ = 1, Direction = 5, -- X+ }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "500", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "None", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a: 5: 5", -- planks "b: 5: 0", -- planks "c: 64: 2", -- wooddoorblock "d: 64: 0", -- wooddoorblock "e: 20: 0", -- glass "f: 64: 9", -- wooddoorblock "g: 76: 3", -- redstonetorchon "h: 64: 8", -- wooddoorblock "i: 76: 4", -- redstonetorchon "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "mmmmmmmmmmmmmmmm", -- 0 "abbbbbbbbbbbbbba", -- 1 "abbbbbbbbbbbbbba", -- 2 "mmmmmmmmmmmmmmmm", -- 3 -- Level 1 "abbbbbbbbbbbbbba", -- 0 "c..............d", -- 1 "c..............d", -- 2 "abbbbbbbbbbbbbba", -- 3 -- Level 2 "abeebbbeebbbeeba", -- 0 "f...g......g...h", -- 1 "h...i......i...f", -- 2 "abeebbbeebbbeeba", -- 3 -- Level 3 "abbbbbbbbbbbbbba", -- 0 "abbbbbbbbbbbbbba", -- 1 "abbbbbbbbbbbbbba", -- 2 "abbbbbbbbbbbbbba", -- 3 }, }, -- Corridor16 { OriginData = { ExportName = "CorridorCorner", Name = "Water 26", GalleryName = "Water", GalleryIndex = "26", ID = "569", CreatorName = "xoft", }, Size = { x = 10, y = 4, z = 10, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 9, MaxY = 3, MaxZ = 9, }, Connectors = { { Type = 1, RelX = 7, RelY = 1, RelZ = 9, Direction = 3, -- Z+ }, { Type = -1, RelX = 8, RelY = 1, RelZ = 9, Direction = 3, -- Z+ }, { Type = 1, RelX = 0, RelY = 1, RelZ = 1, Direction = 4, -- X- }, { Type = -1, RelX = 0, RelY = 1, RelZ = 2, Direction = 4, -- X- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "200", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "None", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a: 5: 5", -- planks "b: 5: 0", -- planks "c: 64: 2", -- wooddoorblock "d: 64: 1", -- wooddoorblock "e: 20: 0", -- glass "f: 64: 9", -- wooddoorblock "g: 76: 3", -- redstonetorchon "h: 64: 8", -- wooddoorblock "i: 76: 4", -- redstonetorchon "j: 76: 2", -- redstonetorchon "k: 76: 1", -- redstonetorchon "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "mmmmmmmmmm", -- 0 "abbbbbmmmm", -- 1 "abbbbbbbmm", -- 2 "mmmbbbbbmm", -- 3 "mmmmmbbbbm", -- 4 "mmmmmmbbbm", -- 5 "mmmmmmbbbm", -- 6 "mmmmmmmbbm", -- 7 "mmmmmmmbbm", -- 8 "mmmmmmmaam", -- 9 -- Level 1 "abbbbbmmmm", -- 0 "c.....bbmm", -- 1 "c.......bm", -- 2 "abb.....bm", -- 3 "mmmbb....b", -- 4 "mmmmmb...b", -- 5 "mmmmmb...b", -- 6 "mmmmmmb..b", -- 7 "mmmmmmb..b", -- 8 "mmmmmmadda", -- 9 -- Level 2 "abeebbmmmm", -- 0 "f...g.bbmm", -- 1 "h.......bm", -- 2 "abbi....bm", -- 3 "mmmbb....b", -- 4 "mmmmmb..jb", -- 5 "mmmmmbk..e", -- 6 "mmmmmmb..e", -- 7 "mmmmmmb..b", -- 8 "mmmmmmafha", -- 9 -- Level 3 "abbbbbmmmm", -- 0 "abbbbbbbmm", -- 1 "abbbbbbbbm", -- 2 "abbbbbbbbm", -- 3 "mmmbbbbbbb", -- 4 "mmmmmbbbbb", -- 5 "mmmmmbbbbb", -- 6 "mmmmmmbbbb", -- 7 "mmmmmmbbbb", -- 8 "mmmmmmaaaa", -- 9 }, }, -- CorridorCorner { OriginData = { ExportName = "ViewingCorridor", Name = "Water 27", GalleryName = "Water", GalleryIndex = "27", ID = "571", CreatorName = "LO1ZB", }, Size = { x = 16, y = 5, z = 6, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 15, MaxY = 4, MaxZ = 5, }, Connectors = { { Type = 1, RelX = 0, RelY = 1, RelZ = 2, Direction = 4, -- X- }, { Type = -1, RelX = 0, RelY = 1, RelZ = 3, Direction = 4, -- X- }, { Type = 1, RelX = 15, RelY = 1, RelZ = 3, Direction = 5, -- X+ }, { Type = -1, RelX = 15, RelY = 1, RelZ = 2, Direction = 5, -- X+ }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "None", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a: 5: 0", -- planks "b: 5: 5", -- planks "c: 20: 0", -- glass "d: 64: 2", -- wooddoorblock "e: 64: 0", -- wooddoorblock "f: 76: 3", -- redstonetorchon "g: 64: 9", -- wooddoorblock "h: 64: 8", -- wooddoorblock "i: 76: 4", -- redstonetorchon "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "mmaaaaaaaaaaaamm", -- 0 "mmaaaaaaaaaaaamm", -- 1 "baaccccccccccaab", -- 2 "baaccccccccccaab", -- 3 "mmaaaaaaaaaaaamm", -- 4 "mmmaaaaaaaaaammm", -- 5 -- Level 1 "mmaccccccccccamm", -- 0 "ba............ab", -- 1 "d..............e", -- 2 "d..............e", -- 3 "ba............ab", -- 4 "mmaccccccccccamm", -- 5 -- Level 2 "mmaccccccccccamm", -- 0 "baf..........fab", -- 1 "g..............h", -- 2 "h..............g", -- 3 "bai..........iab", -- 4 "mmaccccccccccamm", -- 5 -- Level 3 "mmaccccccccccamm", -- 0 "ba............ab", -- 1 "ba............ab", -- 2 "ba............ab", -- 3 "ba............ab", -- 4 "mmaccccccccccamm", -- 5 -- Level 4 "mmmaaaaaaaaaammm", -- 0 "mmaaaaaaaaaaaamm", -- 1 "mmaccccccccccamm", -- 2 "mmaccccccccccamm", -- 3 "mmaaaaaaaaaaaamm", -- 4 "mmmaaaaaaaaaammm", -- 5 }, }, -- ViewingCorridor { OriginData = { ExportName = "CorridorTee", Name = "Water 29", GalleryName = "Water", GalleryIndex = "29", ID = "576", CreatorName = "LO1ZB", }, Size = { x = 16, y = 4, z = 10, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 15, MaxY = 3, MaxZ = 9, }, Connectors = { { Type = 1, RelX = 0, RelY = 1, RelZ = 7, Direction = 4, -- X- }, { Type = -1, RelX = 0, RelY = 1, RelZ = 8, Direction = 4, -- X- }, { Type = 1, RelX = 8, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, { Type = -1, RelX = 7, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, { Type = 1, RelX = 15, RelY = 1, RelZ = 8, Direction = 5, -- X+ }, { Type = -1, RelX = 15, RelY = 1, RelZ = 7, Direction = 5, -- X+ }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "None", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a: 5: 5", -- planks "b: 5: 0", -- planks "c: 64: 3", -- wooddoorblock "d: 64: 2", -- wooddoorblock "e: 64: 0", -- wooddoorblock "f: 64: 8", -- wooddoorblock "g: 64: 9", -- wooddoorblock "h: 20: 0", -- glass "i: 76: 1", -- redstonetorchon "j: 76: 2", -- redstonetorchon "k: 76: 3", -- redstonetorchon "l: 76: 4", -- redstonetorchon "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "mmmmmmmaammmmmmm", -- 0 "mmmmmmmbbmmmmmmm", -- 1 "mmmmmmmbbmmmmmmm", -- 2 "mmmmmmmbbmmmmmmm", -- 3 "mmmmmmmbbmmmmmmm", -- 4 "mmmmmmmbbmmmmmmm", -- 5 "mmmmmmmbbmmmmmmm", -- 6 "abbbbbbbbbbbbbba", -- 7 "abbbbbbbbbbbbbba", -- 8 "mmmmmmmmmmmmmmmm", -- 9 -- Level 1 "mmmmmmaccammmmmm", -- 0 "mmmmmmb..bmmmmmm", -- 1 "mmmmmmb..bmmmmmm", -- 2 "mmmmmmb..bmmmmmm", -- 3 "mmmmmmb..bmmmmmm", -- 4 "mmmmmmb..bmmmmmm", -- 5 "abbbbbb..bbbbbba", -- 6 "d..............e", -- 7 "d..............e", -- 8 "abbbbbbbbbbbbbba", -- 9 -- Level 2 "mmmmmmafgammmmmm", -- 0 "mmmmmmb..bmmmmmm", -- 1 "mmmmmmh..hmmmmmm", -- 2 "mmmmmmh..hmmmmmm", -- 3 "mmmmmmbijbmmmmmm", -- 4 "mmmmmmb..bmmmmmm", -- 5 "abhhbbb..bbbhhba", -- 6 "g...k......k...f", -- 7 "f...l......l...g", -- 8 "abhhbbbhhbbbhhba", -- 9 -- Level 3 "mmmmmmaaaammmmmm", -- 0 "mmmmmmbbbbmmmmmm", -- 1 "mmmmmmbbbbmmmmmm", -- 2 "mmmmmmbbbbmmmmmm", -- 3 "mmmmmmbbbbmmmmmm", -- 4 "mmmmmmbbbbmmmmmm", -- 5 "abbbbbbbbbbbbbba", -- 6 "abbbbbbbbbbbbbba", -- 7 "abbbbbbbbbbbbbba", -- 8 "abbbbbbbbbbbbbba", -- 9 }, }, -- CorridorTee { OriginData = { ExportName = "CorridorCrossing", Name = "Water 31", GalleryName = "Water", GalleryIndex = "31", ID = "581", CreatorName = "LO1ZB", }, Size = { x = 16, y = 4, z = 16, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 15, MaxY = 3, MaxZ = 15, }, Connectors = { { Type = 1, RelX = 0, RelY = 1, RelZ = 7, Direction = 4, -- X- }, { Type = -1, RelX = 0, RelY = 1, RelZ = 8, Direction = 4, -- X- }, { Type = 1, RelX = 7, RelY = 1, RelZ = 15, Direction = 3, -- Z+ }, { Type = -1, RelX = 8, RelY = 1, RelZ = 15, Direction = 3, -- Z+ }, { Type = 1, RelX = 8, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, { Type = -1, RelX = 7, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, { Type = 1, RelX = 15, RelY = 1, RelZ = 8, Direction = 5, -- X+ }, { Type = -1, RelX = 15, RelY = 1, RelZ = 7, Direction = 5, -- X+ }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "None", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a: 5: 5", -- planks "b: 5: 0", -- planks "c: 64: 3", -- wooddoorblock "d: 64: 2", -- wooddoorblock "e: 64: 0", -- wooddoorblock "f: 64: 1", -- wooddoorblock "g: 64: 8", -- wooddoorblock "h: 64: 9", -- wooddoorblock "i: 20: 0", -- glass "j: 76: 1", -- redstonetorchon "k: 76: 2", -- redstonetorchon "l: 76: 3", -- redstonetorchon "m: 19: 0", -- sponge "n: 76: 4", -- redstonetorchon }, BlockData = { -- Level 0 "mmmmmmmaammmmmmm", -- 0 "mmmmmmmbbmmmmmmm", -- 1 "mmmmmmmbbmmmmmmm", -- 2 "mmmmmmmbbmmmmmmm", -- 3 "mmmmmmmbbmmmmmmm", -- 4 "mmmmmmmbbmmmmmmm", -- 5 "mmmmmmmbbmmmmmmm", -- 6 "abbbbbbbbbbbbbba", -- 7 "abbbbbbbbbbbbbba", -- 8 "mmmmmmmbbmmmmmmm", -- 9 "mmmmmmmbbmmmmmmm", -- 10 "mmmmmmmbbmmmmmmm", -- 11 "mmmmmmmbbmmmmmmm", -- 12 "mmmmmmmbbmmmmmmm", -- 13 "mmmmmmmbbmmmmmmm", -- 14 "mmmmmmmaammmmmmm", -- 15 -- Level 1 "mmmmmmaccammmmmm", -- 0 "mmmmmmb..bmmmmmm", -- 1 "mmmmmmb..bmmmmmm", -- 2 "mmmmmmb..bmmmmmm", -- 3 "mmmmmmb..bmmmmmm", -- 4 "mmmmmmb..bmmmmmm", -- 5 "abbbbbb..bbbbbba", -- 6 "d..............e", -- 7 "d..............e", -- 8 "abbbbbb..bbbbbba", -- 9 "mmmmmmb..bmmmmmm", -- 10 "mmmmmmb..bmmmmmm", -- 11 "mmmmmmb..bmmmmmm", -- 12 "mmmmmmb..bmmmmmm", -- 13 "mmmmmmb..bmmmmmm", -- 14 "mmmmmmaffammmmmm", -- 15 -- Level 2 "mmmmmmaghammmmmm", -- 0 "mmmmmmb..bmmmmmm", -- 1 "mmmmmmi..immmmmm", -- 2 "mmmmmmi..immmmmm", -- 3 "mmmmmmbjkbmmmmmm", -- 4 "mmmmmmb..bmmmmmm", -- 5 "abiibbb..bbbiiba", -- 6 "h...l......l...g", -- 7 "g...n......n...h", -- 8 "abiibbb..bbbiiba", -- 9 "mmmmmmb..bmmmmmm", -- 10 "mmmmmmbjkbmmmmmm", -- 11 "mmmmmmi..immmmmm", -- 12 "mmmmmmi..immmmmm", -- 13 "mmmmmmb..bmmmmmm", -- 14 "mmmmmmahgammmmmm", -- 15 -- Level 3 "mmmmmmaaaammmmmm", -- 0 "mmmmmmbbbbmmmmmm", -- 1 "mmmmmmbbbbmmmmmm", -- 2 "mmmmmmbbbbmmmmmm", -- 3 "mmmmmmbbbbmmmmmm", -- 4 "mmmmmmbbbbmmmmmm", -- 5 "abbbbbbbbbbbbbba", -- 6 "abbbbbbbbbbbbbba", -- 7 "abbbbbbbbbbbbbba", -- 8 "abbbbbbbbbbbbbba", -- 9 "mmmmmmbbbbmmmmmm", -- 10 "mmmmmmbbbbmmmmmm", -- 11 "mmmmmmbbbbmmmmmm", -- 12 "mmmmmmbbbbmmmmmm", -- 13 "mmmmmmbbbbmmmmmm", -- 14 "mmmmmmaaaammmmmm", -- 15 }, }, -- CorridorCrossing { OriginData = { ExportName = "CorridorStairs", Name = "Water 32", GalleryName = "Water", GalleryIndex = "32", ID = "582", CreatorName = "LO1ZB", }, Size = { x = 16, y = 9, z = 4, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 15, MaxY = 8, MaxZ = 3, }, Connectors = { { Type = 1, RelX = 0, RelY = 1, RelZ = 1, Direction = 4, -- X- }, { Type = -1, RelX = 0, RelY = 1, RelZ = 2, Direction = 4, -- X- }, { Type = 1, RelX = 15, RelY = 6, RelZ = 2, Direction = 5, -- X+ }, { Type = -1, RelX = 15, RelY = 6, RelZ = 1, Direction = 5, -- X+ }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "None", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a: 5: 5", -- planks "b: 5: 0", -- planks "c: 64: 2", -- wooddoorblock "d: 53: 0", -- woodstairs "e: 20: 0", -- glass "f: 64: 9", -- wooddoorblock "g: 76: 3", -- redstonetorchon "h: 64: 8", -- wooddoorblock "i: 76: 4", -- redstonetorchon "j: 64: 0", -- wooddoorblock "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "mmmmmmmmmmmmmmmm", -- 0 "abbbbbbbmmmmmmmm", -- 1 "abbbbbbbmmmmmmmm", -- 2 "mmmmmmmmmmmmmmmm", -- 3 -- Level 1 "abbbbbbbmmmmmmmm", -- 0 "c.....dbbmmmmmmm", -- 1 "c.....dbbmmmmmmm", -- 2 "abbbbbbbmmmmmmmm", -- 3 -- Level 2 "abeebbbbbmmmmmmm", -- 0 "f...g..dbbmmmmmm", -- 1 "h...i..dbbmmmmmm", -- 2 "abeebbbbbmmmmmmm", -- 3 -- Level 3 "abbbbbbbbbmmmmmm", -- 0 "abbbb...dbbmmmmm", -- 1 "abbbb...dbbmmmmm", -- 2 "abbbbbbbbbmmmmmm", -- 3 -- Level 4 "mmmmmbbbbbmmmmmm", -- 0 "mmmmmb...dbbmmmm", -- 1 "mmmmmb...dbbmmmm", -- 2 "mmmmmbbbbbmmmmmm", -- 3 -- Level 5 "mmmmmmbbbbbmmmmm", -- 0 "mmmmmmb...dbbbba", -- 1 "mmmmmmb...dbbbba", -- 2 "mmmmmmbbbbbmmmmm", -- 3 -- Level 6 "mmmmmmmbbbbbbbba", -- 0 "mmmmmmmb.......j", -- 1 "mmmmmmmb.......j", -- 2 "mmmmmmmbbbbbbbba", -- 3 -- Level 7 "mmmmmmmmbbbeebba", -- 0 "mmmmmmmmb.g....h", -- 1 "mmmmmmmmb.i....f", -- 2 "mmmmmmmmbbbeebba", -- 3 -- Level 8 "mmmmmmmmmbbbbbba", -- 0 "mmmmmmmmmbbbbbba", -- 1 "mmmmmmmmmbbbbbba", -- 2 "mmmmmmmmmbbbbbba", -- 3 }, }, -- CorridorStairs { OriginData = { ExportName = "ViewingCrossing", Name = "Water 38", GalleryName = "Water", GalleryIndex = "38", ID = "611", CreatorName = "LO1ZB", }, Size = { x = 16, y = 7, z = 16, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 15, MaxY = 6, MaxZ = 15, }, Connectors = { { Type = 1, RelX = 0, RelY = 1, RelZ = 7, Direction = 4, -- X- }, { Type = -1, RelX = 0, RelY = 1, RelZ = 8, Direction = 4, -- X- }, { Type = 1, RelX = 8, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, { Type = -1, RelX = 7, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, { Type = 1, RelX = 15, RelY = 1, RelZ = 8, Direction = 5, -- X+ }, { Type = -1, RelX = 15, RelY = 1, RelZ = 7, Direction = 5, -- X+ }, { Type = 1, RelX = 7, RelY = 1, RelZ = 15, Direction = 3, -- Z+ }, { Type = -1, RelX = 8, RelY = 1, RelZ = 15, Direction = 3, -- Z+ }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "50", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "None", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a: 5: 5", -- planks "b: 5: 0", -- planks "c: 20: 0", -- glass "d: 64: 3", -- wooddoorblock "e: 76: 1", -- redstonetorchon "f: 76: 2", -- redstonetorchon "g: 64: 2", -- wooddoorblock "h: 76: 3", -- redstonetorchon "i: 64: 0", -- wooddoorblock "j: 76: 4", -- redstonetorchon "k: 64: 1", -- wooddoorblock "l: 64: 8", -- wooddoorblock "m: 19: 0", -- sponge "n: 64: 9", -- wooddoorblock }, BlockData = { -- Level 0 "mmmmmmmaammmmmmm", -- 0 "mmmmmmmbbmmmmmmm", -- 1 "mmmmmmmbbmmmmmmm", -- 2 "mmmmmmbbbbmmmmmm", -- 3 "mmmmmbbccbbmmmmm", -- 4 "mmmmbbccccbbmmmm", -- 5 "mmmbbccccccbbmmm", -- 6 "abbbccccccccbbba", -- 7 "abbbccccccccbbba", -- 8 "mmmbbccccccbbmmm", -- 9 "mmmmbbccccbbmmmm", -- 10 "mmmmmbbccbbmmmmm", -- 11 "mmmmmmbbbbmmmmmm", -- 12 "mmmmmmmbbmmmmmmm", -- 13 "mmmmmmmbbmmmmmmm", -- 14 "mmmmmmmaammmmmmm", -- 15 -- Level 1 "mmmmmmaddammmmmm", -- 0 "mmmmmmb..bmmmmmm", -- 1 "mmmmmmb..bmmmmmm", -- 2 "mmmmmbbefbbmmmmm", -- 3 "mmmmbb....bbmmmm", -- 4 "mmmbb......bbmmm", -- 5 "abbb........bbba", -- 6 "g..h........h..i", -- 7 "g..j........j..i", -- 8 "abbb........bbba", -- 9 "mmmbb......bbmmm", -- 10 "mmmmbb....bbmmmm", -- 11 "mmmmmbbefbbmmmmm", -- 12 "mmmmmmb..bmmmmmm", -- 13 "mmmmmmb..bmmmmmm", -- 14 "mmmmmmakkammmmmm", -- 15 -- Level 2 "mmmmmmalnammmmmm", -- 0 "mmmmmmb..bmmmmmm", -- 1 "mmmmmmc..cmmmmmm", -- 2 "mmmmmcc..ccmmmmm", -- 3 "mmmmcc....ccmmmm", -- 4 "mmmcc......ccmmm", -- 5 "abcc........ccba", -- 6 "n..............l", -- 7 "l..............n", -- 8 "abcc........ccba", -- 9 "mmmcc......ccmmm", -- 10 "mmmmcc....ccmmmm", -- 11 "mmmmmcc..ccmmmmm", -- 12 "mmmmmmc..cmmmmmm", -- 13 "mmmmmmb..bmmmmmm", -- 14 "mmmmmmanlammmmmm", -- 15 -- Level 3 "mmmmmmaaaammmmmm", -- 0 "mmmmmmbbbbmmmmmm", -- 1 "mmmmmmccccmmmmmm", -- 2 "mmmmmcc..ccmmmmm", -- 3 "mmmmcc....ccmmmm", -- 4 "mmmcc......ccmmm", -- 5 "abcc........ccba", -- 6 "abc..........cba", -- 7 "abc..........cba", -- 8 "abcc........ccba", -- 9 "mmmcc......ccmmm", -- 10 "mmmmcc....ccmmmm", -- 11 "mmmmmcc..ccmmmmm", -- 12 "mmmmmmccccmmmmmm", -- 13 "mmmmmmbbbbmmmmmm", -- 14 "mmmmmmaaaammmmmm", -- 15 -- Level 4 "mmmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmmm", -- 2 "mmmmmmmccmmmmmmm", -- 3 "mmmmmmc..cmmmmmm", -- 4 "mmmmmc....cmmmmm", -- 5 "mmmmc......cmmmm", -- 6 "mmmc........cmmm", -- 7 "mmmc........cmmm", -- 8 "mmmmc......cmmmm", -- 9 "mmmmmc....cmmmmm", -- 10 "mmmmmmc..cmmmmmm", -- 11 "mmmmmmmccmmmmmmm", -- 12 "mmmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmmm", -- 14 "mmmmmmmmmmmmmmmm", -- 15 -- Level 5 "mmmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmmm", -- 3 "mmmmmmmccmmmmmmm", -- 4 "mmmmmmc..cmmmmmm", -- 5 "mmmmmc....cmmmmm", -- 6 "mmmmc......cmmmm", -- 7 "mmmmc......cmmmm", -- 8 "mmmmmc....cmmmmm", -- 9 "mmmmmmc..cmmmmmm", -- 10 "mmmmmmmccmmmmmmm", -- 11 "mmmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmmm", -- 14 "mmmmmmmmmmmmmmmm", -- 15 -- Level 6 "mmmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmmm", -- 4 "mmmmmmmccmmmmmmm", -- 5 "mmmmmmccccmmmmmm", -- 6 "mmmmmccccccmmmmm", -- 7 "mmmmmccccccmmmmm", -- 8 "mmmmmmccccmmmmmm", -- 9 "mmmmmmmccmmmmmmm", -- 10 "mmmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmmm", -- 14 "mmmmmmmmmmmmmmmm", -- 15 }, }, -- ViewingCrossing { OriginData = { ExportName = "ViewingTee", Name = "Water 39", GalleryName = "Water", GalleryIndex = "39", ID = "612", CreatorName = "LO1ZB", }, Size = { x = 14, y = 7, z = 16, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 13, MaxY = 6, MaxZ = 15, }, Connectors = { { Type = 1, RelX = 6, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, { Type = -1, RelX = 5, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, { Type = 1, RelX = 13, RelY = 1, RelZ = 8, Direction = 5, -- X+ }, { Type = -1, RelX = 13, RelY = 1, RelZ = 7, Direction = 5, -- X+ }, { Type = 1, RelX = 5, RelY = 1, RelZ = 15, Direction = 3, -- Z+ }, { Type = -1, RelX = 6, RelY = 1, RelZ = 15, Direction = 3, -- Z+ }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "75", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "None", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a: 5: 5", -- planks "b: 5: 0", -- planks "c: 20: 0", -- glass "d: 64: 3", -- wooddoorblock "e: 76: 1", -- redstonetorchon "f: 76: 2", -- redstonetorchon "g: 76: 3", -- redstonetorchon "h: 64: 0", -- wooddoorblock "i: 76: 4", -- redstonetorchon "j: 64: 1", -- wooddoorblock "k: 64: 8", -- wooddoorblock "l: 64: 9", -- wooddoorblock "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "mmmmmaammmmmmm", -- 0 "mmmmmbbmmmmmmm", -- 1 "mmmmmbbmmmmmmm", -- 2 "mmmmbbbbmmmmmm", -- 3 "mmmbbccbbmmmmm", -- 4 "mmbbccccbbmmmm", -- 5 "mbbccccccbbmmm", -- 6 "mbccccccccbbba", -- 7 "mbccccccccbbba", -- 8 "mbbccccccbbmmm", -- 9 "mmbbccccbbmmmm", -- 10 "mmmbbccbbmmmmm", -- 11 "mmmmbbbbmmmmmm", -- 12 "mmmmmbbmmmmmmm", -- 13 "mmmmmbbmmmmmmm", -- 14 "mmmmmaammmmmmm", -- 15 -- Level 1 "mmmmaddammmmmm", -- 0 "mmmmb..bmmmmmm", -- 1 "mmmmb..bmmmmmm", -- 2 "mmmbbefbbmmmmm", -- 3 "mmbb....bbmmmm", -- 4 "mbb......bbmmm", -- 5 "mb........bbba", -- 6 "be........g..h", -- 7 "be........i..h", -- 8 "mb........bbba", -- 9 "mbb......bbmmm", -- 10 "mmbb....bbmmmm", -- 11 "mmmbbefbbmmmmm", -- 12 "mmmmb..bmmmmmm", -- 13 "mmmmb..bmmmmmm", -- 14 "mmmmajjammmmmm", -- 15 -- Level 2 "mmmmaklammmmmm", -- 0 "mmmmb..bmmmmmm", -- 1 "mmmmc..cmmmmmm", -- 2 "mmmcc..ccmmmmm", -- 3 "mmcc....ccmmmm", -- 4 "mcc......ccmmm", -- 5 "mc........ccba", -- 6 "c............k", -- 7 "c............l", -- 8 "mc........ccba", -- 9 "mcc......ccmmm", -- 10 "mmcc....ccmmmm", -- 11 "mmmcc..ccmmmmm", -- 12 "mmmmc..cmmmmmm", -- 13 "mmmmb..bmmmmmm", -- 14 "mmmmalkammmmmm", -- 15 -- Level 3 "mmmmaaaammmmmm", -- 0 "mmmmbbbbmmmmmm", -- 1 "mmmmccccmmmmmm", -- 2 "mmmcc..ccmmmmm", -- 3 "mmcc....ccmmmm", -- 4 "mcc......ccmmm", -- 5 "mc........ccba", -- 6 "c..........cba", -- 7 "c..........cba", -- 8 "mc........ccba", -- 9 "mcc......ccmmm", -- 10 "mmcc....ccmmmm", -- 11 "mmmcc..ccmmmmm", -- 12 "mmmmccccmmmmmm", -- 13 "mmmmbbbbmmmmmm", -- 14 "mmmmaaaammmmmm", -- 15 -- Level 4 "mmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmm", -- 2 "mmmmmccmmmmmmm", -- 3 "mmmmc..cmmmmmm", -- 4 "mmmc....cmmmmm", -- 5 "mmc......cmmmm", -- 6 "mc........cmmm", -- 7 "mc........cmmm", -- 8 "mmc......cmmmm", -- 9 "mmmc....cmmmmm", -- 10 "mmmmc..cmmmmmm", -- 11 "mmmmmccmmmmmmm", -- 12 "mmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmm", -- 14 "mmmmmmmmmmmmmm", -- 15 -- Level 5 "mmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmm", -- 3 "mmmmmccmmmmmmm", -- 4 "mmmmc..cmmmmmm", -- 5 "mmmc....cmmmmm", -- 6 "mmc......cmmmm", -- 7 "mmc......cmmmm", -- 8 "mmmc....cmmmmm", -- 9 "mmmmc..cmmmmmm", -- 10 "mmmmmccmmmmmmm", -- 11 "mmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmm", -- 14 "mmmmmmmmmmmmmm", -- 15 -- Level 6 "mmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmm", -- 4 "mmmmmccmmmmmmm", -- 5 "mmmmccccmmmmmm", -- 6 "mmmccccccmmmmm", -- 7 "mmmccccccmmmmm", -- 8 "mmmmccccmmmmmm", -- 9 "mmmmmccmmmmmmm", -- 10 "mmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmm", -- 14 "mmmmmmmmmmmmmm", -- 15 }, }, -- ViewingTee { OriginData = { ExportName = "ViewingCorner", Name = "Water 40", GalleryName = "Water", GalleryIndex = "40", ID = "613", CreatorName = "LO1ZB", }, Size = { x = 14, y = 7, z = 14, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 13, MaxY = 6, MaxZ = 13, }, Connectors = { { Type = 1, RelX = 13, RelY = 1, RelZ = 6, Direction = 5, -- X+ }, { Type = -1, RelX = 13, RelY = 1, RelZ = 5, Direction = 5, -- X+ }, { Type = 1, RelX = 5, RelY = 1, RelZ = 13, Direction = 3, -- Z+ }, { Type = -1, RelX = 6, RelY = 1, RelZ = 13, Direction = 3, -- Z+ }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "None", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a: 5: 0", -- planks "b: 20: 0", -- glass "c: 5: 5", -- planks "d: 76: 3", -- redstonetorchon "e: 76: 1", -- redstonetorchon "f: 64: 0", -- wooddoorblock "g: 76: 4", -- redstonetorchon "h: 76: 2", -- redstonetorchon "i: 64: 1", -- wooddoorblock "j: 64: 8", -- wooddoorblock "k: 64: 9", -- wooddoorblock "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "mmmmmmmmmmmmmm", -- 0 "mmmmaaaammmmmm", -- 1 "mmmaabbaammmmm", -- 2 "mmaabbbbaammmm", -- 3 "maabbbbbbaammm", -- 4 "mabbbbbbbbaaac", -- 5 "mabbbbbbbbaaac", -- 6 "maabbbbbbaammm", -- 7 "mmaabbbbaammmm", -- 8 "mmmaabbaammmmm", -- 9 "mmmmaaaammmmmm", -- 10 "mmmmmaammmmmmm", -- 11 "mmmmmaammmmmmm", -- 12 "mmmmmccmmmmmmm", -- 13 -- Level 1 "mmmmmaammmmmmm", -- 0 "mmmaaddaammmmm", -- 1 "mmaa....aammmm", -- 2 "maa......aammm", -- 3 "ma........aaac", -- 4 "ae........d..f", -- 5 "ae........g..f", -- 6 "ma........aaac", -- 7 "maa......aammm", -- 8 "mmaa....aammmm", -- 9 "mmmaaehaammmmm", -- 10 "mmmma..ammmmmm", -- 11 "mmmma..ammmmmm", -- 12 "mmmmciicmmmmmm", -- 13 -- Level 2 "mmmmmbbmmmmmmm", -- 0 "mmmbb..bbmmmmm", -- 1 "mmbb....bbmmmm", -- 2 "mbb......bbmmm", -- 3 "mb........bbac", -- 4 "b............j", -- 5 "b............k", -- 6 "mb........bbac", -- 7 "mbb......bbmmm", -- 8 "mmbb....bbmmmm", -- 9 "mmmbb..bbmmmmm", -- 10 "mmmmb..bmmmmmm", -- 11 "mmmma..ammmmmm", -- 12 "mmmmckjcmmmmmm", -- 13 -- Level 3 "mmmmmbbmmmmmmm", -- 0 "mmmbb..bbmmmmm", -- 1 "mmbb....bbmmmm", -- 2 "mbb......bbmmm", -- 3 "mb........bbac", -- 4 "b..........bac", -- 5 "b..........bac", -- 6 "mb........bbac", -- 7 "mbb......bbmmm", -- 8 "mmbb....bbmmmm", -- 9 "mmmbb..bbmmmmm", -- 10 "mmmmbbbbmmmmmm", -- 11 "mmmmaaaammmmmm", -- 12 "mmmmccccmmmmmm", -- 13 -- Level 4 "mmmmmmmmmmmmmm", -- 0 "mmmmmbbmmmmmmm", -- 1 "mmmmb..bmmmmmm", -- 2 "mmmb....bmmmmm", -- 3 "mmb......bmmmm", -- 4 "mb........bmmm", -- 5 "mb........bmmm", -- 6 "mmb......bmmmm", -- 7 "mmmb....bmmmmm", -- 8 "mmmmb..bmmmmmm", -- 9 "mmmmmbbmmmmmmm", -- 10 "mmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmm", -- 13 -- Level 5 "mmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmm", -- 1 "mmmmmbbmmmmmmm", -- 2 "mmmmb..bmmmmmm", -- 3 "mmmb....bmmmmm", -- 4 "mmb......bmmmm", -- 5 "mmb......bmmmm", -- 6 "mmmb....bmmmmm", -- 7 "mmmmb..bmmmmmm", -- 8 "mmmmmbbmmmmmmm", -- 9 "mmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmm", -- 13 -- Level 6 "mmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmm", -- 2 "mmmmmbbmmmmmmm", -- 3 "mmmmbbbbmmmmmm", -- 4 "mmmbbbbbbmmmmm", -- 5 "mmmbbbbbbmmmmm", -- 6 "mmmmbbbbmmmmmm", -- 7 "mmmmmbbmmmmmmm", -- 8 "mmmmmmmmmmmmmm", -- 9 "mmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmm", -- 13 }, }, -- ViewingCorner { OriginData = { ExportName = "ViewingEnd", Name = "Water 41", GalleryName = "Water", GalleryIndex = "41", ID = "614", CreatorName = "LO1ZB", }, Size = { x = 14, y = 7, z = 12, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 13, MaxY = 6, MaxZ = 11, }, Connectors = { { Type = 1, RelX = 13, RelY = 1, RelZ = 6, Direction = 5, -- X+ }, { Type = -1, RelX = 13, RelY = 1, RelZ = 5, Direction = 5, -- X+ }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "200", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "None", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a: 5: 0", -- planks "b: 20: 0", -- glass "c: 5: 5", -- planks "d: 76: 3", -- redstonetorchon "e: 76: 1", -- redstonetorchon "f: 64: 0", -- wooddoorblock "g: 76: 4", -- redstonetorchon "h: 64: 8", -- wooddoorblock "i: 64: 9", -- wooddoorblock "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "mmmmmmmmmmmmmm", -- 0 "mmmmaaaammmmmm", -- 1 "mmmaabbaammmmm", -- 2 "mmaabbbbaammmm", -- 3 "maabbbbbbaammm", -- 4 "mabbbbbbbbaaac", -- 5 "mabbbbbbbbaaac", -- 6 "maabbbbbbaammm", -- 7 "mmaabbbbaammmm", -- 8 "mmmaabbaammmmm", -- 9 "mmmmaaaammmmmm", -- 10 "mmmmmmmmmmmmmm", -- 11 -- Level 1 "mmmmmaammmmmmm", -- 0 "mmmaaddaammmmm", -- 1 "mmaa....aammmm", -- 2 "maa......aammm", -- 3 "ma........aaac", -- 4 "ae........d..f", -- 5 "ae........g..f", -- 6 "ma........aaac", -- 7 "maa......aammm", -- 8 "mmaa....aammmm", -- 9 "mmmaaggaammmmm", -- 10 "mmmmmaammmmmmm", -- 11 -- Level 2 "mmmmmbbmmmmmmm", -- 0 "mmmbb..bbmmmmm", -- 1 "mmbb....bbmmmm", -- 2 "mbb......bbmmm", -- 3 "mb........bbac", -- 4 "b............h", -- 5 "b............i", -- 6 "mb........bbac", -- 7 "mbb......bbmmm", -- 8 "mmbb....bbmmmm", -- 9 "mmmbb..bbmmmmm", -- 10 "mmmmmbbmmmmmmm", -- 11 -- Level 3 "mmmmmbbmmmmmmm", -- 0 "mmmbb..bbmmmmm", -- 1 "mmbb....bbmmmm", -- 2 "mbb......bbmmm", -- 3 "mb........bbac", -- 4 "b..........bac", -- 5 "b..........bac", -- 6 "mb........bbac", -- 7 "mbb......bbmmm", -- 8 "mmbb....bbmmmm", -- 9 "mmmbb..bbmmmmm", -- 10 "mmmmmbbmmmmmmm", -- 11 -- Level 4 "mmmmmmmmmmmmmm", -- 0 "mmmmmbbmmmmmmm", -- 1 "mmmmb..bmmmmmm", -- 2 "mmmb....bmmmmm", -- 3 "mmb......bmmmm", -- 4 "mb........bmmm", -- 5 "mb........bmmm", -- 6 "mmb......bmmmm", -- 7 "mmmb....bmmmmm", -- 8 "mmmmb..bmmmmmm", -- 9 "mmmmmbbmmmmmmm", -- 10 "mmmmmmmmmmmmmm", -- 11 -- Level 5 "mmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmm", -- 1 "mmmmmbbmmmmmmm", -- 2 "mmmmb..bmmmmmm", -- 3 "mmmb....bmmmmm", -- 4 "mmb......bmmmm", -- 5 "mmb......bmmmm", -- 6 "mmmb....bmmmmm", -- 7 "mmmmb..bmmmmmm", -- 8 "mmmmmbbmmmmmmm", -- 9 "mmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmm", -- 11 -- Level 6 "mmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmm", -- 2 "mmmmmbbmmmmmmm", -- 3 "mmmmbbbbmmmmmm", -- 4 "mmmbbbbbbmmmmm", -- 5 "mmmbbbbbbmmmmm", -- 6 "mmmmbbbbmmmmmm", -- 7 "mmmmmbbmmmmmmm", -- 8 "mmmmmmmmmmmmmm", -- 9 "mmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmm", -- 11 }, }, -- ViewingEnd { OriginData = { ExportName = "ViewingCorridorBulge", Name = "Water 42", GalleryName = "Water", GalleryIndex = "42", ID = "615", CreatorName = "LO1ZB", }, Size = { x = 12, y = 8, z = 16, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 11, MaxY = 7, MaxZ = 15, }, Connectors = { { Type = 1, RelX = 6, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, { Type = -1, RelX = 5, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, { Type = 1, RelX = 5, RelY = 1, RelZ = 15, Direction = 3, -- Z+ }, { Type = -1, RelX = 6, RelY = 1, RelZ = 15, Direction = 3, -- Z+ }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "None", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a: 5: 5", -- planks "b: 5: 0", -- planks "c: 20: 0", -- glass "d: 64: 3", -- wooddoorblock "e: 76: 1", -- redstonetorchon "f: 76: 2", -- redstonetorchon "g: 64: 1", -- wooddoorblock "h: 64: 8", -- wooddoorblock "i: 64: 9", -- wooddoorblock "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "mmmmmaammmmm", -- 0 "mmmmmbbmmmmm", -- 1 "mmmmmbbmmmmm", -- 2 "mmmmbbbbmmmm", -- 3 "mmmbbccbbmmm", -- 4 "mmbbccccbbmm", -- 5 "mbbccccccbbm", -- 6 "mbccccccccbm", -- 7 "mbccccccccbm", -- 8 "mbbccccccbbm", -- 9 "mmbbccccbbmm", -- 10 "mmmbbccbbmmm", -- 11 "mmmmbbbbmmmm", -- 12 "mmmmmbbmmmmm", -- 13 "mmmmmbbmmmmm", -- 14 "mmmmmaammmmm", -- 15 -- Level 1 "mmmmaddammmm", -- 0 "mmmmb..bmmmm", -- 1 "mmmmb..bmmmm", -- 2 "mmmbbefbbmmm", -- 3 "mmbb....bbmm", -- 4 "mbb......bbm", -- 5 "mb........bm", -- 6 "be........fb", -- 7 "be........fb", -- 8 "mb........bm", -- 9 "mbb......bbm", -- 10 "mmbb....bbmm", -- 11 "mmmbbefbbmmm", -- 12 "mmmmb..bmmmm", -- 13 "mmmmb..bmmmm", -- 14 "mmmmaggammmm", -- 15 -- Level 2 "mmmmahiammmm", -- 0 "mmmmb..bmmmm", -- 1 "mmmmc..cmmmm", -- 2 "mmmcc..ccmmm", -- 3 "mmcc....ccmm", -- 4 "mcc......ccm", -- 5 "mc........cm", -- 6 "c..........c", -- 7 "c..........c", -- 8 "mc........cm", -- 9 "mcc......ccm", -- 10 "mmcc....ccmm", -- 11 "mmmcc..ccmmm", -- 12 "mmmmc..cmmmm", -- 13 "mmmmb..bmmmm", -- 14 "mmmmaihammmm", -- 15 -- Level 3 "mmmmaaaammmm", -- 0 "mmmmbbbbmmmm", -- 1 "mmmmccccmmmm", -- 2 "mmmcc..ccmmm", -- 3 "mmcc....ccmm", -- 4 "mcc......ccm", -- 5 "mc........cm", -- 6 "c..........c", -- 7 "c..........c", -- 8 "mc........cm", -- 9 "mcc......ccm", -- 10 "mmcc....ccmm", -- 11 "mmmcc..ccmmm", -- 12 "mmmmccccmmmm", -- 13 "mmmmbbbbmmmm", -- 14 "mmmmaaaammmm", -- 15 -- Level 4 "mmmmmmmmmmmm", -- 0 "mmmmmmmmmmmm", -- 1 "mmmmmmmmmmmm", -- 2 "mmmmmccmmmmm", -- 3 "mmmmc..cmmmm", -- 4 "mmmc....cmmm", -- 5 "mmc......cmm", -- 6 "mc........cm", -- 7 "mc........cm", -- 8 "mmc......cmm", -- 9 "mmmc....cmmm", -- 10 "mmmmc..cmmmm", -- 11 "mmmmmccmmmmm", -- 12 "mmmmmmmmmmmm", -- 13 "mmmmmmmmmmmm", -- 14 "mmmmmmmmmmmm", -- 15 -- Level 5 "mmmmmmmmmmmm", -- 0 "mmmmmmmmmmmm", -- 1 "mmmmmmmmmmmm", -- 2 "mmmmmmmmmmmm", -- 3 "mmmmmccmmmmm", -- 4 "mmmmc..cmmmm", -- 5 "mmmc....cmmm", -- 6 "mmc......cmm", -- 7 "mmc......cmm", -- 8 "mmmc....cmmm", -- 9 "mmmmc..cmmmm", -- 10 "mmmmmccmmmmm", -- 11 "mmmmmmmmmmmm", -- 12 "mmmmmmmmmmmm", -- 13 "mmmmmmmmmmmm", -- 14 "mmmmmmmmmmmm", -- 15 -- Level 6 "mmmmmmmmmmmm", -- 0 "mmmmmmmmmmmm", -- 1 "mmmmmmmmmmmm", -- 2 "mmmmmmmmmmmm", -- 3 "mmmmmmmmmmmm", -- 4 "mmmmmccmmmmm", -- 5 "mmmmccccmmmm", -- 6 "mmmccccccmmm", -- 7 "mmmccccccmmm", -- 8 "mmmmccccmmmm", -- 9 "mmmmmccmmmmm", -- 10 "mmmmmmmmmmmm", -- 11 "mmmmmmmmmmmm", -- 12 "mmmmmmmmmmmm", -- 13 "mmmmmmmmmmmm", -- 14 "mmmmmmmmmmmm", -- 15 -- Level 7 "mmmmmmmmmmmm", -- 0 "mmmmmmmmmmmm", -- 1 "mmmmmmmmmmmm", -- 2 "mmmmmmmmmmmm", -- 3 "mmmmmmmmmmmm", -- 4 "mmmmmmmmmmmm", -- 5 "mmmmmmmmmmmm", -- 6 "mmmmmmmmmmmm", -- 7 "mmmmmmmmmmmm", -- 8 "mmmmmmmmmmmm", -- 9 "mmmmmmmmmmmm", -- 10 "mmmmmmmmmmmm", -- 11 "mmmmmmmmmmmm", -- 12 "mmmmmmmmmmmm", -- 13 "mmmmmmmmmmmm", -- 14 "mmmmmmmmmmmm", -- 15 }, }, -- ViewingCorridorBulge { OriginData = { ExportName = "BrokenRoom", Name = "Water 49", GalleryName = "Water", GalleryIndex = "49", ID = "680", CreatorName = "STR_Warrior", }, Size = { x = 14, y = 7, z = 12, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 13, MaxY = 6, MaxZ = 11, }, Connectors = { { Type = 1, RelX = 13, RelY = 1, RelZ = 6, Direction = 5, -- X+ }, { Type = -1, RelX = 13, RelY = 1, RelZ = 5, Direction = 5, -- X+ }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "None", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a: 5: 0", -- planks "b: 20: 0", -- glass "c: 5: 5", -- planks "d: 8: 0", -- water "e: 64: 0", -- wooddoorblock "f: 64: 8", -- wooddoorblock "g: 64: 9", -- wooddoorblock "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "mmmmmmmmmmmmmm", -- 0 "mmmmaaaammmmmm", -- 1 "mmmaabbaammmmm", -- 2 "mmaabbbbaammmm", -- 3 "maabbbbbbaammm", -- 4 "mabbbbbbbbaaac", -- 5 "mabbbbbbbbaaac", -- 6 "maabbbbbbaammm", -- 7 "mmaabbbbaammmm", -- 8 "mmmaabbaammmmm", -- 9 "mmmmaaaammmmmm", -- 10 "mmmmmmmmmmmmmm", -- 11 -- Level 1 "mmmmmaammmmmmm", -- 0 "mmmaaddaammmmm", -- 1 "mmaaddddaammmm", -- 2 "maaddddddaammm", -- 3 "maddddddddaaac", -- 4 "adddddddddddde", -- 5 "adddddddddddde", -- 6 "maddddddddaaac", -- 7 "maaddddddaammm", -- 8 "mmaaddddaammmm", -- 9 "mmmaaddaammmmm", -- 10 "mmmmmaammmmmmm", -- 11 -- Level 2 "mmmmmbbmmmmmmm", -- 0 "mmmbb..bbmmmmm", -- 1 "mmbb....bbmmmm", -- 2 "mbb......bbmmm", -- 3 "mb........bbac", -- 4 "b............f", -- 5 "b............g", -- 6 "mb........bbac", -- 7 "mbb......bbmmm", -- 8 "mmbb....bbmmmm", -- 9 "mmmbb..bbmmmmm", -- 10 "mmmmmbbmmmmmmm", -- 11 -- Level 3 "mmmmmbbmmmmmmm", -- 0 "mmmbb..bbmmmmm", -- 1 "mmbb....bbmmmm", -- 2 "mbb......bbmmm", -- 3 "mb........bbac", -- 4 "b..........bac", -- 5 "b..........bac", -- 6 "mb........bbac", -- 7 "mbb......bbmmm", -- 8 "mmbb....bbmmmm", -- 9 "mmmbb..bbmmmmm", -- 10 "mmmmmbbmmmmmmm", -- 11 -- Level 4 "mmmmmmmmmmmmmm", -- 0 "mmmmm.bmmmmmmm", -- 1 "mmmmb..bmmmmmm", -- 2 "mmmb....bmmmmm", -- 3 "mmb......bmmmm", -- 4 "m.........bmmm", -- 5 "mb........bmmm", -- 6 "mmb......bmmmm", -- 7 "mmm.....bmmmmm", -- 8 "mmmmb..bmmmmmm", -- 9 "mmmmmbbmmmmmmm", -- 10 "mmmmmmmmmmmmmm", -- 11 -- Level 5 "mmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmm", -- 1 "mmmmmbbmmmmmmm", -- 2 "mmmm....mmmmmm", -- 3 "mmmb....bmmmmm", -- 4 "mmb......bmmmm", -- 5 "mmb......bmmmm", -- 6 "mmmb.....mmmmm", -- 7 "mmmmb..bmmmmmm", -- 8 "mmmmmbbmmmmmmm", -- 9 "mmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmm", -- 11 -- Level 6 "mmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmm", -- 2 "mmmmmbbmmmmmmm", -- 3 "mmmmbbbbmmmmmm", -- 4 "mmmbbbbbbmmmmm", -- 5 "mmmbb.bbbmmmmm", -- 6 "mmmmbbbbmmmmmm", -- 7 "mmmmmbbmmmmmmm", -- 8 "mmmmmmmmmmmmmm", -- 9 "mmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmm", -- 11 }, }, -- BrokenRoom { OriginData = { ExportName = "WaterfallRoom", Name = "Water 50", GalleryName = "Water", GalleryIndex = "50", ID = "681", CreatorName = "Aloe_vera", }, Size = { x = 16, y = 7, z = 16, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 15, MaxY = 6, MaxZ = 15, }, Connectors = { { Type = 1, RelX = 15, RelY = 1, RelZ = 8, Direction = 5, -- X+ }, { Type = -1, RelX = 15, RelY = 1, RelZ = 7, Direction = 5, -- X+ }, { Type = 1, RelX = 8, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, { Type = -1, RelX = 7, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, { Type = 1, RelX = 0, RelY = 1, RelZ = 7, Direction = 4, -- X- }, { Type = -1, RelX = 0, RelY = 1, RelZ = 8, Direction = 4, -- X- }, { Type = 1, RelX = 7, RelY = 1, RelZ = 15, Direction = 3, -- Z+ }, { Type = -1, RelX = 8, RelY = 1, RelZ = 15, Direction = 3, -- Z+ }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "5", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "None", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a: 5: 5", -- planks "b: 5: 0", -- planks "c: 20: 0", -- glass "d: 64: 3", -- wooddoorblock "e: 76: 1", -- redstonetorchon "f: 76: 2", -- redstonetorchon "g: 64: 2", -- wooddoorblock "h: 76: 3", -- redstonetorchon "i: 64: 0", -- wooddoorblock "j: 76: 4", -- redstonetorchon "k: 64: 1", -- wooddoorblock "l: 64: 8", -- wooddoorblock "m: 19: 0", -- sponge "n: 64: 9", -- wooddoorblock }, BlockData = { -- Level 0 "mmmmmmmaammmmmmm", -- 0 "mmmmmmmbbmmmmmmm", -- 1 "mmmmmmmbbmmmmmmm", -- 2 "mmmmmmbbbbmmmmmm", -- 3 "mmmmmbbccbbmmmmm", -- 4 "mmmmbbccccbbmmmm", -- 5 "mmmbbccccccbbmmm", -- 6 "abbbcccmmcccbbba", -- 7 "abbbcccmmcccbbba", -- 8 "mmmbbccccccbbmmm", -- 9 "mmmmbbccccbbmmmm", -- 10 "mmmmmbbccbbmmmmm", -- 11 "mmmmmmbbbbmmmmmm", -- 12 "mmmmmmmbbmmmmmmm", -- 13 "mmmmmmmbbmmmmmmm", -- 14 "mmmmmmmaammmmmmm", -- 15 -- Level 1 "mmmmmmaddammmmmm", -- 0 "mmmmmmb..bmmmmmm", -- 1 "mmmmmmb..bmmmmmm", -- 2 "mmmmmbbefbbmmmmm", -- 3 "mmmmbb....bbmmmm", -- 4 "mmmbb......bbmmm", -- 5 "abbb...cc...bbba", -- 6 "g..h..c..c..h..i", -- 7 "g..j..c..c..j..i", -- 8 "abbb...cc...bbba", -- 9 "mmmbb......bbmmm", -- 10 "mmmmbb....bbmmmm", -- 11 "mmmmmbbefbbmmmmm", -- 12 "mmmmmmb..bmmmmmm", -- 13 "mmmmmmb..bmmmmmm", -- 14 "mmmmmmakkammmmmm", -- 15 -- Level 2 "mmmmmmalnammmmmm", -- 0 "mmmmmmb..bmmmmmm", -- 1 "mmmmmmc..cmmmmmm", -- 2 "mmmmmcc..ccmmmmm", -- 3 "mmmmcc....ccmmmm", -- 4 "mmmcc......ccmmm", -- 5 "abcc........ccba", -- 6 "n..............l", -- 7 "l..............n", -- 8 "abcc........ccba", -- 9 "mmmcc......ccmmm", -- 10 "mmmmcc....ccmmmm", -- 11 "mmmmmcc..ccmmmmm", -- 12 "mmmmmmc..cmmmmmm", -- 13 "mmmmmmb..bmmmmmm", -- 14 "mmmmmmanlammmmmm", -- 15 -- Level 3 "mmmmmmaaaammmmmm", -- 0 "mmmmmmbbbbmmmmmm", -- 1 "mmmmmmccccmmmmmm", -- 2 "mmmmmcc..ccmmmmm", -- 3 "mmmmcc....ccmmmm", -- 4 "mmmcc......ccmmm", -- 5 "abcc........ccba", -- 6 "abc..........cba", -- 7 "abc..........cba", -- 8 "abcc........ccba", -- 9 "mmmcc......ccmmm", -- 10 "mmmmcc....ccmmmm", -- 11 "mmmmmcc..ccmmmmm", -- 12 "mmmmmmccccmmmmmm", -- 13 "mmmmmmbbbbmmmmmm", -- 14 "mmmmmmaaaammmmmm", -- 15 -- Level 4 "mmmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmmm", -- 2 "mmmmmmmccmmmmmmm", -- 3 "mmmmm.c..cmmmmmm", -- 4 "mmmmmc....cmmmmm", -- 5 "mmmmc......cmmmm", -- 6 "mmmc........cmmm", -- 7 "mmmc........cmmm", -- 8 "mmmmc......cmmmm", -- 9 "mmmmmc....cmmmmm", -- 10 "mmmmmmc..cmmmmmm", -- 11 "mmmmmmmccmmmmmmm", -- 12 "mmmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmmm", -- 14 "mmmmmmmmmmmmmmmm", -- 15 -- Level 5 "mmmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmmm", -- 3 "mmmmmm.ccmmmmmmm", -- 4 "mmmmmmc..cmmmmmm", -- 5 "mmmmmc....cmmmmm", -- 6 "mmmmc......cmmmm", -- 7 "mmmmc......cmmmm", -- 8 "mmmmmc....cmmmmm", -- 9 "mmmmmmc..cmmmmmm", -- 10 "mmmmmmmccmmmmmmm", -- 11 "mmmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmmm", -- 14 "mmmmmmmmmmmmmmmm", -- 15 -- Level 6 "mmmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmmm", -- 4 "mmmmmmmccmmmmmmm", -- 5 "mmmmmmccccmmmmmm", -- 6 "mmmmmcc..ccmmmmm", -- 7 "mmmmmcc..ccmmmmm", -- 8 "mmmmmmccccmmmmmm", -- 9 "mmmmmmmccmmmmmmm", -- 10 "mmmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmmm", -- 14 "mmmmmmmmmmmmmmmm", -- 15 }, }, -- WaterfallRoom }, -- Pieces } ================================================ FILE: Server/Prefabs/SinglePieceStructures/DesertPyramid.cubeset ================================================ -- DesertPyramid.cubeset -- Defines the prefabs in the group DesertPyramid -- NOTE: This file has been generated automatically by GalExport! -- Any manual changes will be overwritten by the next automatic export! Cubeset = { Metadata = { CubesetFormatVersion = 1, ExportDate = "2020-08-27 10:42:17", ["AllowedBiomes"] = "Desert, DesertM, DesertHills", ["GridSizeX"] = "500", ["GridSizeZ"] = "500", ["IntendedUse"] = "SinglePieceStructures", ["MaxOffsetX"] = "100", ["MaxOffsetZ"] = "100", ["SeedOffset"] = "47260503", }, Pieces = { { OriginData = { ExportName = "DesertPyramid", Name = "DesertPyramid", GalleryName = "Desert", GalleryIndex = "222", ID = "1706", CreatorName = "12xx12", }, Size = { x = 15, y = 23, z = 15, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 14, MaxY = 22, MaxZ = 14, }, StructureBox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 14, MaxY = 22, MaxZ = 14, }, Connectors = { }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "400", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillNonAir", ["IsStarting"] = "1", ["MergeStrategy"] = "msSpongePrint", ["ShouldExpandFloor"] = "1", ["VerticalStrategy"] = "Fixed|51", }, BlockDefinitions = { ".: 0: 0", -- air "a: 46: 0", -- tnt "b: 24: 0", -- sandstone "c: 24: 2", -- sandstone "d: 24: 1", -- sandstone "e: 54: 3", -- chest "f: 54: 5", -- chest "g: 70: 0", -- stonepressureplate "h: 54: 4", -- chest "i: 54: 2", -- chest "j:128: 7", -- sandstonestairs "k:128: 5", -- sandstonestairs "l:128: 4", -- sandstonestairs "m: 19: 0", -- sponge "n:128: 6", -- sandstonestairs "o:159: 1", -- whiteterracotta "p:159:11", -- whiteterracotta "q:128: 3", -- sandstonestairs "r:128: 2", -- sandstonestairs "s:128: 0", -- sandstonestairs "t:128: 1", -- sandstonestairs "u: 44: 9", -- stone_slab "v: 44: 1", -- stone_slab }, BlockData = { -- Level 0 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmmmmmmmmm", -- 5 "mmmmmmaaammmmmm", -- 6 "mmmmmmaaammmmmm", -- 7 "mmmmmmaaammmmmm", -- 8 "mmmmmmmmmmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 1 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmbmmmmmmm", -- 5 "mmmmmmcccmmmmmm", -- 6 "mmmmmbcbcbmmmmm", -- 7 "mmmmmmcccmmmmmm", -- 8 "mmmmmmmbmmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 2 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmbmmmmmmm", -- 4 "mmmmmmdedmmmmmm", -- 5 "mmmmmd...dmmmmm", -- 6 "mmmmbf.g.hbmmmm", -- 7 "mmmmmd...dmmmmm", -- 8 "mmmmmmdidmmmmmm", -- 9 "mmmmmmmbmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 3 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmcjcmmmmmm", -- 5 "mmmmmc...cmmmmm", -- 6 "mmmmmk...lmmmmm", -- 7 "mmmmmc...cmmmmm", -- 8 "mmmmmmcncmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 4 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmdcdmmmmmm", -- 5 "mmmmmd...dmmmmm", -- 6 "mmmmmc...cmmmmm", -- 7 "mmmmmd...dmmmmm", -- 8 "mmmmmmdcdmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 5 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmcccmmmmmm", -- 5 "mmmmmc...cmmmmm", -- 6 "mmmmmc...cmmmmm", -- 7 "mmmmmc...cmmmmm", -- 8 "mmmmmmcccmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 6 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmcdcmmmmmm", -- 5 "mmmmmc...cmmmmm", -- 6 "mmmmmd...dmmmmm", -- 7 "mmmmmc...cmmmmm", -- 8 "mmmmmmcdcmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 7 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmdcdmmmmmm", -- 5 "mmmmmd...dmmmmm", -- 6 "mmmmmc...cmmmmm", -- 7 "mmmmmd...dmmmmm", -- 8 "mmmmmmdcdmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 8 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmbbbmmmmmm", -- 5 "mmmmmb...bmmmmm", -- 6 "mmmmmb...bmmmmm", -- 7 "mmmmmb...bmmmmm", -- 8 "mmmmmmbbbmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 9 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmbbbmmmmmm", -- 5 "mmmmmb...bmmmmm", -- 6 "mmmmmb...bmmmmm", -- 7 "mmmmmb...bmmmmm", -- 8 "mmmmmmbbbmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 10 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmbbbmmmmmm", -- 5 "mmmmmb...bmmmmm", -- 6 "mmmmmb...bmmmmm", -- 7 "mmmmmb...bmmmmm", -- 8 "mmmmmmbbbmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 11 "bbbbbbbbbbbbbbb", -- 0 "bbbbbbbbbbbbbbb", -- 1 "bbbbbbbbbbbbbbb", -- 2 "bbbbbbbbbbbbbbb", -- 3 "bbbbobobbbobbbb", -- 4 "bbbbbobbbobbbbb", -- 5 "bbbbbbobobbbbbb", -- 6 "bbbbbbbpbbbbbbb", -- 7 "bbbbbbobobbbbbb", -- 8 "bbbbbobbbobbbbb", -- 9 "bbbbobobbbobbbb", -- 10 "bbbbbbbbbbbbbbb", -- 11 "bbbbbbbbbbbbbbb", -- 12 "bbbbbbbbbbbbbbb", -- 13 "bbbbbbbbbbbbbbb", -- 14 -- Level 12 "bbbbbbbbbbbbbbb", -- 0 "b.........bbbbb", -- 1 "b.........bq.bb", -- 2 "b.........b..bb", -- 3 "b....r.....b.bb", -- 4 "b...sbt.......b", -- 5 "b....q........b", -- 6 "b..............", -- 7 "b....r........b", -- 8 "b...sbt.......b", -- 9 "b....q.....b.bb", -- 10 "b.........b..bb", -- 11 "b.........br.bb", -- 12 "b.........bbbbb", -- 13 "bbbbbbbbbbbbbbb", -- 14 -- Level 13 "bbbbbbbbbbbbbbb", -- 0 "b.........b.sbb", -- 1 "b.........b..bo", -- 2 "b.........b..bb", -- 3 "b..........b.bb", -- 4 "b....b........b", -- 5 "b.............b", -- 6 "b..............", -- 7 "b.............b", -- 8 "b....b........b", -- 9 "b..........b.bb", -- 10 "b.........b..bb", -- 11 "b.........b..bo", -- 12 "b.........b.sbb", -- 13 "bbbbbbbbbbbbbbb", -- 14 -- Level 14 "mmmmmmmmmmbbbbb", -- 0 "mbbbbbbbbbb...b", -- 1 "mbu......ub..ro", -- 2 "mb........b.ubb", -- 3 "mb.........bbbb", -- 4 "mb...b......ubv", -- 5 "mb..........ubb", -- 6 "mb...........ub", -- 7 "mb..........ubb", -- 8 "mb...b......ubv", -- 9 "mb.........bbbb", -- 10 "mb........b.ubb", -- 11 "mbu......ub..qo", -- 12 "mbbbbbbbbbb...b", -- 13 "mmmmmmmmmmbbbbb", -- 14 -- Level 15 "mmmmmmmmmmbbbbb", -- 0 "mmmmmmmmmmb...b", -- 1 "mmbbbbbbbbbb..o", -- 2 "mmbbbbbbbbbbt.b", -- 3 "mmbbbbbbbbbbbbb", -- 4 "mmbbbbbbbbbbbmm", -- 5 "mmbbbb...bbbbvm", -- 6 "mmbbbb...bbbbbv", -- 7 "mmbbbb...bbbbvm", -- 8 "mmbbbbbbbbbbbmm", -- 9 "mmbbbbbbbbbbbbb", -- 10 "mmbbbbbbbbbbt.b", -- 11 "mmbbbbbbbbbb..o", -- 12 "mmmmmmmmmmb...b", -- 13 "mmmmmmmmmmbbbbb", -- 14 -- Level 16 "mmmmmmmmmmbbbbb", -- 0 "mmmmmmmmmmb...b", -- 1 "mmmmmmmmmm....o", -- 2 "mmmbbbb.bbb...b", -- 3 "mmmbu.....ubbbb", -- 4 "mmmb.b.....bmmm", -- 5 "mmmb.......bmmm", -- 6 "mmmb.......bvmm", -- 7 "mmmb.......bmmm", -- 8 "mmmb.b.....bmmm", -- 9 "mmmbu.....ubbbb", -- 10 "mmmbbbb.bbb...b", -- 11 "mmmmmmmmmm....o", -- 12 "mmmmmmmmmmb...b", -- 13 "mmmmmmmmmmbbbbb", -- 14 -- Level 17 "mmmmmmmmmmbbbbb", -- 0 "mmmmmmmmmmb...b", -- 1 "mmmmmmmmmm....o", -- 2 "mmmmmmbmbmb...b", -- 3 "mmmmbbb.bbbbbbb", -- 4 "mmmmbb....bmmmm", -- 5 "mmmmb.....bmmmm", -- 6 "mmmmb.....bmmmm", -- 7 "mmmmb.....bmmmm", -- 8 "mmmmbb....bmmmm", -- 9 "mmmmbbb.bbbbbbb", -- 10 "mmmmmmbmbmb...b", -- 11 "mmmmmmmmmm....o", -- 12 "mmmmmmmmmmb...b", -- 13 "mmmmmmmmmmbbbbb", -- 14 -- Level 18 "mmmmmmmmmmbbbbb", -- 0 "mmmmmmmmmmb...o", -- 1 "mmmmmmmmmmb...o", -- 2 "mmmmmmmvmmb...o", -- 3 "mmmmmmvbvmbbbbb", -- 4 "mmmmmbbbbbmmmmm", -- 5 "mmmmmbu.ubmmmmm", -- 6 "mmmmmb...bmmmmm", -- 7 "mmmmmbu.ubmmmmm", -- 8 "mmmmmbbbbbmmmmm", -- 9 "mmmmmmvbvmbbbbb", -- 10 "mmmmmmmvmmb...o", -- 11 "mmmmmmmmmmb...o", -- 12 "mmmmmmmmmmb...o", -- 13 "mmmmmmmmmmbbbbb", -- 14 -- Level 19 "mmmmmmmmmmbbbbb", -- 0 "mmmmmmmmmmb...b", -- 1 "mmmmmmmmmmb...o", -- 2 "mmmmmmmmmmb...b", -- 3 "mmmmmmmmmmbbbbb", -- 4 "mmmmmmmmmmmmmmm", -- 5 "mmmmmmbbbmmmmmm", -- 6 "mmmmmmbbbmmmmmm", -- 7 "mmmmmmbbbmmmmmm", -- 8 "mmmmmmmmmmmmmmm", -- 9 "mmmmmmmmmmbbbbb", -- 10 "mmmmmmmmmmb...b", -- 11 "mmmmmmmmmmb...o", -- 12 "mmmmmmmmmmb...b", -- 13 "mmmmmmmmmmbbbbb", -- 14 -- Level 20 "mmmmmmmmmmbbbbb", -- 0 "mmmmmmmmmmb...b", -- 1 "mmmmmmmmmmb...b", -- 2 "mmmmmmmmmmb...b", -- 3 "mmmmmmmmmmbbbbb", -- 4 "mmmmmmmmmmmmmmm", -- 5 "mmmmmmmmmmmmmmm", -- 6 "mmmmmmmbmmmmmmm", -- 7 "mmmmmmmmmmmmmmm", -- 8 "mmmmmmmmmmmmmmm", -- 9 "mmmmmmmmmmbbbbb", -- 10 "mmmmmmmmmmb...b", -- 11 "mmmmmmmmmmb...b", -- 12 "mmmmmmmmmmb...b", -- 13 "mmmmmmmmmmbbbbb", -- 14 -- Level 21 "mmmmmmmmmmvrvrv", -- 0 "mmmmmmmmmmsbbbt", -- 1 "mmmmmmmmmmvbbbv", -- 2 "mmmmmmmmmmsbbbt", -- 3 "mmmmmmmmmmvqvqv", -- 4 "mmmmmmmmmmmmmmm", -- 5 "mmmmmmmmmmmmmmm", -- 6 "mmmmmmmmmmmmmmm", -- 7 "mmmmmmmmmmmmmmm", -- 8 "mmmmmmmmmmmmmmm", -- 9 "mmmmmmmmmmvrvrv", -- 10 "mmmmmmmmmmsbbbt", -- 11 "mmmmmmmmmmvbbbv", -- 12 "mmmmmmmmmmsbbbt", -- 13 "mmmmmmmmmmvqvqv", -- 14 -- Level 22 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmvmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmmmmmmmmm", -- 5 "mmmmmmmmmmmmmmm", -- 6 "mmmmmmmmmmmmmmm", -- 7 "mmmmmmmmmmmmmmm", -- 8 "mmmmmmmmmmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmvmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 }, }, -- DesertPyramid { OriginData = { ExportName = "SandyDesertPyramid", Name = "SandyDesertPyramid", GalleryName = "Desert", GalleryIndex = "223", ID = "1707", CreatorName = "12xx12", }, Size = { x = 15, y = 23, z = 15, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 14, MaxY = 22, MaxZ = 14, }, StructureBox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 14, MaxY = 22, MaxZ = 14, }, Connectors = { }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillNonAir", ["IsStarting"] = "1", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", ["ShouldExpandFloor"] = "1", ["VerticalStrategy"] = "Fixed|51", }, BlockDefinitions = { ".: 0: 0", -- air "a: 46: 0", -- tnt "b: 24: 0", -- sandstone "c: 24: 2", -- sandstone "d: 54: 3", -- chest "e: 54: 5", -- chest "f: 70: 0", -- stonepressureplate "g: 54: 4", -- chest "h: 54: 2", -- chest "i:128: 7", -- sandstonestairs "j:128: 5", -- sandstonestairs "k:128: 4", -- sandstonestairs "l:128: 6", -- sandstonestairs "m: 19: 0", -- sponge "n: 24: 1", -- sandstone "o:159: 1", -- whiteterracotta "p:159:11", -- whiteterracotta "q:128: 3", -- sandstonestairs "r: 12: 0", -- sand "s:128: 2", -- sandstonestairs "t:128: 0", -- sandstonestairs "u:128: 1", -- sandstonestairs "v: 44: 9", -- stone_slab "w: 44: 1", -- stone_slab }, BlockData = { -- Level 0 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmmmmmmmmm", -- 5 "mmmmmmaaammmmmm", -- 6 "mmmmmmaaammmmmm", -- 7 "mmmmmmaaammmmmm", -- 8 "mmmmmmmmmmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 1 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmbmmmmmmm", -- 5 "mmmmmmcccmmmmmm", -- 6 "mmmmmbcbcbmmmmm", -- 7 "mmmmmmcccmmmmmm", -- 8 "mmmmmmmbmmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 2 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmbmmmmmmm", -- 4 "mmmmmmbdbmmmmmm", -- 5 "mmmmmb...bmmmmm", -- 6 "mmmmbe.f.gbmmmm", -- 7 "mmmmmb...bmmmmm", -- 8 "mmmmmmbhbmmmmmm", -- 9 "mmmmmmmbmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 3 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmbibmmmmmm", -- 5 "mmmmmb...bmmmmm", -- 6 "mmmmmj...kmmmmm", -- 7 "mmmmmb...bmmmmm", -- 8 "mmmmmmblbmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 4 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmnbnmmmmmm", -- 5 "mmmmmn...nmmmmm", -- 6 "mmmmmb...bmmmmm", -- 7 "mmmmmn...nmmmmm", -- 8 "mmmmmmnbnmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 5 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmcccmmmmmm", -- 5 "mmmmmc...cmmmmm", -- 6 "mmmmmc...cmmmmm", -- 7 "mmmmmc...cmmmmm", -- 8 "mmmmmmcccmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 6 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmcncmmmmmm", -- 5 "mmmmmc...cmmmmm", -- 6 "mmmmmn...nmmmmm", -- 7 "mmmmmc...cmmmmm", -- 8 "mmmmmmcncmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 7 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmncnmmmmmm", -- 5 "mmmmmn...nmmmmm", -- 6 "mmmmmc...cmmmmm", -- 7 "mmmmmn...nmmmmm", -- 8 "mmmmmmncnmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 8 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmbbbmmmmmm", -- 5 "mmmmmb...bmmmmm", -- 6 "mmmmmb...bmmmmm", -- 7 "mmmmmb...bmmmmm", -- 8 "mmmmmmbbbmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 9 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmbbbmmmmmm", -- 5 "mmmmmb...bmmmmm", -- 6 "mmmmmb...bmmmmm", -- 7 "mmmmmb...bmmmmm", -- 8 "mmmmmmbbbmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 10 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmmmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmbbbmmmmmm", -- 5 "mmmmmb...bmmmmm", -- 6 "mmmmmb...bmmmmm", -- 7 "mmmmmb...bmmmmm", -- 8 "mmmmmmbbbmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 -- Level 11 "bbbbbbbbbbbbbbb", -- 0 "bbbbbbbbbbbbbbb", -- 1 "bbbbbbbbbbbbbbb", -- 2 "bbbbbbbbbbbbbbb", -- 3 "bbbbobobbbobbbb", -- 4 "bbbbbobbbobbbbb", -- 5 "bbbbbbobobbbbbb", -- 6 "bbbbbbbpbbbbbbb", -- 7 "bbbbbbobobbbbbb", -- 8 "bbbbbobbbobbbbb", -- 9 "bbbbobobbbobbbb", -- 10 "bbbbbbbbbbbbbbb", -- 11 "bbbbbbbbbbbbbbb", -- 12 "bbbbbbbbbbbbbbb", -- 13 "bbbbbbbbbbbbbbb", -- 14 -- Level 12 "bbbbbbbbbbbbbbb", -- 0 "b.........bbbbb", -- 1 "b.........bqrbb", -- 2 "b......rr.b..bb", -- 3 "b....s...r.b.bb", -- 4 "b...tburr.....b", -- 5 "b...rqrrrr..rrb", -- 6 "b....rrrrrr.rrr", -- 7 "b....srrrr..rrb", -- 8 "b...tbu.r.r...b", -- 9 "b....q.r...b.bb", -- 10 "b.........b..bb", -- 11 "b.........bsrbb", -- 12 "b.........bbbbb", -- 13 "bbbbbbbbbbbbbbb", -- 14 -- Level 13 "bbbbbbbbbbbbbbb", -- 0 "b.........brtbb", -- 1 "b.........b.rbo", -- 2 "b.........b..bb", -- 3 "b..........b.bb", -- 4 "b....b........b", -- 5 "b......rr....rb", -- 6 "b.....rrrr...rr", -- 7 "b......rr.....b", -- 8 "b....b........b", -- 9 "b..........b.bb", -- 10 "b.........b..bb", -- 11 "b.........b.rbo", -- 12 "b.........brtbb", -- 13 "bbbbbbbbbbbbbbb", -- 14 -- Level 14 "mmmmmmmmmmbbbbb", -- 0 "mbbbbbbbbbbrrrb", -- 1 "mbv......vb.rso", -- 2 "mb........b.vbb", -- 3 "mb.........bbbb", -- 4 "mb...b......vbw", -- 5 "mb......r...vbb", -- 6 "mb....r......vb", -- 7 "mb.....r....vbb", -- 8 "mb...b......vbw", -- 9 "mb.........bbbb", -- 10 "mb........b.vbb", -- 11 "mbv......vb.rqo", -- 12 "mbbbbbbbbbbrrrb", -- 13 "mmmmmmmmmmbbbbb", -- 14 -- Level 15 "mmmmmmmmmmbbbbb", -- 0 "mmmmmmmmmmbr..b", -- 1 "mmbbbbbbbbbbr.o", -- 2 "mmbbbbbbbbbburb", -- 3 "mmbbbbbbbbbbbbb", -- 4 "mmbbbbbbbbbbbmm", -- 5 "mmbbbb..rbbbbwm", -- 6 "mmbbbbr..bbbbbw", -- 7 "mmbbbb.r.bbbbwm", -- 8 "mmbbbbbbbbbbbmm", -- 9 "mmbbbbbbbbbbbbb", -- 10 "mmbbbbbbbbbburb", -- 11 "mmbbbbbbbbbbrro", -- 12 "mmmmmmmmmmbrr.b", -- 13 "mmmmmmmmmmbbbbb", -- 14 -- Level 16 "mmmmmmmmmmbbbbb", -- 0 "mmmmmmmmmmb...b", -- 1 "mmmmmmmrmmrr..o", -- 2 "mmmbbbbrbbbrr.b", -- 3 "mmmbvrrrrrvbbbb", -- 4 "mmmb.brrrr.bmmm", -- 5 "mmmb.r...rrbmmm", -- 6 "mmmbrr...rrbwmm", -- 7 "mmmbrr...rrbmmm", -- 8 "mmmb.brrrrrbmmm", -- 9 "mmmbv.rrrrvbbbb", -- 10 "mmmbbbbrbbbrr.b", -- 11 "mmmmmmmmmrrrr.o", -- 12 "mmmmmmmmmmb...b", -- 13 "mmmmmmmmmmbbbbb", -- 14 -- Level 17 "mmmmmmmmmmbbbbb", -- 0 "mmmmmmmmmmb...b", -- 1 "mmmmmmmmmmrr..o", -- 2 "mmmmmmbrbrb...b", -- 3 "mmmmbbbrbbbbbbb", -- 4 "mmmmbb.r..bmmmm", -- 5 "mmmmb.....bmmmm", -- 6 "mmmmbr....bmmmm", -- 7 "mmmmb.....bmmmm", -- 8 "mmmmbb..r.bmmmm", -- 9 "mmmmbbbrbbbbbbb", -- 10 "mmmmmmbrbmb.r.b", -- 11 "mmmmmmmmmmrr..o", -- 12 "mmmmmmmmmmb...b", -- 13 "mmmmmmmmmmbbbbb", -- 14 -- Level 18 "mmmmmmmmmmbbbbb", -- 0 "mmmmmmmmmmb...o", -- 1 "mmmmmmmmmmb...o", -- 2 "mmmmmmmwmmb...o", -- 3 "mmmmmmwbwmbbbbb", -- 4 "mmmmmbbbbbmmmmm", -- 5 "mmmmmbv.vbmmmmm", -- 6 "mmmmmb...bmmmmm", -- 7 "mmmmmbv.vbmmmmm", -- 8 "mmmmmbbbbbmmmmm", -- 9 "mmmmmmwbwmbbbbb", -- 10 "mmmmmmmwmmb...o", -- 11 "mmmmmmmmmmb...o", -- 12 "mmmmmmmmmmb...o", -- 13 "mmmmmmmmmmbbbbb", -- 14 -- Level 19 "mmmmmmmmmmbbbbb", -- 0 "mmmmmmmmmmb...b", -- 1 "mmmmmmmmmmb...o", -- 2 "mmmmmmmmmmb...b", -- 3 "mmmmmmmmmmbbbbb", -- 4 "mmmmmmmmmmmmmmm", -- 5 "mmmmmmbbbmmmmmm", -- 6 "mmmmmmb.bmmmmmm", -- 7 "mmmmmmbbbmmmmmm", -- 8 "mmmmmmmmmmmmmmm", -- 9 "mmmmmmmmmmbbbbb", -- 10 "mmmmmmmmmmb...b", -- 11 "mmmmmmmmmmb...o", -- 12 "mmmmmmmmmmb...b", -- 13 "mmmmmmmmmmbbbbb", -- 14 -- Level 20 "mmmmmmmmmmbbbbb", -- 0 "mmmmmmmmmmb...b", -- 1 "mmmmmmmmmmb...b", -- 2 "mmmmmmmmmmb...b", -- 3 "mmmmmmmmmmbbbbb", -- 4 "mmmmmmmmmmmmmmm", -- 5 "mmmmmmmmmmmmmmm", -- 6 "mmmmmmmmmmmmmmm", -- 7 "mmmmmmmmmmmmmmm", -- 8 "mmmmmmmmmmmmmmm", -- 9 "mmmmmmmmmmbbbbb", -- 10 "mmmmmmmmmmb...b", -- 11 "mmmmmmmmmmb...b", -- 12 "mmmmmmmmmmb...b", -- 13 "mmmmmmmmmmbbbbb", -- 14 -- Level 21 "mmmmmmmmmmwswsw", -- 0 "mmmmmmmmmmtbbbu", -- 1 "mmmmmmmmmmwbbbw", -- 2 "mmmmmmmmmmtbbbu", -- 3 "mmmmmmmmmmwqwqw", -- 4 "mmmmmmmmmmmmmmm", -- 5 "mmmmmmmmmmmmmmm", -- 6 "mmmmmmmmmmmmmmm", -- 7 "mmmmmmmmmmmmmmm", -- 8 "mmmmmmmmmmmmmmm", -- 9 "mmmmmmmmmmwswsw", -- 10 "mmmmmmmmmmtbbbu", -- 11 "mmmmmmmmmmwbbbw", -- 12 "mmmmmmmmmmtbbbu", -- 13 "mmmmmmmmmmwqwqw", -- 14 -- Level 22 "mmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmm", -- 1 "mmmmmmmmmmmmwmm", -- 2 "mmmmmmmmmmmmmmm", -- 3 "mmmmmmmmmmmmmmm", -- 4 "mmmmmmmmmmmmmmm", -- 5 "mmmmmmmmmmmmmmm", -- 6 "mmmmmmmmmmmmmmm", -- 7 "mmmmmmmmmmmmmmm", -- 8 "mmmmmmmmmmmmmmm", -- 9 "mmmmmmmmmmmmmmm", -- 10 "mmmmmmmmmmmmmmm", -- 11 "mmmmmmmmmmmmwmm", -- 12 "mmmmmmmmmmmmmmm", -- 13 "mmmmmmmmmmmmmmm", -- 14 }, }, -- SandyDesertPyramid }, -- Pieces } ================================================ FILE: Server/Prefabs/SinglePieceStructures/DesertWell.cubeset ================================================ -- DesertWell.cubeset -- Defines the prefabs in the group DesertWell -- NOTE: This file has been generated automatically by GalExport! -- Any manual changes will be overwritten by the next automatic export! Cubeset = { Metadata = { CubesetFormatVersion = 1, ExportDate = "2020-08-27 10:42:17", ["AllowedBiomes"] = "Desert, DesertM, DesertHills", ["GridSizeX"] = "750", ["GridSizeZ"] = "750", ["IntendedUse"] = "SinglePieceStructures", ["MaxOffsetX"] = "100", ["MaxOffsetZ"] = "100", ["SeedOffset"] = "58612835", }, Pieces = { { OriginData = { ExportName = "DesertWell", Name = "DesertWell", GalleryName = "Desert", GalleryIndex = "221", ID = "1702", CreatorName = "12xx12", }, Size = { x = 5, y = 6, z = 5, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 4, MaxY = 5, MaxZ = 4, }, StructureBox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 4, MaxY = 5, MaxZ = 4, }, Connectors = { }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillNonAir", ["IsStarting"] = "1", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", ["VerticalStrategy"] = "TerrainOrOceanTop|-3", }, BlockDefinitions = { ".: 0: 0", -- air "a: 24: 0", -- sandstone "b: 8: 0", -- water "c: 44: 1", -- stone_slab "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "aaaaa", -- 0 "aaaaa", -- 1 "aaaaa", -- 2 "aaaaa", -- 3 "aaaaa", -- 4 -- Level 1 "aaaaa", -- 0 "aaaaa", -- 1 "aabaa", -- 2 "aaaaa", -- 3 "aaaaa", -- 4 -- Level 2 "aacaa", -- 0 "aa.aa", -- 1 "c...c", -- 2 "aa.aa", -- 3 "aacaa", -- 4 -- Level 3 "mmmmm", -- 0 "ma.am", -- 1 "m...m", -- 2 "ma.am", -- 3 "mmmmm", -- 4 -- Level 4 "mmmmm", -- 0 "ma.am", -- 1 "m...m", -- 2 "ma.am", -- 3 "mmmmm", -- 4 -- Level 5 "mmmmm", -- 0 "mcccm", -- 1 "mcacm", -- 2 "mcccm", -- 3 "mmmmm", -- 4 }, }, -- DesertWell }, -- Pieces } ================================================ FILE: Server/Prefabs/SinglePieceStructures/JungleTemple.cubeset ================================================ -- JungleTemple.cubeset -- Defines the prefabs in the group JungleTemple -- NOTE: This file has been generated automatically by GalExport! -- Any manual changes will be overwritten by the next automatic export! Cubeset = { Metadata = { CubesetFormatVersion = 1, ExportDate = "2020-08-27 10:42:17", ["AllowedBiomes"] = "Jungle, JungleHills, BambooJungle, BambooJungleHills", ["GridSizeX"] = "750", ["GridSizeZ"] = "750", ["IntendedUse"] = "SinglePieceStructures", ["MaxOffsetX"] = "100", ["MaxOffsetZ"] = "100", ["SeedOffset"] = "64775119", }, Pieces = { { OriginData = { ExportName = "JungleTemple_1703", Name = "JungleTemple", GalleryName = "Cube", GalleryIndex = "162", ID = "1703", CreatorName = "12xx12", }, Size = { x = 12, y = 14, z = 15, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 11, MaxY = 13, MaxZ = 14, }, StructureBox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 11, MaxY = 13, MaxZ = 14, }, Connectors = { }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillNonAir", ["IsStarting"] = "1", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", ["VerticalStrategy"] = "TerrainOrOceanTop|-4", }, BlockDefinitions = { ".: 0: 0", -- air "a: 48: 0", -- mossycobblestone "b: 4: 0", -- cobblestone "c: 54: 3", -- chest "d: 67: 2", -- stonestairs "e:131: 3", -- tripwirehook "f:132: 0", -- tripwire "g:131: 1", -- tripwirehook "h: 55: 0", -- redstonewire "i:131: 0", -- tripwirehook "j: 54: 5", -- chest "k:131: 2", -- tripwirehook "l: 69:12", -- lever "m: 19: 0", -- sponge "n: 98: 3", -- stonebricks "o: 93: 2", -- unpoweredrepeater "p: 29: 5", -- stickypiston "q: 29: 1", -- stickypiston "r: 23: 5", -- dispenser "s: 23: 2", -- dispenser "t: 67: 7", -- stonestairs "u: 67: 3", -- stonestairs }, BlockData = { -- Level 0 "aabbbbbaabaa", -- 0 "aaaaaaaaaaaa", -- 1 "babbbaaaaaab", -- 2 "baabaaababaa", -- 3 "aaabaabbbaaa", -- 4 "babaabbaabba", -- 5 "bbabaaabbaab", -- 6 "baabbbabaaaa", -- 7 "bbbaaaabaaaa", -- 8 "bbaabbaaaaab", -- 9 "abaaabababbb", -- 10 "bbaaaaabbaba", -- 11 "abaaababbaaa", -- 12 "aaaabaabbaab", -- 13 "aabaabaaaaab", -- 14 -- Level 1 "abaaaabbaabb", -- 0 "a.........ab", -- 1 "a..........b", -- 2 "aabab..a..aa", -- 3 "abcaa..a...a", -- 4 "aa.bbddb..ab", -- 5 "ba.aaabeffgb", -- 6 "ba.babhb..bb", -- 7 "bbhhaahb...a", -- 8 "aahaiaha..ab", -- 9 "aaa.f.h....b", -- 10 "abj.f.h...aa", -- 11 "baa.f.h....b", -- 12 "aa.akahha.ba", -- 13 "aababaaabaab", -- 14 -- Level 2 "abaaaabbabaa", -- 0 "b.........ab", -- 1 "alll.......b", -- 2 "bnnnb..a..bb", -- 3 "bo.hb..a...a", -- 4 "aa.hb..b..ba", -- 5 "apq.bdda..ab", -- 6 "baaaaabb..ba", -- 7 "aaaaba.a...a", -- 8 "ba..a.....ba", -- 9 "bbh........b", -- 10 "abr.......bb", -- 11 "ab.........b", -- 12 "babba.basbba", -- 13 "aaaaaaaaabaa", -- 14 -- Level 3 "baaaaaaaaaba", -- 0 "b..........b", -- 1 "a.......baaa", -- 2 "aaaba..a...a", -- 3 "b...a..aaaab", -- 4 "bh..b..a...b", -- 5 "ap..b..abaaa", -- 6 "aaaaadda...a", -- 7 "abbaatabbaaa", -- 8 "aaa.a.a....a", -- 9 "aab.....abbb", -- 10 "bba........a", -- 11 "aab.....baba", -- 12 "aab..b.....b", -- 13 "abaababbabaa", -- 14 -- Level 4 "baaabaaaaaaa", -- 0 "baabbbaabbaa", -- 1 "aaabbababaaa", -- 2 "aaaaababbaaa", -- 3 "aaabaabbabba", -- 4 "aabbb..bbaab", -- 5 "aabab..babba", -- 6 "aaabb..baaaa", -- 7 "babaaddababb", -- 8 "abaaabaabbbb", -- 9 "abaabaaaabaa", -- 10 "bbaabaaaaaaa", -- 11 "bbbbaabbbbaa", -- 12 "aaaaaaaaabab", -- 13 "bbaauuuuaaaa", -- 14 -- Level 5 "............", -- 0 "............", -- 1 "..bbabbbab..", -- 2 "..a......b..", -- 3 "..a.abab.b..", -- 4 "..a.a..b.b..", -- 5 "..a.u..u.a..", -- 6 "..a......b..", -- 7 "..b......a..", -- 8 "..b......b..", -- 9 "..a......a..", -- 10 "..a......b..", -- 11 "..aaa..baa..", -- 12 "............", -- 13 "............", -- 14 -- Level 6 "............", -- 0 "............", -- 1 "..bab..aaa..", -- 2 "..b......a..", -- 3 "..a......a..", -- 4 "..a......b..", -- 5 "..a......a..", -- 6 "..a......a..", -- 7 "..b......b..", -- 8 "..a......a..", -- 9 "..b......b..", -- 10 "..b......b..", -- 11 "..aaa..bbb..", -- 12 "............", -- 13 "............", -- 14 -- Level 7 "............", -- 0 ".aababaabaa.", -- 1 ".bbbabbaabb.", -- 2 ".babbbaabbb.", -- 3 ".baataataaa.", -- 4 ".aab....aaa.", -- 5 ".baa....aaa.", -- 6 ".aaa....aab.", -- 7 ".aab....aab.", -- 8 ".aaabaabbab.", -- 9 ".abbaababaa.", -- 10 ".ababbaabba.", -- 11 ".aabaaaabba.", -- 12 ".babbbabaaa.", -- 13 "............", -- 14 -- Level 8 "..b.a..b.b..", -- 0 ".bbaabaaabb.", -- 1 "bb........bb", -- 2 ".a........b.", -- 3 "aa........ba", -- 4 ".a........b.", -- 5 "bb........ab", -- 6 ".b........a.", -- 7 "aa........ba", -- 8 ".a..daad..a.", -- 9 "aa........ba", -- 10 ".a........a.", -- 11 "ab........bb", -- 12 ".baaababaab.", -- 13 "..a.a..b.a..", -- 14 -- Level 9 "..a.a..b.a..", -- 0 ".bbba..aaaa.", -- 1 "bb........bb", -- 2 ".a........a.", -- 3 "bb........aa", -- 4 "............", -- 5 "ab........bb", -- 6 ".a........b.", -- 7 "bb........bb", -- 8 "............", -- 9 "ab........bb", -- 10 ".a........a.", -- 11 "bb........bb", -- 12 ".aaba..babb.", -- 13 "..b.a..a.a..", -- 14 -- Level 10 "............", -- 0 ".bbabababab.", -- 1 ".abaabbaaab.", -- 2 ".aabbaaaabb.", -- 3 ".aaaaaaabba.", -- 4 "abab....abaa", -- 5 ".aab....aaa.", -- 6 ".aba....baa.", -- 7 ".baa....abb.", -- 8 "aabb....baab", -- 9 ".baaababbaa.", -- 10 ".ababaaaaaa.", -- 11 ".ababaaaaba.", -- 12 ".aaaabaabaa.", -- 13 ".....ba.....", -- 14 -- Level 11 "............", -- 0 "............", -- 1 "..a......b..", -- 2 "...abbbab...", -- 3 "...aaaaab...", -- 4 "...bbaabb...", -- 5 "...aa..ba...", -- 6 "...ab..bb...", -- 7 "...aa..aa...", -- 8 "...aaaaaa...", -- 9 "...baaaba...", -- 10 "...ababaa...", -- 11 "..b......a..", -- 12 "............", -- 13 "............", -- 14 -- Level 12 "............", -- 0 "............", -- 1 "..a......a..", -- 2 "............", -- 3 "....abaa....", -- 4 "....baab....", -- 5 "....bbab....", -- 6 "....baab....", -- 7 "....bbaa....", -- 8 "....abaa....", -- 9 "....baba....", -- 10 "............", -- 11 "..b......a..", -- 12 "............", -- 13 "............", -- 14 -- Level 13 "............", -- 0 "............", -- 1 "..a......a..", -- 2 "............", -- 3 "....a..b....", -- 4 "............", -- 5 ".....dd.....", -- 6 ".....ab.....", -- 7 ".....uu.....", -- 8 "............", -- 9 "....b..b....", -- 10 "............", -- 11 "..b......b..", -- 12 "............", -- 13 "............", -- 14 }, }, -- JungleTemple_1703 }, -- Pieces } ================================================ FILE: Server/Prefabs/SinglePieceStructures/WitchHut.cubeset ================================================ -- WitchHut.cubeset -- Defines the prefabs in the group WitchHut -- NOTE: This file has been generated automatically by GalExport! -- Any manual changes will be overwritten by the next automatic export! Cubeset = { Metadata = { CubesetFormatVersion = 1, ExportDate = "2020-08-27 10:42:17", ["AllowedBiomes"] = "Swampland, SwamplandM", ["GridSizeX"] = "750", ["GridSizeZ"] = "750", ["IntendedUse"] = "SinglePieceStructures", ["MaxOffsetX"] = "100", ["MaxOffsetZ"] = "100", ["SeedOffset"] = "4136893", }, Pieces = { { OriginData = { ExportName = "WitchHut", Name = "WitchHut", GalleryName = "Cube", GalleryIndex = "161", ID = "1704", CreatorName = "12xx12", }, Size = { x = 9, y = 5, z = 7, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 8, MaxY = 4, MaxZ = 6, }, StructureBox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 8, MaxY = 4, MaxZ = 6, }, Connectors = { }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillNonAir", ["IsStarting"] = "1", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", ["VerticalStrategy"] = "TerrainOrOceanTop", }, BlockDefinitions = { ".: 0: 0", -- air "a: 17: 0", -- tree "b: 5: 1", -- planks "c: 85: 0", -- fence "d:118: 0", -- cauldronblock "e: 58: 0", -- workbench "f:140: 0", -- flowerpotblock "g:134: 2", -- sprucewoodstairs "h:134: 0", -- sprucewoodstairs "i:134: 1", -- sprucewoodstairs "j:134: 3", -- sprucewoodstairs "m: 19: 0", -- sponge }, BlockData = { -- Level 0 ".........", -- 0 ".a....a..", -- 1 ".........", -- 2 ".........", -- 3 ".........", -- 4 ".a....a..", -- 5 ".........", -- 6 -- Level 1 ".........", -- 0 ".abbbbab.", -- 1 ".bbbbbbbb", -- 2 ".bbbbbbbb", -- 3 ".bbbbbbbb", -- 4 ".abbbbab.", -- 5 ".........", -- 6 -- Level 2 ".........", -- 0 ".abbbbac.", -- 1 ".bd......", -- 2 ".be...b..", -- 3 ".b....b..", -- 4 ".abbbbac.", -- 5 ".........", -- 6 -- Level 3 ".........", -- 0 ".ab..ba..", -- 1 ".b.......", -- 2 ".c....b..", -- 3 ".b....c..", -- 4 ".abf.ba..", -- 5 ".........", -- 6 -- Level 4 "gggggggg.", -- 0 "hbbbbbbi.", -- 1 "hbbbbbbi.", -- 2 "hbbbbbbi.", -- 3 "hbbbbbbi.", -- 4 "hbbbbbbi.", -- 5 "hjjjjjjj.", -- 6 }, }, -- WitchHut }, -- Pieces } ================================================ FILE: Server/Prefabs/Villages/AlchemistVillage.cubeset ================================================ -- AlchemistVillage.cubeset -- Defines the prefabs in the group AlchemistVillage -- NOTE: This file has been generated automatically by GalExport! -- Any manual changes will be overwritten by the next automatic export! Cubeset = { Metadata = { CubesetFormatVersion = 1, ExportDate = "2016-11-30 13:46:13", ["AllowedBiomes"] = "Desert, DesertM", ["IntendedUse"] = "Village", }, Pieces = { { OriginData = { ExportName = "LittleHouse", Name = "Desert 65", GalleryName = "Desert", GalleryIndex = "65", ID = "551", CreatorName = "STR_Warrior", }, Size = { x = 5, y = 6, z = 7, }, Hitbox = { MinX = -1, MinY = 0, MinZ = 0, MaxX = 5, MaxY = 5, MaxZ = 7, }, Connectors = { { Type = -1, RelX = 2, RelY = 2, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 24: 2", -- sandstone "b: 4: 0", -- cobblestone "c: 24: 0", -- sandstone "d: 13: 0", -- gravel "e: 5: 0", -- planks "f: 64: 3", -- woodendoorblock "g: 61: 2", -- furnace "h: 65: 2", -- ladder "i: 64: 9", -- woodendoorblock "j:101: 0", -- ironbars "k: 50: 4", -- torch "l:128: 2", -- sandstonestairs "m: 19: 0", -- sponge "n:126: 8", -- woodenslab "o:128: 4", -- sandstonestairs "p:128: 5", -- sandstonestairs "q:128: 7", -- sandstonestairs "r: 44: 1", -- stone_slab "s: 96: 2", -- trapdoor }, BlockData = { -- Level 0 "abbba", -- 0 "mbbbm", -- 1 "accca", -- 2 "ccccc", -- 3 "ccccc", -- 4 "ccccc", -- 5 "accca", -- 6 -- Level 1 "addda", -- 0 "mdddm", -- 1 "aceca", -- 2 "ceeec", -- 3 "ceeec", -- 4 "ceeec", -- 5 "accca", -- 6 -- Level 2 "a...a", -- 0 ".....", -- 1 "acfca", -- 2 "c...c", -- 3 "c...c", -- 4 "cg.hc", -- 5 "accca", -- 6 -- Level 3 "a...a", -- 0 ".....", -- 1 "acica", -- 2 "c...c", -- 3 "j...j", -- 4 "ck.hc", -- 5 "acjca", -- 6 -- Level 4 "l...l", -- 0 "c...c", -- 1 "accca", -- 2 "cnnnc", -- 3 "onnnp", -- 4 "cnnhc", -- 5 "acqca", -- 6 -- Level 5 ".....", -- 0 ".....", -- 1 "crcrc", -- 2 "r...r", -- 3 "c...c", -- 4 "r..sr", -- 5 "crcrc", -- 6 }, }, -- LittleHouse { OriginData = { ExportName = "LittleHouse3", Name = "Desert 66", GalleryName = "Desert", GalleryIndex = "66", ID = "553", CreatorName = "STR_Warrior", }, Size = { x = 9, y = 6, z = 7, }, Hitbox = { MinX = -1, MinY = 0, MinZ = 0, MaxX = 9, MaxY = 5, MaxZ = 7, }, Connectors = { { Type = -1, RelX = 4, RelY = 2, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 24: 2", -- sandstone "b: 4: 0", -- cobblestone "c: 24: 0", -- sandstone "d: 13: 0", -- gravel "e: 5: 0", -- planks "f: 64: 3", -- woodendoorblock "g: 65: 2", -- ladder "h: 64: 9", -- woodendoorblock "i:101: 0", -- ironbars "j: 50: 4", -- torch "k:128: 2", -- sandstonestairs "l:126: 8", -- woodenslab "m: 19: 0", -- sponge "n:128: 4", -- sandstonestairs "o:128: 5", -- sandstonestairs "p:128: 7", -- sandstonestairs "q: 44: 1", -- stone_slab "r: 96: 2", -- trapdoor }, BlockData = { -- Level 0 "mmabbbamm", -- 0 "mmmbbbmmm", -- 1 "accccccca", -- 2 "ccccccccc", -- 3 "ccccccccc", -- 4 "ccccccccc", -- 5 "accccccca", -- 6 -- Level 1 "mmadddamm", -- 0 "mmmdddmmm", -- 1 "accceccca", -- 2 "ceeeeeeec", -- 3 "ceeeeeeec", -- 4 "ceeeeeeec", -- 5 "accccccca", -- 6 -- Level 2 "mma...amm", -- 0 "mm.....mm", -- 1 "acccfccca", -- 2 "c.......c", -- 3 "c.......c", -- 4 "c......gc", -- 5 "accccccca", -- 6 -- Level 3 "mma...amm", -- 0 "mm.....mm", -- 1 "accchccca", -- 2 "c.......c", -- 3 "i.......i", -- 4 "c.j....gc", -- 5 "acciiicca", -- 6 -- Level 4 "mmk...kmm", -- 0 "mmc...cmm", -- 1 "accccccca", -- 2 "clllllllc", -- 3 "nlllllllo", -- 4 "cllllllgc", -- 5 "accpppcca", -- 6 -- Level 5 "mm.....mm", -- 0 "mm.....mm", -- 1 "cqqqcqqqc", -- 2 "q.......q", -- 3 "c.......c", -- 4 "q......rq", -- 5 "cqqqcqqqc", -- 6 }, }, -- LittleHouse3 { OriginData = { ExportName = "SmallHouse9", Name = "Desert 67", GalleryName = "Desert", GalleryIndex = "67", ID = "556", CreatorName = "STR_Warrior", }, Size = { x = 9, y = 6, z = 11, }, Hitbox = { MinX = -1, MinY = 0, MinZ = 0, MaxX = 9, MaxY = 5, MaxZ = 11, }, Connectors = { { Type = -1, RelX = 6, RelY = 2, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 24: 2", -- sandstone "b: 4: 0", -- cobblestone "c: 24: 0", -- sandstone "d: 13: 0", -- gravel "e: 5: 0", -- planks "f: 64: 3", -- woodendoorblock "g: 65: 2", -- ladder "h: 64: 9", -- woodendoorblock "i:101: 0", -- ironbars "j: 50: 2", -- torch "k: 50: 1", -- torch "l:128: 2", -- sandstonestairs "m: 19: 0", -- sponge "n:126: 8", -- woodenslab "o:128: 5", -- sandstonestairs "p:128: 6", -- sandstonestairs "q:128: 4", -- sandstonestairs "r:128: 7", -- sandstonestairs "s: 44: 1", -- stone_slab "t: 96: 2", -- trapdoor }, BlockData = { -- Level 0 "mmmmabbba", -- 0 "mmmmmbbbm", -- 1 "mmmmaccca", -- 2 "mmmmccccc", -- 3 "mmmmccccc", -- 4 "mmmmccccc", -- 5 "acccacccc", -- 6 "ccccccccc", -- 7 "ccccccccc", -- 8 "ccccccccc", -- 9 "accccccca", -- 10 -- Level 1 "mmmmaddda", -- 0 "mmmmmdddm", -- 1 "mmmmaceca", -- 2 "mmmmceeec", -- 3 "mmmmceeec", -- 4 "mmmmceeec", -- 5 "acccaeeec", -- 6 "ceeeeeeec", -- 7 "ceeeeeeec", -- 8 "ceeeeeeec", -- 9 "accccccca", -- 10 -- Level 2 "mmmma...a", -- 0 "mmmm.....", -- 1 "mmmmacfca", -- 2 "mmmmc...c", -- 3 "mmmmc...c", -- 4 "mmmmc...c", -- 5 "accca...c", -- 6 "c.......c", -- 7 "c.......c", -- 8 "c......gc", -- 9 "accccccca", -- 10 -- Level 3 "mmmma...a", -- 0 "mmmm.....", -- 1 "mmmmachca", -- 2 "mmmmc...c", -- 3 "mmmmc...c", -- 4 "mmmmc...i", -- 5 "acica...i", -- 6 "c.......i", -- 7 "i......jc", -- 8 "ck.....gc", -- 9 "acciiicca", -- 10 -- Level 4 "mmmml...l", -- 0 "mmmmc...c", -- 1 "mmmmaccca", -- 2 "mmmmcnnnc", -- 3 "mmmmcnnnc", -- 4 "mmmmcnnno", -- 5 "acpcannno", -- 6 "cnnnnnnno", -- 7 "qnnnnnnnc", -- 8 "cnnnnnngc", -- 9 "accrrrcca", -- 10 -- Level 5 "mmmm.....", -- 0 "mmmm.....", -- 1 "mmmmcscsc", -- 2 "mmmms...s", -- 3 "mmmms...s", -- 4 "mmmms...s", -- 5 "csssc...c", -- 6 "s.......s", -- 7 "s.......s", -- 8 "s......ts", -- 9 "cssscsssc", -- 10 }, }, -- SmallHouse9 { OriginData = { ExportName = "LittleHouse5", Name = "Desert 68", GalleryName = "Desert", GalleryIndex = "68", ID = "558", CreatorName = "STR_Warrior", }, Size = { x = 9, y = 6, z = 9, }, Hitbox = { MinX = -1, MinY = 0, MinZ = 0, MaxX = 9, MaxY = 5, MaxZ = 9, }, Connectors = { { Type = -1, RelX = 6, RelY = 2, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 24: 2", -- sandstone "b: 4: 0", -- cobblestone "c: 24: 0", -- sandstone "d: 13: 0", -- gravel "e: 5: 0", -- planks "f: 64: 3", -- woodendoorblock "g: 65: 2", -- ladder "h: 64: 9", -- woodendoorblock "i:101: 0", -- ironbars "j: 50: 1", -- torch "k: 50: 4", -- torch "l:128: 2", -- sandstonestairs "m: 19: 0", -- sponge "n:126: 8", -- woodenslab "o:128: 6", -- sandstonestairs "p:128: 5", -- sandstonestairs "q:128: 4", -- sandstonestairs "r:128: 7", -- sandstonestairs "s: 44: 1", -- stone_slab "t: 96: 2", -- trapdoor }, BlockData = { -- Level 0 "mmmmabbba", -- 0 "mmmmmbbbm", -- 1 "mmmmaccca", -- 2 "mmmmccccc", -- 3 "acccacccc", -- 4 "ccccccccc", -- 5 "ccccccccc", -- 6 "ccccccccc", -- 7 "accccccca", -- 8 -- Level 1 "mmmmaddda", -- 0 "mmmmmdddm", -- 1 "mmmmaceca", -- 2 "mmmmceeec", -- 3 "acccaeeec", -- 4 "ceeeeeeec", -- 5 "ceeeeeeec", -- 6 "ceeeeeeec", -- 7 "accccccca", -- 8 -- Level 2 "mmmma...a", -- 0 "mmmm.....", -- 1 "mmmmacfca", -- 2 "mmmmc...c", -- 3 "accca...c", -- 4 "c.......c", -- 5 "c.......c", -- 6 "c......gc", -- 7 "accccccca", -- 8 -- Level 3 "mmmma...a", -- 0 "mmmm.....", -- 1 "mmmmachca", -- 2 "mmmmc...c", -- 3 "acica...i", -- 4 "c.......i", -- 5 "i.......i", -- 6 "cj....kgc", -- 7 "acciiicca", -- 8 -- Level 4 "mmmml...l", -- 0 "mmmmc...c", -- 1 "mmmmaccca", -- 2 "mmmmcnnnc", -- 3 "acocannnp", -- 4 "cnnnnnnnp", -- 5 "qnnnnnnnp", -- 6 "cnnnnnngc", -- 7 "accrrrcca", -- 8 -- Level 5 "mmmm.....", -- 0 "mmmm.....", -- 1 "mmmmcscsc", -- 2 "mmmms...s", -- 3 "csssc...c", -- 4 "s.......s", -- 5 "s.......s", -- 6 "s......ts", -- 7 "cssscsssc", -- 8 }, }, -- LittleHouse5 { OriginData = { ExportName = "LittleHouse6", Name = "Desert 69", GalleryName = "Desert", GalleryIndex = "69", ID = "559", CreatorName = "STR_Warrior", }, Size = { x = 9, y = 6, z = 9, }, Hitbox = { MinX = -1, MinY = 0, MinZ = 0, MaxX = 9, MaxY = 5, MaxZ = 9, }, Connectors = { { Type = -1, RelX = 6, RelY = 2, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "A: 96: 2", -- trapdoor "a: 12: 0", -- sand "b: 24: 2", -- sandstone "c: 4: 0", -- cobblestone "d: 3: 0", -- dirt "e: 24: 0", -- sandstone "f: 13: 0", -- gravel "g: 2: 0", -- grass "h: 5: 0", -- planks "i: 85: 0", -- fence "j: 64: 3", -- woodendoorblock "k: 38: 1", -- rose "l: 38: 2", -- rose "m: 19: 0", -- sponge "n: 38: 5", -- rose "o: 65: 2", -- ladder "p: 64: 9", -- woodendoorblock "q:101: 0", -- ironbars "r: 50: 1", -- torch "s: 50: 4", -- torch "t:128: 2", -- sandstonestairs "u:126: 8", -- woodenslab "v:128: 6", -- sandstonestairs "w:128: 5", -- sandstonestairs "x:128: 4", -- sandstonestairs "y:128: 7", -- sandstonestairs "z: 44: 1", -- stone_slab }, BlockData = { -- Level 0 "aaaabcccb", -- 0 "adddccccm", -- 1 "adddbeeeb", -- 2 "adddeeeee", -- 3 "beeebeeee", -- 4 "eeeeeeeee", -- 5 "eeeeeeeee", -- 6 "eeeeeeeee", -- 7 "beeeeeeeb", -- 8 -- Level 1 "aaaabfffb", -- 0 "agggffffm", -- 1 "agggbeheb", -- 2 "aggdehhhe", -- 3 "beeebhhhe", -- 4 "ehhhhhhhe", -- 5 "ehhhhhhhe", -- 6 "ehhhhhhhe", -- 7 "beeeeeeeb", -- 8 -- Level 2 "iiiib...b", -- 0 "i........", -- 1 "i...bejeb", -- 2 "iklne...e", -- 3 "beeeb...e", -- 4 "e.......e", -- 5 "e.......e", -- 6 "e......oe", -- 7 "beeeeeeeb", -- 8 -- Level 3 "....b...b", -- 0 ".........", -- 1 "....bepeb", -- 2 "....e...e", -- 3 "beqeb...q", -- 4 "e.......q", -- 5 "q.......q", -- 6 "er....soe", -- 7 "beeqqqeeb", -- 8 -- Level 4 "....t...t", -- 0 "....e...e", -- 1 "....beeeb", -- 2 "....euuue", -- 3 "bevebuuuw", -- 4 "euuuuuuuw", -- 5 "xuuuuuuuw", -- 6 "euuuuuuoe", -- 7 "beeyyyeeb", -- 8 -- Level 5 ".........", -- 0 ".........", -- 1 "....ezeze", -- 2 "....z...z", -- 3 "ezzze...e", -- 4 "z.......z", -- 5 "z.......z", -- 6 "z......Az", -- 7 "ezzzezzze", -- 8 }, }, -- LittleHouse6 { OriginData = { ExportName = "LittleHouse4", Name = "Desert 70", GalleryName = "Desert", GalleryIndex = "70", ID = "560", CreatorName = "STR_Warrior", }, Size = { x = 5, y = 6, z = 11, }, Hitbox = { MinX = -1, MinY = 0, MinZ = 0, MaxX = 5, MaxY = 5, MaxZ = 11, }, Connectors = { { Type = -1, RelX = 2, RelY = 2, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 24: 2", -- sandstone "b: 4: 0", -- cobblestone "c: 24: 0", -- sandstone "d: 13: 0", -- gravel "e: 5: 0", -- planks "f: 64: 3", -- woodendoorblock "g: 65: 5", -- ladder "h:134: 3", -- sprucewoodstairs "i: 85: 0", -- fence "j:134: 2", -- sprucewoodstairs "k: 61: 2", -- furnace "l:134: 6", -- sprucewoodstairs "m: 19: 0", -- sponge "n:134: 4", -- sprucewoodstairs "o: 64: 9", -- woodendoorblock "p: 50: 2", -- torch "q:101: 0", -- ironbars "r:171: 8", -- carpet "s:128: 2", -- sandstonestairs "t:126: 8", -- woodenslab "u:128: 4", -- sandstonestairs "v:128: 5", -- sandstonestairs "w:128: 7", -- sandstonestairs "x: 44: 1", -- stone_slab "y: 96: 1", -- trapdoor }, BlockData = { -- Level 0 "abbba", -- 0 "mbbbm", -- 1 "accca", -- 2 "ccccc", -- 3 "ccccc", -- 4 "ccccc", -- 5 "ccccc", -- 6 "ccccc", -- 7 "ccccc", -- 8 "ccccc", -- 9 "accca", -- 10 -- Level 1 "addda", -- 0 "mdddm", -- 1 "aceca", -- 2 "ceeec", -- 3 "ceeec", -- 4 "ceeec", -- 5 "ceeec", -- 6 "ceeec", -- 7 "ceeec", -- 8 "ceeec", -- 9 "accca", -- 10 -- Level 2 "a...a", -- 0 ".....", -- 1 "acfca", -- 2 "cg..c", -- 3 "c...c", -- 4 "c..hc", -- 5 "c..ic", -- 6 "c..jc", -- 7 "c...c", -- 8 "cklnc", -- 9 "accca", -- 10 -- Level 3 "a...a", -- 0 ".....", -- 1 "acoca", -- 2 "cg..c", -- 3 "c..pc", -- 4 "q...q", -- 5 "q..rq", -- 6 "q...q", -- 7 "c...c", -- 8 "c...c", -- 9 "acqca", -- 10 -- Level 4 "s...s", -- 0 "c...c", -- 1 "accca", -- 2 "cgttc", -- 3 "ctttc", -- 4 "utttv", -- 5 "utttv", -- 6 "utttv", -- 7 "ctttc", -- 8 "ctttc", -- 9 "acwca", -- 10 -- Level 5 ".....", -- 0 ".....", -- 1 "cxcxc", -- 2 "xy..x", -- 3 "x...x", -- 4 "x...x", -- 5 "c...c", -- 6 "x...x", -- 7 "x...x", -- 8 "x...x", -- 9 "cxcxc", -- 10 }, }, -- LittleHouse4 { OriginData = { ExportName = "MediumHouse1", Name = "Desert 71", GalleryName = "Desert", GalleryIndex = "71", ID = "561", CreatorName = "STR_Warrior", }, Size = { x = 15, y = 9, z = 9, }, Hitbox = { MinX = -1, MinY = 0, MinZ = 0, MaxX = 15, MaxY = 8, MaxZ = 9, }, Connectors = { { Type = -1, RelX = 5, RelY = 2, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "80", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 24: 2", -- sandstone "b: 4: 0", -- cobblestone "c: 24: 0", -- sandstone "d: 13: 0", -- gravel "e: 5: 0", -- planks "f: 12: 0", -- sand "g: 64: 3", -- woodendoorblock "h: 85: 0", -- fence "i: 64: 0", -- woodendoorblock "j: 65: 5", -- ladder "k: 64: 9", -- woodendoorblock "l:101: 0", -- ironbars "m: 19: 0", -- sponge "n: 64: 8", -- woodendoorblock "o: 50: 4", -- torch "p:128: 2", -- sandstonestairs "q:126: 8", -- woodenslab "r:128: 4", -- sandstonestairs "s:128: 7", -- sandstonestairs "t: 44: 1", -- stone_slab "u: 50: 3", -- torch "v:128: 6", -- sandstonestairs }, BlockData = { -- Level 0 "mmmabbbammmmmmm", -- 0 "mmmmbbbmmmmmmmm", -- 1 "acccccccccacccc", -- 2 "ccccccccccccccc", -- 3 "ccccccccccccccc", -- 4 "ccccccccccccccc", -- 5 "ccccccccccccccc", -- 6 "ccccccccccccccc", -- 7 "acccccccccacccc", -- 8 -- Level 1 "mmmadddammmmmmm", -- 0 "mmmmdddmmmmmmmm", -- 1 "acccceccccaffff", -- 2 "ceeeeeeeeecffff", -- 3 "ceeeeeeeeecffff", -- 4 "ceeeeeeeeeeffff", -- 5 "ceeeeeeeeecffff", -- 6 "ceeeeeeeeecffff", -- 7 "acccccccccaffff", -- 8 -- Level 2 "mmma...ammmmmmm", -- 0 "mmm.....mmmmmmm", -- 1 "accccgccccahhhh", -- 2 "c.........c...h", -- 3 "c.........c...h", -- 4 "c.........i...h", -- 5 "c.........c...h", -- 6 "c.........cj..h", -- 7 "acccccccccahhhh", -- 8 -- Level 3 "mmma...ammmmmmm", -- 0 "mmm.....mmmmmmm", -- 1 "acccckcccca....", -- 2 "c.........c....", -- 3 "l.........c....", -- 4 "l.........n....", -- 5 "l.........c....", -- 6 "c..o...o..cj...", -- 7 "accclllccca....", -- 8 -- Level 4 "mmmp...pmmmmmmm", -- 0 "mmmc...cmmmmmmm", -- 1 "accccccccca....", -- 2 "cqqqqqqqqqc....", -- 3 "rqqqqqqqqqc....", -- 4 "rqqqqqqqqqc....", -- 5 "rqqqqqqqqqc....", -- 6 "cqqqqqqqqqcj...", -- 7 "acccsssccca....", -- 8 -- Level 5 "mmm.....mmmmmmm", -- 0 "mmm.....mmmmmmm", -- 1 "cttttcttttc....", -- 2 "t..accca..t....", -- 3 "t..c...c..t....", -- 4 "c.........c....", -- 5 "t..c...c..t....", -- 6 "t..accca..t....", -- 7 "cttttcttttc....", -- 8 -- Level 6 "...............", -- 0 "...............", -- 1 "...............", -- 2 "...aclca.......", -- 3 "...cu..c.......", -- 4 "...............", -- 5 "...c...c.......", -- 6 "...aclca.......", -- 7 "...............", -- 8 -- Level 7 "...............", -- 0 "...............", -- 1 "...............", -- 2 "...acvca.......", -- 3 "...cqqqc.......", -- 4 "...cqqqc.......", -- 5 "...cqqqc.......", -- 6 "...acsca.......", -- 7 "...............", -- 8 -- Level 8 "...............", -- 0 "...............", -- 1 "...............", -- 2 "...ctctc.......", -- 3 "...t...t.......", -- 4 "...c...c.......", -- 5 "...t...t.......", -- 6 "...ctctc.......", -- 7 "...............", -- 8 }, }, -- MediumHouse1 { OriginData = { ExportName = "LittleHouse2", Name = "Desert 72", GalleryName = "Desert", GalleryIndex = "72", ID = "562", CreatorName = "STR_Warrior", }, Size = { x = 7, y = 6, z = 11, }, Hitbox = { MinX = -1, MinY = 0, MinZ = 0, MaxX = 7, MaxY = 5, MaxZ = 11, }, Connectors = { { Type = -1, RelX = 3, RelY = 2, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 24: 2", -- sandstone "b: 4: 0", -- cobblestone "c: 24: 0", -- sandstone "d: 12: 0", -- sand "e: 13: 0", -- gravel "f: 5: 0", -- planks "g: 64: 3", -- woodendoorblock "h: 65: 5", -- ladder "i: 85: 0", -- fence "j:101: 0", -- ironbars "k: 64: 9", -- woodendoorblock "l: 50: 3", -- torch "m: 19: 0", -- sponge "n:128: 2", -- sandstonestairs "o:128: 6", -- sandstonestairs "p:126: 8", -- woodenslab "q:128: 4", -- sandstonestairs "r:128: 5", -- sandstonestairs "s:128: 7", -- sandstonestairs "t: 44: 1", -- stone_slab "u: 96: 0", -- trapdoor }, BlockData = { -- Level 0 "mabbbam", -- 0 "mmbbbmm", -- 1 "accccca", -- 2 "ccccccc", -- 3 "ccccccc", -- 4 "ccccccc", -- 5 "accccca", -- 6 "ddddddd", -- 7 "ddddddd", -- 8 "ddddddd", -- 9 "ddddddd", -- 10 -- Level 1 "maeeeam", -- 0 "mmeeemm", -- 1 "acccfca", -- 2 "cfffffc", -- 3 "cfffffc", -- 4 "cfffffc", -- 5 "acfccca", -- 6 "ddddddd", -- 7 "ddddddd", -- 8 "ddddddd", -- 9 "ddddddd", -- 10 -- Level 2 "ma...am", -- 0 "m.....m", -- 1 "acccgca", -- 2 "c.....c", -- 3 "c.....c", -- 4 "ch....c", -- 5 "ac.ccca", -- 6 "i.....i", -- 7 "i.....i", -- 8 "i.....i", -- 9 "iiiiiii", -- 10 -- Level 3 "ma...am", -- 0 "m.....m", -- 1 "acjckca", -- 2 "c..l..c", -- 3 "j.....j", -- 4 "ch....c", -- 5 "ac.cjca", -- 6 ".......", -- 7 ".......", -- 8 ".......", -- 9 ".......", -- 10 -- Level 4 "mn...nm", -- 0 "mc...cm", -- 1 "acoccca", -- 2 "cpppppc", -- 3 "qpppppr", -- 4 "chppppc", -- 5 "acccsca", -- 6 ".......", -- 7 ".......", -- 8 ".......", -- 9 ".......", -- 10 -- Level 5 "m.....m", -- 0 "m.....m", -- 1 "cttcttc", -- 2 "t.....t", -- 3 "c.....c", -- 4 "tu....t", -- 5 "cttcttc", -- 6 ".......", -- 7 ".......", -- 8 ".......", -- 9 ".......", -- 10 }, }, -- LittleHouse2 { OriginData = { ExportName = "LittleHouse7", Name = "Desert 73", GalleryName = "Desert", GalleryIndex = "73", ID = "563", CreatorName = "xoft", }, Size = { x = 9, y = 6, z = 11, }, Hitbox = { MinX = -1, MinY = 0, MinZ = 0, MaxX = 9, MaxY = 5, MaxZ = 11, }, Connectors = { { Type = -1, RelX = 6, RelY = 2, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 24: 2", -- sandstone "b: 4: 0", -- cobblestone "c: 24: 0", -- sandstone "d: 13: 0", -- gravel "e: 5: 0", -- planks "f: 64: 3", -- woodendoorblock "g: 65: 2", -- ladder "h:101: 0", -- ironbars "i: 64: 9", -- woodendoorblock "j: 50: 1", -- torch "k: 50: 2", -- torch "l:128: 2", -- sandstonestairs "m: 19: 0", -- sponge "n:128: 6", -- sandstonestairs "o:126: 8", -- woodenslab "p:128: 4", -- sandstonestairs "q:128: 5", -- sandstonestairs "r:128: 7", -- sandstonestairs "s: 44: 1", -- stone_slab "t: 96: 2", -- trapdoor }, BlockData = { -- Level 0 "mmmmabbba", -- 0 "mmmmmbbbm", -- 1 "accccccca", -- 2 "ccccccccc", -- 3 "ccccccccc", -- 4 "ccccccccc", -- 5 "acccacccc", -- 6 "mmmmccccc", -- 7 "mmmmccccc", -- 8 "mmmmccccc", -- 9 "mmmmaccca", -- 10 -- Level 1 "mmmmaddda", -- 0 "mmmmmdddm", -- 1 "accccceca", -- 2 "ceeeeeeec", -- 3 "ceeeeeeec", -- 4 "ceeeeeeec", -- 5 "acccaeeec", -- 6 "mmmmceeec", -- 7 "mmmmceeec", -- 8 "mmmmceeec", -- 9 "mmmmaccca", -- 10 -- Level 2 "mmmma...a", -- 0 "mmmm.....", -- 1 "acccccfca", -- 2 "c.......c", -- 3 "c.......c", -- 4 "c.......c", -- 5 "accca...c", -- 6 "mmmmc...c", -- 7 "mmmmc...c", -- 8 "mmmmc..gc", -- 9 "mmmmaccca", -- 10 -- Level 3 "mmmma...a", -- 0 "mmmm.....", -- 1 "achcccica", -- 2 "c.......c", -- 3 "h.......c", -- 4 "cj......h", -- 5 "achca...h", -- 6 "mmmmc...h", -- 7 "mmmmh..kc", -- 8 "mmmmc..gc", -- 9 "mmmmachca", -- 10 -- Level 4 "mmmml...l", -- 0 "mmmmc...c", -- 1 "acnccccca", -- 2 "coooooooc", -- 3 "poooooooc", -- 4 "coooooooq", -- 5 "acrcaoooq", -- 6 "mmmmcoooq", -- 7 "mmmmpoooc", -- 8 "mmmmcoogc", -- 9 "mmmmacrca", -- 10 -- Level 5 "mmmm.....", -- 0 "mmmm.....", -- 1 "cssscscsc", -- 2 "s.......s", -- 3 "s.......s", -- 4 "s.......s", -- 5 "csssc...c", -- 6 "mmmms...s", -- 7 "mmmms...s", -- 8 "mmmms..ts", -- 9 "mmmmcsssc", -- 10 }, }, -- LittleHouse7 { OriginData = { ExportName = "MediumHouse2", Name = "Desert 74", GalleryName = "Desert", GalleryIndex = "74", ID = "573", CreatorName = "STR_Warrior", }, Size = { x = 11, y = 10, z = 9, }, Hitbox = { MinX = -1, MinY = 0, MinZ = 0, MaxX = 11, MaxY = 9, MaxZ = 9, }, Connectors = { { Type = -1, RelX = 8, RelY = 2, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "80", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "A:128: 7", -- sandstonestairs "B: 44: 1", -- stone_slab "C: 96: 3", -- trapdoor "D: 96: 2", -- trapdoor "E:128: 2", -- sandstonestairs "F:128: 0", -- sandstonestairs "G: 87: 0", -- netherstone "H:128: 1", -- sandstonestairs "I:128: 3", -- sandstonestairs "J: 51: 0", -- fire "K: 44: 9", -- stone_slab "a: 24: 2", -- sandstone "b: 24: 0", -- sandstone "c: 4: 0", -- cobblestone "d: 12: 0", -- sand "e: 13: 0", -- gravel "f: 5: 0", -- planks "g: 65: 3", -- ladder "h: 85: 0", -- fence "i: 64: 3", -- woodendoorblock "j:134: 1", -- sprucewoodstairs "k:134: 2", -- sprucewoodstairs "l: 61: 2", -- furnace "m: 19: 0", -- sponge "n:134: 6", -- sprucewoodstairs "o:134: 4", -- sprucewoodstairs "p: 65: 2", -- ladder "q:101: 0", -- ironbars "r: 50: 2", -- torch "s: 47: 0", -- bookshelf "t: 64: 9", -- woodendoorblock "u: 50: 3", -- torch "v:171: 8", -- carpet "w:128: 6", -- sandstonestairs "x:126: 8", -- woodenslab "y:128: 5", -- sandstonestairs "z:128: 4", -- sandstonestairs }, BlockData = { -- Level 0 "abbbammmcmm", -- 0 "bbbbbdddcdm", -- 1 "bbbbbmmmcdm", -- 2 "bbbbbmmmcdm", -- 3 "bbbbabbbbba", -- 4 "bbbbbbbbbbb", -- 5 "bbbbbbbbbbb", -- 6 "bbbbbbbbbbb", -- 7 "abbbbbbbbba", -- 8 -- Level 1 "abbbammmemm", -- 0 "bfffbdddedm", -- 1 "bfffbmmmedm", -- 2 "bfffbmmmedm", -- 3 "bfffabbbfba", -- 4 "bfffffffffb", -- 5 "bfffffffffb", -- 6 "bfffffffffb", -- 7 "abbbbbbbbba", -- 8 -- Level 2 "abbba......", -- 0 "bg..bhhh.h.", -- 1 "b...b....h.", -- 2 "b...b....h.", -- 3 "b...abbbiba", -- 4 "b.........b", -- 5 "bjh.......b", -- 6 "bjk.lno..pb", -- 7 "abbbbbbbbba", -- 8 -- Level 3 "abqba......", -- 0 "bg..q......", -- 1 "b...q......", -- 2 "q..rb......", -- 3 "q...sbqbtba", -- 4 "q......u..b", -- 5 "b.v.......q", -- 6 "b........pb", -- 7 "abbbqqqbbba", -- 8 -- Level 4 "abwba......", -- 0 "bgxxy......", -- 1 "bxxxy......", -- 2 "zxxxb......", -- 3 "zxxxabwbbba", -- 4 "zxxxxxxxxxb", -- 5 "bxxxxxxxxxy", -- 6 "bxxxsssxxpb", -- 7 "abbbAAAbbba", -- 8 -- Level 5 "bBBBb......", -- 0 "BC..B......", -- 1 "B...B......", -- 2 "B...B......", -- 3 "b...bBBBBBb", -- 4 "Bbbb......B", -- 5 "Bbbb......B", -- 6 "Bbbb.....DB", -- 7 "bBBBBbBBBBb", -- 8 -- Level 6 "...........", -- 0 "...........", -- 1 "...........", -- 2 "...........", -- 3 "...........", -- 4 ".aEa.......", -- 5 ".FGH.......", -- 6 ".aIa.......", -- 7 "...........", -- 8 -- Level 7 "...........", -- 0 "...........", -- 1 "...........", -- 2 "...........", -- 3 "...........", -- 4 ".a.a.......", -- 5 "..J........", -- 6 ".a.a.......", -- 7 "...........", -- 8 -- Level 8 "...........", -- 0 "...........", -- 1 "...........", -- 2 "...........", -- 3 "...........", -- 4 ".bbb.......", -- 5 ".bKb.......", -- 6 ".bbb.......", -- 7 "...........", -- 8 -- Level 9 "...........", -- 0 "...........", -- 1 "...........", -- 2 "...........", -- 3 "...........", -- 4 ".B.B.......", -- 5 "...........", -- 6 ".B.B.......", -- 7 "...........", -- 8 }, }, -- MediumHouse2 { OriginData = { ExportName = "MediumHouse3", Name = "Desert 76", GalleryName = "Desert", GalleryIndex = "76", ID = "575", CreatorName = "STR_Warrior", }, Size = { x = 12, y = 10, z = 11, }, Hitbox = { MinX = -1, MinY = 0, MinZ = 0, MaxX = 12, MaxY = 9, MaxZ = 11, }, Connectors = { { Type = -1, RelX = 9, RelY = 2, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "80", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 24: 2", -- sandstone "b: 4: 0", -- cobblestone "c: 3: 0", -- dirt "d: 24: 0", -- sandstone "e: 13: 0", -- gravel "f: 2: 0", -- grass "g: 5: 0", -- planks "h: 85: 0", -- fence "i: 64: 3", -- woodendoorblock "j: 64: 2", -- woodendoorblock "k: 65: 4", -- ladder "l: 65: 2", -- ladder "m: 19: 0", -- sponge "n: 50: 1", -- torch "o: 50: 2", -- torch "p:101: 0", -- ironbars "q: 64: 9", -- woodendoorblock "r:128: 2", -- sandstonestairs "s:128: 6", -- sandstonestairs "t:126: 8", -- woodenslab "u:128: 5", -- sandstonestairs "v:128: 7", -- sandstonestairs "w: 44: 1", -- stone_slab "x: 96: 0", -- trapdoor "y:126: 0", -- woodenslab "z:128: 4", -- sandstonestairs }, BlockData = { -- Level 0 "mmmmmammbbba", -- 0 "mmmmmmmmbbbm", -- 1 "cccccaddddda", -- 2 "cccccddddddd", -- 3 "cccccddddddd", -- 4 "cccccddddddd", -- 5 "cccddddddddd", -- 6 "mmmddddddddd", -- 7 "mmmdddddddda", -- 8 "mmmdddddmmmm", -- 9 "mmmadddammmm", -- 10 -- Level 1 "mmmmmammeeea", -- 0 "mmmmmmmmeeem", -- 1 "fffffadddgda", -- 2 "fffffdgggggd", -- 3 "fffffggggggd", -- 4 "fffffdgggggd", -- 5 "fffddggggggd", -- 6 "mmmdgggggggd", -- 7 "mmmdggggddda", -- 8 "mmmdgggdmmmm", -- 9 "mmmadddammmm", -- 10 -- Level 2 "mmmmma.....a", -- 0 "mmmmm.......", -- 1 "hhhhhadddida", -- 2 "h....d.....d", -- 3 "h....j.....d", -- 4 "h....d.....d", -- 5 "hhhad......d", -- 6 "mmmd......kd", -- 7 "mmmd....ddda", -- 8 "mmmd..ldmmmm", -- 9 "mmmadddammmm", -- 10 -- Level 3 "mmmmman...oa", -- 0 "mmmmm.......", -- 1 ".....appdqda", -- 2 ".....d.....d", -- 3 ".....q.....d", -- 4 ".....d.....p", -- 5 "...hd......d", -- 6 "mmmd......kd", -- 7 "mmmd....dppa", -- 8 "mmmd..ldmmmm", -- 9 "mmmhdddhmmmm", -- 10 -- Level 4 "mmmmmr.....r", -- 0 "mmmmmd.....d", -- 1 ".....assddda", -- 2 ".....dtttttd", -- 3 ".....dtttttd", -- 4 ".....dtttttu", -- 5 "...hdatttttd", -- 6 "mmmdttttttkd", -- 7 "mmmdtttadvva", -- 8 "mmmdttldmmmm", -- 9 "mmmhdddhmmmm", -- 10 -- Level 5 "............", -- 0 "............", -- 1 ".....dwwdwwd", -- 2 ".....w.....w", -- 3 ".....w.....w", -- 4 ".....w.....d", -- 5 "...hdadh...w", -- 6 "mmmd...d..xw", -- 7 "mmmd...awwwd", -- 8 "mmmd..ldmmmm", -- 9 "mmmhdddhmmmm", -- 10 -- Level 6 "............", -- 0 "............", -- 1 "............", -- 2 "............", -- 3 "............", -- 4 "............", -- 5 "...hd.dh....", -- 6 "mmmd...d....", -- 7 "mmmp........", -- 8 "mmmd..ldmmmm", -- 9 "mmmhdpdhmmmm", -- 10 -- Level 7 "............", -- 0 "............", -- 1 "............", -- 2 "............", -- 3 "............", -- 4 "............", -- 5 "...hd.dh....", -- 6 "mmmd...d....", -- 7 "mmmp........", -- 8 "mmmdn.ldmmmm", -- 9 "mmmhdpdhmmmm", -- 10 -- Level 8 "............", -- 0 "............", -- 1 "............", -- 2 "............", -- 3 "............", -- 4 "............", -- 5 "...adsda....", -- 6 "mmmdyyyd....", -- 7 "mmmzyyyu....", -- 8 "mmmdyyldmmmm", -- 9 "mmmadvdammmm", -- 10 -- Level 9 "............", -- 0 "............", -- 1 "............", -- 2 "............", -- 3 "............", -- 4 "............", -- 5 "...w.w.w....", -- 6 "mmm.........", -- 7 "mmmw...w....", -- 8 "mmm.....mmmm", -- 9 "mmmw.w.wmmmm", -- 10 }, }, -- MediumHouse3 { OriginData = { ExportName = "LargeHouse1", Name = "Desert 77", GalleryName = "Desert", GalleryIndex = "77", ID = "577", CreatorName = "STR_Warrior", }, Size = { x = 15, y = 14, z = 11, }, Hitbox = { MinX = -1, MinY = 0, MinZ = -1, MaxX = 14, MaxY = 13, MaxZ = 11, }, Connectors = { { Type = -1, RelX = 14, RelY = 2, RelZ = 3, Direction = 5, -- X+ }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "60", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "A: 96:10", -- trapdoor "B:128: 4", -- sandstonestairs "C:128: 5", -- sandstonestairs "D:128: 7", -- sandstonestairs "E: 44: 1", -- stone_slab "F:128: 2", -- sandstonestairs "G:128: 0", -- sandstonestairs "H: 87: 0", -- netherstone "I:128: 3", -- sandstonestairs "J: 51: 0", -- fire "K: 44: 9", -- stone_slab "a: 24: 2", -- sandstone "b: 24: 0", -- sandstone "c: 12: 0", -- sand "d: 4: 0", -- cobblestone "e: 5: 0", -- planks "f: 13: 0", -- gravel "g: 85: 0", -- fence "h: 5: 1", -- planks "i: 64: 2", -- woodendoorblock "j: 64: 0", -- woodendoorblock "k: 61: 2", -- furnace "l:118: 0", -- cauldronblock "m: 19: 0", -- sponge "n:134: 4", -- sprucewoodstairs "o: 65: 2", -- ladder "p:101: 0", -- ironbars "q: 50: 1", -- torch "r:140: 0", -- flowerpotblock "s: 64: 9", -- woodendoorblock "t: 50: 3", -- torch "u: 69:12", -- lever "v: 50: 4", -- torch "w:128: 6", -- sandstonestairs "x: 44:10", -- stone_slab "y:128: 1", -- sandstonestairs "z: 47: 0", -- bookshelf }, BlockData = { -- Level 0 "mmmmabbbbbbbamm", -- 0 "ccccbbbbbbbbbma", -- 1 "ccccbbbbbbbbbdd", -- 2 "ccccbbbbbbbbbdd", -- 3 "ccccbbbbbbbbbdd", -- 4 "ccccbbbbbbbbbma", -- 5 "ccccbbbbbbbbbmm", -- 6 "mmmmbbbbbbbbbmm", -- 7 "mmmmbbbbbbbbbmm", -- 8 "mmmmbbbbbbbbbmm", -- 9 "mmmmabbbbbbbamm", -- 10 -- Level 1 "mmmmabbbbbbbamm", -- 0 "ccccbeeeeeeebma", -- 1 "cccceeeeeeeebff", -- 2 "ccccbeeeeeeeeff", -- 3 "ccccbeeeeeeebff", -- 4 "ccccbeeeeeeebma", -- 5 "ccccbeeeeeeebmm", -- 6 "mmmmbeeeeeeebmm", -- 7 "mmmmbeeeeeeebmm", -- 8 "mmmmbeeeeeeebmm", -- 9 "mmmmabbbbbbbamm", -- 10 -- Level 2 "mmmmabbbbbbbamm", -- 0 "ggggb......hb.a", -- 1 "g...i.......b..", -- 2 "g...b.......j..", -- 3 "g...bkln..o.b..", -- 4 "g...bbbb.bbbb.a", -- 5 "ggggb.......bmm", -- 6 "mmmmb.......bmm", -- 7 "mmmmb.......bmm", -- 8 "mmmmb.......bmm", -- 9 "mmmmabbbbbbbamm", -- 10 -- Level 3 "mmmmabbpppbbamm", -- 0 "....bq.....rb.a", -- 1 "....s.......b.t", -- 2 "....b.......s..", -- 3 "....b.u...o.b.v", -- 4 "....bbbb.bbbb.a", -- 5 "....p..t.t..pmm", -- 6 "mmmmp.......pmm", -- 7 "mmmmp.......pmm", -- 8 "mmmmb.......bmm", -- 9 "mmmmabbpppbbamm", -- 10 -- Level 4 "mmmmabbwwwbbamm", -- 0 "....bxxxxxxxbby", -- 1 "....bxxxxxxxb..", -- 2 "....bxxxxxxxb..", -- 3 "....bzzzxxAxb..", -- 4 "....bbbbbbbbbby", -- 5 "....BxxxxxxxCmm", -- 6 "mmmmBxxxxxxxCmm", -- 7 "mmmmBxxxxxxxCmm", -- 8 "mmmmbxxxxxxxbmm", -- 9 "mmmmabbDDDbbamm", -- 10 -- Level 5 "mmmmbEEEbEEEbmm", -- 0 "....EabbbbbaE..", -- 1 "....Eb.....bE..", -- 2 "....Eb.....bE..", -- 3 "....Eb.....bE..", -- 4 "....babb.bbab..", -- 5 "....E.......Emm", -- 6 "mmmmE.......Emm", -- 7 "mmmmE.......Emm", -- 8 "mmmmE.......Emm", -- 9 "mmmmbEEEbEEEbmm", -- 10 -- Level 6 "...............", -- 0 ".....abbpbba...", -- 1 ".....p.....p...", -- 2 ".....p.....p...", -- 3 ".....p.....p...", -- 4 ".....abb.bba...", -- 5 "...............", -- 6 "...............", -- 7 "...............", -- 8 "...............", -- 9 "...............", -- 10 -- Level 7 "...............", -- 0 ".....abbwbba...", -- 1 ".....BxxxxxC...", -- 2 ".....BxxxxxC...", -- 3 ".....BxxxxxC...", -- 4 ".....abbbbba...", -- 5 "...............", -- 6 "...............", -- 7 "...............", -- 8 "...............", -- 9 "...............", -- 10 -- Level 8 "...............", -- 0 ".....bEEbEEb...", -- 1 ".....E.bbb.E...", -- 2 ".....b.bbb.b...", -- 3 ".....E.bbb.E...", -- 4 ".....bEEbEEb...", -- 5 "...............", -- 6 "...............", -- 7 "...............", -- 8 "...............", -- 9 "...............", -- 10 -- Level 9 "...............", -- 0 "...............", -- 1 ".......aFa.....", -- 2 ".......GHy.....", -- 3 ".......aIa.....", -- 4 "...............", -- 5 "...............", -- 6 "...............", -- 7 "...............", -- 8 "...............", -- 9 "...............", -- 10 -- Level 10 "...............", -- 0 "...............", -- 1 ".......a.a.....", -- 2 "........J......", -- 3 ".......a.a.....", -- 4 "...............", -- 5 "...............", -- 6 "...............", -- 7 "...............", -- 8 "...............", -- 9 "...............", -- 10 -- Level 11 "...............", -- 0 "...............", -- 1 ".......awa.....", -- 2 ".......B.C.....", -- 3 ".......aDa.....", -- 4 "...............", -- 5 "...............", -- 6 "...............", -- 7 "...............", -- 8 "...............", -- 9 "...............", -- 10 -- Level 12 "...............", -- 0 "...............", -- 1 ".......bbb.....", -- 2 ".......bKb.....", -- 3 ".......bbb.....", -- 4 "...............", -- 5 "...............", -- 6 "...............", -- 7 "...............", -- 8 "...............", -- 9 "...............", -- 10 -- Level 13 "...............", -- 0 "...............", -- 1 ".......E.E.....", -- 2 "...............", -- 3 ".......E.E.....", -- 4 "...............", -- 5 "...............", -- 6 "...............", -- 7 "...............", -- 8 "...............", -- 9 "...............", -- 10 }, }, -- LargeHouse1 { OriginData = { ExportName = "LittleTower", Name = "Desert 79", GalleryName = "Desert", GalleryIndex = "79", ID = "595", CreatorName = "STR_Warrior", }, Size = { x = 5, y = 9, z = 7, }, Hitbox = { MinX = -1, MinY = 0, MinZ = 0, MaxX = 5, MaxY = 8, MaxZ = 7, }, Connectors = { { Type = -1, RelX = 2, RelY = 2, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 24: 2", -- sandstone "b: 4: 0", -- cobblestone "c: 24: 0", -- sandstone "d: 13: 0", -- gravel "e: 5: 0", -- planks "f: 64: 3", -- woodendoorblock "g: 65: 5", -- ladder "h: 64: 9", -- woodendoorblock "i:101: 0", -- ironbars "j: 50: 4", -- torch "k:128: 2", -- sandstonestairs "l:126: 8", -- woodenslab "m: 19: 0", -- sponge "n:128: 4", -- sandstonestairs "o:128: 5", -- sandstonestairs "p:128: 7", -- sandstonestairs "q:128: 6", -- sandstonestairs "r: 44: 1", -- stone_slab "s: 96: 1", -- trapdoor }, BlockData = { -- Level 0 "abbba", -- 0 "mbbbm", -- 1 "accca", -- 2 "ccccc", -- 3 "ccccc", -- 4 "ccccc", -- 5 "accca", -- 6 -- Level 1 "addda", -- 0 "mdddm", -- 1 "aceca", -- 2 "ceeec", -- 3 "ceeec", -- 4 "ceeec", -- 5 "accca", -- 6 -- Level 2 "a...a", -- 0 ".....", -- 1 "acfca", -- 2 "cg..c", -- 3 "c...c", -- 4 "c...c", -- 5 "accca", -- 6 -- Level 3 "a...a", -- 0 ".....", -- 1 "achca", -- 2 "cg..c", -- 3 "i...i", -- 4 "c..jc", -- 5 "acica", -- 6 -- Level 4 "k...k", -- 0 "c...c", -- 1 "accca", -- 2 "cgllc", -- 3 "nlllo", -- 4 "clllc", -- 5 "acpca", -- 6 -- Level 5 ".....", -- 0 ".....", -- 1 "accca", -- 2 "cg..c", -- 3 "c...c", -- 4 "c...c", -- 5 "accca", -- 6 -- Level 6 ".....", -- 0 ".....", -- 1 "acica", -- 2 "cg..c", -- 3 "i...i", -- 4 "c..jc", -- 5 "acica", -- 6 -- Level 7 ".....", -- 0 ".....", -- 1 "acqca", -- 2 "cgllc", -- 3 "nlllo", -- 4 "clllc", -- 5 "acpca", -- 6 -- Level 8 ".....", -- 0 ".....", -- 1 "crcrc", -- 2 "rs..r", -- 3 "c...c", -- 4 "r...r", -- 5 "crcrc", -- 6 }, }, -- LittleTower { OriginData = { ExportName = "LargeTower", Name = "Desert 80", GalleryName = "Desert", GalleryIndex = "80", ID = "596", CreatorName = "STR_Warrior", }, Size = { x = 7, y = 12, z = 7, }, Hitbox = { MinX = -1, MinY = 0, MinZ = 0, MaxX = 7, MaxY = 11, MaxZ = 7, }, Connectors = { { Type = -1, RelX = 3, RelY = 2, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 24: 0", -- sandstone "b: 4: 0", -- cobblestone "c: 12: 0", -- sand "d: 5: 0", -- planks "e: 13: 0", -- gravel "f:128: 2", -- sandstonestairs "g:128: 0", -- sandstonestairs "h: 24: 2", -- sandstone "i: 71: 3", -- irondoorblock "j:128: 1", -- sandstonestairs "k:128: 3", -- sandstonestairs "l: 77: 4", -- stonebutton "m: 19: 0", -- sponge "n: 71: 9", -- irondoorblock "o: 77: 3", -- stonebutton "p:128: 6", -- sandstonestairs "q:128: 4", -- sandstonestairs "r:128: 5", -- sandstonestairs "s: 50: 4", -- torch "t:128: 7", -- sandstonestairs "u: 85: 0", -- fence "v: 24: 1", -- sandstone "w: 44: 1", -- stone_slab "x: 89: 0", -- lightstone }, BlockData = { -- Level 0 "mabbbam", -- 0 "aacdcaa", -- 1 "madddam", -- 2 "madddam", -- 3 "madddam", -- 4 "aaaaaaa", -- 5 "mammmam", -- 6 -- Level 1 "maeeeam", -- 0 "aacdcaa", -- 1 "madddam", -- 2 "madddam", -- 3 "madddam", -- 4 "aaaaaaa", -- 5 "mammmam", -- 6 -- Level 2 "mf...fm", -- 0 "ghaiahj", -- 1 "ma...am", -- 2 "ma...am", -- 3 "ma...am", -- 4 "ghaaahj", -- 5 "mkmmmkm", -- 6 -- Level 3 "m.l...m", -- 0 ".hanah.", -- 1 ".ao..a.", -- 2 ".a...a.", -- 3 ".a...a.", -- 4 ".haaah.", -- 5 "m.....m", -- 6 -- Level 4 ".......", -- 0 "..pap..", -- 1 ".q...r.", -- 2 ".a...a.", -- 3 ".q.s.r.", -- 4 "..tat..", -- 5 ".......", -- 6 -- Level 5 ".......", -- 0 "..aua..", -- 1 ".a...a.", -- 2 ".u...u.", -- 3 ".a...a.", -- 4 "..aua..", -- 5 ".......", -- 6 -- Level 6 ".......", -- 0 "..aua..", -- 1 ".a...a.", -- 2 ".u...u.", -- 3 ".a...a.", -- 4 "..aua..", -- 5 ".......", -- 6 -- Level 7 ".......", -- 0 "..aua..", -- 1 ".a...a.", -- 2 ".u...u.", -- 3 ".a...a.", -- 4 "..aua..", -- 5 ".......", -- 6 -- Level 8 ".......", -- 0 "..faf..", -- 1 ".g...j.", -- 2 ".a...a.", -- 3 ".g...j.", -- 4 "..kak..", -- 5 ".......", -- 6 -- Level 9 ".......", -- 0 ".aavaa.", -- 1 ".a...a.", -- 2 ".v...v.", -- 3 ".a...a.", -- 4 ".aavaa.", -- 5 ".......", -- 6 -- Level 10 "...p...", -- 0 ".haaah.", -- 1 ".awwwa.", -- 2 "qawawar", -- 3 ".awwwa.", -- 4 ".haaah.", -- 5 "...t...", -- 6 -- Level 11 "...w...", -- 0 ".w...w.", -- 1 ".......", -- 2 "w..x..w", -- 3 ".......", -- 4 ".w...w.", -- 5 "...w...", -- 6 }, }, -- LargeTower { OriginData = { ExportName = "BarWithoutBasement", Name = "Desert 81", GalleryName = "Desert", GalleryIndex = "81", ID = "597", CreatorName = "STR_Warrior", }, Size = { x = 11, y = 9, z = 10, }, Hitbox = { MinX = -1, MinY = 0, MinZ = 0, MaxX = 11, MaxY = 8, MaxZ = 10, }, Connectors = { { Type = -1, RelX = 5, RelY = 2, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "80", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "A:126: 8", -- woodenslab "B:128: 7", -- sandstonestairs "C: 44: 1", -- stone_slab "D: 64: 3", -- woodendoorblock "E:128: 6", -- sandstonestairs "a: 24: 2", -- sandstone "b: 4: 0", -- cobblestone "c: 24: 0", -- sandstone "d: 13: 0", -- gravel "e: 5: 0", -- planks "f:128: 5", -- sandstonestairs "g:107: 0", -- fencegate "h:128: 4", -- sandstonestairs "i:134: 1", -- sprucewoodstairs "j:134: 3", -- sprucewoodstairs "k: 85: 0", -- fence "l:134: 0", -- sprucewoodstairs "m: 19: 0", -- sponge "n:134: 5", -- sprucewoodstairs "o:134: 7", -- sprucewoodstairs "p:134: 4", -- sprucewoodstairs "q:107: 3", -- fencegate "r: 64: 1", -- woodendoorblock "s: 65: 3", -- ladder "t: 50: 3", -- torch "u:171: 8", -- carpet "v:101: 0", -- ironbars "w: 64: 9", -- woodendoorblock "x:128: 2", -- sandstonestairs "y: 24: 1", -- sandstone "z: 44: 9", -- stone_slab }, BlockData = { -- Level 0 "mmmabbbammm", -- 0 "mmmmbbbmmmm", -- 1 "accccccccca", -- 2 "ccccccccccc", -- 3 "ccccccccccc", -- 4 "ccccccccccc", -- 5 "ccccccccccc", -- 6 "ccccccccccc", -- 7 "accccccccca", -- 8 "mmmmmmmmmmm", -- 9 -- Level 1 "mmmadddammm", -- 0 "mmmmdddmmmm", -- 1 "accceeeccca", -- 2 "ceeeeeeeeec", -- 3 "ceeeeeeeeec", -- 4 "ceeeeeeeeec", -- 5 "ceeeeeeeeec", -- 6 "ceeeeeeeeec", -- 7 "aecccccccca", -- 8 "mmmmmmmmmmm", -- 9 -- Level 2 "mmma...ammm", -- 0 "mmm.....mmm", -- 1 "acccfghccca", -- 2 "cij.....jjc", -- 3 "cik.....klc", -- 4 "c.........c", -- 5 "cnoop.....c", -- 6 "c...q..iklc", -- 7 "arcccccccca", -- 8 "mmsmmmmmmmm", -- 9 -- Level 3 "mmma...ammm", -- 0 "mmm.....mmm", -- 1 "accc...ccca", -- 2 "c..t...t..c", -- 3 "c.u.....u.c", -- 4 "v.........v", -- 5 "c.........c", -- 6 "c.......u.c", -- 7 "awccvvvccca", -- 8 "mmsmmmmmmmm", -- 9 -- Level 4 "mmmx...xmmm", -- 0 "mmmy...cmmm", -- 1 "acccfzhccca", -- 2 "cAAAAAAAAAc", -- 3 "cAAAAAAAAAc", -- 4 "hAAAAAAAAAf", -- 5 "cAAAAAAAAAc", -- 6 "cAAAAAAAAAc", -- 7 "acccBBBccca", -- 8 "mmsmmmmmmmm", -- 9 -- Level 5 "mmm.....mmm", -- 0 "mmm.....mmm", -- 1 "cCCCCcCCCCc", -- 2 "CacccccccaC", -- 3 "Cc.......cC", -- 4 "cc.......cc", -- 5 "Cc.......cC", -- 6 "CaDccccccaC", -- 7 "cC.CCcCCCCc", -- 8 "mmmmmmmmmmm", -- 9 -- Level 6 "...........", -- 0 "...........", -- 1 "...........", -- 2 ".accvvvcca.", -- 3 ".c.......c.", -- 4 ".v.......v.", -- 5 ".c.......c.", -- 6 ".awcvvvcca.", -- 7 "...........", -- 8 "...........", -- 9 -- Level 7 "...........", -- 0 "...........", -- 1 "...........", -- 2 ".accEEEcca.", -- 3 ".cAAAAAAAc.", -- 4 ".hAAAAAAAf.", -- 5 ".cAAAAAAAc.", -- 6 ".accBBBcca.", -- 7 "...........", -- 8 "...........", -- 9 -- Level 8 "...........", -- 0 "...........", -- 1 "...........", -- 2 ".cCCCcCCCc.", -- 3 ".C.......C.", -- 4 ".c.......c.", -- 5 ".C.......C.", -- 6 ".cCCCcCCCc.", -- 7 "...........", -- 8 "...........", -- 9 }, }, -- BarWithoutBasement { OriginData = { ExportName = "BarWithBasement", Name = "Desert 82", GalleryName = "Desert", GalleryIndex = "82", ID = "598", CreatorName = "STR_Warrior", }, Size = { x = 11, y = 12, z = 10, }, Hitbox = { MinX = -1, MinY = 0, MinZ = 0, MaxX = 11, MaxY = 11, MaxZ = 10, }, Connectors = { { Type = -1, RelX = 5, RelY = 5, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "70", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "A: 65: 3", -- ladder "B: 50: 3", -- torch "C:171: 8", -- carpet "D:101: 0", -- ironbars "E: 64: 9", -- woodendoorblock "F:128: 2", -- sandstonestairs "G: 24: 1", -- sandstone "H: 44: 9", -- stone_slab "I:126: 8", -- woodenslab "J:128: 7", -- sandstonestairs "K: 44: 1", -- stone_slab "L: 64: 3", -- woodendoorblock "M:128: 6", -- sandstonestairs "a: 24: 2", -- sandstone "b: 1: 0", -- stone "c: 24: 0", -- sandstone "d: 12: 0", -- sand "e:134: 4", -- sprucewoodstairs "f: 5: 1", -- planks "g:134: 5", -- sprucewoodstairs "h: 65: 5", -- ladder "i: 17: 3", -- tree "j: 69:11", -- lever "k: 4: 0", -- cobblestone "l:134: 0", -- sprucewoodstairs "m: 19: 0", -- sponge "n:134: 1", -- sprucewoodstairs "o: 50: 4", -- torch "p: 13: 0", -- gravel "q: 5: 0", -- planks "r: 96: 8", -- trapdoor "s:128: 5", -- sandstonestairs "t:107: 2", -- fencegate "u:128: 4", -- sandstonestairs "v:134: 3", -- sprucewoodstairs "w: 85: 0", -- fence "x:134: 7", -- sprucewoodstairs "y:107: 1", -- fencegate "z: 64: 1", -- woodendoorblock }, BlockData = { -- Level 0 "mmmabbbammm", -- 0 "mcccccccccm", -- 1 "abcccccccba", -- 2 "cbcccccccbc", -- 3 "cbcccccccbc", -- 4 "cbcccccccbc", -- 5 "cbcccccccbc", -- 6 "cbcccccccbc", -- 7 "abbbbbbbbba", -- 8 "mmmmmmmmmmm", -- 9 -- Level 1 "mmmadddammm", -- 0 "mcccccccccm", -- 1 "acefg.efgca", -- 2 "ccefg.efgcc", -- 3 "ccefg.efgcc", -- 4 "cc.......cc", -- 5 "cc.......cc", -- 6 "cch......cc", -- 7 "accccccccca", -- 8 "mmmmmmmmmmm", -- 9 -- Level 2 "mmmadddammm", -- 0 "mcccccccccm", -- 1 "acfff.fffca", -- 2 "ccfff.fffcc", -- 3 "ccfif.fifcc", -- 4 "cc.j...j.cc", -- 5 "cc.......cc", -- 6 "cch......cc", -- 7 "accccccccca", -- 8 "mmmmmmmmmmm", -- 9 -- Level 3 "mmmakkkammm", -- 0 "mcccccccccm", -- 1 "aclfn.lfnca", -- 2 "cclfn.lfncc", -- 3 "cclfn.lfncc", -- 4 "cc.......cc", -- 5 "cc.......cc", -- 6 "cch..o...cc", -- 7 "accccccccca", -- 8 "mmmmmmmmmmm", -- 9 -- Level 4 "mmmapppammm", -- 0 "mmmmpppmmmm", -- 1 "acccqqqccca", -- 2 "cqqqqqqqqqc", -- 3 "cqqqqqqqqqc", -- 4 "cqqqqqqqqqc", -- 5 "cqqqqqqqqqc", -- 6 "cqrqqqqqqqc", -- 7 "aqcccccccca", -- 8 "mmmmmmmmmmm", -- 9 -- Level 5 "mmma...ammm", -- 0 "mmm.....mmm", -- 1 "acccstuccca", -- 2 "cnv.....vvc", -- 3 "cnw.....wlc", -- 4 "c.........c", -- 5 "cgxxe.....c", -- 6 "c...y..nwlc", -- 7 "azcccccccca", -- 8 "mmAmmmmmmmm", -- 9 -- Level 6 "mmma...ammm", -- 0 "mmm.....mmm", -- 1 "accc...ccca", -- 2 "c..B...B..c", -- 3 "c.C.....C.c", -- 4 "D.........D", -- 5 "c.........c", -- 6 "c.......C.c", -- 7 "aEccDDDccca", -- 8 "mmAmmmmmmmm", -- 9 -- Level 7 "mmmF...Fmmm", -- 0 "mmmG...cmmm", -- 1 "acccsHuccca", -- 2 "cIIIIIIIIIc", -- 3 "cIIIIIIIIIc", -- 4 "uIIIIIIIIIs", -- 5 "cIIIIIIIIIc", -- 6 "cIIIIIIIIIc", -- 7 "acccJJJccca", -- 8 "mmAmmmmmmmm", -- 9 -- Level 8 "mmm.....mmm", -- 0 "mmm.....mmm", -- 1 "cKKKKcKKKKc", -- 2 "KacccccccaK", -- 3 "Kc.......cK", -- 4 "cc.......cc", -- 5 "Kc.......cK", -- 6 "KaLccccccaK", -- 7 "cK.KKcKKKKc", -- 8 "mmmmmmmmmmm", -- 9 -- Level 9 "...........", -- 0 "...........", -- 1 "...........", -- 2 ".accDDDcca.", -- 3 ".c.......c.", -- 4 ".D.......D.", -- 5 ".c.......c.", -- 6 ".aEcDDDcca.", -- 7 "...........", -- 8 "...........", -- 9 -- Level 10 "...........", -- 0 "...........", -- 1 "...........", -- 2 ".accMMMcca.", -- 3 ".cIIIIIIIc.", -- 4 ".uIIIIIIIs.", -- 5 ".cIIIIIIIc.", -- 6 ".accJJJcca.", -- 7 "...........", -- 8 "...........", -- 9 -- Level 11 "...........", -- 0 "...........", -- 1 "...........", -- 2 ".cKKKcKKKc.", -- 3 ".K.......K.", -- 4 ".c.......c.", -- 5 ".K.......K.", -- 6 ".cKKKcKKKc.", -- 7 "...........", -- 8 "...........", -- 9 }, }, -- BarWithBasement { OriginData = { ExportName = "Temple", Name = "Desert 83", GalleryName = "Desert", GalleryIndex = "83", ID = "599", CreatorName = "STR_Warrior", }, Size = { x = 13, y = 10, z = 9, }, Hitbox = { MinX = -1, MinY = 0, MinZ = 0, MaxX = 13, MaxY = 9, MaxZ = 9, }, Connectors = { { Type = -1, RelX = 6, RelY = 2, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "50", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "A: 51: 0", -- fire "B: 44: 9", -- stone_slab "a: 24: 2", -- sandstone "b: 4: 0", -- cobblestone "c: 24: 0", -- sandstone "d: 13: 0", -- gravel "e: 5: 0", -- planks "f: 64: 3", -- woodendoorblock "g: 17: 0", -- tree "h:128: 5", -- sandstonestairs "i:128: 4", -- sandstonestairs "j:128: 7", -- sandstonestairs "k:128: 6", -- sandstonestairs "l:118: 3", -- cauldronblock "m: 19: 0", -- sponge "n:155: 1", -- quartzblock "o: 64: 9", -- woodendoorblock "p: 50: 3", -- torch "q:101: 0", -- ironbars "r:140: 0", -- flowerpotblock "s: 24: 1", -- sandstone "t:128: 2", -- sandstonestairs "u:126: 8", -- woodenslab "v: 44: 1", -- stone_slab "w:128: 0", -- sandstonestairs "x: 87: 0", -- netherstone "y:128: 1", -- sandstonestairs "z:128: 3", -- sandstonestairs }, BlockData = { -- Level 0 "mmmmabbbammmm", -- 0 "mmmmmbbbmmmmm", -- 1 "accccccccccca", -- 2 "ccccccccccccc", -- 3 "ccccccccccccc", -- 4 "ccccccccccccc", -- 5 "ccccccccccccc", -- 6 "ccccccccccccc", -- 7 "accccccccccca", -- 8 -- Level 1 "mmmmadddammmm", -- 0 "mmmmmdddmmmmm", -- 1 "accccceccccca", -- 2 "ceeeeeeeeeeec", -- 3 "ceeeeeeeeeeec", -- 4 "ceeeeeeeeeeec", -- 5 "ceeeeeeeeeeec", -- 6 "ceeeeeeeeeeec", -- 7 "accccccccccca", -- 8 -- Level 2 "mmmma...ammmm", -- 0 "mmmm.....mmmm", -- 1 "acccccfccccca", -- 2 "cgh.......igc", -- 3 "cj.........jc", -- 4 "c...........c", -- 5 "ck.........kc", -- 6 "cgh.linhl.igc", -- 7 "accccccccccca", -- 8 -- Level 3 "mmmma...ammmm", -- 0 "mmmm.....mmmm", -- 1 "acccccoccccca", -- 2 "cg...p.p...gc", -- 3 "c...........c", -- 4 "q...........q", -- 5 "c...........c", -- 6 "cg...rsr...gc", -- 7 "acqqqcccqqqca", -- 8 -- Level 4 "mmmmt...tmmmm", -- 0 "mmmms...cmmmm", -- 1 "accccccccccca", -- 2 "cguuuuuuuuugc", -- 3 "cuuuuuuuuuuuc", -- 4 "iuuuuuuuuuuuh", -- 5 "cuuuuuuuuuuuc", -- 6 "cguuuuuuuuugc", -- 7 "acjjjcccjjjca", -- 8 -- Level 5 "mmmm.....mmmm", -- 0 "mmmm.....mmmm", -- 1 "cvvvvvcvvvvvc", -- 2 "v...........v", -- 3 "v.ccc...ccc.v", -- 4 "c.ccc...ccc.c", -- 5 "v.ccc...ccc.v", -- 6 "v...........v", -- 7 "cvvvvvcvvvvvc", -- 8 -- Level 6 ".............", -- 0 ".............", -- 1 ".............", -- 2 ".............", -- 3 "..ata...ata..", -- 4 "..wxy...wxy..", -- 5 "..aza...aza..", -- 6 ".............", -- 7 ".............", -- 8 -- Level 7 ".............", -- 0 ".............", -- 1 ".............", -- 2 ".............", -- 3 "..a.a...a.a..", -- 4 "...A.....A...", -- 5 "..a.a...a.a..", -- 6 ".............", -- 7 ".............", -- 8 -- Level 8 ".............", -- 0 ".............", -- 1 ".............", -- 2 ".............", -- 3 "..ccc...ccc..", -- 4 "..cBc...cBc..", -- 5 "..ccc...ccc..", -- 6 ".............", -- 7 ".............", -- 8 -- Level 9 ".............", -- 0 ".............", -- 1 ".............", -- 2 ".............", -- 3 "..v.v...v.v..", -- 4 ".............", -- 5 "..v.v...v.v..", -- 6 ".............", -- 7 ".............", -- 8 }, }, -- Temple { OriginData = { ExportName = "Well", Name = "Desert 90", GalleryName = "Desert", GalleryIndex = "90", ID = "631", CreatorName = "STR_Warrior", }, Size = { x = 7, y = 21, z = 7, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 6, MaxY = 20, MaxZ = 6, }, Connectors = { { Type = 2, RelX = 3, RelY = 16, RelZ = 6, Direction = 3, -- Z+ }, { Type = 2, RelX = 0, RelY = 16, RelZ = 3, Direction = 4, -- X- }, { Type = 2, RelX = 3, RelY = 16, RelZ = 0, Direction = 2, -- Z- }, { Type = 2, RelX = 6, RelY = 16, RelZ = 3, Direction = 5, -- X+ }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "None", ["IsStarting"] = "1", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", ["VerticalStrategy"] = "TerrainOrOceanTop|-16", }, BlockDefinitions = { ".: 0: 0", -- air "a: 1: 0", -- stone "b: 24: 2", -- sandstone "c: 24: 0", -- sandstone "d: 8: 0", -- water "e: 4: 0", -- cobblestone "f: 13: 0", -- gravel "g:128: 1", -- sandstonestairs "h: 44: 1", -- stone_slab "i:128: 0", -- sandstonestairs "j:128: 3", -- sandstonestairs "k:128: 2", -- sandstonestairs "l: 44: 9", -- stone_slab "m: 19: 0", -- sponge "n:126: 0", -- woodenslab }, BlockData = { -- Level 0 "mmmmmmm", -- 0 "maaaaam", -- 1 "maaaaam", -- 2 "maaaaam", -- 3 "maaaaam", -- 4 "maaaaam", -- 5 "mmmmmmm", -- 6 -- Level 1 "mmmmmmm", -- 0 "mbcccbm", -- 1 "mcdddcm", -- 2 "mcdddcm", -- 3 "mcdddcm", -- 4 "mbcccbm", -- 5 "mmmmmmm", -- 6 -- Level 2 "mmmmmmm", -- 0 "mbcccbm", -- 1 "mcdddcm", -- 2 "mcdddcm", -- 3 "mcdddcm", -- 4 "mbcccbm", -- 5 "mmmmmmm", -- 6 -- Level 3 "mmmmmmm", -- 0 "mbcccbm", -- 1 "mcdddcm", -- 2 "mcdddcm", -- 3 "mcdddcm", -- 4 "mbcccbm", -- 5 "mmmmmmm", -- 6 -- Level 4 "mmmmmmm", -- 0 "mbcccbm", -- 1 "mcdddcm", -- 2 "mcdddcm", -- 3 "mcdddcm", -- 4 "mbcccbm", -- 5 "mmmmmmm", -- 6 -- Level 5 "mmmmmmm", -- 0 "mbcccbm", -- 1 "mcdddcm", -- 2 "mcdddcm", -- 3 "mcdddcm", -- 4 "mbcccbm", -- 5 "mmmmmmm", -- 6 -- Level 6 "mmmmmmm", -- 0 "mbcccbm", -- 1 "mcdddcm", -- 2 "mcdddcm", -- 3 "mcdddcm", -- 4 "mbcccbm", -- 5 "mmmmmmm", -- 6 -- Level 7 "mmmmmmm", -- 0 "mbcccbm", -- 1 "mcdddcm", -- 2 "mcdddcm", -- 3 "mcdddcm", -- 4 "mbcccbm", -- 5 "mmmmmmm", -- 6 -- Level 8 "mmmmmmm", -- 0 "mbcccbm", -- 1 "mcdddcm", -- 2 "mcdddcm", -- 3 "mcdddcm", -- 4 "mbcccbm", -- 5 "mmmmmmm", -- 6 -- Level 9 "mmmmmmm", -- 0 "mbcccbm", -- 1 "mcdddcm", -- 2 "mcdddcm", -- 3 "mcdddcm", -- 4 "mbcccbm", -- 5 "mmmmmmm", -- 6 -- Level 10 "mmmmmmm", -- 0 "mbcccbm", -- 1 "mcdddcm", -- 2 "mcdddcm", -- 3 "mcdddcm", -- 4 "mbcccbm", -- 5 "mmmmmmm", -- 6 -- Level 11 "mmmmmmm", -- 0 "mbcccbm", -- 1 "mcdddcm", -- 2 "mcdddcm", -- 3 "mcdddcm", -- 4 "mbcccbm", -- 5 "mmmmmmm", -- 6 -- Level 12 "mmmmmmm", -- 0 "mbcccbm", -- 1 "mcdddcm", -- 2 "mcdddcm", -- 3 "mcdddcm", -- 4 "mbcccbm", -- 5 "mmmmmmm", -- 6 -- Level 13 "mmmmmmm", -- 0 "mbcccbm", -- 1 "mcdddcm", -- 2 "mcdddcm", -- 3 "mcdddcm", -- 4 "mbcccbm", -- 5 "mmmmmmm", -- 6 -- Level 14 "mmeeemm", -- 0 "mbcccbm", -- 1 "ecdddce", -- 2 "ecdddce", -- 3 "ecdddce", -- 4 "mbcccbm", -- 5 "mmeeemm", -- 6 -- Level 15 "mmfffmm", -- 0 "mbcccbm", -- 1 "fcdddcf", -- 2 "fcdddcf", -- 3 "fcdddcf", -- 4 "mbcccbm", -- 5 "mmfffmm", -- 6 -- Level 16 "mm...mm", -- 0 "mbghibm", -- 1 ".j...j.", -- 2 ".h...h.", -- 3 ".k...k.", -- 4 "mbghibm", -- 5 "mm...mm", -- 6 -- Level 17 "mm...mm", -- 0 "mb...bm", -- 1 ".......", -- 2 ".......", -- 3 ".......", -- 4 "mb...bm", -- 5 "mm...mm", -- 6 -- Level 18 "mm...mm", -- 0 "mblllbm", -- 1 ".l...l.", -- 2 ".l...l.", -- 3 ".l...l.", -- 4 "mblllbm", -- 5 "mm...mm", -- 6 -- Level 19 "mm...mm", -- 0 "mcccccm", -- 1 ".cnnnc.", -- 2 ".cnnnc.", -- 3 ".cnnnc.", -- 4 "mcccccm", -- 5 "mm...mm", -- 6 -- Level 20 "mm...mm", -- 0 "mh.h.hm", -- 1 ".......", -- 2 ".h...h.", -- 3 ".......", -- 4 "mh.h.hm", -- 5 "mm...mm", -- 6 }, }, -- Well { OriginData = { ExportName = "BlackSmith", Name = "Desert 97", GalleryName = "Desert", GalleryIndex = "97", ID = "642", CreatorName = "STR_Warrior", }, Size = { x = 11, y = 6, z = 13, }, Hitbox = { MinX = -1, MinY = 0, MinZ = 0, MaxX = 11, MaxY = 5, MaxZ = 13, }, Connectors = { { Type = -1, RelX = 8, RelY = 2, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "50", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a: 24: 2", -- sandstone "b: 4: 0", -- cobblestone "c: 24: 0", -- sandstone "d: 13: 0", -- gravel "e: 5: 0", -- planks "f: 12: 0", -- sand "g: 64: 3", -- woodendoorblock "h: 43: 0", -- doublestoneslab "i: 53: 5", -- woodstairs "j: 53: 4", -- woodstairs "k: 10: 0", -- lava "l: 54: 5", -- chest "m: 19: 0", -- sponge "n: 64: 9", -- woodendoorblock "o: 50: 3", -- torch "p:101: 0", -- ironbars "q: 50: 1", -- torch "r: 50: 2", -- torch "s:128: 2", -- sandstonestairs "t: 44: 9", -- stone_slab "u:126: 8", -- woodenslab "v:128: 4", -- sandstonestairs "w:128: 5", -- sandstonestairs "x:128: 7", -- sandstonestairs "y: 44: 1", -- stone_slab "z: 43: 1", -- doublestoneslab }, BlockData = { -- Level 0 "mmmmmmabbba", -- 0 "mmmmmmbbbbm", -- 1 "mmmmmmaccca", -- 2 "maccccccccc", -- 3 "mcccccccccc", -- 4 "mcccccccccc", -- 5 "mcccccacccc", -- 6 "mcccccacccc", -- 7 "acccaaacccc", -- 8 "ccccccccccc", -- 9 "ccccccccccc", -- 10 "ccccccccccc", -- 11 "accccccccca", -- 12 -- Level 1 "mmmmmmaddda", -- 0 "mmmmmmddddm", -- 1 "mmmmmmaceca", -- 2 "mafcfcceeec", -- 3 "mcfccfceeec", -- 4 "mcccccceeec", -- 5 "mcffaaaeeec", -- 6 "mffcaaaeeec", -- 7 "acccaaaeeec", -- 8 "ceeeeeeeeec", -- 9 "ceeeeeeeeec", -- 10 "ceeeeeeeeec", -- 11 "accccccccca", -- 12 -- Level 2 "mmmmmma...a", -- 0 "mmmmmm.....", -- 1 "mmmmmmacgca", -- 2 "ma....c...c", -- 3 "m.h...c...c", -- 4 "m.....c...c", -- 5 "m...aac...c", -- 6 "mij.akc...c", -- 7 "accccca...c", -- 8 "cl........c", -- 9 "c.........c", -- 10 "c.........c", -- 11 "accccccccca", -- 12 -- Level 3 "mmmmmma...a", -- 0 "mmmmmm.....", -- 1 "mmmmmmacnca", -- 2 "ma....c..oc", -- 3 "m.....p...c", -- 4 "m.....c...c", -- 5 "m...ppc...p", -- 6 "m...p.c...p", -- 7 "accccca...p", -- 8 "cq........c", -- 9 "p.........c", -- 10 "c........rc", -- 11 "acccpppccca", -- 12 -- Level 4 "mmmmmms...s", -- 0 "mmmmmmc...c", -- 1 "mmmmmmaccca", -- 2 "mattttcuuuc", -- 3 "mtuuuuvuuuc", -- 4 "mtuuuucuuuc", -- 5 "mtuuaacuuuw", -- 6 "mtuua.cuuuw", -- 7 "acccccauuuw", -- 8 "cuuuuuuuuuc", -- 9 "vuuuuuuuuuc", -- 10 "cuuuuuuuuuc", -- 11 "acccxxxccca", -- 12 -- Level 5 "mmmmmm.....", -- 0 "mmmmmm.....", -- 1 "mmmmmmcyyyc", -- 2 "my.y.yy...y", -- 3 "m.....y...y", -- 4 "my....y...y", -- 5 "m...zyz...y", -- 6 "my..y.y...c", -- 7 "cyyyzyc...y", -- 8 "y.........y", -- 9 "y.........y", -- 10 "y.........y", -- 11 "cyyyycyyyyc", -- 12 }, }, -- BlackSmith { OriginData = { ExportName = "LittleHouse8", Name = "Desert 99", GalleryName = "Desert", GalleryIndex = "99", ID = "739", CreatorName = "STR_Warrior", }, Size = { x = 9, y = 6, z = 9, }, Hitbox = { MinX = 0, MinY = 0, MinZ = -1, MaxX = 9, MaxY = 5, MaxZ = 9, }, Connectors = { { Type = -1, RelX = 0, RelY = 2, RelZ = 2, Direction = 4, -- X- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 24: 2", -- sandstone "b: 24: 0", -- sandstone "c: 4: 0", -- cobblestone "d: 13: 0", -- gravel "e: 5: 0", -- planks "f: 64: 2", -- woodendoorblock "g: 65: 2", -- ladder "h:101: 0", -- ironbars "i: 64: 9", -- woodendoorblock "j: 50: 1", -- torch "k:128: 6", -- sandstonestairs "l:126: 8", -- woodenslab "m: 19: 0", -- sponge "n:128: 5", -- sandstonestairs "o:128: 4", -- sandstonestairs "p:128: 7", -- sandstonestairs "q: 44: 1", -- stone_slab "r: 96: 2", -- trapdoor }, BlockData = { -- Level 0 "mmmmabbba", -- 0 "ccccbbbbb", -- 1 "ccccbbbbb", -- 2 "ccccbbbbb", -- 3 "abbbabbbb", -- 4 "bbbbbbbbb", -- 5 "bbbbbbbbb", -- 6 "bbbbbbbbb", -- 7 "abbbbbbba", -- 8 -- Level 1 "mmmmabbba", -- 0 "ddddbeeeb", -- 1 "ddddeeeeb", -- 2 "ddddbeeeb", -- 3 "abbbaeeeb", -- 4 "beeeeeeeb", -- 5 "beeeeeeeb", -- 6 "beeeeeeeb", -- 7 "abbbbbbba", -- 8 -- Level 2 "mmmmabbba", -- 0 "....b...b", -- 1 "....f...b", -- 2 "....b...b", -- 3 "abbba...b", -- 4 "b.......b", -- 5 "b.......b", -- 6 "b......gb", -- 7 "abbbbbbba", -- 8 -- Level 3 "mmmmabhba", -- 0 "....b...b", -- 1 "....i...b", -- 2 "....b...h", -- 3 "abhbaj..h", -- 4 "b.......h", -- 5 "h.......b", -- 6 "b......gb", -- 7 "abbhhhbba", -- 8 -- Level 4 "mmmmabkba", -- 0 "....blllb", -- 1 "....blllb", -- 2 "....bllln", -- 3 "abkballln", -- 4 "bllllllln", -- 5 "olllllllb", -- 6 "bllllllgb", -- 7 "abbpppbba", -- 8 -- Level 5 "mmmmbqbqb", -- 0 "....q...q", -- 1 "....q...q", -- 2 "....q...q", -- 3 "bqqqb...b", -- 4 "q.......q", -- 5 "b.......q", -- 6 "q......rq", -- 7 "bqqqbqqqb", -- 8 }, }, -- LittleHouse8 }, -- Pieces } ================================================ FILE: Server/Prefabs/Villages/JapaneseVillage.cubeset ================================================ -- JapaneseVillage.cubeset -- Defines the prefabs in the group JapaneseVillage -- NOTE: This file has been generated automatically by GalExport! -- Any manual changes will be overwritten by the next automatic export! Cubeset = { Metadata = { CubesetFormatVersion = 1, ExportDate = "2016-11-30 13:45:59", ["AllowedBiomes"] = "Plains, Savanna, SavannaM, SunflowerPlains", ["IntendedUse"] = "Village", }, Pieces = { { OriginData = { ExportName = "Restaurant", Name = "Plains 61", GalleryName = "Plains", GalleryIndex = "61", ID = "117", CreatorName = "Aloe_vera", }, Size = { x = 15, y = 10, z = 15, }, Hitbox = { MinX = -1, MinY = 0, MinZ = -1, MaxX = 14, MaxY = 9, MaxZ = 15, }, Connectors = { { Type = -1, RelX = 14, RelY = 1, RelZ = 7, Direction = 5, -- X+ }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 5: 2", -- planks "b:135: 0", -- whitewoodstairs "c:135: 2", -- whitewoodstairs "d:135: 1", -- whitewoodstairs "e: 17: 9", -- tree "f:135: 3", -- whitewoodstairs "g: 85: 0", -- fence "h: 17: 1", -- tree "i:171: 0", -- carpet "j:171:12", -- carpet "k:126: 1", -- woodenslab "l: 50: 5", -- torch "m: 19: 0", -- sponge "n: 35: 0", -- wool "o: 50: 3", -- torch "p: 50: 1", -- torch "q: 50: 4", -- torch "r: 35:14", -- wool "s: 44: 8", -- stone_slab "t: 43: 0", -- doublestoneslab "u: 44: 0", -- stone_slab "v: 17: 5", -- tree }, BlockData = { -- Level 0 "mmmmaaaaaaammmm", -- 0 "maaaaaaaaaaaaam", -- 1 "maaaaaaaaaaaaam", -- 2 "maaaaaaaaaaaaam", -- 3 "aaaaaaaaaaaaaaa", -- 4 "aaaaaaaaaaaaaaa", -- 5 "aaaaaaaaaaaaaaa", -- 6 "aaaaaaaaaaaaaaa", -- 7 "aaaaaaaaaaaaaaa", -- 8 "aaaaaaaaaaaaaaa", -- 9 "aaaaaaaaaaaaaaa", -- 10 "maaaaaaaaaaaaam", -- 11 "maaaaaaaaaaaaam", -- 12 "maaaaaaaaaaaaam", -- 13 "mmmmaaaaaaammmm", -- 14 -- Level 1 "....bcccccd....", -- 0 ".aaaaaaaaaaaaa.", -- 1 ".aaaaaaaaaaaaa.", -- 2 ".aaaaaaaaaaaaa.", -- 3 "caaaaaaaaaaaaac", -- 4 "baaaaaaaaaaaaad", -- 5 "baaaaaaaaaaaaad", -- 6 "baaaaaaaaaaeaad", -- 7 "baaaaaaaaaaaaad", -- 8 "baaaaaaaaaaaaad", -- 9 "faaaaaaaaaaaaaf", -- 10 ".aaaaaaaaaaaaa.", -- 11 ".aaaaaaaaaaaaa.", -- 12 ".aaaaaaaaaaaaa.", -- 13 "....bfffffd....", -- 14 -- Level 2 "...............", -- 0 ".gggg.....gggg.", -- 1 ".g...........g.", -- 2 ".g.hhhhhhhhh.g.", -- 3 ".g.hiiijiiih.g.", -- 4 "...hikijikih...", -- 5 "...hiiijiiihg..", -- 6 "...hjjjjjjj....", -- 7 "...hiiijiiihg..", -- 8 "...hikijikih...", -- 9 ".g.hiiijiiih.g.", -- 10 ".g.hhhhhhhhh.g.", -- 11 ".g...........g.", -- 12 ".gggg.....gggg.", -- 13 "...............", -- 14 -- Level 3 "...............", -- 0 ".l..g.....g..l.", -- 1 "...............", -- 2 "...hnnnhnnnh...", -- 3 ".g.n.......n.g.", -- 4 "...n.......n...", -- 5 "...n.......hl..", -- 6 "...h...........", -- 7 "...n.......hl..", -- 8 "...n.......n...", -- 9 ".g.n.......n.g.", -- 10 "...hnnnhnnnh...", -- 11 "...............", -- 12 ".l..g.....g..l.", -- 13 "...............", -- 14 -- Level 4 "...............", -- 0 "....g.....g....", -- 1 "...............", -- 2 "...hn.nhn.nh...", -- 3 ".g.n...o...n.g.", -- 4 "...n.......n...", -- 5 "...n.......h...", -- 6 "...hp......e...", -- 7 "...n.......h...", -- 8 "...n.......n...", -- 9 ".g.n...q...n.g.", -- 10 "...hn.nhn.nh...", -- 11 "...............", -- 12 "....g.....g....", -- 13 "...............", -- 14 -- Level 5 "...............", -- 0 "....g.....g....", -- 1 "....ggggggg....", -- 2 "...hnnnhnnnh...", -- 3 ".ggn.......ngg.", -- 4 "..gn.......ng..", -- 5 "..gn.......hg..", -- 6 "..gh..r.r..ng..", -- 7 "..gn.......hg..", -- 8 "..gn.......ng..", -- 9 ".ggn.......ngg.", -- 10 "...hnnnhnnnh...", -- 11 "....ggggggg....", -- 12 "....g.....g....", -- 13 "...............", -- 14 -- Level 6 "...............", -- 0 "...stuuuuuts...", -- 1 "..sttttttttts..", -- 2 ".sthvvvhvvvhts.", -- 3 ".tte.......ett.", -- 4 ".ute.......etu.", -- 5 ".ute.......htu.", -- 6 ".uth..g.g..etu.", -- 7 ".ute.......htu.", -- 8 ".ute.......etu.", -- 9 ".tte.......ett.", -- 10 ".sthvvvhvvvhts.", -- 11 "..sttttttttts..", -- 12 "...stuuuuuts...", -- 13 "...............", -- 14 -- Level 7 "...............", -- 0 ".stu.......uts.", -- 1 ".tu.........ut.", -- 2 ".u.uuuuuuuuu.u.", -- 3 "...utttttttu...", -- 4 "...utttttttu...", -- 5 "...utttttttu...", -- 6 "...utttttttu...", -- 7 "...utttttttu...", -- 8 "...utttttttu...", -- 9 "...utttttttu...", -- 10 ".u.uuuuuuuuu.u.", -- 11 ".tu.........ut.", -- 12 ".stu.......uts.", -- 13 "...............", -- 14 -- Level 8 "...............", -- 0 ".u...........u.", -- 1 "...............", -- 2 "...............", -- 3 "...............", -- 4 ".....uuuuu.....", -- 5 ".....utttu.....", -- 6 ".....utttu.....", -- 7 ".....utttu.....", -- 8 ".....uuuuu.....", -- 9 "...............", -- 10 "...............", -- 11 "...............", -- 12 ".u...........u.", -- 13 "...............", -- 14 -- Level 9 "...............", -- 0 "...............", -- 1 "...............", -- 2 "...............", -- 3 "...............", -- 4 "...............", -- 5 "...............", -- 6 ".......u.......", -- 7 "...............", -- 8 "...............", -- 9 "...............", -- 10 "...............", -- 11 "...............", -- 12 "...............", -- 13 "...............", -- 14 }, }, -- Restaurant { OriginData = { ExportName = "HouseMid", Name = "Plains 62", GalleryName = "Plains", GalleryIndex = "62", ID = "119", CreatorName = "Aloe_vera", }, Size = { x = 10, y = 9, z = 9, }, Hitbox = { MinX = 0, MinY = 0, MinZ = -1, MaxX = 10, MaxY = 8, MaxZ = 9, }, Connectors = { { Type = -1, RelX = 0, RelY = 1, RelZ = 4, Direction = 4, -- X- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 5: 2", -- planks "b:135: 2", -- whitewoodstairs "c:135: 0", -- whitewoodstairs "d: 17: 9", -- tree "e:135: 3", -- whitewoodstairs "f: 85: 0", -- fence "g: 17: 1", -- tree "h:171: 0", -- carpet "i: 50: 5", -- torch "j: 35: 0", -- wool "k: 17: 5", -- tree "l:124: 0", -- redstonelampon "m: 19: 0", -- sponge "n: 69: 9", -- lever "o: 44: 8", -- stone_slab "p: 43: 0", -- doublestoneslab "q: 44: 0", -- stone_slab }, BlockData = { -- Level 0 "maaaaaaaaa", -- 0 "maaaaaaaaa", -- 1 "aaaaaaaaaa", -- 2 "aaaaaaaaaa", -- 3 "aaaaaaaaaa", -- 4 "aaaaaaaaaa", -- 5 "aaaaaaaaaa", -- 6 "maaaaaaaaa", -- 7 "maaaaaaaaa", -- 8 -- Level 1 ".aaaaaaaaa", -- 0 ".aaaaaaaaa", -- 1 "baaaaaaaaa", -- 2 "caaaaaaaaa", -- 3 "caadaaaaaa", -- 4 "caaaaaaaaa", -- 5 "eaaaaaaaaa", -- 6 ".aaaaaaaaa", -- 7 ".aaaaaaaaa", -- 8 -- Level 2 ".fffffffff", -- 0 ".f.......f", -- 1 ".f.ggggg.f", -- 2 "...ghhhg.f", -- 3 "....hhhg.f", -- 4 "...ghhhg.f", -- 5 ".f.ggggg.f", -- 6 ".f.......f", -- 7 ".fffffffff", -- 8 -- Level 3 ".....i...i", -- 0 "..........", -- 1 ".i.jjgjj..", -- 2 "...g...j..", -- 3 ".......g.i", -- 4 "...g...j..", -- 5 ".i.jjgjj..", -- 6 "..........", -- 7 ".....i...i", -- 8 -- Level 4 "..........", -- 0 "..........", -- 1 "...jjgjj..", -- 2 "...g...j..", -- 3 "...j...g..", -- 4 "...g...j..", -- 5 "...jjgjj..", -- 6 "..........", -- 7 "..........", -- 8 -- Level 5 "..........", -- 0 "...f...f..", -- 1 "..fgkgkgf.", -- 2 "..fd...d..", -- 3 "...d.lng..", -- 4 "..fd...d..", -- 5 "..fgkgkgf.", -- 6 "...f...f..", -- 7 "..........", -- 8 -- Level 6 "...ooooo..", -- 0 "..opppppo.", -- 1 ".opgjjjgpo", -- 2 ".opjgggjpo", -- 3 ".opjgggjpo", -- 4 ".opjgggjpo", -- 5 ".opgjjjgpo", -- 6 "..opppppo.", -- 7 "...ooooo..", -- 8 -- Level 7 ".opq...qpo", -- 0 ".pq.....qp", -- 1 ".q.qqqqq.q", -- 2 "...qpppq..", -- 3 "...qpppq..", -- 4 "...qpppq..", -- 5 ".q.qqqqq.q", -- 6 ".pq.....qp", -- 7 ".opq...qpo", -- 8 -- Level 8 ".q.......q", -- 0 "..........", -- 1 "..........", -- 2 "..........", -- 3 ".....q....", -- 4 "..........", -- 5 "..........", -- 6 "..........", -- 7 ".q.......q", -- 8 }, }, -- HouseMid { OriginData = { ExportName = "HouseWide", Name = "Plains 64", GalleryName = "Plains", GalleryIndex = "64", ID = "121", CreatorName = "STR_Warrior", }, Size = { x = 11, y = 6, z = 11, }, Hitbox = { MinX = -1, MinY = 0, MinZ = -1, MaxX = 11, MaxY = 5, MaxZ = 10, }, Connectors = { { Type = -1, RelX = 5, RelY = 1, RelZ = 10, Direction = 3, -- Z+ }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 5: 2", -- planks "b: 17: 1", -- tree "c: 35: 0", -- wool "d:171: 0", -- carpet "e:126: 1", -- woodenslab "f: 64: 1", -- woodendoorblock "g: 85: 0", -- fence "h: 50: 1", -- torch "i: 50: 2", -- torch "j: 64: 9", -- woodendoorblock "k:126:11", -- woodenslab "l: 17: 5", -- tree "m: 19: 0", -- sponge "n:126: 3", -- woodenslab "o:125: 3", -- woodendoubleslab "p: 5: 3", -- planks }, BlockData = { -- Level 0 "mmmmmmmmmmm", -- 0 "mmaaaaaaamm", -- 1 "maaaaaaaaam", -- 2 "maaaaaaaaam", -- 3 "maaaaaaaaam", -- 4 "maaaaaaaaam", -- 5 "maaaaaaaaam", -- 6 "maaaaaaaaam", -- 7 "maaaaaaaaam", -- 8 "mmaaaaaaamm", -- 9 "mmmmmmmmmmm", -- 10 -- Level 1 "...........", -- 0 "..bcbcbcb..", -- 1 ".b.d.....b.", -- 2 ".cded....c.", -- 3 ".bded....b.", -- 4 ".c.d.....c.", -- 5 ".b.......b.", -- 6 ".c.......c.", -- 7 ".b.......b.", -- 8 "..bcbfbcb..", -- 9 "...........", -- 10 -- Level 2 "...........", -- 0 "..bgbgbgb..", -- 1 ".b.......b.", -- 2 ".g.......g.", -- 3 ".bh.....ib.", -- 4 ".g.......g.", -- 5 ".b.......b.", -- 6 ".g.......g.", -- 7 ".b.......b.", -- 8 "..bgbjbgb..", -- 9 "...........", -- 10 -- Level 3 "...kkkkk...", -- 0 "..bcbcbcb..", -- 1 ".b.......b.", -- 2 "kc.......ck", -- 3 "kb.......bk", -- 4 "kc.......ck", -- 5 "kb.......bk", -- 6 "kc.......ck", -- 7 ".b.......b.", -- 8 "..bcblbcb..", -- 9 "...kkkkk...", -- 10 -- Level 4 ".kn.....nk.", -- 0 "konnnnnnnok", -- 1 "nnnnnnnnnnn", -- 2 ".nnpppppnn.", -- 3 ".nnpkkkpnn.", -- 4 ".nnpkkkpnn.", -- 5 ".nnpkkkpnn.", -- 6 ".nnpppppnn.", -- 7 "nnnnnnnnnnn", -- 8 "kknnnnnnnok", -- 9 ".kn.....nk.", -- 10 -- Level 5 "n.........n", -- 0 "...........", -- 1 "...........", -- 2 "...........", -- 3 "....nnn....", -- 4 "....non....", -- 5 "....nnn....", -- 6 "...........", -- 7 "...........", -- 8 "...........", -- 9 "n.........n", -- 10 }, }, -- HouseWide { OriginData = { ExportName = "HouseWithGarden", Name = "Plains 67", GalleryName = "Plains", GalleryIndex = "67", ID = "130", CreatorName = "Aloe_vera", }, Size = { x = 16, y = 9, z = 16, }, Hitbox = { MinX = -1, MinY = 0, MinZ = 0, MaxX = 16, MaxY = 8, MaxZ = 16, }, Connectors = { { Type = -1, RelX = 9, RelY = 2, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 3: 0", -- dirt "b: 5: 2", -- planks "c: 2: 0", -- grass "d:113: 0", -- netherbrickfence "e: 17: 1", -- tree "f: 35: 0", -- wool "g:126: 2", -- woodenslab "h: 31: 2", -- tallgrass "i:125: 2", -- woodendoubleslab "j: 38: 3", -- rose "k: 38: 2", -- rose "l: 38: 1", -- rose "m: 19: 0", -- sponge "n: 17: 2", -- tree "o: 50: 4", -- torch "p: 85: 0", -- fence "q:140: 0", -- flowerpotblock "r: 50: 3", -- torch "s: 44: 8", -- stone_slab "t: 50: 1", -- torch "u: 50: 2", -- torch "v: 43: 0", -- doublestoneslab "w: 44: 0", -- stone_slab "x: 18: 2", -- leaves }, BlockData = { -- Level 0 "mmmmmmmmmaammmmm", -- 0 "aabbbbbbbbbbaaam", -- 1 "aabbbbbbbbbbaaam", -- 2 "aabbbbbbbbbbaaam", -- 3 "aabbbbbbbbbbaaam", -- 4 "aabbbbbbbbbbaaam", -- 5 "aabbbbbbbbbbaaam", -- 6 "aabbbbbbbbbbaaam", -- 7 "aabbbbbbbbbbaaam", -- 8 "aabbbbbbbbbbaaam", -- 9 "aaaaaaaaaaaaaaam", -- 10 "aaaaaaaaaaaaaaam", -- 11 "aaaaaaaaaaaaaaam", -- 12 "aaaaaaaaaaaaaaam", -- 13 "aaaaaaaaaaaaaaam", -- 14 "mmmmmmmmmmmmmmmm", -- 15 -- Level 1 "mmmmmmmmmccmmmmm", -- 0 "aabbbbbbbbbbaacm", -- 1 "acbbbbbbbbbbccam", -- 2 "acbbbbbbbbbbcaam", -- 3 "acbbbbbbbbbbccam", -- 4 "acbbbbbbbbbbaacm", -- 5 "acbbbbbbbbbbcaam", -- 6 "acbbbbbbbbbbccam", -- 7 "acbbbbbbbbbbccam", -- 8 "acbbbbbbbbbbcaam", -- 9 "acccccccccccccam", -- 10 "aaaaaccaacccacam", -- 11 "acacaccacaccccam", -- 12 "accaaccaccaccaam", -- 13 "cccaccccaccacaam", -- 14 "mmmmmmmmmmmmmmmm", -- 15 -- Level 2 "................", -- 0 "ddeffeffe..eddd.", -- 1 "d.fbbgggg..f..d.", -- 2 "d.fbgggggggf.hd.", -- 3 "d.fbgggggggf..d.", -- 4 "d.eggggggggehhd.", -- 5 "d.fgiiggiigf.hd.", -- 6 "d.fgiiggiigf..d.", -- 7 "d.fggggggggf..d.", -- 8 "d.efffeefffe.hd.", -- 9 "d.............d.", -- 10 "djhhk.jhh..hh.d.", -- 11 "d.jlk.hj.h....d.", -- 12 "d..jh.hh..h..nd.", -- 13 "ddddddddddddddd.", -- 14 "................", -- 15 -- Level 3 "........o..o....", -- 0 "..eppeffe..e....", -- 1 "..pqq......p....", -- 2 "..pq.......p....", -- 3 "..pq.......p....", -- 4 "..e........e....", -- 5 "..p........p....", -- 6 "..p........p....", -- 7 "..p........p....", -- 8 "..epppeepppe....", -- 9 "......rr........", -- 10 "................", -- 11 "................", -- 12 ".............n..", -- 13 "................", -- 14 "................", -- 15 -- Level 4 "..ssssssssss....", -- 0 ".seffeffeffes...", -- 1 ".sf..r.....fs...", -- 2 ".sf........fs...", -- 3 ".sf........fs...", -- 4 ".set......ues...", -- 5 ".sf........fs...", -- 6 ".sf........fs...", -- 7 ".sf........fs...", -- 8 ".sefffeefffes...", -- 9 "..ssssssssss....", -- 10 "................", -- 11 "................", -- 12 ".............n..", -- 13 "................", -- 14 "................", -- 15 -- Level 5 ".vw........wv...", -- 0 ".wwwwwwwwwwww...", -- 1 "..wvvvvvvvvw....", -- 2 "..wvvvvvvvvw....", -- 3 "..wvvvvvvvvw....", -- 4 "..wvvvvvvvvw....", -- 5 "..wvvvvvvvvw....", -- 6 "..wvvvvvvvvw....", -- 7 "..wvvvvvvvvw....", -- 8 ".wwwwwwwwwwww...", -- 9 ".vw........wv...", -- 10 "............xxx.", -- 11 "...........xxxxx", -- 12 "...........xxnxx", -- 13 "...........xxxxx", -- 14 "............xxx.", -- 15 -- Level 6 "................", -- 0 "................", -- 1 "................", -- 2 "....wwwwww......", -- 3 "....wvvvvw......", -- 4 "....wvvvvw......", -- 5 "....wvvvvw......", -- 6 "....wwwwww......", -- 7 "................", -- 8 "................", -- 9 "................", -- 10 "............xxx.", -- 11 "...........xxxxx", -- 12 "...........xxnxx", -- 13 "...........xxxxx", -- 14 "............xxx.", -- 15 -- Level 7 "................", -- 0 "................", -- 1 "................", -- 2 "................", -- 3 "................", -- 4 "......ww........", -- 5 "................", -- 6 "................", -- 7 "................", -- 8 "................", -- 9 "................", -- 10 "................", -- 11 "............xxx.", -- 12 "............xnx.", -- 13 "............xx..", -- 14 "................", -- 15 -- Level 8 "................", -- 0 "................", -- 1 "................", -- 2 "................", -- 3 "................", -- 4 "................", -- 5 "................", -- 6 "................", -- 7 "................", -- 8 "................", -- 9 "................", -- 10 "................", -- 11 ".............x..", -- 12 "............xxx.", -- 13 ".............x..", -- 14 "................", -- 15 }, }, -- HouseWithGarden { OriginData = { ExportName = "HouseSmall", Name = "Plains 68", GalleryName = "Plains", GalleryIndex = "68", ID = "131", CreatorName = "Aloe_vera", }, Size = { x = 7, y = 6, z = 7, }, Hitbox = { MinX = -1, MinY = 0, MinZ = 0, MaxX = 7, MaxY = 5, MaxZ = 7, }, Connectors = { { Type = -1, RelX = 4, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 5: 2", -- planks "b: 17: 1", -- tree "c: 35: 0", -- wool "d: 50: 4", -- torch "e: 85: 0", -- fence "f: 44: 8", -- stone_slab "g: 43: 0", -- doublestoneslab "h: 44: 0", -- stone_slab "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "mmmmmmm", -- 0 "maaaaam", -- 1 "maaaaam", -- 2 "maaaaam", -- 3 "maaaaam", -- 4 "maaaaam", -- 5 "mmmmmmm", -- 6 -- Level 1 ".......", -- 0 ".bcc.b.", -- 1 ".c...c.", -- 2 ".c...c.", -- 3 ".c...c.", -- 4 ".bcccb.", -- 5 ".......", -- 6 -- Level 2 ".....d.", -- 0 ".bee.b.", -- 1 ".c...c.", -- 2 ".e...e.", -- 3 ".c...c.", -- 4 ".beeeb.", -- 5 ".......", -- 6 -- Level 3 ".fffff.", -- 0 "fbcccbf", -- 1 "fc...cf", -- 2 "fc...cf", -- 3 "fc...cf", -- 4 "fbcccbf", -- 5 ".fffff.", -- 6 -- Level 4 "gh...hg", -- 0 "hhhhhhh", -- 1 ".hgggh.", -- 2 ".hgggh.", -- 3 ".hgggh.", -- 4 "hhhhhhh", -- 5 "gh...hg", -- 6 -- Level 5 ".......", -- 0 ".......", -- 1 ".......", -- 2 "...h...", -- 3 ".......", -- 4 ".......", -- 5 ".......", -- 6 }, }, -- HouseSmall { OriginData = { ExportName = "HighTemple", Name = "Plains 70", GalleryName = "Plains", GalleryIndex = "70", ID = "133", CreatorName = "Aloe_vera", }, Size = { x = 11, y = 19, z = 11, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 10, MaxY = 18, MaxZ = 10, }, Connectors = { { Type = 2, RelX = 0, RelY = 1, RelZ = 5, Direction = 4, -- X- }, { Type = 2, RelX = 5, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, { Type = 2, RelX = 10, RelY = 1, RelZ = 5, Direction = 5, -- X+ }, { Type = 2, RelX = 5, RelY = 1, RelZ = 10, Direction = 3, -- Z+ }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "1", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", ["VerticalStrategy"] = "TerrainOrOceanTop|-1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 5: 2", -- planks "b:135: 0", -- whitewoodstairs "c:135: 2", -- whitewoodstairs "d:135: 1", -- whitewoodstairs "e: 17: 9", -- tree "f:135: 3", -- whitewoodstairs "g: 85: 0", -- fence "h: 17: 1", -- tree "i:171: 0", -- carpet "j: 50: 5", -- torch "k: 35: 0", -- wool "l: 17: 5", -- tree "m: 19: 0", -- sponge "n:124: 0", -- redstonelampon "o: 69: 9", -- lever "p: 44: 8", -- stone_slab "q: 43: 0", -- doublestoneslab "r: 44: 0", -- stone_slab "s: 50: 4", -- torch "t: 50: 1", -- torch "u: 50: 3", -- torch }, BlockData = { -- Level 0 "mmmaaaaammm", -- 0 "maaaaaaaaam", -- 1 "maaaaaaaaam", -- 2 "aaaaaaaaaaa", -- 3 "aaaaaaaaaaa", -- 4 "aaaaaaaaaaa", -- 5 "aaaaaaaaaaa", -- 6 "aaaaaaaaaaa", -- 7 "maaaaaaaaam", -- 8 "maaaaaaaaam", -- 9 "mmmaaaaammm", -- 10 -- Level 1 "...bcccd...", -- 0 ".aaaaaaaaa.", -- 1 ".aaaaaaaaa.", -- 2 "caaaaaaaaac", -- 3 "baaaaaaaaad", -- 4 "baaeaaaaaad", -- 5 "baaaaaaaaad", -- 6 "faaaaaaaaaf", -- 7 ".aaaaaaaaa.", -- 8 ".aaaaaaaaa.", -- 9 "...bfffd...", -- 10 -- Level 2 "...........", -- 0 ".ggg...ggg.", -- 1 ".g.......g.", -- 2 ".g.hhhhh.g.", -- 3 "...hiiih...", -- 4 "....iiih...", -- 5 "...hiiih...", -- 6 ".g.hhhhh.g.", -- 7 ".g.......g.", -- 8 ".ggg...ggg.", -- 9 "...........", -- 10 -- Level 3 "...........", -- 0 ".j.g...g.j.", -- 1 "...........", -- 2 ".g.kkhkk.g.", -- 3 "...h...k...", -- 4 ".......h...", -- 5 "...h...k...", -- 6 ".g.kkhkk.g.", -- 7 "...........", -- 8 ".j.g...g.j.", -- 9 "...........", -- 10 -- Level 4 "...........", -- 0 "...g...g...", -- 1 "...........", -- 2 ".g.kkhkk.g.", -- 3 "...h...k...", -- 4 "...k...h...", -- 5 "...h...k...", -- 6 ".g.kkhkk.g.", -- 7 "...........", -- 8 "...g...g...", -- 9 "...........", -- 10 -- Level 5 "...........", -- 0 "...g...g...", -- 1 "...ggggg...", -- 2 ".gghlhlhgg.", -- 3 "..ge...eg..", -- 4 "..ge.nohg..", -- 5 "..ge...eg..", -- 6 ".gghlhlhgg.", -- 7 "...ggggg...", -- 8 "...g...g...", -- 9 "...........", -- 10 -- Level 6 "...........", -- 0 "..pqrrrqp..", -- 1 ".pqqqqqqqp.", -- 2 ".qqhkkkhqq.", -- 3 ".rqkhhhkqr.", -- 4 ".rqkhhhkqr.", -- 5 ".rqkhhhkqr.", -- 6 ".qqhkkkhqq.", -- 7 ".pqqqqqqqp.", -- 8 "..pqrrrqp..", -- 9 "...........", -- 10 -- Level 7 "...........", -- 0 ".qr.....rq.", -- 1 ".........r.", -- 2 "...hhhhh...", -- 3 "...hiiih...", -- 4 "....iiih...", -- 5 "...hiiih...", -- 6 "...hhhhh...", -- 7 ".r.......r.", -- 8 ".qr.....rq.", -- 9 "...........", -- 10 -- Level 8 "...........", -- 0 "...........", -- 1 "...........", -- 2 "...kkhkk...", -- 3 "...h...k...", -- 4 ".......h...", -- 5 "...h...k...", -- 6 "...kkhkk...", -- 7 "...........", -- 8 "...........", -- 9 "...........", -- 10 -- Level 9 "...........", -- 0 "...........", -- 1 ".....s.....", -- 2 "...kkhkk...", -- 3 "...h...k...", -- 4 "...k...ht..", -- 5 "...h...k...", -- 6 "...kkhkk...", -- 7 ".....u.....", -- 8 "...........", -- 9 "...........", -- 10 -- Level 10 "...........", -- 0 "...........", -- 1 "...ggggg...", -- 2 "..ghlhlhg..", -- 3 "..ge...eg..", -- 4 "..ge.nohg..", -- 5 "..ge...eg..", -- 6 "..ghlhlhg..", -- 7 "...ggggg...", -- 8 "...........", -- 9 "...........", -- 10 -- Level 11 "...........", -- 0 "..prrrrrp..", -- 1 ".pqqqqqqqp.", -- 2 ".qqhkkkhqq.", -- 3 ".rqkhhhkqr.", -- 4 ".rqkhhhkqr.", -- 5 ".rqkhhhkqr.", -- 6 ".qqhkkkhqr.", -- 7 ".pqqqqqqqp.", -- 8 "..pqrrrqp..", -- 9 "...........", -- 10 -- Level 12 "...........", -- 0 ".qr.....rq.", -- 1 ".r.......r.", -- 2 "...hhhhh...", -- 3 "...hiiih...", -- 4 "....iiih...", -- 5 "...hiiih...", -- 6 "...hhhhh...", -- 7 ".r.......r.", -- 8 ".qr.....rq.", -- 9 "...........", -- 10 -- Level 13 "...........", -- 0 "...........", -- 1 "...........", -- 2 "...kkhkk...", -- 3 "...h...k...", -- 4 ".......h...", -- 5 "...h...k...", -- 6 "...kkhkk...", -- 7 "...........", -- 8 "...........", -- 9 "...........", -- 10 -- Level 14 "...........", -- 0 "...........", -- 1 ".....s.....", -- 2 "...kkhkk...", -- 3 "...h...k...", -- 4 "...k...ht..", -- 5 "...h...k...", -- 6 "...kkhkk...", -- 7 ".....u.....", -- 8 "...........", -- 9 "...........", -- 10 -- Level 15 "...........", -- 0 "...........", -- 1 "...ggggg...", -- 2 "..ghlhlhg..", -- 3 "..ge...eg..", -- 4 "..ge.nohg..", -- 5 "..ge...eg..", -- 6 "..ghlhlhg..", -- 7 "...ggggg...", -- 8 "...........", -- 9 "...........", -- 10 -- Level 16 "...........", -- 0 "..pqrrrqp..", -- 1 ".pqqqqqqqp.", -- 2 ".qqrrrrrqq.", -- 3 ".rqrrrrrqr.", -- 4 ".rqrrrrrqr.", -- 5 ".rqrrrrrqr.", -- 6 ".qqrrrrrqq.", -- 7 ".pqqqqqqqp.", -- 8 "..pqrrrqp..", -- 9 "...........", -- 10 -- Level 17 "...........", -- 0 ".qr.....rq.", -- 1 ".rr.....rr.", -- 2 "...rrrrr...", -- 3 "...rqqqr...", -- 4 "...rqqqr...", -- 5 "...rqqqr...", -- 6 "...rrrrr...", -- 7 ".rr.....rr.", -- 8 ".qr.....rq.", -- 9 "...........", -- 10 -- Level 18 "...........", -- 0 "...........", -- 1 "...........", -- 2 "...........", -- 3 "...........", -- 4 ".....r.....", -- 5 "...........", -- 6 "...........", -- 7 "...........", -- 8 "...........", -- 9 "...........", -- 10 }, }, -- HighTemple { OriginData = { ExportName = "HouseSmallDouble", Name = "Plains 72", GalleryName = "Plains", GalleryIndex = "72", ID = "135", CreatorName = "Aloe_vera", }, Size = { x = 11, y = 6, z = 7, }, Hitbox = { MinX = -1, MinY = 0, MinZ = 0, MaxX = 11, MaxY = 5, MaxZ = 7, }, Connectors = { { Type = -1, RelX = 4, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 5: 2", -- planks "b: 17: 1", -- tree "c: 35: 0", -- wool "d:171:12", -- carpet "e:135: 1", -- whitewoodstairs "f:126: 2", -- woodenslab "g:135: 2", -- whitewoodstairs "h: 50: 4", -- torch "i: 85: 0", -- fence "j: 44: 8", -- stone_slab "k: 43: 0", -- doublestoneslab "l: 44: 0", -- stone_slab "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "mmmmmmmmmmm", -- 0 "maaaaaaaaam", -- 1 "maaaaaaaaam", -- 2 "maaaaaaaaam", -- 3 "maaaaaaaaam", -- 4 "maaaaaaaaam", -- 5 "mmmmmmmmmmm", -- 6 -- Level 1 "...........", -- 0 ".bcc.bcccb.", -- 1 ".cddd.dddc.", -- 2 ".ceddcdfdc.", -- 3 ".cggdcdddc.", -- 4 ".bcccbcccb.", -- 5 "...........", -- 6 -- Level 2 ".h...h...h.", -- 0 ".bii.biiib.", -- 1 ".c.......c.", -- 2 ".i...i...i.", -- 3 ".c...i...c.", -- 4 ".biiibiiib.", -- 5 "...........", -- 6 -- Level 3 ".jjjjjjjjj.", -- 0 "jbiiibiiibj", -- 1 "jc.......cj", -- 2 "jc...c...cj", -- 3 "jc...c...cj", -- 4 "jbcccbcccbj", -- 5 ".jjjjjjjjj.", -- 6 -- Level 4 "kl...l...lk", -- 0 "lllllllllll", -- 1 ".lkkklkkkl.", -- 2 ".lkjklkkkl.", -- 3 ".lkkklkkkl.", -- 4 "lllllllllll", -- 5 "kl...l...lk", -- 6 -- Level 5 "...........", -- 0 "...........", -- 1 "...........", -- 2 "...l...l...", -- 3 "...........", -- 4 "...........", -- 5 "...........", -- 6 }, }, -- HouseSmallDouble { OriginData = { ExportName = "HouseWithSpa", Name = "Plains 73", GalleryName = "Plains", GalleryIndex = "73", ID = "139", CreatorName = "Aloe_vera", }, Size = { x = 16, y = 8, z = 14, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 15, MaxY = 7, MaxZ = 13, }, Connectors = { }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 5: 2", -- planks "b: 3: 0", -- dirt "c: 2: 0", -- grass "d: 8: 0", -- water "e:135: 3", -- whitewoodstairs "f:135: 1", -- whitewoodstairs "g:113: 0", -- netherbrickfence "h: 17: 1", -- tree "i: 35: 0", -- wool "j:171:12", -- carpet "k: 64: 6", -- woodendoorblock "l:126: 2", -- woodenslab "m: 19: 0", -- sponge "n:135: 2", -- whitewoodstairs "o: 64: 7", -- woodendoorblock "p: 50: 4", -- torch "q: 85: 0", -- fence "r: 64:12", -- woodendoorblock "s: 50: 3", -- torch "t: 44: 8", -- stone_slab "u: 43: 0", -- doublestoneslab "v: 44: 0", -- stone_slab }, BlockData = { -- Level 0 "................", -- 0 ".aaaaaaaaaaaaaa.", -- 1 ".aaaaaaaaaaaaaa.", -- 2 ".aaaaaaaaaaaaaa.", -- 3 ".aaaaaaaaaaaaaa.", -- 4 ".aaaaaaaaaaaaaa.", -- 5 ".aaaaaaaaaaaaaa.", -- 6 ".aaaaaabbbbbbbbb", -- 7 ".aaaaaabbbbbbbbb", -- 8 ".aaaaaabbbbbbbbb", -- 9 ".aaaaaabbbbbbbbb", -- 10 ".aaaaaabbbbbbbbb", -- 11 ".aaaaaabbbbbbbbb", -- 12 ".......bbbbbbbbb", -- 13 -- Level 1 "mmmmmmmmmmmmmmmm", -- 0 "maaaaaaaaaaaaaam", -- 1 "maaaaaaaaaaaaaam", -- 2 "maaaaaaaaaaaaaam", -- 3 "maaaaaaaaaaaaaam", -- 4 "maaaaaaaaaaaaaam", -- 5 "maaaaaaaaaaaaaam", -- 6 "maaaaaaaaaaccccc", -- 7 "maaaaaaacccccccc", -- 8 "maaaaaaacccccccc", -- 9 "maaaaaaacccccccc", -- 10 "maaaaaaccccccccc", -- 11 "maaaaaaccccccccc", -- 12 "mmmmmmmccccccccc", -- 13 -- Level 2 "................", -- 0 ".aaaaaaaaaaaaaa.", -- 1 ".aaaaaaaaaaaaaa.", -- 2 ".aaaaaaaaaaaaaa.", -- 3 ".aaaaaaaaaaaaaa.", -- 4 ".aaaaaaaaaaaaaa.", -- 5 ".aaddaaaaaaaaaa.", -- 6 ".aaddaaeeef.....", -- 7 ".aaddaaf........", -- 8 ".aaddaaf........", -- 9 ".aaddaae........", -- 10 ".aaddaa.........", -- 11 ".aaaaaa.........", -- 12 "................", -- 13 -- Level 3 "................", -- 0 ".ggggghiiihiiih.", -- 1 ".geee.ijjjjjjji.", -- 2 ".gf...kjjjijlji.", -- 3 ".gf...innjijjji.", -- 4 ".g....hiiohiiih.", -- 5 ".g....g.........", -- 6 ".g..............", -- 7 ".g..............", -- 8 ".g..............", -- 9 ".g....g.........", -- 10 ".g....g.........", -- 11 ".gggggg.........", -- 12 "................", -- 13 -- Level 4 "......p...p...p.", -- 0 ".g....hqqqhqqqh.", -- 1 "......i.......i.", -- 2 "......r...q...q.", -- 3 "......i...q...i.", -- 4 "......hqqrhqqqh.", -- 5 "......g...s.....", -- 6 "................", -- 7 "................", -- 8 "................", -- 9 "................", -- 10 "................", -- 11 ".g....g.........", -- 12 "................", -- 13 -- Level 5 ".tttttttttttttt.", -- 0 "tggggghqqqhqqqht", -- 1 "tg....i.......it", -- 2 "tg....i...i...it", -- 3 "tg....i...i...it", -- 4 "tg....hiiihiiiht", -- 5 "tg....gtttttttt.", -- 6 "tg....gt........", -- 7 "tg....gt........", -- 8 "tg....gt........", -- 9 "tg....gt........", -- 10 "tg....gt........", -- 11 "tggggggt........", -- 12 ".tttttt.........", -- 13 -- Level 6 "uv............vu", -- 0 "vvvvvvvvvvvvvvvv", -- 1 ".vuuuuuuuuuuuuv.", -- 2 ".vuuuuuutuuuuuv.", -- 3 ".vuuuuuuuuuuuuv.", -- 4 ".vuuuuvvvvvvvvvv", -- 5 ".vuuuuv.......vu", -- 6 ".vuuuuv.........", -- 7 ".vuuuuv.........", -- 8 ".vuuuuv.........", -- 9 ".vuuuuv.........", -- 10 ".vuuuuv.........", -- 11 "vvvvvvvv........", -- 12 "uv....vu........", -- 13 -- Level 7 "................", -- 0 "................", -- 1 "................", -- 2 "...vvvvvvvvvv...", -- 3 "...vv...........", -- 4 "...vv...........", -- 5 "...vv...........", -- 6 "...vv...........", -- 7 "...vv...........", -- 8 "...vv...........", -- 9 "...vv...........", -- 10 "................", -- 11 "................", -- 12 "................", -- 13 }, }, -- HouseWithSpa { OriginData = { ExportName = "HouseWithSakura1", Name = "Plains 75", GalleryName = "Plains", GalleryIndex = "75", ID = "141", CreatorName = "Aloe_vera", }, Size = { x = 13, y = 7, z = 15, }, Hitbox = { MinX = -1, MinY = 0, MinZ = 0, MaxX = 13, MaxY = 6, MaxZ = 15, }, Connectors = { { Type = -1, RelX = 5, RelY = 2, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 3: 0", -- dirt "b: 2: 0", -- grass "c: 17: 5", -- tree "d: 5: 2", -- planks "e: 17: 9", -- tree "f:113: 0", -- netherbrickfence "g: 17: 1", -- tree "h: 35: 0", -- wool "i: 31: 2", -- tallgrass "j: 54: 2", -- chest "k: 38: 6", -- rose "l: 38: 2", -- rose "m: 19: 0", -- sponge "n: 50: 4", -- torch "o: 85: 0", -- fence "p: 44: 8", -- stone_slab "q: 35: 6", -- wool "r: 43: 0", -- doublestoneslab "s: 44: 0", -- stone_slab }, BlockData = { -- Level 0 "aaaaaaaaaaaaa", -- 0 "aaaaaaaaaaaaa", -- 1 "aaaaaaaaaaaaa", -- 2 "aaaaaaaaaaaaa", -- 3 "aaaaaaaaaaaaa", -- 4 "aaaaaaaaaaaaa", -- 5 "aaaaaaaaaaaaa", -- 6 "aaaaaaaaaaaaa", -- 7 "aaaaaaaaaaaaa", -- 8 "aaaaaaaaaaaaa", -- 9 "aaaaaaaaaaaaa", -- 10 "aaaaaaaaaaaaa", -- 11 "aaaaaaaaaaaaa", -- 12 "aaaaaaaaaaaaa", -- 13 "aaaaaaaaaaaaa", -- 14 -- Level 1 "aaaabbbaaaaaa", -- 0 "abbbbbbbbbbba", -- 1 "abbaccdabbaba", -- 2 "abbedddebbaba", -- 3 "abbedddebbbba", -- 4 "aabedddebbaba", -- 5 "abbacccabbbbb", -- 6 "abbbbbbbbbaba", -- 7 "aaabbbbbbbbba", -- 8 "ababbbbabbbba", -- 9 "aababbabbbaba", -- 10 "ababbbbabbbba", -- 11 "ababbbbbbbbba", -- 12 "abbbbbbbbbbba", -- 13 "bbbbbbbbbbbbb", -- 14 -- Level 2 "ffff...ffffff", -- 0 "f...........f", -- 1 "f..ghh.g..i.f", -- 2 "f..h...h..i.f", -- 3 "f..h...h....f", -- 4 "fi.h..jh..i.f", -- 5 "f..ghhhg....f", -- 6 "f.........i.f", -- 7 "fii.........f", -- 8 "f.k..k.i....f", -- 9 "fl.i..i...g.f", -- 10 "f.i..i.k....f", -- 11 "f.l.k.......f", -- 12 "f.....l.....f", -- 13 "fffffffffffff", -- 14 -- Level 3 ".............", -- 0 ".......n.....", -- 1 "...goo.g.....", -- 2 "...h...h.....", -- 3 "...o...o.....", -- 4 "...h...h.....", -- 5 "...gooog.....", -- 6 ".............", -- 7 ".............", -- 8 ".............", -- 9 "..........g..", -- 10 ".............", -- 11 ".............", -- 12 ".............", -- 13 ".............", -- 14 -- Level 4 ".............", -- 0 "...ppppp.....", -- 1 "..pghhhgp....", -- 2 "..ph...hp....", -- 3 "..ph...hp....", -- 4 "..ph...hp....", -- 5 "..pghhhgp....", -- 6 "...ppppp.....", -- 7 ".............", -- 8 "..........q..", -- 9 ".........qgq.", -- 10 "..........q..", -- 11 ".............", -- 12 ".............", -- 13 ".............", -- 14 -- Level 5 ".............", -- 0 "..rs...sr....", -- 1 "..sssssss....", -- 2 "...srrrs.....", -- 3 "...srrrs.....", -- 4 "...srrrs.....", -- 5 "..sssssss....", -- 6 "..rs...sr....", -- 7 ".............", -- 8 ".........qqq.", -- 9 ".........qqq.", -- 10 ".........qqq.", -- 11 ".............", -- 12 ".............", -- 13 ".............", -- 14 -- Level 6 ".............", -- 0 ".............", -- 1 ".............", -- 2 ".............", -- 3 ".....s.......", -- 4 ".............", -- 5 ".............", -- 6 ".............", -- 7 ".............", -- 8 ".............", -- 9 "..........q..", -- 10 ".............", -- 11 ".............", -- 12 ".............", -- 13 ".............", -- 14 }, }, -- HouseWithSakura1 { OriginData = { ExportName = "SakuraDouble", Name = "Plains 76", GalleryName = "Plains", GalleryIndex = "76", ID = "142", CreatorName = "Aloe_vera", }, Size = { x = 12, y = 8, z = 6, }, Hitbox = { MinX = -1, MinY = 0, MinZ = -1, MaxX = 12, MaxY = 7, MaxZ = 6, }, Connectors = { { Type = -1, RelX = -1, RelY = 2, RelZ = 2, Direction = 4, -- X- }, { Type = 3, RelX = 5, RelY = 2, RelZ = 6, Direction = 3, -- Z+ }, { Type = -3, RelX = 6, RelY = 2, RelZ = -1, Direction = 2, -- Z- }, { Type = -3, RelX = 12, RelY = 2, RelZ = 2, Direction = 5, -- X+ }, { Type = 3, RelX = 12, RelY = 2, RelZ = 2, Direction = 5, -- X+ }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 3: 0", -- dirt "b: 2: 0", -- grass "c: 17: 1", -- tree "d: 35: 6", -- wool "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "aaaaaaaaaaaa", -- 0 "aaaaaaaaaaaa", -- 1 "aaaaaaaaaaaa", -- 2 "aaaaaaaaaaaa", -- 3 "aaaaaaaaaaaa", -- 4 "aaaaaaaaaaaa", -- 5 -- Level 1 "bbbbbbbbbbbb", -- 0 "bbbbbbbbbbbb", -- 1 "bbabbbbbbbbb", -- 2 "bbbbbbbbbabb", -- 3 "bbbbbbbbbbbb", -- 4 "bbbbbbbbbbbb", -- 5 -- Level 2 "............", -- 0 "............", -- 1 "..c.........", -- 2 ".........c..", -- 3 "............", -- 4 "............", -- 5 -- Level 3 "............", -- 0 "............", -- 1 "..c.........", -- 2 ".........c..", -- 3 "............", -- 4 "............", -- 5 -- Level 4 "..d.........", -- 0 "ddddd.......", -- 1 "ddcdd...ddd.", -- 2 "ddddd...dcd.", -- 3 "..d.....ddd.", -- 4 "............", -- 5 -- Level 5 ".ddd........", -- 0 ".ddd....ddd.", -- 1 "ddddd..ddddd", -- 2 ".ddd...ddcdd", -- 3 ".ddd...ddddd", -- 4 "........ddd.", -- 5 -- Level 6 "............", -- 0 "..d......d..", -- 1 ".ddd....ddd.", -- 2 "..d....ddddd", -- 3 "........ddd.", -- 4 ".........d..", -- 5 -- Level 7 "............", -- 0 "............", -- 1 "............", -- 2 ".........d..", -- 3 "............", -- 4 "............", -- 5 }, }, -- SakuraDouble { OriginData = { ExportName = "Forge", Name = "Plains 79", GalleryName = "Plains", GalleryIndex = "79", ID = "145", CreatorName = "Aloe_vera", }, Size = { x = 16, y = 11, z = 14, }, Hitbox = { MinX = 0, MinY = 0, MinZ = -1, MaxX = 16, MaxY = 10, MaxZ = 14, }, Connectors = { { Type = -1, RelX = 0, RelY = 1, RelZ = 3, Direction = 4, -- X- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 4: 0", -- cobblestone "b: 17: 1", -- tree "c: 67: 0", -- stonestairs "d: 5: 2", -- planks "e: 67: 2", -- stonestairs "f:113: 0", -- netherbrickfence "g:118: 2", -- cauldronblock "h: 67: 6", -- stonestairs "i: 67: 4", -- stonestairs "j: 87: 0", -- netherstone "k: 67: 7", -- stonestairs "l: 54: 5", -- chest "m: 19: 0", -- sponge "n: 61: 2", -- furnace "o:101: 0", -- ironbars "p: 51: 0", -- fire "q: 50: 4", -- torch "r: 50: 2", -- torch "s: 35: 0", -- wool "t: 67: 3", -- stonestairs "u: 50: 3", -- torch "v: 44: 8", -- stone_slab "w: 43: 0", -- doublestoneslab "x: 44: 0", -- stone_slab "y: 17: 5", -- tree "z: 17: 9", -- tree }, BlockData = { -- Level 0 "mmmmmmmmmmmmmmmm", -- 0 "mmmmmmmmmmmmmmmm", -- 1 "mmaaaaaaaaaaaamm", -- 2 "mmaaaaaaaaaaaamm", -- 3 "mmaaaaaaaaaaaamm", -- 4 "mmaaaaaaaaaaaamm", -- 5 "mmaaaaaaaaaaaamm", -- 6 "mmaaaaaaaaaaaamm", -- 7 "mmaaaaaaaaaaaamm", -- 8 "mmaaaaaaaaaaaamm", -- 9 "mmaaaaaaaaaaaamm", -- 10 "mmaaaaaaaaaaaamm", -- 11 "mmmmmmmmmmmmmmmm", -- 12 "mmmmmmmmmmmmmmmm", -- 13 -- Level 1 "................", -- 0 "................", -- 1 ".....bbbbbbbbb..", -- 2 ".....cdddddddb..", -- 3 ".....cddaaaadb..", -- 4 "..beeedaaaaadb..", -- 5 "..bddddaaaaadb..", -- 6 "..bddddaaaaadb..", -- 7 "..bddddaaaaadb..", -- 8 "..bddddaaaaadb..", -- 9 "..bddddddddddb..", -- 10 "..bbbbbbbbbbbb..", -- 11 "................", -- 12 "................", -- 13 -- Level 2 "................", -- 0 "................", -- 1 ".....bfffbfffb..", -- 2 ".............a..", -- 3 ".............a..", -- 4 "..b.....ghh..a..", -- 5 "..f.....haa..b..", -- 6 "..f.....ija..b..", -- 7 "..f.....kaa..a..", -- 8 "..f..........a..", -- 9 "..fl.........a..", -- 10 "..bffffbbffffb..", -- 11 "................", -- 12 "................", -- 13 -- Level 3 "................", -- 0 "................", -- 1 ".....bfffbfffb..", -- 2 ".............a..", -- 3 ".............a..", -- 4 "..b......nn..a..", -- 5 "..f.....oaa..b..", -- 6 "..f.....opa..b..", -- 7 "..f.....oaa..a..", -- 8 "..f..........a..", -- 9 "..f..........a..", -- 10 "..bffffbbffffb..", -- 11 "................", -- 12 "................", -- 13 -- Level 4 "................", -- 0 ".........q...q..", -- 1 "....rbsssbsssb..", -- 2 ".............a..", -- 3 "..q..........a..", -- 4 "..b......ce..a..", -- 5 "..s......ea..b..", -- 6 "..s......aa..b..", -- 7 "..s......ta..a..", -- 8 "..s..........a..", -- 9 "..s..........a..", -- 10 ".rbssssbbssssb..", -- 11 "..u....uu....u..", -- 12 "................", -- 13 -- Level 5 ".vwxxxxxxxxxxwv.", -- 0 "vvvvvvvvvvvvvvvv", -- 1 "wvbyybyyybbyybvw", -- 2 "xvz..........zvx", -- 3 "xvz..........zvx", -- 4 "xvb..........zvx", -- 5 "xvz.......a..bvx", -- 6 "xvz......ca..bvx", -- 7 "xvz.......a..zvx", -- 8 "xvz..........zvx", -- 9 "xvz..........zvx", -- 10 "wvbyyyyyyyyyybvw", -- 11 "vvvvvvvvvvvvvvvv", -- 12 ".vwxxxxxxxxxxwv.", -- 13 -- Level 6 "wx............xw", -- 0 "x..............x", -- 1 "..xxxxxxxxxxxx..", -- 2 "..xwwwwwwwwwwx..", -- 3 "..xwvvvvvvvvvx..", -- 4 "..xwv.......vx..", -- 5 "..xwv.....a.vx..", -- 6 "..xwv.....a.vx..", -- 7 "..xwv.....a.vx..", -- 8 "..xwvvvvvvvvvx..", -- 9 "..xwwwwwwwwwwx..", -- 10 "..xxxxxxxxxxxx..", -- 11 "x..............x", -- 12 "wx............xw", -- 13 -- Level 7 "................", -- 0 "................", -- 1 "................", -- 2 "................", -- 3 "....xxxxxxxx....", -- 4 "....xxxxxxxx....", -- 5 "....xwwwwwax....", -- 6 "....xwvvvvax....", -- 7 "....xwwwwwax....", -- 8 "....xxxxxxxx....", -- 9 "................", -- 10 "................", -- 11 "................", -- 12 "................", -- 13 -- Level 8 "................", -- 0 "................", -- 1 "................", -- 2 "................", -- 3 "................", -- 4 "................", -- 5 "..........a.....", -- 6 ".......xx.a.....", -- 7 "..........a.....", -- 8 "................", -- 9 "................", -- 10 "................", -- 11 "................", -- 12 "................", -- 13 -- Level 9 "................", -- 0 "................", -- 1 "................", -- 2 "................", -- 3 "................", -- 4 "................", -- 5 "..........a.....", -- 6 "..........a.....", -- 7 "..........a.....", -- 8 "................", -- 9 "................", -- 10 "................", -- 11 "................", -- 12 "................", -- 13 -- Level 10 "................", -- 0 "................", -- 1 "................", -- 2 "................", -- 3 "................", -- 4 "................", -- 5 "..........a.....", -- 6 "..........a.....", -- 7 "..........a.....", -- 8 "................", -- 9 "................", -- 10 "................", -- 11 "................", -- 12 "................", -- 13 }, }, -- Forge { OriginData = { ExportName = "HouseSmallWithDoor", Name = "Plains 112", GalleryName = "Plains", GalleryIndex = "112", ID = "264", CreatorName = "Aloe_vera", }, Size = { x = 7, y = 6, z = 7, }, Hitbox = { MinX = -1, MinY = 0, MinZ = 0, MaxX = 7, MaxY = 5, MaxZ = 7, }, Connectors = { { Type = -1, RelX = 3, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 5: 2", -- planks "b: 17: 1", -- tree "c: 35: 0", -- wool "d: 64: 3", -- woodendoorblock "e: 50: 4", -- torch "f: 64: 9", -- woodendoorblock "g: 85: 0", -- fence "h: 44: 8", -- stone_slab "i: 43: 0", -- doublestoneslab "j: 44: 0", -- stone_slab "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "mmmmmmm", -- 0 "maaaaam", -- 1 "maaaaam", -- 2 "maaaaam", -- 3 "maaaaam", -- 4 "maaaaam", -- 5 "mmmmmmm", -- 6 -- Level 1 ".......", -- 0 ".bcdcb.", -- 1 ".c...c.", -- 2 ".c...c.", -- 3 ".c...c.", -- 4 ".bcccb.", -- 5 ".......", -- 6 -- Level 2 ".....e.", -- 0 ".bcfcb.", -- 1 ".g...g.", -- 2 ".g...g.", -- 3 ".g...g.", -- 4 ".bgggb.", -- 5 ".......", -- 6 -- Level 3 ".hhhhh.", -- 0 "hbcccbh", -- 1 "hc...ch", -- 2 "hc...ch", -- 3 "hc...ch", -- 4 "hbcccbh", -- 5 ".hhhhh.", -- 6 -- Level 4 "ij...ji", -- 0 "jjjjjjj", -- 1 ".jiiij.", -- 2 ".jiiij.", -- 3 ".jiiij.", -- 4 "jjjjjjj", -- 5 "ij...ji", -- 6 -- Level 5 ".......", -- 0 ".......", -- 1 ".......", -- 2 "...j...", -- 3 ".......", -- 4 ".......", -- 5 ".......", -- 6 }, }, -- HouseSmallWithDoor { OriginData = { ExportName = "HouseSmallDblWithDoor", Name = "Plains 113", GalleryName = "Plains", GalleryIndex = "113", ID = "265", CreatorName = "Aloe_vera", }, Size = { x = 11, y = 6, z = 7, }, Hitbox = { MinX = -1, MinY = 0, MinZ = 0, MaxX = 11, MaxY = 5, MaxZ = 7, }, Connectors = { { Type = -1, RelX = 3, RelY = 1, RelZ = -1, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 5: 2", -- planks "b: 17: 9", -- tree "c: 17: 1", -- tree "d: 35: 0", -- wool "e: 64: 3", -- woodendoorblock "f:171:12", -- carpet "g:135: 1", -- whitewoodstairs "h:126: 2", -- woodenslab "i:135: 2", -- whitewoodstairs "j: 50: 4", -- torch "k: 64: 9", -- woodendoorblock "l: 85: 0", -- fence "m: 19: 0", -- sponge "n: 44: 8", -- stone_slab "o: 43: 0", -- doublestoneslab "p: 44: 0", -- stone_slab }, BlockData = { -- Level 0 "mmmmmmmmmmm", -- 0 "maaaaaaaaam", -- 1 "maaaabaaaam", -- 2 "maaaabaaaam", -- 3 "maaaabaaaam", -- 4 "maaaaaaaaam", -- 5 "mmmmmmmmmmm", -- 6 -- Level 1 "...........", -- 0 ".cdedcdddc.", -- 1 ".dfff.fffd.", -- 2 ".dgffdfhfd.", -- 3 ".diifdfffd.", -- 4 ".cdddcdddc.", -- 5 "...........", -- 6 -- Level 2 ".j...j...j.", -- 0 ".cdkdclllc.", -- 1 ".d.......l.", -- 2 ".l...l...l.", -- 3 ".d...l...l.", -- 4 ".clllclllc.", -- 5 "...........", -- 6 -- Level 3 ".nnnnnnnnn.", -- 0 "ncdddcdddcn", -- 1 "nd...d...dn", -- 2 "nd...d...dn", -- 3 "nd...d...dn", -- 4 "ncdddcdddcn", -- 5 ".nnnnnnnnn.", -- 6 -- Level 4 "op.......po", -- 0 "ppppppppppp", -- 1 ".pooooooop.", -- 2 ".ponndnnop.", -- 3 ".pooooooop.", -- 4 "ppppppppppp", -- 5 "op.......po", -- 6 -- Level 5 "...........", -- 0 "...........", -- 1 "...........", -- 2 "...ppppp...", -- 3 "...........", -- 4 "...........", -- 5 "...........", -- 6 }, }, -- HouseSmallDblWithDoor { OriginData = { ExportName = "Well", Name = "Plains 143", GalleryName = "Plains", GalleryIndex = "143", ID = "487", CreatorName = "STR_Warrior", }, Size = { x = 7, y = 14, z = 7, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 6, MaxY = 13, MaxZ = 6, }, Connectors = { { Type = 2, RelX = 0, RelY = 9, RelZ = 3, Direction = 4, -- X- }, { Type = 2, RelX = 3, RelY = 9, RelZ = 0, Direction = 2, -- Z- }, { Type = 2, RelX = 6, RelY = 9, RelZ = 3, Direction = 5, -- X+ }, { Type = 2, RelX = 3, RelY = 9, RelZ = 6, Direction = 3, -- Z+ }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "1", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", ["VerticalStrategy"] = "TerrainOrOceanTop|-9", }, BlockDefinitions = { ".: 0: 0", -- air "a: 1: 0", -- stone "b: 4: 0", -- cobblestone "c: 8: 0", -- water "d: 13: 0", -- gravel "e: 67: 1", -- stonestairs "f: 67: 2", -- stonestairs "g: 67: 0", -- stonestairs "h: 67: 3", -- stonestairs "i: 85: 0", -- fence "j: 44: 8", -- stone_slab "k: 44: 0", -- stone_slab "l: 43: 0", -- doublestoneslab "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "mmmmmmm", -- 0 "maaaaam", -- 1 "maaaaam", -- 2 "maaaaam", -- 3 "maaaaam", -- 4 "maaaaam", -- 5 "mmmmmmm", -- 6 -- Level 1 "mmmmmmm", -- 0 "mbbbbbm", -- 1 "mbcc.bm", -- 2 "mbcccbm", -- 3 "mbcccbm", -- 4 "mbbbbbm", -- 5 "mmmmmmm", -- 6 -- Level 2 "mmmmmmm", -- 0 "mbbbbbm", -- 1 "mbcccbm", -- 2 "mbcccbm", -- 3 "mbcccbm", -- 4 "mbbbbbm", -- 5 "mmmmmmm", -- 6 -- Level 3 "mmmmmmm", -- 0 "mbbbbbm", -- 1 "mbcccbm", -- 2 "mbcccbm", -- 3 "mbcccbm", -- 4 "mbbbbbm", -- 5 "mmmmmmm", -- 6 -- Level 4 "mmmmmmm", -- 0 "mbbbbbm", -- 1 "mbcccbm", -- 2 "mbcccbm", -- 3 "mbcccbm", -- 4 "mbbbbbm", -- 5 "mmmmmmm", -- 6 -- Level 5 "mmmmmmm", -- 0 "mbbbbbm", -- 1 "mbcccbm", -- 2 "mbcccbm", -- 3 "mbcccbm", -- 4 "mbbbbbm", -- 5 "mmmmmmm", -- 6 -- Level 6 "mmmmmmm", -- 0 "mbbbbbm", -- 1 "mbcccbm", -- 2 "mbcccbm", -- 3 "mbcccbm", -- 4 "mbbbbbm", -- 5 "mmmmmmm", -- 6 -- Level 7 "mmbbbmm", -- 0 "mbbbbbm", -- 1 "bbcccbb", -- 2 "bbcccbb", -- 3 "bbcccbb", -- 4 "mbbbbbm", -- 5 "mmbbbmm", -- 6 -- Level 8 "mmdddmm", -- 0 "mbbbbbm", -- 1 "dbcccbd", -- 2 "dbcccbd", -- 3 "dbcccbd", -- 4 "mbbbbbm", -- 5 "mmdddmm", -- 6 -- Level 9 "mm...mm", -- 0 "mbefgbm", -- 1 ".h...h.", -- 2 ".g...e.", -- 3 ".f...f.", -- 4 "mbehgbm", -- 5 "mm...mm", -- 6 -- Level 10 "mm...mm", -- 0 "mi...im", -- 1 ".......", -- 2 ".......", -- 3 ".......", -- 4 "mi...im", -- 5 "mm...mm", -- 6 -- Level 11 "mm...mm", -- 0 "mi...im", -- 1 ".......", -- 2 ".......", -- 3 ".......", -- 4 "mi...im", -- 5 "mm...mm", -- 6 -- Level 12 "mjkkkjm", -- 0 "jlllllj", -- 1 "klllllk", -- 2 "klllllk", -- 3 "klllllk", -- 4 "jlllllj", -- 5 "mjkkkjm", -- 6 -- Level 13 "k.....k", -- 0 ".......", -- 1 "..kkk..", -- 2 "..klk..", -- 3 "..kkk..", -- 4 ".......", -- 5 "k.....k", -- 6 }, }, -- Well { OriginData = { ExportName = "Arch", Name = "Plains 144", GalleryName = "Plains", GalleryIndex = "144", ID = "488", CreatorName = "Aloe_vera", }, Size = { x = 11, y = 7, z = 5, }, Hitbox = { MinX = -1, MinY = 0, MinZ = 0, MaxX = 11, MaxY = 6, MaxZ = 4, }, Connectors = { { Type = 2, RelX = 5, RelY = 1, RelZ = 4, Direction = 3, -- Z+ }, { Type = 2, RelX = 5, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 2: 0", -- grass "b: 3: 0", -- dirt "c: 13: 0", -- gravel "d:113: 0", -- netherbrickfence "e: 50: 5", -- torch "f: 44: 8", -- stone_slab "g: 44: 0", -- stone_slab "h: 43: 0", -- doublestoneslab "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "aabacccaaaa", -- 0 "aabacccabaa", -- 1 "aabacccaaaa", -- 2 "aaaacccaaaa", -- 3 "aaaacccaaaa", -- 4 -- Level 1 "..d.....d..", -- 0 "..d.....d..", -- 1 "..d.....d..", -- 2 "..d.....d..", -- 3 "..d.....d..", -- 4 -- Level 2 "..d.....d..", -- 0 "...........", -- 1 "..d.....d..", -- 2 "...........", -- 3 "..d.....d..", -- 4 -- Level 3 "..e.....e..", -- 0 "...........", -- 1 "..d.....d..", -- 2 "...........", -- 3 "..e.....e..", -- 4 -- Level 4 "...fffff...", -- 0 "...........", -- 1 "..d.....d..", -- 2 "...........", -- 3 "...fffff...", -- 4 -- Level 5 "..g.....g..", -- 0 ".fhggggghf.", -- 1 ".fhfffffhf.", -- 2 ".fhggggghf.", -- 3 "..g.....g..", -- 4 -- Level 6 "...........", -- 0 "...........", -- 1 "hg.......gh", -- 2 "...........", -- 3 "...........", -- 4 }, }, -- Arch { OriginData = { ExportName = "SakuraSmall", Name = "Plains 145", GalleryName = "Plains", GalleryIndex = "145", ID = "489", CreatorName = "Aloe_vera", }, Size = { x = 5, y = 7, z = 5, }, Hitbox = { MinX = -1, MinY = 0, MinZ = -1, MaxX = 5, MaxY = 6, MaxZ = 5, }, Connectors = { { Type = -1, RelX = 2, RelY = 2, RelZ = -1, Direction = 2, -- Z- }, { Type = 3, RelX = 5, RelY = 2, RelZ = 2, Direction = 5, -- X+ }, { Type = -3, RelX = -1, RelY = 2, RelZ = 2, Direction = 4, -- X- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 3: 0", -- dirt "b: 2: 0", -- grass "c: 17: 1", -- tree "d: 35: 6", -- wool "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "aaaaa", -- 0 "aaaaa", -- 1 "aaaaa", -- 2 "aaaaa", -- 3 "aaaaa", -- 4 -- Level 1 "bbbbb", -- 0 "bbbbb", -- 1 "bbabb", -- 2 "bbbbb", -- 3 "bbbbb", -- 4 -- Level 2 ".....", -- 0 ".....", -- 1 "..c..", -- 2 ".....", -- 3 ".....", -- 4 -- Level 3 ".....", -- 0 ".....", -- 1 "..c..", -- 2 ".....", -- 3 ".....", -- 4 -- Level 4 "..d..", -- 0 "ddddd", -- 1 "ddcdd", -- 2 "ddddd", -- 3 "..d..", -- 4 -- Level 5 ".ddd.", -- 0 ".ddd.", -- 1 "ddddd", -- 2 ".ddd.", -- 3 ".ddd.", -- 4 -- Level 6 ".....", -- 0 "..d..", -- 1 ".ddd.", -- 2 "..d..", -- 3 ".....", -- 4 }, }, -- SakuraSmall { OriginData = { ExportName = "MediumSakuraTree", Name = "Plains 146", GalleryName = "Plains", GalleryIndex = "146", ID = "490", CreatorName = "STR_Warrior", }, Size = { x = 7, y = 10, z = 7, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 6, MaxY = 9, MaxZ = 6, }, Connectors = { { Type = -1, RelX = 3, RelY = 2, RelZ = 0, Direction = 2, -- Z- }, { Type = 3, RelX = 6, RelY = 2, RelZ = 3, Direction = 5, -- X+ }, { Type = -3, RelX = 0, RelY = 2, RelZ = 3, Direction = 4, -- X- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 3: 0", -- dirt "b: 2: 0", -- grass "c: 31: 1", -- tallgrass "d: 38: 7", -- rose "e: 17: 1", -- tree "f: 38: 0", -- rose "g: 38: 8", -- rose "h: 38: 5", -- rose "i: 35: 6", -- wool "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "aaaaaaa", -- 0 "aaaaaaa", -- 1 "aaaaaaa", -- 2 "aaaaaaa", -- 3 "aaaaaaa", -- 4 "aaaaaaa", -- 5 "aaaaaaa", -- 6 -- Level 1 "bbbbbbb", -- 0 "bbabbbb", -- 1 "bbabaab", -- 2 "bbbaabb", -- 3 "bbabaab", -- 4 "bbababb", -- 5 "bbbbbbb", -- 6 -- Level 2 "mm...mm", -- 0 "m.c...m", -- 1 ".dccdc.", -- 2 "..cefc.", -- 3 ".ccfgh.", -- 4 "m.ccc.m", -- 5 "mm...mm", -- 6 -- Level 3 "m.....m", -- 0 ".......", -- 1 ".......", -- 2 "...e...", -- 3 ".......", -- 4 ".......", -- 5 "m.....m", -- 6 -- Level 4 ".......", -- 0 "..i....", -- 1 ".......", -- 2 "...e.i.", -- 3 ".i.....", -- 4 ".......", -- 5 ".......", -- 6 -- Level 5 ".......", -- 0 "..i....", -- 1 "...i...", -- 2 "..ieii.", -- 3 ".i.ii..", -- 4 "...i...", -- 5 ".......", -- 6 -- Level 6 ".......", -- 0 "..ii...", -- 1 "..iii..", -- 2 ".iieii.", -- 3 ".iiii..", -- 4 "..iii..", -- 5 ".......", -- 6 -- Level 7 ".......", -- 0 "..iii..", -- 1 ".iiiii.", -- 2 ".iieii.", -- 3 ".iiiii.", -- 4 "..iii..", -- 5 ".......", -- 6 -- Level 8 ".......", -- 0 "...i...", -- 1 "..iiii.", -- 2 ".iiiii.", -- 3 "..iii..", -- 4 "...i...", -- 5 ".......", -- 6 -- Level 9 ".......", -- 0 ".......", -- 1 "...i...", -- 2 "..iii..", -- 3 "...i...", -- 4 ".......", -- 5 ".......", -- 6 }, }, -- MediumSakuraTree { OriginData = { ExportName = "Garden2", Name = "Plains 147", GalleryName = "Plains", GalleryIndex = "147", ID = "491", CreatorName = "Aloe_vera", }, Size = { x = 16, y = 5, z = 16, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 15, MaxY = 4, MaxZ = 15, }, Connectors = { { Type = -1, RelX = 12, RelY = 3, RelZ = 15, Direction = 3, -- Z+ }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 3: 0", -- dirt "b: 2: 0", -- grass "c: 8: 0", -- water "d: 17: 1", -- tree "e: 13: 0", -- gravel "f: 31: 2", -- tallgrass "g: 18: 5", -- leaves "h: 38: 7", -- rose "i: 17: 9", -- tree "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "aaaaaaaaaaaaaaaa", -- 0 "aaaaaaaaaaaaaaaa", -- 1 "aaaaaaaaaaaaaaaa", -- 2 "aaaaaaaaaaaaaaaa", -- 3 "aaaaaaaaaaaaaaaa", -- 4 "aaaaaaaaaaaaaaaa", -- 5 "aaaaaaaaaaaaaaaa", -- 6 "aaaaaaaaaaaaaaaa", -- 7 "aaabaaaaaaaaaaaa", -- 8 "aaaaaaaaaaaaaaaa", -- 9 "aaaaaaaaaaaaaaaa", -- 10 "aaaaaaaaaaaaaaaa", -- 11 "aaaaaaaaaaaaaaaa", -- 12 "aaaaaaaaaaaaaaaa", -- 13 "aaaaaaaaaaaaaaaa", -- 14 "aaaaaaaaaaaaaaaa", -- 15 -- Level 1 "aaaaaaaaaaaaaaaa", -- 0 "aaaaaaaaaaaaaaaa", -- 1 "aaaaaaaaaaaaaaaa", -- 2 "aaaaaaaaaaaaaaaa", -- 3 "aaaaaaaaaaaaaaaa", -- 4 "aaaaaaaaaaaaaaaa", -- 5 "aaaaccaaaaaaaaaa", -- 6 "aaacccaaaaaaaaaa", -- 7 "aabccaaaaaaaaaaa", -- 8 "aaaacaaaaaaaaaaa", -- 9 "aaaabaaaaaaaaaaa", -- 10 "aaaaaaaaaaaaaaaa", -- 11 "aaaaaaaaaaaaaaaa", -- 12 "aaaaaaaaaaaaaaaa", -- 13 "aaaaaaaaaaaaaaaa", -- 14 "aaaaaaaaaaaaaaaa", -- 15 -- Level 2 "bbbbbbabbbbbbbbb", -- 0 "bbdbbbbbbbbdbbbb", -- 1 "abbbbbeebbbabdbb", -- 2 "bbbbbbbeebbbbbbb", -- 3 "bbbbbbbbebbabbbb", -- 4 "bbbccccbebbbbbab", -- 5 "bbbccccbeebbbaab", -- 6 "bbcccccbbeeeebba", -- 7 "bbcccccbbbbbeebb", -- 8 "bbccccbbababbebb", -- 9 "bbbbcbbaabbbbeeb", -- 10 "bbbbbbbbbbbbabeb", -- 11 "bbbbbbbbaaabbbeb", -- 12 "bbbbbbbbbabbbbeb", -- 13 "bbbbabbbbbbbbeeb", -- 14 "bbbbbbbbbbbbeebb", -- 15 -- Level 3 "......f...gg.g..", -- 0 "..gg.....gggggg.", -- 1 "ffgg......ghgggg", -- 2 ".............gg.", -- 3 "...........f....", -- 4 "...........h.ff.", -- 5 ".............fh.", -- 6 "...............f", -- 7 "................", -- 8 ".......ff.f.....", -- 9 ".f.....ffggf....", -- 10 ".......gggg.f...", -- 11 ".f......iddg....", -- 12 ".....f..gdgg....", -- 13 "....ff...gg.....", -- 14 "................", -- 15 -- Level 4 "................", -- 0 "...........g.g..", -- 1 ".............gg.", -- 2 "................", -- 3 "................", -- 4 "................", -- 5 "................", -- 6 "................", -- 7 "................", -- 8 "................", -- 9 ".........g......", -- 10 "........ggg.....", -- 11 "........ggg.....", -- 12 ".........g......", -- 13 "................", -- 14 "................", -- 15 }, }, -- Garden2 { OriginData = { ExportName = "Farm", Name = "Plains 166", GalleryName = "Plains", GalleryIndex = "166", ID = "554", CreatorName = "Aloe_vera", }, Size = { x = 11, y = 8, z = 13, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 10, MaxY = 7, MaxZ = 12, }, Connectors = { { Type = -1, RelX = 10, RelY = 2, RelZ = 6, Direction = 5, -- X+ }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 3: 0", -- dirt "b: 60: 7", -- tilleddirt "c: 60: 6", -- tilleddirt "d: 8: 0", -- water "e: 43: 0", -- doublestoneslab "f: 44: 0", -- stone_slab "g: 59: 7", -- wheatblock "h: 83: 0", -- reedsblock "i:113: 0", -- netherbrickfence "j: 50: 5", -- torch "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "mmmmmmmmmmm", -- 0 "maaaaaaaaam", -- 1 "maaaaaaaaam", -- 2 "maaaaaaaaam", -- 3 "maaaaaaaaam", -- 4 "maaaaaaaaam", -- 5 "maaaaaaaaam", -- 6 "maaaaaaaaam", -- 7 "maaaaaaaaam", -- 8 "maaaaaaaaam", -- 9 "maaaaaaaaam", -- 10 "maaaaaaaaam", -- 11 "mmmmmmmmmmm", -- 12 -- Level 1 "mmmmmmmmmmm", -- 0 "maaaaaaaaam", -- 1 "mabbbbbbbam", -- 2 "mabbbbbbbam", -- 3 "mabbbbbcbam", -- 4 "mabbbbbbcam", -- 5 "mabdddddaam", -- 6 "mabbcbbbbam", -- 7 "mabbbbbbcam", -- 8 "mabbbbbbbam", -- 9 "mabbbbbbbam", -- 10 "maaaaaaaaam", -- 11 "mmmmmmmmmmm", -- 12 -- Level 2 "...........", -- 0 ".efffffffe.", -- 1 ".fgggggggf.", -- 2 ".fgggggggf.", -- 3 ".fgggggggf.", -- 4 ".fghhhhhgf.", -- 5 ".fh.....hf.", -- 6 ".fghhhhhgf.", -- 7 ".fgggggggf.", -- 8 ".fgggggggf.", -- 9 ".fgggggggf.", -- 10 ".efffffffe.", -- 11 "...........", -- 12 -- Level 3 "...........", -- 0 ".i.......i.", -- 1 "...........", -- 2 "...........", -- 3 "...........", -- 4 "...hhhhh...", -- 5 "..h.....h..", -- 6 "...hhhhh...", -- 7 "...........", -- 8 "...........", -- 9 "...........", -- 10 ".i.......i.", -- 11 "...........", -- 12 -- Level 4 "...........", -- 0 ".i.......i.", -- 1 "...........", -- 2 "...........", -- 3 "...........", -- 4 "...hhhhh...", -- 5 "..h.....h..", -- 6 "...hhhhh...", -- 7 "...........", -- 8 "...........", -- 9 "...........", -- 10 ".i.......i.", -- 11 "...........", -- 12 -- Level 5 "...........", -- 0 ".i.......i.", -- 1 "...........", -- 2 "...........", -- 3 "...........", -- 4 "...........", -- 5 "...........", -- 6 "...........", -- 7 "...........", -- 8 "...........", -- 9 "...........", -- 10 ".i.......i.", -- 11 "...........", -- 12 -- Level 6 ".i.......i.", -- 0 "iii.....iii", -- 1 ".i.......i.", -- 2 "...........", -- 3 "...........", -- 4 "...........", -- 5 "...........", -- 6 "...........", -- 7 "...........", -- 8 "...........", -- 9 ".i.......i.", -- 10 "iii.....iii", -- 11 ".i.......i.", -- 12 -- Level 7 ".j.......j.", -- 0 "j.j.....j.j", -- 1 ".j.......j.", -- 2 "...........", -- 3 "...........", -- 4 "...........", -- 5 "...........", -- 6 "...........", -- 7 "...........", -- 8 "...........", -- 9 ".j.......j.", -- 10 "j.j.....j.j", -- 11 ".j.......j.", -- 12 }, }, -- Farm }, -- Pieces } ================================================ FILE: Server/Prefabs/Villages/PlainsVillage.cubeset ================================================ -- PlainsVillage.cubeset -- Defines the prefabs in the group PlainsVillage -- NOTE: This file has been generated automatically by GalExport! -- Any manual changes will be overwritten by the next automatic export! Cubeset = { Metadata = { CubesetFormatVersion = 1, ExportDate = "2016-11-30 13:45:48", ["AllowedBiomes"] = "Plains, Savanna, SavannaM, SunflowerPlains", ["IntendedUse"] = "Village", }, Pieces = { { OriginData = { ExportName = "WoodenHouseL14x14", Name = "Plains 0", GalleryName = "Plains", GalleryIndex = "0", ID = "4", CreatorName = "Aloe_vera", }, Size = { x = 16, y = 8, z = 16, }, Hitbox = { MinX = -1, MinY = 1, MinZ = 0, MaxX = 16, MaxY = 7, MaxZ = 16, }, Connectors = { { Type = -1, RelX = 9, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 4: 0", -- cobblestone "b: 67: 0", -- stonestairs "c: 67: 2", -- stonestairs "d: 67: 1", -- stonestairs "e: 5: 0", -- planks "f: 67: 3", -- stonestairs "g: 17: 0", -- tree "h: 64: 3", -- woodendoorblock "i: 64: 1", -- woodendoorblock "j:102: 0", -- glasspane "k: 64: 9", -- woodendoorblock "l: 53: 2", -- woodstairs "m: 19: 0", -- sponge "n: 53: 1", -- woodstairs "o: 53: 7", -- woodstairs "p: 53: 6", -- woodstairs "q: 53: 3", -- woodstairs "r: 53: 0", -- woodstairs "s: 53: 5", -- woodstairs "t: 53: 4", -- woodstairs "u: 50: 3", -- torch "v: 50: 2", -- torch "w: 50: 4", -- torch "x: 50: 1", -- torch }, BlockData = { -- Level 0 "mmmmmmmmaaammmmm", -- 0 "maaaaaaaaaaaaaam", -- 1 "maaaaaaaaaaaaaam", -- 2 "maaaaaaaaaaaaaam", -- 3 "maaaaaaaaaaaaaam", -- 4 "maaaaaaaaaaaaaam", -- 5 "maaaaaaaaaaaaaam", -- 6 "maaaaaaaaaaaaaam", -- 7 "mmmmmaaaaaaaaaam", -- 8 "mmmmmmmmaaaaaaam", -- 9 "mmmmmmmmaaaaaaam", -- 10 "mmmmmmmmaaaaaaam", -- 11 "mmmmmmmmaaaaaaam", -- 12 "mmmmmmmmaaaaaaam", -- 13 "mmmmmmmmaaaaaaam", -- 14 "mmmmmmmmmmmmmmmm", -- 15 -- Level 1 "........bcd.....", -- 0 ".aaaaaaaaaaaaaa.", -- 1 ".aeeeeeeeeeeeea.", -- 2 ".aeeeeeeeeeeeea.", -- 3 ".aeeeeeeeeeeeea.", -- 4 ".aeeeeeeeeeeeea.", -- 5 ".aeeeeeeeeeeeea.", -- 6 ".aaaaaaaaeeeeea.", -- 7 ".....bfdaeeeeea.", -- 8 "mmmm....aeeeeea.", -- 9 "mmmmmmm.aeeeeea.", -- 10 "mmmmmmm.aeeeeea.", -- 11 "mmmmmmm.aeeeeea.", -- 12 "mmmmmmm.aeeeeea.", -- 13 "mmmmmmm.aaaaaaa.", -- 14 "mmmmmmm.........", -- 15 -- Level 2 "................", -- 0 ".geeeeeeghgeeeg.", -- 1 ".e............e.", -- 2 ".e............e.", -- 3 ".e............e.", -- 4 ".e............e.", -- 5 ".e............e.", -- 6 ".geeeeieg.....e.", -- 7 "........e.....e.", -- 8 "mmmm....e.....e.", -- 9 "mmmmmmm.e.....e.", -- 10 "mmmmmmm.e.....e.", -- 11 "mmmmmmm.e.....e.", -- 12 "mmmmmmm.e.....e.", -- 13 "mmmmmmm.geeeeeg.", -- 14 "mmmmmmm.........", -- 15 -- Level 3 "................", -- 0 ".gejjejjgkgjjeg.", -- 1 ".j............e.", -- 2 ".j............j.", -- 3 ".j............j.", -- 4 ".j............e.", -- 5 ".j............j.", -- 6 ".gejjekeg.....j.", -- 7 "........e.....e.", -- 8 "mmmm....j.....j.", -- 9 "mmmmmmm.j.....j.", -- 10 "mmmmmmm.e.....e.", -- 11 "mmmmmmm.j.....j.", -- 12 "mmmmmmm.j.....j.", -- 13 "mmmmmmm.gjjjjjg.", -- 14 "mmmmmmm.........", -- 15 -- Level 4 "llllllllllllllln", -- 0 "ogeeeeeegegeeegn", -- 1 ".e............en", -- 2 ".e............en", -- 3 ".e............en", -- 4 ".e............en", -- 5 ".e............en", -- 6 "pgeeeeeeg.....en", -- 7 "qqqqqqqre.....en", -- 8 "mmmm...re.....en", -- 9 "mmmmmmmre.....en", -- 10 "mmmmmmmre.....en", -- 11 "mmmmmmmre.....en", -- 12 "mmmmmmmre.....en", -- 13 "mmmmmmmrgeeeeegn", -- 14 "mmmmmmmrs.....tn", -- 15 -- Level 5 "................", -- 0 "lllllllllllllll.", -- 1 "oeeeeeeeeeeeeen.", -- 2 ".e.........u.en.", -- 3 ".e..........ven.", -- 4 ".e......w....en.", -- 5 "peeeeeeeee...en.", -- 6 "qqqqqqqqrex..en.", -- 7 "........re...en.", -- 8 "mmmm....re...en.", -- 9 "mmmmmmm.re...en.", -- 10 "mmmmmmm.re...en.", -- 11 "mmmmmmm.re...en.", -- 12 "mmmmmmm.re...en.", -- 13 "mmmmmmm.reeeeen.", -- 14 "mmmmmmm.rs...tn.", -- 15 -- Level 6 "................", -- 0 "................", -- 1 "llllllllllllln..", -- 2 "oeeeeeeeeeeeen..", -- 3 ".ex.........en..", -- 4 "peeeeeeeeee.en..", -- 5 "qqqqqqqqqre.en..", -- 6 ".........re.en..", -- 7 ".........re.en..", -- 8 "mmmm.....re.en..", -- 9 "mmmmmmm..re.en..", -- 10 "mmmmmmm..re.en..", -- 11 "mmmmmmm..re.en..", -- 12 "mmmmmmm..rewen..", -- 13 "mmmmmmm..reeen..", -- 14 "mmmmmmm..rs.tn..", -- 15 -- Level 7 "................", -- 0 "................", -- 1 "................", -- 2 "lllllllllllll...", -- 3 "eeeeeeeeeeeen...", -- 4 "qqqqqqqqqqren...", -- 5 "..........ren...", -- 6 "..........ren...", -- 7 "..........ren...", -- 8 "mmmm......ren...", -- 9 "mmmmmmm...ren...", -- 10 "mmmmmmm...ren...", -- 11 "mmmmmmm...ren...", -- 12 "mmmmmmm...ren...", -- 13 "mmmmmmm...ren...", -- 14 "mmmmmmm...ren...", -- 15 }, }, -- WoodenHouseL14x14 { OriginData = { ExportName = "CobbleWell4x4", Name = "Plains 1", GalleryName = "Plains", GalleryIndex = "1", ID = "5", CreatorName = "Aloe_vera", }, Size = { x = 4, y = 13, z = 4, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 3, MaxY = 12, MaxZ = 3, }, Connectors = { { Type = 2, RelX = 1, RelY = 9, RelZ = 3, Direction = 3, -- Z+ }, { Type = 2, RelX = 2, RelY = 9, RelZ = 0, Direction = 2, -- Z- }, { Type = 2, RelX = 0, RelY = 9, RelZ = 1, Direction = 4, -- X- }, { Type = 2, RelX = 3, RelY = 9, RelZ = 2, Direction = 5, -- X+ }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "None", ["IsStarting"] = "1", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", ["VerticalStrategy"] = "TerrainOrOceanTop|-9", }, BlockDefinitions = { ".: 0: 0", -- air "a: 1: 0", -- stone "b: 4: 0", -- cobblestone "c: 8: 0", -- water "d: 85: 0", -- fence "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "aaaa", -- 0 "aaaa", -- 1 "aaaa", -- 2 "aaaa", -- 3 -- Level 1 "bbbb", -- 0 "bccb", -- 1 "bccb", -- 2 "bbbb", -- 3 -- Level 2 "bbbb", -- 0 "bccb", -- 1 "bccb", -- 2 "bbbb", -- 3 -- Level 3 "bbbb", -- 0 "bccb", -- 1 "bccb", -- 2 "bbbb", -- 3 -- Level 4 "bbbb", -- 0 "bccb", -- 1 "bccb", -- 2 "bbbb", -- 3 -- Level 5 "bbbb", -- 0 "bccb", -- 1 "bccb", -- 2 "bbbb", -- 3 -- Level 6 "bbbb", -- 0 "bccb", -- 1 "bccb", -- 2 "bbbb", -- 3 -- Level 7 "bbbb", -- 0 "bccb", -- 1 "bccb", -- 2 "bbbb", -- 3 -- Level 8 "bbbb", -- 0 "bccb", -- 1 "bccb", -- 2 "bbbb", -- 3 -- Level 9 "bbbb", -- 0 "b..b", -- 1 "b..b", -- 2 "bbbb", -- 3 -- Level 10 "d..d", -- 0 "....", -- 1 "....", -- 2 "d..d", -- 3 -- Level 11 "d..d", -- 0 "....", -- 1 "....", -- 2 "d..d", -- 3 -- Level 12 "bbbb", -- 0 "bbbb", -- 1 "bbbb", -- 2 "bbbb", -- 3 }, }, -- CobbleWell4x4 { OriginData = { ExportName = "DoublePlantBed", Name = "Plains 5", GalleryName = "Plains", GalleryIndex = "5", ID = "20", CreatorName = "tonibm1999", }, Size = { x = 15, y = 8, z = 9, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 14, MaxY = 7, MaxZ = 8, }, Connectors = { { Type = -1, RelX = 7, RelY = 2, RelZ = 8, Direction = 3, -- Z+ }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 3: 0", -- dirt "b: 2: 0", -- grass "c: 17: 0", -- tree "d: 60: 7", -- tilleddirt "e: 8: 0", -- water "f: 60: 6", -- tilleddirt "g: 50: 5", -- torch "h: 59: 7", -- wheatblock "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "aaaaaaabaaaaaaa", -- 0 "aaaaaaabaaaaaaa", -- 1 "aaaaaaabaaaaaaa", -- 2 "aaaaaaabaaaaaaa", -- 3 "aaaaaaabaaaaaaa", -- 4 "aaaaaaabaaaaaaa", -- 5 "aaaaaaabaaaaaaa", -- 6 "aaaaaaaaaaaaaaa", -- 7 "aaaaaaaaaaaaaaa", -- 8 -- Level 1 "aaaaaaamaaaaaaa", -- 0 "aaaaaaamaaaaaaa", -- 1 "aaaaaaamaaaaaaa", -- 2 "aaaaaaamaaaaaaa", -- 3 "aaaaaaamaaaaaaa", -- 4 "aaaaaaamaaaaaaa", -- 5 "aaaaaaamaaaaaaa", -- 6 "aaaaaaamaaaaaaa", -- 7 "aaaaaaamaaaaaaa", -- 8 -- Level 2 "ccccccc.ccccccc", -- 0 "cddeddc.cddeddc", -- 1 "cddeddc.cddeddc", -- 2 "cddeddc.cddeddc", -- 3 "cddeddc.cddeddc", -- 4 "cddeddc.cddeddc", -- 5 "cddeddc.cdfeddc", -- 6 "cddeddc.cddeddc", -- 7 "ccccccc.ccccccc", -- 8 -- Level 3 "g.....g.g.....g", -- 0 ".hh.hh...hh.hh.", -- 1 ".hh.hh...hh.hh.", -- 2 ".hh.hh...hh.hh.", -- 3 ".hh.hh...hh.hh.", -- 4 ".hh.hh...hh.hh.", -- 5 ".hh.hh...hh.hh.", -- 6 ".hh.hh...hh.hh.", -- 7 "g.....g.g.....g", -- 8 -- Level 4 "...............", -- 0 "...............", -- 1 "...............", -- 2 "...............", -- 3 "...............", -- 4 "...............", -- 5 "...............", -- 6 "...............", -- 7 "...............", -- 8 -- Level 5 "...............", -- 0 "...............", -- 1 "...............", -- 2 "...............", -- 3 "...............", -- 4 "...............", -- 5 "...............", -- 6 "...............", -- 7 "...............", -- 8 -- Level 6 "...............", -- 0 "...............", -- 1 "...............", -- 2 "...............", -- 3 "...............", -- 4 "...............", -- 5 "...............", -- 6 "...............", -- 7 "...............", -- 8 -- Level 7 "...............", -- 0 "...............", -- 1 "...............", -- 2 "...............", -- 3 "...............", -- 4 "...............", -- 5 "...............", -- 6 "...............", -- 7 "...............", -- 8 }, }, -- DoublePlantBed { OriginData = { ExportName = "WoodenHouse9x5Fence", Name = "p9", GalleryName = "Plains", GalleryIndex = "9", ID = "26", CreatorName = "Aloe_vera", }, Size = { x = 10, y = 7, z = 11, }, Hitbox = { MinX = 0, MinY = -1, MinZ = -1, MaxX = 10, MaxY = 6, MaxZ = 11, }, Connectors = { { Type = -1, RelX = 0, RelY = 1, RelZ = 5, Direction = 4, -- X- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 4: 0", -- cobblestone "b: 3: 0", -- dirt "c: 5: 0", -- planks "d: 2: 0", -- grass "e: 67: 2", -- stonestairs "f: 43: 0", -- doublestoneslab "g: 67: 0", -- stonestairs "h: 67: 3", -- stonestairs "i: 17: 0", -- tree "j: 53: 1", -- woodstairs "k: 85: 0", -- fence "l: 53: 0", -- woodstairs "m: 19: 0", -- sponge "n: 64: 2", -- woodendoorblock "o: 64: 0", -- woodendoorblock "p:102: 0", -- glasspane "q: 72: 0", -- woodplate "r: 64: 9", -- woodendoorblock "s: 53: 5", -- woodstairs "t: 53: 4", -- woodstairs "u: 50: 1", -- torch "v: 50: 2", -- torch }, BlockData = { -- Level 0 "mmmmmmmmmm", -- 0 "maaaaammmm", -- 1 "maaaaammmm", -- 2 "maaaaabbbb", -- 3 "aaaaaabbbb", -- 4 "aaaaaabbbb", -- 5 "aaaaaabbbb", -- 6 "maaaaabbbb", -- 7 "maaaaabbbb", -- 8 "maaaaammmm", -- 9 "mmmmmmmmmm", -- 10 -- Level 1 "......mmmm", -- 0 ".aaaaammmm", -- 1 ".acccammmm", -- 2 ".acccadddd", -- 3 "eafffadddd", -- 4 "gaffffdddd", -- 5 "hafffadddd", -- 6 ".afffadddd", -- 7 ".afffadddd", -- 8 ".aaaaammmm", -- 9 "......mmmm", -- 10 -- Level 2 "......mmmm", -- 0 ".icccimmmm", -- 1 ".cjklcmmmm", -- 2 ".c...ckkkk", -- 3 ".c...c...k", -- 4 ".n...o...k", -- 5 ".c...c...k", -- 6 ".cff.c...k", -- 7 ".c...ckkkk", -- 8 ".icccimmmm", -- 9 "......mmmm", -- 10 -- Level 3 "......mmmm", -- 0 ".ipppimmmm", -- 1 ".p.q.pmmmm", -- 2 ".p...p....", -- 3 ".c...c....", -- 4 ".r...r....", -- 5 ".c...c....", -- 6 ".p...p....", -- 7 ".p...p....", -- 8 ".ipppimmmm", -- 9 "......mmmm", -- 10 -- Level 4 "ls...tjmmm", -- 0 "licccijmmm", -- 1 "lc...cjmmm", -- 2 "lc...cj...", -- 3 "lcu.vcj...", -- 4 "lc...cj...", -- 5 "lcu.vcj...", -- 6 "lc...cj...", -- 7 "lc...cj...", -- 8 "licccijmmm", -- 9 "ls...tjmmm", -- 10 -- Level 5 ".ls.tj.mmm", -- 0 ".lcccj.mmm", -- 1 ".lc.cj.mmm", -- 2 ".lc.cj....", -- 3 ".lc.cj....", -- 4 ".lc.cj....", -- 5 ".lc.cj....", -- 6 ".lc.cj....", -- 7 ".lc.cj....", -- 8 ".lcccj.mmm", -- 9 ".ls.tj.mmm", -- 10 -- Level 6 "..lcj..mmm", -- 0 "..lcj..mmm", -- 1 "..lcj..mmm", -- 2 "..lcj.....", -- 3 "..lcj.....", -- 4 "..lcj.....", -- 5 "..lcj.....", -- 6 "..lcj.....", -- 7 "..lcj.....", -- 8 "..lcj..mmm", -- 9 "..lcj..mmm", -- 10 }, }, -- WoodenHouse9x5Fence { OriginData = { ExportName = "SinglePlantBed", Name = "Plains 17", GalleryName = "Plains", GalleryIndex = "17", ID = "60", CreatorName = "Aloe_vera", }, Size = { x = 10, y = 7, z = 7, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 9, MaxY = 6, MaxZ = 6, }, Connectors = { { Type = -1, RelX = 9, RelY = 1, RelZ = 3, Direction = 5, -- X+ }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 3: 0", -- dirt "b: 17: 0", -- tree "c: 60: 7", -- tilleddirt "d: 60: 6", -- tilleddirt "e: 8: 0", -- water "f: 59: 7", -- wheatblock "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "aaaaaaaaaa", -- 0 "aaaaaaaaaa", -- 1 "aaaaaaaaaa", -- 2 "aaaaaaaaaa", -- 3 "aaaaaaaaaa", -- 4 "aaaaaaaaaa", -- 5 "aaaaaaaaaa", -- 6 -- Level 1 "bbbbbbbbbb", -- 0 "bccccccccb", -- 1 "bccccccdcb", -- 2 "beeeeeeeeb", -- 3 "bcccccdccb", -- 4 "bccccccccb", -- 5 "bbbbbbbbbb", -- 6 -- Level 2 "..........", -- 0 ".ffffffff.", -- 1 ".ffffffff.", -- 2 "..........", -- 3 ".ffffffff.", -- 4 ".ffffffff.", -- 5 "..........", -- 6 -- Level 3 "..........", -- 0 "..........", -- 1 "..........", -- 2 "..........", -- 3 "..........", -- 4 "..........", -- 5 "..........", -- 6 -- Level 4 "..........", -- 0 "..........", -- 1 "..........", -- 2 "..........", -- 3 "..........", -- 4 "..........", -- 5 "..........", -- 6 -- Level 5 "..........", -- 0 "..........", -- 1 "..........", -- 2 "..........", -- 3 "..........", -- 4 "..........", -- 5 "..........", -- 6 -- Level 6 "..........", -- 0 "..........", -- 1 "..........", -- 2 "..........", -- 3 "..........", -- 4 "..........", -- 5 "..........", -- 6 }, }, -- SinglePlantBed { OriginData = { ExportName = "CobbleHouse10x5Library", Name = "Plains 23", GalleryName = "Plains", GalleryIndex = "23", ID = "66", CreatorName = "xoft", }, Size = { x = 12, y = 7, z = 7, }, Hitbox = { MinX = -1, MinY = -1, MinZ = 0, MaxX = 12, MaxY = 6, MaxZ = 7, }, Connectors = { { Type = -1, RelX = 8, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 4: 0", -- cobblestone "b: 67: 0", -- stonestairs "c: 67: 2", -- stonestairs "d: 67: 1", -- stonestairs "e: 64: 3", -- woodendoorblock "f: 53: 3", -- woodstairs "g: 53: 1", -- woodstairs "h: 85: 0", -- fence "i: 53: 0", -- woodstairs "j: 53: 2", -- woodstairs "k:102: 0", -- glasspane "l: 64: 9", -- woodendoorblock "m: 19: 0", -- sponge "n: 50: 3", -- torch "o: 72: 0", -- woodplate "p: 50: 4", -- torch "q: 53: 7", -- woodstairs "r: 47: 0", -- bookshelf "s: 50: 1", -- torch "t: 50: 2", -- torch "u: 53: 6", -- woodstairs "v: 5: 0", -- planks }, BlockData = { -- Level 0 "mmmmmmmaaamm", -- 0 "maaaaaaaaaam", -- 1 "maaaaaaaaaam", -- 2 "maaaaaaaaaam", -- 3 "maaaaaaaaaam", -- 4 "maaaaaaaaaam", -- 5 "mmmmmmmmmmmm", -- 6 -- Level 1 ".......bcd..", -- 0 ".aaaaaaaaaa.", -- 1 ".aaaaaaaaaa.", -- 2 ".aaaaaaaaaa.", -- 3 ".aaaaaaaaaa.", -- 4 ".aaaaaaaaaa.", -- 5 "............", -- 6 -- Level 2 "............", -- 0 ".aaaaaaaeaa.", -- 1 ".af.ghi...a.", -- 2 ".ah.......a.", -- 3 ".aj.ghighia.", -- 4 ".aaaaaaaaaa.", -- 5 "............", -- 6 -- Level 3 "............", -- 0 ".akkakkalaa.", -- 1 ".k..no.n.nk.", -- 2 ".ko.......k.", -- 3 ".k..po.po.k.", -- 4 ".akkakkakka.", -- 5 "............", -- 6 -- Level 4 "jjjjjjjjjjjj", -- 0 "qaaaaaaaaaaq", -- 1 ".arrrrrrrra.", -- 2 ".as......ta.", -- 3 ".arrrrrrrra.", -- 4 "uaaaaaaaaaau", -- 5 "ffffffffffff", -- 6 -- Level 5 "............", -- 0 "jjjjjjjjjjjj", -- 1 "qvvvvvvvvvvq", -- 2 ".vvvvvvvvvv.", -- 3 "uvvvvvvvvvvu", -- 4 "ffffffffffff", -- 5 "............", -- 6 -- Level 6 "............", -- 0 "............", -- 1 "jjjjjjjjjjjj", -- 2 "vvvvvvvvvvvv", -- 3 "ffffffffffff", -- 4 "............", -- 5 "............", -- 6 }, }, -- CobbleHouse10x5Library { OriginData = { ExportName = "BigPlantBed", Name = "Plains 26", GalleryName = "Plains", GalleryIndex = "26", ID = "70", CreatorName = "Taugrammaton", }, Size = { x = 13, y = 8, z = 12, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 12, MaxY = 7, MaxZ = 11, }, Connectors = { { Type = -1, RelX = 7, RelY = 1, RelZ = 11, Direction = 3, -- Z+ }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 3: 0", -- dirt "b: 5: 0", -- planks "c: 13: 0", -- gravel "d: 17: 0", -- tree "e: 60: 7", -- tilleddirt "f: 8: 0", -- water "g: 60: 6", -- tilleddirt "h: 60: 4", -- tilleddirt "i: 85: 0", -- fence "j: 59: 7", -- wheatblock "k: 50: 5", -- torch "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "aaaaaaaaaaaaa", -- 0 "aaaaaaaaaaaaa", -- 1 "aaaaaaaaaaaaa", -- 2 "aaaaaaaaaaaaa", -- 3 "aaaaaaaaaaaaa", -- 4 "aaaaaaaaaaaaa", -- 5 "aaaaaaaaaaaaa", -- 6 "aaaaaaaaaaaaa", -- 7 "aaaaaaaaaaaaa", -- 8 "aaaaaaaaaaaaa", -- 9 "aaaaaaaaaaaaa", -- 10 "aaaaaaaaaaaaa", -- 11 -- Level 1 "bbbbbbbbbbbbb", -- 0 "bcccccccccccb", -- 1 "bcccccccccccb", -- 2 "bcccccccccccb", -- 3 "bcccccccccccb", -- 4 "bcccccccccccb", -- 5 "bcccccccccccb", -- 6 "bcccccccccccb", -- 7 "bcccccccccccb", -- 8 "bcccccccccccb", -- 9 "bcccccccccccb", -- 10 "bbbbbbbbbbbbb", -- 11 -- Level 2 "ddddddddddddd", -- 0 "deefeefeefeed", -- 1 "deefeefeefeed", -- 2 "deefeefegfged", -- 3 "deefeefeefeed", -- 4 "deefgefeefged", -- 5 "degfeefegfhed", -- 6 "deefeefeefggd", -- 7 "deefeefeefeed", -- 8 "deefeefeefeed", -- 9 "deefeefeefeed", -- 10 "ddddddddddddd", -- 11 -- Level 3 "i..i..i..i..i", -- 0 "ijj.j..jj.jji", -- 1 "ijj..j.jj.jji", -- 2 "ijj.j..j..jji", -- 3 "ijj.jj.j..jji", -- 4 "ijj.j..jj.jji", -- 5 "ijj.jj.jj.jji", -- 6 "ijj....j..jji", -- 7 "ijj..j....jji", -- 8 "ijj.....j.jji", -- 9 "ijj.jj.j..jji", -- 10 "i..i..i..i..i", -- 11 -- Level 4 "k..k..k..k..k", -- 0 ".............", -- 1 ".............", -- 2 ".............", -- 3 ".............", -- 4 ".............", -- 5 ".............", -- 6 ".............", -- 7 ".............", -- 8 ".............", -- 9 ".............", -- 10 "k..k..k..k..k", -- 11 -- Level 5 ".............", -- 0 ".............", -- 1 ".............", -- 2 ".............", -- 3 ".............", -- 4 ".............", -- 5 ".............", -- 6 ".............", -- 7 ".............", -- 8 ".............", -- 9 ".............", -- 10 ".............", -- 11 -- Level 6 ".............", -- 0 ".............", -- 1 ".............", -- 2 ".............", -- 3 ".............", -- 4 ".............", -- 5 ".............", -- 6 ".............", -- 7 ".............", -- 8 ".............", -- 9 ".............", -- 10 ".............", -- 11 -- Level 7 ".............", -- 0 ".............", -- 1 ".............", -- 2 ".............", -- 3 ".............", -- 4 ".............", -- 5 ".............", -- 6 ".............", -- 7 ".............", -- 8 ".............", -- 9 ".............", -- 10 ".............", -- 11 }, }, -- BigPlantBed { OriginData = { ExportName = "LampPost", Name = "Plains 28", GalleryName = "Plains", GalleryIndex = "28", ID = "73", CreatorName = "STR_Warrior", }, Size = { x = 3, y = 7, z = 3, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 2, MaxY = 6, MaxZ = 2, }, Connectors = { { Type = -1, RelX = 1, RelY = 1, RelZ = 2, Direction = 3, -- Z+ }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 2: 0", -- grass "b: 3: 0", -- dirt "c: 43: 0", -- doublestoneslab "d:139: 0", -- cobblestonewall "e: 50: 4", -- torch "f: 50: 2", -- torch "g: 50: 1", -- torch "h: 50: 3", -- torch "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "aaa", -- 0 "aba", -- 1 "aaa", -- 2 -- Level 1 "...", -- 0 ".c.", -- 1 "...", -- 2 -- Level 2 "...", -- 0 ".d.", -- 1 "...", -- 2 -- Level 3 "...", -- 0 ".d.", -- 1 "...", -- 2 -- Level 4 ".e.", -- 0 "fcg", -- 1 ".h.", -- 2 -- Level 5 "...", -- 0 "...", -- 1 "...", -- 2 -- Level 6 "...", -- 0 "...", -- 1 "...", -- 2 }, }, -- LampPost { OriginData = { ExportName = "WoodenHouse9x7DoubleDoor", Name = "Plains 38", GalleryName = "Plains", GalleryIndex = "38", ID = "87", CreatorName = "Aloe_vera", }, Size = { x = 11, y = 8, z = 9, }, Hitbox = { MinX = -1, MinY = -1, MinZ = 0, MaxX = 11, MaxY = 7, MaxZ = 9, }, Connectors = { { Type = -1, RelX = 5, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 4: 0", -- cobblestone "b: 67: 0", -- stonestairs "c: 67: 2", -- stonestairs "d: 67: 1", -- stonestairs "e: 67: 3", -- stonestairs "f: 17: 0", -- tree "g: 5: 0", -- planks "h: 64: 7", -- woodendoorblock "i: 64: 1", -- woodendoorblock "j:102: 0", -- glasspane "k: 64: 9", -- woodendoorblock "l: 53: 2", -- woodstairs "m: 19: 0", -- sponge "n: 53: 7", -- woodstairs "o: 17: 4", -- tree "p: 17: 8", -- tree "q: 50: 3", -- torch "r: 50: 4", -- torch "s: 53: 6", -- woodstairs "t: 53: 3", -- woodstairs }, BlockData = { -- Level 0 "mmmmaaammmm", -- 0 "maaaaaaaaam", -- 1 "maaaaaaaaam", -- 2 "maaaaaaaaam", -- 3 "maaaaaaaaam", -- 4 "maaaaaaaaam", -- 5 "maaaaaaaaam", -- 6 "maaaaaaaaam", -- 7 "mmmmaaammmm", -- 8 -- Level 1 "....bcd....", -- 0 ".aaaaaaaaa.", -- 1 ".aaaaaaaaa.", -- 2 ".aaaaaaaaa.", -- 3 ".aaaaaaaaa.", -- 4 ".aaaaaaaaa.", -- 5 ".aaaaaaaaa.", -- 6 ".aaaaaaaaa.", -- 7 "....bed....", -- 8 -- Level 2 "...........", -- 0 ".fggfhfggf.", -- 1 ".g.......g.", -- 2 ".g.......g.", -- 3 ".f.......f.", -- 4 ".g.......g.", -- 5 ".g.......g.", -- 6 ".fggfifggf.", -- 7 "...........", -- 8 -- Level 3 "...........", -- 0 ".fjjfkfjjf.", -- 1 ".j.......j.", -- 2 ".j.......j.", -- 3 ".f.......f.", -- 4 ".j.......j.", -- 5 ".j.......j.", -- 6 ".fjjfkfjjf.", -- 7 "...........", -- 8 -- Level 4 "lllllllllll", -- 0 "nfooooooofn", -- 1 ".p..q.q..p.", -- 2 ".p.......p.", -- 3 ".p.......p.", -- 4 ".p.......p.", -- 5 ".p..r.r..p.", -- 6 "sfooooooofs", -- 7 "ttttttttttt", -- 8 -- Level 5 "...........", -- 0 "lllllllllll", -- 1 "ngggggggggn", -- 2 ".g.......g.", -- 3 ".g.......g.", -- 4 ".g.......g.", -- 5 "sgggggggggs", -- 6 "ttttttttttt", -- 7 "...........", -- 8 -- Level 6 "...........", -- 0 "...........", -- 1 "lllllllllll", -- 2 "ngggggggggn", -- 3 ".g.......g.", -- 4 "sgggggggggs", -- 5 "ttttttttttt", -- 6 "...........", -- 7 "...........", -- 8 -- Level 7 "...........", -- 0 "...........", -- 1 "...........", -- 2 "lllllllllll", -- 3 "ggggggggggg", -- 4 "ttttttttttt", -- 5 "...........", -- 6 "...........", -- 7 "...........", -- 8 }, }, -- WoodenHouse9x7DoubleDoor { OriginData = { ExportName = "WoodenHouseL13x14", Name = "Plains 39", GalleryName = "Plains", GalleryIndex = "39", ID = "90", CreatorName = "STR_Warrior", }, Size = { x = 15, y = 9, z = 16, }, Hitbox = { MinX = -1, MinY = -1, MinZ = 0, MaxX = 15, MaxY = 8, MaxZ = 16, }, Connectors = { { Type = -1, RelX = 7, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "A: 53: 7", -- woodstairs "B: 53: 4", -- woodstairs "C: 53: 5", -- woodstairs "D: 53: 6", -- woodstairs "a: 4: 0", -- cobblestone "b: 67: 0", -- stonestairs "c: 67: 2", -- stonestairs "d: 67: 1", -- stonestairs "e: 43: 0", -- doublestoneslab "f: 17: 0", -- tree "g: 5: 0", -- planks "h: 64: 3", -- woodendoorblock "i: 96: 8", -- trapdoor "j: 61: 2", -- furnace "k: 53: 3", -- woodstairs "l: 85: 0", -- fence "m: 19: 0", -- sponge "n: 53: 2", -- woodstairs "o: 53: 1", -- woodstairs "p: 53: 0", -- woodstairs "q: 47: 0", -- bookshelf "r:102: 0", -- glasspane "s: 64: 9", -- woodendoorblock "t: 72: 0", -- woodplate "u: 17: 4", -- tree "v: 17: 8", -- tree "w: 50: 3", -- torch "x: 50: 1", -- torch "y: 50: 4", -- torch "z: 50: 2", -- torch }, BlockData = { -- Level 0 "mmmmmmaaammmmmm", -- 0 "maaaaaaaaaaaaam", -- 1 "maaaaaaaaaaaaam", -- 2 "maaaaaaaaaaaaam", -- 3 "maaaaaaaaaaaaam", -- 4 "maaaaaaaaaaaaam", -- 5 "maaaaaaaaaaaaam", -- 6 "maaaaaaaaaaaaam", -- 7 "mmmmmmmmaaaaaam", -- 8 "mmmmmmmmaaaaaam", -- 9 "mmmmmmmmaaaaaam", -- 10 "mmmmmmmmaaaaaam", -- 11 "mmmmmmmmaaaaaam", -- 12 "mmmmmmmmaaaaaam", -- 13 "mmmmmmmmaaaaaam", -- 14 "mmmmmmmmmmmmmmm", -- 15 -- Level 1 "......bcd......", -- 0 ".aaaaaaaaaaaaa.", -- 1 ".aeeeeaaaaaaaa.", -- 2 ".aeeeeaaaaaaaa.", -- 3 ".aaaaaaaaaaaaa.", -- 4 ".aaaaaaaaaaaaa.", -- 5 ".aaaaaaaaaaaaa.", -- 6 ".aaaaaaaaaaaaa.", -- 7 "........aaaaaa.", -- 8 "mmmmmmm.aaaaaa.", -- 9 "mmmmmmm.aaaaaa.", -- 10 "mmmmmmm.aaaaaa.", -- 11 "mmmmmmm.aaaaaa.", -- 12 "mmmmmmm.aaaaaa.", -- 13 "mmmmmmm.aaaaaa.", -- 14 "mmmmmmm........", -- 15 -- Level 2 "...............", -- 0 ".fggggfhfggggf.", -- 1 ".g...i.......g.", -- 2 ".gjeee......kg.", -- 3 ".f..........lg.", -- 4 ".g..........ng.", -- 5 ".g.olp..ol...g.", -- 6 ".fggggggfn...f.", -- 7 "........g....g.", -- 8 "mmmmmmm.gk...g.", -- 9 "mmmmmmm.gl..kg.", -- 10 "mmmmmmm.gn..lg.", -- 11 "mmmmmmm.g...ng.", -- 12 "mmmmmmm.gq..qg.", -- 13 "mmmmmmm.fggggf.", -- 14 "mmmmmmm........", -- 15 -- Level 3 "...............", -- 0 ".fgrrgfsfgrrgf.", -- 1 ".g...........g.", -- 2 ".g...........r.", -- 3 ".f..........tr.", -- 4 ".g...........r.", -- 5 ".g..t....t...g.", -- 6 ".fgrrrrgf....f.", -- 7 "........g....g.", -- 8 "mmmmmmm.r....r.", -- 9 "mmmmmmm.rt...r.", -- 10 "mmmmmmm.r...tr.", -- 11 "mmmmmmm.r....r.", -- 12 "mmmmmmm.gq..qg.", -- 13 "mmmmmmm.fgrrgf.", -- 14 "mmmmmmm........", -- 15 -- Level 4 "...............", -- 0 ".fuuuuuuuuuuuf.", -- 1 ".v....w.w....v.", -- 2 ".v...........v.", -- 3 ".vx..........v.", -- 4 ".v...........v.", -- 5 ".v......y....v.", -- 6 ".fuuuuuufx..zv.", -- 7 "........v....v.", -- 8 "mmmmmmm.v....v.", -- 9 "mmmmmmm.v....v.", -- 10 "mmmmmmm.v....v.", -- 11 "mmmmmmm.v....v.", -- 12 "mmmmmmm.v.yy.v.", -- 13 "mmmmmmm.fuuuuf.", -- 14 "mmmmmmm........", -- 15 -- Level 5 "nnnnnnnnnnnnnno", -- 0 "pgggggggggggggo", -- 1 "pgAAAAAAAAAABgo", -- 2 "pgC.........Bgo", -- 3 "pgC.........Bgo", -- 4 "pgC.........Bgo", -- 5 "pgCDDDDDDD..Bgo", -- 6 "pggggggggC..Bgo", -- 7 "pkkkkkkpgC..Bgo", -- 8 "mmmmmmmpgC..Bgo", -- 9 "mmmmmmmpgC..Bgo", -- 10 "mmmmmmmpgC..Bgo", -- 11 "mmmmmmmpgC..Bgo", -- 12 "mmmmmmmpgCDDBgo", -- 13 "mmmmmmmpggggggo", -- 14 "mmmmmmmpkkkkkkk", -- 15 -- Level 6 "...............", -- 0 ".pnnnnnnnnnnno.", -- 1 ".pgggggggggggo.", -- 2 ".pgggggggggggo.", -- 3 ".pgggggggggggo.", -- 4 ".pgggggggggggo.", -- 5 ".pgggggggggggo.", -- 6 ".pkkkkkkkggggo.", -- 7 "........pggggo.", -- 8 "mmmmmmm.pggggo.", -- 9 "mmmmmmm.pggggo.", -- 10 "mmmmmmm.pggggo.", -- 11 "mmmmmmm.pggggo.", -- 12 "mmmmmmm.pggggo.", -- 13 "mmmmmmm.kkkkko.", -- 14 "mmmmmmm........", -- 15 -- Level 7 "...............", -- 0 "...............", -- 1 "..nnnnnnnnnnn..", -- 2 "..pgggggggggo..", -- 3 "..pgggggggggo..", -- 4 "..pgggggggggo..", -- 5 "..kkkkkkkkggo..", -- 6 ".........pggo..", -- 7 ".........pggo..", -- 8 "mmmmmmm..pggo..", -- 9 "mmmmmmm..pggo..", -- 10 "mmmmmmm..pggo..", -- 11 "mmmmmmm..pggo..", -- 12 "mmmmmmm..kkko..", -- 13 "mmmmmmm........", -- 14 "mmmmmmm........", -- 15 -- Level 8 "...............", -- 0 "...............", -- 1 "...............", -- 2 "...pnnnnnnno...", -- 3 "...pgggggggo...", -- 4 "...pkkkkkkpo...", -- 5 "..........po...", -- 6 "..........po...", -- 7 "..........po...", -- 8 "mmmmmmm...po...", -- 9 "mmmmmmm...po...", -- 10 "mmmmmmm...po...", -- 11 "mmmmmmm...pk...", -- 12 "mmmmmmm........", -- 13 "mmmmmmm........", -- 14 "mmmmmmm........", -- 15 }, }, -- WoodenHouseL13x14 { OriginData = { ExportName = "WoodenHouse7x5", Name = "Plains 40", GalleryName = "Plains", GalleryIndex = "40", ID = "91", CreatorName = "xoft", }, Size = { x = 9, y = 7, z = 7, }, Hitbox = { MinX = -1, MinY = -1, MinZ = 0, MaxX = 9, MaxY = 6, MaxZ = 7, }, Connectors = { { Type = -1, RelX = 4, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 4: 0", -- cobblestone "b: 67: 0", -- stonestairs "c: 67: 2", -- stonestairs "d: 67: 1", -- stonestairs "e: 17: 0", -- tree "f: 5: 0", -- planks "g: 64: 3", -- woodendoorblock "h:102: 0", -- glasspane "i: 64: 9", -- woodendoorblock "j: 53: 2", -- woodstairs "k: 53: 7", -- woodstairs "l: 50: 3", -- torch "m: 19: 0", -- sponge "n: 53: 6", -- woodstairs "o: 53: 3", -- woodstairs }, BlockData = { -- Level 0 "mmmaaammm", -- 0 "maaaaaaam", -- 1 "maaaaaaam", -- 2 "maaaaaaam", -- 3 "maaaaaaam", -- 4 "maaaaaaam", -- 5 "mmmmmmmmm", -- 6 -- Level 1 "...bcd...", -- 0 ".aaaaaaa.", -- 1 ".aaaaaaa.", -- 2 ".aaaaaaa.", -- 3 ".aaaaaaa.", -- 4 ".aaaaaaa.", -- 5 ".........", -- 6 -- Level 2 ".........", -- 0 ".effgffe.", -- 1 ".f.....f.", -- 2 ".f.....f.", -- 3 ".f.....f.", -- 4 ".efffffe.", -- 5 ".........", -- 6 -- Level 3 ".........", -- 0 ".ehfifhe.", -- 1 ".h.....h.", -- 2 ".h.....h.", -- 3 ".h.....h.", -- 4 ".ehhfhhe.", -- 5 ".........", -- 6 -- Level 4 "jjjjjjjjj", -- 0 "kefffffek", -- 1 ".f.l.l.f.", -- 2 ".f.....f.", -- 3 ".f.....f.", -- 4 "nefffffen", -- 5 "ooooooooo", -- 6 -- Level 5 ".........", -- 0 "jjjjjjjjj", -- 1 "kfffffffk", -- 2 ".f.....f.", -- 3 "nfffffffn", -- 4 "ooooooooo", -- 5 ".........", -- 6 -- Level 6 ".........", -- 0 ".........", -- 1 "jjjjjjjjj", -- 2 "fffffffff", -- 3 "ooooooooo", -- 4 ".........", -- 5 ".........", -- 6 }, }, -- WoodenHouse7x5 { OriginData = { ExportName = "WoodenHouse9x5", Name = "Plains 41", GalleryName = "Plains", GalleryIndex = "41", ID = "92", CreatorName = "xoft", }, Size = { x = 11, y = 7, z = 7, }, Hitbox = { MinX = -1, MinY = -1, MinZ = 0, MaxX = 11, MaxY = 6, MaxZ = 7, }, Connectors = { { Type = -1, RelX = 5, RelY = 1, RelZ = -1, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 4: 0", -- cobblestone "b: 67: 0", -- stonestairs "c: 67: 2", -- stonestairs "d: 67: 1", -- stonestairs "e: 17: 0", -- tree "f: 5: 0", -- planks "g: 64: 3", -- woodendoorblock "h:102: 0", -- glasspane "i: 64: 9", -- woodendoorblock "j: 53: 2", -- woodstairs "k: 53: 7", -- woodstairs "l: 50: 3", -- torch "m: 19: 0", -- sponge "n: 53: 6", -- woodstairs "o: 53: 3", -- woodstairs }, BlockData = { -- Level 0 "mmmmaaammmm", -- 0 "maaaaaaaaam", -- 1 "maaaaaaaaam", -- 2 "maaaaaaaaam", -- 3 "maaaaaaaaam", -- 4 "maaaaaaaaam", -- 5 "mmmmmmmmmmm", -- 6 -- Level 1 "....bcd....", -- 0 ".aaaaaaaaa.", -- 1 ".aaaaaaaaa.", -- 2 ".aaaaaaaaa.", -- 3 ".aaaaaaaaa.", -- 4 ".aaaaaaaaa.", -- 5 "...........", -- 6 -- Level 2 "...........", -- 0 ".efffgfffe.", -- 1 ".f.......f.", -- 2 ".f.......f.", -- 3 ".f.......f.", -- 4 ".efffffffe.", -- 5 "...........", -- 6 -- Level 3 "...........", -- 0 ".ehhfifhhe.", -- 1 ".h.......h.", -- 2 ".h.......h.", -- 3 ".h.......h.", -- 4 ".ehhhfhhhe.", -- 5 "...........", -- 6 -- Level 4 "jjjjjjjjjjj", -- 0 "kfffffffffk", -- 1 ".f..l.l.ff.", -- 2 ".f......ff.", -- 3 ".f......ff.", -- 4 "nfffffffffn", -- 5 "ooooooooooo", -- 6 -- Level 5 "...........", -- 0 "jjjjjjjjjjj", -- 1 "kfffffffffk", -- 2 ".fffffffff.", -- 3 "nfffffffffn", -- 4 "ooooooooooo", -- 5 "...........", -- 6 -- Level 6 "...........", -- 0 "...........", -- 1 "jjjjjjjjjjj", -- 2 "fffffffffff", -- 3 "ooooooooooo", -- 4 "...........", -- 5 "...........", -- 6 }, }, -- WoodenHouse9x5 { OriginData = { ExportName = "WoodenHouseL9x9", Name = "Plains 42", GalleryName = "Plains", GalleryIndex = "42", ID = "93", CreatorName = "xoft", }, Size = { x = 11, y = 7, z = 11, }, Hitbox = { MinX = -1, MinY = -1, MinZ = 0, MaxX = 11, MaxY = 6, MaxZ = 11, }, Connectors = { { Type = -1, RelX = 5, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 4: 0", -- cobblestone "b: 67: 0", -- stonestairs "c: 67: 2", -- stonestairs "d: 67: 1", -- stonestairs "e: 17: 0", -- tree "f: 5: 0", -- planks "g: 64: 3", -- woodendoorblock "h:102: 0", -- glasspane "i: 64: 9", -- woodendoorblock "j: 53: 2", -- woodstairs "k: 53: 7", -- woodstairs "l: 53: 1", -- woodstairs "m: 19: 0", -- sponge "n: 50: 3", -- torch "o: 50: 4", -- torch "p: 53: 6", -- woodstairs "q: 50: 1", -- torch "r: 50: 2", -- torch "s: 53: 3", -- woodstairs "t: 53: 0", -- woodstairs "u: 53: 5", -- woodstairs "v: 53: 4", -- woodstairs }, BlockData = { -- Level 0 "mmmmaaammmm", -- 0 "maaaaaaaaam", -- 1 "maaaaaaaaam", -- 2 "maaaaaaaaam", -- 3 "maaaaaaaaam", -- 4 "maaaaaaaaam", -- 5 "mmmmmaaaaam", -- 6 "mmmmmaaaaam", -- 7 "mmmmmaaaaam", -- 8 "mmmmmaaaaam", -- 9 "mmmmmmmmmmm", -- 10 -- Level 1 "....bcd....", -- 0 ".aaaaaaaaa.", -- 1 ".aaaaaaaaa.", -- 2 ".aaaaaaaaa.", -- 3 ".aaaaaaaaa.", -- 4 ".aaaaaaaaa.", -- 5 ".....aaaaa.", -- 6 "mmmm.aaaaa.", -- 7 "mmmm.aaaaa.", -- 8 "mmmm.aaaaa.", -- 9 "mmmm.......", -- 10 -- Level 2 "...........", -- 0 ".efffgfffe.", -- 1 ".f.......f.", -- 2 ".f.......f.", -- 3 ".f.......f.", -- 4 ".efffe...f.", -- 5 ".....f...f.", -- 6 "mmmm.f...f.", -- 7 "mmmm.f...f.", -- 8 "mmmm.efffe.", -- 9 "mmmm.......", -- 10 -- Level 3 "...........", -- 0 ".ehhfifhhe.", -- 1 ".h.......h.", -- 2 ".h.......h.", -- 3 ".h.......h.", -- 4 ".ehhhe...f.", -- 5 ".....h...h.", -- 6 "mmmm.h...h.", -- 7 "mmmm.h...h.", -- 8 "mmmm.ehhhe.", -- 9 "mmmm.......", -- 10 -- Level 4 "jjjjjjjjjjj", -- 0 "kfffffffffl", -- 1 ".f..n.n..fl", -- 2 ".f.......fl", -- 3 ".f...o...fl", -- 4 "pfffffq.rfl", -- 5 "sssssf...fl", -- 6 "mmmmtf...fl", -- 7 "mmmmtf...fl", -- 8 "mmmmtfffffl", -- 9 "mmmmtu...vl", -- 10 -- Level 5 "...........", -- 0 "jjjjjjjjjl.", -- 1 "kffffffffl.", -- 2 ".f......fl.", -- 3 "pffffff.fl.", -- 4 "ssssssf.fl.", -- 5 ".....tf.fl.", -- 6 "mmmm.tf.fl.", -- 7 "mmmm.tf.fl.", -- 8 "mmmm.tfffl.", -- 9 "mmmm.tu.vl.", -- 10 -- Level 6 "...........", -- 0 "...........", -- 1 "jjjjjjjjj..", -- 2 "ffffffffl..", -- 3 "sssssstfl..", -- 4 "......tfl..", -- 5 "......tfl..", -- 6 "mmmm..tfl..", -- 7 "mmmm..tfl..", -- 8 "mmmm..tfl..", -- 9 "mmmm..tfl..", -- 10 }, }, -- WoodenHouseL9x9 { OriginData = { ExportName = "WoodenHouseU13x9", Name = "Plains 43", GalleryName = "Plains", GalleryIndex = "43", ID = "94", CreatorName = "xoft", }, Size = { x = 15, y = 7, z = 11, }, Hitbox = { MinX = -1, MinY = -1, MinZ = 0, MaxX = 15, MaxY = 6, MaxZ = 11, }, Connectors = { { Type = -1, RelX = 7, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 4: 0", -- cobblestone "b: 67: 0", -- stonestairs "c: 67: 2", -- stonestairs "d: 67: 1", -- stonestairs "e: 17: 0", -- tree "f: 5: 0", -- planks "g: 64: 3", -- woodendoorblock "h:102: 0", -- glasspane "i: 64: 9", -- woodendoorblock "j: 53: 2", -- woodstairs "k: 53: 0", -- woodstairs "l: 53: 1", -- woodstairs "m: 19: 0", -- sponge "n: 50: 3", -- torch "o: 50: 4", -- torch "p: 50: 2", -- torch "q: 50: 1", -- torch "r: 53: 3", -- woodstairs "s: 53: 5", -- woodstairs "t: 53: 4", -- woodstairs }, BlockData = { -- Level 0 "mmmmmmaaammmmmm", -- 0 "maaaaaaaaaaaaam", -- 1 "maaaaaaaaaaaaam", -- 2 "maaaaaaaaaaaaam", -- 3 "maaaaaaaaaaaaam", -- 4 "maaaaaaaaaaaaam", -- 5 "maaaaammmaaaaam", -- 6 "maaaaammmaaaaam", -- 7 "maaaaammmaaaaam", -- 8 "maaaaammmaaaaam", -- 9 "mmmmmmmmmmmmmmm", -- 10 -- Level 1 "......bcd......", -- 0 ".aaaaaaaaaaaaa.", -- 1 ".aaaaaaaaaaaaa.", -- 2 ".aaaaaaaaaaaaa.", -- 3 ".aaaaaaaaaaaaa.", -- 4 ".aaaaaaaaaaaaa.", -- 5 ".aaaaa...aaaaa.", -- 6 ".aaaaa...aaaaa.", -- 7 ".aaaaa...aaaaa.", -- 8 ".aaaaa...aaaaa.", -- 9 "...............", -- 10 -- Level 2 "...............", -- 0 ".efffffgfffffe.", -- 1 ".f...........f.", -- 2 ".f...........f.", -- 3 ".f...........f.", -- 4 ".f...efffe...f.", -- 5 ".f...f...f...f.", -- 6 ".f...f...f...f.", -- 7 ".f...f...f...f.", -- 8 ".efffe...efffe.", -- 9 "...............", -- 10 -- Level 3 "...............", -- 0 ".ehhhhfifhhhhe.", -- 1 ".h...........h.", -- 2 ".h...........h.", -- 3 ".h...........h.", -- 4 ".f...ehhhe...f.", -- 5 ".h...h...h...h.", -- 6 ".h...h...h...h.", -- 7 ".h...h...h...h.", -- 8 ".ehhhe...ehhhe.", -- 9 "...............", -- 10 -- Level 4 "jjjjjjjjjjjjjjj", -- 0 "kfffffffffffffl", -- 1 "kf....n.n....fl", -- 2 "kf...........fl", -- 3 "kf...o...o...fl", -- 4 "kf..pfffffq..fl", -- 5 "kf...frrrf...fl", -- 6 "kf...fl.kf...fl", -- 7 "kf...fl.kf...fl", -- 8 "kfffffl.kfffffl", -- 9 "ks...tl.ks...tl", -- 10 -- Level 5 "...............", -- 0 ".jjjjjjjjjjjjl.", -- 1 ".kfffffffffffl.", -- 2 ".kfffffffffffl.", -- 3 ".kfffffffffffl.", -- 4 ".kffflrrrrfffl.", -- 5 ".kfffl...kfffl.", -- 6 ".kfffl...kfffl.", -- 7 ".kfffl...kfffl.", -- 8 ".kfffl...kfffl.", -- 9 ".ks.tl...ks.tl.", -- 10 -- Level 6 "...............", -- 0 "...............", -- 1 "..kjjjjjjjjjj..", -- 2 "..kfffffffffl..", -- 3 "..kflrrrrrkfl..", -- 4 "..kfl.....kfl..", -- 5 "..kfl.....kfl..", -- 6 "..kfl.....kfl..", -- 7 "..kfl.....kfl..", -- 8 "..kfl.....kfl..", -- 9 "..kfl.....kfl..", -- 10 }, }, -- WoodenHouseU13x9 { OriginData = { ExportName = "WoodenHouse9x5Library", Name = "Plains 46", GalleryName = "Plains", GalleryIndex = "46", ID = "97", CreatorName = "Aloe_vera", }, Size = { x = 11, y = 7, z = 7, }, Hitbox = { MinX = -1, MinY = -1, MinZ = 0, MaxX = 11, MaxY = 6, MaxZ = 7, }, Connectors = { { Type = -1, RelX = 5, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 4: 0", -- cobblestone "b: 67: 0", -- stonestairs "c: 67: 2", -- stonestairs "d: 67: 1", -- stonestairs "e: 17: 0", -- tree "f: 5: 0", -- planks "g: 64: 3", -- woodendoorblock "h: 53: 3", -- woodstairs "i: 85: 0", -- fence "j: 53: 2", -- woodstairs "k: 53: 1", -- woodstairs "l: 53: 0", -- woodstairs "m: 19: 0", -- sponge "n:102: 0", -- glasspane "o: 64: 9", -- woodendoorblock "p: 50: 3", -- torch "q: 72: 0", -- woodplate "r: 53: 7", -- woodstairs "s: 47: 0", -- bookshelf "t: 50: 1", -- torch "u: 50: 2", -- torch "v: 53: 6", -- woodstairs }, BlockData = { -- Level 0 "mmmmaaammmm", -- 0 "maaaaaaaaam", -- 1 "maaaaaaaaam", -- 2 "maaaaaaaaam", -- 3 "maaaaaaaaam", -- 4 "maaaaaaaaam", -- 5 "mmmmmmmmmmm", -- 6 -- Level 1 "....bcd....", -- 0 ".aaaaaaaaa.", -- 1 ".aaaaaaaaa.", -- 2 ".aaaaaaaaa.", -- 3 ".aaaaaaaaa.", -- 4 ".aaaaaaaaa.", -- 5 "...........", -- 6 -- Level 2 "...........", -- 0 ".efffgfffe.", -- 1 ".fh.....hf.", -- 2 ".fi.....if.", -- 3 ".fj.kil.jf.", -- 4 ".efffffffe.", -- 5 "...........", -- 6 -- Level 3 "...........", -- 0 ".ennfofnne.", -- 1 ".n..p.p..n.", -- 2 ".nq.....qn.", -- 3 ".n...q...n.", -- 4 ".ennnfnnne.", -- 5 "...........", -- 6 -- Level 4 "jjjjjjjjjjj", -- 0 "rfffffffffr", -- 1 ".fsssssssf.", -- 2 ".ft.....uf.", -- 3 ".fsssssssf.", -- 4 "vfffffffffv", -- 5 "hhhhhhhhhhh", -- 6 -- Level 5 "...........", -- 0 "jjjjjjjjjjj", -- 1 "rfffffffffr", -- 2 ".f.......f.", -- 3 "vfffffffffv", -- 4 "hhhhhhhhhhh", -- 5 "...........", -- 6 -- Level 6 "...........", -- 0 "...........", -- 1 "jjjjjjjjjjj", -- 2 "fffffffffff", -- 3 "hhhhhhhhhhh", -- 4 "...........", -- 5 "...........", -- 6 }, }, -- WoodenHouse9x5Library { OriginData = { ExportName = "WoodenHouse10x7Library", Name = "Plains 47", GalleryName = "Plains", GalleryIndex = "47", ID = "98", CreatorName = "Aloe_vera", }, Size = { x = 12, y = 8, z = 9, }, Hitbox = { MinX = -1, MinY = -1, MinZ = 0, MaxX = 12, MaxY = 7, MaxZ = 9, }, Connectors = { { Type = -1, RelX = 5, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 4: 0", -- cobblestone "b: 67: 0", -- stonestairs "c: 67: 2", -- stonestairs "d: 67: 1", -- stonestairs "e: 17: 0", -- tree "f: 5: 0", -- planks "g: 64: 3", -- woodendoorblock "h: 53: 3", -- woodstairs "i: 85: 0", -- fence "j: 53: 2", -- woodstairs "k: 53: 1", -- woodstairs "l: 53: 0", -- woodstairs "m: 19: 0", -- sponge "n:102: 0", -- glasspane "o: 64: 8", -- woodendoorblock "p: 64: 9", -- woodendoorblock "q: 50: 3", -- torch "r: 72: 0", -- woodplate "s: 53: 7", -- woodstairs "t: 47: 0", -- bookshelf "u: 50: 1", -- torch "v: 50: 2", -- torch "w: 53: 6", -- woodstairs }, BlockData = { -- Level 0 "mmmmaaaammmm", -- 0 "maaaaaaaaaam", -- 1 "maaaaaaaaaam", -- 2 "maaaaaaaaaam", -- 3 "maaaaaaaaaam", -- 4 "maaaaaaaaaam", -- 5 "maaaaaaaaaam", -- 6 "maaaaaaaaaam", -- 7 "mmmmmmmmmmmm", -- 8 -- Level 1 "....bccd....", -- 0 ".aaaaaaaaaa.", -- 1 ".aaaaaaaaaa.", -- 2 ".aaaaaaaaaa.", -- 3 ".aaaaaaaaaa.", -- 4 ".aaaaaaaaaa.", -- 5 ".aaaaaaaaaa.", -- 6 ".aaaaaaaaaa.", -- 7 "............", -- 8 -- Level 2 "............", -- 0 ".efffggfffe.", -- 1 ".f........f.", -- 2 ".fh......hf.", -- 3 ".fi......if.", -- 4 ".fj......jf.", -- 5 ".f.kilkil.f.", -- 6 ".effffffffe.", -- 7 "............", -- 8 -- Level 3 "............", -- 0 ".ennfopfnne.", -- 1 ".n..q..q..n.", -- 2 ".n........n.", -- 3 ".fr......rf.", -- 4 ".n........n.", -- 5 ".n..r..r..n.", -- 6 ".ennfnnfnne.", -- 7 "............", -- 8 -- Level 4 "jjjjjjjjjjjj", -- 0 "sffffffffffs", -- 1 ".fttttttttf.", -- 2 ".f........f.", -- 3 ".fu......vf.", -- 4 ".f........f.", -- 5 ".fttttttttf.", -- 6 "wffffffffffw", -- 7 "hhhhhhhhhhhh", -- 8 -- Level 5 "............", -- 0 "jjjjjjjjjjjj", -- 1 "sffffffffffs", -- 2 ".fttttttttf.", -- 3 ".f........f.", -- 4 ".fttttttttf.", -- 5 "wffffffffffw", -- 6 "hhhhhhhhhhhh", -- 7 "............", -- 8 -- Level 6 "............", -- 0 "............", -- 1 "jjjjjjjjjjjj", -- 2 "sffffffffffs", -- 3 ".f........f.", -- 4 "wffffffffffw", -- 5 "hhhhhhhhhhhh", -- 6 "............", -- 7 "............", -- 8 -- Level 7 "............", -- 0 "............", -- 1 "............", -- 2 "jjjjjjjjjjjj", -- 3 "ffffffffffff", -- 4 "hhhhhhhhhhhh", -- 5 "............", -- 6 "............", -- 7 "............", -- 8 }, }, -- WoodenHouse10x7Library { OriginData = { ExportName = "WoodenHouse9x7Butcher", Name = "Plains 48", GalleryName = "Plains", GalleryIndex = "48", ID = "99", CreatorName = "Aloe_vera", }, Size = { x = 11, y = 8, z = 13, }, Hitbox = { MinX = -1, MinY = 0, MinZ = 0, MaxX = 11, MaxY = 7, MaxZ = 13, }, Connectors = { { Type = -1, RelX = 5, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 4: 0", -- cobblestone "b: 3: 0", -- dirt "c: 67: 0", -- stonestairs "d: 67: 2", -- stonestairs "e: 67: 1", -- stonestairs "f: 43: 0", -- doublestoneslab "g: 2: 0", -- grass "h: 17: 0", -- tree "i: 5: 0", -- planks "j: 64: 3", -- woodendoorblock "k: 53: 3", -- woodstairs "l: 85: 0", -- fence "m: 19: 0", -- sponge "n: 53: 2", -- woodstairs "o: 64: 1", -- woodendoorblock "p:102: 0", -- glasspane "q: 64: 9", -- woodendoorblock "r: 72: 0", -- woodplate "s: 53: 7", -- woodstairs "t: 50: 1", -- torch "u: 50: 2", -- torch "v: 53: 6", -- woodstairs }, BlockData = { -- Level 0 "mmmmaaammmm", -- 0 "maaaaaaaaam", -- 1 "maaaaaaaaam", -- 2 "maaaaaaaaam", -- 3 "maaaaaaaaam", -- 4 "maaaaaaaaam", -- 5 "maaaaaaaaam", -- 6 "maaaaaaaaam", -- 7 "mmbbbbbbbmm", -- 8 "mmbbbbbbbmm", -- 9 "mmbbbbbbbmm", -- 10 "mmbbbbbbbmm", -- 11 "mmbbbbbbbmm", -- 12 -- Level 1 "....cde....", -- 0 ".aaaaaaaaa.", -- 1 ".affffaaaa.", -- 2 ".affffaaaa.", -- 3 ".affffaaaa.", -- 4 ".affffaaaa.", -- 5 ".affffaaaa.", -- 6 ".aaaaaaaaa.", -- 7 "..ggggggg..", -- 8 "mmgggggggmm", -- 9 "mmgggggggmm", -- 10 "mmgggggggmm", -- 11 "mmgggggggmm", -- 12 -- Level 2 "...........", -- 0 ".hiiijiiih.", -- 1 ".i.f....ki.", -- 2 ".i.f....li.", -- 3 ".i.f....ni.", -- 4 ".i.......i.", -- 5 ".i.......i.", -- 6 ".hiiioiiih.", -- 7 "..l.....l..", -- 8 "mml.....lmm", -- 9 "mml.....lmm", -- 10 "mml.....lmm", -- 11 "mmlllllllmm", -- 12 -- Level 3 "...........", -- 0 ".hppiqipph.", -- 1 ".p.......p.", -- 2 ".p......rp.", -- 3 ".i.......i.", -- 4 ".p.......p.", -- 5 ".p.......p.", -- 6 ".hppiqipph.", -- 7 "...........", -- 8 "mm.......mm", -- 9 "mm.......mm", -- 10 "mm.......mm", -- 11 "mm.......mm", -- 12 -- Level 4 "nnnnnnnnnnn", -- 0 "siiiiiiiiis", -- 1 ".i.......i.", -- 2 ".i.......i.", -- 3 ".it.....ui.", -- 4 ".i.......i.", -- 5 ".i.......i.", -- 6 "viiiiiiiiiv", -- 7 "kkkkkkkkkkk", -- 8 "mm.......mm", -- 9 "mm.......mm", -- 10 "mm.......mm", -- 11 "mm.......mm", -- 12 -- Level 5 "...........", -- 0 "nnnnnnnnnnn", -- 1 "siiiiiiiiis", -- 2 ".i.......i.", -- 3 ".i.......i.", -- 4 ".i.......i.", -- 5 "viiiiiiiiiv", -- 6 "kkkkkkkkkkk", -- 7 "...........", -- 8 "mm.......mm", -- 9 "mm.......mm", -- 10 "mm.......mm", -- 11 "mm.......mm", -- 12 -- Level 6 "...........", -- 0 "...........", -- 1 "nnnnnnnnnnn", -- 2 "siiiiiiiiis", -- 3 ".i.......i.", -- 4 "viiiiiiiiiv", -- 5 "kkkkkkkkkkk", -- 6 "...........", -- 7 "...........", -- 8 "mm.......mm", -- 9 "mm.......mm", -- 10 "mm.......mm", -- 11 "mm.......mm", -- 12 -- Level 7 "...........", -- 0 "...........", -- 1 "...........", -- 2 "nnnnnnnnnnn", -- 3 "iiiiiiiiiii", -- 4 "kkkkkkkkkkk", -- 5 "...........", -- 6 "...........", -- 7 "...........", -- 8 "mm.......mm", -- 9 "mm.......mm", -- 10 "mm.......mm", -- 11 "mm.......mm", -- 12 }, }, -- WoodenHouse9x7Butcher { OriginData = { ExportName = "WoodenHouse5x5", Name = "Plains 49", GalleryName = "Plains", GalleryIndex = "49", ID = "100", CreatorName = "Aloe_vera", }, Size = { x = 7, y = 7, z = 7, }, Hitbox = { MinX = -1, MinY = -1, MinZ = 0, MaxX = 7, MaxY = 6, MaxZ = 7, }, Connectors = { { Type = -1, RelX = 3, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 4: 0", -- cobblestone "b: 67: 0", -- stonestairs "c: 67: 2", -- stonestairs "d: 67: 1", -- stonestairs "e: 17: 0", -- tree "f: 5: 0", -- planks "g: 64: 3", -- woodendoorblock "h: 64: 9", -- woodendoorblock "i:102: 0", -- glasspane "j: 53: 2", -- woodstairs "k: 53: 7", -- woodstairs "l: 50: 3", -- torch "m: 19: 0", -- sponge "n: 53: 6", -- woodstairs "o: 53: 3", -- woodstairs }, BlockData = { -- Level 0 "mmaaamm", -- 0 "maaaaam", -- 1 "maaaaam", -- 2 "maaaaam", -- 3 "maaaaam", -- 4 "maaaaam", -- 5 "mmmmmmm", -- 6 -- Level 1 "..bcd..", -- 0 ".aaaaa.", -- 1 ".aaaaa.", -- 2 ".aaaaa.", -- 3 ".aaaaa.", -- 4 ".aaaaa.", -- 5 ".......", -- 6 -- Level 2 ".......", -- 0 ".efgfe.", -- 1 ".f...f.", -- 2 ".f...f.", -- 3 ".f...f.", -- 4 ".efffe.", -- 5 ".......", -- 6 -- Level 3 ".......", -- 0 ".efhfe.", -- 1 ".i...i.", -- 2 ".i...i.", -- 3 ".i...i.", -- 4 ".eiiie.", -- 5 ".......", -- 6 -- Level 4 "jjjjjjj", -- 0 "kfffffk", -- 1 ".fl.lf.", -- 2 ".f...f.", -- 3 ".f...f.", -- 4 "nfffffn", -- 5 "ooooooo", -- 6 -- Level 5 ".......", -- 0 "jjjjjjj", -- 1 "kfffffk", -- 2 ".f...f.", -- 3 "nfffffn", -- 4 "ooooooo", -- 5 ".......", -- 6 -- Level 6 ".......", -- 0 ".......", -- 1 "jjjjjjj", -- 2 "fffffff", -- 3 "ooooooo", -- 4 ".......", -- 5 ".......", -- 6 }, }, -- WoodenHouse5x5 { OriginData = { ExportName = "Forge", Name = "Plains 51", GalleryName = "Plains", GalleryIndex = "51", ID = "102", CreatorName = "Aloe_vera", }, Size = { x = 12, y = 9, z = 11, }, Hitbox = { MinX = -1, MinY = -1, MinZ = 0, MaxX = 12, MaxY = 8, MaxZ = 11, }, Connectors = { { Type = -1, RelX = 7, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 4: 0", -- cobblestone "b: 67: 0", -- stonestairs "c: 67: 2", -- stonestairs "d: 67: 1", -- stonestairs "e: 17: 0", -- tree "f: 5: 0", -- planks "g: 64: 0", -- woodendoorblock "h: 10: 0", -- lava "i: 54: 2", -- chest "j: 61: 2", -- furnace "k:102: 0", -- glasspane "l: 64: 9", -- woodendoorblock "m: 19: 0", -- sponge "n:139: 0", -- cobblestonewall "o:101: 0", -- ironbars "p: 53: 2", -- woodstairs "q: 53: 7", -- woodstairs "r: 50: 2", -- torch "s: 50: 1", -- torch "t: 53: 6", -- woodstairs "u: 53: 3", -- woodstairs "v: 43: 0", -- doublestoneslab "w: 44: 0", -- stone_slab }, BlockData = { -- Level 0 "mmmmmaaaaamm", -- 0 "maaaaaaaaamm", -- 1 "maaaaaaaaamm", -- 2 "maaaaaaaaaaa", -- 3 "maaaaaaaaaaa", -- 4 "maaaaaaaaaaa", -- 5 "maaaaaaaaaaa", -- 6 "maaaaaaaaaaa", -- 7 "maaaaammmmmm", -- 8 "maaaaammmmmm", -- 9 "mmmmmmmmmmmm", -- 10 -- Level 1 ".....bcccd..", -- 0 ".aaaaaaaad..", -- 1 ".aaaaaaaad..", -- 2 ".aaaaaaaaaaa", -- 3 ".aaaaaaaaaaa", -- 4 ".aaaaaaaaaaa", -- 5 ".aaaaaaaaaaa", -- 6 ".aaaaaaaaaaa", -- 7 ".aaaaa......", -- 8 ".aaaaa......", -- 9 "............", -- 10 -- Level 2 "............", -- 0 ".efffe......", -- 1 ".f...g......", -- 2 ".f...ea..aaa", -- 3 ".f...f...aha", -- 4 ".f...f...aha", -- 5 ".f...fijjaha", -- 6 ".f...eaaaaaa", -- 7 ".f...f......", -- 8 ".efffe......", -- 9 "............", -- 10 -- Level 3 "............", -- 0 ".ekkke......", -- 1 ".k...l......", -- 2 ".k...en..n.a", -- 3 ".k...k.....o", -- 4 ".f...k.....o", -- 5 ".k...k.....o", -- 6 ".k...eaooooa", -- 7 ".k...f......", -- 8 ".ekkke......", -- 9 "............", -- 10 -- Level 4 "ppppppp.....", -- 0 "qfffffq.....", -- 1 ".f...f......", -- 2 ".f..rfa..aoa", -- 3 ".f...f...o.a", -- 4 ".f...f...o.a", -- 5 ".fs..f...o.a", -- 6 ".f...faaaaaa", -- 7 ".f...f......", -- 8 "tffffft.....", -- 9 "uuuuuuu.....", -- 10 -- Level 5 "............", -- 0 "ppppppp.....", -- 1 "qfffffq.....", -- 2 ".f...fvvvvvv", -- 3 ".f...fvwwwwv", -- 4 ".f...fvwwwwv", -- 5 ".f...fvwwwwv", -- 6 ".f...fvvvvvv", -- 7 "tffffft.....", -- 8 "uuuuuuu.....", -- 9 "............", -- 10 -- Level 6 "............", -- 0 "............", -- 1 "ppppppp.....", -- 2 "qfffffq.....", -- 3 ".f...f......", -- 4 ".f...f......", -- 5 ".f...f......", -- 6 "tffffft.....", -- 7 "uuuuuuu.....", -- 8 "............", -- 9 "............", -- 10 -- Level 7 "............", -- 0 "............", -- 1 "............", -- 2 "ppppppp.....", -- 3 "qfffffq.....", -- 4 ".f...f......", -- 5 "tffffft.....", -- 6 "uuuuuuu.....", -- 7 "............", -- 8 "............", -- 9 "............", -- 10 -- Level 8 "............", -- 0 "............", -- 1 "............", -- 2 "............", -- 3 "ppppppp.....", -- 4 "fffffff.....", -- 5 "uuuuuuu.....", -- 6 "............", -- 7 "............", -- 8 "............", -- 9 "............", -- 10 }, }, -- Forge { OriginData = { ExportName = "WoodenHouse9x7", Name = "Plains 52", GalleryName = "Plains", GalleryIndex = "52", ID = "103", CreatorName = "Aloe_vera", }, Size = { x = 11, y = 8, z = 9, }, Hitbox = { MinX = -1, MinY = -1, MinZ = 0, MaxX = 11, MaxY = 7, MaxZ = 9, }, Connectors = { { Type = -1, RelX = 5, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 4: 0", -- cobblestone "b: 67: 0", -- stonestairs "c: 67: 2", -- stonestairs "d: 67: 1", -- stonestairs "e: 17: 0", -- tree "f: 5: 0", -- planks "g: 64: 3", -- woodendoorblock "h:102: 0", -- glasspane "i: 64: 9", -- woodendoorblock "j: 53: 2", -- woodstairs "k: 53: 7", -- woodstairs "l: 50: 3", -- torch "m: 19: 0", -- sponge "n: 50: 4", -- torch "o: 53: 6", -- woodstairs "p: 53: 3", -- woodstairs }, BlockData = { -- Level 0 "mmmmaaammmm", -- 0 "maaaaaaaaam", -- 1 "maaaaaaaaam", -- 2 "maaaaaaaaam", -- 3 "maaaaaaaaam", -- 4 "maaaaaaaaam", -- 5 "maaaaaaaaam", -- 6 "maaaaaaaaam", -- 7 "mmmmmmmmmmm", -- 8 -- Level 1 "....bcd....", -- 0 ".aaaaaaaaa.", -- 1 ".aaaaaaaaa.", -- 2 ".aaaaaaaaa.", -- 3 ".aaaaaaaaa.", -- 4 ".aaaaaaaaa.", -- 5 ".aaaaaaaaa.", -- 6 ".aaaaaaaaa.", -- 7 "...........", -- 8 -- Level 2 "...........", -- 0 ".efffgfffe.", -- 1 ".f.......f.", -- 2 ".f.......f.", -- 3 ".f.......f.", -- 4 ".f.......f.", -- 5 ".f.......f.", -- 6 ".efffffffe.", -- 7 "...........", -- 8 -- Level 3 "...........", -- 0 ".ehhfifhhe.", -- 1 ".h.......h.", -- 2 ".h.......h.", -- 3 ".f.......f.", -- 4 ".h.......h.", -- 5 ".h.......h.", -- 6 ".ehhhfhhhe.", -- 7 "...........", -- 8 -- Level 4 "jjjjjjjjjjj", -- 0 "kfffffffffk", -- 1 ".f..l.l..f.", -- 2 ".f.......f.", -- 3 ".f.......f.", -- 4 ".f.......f.", -- 5 ".f...n...f.", -- 6 "offfffffffo", -- 7 "ppppppppppp", -- 8 -- Level 5 "...........", -- 0 "jjjjjjjjjjj", -- 1 "kfffffffffk", -- 2 ".f.......f.", -- 3 ".f.......f.", -- 4 ".f.......f.", -- 5 "offfffffffo", -- 6 "ppppppppppp", -- 7 "...........", -- 8 -- Level 6 "...........", -- 0 "...........", -- 1 "jjjjjjjjjjj", -- 2 "kfffffffffk", -- 3 ".f.......f.", -- 4 "offfffffffo", -- 5 "ppppppppppp", -- 6 "...........", -- 7 "...........", -- 8 -- Level 7 "...........", -- 0 "...........", -- 1 "...........", -- 2 "jjjjjjjjjjj", -- 3 "fffffffffff", -- 4 "ppppppppppp", -- 5 "...........", -- 6 "...........", -- 7 "...........", -- 8 }, }, -- WoodenHouse9x7 { OriginData = { ExportName = "WoodenGranary", Name = "Plains 54", GalleryName = "Plains", GalleryIndex = "54", ID = "105", CreatorName = "Aloe_vera", }, Size = { x = 7, y = 7, z = 9, }, Hitbox = { MinX = -1, MinY = -1, MinZ = 0, MaxX = 7, MaxY = 6, MaxZ = 9, }, Connectors = { { Type = -1, RelX = 3, RelY = 1, RelZ = -1, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "20", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 4: 0", -- cobblestone "b:170: 0", -- hayblock "c: 67: 0", -- stonestairs "d: 67: 2", -- stonestairs "e: 67: 1", -- stonestairs "f: 17: 0", -- tree "g: 5: 0", -- planks "h:170: 4", -- hayblock "i:170: 8", -- hayblock "j: 54: 2", -- chest "k: 50: 4", -- torch "l: 53: 0", -- woodstairs "m: 19: 0", -- sponge "n: 53: 5", -- woodstairs "o: 53: 4", -- woodstairs "p: 53: 1", -- woodstairs }, BlockData = { -- Level 0 "maaaaam", -- 0 "maaaaam", -- 1 "maaaaam", -- 2 "maaaaam", -- 3 "maaaaam", -- 4 "maaaaam", -- 5 "maaaaam", -- 6 "maaaaam", -- 7 "mmmmmmm", -- 8 -- Level 1 "bcddde.", -- 0 ".aaaaa.", -- 1 ".aaaaa.", -- 2 ".aaaaa.", -- 3 ".aaaaa.", -- 4 ".aaaaa.", -- 5 ".aaaaa.", -- 6 ".aaaaa.", -- 7 ".......", -- 8 -- Level 2 ".......", -- 0 ".f..bf.", -- 1 ".g...g.", -- 2 ".gb.hg.", -- 3 ".fihif.", -- 4 ".gbbbg.", -- 5 ".gijbg.", -- 6 ".fgfgf.", -- 7 ".......", -- 8 -- Level 3 ".k...k.", -- 0 ".f...f.", -- 1 ".g...g.", -- 2 ".g...g.", -- 3 ".fh..f.", -- 4 ".ghibg.", -- 5 ".ghiig.", -- 6 ".fgfgf.", -- 7 ".......", -- 8 -- Level 4 "ln...op", -- 0 "lgggggp", -- 1 "lg...gp", -- 2 "lg...gp", -- 3 "lg...gp", -- 4 "lgbb.gp", -- 5 "lgibigp", -- 6 "lgggggp", -- 7 "ln...op", -- 8 -- Level 5 ".ln.op.", -- 0 ".lgggp.", -- 1 ".lg.gp.", -- 2 ".lg.gp.", -- 3 ".lg.gp.", -- 4 ".lg.gp.", -- 5 ".lg.gp.", -- 6 ".lgggp.", -- 7 ".ln.op.", -- 8 -- Level 6 "..lgp..", -- 0 "..lgp..", -- 1 "..lgp..", -- 2 "..lgp..", -- 3 "..lgp..", -- 4 "..lgp..", -- 5 "..lgp..", -- 6 "..lgp..", -- 7 "..lgp..", -- 8 }, }, -- WoodenGranary { OriginData = { ExportName = "WoodenStables", Name = "Plains 55", GalleryName = "Plains", GalleryIndex = "55", ID = "106", CreatorName = "Aloe_vera", }, Size = { x = 15, y = 9, z = 9, }, Hitbox = { MinX = -1, MinY = -1, MinZ = 0, MaxX = 15, MaxY = 8, MaxZ = 9, }, Connectors = { { Type = -1, RelX = 7, RelY = 1, RelZ = -1, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 4: 0", -- cobblestone "b: 67: 0", -- stonestairs "c: 67: 2", -- stonestairs "d: 67: 1", -- stonestairs "e: 3: 0", -- dirt "f: 17: 0", -- tree "g:107: 0", -- fencegate "h:107: 4", -- fencegate "i: 5: 0", -- planks "j:107: 6", -- fencegate "k: 85: 0", -- fence "l:170: 0", -- hayblock "m: 19: 0", -- sponge "n:170: 4", -- hayblock "o:170: 8", -- hayblock "p: 50: 1", -- torch "q: 50: 2", -- torch "r: 53: 2", -- woodstairs "s: 53: 7", -- woodstairs "t: 53: 6", -- woodstairs "u: 53: 3", -- woodstairs }, BlockData = { -- Level 0 "maaaaaaaaaaaaam", -- 0 "maaaaaaaaaaaaam", -- 1 "maaaaaaaaaaaaam", -- 2 "maaaaaaaaaaaaam", -- 3 "maaaaaaaaaaaaam", -- 4 "maaaaaaaaaaaaam", -- 5 "maaaaaaaaaaaaam", -- 6 "maaaaaaaaaaaaam", -- 7 "mmmmmmmmmmmmmmm", -- 8 -- Level 1 ".bcccccccccccd.", -- 0 ".aaaaaaaaaaaaa.", -- 1 ".aeeeeeeeeeeea.", -- 2 ".aeeeeeeeeeeea.", -- 3 ".aeeeeeeeeeeea.", -- 4 ".aeeeeeeeeeeea.", -- 5 ".aeeeeeeeeeeea.", -- 6 ".aaaaaaaaaaaaa.", -- 7 "...............", -- 8 -- Level 2 "...............", -- 0 ".fghgighgigjgf.", -- 1 ".k...k...k...k.", -- 2 ".k...k...k...k.", -- 3 ".k...k...k...k.", -- 4 ".k...k...k...k.", -- 5 ".kl..k..nko..k.", -- 6 ".fkkkikkkikkkf.", -- 7 "...............", -- 8 -- Level 3 "...............", -- 0 ".f...i...i...f.", -- 1 "...............", -- 2 "...............", -- 3 "...............", -- 4 "...............", -- 5 "...............", -- 6 ".f...i...i...f.", -- 7 "...............", -- 8 -- Level 4 "...............", -- 0 ".fp.qip.qip.qf.", -- 1 "...............", -- 2 "...............", -- 3 "...............", -- 4 "...............", -- 5 "...............", -- 6 ".f...i...i...f.", -- 7 "...............", -- 8 -- Level 5 "rrrrrrrrrrrrrrr", -- 0 "siiiiiiiiiiiiis", -- 1 ".i...........i.", -- 2 ".i...........i.", -- 3 ".i...........i.", -- 4 ".i...........i.", -- 5 ".i...........i.", -- 6 "tiiiiiiiiiiiiit", -- 7 "uuuuuuuuuuuuuuu", -- 8 -- Level 6 "...............", -- 0 "rrrrrrrrrrrrrrr", -- 1 "siiiiiiiiiiiiis", -- 2 ".i...........i.", -- 3 ".i...........i.", -- 4 ".i...........i.", -- 5 "tiiiiiiiiiiiiit", -- 6 "uuuuuuuuuuuuuuu", -- 7 "...............", -- 8 -- Level 7 "...............", -- 0 "...............", -- 1 "rrrrrrrrrrrrrrr", -- 2 "siiiiiiiiiiiiis", -- 3 ".i...........i.", -- 4 "tiiiiiiiiiiiiit", -- 5 "uuuuuuuuuuuuuuu", -- 6 "...............", -- 7 "...............", -- 8 -- Level 8 "...............", -- 0 "...............", -- 1 "...............", -- 2 "rrrrrrrrrrrrrrr", -- 3 "iiiiiiiiiiiiiii", -- 4 "uuuuuuuuuuuuuuu", -- 5 "...............", -- 6 "...............", -- 7 "...............", -- 8 }, }, -- WoodenStables { OriginData = { ExportName = "WoodenChurchMid", Name = "Plains 58", GalleryName = "Plains", GalleryIndex = "58", ID = "109", CreatorName = "Aloe_vera", }, Size = { x = 7, y = 15, z = 13, }, Hitbox = { MinX = -1, MinY = 0, MinZ = 0, MaxX = 7, MaxY = 14, MaxZ = 13, }, Connectors = { { Type = -1, RelX = 3, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "20", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "A: 85: 0", -- fence "B:126: 8", -- woodenslab "a: 4: 0", -- cobblestone "b: 67: 0", -- stonestairs "c: 67: 2", -- stonestairs "d: 67: 1", -- stonestairs "e: 17: 0", -- tree "f: 5: 0", -- planks "g: 64: 1", -- woodendoorblock "h: 65: 3", -- ladder "i: 53: 3", -- woodstairs "j: 53: 7", -- woodstairs "k: 64: 9", -- woodendoorblock "l:102: 0", -- glasspane "m: 19: 0", -- sponge "n: 50: 1", -- torch "o: 50: 2", -- torch "p:171:14", -- carpet "q: 50: 3", -- torch "r: 53: 2", -- woodstairs "s: 53: 0", -- woodstairs "t: 53: 1", -- woodstairs "u: 53: 5", -- woodstairs "v: 53: 4", -- woodstairs "w: 17: 4", -- tree "x: 17: 8", -- tree "y: 54: 2", -- chest "z: 50: 4", -- torch }, BlockData = { -- Level 0 "mmaaamm", -- 0 "maaaaam", -- 1 "maaaaam", -- 2 "maaaaam", -- 3 "maaaaam", -- 4 "maaaaam", -- 5 "maaaaam", -- 6 "maaaaam", -- 7 "maaaaam", -- 8 "maaaaam", -- 9 "maaaaam", -- 10 "maaaaam", -- 11 "mmmmmmm", -- 12 -- Level 1 "..bcd..", -- 0 ".aaaaa.", -- 1 ".aaaaa.", -- 2 ".aaaaa.", -- 3 ".aaaaa.", -- 4 ".aaaaa.", -- 5 ".aaaaa.", -- 6 ".aaaaa.", -- 7 ".aaaaa.", -- 8 ".aaaaa.", -- 9 ".aaaaa.", -- 10 ".aaaaa.", -- 11 ".......", -- 12 -- Level 2 ".......", -- 0 ".efgfe.", -- 1 ".f..hf.", -- 2 ".f...f.", -- 3 ".f...f.", -- 4 ".ei.ie.", -- 5 ".f...f.", -- 6 ".fi.if.", -- 7 ".f...f.", -- 8 ".f.j.f.", -- 9 ".f...f.", -- 10 ".efffe.", -- 11 ".......", -- 12 -- Level 3 ".......", -- 0 ".efkfe.", -- 1 ".l..hl.", -- 2 ".l...l.", -- 3 ".l...l.", -- 4 ".e...e.", -- 5 ".l...l.", -- 6 ".l...l.", -- 7 ".fn.of.", -- 8 ".l.p.l.", -- 9 ".l...l.", -- 10 ".ellle.", -- 11 ".......", -- 12 -- Level 4 ".......", -- 0 ".efffe.", -- 1 ".f.qhf.", -- 2 ".f...f.", -- 3 ".f...f.", -- 4 "re...er", -- 5 "sf...ft", -- 6 "sf...ft", -- 7 "sf...ft", -- 8 "sf...ft", -- 9 "sf...ft", -- 10 "sefffet", -- 11 "su...vt", -- 12 -- Level 5 ".......", -- 0 ".ewwwe.", -- 1 ".xffhx.", -- 2 ".xfffx.", -- 3 ".xfffx.", -- 4 ".ewwwe.", -- 5 ".sf.ft.", -- 6 ".sf.ft.", -- 7 ".sf.ft.", -- 8 ".sf.ft.", -- 9 ".sf.ft.", -- 10 ".sffft.", -- 11 ".su.vt.", -- 12 -- Level 6 ".......", -- 0 ".eflfe.", -- 1 ".f..hf.", -- 2 ".f...f.", -- 3 ".f.y.f.", -- 4 ".efffe.", -- 5 "..sft..", -- 6 "..sft..", -- 7 "..sft..", -- 8 "..sft..", -- 9 "..sft..", -- 10 "..sft..", -- 11 "..sft..", -- 12 -- Level 7 ".......", -- 0 ".eflfe.", -- 1 ".f..hf.", -- 2 ".l...l.", -- 3 ".f...f.", -- 4 ".efffe.", -- 5 ".......", -- 6 ".......", -- 7 ".......", -- 8 ".......", -- 9 ".......", -- 10 ".......", -- 11 ".......", -- 12 -- Level 8 ".......", -- 0 ".eflfe.", -- 1 ".f..hf.", -- 2 ".f...f.", -- 3 ".f.z.f.", -- 4 ".efffe.", -- 5 ".......", -- 6 ".......", -- 7 ".......", -- 8 ".......", -- 9 ".......", -- 10 ".......", -- 11 ".......", -- 12 -- Level 9 ".......", -- 0 ".ewwwe.", -- 1 ".xffhx.", -- 2 ".xfffx.", -- 3 ".xfffx.", -- 4 ".ewwwe.", -- 5 ".......", -- 6 ".......", -- 7 ".......", -- 8 ".......", -- 9 ".......", -- 10 ".......", -- 11 ".......", -- 12 -- Level 10 ".......", -- 0 ".eAAAe.", -- 1 ".A...A.", -- 2 ".A...A.", -- 3 ".A...A.", -- 4 ".eAAAe.", -- 5 ".......", -- 6 ".......", -- 7 ".......", -- 8 ".......", -- 9 ".......", -- 10 ".......", -- 11 ".......", -- 12 -- Level 11 ".......", -- 0 ".e...e.", -- 1 ".......", -- 2 ".......", -- 3 ".......", -- 4 ".e...e.", -- 5 ".......", -- 6 ".......", -- 7 ".......", -- 8 ".......", -- 9 ".......", -- 10 ".......", -- 11 ".......", -- 12 -- Level 12 "su...vt", -- 0 "sefffet", -- 1 "sfBBBft", -- 2 "sfBBBft", -- 3 "sfBBBft", -- 4 "sefffet", -- 5 "su...vt", -- 6 ".......", -- 7 ".......", -- 8 ".......", -- 9 ".......", -- 10 ".......", -- 11 ".......", -- 12 -- Level 13 ".su.vt.", -- 0 ".sffft.", -- 1 ".sffft.", -- 2 ".sffft.", -- 3 ".sffft.", -- 4 ".sffft.", -- 5 ".su.vt.", -- 6 ".......", -- 7 ".......", -- 8 ".......", -- 9 ".......", -- 10 ".......", -- 11 ".......", -- 12 -- Level 14 "..sft..", -- 0 "..sft..", -- 1 "..sft..", -- 2 "..sft..", -- 3 "..sft..", -- 4 "..sft..", -- 5 "..sft..", -- 6 ".......", -- 7 ".......", -- 8 ".......", -- 9 ".......", -- 10 ".......", -- 11 ".......", -- 12 }, }, -- WoodenChurchMid { OriginData = { ExportName = "WoodenMill5x5", Name = "Plains 60", GalleryName = "Plains", GalleryIndex = "60", ID = "111", CreatorName = "Aloe_vera", }, Size = { x = 9, y = 17, z = 13, }, Hitbox = { MinX = -1, MinY = -1, MinZ = 0, MaxX = 8, MaxY = 16, MaxZ = 12, }, Connectors = { { Type = -1, RelX = 8, RelY = 1, RelZ = 6, Direction = 5, -- X+ }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 4: 0", -- cobblestone "b: 67: 2", -- stonestairs "c: 67: 1", -- stonestairs "d: 67: 3", -- stonestairs "e: 17: 0", -- tree "f: 5: 0", -- planks "g: 54: 4", -- chest "h:154: 4", -- hopper "i: 64: 0", -- woodendoorblock "j:102: 0", -- glasspane "k: 85: 0", -- fence "l: 64: 9", -- woodendoorblock "m: 19: 0", -- sponge "n: 50: 2", -- torch "o: 35: 0", -- wool "p: 17: 4", -- tree "q: 17: 8", -- tree "r: 53: 2", -- woodstairs "s: 53: 7", -- woodstairs "t: 53: 6", -- woodstairs "u: 53: 3", -- woodstairs }, BlockData = { -- Level 0 "mmmmmmmmm", -- 0 "mmmmmmmmm", -- 1 "mmmmmmmmm", -- 2 "mmmmmmmmm", -- 3 "maaaaammm", -- 4 "maaaaaamm", -- 5 "maaaaaamm", -- 6 "maaaaaamm", -- 7 "maaaaammm", -- 8 "mmmmmmmmm", -- 9 "mmmmmmmmm", -- 10 "mmmmmmmmm", -- 11 "mmmmmmmmm", -- 12 -- Level 1 "mmmmmmm..", -- 0 "mmmmmmm..", -- 1 "mmmmmmm..", -- 2 ".........", -- 3 ".aaaaa...", -- 4 ".aaaaab..", -- 5 ".aaaaac..", -- 6 ".aaaaad..", -- 7 ".aaaaa...", -- 8 ".........", -- 9 "mmmmmmm..", -- 10 "mmmmmmm..", -- 11 "mmmmmmm..", -- 12 -- Level 2 "mmmmmmm..", -- 0 "mmmmmmm..", -- 1 "mmmmmmm..", -- 2 ".........", -- 3 ".efffe...", -- 4 ".f...f...", -- 5 ".fgh.i...", -- 6 ".f...f...", -- 7 ".efffe...", -- 8 ".........", -- 9 "mmmmmmm..", -- 10 "mmmmmmm..", -- 11 "mmmmmmm..", -- 12 -- Level 3 "mmmmmmm..", -- 0 "mmmmmmm..", -- 1 "mmmmmmm..", -- 2 ".........", -- 3 ".ejjje...", -- 4 ".j...f...", -- 5 ".j.k.l...", -- 6 ".j...f...", -- 7 ".ejjje...", -- 8 ".........", -- 9 "mmmmmmm..", -- 10 "mmmmmmm..", -- 11 "mmmmmmm..", -- 12 -- Level 4 "mmmmmmm..", -- 0 "mmmmmmm..", -- 1 "mmmmmmm..", -- 2 ".........", -- 3 ".efffe...", -- 4 ".f..nf...", -- 5 ".f.k.f...", -- 6 ".f..nf..k", -- 7 ".efffe..o", -- 8 ".........", -- 9 "mmmmmmm..", -- 10 "mmmmmmm..", -- 11 "mmmmmmm..", -- 12 -- Level 5 "mmmmmmm..", -- 0 "mmmmmmm..", -- 1 "mmmmmmm..", -- 2 ".........", -- 3 ".epppe...", -- 4 ".q...q...", -- 5 ".q.k.q...", -- 6 ".q...q..k", -- 7 ".epppe..o", -- 8 ".........", -- 9 "mmmmmmm..", -- 10 "mmmmmmm..", -- 11 "mmmmmmm..", -- 12 -- Level 6 "mmmmmmm..", -- 0 "mmmmmmm..", -- 1 "mmmmmmm..", -- 2 ".........", -- 3 ".efffe...", -- 4 ".f...f...", -- 5 ".f.k.f..k", -- 6 ".f...f..o", -- 7 ".efffe..o", -- 8 ".........", -- 9 "mmmmmmm..", -- 10 "mmmmmmm..", -- 11 "mmmmmmm..", -- 12 -- Level 7 "mmmmmmm..", -- 0 "mmmmmmm..", -- 1 "mmmmmmm..", -- 2 ".........", -- 3 ".ejjje...", -- 4 ".j...j...", -- 5 ".j.k.j..k", -- 6 ".j...j..o", -- 7 ".ejjje...", -- 8 ".........", -- 9 "mmmmmmm..", -- 10 "mmmmmmm..", -- 11 "mmmmmmm..", -- 12 -- Level 8 "mmmmmmm.o", -- 0 "mmmmmmm.o", -- 1 "mmmmmmm.o", -- 2 ".........", -- 3 ".efffe...", -- 4 ".f...f..k", -- 5 ".f.k.f..o", -- 6 ".f...f..o", -- 7 ".efffe...", -- 8 ".........", -- 9 "mmmmmmm..", -- 10 "mmmmmmm..", -- 11 "mmmmmmm..", -- 12 -- Level 9 "mmmmmmm.k", -- 0 "mmmmmmm.k", -- 1 "mmmmmmm.o", -- 2 "........o", -- 3 ".epppe..o", -- 4 ".q...q..k", -- 5 ".q.k.q..o", -- 6 ".q...q..k", -- 7 ".epppe..k", -- 8 ".........", -- 9 "mmmmmmm..", -- 10 "mmmmmmm..", -- 11 "mmmmmmm..", -- 12 -- Level 10 "mmmmmmm..", -- 0 "mmmmmmm..", -- 1 "mmmmmmm.k", -- 2 "rrrrrrr.k", -- 3 "sfffffs.o", -- 4 ".f...f..o", -- 5 ".f.kppppp", -- 6 ".f...f..o", -- 7 "tffffft.o", -- 8 "uuuuuuu.k", -- 9 "mmmmmmm.k", -- 10 "mmmmmmm..", -- 11 "mmmmmmm..", -- 12 -- Level 11 "mmmmmmm..", -- 0 "mmmmmmm..", -- 1 "mmmmmmm..", -- 2 ".........", -- 3 "rrrrrrr.k", -- 4 "sfffffs.k", -- 5 ".f...f..o", -- 6 "tffffft.k", -- 7 "uuuuuuu.o", -- 8 "........o", -- 9 "mmmmmmm.o", -- 10 "mmmmmmm.k", -- 11 "mmmmmmm.k", -- 12 -- Level 12 "mmmmmmm..", -- 0 "mmmmmmm..", -- 1 "mmmmmmm..", -- 2 ".........", -- 3 ".........", -- 4 "rrrrrrr.o", -- 5 "fffffff.o", -- 6 "uuuuuuu.k", -- 7 ".........", -- 8 ".........", -- 9 "mmmmmmm.o", -- 10 "mmmmmmm.o", -- 11 "mmmmmmm.o", -- 12 -- Level 13 "mmmmmmm..", -- 0 "mmmmmmm..", -- 1 "mmmmmmm..", -- 2 ".........", -- 3 ".........", -- 4 "........o", -- 5 "........k", -- 6 ".........", -- 7 ".........", -- 8 ".........", -- 9 "mmmmmmm..", -- 10 "mmmmmmm..", -- 11 "mmmmmmm..", -- 12 -- Level 14 "mmmmmmm..", -- 0 "mmmmmmm..", -- 1 "mmmmmmm..", -- 2 ".........", -- 3 "........o", -- 4 "........o", -- 5 "........k", -- 6 ".........", -- 7 ".........", -- 8 ".........", -- 9 "mmmmmmm..", -- 10 "mmmmmmm..", -- 11 "mmmmmmm..", -- 12 -- Level 15 "mmmmmmm..", -- 0 "mmmmmmm..", -- 1 "mmmmmmm..", -- 2 ".........", -- 3 "........o", -- 4 "........k", -- 5 ".........", -- 6 ".........", -- 7 ".........", -- 8 ".........", -- 9 "mmmmmmm..", -- 10 "mmmmmmm..", -- 11 "mmmmmmm..", -- 12 -- Level 16 "mmmmmmm..", -- 0 "mmmmmmm..", -- 1 "mmmmmmm..", -- 2 ".........", -- 3 "........o", -- 4 "........k", -- 5 ".........", -- 6 ".........", -- 7 ".........", -- 8 ".........", -- 9 "mmmmmmm..", -- 10 "mmmmmmm..", -- 11 "mmmmmmm..", -- 12 }, }, -- WoodenMill5x5 { OriginData = { ExportName = "RoofedWell", Name = "Plains 119", GalleryName = "Plains", GalleryIndex = "119", ID = "271", CreatorName = "STR_Warrior", }, Size = { x = 7, y = 15, z = 7, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 6, MaxY = 14, MaxZ = 6, }, Connectors = { { Type = 2, RelX = 0, RelY = 9, RelZ = 3, Direction = 4, -- X- }, { Type = 2, RelX = 3, RelY = 9, RelZ = 6, Direction = 3, -- Z+ }, { Type = 2, RelX = 6, RelY = 9, RelZ = 3, Direction = 5, -- X+ }, { Type = 2, RelX = 3, RelY = 9, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "1", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", ["VerticalStrategy"] = "TerrainOrOceanTop|-9", }, BlockDefinitions = { ".: 0: 0", -- air "a: 1: 0", -- stone "b: 4: 0", -- cobblestone "c: 8: 0", -- water "d: 3: 0", -- dirt "e: 2: 0", -- grass "f: 13: 0", -- gravel "g:118: 3", -- cauldronblock "h: 85: 0", -- fence "i: 53: 2", -- woodstairs "j: 53: 7", -- woodstairs "k: 5: 0", -- planks "l: 53: 4", -- woodstairs "m: 19: 0", -- sponge "n: 53: 5", -- woodstairs "o: 53: 6", -- woodstairs "p: 53: 3", -- woodstairs }, BlockData = { -- Level 0 "aaaaaaa", -- 0 "aaaaaaa", -- 1 "aaaaaaa", -- 2 "aaaaaaa", -- 3 "aaaaaaa", -- 4 "aaaaaaa", -- 5 "aaaaaaa", -- 6 -- Level 1 "aaaaaaa", -- 0 "abbbbba", -- 1 "abcccba", -- 2 "abcccba", -- 3 "abcccba", -- 4 "abbbbba", -- 5 "aaaaaaa", -- 6 -- Level 2 "aaaaaaa", -- 0 "abbbbba", -- 1 "abcccba", -- 2 "abcccba", -- 3 "abcccba", -- 4 "abbbbba", -- 5 "aaaaaaa", -- 6 -- Level 3 "aaaaaaa", -- 0 "abbbbba", -- 1 "abcccba", -- 2 "abcccba", -- 3 "abcccba", -- 4 "abbbbba", -- 5 "aaaaaaa", -- 6 -- Level 4 "aaaaaaa", -- 0 "abbbbba", -- 1 "abcccba", -- 2 "abcccba", -- 3 "abcccba", -- 4 "abbbbba", -- 5 "aaaaaaa", -- 6 -- Level 5 "ddddddd", -- 0 "dbbbbbd", -- 1 "dbcccbd", -- 2 "dbcccbd", -- 3 "dbcccbd", -- 4 "dbbbbbd", -- 5 "ddddddd", -- 6 -- Level 6 "ddddddd", -- 0 "dbbbbbd", -- 1 "dbcccbd", -- 2 "dbcccbd", -- 3 "dbcccbd", -- 4 "dbbbbbd", -- 5 "ddddddd", -- 6 -- Level 7 "ddddddd", -- 0 "dbbbbbd", -- 1 "dbcccbd", -- 2 "dbcccbd", -- 3 "dbcccbd", -- 4 "dbbbbbd", -- 5 "ddddddd", -- 6 -- Level 8 "eefffee", -- 0 "ebbbbbe", -- 1 "fbcccbf", -- 2 "fbcccbf", -- 3 "fbcccbf", -- 4 "ebbbbbe", -- 5 "eefffee", -- 6 -- Level 9 ".......", -- 0 ".bbbbb.", -- 1 ".b...b.", -- 2 ".b.g.b.", -- 3 ".b...b.", -- 4 ".bbbbb.", -- 5 ".......", -- 6 -- Level 10 ".......", -- 0 ".h...h.", -- 1 ".......", -- 2 "...h...", -- 3 ".......", -- 4 ".h...h.", -- 5 ".......", -- 6 -- Level 11 ".......", -- 0 ".h...h.", -- 1 ".......", -- 2 "...h...", -- 3 ".......", -- 4 ".h...h.", -- 5 ".......", -- 6 -- Level 12 "iiiiiii", -- 0 "jkjjjkj", -- 1 ".l...n.", -- 2 ".l.h.n.", -- 3 ".l...n.", -- 4 "okoooko", -- 5 "ppppppp", -- 6 -- Level 13 ".......", -- 0 "iiiiiii", -- 1 "jkjjjkj", -- 2 ".k.h.k.", -- 3 "okoooko", -- 4 "ppppppp", -- 5 ".......", -- 6 -- Level 14 ".......", -- 0 ".......", -- 1 "iiiiiii", -- 2 "kkkkkkk", -- 3 "ppppppp", -- 4 ".......", -- 5 ".......", -- 6 }, }, -- RoofedWell { OriginData = { ExportName = "MineEntrance", Name = "Plains 138", GalleryName = "Plains", GalleryIndex = "138", ID = "446", CreatorName = "STR_Warrior", }, Size = { x = 7, y = 38, z = 7, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 6, MaxY = 37, MaxZ = 6, }, Connectors = { { Type = 2, RelX = 6, RelY = 32, RelZ = 3, Direction = 5, -- X+ }, { Type = 2, RelX = 3, RelY = 32, RelZ = 6, Direction = 3, -- Z+ }, { Type = 2, RelX = 0, RelY = 32, RelZ = 3, Direction = 4, -- X- }, { Type = 2, RelX = 3, RelY = 32, RelZ = 0, Direction = 2, -- Z- }, { Type = 3, RelX = 3, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "1", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", ["VerticalStrategy"] = "TerrainOrOceanTop|-32", }, BlockDefinitions = { ".: 0: 0", -- air "a: 5: 0", -- planks "b: 77: 2", -- stonebutton "c: 66: 6", -- tracks "d: 27: 1", -- poweredrail "e: 66: 5", -- tracks "f: 66: 9", -- tracks "g: 66: 2", -- tracks "h: 50: 4", -- torch "i: 66: 4", -- tracks "j: 66: 8", -- tracks "k: 66: 3", -- tracks "l: 66: 7", -- tracks "m: 19: 0", -- sponge "n: 50: 2", -- torch "o: 4: 0", -- cobblestone "p: 2: 0", -- grass "q: 13: 0", -- gravel "r: 53: 2", -- woodstairs "s: 77: 1", -- stonebutton "t: 27: 0", -- poweredrail "u: 53: 7", -- woodstairs "v: 53: 6", -- woodstairs "w: 53: 3", -- woodstairs }, BlockData = { -- Level 0 "maaaaam", -- 0 "maaaaam", -- 1 "maaaaam", -- 2 "maaaaam", -- 3 "maaaaam", -- 4 "maaaaam", -- 5 "mmmmmmm", -- 6 -- Level 1 "mm...mm", -- 0 "mm.abam", -- 1 "mmcddam", -- 2 "mae..am", -- 3 "mmaa.mm", -- 4 "mmmammm", -- 5 "mmmmmmm", -- 6 -- Level 2 "mm...mm", -- 0 "mm.a.mm", -- 1 "mm...mm", -- 2 "ma..aam", -- 3 "mmfgamm", -- 4 "mmmammm", -- 5 "mmmmmmm", -- 6 -- Level 3 "mm.h.mm", -- 0 "mm.a.mm", -- 1 "mm.aamm", -- 2 "ma..iam", -- 3 "mm..jmm", -- 4 "mmmammm", -- 5 "mmmmmmm", -- 6 -- Level 4 "mmmmmmm", -- 0 "mmmammm", -- 1 "mmaklmm", -- 2 "maa..am", -- 3 "mm...mm", -- 4 "mmmammm", -- 5 "mmmmmmm", -- 6 -- Level 5 "mmmmmmm", -- 0 "mmmammm", -- 1 "mmc..mm", -- 2 "mae.nam", -- 3 "mmaa.mm", -- 4 "mmmammm", -- 5 "mmmmmmm", -- 6 -- Level 6 "mmmmmmm", -- 0 "mmmammm", -- 1 "mm...mm", -- 2 "ma..aam", -- 3 "mmfgamm", -- 4 "mmmammm", -- 5 "mmmmmmm", -- 6 -- Level 7 "mmmmmmm", -- 0 "mmmammm", -- 1 "mm.aamm", -- 2 "ma..iam", -- 3 "mm..jmm", -- 4 "mmmammm", -- 5 "mmmmmmm", -- 6 -- Level 8 "mmmmmmm", -- 0 "mmmammm", -- 1 "mmaklmm", -- 2 "maa..am", -- 3 "mm...mm", -- 4 "mmmammm", -- 5 "mmmmmmm", -- 6 -- Level 9 "mmmmmmm", -- 0 "mmmammm", -- 1 "mmc..mm", -- 2 "mae.nam", -- 3 "mmaa.mm", -- 4 "mmmammm", -- 5 "mmmmmmm", -- 6 -- Level 10 "mmmmmmm", -- 0 "mmmammm", -- 1 "mm...mm", -- 2 "ma..aam", -- 3 "mmfgamm", -- 4 "mmmammm", -- 5 "mmmmmmm", -- 6 -- Level 11 "mmmmmmm", -- 0 "mmmammm", -- 1 "mm.aamm", -- 2 "ma..iam", -- 3 "mm..jmm", -- 4 "mmmammm", -- 5 "mmmmmmm", -- 6 -- Level 12 "mmmmmmm", -- 0 "mmmammm", -- 1 "mmaklmm", -- 2 "maa..am", -- 3 "mm...mm", -- 4 "mmmammm", -- 5 "mmmmmmm", -- 6 -- Level 13 "mmmmmmm", -- 0 "mmmammm", -- 1 "mmc..mm", -- 2 "mae.nam", -- 3 "mmaa.mm", -- 4 "mmmammm", -- 5 "mmmmmmm", -- 6 -- Level 14 "mmmmmmm", -- 0 "mmmammm", -- 1 "mm...mm", -- 2 "ma..aam", -- 3 "mmfgamm", -- 4 "mmmammm", -- 5 "mmmmmmm", -- 6 -- Level 15 "mmmmmmm", -- 0 "mmmammm", -- 1 "mm.aamm", -- 2 "ma..iam", -- 3 "mm..jmm", -- 4 "mmmammm", -- 5 "mmmmmmm", -- 6 -- Level 16 "mmmmmmm", -- 0 "mmmammm", -- 1 "mmaklmm", -- 2 "maa..am", -- 3 "mm...mm", -- 4 "mmmammm", -- 5 "mmmmmmm", -- 6 -- Level 17 "mmmmmmm", -- 0 "mmmammm", -- 1 "mmc..mm", -- 2 "mae.nam", -- 3 "mmaa.mm", -- 4 "mmmammm", -- 5 "mmmmmmm", -- 6 -- Level 18 "mmmmmmm", -- 0 "mmmammm", -- 1 "mm...mm", -- 2 "ma..aam", -- 3 "mmfgamm", -- 4 "mmmammm", -- 5 "mmmmmmm", -- 6 -- Level 19 "mmmmmmm", -- 0 "mmmammm", -- 1 "mm.aamm", -- 2 "ma..iam", -- 3 "mm..jmm", -- 4 "mmmammm", -- 5 "mmmmmmm", -- 6 -- Level 20 "mmmmmmm", -- 0 "mmmammm", -- 1 "mmaklmm", -- 2 "maa..am", -- 3 "mm...mm", -- 4 "mmmammm", -- 5 "mmmmmmm", -- 6 -- Level 21 "mmmmmmm", -- 0 "mmmammm", -- 1 "mmc..mm", -- 2 "mae.nam", -- 3 "mmaa.mm", -- 4 "mmmammm", -- 5 "mmmmmmm", -- 6 -- Level 22 "mmmmmmm", -- 0 "mmmammm", -- 1 "mm...mm", -- 2 "ma..aam", -- 3 "mmfgamm", -- 4 "mmmammm", -- 5 "mmmmmmm", -- 6 -- Level 23 "mmmmmmm", -- 0 "mmmammm", -- 1 "mm.aamm", -- 2 "ma..iam", -- 3 "mm..jmm", -- 4 "mmmammm", -- 5 "mmmmmmm", -- 6 -- Level 24 "mmmmmmm", -- 0 "mmmammm", -- 1 "mmaklmm", -- 2 "maa..am", -- 3 "mm...mm", -- 4 "mmmammm", -- 5 "mmmmmmm", -- 6 -- Level 25 "mmmmmmm", -- 0 "mmmammm", -- 1 "mmc..mm", -- 2 "mae.nam", -- 3 "mmaa.mm", -- 4 "mmmammm", -- 5 "mmmmmmm", -- 6 -- Level 26 "mmmmmmm", -- 0 "mmmammm", -- 1 "mm...mm", -- 2 "ma..aam", -- 3 "mmfgamm", -- 4 "mmmammm", -- 5 "mmmmmmm", -- 6 -- Level 27 "mmmmmmm", -- 0 "mmmammm", -- 1 "mm.aamm", -- 2 "ma..iam", -- 3 "mm..jmm", -- 4 "mmmammm", -- 5 "mmmmmmm", -- 6 -- Level 28 "mmmmmmm", -- 0 "mmmammm", -- 1 "mmaklmm", -- 2 "maa..am", -- 3 "mm...mm", -- 4 "mmmammm", -- 5 "mmmmmmm", -- 6 -- Level 29 "mmmmmmm", -- 0 "mmmammm", -- 1 "mmc..mm", -- 2 "mae.nam", -- 3 "mmaa.mm", -- 4 "mmmammm", -- 5 "mmmmmmm", -- 6 -- Level 30 "mmooomm", -- 0 "mmmammm", -- 1 "om...mo", -- 2 "oa..aao", -- 3 "omfgamo", -- 4 "mmmammm", -- 5 "mmooomm", -- 6 -- Level 31 "ppqqqpp", -- 0 "paaaaap", -- 1 "qa.aaaq", -- 2 "qa..iaq", -- 3 "qa..jaq", -- 4 "paaaaap", -- 5 "ppqqqpp", -- 6 -- Level 32 "...r...", -- 0 ".astba.", -- 1 "...fl..", -- 2 ".......", -- 3 ".......", -- 4 ".a...a.", -- 5 ".......", -- 6 -- Level 33 ".......", -- 0 ".a...a.", -- 1 ".......", -- 2 ".......", -- 3 ".......", -- 4 ".a...a.", -- 5 ".......", -- 6 -- Level 34 ".......", -- 0 ".a...a.", -- 1 ".......", -- 2 ".......", -- 3 ".......", -- 4 ".a...a.", -- 5 ".......", -- 6 -- Level 35 "rrrrrrr", -- 0 "uaaaaau", -- 1 ".a...a.", -- 2 ".a...a.", -- 3 ".a...a.", -- 4 "vaaaaav", -- 5 "wwwwwww", -- 6 -- Level 36 ".......", -- 0 "rrrrrrr", -- 1 "uaaaaau", -- 2 ".aaaaa.", -- 3 "vaaaaav", -- 4 "wwwwwww", -- 5 ".......", -- 6 -- Level 37 ".......", -- 0 ".......", -- 1 "rrrrrrr", -- 2 "aaaaaaa", -- 3 "wwwwwww", -- 4 ".......", -- 5 ".......", -- 6 }, }, -- MineEntrance { OriginData = { ExportName = "MineshaftCorridor", Name = "Plains 139", GalleryName = "Plains", GalleryIndex = "139", ID = "447", CreatorName = "STR_Warrior", }, Size = { x = 10, y = 4, z = 3, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 9, MaxY = 3, MaxZ = 2, }, Connectors = { { Type = -3, RelX = 0, RelY = 1, RelZ = 1, Direction = 4, -- X- }, { Type = 3, RelX = 9, RelY = 1, RelZ = 1, Direction = 5, -- X+ }, }, Metadata = { ["AddWeightIfSame"] = "200", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "None", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a: 5: 0", -- planks "b: 85: 0", -- fence "c: 66: 1", -- tracks "d: 50: 2", -- torch "e: 50: 1", -- torch "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "aaaaaaaaaa", -- 0 "aaaaaaaaaa", -- 1 "aaaaaaaaaa", -- 2 -- Level 1 "..b....b..", -- 0 "cccccccccc", -- 1 "..b....b..", -- 2 -- Level 2 "..b....b..", -- 0 "..........", -- 1 "..b....b..", -- 2 -- Level 3 "..a....a..", -- 0 ".dae..dae.", -- 1 "..a....a..", -- 2 }, }, -- MineshaftCorridor { OriginData = { ExportName = "Scarecrow", Name = "Plains 150", GalleryName = "Plains", GalleryIndex = "150", ID = "494", CreatorName = "STR_Warrior", }, Size = { x = 1, y = 6, z = 3, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 0, MaxY = 5, MaxZ = 2, }, Connectors = { { Type = -1, RelX = -1, RelY = 0, RelZ = 1, Direction = 4, -- X- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "10", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a:139: 0", -- cobblestonewall "b: 85: 0", -- fence "c:126: 4", -- woodenslab "d: 86: 1", -- pumpkin "e:139: 1", -- cobblestonewall "f:163: 4", -- acaciawoodstairs "m: 19: 0", -- sponge }, BlockData = { -- Level 0 ".", -- 0 "a", -- 1 ".", -- 2 -- Level 1 ".", -- 0 "b", -- 1 ".", -- 2 -- Level 2 "c", -- 0 "d", -- 1 "c", -- 2 -- Level 3 ".", -- 0 "e", -- 1 ".", -- 2 -- Level 4 "f", -- 0 "d", -- 1 "f", -- 2 -- Level 5 ".", -- 0 "f", -- 1 ".", -- 2 }, }, -- Scarecrow { OriginData = { ExportName = "MineshaftCrossing", Name = "Plains 171", GalleryName = "Plains", GalleryIndex = "171", ID = "578", CreatorName = "Aloe_vera", }, Size = { x = 5, y = 4, z = 5, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 4, MaxY = 3, MaxZ = 4, }, Connectors = { { Type = 3, RelX = 4, RelY = 1, RelZ = 2, Direction = 5, -- X+ }, { Type = -3, RelX = 4, RelY = 1, RelZ = 2, Direction = 5, -- X+ }, { Type = -3, RelX = 2, RelY = 1, RelZ = 4, Direction = 3, -- Z+ }, { Type = 3, RelX = 2, RelY = 1, RelZ = 4, Direction = 3, -- Z+ }, { Type = 3, RelX = 0, RelY = 1, RelZ = 2, Direction = 4, -- X- }, { Type = -3, RelX = 0, RelY = 1, RelZ = 2, Direction = 4, -- X- }, { Type = 3, RelX = 2, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, { Type = -3, RelX = 2, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "1", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "None", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a: 5: 0", -- planks "b: 66: 0", -- tracks "c: 66: 1", -- tracks "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "aaaaa", -- 0 "aaaaa", -- 1 "aaaaa", -- 2 "aaaaa", -- 3 "aaaaa", -- 4 -- Level 1 "m.b.m", -- 0 ".aba.", -- 1 "ccccc", -- 2 ".aba.", -- 3 "m.b.m", -- 4 -- Level 2 "m...m", -- 0 ".a.a.", -- 1 ".....", -- 2 ".a.a.", -- 3 "m...m", -- 4 -- Level 3 "m...m", -- 0 ".a.a.", -- 1 ".....", -- 2 ".a.a.", -- 3 "m...m", -- 4 }, }, -- MineshaftCrossing { OriginData = { ExportName = "MineshaftDoubleCrossing", Name = "Plains 172", GalleryName = "Plains", GalleryIndex = "172", ID = "579", CreatorName = "Aloe_vera", }, Size = { x = 5, y = 8, z = 5, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 4, MaxY = 7, MaxZ = 4, }, Connectors = { { Type = -3, RelX = 4, RelY = 5, RelZ = 2, Direction = 5, -- X+ }, { Type = 3, RelX = 4, RelY = 5, RelZ = 2, Direction = 5, -- X+ }, { Type = -3, RelX = 2, RelY = 1, RelZ = 4, Direction = 3, -- Z+ }, { Type = 3, RelX = 2, RelY = 1, RelZ = 4, Direction = 3, -- Z+ }, { Type = -3, RelX = 0, RelY = 1, RelZ = 2, Direction = 4, -- X- }, { Type = 3, RelX = 0, RelY = 1, RelZ = 2, Direction = 4, -- X- }, { Type = -3, RelX = 2, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, { Type = 3, RelX = 2, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, { Type = -3, RelX = 4, RelY = 1, RelZ = 2, Direction = 5, -- X+ }, { Type = 3, RelX = 4, RelY = 1, RelZ = 2, Direction = 5, -- X+ }, { Type = -3, RelX = 2, RelY = 5, RelZ = 4, Direction = 3, -- Z+ }, { Type = 3, RelX = 2, RelY = 5, RelZ = 4, Direction = 3, -- Z+ }, { Type = -3, RelX = 0, RelY = 5, RelZ = 2, Direction = 4, -- X- }, { Type = 3, RelX = 0, RelY = 5, RelZ = 2, Direction = 4, -- X- }, { Type = -3, RelX = 2, RelY = 5, RelZ = 0, Direction = 2, -- Z- }, { Type = 3, RelX = 2, RelY = 5, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "1", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "None", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a: 5: 0", -- planks "b: 66: 0", -- tracks "c: 66: 1", -- tracks "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "aaaaa", -- 0 "aaaaa", -- 1 "aaaaa", -- 2 "aaaaa", -- 3 "aaaaa", -- 4 -- Level 1 "m.b.m", -- 0 ".aba.", -- 1 "ccccc", -- 2 ".aba.", -- 3 "m.b.m", -- 4 -- Level 2 "m...m", -- 0 ".a.a.", -- 1 ".....", -- 2 ".a.a.", -- 3 "m...m", -- 4 -- Level 3 "m...m", -- 0 ".a.a.", -- 1 ".....", -- 2 ".a.a.", -- 3 "m...m", -- 4 -- Level 4 "aaaaa", -- 0 "aa.aa", -- 1 "a...a", -- 2 "aa.aa", -- 3 "aaaaa", -- 4 -- Level 5 "m...m", -- 0 ".a.a.", -- 1 ".....", -- 2 ".a.a.", -- 3 "m...m", -- 4 -- Level 6 "m...m", -- 0 ".a.a.", -- 1 ".....", -- 2 ".a.a.", -- 3 "m...m", -- 4 -- Level 7 "m...m", -- 0 ".a.a.", -- 1 ".....", -- 2 ".a.a.", -- 3 "m...m", -- 4 }, }, -- MineshaftDoubleCrossing { OriginData = { ExportName = "MineshaftCrossing", Name = "Plains 193", GalleryName = "Plains", GalleryIndex = "193", ID = "657", CreatorName = "Aloe_vera", }, Size = { x = 11, y = 4, z = 11, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 10, MaxY = 3, MaxZ = 10, }, Connectors = { { Type = 3, RelX = 5, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, { Type = -3, RelX = 5, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, { Type = 3, RelX = 0, RelY = 1, RelZ = 5, Direction = 4, -- X- }, { Type = -3, RelX = 0, RelY = 1, RelZ = 5, Direction = 4, -- X- }, { Type = 3, RelX = 5, RelY = 1, RelZ = 10, Direction = 3, -- Z+ }, { Type = -3, RelX = 5, RelY = 1, RelZ = 10, Direction = 3, -- Z+ }, { Type = 3, RelX = 10, RelY = 1, RelZ = 5, Direction = 5, -- X+ }, { Type = -3, RelX = 10, RelY = 1, RelZ = 5, Direction = 5, -- X+ }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "10", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "None", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a: 5: 0", -- planks "b: 66: 0", -- tracks "c: 85: 0", -- fence "d: 66: 1", -- tracks "e: 50: 4", -- torch "f: 50: 3", -- torch "g: 50: 2", -- torch "h: 50: 1", -- torch "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "mmmmaaammmm", -- 0 "mmmmaaammmm", -- 1 "mmmmaaammmm", -- 2 "mmmmaaammmm", -- 3 "aaaaaaaaaaa", -- 4 "aaaaaaaaaaa", -- 5 "aaaaaaaaaaa", -- 6 "mmmmaaammmm", -- 7 "mmmmaaammmm", -- 8 "mmmmaaammmm", -- 9 "mmmmaaammmm", -- 10 -- Level 1 "mmmm.b.mmmm", -- 0 "mmmm.b.mmmm", -- 1 "mmmmcbcmmmm", -- 2 "mmmm.b.mmmm", -- 3 "..c..b..c..", -- 4 "ddddddddddd", -- 5 "..c..b..c..", -- 6 "mmmm.b.mmmm", -- 7 "mmmmcbcmmmm", -- 8 "mmmm.b.mmmm", -- 9 "mmmm.b.mmmm", -- 10 -- Level 2 "mmmm...mmmm", -- 0 "mmmm...mmmm", -- 1 "mmmmc.cmmmm", -- 2 "mmmm...mmmm", -- 3 "..c.....c..", -- 4 "...........", -- 5 "..c.....c..", -- 6 "mmmm...mmmm", -- 7 "mmmmc.cmmmm", -- 8 "mmmm...mmmm", -- 9 "mmmm...mmmm", -- 10 -- Level 3 "mmmm...mmmm", -- 0 "mmmm.e.mmmm", -- 1 "mmmmaaammmm", -- 2 "mmmm.f.mmmm", -- 3 "..a.....a..", -- 4 ".gah...gah.", -- 5 "..a.....a..", -- 6 "mmmm.e.mmmm", -- 7 "mmmmaaammmm", -- 8 "mmmm.f.mmmm", -- 9 "mmmm...mmmm", -- 10 }, }, -- MineshaftCrossing { OriginData = { ExportName = "MineshaftTee", Name = "Plains 194", GalleryName = "Plains", GalleryIndex = "194", ID = "658", CreatorName = "Aloe_vera", }, Size = { x = 11, y = 4, z = 7, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 10, MaxY = 3, MaxZ = 6, }, Connectors = { { Type = 3, RelX = 0, RelY = 1, RelZ = 5, Direction = 4, -- X- }, { Type = -3, RelX = 0, RelY = 1, RelZ = 5, Direction = 4, -- X- }, { Type = 3, RelX = 5, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, { Type = -3, RelX = 5, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, { Type = 3, RelX = 10, RelY = 1, RelZ = 5, Direction = 5, -- X+ }, { Type = -3, RelX = 10, RelY = 1, RelZ = 5, Direction = 5, -- X+ }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "20", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "None", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a: 5: 0", -- planks "b: 66: 0", -- tracks "c: 85: 0", -- fence "d: 66: 1", -- tracks "e: 50: 4", -- torch "f: 50: 3", -- torch "g: 50: 2", -- torch "h: 50: 1", -- torch "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "mmmmaaammmm", -- 0 "mmmmaaammmm", -- 1 "mmmmaaammmm", -- 2 "mmmmaaammmm", -- 3 "aaaaaaaaaaa", -- 4 "aaaaaaaaaaa", -- 5 "aaaaaaaaaaa", -- 6 -- Level 1 "mmmm.b.mmmm", -- 0 "mmmm.b.mmmm", -- 1 "mmmmcbcmmmm", -- 2 "mmmm.b.mmmm", -- 3 "..c..b..c..", -- 4 "ddddddddddd", -- 5 "..c.....c..", -- 6 -- Level 2 "mmmm...mmmm", -- 0 "mmmm...mmmm", -- 1 "mmmmc.cmmmm", -- 2 "mmmm...mmmm", -- 3 "..c.....c..", -- 4 "...........", -- 5 "..c.....c..", -- 6 -- Level 3 "mmmm...mmmm", -- 0 "mmmm.e.mmmm", -- 1 "mmmmaaammmm", -- 2 "mmmm.f.mmmm", -- 3 "..a.....a..", -- 4 ".gah...gah.", -- 5 "..a.....a..", -- 6 }, }, -- MineshaftTee { OriginData = { ExportName = "MineshaftStairs", Name = "Plains 195", GalleryName = "Plains", GalleryIndex = "195", ID = "659", CreatorName = "Aloe_vera", }, Size = { x = 7, y = 8, z = 3, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 6, MaxY = 7, MaxZ = 2, }, Connectors = { { Type = 3, RelX = 0, RelY = 1, RelZ = 1, Direction = 4, -- X- }, { Type = -3, RelX = 0, RelY = 1, RelZ = 1, Direction = 4, -- X- }, { Type = 3, RelX = 6, RelY = 5, RelZ = 1, Direction = 5, -- X+ }, { Type = -3, RelX = 6, RelY = 5, RelZ = 1, Direction = 5, -- X+ }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "None", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a: 5: 0", -- planks "b: 66: 1", -- tracks "c: 66: 2", -- tracks "d: 85: 0", -- fence "e: 50: 1", -- torch "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "aaammmm", -- 0 "aaammmm", -- 1 "aaammmm", -- 2 -- Level 1 "..aammm", -- 0 "bcaammm", -- 1 "..aammm", -- 2 -- Level 2 "...aamm", -- 0 "..caamm", -- 1 "...aamm", -- 2 -- Level 3 "...daam", -- 0 "...caam", -- 1 "...daam", -- 2 -- Level 4 "m..d.aa", -- 0 "m...caa", -- 1 "m..d.aa", -- 2 -- Level 5 "mm.d...", -- 0 "mm...bb", -- 1 "mm.d...", -- 2 -- Level 6 "mmmd...", -- 0 "mmm....", -- 1 "mmmd...", -- 2 -- Level 7 "mmma...", -- 0 "mmmae..", -- 1 "mmma...", -- 2 }, }, -- MineshaftStairs { OriginData = { ExportName = "MineshaftSpiral", Name = "Plains 198", GalleryName = "Plains", GalleryIndex = "198", ID = "662", CreatorName = "Aloe_vera", }, Size = { x = 7, y = 12, z = 7, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 6, MaxY = 11, MaxZ = 6, }, Connectors = { { Type = 3, RelX = 1, RelY = 1, RelZ = 6, Direction = 3, -- Z+ }, { Type = -3, RelX = 1, RelY = 1, RelZ = 6, Direction = 3, -- Z+ }, { Type = 3, RelX = 0, RelY = 9, RelZ = 5, Direction = 4, -- X- }, { Type = -3, RelX = 0, RelY = 9, RelZ = 5, Direction = 4, -- X- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "None", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a: 5: 0", -- planks "b: 85: 0", -- fence "c: 66: 4", -- tracks "d: 66: 0", -- tracks "e: 66: 6", -- tracks "f: 66: 2", -- tracks "g: 50: 1", -- torch "h: 50: 3", -- torch "i: 66: 1", -- tracks "j: 66: 7", -- tracks "k: 66: 5", -- tracks "l: 50: 2", -- torch "m: 19: 0", -- sponge "n: 66: 3", -- tracks "o: 66: 8", -- tracks "p: 50: 4", -- torch }, BlockData = { -- Level 0 "mmmmmmm", -- 0 "mmmmmmm", -- 1 "mmmmmmm", -- 2 "aaabmmm", -- 3 "aaammmm", -- 4 "aaammmm", -- 5 "aaammmm", -- 6 -- Level 1 "mmmmmmm", -- 0 "mmmmmmm", -- 1 "aaammmm", -- 2 "aaabmmm", -- 3 ".c.mmmm", -- 4 ".d.mmmm", -- 5 ".d.mmmm", -- 6 -- Level 2 "aaaammm", -- 0 "aaaammm", -- 1 "aaaammm", -- 2 ".c.bmmm", -- 3 "...mmmm", -- 4 "...mmmm", -- 5 "...mmmm", -- 6 -- Level 3 "b..aamm", -- 0 ".efaamm", -- 1 ".d.aamm", -- 2 "...bmmm", -- 3 "...mmmm", -- 4 "...mmmm", -- 5 "...mmmm", -- 6 -- Level 4 "b...aaa", -- 0 "...faaa", -- 1 "....aaa", -- 2 "...baaa", -- 3 "...mmmm", -- 4 "mmmmmmm", -- 5 "mmmmmmm", -- 6 -- Level 5 "ag....b", -- 0 "h...ij.", -- 1 ".....k.", -- 2 "...baaa", -- 3 "mmmmaaa", -- 4 "mmmmmmm", -- 5 "mmmmmmm", -- 6 -- Level 6 "mm....b", -- 0 "mm.....", -- 1 "mm.....", -- 2 "mmmb.k.", -- 3 "mmmaaaa", -- 4 "mmmaaaa", -- 5 "mmmaaaa", -- 6 -- Level 7 "mmm..la", -- 0 "mmm...h", -- 1 "mmm....", -- 2 "mmmb...", -- 3 "mmaa.d.", -- 4 "mmaano.", -- 5 "mmaa..b", -- 6 -- Level 8 "mmmmmmm", -- 0 "mmmmmmm", -- 1 "mmmm...", -- 2 "mmmb...", -- 3 "aaa....", -- 4 "aaan...", -- 5 "aaa...b", -- 6 -- Level 9 "mmmmmmm", -- 0 "mmmmmmm", -- 1 "mmmmmmm", -- 2 "mmmb...", -- 3 ".......", -- 4 "iii...p", -- 5 ".....la", -- 6 -- Level 10 "mmmmmmm", -- 0 "mmmmmmm", -- 1 "mmmmmmm", -- 2 "mmmbmmm", -- 3 ".....mm", -- 4 ".....mm", -- 5 ".....mm", -- 6 -- Level 11 "mmmmmmm", -- 0 "mmmmmmm", -- 1 "mmmmmmm", -- 2 "mmmbmmm", -- 3 "....mmm", -- 4 "....mmm", -- 5 "....mmm", -- 6 }, }, -- MineshaftSpiral { OriginData = { ExportName = "MineshaftStairsCrossing", Name = "Plains 199", GalleryName = "Plains", GalleryIndex = "199", ID = "663", CreatorName = "Aloe_vera", }, Size = { x = 11, y = 12, z = 12, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 10, MaxY = 11, MaxZ = 11, }, Connectors = { { Type = 3, RelX = 0, RelY = 5, RelZ = 6, Direction = 4, -- X- }, { Type = -3, RelX = 0, RelY = 5, RelZ = 6, Direction = 4, -- X- }, { Type = 3, RelX = 10, RelY = 5, RelZ = 6, Direction = 5, -- X+ }, { Type = -3, RelX = 10, RelY = 5, RelZ = 6, Direction = 5, -- X+ }, { Type = 3, RelX = 5, RelY = 9, RelZ = 11, Direction = 3, -- Z+ }, { Type = -3, RelX = 5, RelY = 9, RelZ = 11, Direction = 3, -- Z+ }, { Type = 3, RelX = 5, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, { Type = -3, RelX = 5, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "30", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "None", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a: 5: 0", -- planks "b: 66: 0", -- tracks "c: 66: 5", -- tracks "d: 85: 0", -- fence "e: 66: 1", -- tracks "f: 50: 3", -- torch "g: 50: 2", -- torch "h: 50: 1", -- torch "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "mmmmaaammmm", -- 0 "mmmmaaammmm", -- 1 "mmmmaaammmm", -- 2 "mmmmmmmmmmm", -- 3 "mmmmmmmmmmm", -- 4 "mmmmmmmmmmm", -- 5 "mmmmmmmmmmm", -- 6 "mmmmmmmmmmm", -- 7 "mmmmmmmmmmm", -- 8 "mmmmmmmmmmm", -- 9 "mmmmmmmmmmm", -- 10 "mmmmmmmmmmm", -- 11 -- Level 1 "mmmm.b.mmmm", -- 0 "mmmm.c.mmmm", -- 1 "mmmmaaammmm", -- 2 "mmmmaaammmm", -- 3 "mmmmmmmmmmm", -- 4 "mmmmmmmmmmm", -- 5 "mmmmmmmmmmm", -- 6 "mmmmmmmmmmm", -- 7 "mmmmmmmmmmm", -- 8 "mmmmmmmmmmm", -- 9 "mmmmmmmmmmm", -- 10 "mmmmmmmmmmm", -- 11 -- Level 2 "mmmm...mmmm", -- 0 "mmmm...mmmm", -- 1 "mmmm.c.mmmm", -- 2 "mmmmaaammmm", -- 3 "mmmmaaammmm", -- 4 "mmmmmmmmmmm", -- 5 "mmmmmmmmmmm", -- 6 "mmmmmmmmmmm", -- 7 "mmmmmmmmmmm", -- 8 "mmmmmmmmmmm", -- 9 "mmmmmmmmmmm", -- 10 "mmmmmmmmmmm", -- 11 -- Level 3 "mmmm...mmmm", -- 0 "mmmm...mmmm", -- 1 "mmmm...mmmm", -- 2 "mmmmdcdmmmm", -- 3 "mmmmaaammmm", -- 4 "mmmmaaammmm", -- 5 "mmmmmmmmmmm", -- 6 "mmmmmmmmmmm", -- 7 "mmmmmmmmmmm", -- 8 "mmmmmmmmmmm", -- 9 "mmmmmmmmmmm", -- 10 "mmmmmmmmmmm", -- 11 -- Level 4 "mmmmmmmmmmm", -- 0 "mmmm...mmmm", -- 1 "mmmm...mmmm", -- 2 "mmmmd.dmmmm", -- 3 "mmmm.c.mmmm", -- 4 "aaaaaaaaaaa", -- 5 "aaaaaaaaaaa", -- 6 "aaaaaaaaaaa", -- 7 "mmmmaaammmm", -- 8 "mmmmmmmmmmm", -- 9 "mmmmmmmmmmm", -- 10 "mmmmmmmmmmm", -- 11 -- Level 5 "mmmmmmmmmmm", -- 0 "mmmmmmmmmmm", -- 1 "mmmm...mmmm", -- 2 "mmmmd.dmmmm", -- 3 "mmmm...mmmm", -- 4 "..d..b..d..", -- 5 "eeeeeeeeeee", -- 6 "..d..c..d..", -- 7 "mmmmaaammmm", -- 8 "mmmmaaammmm", -- 9 "mmmmmmmmmmm", -- 10 "mmmmmmmmmmm", -- 11 -- Level 6 "mmmmmmmmmmm", -- 0 "mmmmmmmmmmm", -- 1 "mmmmmmmmmmm", -- 2 "mmmmd.dmmmm", -- 3 "mmmm...mmmm", -- 4 "..d.....d..", -- 5 "...........", -- 6 "..d.....d..", -- 7 "mmmm.c.mmmm", -- 8 "mmmmaaammmm", -- 9 "mmmmaaammmm", -- 10 "mmmmmmmmmmm", -- 11 -- Level 7 "mmmmmmmmmmm", -- 0 "mmmmmmmmmmm", -- 1 "mmmmmmmmmmm", -- 2 "mmmmaaammmm", -- 3 "mmmm.f.mmmm", -- 4 "..a.....a..", -- 5 ".gah...gah.", -- 6 "..a.....a..", -- 7 "mmmm...mmmm", -- 8 "mmmmdcdmmmm", -- 9 "mmmmaaammmm", -- 10 "mmmmaaammmm", -- 11 -- Level 8 "mmmmmmmmmmm", -- 0 "mmmmmmmmmmm", -- 1 "mmmmmmmmmmm", -- 2 "mmmmmmmmmmm", -- 3 "mmmmmmmmmmm", -- 4 "mmmmmmmmmmm", -- 5 "mmmmmmmmmmm", -- 6 "mmmm...mmmm", -- 7 "mmmm...mmmm", -- 8 "mmmmd.dmmmm", -- 9 "mmmm.c.mmmm", -- 10 "mmmmaaammmm", -- 11 -- Level 9 "mmmmmmmmmmm", -- 0 "mmmmmmmmmmm", -- 1 "mmmmmmmmmmm", -- 2 "mmmmmmmmmmm", -- 3 "mmmmmmmmmmm", -- 4 "mmmmmmmmmmm", -- 5 "mmmmmmmmmmm", -- 6 "mmmmmmmmmmm", -- 7 "mmmm...mmmm", -- 8 "mmmmd.dmmmm", -- 9 "mmmm...mmmm", -- 10 "mmmm.b.mmmm", -- 11 -- Level 10 "mmmmmmmmmmm", -- 0 "mmmmmmmmmmm", -- 1 "mmmmmmmmmmm", -- 2 "mmmmmmmmmmm", -- 3 "mmmmmmmmmmm", -- 4 "mmmmmmmmmmm", -- 5 "mmmmmmmmmmm", -- 6 "mmmmmmmmmmm", -- 7 "mmmmmmmmmmm", -- 8 "mmmmd.dmmmm", -- 9 "mmmm...mmmm", -- 10 "mmmm...mmmm", -- 11 -- Level 11 "mmmmmmmmmmm", -- 0 "mmmmmmmmmmm", -- 1 "mmmmmmmmmmm", -- 2 "mmmmmmmmmmm", -- 3 "mmmmmmmmmmm", -- 4 "mmmmmmmmmmm", -- 5 "mmmmmmmmmmm", -- 6 "mmmmmmmmmmm", -- 7 "mmmmmmmmmmm", -- 8 "mmmmaaammmm", -- 9 "mmmm.f.mmmm", -- 10 "mmmm...mmmm", -- 11 }, }, -- MineshaftStairsCrossing { OriginData = { ExportName = "MineshaftsCorridor5", Name = "Plains 200", GalleryName = "Plains", GalleryIndex = "200", ID = "664", CreatorName = "Aloe_vera", }, Size = { x = 11, y = 4, z = 3, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 10, MaxY = 3, MaxZ = 2, }, Connectors = { { Type = 3, RelX = 10, RelY = 1, RelZ = 1, Direction = 5, -- X+ }, { Type = -3, RelX = 10, RelY = 1, RelZ = 1, Direction = 5, -- X+ }, { Type = -3, RelX = 0, RelY = 1, RelZ = 1, Direction = 4, -- X- }, { Type = 3, RelX = 0, RelY = 1, RelZ = 1, Direction = 4, -- X- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "None", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "0", }, BlockDefinitions = { ".: 0: 0", -- air "a: 5: 0", -- planks "b: 85: 0", -- fence "c: 66: 1", -- tracks "d: 50: 2", -- torch "e: 50: 1", -- torch "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "aaaaaaaaaaa", -- 0 "aaaaaaaaaaa", -- 1 "aaaaaaaaaaa", -- 2 -- Level 1 "..b.....b..", -- 0 "ccccccccccc", -- 1 "..b.....b..", -- 2 -- Level 2 "..b.....b..", -- 0 "...........", -- 1 "..b.....b..", -- 2 -- Level 3 "..a.....a..", -- 0 ".dae...dae.", -- 1 "..a.....a..", -- 2 }, }, -- MineshaftsCorridor5 }, -- Pieces } ================================================ FILE: Server/Prefabs/Villages/SandFlatRoofVillage.cubeset ================================================ -- SandFlatRoofVillage.cubeset -- Defines the prefabs in the group SandFlatRoofVillage -- NOTE: This file has been generated automatically by GalExport! -- Any manual changes will be overwritten by the next automatic export! Cubeset = { Metadata = { CubesetFormatVersion = 1, ExportDate = "2016-11-30 13:46:02", ["AllowedBiomes"] = "Desert, DesertM", ["IntendedUse"] = "Village", }, Pieces = { { OriginData = { ExportName = "House5x4", Name = "Desert 25", GalleryName = "Desert", GalleryIndex = "25", ID = "166", CreatorName = "Aloe_vera", }, Size = { x = 7, y = 6, z = 6, }, Hitbox = { MinX = -1, MinY = 0, MinZ = 0, MaxX = 7, MaxY = 5, MaxZ = 6, }, Connectors = { { Type = -1, RelX = 3, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 24: 0", -- sandstone "b:128: 0", -- sandstonestairs "c:128: 2", -- sandstonestairs "d:128: 1", -- sandstonestairs "e: 64: 3", -- woodendoorblock "f:171: 0", -- carpet "g:171:14", -- carpet "h: 24: 2", -- sandstone "i: 64: 9", -- woodendoorblock "j: 50: 3", -- torch "k:128: 4", -- sandstonestairs "l:128: 6", -- sandstonestairs "m: 19: 0", -- sponge "n:128: 5", -- sandstonestairs "o:128: 7", -- sandstonestairs }, BlockData = { -- Level 0 "mmaaamm", -- 0 "maaaaam", -- 1 "maaaaam", -- 2 "maaaaam", -- 3 "maaaaam", -- 4 "mmmmmmm", -- 5 -- Level 1 "..bcd..", -- 0 ".aaaaa.", -- 1 ".aaaaa.", -- 2 ".aaaaa.", -- 3 ".aaaaa.", -- 4 ".......", -- 5 -- Level 2 ".......", -- 0 ".aaeaa.", -- 1 ".afgfa.", -- 2 ".afgfa.", -- 3 ".aaaaa.", -- 4 ".......", -- 5 -- Level 3 ".......", -- 0 ".hhihh.", -- 1 ".h...h.", -- 2 ".h...h.", -- 3 ".hh.hh.", -- 4 ".......", -- 5 -- Level 4 ".......", -- 0 ".aaaaa.", -- 1 ".aj.ja.", -- 2 ".a...a.", -- 3 ".aaaaa.", -- 4 ".......", -- 5 -- Level 5 "kllllln", -- 0 "kaaaaan", -- 1 "kaaaaan", -- 2 "kaaaaan", -- 3 "kaaaaan", -- 4 "oooooon", -- 5 }, }, -- House5x4 { OriginData = { ExportName = "House5x5", Name = "Desert 26", GalleryName = "Desert", GalleryIndex = "26", ID = "167", CreatorName = "Aloe_vera", }, Size = { x = 7, y = 6, z = 7, }, Hitbox = { MinX = -1, MinY = 0, MinZ = 0, MaxX = 7, MaxY = 5, MaxZ = 7, }, Connectors = { { Type = -1, RelX = 3, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 24: 0", -- sandstone "b:128: 0", -- sandstonestairs "c:128: 2", -- sandstonestairs "d:128: 1", -- sandstonestairs "e: 64: 3", -- woodendoorblock "f:171: 0", -- carpet "g:171:15", -- carpet "h:171:14", -- carpet "i: 24: 2", -- sandstone "j: 64: 9", -- woodendoorblock "k: 50: 3", -- torch "l:128: 4", -- sandstonestairs "m: 19: 0", -- sponge "n:128: 6", -- sandstonestairs "o:128: 5", -- sandstonestairs "p:128: 7", -- sandstonestairs }, BlockData = { -- Level 0 "mmaaamm", -- 0 "maaaaam", -- 1 "maaaaam", -- 2 "maaaaam", -- 3 "maaaaam", -- 4 "maaaaam", -- 5 "mmmmmmm", -- 6 -- Level 1 "..bcd..", -- 0 ".aaaaa.", -- 1 ".aaaaa.", -- 2 ".aaaaa.", -- 3 ".aaaaa.", -- 4 ".aaaaa.", -- 5 ".......", -- 6 -- Level 2 ".......", -- 0 ".aaeaa.", -- 1 ".afffa.", -- 2 ".aghga.", -- 3 ".afffa.", -- 4 ".aaaaa.", -- 5 ".......", -- 6 -- Level 3 ".......", -- 0 ".iijii.", -- 1 ".i...i.", -- 2 ".......", -- 3 ".i...i.", -- 4 ".ii.ii.", -- 5 ".......", -- 6 -- Level 4 ".......", -- 0 ".aaaaa.", -- 1 ".ak.ka.", -- 2 ".a...a.", -- 3 ".a...a.", -- 4 ".aaaaa.", -- 5 ".......", -- 6 -- Level 5 "lnnnnno", -- 0 "laaaaao", -- 1 "laaaaao", -- 2 "laaaaao", -- 3 "laaaaao", -- 4 "laaaaao", -- 5 "ppppppo", -- 6 }, }, -- House5x5 { OriginData = { ExportName = "House7x5", Name = "Desert 27", GalleryName = "Desert", GalleryIndex = "27", ID = "168", CreatorName = "Aloe_vera", }, Size = { x = 9, y = 6, z = 7, }, Hitbox = { MinX = -1, MinY = 0, MinZ = 0, MaxX = 9, MaxY = 5, MaxZ = 7, }, Connectors = { { Type = -1, RelX = 3, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 24: 0", -- sandstone "b:128: 0", -- sandstonestairs "c:128: 2", -- sandstonestairs "d:128: 1", -- sandstonestairs "e: 64: 3", -- woodendoorblock "f:171:14", -- carpet "g:171: 0", -- carpet "h:171:15", -- carpet "i: 24: 2", -- sandstone "j: 64: 9", -- woodendoorblock "k: 50: 3", -- torch "l:128: 4", -- sandstonestairs "m: 19: 0", -- sponge "n:128: 6", -- sandstonestairs "o:128: 5", -- sandstonestairs "p:128: 7", -- sandstonestairs }, BlockData = { -- Level 0 "mmaaammmm", -- 0 "maaaaaaam", -- 1 "maaaaaaam", -- 2 "maaaaaaam", -- 3 "maaaaaaam", -- 4 "maaaaaaam", -- 5 "mmmmmmmmm", -- 6 -- Level 1 "..bcd....", -- 0 ".aaaaaaa.", -- 1 ".aaaaaaa.", -- 2 ".aaaaaaa.", -- 3 ".aaaaaaa.", -- 4 ".aaaaaaa.", -- 5 ".........", -- 6 -- Level 2 ".........", -- 0 ".aaeaaaa.", -- 1 ".afffffa.", -- 2 ".aghhhga.", -- 3 ".afffffa.", -- 4 ".aaaaaaa.", -- 5 ".........", -- 6 -- Level 3 ".........", -- 0 ".iiji.ii.", -- 1 ".i.....i.", -- 2 ".........", -- 3 ".i.....i.", -- 4 ".iii.iii.", -- 5 ".........", -- 6 -- Level 4 ".........", -- 0 ".aaaaaaa.", -- 1 ".ak.k..a.", -- 2 ".a.....a.", -- 3 ".a.....a.", -- 4 ".aaaaaaa.", -- 5 ".........", -- 6 -- Level 5 "lnnnnnnnn", -- 0 "laaaaaaao", -- 1 "laaaaaaao", -- 2 "laaaaaaao", -- 3 "laaaaaaao", -- 4 "laaaaaaao", -- 5 "ppppppppo", -- 6 }, }, -- House7x5 { OriginData = { ExportName = "House8x5", Name = "Desert 28", GalleryName = "Desert", GalleryIndex = "28", ID = "169", CreatorName = "Aloe_vera", }, Size = { x = 10, y = 6, z = 7, }, Hitbox = { MinX = -1, MinY = 0, MinZ = 0, MaxX = 10, MaxY = 5, MaxZ = 7, }, Connectors = { { Type = -1, RelX = 3, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 24: 0", -- sandstone "b:128: 0", -- sandstonestairs "c:128: 2", -- sandstonestairs "d:128: 1", -- sandstonestairs "e: 64: 3", -- woodendoorblock "f:171: 0", -- carpet "g:171:14", -- carpet "h:171:15", -- carpet "i: 24: 2", -- sandstone "j: 64: 9", -- woodendoorblock "k: 50: 3", -- torch "l:128: 4", -- sandstonestairs "m: 19: 0", -- sponge "n:128: 6", -- sandstonestairs "o:128: 5", -- sandstonestairs "p:128: 7", -- sandstonestairs }, BlockData = { -- Level 0 "mmaaammmmm", -- 0 "maaaaaaaam", -- 1 "maaaaaaaam", -- 2 "maaaaaaaam", -- 3 "maaaaaaaam", -- 4 "maaaaaaaam", -- 5 "mmmmmmmmmm", -- 6 -- Level 1 "..bcd.....", -- 0 ".aaaaaaaa.", -- 1 ".aaaaaaaa.", -- 2 ".aaaaaaaa.", -- 3 ".aaaaaaaa.", -- 4 ".aaaaaaaa.", -- 5 "..........", -- 6 -- Level 2 "..........", -- 0 ".aaeaaaaa.", -- 1 ".afghhgfa.", -- 2 ".afhffhfa.", -- 3 ".afghhgfa.", -- 4 ".aaaaaaaa.", -- 5 "..........", -- 6 -- Level 3 "..........", -- 0 ".iijii.ii.", -- 1 ".i......i.", -- 2 "..........", -- 3 ".i......i.", -- 4 ".ii.ii.ii.", -- 5 "..........", -- 6 -- Level 4 "..........", -- 0 ".aaaaaaaa.", -- 1 ".ak.k...a.", -- 2 ".a......a.", -- 3 ".a......a.", -- 4 ".aaaaaaaa.", -- 5 "..........", -- 6 -- Level 5 "lnnnnnnnnn", -- 0 "laaaaaaaao", -- 1 "laaaaaaaao", -- 2 "laaaaaaaao", -- 3 "laaaaaaaao", -- 4 "laaaaaaaao", -- 5 "pppppppppo", -- 6 }, }, -- House8x5 { OriginData = { ExportName = "House8x7", Name = "Desert 29", GalleryName = "Desert", GalleryIndex = "29", ID = "170", CreatorName = "Aloe_vera", }, Size = { x = 10, y = 6, z = 9, }, Hitbox = { MinX = -1, MinY = 0, MinZ = 0, MaxX = 10, MaxY = 5, MaxZ = 9, }, Connectors = { { Type = -1, RelX = 3, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 24: 0", -- sandstone "b:128: 0", -- sandstonestairs "c:128: 2", -- sandstonestairs "d:128: 1", -- sandstonestairs "e: 64: 3", -- woodendoorblock "f:171: 0", -- carpet "g:171:14", -- carpet "h:171:15", -- carpet "i: 24: 2", -- sandstone "j: 64: 9", -- woodendoorblock "k: 50: 3", -- torch "l: 50: 1", -- torch "m: 19: 0", -- sponge "n: 50: 2", -- torch "o:128: 4", -- sandstonestairs "p:128: 6", -- sandstonestairs "q:128: 5", -- sandstonestairs "r:128: 7", -- sandstonestairs }, BlockData = { -- Level 0 "mmaaammmmm", -- 0 "maaaaaaaam", -- 1 "maaaaaaaam", -- 2 "maaaaaaaam", -- 3 "maaaaaaaam", -- 4 "maaaaaaaam", -- 5 "maaaaaaaam", -- 6 "maaaaaaaam", -- 7 "mmmmmmmmmm", -- 8 -- Level 1 "..bcd.....", -- 0 ".aaaaaaaa.", -- 1 ".aaaaaaaa.", -- 2 ".aaaaaaaa.", -- 3 ".aaaaaaaa.", -- 4 ".aaaaaaaa.", -- 5 ".aaaaaaaa.", -- 6 ".aaaaaaaa.", -- 7 "..........", -- 8 -- Level 2 "..........", -- 0 ".aaeaaaaa.", -- 1 ".afghhgfa.", -- 2 ".afhffhfa.", -- 3 ".afhgghfa.", -- 4 ".afhffhfa.", -- 5 ".afghhgfa.", -- 6 ".aaaaaaaa.", -- 7 "..........", -- 8 -- Level 3 "..........", -- 0 ".iijii.ii.", -- 1 ".i......i.", -- 2 ".i......i.", -- 3 "..........", -- 4 ".i......i.", -- 5 ".i......i.", -- 6 ".ii.ii.ii.", -- 7 "..........", -- 8 -- Level 4 "..........", -- 0 ".aaaaaaaa.", -- 1 ".a..k...a.", -- 2 ".a......a.", -- 3 ".al....na.", -- 4 ".a......a.", -- 5 ".a......a.", -- 6 ".aaaaaaaa.", -- 7 "..........", -- 8 -- Level 5 "oppppppppp", -- 0 "oaaaaaaaaq", -- 1 "oaaaaaaaaq", -- 2 "oaaaaaaaaq", -- 3 "oaaaaaaaaq", -- 4 "oaaaaaaaaq", -- 5 "oaaaaaaaaq", -- 6 "oaaaaaaaaq", -- 7 "rrrrrrrrrq", -- 8 }, }, -- House8x7 { OriginData = { ExportName = "House9x7", Name = "Desert 30", GalleryName = "Desert", GalleryIndex = "30", ID = "171", CreatorName = "Aloe_vera", }, Size = { x = 11, y = 6, z = 9, }, Hitbox = { MinX = -1, MinY = 0, MinZ = 0, MaxX = 11, MaxY = 5, MaxZ = 9, }, Connectors = { { Type = -1, RelX = 3, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 24: 0", -- sandstone "b:128: 0", -- sandstonestairs "c:128: 2", -- sandstonestairs "d:128: 1", -- sandstonestairs "e: 64: 3", -- woodendoorblock "f:171: 0", -- carpet "g:171:15", -- carpet "h:171:14", -- carpet "i: 24: 2", -- sandstone "j: 64: 9", -- woodendoorblock "k: 50: 3", -- torch "l: 50: 1", -- torch "m: 19: 0", -- sponge "n: 50: 2", -- torch "o: 50: 4", -- torch "p:128: 4", -- sandstonestairs "q:128: 6", -- sandstonestairs "r:128: 5", -- sandstonestairs "s:128: 7", -- sandstonestairs }, BlockData = { -- Level 0 "mmaaammmmmm", -- 0 "maaaaaaaaam", -- 1 "maaaaaaaaam", -- 2 "maaaaaaaaam", -- 3 "maaaaaaaaam", -- 4 "maaaaaaaaam", -- 5 "maaaaaaaaam", -- 6 "maaaaaaaaam", -- 7 "mmmmmmmmmmm", -- 8 -- Level 1 "..bcd......", -- 0 ".aaaaaaaaa.", -- 1 ".aaaaaaaaa.", -- 2 ".aaaaaaaaa.", -- 3 ".aaaaaaaaa.", -- 4 ".aaaaaaaaa.", -- 5 ".aaaaaaaaa.", -- 6 ".aaaaaaaaa.", -- 7 "...........", -- 8 -- Level 2 "...........", -- 0 ".aaeaaaaaa.", -- 1 ".affgggffa.", -- 2 ".afghhhgfa.", -- 3 ".afghfhgfa.", -- 4 ".afghhhgfa.", -- 5 ".affgggffa.", -- 6 ".aaaaaaaaa.", -- 7 "...........", -- 8 -- Level 3 "...........", -- 0 ".iijii.iii.", -- 1 ".i.......i.", -- 2 ".i.......i.", -- 3 "...........", -- 4 ".i.......i.", -- 5 ".i.......i.", -- 6 ".ii.iii.ii.", -- 7 "...........", -- 8 -- Level 4 "...........", -- 0 ".aaaaaaaaa.", -- 1 ".a..k....a.", -- 2 ".a.......a.", -- 3 ".al.....na.", -- 4 ".a.......a.", -- 5 ".a...o...a.", -- 6 ".aaaaaaaaa.", -- 7 "...........", -- 8 -- Level 5 "pqqqqqqqqqq", -- 0 "paaaaaaaaar", -- 1 "paaaaaaaaar", -- 2 "paaaaaaaaar", -- 3 "paaaaaaaaar", -- 4 "paaaaaaaaar", -- 5 "paaaaaaaaar", -- 6 "paaaaaaaaar", -- 7 "ssssssssssr", -- 8 }, }, -- House9x7 { OriginData = { ExportName = "House11x7", Name = "Desert 31", GalleryName = "Desert", GalleryIndex = "31", ID = "172", CreatorName = "Aloe_vera", }, Size = { x = 13, y = 6, z = 9, }, Hitbox = { MinX = -1, MinY = 0, MinZ = 0, MaxX = 13, MaxY = 5, MaxZ = 9, }, Connectors = { { Type = -1, RelX = 3, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 24: 0", -- sandstone "b:128: 0", -- sandstonestairs "c:128: 2", -- sandstonestairs "d:128: 1", -- sandstonestairs "e: 64: 3", -- woodendoorblock "f:171: 0", -- carpet "g:171:15", -- carpet "h:171:14", -- carpet "i: 24: 2", -- sandstone "j: 64: 9", -- woodendoorblock "k: 50: 3", -- torch "l: 50: 1", -- torch "m: 19: 0", -- sponge "n: 50: 2", -- torch "o: 50: 4", -- torch "p:128: 4", -- sandstonestairs "q:128: 6", -- sandstonestairs "r:128: 5", -- sandstonestairs "s:128: 7", -- sandstonestairs }, BlockData = { -- Level 0 "mmaaammmmmmmm", -- 0 "maaaaaaaaaaam", -- 1 "maaaaaaaaaaam", -- 2 "maaaaaaaaaaam", -- 3 "maaaaaaaaaaam", -- 4 "maaaaaaaaaaam", -- 5 "maaaaaaaaaaam", -- 6 "maaaaaaaaaaam", -- 7 "mmmmmmmmmmmmm", -- 8 -- Level 1 "..bcd........", -- 0 ".aaaaaaaaaaa.", -- 1 ".aaaaaaaaaaa.", -- 2 ".aaaaaaaaaaa.", -- 3 ".aaaaaaaaaaa.", -- 4 ".aaaaaaaaaaa.", -- 5 ".aaaaaaaaaaa.", -- 6 ".aaaaaaaaaaa.", -- 7 ".............", -- 8 -- Level 2 ".............", -- 0 ".aaeaaaaaaaa.", -- 1 ".affgggggffa.", -- 2 ".afghhhhhgfa.", -- 3 ".afghfffhgfa.", -- 4 ".afghhhhhgfa.", -- 5 ".affgggggffa.", -- 6 ".aaaaaaaaaaa.", -- 7 ".............", -- 8 -- Level 3 ".............", -- 0 ".iiji.iii.ii.", -- 1 ".i.........i.", -- 2 ".i.........i.", -- 3 ".............", -- 4 ".i.........i.", -- 5 ".i.........i.", -- 6 ".ii.ii.ii.ii.", -- 7 ".............", -- 8 -- Level 4 ".............", -- 0 ".aaaaaaaaaaa.", -- 1 ".a..k..k...a.", -- 2 ".a.........a.", -- 3 ".al.......na.", -- 4 ".a.........a.", -- 5 ".a....o....a.", -- 6 ".aaaaaaaaaaa.", -- 7 ".............", -- 8 -- Level 5 "pqqqqqqqqqqqq", -- 0 "paaaaaaaaaaar", -- 1 "paaaaaaaaaaar", -- 2 "paaaaaaaaaaar", -- 3 "paaaaaaaaaaar", -- 4 "paaaaaaaaaaar", -- 5 "paaaaaaaaaaar", -- 6 "paaaaaaaaaaar", -- 7 "ssssssssssssr", -- 8 }, }, -- House11x7 { OriginData = { ExportName = "Forge", Name = "Desert 32", GalleryName = "Desert", GalleryIndex = "32", ID = "173", CreatorName = "Aloe_vera", }, Size = { x = 12, y = 6, z = 10, }, Hitbox = { MinX = -1, MinY = 0, MinZ = 0, MaxX = 12, MaxY = 5, MaxZ = 10, }, Connectors = { { Type = -1, RelX = 3, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 24: 0", -- sandstone "b:128: 0", -- sandstonestairs "c:128: 2", -- sandstonestairs "d:128: 1", -- sandstonestairs "e:128: 3", -- sandstonestairs "f:171:15", -- carpet "g: 64: 2", -- woodendoorblock "h:171: 0", -- carpet "i:171:14", -- carpet "j: 61: 2", -- furnace "k: 10: 0", -- lava "l: 54: 2", -- chest "m: 19: 0", -- sponge "n: 24: 2", -- sandstone "o: 64: 9", -- woodendoorblock "p: 50: 1", -- torch "q:101: 0", -- ironbars "r:128: 4", -- sandstonestairs "s:128: 6", -- sandstonestairs "t:128: 5", -- sandstonestairs "u:128: 7", -- sandstonestairs }, BlockData = { -- Level 0 "aaaaaaammmmm", -- 0 "aaaaaaaaaaam", -- 1 "aaaaaaaaaaam", -- 2 "aaaaaaaaaaam", -- 3 "aaaaaaaaaaam", -- 4 "aaaaaaaaaaam", -- 5 "maaaaaaaaaam", -- 6 "maaaaaaaaaam", -- 7 "maaaaaaaaaam", -- 8 "mmmmmmmmmmmm", -- 9 -- Level 1 "bcccccd.....", -- 0 "baaaaaaaaaa.", -- 1 "baaaaaaaaaa.", -- 2 "baaaaaaaaaa.", -- 3 "baaaaaaaaaa.", -- 4 "eaaaaaaaaaa.", -- 5 ".aaaaaaaaaa.", -- 6 ".aaaaaaaaaa.", -- 7 ".aaaaaaaaaa.", -- 8 "............", -- 9 -- Level 2 "............", -- 0 ".a....aaaaa.", -- 1 "......afffa.", -- 2 "......ghfha.", -- 3 "......aiiia.", -- 4 ".a....ahfha.", -- 5 ".ajaajafffa.", -- 6 ".aakkaal..a.", -- 7 ".aaaaaaaaaa.", -- 8 "............", -- 9 -- Level 3 "............", -- 0 ".n....nn.nn.", -- 1 "......n...n.", -- 2 "......o...n.", -- 3 "......n.....", -- 4 ".n....n...n.", -- 5 ".n....n...n.", -- 6 ".n....n...n.", -- 7 ".nnn.nnn.nn.", -- 8 "............", -- 9 -- Level 4 "............", -- 0 ".a....aaaaa.", -- 1 "......a...a.", -- 2 "......a...a.", -- 3 "......ap..a.", -- 4 ".a....a...a.", -- 5 ".aqqqqa...a.", -- 6 ".a....a...a.", -- 7 ".aaaaaaaaaa.", -- 8 "............", -- 9 -- Level 5 "rsssssssssss", -- 0 "raaaaaaaaaat", -- 1 "raaaaaaaaaat", -- 2 "raaaaaaaaaat", -- 3 "raaaaaaaaaat", -- 4 "raaaaaaaaaat", -- 5 "raaaaaaaaaat", -- 6 "raaaaaaaaaat", -- 7 "raaaaaaaaaat", -- 8 "uuuuuuuuuuut", -- 9 }, }, -- Forge { OriginData = { ExportName = "MarketStall", Name = "Desert 34", GalleryName = "Desert", GalleryIndex = "34", ID = "175", CreatorName = "Aloe_vera", }, Size = { x = 7, y = 6, z = 7, }, Hitbox = { MinX = -1, MinY = 0, MinZ = 0, MaxX = 7, MaxY = 5, MaxZ = 7, }, Connectors = { { Type = -1, RelX = 2, RelY = 0, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "5", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 12: 0", -- sand "b: 85: 0", -- fence "c:171:14", -- carpet "d:171:15", -- carpet "e:171: 0", -- carpet "f: 35:14", -- wool "g: 35: 0", -- wool "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "aaaaaaa", -- 0 "aaaaaaa", -- 1 "aaaaaaa", -- 2 "aaaaaaa", -- 3 "aaaaaaa", -- 4 "aaaaaaa", -- 5 "aaaaaaa", -- 6 -- Level 1 "b.....b", -- 0 "cddeddc", -- 1 "cdeeedc", -- 2 "cdeeedc", -- 3 "cddeddc", -- 4 "b.....b", -- 5 ".......", -- 6 -- Level 2 "b.....b", -- 0 ".......", -- 1 ".......", -- 2 ".......", -- 3 ".......", -- 4 "b.....b", -- 5 ".......", -- 6 -- Level 3 "b.....b", -- 0 ".......", -- 1 ".......", -- 2 ".......", -- 3 ".......", -- 4 "b.....b", -- 5 "fgfgfgf", -- 6 -- Level 4 "fgfgfgf", -- 0 ".......", -- 1 ".......", -- 2 ".......", -- 3 ".......", -- 4 "fgfgfgf", -- 5 ".......", -- 6 -- Level 5 ".......", -- 0 "fgfgfgf", -- 1 "fgfgfgf", -- 2 "fgfgfgf", -- 3 "fgfgfgf", -- 4 ".......", -- 5 ".......", -- 6 }, }, -- MarketStall { OriginData = { ExportName = "Marketplace", Name = "Desert 38", GalleryName = "Desert", GalleryIndex = "38", ID = "261", CreatorName = "Aloe_vera", }, Size = { x = 14, y = 4, z = 16, }, Hitbox = { MinX = -1, MinY = 0, MinZ = 0, MaxX = 14, MaxY = 3, MaxZ = 16, }, Connectors = { { Type = -1, RelX = 5, RelY = 0, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "20", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 24: 0", -- sandstone "b: 12: 0", -- sand "c: 24: 2", -- sandstone "d: 12: 2", -- sand "e: 85: 0", -- fence "f: 5: 0", -- planks "g:128: 2", -- sandstonestairs "h:128: 0", -- sandstonestairs "i: 8: 0", -- water "j:128: 1", -- sandstonestairs "k:128: 3", -- sandstonestairs "l: 35: 0", -- wool "m: 19: 0", -- sponge "n: 35:14", -- wool }, BlockData = { -- Level 0 "aaaabbbaaabbbb", -- 0 "aaaabbaabbabbb", -- 1 "aababbabcabbbb", -- 2 "aaaaabaaaaabbb", -- 3 "bbbbbbbbbbbbbb", -- 4 "bbbbbbbbbbaabb", -- 5 "bbbbccccbbabab", -- 6 "ccbbccccbbaaab", -- 7 "ccbbccccbbabbb", -- 8 "dcbbccccbbabaa", -- 9 "ccbbbbbbbbaaba", -- 10 "ccbbbbbbbbabaa", -- 11 "bbbbbbbbbbabaa", -- 12 "bbbaababbbaaba", -- 13 "bbbcaaaabbabbb", -- 14 "bbbcccabbbabbb", -- 15 -- Level 1 "e...e.e...e...", -- 0 "..............", -- 1 "..............", -- 2 "fffff.fffff...", -- 3 "..............", -- 4 "..........f..e", -- 5 "....gggg..f...", -- 6 ".f..hiij..f...", -- 7 ".f..hiij..f...", -- 8 ".f..kkkk..f..e", -- 9 ".f............", -- 10 ".f........f..e", -- 11 "...fffff..f...", -- 12 "..........f...", -- 13 "..........f...", -- 14 "...e...e..f..e", -- 15 -- Level 2 "lnlnl.lnlnl...", -- 0 "..............", -- 1 "..............", -- 2 "e...e.e...e...", -- 3 "..............", -- 4 "..........e..l", -- 5 ".............n", -- 6 ".e...........l", -- 7 ".............n", -- 8 "..........e..l", -- 9 "..............", -- 10 ".e........e..l", -- 11 "...e...e.....n", -- 12 ".............l", -- 13 ".............n", -- 14 "...lnlnl..e..l", -- 15 -- Level 3 "..............", -- 0 "lnlnl.lnlnl...", -- 1 "lnlnl.lnlnl...", -- 2 "lnlnl.lnlnl...", -- 3 "..............", -- 4 "..........lll.", -- 5 "..........nnn.", -- 6 "ll........lll.", -- 7 "nn........nnn.", -- 8 "ll........lll.", -- 9 "nn............", -- 10 "ll........lll.", -- 11 "...lnlnl..nnn.", -- 12 "...lnlnl..lll.", -- 13 "...lnlnl..nnn.", -- 14 "..........lll.", -- 15 }, }, -- Marketplace { OriginData = { ExportName = "Well", Name = "Desert 44", GalleryName = "Desert", GalleryIndex = "44", ID = "275", CreatorName = "Aloe_vera", }, Size = { x = 5, y = 16, z = 5, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 4, MaxY = 15, MaxZ = 4, }, Connectors = { { Type = 2, RelX = 4, RelY = 11, RelZ = 2, Direction = 5, -- X+ }, { Type = 2, RelX = 2, RelY = 11, RelZ = 4, Direction = 3, -- Z+ }, { Type = 2, RelX = 0, RelY = 11, RelZ = 2, Direction = 4, -- X- }, { Type = 2, RelX = 2, RelY = 11, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "1", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", ["VerticalStrategy"] = "TerrainOrOceanTop|-11", }, BlockDefinitions = { ".: 0: 0", -- air "a: 1: 0", -- stone "b: 24: 0", -- sandstone "c: 8: 0", -- water "d:128: 2", -- sandstonestairs "e:128: 0", -- sandstonestairs "f:128: 1", -- sandstonestairs "g:128: 3", -- sandstonestairs "h:128: 6", -- sandstonestairs "i:128: 4", -- sandstonestairs "j:128: 5", -- sandstonestairs "k:128: 7", -- sandstonestairs "l: 44: 1", -- stone_slab "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "aaaaa", -- 0 "abbba", -- 1 "abbba", -- 2 "abbba", -- 3 "aaaaa", -- 4 -- Level 1 "bbbbb", -- 0 "bcccb", -- 1 "bcccb", -- 2 "bcccb", -- 3 "bbbbb", -- 4 -- Level 2 "bbbbb", -- 0 "bcccb", -- 1 "bcccb", -- 2 "bcccb", -- 3 "bbbbb", -- 4 -- Level 3 "bbbbb", -- 0 "bcccb", -- 1 "bcccb", -- 2 "bcccb", -- 3 "bbbbb", -- 4 -- Level 4 "bbbbb", -- 0 "bcccb", -- 1 "bcccb", -- 2 "bcccb", -- 3 "bbbbb", -- 4 -- Level 5 "bbbbb", -- 0 "bcccb", -- 1 "bcccb", -- 2 "bcccb", -- 3 "bbbbb", -- 4 -- Level 6 "bbbbb", -- 0 "bcccb", -- 1 "bcccb", -- 2 "bcccb", -- 3 "bbbbb", -- 4 -- Level 7 "bbbbb", -- 0 "bcccb", -- 1 "bcccb", -- 2 "bcccb", -- 3 "bbbbb", -- 4 -- Level 8 "bbbbb", -- 0 "bcbcb", -- 1 "bbcbb", -- 2 "bcbcb", -- 3 "bbbbb", -- 4 -- Level 9 "bbbbb", -- 0 "bcbcb", -- 1 "bbbbb", -- 2 "bcbcb", -- 3 "bbbbb", -- 4 -- Level 10 "bbbbb", -- 0 "bcbcb", -- 1 "bbbbb", -- 2 "bcbcb", -- 3 "bbbbb", -- 4 -- Level 11 "ddddd", -- 0 "ecccf", -- 1 "ecbcf", -- 2 "ecccf", -- 3 "ggggf", -- 4 -- Level 12 ".....", -- 0 ".....", -- 1 "..b..", -- 2 ".....", -- 3 ".....", -- 4 -- Level 13 ".....", -- 0 ".....", -- 1 "..b..", -- 2 ".....", -- 3 ".....", -- 4 -- Level 14 ".....", -- 0 ".hhh.", -- 1 ".ibj.", -- 2 ".kkj.", -- 3 ".....", -- 4 -- Level 15 "lllll", -- 0 "lllll", -- 1 "lllll", -- 2 "lllll", -- 3 "lllll", -- 4 }, }, -- Well { OriginData = { ExportName = "HouseL13x12", Name = "Desert 53", GalleryName = "Desert", GalleryIndex = "53", ID = "345", CreatorName = "jakibaki", }, Size = { x = 15, y = 6, z = 14, }, Hitbox = { MinX = -1, MinY = 0, MinZ = 0, MaxX = 15, MaxY = 5, MaxZ = 14, }, Connectors = { { Type = -1, RelX = 4, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 24: 0", -- sandstone "b:128: 0", -- sandstonestairs "c:128: 2", -- sandstonestairs "d:128: 1", -- sandstonestairs "e: 43: 1", -- doublestoneslab "f: 64: 3", -- woodendoorblock "g:171: 0", -- carpet "h:171:15", -- carpet "i:171:14", -- carpet "j: 58: 0", -- workbench "k: 24: 2", -- sandstone "l: 64: 9", -- woodendoorblock "m: 19: 0", -- sponge "n: 50: 3", -- torch "o: 50: 1", -- torch "p: 50: 2", -- torch "q: 50: 4", -- torch "r:128: 6", -- sandstonestairs "s:128: 5", -- sandstonestairs "t:128: 4", -- sandstonestairs "u:128: 7", -- sandstonestairs }, BlockData = { -- Level 0 "mmmaaammmmmmmmm", -- 0 "maaaaaaaaaaaaam", -- 1 "maaaaaaaaaaaaam", -- 2 "maaaaaaaaaaaaam", -- 3 "maaaaaaaaaaaaam", -- 4 "maaaaaaaaaaaaam", -- 5 "maaaaaaaaaaaaam", -- 6 "maaaaaaaaaaaaam", -- 7 "mmmmmmmaaaaaaam", -- 8 "mmmmmmmaaaaaaam", -- 9 "mmmmmmmaaaaaaam", -- 10 "mmmmmmmaaaaaaam", -- 11 "mmmmmmmaaaaaaam", -- 12 "mmmmmmmmmmmmmmm", -- 13 -- Level 1 "...bcd.........", -- 0 ".aaaaaaaaaaaaa.", -- 1 ".aaaaaaaaaaaaa.", -- 2 ".aaaaaaaaaaaaa.", -- 3 ".aaaaaaaaaaaaa.", -- 4 ".aaaaaaaaaaaea.", -- 5 ".aaaaaaaaaaaaa.", -- 6 ".aaaaaaaaaaaaa.", -- 7 ".......aeaaaaa.", -- 8 "mmmmmm.aaaaaaa.", -- 9 "mmmmmm.aaaaaaa.", -- 10 "mmmmmm.aaaaaaa.", -- 11 "mmmmmm.aaaaaaa.", -- 12 "...............", -- 13 -- Level 2 "...............", -- 0 ".aaafaaaaaaaaa.", -- 1 ".agghhhhhhhhga.", -- 2 ".aghiiiiiiiiha.", -- 3 ".aghiggggggiha.", -- 4 ".aghiiiiiigiha.", -- 5 ".agghhhhhigiha.", -- 6 ".aaaaaaahigiha.", -- 7 ".......ahigiha.", -- 8 "mmmmmm.ahiiiha.", -- 9 "mmmmmm.aghhhga.", -- 10 "mmmmmm.aggggja.", -- 11 "mmmmmm.aaaaaaa.", -- 12 "...............", -- 13 -- Level 3 "...............", -- 0 ".kkklkkkk.kkkk.", -- 1 ".k...........k.", -- 2 ".k...........k.", -- 3 "...............", -- 4 ".k...........k.", -- 5 ".k...........k.", -- 6 ".kkk.kkk.....k.", -- 7 ".......k.....k.", -- 8 "mmmmmm.k.......", -- 9 "mmmmmm.......k.", -- 10 "mmmmmm.k.....k.", -- 11 "mmmmmm.kkk.kkk.", -- 12 "...............", -- 13 -- Level 4 "...............", -- 0 ".aaaaaaaaaaaaa.", -- 1 ".a......n....a.", -- 2 ".a...........a.", -- 3 ".ao..........a.", -- 4 ".a...........a.", -- 5 ".a..........pa.", -- 6 ".aaaaaaa.....a.", -- 7 ".......a.....a.", -- 8 "mmmmmm.a.....a.", -- 9 "mmmmmm.a.....a.", -- 10 "mmmmmm.a..q..a.", -- 11 "mmmmmm.aaaaaaa.", -- 12 "...............", -- 13 -- Level 5 "rrrrrrrrrrrrrrs", -- 0 "taaaaaaaaaaaaas", -- 1 "taaaaaaaaaaaaas", -- 2 "taaaaaaaaaaaaas", -- 3 "taaaaaaaaaaaaas", -- 4 "taaaaaaaaaaaaas", -- 5 "taaaaaaaaaaaaas", -- 6 "taaaaaaaaaaaaas", -- 7 "tuuuuutaaaaaaas", -- 8 "mmmmmmtaaaaaaas", -- 9 "mmmmmmtaaaaaaas", -- 10 "mmmmmmtaaaaaaas", -- 11 "mmmmmmtaaaaaaas", -- 12 "......tuuuuuuuu", -- 13 }, }, -- HouseL13x12 }, -- Pieces } ================================================ FILE: Server/Prefabs/Villages/SandVillage.cubeset ================================================ -- SandVillage.cubeset -- Defines the prefabs in the group SandVillage -- NOTE: This file has been generated automatically by GalExport! -- Any manual changes will be overwritten by the next automatic export! Cubeset = { Metadata = { CubesetFormatVersion = 1, ExportDate = "2016-11-30 13:45:41", ["AllowedBiomes"] = "Desert, DesertM", ["IntendedUse"] = "Village", }, Pieces = { { OriginData = { ExportName = "Well", Name = "Desert 0", GalleryName = "Desert", GalleryIndex = "0", ID = "1", CreatorName = "Aloe_vera", }, Size = { x = 4, y = 13, z = 4, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 3, MaxY = 12, MaxZ = 3, }, Connectors = { { Type = 2, RelX = 2, RelY = 8, RelZ = 0, Direction = 2, -- Z- }, { Type = 2, RelX = 0, RelY = 8, RelZ = 1, Direction = 4, -- X- }, { Type = 2, RelX = 1, RelY = 8, RelZ = 3, Direction = 3, -- Z+ }, { Type = 2, RelX = 3, RelY = 8, RelZ = 2, Direction = 5, -- X+ }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "None", ["IsStarting"] = "1", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", ["VerticalStrategy"] = "TerrainOrOceanTop|-8", }, BlockDefinitions = { ".: 0: 0", -- air "a: 1: 0", -- stone "b: 24: 0", -- sandstone "c: 8: 0", -- water "d: 85: 0", -- fence "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "aaaa", -- 0 "aaaa", -- 1 "aaaa", -- 2 "aaaa", -- 3 -- Level 1 "bbbb", -- 0 "bccb", -- 1 "bccb", -- 2 "bbbb", -- 3 -- Level 2 "bbbb", -- 0 "bccb", -- 1 "bccb", -- 2 "bbbb", -- 3 -- Level 3 "bbbb", -- 0 "bccb", -- 1 "bccb", -- 2 "bbbb", -- 3 -- Level 4 "bbbb", -- 0 "bccb", -- 1 "bccb", -- 2 "bbbb", -- 3 -- Level 5 "bbbb", -- 0 "bccb", -- 1 "bccb", -- 2 "bbbb", -- 3 -- Level 6 "bbbb", -- 0 "bccb", -- 1 "bccb", -- 2 "bbbb", -- 3 -- Level 7 "bbbb", -- 0 "bccb", -- 1 "bccb", -- 2 "bbbb", -- 3 -- Level 8 "bbbb", -- 0 "b..b", -- 1 "b..b", -- 2 "bbbb", -- 3 -- Level 9 "d..d", -- 0 "....", -- 1 "....", -- 2 "d..d", -- 3 -- Level 10 "d..d", -- 0 "....", -- 1 "....", -- 2 "d..d", -- 3 -- Level 11 "d..d", -- 0 "....", -- 1 "....", -- 2 "d..d", -- 3 -- Level 12 "bbbb", -- 0 "bbbb", -- 1 "bbbb", -- 2 "bbbb", -- 3 }, }, -- Well { OriginData = { ExportName = "SmallHut", Name = "Desert 4", GalleryName = "Desert", GalleryIndex = "4", ID = "68", CreatorName = "tonibm1999", }, Size = { x = 5, y = 6, z = 6, }, Hitbox = { MinX = -1, MinY = 0, MinZ = -1, MaxX = 5, MaxY = 5, MaxZ = 5, }, Connectors = { { Type = -1, RelX = 2, RelY = 1, RelZ = 5, Direction = 3, -- Z+ }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 24: 0", -- sandstone "b:128: 3", -- sandstonestairs "c: 24: 2", -- sandstone "d: 50: 5", -- torch "e: 26:10", -- bedblock "f: 26: 2", -- bedblock "g: 64: 1", -- woodendoorblock "h: 64: 9", -- woodendoorblock "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "aaaaa", -- 0 "aaaaa", -- 1 "aaaaa", -- 2 "aaaaa", -- 3 "aaaaa", -- 4 "mmamm", -- 5 -- Level 1 "aaaaa", -- 0 "aaaaa", -- 1 "aaaaa", -- 2 "aaaaa", -- 3 "aaaaa", -- 4 "..b..", -- 5 -- Level 2 "accca", -- 0 "cdedc", -- 1 "c.f.c", -- 2 "c...c", -- 3 "acgca", -- 4 ".....", -- 5 -- Level 3 "ac.ca", -- 0 "c...c", -- 1 ".....", -- 2 "c...c", -- 3 "achca", -- 4 ".....", -- 5 -- Level 4 "accca", -- 0 "c...c", -- 1 "c...c", -- 2 "c...c", -- 3 "accca", -- 4 ".....", -- 5 -- Level 5 ".aaa.", -- 0 "aaaaa", -- 1 "aaaaa", -- 2 "aaaaa", -- 3 ".aaa.", -- 4 ".....", -- 5 }, }, -- SmallHut { OriginData = { ExportName = "DoubleField", Name = "Desert 5", GalleryName = "Desert", GalleryIndex = "5", ID = "75", CreatorName = "tonibm1999", }, Size = { x = 13, y = 3, z = 9, }, Hitbox = { MinX = -1, MinY = 0, MinZ = -1, MaxX = 13, MaxY = 2, MaxZ = 8, }, Connectors = { { Type = -1, RelX = 6, RelY = 1, RelZ = 8, Direction = 3, -- Z+ }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 24: 0", -- sandstone "b: 60: 7", -- tilleddirt "c: 60: 6", -- tilleddirt "d: 8: 0", -- water "e: 50: 5", -- torch "f: 59: 7", -- wheatblock "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "aaaaaaaaaaaaa", -- 0 "aaaaaaaaaaaaa", -- 1 "aaaaaaaaaaaaa", -- 2 "aaaaaaaaaaaaa", -- 3 "aaaaaaaaaaaaa", -- 4 "aaaaaaaaaaaaa", -- 5 "aaaaaaaaaaaaa", -- 6 "aaaaaaaaaaaaa", -- 7 "aaaaaaaaaaaaa", -- 8 -- Level 1 "aaaaaaaaaaaaa", -- 0 "abcdbbabbdbba", -- 1 "abbdbbabbdbba", -- 2 "abbdbbabbdbba", -- 3 "abbdbbabbdbba", -- 4 "abbdbbabbdbba", -- 5 "acbdbbabbdbba", -- 6 "abbdbbabbdbba", -- 7 "aaaaaaaaaaaaa", -- 8 -- Level 2 "e.....e.....e", -- 0 ".ff.ff.ff.ff.", -- 1 ".ff.ff.ff.ff.", -- 2 ".ff.ff.ff.ff.", -- 3 ".ff.ff.ff.ff.", -- 4 ".ff.ff.ff.ff.", -- 5 ".ff.ff.ff.ff.", -- 6 ".ff.ff.ff.ff.", -- 7 "e.....e.....e", -- 8 }, }, -- DoubleField { OriginData = { ExportName = "House11x7", Name = "Desert 6", GalleryName = "Desert", GalleryIndex = "6", ID = "81", CreatorName = "Aloe_vera", }, Size = { x = 11, y = 7, z = 7, }, Hitbox = { MinX = -1, MinY = 0, MinZ = 0, MaxX = 11, MaxY = 6, MaxZ = 7, }, Connectors = { { Type = -1, RelX = 5, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 24: 0", -- sandstone "b:128: 0", -- sandstonestairs "c:128: 2", -- sandstonestairs "d:128: 1", -- sandstonestairs "e: 64: 3", -- woodendoorblock "f:102: 0", -- glasspane "g: 64: 9", -- woodendoorblock "h:128: 7", -- sandstonestairs "i: 50: 3", -- torch "j: 50: 4", -- torch "k:128: 6", -- sandstonestairs "l:128: 3", -- sandstonestairs "m: 19: 0", -- sponge "n: 50: 1", -- torch "o: 50: 2", -- torch }, BlockData = { -- Level 0 "mmmmaaammmm", -- 0 "maaaaaaaaam", -- 1 "maaaaaaaaam", -- 2 "maaaaaaaaam", -- 3 "maaaaaaaaam", -- 4 "maaaaaaaaam", -- 5 "mmmmmmmmmmm", -- 6 -- Level 1 "....bcd....", -- 0 ".aaaaaaaaa.", -- 1 ".aaaaaaaaa.", -- 2 ".aaaaaaaaa.", -- 3 ".aaaaaaaaa.", -- 4 ".aaaaaaaaa.", -- 5 "...........", -- 6 -- Level 2 "...........", -- 0 ".aaaaeaaaa.", -- 1 ".a.......a.", -- 2 ".a.......a.", -- 3 ".a.......a.", -- 4 ".aaaaaaaaa.", -- 5 "...........", -- 6 -- Level 3 "...........", -- 0 ".affagaffa.", -- 1 ".f.......f.", -- 2 ".f.......f.", -- 3 ".f.......f.", -- 4 ".affafaffa.", -- 5 "...........", -- 6 -- Level 4 "ccccccccccc", -- 0 "haaaaaaaaah", -- 1 ".a..i.i..a.", -- 2 ".a.......a.", -- 3 ".a..j.j..a.", -- 4 "kaaaaaaaaak", -- 5 "lllllllllll", -- 6 -- Level 5 "...........", -- 0 "ccccccccccc", -- 1 "haaaaaaaaah", -- 2 ".an.....oa.", -- 3 "kaaaaaaaaak", -- 4 "lllllllllll", -- 5 "...........", -- 6 -- Level 6 "...........", -- 0 "...........", -- 1 "ccccccccccc", -- 2 "aaaaaaaaaaa", -- 3 "lllllllllll", -- 4 "...........", -- 5 "...........", -- 6 }, }, -- House11x7 { OriginData = { ExportName = "HouseL14x12", Name = "Desert 7", GalleryName = "Desert", GalleryIndex = "7", ID = "82", CreatorName = "Aloe_vera", }, Size = { x = 14, y = 7, z = 12, }, Hitbox = { MinX = -1, MinY = 0, MinZ = 0, MaxX = 14, MaxY = 6, MaxZ = 12, }, Connectors = { { Type = -1, RelX = 8, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 24: 0", -- sandstone "b:128: 0", -- sandstonestairs "c:128: 2", -- sandstonestairs "d:128: 1", -- sandstonestairs "e:128: 3", -- sandstonestairs "f: 64: 3", -- woodendoorblock "g: 64: 1", -- woodendoorblock "h:102: 0", -- glasspane "i: 64: 9", -- woodendoorblock "j:128: 7", -- sandstonestairs "k: 50: 3", -- torch "l: 50: 4", -- torch "m: 19: 0", -- sponge "n:128: 6", -- sandstonestairs "o:128: 5", -- sandstonestairs "p:128: 4", -- sandstonestairs "q: 50: 1", -- torch }, BlockData = { -- Level 0 "mmmmmmmaaammmm", -- 0 "maaaaaaaaaaaam", -- 1 "maaaaaaaaaaaam", -- 2 "maaaaaaaaaaaam", -- 3 "maaaaaaaaaaaam", -- 4 "maaaaaaaaaaaam", -- 5 "mmmmaaamaaaaam", -- 6 "mmmmmmmmaaaaam", -- 7 "mmmmmmmmaaaaam", -- 8 "mmmmmmmmaaaaam", -- 9 "mmmmmmmmaaaaam", -- 10 "mmmmmmmmmmmmmm", -- 11 -- Level 1 ".......bcd....", -- 0 ".aaaaaaaaaaaa.", -- 1 ".aaaaaaaaaaaa.", -- 2 ".aaaaaaaaaaaa.", -- 3 ".aaaaaaaaaaaa.", -- 4 ".aaaaaaaaaaaa.", -- 5 "....bed.aaaaa.", -- 6 "........aaaaa.", -- 7 "........aaaaa.", -- 8 "........aaaaa.", -- 9 "........aaaaa.", -- 10 "..............", -- 11 -- Level 2 "..............", -- 0 ".aaaaaaafaaaa.", -- 1 ".a..........a.", -- 2 ".a..........a.", -- 3 ".a..........a.", -- 4 ".aaaagaaa...a.", -- 5 "........a...a.", -- 6 "........a...a.", -- 7 "........a...a.", -- 8 "........a...a.", -- 9 "........aaaaa.", -- 10 "..............", -- 11 -- Level 3 "..............", -- 0 ".ahhahhaiahha.", -- 1 ".h..........h.", -- 2 ".h..........h.", -- 3 ".h..........a.", -- 4 ".ahhaiahh...h.", -- 5 "........h...h.", -- 6 "........a...a.", -- 7 "........h...h.", -- 8 "........h...h.", -- 9 "........ahhha.", -- 10 "..............", -- 11 -- Level 4 "cccccccccccccc", -- 0 "jaaaaaaaaaaaad", -- 1 ".a.....k.k..ad", -- 2 ".a..........ad", -- 3 ".a..l.l.....ad", -- 4 "naaaaaaaa...ad", -- 5 "eeeeeeeba...ad", -- 6 ".......ba...ad", -- 7 ".......ba...ad", -- 8 ".......ba...ad", -- 9 ".......baaaaad", -- 10 ".......bo...pd", -- 11 -- Level 5 "..............", -- 0 "ccccccccccccc.", -- 1 "jaaaaaaaaaaad.", -- 2 ".aq........ad.", -- 3 "naaaaaaaaa.ad.", -- 4 "eeeeeeeeba.ad.", -- 5 "........ba.ad.", -- 6 "........ba.ad.", -- 7 "........ba.ad.", -- 8 "........balad.", -- 9 "........baaad.", -- 10 "........bo.pd.", -- 11 -- Level 6 "..............", -- 0 "..............", -- 1 "cccccccccccc..", -- 2 "aaaaaaaaaaad..", -- 3 "eeeeeeeeebad..", -- 4 ".........bad..", -- 5 ".........bad..", -- 6 ".........bad..", -- 7 ".........bad..", -- 8 ".........bad..", -- 9 ".........bad..", -- 10 ".........bad..", -- 11 }, }, -- HouseL14x12 { OriginData = { ExportName = "House7x7", Name = "Desert 8", GalleryName = "Desert", GalleryIndex = "8", ID = "112", CreatorName = "Aloe_vera", }, Size = { x = 7, y = 7, z = 7, }, Hitbox = { MinX = -1, MinY = 0, MinZ = 0, MaxX = 7, MaxY = 6, MaxZ = 7, }, Connectors = { { Type = -1, RelX = 4, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 24: 0", -- sandstone "b:128: 0", -- sandstonestairs "c:128: 2", -- sandstonestairs "d:128: 1", -- sandstonestairs "e: 64: 3", -- woodendoorblock "f:102: 0", -- glasspane "g: 64: 9", -- woodendoorblock "h:128: 7", -- sandstonestairs "i: 50: 3", -- torch "j:128: 6", -- sandstonestairs "k:128: 3", -- sandstonestairs "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "mmmaaam", -- 0 "maaaaam", -- 1 "maaaaam", -- 2 "maaaaam", -- 3 "maaaaam", -- 4 "maaaaam", -- 5 "mmmmmmm", -- 6 -- Level 1 "...bcd.", -- 0 ".aaaaa.", -- 1 ".aaaaa.", -- 2 ".aaaaa.", -- 3 ".aaaaa.", -- 4 ".aaaaa.", -- 5 ".......", -- 6 -- Level 2 ".......", -- 0 ".aaaea.", -- 1 ".a...a.", -- 2 ".a...a.", -- 3 ".a...a.", -- 4 ".aaaaa.", -- 5 ".......", -- 6 -- Level 3 ".......", -- 0 ".afaga.", -- 1 ".f...f.", -- 2 ".f...f.", -- 3 ".f...f.", -- 4 ".afffa.", -- 5 ".......", -- 6 -- Level 4 "ccccccc", -- 0 "haaaaah", -- 1 ".a.i.a.", -- 2 ".a...a.", -- 3 ".a...a.", -- 4 "jaaaaaj", -- 5 "kkkkkkk", -- 6 -- Level 5 ".......", -- 0 "ccccccc", -- 1 "haaaaah", -- 2 ".a...a.", -- 3 "jaaaaaj", -- 4 "kkkkkkk", -- 5 ".......", -- 6 -- Level 6 ".......", -- 0 ".......", -- 1 "ccccccc", -- 2 "aaaaaaa", -- 3 "kkkkkkk", -- 4 ".......", -- 5 ".......", -- 6 }, }, -- House7x7 { OriginData = { ExportName = "House9x7", Name = "Desert 9", GalleryName = "Desert", GalleryIndex = "9", ID = "113", CreatorName = "xoft", }, Size = { x = 9, y = 7, z = 7, }, Hitbox = { MinX = -1, MinY = 0, MinZ = 0, MaxX = 9, MaxY = 6, MaxZ = 7, }, Connectors = { { Type = -1, RelX = 4, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 24: 0", -- sandstone "b:128: 0", -- sandstonestairs "c:128: 2", -- sandstonestairs "d:128: 1", -- sandstonestairs "e: 64: 3", -- woodendoorblock "f:102: 0", -- glasspane "g: 64: 9", -- woodendoorblock "h:128: 7", -- sandstonestairs "i: 50: 3", -- torch "j: 50: 4", -- torch "k:128: 6", -- sandstonestairs "l:128: 3", -- sandstonestairs "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "mmmaaammm", -- 0 "maaaaaaam", -- 1 "maaaaaaam", -- 2 "maaaaaaam", -- 3 "maaaaaaam", -- 4 "maaaaaaam", -- 5 "mmmmmmmmm", -- 6 -- Level 1 "...bcd...", -- 0 ".aaaaaaa.", -- 1 ".aaaaaaa.", -- 2 ".aaaaaaa.", -- 3 ".aaaaaaa.", -- 4 ".aaaaaaa.", -- 5 ".........", -- 6 -- Level 2 ".........", -- 0 ".aaaeaaa.", -- 1 ".a.....a.", -- 2 ".a.....a.", -- 3 ".a.....a.", -- 4 ".aaaaaaa.", -- 5 ".........", -- 6 -- Level 3 ".........", -- 0 ".afagafa.", -- 1 ".f.....f.", -- 2 ".f.....f.", -- 3 ".f.....f.", -- 4 ".affaffa.", -- 5 ".........", -- 6 -- Level 4 "ccccccccc", -- 0 "haaaaaaah", -- 1 ".a.i.i.a.", -- 2 ".a.....a.", -- 3 ".a..j..a.", -- 4 "kaaaaaaak", -- 5 "lllllllll", -- 6 -- Level 5 ".........", -- 0 "ccccccccc", -- 1 "haaaaaaah", -- 2 ".a.....a.", -- 3 "kaaaaaaak", -- 4 "lllllllll", -- 5 ".........", -- 6 -- Level 6 ".........", -- 0 ".........", -- 1 "ccccccccc", -- 2 "aaaaaaaaa", -- 3 "lllllllll", -- 4 ".........", -- 5 ".........", -- 6 }, }, -- House9x7 { OriginData = { ExportName = "House9x9", Name = "Desert 10", GalleryName = "Desert", GalleryIndex = "10", ID = "114", CreatorName = "xoft", }, Size = { x = 9, y = 8, z = 9, }, Hitbox = { MinX = -1, MinY = 0, MinZ = 0, MaxX = 9, MaxY = 7, MaxZ = 9, }, Connectors = { { Type = -1, RelX = 4, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 24: 0", -- sandstone "b:128: 0", -- sandstonestairs "c:128: 2", -- sandstonestairs "d:128: 1", -- sandstonestairs "e: 64: 3", -- woodendoorblock "f:102: 0", -- glasspane "g: 64: 9", -- woodendoorblock "h:128: 7", -- sandstonestairs "i: 50: 3", -- torch "j: 50: 4", -- torch "k:128: 6", -- sandstonestairs "l:128: 3", -- sandstonestairs "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "mmmaaammm", -- 0 "maaaaaaam", -- 1 "maaaaaaam", -- 2 "maaaaaaam", -- 3 "maaaaaaam", -- 4 "maaaaaaam", -- 5 "maaaaaaam", -- 6 "maaaaaaam", -- 7 "mmmmmmmmm", -- 8 -- Level 1 "...bcd...", -- 0 ".aaaaaaa.", -- 1 ".aaaaaaa.", -- 2 ".aaaaaaa.", -- 3 ".aaaaaaa.", -- 4 ".aaaaaaa.", -- 5 ".aaaaaaa.", -- 6 ".aaaaaaa.", -- 7 ".........", -- 8 -- Level 2 ".........", -- 0 ".aaaeaaa.", -- 1 ".a.....a.", -- 2 ".a.....a.", -- 3 ".a.....a.", -- 4 ".a.....a.", -- 5 ".a.....a.", -- 6 ".aaaaaaa.", -- 7 ".........", -- 8 -- Level 3 ".........", -- 0 ".afagafa.", -- 1 ".f.....f.", -- 2 ".f.....f.", -- 3 ".a.....a.", -- 4 ".f.....f.", -- 5 ".f.....f.", -- 6 ".affaffa.", -- 7 ".........", -- 8 -- Level 4 "ccccccccc", -- 0 "haaaaaaah", -- 1 ".a.i.i.a.", -- 2 ".a.....a.", -- 3 ".a.....a.", -- 4 ".a.....a.", -- 5 ".a..j..a.", -- 6 "kaaaaaaak", -- 7 "lllllllll", -- 8 -- Level 5 ".........", -- 0 "ccccccccc", -- 1 "haaaaaaah", -- 2 ".a.....a.", -- 3 ".a.....a.", -- 4 ".a.....a.", -- 5 "kaaaaaaak", -- 6 "lllllllll", -- 7 ".........", -- 8 -- Level 6 ".........", -- 0 ".........", -- 1 "ccccccccc", -- 2 "haaaaaaah", -- 3 ".a.....a.", -- 4 "kaaaaaaak", -- 5 "lllllllll", -- 6 ".........", -- 7 ".........", -- 8 -- Level 7 ".........", -- 0 ".........", -- 1 ".........", -- 2 "ccccccccc", -- 3 "aaaaaaaaa", -- 4 "lllllllll", -- 5 ".........", -- 6 ".........", -- 7 ".........", -- 8 }, }, -- House9x9 { OriginData = { ExportName = "House11x9", Name = "Desert 11", GalleryName = "Desert", GalleryIndex = "11", ID = "115", CreatorName = "xoft", }, Size = { x = 11, y = 8, z = 9, }, Hitbox = { MinX = -1, MinY = 0, MinZ = 0, MaxX = 11, MaxY = 7, MaxZ = 9, }, Connectors = { { Type = -1, RelX = 5, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 24: 0", -- sandstone "b:128: 0", -- sandstonestairs "c:128: 2", -- sandstonestairs "d:128: 1", -- sandstonestairs "e: 64: 3", -- woodendoorblock "f:102: 0", -- glasspane "g: 64: 9", -- woodendoorblock "h:128: 7", -- sandstonestairs "i: 50: 3", -- torch "j: 50: 4", -- torch "k:128: 6", -- sandstonestairs "l:128: 3", -- sandstonestairs "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "mmmmaaammmm", -- 0 "maaaaaaaaam", -- 1 "maaaaaaaaam", -- 2 "maaaaaaaaam", -- 3 "maaaaaaaaam", -- 4 "maaaaaaaaam", -- 5 "maaaaaaaaam", -- 6 "maaaaaaaaam", -- 7 "mmmmmmmmmmm", -- 8 -- Level 1 "....bcd....", -- 0 ".aaaaaaaaa.", -- 1 ".aaaaaaaaa.", -- 2 ".aaaaaaaaa.", -- 3 ".aaaaaaaaa.", -- 4 ".aaaaaaaaa.", -- 5 ".aaaaaaaaa.", -- 6 ".aaaaaaaaa.", -- 7 "...........", -- 8 -- Level 2 "...........", -- 0 ".aaaaeaaaa.", -- 1 ".a.......a.", -- 2 ".a.......a.", -- 3 ".a.......a.", -- 4 ".a.......a.", -- 5 ".a.......a.", -- 6 ".aaaaaaaaa.", -- 7 "...........", -- 8 -- Level 3 "...........", -- 0 ".affagaffa.", -- 1 ".f.......f.", -- 2 ".f.......f.", -- 3 ".a.......a.", -- 4 ".f.......f.", -- 5 ".f.......f.", -- 6 ".afffafffa.", -- 7 "...........", -- 8 -- Level 4 "ccccccccccc", -- 0 "haaaaaaaaah", -- 1 ".a..i.i..a.", -- 2 ".a.......a.", -- 3 ".a.......a.", -- 4 ".a.......a.", -- 5 ".a...j...a.", -- 6 "kaaaaaaaaak", -- 7 "lllllllllll", -- 8 -- Level 5 "...........", -- 0 "ccccccccccc", -- 1 "haaaaaaaaah", -- 2 ".a.......a.", -- 3 ".a.......a.", -- 4 ".a.......a.", -- 5 "kaaaaaaaaak", -- 6 "lllllllllll", -- 7 "...........", -- 8 -- Level 6 "...........", -- 0 "...........", -- 1 "ccccccccccc", -- 2 "haaaaaaaaah", -- 3 ".a.......a.", -- 4 "kaaaaaaaaak", -- 5 "lllllllllll", -- 6 "...........", -- 7 "...........", -- 8 -- Level 7 "...........", -- 0 "...........", -- 1 "...........", -- 2 "ccccccccccc", -- 3 "aaaaaaaaaaa", -- 4 "lllllllllll", -- 5 "...........", -- 6 "...........", -- 7 "...........", -- 8 }, }, -- House11x9 { OriginData = { ExportName = "House13x9", Name = "Desert 12", GalleryName = "Desert", GalleryIndex = "12", ID = "116", CreatorName = "xoft", }, Size = { x = 13, y = 8, z = 9, }, Hitbox = { MinX = -1, MinY = 0, MinZ = 0, MaxX = 13, MaxY = 7, MaxZ = 9, }, Connectors = { { Type = -1, RelX = 6, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 24: 0", -- sandstone "b:128: 0", -- sandstonestairs "c:128: 2", -- sandstonestairs "d:128: 1", -- sandstonestairs "e: 64: 3", -- woodendoorblock "f:102: 0", -- glasspane "g: 64: 9", -- woodendoorblock "h:128: 7", -- sandstonestairs "i: 50: 3", -- torch "j: 50: 4", -- torch "k:128: 6", -- sandstonestairs "l:128: 3", -- sandstonestairs "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "mmmmmaaammmmm", -- 0 "maaaaaaaaaaam", -- 1 "maaaaaaaaaaam", -- 2 "maaaaaaaaaaam", -- 3 "maaaaaaaaaaam", -- 4 "maaaaaaaaaaam", -- 5 "maaaaaaaaaaam", -- 6 "maaaaaaaaaaam", -- 7 "mmmmmmmmmmmmm", -- 8 -- Level 1 ".....bcd.....", -- 0 ".aaaaaaaaaaa.", -- 1 ".aaaaaaaaaaa.", -- 2 ".aaaaaaaaaaa.", -- 3 ".aaaaaaaaaaa.", -- 4 ".aaaaaaaaaaa.", -- 5 ".aaaaaaaaaaa.", -- 6 ".aaaaaaaaaaa.", -- 7 ".............", -- 8 -- Level 2 ".............", -- 0 ".aaaaaeaaaaa.", -- 1 ".a.........a.", -- 2 ".a.........a.", -- 3 ".a.........a.", -- 4 ".a.........a.", -- 5 ".a.........a.", -- 6 ".aaaaaaaaaaa.", -- 7 ".............", -- 8 -- Level 3 ".............", -- 0 ".afffagafffa.", -- 1 ".f.........f.", -- 2 ".f.........f.", -- 3 ".a.........a.", -- 4 ".f.........f.", -- 5 ".f.........f.", -- 6 ".affaffafffa.", -- 7 ".............", -- 8 -- Level 4 "ccccccccccccc", -- 0 "haaaaaaaaaaah", -- 1 ".a...i.i...a.", -- 2 ".a.........a.", -- 3 ".a.........a.", -- 4 ".a.........a.", -- 5 ".a..j..j...a.", -- 6 "kaaaaaaaaaaak", -- 7 "lllllllllllll", -- 8 -- Level 5 ".............", -- 0 "ccccccccccccc", -- 1 "haaaaaaaaaaah", -- 2 ".a.........a.", -- 3 ".a.........a.", -- 4 ".a.........a.", -- 5 "kaaaaaaaaaaak", -- 6 "lllllllllllll", -- 7 ".............", -- 8 -- Level 6 ".............", -- 0 ".............", -- 1 "ccccccccccccc", -- 2 "haaaaaaaaaaah", -- 3 ".a.........a.", -- 4 "kaaaaaaaaaaak", -- 5 "lllllllllllll", -- 6 ".............", -- 7 ".............", -- 8 -- Level 7 ".............", -- 0 ".............", -- 1 ".............", -- 2 "ccccccccccccc", -- 3 "aaaaaaaaaaaaa", -- 4 "lllllllllllll", -- 5 ".............", -- 6 ".............", -- 7 ".............", -- 8 }, }, -- House13x9 { OriginData = { ExportName = "House15x9", Name = "Desert 13", GalleryName = "Desert", GalleryIndex = "13", ID = "118", CreatorName = "xoft", }, Size = { x = 15, y = 8, z = 9, }, Hitbox = { MinX = -1, MinY = 0, MinZ = 0, MaxX = 15, MaxY = 7, MaxZ = 9, }, Connectors = { { Type = -1, RelX = 6, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 24: 0", -- sandstone "b:128: 0", -- sandstonestairs "c:128: 2", -- sandstonestairs "d:128: 1", -- sandstonestairs "e: 64: 3", -- woodendoorblock "f:102: 0", -- glasspane "g: 64: 9", -- woodendoorblock "h:128: 7", -- sandstonestairs "i: 50: 3", -- torch "j: 50: 4", -- torch "k:128: 6", -- sandstonestairs "l:128: 3", -- sandstonestairs "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "mmmmmaaammmmmmm", -- 0 "maaaaaaaaaaaaam", -- 1 "maaaaaaaaaaaaam", -- 2 "maaaaaaaaaaaaam", -- 3 "maaaaaaaaaaaaam", -- 4 "maaaaaaaaaaaaam", -- 5 "maaaaaaaaaaaaam", -- 6 "maaaaaaaaaaaaam", -- 7 "mmmmmmmmmmmmmmm", -- 8 -- Level 1 ".....bcd.......", -- 0 ".aaaaaaaaaaaaa.", -- 1 ".aaaaaaaaaaaaa.", -- 2 ".aaaaaaaaaaaaa.", -- 3 ".aaaaaaaaaaaaa.", -- 4 ".aaaaaaaaaaaaa.", -- 5 ".aaaaaaaaaaaaa.", -- 6 ".aaaaaaaaaaaaa.", -- 7 "...............", -- 8 -- Level 2 "...............", -- 0 ".aaaaaeaaaaaaa.", -- 1 ".a...........a.", -- 2 ".a...........a.", -- 3 ".a...........a.", -- 4 ".a...........a.", -- 5 ".a...........a.", -- 6 ".aaaaaaaaaaaaa.", -- 7 "...............", -- 8 -- Level 3 "...............", -- 0 ".afffagaffaffa.", -- 1 ".f...........f.", -- 2 ".f...........f.", -- 3 ".a...........a.", -- 4 ".f...........f.", -- 5 ".f...........f.", -- 6 ".affaffaffaffa.", -- 7 "...............", -- 8 -- Level 4 "ccccccccccccccc", -- 0 "haaaaaaaaaaaaah", -- 1 ".a...i.i..i..a.", -- 2 ".a...........a.", -- 3 ".a...........a.", -- 4 ".a...........a.", -- 5 ".a..j..j..j..a.", -- 6 "kaaaaaaaaaaaaak", -- 7 "lllllllllllllll", -- 8 -- Level 5 "...............", -- 0 "ccccccccccccccc", -- 1 "haaaaaaaaaaaaah", -- 2 ".a...........a.", -- 3 ".a...........a.", -- 4 ".a...........a.", -- 5 "kaaaaaaaaaaaaak", -- 6 "lllllllllllllll", -- 7 "...............", -- 8 -- Level 6 "...............", -- 0 "...............", -- 1 "ccccccccccccccc", -- 2 "haaaaaaaaaaaaah", -- 3 ".a...........a.", -- 4 "kaaaaaaaaaaaaak", -- 5 "lllllllllllllll", -- 6 "...............", -- 7 "...............", -- 8 -- Level 7 "...............", -- 0 "...............", -- 1 "...............", -- 2 "ccccccccccccccc", -- 3 "aaaaaaaaaaaaaaa", -- 4 "lllllllllllllll", -- 5 "...............", -- 6 "...............", -- 7 "...............", -- 8 }, }, -- House15x9 { OriginData = { ExportName = "HouseL14x12", Name = "Desert 14", GalleryName = "Desert", GalleryIndex = "14", ID = "124", CreatorName = "Aloe_vera", }, Size = { x = 14, y = 8, z = 12, }, Hitbox = { MinX = -1, MinY = 0, MinZ = 0, MaxX = 14, MaxY = 7, MaxZ = 12, }, Connectors = { { Type = -1, RelX = 5, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 24: 0", -- sandstone "b:128: 0", -- sandstonestairs "c:128: 2", -- sandstonestairs "d:128: 1", -- sandstonestairs "e:128: 3", -- sandstonestairs "f: 64: 3", -- woodendoorblock "g: 64: 1", -- woodendoorblock "h:102: 0", -- glasspane "i: 64: 9", -- woodendoorblock "j: 64: 8", -- woodendoorblock "k:128: 7", -- sandstonestairs "l: 50: 3", -- torch "m: 19: 0", -- sponge "n: 50: 2", -- torch "o: 50: 4", -- torch "p:128: 6", -- sandstonestairs "q: 50: 1", -- torch "r:128: 5", -- sandstonestairs "s:128: 4", -- sandstonestairs }, BlockData = { -- Level 0 "mmmmaaammmmmmm", -- 0 "maaaaaaaaaaaam", -- 1 "maaaaaaaaaaaam", -- 2 "maaaaaaaaaaaam", -- 3 "maaaaaaaaaaaam", -- 4 "maaaaaaaaaaaam", -- 5 "maaaaaaaaaaaam", -- 6 "maaaaaaaaaaaam", -- 7 "mmmmaaaaaaaaam", -- 8 "mmmmmmaaaaaaam", -- 9 "mmmmmmaaaaaaam", -- 10 "mmmmmmmmmmmmmm", -- 11 -- Level 1 "....bcd.......", -- 0 ".aaaaaaaaaaaa.", -- 1 ".aaaaaaaaaaaa.", -- 2 ".aaaaaaaaaaaa.", -- 3 ".aaaaaaaaaaaa.", -- 4 ".aaaaaaaaaaaa.", -- 5 ".aaaaaaaaaaaa.", -- 6 ".aaaaaaaaaaaa.", -- 7 "....beaaaaaaa.", -- 8 "mmmmm.aaaaaaa.", -- 9 "mmmmm.aaaaaaa.", -- 10 "mmmmm.........", -- 11 -- Level 2 "..............", -- 0 ".aaaafaaaaaaa.", -- 1 ".a..........a.", -- 2 ".a..........a.", -- 3 ".a..........a.", -- 4 ".a..........a.", -- 5 ".a..........a.", -- 6 ".aaaaga.....a.", -- 7 "......a.....a.", -- 8 "mmmmm.a.....a.", -- 9 "mmmmm.aaaaaaa.", -- 10 "mmmmm.........", -- 11 -- Level 3 "..............", -- 0 ".ahhaiahhahha.", -- 1 ".h..........h.", -- 2 ".h..........h.", -- 3 ".a..........a.", -- 4 ".h..........h.", -- 5 ".h..........h.", -- 6 ".ahhaja.....a.", -- 7 "......h.....h.", -- 8 "mmmmm.h.....h.", -- 9 "mmmmm.ahhahha.", -- 10 "mmmmm.........", -- 11 -- Level 4 "cccccccccccccc", -- 0 "kaaaaaaaaaaaad", -- 1 ".a..l.l.....ad", -- 2 ".a..........ad", -- 3 ".a.........nad", -- 4 ".a..........ad", -- 5 ".a..o.o.....ad", -- 6 "paaaaaaq...nad", -- 7 "eeeeeba.....ad", -- 8 "mmmmmba.....ad", -- 9 "mmmmmbaaaaaaad", -- 10 "mmmmmbr.....sd", -- 11 -- Level 5 "..............", -- 0 "ccccccccccccd.", -- 1 "kaaaaaaaaaaad.", -- 2 ".a.........ad.", -- 3 ".a.........ad.", -- 4 ".a.........ad.", -- 5 "paaaaaaa...ad.", -- 6 "eeeeeeba...ad.", -- 7 "......ba...ad.", -- 8 "mmmmm.ba...ad.", -- 9 "mmmmm.baaaaad.", -- 10 "mmmmm.br...sd.", -- 11 -- Level 6 "..............", -- 0 "..............", -- 1 "cccccccccccc..", -- 2 "kaaaaaaaaaad..", -- 3 ".a........ad..", -- 4 "paaaaaaaa.ad..", -- 5 "eeeeeeeea.ad..", -- 6 ".......ba.ad..", -- 7 ".......ba.ad..", -- 8 "mmmmm..ba.ad..", -- 9 "mmmmm..baaad..", -- 10 "mmmmm..br.sd..", -- 11 -- Level 7 "..............", -- 0 "..............", -- 1 "..............", -- 2 "ccccccccccc...", -- 3 "aaaaaaaaaad...", -- 4 "eeeeeeeebad...", -- 5 "........bad...", -- 6 "........bad...", -- 7 "........bad...", -- 8 "mmmmm...bad...", -- 9 "mmmmm...bad...", -- 10 "mmmmm...bad...", -- 11 }, }, -- HouseL14x12 { OriginData = { ExportName = "House13x7", Name = "Desert 15", GalleryName = "Desert", GalleryIndex = "15", ID = "125", CreatorName = "Aloe_vera", }, Size = { x = 13, y = 7, z = 7, }, Hitbox = { MinX = -1, MinY = 0, MinZ = 0, MaxX = 13, MaxY = 6, MaxZ = 7, }, Connectors = { { Type = -1, RelX = 6, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 24: 0", -- sandstone "b:128: 0", -- sandstonestairs "c:128: 2", -- sandstonestairs "d:128: 1", -- sandstonestairs "e: 64: 3", -- woodendoorblock "f:102: 0", -- glasspane "g: 64: 9", -- woodendoorblock "h:128: 7", -- sandstonestairs "i: 50: 3", -- torch "j: 50: 4", -- torch "k:128: 6", -- sandstonestairs "l:128: 3", -- sandstonestairs "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "mmmmmaaammmmm", -- 0 "maaaaaaaaaaam", -- 1 "maaaaaaaaaaam", -- 2 "maaaaaaaaaaam", -- 3 "maaaaaaaaaaam", -- 4 "maaaaaaaaaaam", -- 5 "mmmmmmmmmmmmm", -- 6 -- Level 1 ".....bcd.....", -- 0 ".aaaaaaaaaaa.", -- 1 ".aaaaaaaaaaa.", -- 2 ".aaaaaaaaaaa.", -- 3 ".aaaaaaaaaaa.", -- 4 ".aaaaaaaaaaa.", -- 5 ".............", -- 6 -- Level 2 ".............", -- 0 ".aaaaaeaaaaa.", -- 1 ".a.........a.", -- 2 ".a.........a.", -- 3 ".a.........a.", -- 4 ".aaaaaaaaaaa.", -- 5 ".............", -- 6 -- Level 3 ".............", -- 0 ".afffagafffa.", -- 1 ".f.........f.", -- 2 ".f.........f.", -- 3 ".f.........f.", -- 4 ".affafffaffa.", -- 5 ".............", -- 6 -- Level 4 "ccccccccccccc", -- 0 "haaaaaaaaaaah", -- 1 ".a...i.i...a.", -- 2 ".a.........a.", -- 3 ".a..j...j..a.", -- 4 "kaaaaaaaaaaak", -- 5 "lllllllllllll", -- 6 -- Level 5 ".............", -- 0 "ccccccccccccc", -- 1 "haaaaaaaaaaah", -- 2 ".a.........a.", -- 3 "kaaaaaaaaaaak", -- 4 "lllllllllllll", -- 5 ".............", -- 6 -- Level 6 ".............", -- 0 ".............", -- 1 "ccccccccccccc", -- 2 "aaaaaaaaaaaaa", -- 3 "lllllllllllll", -- 4 ".............", -- 5 ".............", -- 6 }, }, -- House13x7 { OriginData = { ExportName = "House16x9", Name = "Desert 16", GalleryName = "Desert", GalleryIndex = "16", ID = "126", CreatorName = "Aloe_vera", }, Size = { x = 16, y = 8, z = 9, }, Hitbox = { MinX = -1, MinY = 0, MinZ = 0, MaxX = 16, MaxY = 7, MaxZ = 9, }, Connectors = { { Type = -1, RelX = 9, RelY = 1, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 24: 0", -- sandstone "b:128: 0", -- sandstonestairs "c:128: 2", -- sandstonestairs "d:128: 1", -- sandstonestairs "e: 64: 3", -- woodendoorblock "f:102: 0", -- glasspane "g: 64: 9", -- woodendoorblock "h:128: 7", -- sandstonestairs "i: 50: 3", -- torch "j: 50: 4", -- torch "k:128: 6", -- sandstonestairs "l:128: 3", -- sandstonestairs "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "mmmmmmmmaaammmmm", -- 0 "maaaaaaaaaaaaaam", -- 1 "maaaaaaaaaaaaaam", -- 2 "maaaaaaaaaaaaaam", -- 3 "maaaaaaaaaaaaaam", -- 4 "maaaaaaaaaaaaaam", -- 5 "maaaaaaaaaaaaaam", -- 6 "maaaaaaaaaaaaaam", -- 7 "mmmmmmmmmmmmmmmm", -- 8 -- Level 1 "........bcd.....", -- 0 ".aaaaaaaaaaaaaa.", -- 1 ".aaaaaaaaaaaaaa.", -- 2 ".aaaaaaaaaaaaaa.", -- 3 ".aaaaaaaaaaaaaa.", -- 4 ".aaaaaaaaaaaaaa.", -- 5 ".aaaaaaaaaaaaaa.", -- 6 ".aaaaaaaaaaaaaa.", -- 7 "................", -- 8 -- Level 2 "................", -- 0 ".aaaaaaaaeaaaaa.", -- 1 ".a............a.", -- 2 ".a............a.", -- 3 ".a............a.", -- 4 ".a............a.", -- 5 ".a............a.", -- 6 ".aaaaaaaaaaaaaa.", -- 7 "................", -- 8 -- Level 3 "................", -- 0 ".affafffagafffa.", -- 1 ".f............f.", -- 2 ".f............f.", -- 3 ".a............a.", -- 4 ".f............f.", -- 5 ".f............f.", -- 6 ".affaffafffaffa.", -- 7 "................", -- 8 -- Level 4 "cccccccccccccccc", -- 0 "haaaaaaaaaaaaaah", -- 1 ".a..i...i.i...a.", -- 2 ".a............a.", -- 3 ".a............a.", -- 4 ".a............a.", -- 5 ".a..j..j...j..a.", -- 6 "kaaaaaaaaaaaaaak", -- 7 "llllllllllllllll", -- 8 -- Level 5 "................", -- 0 "cccccccccccccccc", -- 1 "haaaaaaaaaaaaaah", -- 2 ".a............a.", -- 3 ".a............a.", -- 4 ".a............a.", -- 5 "kaaaaaaaaaaaaaak", -- 6 "llllllllllllllll", -- 7 "................", -- 8 -- Level 6 "................", -- 0 "................", -- 1 "cccccccccccccccc", -- 2 "haaaaaaaaaaaaaah", -- 3 ".a............a.", -- 4 "kaaaaaaaaaaaaaak", -- 5 "llllllllllllllll", -- 6 "................", -- 7 "................", -- 8 -- Level 7 "................", -- 0 "................", -- 1 "................", -- 2 "cccccccccccccccc", -- 3 "aaaaaaaaaaaaaaaa", -- 4 "llllllllllllllll", -- 5 "................", -- 6 "................", -- 7 "................", -- 8 }, }, -- House16x9 { OriginData = { ExportName = "SingleField", Name = "Desert 17", GalleryName = "Desert", GalleryIndex = "17", ID = "127", CreatorName = "Aloe_vera", }, Size = { x = 10, y = 3, z = 7, }, Hitbox = { MinX = 0, MinY = 0, MinZ = -1, MaxX = 10, MaxY = 2, MaxZ = 7, }, Connectors = { { Type = -1, RelX = 0, RelY = 1, RelZ = 3, Direction = 4, -- X- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "0", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", }, BlockDefinitions = { ".: 0: 0", -- air "a: 24: 0", -- sandstone "b: 60: 5", -- tilleddirt "c: 60: 7", -- tilleddirt "d: 60: 6", -- tilleddirt "e: 8: 0", -- water "f: 50: 5", -- torch "g: 59: 7", -- wheatblock "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "aaaaaaaaaa", -- 0 "aaaaaaaaaa", -- 1 "aaaaaaaaaa", -- 2 "aaaaaaaaaa", -- 3 "aaaaaaaaaa", -- 4 "aaaaaaaaaa", -- 5 "aaaaaaaaaa", -- 6 -- Level 1 "aaaaaaaaaa", -- 0 "abccdcccca", -- 1 "acccccccca", -- 2 "aeeeeeeeea", -- 3 "acccccccca", -- 4 "acdcdcccca", -- 5 "aaaaaaaaaa", -- 6 -- Level 2 "f........f", -- 0 ".gggggggg.", -- 1 ".gggggggg.", -- 2 "..........", -- 3 ".gggggggg.", -- 4 ".gggggggg.", -- 5 "f........f", -- 6 }, }, -- SingleField { OriginData = { ExportName = "RoofedWell", Name = "Desert 43", GalleryName = "Desert", GalleryIndex = "43", ID = "274", CreatorName = "Aloe_vera", }, Size = { x = 7, y = 14, z = 7, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 6, MaxY = 13, MaxZ = 6, }, Connectors = { { Type = 2, RelX = 6, RelY = 8, RelZ = 3, Direction = 5, -- X+ }, { Type = 2, RelX = 3, RelY = 8, RelZ = 6, Direction = 3, -- Z+ }, { Type = 2, RelX = 0, RelY = 8, RelZ = 3, Direction = 4, -- X- }, { Type = 2, RelX = 3, RelY = 8, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["AddWeightIfSame"] = "0", ["AllowedRotations"] = "7", ["DefaultWeight"] = "100", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "RepeatBottomTillSolid", ["IsStarting"] = "1", ["MergeStrategy"] = "msSpongePrint", ["MoveToGround"] = "1", ["VerticalStrategy"] = "TerrainOrOceanTop|-8", }, BlockDefinitions = { ".: 0: 0", -- air "a: 1: 0", -- stone "b: 24: 0", -- sandstone "c: 8: 0", -- water "d: 12: 0", -- sand "e: 4: 0", -- cobblestone "f: 13: 0", -- gravel "g:118: 3", -- cauldronblock "h: 85: 0", -- fence "i:128: 2", -- sandstonestairs "j:128: 7", -- sandstonestairs "k:128: 4", -- sandstonestairs "l:128: 5", -- sandstonestairs "m: 19: 0", -- sponge "n:128: 6", -- sandstonestairs "o:128: 3", -- sandstonestairs }, BlockData = { -- Level 0 "aaaaaaa", -- 0 "aaaaaaa", -- 1 "aaaaaaa", -- 2 "aaaaaaa", -- 3 "aaaaaaa", -- 4 "aaaaaaa", -- 5 "aaaaaaa", -- 6 -- Level 1 "aaaaaaa", -- 0 "abbbbba", -- 1 "abcccba", -- 2 "abcccba", -- 3 "abcccba", -- 4 "abbbbba", -- 5 "aaaaaaa", -- 6 -- Level 2 "aaaaaaa", -- 0 "abbbbba", -- 1 "abcccba", -- 2 "abcccba", -- 3 "abcccba", -- 4 "abbbbba", -- 5 "aaaaaaa", -- 6 -- Level 3 "aaaaaaa", -- 0 "abbbbba", -- 1 "abcccba", -- 2 "abcccba", -- 3 "abcccba", -- 4 "abbbbba", -- 5 "aaaaaaa", -- 6 -- Level 4 "ddddddd", -- 0 "dbbbbbd", -- 1 "dbcccbd", -- 2 "dbcccbd", -- 3 "dbcccbd", -- 4 "dbbbbbd", -- 5 "ddddddd", -- 6 -- Level 5 "ddddddd", -- 0 "dbbbbbd", -- 1 "dbcccbd", -- 2 "dbcccbd", -- 3 "dbcccbd", -- 4 "dbbbbbd", -- 5 "ddddddd", -- 6 -- Level 6 "ddeeedd", -- 0 "dbbbbbd", -- 1 "ebcccbe", -- 2 "ebcccbe", -- 3 "ebcccbe", -- 4 "dbbbbbd", -- 5 "ddeeedd", -- 6 -- Level 7 "ddfffdd", -- 0 "dbbbbbd", -- 1 "fbcccbf", -- 2 "fbcccbf", -- 3 "fbcccbf", -- 4 "dbbbbbd", -- 5 "ddfffdd", -- 6 -- Level 8 ".......", -- 0 ".bbbbb.", -- 1 ".b...b.", -- 2 ".b.g.b.", -- 3 ".b...b.", -- 4 ".bbbbb.", -- 5 ".......", -- 6 -- Level 9 ".......", -- 0 ".h...h.", -- 1 ".......", -- 2 "...h...", -- 3 ".......", -- 4 ".h...h.", -- 5 ".......", -- 6 -- Level 10 ".......", -- 0 ".h...h.", -- 1 ".......", -- 2 "...h...", -- 3 ".......", -- 4 ".h...h.", -- 5 ".......", -- 6 -- Level 11 "iiiiiii", -- 0 "jbjjjbj", -- 1 ".k...l.", -- 2 ".k.h.l.", -- 3 ".k...l.", -- 4 "nbnnnbn", -- 5 "ooooooo", -- 6 -- Level 12 ".......", -- 0 "iiiiiii", -- 1 "jb...bj", -- 2 ".b.h.b.", -- 3 "nb...bn", -- 4 "ooooooo", -- 5 ".......", -- 6 -- Level 13 ".......", -- 0 ".......", -- 1 "iiiiiii", -- 2 "bbbbbbb", -- 3 "ooooooo", -- 4 ".......", -- 5 ".......", -- 6 }, }, -- RoofedWell }, -- Pieces } ================================================ FILE: Server/Protocol/1.12.2/base.recipes.txt ================================================ # recipeId minecraftName 11 yellow_wool 12 yellow_terracotta 13 yellow_stained_glass_pane 14 yellow_stained_glass 15 yellow_dye_from_sunflower 16 yellow_dye_from_dandelion 17 yellow_concrete_powder 18 yellow_carpet 19 yellow_bed_from_white_bed 20 yellow_bed 21 yellow_banner 22 writable_book 23 wooden_sword 24 wooden_shovel 25 wooden_pressure_plate 26 wooden_pickaxe 27 wooden_hoe 28 oak_door 29 oak_button 30 wooden_axe 31 white_terracotta 32 white_stained_glass_pane 33 white_stained_glass 34 white_concrete_powder 35 white_carpet 36 white_bed 37 white_banner 38 wheat 39 tripwire_hook 40 trapped_chest 41 oak_trapdoor 42 torch 43 tnt_minecart 44 tnt 45 sugar 46 white_wool_from_string 47 stone_bricks 48 stone_sword 49 stone_stairs 50 stone_slab 51 stone_shovel 52 stone_pressure_plate 53 stone_pickaxe 54 stone_hoe 55 stone_button 56 stone_brick_stairs 57 stone_brick_slab 58 stone_axe 59 sticky_piston 60 stick 61 spruce_slab 62 spruce_stairs 63 spruce_planks 64 spruce_fence_gate 65 spruce_fence 66 spruce_door 67 spruce_boat 68 spectral_arrow 69 glistering_melon_slice 70 snow 71 snow_block 72 smooth_sandstone 73 smooth_red_sandstone 74 slime_ball 75 slime_block 76 oak_sign 77 shield 78 shears 79 sea_lantern 80 sandstone_stairs 81 sandstone_slab 82 sandstone 83 repeater 84 redstone_torch 85 redstone_lamp 86 redstone_block 87 redstone 88 red_wool 89 red_terracotta 90 red_stained_glass_pane 91 red_stained_glass 92 red_sandstone_stairs 93 red_sandstone_slab 94 red_sandstone 95 red_nether_bricks 96 red_dye_from_tulip 97 red_dye_from_rose_bush 98 red_dye_from_poppy 99 red_dye_from_beetroot 100 red_concrete_powder 101 red_carpet 102 red_bed_from_white_bed 103 red_bed 104 red_banner 105 rail 106 rabbit_stew_from_red_mushroom 107 rabbit_stew_from_brown_mushroom 108 quartz_stairs 109 quartz_slab 110 quartz_block 111 purpur_stairs 112 purpur_slab 113 purpur_pillar 114 purpur_block 115 purple_wool 116 purple_terracotta 117 purple_stained_glass_pane 118 purple_stained_glass 119 purpur_shulker_box 120 purple_dye 121 purple_concrete_powder 122 purple_carpet 123 purple_bed_from_white_bed 124 purple_bed 125 purple_banner 126 pumpkin_seeds 127 pumpkin_pie 128 prismarine_bricks 129 prismarine 130 polished_granite 131 polished_diorite 132 polished_andesite 133 piston 134 pink_wool 135 pink_terracotta 136 pink_stained_glass_pane 137 pink_stained_glass 138 pink_dye_from_red_white_dye 139 pink_tulip 140 peony 141 pink_concrete_powder 142 pink_carpet 143 pink_bed_from_white_bed 144 pink_bed 145 pink_banner 146 quartz_pillar 147 paper 148 painting 149 orange_wool 150 orange_terracotta 151 orange_stained_glass_pane 152 orange_stained_glass 153 orange_dye_from_red_yellow 154 orange_dye_from_orange_tulip 155 orange_concrete_powder 156 orange_carpet 157 orange_bed_from_white_bed 158 orange_bed 159 orange_banner 160 observer 161 oak_slab 162 oak_stairs 163 oak_planks 164 note_block 165 nether_wart_block 166 nether_brick_stairs 167 nether_brick_slab 168 nether_brick_fence 169 nether_bricks 170 mushroom_stew 171 mossy_stone_bricks 172 mossy_cobblestone_wall 173 mossy_cobblestone 174 minecart 175 melon_seeds 176 melon 177 map 178 magma_cream 179 magma_block 180 magenta_wool 181 magenta_terracotta 182 magenta_stained_glass_pane 183 magenta_stained_glass 184 magenta_dye_from_purple_and_pink 185 magenta_dye_from_lilac 186 magenta_dye_from_blue_red_pink 187 magenta_dye_from_blue_red_white_dye 188 magenta_dye_from_allium 189 magenta_concrete_powder 190 magenta_carpet 191 magenta_bed_from_white_bed 192 magenta_bed 193 magenta_banner 194 jack_o_lantern 195 lime_wool 196 lime_terracotta 197 lime_stained_glass_pane 198 lime_stained_glass 199 lime_dye 200 lime_concrete_powder 201 lime_carpet 202 lime_bed_from_white_bed 203 lime_bed 204 lime_banner 205 light_weighted_pressure_plate 206 light_gray_wool 207 light_gray_terracotta 208 light_gray_stained_glass_pane 209 light_gray_stained_glass 210 light_gray_dye_from_white_tulip 211 light_gray_dye_from_oxeye_daisy 212 light_gray_dye_from_gray_white_dye 213 light_gray_dye_from_black_white_dye 214 light_gray_dye_from_azure_bluet 215 light_gray_concrete_powder 216 light_gray_carpet 217 light_gray_bed_from_white_bed 218 light_gray_bed 219 light_gray_banner 220 light_blue_wool 221 light_blue_terracotta 222 light_blue_stained_glass_pane 223 light_blue_stained_glass 224 light_blue_dye_from_blue_white_dye 225 light_blue_dye_from_blue_orchid 226 light_blue_concrete_powder 227 light_blue_carpet 228 light_blue_bed_from_white_bed 229 light_blue_bed 230 light_blue_banner 231 lever 232 leather_leggings 233 leather_helmet 234 leather_chestplate 235 leather_boots 236 leather 237 lead 238 lapis_lazuli 239 lapis_block 240 ladder 241 jungle_slab 242 jungle_stairs 243 jungle_planks 244 jungle_fence_gate 245 jungle_fence 246 jungle_door 247 jungle_boat 248 jukebox 249 item_frame 250 iron_trapdoor 251 iron_sword 252 iron_shovel 253 iron_pickaxe 254 iron_nugget 255 iron_leggings 256 iron_ingot_from_iron_block 257 iron_ingot_from_nuggets 258 iron_hoe 259 iron_helmet 260 iron_door 261 iron_chestplate 262 iron_boots 263 iron_block 264 iron_bars 265 iron_axe 266 hopper_minecart 267 hopper 268 heavy_weighted_pressure_plate 269 hay_block 270 green_wool 271 green_terracotta 272 green_stained_glass_pane 273 green_stained_glass 274 green_concrete_powder 275 green_carpet 276 green_bed_from_white_bed 277 green_bed 278 green_banner 279 gray_wool 280 gray_terracotta 281 gray_stained_glass_pane 282 gray_stained_glass 283 gray_dye 284 gray_concrete_powder 285 gray_carpet 286 gray_bed_from_white_bed 287 gray_bed 288 gray_banner 289 granite 290 golden_sword 291 golden_shovel 292 powered_rail 293 golden_pickaxe 294 golden_leggings 295 golden_hoe 296 golden_helmet 297 golden_chestplate 298 golden_carrot 299 golden_boots 300 golden_axe 301 golden_apple 302 gold_nugget 303 gold_ingot_from_gold_block 304 gold_ingot 305 gold_block 306 glowstone 307 glass_pane 308 glass_bottle 309 furnace_minecart 310 furnace 311 flower_pot 312 flint_and_steel 313 fishing_rod 314 fire_charge 315 fermented_spider_eye 316 oak_fence_gate 317 oak_fence 318 ender_eye 319 ender_chest 320 end_rod 321 end_crystal 322 end_stone_bricks 323 enchanting_table 324 emerald_block 325 emerald 326 dropper 327 dispenser 328 diorite 329 diamond_sword 330 diamond_shovel 331 diamond_pickaxe 332 diamond_leggings 333 diamond_hoe 334 diamond_helmet 335 diamond_chestplate 336 diamond_boots 337 diamond_block 338 diamond_axe 339 diamond 340 detector_rail 341 daylight_detector 342 dark_prismarine 343 dark_oak_slab 344 dark_oak_stairs 345 dark_oak_planks 346 dark_oak_fence_gate 347 dark_oak_fence 348 dark_oak_door 349 dark_oak_boat 350 cyan_wool 351 cyan_terracotta 352 cyan_stained_glass_pane 353 cyan_stained_glass 354 cyan_dye 355 cyan_concrete_powder 356 cyan_carpet 357 cyan_bed_from_white_bed 358 cyan_bed 359 cyan_banner 360 crafting_table 361 cookie 362 compass 363 comparator 364 cobblestone_wall 365 cobblestone_slab 366 coarse_dirt 367 coal_block 368 coal 369 clock 370 clay 371 chiseled_stone_bricks 372 chiseled_sandstone 373 chiseled_red_sandstone 374 chiseled_quartz_block 375 chest_minecart 376 chest 377 cauldron 378 carrot_on_a_stick 379 cake 380 bucket 381 brown_wool 382 brown_terracotta 383 brown_stained_glass_pane 384 brown_stained_glass 385 brown_concrete_powder 386 brown_carpet 387 brown_bed_from_white_bed 388 brown_bed 389 brown_banner 390 brick_stairs 391 brick_slab 392 bricks 393 brewing_stand 394 bread 395 bowl 396 bow 397 bookshelf 398 book 399 bone_meal 400 bone_meal_from_bone_block 401 bone_block 402 oak_boat 403 blue_wool 404 blue_terracotta 405 blue_stained_glass_pane 406 blue_stained_glass 407 blue_concrete_powder 408 blue_carpet 409 blue_bed_from_white_bed 410 blue_bed 411 blue_banner 412 blaze_powder 413 black_wool 414 black_terracotta 415 black_stained_glass_pane 416 black_stained_glass 417 black_concrete_powder 418 black_carpet 419 black_bed_from_white_bed 420 black_bed 421 black_banner 422 birch_slab 423 birch_stairs 424 birch_planks 425 birch_fence_gate 426 birch_fence 427 birch_door 428 birch_boat 429 beetroot_soup 430 beacon 431 arrow 432 armor_stand 433 anvil 434 andesite 435 activator_rail 436 acacia_slab 437 acacia_stairs 438 acacia_planks 439 acacia_fence_gate 440 acacia_fence 441 acacia_door 442 acacia_boat ================================================ FILE: Server/Protocol/1.13/base.btp.txt ================================================ BlockTypePalette FileVersion 1 CommonPrefix minecraft: 0 air 1 stone 2 granite 3 polished_granite 4 diorite 5 polished_diorite 6 andesite 7 polished_andesite 8 grass_block snowy true 9 grass_block snowy false 10 dirt 11 coarse_dirt 12 podzol snowy true 13 podzol snowy false 14 cobblestone 15 oak_planks 16 spruce_planks 17 birch_planks 18 jungle_planks 19 acacia_planks 20 dark_oak_planks 21 oak_sapling stage 0 22 oak_sapling stage 1 23 spruce_sapling stage 0 24 spruce_sapling stage 1 25 birch_sapling stage 0 26 birch_sapling stage 1 27 jungle_sapling stage 0 28 jungle_sapling stage 1 29 acacia_sapling stage 0 30 acacia_sapling stage 1 31 dark_oak_sapling stage 0 32 dark_oak_sapling stage 1 33 bedrock 34 water level 0 35 water level 1 36 water level 2 37 water level 3 38 water level 4 39 water level 5 40 water level 6 41 water level 7 42 water level 8 43 water level 9 44 water level 10 45 water level 11 46 water level 12 47 water level 13 48 water level 14 49 water level 15 50 lava level 0 51 lava level 1 52 lava level 2 53 lava level 3 54 lava level 4 55 lava level 5 56 lava level 6 57 lava level 7 58 lava level 8 59 lava level 9 60 lava level 10 61 lava level 11 62 lava level 12 63 lava level 13 64 lava level 14 65 lava level 15 66 sand 67 red_sand 68 gravel 69 gold_ore 70 iron_ore 71 coal_ore 72 oak_log axis x 73 oak_log axis y 74 oak_log axis z 75 spruce_log axis x 76 spruce_log axis y 77 spruce_log axis z 78 birch_log axis x 79 birch_log axis y 80 birch_log axis z 81 jungle_log axis x 82 jungle_log axis y 83 jungle_log axis z 84 acacia_log axis x 85 acacia_log axis y 86 acacia_log axis z 87 dark_oak_log axis x 88 dark_oak_log axis y 89 dark_oak_log axis z 90 stripped_spruce_log axis x 91 stripped_spruce_log axis y 92 stripped_spruce_log axis z 93 stripped_birch_log axis x 94 stripped_birch_log axis y 95 stripped_birch_log axis z 96 stripped_jungle_log axis x 97 stripped_jungle_log axis y 98 stripped_jungle_log axis z 99 stripped_acacia_log axis x 100 stripped_acacia_log axis y 101 stripped_acacia_log axis z 102 stripped_dark_oak_log axis x 103 stripped_dark_oak_log axis y 104 stripped_dark_oak_log axis z 105 stripped_oak_log axis x 106 stripped_oak_log axis y 107 stripped_oak_log axis z 108 oak_wood axis x 109 oak_wood axis y 110 oak_wood axis z 111 spruce_wood axis x 112 spruce_wood axis y 113 spruce_wood axis z 114 birch_wood axis x 115 birch_wood axis y 116 birch_wood axis z 117 jungle_wood axis x 118 jungle_wood axis y 119 jungle_wood axis z 120 acacia_wood axis x 121 acacia_wood axis y 122 acacia_wood axis z 123 dark_oak_wood axis x 124 dark_oak_wood axis y 125 dark_oak_wood axis z 126 stripped_oak_wood axis x 127 stripped_oak_wood axis y 128 stripped_oak_wood axis z 129 stripped_spruce_wood axis x 130 stripped_spruce_wood axis y 131 stripped_spruce_wood axis z 132 stripped_birch_wood axis x 133 stripped_birch_wood axis y 134 stripped_birch_wood axis z 135 stripped_jungle_wood axis x 136 stripped_jungle_wood axis y 137 stripped_jungle_wood axis z 138 stripped_acacia_wood axis x 139 stripped_acacia_wood axis y 140 stripped_acacia_wood axis z 141 stripped_dark_oak_wood axis x 142 stripped_dark_oak_wood axis y 143 stripped_dark_oak_wood axis z 144 oak_leaves persistent true distance 1 145 oak_leaves persistent false distance 1 146 oak_leaves persistent true distance 2 147 oak_leaves persistent false distance 2 148 oak_leaves persistent true distance 3 149 oak_leaves persistent false distance 3 150 oak_leaves persistent true distance 4 151 oak_leaves persistent false distance 4 152 oak_leaves persistent true distance 5 153 oak_leaves persistent false distance 5 154 oak_leaves persistent true distance 6 155 oak_leaves persistent false distance 6 156 oak_leaves persistent true distance 7 157 oak_leaves persistent false distance 7 158 spruce_leaves persistent true distance 1 159 spruce_leaves persistent false distance 1 160 spruce_leaves persistent true distance 2 161 spruce_leaves persistent false distance 2 162 spruce_leaves persistent true distance 3 163 spruce_leaves persistent false distance 3 164 spruce_leaves persistent true distance 4 165 spruce_leaves persistent false distance 4 166 spruce_leaves persistent true distance 5 167 spruce_leaves persistent false distance 5 168 spruce_leaves persistent true distance 6 169 spruce_leaves persistent false distance 6 170 spruce_leaves persistent true distance 7 171 spruce_leaves persistent false distance 7 172 birch_leaves persistent true distance 1 173 birch_leaves persistent false distance 1 174 birch_leaves persistent true distance 2 175 birch_leaves persistent false distance 2 176 birch_leaves persistent true distance 3 177 birch_leaves persistent false distance 3 178 birch_leaves persistent true distance 4 179 birch_leaves persistent false distance 4 180 birch_leaves persistent true distance 5 181 birch_leaves persistent false distance 5 182 birch_leaves persistent true distance 6 183 birch_leaves persistent false distance 6 184 birch_leaves persistent true distance 7 185 birch_leaves persistent false distance 7 186 jungle_leaves persistent true distance 1 187 jungle_leaves persistent false distance 1 188 jungle_leaves persistent true distance 2 189 jungle_leaves persistent false distance 2 190 jungle_leaves persistent true distance 3 191 jungle_leaves persistent false distance 3 192 jungle_leaves persistent true distance 4 193 jungle_leaves persistent false distance 4 194 jungle_leaves persistent true distance 5 195 jungle_leaves persistent false distance 5 196 jungle_leaves persistent true distance 6 197 jungle_leaves persistent false distance 6 198 jungle_leaves persistent true distance 7 199 jungle_leaves persistent false distance 7 200 acacia_leaves persistent true distance 1 201 acacia_leaves persistent false distance 1 202 acacia_leaves persistent true distance 2 203 acacia_leaves persistent false distance 2 204 acacia_leaves persistent true distance 3 205 acacia_leaves persistent false distance 3 206 acacia_leaves persistent true distance 4 207 acacia_leaves persistent false distance 4 208 acacia_leaves persistent true distance 5 209 acacia_leaves persistent false distance 5 210 acacia_leaves persistent true distance 6 211 acacia_leaves persistent false distance 6 212 acacia_leaves persistent true distance 7 213 acacia_leaves persistent false distance 7 214 dark_oak_leaves persistent true distance 1 215 dark_oak_leaves persistent false distance 1 216 dark_oak_leaves persistent true distance 2 217 dark_oak_leaves persistent false distance 2 218 dark_oak_leaves persistent true distance 3 219 dark_oak_leaves persistent false distance 3 220 dark_oak_leaves persistent true distance 4 221 dark_oak_leaves persistent false distance 4 222 dark_oak_leaves persistent true distance 5 223 dark_oak_leaves persistent false distance 5 224 dark_oak_leaves persistent true distance 6 225 dark_oak_leaves persistent false distance 6 226 dark_oak_leaves persistent true distance 7 227 dark_oak_leaves persistent false distance 7 228 sponge 229 wet_sponge 230 glass 231 lapis_ore 232 lapis_block 233 dispenser facing north triggered true 234 dispenser facing north triggered false 235 dispenser facing east triggered true 236 dispenser facing east triggered false 237 dispenser facing south triggered true 238 dispenser facing south triggered false 239 dispenser facing west triggered true 240 dispenser facing west triggered false 241 dispenser facing up triggered true 242 dispenser facing up triggered false 243 dispenser facing down triggered true 244 dispenser facing down triggered false 245 sandstone 246 chiseled_sandstone 247 cut_sandstone 248 note_block instrument harp powered true note 0 249 note_block instrument harp powered false note 0 250 note_block instrument harp powered true note 1 251 note_block instrument harp powered false note 1 252 note_block instrument harp powered true note 2 253 note_block instrument harp powered false note 2 254 note_block instrument harp powered true note 3 255 note_block instrument harp powered false note 3 256 note_block instrument harp powered true note 4 257 note_block instrument harp powered false note 4 258 note_block instrument harp powered true note 5 259 note_block instrument harp powered false note 5 260 note_block instrument harp powered true note 6 261 note_block instrument harp powered false note 6 262 note_block instrument harp powered true note 7 263 note_block instrument harp powered false note 7 264 note_block instrument harp powered true note 8 265 note_block instrument harp powered false note 8 266 note_block instrument harp powered true note 9 267 note_block instrument harp powered false note 9 268 note_block instrument harp powered true note 10 269 note_block instrument harp powered false note 10 270 note_block instrument harp powered true note 11 271 note_block instrument harp powered false note 11 272 note_block instrument harp powered true note 12 273 note_block instrument harp powered false note 12 274 note_block instrument harp powered true note 13 275 note_block instrument harp powered false note 13 276 note_block instrument harp powered true note 14 277 note_block instrument harp powered false note 14 278 note_block instrument harp powered true note 15 279 note_block instrument harp powered false note 15 280 note_block instrument harp powered true note 16 281 note_block instrument harp powered false note 16 282 note_block instrument harp powered true note 17 283 note_block instrument harp powered false note 17 284 note_block instrument harp powered true note 18 285 note_block instrument harp powered false note 18 286 note_block instrument harp powered true note 19 287 note_block instrument harp powered false note 19 288 note_block instrument harp powered true note 20 289 note_block instrument harp powered false note 20 290 note_block instrument harp powered true note 21 291 note_block instrument harp powered false note 21 292 note_block instrument harp powered true note 22 293 note_block instrument harp powered false note 22 294 note_block instrument harp powered true note 23 295 note_block instrument harp powered false note 23 296 note_block instrument harp powered true note 24 297 note_block instrument harp powered false note 24 298 note_block instrument basedrum powered true note 0 299 note_block instrument basedrum powered false note 0 300 note_block instrument basedrum powered true note 1 301 note_block instrument basedrum powered false note 1 302 note_block instrument basedrum powered true note 2 303 note_block instrument basedrum powered false note 2 304 note_block instrument basedrum powered true note 3 305 note_block instrument basedrum powered false note 3 306 note_block instrument basedrum powered true note 4 307 note_block instrument basedrum powered false note 4 308 note_block instrument basedrum powered true note 5 309 note_block instrument basedrum powered false note 5 310 note_block instrument basedrum powered true note 6 311 note_block instrument basedrum powered false note 6 312 note_block instrument basedrum powered true note 7 313 note_block instrument basedrum powered false note 7 314 note_block instrument basedrum powered true note 8 315 note_block instrument basedrum powered false note 8 316 note_block instrument basedrum powered true note 9 317 note_block instrument basedrum powered false note 9 318 note_block instrument basedrum powered true note 10 319 note_block instrument basedrum powered false note 10 320 note_block instrument basedrum powered true note 11 321 note_block instrument basedrum powered false note 11 322 note_block instrument basedrum powered true note 12 323 note_block instrument basedrum powered false note 12 324 note_block instrument basedrum powered true note 13 325 note_block instrument basedrum powered false note 13 326 note_block instrument basedrum powered true note 14 327 note_block instrument basedrum powered false note 14 328 note_block instrument basedrum powered true note 15 329 note_block instrument basedrum powered false note 15 330 note_block instrument basedrum powered true note 16 331 note_block instrument basedrum powered false note 16 332 note_block instrument basedrum powered true note 17 333 note_block instrument basedrum powered false note 17 334 note_block instrument basedrum powered true note 18 335 note_block instrument basedrum powered false note 18 336 note_block instrument basedrum powered true note 19 337 note_block instrument basedrum powered false note 19 338 note_block instrument basedrum powered true note 20 339 note_block instrument basedrum powered false note 20 340 note_block instrument basedrum powered true note 21 341 note_block instrument basedrum powered false note 21 342 note_block instrument basedrum powered true note 22 343 note_block instrument basedrum powered false note 22 344 note_block instrument basedrum powered true note 23 345 note_block instrument basedrum powered false note 23 346 note_block instrument basedrum powered true note 24 347 note_block instrument basedrum powered false note 24 348 note_block instrument snare powered true note 0 349 note_block instrument snare powered false note 0 350 note_block instrument snare powered true note 1 351 note_block instrument snare powered false note 1 352 note_block instrument snare powered true note 2 353 note_block instrument snare powered false note 2 354 note_block instrument snare powered true note 3 355 note_block instrument snare powered false note 3 356 note_block instrument snare powered true note 4 357 note_block instrument snare powered false note 4 358 note_block instrument snare powered true note 5 359 note_block instrument snare powered false note 5 360 note_block instrument snare powered true note 6 361 note_block instrument snare powered false note 6 362 note_block instrument snare powered true note 7 363 note_block instrument snare powered false note 7 364 note_block instrument snare powered true note 8 365 note_block instrument snare powered false note 8 366 note_block instrument snare powered true note 9 367 note_block instrument snare powered false note 9 368 note_block instrument snare powered true note 10 369 note_block instrument snare powered false note 10 370 note_block instrument snare powered true note 11 371 note_block instrument snare powered false note 11 372 note_block instrument snare powered true note 12 373 note_block instrument snare powered false note 12 374 note_block instrument snare powered true note 13 375 note_block instrument snare powered false note 13 376 note_block instrument snare powered true note 14 377 note_block instrument snare powered false note 14 378 note_block instrument snare powered true note 15 379 note_block instrument snare powered false note 15 380 note_block instrument snare powered true note 16 381 note_block instrument snare powered false note 16 382 note_block instrument snare powered true note 17 383 note_block instrument snare powered false note 17 384 note_block instrument snare powered true note 18 385 note_block instrument snare powered false note 18 386 note_block instrument snare powered true note 19 387 note_block instrument snare powered false note 19 388 note_block instrument snare powered true note 20 389 note_block instrument snare powered false note 20 390 note_block instrument snare powered true note 21 391 note_block instrument snare powered false note 21 392 note_block instrument snare powered true note 22 393 note_block instrument snare powered false note 22 394 note_block instrument snare powered true note 23 395 note_block instrument snare powered false note 23 396 note_block instrument snare powered true note 24 397 note_block instrument snare powered false note 24 398 note_block instrument hat powered true note 0 399 note_block instrument hat powered false note 0 400 note_block instrument hat powered true note 1 401 note_block instrument hat powered false note 1 402 note_block instrument hat powered true note 2 403 note_block instrument hat powered false note 2 404 note_block instrument hat powered true note 3 405 note_block instrument hat powered false note 3 406 note_block instrument hat powered true note 4 407 note_block instrument hat powered false note 4 408 note_block instrument hat powered true note 5 409 note_block instrument hat powered false note 5 410 note_block instrument hat powered true note 6 411 note_block instrument hat powered false note 6 412 note_block instrument hat powered true note 7 413 note_block instrument hat powered false note 7 414 note_block instrument hat powered true note 8 415 note_block instrument hat powered false note 8 416 note_block instrument hat powered true note 9 417 note_block instrument hat powered false note 9 418 note_block instrument hat powered true note 10 419 note_block instrument hat powered false note 10 420 note_block instrument hat powered true note 11 421 note_block instrument hat powered false note 11 422 note_block instrument hat powered true note 12 423 note_block instrument hat powered false note 12 424 note_block instrument hat powered true note 13 425 note_block instrument hat powered false note 13 426 note_block instrument hat powered true note 14 427 note_block instrument hat powered false note 14 428 note_block instrument hat powered true note 15 429 note_block instrument hat powered false note 15 430 note_block instrument hat powered true note 16 431 note_block instrument hat powered false note 16 432 note_block instrument hat powered true note 17 433 note_block instrument hat powered false note 17 434 note_block instrument hat powered true note 18 435 note_block instrument hat powered false note 18 436 note_block instrument hat powered true note 19 437 note_block instrument hat powered false note 19 438 note_block instrument hat powered true note 20 439 note_block instrument hat powered false note 20 440 note_block instrument hat powered true note 21 441 note_block instrument hat powered false note 21 442 note_block instrument hat powered true note 22 443 note_block instrument hat powered false note 22 444 note_block instrument hat powered true note 23 445 note_block instrument hat powered false note 23 446 note_block instrument hat powered true note 24 447 note_block instrument hat powered false note 24 448 note_block instrument bass powered true note 0 449 note_block instrument bass powered false note 0 450 note_block instrument bass powered true note 1 451 note_block instrument bass powered false note 1 452 note_block instrument bass powered true note 2 453 note_block instrument bass powered false note 2 454 note_block instrument bass powered true note 3 455 note_block instrument bass powered false note 3 456 note_block instrument bass powered true note 4 457 note_block instrument bass powered false note 4 458 note_block instrument bass powered true note 5 459 note_block instrument bass powered false note 5 460 note_block instrument bass powered true note 6 461 note_block instrument bass powered false note 6 462 note_block instrument bass powered true note 7 463 note_block instrument bass powered false note 7 464 note_block instrument bass powered true note 8 465 note_block instrument bass powered false note 8 466 note_block instrument bass powered true note 9 467 note_block instrument bass powered false note 9 468 note_block instrument bass powered true note 10 469 note_block instrument bass powered false note 10 470 note_block instrument bass powered true note 11 471 note_block instrument bass powered false note 11 472 note_block instrument bass powered true note 12 473 note_block instrument bass powered false note 12 474 note_block instrument bass powered true note 13 475 note_block instrument bass powered false note 13 476 note_block instrument bass powered true note 14 477 note_block instrument bass powered false note 14 478 note_block instrument bass powered true note 15 479 note_block instrument bass powered false note 15 480 note_block instrument bass powered true note 16 481 note_block instrument bass powered false note 16 482 note_block instrument bass powered true note 17 483 note_block instrument bass powered false note 17 484 note_block instrument bass powered true note 18 485 note_block instrument bass powered false note 18 486 note_block instrument bass powered true note 19 487 note_block instrument bass powered false note 19 488 note_block instrument bass powered true note 20 489 note_block instrument bass powered false note 20 490 note_block instrument bass powered true note 21 491 note_block instrument bass powered false note 21 492 note_block instrument bass powered true note 22 493 note_block instrument bass powered false note 22 494 note_block instrument bass powered true note 23 495 note_block instrument bass powered false note 23 496 note_block instrument bass powered true note 24 497 note_block instrument bass powered false note 24 498 note_block instrument flute powered true note 0 499 note_block instrument flute powered false note 0 500 note_block instrument flute powered true note 1 501 note_block instrument flute powered false note 1 502 note_block instrument flute powered true note 2 503 note_block instrument flute powered false note 2 504 note_block instrument flute powered true note 3 505 note_block instrument flute powered false note 3 506 note_block instrument flute powered true note 4 507 note_block instrument flute powered false note 4 508 note_block instrument flute powered true note 5 509 note_block instrument flute powered false note 5 510 note_block instrument flute powered true note 6 511 note_block instrument flute powered false note 6 512 note_block instrument flute powered true note 7 513 note_block instrument flute powered false note 7 514 note_block instrument flute powered true note 8 515 note_block instrument flute powered false note 8 516 note_block instrument flute powered true note 9 517 note_block instrument flute powered false note 9 518 note_block instrument flute powered true note 10 519 note_block instrument flute powered false note 10 520 note_block instrument flute powered true note 11 521 note_block instrument flute powered false note 11 522 note_block instrument flute powered true note 12 523 note_block instrument flute powered false note 12 524 note_block instrument flute powered true note 13 525 note_block instrument flute powered false note 13 526 note_block instrument flute powered true note 14 527 note_block instrument flute powered false note 14 528 note_block instrument flute powered true note 15 529 note_block instrument flute powered false note 15 530 note_block instrument flute powered true note 16 531 note_block instrument flute powered false note 16 532 note_block instrument flute powered true note 17 533 note_block instrument flute powered false note 17 534 note_block instrument flute powered true note 18 535 note_block instrument flute powered false note 18 536 note_block instrument flute powered true note 19 537 note_block instrument flute powered false note 19 538 note_block instrument flute powered true note 20 539 note_block instrument flute powered false note 20 540 note_block instrument flute powered true note 21 541 note_block instrument flute powered false note 21 542 note_block instrument flute powered true note 22 543 note_block instrument flute powered false note 22 544 note_block instrument flute powered true note 23 545 note_block instrument flute powered false note 23 546 note_block instrument flute powered true note 24 547 note_block instrument flute powered false note 24 548 note_block instrument bell powered true note 0 549 note_block instrument bell powered false note 0 550 note_block instrument bell powered true note 1 551 note_block instrument bell powered false note 1 552 note_block instrument bell powered true note 2 553 note_block instrument bell powered false note 2 554 note_block instrument bell powered true note 3 555 note_block instrument bell powered false note 3 556 note_block instrument bell powered true note 4 557 note_block instrument bell powered false note 4 558 note_block instrument bell powered true note 5 559 note_block instrument bell powered false note 5 560 note_block instrument bell powered true note 6 561 note_block instrument bell powered false note 6 562 note_block instrument bell powered true note 7 563 note_block instrument bell powered false note 7 564 note_block instrument bell powered true note 8 565 note_block instrument bell powered false note 8 566 note_block instrument bell powered true note 9 567 note_block instrument bell powered false note 9 568 note_block instrument bell powered true note 10 569 note_block instrument bell powered false note 10 570 note_block instrument bell powered true note 11 571 note_block instrument bell powered false note 11 572 note_block instrument bell powered true note 12 573 note_block instrument bell powered false note 12 574 note_block instrument bell powered true note 13 575 note_block instrument bell powered false note 13 576 note_block instrument bell powered true note 14 577 note_block instrument bell powered false note 14 578 note_block instrument bell powered true note 15 579 note_block instrument bell powered false note 15 580 note_block instrument bell powered true note 16 581 note_block instrument bell powered false note 16 582 note_block instrument bell powered true note 17 583 note_block instrument bell powered false note 17 584 note_block instrument bell powered true note 18 585 note_block instrument bell powered false note 18 586 note_block instrument bell powered true note 19 587 note_block instrument bell powered false note 19 588 note_block instrument bell powered true note 20 589 note_block instrument bell powered false note 20 590 note_block instrument bell powered true note 21 591 note_block instrument bell powered false note 21 592 note_block instrument bell powered true note 22 593 note_block instrument bell powered false note 22 594 note_block instrument bell powered true note 23 595 note_block instrument bell powered false note 23 596 note_block instrument bell powered true note 24 597 note_block instrument bell powered false note 24 598 note_block instrument guitar powered true note 0 599 note_block instrument guitar powered false note 0 600 note_block instrument guitar powered true note 1 601 note_block instrument guitar powered false note 1 602 note_block instrument guitar powered true note 2 603 note_block instrument guitar powered false note 2 604 note_block instrument guitar powered true note 3 605 note_block instrument guitar powered false note 3 606 note_block instrument guitar powered true note 4 607 note_block instrument guitar powered false note 4 608 note_block instrument guitar powered true note 5 609 note_block instrument guitar powered false note 5 610 note_block instrument guitar powered true note 6 611 note_block instrument guitar powered false note 6 612 note_block instrument guitar powered true note 7 613 note_block instrument guitar powered false note 7 614 note_block instrument guitar powered true note 8 615 note_block instrument guitar powered false note 8 616 note_block instrument guitar powered true note 9 617 note_block instrument guitar powered false note 9 618 note_block instrument guitar powered true note 10 619 note_block instrument guitar powered false note 10 620 note_block instrument guitar powered true note 11 621 note_block instrument guitar powered false note 11 622 note_block instrument guitar powered true note 12 623 note_block instrument guitar powered false note 12 624 note_block instrument guitar powered true note 13 625 note_block instrument guitar powered false note 13 626 note_block instrument guitar powered true note 14 627 note_block instrument guitar powered false note 14 628 note_block instrument guitar powered true note 15 629 note_block instrument guitar powered false note 15 630 note_block instrument guitar powered true note 16 631 note_block instrument guitar powered false note 16 632 note_block instrument guitar powered true note 17 633 note_block instrument guitar powered false note 17 634 note_block instrument guitar powered true note 18 635 note_block instrument guitar powered false note 18 636 note_block instrument guitar powered true note 19 637 note_block instrument guitar powered false note 19 638 note_block instrument guitar powered true note 20 639 note_block instrument guitar powered false note 20 640 note_block instrument guitar powered true note 21 641 note_block instrument guitar powered false note 21 642 note_block instrument guitar powered true note 22 643 note_block instrument guitar powered false note 22 644 note_block instrument guitar powered true note 23 645 note_block instrument guitar powered false note 23 646 note_block instrument guitar powered true note 24 647 note_block instrument guitar powered false note 24 648 note_block instrument chime powered true note 0 649 note_block instrument chime powered false note 0 650 note_block instrument chime powered true note 1 651 note_block instrument chime powered false note 1 652 note_block instrument chime powered true note 2 653 note_block instrument chime powered false note 2 654 note_block instrument chime powered true note 3 655 note_block instrument chime powered false note 3 656 note_block instrument chime powered true note 4 657 note_block instrument chime powered false note 4 658 note_block instrument chime powered true note 5 659 note_block instrument chime powered false note 5 660 note_block instrument chime powered true note 6 661 note_block instrument chime powered false note 6 662 note_block instrument chime powered true note 7 663 note_block instrument chime powered false note 7 664 note_block instrument chime powered true note 8 665 note_block instrument chime powered false note 8 666 note_block instrument chime powered true note 9 667 note_block instrument chime powered false note 9 668 note_block instrument chime powered true note 10 669 note_block instrument chime powered false note 10 670 note_block instrument chime powered true note 11 671 note_block instrument chime powered false note 11 672 note_block instrument chime powered true note 12 673 note_block instrument chime powered false note 12 674 note_block instrument chime powered true note 13 675 note_block instrument chime powered false note 13 676 note_block instrument chime powered true note 14 677 note_block instrument chime powered false note 14 678 note_block instrument chime powered true note 15 679 note_block instrument chime powered false note 15 680 note_block instrument chime powered true note 16 681 note_block instrument chime powered false note 16 682 note_block instrument chime powered true note 17 683 note_block instrument chime powered false note 17 684 note_block instrument chime powered true note 18 685 note_block instrument chime powered false note 18 686 note_block instrument chime powered true note 19 687 note_block instrument chime powered false note 19 688 note_block instrument chime powered true note 20 689 note_block instrument chime powered false note 20 690 note_block instrument chime powered true note 21 691 note_block instrument chime powered false note 21 692 note_block instrument chime powered true note 22 693 note_block instrument chime powered false note 22 694 note_block instrument chime powered true note 23 695 note_block instrument chime powered false note 23 696 note_block instrument chime powered true note 24 697 note_block instrument chime powered false note 24 698 note_block instrument xylophone powered true note 0 699 note_block instrument xylophone powered false note 0 700 note_block instrument xylophone powered true note 1 701 note_block instrument xylophone powered false note 1 702 note_block instrument xylophone powered true note 2 703 note_block instrument xylophone powered false note 2 704 note_block instrument xylophone powered true note 3 705 note_block instrument xylophone powered false note 3 706 note_block instrument xylophone powered true note 4 707 note_block instrument xylophone powered false note 4 708 note_block instrument xylophone powered true note 5 709 note_block instrument xylophone powered false note 5 710 note_block instrument xylophone powered true note 6 711 note_block instrument xylophone powered false note 6 712 note_block instrument xylophone powered true note 7 713 note_block instrument xylophone powered false note 7 714 note_block instrument xylophone powered true note 8 715 note_block instrument xylophone powered false note 8 716 note_block instrument xylophone powered true note 9 717 note_block instrument xylophone powered false note 9 718 note_block instrument xylophone powered true note 10 719 note_block instrument xylophone powered false note 10 720 note_block instrument xylophone powered true note 11 721 note_block instrument xylophone powered false note 11 722 note_block instrument xylophone powered true note 12 723 note_block instrument xylophone powered false note 12 724 note_block instrument xylophone powered true note 13 725 note_block instrument xylophone powered false note 13 726 note_block instrument xylophone powered true note 14 727 note_block instrument xylophone powered false note 14 728 note_block instrument xylophone powered true note 15 729 note_block instrument xylophone powered false note 15 730 note_block instrument xylophone powered true note 16 731 note_block instrument xylophone powered false note 16 732 note_block instrument xylophone powered true note 17 733 note_block instrument xylophone powered false note 17 734 note_block instrument xylophone powered true note 18 735 note_block instrument xylophone powered false note 18 736 note_block instrument xylophone powered true note 19 737 note_block instrument xylophone powered false note 19 738 note_block instrument xylophone powered true note 20 739 note_block instrument xylophone powered false note 20 740 note_block instrument xylophone powered true note 21 741 note_block instrument xylophone powered false note 21 742 note_block instrument xylophone powered true note 22 743 note_block instrument xylophone powered false note 22 744 note_block instrument xylophone powered true note 23 745 note_block instrument xylophone powered false note 23 746 note_block instrument xylophone powered true note 24 747 note_block instrument xylophone powered false note 24 748 white_bed facing north occupied true part head 749 white_bed facing north occupied true part foot 750 white_bed facing north occupied false part head 751 white_bed facing north occupied false part foot 752 white_bed facing south occupied true part head 753 white_bed facing south occupied true part foot 754 white_bed facing south occupied false part head 755 white_bed facing south occupied false part foot 756 white_bed facing west occupied true part head 757 white_bed facing west occupied true part foot 758 white_bed facing west occupied false part head 759 white_bed facing west occupied false part foot 760 white_bed facing east occupied true part head 761 white_bed facing east occupied true part foot 762 white_bed facing east occupied false part head 763 white_bed facing east occupied false part foot 764 orange_bed facing north occupied true part head 765 orange_bed facing north occupied true part foot 766 orange_bed facing north occupied false part head 767 orange_bed facing north occupied false part foot 768 orange_bed facing south occupied true part head 769 orange_bed facing south occupied true part foot 770 orange_bed facing south occupied false part head 771 orange_bed facing south occupied false part foot 772 orange_bed facing west occupied true part head 773 orange_bed facing west occupied true part foot 774 orange_bed facing west occupied false part head 775 orange_bed facing west occupied false part foot 776 orange_bed facing east occupied true part head 777 orange_bed facing east occupied true part foot 778 orange_bed facing east occupied false part head 779 orange_bed facing east occupied false part foot 780 magenta_bed facing north occupied true part head 781 magenta_bed facing north occupied true part foot 782 magenta_bed facing north occupied false part head 783 magenta_bed facing north occupied false part foot 784 magenta_bed facing south occupied true part head 785 magenta_bed facing south occupied true part foot 786 magenta_bed facing south occupied false part head 787 magenta_bed facing south occupied false part foot 788 magenta_bed facing west occupied true part head 789 magenta_bed facing west occupied true part foot 790 magenta_bed facing west occupied false part head 791 magenta_bed facing west occupied false part foot 792 magenta_bed facing east occupied true part head 793 magenta_bed facing east occupied true part foot 794 magenta_bed facing east occupied false part head 795 magenta_bed facing east occupied false part foot 796 light_blue_bed facing north occupied true part head 797 light_blue_bed facing north occupied true part foot 798 light_blue_bed facing north occupied false part head 799 light_blue_bed facing north occupied false part foot 800 light_blue_bed facing south occupied true part head 801 light_blue_bed facing south occupied true part foot 802 light_blue_bed facing south occupied false part head 803 light_blue_bed facing south occupied false part foot 804 light_blue_bed facing west occupied true part head 805 light_blue_bed facing west occupied true part foot 806 light_blue_bed facing west occupied false part head 807 light_blue_bed facing west occupied false part foot 808 light_blue_bed facing east occupied true part head 809 light_blue_bed facing east occupied true part foot 810 light_blue_bed facing east occupied false part head 811 light_blue_bed facing east occupied false part foot 812 yellow_bed facing north occupied true part head 813 yellow_bed facing north occupied true part foot 814 yellow_bed facing north occupied false part head 815 yellow_bed facing north occupied false part foot 816 yellow_bed facing south occupied true part head 817 yellow_bed facing south occupied true part foot 818 yellow_bed facing south occupied false part head 819 yellow_bed facing south occupied false part foot 820 yellow_bed facing west occupied true part head 821 yellow_bed facing west occupied true part foot 822 yellow_bed facing west occupied false part head 823 yellow_bed facing west occupied false part foot 824 yellow_bed facing east occupied true part head 825 yellow_bed facing east occupied true part foot 826 yellow_bed facing east occupied false part head 827 yellow_bed facing east occupied false part foot 828 lime_bed facing north occupied true part head 829 lime_bed facing north occupied true part foot 830 lime_bed facing north occupied false part head 831 lime_bed facing north occupied false part foot 832 lime_bed facing south occupied true part head 833 lime_bed facing south occupied true part foot 834 lime_bed facing south occupied false part head 835 lime_bed facing south occupied false part foot 836 lime_bed facing west occupied true part head 837 lime_bed facing west occupied true part foot 838 lime_bed facing west occupied false part head 839 lime_bed facing west occupied false part foot 840 lime_bed facing east occupied true part head 841 lime_bed facing east occupied true part foot 842 lime_bed facing east occupied false part head 843 lime_bed facing east occupied false part foot 844 pink_bed facing north occupied true part head 845 pink_bed facing north occupied true part foot 846 pink_bed facing north occupied false part head 847 pink_bed facing north occupied false part foot 848 pink_bed facing south occupied true part head 849 pink_bed facing south occupied true part foot 850 pink_bed facing south occupied false part head 851 pink_bed facing south occupied false part foot 852 pink_bed facing west occupied true part head 853 pink_bed facing west occupied true part foot 854 pink_bed facing west occupied false part head 855 pink_bed facing west occupied false part foot 856 pink_bed facing east occupied true part head 857 pink_bed facing east occupied true part foot 858 pink_bed facing east occupied false part head 859 pink_bed facing east occupied false part foot 860 gray_bed facing north occupied true part head 861 gray_bed facing north occupied true part foot 862 gray_bed facing north occupied false part head 863 gray_bed facing north occupied false part foot 864 gray_bed facing south occupied true part head 865 gray_bed facing south occupied true part foot 866 gray_bed facing south occupied false part head 867 gray_bed facing south occupied false part foot 868 gray_bed facing west occupied true part head 869 gray_bed facing west occupied true part foot 870 gray_bed facing west occupied false part head 871 gray_bed facing west occupied false part foot 872 gray_bed facing east occupied true part head 873 gray_bed facing east occupied true part foot 874 gray_bed facing east occupied false part head 875 gray_bed facing east occupied false part foot 876 light_gray_bed facing north occupied true part head 877 light_gray_bed facing north occupied true part foot 878 light_gray_bed facing north occupied false part head 879 light_gray_bed facing north occupied false part foot 880 light_gray_bed facing south occupied true part head 881 light_gray_bed facing south occupied true part foot 882 light_gray_bed facing south occupied false part head 883 light_gray_bed facing south occupied false part foot 884 light_gray_bed facing west occupied true part head 885 light_gray_bed facing west occupied true part foot 886 light_gray_bed facing west occupied false part head 887 light_gray_bed facing west occupied false part foot 888 light_gray_bed facing east occupied true part head 889 light_gray_bed facing east occupied true part foot 890 light_gray_bed facing east occupied false part head 891 light_gray_bed facing east occupied false part foot 892 cyan_bed facing north occupied true part head 893 cyan_bed facing north occupied true part foot 894 cyan_bed facing north occupied false part head 895 cyan_bed facing north occupied false part foot 896 cyan_bed facing south occupied true part head 897 cyan_bed facing south occupied true part foot 898 cyan_bed facing south occupied false part head 899 cyan_bed facing south occupied false part foot 900 cyan_bed facing west occupied true part head 901 cyan_bed facing west occupied true part foot 902 cyan_bed facing west occupied false part head 903 cyan_bed facing west occupied false part foot 904 cyan_bed facing east occupied true part head 905 cyan_bed facing east occupied true part foot 906 cyan_bed facing east occupied false part head 907 cyan_bed facing east occupied false part foot 908 purple_bed facing north occupied true part head 909 purple_bed facing north occupied true part foot 910 purple_bed facing north occupied false part head 911 purple_bed facing north occupied false part foot 912 purple_bed facing south occupied true part head 913 purple_bed facing south occupied true part foot 914 purple_bed facing south occupied false part head 915 purple_bed facing south occupied false part foot 916 purple_bed facing west occupied true part head 917 purple_bed facing west occupied true part foot 918 purple_bed facing west occupied false part head 919 purple_bed facing west occupied false part foot 920 purple_bed facing east occupied true part head 921 purple_bed facing east occupied true part foot 922 purple_bed facing east occupied false part head 923 purple_bed facing east occupied false part foot 924 blue_bed facing north occupied true part head 925 blue_bed facing north occupied true part foot 926 blue_bed facing north occupied false part head 927 blue_bed facing north occupied false part foot 928 blue_bed facing south occupied true part head 929 blue_bed facing south occupied true part foot 930 blue_bed facing south occupied false part head 931 blue_bed facing south occupied false part foot 932 blue_bed facing west occupied true part head 933 blue_bed facing west occupied true part foot 934 blue_bed facing west occupied false part head 935 blue_bed facing west occupied false part foot 936 blue_bed facing east occupied true part head 937 blue_bed facing east occupied true part foot 938 blue_bed facing east occupied false part head 939 blue_bed facing east occupied false part foot 940 brown_bed facing north occupied true part head 941 brown_bed facing north occupied true part foot 942 brown_bed facing north occupied false part head 943 brown_bed facing north occupied false part foot 944 brown_bed facing south occupied true part head 945 brown_bed facing south occupied true part foot 946 brown_bed facing south occupied false part head 947 brown_bed facing south occupied false part foot 948 brown_bed facing west occupied true part head 949 brown_bed facing west occupied true part foot 950 brown_bed facing west occupied false part head 951 brown_bed facing west occupied false part foot 952 brown_bed facing east occupied true part head 953 brown_bed facing east occupied true part foot 954 brown_bed facing east occupied false part head 955 brown_bed facing east occupied false part foot 956 green_bed facing north occupied true part head 957 green_bed facing north occupied true part foot 958 green_bed facing north occupied false part head 959 green_bed facing north occupied false part foot 960 green_bed facing south occupied true part head 961 green_bed facing south occupied true part foot 962 green_bed facing south occupied false part head 963 green_bed facing south occupied false part foot 964 green_bed facing west occupied true part head 965 green_bed facing west occupied true part foot 966 green_bed facing west occupied false part head 967 green_bed facing west occupied false part foot 968 green_bed facing east occupied true part head 969 green_bed facing east occupied true part foot 970 green_bed facing east occupied false part head 971 green_bed facing east occupied false part foot 972 red_bed facing north occupied true part head 973 red_bed facing north occupied true part foot 974 red_bed facing north occupied false part head 975 red_bed facing north occupied false part foot 976 red_bed facing south occupied true part head 977 red_bed facing south occupied true part foot 978 red_bed facing south occupied false part head 979 red_bed facing south occupied false part foot 980 red_bed facing west occupied true part head 981 red_bed facing west occupied true part foot 982 red_bed facing west occupied false part head 983 red_bed facing west occupied false part foot 984 red_bed facing east occupied true part head 985 red_bed facing east occupied true part foot 986 red_bed facing east occupied false part head 987 red_bed facing east occupied false part foot 988 black_bed facing north occupied true part head 989 black_bed facing north occupied true part foot 990 black_bed facing north occupied false part head 991 black_bed facing north occupied false part foot 992 black_bed facing south occupied true part head 993 black_bed facing south occupied true part foot 994 black_bed facing south occupied false part head 995 black_bed facing south occupied false part foot 996 black_bed facing west occupied true part head 997 black_bed facing west occupied true part foot 998 black_bed facing west occupied false part head 999 black_bed facing west occupied false part foot 1000 black_bed facing east occupied true part head 1001 black_bed facing east occupied true part foot 1002 black_bed facing east occupied false part head 1003 black_bed facing east occupied false part foot 1004 powered_rail shape north_south powered true 1005 powered_rail shape east_west powered true 1006 powered_rail shape ascending_east powered true 1007 powered_rail shape ascending_west powered true 1008 powered_rail shape ascending_north powered true 1009 powered_rail shape ascending_south powered true 1010 powered_rail shape north_south powered false 1011 powered_rail shape east_west powered false 1012 powered_rail shape ascending_east powered false 1013 powered_rail shape ascending_west powered false 1014 powered_rail shape ascending_north powered false 1015 powered_rail shape ascending_south powered false 1016 detector_rail shape north_south powered true 1017 detector_rail shape east_west powered true 1018 detector_rail shape ascending_east powered true 1019 detector_rail shape ascending_west powered true 1020 detector_rail shape ascending_north powered true 1021 detector_rail shape ascending_south powered true 1022 detector_rail shape north_south powered false 1023 detector_rail shape east_west powered false 1024 detector_rail shape ascending_east powered false 1025 detector_rail shape ascending_west powered false 1026 detector_rail shape ascending_north powered false 1027 detector_rail shape ascending_south powered false 1028 sticky_piston facing north extended true 1029 sticky_piston facing east extended true 1030 sticky_piston facing south extended true 1031 sticky_piston facing west extended true 1032 sticky_piston facing up extended true 1033 sticky_piston facing down extended true 1034 sticky_piston facing north extended false 1035 sticky_piston facing east extended false 1036 sticky_piston facing south extended false 1037 sticky_piston facing west extended false 1038 sticky_piston facing up extended false 1039 sticky_piston facing down extended false 1040 cobweb 1041 grass 1042 fern 1043 dead_bush 1044 seagrass 1045 tall_seagrass half upper 1046 tall_seagrass half lower 1047 piston facing north extended true 1048 piston facing east extended true 1049 piston facing south extended true 1050 piston facing west extended true 1051 piston facing up extended true 1052 piston facing down extended true 1053 piston facing north extended false 1054 piston facing east extended false 1055 piston facing south extended false 1056 piston facing west extended false 1057 piston facing up extended false 1058 piston facing down extended false 1059 piston_head facing north short true type normal 1060 piston_head facing north short true type sticky 1061 piston_head facing north short false type normal 1062 piston_head facing north short false type sticky 1063 piston_head facing east short true type normal 1064 piston_head facing east short true type sticky 1065 piston_head facing east short false type normal 1066 piston_head facing east short false type sticky 1067 piston_head facing south short true type normal 1068 piston_head facing south short true type sticky 1069 piston_head facing south short false type normal 1070 piston_head facing south short false type sticky 1071 piston_head facing west short true type normal 1072 piston_head facing west short true type sticky 1073 piston_head facing west short false type normal 1074 piston_head facing west short false type sticky 1075 piston_head facing up short true type normal 1076 piston_head facing up short true type sticky 1077 piston_head facing up short false type normal 1078 piston_head facing up short false type sticky 1079 piston_head facing down short true type normal 1080 piston_head facing down short true type sticky 1081 piston_head facing down short false type normal 1082 piston_head facing down short false type sticky 1083 white_wool 1084 orange_wool 1085 magenta_wool 1086 light_blue_wool 1087 yellow_wool 1088 lime_wool 1089 pink_wool 1090 gray_wool 1091 light_gray_wool 1092 cyan_wool 1093 purple_wool 1094 blue_wool 1095 brown_wool 1096 green_wool 1097 red_wool 1098 black_wool 1099 moving_piston facing north type normal 1100 moving_piston facing north type sticky 1101 moving_piston facing east type normal 1102 moving_piston facing east type sticky 1103 moving_piston facing south type normal 1104 moving_piston facing south type sticky 1105 moving_piston facing west type normal 1106 moving_piston facing west type sticky 1107 moving_piston facing up type normal 1108 moving_piston facing up type sticky 1109 moving_piston facing down type normal 1110 moving_piston facing down type sticky 1111 dandelion 1112 poppy 1113 blue_orchid 1114 allium 1115 azure_bluet 1116 red_tulip 1117 orange_tulip 1118 white_tulip 1119 pink_tulip 1120 oxeye_daisy 1121 brown_mushroom 1122 red_mushroom 1123 gold_block 1124 iron_block 1125 bricks 1126 tnt 1127 bookshelf 1128 mossy_cobblestone 1129 obsidian 1130 torch 1131 wall_torch facing north 1132 wall_torch facing south 1133 wall_torch facing west 1134 wall_torch facing east 1135 fire north true south true east true age 0 up true west true 1136 fire north true south true east true age 0 up true west false 1137 fire north true south true east true age 0 up false west true 1138 fire north true south true east true age 0 up false west false 1139 fire north true south false east true age 0 up true west true 1140 fire north true south false east true age 0 up true west false 1141 fire north true south false east true age 0 up false west true 1142 fire north true south false east true age 0 up false west false 1143 fire north false south true east true age 0 up true west true 1144 fire north false south true east true age 0 up true west false 1145 fire north false south true east true age 0 up false west true 1146 fire north false south true east true age 0 up false west false 1147 fire north false south false east true age 0 up true west true 1148 fire north false south false east true age 0 up true west false 1149 fire north false south false east true age 0 up false west true 1150 fire north false south false east true age 0 up false west false 1151 fire north true south true east false age 0 up true west true 1152 fire north true south true east false age 0 up true west false 1153 fire north true south true east false age 0 up false west true 1154 fire north true south true east false age 0 up false west false 1155 fire north true south false east false age 0 up true west true 1156 fire north true south false east false age 0 up true west false 1157 fire north true south false east false age 0 up false west true 1158 fire north true south false east false age 0 up false west false 1159 fire north false south true east false age 0 up true west true 1160 fire north false south true east false age 0 up true west false 1161 fire north false south true east false age 0 up false west true 1162 fire north false south true east false age 0 up false west false 1163 fire north false south false east false age 0 up true west true 1164 fire north false south false east false age 0 up true west false 1165 fire north false south false east false age 0 up false west true 1166 fire north false south false east false age 0 up false west false 1167 fire north true south true east true age 1 up true west true 1168 fire north true south true east true age 1 up true west false 1169 fire north true south true east true age 1 up false west true 1170 fire north true south true east true age 1 up false west false 1171 fire north true south false east true age 1 up true west true 1172 fire north true south false east true age 1 up true west false 1173 fire north true south false east true age 1 up false west true 1174 fire north true south false east true age 1 up false west false 1175 fire north false south true east true age 1 up true west true 1176 fire north false south true east true age 1 up true west false 1177 fire north false south true east true age 1 up false west true 1178 fire north false south true east true age 1 up false west false 1179 fire north false south false east true age 1 up true west true 1180 fire north false south false east true age 1 up true west false 1181 fire north false south false east true age 1 up false west true 1182 fire north false south false east true age 1 up false west false 1183 fire north true south true east false age 1 up true west true 1184 fire north true south true east false age 1 up true west false 1185 fire north true south true east false age 1 up false west true 1186 fire north true south true east false age 1 up false west false 1187 fire north true south false east false age 1 up true west true 1188 fire north true south false east false age 1 up true west false 1189 fire north true south false east false age 1 up false west true 1190 fire north true south false east false age 1 up false west false 1191 fire north false south true east false age 1 up true west true 1192 fire north false south true east false age 1 up true west false 1193 fire north false south true east false age 1 up false west true 1194 fire north false south true east false age 1 up false west false 1195 fire north false south false east false age 1 up true west true 1196 fire north false south false east false age 1 up true west false 1197 fire north false south false east false age 1 up false west true 1198 fire north false south false east false age 1 up false west false 1199 fire north true south true east true age 2 up true west true 1200 fire north true south true east true age 2 up true west false 1201 fire north true south true east true age 2 up false west true 1202 fire north true south true east true age 2 up false west false 1203 fire north true south false east true age 2 up true west true 1204 fire north true south false east true age 2 up true west false 1205 fire north true south false east true age 2 up false west true 1206 fire north true south false east true age 2 up false west false 1207 fire north false south true east true age 2 up true west true 1208 fire north false south true east true age 2 up true west false 1209 fire north false south true east true age 2 up false west true 1210 fire north false south true east true age 2 up false west false 1211 fire north false south false east true age 2 up true west true 1212 fire north false south false east true age 2 up true west false 1213 fire north false south false east true age 2 up false west true 1214 fire north false south false east true age 2 up false west false 1215 fire north true south true east false age 2 up true west true 1216 fire north true south true east false age 2 up true west false 1217 fire north true south true east false age 2 up false west true 1218 fire north true south true east false age 2 up false west false 1219 fire north true south false east false age 2 up true west true 1220 fire north true south false east false age 2 up true west false 1221 fire north true south false east false age 2 up false west true 1222 fire north true south false east false age 2 up false west false 1223 fire north false south true east false age 2 up true west true 1224 fire north false south true east false age 2 up true west false 1225 fire north false south true east false age 2 up false west true 1226 fire north false south true east false age 2 up false west false 1227 fire north false south false east false age 2 up true west true 1228 fire north false south false east false age 2 up true west false 1229 fire north false south false east false age 2 up false west true 1230 fire north false south false east false age 2 up false west false 1231 fire north true south true east true age 3 up true west true 1232 fire north true south true east true age 3 up true west false 1233 fire north true south true east true age 3 up false west true 1234 fire north true south true east true age 3 up false west false 1235 fire north true south false east true age 3 up true west true 1236 fire north true south false east true age 3 up true west false 1237 fire north true south false east true age 3 up false west true 1238 fire north true south false east true age 3 up false west false 1239 fire north false south true east true age 3 up true west true 1240 fire north false south true east true age 3 up true west false 1241 fire north false south true east true age 3 up false west true 1242 fire north false south true east true age 3 up false west false 1243 fire north false south false east true age 3 up true west true 1244 fire north false south false east true age 3 up true west false 1245 fire north false south false east true age 3 up false west true 1246 fire north false south false east true age 3 up false west false 1247 fire north true south true east false age 3 up true west true 1248 fire north true south true east false age 3 up true west false 1249 fire north true south true east false age 3 up false west true 1250 fire north true south true east false age 3 up false west false 1251 fire north true south false east false age 3 up true west true 1252 fire north true south false east false age 3 up true west false 1253 fire north true south false east false age 3 up false west true 1254 fire north true south false east false age 3 up false west false 1255 fire north false south true east false age 3 up true west true 1256 fire north false south true east false age 3 up true west false 1257 fire north false south true east false age 3 up false west true 1258 fire north false south true east false age 3 up false west false 1259 fire north false south false east false age 3 up true west true 1260 fire north false south false east false age 3 up true west false 1261 fire north false south false east false age 3 up false west true 1262 fire north false south false east false age 3 up false west false 1263 fire north true south true east true age 4 up true west true 1264 fire north true south true east true age 4 up true west false 1265 fire north true south true east true age 4 up false west true 1266 fire north true south true east true age 4 up false west false 1267 fire north true south false east true age 4 up true west true 1268 fire north true south false east true age 4 up true west false 1269 fire north true south false east true age 4 up false west true 1270 fire north true south false east true age 4 up false west false 1271 fire north false south true east true age 4 up true west true 1272 fire north false south true east true age 4 up true west false 1273 fire north false south true east true age 4 up false west true 1274 fire north false south true east true age 4 up false west false 1275 fire north false south false east true age 4 up true west true 1276 fire north false south false east true age 4 up true west false 1277 fire north false south false east true age 4 up false west true 1278 fire north false south false east true age 4 up false west false 1279 fire north true south true east false age 4 up true west true 1280 fire north true south true east false age 4 up true west false 1281 fire north true south true east false age 4 up false west true 1282 fire north true south true east false age 4 up false west false 1283 fire north true south false east false age 4 up true west true 1284 fire north true south false east false age 4 up true west false 1285 fire north true south false east false age 4 up false west true 1286 fire north true south false east false age 4 up false west false 1287 fire north false south true east false age 4 up true west true 1288 fire north false south true east false age 4 up true west false 1289 fire north false south true east false age 4 up false west true 1290 fire north false south true east false age 4 up false west false 1291 fire north false south false east false age 4 up true west true 1292 fire north false south false east false age 4 up true west false 1293 fire north false south false east false age 4 up false west true 1294 fire north false south false east false age 4 up false west false 1295 fire north true south true east true age 5 up true west true 1296 fire north true south true east true age 5 up true west false 1297 fire north true south true east true age 5 up false west true 1298 fire north true south true east true age 5 up false west false 1299 fire north true south false east true age 5 up true west true 1300 fire north true south false east true age 5 up true west false 1301 fire north true south false east true age 5 up false west true 1302 fire north true south false east true age 5 up false west false 1303 fire north false south true east true age 5 up true west true 1304 fire north false south true east true age 5 up true west false 1305 fire north false south true east true age 5 up false west true 1306 fire north false south true east true age 5 up false west false 1307 fire north false south false east true age 5 up true west true 1308 fire north false south false east true age 5 up true west false 1309 fire north false south false east true age 5 up false west true 1310 fire north false south false east true age 5 up false west false 1311 fire north true south true east false age 5 up true west true 1312 fire north true south true east false age 5 up true west false 1313 fire north true south true east false age 5 up false west true 1314 fire north true south true east false age 5 up false west false 1315 fire north true south false east false age 5 up true west true 1316 fire north true south false east false age 5 up true west false 1317 fire north true south false east false age 5 up false west true 1318 fire north true south false east false age 5 up false west false 1319 fire north false south true east false age 5 up true west true 1320 fire north false south true east false age 5 up true west false 1321 fire north false south true east false age 5 up false west true 1322 fire north false south true east false age 5 up false west false 1323 fire north false south false east false age 5 up true west true 1324 fire north false south false east false age 5 up true west false 1325 fire north false south false east false age 5 up false west true 1326 fire north false south false east false age 5 up false west false 1327 fire north true south true east true age 6 up true west true 1328 fire north true south true east true age 6 up true west false 1329 fire north true south true east true age 6 up false west true 1330 fire north true south true east true age 6 up false west false 1331 fire north true south false east true age 6 up true west true 1332 fire north true south false east true age 6 up true west false 1333 fire north true south false east true age 6 up false west true 1334 fire north true south false east true age 6 up false west false 1335 fire north false south true east true age 6 up true west true 1336 fire north false south true east true age 6 up true west false 1337 fire north false south true east true age 6 up false west true 1338 fire north false south true east true age 6 up false west false 1339 fire north false south false east true age 6 up true west true 1340 fire north false south false east true age 6 up true west false 1341 fire north false south false east true age 6 up false west true 1342 fire north false south false east true age 6 up false west false 1343 fire north true south true east false age 6 up true west true 1344 fire north true south true east false age 6 up true west false 1345 fire north true south true east false age 6 up false west true 1346 fire north true south true east false age 6 up false west false 1347 fire north true south false east false age 6 up true west true 1348 fire north true south false east false age 6 up true west false 1349 fire north true south false east false age 6 up false west true 1350 fire north true south false east false age 6 up false west false 1351 fire north false south true east false age 6 up true west true 1352 fire north false south true east false age 6 up true west false 1353 fire north false south true east false age 6 up false west true 1354 fire north false south true east false age 6 up false west false 1355 fire north false south false east false age 6 up true west true 1356 fire north false south false east false age 6 up true west false 1357 fire north false south false east false age 6 up false west true 1358 fire north false south false east false age 6 up false west false 1359 fire north true south true east true age 7 up true west true 1360 fire north true south true east true age 7 up true west false 1361 fire north true south true east true age 7 up false west true 1362 fire north true south true east true age 7 up false west false 1363 fire north true south false east true age 7 up true west true 1364 fire north true south false east true age 7 up true west false 1365 fire north true south false east true age 7 up false west true 1366 fire north true south false east true age 7 up false west false 1367 fire north false south true east true age 7 up true west true 1368 fire north false south true east true age 7 up true west false 1369 fire north false south true east true age 7 up false west true 1370 fire north false south true east true age 7 up false west false 1371 fire north false south false east true age 7 up true west true 1372 fire north false south false east true age 7 up true west false 1373 fire north false south false east true age 7 up false west true 1374 fire north false south false east true age 7 up false west false 1375 fire north true south true east false age 7 up true west true 1376 fire north true south true east false age 7 up true west false 1377 fire north true south true east false age 7 up false west true 1378 fire north true south true east false age 7 up false west false 1379 fire north true south false east false age 7 up true west true 1380 fire north true south false east false age 7 up true west false 1381 fire north true south false east false age 7 up false west true 1382 fire north true south false east false age 7 up false west false 1383 fire north false south true east false age 7 up true west true 1384 fire north false south true east false age 7 up true west false 1385 fire north false south true east false age 7 up false west true 1386 fire north false south true east false age 7 up false west false 1387 fire north false south false east false age 7 up true west true 1388 fire north false south false east false age 7 up true west false 1389 fire north false south false east false age 7 up false west true 1390 fire north false south false east false age 7 up false west false 1391 fire north true south true east true age 8 up true west true 1392 fire north true south true east true age 8 up true west false 1393 fire north true south true east true age 8 up false west true 1394 fire north true south true east true age 8 up false west false 1395 fire north true south false east true age 8 up true west true 1396 fire north true south false east true age 8 up true west false 1397 fire north true south false east true age 8 up false west true 1398 fire north true south false east true age 8 up false west false 1399 fire north false south true east true age 8 up true west true 1400 fire north false south true east true age 8 up true west false 1401 fire north false south true east true age 8 up false west true 1402 fire north false south true east true age 8 up false west false 1403 fire north false south false east true age 8 up true west true 1404 fire north false south false east true age 8 up true west false 1405 fire north false south false east true age 8 up false west true 1406 fire north false south false east true age 8 up false west false 1407 fire north true south true east false age 8 up true west true 1408 fire north true south true east false age 8 up true west false 1409 fire north true south true east false age 8 up false west true 1410 fire north true south true east false age 8 up false west false 1411 fire north true south false east false age 8 up true west true 1412 fire north true south false east false age 8 up true west false 1413 fire north true south false east false age 8 up false west true 1414 fire north true south false east false age 8 up false west false 1415 fire north false south true east false age 8 up true west true 1416 fire north false south true east false age 8 up true west false 1417 fire north false south true east false age 8 up false west true 1418 fire north false south true east false age 8 up false west false 1419 fire north false south false east false age 8 up true west true 1420 fire north false south false east false age 8 up true west false 1421 fire north false south false east false age 8 up false west true 1422 fire north false south false east false age 8 up false west false 1423 fire north true south true east true age 9 up true west true 1424 fire north true south true east true age 9 up true west false 1425 fire north true south true east true age 9 up false west true 1426 fire north true south true east true age 9 up false west false 1427 fire north true south false east true age 9 up true west true 1428 fire north true south false east true age 9 up true west false 1429 fire north true south false east true age 9 up false west true 1430 fire north true south false east true age 9 up false west false 1431 fire north false south true east true age 9 up true west true 1432 fire north false south true east true age 9 up true west false 1433 fire north false south true east true age 9 up false west true 1434 fire north false south true east true age 9 up false west false 1435 fire north false south false east true age 9 up true west true 1436 fire north false south false east true age 9 up true west false 1437 fire north false south false east true age 9 up false west true 1438 fire north false south false east true age 9 up false west false 1439 fire north true south true east false age 9 up true west true 1440 fire north true south true east false age 9 up true west false 1441 fire north true south true east false age 9 up false west true 1442 fire north true south true east false age 9 up false west false 1443 fire north true south false east false age 9 up true west true 1444 fire north true south false east false age 9 up true west false 1445 fire north true south false east false age 9 up false west true 1446 fire north true south false east false age 9 up false west false 1447 fire north false south true east false age 9 up true west true 1448 fire north false south true east false age 9 up true west false 1449 fire north false south true east false age 9 up false west true 1450 fire north false south true east false age 9 up false west false 1451 fire north false south false east false age 9 up true west true 1452 fire north false south false east false age 9 up true west false 1453 fire north false south false east false age 9 up false west true 1454 fire north false south false east false age 9 up false west false 1455 fire north true south true east true age 10 up true west true 1456 fire north true south true east true age 10 up true west false 1457 fire north true south true east true age 10 up false west true 1458 fire north true south true east true age 10 up false west false 1459 fire north true south false east true age 10 up true west true 1460 fire north true south false east true age 10 up true west false 1461 fire north true south false east true age 10 up false west true 1462 fire north true south false east true age 10 up false west false 1463 fire north false south true east true age 10 up true west true 1464 fire north false south true east true age 10 up true west false 1465 fire north false south true east true age 10 up false west true 1466 fire north false south true east true age 10 up false west false 1467 fire north false south false east true age 10 up true west true 1468 fire north false south false east true age 10 up true west false 1469 fire north false south false east true age 10 up false west true 1470 fire north false south false east true age 10 up false west false 1471 fire north true south true east false age 10 up true west true 1472 fire north true south true east false age 10 up true west false 1473 fire north true south true east false age 10 up false west true 1474 fire north true south true east false age 10 up false west false 1475 fire north true south false east false age 10 up true west true 1476 fire north true south false east false age 10 up true west false 1477 fire north true south false east false age 10 up false west true 1478 fire north true south false east false age 10 up false west false 1479 fire north false south true east false age 10 up true west true 1480 fire north false south true east false age 10 up true west false 1481 fire north false south true east false age 10 up false west true 1482 fire north false south true east false age 10 up false west false 1483 fire north false south false east false age 10 up true west true 1484 fire north false south false east false age 10 up true west false 1485 fire north false south false east false age 10 up false west true 1486 fire north false south false east false age 10 up false west false 1487 fire north true south true east true age 11 up true west true 1488 fire north true south true east true age 11 up true west false 1489 fire north true south true east true age 11 up false west true 1490 fire north true south true east true age 11 up false west false 1491 fire north true south false east true age 11 up true west true 1492 fire north true south false east true age 11 up true west false 1493 fire north true south false east true age 11 up false west true 1494 fire north true south false east true age 11 up false west false 1495 fire north false south true east true age 11 up true west true 1496 fire north false south true east true age 11 up true west false 1497 fire north false south true east true age 11 up false west true 1498 fire north false south true east true age 11 up false west false 1499 fire north false south false east true age 11 up true west true 1500 fire north false south false east true age 11 up true west false 1501 fire north false south false east true age 11 up false west true 1502 fire north false south false east true age 11 up false west false 1503 fire north true south true east false age 11 up true west true 1504 fire north true south true east false age 11 up true west false 1505 fire north true south true east false age 11 up false west true 1506 fire north true south true east false age 11 up false west false 1507 fire north true south false east false age 11 up true west true 1508 fire north true south false east false age 11 up true west false 1509 fire north true south false east false age 11 up false west true 1510 fire north true south false east false age 11 up false west false 1511 fire north false south true east false age 11 up true west true 1512 fire north false south true east false age 11 up true west false 1513 fire north false south true east false age 11 up false west true 1514 fire north false south true east false age 11 up false west false 1515 fire north false south false east false age 11 up true west true 1516 fire north false south false east false age 11 up true west false 1517 fire north false south false east false age 11 up false west true 1518 fire north false south false east false age 11 up false west false 1519 fire north true south true east true age 12 up true west true 1520 fire north true south true east true age 12 up true west false 1521 fire north true south true east true age 12 up false west true 1522 fire north true south true east true age 12 up false west false 1523 fire north true south false east true age 12 up true west true 1524 fire north true south false east true age 12 up true west false 1525 fire north true south false east true age 12 up false west true 1526 fire north true south false east true age 12 up false west false 1527 fire north false south true east true age 12 up true west true 1528 fire north false south true east true age 12 up true west false 1529 fire north false south true east true age 12 up false west true 1530 fire north false south true east true age 12 up false west false 1531 fire north false south false east true age 12 up true west true 1532 fire north false south false east true age 12 up true west false 1533 fire north false south false east true age 12 up false west true 1534 fire north false south false east true age 12 up false west false 1535 fire north true south true east false age 12 up true west true 1536 fire north true south true east false age 12 up true west false 1537 fire north true south true east false age 12 up false west true 1538 fire north true south true east false age 12 up false west false 1539 fire north true south false east false age 12 up true west true 1540 fire north true south false east false age 12 up true west false 1541 fire north true south false east false age 12 up false west true 1542 fire north true south false east false age 12 up false west false 1543 fire north false south true east false age 12 up true west true 1544 fire north false south true east false age 12 up true west false 1545 fire north false south true east false age 12 up false west true 1546 fire north false south true east false age 12 up false west false 1547 fire north false south false east false age 12 up true west true 1548 fire north false south false east false age 12 up true west false 1549 fire north false south false east false age 12 up false west true 1550 fire north false south false east false age 12 up false west false 1551 fire north true south true east true age 13 up true west true 1552 fire north true south true east true age 13 up true west false 1553 fire north true south true east true age 13 up false west true 1554 fire north true south true east true age 13 up false west false 1555 fire north true south false east true age 13 up true west true 1556 fire north true south false east true age 13 up true west false 1557 fire north true south false east true age 13 up false west true 1558 fire north true south false east true age 13 up false west false 1559 fire north false south true east true age 13 up true west true 1560 fire north false south true east true age 13 up true west false 1561 fire north false south true east true age 13 up false west true 1562 fire north false south true east true age 13 up false west false 1563 fire north false south false east true age 13 up true west true 1564 fire north false south false east true age 13 up true west false 1565 fire north false south false east true age 13 up false west true 1566 fire north false south false east true age 13 up false west false 1567 fire north true south true east false age 13 up true west true 1568 fire north true south true east false age 13 up true west false 1569 fire north true south true east false age 13 up false west true 1570 fire north true south true east false age 13 up false west false 1571 fire north true south false east false age 13 up true west true 1572 fire north true south false east false age 13 up true west false 1573 fire north true south false east false age 13 up false west true 1574 fire north true south false east false age 13 up false west false 1575 fire north false south true east false age 13 up true west true 1576 fire north false south true east false age 13 up true west false 1577 fire north false south true east false age 13 up false west true 1578 fire north false south true east false age 13 up false west false 1579 fire north false south false east false age 13 up true west true 1580 fire north false south false east false age 13 up true west false 1581 fire north false south false east false age 13 up false west true 1582 fire north false south false east false age 13 up false west false 1583 fire north true south true east true age 14 up true west true 1584 fire north true south true east true age 14 up true west false 1585 fire north true south true east true age 14 up false west true 1586 fire north true south true east true age 14 up false west false 1587 fire north true south false east true age 14 up true west true 1588 fire north true south false east true age 14 up true west false 1589 fire north true south false east true age 14 up false west true 1590 fire north true south false east true age 14 up false west false 1591 fire north false south true east true age 14 up true west true 1592 fire north false south true east true age 14 up true west false 1593 fire north false south true east true age 14 up false west true 1594 fire north false south true east true age 14 up false west false 1595 fire north false south false east true age 14 up true west true 1596 fire north false south false east true age 14 up true west false 1597 fire north false south false east true age 14 up false west true 1598 fire north false south false east true age 14 up false west false 1599 fire north true south true east false age 14 up true west true 1600 fire north true south true east false age 14 up true west false 1601 fire north true south true east false age 14 up false west true 1602 fire north true south true east false age 14 up false west false 1603 fire north true south false east false age 14 up true west true 1604 fire north true south false east false age 14 up true west false 1605 fire north true south false east false age 14 up false west true 1606 fire north true south false east false age 14 up false west false 1607 fire north false south true east false age 14 up true west true 1608 fire north false south true east false age 14 up true west false 1609 fire north false south true east false age 14 up false west true 1610 fire north false south true east false age 14 up false west false 1611 fire north false south false east false age 14 up true west true 1612 fire north false south false east false age 14 up true west false 1613 fire north false south false east false age 14 up false west true 1614 fire north false south false east false age 14 up false west false 1615 fire north true south true east true age 15 up true west true 1616 fire north true south true east true age 15 up true west false 1617 fire north true south true east true age 15 up false west true 1618 fire north true south true east true age 15 up false west false 1619 fire north true south false east true age 15 up true west true 1620 fire north true south false east true age 15 up true west false 1621 fire north true south false east true age 15 up false west true 1622 fire north true south false east true age 15 up false west false 1623 fire north false south true east true age 15 up true west true 1624 fire north false south true east true age 15 up true west false 1625 fire north false south true east true age 15 up false west true 1626 fire north false south true east true age 15 up false west false 1627 fire north false south false east true age 15 up true west true 1628 fire north false south false east true age 15 up true west false 1629 fire north false south false east true age 15 up false west true 1630 fire north false south false east true age 15 up false west false 1631 fire north true south true east false age 15 up true west true 1632 fire north true south true east false age 15 up true west false 1633 fire north true south true east false age 15 up false west true 1634 fire north true south true east false age 15 up false west false 1635 fire north true south false east false age 15 up true west true 1636 fire north true south false east false age 15 up true west false 1637 fire north true south false east false age 15 up false west true 1638 fire north true south false east false age 15 up false west false 1639 fire north false south true east false age 15 up true west true 1640 fire north false south true east false age 15 up true west false 1641 fire north false south true east false age 15 up false west true 1642 fire north false south true east false age 15 up false west false 1643 fire north false south false east false age 15 up true west true 1644 fire north false south false east false age 15 up true west false 1645 fire north false south false east false age 15 up false west true 1646 fire north false south false east false age 15 up false west false 1647 spawner 1648 oak_stairs facing north waterlogged true shape straight half top 1649 oak_stairs facing north waterlogged false shape straight half top 1650 oak_stairs facing north waterlogged true shape inner_left half top 1651 oak_stairs facing north waterlogged false shape inner_left half top 1652 oak_stairs facing north waterlogged true shape inner_right half top 1653 oak_stairs facing north waterlogged false shape inner_right half top 1654 oak_stairs facing north waterlogged true shape outer_left half top 1655 oak_stairs facing north waterlogged false shape outer_left half top 1656 oak_stairs facing north waterlogged true shape outer_right half top 1657 oak_stairs facing north waterlogged false shape outer_right half top 1658 oak_stairs facing north waterlogged true shape straight half bottom 1659 oak_stairs facing north waterlogged false shape straight half bottom 1660 oak_stairs facing north waterlogged true shape inner_left half bottom 1661 oak_stairs facing north waterlogged false shape inner_left half bottom 1662 oak_stairs facing north waterlogged true shape inner_right half bottom 1663 oak_stairs facing north waterlogged false shape inner_right half bottom 1664 oak_stairs facing north waterlogged true shape outer_left half bottom 1665 oak_stairs facing north waterlogged false shape outer_left half bottom 1666 oak_stairs facing north waterlogged true shape outer_right half bottom 1667 oak_stairs facing north waterlogged false shape outer_right half bottom 1668 oak_stairs facing south waterlogged true shape straight half top 1669 oak_stairs facing south waterlogged false shape straight half top 1670 oak_stairs facing south waterlogged true shape inner_left half top 1671 oak_stairs facing south waterlogged false shape inner_left half top 1672 oak_stairs facing south waterlogged true shape inner_right half top 1673 oak_stairs facing south waterlogged false shape inner_right half top 1674 oak_stairs facing south waterlogged true shape outer_left half top 1675 oak_stairs facing south waterlogged false shape outer_left half top 1676 oak_stairs facing south waterlogged true shape outer_right half top 1677 oak_stairs facing south waterlogged false shape outer_right half top 1678 oak_stairs facing south waterlogged true shape straight half bottom 1679 oak_stairs facing south waterlogged false shape straight half bottom 1680 oak_stairs facing south waterlogged true shape inner_left half bottom 1681 oak_stairs facing south waterlogged false shape inner_left half bottom 1682 oak_stairs facing south waterlogged true shape inner_right half bottom 1683 oak_stairs facing south waterlogged false shape inner_right half bottom 1684 oak_stairs facing south waterlogged true shape outer_left half bottom 1685 oak_stairs facing south waterlogged false shape outer_left half bottom 1686 oak_stairs facing south waterlogged true shape outer_right half bottom 1687 oak_stairs facing south waterlogged false shape outer_right half bottom 1688 oak_stairs facing west waterlogged true shape straight half top 1689 oak_stairs facing west waterlogged false shape straight half top 1690 oak_stairs facing west waterlogged true shape inner_left half top 1691 oak_stairs facing west waterlogged false shape inner_left half top 1692 oak_stairs facing west waterlogged true shape inner_right half top 1693 oak_stairs facing west waterlogged false shape inner_right half top 1694 oak_stairs facing west waterlogged true shape outer_left half top 1695 oak_stairs facing west waterlogged false shape outer_left half top 1696 oak_stairs facing west waterlogged true shape outer_right half top 1697 oak_stairs facing west waterlogged false shape outer_right half top 1698 oak_stairs facing west waterlogged true shape straight half bottom 1699 oak_stairs facing west waterlogged false shape straight half bottom 1700 oak_stairs facing west waterlogged true shape inner_left half bottom 1701 oak_stairs facing west waterlogged false shape inner_left half bottom 1702 oak_stairs facing west waterlogged true shape inner_right half bottom 1703 oak_stairs facing west waterlogged false shape inner_right half bottom 1704 oak_stairs facing west waterlogged true shape outer_left half bottom 1705 oak_stairs facing west waterlogged false shape outer_left half bottom 1706 oak_stairs facing west waterlogged true shape outer_right half bottom 1707 oak_stairs facing west waterlogged false shape outer_right half bottom 1708 oak_stairs facing east waterlogged true shape straight half top 1709 oak_stairs facing east waterlogged false shape straight half top 1710 oak_stairs facing east waterlogged true shape inner_left half top 1711 oak_stairs facing east waterlogged false shape inner_left half top 1712 oak_stairs facing east waterlogged true shape inner_right half top 1713 oak_stairs facing east waterlogged false shape inner_right half top 1714 oak_stairs facing east waterlogged true shape outer_left half top 1715 oak_stairs facing east waterlogged false shape outer_left half top 1716 oak_stairs facing east waterlogged true shape outer_right half top 1717 oak_stairs facing east waterlogged false shape outer_right half top 1718 oak_stairs facing east waterlogged true shape straight half bottom 1719 oak_stairs facing east waterlogged false shape straight half bottom 1720 oak_stairs facing east waterlogged true shape inner_left half bottom 1721 oak_stairs facing east waterlogged false shape inner_left half bottom 1722 oak_stairs facing east waterlogged true shape inner_right half bottom 1723 oak_stairs facing east waterlogged false shape inner_right half bottom 1724 oak_stairs facing east waterlogged true shape outer_left half bottom 1725 oak_stairs facing east waterlogged false shape outer_left half bottom 1726 oak_stairs facing east waterlogged true shape outer_right half bottom 1727 oak_stairs facing east waterlogged false shape outer_right half bottom 1728 chest facing north waterlogged true type single 1729 chest facing north waterlogged false type single 1730 chest facing north waterlogged true type left 1731 chest facing north waterlogged false type left 1732 chest facing north waterlogged true type right 1733 chest facing north waterlogged false type right 1734 chest facing south waterlogged true type single 1735 chest facing south waterlogged false type single 1736 chest facing south waterlogged true type left 1737 chest facing south waterlogged false type left 1738 chest facing south waterlogged true type right 1739 chest facing south waterlogged false type right 1740 chest facing west waterlogged true type single 1741 chest facing west waterlogged false type single 1742 chest facing west waterlogged true type left 1743 chest facing west waterlogged false type left 1744 chest facing west waterlogged true type right 1745 chest facing west waterlogged false type right 1746 chest facing east waterlogged true type single 1747 chest facing east waterlogged false type single 1748 chest facing east waterlogged true type left 1749 chest facing east waterlogged false type left 1750 chest facing east waterlogged true type right 1751 chest facing east waterlogged false type right 1752 redstone_wire south up east up north up power 0 west up 1753 redstone_wire south up east up north up power 0 west side 1754 redstone_wire south up east up north up power 0 west none 1755 redstone_wire south side east up north up power 0 west up 1756 redstone_wire south side east up north up power 0 west side 1757 redstone_wire south side east up north up power 0 west none 1758 redstone_wire south none east up north up power 0 west up 1759 redstone_wire south none east up north up power 0 west side 1760 redstone_wire south none east up north up power 0 west none 1761 redstone_wire south up east up north up power 1 west up 1762 redstone_wire south up east up north up power 1 west side 1763 redstone_wire south up east up north up power 1 west none 1764 redstone_wire south side east up north up power 1 west up 1765 redstone_wire south side east up north up power 1 west side 1766 redstone_wire south side east up north up power 1 west none 1767 redstone_wire south none east up north up power 1 west up 1768 redstone_wire south none east up north up power 1 west side 1769 redstone_wire south none east up north up power 1 west none 1770 redstone_wire south up east up north up power 2 west up 1771 redstone_wire south up east up north up power 2 west side 1772 redstone_wire south up east up north up power 2 west none 1773 redstone_wire south side east up north up power 2 west up 1774 redstone_wire south side east up north up power 2 west side 1775 redstone_wire south side east up north up power 2 west none 1776 redstone_wire south none east up north up power 2 west up 1777 redstone_wire south none east up north up power 2 west side 1778 redstone_wire south none east up north up power 2 west none 1779 redstone_wire south up east up north up power 3 west up 1780 redstone_wire south up east up north up power 3 west side 1781 redstone_wire south up east up north up power 3 west none 1782 redstone_wire south side east up north up power 3 west up 1783 redstone_wire south side east up north up power 3 west side 1784 redstone_wire south side east up north up power 3 west none 1785 redstone_wire south none east up north up power 3 west up 1786 redstone_wire south none east up north up power 3 west side 1787 redstone_wire south none east up north up power 3 west none 1788 redstone_wire south up east up north up power 4 west up 1789 redstone_wire south up east up north up power 4 west side 1790 redstone_wire south up east up north up power 4 west none 1791 redstone_wire south side east up north up power 4 west up 1792 redstone_wire south side east up north up power 4 west side 1793 redstone_wire south side east up north up power 4 west none 1794 redstone_wire south none east up north up power 4 west up 1795 redstone_wire south none east up north up power 4 west side 1796 redstone_wire south none east up north up power 4 west none 1797 redstone_wire south up east up north up power 5 west up 1798 redstone_wire south up east up north up power 5 west side 1799 redstone_wire south up east up north up power 5 west none 1800 redstone_wire south side east up north up power 5 west up 1801 redstone_wire south side east up north up power 5 west side 1802 redstone_wire south side east up north up power 5 west none 1803 redstone_wire south none east up north up power 5 west up 1804 redstone_wire south none east up north up power 5 west side 1805 redstone_wire south none east up north up power 5 west none 1806 redstone_wire south up east up north up power 6 west up 1807 redstone_wire south up east up north up power 6 west side 1808 redstone_wire south up east up north up power 6 west none 1809 redstone_wire south side east up north up power 6 west up 1810 redstone_wire south side east up north up power 6 west side 1811 redstone_wire south side east up north up power 6 west none 1812 redstone_wire south none east up north up power 6 west up 1813 redstone_wire south none east up north up power 6 west side 1814 redstone_wire south none east up north up power 6 west none 1815 redstone_wire south up east up north up power 7 west up 1816 redstone_wire south up east up north up power 7 west side 1817 redstone_wire south up east up north up power 7 west none 1818 redstone_wire south side east up north up power 7 west up 1819 redstone_wire south side east up north up power 7 west side 1820 redstone_wire south side east up north up power 7 west none 1821 redstone_wire south none east up north up power 7 west up 1822 redstone_wire south none east up north up power 7 west side 1823 redstone_wire south none east up north up power 7 west none 1824 redstone_wire south up east up north up power 8 west up 1825 redstone_wire south up east up north up power 8 west side 1826 redstone_wire south up east up north up power 8 west none 1827 redstone_wire south side east up north up power 8 west up 1828 redstone_wire south side east up north up power 8 west side 1829 redstone_wire south side east up north up power 8 west none 1830 redstone_wire south none east up north up power 8 west up 1831 redstone_wire south none east up north up power 8 west side 1832 redstone_wire south none east up north up power 8 west none 1833 redstone_wire south up east up north up power 9 west up 1834 redstone_wire south up east up north up power 9 west side 1835 redstone_wire south up east up north up power 9 west none 1836 redstone_wire south side east up north up power 9 west up 1837 redstone_wire south side east up north up power 9 west side 1838 redstone_wire south side east up north up power 9 west none 1839 redstone_wire south none east up north up power 9 west up 1840 redstone_wire south none east up north up power 9 west side 1841 redstone_wire south none east up north up power 9 west none 1842 redstone_wire south up east up north up power 10 west up 1843 redstone_wire south up east up north up power 10 west side 1844 redstone_wire south up east up north up power 10 west none 1845 redstone_wire south side east up north up power 10 west up 1846 redstone_wire south side east up north up power 10 west side 1847 redstone_wire south side east up north up power 10 west none 1848 redstone_wire south none east up north up power 10 west up 1849 redstone_wire south none east up north up power 10 west side 1850 redstone_wire south none east up north up power 10 west none 1851 redstone_wire south up east up north up power 11 west up 1852 redstone_wire south up east up north up power 11 west side 1853 redstone_wire south up east up north up power 11 west none 1854 redstone_wire south side east up north up power 11 west up 1855 redstone_wire south side east up north up power 11 west side 1856 redstone_wire south side east up north up power 11 west none 1857 redstone_wire south none east up north up power 11 west up 1858 redstone_wire south none east up north up power 11 west side 1859 redstone_wire south none east up north up power 11 west none 1860 redstone_wire south up east up north up power 12 west up 1861 redstone_wire south up east up north up power 12 west side 1862 redstone_wire south up east up north up power 12 west none 1863 redstone_wire south side east up north up power 12 west up 1864 redstone_wire south side east up north up power 12 west side 1865 redstone_wire south side east up north up power 12 west none 1866 redstone_wire south none east up north up power 12 west up 1867 redstone_wire south none east up north up power 12 west side 1868 redstone_wire south none east up north up power 12 west none 1869 redstone_wire south up east up north up power 13 west up 1870 redstone_wire south up east up north up power 13 west side 1871 redstone_wire south up east up north up power 13 west none 1872 redstone_wire south side east up north up power 13 west up 1873 redstone_wire south side east up north up power 13 west side 1874 redstone_wire south side east up north up power 13 west none 1875 redstone_wire south none east up north up power 13 west up 1876 redstone_wire south none east up north up power 13 west side 1877 redstone_wire south none east up north up power 13 west none 1878 redstone_wire south up east up north up power 14 west up 1879 redstone_wire south up east up north up power 14 west side 1880 redstone_wire south up east up north up power 14 west none 1881 redstone_wire south side east up north up power 14 west up 1882 redstone_wire south side east up north up power 14 west side 1883 redstone_wire south side east up north up power 14 west none 1884 redstone_wire south none east up north up power 14 west up 1885 redstone_wire south none east up north up power 14 west side 1886 redstone_wire south none east up north up power 14 west none 1887 redstone_wire south up east up north up power 15 west up 1888 redstone_wire south up east up north up power 15 west side 1889 redstone_wire south up east up north up power 15 west none 1890 redstone_wire south side east up north up power 15 west up 1891 redstone_wire south side east up north up power 15 west side 1892 redstone_wire south side east up north up power 15 west none 1893 redstone_wire south none east up north up power 15 west up 1894 redstone_wire south none east up north up power 15 west side 1895 redstone_wire south none east up north up power 15 west none 1896 redstone_wire south up east up north side power 0 west up 1897 redstone_wire south up east up north side power 0 west side 1898 redstone_wire south up east up north side power 0 west none 1899 redstone_wire south side east up north side power 0 west up 1900 redstone_wire south side east up north side power 0 west side 1901 redstone_wire south side east up north side power 0 west none 1902 redstone_wire south none east up north side power 0 west up 1903 redstone_wire south none east up north side power 0 west side 1904 redstone_wire south none east up north side power 0 west none 1905 redstone_wire south up east up north side power 1 west up 1906 redstone_wire south up east up north side power 1 west side 1907 redstone_wire south up east up north side power 1 west none 1908 redstone_wire south side east up north side power 1 west up 1909 redstone_wire south side east up north side power 1 west side 1910 redstone_wire south side east up north side power 1 west none 1911 redstone_wire south none east up north side power 1 west up 1912 redstone_wire south none east up north side power 1 west side 1913 redstone_wire south none east up north side power 1 west none 1914 redstone_wire south up east up north side power 2 west up 1915 redstone_wire south up east up north side power 2 west side 1916 redstone_wire south up east up north side power 2 west none 1917 redstone_wire south side east up north side power 2 west up 1918 redstone_wire south side east up north side power 2 west side 1919 redstone_wire south side east up north side power 2 west none 1920 redstone_wire south none east up north side power 2 west up 1921 redstone_wire south none east up north side power 2 west side 1922 redstone_wire south none east up north side power 2 west none 1923 redstone_wire south up east up north side power 3 west up 1924 redstone_wire south up east up north side power 3 west side 1925 redstone_wire south up east up north side power 3 west none 1926 redstone_wire south side east up north side power 3 west up 1927 redstone_wire south side east up north side power 3 west side 1928 redstone_wire south side east up north side power 3 west none 1929 redstone_wire south none east up north side power 3 west up 1930 redstone_wire south none east up north side power 3 west side 1931 redstone_wire south none east up north side power 3 west none 1932 redstone_wire south up east up north side power 4 west up 1933 redstone_wire south up east up north side power 4 west side 1934 redstone_wire south up east up north side power 4 west none 1935 redstone_wire south side east up north side power 4 west up 1936 redstone_wire south side east up north side power 4 west side 1937 redstone_wire south side east up north side power 4 west none 1938 redstone_wire south none east up north side power 4 west up 1939 redstone_wire south none east up north side power 4 west side 1940 redstone_wire south none east up north side power 4 west none 1941 redstone_wire south up east up north side power 5 west up 1942 redstone_wire south up east up north side power 5 west side 1943 redstone_wire south up east up north side power 5 west none 1944 redstone_wire south side east up north side power 5 west up 1945 redstone_wire south side east up north side power 5 west side 1946 redstone_wire south side east up north side power 5 west none 1947 redstone_wire south none east up north side power 5 west up 1948 redstone_wire south none east up north side power 5 west side 1949 redstone_wire south none east up north side power 5 west none 1950 redstone_wire south up east up north side power 6 west up 1951 redstone_wire south up east up north side power 6 west side 1952 redstone_wire south up east up north side power 6 west none 1953 redstone_wire south side east up north side power 6 west up 1954 redstone_wire south side east up north side power 6 west side 1955 redstone_wire south side east up north side power 6 west none 1956 redstone_wire south none east up north side power 6 west up 1957 redstone_wire south none east up north side power 6 west side 1958 redstone_wire south none east up north side power 6 west none 1959 redstone_wire south up east up north side power 7 west up 1960 redstone_wire south up east up north side power 7 west side 1961 redstone_wire south up east up north side power 7 west none 1962 redstone_wire south side east up north side power 7 west up 1963 redstone_wire south side east up north side power 7 west side 1964 redstone_wire south side east up north side power 7 west none 1965 redstone_wire south none east up north side power 7 west up 1966 redstone_wire south none east up north side power 7 west side 1967 redstone_wire south none east up north side power 7 west none 1968 redstone_wire south up east up north side power 8 west up 1969 redstone_wire south up east up north side power 8 west side 1970 redstone_wire south up east up north side power 8 west none 1971 redstone_wire south side east up north side power 8 west up 1972 redstone_wire south side east up north side power 8 west side 1973 redstone_wire south side east up north side power 8 west none 1974 redstone_wire south none east up north side power 8 west up 1975 redstone_wire south none east up north side power 8 west side 1976 redstone_wire south none east up north side power 8 west none 1977 redstone_wire south up east up north side power 9 west up 1978 redstone_wire south up east up north side power 9 west side 1979 redstone_wire south up east up north side power 9 west none 1980 redstone_wire south side east up north side power 9 west up 1981 redstone_wire south side east up north side power 9 west side 1982 redstone_wire south side east up north side power 9 west none 1983 redstone_wire south none east up north side power 9 west up 1984 redstone_wire south none east up north side power 9 west side 1985 redstone_wire south none east up north side power 9 west none 1986 redstone_wire south up east up north side power 10 west up 1987 redstone_wire south up east up north side power 10 west side 1988 redstone_wire south up east up north side power 10 west none 1989 redstone_wire south side east up north side power 10 west up 1990 redstone_wire south side east up north side power 10 west side 1991 redstone_wire south side east up north side power 10 west none 1992 redstone_wire south none east up north side power 10 west up 1993 redstone_wire south none east up north side power 10 west side 1994 redstone_wire south none east up north side power 10 west none 1995 redstone_wire south up east up north side power 11 west up 1996 redstone_wire south up east up north side power 11 west side 1997 redstone_wire south up east up north side power 11 west none 1998 redstone_wire south side east up north side power 11 west up 1999 redstone_wire south side east up north side power 11 west side 2000 redstone_wire south side east up north side power 11 west none 2001 redstone_wire south none east up north side power 11 west up 2002 redstone_wire south none east up north side power 11 west side 2003 redstone_wire south none east up north side power 11 west none 2004 redstone_wire south up east up north side power 12 west up 2005 redstone_wire south up east up north side power 12 west side 2006 redstone_wire south up east up north side power 12 west none 2007 redstone_wire south side east up north side power 12 west up 2008 redstone_wire south side east up north side power 12 west side 2009 redstone_wire south side east up north side power 12 west none 2010 redstone_wire south none east up north side power 12 west up 2011 redstone_wire south none east up north side power 12 west side 2012 redstone_wire south none east up north side power 12 west none 2013 redstone_wire south up east up north side power 13 west up 2014 redstone_wire south up east up north side power 13 west side 2015 redstone_wire south up east up north side power 13 west none 2016 redstone_wire south side east up north side power 13 west up 2017 redstone_wire south side east up north side power 13 west side 2018 redstone_wire south side east up north side power 13 west none 2019 redstone_wire south none east up north side power 13 west up 2020 redstone_wire south none east up north side power 13 west side 2021 redstone_wire south none east up north side power 13 west none 2022 redstone_wire south up east up north side power 14 west up 2023 redstone_wire south up east up north side power 14 west side 2024 redstone_wire south up east up north side power 14 west none 2025 redstone_wire south side east up north side power 14 west up 2026 redstone_wire south side east up north side power 14 west side 2027 redstone_wire south side east up north side power 14 west none 2028 redstone_wire south none east up north side power 14 west up 2029 redstone_wire south none east up north side power 14 west side 2030 redstone_wire south none east up north side power 14 west none 2031 redstone_wire south up east up north side power 15 west up 2032 redstone_wire south up east up north side power 15 west side 2033 redstone_wire south up east up north side power 15 west none 2034 redstone_wire south side east up north side power 15 west up 2035 redstone_wire south side east up north side power 15 west side 2036 redstone_wire south side east up north side power 15 west none 2037 redstone_wire south none east up north side power 15 west up 2038 redstone_wire south none east up north side power 15 west side 2039 redstone_wire south none east up north side power 15 west none 2040 redstone_wire south up east up north none power 0 west up 2041 redstone_wire south up east up north none power 0 west side 2042 redstone_wire south up east up north none power 0 west none 2043 redstone_wire south side east up north none power 0 west up 2044 redstone_wire south side east up north none power 0 west side 2045 redstone_wire south side east up north none power 0 west none 2046 redstone_wire south none east up north none power 0 west up 2047 redstone_wire south none east up north none power 0 west side 2048 redstone_wire south none east up north none power 0 west none 2049 redstone_wire south up east up north none power 1 west up 2050 redstone_wire south up east up north none power 1 west side 2051 redstone_wire south up east up north none power 1 west none 2052 redstone_wire south side east up north none power 1 west up 2053 redstone_wire south side east up north none power 1 west side 2054 redstone_wire south side east up north none power 1 west none 2055 redstone_wire south none east up north none power 1 west up 2056 redstone_wire south none east up north none power 1 west side 2057 redstone_wire south none east up north none power 1 west none 2058 redstone_wire south up east up north none power 2 west up 2059 redstone_wire south up east up north none power 2 west side 2060 redstone_wire south up east up north none power 2 west none 2061 redstone_wire south side east up north none power 2 west up 2062 redstone_wire south side east up north none power 2 west side 2063 redstone_wire south side east up north none power 2 west none 2064 redstone_wire south none east up north none power 2 west up 2065 redstone_wire south none east up north none power 2 west side 2066 redstone_wire south none east up north none power 2 west none 2067 redstone_wire south up east up north none power 3 west up 2068 redstone_wire south up east up north none power 3 west side 2069 redstone_wire south up east up north none power 3 west none 2070 redstone_wire south side east up north none power 3 west up 2071 redstone_wire south side east up north none power 3 west side 2072 redstone_wire south side east up north none power 3 west none 2073 redstone_wire south none east up north none power 3 west up 2074 redstone_wire south none east up north none power 3 west side 2075 redstone_wire south none east up north none power 3 west none 2076 redstone_wire south up east up north none power 4 west up 2077 redstone_wire south up east up north none power 4 west side 2078 redstone_wire south up east up north none power 4 west none 2079 redstone_wire south side east up north none power 4 west up 2080 redstone_wire south side east up north none power 4 west side 2081 redstone_wire south side east up north none power 4 west none 2082 redstone_wire south none east up north none power 4 west up 2083 redstone_wire south none east up north none power 4 west side 2084 redstone_wire south none east up north none power 4 west none 2085 redstone_wire south up east up north none power 5 west up 2086 redstone_wire south up east up north none power 5 west side 2087 redstone_wire south up east up north none power 5 west none 2088 redstone_wire south side east up north none power 5 west up 2089 redstone_wire south side east up north none power 5 west side 2090 redstone_wire south side east up north none power 5 west none 2091 redstone_wire south none east up north none power 5 west up 2092 redstone_wire south none east up north none power 5 west side 2093 redstone_wire south none east up north none power 5 west none 2094 redstone_wire south up east up north none power 6 west up 2095 redstone_wire south up east up north none power 6 west side 2096 redstone_wire south up east up north none power 6 west none 2097 redstone_wire south side east up north none power 6 west up 2098 redstone_wire south side east up north none power 6 west side 2099 redstone_wire south side east up north none power 6 west none 2100 redstone_wire south none east up north none power 6 west up 2101 redstone_wire south none east up north none power 6 west side 2102 redstone_wire south none east up north none power 6 west none 2103 redstone_wire south up east up north none power 7 west up 2104 redstone_wire south up east up north none power 7 west side 2105 redstone_wire south up east up north none power 7 west none 2106 redstone_wire south side east up north none power 7 west up 2107 redstone_wire south side east up north none power 7 west side 2108 redstone_wire south side east up north none power 7 west none 2109 redstone_wire south none east up north none power 7 west up 2110 redstone_wire south none east up north none power 7 west side 2111 redstone_wire south none east up north none power 7 west none 2112 redstone_wire south up east up north none power 8 west up 2113 redstone_wire south up east up north none power 8 west side 2114 redstone_wire south up east up north none power 8 west none 2115 redstone_wire south side east up north none power 8 west up 2116 redstone_wire south side east up north none power 8 west side 2117 redstone_wire south side east up north none power 8 west none 2118 redstone_wire south none east up north none power 8 west up 2119 redstone_wire south none east up north none power 8 west side 2120 redstone_wire south none east up north none power 8 west none 2121 redstone_wire south up east up north none power 9 west up 2122 redstone_wire south up east up north none power 9 west side 2123 redstone_wire south up east up north none power 9 west none 2124 redstone_wire south side east up north none power 9 west up 2125 redstone_wire south side east up north none power 9 west side 2126 redstone_wire south side east up north none power 9 west none 2127 redstone_wire south none east up north none power 9 west up 2128 redstone_wire south none east up north none power 9 west side 2129 redstone_wire south none east up north none power 9 west none 2130 redstone_wire south up east up north none power 10 west up 2131 redstone_wire south up east up north none power 10 west side 2132 redstone_wire south up east up north none power 10 west none 2133 redstone_wire south side east up north none power 10 west up 2134 redstone_wire south side east up north none power 10 west side 2135 redstone_wire south side east up north none power 10 west none 2136 redstone_wire south none east up north none power 10 west up 2137 redstone_wire south none east up north none power 10 west side 2138 redstone_wire south none east up north none power 10 west none 2139 redstone_wire south up east up north none power 11 west up 2140 redstone_wire south up east up north none power 11 west side 2141 redstone_wire south up east up north none power 11 west none 2142 redstone_wire south side east up north none power 11 west up 2143 redstone_wire south side east up north none power 11 west side 2144 redstone_wire south side east up north none power 11 west none 2145 redstone_wire south none east up north none power 11 west up 2146 redstone_wire south none east up north none power 11 west side 2147 redstone_wire south none east up north none power 11 west none 2148 redstone_wire south up east up north none power 12 west up 2149 redstone_wire south up east up north none power 12 west side 2150 redstone_wire south up east up north none power 12 west none 2151 redstone_wire south side east up north none power 12 west up 2152 redstone_wire south side east up north none power 12 west side 2153 redstone_wire south side east up north none power 12 west none 2154 redstone_wire south none east up north none power 12 west up 2155 redstone_wire south none east up north none power 12 west side 2156 redstone_wire south none east up north none power 12 west none 2157 redstone_wire south up east up north none power 13 west up 2158 redstone_wire south up east up north none power 13 west side 2159 redstone_wire south up east up north none power 13 west none 2160 redstone_wire south side east up north none power 13 west up 2161 redstone_wire south side east up north none power 13 west side 2162 redstone_wire south side east up north none power 13 west none 2163 redstone_wire south none east up north none power 13 west up 2164 redstone_wire south none east up north none power 13 west side 2165 redstone_wire south none east up north none power 13 west none 2166 redstone_wire south up east up north none power 14 west up 2167 redstone_wire south up east up north none power 14 west side 2168 redstone_wire south up east up north none power 14 west none 2169 redstone_wire south side east up north none power 14 west up 2170 redstone_wire south side east up north none power 14 west side 2171 redstone_wire south side east up north none power 14 west none 2172 redstone_wire south none east up north none power 14 west up 2173 redstone_wire south none east up north none power 14 west side 2174 redstone_wire south none east up north none power 14 west none 2175 redstone_wire south up east up north none power 15 west up 2176 redstone_wire south up east up north none power 15 west side 2177 redstone_wire south up east up north none power 15 west none 2178 redstone_wire south side east up north none power 15 west up 2179 redstone_wire south side east up north none power 15 west side 2180 redstone_wire south side east up north none power 15 west none 2181 redstone_wire south none east up north none power 15 west up 2182 redstone_wire south none east up north none power 15 west side 2183 redstone_wire south none east up north none power 15 west none 2184 redstone_wire south up east side north up power 0 west up 2185 redstone_wire south up east side north up power 0 west side 2186 redstone_wire south up east side north up power 0 west none 2187 redstone_wire south side east side north up power 0 west up 2188 redstone_wire south side east side north up power 0 west side 2189 redstone_wire south side east side north up power 0 west none 2190 redstone_wire south none east side north up power 0 west up 2191 redstone_wire south none east side north up power 0 west side 2192 redstone_wire south none east side north up power 0 west none 2193 redstone_wire south up east side north up power 1 west up 2194 redstone_wire south up east side north up power 1 west side 2195 redstone_wire south up east side north up power 1 west none 2196 redstone_wire south side east side north up power 1 west up 2197 redstone_wire south side east side north up power 1 west side 2198 redstone_wire south side east side north up power 1 west none 2199 redstone_wire south none east side north up power 1 west up 2200 redstone_wire south none east side north up power 1 west side 2201 redstone_wire south none east side north up power 1 west none 2202 redstone_wire south up east side north up power 2 west up 2203 redstone_wire south up east side north up power 2 west side 2204 redstone_wire south up east side north up power 2 west none 2205 redstone_wire south side east side north up power 2 west up 2206 redstone_wire south side east side north up power 2 west side 2207 redstone_wire south side east side north up power 2 west none 2208 redstone_wire south none east side north up power 2 west up 2209 redstone_wire south none east side north up power 2 west side 2210 redstone_wire south none east side north up power 2 west none 2211 redstone_wire south up east side north up power 3 west up 2212 redstone_wire south up east side north up power 3 west side 2213 redstone_wire south up east side north up power 3 west none 2214 redstone_wire south side east side north up power 3 west up 2215 redstone_wire south side east side north up power 3 west side 2216 redstone_wire south side east side north up power 3 west none 2217 redstone_wire south none east side north up power 3 west up 2218 redstone_wire south none east side north up power 3 west side 2219 redstone_wire south none east side north up power 3 west none 2220 redstone_wire south up east side north up power 4 west up 2221 redstone_wire south up east side north up power 4 west side 2222 redstone_wire south up east side north up power 4 west none 2223 redstone_wire south side east side north up power 4 west up 2224 redstone_wire south side east side north up power 4 west side 2225 redstone_wire south side east side north up power 4 west none 2226 redstone_wire south none east side north up power 4 west up 2227 redstone_wire south none east side north up power 4 west side 2228 redstone_wire south none east side north up power 4 west none 2229 redstone_wire south up east side north up power 5 west up 2230 redstone_wire south up east side north up power 5 west side 2231 redstone_wire south up east side north up power 5 west none 2232 redstone_wire south side east side north up power 5 west up 2233 redstone_wire south side east side north up power 5 west side 2234 redstone_wire south side east side north up power 5 west none 2235 redstone_wire south none east side north up power 5 west up 2236 redstone_wire south none east side north up power 5 west side 2237 redstone_wire south none east side north up power 5 west none 2238 redstone_wire south up east side north up power 6 west up 2239 redstone_wire south up east side north up power 6 west side 2240 redstone_wire south up east side north up power 6 west none 2241 redstone_wire south side east side north up power 6 west up 2242 redstone_wire south side east side north up power 6 west side 2243 redstone_wire south side east side north up power 6 west none 2244 redstone_wire south none east side north up power 6 west up 2245 redstone_wire south none east side north up power 6 west side 2246 redstone_wire south none east side north up power 6 west none 2247 redstone_wire south up east side north up power 7 west up 2248 redstone_wire south up east side north up power 7 west side 2249 redstone_wire south up east side north up power 7 west none 2250 redstone_wire south side east side north up power 7 west up 2251 redstone_wire south side east side north up power 7 west side 2252 redstone_wire south side east side north up power 7 west none 2253 redstone_wire south none east side north up power 7 west up 2254 redstone_wire south none east side north up power 7 west side 2255 redstone_wire south none east side north up power 7 west none 2256 redstone_wire south up east side north up power 8 west up 2257 redstone_wire south up east side north up power 8 west side 2258 redstone_wire south up east side north up power 8 west none 2259 redstone_wire south side east side north up power 8 west up 2260 redstone_wire south side east side north up power 8 west side 2261 redstone_wire south side east side north up power 8 west none 2262 redstone_wire south none east side north up power 8 west up 2263 redstone_wire south none east side north up power 8 west side 2264 redstone_wire south none east side north up power 8 west none 2265 redstone_wire south up east side north up power 9 west up 2266 redstone_wire south up east side north up power 9 west side 2267 redstone_wire south up east side north up power 9 west none 2268 redstone_wire south side east side north up power 9 west up 2269 redstone_wire south side east side north up power 9 west side 2270 redstone_wire south side east side north up power 9 west none 2271 redstone_wire south none east side north up power 9 west up 2272 redstone_wire south none east side north up power 9 west side 2273 redstone_wire south none east side north up power 9 west none 2274 redstone_wire south up east side north up power 10 west up 2275 redstone_wire south up east side north up power 10 west side 2276 redstone_wire south up east side north up power 10 west none 2277 redstone_wire south side east side north up power 10 west up 2278 redstone_wire south side east side north up power 10 west side 2279 redstone_wire south side east side north up power 10 west none 2280 redstone_wire south none east side north up power 10 west up 2281 redstone_wire south none east side north up power 10 west side 2282 redstone_wire south none east side north up power 10 west none 2283 redstone_wire south up east side north up power 11 west up 2284 redstone_wire south up east side north up power 11 west side 2285 redstone_wire south up east side north up power 11 west none 2286 redstone_wire south side east side north up power 11 west up 2287 redstone_wire south side east side north up power 11 west side 2288 redstone_wire south side east side north up power 11 west none 2289 redstone_wire south none east side north up power 11 west up 2290 redstone_wire south none east side north up power 11 west side 2291 redstone_wire south none east side north up power 11 west none 2292 redstone_wire south up east side north up power 12 west up 2293 redstone_wire south up east side north up power 12 west side 2294 redstone_wire south up east side north up power 12 west none 2295 redstone_wire south side east side north up power 12 west up 2296 redstone_wire south side east side north up power 12 west side 2297 redstone_wire south side east side north up power 12 west none 2298 redstone_wire south none east side north up power 12 west up 2299 redstone_wire south none east side north up power 12 west side 2300 redstone_wire south none east side north up power 12 west none 2301 redstone_wire south up east side north up power 13 west up 2302 redstone_wire south up east side north up power 13 west side 2303 redstone_wire south up east side north up power 13 west none 2304 redstone_wire south side east side north up power 13 west up 2305 redstone_wire south side east side north up power 13 west side 2306 redstone_wire south side east side north up power 13 west none 2307 redstone_wire south none east side north up power 13 west up 2308 redstone_wire south none east side north up power 13 west side 2309 redstone_wire south none east side north up power 13 west none 2310 redstone_wire south up east side north up power 14 west up 2311 redstone_wire south up east side north up power 14 west side 2312 redstone_wire south up east side north up power 14 west none 2313 redstone_wire south side east side north up power 14 west up 2314 redstone_wire south side east side north up power 14 west side 2315 redstone_wire south side east side north up power 14 west none 2316 redstone_wire south none east side north up power 14 west up 2317 redstone_wire south none east side north up power 14 west side 2318 redstone_wire south none east side north up power 14 west none 2319 redstone_wire south up east side north up power 15 west up 2320 redstone_wire south up east side north up power 15 west side 2321 redstone_wire south up east side north up power 15 west none 2322 redstone_wire south side east side north up power 15 west up 2323 redstone_wire south side east side north up power 15 west side 2324 redstone_wire south side east side north up power 15 west none 2325 redstone_wire south none east side north up power 15 west up 2326 redstone_wire south none east side north up power 15 west side 2327 redstone_wire south none east side north up power 15 west none 2328 redstone_wire south up east side north side power 0 west up 2329 redstone_wire south up east side north side power 0 west side 2330 redstone_wire south up east side north side power 0 west none 2331 redstone_wire south side east side north side power 0 west up 2332 redstone_wire south side east side north side power 0 west side 2333 redstone_wire south side east side north side power 0 west none 2334 redstone_wire south none east side north side power 0 west up 2335 redstone_wire south none east side north side power 0 west side 2336 redstone_wire south none east side north side power 0 west none 2337 redstone_wire south up east side north side power 1 west up 2338 redstone_wire south up east side north side power 1 west side 2339 redstone_wire south up east side north side power 1 west none 2340 redstone_wire south side east side north side power 1 west up 2341 redstone_wire south side east side north side power 1 west side 2342 redstone_wire south side east side north side power 1 west none 2343 redstone_wire south none east side north side power 1 west up 2344 redstone_wire south none east side north side power 1 west side 2345 redstone_wire south none east side north side power 1 west none 2346 redstone_wire south up east side north side power 2 west up 2347 redstone_wire south up east side north side power 2 west side 2348 redstone_wire south up east side north side power 2 west none 2349 redstone_wire south side east side north side power 2 west up 2350 redstone_wire south side east side north side power 2 west side 2351 redstone_wire south side east side north side power 2 west none 2352 redstone_wire south none east side north side power 2 west up 2353 redstone_wire south none east side north side power 2 west side 2354 redstone_wire south none east side north side power 2 west none 2355 redstone_wire south up east side north side power 3 west up 2356 redstone_wire south up east side north side power 3 west side 2357 redstone_wire south up east side north side power 3 west none 2358 redstone_wire south side east side north side power 3 west up 2359 redstone_wire south side east side north side power 3 west side 2360 redstone_wire south side east side north side power 3 west none 2361 redstone_wire south none east side north side power 3 west up 2362 redstone_wire south none east side north side power 3 west side 2363 redstone_wire south none east side north side power 3 west none 2364 redstone_wire south up east side north side power 4 west up 2365 redstone_wire south up east side north side power 4 west side 2366 redstone_wire south up east side north side power 4 west none 2367 redstone_wire south side east side north side power 4 west up 2368 redstone_wire south side east side north side power 4 west side 2369 redstone_wire south side east side north side power 4 west none 2370 redstone_wire south none east side north side power 4 west up 2371 redstone_wire south none east side north side power 4 west side 2372 redstone_wire south none east side north side power 4 west none 2373 redstone_wire south up east side north side power 5 west up 2374 redstone_wire south up east side north side power 5 west side 2375 redstone_wire south up east side north side power 5 west none 2376 redstone_wire south side east side north side power 5 west up 2377 redstone_wire south side east side north side power 5 west side 2378 redstone_wire south side east side north side power 5 west none 2379 redstone_wire south none east side north side power 5 west up 2380 redstone_wire south none east side north side power 5 west side 2381 redstone_wire south none east side north side power 5 west none 2382 redstone_wire south up east side north side power 6 west up 2383 redstone_wire south up east side north side power 6 west side 2384 redstone_wire south up east side north side power 6 west none 2385 redstone_wire south side east side north side power 6 west up 2386 redstone_wire south side east side north side power 6 west side 2387 redstone_wire south side east side north side power 6 west none 2388 redstone_wire south none east side north side power 6 west up 2389 redstone_wire south none east side north side power 6 west side 2390 redstone_wire south none east side north side power 6 west none 2391 redstone_wire south up east side north side power 7 west up 2392 redstone_wire south up east side north side power 7 west side 2393 redstone_wire south up east side north side power 7 west none 2394 redstone_wire south side east side north side power 7 west up 2395 redstone_wire south side east side north side power 7 west side 2396 redstone_wire south side east side north side power 7 west none 2397 redstone_wire south none east side north side power 7 west up 2398 redstone_wire south none east side north side power 7 west side 2399 redstone_wire south none east side north side power 7 west none 2400 redstone_wire south up east side north side power 8 west up 2401 redstone_wire south up east side north side power 8 west side 2402 redstone_wire south up east side north side power 8 west none 2403 redstone_wire south side east side north side power 8 west up 2404 redstone_wire south side east side north side power 8 west side 2405 redstone_wire south side east side north side power 8 west none 2406 redstone_wire south none east side north side power 8 west up 2407 redstone_wire south none east side north side power 8 west side 2408 redstone_wire south none east side north side power 8 west none 2409 redstone_wire south up east side north side power 9 west up 2410 redstone_wire south up east side north side power 9 west side 2411 redstone_wire south up east side north side power 9 west none 2412 redstone_wire south side east side north side power 9 west up 2413 redstone_wire south side east side north side power 9 west side 2414 redstone_wire south side east side north side power 9 west none 2415 redstone_wire south none east side north side power 9 west up 2416 redstone_wire south none east side north side power 9 west side 2417 redstone_wire south none east side north side power 9 west none 2418 redstone_wire south up east side north side power 10 west up 2419 redstone_wire south up east side north side power 10 west side 2420 redstone_wire south up east side north side power 10 west none 2421 redstone_wire south side east side north side power 10 west up 2422 redstone_wire south side east side north side power 10 west side 2423 redstone_wire south side east side north side power 10 west none 2424 redstone_wire south none east side north side power 10 west up 2425 redstone_wire south none east side north side power 10 west side 2426 redstone_wire south none east side north side power 10 west none 2427 redstone_wire south up east side north side power 11 west up 2428 redstone_wire south up east side north side power 11 west side 2429 redstone_wire south up east side north side power 11 west none 2430 redstone_wire south side east side north side power 11 west up 2431 redstone_wire south side east side north side power 11 west side 2432 redstone_wire south side east side north side power 11 west none 2433 redstone_wire south none east side north side power 11 west up 2434 redstone_wire south none east side north side power 11 west side 2435 redstone_wire south none east side north side power 11 west none 2436 redstone_wire south up east side north side power 12 west up 2437 redstone_wire south up east side north side power 12 west side 2438 redstone_wire south up east side north side power 12 west none 2439 redstone_wire south side east side north side power 12 west up 2440 redstone_wire south side east side north side power 12 west side 2441 redstone_wire south side east side north side power 12 west none 2442 redstone_wire south none east side north side power 12 west up 2443 redstone_wire south none east side north side power 12 west side 2444 redstone_wire south none east side north side power 12 west none 2445 redstone_wire south up east side north side power 13 west up 2446 redstone_wire south up east side north side power 13 west side 2447 redstone_wire south up east side north side power 13 west none 2448 redstone_wire south side east side north side power 13 west up 2449 redstone_wire south side east side north side power 13 west side 2450 redstone_wire south side east side north side power 13 west none 2451 redstone_wire south none east side north side power 13 west up 2452 redstone_wire south none east side north side power 13 west side 2453 redstone_wire south none east side north side power 13 west none 2454 redstone_wire south up east side north side power 14 west up 2455 redstone_wire south up east side north side power 14 west side 2456 redstone_wire south up east side north side power 14 west none 2457 redstone_wire south side east side north side power 14 west up 2458 redstone_wire south side east side north side power 14 west side 2459 redstone_wire south side east side north side power 14 west none 2460 redstone_wire south none east side north side power 14 west up 2461 redstone_wire south none east side north side power 14 west side 2462 redstone_wire south none east side north side power 14 west none 2463 redstone_wire south up east side north side power 15 west up 2464 redstone_wire south up east side north side power 15 west side 2465 redstone_wire south up east side north side power 15 west none 2466 redstone_wire south side east side north side power 15 west up 2467 redstone_wire south side east side north side power 15 west side 2468 redstone_wire south side east side north side power 15 west none 2469 redstone_wire south none east side north side power 15 west up 2470 redstone_wire south none east side north side power 15 west side 2471 redstone_wire south none east side north side power 15 west none 2472 redstone_wire south up east side north none power 0 west up 2473 redstone_wire south up east side north none power 0 west side 2474 redstone_wire south up east side north none power 0 west none 2475 redstone_wire south side east side north none power 0 west up 2476 redstone_wire south side east side north none power 0 west side 2477 redstone_wire south side east side north none power 0 west none 2478 redstone_wire south none east side north none power 0 west up 2479 redstone_wire south none east side north none power 0 west side 2480 redstone_wire south none east side north none power 0 west none 2481 redstone_wire south up east side north none power 1 west up 2482 redstone_wire south up east side north none power 1 west side 2483 redstone_wire south up east side north none power 1 west none 2484 redstone_wire south side east side north none power 1 west up 2485 redstone_wire south side east side north none power 1 west side 2486 redstone_wire south side east side north none power 1 west none 2487 redstone_wire south none east side north none power 1 west up 2488 redstone_wire south none east side north none power 1 west side 2489 redstone_wire south none east side north none power 1 west none 2490 redstone_wire south up east side north none power 2 west up 2491 redstone_wire south up east side north none power 2 west side 2492 redstone_wire south up east side north none power 2 west none 2493 redstone_wire south side east side north none power 2 west up 2494 redstone_wire south side east side north none power 2 west side 2495 redstone_wire south side east side north none power 2 west none 2496 redstone_wire south none east side north none power 2 west up 2497 redstone_wire south none east side north none power 2 west side 2498 redstone_wire south none east side north none power 2 west none 2499 redstone_wire south up east side north none power 3 west up 2500 redstone_wire south up east side north none power 3 west side 2501 redstone_wire south up east side north none power 3 west none 2502 redstone_wire south side east side north none power 3 west up 2503 redstone_wire south side east side north none power 3 west side 2504 redstone_wire south side east side north none power 3 west none 2505 redstone_wire south none east side north none power 3 west up 2506 redstone_wire south none east side north none power 3 west side 2507 redstone_wire south none east side north none power 3 west none 2508 redstone_wire south up east side north none power 4 west up 2509 redstone_wire south up east side north none power 4 west side 2510 redstone_wire south up east side north none power 4 west none 2511 redstone_wire south side east side north none power 4 west up 2512 redstone_wire south side east side north none power 4 west side 2513 redstone_wire south side east side north none power 4 west none 2514 redstone_wire south none east side north none power 4 west up 2515 redstone_wire south none east side north none power 4 west side 2516 redstone_wire south none east side north none power 4 west none 2517 redstone_wire south up east side north none power 5 west up 2518 redstone_wire south up east side north none power 5 west side 2519 redstone_wire south up east side north none power 5 west none 2520 redstone_wire south side east side north none power 5 west up 2521 redstone_wire south side east side north none power 5 west side 2522 redstone_wire south side east side north none power 5 west none 2523 redstone_wire south none east side north none power 5 west up 2524 redstone_wire south none east side north none power 5 west side 2525 redstone_wire south none east side north none power 5 west none 2526 redstone_wire south up east side north none power 6 west up 2527 redstone_wire south up east side north none power 6 west side 2528 redstone_wire south up east side north none power 6 west none 2529 redstone_wire south side east side north none power 6 west up 2530 redstone_wire south side east side north none power 6 west side 2531 redstone_wire south side east side north none power 6 west none 2532 redstone_wire south none east side north none power 6 west up 2533 redstone_wire south none east side north none power 6 west side 2534 redstone_wire south none east side north none power 6 west none 2535 redstone_wire south up east side north none power 7 west up 2536 redstone_wire south up east side north none power 7 west side 2537 redstone_wire south up east side north none power 7 west none 2538 redstone_wire south side east side north none power 7 west up 2539 redstone_wire south side east side north none power 7 west side 2540 redstone_wire south side east side north none power 7 west none 2541 redstone_wire south none east side north none power 7 west up 2542 redstone_wire south none east side north none power 7 west side 2543 redstone_wire south none east side north none power 7 west none 2544 redstone_wire south up east side north none power 8 west up 2545 redstone_wire south up east side north none power 8 west side 2546 redstone_wire south up east side north none power 8 west none 2547 redstone_wire south side east side north none power 8 west up 2548 redstone_wire south side east side north none power 8 west side 2549 redstone_wire south side east side north none power 8 west none 2550 redstone_wire south none east side north none power 8 west up 2551 redstone_wire south none east side north none power 8 west side 2552 redstone_wire south none east side north none power 8 west none 2553 redstone_wire south up east side north none power 9 west up 2554 redstone_wire south up east side north none power 9 west side 2555 redstone_wire south up east side north none power 9 west none 2556 redstone_wire south side east side north none power 9 west up 2557 redstone_wire south side east side north none power 9 west side 2558 redstone_wire south side east side north none power 9 west none 2559 redstone_wire south none east side north none power 9 west up 2560 redstone_wire south none east side north none power 9 west side 2561 redstone_wire south none east side north none power 9 west none 2562 redstone_wire south up east side north none power 10 west up 2563 redstone_wire south up east side north none power 10 west side 2564 redstone_wire south up east side north none power 10 west none 2565 redstone_wire south side east side north none power 10 west up 2566 redstone_wire south side east side north none power 10 west side 2567 redstone_wire south side east side north none power 10 west none 2568 redstone_wire south none east side north none power 10 west up 2569 redstone_wire south none east side north none power 10 west side 2570 redstone_wire south none east side north none power 10 west none 2571 redstone_wire south up east side north none power 11 west up 2572 redstone_wire south up east side north none power 11 west side 2573 redstone_wire south up east side north none power 11 west none 2574 redstone_wire south side east side north none power 11 west up 2575 redstone_wire south side east side north none power 11 west side 2576 redstone_wire south side east side north none power 11 west none 2577 redstone_wire south none east side north none power 11 west up 2578 redstone_wire south none east side north none power 11 west side 2579 redstone_wire south none east side north none power 11 west none 2580 redstone_wire south up east side north none power 12 west up 2581 redstone_wire south up east side north none power 12 west side 2582 redstone_wire south up east side north none power 12 west none 2583 redstone_wire south side east side north none power 12 west up 2584 redstone_wire south side east side north none power 12 west side 2585 redstone_wire south side east side north none power 12 west none 2586 redstone_wire south none east side north none power 12 west up 2587 redstone_wire south none east side north none power 12 west side 2588 redstone_wire south none east side north none power 12 west none 2589 redstone_wire south up east side north none power 13 west up 2590 redstone_wire south up east side north none power 13 west side 2591 redstone_wire south up east side north none power 13 west none 2592 redstone_wire south side east side north none power 13 west up 2593 redstone_wire south side east side north none power 13 west side 2594 redstone_wire south side east side north none power 13 west none 2595 redstone_wire south none east side north none power 13 west up 2596 redstone_wire south none east side north none power 13 west side 2597 redstone_wire south none east side north none power 13 west none 2598 redstone_wire south up east side north none power 14 west up 2599 redstone_wire south up east side north none power 14 west side 2600 redstone_wire south up east side north none power 14 west none 2601 redstone_wire south side east side north none power 14 west up 2602 redstone_wire south side east side north none power 14 west side 2603 redstone_wire south side east side north none power 14 west none 2604 redstone_wire south none east side north none power 14 west up 2605 redstone_wire south none east side north none power 14 west side 2606 redstone_wire south none east side north none power 14 west none 2607 redstone_wire south up east side north none power 15 west up 2608 redstone_wire south up east side north none power 15 west side 2609 redstone_wire south up east side north none power 15 west none 2610 redstone_wire south side east side north none power 15 west up 2611 redstone_wire south side east side north none power 15 west side 2612 redstone_wire south side east side north none power 15 west none 2613 redstone_wire south none east side north none power 15 west up 2614 redstone_wire south none east side north none power 15 west side 2615 redstone_wire south none east side north none power 15 west none 2616 redstone_wire south up east none north up power 0 west up 2617 redstone_wire south up east none north up power 0 west side 2618 redstone_wire south up east none north up power 0 west none 2619 redstone_wire south side east none north up power 0 west up 2620 redstone_wire south side east none north up power 0 west side 2621 redstone_wire south side east none north up power 0 west none 2622 redstone_wire south none east none north up power 0 west up 2623 redstone_wire south none east none north up power 0 west side 2624 redstone_wire south none east none north up power 0 west none 2625 redstone_wire south up east none north up power 1 west up 2626 redstone_wire south up east none north up power 1 west side 2627 redstone_wire south up east none north up power 1 west none 2628 redstone_wire south side east none north up power 1 west up 2629 redstone_wire south side east none north up power 1 west side 2630 redstone_wire south side east none north up power 1 west none 2631 redstone_wire south none east none north up power 1 west up 2632 redstone_wire south none east none north up power 1 west side 2633 redstone_wire south none east none north up power 1 west none 2634 redstone_wire south up east none north up power 2 west up 2635 redstone_wire south up east none north up power 2 west side 2636 redstone_wire south up east none north up power 2 west none 2637 redstone_wire south side east none north up power 2 west up 2638 redstone_wire south side east none north up power 2 west side 2639 redstone_wire south side east none north up power 2 west none 2640 redstone_wire south none east none north up power 2 west up 2641 redstone_wire south none east none north up power 2 west side 2642 redstone_wire south none east none north up power 2 west none 2643 redstone_wire south up east none north up power 3 west up 2644 redstone_wire south up east none north up power 3 west side 2645 redstone_wire south up east none north up power 3 west none 2646 redstone_wire south side east none north up power 3 west up 2647 redstone_wire south side east none north up power 3 west side 2648 redstone_wire south side east none north up power 3 west none 2649 redstone_wire south none east none north up power 3 west up 2650 redstone_wire south none east none north up power 3 west side 2651 redstone_wire south none east none north up power 3 west none 2652 redstone_wire south up east none north up power 4 west up 2653 redstone_wire south up east none north up power 4 west side 2654 redstone_wire south up east none north up power 4 west none 2655 redstone_wire south side east none north up power 4 west up 2656 redstone_wire south side east none north up power 4 west side 2657 redstone_wire south side east none north up power 4 west none 2658 redstone_wire south none east none north up power 4 west up 2659 redstone_wire south none east none north up power 4 west side 2660 redstone_wire south none east none north up power 4 west none 2661 redstone_wire south up east none north up power 5 west up 2662 redstone_wire south up east none north up power 5 west side 2663 redstone_wire south up east none north up power 5 west none 2664 redstone_wire south side east none north up power 5 west up 2665 redstone_wire south side east none north up power 5 west side 2666 redstone_wire south side east none north up power 5 west none 2667 redstone_wire south none east none north up power 5 west up 2668 redstone_wire south none east none north up power 5 west side 2669 redstone_wire south none east none north up power 5 west none 2670 redstone_wire south up east none north up power 6 west up 2671 redstone_wire south up east none north up power 6 west side 2672 redstone_wire south up east none north up power 6 west none 2673 redstone_wire south side east none north up power 6 west up 2674 redstone_wire south side east none north up power 6 west side 2675 redstone_wire south side east none north up power 6 west none 2676 redstone_wire south none east none north up power 6 west up 2677 redstone_wire south none east none north up power 6 west side 2678 redstone_wire south none east none north up power 6 west none 2679 redstone_wire south up east none north up power 7 west up 2680 redstone_wire south up east none north up power 7 west side 2681 redstone_wire south up east none north up power 7 west none 2682 redstone_wire south side east none north up power 7 west up 2683 redstone_wire south side east none north up power 7 west side 2684 redstone_wire south side east none north up power 7 west none 2685 redstone_wire south none east none north up power 7 west up 2686 redstone_wire south none east none north up power 7 west side 2687 redstone_wire south none east none north up power 7 west none 2688 redstone_wire south up east none north up power 8 west up 2689 redstone_wire south up east none north up power 8 west side 2690 redstone_wire south up east none north up power 8 west none 2691 redstone_wire south side east none north up power 8 west up 2692 redstone_wire south side east none north up power 8 west side 2693 redstone_wire south side east none north up power 8 west none 2694 redstone_wire south none east none north up power 8 west up 2695 redstone_wire south none east none north up power 8 west side 2696 redstone_wire south none east none north up power 8 west none 2697 redstone_wire south up east none north up power 9 west up 2698 redstone_wire south up east none north up power 9 west side 2699 redstone_wire south up east none north up power 9 west none 2700 redstone_wire south side east none north up power 9 west up 2701 redstone_wire south side east none north up power 9 west side 2702 redstone_wire south side east none north up power 9 west none 2703 redstone_wire south none east none north up power 9 west up 2704 redstone_wire south none east none north up power 9 west side 2705 redstone_wire south none east none north up power 9 west none 2706 redstone_wire south up east none north up power 10 west up 2707 redstone_wire south up east none north up power 10 west side 2708 redstone_wire south up east none north up power 10 west none 2709 redstone_wire south side east none north up power 10 west up 2710 redstone_wire south side east none north up power 10 west side 2711 redstone_wire south side east none north up power 10 west none 2712 redstone_wire south none east none north up power 10 west up 2713 redstone_wire south none east none north up power 10 west side 2714 redstone_wire south none east none north up power 10 west none 2715 redstone_wire south up east none north up power 11 west up 2716 redstone_wire south up east none north up power 11 west side 2717 redstone_wire south up east none north up power 11 west none 2718 redstone_wire south side east none north up power 11 west up 2719 redstone_wire south side east none north up power 11 west side 2720 redstone_wire south side east none north up power 11 west none 2721 redstone_wire south none east none north up power 11 west up 2722 redstone_wire south none east none north up power 11 west side 2723 redstone_wire south none east none north up power 11 west none 2724 redstone_wire south up east none north up power 12 west up 2725 redstone_wire south up east none north up power 12 west side 2726 redstone_wire south up east none north up power 12 west none 2727 redstone_wire south side east none north up power 12 west up 2728 redstone_wire south side east none north up power 12 west side 2729 redstone_wire south side east none north up power 12 west none 2730 redstone_wire south none east none north up power 12 west up 2731 redstone_wire south none east none north up power 12 west side 2732 redstone_wire south none east none north up power 12 west none 2733 redstone_wire south up east none north up power 13 west up 2734 redstone_wire south up east none north up power 13 west side 2735 redstone_wire south up east none north up power 13 west none 2736 redstone_wire south side east none north up power 13 west up 2737 redstone_wire south side east none north up power 13 west side 2738 redstone_wire south side east none north up power 13 west none 2739 redstone_wire south none east none north up power 13 west up 2740 redstone_wire south none east none north up power 13 west side 2741 redstone_wire south none east none north up power 13 west none 2742 redstone_wire south up east none north up power 14 west up 2743 redstone_wire south up east none north up power 14 west side 2744 redstone_wire south up east none north up power 14 west none 2745 redstone_wire south side east none north up power 14 west up 2746 redstone_wire south side east none north up power 14 west side 2747 redstone_wire south side east none north up power 14 west none 2748 redstone_wire south none east none north up power 14 west up 2749 redstone_wire south none east none north up power 14 west side 2750 redstone_wire south none east none north up power 14 west none 2751 redstone_wire south up east none north up power 15 west up 2752 redstone_wire south up east none north up power 15 west side 2753 redstone_wire south up east none north up power 15 west none 2754 redstone_wire south side east none north up power 15 west up 2755 redstone_wire south side east none north up power 15 west side 2756 redstone_wire south side east none north up power 15 west none 2757 redstone_wire south none east none north up power 15 west up 2758 redstone_wire south none east none north up power 15 west side 2759 redstone_wire south none east none north up power 15 west none 2760 redstone_wire south up east none north side power 0 west up 2761 redstone_wire south up east none north side power 0 west side 2762 redstone_wire south up east none north side power 0 west none 2763 redstone_wire south side east none north side power 0 west up 2764 redstone_wire south side east none north side power 0 west side 2765 redstone_wire south side east none north side power 0 west none 2766 redstone_wire south none east none north side power 0 west up 2767 redstone_wire south none east none north side power 0 west side 2768 redstone_wire south none east none north side power 0 west none 2769 redstone_wire south up east none north side power 1 west up 2770 redstone_wire south up east none north side power 1 west side 2771 redstone_wire south up east none north side power 1 west none 2772 redstone_wire south side east none north side power 1 west up 2773 redstone_wire south side east none north side power 1 west side 2774 redstone_wire south side east none north side power 1 west none 2775 redstone_wire south none east none north side power 1 west up 2776 redstone_wire south none east none north side power 1 west side 2777 redstone_wire south none east none north side power 1 west none 2778 redstone_wire south up east none north side power 2 west up 2779 redstone_wire south up east none north side power 2 west side 2780 redstone_wire south up east none north side power 2 west none 2781 redstone_wire south side east none north side power 2 west up 2782 redstone_wire south side east none north side power 2 west side 2783 redstone_wire south side east none north side power 2 west none 2784 redstone_wire south none east none north side power 2 west up 2785 redstone_wire south none east none north side power 2 west side 2786 redstone_wire south none east none north side power 2 west none 2787 redstone_wire south up east none north side power 3 west up 2788 redstone_wire south up east none north side power 3 west side 2789 redstone_wire south up east none north side power 3 west none 2790 redstone_wire south side east none north side power 3 west up 2791 redstone_wire south side east none north side power 3 west side 2792 redstone_wire south side east none north side power 3 west none 2793 redstone_wire south none east none north side power 3 west up 2794 redstone_wire south none east none north side power 3 west side 2795 redstone_wire south none east none north side power 3 west none 2796 redstone_wire south up east none north side power 4 west up 2797 redstone_wire south up east none north side power 4 west side 2798 redstone_wire south up east none north side power 4 west none 2799 redstone_wire south side east none north side power 4 west up 2800 redstone_wire south side east none north side power 4 west side 2801 redstone_wire south side east none north side power 4 west none 2802 redstone_wire south none east none north side power 4 west up 2803 redstone_wire south none east none north side power 4 west side 2804 redstone_wire south none east none north side power 4 west none 2805 redstone_wire south up east none north side power 5 west up 2806 redstone_wire south up east none north side power 5 west side 2807 redstone_wire south up east none north side power 5 west none 2808 redstone_wire south side east none north side power 5 west up 2809 redstone_wire south side east none north side power 5 west side 2810 redstone_wire south side east none north side power 5 west none 2811 redstone_wire south none east none north side power 5 west up 2812 redstone_wire south none east none north side power 5 west side 2813 redstone_wire south none east none north side power 5 west none 2814 redstone_wire south up east none north side power 6 west up 2815 redstone_wire south up east none north side power 6 west side 2816 redstone_wire south up east none north side power 6 west none 2817 redstone_wire south side east none north side power 6 west up 2818 redstone_wire south side east none north side power 6 west side 2819 redstone_wire south side east none north side power 6 west none 2820 redstone_wire south none east none north side power 6 west up 2821 redstone_wire south none east none north side power 6 west side 2822 redstone_wire south none east none north side power 6 west none 2823 redstone_wire south up east none north side power 7 west up 2824 redstone_wire south up east none north side power 7 west side 2825 redstone_wire south up east none north side power 7 west none 2826 redstone_wire south side east none north side power 7 west up 2827 redstone_wire south side east none north side power 7 west side 2828 redstone_wire south side east none north side power 7 west none 2829 redstone_wire south none east none north side power 7 west up 2830 redstone_wire south none east none north side power 7 west side 2831 redstone_wire south none east none north side power 7 west none 2832 redstone_wire south up east none north side power 8 west up 2833 redstone_wire south up east none north side power 8 west side 2834 redstone_wire south up east none north side power 8 west none 2835 redstone_wire south side east none north side power 8 west up 2836 redstone_wire south side east none north side power 8 west side 2837 redstone_wire south side east none north side power 8 west none 2838 redstone_wire south none east none north side power 8 west up 2839 redstone_wire south none east none north side power 8 west side 2840 redstone_wire south none east none north side power 8 west none 2841 redstone_wire south up east none north side power 9 west up 2842 redstone_wire south up east none north side power 9 west side 2843 redstone_wire south up east none north side power 9 west none 2844 redstone_wire south side east none north side power 9 west up 2845 redstone_wire south side east none north side power 9 west side 2846 redstone_wire south side east none north side power 9 west none 2847 redstone_wire south none east none north side power 9 west up 2848 redstone_wire south none east none north side power 9 west side 2849 redstone_wire south none east none north side power 9 west none 2850 redstone_wire south up east none north side power 10 west up 2851 redstone_wire south up east none north side power 10 west side 2852 redstone_wire south up east none north side power 10 west none 2853 redstone_wire south side east none north side power 10 west up 2854 redstone_wire south side east none north side power 10 west side 2855 redstone_wire south side east none north side power 10 west none 2856 redstone_wire south none east none north side power 10 west up 2857 redstone_wire south none east none north side power 10 west side 2858 redstone_wire south none east none north side power 10 west none 2859 redstone_wire south up east none north side power 11 west up 2860 redstone_wire south up east none north side power 11 west side 2861 redstone_wire south up east none north side power 11 west none 2862 redstone_wire south side east none north side power 11 west up 2863 redstone_wire south side east none north side power 11 west side 2864 redstone_wire south side east none north side power 11 west none 2865 redstone_wire south none east none north side power 11 west up 2866 redstone_wire south none east none north side power 11 west side 2867 redstone_wire south none east none north side power 11 west none 2868 redstone_wire south up east none north side power 12 west up 2869 redstone_wire south up east none north side power 12 west side 2870 redstone_wire south up east none north side power 12 west none 2871 redstone_wire south side east none north side power 12 west up 2872 redstone_wire south side east none north side power 12 west side 2873 redstone_wire south side east none north side power 12 west none 2874 redstone_wire south none east none north side power 12 west up 2875 redstone_wire south none east none north side power 12 west side 2876 redstone_wire south none east none north side power 12 west none 2877 redstone_wire south up east none north side power 13 west up 2878 redstone_wire south up east none north side power 13 west side 2879 redstone_wire south up east none north side power 13 west none 2880 redstone_wire south side east none north side power 13 west up 2881 redstone_wire south side east none north side power 13 west side 2882 redstone_wire south side east none north side power 13 west none 2883 redstone_wire south none east none north side power 13 west up 2884 redstone_wire south none east none north side power 13 west side 2885 redstone_wire south none east none north side power 13 west none 2886 redstone_wire south up east none north side power 14 west up 2887 redstone_wire south up east none north side power 14 west side 2888 redstone_wire south up east none north side power 14 west none 2889 redstone_wire south side east none north side power 14 west up 2890 redstone_wire south side east none north side power 14 west side 2891 redstone_wire south side east none north side power 14 west none 2892 redstone_wire south none east none north side power 14 west up 2893 redstone_wire south none east none north side power 14 west side 2894 redstone_wire south none east none north side power 14 west none 2895 redstone_wire south up east none north side power 15 west up 2896 redstone_wire south up east none north side power 15 west side 2897 redstone_wire south up east none north side power 15 west none 2898 redstone_wire south side east none north side power 15 west up 2899 redstone_wire south side east none north side power 15 west side 2900 redstone_wire south side east none north side power 15 west none 2901 redstone_wire south none east none north side power 15 west up 2902 redstone_wire south none east none north side power 15 west side 2903 redstone_wire south none east none north side power 15 west none 2904 redstone_wire south up east none north none power 0 west up 2905 redstone_wire south up east none north none power 0 west side 2906 redstone_wire south up east none north none power 0 west none 2907 redstone_wire south side east none north none power 0 west up 2908 redstone_wire south side east none north none power 0 west side 2909 redstone_wire south side east none north none power 0 west none 2910 redstone_wire south none east none north none power 0 west up 2911 redstone_wire south none east none north none power 0 west side 2912 redstone_wire south none east none north none power 0 west none 2913 redstone_wire south up east none north none power 1 west up 2914 redstone_wire south up east none north none power 1 west side 2915 redstone_wire south up east none north none power 1 west none 2916 redstone_wire south side east none north none power 1 west up 2917 redstone_wire south side east none north none power 1 west side 2918 redstone_wire south side east none north none power 1 west none 2919 redstone_wire south none east none north none power 1 west up 2920 redstone_wire south none east none north none power 1 west side 2921 redstone_wire south none east none north none power 1 west none 2922 redstone_wire south up east none north none power 2 west up 2923 redstone_wire south up east none north none power 2 west side 2924 redstone_wire south up east none north none power 2 west none 2925 redstone_wire south side east none north none power 2 west up 2926 redstone_wire south side east none north none power 2 west side 2927 redstone_wire south side east none north none power 2 west none 2928 redstone_wire south none east none north none power 2 west up 2929 redstone_wire south none east none north none power 2 west side 2930 redstone_wire south none east none north none power 2 west none 2931 redstone_wire south up east none north none power 3 west up 2932 redstone_wire south up east none north none power 3 west side 2933 redstone_wire south up east none north none power 3 west none 2934 redstone_wire south side east none north none power 3 west up 2935 redstone_wire south side east none north none power 3 west side 2936 redstone_wire south side east none north none power 3 west none 2937 redstone_wire south none east none north none power 3 west up 2938 redstone_wire south none east none north none power 3 west side 2939 redstone_wire south none east none north none power 3 west none 2940 redstone_wire south up east none north none power 4 west up 2941 redstone_wire south up east none north none power 4 west side 2942 redstone_wire south up east none north none power 4 west none 2943 redstone_wire south side east none north none power 4 west up 2944 redstone_wire south side east none north none power 4 west side 2945 redstone_wire south side east none north none power 4 west none 2946 redstone_wire south none east none north none power 4 west up 2947 redstone_wire south none east none north none power 4 west side 2948 redstone_wire south none east none north none power 4 west none 2949 redstone_wire south up east none north none power 5 west up 2950 redstone_wire south up east none north none power 5 west side 2951 redstone_wire south up east none north none power 5 west none 2952 redstone_wire south side east none north none power 5 west up 2953 redstone_wire south side east none north none power 5 west side 2954 redstone_wire south side east none north none power 5 west none 2955 redstone_wire south none east none north none power 5 west up 2956 redstone_wire south none east none north none power 5 west side 2957 redstone_wire south none east none north none power 5 west none 2958 redstone_wire south up east none north none power 6 west up 2959 redstone_wire south up east none north none power 6 west side 2960 redstone_wire south up east none north none power 6 west none 2961 redstone_wire south side east none north none power 6 west up 2962 redstone_wire south side east none north none power 6 west side 2963 redstone_wire south side east none north none power 6 west none 2964 redstone_wire south none east none north none power 6 west up 2965 redstone_wire south none east none north none power 6 west side 2966 redstone_wire south none east none north none power 6 west none 2967 redstone_wire south up east none north none power 7 west up 2968 redstone_wire south up east none north none power 7 west side 2969 redstone_wire south up east none north none power 7 west none 2970 redstone_wire south side east none north none power 7 west up 2971 redstone_wire south side east none north none power 7 west side 2972 redstone_wire south side east none north none power 7 west none 2973 redstone_wire south none east none north none power 7 west up 2974 redstone_wire south none east none north none power 7 west side 2975 redstone_wire south none east none north none power 7 west none 2976 redstone_wire south up east none north none power 8 west up 2977 redstone_wire south up east none north none power 8 west side 2978 redstone_wire south up east none north none power 8 west none 2979 redstone_wire south side east none north none power 8 west up 2980 redstone_wire south side east none north none power 8 west side 2981 redstone_wire south side east none north none power 8 west none 2982 redstone_wire south none east none north none power 8 west up 2983 redstone_wire south none east none north none power 8 west side 2984 redstone_wire south none east none north none power 8 west none 2985 redstone_wire south up east none north none power 9 west up 2986 redstone_wire south up east none north none power 9 west side 2987 redstone_wire south up east none north none power 9 west none 2988 redstone_wire south side east none north none power 9 west up 2989 redstone_wire south side east none north none power 9 west side 2990 redstone_wire south side east none north none power 9 west none 2991 redstone_wire south none east none north none power 9 west up 2992 redstone_wire south none east none north none power 9 west side 2993 redstone_wire south none east none north none power 9 west none 2994 redstone_wire south up east none north none power 10 west up 2995 redstone_wire south up east none north none power 10 west side 2996 redstone_wire south up east none north none power 10 west none 2997 redstone_wire south side east none north none power 10 west up 2998 redstone_wire south side east none north none power 10 west side 2999 redstone_wire south side east none north none power 10 west none 3000 redstone_wire south none east none north none power 10 west up 3001 redstone_wire south none east none north none power 10 west side 3002 redstone_wire south none east none north none power 10 west none 3003 redstone_wire south up east none north none power 11 west up 3004 redstone_wire south up east none north none power 11 west side 3005 redstone_wire south up east none north none power 11 west none 3006 redstone_wire south side east none north none power 11 west up 3007 redstone_wire south side east none north none power 11 west side 3008 redstone_wire south side east none north none power 11 west none 3009 redstone_wire south none east none north none power 11 west up 3010 redstone_wire south none east none north none power 11 west side 3011 redstone_wire south none east none north none power 11 west none 3012 redstone_wire south up east none north none power 12 west up 3013 redstone_wire south up east none north none power 12 west side 3014 redstone_wire south up east none north none power 12 west none 3015 redstone_wire south side east none north none power 12 west up 3016 redstone_wire south side east none north none power 12 west side 3017 redstone_wire south side east none north none power 12 west none 3018 redstone_wire south none east none north none power 12 west up 3019 redstone_wire south none east none north none power 12 west side 3020 redstone_wire south none east none north none power 12 west none 3021 redstone_wire south up east none north none power 13 west up 3022 redstone_wire south up east none north none power 13 west side 3023 redstone_wire south up east none north none power 13 west none 3024 redstone_wire south side east none north none power 13 west up 3025 redstone_wire south side east none north none power 13 west side 3026 redstone_wire south side east none north none power 13 west none 3027 redstone_wire south none east none north none power 13 west up 3028 redstone_wire south none east none north none power 13 west side 3029 redstone_wire south none east none north none power 13 west none 3030 redstone_wire south up east none north none power 14 west up 3031 redstone_wire south up east none north none power 14 west side 3032 redstone_wire south up east none north none power 14 west none 3033 redstone_wire south side east none north none power 14 west up 3034 redstone_wire south side east none north none power 14 west side 3035 redstone_wire south side east none north none power 14 west none 3036 redstone_wire south none east none north none power 14 west up 3037 redstone_wire south none east none north none power 14 west side 3038 redstone_wire south none east none north none power 14 west none 3039 redstone_wire south up east none north none power 15 west up 3040 redstone_wire south up east none north none power 15 west side 3041 redstone_wire south up east none north none power 15 west none 3042 redstone_wire south side east none north none power 15 west up 3043 redstone_wire south side east none north none power 15 west side 3044 redstone_wire south side east none north none power 15 west none 3045 redstone_wire south none east none north none power 15 west up 3046 redstone_wire south none east none north none power 15 west side 3047 redstone_wire south none east none north none power 15 west none 3048 diamond_ore 3049 diamond_block 3050 crafting_table 3051 wheat age 0 3052 wheat age 1 3053 wheat age 2 3054 wheat age 3 3055 wheat age 4 3056 wheat age 5 3057 wheat age 6 3058 wheat age 7 3059 farmland moisture 0 3060 farmland moisture 1 3061 farmland moisture 2 3062 farmland moisture 3 3063 farmland moisture 4 3064 farmland moisture 5 3065 farmland moisture 6 3066 farmland moisture 7 3067 furnace facing north lit true 3068 furnace facing north lit false 3069 furnace facing south lit true 3070 furnace facing south lit false 3071 furnace facing west lit true 3072 furnace facing west lit false 3073 furnace facing east lit true 3074 furnace facing east lit false 3075 sign waterlogged true rotation 0 3076 sign waterlogged false rotation 0 3077 sign waterlogged true rotation 1 3078 sign waterlogged false rotation 1 3079 sign waterlogged true rotation 2 3080 sign waterlogged false rotation 2 3081 sign waterlogged true rotation 3 3082 sign waterlogged false rotation 3 3083 sign waterlogged true rotation 4 3084 sign waterlogged false rotation 4 3085 sign waterlogged true rotation 5 3086 sign waterlogged false rotation 5 3087 sign waterlogged true rotation 6 3088 sign waterlogged false rotation 6 3089 sign waterlogged true rotation 7 3090 sign waterlogged false rotation 7 3091 sign waterlogged true rotation 8 3092 sign waterlogged false rotation 8 3093 sign waterlogged true rotation 9 3094 sign waterlogged false rotation 9 3095 sign waterlogged true rotation 10 3096 sign waterlogged false rotation 10 3097 sign waterlogged true rotation 11 3098 sign waterlogged false rotation 11 3099 sign waterlogged true rotation 12 3100 sign waterlogged false rotation 12 3101 sign waterlogged true rotation 13 3102 sign waterlogged false rotation 13 3103 sign waterlogged true rotation 14 3104 sign waterlogged false rotation 14 3105 sign waterlogged true rotation 15 3106 sign waterlogged false rotation 15 3107 oak_door hinge left half upper facing north powered true open true 3108 oak_door hinge left half upper facing north powered false open true 3109 oak_door hinge left half upper facing north powered true open false 3110 oak_door hinge left half upper facing north powered false open false 3111 oak_door hinge right half upper facing north powered true open true 3112 oak_door hinge right half upper facing north powered false open true 3113 oak_door hinge right half upper facing north powered true open false 3114 oak_door hinge right half upper facing north powered false open false 3115 oak_door hinge left half lower facing north powered true open true 3116 oak_door hinge left half lower facing north powered false open true 3117 oak_door hinge left half lower facing north powered true open false 3118 oak_door hinge left half lower facing north powered false open false 3119 oak_door hinge right half lower facing north powered true open true 3120 oak_door hinge right half lower facing north powered false open true 3121 oak_door hinge right half lower facing north powered true open false 3122 oak_door hinge right half lower facing north powered false open false 3123 oak_door hinge left half upper facing south powered true open true 3124 oak_door hinge left half upper facing south powered false open true 3125 oak_door hinge left half upper facing south powered true open false 3126 oak_door hinge left half upper facing south powered false open false 3127 oak_door hinge right half upper facing south powered true open true 3128 oak_door hinge right half upper facing south powered false open true 3129 oak_door hinge right half upper facing south powered true open false 3130 oak_door hinge right half upper facing south powered false open false 3131 oak_door hinge left half lower facing south powered true open true 3132 oak_door hinge left half lower facing south powered false open true 3133 oak_door hinge left half lower facing south powered true open false 3134 oak_door hinge left half lower facing south powered false open false 3135 oak_door hinge right half lower facing south powered true open true 3136 oak_door hinge right half lower facing south powered false open true 3137 oak_door hinge right half lower facing south powered true open false 3138 oak_door hinge right half lower facing south powered false open false 3139 oak_door hinge left half upper facing west powered true open true 3140 oak_door hinge left half upper facing west powered false open true 3141 oak_door hinge left half upper facing west powered true open false 3142 oak_door hinge left half upper facing west powered false open false 3143 oak_door hinge right half upper facing west powered true open true 3144 oak_door hinge right half upper facing west powered false open true 3145 oak_door hinge right half upper facing west powered true open false 3146 oak_door hinge right half upper facing west powered false open false 3147 oak_door hinge left half lower facing west powered true open true 3148 oak_door hinge left half lower facing west powered false open true 3149 oak_door hinge left half lower facing west powered true open false 3150 oak_door hinge left half lower facing west powered false open false 3151 oak_door hinge right half lower facing west powered true open true 3152 oak_door hinge right half lower facing west powered false open true 3153 oak_door hinge right half lower facing west powered true open false 3154 oak_door hinge right half lower facing west powered false open false 3155 oak_door hinge left half upper facing east powered true open true 3156 oak_door hinge left half upper facing east powered false open true 3157 oak_door hinge left half upper facing east powered true open false 3158 oak_door hinge left half upper facing east powered false open false 3159 oak_door hinge right half upper facing east powered true open true 3160 oak_door hinge right half upper facing east powered false open true 3161 oak_door hinge right half upper facing east powered true open false 3162 oak_door hinge right half upper facing east powered false open false 3163 oak_door hinge left half lower facing east powered true open true 3164 oak_door hinge left half lower facing east powered false open true 3165 oak_door hinge left half lower facing east powered true open false 3166 oak_door hinge left half lower facing east powered false open false 3167 oak_door hinge right half lower facing east powered true open true 3168 oak_door hinge right half lower facing east powered false open true 3169 oak_door hinge right half lower facing east powered true open false 3170 oak_door hinge right half lower facing east powered false open false 3171 ladder facing north waterlogged true 3172 ladder facing north waterlogged false 3173 ladder facing south waterlogged true 3174 ladder facing south waterlogged false 3175 ladder facing west waterlogged true 3176 ladder facing west waterlogged false 3177 ladder facing east waterlogged true 3178 ladder facing east waterlogged false 3179 rail shape north_south 3180 rail shape east_west 3181 rail shape ascending_east 3182 rail shape ascending_west 3183 rail shape ascending_north 3184 rail shape ascending_south 3185 rail shape south_east 3186 rail shape south_west 3187 rail shape north_west 3188 rail shape north_east 3189 cobblestone_stairs facing north waterlogged true shape straight half top 3190 cobblestone_stairs facing north waterlogged false shape straight half top 3191 cobblestone_stairs facing north waterlogged true shape inner_left half top 3192 cobblestone_stairs facing north waterlogged false shape inner_left half top 3193 cobblestone_stairs facing north waterlogged true shape inner_right half top 3194 cobblestone_stairs facing north waterlogged false shape inner_right half top 3195 cobblestone_stairs facing north waterlogged true shape outer_left half top 3196 cobblestone_stairs facing north waterlogged false shape outer_left half top 3197 cobblestone_stairs facing north waterlogged true shape outer_right half top 3198 cobblestone_stairs facing north waterlogged false shape outer_right half top 3199 cobblestone_stairs facing north waterlogged true shape straight half bottom 3200 cobblestone_stairs facing north waterlogged false shape straight half bottom 3201 cobblestone_stairs facing north waterlogged true shape inner_left half bottom 3202 cobblestone_stairs facing north waterlogged false shape inner_left half bottom 3203 cobblestone_stairs facing north waterlogged true shape inner_right half bottom 3204 cobblestone_stairs facing north waterlogged false shape inner_right half bottom 3205 cobblestone_stairs facing north waterlogged true shape outer_left half bottom 3206 cobblestone_stairs facing north waterlogged false shape outer_left half bottom 3207 cobblestone_stairs facing north waterlogged true shape outer_right half bottom 3208 cobblestone_stairs facing north waterlogged false shape outer_right half bottom 3209 cobblestone_stairs facing south waterlogged true shape straight half top 3210 cobblestone_stairs facing south waterlogged false shape straight half top 3211 cobblestone_stairs facing south waterlogged true shape inner_left half top 3212 cobblestone_stairs facing south waterlogged false shape inner_left half top 3213 cobblestone_stairs facing south waterlogged true shape inner_right half top 3214 cobblestone_stairs facing south waterlogged false shape inner_right half top 3215 cobblestone_stairs facing south waterlogged true shape outer_left half top 3216 cobblestone_stairs facing south waterlogged false shape outer_left half top 3217 cobblestone_stairs facing south waterlogged true shape outer_right half top 3218 cobblestone_stairs facing south waterlogged false shape outer_right half top 3219 cobblestone_stairs facing south waterlogged true shape straight half bottom 3220 cobblestone_stairs facing south waterlogged false shape straight half bottom 3221 cobblestone_stairs facing south waterlogged true shape inner_left half bottom 3222 cobblestone_stairs facing south waterlogged false shape inner_left half bottom 3223 cobblestone_stairs facing south waterlogged true shape inner_right half bottom 3224 cobblestone_stairs facing south waterlogged false shape inner_right half bottom 3225 cobblestone_stairs facing south waterlogged true shape outer_left half bottom 3226 cobblestone_stairs facing south waterlogged false shape outer_left half bottom 3227 cobblestone_stairs facing south waterlogged true shape outer_right half bottom 3228 cobblestone_stairs facing south waterlogged false shape outer_right half bottom 3229 cobblestone_stairs facing west waterlogged true shape straight half top 3230 cobblestone_stairs facing west waterlogged false shape straight half top 3231 cobblestone_stairs facing west waterlogged true shape inner_left half top 3232 cobblestone_stairs facing west waterlogged false shape inner_left half top 3233 cobblestone_stairs facing west waterlogged true shape inner_right half top 3234 cobblestone_stairs facing west waterlogged false shape inner_right half top 3235 cobblestone_stairs facing west waterlogged true shape outer_left half top 3236 cobblestone_stairs facing west waterlogged false shape outer_left half top 3237 cobblestone_stairs facing west waterlogged true shape outer_right half top 3238 cobblestone_stairs facing west waterlogged false shape outer_right half top 3239 cobblestone_stairs facing west waterlogged true shape straight half bottom 3240 cobblestone_stairs facing west waterlogged false shape straight half bottom 3241 cobblestone_stairs facing west waterlogged true shape inner_left half bottom 3242 cobblestone_stairs facing west waterlogged false shape inner_left half bottom 3243 cobblestone_stairs facing west waterlogged true shape inner_right half bottom 3244 cobblestone_stairs facing west waterlogged false shape inner_right half bottom 3245 cobblestone_stairs facing west waterlogged true shape outer_left half bottom 3246 cobblestone_stairs facing west waterlogged false shape outer_left half bottom 3247 cobblestone_stairs facing west waterlogged true shape outer_right half bottom 3248 cobblestone_stairs facing west waterlogged false shape outer_right half bottom 3249 cobblestone_stairs facing east waterlogged true shape straight half top 3250 cobblestone_stairs facing east waterlogged false shape straight half top 3251 cobblestone_stairs facing east waterlogged true shape inner_left half top 3252 cobblestone_stairs facing east waterlogged false shape inner_left half top 3253 cobblestone_stairs facing east waterlogged true shape inner_right half top 3254 cobblestone_stairs facing east waterlogged false shape inner_right half top 3255 cobblestone_stairs facing east waterlogged true shape outer_left half top 3256 cobblestone_stairs facing east waterlogged false shape outer_left half top 3257 cobblestone_stairs facing east waterlogged true shape outer_right half top 3258 cobblestone_stairs facing east waterlogged false shape outer_right half top 3259 cobblestone_stairs facing east waterlogged true shape straight half bottom 3260 cobblestone_stairs facing east waterlogged false shape straight half bottom 3261 cobblestone_stairs facing east waterlogged true shape inner_left half bottom 3262 cobblestone_stairs facing east waterlogged false shape inner_left half bottom 3263 cobblestone_stairs facing east waterlogged true shape inner_right half bottom 3264 cobblestone_stairs facing east waterlogged false shape inner_right half bottom 3265 cobblestone_stairs facing east waterlogged true shape outer_left half bottom 3266 cobblestone_stairs facing east waterlogged false shape outer_left half bottom 3267 cobblestone_stairs facing east waterlogged true shape outer_right half bottom 3268 cobblestone_stairs facing east waterlogged false shape outer_right half bottom 3269 wall_sign facing north waterlogged true 3270 wall_sign facing north waterlogged false 3271 wall_sign facing south waterlogged true 3272 wall_sign facing south waterlogged false 3273 wall_sign facing west waterlogged true 3274 wall_sign facing west waterlogged false 3275 wall_sign facing east waterlogged true 3276 wall_sign facing east waterlogged false 3277 lever facing north face floor powered true 3278 lever facing north face floor powered false 3279 lever facing south face floor powered true 3280 lever facing south face floor powered false 3281 lever facing west face floor powered true 3282 lever facing west face floor powered false 3283 lever facing east face floor powered true 3284 lever facing east face floor powered false 3285 lever facing north face wall powered true 3286 lever facing north face wall powered false 3287 lever facing south face wall powered true 3288 lever facing south face wall powered false 3289 lever facing west face wall powered true 3290 lever facing west face wall powered false 3291 lever facing east face wall powered true 3292 lever facing east face wall powered false 3293 lever facing north face ceiling powered true 3294 lever facing north face ceiling powered false 3295 lever facing south face ceiling powered true 3296 lever facing south face ceiling powered false 3297 lever facing west face ceiling powered true 3298 lever facing west face ceiling powered false 3299 lever facing east face ceiling powered true 3300 lever facing east face ceiling powered false 3301 stone_pressure_plate powered true 3302 stone_pressure_plate powered false 3303 iron_door hinge left half upper facing north powered true open true 3304 iron_door hinge left half upper facing north powered false open true 3305 iron_door hinge left half upper facing north powered true open false 3306 iron_door hinge left half upper facing north powered false open false 3307 iron_door hinge right half upper facing north powered true open true 3308 iron_door hinge right half upper facing north powered false open true 3309 iron_door hinge right half upper facing north powered true open false 3310 iron_door hinge right half upper facing north powered false open false 3311 iron_door hinge left half lower facing north powered true open true 3312 iron_door hinge left half lower facing north powered false open true 3313 iron_door hinge left half lower facing north powered true open false 3314 iron_door hinge left half lower facing north powered false open false 3315 iron_door hinge right half lower facing north powered true open true 3316 iron_door hinge right half lower facing north powered false open true 3317 iron_door hinge right half lower facing north powered true open false 3318 iron_door hinge right half lower facing north powered false open false 3319 iron_door hinge left half upper facing south powered true open true 3320 iron_door hinge left half upper facing south powered false open true 3321 iron_door hinge left half upper facing south powered true open false 3322 iron_door hinge left half upper facing south powered false open false 3323 iron_door hinge right half upper facing south powered true open true 3324 iron_door hinge right half upper facing south powered false open true 3325 iron_door hinge right half upper facing south powered true open false 3326 iron_door hinge right half upper facing south powered false open false 3327 iron_door hinge left half lower facing south powered true open true 3328 iron_door hinge left half lower facing south powered false open true 3329 iron_door hinge left half lower facing south powered true open false 3330 iron_door hinge left half lower facing south powered false open false 3331 iron_door hinge right half lower facing south powered true open true 3332 iron_door hinge right half lower facing south powered false open true 3333 iron_door hinge right half lower facing south powered true open false 3334 iron_door hinge right half lower facing south powered false open false 3335 iron_door hinge left half upper facing west powered true open true 3336 iron_door hinge left half upper facing west powered false open true 3337 iron_door hinge left half upper facing west powered true open false 3338 iron_door hinge left half upper facing west powered false open false 3339 iron_door hinge right half upper facing west powered true open true 3340 iron_door hinge right half upper facing west powered false open true 3341 iron_door hinge right half upper facing west powered true open false 3342 iron_door hinge right half upper facing west powered false open false 3343 iron_door hinge left half lower facing west powered true open true 3344 iron_door hinge left half lower facing west powered false open true 3345 iron_door hinge left half lower facing west powered true open false 3346 iron_door hinge left half lower facing west powered false open false 3347 iron_door hinge right half lower facing west powered true open true 3348 iron_door hinge right half lower facing west powered false open true 3349 iron_door hinge right half lower facing west powered true open false 3350 iron_door hinge right half lower facing west powered false open false 3351 iron_door hinge left half upper facing east powered true open true 3352 iron_door hinge left half upper facing east powered false open true 3353 iron_door hinge left half upper facing east powered true open false 3354 iron_door hinge left half upper facing east powered false open false 3355 iron_door hinge right half upper facing east powered true open true 3356 iron_door hinge right half upper facing east powered false open true 3357 iron_door hinge right half upper facing east powered true open false 3358 iron_door hinge right half upper facing east powered false open false 3359 iron_door hinge left half lower facing east powered true open true 3360 iron_door hinge left half lower facing east powered false open true 3361 iron_door hinge left half lower facing east powered true open false 3362 iron_door hinge left half lower facing east powered false open false 3363 iron_door hinge right half lower facing east powered true open true 3364 iron_door hinge right half lower facing east powered false open true 3365 iron_door hinge right half lower facing east powered true open false 3366 iron_door hinge right half lower facing east powered false open false 3367 oak_pressure_plate powered true 3368 oak_pressure_plate powered false 3369 spruce_pressure_plate powered true 3370 spruce_pressure_plate powered false 3371 birch_pressure_plate powered true 3372 birch_pressure_plate powered false 3373 jungle_pressure_plate powered true 3374 jungle_pressure_plate powered false 3375 acacia_pressure_plate powered true 3376 acacia_pressure_plate powered false 3377 dark_oak_pressure_plate powered true 3378 dark_oak_pressure_plate powered false 3379 redstone_ore lit true 3380 redstone_ore lit false 3381 redstone_torch lit true 3382 redstone_torch lit false 3383 redstone_wall_torch facing north lit true 3384 redstone_wall_torch facing north lit false 3385 redstone_wall_torch facing south lit true 3386 redstone_wall_torch facing south lit false 3387 redstone_wall_torch facing west lit true 3388 redstone_wall_torch facing west lit false 3389 redstone_wall_torch facing east lit true 3390 redstone_wall_torch facing east lit false 3391 stone_button facing north face floor powered true 3392 stone_button facing north face floor powered false 3393 stone_button facing south face floor powered true 3394 stone_button facing south face floor powered false 3395 stone_button facing west face floor powered true 3396 stone_button facing west face floor powered false 3397 stone_button facing east face floor powered true 3398 stone_button facing east face floor powered false 3399 stone_button facing north face wall powered true 3400 stone_button facing north face wall powered false 3401 stone_button facing south face wall powered true 3402 stone_button facing south face wall powered false 3403 stone_button facing west face wall powered true 3404 stone_button facing west face wall powered false 3405 stone_button facing east face wall powered true 3406 stone_button facing east face wall powered false 3407 stone_button facing north face ceiling powered true 3408 stone_button facing north face ceiling powered false 3409 stone_button facing south face ceiling powered true 3410 stone_button facing south face ceiling powered false 3411 stone_button facing west face ceiling powered true 3412 stone_button facing west face ceiling powered false 3413 stone_button facing east face ceiling powered true 3414 stone_button facing east face ceiling powered false 3415 snow layers 1 3416 snow layers 2 3417 snow layers 3 3418 snow layers 4 3419 snow layers 5 3420 snow layers 6 3421 snow layers 7 3422 snow layers 8 3423 ice 3424 snow_block 3425 cactus age 0 3426 cactus age 1 3427 cactus age 2 3428 cactus age 3 3429 cactus age 4 3430 cactus age 5 3431 cactus age 6 3432 cactus age 7 3433 cactus age 8 3434 cactus age 9 3435 cactus age 10 3436 cactus age 11 3437 cactus age 12 3438 cactus age 13 3439 cactus age 14 3440 cactus age 15 3441 clay 3442 sugar_cane age 0 3443 sugar_cane age 1 3444 sugar_cane age 2 3445 sugar_cane age 3 3446 sugar_cane age 4 3447 sugar_cane age 5 3448 sugar_cane age 6 3449 sugar_cane age 7 3450 sugar_cane age 8 3451 sugar_cane age 9 3452 sugar_cane age 10 3453 sugar_cane age 11 3454 sugar_cane age 12 3455 sugar_cane age 13 3456 sugar_cane age 14 3457 sugar_cane age 15 3458 jukebox has_record true 3459 jukebox has_record false 3460 oak_fence waterlogged true south true east true north true west true 3461 oak_fence waterlogged true south true east true north true west false 3462 oak_fence waterlogged false south true east true north true west true 3463 oak_fence waterlogged false south true east true north true west false 3464 oak_fence waterlogged true south false east true north true west true 3465 oak_fence waterlogged true south false east true north true west false 3466 oak_fence waterlogged false south false east true north true west true 3467 oak_fence waterlogged false south false east true north true west false 3468 oak_fence waterlogged true south true east true north false west true 3469 oak_fence waterlogged true south true east true north false west false 3470 oak_fence waterlogged false south true east true north false west true 3471 oak_fence waterlogged false south true east true north false west false 3472 oak_fence waterlogged true south false east true north false west true 3473 oak_fence waterlogged true south false east true north false west false 3474 oak_fence waterlogged false south false east true north false west true 3475 oak_fence waterlogged false south false east true north false west false 3476 oak_fence waterlogged true south true east false north true west true 3477 oak_fence waterlogged true south true east false north true west false 3478 oak_fence waterlogged false south true east false north true west true 3479 oak_fence waterlogged false south true east false north true west false 3480 oak_fence waterlogged true south false east false north true west true 3481 oak_fence waterlogged true south false east false north true west false 3482 oak_fence waterlogged false south false east false north true west true 3483 oak_fence waterlogged false south false east false north true west false 3484 oak_fence waterlogged true south true east false north false west true 3485 oak_fence waterlogged true south true east false north false west false 3486 oak_fence waterlogged false south true east false north false west true 3487 oak_fence waterlogged false south true east false north false west false 3488 oak_fence waterlogged true south false east false north false west true 3489 oak_fence waterlogged true south false east false north false west false 3490 oak_fence waterlogged false south false east false north false west true 3491 oak_fence waterlogged false south false east false north false west false 3492 pumpkin 3493 netherrack 3494 soul_sand 3495 glowstone 3496 nether_portal axis x 3497 nether_portal axis z 3498 carved_pumpkin facing north 3499 carved_pumpkin facing south 3500 carved_pumpkin facing west 3501 carved_pumpkin facing east 3502 jack_o_lantern facing north 3503 jack_o_lantern facing south 3504 jack_o_lantern facing west 3505 jack_o_lantern facing east 3506 cake bites 0 3507 cake bites 1 3508 cake bites 2 3509 cake bites 3 3510 cake bites 4 3511 cake bites 5 3512 cake bites 6 3513 repeater facing north powered true locked true delay 1 3514 repeater facing north powered false locked true delay 1 3515 repeater facing north powered true locked false delay 1 3516 repeater facing north powered false locked false delay 1 3517 repeater facing south powered true locked true delay 1 3518 repeater facing south powered false locked true delay 1 3519 repeater facing south powered true locked false delay 1 3520 repeater facing south powered false locked false delay 1 3521 repeater facing west powered true locked true delay 1 3522 repeater facing west powered false locked true delay 1 3523 repeater facing west powered true locked false delay 1 3524 repeater facing west powered false locked false delay 1 3525 repeater facing east powered true locked true delay 1 3526 repeater facing east powered false locked true delay 1 3527 repeater facing east powered true locked false delay 1 3528 repeater facing east powered false locked false delay 1 3529 repeater facing north powered true locked true delay 2 3530 repeater facing north powered false locked true delay 2 3531 repeater facing north powered true locked false delay 2 3532 repeater facing north powered false locked false delay 2 3533 repeater facing south powered true locked true delay 2 3534 repeater facing south powered false locked true delay 2 3535 repeater facing south powered true locked false delay 2 3536 repeater facing south powered false locked false delay 2 3537 repeater facing west powered true locked true delay 2 3538 repeater facing west powered false locked true delay 2 3539 repeater facing west powered true locked false delay 2 3540 repeater facing west powered false locked false delay 2 3541 repeater facing east powered true locked true delay 2 3542 repeater facing east powered false locked true delay 2 3543 repeater facing east powered true locked false delay 2 3544 repeater facing east powered false locked false delay 2 3545 repeater facing north powered true locked true delay 3 3546 repeater facing north powered false locked true delay 3 3547 repeater facing north powered true locked false delay 3 3548 repeater facing north powered false locked false delay 3 3549 repeater facing south powered true locked true delay 3 3550 repeater facing south powered false locked true delay 3 3551 repeater facing south powered true locked false delay 3 3552 repeater facing south powered false locked false delay 3 3553 repeater facing west powered true locked true delay 3 3554 repeater facing west powered false locked true delay 3 3555 repeater facing west powered true locked false delay 3 3556 repeater facing west powered false locked false delay 3 3557 repeater facing east powered true locked true delay 3 3558 repeater facing east powered false locked true delay 3 3559 repeater facing east powered true locked false delay 3 3560 repeater facing east powered false locked false delay 3 3561 repeater facing north powered true locked true delay 4 3562 repeater facing north powered false locked true delay 4 3563 repeater facing north powered true locked false delay 4 3564 repeater facing north powered false locked false delay 4 3565 repeater facing south powered true locked true delay 4 3566 repeater facing south powered false locked true delay 4 3567 repeater facing south powered true locked false delay 4 3568 repeater facing south powered false locked false delay 4 3569 repeater facing west powered true locked true delay 4 3570 repeater facing west powered false locked true delay 4 3571 repeater facing west powered true locked false delay 4 3572 repeater facing west powered false locked false delay 4 3573 repeater facing east powered true locked true delay 4 3574 repeater facing east powered false locked true delay 4 3575 repeater facing east powered true locked false delay 4 3576 repeater facing east powered false locked false delay 4 3577 white_stained_glass 3578 orange_stained_glass 3579 magenta_stained_glass 3580 light_blue_stained_glass 3581 yellow_stained_glass 3582 lime_stained_glass 3583 pink_stained_glass 3584 gray_stained_glass 3585 light_gray_stained_glass 3586 cyan_stained_glass 3587 purple_stained_glass 3588 blue_stained_glass 3589 brown_stained_glass 3590 green_stained_glass 3591 red_stained_glass 3592 black_stained_glass 3593 oak_trapdoor waterlogged true powered true facing north half top open true 3594 oak_trapdoor waterlogged false powered true facing north half top open true 3595 oak_trapdoor waterlogged true powered false facing north half top open true 3596 oak_trapdoor waterlogged false powered false facing north half top open true 3597 oak_trapdoor waterlogged true powered true facing north half top open false 3598 oak_trapdoor waterlogged false powered true facing north half top open false 3599 oak_trapdoor waterlogged true powered false facing north half top open false 3600 oak_trapdoor waterlogged false powered false facing north half top open false 3601 oak_trapdoor waterlogged true powered true facing north half bottom open true 3602 oak_trapdoor waterlogged false powered true facing north half bottom open true 3603 oak_trapdoor waterlogged true powered false facing north half bottom open true 3604 oak_trapdoor waterlogged false powered false facing north half bottom open true 3605 oak_trapdoor waterlogged true powered true facing north half bottom open false 3606 oak_trapdoor waterlogged false powered true facing north half bottom open false 3607 oak_trapdoor waterlogged true powered false facing north half bottom open false 3608 oak_trapdoor waterlogged false powered false facing north half bottom open false 3609 oak_trapdoor waterlogged true powered true facing south half top open true 3610 oak_trapdoor waterlogged false powered true facing south half top open true 3611 oak_trapdoor waterlogged true powered false facing south half top open true 3612 oak_trapdoor waterlogged false powered false facing south half top open true 3613 oak_trapdoor waterlogged true powered true facing south half top open false 3614 oak_trapdoor waterlogged false powered true facing south half top open false 3615 oak_trapdoor waterlogged true powered false facing south half top open false 3616 oak_trapdoor waterlogged false powered false facing south half top open false 3617 oak_trapdoor waterlogged true powered true facing south half bottom open true 3618 oak_trapdoor waterlogged false powered true facing south half bottom open true 3619 oak_trapdoor waterlogged true powered false facing south half bottom open true 3620 oak_trapdoor waterlogged false powered false facing south half bottom open true 3621 oak_trapdoor waterlogged true powered true facing south half bottom open false 3622 oak_trapdoor waterlogged false powered true facing south half bottom open false 3623 oak_trapdoor waterlogged true powered false facing south half bottom open false 3624 oak_trapdoor waterlogged false powered false facing south half bottom open false 3625 oak_trapdoor waterlogged true powered true facing west half top open true 3626 oak_trapdoor waterlogged false powered true facing west half top open true 3627 oak_trapdoor waterlogged true powered false facing west half top open true 3628 oak_trapdoor waterlogged false powered false facing west half top open true 3629 oak_trapdoor waterlogged true powered true facing west half top open false 3630 oak_trapdoor waterlogged false powered true facing west half top open false 3631 oak_trapdoor waterlogged true powered false facing west half top open false 3632 oak_trapdoor waterlogged false powered false facing west half top open false 3633 oak_trapdoor waterlogged true powered true facing west half bottom open true 3634 oak_trapdoor waterlogged false powered true facing west half bottom open true 3635 oak_trapdoor waterlogged true powered false facing west half bottom open true 3636 oak_trapdoor waterlogged false powered false facing west half bottom open true 3637 oak_trapdoor waterlogged true powered true facing west half bottom open false 3638 oak_trapdoor waterlogged false powered true facing west half bottom open false 3639 oak_trapdoor waterlogged true powered false facing west half bottom open false 3640 oak_trapdoor waterlogged false powered false facing west half bottom open false 3641 oak_trapdoor waterlogged true powered true facing east half top open true 3642 oak_trapdoor waterlogged false powered true facing east half top open true 3643 oak_trapdoor waterlogged true powered false facing east half top open true 3644 oak_trapdoor waterlogged false powered false facing east half top open true 3645 oak_trapdoor waterlogged true powered true facing east half top open false 3646 oak_trapdoor waterlogged false powered true facing east half top open false 3647 oak_trapdoor waterlogged true powered false facing east half top open false 3648 oak_trapdoor waterlogged false powered false facing east half top open false 3649 oak_trapdoor waterlogged true powered true facing east half bottom open true 3650 oak_trapdoor waterlogged false powered true facing east half bottom open true 3651 oak_trapdoor waterlogged true powered false facing east half bottom open true 3652 oak_trapdoor waterlogged false powered false facing east half bottom open true 3653 oak_trapdoor waterlogged true powered true facing east half bottom open false 3654 oak_trapdoor waterlogged false powered true facing east half bottom open false 3655 oak_trapdoor waterlogged true powered false facing east half bottom open false 3656 oak_trapdoor waterlogged false powered false facing east half bottom open false 3657 spruce_trapdoor waterlogged true powered true facing north half top open true 3658 spruce_trapdoor waterlogged false powered true facing north half top open true 3659 spruce_trapdoor waterlogged true powered false facing north half top open true 3660 spruce_trapdoor waterlogged false powered false facing north half top open true 3661 spruce_trapdoor waterlogged true powered true facing north half top open false 3662 spruce_trapdoor waterlogged false powered true facing north half top open false 3663 spruce_trapdoor waterlogged true powered false facing north half top open false 3664 spruce_trapdoor waterlogged false powered false facing north half top open false 3665 spruce_trapdoor waterlogged true powered true facing north half bottom open true 3666 spruce_trapdoor waterlogged false powered true facing north half bottom open true 3667 spruce_trapdoor waterlogged true powered false facing north half bottom open true 3668 spruce_trapdoor waterlogged false powered false facing north half bottom open true 3669 spruce_trapdoor waterlogged true powered true facing north half bottom open false 3670 spruce_trapdoor waterlogged false powered true facing north half bottom open false 3671 spruce_trapdoor waterlogged true powered false facing north half bottom open false 3672 spruce_trapdoor waterlogged false powered false facing north half bottom open false 3673 spruce_trapdoor waterlogged true powered true facing south half top open true 3674 spruce_trapdoor waterlogged false powered true facing south half top open true 3675 spruce_trapdoor waterlogged true powered false facing south half top open true 3676 spruce_trapdoor waterlogged false powered false facing south half top open true 3677 spruce_trapdoor waterlogged true powered true facing south half top open false 3678 spruce_trapdoor waterlogged false powered true facing south half top open false 3679 spruce_trapdoor waterlogged true powered false facing south half top open false 3680 spruce_trapdoor waterlogged false powered false facing south half top open false 3681 spruce_trapdoor waterlogged true powered true facing south half bottom open true 3682 spruce_trapdoor waterlogged false powered true facing south half bottom open true 3683 spruce_trapdoor waterlogged true powered false facing south half bottom open true 3684 spruce_trapdoor waterlogged false powered false facing south half bottom open true 3685 spruce_trapdoor waterlogged true powered true facing south half bottom open false 3686 spruce_trapdoor waterlogged false powered true facing south half bottom open false 3687 spruce_trapdoor waterlogged true powered false facing south half bottom open false 3688 spruce_trapdoor waterlogged false powered false facing south half bottom open false 3689 spruce_trapdoor waterlogged true powered true facing west half top open true 3690 spruce_trapdoor waterlogged false powered true facing west half top open true 3691 spruce_trapdoor waterlogged true powered false facing west half top open true 3692 spruce_trapdoor waterlogged false powered false facing west half top open true 3693 spruce_trapdoor waterlogged true powered true facing west half top open false 3694 spruce_trapdoor waterlogged false powered true facing west half top open false 3695 spruce_trapdoor waterlogged true powered false facing west half top open false 3696 spruce_trapdoor waterlogged false powered false facing west half top open false 3697 spruce_trapdoor waterlogged true powered true facing west half bottom open true 3698 spruce_trapdoor waterlogged false powered true facing west half bottom open true 3699 spruce_trapdoor waterlogged true powered false facing west half bottom open true 3700 spruce_trapdoor waterlogged false powered false facing west half bottom open true 3701 spruce_trapdoor waterlogged true powered true facing west half bottom open false 3702 spruce_trapdoor waterlogged false powered true facing west half bottom open false 3703 spruce_trapdoor waterlogged true powered false facing west half bottom open false 3704 spruce_trapdoor waterlogged false powered false facing west half bottom open false 3705 spruce_trapdoor waterlogged true powered true facing east half top open true 3706 spruce_trapdoor waterlogged false powered true facing east half top open true 3707 spruce_trapdoor waterlogged true powered false facing east half top open true 3708 spruce_trapdoor waterlogged false powered false facing east half top open true 3709 spruce_trapdoor waterlogged true powered true facing east half top open false 3710 spruce_trapdoor waterlogged false powered true facing east half top open false 3711 spruce_trapdoor waterlogged true powered false facing east half top open false 3712 spruce_trapdoor waterlogged false powered false facing east half top open false 3713 spruce_trapdoor waterlogged true powered true facing east half bottom open true 3714 spruce_trapdoor waterlogged false powered true facing east half bottom open true 3715 spruce_trapdoor waterlogged true powered false facing east half bottom open true 3716 spruce_trapdoor waterlogged false powered false facing east half bottom open true 3717 spruce_trapdoor waterlogged true powered true facing east half bottom open false 3718 spruce_trapdoor waterlogged false powered true facing east half bottom open false 3719 spruce_trapdoor waterlogged true powered false facing east half bottom open false 3720 spruce_trapdoor waterlogged false powered false facing east half bottom open false 3721 birch_trapdoor waterlogged true powered true facing north half top open true 3722 birch_trapdoor waterlogged false powered true facing north half top open true 3723 birch_trapdoor waterlogged true powered false facing north half top open true 3724 birch_trapdoor waterlogged false powered false facing north half top open true 3725 birch_trapdoor waterlogged true powered true facing north half top open false 3726 birch_trapdoor waterlogged false powered true facing north half top open false 3727 birch_trapdoor waterlogged true powered false facing north half top open false 3728 birch_trapdoor waterlogged false powered false facing north half top open false 3729 birch_trapdoor waterlogged true powered true facing north half bottom open true 3730 birch_trapdoor waterlogged false powered true facing north half bottom open true 3731 birch_trapdoor waterlogged true powered false facing north half bottom open true 3732 birch_trapdoor waterlogged false powered false facing north half bottom open true 3733 birch_trapdoor waterlogged true powered true facing north half bottom open false 3734 birch_trapdoor waterlogged false powered true facing north half bottom open false 3735 birch_trapdoor waterlogged true powered false facing north half bottom open false 3736 birch_trapdoor waterlogged false powered false facing north half bottom open false 3737 birch_trapdoor waterlogged true powered true facing south half top open true 3738 birch_trapdoor waterlogged false powered true facing south half top open true 3739 birch_trapdoor waterlogged true powered false facing south half top open true 3740 birch_trapdoor waterlogged false powered false facing south half top open true 3741 birch_trapdoor waterlogged true powered true facing south half top open false 3742 birch_trapdoor waterlogged false powered true facing south half top open false 3743 birch_trapdoor waterlogged true powered false facing south half top open false 3744 birch_trapdoor waterlogged false powered false facing south half top open false 3745 birch_trapdoor waterlogged true powered true facing south half bottom open true 3746 birch_trapdoor waterlogged false powered true facing south half bottom open true 3747 birch_trapdoor waterlogged true powered false facing south half bottom open true 3748 birch_trapdoor waterlogged false powered false facing south half bottom open true 3749 birch_trapdoor waterlogged true powered true facing south half bottom open false 3750 birch_trapdoor waterlogged false powered true facing south half bottom open false 3751 birch_trapdoor waterlogged true powered false facing south half bottom open false 3752 birch_trapdoor waterlogged false powered false facing south half bottom open false 3753 birch_trapdoor waterlogged true powered true facing west half top open true 3754 birch_trapdoor waterlogged false powered true facing west half top open true 3755 birch_trapdoor waterlogged true powered false facing west half top open true 3756 birch_trapdoor waterlogged false powered false facing west half top open true 3757 birch_trapdoor waterlogged true powered true facing west half top open false 3758 birch_trapdoor waterlogged false powered true facing west half top open false 3759 birch_trapdoor waterlogged true powered false facing west half top open false 3760 birch_trapdoor waterlogged false powered false facing west half top open false 3761 birch_trapdoor waterlogged true powered true facing west half bottom open true 3762 birch_trapdoor waterlogged false powered true facing west half bottom open true 3763 birch_trapdoor waterlogged true powered false facing west half bottom open true 3764 birch_trapdoor waterlogged false powered false facing west half bottom open true 3765 birch_trapdoor waterlogged true powered true facing west half bottom open false 3766 birch_trapdoor waterlogged false powered true facing west half bottom open false 3767 birch_trapdoor waterlogged true powered false facing west half bottom open false 3768 birch_trapdoor waterlogged false powered false facing west half bottom open false 3769 birch_trapdoor waterlogged true powered true facing east half top open true 3770 birch_trapdoor waterlogged false powered true facing east half top open true 3771 birch_trapdoor waterlogged true powered false facing east half top open true 3772 birch_trapdoor waterlogged false powered false facing east half top open true 3773 birch_trapdoor waterlogged true powered true facing east half top open false 3774 birch_trapdoor waterlogged false powered true facing east half top open false 3775 birch_trapdoor waterlogged true powered false facing east half top open false 3776 birch_trapdoor waterlogged false powered false facing east half top open false 3777 birch_trapdoor waterlogged true powered true facing east half bottom open true 3778 birch_trapdoor waterlogged false powered true facing east half bottom open true 3779 birch_trapdoor waterlogged true powered false facing east half bottom open true 3780 birch_trapdoor waterlogged false powered false facing east half bottom open true 3781 birch_trapdoor waterlogged true powered true facing east half bottom open false 3782 birch_trapdoor waterlogged false powered true facing east half bottom open false 3783 birch_trapdoor waterlogged true powered false facing east half bottom open false 3784 birch_trapdoor waterlogged false powered false facing east half bottom open false 3785 jungle_trapdoor waterlogged true powered true facing north half top open true 3786 jungle_trapdoor waterlogged false powered true facing north half top open true 3787 jungle_trapdoor waterlogged true powered false facing north half top open true 3788 jungle_trapdoor waterlogged false powered false facing north half top open true 3789 jungle_trapdoor waterlogged true powered true facing north half top open false 3790 jungle_trapdoor waterlogged false powered true facing north half top open false 3791 jungle_trapdoor waterlogged true powered false facing north half top open false 3792 jungle_trapdoor waterlogged false powered false facing north half top open false 3793 jungle_trapdoor waterlogged true powered true facing north half bottom open true 3794 jungle_trapdoor waterlogged false powered true facing north half bottom open true 3795 jungle_trapdoor waterlogged true powered false facing north half bottom open true 3796 jungle_trapdoor waterlogged false powered false facing north half bottom open true 3797 jungle_trapdoor waterlogged true powered true facing north half bottom open false 3798 jungle_trapdoor waterlogged false powered true facing north half bottom open false 3799 jungle_trapdoor waterlogged true powered false facing north half bottom open false 3800 jungle_trapdoor waterlogged false powered false facing north half bottom open false 3801 jungle_trapdoor waterlogged true powered true facing south half top open true 3802 jungle_trapdoor waterlogged false powered true facing south half top open true 3803 jungle_trapdoor waterlogged true powered false facing south half top open true 3804 jungle_trapdoor waterlogged false powered false facing south half top open true 3805 jungle_trapdoor waterlogged true powered true facing south half top open false 3806 jungle_trapdoor waterlogged false powered true facing south half top open false 3807 jungle_trapdoor waterlogged true powered false facing south half top open false 3808 jungle_trapdoor waterlogged false powered false facing south half top open false 3809 jungle_trapdoor waterlogged true powered true facing south half bottom open true 3810 jungle_trapdoor waterlogged false powered true facing south half bottom open true 3811 jungle_trapdoor waterlogged true powered false facing south half bottom open true 3812 jungle_trapdoor waterlogged false powered false facing south half bottom open true 3813 jungle_trapdoor waterlogged true powered true facing south half bottom open false 3814 jungle_trapdoor waterlogged false powered true facing south half bottom open false 3815 jungle_trapdoor waterlogged true powered false facing south half bottom open false 3816 jungle_trapdoor waterlogged false powered false facing south half bottom open false 3817 jungle_trapdoor waterlogged true powered true facing west half top open true 3818 jungle_trapdoor waterlogged false powered true facing west half top open true 3819 jungle_trapdoor waterlogged true powered false facing west half top open true 3820 jungle_trapdoor waterlogged false powered false facing west half top open true 3821 jungle_trapdoor waterlogged true powered true facing west half top open false 3822 jungle_trapdoor waterlogged false powered true facing west half top open false 3823 jungle_trapdoor waterlogged true powered false facing west half top open false 3824 jungle_trapdoor waterlogged false powered false facing west half top open false 3825 jungle_trapdoor waterlogged true powered true facing west half bottom open true 3826 jungle_trapdoor waterlogged false powered true facing west half bottom open true 3827 jungle_trapdoor waterlogged true powered false facing west half bottom open true 3828 jungle_trapdoor waterlogged false powered false facing west half bottom open true 3829 jungle_trapdoor waterlogged true powered true facing west half bottom open false 3830 jungle_trapdoor waterlogged false powered true facing west half bottom open false 3831 jungle_trapdoor waterlogged true powered false facing west half bottom open false 3832 jungle_trapdoor waterlogged false powered false facing west half bottom open false 3833 jungle_trapdoor waterlogged true powered true facing east half top open true 3834 jungle_trapdoor waterlogged false powered true facing east half top open true 3835 jungle_trapdoor waterlogged true powered false facing east half top open true 3836 jungle_trapdoor waterlogged false powered false facing east half top open true 3837 jungle_trapdoor waterlogged true powered true facing east half top open false 3838 jungle_trapdoor waterlogged false powered true facing east half top open false 3839 jungle_trapdoor waterlogged true powered false facing east half top open false 3840 jungle_trapdoor waterlogged false powered false facing east half top open false 3841 jungle_trapdoor waterlogged true powered true facing east half bottom open true 3842 jungle_trapdoor waterlogged false powered true facing east half bottom open true 3843 jungle_trapdoor waterlogged true powered false facing east half bottom open true 3844 jungle_trapdoor waterlogged false powered false facing east half bottom open true 3845 jungle_trapdoor waterlogged true powered true facing east half bottom open false 3846 jungle_trapdoor waterlogged false powered true facing east half bottom open false 3847 jungle_trapdoor waterlogged true powered false facing east half bottom open false 3848 jungle_trapdoor waterlogged false powered false facing east half bottom open false 3849 acacia_trapdoor waterlogged true powered true facing north half top open true 3850 acacia_trapdoor waterlogged false powered true facing north half top open true 3851 acacia_trapdoor waterlogged true powered false facing north half top open true 3852 acacia_trapdoor waterlogged false powered false facing north half top open true 3853 acacia_trapdoor waterlogged true powered true facing north half top open false 3854 acacia_trapdoor waterlogged false powered true facing north half top open false 3855 acacia_trapdoor waterlogged true powered false facing north half top open false 3856 acacia_trapdoor waterlogged false powered false facing north half top open false 3857 acacia_trapdoor waterlogged true powered true facing north half bottom open true 3858 acacia_trapdoor waterlogged false powered true facing north half bottom open true 3859 acacia_trapdoor waterlogged true powered false facing north half bottom open true 3860 acacia_trapdoor waterlogged false powered false facing north half bottom open true 3861 acacia_trapdoor waterlogged true powered true facing north half bottom open false 3862 acacia_trapdoor waterlogged false powered true facing north half bottom open false 3863 acacia_trapdoor waterlogged true powered false facing north half bottom open false 3864 acacia_trapdoor waterlogged false powered false facing north half bottom open false 3865 acacia_trapdoor waterlogged true powered true facing south half top open true 3866 acacia_trapdoor waterlogged false powered true facing south half top open true 3867 acacia_trapdoor waterlogged true powered false facing south half top open true 3868 acacia_trapdoor waterlogged false powered false facing south half top open true 3869 acacia_trapdoor waterlogged true powered true facing south half top open false 3870 acacia_trapdoor waterlogged false powered true facing south half top open false 3871 acacia_trapdoor waterlogged true powered false facing south half top open false 3872 acacia_trapdoor waterlogged false powered false facing south half top open false 3873 acacia_trapdoor waterlogged true powered true facing south half bottom open true 3874 acacia_trapdoor waterlogged false powered true facing south half bottom open true 3875 acacia_trapdoor waterlogged true powered false facing south half bottom open true 3876 acacia_trapdoor waterlogged false powered false facing south half bottom open true 3877 acacia_trapdoor waterlogged true powered true facing south half bottom open false 3878 acacia_trapdoor waterlogged false powered true facing south half bottom open false 3879 acacia_trapdoor waterlogged true powered false facing south half bottom open false 3880 acacia_trapdoor waterlogged false powered false facing south half bottom open false 3881 acacia_trapdoor waterlogged true powered true facing west half top open true 3882 acacia_trapdoor waterlogged false powered true facing west half top open true 3883 acacia_trapdoor waterlogged true powered false facing west half top open true 3884 acacia_trapdoor waterlogged false powered false facing west half top open true 3885 acacia_trapdoor waterlogged true powered true facing west half top open false 3886 acacia_trapdoor waterlogged false powered true facing west half top open false 3887 acacia_trapdoor waterlogged true powered false facing west half top open false 3888 acacia_trapdoor waterlogged false powered false facing west half top open false 3889 acacia_trapdoor waterlogged true powered true facing west half bottom open true 3890 acacia_trapdoor waterlogged false powered true facing west half bottom open true 3891 acacia_trapdoor waterlogged true powered false facing west half bottom open true 3892 acacia_trapdoor waterlogged false powered false facing west half bottom open true 3893 acacia_trapdoor waterlogged true powered true facing west half bottom open false 3894 acacia_trapdoor waterlogged false powered true facing west half bottom open false 3895 acacia_trapdoor waterlogged true powered false facing west half bottom open false 3896 acacia_trapdoor waterlogged false powered false facing west half bottom open false 3897 acacia_trapdoor waterlogged true powered true facing east half top open true 3898 acacia_trapdoor waterlogged false powered true facing east half top open true 3899 acacia_trapdoor waterlogged true powered false facing east half top open true 3900 acacia_trapdoor waterlogged false powered false facing east half top open true 3901 acacia_trapdoor waterlogged true powered true facing east half top open false 3902 acacia_trapdoor waterlogged false powered true facing east half top open false 3903 acacia_trapdoor waterlogged true powered false facing east half top open false 3904 acacia_trapdoor waterlogged false powered false facing east half top open false 3905 acacia_trapdoor waterlogged true powered true facing east half bottom open true 3906 acacia_trapdoor waterlogged false powered true facing east half bottom open true 3907 acacia_trapdoor waterlogged true powered false facing east half bottom open true 3908 acacia_trapdoor waterlogged false powered false facing east half bottom open true 3909 acacia_trapdoor waterlogged true powered true facing east half bottom open false 3910 acacia_trapdoor waterlogged false powered true facing east half bottom open false 3911 acacia_trapdoor waterlogged true powered false facing east half bottom open false 3912 acacia_trapdoor waterlogged false powered false facing east half bottom open false 3913 dark_oak_trapdoor waterlogged true powered true facing north half top open true 3914 dark_oak_trapdoor waterlogged false powered true facing north half top open true 3915 dark_oak_trapdoor waterlogged true powered false facing north half top open true 3916 dark_oak_trapdoor waterlogged false powered false facing north half top open true 3917 dark_oak_trapdoor waterlogged true powered true facing north half top open false 3918 dark_oak_trapdoor waterlogged false powered true facing north half top open false 3919 dark_oak_trapdoor waterlogged true powered false facing north half top open false 3920 dark_oak_trapdoor waterlogged false powered false facing north half top open false 3921 dark_oak_trapdoor waterlogged true powered true facing north half bottom open true 3922 dark_oak_trapdoor waterlogged false powered true facing north half bottom open true 3923 dark_oak_trapdoor waterlogged true powered false facing north half bottom open true 3924 dark_oak_trapdoor waterlogged false powered false facing north half bottom open true 3925 dark_oak_trapdoor waterlogged true powered true facing north half bottom open false 3926 dark_oak_trapdoor waterlogged false powered true facing north half bottom open false 3927 dark_oak_trapdoor waterlogged true powered false facing north half bottom open false 3928 dark_oak_trapdoor waterlogged false powered false facing north half bottom open false 3929 dark_oak_trapdoor waterlogged true powered true facing south half top open true 3930 dark_oak_trapdoor waterlogged false powered true facing south half top open true 3931 dark_oak_trapdoor waterlogged true powered false facing south half top open true 3932 dark_oak_trapdoor waterlogged false powered false facing south half top open true 3933 dark_oak_trapdoor waterlogged true powered true facing south half top open false 3934 dark_oak_trapdoor waterlogged false powered true facing south half top open false 3935 dark_oak_trapdoor waterlogged true powered false facing south half top open false 3936 dark_oak_trapdoor waterlogged false powered false facing south half top open false 3937 dark_oak_trapdoor waterlogged true powered true facing south half bottom open true 3938 dark_oak_trapdoor waterlogged false powered true facing south half bottom open true 3939 dark_oak_trapdoor waterlogged true powered false facing south half bottom open true 3940 dark_oak_trapdoor waterlogged false powered false facing south half bottom open true 3941 dark_oak_trapdoor waterlogged true powered true facing south half bottom open false 3942 dark_oak_trapdoor waterlogged false powered true facing south half bottom open false 3943 dark_oak_trapdoor waterlogged true powered false facing south half bottom open false 3944 dark_oak_trapdoor waterlogged false powered false facing south half bottom open false 3945 dark_oak_trapdoor waterlogged true powered true facing west half top open true 3946 dark_oak_trapdoor waterlogged false powered true facing west half top open true 3947 dark_oak_trapdoor waterlogged true powered false facing west half top open true 3948 dark_oak_trapdoor waterlogged false powered false facing west half top open true 3949 dark_oak_trapdoor waterlogged true powered true facing west half top open false 3950 dark_oak_trapdoor waterlogged false powered true facing west half top open false 3951 dark_oak_trapdoor waterlogged true powered false facing west half top open false 3952 dark_oak_trapdoor waterlogged false powered false facing west half top open false 3953 dark_oak_trapdoor waterlogged true powered true facing west half bottom open true 3954 dark_oak_trapdoor waterlogged false powered true facing west half bottom open true 3955 dark_oak_trapdoor waterlogged true powered false facing west half bottom open true 3956 dark_oak_trapdoor waterlogged false powered false facing west half bottom open true 3957 dark_oak_trapdoor waterlogged true powered true facing west half bottom open false 3958 dark_oak_trapdoor waterlogged false powered true facing west half bottom open false 3959 dark_oak_trapdoor waterlogged true powered false facing west half bottom open false 3960 dark_oak_trapdoor waterlogged false powered false facing west half bottom open false 3961 dark_oak_trapdoor waterlogged true powered true facing east half top open true 3962 dark_oak_trapdoor waterlogged false powered true facing east half top open true 3963 dark_oak_trapdoor waterlogged true powered false facing east half top open true 3964 dark_oak_trapdoor waterlogged false powered false facing east half top open true 3965 dark_oak_trapdoor waterlogged true powered true facing east half top open false 3966 dark_oak_trapdoor waterlogged false powered true facing east half top open false 3967 dark_oak_trapdoor waterlogged true powered false facing east half top open false 3968 dark_oak_trapdoor waterlogged false powered false facing east half top open false 3969 dark_oak_trapdoor waterlogged true powered true facing east half bottom open true 3970 dark_oak_trapdoor waterlogged false powered true facing east half bottom open true 3971 dark_oak_trapdoor waterlogged true powered false facing east half bottom open true 3972 dark_oak_trapdoor waterlogged false powered false facing east half bottom open true 3973 dark_oak_trapdoor waterlogged true powered true facing east half bottom open false 3974 dark_oak_trapdoor waterlogged false powered true facing east half bottom open false 3975 dark_oak_trapdoor waterlogged true powered false facing east half bottom open false 3976 dark_oak_trapdoor waterlogged false powered false facing east half bottom open false 3977 infested_stone 3978 infested_cobblestone 3979 infested_stone_bricks 3980 infested_mossy_stone_bricks 3981 infested_cracked_stone_bricks 3982 infested_chiseled_stone_bricks 3983 stone_bricks 3984 mossy_stone_bricks 3985 cracked_stone_bricks 3986 chiseled_stone_bricks 3987 brown_mushroom_block up true south true east true north true down true west true 3988 brown_mushroom_block up true south true east true north true down true west false 3989 brown_mushroom_block up false south true east true north true down true west true 3990 brown_mushroom_block up false south true east true north true down true west false 3991 brown_mushroom_block up true south false east true north true down true west true 3992 brown_mushroom_block up true south false east true north true down true west false 3993 brown_mushroom_block up false south false east true north true down true west true 3994 brown_mushroom_block up false south false east true north true down true west false 3995 brown_mushroom_block up true south true east true north false down true west true 3996 brown_mushroom_block up true south true east true north false down true west false 3997 brown_mushroom_block up false south true east true north false down true west true 3998 brown_mushroom_block up false south true east true north false down true west false 3999 brown_mushroom_block up true south false east true north false down true west true 4000 brown_mushroom_block up true south false east true north false down true west false 4001 brown_mushroom_block up false south false east true north false down true west true 4002 brown_mushroom_block up false south false east true north false down true west false 4003 brown_mushroom_block up true south true east false north true down true west true 4004 brown_mushroom_block up true south true east false north true down true west false 4005 brown_mushroom_block up false south true east false north true down true west true 4006 brown_mushroom_block up false south true east false north true down true west false 4007 brown_mushroom_block up true south false east false north true down true west true 4008 brown_mushroom_block up true south false east false north true down true west false 4009 brown_mushroom_block up false south false east false north true down true west true 4010 brown_mushroom_block up false south false east false north true down true west false 4011 brown_mushroom_block up true south true east false north false down true west true 4012 brown_mushroom_block up true south true east false north false down true west false 4013 brown_mushroom_block up false south true east false north false down true west true 4014 brown_mushroom_block up false south true east false north false down true west false 4015 brown_mushroom_block up true south false east false north false down true west true 4016 brown_mushroom_block up true south false east false north false down true west false 4017 brown_mushroom_block up false south false east false north false down true west true 4018 brown_mushroom_block up false south false east false north false down true west false 4019 brown_mushroom_block up true south true east true north true down false west true 4020 brown_mushroom_block up true south true east true north true down false west false 4021 brown_mushroom_block up false south true east true north true down false west true 4022 brown_mushroom_block up false south true east true north true down false west false 4023 brown_mushroom_block up true south false east true north true down false west true 4024 brown_mushroom_block up true south false east true north true down false west false 4025 brown_mushroom_block up false south false east true north true down false west true 4026 brown_mushroom_block up false south false east true north true down false west false 4027 brown_mushroom_block up true south true east true north false down false west true 4028 brown_mushroom_block up true south true east true north false down false west false 4029 brown_mushroom_block up false south true east true north false down false west true 4030 brown_mushroom_block up false south true east true north false down false west false 4031 brown_mushroom_block up true south false east true north false down false west true 4032 brown_mushroom_block up true south false east true north false down false west false 4033 brown_mushroom_block up false south false east true north false down false west true 4034 brown_mushroom_block up false south false east true north false down false west false 4035 brown_mushroom_block up true south true east false north true down false west true 4036 brown_mushroom_block up true south true east false north true down false west false 4037 brown_mushroom_block up false south true east false north true down false west true 4038 brown_mushroom_block up false south true east false north true down false west false 4039 brown_mushroom_block up true south false east false north true down false west true 4040 brown_mushroom_block up true south false east false north true down false west false 4041 brown_mushroom_block up false south false east false north true down false west true 4042 brown_mushroom_block up false south false east false north true down false west false 4043 brown_mushroom_block up true south true east false north false down false west true 4044 brown_mushroom_block up true south true east false north false down false west false 4045 brown_mushroom_block up false south true east false north false down false west true 4046 brown_mushroom_block up false south true east false north false down false west false 4047 brown_mushroom_block up true south false east false north false down false west true 4048 brown_mushroom_block up true south false east false north false down false west false 4049 brown_mushroom_block up false south false east false north false down false west true 4050 brown_mushroom_block up false south false east false north false down false west false 4051 red_mushroom_block up true south true east true north true down true west true 4052 red_mushroom_block up true south true east true north true down true west false 4053 red_mushroom_block up false south true east true north true down true west true 4054 red_mushroom_block up false south true east true north true down true west false 4055 red_mushroom_block up true south false east true north true down true west true 4056 red_mushroom_block up true south false east true north true down true west false 4057 red_mushroom_block up false south false east true north true down true west true 4058 red_mushroom_block up false south false east true north true down true west false 4059 red_mushroom_block up true south true east true north false down true west true 4060 red_mushroom_block up true south true east true north false down true west false 4061 red_mushroom_block up false south true east true north false down true west true 4062 red_mushroom_block up false south true east true north false down true west false 4063 red_mushroom_block up true south false east true north false down true west true 4064 red_mushroom_block up true south false east true north false down true west false 4065 red_mushroom_block up false south false east true north false down true west true 4066 red_mushroom_block up false south false east true north false down true west false 4067 red_mushroom_block up true south true east false north true down true west true 4068 red_mushroom_block up true south true east false north true down true west false 4069 red_mushroom_block up false south true east false north true down true west true 4070 red_mushroom_block up false south true east false north true down true west false 4071 red_mushroom_block up true south false east false north true down true west true 4072 red_mushroom_block up true south false east false north true down true west false 4073 red_mushroom_block up false south false east false north true down true west true 4074 red_mushroom_block up false south false east false north true down true west false 4075 red_mushroom_block up true south true east false north false down true west true 4076 red_mushroom_block up true south true east false north false down true west false 4077 red_mushroom_block up false south true east false north false down true west true 4078 red_mushroom_block up false south true east false north false down true west false 4079 red_mushroom_block up true south false east false north false down true west true 4080 red_mushroom_block up true south false east false north false down true west false 4081 red_mushroom_block up false south false east false north false down true west true 4082 red_mushroom_block up false south false east false north false down true west false 4083 red_mushroom_block up true south true east true north true down false west true 4084 red_mushroom_block up true south true east true north true down false west false 4085 red_mushroom_block up false south true east true north true down false west true 4086 red_mushroom_block up false south true east true north true down false west false 4087 red_mushroom_block up true south false east true north true down false west true 4088 red_mushroom_block up true south false east true north true down false west false 4089 red_mushroom_block up false south false east true north true down false west true 4090 red_mushroom_block up false south false east true north true down false west false 4091 red_mushroom_block up true south true east true north false down false west true 4092 red_mushroom_block up true south true east true north false down false west false 4093 red_mushroom_block up false south true east true north false down false west true 4094 red_mushroom_block up false south true east true north false down false west false 4095 red_mushroom_block up true south false east true north false down false west true 4096 red_mushroom_block up true south false east true north false down false west false 4097 red_mushroom_block up false south false east true north false down false west true 4098 red_mushroom_block up false south false east true north false down false west false 4099 red_mushroom_block up true south true east false north true down false west true 4100 red_mushroom_block up true south true east false north true down false west false 4101 red_mushroom_block up false south true east false north true down false west true 4102 red_mushroom_block up false south true east false north true down false west false 4103 red_mushroom_block up true south false east false north true down false west true 4104 red_mushroom_block up true south false east false north true down false west false 4105 red_mushroom_block up false south false east false north true down false west true 4106 red_mushroom_block up false south false east false north true down false west false 4107 red_mushroom_block up true south true east false north false down false west true 4108 red_mushroom_block up true south true east false north false down false west false 4109 red_mushroom_block up false south true east false north false down false west true 4110 red_mushroom_block up false south true east false north false down false west false 4111 red_mushroom_block up true south false east false north false down false west true 4112 red_mushroom_block up true south false east false north false down false west false 4113 red_mushroom_block up false south false east false north false down false west true 4114 red_mushroom_block up false south false east false north false down false west false 4115 mushroom_stem up true south true east true north true down true west true 4116 mushroom_stem up true south true east true north true down true west false 4117 mushroom_stem up false south true east true north true down true west true 4118 mushroom_stem up false south true east true north true down true west false 4119 mushroom_stem up true south false east true north true down true west true 4120 mushroom_stem up true south false east true north true down true west false 4121 mushroom_stem up false south false east true north true down true west true 4122 mushroom_stem up false south false east true north true down true west false 4123 mushroom_stem up true south true east true north false down true west true 4124 mushroom_stem up true south true east true north false down true west false 4125 mushroom_stem up false south true east true north false down true west true 4126 mushroom_stem up false south true east true north false down true west false 4127 mushroom_stem up true south false east true north false down true west true 4128 mushroom_stem up true south false east true north false down true west false 4129 mushroom_stem up false south false east true north false down true west true 4130 mushroom_stem up false south false east true north false down true west false 4131 mushroom_stem up true south true east false north true down true west true 4132 mushroom_stem up true south true east false north true down true west false 4133 mushroom_stem up false south true east false north true down true west true 4134 mushroom_stem up false south true east false north true down true west false 4135 mushroom_stem up true south false east false north true down true west true 4136 mushroom_stem up true south false east false north true down true west false 4137 mushroom_stem up false south false east false north true down true west true 4138 mushroom_stem up false south false east false north true down true west false 4139 mushroom_stem up true south true east false north false down true west true 4140 mushroom_stem up true south true east false north false down true west false 4141 mushroom_stem up false south true east false north false down true west true 4142 mushroom_stem up false south true east false north false down true west false 4143 mushroom_stem up true south false east false north false down true west true 4144 mushroom_stem up true south false east false north false down true west false 4145 mushroom_stem up false south false east false north false down true west true 4146 mushroom_stem up false south false east false north false down true west false 4147 mushroom_stem up true south true east true north true down false west true 4148 mushroom_stem up true south true east true north true down false west false 4149 mushroom_stem up false south true east true north true down false west true 4150 mushroom_stem up false south true east true north true down false west false 4151 mushroom_stem up true south false east true north true down false west true 4152 mushroom_stem up true south false east true north true down false west false 4153 mushroom_stem up false south false east true north true down false west true 4154 mushroom_stem up false south false east true north true down false west false 4155 mushroom_stem up true south true east true north false down false west true 4156 mushroom_stem up true south true east true north false down false west false 4157 mushroom_stem up false south true east true north false down false west true 4158 mushroom_stem up false south true east true north false down false west false 4159 mushroom_stem up true south false east true north false down false west true 4160 mushroom_stem up true south false east true north false down false west false 4161 mushroom_stem up false south false east true north false down false west true 4162 mushroom_stem up false south false east true north false down false west false 4163 mushroom_stem up true south true east false north true down false west true 4164 mushroom_stem up true south true east false north true down false west false 4165 mushroom_stem up false south true east false north true down false west true 4166 mushroom_stem up false south true east false north true down false west false 4167 mushroom_stem up true south false east false north true down false west true 4168 mushroom_stem up true south false east false north true down false west false 4169 mushroom_stem up false south false east false north true down false west true 4170 mushroom_stem up false south false east false north true down false west false 4171 mushroom_stem up true south true east false north false down false west true 4172 mushroom_stem up true south true east false north false down false west false 4173 mushroom_stem up false south true east false north false down false west true 4174 mushroom_stem up false south true east false north false down false west false 4175 mushroom_stem up true south false east false north false down false west true 4176 mushroom_stem up true south false east false north false down false west false 4177 mushroom_stem up false south false east false north false down false west true 4178 mushroom_stem up false south false east false north false down false west false 4179 iron_bars waterlogged true south true east true north true west true 4180 iron_bars waterlogged true south true east true north true west false 4181 iron_bars waterlogged false south true east true north true west true 4182 iron_bars waterlogged false south true east true north true west false 4183 iron_bars waterlogged true south false east true north true west true 4184 iron_bars waterlogged true south false east true north true west false 4185 iron_bars waterlogged false south false east true north true west true 4186 iron_bars waterlogged false south false east true north true west false 4187 iron_bars waterlogged true south true east true north false west true 4188 iron_bars waterlogged true south true east true north false west false 4189 iron_bars waterlogged false south true east true north false west true 4190 iron_bars waterlogged false south true east true north false west false 4191 iron_bars waterlogged true south false east true north false west true 4192 iron_bars waterlogged true south false east true north false west false 4193 iron_bars waterlogged false south false east true north false west true 4194 iron_bars waterlogged false south false east true north false west false 4195 iron_bars waterlogged true south true east false north true west true 4196 iron_bars waterlogged true south true east false north true west false 4197 iron_bars waterlogged false south true east false north true west true 4198 iron_bars waterlogged false south true east false north true west false 4199 iron_bars waterlogged true south false east false north true west true 4200 iron_bars waterlogged true south false east false north true west false 4201 iron_bars waterlogged false south false east false north true west true 4202 iron_bars waterlogged false south false east false north true west false 4203 iron_bars waterlogged true south true east false north false west true 4204 iron_bars waterlogged true south true east false north false west false 4205 iron_bars waterlogged false south true east false north false west true 4206 iron_bars waterlogged false south true east false north false west false 4207 iron_bars waterlogged true south false east false north false west true 4208 iron_bars waterlogged true south false east false north false west false 4209 iron_bars waterlogged false south false east false north false west true 4210 iron_bars waterlogged false south false east false north false west false 4211 glass_pane waterlogged true south true east true north true west true 4212 glass_pane waterlogged true south true east true north true west false 4213 glass_pane waterlogged false south true east true north true west true 4214 glass_pane waterlogged false south true east true north true west false 4215 glass_pane waterlogged true south false east true north true west true 4216 glass_pane waterlogged true south false east true north true west false 4217 glass_pane waterlogged false south false east true north true west true 4218 glass_pane waterlogged false south false east true north true west false 4219 glass_pane waterlogged true south true east true north false west true 4220 glass_pane waterlogged true south true east true north false west false 4221 glass_pane waterlogged false south true east true north false west true 4222 glass_pane waterlogged false south true east true north false west false 4223 glass_pane waterlogged true south false east true north false west true 4224 glass_pane waterlogged true south false east true north false west false 4225 glass_pane waterlogged false south false east true north false west true 4226 glass_pane waterlogged false south false east true north false west false 4227 glass_pane waterlogged true south true east false north true west true 4228 glass_pane waterlogged true south true east false north true west false 4229 glass_pane waterlogged false south true east false north true west true 4230 glass_pane waterlogged false south true east false north true west false 4231 glass_pane waterlogged true south false east false north true west true 4232 glass_pane waterlogged true south false east false north true west false 4233 glass_pane waterlogged false south false east false north true west true 4234 glass_pane waterlogged false south false east false north true west false 4235 glass_pane waterlogged true south true east false north false west true 4236 glass_pane waterlogged true south true east false north false west false 4237 glass_pane waterlogged false south true east false north false west true 4238 glass_pane waterlogged false south true east false north false west false 4239 glass_pane waterlogged true south false east false north false west true 4240 glass_pane waterlogged true south false east false north false west false 4241 glass_pane waterlogged false south false east false north false west true 4242 glass_pane waterlogged false south false east false north false west false 4243 melon 4244 attached_pumpkin_stem facing north 4245 attached_pumpkin_stem facing south 4246 attached_pumpkin_stem facing west 4247 attached_pumpkin_stem facing east 4248 attached_melon_stem facing north 4249 attached_melon_stem facing south 4250 attached_melon_stem facing west 4251 attached_melon_stem facing east 4252 pumpkin_stem age 0 4253 pumpkin_stem age 1 4254 pumpkin_stem age 2 4255 pumpkin_stem age 3 4256 pumpkin_stem age 4 4257 pumpkin_stem age 5 4258 pumpkin_stem age 6 4259 pumpkin_stem age 7 4260 melon_stem age 0 4261 melon_stem age 1 4262 melon_stem age 2 4263 melon_stem age 3 4264 melon_stem age 4 4265 melon_stem age 5 4266 melon_stem age 6 4267 melon_stem age 7 4268 vine south true east true north true up true west true 4269 vine south true east true north true up true west false 4270 vine south true east true north true up false west true 4271 vine south true east true north true up false west false 4272 vine south false east true north true up true west true 4273 vine south false east true north true up true west false 4274 vine south false east true north true up false west true 4275 vine south false east true north true up false west false 4276 vine south true east true north false up true west true 4277 vine south true east true north false up true west false 4278 vine south true east true north false up false west true 4279 vine south true east true north false up false west false 4280 vine south false east true north false up true west true 4281 vine south false east true north false up true west false 4282 vine south false east true north false up false west true 4283 vine south false east true north false up false west false 4284 vine south true east false north true up true west true 4285 vine south true east false north true up true west false 4286 vine south true east false north true up false west true 4287 vine south true east false north true up false west false 4288 vine south false east false north true up true west true 4289 vine south false east false north true up true west false 4290 vine south false east false north true up false west true 4291 vine south false east false north true up false west false 4292 vine south true east false north false up true west true 4293 vine south true east false north false up true west false 4294 vine south true east false north false up false west true 4295 vine south true east false north false up false west false 4296 vine south false east false north false up true west true 4297 vine south false east false north false up true west false 4298 vine south false east false north false up false west true 4299 vine south false east false north false up false west false 4300 oak_fence_gate facing north powered true open true in_wall true 4301 oak_fence_gate facing north powered false open true in_wall true 4302 oak_fence_gate facing north powered true open false in_wall true 4303 oak_fence_gate facing north powered false open false in_wall true 4304 oak_fence_gate facing north powered true open true in_wall false 4305 oak_fence_gate facing north powered false open true in_wall false 4306 oak_fence_gate facing north powered true open false in_wall false 4307 oak_fence_gate facing north powered false open false in_wall false 4308 oak_fence_gate facing south powered true open true in_wall true 4309 oak_fence_gate facing south powered false open true in_wall true 4310 oak_fence_gate facing south powered true open false in_wall true 4311 oak_fence_gate facing south powered false open false in_wall true 4312 oak_fence_gate facing south powered true open true in_wall false 4313 oak_fence_gate facing south powered false open true in_wall false 4314 oak_fence_gate facing south powered true open false in_wall false 4315 oak_fence_gate facing south powered false open false in_wall false 4316 oak_fence_gate facing west powered true open true in_wall true 4317 oak_fence_gate facing west powered false open true in_wall true 4318 oak_fence_gate facing west powered true open false in_wall true 4319 oak_fence_gate facing west powered false open false in_wall true 4320 oak_fence_gate facing west powered true open true in_wall false 4321 oak_fence_gate facing west powered false open true in_wall false 4322 oak_fence_gate facing west powered true open false in_wall false 4323 oak_fence_gate facing west powered false open false in_wall false 4324 oak_fence_gate facing east powered true open true in_wall true 4325 oak_fence_gate facing east powered false open true in_wall true 4326 oak_fence_gate facing east powered true open false in_wall true 4327 oak_fence_gate facing east powered false open false in_wall true 4328 oak_fence_gate facing east powered true open true in_wall false 4329 oak_fence_gate facing east powered false open true in_wall false 4330 oak_fence_gate facing east powered true open false in_wall false 4331 oak_fence_gate facing east powered false open false in_wall false 4332 brick_stairs facing north waterlogged true shape straight half top 4333 brick_stairs facing north waterlogged false shape straight half top 4334 brick_stairs facing north waterlogged true shape inner_left half top 4335 brick_stairs facing north waterlogged false shape inner_left half top 4336 brick_stairs facing north waterlogged true shape inner_right half top 4337 brick_stairs facing north waterlogged false shape inner_right half top 4338 brick_stairs facing north waterlogged true shape outer_left half top 4339 brick_stairs facing north waterlogged false shape outer_left half top 4340 brick_stairs facing north waterlogged true shape outer_right half top 4341 brick_stairs facing north waterlogged false shape outer_right half top 4342 brick_stairs facing north waterlogged true shape straight half bottom 4343 brick_stairs facing north waterlogged false shape straight half bottom 4344 brick_stairs facing north waterlogged true shape inner_left half bottom 4345 brick_stairs facing north waterlogged false shape inner_left half bottom 4346 brick_stairs facing north waterlogged true shape inner_right half bottom 4347 brick_stairs facing north waterlogged false shape inner_right half bottom 4348 brick_stairs facing north waterlogged true shape outer_left half bottom 4349 brick_stairs facing north waterlogged false shape outer_left half bottom 4350 brick_stairs facing north waterlogged true shape outer_right half bottom 4351 brick_stairs facing north waterlogged false shape outer_right half bottom 4352 brick_stairs facing south waterlogged true shape straight half top 4353 brick_stairs facing south waterlogged false shape straight half top 4354 brick_stairs facing south waterlogged true shape inner_left half top 4355 brick_stairs facing south waterlogged false shape inner_left half top 4356 brick_stairs facing south waterlogged true shape inner_right half top 4357 brick_stairs facing south waterlogged false shape inner_right half top 4358 brick_stairs facing south waterlogged true shape outer_left half top 4359 brick_stairs facing south waterlogged false shape outer_left half top 4360 brick_stairs facing south waterlogged true shape outer_right half top 4361 brick_stairs facing south waterlogged false shape outer_right half top 4362 brick_stairs facing south waterlogged true shape straight half bottom 4363 brick_stairs facing south waterlogged false shape straight half bottom 4364 brick_stairs facing south waterlogged true shape inner_left half bottom 4365 brick_stairs facing south waterlogged false shape inner_left half bottom 4366 brick_stairs facing south waterlogged true shape inner_right half bottom 4367 brick_stairs facing south waterlogged false shape inner_right half bottom 4368 brick_stairs facing south waterlogged true shape outer_left half bottom 4369 brick_stairs facing south waterlogged false shape outer_left half bottom 4370 brick_stairs facing south waterlogged true shape outer_right half bottom 4371 brick_stairs facing south waterlogged false shape outer_right half bottom 4372 brick_stairs facing west waterlogged true shape straight half top 4373 brick_stairs facing west waterlogged false shape straight half top 4374 brick_stairs facing west waterlogged true shape inner_left half top 4375 brick_stairs facing west waterlogged false shape inner_left half top 4376 brick_stairs facing west waterlogged true shape inner_right half top 4377 brick_stairs facing west waterlogged false shape inner_right half top 4378 brick_stairs facing west waterlogged true shape outer_left half top 4379 brick_stairs facing west waterlogged false shape outer_left half top 4380 brick_stairs facing west waterlogged true shape outer_right half top 4381 brick_stairs facing west waterlogged false shape outer_right half top 4382 brick_stairs facing west waterlogged true shape straight half bottom 4383 brick_stairs facing west waterlogged false shape straight half bottom 4384 brick_stairs facing west waterlogged true shape inner_left half bottom 4385 brick_stairs facing west waterlogged false shape inner_left half bottom 4386 brick_stairs facing west waterlogged true shape inner_right half bottom 4387 brick_stairs facing west waterlogged false shape inner_right half bottom 4388 brick_stairs facing west waterlogged true shape outer_left half bottom 4389 brick_stairs facing west waterlogged false shape outer_left half bottom 4390 brick_stairs facing west waterlogged true shape outer_right half bottom 4391 brick_stairs facing west waterlogged false shape outer_right half bottom 4392 brick_stairs facing east waterlogged true shape straight half top 4393 brick_stairs facing east waterlogged false shape straight half top 4394 brick_stairs facing east waterlogged true shape inner_left half top 4395 brick_stairs facing east waterlogged false shape inner_left half top 4396 brick_stairs facing east waterlogged true shape inner_right half top 4397 brick_stairs facing east waterlogged false shape inner_right half top 4398 brick_stairs facing east waterlogged true shape outer_left half top 4399 brick_stairs facing east waterlogged false shape outer_left half top 4400 brick_stairs facing east waterlogged true shape outer_right half top 4401 brick_stairs facing east waterlogged false shape outer_right half top 4402 brick_stairs facing east waterlogged true shape straight half bottom 4403 brick_stairs facing east waterlogged false shape straight half bottom 4404 brick_stairs facing east waterlogged true shape inner_left half bottom 4405 brick_stairs facing east waterlogged false shape inner_left half bottom 4406 brick_stairs facing east waterlogged true shape inner_right half bottom 4407 brick_stairs facing east waterlogged false shape inner_right half bottom 4408 brick_stairs facing east waterlogged true shape outer_left half bottom 4409 brick_stairs facing east waterlogged false shape outer_left half bottom 4410 brick_stairs facing east waterlogged true shape outer_right half bottom 4411 brick_stairs facing east waterlogged false shape outer_right half bottom 4412 stone_brick_stairs facing north waterlogged true shape straight half top 4413 stone_brick_stairs facing north waterlogged false shape straight half top 4414 stone_brick_stairs facing north waterlogged true shape inner_left half top 4415 stone_brick_stairs facing north waterlogged false shape inner_left half top 4416 stone_brick_stairs facing north waterlogged true shape inner_right half top 4417 stone_brick_stairs facing north waterlogged false shape inner_right half top 4418 stone_brick_stairs facing north waterlogged true shape outer_left half top 4419 stone_brick_stairs facing north waterlogged false shape outer_left half top 4420 stone_brick_stairs facing north waterlogged true shape outer_right half top 4421 stone_brick_stairs facing north waterlogged false shape outer_right half top 4422 stone_brick_stairs facing north waterlogged true shape straight half bottom 4423 stone_brick_stairs facing north waterlogged false shape straight half bottom 4424 stone_brick_stairs facing north waterlogged true shape inner_left half bottom 4425 stone_brick_stairs facing north waterlogged false shape inner_left half bottom 4426 stone_brick_stairs facing north waterlogged true shape inner_right half bottom 4427 stone_brick_stairs facing north waterlogged false shape inner_right half bottom 4428 stone_brick_stairs facing north waterlogged true shape outer_left half bottom 4429 stone_brick_stairs facing north waterlogged false shape outer_left half bottom 4430 stone_brick_stairs facing north waterlogged true shape outer_right half bottom 4431 stone_brick_stairs facing north waterlogged false shape outer_right half bottom 4432 stone_brick_stairs facing south waterlogged true shape straight half top 4433 stone_brick_stairs facing south waterlogged false shape straight half top 4434 stone_brick_stairs facing south waterlogged true shape inner_left half top 4435 stone_brick_stairs facing south waterlogged false shape inner_left half top 4436 stone_brick_stairs facing south waterlogged true shape inner_right half top 4437 stone_brick_stairs facing south waterlogged false shape inner_right half top 4438 stone_brick_stairs facing south waterlogged true shape outer_left half top 4439 stone_brick_stairs facing south waterlogged false shape outer_left half top 4440 stone_brick_stairs facing south waterlogged true shape outer_right half top 4441 stone_brick_stairs facing south waterlogged false shape outer_right half top 4442 stone_brick_stairs facing south waterlogged true shape straight half bottom 4443 stone_brick_stairs facing south waterlogged false shape straight half bottom 4444 stone_brick_stairs facing south waterlogged true shape inner_left half bottom 4445 stone_brick_stairs facing south waterlogged false shape inner_left half bottom 4446 stone_brick_stairs facing south waterlogged true shape inner_right half bottom 4447 stone_brick_stairs facing south waterlogged false shape inner_right half bottom 4448 stone_brick_stairs facing south waterlogged true shape outer_left half bottom 4449 stone_brick_stairs facing south waterlogged false shape outer_left half bottom 4450 stone_brick_stairs facing south waterlogged true shape outer_right half bottom 4451 stone_brick_stairs facing south waterlogged false shape outer_right half bottom 4452 stone_brick_stairs facing west waterlogged true shape straight half top 4453 stone_brick_stairs facing west waterlogged false shape straight half top 4454 stone_brick_stairs facing west waterlogged true shape inner_left half top 4455 stone_brick_stairs facing west waterlogged false shape inner_left half top 4456 stone_brick_stairs facing west waterlogged true shape inner_right half top 4457 stone_brick_stairs facing west waterlogged false shape inner_right half top 4458 stone_brick_stairs facing west waterlogged true shape outer_left half top 4459 stone_brick_stairs facing west waterlogged false shape outer_left half top 4460 stone_brick_stairs facing west waterlogged true shape outer_right half top 4461 stone_brick_stairs facing west waterlogged false shape outer_right half top 4462 stone_brick_stairs facing west waterlogged true shape straight half bottom 4463 stone_brick_stairs facing west waterlogged false shape straight half bottom 4464 stone_brick_stairs facing west waterlogged true shape inner_left half bottom 4465 stone_brick_stairs facing west waterlogged false shape inner_left half bottom 4466 stone_brick_stairs facing west waterlogged true shape inner_right half bottom 4467 stone_brick_stairs facing west waterlogged false shape inner_right half bottom 4468 stone_brick_stairs facing west waterlogged true shape outer_left half bottom 4469 stone_brick_stairs facing west waterlogged false shape outer_left half bottom 4470 stone_brick_stairs facing west waterlogged true shape outer_right half bottom 4471 stone_brick_stairs facing west waterlogged false shape outer_right half bottom 4472 stone_brick_stairs facing east waterlogged true shape straight half top 4473 stone_brick_stairs facing east waterlogged false shape straight half top 4474 stone_brick_stairs facing east waterlogged true shape inner_left half top 4475 stone_brick_stairs facing east waterlogged false shape inner_left half top 4476 stone_brick_stairs facing east waterlogged true shape inner_right half top 4477 stone_brick_stairs facing east waterlogged false shape inner_right half top 4478 stone_brick_stairs facing east waterlogged true shape outer_left half top 4479 stone_brick_stairs facing east waterlogged false shape outer_left half top 4480 stone_brick_stairs facing east waterlogged true shape outer_right half top 4481 stone_brick_stairs facing east waterlogged false shape outer_right half top 4482 stone_brick_stairs facing east waterlogged true shape straight half bottom 4483 stone_brick_stairs facing east waterlogged false shape straight half bottom 4484 stone_brick_stairs facing east waterlogged true shape inner_left half bottom 4485 stone_brick_stairs facing east waterlogged false shape inner_left half bottom 4486 stone_brick_stairs facing east waterlogged true shape inner_right half bottom 4487 stone_brick_stairs facing east waterlogged false shape inner_right half bottom 4488 stone_brick_stairs facing east waterlogged true shape outer_left half bottom 4489 stone_brick_stairs facing east waterlogged false shape outer_left half bottom 4490 stone_brick_stairs facing east waterlogged true shape outer_right half bottom 4491 stone_brick_stairs facing east waterlogged false shape outer_right half bottom 4492 mycelium snowy true 4493 mycelium snowy false 4494 lily_pad 4495 nether_bricks 4496 nether_brick_fence waterlogged true south true east true north true west true 4497 nether_brick_fence waterlogged true south true east true north true west false 4498 nether_brick_fence waterlogged false south true east true north true west true 4499 nether_brick_fence waterlogged false south true east true north true west false 4500 nether_brick_fence waterlogged true south false east true north true west true 4501 nether_brick_fence waterlogged true south false east true north true west false 4502 nether_brick_fence waterlogged false south false east true north true west true 4503 nether_brick_fence waterlogged false south false east true north true west false 4504 nether_brick_fence waterlogged true south true east true north false west true 4505 nether_brick_fence waterlogged true south true east true north false west false 4506 nether_brick_fence waterlogged false south true east true north false west true 4507 nether_brick_fence waterlogged false south true east true north false west false 4508 nether_brick_fence waterlogged true south false east true north false west true 4509 nether_brick_fence waterlogged true south false east true north false west false 4510 nether_brick_fence waterlogged false south false east true north false west true 4511 nether_brick_fence waterlogged false south false east true north false west false 4512 nether_brick_fence waterlogged true south true east false north true west true 4513 nether_brick_fence waterlogged true south true east false north true west false 4514 nether_brick_fence waterlogged false south true east false north true west true 4515 nether_brick_fence waterlogged false south true east false north true west false 4516 nether_brick_fence waterlogged true south false east false north true west true 4517 nether_brick_fence waterlogged true south false east false north true west false 4518 nether_brick_fence waterlogged false south false east false north true west true 4519 nether_brick_fence waterlogged false south false east false north true west false 4520 nether_brick_fence waterlogged true south true east false north false west true 4521 nether_brick_fence waterlogged true south true east false north false west false 4522 nether_brick_fence waterlogged false south true east false north false west true 4523 nether_brick_fence waterlogged false south true east false north false west false 4524 nether_brick_fence waterlogged true south false east false north false west true 4525 nether_brick_fence waterlogged true south false east false north false west false 4526 nether_brick_fence waterlogged false south false east false north false west true 4527 nether_brick_fence waterlogged false south false east false north false west false 4528 nether_brick_stairs facing north waterlogged true shape straight half top 4529 nether_brick_stairs facing north waterlogged false shape straight half top 4530 nether_brick_stairs facing north waterlogged true shape inner_left half top 4531 nether_brick_stairs facing north waterlogged false shape inner_left half top 4532 nether_brick_stairs facing north waterlogged true shape inner_right half top 4533 nether_brick_stairs facing north waterlogged false shape inner_right half top 4534 nether_brick_stairs facing north waterlogged true shape outer_left half top 4535 nether_brick_stairs facing north waterlogged false shape outer_left half top 4536 nether_brick_stairs facing north waterlogged true shape outer_right half top 4537 nether_brick_stairs facing north waterlogged false shape outer_right half top 4538 nether_brick_stairs facing north waterlogged true shape straight half bottom 4539 nether_brick_stairs facing north waterlogged false shape straight half bottom 4540 nether_brick_stairs facing north waterlogged true shape inner_left half bottom 4541 nether_brick_stairs facing north waterlogged false shape inner_left half bottom 4542 nether_brick_stairs facing north waterlogged true shape inner_right half bottom 4543 nether_brick_stairs facing north waterlogged false shape inner_right half bottom 4544 nether_brick_stairs facing north waterlogged true shape outer_left half bottom 4545 nether_brick_stairs facing north waterlogged false shape outer_left half bottom 4546 nether_brick_stairs facing north waterlogged true shape outer_right half bottom 4547 nether_brick_stairs facing north waterlogged false shape outer_right half bottom 4548 nether_brick_stairs facing south waterlogged true shape straight half top 4549 nether_brick_stairs facing south waterlogged false shape straight half top 4550 nether_brick_stairs facing south waterlogged true shape inner_left half top 4551 nether_brick_stairs facing south waterlogged false shape inner_left half top 4552 nether_brick_stairs facing south waterlogged true shape inner_right half top 4553 nether_brick_stairs facing south waterlogged false shape inner_right half top 4554 nether_brick_stairs facing south waterlogged true shape outer_left half top 4555 nether_brick_stairs facing south waterlogged false shape outer_left half top 4556 nether_brick_stairs facing south waterlogged true shape outer_right half top 4557 nether_brick_stairs facing south waterlogged false shape outer_right half top 4558 nether_brick_stairs facing south waterlogged true shape straight half bottom 4559 nether_brick_stairs facing south waterlogged false shape straight half bottom 4560 nether_brick_stairs facing south waterlogged true shape inner_left half bottom 4561 nether_brick_stairs facing south waterlogged false shape inner_left half bottom 4562 nether_brick_stairs facing south waterlogged true shape inner_right half bottom 4563 nether_brick_stairs facing south waterlogged false shape inner_right half bottom 4564 nether_brick_stairs facing south waterlogged true shape outer_left half bottom 4565 nether_brick_stairs facing south waterlogged false shape outer_left half bottom 4566 nether_brick_stairs facing south waterlogged true shape outer_right half bottom 4567 nether_brick_stairs facing south waterlogged false shape outer_right half bottom 4568 nether_brick_stairs facing west waterlogged true shape straight half top 4569 nether_brick_stairs facing west waterlogged false shape straight half top 4570 nether_brick_stairs facing west waterlogged true shape inner_left half top 4571 nether_brick_stairs facing west waterlogged false shape inner_left half top 4572 nether_brick_stairs facing west waterlogged true shape inner_right half top 4573 nether_brick_stairs facing west waterlogged false shape inner_right half top 4574 nether_brick_stairs facing west waterlogged true shape outer_left half top 4575 nether_brick_stairs facing west waterlogged false shape outer_left half top 4576 nether_brick_stairs facing west waterlogged true shape outer_right half top 4577 nether_brick_stairs facing west waterlogged false shape outer_right half top 4578 nether_brick_stairs facing west waterlogged true shape straight half bottom 4579 nether_brick_stairs facing west waterlogged false shape straight half bottom 4580 nether_brick_stairs facing west waterlogged true shape inner_left half bottom 4581 nether_brick_stairs facing west waterlogged false shape inner_left half bottom 4582 nether_brick_stairs facing west waterlogged true shape inner_right half bottom 4583 nether_brick_stairs facing west waterlogged false shape inner_right half bottom 4584 nether_brick_stairs facing west waterlogged true shape outer_left half bottom 4585 nether_brick_stairs facing west waterlogged false shape outer_left half bottom 4586 nether_brick_stairs facing west waterlogged true shape outer_right half bottom 4587 nether_brick_stairs facing west waterlogged false shape outer_right half bottom 4588 nether_brick_stairs facing east waterlogged true shape straight half top 4589 nether_brick_stairs facing east waterlogged false shape straight half top 4590 nether_brick_stairs facing east waterlogged true shape inner_left half top 4591 nether_brick_stairs facing east waterlogged false shape inner_left half top 4592 nether_brick_stairs facing east waterlogged true shape inner_right half top 4593 nether_brick_stairs facing east waterlogged false shape inner_right half top 4594 nether_brick_stairs facing east waterlogged true shape outer_left half top 4595 nether_brick_stairs facing east waterlogged false shape outer_left half top 4596 nether_brick_stairs facing east waterlogged true shape outer_right half top 4597 nether_brick_stairs facing east waterlogged false shape outer_right half top 4598 nether_brick_stairs facing east waterlogged true shape straight half bottom 4599 nether_brick_stairs facing east waterlogged false shape straight half bottom 4600 nether_brick_stairs facing east waterlogged true shape inner_left half bottom 4601 nether_brick_stairs facing east waterlogged false shape inner_left half bottom 4602 nether_brick_stairs facing east waterlogged true shape inner_right half bottom 4603 nether_brick_stairs facing east waterlogged false shape inner_right half bottom 4604 nether_brick_stairs facing east waterlogged true shape outer_left half bottom 4605 nether_brick_stairs facing east waterlogged false shape outer_left half bottom 4606 nether_brick_stairs facing east waterlogged true shape outer_right half bottom 4607 nether_brick_stairs facing east waterlogged false shape outer_right half bottom 4608 nether_wart age 0 4609 nether_wart age 1 4610 nether_wart age 2 4611 nether_wart age 3 4612 enchanting_table 4613 brewing_stand has_bottle_0 true has_bottle_1 true has_bottle_2 true 4614 brewing_stand has_bottle_0 true has_bottle_1 true has_bottle_2 false 4615 brewing_stand has_bottle_0 true has_bottle_1 false has_bottle_2 true 4616 brewing_stand has_bottle_0 true has_bottle_1 false has_bottle_2 false 4617 brewing_stand has_bottle_0 false has_bottle_1 true has_bottle_2 true 4618 brewing_stand has_bottle_0 false has_bottle_1 true has_bottle_2 false 4619 brewing_stand has_bottle_0 false has_bottle_1 false has_bottle_2 true 4620 brewing_stand has_bottle_0 false has_bottle_1 false has_bottle_2 false 4621 cauldron level 0 4622 cauldron level 1 4623 cauldron level 2 4624 cauldron level 3 4625 end_portal 4626 end_portal_frame facing north eye true 4627 end_portal_frame facing south eye true 4628 end_portal_frame facing west eye true 4629 end_portal_frame facing east eye true 4630 end_portal_frame facing north eye false 4631 end_portal_frame facing south eye false 4632 end_portal_frame facing west eye false 4633 end_portal_frame facing east eye false 4634 end_stone 4635 dragon_egg 4636 redstone_lamp lit true 4637 redstone_lamp lit false 4638 cocoa facing north age 0 4639 cocoa facing south age 0 4640 cocoa facing west age 0 4641 cocoa facing east age 0 4642 cocoa facing north age 1 4643 cocoa facing south age 1 4644 cocoa facing west age 1 4645 cocoa facing east age 1 4646 cocoa facing north age 2 4647 cocoa facing south age 2 4648 cocoa facing west age 2 4649 cocoa facing east age 2 4650 sandstone_stairs facing north waterlogged true shape straight half top 4651 sandstone_stairs facing north waterlogged false shape straight half top 4652 sandstone_stairs facing north waterlogged true shape inner_left half top 4653 sandstone_stairs facing north waterlogged false shape inner_left half top 4654 sandstone_stairs facing north waterlogged true shape inner_right half top 4655 sandstone_stairs facing north waterlogged false shape inner_right half top 4656 sandstone_stairs facing north waterlogged true shape outer_left half top 4657 sandstone_stairs facing north waterlogged false shape outer_left half top 4658 sandstone_stairs facing north waterlogged true shape outer_right half top 4659 sandstone_stairs facing north waterlogged false shape outer_right half top 4660 sandstone_stairs facing north waterlogged true shape straight half bottom 4661 sandstone_stairs facing north waterlogged false shape straight half bottom 4662 sandstone_stairs facing north waterlogged true shape inner_left half bottom 4663 sandstone_stairs facing north waterlogged false shape inner_left half bottom 4664 sandstone_stairs facing north waterlogged true shape inner_right half bottom 4665 sandstone_stairs facing north waterlogged false shape inner_right half bottom 4666 sandstone_stairs facing north waterlogged true shape outer_left half bottom 4667 sandstone_stairs facing north waterlogged false shape outer_left half bottom 4668 sandstone_stairs facing north waterlogged true shape outer_right half bottom 4669 sandstone_stairs facing north waterlogged false shape outer_right half bottom 4670 sandstone_stairs facing south waterlogged true shape straight half top 4671 sandstone_stairs facing south waterlogged false shape straight half top 4672 sandstone_stairs facing south waterlogged true shape inner_left half top 4673 sandstone_stairs facing south waterlogged false shape inner_left half top 4674 sandstone_stairs facing south waterlogged true shape inner_right half top 4675 sandstone_stairs facing south waterlogged false shape inner_right half top 4676 sandstone_stairs facing south waterlogged true shape outer_left half top 4677 sandstone_stairs facing south waterlogged false shape outer_left half top 4678 sandstone_stairs facing south waterlogged true shape outer_right half top 4679 sandstone_stairs facing south waterlogged false shape outer_right half top 4680 sandstone_stairs facing south waterlogged true shape straight half bottom 4681 sandstone_stairs facing south waterlogged false shape straight half bottom 4682 sandstone_stairs facing south waterlogged true shape inner_left half bottom 4683 sandstone_stairs facing south waterlogged false shape inner_left half bottom 4684 sandstone_stairs facing south waterlogged true shape inner_right half bottom 4685 sandstone_stairs facing south waterlogged false shape inner_right half bottom 4686 sandstone_stairs facing south waterlogged true shape outer_left half bottom 4687 sandstone_stairs facing south waterlogged false shape outer_left half bottom 4688 sandstone_stairs facing south waterlogged true shape outer_right half bottom 4689 sandstone_stairs facing south waterlogged false shape outer_right half bottom 4690 sandstone_stairs facing west waterlogged true shape straight half top 4691 sandstone_stairs facing west waterlogged false shape straight half top 4692 sandstone_stairs facing west waterlogged true shape inner_left half top 4693 sandstone_stairs facing west waterlogged false shape inner_left half top 4694 sandstone_stairs facing west waterlogged true shape inner_right half top 4695 sandstone_stairs facing west waterlogged false shape inner_right half top 4696 sandstone_stairs facing west waterlogged true shape outer_left half top 4697 sandstone_stairs facing west waterlogged false shape outer_left half top 4698 sandstone_stairs facing west waterlogged true shape outer_right half top 4699 sandstone_stairs facing west waterlogged false shape outer_right half top 4700 sandstone_stairs facing west waterlogged true shape straight half bottom 4701 sandstone_stairs facing west waterlogged false shape straight half bottom 4702 sandstone_stairs facing west waterlogged true shape inner_left half bottom 4703 sandstone_stairs facing west waterlogged false shape inner_left half bottom 4704 sandstone_stairs facing west waterlogged true shape inner_right half bottom 4705 sandstone_stairs facing west waterlogged false shape inner_right half bottom 4706 sandstone_stairs facing west waterlogged true shape outer_left half bottom 4707 sandstone_stairs facing west waterlogged false shape outer_left half bottom 4708 sandstone_stairs facing west waterlogged true shape outer_right half bottom 4709 sandstone_stairs facing west waterlogged false shape outer_right half bottom 4710 sandstone_stairs facing east waterlogged true shape straight half top 4711 sandstone_stairs facing east waterlogged false shape straight half top 4712 sandstone_stairs facing east waterlogged true shape inner_left half top 4713 sandstone_stairs facing east waterlogged false shape inner_left half top 4714 sandstone_stairs facing east waterlogged true shape inner_right half top 4715 sandstone_stairs facing east waterlogged false shape inner_right half top 4716 sandstone_stairs facing east waterlogged true shape outer_left half top 4717 sandstone_stairs facing east waterlogged false shape outer_left half top 4718 sandstone_stairs facing east waterlogged true shape outer_right half top 4719 sandstone_stairs facing east waterlogged false shape outer_right half top 4720 sandstone_stairs facing east waterlogged true shape straight half bottom 4721 sandstone_stairs facing east waterlogged false shape straight half bottom 4722 sandstone_stairs facing east waterlogged true shape inner_left half bottom 4723 sandstone_stairs facing east waterlogged false shape inner_left half bottom 4724 sandstone_stairs facing east waterlogged true shape inner_right half bottom 4725 sandstone_stairs facing east waterlogged false shape inner_right half bottom 4726 sandstone_stairs facing east waterlogged true shape outer_left half bottom 4727 sandstone_stairs facing east waterlogged false shape outer_left half bottom 4728 sandstone_stairs facing east waterlogged true shape outer_right half bottom 4729 sandstone_stairs facing east waterlogged false shape outer_right half bottom 4730 emerald_ore 4731 ender_chest facing north waterlogged true 4732 ender_chest facing north waterlogged false 4733 ender_chest facing south waterlogged true 4734 ender_chest facing south waterlogged false 4735 ender_chest facing west waterlogged true 4736 ender_chest facing west waterlogged false 4737 ender_chest facing east waterlogged true 4738 ender_chest facing east waterlogged false 4739 tripwire_hook attached true facing north powered true 4740 tripwire_hook attached true facing north powered false 4741 tripwire_hook attached true facing south powered true 4742 tripwire_hook attached true facing south powered false 4743 tripwire_hook attached true facing west powered true 4744 tripwire_hook attached true facing west powered false 4745 tripwire_hook attached true facing east powered true 4746 tripwire_hook attached true facing east powered false 4747 tripwire_hook attached false facing north powered true 4748 tripwire_hook attached false facing north powered false 4749 tripwire_hook attached false facing south powered true 4750 tripwire_hook attached false facing south powered false 4751 tripwire_hook attached false facing west powered true 4752 tripwire_hook attached false facing west powered false 4753 tripwire_hook attached false facing east powered true 4754 tripwire_hook attached false facing east powered false 4755 tripwire attached true disarmed true powered true east true north true south true west true 4756 tripwire attached true disarmed true powered true east true north true south true west false 4757 tripwire attached true disarmed true powered true east true north true south false west true 4758 tripwire attached true disarmed true powered true east true north true south false west false 4759 tripwire attached true disarmed true powered false east true north true south true west true 4760 tripwire attached true disarmed true powered false east true north true south true west false 4761 tripwire attached true disarmed true powered false east true north true south false west true 4762 tripwire attached true disarmed true powered false east true north true south false west false 4763 tripwire attached true disarmed true powered true east true north false south true west true 4764 tripwire attached true disarmed true powered true east true north false south true west false 4765 tripwire attached true disarmed true powered true east true north false south false west true 4766 tripwire attached true disarmed true powered true east true north false south false west false 4767 tripwire attached true disarmed true powered false east true north false south true west true 4768 tripwire attached true disarmed true powered false east true north false south true west false 4769 tripwire attached true disarmed true powered false east true north false south false west true 4770 tripwire attached true disarmed true powered false east true north false south false west false 4771 tripwire attached true disarmed true powered true east false north true south true west true 4772 tripwire attached true disarmed true powered true east false north true south true west false 4773 tripwire attached true disarmed true powered true east false north true south false west true 4774 tripwire attached true disarmed true powered true east false north true south false west false 4775 tripwire attached true disarmed true powered false east false north true south true west true 4776 tripwire attached true disarmed true powered false east false north true south true west false 4777 tripwire attached true disarmed true powered false east false north true south false west true 4778 tripwire attached true disarmed true powered false east false north true south false west false 4779 tripwire attached true disarmed true powered true east false north false south true west true 4780 tripwire attached true disarmed true powered true east false north false south true west false 4781 tripwire attached true disarmed true powered true east false north false south false west true 4782 tripwire attached true disarmed true powered true east false north false south false west false 4783 tripwire attached true disarmed true powered false east false north false south true west true 4784 tripwire attached true disarmed true powered false east false north false south true west false 4785 tripwire attached true disarmed true powered false east false north false south false west true 4786 tripwire attached true disarmed true powered false east false north false south false west false 4787 tripwire attached true disarmed false powered true east true north true south true west true 4788 tripwire attached true disarmed false powered true east true north true south true west false 4789 tripwire attached true disarmed false powered true east true north true south false west true 4790 tripwire attached true disarmed false powered true east true north true south false west false 4791 tripwire attached true disarmed false powered false east true north true south true west true 4792 tripwire attached true disarmed false powered false east true north true south true west false 4793 tripwire attached true disarmed false powered false east true north true south false west true 4794 tripwire attached true disarmed false powered false east true north true south false west false 4795 tripwire attached true disarmed false powered true east true north false south true west true 4796 tripwire attached true disarmed false powered true east true north false south true west false 4797 tripwire attached true disarmed false powered true east true north false south false west true 4798 tripwire attached true disarmed false powered true east true north false south false west false 4799 tripwire attached true disarmed false powered false east true north false south true west true 4800 tripwire attached true disarmed false powered false east true north false south true west false 4801 tripwire attached true disarmed false powered false east true north false south false west true 4802 tripwire attached true disarmed false powered false east true north false south false west false 4803 tripwire attached true disarmed false powered true east false north true south true west true 4804 tripwire attached true disarmed false powered true east false north true south true west false 4805 tripwire attached true disarmed false powered true east false north true south false west true 4806 tripwire attached true disarmed false powered true east false north true south false west false 4807 tripwire attached true disarmed false powered false east false north true south true west true 4808 tripwire attached true disarmed false powered false east false north true south true west false 4809 tripwire attached true disarmed false powered false east false north true south false west true 4810 tripwire attached true disarmed false powered false east false north true south false west false 4811 tripwire attached true disarmed false powered true east false north false south true west true 4812 tripwire attached true disarmed false powered true east false north false south true west false 4813 tripwire attached true disarmed false powered true east false north false south false west true 4814 tripwire attached true disarmed false powered true east false north false south false west false 4815 tripwire attached true disarmed false powered false east false north false south true west true 4816 tripwire attached true disarmed false powered false east false north false south true west false 4817 tripwire attached true disarmed false powered false east false north false south false west true 4818 tripwire attached true disarmed false powered false east false north false south false west false 4819 tripwire attached false disarmed true powered true east true north true south true west true 4820 tripwire attached false disarmed true powered true east true north true south true west false 4821 tripwire attached false disarmed true powered true east true north true south false west true 4822 tripwire attached false disarmed true powered true east true north true south false west false 4823 tripwire attached false disarmed true powered false east true north true south true west true 4824 tripwire attached false disarmed true powered false east true north true south true west false 4825 tripwire attached false disarmed true powered false east true north true south false west true 4826 tripwire attached false disarmed true powered false east true north true south false west false 4827 tripwire attached false disarmed true powered true east true north false south true west true 4828 tripwire attached false disarmed true powered true east true north false south true west false 4829 tripwire attached false disarmed true powered true east true north false south false west true 4830 tripwire attached false disarmed true powered true east true north false south false west false 4831 tripwire attached false disarmed true powered false east true north false south true west true 4832 tripwire attached false disarmed true powered false east true north false south true west false 4833 tripwire attached false disarmed true powered false east true north false south false west true 4834 tripwire attached false disarmed true powered false east true north false south false west false 4835 tripwire attached false disarmed true powered true east false north true south true west true 4836 tripwire attached false disarmed true powered true east false north true south true west false 4837 tripwire attached false disarmed true powered true east false north true south false west true 4838 tripwire attached false disarmed true powered true east false north true south false west false 4839 tripwire attached false disarmed true powered false east false north true south true west true 4840 tripwire attached false disarmed true powered false east false north true south true west false 4841 tripwire attached false disarmed true powered false east false north true south false west true 4842 tripwire attached false disarmed true powered false east false north true south false west false 4843 tripwire attached false disarmed true powered true east false north false south true west true 4844 tripwire attached false disarmed true powered true east false north false south true west false 4845 tripwire attached false disarmed true powered true east false north false south false west true 4846 tripwire attached false disarmed true powered true east false north false south false west false 4847 tripwire attached false disarmed true powered false east false north false south true west true 4848 tripwire attached false disarmed true powered false east false north false south true west false 4849 tripwire attached false disarmed true powered false east false north false south false west true 4850 tripwire attached false disarmed true powered false east false north false south false west false 4851 tripwire attached false disarmed false powered true east true north true south true west true 4852 tripwire attached false disarmed false powered true east true north true south true west false 4853 tripwire attached false disarmed false powered true east true north true south false west true 4854 tripwire attached false disarmed false powered true east true north true south false west false 4855 tripwire attached false disarmed false powered false east true north true south true west true 4856 tripwire attached false disarmed false powered false east true north true south true west false 4857 tripwire attached false disarmed false powered false east true north true south false west true 4858 tripwire attached false disarmed false powered false east true north true south false west false 4859 tripwire attached false disarmed false powered true east true north false south true west true 4860 tripwire attached false disarmed false powered true east true north false south true west false 4861 tripwire attached false disarmed false powered true east true north false south false west true 4862 tripwire attached false disarmed false powered true east true north false south false west false 4863 tripwire attached false disarmed false powered false east true north false south true west true 4864 tripwire attached false disarmed false powered false east true north false south true west false 4865 tripwire attached false disarmed false powered false east true north false south false west true 4866 tripwire attached false disarmed false powered false east true north false south false west false 4867 tripwire attached false disarmed false powered true east false north true south true west true 4868 tripwire attached false disarmed false powered true east false north true south true west false 4869 tripwire attached false disarmed false powered true east false north true south false west true 4870 tripwire attached false disarmed false powered true east false north true south false west false 4871 tripwire attached false disarmed false powered false east false north true south true west true 4872 tripwire attached false disarmed false powered false east false north true south true west false 4873 tripwire attached false disarmed false powered false east false north true south false west true 4874 tripwire attached false disarmed false powered false east false north true south false west false 4875 tripwire attached false disarmed false powered true east false north false south true west true 4876 tripwire attached false disarmed false powered true east false north false south true west false 4877 tripwire attached false disarmed false powered true east false north false south false west true 4878 tripwire attached false disarmed false powered true east false north false south false west false 4879 tripwire attached false disarmed false powered false east false north false south true west true 4880 tripwire attached false disarmed false powered false east false north false south true west false 4881 tripwire attached false disarmed false powered false east false north false south false west true 4882 tripwire attached false disarmed false powered false east false north false south false west false 4883 emerald_block 4884 spruce_stairs facing north waterlogged true shape straight half top 4885 spruce_stairs facing north waterlogged false shape straight half top 4886 spruce_stairs facing north waterlogged true shape inner_left half top 4887 spruce_stairs facing north waterlogged false shape inner_left half top 4888 spruce_stairs facing north waterlogged true shape inner_right half top 4889 spruce_stairs facing north waterlogged false shape inner_right half top 4890 spruce_stairs facing north waterlogged true shape outer_left half top 4891 spruce_stairs facing north waterlogged false shape outer_left half top 4892 spruce_stairs facing north waterlogged true shape outer_right half top 4893 spruce_stairs facing north waterlogged false shape outer_right half top 4894 spruce_stairs facing north waterlogged true shape straight half bottom 4895 spruce_stairs facing north waterlogged false shape straight half bottom 4896 spruce_stairs facing north waterlogged true shape inner_left half bottom 4897 spruce_stairs facing north waterlogged false shape inner_left half bottom 4898 spruce_stairs facing north waterlogged true shape inner_right half bottom 4899 spruce_stairs facing north waterlogged false shape inner_right half bottom 4900 spruce_stairs facing north waterlogged true shape outer_left half bottom 4901 spruce_stairs facing north waterlogged false shape outer_left half bottom 4902 spruce_stairs facing north waterlogged true shape outer_right half bottom 4903 spruce_stairs facing north waterlogged false shape outer_right half bottom 4904 spruce_stairs facing south waterlogged true shape straight half top 4905 spruce_stairs facing south waterlogged false shape straight half top 4906 spruce_stairs facing south waterlogged true shape inner_left half top 4907 spruce_stairs facing south waterlogged false shape inner_left half top 4908 spruce_stairs facing south waterlogged true shape inner_right half top 4909 spruce_stairs facing south waterlogged false shape inner_right half top 4910 spruce_stairs facing south waterlogged true shape outer_left half top 4911 spruce_stairs facing south waterlogged false shape outer_left half top 4912 spruce_stairs facing south waterlogged true shape outer_right half top 4913 spruce_stairs facing south waterlogged false shape outer_right half top 4914 spruce_stairs facing south waterlogged true shape straight half bottom 4915 spruce_stairs facing south waterlogged false shape straight half bottom 4916 spruce_stairs facing south waterlogged true shape inner_left half bottom 4917 spruce_stairs facing south waterlogged false shape inner_left half bottom 4918 spruce_stairs facing south waterlogged true shape inner_right half bottom 4919 spruce_stairs facing south waterlogged false shape inner_right half bottom 4920 spruce_stairs facing south waterlogged true shape outer_left half bottom 4921 spruce_stairs facing south waterlogged false shape outer_left half bottom 4922 spruce_stairs facing south waterlogged true shape outer_right half bottom 4923 spruce_stairs facing south waterlogged false shape outer_right half bottom 4924 spruce_stairs facing west waterlogged true shape straight half top 4925 spruce_stairs facing west waterlogged false shape straight half top 4926 spruce_stairs facing west waterlogged true shape inner_left half top 4927 spruce_stairs facing west waterlogged false shape inner_left half top 4928 spruce_stairs facing west waterlogged true shape inner_right half top 4929 spruce_stairs facing west waterlogged false shape inner_right half top 4930 spruce_stairs facing west waterlogged true shape outer_left half top 4931 spruce_stairs facing west waterlogged false shape outer_left half top 4932 spruce_stairs facing west waterlogged true shape outer_right half top 4933 spruce_stairs facing west waterlogged false shape outer_right half top 4934 spruce_stairs facing west waterlogged true shape straight half bottom 4935 spruce_stairs facing west waterlogged false shape straight half bottom 4936 spruce_stairs facing west waterlogged true shape inner_left half bottom 4937 spruce_stairs facing west waterlogged false shape inner_left half bottom 4938 spruce_stairs facing west waterlogged true shape inner_right half bottom 4939 spruce_stairs facing west waterlogged false shape inner_right half bottom 4940 spruce_stairs facing west waterlogged true shape outer_left half bottom 4941 spruce_stairs facing west waterlogged false shape outer_left half bottom 4942 spruce_stairs facing west waterlogged true shape outer_right half bottom 4943 spruce_stairs facing west waterlogged false shape outer_right half bottom 4944 spruce_stairs facing east waterlogged true shape straight half top 4945 spruce_stairs facing east waterlogged false shape straight half top 4946 spruce_stairs facing east waterlogged true shape inner_left half top 4947 spruce_stairs facing east waterlogged false shape inner_left half top 4948 spruce_stairs facing east waterlogged true shape inner_right half top 4949 spruce_stairs facing east waterlogged false shape inner_right half top 4950 spruce_stairs facing east waterlogged true shape outer_left half top 4951 spruce_stairs facing east waterlogged false shape outer_left half top 4952 spruce_stairs facing east waterlogged true shape outer_right half top 4953 spruce_stairs facing east waterlogged false shape outer_right half top 4954 spruce_stairs facing east waterlogged true shape straight half bottom 4955 spruce_stairs facing east waterlogged false shape straight half bottom 4956 spruce_stairs facing east waterlogged true shape inner_left half bottom 4957 spruce_stairs facing east waterlogged false shape inner_left half bottom 4958 spruce_stairs facing east waterlogged true shape inner_right half bottom 4959 spruce_stairs facing east waterlogged false shape inner_right half bottom 4960 spruce_stairs facing east waterlogged true shape outer_left half bottom 4961 spruce_stairs facing east waterlogged false shape outer_left half bottom 4962 spruce_stairs facing east waterlogged true shape outer_right half bottom 4963 spruce_stairs facing east waterlogged false shape outer_right half bottom 4964 birch_stairs facing north waterlogged true shape straight half top 4965 birch_stairs facing north waterlogged false shape straight half top 4966 birch_stairs facing north waterlogged true shape inner_left half top 4967 birch_stairs facing north waterlogged false shape inner_left half top 4968 birch_stairs facing north waterlogged true shape inner_right half top 4969 birch_stairs facing north waterlogged false shape inner_right half top 4970 birch_stairs facing north waterlogged true shape outer_left half top 4971 birch_stairs facing north waterlogged false shape outer_left half top 4972 birch_stairs facing north waterlogged true shape outer_right half top 4973 birch_stairs facing north waterlogged false shape outer_right half top 4974 birch_stairs facing north waterlogged true shape straight half bottom 4975 birch_stairs facing north waterlogged false shape straight half bottom 4976 birch_stairs facing north waterlogged true shape inner_left half bottom 4977 birch_stairs facing north waterlogged false shape inner_left half bottom 4978 birch_stairs facing north waterlogged true shape inner_right half bottom 4979 birch_stairs facing north waterlogged false shape inner_right half bottom 4980 birch_stairs facing north waterlogged true shape outer_left half bottom 4981 birch_stairs facing north waterlogged false shape outer_left half bottom 4982 birch_stairs facing north waterlogged true shape outer_right half bottom 4983 birch_stairs facing north waterlogged false shape outer_right half bottom 4984 birch_stairs facing south waterlogged true shape straight half top 4985 birch_stairs facing south waterlogged false shape straight half top 4986 birch_stairs facing south waterlogged true shape inner_left half top 4987 birch_stairs facing south waterlogged false shape inner_left half top 4988 birch_stairs facing south waterlogged true shape inner_right half top 4989 birch_stairs facing south waterlogged false shape inner_right half top 4990 birch_stairs facing south waterlogged true shape outer_left half top 4991 birch_stairs facing south waterlogged false shape outer_left half top 4992 birch_stairs facing south waterlogged true shape outer_right half top 4993 birch_stairs facing south waterlogged false shape outer_right half top 4994 birch_stairs facing south waterlogged true shape straight half bottom 4995 birch_stairs facing south waterlogged false shape straight half bottom 4996 birch_stairs facing south waterlogged true shape inner_left half bottom 4997 birch_stairs facing south waterlogged false shape inner_left half bottom 4998 birch_stairs facing south waterlogged true shape inner_right half bottom 4999 birch_stairs facing south waterlogged false shape inner_right half bottom 5000 birch_stairs facing south waterlogged true shape outer_left half bottom 5001 birch_stairs facing south waterlogged false shape outer_left half bottom 5002 birch_stairs facing south waterlogged true shape outer_right half bottom 5003 birch_stairs facing south waterlogged false shape outer_right half bottom 5004 birch_stairs facing west waterlogged true shape straight half top 5005 birch_stairs facing west waterlogged false shape straight half top 5006 birch_stairs facing west waterlogged true shape inner_left half top 5007 birch_stairs facing west waterlogged false shape inner_left half top 5008 birch_stairs facing west waterlogged true shape inner_right half top 5009 birch_stairs facing west waterlogged false shape inner_right half top 5010 birch_stairs facing west waterlogged true shape outer_left half top 5011 birch_stairs facing west waterlogged false shape outer_left half top 5012 birch_stairs facing west waterlogged true shape outer_right half top 5013 birch_stairs facing west waterlogged false shape outer_right half top 5014 birch_stairs facing west waterlogged true shape straight half bottom 5015 birch_stairs facing west waterlogged false shape straight half bottom 5016 birch_stairs facing west waterlogged true shape inner_left half bottom 5017 birch_stairs facing west waterlogged false shape inner_left half bottom 5018 birch_stairs facing west waterlogged true shape inner_right half bottom 5019 birch_stairs facing west waterlogged false shape inner_right half bottom 5020 birch_stairs facing west waterlogged true shape outer_left half bottom 5021 birch_stairs facing west waterlogged false shape outer_left half bottom 5022 birch_stairs facing west waterlogged true shape outer_right half bottom 5023 birch_stairs facing west waterlogged false shape outer_right half bottom 5024 birch_stairs facing east waterlogged true shape straight half top 5025 birch_stairs facing east waterlogged false shape straight half top 5026 birch_stairs facing east waterlogged true shape inner_left half top 5027 birch_stairs facing east waterlogged false shape inner_left half top 5028 birch_stairs facing east waterlogged true shape inner_right half top 5029 birch_stairs facing east waterlogged false shape inner_right half top 5030 birch_stairs facing east waterlogged true shape outer_left half top 5031 birch_stairs facing east waterlogged false shape outer_left half top 5032 birch_stairs facing east waterlogged true shape outer_right half top 5033 birch_stairs facing east waterlogged false shape outer_right half top 5034 birch_stairs facing east waterlogged true shape straight half bottom 5035 birch_stairs facing east waterlogged false shape straight half bottom 5036 birch_stairs facing east waterlogged true shape inner_left half bottom 5037 birch_stairs facing east waterlogged false shape inner_left half bottom 5038 birch_stairs facing east waterlogged true shape inner_right half bottom 5039 birch_stairs facing east waterlogged false shape inner_right half bottom 5040 birch_stairs facing east waterlogged true shape outer_left half bottom 5041 birch_stairs facing east waterlogged false shape outer_left half bottom 5042 birch_stairs facing east waterlogged true shape outer_right half bottom 5043 birch_stairs facing east waterlogged false shape outer_right half bottom 5044 jungle_stairs facing north waterlogged true shape straight half top 5045 jungle_stairs facing north waterlogged false shape straight half top 5046 jungle_stairs facing north waterlogged true shape inner_left half top 5047 jungle_stairs facing north waterlogged false shape inner_left half top 5048 jungle_stairs facing north waterlogged true shape inner_right half top 5049 jungle_stairs facing north waterlogged false shape inner_right half top 5050 jungle_stairs facing north waterlogged true shape outer_left half top 5051 jungle_stairs facing north waterlogged false shape outer_left half top 5052 jungle_stairs facing north waterlogged true shape outer_right half top 5053 jungle_stairs facing north waterlogged false shape outer_right half top 5054 jungle_stairs facing north waterlogged true shape straight half bottom 5055 jungle_stairs facing north waterlogged false shape straight half bottom 5056 jungle_stairs facing north waterlogged true shape inner_left half bottom 5057 jungle_stairs facing north waterlogged false shape inner_left half bottom 5058 jungle_stairs facing north waterlogged true shape inner_right half bottom 5059 jungle_stairs facing north waterlogged false shape inner_right half bottom 5060 jungle_stairs facing north waterlogged true shape outer_left half bottom 5061 jungle_stairs facing north waterlogged false shape outer_left half bottom 5062 jungle_stairs facing north waterlogged true shape outer_right half bottom 5063 jungle_stairs facing north waterlogged false shape outer_right half bottom 5064 jungle_stairs facing south waterlogged true shape straight half top 5065 jungle_stairs facing south waterlogged false shape straight half top 5066 jungle_stairs facing south waterlogged true shape inner_left half top 5067 jungle_stairs facing south waterlogged false shape inner_left half top 5068 jungle_stairs facing south waterlogged true shape inner_right half top 5069 jungle_stairs facing south waterlogged false shape inner_right half top 5070 jungle_stairs facing south waterlogged true shape outer_left half top 5071 jungle_stairs facing south waterlogged false shape outer_left half top 5072 jungle_stairs facing south waterlogged true shape outer_right half top 5073 jungle_stairs facing south waterlogged false shape outer_right half top 5074 jungle_stairs facing south waterlogged true shape straight half bottom 5075 jungle_stairs facing south waterlogged false shape straight half bottom 5076 jungle_stairs facing south waterlogged true shape inner_left half bottom 5077 jungle_stairs facing south waterlogged false shape inner_left half bottom 5078 jungle_stairs facing south waterlogged true shape inner_right half bottom 5079 jungle_stairs facing south waterlogged false shape inner_right half bottom 5080 jungle_stairs facing south waterlogged true shape outer_left half bottom 5081 jungle_stairs facing south waterlogged false shape outer_left half bottom 5082 jungle_stairs facing south waterlogged true shape outer_right half bottom 5083 jungle_stairs facing south waterlogged false shape outer_right half bottom 5084 jungle_stairs facing west waterlogged true shape straight half top 5085 jungle_stairs facing west waterlogged false shape straight half top 5086 jungle_stairs facing west waterlogged true shape inner_left half top 5087 jungle_stairs facing west waterlogged false shape inner_left half top 5088 jungle_stairs facing west waterlogged true shape inner_right half top 5089 jungle_stairs facing west waterlogged false shape inner_right half top 5090 jungle_stairs facing west waterlogged true shape outer_left half top 5091 jungle_stairs facing west waterlogged false shape outer_left half top 5092 jungle_stairs facing west waterlogged true shape outer_right half top 5093 jungle_stairs facing west waterlogged false shape outer_right half top 5094 jungle_stairs facing west waterlogged true shape straight half bottom 5095 jungle_stairs facing west waterlogged false shape straight half bottom 5096 jungle_stairs facing west waterlogged true shape inner_left half bottom 5097 jungle_stairs facing west waterlogged false shape inner_left half bottom 5098 jungle_stairs facing west waterlogged true shape inner_right half bottom 5099 jungle_stairs facing west waterlogged false shape inner_right half bottom 5100 jungle_stairs facing west waterlogged true shape outer_left half bottom 5101 jungle_stairs facing west waterlogged false shape outer_left half bottom 5102 jungle_stairs facing west waterlogged true shape outer_right half bottom 5103 jungle_stairs facing west waterlogged false shape outer_right half bottom 5104 jungle_stairs facing east waterlogged true shape straight half top 5105 jungle_stairs facing east waterlogged false shape straight half top 5106 jungle_stairs facing east waterlogged true shape inner_left half top 5107 jungle_stairs facing east waterlogged false shape inner_left half top 5108 jungle_stairs facing east waterlogged true shape inner_right half top 5109 jungle_stairs facing east waterlogged false shape inner_right half top 5110 jungle_stairs facing east waterlogged true shape outer_left half top 5111 jungle_stairs facing east waterlogged false shape outer_left half top 5112 jungle_stairs facing east waterlogged true shape outer_right half top 5113 jungle_stairs facing east waterlogged false shape outer_right half top 5114 jungle_stairs facing east waterlogged true shape straight half bottom 5115 jungle_stairs facing east waterlogged false shape straight half bottom 5116 jungle_stairs facing east waterlogged true shape inner_left half bottom 5117 jungle_stairs facing east waterlogged false shape inner_left half bottom 5118 jungle_stairs facing east waterlogged true shape inner_right half bottom 5119 jungle_stairs facing east waterlogged false shape inner_right half bottom 5120 jungle_stairs facing east waterlogged true shape outer_left half bottom 5121 jungle_stairs facing east waterlogged false shape outer_left half bottom 5122 jungle_stairs facing east waterlogged true shape outer_right half bottom 5123 jungle_stairs facing east waterlogged false shape outer_right half bottom 5124 command_block conditional true facing north 5125 command_block conditional true facing east 5126 command_block conditional true facing south 5127 command_block conditional true facing west 5128 command_block conditional true facing up 5129 command_block conditional true facing down 5130 command_block conditional false facing north 5131 command_block conditional false facing east 5132 command_block conditional false facing south 5133 command_block conditional false facing west 5134 command_block conditional false facing up 5135 command_block conditional false facing down 5136 beacon 5137 cobblestone_wall waterlogged true south true east true north true up true west true 5138 cobblestone_wall waterlogged true south true east true north true up true west false 5139 cobblestone_wall waterlogged false south true east true north true up true west true 5140 cobblestone_wall waterlogged false south true east true north true up true west false 5141 cobblestone_wall waterlogged true south true east true north true up false west true 5142 cobblestone_wall waterlogged true south true east true north true up false west false 5143 cobblestone_wall waterlogged false south true east true north true up false west true 5144 cobblestone_wall waterlogged false south true east true north true up false west false 5145 cobblestone_wall waterlogged true south false east true north true up true west true 5146 cobblestone_wall waterlogged true south false east true north true up true west false 5147 cobblestone_wall waterlogged false south false east true north true up true west true 5148 cobblestone_wall waterlogged false south false east true north true up true west false 5149 cobblestone_wall waterlogged true south false east true north true up false west true 5150 cobblestone_wall waterlogged true south false east true north true up false west false 5151 cobblestone_wall waterlogged false south false east true north true up false west true 5152 cobblestone_wall waterlogged false south false east true north true up false west false 5153 cobblestone_wall waterlogged true south true east true north false up true west true 5154 cobblestone_wall waterlogged true south true east true north false up true west false 5155 cobblestone_wall waterlogged false south true east true north false up true west true 5156 cobblestone_wall waterlogged false south true east true north false up true west false 5157 cobblestone_wall waterlogged true south true east true north false up false west true 5158 cobblestone_wall waterlogged true south true east true north false up false west false 5159 cobblestone_wall waterlogged false south true east true north false up false west true 5160 cobblestone_wall waterlogged false south true east true north false up false west false 5161 cobblestone_wall waterlogged true south false east true north false up true west true 5162 cobblestone_wall waterlogged true south false east true north false up true west false 5163 cobblestone_wall waterlogged false south false east true north false up true west true 5164 cobblestone_wall waterlogged false south false east true north false up true west false 5165 cobblestone_wall waterlogged true south false east true north false up false west true 5166 cobblestone_wall waterlogged true south false east true north false up false west false 5167 cobblestone_wall waterlogged false south false east true north false up false west true 5168 cobblestone_wall waterlogged false south false east true north false up false west false 5169 cobblestone_wall waterlogged true south true east false north true up true west true 5170 cobblestone_wall waterlogged true south true east false north true up true west false 5171 cobblestone_wall waterlogged false south true east false north true up true west true 5172 cobblestone_wall waterlogged false south true east false north true up true west false 5173 cobblestone_wall waterlogged true south true east false north true up false west true 5174 cobblestone_wall waterlogged true south true east false north true up false west false 5175 cobblestone_wall waterlogged false south true east false north true up false west true 5176 cobblestone_wall waterlogged false south true east false north true up false west false 5177 cobblestone_wall waterlogged true south false east false north true up true west true 5178 cobblestone_wall waterlogged true south false east false north true up true west false 5179 cobblestone_wall waterlogged false south false east false north true up true west true 5180 cobblestone_wall waterlogged false south false east false north true up true west false 5181 cobblestone_wall waterlogged true south false east false north true up false west true 5182 cobblestone_wall waterlogged true south false east false north true up false west false 5183 cobblestone_wall waterlogged false south false east false north true up false west true 5184 cobblestone_wall waterlogged false south false east false north true up false west false 5185 cobblestone_wall waterlogged true south true east false north false up true west true 5186 cobblestone_wall waterlogged true south true east false north false up true west false 5187 cobblestone_wall waterlogged false south true east false north false up true west true 5188 cobblestone_wall waterlogged false south true east false north false up true west false 5189 cobblestone_wall waterlogged true south true east false north false up false west true 5190 cobblestone_wall waterlogged true south true east false north false up false west false 5191 cobblestone_wall waterlogged false south true east false north false up false west true 5192 cobblestone_wall waterlogged false south true east false north false up false west false 5193 cobblestone_wall waterlogged true south false east false north false up true west true 5194 cobblestone_wall waterlogged true south false east false north false up true west false 5195 cobblestone_wall waterlogged false south false east false north false up true west true 5196 cobblestone_wall waterlogged false south false east false north false up true west false 5197 cobblestone_wall waterlogged true south false east false north false up false west true 5198 cobblestone_wall waterlogged true south false east false north false up false west false 5199 cobblestone_wall waterlogged false south false east false north false up false west true 5200 cobblestone_wall waterlogged false south false east false north false up false west false 5201 mossy_cobblestone_wall waterlogged true south true east true north true up true west true 5202 mossy_cobblestone_wall waterlogged true south true east true north true up true west false 5203 mossy_cobblestone_wall waterlogged false south true east true north true up true west true 5204 mossy_cobblestone_wall waterlogged false south true east true north true up true west false 5205 mossy_cobblestone_wall waterlogged true south true east true north true up false west true 5206 mossy_cobblestone_wall waterlogged true south true east true north true up false west false 5207 mossy_cobblestone_wall waterlogged false south true east true north true up false west true 5208 mossy_cobblestone_wall waterlogged false south true east true north true up false west false 5209 mossy_cobblestone_wall waterlogged true south false east true north true up true west true 5210 mossy_cobblestone_wall waterlogged true south false east true north true up true west false 5211 mossy_cobblestone_wall waterlogged false south false east true north true up true west true 5212 mossy_cobblestone_wall waterlogged false south false east true north true up true west false 5213 mossy_cobblestone_wall waterlogged true south false east true north true up false west true 5214 mossy_cobblestone_wall waterlogged true south false east true north true up false west false 5215 mossy_cobblestone_wall waterlogged false south false east true north true up false west true 5216 mossy_cobblestone_wall waterlogged false south false east true north true up false west false 5217 mossy_cobblestone_wall waterlogged true south true east true north false up true west true 5218 mossy_cobblestone_wall waterlogged true south true east true north false up true west false 5219 mossy_cobblestone_wall waterlogged false south true east true north false up true west true 5220 mossy_cobblestone_wall waterlogged false south true east true north false up true west false 5221 mossy_cobblestone_wall waterlogged true south true east true north false up false west true 5222 mossy_cobblestone_wall waterlogged true south true east true north false up false west false 5223 mossy_cobblestone_wall waterlogged false south true east true north false up false west true 5224 mossy_cobblestone_wall waterlogged false south true east true north false up false west false 5225 mossy_cobblestone_wall waterlogged true south false east true north false up true west true 5226 mossy_cobblestone_wall waterlogged true south false east true north false up true west false 5227 mossy_cobblestone_wall waterlogged false south false east true north false up true west true 5228 mossy_cobblestone_wall waterlogged false south false east true north false up true west false 5229 mossy_cobblestone_wall waterlogged true south false east true north false up false west true 5230 mossy_cobblestone_wall waterlogged true south false east true north false up false west false 5231 mossy_cobblestone_wall waterlogged false south false east true north false up false west true 5232 mossy_cobblestone_wall waterlogged false south false east true north false up false west false 5233 mossy_cobblestone_wall waterlogged true south true east false north true up true west true 5234 mossy_cobblestone_wall waterlogged true south true east false north true up true west false 5235 mossy_cobblestone_wall waterlogged false south true east false north true up true west true 5236 mossy_cobblestone_wall waterlogged false south true east false north true up true west false 5237 mossy_cobblestone_wall waterlogged true south true east false north true up false west true 5238 mossy_cobblestone_wall waterlogged true south true east false north true up false west false 5239 mossy_cobblestone_wall waterlogged false south true east false north true up false west true 5240 mossy_cobblestone_wall waterlogged false south true east false north true up false west false 5241 mossy_cobblestone_wall waterlogged true south false east false north true up true west true 5242 mossy_cobblestone_wall waterlogged true south false east false north true up true west false 5243 mossy_cobblestone_wall waterlogged false south false east false north true up true west true 5244 mossy_cobblestone_wall waterlogged false south false east false north true up true west false 5245 mossy_cobblestone_wall waterlogged true south false east false north true up false west true 5246 mossy_cobblestone_wall waterlogged true south false east false north true up false west false 5247 mossy_cobblestone_wall waterlogged false south false east false north true up false west true 5248 mossy_cobblestone_wall waterlogged false south false east false north true up false west false 5249 mossy_cobblestone_wall waterlogged true south true east false north false up true west true 5250 mossy_cobblestone_wall waterlogged true south true east false north false up true west false 5251 mossy_cobblestone_wall waterlogged false south true east false north false up true west true 5252 mossy_cobblestone_wall waterlogged false south true east false north false up true west false 5253 mossy_cobblestone_wall waterlogged true south true east false north false up false west true 5254 mossy_cobblestone_wall waterlogged true south true east false north false up false west false 5255 mossy_cobblestone_wall waterlogged false south true east false north false up false west true 5256 mossy_cobblestone_wall waterlogged false south true east false north false up false west false 5257 mossy_cobblestone_wall waterlogged true south false east false north false up true west true 5258 mossy_cobblestone_wall waterlogged true south false east false north false up true west false 5259 mossy_cobblestone_wall waterlogged false south false east false north false up true west true 5260 mossy_cobblestone_wall waterlogged false south false east false north false up true west false 5261 mossy_cobblestone_wall waterlogged true south false east false north false up false west true 5262 mossy_cobblestone_wall waterlogged true south false east false north false up false west false 5263 mossy_cobblestone_wall waterlogged false south false east false north false up false west true 5264 mossy_cobblestone_wall waterlogged false south false east false north false up false west false 5265 flower_pot 5266 potted_oak_sapling 5267 potted_spruce_sapling 5268 potted_birch_sapling 5269 potted_jungle_sapling 5270 potted_acacia_sapling 5271 potted_dark_oak_sapling 5272 potted_fern 5273 potted_dandelion 5274 potted_poppy 5275 potted_blue_orchid 5276 potted_allium 5277 potted_azure_bluet 5278 potted_red_tulip 5279 potted_orange_tulip 5280 potted_white_tulip 5281 potted_pink_tulip 5282 potted_oxeye_daisy 5283 potted_red_mushroom 5284 potted_brown_mushroom 5285 potted_dead_bush 5286 potted_cactus 5287 carrots age 0 5288 carrots age 1 5289 carrots age 2 5290 carrots age 3 5291 carrots age 4 5292 carrots age 5 5293 carrots age 6 5294 carrots age 7 5295 potatoes age 0 5296 potatoes age 1 5297 potatoes age 2 5298 potatoes age 3 5299 potatoes age 4 5300 potatoes age 5 5301 potatoes age 6 5302 potatoes age 7 5303 oak_button facing north face floor powered true 5304 oak_button facing north face floor powered false 5305 oak_button facing south face floor powered true 5306 oak_button facing south face floor powered false 5307 oak_button facing west face floor powered true 5308 oak_button facing west face floor powered false 5309 oak_button facing east face floor powered true 5310 oak_button facing east face floor powered false 5311 oak_button facing north face wall powered true 5312 oak_button facing north face wall powered false 5313 oak_button facing south face wall powered true 5314 oak_button facing south face wall powered false 5315 oak_button facing west face wall powered true 5316 oak_button facing west face wall powered false 5317 oak_button facing east face wall powered true 5318 oak_button facing east face wall powered false 5319 oak_button facing north face ceiling powered true 5320 oak_button facing north face ceiling powered false 5321 oak_button facing south face ceiling powered true 5322 oak_button facing south face ceiling powered false 5323 oak_button facing west face ceiling powered true 5324 oak_button facing west face ceiling powered false 5325 oak_button facing east face ceiling powered true 5326 oak_button facing east face ceiling powered false 5327 spruce_button facing north face floor powered true 5328 spruce_button facing north face floor powered false 5329 spruce_button facing south face floor powered true 5330 spruce_button facing south face floor powered false 5331 spruce_button facing west face floor powered true 5332 spruce_button facing west face floor powered false 5333 spruce_button facing east face floor powered true 5334 spruce_button facing east face floor powered false 5335 spruce_button facing north face wall powered true 5336 spruce_button facing north face wall powered false 5337 spruce_button facing south face wall powered true 5338 spruce_button facing south face wall powered false 5339 spruce_button facing west face wall powered true 5340 spruce_button facing west face wall powered false 5341 spruce_button facing east face wall powered true 5342 spruce_button facing east face wall powered false 5343 spruce_button facing north face ceiling powered true 5344 spruce_button facing north face ceiling powered false 5345 spruce_button facing south face ceiling powered true 5346 spruce_button facing south face ceiling powered false 5347 spruce_button facing west face ceiling powered true 5348 spruce_button facing west face ceiling powered false 5349 spruce_button facing east face ceiling powered true 5350 spruce_button facing east face ceiling powered false 5351 birch_button facing north face floor powered true 5352 birch_button facing north face floor powered false 5353 birch_button facing south face floor powered true 5354 birch_button facing south face floor powered false 5355 birch_button facing west face floor powered true 5356 birch_button facing west face floor powered false 5357 birch_button facing east face floor powered true 5358 birch_button facing east face floor powered false 5359 birch_button facing north face wall powered true 5360 birch_button facing north face wall powered false 5361 birch_button facing south face wall powered true 5362 birch_button facing south face wall powered false 5363 birch_button facing west face wall powered true 5364 birch_button facing west face wall powered false 5365 birch_button facing east face wall powered true 5366 birch_button facing east face wall powered false 5367 birch_button facing north face ceiling powered true 5368 birch_button facing north face ceiling powered false 5369 birch_button facing south face ceiling powered true 5370 birch_button facing south face ceiling powered false 5371 birch_button facing west face ceiling powered true 5372 birch_button facing west face ceiling powered false 5373 birch_button facing east face ceiling powered true 5374 birch_button facing east face ceiling powered false 5375 jungle_button facing north face floor powered true 5376 jungle_button facing north face floor powered false 5377 jungle_button facing south face floor powered true 5378 jungle_button facing south face floor powered false 5379 jungle_button facing west face floor powered true 5380 jungle_button facing west face floor powered false 5381 jungle_button facing east face floor powered true 5382 jungle_button facing east face floor powered false 5383 jungle_button facing north face wall powered true 5384 jungle_button facing north face wall powered false 5385 jungle_button facing south face wall powered true 5386 jungle_button facing south face wall powered false 5387 jungle_button facing west face wall powered true 5388 jungle_button facing west face wall powered false 5389 jungle_button facing east face wall powered true 5390 jungle_button facing east face wall powered false 5391 jungle_button facing north face ceiling powered true 5392 jungle_button facing north face ceiling powered false 5393 jungle_button facing south face ceiling powered true 5394 jungle_button facing south face ceiling powered false 5395 jungle_button facing west face ceiling powered true 5396 jungle_button facing west face ceiling powered false 5397 jungle_button facing east face ceiling powered true 5398 jungle_button facing east face ceiling powered false 5399 acacia_button facing north face floor powered true 5400 acacia_button facing north face floor powered false 5401 acacia_button facing south face floor powered true 5402 acacia_button facing south face floor powered false 5403 acacia_button facing west face floor powered true 5404 acacia_button facing west face floor powered false 5405 acacia_button facing east face floor powered true 5406 acacia_button facing east face floor powered false 5407 acacia_button facing north face wall powered true 5408 acacia_button facing north face wall powered false 5409 acacia_button facing south face wall powered true 5410 acacia_button facing south face wall powered false 5411 acacia_button facing west face wall powered true 5412 acacia_button facing west face wall powered false 5413 acacia_button facing east face wall powered true 5414 acacia_button facing east face wall powered false 5415 acacia_button facing north face ceiling powered true 5416 acacia_button facing north face ceiling powered false 5417 acacia_button facing south face ceiling powered true 5418 acacia_button facing south face ceiling powered false 5419 acacia_button facing west face ceiling powered true 5420 acacia_button facing west face ceiling powered false 5421 acacia_button facing east face ceiling powered true 5422 acacia_button facing east face ceiling powered false 5423 dark_oak_button facing north face floor powered true 5424 dark_oak_button facing north face floor powered false 5425 dark_oak_button facing south face floor powered true 5426 dark_oak_button facing south face floor powered false 5427 dark_oak_button facing west face floor powered true 5428 dark_oak_button facing west face floor powered false 5429 dark_oak_button facing east face floor powered true 5430 dark_oak_button facing east face floor powered false 5431 dark_oak_button facing north face wall powered true 5432 dark_oak_button facing north face wall powered false 5433 dark_oak_button facing south face wall powered true 5434 dark_oak_button facing south face wall powered false 5435 dark_oak_button facing west face wall powered true 5436 dark_oak_button facing west face wall powered false 5437 dark_oak_button facing east face wall powered true 5438 dark_oak_button facing east face wall powered false 5439 dark_oak_button facing north face ceiling powered true 5440 dark_oak_button facing north face ceiling powered false 5441 dark_oak_button facing south face ceiling powered true 5442 dark_oak_button facing south face ceiling powered false 5443 dark_oak_button facing west face ceiling powered true 5444 dark_oak_button facing west face ceiling powered false 5445 dark_oak_button facing east face ceiling powered true 5446 dark_oak_button facing east face ceiling powered false 5447 skeleton_wall_skull facing north 5448 skeleton_wall_skull facing south 5449 skeleton_wall_skull facing west 5450 skeleton_wall_skull facing east 5451 skeleton_skull rotation 0 5452 skeleton_skull rotation 1 5453 skeleton_skull rotation 2 5454 skeleton_skull rotation 3 5455 skeleton_skull rotation 4 5456 skeleton_skull rotation 5 5457 skeleton_skull rotation 6 5458 skeleton_skull rotation 7 5459 skeleton_skull rotation 8 5460 skeleton_skull rotation 9 5461 skeleton_skull rotation 10 5462 skeleton_skull rotation 11 5463 skeleton_skull rotation 12 5464 skeleton_skull rotation 13 5465 skeleton_skull rotation 14 5466 skeleton_skull rotation 15 5467 wither_skeleton_wall_skull facing north 5468 wither_skeleton_wall_skull facing south 5469 wither_skeleton_wall_skull facing west 5470 wither_skeleton_wall_skull facing east 5471 wither_skeleton_skull rotation 0 5472 wither_skeleton_skull rotation 1 5473 wither_skeleton_skull rotation 2 5474 wither_skeleton_skull rotation 3 5475 wither_skeleton_skull rotation 4 5476 wither_skeleton_skull rotation 5 5477 wither_skeleton_skull rotation 6 5478 wither_skeleton_skull rotation 7 5479 wither_skeleton_skull rotation 8 5480 wither_skeleton_skull rotation 9 5481 wither_skeleton_skull rotation 10 5482 wither_skeleton_skull rotation 11 5483 wither_skeleton_skull rotation 12 5484 wither_skeleton_skull rotation 13 5485 wither_skeleton_skull rotation 14 5486 wither_skeleton_skull rotation 15 5487 zombie_wall_head facing north 5488 zombie_wall_head facing south 5489 zombie_wall_head facing west 5490 zombie_wall_head facing east 5491 zombie_head rotation 0 5492 zombie_head rotation 1 5493 zombie_head rotation 2 5494 zombie_head rotation 3 5495 zombie_head rotation 4 5496 zombie_head rotation 5 5497 zombie_head rotation 6 5498 zombie_head rotation 7 5499 zombie_head rotation 8 5500 zombie_head rotation 9 5501 zombie_head rotation 10 5502 zombie_head rotation 11 5503 zombie_head rotation 12 5504 zombie_head rotation 13 5505 zombie_head rotation 14 5506 zombie_head rotation 15 5507 player_wall_head facing north 5508 player_wall_head facing south 5509 player_wall_head facing west 5510 player_wall_head facing east 5511 player_head rotation 0 5512 player_head rotation 1 5513 player_head rotation 2 5514 player_head rotation 3 5515 player_head rotation 4 5516 player_head rotation 5 5517 player_head rotation 6 5518 player_head rotation 7 5519 player_head rotation 8 5520 player_head rotation 9 5521 player_head rotation 10 5522 player_head rotation 11 5523 player_head rotation 12 5524 player_head rotation 13 5525 player_head rotation 14 5526 player_head rotation 15 5527 creeper_wall_head facing north 5528 creeper_wall_head facing south 5529 creeper_wall_head facing west 5530 creeper_wall_head facing east 5531 creeper_head rotation 0 5532 creeper_head rotation 1 5533 creeper_head rotation 2 5534 creeper_head rotation 3 5535 creeper_head rotation 4 5536 creeper_head rotation 5 5537 creeper_head rotation 6 5538 creeper_head rotation 7 5539 creeper_head rotation 8 5540 creeper_head rotation 9 5541 creeper_head rotation 10 5542 creeper_head rotation 11 5543 creeper_head rotation 12 5544 creeper_head rotation 13 5545 creeper_head rotation 14 5546 creeper_head rotation 15 5547 dragon_wall_head facing north 5548 dragon_wall_head facing south 5549 dragon_wall_head facing west 5550 dragon_wall_head facing east 5551 dragon_head rotation 0 5552 dragon_head rotation 1 5553 dragon_head rotation 2 5554 dragon_head rotation 3 5555 dragon_head rotation 4 5556 dragon_head rotation 5 5557 dragon_head rotation 6 5558 dragon_head rotation 7 5559 dragon_head rotation 8 5560 dragon_head rotation 9 5561 dragon_head rotation 10 5562 dragon_head rotation 11 5563 dragon_head rotation 12 5564 dragon_head rotation 13 5565 dragon_head rotation 14 5566 dragon_head rotation 15 5567 anvil facing north 5568 anvil facing south 5569 anvil facing west 5570 anvil facing east 5571 chipped_anvil facing north 5572 chipped_anvil facing south 5573 chipped_anvil facing west 5574 chipped_anvil facing east 5575 damaged_anvil facing north 5576 damaged_anvil facing south 5577 damaged_anvil facing west 5578 damaged_anvil facing east 5579 trapped_chest facing north waterlogged true type single 5580 trapped_chest facing north waterlogged false type single 5581 trapped_chest facing north waterlogged true type left 5582 trapped_chest facing north waterlogged false type left 5583 trapped_chest facing north waterlogged true type right 5584 trapped_chest facing north waterlogged false type right 5585 trapped_chest facing south waterlogged true type single 5586 trapped_chest facing south waterlogged false type single 5587 trapped_chest facing south waterlogged true type left 5588 trapped_chest facing south waterlogged false type left 5589 trapped_chest facing south waterlogged true type right 5590 trapped_chest facing south waterlogged false type right 5591 trapped_chest facing west waterlogged true type single 5592 trapped_chest facing west waterlogged false type single 5593 trapped_chest facing west waterlogged true type left 5594 trapped_chest facing west waterlogged false type left 5595 trapped_chest facing west waterlogged true type right 5596 trapped_chest facing west waterlogged false type right 5597 trapped_chest facing east waterlogged true type single 5598 trapped_chest facing east waterlogged false type single 5599 trapped_chest facing east waterlogged true type left 5600 trapped_chest facing east waterlogged false type left 5601 trapped_chest facing east waterlogged true type right 5602 trapped_chest facing east waterlogged false type right 5603 light_weighted_pressure_plate power 0 5604 light_weighted_pressure_plate power 1 5605 light_weighted_pressure_plate power 2 5606 light_weighted_pressure_plate power 3 5607 light_weighted_pressure_plate power 4 5608 light_weighted_pressure_plate power 5 5609 light_weighted_pressure_plate power 6 5610 light_weighted_pressure_plate power 7 5611 light_weighted_pressure_plate power 8 5612 light_weighted_pressure_plate power 9 5613 light_weighted_pressure_plate power 10 5614 light_weighted_pressure_plate power 11 5615 light_weighted_pressure_plate power 12 5616 light_weighted_pressure_plate power 13 5617 light_weighted_pressure_plate power 14 5618 light_weighted_pressure_plate power 15 5619 heavy_weighted_pressure_plate power 0 5620 heavy_weighted_pressure_plate power 1 5621 heavy_weighted_pressure_plate power 2 5622 heavy_weighted_pressure_plate power 3 5623 heavy_weighted_pressure_plate power 4 5624 heavy_weighted_pressure_plate power 5 5625 heavy_weighted_pressure_plate power 6 5626 heavy_weighted_pressure_plate power 7 5627 heavy_weighted_pressure_plate power 8 5628 heavy_weighted_pressure_plate power 9 5629 heavy_weighted_pressure_plate power 10 5630 heavy_weighted_pressure_plate power 11 5631 heavy_weighted_pressure_plate power 12 5632 heavy_weighted_pressure_plate power 13 5633 heavy_weighted_pressure_plate power 14 5634 heavy_weighted_pressure_plate power 15 5635 comparator facing north mode compare powered true 5636 comparator facing north mode compare powered false 5637 comparator facing north mode subtract powered true 5638 comparator facing north mode subtract powered false 5639 comparator facing south mode compare powered true 5640 comparator facing south mode compare powered false 5641 comparator facing south mode subtract powered true 5642 comparator facing south mode subtract powered false 5643 comparator facing west mode compare powered true 5644 comparator facing west mode compare powered false 5645 comparator facing west mode subtract powered true 5646 comparator facing west mode subtract powered false 5647 comparator facing east mode compare powered true 5648 comparator facing east mode compare powered false 5649 comparator facing east mode subtract powered true 5650 comparator facing east mode subtract powered false 5651 daylight_detector inverted true power 0 5652 daylight_detector inverted true power 1 5653 daylight_detector inverted true power 2 5654 daylight_detector inverted true power 3 5655 daylight_detector inverted true power 4 5656 daylight_detector inverted true power 5 5657 daylight_detector inverted true power 6 5658 daylight_detector inverted true power 7 5659 daylight_detector inverted true power 8 5660 daylight_detector inverted true power 9 5661 daylight_detector inverted true power 10 5662 daylight_detector inverted true power 11 5663 daylight_detector inverted true power 12 5664 daylight_detector inverted true power 13 5665 daylight_detector inverted true power 14 5666 daylight_detector inverted true power 15 5667 daylight_detector inverted false power 0 5668 daylight_detector inverted false power 1 5669 daylight_detector inverted false power 2 5670 daylight_detector inverted false power 3 5671 daylight_detector inverted false power 4 5672 daylight_detector inverted false power 5 5673 daylight_detector inverted false power 6 5674 daylight_detector inverted false power 7 5675 daylight_detector inverted false power 8 5676 daylight_detector inverted false power 9 5677 daylight_detector inverted false power 10 5678 daylight_detector inverted false power 11 5679 daylight_detector inverted false power 12 5680 daylight_detector inverted false power 13 5681 daylight_detector inverted false power 14 5682 daylight_detector inverted false power 15 5683 redstone_block 5684 nether_quartz_ore 5685 hopper facing down enabled true 5686 hopper facing north enabled true 5687 hopper facing south enabled true 5688 hopper facing west enabled true 5689 hopper facing east enabled true 5690 hopper facing down enabled false 5691 hopper facing north enabled false 5692 hopper facing south enabled false 5693 hopper facing west enabled false 5694 hopper facing east enabled false 5695 quartz_block 5696 chiseled_quartz_block 5697 quartz_pillar axis x 5698 quartz_pillar axis y 5699 quartz_pillar axis z 5700 quartz_stairs facing north waterlogged true shape straight half top 5701 quartz_stairs facing north waterlogged false shape straight half top 5702 quartz_stairs facing north waterlogged true shape inner_left half top 5703 quartz_stairs facing north waterlogged false shape inner_left half top 5704 quartz_stairs facing north waterlogged true shape inner_right half top 5705 quartz_stairs facing north waterlogged false shape inner_right half top 5706 quartz_stairs facing north waterlogged true shape outer_left half top 5707 quartz_stairs facing north waterlogged false shape outer_left half top 5708 quartz_stairs facing north waterlogged true shape outer_right half top 5709 quartz_stairs facing north waterlogged false shape outer_right half top 5710 quartz_stairs facing north waterlogged true shape straight half bottom 5711 quartz_stairs facing north waterlogged false shape straight half bottom 5712 quartz_stairs facing north waterlogged true shape inner_left half bottom 5713 quartz_stairs facing north waterlogged false shape inner_left half bottom 5714 quartz_stairs facing north waterlogged true shape inner_right half bottom 5715 quartz_stairs facing north waterlogged false shape inner_right half bottom 5716 quartz_stairs facing north waterlogged true shape outer_left half bottom 5717 quartz_stairs facing north waterlogged false shape outer_left half bottom 5718 quartz_stairs facing north waterlogged true shape outer_right half bottom 5719 quartz_stairs facing north waterlogged false shape outer_right half bottom 5720 quartz_stairs facing south waterlogged true shape straight half top 5721 quartz_stairs facing south waterlogged false shape straight half top 5722 quartz_stairs facing south waterlogged true shape inner_left half top 5723 quartz_stairs facing south waterlogged false shape inner_left half top 5724 quartz_stairs facing south waterlogged true shape inner_right half top 5725 quartz_stairs facing south waterlogged false shape inner_right half top 5726 quartz_stairs facing south waterlogged true shape outer_left half top 5727 quartz_stairs facing south waterlogged false shape outer_left half top 5728 quartz_stairs facing south waterlogged true shape outer_right half top 5729 quartz_stairs facing south waterlogged false shape outer_right half top 5730 quartz_stairs facing south waterlogged true shape straight half bottom 5731 quartz_stairs facing south waterlogged false shape straight half bottom 5732 quartz_stairs facing south waterlogged true shape inner_left half bottom 5733 quartz_stairs facing south waterlogged false shape inner_left half bottom 5734 quartz_stairs facing south waterlogged true shape inner_right half bottom 5735 quartz_stairs facing south waterlogged false shape inner_right half bottom 5736 quartz_stairs facing south waterlogged true shape outer_left half bottom 5737 quartz_stairs facing south waterlogged false shape outer_left half bottom 5738 quartz_stairs facing south waterlogged true shape outer_right half bottom 5739 quartz_stairs facing south waterlogged false shape outer_right half bottom 5740 quartz_stairs facing west waterlogged true shape straight half top 5741 quartz_stairs facing west waterlogged false shape straight half top 5742 quartz_stairs facing west waterlogged true shape inner_left half top 5743 quartz_stairs facing west waterlogged false shape inner_left half top 5744 quartz_stairs facing west waterlogged true shape inner_right half top 5745 quartz_stairs facing west waterlogged false shape inner_right half top 5746 quartz_stairs facing west waterlogged true shape outer_left half top 5747 quartz_stairs facing west waterlogged false shape outer_left half top 5748 quartz_stairs facing west waterlogged true shape outer_right half top 5749 quartz_stairs facing west waterlogged false shape outer_right half top 5750 quartz_stairs facing west waterlogged true shape straight half bottom 5751 quartz_stairs facing west waterlogged false shape straight half bottom 5752 quartz_stairs facing west waterlogged true shape inner_left half bottom 5753 quartz_stairs facing west waterlogged false shape inner_left half bottom 5754 quartz_stairs facing west waterlogged true shape inner_right half bottom 5755 quartz_stairs facing west waterlogged false shape inner_right half bottom 5756 quartz_stairs facing west waterlogged true shape outer_left half bottom 5757 quartz_stairs facing west waterlogged false shape outer_left half bottom 5758 quartz_stairs facing west waterlogged true shape outer_right half bottom 5759 quartz_stairs facing west waterlogged false shape outer_right half bottom 5760 quartz_stairs facing east waterlogged true shape straight half top 5761 quartz_stairs facing east waterlogged false shape straight half top 5762 quartz_stairs facing east waterlogged true shape inner_left half top 5763 quartz_stairs facing east waterlogged false shape inner_left half top 5764 quartz_stairs facing east waterlogged true shape inner_right half top 5765 quartz_stairs facing east waterlogged false shape inner_right half top 5766 quartz_stairs facing east waterlogged true shape outer_left half top 5767 quartz_stairs facing east waterlogged false shape outer_left half top 5768 quartz_stairs facing east waterlogged true shape outer_right half top 5769 quartz_stairs facing east waterlogged false shape outer_right half top 5770 quartz_stairs facing east waterlogged true shape straight half bottom 5771 quartz_stairs facing east waterlogged false shape straight half bottom 5772 quartz_stairs facing east waterlogged true shape inner_left half bottom 5773 quartz_stairs facing east waterlogged false shape inner_left half bottom 5774 quartz_stairs facing east waterlogged true shape inner_right half bottom 5775 quartz_stairs facing east waterlogged false shape inner_right half bottom 5776 quartz_stairs facing east waterlogged true shape outer_left half bottom 5777 quartz_stairs facing east waterlogged false shape outer_left half bottom 5778 quartz_stairs facing east waterlogged true shape outer_right half bottom 5779 quartz_stairs facing east waterlogged false shape outer_right half bottom 5780 activator_rail shape north_south powered true 5781 activator_rail shape east_west powered true 5782 activator_rail shape ascending_east powered true 5783 activator_rail shape ascending_west powered true 5784 activator_rail shape ascending_north powered true 5785 activator_rail shape ascending_south powered true 5786 activator_rail shape north_south powered false 5787 activator_rail shape east_west powered false 5788 activator_rail shape ascending_east powered false 5789 activator_rail shape ascending_west powered false 5790 activator_rail shape ascending_north powered false 5791 activator_rail shape ascending_south powered false 5792 dropper facing north triggered true 5793 dropper facing north triggered false 5794 dropper facing east triggered true 5795 dropper facing east triggered false 5796 dropper facing south triggered true 5797 dropper facing south triggered false 5798 dropper facing west triggered true 5799 dropper facing west triggered false 5800 dropper facing up triggered true 5801 dropper facing up triggered false 5802 dropper facing down triggered true 5803 dropper facing down triggered false 5804 white_terracotta 5805 orange_terracotta 5806 magenta_terracotta 5807 light_blue_terracotta 5808 yellow_terracotta 5809 lime_terracotta 5810 pink_terracotta 5811 gray_terracotta 5812 light_gray_terracotta 5813 cyan_terracotta 5814 purple_terracotta 5815 blue_terracotta 5816 brown_terracotta 5817 green_terracotta 5818 red_terracotta 5819 black_terracotta 5820 white_stained_glass_pane waterlogged true south true east true north true west true 5821 white_stained_glass_pane waterlogged true south true east true north true west false 5822 white_stained_glass_pane waterlogged false south true east true north true west true 5823 white_stained_glass_pane waterlogged false south true east true north true west false 5824 white_stained_glass_pane waterlogged true south false east true north true west true 5825 white_stained_glass_pane waterlogged true south false east true north true west false 5826 white_stained_glass_pane waterlogged false south false east true north true west true 5827 white_stained_glass_pane waterlogged false south false east true north true west false 5828 white_stained_glass_pane waterlogged true south true east true north false west true 5829 white_stained_glass_pane waterlogged true south true east true north false west false 5830 white_stained_glass_pane waterlogged false south true east true north false west true 5831 white_stained_glass_pane waterlogged false south true east true north false west false 5832 white_stained_glass_pane waterlogged true south false east true north false west true 5833 white_stained_glass_pane waterlogged true south false east true north false west false 5834 white_stained_glass_pane waterlogged false south false east true north false west true 5835 white_stained_glass_pane waterlogged false south false east true north false west false 5836 white_stained_glass_pane waterlogged true south true east false north true west true 5837 white_stained_glass_pane waterlogged true south true east false north true west false 5838 white_stained_glass_pane waterlogged false south true east false north true west true 5839 white_stained_glass_pane waterlogged false south true east false north true west false 5840 white_stained_glass_pane waterlogged true south false east false north true west true 5841 white_stained_glass_pane waterlogged true south false east false north true west false 5842 white_stained_glass_pane waterlogged false south false east false north true west true 5843 white_stained_glass_pane waterlogged false south false east false north true west false 5844 white_stained_glass_pane waterlogged true south true east false north false west true 5845 white_stained_glass_pane waterlogged true south true east false north false west false 5846 white_stained_glass_pane waterlogged false south true east false north false west true 5847 white_stained_glass_pane waterlogged false south true east false north false west false 5848 white_stained_glass_pane waterlogged true south false east false north false west true 5849 white_stained_glass_pane waterlogged true south false east false north false west false 5850 white_stained_glass_pane waterlogged false south false east false north false west true 5851 white_stained_glass_pane waterlogged false south false east false north false west false 5852 orange_stained_glass_pane waterlogged true south true east true north true west true 5853 orange_stained_glass_pane waterlogged true south true east true north true west false 5854 orange_stained_glass_pane waterlogged false south true east true north true west true 5855 orange_stained_glass_pane waterlogged false south true east true north true west false 5856 orange_stained_glass_pane waterlogged true south false east true north true west true 5857 orange_stained_glass_pane waterlogged true south false east true north true west false 5858 orange_stained_glass_pane waterlogged false south false east true north true west true 5859 orange_stained_glass_pane waterlogged false south false east true north true west false 5860 orange_stained_glass_pane waterlogged true south true east true north false west true 5861 orange_stained_glass_pane waterlogged true south true east true north false west false 5862 orange_stained_glass_pane waterlogged false south true east true north false west true 5863 orange_stained_glass_pane waterlogged false south true east true north false west false 5864 orange_stained_glass_pane waterlogged true south false east true north false west true 5865 orange_stained_glass_pane waterlogged true south false east true north false west false 5866 orange_stained_glass_pane waterlogged false south false east true north false west true 5867 orange_stained_glass_pane waterlogged false south false east true north false west false 5868 orange_stained_glass_pane waterlogged true south true east false north true west true 5869 orange_stained_glass_pane waterlogged true south true east false north true west false 5870 orange_stained_glass_pane waterlogged false south true east false north true west true 5871 orange_stained_glass_pane waterlogged false south true east false north true west false 5872 orange_stained_glass_pane waterlogged true south false east false north true west true 5873 orange_stained_glass_pane waterlogged true south false east false north true west false 5874 orange_stained_glass_pane waterlogged false south false east false north true west true 5875 orange_stained_glass_pane waterlogged false south false east false north true west false 5876 orange_stained_glass_pane waterlogged true south true east false north false west true 5877 orange_stained_glass_pane waterlogged true south true east false north false west false 5878 orange_stained_glass_pane waterlogged false south true east false north false west true 5879 orange_stained_glass_pane waterlogged false south true east false north false west false 5880 orange_stained_glass_pane waterlogged true south false east false north false west true 5881 orange_stained_glass_pane waterlogged true south false east false north false west false 5882 orange_stained_glass_pane waterlogged false south false east false north false west true 5883 orange_stained_glass_pane waterlogged false south false east false north false west false 5884 magenta_stained_glass_pane waterlogged true south true east true north true west true 5885 magenta_stained_glass_pane waterlogged true south true east true north true west false 5886 magenta_stained_glass_pane waterlogged false south true east true north true west true 5887 magenta_stained_glass_pane waterlogged false south true east true north true west false 5888 magenta_stained_glass_pane waterlogged true south false east true north true west true 5889 magenta_stained_glass_pane waterlogged true south false east true north true west false 5890 magenta_stained_glass_pane waterlogged false south false east true north true west true 5891 magenta_stained_glass_pane waterlogged false south false east true north true west false 5892 magenta_stained_glass_pane waterlogged true south true east true north false west true 5893 magenta_stained_glass_pane waterlogged true south true east true north false west false 5894 magenta_stained_glass_pane waterlogged false south true east true north false west true 5895 magenta_stained_glass_pane waterlogged false south true east true north false west false 5896 magenta_stained_glass_pane waterlogged true south false east true north false west true 5897 magenta_stained_glass_pane waterlogged true south false east true north false west false 5898 magenta_stained_glass_pane waterlogged false south false east true north false west true 5899 magenta_stained_glass_pane waterlogged false south false east true north false west false 5900 magenta_stained_glass_pane waterlogged true south true east false north true west true 5901 magenta_stained_glass_pane waterlogged true south true east false north true west false 5902 magenta_stained_glass_pane waterlogged false south true east false north true west true 5903 magenta_stained_glass_pane waterlogged false south true east false north true west false 5904 magenta_stained_glass_pane waterlogged true south false east false north true west true 5905 magenta_stained_glass_pane waterlogged true south false east false north true west false 5906 magenta_stained_glass_pane waterlogged false south false east false north true west true 5907 magenta_stained_glass_pane waterlogged false south false east false north true west false 5908 magenta_stained_glass_pane waterlogged true south true east false north false west true 5909 magenta_stained_glass_pane waterlogged true south true east false north false west false 5910 magenta_stained_glass_pane waterlogged false south true east false north false west true 5911 magenta_stained_glass_pane waterlogged false south true east false north false west false 5912 magenta_stained_glass_pane waterlogged true south false east false north false west true 5913 magenta_stained_glass_pane waterlogged true south false east false north false west false 5914 magenta_stained_glass_pane waterlogged false south false east false north false west true 5915 magenta_stained_glass_pane waterlogged false south false east false north false west false 5916 light_blue_stained_glass_pane waterlogged true south true east true north true west true 5917 light_blue_stained_glass_pane waterlogged true south true east true north true west false 5918 light_blue_stained_glass_pane waterlogged false south true east true north true west true 5919 light_blue_stained_glass_pane waterlogged false south true east true north true west false 5920 light_blue_stained_glass_pane waterlogged true south false east true north true west true 5921 light_blue_stained_glass_pane waterlogged true south false east true north true west false 5922 light_blue_stained_glass_pane waterlogged false south false east true north true west true 5923 light_blue_stained_glass_pane waterlogged false south false east true north true west false 5924 light_blue_stained_glass_pane waterlogged true south true east true north false west true 5925 light_blue_stained_glass_pane waterlogged true south true east true north false west false 5926 light_blue_stained_glass_pane waterlogged false south true east true north false west true 5927 light_blue_stained_glass_pane waterlogged false south true east true north false west false 5928 light_blue_stained_glass_pane waterlogged true south false east true north false west true 5929 light_blue_stained_glass_pane waterlogged true south false east true north false west false 5930 light_blue_stained_glass_pane waterlogged false south false east true north false west true 5931 light_blue_stained_glass_pane waterlogged false south false east true north false west false 5932 light_blue_stained_glass_pane waterlogged true south true east false north true west true 5933 light_blue_stained_glass_pane waterlogged true south true east false north true west false 5934 light_blue_stained_glass_pane waterlogged false south true east false north true west true 5935 light_blue_stained_glass_pane waterlogged false south true east false north true west false 5936 light_blue_stained_glass_pane waterlogged true south false east false north true west true 5937 light_blue_stained_glass_pane waterlogged true south false east false north true west false 5938 light_blue_stained_glass_pane waterlogged false south false east false north true west true 5939 light_blue_stained_glass_pane waterlogged false south false east false north true west false 5940 light_blue_stained_glass_pane waterlogged true south true east false north false west true 5941 light_blue_stained_glass_pane waterlogged true south true east false north false west false 5942 light_blue_stained_glass_pane waterlogged false south true east false north false west true 5943 light_blue_stained_glass_pane waterlogged false south true east false north false west false 5944 light_blue_stained_glass_pane waterlogged true south false east false north false west true 5945 light_blue_stained_glass_pane waterlogged true south false east false north false west false 5946 light_blue_stained_glass_pane waterlogged false south false east false north false west true 5947 light_blue_stained_glass_pane waterlogged false south false east false north false west false 5948 yellow_stained_glass_pane waterlogged true south true east true north true west true 5949 yellow_stained_glass_pane waterlogged true south true east true north true west false 5950 yellow_stained_glass_pane waterlogged false south true east true north true west true 5951 yellow_stained_glass_pane waterlogged false south true east true north true west false 5952 yellow_stained_glass_pane waterlogged true south false east true north true west true 5953 yellow_stained_glass_pane waterlogged true south false east true north true west false 5954 yellow_stained_glass_pane waterlogged false south false east true north true west true 5955 yellow_stained_glass_pane waterlogged false south false east true north true west false 5956 yellow_stained_glass_pane waterlogged true south true east true north false west true 5957 yellow_stained_glass_pane waterlogged true south true east true north false west false 5958 yellow_stained_glass_pane waterlogged false south true east true north false west true 5959 yellow_stained_glass_pane waterlogged false south true east true north false west false 5960 yellow_stained_glass_pane waterlogged true south false east true north false west true 5961 yellow_stained_glass_pane waterlogged true south false east true north false west false 5962 yellow_stained_glass_pane waterlogged false south false east true north false west true 5963 yellow_stained_glass_pane waterlogged false south false east true north false west false 5964 yellow_stained_glass_pane waterlogged true south true east false north true west true 5965 yellow_stained_glass_pane waterlogged true south true east false north true west false 5966 yellow_stained_glass_pane waterlogged false south true east false north true west true 5967 yellow_stained_glass_pane waterlogged false south true east false north true west false 5968 yellow_stained_glass_pane waterlogged true south false east false north true west true 5969 yellow_stained_glass_pane waterlogged true south false east false north true west false 5970 yellow_stained_glass_pane waterlogged false south false east false north true west true 5971 yellow_stained_glass_pane waterlogged false south false east false north true west false 5972 yellow_stained_glass_pane waterlogged true south true east false north false west true 5973 yellow_stained_glass_pane waterlogged true south true east false north false west false 5974 yellow_stained_glass_pane waterlogged false south true east false north false west true 5975 yellow_stained_glass_pane waterlogged false south true east false north false west false 5976 yellow_stained_glass_pane waterlogged true south false east false north false west true 5977 yellow_stained_glass_pane waterlogged true south false east false north false west false 5978 yellow_stained_glass_pane waterlogged false south false east false north false west true 5979 yellow_stained_glass_pane waterlogged false south false east false north false west false 5980 lime_stained_glass_pane waterlogged true south true east true north true west true 5981 lime_stained_glass_pane waterlogged true south true east true north true west false 5982 lime_stained_glass_pane waterlogged false south true east true north true west true 5983 lime_stained_glass_pane waterlogged false south true east true north true west false 5984 lime_stained_glass_pane waterlogged true south false east true north true west true 5985 lime_stained_glass_pane waterlogged true south false east true north true west false 5986 lime_stained_glass_pane waterlogged false south false east true north true west true 5987 lime_stained_glass_pane waterlogged false south false east true north true west false 5988 lime_stained_glass_pane waterlogged true south true east true north false west true 5989 lime_stained_glass_pane waterlogged true south true east true north false west false 5990 lime_stained_glass_pane waterlogged false south true east true north false west true 5991 lime_stained_glass_pane waterlogged false south true east true north false west false 5992 lime_stained_glass_pane waterlogged true south false east true north false west true 5993 lime_stained_glass_pane waterlogged true south false east true north false west false 5994 lime_stained_glass_pane waterlogged false south false east true north false west true 5995 lime_stained_glass_pane waterlogged false south false east true north false west false 5996 lime_stained_glass_pane waterlogged true south true east false north true west true 5997 lime_stained_glass_pane waterlogged true south true east false north true west false 5998 lime_stained_glass_pane waterlogged false south true east false north true west true 5999 lime_stained_glass_pane waterlogged false south true east false north true west false 6000 lime_stained_glass_pane waterlogged true south false east false north true west true 6001 lime_stained_glass_pane waterlogged true south false east false north true west false 6002 lime_stained_glass_pane waterlogged false south false east false north true west true 6003 lime_stained_glass_pane waterlogged false south false east false north true west false 6004 lime_stained_glass_pane waterlogged true south true east false north false west true 6005 lime_stained_glass_pane waterlogged true south true east false north false west false 6006 lime_stained_glass_pane waterlogged false south true east false north false west true 6007 lime_stained_glass_pane waterlogged false south true east false north false west false 6008 lime_stained_glass_pane waterlogged true south false east false north false west true 6009 lime_stained_glass_pane waterlogged true south false east false north false west false 6010 lime_stained_glass_pane waterlogged false south false east false north false west true 6011 lime_stained_glass_pane waterlogged false south false east false north false west false 6012 pink_stained_glass_pane waterlogged true south true east true north true west true 6013 pink_stained_glass_pane waterlogged true south true east true north true west false 6014 pink_stained_glass_pane waterlogged false south true east true north true west true 6015 pink_stained_glass_pane waterlogged false south true east true north true west false 6016 pink_stained_glass_pane waterlogged true south false east true north true west true 6017 pink_stained_glass_pane waterlogged true south false east true north true west false 6018 pink_stained_glass_pane waterlogged false south false east true north true west true 6019 pink_stained_glass_pane waterlogged false south false east true north true west false 6020 pink_stained_glass_pane waterlogged true south true east true north false west true 6021 pink_stained_glass_pane waterlogged true south true east true north false west false 6022 pink_stained_glass_pane waterlogged false south true east true north false west true 6023 pink_stained_glass_pane waterlogged false south true east true north false west false 6024 pink_stained_glass_pane waterlogged true south false east true north false west true 6025 pink_stained_glass_pane waterlogged true south false east true north false west false 6026 pink_stained_glass_pane waterlogged false south false east true north false west true 6027 pink_stained_glass_pane waterlogged false south false east true north false west false 6028 pink_stained_glass_pane waterlogged true south true east false north true west true 6029 pink_stained_glass_pane waterlogged true south true east false north true west false 6030 pink_stained_glass_pane waterlogged false south true east false north true west true 6031 pink_stained_glass_pane waterlogged false south true east false north true west false 6032 pink_stained_glass_pane waterlogged true south false east false north true west true 6033 pink_stained_glass_pane waterlogged true south false east false north true west false 6034 pink_stained_glass_pane waterlogged false south false east false north true west true 6035 pink_stained_glass_pane waterlogged false south false east false north true west false 6036 pink_stained_glass_pane waterlogged true south true east false north false west true 6037 pink_stained_glass_pane waterlogged true south true east false north false west false 6038 pink_stained_glass_pane waterlogged false south true east false north false west true 6039 pink_stained_glass_pane waterlogged false south true east false north false west false 6040 pink_stained_glass_pane waterlogged true south false east false north false west true 6041 pink_stained_glass_pane waterlogged true south false east false north false west false 6042 pink_stained_glass_pane waterlogged false south false east false north false west true 6043 pink_stained_glass_pane waterlogged false south false east false north false west false 6044 gray_stained_glass_pane waterlogged true south true east true north true west true 6045 gray_stained_glass_pane waterlogged true south true east true north true west false 6046 gray_stained_glass_pane waterlogged false south true east true north true west true 6047 gray_stained_glass_pane waterlogged false south true east true north true west false 6048 gray_stained_glass_pane waterlogged true south false east true north true west true 6049 gray_stained_glass_pane waterlogged true south false east true north true west false 6050 gray_stained_glass_pane waterlogged false south false east true north true west true 6051 gray_stained_glass_pane waterlogged false south false east true north true west false 6052 gray_stained_glass_pane waterlogged true south true east true north false west true 6053 gray_stained_glass_pane waterlogged true south true east true north false west false 6054 gray_stained_glass_pane waterlogged false south true east true north false west true 6055 gray_stained_glass_pane waterlogged false south true east true north false west false 6056 gray_stained_glass_pane waterlogged true south false east true north false west true 6057 gray_stained_glass_pane waterlogged true south false east true north false west false 6058 gray_stained_glass_pane waterlogged false south false east true north false west true 6059 gray_stained_glass_pane waterlogged false south false east true north false west false 6060 gray_stained_glass_pane waterlogged true south true east false north true west true 6061 gray_stained_glass_pane waterlogged true south true east false north true west false 6062 gray_stained_glass_pane waterlogged false south true east false north true west true 6063 gray_stained_glass_pane waterlogged false south true east false north true west false 6064 gray_stained_glass_pane waterlogged true south false east false north true west true 6065 gray_stained_glass_pane waterlogged true south false east false north true west false 6066 gray_stained_glass_pane waterlogged false south false east false north true west true 6067 gray_stained_glass_pane waterlogged false south false east false north true west false 6068 gray_stained_glass_pane waterlogged true south true east false north false west true 6069 gray_stained_glass_pane waterlogged true south true east false north false west false 6070 gray_stained_glass_pane waterlogged false south true east false north false west true 6071 gray_stained_glass_pane waterlogged false south true east false north false west false 6072 gray_stained_glass_pane waterlogged true south false east false north false west true 6073 gray_stained_glass_pane waterlogged true south false east false north false west false 6074 gray_stained_glass_pane waterlogged false south false east false north false west true 6075 gray_stained_glass_pane waterlogged false south false east false north false west false 6076 light_gray_stained_glass_pane waterlogged true south true east true north true west true 6077 light_gray_stained_glass_pane waterlogged true south true east true north true west false 6078 light_gray_stained_glass_pane waterlogged false south true east true north true west true 6079 light_gray_stained_glass_pane waterlogged false south true east true north true west false 6080 light_gray_stained_glass_pane waterlogged true south false east true north true west true 6081 light_gray_stained_glass_pane waterlogged true south false east true north true west false 6082 light_gray_stained_glass_pane waterlogged false south false east true north true west true 6083 light_gray_stained_glass_pane waterlogged false south false east true north true west false 6084 light_gray_stained_glass_pane waterlogged true south true east true north false west true 6085 light_gray_stained_glass_pane waterlogged true south true east true north false west false 6086 light_gray_stained_glass_pane waterlogged false south true east true north false west true 6087 light_gray_stained_glass_pane waterlogged false south true east true north false west false 6088 light_gray_stained_glass_pane waterlogged true south false east true north false west true 6089 light_gray_stained_glass_pane waterlogged true south false east true north false west false 6090 light_gray_stained_glass_pane waterlogged false south false east true north false west true 6091 light_gray_stained_glass_pane waterlogged false south false east true north false west false 6092 light_gray_stained_glass_pane waterlogged true south true east false north true west true 6093 light_gray_stained_glass_pane waterlogged true south true east false north true west false 6094 light_gray_stained_glass_pane waterlogged false south true east false north true west true 6095 light_gray_stained_glass_pane waterlogged false south true east false north true west false 6096 light_gray_stained_glass_pane waterlogged true south false east false north true west true 6097 light_gray_stained_glass_pane waterlogged true south false east false north true west false 6098 light_gray_stained_glass_pane waterlogged false south false east false north true west true 6099 light_gray_stained_glass_pane waterlogged false south false east false north true west false 6100 light_gray_stained_glass_pane waterlogged true south true east false north false west true 6101 light_gray_stained_glass_pane waterlogged true south true east false north false west false 6102 light_gray_stained_glass_pane waterlogged false south true east false north false west true 6103 light_gray_stained_glass_pane waterlogged false south true east false north false west false 6104 light_gray_stained_glass_pane waterlogged true south false east false north false west true 6105 light_gray_stained_glass_pane waterlogged true south false east false north false west false 6106 light_gray_stained_glass_pane waterlogged false south false east false north false west true 6107 light_gray_stained_glass_pane waterlogged false south false east false north false west false 6108 cyan_stained_glass_pane waterlogged true south true east true north true west true 6109 cyan_stained_glass_pane waterlogged true south true east true north true west false 6110 cyan_stained_glass_pane waterlogged false south true east true north true west true 6111 cyan_stained_glass_pane waterlogged false south true east true north true west false 6112 cyan_stained_glass_pane waterlogged true south false east true north true west true 6113 cyan_stained_glass_pane waterlogged true south false east true north true west false 6114 cyan_stained_glass_pane waterlogged false south false east true north true west true 6115 cyan_stained_glass_pane waterlogged false south false east true north true west false 6116 cyan_stained_glass_pane waterlogged true south true east true north false west true 6117 cyan_stained_glass_pane waterlogged true south true east true north false west false 6118 cyan_stained_glass_pane waterlogged false south true east true north false west true 6119 cyan_stained_glass_pane waterlogged false south true east true north false west false 6120 cyan_stained_glass_pane waterlogged true south false east true north false west true 6121 cyan_stained_glass_pane waterlogged true south false east true north false west false 6122 cyan_stained_glass_pane waterlogged false south false east true north false west true 6123 cyan_stained_glass_pane waterlogged false south false east true north false west false 6124 cyan_stained_glass_pane waterlogged true south true east false north true west true 6125 cyan_stained_glass_pane waterlogged true south true east false north true west false 6126 cyan_stained_glass_pane waterlogged false south true east false north true west true 6127 cyan_stained_glass_pane waterlogged false south true east false north true west false 6128 cyan_stained_glass_pane waterlogged true south false east false north true west true 6129 cyan_stained_glass_pane waterlogged true south false east false north true west false 6130 cyan_stained_glass_pane waterlogged false south false east false north true west true 6131 cyan_stained_glass_pane waterlogged false south false east false north true west false 6132 cyan_stained_glass_pane waterlogged true south true east false north false west true 6133 cyan_stained_glass_pane waterlogged true south true east false north false west false 6134 cyan_stained_glass_pane waterlogged false south true east false north false west true 6135 cyan_stained_glass_pane waterlogged false south true east false north false west false 6136 cyan_stained_glass_pane waterlogged true south false east false north false west true 6137 cyan_stained_glass_pane waterlogged true south false east false north false west false 6138 cyan_stained_glass_pane waterlogged false south false east false north false west true 6139 cyan_stained_glass_pane waterlogged false south false east false north false west false 6140 purple_stained_glass_pane waterlogged true south true east true north true west true 6141 purple_stained_glass_pane waterlogged true south true east true north true west false 6142 purple_stained_glass_pane waterlogged false south true east true north true west true 6143 purple_stained_glass_pane waterlogged false south true east true north true west false 6144 purple_stained_glass_pane waterlogged true south false east true north true west true 6145 purple_stained_glass_pane waterlogged true south false east true north true west false 6146 purple_stained_glass_pane waterlogged false south false east true north true west true 6147 purple_stained_glass_pane waterlogged false south false east true north true west false 6148 purple_stained_glass_pane waterlogged true south true east true north false west true 6149 purple_stained_glass_pane waterlogged true south true east true north false west false 6150 purple_stained_glass_pane waterlogged false south true east true north false west true 6151 purple_stained_glass_pane waterlogged false south true east true north false west false 6152 purple_stained_glass_pane waterlogged true south false east true north false west true 6153 purple_stained_glass_pane waterlogged true south false east true north false west false 6154 purple_stained_glass_pane waterlogged false south false east true north false west true 6155 purple_stained_glass_pane waterlogged false south false east true north false west false 6156 purple_stained_glass_pane waterlogged true south true east false north true west true 6157 purple_stained_glass_pane waterlogged true south true east false north true west false 6158 purple_stained_glass_pane waterlogged false south true east false north true west true 6159 purple_stained_glass_pane waterlogged false south true east false north true west false 6160 purple_stained_glass_pane waterlogged true south false east false north true west true 6161 purple_stained_glass_pane waterlogged true south false east false north true west false 6162 purple_stained_glass_pane waterlogged false south false east false north true west true 6163 purple_stained_glass_pane waterlogged false south false east false north true west false 6164 purple_stained_glass_pane waterlogged true south true east false north false west true 6165 purple_stained_glass_pane waterlogged true south true east false north false west false 6166 purple_stained_glass_pane waterlogged false south true east false north false west true 6167 purple_stained_glass_pane waterlogged false south true east false north false west false 6168 purple_stained_glass_pane waterlogged true south false east false north false west true 6169 purple_stained_glass_pane waterlogged true south false east false north false west false 6170 purple_stained_glass_pane waterlogged false south false east false north false west true 6171 purple_stained_glass_pane waterlogged false south false east false north false west false 6172 blue_stained_glass_pane waterlogged true south true east true north true west true 6173 blue_stained_glass_pane waterlogged true south true east true north true west false 6174 blue_stained_glass_pane waterlogged false south true east true north true west true 6175 blue_stained_glass_pane waterlogged false south true east true north true west false 6176 blue_stained_glass_pane waterlogged true south false east true north true west true 6177 blue_stained_glass_pane waterlogged true south false east true north true west false 6178 blue_stained_glass_pane waterlogged false south false east true north true west true 6179 blue_stained_glass_pane waterlogged false south false east true north true west false 6180 blue_stained_glass_pane waterlogged true south true east true north false west true 6181 blue_stained_glass_pane waterlogged true south true east true north false west false 6182 blue_stained_glass_pane waterlogged false south true east true north false west true 6183 blue_stained_glass_pane waterlogged false south true east true north false west false 6184 blue_stained_glass_pane waterlogged true south false east true north false west true 6185 blue_stained_glass_pane waterlogged true south false east true north false west false 6186 blue_stained_glass_pane waterlogged false south false east true north false west true 6187 blue_stained_glass_pane waterlogged false south false east true north false west false 6188 blue_stained_glass_pane waterlogged true south true east false north true west true 6189 blue_stained_glass_pane waterlogged true south true east false north true west false 6190 blue_stained_glass_pane waterlogged false south true east false north true west true 6191 blue_stained_glass_pane waterlogged false south true east false north true west false 6192 blue_stained_glass_pane waterlogged true south false east false north true west true 6193 blue_stained_glass_pane waterlogged true south false east false north true west false 6194 blue_stained_glass_pane waterlogged false south false east false north true west true 6195 blue_stained_glass_pane waterlogged false south false east false north true west false 6196 blue_stained_glass_pane waterlogged true south true east false north false west true 6197 blue_stained_glass_pane waterlogged true south true east false north false west false 6198 blue_stained_glass_pane waterlogged false south true east false north false west true 6199 blue_stained_glass_pane waterlogged false south true east false north false west false 6200 blue_stained_glass_pane waterlogged true south false east false north false west true 6201 blue_stained_glass_pane waterlogged true south false east false north false west false 6202 blue_stained_glass_pane waterlogged false south false east false north false west true 6203 blue_stained_glass_pane waterlogged false south false east false north false west false 6204 brown_stained_glass_pane waterlogged true south true east true north true west true 6205 brown_stained_glass_pane waterlogged true south true east true north true west false 6206 brown_stained_glass_pane waterlogged false south true east true north true west true 6207 brown_stained_glass_pane waterlogged false south true east true north true west false 6208 brown_stained_glass_pane waterlogged true south false east true north true west true 6209 brown_stained_glass_pane waterlogged true south false east true north true west false 6210 brown_stained_glass_pane waterlogged false south false east true north true west true 6211 brown_stained_glass_pane waterlogged false south false east true north true west false 6212 brown_stained_glass_pane waterlogged true south true east true north false west true 6213 brown_stained_glass_pane waterlogged true south true east true north false west false 6214 brown_stained_glass_pane waterlogged false south true east true north false west true 6215 brown_stained_glass_pane waterlogged false south true east true north false west false 6216 brown_stained_glass_pane waterlogged true south false east true north false west true 6217 brown_stained_glass_pane waterlogged true south false east true north false west false 6218 brown_stained_glass_pane waterlogged false south false east true north false west true 6219 brown_stained_glass_pane waterlogged false south false east true north false west false 6220 brown_stained_glass_pane waterlogged true south true east false north true west true 6221 brown_stained_glass_pane waterlogged true south true east false north true west false 6222 brown_stained_glass_pane waterlogged false south true east false north true west true 6223 brown_stained_glass_pane waterlogged false south true east false north true west false 6224 brown_stained_glass_pane waterlogged true south false east false north true west true 6225 brown_stained_glass_pane waterlogged true south false east false north true west false 6226 brown_stained_glass_pane waterlogged false south false east false north true west true 6227 brown_stained_glass_pane waterlogged false south false east false north true west false 6228 brown_stained_glass_pane waterlogged true south true east false north false west true 6229 brown_stained_glass_pane waterlogged true south true east false north false west false 6230 brown_stained_glass_pane waterlogged false south true east false north false west true 6231 brown_stained_glass_pane waterlogged false south true east false north false west false 6232 brown_stained_glass_pane waterlogged true south false east false north false west true 6233 brown_stained_glass_pane waterlogged true south false east false north false west false 6234 brown_stained_glass_pane waterlogged false south false east false north false west true 6235 brown_stained_glass_pane waterlogged false south false east false north false west false 6236 green_stained_glass_pane waterlogged true south true east true north true west true 6237 green_stained_glass_pane waterlogged true south true east true north true west false 6238 green_stained_glass_pane waterlogged false south true east true north true west true 6239 green_stained_glass_pane waterlogged false south true east true north true west false 6240 green_stained_glass_pane waterlogged true south false east true north true west true 6241 green_stained_glass_pane waterlogged true south false east true north true west false 6242 green_stained_glass_pane waterlogged false south false east true north true west true 6243 green_stained_glass_pane waterlogged false south false east true north true west false 6244 green_stained_glass_pane waterlogged true south true east true north false west true 6245 green_stained_glass_pane waterlogged true south true east true north false west false 6246 green_stained_glass_pane waterlogged false south true east true north false west true 6247 green_stained_glass_pane waterlogged false south true east true north false west false 6248 green_stained_glass_pane waterlogged true south false east true north false west true 6249 green_stained_glass_pane waterlogged true south false east true north false west false 6250 green_stained_glass_pane waterlogged false south false east true north false west true 6251 green_stained_glass_pane waterlogged false south false east true north false west false 6252 green_stained_glass_pane waterlogged true south true east false north true west true 6253 green_stained_glass_pane waterlogged true south true east false north true west false 6254 green_stained_glass_pane waterlogged false south true east false north true west true 6255 green_stained_glass_pane waterlogged false south true east false north true west false 6256 green_stained_glass_pane waterlogged true south false east false north true west true 6257 green_stained_glass_pane waterlogged true south false east false north true west false 6258 green_stained_glass_pane waterlogged false south false east false north true west true 6259 green_stained_glass_pane waterlogged false south false east false north true west false 6260 green_stained_glass_pane waterlogged true south true east false north false west true 6261 green_stained_glass_pane waterlogged true south true east false north false west false 6262 green_stained_glass_pane waterlogged false south true east false north false west true 6263 green_stained_glass_pane waterlogged false south true east false north false west false 6264 green_stained_glass_pane waterlogged true south false east false north false west true 6265 green_stained_glass_pane waterlogged true south false east false north false west false 6266 green_stained_glass_pane waterlogged false south false east false north false west true 6267 green_stained_glass_pane waterlogged false south false east false north false west false 6268 red_stained_glass_pane waterlogged true south true east true north true west true 6269 red_stained_glass_pane waterlogged true south true east true north true west false 6270 red_stained_glass_pane waterlogged false south true east true north true west true 6271 red_stained_glass_pane waterlogged false south true east true north true west false 6272 red_stained_glass_pane waterlogged true south false east true north true west true 6273 red_stained_glass_pane waterlogged true south false east true north true west false 6274 red_stained_glass_pane waterlogged false south false east true north true west true 6275 red_stained_glass_pane waterlogged false south false east true north true west false 6276 red_stained_glass_pane waterlogged true south true east true north false west true 6277 red_stained_glass_pane waterlogged true south true east true north false west false 6278 red_stained_glass_pane waterlogged false south true east true north false west true 6279 red_stained_glass_pane waterlogged false south true east true north false west false 6280 red_stained_glass_pane waterlogged true south false east true north false west true 6281 red_stained_glass_pane waterlogged true south false east true north false west false 6282 red_stained_glass_pane waterlogged false south false east true north false west true 6283 red_stained_glass_pane waterlogged false south false east true north false west false 6284 red_stained_glass_pane waterlogged true south true east false north true west true 6285 red_stained_glass_pane waterlogged true south true east false north true west false 6286 red_stained_glass_pane waterlogged false south true east false north true west true 6287 red_stained_glass_pane waterlogged false south true east false north true west false 6288 red_stained_glass_pane waterlogged true south false east false north true west true 6289 red_stained_glass_pane waterlogged true south false east false north true west false 6290 red_stained_glass_pane waterlogged false south false east false north true west true 6291 red_stained_glass_pane waterlogged false south false east false north true west false 6292 red_stained_glass_pane waterlogged true south true east false north false west true 6293 red_stained_glass_pane waterlogged true south true east false north false west false 6294 red_stained_glass_pane waterlogged false south true east false north false west true 6295 red_stained_glass_pane waterlogged false south true east false north false west false 6296 red_stained_glass_pane waterlogged true south false east false north false west true 6297 red_stained_glass_pane waterlogged true south false east false north false west false 6298 red_stained_glass_pane waterlogged false south false east false north false west true 6299 red_stained_glass_pane waterlogged false south false east false north false west false 6300 black_stained_glass_pane waterlogged true south true east true north true west true 6301 black_stained_glass_pane waterlogged true south true east true north true west false 6302 black_stained_glass_pane waterlogged false south true east true north true west true 6303 black_stained_glass_pane waterlogged false south true east true north true west false 6304 black_stained_glass_pane waterlogged true south false east true north true west true 6305 black_stained_glass_pane waterlogged true south false east true north true west false 6306 black_stained_glass_pane waterlogged false south false east true north true west true 6307 black_stained_glass_pane waterlogged false south false east true north true west false 6308 black_stained_glass_pane waterlogged true south true east true north false west true 6309 black_stained_glass_pane waterlogged true south true east true north false west false 6310 black_stained_glass_pane waterlogged false south true east true north false west true 6311 black_stained_glass_pane waterlogged false south true east true north false west false 6312 black_stained_glass_pane waterlogged true south false east true north false west true 6313 black_stained_glass_pane waterlogged true south false east true north false west false 6314 black_stained_glass_pane waterlogged false south false east true north false west true 6315 black_stained_glass_pane waterlogged false south false east true north false west false 6316 black_stained_glass_pane waterlogged true south true east false north true west true 6317 black_stained_glass_pane waterlogged true south true east false north true west false 6318 black_stained_glass_pane waterlogged false south true east false north true west true 6319 black_stained_glass_pane waterlogged false south true east false north true west false 6320 black_stained_glass_pane waterlogged true south false east false north true west true 6321 black_stained_glass_pane waterlogged true south false east false north true west false 6322 black_stained_glass_pane waterlogged false south false east false north true west true 6323 black_stained_glass_pane waterlogged false south false east false north true west false 6324 black_stained_glass_pane waterlogged true south true east false north false west true 6325 black_stained_glass_pane waterlogged true south true east false north false west false 6326 black_stained_glass_pane waterlogged false south true east false north false west true 6327 black_stained_glass_pane waterlogged false south true east false north false west false 6328 black_stained_glass_pane waterlogged true south false east false north false west true 6329 black_stained_glass_pane waterlogged true south false east false north false west false 6330 black_stained_glass_pane waterlogged false south false east false north false west true 6331 black_stained_glass_pane waterlogged false south false east false north false west false 6332 acacia_stairs facing north waterlogged true shape straight half top 6333 acacia_stairs facing north waterlogged false shape straight half top 6334 acacia_stairs facing north waterlogged true shape inner_left half top 6335 acacia_stairs facing north waterlogged false shape inner_left half top 6336 acacia_stairs facing north waterlogged true shape inner_right half top 6337 acacia_stairs facing north waterlogged false shape inner_right half top 6338 acacia_stairs facing north waterlogged true shape outer_left half top 6339 acacia_stairs facing north waterlogged false shape outer_left half top 6340 acacia_stairs facing north waterlogged true shape outer_right half top 6341 acacia_stairs facing north waterlogged false shape outer_right half top 6342 acacia_stairs facing north waterlogged true shape straight half bottom 6343 acacia_stairs facing north waterlogged false shape straight half bottom 6344 acacia_stairs facing north waterlogged true shape inner_left half bottom 6345 acacia_stairs facing north waterlogged false shape inner_left half bottom 6346 acacia_stairs facing north waterlogged true shape inner_right half bottom 6347 acacia_stairs facing north waterlogged false shape inner_right half bottom 6348 acacia_stairs facing north waterlogged true shape outer_left half bottom 6349 acacia_stairs facing north waterlogged false shape outer_left half bottom 6350 acacia_stairs facing north waterlogged true shape outer_right half bottom 6351 acacia_stairs facing north waterlogged false shape outer_right half bottom 6352 acacia_stairs facing south waterlogged true shape straight half top 6353 acacia_stairs facing south waterlogged false shape straight half top 6354 acacia_stairs facing south waterlogged true shape inner_left half top 6355 acacia_stairs facing south waterlogged false shape inner_left half top 6356 acacia_stairs facing south waterlogged true shape inner_right half top 6357 acacia_stairs facing south waterlogged false shape inner_right half top 6358 acacia_stairs facing south waterlogged true shape outer_left half top 6359 acacia_stairs facing south waterlogged false shape outer_left half top 6360 acacia_stairs facing south waterlogged true shape outer_right half top 6361 acacia_stairs facing south waterlogged false shape outer_right half top 6362 acacia_stairs facing south waterlogged true shape straight half bottom 6363 acacia_stairs facing south waterlogged false shape straight half bottom 6364 acacia_stairs facing south waterlogged true shape inner_left half bottom 6365 acacia_stairs facing south waterlogged false shape inner_left half bottom 6366 acacia_stairs facing south waterlogged true shape inner_right half bottom 6367 acacia_stairs facing south waterlogged false shape inner_right half bottom 6368 acacia_stairs facing south waterlogged true shape outer_left half bottom 6369 acacia_stairs facing south waterlogged false shape outer_left half bottom 6370 acacia_stairs facing south waterlogged true shape outer_right half bottom 6371 acacia_stairs facing south waterlogged false shape outer_right half bottom 6372 acacia_stairs facing west waterlogged true shape straight half top 6373 acacia_stairs facing west waterlogged false shape straight half top 6374 acacia_stairs facing west waterlogged true shape inner_left half top 6375 acacia_stairs facing west waterlogged false shape inner_left half top 6376 acacia_stairs facing west waterlogged true shape inner_right half top 6377 acacia_stairs facing west waterlogged false shape inner_right half top 6378 acacia_stairs facing west waterlogged true shape outer_left half top 6379 acacia_stairs facing west waterlogged false shape outer_left half top 6380 acacia_stairs facing west waterlogged true shape outer_right half top 6381 acacia_stairs facing west waterlogged false shape outer_right half top 6382 acacia_stairs facing west waterlogged true shape straight half bottom 6383 acacia_stairs facing west waterlogged false shape straight half bottom 6384 acacia_stairs facing west waterlogged true shape inner_left half bottom 6385 acacia_stairs facing west waterlogged false shape inner_left half bottom 6386 acacia_stairs facing west waterlogged true shape inner_right half bottom 6387 acacia_stairs facing west waterlogged false shape inner_right half bottom 6388 acacia_stairs facing west waterlogged true shape outer_left half bottom 6389 acacia_stairs facing west waterlogged false shape outer_left half bottom 6390 acacia_stairs facing west waterlogged true shape outer_right half bottom 6391 acacia_stairs facing west waterlogged false shape outer_right half bottom 6392 acacia_stairs facing east waterlogged true shape straight half top 6393 acacia_stairs facing east waterlogged false shape straight half top 6394 acacia_stairs facing east waterlogged true shape inner_left half top 6395 acacia_stairs facing east waterlogged false shape inner_left half top 6396 acacia_stairs facing east waterlogged true shape inner_right half top 6397 acacia_stairs facing east waterlogged false shape inner_right half top 6398 acacia_stairs facing east waterlogged true shape outer_left half top 6399 acacia_stairs facing east waterlogged false shape outer_left half top 6400 acacia_stairs facing east waterlogged true shape outer_right half top 6401 acacia_stairs facing east waterlogged false shape outer_right half top 6402 acacia_stairs facing east waterlogged true shape straight half bottom 6403 acacia_stairs facing east waterlogged false shape straight half bottom 6404 acacia_stairs facing east waterlogged true shape inner_left half bottom 6405 acacia_stairs facing east waterlogged false shape inner_left half bottom 6406 acacia_stairs facing east waterlogged true shape inner_right half bottom 6407 acacia_stairs facing east waterlogged false shape inner_right half bottom 6408 acacia_stairs facing east waterlogged true shape outer_left half bottom 6409 acacia_stairs facing east waterlogged false shape outer_left half bottom 6410 acacia_stairs facing east waterlogged true shape outer_right half bottom 6411 acacia_stairs facing east waterlogged false shape outer_right half bottom 6412 dark_oak_stairs facing north waterlogged true shape straight half top 6413 dark_oak_stairs facing north waterlogged false shape straight half top 6414 dark_oak_stairs facing north waterlogged true shape inner_left half top 6415 dark_oak_stairs facing north waterlogged false shape inner_left half top 6416 dark_oak_stairs facing north waterlogged true shape inner_right half top 6417 dark_oak_stairs facing north waterlogged false shape inner_right half top 6418 dark_oak_stairs facing north waterlogged true shape outer_left half top 6419 dark_oak_stairs facing north waterlogged false shape outer_left half top 6420 dark_oak_stairs facing north waterlogged true shape outer_right half top 6421 dark_oak_stairs facing north waterlogged false shape outer_right half top 6422 dark_oak_stairs facing north waterlogged true shape straight half bottom 6423 dark_oak_stairs facing north waterlogged false shape straight half bottom 6424 dark_oak_stairs facing north waterlogged true shape inner_left half bottom 6425 dark_oak_stairs facing north waterlogged false shape inner_left half bottom 6426 dark_oak_stairs facing north waterlogged true shape inner_right half bottom 6427 dark_oak_stairs facing north waterlogged false shape inner_right half bottom 6428 dark_oak_stairs facing north waterlogged true shape outer_left half bottom 6429 dark_oak_stairs facing north waterlogged false shape outer_left half bottom 6430 dark_oak_stairs facing north waterlogged true shape outer_right half bottom 6431 dark_oak_stairs facing north waterlogged false shape outer_right half bottom 6432 dark_oak_stairs facing south waterlogged true shape straight half top 6433 dark_oak_stairs facing south waterlogged false shape straight half top 6434 dark_oak_stairs facing south waterlogged true shape inner_left half top 6435 dark_oak_stairs facing south waterlogged false shape inner_left half top 6436 dark_oak_stairs facing south waterlogged true shape inner_right half top 6437 dark_oak_stairs facing south waterlogged false shape inner_right half top 6438 dark_oak_stairs facing south waterlogged true shape outer_left half top 6439 dark_oak_stairs facing south waterlogged false shape outer_left half top 6440 dark_oak_stairs facing south waterlogged true shape outer_right half top 6441 dark_oak_stairs facing south waterlogged false shape outer_right half top 6442 dark_oak_stairs facing south waterlogged true shape straight half bottom 6443 dark_oak_stairs facing south waterlogged false shape straight half bottom 6444 dark_oak_stairs facing south waterlogged true shape inner_left half bottom 6445 dark_oak_stairs facing south waterlogged false shape inner_left half bottom 6446 dark_oak_stairs facing south waterlogged true shape inner_right half bottom 6447 dark_oak_stairs facing south waterlogged false shape inner_right half bottom 6448 dark_oak_stairs facing south waterlogged true shape outer_left half bottom 6449 dark_oak_stairs facing south waterlogged false shape outer_left half bottom 6450 dark_oak_stairs facing south waterlogged true shape outer_right half bottom 6451 dark_oak_stairs facing south waterlogged false shape outer_right half bottom 6452 dark_oak_stairs facing west waterlogged true shape straight half top 6453 dark_oak_stairs facing west waterlogged false shape straight half top 6454 dark_oak_stairs facing west waterlogged true shape inner_left half top 6455 dark_oak_stairs facing west waterlogged false shape inner_left half top 6456 dark_oak_stairs facing west waterlogged true shape inner_right half top 6457 dark_oak_stairs facing west waterlogged false shape inner_right half top 6458 dark_oak_stairs facing west waterlogged true shape outer_left half top 6459 dark_oak_stairs facing west waterlogged false shape outer_left half top 6460 dark_oak_stairs facing west waterlogged true shape outer_right half top 6461 dark_oak_stairs facing west waterlogged false shape outer_right half top 6462 dark_oak_stairs facing west waterlogged true shape straight half bottom 6463 dark_oak_stairs facing west waterlogged false shape straight half bottom 6464 dark_oak_stairs facing west waterlogged true shape inner_left half bottom 6465 dark_oak_stairs facing west waterlogged false shape inner_left half bottom 6466 dark_oak_stairs facing west waterlogged true shape inner_right half bottom 6467 dark_oak_stairs facing west waterlogged false shape inner_right half bottom 6468 dark_oak_stairs facing west waterlogged true shape outer_left half bottom 6469 dark_oak_stairs facing west waterlogged false shape outer_left half bottom 6470 dark_oak_stairs facing west waterlogged true shape outer_right half bottom 6471 dark_oak_stairs facing west waterlogged false shape outer_right half bottom 6472 dark_oak_stairs facing east waterlogged true shape straight half top 6473 dark_oak_stairs facing east waterlogged false shape straight half top 6474 dark_oak_stairs facing east waterlogged true shape inner_left half top 6475 dark_oak_stairs facing east waterlogged false shape inner_left half top 6476 dark_oak_stairs facing east waterlogged true shape inner_right half top 6477 dark_oak_stairs facing east waterlogged false shape inner_right half top 6478 dark_oak_stairs facing east waterlogged true shape outer_left half top 6479 dark_oak_stairs facing east waterlogged false shape outer_left half top 6480 dark_oak_stairs facing east waterlogged true shape outer_right half top 6481 dark_oak_stairs facing east waterlogged false shape outer_right half top 6482 dark_oak_stairs facing east waterlogged true shape straight half bottom 6483 dark_oak_stairs facing east waterlogged false shape straight half bottom 6484 dark_oak_stairs facing east waterlogged true shape inner_left half bottom 6485 dark_oak_stairs facing east waterlogged false shape inner_left half bottom 6486 dark_oak_stairs facing east waterlogged true shape inner_right half bottom 6487 dark_oak_stairs facing east waterlogged false shape inner_right half bottom 6488 dark_oak_stairs facing east waterlogged true shape outer_left half bottom 6489 dark_oak_stairs facing east waterlogged false shape outer_left half bottom 6490 dark_oak_stairs facing east waterlogged true shape outer_right half bottom 6491 dark_oak_stairs facing east waterlogged false shape outer_right half bottom 6492 slime_block 6493 barrier 6494 iron_trapdoor waterlogged true powered true facing north half top open true 6495 iron_trapdoor waterlogged false powered true facing north half top open true 6496 iron_trapdoor waterlogged true powered false facing north half top open true 6497 iron_trapdoor waterlogged false powered false facing north half top open true 6498 iron_trapdoor waterlogged true powered true facing north half top open false 6499 iron_trapdoor waterlogged false powered true facing north half top open false 6500 iron_trapdoor waterlogged true powered false facing north half top open false 6501 iron_trapdoor waterlogged false powered false facing north half top open false 6502 iron_trapdoor waterlogged true powered true facing north half bottom open true 6503 iron_trapdoor waterlogged false powered true facing north half bottom open true 6504 iron_trapdoor waterlogged true powered false facing north half bottom open true 6505 iron_trapdoor waterlogged false powered false facing north half bottom open true 6506 iron_trapdoor waterlogged true powered true facing north half bottom open false 6507 iron_trapdoor waterlogged false powered true facing north half bottom open false 6508 iron_trapdoor waterlogged true powered false facing north half bottom open false 6509 iron_trapdoor waterlogged false powered false facing north half bottom open false 6510 iron_trapdoor waterlogged true powered true facing south half top open true 6511 iron_trapdoor waterlogged false powered true facing south half top open true 6512 iron_trapdoor waterlogged true powered false facing south half top open true 6513 iron_trapdoor waterlogged false powered false facing south half top open true 6514 iron_trapdoor waterlogged true powered true facing south half top open false 6515 iron_trapdoor waterlogged false powered true facing south half top open false 6516 iron_trapdoor waterlogged true powered false facing south half top open false 6517 iron_trapdoor waterlogged false powered false facing south half top open false 6518 iron_trapdoor waterlogged true powered true facing south half bottom open true 6519 iron_trapdoor waterlogged false powered true facing south half bottom open true 6520 iron_trapdoor waterlogged true powered false facing south half bottom open true 6521 iron_trapdoor waterlogged false powered false facing south half bottom open true 6522 iron_trapdoor waterlogged true powered true facing south half bottom open false 6523 iron_trapdoor waterlogged false powered true facing south half bottom open false 6524 iron_trapdoor waterlogged true powered false facing south half bottom open false 6525 iron_trapdoor waterlogged false powered false facing south half bottom open false 6526 iron_trapdoor waterlogged true powered true facing west half top open true 6527 iron_trapdoor waterlogged false powered true facing west half top open true 6528 iron_trapdoor waterlogged true powered false facing west half top open true 6529 iron_trapdoor waterlogged false powered false facing west half top open true 6530 iron_trapdoor waterlogged true powered true facing west half top open false 6531 iron_trapdoor waterlogged false powered true facing west half top open false 6532 iron_trapdoor waterlogged true powered false facing west half top open false 6533 iron_trapdoor waterlogged false powered false facing west half top open false 6534 iron_trapdoor waterlogged true powered true facing west half bottom open true 6535 iron_trapdoor waterlogged false powered true facing west half bottom open true 6536 iron_trapdoor waterlogged true powered false facing west half bottom open true 6537 iron_trapdoor waterlogged false powered false facing west half bottom open true 6538 iron_trapdoor waterlogged true powered true facing west half bottom open false 6539 iron_trapdoor waterlogged false powered true facing west half bottom open false 6540 iron_trapdoor waterlogged true powered false facing west half bottom open false 6541 iron_trapdoor waterlogged false powered false facing west half bottom open false 6542 iron_trapdoor waterlogged true powered true facing east half top open true 6543 iron_trapdoor waterlogged false powered true facing east half top open true 6544 iron_trapdoor waterlogged true powered false facing east half top open true 6545 iron_trapdoor waterlogged false powered false facing east half top open true 6546 iron_trapdoor waterlogged true powered true facing east half top open false 6547 iron_trapdoor waterlogged false powered true facing east half top open false 6548 iron_trapdoor waterlogged true powered false facing east half top open false 6549 iron_trapdoor waterlogged false powered false facing east half top open false 6550 iron_trapdoor waterlogged true powered true facing east half bottom open true 6551 iron_trapdoor waterlogged false powered true facing east half bottom open true 6552 iron_trapdoor waterlogged true powered false facing east half bottom open true 6553 iron_trapdoor waterlogged false powered false facing east half bottom open true 6554 iron_trapdoor waterlogged true powered true facing east half bottom open false 6555 iron_trapdoor waterlogged false powered true facing east half bottom open false 6556 iron_trapdoor waterlogged true powered false facing east half bottom open false 6557 iron_trapdoor waterlogged false powered false facing east half bottom open false 6558 prismarine 6559 prismarine_bricks 6560 dark_prismarine 6561 prismarine_stairs facing north waterlogged true shape straight half top 6562 prismarine_stairs facing north waterlogged false shape straight half top 6563 prismarine_stairs facing north waterlogged true shape inner_left half top 6564 prismarine_stairs facing north waterlogged false shape inner_left half top 6565 prismarine_stairs facing north waterlogged true shape inner_right half top 6566 prismarine_stairs facing north waterlogged false shape inner_right half top 6567 prismarine_stairs facing north waterlogged true shape outer_left half top 6568 prismarine_stairs facing north waterlogged false shape outer_left half top 6569 prismarine_stairs facing north waterlogged true shape outer_right half top 6570 prismarine_stairs facing north waterlogged false shape outer_right half top 6571 prismarine_stairs facing north waterlogged true shape straight half bottom 6572 prismarine_stairs facing north waterlogged false shape straight half bottom 6573 prismarine_stairs facing north waterlogged true shape inner_left half bottom 6574 prismarine_stairs facing north waterlogged false shape inner_left half bottom 6575 prismarine_stairs facing north waterlogged true shape inner_right half bottom 6576 prismarine_stairs facing north waterlogged false shape inner_right half bottom 6577 prismarine_stairs facing north waterlogged true shape outer_left half bottom 6578 prismarine_stairs facing north waterlogged false shape outer_left half bottom 6579 prismarine_stairs facing north waterlogged true shape outer_right half bottom 6580 prismarine_stairs facing north waterlogged false shape outer_right half bottom 6581 prismarine_stairs facing south waterlogged true shape straight half top 6582 prismarine_stairs facing south waterlogged false shape straight half top 6583 prismarine_stairs facing south waterlogged true shape inner_left half top 6584 prismarine_stairs facing south waterlogged false shape inner_left half top 6585 prismarine_stairs facing south waterlogged true shape inner_right half top 6586 prismarine_stairs facing south waterlogged false shape inner_right half top 6587 prismarine_stairs facing south waterlogged true shape outer_left half top 6588 prismarine_stairs facing south waterlogged false shape outer_left half top 6589 prismarine_stairs facing south waterlogged true shape outer_right half top 6590 prismarine_stairs facing south waterlogged false shape outer_right half top 6591 prismarine_stairs facing south waterlogged true shape straight half bottom 6592 prismarine_stairs facing south waterlogged false shape straight half bottom 6593 prismarine_stairs facing south waterlogged true shape inner_left half bottom 6594 prismarine_stairs facing south waterlogged false shape inner_left half bottom 6595 prismarine_stairs facing south waterlogged true shape inner_right half bottom 6596 prismarine_stairs facing south waterlogged false shape inner_right half bottom 6597 prismarine_stairs facing south waterlogged true shape outer_left half bottom 6598 prismarine_stairs facing south waterlogged false shape outer_left half bottom 6599 prismarine_stairs facing south waterlogged true shape outer_right half bottom 6600 prismarine_stairs facing south waterlogged false shape outer_right half bottom 6601 prismarine_stairs facing west waterlogged true shape straight half top 6602 prismarine_stairs facing west waterlogged false shape straight half top 6603 prismarine_stairs facing west waterlogged true shape inner_left half top 6604 prismarine_stairs facing west waterlogged false shape inner_left half top 6605 prismarine_stairs facing west waterlogged true shape inner_right half top 6606 prismarine_stairs facing west waterlogged false shape inner_right half top 6607 prismarine_stairs facing west waterlogged true shape outer_left half top 6608 prismarine_stairs facing west waterlogged false shape outer_left half top 6609 prismarine_stairs facing west waterlogged true shape outer_right half top 6610 prismarine_stairs facing west waterlogged false shape outer_right half top 6611 prismarine_stairs facing west waterlogged true shape straight half bottom 6612 prismarine_stairs facing west waterlogged false shape straight half bottom 6613 prismarine_stairs facing west waterlogged true shape inner_left half bottom 6614 prismarine_stairs facing west waterlogged false shape inner_left half bottom 6615 prismarine_stairs facing west waterlogged true shape inner_right half bottom 6616 prismarine_stairs facing west waterlogged false shape inner_right half bottom 6617 prismarine_stairs facing west waterlogged true shape outer_left half bottom 6618 prismarine_stairs facing west waterlogged false shape outer_left half bottom 6619 prismarine_stairs facing west waterlogged true shape outer_right half bottom 6620 prismarine_stairs facing west waterlogged false shape outer_right half bottom 6621 prismarine_stairs facing east waterlogged true shape straight half top 6622 prismarine_stairs facing east waterlogged false shape straight half top 6623 prismarine_stairs facing east waterlogged true shape inner_left half top 6624 prismarine_stairs facing east waterlogged false shape inner_left half top 6625 prismarine_stairs facing east waterlogged true shape inner_right half top 6626 prismarine_stairs facing east waterlogged false shape inner_right half top 6627 prismarine_stairs facing east waterlogged true shape outer_left half top 6628 prismarine_stairs facing east waterlogged false shape outer_left half top 6629 prismarine_stairs facing east waterlogged true shape outer_right half top 6630 prismarine_stairs facing east waterlogged false shape outer_right half top 6631 prismarine_stairs facing east waterlogged true shape straight half bottom 6632 prismarine_stairs facing east waterlogged false shape straight half bottom 6633 prismarine_stairs facing east waterlogged true shape inner_left half bottom 6634 prismarine_stairs facing east waterlogged false shape inner_left half bottom 6635 prismarine_stairs facing east waterlogged true shape inner_right half bottom 6636 prismarine_stairs facing east waterlogged false shape inner_right half bottom 6637 prismarine_stairs facing east waterlogged true shape outer_left half bottom 6638 prismarine_stairs facing east waterlogged false shape outer_left half bottom 6639 prismarine_stairs facing east waterlogged true shape outer_right half bottom 6640 prismarine_stairs facing east waterlogged false shape outer_right half bottom 6641 prismarine_brick_stairs facing north waterlogged true shape straight half top 6642 prismarine_brick_stairs facing north waterlogged false shape straight half top 6643 prismarine_brick_stairs facing north waterlogged true shape inner_left half top 6644 prismarine_brick_stairs facing north waterlogged false shape inner_left half top 6645 prismarine_brick_stairs facing north waterlogged true shape inner_right half top 6646 prismarine_brick_stairs facing north waterlogged false shape inner_right half top 6647 prismarine_brick_stairs facing north waterlogged true shape outer_left half top 6648 prismarine_brick_stairs facing north waterlogged false shape outer_left half top 6649 prismarine_brick_stairs facing north waterlogged true shape outer_right half top 6650 prismarine_brick_stairs facing north waterlogged false shape outer_right half top 6651 prismarine_brick_stairs facing north waterlogged true shape straight half bottom 6652 prismarine_brick_stairs facing north waterlogged false shape straight half bottom 6653 prismarine_brick_stairs facing north waterlogged true shape inner_left half bottom 6654 prismarine_brick_stairs facing north waterlogged false shape inner_left half bottom 6655 prismarine_brick_stairs facing north waterlogged true shape inner_right half bottom 6656 prismarine_brick_stairs facing north waterlogged false shape inner_right half bottom 6657 prismarine_brick_stairs facing north waterlogged true shape outer_left half bottom 6658 prismarine_brick_stairs facing north waterlogged false shape outer_left half bottom 6659 prismarine_brick_stairs facing north waterlogged true shape outer_right half bottom 6660 prismarine_brick_stairs facing north waterlogged false shape outer_right half bottom 6661 prismarine_brick_stairs facing south waterlogged true shape straight half top 6662 prismarine_brick_stairs facing south waterlogged false shape straight half top 6663 prismarine_brick_stairs facing south waterlogged true shape inner_left half top 6664 prismarine_brick_stairs facing south waterlogged false shape inner_left half top 6665 prismarine_brick_stairs facing south waterlogged true shape inner_right half top 6666 prismarine_brick_stairs facing south waterlogged false shape inner_right half top 6667 prismarine_brick_stairs facing south waterlogged true shape outer_left half top 6668 prismarine_brick_stairs facing south waterlogged false shape outer_left half top 6669 prismarine_brick_stairs facing south waterlogged true shape outer_right half top 6670 prismarine_brick_stairs facing south waterlogged false shape outer_right half top 6671 prismarine_brick_stairs facing south waterlogged true shape straight half bottom 6672 prismarine_brick_stairs facing south waterlogged false shape straight half bottom 6673 prismarine_brick_stairs facing south waterlogged true shape inner_left half bottom 6674 prismarine_brick_stairs facing south waterlogged false shape inner_left half bottom 6675 prismarine_brick_stairs facing south waterlogged true shape inner_right half bottom 6676 prismarine_brick_stairs facing south waterlogged false shape inner_right half bottom 6677 prismarine_brick_stairs facing south waterlogged true shape outer_left half bottom 6678 prismarine_brick_stairs facing south waterlogged false shape outer_left half bottom 6679 prismarine_brick_stairs facing south waterlogged true shape outer_right half bottom 6680 prismarine_brick_stairs facing south waterlogged false shape outer_right half bottom 6681 prismarine_brick_stairs facing west waterlogged true shape straight half top 6682 prismarine_brick_stairs facing west waterlogged false shape straight half top 6683 prismarine_brick_stairs facing west waterlogged true shape inner_left half top 6684 prismarine_brick_stairs facing west waterlogged false shape inner_left half top 6685 prismarine_brick_stairs facing west waterlogged true shape inner_right half top 6686 prismarine_brick_stairs facing west waterlogged false shape inner_right half top 6687 prismarine_brick_stairs facing west waterlogged true shape outer_left half top 6688 prismarine_brick_stairs facing west waterlogged false shape outer_left half top 6689 prismarine_brick_stairs facing west waterlogged true shape outer_right half top 6690 prismarine_brick_stairs facing west waterlogged false shape outer_right half top 6691 prismarine_brick_stairs facing west waterlogged true shape straight half bottom 6692 prismarine_brick_stairs facing west waterlogged false shape straight half bottom 6693 prismarine_brick_stairs facing west waterlogged true shape inner_left half bottom 6694 prismarine_brick_stairs facing west waterlogged false shape inner_left half bottom 6695 prismarine_brick_stairs facing west waterlogged true shape inner_right half bottom 6696 prismarine_brick_stairs facing west waterlogged false shape inner_right half bottom 6697 prismarine_brick_stairs facing west waterlogged true shape outer_left half bottom 6698 prismarine_brick_stairs facing west waterlogged false shape outer_left half bottom 6699 prismarine_brick_stairs facing west waterlogged true shape outer_right half bottom 6700 prismarine_brick_stairs facing west waterlogged false shape outer_right half bottom 6701 prismarine_brick_stairs facing east waterlogged true shape straight half top 6702 prismarine_brick_stairs facing east waterlogged false shape straight half top 6703 prismarine_brick_stairs facing east waterlogged true shape inner_left half top 6704 prismarine_brick_stairs facing east waterlogged false shape inner_left half top 6705 prismarine_brick_stairs facing east waterlogged true shape inner_right half top 6706 prismarine_brick_stairs facing east waterlogged false shape inner_right half top 6707 prismarine_brick_stairs facing east waterlogged true shape outer_left half top 6708 prismarine_brick_stairs facing east waterlogged false shape outer_left half top 6709 prismarine_brick_stairs facing east waterlogged true shape outer_right half top 6710 prismarine_brick_stairs facing east waterlogged false shape outer_right half top 6711 prismarine_brick_stairs facing east waterlogged true shape straight half bottom 6712 prismarine_brick_stairs facing east waterlogged false shape straight half bottom 6713 prismarine_brick_stairs facing east waterlogged true shape inner_left half bottom 6714 prismarine_brick_stairs facing east waterlogged false shape inner_left half bottom 6715 prismarine_brick_stairs facing east waterlogged true shape inner_right half bottom 6716 prismarine_brick_stairs facing east waterlogged false shape inner_right half bottom 6717 prismarine_brick_stairs facing east waterlogged true shape outer_left half bottom 6718 prismarine_brick_stairs facing east waterlogged false shape outer_left half bottom 6719 prismarine_brick_stairs facing east waterlogged true shape outer_right half bottom 6720 prismarine_brick_stairs facing east waterlogged false shape outer_right half bottom 6721 dark_prismarine_stairs facing north waterlogged true shape straight half top 6722 dark_prismarine_stairs facing north waterlogged false shape straight half top 6723 dark_prismarine_stairs facing north waterlogged true shape inner_left half top 6724 dark_prismarine_stairs facing north waterlogged false shape inner_left half top 6725 dark_prismarine_stairs facing north waterlogged true shape inner_right half top 6726 dark_prismarine_stairs facing north waterlogged false shape inner_right half top 6727 dark_prismarine_stairs facing north waterlogged true shape outer_left half top 6728 dark_prismarine_stairs facing north waterlogged false shape outer_left half top 6729 dark_prismarine_stairs facing north waterlogged true shape outer_right half top 6730 dark_prismarine_stairs facing north waterlogged false shape outer_right half top 6731 dark_prismarine_stairs facing north waterlogged true shape straight half bottom 6732 dark_prismarine_stairs facing north waterlogged false shape straight half bottom 6733 dark_prismarine_stairs facing north waterlogged true shape inner_left half bottom 6734 dark_prismarine_stairs facing north waterlogged false shape inner_left half bottom 6735 dark_prismarine_stairs facing north waterlogged true shape inner_right half bottom 6736 dark_prismarine_stairs facing north waterlogged false shape inner_right half bottom 6737 dark_prismarine_stairs facing north waterlogged true shape outer_left half bottom 6738 dark_prismarine_stairs facing north waterlogged false shape outer_left half bottom 6739 dark_prismarine_stairs facing north waterlogged true shape outer_right half bottom 6740 dark_prismarine_stairs facing north waterlogged false shape outer_right half bottom 6741 dark_prismarine_stairs facing south waterlogged true shape straight half top 6742 dark_prismarine_stairs facing south waterlogged false shape straight half top 6743 dark_prismarine_stairs facing south waterlogged true shape inner_left half top 6744 dark_prismarine_stairs facing south waterlogged false shape inner_left half top 6745 dark_prismarine_stairs facing south waterlogged true shape inner_right half top 6746 dark_prismarine_stairs facing south waterlogged false shape inner_right half top 6747 dark_prismarine_stairs facing south waterlogged true shape outer_left half top 6748 dark_prismarine_stairs facing south waterlogged false shape outer_left half top 6749 dark_prismarine_stairs facing south waterlogged true shape outer_right half top 6750 dark_prismarine_stairs facing south waterlogged false shape outer_right half top 6751 dark_prismarine_stairs facing south waterlogged true shape straight half bottom 6752 dark_prismarine_stairs facing south waterlogged false shape straight half bottom 6753 dark_prismarine_stairs facing south waterlogged true shape inner_left half bottom 6754 dark_prismarine_stairs facing south waterlogged false shape inner_left half bottom 6755 dark_prismarine_stairs facing south waterlogged true shape inner_right half bottom 6756 dark_prismarine_stairs facing south waterlogged false shape inner_right half bottom 6757 dark_prismarine_stairs facing south waterlogged true shape outer_left half bottom 6758 dark_prismarine_stairs facing south waterlogged false shape outer_left half bottom 6759 dark_prismarine_stairs facing south waterlogged true shape outer_right half bottom 6760 dark_prismarine_stairs facing south waterlogged false shape outer_right half bottom 6761 dark_prismarine_stairs facing west waterlogged true shape straight half top 6762 dark_prismarine_stairs facing west waterlogged false shape straight half top 6763 dark_prismarine_stairs facing west waterlogged true shape inner_left half top 6764 dark_prismarine_stairs facing west waterlogged false shape inner_left half top 6765 dark_prismarine_stairs facing west waterlogged true shape inner_right half top 6766 dark_prismarine_stairs facing west waterlogged false shape inner_right half top 6767 dark_prismarine_stairs facing west waterlogged true shape outer_left half top 6768 dark_prismarine_stairs facing west waterlogged false shape outer_left half top 6769 dark_prismarine_stairs facing west waterlogged true shape outer_right half top 6770 dark_prismarine_stairs facing west waterlogged false shape outer_right half top 6771 dark_prismarine_stairs facing west waterlogged true shape straight half bottom 6772 dark_prismarine_stairs facing west waterlogged false shape straight half bottom 6773 dark_prismarine_stairs facing west waterlogged true shape inner_left half bottom 6774 dark_prismarine_stairs facing west waterlogged false shape inner_left half bottom 6775 dark_prismarine_stairs facing west waterlogged true shape inner_right half bottom 6776 dark_prismarine_stairs facing west waterlogged false shape inner_right half bottom 6777 dark_prismarine_stairs facing west waterlogged true shape outer_left half bottom 6778 dark_prismarine_stairs facing west waterlogged false shape outer_left half bottom 6779 dark_prismarine_stairs facing west waterlogged true shape outer_right half bottom 6780 dark_prismarine_stairs facing west waterlogged false shape outer_right half bottom 6781 dark_prismarine_stairs facing east waterlogged true shape straight half top 6782 dark_prismarine_stairs facing east waterlogged false shape straight half top 6783 dark_prismarine_stairs facing east waterlogged true shape inner_left half top 6784 dark_prismarine_stairs facing east waterlogged false shape inner_left half top 6785 dark_prismarine_stairs facing east waterlogged true shape inner_right half top 6786 dark_prismarine_stairs facing east waterlogged false shape inner_right half top 6787 dark_prismarine_stairs facing east waterlogged true shape outer_left half top 6788 dark_prismarine_stairs facing east waterlogged false shape outer_left half top 6789 dark_prismarine_stairs facing east waterlogged true shape outer_right half top 6790 dark_prismarine_stairs facing east waterlogged false shape outer_right half top 6791 dark_prismarine_stairs facing east waterlogged true shape straight half bottom 6792 dark_prismarine_stairs facing east waterlogged false shape straight half bottom 6793 dark_prismarine_stairs facing east waterlogged true shape inner_left half bottom 6794 dark_prismarine_stairs facing east waterlogged false shape inner_left half bottom 6795 dark_prismarine_stairs facing east waterlogged true shape inner_right half bottom 6796 dark_prismarine_stairs facing east waterlogged false shape inner_right half bottom 6797 dark_prismarine_stairs facing east waterlogged true shape outer_left half bottom 6798 dark_prismarine_stairs facing east waterlogged false shape outer_left half bottom 6799 dark_prismarine_stairs facing east waterlogged true shape outer_right half bottom 6800 dark_prismarine_stairs facing east waterlogged false shape outer_right half bottom 6801 prismarine_slab type top waterlogged true 6802 prismarine_slab type top waterlogged false 6803 prismarine_slab type bottom waterlogged true 6804 prismarine_slab type bottom waterlogged false 6805 prismarine_slab type double waterlogged true 6806 prismarine_slab type double waterlogged false 6807 prismarine_brick_slab type top waterlogged true 6808 prismarine_brick_slab type top waterlogged false 6809 prismarine_brick_slab type bottom waterlogged true 6810 prismarine_brick_slab type bottom waterlogged false 6811 prismarine_brick_slab type double waterlogged true 6812 prismarine_brick_slab type double waterlogged false 6813 dark_prismarine_slab type top waterlogged true 6814 dark_prismarine_slab type top waterlogged false 6815 dark_prismarine_slab type bottom waterlogged true 6816 dark_prismarine_slab type bottom waterlogged false 6817 dark_prismarine_slab type double waterlogged true 6818 dark_prismarine_slab type double waterlogged false 6819 sea_lantern 6820 hay_block axis x 6821 hay_block axis y 6822 hay_block axis z 6823 white_carpet 6824 orange_carpet 6825 magenta_carpet 6826 light_blue_carpet 6827 yellow_carpet 6828 lime_carpet 6829 pink_carpet 6830 gray_carpet 6831 light_gray_carpet 6832 cyan_carpet 6833 purple_carpet 6834 blue_carpet 6835 brown_carpet 6836 green_carpet 6837 red_carpet 6838 black_carpet 6839 terracotta 6840 coal_block 6841 packed_ice 6842 sunflower half upper 6843 sunflower half lower 6844 lilac half upper 6845 lilac half lower 6846 rose_bush half upper 6847 rose_bush half lower 6848 peony half upper 6849 peony half lower 6850 tall_grass half upper 6851 tall_grass half lower 6852 large_fern half upper 6853 large_fern half lower 6854 white_banner rotation 0 6855 white_banner rotation 1 6856 white_banner rotation 2 6857 white_banner rotation 3 6858 white_banner rotation 4 6859 white_banner rotation 5 6860 white_banner rotation 6 6861 white_banner rotation 7 6862 white_banner rotation 8 6863 white_banner rotation 9 6864 white_banner rotation 10 6865 white_banner rotation 11 6866 white_banner rotation 12 6867 white_banner rotation 13 6868 white_banner rotation 14 6869 white_banner rotation 15 6870 orange_banner rotation 0 6871 orange_banner rotation 1 6872 orange_banner rotation 2 6873 orange_banner rotation 3 6874 orange_banner rotation 4 6875 orange_banner rotation 5 6876 orange_banner rotation 6 6877 orange_banner rotation 7 6878 orange_banner rotation 8 6879 orange_banner rotation 9 6880 orange_banner rotation 10 6881 orange_banner rotation 11 6882 orange_banner rotation 12 6883 orange_banner rotation 13 6884 orange_banner rotation 14 6885 orange_banner rotation 15 6886 magenta_banner rotation 0 6887 magenta_banner rotation 1 6888 magenta_banner rotation 2 6889 magenta_banner rotation 3 6890 magenta_banner rotation 4 6891 magenta_banner rotation 5 6892 magenta_banner rotation 6 6893 magenta_banner rotation 7 6894 magenta_banner rotation 8 6895 magenta_banner rotation 9 6896 magenta_banner rotation 10 6897 magenta_banner rotation 11 6898 magenta_banner rotation 12 6899 magenta_banner rotation 13 6900 magenta_banner rotation 14 6901 magenta_banner rotation 15 6902 light_blue_banner rotation 0 6903 light_blue_banner rotation 1 6904 light_blue_banner rotation 2 6905 light_blue_banner rotation 3 6906 light_blue_banner rotation 4 6907 light_blue_banner rotation 5 6908 light_blue_banner rotation 6 6909 light_blue_banner rotation 7 6910 light_blue_banner rotation 8 6911 light_blue_banner rotation 9 6912 light_blue_banner rotation 10 6913 light_blue_banner rotation 11 6914 light_blue_banner rotation 12 6915 light_blue_banner rotation 13 6916 light_blue_banner rotation 14 6917 light_blue_banner rotation 15 6918 yellow_banner rotation 0 6919 yellow_banner rotation 1 6920 yellow_banner rotation 2 6921 yellow_banner rotation 3 6922 yellow_banner rotation 4 6923 yellow_banner rotation 5 6924 yellow_banner rotation 6 6925 yellow_banner rotation 7 6926 yellow_banner rotation 8 6927 yellow_banner rotation 9 6928 yellow_banner rotation 10 6929 yellow_banner rotation 11 6930 yellow_banner rotation 12 6931 yellow_banner rotation 13 6932 yellow_banner rotation 14 6933 yellow_banner rotation 15 6934 lime_banner rotation 0 6935 lime_banner rotation 1 6936 lime_banner rotation 2 6937 lime_banner rotation 3 6938 lime_banner rotation 4 6939 lime_banner rotation 5 6940 lime_banner rotation 6 6941 lime_banner rotation 7 6942 lime_banner rotation 8 6943 lime_banner rotation 9 6944 lime_banner rotation 10 6945 lime_banner rotation 11 6946 lime_banner rotation 12 6947 lime_banner rotation 13 6948 lime_banner rotation 14 6949 lime_banner rotation 15 6950 pink_banner rotation 0 6951 pink_banner rotation 1 6952 pink_banner rotation 2 6953 pink_banner rotation 3 6954 pink_banner rotation 4 6955 pink_banner rotation 5 6956 pink_banner rotation 6 6957 pink_banner rotation 7 6958 pink_banner rotation 8 6959 pink_banner rotation 9 6960 pink_banner rotation 10 6961 pink_banner rotation 11 6962 pink_banner rotation 12 6963 pink_banner rotation 13 6964 pink_banner rotation 14 6965 pink_banner rotation 15 6966 gray_banner rotation 0 6967 gray_banner rotation 1 6968 gray_banner rotation 2 6969 gray_banner rotation 3 6970 gray_banner rotation 4 6971 gray_banner rotation 5 6972 gray_banner rotation 6 6973 gray_banner rotation 7 6974 gray_banner rotation 8 6975 gray_banner rotation 9 6976 gray_banner rotation 10 6977 gray_banner rotation 11 6978 gray_banner rotation 12 6979 gray_banner rotation 13 6980 gray_banner rotation 14 6981 gray_banner rotation 15 6982 light_gray_banner rotation 0 6983 light_gray_banner rotation 1 6984 light_gray_banner rotation 2 6985 light_gray_banner rotation 3 6986 light_gray_banner rotation 4 6987 light_gray_banner rotation 5 6988 light_gray_banner rotation 6 6989 light_gray_banner rotation 7 6990 light_gray_banner rotation 8 6991 light_gray_banner rotation 9 6992 light_gray_banner rotation 10 6993 light_gray_banner rotation 11 6994 light_gray_banner rotation 12 6995 light_gray_banner rotation 13 6996 light_gray_banner rotation 14 6997 light_gray_banner rotation 15 6998 cyan_banner rotation 0 6999 cyan_banner rotation 1 7000 cyan_banner rotation 2 7001 cyan_banner rotation 3 7002 cyan_banner rotation 4 7003 cyan_banner rotation 5 7004 cyan_banner rotation 6 7005 cyan_banner rotation 7 7006 cyan_banner rotation 8 7007 cyan_banner rotation 9 7008 cyan_banner rotation 10 7009 cyan_banner rotation 11 7010 cyan_banner rotation 12 7011 cyan_banner rotation 13 7012 cyan_banner rotation 14 7013 cyan_banner rotation 15 7014 purple_banner rotation 0 7015 purple_banner rotation 1 7016 purple_banner rotation 2 7017 purple_banner rotation 3 7018 purple_banner rotation 4 7019 purple_banner rotation 5 7020 purple_banner rotation 6 7021 purple_banner rotation 7 7022 purple_banner rotation 8 7023 purple_banner rotation 9 7024 purple_banner rotation 10 7025 purple_banner rotation 11 7026 purple_banner rotation 12 7027 purple_banner rotation 13 7028 purple_banner rotation 14 7029 purple_banner rotation 15 7030 blue_banner rotation 0 7031 blue_banner rotation 1 7032 blue_banner rotation 2 7033 blue_banner rotation 3 7034 blue_banner rotation 4 7035 blue_banner rotation 5 7036 blue_banner rotation 6 7037 blue_banner rotation 7 7038 blue_banner rotation 8 7039 blue_banner rotation 9 7040 blue_banner rotation 10 7041 blue_banner rotation 11 7042 blue_banner rotation 12 7043 blue_banner rotation 13 7044 blue_banner rotation 14 7045 blue_banner rotation 15 7046 brown_banner rotation 0 7047 brown_banner rotation 1 7048 brown_banner rotation 2 7049 brown_banner rotation 3 7050 brown_banner rotation 4 7051 brown_banner rotation 5 7052 brown_banner rotation 6 7053 brown_banner rotation 7 7054 brown_banner rotation 8 7055 brown_banner rotation 9 7056 brown_banner rotation 10 7057 brown_banner rotation 11 7058 brown_banner rotation 12 7059 brown_banner rotation 13 7060 brown_banner rotation 14 7061 brown_banner rotation 15 7062 green_banner rotation 0 7063 green_banner rotation 1 7064 green_banner rotation 2 7065 green_banner rotation 3 7066 green_banner rotation 4 7067 green_banner rotation 5 7068 green_banner rotation 6 7069 green_banner rotation 7 7070 green_banner rotation 8 7071 green_banner rotation 9 7072 green_banner rotation 10 7073 green_banner rotation 11 7074 green_banner rotation 12 7075 green_banner rotation 13 7076 green_banner rotation 14 7077 green_banner rotation 15 7078 red_banner rotation 0 7079 red_banner rotation 1 7080 red_banner rotation 2 7081 red_banner rotation 3 7082 red_banner rotation 4 7083 red_banner rotation 5 7084 red_banner rotation 6 7085 red_banner rotation 7 7086 red_banner rotation 8 7087 red_banner rotation 9 7088 red_banner rotation 10 7089 red_banner rotation 11 7090 red_banner rotation 12 7091 red_banner rotation 13 7092 red_banner rotation 14 7093 red_banner rotation 15 7094 black_banner rotation 0 7095 black_banner rotation 1 7096 black_banner rotation 2 7097 black_banner rotation 3 7098 black_banner rotation 4 7099 black_banner rotation 5 7100 black_banner rotation 6 7101 black_banner rotation 7 7102 black_banner rotation 8 7103 black_banner rotation 9 7104 black_banner rotation 10 7105 black_banner rotation 11 7106 black_banner rotation 12 7107 black_banner rotation 13 7108 black_banner rotation 14 7109 black_banner rotation 15 7110 white_wall_banner facing north 7111 white_wall_banner facing south 7112 white_wall_banner facing west 7113 white_wall_banner facing east 7114 orange_wall_banner facing north 7115 orange_wall_banner facing south 7116 orange_wall_banner facing west 7117 orange_wall_banner facing east 7118 magenta_wall_banner facing north 7119 magenta_wall_banner facing south 7120 magenta_wall_banner facing west 7121 magenta_wall_banner facing east 7122 light_blue_wall_banner facing north 7123 light_blue_wall_banner facing south 7124 light_blue_wall_banner facing west 7125 light_blue_wall_banner facing east 7126 yellow_wall_banner facing north 7127 yellow_wall_banner facing south 7128 yellow_wall_banner facing west 7129 yellow_wall_banner facing east 7130 lime_wall_banner facing north 7131 lime_wall_banner facing south 7132 lime_wall_banner facing west 7133 lime_wall_banner facing east 7134 pink_wall_banner facing north 7135 pink_wall_banner facing south 7136 pink_wall_banner facing west 7137 pink_wall_banner facing east 7138 gray_wall_banner facing north 7139 gray_wall_banner facing south 7140 gray_wall_banner facing west 7141 gray_wall_banner facing east 7142 light_gray_wall_banner facing north 7143 light_gray_wall_banner facing south 7144 light_gray_wall_banner facing west 7145 light_gray_wall_banner facing east 7146 cyan_wall_banner facing north 7147 cyan_wall_banner facing south 7148 cyan_wall_banner facing west 7149 cyan_wall_banner facing east 7150 purple_wall_banner facing north 7151 purple_wall_banner facing south 7152 purple_wall_banner facing west 7153 purple_wall_banner facing east 7154 blue_wall_banner facing north 7155 blue_wall_banner facing south 7156 blue_wall_banner facing west 7157 blue_wall_banner facing east 7158 brown_wall_banner facing north 7159 brown_wall_banner facing south 7160 brown_wall_banner facing west 7161 brown_wall_banner facing east 7162 green_wall_banner facing north 7163 green_wall_banner facing south 7164 green_wall_banner facing west 7165 green_wall_banner facing east 7166 red_wall_banner facing north 7167 red_wall_banner facing south 7168 red_wall_banner facing west 7169 red_wall_banner facing east 7170 black_wall_banner facing north 7171 black_wall_banner facing south 7172 black_wall_banner facing west 7173 black_wall_banner facing east 7174 red_sandstone 7175 chiseled_red_sandstone 7176 cut_red_sandstone 7177 red_sandstone_stairs facing north waterlogged true shape straight half top 7178 red_sandstone_stairs facing north waterlogged false shape straight half top 7179 red_sandstone_stairs facing north waterlogged true shape inner_left half top 7180 red_sandstone_stairs facing north waterlogged false shape inner_left half top 7181 red_sandstone_stairs facing north waterlogged true shape inner_right half top 7182 red_sandstone_stairs facing north waterlogged false shape inner_right half top 7183 red_sandstone_stairs facing north waterlogged true shape outer_left half top 7184 red_sandstone_stairs facing north waterlogged false shape outer_left half top 7185 red_sandstone_stairs facing north waterlogged true shape outer_right half top 7186 red_sandstone_stairs facing north waterlogged false shape outer_right half top 7187 red_sandstone_stairs facing north waterlogged true shape straight half bottom 7188 red_sandstone_stairs facing north waterlogged false shape straight half bottom 7189 red_sandstone_stairs facing north waterlogged true shape inner_left half bottom 7190 red_sandstone_stairs facing north waterlogged false shape inner_left half bottom 7191 red_sandstone_stairs facing north waterlogged true shape inner_right half bottom 7192 red_sandstone_stairs facing north waterlogged false shape inner_right half bottom 7193 red_sandstone_stairs facing north waterlogged true shape outer_left half bottom 7194 red_sandstone_stairs facing north waterlogged false shape outer_left half bottom 7195 red_sandstone_stairs facing north waterlogged true shape outer_right half bottom 7196 red_sandstone_stairs facing north waterlogged false shape outer_right half bottom 7197 red_sandstone_stairs facing south waterlogged true shape straight half top 7198 red_sandstone_stairs facing south waterlogged false shape straight half top 7199 red_sandstone_stairs facing south waterlogged true shape inner_left half top 7200 red_sandstone_stairs facing south waterlogged false shape inner_left half top 7201 red_sandstone_stairs facing south waterlogged true shape inner_right half top 7202 red_sandstone_stairs facing south waterlogged false shape inner_right half top 7203 red_sandstone_stairs facing south waterlogged true shape outer_left half top 7204 red_sandstone_stairs facing south waterlogged false shape outer_left half top 7205 red_sandstone_stairs facing south waterlogged true shape outer_right half top 7206 red_sandstone_stairs facing south waterlogged false shape outer_right half top 7207 red_sandstone_stairs facing south waterlogged true shape straight half bottom 7208 red_sandstone_stairs facing south waterlogged false shape straight half bottom 7209 red_sandstone_stairs facing south waterlogged true shape inner_left half bottom 7210 red_sandstone_stairs facing south waterlogged false shape inner_left half bottom 7211 red_sandstone_stairs facing south waterlogged true shape inner_right half bottom 7212 red_sandstone_stairs facing south waterlogged false shape inner_right half bottom 7213 red_sandstone_stairs facing south waterlogged true shape outer_left half bottom 7214 red_sandstone_stairs facing south waterlogged false shape outer_left half bottom 7215 red_sandstone_stairs facing south waterlogged true shape outer_right half bottom 7216 red_sandstone_stairs facing south waterlogged false shape outer_right half bottom 7217 red_sandstone_stairs facing west waterlogged true shape straight half top 7218 red_sandstone_stairs facing west waterlogged false shape straight half top 7219 red_sandstone_stairs facing west waterlogged true shape inner_left half top 7220 red_sandstone_stairs facing west waterlogged false shape inner_left half top 7221 red_sandstone_stairs facing west waterlogged true shape inner_right half top 7222 red_sandstone_stairs facing west waterlogged false shape inner_right half top 7223 red_sandstone_stairs facing west waterlogged true shape outer_left half top 7224 red_sandstone_stairs facing west waterlogged false shape outer_left half top 7225 red_sandstone_stairs facing west waterlogged true shape outer_right half top 7226 red_sandstone_stairs facing west waterlogged false shape outer_right half top 7227 red_sandstone_stairs facing west waterlogged true shape straight half bottom 7228 red_sandstone_stairs facing west waterlogged false shape straight half bottom 7229 red_sandstone_stairs facing west waterlogged true shape inner_left half bottom 7230 red_sandstone_stairs facing west waterlogged false shape inner_left half bottom 7231 red_sandstone_stairs facing west waterlogged true shape inner_right half bottom 7232 red_sandstone_stairs facing west waterlogged false shape inner_right half bottom 7233 red_sandstone_stairs facing west waterlogged true shape outer_left half bottom 7234 red_sandstone_stairs facing west waterlogged false shape outer_left half bottom 7235 red_sandstone_stairs facing west waterlogged true shape outer_right half bottom 7236 red_sandstone_stairs facing west waterlogged false shape outer_right half bottom 7237 red_sandstone_stairs facing east waterlogged true shape straight half top 7238 red_sandstone_stairs facing east waterlogged false shape straight half top 7239 red_sandstone_stairs facing east waterlogged true shape inner_left half top 7240 red_sandstone_stairs facing east waterlogged false shape inner_left half top 7241 red_sandstone_stairs facing east waterlogged true shape inner_right half top 7242 red_sandstone_stairs facing east waterlogged false shape inner_right half top 7243 red_sandstone_stairs facing east waterlogged true shape outer_left half top 7244 red_sandstone_stairs facing east waterlogged false shape outer_left half top 7245 red_sandstone_stairs facing east waterlogged true shape outer_right half top 7246 red_sandstone_stairs facing east waterlogged false shape outer_right half top 7247 red_sandstone_stairs facing east waterlogged true shape straight half bottom 7248 red_sandstone_stairs facing east waterlogged false shape straight half bottom 7249 red_sandstone_stairs facing east waterlogged true shape inner_left half bottom 7250 red_sandstone_stairs facing east waterlogged false shape inner_left half bottom 7251 red_sandstone_stairs facing east waterlogged true shape inner_right half bottom 7252 red_sandstone_stairs facing east waterlogged false shape inner_right half bottom 7253 red_sandstone_stairs facing east waterlogged true shape outer_left half bottom 7254 red_sandstone_stairs facing east waterlogged false shape outer_left half bottom 7255 red_sandstone_stairs facing east waterlogged true shape outer_right half bottom 7256 red_sandstone_stairs facing east waterlogged false shape outer_right half bottom 7257 oak_slab type top waterlogged true 7258 oak_slab type top waterlogged false 7259 oak_slab type bottom waterlogged true 7260 oak_slab type bottom waterlogged false 7261 oak_slab type double waterlogged true 7262 oak_slab type double waterlogged false 7263 spruce_slab type top waterlogged true 7264 spruce_slab type top waterlogged false 7265 spruce_slab type bottom waterlogged true 7266 spruce_slab type bottom waterlogged false 7267 spruce_slab type double waterlogged true 7268 spruce_slab type double waterlogged false 7269 birch_slab type top waterlogged true 7270 birch_slab type top waterlogged false 7271 birch_slab type bottom waterlogged true 7272 birch_slab type bottom waterlogged false 7273 birch_slab type double waterlogged true 7274 birch_slab type double waterlogged false 7275 jungle_slab type top waterlogged true 7276 jungle_slab type top waterlogged false 7277 jungle_slab type bottom waterlogged true 7278 jungle_slab type bottom waterlogged false 7279 jungle_slab type double waterlogged true 7280 jungle_slab type double waterlogged false 7281 acacia_slab type top waterlogged true 7282 acacia_slab type top waterlogged false 7283 acacia_slab type bottom waterlogged true 7284 acacia_slab type bottom waterlogged false 7285 acacia_slab type double waterlogged true 7286 acacia_slab type double waterlogged false 7287 dark_oak_slab type top waterlogged true 7288 dark_oak_slab type top waterlogged false 7289 dark_oak_slab type bottom waterlogged true 7290 dark_oak_slab type bottom waterlogged false 7291 dark_oak_slab type double waterlogged true 7292 dark_oak_slab type double waterlogged false 7293 stone_slab type top waterlogged true 7294 stone_slab type top waterlogged false 7295 stone_slab type bottom waterlogged true 7296 stone_slab type bottom waterlogged false 7297 stone_slab type double waterlogged true 7298 stone_slab type double waterlogged false 7299 sandstone_slab type top waterlogged true 7300 sandstone_slab type top waterlogged false 7301 sandstone_slab type bottom waterlogged true 7302 sandstone_slab type bottom waterlogged false 7303 sandstone_slab type double waterlogged true 7304 sandstone_slab type double waterlogged false 7305 petrified_oak_slab type top waterlogged true 7306 petrified_oak_slab type top waterlogged false 7307 petrified_oak_slab type bottom waterlogged true 7308 petrified_oak_slab type bottom waterlogged false 7309 petrified_oak_slab type double waterlogged true 7310 petrified_oak_slab type double waterlogged false 7311 cobblestone_slab type top waterlogged true 7312 cobblestone_slab type top waterlogged false 7313 cobblestone_slab type bottom waterlogged true 7314 cobblestone_slab type bottom waterlogged false 7315 cobblestone_slab type double waterlogged true 7316 cobblestone_slab type double waterlogged false 7317 brick_slab type top waterlogged true 7318 brick_slab type top waterlogged false 7319 brick_slab type bottom waterlogged true 7320 brick_slab type bottom waterlogged false 7321 brick_slab type double waterlogged true 7322 brick_slab type double waterlogged false 7323 stone_brick_slab type top waterlogged true 7324 stone_brick_slab type top waterlogged false 7325 stone_brick_slab type bottom waterlogged true 7326 stone_brick_slab type bottom waterlogged false 7327 stone_brick_slab type double waterlogged true 7328 stone_brick_slab type double waterlogged false 7329 nether_brick_slab type top waterlogged true 7330 nether_brick_slab type top waterlogged false 7331 nether_brick_slab type bottom waterlogged true 7332 nether_brick_slab type bottom waterlogged false 7333 nether_brick_slab type double waterlogged true 7334 nether_brick_slab type double waterlogged false 7335 quartz_slab type top waterlogged true 7336 quartz_slab type top waterlogged false 7337 quartz_slab type bottom waterlogged true 7338 quartz_slab type bottom waterlogged false 7339 quartz_slab type double waterlogged true 7340 quartz_slab type double waterlogged false 7341 red_sandstone_slab type top waterlogged true 7342 red_sandstone_slab type top waterlogged false 7343 red_sandstone_slab type bottom waterlogged true 7344 red_sandstone_slab type bottom waterlogged false 7345 red_sandstone_slab type double waterlogged true 7346 red_sandstone_slab type double waterlogged false 7347 purpur_slab type top waterlogged true 7348 purpur_slab type top waterlogged false 7349 purpur_slab type bottom waterlogged true 7350 purpur_slab type bottom waterlogged false 7351 purpur_slab type double waterlogged true 7352 purpur_slab type double waterlogged false 7353 smooth_stone 7354 smooth_sandstone 7355 smooth_quartz 7356 smooth_red_sandstone 7357 spruce_fence_gate facing north powered true open true in_wall true 7358 spruce_fence_gate facing north powered false open true in_wall true 7359 spruce_fence_gate facing north powered true open false in_wall true 7360 spruce_fence_gate facing north powered false open false in_wall true 7361 spruce_fence_gate facing north powered true open true in_wall false 7362 spruce_fence_gate facing north powered false open true in_wall false 7363 spruce_fence_gate facing north powered true open false in_wall false 7364 spruce_fence_gate facing north powered false open false in_wall false 7365 spruce_fence_gate facing south powered true open true in_wall true 7366 spruce_fence_gate facing south powered false open true in_wall true 7367 spruce_fence_gate facing south powered true open false in_wall true 7368 spruce_fence_gate facing south powered false open false in_wall true 7369 spruce_fence_gate facing south powered true open true in_wall false 7370 spruce_fence_gate facing south powered false open true in_wall false 7371 spruce_fence_gate facing south powered true open false in_wall false 7372 spruce_fence_gate facing south powered false open false in_wall false 7373 spruce_fence_gate facing west powered true open true in_wall true 7374 spruce_fence_gate facing west powered false open true in_wall true 7375 spruce_fence_gate facing west powered true open false in_wall true 7376 spruce_fence_gate facing west powered false open false in_wall true 7377 spruce_fence_gate facing west powered true open true in_wall false 7378 spruce_fence_gate facing west powered false open true in_wall false 7379 spruce_fence_gate facing west powered true open false in_wall false 7380 spruce_fence_gate facing west powered false open false in_wall false 7381 spruce_fence_gate facing east powered true open true in_wall true 7382 spruce_fence_gate facing east powered false open true in_wall true 7383 spruce_fence_gate facing east powered true open false in_wall true 7384 spruce_fence_gate facing east powered false open false in_wall true 7385 spruce_fence_gate facing east powered true open true in_wall false 7386 spruce_fence_gate facing east powered false open true in_wall false 7387 spruce_fence_gate facing east powered true open false in_wall false 7388 spruce_fence_gate facing east powered false open false in_wall false 7389 birch_fence_gate facing north powered true open true in_wall true 7390 birch_fence_gate facing north powered false open true in_wall true 7391 birch_fence_gate facing north powered true open false in_wall true 7392 birch_fence_gate facing north powered false open false in_wall true 7393 birch_fence_gate facing north powered true open true in_wall false 7394 birch_fence_gate facing north powered false open true in_wall false 7395 birch_fence_gate facing north powered true open false in_wall false 7396 birch_fence_gate facing north powered false open false in_wall false 7397 birch_fence_gate facing south powered true open true in_wall true 7398 birch_fence_gate facing south powered false open true in_wall true 7399 birch_fence_gate facing south powered true open false in_wall true 7400 birch_fence_gate facing south powered false open false in_wall true 7401 birch_fence_gate facing south powered true open true in_wall false 7402 birch_fence_gate facing south powered false open true in_wall false 7403 birch_fence_gate facing south powered true open false in_wall false 7404 birch_fence_gate facing south powered false open false in_wall false 7405 birch_fence_gate facing west powered true open true in_wall true 7406 birch_fence_gate facing west powered false open true in_wall true 7407 birch_fence_gate facing west powered true open false in_wall true 7408 birch_fence_gate facing west powered false open false in_wall true 7409 birch_fence_gate facing west powered true open true in_wall false 7410 birch_fence_gate facing west powered false open true in_wall false 7411 birch_fence_gate facing west powered true open false in_wall false 7412 birch_fence_gate facing west powered false open false in_wall false 7413 birch_fence_gate facing east powered true open true in_wall true 7414 birch_fence_gate facing east powered false open true in_wall true 7415 birch_fence_gate facing east powered true open false in_wall true 7416 birch_fence_gate facing east powered false open false in_wall true 7417 birch_fence_gate facing east powered true open true in_wall false 7418 birch_fence_gate facing east powered false open true in_wall false 7419 birch_fence_gate facing east powered true open false in_wall false 7420 birch_fence_gate facing east powered false open false in_wall false 7421 jungle_fence_gate facing north powered true open true in_wall true 7422 jungle_fence_gate facing north powered false open true in_wall true 7423 jungle_fence_gate facing north powered true open false in_wall true 7424 jungle_fence_gate facing north powered false open false in_wall true 7425 jungle_fence_gate facing north powered true open true in_wall false 7426 jungle_fence_gate facing north powered false open true in_wall false 7427 jungle_fence_gate facing north powered true open false in_wall false 7428 jungle_fence_gate facing north powered false open false in_wall false 7429 jungle_fence_gate facing south powered true open true in_wall true 7430 jungle_fence_gate facing south powered false open true in_wall true 7431 jungle_fence_gate facing south powered true open false in_wall true 7432 jungle_fence_gate facing south powered false open false in_wall true 7433 jungle_fence_gate facing south powered true open true in_wall false 7434 jungle_fence_gate facing south powered false open true in_wall false 7435 jungle_fence_gate facing south powered true open false in_wall false 7436 jungle_fence_gate facing south powered false open false in_wall false 7437 jungle_fence_gate facing west powered true open true in_wall true 7438 jungle_fence_gate facing west powered false open true in_wall true 7439 jungle_fence_gate facing west powered true open false in_wall true 7440 jungle_fence_gate facing west powered false open false in_wall true 7441 jungle_fence_gate facing west powered true open true in_wall false 7442 jungle_fence_gate facing west powered false open true in_wall false 7443 jungle_fence_gate facing west powered true open false in_wall false 7444 jungle_fence_gate facing west powered false open false in_wall false 7445 jungle_fence_gate facing east powered true open true in_wall true 7446 jungle_fence_gate facing east powered false open true in_wall true 7447 jungle_fence_gate facing east powered true open false in_wall true 7448 jungle_fence_gate facing east powered false open false in_wall true 7449 jungle_fence_gate facing east powered true open true in_wall false 7450 jungle_fence_gate facing east powered false open true in_wall false 7451 jungle_fence_gate facing east powered true open false in_wall false 7452 jungle_fence_gate facing east powered false open false in_wall false 7453 acacia_fence_gate facing north powered true open true in_wall true 7454 acacia_fence_gate facing north powered false open true in_wall true 7455 acacia_fence_gate facing north powered true open false in_wall true 7456 acacia_fence_gate facing north powered false open false in_wall true 7457 acacia_fence_gate facing north powered true open true in_wall false 7458 acacia_fence_gate facing north powered false open true in_wall false 7459 acacia_fence_gate facing north powered true open false in_wall false 7460 acacia_fence_gate facing north powered false open false in_wall false 7461 acacia_fence_gate facing south powered true open true in_wall true 7462 acacia_fence_gate facing south powered false open true in_wall true 7463 acacia_fence_gate facing south powered true open false in_wall true 7464 acacia_fence_gate facing south powered false open false in_wall true 7465 acacia_fence_gate facing south powered true open true in_wall false 7466 acacia_fence_gate facing south powered false open true in_wall false 7467 acacia_fence_gate facing south powered true open false in_wall false 7468 acacia_fence_gate facing south powered false open false in_wall false 7469 acacia_fence_gate facing west powered true open true in_wall true 7470 acacia_fence_gate facing west powered false open true in_wall true 7471 acacia_fence_gate facing west powered true open false in_wall true 7472 acacia_fence_gate facing west powered false open false in_wall true 7473 acacia_fence_gate facing west powered true open true in_wall false 7474 acacia_fence_gate facing west powered false open true in_wall false 7475 acacia_fence_gate facing west powered true open false in_wall false 7476 acacia_fence_gate facing west powered false open false in_wall false 7477 acacia_fence_gate facing east powered true open true in_wall true 7478 acacia_fence_gate facing east powered false open true in_wall true 7479 acacia_fence_gate facing east powered true open false in_wall true 7480 acacia_fence_gate facing east powered false open false in_wall true 7481 acacia_fence_gate facing east powered true open true in_wall false 7482 acacia_fence_gate facing east powered false open true in_wall false 7483 acacia_fence_gate facing east powered true open false in_wall false 7484 acacia_fence_gate facing east powered false open false in_wall false 7485 dark_oak_fence_gate facing north powered true open true in_wall true 7486 dark_oak_fence_gate facing north powered false open true in_wall true 7487 dark_oak_fence_gate facing north powered true open false in_wall true 7488 dark_oak_fence_gate facing north powered false open false in_wall true 7489 dark_oak_fence_gate facing north powered true open true in_wall false 7490 dark_oak_fence_gate facing north powered false open true in_wall false 7491 dark_oak_fence_gate facing north powered true open false in_wall false 7492 dark_oak_fence_gate facing north powered false open false in_wall false 7493 dark_oak_fence_gate facing south powered true open true in_wall true 7494 dark_oak_fence_gate facing south powered false open true in_wall true 7495 dark_oak_fence_gate facing south powered true open false in_wall true 7496 dark_oak_fence_gate facing south powered false open false in_wall true 7497 dark_oak_fence_gate facing south powered true open true in_wall false 7498 dark_oak_fence_gate facing south powered false open true in_wall false 7499 dark_oak_fence_gate facing south powered true open false in_wall false 7500 dark_oak_fence_gate facing south powered false open false in_wall false 7501 dark_oak_fence_gate facing west powered true open true in_wall true 7502 dark_oak_fence_gate facing west powered false open true in_wall true 7503 dark_oak_fence_gate facing west powered true open false in_wall true 7504 dark_oak_fence_gate facing west powered false open false in_wall true 7505 dark_oak_fence_gate facing west powered true open true in_wall false 7506 dark_oak_fence_gate facing west powered false open true in_wall false 7507 dark_oak_fence_gate facing west powered true open false in_wall false 7508 dark_oak_fence_gate facing west powered false open false in_wall false 7509 dark_oak_fence_gate facing east powered true open true in_wall true 7510 dark_oak_fence_gate facing east powered false open true in_wall true 7511 dark_oak_fence_gate facing east powered true open false in_wall true 7512 dark_oak_fence_gate facing east powered false open false in_wall true 7513 dark_oak_fence_gate facing east powered true open true in_wall false 7514 dark_oak_fence_gate facing east powered false open true in_wall false 7515 dark_oak_fence_gate facing east powered true open false in_wall false 7516 dark_oak_fence_gate facing east powered false open false in_wall false 7517 spruce_fence waterlogged true south true east true north true west true 7518 spruce_fence waterlogged true south true east true north true west false 7519 spruce_fence waterlogged false south true east true north true west true 7520 spruce_fence waterlogged false south true east true north true west false 7521 spruce_fence waterlogged true south false east true north true west true 7522 spruce_fence waterlogged true south false east true north true west false 7523 spruce_fence waterlogged false south false east true north true west true 7524 spruce_fence waterlogged false south false east true north true west false 7525 spruce_fence waterlogged true south true east true north false west true 7526 spruce_fence waterlogged true south true east true north false west false 7527 spruce_fence waterlogged false south true east true north false west true 7528 spruce_fence waterlogged false south true east true north false west false 7529 spruce_fence waterlogged true south false east true north false west true 7530 spruce_fence waterlogged true south false east true north false west false 7531 spruce_fence waterlogged false south false east true north false west true 7532 spruce_fence waterlogged false south false east true north false west false 7533 spruce_fence waterlogged true south true east false north true west true 7534 spruce_fence waterlogged true south true east false north true west false 7535 spruce_fence waterlogged false south true east false north true west true 7536 spruce_fence waterlogged false south true east false north true west false 7537 spruce_fence waterlogged true south false east false north true west true 7538 spruce_fence waterlogged true south false east false north true west false 7539 spruce_fence waterlogged false south false east false north true west true 7540 spruce_fence waterlogged false south false east false north true west false 7541 spruce_fence waterlogged true south true east false north false west true 7542 spruce_fence waterlogged true south true east false north false west false 7543 spruce_fence waterlogged false south true east false north false west true 7544 spruce_fence waterlogged false south true east false north false west false 7545 spruce_fence waterlogged true south false east false north false west true 7546 spruce_fence waterlogged true south false east false north false west false 7547 spruce_fence waterlogged false south false east false north false west true 7548 spruce_fence waterlogged false south false east false north false west false 7549 birch_fence waterlogged true south true east true north true west true 7550 birch_fence waterlogged true south true east true north true west false 7551 birch_fence waterlogged false south true east true north true west true 7552 birch_fence waterlogged false south true east true north true west false 7553 birch_fence waterlogged true south false east true north true west true 7554 birch_fence waterlogged true south false east true north true west false 7555 birch_fence waterlogged false south false east true north true west true 7556 birch_fence waterlogged false south false east true north true west false 7557 birch_fence waterlogged true south true east true north false west true 7558 birch_fence waterlogged true south true east true north false west false 7559 birch_fence waterlogged false south true east true north false west true 7560 birch_fence waterlogged false south true east true north false west false 7561 birch_fence waterlogged true south false east true north false west true 7562 birch_fence waterlogged true south false east true north false west false 7563 birch_fence waterlogged false south false east true north false west true 7564 birch_fence waterlogged false south false east true north false west false 7565 birch_fence waterlogged true south true east false north true west true 7566 birch_fence waterlogged true south true east false north true west false 7567 birch_fence waterlogged false south true east false north true west true 7568 birch_fence waterlogged false south true east false north true west false 7569 birch_fence waterlogged true south false east false north true west true 7570 birch_fence waterlogged true south false east false north true west false 7571 birch_fence waterlogged false south false east false north true west true 7572 birch_fence waterlogged false south false east false north true west false 7573 birch_fence waterlogged true south true east false north false west true 7574 birch_fence waterlogged true south true east false north false west false 7575 birch_fence waterlogged false south true east false north false west true 7576 birch_fence waterlogged false south true east false north false west false 7577 birch_fence waterlogged true south false east false north false west true 7578 birch_fence waterlogged true south false east false north false west false 7579 birch_fence waterlogged false south false east false north false west true 7580 birch_fence waterlogged false south false east false north false west false 7581 jungle_fence waterlogged true south true east true north true west true 7582 jungle_fence waterlogged true south true east true north true west false 7583 jungle_fence waterlogged false south true east true north true west true 7584 jungle_fence waterlogged false south true east true north true west false 7585 jungle_fence waterlogged true south false east true north true west true 7586 jungle_fence waterlogged true south false east true north true west false 7587 jungle_fence waterlogged false south false east true north true west true 7588 jungle_fence waterlogged false south false east true north true west false 7589 jungle_fence waterlogged true south true east true north false west true 7590 jungle_fence waterlogged true south true east true north false west false 7591 jungle_fence waterlogged false south true east true north false west true 7592 jungle_fence waterlogged false south true east true north false west false 7593 jungle_fence waterlogged true south false east true north false west true 7594 jungle_fence waterlogged true south false east true north false west false 7595 jungle_fence waterlogged false south false east true north false west true 7596 jungle_fence waterlogged false south false east true north false west false 7597 jungle_fence waterlogged true south true east false north true west true 7598 jungle_fence waterlogged true south true east false north true west false 7599 jungle_fence waterlogged false south true east false north true west true 7600 jungle_fence waterlogged false south true east false north true west false 7601 jungle_fence waterlogged true south false east false north true west true 7602 jungle_fence waterlogged true south false east false north true west false 7603 jungle_fence waterlogged false south false east false north true west true 7604 jungle_fence waterlogged false south false east false north true west false 7605 jungle_fence waterlogged true south true east false north false west true 7606 jungle_fence waterlogged true south true east false north false west false 7607 jungle_fence waterlogged false south true east false north false west true 7608 jungle_fence waterlogged false south true east false north false west false 7609 jungle_fence waterlogged true south false east false north false west true 7610 jungle_fence waterlogged true south false east false north false west false 7611 jungle_fence waterlogged false south false east false north false west true 7612 jungle_fence waterlogged false south false east false north false west false 7613 acacia_fence waterlogged true south true east true north true west true 7614 acacia_fence waterlogged true south true east true north true west false 7615 acacia_fence waterlogged false south true east true north true west true 7616 acacia_fence waterlogged false south true east true north true west false 7617 acacia_fence waterlogged true south false east true north true west true 7618 acacia_fence waterlogged true south false east true north true west false 7619 acacia_fence waterlogged false south false east true north true west true 7620 acacia_fence waterlogged false south false east true north true west false 7621 acacia_fence waterlogged true south true east true north false west true 7622 acacia_fence waterlogged true south true east true north false west false 7623 acacia_fence waterlogged false south true east true north false west true 7624 acacia_fence waterlogged false south true east true north false west false 7625 acacia_fence waterlogged true south false east true north false west true 7626 acacia_fence waterlogged true south false east true north false west false 7627 acacia_fence waterlogged false south false east true north false west true 7628 acacia_fence waterlogged false south false east true north false west false 7629 acacia_fence waterlogged true south true east false north true west true 7630 acacia_fence waterlogged true south true east false north true west false 7631 acacia_fence waterlogged false south true east false north true west true 7632 acacia_fence waterlogged false south true east false north true west false 7633 acacia_fence waterlogged true south false east false north true west true 7634 acacia_fence waterlogged true south false east false north true west false 7635 acacia_fence waterlogged false south false east false north true west true 7636 acacia_fence waterlogged false south false east false north true west false 7637 acacia_fence waterlogged true south true east false north false west true 7638 acacia_fence waterlogged true south true east false north false west false 7639 acacia_fence waterlogged false south true east false north false west true 7640 acacia_fence waterlogged false south true east false north false west false 7641 acacia_fence waterlogged true south false east false north false west true 7642 acacia_fence waterlogged true south false east false north false west false 7643 acacia_fence waterlogged false south false east false north false west true 7644 acacia_fence waterlogged false south false east false north false west false 7645 dark_oak_fence waterlogged true south true east true north true west true 7646 dark_oak_fence waterlogged true south true east true north true west false 7647 dark_oak_fence waterlogged false south true east true north true west true 7648 dark_oak_fence waterlogged false south true east true north true west false 7649 dark_oak_fence waterlogged true south false east true north true west true 7650 dark_oak_fence waterlogged true south false east true north true west false 7651 dark_oak_fence waterlogged false south false east true north true west true 7652 dark_oak_fence waterlogged false south false east true north true west false 7653 dark_oak_fence waterlogged true south true east true north false west true 7654 dark_oak_fence waterlogged true south true east true north false west false 7655 dark_oak_fence waterlogged false south true east true north false west true 7656 dark_oak_fence waterlogged false south true east true north false west false 7657 dark_oak_fence waterlogged true south false east true north false west true 7658 dark_oak_fence waterlogged true south false east true north false west false 7659 dark_oak_fence waterlogged false south false east true north false west true 7660 dark_oak_fence waterlogged false south false east true north false west false 7661 dark_oak_fence waterlogged true south true east false north true west true 7662 dark_oak_fence waterlogged true south true east false north true west false 7663 dark_oak_fence waterlogged false south true east false north true west true 7664 dark_oak_fence waterlogged false south true east false north true west false 7665 dark_oak_fence waterlogged true south false east false north true west true 7666 dark_oak_fence waterlogged true south false east false north true west false 7667 dark_oak_fence waterlogged false south false east false north true west true 7668 dark_oak_fence waterlogged false south false east false north true west false 7669 dark_oak_fence waterlogged true south true east false north false west true 7670 dark_oak_fence waterlogged true south true east false north false west false 7671 dark_oak_fence waterlogged false south true east false north false west true 7672 dark_oak_fence waterlogged false south true east false north false west false 7673 dark_oak_fence waterlogged true south false east false north false west true 7674 dark_oak_fence waterlogged true south false east false north false west false 7675 dark_oak_fence waterlogged false south false east false north false west true 7676 dark_oak_fence waterlogged false south false east false north false west false 7677 spruce_door hinge left half upper facing north powered true open true 7678 spruce_door hinge left half upper facing north powered false open true 7679 spruce_door hinge left half upper facing north powered true open false 7680 spruce_door hinge left half upper facing north powered false open false 7681 spruce_door hinge right half upper facing north powered true open true 7682 spruce_door hinge right half upper facing north powered false open true 7683 spruce_door hinge right half upper facing north powered true open false 7684 spruce_door hinge right half upper facing north powered false open false 7685 spruce_door hinge left half lower facing north powered true open true 7686 spruce_door hinge left half lower facing north powered false open true 7687 spruce_door hinge left half lower facing north powered true open false 7688 spruce_door hinge left half lower facing north powered false open false 7689 spruce_door hinge right half lower facing north powered true open true 7690 spruce_door hinge right half lower facing north powered false open true 7691 spruce_door hinge right half lower facing north powered true open false 7692 spruce_door hinge right half lower facing north powered false open false 7693 spruce_door hinge left half upper facing south powered true open true 7694 spruce_door hinge left half upper facing south powered false open true 7695 spruce_door hinge left half upper facing south powered true open false 7696 spruce_door hinge left half upper facing south powered false open false 7697 spruce_door hinge right half upper facing south powered true open true 7698 spruce_door hinge right half upper facing south powered false open true 7699 spruce_door hinge right half upper facing south powered true open false 7700 spruce_door hinge right half upper facing south powered false open false 7701 spruce_door hinge left half lower facing south powered true open true 7702 spruce_door hinge left half lower facing south powered false open true 7703 spruce_door hinge left half lower facing south powered true open false 7704 spruce_door hinge left half lower facing south powered false open false 7705 spruce_door hinge right half lower facing south powered true open true 7706 spruce_door hinge right half lower facing south powered false open true 7707 spruce_door hinge right half lower facing south powered true open false 7708 spruce_door hinge right half lower facing south powered false open false 7709 spruce_door hinge left half upper facing west powered true open true 7710 spruce_door hinge left half upper facing west powered false open true 7711 spruce_door hinge left half upper facing west powered true open false 7712 spruce_door hinge left half upper facing west powered false open false 7713 spruce_door hinge right half upper facing west powered true open true 7714 spruce_door hinge right half upper facing west powered false open true 7715 spruce_door hinge right half upper facing west powered true open false 7716 spruce_door hinge right half upper facing west powered false open false 7717 spruce_door hinge left half lower facing west powered true open true 7718 spruce_door hinge left half lower facing west powered false open true 7719 spruce_door hinge left half lower facing west powered true open false 7720 spruce_door hinge left half lower facing west powered false open false 7721 spruce_door hinge right half lower facing west powered true open true 7722 spruce_door hinge right half lower facing west powered false open true 7723 spruce_door hinge right half lower facing west powered true open false 7724 spruce_door hinge right half lower facing west powered false open false 7725 spruce_door hinge left half upper facing east powered true open true 7726 spruce_door hinge left half upper facing east powered false open true 7727 spruce_door hinge left half upper facing east powered true open false 7728 spruce_door hinge left half upper facing east powered false open false 7729 spruce_door hinge right half upper facing east powered true open true 7730 spruce_door hinge right half upper facing east powered false open true 7731 spruce_door hinge right half upper facing east powered true open false 7732 spruce_door hinge right half upper facing east powered false open false 7733 spruce_door hinge left half lower facing east powered true open true 7734 spruce_door hinge left half lower facing east powered false open true 7735 spruce_door hinge left half lower facing east powered true open false 7736 spruce_door hinge left half lower facing east powered false open false 7737 spruce_door hinge right half lower facing east powered true open true 7738 spruce_door hinge right half lower facing east powered false open true 7739 spruce_door hinge right half lower facing east powered true open false 7740 spruce_door hinge right half lower facing east powered false open false 7741 birch_door hinge left half upper facing north powered true open true 7742 birch_door hinge left half upper facing north powered false open true 7743 birch_door hinge left half upper facing north powered true open false 7744 birch_door hinge left half upper facing north powered false open false 7745 birch_door hinge right half upper facing north powered true open true 7746 birch_door hinge right half upper facing north powered false open true 7747 birch_door hinge right half upper facing north powered true open false 7748 birch_door hinge right half upper facing north powered false open false 7749 birch_door hinge left half lower facing north powered true open true 7750 birch_door hinge left half lower facing north powered false open true 7751 birch_door hinge left half lower facing north powered true open false 7752 birch_door hinge left half lower facing north powered false open false 7753 birch_door hinge right half lower facing north powered true open true 7754 birch_door hinge right half lower facing north powered false open true 7755 birch_door hinge right half lower facing north powered true open false 7756 birch_door hinge right half lower facing north powered false open false 7757 birch_door hinge left half upper facing south powered true open true 7758 birch_door hinge left half upper facing south powered false open true 7759 birch_door hinge left half upper facing south powered true open false 7760 birch_door hinge left half upper facing south powered false open false 7761 birch_door hinge right half upper facing south powered true open true 7762 birch_door hinge right half upper facing south powered false open true 7763 birch_door hinge right half upper facing south powered true open false 7764 birch_door hinge right half upper facing south powered false open false 7765 birch_door hinge left half lower facing south powered true open true 7766 birch_door hinge left half lower facing south powered false open true 7767 birch_door hinge left half lower facing south powered true open false 7768 birch_door hinge left half lower facing south powered false open false 7769 birch_door hinge right half lower facing south powered true open true 7770 birch_door hinge right half lower facing south powered false open true 7771 birch_door hinge right half lower facing south powered true open false 7772 birch_door hinge right half lower facing south powered false open false 7773 birch_door hinge left half upper facing west powered true open true 7774 birch_door hinge left half upper facing west powered false open true 7775 birch_door hinge left half upper facing west powered true open false 7776 birch_door hinge left half upper facing west powered false open false 7777 birch_door hinge right half upper facing west powered true open true 7778 birch_door hinge right half upper facing west powered false open true 7779 birch_door hinge right half upper facing west powered true open false 7780 birch_door hinge right half upper facing west powered false open false 7781 birch_door hinge left half lower facing west powered true open true 7782 birch_door hinge left half lower facing west powered false open true 7783 birch_door hinge left half lower facing west powered true open false 7784 birch_door hinge left half lower facing west powered false open false 7785 birch_door hinge right half lower facing west powered true open true 7786 birch_door hinge right half lower facing west powered false open true 7787 birch_door hinge right half lower facing west powered true open false 7788 birch_door hinge right half lower facing west powered false open false 7789 birch_door hinge left half upper facing east powered true open true 7790 birch_door hinge left half upper facing east powered false open true 7791 birch_door hinge left half upper facing east powered true open false 7792 birch_door hinge left half upper facing east powered false open false 7793 birch_door hinge right half upper facing east powered true open true 7794 birch_door hinge right half upper facing east powered false open true 7795 birch_door hinge right half upper facing east powered true open false 7796 birch_door hinge right half upper facing east powered false open false 7797 birch_door hinge left half lower facing east powered true open true 7798 birch_door hinge left half lower facing east powered false open true 7799 birch_door hinge left half lower facing east powered true open false 7800 birch_door hinge left half lower facing east powered false open false 7801 birch_door hinge right half lower facing east powered true open true 7802 birch_door hinge right half lower facing east powered false open true 7803 birch_door hinge right half lower facing east powered true open false 7804 birch_door hinge right half lower facing east powered false open false 7805 jungle_door hinge left half upper facing north powered true open true 7806 jungle_door hinge left half upper facing north powered false open true 7807 jungle_door hinge left half upper facing north powered true open false 7808 jungle_door hinge left half upper facing north powered false open false 7809 jungle_door hinge right half upper facing north powered true open true 7810 jungle_door hinge right half upper facing north powered false open true 7811 jungle_door hinge right half upper facing north powered true open false 7812 jungle_door hinge right half upper facing north powered false open false 7813 jungle_door hinge left half lower facing north powered true open true 7814 jungle_door hinge left half lower facing north powered false open true 7815 jungle_door hinge left half lower facing north powered true open false 7816 jungle_door hinge left half lower facing north powered false open false 7817 jungle_door hinge right half lower facing north powered true open true 7818 jungle_door hinge right half lower facing north powered false open true 7819 jungle_door hinge right half lower facing north powered true open false 7820 jungle_door hinge right half lower facing north powered false open false 7821 jungle_door hinge left half upper facing south powered true open true 7822 jungle_door hinge left half upper facing south powered false open true 7823 jungle_door hinge left half upper facing south powered true open false 7824 jungle_door hinge left half upper facing south powered false open false 7825 jungle_door hinge right half upper facing south powered true open true 7826 jungle_door hinge right half upper facing south powered false open true 7827 jungle_door hinge right half upper facing south powered true open false 7828 jungle_door hinge right half upper facing south powered false open false 7829 jungle_door hinge left half lower facing south powered true open true 7830 jungle_door hinge left half lower facing south powered false open true 7831 jungle_door hinge left half lower facing south powered true open false 7832 jungle_door hinge left half lower facing south powered false open false 7833 jungle_door hinge right half lower facing south powered true open true 7834 jungle_door hinge right half lower facing south powered false open true 7835 jungle_door hinge right half lower facing south powered true open false 7836 jungle_door hinge right half lower facing south powered false open false 7837 jungle_door hinge left half upper facing west powered true open true 7838 jungle_door hinge left half upper facing west powered false open true 7839 jungle_door hinge left half upper facing west powered true open false 7840 jungle_door hinge left half upper facing west powered false open false 7841 jungle_door hinge right half upper facing west powered true open true 7842 jungle_door hinge right half upper facing west powered false open true 7843 jungle_door hinge right half upper facing west powered true open false 7844 jungle_door hinge right half upper facing west powered false open false 7845 jungle_door hinge left half lower facing west powered true open true 7846 jungle_door hinge left half lower facing west powered false open true 7847 jungle_door hinge left half lower facing west powered true open false 7848 jungle_door hinge left half lower facing west powered false open false 7849 jungle_door hinge right half lower facing west powered true open true 7850 jungle_door hinge right half lower facing west powered false open true 7851 jungle_door hinge right half lower facing west powered true open false 7852 jungle_door hinge right half lower facing west powered false open false 7853 jungle_door hinge left half upper facing east powered true open true 7854 jungle_door hinge left half upper facing east powered false open true 7855 jungle_door hinge left half upper facing east powered true open false 7856 jungle_door hinge left half upper facing east powered false open false 7857 jungle_door hinge right half upper facing east powered true open true 7858 jungle_door hinge right half upper facing east powered false open true 7859 jungle_door hinge right half upper facing east powered true open false 7860 jungle_door hinge right half upper facing east powered false open false 7861 jungle_door hinge left half lower facing east powered true open true 7862 jungle_door hinge left half lower facing east powered false open true 7863 jungle_door hinge left half lower facing east powered true open false 7864 jungle_door hinge left half lower facing east powered false open false 7865 jungle_door hinge right half lower facing east powered true open true 7866 jungle_door hinge right half lower facing east powered false open true 7867 jungle_door hinge right half lower facing east powered true open false 7868 jungle_door hinge right half lower facing east powered false open false 7869 acacia_door hinge left half upper facing north powered true open true 7870 acacia_door hinge left half upper facing north powered false open true 7871 acacia_door hinge left half upper facing north powered true open false 7872 acacia_door hinge left half upper facing north powered false open false 7873 acacia_door hinge right half upper facing north powered true open true 7874 acacia_door hinge right half upper facing north powered false open true 7875 acacia_door hinge right half upper facing north powered true open false 7876 acacia_door hinge right half upper facing north powered false open false 7877 acacia_door hinge left half lower facing north powered true open true 7878 acacia_door hinge left half lower facing north powered false open true 7879 acacia_door hinge left half lower facing north powered true open false 7880 acacia_door hinge left half lower facing north powered false open false 7881 acacia_door hinge right half lower facing north powered true open true 7882 acacia_door hinge right half lower facing north powered false open true 7883 acacia_door hinge right half lower facing north powered true open false 7884 acacia_door hinge right half lower facing north powered false open false 7885 acacia_door hinge left half upper facing south powered true open true 7886 acacia_door hinge left half upper facing south powered false open true 7887 acacia_door hinge left half upper facing south powered true open false 7888 acacia_door hinge left half upper facing south powered false open false 7889 acacia_door hinge right half upper facing south powered true open true 7890 acacia_door hinge right half upper facing south powered false open true 7891 acacia_door hinge right half upper facing south powered true open false 7892 acacia_door hinge right half upper facing south powered false open false 7893 acacia_door hinge left half lower facing south powered true open true 7894 acacia_door hinge left half lower facing south powered false open true 7895 acacia_door hinge left half lower facing south powered true open false 7896 acacia_door hinge left half lower facing south powered false open false 7897 acacia_door hinge right half lower facing south powered true open true 7898 acacia_door hinge right half lower facing south powered false open true 7899 acacia_door hinge right half lower facing south powered true open false 7900 acacia_door hinge right half lower facing south powered false open false 7901 acacia_door hinge left half upper facing west powered true open true 7902 acacia_door hinge left half upper facing west powered false open true 7903 acacia_door hinge left half upper facing west powered true open false 7904 acacia_door hinge left half upper facing west powered false open false 7905 acacia_door hinge right half upper facing west powered true open true 7906 acacia_door hinge right half upper facing west powered false open true 7907 acacia_door hinge right half upper facing west powered true open false 7908 acacia_door hinge right half upper facing west powered false open false 7909 acacia_door hinge left half lower facing west powered true open true 7910 acacia_door hinge left half lower facing west powered false open true 7911 acacia_door hinge left half lower facing west powered true open false 7912 acacia_door hinge left half lower facing west powered false open false 7913 acacia_door hinge right half lower facing west powered true open true 7914 acacia_door hinge right half lower facing west powered false open true 7915 acacia_door hinge right half lower facing west powered true open false 7916 acacia_door hinge right half lower facing west powered false open false 7917 acacia_door hinge left half upper facing east powered true open true 7918 acacia_door hinge left half upper facing east powered false open true 7919 acacia_door hinge left half upper facing east powered true open false 7920 acacia_door hinge left half upper facing east powered false open false 7921 acacia_door hinge right half upper facing east powered true open true 7922 acacia_door hinge right half upper facing east powered false open true 7923 acacia_door hinge right half upper facing east powered true open false 7924 acacia_door hinge right half upper facing east powered false open false 7925 acacia_door hinge left half lower facing east powered true open true 7926 acacia_door hinge left half lower facing east powered false open true 7927 acacia_door hinge left half lower facing east powered true open false 7928 acacia_door hinge left half lower facing east powered false open false 7929 acacia_door hinge right half lower facing east powered true open true 7930 acacia_door hinge right half lower facing east powered false open true 7931 acacia_door hinge right half lower facing east powered true open false 7932 acacia_door hinge right half lower facing east powered false open false 7933 dark_oak_door hinge left half upper facing north powered true open true 7934 dark_oak_door hinge left half upper facing north powered false open true 7935 dark_oak_door hinge left half upper facing north powered true open false 7936 dark_oak_door hinge left half upper facing north powered false open false 7937 dark_oak_door hinge right half upper facing north powered true open true 7938 dark_oak_door hinge right half upper facing north powered false open true 7939 dark_oak_door hinge right half upper facing north powered true open false 7940 dark_oak_door hinge right half upper facing north powered false open false 7941 dark_oak_door hinge left half lower facing north powered true open true 7942 dark_oak_door hinge left half lower facing north powered false open true 7943 dark_oak_door hinge left half lower facing north powered true open false 7944 dark_oak_door hinge left half lower facing north powered false open false 7945 dark_oak_door hinge right half lower facing north powered true open true 7946 dark_oak_door hinge right half lower facing north powered false open true 7947 dark_oak_door hinge right half lower facing north powered true open false 7948 dark_oak_door hinge right half lower facing north powered false open false 7949 dark_oak_door hinge left half upper facing south powered true open true 7950 dark_oak_door hinge left half upper facing south powered false open true 7951 dark_oak_door hinge left half upper facing south powered true open false 7952 dark_oak_door hinge left half upper facing south powered false open false 7953 dark_oak_door hinge right half upper facing south powered true open true 7954 dark_oak_door hinge right half upper facing south powered false open true 7955 dark_oak_door hinge right half upper facing south powered true open false 7956 dark_oak_door hinge right half upper facing south powered false open false 7957 dark_oak_door hinge left half lower facing south powered true open true 7958 dark_oak_door hinge left half lower facing south powered false open true 7959 dark_oak_door hinge left half lower facing south powered true open false 7960 dark_oak_door hinge left half lower facing south powered false open false 7961 dark_oak_door hinge right half lower facing south powered true open true 7962 dark_oak_door hinge right half lower facing south powered false open true 7963 dark_oak_door hinge right half lower facing south powered true open false 7964 dark_oak_door hinge right half lower facing south powered false open false 7965 dark_oak_door hinge left half upper facing west powered true open true 7966 dark_oak_door hinge left half upper facing west powered false open true 7967 dark_oak_door hinge left half upper facing west powered true open false 7968 dark_oak_door hinge left half upper facing west powered false open false 7969 dark_oak_door hinge right half upper facing west powered true open true 7970 dark_oak_door hinge right half upper facing west powered false open true 7971 dark_oak_door hinge right half upper facing west powered true open false 7972 dark_oak_door hinge right half upper facing west powered false open false 7973 dark_oak_door hinge left half lower facing west powered true open true 7974 dark_oak_door hinge left half lower facing west powered false open true 7975 dark_oak_door hinge left half lower facing west powered true open false 7976 dark_oak_door hinge left half lower facing west powered false open false 7977 dark_oak_door hinge right half lower facing west powered true open true 7978 dark_oak_door hinge right half lower facing west powered false open true 7979 dark_oak_door hinge right half lower facing west powered true open false 7980 dark_oak_door hinge right half lower facing west powered false open false 7981 dark_oak_door hinge left half upper facing east powered true open true 7982 dark_oak_door hinge left half upper facing east powered false open true 7983 dark_oak_door hinge left half upper facing east powered true open false 7984 dark_oak_door hinge left half upper facing east powered false open false 7985 dark_oak_door hinge right half upper facing east powered true open true 7986 dark_oak_door hinge right half upper facing east powered false open true 7987 dark_oak_door hinge right half upper facing east powered true open false 7988 dark_oak_door hinge right half upper facing east powered false open false 7989 dark_oak_door hinge left half lower facing east powered true open true 7990 dark_oak_door hinge left half lower facing east powered false open true 7991 dark_oak_door hinge left half lower facing east powered true open false 7992 dark_oak_door hinge left half lower facing east powered false open false 7993 dark_oak_door hinge right half lower facing east powered true open true 7994 dark_oak_door hinge right half lower facing east powered false open true 7995 dark_oak_door hinge right half lower facing east powered true open false 7996 dark_oak_door hinge right half lower facing east powered false open false 7997 end_rod facing north 7998 end_rod facing east 7999 end_rod facing south 8000 end_rod facing west 8001 end_rod facing up 8002 end_rod facing down 8003 chorus_plant up true south true east true north true down true west true 8004 chorus_plant up true south true east true north true down true west false 8005 chorus_plant up false south true east true north true down true west true 8006 chorus_plant up false south true east true north true down true west false 8007 chorus_plant up true south false east true north true down true west true 8008 chorus_plant up true south false east true north true down true west false 8009 chorus_plant up false south false east true north true down true west true 8010 chorus_plant up false south false east true north true down true west false 8011 chorus_plant up true south true east true north false down true west true 8012 chorus_plant up true south true east true north false down true west false 8013 chorus_plant up false south true east true north false down true west true 8014 chorus_plant up false south true east true north false down true west false 8015 chorus_plant up true south false east true north false down true west true 8016 chorus_plant up true south false east true north false down true west false 8017 chorus_plant up false south false east true north false down true west true 8018 chorus_plant up false south false east true north false down true west false 8019 chorus_plant up true south true east false north true down true west true 8020 chorus_plant up true south true east false north true down true west false 8021 chorus_plant up false south true east false north true down true west true 8022 chorus_plant up false south true east false north true down true west false 8023 chorus_plant up true south false east false north true down true west true 8024 chorus_plant up true south false east false north true down true west false 8025 chorus_plant up false south false east false north true down true west true 8026 chorus_plant up false south false east false north true down true west false 8027 chorus_plant up true south true east false north false down true west true 8028 chorus_plant up true south true east false north false down true west false 8029 chorus_plant up false south true east false north false down true west true 8030 chorus_plant up false south true east false north false down true west false 8031 chorus_plant up true south false east false north false down true west true 8032 chorus_plant up true south false east false north false down true west false 8033 chorus_plant up false south false east false north false down true west true 8034 chorus_plant up false south false east false north false down true west false 8035 chorus_plant up true south true east true north true down false west true 8036 chorus_plant up true south true east true north true down false west false 8037 chorus_plant up false south true east true north true down false west true 8038 chorus_plant up false south true east true north true down false west false 8039 chorus_plant up true south false east true north true down false west true 8040 chorus_plant up true south false east true north true down false west false 8041 chorus_plant up false south false east true north true down false west true 8042 chorus_plant up false south false east true north true down false west false 8043 chorus_plant up true south true east true north false down false west true 8044 chorus_plant up true south true east true north false down false west false 8045 chorus_plant up false south true east true north false down false west true 8046 chorus_plant up false south true east true north false down false west false 8047 chorus_plant up true south false east true north false down false west true 8048 chorus_plant up true south false east true north false down false west false 8049 chorus_plant up false south false east true north false down false west true 8050 chorus_plant up false south false east true north false down false west false 8051 chorus_plant up true south true east false north true down false west true 8052 chorus_plant up true south true east false north true down false west false 8053 chorus_plant up false south true east false north true down false west true 8054 chorus_plant up false south true east false north true down false west false 8055 chorus_plant up true south false east false north true down false west true 8056 chorus_plant up true south false east false north true down false west false 8057 chorus_plant up false south false east false north true down false west true 8058 chorus_plant up false south false east false north true down false west false 8059 chorus_plant up true south true east false north false down false west true 8060 chorus_plant up true south true east false north false down false west false 8061 chorus_plant up false south true east false north false down false west true 8062 chorus_plant up false south true east false north false down false west false 8063 chorus_plant up true south false east false north false down false west true 8064 chorus_plant up true south false east false north false down false west false 8065 chorus_plant up false south false east false north false down false west true 8066 chorus_plant up false south false east false north false down false west false 8067 chorus_flower age 0 8068 chorus_flower age 1 8069 chorus_flower age 2 8070 chorus_flower age 3 8071 chorus_flower age 4 8072 chorus_flower age 5 8073 purpur_block 8074 purpur_pillar axis x 8075 purpur_pillar axis y 8076 purpur_pillar axis z 8077 purpur_stairs facing north waterlogged true shape straight half top 8078 purpur_stairs facing north waterlogged false shape straight half top 8079 purpur_stairs facing north waterlogged true shape inner_left half top 8080 purpur_stairs facing north waterlogged false shape inner_left half top 8081 purpur_stairs facing north waterlogged true shape inner_right half top 8082 purpur_stairs facing north waterlogged false shape inner_right half top 8083 purpur_stairs facing north waterlogged true shape outer_left half top 8084 purpur_stairs facing north waterlogged false shape outer_left half top 8085 purpur_stairs facing north waterlogged true shape outer_right half top 8086 purpur_stairs facing north waterlogged false shape outer_right half top 8087 purpur_stairs facing north waterlogged true shape straight half bottom 8088 purpur_stairs facing north waterlogged false shape straight half bottom 8089 purpur_stairs facing north waterlogged true shape inner_left half bottom 8090 purpur_stairs facing north waterlogged false shape inner_left half bottom 8091 purpur_stairs facing north waterlogged true shape inner_right half bottom 8092 purpur_stairs facing north waterlogged false shape inner_right half bottom 8093 purpur_stairs facing north waterlogged true shape outer_left half bottom 8094 purpur_stairs facing north waterlogged false shape outer_left half bottom 8095 purpur_stairs facing north waterlogged true shape outer_right half bottom 8096 purpur_stairs facing north waterlogged false shape outer_right half bottom 8097 purpur_stairs facing south waterlogged true shape straight half top 8098 purpur_stairs facing south waterlogged false shape straight half top 8099 purpur_stairs facing south waterlogged true shape inner_left half top 8100 purpur_stairs facing south waterlogged false shape inner_left half top 8101 purpur_stairs facing south waterlogged true shape inner_right half top 8102 purpur_stairs facing south waterlogged false shape inner_right half top 8103 purpur_stairs facing south waterlogged true shape outer_left half top 8104 purpur_stairs facing south waterlogged false shape outer_left half top 8105 purpur_stairs facing south waterlogged true shape outer_right half top 8106 purpur_stairs facing south waterlogged false shape outer_right half top 8107 purpur_stairs facing south waterlogged true shape straight half bottom 8108 purpur_stairs facing south waterlogged false shape straight half bottom 8109 purpur_stairs facing south waterlogged true shape inner_left half bottom 8110 purpur_stairs facing south waterlogged false shape inner_left half bottom 8111 purpur_stairs facing south waterlogged true shape inner_right half bottom 8112 purpur_stairs facing south waterlogged false shape inner_right half bottom 8113 purpur_stairs facing south waterlogged true shape outer_left half bottom 8114 purpur_stairs facing south waterlogged false shape outer_left half bottom 8115 purpur_stairs facing south waterlogged true shape outer_right half bottom 8116 purpur_stairs facing south waterlogged false shape outer_right half bottom 8117 purpur_stairs facing west waterlogged true shape straight half top 8118 purpur_stairs facing west waterlogged false shape straight half top 8119 purpur_stairs facing west waterlogged true shape inner_left half top 8120 purpur_stairs facing west waterlogged false shape inner_left half top 8121 purpur_stairs facing west waterlogged true shape inner_right half top 8122 purpur_stairs facing west waterlogged false shape inner_right half top 8123 purpur_stairs facing west waterlogged true shape outer_left half top 8124 purpur_stairs facing west waterlogged false shape outer_left half top 8125 purpur_stairs facing west waterlogged true shape outer_right half top 8126 purpur_stairs facing west waterlogged false shape outer_right half top 8127 purpur_stairs facing west waterlogged true shape straight half bottom 8128 purpur_stairs facing west waterlogged false shape straight half bottom 8129 purpur_stairs facing west waterlogged true shape inner_left half bottom 8130 purpur_stairs facing west waterlogged false shape inner_left half bottom 8131 purpur_stairs facing west waterlogged true shape inner_right half bottom 8132 purpur_stairs facing west waterlogged false shape inner_right half bottom 8133 purpur_stairs facing west waterlogged true shape outer_left half bottom 8134 purpur_stairs facing west waterlogged false shape outer_left half bottom 8135 purpur_stairs facing west waterlogged true shape outer_right half bottom 8136 purpur_stairs facing west waterlogged false shape outer_right half bottom 8137 purpur_stairs facing east waterlogged true shape straight half top 8138 purpur_stairs facing east waterlogged false shape straight half top 8139 purpur_stairs facing east waterlogged true shape inner_left half top 8140 purpur_stairs facing east waterlogged false shape inner_left half top 8141 purpur_stairs facing east waterlogged true shape inner_right half top 8142 purpur_stairs facing east waterlogged false shape inner_right half top 8143 purpur_stairs facing east waterlogged true shape outer_left half top 8144 purpur_stairs facing east waterlogged false shape outer_left half top 8145 purpur_stairs facing east waterlogged true shape outer_right half top 8146 purpur_stairs facing east waterlogged false shape outer_right half top 8147 purpur_stairs facing east waterlogged true shape straight half bottom 8148 purpur_stairs facing east waterlogged false shape straight half bottom 8149 purpur_stairs facing east waterlogged true shape inner_left half bottom 8150 purpur_stairs facing east waterlogged false shape inner_left half bottom 8151 purpur_stairs facing east waterlogged true shape inner_right half bottom 8152 purpur_stairs facing east waterlogged false shape inner_right half bottom 8153 purpur_stairs facing east waterlogged true shape outer_left half bottom 8154 purpur_stairs facing east waterlogged false shape outer_left half bottom 8155 purpur_stairs facing east waterlogged true shape outer_right half bottom 8156 purpur_stairs facing east waterlogged false shape outer_right half bottom 8157 end_stone_bricks 8158 beetroots age 0 8159 beetroots age 1 8160 beetroots age 2 8161 beetroots age 3 8162 grass_path 8163 end_gateway 8164 repeating_command_block conditional true facing north 8165 repeating_command_block conditional true facing east 8166 repeating_command_block conditional true facing south 8167 repeating_command_block conditional true facing west 8168 repeating_command_block conditional true facing up 8169 repeating_command_block conditional true facing down 8170 repeating_command_block conditional false facing north 8171 repeating_command_block conditional false facing east 8172 repeating_command_block conditional false facing south 8173 repeating_command_block conditional false facing west 8174 repeating_command_block conditional false facing up 8175 repeating_command_block conditional false facing down 8176 chain_command_block conditional true facing north 8177 chain_command_block conditional true facing east 8178 chain_command_block conditional true facing south 8179 chain_command_block conditional true facing west 8180 chain_command_block conditional true facing up 8181 chain_command_block conditional true facing down 8182 chain_command_block conditional false facing north 8183 chain_command_block conditional false facing east 8184 chain_command_block conditional false facing south 8185 chain_command_block conditional false facing west 8186 chain_command_block conditional false facing up 8187 chain_command_block conditional false facing down 8188 frosted_ice age 0 8189 frosted_ice age 1 8190 frosted_ice age 2 8191 frosted_ice age 3 8192 magma_block 8193 nether_wart_block 8194 red_nether_bricks 8195 bone_block axis x 8196 bone_block axis y 8197 bone_block axis z 8198 structure_void 8199 observer facing north powered true 8200 observer facing north powered false 8201 observer facing east powered true 8202 observer facing east powered false 8203 observer facing south powered true 8204 observer facing south powered false 8205 observer facing west powered true 8206 observer facing west powered false 8207 observer facing up powered true 8208 observer facing up powered false 8209 observer facing down powered true 8210 observer facing down powered false 8211 shulker_box facing north 8212 shulker_box facing east 8213 shulker_box facing south 8214 shulker_box facing west 8215 shulker_box facing up 8216 shulker_box facing down 8217 white_shulker_box facing north 8218 white_shulker_box facing east 8219 white_shulker_box facing south 8220 white_shulker_box facing west 8221 white_shulker_box facing up 8222 white_shulker_box facing down 8223 orange_shulker_box facing north 8224 orange_shulker_box facing east 8225 orange_shulker_box facing south 8226 orange_shulker_box facing west 8227 orange_shulker_box facing up 8228 orange_shulker_box facing down 8229 magenta_shulker_box facing north 8230 magenta_shulker_box facing east 8231 magenta_shulker_box facing south 8232 magenta_shulker_box facing west 8233 magenta_shulker_box facing up 8234 magenta_shulker_box facing down 8235 light_blue_shulker_box facing north 8236 light_blue_shulker_box facing east 8237 light_blue_shulker_box facing south 8238 light_blue_shulker_box facing west 8239 light_blue_shulker_box facing up 8240 light_blue_shulker_box facing down 8241 yellow_shulker_box facing north 8242 yellow_shulker_box facing east 8243 yellow_shulker_box facing south 8244 yellow_shulker_box facing west 8245 yellow_shulker_box facing up 8246 yellow_shulker_box facing down 8247 lime_shulker_box facing north 8248 lime_shulker_box facing east 8249 lime_shulker_box facing south 8250 lime_shulker_box facing west 8251 lime_shulker_box facing up 8252 lime_shulker_box facing down 8253 pink_shulker_box facing north 8254 pink_shulker_box facing east 8255 pink_shulker_box facing south 8256 pink_shulker_box facing west 8257 pink_shulker_box facing up 8258 pink_shulker_box facing down 8259 gray_shulker_box facing north 8260 gray_shulker_box facing east 8261 gray_shulker_box facing south 8262 gray_shulker_box facing west 8263 gray_shulker_box facing up 8264 gray_shulker_box facing down 8265 light_gray_shulker_box facing north 8266 light_gray_shulker_box facing east 8267 light_gray_shulker_box facing south 8268 light_gray_shulker_box facing west 8269 light_gray_shulker_box facing up 8270 light_gray_shulker_box facing down 8271 cyan_shulker_box facing north 8272 cyan_shulker_box facing east 8273 cyan_shulker_box facing south 8274 cyan_shulker_box facing west 8275 cyan_shulker_box facing up 8276 cyan_shulker_box facing down 8277 purple_shulker_box facing north 8278 purple_shulker_box facing east 8279 purple_shulker_box facing south 8280 purple_shulker_box facing west 8281 purple_shulker_box facing up 8282 purple_shulker_box facing down 8283 blue_shulker_box facing north 8284 blue_shulker_box facing east 8285 blue_shulker_box facing south 8286 blue_shulker_box facing west 8287 blue_shulker_box facing up 8288 blue_shulker_box facing down 8289 brown_shulker_box facing north 8290 brown_shulker_box facing east 8291 brown_shulker_box facing south 8292 brown_shulker_box facing west 8293 brown_shulker_box facing up 8294 brown_shulker_box facing down 8295 green_shulker_box facing north 8296 green_shulker_box facing east 8297 green_shulker_box facing south 8298 green_shulker_box facing west 8299 green_shulker_box facing up 8300 green_shulker_box facing down 8301 red_shulker_box facing north 8302 red_shulker_box facing east 8303 red_shulker_box facing south 8304 red_shulker_box facing west 8305 red_shulker_box facing up 8306 red_shulker_box facing down 8307 black_shulker_box facing north 8308 black_shulker_box facing east 8309 black_shulker_box facing south 8310 black_shulker_box facing west 8311 black_shulker_box facing up 8312 black_shulker_box facing down 8313 white_glazed_terracotta facing north 8314 white_glazed_terracotta facing south 8315 white_glazed_terracotta facing west 8316 white_glazed_terracotta facing east 8317 orange_glazed_terracotta facing north 8318 orange_glazed_terracotta facing south 8319 orange_glazed_terracotta facing west 8320 orange_glazed_terracotta facing east 8321 magenta_glazed_terracotta facing north 8322 magenta_glazed_terracotta facing south 8323 magenta_glazed_terracotta facing west 8324 magenta_glazed_terracotta facing east 8325 light_blue_glazed_terracotta facing north 8326 light_blue_glazed_terracotta facing south 8327 light_blue_glazed_terracotta facing west 8328 light_blue_glazed_terracotta facing east 8329 yellow_glazed_terracotta facing north 8330 yellow_glazed_terracotta facing south 8331 yellow_glazed_terracotta facing west 8332 yellow_glazed_terracotta facing east 8333 lime_glazed_terracotta facing north 8334 lime_glazed_terracotta facing south 8335 lime_glazed_terracotta facing west 8336 lime_glazed_terracotta facing east 8337 pink_glazed_terracotta facing north 8338 pink_glazed_terracotta facing south 8339 pink_glazed_terracotta facing west 8340 pink_glazed_terracotta facing east 8341 gray_glazed_terracotta facing north 8342 gray_glazed_terracotta facing south 8343 gray_glazed_terracotta facing west 8344 gray_glazed_terracotta facing east 8345 light_gray_glazed_terracotta facing north 8346 light_gray_glazed_terracotta facing south 8347 light_gray_glazed_terracotta facing west 8348 light_gray_glazed_terracotta facing east 8349 cyan_glazed_terracotta facing north 8350 cyan_glazed_terracotta facing south 8351 cyan_glazed_terracotta facing west 8352 cyan_glazed_terracotta facing east 8353 purple_glazed_terracotta facing north 8354 purple_glazed_terracotta facing south 8355 purple_glazed_terracotta facing west 8356 purple_glazed_terracotta facing east 8357 blue_glazed_terracotta facing north 8358 blue_glazed_terracotta facing south 8359 blue_glazed_terracotta facing west 8360 blue_glazed_terracotta facing east 8361 brown_glazed_terracotta facing north 8362 brown_glazed_terracotta facing south 8363 brown_glazed_terracotta facing west 8364 brown_glazed_terracotta facing east 8365 green_glazed_terracotta facing north 8366 green_glazed_terracotta facing south 8367 green_glazed_terracotta facing west 8368 green_glazed_terracotta facing east 8369 red_glazed_terracotta facing north 8370 red_glazed_terracotta facing south 8371 red_glazed_terracotta facing west 8372 red_glazed_terracotta facing east 8373 black_glazed_terracotta facing north 8374 black_glazed_terracotta facing south 8375 black_glazed_terracotta facing west 8376 black_glazed_terracotta facing east 8377 white_concrete 8378 orange_concrete 8379 magenta_concrete 8380 light_blue_concrete 8381 yellow_concrete 8382 lime_concrete 8383 pink_concrete 8384 gray_concrete 8385 light_gray_concrete 8386 cyan_concrete 8387 purple_concrete 8388 blue_concrete 8389 brown_concrete 8390 green_concrete 8391 red_concrete 8392 black_concrete 8393 white_concrete_powder 8394 orange_concrete_powder 8395 magenta_concrete_powder 8396 light_blue_concrete_powder 8397 yellow_concrete_powder 8398 lime_concrete_powder 8399 pink_concrete_powder 8400 gray_concrete_powder 8401 light_gray_concrete_powder 8402 cyan_concrete_powder 8403 purple_concrete_powder 8404 blue_concrete_powder 8405 brown_concrete_powder 8406 green_concrete_powder 8407 red_concrete_powder 8408 black_concrete_powder 8409 kelp age 0 8410 kelp age 1 8411 kelp age 2 8412 kelp age 3 8413 kelp age 4 8414 kelp age 5 8415 kelp age 6 8416 kelp age 7 8417 kelp age 8 8418 kelp age 9 8419 kelp age 10 8420 kelp age 11 8421 kelp age 12 8422 kelp age 13 8423 kelp age 14 8424 kelp age 15 8425 kelp age 16 8426 kelp age 17 8427 kelp age 18 8428 kelp age 19 8429 kelp age 20 8430 kelp age 21 8431 kelp age 22 8432 kelp age 23 8433 kelp age 24 8434 kelp age 25 8435 kelp_plant 8436 dried_kelp_block 8437 turtle_egg eggs 1 hatch 0 8438 turtle_egg eggs 1 hatch 1 8439 turtle_egg eggs 1 hatch 2 8440 turtle_egg eggs 2 hatch 0 8441 turtle_egg eggs 2 hatch 1 8442 turtle_egg eggs 2 hatch 2 8443 turtle_egg eggs 3 hatch 0 8444 turtle_egg eggs 3 hatch 1 8445 turtle_egg eggs 3 hatch 2 8446 turtle_egg eggs 4 hatch 0 8447 turtle_egg eggs 4 hatch 1 8448 turtle_egg eggs 4 hatch 2 8449 dead_tube_coral_block 8450 dead_brain_coral_block 8451 dead_bubble_coral_block 8452 dead_fire_coral_block 8453 dead_horn_coral_block 8454 tube_coral_block 8455 brain_coral_block 8456 bubble_coral_block 8457 fire_coral_block 8458 horn_coral_block 8459 tube_coral 8460 brain_coral 8461 bubble_coral 8462 fire_coral 8463 horn_coral 8464 dead_tube_coral_wall_fan facing north waterlogged true 8465 dead_tube_coral_wall_fan facing north waterlogged false 8466 dead_tube_coral_wall_fan facing south waterlogged true 8467 dead_tube_coral_wall_fan facing south waterlogged false 8468 dead_tube_coral_wall_fan facing west waterlogged true 8469 dead_tube_coral_wall_fan facing west waterlogged false 8470 dead_tube_coral_wall_fan facing east waterlogged true 8471 dead_tube_coral_wall_fan facing east waterlogged false 8472 dead_brain_coral_wall_fan facing north waterlogged true 8473 dead_brain_coral_wall_fan facing north waterlogged false 8474 dead_brain_coral_wall_fan facing south waterlogged true 8475 dead_brain_coral_wall_fan facing south waterlogged false 8476 dead_brain_coral_wall_fan facing west waterlogged true 8477 dead_brain_coral_wall_fan facing west waterlogged false 8478 dead_brain_coral_wall_fan facing east waterlogged true 8479 dead_brain_coral_wall_fan facing east waterlogged false 8480 dead_bubble_coral_wall_fan facing north waterlogged true 8481 dead_bubble_coral_wall_fan facing north waterlogged false 8482 dead_bubble_coral_wall_fan facing south waterlogged true 8483 dead_bubble_coral_wall_fan facing south waterlogged false 8484 dead_bubble_coral_wall_fan facing west waterlogged true 8485 dead_bubble_coral_wall_fan facing west waterlogged false 8486 dead_bubble_coral_wall_fan facing east waterlogged true 8487 dead_bubble_coral_wall_fan facing east waterlogged false 8488 dead_fire_coral_wall_fan facing north waterlogged true 8489 dead_fire_coral_wall_fan facing north waterlogged false 8490 dead_fire_coral_wall_fan facing south waterlogged true 8491 dead_fire_coral_wall_fan facing south waterlogged false 8492 dead_fire_coral_wall_fan facing west waterlogged true 8493 dead_fire_coral_wall_fan facing west waterlogged false 8494 dead_fire_coral_wall_fan facing east waterlogged true 8495 dead_fire_coral_wall_fan facing east waterlogged false 8496 dead_horn_coral_wall_fan facing north waterlogged true 8497 dead_horn_coral_wall_fan facing north waterlogged false 8498 dead_horn_coral_wall_fan facing south waterlogged true 8499 dead_horn_coral_wall_fan facing south waterlogged false 8500 dead_horn_coral_wall_fan facing west waterlogged true 8501 dead_horn_coral_wall_fan facing west waterlogged false 8502 dead_horn_coral_wall_fan facing east waterlogged true 8503 dead_horn_coral_wall_fan facing east waterlogged false 8504 tube_coral_wall_fan facing north waterlogged true 8505 tube_coral_wall_fan facing north waterlogged false 8506 tube_coral_wall_fan facing south waterlogged true 8507 tube_coral_wall_fan facing south waterlogged false 8508 tube_coral_wall_fan facing west waterlogged true 8509 tube_coral_wall_fan facing west waterlogged false 8510 tube_coral_wall_fan facing east waterlogged true 8511 tube_coral_wall_fan facing east waterlogged false 8512 brain_coral_wall_fan facing north waterlogged true 8513 brain_coral_wall_fan facing north waterlogged false 8514 brain_coral_wall_fan facing south waterlogged true 8515 brain_coral_wall_fan facing south waterlogged false 8516 brain_coral_wall_fan facing west waterlogged true 8517 brain_coral_wall_fan facing west waterlogged false 8518 brain_coral_wall_fan facing east waterlogged true 8519 brain_coral_wall_fan facing east waterlogged false 8520 bubble_coral_wall_fan facing north waterlogged true 8521 bubble_coral_wall_fan facing north waterlogged false 8522 bubble_coral_wall_fan facing south waterlogged true 8523 bubble_coral_wall_fan facing south waterlogged false 8524 bubble_coral_wall_fan facing west waterlogged true 8525 bubble_coral_wall_fan facing west waterlogged false 8526 bubble_coral_wall_fan facing east waterlogged true 8527 bubble_coral_wall_fan facing east waterlogged false 8528 fire_coral_wall_fan facing north waterlogged true 8529 fire_coral_wall_fan facing north waterlogged false 8530 fire_coral_wall_fan facing south waterlogged true 8531 fire_coral_wall_fan facing south waterlogged false 8532 fire_coral_wall_fan facing west waterlogged true 8533 fire_coral_wall_fan facing west waterlogged false 8534 fire_coral_wall_fan facing east waterlogged true 8535 fire_coral_wall_fan facing east waterlogged false 8536 horn_coral_wall_fan facing north waterlogged true 8537 horn_coral_wall_fan facing north waterlogged false 8538 horn_coral_wall_fan facing south waterlogged true 8539 horn_coral_wall_fan facing south waterlogged false 8540 horn_coral_wall_fan facing west waterlogged true 8541 horn_coral_wall_fan facing west waterlogged false 8542 horn_coral_wall_fan facing east waterlogged true 8543 horn_coral_wall_fan facing east waterlogged false 8544 dead_tube_coral_fan waterlogged true 8545 dead_tube_coral_fan waterlogged false 8546 dead_brain_coral_fan waterlogged true 8547 dead_brain_coral_fan waterlogged false 8548 dead_bubble_coral_fan waterlogged true 8549 dead_bubble_coral_fan waterlogged false 8550 dead_fire_coral_fan waterlogged true 8551 dead_fire_coral_fan waterlogged false 8552 dead_horn_coral_fan waterlogged true 8553 dead_horn_coral_fan waterlogged false 8554 tube_coral_fan waterlogged true 8555 tube_coral_fan waterlogged false 8556 brain_coral_fan waterlogged true 8557 brain_coral_fan waterlogged false 8558 bubble_coral_fan waterlogged true 8559 bubble_coral_fan waterlogged false 8560 fire_coral_fan waterlogged true 8561 fire_coral_fan waterlogged false 8562 horn_coral_fan waterlogged true 8563 horn_coral_fan waterlogged false 8564 sea_pickle waterlogged true pickles 1 8565 sea_pickle waterlogged false pickles 1 8566 sea_pickle waterlogged true pickles 2 8567 sea_pickle waterlogged false pickles 2 8568 sea_pickle waterlogged true pickles 3 8569 sea_pickle waterlogged false pickles 3 8570 sea_pickle waterlogged true pickles 4 8571 sea_pickle waterlogged false pickles 4 8572 blue_ice 8573 conduit 8574 void_air 8575 cave_air 8576 bubble_column drag true 8577 bubble_column drag false 8578 structure_block mode save 8579 structure_block mode load 8580 structure_block mode corner 8581 structure_block mode data ================================================ FILE: Server/Protocol/1.14.4/base.btp.txt ================================================ BlockTypePalette FileVersion 1 CommonPrefix minecraft: 0 air 1 stone 2 granite 3 polished_granite 4 diorite 5 polished_diorite 6 andesite 7 polished_andesite 8 grass_block snowy true 9 grass_block snowy false 10 dirt 11 coarse_dirt 12 podzol snowy true 13 podzol snowy false 14 cobblestone 15 oak_planks 16 spruce_planks 17 birch_planks 18 jungle_planks 19 acacia_planks 20 dark_oak_planks 21 oak_sapling stage 0 22 oak_sapling stage 1 23 spruce_sapling stage 0 24 spruce_sapling stage 1 25 birch_sapling stage 0 26 birch_sapling stage 1 27 jungle_sapling stage 0 28 jungle_sapling stage 1 29 acacia_sapling stage 0 30 acacia_sapling stage 1 31 dark_oak_sapling stage 0 32 dark_oak_sapling stage 1 33 bedrock 34 water level 0 35 water level 1 36 water level 2 37 water level 3 38 water level 4 39 water level 5 40 water level 6 41 water level 7 42 water level 8 43 water level 9 44 water level 10 45 water level 11 46 water level 12 47 water level 13 48 water level 14 49 water level 15 50 lava level 0 51 lava level 1 52 lava level 2 53 lava level 3 54 lava level 4 55 lava level 5 56 lava level 6 57 lava level 7 58 lava level 8 59 lava level 9 60 lava level 10 61 lava level 11 62 lava level 12 63 lava level 13 64 lava level 14 65 lava level 15 66 sand 67 red_sand 68 gravel 69 gold_ore 70 iron_ore 71 coal_ore 72 oak_log axis x 73 oak_log axis y 74 oak_log axis z 75 spruce_log axis x 76 spruce_log axis y 77 spruce_log axis z 78 birch_log axis x 79 birch_log axis y 80 birch_log axis z 81 jungle_log axis x 82 jungle_log axis y 83 jungle_log axis z 84 acacia_log axis x 85 acacia_log axis y 86 acacia_log axis z 87 dark_oak_log axis x 88 dark_oak_log axis y 89 dark_oak_log axis z 90 stripped_spruce_log axis x 91 stripped_spruce_log axis y 92 stripped_spruce_log axis z 93 stripped_birch_log axis x 94 stripped_birch_log axis y 95 stripped_birch_log axis z 96 stripped_jungle_log axis x 97 stripped_jungle_log axis y 98 stripped_jungle_log axis z 99 stripped_acacia_log axis x 100 stripped_acacia_log axis y 101 stripped_acacia_log axis z 102 stripped_dark_oak_log axis x 103 stripped_dark_oak_log axis y 104 stripped_dark_oak_log axis z 105 stripped_oak_log axis x 106 stripped_oak_log axis y 107 stripped_oak_log axis z 108 oak_wood axis x 109 oak_wood axis y 110 oak_wood axis z 111 spruce_wood axis x 112 spruce_wood axis y 113 spruce_wood axis z 114 birch_wood axis x 115 birch_wood axis y 116 birch_wood axis z 117 jungle_wood axis x 118 jungle_wood axis y 119 jungle_wood axis z 120 acacia_wood axis x 121 acacia_wood axis y 122 acacia_wood axis z 123 dark_oak_wood axis x 124 dark_oak_wood axis y 125 dark_oak_wood axis z 126 stripped_oak_wood axis x 127 stripped_oak_wood axis y 128 stripped_oak_wood axis z 129 stripped_spruce_wood axis x 130 stripped_spruce_wood axis y 131 stripped_spruce_wood axis z 132 stripped_birch_wood axis x 133 stripped_birch_wood axis y 134 stripped_birch_wood axis z 135 stripped_jungle_wood axis x 136 stripped_jungle_wood axis y 137 stripped_jungle_wood axis z 138 stripped_acacia_wood axis x 139 stripped_acacia_wood axis y 140 stripped_acacia_wood axis z 141 stripped_dark_oak_wood axis x 142 stripped_dark_oak_wood axis y 143 stripped_dark_oak_wood axis z 144 oak_leaves persistent true distance 1 145 oak_leaves persistent false distance 1 146 oak_leaves persistent true distance 2 147 oak_leaves persistent false distance 2 148 oak_leaves persistent true distance 3 149 oak_leaves persistent false distance 3 150 oak_leaves persistent true distance 4 151 oak_leaves persistent false distance 4 152 oak_leaves persistent true distance 5 153 oak_leaves persistent false distance 5 154 oak_leaves persistent true distance 6 155 oak_leaves persistent false distance 6 156 oak_leaves persistent true distance 7 157 oak_leaves persistent false distance 7 158 spruce_leaves persistent true distance 1 159 spruce_leaves persistent false distance 1 160 spruce_leaves persistent true distance 2 161 spruce_leaves persistent false distance 2 162 spruce_leaves persistent true distance 3 163 spruce_leaves persistent false distance 3 164 spruce_leaves persistent true distance 4 165 spruce_leaves persistent false distance 4 166 spruce_leaves persistent true distance 5 167 spruce_leaves persistent false distance 5 168 spruce_leaves persistent true distance 6 169 spruce_leaves persistent false distance 6 170 spruce_leaves persistent true distance 7 171 spruce_leaves persistent false distance 7 172 birch_leaves persistent true distance 1 173 birch_leaves persistent false distance 1 174 birch_leaves persistent true distance 2 175 birch_leaves persistent false distance 2 176 birch_leaves persistent true distance 3 177 birch_leaves persistent false distance 3 178 birch_leaves persistent true distance 4 179 birch_leaves persistent false distance 4 180 birch_leaves persistent true distance 5 181 birch_leaves persistent false distance 5 182 birch_leaves persistent true distance 6 183 birch_leaves persistent false distance 6 184 birch_leaves persistent true distance 7 185 birch_leaves persistent false distance 7 186 jungle_leaves persistent true distance 1 187 jungle_leaves persistent false distance 1 188 jungle_leaves persistent true distance 2 189 jungle_leaves persistent false distance 2 190 jungle_leaves persistent true distance 3 191 jungle_leaves persistent false distance 3 192 jungle_leaves persistent true distance 4 193 jungle_leaves persistent false distance 4 194 jungle_leaves persistent true distance 5 195 jungle_leaves persistent false distance 5 196 jungle_leaves persistent true distance 6 197 jungle_leaves persistent false distance 6 198 jungle_leaves persistent true distance 7 199 jungle_leaves persistent false distance 7 200 acacia_leaves persistent true distance 1 201 acacia_leaves persistent false distance 1 202 acacia_leaves persistent true distance 2 203 acacia_leaves persistent false distance 2 204 acacia_leaves persistent true distance 3 205 acacia_leaves persistent false distance 3 206 acacia_leaves persistent true distance 4 207 acacia_leaves persistent false distance 4 208 acacia_leaves persistent true distance 5 209 acacia_leaves persistent false distance 5 210 acacia_leaves persistent true distance 6 211 acacia_leaves persistent false distance 6 212 acacia_leaves persistent true distance 7 213 acacia_leaves persistent false distance 7 214 dark_oak_leaves persistent true distance 1 215 dark_oak_leaves persistent false distance 1 216 dark_oak_leaves persistent true distance 2 217 dark_oak_leaves persistent false distance 2 218 dark_oak_leaves persistent true distance 3 219 dark_oak_leaves persistent false distance 3 220 dark_oak_leaves persistent true distance 4 221 dark_oak_leaves persistent false distance 4 222 dark_oak_leaves persistent true distance 5 223 dark_oak_leaves persistent false distance 5 224 dark_oak_leaves persistent true distance 6 225 dark_oak_leaves persistent false distance 6 226 dark_oak_leaves persistent true distance 7 227 dark_oak_leaves persistent false distance 7 228 sponge 229 wet_sponge 230 glass 231 lapis_ore 232 lapis_block 233 dispenser facing north triggered true 234 dispenser facing north triggered false 235 dispenser facing east triggered true 236 dispenser facing east triggered false 237 dispenser facing south triggered true 238 dispenser facing south triggered false 239 dispenser facing west triggered true 240 dispenser facing west triggered false 241 dispenser facing up triggered true 242 dispenser facing up triggered false 243 dispenser facing down triggered true 244 dispenser facing down triggered false 245 sandstone 246 chiseled_sandstone 247 cut_sandstone 248 note_block instrument harp powered true note 0 249 note_block instrument harp powered false note 0 250 note_block instrument harp powered true note 1 251 note_block instrument harp powered false note 1 252 note_block instrument harp powered true note 2 253 note_block instrument harp powered false note 2 254 note_block instrument harp powered true note 3 255 note_block instrument harp powered false note 3 256 note_block instrument harp powered true note 4 257 note_block instrument harp powered false note 4 258 note_block instrument harp powered true note 5 259 note_block instrument harp powered false note 5 260 note_block instrument harp powered true note 6 261 note_block instrument harp powered false note 6 262 note_block instrument harp powered true note 7 263 note_block instrument harp powered false note 7 264 note_block instrument harp powered true note 8 265 note_block instrument harp powered false note 8 266 note_block instrument harp powered true note 9 267 note_block instrument harp powered false note 9 268 note_block instrument harp powered true note 10 269 note_block instrument harp powered false note 10 270 note_block instrument harp powered true note 11 271 note_block instrument harp powered false note 11 272 note_block instrument harp powered true note 12 273 note_block instrument harp powered false note 12 274 note_block instrument harp powered true note 13 275 note_block instrument harp powered false note 13 276 note_block instrument harp powered true note 14 277 note_block instrument harp powered false note 14 278 note_block instrument harp powered true note 15 279 note_block instrument harp powered false note 15 280 note_block instrument harp powered true note 16 281 note_block instrument harp powered false note 16 282 note_block instrument harp powered true note 17 283 note_block instrument harp powered false note 17 284 note_block instrument harp powered true note 18 285 note_block instrument harp powered false note 18 286 note_block instrument harp powered true note 19 287 note_block instrument harp powered false note 19 288 note_block instrument harp powered true note 20 289 note_block instrument harp powered false note 20 290 note_block instrument harp powered true note 21 291 note_block instrument harp powered false note 21 292 note_block instrument harp powered true note 22 293 note_block instrument harp powered false note 22 294 note_block instrument harp powered true note 23 295 note_block instrument harp powered false note 23 296 note_block instrument harp powered true note 24 297 note_block instrument harp powered false note 24 298 note_block instrument basedrum powered true note 0 299 note_block instrument basedrum powered false note 0 300 note_block instrument basedrum powered true note 1 301 note_block instrument basedrum powered false note 1 302 note_block instrument basedrum powered true note 2 303 note_block instrument basedrum powered false note 2 304 note_block instrument basedrum powered true note 3 305 note_block instrument basedrum powered false note 3 306 note_block instrument basedrum powered true note 4 307 note_block instrument basedrum powered false note 4 308 note_block instrument basedrum powered true note 5 309 note_block instrument basedrum powered false note 5 310 note_block instrument basedrum powered true note 6 311 note_block instrument basedrum powered false note 6 312 note_block instrument basedrum powered true note 7 313 note_block instrument basedrum powered false note 7 314 note_block instrument basedrum powered true note 8 315 note_block instrument basedrum powered false note 8 316 note_block instrument basedrum powered true note 9 317 note_block instrument basedrum powered false note 9 318 note_block instrument basedrum powered true note 10 319 note_block instrument basedrum powered false note 10 320 note_block instrument basedrum powered true note 11 321 note_block instrument basedrum powered false note 11 322 note_block instrument basedrum powered true note 12 323 note_block instrument basedrum powered false note 12 324 note_block instrument basedrum powered true note 13 325 note_block instrument basedrum powered false note 13 326 note_block instrument basedrum powered true note 14 327 note_block instrument basedrum powered false note 14 328 note_block instrument basedrum powered true note 15 329 note_block instrument basedrum powered false note 15 330 note_block instrument basedrum powered true note 16 331 note_block instrument basedrum powered false note 16 332 note_block instrument basedrum powered true note 17 333 note_block instrument basedrum powered false note 17 334 note_block instrument basedrum powered true note 18 335 note_block instrument basedrum powered false note 18 336 note_block instrument basedrum powered true note 19 337 note_block instrument basedrum powered false note 19 338 note_block instrument basedrum powered true note 20 339 note_block instrument basedrum powered false note 20 340 note_block instrument basedrum powered true note 21 341 note_block instrument basedrum powered false note 21 342 note_block instrument basedrum powered true note 22 343 note_block instrument basedrum powered false note 22 344 note_block instrument basedrum powered true note 23 345 note_block instrument basedrum powered false note 23 346 note_block instrument basedrum powered true note 24 347 note_block instrument basedrum powered false note 24 348 note_block instrument snare powered true note 0 349 note_block instrument snare powered false note 0 350 note_block instrument snare powered true note 1 351 note_block instrument snare powered false note 1 352 note_block instrument snare powered true note 2 353 note_block instrument snare powered false note 2 354 note_block instrument snare powered true note 3 355 note_block instrument snare powered false note 3 356 note_block instrument snare powered true note 4 357 note_block instrument snare powered false note 4 358 note_block instrument snare powered true note 5 359 note_block instrument snare powered false note 5 360 note_block instrument snare powered true note 6 361 note_block instrument snare powered false note 6 362 note_block instrument snare powered true note 7 363 note_block instrument snare powered false note 7 364 note_block instrument snare powered true note 8 365 note_block instrument snare powered false note 8 366 note_block instrument snare powered true note 9 367 note_block instrument snare powered false note 9 368 note_block instrument snare powered true note 10 369 note_block instrument snare powered false note 10 370 note_block instrument snare powered true note 11 371 note_block instrument snare powered false note 11 372 note_block instrument snare powered true note 12 373 note_block instrument snare powered false note 12 374 note_block instrument snare powered true note 13 375 note_block instrument snare powered false note 13 376 note_block instrument snare powered true note 14 377 note_block instrument snare powered false note 14 378 note_block instrument snare powered true note 15 379 note_block instrument snare powered false note 15 380 note_block instrument snare powered true note 16 381 note_block instrument snare powered false note 16 382 note_block instrument snare powered true note 17 383 note_block instrument snare powered false note 17 384 note_block instrument snare powered true note 18 385 note_block instrument snare powered false note 18 386 note_block instrument snare powered true note 19 387 note_block instrument snare powered false note 19 388 note_block instrument snare powered true note 20 389 note_block instrument snare powered false note 20 390 note_block instrument snare powered true note 21 391 note_block instrument snare powered false note 21 392 note_block instrument snare powered true note 22 393 note_block instrument snare powered false note 22 394 note_block instrument snare powered true note 23 395 note_block instrument snare powered false note 23 396 note_block instrument snare powered true note 24 397 note_block instrument snare powered false note 24 398 note_block instrument hat powered true note 0 399 note_block instrument hat powered false note 0 400 note_block instrument hat powered true note 1 401 note_block instrument hat powered false note 1 402 note_block instrument hat powered true note 2 403 note_block instrument hat powered false note 2 404 note_block instrument hat powered true note 3 405 note_block instrument hat powered false note 3 406 note_block instrument hat powered true note 4 407 note_block instrument hat powered false note 4 408 note_block instrument hat powered true note 5 409 note_block instrument hat powered false note 5 410 note_block instrument hat powered true note 6 411 note_block instrument hat powered false note 6 412 note_block instrument hat powered true note 7 413 note_block instrument hat powered false note 7 414 note_block instrument hat powered true note 8 415 note_block instrument hat powered false note 8 416 note_block instrument hat powered true note 9 417 note_block instrument hat powered false note 9 418 note_block instrument hat powered true note 10 419 note_block instrument hat powered false note 10 420 note_block instrument hat powered true note 11 421 note_block instrument hat powered false note 11 422 note_block instrument hat powered true note 12 423 note_block instrument hat powered false note 12 424 note_block instrument hat powered true note 13 425 note_block instrument hat powered false note 13 426 note_block instrument hat powered true note 14 427 note_block instrument hat powered false note 14 428 note_block instrument hat powered true note 15 429 note_block instrument hat powered false note 15 430 note_block instrument hat powered true note 16 431 note_block instrument hat powered false note 16 432 note_block instrument hat powered true note 17 433 note_block instrument hat powered false note 17 434 note_block instrument hat powered true note 18 435 note_block instrument hat powered false note 18 436 note_block instrument hat powered true note 19 437 note_block instrument hat powered false note 19 438 note_block instrument hat powered true note 20 439 note_block instrument hat powered false note 20 440 note_block instrument hat powered true note 21 441 note_block instrument hat powered false note 21 442 note_block instrument hat powered true note 22 443 note_block instrument hat powered false note 22 444 note_block instrument hat powered true note 23 445 note_block instrument hat powered false note 23 446 note_block instrument hat powered true note 24 447 note_block instrument hat powered false note 24 448 note_block instrument bass powered true note 0 449 note_block instrument bass powered false note 0 450 note_block instrument bass powered true note 1 451 note_block instrument bass powered false note 1 452 note_block instrument bass powered true note 2 453 note_block instrument bass powered false note 2 454 note_block instrument bass powered true note 3 455 note_block instrument bass powered false note 3 456 note_block instrument bass powered true note 4 457 note_block instrument bass powered false note 4 458 note_block instrument bass powered true note 5 459 note_block instrument bass powered false note 5 460 note_block instrument bass powered true note 6 461 note_block instrument bass powered false note 6 462 note_block instrument bass powered true note 7 463 note_block instrument bass powered false note 7 464 note_block instrument bass powered true note 8 465 note_block instrument bass powered false note 8 466 note_block instrument bass powered true note 9 467 note_block instrument bass powered false note 9 468 note_block instrument bass powered true note 10 469 note_block instrument bass powered false note 10 470 note_block instrument bass powered true note 11 471 note_block instrument bass powered false note 11 472 note_block instrument bass powered true note 12 473 note_block instrument bass powered false note 12 474 note_block instrument bass powered true note 13 475 note_block instrument bass powered false note 13 476 note_block instrument bass powered true note 14 477 note_block instrument bass powered false note 14 478 note_block instrument bass powered true note 15 479 note_block instrument bass powered false note 15 480 note_block instrument bass powered true note 16 481 note_block instrument bass powered false note 16 482 note_block instrument bass powered true note 17 483 note_block instrument bass powered false note 17 484 note_block instrument bass powered true note 18 485 note_block instrument bass powered false note 18 486 note_block instrument bass powered true note 19 487 note_block instrument bass powered false note 19 488 note_block instrument bass powered true note 20 489 note_block instrument bass powered false note 20 490 note_block instrument bass powered true note 21 491 note_block instrument bass powered false note 21 492 note_block instrument bass powered true note 22 493 note_block instrument bass powered false note 22 494 note_block instrument bass powered true note 23 495 note_block instrument bass powered false note 23 496 note_block instrument bass powered true note 24 497 note_block instrument bass powered false note 24 498 note_block instrument flute powered true note 0 499 note_block instrument flute powered false note 0 500 note_block instrument flute powered true note 1 501 note_block instrument flute powered false note 1 502 note_block instrument flute powered true note 2 503 note_block instrument flute powered false note 2 504 note_block instrument flute powered true note 3 505 note_block instrument flute powered false note 3 506 note_block instrument flute powered true note 4 507 note_block instrument flute powered false note 4 508 note_block instrument flute powered true note 5 509 note_block instrument flute powered false note 5 510 note_block instrument flute powered true note 6 511 note_block instrument flute powered false note 6 512 note_block instrument flute powered true note 7 513 note_block instrument flute powered false note 7 514 note_block instrument flute powered true note 8 515 note_block instrument flute powered false note 8 516 note_block instrument flute powered true note 9 517 note_block instrument flute powered false note 9 518 note_block instrument flute powered true note 10 519 note_block instrument flute powered false note 10 520 note_block instrument flute powered true note 11 521 note_block instrument flute powered false note 11 522 note_block instrument flute powered true note 12 523 note_block instrument flute powered false note 12 524 note_block instrument flute powered true note 13 525 note_block instrument flute powered false note 13 526 note_block instrument flute powered true note 14 527 note_block instrument flute powered false note 14 528 note_block instrument flute powered true note 15 529 note_block instrument flute powered false note 15 530 note_block instrument flute powered true note 16 531 note_block instrument flute powered false note 16 532 note_block instrument flute powered true note 17 533 note_block instrument flute powered false note 17 534 note_block instrument flute powered true note 18 535 note_block instrument flute powered false note 18 536 note_block instrument flute powered true note 19 537 note_block instrument flute powered false note 19 538 note_block instrument flute powered true note 20 539 note_block instrument flute powered false note 20 540 note_block instrument flute powered true note 21 541 note_block instrument flute powered false note 21 542 note_block instrument flute powered true note 22 543 note_block instrument flute powered false note 22 544 note_block instrument flute powered true note 23 545 note_block instrument flute powered false note 23 546 note_block instrument flute powered true note 24 547 note_block instrument flute powered false note 24 548 note_block instrument bell powered true note 0 549 note_block instrument bell powered false note 0 550 note_block instrument bell powered true note 1 551 note_block instrument bell powered false note 1 552 note_block instrument bell powered true note 2 553 note_block instrument bell powered false note 2 554 note_block instrument bell powered true note 3 555 note_block instrument bell powered false note 3 556 note_block instrument bell powered true note 4 557 note_block instrument bell powered false note 4 558 note_block instrument bell powered true note 5 559 note_block instrument bell powered false note 5 560 note_block instrument bell powered true note 6 561 note_block instrument bell powered false note 6 562 note_block instrument bell powered true note 7 563 note_block instrument bell powered false note 7 564 note_block instrument bell powered true note 8 565 note_block instrument bell powered false note 8 566 note_block instrument bell powered true note 9 567 note_block instrument bell powered false note 9 568 note_block instrument bell powered true note 10 569 note_block instrument bell powered false note 10 570 note_block instrument bell powered true note 11 571 note_block instrument bell powered false note 11 572 note_block instrument bell powered true note 12 573 note_block instrument bell powered false note 12 574 note_block instrument bell powered true note 13 575 note_block instrument bell powered false note 13 576 note_block instrument bell powered true note 14 577 note_block instrument bell powered false note 14 578 note_block instrument bell powered true note 15 579 note_block instrument bell powered false note 15 580 note_block instrument bell powered true note 16 581 note_block instrument bell powered false note 16 582 note_block instrument bell powered true note 17 583 note_block instrument bell powered false note 17 584 note_block instrument bell powered true note 18 585 note_block instrument bell powered false note 18 586 note_block instrument bell powered true note 19 587 note_block instrument bell powered false note 19 588 note_block instrument bell powered true note 20 589 note_block instrument bell powered false note 20 590 note_block instrument bell powered true note 21 591 note_block instrument bell powered false note 21 592 note_block instrument bell powered true note 22 593 note_block instrument bell powered false note 22 594 note_block instrument bell powered true note 23 595 note_block instrument bell powered false note 23 596 note_block instrument bell powered true note 24 597 note_block instrument bell powered false note 24 598 note_block instrument guitar powered true note 0 599 note_block instrument guitar powered false note 0 600 note_block instrument guitar powered true note 1 601 note_block instrument guitar powered false note 1 602 note_block instrument guitar powered true note 2 603 note_block instrument guitar powered false note 2 604 note_block instrument guitar powered true note 3 605 note_block instrument guitar powered false note 3 606 note_block instrument guitar powered true note 4 607 note_block instrument guitar powered false note 4 608 note_block instrument guitar powered true note 5 609 note_block instrument guitar powered false note 5 610 note_block instrument guitar powered true note 6 611 note_block instrument guitar powered false note 6 612 note_block instrument guitar powered true note 7 613 note_block instrument guitar powered false note 7 614 note_block instrument guitar powered true note 8 615 note_block instrument guitar powered false note 8 616 note_block instrument guitar powered true note 9 617 note_block instrument guitar powered false note 9 618 note_block instrument guitar powered true note 10 619 note_block instrument guitar powered false note 10 620 note_block instrument guitar powered true note 11 621 note_block instrument guitar powered false note 11 622 note_block instrument guitar powered true note 12 623 note_block instrument guitar powered false note 12 624 note_block instrument guitar powered true note 13 625 note_block instrument guitar powered false note 13 626 note_block instrument guitar powered true note 14 627 note_block instrument guitar powered false note 14 628 note_block instrument guitar powered true note 15 629 note_block instrument guitar powered false note 15 630 note_block instrument guitar powered true note 16 631 note_block instrument guitar powered false note 16 632 note_block instrument guitar powered true note 17 633 note_block instrument guitar powered false note 17 634 note_block instrument guitar powered true note 18 635 note_block instrument guitar powered false note 18 636 note_block instrument guitar powered true note 19 637 note_block instrument guitar powered false note 19 638 note_block instrument guitar powered true note 20 639 note_block instrument guitar powered false note 20 640 note_block instrument guitar powered true note 21 641 note_block instrument guitar powered false note 21 642 note_block instrument guitar powered true note 22 643 note_block instrument guitar powered false note 22 644 note_block instrument guitar powered true note 23 645 note_block instrument guitar powered false note 23 646 note_block instrument guitar powered true note 24 647 note_block instrument guitar powered false note 24 648 note_block instrument chime powered true note 0 649 note_block instrument chime powered false note 0 650 note_block instrument chime powered true note 1 651 note_block instrument chime powered false note 1 652 note_block instrument chime powered true note 2 653 note_block instrument chime powered false note 2 654 note_block instrument chime powered true note 3 655 note_block instrument chime powered false note 3 656 note_block instrument chime powered true note 4 657 note_block instrument chime powered false note 4 658 note_block instrument chime powered true note 5 659 note_block instrument chime powered false note 5 660 note_block instrument chime powered true note 6 661 note_block instrument chime powered false note 6 662 note_block instrument chime powered true note 7 663 note_block instrument chime powered false note 7 664 note_block instrument chime powered true note 8 665 note_block instrument chime powered false note 8 666 note_block instrument chime powered true note 9 667 note_block instrument chime powered false note 9 668 note_block instrument chime powered true note 10 669 note_block instrument chime powered false note 10 670 note_block instrument chime powered true note 11 671 note_block instrument chime powered false note 11 672 note_block instrument chime powered true note 12 673 note_block instrument chime powered false note 12 674 note_block instrument chime powered true note 13 675 note_block instrument chime powered false note 13 676 note_block instrument chime powered true note 14 677 note_block instrument chime powered false note 14 678 note_block instrument chime powered true note 15 679 note_block instrument chime powered false note 15 680 note_block instrument chime powered true note 16 681 note_block instrument chime powered false note 16 682 note_block instrument chime powered true note 17 683 note_block instrument chime powered false note 17 684 note_block instrument chime powered true note 18 685 note_block instrument chime powered false note 18 686 note_block instrument chime powered true note 19 687 note_block instrument chime powered false note 19 688 note_block instrument chime powered true note 20 689 note_block instrument chime powered false note 20 690 note_block instrument chime powered true note 21 691 note_block instrument chime powered false note 21 692 note_block instrument chime powered true note 22 693 note_block instrument chime powered false note 22 694 note_block instrument chime powered true note 23 695 note_block instrument chime powered false note 23 696 note_block instrument chime powered true note 24 697 note_block instrument chime powered false note 24 698 note_block instrument xylophone powered true note 0 699 note_block instrument xylophone powered false note 0 700 note_block instrument xylophone powered true note 1 701 note_block instrument xylophone powered false note 1 702 note_block instrument xylophone powered true note 2 703 note_block instrument xylophone powered false note 2 704 note_block instrument xylophone powered true note 3 705 note_block instrument xylophone powered false note 3 706 note_block instrument xylophone powered true note 4 707 note_block instrument xylophone powered false note 4 708 note_block instrument xylophone powered true note 5 709 note_block instrument xylophone powered false note 5 710 note_block instrument xylophone powered true note 6 711 note_block instrument xylophone powered false note 6 712 note_block instrument xylophone powered true note 7 713 note_block instrument xylophone powered false note 7 714 note_block instrument xylophone powered true note 8 715 note_block instrument xylophone powered false note 8 716 note_block instrument xylophone powered true note 9 717 note_block instrument xylophone powered false note 9 718 note_block instrument xylophone powered true note 10 719 note_block instrument xylophone powered false note 10 720 note_block instrument xylophone powered true note 11 721 note_block instrument xylophone powered false note 11 722 note_block instrument xylophone powered true note 12 723 note_block instrument xylophone powered false note 12 724 note_block instrument xylophone powered true note 13 725 note_block instrument xylophone powered false note 13 726 note_block instrument xylophone powered true note 14 727 note_block instrument xylophone powered false note 14 728 note_block instrument xylophone powered true note 15 729 note_block instrument xylophone powered false note 15 730 note_block instrument xylophone powered true note 16 731 note_block instrument xylophone powered false note 16 732 note_block instrument xylophone powered true note 17 733 note_block instrument xylophone powered false note 17 734 note_block instrument xylophone powered true note 18 735 note_block instrument xylophone powered false note 18 736 note_block instrument xylophone powered true note 19 737 note_block instrument xylophone powered false note 19 738 note_block instrument xylophone powered true note 20 739 note_block instrument xylophone powered false note 20 740 note_block instrument xylophone powered true note 21 741 note_block instrument xylophone powered false note 21 742 note_block instrument xylophone powered true note 22 743 note_block instrument xylophone powered false note 22 744 note_block instrument xylophone powered true note 23 745 note_block instrument xylophone powered false note 23 746 note_block instrument xylophone powered true note 24 747 note_block instrument xylophone powered false note 24 748 note_block instrument iron_xylophone powered true note 0 749 note_block instrument iron_xylophone powered false note 0 750 note_block instrument iron_xylophone powered true note 1 751 note_block instrument iron_xylophone powered false note 1 752 note_block instrument iron_xylophone powered true note 2 753 note_block instrument iron_xylophone powered false note 2 754 note_block instrument iron_xylophone powered true note 3 755 note_block instrument iron_xylophone powered false note 3 756 note_block instrument iron_xylophone powered true note 4 757 note_block instrument iron_xylophone powered false note 4 758 note_block instrument iron_xylophone powered true note 5 759 note_block instrument iron_xylophone powered false note 5 760 note_block instrument iron_xylophone powered true note 6 761 note_block instrument iron_xylophone powered false note 6 762 note_block instrument iron_xylophone powered true note 7 763 note_block instrument iron_xylophone powered false note 7 764 note_block instrument iron_xylophone powered true note 8 765 note_block instrument iron_xylophone powered false note 8 766 note_block instrument iron_xylophone powered true note 9 767 note_block instrument iron_xylophone powered false note 9 768 note_block instrument iron_xylophone powered true note 10 769 note_block instrument iron_xylophone powered false note 10 770 note_block instrument iron_xylophone powered true note 11 771 note_block instrument iron_xylophone powered false note 11 772 note_block instrument iron_xylophone powered true note 12 773 note_block instrument iron_xylophone powered false note 12 774 note_block instrument iron_xylophone powered true note 13 775 note_block instrument iron_xylophone powered false note 13 776 note_block instrument iron_xylophone powered true note 14 777 note_block instrument iron_xylophone powered false note 14 778 note_block instrument iron_xylophone powered true note 15 779 note_block instrument iron_xylophone powered false note 15 780 note_block instrument iron_xylophone powered true note 16 781 note_block instrument iron_xylophone powered false note 16 782 note_block instrument iron_xylophone powered true note 17 783 note_block instrument iron_xylophone powered false note 17 784 note_block instrument iron_xylophone powered true note 18 785 note_block instrument iron_xylophone powered false note 18 786 note_block instrument iron_xylophone powered true note 19 787 note_block instrument iron_xylophone powered false note 19 788 note_block instrument iron_xylophone powered true note 20 789 note_block instrument iron_xylophone powered false note 20 790 note_block instrument iron_xylophone powered true note 21 791 note_block instrument iron_xylophone powered false note 21 792 note_block instrument iron_xylophone powered true note 22 793 note_block instrument iron_xylophone powered false note 22 794 note_block instrument iron_xylophone powered true note 23 795 note_block instrument iron_xylophone powered false note 23 796 note_block instrument iron_xylophone powered true note 24 797 note_block instrument iron_xylophone powered false note 24 798 note_block instrument cow_bell powered true note 0 799 note_block instrument cow_bell powered false note 0 800 note_block instrument cow_bell powered true note 1 801 note_block instrument cow_bell powered false note 1 802 note_block instrument cow_bell powered true note 2 803 note_block instrument cow_bell powered false note 2 804 note_block instrument cow_bell powered true note 3 805 note_block instrument cow_bell powered false note 3 806 note_block instrument cow_bell powered true note 4 807 note_block instrument cow_bell powered false note 4 808 note_block instrument cow_bell powered true note 5 809 note_block instrument cow_bell powered false note 5 810 note_block instrument cow_bell powered true note 6 811 note_block instrument cow_bell powered false note 6 812 note_block instrument cow_bell powered true note 7 813 note_block instrument cow_bell powered false note 7 814 note_block instrument cow_bell powered true note 8 815 note_block instrument cow_bell powered false note 8 816 note_block instrument cow_bell powered true note 9 817 note_block instrument cow_bell powered false note 9 818 note_block instrument cow_bell powered true note 10 819 note_block instrument cow_bell powered false note 10 820 note_block instrument cow_bell powered true note 11 821 note_block instrument cow_bell powered false note 11 822 note_block instrument cow_bell powered true note 12 823 note_block instrument cow_bell powered false note 12 824 note_block instrument cow_bell powered true note 13 825 note_block instrument cow_bell powered false note 13 826 note_block instrument cow_bell powered true note 14 827 note_block instrument cow_bell powered false note 14 828 note_block instrument cow_bell powered true note 15 829 note_block instrument cow_bell powered false note 15 830 note_block instrument cow_bell powered true note 16 831 note_block instrument cow_bell powered false note 16 832 note_block instrument cow_bell powered true note 17 833 note_block instrument cow_bell powered false note 17 834 note_block instrument cow_bell powered true note 18 835 note_block instrument cow_bell powered false note 18 836 note_block instrument cow_bell powered true note 19 837 note_block instrument cow_bell powered false note 19 838 note_block instrument cow_bell powered true note 20 839 note_block instrument cow_bell powered false note 20 840 note_block instrument cow_bell powered true note 21 841 note_block instrument cow_bell powered false note 21 842 note_block instrument cow_bell powered true note 22 843 note_block instrument cow_bell powered false note 22 844 note_block instrument cow_bell powered true note 23 845 note_block instrument cow_bell powered false note 23 846 note_block instrument cow_bell powered true note 24 847 note_block instrument cow_bell powered false note 24 848 note_block instrument didgeridoo powered true note 0 849 note_block instrument didgeridoo powered false note 0 850 note_block instrument didgeridoo powered true note 1 851 note_block instrument didgeridoo powered false note 1 852 note_block instrument didgeridoo powered true note 2 853 note_block instrument didgeridoo powered false note 2 854 note_block instrument didgeridoo powered true note 3 855 note_block instrument didgeridoo powered false note 3 856 note_block instrument didgeridoo powered true note 4 857 note_block instrument didgeridoo powered false note 4 858 note_block instrument didgeridoo powered true note 5 859 note_block instrument didgeridoo powered false note 5 860 note_block instrument didgeridoo powered true note 6 861 note_block instrument didgeridoo powered false note 6 862 note_block instrument didgeridoo powered true note 7 863 note_block instrument didgeridoo powered false note 7 864 note_block instrument didgeridoo powered true note 8 865 note_block instrument didgeridoo powered false note 8 866 note_block instrument didgeridoo powered true note 9 867 note_block instrument didgeridoo powered false note 9 868 note_block instrument didgeridoo powered true note 10 869 note_block instrument didgeridoo powered false note 10 870 note_block instrument didgeridoo powered true note 11 871 note_block instrument didgeridoo powered false note 11 872 note_block instrument didgeridoo powered true note 12 873 note_block instrument didgeridoo powered false note 12 874 note_block instrument didgeridoo powered true note 13 875 note_block instrument didgeridoo powered false note 13 876 note_block instrument didgeridoo powered true note 14 877 note_block instrument didgeridoo powered false note 14 878 note_block instrument didgeridoo powered true note 15 879 note_block instrument didgeridoo powered false note 15 880 note_block instrument didgeridoo powered true note 16 881 note_block instrument didgeridoo powered false note 16 882 note_block instrument didgeridoo powered true note 17 883 note_block instrument didgeridoo powered false note 17 884 note_block instrument didgeridoo powered true note 18 885 note_block instrument didgeridoo powered false note 18 886 note_block instrument didgeridoo powered true note 19 887 note_block instrument didgeridoo powered false note 19 888 note_block instrument didgeridoo powered true note 20 889 note_block instrument didgeridoo powered false note 20 890 note_block instrument didgeridoo powered true note 21 891 note_block instrument didgeridoo powered false note 21 892 note_block instrument didgeridoo powered true note 22 893 note_block instrument didgeridoo powered false note 22 894 note_block instrument didgeridoo powered true note 23 895 note_block instrument didgeridoo powered false note 23 896 note_block instrument didgeridoo powered true note 24 897 note_block instrument didgeridoo powered false note 24 898 note_block instrument bit powered true note 0 899 note_block instrument bit powered false note 0 900 note_block instrument bit powered true note 1 901 note_block instrument bit powered false note 1 902 note_block instrument bit powered true note 2 903 note_block instrument bit powered false note 2 904 note_block instrument bit powered true note 3 905 note_block instrument bit powered false note 3 906 note_block instrument bit powered true note 4 907 note_block instrument bit powered false note 4 908 note_block instrument bit powered true note 5 909 note_block instrument bit powered false note 5 910 note_block instrument bit powered true note 6 911 note_block instrument bit powered false note 6 912 note_block instrument bit powered true note 7 913 note_block instrument bit powered false note 7 914 note_block instrument bit powered true note 8 915 note_block instrument bit powered false note 8 916 note_block instrument bit powered true note 9 917 note_block instrument bit powered false note 9 918 note_block instrument bit powered true note 10 919 note_block instrument bit powered false note 10 920 note_block instrument bit powered true note 11 921 note_block instrument bit powered false note 11 922 note_block instrument bit powered true note 12 923 note_block instrument bit powered false note 12 924 note_block instrument bit powered true note 13 925 note_block instrument bit powered false note 13 926 note_block instrument bit powered true note 14 927 note_block instrument bit powered false note 14 928 note_block instrument bit powered true note 15 929 note_block instrument bit powered false note 15 930 note_block instrument bit powered true note 16 931 note_block instrument bit powered false note 16 932 note_block instrument bit powered true note 17 933 note_block instrument bit powered false note 17 934 note_block instrument bit powered true note 18 935 note_block instrument bit powered false note 18 936 note_block instrument bit powered true note 19 937 note_block instrument bit powered false note 19 938 note_block instrument bit powered true note 20 939 note_block instrument bit powered false note 20 940 note_block instrument bit powered true note 21 941 note_block instrument bit powered false note 21 942 note_block instrument bit powered true note 22 943 note_block instrument bit powered false note 22 944 note_block instrument bit powered true note 23 945 note_block instrument bit powered false note 23 946 note_block instrument bit powered true note 24 947 note_block instrument bit powered false note 24 948 note_block instrument banjo powered true note 0 949 note_block instrument banjo powered false note 0 950 note_block instrument banjo powered true note 1 951 note_block instrument banjo powered false note 1 952 note_block instrument banjo powered true note 2 953 note_block instrument banjo powered false note 2 954 note_block instrument banjo powered true note 3 955 note_block instrument banjo powered false note 3 956 note_block instrument banjo powered true note 4 957 note_block instrument banjo powered false note 4 958 note_block instrument banjo powered true note 5 959 note_block instrument banjo powered false note 5 960 note_block instrument banjo powered true note 6 961 note_block instrument banjo powered false note 6 962 note_block instrument banjo powered true note 7 963 note_block instrument banjo powered false note 7 964 note_block instrument banjo powered true note 8 965 note_block instrument banjo powered false note 8 966 note_block instrument banjo powered true note 9 967 note_block instrument banjo powered false note 9 968 note_block instrument banjo powered true note 10 969 note_block instrument banjo powered false note 10 970 note_block instrument banjo powered true note 11 971 note_block instrument banjo powered false note 11 972 note_block instrument banjo powered true note 12 973 note_block instrument banjo powered false note 12 974 note_block instrument banjo powered true note 13 975 note_block instrument banjo powered false note 13 976 note_block instrument banjo powered true note 14 977 note_block instrument banjo powered false note 14 978 note_block instrument banjo powered true note 15 979 note_block instrument banjo powered false note 15 980 note_block instrument banjo powered true note 16 981 note_block instrument banjo powered false note 16 982 note_block instrument banjo powered true note 17 983 note_block instrument banjo powered false note 17 984 note_block instrument banjo powered true note 18 985 note_block instrument banjo powered false note 18 986 note_block instrument banjo powered true note 19 987 note_block instrument banjo powered false note 19 988 note_block instrument banjo powered true note 20 989 note_block instrument banjo powered false note 20 990 note_block instrument banjo powered true note 21 991 note_block instrument banjo powered false note 21 992 note_block instrument banjo powered true note 22 993 note_block instrument banjo powered false note 22 994 note_block instrument banjo powered true note 23 995 note_block instrument banjo powered false note 23 996 note_block instrument banjo powered true note 24 997 note_block instrument banjo powered false note 24 998 note_block instrument pling powered true note 0 999 note_block instrument pling powered false note 0 1000 note_block instrument pling powered true note 1 1001 note_block instrument pling powered false note 1 1002 note_block instrument pling powered true note 2 1003 note_block instrument pling powered false note 2 1004 note_block instrument pling powered true note 3 1005 note_block instrument pling powered false note 3 1006 note_block instrument pling powered true note 4 1007 note_block instrument pling powered false note 4 1008 note_block instrument pling powered true note 5 1009 note_block instrument pling powered false note 5 1010 note_block instrument pling powered true note 6 1011 note_block instrument pling powered false note 6 1012 note_block instrument pling powered true note 7 1013 note_block instrument pling powered false note 7 1014 note_block instrument pling powered true note 8 1015 note_block instrument pling powered false note 8 1016 note_block instrument pling powered true note 9 1017 note_block instrument pling powered false note 9 1018 note_block instrument pling powered true note 10 1019 note_block instrument pling powered false note 10 1020 note_block instrument pling powered true note 11 1021 note_block instrument pling powered false note 11 1022 note_block instrument pling powered true note 12 1023 note_block instrument pling powered false note 12 1024 note_block instrument pling powered true note 13 1025 note_block instrument pling powered false note 13 1026 note_block instrument pling powered true note 14 1027 note_block instrument pling powered false note 14 1028 note_block instrument pling powered true note 15 1029 note_block instrument pling powered false note 15 1030 note_block instrument pling powered true note 16 1031 note_block instrument pling powered false note 16 1032 note_block instrument pling powered true note 17 1033 note_block instrument pling powered false note 17 1034 note_block instrument pling powered true note 18 1035 note_block instrument pling powered false note 18 1036 note_block instrument pling powered true note 19 1037 note_block instrument pling powered false note 19 1038 note_block instrument pling powered true note 20 1039 note_block instrument pling powered false note 20 1040 note_block instrument pling powered true note 21 1041 note_block instrument pling powered false note 21 1042 note_block instrument pling powered true note 22 1043 note_block instrument pling powered false note 22 1044 note_block instrument pling powered true note 23 1045 note_block instrument pling powered false note 23 1046 note_block instrument pling powered true note 24 1047 note_block instrument pling powered false note 24 1048 white_bed facing north occupied true part head 1049 white_bed facing north occupied true part foot 1050 white_bed facing north occupied false part head 1051 white_bed facing north occupied false part foot 1052 white_bed facing south occupied true part head 1053 white_bed facing south occupied true part foot 1054 white_bed facing south occupied false part head 1055 white_bed facing south occupied false part foot 1056 white_bed facing west occupied true part head 1057 white_bed facing west occupied true part foot 1058 white_bed facing west occupied false part head 1059 white_bed facing west occupied false part foot 1060 white_bed facing east occupied true part head 1061 white_bed facing east occupied true part foot 1062 white_bed facing east occupied false part head 1063 white_bed facing east occupied false part foot 1064 orange_bed facing north occupied true part head 1065 orange_bed facing north occupied true part foot 1066 orange_bed facing north occupied false part head 1067 orange_bed facing north occupied false part foot 1068 orange_bed facing south occupied true part head 1069 orange_bed facing south occupied true part foot 1070 orange_bed facing south occupied false part head 1071 orange_bed facing south occupied false part foot 1072 orange_bed facing west occupied true part head 1073 orange_bed facing west occupied true part foot 1074 orange_bed facing west occupied false part head 1075 orange_bed facing west occupied false part foot 1076 orange_bed facing east occupied true part head 1077 orange_bed facing east occupied true part foot 1078 orange_bed facing east occupied false part head 1079 orange_bed facing east occupied false part foot 1080 magenta_bed facing north occupied true part head 1081 magenta_bed facing north occupied true part foot 1082 magenta_bed facing north occupied false part head 1083 magenta_bed facing north occupied false part foot 1084 magenta_bed facing south occupied true part head 1085 magenta_bed facing south occupied true part foot 1086 magenta_bed facing south occupied false part head 1087 magenta_bed facing south occupied false part foot 1088 magenta_bed facing west occupied true part head 1089 magenta_bed facing west occupied true part foot 1090 magenta_bed facing west occupied false part head 1091 magenta_bed facing west occupied false part foot 1092 magenta_bed facing east occupied true part head 1093 magenta_bed facing east occupied true part foot 1094 magenta_bed facing east occupied false part head 1095 magenta_bed facing east occupied false part foot 1096 light_blue_bed facing north occupied true part head 1097 light_blue_bed facing north occupied true part foot 1098 light_blue_bed facing north occupied false part head 1099 light_blue_bed facing north occupied false part foot 1100 light_blue_bed facing south occupied true part head 1101 light_blue_bed facing south occupied true part foot 1102 light_blue_bed facing south occupied false part head 1103 light_blue_bed facing south occupied false part foot 1104 light_blue_bed facing west occupied true part head 1105 light_blue_bed facing west occupied true part foot 1106 light_blue_bed facing west occupied false part head 1107 light_blue_bed facing west occupied false part foot 1108 light_blue_bed facing east occupied true part head 1109 light_blue_bed facing east occupied true part foot 1110 light_blue_bed facing east occupied false part head 1111 light_blue_bed facing east occupied false part foot 1112 yellow_bed facing north occupied true part head 1113 yellow_bed facing north occupied true part foot 1114 yellow_bed facing north occupied false part head 1115 yellow_bed facing north occupied false part foot 1116 yellow_bed facing south occupied true part head 1117 yellow_bed facing south occupied true part foot 1118 yellow_bed facing south occupied false part head 1119 yellow_bed facing south occupied false part foot 1120 yellow_bed facing west occupied true part head 1121 yellow_bed facing west occupied true part foot 1122 yellow_bed facing west occupied false part head 1123 yellow_bed facing west occupied false part foot 1124 yellow_bed facing east occupied true part head 1125 yellow_bed facing east occupied true part foot 1126 yellow_bed facing east occupied false part head 1127 yellow_bed facing east occupied false part foot 1128 lime_bed facing north occupied true part head 1129 lime_bed facing north occupied true part foot 1130 lime_bed facing north occupied false part head 1131 lime_bed facing north occupied false part foot 1132 lime_bed facing south occupied true part head 1133 lime_bed facing south occupied true part foot 1134 lime_bed facing south occupied false part head 1135 lime_bed facing south occupied false part foot 1136 lime_bed facing west occupied true part head 1137 lime_bed facing west occupied true part foot 1138 lime_bed facing west occupied false part head 1139 lime_bed facing west occupied false part foot 1140 lime_bed facing east occupied true part head 1141 lime_bed facing east occupied true part foot 1142 lime_bed facing east occupied false part head 1143 lime_bed facing east occupied false part foot 1144 pink_bed facing north occupied true part head 1145 pink_bed facing north occupied true part foot 1146 pink_bed facing north occupied false part head 1147 pink_bed facing north occupied false part foot 1148 pink_bed facing south occupied true part head 1149 pink_bed facing south occupied true part foot 1150 pink_bed facing south occupied false part head 1151 pink_bed facing south occupied false part foot 1152 pink_bed facing west occupied true part head 1153 pink_bed facing west occupied true part foot 1154 pink_bed facing west occupied false part head 1155 pink_bed facing west occupied false part foot 1156 pink_bed facing east occupied true part head 1157 pink_bed facing east occupied true part foot 1158 pink_bed facing east occupied false part head 1159 pink_bed facing east occupied false part foot 1160 gray_bed facing north occupied true part head 1161 gray_bed facing north occupied true part foot 1162 gray_bed facing north occupied false part head 1163 gray_bed facing north occupied false part foot 1164 gray_bed facing south occupied true part head 1165 gray_bed facing south occupied true part foot 1166 gray_bed facing south occupied false part head 1167 gray_bed facing south occupied false part foot 1168 gray_bed facing west occupied true part head 1169 gray_bed facing west occupied true part foot 1170 gray_bed facing west occupied false part head 1171 gray_bed facing west occupied false part foot 1172 gray_bed facing east occupied true part head 1173 gray_bed facing east occupied true part foot 1174 gray_bed facing east occupied false part head 1175 gray_bed facing east occupied false part foot 1176 light_gray_bed facing north occupied true part head 1177 light_gray_bed facing north occupied true part foot 1178 light_gray_bed facing north occupied false part head 1179 light_gray_bed facing north occupied false part foot 1180 light_gray_bed facing south occupied true part head 1181 light_gray_bed facing south occupied true part foot 1182 light_gray_bed facing south occupied false part head 1183 light_gray_bed facing south occupied false part foot 1184 light_gray_bed facing west occupied true part head 1185 light_gray_bed facing west occupied true part foot 1186 light_gray_bed facing west occupied false part head 1187 light_gray_bed facing west occupied false part foot 1188 light_gray_bed facing east occupied true part head 1189 light_gray_bed facing east occupied true part foot 1190 light_gray_bed facing east occupied false part head 1191 light_gray_bed facing east occupied false part foot 1192 cyan_bed facing north occupied true part head 1193 cyan_bed facing north occupied true part foot 1194 cyan_bed facing north occupied false part head 1195 cyan_bed facing north occupied false part foot 1196 cyan_bed facing south occupied true part head 1197 cyan_bed facing south occupied true part foot 1198 cyan_bed facing south occupied false part head 1199 cyan_bed facing south occupied false part foot 1200 cyan_bed facing west occupied true part head 1201 cyan_bed facing west occupied true part foot 1202 cyan_bed facing west occupied false part head 1203 cyan_bed facing west occupied false part foot 1204 cyan_bed facing east occupied true part head 1205 cyan_bed facing east occupied true part foot 1206 cyan_bed facing east occupied false part head 1207 cyan_bed facing east occupied false part foot 1208 purple_bed facing north occupied true part head 1209 purple_bed facing north occupied true part foot 1210 purple_bed facing north occupied false part head 1211 purple_bed facing north occupied false part foot 1212 purple_bed facing south occupied true part head 1213 purple_bed facing south occupied true part foot 1214 purple_bed facing south occupied false part head 1215 purple_bed facing south occupied false part foot 1216 purple_bed facing west occupied true part head 1217 purple_bed facing west occupied true part foot 1218 purple_bed facing west occupied false part head 1219 purple_bed facing west occupied false part foot 1220 purple_bed facing east occupied true part head 1221 purple_bed facing east occupied true part foot 1222 purple_bed facing east occupied false part head 1223 purple_bed facing east occupied false part foot 1224 blue_bed facing north occupied true part head 1225 blue_bed facing north occupied true part foot 1226 blue_bed facing north occupied false part head 1227 blue_bed facing north occupied false part foot 1228 blue_bed facing south occupied true part head 1229 blue_bed facing south occupied true part foot 1230 blue_bed facing south occupied false part head 1231 blue_bed facing south occupied false part foot 1232 blue_bed facing west occupied true part head 1233 blue_bed facing west occupied true part foot 1234 blue_bed facing west occupied false part head 1235 blue_bed facing west occupied false part foot 1236 blue_bed facing east occupied true part head 1237 blue_bed facing east occupied true part foot 1238 blue_bed facing east occupied false part head 1239 blue_bed facing east occupied false part foot 1240 brown_bed facing north occupied true part head 1241 brown_bed facing north occupied true part foot 1242 brown_bed facing north occupied false part head 1243 brown_bed facing north occupied false part foot 1244 brown_bed facing south occupied true part head 1245 brown_bed facing south occupied true part foot 1246 brown_bed facing south occupied false part head 1247 brown_bed facing south occupied false part foot 1248 brown_bed facing west occupied true part head 1249 brown_bed facing west occupied true part foot 1250 brown_bed facing west occupied false part head 1251 brown_bed facing west occupied false part foot 1252 brown_bed facing east occupied true part head 1253 brown_bed facing east occupied true part foot 1254 brown_bed facing east occupied false part head 1255 brown_bed facing east occupied false part foot 1256 green_bed facing north occupied true part head 1257 green_bed facing north occupied true part foot 1258 green_bed facing north occupied false part head 1259 green_bed facing north occupied false part foot 1260 green_bed facing south occupied true part head 1261 green_bed facing south occupied true part foot 1262 green_bed facing south occupied false part head 1263 green_bed facing south occupied false part foot 1264 green_bed facing west occupied true part head 1265 green_bed facing west occupied true part foot 1266 green_bed facing west occupied false part head 1267 green_bed facing west occupied false part foot 1268 green_bed facing east occupied true part head 1269 green_bed facing east occupied true part foot 1270 green_bed facing east occupied false part head 1271 green_bed facing east occupied false part foot 1272 red_bed facing north occupied true part head 1273 red_bed facing north occupied true part foot 1274 red_bed facing north occupied false part head 1275 red_bed facing north occupied false part foot 1276 red_bed facing south occupied true part head 1277 red_bed facing south occupied true part foot 1278 red_bed facing south occupied false part head 1279 red_bed facing south occupied false part foot 1280 red_bed facing west occupied true part head 1281 red_bed facing west occupied true part foot 1282 red_bed facing west occupied false part head 1283 red_bed facing west occupied false part foot 1284 red_bed facing east occupied true part head 1285 red_bed facing east occupied true part foot 1286 red_bed facing east occupied false part head 1287 red_bed facing east occupied false part foot 1288 black_bed facing north occupied true part head 1289 black_bed facing north occupied true part foot 1290 black_bed facing north occupied false part head 1291 black_bed facing north occupied false part foot 1292 black_bed facing south occupied true part head 1293 black_bed facing south occupied true part foot 1294 black_bed facing south occupied false part head 1295 black_bed facing south occupied false part foot 1296 black_bed facing west occupied true part head 1297 black_bed facing west occupied true part foot 1298 black_bed facing west occupied false part head 1299 black_bed facing west occupied false part foot 1300 black_bed facing east occupied true part head 1301 black_bed facing east occupied true part foot 1302 black_bed facing east occupied false part head 1303 black_bed facing east occupied false part foot 1304 powered_rail shape north_south powered true 1305 powered_rail shape east_west powered true 1306 powered_rail shape ascending_east powered true 1307 powered_rail shape ascending_west powered true 1308 powered_rail shape ascending_north powered true 1309 powered_rail shape ascending_south powered true 1310 powered_rail shape north_south powered false 1311 powered_rail shape east_west powered false 1312 powered_rail shape ascending_east powered false 1313 powered_rail shape ascending_west powered false 1314 powered_rail shape ascending_north powered false 1315 powered_rail shape ascending_south powered false 1316 detector_rail shape north_south powered true 1317 detector_rail shape east_west powered true 1318 detector_rail shape ascending_east powered true 1319 detector_rail shape ascending_west powered true 1320 detector_rail shape ascending_north powered true 1321 detector_rail shape ascending_south powered true 1322 detector_rail shape north_south powered false 1323 detector_rail shape east_west powered false 1324 detector_rail shape ascending_east powered false 1325 detector_rail shape ascending_west powered false 1326 detector_rail shape ascending_north powered false 1327 detector_rail shape ascending_south powered false 1328 sticky_piston facing north extended true 1329 sticky_piston facing east extended true 1330 sticky_piston facing south extended true 1331 sticky_piston facing west extended true 1332 sticky_piston facing up extended true 1333 sticky_piston facing down extended true 1334 sticky_piston facing north extended false 1335 sticky_piston facing east extended false 1336 sticky_piston facing south extended false 1337 sticky_piston facing west extended false 1338 sticky_piston facing up extended false 1339 sticky_piston facing down extended false 1340 cobweb 1341 grass 1342 fern 1343 dead_bush 1344 seagrass 1345 tall_seagrass half upper 1346 tall_seagrass half lower 1347 piston facing north extended true 1348 piston facing east extended true 1349 piston facing south extended true 1350 piston facing west extended true 1351 piston facing up extended true 1352 piston facing down extended true 1353 piston facing north extended false 1354 piston facing east extended false 1355 piston facing south extended false 1356 piston facing west extended false 1357 piston facing up extended false 1358 piston facing down extended false 1359 piston_head facing north short true type normal 1360 piston_head facing north short true type sticky 1361 piston_head facing north short false type normal 1362 piston_head facing north short false type sticky 1363 piston_head facing east short true type normal 1364 piston_head facing east short true type sticky 1365 piston_head facing east short false type normal 1366 piston_head facing east short false type sticky 1367 piston_head facing south short true type normal 1368 piston_head facing south short true type sticky 1369 piston_head facing south short false type normal 1370 piston_head facing south short false type sticky 1371 piston_head facing west short true type normal 1372 piston_head facing west short true type sticky 1373 piston_head facing west short false type normal 1374 piston_head facing west short false type sticky 1375 piston_head facing up short true type normal 1376 piston_head facing up short true type sticky 1377 piston_head facing up short false type normal 1378 piston_head facing up short false type sticky 1379 piston_head facing down short true type normal 1380 piston_head facing down short true type sticky 1381 piston_head facing down short false type normal 1382 piston_head facing down short false type sticky 1383 white_wool 1384 orange_wool 1385 magenta_wool 1386 light_blue_wool 1387 yellow_wool 1388 lime_wool 1389 pink_wool 1390 gray_wool 1391 light_gray_wool 1392 cyan_wool 1393 purple_wool 1394 blue_wool 1395 brown_wool 1396 green_wool 1397 red_wool 1398 black_wool 1399 moving_piston facing north type normal 1400 moving_piston facing north type sticky 1401 moving_piston facing east type normal 1402 moving_piston facing east type sticky 1403 moving_piston facing south type normal 1404 moving_piston facing south type sticky 1405 moving_piston facing west type normal 1406 moving_piston facing west type sticky 1407 moving_piston facing up type normal 1408 moving_piston facing up type sticky 1409 moving_piston facing down type normal 1410 moving_piston facing down type sticky 1411 dandelion 1412 poppy 1413 blue_orchid 1414 allium 1415 azure_bluet 1416 red_tulip 1417 orange_tulip 1418 white_tulip 1419 pink_tulip 1420 oxeye_daisy 1421 cornflower 1422 wither_rose 1423 lily_of_the_valley 1424 brown_mushroom 1425 red_mushroom 1426 gold_block 1427 iron_block 1428 bricks 1429 tnt unstable true 1430 tnt unstable false 1431 bookshelf 1432 mossy_cobblestone 1433 obsidian 1434 torch 1435 wall_torch facing north 1436 wall_torch facing south 1437 wall_torch facing west 1438 wall_torch facing east 1439 fire north true south true east true age 0 up true west true 1440 fire north true south true east true age 0 up true west false 1441 fire north true south true east true age 0 up false west true 1442 fire north true south true east true age 0 up false west false 1443 fire north true south false east true age 0 up true west true 1444 fire north true south false east true age 0 up true west false 1445 fire north true south false east true age 0 up false west true 1446 fire north true south false east true age 0 up false west false 1447 fire north false south true east true age 0 up true west true 1448 fire north false south true east true age 0 up true west false 1449 fire north false south true east true age 0 up false west true 1450 fire north false south true east true age 0 up false west false 1451 fire north false south false east true age 0 up true west true 1452 fire north false south false east true age 0 up true west false 1453 fire north false south false east true age 0 up false west true 1454 fire north false south false east true age 0 up false west false 1455 fire north true south true east false age 0 up true west true 1456 fire north true south true east false age 0 up true west false 1457 fire north true south true east false age 0 up false west true 1458 fire north true south true east false age 0 up false west false 1459 fire north true south false east false age 0 up true west true 1460 fire north true south false east false age 0 up true west false 1461 fire north true south false east false age 0 up false west true 1462 fire north true south false east false age 0 up false west false 1463 fire north false south true east false age 0 up true west true 1464 fire north false south true east false age 0 up true west false 1465 fire north false south true east false age 0 up false west true 1466 fire north false south true east false age 0 up false west false 1467 fire north false south false east false age 0 up true west true 1468 fire north false south false east false age 0 up true west false 1469 fire north false south false east false age 0 up false west true 1470 fire north false south false east false age 0 up false west false 1471 fire north true south true east true age 1 up true west true 1472 fire north true south true east true age 1 up true west false 1473 fire north true south true east true age 1 up false west true 1474 fire north true south true east true age 1 up false west false 1475 fire north true south false east true age 1 up true west true 1476 fire north true south false east true age 1 up true west false 1477 fire north true south false east true age 1 up false west true 1478 fire north true south false east true age 1 up false west false 1479 fire north false south true east true age 1 up true west true 1480 fire north false south true east true age 1 up true west false 1481 fire north false south true east true age 1 up false west true 1482 fire north false south true east true age 1 up false west false 1483 fire north false south false east true age 1 up true west true 1484 fire north false south false east true age 1 up true west false 1485 fire north false south false east true age 1 up false west true 1486 fire north false south false east true age 1 up false west false 1487 fire north true south true east false age 1 up true west true 1488 fire north true south true east false age 1 up true west false 1489 fire north true south true east false age 1 up false west true 1490 fire north true south true east false age 1 up false west false 1491 fire north true south false east false age 1 up true west true 1492 fire north true south false east false age 1 up true west false 1493 fire north true south false east false age 1 up false west true 1494 fire north true south false east false age 1 up false west false 1495 fire north false south true east false age 1 up true west true 1496 fire north false south true east false age 1 up true west false 1497 fire north false south true east false age 1 up false west true 1498 fire north false south true east false age 1 up false west false 1499 fire north false south false east false age 1 up true west true 1500 fire north false south false east false age 1 up true west false 1501 fire north false south false east false age 1 up false west true 1502 fire north false south false east false age 1 up false west false 1503 fire north true south true east true age 2 up true west true 1504 fire north true south true east true age 2 up true west false 1505 fire north true south true east true age 2 up false west true 1506 fire north true south true east true age 2 up false west false 1507 fire north true south false east true age 2 up true west true 1508 fire north true south false east true age 2 up true west false 1509 fire north true south false east true age 2 up false west true 1510 fire north true south false east true age 2 up false west false 1511 fire north false south true east true age 2 up true west true 1512 fire north false south true east true age 2 up true west false 1513 fire north false south true east true age 2 up false west true 1514 fire north false south true east true age 2 up false west false 1515 fire north false south false east true age 2 up true west true 1516 fire north false south false east true age 2 up true west false 1517 fire north false south false east true age 2 up false west true 1518 fire north false south false east true age 2 up false west false 1519 fire north true south true east false age 2 up true west true 1520 fire north true south true east false age 2 up true west false 1521 fire north true south true east false age 2 up false west true 1522 fire north true south true east false age 2 up false west false 1523 fire north true south false east false age 2 up true west true 1524 fire north true south false east false age 2 up true west false 1525 fire north true south false east false age 2 up false west true 1526 fire north true south false east false age 2 up false west false 1527 fire north false south true east false age 2 up true west true 1528 fire north false south true east false age 2 up true west false 1529 fire north false south true east false age 2 up false west true 1530 fire north false south true east false age 2 up false west false 1531 fire north false south false east false age 2 up true west true 1532 fire north false south false east false age 2 up true west false 1533 fire north false south false east false age 2 up false west true 1534 fire north false south false east false age 2 up false west false 1535 fire north true south true east true age 3 up true west true 1536 fire north true south true east true age 3 up true west false 1537 fire north true south true east true age 3 up false west true 1538 fire north true south true east true age 3 up false west false 1539 fire north true south false east true age 3 up true west true 1540 fire north true south false east true age 3 up true west false 1541 fire north true south false east true age 3 up false west true 1542 fire north true south false east true age 3 up false west false 1543 fire north false south true east true age 3 up true west true 1544 fire north false south true east true age 3 up true west false 1545 fire north false south true east true age 3 up false west true 1546 fire north false south true east true age 3 up false west false 1547 fire north false south false east true age 3 up true west true 1548 fire north false south false east true age 3 up true west false 1549 fire north false south false east true age 3 up false west true 1550 fire north false south false east true age 3 up false west false 1551 fire north true south true east false age 3 up true west true 1552 fire north true south true east false age 3 up true west false 1553 fire north true south true east false age 3 up false west true 1554 fire north true south true east false age 3 up false west false 1555 fire north true south false east false age 3 up true west true 1556 fire north true south false east false age 3 up true west false 1557 fire north true south false east false age 3 up false west true 1558 fire north true south false east false age 3 up false west false 1559 fire north false south true east false age 3 up true west true 1560 fire north false south true east false age 3 up true west false 1561 fire north false south true east false age 3 up false west true 1562 fire north false south true east false age 3 up false west false 1563 fire north false south false east false age 3 up true west true 1564 fire north false south false east false age 3 up true west false 1565 fire north false south false east false age 3 up false west true 1566 fire north false south false east false age 3 up false west false 1567 fire north true south true east true age 4 up true west true 1568 fire north true south true east true age 4 up true west false 1569 fire north true south true east true age 4 up false west true 1570 fire north true south true east true age 4 up false west false 1571 fire north true south false east true age 4 up true west true 1572 fire north true south false east true age 4 up true west false 1573 fire north true south false east true age 4 up false west true 1574 fire north true south false east true age 4 up false west false 1575 fire north false south true east true age 4 up true west true 1576 fire north false south true east true age 4 up true west false 1577 fire north false south true east true age 4 up false west true 1578 fire north false south true east true age 4 up false west false 1579 fire north false south false east true age 4 up true west true 1580 fire north false south false east true age 4 up true west false 1581 fire north false south false east true age 4 up false west true 1582 fire north false south false east true age 4 up false west false 1583 fire north true south true east false age 4 up true west true 1584 fire north true south true east false age 4 up true west false 1585 fire north true south true east false age 4 up false west true 1586 fire north true south true east false age 4 up false west false 1587 fire north true south false east false age 4 up true west true 1588 fire north true south false east false age 4 up true west false 1589 fire north true south false east false age 4 up false west true 1590 fire north true south false east false age 4 up false west false 1591 fire north false south true east false age 4 up true west true 1592 fire north false south true east false age 4 up true west false 1593 fire north false south true east false age 4 up false west true 1594 fire north false south true east false age 4 up false west false 1595 fire north false south false east false age 4 up true west true 1596 fire north false south false east false age 4 up true west false 1597 fire north false south false east false age 4 up false west true 1598 fire north false south false east false age 4 up false west false 1599 fire north true south true east true age 5 up true west true 1600 fire north true south true east true age 5 up true west false 1601 fire north true south true east true age 5 up false west true 1602 fire north true south true east true age 5 up false west false 1603 fire north true south false east true age 5 up true west true 1604 fire north true south false east true age 5 up true west false 1605 fire north true south false east true age 5 up false west true 1606 fire north true south false east true age 5 up false west false 1607 fire north false south true east true age 5 up true west true 1608 fire north false south true east true age 5 up true west false 1609 fire north false south true east true age 5 up false west true 1610 fire north false south true east true age 5 up false west false 1611 fire north false south false east true age 5 up true west true 1612 fire north false south false east true age 5 up true west false 1613 fire north false south false east true age 5 up false west true 1614 fire north false south false east true age 5 up false west false 1615 fire north true south true east false age 5 up true west true 1616 fire north true south true east false age 5 up true west false 1617 fire north true south true east false age 5 up false west true 1618 fire north true south true east false age 5 up false west false 1619 fire north true south false east false age 5 up true west true 1620 fire north true south false east false age 5 up true west false 1621 fire north true south false east false age 5 up false west true 1622 fire north true south false east false age 5 up false west false 1623 fire north false south true east false age 5 up true west true 1624 fire north false south true east false age 5 up true west false 1625 fire north false south true east false age 5 up false west true 1626 fire north false south true east false age 5 up false west false 1627 fire north false south false east false age 5 up true west true 1628 fire north false south false east false age 5 up true west false 1629 fire north false south false east false age 5 up false west true 1630 fire north false south false east false age 5 up false west false 1631 fire north true south true east true age 6 up true west true 1632 fire north true south true east true age 6 up true west false 1633 fire north true south true east true age 6 up false west true 1634 fire north true south true east true age 6 up false west false 1635 fire north true south false east true age 6 up true west true 1636 fire north true south false east true age 6 up true west false 1637 fire north true south false east true age 6 up false west true 1638 fire north true south false east true age 6 up false west false 1639 fire north false south true east true age 6 up true west true 1640 fire north false south true east true age 6 up true west false 1641 fire north false south true east true age 6 up false west true 1642 fire north false south true east true age 6 up false west false 1643 fire north false south false east true age 6 up true west true 1644 fire north false south false east true age 6 up true west false 1645 fire north false south false east true age 6 up false west true 1646 fire north false south false east true age 6 up false west false 1647 fire north true south true east false age 6 up true west true 1648 fire north true south true east false age 6 up true west false 1649 fire north true south true east false age 6 up false west true 1650 fire north true south true east false age 6 up false west false 1651 fire north true south false east false age 6 up true west true 1652 fire north true south false east false age 6 up true west false 1653 fire north true south false east false age 6 up false west true 1654 fire north true south false east false age 6 up false west false 1655 fire north false south true east false age 6 up true west true 1656 fire north false south true east false age 6 up true west false 1657 fire north false south true east false age 6 up false west true 1658 fire north false south true east false age 6 up false west false 1659 fire north false south false east false age 6 up true west true 1660 fire north false south false east false age 6 up true west false 1661 fire north false south false east false age 6 up false west true 1662 fire north false south false east false age 6 up false west false 1663 fire north true south true east true age 7 up true west true 1664 fire north true south true east true age 7 up true west false 1665 fire north true south true east true age 7 up false west true 1666 fire north true south true east true age 7 up false west false 1667 fire north true south false east true age 7 up true west true 1668 fire north true south false east true age 7 up true west false 1669 fire north true south false east true age 7 up false west true 1670 fire north true south false east true age 7 up false west false 1671 fire north false south true east true age 7 up true west true 1672 fire north false south true east true age 7 up true west false 1673 fire north false south true east true age 7 up false west true 1674 fire north false south true east true age 7 up false west false 1675 fire north false south false east true age 7 up true west true 1676 fire north false south false east true age 7 up true west false 1677 fire north false south false east true age 7 up false west true 1678 fire north false south false east true age 7 up false west false 1679 fire north true south true east false age 7 up true west true 1680 fire north true south true east false age 7 up true west false 1681 fire north true south true east false age 7 up false west true 1682 fire north true south true east false age 7 up false west false 1683 fire north true south false east false age 7 up true west true 1684 fire north true south false east false age 7 up true west false 1685 fire north true south false east false age 7 up false west true 1686 fire north true south false east false age 7 up false west false 1687 fire north false south true east false age 7 up true west true 1688 fire north false south true east false age 7 up true west false 1689 fire north false south true east false age 7 up false west true 1690 fire north false south true east false age 7 up false west false 1691 fire north false south false east false age 7 up true west true 1692 fire north false south false east false age 7 up true west false 1693 fire north false south false east false age 7 up false west true 1694 fire north false south false east false age 7 up false west false 1695 fire north true south true east true age 8 up true west true 1696 fire north true south true east true age 8 up true west false 1697 fire north true south true east true age 8 up false west true 1698 fire north true south true east true age 8 up false west false 1699 fire north true south false east true age 8 up true west true 1700 fire north true south false east true age 8 up true west false 1701 fire north true south false east true age 8 up false west true 1702 fire north true south false east true age 8 up false west false 1703 fire north false south true east true age 8 up true west true 1704 fire north false south true east true age 8 up true west false 1705 fire north false south true east true age 8 up false west true 1706 fire north false south true east true age 8 up false west false 1707 fire north false south false east true age 8 up true west true 1708 fire north false south false east true age 8 up true west false 1709 fire north false south false east true age 8 up false west true 1710 fire north false south false east true age 8 up false west false 1711 fire north true south true east false age 8 up true west true 1712 fire north true south true east false age 8 up true west false 1713 fire north true south true east false age 8 up false west true 1714 fire north true south true east false age 8 up false west false 1715 fire north true south false east false age 8 up true west true 1716 fire north true south false east false age 8 up true west false 1717 fire north true south false east false age 8 up false west true 1718 fire north true south false east false age 8 up false west false 1719 fire north false south true east false age 8 up true west true 1720 fire north false south true east false age 8 up true west false 1721 fire north false south true east false age 8 up false west true 1722 fire north false south true east false age 8 up false west false 1723 fire north false south false east false age 8 up true west true 1724 fire north false south false east false age 8 up true west false 1725 fire north false south false east false age 8 up false west true 1726 fire north false south false east false age 8 up false west false 1727 fire north true south true east true age 9 up true west true 1728 fire north true south true east true age 9 up true west false 1729 fire north true south true east true age 9 up false west true 1730 fire north true south true east true age 9 up false west false 1731 fire north true south false east true age 9 up true west true 1732 fire north true south false east true age 9 up true west false 1733 fire north true south false east true age 9 up false west true 1734 fire north true south false east true age 9 up false west false 1735 fire north false south true east true age 9 up true west true 1736 fire north false south true east true age 9 up true west false 1737 fire north false south true east true age 9 up false west true 1738 fire north false south true east true age 9 up false west false 1739 fire north false south false east true age 9 up true west true 1740 fire north false south false east true age 9 up true west false 1741 fire north false south false east true age 9 up false west true 1742 fire north false south false east true age 9 up false west false 1743 fire north true south true east false age 9 up true west true 1744 fire north true south true east false age 9 up true west false 1745 fire north true south true east false age 9 up false west true 1746 fire north true south true east false age 9 up false west false 1747 fire north true south false east false age 9 up true west true 1748 fire north true south false east false age 9 up true west false 1749 fire north true south false east false age 9 up false west true 1750 fire north true south false east false age 9 up false west false 1751 fire north false south true east false age 9 up true west true 1752 fire north false south true east false age 9 up true west false 1753 fire north false south true east false age 9 up false west true 1754 fire north false south true east false age 9 up false west false 1755 fire north false south false east false age 9 up true west true 1756 fire north false south false east false age 9 up true west false 1757 fire north false south false east false age 9 up false west true 1758 fire north false south false east false age 9 up false west false 1759 fire north true south true east true age 10 up true west true 1760 fire north true south true east true age 10 up true west false 1761 fire north true south true east true age 10 up false west true 1762 fire north true south true east true age 10 up false west false 1763 fire north true south false east true age 10 up true west true 1764 fire north true south false east true age 10 up true west false 1765 fire north true south false east true age 10 up false west true 1766 fire north true south false east true age 10 up false west false 1767 fire north false south true east true age 10 up true west true 1768 fire north false south true east true age 10 up true west false 1769 fire north false south true east true age 10 up false west true 1770 fire north false south true east true age 10 up false west false 1771 fire north false south false east true age 10 up true west true 1772 fire north false south false east true age 10 up true west false 1773 fire north false south false east true age 10 up false west true 1774 fire north false south false east true age 10 up false west false 1775 fire north true south true east false age 10 up true west true 1776 fire north true south true east false age 10 up true west false 1777 fire north true south true east false age 10 up false west true 1778 fire north true south true east false age 10 up false west false 1779 fire north true south false east false age 10 up true west true 1780 fire north true south false east false age 10 up true west false 1781 fire north true south false east false age 10 up false west true 1782 fire north true south false east false age 10 up false west false 1783 fire north false south true east false age 10 up true west true 1784 fire north false south true east false age 10 up true west false 1785 fire north false south true east false age 10 up false west true 1786 fire north false south true east false age 10 up false west false 1787 fire north false south false east false age 10 up true west true 1788 fire north false south false east false age 10 up true west false 1789 fire north false south false east false age 10 up false west true 1790 fire north false south false east false age 10 up false west false 1791 fire north true south true east true age 11 up true west true 1792 fire north true south true east true age 11 up true west false 1793 fire north true south true east true age 11 up false west true 1794 fire north true south true east true age 11 up false west false 1795 fire north true south false east true age 11 up true west true 1796 fire north true south false east true age 11 up true west false 1797 fire north true south false east true age 11 up false west true 1798 fire north true south false east true age 11 up false west false 1799 fire north false south true east true age 11 up true west true 1800 fire north false south true east true age 11 up true west false 1801 fire north false south true east true age 11 up false west true 1802 fire north false south true east true age 11 up false west false 1803 fire north false south false east true age 11 up true west true 1804 fire north false south false east true age 11 up true west false 1805 fire north false south false east true age 11 up false west true 1806 fire north false south false east true age 11 up false west false 1807 fire north true south true east false age 11 up true west true 1808 fire north true south true east false age 11 up true west false 1809 fire north true south true east false age 11 up false west true 1810 fire north true south true east false age 11 up false west false 1811 fire north true south false east false age 11 up true west true 1812 fire north true south false east false age 11 up true west false 1813 fire north true south false east false age 11 up false west true 1814 fire north true south false east false age 11 up false west false 1815 fire north false south true east false age 11 up true west true 1816 fire north false south true east false age 11 up true west false 1817 fire north false south true east false age 11 up false west true 1818 fire north false south true east false age 11 up false west false 1819 fire north false south false east false age 11 up true west true 1820 fire north false south false east false age 11 up true west false 1821 fire north false south false east false age 11 up false west true 1822 fire north false south false east false age 11 up false west false 1823 fire north true south true east true age 12 up true west true 1824 fire north true south true east true age 12 up true west false 1825 fire north true south true east true age 12 up false west true 1826 fire north true south true east true age 12 up false west false 1827 fire north true south false east true age 12 up true west true 1828 fire north true south false east true age 12 up true west false 1829 fire north true south false east true age 12 up false west true 1830 fire north true south false east true age 12 up false west false 1831 fire north false south true east true age 12 up true west true 1832 fire north false south true east true age 12 up true west false 1833 fire north false south true east true age 12 up false west true 1834 fire north false south true east true age 12 up false west false 1835 fire north false south false east true age 12 up true west true 1836 fire north false south false east true age 12 up true west false 1837 fire north false south false east true age 12 up false west true 1838 fire north false south false east true age 12 up false west false 1839 fire north true south true east false age 12 up true west true 1840 fire north true south true east false age 12 up true west false 1841 fire north true south true east false age 12 up false west true 1842 fire north true south true east false age 12 up false west false 1843 fire north true south false east false age 12 up true west true 1844 fire north true south false east false age 12 up true west false 1845 fire north true south false east false age 12 up false west true 1846 fire north true south false east false age 12 up false west false 1847 fire north false south true east false age 12 up true west true 1848 fire north false south true east false age 12 up true west false 1849 fire north false south true east false age 12 up false west true 1850 fire north false south true east false age 12 up false west false 1851 fire north false south false east false age 12 up true west true 1852 fire north false south false east false age 12 up true west false 1853 fire north false south false east false age 12 up false west true 1854 fire north false south false east false age 12 up false west false 1855 fire north true south true east true age 13 up true west true 1856 fire north true south true east true age 13 up true west false 1857 fire north true south true east true age 13 up false west true 1858 fire north true south true east true age 13 up false west false 1859 fire north true south false east true age 13 up true west true 1860 fire north true south false east true age 13 up true west false 1861 fire north true south false east true age 13 up false west true 1862 fire north true south false east true age 13 up false west false 1863 fire north false south true east true age 13 up true west true 1864 fire north false south true east true age 13 up true west false 1865 fire north false south true east true age 13 up false west true 1866 fire north false south true east true age 13 up false west false 1867 fire north false south false east true age 13 up true west true 1868 fire north false south false east true age 13 up true west false 1869 fire north false south false east true age 13 up false west true 1870 fire north false south false east true age 13 up false west false 1871 fire north true south true east false age 13 up true west true 1872 fire north true south true east false age 13 up true west false 1873 fire north true south true east false age 13 up false west true 1874 fire north true south true east false age 13 up false west false 1875 fire north true south false east false age 13 up true west true 1876 fire north true south false east false age 13 up true west false 1877 fire north true south false east false age 13 up false west true 1878 fire north true south false east false age 13 up false west false 1879 fire north false south true east false age 13 up true west true 1880 fire north false south true east false age 13 up true west false 1881 fire north false south true east false age 13 up false west true 1882 fire north false south true east false age 13 up false west false 1883 fire north false south false east false age 13 up true west true 1884 fire north false south false east false age 13 up true west false 1885 fire north false south false east false age 13 up false west true 1886 fire north false south false east false age 13 up false west false 1887 fire north true south true east true age 14 up true west true 1888 fire north true south true east true age 14 up true west false 1889 fire north true south true east true age 14 up false west true 1890 fire north true south true east true age 14 up false west false 1891 fire north true south false east true age 14 up true west true 1892 fire north true south false east true age 14 up true west false 1893 fire north true south false east true age 14 up false west true 1894 fire north true south false east true age 14 up false west false 1895 fire north false south true east true age 14 up true west true 1896 fire north false south true east true age 14 up true west false 1897 fire north false south true east true age 14 up false west true 1898 fire north false south true east true age 14 up false west false 1899 fire north false south false east true age 14 up true west true 1900 fire north false south false east true age 14 up true west false 1901 fire north false south false east true age 14 up false west true 1902 fire north false south false east true age 14 up false west false 1903 fire north true south true east false age 14 up true west true 1904 fire north true south true east false age 14 up true west false 1905 fire north true south true east false age 14 up false west true 1906 fire north true south true east false age 14 up false west false 1907 fire north true south false east false age 14 up true west true 1908 fire north true south false east false age 14 up true west false 1909 fire north true south false east false age 14 up false west true 1910 fire north true south false east false age 14 up false west false 1911 fire north false south true east false age 14 up true west true 1912 fire north false south true east false age 14 up true west false 1913 fire north false south true east false age 14 up false west true 1914 fire north false south true east false age 14 up false west false 1915 fire north false south false east false age 14 up true west true 1916 fire north false south false east false age 14 up true west false 1917 fire north false south false east false age 14 up false west true 1918 fire north false south false east false age 14 up false west false 1919 fire north true south true east true age 15 up true west true 1920 fire north true south true east true age 15 up true west false 1921 fire north true south true east true age 15 up false west true 1922 fire north true south true east true age 15 up false west false 1923 fire north true south false east true age 15 up true west true 1924 fire north true south false east true age 15 up true west false 1925 fire north true south false east true age 15 up false west true 1926 fire north true south false east true age 15 up false west false 1927 fire north false south true east true age 15 up true west true 1928 fire north false south true east true age 15 up true west false 1929 fire north false south true east true age 15 up false west true 1930 fire north false south true east true age 15 up false west false 1931 fire north false south false east true age 15 up true west true 1932 fire north false south false east true age 15 up true west false 1933 fire north false south false east true age 15 up false west true 1934 fire north false south false east true age 15 up false west false 1935 fire north true south true east false age 15 up true west true 1936 fire north true south true east false age 15 up true west false 1937 fire north true south true east false age 15 up false west true 1938 fire north true south true east false age 15 up false west false 1939 fire north true south false east false age 15 up true west true 1940 fire north true south false east false age 15 up true west false 1941 fire north true south false east false age 15 up false west true 1942 fire north true south false east false age 15 up false west false 1943 fire north false south true east false age 15 up true west true 1944 fire north false south true east false age 15 up true west false 1945 fire north false south true east false age 15 up false west true 1946 fire north false south true east false age 15 up false west false 1947 fire north false south false east false age 15 up true west true 1948 fire north false south false east false age 15 up true west false 1949 fire north false south false east false age 15 up false west true 1950 fire north false south false east false age 15 up false west false 1951 spawner 1952 oak_stairs facing north waterlogged true shape straight half top 1953 oak_stairs facing north waterlogged false shape straight half top 1954 oak_stairs facing north waterlogged true shape inner_left half top 1955 oak_stairs facing north waterlogged false shape inner_left half top 1956 oak_stairs facing north waterlogged true shape inner_right half top 1957 oak_stairs facing north waterlogged false shape inner_right half top 1958 oak_stairs facing north waterlogged true shape outer_left half top 1959 oak_stairs facing north waterlogged false shape outer_left half top 1960 oak_stairs facing north waterlogged true shape outer_right half top 1961 oak_stairs facing north waterlogged false shape outer_right half top 1962 oak_stairs facing north waterlogged true shape straight half bottom 1963 oak_stairs facing north waterlogged false shape straight half bottom 1964 oak_stairs facing north waterlogged true shape inner_left half bottom 1965 oak_stairs facing north waterlogged false shape inner_left half bottom 1966 oak_stairs facing north waterlogged true shape inner_right half bottom 1967 oak_stairs facing north waterlogged false shape inner_right half bottom 1968 oak_stairs facing north waterlogged true shape outer_left half bottom 1969 oak_stairs facing north waterlogged false shape outer_left half bottom 1970 oak_stairs facing north waterlogged true shape outer_right half bottom 1971 oak_stairs facing north waterlogged false shape outer_right half bottom 1972 oak_stairs facing south waterlogged true shape straight half top 1973 oak_stairs facing south waterlogged false shape straight half top 1974 oak_stairs facing south waterlogged true shape inner_left half top 1975 oak_stairs facing south waterlogged false shape inner_left half top 1976 oak_stairs facing south waterlogged true shape inner_right half top 1977 oak_stairs facing south waterlogged false shape inner_right half top 1978 oak_stairs facing south waterlogged true shape outer_left half top 1979 oak_stairs facing south waterlogged false shape outer_left half top 1980 oak_stairs facing south waterlogged true shape outer_right half top 1981 oak_stairs facing south waterlogged false shape outer_right half top 1982 oak_stairs facing south waterlogged true shape straight half bottom 1983 oak_stairs facing south waterlogged false shape straight half bottom 1984 oak_stairs facing south waterlogged true shape inner_left half bottom 1985 oak_stairs facing south waterlogged false shape inner_left half bottom 1986 oak_stairs facing south waterlogged true shape inner_right half bottom 1987 oak_stairs facing south waterlogged false shape inner_right half bottom 1988 oak_stairs facing south waterlogged true shape outer_left half bottom 1989 oak_stairs facing south waterlogged false shape outer_left half bottom 1990 oak_stairs facing south waterlogged true shape outer_right half bottom 1991 oak_stairs facing south waterlogged false shape outer_right half bottom 1992 oak_stairs facing west waterlogged true shape straight half top 1993 oak_stairs facing west waterlogged false shape straight half top 1994 oak_stairs facing west waterlogged true shape inner_left half top 1995 oak_stairs facing west waterlogged false shape inner_left half top 1996 oak_stairs facing west waterlogged true shape inner_right half top 1997 oak_stairs facing west waterlogged false shape inner_right half top 1998 oak_stairs facing west waterlogged true shape outer_left half top 1999 oak_stairs facing west waterlogged false shape outer_left half top 2000 oak_stairs facing west waterlogged true shape outer_right half top 2001 oak_stairs facing west waterlogged false shape outer_right half top 2002 oak_stairs facing west waterlogged true shape straight half bottom 2003 oak_stairs facing west waterlogged false shape straight half bottom 2004 oak_stairs facing west waterlogged true shape inner_left half bottom 2005 oak_stairs facing west waterlogged false shape inner_left half bottom 2006 oak_stairs facing west waterlogged true shape inner_right half bottom 2007 oak_stairs facing west waterlogged false shape inner_right half bottom 2008 oak_stairs facing west waterlogged true shape outer_left half bottom 2009 oak_stairs facing west waterlogged false shape outer_left half bottom 2010 oak_stairs facing west waterlogged true shape outer_right half bottom 2011 oak_stairs facing west waterlogged false shape outer_right half bottom 2012 oak_stairs facing east waterlogged true shape straight half top 2013 oak_stairs facing east waterlogged false shape straight half top 2014 oak_stairs facing east waterlogged true shape inner_left half top 2015 oak_stairs facing east waterlogged false shape inner_left half top 2016 oak_stairs facing east waterlogged true shape inner_right half top 2017 oak_stairs facing east waterlogged false shape inner_right half top 2018 oak_stairs facing east waterlogged true shape outer_left half top 2019 oak_stairs facing east waterlogged false shape outer_left half top 2020 oak_stairs facing east waterlogged true shape outer_right half top 2021 oak_stairs facing east waterlogged false shape outer_right half top 2022 oak_stairs facing east waterlogged true shape straight half bottom 2023 oak_stairs facing east waterlogged false shape straight half bottom 2024 oak_stairs facing east waterlogged true shape inner_left half bottom 2025 oak_stairs facing east waterlogged false shape inner_left half bottom 2026 oak_stairs facing east waterlogged true shape inner_right half bottom 2027 oak_stairs facing east waterlogged false shape inner_right half bottom 2028 oak_stairs facing east waterlogged true shape outer_left half bottom 2029 oak_stairs facing east waterlogged false shape outer_left half bottom 2030 oak_stairs facing east waterlogged true shape outer_right half bottom 2031 oak_stairs facing east waterlogged false shape outer_right half bottom 2032 chest facing north waterlogged true type single 2033 chest facing north waterlogged false type single 2034 chest facing north waterlogged true type left 2035 chest facing north waterlogged false type left 2036 chest facing north waterlogged true type right 2037 chest facing north waterlogged false type right 2038 chest facing south waterlogged true type single 2039 chest facing south waterlogged false type single 2040 chest facing south waterlogged true type left 2041 chest facing south waterlogged false type left 2042 chest facing south waterlogged true type right 2043 chest facing south waterlogged false type right 2044 chest facing west waterlogged true type single 2045 chest facing west waterlogged false type single 2046 chest facing west waterlogged true type left 2047 chest facing west waterlogged false type left 2048 chest facing west waterlogged true type right 2049 chest facing west waterlogged false type right 2050 chest facing east waterlogged true type single 2051 chest facing east waterlogged false type single 2052 chest facing east waterlogged true type left 2053 chest facing east waterlogged false type left 2054 chest facing east waterlogged true type right 2055 chest facing east waterlogged false type right 2056 redstone_wire south up east up north up power 0 west up 2057 redstone_wire south up east up north up power 0 west side 2058 redstone_wire south up east up north up power 0 west none 2059 redstone_wire south side east up north up power 0 west up 2060 redstone_wire south side east up north up power 0 west side 2061 redstone_wire south side east up north up power 0 west none 2062 redstone_wire south none east up north up power 0 west up 2063 redstone_wire south none east up north up power 0 west side 2064 redstone_wire south none east up north up power 0 west none 2065 redstone_wire south up east up north up power 1 west up 2066 redstone_wire south up east up north up power 1 west side 2067 redstone_wire south up east up north up power 1 west none 2068 redstone_wire south side east up north up power 1 west up 2069 redstone_wire south side east up north up power 1 west side 2070 redstone_wire south side east up north up power 1 west none 2071 redstone_wire south none east up north up power 1 west up 2072 redstone_wire south none east up north up power 1 west side 2073 redstone_wire south none east up north up power 1 west none 2074 redstone_wire south up east up north up power 2 west up 2075 redstone_wire south up east up north up power 2 west side 2076 redstone_wire south up east up north up power 2 west none 2077 redstone_wire south side east up north up power 2 west up 2078 redstone_wire south side east up north up power 2 west side 2079 redstone_wire south side east up north up power 2 west none 2080 redstone_wire south none east up north up power 2 west up 2081 redstone_wire south none east up north up power 2 west side 2082 redstone_wire south none east up north up power 2 west none 2083 redstone_wire south up east up north up power 3 west up 2084 redstone_wire south up east up north up power 3 west side 2085 redstone_wire south up east up north up power 3 west none 2086 redstone_wire south side east up north up power 3 west up 2087 redstone_wire south side east up north up power 3 west side 2088 redstone_wire south side east up north up power 3 west none 2089 redstone_wire south none east up north up power 3 west up 2090 redstone_wire south none east up north up power 3 west side 2091 redstone_wire south none east up north up power 3 west none 2092 redstone_wire south up east up north up power 4 west up 2093 redstone_wire south up east up north up power 4 west side 2094 redstone_wire south up east up north up power 4 west none 2095 redstone_wire south side east up north up power 4 west up 2096 redstone_wire south side east up north up power 4 west side 2097 redstone_wire south side east up north up power 4 west none 2098 redstone_wire south none east up north up power 4 west up 2099 redstone_wire south none east up north up power 4 west side 2100 redstone_wire south none east up north up power 4 west none 2101 redstone_wire south up east up north up power 5 west up 2102 redstone_wire south up east up north up power 5 west side 2103 redstone_wire south up east up north up power 5 west none 2104 redstone_wire south side east up north up power 5 west up 2105 redstone_wire south side east up north up power 5 west side 2106 redstone_wire south side east up north up power 5 west none 2107 redstone_wire south none east up north up power 5 west up 2108 redstone_wire south none east up north up power 5 west side 2109 redstone_wire south none east up north up power 5 west none 2110 redstone_wire south up east up north up power 6 west up 2111 redstone_wire south up east up north up power 6 west side 2112 redstone_wire south up east up north up power 6 west none 2113 redstone_wire south side east up north up power 6 west up 2114 redstone_wire south side east up north up power 6 west side 2115 redstone_wire south side east up north up power 6 west none 2116 redstone_wire south none east up north up power 6 west up 2117 redstone_wire south none east up north up power 6 west side 2118 redstone_wire south none east up north up power 6 west none 2119 redstone_wire south up east up north up power 7 west up 2120 redstone_wire south up east up north up power 7 west side 2121 redstone_wire south up east up north up power 7 west none 2122 redstone_wire south side east up north up power 7 west up 2123 redstone_wire south side east up north up power 7 west side 2124 redstone_wire south side east up north up power 7 west none 2125 redstone_wire south none east up north up power 7 west up 2126 redstone_wire south none east up north up power 7 west side 2127 redstone_wire south none east up north up power 7 west none 2128 redstone_wire south up east up north up power 8 west up 2129 redstone_wire south up east up north up power 8 west side 2130 redstone_wire south up east up north up power 8 west none 2131 redstone_wire south side east up north up power 8 west up 2132 redstone_wire south side east up north up power 8 west side 2133 redstone_wire south side east up north up power 8 west none 2134 redstone_wire south none east up north up power 8 west up 2135 redstone_wire south none east up north up power 8 west side 2136 redstone_wire south none east up north up power 8 west none 2137 redstone_wire south up east up north up power 9 west up 2138 redstone_wire south up east up north up power 9 west side 2139 redstone_wire south up east up north up power 9 west none 2140 redstone_wire south side east up north up power 9 west up 2141 redstone_wire south side east up north up power 9 west side 2142 redstone_wire south side east up north up power 9 west none 2143 redstone_wire south none east up north up power 9 west up 2144 redstone_wire south none east up north up power 9 west side 2145 redstone_wire south none east up north up power 9 west none 2146 redstone_wire south up east up north up power 10 west up 2147 redstone_wire south up east up north up power 10 west side 2148 redstone_wire south up east up north up power 10 west none 2149 redstone_wire south side east up north up power 10 west up 2150 redstone_wire south side east up north up power 10 west side 2151 redstone_wire south side east up north up power 10 west none 2152 redstone_wire south none east up north up power 10 west up 2153 redstone_wire south none east up north up power 10 west side 2154 redstone_wire south none east up north up power 10 west none 2155 redstone_wire south up east up north up power 11 west up 2156 redstone_wire south up east up north up power 11 west side 2157 redstone_wire south up east up north up power 11 west none 2158 redstone_wire south side east up north up power 11 west up 2159 redstone_wire south side east up north up power 11 west side 2160 redstone_wire south side east up north up power 11 west none 2161 redstone_wire south none east up north up power 11 west up 2162 redstone_wire south none east up north up power 11 west side 2163 redstone_wire south none east up north up power 11 west none 2164 redstone_wire south up east up north up power 12 west up 2165 redstone_wire south up east up north up power 12 west side 2166 redstone_wire south up east up north up power 12 west none 2167 redstone_wire south side east up north up power 12 west up 2168 redstone_wire south side east up north up power 12 west side 2169 redstone_wire south side east up north up power 12 west none 2170 redstone_wire south none east up north up power 12 west up 2171 redstone_wire south none east up north up power 12 west side 2172 redstone_wire south none east up north up power 12 west none 2173 redstone_wire south up east up north up power 13 west up 2174 redstone_wire south up east up north up power 13 west side 2175 redstone_wire south up east up north up power 13 west none 2176 redstone_wire south side east up north up power 13 west up 2177 redstone_wire south side east up north up power 13 west side 2178 redstone_wire south side east up north up power 13 west none 2179 redstone_wire south none east up north up power 13 west up 2180 redstone_wire south none east up north up power 13 west side 2181 redstone_wire south none east up north up power 13 west none 2182 redstone_wire south up east up north up power 14 west up 2183 redstone_wire south up east up north up power 14 west side 2184 redstone_wire south up east up north up power 14 west none 2185 redstone_wire south side east up north up power 14 west up 2186 redstone_wire south side east up north up power 14 west side 2187 redstone_wire south side east up north up power 14 west none 2188 redstone_wire south none east up north up power 14 west up 2189 redstone_wire south none east up north up power 14 west side 2190 redstone_wire south none east up north up power 14 west none 2191 redstone_wire south up east up north up power 15 west up 2192 redstone_wire south up east up north up power 15 west side 2193 redstone_wire south up east up north up power 15 west none 2194 redstone_wire south side east up north up power 15 west up 2195 redstone_wire south side east up north up power 15 west side 2196 redstone_wire south side east up north up power 15 west none 2197 redstone_wire south none east up north up power 15 west up 2198 redstone_wire south none east up north up power 15 west side 2199 redstone_wire south none east up north up power 15 west none 2200 redstone_wire south up east up north side power 0 west up 2201 redstone_wire south up east up north side power 0 west side 2202 redstone_wire south up east up north side power 0 west none 2203 redstone_wire south side east up north side power 0 west up 2204 redstone_wire south side east up north side power 0 west side 2205 redstone_wire south side east up north side power 0 west none 2206 redstone_wire south none east up north side power 0 west up 2207 redstone_wire south none east up north side power 0 west side 2208 redstone_wire south none east up north side power 0 west none 2209 redstone_wire south up east up north side power 1 west up 2210 redstone_wire south up east up north side power 1 west side 2211 redstone_wire south up east up north side power 1 west none 2212 redstone_wire south side east up north side power 1 west up 2213 redstone_wire south side east up north side power 1 west side 2214 redstone_wire south side east up north side power 1 west none 2215 redstone_wire south none east up north side power 1 west up 2216 redstone_wire south none east up north side power 1 west side 2217 redstone_wire south none east up north side power 1 west none 2218 redstone_wire south up east up north side power 2 west up 2219 redstone_wire south up east up north side power 2 west side 2220 redstone_wire south up east up north side power 2 west none 2221 redstone_wire south side east up north side power 2 west up 2222 redstone_wire south side east up north side power 2 west side 2223 redstone_wire south side east up north side power 2 west none 2224 redstone_wire south none east up north side power 2 west up 2225 redstone_wire south none east up north side power 2 west side 2226 redstone_wire south none east up north side power 2 west none 2227 redstone_wire south up east up north side power 3 west up 2228 redstone_wire south up east up north side power 3 west side 2229 redstone_wire south up east up north side power 3 west none 2230 redstone_wire south side east up north side power 3 west up 2231 redstone_wire south side east up north side power 3 west side 2232 redstone_wire south side east up north side power 3 west none 2233 redstone_wire south none east up north side power 3 west up 2234 redstone_wire south none east up north side power 3 west side 2235 redstone_wire south none east up north side power 3 west none 2236 redstone_wire south up east up north side power 4 west up 2237 redstone_wire south up east up north side power 4 west side 2238 redstone_wire south up east up north side power 4 west none 2239 redstone_wire south side east up north side power 4 west up 2240 redstone_wire south side east up north side power 4 west side 2241 redstone_wire south side east up north side power 4 west none 2242 redstone_wire south none east up north side power 4 west up 2243 redstone_wire south none east up north side power 4 west side 2244 redstone_wire south none east up north side power 4 west none 2245 redstone_wire south up east up north side power 5 west up 2246 redstone_wire south up east up north side power 5 west side 2247 redstone_wire south up east up north side power 5 west none 2248 redstone_wire south side east up north side power 5 west up 2249 redstone_wire south side east up north side power 5 west side 2250 redstone_wire south side east up north side power 5 west none 2251 redstone_wire south none east up north side power 5 west up 2252 redstone_wire south none east up north side power 5 west side 2253 redstone_wire south none east up north side power 5 west none 2254 redstone_wire south up east up north side power 6 west up 2255 redstone_wire south up east up north side power 6 west side 2256 redstone_wire south up east up north side power 6 west none 2257 redstone_wire south side east up north side power 6 west up 2258 redstone_wire south side east up north side power 6 west side 2259 redstone_wire south side east up north side power 6 west none 2260 redstone_wire south none east up north side power 6 west up 2261 redstone_wire south none east up north side power 6 west side 2262 redstone_wire south none east up north side power 6 west none 2263 redstone_wire south up east up north side power 7 west up 2264 redstone_wire south up east up north side power 7 west side 2265 redstone_wire south up east up north side power 7 west none 2266 redstone_wire south side east up north side power 7 west up 2267 redstone_wire south side east up north side power 7 west side 2268 redstone_wire south side east up north side power 7 west none 2269 redstone_wire south none east up north side power 7 west up 2270 redstone_wire south none east up north side power 7 west side 2271 redstone_wire south none east up north side power 7 west none 2272 redstone_wire south up east up north side power 8 west up 2273 redstone_wire south up east up north side power 8 west side 2274 redstone_wire south up east up north side power 8 west none 2275 redstone_wire south side east up north side power 8 west up 2276 redstone_wire south side east up north side power 8 west side 2277 redstone_wire south side east up north side power 8 west none 2278 redstone_wire south none east up north side power 8 west up 2279 redstone_wire south none east up north side power 8 west side 2280 redstone_wire south none east up north side power 8 west none 2281 redstone_wire south up east up north side power 9 west up 2282 redstone_wire south up east up north side power 9 west side 2283 redstone_wire south up east up north side power 9 west none 2284 redstone_wire south side east up north side power 9 west up 2285 redstone_wire south side east up north side power 9 west side 2286 redstone_wire south side east up north side power 9 west none 2287 redstone_wire south none east up north side power 9 west up 2288 redstone_wire south none east up north side power 9 west side 2289 redstone_wire south none east up north side power 9 west none 2290 redstone_wire south up east up north side power 10 west up 2291 redstone_wire south up east up north side power 10 west side 2292 redstone_wire south up east up north side power 10 west none 2293 redstone_wire south side east up north side power 10 west up 2294 redstone_wire south side east up north side power 10 west side 2295 redstone_wire south side east up north side power 10 west none 2296 redstone_wire south none east up north side power 10 west up 2297 redstone_wire south none east up north side power 10 west side 2298 redstone_wire south none east up north side power 10 west none 2299 redstone_wire south up east up north side power 11 west up 2300 redstone_wire south up east up north side power 11 west side 2301 redstone_wire south up east up north side power 11 west none 2302 redstone_wire south side east up north side power 11 west up 2303 redstone_wire south side east up north side power 11 west side 2304 redstone_wire south side east up north side power 11 west none 2305 redstone_wire south none east up north side power 11 west up 2306 redstone_wire south none east up north side power 11 west side 2307 redstone_wire south none east up north side power 11 west none 2308 redstone_wire south up east up north side power 12 west up 2309 redstone_wire south up east up north side power 12 west side 2310 redstone_wire south up east up north side power 12 west none 2311 redstone_wire south side east up north side power 12 west up 2312 redstone_wire south side east up north side power 12 west side 2313 redstone_wire south side east up north side power 12 west none 2314 redstone_wire south none east up north side power 12 west up 2315 redstone_wire south none east up north side power 12 west side 2316 redstone_wire south none east up north side power 12 west none 2317 redstone_wire south up east up north side power 13 west up 2318 redstone_wire south up east up north side power 13 west side 2319 redstone_wire south up east up north side power 13 west none 2320 redstone_wire south side east up north side power 13 west up 2321 redstone_wire south side east up north side power 13 west side 2322 redstone_wire south side east up north side power 13 west none 2323 redstone_wire south none east up north side power 13 west up 2324 redstone_wire south none east up north side power 13 west side 2325 redstone_wire south none east up north side power 13 west none 2326 redstone_wire south up east up north side power 14 west up 2327 redstone_wire south up east up north side power 14 west side 2328 redstone_wire south up east up north side power 14 west none 2329 redstone_wire south side east up north side power 14 west up 2330 redstone_wire south side east up north side power 14 west side 2331 redstone_wire south side east up north side power 14 west none 2332 redstone_wire south none east up north side power 14 west up 2333 redstone_wire south none east up north side power 14 west side 2334 redstone_wire south none east up north side power 14 west none 2335 redstone_wire south up east up north side power 15 west up 2336 redstone_wire south up east up north side power 15 west side 2337 redstone_wire south up east up north side power 15 west none 2338 redstone_wire south side east up north side power 15 west up 2339 redstone_wire south side east up north side power 15 west side 2340 redstone_wire south side east up north side power 15 west none 2341 redstone_wire south none east up north side power 15 west up 2342 redstone_wire south none east up north side power 15 west side 2343 redstone_wire south none east up north side power 15 west none 2344 redstone_wire south up east up north none power 0 west up 2345 redstone_wire south up east up north none power 0 west side 2346 redstone_wire south up east up north none power 0 west none 2347 redstone_wire south side east up north none power 0 west up 2348 redstone_wire south side east up north none power 0 west side 2349 redstone_wire south side east up north none power 0 west none 2350 redstone_wire south none east up north none power 0 west up 2351 redstone_wire south none east up north none power 0 west side 2352 redstone_wire south none east up north none power 0 west none 2353 redstone_wire south up east up north none power 1 west up 2354 redstone_wire south up east up north none power 1 west side 2355 redstone_wire south up east up north none power 1 west none 2356 redstone_wire south side east up north none power 1 west up 2357 redstone_wire south side east up north none power 1 west side 2358 redstone_wire south side east up north none power 1 west none 2359 redstone_wire south none east up north none power 1 west up 2360 redstone_wire south none east up north none power 1 west side 2361 redstone_wire south none east up north none power 1 west none 2362 redstone_wire south up east up north none power 2 west up 2363 redstone_wire south up east up north none power 2 west side 2364 redstone_wire south up east up north none power 2 west none 2365 redstone_wire south side east up north none power 2 west up 2366 redstone_wire south side east up north none power 2 west side 2367 redstone_wire south side east up north none power 2 west none 2368 redstone_wire south none east up north none power 2 west up 2369 redstone_wire south none east up north none power 2 west side 2370 redstone_wire south none east up north none power 2 west none 2371 redstone_wire south up east up north none power 3 west up 2372 redstone_wire south up east up north none power 3 west side 2373 redstone_wire south up east up north none power 3 west none 2374 redstone_wire south side east up north none power 3 west up 2375 redstone_wire south side east up north none power 3 west side 2376 redstone_wire south side east up north none power 3 west none 2377 redstone_wire south none east up north none power 3 west up 2378 redstone_wire south none east up north none power 3 west side 2379 redstone_wire south none east up north none power 3 west none 2380 redstone_wire south up east up north none power 4 west up 2381 redstone_wire south up east up north none power 4 west side 2382 redstone_wire south up east up north none power 4 west none 2383 redstone_wire south side east up north none power 4 west up 2384 redstone_wire south side east up north none power 4 west side 2385 redstone_wire south side east up north none power 4 west none 2386 redstone_wire south none east up north none power 4 west up 2387 redstone_wire south none east up north none power 4 west side 2388 redstone_wire south none east up north none power 4 west none 2389 redstone_wire south up east up north none power 5 west up 2390 redstone_wire south up east up north none power 5 west side 2391 redstone_wire south up east up north none power 5 west none 2392 redstone_wire south side east up north none power 5 west up 2393 redstone_wire south side east up north none power 5 west side 2394 redstone_wire south side east up north none power 5 west none 2395 redstone_wire south none east up north none power 5 west up 2396 redstone_wire south none east up north none power 5 west side 2397 redstone_wire south none east up north none power 5 west none 2398 redstone_wire south up east up north none power 6 west up 2399 redstone_wire south up east up north none power 6 west side 2400 redstone_wire south up east up north none power 6 west none 2401 redstone_wire south side east up north none power 6 west up 2402 redstone_wire south side east up north none power 6 west side 2403 redstone_wire south side east up north none power 6 west none 2404 redstone_wire south none east up north none power 6 west up 2405 redstone_wire south none east up north none power 6 west side 2406 redstone_wire south none east up north none power 6 west none 2407 redstone_wire south up east up north none power 7 west up 2408 redstone_wire south up east up north none power 7 west side 2409 redstone_wire south up east up north none power 7 west none 2410 redstone_wire south side east up north none power 7 west up 2411 redstone_wire south side east up north none power 7 west side 2412 redstone_wire south side east up north none power 7 west none 2413 redstone_wire south none east up north none power 7 west up 2414 redstone_wire south none east up north none power 7 west side 2415 redstone_wire south none east up north none power 7 west none 2416 redstone_wire south up east up north none power 8 west up 2417 redstone_wire south up east up north none power 8 west side 2418 redstone_wire south up east up north none power 8 west none 2419 redstone_wire south side east up north none power 8 west up 2420 redstone_wire south side east up north none power 8 west side 2421 redstone_wire south side east up north none power 8 west none 2422 redstone_wire south none east up north none power 8 west up 2423 redstone_wire south none east up north none power 8 west side 2424 redstone_wire south none east up north none power 8 west none 2425 redstone_wire south up east up north none power 9 west up 2426 redstone_wire south up east up north none power 9 west side 2427 redstone_wire south up east up north none power 9 west none 2428 redstone_wire south side east up north none power 9 west up 2429 redstone_wire south side east up north none power 9 west side 2430 redstone_wire south side east up north none power 9 west none 2431 redstone_wire south none east up north none power 9 west up 2432 redstone_wire south none east up north none power 9 west side 2433 redstone_wire south none east up north none power 9 west none 2434 redstone_wire south up east up north none power 10 west up 2435 redstone_wire south up east up north none power 10 west side 2436 redstone_wire south up east up north none power 10 west none 2437 redstone_wire south side east up north none power 10 west up 2438 redstone_wire south side east up north none power 10 west side 2439 redstone_wire south side east up north none power 10 west none 2440 redstone_wire south none east up north none power 10 west up 2441 redstone_wire south none east up north none power 10 west side 2442 redstone_wire south none east up north none power 10 west none 2443 redstone_wire south up east up north none power 11 west up 2444 redstone_wire south up east up north none power 11 west side 2445 redstone_wire south up east up north none power 11 west none 2446 redstone_wire south side east up north none power 11 west up 2447 redstone_wire south side east up north none power 11 west side 2448 redstone_wire south side east up north none power 11 west none 2449 redstone_wire south none east up north none power 11 west up 2450 redstone_wire south none east up north none power 11 west side 2451 redstone_wire south none east up north none power 11 west none 2452 redstone_wire south up east up north none power 12 west up 2453 redstone_wire south up east up north none power 12 west side 2454 redstone_wire south up east up north none power 12 west none 2455 redstone_wire south side east up north none power 12 west up 2456 redstone_wire south side east up north none power 12 west side 2457 redstone_wire south side east up north none power 12 west none 2458 redstone_wire south none east up north none power 12 west up 2459 redstone_wire south none east up north none power 12 west side 2460 redstone_wire south none east up north none power 12 west none 2461 redstone_wire south up east up north none power 13 west up 2462 redstone_wire south up east up north none power 13 west side 2463 redstone_wire south up east up north none power 13 west none 2464 redstone_wire south side east up north none power 13 west up 2465 redstone_wire south side east up north none power 13 west side 2466 redstone_wire south side east up north none power 13 west none 2467 redstone_wire south none east up north none power 13 west up 2468 redstone_wire south none east up north none power 13 west side 2469 redstone_wire south none east up north none power 13 west none 2470 redstone_wire south up east up north none power 14 west up 2471 redstone_wire south up east up north none power 14 west side 2472 redstone_wire south up east up north none power 14 west none 2473 redstone_wire south side east up north none power 14 west up 2474 redstone_wire south side east up north none power 14 west side 2475 redstone_wire south side east up north none power 14 west none 2476 redstone_wire south none east up north none power 14 west up 2477 redstone_wire south none east up north none power 14 west side 2478 redstone_wire south none east up north none power 14 west none 2479 redstone_wire south up east up north none power 15 west up 2480 redstone_wire south up east up north none power 15 west side 2481 redstone_wire south up east up north none power 15 west none 2482 redstone_wire south side east up north none power 15 west up 2483 redstone_wire south side east up north none power 15 west side 2484 redstone_wire south side east up north none power 15 west none 2485 redstone_wire south none east up north none power 15 west up 2486 redstone_wire south none east up north none power 15 west side 2487 redstone_wire south none east up north none power 15 west none 2488 redstone_wire south up east side north up power 0 west up 2489 redstone_wire south up east side north up power 0 west side 2490 redstone_wire south up east side north up power 0 west none 2491 redstone_wire south side east side north up power 0 west up 2492 redstone_wire south side east side north up power 0 west side 2493 redstone_wire south side east side north up power 0 west none 2494 redstone_wire south none east side north up power 0 west up 2495 redstone_wire south none east side north up power 0 west side 2496 redstone_wire south none east side north up power 0 west none 2497 redstone_wire south up east side north up power 1 west up 2498 redstone_wire south up east side north up power 1 west side 2499 redstone_wire south up east side north up power 1 west none 2500 redstone_wire south side east side north up power 1 west up 2501 redstone_wire south side east side north up power 1 west side 2502 redstone_wire south side east side north up power 1 west none 2503 redstone_wire south none east side north up power 1 west up 2504 redstone_wire south none east side north up power 1 west side 2505 redstone_wire south none east side north up power 1 west none 2506 redstone_wire south up east side north up power 2 west up 2507 redstone_wire south up east side north up power 2 west side 2508 redstone_wire south up east side north up power 2 west none 2509 redstone_wire south side east side north up power 2 west up 2510 redstone_wire south side east side north up power 2 west side 2511 redstone_wire south side east side north up power 2 west none 2512 redstone_wire south none east side north up power 2 west up 2513 redstone_wire south none east side north up power 2 west side 2514 redstone_wire south none east side north up power 2 west none 2515 redstone_wire south up east side north up power 3 west up 2516 redstone_wire south up east side north up power 3 west side 2517 redstone_wire south up east side north up power 3 west none 2518 redstone_wire south side east side north up power 3 west up 2519 redstone_wire south side east side north up power 3 west side 2520 redstone_wire south side east side north up power 3 west none 2521 redstone_wire south none east side north up power 3 west up 2522 redstone_wire south none east side north up power 3 west side 2523 redstone_wire south none east side north up power 3 west none 2524 redstone_wire south up east side north up power 4 west up 2525 redstone_wire south up east side north up power 4 west side 2526 redstone_wire south up east side north up power 4 west none 2527 redstone_wire south side east side north up power 4 west up 2528 redstone_wire south side east side north up power 4 west side 2529 redstone_wire south side east side north up power 4 west none 2530 redstone_wire south none east side north up power 4 west up 2531 redstone_wire south none east side north up power 4 west side 2532 redstone_wire south none east side north up power 4 west none 2533 redstone_wire south up east side north up power 5 west up 2534 redstone_wire south up east side north up power 5 west side 2535 redstone_wire south up east side north up power 5 west none 2536 redstone_wire south side east side north up power 5 west up 2537 redstone_wire south side east side north up power 5 west side 2538 redstone_wire south side east side north up power 5 west none 2539 redstone_wire south none east side north up power 5 west up 2540 redstone_wire south none east side north up power 5 west side 2541 redstone_wire south none east side north up power 5 west none 2542 redstone_wire south up east side north up power 6 west up 2543 redstone_wire south up east side north up power 6 west side 2544 redstone_wire south up east side north up power 6 west none 2545 redstone_wire south side east side north up power 6 west up 2546 redstone_wire south side east side north up power 6 west side 2547 redstone_wire south side east side north up power 6 west none 2548 redstone_wire south none east side north up power 6 west up 2549 redstone_wire south none east side north up power 6 west side 2550 redstone_wire south none east side north up power 6 west none 2551 redstone_wire south up east side north up power 7 west up 2552 redstone_wire south up east side north up power 7 west side 2553 redstone_wire south up east side north up power 7 west none 2554 redstone_wire south side east side north up power 7 west up 2555 redstone_wire south side east side north up power 7 west side 2556 redstone_wire south side east side north up power 7 west none 2557 redstone_wire south none east side north up power 7 west up 2558 redstone_wire south none east side north up power 7 west side 2559 redstone_wire south none east side north up power 7 west none 2560 redstone_wire south up east side north up power 8 west up 2561 redstone_wire south up east side north up power 8 west side 2562 redstone_wire south up east side north up power 8 west none 2563 redstone_wire south side east side north up power 8 west up 2564 redstone_wire south side east side north up power 8 west side 2565 redstone_wire south side east side north up power 8 west none 2566 redstone_wire south none east side north up power 8 west up 2567 redstone_wire south none east side north up power 8 west side 2568 redstone_wire south none east side north up power 8 west none 2569 redstone_wire south up east side north up power 9 west up 2570 redstone_wire south up east side north up power 9 west side 2571 redstone_wire south up east side north up power 9 west none 2572 redstone_wire south side east side north up power 9 west up 2573 redstone_wire south side east side north up power 9 west side 2574 redstone_wire south side east side north up power 9 west none 2575 redstone_wire south none east side north up power 9 west up 2576 redstone_wire south none east side north up power 9 west side 2577 redstone_wire south none east side north up power 9 west none 2578 redstone_wire south up east side north up power 10 west up 2579 redstone_wire south up east side north up power 10 west side 2580 redstone_wire south up east side north up power 10 west none 2581 redstone_wire south side east side north up power 10 west up 2582 redstone_wire south side east side north up power 10 west side 2583 redstone_wire south side east side north up power 10 west none 2584 redstone_wire south none east side north up power 10 west up 2585 redstone_wire south none east side north up power 10 west side 2586 redstone_wire south none east side north up power 10 west none 2587 redstone_wire south up east side north up power 11 west up 2588 redstone_wire south up east side north up power 11 west side 2589 redstone_wire south up east side north up power 11 west none 2590 redstone_wire south side east side north up power 11 west up 2591 redstone_wire south side east side north up power 11 west side 2592 redstone_wire south side east side north up power 11 west none 2593 redstone_wire south none east side north up power 11 west up 2594 redstone_wire south none east side north up power 11 west side 2595 redstone_wire south none east side north up power 11 west none 2596 redstone_wire south up east side north up power 12 west up 2597 redstone_wire south up east side north up power 12 west side 2598 redstone_wire south up east side north up power 12 west none 2599 redstone_wire south side east side north up power 12 west up 2600 redstone_wire south side east side north up power 12 west side 2601 redstone_wire south side east side north up power 12 west none 2602 redstone_wire south none east side north up power 12 west up 2603 redstone_wire south none east side north up power 12 west side 2604 redstone_wire south none east side north up power 12 west none 2605 redstone_wire south up east side north up power 13 west up 2606 redstone_wire south up east side north up power 13 west side 2607 redstone_wire south up east side north up power 13 west none 2608 redstone_wire south side east side north up power 13 west up 2609 redstone_wire south side east side north up power 13 west side 2610 redstone_wire south side east side north up power 13 west none 2611 redstone_wire south none east side north up power 13 west up 2612 redstone_wire south none east side north up power 13 west side 2613 redstone_wire south none east side north up power 13 west none 2614 redstone_wire south up east side north up power 14 west up 2615 redstone_wire south up east side north up power 14 west side 2616 redstone_wire south up east side north up power 14 west none 2617 redstone_wire south side east side north up power 14 west up 2618 redstone_wire south side east side north up power 14 west side 2619 redstone_wire south side east side north up power 14 west none 2620 redstone_wire south none east side north up power 14 west up 2621 redstone_wire south none east side north up power 14 west side 2622 redstone_wire south none east side north up power 14 west none 2623 redstone_wire south up east side north up power 15 west up 2624 redstone_wire south up east side north up power 15 west side 2625 redstone_wire south up east side north up power 15 west none 2626 redstone_wire south side east side north up power 15 west up 2627 redstone_wire south side east side north up power 15 west side 2628 redstone_wire south side east side north up power 15 west none 2629 redstone_wire south none east side north up power 15 west up 2630 redstone_wire south none east side north up power 15 west side 2631 redstone_wire south none east side north up power 15 west none 2632 redstone_wire south up east side north side power 0 west up 2633 redstone_wire south up east side north side power 0 west side 2634 redstone_wire south up east side north side power 0 west none 2635 redstone_wire south side east side north side power 0 west up 2636 redstone_wire south side east side north side power 0 west side 2637 redstone_wire south side east side north side power 0 west none 2638 redstone_wire south none east side north side power 0 west up 2639 redstone_wire south none east side north side power 0 west side 2640 redstone_wire south none east side north side power 0 west none 2641 redstone_wire south up east side north side power 1 west up 2642 redstone_wire south up east side north side power 1 west side 2643 redstone_wire south up east side north side power 1 west none 2644 redstone_wire south side east side north side power 1 west up 2645 redstone_wire south side east side north side power 1 west side 2646 redstone_wire south side east side north side power 1 west none 2647 redstone_wire south none east side north side power 1 west up 2648 redstone_wire south none east side north side power 1 west side 2649 redstone_wire south none east side north side power 1 west none 2650 redstone_wire south up east side north side power 2 west up 2651 redstone_wire south up east side north side power 2 west side 2652 redstone_wire south up east side north side power 2 west none 2653 redstone_wire south side east side north side power 2 west up 2654 redstone_wire south side east side north side power 2 west side 2655 redstone_wire south side east side north side power 2 west none 2656 redstone_wire south none east side north side power 2 west up 2657 redstone_wire south none east side north side power 2 west side 2658 redstone_wire south none east side north side power 2 west none 2659 redstone_wire south up east side north side power 3 west up 2660 redstone_wire south up east side north side power 3 west side 2661 redstone_wire south up east side north side power 3 west none 2662 redstone_wire south side east side north side power 3 west up 2663 redstone_wire south side east side north side power 3 west side 2664 redstone_wire south side east side north side power 3 west none 2665 redstone_wire south none east side north side power 3 west up 2666 redstone_wire south none east side north side power 3 west side 2667 redstone_wire south none east side north side power 3 west none 2668 redstone_wire south up east side north side power 4 west up 2669 redstone_wire south up east side north side power 4 west side 2670 redstone_wire south up east side north side power 4 west none 2671 redstone_wire south side east side north side power 4 west up 2672 redstone_wire south side east side north side power 4 west side 2673 redstone_wire south side east side north side power 4 west none 2674 redstone_wire south none east side north side power 4 west up 2675 redstone_wire south none east side north side power 4 west side 2676 redstone_wire south none east side north side power 4 west none 2677 redstone_wire south up east side north side power 5 west up 2678 redstone_wire south up east side north side power 5 west side 2679 redstone_wire south up east side north side power 5 west none 2680 redstone_wire south side east side north side power 5 west up 2681 redstone_wire south side east side north side power 5 west side 2682 redstone_wire south side east side north side power 5 west none 2683 redstone_wire south none east side north side power 5 west up 2684 redstone_wire south none east side north side power 5 west side 2685 redstone_wire south none east side north side power 5 west none 2686 redstone_wire south up east side north side power 6 west up 2687 redstone_wire south up east side north side power 6 west side 2688 redstone_wire south up east side north side power 6 west none 2689 redstone_wire south side east side north side power 6 west up 2690 redstone_wire south side east side north side power 6 west side 2691 redstone_wire south side east side north side power 6 west none 2692 redstone_wire south none east side north side power 6 west up 2693 redstone_wire south none east side north side power 6 west side 2694 redstone_wire south none east side north side power 6 west none 2695 redstone_wire south up east side north side power 7 west up 2696 redstone_wire south up east side north side power 7 west side 2697 redstone_wire south up east side north side power 7 west none 2698 redstone_wire south side east side north side power 7 west up 2699 redstone_wire south side east side north side power 7 west side 2700 redstone_wire south side east side north side power 7 west none 2701 redstone_wire south none east side north side power 7 west up 2702 redstone_wire south none east side north side power 7 west side 2703 redstone_wire south none east side north side power 7 west none 2704 redstone_wire south up east side north side power 8 west up 2705 redstone_wire south up east side north side power 8 west side 2706 redstone_wire south up east side north side power 8 west none 2707 redstone_wire south side east side north side power 8 west up 2708 redstone_wire south side east side north side power 8 west side 2709 redstone_wire south side east side north side power 8 west none 2710 redstone_wire south none east side north side power 8 west up 2711 redstone_wire south none east side north side power 8 west side 2712 redstone_wire south none east side north side power 8 west none 2713 redstone_wire south up east side north side power 9 west up 2714 redstone_wire south up east side north side power 9 west side 2715 redstone_wire south up east side north side power 9 west none 2716 redstone_wire south side east side north side power 9 west up 2717 redstone_wire south side east side north side power 9 west side 2718 redstone_wire south side east side north side power 9 west none 2719 redstone_wire south none east side north side power 9 west up 2720 redstone_wire south none east side north side power 9 west side 2721 redstone_wire south none east side north side power 9 west none 2722 redstone_wire south up east side north side power 10 west up 2723 redstone_wire south up east side north side power 10 west side 2724 redstone_wire south up east side north side power 10 west none 2725 redstone_wire south side east side north side power 10 west up 2726 redstone_wire south side east side north side power 10 west side 2727 redstone_wire south side east side north side power 10 west none 2728 redstone_wire south none east side north side power 10 west up 2729 redstone_wire south none east side north side power 10 west side 2730 redstone_wire south none east side north side power 10 west none 2731 redstone_wire south up east side north side power 11 west up 2732 redstone_wire south up east side north side power 11 west side 2733 redstone_wire south up east side north side power 11 west none 2734 redstone_wire south side east side north side power 11 west up 2735 redstone_wire south side east side north side power 11 west side 2736 redstone_wire south side east side north side power 11 west none 2737 redstone_wire south none east side north side power 11 west up 2738 redstone_wire south none east side north side power 11 west side 2739 redstone_wire south none east side north side power 11 west none 2740 redstone_wire south up east side north side power 12 west up 2741 redstone_wire south up east side north side power 12 west side 2742 redstone_wire south up east side north side power 12 west none 2743 redstone_wire south side east side north side power 12 west up 2744 redstone_wire south side east side north side power 12 west side 2745 redstone_wire south side east side north side power 12 west none 2746 redstone_wire south none east side north side power 12 west up 2747 redstone_wire south none east side north side power 12 west side 2748 redstone_wire south none east side north side power 12 west none 2749 redstone_wire south up east side north side power 13 west up 2750 redstone_wire south up east side north side power 13 west side 2751 redstone_wire south up east side north side power 13 west none 2752 redstone_wire south side east side north side power 13 west up 2753 redstone_wire south side east side north side power 13 west side 2754 redstone_wire south side east side north side power 13 west none 2755 redstone_wire south none east side north side power 13 west up 2756 redstone_wire south none east side north side power 13 west side 2757 redstone_wire south none east side north side power 13 west none 2758 redstone_wire south up east side north side power 14 west up 2759 redstone_wire south up east side north side power 14 west side 2760 redstone_wire south up east side north side power 14 west none 2761 redstone_wire south side east side north side power 14 west up 2762 redstone_wire south side east side north side power 14 west side 2763 redstone_wire south side east side north side power 14 west none 2764 redstone_wire south none east side north side power 14 west up 2765 redstone_wire south none east side north side power 14 west side 2766 redstone_wire south none east side north side power 14 west none 2767 redstone_wire south up east side north side power 15 west up 2768 redstone_wire south up east side north side power 15 west side 2769 redstone_wire south up east side north side power 15 west none 2770 redstone_wire south side east side north side power 15 west up 2771 redstone_wire south side east side north side power 15 west side 2772 redstone_wire south side east side north side power 15 west none 2773 redstone_wire south none east side north side power 15 west up 2774 redstone_wire south none east side north side power 15 west side 2775 redstone_wire south none east side north side power 15 west none 2776 redstone_wire south up east side north none power 0 west up 2777 redstone_wire south up east side north none power 0 west side 2778 redstone_wire south up east side north none power 0 west none 2779 redstone_wire south side east side north none power 0 west up 2780 redstone_wire south side east side north none power 0 west side 2781 redstone_wire south side east side north none power 0 west none 2782 redstone_wire south none east side north none power 0 west up 2783 redstone_wire south none east side north none power 0 west side 2784 redstone_wire south none east side north none power 0 west none 2785 redstone_wire south up east side north none power 1 west up 2786 redstone_wire south up east side north none power 1 west side 2787 redstone_wire south up east side north none power 1 west none 2788 redstone_wire south side east side north none power 1 west up 2789 redstone_wire south side east side north none power 1 west side 2790 redstone_wire south side east side north none power 1 west none 2791 redstone_wire south none east side north none power 1 west up 2792 redstone_wire south none east side north none power 1 west side 2793 redstone_wire south none east side north none power 1 west none 2794 redstone_wire south up east side north none power 2 west up 2795 redstone_wire south up east side north none power 2 west side 2796 redstone_wire south up east side north none power 2 west none 2797 redstone_wire south side east side north none power 2 west up 2798 redstone_wire south side east side north none power 2 west side 2799 redstone_wire south side east side north none power 2 west none 2800 redstone_wire south none east side north none power 2 west up 2801 redstone_wire south none east side north none power 2 west side 2802 redstone_wire south none east side north none power 2 west none 2803 redstone_wire south up east side north none power 3 west up 2804 redstone_wire south up east side north none power 3 west side 2805 redstone_wire south up east side north none power 3 west none 2806 redstone_wire south side east side north none power 3 west up 2807 redstone_wire south side east side north none power 3 west side 2808 redstone_wire south side east side north none power 3 west none 2809 redstone_wire south none east side north none power 3 west up 2810 redstone_wire south none east side north none power 3 west side 2811 redstone_wire south none east side north none power 3 west none 2812 redstone_wire south up east side north none power 4 west up 2813 redstone_wire south up east side north none power 4 west side 2814 redstone_wire south up east side north none power 4 west none 2815 redstone_wire south side east side north none power 4 west up 2816 redstone_wire south side east side north none power 4 west side 2817 redstone_wire south side east side north none power 4 west none 2818 redstone_wire south none east side north none power 4 west up 2819 redstone_wire south none east side north none power 4 west side 2820 redstone_wire south none east side north none power 4 west none 2821 redstone_wire south up east side north none power 5 west up 2822 redstone_wire south up east side north none power 5 west side 2823 redstone_wire south up east side north none power 5 west none 2824 redstone_wire south side east side north none power 5 west up 2825 redstone_wire south side east side north none power 5 west side 2826 redstone_wire south side east side north none power 5 west none 2827 redstone_wire south none east side north none power 5 west up 2828 redstone_wire south none east side north none power 5 west side 2829 redstone_wire south none east side north none power 5 west none 2830 redstone_wire south up east side north none power 6 west up 2831 redstone_wire south up east side north none power 6 west side 2832 redstone_wire south up east side north none power 6 west none 2833 redstone_wire south side east side north none power 6 west up 2834 redstone_wire south side east side north none power 6 west side 2835 redstone_wire south side east side north none power 6 west none 2836 redstone_wire south none east side north none power 6 west up 2837 redstone_wire south none east side north none power 6 west side 2838 redstone_wire south none east side north none power 6 west none 2839 redstone_wire south up east side north none power 7 west up 2840 redstone_wire south up east side north none power 7 west side 2841 redstone_wire south up east side north none power 7 west none 2842 redstone_wire south side east side north none power 7 west up 2843 redstone_wire south side east side north none power 7 west side 2844 redstone_wire south side east side north none power 7 west none 2845 redstone_wire south none east side north none power 7 west up 2846 redstone_wire south none east side north none power 7 west side 2847 redstone_wire south none east side north none power 7 west none 2848 redstone_wire south up east side north none power 8 west up 2849 redstone_wire south up east side north none power 8 west side 2850 redstone_wire south up east side north none power 8 west none 2851 redstone_wire south side east side north none power 8 west up 2852 redstone_wire south side east side north none power 8 west side 2853 redstone_wire south side east side north none power 8 west none 2854 redstone_wire south none east side north none power 8 west up 2855 redstone_wire south none east side north none power 8 west side 2856 redstone_wire south none east side north none power 8 west none 2857 redstone_wire south up east side north none power 9 west up 2858 redstone_wire south up east side north none power 9 west side 2859 redstone_wire south up east side north none power 9 west none 2860 redstone_wire south side east side north none power 9 west up 2861 redstone_wire south side east side north none power 9 west side 2862 redstone_wire south side east side north none power 9 west none 2863 redstone_wire south none east side north none power 9 west up 2864 redstone_wire south none east side north none power 9 west side 2865 redstone_wire south none east side north none power 9 west none 2866 redstone_wire south up east side north none power 10 west up 2867 redstone_wire south up east side north none power 10 west side 2868 redstone_wire south up east side north none power 10 west none 2869 redstone_wire south side east side north none power 10 west up 2870 redstone_wire south side east side north none power 10 west side 2871 redstone_wire south side east side north none power 10 west none 2872 redstone_wire south none east side north none power 10 west up 2873 redstone_wire south none east side north none power 10 west side 2874 redstone_wire south none east side north none power 10 west none 2875 redstone_wire south up east side north none power 11 west up 2876 redstone_wire south up east side north none power 11 west side 2877 redstone_wire south up east side north none power 11 west none 2878 redstone_wire south side east side north none power 11 west up 2879 redstone_wire south side east side north none power 11 west side 2880 redstone_wire south side east side north none power 11 west none 2881 redstone_wire south none east side north none power 11 west up 2882 redstone_wire south none east side north none power 11 west side 2883 redstone_wire south none east side north none power 11 west none 2884 redstone_wire south up east side north none power 12 west up 2885 redstone_wire south up east side north none power 12 west side 2886 redstone_wire south up east side north none power 12 west none 2887 redstone_wire south side east side north none power 12 west up 2888 redstone_wire south side east side north none power 12 west side 2889 redstone_wire south side east side north none power 12 west none 2890 redstone_wire south none east side north none power 12 west up 2891 redstone_wire south none east side north none power 12 west side 2892 redstone_wire south none east side north none power 12 west none 2893 redstone_wire south up east side north none power 13 west up 2894 redstone_wire south up east side north none power 13 west side 2895 redstone_wire south up east side north none power 13 west none 2896 redstone_wire south side east side north none power 13 west up 2897 redstone_wire south side east side north none power 13 west side 2898 redstone_wire south side east side north none power 13 west none 2899 redstone_wire south none east side north none power 13 west up 2900 redstone_wire south none east side north none power 13 west side 2901 redstone_wire south none east side north none power 13 west none 2902 redstone_wire south up east side north none power 14 west up 2903 redstone_wire south up east side north none power 14 west side 2904 redstone_wire south up east side north none power 14 west none 2905 redstone_wire south side east side north none power 14 west up 2906 redstone_wire south side east side north none power 14 west side 2907 redstone_wire south side east side north none power 14 west none 2908 redstone_wire south none east side north none power 14 west up 2909 redstone_wire south none east side north none power 14 west side 2910 redstone_wire south none east side north none power 14 west none 2911 redstone_wire south up east side north none power 15 west up 2912 redstone_wire south up east side north none power 15 west side 2913 redstone_wire south up east side north none power 15 west none 2914 redstone_wire south side east side north none power 15 west up 2915 redstone_wire south side east side north none power 15 west side 2916 redstone_wire south side east side north none power 15 west none 2917 redstone_wire south none east side north none power 15 west up 2918 redstone_wire south none east side north none power 15 west side 2919 redstone_wire south none east side north none power 15 west none 2920 redstone_wire south up east none north up power 0 west up 2921 redstone_wire south up east none north up power 0 west side 2922 redstone_wire south up east none north up power 0 west none 2923 redstone_wire south side east none north up power 0 west up 2924 redstone_wire south side east none north up power 0 west side 2925 redstone_wire south side east none north up power 0 west none 2926 redstone_wire south none east none north up power 0 west up 2927 redstone_wire south none east none north up power 0 west side 2928 redstone_wire south none east none north up power 0 west none 2929 redstone_wire south up east none north up power 1 west up 2930 redstone_wire south up east none north up power 1 west side 2931 redstone_wire south up east none north up power 1 west none 2932 redstone_wire south side east none north up power 1 west up 2933 redstone_wire south side east none north up power 1 west side 2934 redstone_wire south side east none north up power 1 west none 2935 redstone_wire south none east none north up power 1 west up 2936 redstone_wire south none east none north up power 1 west side 2937 redstone_wire south none east none north up power 1 west none 2938 redstone_wire south up east none north up power 2 west up 2939 redstone_wire south up east none north up power 2 west side 2940 redstone_wire south up east none north up power 2 west none 2941 redstone_wire south side east none north up power 2 west up 2942 redstone_wire south side east none north up power 2 west side 2943 redstone_wire south side east none north up power 2 west none 2944 redstone_wire south none east none north up power 2 west up 2945 redstone_wire south none east none north up power 2 west side 2946 redstone_wire south none east none north up power 2 west none 2947 redstone_wire south up east none north up power 3 west up 2948 redstone_wire south up east none north up power 3 west side 2949 redstone_wire south up east none north up power 3 west none 2950 redstone_wire south side east none north up power 3 west up 2951 redstone_wire south side east none north up power 3 west side 2952 redstone_wire south side east none north up power 3 west none 2953 redstone_wire south none east none north up power 3 west up 2954 redstone_wire south none east none north up power 3 west side 2955 redstone_wire south none east none north up power 3 west none 2956 redstone_wire south up east none north up power 4 west up 2957 redstone_wire south up east none north up power 4 west side 2958 redstone_wire south up east none north up power 4 west none 2959 redstone_wire south side east none north up power 4 west up 2960 redstone_wire south side east none north up power 4 west side 2961 redstone_wire south side east none north up power 4 west none 2962 redstone_wire south none east none north up power 4 west up 2963 redstone_wire south none east none north up power 4 west side 2964 redstone_wire south none east none north up power 4 west none 2965 redstone_wire south up east none north up power 5 west up 2966 redstone_wire south up east none north up power 5 west side 2967 redstone_wire south up east none north up power 5 west none 2968 redstone_wire south side east none north up power 5 west up 2969 redstone_wire south side east none north up power 5 west side 2970 redstone_wire south side east none north up power 5 west none 2971 redstone_wire south none east none north up power 5 west up 2972 redstone_wire south none east none north up power 5 west side 2973 redstone_wire south none east none north up power 5 west none 2974 redstone_wire south up east none north up power 6 west up 2975 redstone_wire south up east none north up power 6 west side 2976 redstone_wire south up east none north up power 6 west none 2977 redstone_wire south side east none north up power 6 west up 2978 redstone_wire south side east none north up power 6 west side 2979 redstone_wire south side east none north up power 6 west none 2980 redstone_wire south none east none north up power 6 west up 2981 redstone_wire south none east none north up power 6 west side 2982 redstone_wire south none east none north up power 6 west none 2983 redstone_wire south up east none north up power 7 west up 2984 redstone_wire south up east none north up power 7 west side 2985 redstone_wire south up east none north up power 7 west none 2986 redstone_wire south side east none north up power 7 west up 2987 redstone_wire south side east none north up power 7 west side 2988 redstone_wire south side east none north up power 7 west none 2989 redstone_wire south none east none north up power 7 west up 2990 redstone_wire south none east none north up power 7 west side 2991 redstone_wire south none east none north up power 7 west none 2992 redstone_wire south up east none north up power 8 west up 2993 redstone_wire south up east none north up power 8 west side 2994 redstone_wire south up east none north up power 8 west none 2995 redstone_wire south side east none north up power 8 west up 2996 redstone_wire south side east none north up power 8 west side 2997 redstone_wire south side east none north up power 8 west none 2998 redstone_wire south none east none north up power 8 west up 2999 redstone_wire south none east none north up power 8 west side 3000 redstone_wire south none east none north up power 8 west none 3001 redstone_wire south up east none north up power 9 west up 3002 redstone_wire south up east none north up power 9 west side 3003 redstone_wire south up east none north up power 9 west none 3004 redstone_wire south side east none north up power 9 west up 3005 redstone_wire south side east none north up power 9 west side 3006 redstone_wire south side east none north up power 9 west none 3007 redstone_wire south none east none north up power 9 west up 3008 redstone_wire south none east none north up power 9 west side 3009 redstone_wire south none east none north up power 9 west none 3010 redstone_wire south up east none north up power 10 west up 3011 redstone_wire south up east none north up power 10 west side 3012 redstone_wire south up east none north up power 10 west none 3013 redstone_wire south side east none north up power 10 west up 3014 redstone_wire south side east none north up power 10 west side 3015 redstone_wire south side east none north up power 10 west none 3016 redstone_wire south none east none north up power 10 west up 3017 redstone_wire south none east none north up power 10 west side 3018 redstone_wire south none east none north up power 10 west none 3019 redstone_wire south up east none north up power 11 west up 3020 redstone_wire south up east none north up power 11 west side 3021 redstone_wire south up east none north up power 11 west none 3022 redstone_wire south side east none north up power 11 west up 3023 redstone_wire south side east none north up power 11 west side 3024 redstone_wire south side east none north up power 11 west none 3025 redstone_wire south none east none north up power 11 west up 3026 redstone_wire south none east none north up power 11 west side 3027 redstone_wire south none east none north up power 11 west none 3028 redstone_wire south up east none north up power 12 west up 3029 redstone_wire south up east none north up power 12 west side 3030 redstone_wire south up east none north up power 12 west none 3031 redstone_wire south side east none north up power 12 west up 3032 redstone_wire south side east none north up power 12 west side 3033 redstone_wire south side east none north up power 12 west none 3034 redstone_wire south none east none north up power 12 west up 3035 redstone_wire south none east none north up power 12 west side 3036 redstone_wire south none east none north up power 12 west none 3037 redstone_wire south up east none north up power 13 west up 3038 redstone_wire south up east none north up power 13 west side 3039 redstone_wire south up east none north up power 13 west none 3040 redstone_wire south side east none north up power 13 west up 3041 redstone_wire south side east none north up power 13 west side 3042 redstone_wire south side east none north up power 13 west none 3043 redstone_wire south none east none north up power 13 west up 3044 redstone_wire south none east none north up power 13 west side 3045 redstone_wire south none east none north up power 13 west none 3046 redstone_wire south up east none north up power 14 west up 3047 redstone_wire south up east none north up power 14 west side 3048 redstone_wire south up east none north up power 14 west none 3049 redstone_wire south side east none north up power 14 west up 3050 redstone_wire south side east none north up power 14 west side 3051 redstone_wire south side east none north up power 14 west none 3052 redstone_wire south none east none north up power 14 west up 3053 redstone_wire south none east none north up power 14 west side 3054 redstone_wire south none east none north up power 14 west none 3055 redstone_wire south up east none north up power 15 west up 3056 redstone_wire south up east none north up power 15 west side 3057 redstone_wire south up east none north up power 15 west none 3058 redstone_wire south side east none north up power 15 west up 3059 redstone_wire south side east none north up power 15 west side 3060 redstone_wire south side east none north up power 15 west none 3061 redstone_wire south none east none north up power 15 west up 3062 redstone_wire south none east none north up power 15 west side 3063 redstone_wire south none east none north up power 15 west none 3064 redstone_wire south up east none north side power 0 west up 3065 redstone_wire south up east none north side power 0 west side 3066 redstone_wire south up east none north side power 0 west none 3067 redstone_wire south side east none north side power 0 west up 3068 redstone_wire south side east none north side power 0 west side 3069 redstone_wire south side east none north side power 0 west none 3070 redstone_wire south none east none north side power 0 west up 3071 redstone_wire south none east none north side power 0 west side 3072 redstone_wire south none east none north side power 0 west none 3073 redstone_wire south up east none north side power 1 west up 3074 redstone_wire south up east none north side power 1 west side 3075 redstone_wire south up east none north side power 1 west none 3076 redstone_wire south side east none north side power 1 west up 3077 redstone_wire south side east none north side power 1 west side 3078 redstone_wire south side east none north side power 1 west none 3079 redstone_wire south none east none north side power 1 west up 3080 redstone_wire south none east none north side power 1 west side 3081 redstone_wire south none east none north side power 1 west none 3082 redstone_wire south up east none north side power 2 west up 3083 redstone_wire south up east none north side power 2 west side 3084 redstone_wire south up east none north side power 2 west none 3085 redstone_wire south side east none north side power 2 west up 3086 redstone_wire south side east none north side power 2 west side 3087 redstone_wire south side east none north side power 2 west none 3088 redstone_wire south none east none north side power 2 west up 3089 redstone_wire south none east none north side power 2 west side 3090 redstone_wire south none east none north side power 2 west none 3091 redstone_wire south up east none north side power 3 west up 3092 redstone_wire south up east none north side power 3 west side 3093 redstone_wire south up east none north side power 3 west none 3094 redstone_wire south side east none north side power 3 west up 3095 redstone_wire south side east none north side power 3 west side 3096 redstone_wire south side east none north side power 3 west none 3097 redstone_wire south none east none north side power 3 west up 3098 redstone_wire south none east none north side power 3 west side 3099 redstone_wire south none east none north side power 3 west none 3100 redstone_wire south up east none north side power 4 west up 3101 redstone_wire south up east none north side power 4 west side 3102 redstone_wire south up east none north side power 4 west none 3103 redstone_wire south side east none north side power 4 west up 3104 redstone_wire south side east none north side power 4 west side 3105 redstone_wire south side east none north side power 4 west none 3106 redstone_wire south none east none north side power 4 west up 3107 redstone_wire south none east none north side power 4 west side 3108 redstone_wire south none east none north side power 4 west none 3109 redstone_wire south up east none north side power 5 west up 3110 redstone_wire south up east none north side power 5 west side 3111 redstone_wire south up east none north side power 5 west none 3112 redstone_wire south side east none north side power 5 west up 3113 redstone_wire south side east none north side power 5 west side 3114 redstone_wire south side east none north side power 5 west none 3115 redstone_wire south none east none north side power 5 west up 3116 redstone_wire south none east none north side power 5 west side 3117 redstone_wire south none east none north side power 5 west none 3118 redstone_wire south up east none north side power 6 west up 3119 redstone_wire south up east none north side power 6 west side 3120 redstone_wire south up east none north side power 6 west none 3121 redstone_wire south side east none north side power 6 west up 3122 redstone_wire south side east none north side power 6 west side 3123 redstone_wire south side east none north side power 6 west none 3124 redstone_wire south none east none north side power 6 west up 3125 redstone_wire south none east none north side power 6 west side 3126 redstone_wire south none east none north side power 6 west none 3127 redstone_wire south up east none north side power 7 west up 3128 redstone_wire south up east none north side power 7 west side 3129 redstone_wire south up east none north side power 7 west none 3130 redstone_wire south side east none north side power 7 west up 3131 redstone_wire south side east none north side power 7 west side 3132 redstone_wire south side east none north side power 7 west none 3133 redstone_wire south none east none north side power 7 west up 3134 redstone_wire south none east none north side power 7 west side 3135 redstone_wire south none east none north side power 7 west none 3136 redstone_wire south up east none north side power 8 west up 3137 redstone_wire south up east none north side power 8 west side 3138 redstone_wire south up east none north side power 8 west none 3139 redstone_wire south side east none north side power 8 west up 3140 redstone_wire south side east none north side power 8 west side 3141 redstone_wire south side east none north side power 8 west none 3142 redstone_wire south none east none north side power 8 west up 3143 redstone_wire south none east none north side power 8 west side 3144 redstone_wire south none east none north side power 8 west none 3145 redstone_wire south up east none north side power 9 west up 3146 redstone_wire south up east none north side power 9 west side 3147 redstone_wire south up east none north side power 9 west none 3148 redstone_wire south side east none north side power 9 west up 3149 redstone_wire south side east none north side power 9 west side 3150 redstone_wire south side east none north side power 9 west none 3151 redstone_wire south none east none north side power 9 west up 3152 redstone_wire south none east none north side power 9 west side 3153 redstone_wire south none east none north side power 9 west none 3154 redstone_wire south up east none north side power 10 west up 3155 redstone_wire south up east none north side power 10 west side 3156 redstone_wire south up east none north side power 10 west none 3157 redstone_wire south side east none north side power 10 west up 3158 redstone_wire south side east none north side power 10 west side 3159 redstone_wire south side east none north side power 10 west none 3160 redstone_wire south none east none north side power 10 west up 3161 redstone_wire south none east none north side power 10 west side 3162 redstone_wire south none east none north side power 10 west none 3163 redstone_wire south up east none north side power 11 west up 3164 redstone_wire south up east none north side power 11 west side 3165 redstone_wire south up east none north side power 11 west none 3166 redstone_wire south side east none north side power 11 west up 3167 redstone_wire south side east none north side power 11 west side 3168 redstone_wire south side east none north side power 11 west none 3169 redstone_wire south none east none north side power 11 west up 3170 redstone_wire south none east none north side power 11 west side 3171 redstone_wire south none east none north side power 11 west none 3172 redstone_wire south up east none north side power 12 west up 3173 redstone_wire south up east none north side power 12 west side 3174 redstone_wire south up east none north side power 12 west none 3175 redstone_wire south side east none north side power 12 west up 3176 redstone_wire south side east none north side power 12 west side 3177 redstone_wire south side east none north side power 12 west none 3178 redstone_wire south none east none north side power 12 west up 3179 redstone_wire south none east none north side power 12 west side 3180 redstone_wire south none east none north side power 12 west none 3181 redstone_wire south up east none north side power 13 west up 3182 redstone_wire south up east none north side power 13 west side 3183 redstone_wire south up east none north side power 13 west none 3184 redstone_wire south side east none north side power 13 west up 3185 redstone_wire south side east none north side power 13 west side 3186 redstone_wire south side east none north side power 13 west none 3187 redstone_wire south none east none north side power 13 west up 3188 redstone_wire south none east none north side power 13 west side 3189 redstone_wire south none east none north side power 13 west none 3190 redstone_wire south up east none north side power 14 west up 3191 redstone_wire south up east none north side power 14 west side 3192 redstone_wire south up east none north side power 14 west none 3193 redstone_wire south side east none north side power 14 west up 3194 redstone_wire south side east none north side power 14 west side 3195 redstone_wire south side east none north side power 14 west none 3196 redstone_wire south none east none north side power 14 west up 3197 redstone_wire south none east none north side power 14 west side 3198 redstone_wire south none east none north side power 14 west none 3199 redstone_wire south up east none north side power 15 west up 3200 redstone_wire south up east none north side power 15 west side 3201 redstone_wire south up east none north side power 15 west none 3202 redstone_wire south side east none north side power 15 west up 3203 redstone_wire south side east none north side power 15 west side 3204 redstone_wire south side east none north side power 15 west none 3205 redstone_wire south none east none north side power 15 west up 3206 redstone_wire south none east none north side power 15 west side 3207 redstone_wire south none east none north side power 15 west none 3208 redstone_wire south up east none north none power 0 west up 3209 redstone_wire south up east none north none power 0 west side 3210 redstone_wire south up east none north none power 0 west none 3211 redstone_wire south side east none north none power 0 west up 3212 redstone_wire south side east none north none power 0 west side 3213 redstone_wire south side east none north none power 0 west none 3214 redstone_wire south none east none north none power 0 west up 3215 redstone_wire south none east none north none power 0 west side 3216 redstone_wire south none east none north none power 0 west none 3217 redstone_wire south up east none north none power 1 west up 3218 redstone_wire south up east none north none power 1 west side 3219 redstone_wire south up east none north none power 1 west none 3220 redstone_wire south side east none north none power 1 west up 3221 redstone_wire south side east none north none power 1 west side 3222 redstone_wire south side east none north none power 1 west none 3223 redstone_wire south none east none north none power 1 west up 3224 redstone_wire south none east none north none power 1 west side 3225 redstone_wire south none east none north none power 1 west none 3226 redstone_wire south up east none north none power 2 west up 3227 redstone_wire south up east none north none power 2 west side 3228 redstone_wire south up east none north none power 2 west none 3229 redstone_wire south side east none north none power 2 west up 3230 redstone_wire south side east none north none power 2 west side 3231 redstone_wire south side east none north none power 2 west none 3232 redstone_wire south none east none north none power 2 west up 3233 redstone_wire south none east none north none power 2 west side 3234 redstone_wire south none east none north none power 2 west none 3235 redstone_wire south up east none north none power 3 west up 3236 redstone_wire south up east none north none power 3 west side 3237 redstone_wire south up east none north none power 3 west none 3238 redstone_wire south side east none north none power 3 west up 3239 redstone_wire south side east none north none power 3 west side 3240 redstone_wire south side east none north none power 3 west none 3241 redstone_wire south none east none north none power 3 west up 3242 redstone_wire south none east none north none power 3 west side 3243 redstone_wire south none east none north none power 3 west none 3244 redstone_wire south up east none north none power 4 west up 3245 redstone_wire south up east none north none power 4 west side 3246 redstone_wire south up east none north none power 4 west none 3247 redstone_wire south side east none north none power 4 west up 3248 redstone_wire south side east none north none power 4 west side 3249 redstone_wire south side east none north none power 4 west none 3250 redstone_wire south none east none north none power 4 west up 3251 redstone_wire south none east none north none power 4 west side 3252 redstone_wire south none east none north none power 4 west none 3253 redstone_wire south up east none north none power 5 west up 3254 redstone_wire south up east none north none power 5 west side 3255 redstone_wire south up east none north none power 5 west none 3256 redstone_wire south side east none north none power 5 west up 3257 redstone_wire south side east none north none power 5 west side 3258 redstone_wire south side east none north none power 5 west none 3259 redstone_wire south none east none north none power 5 west up 3260 redstone_wire south none east none north none power 5 west side 3261 redstone_wire south none east none north none power 5 west none 3262 redstone_wire south up east none north none power 6 west up 3263 redstone_wire south up east none north none power 6 west side 3264 redstone_wire south up east none north none power 6 west none 3265 redstone_wire south side east none north none power 6 west up 3266 redstone_wire south side east none north none power 6 west side 3267 redstone_wire south side east none north none power 6 west none 3268 redstone_wire south none east none north none power 6 west up 3269 redstone_wire south none east none north none power 6 west side 3270 redstone_wire south none east none north none power 6 west none 3271 redstone_wire south up east none north none power 7 west up 3272 redstone_wire south up east none north none power 7 west side 3273 redstone_wire south up east none north none power 7 west none 3274 redstone_wire south side east none north none power 7 west up 3275 redstone_wire south side east none north none power 7 west side 3276 redstone_wire south side east none north none power 7 west none 3277 redstone_wire south none east none north none power 7 west up 3278 redstone_wire south none east none north none power 7 west side 3279 redstone_wire south none east none north none power 7 west none 3280 redstone_wire south up east none north none power 8 west up 3281 redstone_wire south up east none north none power 8 west side 3282 redstone_wire south up east none north none power 8 west none 3283 redstone_wire south side east none north none power 8 west up 3284 redstone_wire south side east none north none power 8 west side 3285 redstone_wire south side east none north none power 8 west none 3286 redstone_wire south none east none north none power 8 west up 3287 redstone_wire south none east none north none power 8 west side 3288 redstone_wire south none east none north none power 8 west none 3289 redstone_wire south up east none north none power 9 west up 3290 redstone_wire south up east none north none power 9 west side 3291 redstone_wire south up east none north none power 9 west none 3292 redstone_wire south side east none north none power 9 west up 3293 redstone_wire south side east none north none power 9 west side 3294 redstone_wire south side east none north none power 9 west none 3295 redstone_wire south none east none north none power 9 west up 3296 redstone_wire south none east none north none power 9 west side 3297 redstone_wire south none east none north none power 9 west none 3298 redstone_wire south up east none north none power 10 west up 3299 redstone_wire south up east none north none power 10 west side 3300 redstone_wire south up east none north none power 10 west none 3301 redstone_wire south side east none north none power 10 west up 3302 redstone_wire south side east none north none power 10 west side 3303 redstone_wire south side east none north none power 10 west none 3304 redstone_wire south none east none north none power 10 west up 3305 redstone_wire south none east none north none power 10 west side 3306 redstone_wire south none east none north none power 10 west none 3307 redstone_wire south up east none north none power 11 west up 3308 redstone_wire south up east none north none power 11 west side 3309 redstone_wire south up east none north none power 11 west none 3310 redstone_wire south side east none north none power 11 west up 3311 redstone_wire south side east none north none power 11 west side 3312 redstone_wire south side east none north none power 11 west none 3313 redstone_wire south none east none north none power 11 west up 3314 redstone_wire south none east none north none power 11 west side 3315 redstone_wire south none east none north none power 11 west none 3316 redstone_wire south up east none north none power 12 west up 3317 redstone_wire south up east none north none power 12 west side 3318 redstone_wire south up east none north none power 12 west none 3319 redstone_wire south side east none north none power 12 west up 3320 redstone_wire south side east none north none power 12 west side 3321 redstone_wire south side east none north none power 12 west none 3322 redstone_wire south none east none north none power 12 west up 3323 redstone_wire south none east none north none power 12 west side 3324 redstone_wire south none east none north none power 12 west none 3325 redstone_wire south up east none north none power 13 west up 3326 redstone_wire south up east none north none power 13 west side 3327 redstone_wire south up east none north none power 13 west none 3328 redstone_wire south side east none north none power 13 west up 3329 redstone_wire south side east none north none power 13 west side 3330 redstone_wire south side east none north none power 13 west none 3331 redstone_wire south none east none north none power 13 west up 3332 redstone_wire south none east none north none power 13 west side 3333 redstone_wire south none east none north none power 13 west none 3334 redstone_wire south up east none north none power 14 west up 3335 redstone_wire south up east none north none power 14 west side 3336 redstone_wire south up east none north none power 14 west none 3337 redstone_wire south side east none north none power 14 west up 3338 redstone_wire south side east none north none power 14 west side 3339 redstone_wire south side east none north none power 14 west none 3340 redstone_wire south none east none north none power 14 west up 3341 redstone_wire south none east none north none power 14 west side 3342 redstone_wire south none east none north none power 14 west none 3343 redstone_wire south up east none north none power 15 west up 3344 redstone_wire south up east none north none power 15 west side 3345 redstone_wire south up east none north none power 15 west none 3346 redstone_wire south side east none north none power 15 west up 3347 redstone_wire south side east none north none power 15 west side 3348 redstone_wire south side east none north none power 15 west none 3349 redstone_wire south none east none north none power 15 west up 3350 redstone_wire south none east none north none power 15 west side 3351 redstone_wire south none east none north none power 15 west none 3352 diamond_ore 3353 diamond_block 3354 crafting_table 3355 wheat age 0 3356 wheat age 1 3357 wheat age 2 3358 wheat age 3 3359 wheat age 4 3360 wheat age 5 3361 wheat age 6 3362 wheat age 7 3363 farmland moisture 0 3364 farmland moisture 1 3365 farmland moisture 2 3366 farmland moisture 3 3367 farmland moisture 4 3368 farmland moisture 5 3369 farmland moisture 6 3370 farmland moisture 7 3371 furnace facing north lit true 3372 furnace facing north lit false 3373 furnace facing south lit true 3374 furnace facing south lit false 3375 furnace facing west lit true 3376 furnace facing west lit false 3377 furnace facing east lit true 3378 furnace facing east lit false 3379 oak_sign waterlogged true rotation 0 3380 oak_sign waterlogged false rotation 0 3381 oak_sign waterlogged true rotation 1 3382 oak_sign waterlogged false rotation 1 3383 oak_sign waterlogged true rotation 2 3384 oak_sign waterlogged false rotation 2 3385 oak_sign waterlogged true rotation 3 3386 oak_sign waterlogged false rotation 3 3387 oak_sign waterlogged true rotation 4 3388 oak_sign waterlogged false rotation 4 3389 oak_sign waterlogged true rotation 5 3390 oak_sign waterlogged false rotation 5 3391 oak_sign waterlogged true rotation 6 3392 oak_sign waterlogged false rotation 6 3393 oak_sign waterlogged true rotation 7 3394 oak_sign waterlogged false rotation 7 3395 oak_sign waterlogged true rotation 8 3396 oak_sign waterlogged false rotation 8 3397 oak_sign waterlogged true rotation 9 3398 oak_sign waterlogged false rotation 9 3399 oak_sign waterlogged true rotation 10 3400 oak_sign waterlogged false rotation 10 3401 oak_sign waterlogged true rotation 11 3402 oak_sign waterlogged false rotation 11 3403 oak_sign waterlogged true rotation 12 3404 oak_sign waterlogged false rotation 12 3405 oak_sign waterlogged true rotation 13 3406 oak_sign waterlogged false rotation 13 3407 oak_sign waterlogged true rotation 14 3408 oak_sign waterlogged false rotation 14 3409 oak_sign waterlogged true rotation 15 3410 oak_sign waterlogged false rotation 15 3411 spruce_sign waterlogged true rotation 0 3412 spruce_sign waterlogged false rotation 0 3413 spruce_sign waterlogged true rotation 1 3414 spruce_sign waterlogged false rotation 1 3415 spruce_sign waterlogged true rotation 2 3416 spruce_sign waterlogged false rotation 2 3417 spruce_sign waterlogged true rotation 3 3418 spruce_sign waterlogged false rotation 3 3419 spruce_sign waterlogged true rotation 4 3420 spruce_sign waterlogged false rotation 4 3421 spruce_sign waterlogged true rotation 5 3422 spruce_sign waterlogged false rotation 5 3423 spruce_sign waterlogged true rotation 6 3424 spruce_sign waterlogged false rotation 6 3425 spruce_sign waterlogged true rotation 7 3426 spruce_sign waterlogged false rotation 7 3427 spruce_sign waterlogged true rotation 8 3428 spruce_sign waterlogged false rotation 8 3429 spruce_sign waterlogged true rotation 9 3430 spruce_sign waterlogged false rotation 9 3431 spruce_sign waterlogged true rotation 10 3432 spruce_sign waterlogged false rotation 10 3433 spruce_sign waterlogged true rotation 11 3434 spruce_sign waterlogged false rotation 11 3435 spruce_sign waterlogged true rotation 12 3436 spruce_sign waterlogged false rotation 12 3437 spruce_sign waterlogged true rotation 13 3438 spruce_sign waterlogged false rotation 13 3439 spruce_sign waterlogged true rotation 14 3440 spruce_sign waterlogged false rotation 14 3441 spruce_sign waterlogged true rotation 15 3442 spruce_sign waterlogged false rotation 15 3443 birch_sign waterlogged true rotation 0 3444 birch_sign waterlogged false rotation 0 3445 birch_sign waterlogged true rotation 1 3446 birch_sign waterlogged false rotation 1 3447 birch_sign waterlogged true rotation 2 3448 birch_sign waterlogged false rotation 2 3449 birch_sign waterlogged true rotation 3 3450 birch_sign waterlogged false rotation 3 3451 birch_sign waterlogged true rotation 4 3452 birch_sign waterlogged false rotation 4 3453 birch_sign waterlogged true rotation 5 3454 birch_sign waterlogged false rotation 5 3455 birch_sign waterlogged true rotation 6 3456 birch_sign waterlogged false rotation 6 3457 birch_sign waterlogged true rotation 7 3458 birch_sign waterlogged false rotation 7 3459 birch_sign waterlogged true rotation 8 3460 birch_sign waterlogged false rotation 8 3461 birch_sign waterlogged true rotation 9 3462 birch_sign waterlogged false rotation 9 3463 birch_sign waterlogged true rotation 10 3464 birch_sign waterlogged false rotation 10 3465 birch_sign waterlogged true rotation 11 3466 birch_sign waterlogged false rotation 11 3467 birch_sign waterlogged true rotation 12 3468 birch_sign waterlogged false rotation 12 3469 birch_sign waterlogged true rotation 13 3470 birch_sign waterlogged false rotation 13 3471 birch_sign waterlogged true rotation 14 3472 birch_sign waterlogged false rotation 14 3473 birch_sign waterlogged true rotation 15 3474 birch_sign waterlogged false rotation 15 3475 acacia_sign waterlogged true rotation 0 3476 acacia_sign waterlogged false rotation 0 3477 acacia_sign waterlogged true rotation 1 3478 acacia_sign waterlogged false rotation 1 3479 acacia_sign waterlogged true rotation 2 3480 acacia_sign waterlogged false rotation 2 3481 acacia_sign waterlogged true rotation 3 3482 acacia_sign waterlogged false rotation 3 3483 acacia_sign waterlogged true rotation 4 3484 acacia_sign waterlogged false rotation 4 3485 acacia_sign waterlogged true rotation 5 3486 acacia_sign waterlogged false rotation 5 3487 acacia_sign waterlogged true rotation 6 3488 acacia_sign waterlogged false rotation 6 3489 acacia_sign waterlogged true rotation 7 3490 acacia_sign waterlogged false rotation 7 3491 acacia_sign waterlogged true rotation 8 3492 acacia_sign waterlogged false rotation 8 3493 acacia_sign waterlogged true rotation 9 3494 acacia_sign waterlogged false rotation 9 3495 acacia_sign waterlogged true rotation 10 3496 acacia_sign waterlogged false rotation 10 3497 acacia_sign waterlogged true rotation 11 3498 acacia_sign waterlogged false rotation 11 3499 acacia_sign waterlogged true rotation 12 3500 acacia_sign waterlogged false rotation 12 3501 acacia_sign waterlogged true rotation 13 3502 acacia_sign waterlogged false rotation 13 3503 acacia_sign waterlogged true rotation 14 3504 acacia_sign waterlogged false rotation 14 3505 acacia_sign waterlogged true rotation 15 3506 acacia_sign waterlogged false rotation 15 3507 jungle_sign waterlogged true rotation 0 3508 jungle_sign waterlogged false rotation 0 3509 jungle_sign waterlogged true rotation 1 3510 jungle_sign waterlogged false rotation 1 3511 jungle_sign waterlogged true rotation 2 3512 jungle_sign waterlogged false rotation 2 3513 jungle_sign waterlogged true rotation 3 3514 jungle_sign waterlogged false rotation 3 3515 jungle_sign waterlogged true rotation 4 3516 jungle_sign waterlogged false rotation 4 3517 jungle_sign waterlogged true rotation 5 3518 jungle_sign waterlogged false rotation 5 3519 jungle_sign waterlogged true rotation 6 3520 jungle_sign waterlogged false rotation 6 3521 jungle_sign waterlogged true rotation 7 3522 jungle_sign waterlogged false rotation 7 3523 jungle_sign waterlogged true rotation 8 3524 jungle_sign waterlogged false rotation 8 3525 jungle_sign waterlogged true rotation 9 3526 jungle_sign waterlogged false rotation 9 3527 jungle_sign waterlogged true rotation 10 3528 jungle_sign waterlogged false rotation 10 3529 jungle_sign waterlogged true rotation 11 3530 jungle_sign waterlogged false rotation 11 3531 jungle_sign waterlogged true rotation 12 3532 jungle_sign waterlogged false rotation 12 3533 jungle_sign waterlogged true rotation 13 3534 jungle_sign waterlogged false rotation 13 3535 jungle_sign waterlogged true rotation 14 3536 jungle_sign waterlogged false rotation 14 3537 jungle_sign waterlogged true rotation 15 3538 jungle_sign waterlogged false rotation 15 3539 dark_oak_sign waterlogged true rotation 0 3540 dark_oak_sign waterlogged false rotation 0 3541 dark_oak_sign waterlogged true rotation 1 3542 dark_oak_sign waterlogged false rotation 1 3543 dark_oak_sign waterlogged true rotation 2 3544 dark_oak_sign waterlogged false rotation 2 3545 dark_oak_sign waterlogged true rotation 3 3546 dark_oak_sign waterlogged false rotation 3 3547 dark_oak_sign waterlogged true rotation 4 3548 dark_oak_sign waterlogged false rotation 4 3549 dark_oak_sign waterlogged true rotation 5 3550 dark_oak_sign waterlogged false rotation 5 3551 dark_oak_sign waterlogged true rotation 6 3552 dark_oak_sign waterlogged false rotation 6 3553 dark_oak_sign waterlogged true rotation 7 3554 dark_oak_sign waterlogged false rotation 7 3555 dark_oak_sign waterlogged true rotation 8 3556 dark_oak_sign waterlogged false rotation 8 3557 dark_oak_sign waterlogged true rotation 9 3558 dark_oak_sign waterlogged false rotation 9 3559 dark_oak_sign waterlogged true rotation 10 3560 dark_oak_sign waterlogged false rotation 10 3561 dark_oak_sign waterlogged true rotation 11 3562 dark_oak_sign waterlogged false rotation 11 3563 dark_oak_sign waterlogged true rotation 12 3564 dark_oak_sign waterlogged false rotation 12 3565 dark_oak_sign waterlogged true rotation 13 3566 dark_oak_sign waterlogged false rotation 13 3567 dark_oak_sign waterlogged true rotation 14 3568 dark_oak_sign waterlogged false rotation 14 3569 dark_oak_sign waterlogged true rotation 15 3570 dark_oak_sign waterlogged false rotation 15 3571 oak_door hinge left half upper facing north powered true open true 3572 oak_door hinge left half upper facing north powered false open true 3573 oak_door hinge left half upper facing north powered true open false 3574 oak_door hinge left half upper facing north powered false open false 3575 oak_door hinge right half upper facing north powered true open true 3576 oak_door hinge right half upper facing north powered false open true 3577 oak_door hinge right half upper facing north powered true open false 3578 oak_door hinge right half upper facing north powered false open false 3579 oak_door hinge left half lower facing north powered true open true 3580 oak_door hinge left half lower facing north powered false open true 3581 oak_door hinge left half lower facing north powered true open false 3582 oak_door hinge left half lower facing north powered false open false 3583 oak_door hinge right half lower facing north powered true open true 3584 oak_door hinge right half lower facing north powered false open true 3585 oak_door hinge right half lower facing north powered true open false 3586 oak_door hinge right half lower facing north powered false open false 3587 oak_door hinge left half upper facing south powered true open true 3588 oak_door hinge left half upper facing south powered false open true 3589 oak_door hinge left half upper facing south powered true open false 3590 oak_door hinge left half upper facing south powered false open false 3591 oak_door hinge right half upper facing south powered true open true 3592 oak_door hinge right half upper facing south powered false open true 3593 oak_door hinge right half upper facing south powered true open false 3594 oak_door hinge right half upper facing south powered false open false 3595 oak_door hinge left half lower facing south powered true open true 3596 oak_door hinge left half lower facing south powered false open true 3597 oak_door hinge left half lower facing south powered true open false 3598 oak_door hinge left half lower facing south powered false open false 3599 oak_door hinge right half lower facing south powered true open true 3600 oak_door hinge right half lower facing south powered false open true 3601 oak_door hinge right half lower facing south powered true open false 3602 oak_door hinge right half lower facing south powered false open false 3603 oak_door hinge left half upper facing west powered true open true 3604 oak_door hinge left half upper facing west powered false open true 3605 oak_door hinge left half upper facing west powered true open false 3606 oak_door hinge left half upper facing west powered false open false 3607 oak_door hinge right half upper facing west powered true open true 3608 oak_door hinge right half upper facing west powered false open true 3609 oak_door hinge right half upper facing west powered true open false 3610 oak_door hinge right half upper facing west powered false open false 3611 oak_door hinge left half lower facing west powered true open true 3612 oak_door hinge left half lower facing west powered false open true 3613 oak_door hinge left half lower facing west powered true open false 3614 oak_door hinge left half lower facing west powered false open false 3615 oak_door hinge right half lower facing west powered true open true 3616 oak_door hinge right half lower facing west powered false open true 3617 oak_door hinge right half lower facing west powered true open false 3618 oak_door hinge right half lower facing west powered false open false 3619 oak_door hinge left half upper facing east powered true open true 3620 oak_door hinge left half upper facing east powered false open true 3621 oak_door hinge left half upper facing east powered true open false 3622 oak_door hinge left half upper facing east powered false open false 3623 oak_door hinge right half upper facing east powered true open true 3624 oak_door hinge right half upper facing east powered false open true 3625 oak_door hinge right half upper facing east powered true open false 3626 oak_door hinge right half upper facing east powered false open false 3627 oak_door hinge left half lower facing east powered true open true 3628 oak_door hinge left half lower facing east powered false open true 3629 oak_door hinge left half lower facing east powered true open false 3630 oak_door hinge left half lower facing east powered false open false 3631 oak_door hinge right half lower facing east powered true open true 3632 oak_door hinge right half lower facing east powered false open true 3633 oak_door hinge right half lower facing east powered true open false 3634 oak_door hinge right half lower facing east powered false open false 3635 ladder facing north waterlogged true 3636 ladder facing north waterlogged false 3637 ladder facing south waterlogged true 3638 ladder facing south waterlogged false 3639 ladder facing west waterlogged true 3640 ladder facing west waterlogged false 3641 ladder facing east waterlogged true 3642 ladder facing east waterlogged false 3643 rail shape north_south 3644 rail shape east_west 3645 rail shape ascending_east 3646 rail shape ascending_west 3647 rail shape ascending_north 3648 rail shape ascending_south 3649 rail shape south_east 3650 rail shape south_west 3651 rail shape north_west 3652 rail shape north_east 3653 cobblestone_stairs facing north waterlogged true shape straight half top 3654 cobblestone_stairs facing north waterlogged false shape straight half top 3655 cobblestone_stairs facing north waterlogged true shape inner_left half top 3656 cobblestone_stairs facing north waterlogged false shape inner_left half top 3657 cobblestone_stairs facing north waterlogged true shape inner_right half top 3658 cobblestone_stairs facing north waterlogged false shape inner_right half top 3659 cobblestone_stairs facing north waterlogged true shape outer_left half top 3660 cobblestone_stairs facing north waterlogged false shape outer_left half top 3661 cobblestone_stairs facing north waterlogged true shape outer_right half top 3662 cobblestone_stairs facing north waterlogged false shape outer_right half top 3663 cobblestone_stairs facing north waterlogged true shape straight half bottom 3664 cobblestone_stairs facing north waterlogged false shape straight half bottom 3665 cobblestone_stairs facing north waterlogged true shape inner_left half bottom 3666 cobblestone_stairs facing north waterlogged false shape inner_left half bottom 3667 cobblestone_stairs facing north waterlogged true shape inner_right half bottom 3668 cobblestone_stairs facing north waterlogged false shape inner_right half bottom 3669 cobblestone_stairs facing north waterlogged true shape outer_left half bottom 3670 cobblestone_stairs facing north waterlogged false shape outer_left half bottom 3671 cobblestone_stairs facing north waterlogged true shape outer_right half bottom 3672 cobblestone_stairs facing north waterlogged false shape outer_right half bottom 3673 cobblestone_stairs facing south waterlogged true shape straight half top 3674 cobblestone_stairs facing south waterlogged false shape straight half top 3675 cobblestone_stairs facing south waterlogged true shape inner_left half top 3676 cobblestone_stairs facing south waterlogged false shape inner_left half top 3677 cobblestone_stairs facing south waterlogged true shape inner_right half top 3678 cobblestone_stairs facing south waterlogged false shape inner_right half top 3679 cobblestone_stairs facing south waterlogged true shape outer_left half top 3680 cobblestone_stairs facing south waterlogged false shape outer_left half top 3681 cobblestone_stairs facing south waterlogged true shape outer_right half top 3682 cobblestone_stairs facing south waterlogged false shape outer_right half top 3683 cobblestone_stairs facing south waterlogged true shape straight half bottom 3684 cobblestone_stairs facing south waterlogged false shape straight half bottom 3685 cobblestone_stairs facing south waterlogged true shape inner_left half bottom 3686 cobblestone_stairs facing south waterlogged false shape inner_left half bottom 3687 cobblestone_stairs facing south waterlogged true shape inner_right half bottom 3688 cobblestone_stairs facing south waterlogged false shape inner_right half bottom 3689 cobblestone_stairs facing south waterlogged true shape outer_left half bottom 3690 cobblestone_stairs facing south waterlogged false shape outer_left half bottom 3691 cobblestone_stairs facing south waterlogged true shape outer_right half bottom 3692 cobblestone_stairs facing south waterlogged false shape outer_right half bottom 3693 cobblestone_stairs facing west waterlogged true shape straight half top 3694 cobblestone_stairs facing west waterlogged false shape straight half top 3695 cobblestone_stairs facing west waterlogged true shape inner_left half top 3696 cobblestone_stairs facing west waterlogged false shape inner_left half top 3697 cobblestone_stairs facing west waterlogged true shape inner_right half top 3698 cobblestone_stairs facing west waterlogged false shape inner_right half top 3699 cobblestone_stairs facing west waterlogged true shape outer_left half top 3700 cobblestone_stairs facing west waterlogged false shape outer_left half top 3701 cobblestone_stairs facing west waterlogged true shape outer_right half top 3702 cobblestone_stairs facing west waterlogged false shape outer_right half top 3703 cobblestone_stairs facing west waterlogged true shape straight half bottom 3704 cobblestone_stairs facing west waterlogged false shape straight half bottom 3705 cobblestone_stairs facing west waterlogged true shape inner_left half bottom 3706 cobblestone_stairs facing west waterlogged false shape inner_left half bottom 3707 cobblestone_stairs facing west waterlogged true shape inner_right half bottom 3708 cobblestone_stairs facing west waterlogged false shape inner_right half bottom 3709 cobblestone_stairs facing west waterlogged true shape outer_left half bottom 3710 cobblestone_stairs facing west waterlogged false shape outer_left half bottom 3711 cobblestone_stairs facing west waterlogged true shape outer_right half bottom 3712 cobblestone_stairs facing west waterlogged false shape outer_right half bottom 3713 cobblestone_stairs facing east waterlogged true shape straight half top 3714 cobblestone_stairs facing east waterlogged false shape straight half top 3715 cobblestone_stairs facing east waterlogged true shape inner_left half top 3716 cobblestone_stairs facing east waterlogged false shape inner_left half top 3717 cobblestone_stairs facing east waterlogged true shape inner_right half top 3718 cobblestone_stairs facing east waterlogged false shape inner_right half top 3719 cobblestone_stairs facing east waterlogged true shape outer_left half top 3720 cobblestone_stairs facing east waterlogged false shape outer_left half top 3721 cobblestone_stairs facing east waterlogged true shape outer_right half top 3722 cobblestone_stairs facing east waterlogged false shape outer_right half top 3723 cobblestone_stairs facing east waterlogged true shape straight half bottom 3724 cobblestone_stairs facing east waterlogged false shape straight half bottom 3725 cobblestone_stairs facing east waterlogged true shape inner_left half bottom 3726 cobblestone_stairs facing east waterlogged false shape inner_left half bottom 3727 cobblestone_stairs facing east waterlogged true shape inner_right half bottom 3728 cobblestone_stairs facing east waterlogged false shape inner_right half bottom 3729 cobblestone_stairs facing east waterlogged true shape outer_left half bottom 3730 cobblestone_stairs facing east waterlogged false shape outer_left half bottom 3731 cobblestone_stairs facing east waterlogged true shape outer_right half bottom 3732 cobblestone_stairs facing east waterlogged false shape outer_right half bottom 3733 oak_wall_sign facing north waterlogged true 3734 oak_wall_sign facing north waterlogged false 3735 oak_wall_sign facing south waterlogged true 3736 oak_wall_sign facing south waterlogged false 3737 oak_wall_sign facing west waterlogged true 3738 oak_wall_sign facing west waterlogged false 3739 oak_wall_sign facing east waterlogged true 3740 oak_wall_sign facing east waterlogged false 3741 spruce_wall_sign facing north waterlogged true 3742 spruce_wall_sign facing north waterlogged false 3743 spruce_wall_sign facing south waterlogged true 3744 spruce_wall_sign facing south waterlogged false 3745 spruce_wall_sign facing west waterlogged true 3746 spruce_wall_sign facing west waterlogged false 3747 spruce_wall_sign facing east waterlogged true 3748 spruce_wall_sign facing east waterlogged false 3749 birch_wall_sign facing north waterlogged true 3750 birch_wall_sign facing north waterlogged false 3751 birch_wall_sign facing south waterlogged true 3752 birch_wall_sign facing south waterlogged false 3753 birch_wall_sign facing west waterlogged true 3754 birch_wall_sign facing west waterlogged false 3755 birch_wall_sign facing east waterlogged true 3756 birch_wall_sign facing east waterlogged false 3757 acacia_wall_sign facing north waterlogged true 3758 acacia_wall_sign facing north waterlogged false 3759 acacia_wall_sign facing south waterlogged true 3760 acacia_wall_sign facing south waterlogged false 3761 acacia_wall_sign facing west waterlogged true 3762 acacia_wall_sign facing west waterlogged false 3763 acacia_wall_sign facing east waterlogged true 3764 acacia_wall_sign facing east waterlogged false 3765 jungle_wall_sign facing north waterlogged true 3766 jungle_wall_sign facing north waterlogged false 3767 jungle_wall_sign facing south waterlogged true 3768 jungle_wall_sign facing south waterlogged false 3769 jungle_wall_sign facing west waterlogged true 3770 jungle_wall_sign facing west waterlogged false 3771 jungle_wall_sign facing east waterlogged true 3772 jungle_wall_sign facing east waterlogged false 3773 dark_oak_wall_sign facing north waterlogged true 3774 dark_oak_wall_sign facing north waterlogged false 3775 dark_oak_wall_sign facing south waterlogged true 3776 dark_oak_wall_sign facing south waterlogged false 3777 dark_oak_wall_sign facing west waterlogged true 3778 dark_oak_wall_sign facing west waterlogged false 3779 dark_oak_wall_sign facing east waterlogged true 3780 dark_oak_wall_sign facing east waterlogged false 3781 lever facing north face floor powered true 3782 lever facing north face floor powered false 3783 lever facing south face floor powered true 3784 lever facing south face floor powered false 3785 lever facing west face floor powered true 3786 lever facing west face floor powered false 3787 lever facing east face floor powered true 3788 lever facing east face floor powered false 3789 lever facing north face wall powered true 3790 lever facing north face wall powered false 3791 lever facing south face wall powered true 3792 lever facing south face wall powered false 3793 lever facing west face wall powered true 3794 lever facing west face wall powered false 3795 lever facing east face wall powered true 3796 lever facing east face wall powered false 3797 lever facing north face ceiling powered true 3798 lever facing north face ceiling powered false 3799 lever facing south face ceiling powered true 3800 lever facing south face ceiling powered false 3801 lever facing west face ceiling powered true 3802 lever facing west face ceiling powered false 3803 lever facing east face ceiling powered true 3804 lever facing east face ceiling powered false 3805 stone_pressure_plate powered true 3806 stone_pressure_plate powered false 3807 iron_door hinge left half upper facing north powered true open true 3808 iron_door hinge left half upper facing north powered false open true 3809 iron_door hinge left half upper facing north powered true open false 3810 iron_door hinge left half upper facing north powered false open false 3811 iron_door hinge right half upper facing north powered true open true 3812 iron_door hinge right half upper facing north powered false open true 3813 iron_door hinge right half upper facing north powered true open false 3814 iron_door hinge right half upper facing north powered false open false 3815 iron_door hinge left half lower facing north powered true open true 3816 iron_door hinge left half lower facing north powered false open true 3817 iron_door hinge left half lower facing north powered true open false 3818 iron_door hinge left half lower facing north powered false open false 3819 iron_door hinge right half lower facing north powered true open true 3820 iron_door hinge right half lower facing north powered false open true 3821 iron_door hinge right half lower facing north powered true open false 3822 iron_door hinge right half lower facing north powered false open false 3823 iron_door hinge left half upper facing south powered true open true 3824 iron_door hinge left half upper facing south powered false open true 3825 iron_door hinge left half upper facing south powered true open false 3826 iron_door hinge left half upper facing south powered false open false 3827 iron_door hinge right half upper facing south powered true open true 3828 iron_door hinge right half upper facing south powered false open true 3829 iron_door hinge right half upper facing south powered true open false 3830 iron_door hinge right half upper facing south powered false open false 3831 iron_door hinge left half lower facing south powered true open true 3832 iron_door hinge left half lower facing south powered false open true 3833 iron_door hinge left half lower facing south powered true open false 3834 iron_door hinge left half lower facing south powered false open false 3835 iron_door hinge right half lower facing south powered true open true 3836 iron_door hinge right half lower facing south powered false open true 3837 iron_door hinge right half lower facing south powered true open false 3838 iron_door hinge right half lower facing south powered false open false 3839 iron_door hinge left half upper facing west powered true open true 3840 iron_door hinge left half upper facing west powered false open true 3841 iron_door hinge left half upper facing west powered true open false 3842 iron_door hinge left half upper facing west powered false open false 3843 iron_door hinge right half upper facing west powered true open true 3844 iron_door hinge right half upper facing west powered false open true 3845 iron_door hinge right half upper facing west powered true open false 3846 iron_door hinge right half upper facing west powered false open false 3847 iron_door hinge left half lower facing west powered true open true 3848 iron_door hinge left half lower facing west powered false open true 3849 iron_door hinge left half lower facing west powered true open false 3850 iron_door hinge left half lower facing west powered false open false 3851 iron_door hinge right half lower facing west powered true open true 3852 iron_door hinge right half lower facing west powered false open true 3853 iron_door hinge right half lower facing west powered true open false 3854 iron_door hinge right half lower facing west powered false open false 3855 iron_door hinge left half upper facing east powered true open true 3856 iron_door hinge left half upper facing east powered false open true 3857 iron_door hinge left half upper facing east powered true open false 3858 iron_door hinge left half upper facing east powered false open false 3859 iron_door hinge right half upper facing east powered true open true 3860 iron_door hinge right half upper facing east powered false open true 3861 iron_door hinge right half upper facing east powered true open false 3862 iron_door hinge right half upper facing east powered false open false 3863 iron_door hinge left half lower facing east powered true open true 3864 iron_door hinge left half lower facing east powered false open true 3865 iron_door hinge left half lower facing east powered true open false 3866 iron_door hinge left half lower facing east powered false open false 3867 iron_door hinge right half lower facing east powered true open true 3868 iron_door hinge right half lower facing east powered false open true 3869 iron_door hinge right half lower facing east powered true open false 3870 iron_door hinge right half lower facing east powered false open false 3871 oak_pressure_plate powered true 3872 oak_pressure_plate powered false 3873 spruce_pressure_plate powered true 3874 spruce_pressure_plate powered false 3875 birch_pressure_plate powered true 3876 birch_pressure_plate powered false 3877 jungle_pressure_plate powered true 3878 jungle_pressure_plate powered false 3879 acacia_pressure_plate powered true 3880 acacia_pressure_plate powered false 3881 dark_oak_pressure_plate powered true 3882 dark_oak_pressure_plate powered false 3883 redstone_ore lit true 3884 redstone_ore lit false 3885 redstone_torch lit true 3886 redstone_torch lit false 3887 redstone_wall_torch facing north lit true 3888 redstone_wall_torch facing north lit false 3889 redstone_wall_torch facing south lit true 3890 redstone_wall_torch facing south lit false 3891 redstone_wall_torch facing west lit true 3892 redstone_wall_torch facing west lit false 3893 redstone_wall_torch facing east lit true 3894 redstone_wall_torch facing east lit false 3895 stone_button facing north face floor powered true 3896 stone_button facing north face floor powered false 3897 stone_button facing south face floor powered true 3898 stone_button facing south face floor powered false 3899 stone_button facing west face floor powered true 3900 stone_button facing west face floor powered false 3901 stone_button facing east face floor powered true 3902 stone_button facing east face floor powered false 3903 stone_button facing north face wall powered true 3904 stone_button facing north face wall powered false 3905 stone_button facing south face wall powered true 3906 stone_button facing south face wall powered false 3907 stone_button facing west face wall powered true 3908 stone_button facing west face wall powered false 3909 stone_button facing east face wall powered true 3910 stone_button facing east face wall powered false 3911 stone_button facing north face ceiling powered true 3912 stone_button facing north face ceiling powered false 3913 stone_button facing south face ceiling powered true 3914 stone_button facing south face ceiling powered false 3915 stone_button facing west face ceiling powered true 3916 stone_button facing west face ceiling powered false 3917 stone_button facing east face ceiling powered true 3918 stone_button facing east face ceiling powered false 3919 snow layers 1 3920 snow layers 2 3921 snow layers 3 3922 snow layers 4 3923 snow layers 5 3924 snow layers 6 3925 snow layers 7 3926 snow layers 8 3927 ice 3928 snow_block 3929 cactus age 0 3930 cactus age 1 3931 cactus age 2 3932 cactus age 3 3933 cactus age 4 3934 cactus age 5 3935 cactus age 6 3936 cactus age 7 3937 cactus age 8 3938 cactus age 9 3939 cactus age 10 3940 cactus age 11 3941 cactus age 12 3942 cactus age 13 3943 cactus age 14 3944 cactus age 15 3945 clay 3946 sugar_cane age 0 3947 sugar_cane age 1 3948 sugar_cane age 2 3949 sugar_cane age 3 3950 sugar_cane age 4 3951 sugar_cane age 5 3952 sugar_cane age 6 3953 sugar_cane age 7 3954 sugar_cane age 8 3955 sugar_cane age 9 3956 sugar_cane age 10 3957 sugar_cane age 11 3958 sugar_cane age 12 3959 sugar_cane age 13 3960 sugar_cane age 14 3961 sugar_cane age 15 3962 jukebox has_record true 3963 jukebox has_record false 3964 oak_fence waterlogged true south true east true north true west true 3965 oak_fence waterlogged true south true east true north true west false 3966 oak_fence waterlogged false south true east true north true west true 3967 oak_fence waterlogged false south true east true north true west false 3968 oak_fence waterlogged true south false east true north true west true 3969 oak_fence waterlogged true south false east true north true west false 3970 oak_fence waterlogged false south false east true north true west true 3971 oak_fence waterlogged false south false east true north true west false 3972 oak_fence waterlogged true south true east true north false west true 3973 oak_fence waterlogged true south true east true north false west false 3974 oak_fence waterlogged false south true east true north false west true 3975 oak_fence waterlogged false south true east true north false west false 3976 oak_fence waterlogged true south false east true north false west true 3977 oak_fence waterlogged true south false east true north false west false 3978 oak_fence waterlogged false south false east true north false west true 3979 oak_fence waterlogged false south false east true north false west false 3980 oak_fence waterlogged true south true east false north true west true 3981 oak_fence waterlogged true south true east false north true west false 3982 oak_fence waterlogged false south true east false north true west true 3983 oak_fence waterlogged false south true east false north true west false 3984 oak_fence waterlogged true south false east false north true west true 3985 oak_fence waterlogged true south false east false north true west false 3986 oak_fence waterlogged false south false east false north true west true 3987 oak_fence waterlogged false south false east false north true west false 3988 oak_fence waterlogged true south true east false north false west true 3989 oak_fence waterlogged true south true east false north false west false 3990 oak_fence waterlogged false south true east false north false west true 3991 oak_fence waterlogged false south true east false north false west false 3992 oak_fence waterlogged true south false east false north false west true 3993 oak_fence waterlogged true south false east false north false west false 3994 oak_fence waterlogged false south false east false north false west true 3995 oak_fence waterlogged false south false east false north false west false 3996 pumpkin 3997 netherrack 3998 soul_sand 3999 glowstone 4000 nether_portal axis x 4001 nether_portal axis z 4002 carved_pumpkin facing north 4003 carved_pumpkin facing south 4004 carved_pumpkin facing west 4005 carved_pumpkin facing east 4006 jack_o_lantern facing north 4007 jack_o_lantern facing south 4008 jack_o_lantern facing west 4009 jack_o_lantern facing east 4010 cake bites 0 4011 cake bites 1 4012 cake bites 2 4013 cake bites 3 4014 cake bites 4 4015 cake bites 5 4016 cake bites 6 4017 repeater facing north powered true locked true delay 1 4018 repeater facing north powered false locked true delay 1 4019 repeater facing north powered true locked false delay 1 4020 repeater facing north powered false locked false delay 1 4021 repeater facing south powered true locked true delay 1 4022 repeater facing south powered false locked true delay 1 4023 repeater facing south powered true locked false delay 1 4024 repeater facing south powered false locked false delay 1 4025 repeater facing west powered true locked true delay 1 4026 repeater facing west powered false locked true delay 1 4027 repeater facing west powered true locked false delay 1 4028 repeater facing west powered false locked false delay 1 4029 repeater facing east powered true locked true delay 1 4030 repeater facing east powered false locked true delay 1 4031 repeater facing east powered true locked false delay 1 4032 repeater facing east powered false locked false delay 1 4033 repeater facing north powered true locked true delay 2 4034 repeater facing north powered false locked true delay 2 4035 repeater facing north powered true locked false delay 2 4036 repeater facing north powered false locked false delay 2 4037 repeater facing south powered true locked true delay 2 4038 repeater facing south powered false locked true delay 2 4039 repeater facing south powered true locked false delay 2 4040 repeater facing south powered false locked false delay 2 4041 repeater facing west powered true locked true delay 2 4042 repeater facing west powered false locked true delay 2 4043 repeater facing west powered true locked false delay 2 4044 repeater facing west powered false locked false delay 2 4045 repeater facing east powered true locked true delay 2 4046 repeater facing east powered false locked true delay 2 4047 repeater facing east powered true locked false delay 2 4048 repeater facing east powered false locked false delay 2 4049 repeater facing north powered true locked true delay 3 4050 repeater facing north powered false locked true delay 3 4051 repeater facing north powered true locked false delay 3 4052 repeater facing north powered false locked false delay 3 4053 repeater facing south powered true locked true delay 3 4054 repeater facing south powered false locked true delay 3 4055 repeater facing south powered true locked false delay 3 4056 repeater facing south powered false locked false delay 3 4057 repeater facing west powered true locked true delay 3 4058 repeater facing west powered false locked true delay 3 4059 repeater facing west powered true locked false delay 3 4060 repeater facing west powered false locked false delay 3 4061 repeater facing east powered true locked true delay 3 4062 repeater facing east powered false locked true delay 3 4063 repeater facing east powered true locked false delay 3 4064 repeater facing east powered false locked false delay 3 4065 repeater facing north powered true locked true delay 4 4066 repeater facing north powered false locked true delay 4 4067 repeater facing north powered true locked false delay 4 4068 repeater facing north powered false locked false delay 4 4069 repeater facing south powered true locked true delay 4 4070 repeater facing south powered false locked true delay 4 4071 repeater facing south powered true locked false delay 4 4072 repeater facing south powered false locked false delay 4 4073 repeater facing west powered true locked true delay 4 4074 repeater facing west powered false locked true delay 4 4075 repeater facing west powered true locked false delay 4 4076 repeater facing west powered false locked false delay 4 4077 repeater facing east powered true locked true delay 4 4078 repeater facing east powered false locked true delay 4 4079 repeater facing east powered true locked false delay 4 4080 repeater facing east powered false locked false delay 4 4081 white_stained_glass 4082 orange_stained_glass 4083 magenta_stained_glass 4084 light_blue_stained_glass 4085 yellow_stained_glass 4086 lime_stained_glass 4087 pink_stained_glass 4088 gray_stained_glass 4089 light_gray_stained_glass 4090 cyan_stained_glass 4091 purple_stained_glass 4092 blue_stained_glass 4093 brown_stained_glass 4094 green_stained_glass 4095 red_stained_glass 4096 black_stained_glass 4097 oak_trapdoor waterlogged true powered true facing north half top open true 4098 oak_trapdoor waterlogged false powered true facing north half top open true 4099 oak_trapdoor waterlogged true powered false facing north half top open true 4100 oak_trapdoor waterlogged false powered false facing north half top open true 4101 oak_trapdoor waterlogged true powered true facing north half top open false 4102 oak_trapdoor waterlogged false powered true facing north half top open false 4103 oak_trapdoor waterlogged true powered false facing north half top open false 4104 oak_trapdoor waterlogged false powered false facing north half top open false 4105 oak_trapdoor waterlogged true powered true facing north half bottom open true 4106 oak_trapdoor waterlogged false powered true facing north half bottom open true 4107 oak_trapdoor waterlogged true powered false facing north half bottom open true 4108 oak_trapdoor waterlogged false powered false facing north half bottom open true 4109 oak_trapdoor waterlogged true powered true facing north half bottom open false 4110 oak_trapdoor waterlogged false powered true facing north half bottom open false 4111 oak_trapdoor waterlogged true powered false facing north half bottom open false 4112 oak_trapdoor waterlogged false powered false facing north half bottom open false 4113 oak_trapdoor waterlogged true powered true facing south half top open true 4114 oak_trapdoor waterlogged false powered true facing south half top open true 4115 oak_trapdoor waterlogged true powered false facing south half top open true 4116 oak_trapdoor waterlogged false powered false facing south half top open true 4117 oak_trapdoor waterlogged true powered true facing south half top open false 4118 oak_trapdoor waterlogged false powered true facing south half top open false 4119 oak_trapdoor waterlogged true powered false facing south half top open false 4120 oak_trapdoor waterlogged false powered false facing south half top open false 4121 oak_trapdoor waterlogged true powered true facing south half bottom open true 4122 oak_trapdoor waterlogged false powered true facing south half bottom open true 4123 oak_trapdoor waterlogged true powered false facing south half bottom open true 4124 oak_trapdoor waterlogged false powered false facing south half bottom open true 4125 oak_trapdoor waterlogged true powered true facing south half bottom open false 4126 oak_trapdoor waterlogged false powered true facing south half bottom open false 4127 oak_trapdoor waterlogged true powered false facing south half bottom open false 4128 oak_trapdoor waterlogged false powered false facing south half bottom open false 4129 oak_trapdoor waterlogged true powered true facing west half top open true 4130 oak_trapdoor waterlogged false powered true facing west half top open true 4131 oak_trapdoor waterlogged true powered false facing west half top open true 4132 oak_trapdoor waterlogged false powered false facing west half top open true 4133 oak_trapdoor waterlogged true powered true facing west half top open false 4134 oak_trapdoor waterlogged false powered true facing west half top open false 4135 oak_trapdoor waterlogged true powered false facing west half top open false 4136 oak_trapdoor waterlogged false powered false facing west half top open false 4137 oak_trapdoor waterlogged true powered true facing west half bottom open true 4138 oak_trapdoor waterlogged false powered true facing west half bottom open true 4139 oak_trapdoor waterlogged true powered false facing west half bottom open true 4140 oak_trapdoor waterlogged false powered false facing west half bottom open true 4141 oak_trapdoor waterlogged true powered true facing west half bottom open false 4142 oak_trapdoor waterlogged false powered true facing west half bottom open false 4143 oak_trapdoor waterlogged true powered false facing west half bottom open false 4144 oak_trapdoor waterlogged false powered false facing west half bottom open false 4145 oak_trapdoor waterlogged true powered true facing east half top open true 4146 oak_trapdoor waterlogged false powered true facing east half top open true 4147 oak_trapdoor waterlogged true powered false facing east half top open true 4148 oak_trapdoor waterlogged false powered false facing east half top open true 4149 oak_trapdoor waterlogged true powered true facing east half top open false 4150 oak_trapdoor waterlogged false powered true facing east half top open false 4151 oak_trapdoor waterlogged true powered false facing east half top open false 4152 oak_trapdoor waterlogged false powered false facing east half top open false 4153 oak_trapdoor waterlogged true powered true facing east half bottom open true 4154 oak_trapdoor waterlogged false powered true facing east half bottom open true 4155 oak_trapdoor waterlogged true powered false facing east half bottom open true 4156 oak_trapdoor waterlogged false powered false facing east half bottom open true 4157 oak_trapdoor waterlogged true powered true facing east half bottom open false 4158 oak_trapdoor waterlogged false powered true facing east half bottom open false 4159 oak_trapdoor waterlogged true powered false facing east half bottom open false 4160 oak_trapdoor waterlogged false powered false facing east half bottom open false 4161 spruce_trapdoor waterlogged true powered true facing north half top open true 4162 spruce_trapdoor waterlogged false powered true facing north half top open true 4163 spruce_trapdoor waterlogged true powered false facing north half top open true 4164 spruce_trapdoor waterlogged false powered false facing north half top open true 4165 spruce_trapdoor waterlogged true powered true facing north half top open false 4166 spruce_trapdoor waterlogged false powered true facing north half top open false 4167 spruce_trapdoor waterlogged true powered false facing north half top open false 4168 spruce_trapdoor waterlogged false powered false facing north half top open false 4169 spruce_trapdoor waterlogged true powered true facing north half bottom open true 4170 spruce_trapdoor waterlogged false powered true facing north half bottom open true 4171 spruce_trapdoor waterlogged true powered false facing north half bottom open true 4172 spruce_trapdoor waterlogged false powered false facing north half bottom open true 4173 spruce_trapdoor waterlogged true powered true facing north half bottom open false 4174 spruce_trapdoor waterlogged false powered true facing north half bottom open false 4175 spruce_trapdoor waterlogged true powered false facing north half bottom open false 4176 spruce_trapdoor waterlogged false powered false facing north half bottom open false 4177 spruce_trapdoor waterlogged true powered true facing south half top open true 4178 spruce_trapdoor waterlogged false powered true facing south half top open true 4179 spruce_trapdoor waterlogged true powered false facing south half top open true 4180 spruce_trapdoor waterlogged false powered false facing south half top open true 4181 spruce_trapdoor waterlogged true powered true facing south half top open false 4182 spruce_trapdoor waterlogged false powered true facing south half top open false 4183 spruce_trapdoor waterlogged true powered false facing south half top open false 4184 spruce_trapdoor waterlogged false powered false facing south half top open false 4185 spruce_trapdoor waterlogged true powered true facing south half bottom open true 4186 spruce_trapdoor waterlogged false powered true facing south half bottom open true 4187 spruce_trapdoor waterlogged true powered false facing south half bottom open true 4188 spruce_trapdoor waterlogged false powered false facing south half bottom open true 4189 spruce_trapdoor waterlogged true powered true facing south half bottom open false 4190 spruce_trapdoor waterlogged false powered true facing south half bottom open false 4191 spruce_trapdoor waterlogged true powered false facing south half bottom open false 4192 spruce_trapdoor waterlogged false powered false facing south half bottom open false 4193 spruce_trapdoor waterlogged true powered true facing west half top open true 4194 spruce_trapdoor waterlogged false powered true facing west half top open true 4195 spruce_trapdoor waterlogged true powered false facing west half top open true 4196 spruce_trapdoor waterlogged false powered false facing west half top open true 4197 spruce_trapdoor waterlogged true powered true facing west half top open false 4198 spruce_trapdoor waterlogged false powered true facing west half top open false 4199 spruce_trapdoor waterlogged true powered false facing west half top open false 4200 spruce_trapdoor waterlogged false powered false facing west half top open false 4201 spruce_trapdoor waterlogged true powered true facing west half bottom open true 4202 spruce_trapdoor waterlogged false powered true facing west half bottom open true 4203 spruce_trapdoor waterlogged true powered false facing west half bottom open true 4204 spruce_trapdoor waterlogged false powered false facing west half bottom open true 4205 spruce_trapdoor waterlogged true powered true facing west half bottom open false 4206 spruce_trapdoor waterlogged false powered true facing west half bottom open false 4207 spruce_trapdoor waterlogged true powered false facing west half bottom open false 4208 spruce_trapdoor waterlogged false powered false facing west half bottom open false 4209 spruce_trapdoor waterlogged true powered true facing east half top open true 4210 spruce_trapdoor waterlogged false powered true facing east half top open true 4211 spruce_trapdoor waterlogged true powered false facing east half top open true 4212 spruce_trapdoor waterlogged false powered false facing east half top open true 4213 spruce_trapdoor waterlogged true powered true facing east half top open false 4214 spruce_trapdoor waterlogged false powered true facing east half top open false 4215 spruce_trapdoor waterlogged true powered false facing east half top open false 4216 spruce_trapdoor waterlogged false powered false facing east half top open false 4217 spruce_trapdoor waterlogged true powered true facing east half bottom open true 4218 spruce_trapdoor waterlogged false powered true facing east half bottom open true 4219 spruce_trapdoor waterlogged true powered false facing east half bottom open true 4220 spruce_trapdoor waterlogged false powered false facing east half bottom open true 4221 spruce_trapdoor waterlogged true powered true facing east half bottom open false 4222 spruce_trapdoor waterlogged false powered true facing east half bottom open false 4223 spruce_trapdoor waterlogged true powered false facing east half bottom open false 4224 spruce_trapdoor waterlogged false powered false facing east half bottom open false 4225 birch_trapdoor waterlogged true powered true facing north half top open true 4226 birch_trapdoor waterlogged false powered true facing north half top open true 4227 birch_trapdoor waterlogged true powered false facing north half top open true 4228 birch_trapdoor waterlogged false powered false facing north half top open true 4229 birch_trapdoor waterlogged true powered true facing north half top open false 4230 birch_trapdoor waterlogged false powered true facing north half top open false 4231 birch_trapdoor waterlogged true powered false facing north half top open false 4232 birch_trapdoor waterlogged false powered false facing north half top open false 4233 birch_trapdoor waterlogged true powered true facing north half bottom open true 4234 birch_trapdoor waterlogged false powered true facing north half bottom open true 4235 birch_trapdoor waterlogged true powered false facing north half bottom open true 4236 birch_trapdoor waterlogged false powered false facing north half bottom open true 4237 birch_trapdoor waterlogged true powered true facing north half bottom open false 4238 birch_trapdoor waterlogged false powered true facing north half bottom open false 4239 birch_trapdoor waterlogged true powered false facing north half bottom open false 4240 birch_trapdoor waterlogged false powered false facing north half bottom open false 4241 birch_trapdoor waterlogged true powered true facing south half top open true 4242 birch_trapdoor waterlogged false powered true facing south half top open true 4243 birch_trapdoor waterlogged true powered false facing south half top open true 4244 birch_trapdoor waterlogged false powered false facing south half top open true 4245 birch_trapdoor waterlogged true powered true facing south half top open false 4246 birch_trapdoor waterlogged false powered true facing south half top open false 4247 birch_trapdoor waterlogged true powered false facing south half top open false 4248 birch_trapdoor waterlogged false powered false facing south half top open false 4249 birch_trapdoor waterlogged true powered true facing south half bottom open true 4250 birch_trapdoor waterlogged false powered true facing south half bottom open true 4251 birch_trapdoor waterlogged true powered false facing south half bottom open true 4252 birch_trapdoor waterlogged false powered false facing south half bottom open true 4253 birch_trapdoor waterlogged true powered true facing south half bottom open false 4254 birch_trapdoor waterlogged false powered true facing south half bottom open false 4255 birch_trapdoor waterlogged true powered false facing south half bottom open false 4256 birch_trapdoor waterlogged false powered false facing south half bottom open false 4257 birch_trapdoor waterlogged true powered true facing west half top open true 4258 birch_trapdoor waterlogged false powered true facing west half top open true 4259 birch_trapdoor waterlogged true powered false facing west half top open true 4260 birch_trapdoor waterlogged false powered false facing west half top open true 4261 birch_trapdoor waterlogged true powered true facing west half top open false 4262 birch_trapdoor waterlogged false powered true facing west half top open false 4263 birch_trapdoor waterlogged true powered false facing west half top open false 4264 birch_trapdoor waterlogged false powered false facing west half top open false 4265 birch_trapdoor waterlogged true powered true facing west half bottom open true 4266 birch_trapdoor waterlogged false powered true facing west half bottom open true 4267 birch_trapdoor waterlogged true powered false facing west half bottom open true 4268 birch_trapdoor waterlogged false powered false facing west half bottom open true 4269 birch_trapdoor waterlogged true powered true facing west half bottom open false 4270 birch_trapdoor waterlogged false powered true facing west half bottom open false 4271 birch_trapdoor waterlogged true powered false facing west half bottom open false 4272 birch_trapdoor waterlogged false powered false facing west half bottom open false 4273 birch_trapdoor waterlogged true powered true facing east half top open true 4274 birch_trapdoor waterlogged false powered true facing east half top open true 4275 birch_trapdoor waterlogged true powered false facing east half top open true 4276 birch_trapdoor waterlogged false powered false facing east half top open true 4277 birch_trapdoor waterlogged true powered true facing east half top open false 4278 birch_trapdoor waterlogged false powered true facing east half top open false 4279 birch_trapdoor waterlogged true powered false facing east half top open false 4280 birch_trapdoor waterlogged false powered false facing east half top open false 4281 birch_trapdoor waterlogged true powered true facing east half bottom open true 4282 birch_trapdoor waterlogged false powered true facing east half bottom open true 4283 birch_trapdoor waterlogged true powered false facing east half bottom open true 4284 birch_trapdoor waterlogged false powered false facing east half bottom open true 4285 birch_trapdoor waterlogged true powered true facing east half bottom open false 4286 birch_trapdoor waterlogged false powered true facing east half bottom open false 4287 birch_trapdoor waterlogged true powered false facing east half bottom open false 4288 birch_trapdoor waterlogged false powered false facing east half bottom open false 4289 jungle_trapdoor waterlogged true powered true facing north half top open true 4290 jungle_trapdoor waterlogged false powered true facing north half top open true 4291 jungle_trapdoor waterlogged true powered false facing north half top open true 4292 jungle_trapdoor waterlogged false powered false facing north half top open true 4293 jungle_trapdoor waterlogged true powered true facing north half top open false 4294 jungle_trapdoor waterlogged false powered true facing north half top open false 4295 jungle_trapdoor waterlogged true powered false facing north half top open false 4296 jungle_trapdoor waterlogged false powered false facing north half top open false 4297 jungle_trapdoor waterlogged true powered true facing north half bottom open true 4298 jungle_trapdoor waterlogged false powered true facing north half bottom open true 4299 jungle_trapdoor waterlogged true powered false facing north half bottom open true 4300 jungle_trapdoor waterlogged false powered false facing north half bottom open true 4301 jungle_trapdoor waterlogged true powered true facing north half bottom open false 4302 jungle_trapdoor waterlogged false powered true facing north half bottom open false 4303 jungle_trapdoor waterlogged true powered false facing north half bottom open false 4304 jungle_trapdoor waterlogged false powered false facing north half bottom open false 4305 jungle_trapdoor waterlogged true powered true facing south half top open true 4306 jungle_trapdoor waterlogged false powered true facing south half top open true 4307 jungle_trapdoor waterlogged true powered false facing south half top open true 4308 jungle_trapdoor waterlogged false powered false facing south half top open true 4309 jungle_trapdoor waterlogged true powered true facing south half top open false 4310 jungle_trapdoor waterlogged false powered true facing south half top open false 4311 jungle_trapdoor waterlogged true powered false facing south half top open false 4312 jungle_trapdoor waterlogged false powered false facing south half top open false 4313 jungle_trapdoor waterlogged true powered true facing south half bottom open true 4314 jungle_trapdoor waterlogged false powered true facing south half bottom open true 4315 jungle_trapdoor waterlogged true powered false facing south half bottom open true 4316 jungle_trapdoor waterlogged false powered false facing south half bottom open true 4317 jungle_trapdoor waterlogged true powered true facing south half bottom open false 4318 jungle_trapdoor waterlogged false powered true facing south half bottom open false 4319 jungle_trapdoor waterlogged true powered false facing south half bottom open false 4320 jungle_trapdoor waterlogged false powered false facing south half bottom open false 4321 jungle_trapdoor waterlogged true powered true facing west half top open true 4322 jungle_trapdoor waterlogged false powered true facing west half top open true 4323 jungle_trapdoor waterlogged true powered false facing west half top open true 4324 jungle_trapdoor waterlogged false powered false facing west half top open true 4325 jungle_trapdoor waterlogged true powered true facing west half top open false 4326 jungle_trapdoor waterlogged false powered true facing west half top open false 4327 jungle_trapdoor waterlogged true powered false facing west half top open false 4328 jungle_trapdoor waterlogged false powered false facing west half top open false 4329 jungle_trapdoor waterlogged true powered true facing west half bottom open true 4330 jungle_trapdoor waterlogged false powered true facing west half bottom open true 4331 jungle_trapdoor waterlogged true powered false facing west half bottom open true 4332 jungle_trapdoor waterlogged false powered false facing west half bottom open true 4333 jungle_trapdoor waterlogged true powered true facing west half bottom open false 4334 jungle_trapdoor waterlogged false powered true facing west half bottom open false 4335 jungle_trapdoor waterlogged true powered false facing west half bottom open false 4336 jungle_trapdoor waterlogged false powered false facing west half bottom open false 4337 jungle_trapdoor waterlogged true powered true facing east half top open true 4338 jungle_trapdoor waterlogged false powered true facing east half top open true 4339 jungle_trapdoor waterlogged true powered false facing east half top open true 4340 jungle_trapdoor waterlogged false powered false facing east half top open true 4341 jungle_trapdoor waterlogged true powered true facing east half top open false 4342 jungle_trapdoor waterlogged false powered true facing east half top open false 4343 jungle_trapdoor waterlogged true powered false facing east half top open false 4344 jungle_trapdoor waterlogged false powered false facing east half top open false 4345 jungle_trapdoor waterlogged true powered true facing east half bottom open true 4346 jungle_trapdoor waterlogged false powered true facing east half bottom open true 4347 jungle_trapdoor waterlogged true powered false facing east half bottom open true 4348 jungle_trapdoor waterlogged false powered false facing east half bottom open true 4349 jungle_trapdoor waterlogged true powered true facing east half bottom open false 4350 jungle_trapdoor waterlogged false powered true facing east half bottom open false 4351 jungle_trapdoor waterlogged true powered false facing east half bottom open false 4352 jungle_trapdoor waterlogged false powered false facing east half bottom open false 4353 acacia_trapdoor waterlogged true powered true facing north half top open true 4354 acacia_trapdoor waterlogged false powered true facing north half top open true 4355 acacia_trapdoor waterlogged true powered false facing north half top open true 4356 acacia_trapdoor waterlogged false powered false facing north half top open true 4357 acacia_trapdoor waterlogged true powered true facing north half top open false 4358 acacia_trapdoor waterlogged false powered true facing north half top open false 4359 acacia_trapdoor waterlogged true powered false facing north half top open false 4360 acacia_trapdoor waterlogged false powered false facing north half top open false 4361 acacia_trapdoor waterlogged true powered true facing north half bottom open true 4362 acacia_trapdoor waterlogged false powered true facing north half bottom open true 4363 acacia_trapdoor waterlogged true powered false facing north half bottom open true 4364 acacia_trapdoor waterlogged false powered false facing north half bottom open true 4365 acacia_trapdoor waterlogged true powered true facing north half bottom open false 4366 acacia_trapdoor waterlogged false powered true facing north half bottom open false 4367 acacia_trapdoor waterlogged true powered false facing north half bottom open false 4368 acacia_trapdoor waterlogged false powered false facing north half bottom open false 4369 acacia_trapdoor waterlogged true powered true facing south half top open true 4370 acacia_trapdoor waterlogged false powered true facing south half top open true 4371 acacia_trapdoor waterlogged true powered false facing south half top open true 4372 acacia_trapdoor waterlogged false powered false facing south half top open true 4373 acacia_trapdoor waterlogged true powered true facing south half top open false 4374 acacia_trapdoor waterlogged false powered true facing south half top open false 4375 acacia_trapdoor waterlogged true powered false facing south half top open false 4376 acacia_trapdoor waterlogged false powered false facing south half top open false 4377 acacia_trapdoor waterlogged true powered true facing south half bottom open true 4378 acacia_trapdoor waterlogged false powered true facing south half bottom open true 4379 acacia_trapdoor waterlogged true powered false facing south half bottom open true 4380 acacia_trapdoor waterlogged false powered false facing south half bottom open true 4381 acacia_trapdoor waterlogged true powered true facing south half bottom open false 4382 acacia_trapdoor waterlogged false powered true facing south half bottom open false 4383 acacia_trapdoor waterlogged true powered false facing south half bottom open false 4384 acacia_trapdoor waterlogged false powered false facing south half bottom open false 4385 acacia_trapdoor waterlogged true powered true facing west half top open true 4386 acacia_trapdoor waterlogged false powered true facing west half top open true 4387 acacia_trapdoor waterlogged true powered false facing west half top open true 4388 acacia_trapdoor waterlogged false powered false facing west half top open true 4389 acacia_trapdoor waterlogged true powered true facing west half top open false 4390 acacia_trapdoor waterlogged false powered true facing west half top open false 4391 acacia_trapdoor waterlogged true powered false facing west half top open false 4392 acacia_trapdoor waterlogged false powered false facing west half top open false 4393 acacia_trapdoor waterlogged true powered true facing west half bottom open true 4394 acacia_trapdoor waterlogged false powered true facing west half bottom open true 4395 acacia_trapdoor waterlogged true powered false facing west half bottom open true 4396 acacia_trapdoor waterlogged false powered false facing west half bottom open true 4397 acacia_trapdoor waterlogged true powered true facing west half bottom open false 4398 acacia_trapdoor waterlogged false powered true facing west half bottom open false 4399 acacia_trapdoor waterlogged true powered false facing west half bottom open false 4400 acacia_trapdoor waterlogged false powered false facing west half bottom open false 4401 acacia_trapdoor waterlogged true powered true facing east half top open true 4402 acacia_trapdoor waterlogged false powered true facing east half top open true 4403 acacia_trapdoor waterlogged true powered false facing east half top open true 4404 acacia_trapdoor waterlogged false powered false facing east half top open true 4405 acacia_trapdoor waterlogged true powered true facing east half top open false 4406 acacia_trapdoor waterlogged false powered true facing east half top open false 4407 acacia_trapdoor waterlogged true powered false facing east half top open false 4408 acacia_trapdoor waterlogged false powered false facing east half top open false 4409 acacia_trapdoor waterlogged true powered true facing east half bottom open true 4410 acacia_trapdoor waterlogged false powered true facing east half bottom open true 4411 acacia_trapdoor waterlogged true powered false facing east half bottom open true 4412 acacia_trapdoor waterlogged false powered false facing east half bottom open true 4413 acacia_trapdoor waterlogged true powered true facing east half bottom open false 4414 acacia_trapdoor waterlogged false powered true facing east half bottom open false 4415 acacia_trapdoor waterlogged true powered false facing east half bottom open false 4416 acacia_trapdoor waterlogged false powered false facing east half bottom open false 4417 dark_oak_trapdoor waterlogged true powered true facing north half top open true 4418 dark_oak_trapdoor waterlogged false powered true facing north half top open true 4419 dark_oak_trapdoor waterlogged true powered false facing north half top open true 4420 dark_oak_trapdoor waterlogged false powered false facing north half top open true 4421 dark_oak_trapdoor waterlogged true powered true facing north half top open false 4422 dark_oak_trapdoor waterlogged false powered true facing north half top open false 4423 dark_oak_trapdoor waterlogged true powered false facing north half top open false 4424 dark_oak_trapdoor waterlogged false powered false facing north half top open false 4425 dark_oak_trapdoor waterlogged true powered true facing north half bottom open true 4426 dark_oak_trapdoor waterlogged false powered true facing north half bottom open true 4427 dark_oak_trapdoor waterlogged true powered false facing north half bottom open true 4428 dark_oak_trapdoor waterlogged false powered false facing north half bottom open true 4429 dark_oak_trapdoor waterlogged true powered true facing north half bottom open false 4430 dark_oak_trapdoor waterlogged false powered true facing north half bottom open false 4431 dark_oak_trapdoor waterlogged true powered false facing north half bottom open false 4432 dark_oak_trapdoor waterlogged false powered false facing north half bottom open false 4433 dark_oak_trapdoor waterlogged true powered true facing south half top open true 4434 dark_oak_trapdoor waterlogged false powered true facing south half top open true 4435 dark_oak_trapdoor waterlogged true powered false facing south half top open true 4436 dark_oak_trapdoor waterlogged false powered false facing south half top open true 4437 dark_oak_trapdoor waterlogged true powered true facing south half top open false 4438 dark_oak_trapdoor waterlogged false powered true facing south half top open false 4439 dark_oak_trapdoor waterlogged true powered false facing south half top open false 4440 dark_oak_trapdoor waterlogged false powered false facing south half top open false 4441 dark_oak_trapdoor waterlogged true powered true facing south half bottom open true 4442 dark_oak_trapdoor waterlogged false powered true facing south half bottom open true 4443 dark_oak_trapdoor waterlogged true powered false facing south half bottom open true 4444 dark_oak_trapdoor waterlogged false powered false facing south half bottom open true 4445 dark_oak_trapdoor waterlogged true powered true facing south half bottom open false 4446 dark_oak_trapdoor waterlogged false powered true facing south half bottom open false 4447 dark_oak_trapdoor waterlogged true powered false facing south half bottom open false 4448 dark_oak_trapdoor waterlogged false powered false facing south half bottom open false 4449 dark_oak_trapdoor waterlogged true powered true facing west half top open true 4450 dark_oak_trapdoor waterlogged false powered true facing west half top open true 4451 dark_oak_trapdoor waterlogged true powered false facing west half top open true 4452 dark_oak_trapdoor waterlogged false powered false facing west half top open true 4453 dark_oak_trapdoor waterlogged true powered true facing west half top open false 4454 dark_oak_trapdoor waterlogged false powered true facing west half top open false 4455 dark_oak_trapdoor waterlogged true powered false facing west half top open false 4456 dark_oak_trapdoor waterlogged false powered false facing west half top open false 4457 dark_oak_trapdoor waterlogged true powered true facing west half bottom open true 4458 dark_oak_trapdoor waterlogged false powered true facing west half bottom open true 4459 dark_oak_trapdoor waterlogged true powered false facing west half bottom open true 4460 dark_oak_trapdoor waterlogged false powered false facing west half bottom open true 4461 dark_oak_trapdoor waterlogged true powered true facing west half bottom open false 4462 dark_oak_trapdoor waterlogged false powered true facing west half bottom open false 4463 dark_oak_trapdoor waterlogged true powered false facing west half bottom open false 4464 dark_oak_trapdoor waterlogged false powered false facing west half bottom open false 4465 dark_oak_trapdoor waterlogged true powered true facing east half top open true 4466 dark_oak_trapdoor waterlogged false powered true facing east half top open true 4467 dark_oak_trapdoor waterlogged true powered false facing east half top open true 4468 dark_oak_trapdoor waterlogged false powered false facing east half top open true 4469 dark_oak_trapdoor waterlogged true powered true facing east half top open false 4470 dark_oak_trapdoor waterlogged false powered true facing east half top open false 4471 dark_oak_trapdoor waterlogged true powered false facing east half top open false 4472 dark_oak_trapdoor waterlogged false powered false facing east half top open false 4473 dark_oak_trapdoor waterlogged true powered true facing east half bottom open true 4474 dark_oak_trapdoor waterlogged false powered true facing east half bottom open true 4475 dark_oak_trapdoor waterlogged true powered false facing east half bottom open true 4476 dark_oak_trapdoor waterlogged false powered false facing east half bottom open true 4477 dark_oak_trapdoor waterlogged true powered true facing east half bottom open false 4478 dark_oak_trapdoor waterlogged false powered true facing east half bottom open false 4479 dark_oak_trapdoor waterlogged true powered false facing east half bottom open false 4480 dark_oak_trapdoor waterlogged false powered false facing east half bottom open false 4481 stone_bricks 4482 mossy_stone_bricks 4483 cracked_stone_bricks 4484 chiseled_stone_bricks 4485 infested_stone 4486 infested_cobblestone 4487 infested_stone_bricks 4488 infested_mossy_stone_bricks 4489 infested_cracked_stone_bricks 4490 infested_chiseled_stone_bricks 4491 brown_mushroom_block up true south true east true north true down true west true 4492 brown_mushroom_block up true south true east true north true down true west false 4493 brown_mushroom_block up false south true east true north true down true west true 4494 brown_mushroom_block up false south true east true north true down true west false 4495 brown_mushroom_block up true south false east true north true down true west true 4496 brown_mushroom_block up true south false east true north true down true west false 4497 brown_mushroom_block up false south false east true north true down true west true 4498 brown_mushroom_block up false south false east true north true down true west false 4499 brown_mushroom_block up true south true east true north false down true west true 4500 brown_mushroom_block up true south true east true north false down true west false 4501 brown_mushroom_block up false south true east true north false down true west true 4502 brown_mushroom_block up false south true east true north false down true west false 4503 brown_mushroom_block up true south false east true north false down true west true 4504 brown_mushroom_block up true south false east true north false down true west false 4505 brown_mushroom_block up false south false east true north false down true west true 4506 brown_mushroom_block up false south false east true north false down true west false 4507 brown_mushroom_block up true south true east false north true down true west true 4508 brown_mushroom_block up true south true east false north true down true west false 4509 brown_mushroom_block up false south true east false north true down true west true 4510 brown_mushroom_block up false south true east false north true down true west false 4511 brown_mushroom_block up true south false east false north true down true west true 4512 brown_mushroom_block up true south false east false north true down true west false 4513 brown_mushroom_block up false south false east false north true down true west true 4514 brown_mushroom_block up false south false east false north true down true west false 4515 brown_mushroom_block up true south true east false north false down true west true 4516 brown_mushroom_block up true south true east false north false down true west false 4517 brown_mushroom_block up false south true east false north false down true west true 4518 brown_mushroom_block up false south true east false north false down true west false 4519 brown_mushroom_block up true south false east false north false down true west true 4520 brown_mushroom_block up true south false east false north false down true west false 4521 brown_mushroom_block up false south false east false north false down true west true 4522 brown_mushroom_block up false south false east false north false down true west false 4523 brown_mushroom_block up true south true east true north true down false west true 4524 brown_mushroom_block up true south true east true north true down false west false 4525 brown_mushroom_block up false south true east true north true down false west true 4526 brown_mushroom_block up false south true east true north true down false west false 4527 brown_mushroom_block up true south false east true north true down false west true 4528 brown_mushroom_block up true south false east true north true down false west false 4529 brown_mushroom_block up false south false east true north true down false west true 4530 brown_mushroom_block up false south false east true north true down false west false 4531 brown_mushroom_block up true south true east true north false down false west true 4532 brown_mushroom_block up true south true east true north false down false west false 4533 brown_mushroom_block up false south true east true north false down false west true 4534 brown_mushroom_block up false south true east true north false down false west false 4535 brown_mushroom_block up true south false east true north false down false west true 4536 brown_mushroom_block up true south false east true north false down false west false 4537 brown_mushroom_block up false south false east true north false down false west true 4538 brown_mushroom_block up false south false east true north false down false west false 4539 brown_mushroom_block up true south true east false north true down false west true 4540 brown_mushroom_block up true south true east false north true down false west false 4541 brown_mushroom_block up false south true east false north true down false west true 4542 brown_mushroom_block up false south true east false north true down false west false 4543 brown_mushroom_block up true south false east false north true down false west true 4544 brown_mushroom_block up true south false east false north true down false west false 4545 brown_mushroom_block up false south false east false north true down false west true 4546 brown_mushroom_block up false south false east false north true down false west false 4547 brown_mushroom_block up true south true east false north false down false west true 4548 brown_mushroom_block up true south true east false north false down false west false 4549 brown_mushroom_block up false south true east false north false down false west true 4550 brown_mushroom_block up false south true east false north false down false west false 4551 brown_mushroom_block up true south false east false north false down false west true 4552 brown_mushroom_block up true south false east false north false down false west false 4553 brown_mushroom_block up false south false east false north false down false west true 4554 brown_mushroom_block up false south false east false north false down false west false 4555 red_mushroom_block up true south true east true north true down true west true 4556 red_mushroom_block up true south true east true north true down true west false 4557 red_mushroom_block up false south true east true north true down true west true 4558 red_mushroom_block up false south true east true north true down true west false 4559 red_mushroom_block up true south false east true north true down true west true 4560 red_mushroom_block up true south false east true north true down true west false 4561 red_mushroom_block up false south false east true north true down true west true 4562 red_mushroom_block up false south false east true north true down true west false 4563 red_mushroom_block up true south true east true north false down true west true 4564 red_mushroom_block up true south true east true north false down true west false 4565 red_mushroom_block up false south true east true north false down true west true 4566 red_mushroom_block up false south true east true north false down true west false 4567 red_mushroom_block up true south false east true north false down true west true 4568 red_mushroom_block up true south false east true north false down true west false 4569 red_mushroom_block up false south false east true north false down true west true 4570 red_mushroom_block up false south false east true north false down true west false 4571 red_mushroom_block up true south true east false north true down true west true 4572 red_mushroom_block up true south true east false north true down true west false 4573 red_mushroom_block up false south true east false north true down true west true 4574 red_mushroom_block up false south true east false north true down true west false 4575 red_mushroom_block up true south false east false north true down true west true 4576 red_mushroom_block up true south false east false north true down true west false 4577 red_mushroom_block up false south false east false north true down true west true 4578 red_mushroom_block up false south false east false north true down true west false 4579 red_mushroom_block up true south true east false north false down true west true 4580 red_mushroom_block up true south true east false north false down true west false 4581 red_mushroom_block up false south true east false north false down true west true 4582 red_mushroom_block up false south true east false north false down true west false 4583 red_mushroom_block up true south false east false north false down true west true 4584 red_mushroom_block up true south false east false north false down true west false 4585 red_mushroom_block up false south false east false north false down true west true 4586 red_mushroom_block up false south false east false north false down true west false 4587 red_mushroom_block up true south true east true north true down false west true 4588 red_mushroom_block up true south true east true north true down false west false 4589 red_mushroom_block up false south true east true north true down false west true 4590 red_mushroom_block up false south true east true north true down false west false 4591 red_mushroom_block up true south false east true north true down false west true 4592 red_mushroom_block up true south false east true north true down false west false 4593 red_mushroom_block up false south false east true north true down false west true 4594 red_mushroom_block up false south false east true north true down false west false 4595 red_mushroom_block up true south true east true north false down false west true 4596 red_mushroom_block up true south true east true north false down false west false 4597 red_mushroom_block up false south true east true north false down false west true 4598 red_mushroom_block up false south true east true north false down false west false 4599 red_mushroom_block up true south false east true north false down false west true 4600 red_mushroom_block up true south false east true north false down false west false 4601 red_mushroom_block up false south false east true north false down false west true 4602 red_mushroom_block up false south false east true north false down false west false 4603 red_mushroom_block up true south true east false north true down false west true 4604 red_mushroom_block up true south true east false north true down false west false 4605 red_mushroom_block up false south true east false north true down false west true 4606 red_mushroom_block up false south true east false north true down false west false 4607 red_mushroom_block up true south false east false north true down false west true 4608 red_mushroom_block up true south false east false north true down false west false 4609 red_mushroom_block up false south false east false north true down false west true 4610 red_mushroom_block up false south false east false north true down false west false 4611 red_mushroom_block up true south true east false north false down false west true 4612 red_mushroom_block up true south true east false north false down false west false 4613 red_mushroom_block up false south true east false north false down false west true 4614 red_mushroom_block up false south true east false north false down false west false 4615 red_mushroom_block up true south false east false north false down false west true 4616 red_mushroom_block up true south false east false north false down false west false 4617 red_mushroom_block up false south false east false north false down false west true 4618 red_mushroom_block up false south false east false north false down false west false 4619 mushroom_stem up true south true east true north true down true west true 4620 mushroom_stem up true south true east true north true down true west false 4621 mushroom_stem up false south true east true north true down true west true 4622 mushroom_stem up false south true east true north true down true west false 4623 mushroom_stem up true south false east true north true down true west true 4624 mushroom_stem up true south false east true north true down true west false 4625 mushroom_stem up false south false east true north true down true west true 4626 mushroom_stem up false south false east true north true down true west false 4627 mushroom_stem up true south true east true north false down true west true 4628 mushroom_stem up true south true east true north false down true west false 4629 mushroom_stem up false south true east true north false down true west true 4630 mushroom_stem up false south true east true north false down true west false 4631 mushroom_stem up true south false east true north false down true west true 4632 mushroom_stem up true south false east true north false down true west false 4633 mushroom_stem up false south false east true north false down true west true 4634 mushroom_stem up false south false east true north false down true west false 4635 mushroom_stem up true south true east false north true down true west true 4636 mushroom_stem up true south true east false north true down true west false 4637 mushroom_stem up false south true east false north true down true west true 4638 mushroom_stem up false south true east false north true down true west false 4639 mushroom_stem up true south false east false north true down true west true 4640 mushroom_stem up true south false east false north true down true west false 4641 mushroom_stem up false south false east false north true down true west true 4642 mushroom_stem up false south false east false north true down true west false 4643 mushroom_stem up true south true east false north false down true west true 4644 mushroom_stem up true south true east false north false down true west false 4645 mushroom_stem up false south true east false north false down true west true 4646 mushroom_stem up false south true east false north false down true west false 4647 mushroom_stem up true south false east false north false down true west true 4648 mushroom_stem up true south false east false north false down true west false 4649 mushroom_stem up false south false east false north false down true west true 4650 mushroom_stem up false south false east false north false down true west false 4651 mushroom_stem up true south true east true north true down false west true 4652 mushroom_stem up true south true east true north true down false west false 4653 mushroom_stem up false south true east true north true down false west true 4654 mushroom_stem up false south true east true north true down false west false 4655 mushroom_stem up true south false east true north true down false west true 4656 mushroom_stem up true south false east true north true down false west false 4657 mushroom_stem up false south false east true north true down false west true 4658 mushroom_stem up false south false east true north true down false west false 4659 mushroom_stem up true south true east true north false down false west true 4660 mushroom_stem up true south true east true north false down false west false 4661 mushroom_stem up false south true east true north false down false west true 4662 mushroom_stem up false south true east true north false down false west false 4663 mushroom_stem up true south false east true north false down false west true 4664 mushroom_stem up true south false east true north false down false west false 4665 mushroom_stem up false south false east true north false down false west true 4666 mushroom_stem up false south false east true north false down false west false 4667 mushroom_stem up true south true east false north true down false west true 4668 mushroom_stem up true south true east false north true down false west false 4669 mushroom_stem up false south true east false north true down false west true 4670 mushroom_stem up false south true east false north true down false west false 4671 mushroom_stem up true south false east false north true down false west true 4672 mushroom_stem up true south false east false north true down false west false 4673 mushroom_stem up false south false east false north true down false west true 4674 mushroom_stem up false south false east false north true down false west false 4675 mushroom_stem up true south true east false north false down false west true 4676 mushroom_stem up true south true east false north false down false west false 4677 mushroom_stem up false south true east false north false down false west true 4678 mushroom_stem up false south true east false north false down false west false 4679 mushroom_stem up true south false east false north false down false west true 4680 mushroom_stem up true south false east false north false down false west false 4681 mushroom_stem up false south false east false north false down false west true 4682 mushroom_stem up false south false east false north false down false west false 4683 iron_bars waterlogged true south true east true north true west true 4684 iron_bars waterlogged true south true east true north true west false 4685 iron_bars waterlogged false south true east true north true west true 4686 iron_bars waterlogged false south true east true north true west false 4687 iron_bars waterlogged true south false east true north true west true 4688 iron_bars waterlogged true south false east true north true west false 4689 iron_bars waterlogged false south false east true north true west true 4690 iron_bars waterlogged false south false east true north true west false 4691 iron_bars waterlogged true south true east true north false west true 4692 iron_bars waterlogged true south true east true north false west false 4693 iron_bars waterlogged false south true east true north false west true 4694 iron_bars waterlogged false south true east true north false west false 4695 iron_bars waterlogged true south false east true north false west true 4696 iron_bars waterlogged true south false east true north false west false 4697 iron_bars waterlogged false south false east true north false west true 4698 iron_bars waterlogged false south false east true north false west false 4699 iron_bars waterlogged true south true east false north true west true 4700 iron_bars waterlogged true south true east false north true west false 4701 iron_bars waterlogged false south true east false north true west true 4702 iron_bars waterlogged false south true east false north true west false 4703 iron_bars waterlogged true south false east false north true west true 4704 iron_bars waterlogged true south false east false north true west false 4705 iron_bars waterlogged false south false east false north true west true 4706 iron_bars waterlogged false south false east false north true west false 4707 iron_bars waterlogged true south true east false north false west true 4708 iron_bars waterlogged true south true east false north false west false 4709 iron_bars waterlogged false south true east false north false west true 4710 iron_bars waterlogged false south true east false north false west false 4711 iron_bars waterlogged true south false east false north false west true 4712 iron_bars waterlogged true south false east false north false west false 4713 iron_bars waterlogged false south false east false north false west true 4714 iron_bars waterlogged false south false east false north false west false 4715 glass_pane waterlogged true south true east true north true west true 4716 glass_pane waterlogged true south true east true north true west false 4717 glass_pane waterlogged false south true east true north true west true 4718 glass_pane waterlogged false south true east true north true west false 4719 glass_pane waterlogged true south false east true north true west true 4720 glass_pane waterlogged true south false east true north true west false 4721 glass_pane waterlogged false south false east true north true west true 4722 glass_pane waterlogged false south false east true north true west false 4723 glass_pane waterlogged true south true east true north false west true 4724 glass_pane waterlogged true south true east true north false west false 4725 glass_pane waterlogged false south true east true north false west true 4726 glass_pane waterlogged false south true east true north false west false 4727 glass_pane waterlogged true south false east true north false west true 4728 glass_pane waterlogged true south false east true north false west false 4729 glass_pane waterlogged false south false east true north false west true 4730 glass_pane waterlogged false south false east true north false west false 4731 glass_pane waterlogged true south true east false north true west true 4732 glass_pane waterlogged true south true east false north true west false 4733 glass_pane waterlogged false south true east false north true west true 4734 glass_pane waterlogged false south true east false north true west false 4735 glass_pane waterlogged true south false east false north true west true 4736 glass_pane waterlogged true south false east false north true west false 4737 glass_pane waterlogged false south false east false north true west true 4738 glass_pane waterlogged false south false east false north true west false 4739 glass_pane waterlogged true south true east false north false west true 4740 glass_pane waterlogged true south true east false north false west false 4741 glass_pane waterlogged false south true east false north false west true 4742 glass_pane waterlogged false south true east false north false west false 4743 glass_pane waterlogged true south false east false north false west true 4744 glass_pane waterlogged true south false east false north false west false 4745 glass_pane waterlogged false south false east false north false west true 4746 glass_pane waterlogged false south false east false north false west false 4747 melon 4748 attached_pumpkin_stem facing north 4749 attached_pumpkin_stem facing south 4750 attached_pumpkin_stem facing west 4751 attached_pumpkin_stem facing east 4752 attached_melon_stem facing north 4753 attached_melon_stem facing south 4754 attached_melon_stem facing west 4755 attached_melon_stem facing east 4756 pumpkin_stem age 0 4757 pumpkin_stem age 1 4758 pumpkin_stem age 2 4759 pumpkin_stem age 3 4760 pumpkin_stem age 4 4761 pumpkin_stem age 5 4762 pumpkin_stem age 6 4763 pumpkin_stem age 7 4764 melon_stem age 0 4765 melon_stem age 1 4766 melon_stem age 2 4767 melon_stem age 3 4768 melon_stem age 4 4769 melon_stem age 5 4770 melon_stem age 6 4771 melon_stem age 7 4772 vine south true east true north true up true west true 4773 vine south true east true north true up true west false 4774 vine south true east true north true up false west true 4775 vine south true east true north true up false west false 4776 vine south false east true north true up true west true 4777 vine south false east true north true up true west false 4778 vine south false east true north true up false west true 4779 vine south false east true north true up false west false 4780 vine south true east true north false up true west true 4781 vine south true east true north false up true west false 4782 vine south true east true north false up false west true 4783 vine south true east true north false up false west false 4784 vine south false east true north false up true west true 4785 vine south false east true north false up true west false 4786 vine south false east true north false up false west true 4787 vine south false east true north false up false west false 4788 vine south true east false north true up true west true 4789 vine south true east false north true up true west false 4790 vine south true east false north true up false west true 4791 vine south true east false north true up false west false 4792 vine south false east false north true up true west true 4793 vine south false east false north true up true west false 4794 vine south false east false north true up false west true 4795 vine south false east false north true up false west false 4796 vine south true east false north false up true west true 4797 vine south true east false north false up true west false 4798 vine south true east false north false up false west true 4799 vine south true east false north false up false west false 4800 vine south false east false north false up true west true 4801 vine south false east false north false up true west false 4802 vine south false east false north false up false west true 4803 vine south false east false north false up false west false 4804 oak_fence_gate facing north powered true open true in_wall true 4805 oak_fence_gate facing north powered false open true in_wall true 4806 oak_fence_gate facing north powered true open false in_wall true 4807 oak_fence_gate facing north powered false open false in_wall true 4808 oak_fence_gate facing north powered true open true in_wall false 4809 oak_fence_gate facing north powered false open true in_wall false 4810 oak_fence_gate facing north powered true open false in_wall false 4811 oak_fence_gate facing north powered false open false in_wall false 4812 oak_fence_gate facing south powered true open true in_wall true 4813 oak_fence_gate facing south powered false open true in_wall true 4814 oak_fence_gate facing south powered true open false in_wall true 4815 oak_fence_gate facing south powered false open false in_wall true 4816 oak_fence_gate facing south powered true open true in_wall false 4817 oak_fence_gate facing south powered false open true in_wall false 4818 oak_fence_gate facing south powered true open false in_wall false 4819 oak_fence_gate facing south powered false open false in_wall false 4820 oak_fence_gate facing west powered true open true in_wall true 4821 oak_fence_gate facing west powered false open true in_wall true 4822 oak_fence_gate facing west powered true open false in_wall true 4823 oak_fence_gate facing west powered false open false in_wall true 4824 oak_fence_gate facing west powered true open true in_wall false 4825 oak_fence_gate facing west powered false open true in_wall false 4826 oak_fence_gate facing west powered true open false in_wall false 4827 oak_fence_gate facing west powered false open false in_wall false 4828 oak_fence_gate facing east powered true open true in_wall true 4829 oak_fence_gate facing east powered false open true in_wall true 4830 oak_fence_gate facing east powered true open false in_wall true 4831 oak_fence_gate facing east powered false open false in_wall true 4832 oak_fence_gate facing east powered true open true in_wall false 4833 oak_fence_gate facing east powered false open true in_wall false 4834 oak_fence_gate facing east powered true open false in_wall false 4835 oak_fence_gate facing east powered false open false in_wall false 4836 brick_stairs facing north waterlogged true shape straight half top 4837 brick_stairs facing north waterlogged false shape straight half top 4838 brick_stairs facing north waterlogged true shape inner_left half top 4839 brick_stairs facing north waterlogged false shape inner_left half top 4840 brick_stairs facing north waterlogged true shape inner_right half top 4841 brick_stairs facing north waterlogged false shape inner_right half top 4842 brick_stairs facing north waterlogged true shape outer_left half top 4843 brick_stairs facing north waterlogged false shape outer_left half top 4844 brick_stairs facing north waterlogged true shape outer_right half top 4845 brick_stairs facing north waterlogged false shape outer_right half top 4846 brick_stairs facing north waterlogged true shape straight half bottom 4847 brick_stairs facing north waterlogged false shape straight half bottom 4848 brick_stairs facing north waterlogged true shape inner_left half bottom 4849 brick_stairs facing north waterlogged false shape inner_left half bottom 4850 brick_stairs facing north waterlogged true shape inner_right half bottom 4851 brick_stairs facing north waterlogged false shape inner_right half bottom 4852 brick_stairs facing north waterlogged true shape outer_left half bottom 4853 brick_stairs facing north waterlogged false shape outer_left half bottom 4854 brick_stairs facing north waterlogged true shape outer_right half bottom 4855 brick_stairs facing north waterlogged false shape outer_right half bottom 4856 brick_stairs facing south waterlogged true shape straight half top 4857 brick_stairs facing south waterlogged false shape straight half top 4858 brick_stairs facing south waterlogged true shape inner_left half top 4859 brick_stairs facing south waterlogged false shape inner_left half top 4860 brick_stairs facing south waterlogged true shape inner_right half top 4861 brick_stairs facing south waterlogged false shape inner_right half top 4862 brick_stairs facing south waterlogged true shape outer_left half top 4863 brick_stairs facing south waterlogged false shape outer_left half top 4864 brick_stairs facing south waterlogged true shape outer_right half top 4865 brick_stairs facing south waterlogged false shape outer_right half top 4866 brick_stairs facing south waterlogged true shape straight half bottom 4867 brick_stairs facing south waterlogged false shape straight half bottom 4868 brick_stairs facing south waterlogged true shape inner_left half bottom 4869 brick_stairs facing south waterlogged false shape inner_left half bottom 4870 brick_stairs facing south waterlogged true shape inner_right half bottom 4871 brick_stairs facing south waterlogged false shape inner_right half bottom 4872 brick_stairs facing south waterlogged true shape outer_left half bottom 4873 brick_stairs facing south waterlogged false shape outer_left half bottom 4874 brick_stairs facing south waterlogged true shape outer_right half bottom 4875 brick_stairs facing south waterlogged false shape outer_right half bottom 4876 brick_stairs facing west waterlogged true shape straight half top 4877 brick_stairs facing west waterlogged false shape straight half top 4878 brick_stairs facing west waterlogged true shape inner_left half top 4879 brick_stairs facing west waterlogged false shape inner_left half top 4880 brick_stairs facing west waterlogged true shape inner_right half top 4881 brick_stairs facing west waterlogged false shape inner_right half top 4882 brick_stairs facing west waterlogged true shape outer_left half top 4883 brick_stairs facing west waterlogged false shape outer_left half top 4884 brick_stairs facing west waterlogged true shape outer_right half top 4885 brick_stairs facing west waterlogged false shape outer_right half top 4886 brick_stairs facing west waterlogged true shape straight half bottom 4887 brick_stairs facing west waterlogged false shape straight half bottom 4888 brick_stairs facing west waterlogged true shape inner_left half bottom 4889 brick_stairs facing west waterlogged false shape inner_left half bottom 4890 brick_stairs facing west waterlogged true shape inner_right half bottom 4891 brick_stairs facing west waterlogged false shape inner_right half bottom 4892 brick_stairs facing west waterlogged true shape outer_left half bottom 4893 brick_stairs facing west waterlogged false shape outer_left half bottom 4894 brick_stairs facing west waterlogged true shape outer_right half bottom 4895 brick_stairs facing west waterlogged false shape outer_right half bottom 4896 brick_stairs facing east waterlogged true shape straight half top 4897 brick_stairs facing east waterlogged false shape straight half top 4898 brick_stairs facing east waterlogged true shape inner_left half top 4899 brick_stairs facing east waterlogged false shape inner_left half top 4900 brick_stairs facing east waterlogged true shape inner_right half top 4901 brick_stairs facing east waterlogged false shape inner_right half top 4902 brick_stairs facing east waterlogged true shape outer_left half top 4903 brick_stairs facing east waterlogged false shape outer_left half top 4904 brick_stairs facing east waterlogged true shape outer_right half top 4905 brick_stairs facing east waterlogged false shape outer_right half top 4906 brick_stairs facing east waterlogged true shape straight half bottom 4907 brick_stairs facing east waterlogged false shape straight half bottom 4908 brick_stairs facing east waterlogged true shape inner_left half bottom 4909 brick_stairs facing east waterlogged false shape inner_left half bottom 4910 brick_stairs facing east waterlogged true shape inner_right half bottom 4911 brick_stairs facing east waterlogged false shape inner_right half bottom 4912 brick_stairs facing east waterlogged true shape outer_left half bottom 4913 brick_stairs facing east waterlogged false shape outer_left half bottom 4914 brick_stairs facing east waterlogged true shape outer_right half bottom 4915 brick_stairs facing east waterlogged false shape outer_right half bottom 4916 stone_brick_stairs facing north waterlogged true shape straight half top 4917 stone_brick_stairs facing north waterlogged false shape straight half top 4918 stone_brick_stairs facing north waterlogged true shape inner_left half top 4919 stone_brick_stairs facing north waterlogged false shape inner_left half top 4920 stone_brick_stairs facing north waterlogged true shape inner_right half top 4921 stone_brick_stairs facing north waterlogged false shape inner_right half top 4922 stone_brick_stairs facing north waterlogged true shape outer_left half top 4923 stone_brick_stairs facing north waterlogged false shape outer_left half top 4924 stone_brick_stairs facing north waterlogged true shape outer_right half top 4925 stone_brick_stairs facing north waterlogged false shape outer_right half top 4926 stone_brick_stairs facing north waterlogged true shape straight half bottom 4927 stone_brick_stairs facing north waterlogged false shape straight half bottom 4928 stone_brick_stairs facing north waterlogged true shape inner_left half bottom 4929 stone_brick_stairs facing north waterlogged false shape inner_left half bottom 4930 stone_brick_stairs facing north waterlogged true shape inner_right half bottom 4931 stone_brick_stairs facing north waterlogged false shape inner_right half bottom 4932 stone_brick_stairs facing north waterlogged true shape outer_left half bottom 4933 stone_brick_stairs facing north waterlogged false shape outer_left half bottom 4934 stone_brick_stairs facing north waterlogged true shape outer_right half bottom 4935 stone_brick_stairs facing north waterlogged false shape outer_right half bottom 4936 stone_brick_stairs facing south waterlogged true shape straight half top 4937 stone_brick_stairs facing south waterlogged false shape straight half top 4938 stone_brick_stairs facing south waterlogged true shape inner_left half top 4939 stone_brick_stairs facing south waterlogged false shape inner_left half top 4940 stone_brick_stairs facing south waterlogged true shape inner_right half top 4941 stone_brick_stairs facing south waterlogged false shape inner_right half top 4942 stone_brick_stairs facing south waterlogged true shape outer_left half top 4943 stone_brick_stairs facing south waterlogged false shape outer_left half top 4944 stone_brick_stairs facing south waterlogged true shape outer_right half top 4945 stone_brick_stairs facing south waterlogged false shape outer_right half top 4946 stone_brick_stairs facing south waterlogged true shape straight half bottom 4947 stone_brick_stairs facing south waterlogged false shape straight half bottom 4948 stone_brick_stairs facing south waterlogged true shape inner_left half bottom 4949 stone_brick_stairs facing south waterlogged false shape inner_left half bottom 4950 stone_brick_stairs facing south waterlogged true shape inner_right half bottom 4951 stone_brick_stairs facing south waterlogged false shape inner_right half bottom 4952 stone_brick_stairs facing south waterlogged true shape outer_left half bottom 4953 stone_brick_stairs facing south waterlogged false shape outer_left half bottom 4954 stone_brick_stairs facing south waterlogged true shape outer_right half bottom 4955 stone_brick_stairs facing south waterlogged false shape outer_right half bottom 4956 stone_brick_stairs facing west waterlogged true shape straight half top 4957 stone_brick_stairs facing west waterlogged false shape straight half top 4958 stone_brick_stairs facing west waterlogged true shape inner_left half top 4959 stone_brick_stairs facing west waterlogged false shape inner_left half top 4960 stone_brick_stairs facing west waterlogged true shape inner_right half top 4961 stone_brick_stairs facing west waterlogged false shape inner_right half top 4962 stone_brick_stairs facing west waterlogged true shape outer_left half top 4963 stone_brick_stairs facing west waterlogged false shape outer_left half top 4964 stone_brick_stairs facing west waterlogged true shape outer_right half top 4965 stone_brick_stairs facing west waterlogged false shape outer_right half top 4966 stone_brick_stairs facing west waterlogged true shape straight half bottom 4967 stone_brick_stairs facing west waterlogged false shape straight half bottom 4968 stone_brick_stairs facing west waterlogged true shape inner_left half bottom 4969 stone_brick_stairs facing west waterlogged false shape inner_left half bottom 4970 stone_brick_stairs facing west waterlogged true shape inner_right half bottom 4971 stone_brick_stairs facing west waterlogged false shape inner_right half bottom 4972 stone_brick_stairs facing west waterlogged true shape outer_left half bottom 4973 stone_brick_stairs facing west waterlogged false shape outer_left half bottom 4974 stone_brick_stairs facing west waterlogged true shape outer_right half bottom 4975 stone_brick_stairs facing west waterlogged false shape outer_right half bottom 4976 stone_brick_stairs facing east waterlogged true shape straight half top 4977 stone_brick_stairs facing east waterlogged false shape straight half top 4978 stone_brick_stairs facing east waterlogged true shape inner_left half top 4979 stone_brick_stairs facing east waterlogged false shape inner_left half top 4980 stone_brick_stairs facing east waterlogged true shape inner_right half top 4981 stone_brick_stairs facing east waterlogged false shape inner_right half top 4982 stone_brick_stairs facing east waterlogged true shape outer_left half top 4983 stone_brick_stairs facing east waterlogged false shape outer_left half top 4984 stone_brick_stairs facing east waterlogged true shape outer_right half top 4985 stone_brick_stairs facing east waterlogged false shape outer_right half top 4986 stone_brick_stairs facing east waterlogged true shape straight half bottom 4987 stone_brick_stairs facing east waterlogged false shape straight half bottom 4988 stone_brick_stairs facing east waterlogged true shape inner_left half bottom 4989 stone_brick_stairs facing east waterlogged false shape inner_left half bottom 4990 stone_brick_stairs facing east waterlogged true shape inner_right half bottom 4991 stone_brick_stairs facing east waterlogged false shape inner_right half bottom 4992 stone_brick_stairs facing east waterlogged true shape outer_left half bottom 4993 stone_brick_stairs facing east waterlogged false shape outer_left half bottom 4994 stone_brick_stairs facing east waterlogged true shape outer_right half bottom 4995 stone_brick_stairs facing east waterlogged false shape outer_right half bottom 4996 mycelium snowy true 4997 mycelium snowy false 4998 lily_pad 4999 nether_bricks 5000 nether_brick_fence waterlogged true south true east true north true west true 5001 nether_brick_fence waterlogged true south true east true north true west false 5002 nether_brick_fence waterlogged false south true east true north true west true 5003 nether_brick_fence waterlogged false south true east true north true west false 5004 nether_brick_fence waterlogged true south false east true north true west true 5005 nether_brick_fence waterlogged true south false east true north true west false 5006 nether_brick_fence waterlogged false south false east true north true west true 5007 nether_brick_fence waterlogged false south false east true north true west false 5008 nether_brick_fence waterlogged true south true east true north false west true 5009 nether_brick_fence waterlogged true south true east true north false west false 5010 nether_brick_fence waterlogged false south true east true north false west true 5011 nether_brick_fence waterlogged false south true east true north false west false 5012 nether_brick_fence waterlogged true south false east true north false west true 5013 nether_brick_fence waterlogged true south false east true north false west false 5014 nether_brick_fence waterlogged false south false east true north false west true 5015 nether_brick_fence waterlogged false south false east true north false west false 5016 nether_brick_fence waterlogged true south true east false north true west true 5017 nether_brick_fence waterlogged true south true east false north true west false 5018 nether_brick_fence waterlogged false south true east false north true west true 5019 nether_brick_fence waterlogged false south true east false north true west false 5020 nether_brick_fence waterlogged true south false east false north true west true 5021 nether_brick_fence waterlogged true south false east false north true west false 5022 nether_brick_fence waterlogged false south false east false north true west true 5023 nether_brick_fence waterlogged false south false east false north true west false 5024 nether_brick_fence waterlogged true south true east false north false west true 5025 nether_brick_fence waterlogged true south true east false north false west false 5026 nether_brick_fence waterlogged false south true east false north false west true 5027 nether_brick_fence waterlogged false south true east false north false west false 5028 nether_brick_fence waterlogged true south false east false north false west true 5029 nether_brick_fence waterlogged true south false east false north false west false 5030 nether_brick_fence waterlogged false south false east false north false west true 5031 nether_brick_fence waterlogged false south false east false north false west false 5032 nether_brick_stairs facing north waterlogged true shape straight half top 5033 nether_brick_stairs facing north waterlogged false shape straight half top 5034 nether_brick_stairs facing north waterlogged true shape inner_left half top 5035 nether_brick_stairs facing north waterlogged false shape inner_left half top 5036 nether_brick_stairs facing north waterlogged true shape inner_right half top 5037 nether_brick_stairs facing north waterlogged false shape inner_right half top 5038 nether_brick_stairs facing north waterlogged true shape outer_left half top 5039 nether_brick_stairs facing north waterlogged false shape outer_left half top 5040 nether_brick_stairs facing north waterlogged true shape outer_right half top 5041 nether_brick_stairs facing north waterlogged false shape outer_right half top 5042 nether_brick_stairs facing north waterlogged true shape straight half bottom 5043 nether_brick_stairs facing north waterlogged false shape straight half bottom 5044 nether_brick_stairs facing north waterlogged true shape inner_left half bottom 5045 nether_brick_stairs facing north waterlogged false shape inner_left half bottom 5046 nether_brick_stairs facing north waterlogged true shape inner_right half bottom 5047 nether_brick_stairs facing north waterlogged false shape inner_right half bottom 5048 nether_brick_stairs facing north waterlogged true shape outer_left half bottom 5049 nether_brick_stairs facing north waterlogged false shape outer_left half bottom 5050 nether_brick_stairs facing north waterlogged true shape outer_right half bottom 5051 nether_brick_stairs facing north waterlogged false shape outer_right half bottom 5052 nether_brick_stairs facing south waterlogged true shape straight half top 5053 nether_brick_stairs facing south waterlogged false shape straight half top 5054 nether_brick_stairs facing south waterlogged true shape inner_left half top 5055 nether_brick_stairs facing south waterlogged false shape inner_left half top 5056 nether_brick_stairs facing south waterlogged true shape inner_right half top 5057 nether_brick_stairs facing south waterlogged false shape inner_right half top 5058 nether_brick_stairs facing south waterlogged true shape outer_left half top 5059 nether_brick_stairs facing south waterlogged false shape outer_left half top 5060 nether_brick_stairs facing south waterlogged true shape outer_right half top 5061 nether_brick_stairs facing south waterlogged false shape outer_right half top 5062 nether_brick_stairs facing south waterlogged true shape straight half bottom 5063 nether_brick_stairs facing south waterlogged false shape straight half bottom 5064 nether_brick_stairs facing south waterlogged true shape inner_left half bottom 5065 nether_brick_stairs facing south waterlogged false shape inner_left half bottom 5066 nether_brick_stairs facing south waterlogged true shape inner_right half bottom 5067 nether_brick_stairs facing south waterlogged false shape inner_right half bottom 5068 nether_brick_stairs facing south waterlogged true shape outer_left half bottom 5069 nether_brick_stairs facing south waterlogged false shape outer_left half bottom 5070 nether_brick_stairs facing south waterlogged true shape outer_right half bottom 5071 nether_brick_stairs facing south waterlogged false shape outer_right half bottom 5072 nether_brick_stairs facing west waterlogged true shape straight half top 5073 nether_brick_stairs facing west waterlogged false shape straight half top 5074 nether_brick_stairs facing west waterlogged true shape inner_left half top 5075 nether_brick_stairs facing west waterlogged false shape inner_left half top 5076 nether_brick_stairs facing west waterlogged true shape inner_right half top 5077 nether_brick_stairs facing west waterlogged false shape inner_right half top 5078 nether_brick_stairs facing west waterlogged true shape outer_left half top 5079 nether_brick_stairs facing west waterlogged false shape outer_left half top 5080 nether_brick_stairs facing west waterlogged true shape outer_right half top 5081 nether_brick_stairs facing west waterlogged false shape outer_right half top 5082 nether_brick_stairs facing west waterlogged true shape straight half bottom 5083 nether_brick_stairs facing west waterlogged false shape straight half bottom 5084 nether_brick_stairs facing west waterlogged true shape inner_left half bottom 5085 nether_brick_stairs facing west waterlogged false shape inner_left half bottom 5086 nether_brick_stairs facing west waterlogged true shape inner_right half bottom 5087 nether_brick_stairs facing west waterlogged false shape inner_right half bottom 5088 nether_brick_stairs facing west waterlogged true shape outer_left half bottom 5089 nether_brick_stairs facing west waterlogged false shape outer_left half bottom 5090 nether_brick_stairs facing west waterlogged true shape outer_right half bottom 5091 nether_brick_stairs facing west waterlogged false shape outer_right half bottom 5092 nether_brick_stairs facing east waterlogged true shape straight half top 5093 nether_brick_stairs facing east waterlogged false shape straight half top 5094 nether_brick_stairs facing east waterlogged true shape inner_left half top 5095 nether_brick_stairs facing east waterlogged false shape inner_left half top 5096 nether_brick_stairs facing east waterlogged true shape inner_right half top 5097 nether_brick_stairs facing east waterlogged false shape inner_right half top 5098 nether_brick_stairs facing east waterlogged true shape outer_left half top 5099 nether_brick_stairs facing east waterlogged false shape outer_left half top 5100 nether_brick_stairs facing east waterlogged true shape outer_right half top 5101 nether_brick_stairs facing east waterlogged false shape outer_right half top 5102 nether_brick_stairs facing east waterlogged true shape straight half bottom 5103 nether_brick_stairs facing east waterlogged false shape straight half bottom 5104 nether_brick_stairs facing east waterlogged true shape inner_left half bottom 5105 nether_brick_stairs facing east waterlogged false shape inner_left half bottom 5106 nether_brick_stairs facing east waterlogged true shape inner_right half bottom 5107 nether_brick_stairs facing east waterlogged false shape inner_right half bottom 5108 nether_brick_stairs facing east waterlogged true shape outer_left half bottom 5109 nether_brick_stairs facing east waterlogged false shape outer_left half bottom 5110 nether_brick_stairs facing east waterlogged true shape outer_right half bottom 5111 nether_brick_stairs facing east waterlogged false shape outer_right half bottom 5112 nether_wart age 0 5113 nether_wart age 1 5114 nether_wart age 2 5115 nether_wart age 3 5116 enchanting_table 5117 brewing_stand has_bottle_0 true has_bottle_1 true has_bottle_2 true 5118 brewing_stand has_bottle_0 true has_bottle_1 true has_bottle_2 false 5119 brewing_stand has_bottle_0 true has_bottle_1 false has_bottle_2 true 5120 brewing_stand has_bottle_0 true has_bottle_1 false has_bottle_2 false 5121 brewing_stand has_bottle_0 false has_bottle_1 true has_bottle_2 true 5122 brewing_stand has_bottle_0 false has_bottle_1 true has_bottle_2 false 5123 brewing_stand has_bottle_0 false has_bottle_1 false has_bottle_2 true 5124 brewing_stand has_bottle_0 false has_bottle_1 false has_bottle_2 false 5125 cauldron level 0 5126 cauldron level 1 5127 cauldron level 2 5128 cauldron level 3 5129 end_portal 5130 end_portal_frame facing north eye true 5131 end_portal_frame facing south eye true 5132 end_portal_frame facing west eye true 5133 end_portal_frame facing east eye true 5134 end_portal_frame facing north eye false 5135 end_portal_frame facing south eye false 5136 end_portal_frame facing west eye false 5137 end_portal_frame facing east eye false 5138 end_stone 5139 dragon_egg 5140 redstone_lamp lit true 5141 redstone_lamp lit false 5142 cocoa facing north age 0 5143 cocoa facing south age 0 5144 cocoa facing west age 0 5145 cocoa facing east age 0 5146 cocoa facing north age 1 5147 cocoa facing south age 1 5148 cocoa facing west age 1 5149 cocoa facing east age 1 5150 cocoa facing north age 2 5151 cocoa facing south age 2 5152 cocoa facing west age 2 5153 cocoa facing east age 2 5154 sandstone_stairs facing north waterlogged true shape straight half top 5155 sandstone_stairs facing north waterlogged false shape straight half top 5156 sandstone_stairs facing north waterlogged true shape inner_left half top 5157 sandstone_stairs facing north waterlogged false shape inner_left half top 5158 sandstone_stairs facing north waterlogged true shape inner_right half top 5159 sandstone_stairs facing north waterlogged false shape inner_right half top 5160 sandstone_stairs facing north waterlogged true shape outer_left half top 5161 sandstone_stairs facing north waterlogged false shape outer_left half top 5162 sandstone_stairs facing north waterlogged true shape outer_right half top 5163 sandstone_stairs facing north waterlogged false shape outer_right half top 5164 sandstone_stairs facing north waterlogged true shape straight half bottom 5165 sandstone_stairs facing north waterlogged false shape straight half bottom 5166 sandstone_stairs facing north waterlogged true shape inner_left half bottom 5167 sandstone_stairs facing north waterlogged false shape inner_left half bottom 5168 sandstone_stairs facing north waterlogged true shape inner_right half bottom 5169 sandstone_stairs facing north waterlogged false shape inner_right half bottom 5170 sandstone_stairs facing north waterlogged true shape outer_left half bottom 5171 sandstone_stairs facing north waterlogged false shape outer_left half bottom 5172 sandstone_stairs facing north waterlogged true shape outer_right half bottom 5173 sandstone_stairs facing north waterlogged false shape outer_right half bottom 5174 sandstone_stairs facing south waterlogged true shape straight half top 5175 sandstone_stairs facing south waterlogged false shape straight half top 5176 sandstone_stairs facing south waterlogged true shape inner_left half top 5177 sandstone_stairs facing south waterlogged false shape inner_left half top 5178 sandstone_stairs facing south waterlogged true shape inner_right half top 5179 sandstone_stairs facing south waterlogged false shape inner_right half top 5180 sandstone_stairs facing south waterlogged true shape outer_left half top 5181 sandstone_stairs facing south waterlogged false shape outer_left half top 5182 sandstone_stairs facing south waterlogged true shape outer_right half top 5183 sandstone_stairs facing south waterlogged false shape outer_right half top 5184 sandstone_stairs facing south waterlogged true shape straight half bottom 5185 sandstone_stairs facing south waterlogged false shape straight half bottom 5186 sandstone_stairs facing south waterlogged true shape inner_left half bottom 5187 sandstone_stairs facing south waterlogged false shape inner_left half bottom 5188 sandstone_stairs facing south waterlogged true shape inner_right half bottom 5189 sandstone_stairs facing south waterlogged false shape inner_right half bottom 5190 sandstone_stairs facing south waterlogged true shape outer_left half bottom 5191 sandstone_stairs facing south waterlogged false shape outer_left half bottom 5192 sandstone_stairs facing south waterlogged true shape outer_right half bottom 5193 sandstone_stairs facing south waterlogged false shape outer_right half bottom 5194 sandstone_stairs facing west waterlogged true shape straight half top 5195 sandstone_stairs facing west waterlogged false shape straight half top 5196 sandstone_stairs facing west waterlogged true shape inner_left half top 5197 sandstone_stairs facing west waterlogged false shape inner_left half top 5198 sandstone_stairs facing west waterlogged true shape inner_right half top 5199 sandstone_stairs facing west waterlogged false shape inner_right half top 5200 sandstone_stairs facing west waterlogged true shape outer_left half top 5201 sandstone_stairs facing west waterlogged false shape outer_left half top 5202 sandstone_stairs facing west waterlogged true shape outer_right half top 5203 sandstone_stairs facing west waterlogged false shape outer_right half top 5204 sandstone_stairs facing west waterlogged true shape straight half bottom 5205 sandstone_stairs facing west waterlogged false shape straight half bottom 5206 sandstone_stairs facing west waterlogged true shape inner_left half bottom 5207 sandstone_stairs facing west waterlogged false shape inner_left half bottom 5208 sandstone_stairs facing west waterlogged true shape inner_right half bottom 5209 sandstone_stairs facing west waterlogged false shape inner_right half bottom 5210 sandstone_stairs facing west waterlogged true shape outer_left half bottom 5211 sandstone_stairs facing west waterlogged false shape outer_left half bottom 5212 sandstone_stairs facing west waterlogged true shape outer_right half bottom 5213 sandstone_stairs facing west waterlogged false shape outer_right half bottom 5214 sandstone_stairs facing east waterlogged true shape straight half top 5215 sandstone_stairs facing east waterlogged false shape straight half top 5216 sandstone_stairs facing east waterlogged true shape inner_left half top 5217 sandstone_stairs facing east waterlogged false shape inner_left half top 5218 sandstone_stairs facing east waterlogged true shape inner_right half top 5219 sandstone_stairs facing east waterlogged false shape inner_right half top 5220 sandstone_stairs facing east waterlogged true shape outer_left half top 5221 sandstone_stairs facing east waterlogged false shape outer_left half top 5222 sandstone_stairs facing east waterlogged true shape outer_right half top 5223 sandstone_stairs facing east waterlogged false shape outer_right half top 5224 sandstone_stairs facing east waterlogged true shape straight half bottom 5225 sandstone_stairs facing east waterlogged false shape straight half bottom 5226 sandstone_stairs facing east waterlogged true shape inner_left half bottom 5227 sandstone_stairs facing east waterlogged false shape inner_left half bottom 5228 sandstone_stairs facing east waterlogged true shape inner_right half bottom 5229 sandstone_stairs facing east waterlogged false shape inner_right half bottom 5230 sandstone_stairs facing east waterlogged true shape outer_left half bottom 5231 sandstone_stairs facing east waterlogged false shape outer_left half bottom 5232 sandstone_stairs facing east waterlogged true shape outer_right half bottom 5233 sandstone_stairs facing east waterlogged false shape outer_right half bottom 5234 emerald_ore 5235 ender_chest facing north waterlogged true 5236 ender_chest facing north waterlogged false 5237 ender_chest facing south waterlogged true 5238 ender_chest facing south waterlogged false 5239 ender_chest facing west waterlogged true 5240 ender_chest facing west waterlogged false 5241 ender_chest facing east waterlogged true 5242 ender_chest facing east waterlogged false 5243 tripwire_hook attached true facing north powered true 5244 tripwire_hook attached true facing north powered false 5245 tripwire_hook attached true facing south powered true 5246 tripwire_hook attached true facing south powered false 5247 tripwire_hook attached true facing west powered true 5248 tripwire_hook attached true facing west powered false 5249 tripwire_hook attached true facing east powered true 5250 tripwire_hook attached true facing east powered false 5251 tripwire_hook attached false facing north powered true 5252 tripwire_hook attached false facing north powered false 5253 tripwire_hook attached false facing south powered true 5254 tripwire_hook attached false facing south powered false 5255 tripwire_hook attached false facing west powered true 5256 tripwire_hook attached false facing west powered false 5257 tripwire_hook attached false facing east powered true 5258 tripwire_hook attached false facing east powered false 5259 tripwire attached true disarmed true powered true east true north true south true west true 5260 tripwire attached true disarmed true powered true east true north true south true west false 5261 tripwire attached true disarmed true powered true east true north true south false west true 5262 tripwire attached true disarmed true powered true east true north true south false west false 5263 tripwire attached true disarmed true powered false east true north true south true west true 5264 tripwire attached true disarmed true powered false east true north true south true west false 5265 tripwire attached true disarmed true powered false east true north true south false west true 5266 tripwire attached true disarmed true powered false east true north true south false west false 5267 tripwire attached true disarmed true powered true east true north false south true west true 5268 tripwire attached true disarmed true powered true east true north false south true west false 5269 tripwire attached true disarmed true powered true east true north false south false west true 5270 tripwire attached true disarmed true powered true east true north false south false west false 5271 tripwire attached true disarmed true powered false east true north false south true west true 5272 tripwire attached true disarmed true powered false east true north false south true west false 5273 tripwire attached true disarmed true powered false east true north false south false west true 5274 tripwire attached true disarmed true powered false east true north false south false west false 5275 tripwire attached true disarmed true powered true east false north true south true west true 5276 tripwire attached true disarmed true powered true east false north true south true west false 5277 tripwire attached true disarmed true powered true east false north true south false west true 5278 tripwire attached true disarmed true powered true east false north true south false west false 5279 tripwire attached true disarmed true powered false east false north true south true west true 5280 tripwire attached true disarmed true powered false east false north true south true west false 5281 tripwire attached true disarmed true powered false east false north true south false west true 5282 tripwire attached true disarmed true powered false east false north true south false west false 5283 tripwire attached true disarmed true powered true east false north false south true west true 5284 tripwire attached true disarmed true powered true east false north false south true west false 5285 tripwire attached true disarmed true powered true east false north false south false west true 5286 tripwire attached true disarmed true powered true east false north false south false west false 5287 tripwire attached true disarmed true powered false east false north false south true west true 5288 tripwire attached true disarmed true powered false east false north false south true west false 5289 tripwire attached true disarmed true powered false east false north false south false west true 5290 tripwire attached true disarmed true powered false east false north false south false west false 5291 tripwire attached true disarmed false powered true east true north true south true west true 5292 tripwire attached true disarmed false powered true east true north true south true west false 5293 tripwire attached true disarmed false powered true east true north true south false west true 5294 tripwire attached true disarmed false powered true east true north true south false west false 5295 tripwire attached true disarmed false powered false east true north true south true west true 5296 tripwire attached true disarmed false powered false east true north true south true west false 5297 tripwire attached true disarmed false powered false east true north true south false west true 5298 tripwire attached true disarmed false powered false east true north true south false west false 5299 tripwire attached true disarmed false powered true east true north false south true west true 5300 tripwire attached true disarmed false powered true east true north false south true west false 5301 tripwire attached true disarmed false powered true east true north false south false west true 5302 tripwire attached true disarmed false powered true east true north false south false west false 5303 tripwire attached true disarmed false powered false east true north false south true west true 5304 tripwire attached true disarmed false powered false east true north false south true west false 5305 tripwire attached true disarmed false powered false east true north false south false west true 5306 tripwire attached true disarmed false powered false east true north false south false west false 5307 tripwire attached true disarmed false powered true east false north true south true west true 5308 tripwire attached true disarmed false powered true east false north true south true west false 5309 tripwire attached true disarmed false powered true east false north true south false west true 5310 tripwire attached true disarmed false powered true east false north true south false west false 5311 tripwire attached true disarmed false powered false east false north true south true west true 5312 tripwire attached true disarmed false powered false east false north true south true west false 5313 tripwire attached true disarmed false powered false east false north true south false west true 5314 tripwire attached true disarmed false powered false east false north true south false west false 5315 tripwire attached true disarmed false powered true east false north false south true west true 5316 tripwire attached true disarmed false powered true east false north false south true west false 5317 tripwire attached true disarmed false powered true east false north false south false west true 5318 tripwire attached true disarmed false powered true east false north false south false west false 5319 tripwire attached true disarmed false powered false east false north false south true west true 5320 tripwire attached true disarmed false powered false east false north false south true west false 5321 tripwire attached true disarmed false powered false east false north false south false west true 5322 tripwire attached true disarmed false powered false east false north false south false west false 5323 tripwire attached false disarmed true powered true east true north true south true west true 5324 tripwire attached false disarmed true powered true east true north true south true west false 5325 tripwire attached false disarmed true powered true east true north true south false west true 5326 tripwire attached false disarmed true powered true east true north true south false west false 5327 tripwire attached false disarmed true powered false east true north true south true west true 5328 tripwire attached false disarmed true powered false east true north true south true west false 5329 tripwire attached false disarmed true powered false east true north true south false west true 5330 tripwire attached false disarmed true powered false east true north true south false west false 5331 tripwire attached false disarmed true powered true east true north false south true west true 5332 tripwire attached false disarmed true powered true east true north false south true west false 5333 tripwire attached false disarmed true powered true east true north false south false west true 5334 tripwire attached false disarmed true powered true east true north false south false west false 5335 tripwire attached false disarmed true powered false east true north false south true west true 5336 tripwire attached false disarmed true powered false east true north false south true west false 5337 tripwire attached false disarmed true powered false east true north false south false west true 5338 tripwire attached false disarmed true powered false east true north false south false west false 5339 tripwire attached false disarmed true powered true east false north true south true west true 5340 tripwire attached false disarmed true powered true east false north true south true west false 5341 tripwire attached false disarmed true powered true east false north true south false west true 5342 tripwire attached false disarmed true powered true east false north true south false west false 5343 tripwire attached false disarmed true powered false east false north true south true west true 5344 tripwire attached false disarmed true powered false east false north true south true west false 5345 tripwire attached false disarmed true powered false east false north true south false west true 5346 tripwire attached false disarmed true powered false east false north true south false west false 5347 tripwire attached false disarmed true powered true east false north false south true west true 5348 tripwire attached false disarmed true powered true east false north false south true west false 5349 tripwire attached false disarmed true powered true east false north false south false west true 5350 tripwire attached false disarmed true powered true east false north false south false west false 5351 tripwire attached false disarmed true powered false east false north false south true west true 5352 tripwire attached false disarmed true powered false east false north false south true west false 5353 tripwire attached false disarmed true powered false east false north false south false west true 5354 tripwire attached false disarmed true powered false east false north false south false west false 5355 tripwire attached false disarmed false powered true east true north true south true west true 5356 tripwire attached false disarmed false powered true east true north true south true west false 5357 tripwire attached false disarmed false powered true east true north true south false west true 5358 tripwire attached false disarmed false powered true east true north true south false west false 5359 tripwire attached false disarmed false powered false east true north true south true west true 5360 tripwire attached false disarmed false powered false east true north true south true west false 5361 tripwire attached false disarmed false powered false east true north true south false west true 5362 tripwire attached false disarmed false powered false east true north true south false west false 5363 tripwire attached false disarmed false powered true east true north false south true west true 5364 tripwire attached false disarmed false powered true east true north false south true west false 5365 tripwire attached false disarmed false powered true east true north false south false west true 5366 tripwire attached false disarmed false powered true east true north false south false west false 5367 tripwire attached false disarmed false powered false east true north false south true west true 5368 tripwire attached false disarmed false powered false east true north false south true west false 5369 tripwire attached false disarmed false powered false east true north false south false west true 5370 tripwire attached false disarmed false powered false east true north false south false west false 5371 tripwire attached false disarmed false powered true east false north true south true west true 5372 tripwire attached false disarmed false powered true east false north true south true west false 5373 tripwire attached false disarmed false powered true east false north true south false west true 5374 tripwire attached false disarmed false powered true east false north true south false west false 5375 tripwire attached false disarmed false powered false east false north true south true west true 5376 tripwire attached false disarmed false powered false east false north true south true west false 5377 tripwire attached false disarmed false powered false east false north true south false west true 5378 tripwire attached false disarmed false powered false east false north true south false west false 5379 tripwire attached false disarmed false powered true east false north false south true west true 5380 tripwire attached false disarmed false powered true east false north false south true west false 5381 tripwire attached false disarmed false powered true east false north false south false west true 5382 tripwire attached false disarmed false powered true east false north false south false west false 5383 tripwire attached false disarmed false powered false east false north false south true west true 5384 tripwire attached false disarmed false powered false east false north false south true west false 5385 tripwire attached false disarmed false powered false east false north false south false west true 5386 tripwire attached false disarmed false powered false east false north false south false west false 5387 emerald_block 5388 spruce_stairs facing north waterlogged true shape straight half top 5389 spruce_stairs facing north waterlogged false shape straight half top 5390 spruce_stairs facing north waterlogged true shape inner_left half top 5391 spruce_stairs facing north waterlogged false shape inner_left half top 5392 spruce_stairs facing north waterlogged true shape inner_right half top 5393 spruce_stairs facing north waterlogged false shape inner_right half top 5394 spruce_stairs facing north waterlogged true shape outer_left half top 5395 spruce_stairs facing north waterlogged false shape outer_left half top 5396 spruce_stairs facing north waterlogged true shape outer_right half top 5397 spruce_stairs facing north waterlogged false shape outer_right half top 5398 spruce_stairs facing north waterlogged true shape straight half bottom 5399 spruce_stairs facing north waterlogged false shape straight half bottom 5400 spruce_stairs facing north waterlogged true shape inner_left half bottom 5401 spruce_stairs facing north waterlogged false shape inner_left half bottom 5402 spruce_stairs facing north waterlogged true shape inner_right half bottom 5403 spruce_stairs facing north waterlogged false shape inner_right half bottom 5404 spruce_stairs facing north waterlogged true shape outer_left half bottom 5405 spruce_stairs facing north waterlogged false shape outer_left half bottom 5406 spruce_stairs facing north waterlogged true shape outer_right half bottom 5407 spruce_stairs facing north waterlogged false shape outer_right half bottom 5408 spruce_stairs facing south waterlogged true shape straight half top 5409 spruce_stairs facing south waterlogged false shape straight half top 5410 spruce_stairs facing south waterlogged true shape inner_left half top 5411 spruce_stairs facing south waterlogged false shape inner_left half top 5412 spruce_stairs facing south waterlogged true shape inner_right half top 5413 spruce_stairs facing south waterlogged false shape inner_right half top 5414 spruce_stairs facing south waterlogged true shape outer_left half top 5415 spruce_stairs facing south waterlogged false shape outer_left half top 5416 spruce_stairs facing south waterlogged true shape outer_right half top 5417 spruce_stairs facing south waterlogged false shape outer_right half top 5418 spruce_stairs facing south waterlogged true shape straight half bottom 5419 spruce_stairs facing south waterlogged false shape straight half bottom 5420 spruce_stairs facing south waterlogged true shape inner_left half bottom 5421 spruce_stairs facing south waterlogged false shape inner_left half bottom 5422 spruce_stairs facing south waterlogged true shape inner_right half bottom 5423 spruce_stairs facing south waterlogged false shape inner_right half bottom 5424 spruce_stairs facing south waterlogged true shape outer_left half bottom 5425 spruce_stairs facing south waterlogged false shape outer_left half bottom 5426 spruce_stairs facing south waterlogged true shape outer_right half bottom 5427 spruce_stairs facing south waterlogged false shape outer_right half bottom 5428 spruce_stairs facing west waterlogged true shape straight half top 5429 spruce_stairs facing west waterlogged false shape straight half top 5430 spruce_stairs facing west waterlogged true shape inner_left half top 5431 spruce_stairs facing west waterlogged false shape inner_left half top 5432 spruce_stairs facing west waterlogged true shape inner_right half top 5433 spruce_stairs facing west waterlogged false shape inner_right half top 5434 spruce_stairs facing west waterlogged true shape outer_left half top 5435 spruce_stairs facing west waterlogged false shape outer_left half top 5436 spruce_stairs facing west waterlogged true shape outer_right half top 5437 spruce_stairs facing west waterlogged false shape outer_right half top 5438 spruce_stairs facing west waterlogged true shape straight half bottom 5439 spruce_stairs facing west waterlogged false shape straight half bottom 5440 spruce_stairs facing west waterlogged true shape inner_left half bottom 5441 spruce_stairs facing west waterlogged false shape inner_left half bottom 5442 spruce_stairs facing west waterlogged true shape inner_right half bottom 5443 spruce_stairs facing west waterlogged false shape inner_right half bottom 5444 spruce_stairs facing west waterlogged true shape outer_left half bottom 5445 spruce_stairs facing west waterlogged false shape outer_left half bottom 5446 spruce_stairs facing west waterlogged true shape outer_right half bottom 5447 spruce_stairs facing west waterlogged false shape outer_right half bottom 5448 spruce_stairs facing east waterlogged true shape straight half top 5449 spruce_stairs facing east waterlogged false shape straight half top 5450 spruce_stairs facing east waterlogged true shape inner_left half top 5451 spruce_stairs facing east waterlogged false shape inner_left half top 5452 spruce_stairs facing east waterlogged true shape inner_right half top 5453 spruce_stairs facing east waterlogged false shape inner_right half top 5454 spruce_stairs facing east waterlogged true shape outer_left half top 5455 spruce_stairs facing east waterlogged false shape outer_left half top 5456 spruce_stairs facing east waterlogged true shape outer_right half top 5457 spruce_stairs facing east waterlogged false shape outer_right half top 5458 spruce_stairs facing east waterlogged true shape straight half bottom 5459 spruce_stairs facing east waterlogged false shape straight half bottom 5460 spruce_stairs facing east waterlogged true shape inner_left half bottom 5461 spruce_stairs facing east waterlogged false shape inner_left half bottom 5462 spruce_stairs facing east waterlogged true shape inner_right half bottom 5463 spruce_stairs facing east waterlogged false shape inner_right half bottom 5464 spruce_stairs facing east waterlogged true shape outer_left half bottom 5465 spruce_stairs facing east waterlogged false shape outer_left half bottom 5466 spruce_stairs facing east waterlogged true shape outer_right half bottom 5467 spruce_stairs facing east waterlogged false shape outer_right half bottom 5468 birch_stairs facing north waterlogged true shape straight half top 5469 birch_stairs facing north waterlogged false shape straight half top 5470 birch_stairs facing north waterlogged true shape inner_left half top 5471 birch_stairs facing north waterlogged false shape inner_left half top 5472 birch_stairs facing north waterlogged true shape inner_right half top 5473 birch_stairs facing north waterlogged false shape inner_right half top 5474 birch_stairs facing north waterlogged true shape outer_left half top 5475 birch_stairs facing north waterlogged false shape outer_left half top 5476 birch_stairs facing north waterlogged true shape outer_right half top 5477 birch_stairs facing north waterlogged false shape outer_right half top 5478 birch_stairs facing north waterlogged true shape straight half bottom 5479 birch_stairs facing north waterlogged false shape straight half bottom 5480 birch_stairs facing north waterlogged true shape inner_left half bottom 5481 birch_stairs facing north waterlogged false shape inner_left half bottom 5482 birch_stairs facing north waterlogged true shape inner_right half bottom 5483 birch_stairs facing north waterlogged false shape inner_right half bottom 5484 birch_stairs facing north waterlogged true shape outer_left half bottom 5485 birch_stairs facing north waterlogged false shape outer_left half bottom 5486 birch_stairs facing north waterlogged true shape outer_right half bottom 5487 birch_stairs facing north waterlogged false shape outer_right half bottom 5488 birch_stairs facing south waterlogged true shape straight half top 5489 birch_stairs facing south waterlogged false shape straight half top 5490 birch_stairs facing south waterlogged true shape inner_left half top 5491 birch_stairs facing south waterlogged false shape inner_left half top 5492 birch_stairs facing south waterlogged true shape inner_right half top 5493 birch_stairs facing south waterlogged false shape inner_right half top 5494 birch_stairs facing south waterlogged true shape outer_left half top 5495 birch_stairs facing south waterlogged false shape outer_left half top 5496 birch_stairs facing south waterlogged true shape outer_right half top 5497 birch_stairs facing south waterlogged false shape outer_right half top 5498 birch_stairs facing south waterlogged true shape straight half bottom 5499 birch_stairs facing south waterlogged false shape straight half bottom 5500 birch_stairs facing south waterlogged true shape inner_left half bottom 5501 birch_stairs facing south waterlogged false shape inner_left half bottom 5502 birch_stairs facing south waterlogged true shape inner_right half bottom 5503 birch_stairs facing south waterlogged false shape inner_right half bottom 5504 birch_stairs facing south waterlogged true shape outer_left half bottom 5505 birch_stairs facing south waterlogged false shape outer_left half bottom 5506 birch_stairs facing south waterlogged true shape outer_right half bottom 5507 birch_stairs facing south waterlogged false shape outer_right half bottom 5508 birch_stairs facing west waterlogged true shape straight half top 5509 birch_stairs facing west waterlogged false shape straight half top 5510 birch_stairs facing west waterlogged true shape inner_left half top 5511 birch_stairs facing west waterlogged false shape inner_left half top 5512 birch_stairs facing west waterlogged true shape inner_right half top 5513 birch_stairs facing west waterlogged false shape inner_right half top 5514 birch_stairs facing west waterlogged true shape outer_left half top 5515 birch_stairs facing west waterlogged false shape outer_left half top 5516 birch_stairs facing west waterlogged true shape outer_right half top 5517 birch_stairs facing west waterlogged false shape outer_right half top 5518 birch_stairs facing west waterlogged true shape straight half bottom 5519 birch_stairs facing west waterlogged false shape straight half bottom 5520 birch_stairs facing west waterlogged true shape inner_left half bottom 5521 birch_stairs facing west waterlogged false shape inner_left half bottom 5522 birch_stairs facing west waterlogged true shape inner_right half bottom 5523 birch_stairs facing west waterlogged false shape inner_right half bottom 5524 birch_stairs facing west waterlogged true shape outer_left half bottom 5525 birch_stairs facing west waterlogged false shape outer_left half bottom 5526 birch_stairs facing west waterlogged true shape outer_right half bottom 5527 birch_stairs facing west waterlogged false shape outer_right half bottom 5528 birch_stairs facing east waterlogged true shape straight half top 5529 birch_stairs facing east waterlogged false shape straight half top 5530 birch_stairs facing east waterlogged true shape inner_left half top 5531 birch_stairs facing east waterlogged false shape inner_left half top 5532 birch_stairs facing east waterlogged true shape inner_right half top 5533 birch_stairs facing east waterlogged false shape inner_right half top 5534 birch_stairs facing east waterlogged true shape outer_left half top 5535 birch_stairs facing east waterlogged false shape outer_left half top 5536 birch_stairs facing east waterlogged true shape outer_right half top 5537 birch_stairs facing east waterlogged false shape outer_right half top 5538 birch_stairs facing east waterlogged true shape straight half bottom 5539 birch_stairs facing east waterlogged false shape straight half bottom 5540 birch_stairs facing east waterlogged true shape inner_left half bottom 5541 birch_stairs facing east waterlogged false shape inner_left half bottom 5542 birch_stairs facing east waterlogged true shape inner_right half bottom 5543 birch_stairs facing east waterlogged false shape inner_right half bottom 5544 birch_stairs facing east waterlogged true shape outer_left half bottom 5545 birch_stairs facing east waterlogged false shape outer_left half bottom 5546 birch_stairs facing east waterlogged true shape outer_right half bottom 5547 birch_stairs facing east waterlogged false shape outer_right half bottom 5548 jungle_stairs facing north waterlogged true shape straight half top 5549 jungle_stairs facing north waterlogged false shape straight half top 5550 jungle_stairs facing north waterlogged true shape inner_left half top 5551 jungle_stairs facing north waterlogged false shape inner_left half top 5552 jungle_stairs facing north waterlogged true shape inner_right half top 5553 jungle_stairs facing north waterlogged false shape inner_right half top 5554 jungle_stairs facing north waterlogged true shape outer_left half top 5555 jungle_stairs facing north waterlogged false shape outer_left half top 5556 jungle_stairs facing north waterlogged true shape outer_right half top 5557 jungle_stairs facing north waterlogged false shape outer_right half top 5558 jungle_stairs facing north waterlogged true shape straight half bottom 5559 jungle_stairs facing north waterlogged false shape straight half bottom 5560 jungle_stairs facing north waterlogged true shape inner_left half bottom 5561 jungle_stairs facing north waterlogged false shape inner_left half bottom 5562 jungle_stairs facing north waterlogged true shape inner_right half bottom 5563 jungle_stairs facing north waterlogged false shape inner_right half bottom 5564 jungle_stairs facing north waterlogged true shape outer_left half bottom 5565 jungle_stairs facing north waterlogged false shape outer_left half bottom 5566 jungle_stairs facing north waterlogged true shape outer_right half bottom 5567 jungle_stairs facing north waterlogged false shape outer_right half bottom 5568 jungle_stairs facing south waterlogged true shape straight half top 5569 jungle_stairs facing south waterlogged false shape straight half top 5570 jungle_stairs facing south waterlogged true shape inner_left half top 5571 jungle_stairs facing south waterlogged false shape inner_left half top 5572 jungle_stairs facing south waterlogged true shape inner_right half top 5573 jungle_stairs facing south waterlogged false shape inner_right half top 5574 jungle_stairs facing south waterlogged true shape outer_left half top 5575 jungle_stairs facing south waterlogged false shape outer_left half top 5576 jungle_stairs facing south waterlogged true shape outer_right half top 5577 jungle_stairs facing south waterlogged false shape outer_right half top 5578 jungle_stairs facing south waterlogged true shape straight half bottom 5579 jungle_stairs facing south waterlogged false shape straight half bottom 5580 jungle_stairs facing south waterlogged true shape inner_left half bottom 5581 jungle_stairs facing south waterlogged false shape inner_left half bottom 5582 jungle_stairs facing south waterlogged true shape inner_right half bottom 5583 jungle_stairs facing south waterlogged false shape inner_right half bottom 5584 jungle_stairs facing south waterlogged true shape outer_left half bottom 5585 jungle_stairs facing south waterlogged false shape outer_left half bottom 5586 jungle_stairs facing south waterlogged true shape outer_right half bottom 5587 jungle_stairs facing south waterlogged false shape outer_right half bottom 5588 jungle_stairs facing west waterlogged true shape straight half top 5589 jungle_stairs facing west waterlogged false shape straight half top 5590 jungle_stairs facing west waterlogged true shape inner_left half top 5591 jungle_stairs facing west waterlogged false shape inner_left half top 5592 jungle_stairs facing west waterlogged true shape inner_right half top 5593 jungle_stairs facing west waterlogged false shape inner_right half top 5594 jungle_stairs facing west waterlogged true shape outer_left half top 5595 jungle_stairs facing west waterlogged false shape outer_left half top 5596 jungle_stairs facing west waterlogged true shape outer_right half top 5597 jungle_stairs facing west waterlogged false shape outer_right half top 5598 jungle_stairs facing west waterlogged true shape straight half bottom 5599 jungle_stairs facing west waterlogged false shape straight half bottom 5600 jungle_stairs facing west waterlogged true shape inner_left half bottom 5601 jungle_stairs facing west waterlogged false shape inner_left half bottom 5602 jungle_stairs facing west waterlogged true shape inner_right half bottom 5603 jungle_stairs facing west waterlogged false shape inner_right half bottom 5604 jungle_stairs facing west waterlogged true shape outer_left half bottom 5605 jungle_stairs facing west waterlogged false shape outer_left half bottom 5606 jungle_stairs facing west waterlogged true shape outer_right half bottom 5607 jungle_stairs facing west waterlogged false shape outer_right half bottom 5608 jungle_stairs facing east waterlogged true shape straight half top 5609 jungle_stairs facing east waterlogged false shape straight half top 5610 jungle_stairs facing east waterlogged true shape inner_left half top 5611 jungle_stairs facing east waterlogged false shape inner_left half top 5612 jungle_stairs facing east waterlogged true shape inner_right half top 5613 jungle_stairs facing east waterlogged false shape inner_right half top 5614 jungle_stairs facing east waterlogged true shape outer_left half top 5615 jungle_stairs facing east waterlogged false shape outer_left half top 5616 jungle_stairs facing east waterlogged true shape outer_right half top 5617 jungle_stairs facing east waterlogged false shape outer_right half top 5618 jungle_stairs facing east waterlogged true shape straight half bottom 5619 jungle_stairs facing east waterlogged false shape straight half bottom 5620 jungle_stairs facing east waterlogged true shape inner_left half bottom 5621 jungle_stairs facing east waterlogged false shape inner_left half bottom 5622 jungle_stairs facing east waterlogged true shape inner_right half bottom 5623 jungle_stairs facing east waterlogged false shape inner_right half bottom 5624 jungle_stairs facing east waterlogged true shape outer_left half bottom 5625 jungle_stairs facing east waterlogged false shape outer_left half bottom 5626 jungle_stairs facing east waterlogged true shape outer_right half bottom 5627 jungle_stairs facing east waterlogged false shape outer_right half bottom 5628 command_block conditional true facing north 5629 command_block conditional true facing east 5630 command_block conditional true facing south 5631 command_block conditional true facing west 5632 command_block conditional true facing up 5633 command_block conditional true facing down 5634 command_block conditional false facing north 5635 command_block conditional false facing east 5636 command_block conditional false facing south 5637 command_block conditional false facing west 5638 command_block conditional false facing up 5639 command_block conditional false facing down 5640 beacon 5641 cobblestone_wall waterlogged true south true east true north true up true west true 5642 cobblestone_wall waterlogged true south true east true north true up true west false 5643 cobblestone_wall waterlogged false south true east true north true up true west true 5644 cobblestone_wall waterlogged false south true east true north true up true west false 5645 cobblestone_wall waterlogged true south true east true north true up false west true 5646 cobblestone_wall waterlogged true south true east true north true up false west false 5647 cobblestone_wall waterlogged false south true east true north true up false west true 5648 cobblestone_wall waterlogged false south true east true north true up false west false 5649 cobblestone_wall waterlogged true south false east true north true up true west true 5650 cobblestone_wall waterlogged true south false east true north true up true west false 5651 cobblestone_wall waterlogged false south false east true north true up true west true 5652 cobblestone_wall waterlogged false south false east true north true up true west false 5653 cobblestone_wall waterlogged true south false east true north true up false west true 5654 cobblestone_wall waterlogged true south false east true north true up false west false 5655 cobblestone_wall waterlogged false south false east true north true up false west true 5656 cobblestone_wall waterlogged false south false east true north true up false west false 5657 cobblestone_wall waterlogged true south true east true north false up true west true 5658 cobblestone_wall waterlogged true south true east true north false up true west false 5659 cobblestone_wall waterlogged false south true east true north false up true west true 5660 cobblestone_wall waterlogged false south true east true north false up true west false 5661 cobblestone_wall waterlogged true south true east true north false up false west true 5662 cobblestone_wall waterlogged true south true east true north false up false west false 5663 cobblestone_wall waterlogged false south true east true north false up false west true 5664 cobblestone_wall waterlogged false south true east true north false up false west false 5665 cobblestone_wall waterlogged true south false east true north false up true west true 5666 cobblestone_wall waterlogged true south false east true north false up true west false 5667 cobblestone_wall waterlogged false south false east true north false up true west true 5668 cobblestone_wall waterlogged false south false east true north false up true west false 5669 cobblestone_wall waterlogged true south false east true north false up false west true 5670 cobblestone_wall waterlogged true south false east true north false up false west false 5671 cobblestone_wall waterlogged false south false east true north false up false west true 5672 cobblestone_wall waterlogged false south false east true north false up false west false 5673 cobblestone_wall waterlogged true south true east false north true up true west true 5674 cobblestone_wall waterlogged true south true east false north true up true west false 5675 cobblestone_wall waterlogged false south true east false north true up true west true 5676 cobblestone_wall waterlogged false south true east false north true up true west false 5677 cobblestone_wall waterlogged true south true east false north true up false west true 5678 cobblestone_wall waterlogged true south true east false north true up false west false 5679 cobblestone_wall waterlogged false south true east false north true up false west true 5680 cobblestone_wall waterlogged false south true east false north true up false west false 5681 cobblestone_wall waterlogged true south false east false north true up true west true 5682 cobblestone_wall waterlogged true south false east false north true up true west false 5683 cobblestone_wall waterlogged false south false east false north true up true west true 5684 cobblestone_wall waterlogged false south false east false north true up true west false 5685 cobblestone_wall waterlogged true south false east false north true up false west true 5686 cobblestone_wall waterlogged true south false east false north true up false west false 5687 cobblestone_wall waterlogged false south false east false north true up false west true 5688 cobblestone_wall waterlogged false south false east false north true up false west false 5689 cobblestone_wall waterlogged true south true east false north false up true west true 5690 cobblestone_wall waterlogged true south true east false north false up true west false 5691 cobblestone_wall waterlogged false south true east false north false up true west true 5692 cobblestone_wall waterlogged false south true east false north false up true west false 5693 cobblestone_wall waterlogged true south true east false north false up false west true 5694 cobblestone_wall waterlogged true south true east false north false up false west false 5695 cobblestone_wall waterlogged false south true east false north false up false west true 5696 cobblestone_wall waterlogged false south true east false north false up false west false 5697 cobblestone_wall waterlogged true south false east false north false up true west true 5698 cobblestone_wall waterlogged true south false east false north false up true west false 5699 cobblestone_wall waterlogged false south false east false north false up true west true 5700 cobblestone_wall waterlogged false south false east false north false up true west false 5701 cobblestone_wall waterlogged true south false east false north false up false west true 5702 cobblestone_wall waterlogged true south false east false north false up false west false 5703 cobblestone_wall waterlogged false south false east false north false up false west true 5704 cobblestone_wall waterlogged false south false east false north false up false west false 5705 mossy_cobblestone_wall waterlogged true south true east true north true up true west true 5706 mossy_cobblestone_wall waterlogged true south true east true north true up true west false 5707 mossy_cobblestone_wall waterlogged false south true east true north true up true west true 5708 mossy_cobblestone_wall waterlogged false south true east true north true up true west false 5709 mossy_cobblestone_wall waterlogged true south true east true north true up false west true 5710 mossy_cobblestone_wall waterlogged true south true east true north true up false west false 5711 mossy_cobblestone_wall waterlogged false south true east true north true up false west true 5712 mossy_cobblestone_wall waterlogged false south true east true north true up false west false 5713 mossy_cobblestone_wall waterlogged true south false east true north true up true west true 5714 mossy_cobblestone_wall waterlogged true south false east true north true up true west false 5715 mossy_cobblestone_wall waterlogged false south false east true north true up true west true 5716 mossy_cobblestone_wall waterlogged false south false east true north true up true west false 5717 mossy_cobblestone_wall waterlogged true south false east true north true up false west true 5718 mossy_cobblestone_wall waterlogged true south false east true north true up false west false 5719 mossy_cobblestone_wall waterlogged false south false east true north true up false west true 5720 mossy_cobblestone_wall waterlogged false south false east true north true up false west false 5721 mossy_cobblestone_wall waterlogged true south true east true north false up true west true 5722 mossy_cobblestone_wall waterlogged true south true east true north false up true west false 5723 mossy_cobblestone_wall waterlogged false south true east true north false up true west true 5724 mossy_cobblestone_wall waterlogged false south true east true north false up true west false 5725 mossy_cobblestone_wall waterlogged true south true east true north false up false west true 5726 mossy_cobblestone_wall waterlogged true south true east true north false up false west false 5727 mossy_cobblestone_wall waterlogged false south true east true north false up false west true 5728 mossy_cobblestone_wall waterlogged false south true east true north false up false west false 5729 mossy_cobblestone_wall waterlogged true south false east true north false up true west true 5730 mossy_cobblestone_wall waterlogged true south false east true north false up true west false 5731 mossy_cobblestone_wall waterlogged false south false east true north false up true west true 5732 mossy_cobblestone_wall waterlogged false south false east true north false up true west false 5733 mossy_cobblestone_wall waterlogged true south false east true north false up false west true 5734 mossy_cobblestone_wall waterlogged true south false east true north false up false west false 5735 mossy_cobblestone_wall waterlogged false south false east true north false up false west true 5736 mossy_cobblestone_wall waterlogged false south false east true north false up false west false 5737 mossy_cobblestone_wall waterlogged true south true east false north true up true west true 5738 mossy_cobblestone_wall waterlogged true south true east false north true up true west false 5739 mossy_cobblestone_wall waterlogged false south true east false north true up true west true 5740 mossy_cobblestone_wall waterlogged false south true east false north true up true west false 5741 mossy_cobblestone_wall waterlogged true south true east false north true up false west true 5742 mossy_cobblestone_wall waterlogged true south true east false north true up false west false 5743 mossy_cobblestone_wall waterlogged false south true east false north true up false west true 5744 mossy_cobblestone_wall waterlogged false south true east false north true up false west false 5745 mossy_cobblestone_wall waterlogged true south false east false north true up true west true 5746 mossy_cobblestone_wall waterlogged true south false east false north true up true west false 5747 mossy_cobblestone_wall waterlogged false south false east false north true up true west true 5748 mossy_cobblestone_wall waterlogged false south false east false north true up true west false 5749 mossy_cobblestone_wall waterlogged true south false east false north true up false west true 5750 mossy_cobblestone_wall waterlogged true south false east false north true up false west false 5751 mossy_cobblestone_wall waterlogged false south false east false north true up false west true 5752 mossy_cobblestone_wall waterlogged false south false east false north true up false west false 5753 mossy_cobblestone_wall waterlogged true south true east false north false up true west true 5754 mossy_cobblestone_wall waterlogged true south true east false north false up true west false 5755 mossy_cobblestone_wall waterlogged false south true east false north false up true west true 5756 mossy_cobblestone_wall waterlogged false south true east false north false up true west false 5757 mossy_cobblestone_wall waterlogged true south true east false north false up false west true 5758 mossy_cobblestone_wall waterlogged true south true east false north false up false west false 5759 mossy_cobblestone_wall waterlogged false south true east false north false up false west true 5760 mossy_cobblestone_wall waterlogged false south true east false north false up false west false 5761 mossy_cobblestone_wall waterlogged true south false east false north false up true west true 5762 mossy_cobblestone_wall waterlogged true south false east false north false up true west false 5763 mossy_cobblestone_wall waterlogged false south false east false north false up true west true 5764 mossy_cobblestone_wall waterlogged false south false east false north false up true west false 5765 mossy_cobblestone_wall waterlogged true south false east false north false up false west true 5766 mossy_cobblestone_wall waterlogged true south false east false north false up false west false 5767 mossy_cobblestone_wall waterlogged false south false east false north false up false west true 5768 mossy_cobblestone_wall waterlogged false south false east false north false up false west false 5769 flower_pot 5770 potted_oak_sapling 5771 potted_spruce_sapling 5772 potted_birch_sapling 5773 potted_jungle_sapling 5774 potted_acacia_sapling 5775 potted_dark_oak_sapling 5776 potted_fern 5777 potted_dandelion 5778 potted_poppy 5779 potted_blue_orchid 5780 potted_allium 5781 potted_azure_bluet 5782 potted_red_tulip 5783 potted_orange_tulip 5784 potted_white_tulip 5785 potted_pink_tulip 5786 potted_oxeye_daisy 5787 potted_cornflower 5788 potted_lily_of_the_valley 5789 potted_wither_rose 5790 potted_red_mushroom 5791 potted_brown_mushroom 5792 potted_dead_bush 5793 potted_cactus 5794 carrots age 0 5795 carrots age 1 5796 carrots age 2 5797 carrots age 3 5798 carrots age 4 5799 carrots age 5 5800 carrots age 6 5801 carrots age 7 5802 potatoes age 0 5803 potatoes age 1 5804 potatoes age 2 5805 potatoes age 3 5806 potatoes age 4 5807 potatoes age 5 5808 potatoes age 6 5809 potatoes age 7 5810 oak_button facing north face floor powered true 5811 oak_button facing north face floor powered false 5812 oak_button facing south face floor powered true 5813 oak_button facing south face floor powered false 5814 oak_button facing west face floor powered true 5815 oak_button facing west face floor powered false 5816 oak_button facing east face floor powered true 5817 oak_button facing east face floor powered false 5818 oak_button facing north face wall powered true 5819 oak_button facing north face wall powered false 5820 oak_button facing south face wall powered true 5821 oak_button facing south face wall powered false 5822 oak_button facing west face wall powered true 5823 oak_button facing west face wall powered false 5824 oak_button facing east face wall powered true 5825 oak_button facing east face wall powered false 5826 oak_button facing north face ceiling powered true 5827 oak_button facing north face ceiling powered false 5828 oak_button facing south face ceiling powered true 5829 oak_button facing south face ceiling powered false 5830 oak_button facing west face ceiling powered true 5831 oak_button facing west face ceiling powered false 5832 oak_button facing east face ceiling powered true 5833 oak_button facing east face ceiling powered false 5834 spruce_button facing north face floor powered true 5835 spruce_button facing north face floor powered false 5836 spruce_button facing south face floor powered true 5837 spruce_button facing south face floor powered false 5838 spruce_button facing west face floor powered true 5839 spruce_button facing west face floor powered false 5840 spruce_button facing east face floor powered true 5841 spruce_button facing east face floor powered false 5842 spruce_button facing north face wall powered true 5843 spruce_button facing north face wall powered false 5844 spruce_button facing south face wall powered true 5845 spruce_button facing south face wall powered false 5846 spruce_button facing west face wall powered true 5847 spruce_button facing west face wall powered false 5848 spruce_button facing east face wall powered true 5849 spruce_button facing east face wall powered false 5850 spruce_button facing north face ceiling powered true 5851 spruce_button facing north face ceiling powered false 5852 spruce_button facing south face ceiling powered true 5853 spruce_button facing south face ceiling powered false 5854 spruce_button facing west face ceiling powered true 5855 spruce_button facing west face ceiling powered false 5856 spruce_button facing east face ceiling powered true 5857 spruce_button facing east face ceiling powered false 5858 birch_button facing north face floor powered true 5859 birch_button facing north face floor powered false 5860 birch_button facing south face floor powered true 5861 birch_button facing south face floor powered false 5862 birch_button facing west face floor powered true 5863 birch_button facing west face floor powered false 5864 birch_button facing east face floor powered true 5865 birch_button facing east face floor powered false 5866 birch_button facing north face wall powered true 5867 birch_button facing north face wall powered false 5868 birch_button facing south face wall powered true 5869 birch_button facing south face wall powered false 5870 birch_button facing west face wall powered true 5871 birch_button facing west face wall powered false 5872 birch_button facing east face wall powered true 5873 birch_button facing east face wall powered false 5874 birch_button facing north face ceiling powered true 5875 birch_button facing north face ceiling powered false 5876 birch_button facing south face ceiling powered true 5877 birch_button facing south face ceiling powered false 5878 birch_button facing west face ceiling powered true 5879 birch_button facing west face ceiling powered false 5880 birch_button facing east face ceiling powered true 5881 birch_button facing east face ceiling powered false 5882 jungle_button facing north face floor powered true 5883 jungle_button facing north face floor powered false 5884 jungle_button facing south face floor powered true 5885 jungle_button facing south face floor powered false 5886 jungle_button facing west face floor powered true 5887 jungle_button facing west face floor powered false 5888 jungle_button facing east face floor powered true 5889 jungle_button facing east face floor powered false 5890 jungle_button facing north face wall powered true 5891 jungle_button facing north face wall powered false 5892 jungle_button facing south face wall powered true 5893 jungle_button facing south face wall powered false 5894 jungle_button facing west face wall powered true 5895 jungle_button facing west face wall powered false 5896 jungle_button facing east face wall powered true 5897 jungle_button facing east face wall powered false 5898 jungle_button facing north face ceiling powered true 5899 jungle_button facing north face ceiling powered false 5900 jungle_button facing south face ceiling powered true 5901 jungle_button facing south face ceiling powered false 5902 jungle_button facing west face ceiling powered true 5903 jungle_button facing west face ceiling powered false 5904 jungle_button facing east face ceiling powered true 5905 jungle_button facing east face ceiling powered false 5906 acacia_button facing north face floor powered true 5907 acacia_button facing north face floor powered false 5908 acacia_button facing south face floor powered true 5909 acacia_button facing south face floor powered false 5910 acacia_button facing west face floor powered true 5911 acacia_button facing west face floor powered false 5912 acacia_button facing east face floor powered true 5913 acacia_button facing east face floor powered false 5914 acacia_button facing north face wall powered true 5915 acacia_button facing north face wall powered false 5916 acacia_button facing south face wall powered true 5917 acacia_button facing south face wall powered false 5918 acacia_button facing west face wall powered true 5919 acacia_button facing west face wall powered false 5920 acacia_button facing east face wall powered true 5921 acacia_button facing east face wall powered false 5922 acacia_button facing north face ceiling powered true 5923 acacia_button facing north face ceiling powered false 5924 acacia_button facing south face ceiling powered true 5925 acacia_button facing south face ceiling powered false 5926 acacia_button facing west face ceiling powered true 5927 acacia_button facing west face ceiling powered false 5928 acacia_button facing east face ceiling powered true 5929 acacia_button facing east face ceiling powered false 5930 dark_oak_button facing north face floor powered true 5931 dark_oak_button facing north face floor powered false 5932 dark_oak_button facing south face floor powered true 5933 dark_oak_button facing south face floor powered false 5934 dark_oak_button facing west face floor powered true 5935 dark_oak_button facing west face floor powered false 5936 dark_oak_button facing east face floor powered true 5937 dark_oak_button facing east face floor powered false 5938 dark_oak_button facing north face wall powered true 5939 dark_oak_button facing north face wall powered false 5940 dark_oak_button facing south face wall powered true 5941 dark_oak_button facing south face wall powered false 5942 dark_oak_button facing west face wall powered true 5943 dark_oak_button facing west face wall powered false 5944 dark_oak_button facing east face wall powered true 5945 dark_oak_button facing east face wall powered false 5946 dark_oak_button facing north face ceiling powered true 5947 dark_oak_button facing north face ceiling powered false 5948 dark_oak_button facing south face ceiling powered true 5949 dark_oak_button facing south face ceiling powered false 5950 dark_oak_button facing west face ceiling powered true 5951 dark_oak_button facing west face ceiling powered false 5952 dark_oak_button facing east face ceiling powered true 5953 dark_oak_button facing east face ceiling powered false 5954 skeleton_skull rotation 0 5955 skeleton_skull rotation 1 5956 skeleton_skull rotation 2 5957 skeleton_skull rotation 3 5958 skeleton_skull rotation 4 5959 skeleton_skull rotation 5 5960 skeleton_skull rotation 6 5961 skeleton_skull rotation 7 5962 skeleton_skull rotation 8 5963 skeleton_skull rotation 9 5964 skeleton_skull rotation 10 5965 skeleton_skull rotation 11 5966 skeleton_skull rotation 12 5967 skeleton_skull rotation 13 5968 skeleton_skull rotation 14 5969 skeleton_skull rotation 15 5970 skeleton_wall_skull facing north 5971 skeleton_wall_skull facing south 5972 skeleton_wall_skull facing west 5973 skeleton_wall_skull facing east 5974 wither_skeleton_skull rotation 0 5975 wither_skeleton_skull rotation 1 5976 wither_skeleton_skull rotation 2 5977 wither_skeleton_skull rotation 3 5978 wither_skeleton_skull rotation 4 5979 wither_skeleton_skull rotation 5 5980 wither_skeleton_skull rotation 6 5981 wither_skeleton_skull rotation 7 5982 wither_skeleton_skull rotation 8 5983 wither_skeleton_skull rotation 9 5984 wither_skeleton_skull rotation 10 5985 wither_skeleton_skull rotation 11 5986 wither_skeleton_skull rotation 12 5987 wither_skeleton_skull rotation 13 5988 wither_skeleton_skull rotation 14 5989 wither_skeleton_skull rotation 15 5990 wither_skeleton_wall_skull facing north 5991 wither_skeleton_wall_skull facing south 5992 wither_skeleton_wall_skull facing west 5993 wither_skeleton_wall_skull facing east 5994 zombie_head rotation 0 5995 zombie_head rotation 1 5996 zombie_head rotation 2 5997 zombie_head rotation 3 5998 zombie_head rotation 4 5999 zombie_head rotation 5 6000 zombie_head rotation 6 6001 zombie_head rotation 7 6002 zombie_head rotation 8 6003 zombie_head rotation 9 6004 zombie_head rotation 10 6005 zombie_head rotation 11 6006 zombie_head rotation 12 6007 zombie_head rotation 13 6008 zombie_head rotation 14 6009 zombie_head rotation 15 6010 zombie_wall_head facing north 6011 zombie_wall_head facing south 6012 zombie_wall_head facing west 6013 zombie_wall_head facing east 6014 player_head rotation 0 6015 player_head rotation 1 6016 player_head rotation 2 6017 player_head rotation 3 6018 player_head rotation 4 6019 player_head rotation 5 6020 player_head rotation 6 6021 player_head rotation 7 6022 player_head rotation 8 6023 player_head rotation 9 6024 player_head rotation 10 6025 player_head rotation 11 6026 player_head rotation 12 6027 player_head rotation 13 6028 player_head rotation 14 6029 player_head rotation 15 6030 player_wall_head facing north 6031 player_wall_head facing south 6032 player_wall_head facing west 6033 player_wall_head facing east 6034 creeper_head rotation 0 6035 creeper_head rotation 1 6036 creeper_head rotation 2 6037 creeper_head rotation 3 6038 creeper_head rotation 4 6039 creeper_head rotation 5 6040 creeper_head rotation 6 6041 creeper_head rotation 7 6042 creeper_head rotation 8 6043 creeper_head rotation 9 6044 creeper_head rotation 10 6045 creeper_head rotation 11 6046 creeper_head rotation 12 6047 creeper_head rotation 13 6048 creeper_head rotation 14 6049 creeper_head rotation 15 6050 creeper_wall_head facing north 6051 creeper_wall_head facing south 6052 creeper_wall_head facing west 6053 creeper_wall_head facing east 6054 dragon_head rotation 0 6055 dragon_head rotation 1 6056 dragon_head rotation 2 6057 dragon_head rotation 3 6058 dragon_head rotation 4 6059 dragon_head rotation 5 6060 dragon_head rotation 6 6061 dragon_head rotation 7 6062 dragon_head rotation 8 6063 dragon_head rotation 9 6064 dragon_head rotation 10 6065 dragon_head rotation 11 6066 dragon_head rotation 12 6067 dragon_head rotation 13 6068 dragon_head rotation 14 6069 dragon_head rotation 15 6070 dragon_wall_head facing north 6071 dragon_wall_head facing south 6072 dragon_wall_head facing west 6073 dragon_wall_head facing east 6074 anvil facing north 6075 anvil facing south 6076 anvil facing west 6077 anvil facing east 6078 chipped_anvil facing north 6079 chipped_anvil facing south 6080 chipped_anvil facing west 6081 chipped_anvil facing east 6082 damaged_anvil facing north 6083 damaged_anvil facing south 6084 damaged_anvil facing west 6085 damaged_anvil facing east 6086 trapped_chest facing north waterlogged true type single 6087 trapped_chest facing north waterlogged false type single 6088 trapped_chest facing north waterlogged true type left 6089 trapped_chest facing north waterlogged false type left 6090 trapped_chest facing north waterlogged true type right 6091 trapped_chest facing north waterlogged false type right 6092 trapped_chest facing south waterlogged true type single 6093 trapped_chest facing south waterlogged false type single 6094 trapped_chest facing south waterlogged true type left 6095 trapped_chest facing south waterlogged false type left 6096 trapped_chest facing south waterlogged true type right 6097 trapped_chest facing south waterlogged false type right 6098 trapped_chest facing west waterlogged true type single 6099 trapped_chest facing west waterlogged false type single 6100 trapped_chest facing west waterlogged true type left 6101 trapped_chest facing west waterlogged false type left 6102 trapped_chest facing west waterlogged true type right 6103 trapped_chest facing west waterlogged false type right 6104 trapped_chest facing east waterlogged true type single 6105 trapped_chest facing east waterlogged false type single 6106 trapped_chest facing east waterlogged true type left 6107 trapped_chest facing east waterlogged false type left 6108 trapped_chest facing east waterlogged true type right 6109 trapped_chest facing east waterlogged false type right 6110 light_weighted_pressure_plate power 0 6111 light_weighted_pressure_plate power 1 6112 light_weighted_pressure_plate power 2 6113 light_weighted_pressure_plate power 3 6114 light_weighted_pressure_plate power 4 6115 light_weighted_pressure_plate power 5 6116 light_weighted_pressure_plate power 6 6117 light_weighted_pressure_plate power 7 6118 light_weighted_pressure_plate power 8 6119 light_weighted_pressure_plate power 9 6120 light_weighted_pressure_plate power 10 6121 light_weighted_pressure_plate power 11 6122 light_weighted_pressure_plate power 12 6123 light_weighted_pressure_plate power 13 6124 light_weighted_pressure_plate power 14 6125 light_weighted_pressure_plate power 15 6126 heavy_weighted_pressure_plate power 0 6127 heavy_weighted_pressure_plate power 1 6128 heavy_weighted_pressure_plate power 2 6129 heavy_weighted_pressure_plate power 3 6130 heavy_weighted_pressure_plate power 4 6131 heavy_weighted_pressure_plate power 5 6132 heavy_weighted_pressure_plate power 6 6133 heavy_weighted_pressure_plate power 7 6134 heavy_weighted_pressure_plate power 8 6135 heavy_weighted_pressure_plate power 9 6136 heavy_weighted_pressure_plate power 10 6137 heavy_weighted_pressure_plate power 11 6138 heavy_weighted_pressure_plate power 12 6139 heavy_weighted_pressure_plate power 13 6140 heavy_weighted_pressure_plate power 14 6141 heavy_weighted_pressure_plate power 15 6142 comparator facing north mode compare powered true 6143 comparator facing north mode compare powered false 6144 comparator facing north mode subtract powered true 6145 comparator facing north mode subtract powered false 6146 comparator facing south mode compare powered true 6147 comparator facing south mode compare powered false 6148 comparator facing south mode subtract powered true 6149 comparator facing south mode subtract powered false 6150 comparator facing west mode compare powered true 6151 comparator facing west mode compare powered false 6152 comparator facing west mode subtract powered true 6153 comparator facing west mode subtract powered false 6154 comparator facing east mode compare powered true 6155 comparator facing east mode compare powered false 6156 comparator facing east mode subtract powered true 6157 comparator facing east mode subtract powered false 6158 daylight_detector inverted true power 0 6159 daylight_detector inverted true power 1 6160 daylight_detector inverted true power 2 6161 daylight_detector inverted true power 3 6162 daylight_detector inverted true power 4 6163 daylight_detector inverted true power 5 6164 daylight_detector inverted true power 6 6165 daylight_detector inverted true power 7 6166 daylight_detector inverted true power 8 6167 daylight_detector inverted true power 9 6168 daylight_detector inverted true power 10 6169 daylight_detector inverted true power 11 6170 daylight_detector inverted true power 12 6171 daylight_detector inverted true power 13 6172 daylight_detector inverted true power 14 6173 daylight_detector inverted true power 15 6174 daylight_detector inverted false power 0 6175 daylight_detector inverted false power 1 6176 daylight_detector inverted false power 2 6177 daylight_detector inverted false power 3 6178 daylight_detector inverted false power 4 6179 daylight_detector inverted false power 5 6180 daylight_detector inverted false power 6 6181 daylight_detector inverted false power 7 6182 daylight_detector inverted false power 8 6183 daylight_detector inverted false power 9 6184 daylight_detector inverted false power 10 6185 daylight_detector inverted false power 11 6186 daylight_detector inverted false power 12 6187 daylight_detector inverted false power 13 6188 daylight_detector inverted false power 14 6189 daylight_detector inverted false power 15 6190 redstone_block 6191 nether_quartz_ore 6192 hopper facing down enabled true 6193 hopper facing north enabled true 6194 hopper facing south enabled true 6195 hopper facing west enabled true 6196 hopper facing east enabled true 6197 hopper facing down enabled false 6198 hopper facing north enabled false 6199 hopper facing south enabled false 6200 hopper facing west enabled false 6201 hopper facing east enabled false 6202 quartz_block 6203 chiseled_quartz_block 6204 quartz_pillar axis x 6205 quartz_pillar axis y 6206 quartz_pillar axis z 6207 quartz_stairs facing north waterlogged true shape straight half top 6208 quartz_stairs facing north waterlogged false shape straight half top 6209 quartz_stairs facing north waterlogged true shape inner_left half top 6210 quartz_stairs facing north waterlogged false shape inner_left half top 6211 quartz_stairs facing north waterlogged true shape inner_right half top 6212 quartz_stairs facing north waterlogged false shape inner_right half top 6213 quartz_stairs facing north waterlogged true shape outer_left half top 6214 quartz_stairs facing north waterlogged false shape outer_left half top 6215 quartz_stairs facing north waterlogged true shape outer_right half top 6216 quartz_stairs facing north waterlogged false shape outer_right half top 6217 quartz_stairs facing north waterlogged true shape straight half bottom 6218 quartz_stairs facing north waterlogged false shape straight half bottom 6219 quartz_stairs facing north waterlogged true shape inner_left half bottom 6220 quartz_stairs facing north waterlogged false shape inner_left half bottom 6221 quartz_stairs facing north waterlogged true shape inner_right half bottom 6222 quartz_stairs facing north waterlogged false shape inner_right half bottom 6223 quartz_stairs facing north waterlogged true shape outer_left half bottom 6224 quartz_stairs facing north waterlogged false shape outer_left half bottom 6225 quartz_stairs facing north waterlogged true shape outer_right half bottom 6226 quartz_stairs facing north waterlogged false shape outer_right half bottom 6227 quartz_stairs facing south waterlogged true shape straight half top 6228 quartz_stairs facing south waterlogged false shape straight half top 6229 quartz_stairs facing south waterlogged true shape inner_left half top 6230 quartz_stairs facing south waterlogged false shape inner_left half top 6231 quartz_stairs facing south waterlogged true shape inner_right half top 6232 quartz_stairs facing south waterlogged false shape inner_right half top 6233 quartz_stairs facing south waterlogged true shape outer_left half top 6234 quartz_stairs facing south waterlogged false shape outer_left half top 6235 quartz_stairs facing south waterlogged true shape outer_right half top 6236 quartz_stairs facing south waterlogged false shape outer_right half top 6237 quartz_stairs facing south waterlogged true shape straight half bottom 6238 quartz_stairs facing south waterlogged false shape straight half bottom 6239 quartz_stairs facing south waterlogged true shape inner_left half bottom 6240 quartz_stairs facing south waterlogged false shape inner_left half bottom 6241 quartz_stairs facing south waterlogged true shape inner_right half bottom 6242 quartz_stairs facing south waterlogged false shape inner_right half bottom 6243 quartz_stairs facing south waterlogged true shape outer_left half bottom 6244 quartz_stairs facing south waterlogged false shape outer_left half bottom 6245 quartz_stairs facing south waterlogged true shape outer_right half bottom 6246 quartz_stairs facing south waterlogged false shape outer_right half bottom 6247 quartz_stairs facing west waterlogged true shape straight half top 6248 quartz_stairs facing west waterlogged false shape straight half top 6249 quartz_stairs facing west waterlogged true shape inner_left half top 6250 quartz_stairs facing west waterlogged false shape inner_left half top 6251 quartz_stairs facing west waterlogged true shape inner_right half top 6252 quartz_stairs facing west waterlogged false shape inner_right half top 6253 quartz_stairs facing west waterlogged true shape outer_left half top 6254 quartz_stairs facing west waterlogged false shape outer_left half top 6255 quartz_stairs facing west waterlogged true shape outer_right half top 6256 quartz_stairs facing west waterlogged false shape outer_right half top 6257 quartz_stairs facing west waterlogged true shape straight half bottom 6258 quartz_stairs facing west waterlogged false shape straight half bottom 6259 quartz_stairs facing west waterlogged true shape inner_left half bottom 6260 quartz_stairs facing west waterlogged false shape inner_left half bottom 6261 quartz_stairs facing west waterlogged true shape inner_right half bottom 6262 quartz_stairs facing west waterlogged false shape inner_right half bottom 6263 quartz_stairs facing west waterlogged true shape outer_left half bottom 6264 quartz_stairs facing west waterlogged false shape outer_left half bottom 6265 quartz_stairs facing west waterlogged true shape outer_right half bottom 6266 quartz_stairs facing west waterlogged false shape outer_right half bottom 6267 quartz_stairs facing east waterlogged true shape straight half top 6268 quartz_stairs facing east waterlogged false shape straight half top 6269 quartz_stairs facing east waterlogged true shape inner_left half top 6270 quartz_stairs facing east waterlogged false shape inner_left half top 6271 quartz_stairs facing east waterlogged true shape inner_right half top 6272 quartz_stairs facing east waterlogged false shape inner_right half top 6273 quartz_stairs facing east waterlogged true shape outer_left half top 6274 quartz_stairs facing east waterlogged false shape outer_left half top 6275 quartz_stairs facing east waterlogged true shape outer_right half top 6276 quartz_stairs facing east waterlogged false shape outer_right half top 6277 quartz_stairs facing east waterlogged true shape straight half bottom 6278 quartz_stairs facing east waterlogged false shape straight half bottom 6279 quartz_stairs facing east waterlogged true shape inner_left half bottom 6280 quartz_stairs facing east waterlogged false shape inner_left half bottom 6281 quartz_stairs facing east waterlogged true shape inner_right half bottom 6282 quartz_stairs facing east waterlogged false shape inner_right half bottom 6283 quartz_stairs facing east waterlogged true shape outer_left half bottom 6284 quartz_stairs facing east waterlogged false shape outer_left half bottom 6285 quartz_stairs facing east waterlogged true shape outer_right half bottom 6286 quartz_stairs facing east waterlogged false shape outer_right half bottom 6287 activator_rail shape north_south powered true 6288 activator_rail shape east_west powered true 6289 activator_rail shape ascending_east powered true 6290 activator_rail shape ascending_west powered true 6291 activator_rail shape ascending_north powered true 6292 activator_rail shape ascending_south powered true 6293 activator_rail shape north_south powered false 6294 activator_rail shape east_west powered false 6295 activator_rail shape ascending_east powered false 6296 activator_rail shape ascending_west powered false 6297 activator_rail shape ascending_north powered false 6298 activator_rail shape ascending_south powered false 6299 dropper facing north triggered true 6300 dropper facing north triggered false 6301 dropper facing east triggered true 6302 dropper facing east triggered false 6303 dropper facing south triggered true 6304 dropper facing south triggered false 6305 dropper facing west triggered true 6306 dropper facing west triggered false 6307 dropper facing up triggered true 6308 dropper facing up triggered false 6309 dropper facing down triggered true 6310 dropper facing down triggered false 6311 white_terracotta 6312 orange_terracotta 6313 magenta_terracotta 6314 light_blue_terracotta 6315 yellow_terracotta 6316 lime_terracotta 6317 pink_terracotta 6318 gray_terracotta 6319 light_gray_terracotta 6320 cyan_terracotta 6321 purple_terracotta 6322 blue_terracotta 6323 brown_terracotta 6324 green_terracotta 6325 red_terracotta 6326 black_terracotta 6327 white_stained_glass_pane waterlogged true south true east true north true west true 6328 white_stained_glass_pane waterlogged true south true east true north true west false 6329 white_stained_glass_pane waterlogged false south true east true north true west true 6330 white_stained_glass_pane waterlogged false south true east true north true west false 6331 white_stained_glass_pane waterlogged true south false east true north true west true 6332 white_stained_glass_pane waterlogged true south false east true north true west false 6333 white_stained_glass_pane waterlogged false south false east true north true west true 6334 white_stained_glass_pane waterlogged false south false east true north true west false 6335 white_stained_glass_pane waterlogged true south true east true north false west true 6336 white_stained_glass_pane waterlogged true south true east true north false west false 6337 white_stained_glass_pane waterlogged false south true east true north false west true 6338 white_stained_glass_pane waterlogged false south true east true north false west false 6339 white_stained_glass_pane waterlogged true south false east true north false west true 6340 white_stained_glass_pane waterlogged true south false east true north false west false 6341 white_stained_glass_pane waterlogged false south false east true north false west true 6342 white_stained_glass_pane waterlogged false south false east true north false west false 6343 white_stained_glass_pane waterlogged true south true east false north true west true 6344 white_stained_glass_pane waterlogged true south true east false north true west false 6345 white_stained_glass_pane waterlogged false south true east false north true west true 6346 white_stained_glass_pane waterlogged false south true east false north true west false 6347 white_stained_glass_pane waterlogged true south false east false north true west true 6348 white_stained_glass_pane waterlogged true south false east false north true west false 6349 white_stained_glass_pane waterlogged false south false east false north true west true 6350 white_stained_glass_pane waterlogged false south false east false north true west false 6351 white_stained_glass_pane waterlogged true south true east false north false west true 6352 white_stained_glass_pane waterlogged true south true east false north false west false 6353 white_stained_glass_pane waterlogged false south true east false north false west true 6354 white_stained_glass_pane waterlogged false south true east false north false west false 6355 white_stained_glass_pane waterlogged true south false east false north false west true 6356 white_stained_glass_pane waterlogged true south false east false north false west false 6357 white_stained_glass_pane waterlogged false south false east false north false west true 6358 white_stained_glass_pane waterlogged false south false east false north false west false 6359 orange_stained_glass_pane waterlogged true south true east true north true west true 6360 orange_stained_glass_pane waterlogged true south true east true north true west false 6361 orange_stained_glass_pane waterlogged false south true east true north true west true 6362 orange_stained_glass_pane waterlogged false south true east true north true west false 6363 orange_stained_glass_pane waterlogged true south false east true north true west true 6364 orange_stained_glass_pane waterlogged true south false east true north true west false 6365 orange_stained_glass_pane waterlogged false south false east true north true west true 6366 orange_stained_glass_pane waterlogged false south false east true north true west false 6367 orange_stained_glass_pane waterlogged true south true east true north false west true 6368 orange_stained_glass_pane waterlogged true south true east true north false west false 6369 orange_stained_glass_pane waterlogged false south true east true north false west true 6370 orange_stained_glass_pane waterlogged false south true east true north false west false 6371 orange_stained_glass_pane waterlogged true south false east true north false west true 6372 orange_stained_glass_pane waterlogged true south false east true north false west false 6373 orange_stained_glass_pane waterlogged false south false east true north false west true 6374 orange_stained_glass_pane waterlogged false south false east true north false west false 6375 orange_stained_glass_pane waterlogged true south true east false north true west true 6376 orange_stained_glass_pane waterlogged true south true east false north true west false 6377 orange_stained_glass_pane waterlogged false south true east false north true west true 6378 orange_stained_glass_pane waterlogged false south true east false north true west false 6379 orange_stained_glass_pane waterlogged true south false east false north true west true 6380 orange_stained_glass_pane waterlogged true south false east false north true west false 6381 orange_stained_glass_pane waterlogged false south false east false north true west true 6382 orange_stained_glass_pane waterlogged false south false east false north true west false 6383 orange_stained_glass_pane waterlogged true south true east false north false west true 6384 orange_stained_glass_pane waterlogged true south true east false north false west false 6385 orange_stained_glass_pane waterlogged false south true east false north false west true 6386 orange_stained_glass_pane waterlogged false south true east false north false west false 6387 orange_stained_glass_pane waterlogged true south false east false north false west true 6388 orange_stained_glass_pane waterlogged true south false east false north false west false 6389 orange_stained_glass_pane waterlogged false south false east false north false west true 6390 orange_stained_glass_pane waterlogged false south false east false north false west false 6391 magenta_stained_glass_pane waterlogged true south true east true north true west true 6392 magenta_stained_glass_pane waterlogged true south true east true north true west false 6393 magenta_stained_glass_pane waterlogged false south true east true north true west true 6394 magenta_stained_glass_pane waterlogged false south true east true north true west false 6395 magenta_stained_glass_pane waterlogged true south false east true north true west true 6396 magenta_stained_glass_pane waterlogged true south false east true north true west false 6397 magenta_stained_glass_pane waterlogged false south false east true north true west true 6398 magenta_stained_glass_pane waterlogged false south false east true north true west false 6399 magenta_stained_glass_pane waterlogged true south true east true north false west true 6400 magenta_stained_glass_pane waterlogged true south true east true north false west false 6401 magenta_stained_glass_pane waterlogged false south true east true north false west true 6402 magenta_stained_glass_pane waterlogged false south true east true north false west false 6403 magenta_stained_glass_pane waterlogged true south false east true north false west true 6404 magenta_stained_glass_pane waterlogged true south false east true north false west false 6405 magenta_stained_glass_pane waterlogged false south false east true north false west true 6406 magenta_stained_glass_pane waterlogged false south false east true north false west false 6407 magenta_stained_glass_pane waterlogged true south true east false north true west true 6408 magenta_stained_glass_pane waterlogged true south true east false north true west false 6409 magenta_stained_glass_pane waterlogged false south true east false north true west true 6410 magenta_stained_glass_pane waterlogged false south true east false north true west false 6411 magenta_stained_glass_pane waterlogged true south false east false north true west true 6412 magenta_stained_glass_pane waterlogged true south false east false north true west false 6413 magenta_stained_glass_pane waterlogged false south false east false north true west true 6414 magenta_stained_glass_pane waterlogged false south false east false north true west false 6415 magenta_stained_glass_pane waterlogged true south true east false north false west true 6416 magenta_stained_glass_pane waterlogged true south true east false north false west false 6417 magenta_stained_glass_pane waterlogged false south true east false north false west true 6418 magenta_stained_glass_pane waterlogged false south true east false north false west false 6419 magenta_stained_glass_pane waterlogged true south false east false north false west true 6420 magenta_stained_glass_pane waterlogged true south false east false north false west false 6421 magenta_stained_glass_pane waterlogged false south false east false north false west true 6422 magenta_stained_glass_pane waterlogged false south false east false north false west false 6423 light_blue_stained_glass_pane waterlogged true south true east true north true west true 6424 light_blue_stained_glass_pane waterlogged true south true east true north true west false 6425 light_blue_stained_glass_pane waterlogged false south true east true north true west true 6426 light_blue_stained_glass_pane waterlogged false south true east true north true west false 6427 light_blue_stained_glass_pane waterlogged true south false east true north true west true 6428 light_blue_stained_glass_pane waterlogged true south false east true north true west false 6429 light_blue_stained_glass_pane waterlogged false south false east true north true west true 6430 light_blue_stained_glass_pane waterlogged false south false east true north true west false 6431 light_blue_stained_glass_pane waterlogged true south true east true north false west true 6432 light_blue_stained_glass_pane waterlogged true south true east true north false west false 6433 light_blue_stained_glass_pane waterlogged false south true east true north false west true 6434 light_blue_stained_glass_pane waterlogged false south true east true north false west false 6435 light_blue_stained_glass_pane waterlogged true south false east true north false west true 6436 light_blue_stained_glass_pane waterlogged true south false east true north false west false 6437 light_blue_stained_glass_pane waterlogged false south false east true north false west true 6438 light_blue_stained_glass_pane waterlogged false south false east true north false west false 6439 light_blue_stained_glass_pane waterlogged true south true east false north true west true 6440 light_blue_stained_glass_pane waterlogged true south true east false north true west false 6441 light_blue_stained_glass_pane waterlogged false south true east false north true west true 6442 light_blue_stained_glass_pane waterlogged false south true east false north true west false 6443 light_blue_stained_glass_pane waterlogged true south false east false north true west true 6444 light_blue_stained_glass_pane waterlogged true south false east false north true west false 6445 light_blue_stained_glass_pane waterlogged false south false east false north true west true 6446 light_blue_stained_glass_pane waterlogged false south false east false north true west false 6447 light_blue_stained_glass_pane waterlogged true south true east false north false west true 6448 light_blue_stained_glass_pane waterlogged true south true east false north false west false 6449 light_blue_stained_glass_pane waterlogged false south true east false north false west true 6450 light_blue_stained_glass_pane waterlogged false south true east false north false west false 6451 light_blue_stained_glass_pane waterlogged true south false east false north false west true 6452 light_blue_stained_glass_pane waterlogged true south false east false north false west false 6453 light_blue_stained_glass_pane waterlogged false south false east false north false west true 6454 light_blue_stained_glass_pane waterlogged false south false east false north false west false 6455 yellow_stained_glass_pane waterlogged true south true east true north true west true 6456 yellow_stained_glass_pane waterlogged true south true east true north true west false 6457 yellow_stained_glass_pane waterlogged false south true east true north true west true 6458 yellow_stained_glass_pane waterlogged false south true east true north true west false 6459 yellow_stained_glass_pane waterlogged true south false east true north true west true 6460 yellow_stained_glass_pane waterlogged true south false east true north true west false 6461 yellow_stained_glass_pane waterlogged false south false east true north true west true 6462 yellow_stained_glass_pane waterlogged false south false east true north true west false 6463 yellow_stained_glass_pane waterlogged true south true east true north false west true 6464 yellow_stained_glass_pane waterlogged true south true east true north false west false 6465 yellow_stained_glass_pane waterlogged false south true east true north false west true 6466 yellow_stained_glass_pane waterlogged false south true east true north false west false 6467 yellow_stained_glass_pane waterlogged true south false east true north false west true 6468 yellow_stained_glass_pane waterlogged true south false east true north false west false 6469 yellow_stained_glass_pane waterlogged false south false east true north false west true 6470 yellow_stained_glass_pane waterlogged false south false east true north false west false 6471 yellow_stained_glass_pane waterlogged true south true east false north true west true 6472 yellow_stained_glass_pane waterlogged true south true east false north true west false 6473 yellow_stained_glass_pane waterlogged false south true east false north true west true 6474 yellow_stained_glass_pane waterlogged false south true east false north true west false 6475 yellow_stained_glass_pane waterlogged true south false east false north true west true 6476 yellow_stained_glass_pane waterlogged true south false east false north true west false 6477 yellow_stained_glass_pane waterlogged false south false east false north true west true 6478 yellow_stained_glass_pane waterlogged false south false east false north true west false 6479 yellow_stained_glass_pane waterlogged true south true east false north false west true 6480 yellow_stained_glass_pane waterlogged true south true east false north false west false 6481 yellow_stained_glass_pane waterlogged false south true east false north false west true 6482 yellow_stained_glass_pane waterlogged false south true east false north false west false 6483 yellow_stained_glass_pane waterlogged true south false east false north false west true 6484 yellow_stained_glass_pane waterlogged true south false east false north false west false 6485 yellow_stained_glass_pane waterlogged false south false east false north false west true 6486 yellow_stained_glass_pane waterlogged false south false east false north false west false 6487 lime_stained_glass_pane waterlogged true south true east true north true west true 6488 lime_stained_glass_pane waterlogged true south true east true north true west false 6489 lime_stained_glass_pane waterlogged false south true east true north true west true 6490 lime_stained_glass_pane waterlogged false south true east true north true west false 6491 lime_stained_glass_pane waterlogged true south false east true north true west true 6492 lime_stained_glass_pane waterlogged true south false east true north true west false 6493 lime_stained_glass_pane waterlogged false south false east true north true west true 6494 lime_stained_glass_pane waterlogged false south false east true north true west false 6495 lime_stained_glass_pane waterlogged true south true east true north false west true 6496 lime_stained_glass_pane waterlogged true south true east true north false west false 6497 lime_stained_glass_pane waterlogged false south true east true north false west true 6498 lime_stained_glass_pane waterlogged false south true east true north false west false 6499 lime_stained_glass_pane waterlogged true south false east true north false west true 6500 lime_stained_glass_pane waterlogged true south false east true north false west false 6501 lime_stained_glass_pane waterlogged false south false east true north false west true 6502 lime_stained_glass_pane waterlogged false south false east true north false west false 6503 lime_stained_glass_pane waterlogged true south true east false north true west true 6504 lime_stained_glass_pane waterlogged true south true east false north true west false 6505 lime_stained_glass_pane waterlogged false south true east false north true west true 6506 lime_stained_glass_pane waterlogged false south true east false north true west false 6507 lime_stained_glass_pane waterlogged true south false east false north true west true 6508 lime_stained_glass_pane waterlogged true south false east false north true west false 6509 lime_stained_glass_pane waterlogged false south false east false north true west true 6510 lime_stained_glass_pane waterlogged false south false east false north true west false 6511 lime_stained_glass_pane waterlogged true south true east false north false west true 6512 lime_stained_glass_pane waterlogged true south true east false north false west false 6513 lime_stained_glass_pane waterlogged false south true east false north false west true 6514 lime_stained_glass_pane waterlogged false south true east false north false west false 6515 lime_stained_glass_pane waterlogged true south false east false north false west true 6516 lime_stained_glass_pane waterlogged true south false east false north false west false 6517 lime_stained_glass_pane waterlogged false south false east false north false west true 6518 lime_stained_glass_pane waterlogged false south false east false north false west false 6519 pink_stained_glass_pane waterlogged true south true east true north true west true 6520 pink_stained_glass_pane waterlogged true south true east true north true west false 6521 pink_stained_glass_pane waterlogged false south true east true north true west true 6522 pink_stained_glass_pane waterlogged false south true east true north true west false 6523 pink_stained_glass_pane waterlogged true south false east true north true west true 6524 pink_stained_glass_pane waterlogged true south false east true north true west false 6525 pink_stained_glass_pane waterlogged false south false east true north true west true 6526 pink_stained_glass_pane waterlogged false south false east true north true west false 6527 pink_stained_glass_pane waterlogged true south true east true north false west true 6528 pink_stained_glass_pane waterlogged true south true east true north false west false 6529 pink_stained_glass_pane waterlogged false south true east true north false west true 6530 pink_stained_glass_pane waterlogged false south true east true north false west false 6531 pink_stained_glass_pane waterlogged true south false east true north false west true 6532 pink_stained_glass_pane waterlogged true south false east true north false west false 6533 pink_stained_glass_pane waterlogged false south false east true north false west true 6534 pink_stained_glass_pane waterlogged false south false east true north false west false 6535 pink_stained_glass_pane waterlogged true south true east false north true west true 6536 pink_stained_glass_pane waterlogged true south true east false north true west false 6537 pink_stained_glass_pane waterlogged false south true east false north true west true 6538 pink_stained_glass_pane waterlogged false south true east false north true west false 6539 pink_stained_glass_pane waterlogged true south false east false north true west true 6540 pink_stained_glass_pane waterlogged true south false east false north true west false 6541 pink_stained_glass_pane waterlogged false south false east false north true west true 6542 pink_stained_glass_pane waterlogged false south false east false north true west false 6543 pink_stained_glass_pane waterlogged true south true east false north false west true 6544 pink_stained_glass_pane waterlogged true south true east false north false west false 6545 pink_stained_glass_pane waterlogged false south true east false north false west true 6546 pink_stained_glass_pane waterlogged false south true east false north false west false 6547 pink_stained_glass_pane waterlogged true south false east false north false west true 6548 pink_stained_glass_pane waterlogged true south false east false north false west false 6549 pink_stained_glass_pane waterlogged false south false east false north false west true 6550 pink_stained_glass_pane waterlogged false south false east false north false west false 6551 gray_stained_glass_pane waterlogged true south true east true north true west true 6552 gray_stained_glass_pane waterlogged true south true east true north true west false 6553 gray_stained_glass_pane waterlogged false south true east true north true west true 6554 gray_stained_glass_pane waterlogged false south true east true north true west false 6555 gray_stained_glass_pane waterlogged true south false east true north true west true 6556 gray_stained_glass_pane waterlogged true south false east true north true west false 6557 gray_stained_glass_pane waterlogged false south false east true north true west true 6558 gray_stained_glass_pane waterlogged false south false east true north true west false 6559 gray_stained_glass_pane waterlogged true south true east true north false west true 6560 gray_stained_glass_pane waterlogged true south true east true north false west false 6561 gray_stained_glass_pane waterlogged false south true east true north false west true 6562 gray_stained_glass_pane waterlogged false south true east true north false west false 6563 gray_stained_glass_pane waterlogged true south false east true north false west true 6564 gray_stained_glass_pane waterlogged true south false east true north false west false 6565 gray_stained_glass_pane waterlogged false south false east true north false west true 6566 gray_stained_glass_pane waterlogged false south false east true north false west false 6567 gray_stained_glass_pane waterlogged true south true east false north true west true 6568 gray_stained_glass_pane waterlogged true south true east false north true west false 6569 gray_stained_glass_pane waterlogged false south true east false north true west true 6570 gray_stained_glass_pane waterlogged false south true east false north true west false 6571 gray_stained_glass_pane waterlogged true south false east false north true west true 6572 gray_stained_glass_pane waterlogged true south false east false north true west false 6573 gray_stained_glass_pane waterlogged false south false east false north true west true 6574 gray_stained_glass_pane waterlogged false south false east false north true west false 6575 gray_stained_glass_pane waterlogged true south true east false north false west true 6576 gray_stained_glass_pane waterlogged true south true east false north false west false 6577 gray_stained_glass_pane waterlogged false south true east false north false west true 6578 gray_stained_glass_pane waterlogged false south true east false north false west false 6579 gray_stained_glass_pane waterlogged true south false east false north false west true 6580 gray_stained_glass_pane waterlogged true south false east false north false west false 6581 gray_stained_glass_pane waterlogged false south false east false north false west true 6582 gray_stained_glass_pane waterlogged false south false east false north false west false 6583 light_gray_stained_glass_pane waterlogged true south true east true north true west true 6584 light_gray_stained_glass_pane waterlogged true south true east true north true west false 6585 light_gray_stained_glass_pane waterlogged false south true east true north true west true 6586 light_gray_stained_glass_pane waterlogged false south true east true north true west false 6587 light_gray_stained_glass_pane waterlogged true south false east true north true west true 6588 light_gray_stained_glass_pane waterlogged true south false east true north true west false 6589 light_gray_stained_glass_pane waterlogged false south false east true north true west true 6590 light_gray_stained_glass_pane waterlogged false south false east true north true west false 6591 light_gray_stained_glass_pane waterlogged true south true east true north false west true 6592 light_gray_stained_glass_pane waterlogged true south true east true north false west false 6593 light_gray_stained_glass_pane waterlogged false south true east true north false west true 6594 light_gray_stained_glass_pane waterlogged false south true east true north false west false 6595 light_gray_stained_glass_pane waterlogged true south false east true north false west true 6596 light_gray_stained_glass_pane waterlogged true south false east true north false west false 6597 light_gray_stained_glass_pane waterlogged false south false east true north false west true 6598 light_gray_stained_glass_pane waterlogged false south false east true north false west false 6599 light_gray_stained_glass_pane waterlogged true south true east false north true west true 6600 light_gray_stained_glass_pane waterlogged true south true east false north true west false 6601 light_gray_stained_glass_pane waterlogged false south true east false north true west true 6602 light_gray_stained_glass_pane waterlogged false south true east false north true west false 6603 light_gray_stained_glass_pane waterlogged true south false east false north true west true 6604 light_gray_stained_glass_pane waterlogged true south false east false north true west false 6605 light_gray_stained_glass_pane waterlogged false south false east false north true west true 6606 light_gray_stained_glass_pane waterlogged false south false east false north true west false 6607 light_gray_stained_glass_pane waterlogged true south true east false north false west true 6608 light_gray_stained_glass_pane waterlogged true south true east false north false west false 6609 light_gray_stained_glass_pane waterlogged false south true east false north false west true 6610 light_gray_stained_glass_pane waterlogged false south true east false north false west false 6611 light_gray_stained_glass_pane waterlogged true south false east false north false west true 6612 light_gray_stained_glass_pane waterlogged true south false east false north false west false 6613 light_gray_stained_glass_pane waterlogged false south false east false north false west true 6614 light_gray_stained_glass_pane waterlogged false south false east false north false west false 6615 cyan_stained_glass_pane waterlogged true south true east true north true west true 6616 cyan_stained_glass_pane waterlogged true south true east true north true west false 6617 cyan_stained_glass_pane waterlogged false south true east true north true west true 6618 cyan_stained_glass_pane waterlogged false south true east true north true west false 6619 cyan_stained_glass_pane waterlogged true south false east true north true west true 6620 cyan_stained_glass_pane waterlogged true south false east true north true west false 6621 cyan_stained_glass_pane waterlogged false south false east true north true west true 6622 cyan_stained_glass_pane waterlogged false south false east true north true west false 6623 cyan_stained_glass_pane waterlogged true south true east true north false west true 6624 cyan_stained_glass_pane waterlogged true south true east true north false west false 6625 cyan_stained_glass_pane waterlogged false south true east true north false west true 6626 cyan_stained_glass_pane waterlogged false south true east true north false west false 6627 cyan_stained_glass_pane waterlogged true south false east true north false west true 6628 cyan_stained_glass_pane waterlogged true south false east true north false west false 6629 cyan_stained_glass_pane waterlogged false south false east true north false west true 6630 cyan_stained_glass_pane waterlogged false south false east true north false west false 6631 cyan_stained_glass_pane waterlogged true south true east false north true west true 6632 cyan_stained_glass_pane waterlogged true south true east false north true west false 6633 cyan_stained_glass_pane waterlogged false south true east false north true west true 6634 cyan_stained_glass_pane waterlogged false south true east false north true west false 6635 cyan_stained_glass_pane waterlogged true south false east false north true west true 6636 cyan_stained_glass_pane waterlogged true south false east false north true west false 6637 cyan_stained_glass_pane waterlogged false south false east false north true west true 6638 cyan_stained_glass_pane waterlogged false south false east false north true west false 6639 cyan_stained_glass_pane waterlogged true south true east false north false west true 6640 cyan_stained_glass_pane waterlogged true south true east false north false west false 6641 cyan_stained_glass_pane waterlogged false south true east false north false west true 6642 cyan_stained_glass_pane waterlogged false south true east false north false west false 6643 cyan_stained_glass_pane waterlogged true south false east false north false west true 6644 cyan_stained_glass_pane waterlogged true south false east false north false west false 6645 cyan_stained_glass_pane waterlogged false south false east false north false west true 6646 cyan_stained_glass_pane waterlogged false south false east false north false west false 6647 purple_stained_glass_pane waterlogged true south true east true north true west true 6648 purple_stained_glass_pane waterlogged true south true east true north true west false 6649 purple_stained_glass_pane waterlogged false south true east true north true west true 6650 purple_stained_glass_pane waterlogged false south true east true north true west false 6651 purple_stained_glass_pane waterlogged true south false east true north true west true 6652 purple_stained_glass_pane waterlogged true south false east true north true west false 6653 purple_stained_glass_pane waterlogged false south false east true north true west true 6654 purple_stained_glass_pane waterlogged false south false east true north true west false 6655 purple_stained_glass_pane waterlogged true south true east true north false west true 6656 purple_stained_glass_pane waterlogged true south true east true north false west false 6657 purple_stained_glass_pane waterlogged false south true east true north false west true 6658 purple_stained_glass_pane waterlogged false south true east true north false west false 6659 purple_stained_glass_pane waterlogged true south false east true north false west true 6660 purple_stained_glass_pane waterlogged true south false east true north false west false 6661 purple_stained_glass_pane waterlogged false south false east true north false west true 6662 purple_stained_glass_pane waterlogged false south false east true north false west false 6663 purple_stained_glass_pane waterlogged true south true east false north true west true 6664 purple_stained_glass_pane waterlogged true south true east false north true west false 6665 purple_stained_glass_pane waterlogged false south true east false north true west true 6666 purple_stained_glass_pane waterlogged false south true east false north true west false 6667 purple_stained_glass_pane waterlogged true south false east false north true west true 6668 purple_stained_glass_pane waterlogged true south false east false north true west false 6669 purple_stained_glass_pane waterlogged false south false east false north true west true 6670 purple_stained_glass_pane waterlogged false south false east false north true west false 6671 purple_stained_glass_pane waterlogged true south true east false north false west true 6672 purple_stained_glass_pane waterlogged true south true east false north false west false 6673 purple_stained_glass_pane waterlogged false south true east false north false west true 6674 purple_stained_glass_pane waterlogged false south true east false north false west false 6675 purple_stained_glass_pane waterlogged true south false east false north false west true 6676 purple_stained_glass_pane waterlogged true south false east false north false west false 6677 purple_stained_glass_pane waterlogged false south false east false north false west true 6678 purple_stained_glass_pane waterlogged false south false east false north false west false 6679 blue_stained_glass_pane waterlogged true south true east true north true west true 6680 blue_stained_glass_pane waterlogged true south true east true north true west false 6681 blue_stained_glass_pane waterlogged false south true east true north true west true 6682 blue_stained_glass_pane waterlogged false south true east true north true west false 6683 blue_stained_glass_pane waterlogged true south false east true north true west true 6684 blue_stained_glass_pane waterlogged true south false east true north true west false 6685 blue_stained_glass_pane waterlogged false south false east true north true west true 6686 blue_stained_glass_pane waterlogged false south false east true north true west false 6687 blue_stained_glass_pane waterlogged true south true east true north false west true 6688 blue_stained_glass_pane waterlogged true south true east true north false west false 6689 blue_stained_glass_pane waterlogged false south true east true north false west true 6690 blue_stained_glass_pane waterlogged false south true east true north false west false 6691 blue_stained_glass_pane waterlogged true south false east true north false west true 6692 blue_stained_glass_pane waterlogged true south false east true north false west false 6693 blue_stained_glass_pane waterlogged false south false east true north false west true 6694 blue_stained_glass_pane waterlogged false south false east true north false west false 6695 blue_stained_glass_pane waterlogged true south true east false north true west true 6696 blue_stained_glass_pane waterlogged true south true east false north true west false 6697 blue_stained_glass_pane waterlogged false south true east false north true west true 6698 blue_stained_glass_pane waterlogged false south true east false north true west false 6699 blue_stained_glass_pane waterlogged true south false east false north true west true 6700 blue_stained_glass_pane waterlogged true south false east false north true west false 6701 blue_stained_glass_pane waterlogged false south false east false north true west true 6702 blue_stained_glass_pane waterlogged false south false east false north true west false 6703 blue_stained_glass_pane waterlogged true south true east false north false west true 6704 blue_stained_glass_pane waterlogged true south true east false north false west false 6705 blue_stained_glass_pane waterlogged false south true east false north false west true 6706 blue_stained_glass_pane waterlogged false south true east false north false west false 6707 blue_stained_glass_pane waterlogged true south false east false north false west true 6708 blue_stained_glass_pane waterlogged true south false east false north false west false 6709 blue_stained_glass_pane waterlogged false south false east false north false west true 6710 blue_stained_glass_pane waterlogged false south false east false north false west false 6711 brown_stained_glass_pane waterlogged true south true east true north true west true 6712 brown_stained_glass_pane waterlogged true south true east true north true west false 6713 brown_stained_glass_pane waterlogged false south true east true north true west true 6714 brown_stained_glass_pane waterlogged false south true east true north true west false 6715 brown_stained_glass_pane waterlogged true south false east true north true west true 6716 brown_stained_glass_pane waterlogged true south false east true north true west false 6717 brown_stained_glass_pane waterlogged false south false east true north true west true 6718 brown_stained_glass_pane waterlogged false south false east true north true west false 6719 brown_stained_glass_pane waterlogged true south true east true north false west true 6720 brown_stained_glass_pane waterlogged true south true east true north false west false 6721 brown_stained_glass_pane waterlogged false south true east true north false west true 6722 brown_stained_glass_pane waterlogged false south true east true north false west false 6723 brown_stained_glass_pane waterlogged true south false east true north false west true 6724 brown_stained_glass_pane waterlogged true south false east true north false west false 6725 brown_stained_glass_pane waterlogged false south false east true north false west true 6726 brown_stained_glass_pane waterlogged false south false east true north false west false 6727 brown_stained_glass_pane waterlogged true south true east false north true west true 6728 brown_stained_glass_pane waterlogged true south true east false north true west false 6729 brown_stained_glass_pane waterlogged false south true east false north true west true 6730 brown_stained_glass_pane waterlogged false south true east false north true west false 6731 brown_stained_glass_pane waterlogged true south false east false north true west true 6732 brown_stained_glass_pane waterlogged true south false east false north true west false 6733 brown_stained_glass_pane waterlogged false south false east false north true west true 6734 brown_stained_glass_pane waterlogged false south false east false north true west false 6735 brown_stained_glass_pane waterlogged true south true east false north false west true 6736 brown_stained_glass_pane waterlogged true south true east false north false west false 6737 brown_stained_glass_pane waterlogged false south true east false north false west true 6738 brown_stained_glass_pane waterlogged false south true east false north false west false 6739 brown_stained_glass_pane waterlogged true south false east false north false west true 6740 brown_stained_glass_pane waterlogged true south false east false north false west false 6741 brown_stained_glass_pane waterlogged false south false east false north false west true 6742 brown_stained_glass_pane waterlogged false south false east false north false west false 6743 green_stained_glass_pane waterlogged true south true east true north true west true 6744 green_stained_glass_pane waterlogged true south true east true north true west false 6745 green_stained_glass_pane waterlogged false south true east true north true west true 6746 green_stained_glass_pane waterlogged false south true east true north true west false 6747 green_stained_glass_pane waterlogged true south false east true north true west true 6748 green_stained_glass_pane waterlogged true south false east true north true west false 6749 green_stained_glass_pane waterlogged false south false east true north true west true 6750 green_stained_glass_pane waterlogged false south false east true north true west false 6751 green_stained_glass_pane waterlogged true south true east true north false west true 6752 green_stained_glass_pane waterlogged true south true east true north false west false 6753 green_stained_glass_pane waterlogged false south true east true north false west true 6754 green_stained_glass_pane waterlogged false south true east true north false west false 6755 green_stained_glass_pane waterlogged true south false east true north false west true 6756 green_stained_glass_pane waterlogged true south false east true north false west false 6757 green_stained_glass_pane waterlogged false south false east true north false west true 6758 green_stained_glass_pane waterlogged false south false east true north false west false 6759 green_stained_glass_pane waterlogged true south true east false north true west true 6760 green_stained_glass_pane waterlogged true south true east false north true west false 6761 green_stained_glass_pane waterlogged false south true east false north true west true 6762 green_stained_glass_pane waterlogged false south true east false north true west false 6763 green_stained_glass_pane waterlogged true south false east false north true west true 6764 green_stained_glass_pane waterlogged true south false east false north true west false 6765 green_stained_glass_pane waterlogged false south false east false north true west true 6766 green_stained_glass_pane waterlogged false south false east false north true west false 6767 green_stained_glass_pane waterlogged true south true east false north false west true 6768 green_stained_glass_pane waterlogged true south true east false north false west false 6769 green_stained_glass_pane waterlogged false south true east false north false west true 6770 green_stained_glass_pane waterlogged false south true east false north false west false 6771 green_stained_glass_pane waterlogged true south false east false north false west true 6772 green_stained_glass_pane waterlogged true south false east false north false west false 6773 green_stained_glass_pane waterlogged false south false east false north false west true 6774 green_stained_glass_pane waterlogged false south false east false north false west false 6775 red_stained_glass_pane waterlogged true south true east true north true west true 6776 red_stained_glass_pane waterlogged true south true east true north true west false 6777 red_stained_glass_pane waterlogged false south true east true north true west true 6778 red_stained_glass_pane waterlogged false south true east true north true west false 6779 red_stained_glass_pane waterlogged true south false east true north true west true 6780 red_stained_glass_pane waterlogged true south false east true north true west false 6781 red_stained_glass_pane waterlogged false south false east true north true west true 6782 red_stained_glass_pane waterlogged false south false east true north true west false 6783 red_stained_glass_pane waterlogged true south true east true north false west true 6784 red_stained_glass_pane waterlogged true south true east true north false west false 6785 red_stained_glass_pane waterlogged false south true east true north false west true 6786 red_stained_glass_pane waterlogged false south true east true north false west false 6787 red_stained_glass_pane waterlogged true south false east true north false west true 6788 red_stained_glass_pane waterlogged true south false east true north false west false 6789 red_stained_glass_pane waterlogged false south false east true north false west true 6790 red_stained_glass_pane waterlogged false south false east true north false west false 6791 red_stained_glass_pane waterlogged true south true east false north true west true 6792 red_stained_glass_pane waterlogged true south true east false north true west false 6793 red_stained_glass_pane waterlogged false south true east false north true west true 6794 red_stained_glass_pane waterlogged false south true east false north true west false 6795 red_stained_glass_pane waterlogged true south false east false north true west true 6796 red_stained_glass_pane waterlogged true south false east false north true west false 6797 red_stained_glass_pane waterlogged false south false east false north true west true 6798 red_stained_glass_pane waterlogged false south false east false north true west false 6799 red_stained_glass_pane waterlogged true south true east false north false west true 6800 red_stained_glass_pane waterlogged true south true east false north false west false 6801 red_stained_glass_pane waterlogged false south true east false north false west true 6802 red_stained_glass_pane waterlogged false south true east false north false west false 6803 red_stained_glass_pane waterlogged true south false east false north false west true 6804 red_stained_glass_pane waterlogged true south false east false north false west false 6805 red_stained_glass_pane waterlogged false south false east false north false west true 6806 red_stained_glass_pane waterlogged false south false east false north false west false 6807 black_stained_glass_pane waterlogged true south true east true north true west true 6808 black_stained_glass_pane waterlogged true south true east true north true west false 6809 black_stained_glass_pane waterlogged false south true east true north true west true 6810 black_stained_glass_pane waterlogged false south true east true north true west false 6811 black_stained_glass_pane waterlogged true south false east true north true west true 6812 black_stained_glass_pane waterlogged true south false east true north true west false 6813 black_stained_glass_pane waterlogged false south false east true north true west true 6814 black_stained_glass_pane waterlogged false south false east true north true west false 6815 black_stained_glass_pane waterlogged true south true east true north false west true 6816 black_stained_glass_pane waterlogged true south true east true north false west false 6817 black_stained_glass_pane waterlogged false south true east true north false west true 6818 black_stained_glass_pane waterlogged false south true east true north false west false 6819 black_stained_glass_pane waterlogged true south false east true north false west true 6820 black_stained_glass_pane waterlogged true south false east true north false west false 6821 black_stained_glass_pane waterlogged false south false east true north false west true 6822 black_stained_glass_pane waterlogged false south false east true north false west false 6823 black_stained_glass_pane waterlogged true south true east false north true west true 6824 black_stained_glass_pane waterlogged true south true east false north true west false 6825 black_stained_glass_pane waterlogged false south true east false north true west true 6826 black_stained_glass_pane waterlogged false south true east false north true west false 6827 black_stained_glass_pane waterlogged true south false east false north true west true 6828 black_stained_glass_pane waterlogged true south false east false north true west false 6829 black_stained_glass_pane waterlogged false south false east false north true west true 6830 black_stained_glass_pane waterlogged false south false east false north true west false 6831 black_stained_glass_pane waterlogged true south true east false north false west true 6832 black_stained_glass_pane waterlogged true south true east false north false west false 6833 black_stained_glass_pane waterlogged false south true east false north false west true 6834 black_stained_glass_pane waterlogged false south true east false north false west false 6835 black_stained_glass_pane waterlogged true south false east false north false west true 6836 black_stained_glass_pane waterlogged true south false east false north false west false 6837 black_stained_glass_pane waterlogged false south false east false north false west true 6838 black_stained_glass_pane waterlogged false south false east false north false west false 6839 acacia_stairs facing north waterlogged true shape straight half top 6840 acacia_stairs facing north waterlogged false shape straight half top 6841 acacia_stairs facing north waterlogged true shape inner_left half top 6842 acacia_stairs facing north waterlogged false shape inner_left half top 6843 acacia_stairs facing north waterlogged true shape inner_right half top 6844 acacia_stairs facing north waterlogged false shape inner_right half top 6845 acacia_stairs facing north waterlogged true shape outer_left half top 6846 acacia_stairs facing north waterlogged false shape outer_left half top 6847 acacia_stairs facing north waterlogged true shape outer_right half top 6848 acacia_stairs facing north waterlogged false shape outer_right half top 6849 acacia_stairs facing north waterlogged true shape straight half bottom 6850 acacia_stairs facing north waterlogged false shape straight half bottom 6851 acacia_stairs facing north waterlogged true shape inner_left half bottom 6852 acacia_stairs facing north waterlogged false shape inner_left half bottom 6853 acacia_stairs facing north waterlogged true shape inner_right half bottom 6854 acacia_stairs facing north waterlogged false shape inner_right half bottom 6855 acacia_stairs facing north waterlogged true shape outer_left half bottom 6856 acacia_stairs facing north waterlogged false shape outer_left half bottom 6857 acacia_stairs facing north waterlogged true shape outer_right half bottom 6858 acacia_stairs facing north waterlogged false shape outer_right half bottom 6859 acacia_stairs facing south waterlogged true shape straight half top 6860 acacia_stairs facing south waterlogged false shape straight half top 6861 acacia_stairs facing south waterlogged true shape inner_left half top 6862 acacia_stairs facing south waterlogged false shape inner_left half top 6863 acacia_stairs facing south waterlogged true shape inner_right half top 6864 acacia_stairs facing south waterlogged false shape inner_right half top 6865 acacia_stairs facing south waterlogged true shape outer_left half top 6866 acacia_stairs facing south waterlogged false shape outer_left half top 6867 acacia_stairs facing south waterlogged true shape outer_right half top 6868 acacia_stairs facing south waterlogged false shape outer_right half top 6869 acacia_stairs facing south waterlogged true shape straight half bottom 6870 acacia_stairs facing south waterlogged false shape straight half bottom 6871 acacia_stairs facing south waterlogged true shape inner_left half bottom 6872 acacia_stairs facing south waterlogged false shape inner_left half bottom 6873 acacia_stairs facing south waterlogged true shape inner_right half bottom 6874 acacia_stairs facing south waterlogged false shape inner_right half bottom 6875 acacia_stairs facing south waterlogged true shape outer_left half bottom 6876 acacia_stairs facing south waterlogged false shape outer_left half bottom 6877 acacia_stairs facing south waterlogged true shape outer_right half bottom 6878 acacia_stairs facing south waterlogged false shape outer_right half bottom 6879 acacia_stairs facing west waterlogged true shape straight half top 6880 acacia_stairs facing west waterlogged false shape straight half top 6881 acacia_stairs facing west waterlogged true shape inner_left half top 6882 acacia_stairs facing west waterlogged false shape inner_left half top 6883 acacia_stairs facing west waterlogged true shape inner_right half top 6884 acacia_stairs facing west waterlogged false shape inner_right half top 6885 acacia_stairs facing west waterlogged true shape outer_left half top 6886 acacia_stairs facing west waterlogged false shape outer_left half top 6887 acacia_stairs facing west waterlogged true shape outer_right half top 6888 acacia_stairs facing west waterlogged false shape outer_right half top 6889 acacia_stairs facing west waterlogged true shape straight half bottom 6890 acacia_stairs facing west waterlogged false shape straight half bottom 6891 acacia_stairs facing west waterlogged true shape inner_left half bottom 6892 acacia_stairs facing west waterlogged false shape inner_left half bottom 6893 acacia_stairs facing west waterlogged true shape inner_right half bottom 6894 acacia_stairs facing west waterlogged false shape inner_right half bottom 6895 acacia_stairs facing west waterlogged true shape outer_left half bottom 6896 acacia_stairs facing west waterlogged false shape outer_left half bottom 6897 acacia_stairs facing west waterlogged true shape outer_right half bottom 6898 acacia_stairs facing west waterlogged false shape outer_right half bottom 6899 acacia_stairs facing east waterlogged true shape straight half top 6900 acacia_stairs facing east waterlogged false shape straight half top 6901 acacia_stairs facing east waterlogged true shape inner_left half top 6902 acacia_stairs facing east waterlogged false shape inner_left half top 6903 acacia_stairs facing east waterlogged true shape inner_right half top 6904 acacia_stairs facing east waterlogged false shape inner_right half top 6905 acacia_stairs facing east waterlogged true shape outer_left half top 6906 acacia_stairs facing east waterlogged false shape outer_left half top 6907 acacia_stairs facing east waterlogged true shape outer_right half top 6908 acacia_stairs facing east waterlogged false shape outer_right half top 6909 acacia_stairs facing east waterlogged true shape straight half bottom 6910 acacia_stairs facing east waterlogged false shape straight half bottom 6911 acacia_stairs facing east waterlogged true shape inner_left half bottom 6912 acacia_stairs facing east waterlogged false shape inner_left half bottom 6913 acacia_stairs facing east waterlogged true shape inner_right half bottom 6914 acacia_stairs facing east waterlogged false shape inner_right half bottom 6915 acacia_stairs facing east waterlogged true shape outer_left half bottom 6916 acacia_stairs facing east waterlogged false shape outer_left half bottom 6917 acacia_stairs facing east waterlogged true shape outer_right half bottom 6918 acacia_stairs facing east waterlogged false shape outer_right half bottom 6919 dark_oak_stairs facing north waterlogged true shape straight half top 6920 dark_oak_stairs facing north waterlogged false shape straight half top 6921 dark_oak_stairs facing north waterlogged true shape inner_left half top 6922 dark_oak_stairs facing north waterlogged false shape inner_left half top 6923 dark_oak_stairs facing north waterlogged true shape inner_right half top 6924 dark_oak_stairs facing north waterlogged false shape inner_right half top 6925 dark_oak_stairs facing north waterlogged true shape outer_left half top 6926 dark_oak_stairs facing north waterlogged false shape outer_left half top 6927 dark_oak_stairs facing north waterlogged true shape outer_right half top 6928 dark_oak_stairs facing north waterlogged false shape outer_right half top 6929 dark_oak_stairs facing north waterlogged true shape straight half bottom 6930 dark_oak_stairs facing north waterlogged false shape straight half bottom 6931 dark_oak_stairs facing north waterlogged true shape inner_left half bottom 6932 dark_oak_stairs facing north waterlogged false shape inner_left half bottom 6933 dark_oak_stairs facing north waterlogged true shape inner_right half bottom 6934 dark_oak_stairs facing north waterlogged false shape inner_right half bottom 6935 dark_oak_stairs facing north waterlogged true shape outer_left half bottom 6936 dark_oak_stairs facing north waterlogged false shape outer_left half bottom 6937 dark_oak_stairs facing north waterlogged true shape outer_right half bottom 6938 dark_oak_stairs facing north waterlogged false shape outer_right half bottom 6939 dark_oak_stairs facing south waterlogged true shape straight half top 6940 dark_oak_stairs facing south waterlogged false shape straight half top 6941 dark_oak_stairs facing south waterlogged true shape inner_left half top 6942 dark_oak_stairs facing south waterlogged false shape inner_left half top 6943 dark_oak_stairs facing south waterlogged true shape inner_right half top 6944 dark_oak_stairs facing south waterlogged false shape inner_right half top 6945 dark_oak_stairs facing south waterlogged true shape outer_left half top 6946 dark_oak_stairs facing south waterlogged false shape outer_left half top 6947 dark_oak_stairs facing south waterlogged true shape outer_right half top 6948 dark_oak_stairs facing south waterlogged false shape outer_right half top 6949 dark_oak_stairs facing south waterlogged true shape straight half bottom 6950 dark_oak_stairs facing south waterlogged false shape straight half bottom 6951 dark_oak_stairs facing south waterlogged true shape inner_left half bottom 6952 dark_oak_stairs facing south waterlogged false shape inner_left half bottom 6953 dark_oak_stairs facing south waterlogged true shape inner_right half bottom 6954 dark_oak_stairs facing south waterlogged false shape inner_right half bottom 6955 dark_oak_stairs facing south waterlogged true shape outer_left half bottom 6956 dark_oak_stairs facing south waterlogged false shape outer_left half bottom 6957 dark_oak_stairs facing south waterlogged true shape outer_right half bottom 6958 dark_oak_stairs facing south waterlogged false shape outer_right half bottom 6959 dark_oak_stairs facing west waterlogged true shape straight half top 6960 dark_oak_stairs facing west waterlogged false shape straight half top 6961 dark_oak_stairs facing west waterlogged true shape inner_left half top 6962 dark_oak_stairs facing west waterlogged false shape inner_left half top 6963 dark_oak_stairs facing west waterlogged true shape inner_right half top 6964 dark_oak_stairs facing west waterlogged false shape inner_right half top 6965 dark_oak_stairs facing west waterlogged true shape outer_left half top 6966 dark_oak_stairs facing west waterlogged false shape outer_left half top 6967 dark_oak_stairs facing west waterlogged true shape outer_right half top 6968 dark_oak_stairs facing west waterlogged false shape outer_right half top 6969 dark_oak_stairs facing west waterlogged true shape straight half bottom 6970 dark_oak_stairs facing west waterlogged false shape straight half bottom 6971 dark_oak_stairs facing west waterlogged true shape inner_left half bottom 6972 dark_oak_stairs facing west waterlogged false shape inner_left half bottom 6973 dark_oak_stairs facing west waterlogged true shape inner_right half bottom 6974 dark_oak_stairs facing west waterlogged false shape inner_right half bottom 6975 dark_oak_stairs facing west waterlogged true shape outer_left half bottom 6976 dark_oak_stairs facing west waterlogged false shape outer_left half bottom 6977 dark_oak_stairs facing west waterlogged true shape outer_right half bottom 6978 dark_oak_stairs facing west waterlogged false shape outer_right half bottom 6979 dark_oak_stairs facing east waterlogged true shape straight half top 6980 dark_oak_stairs facing east waterlogged false shape straight half top 6981 dark_oak_stairs facing east waterlogged true shape inner_left half top 6982 dark_oak_stairs facing east waterlogged false shape inner_left half top 6983 dark_oak_stairs facing east waterlogged true shape inner_right half top 6984 dark_oak_stairs facing east waterlogged false shape inner_right half top 6985 dark_oak_stairs facing east waterlogged true shape outer_left half top 6986 dark_oak_stairs facing east waterlogged false shape outer_left half top 6987 dark_oak_stairs facing east waterlogged true shape outer_right half top 6988 dark_oak_stairs facing east waterlogged false shape outer_right half top 6989 dark_oak_stairs facing east waterlogged true shape straight half bottom 6990 dark_oak_stairs facing east waterlogged false shape straight half bottom 6991 dark_oak_stairs facing east waterlogged true shape inner_left half bottom 6992 dark_oak_stairs facing east waterlogged false shape inner_left half bottom 6993 dark_oak_stairs facing east waterlogged true shape inner_right half bottom 6994 dark_oak_stairs facing east waterlogged false shape inner_right half bottom 6995 dark_oak_stairs facing east waterlogged true shape outer_left half bottom 6996 dark_oak_stairs facing east waterlogged false shape outer_left half bottom 6997 dark_oak_stairs facing east waterlogged true shape outer_right half bottom 6998 dark_oak_stairs facing east waterlogged false shape outer_right half bottom 6999 slime_block 7000 barrier 7001 iron_trapdoor waterlogged true powered true facing north half top open true 7002 iron_trapdoor waterlogged false powered true facing north half top open true 7003 iron_trapdoor waterlogged true powered false facing north half top open true 7004 iron_trapdoor waterlogged false powered false facing north half top open true 7005 iron_trapdoor waterlogged true powered true facing north half top open false 7006 iron_trapdoor waterlogged false powered true facing north half top open false 7007 iron_trapdoor waterlogged true powered false facing north half top open false 7008 iron_trapdoor waterlogged false powered false facing north half top open false 7009 iron_trapdoor waterlogged true powered true facing north half bottom open true 7010 iron_trapdoor waterlogged false powered true facing north half bottom open true 7011 iron_trapdoor waterlogged true powered false facing north half bottom open true 7012 iron_trapdoor waterlogged false powered false facing north half bottom open true 7013 iron_trapdoor waterlogged true powered true facing north half bottom open false 7014 iron_trapdoor waterlogged false powered true facing north half bottom open false 7015 iron_trapdoor waterlogged true powered false facing north half bottom open false 7016 iron_trapdoor waterlogged false powered false facing north half bottom open false 7017 iron_trapdoor waterlogged true powered true facing south half top open true 7018 iron_trapdoor waterlogged false powered true facing south half top open true 7019 iron_trapdoor waterlogged true powered false facing south half top open true 7020 iron_trapdoor waterlogged false powered false facing south half top open true 7021 iron_trapdoor waterlogged true powered true facing south half top open false 7022 iron_trapdoor waterlogged false powered true facing south half top open false 7023 iron_trapdoor waterlogged true powered false facing south half top open false 7024 iron_trapdoor waterlogged false powered false facing south half top open false 7025 iron_trapdoor waterlogged true powered true facing south half bottom open true 7026 iron_trapdoor waterlogged false powered true facing south half bottom open true 7027 iron_trapdoor waterlogged true powered false facing south half bottom open true 7028 iron_trapdoor waterlogged false powered false facing south half bottom open true 7029 iron_trapdoor waterlogged true powered true facing south half bottom open false 7030 iron_trapdoor waterlogged false powered true facing south half bottom open false 7031 iron_trapdoor waterlogged true powered false facing south half bottom open false 7032 iron_trapdoor waterlogged false powered false facing south half bottom open false 7033 iron_trapdoor waterlogged true powered true facing west half top open true 7034 iron_trapdoor waterlogged false powered true facing west half top open true 7035 iron_trapdoor waterlogged true powered false facing west half top open true 7036 iron_trapdoor waterlogged false powered false facing west half top open true 7037 iron_trapdoor waterlogged true powered true facing west half top open false 7038 iron_trapdoor waterlogged false powered true facing west half top open false 7039 iron_trapdoor waterlogged true powered false facing west half top open false 7040 iron_trapdoor waterlogged false powered false facing west half top open false 7041 iron_trapdoor waterlogged true powered true facing west half bottom open true 7042 iron_trapdoor waterlogged false powered true facing west half bottom open true 7043 iron_trapdoor waterlogged true powered false facing west half bottom open true 7044 iron_trapdoor waterlogged false powered false facing west half bottom open true 7045 iron_trapdoor waterlogged true powered true facing west half bottom open false 7046 iron_trapdoor waterlogged false powered true facing west half bottom open false 7047 iron_trapdoor waterlogged true powered false facing west half bottom open false 7048 iron_trapdoor waterlogged false powered false facing west half bottom open false 7049 iron_trapdoor waterlogged true powered true facing east half top open true 7050 iron_trapdoor waterlogged false powered true facing east half top open true 7051 iron_trapdoor waterlogged true powered false facing east half top open true 7052 iron_trapdoor waterlogged false powered false facing east half top open true 7053 iron_trapdoor waterlogged true powered true facing east half top open false 7054 iron_trapdoor waterlogged false powered true facing east half top open false 7055 iron_trapdoor waterlogged true powered false facing east half top open false 7056 iron_trapdoor waterlogged false powered false facing east half top open false 7057 iron_trapdoor waterlogged true powered true facing east half bottom open true 7058 iron_trapdoor waterlogged false powered true facing east half bottom open true 7059 iron_trapdoor waterlogged true powered false facing east half bottom open true 7060 iron_trapdoor waterlogged false powered false facing east half bottom open true 7061 iron_trapdoor waterlogged true powered true facing east half bottom open false 7062 iron_trapdoor waterlogged false powered true facing east half bottom open false 7063 iron_trapdoor waterlogged true powered false facing east half bottom open false 7064 iron_trapdoor waterlogged false powered false facing east half bottom open false 7065 prismarine 7066 prismarine_bricks 7067 dark_prismarine 7068 prismarine_stairs facing north waterlogged true shape straight half top 7069 prismarine_stairs facing north waterlogged false shape straight half top 7070 prismarine_stairs facing north waterlogged true shape inner_left half top 7071 prismarine_stairs facing north waterlogged false shape inner_left half top 7072 prismarine_stairs facing north waterlogged true shape inner_right half top 7073 prismarine_stairs facing north waterlogged false shape inner_right half top 7074 prismarine_stairs facing north waterlogged true shape outer_left half top 7075 prismarine_stairs facing north waterlogged false shape outer_left half top 7076 prismarine_stairs facing north waterlogged true shape outer_right half top 7077 prismarine_stairs facing north waterlogged false shape outer_right half top 7078 prismarine_stairs facing north waterlogged true shape straight half bottom 7079 prismarine_stairs facing north waterlogged false shape straight half bottom 7080 prismarine_stairs facing north waterlogged true shape inner_left half bottom 7081 prismarine_stairs facing north waterlogged false shape inner_left half bottom 7082 prismarine_stairs facing north waterlogged true shape inner_right half bottom 7083 prismarine_stairs facing north waterlogged false shape inner_right half bottom 7084 prismarine_stairs facing north waterlogged true shape outer_left half bottom 7085 prismarine_stairs facing north waterlogged false shape outer_left half bottom 7086 prismarine_stairs facing north waterlogged true shape outer_right half bottom 7087 prismarine_stairs facing north waterlogged false shape outer_right half bottom 7088 prismarine_stairs facing south waterlogged true shape straight half top 7089 prismarine_stairs facing south waterlogged false shape straight half top 7090 prismarine_stairs facing south waterlogged true shape inner_left half top 7091 prismarine_stairs facing south waterlogged false shape inner_left half top 7092 prismarine_stairs facing south waterlogged true shape inner_right half top 7093 prismarine_stairs facing south waterlogged false shape inner_right half top 7094 prismarine_stairs facing south waterlogged true shape outer_left half top 7095 prismarine_stairs facing south waterlogged false shape outer_left half top 7096 prismarine_stairs facing south waterlogged true shape outer_right half top 7097 prismarine_stairs facing south waterlogged false shape outer_right half top 7098 prismarine_stairs facing south waterlogged true shape straight half bottom 7099 prismarine_stairs facing south waterlogged false shape straight half bottom 7100 prismarine_stairs facing south waterlogged true shape inner_left half bottom 7101 prismarine_stairs facing south waterlogged false shape inner_left half bottom 7102 prismarine_stairs facing south waterlogged true shape inner_right half bottom 7103 prismarine_stairs facing south waterlogged false shape inner_right half bottom 7104 prismarine_stairs facing south waterlogged true shape outer_left half bottom 7105 prismarine_stairs facing south waterlogged false shape outer_left half bottom 7106 prismarine_stairs facing south waterlogged true shape outer_right half bottom 7107 prismarine_stairs facing south waterlogged false shape outer_right half bottom 7108 prismarine_stairs facing west waterlogged true shape straight half top 7109 prismarine_stairs facing west waterlogged false shape straight half top 7110 prismarine_stairs facing west waterlogged true shape inner_left half top 7111 prismarine_stairs facing west waterlogged false shape inner_left half top 7112 prismarine_stairs facing west waterlogged true shape inner_right half top 7113 prismarine_stairs facing west waterlogged false shape inner_right half top 7114 prismarine_stairs facing west waterlogged true shape outer_left half top 7115 prismarine_stairs facing west waterlogged false shape outer_left half top 7116 prismarine_stairs facing west waterlogged true shape outer_right half top 7117 prismarine_stairs facing west waterlogged false shape outer_right half top 7118 prismarine_stairs facing west waterlogged true shape straight half bottom 7119 prismarine_stairs facing west waterlogged false shape straight half bottom 7120 prismarine_stairs facing west waterlogged true shape inner_left half bottom 7121 prismarine_stairs facing west waterlogged false shape inner_left half bottom 7122 prismarine_stairs facing west waterlogged true shape inner_right half bottom 7123 prismarine_stairs facing west waterlogged false shape inner_right half bottom 7124 prismarine_stairs facing west waterlogged true shape outer_left half bottom 7125 prismarine_stairs facing west waterlogged false shape outer_left half bottom 7126 prismarine_stairs facing west waterlogged true shape outer_right half bottom 7127 prismarine_stairs facing west waterlogged false shape outer_right half bottom 7128 prismarine_stairs facing east waterlogged true shape straight half top 7129 prismarine_stairs facing east waterlogged false shape straight half top 7130 prismarine_stairs facing east waterlogged true shape inner_left half top 7131 prismarine_stairs facing east waterlogged false shape inner_left half top 7132 prismarine_stairs facing east waterlogged true shape inner_right half top 7133 prismarine_stairs facing east waterlogged false shape inner_right half top 7134 prismarine_stairs facing east waterlogged true shape outer_left half top 7135 prismarine_stairs facing east waterlogged false shape outer_left half top 7136 prismarine_stairs facing east waterlogged true shape outer_right half top 7137 prismarine_stairs facing east waterlogged false shape outer_right half top 7138 prismarine_stairs facing east waterlogged true shape straight half bottom 7139 prismarine_stairs facing east waterlogged false shape straight half bottom 7140 prismarine_stairs facing east waterlogged true shape inner_left half bottom 7141 prismarine_stairs facing east waterlogged false shape inner_left half bottom 7142 prismarine_stairs facing east waterlogged true shape inner_right half bottom 7143 prismarine_stairs facing east waterlogged false shape inner_right half bottom 7144 prismarine_stairs facing east waterlogged true shape outer_left half bottom 7145 prismarine_stairs facing east waterlogged false shape outer_left half bottom 7146 prismarine_stairs facing east waterlogged true shape outer_right half bottom 7147 prismarine_stairs facing east waterlogged false shape outer_right half bottom 7148 prismarine_brick_stairs facing north waterlogged true shape straight half top 7149 prismarine_brick_stairs facing north waterlogged false shape straight half top 7150 prismarine_brick_stairs facing north waterlogged true shape inner_left half top 7151 prismarine_brick_stairs facing north waterlogged false shape inner_left half top 7152 prismarine_brick_stairs facing north waterlogged true shape inner_right half top 7153 prismarine_brick_stairs facing north waterlogged false shape inner_right half top 7154 prismarine_brick_stairs facing north waterlogged true shape outer_left half top 7155 prismarine_brick_stairs facing north waterlogged false shape outer_left half top 7156 prismarine_brick_stairs facing north waterlogged true shape outer_right half top 7157 prismarine_brick_stairs facing north waterlogged false shape outer_right half top 7158 prismarine_brick_stairs facing north waterlogged true shape straight half bottom 7159 prismarine_brick_stairs facing north waterlogged false shape straight half bottom 7160 prismarine_brick_stairs facing north waterlogged true shape inner_left half bottom 7161 prismarine_brick_stairs facing north waterlogged false shape inner_left half bottom 7162 prismarine_brick_stairs facing north waterlogged true shape inner_right half bottom 7163 prismarine_brick_stairs facing north waterlogged false shape inner_right half bottom 7164 prismarine_brick_stairs facing north waterlogged true shape outer_left half bottom 7165 prismarine_brick_stairs facing north waterlogged false shape outer_left half bottom 7166 prismarine_brick_stairs facing north waterlogged true shape outer_right half bottom 7167 prismarine_brick_stairs facing north waterlogged false shape outer_right half bottom 7168 prismarine_brick_stairs facing south waterlogged true shape straight half top 7169 prismarine_brick_stairs facing south waterlogged false shape straight half top 7170 prismarine_brick_stairs facing south waterlogged true shape inner_left half top 7171 prismarine_brick_stairs facing south waterlogged false shape inner_left half top 7172 prismarine_brick_stairs facing south waterlogged true shape inner_right half top 7173 prismarine_brick_stairs facing south waterlogged false shape inner_right half top 7174 prismarine_brick_stairs facing south waterlogged true shape outer_left half top 7175 prismarine_brick_stairs facing south waterlogged false shape outer_left half top 7176 prismarine_brick_stairs facing south waterlogged true shape outer_right half top 7177 prismarine_brick_stairs facing south waterlogged false shape outer_right half top 7178 prismarine_brick_stairs facing south waterlogged true shape straight half bottom 7179 prismarine_brick_stairs facing south waterlogged false shape straight half bottom 7180 prismarine_brick_stairs facing south waterlogged true shape inner_left half bottom 7181 prismarine_brick_stairs facing south waterlogged false shape inner_left half bottom 7182 prismarine_brick_stairs facing south waterlogged true shape inner_right half bottom 7183 prismarine_brick_stairs facing south waterlogged false shape inner_right half bottom 7184 prismarine_brick_stairs facing south waterlogged true shape outer_left half bottom 7185 prismarine_brick_stairs facing south waterlogged false shape outer_left half bottom 7186 prismarine_brick_stairs facing south waterlogged true shape outer_right half bottom 7187 prismarine_brick_stairs facing south waterlogged false shape outer_right half bottom 7188 prismarine_brick_stairs facing west waterlogged true shape straight half top 7189 prismarine_brick_stairs facing west waterlogged false shape straight half top 7190 prismarine_brick_stairs facing west waterlogged true shape inner_left half top 7191 prismarine_brick_stairs facing west waterlogged false shape inner_left half top 7192 prismarine_brick_stairs facing west waterlogged true shape inner_right half top 7193 prismarine_brick_stairs facing west waterlogged false shape inner_right half top 7194 prismarine_brick_stairs facing west waterlogged true shape outer_left half top 7195 prismarine_brick_stairs facing west waterlogged false shape outer_left half top 7196 prismarine_brick_stairs facing west waterlogged true shape outer_right half top 7197 prismarine_brick_stairs facing west waterlogged false shape outer_right half top 7198 prismarine_brick_stairs facing west waterlogged true shape straight half bottom 7199 prismarine_brick_stairs facing west waterlogged false shape straight half bottom 7200 prismarine_brick_stairs facing west waterlogged true shape inner_left half bottom 7201 prismarine_brick_stairs facing west waterlogged false shape inner_left half bottom 7202 prismarine_brick_stairs facing west waterlogged true shape inner_right half bottom 7203 prismarine_brick_stairs facing west waterlogged false shape inner_right half bottom 7204 prismarine_brick_stairs facing west waterlogged true shape outer_left half bottom 7205 prismarine_brick_stairs facing west waterlogged false shape outer_left half bottom 7206 prismarine_brick_stairs facing west waterlogged true shape outer_right half bottom 7207 prismarine_brick_stairs facing west waterlogged false shape outer_right half bottom 7208 prismarine_brick_stairs facing east waterlogged true shape straight half top 7209 prismarine_brick_stairs facing east waterlogged false shape straight half top 7210 prismarine_brick_stairs facing east waterlogged true shape inner_left half top 7211 prismarine_brick_stairs facing east waterlogged false shape inner_left half top 7212 prismarine_brick_stairs facing east waterlogged true shape inner_right half top 7213 prismarine_brick_stairs facing east waterlogged false shape inner_right half top 7214 prismarine_brick_stairs facing east waterlogged true shape outer_left half top 7215 prismarine_brick_stairs facing east waterlogged false shape outer_left half top 7216 prismarine_brick_stairs facing east waterlogged true shape outer_right half top 7217 prismarine_brick_stairs facing east waterlogged false shape outer_right half top 7218 prismarine_brick_stairs facing east waterlogged true shape straight half bottom 7219 prismarine_brick_stairs facing east waterlogged false shape straight half bottom 7220 prismarine_brick_stairs facing east waterlogged true shape inner_left half bottom 7221 prismarine_brick_stairs facing east waterlogged false shape inner_left half bottom 7222 prismarine_brick_stairs facing east waterlogged true shape inner_right half bottom 7223 prismarine_brick_stairs facing east waterlogged false shape inner_right half bottom 7224 prismarine_brick_stairs facing east waterlogged true shape outer_left half bottom 7225 prismarine_brick_stairs facing east waterlogged false shape outer_left half bottom 7226 prismarine_brick_stairs facing east waterlogged true shape outer_right half bottom 7227 prismarine_brick_stairs facing east waterlogged false shape outer_right half bottom 7228 dark_prismarine_stairs facing north waterlogged true shape straight half top 7229 dark_prismarine_stairs facing north waterlogged false shape straight half top 7230 dark_prismarine_stairs facing north waterlogged true shape inner_left half top 7231 dark_prismarine_stairs facing north waterlogged false shape inner_left half top 7232 dark_prismarine_stairs facing north waterlogged true shape inner_right half top 7233 dark_prismarine_stairs facing north waterlogged false shape inner_right half top 7234 dark_prismarine_stairs facing north waterlogged true shape outer_left half top 7235 dark_prismarine_stairs facing north waterlogged false shape outer_left half top 7236 dark_prismarine_stairs facing north waterlogged true shape outer_right half top 7237 dark_prismarine_stairs facing north waterlogged false shape outer_right half top 7238 dark_prismarine_stairs facing north waterlogged true shape straight half bottom 7239 dark_prismarine_stairs facing north waterlogged false shape straight half bottom 7240 dark_prismarine_stairs facing north waterlogged true shape inner_left half bottom 7241 dark_prismarine_stairs facing north waterlogged false shape inner_left half bottom 7242 dark_prismarine_stairs facing north waterlogged true shape inner_right half bottom 7243 dark_prismarine_stairs facing north waterlogged false shape inner_right half bottom 7244 dark_prismarine_stairs facing north waterlogged true shape outer_left half bottom 7245 dark_prismarine_stairs facing north waterlogged false shape outer_left half bottom 7246 dark_prismarine_stairs facing north waterlogged true shape outer_right half bottom 7247 dark_prismarine_stairs facing north waterlogged false shape outer_right half bottom 7248 dark_prismarine_stairs facing south waterlogged true shape straight half top 7249 dark_prismarine_stairs facing south waterlogged false shape straight half top 7250 dark_prismarine_stairs facing south waterlogged true shape inner_left half top 7251 dark_prismarine_stairs facing south waterlogged false shape inner_left half top 7252 dark_prismarine_stairs facing south waterlogged true shape inner_right half top 7253 dark_prismarine_stairs facing south waterlogged false shape inner_right half top 7254 dark_prismarine_stairs facing south waterlogged true shape outer_left half top 7255 dark_prismarine_stairs facing south waterlogged false shape outer_left half top 7256 dark_prismarine_stairs facing south waterlogged true shape outer_right half top 7257 dark_prismarine_stairs facing south waterlogged false shape outer_right half top 7258 dark_prismarine_stairs facing south waterlogged true shape straight half bottom 7259 dark_prismarine_stairs facing south waterlogged false shape straight half bottom 7260 dark_prismarine_stairs facing south waterlogged true shape inner_left half bottom 7261 dark_prismarine_stairs facing south waterlogged false shape inner_left half bottom 7262 dark_prismarine_stairs facing south waterlogged true shape inner_right half bottom 7263 dark_prismarine_stairs facing south waterlogged false shape inner_right half bottom 7264 dark_prismarine_stairs facing south waterlogged true shape outer_left half bottom 7265 dark_prismarine_stairs facing south waterlogged false shape outer_left half bottom 7266 dark_prismarine_stairs facing south waterlogged true shape outer_right half bottom 7267 dark_prismarine_stairs facing south waterlogged false shape outer_right half bottom 7268 dark_prismarine_stairs facing west waterlogged true shape straight half top 7269 dark_prismarine_stairs facing west waterlogged false shape straight half top 7270 dark_prismarine_stairs facing west waterlogged true shape inner_left half top 7271 dark_prismarine_stairs facing west waterlogged false shape inner_left half top 7272 dark_prismarine_stairs facing west waterlogged true shape inner_right half top 7273 dark_prismarine_stairs facing west waterlogged false shape inner_right half top 7274 dark_prismarine_stairs facing west waterlogged true shape outer_left half top 7275 dark_prismarine_stairs facing west waterlogged false shape outer_left half top 7276 dark_prismarine_stairs facing west waterlogged true shape outer_right half top 7277 dark_prismarine_stairs facing west waterlogged false shape outer_right half top 7278 dark_prismarine_stairs facing west waterlogged true shape straight half bottom 7279 dark_prismarine_stairs facing west waterlogged false shape straight half bottom 7280 dark_prismarine_stairs facing west waterlogged true shape inner_left half bottom 7281 dark_prismarine_stairs facing west waterlogged false shape inner_left half bottom 7282 dark_prismarine_stairs facing west waterlogged true shape inner_right half bottom 7283 dark_prismarine_stairs facing west waterlogged false shape inner_right half bottom 7284 dark_prismarine_stairs facing west waterlogged true shape outer_left half bottom 7285 dark_prismarine_stairs facing west waterlogged false shape outer_left half bottom 7286 dark_prismarine_stairs facing west waterlogged true shape outer_right half bottom 7287 dark_prismarine_stairs facing west waterlogged false shape outer_right half bottom 7288 dark_prismarine_stairs facing east waterlogged true shape straight half top 7289 dark_prismarine_stairs facing east waterlogged false shape straight half top 7290 dark_prismarine_stairs facing east waterlogged true shape inner_left half top 7291 dark_prismarine_stairs facing east waterlogged false shape inner_left half top 7292 dark_prismarine_stairs facing east waterlogged true shape inner_right half top 7293 dark_prismarine_stairs facing east waterlogged false shape inner_right half top 7294 dark_prismarine_stairs facing east waterlogged true shape outer_left half top 7295 dark_prismarine_stairs facing east waterlogged false shape outer_left half top 7296 dark_prismarine_stairs facing east waterlogged true shape outer_right half top 7297 dark_prismarine_stairs facing east waterlogged false shape outer_right half top 7298 dark_prismarine_stairs facing east waterlogged true shape straight half bottom 7299 dark_prismarine_stairs facing east waterlogged false shape straight half bottom 7300 dark_prismarine_stairs facing east waterlogged true shape inner_left half bottom 7301 dark_prismarine_stairs facing east waterlogged false shape inner_left half bottom 7302 dark_prismarine_stairs facing east waterlogged true shape inner_right half bottom 7303 dark_prismarine_stairs facing east waterlogged false shape inner_right half bottom 7304 dark_prismarine_stairs facing east waterlogged true shape outer_left half bottom 7305 dark_prismarine_stairs facing east waterlogged false shape outer_left half bottom 7306 dark_prismarine_stairs facing east waterlogged true shape outer_right half bottom 7307 dark_prismarine_stairs facing east waterlogged false shape outer_right half bottom 7308 prismarine_slab type top waterlogged true 7309 prismarine_slab type top waterlogged false 7310 prismarine_slab type bottom waterlogged true 7311 prismarine_slab type bottom waterlogged false 7312 prismarine_slab type double waterlogged true 7313 prismarine_slab type double waterlogged false 7314 prismarine_brick_slab type top waterlogged true 7315 prismarine_brick_slab type top waterlogged false 7316 prismarine_brick_slab type bottom waterlogged true 7317 prismarine_brick_slab type bottom waterlogged false 7318 prismarine_brick_slab type double waterlogged true 7319 prismarine_brick_slab type double waterlogged false 7320 dark_prismarine_slab type top waterlogged true 7321 dark_prismarine_slab type top waterlogged false 7322 dark_prismarine_slab type bottom waterlogged true 7323 dark_prismarine_slab type bottom waterlogged false 7324 dark_prismarine_slab type double waterlogged true 7325 dark_prismarine_slab type double waterlogged false 7326 sea_lantern 7327 hay_block axis x 7328 hay_block axis y 7329 hay_block axis z 7330 white_carpet 7331 orange_carpet 7332 magenta_carpet 7333 light_blue_carpet 7334 yellow_carpet 7335 lime_carpet 7336 pink_carpet 7337 gray_carpet 7338 light_gray_carpet 7339 cyan_carpet 7340 purple_carpet 7341 blue_carpet 7342 brown_carpet 7343 green_carpet 7344 red_carpet 7345 black_carpet 7346 terracotta 7347 coal_block 7348 packed_ice 7349 sunflower half upper 7350 sunflower half lower 7351 lilac half upper 7352 lilac half lower 7353 rose_bush half upper 7354 rose_bush half lower 7355 peony half upper 7356 peony half lower 7357 tall_grass half upper 7358 tall_grass half lower 7359 large_fern half upper 7360 large_fern half lower 7361 white_banner rotation 0 7362 white_banner rotation 1 7363 white_banner rotation 2 7364 white_banner rotation 3 7365 white_banner rotation 4 7366 white_banner rotation 5 7367 white_banner rotation 6 7368 white_banner rotation 7 7369 white_banner rotation 8 7370 white_banner rotation 9 7371 white_banner rotation 10 7372 white_banner rotation 11 7373 white_banner rotation 12 7374 white_banner rotation 13 7375 white_banner rotation 14 7376 white_banner rotation 15 7377 orange_banner rotation 0 7378 orange_banner rotation 1 7379 orange_banner rotation 2 7380 orange_banner rotation 3 7381 orange_banner rotation 4 7382 orange_banner rotation 5 7383 orange_banner rotation 6 7384 orange_banner rotation 7 7385 orange_banner rotation 8 7386 orange_banner rotation 9 7387 orange_banner rotation 10 7388 orange_banner rotation 11 7389 orange_banner rotation 12 7390 orange_banner rotation 13 7391 orange_banner rotation 14 7392 orange_banner rotation 15 7393 magenta_banner rotation 0 7394 magenta_banner rotation 1 7395 magenta_banner rotation 2 7396 magenta_banner rotation 3 7397 magenta_banner rotation 4 7398 magenta_banner rotation 5 7399 magenta_banner rotation 6 7400 magenta_banner rotation 7 7401 magenta_banner rotation 8 7402 magenta_banner rotation 9 7403 magenta_banner rotation 10 7404 magenta_banner rotation 11 7405 magenta_banner rotation 12 7406 magenta_banner rotation 13 7407 magenta_banner rotation 14 7408 magenta_banner rotation 15 7409 light_blue_banner rotation 0 7410 light_blue_banner rotation 1 7411 light_blue_banner rotation 2 7412 light_blue_banner rotation 3 7413 light_blue_banner rotation 4 7414 light_blue_banner rotation 5 7415 light_blue_banner rotation 6 7416 light_blue_banner rotation 7 7417 light_blue_banner rotation 8 7418 light_blue_banner rotation 9 7419 light_blue_banner rotation 10 7420 light_blue_banner rotation 11 7421 light_blue_banner rotation 12 7422 light_blue_banner rotation 13 7423 light_blue_banner rotation 14 7424 light_blue_banner rotation 15 7425 yellow_banner rotation 0 7426 yellow_banner rotation 1 7427 yellow_banner rotation 2 7428 yellow_banner rotation 3 7429 yellow_banner rotation 4 7430 yellow_banner rotation 5 7431 yellow_banner rotation 6 7432 yellow_banner rotation 7 7433 yellow_banner rotation 8 7434 yellow_banner rotation 9 7435 yellow_banner rotation 10 7436 yellow_banner rotation 11 7437 yellow_banner rotation 12 7438 yellow_banner rotation 13 7439 yellow_banner rotation 14 7440 yellow_banner rotation 15 7441 lime_banner rotation 0 7442 lime_banner rotation 1 7443 lime_banner rotation 2 7444 lime_banner rotation 3 7445 lime_banner rotation 4 7446 lime_banner rotation 5 7447 lime_banner rotation 6 7448 lime_banner rotation 7 7449 lime_banner rotation 8 7450 lime_banner rotation 9 7451 lime_banner rotation 10 7452 lime_banner rotation 11 7453 lime_banner rotation 12 7454 lime_banner rotation 13 7455 lime_banner rotation 14 7456 lime_banner rotation 15 7457 pink_banner rotation 0 7458 pink_banner rotation 1 7459 pink_banner rotation 2 7460 pink_banner rotation 3 7461 pink_banner rotation 4 7462 pink_banner rotation 5 7463 pink_banner rotation 6 7464 pink_banner rotation 7 7465 pink_banner rotation 8 7466 pink_banner rotation 9 7467 pink_banner rotation 10 7468 pink_banner rotation 11 7469 pink_banner rotation 12 7470 pink_banner rotation 13 7471 pink_banner rotation 14 7472 pink_banner rotation 15 7473 gray_banner rotation 0 7474 gray_banner rotation 1 7475 gray_banner rotation 2 7476 gray_banner rotation 3 7477 gray_banner rotation 4 7478 gray_banner rotation 5 7479 gray_banner rotation 6 7480 gray_banner rotation 7 7481 gray_banner rotation 8 7482 gray_banner rotation 9 7483 gray_banner rotation 10 7484 gray_banner rotation 11 7485 gray_banner rotation 12 7486 gray_banner rotation 13 7487 gray_banner rotation 14 7488 gray_banner rotation 15 7489 light_gray_banner rotation 0 7490 light_gray_banner rotation 1 7491 light_gray_banner rotation 2 7492 light_gray_banner rotation 3 7493 light_gray_banner rotation 4 7494 light_gray_banner rotation 5 7495 light_gray_banner rotation 6 7496 light_gray_banner rotation 7 7497 light_gray_banner rotation 8 7498 light_gray_banner rotation 9 7499 light_gray_banner rotation 10 7500 light_gray_banner rotation 11 7501 light_gray_banner rotation 12 7502 light_gray_banner rotation 13 7503 light_gray_banner rotation 14 7504 light_gray_banner rotation 15 7505 cyan_banner rotation 0 7506 cyan_banner rotation 1 7507 cyan_banner rotation 2 7508 cyan_banner rotation 3 7509 cyan_banner rotation 4 7510 cyan_banner rotation 5 7511 cyan_banner rotation 6 7512 cyan_banner rotation 7 7513 cyan_banner rotation 8 7514 cyan_banner rotation 9 7515 cyan_banner rotation 10 7516 cyan_banner rotation 11 7517 cyan_banner rotation 12 7518 cyan_banner rotation 13 7519 cyan_banner rotation 14 7520 cyan_banner rotation 15 7521 purple_banner rotation 0 7522 purple_banner rotation 1 7523 purple_banner rotation 2 7524 purple_banner rotation 3 7525 purple_banner rotation 4 7526 purple_banner rotation 5 7527 purple_banner rotation 6 7528 purple_banner rotation 7 7529 purple_banner rotation 8 7530 purple_banner rotation 9 7531 purple_banner rotation 10 7532 purple_banner rotation 11 7533 purple_banner rotation 12 7534 purple_banner rotation 13 7535 purple_banner rotation 14 7536 purple_banner rotation 15 7537 blue_banner rotation 0 7538 blue_banner rotation 1 7539 blue_banner rotation 2 7540 blue_banner rotation 3 7541 blue_banner rotation 4 7542 blue_banner rotation 5 7543 blue_banner rotation 6 7544 blue_banner rotation 7 7545 blue_banner rotation 8 7546 blue_banner rotation 9 7547 blue_banner rotation 10 7548 blue_banner rotation 11 7549 blue_banner rotation 12 7550 blue_banner rotation 13 7551 blue_banner rotation 14 7552 blue_banner rotation 15 7553 brown_banner rotation 0 7554 brown_banner rotation 1 7555 brown_banner rotation 2 7556 brown_banner rotation 3 7557 brown_banner rotation 4 7558 brown_banner rotation 5 7559 brown_banner rotation 6 7560 brown_banner rotation 7 7561 brown_banner rotation 8 7562 brown_banner rotation 9 7563 brown_banner rotation 10 7564 brown_banner rotation 11 7565 brown_banner rotation 12 7566 brown_banner rotation 13 7567 brown_banner rotation 14 7568 brown_banner rotation 15 7569 green_banner rotation 0 7570 green_banner rotation 1 7571 green_banner rotation 2 7572 green_banner rotation 3 7573 green_banner rotation 4 7574 green_banner rotation 5 7575 green_banner rotation 6 7576 green_banner rotation 7 7577 green_banner rotation 8 7578 green_banner rotation 9 7579 green_banner rotation 10 7580 green_banner rotation 11 7581 green_banner rotation 12 7582 green_banner rotation 13 7583 green_banner rotation 14 7584 green_banner rotation 15 7585 red_banner rotation 0 7586 red_banner rotation 1 7587 red_banner rotation 2 7588 red_banner rotation 3 7589 red_banner rotation 4 7590 red_banner rotation 5 7591 red_banner rotation 6 7592 red_banner rotation 7 7593 red_banner rotation 8 7594 red_banner rotation 9 7595 red_banner rotation 10 7596 red_banner rotation 11 7597 red_banner rotation 12 7598 red_banner rotation 13 7599 red_banner rotation 14 7600 red_banner rotation 15 7601 black_banner rotation 0 7602 black_banner rotation 1 7603 black_banner rotation 2 7604 black_banner rotation 3 7605 black_banner rotation 4 7606 black_banner rotation 5 7607 black_banner rotation 6 7608 black_banner rotation 7 7609 black_banner rotation 8 7610 black_banner rotation 9 7611 black_banner rotation 10 7612 black_banner rotation 11 7613 black_banner rotation 12 7614 black_banner rotation 13 7615 black_banner rotation 14 7616 black_banner rotation 15 7617 white_wall_banner facing north 7618 white_wall_banner facing south 7619 white_wall_banner facing west 7620 white_wall_banner facing east 7621 orange_wall_banner facing north 7622 orange_wall_banner facing south 7623 orange_wall_banner facing west 7624 orange_wall_banner facing east 7625 magenta_wall_banner facing north 7626 magenta_wall_banner facing south 7627 magenta_wall_banner facing west 7628 magenta_wall_banner facing east 7629 light_blue_wall_banner facing north 7630 light_blue_wall_banner facing south 7631 light_blue_wall_banner facing west 7632 light_blue_wall_banner facing east 7633 yellow_wall_banner facing north 7634 yellow_wall_banner facing south 7635 yellow_wall_banner facing west 7636 yellow_wall_banner facing east 7637 lime_wall_banner facing north 7638 lime_wall_banner facing south 7639 lime_wall_banner facing west 7640 lime_wall_banner facing east 7641 pink_wall_banner facing north 7642 pink_wall_banner facing south 7643 pink_wall_banner facing west 7644 pink_wall_banner facing east 7645 gray_wall_banner facing north 7646 gray_wall_banner facing south 7647 gray_wall_banner facing west 7648 gray_wall_banner facing east 7649 light_gray_wall_banner facing north 7650 light_gray_wall_banner facing south 7651 light_gray_wall_banner facing west 7652 light_gray_wall_banner facing east 7653 cyan_wall_banner facing north 7654 cyan_wall_banner facing south 7655 cyan_wall_banner facing west 7656 cyan_wall_banner facing east 7657 purple_wall_banner facing north 7658 purple_wall_banner facing south 7659 purple_wall_banner facing west 7660 purple_wall_banner facing east 7661 blue_wall_banner facing north 7662 blue_wall_banner facing south 7663 blue_wall_banner facing west 7664 blue_wall_banner facing east 7665 brown_wall_banner facing north 7666 brown_wall_banner facing south 7667 brown_wall_banner facing west 7668 brown_wall_banner facing east 7669 green_wall_banner facing north 7670 green_wall_banner facing south 7671 green_wall_banner facing west 7672 green_wall_banner facing east 7673 red_wall_banner facing north 7674 red_wall_banner facing south 7675 red_wall_banner facing west 7676 red_wall_banner facing east 7677 black_wall_banner facing north 7678 black_wall_banner facing south 7679 black_wall_banner facing west 7680 black_wall_banner facing east 7681 red_sandstone 7682 chiseled_red_sandstone 7683 cut_red_sandstone 7684 red_sandstone_stairs facing north waterlogged true shape straight half top 7685 red_sandstone_stairs facing north waterlogged false shape straight half top 7686 red_sandstone_stairs facing north waterlogged true shape inner_left half top 7687 red_sandstone_stairs facing north waterlogged false shape inner_left half top 7688 red_sandstone_stairs facing north waterlogged true shape inner_right half top 7689 red_sandstone_stairs facing north waterlogged false shape inner_right half top 7690 red_sandstone_stairs facing north waterlogged true shape outer_left half top 7691 red_sandstone_stairs facing north waterlogged false shape outer_left half top 7692 red_sandstone_stairs facing north waterlogged true shape outer_right half top 7693 red_sandstone_stairs facing north waterlogged false shape outer_right half top 7694 red_sandstone_stairs facing north waterlogged true shape straight half bottom 7695 red_sandstone_stairs facing north waterlogged false shape straight half bottom 7696 red_sandstone_stairs facing north waterlogged true shape inner_left half bottom 7697 red_sandstone_stairs facing north waterlogged false shape inner_left half bottom 7698 red_sandstone_stairs facing north waterlogged true shape inner_right half bottom 7699 red_sandstone_stairs facing north waterlogged false shape inner_right half bottom 7700 red_sandstone_stairs facing north waterlogged true shape outer_left half bottom 7701 red_sandstone_stairs facing north waterlogged false shape outer_left half bottom 7702 red_sandstone_stairs facing north waterlogged true shape outer_right half bottom 7703 red_sandstone_stairs facing north waterlogged false shape outer_right half bottom 7704 red_sandstone_stairs facing south waterlogged true shape straight half top 7705 red_sandstone_stairs facing south waterlogged false shape straight half top 7706 red_sandstone_stairs facing south waterlogged true shape inner_left half top 7707 red_sandstone_stairs facing south waterlogged false shape inner_left half top 7708 red_sandstone_stairs facing south waterlogged true shape inner_right half top 7709 red_sandstone_stairs facing south waterlogged false shape inner_right half top 7710 red_sandstone_stairs facing south waterlogged true shape outer_left half top 7711 red_sandstone_stairs facing south waterlogged false shape outer_left half top 7712 red_sandstone_stairs facing south waterlogged true shape outer_right half top 7713 red_sandstone_stairs facing south waterlogged false shape outer_right half top 7714 red_sandstone_stairs facing south waterlogged true shape straight half bottom 7715 red_sandstone_stairs facing south waterlogged false shape straight half bottom 7716 red_sandstone_stairs facing south waterlogged true shape inner_left half bottom 7717 red_sandstone_stairs facing south waterlogged false shape inner_left half bottom 7718 red_sandstone_stairs facing south waterlogged true shape inner_right half bottom 7719 red_sandstone_stairs facing south waterlogged false shape inner_right half bottom 7720 red_sandstone_stairs facing south waterlogged true shape outer_left half bottom 7721 red_sandstone_stairs facing south waterlogged false shape outer_left half bottom 7722 red_sandstone_stairs facing south waterlogged true shape outer_right half bottom 7723 red_sandstone_stairs facing south waterlogged false shape outer_right half bottom 7724 red_sandstone_stairs facing west waterlogged true shape straight half top 7725 red_sandstone_stairs facing west waterlogged false shape straight half top 7726 red_sandstone_stairs facing west waterlogged true shape inner_left half top 7727 red_sandstone_stairs facing west waterlogged false shape inner_left half top 7728 red_sandstone_stairs facing west waterlogged true shape inner_right half top 7729 red_sandstone_stairs facing west waterlogged false shape inner_right half top 7730 red_sandstone_stairs facing west waterlogged true shape outer_left half top 7731 red_sandstone_stairs facing west waterlogged false shape outer_left half top 7732 red_sandstone_stairs facing west waterlogged true shape outer_right half top 7733 red_sandstone_stairs facing west waterlogged false shape outer_right half top 7734 red_sandstone_stairs facing west waterlogged true shape straight half bottom 7735 red_sandstone_stairs facing west waterlogged false shape straight half bottom 7736 red_sandstone_stairs facing west waterlogged true shape inner_left half bottom 7737 red_sandstone_stairs facing west waterlogged false shape inner_left half bottom 7738 red_sandstone_stairs facing west waterlogged true shape inner_right half bottom 7739 red_sandstone_stairs facing west waterlogged false shape inner_right half bottom 7740 red_sandstone_stairs facing west waterlogged true shape outer_left half bottom 7741 red_sandstone_stairs facing west waterlogged false shape outer_left half bottom 7742 red_sandstone_stairs facing west waterlogged true shape outer_right half bottom 7743 red_sandstone_stairs facing west waterlogged false shape outer_right half bottom 7744 red_sandstone_stairs facing east waterlogged true shape straight half top 7745 red_sandstone_stairs facing east waterlogged false shape straight half top 7746 red_sandstone_stairs facing east waterlogged true shape inner_left half top 7747 red_sandstone_stairs facing east waterlogged false shape inner_left half top 7748 red_sandstone_stairs facing east waterlogged true shape inner_right half top 7749 red_sandstone_stairs facing east waterlogged false shape inner_right half top 7750 red_sandstone_stairs facing east waterlogged true shape outer_left half top 7751 red_sandstone_stairs facing east waterlogged false shape outer_left half top 7752 red_sandstone_stairs facing east waterlogged true shape outer_right half top 7753 red_sandstone_stairs facing east waterlogged false shape outer_right half top 7754 red_sandstone_stairs facing east waterlogged true shape straight half bottom 7755 red_sandstone_stairs facing east waterlogged false shape straight half bottom 7756 red_sandstone_stairs facing east waterlogged true shape inner_left half bottom 7757 red_sandstone_stairs facing east waterlogged false shape inner_left half bottom 7758 red_sandstone_stairs facing east waterlogged true shape inner_right half bottom 7759 red_sandstone_stairs facing east waterlogged false shape inner_right half bottom 7760 red_sandstone_stairs facing east waterlogged true shape outer_left half bottom 7761 red_sandstone_stairs facing east waterlogged false shape outer_left half bottom 7762 red_sandstone_stairs facing east waterlogged true shape outer_right half bottom 7763 red_sandstone_stairs facing east waterlogged false shape outer_right half bottom 7764 oak_slab type top waterlogged true 7765 oak_slab type top waterlogged false 7766 oak_slab type bottom waterlogged true 7767 oak_slab type bottom waterlogged false 7768 oak_slab type double waterlogged true 7769 oak_slab type double waterlogged false 7770 spruce_slab type top waterlogged true 7771 spruce_slab type top waterlogged false 7772 spruce_slab type bottom waterlogged true 7773 spruce_slab type bottom waterlogged false 7774 spruce_slab type double waterlogged true 7775 spruce_slab type double waterlogged false 7776 birch_slab type top waterlogged true 7777 birch_slab type top waterlogged false 7778 birch_slab type bottom waterlogged true 7779 birch_slab type bottom waterlogged false 7780 birch_slab type double waterlogged true 7781 birch_slab type double waterlogged false 7782 jungle_slab type top waterlogged true 7783 jungle_slab type top waterlogged false 7784 jungle_slab type bottom waterlogged true 7785 jungle_slab type bottom waterlogged false 7786 jungle_slab type double waterlogged true 7787 jungle_slab type double waterlogged false 7788 acacia_slab type top waterlogged true 7789 acacia_slab type top waterlogged false 7790 acacia_slab type bottom waterlogged true 7791 acacia_slab type bottom waterlogged false 7792 acacia_slab type double waterlogged true 7793 acacia_slab type double waterlogged false 7794 dark_oak_slab type top waterlogged true 7795 dark_oak_slab type top waterlogged false 7796 dark_oak_slab type bottom waterlogged true 7797 dark_oak_slab type bottom waterlogged false 7798 dark_oak_slab type double waterlogged true 7799 dark_oak_slab type double waterlogged false 7800 stone_slab type top waterlogged true 7801 stone_slab type top waterlogged false 7802 stone_slab type bottom waterlogged true 7803 stone_slab type bottom waterlogged false 7804 stone_slab type double waterlogged true 7805 stone_slab type double waterlogged false 7806 smooth_stone_slab type top waterlogged true 7807 smooth_stone_slab type top waterlogged false 7808 smooth_stone_slab type bottom waterlogged true 7809 smooth_stone_slab type bottom waterlogged false 7810 smooth_stone_slab type double waterlogged true 7811 smooth_stone_slab type double waterlogged false 7812 sandstone_slab type top waterlogged true 7813 sandstone_slab type top waterlogged false 7814 sandstone_slab type bottom waterlogged true 7815 sandstone_slab type bottom waterlogged false 7816 sandstone_slab type double waterlogged true 7817 sandstone_slab type double waterlogged false 7818 cut_sandstone_slab type top waterlogged true 7819 cut_sandstone_slab type top waterlogged false 7820 cut_sandstone_slab type bottom waterlogged true 7821 cut_sandstone_slab type bottom waterlogged false 7822 cut_sandstone_slab type double waterlogged true 7823 cut_sandstone_slab type double waterlogged false 7824 petrified_oak_slab type top waterlogged true 7825 petrified_oak_slab type top waterlogged false 7826 petrified_oak_slab type bottom waterlogged true 7827 petrified_oak_slab type bottom waterlogged false 7828 petrified_oak_slab type double waterlogged true 7829 petrified_oak_slab type double waterlogged false 7830 cobblestone_slab type top waterlogged true 7831 cobblestone_slab type top waterlogged false 7832 cobblestone_slab type bottom waterlogged true 7833 cobblestone_slab type bottom waterlogged false 7834 cobblestone_slab type double waterlogged true 7835 cobblestone_slab type double waterlogged false 7836 brick_slab type top waterlogged true 7837 brick_slab type top waterlogged false 7838 brick_slab type bottom waterlogged true 7839 brick_slab type bottom waterlogged false 7840 brick_slab type double waterlogged true 7841 brick_slab type double waterlogged false 7842 stone_brick_slab type top waterlogged true 7843 stone_brick_slab type top waterlogged false 7844 stone_brick_slab type bottom waterlogged true 7845 stone_brick_slab type bottom waterlogged false 7846 stone_brick_slab type double waterlogged true 7847 stone_brick_slab type double waterlogged false 7848 nether_brick_slab type top waterlogged true 7849 nether_brick_slab type top waterlogged false 7850 nether_brick_slab type bottom waterlogged true 7851 nether_brick_slab type bottom waterlogged false 7852 nether_brick_slab type double waterlogged true 7853 nether_brick_slab type double waterlogged false 7854 quartz_slab type top waterlogged true 7855 quartz_slab type top waterlogged false 7856 quartz_slab type bottom waterlogged true 7857 quartz_slab type bottom waterlogged false 7858 quartz_slab type double waterlogged true 7859 quartz_slab type double waterlogged false 7860 red_sandstone_slab type top waterlogged true 7861 red_sandstone_slab type top waterlogged false 7862 red_sandstone_slab type bottom waterlogged true 7863 red_sandstone_slab type bottom waterlogged false 7864 red_sandstone_slab type double waterlogged true 7865 red_sandstone_slab type double waterlogged false 7866 cut_red_sandstone_slab type top waterlogged true 7867 cut_red_sandstone_slab type top waterlogged false 7868 cut_red_sandstone_slab type bottom waterlogged true 7869 cut_red_sandstone_slab type bottom waterlogged false 7870 cut_red_sandstone_slab type double waterlogged true 7871 cut_red_sandstone_slab type double waterlogged false 7872 purpur_slab type top waterlogged true 7873 purpur_slab type top waterlogged false 7874 purpur_slab type bottom waterlogged true 7875 purpur_slab type bottom waterlogged false 7876 purpur_slab type double waterlogged true 7877 purpur_slab type double waterlogged false 7878 smooth_stone 7879 smooth_sandstone 7880 smooth_quartz 7881 smooth_red_sandstone 7882 spruce_fence_gate facing north powered true open true in_wall true 7883 spruce_fence_gate facing north powered false open true in_wall true 7884 spruce_fence_gate facing north powered true open false in_wall true 7885 spruce_fence_gate facing north powered false open false in_wall true 7886 spruce_fence_gate facing north powered true open true in_wall false 7887 spruce_fence_gate facing north powered false open true in_wall false 7888 spruce_fence_gate facing north powered true open false in_wall false 7889 spruce_fence_gate facing north powered false open false in_wall false 7890 spruce_fence_gate facing south powered true open true in_wall true 7891 spruce_fence_gate facing south powered false open true in_wall true 7892 spruce_fence_gate facing south powered true open false in_wall true 7893 spruce_fence_gate facing south powered false open false in_wall true 7894 spruce_fence_gate facing south powered true open true in_wall false 7895 spruce_fence_gate facing south powered false open true in_wall false 7896 spruce_fence_gate facing south powered true open false in_wall false 7897 spruce_fence_gate facing south powered false open false in_wall false 7898 spruce_fence_gate facing west powered true open true in_wall true 7899 spruce_fence_gate facing west powered false open true in_wall true 7900 spruce_fence_gate facing west powered true open false in_wall true 7901 spruce_fence_gate facing west powered false open false in_wall true 7902 spruce_fence_gate facing west powered true open true in_wall false 7903 spruce_fence_gate facing west powered false open true in_wall false 7904 spruce_fence_gate facing west powered true open false in_wall false 7905 spruce_fence_gate facing west powered false open false in_wall false 7906 spruce_fence_gate facing east powered true open true in_wall true 7907 spruce_fence_gate facing east powered false open true in_wall true 7908 spruce_fence_gate facing east powered true open false in_wall true 7909 spruce_fence_gate facing east powered false open false in_wall true 7910 spruce_fence_gate facing east powered true open true in_wall false 7911 spruce_fence_gate facing east powered false open true in_wall false 7912 spruce_fence_gate facing east powered true open false in_wall false 7913 spruce_fence_gate facing east powered false open false in_wall false 7914 birch_fence_gate facing north powered true open true in_wall true 7915 birch_fence_gate facing north powered false open true in_wall true 7916 birch_fence_gate facing north powered true open false in_wall true 7917 birch_fence_gate facing north powered false open false in_wall true 7918 birch_fence_gate facing north powered true open true in_wall false 7919 birch_fence_gate facing north powered false open true in_wall false 7920 birch_fence_gate facing north powered true open false in_wall false 7921 birch_fence_gate facing north powered false open false in_wall false 7922 birch_fence_gate facing south powered true open true in_wall true 7923 birch_fence_gate facing south powered false open true in_wall true 7924 birch_fence_gate facing south powered true open false in_wall true 7925 birch_fence_gate facing south powered false open false in_wall true 7926 birch_fence_gate facing south powered true open true in_wall false 7927 birch_fence_gate facing south powered false open true in_wall false 7928 birch_fence_gate facing south powered true open false in_wall false 7929 birch_fence_gate facing south powered false open false in_wall false 7930 birch_fence_gate facing west powered true open true in_wall true 7931 birch_fence_gate facing west powered false open true in_wall true 7932 birch_fence_gate facing west powered true open false in_wall true 7933 birch_fence_gate facing west powered false open false in_wall true 7934 birch_fence_gate facing west powered true open true in_wall false 7935 birch_fence_gate facing west powered false open true in_wall false 7936 birch_fence_gate facing west powered true open false in_wall false 7937 birch_fence_gate facing west powered false open false in_wall false 7938 birch_fence_gate facing east powered true open true in_wall true 7939 birch_fence_gate facing east powered false open true in_wall true 7940 birch_fence_gate facing east powered true open false in_wall true 7941 birch_fence_gate facing east powered false open false in_wall true 7942 birch_fence_gate facing east powered true open true in_wall false 7943 birch_fence_gate facing east powered false open true in_wall false 7944 birch_fence_gate facing east powered true open false in_wall false 7945 birch_fence_gate facing east powered false open false in_wall false 7946 jungle_fence_gate facing north powered true open true in_wall true 7947 jungle_fence_gate facing north powered false open true in_wall true 7948 jungle_fence_gate facing north powered true open false in_wall true 7949 jungle_fence_gate facing north powered false open false in_wall true 7950 jungle_fence_gate facing north powered true open true in_wall false 7951 jungle_fence_gate facing north powered false open true in_wall false 7952 jungle_fence_gate facing north powered true open false in_wall false 7953 jungle_fence_gate facing north powered false open false in_wall false 7954 jungle_fence_gate facing south powered true open true in_wall true 7955 jungle_fence_gate facing south powered false open true in_wall true 7956 jungle_fence_gate facing south powered true open false in_wall true 7957 jungle_fence_gate facing south powered false open false in_wall true 7958 jungle_fence_gate facing south powered true open true in_wall false 7959 jungle_fence_gate facing south powered false open true in_wall false 7960 jungle_fence_gate facing south powered true open false in_wall false 7961 jungle_fence_gate facing south powered false open false in_wall false 7962 jungle_fence_gate facing west powered true open true in_wall true 7963 jungle_fence_gate facing west powered false open true in_wall true 7964 jungle_fence_gate facing west powered true open false in_wall true 7965 jungle_fence_gate facing west powered false open false in_wall true 7966 jungle_fence_gate facing west powered true open true in_wall false 7967 jungle_fence_gate facing west powered false open true in_wall false 7968 jungle_fence_gate facing west powered true open false in_wall false 7969 jungle_fence_gate facing west powered false open false in_wall false 7970 jungle_fence_gate facing east powered true open true in_wall true 7971 jungle_fence_gate facing east powered false open true in_wall true 7972 jungle_fence_gate facing east powered true open false in_wall true 7973 jungle_fence_gate facing east powered false open false in_wall true 7974 jungle_fence_gate facing east powered true open true in_wall false 7975 jungle_fence_gate facing east powered false open true in_wall false 7976 jungle_fence_gate facing east powered true open false in_wall false 7977 jungle_fence_gate facing east powered false open false in_wall false 7978 acacia_fence_gate facing north powered true open true in_wall true 7979 acacia_fence_gate facing north powered false open true in_wall true 7980 acacia_fence_gate facing north powered true open false in_wall true 7981 acacia_fence_gate facing north powered false open false in_wall true 7982 acacia_fence_gate facing north powered true open true in_wall false 7983 acacia_fence_gate facing north powered false open true in_wall false 7984 acacia_fence_gate facing north powered true open false in_wall false 7985 acacia_fence_gate facing north powered false open false in_wall false 7986 acacia_fence_gate facing south powered true open true in_wall true 7987 acacia_fence_gate facing south powered false open true in_wall true 7988 acacia_fence_gate facing south powered true open false in_wall true 7989 acacia_fence_gate facing south powered false open false in_wall true 7990 acacia_fence_gate facing south powered true open true in_wall false 7991 acacia_fence_gate facing south powered false open true in_wall false 7992 acacia_fence_gate facing south powered true open false in_wall false 7993 acacia_fence_gate facing south powered false open false in_wall false 7994 acacia_fence_gate facing west powered true open true in_wall true 7995 acacia_fence_gate facing west powered false open true in_wall true 7996 acacia_fence_gate facing west powered true open false in_wall true 7997 acacia_fence_gate facing west powered false open false in_wall true 7998 acacia_fence_gate facing west powered true open true in_wall false 7999 acacia_fence_gate facing west powered false open true in_wall false 8000 acacia_fence_gate facing west powered true open false in_wall false 8001 acacia_fence_gate facing west powered false open false in_wall false 8002 acacia_fence_gate facing east powered true open true in_wall true 8003 acacia_fence_gate facing east powered false open true in_wall true 8004 acacia_fence_gate facing east powered true open false in_wall true 8005 acacia_fence_gate facing east powered false open false in_wall true 8006 acacia_fence_gate facing east powered true open true in_wall false 8007 acacia_fence_gate facing east powered false open true in_wall false 8008 acacia_fence_gate facing east powered true open false in_wall false 8009 acacia_fence_gate facing east powered false open false in_wall false 8010 dark_oak_fence_gate facing north powered true open true in_wall true 8011 dark_oak_fence_gate facing north powered false open true in_wall true 8012 dark_oak_fence_gate facing north powered true open false in_wall true 8013 dark_oak_fence_gate facing north powered false open false in_wall true 8014 dark_oak_fence_gate facing north powered true open true in_wall false 8015 dark_oak_fence_gate facing north powered false open true in_wall false 8016 dark_oak_fence_gate facing north powered true open false in_wall false 8017 dark_oak_fence_gate facing north powered false open false in_wall false 8018 dark_oak_fence_gate facing south powered true open true in_wall true 8019 dark_oak_fence_gate facing south powered false open true in_wall true 8020 dark_oak_fence_gate facing south powered true open false in_wall true 8021 dark_oak_fence_gate facing south powered false open false in_wall true 8022 dark_oak_fence_gate facing south powered true open true in_wall false 8023 dark_oak_fence_gate facing south powered false open true in_wall false 8024 dark_oak_fence_gate facing south powered true open false in_wall false 8025 dark_oak_fence_gate facing south powered false open false in_wall false 8026 dark_oak_fence_gate facing west powered true open true in_wall true 8027 dark_oak_fence_gate facing west powered false open true in_wall true 8028 dark_oak_fence_gate facing west powered true open false in_wall true 8029 dark_oak_fence_gate facing west powered false open false in_wall true 8030 dark_oak_fence_gate facing west powered true open true in_wall false 8031 dark_oak_fence_gate facing west powered false open true in_wall false 8032 dark_oak_fence_gate facing west powered true open false in_wall false 8033 dark_oak_fence_gate facing west powered false open false in_wall false 8034 dark_oak_fence_gate facing east powered true open true in_wall true 8035 dark_oak_fence_gate facing east powered false open true in_wall true 8036 dark_oak_fence_gate facing east powered true open false in_wall true 8037 dark_oak_fence_gate facing east powered false open false in_wall true 8038 dark_oak_fence_gate facing east powered true open true in_wall false 8039 dark_oak_fence_gate facing east powered false open true in_wall false 8040 dark_oak_fence_gate facing east powered true open false in_wall false 8041 dark_oak_fence_gate facing east powered false open false in_wall false 8042 spruce_fence waterlogged true south true east true north true west true 8043 spruce_fence waterlogged true south true east true north true west false 8044 spruce_fence waterlogged false south true east true north true west true 8045 spruce_fence waterlogged false south true east true north true west false 8046 spruce_fence waterlogged true south false east true north true west true 8047 spruce_fence waterlogged true south false east true north true west false 8048 spruce_fence waterlogged false south false east true north true west true 8049 spruce_fence waterlogged false south false east true north true west false 8050 spruce_fence waterlogged true south true east true north false west true 8051 spruce_fence waterlogged true south true east true north false west false 8052 spruce_fence waterlogged false south true east true north false west true 8053 spruce_fence waterlogged false south true east true north false west false 8054 spruce_fence waterlogged true south false east true north false west true 8055 spruce_fence waterlogged true south false east true north false west false 8056 spruce_fence waterlogged false south false east true north false west true 8057 spruce_fence waterlogged false south false east true north false west false 8058 spruce_fence waterlogged true south true east false north true west true 8059 spruce_fence waterlogged true south true east false north true west false 8060 spruce_fence waterlogged false south true east false north true west true 8061 spruce_fence waterlogged false south true east false north true west false 8062 spruce_fence waterlogged true south false east false north true west true 8063 spruce_fence waterlogged true south false east false north true west false 8064 spruce_fence waterlogged false south false east false north true west true 8065 spruce_fence waterlogged false south false east false north true west false 8066 spruce_fence waterlogged true south true east false north false west true 8067 spruce_fence waterlogged true south true east false north false west false 8068 spruce_fence waterlogged false south true east false north false west true 8069 spruce_fence waterlogged false south true east false north false west false 8070 spruce_fence waterlogged true south false east false north false west true 8071 spruce_fence waterlogged true south false east false north false west false 8072 spruce_fence waterlogged false south false east false north false west true 8073 spruce_fence waterlogged false south false east false north false west false 8074 birch_fence waterlogged true south true east true north true west true 8075 birch_fence waterlogged true south true east true north true west false 8076 birch_fence waterlogged false south true east true north true west true 8077 birch_fence waterlogged false south true east true north true west false 8078 birch_fence waterlogged true south false east true north true west true 8079 birch_fence waterlogged true south false east true north true west false 8080 birch_fence waterlogged false south false east true north true west true 8081 birch_fence waterlogged false south false east true north true west false 8082 birch_fence waterlogged true south true east true north false west true 8083 birch_fence waterlogged true south true east true north false west false 8084 birch_fence waterlogged false south true east true north false west true 8085 birch_fence waterlogged false south true east true north false west false 8086 birch_fence waterlogged true south false east true north false west true 8087 birch_fence waterlogged true south false east true north false west false 8088 birch_fence waterlogged false south false east true north false west true 8089 birch_fence waterlogged false south false east true north false west false 8090 birch_fence waterlogged true south true east false north true west true 8091 birch_fence waterlogged true south true east false north true west false 8092 birch_fence waterlogged false south true east false north true west true 8093 birch_fence waterlogged false south true east false north true west false 8094 birch_fence waterlogged true south false east false north true west true 8095 birch_fence waterlogged true south false east false north true west false 8096 birch_fence waterlogged false south false east false north true west true 8097 birch_fence waterlogged false south false east false north true west false 8098 birch_fence waterlogged true south true east false north false west true 8099 birch_fence waterlogged true south true east false north false west false 8100 birch_fence waterlogged false south true east false north false west true 8101 birch_fence waterlogged false south true east false north false west false 8102 birch_fence waterlogged true south false east false north false west true 8103 birch_fence waterlogged true south false east false north false west false 8104 birch_fence waterlogged false south false east false north false west true 8105 birch_fence waterlogged false south false east false north false west false 8106 jungle_fence waterlogged true south true east true north true west true 8107 jungle_fence waterlogged true south true east true north true west false 8108 jungle_fence waterlogged false south true east true north true west true 8109 jungle_fence waterlogged false south true east true north true west false 8110 jungle_fence waterlogged true south false east true north true west true 8111 jungle_fence waterlogged true south false east true north true west false 8112 jungle_fence waterlogged false south false east true north true west true 8113 jungle_fence waterlogged false south false east true north true west false 8114 jungle_fence waterlogged true south true east true north false west true 8115 jungle_fence waterlogged true south true east true north false west false 8116 jungle_fence waterlogged false south true east true north false west true 8117 jungle_fence waterlogged false south true east true north false west false 8118 jungle_fence waterlogged true south false east true north false west true 8119 jungle_fence waterlogged true south false east true north false west false 8120 jungle_fence waterlogged false south false east true north false west true 8121 jungle_fence waterlogged false south false east true north false west false 8122 jungle_fence waterlogged true south true east false north true west true 8123 jungle_fence waterlogged true south true east false north true west false 8124 jungle_fence waterlogged false south true east false north true west true 8125 jungle_fence waterlogged false south true east false north true west false 8126 jungle_fence waterlogged true south false east false north true west true 8127 jungle_fence waterlogged true south false east false north true west false 8128 jungle_fence waterlogged false south false east false north true west true 8129 jungle_fence waterlogged false south false east false north true west false 8130 jungle_fence waterlogged true south true east false north false west true 8131 jungle_fence waterlogged true south true east false north false west false 8132 jungle_fence waterlogged false south true east false north false west true 8133 jungle_fence waterlogged false south true east false north false west false 8134 jungle_fence waterlogged true south false east false north false west true 8135 jungle_fence waterlogged true south false east false north false west false 8136 jungle_fence waterlogged false south false east false north false west true 8137 jungle_fence waterlogged false south false east false north false west false 8138 acacia_fence waterlogged true south true east true north true west true 8139 acacia_fence waterlogged true south true east true north true west false 8140 acacia_fence waterlogged false south true east true north true west true 8141 acacia_fence waterlogged false south true east true north true west false 8142 acacia_fence waterlogged true south false east true north true west true 8143 acacia_fence waterlogged true south false east true north true west false 8144 acacia_fence waterlogged false south false east true north true west true 8145 acacia_fence waterlogged false south false east true north true west false 8146 acacia_fence waterlogged true south true east true north false west true 8147 acacia_fence waterlogged true south true east true north false west false 8148 acacia_fence waterlogged false south true east true north false west true 8149 acacia_fence waterlogged false south true east true north false west false 8150 acacia_fence waterlogged true south false east true north false west true 8151 acacia_fence waterlogged true south false east true north false west false 8152 acacia_fence waterlogged false south false east true north false west true 8153 acacia_fence waterlogged false south false east true north false west false 8154 acacia_fence waterlogged true south true east false north true west true 8155 acacia_fence waterlogged true south true east false north true west false 8156 acacia_fence waterlogged false south true east false north true west true 8157 acacia_fence waterlogged false south true east false north true west false 8158 acacia_fence waterlogged true south false east false north true west true 8159 acacia_fence waterlogged true south false east false north true west false 8160 acacia_fence waterlogged false south false east false north true west true 8161 acacia_fence waterlogged false south false east false north true west false 8162 acacia_fence waterlogged true south true east false north false west true 8163 acacia_fence waterlogged true south true east false north false west false 8164 acacia_fence waterlogged false south true east false north false west true 8165 acacia_fence waterlogged false south true east false north false west false 8166 acacia_fence waterlogged true south false east false north false west true 8167 acacia_fence waterlogged true south false east false north false west false 8168 acacia_fence waterlogged false south false east false north false west true 8169 acacia_fence waterlogged false south false east false north false west false 8170 dark_oak_fence waterlogged true south true east true north true west true 8171 dark_oak_fence waterlogged true south true east true north true west false 8172 dark_oak_fence waterlogged false south true east true north true west true 8173 dark_oak_fence waterlogged false south true east true north true west false 8174 dark_oak_fence waterlogged true south false east true north true west true 8175 dark_oak_fence waterlogged true south false east true north true west false 8176 dark_oak_fence waterlogged false south false east true north true west true 8177 dark_oak_fence waterlogged false south false east true north true west false 8178 dark_oak_fence waterlogged true south true east true north false west true 8179 dark_oak_fence waterlogged true south true east true north false west false 8180 dark_oak_fence waterlogged false south true east true north false west true 8181 dark_oak_fence waterlogged false south true east true north false west false 8182 dark_oak_fence waterlogged true south false east true north false west true 8183 dark_oak_fence waterlogged true south false east true north false west false 8184 dark_oak_fence waterlogged false south false east true north false west true 8185 dark_oak_fence waterlogged false south false east true north false west false 8186 dark_oak_fence waterlogged true south true east false north true west true 8187 dark_oak_fence waterlogged true south true east false north true west false 8188 dark_oak_fence waterlogged false south true east false north true west true 8189 dark_oak_fence waterlogged false south true east false north true west false 8190 dark_oak_fence waterlogged true south false east false north true west true 8191 dark_oak_fence waterlogged true south false east false north true west false 8192 dark_oak_fence waterlogged false south false east false north true west true 8193 dark_oak_fence waterlogged false south false east false north true west false 8194 dark_oak_fence waterlogged true south true east false north false west true 8195 dark_oak_fence waterlogged true south true east false north false west false 8196 dark_oak_fence waterlogged false south true east false north false west true 8197 dark_oak_fence waterlogged false south true east false north false west false 8198 dark_oak_fence waterlogged true south false east false north false west true 8199 dark_oak_fence waterlogged true south false east false north false west false 8200 dark_oak_fence waterlogged false south false east false north false west true 8201 dark_oak_fence waterlogged false south false east false north false west false 8202 spruce_door hinge left half upper facing north powered true open true 8203 spruce_door hinge left half upper facing north powered false open true 8204 spruce_door hinge left half upper facing north powered true open false 8205 spruce_door hinge left half upper facing north powered false open false 8206 spruce_door hinge right half upper facing north powered true open true 8207 spruce_door hinge right half upper facing north powered false open true 8208 spruce_door hinge right half upper facing north powered true open false 8209 spruce_door hinge right half upper facing north powered false open false 8210 spruce_door hinge left half lower facing north powered true open true 8211 spruce_door hinge left half lower facing north powered false open true 8212 spruce_door hinge left half lower facing north powered true open false 8213 spruce_door hinge left half lower facing north powered false open false 8214 spruce_door hinge right half lower facing north powered true open true 8215 spruce_door hinge right half lower facing north powered false open true 8216 spruce_door hinge right half lower facing north powered true open false 8217 spruce_door hinge right half lower facing north powered false open false 8218 spruce_door hinge left half upper facing south powered true open true 8219 spruce_door hinge left half upper facing south powered false open true 8220 spruce_door hinge left half upper facing south powered true open false 8221 spruce_door hinge left half upper facing south powered false open false 8222 spruce_door hinge right half upper facing south powered true open true 8223 spruce_door hinge right half upper facing south powered false open true 8224 spruce_door hinge right half upper facing south powered true open false 8225 spruce_door hinge right half upper facing south powered false open false 8226 spruce_door hinge left half lower facing south powered true open true 8227 spruce_door hinge left half lower facing south powered false open true 8228 spruce_door hinge left half lower facing south powered true open false 8229 spruce_door hinge left half lower facing south powered false open false 8230 spruce_door hinge right half lower facing south powered true open true 8231 spruce_door hinge right half lower facing south powered false open true 8232 spruce_door hinge right half lower facing south powered true open false 8233 spruce_door hinge right half lower facing south powered false open false 8234 spruce_door hinge left half upper facing west powered true open true 8235 spruce_door hinge left half upper facing west powered false open true 8236 spruce_door hinge left half upper facing west powered true open false 8237 spruce_door hinge left half upper facing west powered false open false 8238 spruce_door hinge right half upper facing west powered true open true 8239 spruce_door hinge right half upper facing west powered false open true 8240 spruce_door hinge right half upper facing west powered true open false 8241 spruce_door hinge right half upper facing west powered false open false 8242 spruce_door hinge left half lower facing west powered true open true 8243 spruce_door hinge left half lower facing west powered false open true 8244 spruce_door hinge left half lower facing west powered true open false 8245 spruce_door hinge left half lower facing west powered false open false 8246 spruce_door hinge right half lower facing west powered true open true 8247 spruce_door hinge right half lower facing west powered false open true 8248 spruce_door hinge right half lower facing west powered true open false 8249 spruce_door hinge right half lower facing west powered false open false 8250 spruce_door hinge left half upper facing east powered true open true 8251 spruce_door hinge left half upper facing east powered false open true 8252 spruce_door hinge left half upper facing east powered true open false 8253 spruce_door hinge left half upper facing east powered false open false 8254 spruce_door hinge right half upper facing east powered true open true 8255 spruce_door hinge right half upper facing east powered false open true 8256 spruce_door hinge right half upper facing east powered true open false 8257 spruce_door hinge right half upper facing east powered false open false 8258 spruce_door hinge left half lower facing east powered true open true 8259 spruce_door hinge left half lower facing east powered false open true 8260 spruce_door hinge left half lower facing east powered true open false 8261 spruce_door hinge left half lower facing east powered false open false 8262 spruce_door hinge right half lower facing east powered true open true 8263 spruce_door hinge right half lower facing east powered false open true 8264 spruce_door hinge right half lower facing east powered true open false 8265 spruce_door hinge right half lower facing east powered false open false 8266 birch_door hinge left half upper facing north powered true open true 8267 birch_door hinge left half upper facing north powered false open true 8268 birch_door hinge left half upper facing north powered true open false 8269 birch_door hinge left half upper facing north powered false open false 8270 birch_door hinge right half upper facing north powered true open true 8271 birch_door hinge right half upper facing north powered false open true 8272 birch_door hinge right half upper facing north powered true open false 8273 birch_door hinge right half upper facing north powered false open false 8274 birch_door hinge left half lower facing north powered true open true 8275 birch_door hinge left half lower facing north powered false open true 8276 birch_door hinge left half lower facing north powered true open false 8277 birch_door hinge left half lower facing north powered false open false 8278 birch_door hinge right half lower facing north powered true open true 8279 birch_door hinge right half lower facing north powered false open true 8280 birch_door hinge right half lower facing north powered true open false 8281 birch_door hinge right half lower facing north powered false open false 8282 birch_door hinge left half upper facing south powered true open true 8283 birch_door hinge left half upper facing south powered false open true 8284 birch_door hinge left half upper facing south powered true open false 8285 birch_door hinge left half upper facing south powered false open false 8286 birch_door hinge right half upper facing south powered true open true 8287 birch_door hinge right half upper facing south powered false open true 8288 birch_door hinge right half upper facing south powered true open false 8289 birch_door hinge right half upper facing south powered false open false 8290 birch_door hinge left half lower facing south powered true open true 8291 birch_door hinge left half lower facing south powered false open true 8292 birch_door hinge left half lower facing south powered true open false 8293 birch_door hinge left half lower facing south powered false open false 8294 birch_door hinge right half lower facing south powered true open true 8295 birch_door hinge right half lower facing south powered false open true 8296 birch_door hinge right half lower facing south powered true open false 8297 birch_door hinge right half lower facing south powered false open false 8298 birch_door hinge left half upper facing west powered true open true 8299 birch_door hinge left half upper facing west powered false open true 8300 birch_door hinge left half upper facing west powered true open false 8301 birch_door hinge left half upper facing west powered false open false 8302 birch_door hinge right half upper facing west powered true open true 8303 birch_door hinge right half upper facing west powered false open true 8304 birch_door hinge right half upper facing west powered true open false 8305 birch_door hinge right half upper facing west powered false open false 8306 birch_door hinge left half lower facing west powered true open true 8307 birch_door hinge left half lower facing west powered false open true 8308 birch_door hinge left half lower facing west powered true open false 8309 birch_door hinge left half lower facing west powered false open false 8310 birch_door hinge right half lower facing west powered true open true 8311 birch_door hinge right half lower facing west powered false open true 8312 birch_door hinge right half lower facing west powered true open false 8313 birch_door hinge right half lower facing west powered false open false 8314 birch_door hinge left half upper facing east powered true open true 8315 birch_door hinge left half upper facing east powered false open true 8316 birch_door hinge left half upper facing east powered true open false 8317 birch_door hinge left half upper facing east powered false open false 8318 birch_door hinge right half upper facing east powered true open true 8319 birch_door hinge right half upper facing east powered false open true 8320 birch_door hinge right half upper facing east powered true open false 8321 birch_door hinge right half upper facing east powered false open false 8322 birch_door hinge left half lower facing east powered true open true 8323 birch_door hinge left half lower facing east powered false open true 8324 birch_door hinge left half lower facing east powered true open false 8325 birch_door hinge left half lower facing east powered false open false 8326 birch_door hinge right half lower facing east powered true open true 8327 birch_door hinge right half lower facing east powered false open true 8328 birch_door hinge right half lower facing east powered true open false 8329 birch_door hinge right half lower facing east powered false open false 8330 jungle_door hinge left half upper facing north powered true open true 8331 jungle_door hinge left half upper facing north powered false open true 8332 jungle_door hinge left half upper facing north powered true open false 8333 jungle_door hinge left half upper facing north powered false open false 8334 jungle_door hinge right half upper facing north powered true open true 8335 jungle_door hinge right half upper facing north powered false open true 8336 jungle_door hinge right half upper facing north powered true open false 8337 jungle_door hinge right half upper facing north powered false open false 8338 jungle_door hinge left half lower facing north powered true open true 8339 jungle_door hinge left half lower facing north powered false open true 8340 jungle_door hinge left half lower facing north powered true open false 8341 jungle_door hinge left half lower facing north powered false open false 8342 jungle_door hinge right half lower facing north powered true open true 8343 jungle_door hinge right half lower facing north powered false open true 8344 jungle_door hinge right half lower facing north powered true open false 8345 jungle_door hinge right half lower facing north powered false open false 8346 jungle_door hinge left half upper facing south powered true open true 8347 jungle_door hinge left half upper facing south powered false open true 8348 jungle_door hinge left half upper facing south powered true open false 8349 jungle_door hinge left half upper facing south powered false open false 8350 jungle_door hinge right half upper facing south powered true open true 8351 jungle_door hinge right half upper facing south powered false open true 8352 jungle_door hinge right half upper facing south powered true open false 8353 jungle_door hinge right half upper facing south powered false open false 8354 jungle_door hinge left half lower facing south powered true open true 8355 jungle_door hinge left half lower facing south powered false open true 8356 jungle_door hinge left half lower facing south powered true open false 8357 jungle_door hinge left half lower facing south powered false open false 8358 jungle_door hinge right half lower facing south powered true open true 8359 jungle_door hinge right half lower facing south powered false open true 8360 jungle_door hinge right half lower facing south powered true open false 8361 jungle_door hinge right half lower facing south powered false open false 8362 jungle_door hinge left half upper facing west powered true open true 8363 jungle_door hinge left half upper facing west powered false open true 8364 jungle_door hinge left half upper facing west powered true open false 8365 jungle_door hinge left half upper facing west powered false open false 8366 jungle_door hinge right half upper facing west powered true open true 8367 jungle_door hinge right half upper facing west powered false open true 8368 jungle_door hinge right half upper facing west powered true open false 8369 jungle_door hinge right half upper facing west powered false open false 8370 jungle_door hinge left half lower facing west powered true open true 8371 jungle_door hinge left half lower facing west powered false open true 8372 jungle_door hinge left half lower facing west powered true open false 8373 jungle_door hinge left half lower facing west powered false open false 8374 jungle_door hinge right half lower facing west powered true open true 8375 jungle_door hinge right half lower facing west powered false open true 8376 jungle_door hinge right half lower facing west powered true open false 8377 jungle_door hinge right half lower facing west powered false open false 8378 jungle_door hinge left half upper facing east powered true open true 8379 jungle_door hinge left half upper facing east powered false open true 8380 jungle_door hinge left half upper facing east powered true open false 8381 jungle_door hinge left half upper facing east powered false open false 8382 jungle_door hinge right half upper facing east powered true open true 8383 jungle_door hinge right half upper facing east powered false open true 8384 jungle_door hinge right half upper facing east powered true open false 8385 jungle_door hinge right half upper facing east powered false open false 8386 jungle_door hinge left half lower facing east powered true open true 8387 jungle_door hinge left half lower facing east powered false open true 8388 jungle_door hinge left half lower facing east powered true open false 8389 jungle_door hinge left half lower facing east powered false open false 8390 jungle_door hinge right half lower facing east powered true open true 8391 jungle_door hinge right half lower facing east powered false open true 8392 jungle_door hinge right half lower facing east powered true open false 8393 jungle_door hinge right half lower facing east powered false open false 8394 acacia_door hinge left half upper facing north powered true open true 8395 acacia_door hinge left half upper facing north powered false open true 8396 acacia_door hinge left half upper facing north powered true open false 8397 acacia_door hinge left half upper facing north powered false open false 8398 acacia_door hinge right half upper facing north powered true open true 8399 acacia_door hinge right half upper facing north powered false open true 8400 acacia_door hinge right half upper facing north powered true open false 8401 acacia_door hinge right half upper facing north powered false open false 8402 acacia_door hinge left half lower facing north powered true open true 8403 acacia_door hinge left half lower facing north powered false open true 8404 acacia_door hinge left half lower facing north powered true open false 8405 acacia_door hinge left half lower facing north powered false open false 8406 acacia_door hinge right half lower facing north powered true open true 8407 acacia_door hinge right half lower facing north powered false open true 8408 acacia_door hinge right half lower facing north powered true open false 8409 acacia_door hinge right half lower facing north powered false open false 8410 acacia_door hinge left half upper facing south powered true open true 8411 acacia_door hinge left half upper facing south powered false open true 8412 acacia_door hinge left half upper facing south powered true open false 8413 acacia_door hinge left half upper facing south powered false open false 8414 acacia_door hinge right half upper facing south powered true open true 8415 acacia_door hinge right half upper facing south powered false open true 8416 acacia_door hinge right half upper facing south powered true open false 8417 acacia_door hinge right half upper facing south powered false open false 8418 acacia_door hinge left half lower facing south powered true open true 8419 acacia_door hinge left half lower facing south powered false open true 8420 acacia_door hinge left half lower facing south powered true open false 8421 acacia_door hinge left half lower facing south powered false open false 8422 acacia_door hinge right half lower facing south powered true open true 8423 acacia_door hinge right half lower facing south powered false open true 8424 acacia_door hinge right half lower facing south powered true open false 8425 acacia_door hinge right half lower facing south powered false open false 8426 acacia_door hinge left half upper facing west powered true open true 8427 acacia_door hinge left half upper facing west powered false open true 8428 acacia_door hinge left half upper facing west powered true open false 8429 acacia_door hinge left half upper facing west powered false open false 8430 acacia_door hinge right half upper facing west powered true open true 8431 acacia_door hinge right half upper facing west powered false open true 8432 acacia_door hinge right half upper facing west powered true open false 8433 acacia_door hinge right half upper facing west powered false open false 8434 acacia_door hinge left half lower facing west powered true open true 8435 acacia_door hinge left half lower facing west powered false open true 8436 acacia_door hinge left half lower facing west powered true open false 8437 acacia_door hinge left half lower facing west powered false open false 8438 acacia_door hinge right half lower facing west powered true open true 8439 acacia_door hinge right half lower facing west powered false open true 8440 acacia_door hinge right half lower facing west powered true open false 8441 acacia_door hinge right half lower facing west powered false open false 8442 acacia_door hinge left half upper facing east powered true open true 8443 acacia_door hinge left half upper facing east powered false open true 8444 acacia_door hinge left half upper facing east powered true open false 8445 acacia_door hinge left half upper facing east powered false open false 8446 acacia_door hinge right half upper facing east powered true open true 8447 acacia_door hinge right half upper facing east powered false open true 8448 acacia_door hinge right half upper facing east powered true open false 8449 acacia_door hinge right half upper facing east powered false open false 8450 acacia_door hinge left half lower facing east powered true open true 8451 acacia_door hinge left half lower facing east powered false open true 8452 acacia_door hinge left half lower facing east powered true open false 8453 acacia_door hinge left half lower facing east powered false open false 8454 acacia_door hinge right half lower facing east powered true open true 8455 acacia_door hinge right half lower facing east powered false open true 8456 acacia_door hinge right half lower facing east powered true open false 8457 acacia_door hinge right half lower facing east powered false open false 8458 dark_oak_door hinge left half upper facing north powered true open true 8459 dark_oak_door hinge left half upper facing north powered false open true 8460 dark_oak_door hinge left half upper facing north powered true open false 8461 dark_oak_door hinge left half upper facing north powered false open false 8462 dark_oak_door hinge right half upper facing north powered true open true 8463 dark_oak_door hinge right half upper facing north powered false open true 8464 dark_oak_door hinge right half upper facing north powered true open false 8465 dark_oak_door hinge right half upper facing north powered false open false 8466 dark_oak_door hinge left half lower facing north powered true open true 8467 dark_oak_door hinge left half lower facing north powered false open true 8468 dark_oak_door hinge left half lower facing north powered true open false 8469 dark_oak_door hinge left half lower facing north powered false open false 8470 dark_oak_door hinge right half lower facing north powered true open true 8471 dark_oak_door hinge right half lower facing north powered false open true 8472 dark_oak_door hinge right half lower facing north powered true open false 8473 dark_oak_door hinge right half lower facing north powered false open false 8474 dark_oak_door hinge left half upper facing south powered true open true 8475 dark_oak_door hinge left half upper facing south powered false open true 8476 dark_oak_door hinge left half upper facing south powered true open false 8477 dark_oak_door hinge left half upper facing south powered false open false 8478 dark_oak_door hinge right half upper facing south powered true open true 8479 dark_oak_door hinge right half upper facing south powered false open true 8480 dark_oak_door hinge right half upper facing south powered true open false 8481 dark_oak_door hinge right half upper facing south powered false open false 8482 dark_oak_door hinge left half lower facing south powered true open true 8483 dark_oak_door hinge left half lower facing south powered false open true 8484 dark_oak_door hinge left half lower facing south powered true open false 8485 dark_oak_door hinge left half lower facing south powered false open false 8486 dark_oak_door hinge right half lower facing south powered true open true 8487 dark_oak_door hinge right half lower facing south powered false open true 8488 dark_oak_door hinge right half lower facing south powered true open false 8489 dark_oak_door hinge right half lower facing south powered false open false 8490 dark_oak_door hinge left half upper facing west powered true open true 8491 dark_oak_door hinge left half upper facing west powered false open true 8492 dark_oak_door hinge left half upper facing west powered true open false 8493 dark_oak_door hinge left half upper facing west powered false open false 8494 dark_oak_door hinge right half upper facing west powered true open true 8495 dark_oak_door hinge right half upper facing west powered false open true 8496 dark_oak_door hinge right half upper facing west powered true open false 8497 dark_oak_door hinge right half upper facing west powered false open false 8498 dark_oak_door hinge left half lower facing west powered true open true 8499 dark_oak_door hinge left half lower facing west powered false open true 8500 dark_oak_door hinge left half lower facing west powered true open false 8501 dark_oak_door hinge left half lower facing west powered false open false 8502 dark_oak_door hinge right half lower facing west powered true open true 8503 dark_oak_door hinge right half lower facing west powered false open true 8504 dark_oak_door hinge right half lower facing west powered true open false 8505 dark_oak_door hinge right half lower facing west powered false open false 8506 dark_oak_door hinge left half upper facing east powered true open true 8507 dark_oak_door hinge left half upper facing east powered false open true 8508 dark_oak_door hinge left half upper facing east powered true open false 8509 dark_oak_door hinge left half upper facing east powered false open false 8510 dark_oak_door hinge right half upper facing east powered true open true 8511 dark_oak_door hinge right half upper facing east powered false open true 8512 dark_oak_door hinge right half upper facing east powered true open false 8513 dark_oak_door hinge right half upper facing east powered false open false 8514 dark_oak_door hinge left half lower facing east powered true open true 8515 dark_oak_door hinge left half lower facing east powered false open true 8516 dark_oak_door hinge left half lower facing east powered true open false 8517 dark_oak_door hinge left half lower facing east powered false open false 8518 dark_oak_door hinge right half lower facing east powered true open true 8519 dark_oak_door hinge right half lower facing east powered false open true 8520 dark_oak_door hinge right half lower facing east powered true open false 8521 dark_oak_door hinge right half lower facing east powered false open false 8522 end_rod facing north 8523 end_rod facing east 8524 end_rod facing south 8525 end_rod facing west 8526 end_rod facing up 8527 end_rod facing down 8528 chorus_plant up true south true east true north true down true west true 8529 chorus_plant up true south true east true north true down true west false 8530 chorus_plant up false south true east true north true down true west true 8531 chorus_plant up false south true east true north true down true west false 8532 chorus_plant up true south false east true north true down true west true 8533 chorus_plant up true south false east true north true down true west false 8534 chorus_plant up false south false east true north true down true west true 8535 chorus_plant up false south false east true north true down true west false 8536 chorus_plant up true south true east true north false down true west true 8537 chorus_plant up true south true east true north false down true west false 8538 chorus_plant up false south true east true north false down true west true 8539 chorus_plant up false south true east true north false down true west false 8540 chorus_plant up true south false east true north false down true west true 8541 chorus_plant up true south false east true north false down true west false 8542 chorus_plant up false south false east true north false down true west true 8543 chorus_plant up false south false east true north false down true west false 8544 chorus_plant up true south true east false north true down true west true 8545 chorus_plant up true south true east false north true down true west false 8546 chorus_plant up false south true east false north true down true west true 8547 chorus_plant up false south true east false north true down true west false 8548 chorus_plant up true south false east false north true down true west true 8549 chorus_plant up true south false east false north true down true west false 8550 chorus_plant up false south false east false north true down true west true 8551 chorus_plant up false south false east false north true down true west false 8552 chorus_plant up true south true east false north false down true west true 8553 chorus_plant up true south true east false north false down true west false 8554 chorus_plant up false south true east false north false down true west true 8555 chorus_plant up false south true east false north false down true west false 8556 chorus_plant up true south false east false north false down true west true 8557 chorus_plant up true south false east false north false down true west false 8558 chorus_plant up false south false east false north false down true west true 8559 chorus_plant up false south false east false north false down true west false 8560 chorus_plant up true south true east true north true down false west true 8561 chorus_plant up true south true east true north true down false west false 8562 chorus_plant up false south true east true north true down false west true 8563 chorus_plant up false south true east true north true down false west false 8564 chorus_plant up true south false east true north true down false west true 8565 chorus_plant up true south false east true north true down false west false 8566 chorus_plant up false south false east true north true down false west true 8567 chorus_plant up false south false east true north true down false west false 8568 chorus_plant up true south true east true north false down false west true 8569 chorus_plant up true south true east true north false down false west false 8570 chorus_plant up false south true east true north false down false west true 8571 chorus_plant up false south true east true north false down false west false 8572 chorus_plant up true south false east true north false down false west true 8573 chorus_plant up true south false east true north false down false west false 8574 chorus_plant up false south false east true north false down false west true 8575 chorus_plant up false south false east true north false down false west false 8576 chorus_plant up true south true east false north true down false west true 8577 chorus_plant up true south true east false north true down false west false 8578 chorus_plant up false south true east false north true down false west true 8579 chorus_plant up false south true east false north true down false west false 8580 chorus_plant up true south false east false north true down false west true 8581 chorus_plant up true south false east false north true down false west false 8582 chorus_plant up false south false east false north true down false west true 8583 chorus_plant up false south false east false north true down false west false 8584 chorus_plant up true south true east false north false down false west true 8585 chorus_plant up true south true east false north false down false west false 8586 chorus_plant up false south true east false north false down false west true 8587 chorus_plant up false south true east false north false down false west false 8588 chorus_plant up true south false east false north false down false west true 8589 chorus_plant up true south false east false north false down false west false 8590 chorus_plant up false south false east false north false down false west true 8591 chorus_plant up false south false east false north false down false west false 8592 chorus_flower age 0 8593 chorus_flower age 1 8594 chorus_flower age 2 8595 chorus_flower age 3 8596 chorus_flower age 4 8597 chorus_flower age 5 8598 purpur_block 8599 purpur_pillar axis x 8600 purpur_pillar axis y 8601 purpur_pillar axis z 8602 purpur_stairs facing north waterlogged true shape straight half top 8603 purpur_stairs facing north waterlogged false shape straight half top 8604 purpur_stairs facing north waterlogged true shape inner_left half top 8605 purpur_stairs facing north waterlogged false shape inner_left half top 8606 purpur_stairs facing north waterlogged true shape inner_right half top 8607 purpur_stairs facing north waterlogged false shape inner_right half top 8608 purpur_stairs facing north waterlogged true shape outer_left half top 8609 purpur_stairs facing north waterlogged false shape outer_left half top 8610 purpur_stairs facing north waterlogged true shape outer_right half top 8611 purpur_stairs facing north waterlogged false shape outer_right half top 8612 purpur_stairs facing north waterlogged true shape straight half bottom 8613 purpur_stairs facing north waterlogged false shape straight half bottom 8614 purpur_stairs facing north waterlogged true shape inner_left half bottom 8615 purpur_stairs facing north waterlogged false shape inner_left half bottom 8616 purpur_stairs facing north waterlogged true shape inner_right half bottom 8617 purpur_stairs facing north waterlogged false shape inner_right half bottom 8618 purpur_stairs facing north waterlogged true shape outer_left half bottom 8619 purpur_stairs facing north waterlogged false shape outer_left half bottom 8620 purpur_stairs facing north waterlogged true shape outer_right half bottom 8621 purpur_stairs facing north waterlogged false shape outer_right half bottom 8622 purpur_stairs facing south waterlogged true shape straight half top 8623 purpur_stairs facing south waterlogged false shape straight half top 8624 purpur_stairs facing south waterlogged true shape inner_left half top 8625 purpur_stairs facing south waterlogged false shape inner_left half top 8626 purpur_stairs facing south waterlogged true shape inner_right half top 8627 purpur_stairs facing south waterlogged false shape inner_right half top 8628 purpur_stairs facing south waterlogged true shape outer_left half top 8629 purpur_stairs facing south waterlogged false shape outer_left half top 8630 purpur_stairs facing south waterlogged true shape outer_right half top 8631 purpur_stairs facing south waterlogged false shape outer_right half top 8632 purpur_stairs facing south waterlogged true shape straight half bottom 8633 purpur_stairs facing south waterlogged false shape straight half bottom 8634 purpur_stairs facing south waterlogged true shape inner_left half bottom 8635 purpur_stairs facing south waterlogged false shape inner_left half bottom 8636 purpur_stairs facing south waterlogged true shape inner_right half bottom 8637 purpur_stairs facing south waterlogged false shape inner_right half bottom 8638 purpur_stairs facing south waterlogged true shape outer_left half bottom 8639 purpur_stairs facing south waterlogged false shape outer_left half bottom 8640 purpur_stairs facing south waterlogged true shape outer_right half bottom 8641 purpur_stairs facing south waterlogged false shape outer_right half bottom 8642 purpur_stairs facing west waterlogged true shape straight half top 8643 purpur_stairs facing west waterlogged false shape straight half top 8644 purpur_stairs facing west waterlogged true shape inner_left half top 8645 purpur_stairs facing west waterlogged false shape inner_left half top 8646 purpur_stairs facing west waterlogged true shape inner_right half top 8647 purpur_stairs facing west waterlogged false shape inner_right half top 8648 purpur_stairs facing west waterlogged true shape outer_left half top 8649 purpur_stairs facing west waterlogged false shape outer_left half top 8650 purpur_stairs facing west waterlogged true shape outer_right half top 8651 purpur_stairs facing west waterlogged false shape outer_right half top 8652 purpur_stairs facing west waterlogged true shape straight half bottom 8653 purpur_stairs facing west waterlogged false shape straight half bottom 8654 purpur_stairs facing west waterlogged true shape inner_left half bottom 8655 purpur_stairs facing west waterlogged false shape inner_left half bottom 8656 purpur_stairs facing west waterlogged true shape inner_right half bottom 8657 purpur_stairs facing west waterlogged false shape inner_right half bottom 8658 purpur_stairs facing west waterlogged true shape outer_left half bottom 8659 purpur_stairs facing west waterlogged false shape outer_left half bottom 8660 purpur_stairs facing west waterlogged true shape outer_right half bottom 8661 purpur_stairs facing west waterlogged false shape outer_right half bottom 8662 purpur_stairs facing east waterlogged true shape straight half top 8663 purpur_stairs facing east waterlogged false shape straight half top 8664 purpur_stairs facing east waterlogged true shape inner_left half top 8665 purpur_stairs facing east waterlogged false shape inner_left half top 8666 purpur_stairs facing east waterlogged true shape inner_right half top 8667 purpur_stairs facing east waterlogged false shape inner_right half top 8668 purpur_stairs facing east waterlogged true shape outer_left half top 8669 purpur_stairs facing east waterlogged false shape outer_left half top 8670 purpur_stairs facing east waterlogged true shape outer_right half top 8671 purpur_stairs facing east waterlogged false shape outer_right half top 8672 purpur_stairs facing east waterlogged true shape straight half bottom 8673 purpur_stairs facing east waterlogged false shape straight half bottom 8674 purpur_stairs facing east waterlogged true shape inner_left half bottom 8675 purpur_stairs facing east waterlogged false shape inner_left half bottom 8676 purpur_stairs facing east waterlogged true shape inner_right half bottom 8677 purpur_stairs facing east waterlogged false shape inner_right half bottom 8678 purpur_stairs facing east waterlogged true shape outer_left half bottom 8679 purpur_stairs facing east waterlogged false shape outer_left half bottom 8680 purpur_stairs facing east waterlogged true shape outer_right half bottom 8681 purpur_stairs facing east waterlogged false shape outer_right half bottom 8682 end_stone_bricks 8683 beetroots age 0 8684 beetroots age 1 8685 beetroots age 2 8686 beetroots age 3 8687 grass_path 8688 end_gateway 8689 repeating_command_block conditional true facing north 8690 repeating_command_block conditional true facing east 8691 repeating_command_block conditional true facing south 8692 repeating_command_block conditional true facing west 8693 repeating_command_block conditional true facing up 8694 repeating_command_block conditional true facing down 8695 repeating_command_block conditional false facing north 8696 repeating_command_block conditional false facing east 8697 repeating_command_block conditional false facing south 8698 repeating_command_block conditional false facing west 8699 repeating_command_block conditional false facing up 8700 repeating_command_block conditional false facing down 8701 chain_command_block conditional true facing north 8702 chain_command_block conditional true facing east 8703 chain_command_block conditional true facing south 8704 chain_command_block conditional true facing west 8705 chain_command_block conditional true facing up 8706 chain_command_block conditional true facing down 8707 chain_command_block conditional false facing north 8708 chain_command_block conditional false facing east 8709 chain_command_block conditional false facing south 8710 chain_command_block conditional false facing west 8711 chain_command_block conditional false facing up 8712 chain_command_block conditional false facing down 8713 frosted_ice age 0 8714 frosted_ice age 1 8715 frosted_ice age 2 8716 frosted_ice age 3 8717 magma_block 8718 nether_wart_block 8719 red_nether_bricks 8720 bone_block axis x 8721 bone_block axis y 8722 bone_block axis z 8723 structure_void 8724 observer facing north powered true 8725 observer facing north powered false 8726 observer facing east powered true 8727 observer facing east powered false 8728 observer facing south powered true 8729 observer facing south powered false 8730 observer facing west powered true 8731 observer facing west powered false 8732 observer facing up powered true 8733 observer facing up powered false 8734 observer facing down powered true 8735 observer facing down powered false 8736 shulker_box facing north 8737 shulker_box facing east 8738 shulker_box facing south 8739 shulker_box facing west 8740 shulker_box facing up 8741 shulker_box facing down 8742 white_shulker_box facing north 8743 white_shulker_box facing east 8744 white_shulker_box facing south 8745 white_shulker_box facing west 8746 white_shulker_box facing up 8747 white_shulker_box facing down 8748 orange_shulker_box facing north 8749 orange_shulker_box facing east 8750 orange_shulker_box facing south 8751 orange_shulker_box facing west 8752 orange_shulker_box facing up 8753 orange_shulker_box facing down 8754 magenta_shulker_box facing north 8755 magenta_shulker_box facing east 8756 magenta_shulker_box facing south 8757 magenta_shulker_box facing west 8758 magenta_shulker_box facing up 8759 magenta_shulker_box facing down 8760 light_blue_shulker_box facing north 8761 light_blue_shulker_box facing east 8762 light_blue_shulker_box facing south 8763 light_blue_shulker_box facing west 8764 light_blue_shulker_box facing up 8765 light_blue_shulker_box facing down 8766 yellow_shulker_box facing north 8767 yellow_shulker_box facing east 8768 yellow_shulker_box facing south 8769 yellow_shulker_box facing west 8770 yellow_shulker_box facing up 8771 yellow_shulker_box facing down 8772 lime_shulker_box facing north 8773 lime_shulker_box facing east 8774 lime_shulker_box facing south 8775 lime_shulker_box facing west 8776 lime_shulker_box facing up 8777 lime_shulker_box facing down 8778 pink_shulker_box facing north 8779 pink_shulker_box facing east 8780 pink_shulker_box facing south 8781 pink_shulker_box facing west 8782 pink_shulker_box facing up 8783 pink_shulker_box facing down 8784 gray_shulker_box facing north 8785 gray_shulker_box facing east 8786 gray_shulker_box facing south 8787 gray_shulker_box facing west 8788 gray_shulker_box facing up 8789 gray_shulker_box facing down 8790 light_gray_shulker_box facing north 8791 light_gray_shulker_box facing east 8792 light_gray_shulker_box facing south 8793 light_gray_shulker_box facing west 8794 light_gray_shulker_box facing up 8795 light_gray_shulker_box facing down 8796 cyan_shulker_box facing north 8797 cyan_shulker_box facing east 8798 cyan_shulker_box facing south 8799 cyan_shulker_box facing west 8800 cyan_shulker_box facing up 8801 cyan_shulker_box facing down 8802 purple_shulker_box facing north 8803 purple_shulker_box facing east 8804 purple_shulker_box facing south 8805 purple_shulker_box facing west 8806 purple_shulker_box facing up 8807 purple_shulker_box facing down 8808 blue_shulker_box facing north 8809 blue_shulker_box facing east 8810 blue_shulker_box facing south 8811 blue_shulker_box facing west 8812 blue_shulker_box facing up 8813 blue_shulker_box facing down 8814 brown_shulker_box facing north 8815 brown_shulker_box facing east 8816 brown_shulker_box facing south 8817 brown_shulker_box facing west 8818 brown_shulker_box facing up 8819 brown_shulker_box facing down 8820 green_shulker_box facing north 8821 green_shulker_box facing east 8822 green_shulker_box facing south 8823 green_shulker_box facing west 8824 green_shulker_box facing up 8825 green_shulker_box facing down 8826 red_shulker_box facing north 8827 red_shulker_box facing east 8828 red_shulker_box facing south 8829 red_shulker_box facing west 8830 red_shulker_box facing up 8831 red_shulker_box facing down 8832 black_shulker_box facing north 8833 black_shulker_box facing east 8834 black_shulker_box facing south 8835 black_shulker_box facing west 8836 black_shulker_box facing up 8837 black_shulker_box facing down 8838 white_glazed_terracotta facing north 8839 white_glazed_terracotta facing south 8840 white_glazed_terracotta facing west 8841 white_glazed_terracotta facing east 8842 orange_glazed_terracotta facing north 8843 orange_glazed_terracotta facing south 8844 orange_glazed_terracotta facing west 8845 orange_glazed_terracotta facing east 8846 magenta_glazed_terracotta facing north 8847 magenta_glazed_terracotta facing south 8848 magenta_glazed_terracotta facing west 8849 magenta_glazed_terracotta facing east 8850 light_blue_glazed_terracotta facing north 8851 light_blue_glazed_terracotta facing south 8852 light_blue_glazed_terracotta facing west 8853 light_blue_glazed_terracotta facing east 8854 yellow_glazed_terracotta facing north 8855 yellow_glazed_terracotta facing south 8856 yellow_glazed_terracotta facing west 8857 yellow_glazed_terracotta facing east 8858 lime_glazed_terracotta facing north 8859 lime_glazed_terracotta facing south 8860 lime_glazed_terracotta facing west 8861 lime_glazed_terracotta facing east 8862 pink_glazed_terracotta facing north 8863 pink_glazed_terracotta facing south 8864 pink_glazed_terracotta facing west 8865 pink_glazed_terracotta facing east 8866 gray_glazed_terracotta facing north 8867 gray_glazed_terracotta facing south 8868 gray_glazed_terracotta facing west 8869 gray_glazed_terracotta facing east 8870 light_gray_glazed_terracotta facing north 8871 light_gray_glazed_terracotta facing south 8872 light_gray_glazed_terracotta facing west 8873 light_gray_glazed_terracotta facing east 8874 cyan_glazed_terracotta facing north 8875 cyan_glazed_terracotta facing south 8876 cyan_glazed_terracotta facing west 8877 cyan_glazed_terracotta facing east 8878 purple_glazed_terracotta facing north 8879 purple_glazed_terracotta facing south 8880 purple_glazed_terracotta facing west 8881 purple_glazed_terracotta facing east 8882 blue_glazed_terracotta facing north 8883 blue_glazed_terracotta facing south 8884 blue_glazed_terracotta facing west 8885 blue_glazed_terracotta facing east 8886 brown_glazed_terracotta facing north 8887 brown_glazed_terracotta facing south 8888 brown_glazed_terracotta facing west 8889 brown_glazed_terracotta facing east 8890 green_glazed_terracotta facing north 8891 green_glazed_terracotta facing south 8892 green_glazed_terracotta facing west 8893 green_glazed_terracotta facing east 8894 red_glazed_terracotta facing north 8895 red_glazed_terracotta facing south 8896 red_glazed_terracotta facing west 8897 red_glazed_terracotta facing east 8898 black_glazed_terracotta facing north 8899 black_glazed_terracotta facing south 8900 black_glazed_terracotta facing west 8901 black_glazed_terracotta facing east 8902 white_concrete 8903 orange_concrete 8904 magenta_concrete 8905 light_blue_concrete 8906 yellow_concrete 8907 lime_concrete 8908 pink_concrete 8909 gray_concrete 8910 light_gray_concrete 8911 cyan_concrete 8912 purple_concrete 8913 blue_concrete 8914 brown_concrete 8915 green_concrete 8916 red_concrete 8917 black_concrete 8918 white_concrete_powder 8919 orange_concrete_powder 8920 magenta_concrete_powder 8921 light_blue_concrete_powder 8922 yellow_concrete_powder 8923 lime_concrete_powder 8924 pink_concrete_powder 8925 gray_concrete_powder 8926 light_gray_concrete_powder 8927 cyan_concrete_powder 8928 purple_concrete_powder 8929 blue_concrete_powder 8930 brown_concrete_powder 8931 green_concrete_powder 8932 red_concrete_powder 8933 black_concrete_powder 8934 kelp age 0 8935 kelp age 1 8936 kelp age 2 8937 kelp age 3 8938 kelp age 4 8939 kelp age 5 8940 kelp age 6 8941 kelp age 7 8942 kelp age 8 8943 kelp age 9 8944 kelp age 10 8945 kelp age 11 8946 kelp age 12 8947 kelp age 13 8948 kelp age 14 8949 kelp age 15 8950 kelp age 16 8951 kelp age 17 8952 kelp age 18 8953 kelp age 19 8954 kelp age 20 8955 kelp age 21 8956 kelp age 22 8957 kelp age 23 8958 kelp age 24 8959 kelp age 25 8960 kelp_plant 8961 dried_kelp_block 8962 turtle_egg eggs 1 hatch 0 8963 turtle_egg eggs 1 hatch 1 8964 turtle_egg eggs 1 hatch 2 8965 turtle_egg eggs 2 hatch 0 8966 turtle_egg eggs 2 hatch 1 8967 turtle_egg eggs 2 hatch 2 8968 turtle_egg eggs 3 hatch 0 8969 turtle_egg eggs 3 hatch 1 8970 turtle_egg eggs 3 hatch 2 8971 turtle_egg eggs 4 hatch 0 8972 turtle_egg eggs 4 hatch 1 8973 turtle_egg eggs 4 hatch 2 8974 dead_tube_coral_block 8975 dead_brain_coral_block 8976 dead_bubble_coral_block 8977 dead_fire_coral_block 8978 dead_horn_coral_block 8979 tube_coral_block 8980 brain_coral_block 8981 bubble_coral_block 8982 fire_coral_block 8983 horn_coral_block 8984 dead_tube_coral waterlogged true 8985 dead_tube_coral waterlogged false 8986 dead_brain_coral waterlogged true 8987 dead_brain_coral waterlogged false 8988 dead_bubble_coral waterlogged true 8989 dead_bubble_coral waterlogged false 8990 dead_fire_coral waterlogged true 8991 dead_fire_coral waterlogged false 8992 dead_horn_coral waterlogged true 8993 dead_horn_coral waterlogged false 8994 tube_coral waterlogged true 8995 tube_coral waterlogged false 8996 brain_coral waterlogged true 8997 brain_coral waterlogged false 8998 bubble_coral waterlogged true 8999 bubble_coral waterlogged false 9000 fire_coral waterlogged true 9001 fire_coral waterlogged false 9002 horn_coral waterlogged true 9003 horn_coral waterlogged false 9004 dead_tube_coral_fan waterlogged true 9005 dead_tube_coral_fan waterlogged false 9006 dead_brain_coral_fan waterlogged true 9007 dead_brain_coral_fan waterlogged false 9008 dead_bubble_coral_fan waterlogged true 9009 dead_bubble_coral_fan waterlogged false 9010 dead_fire_coral_fan waterlogged true 9011 dead_fire_coral_fan waterlogged false 9012 dead_horn_coral_fan waterlogged true 9013 dead_horn_coral_fan waterlogged false 9014 tube_coral_fan waterlogged true 9015 tube_coral_fan waterlogged false 9016 brain_coral_fan waterlogged true 9017 brain_coral_fan waterlogged false 9018 bubble_coral_fan waterlogged true 9019 bubble_coral_fan waterlogged false 9020 fire_coral_fan waterlogged true 9021 fire_coral_fan waterlogged false 9022 horn_coral_fan waterlogged true 9023 horn_coral_fan waterlogged false 9024 dead_tube_coral_wall_fan facing north waterlogged true 9025 dead_tube_coral_wall_fan facing north waterlogged false 9026 dead_tube_coral_wall_fan facing south waterlogged true 9027 dead_tube_coral_wall_fan facing south waterlogged false 9028 dead_tube_coral_wall_fan facing west waterlogged true 9029 dead_tube_coral_wall_fan facing west waterlogged false 9030 dead_tube_coral_wall_fan facing east waterlogged true 9031 dead_tube_coral_wall_fan facing east waterlogged false 9032 dead_brain_coral_wall_fan facing north waterlogged true 9033 dead_brain_coral_wall_fan facing north waterlogged false 9034 dead_brain_coral_wall_fan facing south waterlogged true 9035 dead_brain_coral_wall_fan facing south waterlogged false 9036 dead_brain_coral_wall_fan facing west waterlogged true 9037 dead_brain_coral_wall_fan facing west waterlogged false 9038 dead_brain_coral_wall_fan facing east waterlogged true 9039 dead_brain_coral_wall_fan facing east waterlogged false 9040 dead_bubble_coral_wall_fan facing north waterlogged true 9041 dead_bubble_coral_wall_fan facing north waterlogged false 9042 dead_bubble_coral_wall_fan facing south waterlogged true 9043 dead_bubble_coral_wall_fan facing south waterlogged false 9044 dead_bubble_coral_wall_fan facing west waterlogged true 9045 dead_bubble_coral_wall_fan facing west waterlogged false 9046 dead_bubble_coral_wall_fan facing east waterlogged true 9047 dead_bubble_coral_wall_fan facing east waterlogged false 9048 dead_fire_coral_wall_fan facing north waterlogged true 9049 dead_fire_coral_wall_fan facing north waterlogged false 9050 dead_fire_coral_wall_fan facing south waterlogged true 9051 dead_fire_coral_wall_fan facing south waterlogged false 9052 dead_fire_coral_wall_fan facing west waterlogged true 9053 dead_fire_coral_wall_fan facing west waterlogged false 9054 dead_fire_coral_wall_fan facing east waterlogged true 9055 dead_fire_coral_wall_fan facing east waterlogged false 9056 dead_horn_coral_wall_fan facing north waterlogged true 9057 dead_horn_coral_wall_fan facing north waterlogged false 9058 dead_horn_coral_wall_fan facing south waterlogged true 9059 dead_horn_coral_wall_fan facing south waterlogged false 9060 dead_horn_coral_wall_fan facing west waterlogged true 9061 dead_horn_coral_wall_fan facing west waterlogged false 9062 dead_horn_coral_wall_fan facing east waterlogged true 9063 dead_horn_coral_wall_fan facing east waterlogged false 9064 tube_coral_wall_fan facing north waterlogged true 9065 tube_coral_wall_fan facing north waterlogged false 9066 tube_coral_wall_fan facing south waterlogged true 9067 tube_coral_wall_fan facing south waterlogged false 9068 tube_coral_wall_fan facing west waterlogged true 9069 tube_coral_wall_fan facing west waterlogged false 9070 tube_coral_wall_fan facing east waterlogged true 9071 tube_coral_wall_fan facing east waterlogged false 9072 brain_coral_wall_fan facing north waterlogged true 9073 brain_coral_wall_fan facing north waterlogged false 9074 brain_coral_wall_fan facing south waterlogged true 9075 brain_coral_wall_fan facing south waterlogged false 9076 brain_coral_wall_fan facing west waterlogged true 9077 brain_coral_wall_fan facing west waterlogged false 9078 brain_coral_wall_fan facing east waterlogged true 9079 brain_coral_wall_fan facing east waterlogged false 9080 bubble_coral_wall_fan facing north waterlogged true 9081 bubble_coral_wall_fan facing north waterlogged false 9082 bubble_coral_wall_fan facing south waterlogged true 9083 bubble_coral_wall_fan facing south waterlogged false 9084 bubble_coral_wall_fan facing west waterlogged true 9085 bubble_coral_wall_fan facing west waterlogged false 9086 bubble_coral_wall_fan facing east waterlogged true 9087 bubble_coral_wall_fan facing east waterlogged false 9088 fire_coral_wall_fan facing north waterlogged true 9089 fire_coral_wall_fan facing north waterlogged false 9090 fire_coral_wall_fan facing south waterlogged true 9091 fire_coral_wall_fan facing south waterlogged false 9092 fire_coral_wall_fan facing west waterlogged true 9093 fire_coral_wall_fan facing west waterlogged false 9094 fire_coral_wall_fan facing east waterlogged true 9095 fire_coral_wall_fan facing east waterlogged false 9096 horn_coral_wall_fan facing north waterlogged true 9097 horn_coral_wall_fan facing north waterlogged false 9098 horn_coral_wall_fan facing south waterlogged true 9099 horn_coral_wall_fan facing south waterlogged false 9100 horn_coral_wall_fan facing west waterlogged true 9101 horn_coral_wall_fan facing west waterlogged false 9102 horn_coral_wall_fan facing east waterlogged true 9103 horn_coral_wall_fan facing east waterlogged false 9104 sea_pickle waterlogged true pickles 1 9105 sea_pickle waterlogged false pickles 1 9106 sea_pickle waterlogged true pickles 2 9107 sea_pickle waterlogged false pickles 2 9108 sea_pickle waterlogged true pickles 3 9109 sea_pickle waterlogged false pickles 3 9110 sea_pickle waterlogged true pickles 4 9111 sea_pickle waterlogged false pickles 4 9112 blue_ice 9113 conduit waterlogged true 9114 conduit waterlogged false 9115 bamboo_sapling 9116 bamboo leaves none stage 0 age 0 9117 bamboo leaves none stage 1 age 0 9118 bamboo leaves small stage 0 age 0 9119 bamboo leaves small stage 1 age 0 9120 bamboo leaves large stage 0 age 0 9121 bamboo leaves large stage 1 age 0 9122 bamboo leaves none stage 0 age 1 9123 bamboo leaves none stage 1 age 1 9124 bamboo leaves small stage 0 age 1 9125 bamboo leaves small stage 1 age 1 9126 bamboo leaves large stage 0 age 1 9127 bamboo leaves large stage 1 age 1 9128 potted_bamboo 9129 void_air 9130 cave_air 9131 bubble_column drag true 9132 bubble_column drag false 9133 polished_granite_stairs facing north waterlogged true shape straight half top 9134 polished_granite_stairs facing north waterlogged false shape straight half top 9135 polished_granite_stairs facing north waterlogged true shape inner_left half top 9136 polished_granite_stairs facing north waterlogged false shape inner_left half top 9137 polished_granite_stairs facing north waterlogged true shape inner_right half top 9138 polished_granite_stairs facing north waterlogged false shape inner_right half top 9139 polished_granite_stairs facing north waterlogged true shape outer_left half top 9140 polished_granite_stairs facing north waterlogged false shape outer_left half top 9141 polished_granite_stairs facing north waterlogged true shape outer_right half top 9142 polished_granite_stairs facing north waterlogged false shape outer_right half top 9143 polished_granite_stairs facing north waterlogged true shape straight half bottom 9144 polished_granite_stairs facing north waterlogged false shape straight half bottom 9145 polished_granite_stairs facing north waterlogged true shape inner_left half bottom 9146 polished_granite_stairs facing north waterlogged false shape inner_left half bottom 9147 polished_granite_stairs facing north waterlogged true shape inner_right half bottom 9148 polished_granite_stairs facing north waterlogged false shape inner_right half bottom 9149 polished_granite_stairs facing north waterlogged true shape outer_left half bottom 9150 polished_granite_stairs facing north waterlogged false shape outer_left half bottom 9151 polished_granite_stairs facing north waterlogged true shape outer_right half bottom 9152 polished_granite_stairs facing north waterlogged false shape outer_right half bottom 9153 polished_granite_stairs facing south waterlogged true shape straight half top 9154 polished_granite_stairs facing south waterlogged false shape straight half top 9155 polished_granite_stairs facing south waterlogged true shape inner_left half top 9156 polished_granite_stairs facing south waterlogged false shape inner_left half top 9157 polished_granite_stairs facing south waterlogged true shape inner_right half top 9158 polished_granite_stairs facing south waterlogged false shape inner_right half top 9159 polished_granite_stairs facing south waterlogged true shape outer_left half top 9160 polished_granite_stairs facing south waterlogged false shape outer_left half top 9161 polished_granite_stairs facing south waterlogged true shape outer_right half top 9162 polished_granite_stairs facing south waterlogged false shape outer_right half top 9163 polished_granite_stairs facing south waterlogged true shape straight half bottom 9164 polished_granite_stairs facing south waterlogged false shape straight half bottom 9165 polished_granite_stairs facing south waterlogged true shape inner_left half bottom 9166 polished_granite_stairs facing south waterlogged false shape inner_left half bottom 9167 polished_granite_stairs facing south waterlogged true shape inner_right half bottom 9168 polished_granite_stairs facing south waterlogged false shape inner_right half bottom 9169 polished_granite_stairs facing south waterlogged true shape outer_left half bottom 9170 polished_granite_stairs facing south waterlogged false shape outer_left half bottom 9171 polished_granite_stairs facing south waterlogged true shape outer_right half bottom 9172 polished_granite_stairs facing south waterlogged false shape outer_right half bottom 9173 polished_granite_stairs facing west waterlogged true shape straight half top 9174 polished_granite_stairs facing west waterlogged false shape straight half top 9175 polished_granite_stairs facing west waterlogged true shape inner_left half top 9176 polished_granite_stairs facing west waterlogged false shape inner_left half top 9177 polished_granite_stairs facing west waterlogged true shape inner_right half top 9178 polished_granite_stairs facing west waterlogged false shape inner_right half top 9179 polished_granite_stairs facing west waterlogged true shape outer_left half top 9180 polished_granite_stairs facing west waterlogged false shape outer_left half top 9181 polished_granite_stairs facing west waterlogged true shape outer_right half top 9182 polished_granite_stairs facing west waterlogged false shape outer_right half top 9183 polished_granite_stairs facing west waterlogged true shape straight half bottom 9184 polished_granite_stairs facing west waterlogged false shape straight half bottom 9185 polished_granite_stairs facing west waterlogged true shape inner_left half bottom 9186 polished_granite_stairs facing west waterlogged false shape inner_left half bottom 9187 polished_granite_stairs facing west waterlogged true shape inner_right half bottom 9188 polished_granite_stairs facing west waterlogged false shape inner_right half bottom 9189 polished_granite_stairs facing west waterlogged true shape outer_left half bottom 9190 polished_granite_stairs facing west waterlogged false shape outer_left half bottom 9191 polished_granite_stairs facing west waterlogged true shape outer_right half bottom 9192 polished_granite_stairs facing west waterlogged false shape outer_right half bottom 9193 polished_granite_stairs facing east waterlogged true shape straight half top 9194 polished_granite_stairs facing east waterlogged false shape straight half top 9195 polished_granite_stairs facing east waterlogged true shape inner_left half top 9196 polished_granite_stairs facing east waterlogged false shape inner_left half top 9197 polished_granite_stairs facing east waterlogged true shape inner_right half top 9198 polished_granite_stairs facing east waterlogged false shape inner_right half top 9199 polished_granite_stairs facing east waterlogged true shape outer_left half top 9200 polished_granite_stairs facing east waterlogged false shape outer_left half top 9201 polished_granite_stairs facing east waterlogged true shape outer_right half top 9202 polished_granite_stairs facing east waterlogged false shape outer_right half top 9203 polished_granite_stairs facing east waterlogged true shape straight half bottom 9204 polished_granite_stairs facing east waterlogged false shape straight half bottom 9205 polished_granite_stairs facing east waterlogged true shape inner_left half bottom 9206 polished_granite_stairs facing east waterlogged false shape inner_left half bottom 9207 polished_granite_stairs facing east waterlogged true shape inner_right half bottom 9208 polished_granite_stairs facing east waterlogged false shape inner_right half bottom 9209 polished_granite_stairs facing east waterlogged true shape outer_left half bottom 9210 polished_granite_stairs facing east waterlogged false shape outer_left half bottom 9211 polished_granite_stairs facing east waterlogged true shape outer_right half bottom 9212 polished_granite_stairs facing east waterlogged false shape outer_right half bottom 9213 smooth_red_sandstone_stairs facing north waterlogged true shape straight half top 9214 smooth_red_sandstone_stairs facing north waterlogged false shape straight half top 9215 smooth_red_sandstone_stairs facing north waterlogged true shape inner_left half top 9216 smooth_red_sandstone_stairs facing north waterlogged false shape inner_left half top 9217 smooth_red_sandstone_stairs facing north waterlogged true shape inner_right half top 9218 smooth_red_sandstone_stairs facing north waterlogged false shape inner_right half top 9219 smooth_red_sandstone_stairs facing north waterlogged true shape outer_left half top 9220 smooth_red_sandstone_stairs facing north waterlogged false shape outer_left half top 9221 smooth_red_sandstone_stairs facing north waterlogged true shape outer_right half top 9222 smooth_red_sandstone_stairs facing north waterlogged false shape outer_right half top 9223 smooth_red_sandstone_stairs facing north waterlogged true shape straight half bottom 9224 smooth_red_sandstone_stairs facing north waterlogged false shape straight half bottom 9225 smooth_red_sandstone_stairs facing north waterlogged true shape inner_left half bottom 9226 smooth_red_sandstone_stairs facing north waterlogged false shape inner_left half bottom 9227 smooth_red_sandstone_stairs facing north waterlogged true shape inner_right half bottom 9228 smooth_red_sandstone_stairs facing north waterlogged false shape inner_right half bottom 9229 smooth_red_sandstone_stairs facing north waterlogged true shape outer_left half bottom 9230 smooth_red_sandstone_stairs facing north waterlogged false shape outer_left half bottom 9231 smooth_red_sandstone_stairs facing north waterlogged true shape outer_right half bottom 9232 smooth_red_sandstone_stairs facing north waterlogged false shape outer_right half bottom 9233 smooth_red_sandstone_stairs facing south waterlogged true shape straight half top 9234 smooth_red_sandstone_stairs facing south waterlogged false shape straight half top 9235 smooth_red_sandstone_stairs facing south waterlogged true shape inner_left half top 9236 smooth_red_sandstone_stairs facing south waterlogged false shape inner_left half top 9237 smooth_red_sandstone_stairs facing south waterlogged true shape inner_right half top 9238 smooth_red_sandstone_stairs facing south waterlogged false shape inner_right half top 9239 smooth_red_sandstone_stairs facing south waterlogged true shape outer_left half top 9240 smooth_red_sandstone_stairs facing south waterlogged false shape outer_left half top 9241 smooth_red_sandstone_stairs facing south waterlogged true shape outer_right half top 9242 smooth_red_sandstone_stairs facing south waterlogged false shape outer_right half top 9243 smooth_red_sandstone_stairs facing south waterlogged true shape straight half bottom 9244 smooth_red_sandstone_stairs facing south waterlogged false shape straight half bottom 9245 smooth_red_sandstone_stairs facing south waterlogged true shape inner_left half bottom 9246 smooth_red_sandstone_stairs facing south waterlogged false shape inner_left half bottom 9247 smooth_red_sandstone_stairs facing south waterlogged true shape inner_right half bottom 9248 smooth_red_sandstone_stairs facing south waterlogged false shape inner_right half bottom 9249 smooth_red_sandstone_stairs facing south waterlogged true shape outer_left half bottom 9250 smooth_red_sandstone_stairs facing south waterlogged false shape outer_left half bottom 9251 smooth_red_sandstone_stairs facing south waterlogged true shape outer_right half bottom 9252 smooth_red_sandstone_stairs facing south waterlogged false shape outer_right half bottom 9253 smooth_red_sandstone_stairs facing west waterlogged true shape straight half top 9254 smooth_red_sandstone_stairs facing west waterlogged false shape straight half top 9255 smooth_red_sandstone_stairs facing west waterlogged true shape inner_left half top 9256 smooth_red_sandstone_stairs facing west waterlogged false shape inner_left half top 9257 smooth_red_sandstone_stairs facing west waterlogged true shape inner_right half top 9258 smooth_red_sandstone_stairs facing west waterlogged false shape inner_right half top 9259 smooth_red_sandstone_stairs facing west waterlogged true shape outer_left half top 9260 smooth_red_sandstone_stairs facing west waterlogged false shape outer_left half top 9261 smooth_red_sandstone_stairs facing west waterlogged true shape outer_right half top 9262 smooth_red_sandstone_stairs facing west waterlogged false shape outer_right half top 9263 smooth_red_sandstone_stairs facing west waterlogged true shape straight half bottom 9264 smooth_red_sandstone_stairs facing west waterlogged false shape straight half bottom 9265 smooth_red_sandstone_stairs facing west waterlogged true shape inner_left half bottom 9266 smooth_red_sandstone_stairs facing west waterlogged false shape inner_left half bottom 9267 smooth_red_sandstone_stairs facing west waterlogged true shape inner_right half bottom 9268 smooth_red_sandstone_stairs facing west waterlogged false shape inner_right half bottom 9269 smooth_red_sandstone_stairs facing west waterlogged true shape outer_left half bottom 9270 smooth_red_sandstone_stairs facing west waterlogged false shape outer_left half bottom 9271 smooth_red_sandstone_stairs facing west waterlogged true shape outer_right half bottom 9272 smooth_red_sandstone_stairs facing west waterlogged false shape outer_right half bottom 9273 smooth_red_sandstone_stairs facing east waterlogged true shape straight half top 9274 smooth_red_sandstone_stairs facing east waterlogged false shape straight half top 9275 smooth_red_sandstone_stairs facing east waterlogged true shape inner_left half top 9276 smooth_red_sandstone_stairs facing east waterlogged false shape inner_left half top 9277 smooth_red_sandstone_stairs facing east waterlogged true shape inner_right half top 9278 smooth_red_sandstone_stairs facing east waterlogged false shape inner_right half top 9279 smooth_red_sandstone_stairs facing east waterlogged true shape outer_left half top 9280 smooth_red_sandstone_stairs facing east waterlogged false shape outer_left half top 9281 smooth_red_sandstone_stairs facing east waterlogged true shape outer_right half top 9282 smooth_red_sandstone_stairs facing east waterlogged false shape outer_right half top 9283 smooth_red_sandstone_stairs facing east waterlogged true shape straight half bottom 9284 smooth_red_sandstone_stairs facing east waterlogged false shape straight half bottom 9285 smooth_red_sandstone_stairs facing east waterlogged true shape inner_left half bottom 9286 smooth_red_sandstone_stairs facing east waterlogged false shape inner_left half bottom 9287 smooth_red_sandstone_stairs facing east waterlogged true shape inner_right half bottom 9288 smooth_red_sandstone_stairs facing east waterlogged false shape inner_right half bottom 9289 smooth_red_sandstone_stairs facing east waterlogged true shape outer_left half bottom 9290 smooth_red_sandstone_stairs facing east waterlogged false shape outer_left half bottom 9291 smooth_red_sandstone_stairs facing east waterlogged true shape outer_right half bottom 9292 smooth_red_sandstone_stairs facing east waterlogged false shape outer_right half bottom 9293 mossy_stone_brick_stairs facing north waterlogged true shape straight half top 9294 mossy_stone_brick_stairs facing north waterlogged false shape straight half top 9295 mossy_stone_brick_stairs facing north waterlogged true shape inner_left half top 9296 mossy_stone_brick_stairs facing north waterlogged false shape inner_left half top 9297 mossy_stone_brick_stairs facing north waterlogged true shape inner_right half top 9298 mossy_stone_brick_stairs facing north waterlogged false shape inner_right half top 9299 mossy_stone_brick_stairs facing north waterlogged true shape outer_left half top 9300 mossy_stone_brick_stairs facing north waterlogged false shape outer_left half top 9301 mossy_stone_brick_stairs facing north waterlogged true shape outer_right half top 9302 mossy_stone_brick_stairs facing north waterlogged false shape outer_right half top 9303 mossy_stone_brick_stairs facing north waterlogged true shape straight half bottom 9304 mossy_stone_brick_stairs facing north waterlogged false shape straight half bottom 9305 mossy_stone_brick_stairs facing north waterlogged true shape inner_left half bottom 9306 mossy_stone_brick_stairs facing north waterlogged false shape inner_left half bottom 9307 mossy_stone_brick_stairs facing north waterlogged true shape inner_right half bottom 9308 mossy_stone_brick_stairs facing north waterlogged false shape inner_right half bottom 9309 mossy_stone_brick_stairs facing north waterlogged true shape outer_left half bottom 9310 mossy_stone_brick_stairs facing north waterlogged false shape outer_left half bottom 9311 mossy_stone_brick_stairs facing north waterlogged true shape outer_right half bottom 9312 mossy_stone_brick_stairs facing north waterlogged false shape outer_right half bottom 9313 mossy_stone_brick_stairs facing south waterlogged true shape straight half top 9314 mossy_stone_brick_stairs facing south waterlogged false shape straight half top 9315 mossy_stone_brick_stairs facing south waterlogged true shape inner_left half top 9316 mossy_stone_brick_stairs facing south waterlogged false shape inner_left half top 9317 mossy_stone_brick_stairs facing south waterlogged true shape inner_right half top 9318 mossy_stone_brick_stairs facing south waterlogged false shape inner_right half top 9319 mossy_stone_brick_stairs facing south waterlogged true shape outer_left half top 9320 mossy_stone_brick_stairs facing south waterlogged false shape outer_left half top 9321 mossy_stone_brick_stairs facing south waterlogged true shape outer_right half top 9322 mossy_stone_brick_stairs facing south waterlogged false shape outer_right half top 9323 mossy_stone_brick_stairs facing south waterlogged true shape straight half bottom 9324 mossy_stone_brick_stairs facing south waterlogged false shape straight half bottom 9325 mossy_stone_brick_stairs facing south waterlogged true shape inner_left half bottom 9326 mossy_stone_brick_stairs facing south waterlogged false shape inner_left half bottom 9327 mossy_stone_brick_stairs facing south waterlogged true shape inner_right half bottom 9328 mossy_stone_brick_stairs facing south waterlogged false shape inner_right half bottom 9329 mossy_stone_brick_stairs facing south waterlogged true shape outer_left half bottom 9330 mossy_stone_brick_stairs facing south waterlogged false shape outer_left half bottom 9331 mossy_stone_brick_stairs facing south waterlogged true shape outer_right half bottom 9332 mossy_stone_brick_stairs facing south waterlogged false shape outer_right half bottom 9333 mossy_stone_brick_stairs facing west waterlogged true shape straight half top 9334 mossy_stone_brick_stairs facing west waterlogged false shape straight half top 9335 mossy_stone_brick_stairs facing west waterlogged true shape inner_left half top 9336 mossy_stone_brick_stairs facing west waterlogged false shape inner_left half top 9337 mossy_stone_brick_stairs facing west waterlogged true shape inner_right half top 9338 mossy_stone_brick_stairs facing west waterlogged false shape inner_right half top 9339 mossy_stone_brick_stairs facing west waterlogged true shape outer_left half top 9340 mossy_stone_brick_stairs facing west waterlogged false shape outer_left half top 9341 mossy_stone_brick_stairs facing west waterlogged true shape outer_right half top 9342 mossy_stone_brick_stairs facing west waterlogged false shape outer_right half top 9343 mossy_stone_brick_stairs facing west waterlogged true shape straight half bottom 9344 mossy_stone_brick_stairs facing west waterlogged false shape straight half bottom 9345 mossy_stone_brick_stairs facing west waterlogged true shape inner_left half bottom 9346 mossy_stone_brick_stairs facing west waterlogged false shape inner_left half bottom 9347 mossy_stone_brick_stairs facing west waterlogged true shape inner_right half bottom 9348 mossy_stone_brick_stairs facing west waterlogged false shape inner_right half bottom 9349 mossy_stone_brick_stairs facing west waterlogged true shape outer_left half bottom 9350 mossy_stone_brick_stairs facing west waterlogged false shape outer_left half bottom 9351 mossy_stone_brick_stairs facing west waterlogged true shape outer_right half bottom 9352 mossy_stone_brick_stairs facing west waterlogged false shape outer_right half bottom 9353 mossy_stone_brick_stairs facing east waterlogged true shape straight half top 9354 mossy_stone_brick_stairs facing east waterlogged false shape straight half top 9355 mossy_stone_brick_stairs facing east waterlogged true shape inner_left half top 9356 mossy_stone_brick_stairs facing east waterlogged false shape inner_left half top 9357 mossy_stone_brick_stairs facing east waterlogged true shape inner_right half top 9358 mossy_stone_brick_stairs facing east waterlogged false shape inner_right half top 9359 mossy_stone_brick_stairs facing east waterlogged true shape outer_left half top 9360 mossy_stone_brick_stairs facing east waterlogged false shape outer_left half top 9361 mossy_stone_brick_stairs facing east waterlogged true shape outer_right half top 9362 mossy_stone_brick_stairs facing east waterlogged false shape outer_right half top 9363 mossy_stone_brick_stairs facing east waterlogged true shape straight half bottom 9364 mossy_stone_brick_stairs facing east waterlogged false shape straight half bottom 9365 mossy_stone_brick_stairs facing east waterlogged true shape inner_left half bottom 9366 mossy_stone_brick_stairs facing east waterlogged false shape inner_left half bottom 9367 mossy_stone_brick_stairs facing east waterlogged true shape inner_right half bottom 9368 mossy_stone_brick_stairs facing east waterlogged false shape inner_right half bottom 9369 mossy_stone_brick_stairs facing east waterlogged true shape outer_left half bottom 9370 mossy_stone_brick_stairs facing east waterlogged false shape outer_left half bottom 9371 mossy_stone_brick_stairs facing east waterlogged true shape outer_right half bottom 9372 mossy_stone_brick_stairs facing east waterlogged false shape outer_right half bottom 9373 polished_diorite_stairs facing north waterlogged true shape straight half top 9374 polished_diorite_stairs facing north waterlogged false shape straight half top 9375 polished_diorite_stairs facing north waterlogged true shape inner_left half top 9376 polished_diorite_stairs facing north waterlogged false shape inner_left half top 9377 polished_diorite_stairs facing north waterlogged true shape inner_right half top 9378 polished_diorite_stairs facing north waterlogged false shape inner_right half top 9379 polished_diorite_stairs facing north waterlogged true shape outer_left half top 9380 polished_diorite_stairs facing north waterlogged false shape outer_left half top 9381 polished_diorite_stairs facing north waterlogged true shape outer_right half top 9382 polished_diorite_stairs facing north waterlogged false shape outer_right half top 9383 polished_diorite_stairs facing north waterlogged true shape straight half bottom 9384 polished_diorite_stairs facing north waterlogged false shape straight half bottom 9385 polished_diorite_stairs facing north waterlogged true shape inner_left half bottom 9386 polished_diorite_stairs facing north waterlogged false shape inner_left half bottom 9387 polished_diorite_stairs facing north waterlogged true shape inner_right half bottom 9388 polished_diorite_stairs facing north waterlogged false shape inner_right half bottom 9389 polished_diorite_stairs facing north waterlogged true shape outer_left half bottom 9390 polished_diorite_stairs facing north waterlogged false shape outer_left half bottom 9391 polished_diorite_stairs facing north waterlogged true shape outer_right half bottom 9392 polished_diorite_stairs facing north waterlogged false shape outer_right half bottom 9393 polished_diorite_stairs facing south waterlogged true shape straight half top 9394 polished_diorite_stairs facing south waterlogged false shape straight half top 9395 polished_diorite_stairs facing south waterlogged true shape inner_left half top 9396 polished_diorite_stairs facing south waterlogged false shape inner_left half top 9397 polished_diorite_stairs facing south waterlogged true shape inner_right half top 9398 polished_diorite_stairs facing south waterlogged false shape inner_right half top 9399 polished_diorite_stairs facing south waterlogged true shape outer_left half top 9400 polished_diorite_stairs facing south waterlogged false shape outer_left half top 9401 polished_diorite_stairs facing south waterlogged true shape outer_right half top 9402 polished_diorite_stairs facing south waterlogged false shape outer_right half top 9403 polished_diorite_stairs facing south waterlogged true shape straight half bottom 9404 polished_diorite_stairs facing south waterlogged false shape straight half bottom 9405 polished_diorite_stairs facing south waterlogged true shape inner_left half bottom 9406 polished_diorite_stairs facing south waterlogged false shape inner_left half bottom 9407 polished_diorite_stairs facing south waterlogged true shape inner_right half bottom 9408 polished_diorite_stairs facing south waterlogged false shape inner_right half bottom 9409 polished_diorite_stairs facing south waterlogged true shape outer_left half bottom 9410 polished_diorite_stairs facing south waterlogged false shape outer_left half bottom 9411 polished_diorite_stairs facing south waterlogged true shape outer_right half bottom 9412 polished_diorite_stairs facing south waterlogged false shape outer_right half bottom 9413 polished_diorite_stairs facing west waterlogged true shape straight half top 9414 polished_diorite_stairs facing west waterlogged false shape straight half top 9415 polished_diorite_stairs facing west waterlogged true shape inner_left half top 9416 polished_diorite_stairs facing west waterlogged false shape inner_left half top 9417 polished_diorite_stairs facing west waterlogged true shape inner_right half top 9418 polished_diorite_stairs facing west waterlogged false shape inner_right half top 9419 polished_diorite_stairs facing west waterlogged true shape outer_left half top 9420 polished_diorite_stairs facing west waterlogged false shape outer_left half top 9421 polished_diorite_stairs facing west waterlogged true shape outer_right half top 9422 polished_diorite_stairs facing west waterlogged false shape outer_right half top 9423 polished_diorite_stairs facing west waterlogged true shape straight half bottom 9424 polished_diorite_stairs facing west waterlogged false shape straight half bottom 9425 polished_diorite_stairs facing west waterlogged true shape inner_left half bottom 9426 polished_diorite_stairs facing west waterlogged false shape inner_left half bottom 9427 polished_diorite_stairs facing west waterlogged true shape inner_right half bottom 9428 polished_diorite_stairs facing west waterlogged false shape inner_right half bottom 9429 polished_diorite_stairs facing west waterlogged true shape outer_left half bottom 9430 polished_diorite_stairs facing west waterlogged false shape outer_left half bottom 9431 polished_diorite_stairs facing west waterlogged true shape outer_right half bottom 9432 polished_diorite_stairs facing west waterlogged false shape outer_right half bottom 9433 polished_diorite_stairs facing east waterlogged true shape straight half top 9434 polished_diorite_stairs facing east waterlogged false shape straight half top 9435 polished_diorite_stairs facing east waterlogged true shape inner_left half top 9436 polished_diorite_stairs facing east waterlogged false shape inner_left half top 9437 polished_diorite_stairs facing east waterlogged true shape inner_right half top 9438 polished_diorite_stairs facing east waterlogged false shape inner_right half top 9439 polished_diorite_stairs facing east waterlogged true shape outer_left half top 9440 polished_diorite_stairs facing east waterlogged false shape outer_left half top 9441 polished_diorite_stairs facing east waterlogged true shape outer_right half top 9442 polished_diorite_stairs facing east waterlogged false shape outer_right half top 9443 polished_diorite_stairs facing east waterlogged true shape straight half bottom 9444 polished_diorite_stairs facing east waterlogged false shape straight half bottom 9445 polished_diorite_stairs facing east waterlogged true shape inner_left half bottom 9446 polished_diorite_stairs facing east waterlogged false shape inner_left half bottom 9447 polished_diorite_stairs facing east waterlogged true shape inner_right half bottom 9448 polished_diorite_stairs facing east waterlogged false shape inner_right half bottom 9449 polished_diorite_stairs facing east waterlogged true shape outer_left half bottom 9450 polished_diorite_stairs facing east waterlogged false shape outer_left half bottom 9451 polished_diorite_stairs facing east waterlogged true shape outer_right half bottom 9452 polished_diorite_stairs facing east waterlogged false shape outer_right half bottom 9453 mossy_cobblestone_stairs facing north waterlogged true shape straight half top 9454 mossy_cobblestone_stairs facing north waterlogged false shape straight half top 9455 mossy_cobblestone_stairs facing north waterlogged true shape inner_left half top 9456 mossy_cobblestone_stairs facing north waterlogged false shape inner_left half top 9457 mossy_cobblestone_stairs facing north waterlogged true shape inner_right half top 9458 mossy_cobblestone_stairs facing north waterlogged false shape inner_right half top 9459 mossy_cobblestone_stairs facing north waterlogged true shape outer_left half top 9460 mossy_cobblestone_stairs facing north waterlogged false shape outer_left half top 9461 mossy_cobblestone_stairs facing north waterlogged true shape outer_right half top 9462 mossy_cobblestone_stairs facing north waterlogged false shape outer_right half top 9463 mossy_cobblestone_stairs facing north waterlogged true shape straight half bottom 9464 mossy_cobblestone_stairs facing north waterlogged false shape straight half bottom 9465 mossy_cobblestone_stairs facing north waterlogged true shape inner_left half bottom 9466 mossy_cobblestone_stairs facing north waterlogged false shape inner_left half bottom 9467 mossy_cobblestone_stairs facing north waterlogged true shape inner_right half bottom 9468 mossy_cobblestone_stairs facing north waterlogged false shape inner_right half bottom 9469 mossy_cobblestone_stairs facing north waterlogged true shape outer_left half bottom 9470 mossy_cobblestone_stairs facing north waterlogged false shape outer_left half bottom 9471 mossy_cobblestone_stairs facing north waterlogged true shape outer_right half bottom 9472 mossy_cobblestone_stairs facing north waterlogged false shape outer_right half bottom 9473 mossy_cobblestone_stairs facing south waterlogged true shape straight half top 9474 mossy_cobblestone_stairs facing south waterlogged false shape straight half top 9475 mossy_cobblestone_stairs facing south waterlogged true shape inner_left half top 9476 mossy_cobblestone_stairs facing south waterlogged false shape inner_left half top 9477 mossy_cobblestone_stairs facing south waterlogged true shape inner_right half top 9478 mossy_cobblestone_stairs facing south waterlogged false shape inner_right half top 9479 mossy_cobblestone_stairs facing south waterlogged true shape outer_left half top 9480 mossy_cobblestone_stairs facing south waterlogged false shape outer_left half top 9481 mossy_cobblestone_stairs facing south waterlogged true shape outer_right half top 9482 mossy_cobblestone_stairs facing south waterlogged false shape outer_right half top 9483 mossy_cobblestone_stairs facing south waterlogged true shape straight half bottom 9484 mossy_cobblestone_stairs facing south waterlogged false shape straight half bottom 9485 mossy_cobblestone_stairs facing south waterlogged true shape inner_left half bottom 9486 mossy_cobblestone_stairs facing south waterlogged false shape inner_left half bottom 9487 mossy_cobblestone_stairs facing south waterlogged true shape inner_right half bottom 9488 mossy_cobblestone_stairs facing south waterlogged false shape inner_right half bottom 9489 mossy_cobblestone_stairs facing south waterlogged true shape outer_left half bottom 9490 mossy_cobblestone_stairs facing south waterlogged false shape outer_left half bottom 9491 mossy_cobblestone_stairs facing south waterlogged true shape outer_right half bottom 9492 mossy_cobblestone_stairs facing south waterlogged false shape outer_right half bottom 9493 mossy_cobblestone_stairs facing west waterlogged true shape straight half top 9494 mossy_cobblestone_stairs facing west waterlogged false shape straight half top 9495 mossy_cobblestone_stairs facing west waterlogged true shape inner_left half top 9496 mossy_cobblestone_stairs facing west waterlogged false shape inner_left half top 9497 mossy_cobblestone_stairs facing west waterlogged true shape inner_right half top 9498 mossy_cobblestone_stairs facing west waterlogged false shape inner_right half top 9499 mossy_cobblestone_stairs facing west waterlogged true shape outer_left half top 9500 mossy_cobblestone_stairs facing west waterlogged false shape outer_left half top 9501 mossy_cobblestone_stairs facing west waterlogged true shape outer_right half top 9502 mossy_cobblestone_stairs facing west waterlogged false shape outer_right half top 9503 mossy_cobblestone_stairs facing west waterlogged true shape straight half bottom 9504 mossy_cobblestone_stairs facing west waterlogged false shape straight half bottom 9505 mossy_cobblestone_stairs facing west waterlogged true shape inner_left half bottom 9506 mossy_cobblestone_stairs facing west waterlogged false shape inner_left half bottom 9507 mossy_cobblestone_stairs facing west waterlogged true shape inner_right half bottom 9508 mossy_cobblestone_stairs facing west waterlogged false shape inner_right half bottom 9509 mossy_cobblestone_stairs facing west waterlogged true shape outer_left half bottom 9510 mossy_cobblestone_stairs facing west waterlogged false shape outer_left half bottom 9511 mossy_cobblestone_stairs facing west waterlogged true shape outer_right half bottom 9512 mossy_cobblestone_stairs facing west waterlogged false shape outer_right half bottom 9513 mossy_cobblestone_stairs facing east waterlogged true shape straight half top 9514 mossy_cobblestone_stairs facing east waterlogged false shape straight half top 9515 mossy_cobblestone_stairs facing east waterlogged true shape inner_left half top 9516 mossy_cobblestone_stairs facing east waterlogged false shape inner_left half top 9517 mossy_cobblestone_stairs facing east waterlogged true shape inner_right half top 9518 mossy_cobblestone_stairs facing east waterlogged false shape inner_right half top 9519 mossy_cobblestone_stairs facing east waterlogged true shape outer_left half top 9520 mossy_cobblestone_stairs facing east waterlogged false shape outer_left half top 9521 mossy_cobblestone_stairs facing east waterlogged true shape outer_right half top 9522 mossy_cobblestone_stairs facing east waterlogged false shape outer_right half top 9523 mossy_cobblestone_stairs facing east waterlogged true shape straight half bottom 9524 mossy_cobblestone_stairs facing east waterlogged false shape straight half bottom 9525 mossy_cobblestone_stairs facing east waterlogged true shape inner_left half bottom 9526 mossy_cobblestone_stairs facing east waterlogged false shape inner_left half bottom 9527 mossy_cobblestone_stairs facing east waterlogged true shape inner_right half bottom 9528 mossy_cobblestone_stairs facing east waterlogged false shape inner_right half bottom 9529 mossy_cobblestone_stairs facing east waterlogged true shape outer_left half bottom 9530 mossy_cobblestone_stairs facing east waterlogged false shape outer_left half bottom 9531 mossy_cobblestone_stairs facing east waterlogged true shape outer_right half bottom 9532 mossy_cobblestone_stairs facing east waterlogged false shape outer_right half bottom 9533 end_stone_brick_stairs facing north waterlogged true shape straight half top 9534 end_stone_brick_stairs facing north waterlogged false shape straight half top 9535 end_stone_brick_stairs facing north waterlogged true shape inner_left half top 9536 end_stone_brick_stairs facing north waterlogged false shape inner_left half top 9537 end_stone_brick_stairs facing north waterlogged true shape inner_right half top 9538 end_stone_brick_stairs facing north waterlogged false shape inner_right half top 9539 end_stone_brick_stairs facing north waterlogged true shape outer_left half top 9540 end_stone_brick_stairs facing north waterlogged false shape outer_left half top 9541 end_stone_brick_stairs facing north waterlogged true shape outer_right half top 9542 end_stone_brick_stairs facing north waterlogged false shape outer_right half top 9543 end_stone_brick_stairs facing north waterlogged true shape straight half bottom 9544 end_stone_brick_stairs facing north waterlogged false shape straight half bottom 9545 end_stone_brick_stairs facing north waterlogged true shape inner_left half bottom 9546 end_stone_brick_stairs facing north waterlogged false shape inner_left half bottom 9547 end_stone_brick_stairs facing north waterlogged true shape inner_right half bottom 9548 end_stone_brick_stairs facing north waterlogged false shape inner_right half bottom 9549 end_stone_brick_stairs facing north waterlogged true shape outer_left half bottom 9550 end_stone_brick_stairs facing north waterlogged false shape outer_left half bottom 9551 end_stone_brick_stairs facing north waterlogged true shape outer_right half bottom 9552 end_stone_brick_stairs facing north waterlogged false shape outer_right half bottom 9553 end_stone_brick_stairs facing south waterlogged true shape straight half top 9554 end_stone_brick_stairs facing south waterlogged false shape straight half top 9555 end_stone_brick_stairs facing south waterlogged true shape inner_left half top 9556 end_stone_brick_stairs facing south waterlogged false shape inner_left half top 9557 end_stone_brick_stairs facing south waterlogged true shape inner_right half top 9558 end_stone_brick_stairs facing south waterlogged false shape inner_right half top 9559 end_stone_brick_stairs facing south waterlogged true shape outer_left half top 9560 end_stone_brick_stairs facing south waterlogged false shape outer_left half top 9561 end_stone_brick_stairs facing south waterlogged true shape outer_right half top 9562 end_stone_brick_stairs facing south waterlogged false shape outer_right half top 9563 end_stone_brick_stairs facing south waterlogged true shape straight half bottom 9564 end_stone_brick_stairs facing south waterlogged false shape straight half bottom 9565 end_stone_brick_stairs facing south waterlogged true shape inner_left half bottom 9566 end_stone_brick_stairs facing south waterlogged false shape inner_left half bottom 9567 end_stone_brick_stairs facing south waterlogged true shape inner_right half bottom 9568 end_stone_brick_stairs facing south waterlogged false shape inner_right half bottom 9569 end_stone_brick_stairs facing south waterlogged true shape outer_left half bottom 9570 end_stone_brick_stairs facing south waterlogged false shape outer_left half bottom 9571 end_stone_brick_stairs facing south waterlogged true shape outer_right half bottom 9572 end_stone_brick_stairs facing south waterlogged false shape outer_right half bottom 9573 end_stone_brick_stairs facing west waterlogged true shape straight half top 9574 end_stone_brick_stairs facing west waterlogged false shape straight half top 9575 end_stone_brick_stairs facing west waterlogged true shape inner_left half top 9576 end_stone_brick_stairs facing west waterlogged false shape inner_left half top 9577 end_stone_brick_stairs facing west waterlogged true shape inner_right half top 9578 end_stone_brick_stairs facing west waterlogged false shape inner_right half top 9579 end_stone_brick_stairs facing west waterlogged true shape outer_left half top 9580 end_stone_brick_stairs facing west waterlogged false shape outer_left half top 9581 end_stone_brick_stairs facing west waterlogged true shape outer_right half top 9582 end_stone_brick_stairs facing west waterlogged false shape outer_right half top 9583 end_stone_brick_stairs facing west waterlogged true shape straight half bottom 9584 end_stone_brick_stairs facing west waterlogged false shape straight half bottom 9585 end_stone_brick_stairs facing west waterlogged true shape inner_left half bottom 9586 end_stone_brick_stairs facing west waterlogged false shape inner_left half bottom 9587 end_stone_brick_stairs facing west waterlogged true shape inner_right half bottom 9588 end_stone_brick_stairs facing west waterlogged false shape inner_right half bottom 9589 end_stone_brick_stairs facing west waterlogged true shape outer_left half bottom 9590 end_stone_brick_stairs facing west waterlogged false shape outer_left half bottom 9591 end_stone_brick_stairs facing west waterlogged true shape outer_right half bottom 9592 end_stone_brick_stairs facing west waterlogged false shape outer_right half bottom 9593 end_stone_brick_stairs facing east waterlogged true shape straight half top 9594 end_stone_brick_stairs facing east waterlogged false shape straight half top 9595 end_stone_brick_stairs facing east waterlogged true shape inner_left half top 9596 end_stone_brick_stairs facing east waterlogged false shape inner_left half top 9597 end_stone_brick_stairs facing east waterlogged true shape inner_right half top 9598 end_stone_brick_stairs facing east waterlogged false shape inner_right half top 9599 end_stone_brick_stairs facing east waterlogged true shape outer_left half top 9600 end_stone_brick_stairs facing east waterlogged false shape outer_left half top 9601 end_stone_brick_stairs facing east waterlogged true shape outer_right half top 9602 end_stone_brick_stairs facing east waterlogged false shape outer_right half top 9603 end_stone_brick_stairs facing east waterlogged true shape straight half bottom 9604 end_stone_brick_stairs facing east waterlogged false shape straight half bottom 9605 end_stone_brick_stairs facing east waterlogged true shape inner_left half bottom 9606 end_stone_brick_stairs facing east waterlogged false shape inner_left half bottom 9607 end_stone_brick_stairs facing east waterlogged true shape inner_right half bottom 9608 end_stone_brick_stairs facing east waterlogged false shape inner_right half bottom 9609 end_stone_brick_stairs facing east waterlogged true shape outer_left half bottom 9610 end_stone_brick_stairs facing east waterlogged false shape outer_left half bottom 9611 end_stone_brick_stairs facing east waterlogged true shape outer_right half bottom 9612 end_stone_brick_stairs facing east waterlogged false shape outer_right half bottom 9613 stone_stairs facing north waterlogged true shape straight half top 9614 stone_stairs facing north waterlogged false shape straight half top 9615 stone_stairs facing north waterlogged true shape inner_left half top 9616 stone_stairs facing north waterlogged false shape inner_left half top 9617 stone_stairs facing north waterlogged true shape inner_right half top 9618 stone_stairs facing north waterlogged false shape inner_right half top 9619 stone_stairs facing north waterlogged true shape outer_left half top 9620 stone_stairs facing north waterlogged false shape outer_left half top 9621 stone_stairs facing north waterlogged true shape outer_right half top 9622 stone_stairs facing north waterlogged false shape outer_right half top 9623 stone_stairs facing north waterlogged true shape straight half bottom 9624 stone_stairs facing north waterlogged false shape straight half bottom 9625 stone_stairs facing north waterlogged true shape inner_left half bottom 9626 stone_stairs facing north waterlogged false shape inner_left half bottom 9627 stone_stairs facing north waterlogged true shape inner_right half bottom 9628 stone_stairs facing north waterlogged false shape inner_right half bottom 9629 stone_stairs facing north waterlogged true shape outer_left half bottom 9630 stone_stairs facing north waterlogged false shape outer_left half bottom 9631 stone_stairs facing north waterlogged true shape outer_right half bottom 9632 stone_stairs facing north waterlogged false shape outer_right half bottom 9633 stone_stairs facing south waterlogged true shape straight half top 9634 stone_stairs facing south waterlogged false shape straight half top 9635 stone_stairs facing south waterlogged true shape inner_left half top 9636 stone_stairs facing south waterlogged false shape inner_left half top 9637 stone_stairs facing south waterlogged true shape inner_right half top 9638 stone_stairs facing south waterlogged false shape inner_right half top 9639 stone_stairs facing south waterlogged true shape outer_left half top 9640 stone_stairs facing south waterlogged false shape outer_left half top 9641 stone_stairs facing south waterlogged true shape outer_right half top 9642 stone_stairs facing south waterlogged false shape outer_right half top 9643 stone_stairs facing south waterlogged true shape straight half bottom 9644 stone_stairs facing south waterlogged false shape straight half bottom 9645 stone_stairs facing south waterlogged true shape inner_left half bottom 9646 stone_stairs facing south waterlogged false shape inner_left half bottom 9647 stone_stairs facing south waterlogged true shape inner_right half bottom 9648 stone_stairs facing south waterlogged false shape inner_right half bottom 9649 stone_stairs facing south waterlogged true shape outer_left half bottom 9650 stone_stairs facing south waterlogged false shape outer_left half bottom 9651 stone_stairs facing south waterlogged true shape outer_right half bottom 9652 stone_stairs facing south waterlogged false shape outer_right half bottom 9653 stone_stairs facing west waterlogged true shape straight half top 9654 stone_stairs facing west waterlogged false shape straight half top 9655 stone_stairs facing west waterlogged true shape inner_left half top 9656 stone_stairs facing west waterlogged false shape inner_left half top 9657 stone_stairs facing west waterlogged true shape inner_right half top 9658 stone_stairs facing west waterlogged false shape inner_right half top 9659 stone_stairs facing west waterlogged true shape outer_left half top 9660 stone_stairs facing west waterlogged false shape outer_left half top 9661 stone_stairs facing west waterlogged true shape outer_right half top 9662 stone_stairs facing west waterlogged false shape outer_right half top 9663 stone_stairs facing west waterlogged true shape straight half bottom 9664 stone_stairs facing west waterlogged false shape straight half bottom 9665 stone_stairs facing west waterlogged true shape inner_left half bottom 9666 stone_stairs facing west waterlogged false shape inner_left half bottom 9667 stone_stairs facing west waterlogged true shape inner_right half bottom 9668 stone_stairs facing west waterlogged false shape inner_right half bottom 9669 stone_stairs facing west waterlogged true shape outer_left half bottom 9670 stone_stairs facing west waterlogged false shape outer_left half bottom 9671 stone_stairs facing west waterlogged true shape outer_right half bottom 9672 stone_stairs facing west waterlogged false shape outer_right half bottom 9673 stone_stairs facing east waterlogged true shape straight half top 9674 stone_stairs facing east waterlogged false shape straight half top 9675 stone_stairs facing east waterlogged true shape inner_left half top 9676 stone_stairs facing east waterlogged false shape inner_left half top 9677 stone_stairs facing east waterlogged true shape inner_right half top 9678 stone_stairs facing east waterlogged false shape inner_right half top 9679 stone_stairs facing east waterlogged true shape outer_left half top 9680 stone_stairs facing east waterlogged false shape outer_left half top 9681 stone_stairs facing east waterlogged true shape outer_right half top 9682 stone_stairs facing east waterlogged false shape outer_right half top 9683 stone_stairs facing east waterlogged true shape straight half bottom 9684 stone_stairs facing east waterlogged false shape straight half bottom 9685 stone_stairs facing east waterlogged true shape inner_left half bottom 9686 stone_stairs facing east waterlogged false shape inner_left half bottom 9687 stone_stairs facing east waterlogged true shape inner_right half bottom 9688 stone_stairs facing east waterlogged false shape inner_right half bottom 9689 stone_stairs facing east waterlogged true shape outer_left half bottom 9690 stone_stairs facing east waterlogged false shape outer_left half bottom 9691 stone_stairs facing east waterlogged true shape outer_right half bottom 9692 stone_stairs facing east waterlogged false shape outer_right half bottom 9693 smooth_sandstone_stairs facing north waterlogged true shape straight half top 9694 smooth_sandstone_stairs facing north waterlogged false shape straight half top 9695 smooth_sandstone_stairs facing north waterlogged true shape inner_left half top 9696 smooth_sandstone_stairs facing north waterlogged false shape inner_left half top 9697 smooth_sandstone_stairs facing north waterlogged true shape inner_right half top 9698 smooth_sandstone_stairs facing north waterlogged false shape inner_right half top 9699 smooth_sandstone_stairs facing north waterlogged true shape outer_left half top 9700 smooth_sandstone_stairs facing north waterlogged false shape outer_left half top 9701 smooth_sandstone_stairs facing north waterlogged true shape outer_right half top 9702 smooth_sandstone_stairs facing north waterlogged false shape outer_right half top 9703 smooth_sandstone_stairs facing north waterlogged true shape straight half bottom 9704 smooth_sandstone_stairs facing north waterlogged false shape straight half bottom 9705 smooth_sandstone_stairs facing north waterlogged true shape inner_left half bottom 9706 smooth_sandstone_stairs facing north waterlogged false shape inner_left half bottom 9707 smooth_sandstone_stairs facing north waterlogged true shape inner_right half bottom 9708 smooth_sandstone_stairs facing north waterlogged false shape inner_right half bottom 9709 smooth_sandstone_stairs facing north waterlogged true shape outer_left half bottom 9710 smooth_sandstone_stairs facing north waterlogged false shape outer_left half bottom 9711 smooth_sandstone_stairs facing north waterlogged true shape outer_right half bottom 9712 smooth_sandstone_stairs facing north waterlogged false shape outer_right half bottom 9713 smooth_sandstone_stairs facing south waterlogged true shape straight half top 9714 smooth_sandstone_stairs facing south waterlogged false shape straight half top 9715 smooth_sandstone_stairs facing south waterlogged true shape inner_left half top 9716 smooth_sandstone_stairs facing south waterlogged false shape inner_left half top 9717 smooth_sandstone_stairs facing south waterlogged true shape inner_right half top 9718 smooth_sandstone_stairs facing south waterlogged false shape inner_right half top 9719 smooth_sandstone_stairs facing south waterlogged true shape outer_left half top 9720 smooth_sandstone_stairs facing south waterlogged false shape outer_left half top 9721 smooth_sandstone_stairs facing south waterlogged true shape outer_right half top 9722 smooth_sandstone_stairs facing south waterlogged false shape outer_right half top 9723 smooth_sandstone_stairs facing south waterlogged true shape straight half bottom 9724 smooth_sandstone_stairs facing south waterlogged false shape straight half bottom 9725 smooth_sandstone_stairs facing south waterlogged true shape inner_left half bottom 9726 smooth_sandstone_stairs facing south waterlogged false shape inner_left half bottom 9727 smooth_sandstone_stairs facing south waterlogged true shape inner_right half bottom 9728 smooth_sandstone_stairs facing south waterlogged false shape inner_right half bottom 9729 smooth_sandstone_stairs facing south waterlogged true shape outer_left half bottom 9730 smooth_sandstone_stairs facing south waterlogged false shape outer_left half bottom 9731 smooth_sandstone_stairs facing south waterlogged true shape outer_right half bottom 9732 smooth_sandstone_stairs facing south waterlogged false shape outer_right half bottom 9733 smooth_sandstone_stairs facing west waterlogged true shape straight half top 9734 smooth_sandstone_stairs facing west waterlogged false shape straight half top 9735 smooth_sandstone_stairs facing west waterlogged true shape inner_left half top 9736 smooth_sandstone_stairs facing west waterlogged false shape inner_left half top 9737 smooth_sandstone_stairs facing west waterlogged true shape inner_right half top 9738 smooth_sandstone_stairs facing west waterlogged false shape inner_right half top 9739 smooth_sandstone_stairs facing west waterlogged true shape outer_left half top 9740 smooth_sandstone_stairs facing west waterlogged false shape outer_left half top 9741 smooth_sandstone_stairs facing west waterlogged true shape outer_right half top 9742 smooth_sandstone_stairs facing west waterlogged false shape outer_right half top 9743 smooth_sandstone_stairs facing west waterlogged true shape straight half bottom 9744 smooth_sandstone_stairs facing west waterlogged false shape straight half bottom 9745 smooth_sandstone_stairs facing west waterlogged true shape inner_left half bottom 9746 smooth_sandstone_stairs facing west waterlogged false shape inner_left half bottom 9747 smooth_sandstone_stairs facing west waterlogged true shape inner_right half bottom 9748 smooth_sandstone_stairs facing west waterlogged false shape inner_right half bottom 9749 smooth_sandstone_stairs facing west waterlogged true shape outer_left half bottom 9750 smooth_sandstone_stairs facing west waterlogged false shape outer_left half bottom 9751 smooth_sandstone_stairs facing west waterlogged true shape outer_right half bottom 9752 smooth_sandstone_stairs facing west waterlogged false shape outer_right half bottom 9753 smooth_sandstone_stairs facing east waterlogged true shape straight half top 9754 smooth_sandstone_stairs facing east waterlogged false shape straight half top 9755 smooth_sandstone_stairs facing east waterlogged true shape inner_left half top 9756 smooth_sandstone_stairs facing east waterlogged false shape inner_left half top 9757 smooth_sandstone_stairs facing east waterlogged true shape inner_right half top 9758 smooth_sandstone_stairs facing east waterlogged false shape inner_right half top 9759 smooth_sandstone_stairs facing east waterlogged true shape outer_left half top 9760 smooth_sandstone_stairs facing east waterlogged false shape outer_left half top 9761 smooth_sandstone_stairs facing east waterlogged true shape outer_right half top 9762 smooth_sandstone_stairs facing east waterlogged false shape outer_right half top 9763 smooth_sandstone_stairs facing east waterlogged true shape straight half bottom 9764 smooth_sandstone_stairs facing east waterlogged false shape straight half bottom 9765 smooth_sandstone_stairs facing east waterlogged true shape inner_left half bottom 9766 smooth_sandstone_stairs facing east waterlogged false shape inner_left half bottom 9767 smooth_sandstone_stairs facing east waterlogged true shape inner_right half bottom 9768 smooth_sandstone_stairs facing east waterlogged false shape inner_right half bottom 9769 smooth_sandstone_stairs facing east waterlogged true shape outer_left half bottom 9770 smooth_sandstone_stairs facing east waterlogged false shape outer_left half bottom 9771 smooth_sandstone_stairs facing east waterlogged true shape outer_right half bottom 9772 smooth_sandstone_stairs facing east waterlogged false shape outer_right half bottom 9773 smooth_quartz_stairs facing north waterlogged true shape straight half top 9774 smooth_quartz_stairs facing north waterlogged false shape straight half top 9775 smooth_quartz_stairs facing north waterlogged true shape inner_left half top 9776 smooth_quartz_stairs facing north waterlogged false shape inner_left half top 9777 smooth_quartz_stairs facing north waterlogged true shape inner_right half top 9778 smooth_quartz_stairs facing north waterlogged false shape inner_right half top 9779 smooth_quartz_stairs facing north waterlogged true shape outer_left half top 9780 smooth_quartz_stairs facing north waterlogged false shape outer_left half top 9781 smooth_quartz_stairs facing north waterlogged true shape outer_right half top 9782 smooth_quartz_stairs facing north waterlogged false shape outer_right half top 9783 smooth_quartz_stairs facing north waterlogged true shape straight half bottom 9784 smooth_quartz_stairs facing north waterlogged false shape straight half bottom 9785 smooth_quartz_stairs facing north waterlogged true shape inner_left half bottom 9786 smooth_quartz_stairs facing north waterlogged false shape inner_left half bottom 9787 smooth_quartz_stairs facing north waterlogged true shape inner_right half bottom 9788 smooth_quartz_stairs facing north waterlogged false shape inner_right half bottom 9789 smooth_quartz_stairs facing north waterlogged true shape outer_left half bottom 9790 smooth_quartz_stairs facing north waterlogged false shape outer_left half bottom 9791 smooth_quartz_stairs facing north waterlogged true shape outer_right half bottom 9792 smooth_quartz_stairs facing north waterlogged false shape outer_right half bottom 9793 smooth_quartz_stairs facing south waterlogged true shape straight half top 9794 smooth_quartz_stairs facing south waterlogged false shape straight half top 9795 smooth_quartz_stairs facing south waterlogged true shape inner_left half top 9796 smooth_quartz_stairs facing south waterlogged false shape inner_left half top 9797 smooth_quartz_stairs facing south waterlogged true shape inner_right half top 9798 smooth_quartz_stairs facing south waterlogged false shape inner_right half top 9799 smooth_quartz_stairs facing south waterlogged true shape outer_left half top 9800 smooth_quartz_stairs facing south waterlogged false shape outer_left half top 9801 smooth_quartz_stairs facing south waterlogged true shape outer_right half top 9802 smooth_quartz_stairs facing south waterlogged false shape outer_right half top 9803 smooth_quartz_stairs facing south waterlogged true shape straight half bottom 9804 smooth_quartz_stairs facing south waterlogged false shape straight half bottom 9805 smooth_quartz_stairs facing south waterlogged true shape inner_left half bottom 9806 smooth_quartz_stairs facing south waterlogged false shape inner_left half bottom 9807 smooth_quartz_stairs facing south waterlogged true shape inner_right half bottom 9808 smooth_quartz_stairs facing south waterlogged false shape inner_right half bottom 9809 smooth_quartz_stairs facing south waterlogged true shape outer_left half bottom 9810 smooth_quartz_stairs facing south waterlogged false shape outer_left half bottom 9811 smooth_quartz_stairs facing south waterlogged true shape outer_right half bottom 9812 smooth_quartz_stairs facing south waterlogged false shape outer_right half bottom 9813 smooth_quartz_stairs facing west waterlogged true shape straight half top 9814 smooth_quartz_stairs facing west waterlogged false shape straight half top 9815 smooth_quartz_stairs facing west waterlogged true shape inner_left half top 9816 smooth_quartz_stairs facing west waterlogged false shape inner_left half top 9817 smooth_quartz_stairs facing west waterlogged true shape inner_right half top 9818 smooth_quartz_stairs facing west waterlogged false shape inner_right half top 9819 smooth_quartz_stairs facing west waterlogged true shape outer_left half top 9820 smooth_quartz_stairs facing west waterlogged false shape outer_left half top 9821 smooth_quartz_stairs facing west waterlogged true shape outer_right half top 9822 smooth_quartz_stairs facing west waterlogged false shape outer_right half top 9823 smooth_quartz_stairs facing west waterlogged true shape straight half bottom 9824 smooth_quartz_stairs facing west waterlogged false shape straight half bottom 9825 smooth_quartz_stairs facing west waterlogged true shape inner_left half bottom 9826 smooth_quartz_stairs facing west waterlogged false shape inner_left half bottom 9827 smooth_quartz_stairs facing west waterlogged true shape inner_right half bottom 9828 smooth_quartz_stairs facing west waterlogged false shape inner_right half bottom 9829 smooth_quartz_stairs facing west waterlogged true shape outer_left half bottom 9830 smooth_quartz_stairs facing west waterlogged false shape outer_left half bottom 9831 smooth_quartz_stairs facing west waterlogged true shape outer_right half bottom 9832 smooth_quartz_stairs facing west waterlogged false shape outer_right half bottom 9833 smooth_quartz_stairs facing east waterlogged true shape straight half top 9834 smooth_quartz_stairs facing east waterlogged false shape straight half top 9835 smooth_quartz_stairs facing east waterlogged true shape inner_left half top 9836 smooth_quartz_stairs facing east waterlogged false shape inner_left half top 9837 smooth_quartz_stairs facing east waterlogged true shape inner_right half top 9838 smooth_quartz_stairs facing east waterlogged false shape inner_right half top 9839 smooth_quartz_stairs facing east waterlogged true shape outer_left half top 9840 smooth_quartz_stairs facing east waterlogged false shape outer_left half top 9841 smooth_quartz_stairs facing east waterlogged true shape outer_right half top 9842 smooth_quartz_stairs facing east waterlogged false shape outer_right half top 9843 smooth_quartz_stairs facing east waterlogged true shape straight half bottom 9844 smooth_quartz_stairs facing east waterlogged false shape straight half bottom 9845 smooth_quartz_stairs facing east waterlogged true shape inner_left half bottom 9846 smooth_quartz_stairs facing east waterlogged false shape inner_left half bottom 9847 smooth_quartz_stairs facing east waterlogged true shape inner_right half bottom 9848 smooth_quartz_stairs facing east waterlogged false shape inner_right half bottom 9849 smooth_quartz_stairs facing east waterlogged true shape outer_left half bottom 9850 smooth_quartz_stairs facing east waterlogged false shape outer_left half bottom 9851 smooth_quartz_stairs facing east waterlogged true shape outer_right half bottom 9852 smooth_quartz_stairs facing east waterlogged false shape outer_right half bottom 9853 granite_stairs facing north waterlogged true shape straight half top 9854 granite_stairs facing north waterlogged false shape straight half top 9855 granite_stairs facing north waterlogged true shape inner_left half top 9856 granite_stairs facing north waterlogged false shape inner_left half top 9857 granite_stairs facing north waterlogged true shape inner_right half top 9858 granite_stairs facing north waterlogged false shape inner_right half top 9859 granite_stairs facing north waterlogged true shape outer_left half top 9860 granite_stairs facing north waterlogged false shape outer_left half top 9861 granite_stairs facing north waterlogged true shape outer_right half top 9862 granite_stairs facing north waterlogged false shape outer_right half top 9863 granite_stairs facing north waterlogged true shape straight half bottom 9864 granite_stairs facing north waterlogged false shape straight half bottom 9865 granite_stairs facing north waterlogged true shape inner_left half bottom 9866 granite_stairs facing north waterlogged false shape inner_left half bottom 9867 granite_stairs facing north waterlogged true shape inner_right half bottom 9868 granite_stairs facing north waterlogged false shape inner_right half bottom 9869 granite_stairs facing north waterlogged true shape outer_left half bottom 9870 granite_stairs facing north waterlogged false shape outer_left half bottom 9871 granite_stairs facing north waterlogged true shape outer_right half bottom 9872 granite_stairs facing north waterlogged false shape outer_right half bottom 9873 granite_stairs facing south waterlogged true shape straight half top 9874 granite_stairs facing south waterlogged false shape straight half top 9875 granite_stairs facing south waterlogged true shape inner_left half top 9876 granite_stairs facing south waterlogged false shape inner_left half top 9877 granite_stairs facing south waterlogged true shape inner_right half top 9878 granite_stairs facing south waterlogged false shape inner_right half top 9879 granite_stairs facing south waterlogged true shape outer_left half top 9880 granite_stairs facing south waterlogged false shape outer_left half top 9881 granite_stairs facing south waterlogged true shape outer_right half top 9882 granite_stairs facing south waterlogged false shape outer_right half top 9883 granite_stairs facing south waterlogged true shape straight half bottom 9884 granite_stairs facing south waterlogged false shape straight half bottom 9885 granite_stairs facing south waterlogged true shape inner_left half bottom 9886 granite_stairs facing south waterlogged false shape inner_left half bottom 9887 granite_stairs facing south waterlogged true shape inner_right half bottom 9888 granite_stairs facing south waterlogged false shape inner_right half bottom 9889 granite_stairs facing south waterlogged true shape outer_left half bottom 9890 granite_stairs facing south waterlogged false shape outer_left half bottom 9891 granite_stairs facing south waterlogged true shape outer_right half bottom 9892 granite_stairs facing south waterlogged false shape outer_right half bottom 9893 granite_stairs facing west waterlogged true shape straight half top 9894 granite_stairs facing west waterlogged false shape straight half top 9895 granite_stairs facing west waterlogged true shape inner_left half top 9896 granite_stairs facing west waterlogged false shape inner_left half top 9897 granite_stairs facing west waterlogged true shape inner_right half top 9898 granite_stairs facing west waterlogged false shape inner_right half top 9899 granite_stairs facing west waterlogged true shape outer_left half top 9900 granite_stairs facing west waterlogged false shape outer_left half top 9901 granite_stairs facing west waterlogged true shape outer_right half top 9902 granite_stairs facing west waterlogged false shape outer_right half top 9903 granite_stairs facing west waterlogged true shape straight half bottom 9904 granite_stairs facing west waterlogged false shape straight half bottom 9905 granite_stairs facing west waterlogged true shape inner_left half bottom 9906 granite_stairs facing west waterlogged false shape inner_left half bottom 9907 granite_stairs facing west waterlogged true shape inner_right half bottom 9908 granite_stairs facing west waterlogged false shape inner_right half bottom 9909 granite_stairs facing west waterlogged true shape outer_left half bottom 9910 granite_stairs facing west waterlogged false shape outer_left half bottom 9911 granite_stairs facing west waterlogged true shape outer_right half bottom 9912 granite_stairs facing west waterlogged false shape outer_right half bottom 9913 granite_stairs facing east waterlogged true shape straight half top 9914 granite_stairs facing east waterlogged false shape straight half top 9915 granite_stairs facing east waterlogged true shape inner_left half top 9916 granite_stairs facing east waterlogged false shape inner_left half top 9917 granite_stairs facing east waterlogged true shape inner_right half top 9918 granite_stairs facing east waterlogged false shape inner_right half top 9919 granite_stairs facing east waterlogged true shape outer_left half top 9920 granite_stairs facing east waterlogged false shape outer_left half top 9921 granite_stairs facing east waterlogged true shape outer_right half top 9922 granite_stairs facing east waterlogged false shape outer_right half top 9923 granite_stairs facing east waterlogged true shape straight half bottom 9924 granite_stairs facing east waterlogged false shape straight half bottom 9925 granite_stairs facing east waterlogged true shape inner_left half bottom 9926 granite_stairs facing east waterlogged false shape inner_left half bottom 9927 granite_stairs facing east waterlogged true shape inner_right half bottom 9928 granite_stairs facing east waterlogged false shape inner_right half bottom 9929 granite_stairs facing east waterlogged true shape outer_left half bottom 9930 granite_stairs facing east waterlogged false shape outer_left half bottom 9931 granite_stairs facing east waterlogged true shape outer_right half bottom 9932 granite_stairs facing east waterlogged false shape outer_right half bottom 9933 andesite_stairs facing north waterlogged true shape straight half top 9934 andesite_stairs facing north waterlogged false shape straight half top 9935 andesite_stairs facing north waterlogged true shape inner_left half top 9936 andesite_stairs facing north waterlogged false shape inner_left half top 9937 andesite_stairs facing north waterlogged true shape inner_right half top 9938 andesite_stairs facing north waterlogged false shape inner_right half top 9939 andesite_stairs facing north waterlogged true shape outer_left half top 9940 andesite_stairs facing north waterlogged false shape outer_left half top 9941 andesite_stairs facing north waterlogged true shape outer_right half top 9942 andesite_stairs facing north waterlogged false shape outer_right half top 9943 andesite_stairs facing north waterlogged true shape straight half bottom 9944 andesite_stairs facing north waterlogged false shape straight half bottom 9945 andesite_stairs facing north waterlogged true shape inner_left half bottom 9946 andesite_stairs facing north waterlogged false shape inner_left half bottom 9947 andesite_stairs facing north waterlogged true shape inner_right half bottom 9948 andesite_stairs facing north waterlogged false shape inner_right half bottom 9949 andesite_stairs facing north waterlogged true shape outer_left half bottom 9950 andesite_stairs facing north waterlogged false shape outer_left half bottom 9951 andesite_stairs facing north waterlogged true shape outer_right half bottom 9952 andesite_stairs facing north waterlogged false shape outer_right half bottom 9953 andesite_stairs facing south waterlogged true shape straight half top 9954 andesite_stairs facing south waterlogged false shape straight half top 9955 andesite_stairs facing south waterlogged true shape inner_left half top 9956 andesite_stairs facing south waterlogged false shape inner_left half top 9957 andesite_stairs facing south waterlogged true shape inner_right half top 9958 andesite_stairs facing south waterlogged false shape inner_right half top 9959 andesite_stairs facing south waterlogged true shape outer_left half top 9960 andesite_stairs facing south waterlogged false shape outer_left half top 9961 andesite_stairs facing south waterlogged true shape outer_right half top 9962 andesite_stairs facing south waterlogged false shape outer_right half top 9963 andesite_stairs facing south waterlogged true shape straight half bottom 9964 andesite_stairs facing south waterlogged false shape straight half bottom 9965 andesite_stairs facing south waterlogged true shape inner_left half bottom 9966 andesite_stairs facing south waterlogged false shape inner_left half bottom 9967 andesite_stairs facing south waterlogged true shape inner_right half bottom 9968 andesite_stairs facing south waterlogged false shape inner_right half bottom 9969 andesite_stairs facing south waterlogged true shape outer_left half bottom 9970 andesite_stairs facing south waterlogged false shape outer_left half bottom 9971 andesite_stairs facing south waterlogged true shape outer_right half bottom 9972 andesite_stairs facing south waterlogged false shape outer_right half bottom 9973 andesite_stairs facing west waterlogged true shape straight half top 9974 andesite_stairs facing west waterlogged false shape straight half top 9975 andesite_stairs facing west waterlogged true shape inner_left half top 9976 andesite_stairs facing west waterlogged false shape inner_left half top 9977 andesite_stairs facing west waterlogged true shape inner_right half top 9978 andesite_stairs facing west waterlogged false shape inner_right half top 9979 andesite_stairs facing west waterlogged true shape outer_left half top 9980 andesite_stairs facing west waterlogged false shape outer_left half top 9981 andesite_stairs facing west waterlogged true shape outer_right half top 9982 andesite_stairs facing west waterlogged false shape outer_right half top 9983 andesite_stairs facing west waterlogged true shape straight half bottom 9984 andesite_stairs facing west waterlogged false shape straight half bottom 9985 andesite_stairs facing west waterlogged true shape inner_left half bottom 9986 andesite_stairs facing west waterlogged false shape inner_left half bottom 9987 andesite_stairs facing west waterlogged true shape inner_right half bottom 9988 andesite_stairs facing west waterlogged false shape inner_right half bottom 9989 andesite_stairs facing west waterlogged true shape outer_left half bottom 9990 andesite_stairs facing west waterlogged false shape outer_left half bottom 9991 andesite_stairs facing west waterlogged true shape outer_right half bottom 9992 andesite_stairs facing west waterlogged false shape outer_right half bottom 9993 andesite_stairs facing east waterlogged true shape straight half top 9994 andesite_stairs facing east waterlogged false shape straight half top 9995 andesite_stairs facing east waterlogged true shape inner_left half top 9996 andesite_stairs facing east waterlogged false shape inner_left half top 9997 andesite_stairs facing east waterlogged true shape inner_right half top 9998 andesite_stairs facing east waterlogged false shape inner_right half top 9999 andesite_stairs facing east waterlogged true shape outer_left half top 10000 andesite_stairs facing east waterlogged false shape outer_left half top 10001 andesite_stairs facing east waterlogged true shape outer_right half top 10002 andesite_stairs facing east waterlogged false shape outer_right half top 10003 andesite_stairs facing east waterlogged true shape straight half bottom 10004 andesite_stairs facing east waterlogged false shape straight half bottom 10005 andesite_stairs facing east waterlogged true shape inner_left half bottom 10006 andesite_stairs facing east waterlogged false shape inner_left half bottom 10007 andesite_stairs facing east waterlogged true shape inner_right half bottom 10008 andesite_stairs facing east waterlogged false shape inner_right half bottom 10009 andesite_stairs facing east waterlogged true shape outer_left half bottom 10010 andesite_stairs facing east waterlogged false shape outer_left half bottom 10011 andesite_stairs facing east waterlogged true shape outer_right half bottom 10012 andesite_stairs facing east waterlogged false shape outer_right half bottom 10013 red_nether_brick_stairs facing north waterlogged true shape straight half top 10014 red_nether_brick_stairs facing north waterlogged false shape straight half top 10015 red_nether_brick_stairs facing north waterlogged true shape inner_left half top 10016 red_nether_brick_stairs facing north waterlogged false shape inner_left half top 10017 red_nether_brick_stairs facing north waterlogged true shape inner_right half top 10018 red_nether_brick_stairs facing north waterlogged false shape inner_right half top 10019 red_nether_brick_stairs facing north waterlogged true shape outer_left half top 10020 red_nether_brick_stairs facing north waterlogged false shape outer_left half top 10021 red_nether_brick_stairs facing north waterlogged true shape outer_right half top 10022 red_nether_brick_stairs facing north waterlogged false shape outer_right half top 10023 red_nether_brick_stairs facing north waterlogged true shape straight half bottom 10024 red_nether_brick_stairs facing north waterlogged false shape straight half bottom 10025 red_nether_brick_stairs facing north waterlogged true shape inner_left half bottom 10026 red_nether_brick_stairs facing north waterlogged false shape inner_left half bottom 10027 red_nether_brick_stairs facing north waterlogged true shape inner_right half bottom 10028 red_nether_brick_stairs facing north waterlogged false shape inner_right half bottom 10029 red_nether_brick_stairs facing north waterlogged true shape outer_left half bottom 10030 red_nether_brick_stairs facing north waterlogged false shape outer_left half bottom 10031 red_nether_brick_stairs facing north waterlogged true shape outer_right half bottom 10032 red_nether_brick_stairs facing north waterlogged false shape outer_right half bottom 10033 red_nether_brick_stairs facing south waterlogged true shape straight half top 10034 red_nether_brick_stairs facing south waterlogged false shape straight half top 10035 red_nether_brick_stairs facing south waterlogged true shape inner_left half top 10036 red_nether_brick_stairs facing south waterlogged false shape inner_left half top 10037 red_nether_brick_stairs facing south waterlogged true shape inner_right half top 10038 red_nether_brick_stairs facing south waterlogged false shape inner_right half top 10039 red_nether_brick_stairs facing south waterlogged true shape outer_left half top 10040 red_nether_brick_stairs facing south waterlogged false shape outer_left half top 10041 red_nether_brick_stairs facing south waterlogged true shape outer_right half top 10042 red_nether_brick_stairs facing south waterlogged false shape outer_right half top 10043 red_nether_brick_stairs facing south waterlogged true shape straight half bottom 10044 red_nether_brick_stairs facing south waterlogged false shape straight half bottom 10045 red_nether_brick_stairs facing south waterlogged true shape inner_left half bottom 10046 red_nether_brick_stairs facing south waterlogged false shape inner_left half bottom 10047 red_nether_brick_stairs facing south waterlogged true shape inner_right half bottom 10048 red_nether_brick_stairs facing south waterlogged false shape inner_right half bottom 10049 red_nether_brick_stairs facing south waterlogged true shape outer_left half bottom 10050 red_nether_brick_stairs facing south waterlogged false shape outer_left half bottom 10051 red_nether_brick_stairs facing south waterlogged true shape outer_right half bottom 10052 red_nether_brick_stairs facing south waterlogged false shape outer_right half bottom 10053 red_nether_brick_stairs facing west waterlogged true shape straight half top 10054 red_nether_brick_stairs facing west waterlogged false shape straight half top 10055 red_nether_brick_stairs facing west waterlogged true shape inner_left half top 10056 red_nether_brick_stairs facing west waterlogged false shape inner_left half top 10057 red_nether_brick_stairs facing west waterlogged true shape inner_right half top 10058 red_nether_brick_stairs facing west waterlogged false shape inner_right half top 10059 red_nether_brick_stairs facing west waterlogged true shape outer_left half top 10060 red_nether_brick_stairs facing west waterlogged false shape outer_left half top 10061 red_nether_brick_stairs facing west waterlogged true shape outer_right half top 10062 red_nether_brick_stairs facing west waterlogged false shape outer_right half top 10063 red_nether_brick_stairs facing west waterlogged true shape straight half bottom 10064 red_nether_brick_stairs facing west waterlogged false shape straight half bottom 10065 red_nether_brick_stairs facing west waterlogged true shape inner_left half bottom 10066 red_nether_brick_stairs facing west waterlogged false shape inner_left half bottom 10067 red_nether_brick_stairs facing west waterlogged true shape inner_right half bottom 10068 red_nether_brick_stairs facing west waterlogged false shape inner_right half bottom 10069 red_nether_brick_stairs facing west waterlogged true shape outer_left half bottom 10070 red_nether_brick_stairs facing west waterlogged false shape outer_left half bottom 10071 red_nether_brick_stairs facing west waterlogged true shape outer_right half bottom 10072 red_nether_brick_stairs facing west waterlogged false shape outer_right half bottom 10073 red_nether_brick_stairs facing east waterlogged true shape straight half top 10074 red_nether_brick_stairs facing east waterlogged false shape straight half top 10075 red_nether_brick_stairs facing east waterlogged true shape inner_left half top 10076 red_nether_brick_stairs facing east waterlogged false shape inner_left half top 10077 red_nether_brick_stairs facing east waterlogged true shape inner_right half top 10078 red_nether_brick_stairs facing east waterlogged false shape inner_right half top 10079 red_nether_brick_stairs facing east waterlogged true shape outer_left half top 10080 red_nether_brick_stairs facing east waterlogged false shape outer_left half top 10081 red_nether_brick_stairs facing east waterlogged true shape outer_right half top 10082 red_nether_brick_stairs facing east waterlogged false shape outer_right half top 10083 red_nether_brick_stairs facing east waterlogged true shape straight half bottom 10084 red_nether_brick_stairs facing east waterlogged false shape straight half bottom 10085 red_nether_brick_stairs facing east waterlogged true shape inner_left half bottom 10086 red_nether_brick_stairs facing east waterlogged false shape inner_left half bottom 10087 red_nether_brick_stairs facing east waterlogged true shape inner_right half bottom 10088 red_nether_brick_stairs facing east waterlogged false shape inner_right half bottom 10089 red_nether_brick_stairs facing east waterlogged true shape outer_left half bottom 10090 red_nether_brick_stairs facing east waterlogged false shape outer_left half bottom 10091 red_nether_brick_stairs facing east waterlogged true shape outer_right half bottom 10092 red_nether_brick_stairs facing east waterlogged false shape outer_right half bottom 10093 polished_andesite_stairs facing north waterlogged true shape straight half top 10094 polished_andesite_stairs facing north waterlogged false shape straight half top 10095 polished_andesite_stairs facing north waterlogged true shape inner_left half top 10096 polished_andesite_stairs facing north waterlogged false shape inner_left half top 10097 polished_andesite_stairs facing north waterlogged true shape inner_right half top 10098 polished_andesite_stairs facing north waterlogged false shape inner_right half top 10099 polished_andesite_stairs facing north waterlogged true shape outer_left half top 10100 polished_andesite_stairs facing north waterlogged false shape outer_left half top 10101 polished_andesite_stairs facing north waterlogged true shape outer_right half top 10102 polished_andesite_stairs facing north waterlogged false shape outer_right half top 10103 polished_andesite_stairs facing north waterlogged true shape straight half bottom 10104 polished_andesite_stairs facing north waterlogged false shape straight half bottom 10105 polished_andesite_stairs facing north waterlogged true shape inner_left half bottom 10106 polished_andesite_stairs facing north waterlogged false shape inner_left half bottom 10107 polished_andesite_stairs facing north waterlogged true shape inner_right half bottom 10108 polished_andesite_stairs facing north waterlogged false shape inner_right half bottom 10109 polished_andesite_stairs facing north waterlogged true shape outer_left half bottom 10110 polished_andesite_stairs facing north waterlogged false shape outer_left half bottom 10111 polished_andesite_stairs facing north waterlogged true shape outer_right half bottom 10112 polished_andesite_stairs facing north waterlogged false shape outer_right half bottom 10113 polished_andesite_stairs facing south waterlogged true shape straight half top 10114 polished_andesite_stairs facing south waterlogged false shape straight half top 10115 polished_andesite_stairs facing south waterlogged true shape inner_left half top 10116 polished_andesite_stairs facing south waterlogged false shape inner_left half top 10117 polished_andesite_stairs facing south waterlogged true shape inner_right half top 10118 polished_andesite_stairs facing south waterlogged false shape inner_right half top 10119 polished_andesite_stairs facing south waterlogged true shape outer_left half top 10120 polished_andesite_stairs facing south waterlogged false shape outer_left half top 10121 polished_andesite_stairs facing south waterlogged true shape outer_right half top 10122 polished_andesite_stairs facing south waterlogged false shape outer_right half top 10123 polished_andesite_stairs facing south waterlogged true shape straight half bottom 10124 polished_andesite_stairs facing south waterlogged false shape straight half bottom 10125 polished_andesite_stairs facing south waterlogged true shape inner_left half bottom 10126 polished_andesite_stairs facing south waterlogged false shape inner_left half bottom 10127 polished_andesite_stairs facing south waterlogged true shape inner_right half bottom 10128 polished_andesite_stairs facing south waterlogged false shape inner_right half bottom 10129 polished_andesite_stairs facing south waterlogged true shape outer_left half bottom 10130 polished_andesite_stairs facing south waterlogged false shape outer_left half bottom 10131 polished_andesite_stairs facing south waterlogged true shape outer_right half bottom 10132 polished_andesite_stairs facing south waterlogged false shape outer_right half bottom 10133 polished_andesite_stairs facing west waterlogged true shape straight half top 10134 polished_andesite_stairs facing west waterlogged false shape straight half top 10135 polished_andesite_stairs facing west waterlogged true shape inner_left half top 10136 polished_andesite_stairs facing west waterlogged false shape inner_left half top 10137 polished_andesite_stairs facing west waterlogged true shape inner_right half top 10138 polished_andesite_stairs facing west waterlogged false shape inner_right half top 10139 polished_andesite_stairs facing west waterlogged true shape outer_left half top 10140 polished_andesite_stairs facing west waterlogged false shape outer_left half top 10141 polished_andesite_stairs facing west waterlogged true shape outer_right half top 10142 polished_andesite_stairs facing west waterlogged false shape outer_right half top 10143 polished_andesite_stairs facing west waterlogged true shape straight half bottom 10144 polished_andesite_stairs facing west waterlogged false shape straight half bottom 10145 polished_andesite_stairs facing west waterlogged true shape inner_left half bottom 10146 polished_andesite_stairs facing west waterlogged false shape inner_left half bottom 10147 polished_andesite_stairs facing west waterlogged true shape inner_right half bottom 10148 polished_andesite_stairs facing west waterlogged false shape inner_right half bottom 10149 polished_andesite_stairs facing west waterlogged true shape outer_left half bottom 10150 polished_andesite_stairs facing west waterlogged false shape outer_left half bottom 10151 polished_andesite_stairs facing west waterlogged true shape outer_right half bottom 10152 polished_andesite_stairs facing west waterlogged false shape outer_right half bottom 10153 polished_andesite_stairs facing east waterlogged true shape straight half top 10154 polished_andesite_stairs facing east waterlogged false shape straight half top 10155 polished_andesite_stairs facing east waterlogged true shape inner_left half top 10156 polished_andesite_stairs facing east waterlogged false shape inner_left half top 10157 polished_andesite_stairs facing east waterlogged true shape inner_right half top 10158 polished_andesite_stairs facing east waterlogged false shape inner_right half top 10159 polished_andesite_stairs facing east waterlogged true shape outer_left half top 10160 polished_andesite_stairs facing east waterlogged false shape outer_left half top 10161 polished_andesite_stairs facing east waterlogged true shape outer_right half top 10162 polished_andesite_stairs facing east waterlogged false shape outer_right half top 10163 polished_andesite_stairs facing east waterlogged true shape straight half bottom 10164 polished_andesite_stairs facing east waterlogged false shape straight half bottom 10165 polished_andesite_stairs facing east waterlogged true shape inner_left half bottom 10166 polished_andesite_stairs facing east waterlogged false shape inner_left half bottom 10167 polished_andesite_stairs facing east waterlogged true shape inner_right half bottom 10168 polished_andesite_stairs facing east waterlogged false shape inner_right half bottom 10169 polished_andesite_stairs facing east waterlogged true shape outer_left half bottom 10170 polished_andesite_stairs facing east waterlogged false shape outer_left half bottom 10171 polished_andesite_stairs facing east waterlogged true shape outer_right half bottom 10172 polished_andesite_stairs facing east waterlogged false shape outer_right half bottom 10173 diorite_stairs facing north waterlogged true shape straight half top 10174 diorite_stairs facing north waterlogged false shape straight half top 10175 diorite_stairs facing north waterlogged true shape inner_left half top 10176 diorite_stairs facing north waterlogged false shape inner_left half top 10177 diorite_stairs facing north waterlogged true shape inner_right half top 10178 diorite_stairs facing north waterlogged false shape inner_right half top 10179 diorite_stairs facing north waterlogged true shape outer_left half top 10180 diorite_stairs facing north waterlogged false shape outer_left half top 10181 diorite_stairs facing north waterlogged true shape outer_right half top 10182 diorite_stairs facing north waterlogged false shape outer_right half top 10183 diorite_stairs facing north waterlogged true shape straight half bottom 10184 diorite_stairs facing north waterlogged false shape straight half bottom 10185 diorite_stairs facing north waterlogged true shape inner_left half bottom 10186 diorite_stairs facing north waterlogged false shape inner_left half bottom 10187 diorite_stairs facing north waterlogged true shape inner_right half bottom 10188 diorite_stairs facing north waterlogged false shape inner_right half bottom 10189 diorite_stairs facing north waterlogged true shape outer_left half bottom 10190 diorite_stairs facing north waterlogged false shape outer_left half bottom 10191 diorite_stairs facing north waterlogged true shape outer_right half bottom 10192 diorite_stairs facing north waterlogged false shape outer_right half bottom 10193 diorite_stairs facing south waterlogged true shape straight half top 10194 diorite_stairs facing south waterlogged false shape straight half top 10195 diorite_stairs facing south waterlogged true shape inner_left half top 10196 diorite_stairs facing south waterlogged false shape inner_left half top 10197 diorite_stairs facing south waterlogged true shape inner_right half top 10198 diorite_stairs facing south waterlogged false shape inner_right half top 10199 diorite_stairs facing south waterlogged true shape outer_left half top 10200 diorite_stairs facing south waterlogged false shape outer_left half top 10201 diorite_stairs facing south waterlogged true shape outer_right half top 10202 diorite_stairs facing south waterlogged false shape outer_right half top 10203 diorite_stairs facing south waterlogged true shape straight half bottom 10204 diorite_stairs facing south waterlogged false shape straight half bottom 10205 diorite_stairs facing south waterlogged true shape inner_left half bottom 10206 diorite_stairs facing south waterlogged false shape inner_left half bottom 10207 diorite_stairs facing south waterlogged true shape inner_right half bottom 10208 diorite_stairs facing south waterlogged false shape inner_right half bottom 10209 diorite_stairs facing south waterlogged true shape outer_left half bottom 10210 diorite_stairs facing south waterlogged false shape outer_left half bottom 10211 diorite_stairs facing south waterlogged true shape outer_right half bottom 10212 diorite_stairs facing south waterlogged false shape outer_right half bottom 10213 diorite_stairs facing west waterlogged true shape straight half top 10214 diorite_stairs facing west waterlogged false shape straight half top 10215 diorite_stairs facing west waterlogged true shape inner_left half top 10216 diorite_stairs facing west waterlogged false shape inner_left half top 10217 diorite_stairs facing west waterlogged true shape inner_right half top 10218 diorite_stairs facing west waterlogged false shape inner_right half top 10219 diorite_stairs facing west waterlogged true shape outer_left half top 10220 diorite_stairs facing west waterlogged false shape outer_left half top 10221 diorite_stairs facing west waterlogged true shape outer_right half top 10222 diorite_stairs facing west waterlogged false shape outer_right half top 10223 diorite_stairs facing west waterlogged true shape straight half bottom 10224 diorite_stairs facing west waterlogged false shape straight half bottom 10225 diorite_stairs facing west waterlogged true shape inner_left half bottom 10226 diorite_stairs facing west waterlogged false shape inner_left half bottom 10227 diorite_stairs facing west waterlogged true shape inner_right half bottom 10228 diorite_stairs facing west waterlogged false shape inner_right half bottom 10229 diorite_stairs facing west waterlogged true shape outer_left half bottom 10230 diorite_stairs facing west waterlogged false shape outer_left half bottom 10231 diorite_stairs facing west waterlogged true shape outer_right half bottom 10232 diorite_stairs facing west waterlogged false shape outer_right half bottom 10233 diorite_stairs facing east waterlogged true shape straight half top 10234 diorite_stairs facing east waterlogged false shape straight half top 10235 diorite_stairs facing east waterlogged true shape inner_left half top 10236 diorite_stairs facing east waterlogged false shape inner_left half top 10237 diorite_stairs facing east waterlogged true shape inner_right half top 10238 diorite_stairs facing east waterlogged false shape inner_right half top 10239 diorite_stairs facing east waterlogged true shape outer_left half top 10240 diorite_stairs facing east waterlogged false shape outer_left half top 10241 diorite_stairs facing east waterlogged true shape outer_right half top 10242 diorite_stairs facing east waterlogged false shape outer_right half top 10243 diorite_stairs facing east waterlogged true shape straight half bottom 10244 diorite_stairs facing east waterlogged false shape straight half bottom 10245 diorite_stairs facing east waterlogged true shape inner_left half bottom 10246 diorite_stairs facing east waterlogged false shape inner_left half bottom 10247 diorite_stairs facing east waterlogged true shape inner_right half bottom 10248 diorite_stairs facing east waterlogged false shape inner_right half bottom 10249 diorite_stairs facing east waterlogged true shape outer_left half bottom 10250 diorite_stairs facing east waterlogged false shape outer_left half bottom 10251 diorite_stairs facing east waterlogged true shape outer_right half bottom 10252 diorite_stairs facing east waterlogged false shape outer_right half bottom 10253 polished_granite_slab type top waterlogged true 10254 polished_granite_slab type top waterlogged false 10255 polished_granite_slab type bottom waterlogged true 10256 polished_granite_slab type bottom waterlogged false 10257 polished_granite_slab type double waterlogged true 10258 polished_granite_slab type double waterlogged false 10259 smooth_red_sandstone_slab type top waterlogged true 10260 smooth_red_sandstone_slab type top waterlogged false 10261 smooth_red_sandstone_slab type bottom waterlogged true 10262 smooth_red_sandstone_slab type bottom waterlogged false 10263 smooth_red_sandstone_slab type double waterlogged true 10264 smooth_red_sandstone_slab type double waterlogged false 10265 mossy_stone_brick_slab type top waterlogged true 10266 mossy_stone_brick_slab type top waterlogged false 10267 mossy_stone_brick_slab type bottom waterlogged true 10268 mossy_stone_brick_slab type bottom waterlogged false 10269 mossy_stone_brick_slab type double waterlogged true 10270 mossy_stone_brick_slab type double waterlogged false 10271 polished_diorite_slab type top waterlogged true 10272 polished_diorite_slab type top waterlogged false 10273 polished_diorite_slab type bottom waterlogged true 10274 polished_diorite_slab type bottom waterlogged false 10275 polished_diorite_slab type double waterlogged true 10276 polished_diorite_slab type double waterlogged false 10277 mossy_cobblestone_slab type top waterlogged true 10278 mossy_cobblestone_slab type top waterlogged false 10279 mossy_cobblestone_slab type bottom waterlogged true 10280 mossy_cobblestone_slab type bottom waterlogged false 10281 mossy_cobblestone_slab type double waterlogged true 10282 mossy_cobblestone_slab type double waterlogged false 10283 end_stone_brick_slab type top waterlogged true 10284 end_stone_brick_slab type top waterlogged false 10285 end_stone_brick_slab type bottom waterlogged true 10286 end_stone_brick_slab type bottom waterlogged false 10287 end_stone_brick_slab type double waterlogged true 10288 end_stone_brick_slab type double waterlogged false 10289 smooth_sandstone_slab type top waterlogged true 10290 smooth_sandstone_slab type top waterlogged false 10291 smooth_sandstone_slab type bottom waterlogged true 10292 smooth_sandstone_slab type bottom waterlogged false 10293 smooth_sandstone_slab type double waterlogged true 10294 smooth_sandstone_slab type double waterlogged false 10295 smooth_quartz_slab type top waterlogged true 10296 smooth_quartz_slab type top waterlogged false 10297 smooth_quartz_slab type bottom waterlogged true 10298 smooth_quartz_slab type bottom waterlogged false 10299 smooth_quartz_slab type double waterlogged true 10300 smooth_quartz_slab type double waterlogged false 10301 granite_slab type top waterlogged true 10302 granite_slab type top waterlogged false 10303 granite_slab type bottom waterlogged true 10304 granite_slab type bottom waterlogged false 10305 granite_slab type double waterlogged true 10306 granite_slab type double waterlogged false 10307 andesite_slab type top waterlogged true 10308 andesite_slab type top waterlogged false 10309 andesite_slab type bottom waterlogged true 10310 andesite_slab type bottom waterlogged false 10311 andesite_slab type double waterlogged true 10312 andesite_slab type double waterlogged false 10313 red_nether_brick_slab type top waterlogged true 10314 red_nether_brick_slab type top waterlogged false 10315 red_nether_brick_slab type bottom waterlogged true 10316 red_nether_brick_slab type bottom waterlogged false 10317 red_nether_brick_slab type double waterlogged true 10318 red_nether_brick_slab type double waterlogged false 10319 polished_andesite_slab type top waterlogged true 10320 polished_andesite_slab type top waterlogged false 10321 polished_andesite_slab type bottom waterlogged true 10322 polished_andesite_slab type bottom waterlogged false 10323 polished_andesite_slab type double waterlogged true 10324 polished_andesite_slab type double waterlogged false 10325 diorite_slab type top waterlogged true 10326 diorite_slab type top waterlogged false 10327 diorite_slab type bottom waterlogged true 10328 diorite_slab type bottom waterlogged false 10329 diorite_slab type double waterlogged true 10330 diorite_slab type double waterlogged false 10331 brick_wall waterlogged true south true east true north true up true west true 10332 brick_wall waterlogged true south true east true north true up true west false 10333 brick_wall waterlogged false south true east true north true up true west true 10334 brick_wall waterlogged false south true east true north true up true west false 10335 brick_wall waterlogged true south true east true north true up false west true 10336 brick_wall waterlogged true south true east true north true up false west false 10337 brick_wall waterlogged false south true east true north true up false west true 10338 brick_wall waterlogged false south true east true north true up false west false 10339 brick_wall waterlogged true south false east true north true up true west true 10340 brick_wall waterlogged true south false east true north true up true west false 10341 brick_wall waterlogged false south false east true north true up true west true 10342 brick_wall waterlogged false south false east true north true up true west false 10343 brick_wall waterlogged true south false east true north true up false west true 10344 brick_wall waterlogged true south false east true north true up false west false 10345 brick_wall waterlogged false south false east true north true up false west true 10346 brick_wall waterlogged false south false east true north true up false west false 10347 brick_wall waterlogged true south true east true north false up true west true 10348 brick_wall waterlogged true south true east true north false up true west false 10349 brick_wall waterlogged false south true east true north false up true west true 10350 brick_wall waterlogged false south true east true north false up true west false 10351 brick_wall waterlogged true south true east true north false up false west true 10352 brick_wall waterlogged true south true east true north false up false west false 10353 brick_wall waterlogged false south true east true north false up false west true 10354 brick_wall waterlogged false south true east true north false up false west false 10355 brick_wall waterlogged true south false east true north false up true west true 10356 brick_wall waterlogged true south false east true north false up true west false 10357 brick_wall waterlogged false south false east true north false up true west true 10358 brick_wall waterlogged false south false east true north false up true west false 10359 brick_wall waterlogged true south false east true north false up false west true 10360 brick_wall waterlogged true south false east true north false up false west false 10361 brick_wall waterlogged false south false east true north false up false west true 10362 brick_wall waterlogged false south false east true north false up false west false 10363 brick_wall waterlogged true south true east false north true up true west true 10364 brick_wall waterlogged true south true east false north true up true west false 10365 brick_wall waterlogged false south true east false north true up true west true 10366 brick_wall waterlogged false south true east false north true up true west false 10367 brick_wall waterlogged true south true east false north true up false west true 10368 brick_wall waterlogged true south true east false north true up false west false 10369 brick_wall waterlogged false south true east false north true up false west true 10370 brick_wall waterlogged false south true east false north true up false west false 10371 brick_wall waterlogged true south false east false north true up true west true 10372 brick_wall waterlogged true south false east false north true up true west false 10373 brick_wall waterlogged false south false east false north true up true west true 10374 brick_wall waterlogged false south false east false north true up true west false 10375 brick_wall waterlogged true south false east false north true up false west true 10376 brick_wall waterlogged true south false east false north true up false west false 10377 brick_wall waterlogged false south false east false north true up false west true 10378 brick_wall waterlogged false south false east false north true up false west false 10379 brick_wall waterlogged true south true east false north false up true west true 10380 brick_wall waterlogged true south true east false north false up true west false 10381 brick_wall waterlogged false south true east false north false up true west true 10382 brick_wall waterlogged false south true east false north false up true west false 10383 brick_wall waterlogged true south true east false north false up false west true 10384 brick_wall waterlogged true south true east false north false up false west false 10385 brick_wall waterlogged false south true east false north false up false west true 10386 brick_wall waterlogged false south true east false north false up false west false 10387 brick_wall waterlogged true south false east false north false up true west true 10388 brick_wall waterlogged true south false east false north false up true west false 10389 brick_wall waterlogged false south false east false north false up true west true 10390 brick_wall waterlogged false south false east false north false up true west false 10391 brick_wall waterlogged true south false east false north false up false west true 10392 brick_wall waterlogged true south false east false north false up false west false 10393 brick_wall waterlogged false south false east false north false up false west true 10394 brick_wall waterlogged false south false east false north false up false west false 10395 prismarine_wall waterlogged true south true east true north true up true west true 10396 prismarine_wall waterlogged true south true east true north true up true west false 10397 prismarine_wall waterlogged false south true east true north true up true west true 10398 prismarine_wall waterlogged false south true east true north true up true west false 10399 prismarine_wall waterlogged true south true east true north true up false west true 10400 prismarine_wall waterlogged true south true east true north true up false west false 10401 prismarine_wall waterlogged false south true east true north true up false west true 10402 prismarine_wall waterlogged false south true east true north true up false west false 10403 prismarine_wall waterlogged true south false east true north true up true west true 10404 prismarine_wall waterlogged true south false east true north true up true west false 10405 prismarine_wall waterlogged false south false east true north true up true west true 10406 prismarine_wall waterlogged false south false east true north true up true west false 10407 prismarine_wall waterlogged true south false east true north true up false west true 10408 prismarine_wall waterlogged true south false east true north true up false west false 10409 prismarine_wall waterlogged false south false east true north true up false west true 10410 prismarine_wall waterlogged false south false east true north true up false west false 10411 prismarine_wall waterlogged true south true east true north false up true west true 10412 prismarine_wall waterlogged true south true east true north false up true west false 10413 prismarine_wall waterlogged false south true east true north false up true west true 10414 prismarine_wall waterlogged false south true east true north false up true west false 10415 prismarine_wall waterlogged true south true east true north false up false west true 10416 prismarine_wall waterlogged true south true east true north false up false west false 10417 prismarine_wall waterlogged false south true east true north false up false west true 10418 prismarine_wall waterlogged false south true east true north false up false west false 10419 prismarine_wall waterlogged true south false east true north false up true west true 10420 prismarine_wall waterlogged true south false east true north false up true west false 10421 prismarine_wall waterlogged false south false east true north false up true west true 10422 prismarine_wall waterlogged false south false east true north false up true west false 10423 prismarine_wall waterlogged true south false east true north false up false west true 10424 prismarine_wall waterlogged true south false east true north false up false west false 10425 prismarine_wall waterlogged false south false east true north false up false west true 10426 prismarine_wall waterlogged false south false east true north false up false west false 10427 prismarine_wall waterlogged true south true east false north true up true west true 10428 prismarine_wall waterlogged true south true east false north true up true west false 10429 prismarine_wall waterlogged false south true east false north true up true west true 10430 prismarine_wall waterlogged false south true east false north true up true west false 10431 prismarine_wall waterlogged true south true east false north true up false west true 10432 prismarine_wall waterlogged true south true east false north true up false west false 10433 prismarine_wall waterlogged false south true east false north true up false west true 10434 prismarine_wall waterlogged false south true east false north true up false west false 10435 prismarine_wall waterlogged true south false east false north true up true west true 10436 prismarine_wall waterlogged true south false east false north true up true west false 10437 prismarine_wall waterlogged false south false east false north true up true west true 10438 prismarine_wall waterlogged false south false east false north true up true west false 10439 prismarine_wall waterlogged true south false east false north true up false west true 10440 prismarine_wall waterlogged true south false east false north true up false west false 10441 prismarine_wall waterlogged false south false east false north true up false west true 10442 prismarine_wall waterlogged false south false east false north true up false west false 10443 prismarine_wall waterlogged true south true east false north false up true west true 10444 prismarine_wall waterlogged true south true east false north false up true west false 10445 prismarine_wall waterlogged false south true east false north false up true west true 10446 prismarine_wall waterlogged false south true east false north false up true west false 10447 prismarine_wall waterlogged true south true east false north false up false west true 10448 prismarine_wall waterlogged true south true east false north false up false west false 10449 prismarine_wall waterlogged false south true east false north false up false west true 10450 prismarine_wall waterlogged false south true east false north false up false west false 10451 prismarine_wall waterlogged true south false east false north false up true west true 10452 prismarine_wall waterlogged true south false east false north false up true west false 10453 prismarine_wall waterlogged false south false east false north false up true west true 10454 prismarine_wall waterlogged false south false east false north false up true west false 10455 prismarine_wall waterlogged true south false east false north false up false west true 10456 prismarine_wall waterlogged true south false east false north false up false west false 10457 prismarine_wall waterlogged false south false east false north false up false west true 10458 prismarine_wall waterlogged false south false east false north false up false west false 10459 red_sandstone_wall waterlogged true south true east true north true up true west true 10460 red_sandstone_wall waterlogged true south true east true north true up true west false 10461 red_sandstone_wall waterlogged false south true east true north true up true west true 10462 red_sandstone_wall waterlogged false south true east true north true up true west false 10463 red_sandstone_wall waterlogged true south true east true north true up false west true 10464 red_sandstone_wall waterlogged true south true east true north true up false west false 10465 red_sandstone_wall waterlogged false south true east true north true up false west true 10466 red_sandstone_wall waterlogged false south true east true north true up false west false 10467 red_sandstone_wall waterlogged true south false east true north true up true west true 10468 red_sandstone_wall waterlogged true south false east true north true up true west false 10469 red_sandstone_wall waterlogged false south false east true north true up true west true 10470 red_sandstone_wall waterlogged false south false east true north true up true west false 10471 red_sandstone_wall waterlogged true south false east true north true up false west true 10472 red_sandstone_wall waterlogged true south false east true north true up false west false 10473 red_sandstone_wall waterlogged false south false east true north true up false west true 10474 red_sandstone_wall waterlogged false south false east true north true up false west false 10475 red_sandstone_wall waterlogged true south true east true north false up true west true 10476 red_sandstone_wall waterlogged true south true east true north false up true west false 10477 red_sandstone_wall waterlogged false south true east true north false up true west true 10478 red_sandstone_wall waterlogged false south true east true north false up true west false 10479 red_sandstone_wall waterlogged true south true east true north false up false west true 10480 red_sandstone_wall waterlogged true south true east true north false up false west false 10481 red_sandstone_wall waterlogged false south true east true north false up false west true 10482 red_sandstone_wall waterlogged false south true east true north false up false west false 10483 red_sandstone_wall waterlogged true south false east true north false up true west true 10484 red_sandstone_wall waterlogged true south false east true north false up true west false 10485 red_sandstone_wall waterlogged false south false east true north false up true west true 10486 red_sandstone_wall waterlogged false south false east true north false up true west false 10487 red_sandstone_wall waterlogged true south false east true north false up false west true 10488 red_sandstone_wall waterlogged true south false east true north false up false west false 10489 red_sandstone_wall waterlogged false south false east true north false up false west true 10490 red_sandstone_wall waterlogged false south false east true north false up false west false 10491 red_sandstone_wall waterlogged true south true east false north true up true west true 10492 red_sandstone_wall waterlogged true south true east false north true up true west false 10493 red_sandstone_wall waterlogged false south true east false north true up true west true 10494 red_sandstone_wall waterlogged false south true east false north true up true west false 10495 red_sandstone_wall waterlogged true south true east false north true up false west true 10496 red_sandstone_wall waterlogged true south true east false north true up false west false 10497 red_sandstone_wall waterlogged false south true east false north true up false west true 10498 red_sandstone_wall waterlogged false south true east false north true up false west false 10499 red_sandstone_wall waterlogged true south false east false north true up true west true 10500 red_sandstone_wall waterlogged true south false east false north true up true west false 10501 red_sandstone_wall waterlogged false south false east false north true up true west true 10502 red_sandstone_wall waterlogged false south false east false north true up true west false 10503 red_sandstone_wall waterlogged true south false east false north true up false west true 10504 red_sandstone_wall waterlogged true south false east false north true up false west false 10505 red_sandstone_wall waterlogged false south false east false north true up false west true 10506 red_sandstone_wall waterlogged false south false east false north true up false west false 10507 red_sandstone_wall waterlogged true south true east false north false up true west true 10508 red_sandstone_wall waterlogged true south true east false north false up true west false 10509 red_sandstone_wall waterlogged false south true east false north false up true west true 10510 red_sandstone_wall waterlogged false south true east false north false up true west false 10511 red_sandstone_wall waterlogged true south true east false north false up false west true 10512 red_sandstone_wall waterlogged true south true east false north false up false west false 10513 red_sandstone_wall waterlogged false south true east false north false up false west true 10514 red_sandstone_wall waterlogged false south true east false north false up false west false 10515 red_sandstone_wall waterlogged true south false east false north false up true west true 10516 red_sandstone_wall waterlogged true south false east false north false up true west false 10517 red_sandstone_wall waterlogged false south false east false north false up true west true 10518 red_sandstone_wall waterlogged false south false east false north false up true west false 10519 red_sandstone_wall waterlogged true south false east false north false up false west true 10520 red_sandstone_wall waterlogged true south false east false north false up false west false 10521 red_sandstone_wall waterlogged false south false east false north false up false west true 10522 red_sandstone_wall waterlogged false south false east false north false up false west false 10523 mossy_stone_brick_wall waterlogged true south true east true north true up true west true 10524 mossy_stone_brick_wall waterlogged true south true east true north true up true west false 10525 mossy_stone_brick_wall waterlogged false south true east true north true up true west true 10526 mossy_stone_brick_wall waterlogged false south true east true north true up true west false 10527 mossy_stone_brick_wall waterlogged true south true east true north true up false west true 10528 mossy_stone_brick_wall waterlogged true south true east true north true up false west false 10529 mossy_stone_brick_wall waterlogged false south true east true north true up false west true 10530 mossy_stone_brick_wall waterlogged false south true east true north true up false west false 10531 mossy_stone_brick_wall waterlogged true south false east true north true up true west true 10532 mossy_stone_brick_wall waterlogged true south false east true north true up true west false 10533 mossy_stone_brick_wall waterlogged false south false east true north true up true west true 10534 mossy_stone_brick_wall waterlogged false south false east true north true up true west false 10535 mossy_stone_brick_wall waterlogged true south false east true north true up false west true 10536 mossy_stone_brick_wall waterlogged true south false east true north true up false west false 10537 mossy_stone_brick_wall waterlogged false south false east true north true up false west true 10538 mossy_stone_brick_wall waterlogged false south false east true north true up false west false 10539 mossy_stone_brick_wall waterlogged true south true east true north false up true west true 10540 mossy_stone_brick_wall waterlogged true south true east true north false up true west false 10541 mossy_stone_brick_wall waterlogged false south true east true north false up true west true 10542 mossy_stone_brick_wall waterlogged false south true east true north false up true west false 10543 mossy_stone_brick_wall waterlogged true south true east true north false up false west true 10544 mossy_stone_brick_wall waterlogged true south true east true north false up false west false 10545 mossy_stone_brick_wall waterlogged false south true east true north false up false west true 10546 mossy_stone_brick_wall waterlogged false south true east true north false up false west false 10547 mossy_stone_brick_wall waterlogged true south false east true north false up true west true 10548 mossy_stone_brick_wall waterlogged true south false east true north false up true west false 10549 mossy_stone_brick_wall waterlogged false south false east true north false up true west true 10550 mossy_stone_brick_wall waterlogged false south false east true north false up true west false 10551 mossy_stone_brick_wall waterlogged true south false east true north false up false west true 10552 mossy_stone_brick_wall waterlogged true south false east true north false up false west false 10553 mossy_stone_brick_wall waterlogged false south false east true north false up false west true 10554 mossy_stone_brick_wall waterlogged false south false east true north false up false west false 10555 mossy_stone_brick_wall waterlogged true south true east false north true up true west true 10556 mossy_stone_brick_wall waterlogged true south true east false north true up true west false 10557 mossy_stone_brick_wall waterlogged false south true east false north true up true west true 10558 mossy_stone_brick_wall waterlogged false south true east false north true up true west false 10559 mossy_stone_brick_wall waterlogged true south true east false north true up false west true 10560 mossy_stone_brick_wall waterlogged true south true east false north true up false west false 10561 mossy_stone_brick_wall waterlogged false south true east false north true up false west true 10562 mossy_stone_brick_wall waterlogged false south true east false north true up false west false 10563 mossy_stone_brick_wall waterlogged true south false east false north true up true west true 10564 mossy_stone_brick_wall waterlogged true south false east false north true up true west false 10565 mossy_stone_brick_wall waterlogged false south false east false north true up true west true 10566 mossy_stone_brick_wall waterlogged false south false east false north true up true west false 10567 mossy_stone_brick_wall waterlogged true south false east false north true up false west true 10568 mossy_stone_brick_wall waterlogged true south false east false north true up false west false 10569 mossy_stone_brick_wall waterlogged false south false east false north true up false west true 10570 mossy_stone_brick_wall waterlogged false south false east false north true up false west false 10571 mossy_stone_brick_wall waterlogged true south true east false north false up true west true 10572 mossy_stone_brick_wall waterlogged true south true east false north false up true west false 10573 mossy_stone_brick_wall waterlogged false south true east false north false up true west true 10574 mossy_stone_brick_wall waterlogged false south true east false north false up true west false 10575 mossy_stone_brick_wall waterlogged true south true east false north false up false west true 10576 mossy_stone_brick_wall waterlogged true south true east false north false up false west false 10577 mossy_stone_brick_wall waterlogged false south true east false north false up false west true 10578 mossy_stone_brick_wall waterlogged false south true east false north false up false west false 10579 mossy_stone_brick_wall waterlogged true south false east false north false up true west true 10580 mossy_stone_brick_wall waterlogged true south false east false north false up true west false 10581 mossy_stone_brick_wall waterlogged false south false east false north false up true west true 10582 mossy_stone_brick_wall waterlogged false south false east false north false up true west false 10583 mossy_stone_brick_wall waterlogged true south false east false north false up false west true 10584 mossy_stone_brick_wall waterlogged true south false east false north false up false west false 10585 mossy_stone_brick_wall waterlogged false south false east false north false up false west true 10586 mossy_stone_brick_wall waterlogged false south false east false north false up false west false 10587 granite_wall waterlogged true south true east true north true up true west true 10588 granite_wall waterlogged true south true east true north true up true west false 10589 granite_wall waterlogged false south true east true north true up true west true 10590 granite_wall waterlogged false south true east true north true up true west false 10591 granite_wall waterlogged true south true east true north true up false west true 10592 granite_wall waterlogged true south true east true north true up false west false 10593 granite_wall waterlogged false south true east true north true up false west true 10594 granite_wall waterlogged false south true east true north true up false west false 10595 granite_wall waterlogged true south false east true north true up true west true 10596 granite_wall waterlogged true south false east true north true up true west false 10597 granite_wall waterlogged false south false east true north true up true west true 10598 granite_wall waterlogged false south false east true north true up true west false 10599 granite_wall waterlogged true south false east true north true up false west true 10600 granite_wall waterlogged true south false east true north true up false west false 10601 granite_wall waterlogged false south false east true north true up false west true 10602 granite_wall waterlogged false south false east true north true up false west false 10603 granite_wall waterlogged true south true east true north false up true west true 10604 granite_wall waterlogged true south true east true north false up true west false 10605 granite_wall waterlogged false south true east true north false up true west true 10606 granite_wall waterlogged false south true east true north false up true west false 10607 granite_wall waterlogged true south true east true north false up false west true 10608 granite_wall waterlogged true south true east true north false up false west false 10609 granite_wall waterlogged false south true east true north false up false west true 10610 granite_wall waterlogged false south true east true north false up false west false 10611 granite_wall waterlogged true south false east true north false up true west true 10612 granite_wall waterlogged true south false east true north false up true west false 10613 granite_wall waterlogged false south false east true north false up true west true 10614 granite_wall waterlogged false south false east true north false up true west false 10615 granite_wall waterlogged true south false east true north false up false west true 10616 granite_wall waterlogged true south false east true north false up false west false 10617 granite_wall waterlogged false south false east true north false up false west true 10618 granite_wall waterlogged false south false east true north false up false west false 10619 granite_wall waterlogged true south true east false north true up true west true 10620 granite_wall waterlogged true south true east false north true up true west false 10621 granite_wall waterlogged false south true east false north true up true west true 10622 granite_wall waterlogged false south true east false north true up true west false 10623 granite_wall waterlogged true south true east false north true up false west true 10624 granite_wall waterlogged true south true east false north true up false west false 10625 granite_wall waterlogged false south true east false north true up false west true 10626 granite_wall waterlogged false south true east false north true up false west false 10627 granite_wall waterlogged true south false east false north true up true west true 10628 granite_wall waterlogged true south false east false north true up true west false 10629 granite_wall waterlogged false south false east false north true up true west true 10630 granite_wall waterlogged false south false east false north true up true west false 10631 granite_wall waterlogged true south false east false north true up false west true 10632 granite_wall waterlogged true south false east false north true up false west false 10633 granite_wall waterlogged false south false east false north true up false west true 10634 granite_wall waterlogged false south false east false north true up false west false 10635 granite_wall waterlogged true south true east false north false up true west true 10636 granite_wall waterlogged true south true east false north false up true west false 10637 granite_wall waterlogged false south true east false north false up true west true 10638 granite_wall waterlogged false south true east false north false up true west false 10639 granite_wall waterlogged true south true east false north false up false west true 10640 granite_wall waterlogged true south true east false north false up false west false 10641 granite_wall waterlogged false south true east false north false up false west true 10642 granite_wall waterlogged false south true east false north false up false west false 10643 granite_wall waterlogged true south false east false north false up true west true 10644 granite_wall waterlogged true south false east false north false up true west false 10645 granite_wall waterlogged false south false east false north false up true west true 10646 granite_wall waterlogged false south false east false north false up true west false 10647 granite_wall waterlogged true south false east false north false up false west true 10648 granite_wall waterlogged true south false east false north false up false west false 10649 granite_wall waterlogged false south false east false north false up false west true 10650 granite_wall waterlogged false south false east false north false up false west false 10651 stone_brick_wall waterlogged true south true east true north true up true west true 10652 stone_brick_wall waterlogged true south true east true north true up true west false 10653 stone_brick_wall waterlogged false south true east true north true up true west true 10654 stone_brick_wall waterlogged false south true east true north true up true west false 10655 stone_brick_wall waterlogged true south true east true north true up false west true 10656 stone_brick_wall waterlogged true south true east true north true up false west false 10657 stone_brick_wall waterlogged false south true east true north true up false west true 10658 stone_brick_wall waterlogged false south true east true north true up false west false 10659 stone_brick_wall waterlogged true south false east true north true up true west true 10660 stone_brick_wall waterlogged true south false east true north true up true west false 10661 stone_brick_wall waterlogged false south false east true north true up true west true 10662 stone_brick_wall waterlogged false south false east true north true up true west false 10663 stone_brick_wall waterlogged true south false east true north true up false west true 10664 stone_brick_wall waterlogged true south false east true north true up false west false 10665 stone_brick_wall waterlogged false south false east true north true up false west true 10666 stone_brick_wall waterlogged false south false east true north true up false west false 10667 stone_brick_wall waterlogged true south true east true north false up true west true 10668 stone_brick_wall waterlogged true south true east true north false up true west false 10669 stone_brick_wall waterlogged false south true east true north false up true west true 10670 stone_brick_wall waterlogged false south true east true north false up true west false 10671 stone_brick_wall waterlogged true south true east true north false up false west true 10672 stone_brick_wall waterlogged true south true east true north false up false west false 10673 stone_brick_wall waterlogged false south true east true north false up false west true 10674 stone_brick_wall waterlogged false south true east true north false up false west false 10675 stone_brick_wall waterlogged true south false east true north false up true west true 10676 stone_brick_wall waterlogged true south false east true north false up true west false 10677 stone_brick_wall waterlogged false south false east true north false up true west true 10678 stone_brick_wall waterlogged false south false east true north false up true west false 10679 stone_brick_wall waterlogged true south false east true north false up false west true 10680 stone_brick_wall waterlogged true south false east true north false up false west false 10681 stone_brick_wall waterlogged false south false east true north false up false west true 10682 stone_brick_wall waterlogged false south false east true north false up false west false 10683 stone_brick_wall waterlogged true south true east false north true up true west true 10684 stone_brick_wall waterlogged true south true east false north true up true west false 10685 stone_brick_wall waterlogged false south true east false north true up true west true 10686 stone_brick_wall waterlogged false south true east false north true up true west false 10687 stone_brick_wall waterlogged true south true east false north true up false west true 10688 stone_brick_wall waterlogged true south true east false north true up false west false 10689 stone_brick_wall waterlogged false south true east false north true up false west true 10690 stone_brick_wall waterlogged false south true east false north true up false west false 10691 stone_brick_wall waterlogged true south false east false north true up true west true 10692 stone_brick_wall waterlogged true south false east false north true up true west false 10693 stone_brick_wall waterlogged false south false east false north true up true west true 10694 stone_brick_wall waterlogged false south false east false north true up true west false 10695 stone_brick_wall waterlogged true south false east false north true up false west true 10696 stone_brick_wall waterlogged true south false east false north true up false west false 10697 stone_brick_wall waterlogged false south false east false north true up false west true 10698 stone_brick_wall waterlogged false south false east false north true up false west false 10699 stone_brick_wall waterlogged true south true east false north false up true west true 10700 stone_brick_wall waterlogged true south true east false north false up true west false 10701 stone_brick_wall waterlogged false south true east false north false up true west true 10702 stone_brick_wall waterlogged false south true east false north false up true west false 10703 stone_brick_wall waterlogged true south true east false north false up false west true 10704 stone_brick_wall waterlogged true south true east false north false up false west false 10705 stone_brick_wall waterlogged false south true east false north false up false west true 10706 stone_brick_wall waterlogged false south true east false north false up false west false 10707 stone_brick_wall waterlogged true south false east false north false up true west true 10708 stone_brick_wall waterlogged true south false east false north false up true west false 10709 stone_brick_wall waterlogged false south false east false north false up true west true 10710 stone_brick_wall waterlogged false south false east false north false up true west false 10711 stone_brick_wall waterlogged true south false east false north false up false west true 10712 stone_brick_wall waterlogged true south false east false north false up false west false 10713 stone_brick_wall waterlogged false south false east false north false up false west true 10714 stone_brick_wall waterlogged false south false east false north false up false west false 10715 nether_brick_wall waterlogged true south true east true north true up true west true 10716 nether_brick_wall waterlogged true south true east true north true up true west false 10717 nether_brick_wall waterlogged false south true east true north true up true west true 10718 nether_brick_wall waterlogged false south true east true north true up true west false 10719 nether_brick_wall waterlogged true south true east true north true up false west true 10720 nether_brick_wall waterlogged true south true east true north true up false west false 10721 nether_brick_wall waterlogged false south true east true north true up false west true 10722 nether_brick_wall waterlogged false south true east true north true up false west false 10723 nether_brick_wall waterlogged true south false east true north true up true west true 10724 nether_brick_wall waterlogged true south false east true north true up true west false 10725 nether_brick_wall waterlogged false south false east true north true up true west true 10726 nether_brick_wall waterlogged false south false east true north true up true west false 10727 nether_brick_wall waterlogged true south false east true north true up false west true 10728 nether_brick_wall waterlogged true south false east true north true up false west false 10729 nether_brick_wall waterlogged false south false east true north true up false west true 10730 nether_brick_wall waterlogged false south false east true north true up false west false 10731 nether_brick_wall waterlogged true south true east true north false up true west true 10732 nether_brick_wall waterlogged true south true east true north false up true west false 10733 nether_brick_wall waterlogged false south true east true north false up true west true 10734 nether_brick_wall waterlogged false south true east true north false up true west false 10735 nether_brick_wall waterlogged true south true east true north false up false west true 10736 nether_brick_wall waterlogged true south true east true north false up false west false 10737 nether_brick_wall waterlogged false south true east true north false up false west true 10738 nether_brick_wall waterlogged false south true east true north false up false west false 10739 nether_brick_wall waterlogged true south false east true north false up true west true 10740 nether_brick_wall waterlogged true south false east true north false up true west false 10741 nether_brick_wall waterlogged false south false east true north false up true west true 10742 nether_brick_wall waterlogged false south false east true north false up true west false 10743 nether_brick_wall waterlogged true south false east true north false up false west true 10744 nether_brick_wall waterlogged true south false east true north false up false west false 10745 nether_brick_wall waterlogged false south false east true north false up false west true 10746 nether_brick_wall waterlogged false south false east true north false up false west false 10747 nether_brick_wall waterlogged true south true east false north true up true west true 10748 nether_brick_wall waterlogged true south true east false north true up true west false 10749 nether_brick_wall waterlogged false south true east false north true up true west true 10750 nether_brick_wall waterlogged false south true east false north true up true west false 10751 nether_brick_wall waterlogged true south true east false north true up false west true 10752 nether_brick_wall waterlogged true south true east false north true up false west false 10753 nether_brick_wall waterlogged false south true east false north true up false west true 10754 nether_brick_wall waterlogged false south true east false north true up false west false 10755 nether_brick_wall waterlogged true south false east false north true up true west true 10756 nether_brick_wall waterlogged true south false east false north true up true west false 10757 nether_brick_wall waterlogged false south false east false north true up true west true 10758 nether_brick_wall waterlogged false south false east false north true up true west false 10759 nether_brick_wall waterlogged true south false east false north true up false west true 10760 nether_brick_wall waterlogged true south false east false north true up false west false 10761 nether_brick_wall waterlogged false south false east false north true up false west true 10762 nether_brick_wall waterlogged false south false east false north true up false west false 10763 nether_brick_wall waterlogged true south true east false north false up true west true 10764 nether_brick_wall waterlogged true south true east false north false up true west false 10765 nether_brick_wall waterlogged false south true east false north false up true west true 10766 nether_brick_wall waterlogged false south true east false north false up true west false 10767 nether_brick_wall waterlogged true south true east false north false up false west true 10768 nether_brick_wall waterlogged true south true east false north false up false west false 10769 nether_brick_wall waterlogged false south true east false north false up false west true 10770 nether_brick_wall waterlogged false south true east false north false up false west false 10771 nether_brick_wall waterlogged true south false east false north false up true west true 10772 nether_brick_wall waterlogged true south false east false north false up true west false 10773 nether_brick_wall waterlogged false south false east false north false up true west true 10774 nether_brick_wall waterlogged false south false east false north false up true west false 10775 nether_brick_wall waterlogged true south false east false north false up false west true 10776 nether_brick_wall waterlogged true south false east false north false up false west false 10777 nether_brick_wall waterlogged false south false east false north false up false west true 10778 nether_brick_wall waterlogged false south false east false north false up false west false 10779 andesite_wall waterlogged true south true east true north true up true west true 10780 andesite_wall waterlogged true south true east true north true up true west false 10781 andesite_wall waterlogged false south true east true north true up true west true 10782 andesite_wall waterlogged false south true east true north true up true west false 10783 andesite_wall waterlogged true south true east true north true up false west true 10784 andesite_wall waterlogged true south true east true north true up false west false 10785 andesite_wall waterlogged false south true east true north true up false west true 10786 andesite_wall waterlogged false south true east true north true up false west false 10787 andesite_wall waterlogged true south false east true north true up true west true 10788 andesite_wall waterlogged true south false east true north true up true west false 10789 andesite_wall waterlogged false south false east true north true up true west true 10790 andesite_wall waterlogged false south false east true north true up true west false 10791 andesite_wall waterlogged true south false east true north true up false west true 10792 andesite_wall waterlogged true south false east true north true up false west false 10793 andesite_wall waterlogged false south false east true north true up false west true 10794 andesite_wall waterlogged false south false east true north true up false west false 10795 andesite_wall waterlogged true south true east true north false up true west true 10796 andesite_wall waterlogged true south true east true north false up true west false 10797 andesite_wall waterlogged false south true east true north false up true west true 10798 andesite_wall waterlogged false south true east true north false up true west false 10799 andesite_wall waterlogged true south true east true north false up false west true 10800 andesite_wall waterlogged true south true east true north false up false west false 10801 andesite_wall waterlogged false south true east true north false up false west true 10802 andesite_wall waterlogged false south true east true north false up false west false 10803 andesite_wall waterlogged true south false east true north false up true west true 10804 andesite_wall waterlogged true south false east true north false up true west false 10805 andesite_wall waterlogged false south false east true north false up true west true 10806 andesite_wall waterlogged false south false east true north false up true west false 10807 andesite_wall waterlogged true south false east true north false up false west true 10808 andesite_wall waterlogged true south false east true north false up false west false 10809 andesite_wall waterlogged false south false east true north false up false west true 10810 andesite_wall waterlogged false south false east true north false up false west false 10811 andesite_wall waterlogged true south true east false north true up true west true 10812 andesite_wall waterlogged true south true east false north true up true west false 10813 andesite_wall waterlogged false south true east false north true up true west true 10814 andesite_wall waterlogged false south true east false north true up true west false 10815 andesite_wall waterlogged true south true east false north true up false west true 10816 andesite_wall waterlogged true south true east false north true up false west false 10817 andesite_wall waterlogged false south true east false north true up false west true 10818 andesite_wall waterlogged false south true east false north true up false west false 10819 andesite_wall waterlogged true south false east false north true up true west true 10820 andesite_wall waterlogged true south false east false north true up true west false 10821 andesite_wall waterlogged false south false east false north true up true west true 10822 andesite_wall waterlogged false south false east false north true up true west false 10823 andesite_wall waterlogged true south false east false north true up false west true 10824 andesite_wall waterlogged true south false east false north true up false west false 10825 andesite_wall waterlogged false south false east false north true up false west true 10826 andesite_wall waterlogged false south false east false north true up false west false 10827 andesite_wall waterlogged true south true east false north false up true west true 10828 andesite_wall waterlogged true south true east false north false up true west false 10829 andesite_wall waterlogged false south true east false north false up true west true 10830 andesite_wall waterlogged false south true east false north false up true west false 10831 andesite_wall waterlogged true south true east false north false up false west true 10832 andesite_wall waterlogged true south true east false north false up false west false 10833 andesite_wall waterlogged false south true east false north false up false west true 10834 andesite_wall waterlogged false south true east false north false up false west false 10835 andesite_wall waterlogged true south false east false north false up true west true 10836 andesite_wall waterlogged true south false east false north false up true west false 10837 andesite_wall waterlogged false south false east false north false up true west true 10838 andesite_wall waterlogged false south false east false north false up true west false 10839 andesite_wall waterlogged true south false east false north false up false west true 10840 andesite_wall waterlogged true south false east false north false up false west false 10841 andesite_wall waterlogged false south false east false north false up false west true 10842 andesite_wall waterlogged false south false east false north false up false west false 10843 red_nether_brick_wall waterlogged true south true east true north true up true west true 10844 red_nether_brick_wall waterlogged true south true east true north true up true west false 10845 red_nether_brick_wall waterlogged false south true east true north true up true west true 10846 red_nether_brick_wall waterlogged false south true east true north true up true west false 10847 red_nether_brick_wall waterlogged true south true east true north true up false west true 10848 red_nether_brick_wall waterlogged true south true east true north true up false west false 10849 red_nether_brick_wall waterlogged false south true east true north true up false west true 10850 red_nether_brick_wall waterlogged false south true east true north true up false west false 10851 red_nether_brick_wall waterlogged true south false east true north true up true west true 10852 red_nether_brick_wall waterlogged true south false east true north true up true west false 10853 red_nether_brick_wall waterlogged false south false east true north true up true west true 10854 red_nether_brick_wall waterlogged false south false east true north true up true west false 10855 red_nether_brick_wall waterlogged true south false east true north true up false west true 10856 red_nether_brick_wall waterlogged true south false east true north true up false west false 10857 red_nether_brick_wall waterlogged false south false east true north true up false west true 10858 red_nether_brick_wall waterlogged false south false east true north true up false west false 10859 red_nether_brick_wall waterlogged true south true east true north false up true west true 10860 red_nether_brick_wall waterlogged true south true east true north false up true west false 10861 red_nether_brick_wall waterlogged false south true east true north false up true west true 10862 red_nether_brick_wall waterlogged false south true east true north false up true west false 10863 red_nether_brick_wall waterlogged true south true east true north false up false west true 10864 red_nether_brick_wall waterlogged true south true east true north false up false west false 10865 red_nether_brick_wall waterlogged false south true east true north false up false west true 10866 red_nether_brick_wall waterlogged false south true east true north false up false west false 10867 red_nether_brick_wall waterlogged true south false east true north false up true west true 10868 red_nether_brick_wall waterlogged true south false east true north false up true west false 10869 red_nether_brick_wall waterlogged false south false east true north false up true west true 10870 red_nether_brick_wall waterlogged false south false east true north false up true west false 10871 red_nether_brick_wall waterlogged true south false east true north false up false west true 10872 red_nether_brick_wall waterlogged true south false east true north false up false west false 10873 red_nether_brick_wall waterlogged false south false east true north false up false west true 10874 red_nether_brick_wall waterlogged false south false east true north false up false west false 10875 red_nether_brick_wall waterlogged true south true east false north true up true west true 10876 red_nether_brick_wall waterlogged true south true east false north true up true west false 10877 red_nether_brick_wall waterlogged false south true east false north true up true west true 10878 red_nether_brick_wall waterlogged false south true east false north true up true west false 10879 red_nether_brick_wall waterlogged true south true east false north true up false west true 10880 red_nether_brick_wall waterlogged true south true east false north true up false west false 10881 red_nether_brick_wall waterlogged false south true east false north true up false west true 10882 red_nether_brick_wall waterlogged false south true east false north true up false west false 10883 red_nether_brick_wall waterlogged true south false east false north true up true west true 10884 red_nether_brick_wall waterlogged true south false east false north true up true west false 10885 red_nether_brick_wall waterlogged false south false east false north true up true west true 10886 red_nether_brick_wall waterlogged false south false east false north true up true west false 10887 red_nether_brick_wall waterlogged true south false east false north true up false west true 10888 red_nether_brick_wall waterlogged true south false east false north true up false west false 10889 red_nether_brick_wall waterlogged false south false east false north true up false west true 10890 red_nether_brick_wall waterlogged false south false east false north true up false west false 10891 red_nether_brick_wall waterlogged true south true east false north false up true west true 10892 red_nether_brick_wall waterlogged true south true east false north false up true west false 10893 red_nether_brick_wall waterlogged false south true east false north false up true west true 10894 red_nether_brick_wall waterlogged false south true east false north false up true west false 10895 red_nether_brick_wall waterlogged true south true east false north false up false west true 10896 red_nether_brick_wall waterlogged true south true east false north false up false west false 10897 red_nether_brick_wall waterlogged false south true east false north false up false west true 10898 red_nether_brick_wall waterlogged false south true east false north false up false west false 10899 red_nether_brick_wall waterlogged true south false east false north false up true west true 10900 red_nether_brick_wall waterlogged true south false east false north false up true west false 10901 red_nether_brick_wall waterlogged false south false east false north false up true west true 10902 red_nether_brick_wall waterlogged false south false east false north false up true west false 10903 red_nether_brick_wall waterlogged true south false east false north false up false west true 10904 red_nether_brick_wall waterlogged true south false east false north false up false west false 10905 red_nether_brick_wall waterlogged false south false east false north false up false west true 10906 red_nether_brick_wall waterlogged false south false east false north false up false west false 10907 sandstone_wall waterlogged true south true east true north true up true west true 10908 sandstone_wall waterlogged true south true east true north true up true west false 10909 sandstone_wall waterlogged false south true east true north true up true west true 10910 sandstone_wall waterlogged false south true east true north true up true west false 10911 sandstone_wall waterlogged true south true east true north true up false west true 10912 sandstone_wall waterlogged true south true east true north true up false west false 10913 sandstone_wall waterlogged false south true east true north true up false west true 10914 sandstone_wall waterlogged false south true east true north true up false west false 10915 sandstone_wall waterlogged true south false east true north true up true west true 10916 sandstone_wall waterlogged true south false east true north true up true west false 10917 sandstone_wall waterlogged false south false east true north true up true west true 10918 sandstone_wall waterlogged false south false east true north true up true west false 10919 sandstone_wall waterlogged true south false east true north true up false west true 10920 sandstone_wall waterlogged true south false east true north true up false west false 10921 sandstone_wall waterlogged false south false east true north true up false west true 10922 sandstone_wall waterlogged false south false east true north true up false west false 10923 sandstone_wall waterlogged true south true east true north false up true west true 10924 sandstone_wall waterlogged true south true east true north false up true west false 10925 sandstone_wall waterlogged false south true east true north false up true west true 10926 sandstone_wall waterlogged false south true east true north false up true west false 10927 sandstone_wall waterlogged true south true east true north false up false west true 10928 sandstone_wall waterlogged true south true east true north false up false west false 10929 sandstone_wall waterlogged false south true east true north false up false west true 10930 sandstone_wall waterlogged false south true east true north false up false west false 10931 sandstone_wall waterlogged true south false east true north false up true west true 10932 sandstone_wall waterlogged true south false east true north false up true west false 10933 sandstone_wall waterlogged false south false east true north false up true west true 10934 sandstone_wall waterlogged false south false east true north false up true west false 10935 sandstone_wall waterlogged true south false east true north false up false west true 10936 sandstone_wall waterlogged true south false east true north false up false west false 10937 sandstone_wall waterlogged false south false east true north false up false west true 10938 sandstone_wall waterlogged false south false east true north false up false west false 10939 sandstone_wall waterlogged true south true east false north true up true west true 10940 sandstone_wall waterlogged true south true east false north true up true west false 10941 sandstone_wall waterlogged false south true east false north true up true west true 10942 sandstone_wall waterlogged false south true east false north true up true west false 10943 sandstone_wall waterlogged true south true east false north true up false west true 10944 sandstone_wall waterlogged true south true east false north true up false west false 10945 sandstone_wall waterlogged false south true east false north true up false west true 10946 sandstone_wall waterlogged false south true east false north true up false west false 10947 sandstone_wall waterlogged true south false east false north true up true west true 10948 sandstone_wall waterlogged true south false east false north true up true west false 10949 sandstone_wall waterlogged false south false east false north true up true west true 10950 sandstone_wall waterlogged false south false east false north true up true west false 10951 sandstone_wall waterlogged true south false east false north true up false west true 10952 sandstone_wall waterlogged true south false east false north true up false west false 10953 sandstone_wall waterlogged false south false east false north true up false west true 10954 sandstone_wall waterlogged false south false east false north true up false west false 10955 sandstone_wall waterlogged true south true east false north false up true west true 10956 sandstone_wall waterlogged true south true east false north false up true west false 10957 sandstone_wall waterlogged false south true east false north false up true west true 10958 sandstone_wall waterlogged false south true east false north false up true west false 10959 sandstone_wall waterlogged true south true east false north false up false west true 10960 sandstone_wall waterlogged true south true east false north false up false west false 10961 sandstone_wall waterlogged false south true east false north false up false west true 10962 sandstone_wall waterlogged false south true east false north false up false west false 10963 sandstone_wall waterlogged true south false east false north false up true west true 10964 sandstone_wall waterlogged true south false east false north false up true west false 10965 sandstone_wall waterlogged false south false east false north false up true west true 10966 sandstone_wall waterlogged false south false east false north false up true west false 10967 sandstone_wall waterlogged true south false east false north false up false west true 10968 sandstone_wall waterlogged true south false east false north false up false west false 10969 sandstone_wall waterlogged false south false east false north false up false west true 10970 sandstone_wall waterlogged false south false east false north false up false west false 10971 end_stone_brick_wall waterlogged true south true east true north true up true west true 10972 end_stone_brick_wall waterlogged true south true east true north true up true west false 10973 end_stone_brick_wall waterlogged false south true east true north true up true west true 10974 end_stone_brick_wall waterlogged false south true east true north true up true west false 10975 end_stone_brick_wall waterlogged true south true east true north true up false west true 10976 end_stone_brick_wall waterlogged true south true east true north true up false west false 10977 end_stone_brick_wall waterlogged false south true east true north true up false west true 10978 end_stone_brick_wall waterlogged false south true east true north true up false west false 10979 end_stone_brick_wall waterlogged true south false east true north true up true west true 10980 end_stone_brick_wall waterlogged true south false east true north true up true west false 10981 end_stone_brick_wall waterlogged false south false east true north true up true west true 10982 end_stone_brick_wall waterlogged false south false east true north true up true west false 10983 end_stone_brick_wall waterlogged true south false east true north true up false west true 10984 end_stone_brick_wall waterlogged true south false east true north true up false west false 10985 end_stone_brick_wall waterlogged false south false east true north true up false west true 10986 end_stone_brick_wall waterlogged false south false east true north true up false west false 10987 end_stone_brick_wall waterlogged true south true east true north false up true west true 10988 end_stone_brick_wall waterlogged true south true east true north false up true west false 10989 end_stone_brick_wall waterlogged false south true east true north false up true west true 10990 end_stone_brick_wall waterlogged false south true east true north false up true west false 10991 end_stone_brick_wall waterlogged true south true east true north false up false west true 10992 end_stone_brick_wall waterlogged true south true east true north false up false west false 10993 end_stone_brick_wall waterlogged false south true east true north false up false west true 10994 end_stone_brick_wall waterlogged false south true east true north false up false west false 10995 end_stone_brick_wall waterlogged true south false east true north false up true west true 10996 end_stone_brick_wall waterlogged true south false east true north false up true west false 10997 end_stone_brick_wall waterlogged false south false east true north false up true west true 10998 end_stone_brick_wall waterlogged false south false east true north false up true west false 10999 end_stone_brick_wall waterlogged true south false east true north false up false west true 11000 end_stone_brick_wall waterlogged true south false east true north false up false west false 11001 end_stone_brick_wall waterlogged false south false east true north false up false west true 11002 end_stone_brick_wall waterlogged false south false east true north false up false west false 11003 end_stone_brick_wall waterlogged true south true east false north true up true west true 11004 end_stone_brick_wall waterlogged true south true east false north true up true west false 11005 end_stone_brick_wall waterlogged false south true east false north true up true west true 11006 end_stone_brick_wall waterlogged false south true east false north true up true west false 11007 end_stone_brick_wall waterlogged true south true east false north true up false west true 11008 end_stone_brick_wall waterlogged true south true east false north true up false west false 11009 end_stone_brick_wall waterlogged false south true east false north true up false west true 11010 end_stone_brick_wall waterlogged false south true east false north true up false west false 11011 end_stone_brick_wall waterlogged true south false east false north true up true west true 11012 end_stone_brick_wall waterlogged true south false east false north true up true west false 11013 end_stone_brick_wall waterlogged false south false east false north true up true west true 11014 end_stone_brick_wall waterlogged false south false east false north true up true west false 11015 end_stone_brick_wall waterlogged true south false east false north true up false west true 11016 end_stone_brick_wall waterlogged true south false east false north true up false west false 11017 end_stone_brick_wall waterlogged false south false east false north true up false west true 11018 end_stone_brick_wall waterlogged false south false east false north true up false west false 11019 end_stone_brick_wall waterlogged true south true east false north false up true west true 11020 end_stone_brick_wall waterlogged true south true east false north false up true west false 11021 end_stone_brick_wall waterlogged false south true east false north false up true west true 11022 end_stone_brick_wall waterlogged false south true east false north false up true west false 11023 end_stone_brick_wall waterlogged true south true east false north false up false west true 11024 end_stone_brick_wall waterlogged true south true east false north false up false west false 11025 end_stone_brick_wall waterlogged false south true east false north false up false west true 11026 end_stone_brick_wall waterlogged false south true east false north false up false west false 11027 end_stone_brick_wall waterlogged true south false east false north false up true west true 11028 end_stone_brick_wall waterlogged true south false east false north false up true west false 11029 end_stone_brick_wall waterlogged false south false east false north false up true west true 11030 end_stone_brick_wall waterlogged false south false east false north false up true west false 11031 end_stone_brick_wall waterlogged true south false east false north false up false west true 11032 end_stone_brick_wall waterlogged true south false east false north false up false west false 11033 end_stone_brick_wall waterlogged false south false east false north false up false west true 11034 end_stone_brick_wall waterlogged false south false east false north false up false west false 11035 diorite_wall waterlogged true south true east true north true up true west true 11036 diorite_wall waterlogged true south true east true north true up true west false 11037 diorite_wall waterlogged false south true east true north true up true west true 11038 diorite_wall waterlogged false south true east true north true up true west false 11039 diorite_wall waterlogged true south true east true north true up false west true 11040 diorite_wall waterlogged true south true east true north true up false west false 11041 diorite_wall waterlogged false south true east true north true up false west true 11042 diorite_wall waterlogged false south true east true north true up false west false 11043 diorite_wall waterlogged true south false east true north true up true west true 11044 diorite_wall waterlogged true south false east true north true up true west false 11045 diorite_wall waterlogged false south false east true north true up true west true 11046 diorite_wall waterlogged false south false east true north true up true west false 11047 diorite_wall waterlogged true south false east true north true up false west true 11048 diorite_wall waterlogged true south false east true north true up false west false 11049 diorite_wall waterlogged false south false east true north true up false west true 11050 diorite_wall waterlogged false south false east true north true up false west false 11051 diorite_wall waterlogged true south true east true north false up true west true 11052 diorite_wall waterlogged true south true east true north false up true west false 11053 diorite_wall waterlogged false south true east true north false up true west true 11054 diorite_wall waterlogged false south true east true north false up true west false 11055 diorite_wall waterlogged true south true east true north false up false west true 11056 diorite_wall waterlogged true south true east true north false up false west false 11057 diorite_wall waterlogged false south true east true north false up false west true 11058 diorite_wall waterlogged false south true east true north false up false west false 11059 diorite_wall waterlogged true south false east true north false up true west true 11060 diorite_wall waterlogged true south false east true north false up true west false 11061 diorite_wall waterlogged false south false east true north false up true west true 11062 diorite_wall waterlogged false south false east true north false up true west false 11063 diorite_wall waterlogged true south false east true north false up false west true 11064 diorite_wall waterlogged true south false east true north false up false west false 11065 diorite_wall waterlogged false south false east true north false up false west true 11066 diorite_wall waterlogged false south false east true north false up false west false 11067 diorite_wall waterlogged true south true east false north true up true west true 11068 diorite_wall waterlogged true south true east false north true up true west false 11069 diorite_wall waterlogged false south true east false north true up true west true 11070 diorite_wall waterlogged false south true east false north true up true west false 11071 diorite_wall waterlogged true south true east false north true up false west true 11072 diorite_wall waterlogged true south true east false north true up false west false 11073 diorite_wall waterlogged false south true east false north true up false west true 11074 diorite_wall waterlogged false south true east false north true up false west false 11075 diorite_wall waterlogged true south false east false north true up true west true 11076 diorite_wall waterlogged true south false east false north true up true west false 11077 diorite_wall waterlogged false south false east false north true up true west true 11078 diorite_wall waterlogged false south false east false north true up true west false 11079 diorite_wall waterlogged true south false east false north true up false west true 11080 diorite_wall waterlogged true south false east false north true up false west false 11081 diorite_wall waterlogged false south false east false north true up false west true 11082 diorite_wall waterlogged false south false east false north true up false west false 11083 diorite_wall waterlogged true south true east false north false up true west true 11084 diorite_wall waterlogged true south true east false north false up true west false 11085 diorite_wall waterlogged false south true east false north false up true west true 11086 diorite_wall waterlogged false south true east false north false up true west false 11087 diorite_wall waterlogged true south true east false north false up false west true 11088 diorite_wall waterlogged true south true east false north false up false west false 11089 diorite_wall waterlogged false south true east false north false up false west true 11090 diorite_wall waterlogged false south true east false north false up false west false 11091 diorite_wall waterlogged true south false east false north false up true west true 11092 diorite_wall waterlogged true south false east false north false up true west false 11093 diorite_wall waterlogged false south false east false north false up true west true 11094 diorite_wall waterlogged false south false east false north false up true west false 11095 diorite_wall waterlogged true south false east false north false up false west true 11096 diorite_wall waterlogged true south false east false north false up false west false 11097 diorite_wall waterlogged false south false east false north false up false west true 11098 diorite_wall waterlogged false south false east false north false up false west false 11099 scaffolding distance 0 waterlogged true bottom true 11100 scaffolding distance 0 waterlogged false bottom true 11101 scaffolding distance 1 waterlogged true bottom true 11102 scaffolding distance 1 waterlogged false bottom true 11103 scaffolding distance 2 waterlogged true bottom true 11104 scaffolding distance 2 waterlogged false bottom true 11105 scaffolding distance 3 waterlogged true bottom true 11106 scaffolding distance 3 waterlogged false bottom true 11107 scaffolding distance 4 waterlogged true bottom true 11108 scaffolding distance 4 waterlogged false bottom true 11109 scaffolding distance 5 waterlogged true bottom true 11110 scaffolding distance 5 waterlogged false bottom true 11111 scaffolding distance 6 waterlogged true bottom true 11112 scaffolding distance 6 waterlogged false bottom true 11113 scaffolding distance 7 waterlogged true bottom true 11114 scaffolding distance 7 waterlogged false bottom true 11115 scaffolding distance 0 waterlogged true bottom false 11116 scaffolding distance 0 waterlogged false bottom false 11117 scaffolding distance 1 waterlogged true bottom false 11118 scaffolding distance 1 waterlogged false bottom false 11119 scaffolding distance 2 waterlogged true bottom false 11120 scaffolding distance 2 waterlogged false bottom false 11121 scaffolding distance 3 waterlogged true bottom false 11122 scaffolding distance 3 waterlogged false bottom false 11123 scaffolding distance 4 waterlogged true bottom false 11124 scaffolding distance 4 waterlogged false bottom false 11125 scaffolding distance 5 waterlogged true bottom false 11126 scaffolding distance 5 waterlogged false bottom false 11127 scaffolding distance 6 waterlogged true bottom false 11128 scaffolding distance 6 waterlogged false bottom false 11129 scaffolding distance 7 waterlogged true bottom false 11130 scaffolding distance 7 waterlogged false bottom false 11131 loom facing north 11132 loom facing south 11133 loom facing west 11134 loom facing east 11135 barrel facing north open true 11136 barrel facing north open false 11137 barrel facing east open true 11138 barrel facing east open false 11139 barrel facing south open true 11140 barrel facing south open false 11141 barrel facing west open true 11142 barrel facing west open false 11143 barrel facing up open true 11144 barrel facing up open false 11145 barrel facing down open true 11146 barrel facing down open false 11147 smoker facing north lit true 11148 smoker facing north lit false 11149 smoker facing south lit true 11150 smoker facing south lit false 11151 smoker facing west lit true 11152 smoker facing west lit false 11153 smoker facing east lit true 11154 smoker facing east lit false 11155 blast_furnace facing north lit true 11156 blast_furnace facing north lit false 11157 blast_furnace facing south lit true 11158 blast_furnace facing south lit false 11159 blast_furnace facing west lit true 11160 blast_furnace facing west lit false 11161 blast_furnace facing east lit true 11162 blast_furnace facing east lit false 11163 cartography_table 11164 fletching_table 11165 grindstone face floor facing north 11166 grindstone face floor facing south 11167 grindstone face floor facing west 11168 grindstone face floor facing east 11169 grindstone face wall facing north 11170 grindstone face wall facing south 11171 grindstone face wall facing west 11172 grindstone face wall facing east 11173 grindstone face ceiling facing north 11174 grindstone face ceiling facing south 11175 grindstone face ceiling facing west 11176 grindstone face ceiling facing east 11177 lectern facing north has_book true powered true 11178 lectern facing north has_book true powered false 11179 lectern facing north has_book false powered true 11180 lectern facing north has_book false powered false 11181 lectern facing south has_book true powered true 11182 lectern facing south has_book true powered false 11183 lectern facing south has_book false powered true 11184 lectern facing south has_book false powered false 11185 lectern facing west has_book true powered true 11186 lectern facing west has_book true powered false 11187 lectern facing west has_book false powered true 11188 lectern facing west has_book false powered false 11189 lectern facing east has_book true powered true 11190 lectern facing east has_book true powered false 11191 lectern facing east has_book false powered true 11192 lectern facing east has_book false powered false 11193 smithing_table 11194 stonecutter facing north 11195 stonecutter facing south 11196 stonecutter facing west 11197 stonecutter facing east 11198 bell facing north attachment floor 11199 bell facing south attachment floor 11200 bell facing west attachment floor 11201 bell facing east attachment floor 11202 bell facing north attachment ceiling 11203 bell facing south attachment ceiling 11204 bell facing west attachment ceiling 11205 bell facing east attachment ceiling 11206 bell facing north attachment single_wall 11207 bell facing south attachment single_wall 11208 bell facing west attachment single_wall 11209 bell facing east attachment single_wall 11210 bell facing north attachment double_wall 11211 bell facing south attachment double_wall 11212 bell facing west attachment double_wall 11213 bell facing east attachment double_wall 11214 lantern hanging true 11215 lantern hanging false 11216 campfire facing north waterlogged true signal_fire true lit true 11217 campfire facing north waterlogged false signal_fire true lit true 11218 campfire facing north waterlogged true signal_fire false lit true 11219 campfire facing north waterlogged false signal_fire false lit true 11220 campfire facing north waterlogged true signal_fire true lit false 11221 campfire facing north waterlogged false signal_fire true lit false 11222 campfire facing north waterlogged true signal_fire false lit false 11223 campfire facing north waterlogged false signal_fire false lit false 11224 campfire facing south waterlogged true signal_fire true lit true 11225 campfire facing south waterlogged false signal_fire true lit true 11226 campfire facing south waterlogged true signal_fire false lit true 11227 campfire facing south waterlogged false signal_fire false lit true 11228 campfire facing south waterlogged true signal_fire true lit false 11229 campfire facing south waterlogged false signal_fire true lit false 11230 campfire facing south waterlogged true signal_fire false lit false 11231 campfire facing south waterlogged false signal_fire false lit false 11232 campfire facing west waterlogged true signal_fire true lit true 11233 campfire facing west waterlogged false signal_fire true lit true 11234 campfire facing west waterlogged true signal_fire false lit true 11235 campfire facing west waterlogged false signal_fire false lit true 11236 campfire facing west waterlogged true signal_fire true lit false 11237 campfire facing west waterlogged false signal_fire true lit false 11238 campfire facing west waterlogged true signal_fire false lit false 11239 campfire facing west waterlogged false signal_fire false lit false 11240 campfire facing east waterlogged true signal_fire true lit true 11241 campfire facing east waterlogged false signal_fire true lit true 11242 campfire facing east waterlogged true signal_fire false lit true 11243 campfire facing east waterlogged false signal_fire false lit true 11244 campfire facing east waterlogged true signal_fire true lit false 11245 campfire facing east waterlogged false signal_fire true lit false 11246 campfire facing east waterlogged true signal_fire false lit false 11247 campfire facing east waterlogged false signal_fire false lit false 11248 sweet_berry_bush age 0 11249 sweet_berry_bush age 1 11250 sweet_berry_bush age 2 11251 sweet_berry_bush age 3 11252 structure_block mode save 11253 structure_block mode load 11254 structure_block mode corner 11255 structure_block mode data 11256 jigsaw facing north 11257 jigsaw facing east 11258 jigsaw facing south 11259 jigsaw facing west 11260 jigsaw facing up 11261 jigsaw facing down 11262 composter level 0 11263 composter level 1 11264 composter level 2 11265 composter level 3 11266 composter level 4 11267 composter level 5 11268 composter level 6 11269 composter level 7 11270 composter level 8 ================================================ FILE: Server/Protocol/UpgradeBlockTypePalette.txt ================================================ UpgradeBlockTypePalette FileVersion 1 CommonPrefix minecraft: 0 0 air 1 0 stone 1 1 granite 1 2 polished_granite 1 3 diorite 1 4 polished_diorite 1 5 andesite 1 6 polished_andesite 2 0 grass_block snowy false 3 0 dirt 3 1 coarse_dirt 3 2 podzol snowy false 4 0 cobblestone 5 0 oak_planks 5 1 spruce_planks 5 2 birch_planks 5 3 jungle_planks 5 4 acacia_planks 5 5 dark_oak_planks 6 0 oak_sapling stage 0 6 1 spruce_sapling stage 0 6 2 birch_sapling stage 0 6 3 jungle_sapling stage 0 6 4 acacia_sapling stage 0 6 5 dark_oak_sapling stage 0 6 8 oak_sapling stage 1 6 9 spruce_sapling stage 1 6 10 birch_sapling stage 1 6 11 jungle_sapling stage 1 6 12 acacia_sapling stage 1 6 13 dark_oak_sapling stage 1 7 0 bedrock 8 0 water level 0 8 1 water level 1 8 2 water level 2 8 3 water level 3 8 4 water level 4 8 5 water level 5 8 6 water level 6 8 7 water level 7 8 8 water level 8 8 9 water level 9 8 10 water level 10 8 11 water level 11 8 12 water level 12 8 13 water level 13 8 14 water level 14 8 15 water level 15 9 0 water level 0 9 1 water level 1 9 2 water level 2 9 3 water level 3 9 4 water level 4 9 5 water level 5 9 6 water level 6 9 7 water level 7 9 8 water level 8 9 9 water level 9 9 10 water level 10 9 11 water level 11 9 12 water level 12 9 13 water level 13 9 14 water level 14 9 15 water level 15 10 0 lava level 0 10 1 lava level 1 10 2 lava level 2 10 3 lava level 3 10 4 lava level 4 10 5 lava level 5 10 6 lava level 6 10 7 lava level 7 10 8 lava level 8 10 9 lava level 9 10 10 lava level 10 10 11 lava level 11 10 12 lava level 12 10 13 lava level 13 10 14 lava level 14 10 15 lava level 15 11 0 lava level 0 11 1 lava level 1 11 2 lava level 2 11 3 lava level 3 11 4 lava level 4 11 5 lava level 5 11 6 lava level 6 11 7 lava level 7 11 8 lava level 8 11 9 lava level 9 11 10 lava level 10 11 11 lava level 11 11 12 lava level 12 11 13 lava level 13 11 14 lava level 14 11 15 lava level 15 12 0 sand 12 1 red_sand 13 0 gravel 14 0 gold_ore 15 0 iron_ore 16 0 coal_ore 17 0 oak_log axis y 17 1 spruce_log axis y 17 2 birch_log axis y 17 3 jungle_log axis y 17 4 oak_log axis x 17 5 spruce_log axis x 17 6 birch_log axis x 17 7 jungle_log axis x 17 8 oak_log axis z 17 9 spruce_log axis z 17 10 birch_log axis z 17 11 jungle_log axis z 17 12 oak_bark 17 13 spruce_bark 17 14 birch_bark 17 15 jungle_bark 18 0 oak_leaves decayable true check_decay false 18 1 spruce_leaves decayable true check_decay false 18 2 birch_leaves decayable true check_decay false 18 3 jungle_leaves decayable true check_decay false 18 4 oak_leaves decayable false check_decay false 18 5 spruce_leaves decayable false check_decay false 18 6 birch_leaves decayable false check_decay false 18 7 jungle_leaves decayable false check_decay false 18 8 oak_leaves decayable true check_decay true 18 9 spruce_leaves decayable true check_decay true 18 10 birch_leaves decayable true check_decay true 18 11 jungle_leaves decayable true check_decay true 18 12 oak_leaves decayable false check_decay true 18 13 spruce_leaves decayable false check_decay true 18 14 birch_leaves decayable false check_decay true 18 15 jungle_leaves decayable false check_decay true 19 0 sponge 19 1 wet_sponge 20 0 glass 21 0 lapis_ore 22 0 lapis_block 23 0 dispenser facing down triggered false 23 1 dispenser facing up triggered false 23 2 dispenser facing north triggered false 23 3 dispenser facing south triggered false 23 4 dispenser facing west triggered false 23 5 dispenser facing east triggered false 23 8 dispenser facing down triggered true 23 9 dispenser facing up triggered true 23 10 dispenser facing north triggered true 23 11 dispenser facing south triggered true 23 12 dispenser facing west triggered true 23 13 dispenser facing east triggered true 24 0 sandstone 24 1 chiseled_sandstone 24 2 cut_sandstone 25 0 note_block 26 0 red_bed facing south occupied false part foot 26 1 red_bed facing west occupied false part foot 26 2 red_bed facing north occupied false part foot 26 3 red_bed facing east occupied false part foot 26 8 red_bed facing south occupied false part head 26 9 red_bed facing west occupied false part head 26 10 red_bed facing north occupied false part head 26 11 red_bed facing east occupied false part head 26 12 red_bed facing south occupied true part head 26 13 red_bed facing west occupied true part head 26 14 red_bed facing north occupied true part head 26 15 red_bed facing east occupied true part head 27 0 powered_rail shape north_south powered false 27 1 powered_rail shape east_west powered false 27 2 powered_rail shape ascending_east powered false 27 3 powered_rail shape ascending_west powered false 27 4 powered_rail shape ascending_north powered false 27 5 powered_rail shape ascending_south powered false 27 8 powered_rail shape north_south powered true 27 9 powered_rail shape east_west powered true 27 10 powered_rail shape ascending_east powered true 27 11 powered_rail shape ascending_west powered true 27 12 powered_rail shape ascending_north powered true 27 13 powered_rail shape ascending_south powered true 28 0 detector_rail shape north_south powered false 28 1 detector_rail shape east_west powered false 28 2 detector_rail shape ascending_east powered false 28 3 detector_rail shape ascending_west powered false 28 4 detector_rail shape ascending_north powered false 28 5 detector_rail shape ascending_south powered false 28 8 detector_rail shape north_south powered true 28 9 detector_rail shape east_west powered true 28 10 detector_rail shape ascending_east powered true 28 11 detector_rail shape ascending_west powered true 28 12 detector_rail shape ascending_north powered true 28 13 detector_rail shape ascending_south powered true 29 0 sticky_piston facing down extended false 29 1 sticky_piston facing up extended false 29 2 sticky_piston facing north extended false 29 3 sticky_piston facing south extended false 29 4 sticky_piston facing west extended false 29 5 sticky_piston facing east extended false 29 8 sticky_piston facing down extended true 29 9 sticky_piston facing up extended true 29 10 sticky_piston facing north extended true 29 11 sticky_piston facing south extended true 29 12 sticky_piston facing west extended true 29 13 sticky_piston facing east extended true 30 0 cobweb 31 0 dead_bush 31 1 grass 31 2 fern 32 0 dead_bush 33 0 piston facing down extended false 33 1 piston facing up extended false 33 2 piston facing north extended false 33 3 piston facing south extended false 33 4 piston facing west extended false 33 5 piston facing east extended false 33 8 piston facing down extended true 33 9 piston facing up extended true 33 10 piston facing north extended true 33 11 piston facing south extended true 33 12 piston facing west extended true 33 13 piston facing east extended true 34 0 piston_head facing down short false type normal 34 1 piston_head facing up short false type normal 34 2 piston_head facing north short false type normal 34 3 piston_head facing south short false type normal 34 4 piston_head facing west short false type normal 34 5 piston_head facing east short false type normal 34 8 piston_head facing down short false type sticky 34 9 piston_head facing up short false type sticky 34 10 piston_head facing north short false type sticky 34 11 piston_head facing south short false type sticky 34 12 piston_head facing west short false type sticky 34 13 piston_head facing east short false type sticky 35 0 white_wool 35 1 orange_wool 35 2 magenta_wool 35 3 light_blue_wool 35 4 yellow_wool 35 5 lime_wool 35 6 pink_wool 35 7 gray_wool 35 8 light_gray_wool 35 9 cyan_wool 35 10 purple_wool 35 11 blue_wool 35 12 brown_wool 35 13 green_wool 35 14 red_wool 35 15 black_wool 36 0 moving_piston facing down type normal 36 1 moving_piston facing up type normal 36 2 moving_piston facing north type normal 36 3 moving_piston facing south type normal 36 4 moving_piston facing west type normal 36 5 moving_piston facing east type normal 36 8 moving_piston facing down type sticky 36 9 moving_piston facing up type sticky 36 10 moving_piston facing north type sticky 36 11 moving_piston facing south type sticky 36 12 moving_piston facing west type sticky 36 13 moving_piston facing east type sticky 37 0 dandelion 38 0 poppy 38 1 blue_orchid 38 2 allium 38 3 azure_bluet 38 4 red_tulip 38 5 orange_tulip 38 6 white_tulip 38 7 pink_tulip 38 8 oxeye_daisy 39 0 brown_mushroom 40 0 red_mushroom 41 0 gold_block 42 0 iron_block 43 0 stone_slab type double 43 1 sandstone_slab type double 43 2 petrified_oak_slab type double 43 3 cobblestone_slab type double 43 4 brick_slab type double 43 5 stone_brick_slab type double 43 6 nether_brick_slab type double 43 7 quartz_slab type double 43 8 smooth_stone 43 9 smooth_sandstone 43 10 petrified_oak_slab type double 43 11 cobblestone_slab type double 43 12 brick_slab type double 43 13 stone_brick_slab type double 43 14 nether_brick_slab type double 43 15 smooth_quartz 44 0 stone_slab type bottom 44 1 sandstone_slab type bottom 44 2 petrified_oak_slab type bottom 44 3 cobblestone_slab type bottom 44 4 brick_slab type bottom 44 5 stone_brick_slab type bottom 44 6 nether_brick_slab type bottom 44 7 quartz_slab type bottom 44 8 stone_slab type top 44 9 sandstone_slab type top 44 10 petrified_oak_slab type top 44 11 cobblestone_slab type top 44 12 brick_slab type top 44 13 stone_brick_slab type top 44 14 nether_brick_slab type top 44 15 quartz_slab type top 45 0 bricks 46 0 tnt unstable false 46 1 tnt unstable true 47 0 bookshelf 48 0 mossy_cobblestone 49 0 obsidian 50 1 wall_torch facing east 50 2 wall_torch facing west 50 3 wall_torch facing south 50 4 wall_torch facing north 50 5 torch 51 0 fire north false south false east false age 0 up false west false 51 1 fire north false south false east false age 1 up false west false 51 2 fire north false south false east false age 2 up false west false 51 3 fire north false south false east false age 3 up false west false 51 4 fire north false south false east false age 4 up false west false 51 5 fire north false south false east false age 5 up false west false 51 6 fire north false south false east false age 6 up false west false 51 7 fire north false south false east false age 7 up false west false 51 8 fire north false south false east false age 8 up false west false 51 9 fire north false south false east false age 9 up false west false 51 10 fire north false south false east false age 10 up false west false 51 11 fire north false south false east false age 11 up false west false 51 12 fire north false south false east false age 12 up false west false 51 13 fire north false south false east false age 13 up false west false 51 14 fire north false south false east false age 14 up false west false 51 15 fire north false south false east false age 15 up false west false 52 0 mob_spawner 53 0 oak_stairs facing east shape straight half bottom 53 1 oak_stairs facing west shape straight half bottom 53 2 oak_stairs facing south shape straight half bottom 53 3 oak_stairs facing north shape straight half bottom 53 4 oak_stairs facing east shape straight half top 53 5 oak_stairs facing west shape straight half top 53 6 oak_stairs facing south shape straight half top 53 7 oak_stairs facing north shape straight half top 54 2 chest facing north type single 54 3 chest facing south type single 54 4 chest facing west type single 54 5 chest facing east type single 55 0 redstone_wire south none east none north none power 0 west none 55 1 redstone_wire south none east none north none power 1 west none 55 2 redstone_wire south none east none north none power 2 west none 55 3 redstone_wire south none east none north none power 3 west none 55 4 redstone_wire south none east none north none power 4 west none 55 5 redstone_wire south none east none north none power 5 west none 55 6 redstone_wire south none east none north none power 6 west none 55 7 redstone_wire south none east none north none power 7 west none 55 8 redstone_wire south none east none north none power 8 west none 55 9 redstone_wire south none east none north none power 9 west none 55 10 redstone_wire south none east none north none power 10 west none 55 11 redstone_wire south none east none north none power 11 west none 55 12 redstone_wire south none east none north none power 12 west none 55 13 redstone_wire south none east none north none power 13 west none 55 14 redstone_wire south none east none north none power 14 west none 55 15 redstone_wire south none east none north none power 15 west none 56 0 diamond_ore 57 0 diamond_block 58 0 crafting_table 59 0 wheat age 0 59 1 wheat age 1 59 2 wheat age 2 59 3 wheat age 3 59 4 wheat age 4 59 5 wheat age 5 59 6 wheat age 6 59 7 wheat age 7 60 0 farmland moisture 0 60 1 farmland moisture 1 60 2 farmland moisture 2 60 3 farmland moisture 3 60 4 farmland moisture 4 60 5 farmland moisture 5 60 6 farmland moisture 6 60 7 farmland moisture 7 61 2 furnace facing north lit false 61 3 furnace facing south lit false 61 4 furnace facing west lit false 61 5 furnace facing east lit false 62 2 furnace facing north lit true 62 3 furnace facing south lit true 62 4 furnace facing west lit true 62 5 furnace facing east lit true 63 0 sign rotation 0 63 1 sign rotation 1 63 2 sign rotation 2 63 3 sign rotation 3 63 4 sign rotation 4 63 5 sign rotation 5 63 6 sign rotation 6 63 7 sign rotation 7 63 8 sign rotation 8 63 9 sign rotation 9 63 10 sign rotation 10 63 11 sign rotation 11 63 12 sign rotation 12 63 13 sign rotation 13 63 14 sign rotation 14 63 15 sign rotation 15 64 0 oak_door hinge right half lower facing east powered false open false 64 1 oak_door hinge right half lower facing south powered false open false 64 2 oak_door hinge right half lower facing west powered false open false 64 3 oak_door hinge right half lower facing north powered false open false 64 4 oak_door hinge right half lower facing east powered false open true 64 5 oak_door hinge right half lower facing south powered false open true 64 6 oak_door hinge right half lower facing west powered false open true 64 7 oak_door hinge right half lower facing north powered false open true 64 8 oak_door hinge left half upper facing east powered false open false 64 9 oak_door hinge right half upper facing east powered false open false 64 10 oak_door hinge left half upper facing east powered true open false 64 11 oak_door hinge right half upper facing east powered true open false 64 12 oak_door hinge left half upper facing east powered false open true 64 13 oak_door hinge left half upper facing south powered false open true 64 14 oak_door hinge left half upper facing west powered false open true 64 15 oak_door hinge left half upper facing north powered false open true 65 2 ladder facing north 65 3 ladder facing south 65 4 ladder facing west 65 5 ladder facing east 66 0 rail shape north_south 66 1 rail shape east_west 66 2 rail shape ascending_east 66 3 rail shape ascending_west 66 4 rail shape ascending_north 66 5 rail shape ascending_south 66 6 rail shape south_east 66 7 rail shape south_west 66 8 rail shape north_west 66 9 rail shape north_east 67 0 cobblestone_stairs facing east shape straight half bottom 67 1 cobblestone_stairs facing west shape straight half bottom 67 2 cobblestone_stairs facing south shape straight half bottom 67 3 cobblestone_stairs facing north shape straight half bottom 67 4 cobblestone_stairs facing east shape straight half top 67 5 cobblestone_stairs facing west shape straight half top 67 6 cobblestone_stairs facing south shape straight half top 67 7 cobblestone_stairs facing north shape straight half top 68 2 wall_sign facing north 68 3 wall_sign facing south 68 4 wall_sign facing west 68 5 wall_sign facing east 69 0 lever facing west face ceiling powered false 69 1 lever facing east face wall powered false 69 2 lever facing west face wall powered false 69 3 lever facing south face wall powered false 69 4 lever facing north face wall powered false 69 5 lever facing north face floor powered false 69 6 lever facing west face floor powered false 69 7 lever facing north face ceiling powered false 69 8 lever facing west face ceiling powered true 69 9 lever facing east face wall powered true 69 10 lever facing west face wall powered true 69 11 lever facing south face wall powered true 69 12 lever facing north face wall powered true 69 13 lever facing north face floor powered true 69 14 lever facing west face floor powered true 69 15 lever facing north face ceiling powered true 70 0 stone_pressure_plate powered false 70 1 stone_pressure_plate powered true 71 0 iron_door hinge right half lower facing east powered false open false 71 1 iron_door hinge right half lower facing south powered false open false 71 2 iron_door hinge right half lower facing west powered false open false 71 3 iron_door hinge right half lower facing north powered false open false 71 4 iron_door hinge right half lower facing east powered false open true 71 5 iron_door hinge right half lower facing south powered false open true 71 6 iron_door hinge right half lower facing west powered false open true 71 7 iron_door hinge right half lower facing north powered false open true 71 8 iron_door hinge left half upper facing east powered false open false 71 9 iron_door hinge right half upper facing east powered false open false 71 10 iron_door hinge left half upper facing east powered true open false 71 11 iron_door hinge right half upper facing east powered true open false 71 12 iron_door hinge left half upper facing east powered false open true 71 13 iron_door hinge left half upper facing south powered false open true 71 14 iron_door hinge left half upper facing west powered false open true 71 15 iron_door hinge left half upper facing north powered false open true 72 0 oak_pressure_plate powered false 72 1 oak_pressure_plate powered true 73 0 redstone_ore lit false 74 0 redstone_ore lit true 75 1 redstone_wall_torch facing east lit false 75 2 redstone_wall_torch facing west lit false 75 3 redstone_wall_torch facing south lit false 75 4 redstone_wall_torch facing north lit false 75 5 redstone_torch lit false 76 1 redstone_wall_torch facing east lit true 76 2 redstone_wall_torch facing west lit true 76 3 redstone_wall_torch facing south lit true 76 4 redstone_wall_torch facing north lit true 76 5 redstone_torch lit true 77 0 stone_button facing north face ceiling powered false 77 1 stone_button facing east face wall powered false 77 2 stone_button facing west face wall powered false 77 3 stone_button facing south face wall powered false 77 4 stone_button facing north face wall powered false 77 5 stone_button facing north face floor powered false 77 8 stone_button facing north face ceiling powered true 77 9 stone_button facing east face wall powered true 77 10 stone_button facing west face wall powered true 77 11 stone_button facing south face wall powered true 77 12 stone_button facing north face wall powered true 77 13 stone_button facing north face floor powered true 78 0 snow layers 1 78 1 snow layers 2 78 2 snow layers 3 78 3 snow layers 4 78 4 snow layers 5 78 5 snow layers 6 78 6 snow layers 7 78 7 snow layers 8 79 0 ice 80 0 snow_block 81 0 cactus age 0 81 1 cactus age 1 81 2 cactus age 2 81 3 cactus age 3 81 4 cactus age 4 81 5 cactus age 5 81 6 cactus age 6 81 7 cactus age 7 81 8 cactus age 8 81 9 cactus age 9 81 10 cactus age 10 81 11 cactus age 11 81 12 cactus age 12 81 13 cactus age 13 81 14 cactus age 14 81 15 cactus age 15 82 0 clay 83 0 sugar_cane age 0 83 1 sugar_cane age 1 83 2 sugar_cane age 2 83 3 sugar_cane age 3 83 4 sugar_cane age 4 83 5 sugar_cane age 5 83 6 sugar_cane age 6 83 7 sugar_cane age 7 83 8 sugar_cane age 8 83 9 sugar_cane age 9 83 10 sugar_cane age 10 83 11 sugar_cane age 11 83 12 sugar_cane age 12 83 13 sugar_cane age 13 83 14 sugar_cane age 14 83 15 sugar_cane age 15 84 0 jukebox has_record false 84 1 jukebox has_record true 85 0 oak_fence east false north false west false south false 86 0 carved_pumpkin facing south 86 1 carved_pumpkin facing west 86 2 carved_pumpkin facing north 86 3 carved_pumpkin facing east 87 0 netherrack 88 0 soul_sand 89 0 glowstone 90 1 portal axis x 90 2 portal axis z 91 0 jack_o_lantern facing south 91 1 jack_o_lantern facing west 91 2 jack_o_lantern facing north 91 3 jack_o_lantern facing east 92 0 cake bites 0 92 1 cake bites 1 92 2 cake bites 2 92 3 cake bites 3 92 4 cake bites 4 92 5 cake bites 5 92 6 cake bites 6 93 0 repeater facing south powered false locked false delay 1 93 1 repeater facing west powered false locked false delay 1 93 2 repeater facing north powered false locked false delay 1 93 3 repeater facing east powered false locked false delay 1 93 4 repeater facing south powered false locked false delay 2 93 5 repeater facing west powered false locked false delay 2 93 6 repeater facing north powered false locked false delay 2 93 7 repeater facing east powered false locked false delay 2 93 8 repeater facing south powered false locked false delay 3 93 9 repeater facing west powered false locked false delay 3 93 10 repeater facing north powered false locked false delay 3 93 11 repeater facing east powered false locked false delay 3 93 12 repeater facing south powered false locked false delay 4 93 13 repeater facing west powered false locked false delay 4 93 14 repeater facing north powered false locked false delay 4 93 15 repeater facing east powered false locked false delay 4 94 0 repeater facing south powered true locked false delay 1 94 1 repeater facing west powered true locked false delay 1 94 2 repeater facing north powered true locked false delay 1 94 3 repeater facing east powered true locked false delay 1 94 4 repeater facing south powered true locked false delay 2 94 5 repeater facing west powered true locked false delay 2 94 6 repeater facing north powered true locked false delay 2 94 7 repeater facing east powered true locked false delay 2 94 8 repeater facing south powered true locked false delay 3 94 9 repeater facing west powered true locked false delay 3 94 10 repeater facing north powered true locked false delay 3 94 11 repeater facing east powered true locked false delay 3 94 12 repeater facing south powered true locked false delay 4 94 13 repeater facing west powered true locked false delay 4 94 14 repeater facing north powered true locked false delay 4 94 15 repeater facing east powered true locked false delay 4 95 0 white_stained_glass 95 1 orange_stained_glass 95 2 magenta_stained_glass 95 3 light_blue_stained_glass 95 4 yellow_stained_glass 95 5 lime_stained_glass 95 6 pink_stained_glass 95 7 gray_stained_glass 95 8 light_gray_stained_glass 95 9 cyan_stained_glass 95 10 purple_stained_glass 95 11 blue_stained_glass 95 12 brown_stained_glass 95 13 green_stained_glass 95 14 red_stained_glass 95 15 black_stained_glass 96 0 oak_trapdoor facing north open false half bottom 96 1 oak_trapdoor facing south open false half bottom 96 2 oak_trapdoor facing west open false half bottom 96 3 oak_trapdoor facing east open false half bottom 96 4 oak_trapdoor facing north open true half bottom 96 5 oak_trapdoor facing south open true half bottom 96 6 oak_trapdoor facing west open true half bottom 96 7 oak_trapdoor facing east open true half bottom 96 8 oak_trapdoor facing north open false half top 96 9 oak_trapdoor facing south open false half top 96 10 oak_trapdoor facing west open false half top 96 11 oak_trapdoor facing east open false half top 96 12 oak_trapdoor facing north open true half top 96 13 oak_trapdoor facing south open true half top 96 14 oak_trapdoor facing west open true half top 96 15 oak_trapdoor facing east open true half top 97 0 infested_stone 97 1 infested_cobblestone 97 2 infested_stone_bricks 97 3 infested_mossy_stone_bricks 97 4 infested_cracked_stone_bricks 97 5 infested_chiseled_stone_bricks 98 0 stone_bricks 98 1 mossy_stone_bricks 98 2 cracked_stone_bricks 98 3 chiseled_stone_bricks 99 0 brown_mushroom_block down false south false east false north false up false west false 99 1 brown_mushroom_block down false south false east false north true up true west true 99 2 brown_mushroom_block down false south false east false north true up true west false 99 3 brown_mushroom_block down false south false east true north true up true west false 99 4 brown_mushroom_block down false south false east false north false up true west true 99 5 brown_mushroom_block down false south false east false north false up true west false 99 6 brown_mushroom_block down false south false east true north false up true west false 99 7 brown_mushroom_block down false south true east false north false up true west true 99 8 brown_mushroom_block down false south true east false north false up true west false 99 9 brown_mushroom_block down false south true east true north false up true west false 99 10 mushroom_stem down false south true east true north true up false west true 99 11 brown_mushroom_block down false south false east false north false up false west false 99 12 brown_mushroom_block down false south false east false north false up false west false 99 13 brown_mushroom_block down false south false east false north false up false west false 99 14 brown_mushroom_block down true south true east true north true up true west true 99 15 mushroom_stem down true south true east true north true up true west true 100 0 red_mushroom_block down false south false east false north false up false west false 100 1 red_mushroom_block down false south false east false north true up true west true 100 2 red_mushroom_block down false south false east false north true up true west false 100 3 red_mushroom_block down false south false east true north true up true west false 100 4 red_mushroom_block down false south false east false north false up true west true 100 5 red_mushroom_block down false south false east false north false up true west false 100 6 red_mushroom_block down false south false east true north false up true west false 100 7 red_mushroom_block down false south true east false north false up true west true 100 8 red_mushroom_block down false south true east false north false up true west false 100 9 red_mushroom_block down false south true east true north false up true west false 100 10 mushroom_stem down false south true east true north true up false west true 100 11 red_mushroom_block down false south false east false north false up false west false 100 12 red_mushroom_block down false south false east false north false up false west false 100 13 red_mushroom_block down false south false east false north false up false west false 100 14 red_mushroom_block down true south true east true north true up true west true 100 15 mushroom_stem down true south true east true north true up true west true 101 0 iron_bars east false north false west false south false 102 0 glass_pane east false north false west false south false 103 0 melon_block 104 0 pumpkin_stem age 0 104 1 pumpkin_stem age 1 104 2 pumpkin_stem age 2 104 3 pumpkin_stem age 3 104 4 pumpkin_stem age 4 104 5 pumpkin_stem age 5 104 6 pumpkin_stem age 6 104 7 pumpkin_stem age 7 105 0 melon_stem age 0 105 1 melon_stem age 1 105 2 melon_stem age 2 105 3 melon_stem age 3 105 4 melon_stem age 4 105 5 melon_stem age 5 105 6 melon_stem age 6 105 7 melon_stem age 7 106 0 vine south false east false north false up true west false 106 1 vine south true east false north false up true west false 106 2 vine south false east false north false up true west true 106 3 vine south true east false north false up true west true 106 4 vine south false east false north true up true west false 106 5 vine south true east false north true up true west false 106 6 vine south false east false north true up true west true 106 7 vine south true east false north true up true west true 106 8 vine south false east true north false up true west false 106 9 vine south true east true north false up true west false 106 10 vine south false east true north false up true west true 106 11 vine south true east true north false up true west true 106 12 vine south false east true north true up true west false 106 13 vine south true east true north true up true west false 106 14 vine south false east true north true up true west true 106 15 vine south true east true north true up true west true 107 0 oak_fence_gate facing south powered false open false in_wall false 107 1 oak_fence_gate facing west powered false open false in_wall false 107 2 oak_fence_gate facing north powered false open false in_wall false 107 3 oak_fence_gate facing east powered false open false in_wall false 107 4 oak_fence_gate facing south powered false open true in_wall false 107 5 oak_fence_gate facing west powered false open true in_wall false 107 6 oak_fence_gate facing north powered false open true in_wall false 107 7 oak_fence_gate facing east powered false open true in_wall false 107 8 oak_fence_gate facing south powered true open false in_wall false 107 9 oak_fence_gate facing west powered true open false in_wall false 107 10 oak_fence_gate facing north powered true open false in_wall false 107 11 oak_fence_gate facing east powered true open false in_wall false 107 12 oak_fence_gate facing south powered true open true in_wall false 107 13 oak_fence_gate facing west powered true open true in_wall false 107 14 oak_fence_gate facing north powered true open true in_wall false 107 15 oak_fence_gate facing east powered true open true in_wall false 108 0 brick_stairs facing east shape straight half bottom 108 1 brick_stairs facing west shape straight half bottom 108 2 brick_stairs facing south shape straight half bottom 108 3 brick_stairs facing north shape straight half bottom 108 4 brick_stairs facing east shape straight half top 108 5 brick_stairs facing west shape straight half top 108 6 brick_stairs facing south shape straight half top 108 7 brick_stairs facing north shape straight half top 109 0 stone_brick_stairs facing east shape straight half bottom 109 1 stone_brick_stairs facing west shape straight half bottom 109 2 stone_brick_stairs facing south shape straight half bottom 109 3 stone_brick_stairs facing north shape straight half bottom 109 4 stone_brick_stairs facing east shape straight half top 109 5 stone_brick_stairs facing west shape straight half top 109 6 stone_brick_stairs facing south shape straight half top 109 7 stone_brick_stairs facing north shape straight half top 110 0 mycelium snowy false 111 0 lily_pad 112 0 nether_bricks 113 0 nether_brick_fence east false north false west false south false 114 0 nether_brick_stairs facing east shape straight half bottom 114 1 nether_brick_stairs facing west shape straight half bottom 114 2 nether_brick_stairs facing south shape straight half bottom 114 3 nether_brick_stairs facing north shape straight half bottom 114 4 nether_brick_stairs facing east shape straight half top 114 5 nether_brick_stairs facing west shape straight half top 114 6 nether_brick_stairs facing south shape straight half top 114 7 nether_brick_stairs facing north shape straight half top 115 0 nether_wart age 0 115 1 nether_wart age 1 115 2 nether_wart age 2 115 3 nether_wart age 3 116 0 enchanting_table 117 0 brewing_stand has_bottle_0 false has_bottle_1 false has_bottle_2 false 117 1 brewing_stand has_bottle_0 true has_bottle_1 false has_bottle_2 false 117 2 brewing_stand has_bottle_0 false has_bottle_1 true has_bottle_2 false 117 3 brewing_stand has_bottle_0 true has_bottle_1 true has_bottle_2 false 117 4 brewing_stand has_bottle_0 false has_bottle_1 false has_bottle_2 true 117 5 brewing_stand has_bottle_0 true has_bottle_1 false has_bottle_2 true 117 6 brewing_stand has_bottle_0 false has_bottle_1 true has_bottle_2 true 117 7 brewing_stand has_bottle_0 true has_bottle_1 true has_bottle_2 true 118 0 cauldron level 0 118 1 cauldron level 1 118 2 cauldron level 2 118 3 cauldron level 3 119 0 end_portal 120 0 end_portal_frame facing south eye false 120 1 end_portal_frame facing west eye false 120 2 end_portal_frame facing north eye false 120 3 end_portal_frame facing east eye false 120 4 end_portal_frame facing south eye true 120 5 end_portal_frame facing west eye true 120 6 end_portal_frame facing north eye true 120 7 end_portal_frame facing east eye true 121 0 end_stone 122 0 dragon_egg 123 0 redstone_lamp lit false 124 0 redstone_lamp lit true 125 0 oak_slab type double 125 1 spruce_slab type double 125 2 birch_slab type double 125 3 jungle_slab type double 125 4 acacia_slab type double 125 5 dark_oak_slab type double 126 0 oak_slab type bottom 126 1 spruce_slab type bottom 126 2 birch_slab type bottom 126 3 jungle_slab type bottom 126 4 acacia_slab type bottom 126 5 dark_oak_slab type bottom 126 8 oak_slab type top 126 9 spruce_slab type top 126 10 birch_slab type top 126 11 jungle_slab type top 126 12 acacia_slab type top 126 13 dark_oak_slab type top 127 0 cocoa facing south age 0 127 1 cocoa facing west age 0 127 2 cocoa facing north age 0 127 3 cocoa facing east age 0 127 4 cocoa facing south age 1 127 5 cocoa facing west age 1 127 6 cocoa facing north age 1 127 7 cocoa facing east age 1 127 8 cocoa facing south age 2 127 9 cocoa facing west age 2 127 10 cocoa facing north age 2 127 11 cocoa facing east age 2 128 0 sandstone_stairs facing east shape straight half bottom 128 1 sandstone_stairs facing west shape straight half bottom 128 2 sandstone_stairs facing south shape straight half bottom 128 3 sandstone_stairs facing north shape straight half bottom 128 4 sandstone_stairs facing east shape straight half top 128 5 sandstone_stairs facing west shape straight half top 128 6 sandstone_stairs facing south shape straight half top 128 7 sandstone_stairs facing north shape straight half top 129 0 emerald_ore 130 2 ender_chest facing north 130 3 ender_chest facing south 130 4 ender_chest facing west 130 5 ender_chest facing east 131 0 tripwire_hook attached false facing south powered false 131 1 tripwire_hook attached false facing west powered false 131 2 tripwire_hook attached false facing north powered false 131 3 tripwire_hook attached false facing east powered false 131 4 tripwire_hook attached true facing south powered false 131 5 tripwire_hook attached true facing west powered false 131 6 tripwire_hook attached true facing north powered false 131 7 tripwire_hook attached true facing east powered false 131 8 tripwire_hook attached false facing south powered true 131 9 tripwire_hook attached false facing west powered true 131 10 tripwire_hook attached false facing north powered true 131 11 tripwire_hook attached false facing east powered true 131 12 tripwire_hook attached true facing south powered true 131 13 tripwire_hook attached true facing west powered true 131 14 tripwire_hook attached true facing north powered true 131 15 tripwire_hook attached true facing east powered true 132 0 tripwire attached false disarmed false powered false east false north false south false west false 132 1 tripwire attached false disarmed false powered true east false north false south false west false 132 2 tripwire attached false disarmed false powered false east false north false south false west false 132 3 tripwire attached false disarmed false powered true east false north false south false west false 132 4 tripwire attached true disarmed false powered false east false north false south false west false 132 5 tripwire attached true disarmed false powered true east false north false south false west false 132 6 tripwire attached true disarmed false powered false east false north false south false west false 132 7 tripwire attached true disarmed false powered true east false north false south false west false 132 8 tripwire attached false disarmed true powered false east false north false south false west false 132 9 tripwire attached false disarmed true powered true east false north false south false west false 132 10 tripwire attached false disarmed true powered false east false north false south false west false 132 11 tripwire attached false disarmed true powered true east false north false south false west false 132 12 tripwire attached true disarmed true powered false east false north false south false west false 132 13 tripwire attached true disarmed true powered true east false north false south false west false 132 14 tripwire attached true disarmed true powered false east false north false south false west false 133 0 emerald_block 134 0 spruce_stairs facing east shape straight half bottom 134 1 spruce_stairs facing west shape straight half bottom 134 2 spruce_stairs facing south shape straight half bottom 134 3 spruce_stairs facing north shape straight half bottom 134 4 spruce_stairs facing east shape straight half top 134 5 spruce_stairs facing west shape straight half top 134 6 spruce_stairs facing south shape straight half top 134 7 spruce_stairs facing north shape straight half top 135 0 birch_stairs facing east shape straight half bottom 135 1 birch_stairs facing west shape straight half bottom 135 2 birch_stairs facing south shape straight half bottom 135 3 birch_stairs facing north shape straight half bottom 135 4 birch_stairs facing east shape straight half top 135 5 birch_stairs facing west shape straight half top 135 6 birch_stairs facing south shape straight half top 135 7 birch_stairs facing north shape straight half top 136 0 jungle_stairs facing east shape straight half bottom 136 1 jungle_stairs facing west shape straight half bottom 136 2 jungle_stairs facing south shape straight half bottom 136 3 jungle_stairs facing north shape straight half bottom 136 4 jungle_stairs facing east shape straight half top 136 5 jungle_stairs facing west shape straight half top 136 6 jungle_stairs facing south shape straight half top 136 7 jungle_stairs facing north shape straight half top 137 0 command_block conditional false facing down 137 1 command_block conditional false facing up 137 2 command_block conditional false facing north 137 3 command_block conditional false facing south 137 4 command_block conditional false facing west 137 5 command_block conditional false facing east 137 8 command_block conditional true facing down 137 9 command_block conditional true facing up 137 10 command_block conditional true facing north 137 11 command_block conditional true facing south 137 12 command_block conditional true facing west 137 13 command_block conditional true facing east 138 0 beacon 139 0 cobblestone_wall south false east false north false up false west false 139 1 mossy_cobblestone_wall south false east false north false up false west false 140 0 potted_cactus 140 1 potted_cactus 140 2 potted_cactus 140 3 potted_cactus 140 4 potted_cactus 140 5 potted_cactus 140 6 potted_cactus 140 7 potted_cactus 140 8 potted_cactus 140 9 potted_cactus 140 10 potted_cactus 140 11 potted_cactus 140 12 potted_cactus 140 13 potted_cactus 140 14 potted_cactus 140 15 potted_cactus 141 0 carrots age 0 141 1 carrots age 1 141 2 carrots age 2 141 3 carrots age 3 141 4 carrots age 4 141 5 carrots age 5 141 6 carrots age 6 141 7 carrots age 7 142 0 potatoes age 0 142 1 potatoes age 1 142 2 potatoes age 2 142 3 potatoes age 3 142 4 potatoes age 4 142 5 potatoes age 5 142 6 potatoes age 6 142 7 potatoes age 7 143 0 oak_button facing north face ceiling powered false 143 1 oak_button facing east face wall powered false 143 2 oak_button facing west face wall powered false 143 3 oak_button facing south face wall powered false 143 4 oak_button facing north face wall powered false 143 5 oak_button facing north face floor powered false 143 8 oak_button facing north face ceiling powered true 143 9 oak_button facing east face wall powered true 143 10 oak_button facing west face wall powered true 143 11 oak_button facing south face wall powered true 143 12 oak_button facing north face wall powered true 143 13 oak_button facing north face floor powered true 144 0 %%FILTER_ME%% facing down nodrop false 144 1 %%FILTER_ME%% facing up nodrop false 144 2 %%FILTER_ME%% facing north nodrop false 144 3 %%FILTER_ME%% facing south nodrop false 144 4 %%FILTER_ME%% facing west nodrop false 144 5 %%FILTER_ME%% facing east nodrop false 144 8 %%FILTER_ME%% facing down nodrop true 144 9 %%FILTER_ME%% facing up nodrop true 144 10 %%FILTER_ME%% facing north nodrop true 144 11 %%FILTER_ME%% facing south nodrop true 144 12 %%FILTER_ME%% facing west nodrop true 144 13 %%FILTER_ME%% facing east nodrop true 145 0 anvil facing south 145 1 anvil facing west 145 2 anvil facing north 145 3 anvil facing east 145 4 chipped_anvil facing south 145 5 chipped_anvil facing west 145 6 chipped_anvil facing north 145 7 chipped_anvil facing east 145 8 damaged_anvil facing south 145 9 damaged_anvil facing west 145 10 damaged_anvil facing north 145 11 damaged_anvil facing east 146 2 trapped_chest facing north type single 146 3 trapped_chest facing south type single 146 4 trapped_chest facing west type single 146 5 trapped_chest facing east type single 147 0 light_weighted_pressure_plate power 0 147 1 light_weighted_pressure_plate power 1 147 2 light_weighted_pressure_plate power 2 147 3 light_weighted_pressure_plate power 3 147 4 light_weighted_pressure_plate power 4 147 5 light_weighted_pressure_plate power 5 147 6 light_weighted_pressure_plate power 6 147 7 light_weighted_pressure_plate power 7 147 8 light_weighted_pressure_plate power 8 147 9 light_weighted_pressure_plate power 9 147 10 light_weighted_pressure_plate power 10 147 11 light_weighted_pressure_plate power 11 147 12 light_weighted_pressure_plate power 12 147 13 light_weighted_pressure_plate power 13 147 14 light_weighted_pressure_plate power 14 147 15 light_weighted_pressure_plate power 15 148 0 heavy_weighted_pressure_plate power 0 148 1 heavy_weighted_pressure_plate power 1 148 2 heavy_weighted_pressure_plate power 2 148 3 heavy_weighted_pressure_plate power 3 148 4 heavy_weighted_pressure_plate power 4 148 5 heavy_weighted_pressure_plate power 5 148 6 heavy_weighted_pressure_plate power 6 148 7 heavy_weighted_pressure_plate power 7 148 8 heavy_weighted_pressure_plate power 8 148 9 heavy_weighted_pressure_plate power 9 148 10 heavy_weighted_pressure_plate power 10 148 11 heavy_weighted_pressure_plate power 11 148 12 heavy_weighted_pressure_plate power 12 148 13 heavy_weighted_pressure_plate power 13 148 14 heavy_weighted_pressure_plate power 14 148 15 heavy_weighted_pressure_plate power 15 149 0 comparator facing south mode compare powered false 149 1 comparator facing west mode compare powered false 149 2 comparator facing north mode compare powered false 149 3 comparator facing east mode compare powered false 149 4 comparator facing south mode subtract powered false 149 5 comparator facing west mode subtract powered false 149 6 comparator facing north mode subtract powered false 149 7 comparator facing east mode subtract powered false 149 8 comparator facing south mode compare powered true 149 9 comparator facing west mode compare powered true 149 10 comparator facing north mode compare powered true 149 11 comparator facing east mode compare powered true 149 12 comparator facing south mode subtract powered true 149 13 comparator facing west mode subtract powered true 149 14 comparator facing north mode subtract powered true 149 15 comparator facing east mode subtract powered true 150 0 comparator facing south mode compare powered false 150 1 comparator facing west mode compare powered false 150 2 comparator facing north mode compare powered false 150 3 comparator facing east mode compare powered false 150 4 comparator facing south mode subtract powered false 150 5 comparator facing west mode subtract powered false 150 6 comparator facing north mode subtract powered false 150 7 comparator facing east mode subtract powered false 150 8 comparator facing south mode compare powered true 150 9 comparator facing west mode compare powered true 150 10 comparator facing north mode compare powered true 150 11 comparator facing east mode compare powered true 150 12 comparator facing south mode subtract powered true 150 13 comparator facing west mode subtract powered true 150 14 comparator facing north mode subtract powered true 150 15 comparator facing east mode subtract powered true 151 0 daylight_detector inverted false power 0 151 1 daylight_detector inverted false power 1 151 2 daylight_detector inverted false power 2 151 3 daylight_detector inverted false power 3 151 4 daylight_detector inverted false power 4 151 5 daylight_detector inverted false power 5 151 6 daylight_detector inverted false power 6 151 7 daylight_detector inverted false power 7 151 8 daylight_detector inverted false power 8 151 9 daylight_detector inverted false power 9 151 10 daylight_detector inverted false power 10 151 11 daylight_detector inverted false power 11 151 12 daylight_detector inverted false power 12 151 13 daylight_detector inverted false power 13 151 14 daylight_detector inverted false power 14 151 15 daylight_detector inverted false power 15 152 0 redstone_block 153 0 nether_quartz_ore 154 0 hopper facing down enabled true 154 2 hopper facing north enabled true 154 3 hopper facing south enabled true 154 4 hopper facing west enabled true 154 5 hopper facing east enabled true 154 8 hopper facing down enabled false 154 10 hopper facing north enabled false 154 11 hopper facing south enabled false 154 12 hopper facing west enabled false 154 13 hopper facing east enabled false 155 0 quartz_block 155 1 chiseled_quartz_block 155 2 quartz_pillar axis y 155 3 quartz_pillar axis x 155 4 quartz_pillar axis z 156 0 quartz_stairs facing east shape straight half bottom 156 1 quartz_stairs facing west shape straight half bottom 156 2 quartz_stairs facing south shape straight half bottom 156 3 quartz_stairs facing north shape straight half bottom 156 4 quartz_stairs facing east shape straight half top 156 5 quartz_stairs facing west shape straight half top 156 6 quartz_stairs facing south shape straight half top 156 7 quartz_stairs facing north shape straight half top 157 0 activator_rail shape north_south powered false 157 1 activator_rail shape east_west powered false 157 2 activator_rail shape ascending_east powered false 157 3 activator_rail shape ascending_west powered false 157 4 activator_rail shape ascending_north powered false 157 5 activator_rail shape ascending_south powered false 157 8 activator_rail shape north_south powered true 157 9 activator_rail shape east_west powered true 157 10 activator_rail shape ascending_east powered true 157 11 activator_rail shape ascending_west powered true 157 12 activator_rail shape ascending_north powered true 157 13 activator_rail shape ascending_south powered true 158 0 dropper facing down triggered false 158 1 dropper facing up triggered false 158 2 dropper facing north triggered false 158 3 dropper facing south triggered false 158 4 dropper facing west triggered false 158 5 dropper facing east triggered false 158 8 dropper facing down triggered true 158 9 dropper facing up triggered true 158 10 dropper facing north triggered true 158 11 dropper facing south triggered true 158 12 dropper facing west triggered true 158 13 dropper facing east triggered true 159 0 white_terracotta 159 1 orange_terracotta 159 2 magenta_terracotta 159 3 light_blue_terracotta 159 4 yellow_terracotta 159 5 lime_terracotta 159 6 pink_terracotta 159 7 gray_terracotta 159 8 light_gray_terracotta 159 9 cyan_terracotta 159 10 purple_terracotta 159 11 blue_terracotta 159 12 brown_terracotta 159 13 green_terracotta 159 14 red_terracotta 159 15 black_terracotta 160 0 white_stained_glass_pane east false north false west false south false 160 1 orange_stained_glass_pane east false north false west false south false 160 2 magenta_stained_glass_pane east false north false west false south false 160 3 light_blue_stained_glass_pane east false north false west false south false 160 4 yellow_stained_glass_pane east false north false west false south false 160 5 lime_stained_glass_pane east false north false west false south false 160 6 pink_stained_glass_pane east false north false west false south false 160 7 gray_stained_glass_pane east false north false west false south false 160 8 light_gray_stained_glass_pane east false north false west false south false 160 9 cyan_stained_glass_pane east false north false west false south false 160 10 purple_stained_glass_pane east false north false west false south false 160 11 blue_stained_glass_pane east false north false west false south false 160 12 brown_stained_glass_pane east false north false west false south false 160 13 green_stained_glass_pane east false north false west false south false 160 14 red_stained_glass_pane east false north false west false south false 160 15 black_stained_glass_pane east false north false west false south false 161 0 acacia_leaves decayable true check_decay false 161 1 dark_oak_leaves decayable true check_decay false 161 4 acacia_leaves decayable false check_decay false 161 5 dark_oak_leaves decayable false check_decay false 161 8 acacia_leaves decayable true check_decay true 161 9 dark_oak_leaves decayable true check_decay true 161 12 acacia_leaves decayable false check_decay true 161 13 dark_oak_leaves decayable false check_decay true 162 0 acacia_log axis y 162 1 dark_oak_log axis y 162 4 acacia_log axis x 162 5 dark_oak_log axis x 162 8 acacia_log axis z 162 9 dark_oak_log axis z 162 12 acacia_bark 162 13 dark_oak_bark 163 0 acacia_stairs facing east shape straight half bottom 163 1 acacia_stairs facing west shape straight half bottom 163 2 acacia_stairs facing south shape straight half bottom 163 3 acacia_stairs facing north shape straight half bottom 163 4 acacia_stairs facing east shape straight half top 163 5 acacia_stairs facing west shape straight half top 163 6 acacia_stairs facing south shape straight half top 163 7 acacia_stairs facing north shape straight half top 164 0 dark_oak_stairs facing east shape straight half bottom 164 1 dark_oak_stairs facing west shape straight half bottom 164 2 dark_oak_stairs facing south shape straight half bottom 164 3 dark_oak_stairs facing north shape straight half bottom 164 4 dark_oak_stairs facing east shape straight half top 164 5 dark_oak_stairs facing west shape straight half top 164 6 dark_oak_stairs facing south shape straight half top 164 7 dark_oak_stairs facing north shape straight half top 165 0 slime_block 166 0 barrier 167 0 iron_trapdoor facing north open false half bottom 167 1 iron_trapdoor facing south open false half bottom 167 2 iron_trapdoor facing west open false half bottom 167 3 iron_trapdoor facing east open false half bottom 167 4 iron_trapdoor facing north open true half bottom 167 5 iron_trapdoor facing south open true half bottom 167 6 iron_trapdoor facing west open true half bottom 167 7 iron_trapdoor facing east open true half bottom 167 8 iron_trapdoor facing north open false half top 167 9 iron_trapdoor facing south open false half top 167 10 iron_trapdoor facing west open false half top 167 11 iron_trapdoor facing east open false half top 167 12 iron_trapdoor facing north open true half top 167 13 iron_trapdoor facing south open true half top 167 14 iron_trapdoor facing west open true half top 167 15 iron_trapdoor facing east open true half top 168 0 prismarine 168 1 prismarine_bricks 168 2 dark_prismarine 169 0 sea_lantern 170 0 hay_block axis y 170 4 hay_block axis x 170 8 hay_block axis z 171 0 white_carpet 171 1 orange_carpet 171 2 magenta_carpet 171 3 light_blue_carpet 171 4 yellow_carpet 171 5 lime_carpet 171 6 pink_carpet 171 7 gray_carpet 171 8 light_gray_carpet 171 9 cyan_carpet 171 10 purple_carpet 171 11 blue_carpet 171 12 brown_carpet 171 13 green_carpet 171 14 red_carpet 171 15 black_carpet 172 0 terracotta 173 0 coal_block 174 0 packed_ice 175 0 sunflower half lower 175 1 lilac half lower 175 2 tall_grass half lower 175 3 large_fern half lower 175 4 rose_bush half lower 175 5 peony half lower 175 8 peony half upper 175 9 peony half upper 175 10 peony half upper 175 11 peony half upper 176 0 white_banner rotation 0 176 1 white_banner rotation 1 176 2 white_banner rotation 2 176 3 white_banner rotation 3 176 4 white_banner rotation 4 176 5 white_banner rotation 5 176 6 white_banner rotation 6 176 7 white_banner rotation 7 176 8 white_banner rotation 8 176 9 white_banner rotation 9 176 10 white_banner rotation 10 176 11 white_banner rotation 11 176 12 white_banner rotation 12 176 13 white_banner rotation 13 176 14 white_banner rotation 14 176 15 white_banner rotation 15 177 2 white_wall_banner facing north 177 3 white_wall_banner facing south 177 4 white_wall_banner facing west 177 5 white_wall_banner facing east 178 0 daylight_detector inverted true power 0 178 1 daylight_detector inverted true power 1 178 2 daylight_detector inverted true power 2 178 3 daylight_detector inverted true power 3 178 4 daylight_detector inverted true power 4 178 5 daylight_detector inverted true power 5 178 6 daylight_detector inverted true power 6 178 7 daylight_detector inverted true power 7 178 8 daylight_detector inverted true power 8 178 9 daylight_detector inverted true power 9 178 10 daylight_detector inverted true power 10 178 11 daylight_detector inverted true power 11 178 12 daylight_detector inverted true power 12 178 13 daylight_detector inverted true power 13 178 14 daylight_detector inverted true power 14 178 15 daylight_detector inverted true power 15 179 0 red_sandstone 179 1 chiseled_red_sandstone 179 2 cut_red_sandstone 180 0 red_sandstone_stairs facing east shape straight half bottom 180 1 red_sandstone_stairs facing west shape straight half bottom 180 2 red_sandstone_stairs facing south shape straight half bottom 180 3 red_sandstone_stairs facing north shape straight half bottom 180 4 red_sandstone_stairs facing east shape straight half top 180 5 red_sandstone_stairs facing west shape straight half top 180 6 red_sandstone_stairs facing south shape straight half top 180 7 red_sandstone_stairs facing north shape straight half top 181 0 red_sandstone_slab type double 181 8 smooth_red_sandstone 182 0 red_sandstone_slab type bottom 182 8 red_sandstone_slab type top 183 0 spruce_fence_gate facing south powered false open false in_wall false 183 1 spruce_fence_gate facing west powered false open false in_wall false 183 2 spruce_fence_gate facing north powered false open false in_wall false 183 3 spruce_fence_gate facing east powered false open false in_wall false 183 4 spruce_fence_gate facing south powered false open true in_wall false 183 5 spruce_fence_gate facing west powered false open true in_wall false 183 6 spruce_fence_gate facing north powered false open true in_wall false 183 7 spruce_fence_gate facing east powered false open true in_wall false 183 8 spruce_fence_gate facing south powered true open false in_wall false 183 9 spruce_fence_gate facing west powered true open false in_wall false 183 10 spruce_fence_gate facing north powered true open false in_wall false 183 11 spruce_fence_gate facing east powered true open false in_wall false 183 12 spruce_fence_gate facing south powered true open true in_wall false 183 13 spruce_fence_gate facing west powered true open true in_wall false 183 14 spruce_fence_gate facing north powered true open true in_wall false 183 15 spruce_fence_gate facing east powered true open true in_wall false 184 0 birch_fence_gate facing south powered false open false in_wall false 184 1 birch_fence_gate facing west powered false open false in_wall false 184 2 birch_fence_gate facing north powered false open false in_wall false 184 3 birch_fence_gate facing east powered false open false in_wall false 184 4 birch_fence_gate facing south powered false open true in_wall false 184 5 birch_fence_gate facing west powered false open true in_wall false 184 6 birch_fence_gate facing north powered false open true in_wall false 184 7 birch_fence_gate facing east powered false open true in_wall false 184 8 birch_fence_gate facing south powered true open false in_wall false 184 9 birch_fence_gate facing west powered true open false in_wall false 184 10 birch_fence_gate facing north powered true open false in_wall false 184 11 birch_fence_gate facing east powered true open false in_wall false 184 12 birch_fence_gate facing south powered true open true in_wall false 184 13 birch_fence_gate facing west powered true open true in_wall false 184 14 birch_fence_gate facing north powered true open true in_wall false 184 15 birch_fence_gate facing east powered true open true in_wall false 185 0 jungle_fence_gate facing south powered false open false in_wall false 185 1 jungle_fence_gate facing west powered false open false in_wall false 185 2 jungle_fence_gate facing north powered false open false in_wall false 185 3 jungle_fence_gate facing east powered false open false in_wall false 185 4 jungle_fence_gate facing south powered false open true in_wall false 185 5 jungle_fence_gate facing west powered false open true in_wall false 185 6 jungle_fence_gate facing north powered false open true in_wall false 185 7 jungle_fence_gate facing east powered false open true in_wall false 185 8 jungle_fence_gate facing south powered true open false in_wall false 185 9 jungle_fence_gate facing west powered true open false in_wall false 185 10 jungle_fence_gate facing north powered true open false in_wall false 185 11 jungle_fence_gate facing east powered true open false in_wall false 185 12 jungle_fence_gate facing south powered true open true in_wall false 185 13 jungle_fence_gate facing west powered true open true in_wall false 185 14 jungle_fence_gate facing north powered true open true in_wall false 185 15 jungle_fence_gate facing east powered true open true in_wall false 186 0 dark_oak_fence_gate facing south powered false open false in_wall false 186 1 dark_oak_fence_gate facing west powered false open false in_wall false 186 2 dark_oak_fence_gate facing north powered false open false in_wall false 186 3 dark_oak_fence_gate facing east powered false open false in_wall false 186 4 dark_oak_fence_gate facing south powered false open true in_wall false 186 5 dark_oak_fence_gate facing west powered false open true in_wall false 186 6 dark_oak_fence_gate facing north powered false open true in_wall false 186 7 dark_oak_fence_gate facing east powered false open true in_wall false 186 8 dark_oak_fence_gate facing south powered true open false in_wall false 186 9 dark_oak_fence_gate facing west powered true open false in_wall false 186 10 dark_oak_fence_gate facing north powered true open false in_wall false 186 11 dark_oak_fence_gate facing east powered true open false in_wall false 186 12 dark_oak_fence_gate facing south powered true open true in_wall false 186 13 dark_oak_fence_gate facing west powered true open true in_wall false 186 14 dark_oak_fence_gate facing north powered true open true in_wall false 186 15 dark_oak_fence_gate facing east powered true open true in_wall false 187 0 acacia_fence_gate facing south powered false open false in_wall false 187 1 acacia_fence_gate facing west powered false open false in_wall false 187 2 acacia_fence_gate facing north powered false open false in_wall false 187 3 acacia_fence_gate facing east powered false open false in_wall false 187 4 acacia_fence_gate facing south powered false open true in_wall false 187 5 acacia_fence_gate facing west powered false open true in_wall false 187 6 acacia_fence_gate facing north powered false open true in_wall false 187 7 acacia_fence_gate facing east powered false open true in_wall false 187 8 acacia_fence_gate facing south powered true open false in_wall false 187 9 acacia_fence_gate facing west powered true open false in_wall false 187 10 acacia_fence_gate facing north powered true open false in_wall false 187 11 acacia_fence_gate facing east powered true open false in_wall false 187 12 acacia_fence_gate facing south powered true open true in_wall false 187 13 acacia_fence_gate facing west powered true open true in_wall false 187 14 acacia_fence_gate facing north powered true open true in_wall false 187 15 acacia_fence_gate facing east powered true open true in_wall false 188 0 spruce_fence east false north false west false south false 189 0 birch_fence east false north false west false south false 190 0 jungle_fence east false north false west false south false 191 0 dark_oak_fence east false north false west false south false 192 0 acacia_fence east false north false west false south false 193 0 spruce_door hinge right half lower facing east powered false open false 193 1 spruce_door hinge right half lower facing south powered false open false 193 2 spruce_door hinge right half lower facing west powered false open false 193 3 spruce_door hinge right half lower facing north powered false open false 193 4 spruce_door hinge right half lower facing east powered false open true 193 5 spruce_door hinge right half lower facing south powered false open true 193 6 spruce_door hinge right half lower facing west powered false open true 193 7 spruce_door hinge right half lower facing north powered false open true 193 8 spruce_door hinge left half upper facing east powered false open false 193 9 spruce_door hinge right half upper facing east powered false open false 193 10 spruce_door hinge left half upper facing east powered true open false 193 11 spruce_door hinge right half upper facing east powered true open false 194 0 birch_door hinge right half lower facing east powered false open false 194 1 birch_door hinge right half lower facing south powered false open false 194 2 birch_door hinge right half lower facing west powered false open false 194 3 birch_door hinge right half lower facing north powered false open false 194 4 birch_door hinge right half lower facing east powered false open true 194 5 birch_door hinge right half lower facing south powered false open true 194 6 birch_door hinge right half lower facing west powered false open true 194 7 birch_door hinge right half lower facing north powered false open true 194 8 birch_door hinge left half upper facing east powered false open false 194 9 birch_door hinge right half upper facing east powered false open false 194 10 birch_door hinge left half upper facing east powered true open false 194 11 birch_door hinge right half upper facing east powered true open false 195 0 jungle_door hinge right half lower facing east powered false open false 195 1 jungle_door hinge right half lower facing south powered false open false 195 2 jungle_door hinge right half lower facing west powered false open false 195 3 jungle_door hinge right half lower facing north powered false open false 195 4 jungle_door hinge right half lower facing east powered false open true 195 5 jungle_door hinge right half lower facing south powered false open true 195 6 jungle_door hinge right half lower facing west powered false open true 195 7 jungle_door hinge right half lower facing north powered false open true 195 8 jungle_door hinge left half upper facing east powered false open false 195 9 jungle_door hinge right half upper facing east powered false open false 195 10 jungle_door hinge left half upper facing east powered true open false 195 11 jungle_door hinge right half upper facing east powered true open false 196 0 acacia_door hinge right half lower facing east powered false open false 196 1 acacia_door hinge right half lower facing south powered false open false 196 2 acacia_door hinge right half lower facing west powered false open false 196 3 acacia_door hinge right half lower facing north powered false open false 196 4 acacia_door hinge right half lower facing east powered false open true 196 5 acacia_door hinge right half lower facing south powered false open true 196 6 acacia_door hinge right half lower facing west powered false open true 196 7 acacia_door hinge right half lower facing north powered false open true 196 8 acacia_door hinge left half upper facing east powered false open false 196 9 acacia_door hinge right half upper facing east powered false open false 196 10 acacia_door hinge left half upper facing east powered true open false 196 11 acacia_door hinge right half upper facing east powered true open false 197 0 dark_oak_door hinge right half lower facing east powered false open false 197 1 dark_oak_door hinge right half lower facing south powered false open false 197 2 dark_oak_door hinge right half lower facing west powered false open false 197 3 dark_oak_door hinge right half lower facing north powered false open false 197 4 dark_oak_door hinge right half lower facing east powered false open true 197 5 dark_oak_door hinge right half lower facing south powered false open true 197 6 dark_oak_door hinge right half lower facing west powered false open true 197 7 dark_oak_door hinge right half lower facing north powered false open true 197 8 dark_oak_door hinge left half upper facing east powered false open false 197 9 dark_oak_door hinge right half upper facing east powered false open false 197 10 dark_oak_door hinge left half upper facing east powered true open false 197 11 dark_oak_door hinge right half upper facing east powered true open false 198 0 end_rod facing down 198 1 end_rod facing up 198 2 end_rod facing north 198 3 end_rod facing south 198 4 end_rod facing west 198 5 end_rod facing east 199 0 chorus_plant up false south false east false north false down false west false 200 0 chorus_flower age 0 200 1 chorus_flower age 1 200 2 chorus_flower age 2 200 3 chorus_flower age 3 200 4 chorus_flower age 4 200 5 chorus_flower age 5 201 0 purpur_block 202 0 purpur_pillar axis y 202 4 purpur_pillar axis x 202 8 purpur_pillar axis z 203 0 purpur_stairs facing east shape straight half bottom 203 1 purpur_stairs facing west shape straight half bottom 203 2 purpur_stairs facing south shape straight half bottom 203 3 purpur_stairs facing north shape straight half bottom 203 4 purpur_stairs facing east shape straight half top 203 5 purpur_stairs facing west shape straight half top 203 6 purpur_stairs facing south shape straight half top 203 7 purpur_stairs facing north shape straight half top 204 0 purpur_slab type double 205 0 purpur_slab type bottom 205 8 purpur_slab type top 206 0 end_stone_bricks 207 0 beetroots age 0 207 1 beetroots age 1 207 2 beetroots age 2 207 3 beetroots age 3 208 0 grass_path 209 0 end_gateway 210 0 repeating_command_block conditional false facing down 210 1 repeating_command_block conditional false facing up 210 2 repeating_command_block conditional false facing north 210 3 repeating_command_block conditional false facing south 210 4 repeating_command_block conditional false facing west 210 5 repeating_command_block conditional false facing east 210 8 repeating_command_block conditional true facing down 210 9 repeating_command_block conditional true facing up 210 10 repeating_command_block conditional true facing north 210 11 repeating_command_block conditional true facing south 210 12 repeating_command_block conditional true facing west 210 13 repeating_command_block conditional true facing east 211 0 chain_command_block conditional false facing down 211 1 chain_command_block conditional false facing up 211 2 chain_command_block conditional false facing north 211 3 chain_command_block conditional false facing south 211 4 chain_command_block conditional false facing west 211 5 chain_command_block conditional false facing east 211 8 chain_command_block conditional true facing down 211 9 chain_command_block conditional true facing up 211 10 chain_command_block conditional true facing north 211 11 chain_command_block conditional true facing south 211 12 chain_command_block conditional true facing west 211 13 chain_command_block conditional true facing east 212 0 frosted_ice age 0 212 1 frosted_ice age 1 212 2 frosted_ice age 2 212 3 frosted_ice age 3 213 0 magma_block 214 0 nether_wart_block 215 0 red_nether_bricks 216 0 bone_block axis y 216 4 bone_block axis x 216 8 bone_block axis z 217 0 structure_void 218 0 observer facing down powered false 218 1 observer facing up powered false 218 2 observer facing north powered false 218 3 observer facing south powered false 218 4 observer facing west powered false 218 5 observer facing east powered false 218 8 observer facing down powered true 218 9 observer facing up powered true 218 10 observer facing north powered true 218 11 observer facing south powered true 218 12 observer facing west powered true 218 13 observer facing east powered true 219 0 white_shulker_box facing down 219 1 white_shulker_box facing up 219 2 white_shulker_box facing north 219 3 white_shulker_box facing south 219 4 white_shulker_box facing west 219 5 white_shulker_box facing east 220 0 orange_shulker_box facing down 220 1 orange_shulker_box facing up 220 2 orange_shulker_box facing north 220 3 orange_shulker_box facing south 220 4 orange_shulker_box facing west 220 5 orange_shulker_box facing east 221 0 magenta_shulker_box facing down 221 1 magenta_shulker_box facing up 221 2 magenta_shulker_box facing north 221 3 magenta_shulker_box facing south 221 4 magenta_shulker_box facing west 221 5 magenta_shulker_box facing east 222 0 light_blue_shulker_box facing down 222 1 light_blue_shulker_box facing up 222 2 light_blue_shulker_box facing north 222 3 light_blue_shulker_box facing south 222 4 light_blue_shulker_box facing west 222 5 light_blue_shulker_box facing east 223 0 yellow_shulker_box facing down 223 1 yellow_shulker_box facing up 223 2 yellow_shulker_box facing north 223 3 yellow_shulker_box facing south 223 4 yellow_shulker_box facing west 223 5 yellow_shulker_box facing east 224 0 lime_shulker_box facing down 224 1 lime_shulker_box facing up 224 2 lime_shulker_box facing north 224 3 lime_shulker_box facing south 224 4 lime_shulker_box facing west 224 5 lime_shulker_box facing east 225 0 pink_shulker_box facing down 225 1 pink_shulker_box facing up 225 2 pink_shulker_box facing north 225 3 pink_shulker_box facing south 225 4 pink_shulker_box facing west 225 5 pink_shulker_box facing east 226 0 gray_shulker_box facing down 226 1 gray_shulker_box facing up 226 2 gray_shulker_box facing north 226 3 gray_shulker_box facing south 226 4 gray_shulker_box facing west 226 5 gray_shulker_box facing east 227 0 light_gray_shulker_box facing down 227 1 light_gray_shulker_box facing up 227 2 light_gray_shulker_box facing north 227 3 light_gray_shulker_box facing south 227 4 light_gray_shulker_box facing west 227 5 light_gray_shulker_box facing east 228 0 cyan_shulker_box facing down 228 1 cyan_shulker_box facing up 228 2 cyan_shulker_box facing north 228 3 cyan_shulker_box facing south 228 4 cyan_shulker_box facing west 228 5 cyan_shulker_box facing east 229 0 purple_shulker_box facing down 229 1 purple_shulker_box facing up 229 2 purple_shulker_box facing north 229 3 purple_shulker_box facing south 229 4 purple_shulker_box facing west 229 5 purple_shulker_box facing east 230 0 blue_shulker_box facing down 230 1 blue_shulker_box facing up 230 2 blue_shulker_box facing north 230 3 blue_shulker_box facing south 230 4 blue_shulker_box facing west 230 5 blue_shulker_box facing east 231 0 brown_shulker_box facing down 231 1 brown_shulker_box facing up 231 2 brown_shulker_box facing north 231 3 brown_shulker_box facing south 231 4 brown_shulker_box facing west 231 5 brown_shulker_box facing east 232 0 green_shulker_box facing down 232 1 green_shulker_box facing up 232 2 green_shulker_box facing north 232 3 green_shulker_box facing south 232 4 green_shulker_box facing west 232 5 green_shulker_box facing east 233 0 red_shulker_box facing down 233 1 red_shulker_box facing up 233 2 red_shulker_box facing north 233 3 red_shulker_box facing south 233 4 red_shulker_box facing west 233 5 red_shulker_box facing east 234 0 black_shulker_box facing down 234 1 black_shulker_box facing up 234 2 black_shulker_box facing north 234 3 black_shulker_box facing south 234 4 black_shulker_box facing west 234 5 black_shulker_box facing east 235 0 white_glazed_terracotta facing south 235 1 white_glazed_terracotta facing west 235 2 white_glazed_terracotta facing north 235 3 white_glazed_terracotta facing east 236 0 orange_glazed_terracotta facing south 236 1 orange_glazed_terracotta facing west 236 2 orange_glazed_terracotta facing north 236 3 orange_glazed_terracotta facing east 237 0 magenta_glazed_terracotta facing south 237 1 magenta_glazed_terracotta facing west 237 2 magenta_glazed_terracotta facing north 237 3 magenta_glazed_terracotta facing east 238 0 light_blue_glazed_terracotta facing south 238 1 light_blue_glazed_terracotta facing west 238 2 light_blue_glazed_terracotta facing north 238 3 light_blue_glazed_terracotta facing east 239 0 yellow_glazed_terracotta facing south 239 1 yellow_glazed_terracotta facing west 239 2 yellow_glazed_terracotta facing north 239 3 yellow_glazed_terracotta facing east 240 0 lime_glazed_terracotta facing south 240 1 lime_glazed_terracotta facing west 240 2 lime_glazed_terracotta facing north 240 3 lime_glazed_terracotta facing east 241 0 pink_glazed_terracotta facing south 241 1 pink_glazed_terracotta facing west 241 2 pink_glazed_terracotta facing north 241 3 pink_glazed_terracotta facing east 242 0 gray_glazed_terracotta facing south 242 1 gray_glazed_terracotta facing west 242 2 gray_glazed_terracotta facing north 242 3 gray_glazed_terracotta facing east 243 0 light_gray_glazed_terracotta facing south 243 1 light_gray_glazed_terracotta facing west 243 2 light_gray_glazed_terracotta facing north 243 3 light_gray_glazed_terracotta facing east 244 0 cyan_glazed_terracotta facing south 244 1 cyan_glazed_terracotta facing west 244 2 cyan_glazed_terracotta facing north 244 3 cyan_glazed_terracotta facing east 245 0 purple_glazed_terracotta facing south 245 1 purple_glazed_terracotta facing west 245 2 purple_glazed_terracotta facing north 245 3 purple_glazed_terracotta facing east 246 0 blue_glazed_terracotta facing south 246 1 blue_glazed_terracotta facing west 246 2 blue_glazed_terracotta facing north 246 3 blue_glazed_terracotta facing east 247 0 brown_glazed_terracotta facing south 247 1 brown_glazed_terracotta facing west 247 2 brown_glazed_terracotta facing north 247 3 brown_glazed_terracotta facing east 248 0 green_glazed_terracotta facing south 248 1 green_glazed_terracotta facing west 248 2 green_glazed_terracotta facing north 248 3 green_glazed_terracotta facing east 249 0 red_glazed_terracotta facing south 249 1 red_glazed_terracotta facing west 249 2 red_glazed_terracotta facing north 249 3 red_glazed_terracotta facing east 250 0 black_glazed_terracotta facing south 250 1 black_glazed_terracotta facing west 250 2 black_glazed_terracotta facing north 250 3 black_glazed_terracotta facing east 251 0 white_concrete 251 1 orange_concrete 251 2 magenta_concrete 251 3 light_blue_concrete 251 4 yellow_concrete 251 5 lime_concrete 251 6 pink_concrete 251 7 gray_concrete 251 8 light_gray_concrete 251 9 cyan_concrete 251 10 purple_concrete 251 11 blue_concrete 251 12 brown_concrete 251 13 green_concrete 251 14 red_concrete 251 15 black_concrete 252 0 white_concrete_powder 252 1 orange_concrete_powder 252 2 magenta_concrete_powder 252 3 light_blue_concrete_powder 252 4 yellow_concrete_powder 252 5 lime_concrete_powder 252 6 pink_concrete_powder 252 7 gray_concrete_powder 252 8 light_gray_concrete_powder 252 9 cyan_concrete_powder 252 10 purple_concrete_powder 252 11 blue_concrete_powder 252 12 brown_concrete_powder 252 13 green_concrete_powder 252 14 red_concrete_powder 252 15 black_concrete_powder 255 0 structure_block mode save 255 1 structure_block mode load 255 2 structure_block mode corner 255 3 structure_block mode data ================================================ FILE: Server/README.txt ================================================ -------------------------------------------------------------------------------- Welcome to your new Cuberite server, compatible with Minecraft 1.8 - 1.12! -------------------------------------------------------------------------------- - To get started with your server, read the user's manual at https://book.cuberite.org/ - Subscribe to the Newsletter for update news and important information at https://cuberite.org/news/#subscribe - For information about adding plugins to your server, visit https://cuberite.org/plugins/ - For additional support, visit https://cuberite.org/discuss/ -------------------------------------------------------------------------------- ================================================ FILE: Server/brewing.txt ================================================ #*****************# # Brewing Recipes # #*****************# # The time for a brewing recipe is always 20 seconds (400 ticks). # # Minecraft-Wiki Brewing: # https://minecraft.wiki/w/Brewing # # A brewing recipe has this format: # Data Value + Ingredient = Potion ### Primary ### # Akward Potion 0 + netherwart = 8208 # Mundane Potion 0 + redstonedust = 8192 0 + ghasttear = 8192 0 + glisteringmelon = 8192 0 + blazepowder = 8192 0 + magmacream = 8192 0 + sugar = 8192 0 + spidereye = 8192 0 + rabbitsfoot = 8192 # Thick Potion 0 + glowstonedust = 8224 # Potion of Weakness 0 + fermentedspidereye = 8200 ### Secondary ### ## Positive ## # Potion of Healing 8208 + glisteringmelon = 8197 # Potion of Fire Resistance 8208 + magmacream = 8195 # Potion of Regeneration 8208 + ghasttear = 8193 # Potion of Strength 8208 + blazepowder = 8201 # Potion of Swiftness 8208 + sugar = 8194 # Potion of Night Vision 8208 + goldencarrot = 8198 # Potion of Water Breathing 8208 + pufferfish = 8205 # Potion of Leaping 8208 + rabbitsfoot = 8203 ## Negative ## # Potion of Poison 8208 + spidereye = 8196 # Potion of Weakness (extended) 8200 + redstonedust = 8264 ### Tertiary ### ## Positive ## # Potion of Fire Resistance (extended) 8195 + redstonedust = 8259 # Potion of Healing II 8197 + glowstonedust = 8229 # Potion of Regeneration (extended) 8193 + redstonedust = 8257 # Potion of Regeneration II 8193 + glowstonedust = 8225 # Potion of Strength (extended) 8201 + redstonedust = 8265 # Potion of Strength II 8201 + glowstonedust = 8233 # Potion of Swiftness (extended) 8194 + redstonedust = 8258 # Potion of Swiftness II 8194 + glowstonedust = 8226 # Potion of Night Vision (extended) 8198 + redstonedust = 8262 # Potion of Invisibility 8198 + fermentedspidereye = 8206 # Potion of Invisibility (extended) 8262 + fermentedspidereye = 8270 # Potion of Invisibility (extended) 8206 + redstonedust = 8270 # Potion of Water Breathing (extended) 8205 + redstonedust = 8269 # Potion of Leaping II 8203 + glowstonedust = 8235 # Potion of Leaping (extended) 8203 + redstonedust = 8267 ## Negative ## # Potion of Harming 8196 + fermentedspidereye = 8204 8197 + fermentedspidereye = 8204 8260 + fermentedspidereye = 8204 # Potion of Harming II 8228 + fermentedspidereye = 8236 8229 + fermentedspidereye = 8236 # Potion of Harming II 8204 + glowstonedust = 8236 # Potion of Poison (extended) 8196 + redstonedust = 8260 # Potion of Poison II 8196 + glowstonedust = 8228 # Potion of Slowness 8194 + fermentedspidereye = 8202 8203 + fermentedspidereye = 8202 # Potion of Slowness (extended) 8202 + redstonedust = 8266 # Potion of Slowness (extended) 8258 + fermentedspidereye = 8266 8267 + fermentedspidereye = 8266 ================================================ FILE: Server/delete_windows_service.cmd ================================================ @echo off set SERVICENAME="Cuberite" sc delete %SERVICENAME% ================================================ FILE: Server/furnace.txt ================================================ #*****************# # Furnace Recipes # #*****************# # # #******************************************************# # Basic Notation Help # # **** Item Definition **** # An Item is defined by an Item Type, an amount (and damage) # The damage is optional, and if not specified it's assumed to be 0. # If a damage of -1 is specified, then the damage won't be checked when matching recipes. # Note that when specifying items using names from items.ini, those already contain the damage value in them, # so the damage value doesn't need to be specified here. # # Cactus Green example: # 351 : 2 ( , 1 ) # ItemType : Damage ( , Amount ) # or simple use the item name (marked in items.ini): # CactusGreen ( , 1 ) # # # **** Recipe and result **** # # Cobble @ 200 = Stone $ 15 -> Produces 1 smooth stone from 1 cobblestone in 200 ticks (10 seconds). Rewards 15 experience. # # Write in full: # Cobble : 0 , 1 @ 200 = 1 : 1 , 1 $ 10 # ItemType : Damage , Amount @ ticks = ItemType : Damage , Amount $ Experience # # If the experience parameter isn't included, experience reward will default to zero. # # **** Fuel **** # # !17:1 = 300 -> 1 Wood burns for 300 ticks (15 s) # # ! Wood , 1 = 300 # Fuel ItemType , Amount = ticks # #******************************************************# #-------------------------- # Smelting recipes Beef = Steak $ 0.35 BlackTerracotta = BlackGlazedTerracotta $ 0.1 BlueTerracotta = BlueGlazedTerracotta $ 0.1 BrownTerracotta = BrownGlazedTerracotta $ 0.10 Cactus = CactusGreen $ 0.2 ChainmailBoots:-1 = IronNugget $ 0.1 ChainmailChestplate:-1 = IronNugget $ 0.1 ChainmailHelmet:-1 = IronNugget $ 0.1 ChainmailLeggings:-1 = IronNugget $ 0.1 Chicken = CookedChicken $ 0.35 ChorusFruit = PoppedChorusFruit $ 0.1 Clay = Brick $ 0.3 ClayBlock = HardenedClay $ 0.35 CoalOre = Coal $ 0.1 Cobblestone = Stone $ 0.1 CyanTerracotta = CyanGlazedTerracotta $ 0.1 DiamondOre = Diamond $ 1.0 EmeraldOre = Emerald $ 1.0 Fish = CookedFish $ 0.35 GoldOre = GoldIngot $ 1.0 GoldAxe:-1 = GoldNugget $ 0.1 GoldBoots:-1 = GoldNugget $ 0.1 GoldChestplate:-1 = GoldNugget $ 0.1 GoldHorseArmor:-1 = GoldNugget $ 0.1 GoldHelmet:-1 = GoldNugget $ 0.1 GoldHoe:-1 = GoldNugget $ 0.1 GoldPants:-1 = GoldNugget $ 0.1 GoldPickaxe:-1 = GoldNugget $ 0.1 GoldShovel:-1 = GoldNugget $ 0.1 GoldSword:-1 = GoldNugget $ 0.1 GrayTerracotta = GrayGlazedTerracotta $ 0.1 GreenTerracotta = GreenGlazedTerracotta $ 0.1 IronOre = IronIngot $ 0.7 IronAxe:-1 = IronNugget $ 0.1 IronBoots:-1 = IronNugget $ 0.1 IronChestplate:-1 = IronNugget $ 0.1 IronHorseArmor:-1 = IronNugget $ 0.1 IronHelmet:-1 = IronNugget $ 0.1 IronHoe:-1 = IronNugget $ 0.1 IronLeggings:-1 = IronNugget $ 0.1 IronPickaxe:-1 = IronNugget $ 0.1 IronShovel:-1 = IronNugget $ 0.1 IronSword:-1 = IronNugget $ 0.1 LapisOre = LapisLazuli $ 0.2 LightBlueTerracotta = LightBlueGlazedTerracotta $ 0.1 LightGrayTerracotta = LightGrayGlazedTerracotta $ 0.1 LimeTerracotta = LimeGlazedTerracotta $ 0.1 Log:-1 = CharCoal $ 0.15 Log2:-1 = CharCoal $ 0.15 MagentaTerracotta = MagentaGlazedTerracotta $ 0.1 Mutton = CookedMutton $ 0.35 NetherQuartzOre = NetherQuartz $ 0.2 Netherrack = NetherBrick $ 0.1 OrangeTerracotta = OrangeGlazedTerracotta $ 0.1 PinkTerracotta = PinkGlazedTerracotta $ 0.1 Porkchop = CookedPorkchop $ 0.35 Potato = BakedPotato $ 0.35 PurpleTerracotta = PurpleGlazedTerracotta $ 0.1 Rabbit = CookedRabbit $ 0.35 RedTerracotta = RedGlazedTerracotta $ 0.1 RedstoneOre = Redstone $ 0.7 Salmon = CookedSalmon $ 0.35 Sand = Glass $ 0.1 StoneBrick = CrackedStoneBricks $ 0.1 WetSponge = Sponge $ 0.15 WhiteTerracotta = WhiteGlazedTerracotta $ 0.1 YellowTerracotta = YellowGlazedTerracotta $ 0.1 #-------------------------- # Fuels ! AcaciaBoat = 400 # -> 20 sec ! AcaciaDoor = 200 # -> 10 sec ! AcaciaFence = 300 # -> 15 sec ! AcaciaFenceGate = 300 # -> 15 sec ! AcaciaStairs = 300 # -> 15 sec ! Banner = 300 # -> 15 sec ! BirchBoat = 400 # -> 20 sec ! BirchDoor = 200 # -> 10 sec ! BirchFence = 300 # -> 15 sec ! BirchFenceGate = 300 # -> 15 sec ! BirchStairs = 300 # -> 15 sec ! BlazeRod = 2400 # -> 120 sec ! Boat = 400 # -> 20 sec ! Bookshelf = 300 # -> 15 sec ! Bow = 300 # -> 15 sec ! Bowl = 100 # -> 5 sec ! BrownMushroomBlock = 300 # -> 15 sec ! Carpet = 67 # -> 3.35 sec ! CharCoal = 1600 # -> 80 sec ! Chest = 300 # -> 15 sec ! Coal = 1600 # -> 80 sec ! CoalBlock = 16000 # -> 800 sec ! CraftingTable = 300 # -> 15 sec ! DarkOakBoat = 400 # -> 20 sec ! DarkOakDoor = 200 # -> 10 sec ! DarkOakFence = 300 # -> 15 sec ! DarkOakFenceGate = 300 # -> 15 sec ! DarkOakStairs = 300 # -> 15 sec ! DaylightSensor = 300 # -> 15 sec ! Fence = 300 # -> 15 sec ! FenceGate = 300 # -> 15 sec ! FishingRod = 300 # -> 15 sec ! Jukebox = 300 # -> 15 sec ! JungleBoat = 400 # -> 20 sec ! JungleDoor = 200 # -> 10 sec ! JungleFence = 300 # -> 15 sec ! JungleFenceGate = 300 # -> 15 sec ! JungleStairs = 300 # -> 15 sec ! Ladder = 300 # -> 15 sec ! Lavabucket = 20000 # -> 1000 sec ! Log = 300 # -> 15 sec ! Log2 = 300 # -> 15 sec ! NoteBlock = 300 # -> 15 sec ! OakStairs = 300 # -> 15 sec ! Planks = 300 # -> 15 sec ! RedMushroomBlock = 300 # -> 15 sec ! Sapling = 100 # -> 5 sec ! Sign = 200 # -> 10 sec ! SpruceBoat = 400 # -> 20 sec ! SpruceDoor = 200 # -> 10 sec ! SpruceFence = 300 # -> 15 sec ! SpruceFenceGate = 300 # -> 15 sec ! SpruceStairs = 300 # -> 15 sec ! Stick = 100 # -> 5 sec ! Trapdoor = 300 # -> 15 sec ! TrappedChest = 300 # -> 15 sec ! WoodenAxe = 200 # -> 10 sec ! WoodenButton = 100 # -> 5 sec ! WoodenDoor = 200 # -> 10 sec ! WoodenHoe = 200 # -> 10 sec ! WoodenPressurePlate = 300 # -> 15 sec ! WoodenPickaxe = 200 # -> 10 sec ! WoodenSlab = 150 # -> 7.5 sec ! WoodenShovel = 200 # -> 10 sec ! WoodenSword = 200 # -> 10 sec ! Wool = 100 # -> 5 sec ================================================ FILE: Server/hg ================================================ #! /bin/bash # This script runs Cuberite under helgrind # It expects valgrind to be normally installed and available # Note that this is for Linux only and debug-only, since it slows down MCS way too much valgrind --log-file=helgrind.log --suppressions=hg.supp --gen-suppressions=all --tool=helgrind -v ./Cuberite ================================================ FILE: Server/hg.supp ================================================ # This is a valgrind suppressions file for running helgrind on Cuberite # Use by adding "--suppressions=hg.supp" to the helgrind commandline # This covers GCC bug 40518, https://gcc.gnu.org/bugzilla/show_bug.cgi?id=40518 # "Erasing an empty string causes a global value write / race condition warning in helgrind" # Original suppression authored by Jonathan Wakely: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=40518#c20 # Modified by Mattes to match the mangled function name used on Ubuntu { libstdcxx_std_string_race_pr40518 Helgrind:Race fun:_ZNSs9_M_mutateEjjj } ================================================ FILE: Server/install_windows_service.cmd ================================================ rem Alter this if you need to install multiple instances. @echo off set SERVICENAME="Cuberite" set CURRENTDIR=%CD% sc create %SERVICENAME% binPath= "%CURRENTDIR%\Cuberite.exe -d" start= auto DisplayName= "@%CURRENTDIR%\Cuberite.exe,-1" sc description %SERVICENAME% "@%CURRENTDIR%\Cuberite.exe,-2" ================================================ FILE: Server/vg ================================================ #! /bin/bash # This script runs Cuberite under valgrind # It expects valgrind to be normally installed and available # Note that this is for Linux only and debug-only, since it slows down MCS way too much valgrind --log-file=valgrind.log --suppressions=vg.supp --tool=memcheck --leak-check=full --leak-resolution=high --show-reachable=yes --track-origins=yes -v ./Cuberite ================================================ FILE: Server/vg.supp ================================================ ================================================ FILE: Server/webadmin/GenerateSelfSignedHTTPSCertUsingOpenssl.cmd ================================================ @echo off echo This script generates the certificate and private key for the https webadmin echo Note that the generated certificate is self-signed, and therefore not trusted by browsers echo Note that this script requires openssl to be installed and in PATH echo. echo When OpenSSL asks you for Common Name, you need to enter the fully qualified domain name of the server, that is, e. g. gallery.xoft.cz echo. echo If OpenSSL fails with an error, "WARNING: can't open config file: /usr/local/ssl/openssl.cnf", you need to run this script as an administrator echo. openssl req -x509 -newkey rsa:2048 -keyout httpskey.pem -out httpscert.crt -days 3650 -nodes pause ================================================ FILE: Server/webadmin/GenerateSelfSignedHTTPSCertUsingOpenssl.sh ================================================ #!/bin/bash echo "This script generates the certificate and private key for the https webadmin" echo "Note that the generated certificate is self-signed, and therefore not trusted by browsers" echo "Note that this script requires openssl to be installed and in PATH" echo "" echo "When OpenSSL asks you for Common Name, you need to enter the fully qualified domain name of the server, that is, e. g. gallery.xoft.cz" echo "" openssl req -x509 -newkey rsa:2048 -keyout httpskey.pem -out httpscert.crt -days 3650 -nodes ================================================ FILE: Server/webadmin/files/guest.html ================================================ Guest Information

    Hello! Welcome to the Cuberite WebAdmin.

    This is a default message, edit files/guest.html to add your own custom message.

    ================================================ FILE: Server/webadmin/files/style.css ================================================ /* Copyright Justin S and Cuberite Team, licensed under CC-BY-SA 3.0 */ * { font-family: inherit; margin: 0; } html, body { height: 100%; width: 100%; } body { font-family: Tahoma, Verdana, Arial, sans-serif; background: #fff; color: #343434; display: table; font-size: 13px; line-height: 1.4; } h4 { background: #F4F7F6; border-bottom: 1px solid #CCDDD9; padding: 8px 3px; } img { border: none; } ul { padding-top: 10px; padding-bottom: 10px; } p { margin: 4px 0; padding: 4px 3px; } hr { background: rgba(204, 221, 217, .6); border: none; height: 1px; margin: 5px 0; } a { color: #666; text-decoration: none; } a:visited { color: #444; text-decoration: none; } a:hover, a:active { color: #888; text-decoration: underline; } .color-background { background: #245A48; background: linear-gradient(200deg, #245d33, #24575D); text-shadow: 0 2px 1px rgba(0, 0, 0, .15); } .wrapper { padding: 0 15px; margin: auto; max-width: 1000px; } .header { border-bottom: 1px solid rgba(0, 0, 0, .2); padding: 13px 0; } .header a { color: #fff; text-decoration: none; } .header svg { vertical-align: top; } .logo { background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='42' height='42' viewBox='0 0 24 24'%3E%3Cpath fill='%23fff' d='M6 3.04l-6 3v11.92l6 3 6 3 6-3 6-3V6.03l-6-3-6.02-3-6 3zm5.05 4.58l.96.47.96-.5.96-.47V5.96c0-.64.02-1.18.05-1.2.08-.03 4.24 2.12 4.24 2.2 0 .03-1.4.76-3.1 1.63L12 10.14 9.05 8.67C7.4 7.85 5.98 7.13 5.87 7.05l-.2-.12 2.18-1.1 2.2-1.1.02 1.2v1.2zm-4.08 3.72l3.1 1.58v6.34l-2.2-1.1c-1.2-.6-2.2-1.1-2.2-1.13 0-.02.57-.3 1.25-.65l1.25-.6v-1.75l-1-.5-1-.5-1.16.6-1.2.58c-.02 0-.04-1-.04-2.23s.02-2.24.05-2.24c.03 0 1.45.7 3.17 1.58zm13.23.68l-.06 2.2-1.15-.58-1.18-.58-1 .5-1 .5v.74c0 .4.04.8.06.9.03.08.34.28.94.57.5.25 1 .53 1.14.65l.24.2-2.15 1.08-2.13 1.08v-6.4l3.14-1.54c1.73-.86 3.16-1.55 3.16-1.54.02 0 0 1-.02 2.22z'/%3E%3C/svg%3E") no-repeat left center; font-size: 32px; font-weight: bold; padding: 6px 6px 6px 56px; text-transform: uppercase; } .panel { background: #F4F7F6; border-bottom: 1px solid #CCDDD9; overflow: hidden; padding: 8px; } .welcome { display: inline; } .stats { float: right; font-weight: bold; padding: 0; } .stats li { display: inline; padding: 0 0 0 20px; } .link-login { background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='19' height='19' viewBox='0 0 24 24'%3E%3Cpath fill='%23B7A540' d='M12.65 10C11.7 7.31 8.9 5.5 5.77 6.12c-2.29.46-4.15 2.29-4.63 4.58C.32 14.57 3.26 18 7 18c2.61 0 4.83-1.67 5.65-4H17v2c0 1.1.9 2 2 2s2-.9 2-2v-2c1.1 0 2-.9 2-2s-.9-2-2-2h-8.35zM7 14c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2z'/%3E%3C/svg%3E") no-repeat left center; border: 0; margin: 0; padding: 0 0 0 24px; } .link-login:hover, .link-login:active { color: #888; text-decoration: underline; } .link-logout { background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='19' height='19' viewBox='0 0 24 24'%3E%3Cpath fill='%23c14544' d='M13 3h-2v10h2V3zm4.83 2.17l-1.42 1.42C17.99 7.86 19 9.81 19 12c0 3.87-3.13 7-7 7s-7-3.13-7-7c0-2.19 1.01-4.14 2.58-5.42L6.17 5.17C4.23 6.82 3 9.26 3 12c0 4.97 4.03 9 9 9s9-4.03 9-9c0-2.74-1.23-5.18-3.17-6.83z'/%3E%3C/svg%3E") no-repeat left center; margin: 0 0 0 10px; padding: 0 0 0 24px; } .columns { display: table-row; height: 100%; } .columns-wrapper { display: table; margin: auto; max-width: 1030px; padding: 0; width: 100%; } .columns-spacing { display: table-cell; padding: 15px; } .box { background: #f9fbfa; border: 1px solid #CCDDD9; border-radius: 7px; } .box.left { float: left; margin: 0; width: 220px; } .box.right { margin: 0 0 0 235px; } .guest-iframe { border: 0; min-height: 250px; max-height: 450px; } .head { border-radius: 6px 6px 0 0; color: #fff; font-size: 13px; font-weight: bold; padding: 9px; border-bottom: 1px solid rgba(0, 0, 0, .2); } .main-content { padding: 10px; } .category { background: #F4F7F6; border-bottom: 1px solid #CCDDD9; border-top: 1px solid #CCDDD9; font-weight: bold; padding: 6px; } .sidebar { list-style: none; padding: 6px; } .sidebar li a { display: block; } .link-home { background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 24 24'%3E%3Cpath fill='%23434343' d='M19,9.3V5c0-0.55-0.45-1-1-1h-1c-0.55,0-1,0.45-1,1v1.6l-3.33-3c-0.38-0.34-0.96-0.34-1.34,0l-8.36,7.53C2.63,11.43,2.84,12,3.3,12H5v7c0,0.55,0.45,1,1,1h3c0.55,0,1-0.45,1-1v-5h4v5c0,0.55,0.45,1,1,1h3c0.55,0,1-0.45,1-1v-7h1.7c0.46,0,0.68-0.57,0.33-0.87L19,9.3z M10,10c0-1.1,0.9-2,2-2s2,0.9,2,2H10z'/%3E%3C/svg%3E") no-repeat left center; padding: 4px 4px 4px 25px; } .link-page { background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='22' height='22' viewBox='0 0 24 24'%3E%3Cpath fill='%23434343' d='M16.01 7L16 4c0-.55-.45-1-1-1s-1 .45-1 1v3h-4V4c0-.55-.45-1-1-1s-1 .45-1 1v3h-.01C6.9 7 6 7.9 6 8.99v4.66c0 .53.21 1.04.58 1.41L9.5 18v2c0 .55.45 1 1 1h3c.55 0 1-.45 1-1v-2l2.92-2.92c.37-.38.58-.89.58-1.42V8.99C18 7.89 17.11 7 16.01 7z'/%3E%3C/svg%3E") no-repeat left center; padding: 4px 4px 4px 25px; } .link-subpage { background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='21' height='21' viewBox='0 0 24 24'%3E%3Cpath fill='%23666' d='M9.29 15.88L13.17 12 9.29 8.12c-.39-.39-.39-1.02 0-1.41.39-.39 1.02-.39 1.41 0l4.59 4.59c.39.39.39 1.02 0 1.41L10.7 17.3c-.39.39-1.02.39-1.41 0-.38-.39-.39-1.03 0-1.42z'/%3E%3C/svg%3E") no-repeat 20px center; padding: 4px 4px 4px 41px; } #ChatMessage { margin-top: 10px; width: 88%; } table { width: 100%; } th { border-bottom: 1px solid #CCDDD9; padding: 8px 5px; text-align: left; } tr:nth-child(odd) { background: #F4F7F6; } td { padding: 3px 5px; } button, input, select, textarea { background: #fff; border: 1px solid #ccc; border-radius: 5px; padding: 6px; } input[type="text"]:hover, input[type="text"]:focus { background: #f8f8f7; } button, input[type="submit"] { background: #f5f5f5; cursor: pointer; margin: 2px; } button, input[type="submit"]:hover { background: #E5E4E2; } button:disabled, input:disabled { color: #fff; background: #ccc; } .footer { display: table-row; } .footer a { font-weight: bold; } .copyright { display: inline; } .footer-links { float: right; padding: 0; } .footer-links li { display: inline; padding-left: 20px; } .footer-container { background: #F4F7F6; border-top: 1px solid #CCDDD9; overflow: hidden; padding: 10px; } @media (max-width: 700px) { .box.left { float: none; margin: 0 0 10px; width: 100%; } .box.right { margin: 0; } } ================================================ FILE: Server/webadmin/login_template.html ================================================ Cuberite WebAdmin - Login

    Cuberite WebAdmin

    ================================================ FILE: Server/webadmin/template.lua ================================================ -- Use a table for fast concatenation of strings local SiteContent = {} function Output(String) table.insert(SiteContent, String) end local function GetDefaultPage() local PM = cRoot:Get():GetPluginManager() local SubTitle = "Current Game" local Content = "" Content = Content .. "

    Plugins:

      " PM:ForEachPlugin( function (a_CBPlugin) if (a_CBPlugin:IsLoaded()) then Content = Content .. "
    • " .. a_CBPlugin:GetName() .. " (version " .. a_CBPlugin:GetVersion() .. ")
    • " end end ) Content = Content .. "
    " Content = Content .. "

    Players:

      " cRoot:Get():ForEachPlayer( function(a_CBPlayer) Content = Content .. "
    • " .. a_CBPlayer:GetName() .. "
    • " end ) Content = Content .. "
    "; return Content, SubTitle end function ShowPage(WebAdmin, TemplateRequest) SiteContent = {} local BaseURL = cWebAdmin:GetBaseURL(TemplateRequest.Request.Path) local Title = "Cuberite WebAdmin" local NumPlayers = cRoot:Get():GetServer():GetNumPlayers() local MemoryUsageKiB = cRoot:GetPhysicalRAMUsage() local NumChunks = cRoot:Get():GetTotalChunkCount() local PluginPage = cWebAdmin:GetPage(TemplateRequest.Request) local PageContent = PluginPage.Content local SubTitle = PluginPage.PluginFolder if (PluginPage.UrlPath ~= "") then SubTitle = PluginPage.PluginFolder .. " - " .. PluginPage.TabTitle end if (PageContent == "") then PageContent, SubTitle = GetDefaultPage() end Output([[ ]] .. Title .. [[
    Welcome back, ]] .. TemplateRequest.Request.Username .. [[ Log out
    • Players online: ]] .. NumPlayers .. [[
    • Memory: ]] .. string.format("%.2f", MemoryUsageKiB / 1024) .. [[MB
    • Chunks: ]] .. NumChunks .. [[

    Menu

    Server Management

    ]] .. SubTitle .. [[

    ]] .. PageContent .. [[
    ]]) return table.concat(SiteContent) end ================================================ FILE: SetFlags.cmake ================================================ 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_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}") endmacro() macro(enable_profile) # Declare the flags used for profiling builds: if (MSVC) set (CXX_PROFILING "/Zi") set (LNK_PROFILING "/PROFILE /DEBUG") else() set (CXX_PROFILING "-pg") set (LNK_PROFILING "-pg") endif() # Declare the profiling configurations: SET(CMAKE_CXX_FLAGS_DEBUGPROFILE "${CMAKE_CXX_FLAGS_DEBUG} ${CXX_PROFILING}" CACHE STRING "Flags used by the C++ compiler during profile builds." FORCE ) SET(CMAKE_C_FLAGS_DEBUGPROFILE "${CMAKE_C_FLAGS_DEBUG} ${CXX_PROFILING}" CACHE STRING "Flags used by the C compiler during profile builds." FORCE ) SET(CMAKE_EXE_LINKER_FLAGS_DEBUGPROFILE "${CMAKE_EXE_LINKER_FLAGS_DEBUG} ${LNK_PROFILING}" CACHE STRING "Flags used for linking binaries during profile builds." FORCE ) SET(CMAKE_SHARED_LINKER_FLAGS_DEBUGPROFILE "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} ${LNK_PROFILING}" CACHE STRING "Flags used by the shared libraries linker during profile builds." FORCE ) MARK_AS_ADVANCED( CMAKE_CXX_FLAGS_DEBUGPROFILE CMAKE_C_FLAGS_DEBUGPROFILE CMAKE_EXE_LINKER_FLAGS_DEBUGPROFILE CMAKE_SHARED_LINKER_FLAGS_DEBUGPROFILE ) SET(CMAKE_CXX_FLAGS_RELEASEPROFILE "${CMAKE_CXX_FLAGS_RELEASE} ${CXX_PROFILING}" CACHE STRING "Flags used by the C++ compiler during profile builds." FORCE ) SET(CMAKE_C_FLAGS_RELEASEPROFILE "${CMAKE_C_FLAGS_RELEASE} ${CXX_PROFILING}" CACHE STRING "Flags used by the C compiler during profile builds." FORCE ) SET(CMAKE_EXE_LINKER_FLAGS_RELEASEPROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} ${LNK_PROFILING}" CACHE STRING "Flags used for linking binaries during profile builds." FORCE ) SET(CMAKE_SHARED_LINKER_FLAGS_RELEASEPROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} ${LNK_PROFILING}" CACHE STRING "Flags used by the shared libraries linker during profile builds." FORCE ) MARK_AS_ADVANCED( CMAKE_CXX_FLAGS_RELEASEPROFILE CMAKE_C_FLAGS_RELEASEPROFILE 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 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() function(set_global_flags) if(MSVC) # Make build use multiple threads under MSVC: add_compile_options(/MP) # Make build use Unicode: add_compile_definitions(UNICODE _UNICODE) # Turn off CRT warnings: add_compile_definitions(_CRT_SECURE_NO_WARNINGS) return () endif() # Allow for a forced 32-bit build under 64-bit OS: if (FORCE_32) add_compile_options(-m32) add_link_options(-m32) endif() # https://en.wikipedia.org/wiki/Uname # https://gcc.gnu.org/onlinedocs/gcc/index.html # Have the compiler generate code specifically targeted at the current machine on Linux: if(NOT NO_NATIVE_OPTIMIZATION AND NOT CMAKE_CROSSCOMPILING) string(TOLOWER ${CMAKE_SYSTEM_PROCESSOR} SYSTEM_PROCESSOR) if (SYSTEM_PROCESSOR MATCHES "^(i386|i686|x86|amd64|mips)") message(STATUS "Optimising for this machine (march=native)") add_compile_options(-march=native) elseif (SYSTEM_PROCESSOR MATCHES "^(arm|aarch|powerpc|ppc|sparc|alpha)") message(STATUS "Optimising for this machine (mcpu=native)") add_compile_options(-mcpu=native) endif() endif() endfunction() function(set_exe_flags TARGET) if (MSVC) # TODO: Warnings as errors target_compile_options( ${TARGET} PRIVATE # Warnings level 4: /W4 # Excessive amount of logspam (Unreferenced formal parameter), disable for now: /wd4100 ) return () endif() target_compile_options( ${TARGET} PRIVATE # We use a signed char (fixes #640 on RasPi) # TODO: specify this in code, not a compile flag: -fsigned-char # We support non-IEEE 754 FPUs so can make no guarantees about error: -ffast-math # All warnings: -Wall -Wextra # Excessive amount of logspam, disable for now: -Wno-unused-parameter ) if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") target_compile_options( ${TARGET} PRIVATE # TODO: actually fix the warnings instead of disabling them # or at least disable on a file-level basis: -Wno-missing-noreturn -Wno-padded -Wno-implicit-fallthrough -Wno-double-promotion # This is a pretty useless warning, we've already got -Wswitch which is what we need: -Wno-switch-enum # Weverything with Clang exceptions: -Weverything -Wno-exit-time-destructors -Wno-error=disabled-macro-expansion -Wno-weak-vtables -Wno-string-conversion -Wno-c++98-compat-pedantic -Wno-c++2a-compat-pedantic -Wno-documentation -Wno-documentation-unknown-command -Wno-reserved-id-macro -Wno-error=unused-command-line-argument ) # Werror only for debug builds if(CMAKE_BUILD_TYPE STREQUAL "Debug") target_compile_options( ${TARGET} PRIVATE # Warnings-as-errors only on Clang for now: -Werror ) endif() if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 7 AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 13) target_compile_options( ${TARGET} PRIVATE # We aren't using C++11: -Wno-return-std-move-in-c++11 ) endif() if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 10) target_compile_options( ${TARGET} PRIVATE # int to float conversions happen a lot, not worth fixing all warnings: -Wno-implicit-int-float-conversion ) endif() if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 13) target_compile_options( ${TARGET} PRIVATE # TODO: fix -Wno-reserved-identifier ) endif() if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 16) target_compile_options( ${TARGET} PRIVATE -Wno-unsafe-buffer-usage ) endif() endif() endfunction() ================================================ FILE: TESTING.md ================================================ Contributing by Testing Cuberite ================================ You can help us even if you are not a programmer! This document explains how. If you would like to help with coding instead, see [GETTING-STARTED.md][1] and [CONTRIBUTING.md][2]. Here are things you can help with without being a programmer: - Run and test Cuberite. Report issues, bugs, crashes, and stacktraces at the [issue tracker][3]. This is best done in debug mode. - Test unmerged versions (known as branches or Pull Requests) which are marked with the [ingame-testing-needed][4] label. Note that code marked with `ingame-testing-needed` is not always available, and sometimes the above list will be empty. Please use the issue tracker search feature and make sure your issue has not been reported before! Obtaining Debug Builds ---------------------- When testing Cuberite, debug builds are preferred because they output detailed info about the problem that had occurred at the server console. Currently, we do not provide debug builds. You will have to compile Cuberite yourself to obtain them. See the compilation instructions. You can also test with regular builds. Testing Unmerged Pull Requests ------------------------------ To test unmerged branches, pick one from the ingame-testing-needed list, and follow the download instructions. If you are familiar with git, you can also fetch and compile the unmerged branch instead. [1]: https://github.com/cuberite/cuberite/blob/master/GETTING-STARTED.md [2]: https://github.com/cuberite/cuberite/blob/master/CONTRIBUTING.md [3]: https://github.com/cuberite/cuberite/issues [4]: https://github.com/cuberite/cuberite/pulls?q=is%3Aopen+is%3Apr+label%3Astatus%2Fingame-testing-needed ================================================ FILE: Tools/.gitignore ================================================ Debug/ ================================================ FILE: Tools/AnvilStats/.gitignore ================================================ *.vcproj *.vcxproj *.sln *.user .xls Statistics.txt *.bmp Debug/ Release/ Profiling *.png world/ *.html *.xls ================================================ FILE: Tools/AnvilStats/AnvilStats.cpp ================================================ // AnvilStats.cpp // Implements the main app entrypoint #include "Globals.h" #include "Processor.h" #include "Statistics.h" #include "BiomeMap.h" #include "HeightMap.h" #include "HeightBiomeMap.h" #include "ChunkExtract.h" #include "SpringStats.h" int main(int argc, char * argv[]) { if (argc < 2) { LOG("Usage: %s []", argv[0]); LOG("Available methods:"); LOG(" 0 - statistics"); LOG(" 1 - biome map"); LOG(" 2 - height map"); LOG(" 3 - extract chunks"); LOG(" 4 - count lava- and water- springs"); LOG(" 5 - biome and height map"); LOG("\nNo method number present, aborting."); return -1; } AString WorldFolder; if (argc > 2) { WorldFolder = argv[2]; } else { WorldFolder = "." + cFile::PathSeparator; } cCallbackFactory * Factory = NULL; switch (atol(argv[1])) { case 0: Factory = new cStatisticsFactory; break; case 1: Factory = new cBiomeMapFactory; break; case 2: Factory = new cHeightMapFactory; break; case 3: Factory = new cChunkExtractFactory(WorldFolder); break; case 4: Factory = new cSpringStatsFactory; break; case 5: Factory = new cHeightBiomeMapFactory; break; default: { LOG("Unknown method \"%s\", aborting.", argv[1]); return -2; } } cProcessor Processor; Processor.ProcessWorld(WorldFolder, *Factory); LOG("Processing finished"); delete Factory; LOG("Done"); } ================================================ FILE: Tools/AnvilStats/AnvilStats.txt ================================================ // AnvilStats.txt // A Readme for the project /* AnvilStats ========== This is a project for measuring various metrics throughout an Anvil world, presumably created by a vanilla MC. It works by parsing the MCA files in the path specified as its param (or current directory, if no params) and feeding each decompressed chunk into the statistics-gathering callback function. Possible usage: - count the per-chunk density of specific blocks - count the per-chunk density of dungeons, by measuring the number of zombie/skeleton/regularspider spawners - count the per-chunk-per-biome density of trees, by measuring the number of dirt-log vertical transitions, correlating to biome data - draw a vertical map of the world based on a specific measured value (biome, elevation, ...) This project is Windows-only, although it shouldn't be too difficult to make it portable. Because this project uses NBT extensively, it runs much faster in Release mode. */ ================================================ FILE: Tools/AnvilStats/BiomeMap.cpp ================================================ // BiomeMap.cpp // Implements the cBiomeMap class representing a cCallback descendant that draws a map of biomes for the world #include "Globals.h" #include "BiomeMap.h" #include "../BiomeVisualiser/BiomeColors.h" static const unsigned char g_BMPHeader[] = { 0x42, 0x4D, 0x36, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x13, 0x0B, 0x00, 0x00, 0x13, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } ; cBiomeMap::cBiomeMap(void) : m_CurrentRegionX(0), m_CurrentRegionZ(0), m_IsCurrentRegionValid(false) { } void cBiomeMap::Finish(void) { if (m_IsCurrentRegionValid) { StartNewRegion(0, 0); } } bool cBiomeMap::OnNewChunk(int a_ChunkX, int a_ChunkZ) { int RegionX = (a_ChunkX < 0) ? (a_ChunkX - 31) / 32 : a_ChunkX / 32; int RegionZ = (a_ChunkZ < 0) ? (a_ChunkZ - 31) / 32 : a_ChunkZ / 32; if ((RegionX != m_CurrentRegionX) || (RegionZ != m_CurrentRegionZ)) { if (m_IsCurrentRegionValid) { StartNewRegion(RegionX, RegionZ); } m_CurrentRegionX = RegionX; m_CurrentRegionZ = RegionZ; } m_IsCurrentRegionValid = true; m_CurrentChunkX = a_ChunkX; m_CurrentChunkZ = a_ChunkZ; m_CurrentChunkOffX = m_CurrentChunkX - m_CurrentRegionX * 32; m_CurrentChunkOffZ = m_CurrentChunkZ - m_CurrentRegionZ * 32; return false; } bool cBiomeMap::OnBiomes(const unsigned char * a_BiomeData) { ASSERT(m_CurrentChunkOffX >= 0); ASSERT(m_CurrentChunkOffX < 32); ASSERT(m_CurrentChunkOffZ >= 0); ASSERT(m_CurrentChunkOffZ < 32); char * BaseBiomes = m_Biomes + m_CurrentChunkOffZ * 16 * 512 + m_CurrentChunkOffX * 16; for (int z = 0; z < 16; z++) { char * Row = BaseBiomes + z * 512; memcpy(Row, a_BiomeData + z * 16, 16); } // for z return true; } void cBiomeMap::StartNewRegion(int a_RegionX, int a_RegionZ) { AString FileName; Printf(FileName, "Biomes.%d.%d.bmp", m_CurrentRegionX, m_CurrentRegionZ); cFile f; if (!f.Open(FileName, cFile::fmWrite)) { LOG("Cannot open file \"%s\" for writing the biome map. Data for this region lost.", FileName.c_str()); } else { f.Write(g_BMPHeader, sizeof(g_BMPHeader)); for (int z = 0; z < 512; z++) { int RowData[512]; unsigned char * BiomeRow = (unsigned char *)m_Biomes + z * 512; for (int x = 0; x < 512; x++) { RowData[x] = g_BiomeColors[BiomeRow[x]]; } f.Write(RowData, sizeof(RowData)); } // for z } memset(m_Biomes, 0, sizeof(m_Biomes)); m_CurrentRegionX = a_RegionX; m_CurrentRegionZ = a_RegionZ; } //////////////////////////////////////////////////////////////////////////////// // cBiomeMapFactory: cBiomeMapFactory::~cBiomeMapFactory() { // Force all threads to save their last regions: for (cCallbacks::iterator itr = m_Callbacks.begin(), end = m_Callbacks.end(); itr != end; ++itr) { ((cBiomeMap *)(*itr))->Finish(); } // TODO: Join all the files into one giant image file } ================================================ FILE: Tools/AnvilStats/BiomeMap.h ================================================ // BiomeMap.h // Interfaces to the cBiomeMap class representing a cCallback descendant that draws a map of biomes for the world #pragma once #include "Callback.h" class cBiomeMap : public cCallback { public: cBiomeMap(void); /** Saves the last region that it was processing */ void Finish(void); protected: int m_CurrentChunkX; // Absolute chunk coords int m_CurrentChunkZ; int m_CurrentChunkOffX; // Chunk offset from the start of the region int m_CurrentChunkOffZ; int m_CurrentRegionX; int m_CurrentRegionZ; bool m_IsCurrentRegionValid; char m_Biomes[16 * 32 * 16 * 32]; // Biome map of the entire current region [x + 16 * 32 * z] // cCallback overrides: virtual bool OnNewChunk(int a_ChunkX, int a_ChunkZ) override; virtual bool OnHeader(int a_FileOffset, unsigned char a_NumSectors, int a_Timestamp) override { return false; } virtual bool OnCompressedDataSizePos(int a_CompressedDataSize, int a_DataOffset, char a_CompressionMethod) override { return false; } virtual bool OnDecompressedData(const char * a_DecompressedNBT, int a_DataSize) override { return false; } virtual bool OnRealCoords(int a_ChunkX, int a_ChunkZ) override { return false; } virtual bool OnLastUpdate(Int64 a_LastUpdate) override { return false; } virtual bool OnTerrainPopulated(bool a_Populated) override { return false; } // We don't care about "populated", the biomes are the same virtual bool OnBiomes(const unsigned char * a_BiomeData) override; void StartNewRegion(int a_RegionX, int a_RegionZ); } ; class cBiomeMapFactory : public cCallbackFactory { public: virtual ~cBiomeMapFactory(); virtual cCallback * CreateNewCallback(void) override { return new cBiomeMap; } } ; ================================================ FILE: Tools/AnvilStats/CMakeLists.txt ================================================ project (AnvilStats) # Set include paths to the used libraries: include_directories("../../lib") include_directories("../../src") function(flatten_files arg1) set(res "") foreach(f ${${arg1}}) get_filename_component(f ${f} ABSOLUTE) list(APPEND res ${f}) endforeach() set(${arg1} "${res}" PARENT_SCOPE) endfunction() add_subdirectory(../../lib/zlib ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}/lib/zlib) # Include the shared files: set(SHARED_SRC ../../src/ByteBuffer.cpp ../../src/StringUtils.cpp ../../src/LoggerListeners.cpp ../../src/Logger.cpp ../../src/WorldStorage/FastNBT.cpp ../BiomeVisualiser/BiomeColors.cpp ) set(SHARED_HDR ../../src/ByteBuffer.h ../../src/StringUtils.h ../../src/LoggerListeners.h ../../src/Logger.h ../../src/WorldStorage/FastNBT.h ../BiomeVisualiser/BiomeColors.h ) set(SHARED_OSS_SRC ../../src/OSSupport/CriticalSection.cpp ../../src/OSSupport/Event.cpp ../../src/OSSupport/File.cpp ../../src/OSSupport/GZipFile.cpp ../../src/OSSupport/IsThread.cpp ) set(SHARED_OSS_HDR ../../src/OSSupport/CriticalSection.h ../../src/OSSupport/Event.h ../../src/OSSupport/File.h ../../src/OSSupport/GZipFile.h ../../src/OSSupport/IsThread.h ) flatten_files(SHARED_SRC) flatten_files(SHARED_HDR) flatten_files(SHARED_OSS_SRC) flatten_files(SHARED_OSS_HDR) source_group("Shared" FILES ${SHARED_SRC} ${SHARED_HDR}) source_group("Shared\\OSSupport" FILES ${SHARED_OSS_SRC} ${SHARED_OSS_HDR}) # Include the main source files: set(SOURCES AnvilStats.cpp BiomeMap.cpp ChunkExtract.cpp Globals.cpp HeightBiomeMap.cpp HeightMap.cpp ImageComposingCallback.cpp Processor.cpp SpringStats.cpp Statistics.cpp Utils.cpp ) set(HEADERS BiomeMap.h Callback.h ChunkExtract.h Globals.h HeightBiomeMap.h HeightMap.h ImageComposingCallback.h Processor.h SpringStats.h Statistics.h Utils.h AnvilStats.txt ) source_group("" FILES ${SOURCES} ${HEADERS}) add_definitions(-DNBT_RESERVE_SIZE=10000) add_executable(AnvilStats ${SOURCES} ${HEADERS} ${SHARED_SRC} ${SHARED_HDR} ${SHARED_OSS_SRC} ${SHARED_OSS_HDR} ) target_link_libraries(AnvilStats zlib) include(../../SetFlags.cmake) set_exe_flags(AnvilStats) # Under MSVC we need to enlarge the default stack size for the executable: if (MSVC) get_target_property(TEMP AnvilStats LINK_FLAGS) if (TEMP STREQUAL "TEMP-NOTFOUND") SET(TEMP "") # set to empty string message("LINKER_FLAGS not found") else () SET(TEMP "${TEMP} ") # a space to cleanly separate from existing content message("LINKER_FLAGS: ${LINKER_FLAGS}") endif () # append our values SET(TEMP "${TEMP}/STACK:16777216") set_target_properties(AnvilStats PROPERTIES LINK_FLAGS ${TEMP}) endif () ================================================ FILE: Tools/AnvilStats/Callback.h ================================================ // Callback.h // Interfaces to the cCallback base class used as the base class for all statistical callbacks #pragma once // fwd: class cParsedNBT; /** The base class for all chunk-processor callbacks, declares the interface. The processor calls each virtual function in the order they are declared here with the specified args. If the function returns true, the processor doesn't process the data item, moves on to the next chunk and starts calling the callbacks again from start with the new chunk data. So if a statistics collector doesn't need data decompression at all, it can stop the processor from doing so early-enough and still get meaningful data. A callback is guaranteed to run in a single thread and always the same thread for the same chunk. A callback is guaranteed to run on all chunks in a region and one region is guaranteed to be handled by only callback. */ class cCallback abstract { public: enum { CALLBACK_CONTINUE = false, CALLBACK_ABORT = true, } ; virtual ~cCallback() {} // Force a virtual destructor in each descendant /** Called when a new region file is about to be opened; by default allow the region */ virtual bool OnNewRegion(int a_RegionX, int a_RegionZ) { return CALLBACK_CONTINUE; } /** Called to inform the stats module of the chunk coords for newly processing chunk */ virtual bool OnNewChunk(int a_ChunkX, int a_ChunkZ) = 0; /** Called to inform about the chunk's data offset in the file (chunk mini-header), the number of sectors it uses and the timestamp field value */ virtual bool OnHeader(int a_FileOffset, unsigned char a_NumSectors, int a_Timestamp) { return CALLBACK_ABORT; } /** Called to inform of the compressed chunk data size and position in the file (offset from file start to the actual data) */ virtual bool OnCompressedDataSizePos(int a_CompressedDataSize, int a_DataOffset, char a_CompressionMethod) { return CALLBACK_ABORT; } /** Just in case you wanted to process the NBT yourself ;) */ virtual bool OnDecompressedData(const char * a_DecompressedNBT, int a_DataSize) { return CALLBACK_ABORT; } /** The chunk's NBT should specify chunk coords, these are sent here: */ virtual bool OnRealCoords(int a_ChunkX, int a_ChunkZ) { return CALLBACK_ABORT; } /** The chunk contains a LastUpdate value specifying the last tick in which it was saved. */ virtual bool OnLastUpdate(Int64 a_LastUpdate) { return CALLBACK_ABORT; } virtual bool OnTerrainPopulated(bool a_Populated) { return CALLBACK_ABORT; } virtual bool OnBiomes(const unsigned char * a_BiomeData) { return CALLBACK_ABORT; } /** Called when a heightmap for the chunk is read from the file. Note that the heightmap is given in big-endian ints, so if you want it, you need to ntohl() it first! */ virtual bool OnHeightMap(const int * a_HeightMapBE) { return CALLBACK_ABORT; } /** If there is data for the section, this callback is called; otherwise OnEmptySection() is called instead. All OnSection() callbacks are called first, and only then all the remaining sections are reported in OnEmptySection(). */ virtual bool OnSection( unsigned char a_Y, const BLOCKTYPE * a_BlockTypes, const NIBBLETYPE * a_BlockAdditional, const NIBBLETYPE * a_BlockMeta, const NIBBLETYPE * a_BlockLight, const NIBBLETYPE * a_BlockSkyLight ) { return CALLBACK_ABORT; } /** If there is no data for a section, this callback is called; otherwise OnSection() is called instead. OnEmptySection() callbacks are called after all OnSection() callbacks. */ virtual bool OnEmptySection(unsigned char a_Y) { return CALLBACK_CONTINUE; } /** Called after all sections have been processed via either OnSection() or OnEmptySection(). */ virtual bool OnSectionsFinished(void) { return CALLBACK_ABORT; } /** Called for each entity in the chunk. Common parameters are parsed from the NBT. The callback may parse any other param from the a_NBT and a_NBTTag parameters. The a_NBTTag parameter points to the entity compound tag inside the Entities tag. */ virtual bool OnEntity( const AString & a_EntityType, double a_PosX, double a_PosY, double a_PosZ, double a_SpeedX, double a_SpeedY, double a_SpeedZ, float a_Yaw, float a_Pitch, float a_FallDistance, short a_FireTicksLeft, short a_AirTicks, char a_IsOnGround, cParsedNBT & a_NBT, int a_NBTTag ) { return CALLBACK_ABORT; } /** Called for each tile entity in the chunk. Common parameters are parsed from the NBT. The callback may parse any other param from the a_NBT and a_NBTTag parameters. The a_NBTTag parameter points to the tile entity compound tag inside the TileEntities tag. */ virtual bool OnTileEntity( const AString & a_EntityType, int a_PosX, int a_PosY, int a_PosZ, cParsedNBT & a_NBT, int a_NBTTag ) { return CALLBACK_ABORT; } /** Called for each tile tick in the chunk */ virtual bool OnTileTick( int a_BlockType, int a_TicksLeft, int a_PosX, int a_PosY, int a_PosZ ) { return CALLBACK_ABORT; } /** Called after the entire region file has been processed. No more callbacks for this region will be called. No processing by default */ virtual void OnRegionFinished(int a_RegionX, int a_RegionZ) {} } ; typedef std::vector cCallbacks; /** The base class for a factory that creates callback objects for separate threads. The processor creates a callback for each thread on which it runs using this factory. The factory is guaranteed to be called from a single thread. The factory keeps track of all the callbacks that it has created and deletes them when destructed */ class cCallbackFactory { public: virtual ~cCallbackFactory() { for (cCallbacks::iterator itr = m_Callbacks.begin(), end = m_Callbacks.end(); itr != end; ++itr) { delete *itr; } } /** Descendants override this method to return the correct callback type */ virtual cCallback * CreateNewCallback(void) = 0; /** cProcessor uses this method to request a new callback */ cCallback * GetNewCallback(void) { cCallback * Callback = CreateNewCallback(); if (Callback != NULL) { m_Callbacks.push_back(Callback); } return Callback; } protected: cCallbacks m_Callbacks; } ; ================================================ FILE: Tools/AnvilStats/ChunkExtract.cpp ================================================ // ChunkExtract.cpp // Implements the cChunkExtract class representing a cCallback descendant that extracts raw chunk data into separate .chunk files #include "Globals.h" #include "ChunkExtract.h" #include "../../src/OSSupport/GZipFile.h" cChunkExtract::cChunkExtract(const AString & iWorldFolder) : mWorldFolder(iWorldFolder) { } bool cChunkExtract::OnNewChunk(int a_ChunkX, int a_ChunkZ) { int AnvilX = (a_ChunkX - ((a_ChunkX > 0) ? 0 : 31)) / 32; int AnvilZ = (a_ChunkZ - ((a_ChunkZ > 0) ? 0 : 31)) / 32; if ((AnvilX != mCurAnvilX) || (AnvilZ != mCurAnvilZ)) { OpenAnvilFile(AnvilX, AnvilZ); } mCurChunkX = a_ChunkX; mCurChunkZ = a_ChunkZ; return false; } bool cChunkExtract::OnCompressedDataSizePos(int a_CompressedDataSize, int a_DataOffset, char a_CompressionMethod) { if (!mAnvilFile.IsOpen()) { return true; } cFile ChunkFile; AString ChunkPath = Printf("%d.%d.zchunk", mCurChunkX, mCurChunkZ); if (!ChunkFile.Open(ChunkPath, cFile::fmWrite)) { LOG("Cannot open zchunk file \"%s\" for writing. Chunk [%d, %d] skipped.", ChunkPath.c_str(), mCurChunkX, mCurChunkZ); return false; } // Copy data from mAnvilFile to ChunkFile: mAnvilFile.Seek(a_DataOffset); for (int BytesToCopy = a_CompressedDataSize; BytesToCopy > 0;) { char Buffer[64000]; int NumBytes = std::min(BytesToCopy, (int)sizeof(Buffer)); int BytesRead = mAnvilFile.Read(Buffer, NumBytes); if (BytesRead != NumBytes) { LOG("Cannot copy chunk data, chunk [%d, %d] is probably corrupted. Skipping chunk.", mCurChunkX, mCurChunkZ); return false; } ChunkFile.Write(Buffer, BytesRead); BytesToCopy -= BytesRead; } // for BytesToCopy return false; } bool cChunkExtract::OnDecompressedData(const char * a_DecompressedNBT, int a_DataSize) { ASSERT(mAnvilFile.IsOpen()); // If it weren't, the OnCompressedDataSizePos would've prevented this from running AString FileName = Printf("%d.%d.gzchunk", mCurChunkX, mCurChunkZ); cGZipFile GZipChunk; if (!GZipChunk.Open(FileName, cGZipFile::fmWrite)) { LOG("Cannot open gzchunk file \"%s\" for writing. Chunk [%d, %d] skipped.", FileName.c_str(), mCurChunkX, mCurChunkZ); return true; } GZipChunk.Write(a_DecompressedNBT, a_DataSize); return true; } void cChunkExtract::OpenAnvilFile(int a_AnvilX, int a_AnvilZ) { mAnvilFile.Close(); AString FileName = Printf("%s/r.%d.%d.mca", mWorldFolder.c_str(), a_AnvilX, a_AnvilZ); if (!mAnvilFile.Open(FileName, cFile::fmRead)) { LOG("Cannot open Anvil file \"%s\" for reading", FileName.c_str()); } mCurAnvilX = a_AnvilX; mCurAnvilZ = a_AnvilZ; } ================================================ FILE: Tools/AnvilStats/ChunkExtract.h ================================================ // ChunkExtract.h // Declares the cChunkExtract class representing a cCallback descendant that extracts raw chunk data into separate .chunk files #pragma once #include "Callback.h" class cChunkExtract : public cCallback { public: cChunkExtract(const AString & iWorldFolder); protected: AString mWorldFolder; cFile mAnvilFile; int mCurAnvilX; // X-coord of mAnvilFile, in Anvil-coords (1 Anvil-coord = 32 chunks) int mCurAnvilZ; // Z-coord of mAnvilFile, -"- int mCurChunkX; // X-coord of the chunk being processed int mCurChunkZ; // Z-coord of the chunk being processed /** Opens new anvil file into mAnvilFile, sets mCurAnvilX and mCurAnvilZ */ void OpenAnvilFile(int a_AnvilX, int a_AnvilZ); // cCallback overrides: virtual bool OnNewChunk(int a_ChunkX, int a_ChunkZ) override; virtual bool OnHeader(int a_FileOffset, unsigned char a_NumSectors, int a_Timestamp) override { return false; } virtual bool OnCompressedDataSizePos(int a_CompressedDataSize, int a_DataOffset, char a_CompressionMethod) override; virtual bool OnDecompressedData(const char * a_DecompressedNBT, int a_DataSize) override; } ; class cChunkExtractFactory : public cCallbackFactory { public: cChunkExtractFactory(const AString & iWorldFolder) : mWorldFolder(iWorldFolder) { } virtual cCallback * CreateNewCallback(void) override { return new cChunkExtract(mWorldFolder); } protected: AString mWorldFolder; } ; ================================================ FILE: Tools/AnvilStats/Globals.cpp ================================================ // Globals.cpp // This file is used for precompiled header generation in MSVC environments #include "Globals.h" ================================================ FILE: Tools/AnvilStats/Globals.h ================================================ // Globals.h // This file gets included from every module in the project, so that global symbols may be introduced easily // Also used for precompiled header generation in MSVC environments // Compiler-dependent stuff: #if defined(_MSC_VER) // MSVC produces warning C4481 on the override keyword usage, so disable the warning altogether #pragma warning(disable:4481) // Disable some warnings that we don't care about: #pragma warning(disable:4100) #define _CRT_SECURE_NO_WARNINGS #elif defined(__GNUC__) // TODO: Can GCC explicitly mark classes as abstract (no instances can be created)? #define abstract #else #error "You are using an unsupported compiler, you might need to #define some stuff here for your compiler" #endif // Integral types with predefined sizes: typedef long long Int64; typedef int Int32; typedef short Int16; typedef unsigned long long UInt64; typedef unsigned int UInt32; typedef unsigned short UInt16; // A macro to disallow the copy constructor and operator= functions // This should be used in the private: declarations for any class that shouldn't allow copying itself #define DISALLOW_COPY_AND_ASSIGN(TypeName) \ TypeName(const TypeName &); \ void operator=(const TypeName &) // A macro that is used to mark unused function parameters, to avoid pedantic warnings in gcc #define UNUSED(X) (void)(X) // OS-dependent stuff: #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN #include #include // Windows SDK defines min and max macros, messing up with our std::min and std::max usage #undef min #undef max // Windows SDK defines GetFreeSpace as a constant, probably a Win16 API remnant #ifdef GetFreeSpace #undef GetFreeSpace #endif // GetFreeSpace #else #include #include // for mkdir #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #endif // CRT stuff: #include #include #include #include #include // STL stuff: #include #include #include #include #include #include #include #include // Common headers (part 1, without macros): #include "../../src/StringUtils.h" #include "../../src/OSSupport/CriticalSection.h" #include "../../src/OSSupport/Semaphore.h" #include "../../src/OSSupport/Event.h" #include "../../src/OSSupport/IsThread.h" #include "../../src/OSSupport/File.h" // Common definitions: #define LOG(x, ...) printf(x "\n", __VA_ARGS__) #define LOGERROR LOG #define LOGWARNING LOG #define LOGINFO LOG #define LOGWARN LOG /** Evaluates to the number of elements in an array (compile-time!) */ #define ARRAYCOUNT(X) (sizeof(X) / sizeof(*(X))) /** Allows arithmetic expressions like "32 KiB" (but consider using parenthesis around it, "(32 KiB)") */ #define KiB * 1024 /** Allows arithmetic expressions like "32 MiB" (but consider using parenthesis around it, "(32 MiB)") */ #define MiB * 1024 * 1024 /** Faster than (int)floorf((float)x / (float)div) */ #define FAST_FLOOR_DIV(x, div) ((x) < 0 ? (((int)x / div) - 1) : ((int)x / div)) #define TOLUA_TEMPLATE_BIND(...) // 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)) #else #define ASSERT(x) ((void)0) #endif // Pretty much the same as ASSERT() but stays in Release builds #define VERIFY(x) (!!(x) || (LOGERROR("Verification failed: %s, file %s, line %i", #x, __FILE__, __LINE__), exit(1), 0)) typedef unsigned char Byte; /** Clamp value to the specified range. */ template T Clamp(T a_Value, T a_Min, T a_Max) { return (a_Value < a_Min) ? a_Min : ((a_Value > a_Max) ? a_Max : a_Value); } // Common headers (part 2, with macros): #include "../../src/ChunkDef.h" #include "../../src/BlockID.h" ================================================ FILE: Tools/AnvilStats/HeightBiomeMap.cpp ================================================ // HeightBiomeMap.cpp // Declares the cHeightBiomeMap class representing a stats module that produces an image of heights and biomes combined #include "Globals.h" #include "HeightBiomeMap.h" #include "HeightMap.h" cHeightBiomeMap::cHeightBiomeMap(void) : super("HeBi"), m_MinRegionX(100000), m_MaxRegionX(-100000), m_MinRegionZ(100000), m_MaxRegionZ(-100000) { } bool cHeightBiomeMap::OnNewRegion(int a_RegionX, int a_RegionZ) { if (a_RegionX < m_MinRegionX) { m_MinRegionX = a_RegionX; } if (a_RegionX > m_MaxRegionX) { m_MaxRegionX = a_RegionX; } if (a_RegionZ < m_MinRegionZ) { m_MinRegionZ = a_RegionZ; } if (a_RegionZ > m_MaxRegionZ) { m_MaxRegionZ = a_RegionZ; } return super::OnNewRegion(a_RegionX, a_RegionZ); } bool cHeightBiomeMap::OnNewChunk(int a_ChunkX, int a_ChunkZ) { m_CurrentChunkX = a_ChunkX; m_CurrentChunkZ = a_ChunkZ; m_CurrentChunkRelX = m_CurrentChunkX - m_CurrentRegionX * 32; m_CurrentChunkRelZ = m_CurrentChunkZ - m_CurrentRegionZ * 32; ASSERT((m_CurrentChunkRelX >= 0) && (m_CurrentChunkRelX < 32)); ASSERT((m_CurrentChunkRelZ >= 0) && (m_CurrentChunkRelZ < 32)); memset(m_BlockTypes, 0, sizeof(m_BlockTypes)); return CALLBACK_CONTINUE; } bool cHeightBiomeMap::OnBiomes(const unsigned char * a_BiomeData) { memcpy(m_ChunkBiomes, a_BiomeData, sizeof(m_ChunkBiomes)); return CALLBACK_CONTINUE; } bool cHeightBiomeMap::OnHeightMap(const int * a_HeightMapBE) { for (int i = 0; i < ARRAYCOUNT(m_ChunkHeight); i++) { m_ChunkHeight[i] = ntohl(a_HeightMapBE[i]); } // for i - m_ChunkHeight return CALLBACK_CONTINUE; } bool cHeightBiomeMap::OnSection( unsigned char a_Y, const BLOCKTYPE * a_BlockTypes, const NIBBLETYPE * a_BlockAdditional, const NIBBLETYPE * a_BlockMeta, const NIBBLETYPE * a_BlockLight, const NIBBLETYPE * a_BlockSkyLight ) { // Copy the section data into the appropriate place in the internal buffer memcpy(m_BlockTypes + a_Y * 16 * 16 * 16, a_BlockTypes, 16 * 16 * 16); return CALLBACK_CONTINUE; } bool cHeightBiomeMap::OnSectionsFinished(void) { static const int BiomePalette[] = { // ARGB: 0xff0000ff, /* Ocean */ 0xff00cf3f, /* Plains */ 0xffffff00, /* Desert */ 0xff7f7f7f, /* Extreme Hills */ 0xff00cf00, /* Forest */ 0xff007f3f, /* Taiga */ 0xff3f7f00, /* Swampland */ 0xff003fff, /* River */ 0xff7f0000, /* Hell */ 0xff007fff, /* Sky */ 0xff3f3fff, /* Frozen Ocean */ 0xff3f3fff, /* Frozen River */ 0xff7fffcf, /* Ice Plains */ 0xff3fcf7f, /* Ice Mountains */ 0xffcf00cf, /* Mushroom Island */ 0xff7f00ff, /* Mushroom Island Shore */ 0xffffff3f, /* Beach */ 0xffcfcf00, /* Desert Hills */ 0xff00cf3f, /* Forest Hills */ 0xff006f1f, /* Taiga Hills */ 0xff7f8f7f, /* Extreme Hills Edge */ 0xff004f00, /* Jungle */ 0xff003f00, /* Jungle Hills */ } ; // Remove trees and other unwanted stuff from the heightmap: for (int z = 0; z < 16; z++) { int PixelLine[16]; // line of 16 pixels that is used as a buffer for setting the image pixels for (int x = 0; x < 16; x++) { int Height = m_ChunkHeight[16 * z + x]; for (int y = Height; y >= 0; y--) { if (cHeightMap::IsGround(m_BlockTypes[256 * y + 16 * z + x])) { Height = y; break; // for y } } // for y // Set the color based on the biome and height: char Biome = m_ChunkBiomes[16 * z + x]; PixelLine[x] = ShadeColor(BiomePalette[Biome], Height); } // for x // Set the pixelline into the image: SetPixelURow(m_CurrentChunkRelX * 16, m_CurrentChunkRelZ * 16 + z, 16, PixelLine); } // for z return CALLBACK_ABORT; } //////////////////////////////////////////////////////////////////////////////// // cHeightBiomeMapFactory: cHeightBiomeMapFactory::~cHeightBiomeMapFactory() { // Get the min and max region coords: int MinRegionX = 100000; int MaxRegionX = -100000; int MinRegionZ = 100000; int MaxRegionZ = -100000; for (cCallbacks::iterator itr = m_Callbacks.begin(), end = m_Callbacks.end(); itr != end; ++itr) { cHeightBiomeMap * cb = (cHeightBiomeMap *)(*itr); if (cb->m_MinRegionX < MinRegionX) { MinRegionX = cb->m_MinRegionX; } if (cb->m_MaxRegionX > MaxRegionX) { MaxRegionX = cb->m_MaxRegionX; } if (cb->m_MinRegionZ < MinRegionZ) { MinRegionZ = cb->m_MinRegionZ; } if (cb->m_MaxRegionZ > MaxRegionZ) { MaxRegionZ = cb->m_MaxRegionZ; } } // If the size is small enough, write an HTML file referencing all the images in a table: if ((MaxRegionX >= MinRegionX) && (MaxRegionZ >= MinRegionZ) && (MaxRegionX - MinRegionX < 100) && (MaxRegionZ - MinRegionZ < 100)) { cFile HTML("HeBi.html", cFile::fmWrite); if (HTML.IsOpen()) { HTML.Printf("\n"); for (int z = MinRegionZ; z <= MaxRegionZ; z++) { HTML.Printf(""); for (int x = MinRegionX; x <= MaxRegionX; x++) { HTML.Printf("", x, z); } HTML.Printf("\n"); } HTML.Printf("
    "); } } } ================================================ FILE: Tools/AnvilStats/HeightBiomeMap.h ================================================ // HeightBiomeMap.h // Declares the cHeightBiomeMap class representing a stats module that produces an image of heights and biomes combined #pragma once #include "ImageComposingCallback.h" class cHeightBiomeMap : public cImageComposingCallback { typedef cImageComposingCallback super; public: // Minima and maxima for the regions processed through this callback int m_MinRegionX, m_MaxRegionX; int m_MinRegionZ, m_MaxRegionZ; cHeightBiomeMap(void); protected: int m_CurrentChunkX; // Absolute chunk coords int m_CurrentChunkZ; int m_CurrentChunkRelX; // Chunk offset from the start of the region int m_CurrentChunkRelZ; /** Biome-map for the current chunk */ char m_ChunkBiomes[16 * 16]; /** Height-map for the current chunk */ int m_ChunkHeight[16 * 16]; /** Block data for the current chunk (between OnSection() and OnSectionsFinished()) */ BLOCKTYPE m_BlockTypes [16 * 16 * 256]; // cCallback overrides: virtual bool OnNewRegion(int a_RegionX, int a_RegionZ) override; virtual bool OnNewChunk(int a_ChunkX, int a_ChunkZ) override; virtual bool OnHeader(int a_FileOffset, unsigned char a_NumSectors, int a_Timestamp) override { return CALLBACK_CONTINUE; } virtual bool OnCompressedDataSizePos(int a_CompressedDataSize, int a_DataOffset, char a_CompressionMethod) override { return CALLBACK_CONTINUE; } virtual bool OnDecompressedData(const char * a_DecompressedNBT, int a_DataSize) override { return CALLBACK_CONTINUE; } virtual bool OnRealCoords(int a_ChunkX, int a_ChunkZ) override { return CALLBACK_CONTINUE; } virtual bool OnLastUpdate(Int64 a_LastUpdate) override { return CALLBACK_CONTINUE; } virtual bool OnTerrainPopulated(bool a_Populated) override { return a_Populated ? CALLBACK_CONTINUE : CALLBACK_ABORT; } // If not populated, we don't want it! virtual bool OnBiomes(const unsigned char * a_BiomeData) override; virtual bool OnHeightMap(const int * a_HeightMapBE) override; virtual bool OnSection( unsigned char a_Y, const BLOCKTYPE * a_BlockTypes, const NIBBLETYPE * a_BlockAdditional, const NIBBLETYPE * a_BlockMeta, const NIBBLETYPE * a_BlockLight, const NIBBLETYPE * a_BlockSkyLight ) override; virtual bool OnSectionsFinished(void) override; } ; class cHeightBiomeMapFactory : public cCallbackFactory { public: virtual ~cHeightBiomeMapFactory(); virtual cCallback * CreateNewCallback(void) override { return new cHeightBiomeMap; } } ; ================================================ FILE: Tools/AnvilStats/HeightMap.cpp ================================================ // HeightMap.cpp // Implements the cHeightMap class representing a cCallback descendant that draws a B & W map of heights for the world #include "Globals.h" #include "HeightMap.h" static const unsigned char g_BMPHeader[] = { 0x42, 0x4D, 0x36, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x13, 0x0B, 0x00, 0x00, 0x13, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } ; cHeightMap::cHeightMap(void) : m_CurrentRegionX(0), m_CurrentRegionZ(0), m_IsCurrentRegionValid(false) { } void cHeightMap::Finish(void) { if (m_IsCurrentRegionValid) { StartNewRegion(0, 0); } } bool cHeightMap::OnNewChunk(int a_ChunkX, int a_ChunkZ) { int RegionX = (a_ChunkX < 0) ? (a_ChunkX - 31) / 32 : a_ChunkX / 32; int RegionZ = (a_ChunkZ < 0) ? (a_ChunkZ - 31) / 32 : a_ChunkZ / 32; if ((RegionX != m_CurrentRegionX) || (RegionZ != m_CurrentRegionZ)) { if (m_IsCurrentRegionValid) { StartNewRegion(RegionX, RegionZ); } m_CurrentRegionX = RegionX; m_CurrentRegionZ = RegionZ; } m_IsCurrentRegionValid = true; m_CurrentChunkX = a_ChunkX; m_CurrentChunkZ = a_ChunkZ; m_CurrentChunkOffX = m_CurrentChunkX - m_CurrentRegionX * 32; m_CurrentChunkOffZ = m_CurrentChunkZ - m_CurrentRegionZ * 32; memset(m_BlockTypes, 0, sizeof(m_BlockTypes)); return false; } bool cHeightMap::OnHeightMap(const int * a_HeightMapBE) { ASSERT(m_CurrentChunkOffX >= 0); ASSERT(m_CurrentChunkOffX < 32); ASSERT(m_CurrentChunkOffZ >= 0); ASSERT(m_CurrentChunkOffZ < 32); int * BaseHeight = m_Height + m_CurrentChunkOffZ * 16 * 512 + m_CurrentChunkOffX * 16; for (int z = 0; z < 16; z++) { int * Row = BaseHeight + z * 512; for (int x = 0; x < 16; x++) { Row[x] = ntohl(a_HeightMapBE[z * 16 + x]); } } // for z return false; // Still want blockdata to remove trees from the heightmap } bool cHeightMap::OnSection( unsigned char a_Y, const BLOCKTYPE * a_BlockTypes, const NIBBLETYPE * a_BlockAdditional, const NIBBLETYPE * a_BlockMeta, const NIBBLETYPE * a_BlockLight, const NIBBLETYPE * a_BlockSkyLight ) { // Copy the section data into the appropriate place in the internal buffer memcpy(m_BlockTypes + a_Y * 16 * 16 * 16, a_BlockTypes, 16 * 16 * 16); return false; } bool cHeightMap::OnSectionsFinished(void) { // Remove trees from the heightmap: for (int z = 0; z < 16; z++) { for (int x = 0; x < 16; x++) { for (int y = m_Height[512 * (16 * m_CurrentChunkOffZ + z) + 16 * m_CurrentChunkOffX + x]; y >= 0; y--) { if (IsGround(m_BlockTypes[256 * y + 16 * z + x])) { m_Height[512 * (16 * m_CurrentChunkOffZ + z) + 16 * m_CurrentChunkOffX + x] = y; break; // for y } } // for y } // for x } // for z return true; } void cHeightMap::StartNewRegion(int a_RegionX, int a_RegionZ) { AString FileName; Printf(FileName, "Height.%d.%d.bmp", m_CurrentRegionX, m_CurrentRegionZ); cFile f; if (!f.Open(FileName, cFile::fmWrite)) { LOG("Cannot open file \"%s\" for writing the height map. Data for this region lost.", FileName.c_str()); } else { f.Write(g_BMPHeader, sizeof(g_BMPHeader)); for (int z = 0; z < 512; z++) { int RowData[512]; int * HeightRow = m_Height + z * 512; for (int x = 0; x < 512; x++) { RowData[x] = std::max(std::min(HeightRow[x], 255), 0) * 0x010101; } f.Write(RowData, sizeof(RowData)); } // for z } memset(m_Height, 0, sizeof(m_Height)); m_CurrentRegionX = a_RegionX; m_CurrentRegionZ = a_RegionZ; } bool cHeightMap::IsGround(BLOCKTYPE a_BlockType) { // Name all blocks that are NOT ground, return false for them: switch (a_BlockType) { case E_BLOCK_AIR: case E_BLOCK_BED: case E_BLOCK_BEETROOTS: case E_BLOCK_BREWING_STAND: case E_BLOCK_BROWN_MUSHROOM: case E_BLOCK_CACTUS: case E_BLOCK_CAKE: case E_BLOCK_CARROTS: case E_BLOCK_CAULDRON: case E_BLOCK_CHEST: case E_BLOCK_CHORUS_FLOWER: case E_BLOCK_CHORUS_PLANT: case E_BLOCK_COBBLESTONE_WALL: case E_BLOCK_COBWEB: case E_BLOCK_COCOA_POD: case E_BLOCK_CROPS: case E_BLOCK_DEAD_BUSH: case E_BLOCK_DETECTOR_RAIL: case E_BLOCK_DIRT: case E_BLOCK_DRAGON_EGG: case E_BLOCK_END_GATEWAY: case E_BLOCK_END_PORTAL: case E_BLOCK_END_ROD: case E_BLOCK_ENDER_CHEST: case E_BLOCK_FENCE: case E_BLOCK_FENCE_GATE: case E_BLOCK_FIRE: case E_BLOCK_FLOWER_POT: case E_BLOCK_HEAD: case E_BLOCK_IRON_BARS: case E_BLOCK_LADDER: case E_BLOCK_LAVA: case E_BLOCK_LEAVES: case E_BLOCK_LEVER: case E_BLOCK_LILY_PAD: case E_BLOCK_LOG: // NOTE: This block is actually solid, but we don't want it because it's the thing that trees are made of, and we're getting rid of trees case E_BLOCK_MELON: case E_BLOCK_MELON_STEM: case E_BLOCK_NETHER_BRICK_FENCE: case E_BLOCK_NETHER_PORTAL: case E_BLOCK_POWERED_RAIL: case E_BLOCK_PUMPKIN: case E_BLOCK_PUMPKIN_STEM: case E_BLOCK_RAIL: case E_BLOCK_RED_ROSE: case E_BLOCK_RED_MUSHROOM: case E_BLOCK_REDSTONE_REPEATER_OFF: case E_BLOCK_REDSTONE_REPEATER_ON: case E_BLOCK_REDSTONE_TORCH_OFF: case E_BLOCK_REDSTONE_TORCH_ON: case E_BLOCK_REDSTONE_WIRE: case E_BLOCK_REEDS: case E_BLOCK_SAPLING: case E_BLOCK_SIGN_POST: case E_BLOCK_SNOW: case E_BLOCK_STATIONARY_LAVA: case E_BLOCK_STATIONARY_WATER: case E_BLOCK_STONE_BUTTON: case E_BLOCK_STONE_PRESSURE_PLATE: case E_BLOCK_STRUCTURE_VOID: case E_BLOCK_TALL_GRASS: case E_BLOCK_TORCH: case E_BLOCK_TRIPWIRE: case E_BLOCK_TRIPWIRE_HOOK: case E_BLOCK_VINES: case E_BLOCK_WALLSIGN: case E_BLOCK_WATER: case E_BLOCK_WOODEN_BUTTON: case E_BLOCK_WOODEN_PRESSURE_PLATE: case E_BLOCK_YELLOW_FLOWER: { return false; } } return true; } //////////////////////////////////////////////////////////////////////////////// // cHeightMapFactory: cHeightMapFactory::~cHeightMapFactory() { // Force all threads to save their last regions: for (cCallbacks::iterator itr = m_Callbacks.begin(), end = m_Callbacks.end(); itr != end; ++itr) { ((cHeightMap *)(*itr))->Finish(); } // TODO: Join all the files into one giant image file } ================================================ FILE: Tools/AnvilStats/HeightMap.h ================================================ // HeightMap.h // Declares the cHeightMap class representing a cCallback descendant that draws a B & W map of heights for the world #pragma once #include "Callback.h" class cHeightMap : public cCallback { public: cHeightMap(void); void Finish(void); static bool IsGround(BLOCKTYPE a_BlockType); protected: int m_CurrentChunkX; // Absolute chunk coords int m_CurrentChunkZ; int m_CurrentChunkOffX; // Chunk offset from the start of the region int m_CurrentChunkOffZ; int m_CurrentRegionX; int m_CurrentRegionZ; bool m_IsCurrentRegionValid; /** Height-map of the entire current region [x + 16 * 32 * z] */ int m_Height[16 * 32 * 16 * 32]; /** Block data of the currently processed chunk (between OnSection() and OnSectionsFinished()) */ BLOCKTYPE m_BlockTypes[16 * 16 * 256]; // cCallback overrides: virtual bool OnNewChunk(int a_ChunkX, int a_ChunkZ) override; virtual bool OnHeader(int a_FileOffset, unsigned char a_NumSectors, int a_Timestamp) override { return false; } virtual bool OnCompressedDataSizePos(int a_CompressedDataSize, int a_DataOffset, char a_CompressionMethod) override { return false; } virtual bool OnDecompressedData(const char * a_DecompressedNBT, int a_DataSize) override { return false; } virtual bool OnRealCoords(int a_ChunkX, int a_ChunkZ) override { return false; } virtual bool OnLastUpdate(Int64 a_LastUpdate) override { return false; } virtual bool OnTerrainPopulated(bool a_Populated) override { return !a_Populated; } // If not populated, we don't want it! virtual bool OnBiomes(const unsigned char * a_BiomeData) { return false; } virtual bool OnHeightMap(const int * a_HeightMapBE) override; virtual bool OnSection( unsigned char a_Y, const BLOCKTYPE * a_BlockTypes, const NIBBLETYPE * a_BlockAdditional, const NIBBLETYPE * a_BlockMeta, const NIBBLETYPE * a_BlockLight, const NIBBLETYPE * a_BlockSkyLight ) override; virtual bool OnSectionsFinished(void) override; void StartNewRegion(int a_RegionX, int a_RegionZ); } ; class cHeightMapFactory : public cCallbackFactory { public: virtual ~cHeightMapFactory(); virtual cCallback * CreateNewCallback(void) override { return new cHeightMap; } } ; ================================================ FILE: Tools/AnvilStats/ImageComposingCallback.cpp ================================================ // ImageComposingCallback.cpp // Implements the cImageComposingCallback class that implements a subset of cCallback for composing per-region images #include "Globals.h" #include "ImageComposingCallback.h" cImageComposingCallback::cImageComposingCallback(const AString & a_FileNamePrefix) : m_FileNamePrefix(a_FileNamePrefix), m_CurrentRegionX(INVALID_REGION_COORD), m_CurrentRegionZ(INVALID_REGION_COORD), m_ImageData(new int[32 * 16 * 32 * 16]) { } cImageComposingCallback::~cImageComposingCallback() { delete[] m_ImageData; } bool cImageComposingCallback::OnNewRegion(int a_RegionX, int a_RegionZ) { ASSERT(m_CurrentRegionX == INVALID_REGION_COORD); ASSERT(m_CurrentRegionZ == INVALID_REGION_COORD); // Has any previous region been finished properly? m_CurrentRegionX = a_RegionX; m_CurrentRegionZ = a_RegionZ; OnEraseImage(); return CALLBACK_CONTINUE; } void cImageComposingCallback::OnRegionFinished(int a_RegionX, int a_RegionZ) { ASSERT(m_CurrentRegionX != INVALID_REGION_COORD); ASSERT(m_CurrentRegionZ != INVALID_REGION_COORD); // Has a region been started properly? ASSERT(m_CurrentRegionX == a_RegionX); ASSERT(m_CurrentRegionZ == a_RegionZ); // Is it the same region that has been started? AString FileName = GetFileName(a_RegionX, a_RegionZ); if (!FileName.empty()) { OnBeforeImageSaved(a_RegionX, a_RegionZ, FileName); SaveImage(FileName); OnAfterImageSaved(a_RegionX, a_RegionZ, FileName); } m_CurrentRegionX = INVALID_REGION_COORD; m_CurrentRegionZ = INVALID_REGION_COORD; } AString cImageComposingCallback::GetFileName(int a_RegionX, int a_RegionZ) { return Printf("%s.%d.%d.bmp", m_FileNamePrefix.c_str(), a_RegionX, a_RegionZ); } void cImageComposingCallback::OnEraseImage(void) { // By default erase the image to black: EraseImage(0); } void cImageComposingCallback::EraseImage(int a_Color) { for (int i = 0; i < PIXEL_COUNT; i++) { m_ImageData[i] = a_Color; } } void cImageComposingCallback::EraseChunk(int a_Color, int a_RelChunkX, int a_RelChunkZ) { int Base = a_RelChunkZ * IMAGE_HEIGHT + a_RelChunkX * 16; for (int v = 0; v < 16; v++) { int BaseV = Base + v * IMAGE_HEIGHT; for (int u = 0; u < 16; u++) { m_ImageData[BaseV + u] = a_Color; } } // for y } void cImageComposingCallback::SetPixel(int a_RelU, int a_RelV, int a_Color) { ASSERT((a_RelU >= 0) && (a_RelU < IMAGE_WIDTH)); ASSERT((a_RelV >= 0) && (a_RelV < IMAGE_HEIGHT)); m_ImageData[a_RelU + IMAGE_WIDTH * a_RelV] = a_Color; } int cImageComposingCallback::GetPixel(int a_RelU, int a_RelV) { if ((a_RelU < 0) || (a_RelU >= IMAGE_WIDTH) || (a_RelV < 0) || (a_RelV >= IMAGE_HEIGHT)) { // Outside the image data return -1; } return m_ImageData[a_RelU + IMAGE_WIDTH * a_RelV]; } void cImageComposingCallback::SetPixelURow(int a_RelUStart, int a_RelV, int a_CountU, int * a_Pixels) { ASSERT((a_RelUStart >= 0) && (a_RelUStart + a_CountU <= IMAGE_WIDTH)); ASSERT((a_RelV >= 0) && (a_RelV < IMAGE_HEIGHT)); ASSERT(a_Pixels != NULL); int Base = a_RelUStart + a_RelV * IMAGE_WIDTH; for (int u = 0; u < a_CountU; u++) { m_ImageData[Base + u] = a_Pixels[u]; } } int cImageComposingCallback::ShadeColor(int a_Color, int a_Shade) { if (a_Shade < 64) { return MixColor(0, a_Color, a_Shade * 4); } return MixColor(a_Color, 0xffffff, (a_Shade - 64) * 4); } int cImageComposingCallback::MixColor(int a_Src, int a_Dest, int a_Amount) { int r = a_Src & 0xff; int g = (a_Src >> 8) & 0xff; int b = (a_Src >> 16) & 0xff; int rd = a_Dest & 0xff; int gd = (a_Dest >> 8) & 0xff; int bd = (a_Dest >> 16) & 0xff; int nr = r + (rd - r) * a_Amount / 256; int ng = g + (gd - g) * a_Amount / 256; int nb = b + (bd - b) * a_Amount / 256; return nr | (ng << 8) | (nb << 16); } void cImageComposingCallback::SaveImage(const AString & a_FileName) { cFile f(a_FileName, cFile::fmWrite); if (!f.IsOpen()) { return; } // Header for BMP files (is the same for the same-size files) static const unsigned char BMPHeader[] = { 0x42, 0x4D, 0x36, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x13, 0x0B, 0x00, 0x00, 0x13, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } ; f.Write(BMPHeader, sizeof(BMPHeader)); f.Write(m_ImageData, PIXEL_COUNT * 4); } ================================================ FILE: Tools/AnvilStats/ImageComposingCallback.h ================================================ // ImageComposingCallback // Declares the cImageComposingCallback class that implements a subset of cCallback for composing per-region images #pragma once #include "Callback.h" /** Implements the plumbing for composing per-region images from multiple chunks. To use this class, create a descendant that writes the image data using SetPixel() or SetPixelURow() functions. For the purpose of this class the image data is indexed U (horz) * V (vert), to avoid confusion with other coords. The image is a 32bpp raw imagedata, written into a BMP file. */ class cImageComposingCallback : public cCallback { public: enum { INVALID_REGION_COORD = 99999, ///< Used for un-assigned region coords IMAGE_WIDTH = 32 * 16, IMAGE_HEIGHT = 32 * 16, PIXEL_COUNT = IMAGE_WIDTH * IMAGE_HEIGHT, ///< Total pixel count of the image data } ; cImageComposingCallback(const AString & a_FileNamePrefix); virtual ~cImageComposingCallback(); // cCallback overrides: virtual bool OnNewRegion(int a_RegionX, int a_RegionZ) override; virtual void OnRegionFinished(int a_RegionX, int a_RegionZ) override; // New introduced overridable functions: /** Called when a file is about to be saved, to generate the filename */ virtual AString GetFileName(int a_RegionX, int a_RegionZ); /** Called before the file is saved */ virtual void OnBeforeImageSaved(int a_RegionX, int a_RegionZ, const AString & a_FileName) {} /** Called after the image is saved to a file */ virtual void OnAfterImageSaved(int a_RegionX, int a_RegionZ, const AString & a_FileName) {} /** Called when a new region is beginning, to erase the image data */ virtual void OnEraseImage(void); // Functions for manipulating the image: /** Erases the entire image with the specified color */ void EraseImage(int a_Color); /** Erases the specified chunk's portion of the image with the specified color. Note that chunk coords are relative to the current region */ void EraseChunk(int a_Color, int a_RelChunkX, int a_RelChunkZ); /** Returns the current region X coord */ int GetCurrentRegionX(void) const { return m_CurrentRegionX; } /** Returns the current region Z coord */ int GetCurrentRegionZ(void) const { return m_CurrentRegionZ; } /** Sets the pixel at the specified UV coords to the specified color */ void SetPixel(int a_RelU, int a_RelV, int a_Color); /** Returns the color of the pixel at the specified UV coords; -1 if outside */ int GetPixel(int a_RelU, int a_RelV); /** Sets a row of pixels. a_Pixels is expected to be a_CountU pixels wide. a_RelUStart + a_CountU is assumed less than image width */ void SetPixelURow(int a_RelUStart, int a_RelV, int a_CountU, int * a_Pixels); /** "Shades" the given color based on the shade amount given Shade amount 0 .. 63 shades the color from black to a_Color. Shade amount 64 .. 127 shades the color from a_Color to white. All other shade amounts have undefined results. */ static int ShadeColor(int a_Color, int a_Shade); /** Mixes the two colors in the specified ratio; a_Ratio is between 0 and 256, 0 returning a_Src */ static int MixColor(int a_Src, int a_Dest, int a_Ratio); protected: /** Prefix for the filenames, when generated by the default GetFileName() function */ AString m_FileNamePrefix; /** Coords of the currently processed region */ int m_CurrentRegionX, m_CurrentRegionZ; /** Raw image data; 1 MiB worth of data, therefore unsuitable for stack allocation. [u + IMAGE_WIDTH * v] */ int * m_ImageData; void SaveImage(const AString & a_FileName); } ; ================================================ FILE: Tools/AnvilStats/Processor.cpp ================================================ // Processor.cpp // Implements the cProcessor class representing the overall processor engine that manages threads, calls callbacks etc. #include "Globals.h" #include "Processor.h" #include "Callback.h" #include "../../src/WorldStorage/FastNBT.h" #include "zlib/zlib.h" #include "Utils.h" const int CHUNK_INFLATE_MAX = 1 MiB; //////////////////////////////////////////////////////////////////////////////// // cProcessor::cThread: cProcessor::cThread::cThread(cCallback & a_Callback, cProcessor & a_ParentProcessor) : super("cProcessor::cThread"), m_Callback(a_Callback), m_ParentProcessor(a_ParentProcessor) { LOG("Created a new thread: %p", this); super::Start(); } void cProcessor::cThread::WaitForStart(void) { m_HasStarted.Wait(); } void cProcessor::cThread::Execute(void) { LOG("Started a new thread: %p, ID %d", this, cIsThread::GetCurrentID()); m_HasStarted.Set(); for (;;) { AString FileName = m_ParentProcessor.GetOneFileName(); if (FileName.empty()) { // All done, terminate the thread break; } ProcessFile(FileName); } // for-ever LOG("Thread %p (ID %d) terminated", this, cIsThread::GetCurrentID()); } void cProcessor::cThread::ProcessFile(const AString & a_FileName) { LOG("Processing file \"%s\"", a_FileName.c_str()); size_t idx = a_FileName.rfind("r."); if (idx == AString::npos) { LOG("Cannot parse filename \"%s\", skipping file.", a_FileName.c_str()); return; } int RegionX = 0, RegionZ = 0; if (sscanf_s(a_FileName.c_str() + idx, "r.%d.%d.mca", &RegionX, &RegionZ) != 2) { LOG("Cannot parse filename \"%s\" into coords, skipping file.", a_FileName.c_str()); return; } if (m_Callback.OnNewRegion(RegionX, RegionZ)) { // Callback doesn't want the region file processed return; } cFile f; if (!f.Open(a_FileName, cFile::fmRead)) { LOG("Cannot open file \"%s\", skipping file.", a_FileName.c_str()); return; } AString FileContents; f.ReadRestOfFile(FileContents); if (FileContents.size() < sizeof(8 KiB)) { LOG("Cannot read header in file \"%s\", skipping file.", a_FileName.c_str()); return; } ProcessFileData(FileContents.data(), FileContents.size(), RegionX * 32, RegionZ * 32); m_Callback.OnRegionFinished(RegionX, RegionZ); } void cProcessor::cThread::ProcessFileData(const char * a_FileData, size_t a_Size, int a_ChunkBaseX, int a_ChunkBaseZ) { int Header[2048]; int * HeaderPtr = (int *)a_FileData; for (int i = 0; i < ARRAYCOUNT(Header); i++) { Header[i] = ntohl(HeaderPtr[i]); } for (int i = 0; i < 1024; i++) { unsigned Location = Header[i]; unsigned Timestamp = Header[i + 1024]; if ( ((Location == 0) && (Timestamp == 0)) || // Official docs' "not present" (Location >> 8 < 2) || // Logical - no chunk can start inside the header ((Location & 0xff) == 0) || // Logical - no chunk can be zero bytes ((Location >> 8) * 4096 > a_Size) // Logical - no chunk can start at beyond the file end ) { // Chunk not present in the file continue; } int ChunkX = a_ChunkBaseX + (i % 32); int ChunkZ = a_ChunkBaseZ + (i / 32); if (m_Callback.OnNewChunk(ChunkX, ChunkZ)) { continue; } ProcessChunk(a_FileData, ChunkX, ChunkZ, Location >> 8, Location & 0xff, Timestamp); } // for i - chunk index } void cProcessor::cThread::ProcessChunk(const char * a_FileData, int a_ChunkX, int a_ChunkZ, unsigned a_SectorStart, unsigned a_SectorSize, unsigned a_TimeStamp) { if (m_Callback.OnHeader(a_SectorStart * 4096, a_SectorSize, a_TimeStamp)) { return; } const char * ChunkStart = a_FileData + a_SectorStart * 4096; int ByteSize = ntohl(*(int *)ChunkStart); char CompressionMethod = ChunkStart[4]; if (m_Callback.OnCompressedDataSizePos(ByteSize, a_SectorStart * 4096 + 5, CompressionMethod)) { return; } ProcessCompressedChunkData(a_ChunkX, a_ChunkZ, ChunkStart + 5, ByteSize); } void cProcessor::cThread::ProcessCompressedChunkData(int a_ChunkX, int a_ChunkZ, const char * a_CompressedData, int a_CompressedSize) { char Decompressed[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 *)Decompressed; strm.avail_out = sizeof(Decompressed); strm.next_in = (Bytef *)a_CompressedData; strm.avail_in = a_CompressedSize; int res = inflate(&strm, Z_FINISH); inflateEnd(&strm); if (res != Z_STREAM_END) { LOG("Decompression failed, skipping chunk [%d, %d]", a_ChunkX, a_ChunkZ); return; } if (m_Callback.OnDecompressedData(Decompressed, strm.total_out)) { return; } // Parse the NBT data: cParsedNBT NBT(Decompressed, strm.total_out); if (!NBT.IsValid()) { LOG("NBT Parsing failed, skipping chunk [%d, %d]", a_ChunkX, a_ChunkZ); return; } ProcessParsedChunkData(a_ChunkX, a_ChunkZ, NBT); } void cProcessor::cThread::ProcessParsedChunkData(int a_ChunkX, int a_ChunkZ, cParsedNBT & a_NBT) { int LevelTag = a_NBT.FindChildByName(0, "Level"); if (LevelTag < 0) { LOG("Bad logical structure of the NBT, skipping chunk [%d, %d].", a_ChunkX, a_ChunkZ); return; } int XPosTag = a_NBT.FindChildByName(LevelTag, "xPos"); int ZPosTag = a_NBT.FindChildByName(LevelTag, "zPos"); if ((XPosTag < 0) || (ZPosTag < 0)) { LOG("Pos tags missing in NTB, skipping chunk [%d, %d].", a_ChunkX, a_ChunkZ); return; } if (m_Callback.OnRealCoords(a_NBT.GetInt(XPosTag), a_NBT.GetInt(ZPosTag))) { return; } int LastUpdateTag = a_NBT.FindChildByName(LevelTag, "LastUpdate"); if (LastUpdateTag > 0) { if (m_Callback.OnLastUpdate(a_NBT.GetLong(LastUpdateTag))) { return; } } int TerrainPopulatedTag = a_NBT.FindChildByName(LevelTag, "TerrainPopulated"); bool TerrainPopulated = (TerrainPopulatedTag < 0) ? false : (a_NBT.GetByte(TerrainPopulatedTag) != 0); if (m_Callback.OnTerrainPopulated(TerrainPopulated)) { return; } int BiomesTag = a_NBT.FindChildByName(LevelTag, "Biomes"); if (BiomesTag > 0) { if (m_Callback.OnBiomes((const unsigned char *)(a_NBT.GetData(BiomesTag)))) { return; } } int HeightMapTag = a_NBT.FindChildByName(LevelTag, "HeightMap"); if (HeightMapTag > 0) { if (m_Callback.OnHeightMap((const int *)(a_NBT.GetData(HeightMapTag)))) { return; } } if (ProcessChunkSections(a_ChunkX, a_ChunkZ, a_NBT, LevelTag)) { return; } if (ProcessChunkEntities(a_ChunkX, a_ChunkZ, a_NBT, LevelTag)) { return; } if (ProcessChunkTileEntities(a_ChunkX, a_ChunkZ, a_NBT, LevelTag)) { return; } if (ProcessChunkTileTicks(a_ChunkX, a_ChunkZ, a_NBT, LevelTag)) { return; } } bool cProcessor::cThread::ProcessChunkSections(int a_ChunkX, int a_ChunkZ, cParsedNBT & a_NBT, int a_LevelTag) { int Sections = a_NBT.FindChildByName(a_LevelTag, "Sections"); if (Sections < 0) { return false; } bool SectionProcessed[16]; memset(SectionProcessed, 0, sizeof(SectionProcessed)); for (int Tag = a_NBT.GetFirstChild(Sections); Tag > 0; Tag = a_NBT.GetNextSibling(Tag)) { int YTag = a_NBT.FindChildByName(Tag, "Y"); int BlocksTag = a_NBT.FindChildByName(Tag, "Blocks"); int AddTag = a_NBT.FindChildByName(Tag, "Add"); int DataTag = a_NBT.FindChildByName(Tag, "Data"); int BlockLightTag = a_NBT.FindChildByName(Tag, "BlockLightTag"); int SkyLightTag = a_NBT.FindChildByName(Tag, "SkyLight"); if ((YTag < 0) || (BlocksTag < 0) || (DataTag < 0)) { continue; } unsigned char SectionY = a_NBT.GetByte(YTag); if (SectionY >= 16) { LOG("WARNING: Section Y >= 16 (%d), high world, wtf? Skipping section!", SectionY); continue; } if (m_Callback.OnSection( SectionY, (const BLOCKTYPE *) (a_NBT.GetData(BlocksTag)), (AddTag > 0) ? (const NIBBLETYPE *)(a_NBT.GetData(AddTag)) : NULL, (const NIBBLETYPE *)(a_NBT.GetData(DataTag)), (BlockLightTag > 0) ? (const NIBBLETYPE *)(a_NBT.GetData(BlockLightTag)) : NULL, (BlockLightTag > 0) ? (const NIBBLETYPE *)(a_NBT.GetData(BlockLightTag)) : NULL )) { return true; } SectionProcessed[SectionY] = true; } // for Tag - Sections[] // Call the callback for empty sections: for (unsigned char y = 0; y < 16; y++) { if (!SectionProcessed[y]) { if (m_Callback.OnEmptySection(y)) { return true; } } } if (m_Callback.OnSectionsFinished()) { return true; } return false; } bool cProcessor::cThread::ProcessChunkEntities(int a_ChunkX, int a_ChunkZ, cParsedNBT & a_NBT, int a_LevelTag) { int EntitiesTag = a_NBT.FindChildByName(a_LevelTag, "Entities"); if (EntitiesTag < 0) { return false; } for (int EntityTag = a_NBT.GetFirstChild(EntitiesTag); EntityTag > 0; EntityTag = a_NBT.GetNextSibling(EntityTag)) { int PosTag = a_NBT.FindChildByName(EntityTag, "Pos"); if (PosTag < 0) { continue; } int SpeedTag = a_NBT.FindChildByName(EntityTag, "Motion"); if (SpeedTag < 0) { continue; } int RotTag = a_NBT.FindChildByName(EntityTag, "Rotation"); if (RotTag < 0) { continue; } double Pos[3]; for (int i = 0, tag = a_NBT.GetFirstChild(PosTag); (i < 3) && (tag > 0); i++) { Pos[i] = a_NBT.GetDouble(tag); } double Speed[3]; for (int i = 0, tag = a_NBT.GetFirstChild(SpeedTag); (i < 3) && (tag > 0); i++) { Speed[i] = a_NBT.GetDouble(tag); } float Rot[2]; for (int i = 0, tag = a_NBT.GetFirstChild(RotTag); (i < 2) && (tag > 0); i++) { Rot[i] = a_NBT.GetFloat(tag); } if (m_Callback.OnEntity( a_NBT.GetString(a_NBT.FindChildByName(EntityTag, "id")), Pos[0], Pos[1], Pos[2], Speed[0], Speed[1], Speed[2], Rot[0], Rot[1], a_NBT.GetFloat(a_NBT.FindChildByName(EntityTag, "FallDistance")), a_NBT.GetShort(a_NBT.FindChildByName(EntityTag, "Fire")), a_NBT.GetShort(a_NBT.FindChildByName(EntityTag, "Air")), a_NBT.GetByte(a_NBT.FindChildByName(EntityTag, "OnGround")), a_NBT, EntityTag )) { return true; } } // for EntityTag - Entities[] return false; } bool cProcessor::cThread::ProcessChunkTileEntities(int a_ChunkX, int a_ChunkZ, cParsedNBT & a_NBT, int a_LevelTag) { int TileEntitiesTag = a_NBT.FindChildByName(a_LevelTag, "TileEntities"); if (TileEntitiesTag < 0) { return false; } for (int TileEntityTag = a_NBT.GetFirstChild(TileEntitiesTag); TileEntityTag > 0; TileEntityTag = a_NBT.GetNextSibling(TileEntityTag)) { if (m_Callback.OnTileEntity( a_NBT.GetString(a_NBT.FindChildByName(TileEntityTag, "id")), a_NBT.GetInt(a_NBT.FindChildByName(TileEntityTag, "x")), a_NBT.GetInt(a_NBT.FindChildByName(TileEntityTag, "y")), a_NBT.GetInt(a_NBT.FindChildByName(TileEntityTag, "z")), a_NBT, TileEntityTag )) { return true; } } // for EntityTag - Entities[] return false; } bool cProcessor::cThread::ProcessChunkTileTicks(int a_ChunkX, int a_ChunkZ, cParsedNBT & a_NBT, int a_LevelTag) { int TileTicksTag = a_NBT.FindChildByName(a_LevelTag, "TileTicks"); if (TileTicksTag < 0) { return false; } for (int TileTickTag = a_NBT.GetFirstChild(TileTicksTag); TileTickTag > 0; TileTickTag = a_NBT.GetNextSibling(TileTickTag)) { int iTag = a_NBT.FindChildByName(TileTicksTag, "i"); int tTag = a_NBT.FindChildByName(TileTicksTag, "t"); int xTag = a_NBT.FindChildByName(TileTicksTag, "x"); int yTag = a_NBT.FindChildByName(TileTicksTag, "y"); int zTag = a_NBT.FindChildByName(TileTicksTag, "z"); if ((iTag < 0) || (tTag < 0) || (xTag < 0) || (yTag < 0) || (zTag < 0)) { continue; } if (m_Callback.OnTileTick( a_NBT.GetInt(iTag), a_NBT.GetInt(iTag), a_NBT.GetInt(iTag), a_NBT.GetInt(iTag), a_NBT.GetInt(iTag) )) { return true; } } // for EntityTag - Entities[] return false; } //////////////////////////////////////////////////////////////////////////////// // cProcessor: cProcessor::cProcessor(void) : m_IsShuttingDown(false) { } cProcessor::~cProcessor() { } void cProcessor::ProcessWorld(const AString & a_WorldFolder, cCallbackFactory & a_CallbackFactory) { PopulateFileQueue(a_WorldFolder); if (m_FileQueue.empty()) { LOG("No files to process, exitting."); return; } // Start as many threads as there are cores, plus one: // (One more thread can be in the file-read IO block while all other threads crunch the numbers) int NumThreads = GetNumCores() + 1; /* // Limit the number of threads in DEBUG mode to 1 for easier debugging #ifdef _DEBUG NumThreads = 1; #endif // _DEBUG //*/ // Start all the threads: for (int i = 0; i < NumThreads; i++) { cCallback * Callback = a_CallbackFactory.GetNewCallback(); m_Threads.push_back(new cThread(*Callback, *this)); } // Wait for all threads to finish: LOG("Waiting for threads to finish"); for (cThreads::iterator itr = m_Threads.begin(), end = m_Threads.end(); itr != end; ++itr) { (*itr)->WaitForStart(); delete *itr; } // for itr - m_Threads[] LOG("Processor finished"); } void cProcessor::PopulateFileQueue(const AString & a_WorldFolder) { LOG("Processing world in \"%s\"...", a_WorldFolder.c_str()); AString Path = a_WorldFolder; if (!Path.empty() && (Path[Path.length() - 1] != cFile::PathSeparator)) { Path.push_back(cFile::PathSeparator); } AStringVector AllFiles = cFile::GetFolderContents(Path.c_str()); for (AStringVector::iterator itr = AllFiles.begin(), end = AllFiles.end(); itr != end; ++itr) { if (itr->rfind(".mca") != itr->length() - 4) { // Not a .mca file continue; } m_FileQueue.push_back(Path + *itr); } // for itr - AllFiles[] } AString cProcessor::GetOneFileName(void) { cCSLock Lock(m_CS); if (m_FileQueue.empty()) { return ""; } AString res = m_FileQueue.back(); m_FileQueue.pop_back(); return res; } ================================================ FILE: Tools/AnvilStats/Processor.h ================================================ // Processor.h // Interfaces to the cProcessor class representing the overall processor engine that manages threads, calls callbacks etc. #pragma once // fwd: class cCallback; class cCallbackFactory; class cParsedNBT; class cProcessor { class cThread : public cIsThread { typedef cIsThread super; cCallback & m_Callback; cProcessor & m_ParentProcessor; cEvent m_HasStarted; // cIsThread override: virtual void Execute(void) override; void ProcessFile(const AString & a_FileName); void ProcessFileData(const char * a_FileData, size_t a_Size, int a_ChunkBaseX, int a_ChunkBaseZ); void ProcessChunk(const char * a_FileData, int a_ChunkX, int a_ChunkZ, unsigned a_SectorStart, unsigned a_SectorSize, unsigned a_TimeStamp); void ProcessCompressedChunkData(int a_ChunkX, int a_ChunkZ, const char * a_CompressedData, int a_CompressedSize); void ProcessParsedChunkData(int a_ChunkX, int a_ChunkZ, cParsedNBT & a_NBT); // The following processing parts return true if they were interrupted by the callback, causing the processing of current chunk to abort bool ProcessChunkSections(int a_ChunkX, int a_ChunkZ, cParsedNBT & a_NBT, int a_LevelTag); bool ProcessChunkEntities(int a_ChunkX, int a_ChunkZ, cParsedNBT & a_NBT, int a_LevelTag); bool ProcessChunkTileEntities(int a_ChunkX, int a_ChunkZ, cParsedNBT & a_NBT, int a_LevelTag); bool ProcessChunkTileTicks(int a_ChunkX, int a_ChunkZ, cParsedNBT & a_NBT, int a_LevelTag); public: cThread(cCallback & a_Callback, cProcessor & a_ParentProcessor); /** Waits until the thread starts processing the callback code. */ void WaitForStart(void); } ; typedef std::vector cThreads; public: cProcessor(void); ~cProcessor(); void ProcessWorld(const AString & a_WorldFolder, cCallbackFactory & a_CallbackFactory); protected: bool m_IsShuttingDown; // If true, the threads should stop ASAP cCriticalSection m_CS; AStringList m_FileQueue; cThreads m_Threads; /** Populates m_FileQueue with Anvil files from the specified folder. */ void PopulateFileQueue(const AString & a_WorldFolder); /** Returns one filename from m_FileQueue, and removes the name from the queue. */ AString GetOneFileName(void); } ; ================================================ FILE: Tools/AnvilStats/SpringStats.cpp ================================================ // SpringStats.cpp // Implements the cSpringStats class representing a cCallback descendant that collects statistics on lava and water springs #include "Globals.h" #include "SpringStats.h" //////////////////////////////////////////////////////////////////////////////// // cSpringStats::cStats cSpringStats::cStats::cStats(void) : m_TotalChunks(0) { memset(m_LavaSprings, 0, sizeof(m_LavaSprings)); memset(m_WaterSprings, 0, sizeof(m_WaterSprings)); } void cSpringStats::cStats::Add(const cSpringStats::cStats & a_Other) { m_TotalChunks += a_Other.m_TotalChunks; for (int Biome = 0; Biome < 256; Biome++) { for (int Height = 0; Height < 256; Height++) { m_LavaSprings[Biome][Height] += a_Other.m_LavaSprings[Biome][Height]; m_WaterSprings[Biome][Height] += a_Other.m_WaterSprings[Biome][Height]; } } } //////////////////////////////////////////////////////////////////////////////// // cSpringStats: cSpringStats::cSpringStats(void) : m_AreBiomesValid(false) { } bool cSpringStats::OnNewChunk(int a_ChunkX, int a_ChunkZ) { memset(m_BlockTypes, 0, sizeof(m_BlockTypes)); m_AreBiomesValid = false; return false; } bool cSpringStats::OnBiomes(const unsigned char * a_BiomeData) { memcpy(m_Biomes, a_BiomeData, sizeof(m_Biomes)); m_AreBiomesValid = true; return false; } bool cSpringStats::OnSection( unsigned char a_Y, const BLOCKTYPE * a_BlockTypes, const NIBBLETYPE * a_BlockAdditional, const NIBBLETYPE * a_BlockMeta, const NIBBLETYPE * a_BlockLight, const NIBBLETYPE * a_BlockSkyLight ) { memcpy(m_BlockTypes + ((int)a_Y) * 16 * 16 * 16, a_BlockTypes, 16 * 16 * 16); memcpy(m_BlockMetas + ((int)a_Y) * 16 * 16 * 16 / 2, a_BlockMeta, 16 * 16 * 16 / 2); return false; } bool cSpringStats::OnSectionsFinished(void) { if (!m_AreBiomesValid) { return true; } // Calc the spring stats: for (int y = 1; y < 255; y++) { int BaseY = y * 16 * 16; for (int z = 1; z < 15; z++) { int Base = BaseY + z * 16; for (int x = 1; x < 15; x++) { if (cChunkDef::GetNibble(m_BlockMetas, x, y, z) != 0) { // Not a source block continue; } switch (m_BlockTypes[Base + x]) { case E_BLOCK_WATER: case E_BLOCK_STATIONARY_WATER: { TestSpring(x, y, z, m_Stats.m_WaterSprings); break; } case E_BLOCK_LAVA: case E_BLOCK_STATIONARY_LAVA: { TestSpring(x, y, z, m_Stats.m_LavaSprings); break; } } // switch (BlockType) } // for x } // for z } // for y m_Stats.m_TotalChunks += 1; return true; } void cSpringStats::TestSpring(int a_RelX, int a_RelY, int a_RelZ, cSpringStats::cStats::SpringStats & a_Stats) { static const struct { int x, y, z; } Coords[] = { {-1, 0, 0}, { 1, 0, 0}, { 0, -1, 0}, { 0, 1, 0}, { 0, 0, -1}, { 0, 0, 1}, } ; bool HasFluidNextToIt = false; for (int i = 0; i < ARRAYCOUNT(Coords); i++) { switch (cChunkDef::GetBlock(m_BlockTypes, a_RelX + Coords[i].x, a_RelY + Coords[i].y, a_RelZ + Coords[i].z)) { case E_BLOCK_WATER: case E_BLOCK_STATIONARY_WATER: case E_BLOCK_LAVA: case E_BLOCK_STATIONARY_LAVA: { if (cChunkDef::GetNibble(m_BlockMetas, a_RelX + Coords[i].x, a_RelY + Coords[i].y, a_RelZ + Coords[i].z) == 0) { // There is another source block next to this, so this is not a spring return; } HasFluidNextToIt = true; } } // switch (BlockType) } // for i - Coords[] if (!HasFluidNextToIt) { // Surrounded by solids on all sides, this is probably not a spring, // but rather a bedrocked lake or something similar. Dont want. return; } // No source blocks next to the specified block, so it is a spring. Add it to stats: a_Stats[a_RelY][((unsigned char *)m_Biomes)[a_RelX + 16 * a_RelZ]] += 1; } //////////////////////////////////////////////////////////////////////////////// // cSpringStatsFactory: cSpringStatsFactory::~cSpringStatsFactory() { LOG("cSpringStats:"); LOG(" Joining results..."); JoinResults(); LOG(" Total %llu chunks went through", m_CombinedStats.m_TotalChunks); // Save statistics: LOG(" Saving statistics into files:"); LOG(" Springs.xls"); SaveTotals("Springs.xls"); LOG(" BiomeWaterSprings.xls"); SaveStatistics(m_CombinedStats.m_WaterSprings, "BiomeWaterSprings.xls"); LOG(" BiomeLavaSprings.xls"); SaveStatistics(m_CombinedStats.m_LavaSprings, "BiomeLavaSprings.xls"); } void cSpringStatsFactory::JoinResults(void) { for (cCallbacks::iterator itr = m_Callbacks.begin(), end = m_Callbacks.end(); itr != end; ++itr) { m_CombinedStats.Add(((cSpringStats *)(*itr))->GetStats()); } // for itr - m_Callbacks[] } void cSpringStatsFactory::SaveTotals(const AString & a_FileName) { cFile f(a_FileName, cFile::fmWrite); if (!f.IsOpen()) { LOG("Cannot open file \"%s\" for writing!", a_FileName.c_str()); return; } f.Printf("Height\tWater\tLava\n"); for (int Height = 0; Height < 256; Height++) { UInt64 TotalW = 0; UInt64 TotalL = 0; for (int Biome = 0; Biome < 256; Biome++) { TotalW += m_CombinedStats.m_WaterSprings[Height][Biome]; TotalL += m_CombinedStats.m_LavaSprings[Height][Biome]; } f.Printf("%d\t%llu\t%llu\n", Height, TotalW, TotalL); } f.Printf("\n# Chunks\t%llu", m_CombinedStats.m_TotalChunks); } void cSpringStatsFactory::SaveStatistics(const cSpringStats::cStats::SpringStats & a_Stats, const AString & a_FileName) { cFile f(a_FileName, cFile::fmWrite); if (!f.IsOpen()) { LOG("Cannot open file \"%s\" for writing!", a_FileName.c_str()); return; } for (int Height = 0; Height < 256; Height++) { AString Line; Line.reserve(2000); Printf(Line, "%d\t", Height); for (int Biome = 0; Biome < 256; Biome++) { AppendPrintf(Line, "%llu\t", a_Stats[Height][Biome]); } Line.append("\n"); f.Write(Line.c_str(), Line.size()); } } ================================================ FILE: Tools/AnvilStats/SpringStats.h ================================================ // SpringStats.h // Declares the cSpringStats class representing a cCallback descendant that collects statistics on lava and water springs #pragma once #include "Callback.h" class cSpringStats : public cCallback { public: class cStats { public: /** Per-height, per-biome frequencies of springs */ typedef UInt64 SpringStats[256][256]; SpringStats m_LavaSprings; SpringStats m_WaterSprings; /** Total number of chunks that are fully processed through this callback(OnSectionsFinished()) */ UInt64 m_TotalChunks; cStats(void); void Add(const cStats & a_Other); } ; cSpringStats(void); const cStats & GetStats(void) const { return m_Stats; } protected: BLOCKTYPE m_BlockTypes[16 * 16 * 256]; NIBBLETYPE m_BlockMetas[16 * 16 * 256 / 2]; char m_Biomes[16 * 16]; bool m_AreBiomesValid; cStats m_Stats; // cCallback overrides: virtual bool OnNewChunk(int a_ChunkX, int a_ChunkZ) override; virtual bool OnHeader(int a_FileOffset, unsigned char a_NumSectors, int a_Timestamp) override { return false; } virtual bool OnCompressedDataSizePos(int a_CompressedDataSize, int a_DataOffset, char a_CompressionMethod) override { return false; } virtual bool OnDecompressedData(const char * a_DecompressedNBT, int a_DataSize) override { return false; } virtual bool OnRealCoords(int a_ChunkX, int a_ChunkZ) override { return false; } virtual bool OnLastUpdate(Int64 a_LastUpdate) override { return false; } virtual bool OnTerrainPopulated(bool a_Populated) override { return !a_Populated; } // If not populated, we don't want it! virtual bool OnBiomes(const unsigned char * a_BiomeData) override; virtual bool OnHeightMap(const int * a_HeightMap) override { return false; } virtual bool OnSection( unsigned char a_Y, const BLOCKTYPE * a_BlockTypes, const NIBBLETYPE * a_BlockAdditional, const NIBBLETYPE * a_BlockMeta, const NIBBLETYPE * a_BlockLight, const NIBBLETYPE * a_BlockSkyLight ) override; virtual bool OnSectionsFinished(void) override; /** Tests the specified block, if it appears to be a spring, it is added to a_Stats */ void TestSpring(int a_RelX, int a_RelY, int a_RelZ, cStats::SpringStats & a_Stats); } ; class cSpringStatsFactory : public cCallbackFactory { public: virtual ~cSpringStatsFactory(); virtual cCallback * CreateNewCallback(void) override { return new cSpringStats; } cSpringStats::cStats m_CombinedStats; void JoinResults(void); /** Saves total per-height data (summed through biomes) for both spring types to the file */ void SaveTotals(const AString & a_FileName); /** Saves complete per-height, per-biome statistics for the springs to the file */ void SaveStatistics(const cSpringStats::cStats::SpringStats & a_Stats, const AString & a_FileName); } ; ================================================ FILE: Tools/AnvilStats/Statistics.cpp ================================================ // Statistics.cpp // Implements the various statistics-collecting classes #include "Globals.h" #include "Statistics.h" #include "../../src/WorldStorage/FastNBT.h" //////////////////////////////////////////////////////////////////////////////// // cStatistics::cStats: cStatistics::cStats::cStats(void) : m_TotalChunks(0), m_BiomeNumChunks(0), m_BlockNumChunks(0), m_NumEntities(0), m_NumTileEntities(0), m_NumTileTicks(0), m_MinChunkX(0x7fffffff), m_MaxChunkX(0x80000000), m_MinChunkZ(0x7fffffff), m_MaxChunkZ(0x80000000) { memset(m_BiomeCounts, 0, sizeof(m_BiomeCounts)); memset(m_BlockCounts, 0, sizeof(m_BlockCounts)); memset(m_PerHeightBlockCounts, 0, sizeof(m_PerHeightBlockCounts)); memset(m_PerHeightSpawners, 0, sizeof(m_PerHeightSpawners)); memset(m_SpawnerEntity, 0, sizeof(m_SpawnerEntity)); } void cStatistics::cStats::Add(const cStatistics::cStats & a_Stats) { for (int i = 0; i <= 255; i++) { m_BiomeCounts[i] += a_Stats.m_BiomeCounts[i]; } for (int i = 0; i <= 255; i++) { for (int j = 0; j <= 255; j++) { m_BlockCounts[i][j] += a_Stats.m_BlockCounts[i][j]; m_PerHeightBlockCounts[i][j] += a_Stats.m_PerHeightBlockCounts[i][j]; } for (int j = 0; j < ARRAYCOUNT(m_PerHeightSpawners[0]); j++) { m_PerHeightSpawners[i][j] += a_Stats.m_PerHeightSpawners[i][j]; } } for (int i = 0; i < ARRAYCOUNT(m_SpawnerEntity); i++) { m_SpawnerEntity[i] += a_Stats.m_SpawnerEntity[i]; } m_BiomeNumChunks += a_Stats.m_BiomeNumChunks; m_BlockNumChunks += a_Stats.m_BlockNumChunks; m_TotalChunks += a_Stats.m_TotalChunks; m_NumEntities += a_Stats.m_NumEntities; m_NumTileEntities += a_Stats.m_NumTileEntities; m_NumTileTicks += a_Stats.m_NumTileTicks; UpdateCoordsRange(a_Stats.m_MinChunkX, a_Stats.m_MinChunkZ); UpdateCoordsRange(a_Stats.m_MinChunkX, a_Stats.m_MinChunkZ); } void cStatistics::cStats::UpdateCoordsRange(int a_ChunkX, int a_ChunkZ) { if (a_ChunkX < m_MinChunkX) { m_MinChunkX = a_ChunkX; } if (a_ChunkX > m_MaxChunkX) { m_MaxChunkX = a_ChunkX; } if (a_ChunkZ < m_MinChunkZ) { m_MinChunkZ = a_ChunkZ; } if (a_ChunkZ > m_MaxChunkZ) { m_MaxChunkZ = a_ChunkZ; } } //////////////////////////////////////////////////////////////////////////////// // cStatistics: cStatistics::cStatistics(void) { } bool cStatistics::OnNewChunk(int a_ChunkX, int a_ChunkZ) { m_Stats.m_TotalChunks++; m_Stats.UpdateCoordsRange(a_ChunkX, a_ChunkZ); m_IsBiomesValid = false; m_IsFirstSectionInChunk = true; return false; } bool cStatistics::OnBiomes(const unsigned char * a_BiomeData) { for (int i = 0; i < 16 * 16; i++) { m_Stats.m_BiomeCounts[a_BiomeData[i]] += 1; } m_Stats.m_BiomeNumChunks += 1; memcpy(m_BiomeData, a_BiomeData, sizeof(m_BiomeData)); m_IsBiomesValid = true; return false; } bool cStatistics::OnSection ( unsigned char a_Y, const BLOCKTYPE * a_BlockTypes, const NIBBLETYPE * a_BlockAdditional, const NIBBLETYPE * a_BlockMeta, const NIBBLETYPE * a_BlockLight, const NIBBLETYPE * a_BlockSkyLight ) { if (!m_IsBiomesValid) { // The current biome data is not valid, we don't have the means for sorting the BlockTypes into per-biome arrays return true; } for (int y = 0; y < 16; y++) { int Height = (int)a_Y * 16 + y; for (int z = 0; z < 16; z++) { for (int x = 0; x < 16; x++) { unsigned char Biome = m_BiomeData[x + 16 * z]; // Cannot use cChunkDef, different datatype unsigned char BlockType = cChunkDef::GetBlock(a_BlockTypes, x, y, z); m_Stats.m_BlockCounts[Biome][BlockType] += 1; m_Stats.m_PerHeightBlockCounts[Height][BlockType] += 1; } } } m_Stats.m_BlockNumChunks += m_IsFirstSectionInChunk ? 1 : 0; m_IsFirstSectionInChunk = false; return false; } bool cStatistics::OnEmptySection(unsigned char a_Y) { if (!m_IsBiomesValid) { // The current biome data is not valid, we don't have the means for sorting the BlockTypes into per-biome arrays return true; } // Add air to all columns: for (int z = 0; z < 16; z++) { for (int x = 0; x < 16; x++) { unsigned char Biome = m_BiomeData[x + 16 * z]; // Cannot use cChunkDef, different datatype m_Stats.m_BlockCounts[Biome][0] += 16; // 16 blocks in a column, all air } } m_Stats.m_BlockNumChunks += m_IsFirstSectionInChunk ? 1 : 0; m_IsFirstSectionInChunk = false; return false; } bool cStatistics::OnEntity( const AString & a_EntityType, double a_PosX, double a_PosY, double a_PosZ, double a_SpeedX, double a_SpeedY, double a_SpeedZ, float a_Yaw, float a_Pitch, float a_FallDistance, short a_FireTicksLeft, short a_AirTicks, char a_IsOnGround, cParsedNBT & a_NBT, int a_NBTTag ) { m_Stats.m_NumEntities += 1; // TODO return false; } bool cStatistics::OnTileEntity( const AString & a_EntityType, int a_PosX, int a_PosY, int a_PosZ, cParsedNBT & a_NBT, int a_NBTTag ) { m_Stats.m_NumTileEntities += 1; if (a_EntityType == "MobSpawner") { OnSpawner(a_NBT, a_NBTTag); } return false; } bool cStatistics::OnTileTick( int a_BlockType, int a_TicksLeft, int a_PosX, int a_PosY, int a_PosZ ) { m_Stats.m_NumTileTicks += 1; return false; } void cStatistics::OnSpawner(cParsedNBT & a_NBT, int a_TileEntityTag) { // Get the spawned entity type: int EntityIDTag = a_NBT.FindChildByName(a_TileEntityTag, "EntityId"); if ((EntityIDTag < 0) || (a_NBT.GetType(EntityIDTag) != TAG_String)) { return; } eEntityType Ent = GetEntityType(a_NBT.GetString(EntityIDTag)); if (Ent >= ARRAYCOUNT(m_Stats.m_SpawnerEntity)) { return; } m_Stats.m_SpawnerEntity[Ent] += 1; // Get the spawner pos: int PosYTag = a_NBT.FindChildByName(a_TileEntityTag, "y"); if ((PosYTag < 0) || (a_NBT.GetType(PosYTag) != TAG_Int)) { return; } int BlockY = Clamp(a_NBT.GetInt(PosYTag), 0, 255); m_Stats.m_PerHeightSpawners[BlockY][Ent] += 1; } //////////////////////////////////////////////////////////////////////////////// // cStatisticsFactory: cStatisticsFactory::cStatisticsFactory(void) : m_BeginTick(clock()) { } cStatisticsFactory::~cStatisticsFactory() { // Join the results together: LOG("cStatistics:"); LOG(" Joining results..."); JoinResults(); LOG(" Total %llu chunks went through", m_CombinedStats.m_TotalChunks); LOG(" Biomes processed for %llu chunks", m_CombinedStats.m_BiomeNumChunks); // Check the number of blocks processed UInt64 TotalBlocks = 0; for (int i = 0; i <= 255; i++) { for (int j = 0; j < 255; j++) { TotalBlocks += m_CombinedStats.m_BlockCounts[i][j]; } } UInt64 ExpTotalBlocks = m_CombinedStats.m_BlockNumChunks * 16LL * 16LL * 256LL; LOG(" BlockIDs processed for %llu chunks, %llu blocks (exp %llu; %s)", m_CombinedStats.m_BlockNumChunks, TotalBlocks, ExpTotalBlocks, (TotalBlocks == ExpTotalBlocks) ? "match" : "failed"); // Save statistics: LOG(" Saving statistics into files:"); LOG(" Statistics.txt"); SaveStatistics(); LOG(" Biomes.xls"); SaveBiomes(); LOG(" BlockTypes.xls"); SaveBlockTypes(); LOG(" PerHeightBlockTypes.xls"); SavePerHeightBlockTypes(); LOG(" BiomeBlockTypes.xls"); SaveBiomeBlockTypes(); LOG(" Spawners.xls"); SaveSpawners(); LOG(" PerHeightSpawners.xls"); SavePerHeightSpawners(); } void cStatisticsFactory::JoinResults(void) { for (cCallbacks::iterator itr = m_Callbacks.begin(), end = m_Callbacks.end(); itr != end; ++itr) { m_CombinedStats.Add(((cStatistics *)(*itr))->GetStats()); } // for itr - m_Callbacks[] } void cStatisticsFactory::SaveBiomes(void) { cFile f; if (!f.Open("Biomes.xls", cFile::fmWrite)) { LOG("Cannot write to file Biomes.xls. Statistics not written."); return; } double TotalColumns = (double)(m_CombinedStats.m_BiomeNumChunks) * 16 * 16 / 100; // Total number of columns processed; convert into percent if (TotalColumns < 1) { // Avoid division by zero TotalColumns = 1; } for (int i = 0; i <= 255; i++) { AString Line; Printf(Line, "%s\t%d\t%llu\t%.05f\n", GetBiomeString(i), i, m_CombinedStats.m_BiomeCounts[i], ((double)(m_CombinedStats.m_BiomeCounts[i])) / TotalColumns); f.Write(Line.c_str(), Line.length()); } } void cStatisticsFactory::SaveBlockTypes(void) { cFile f; if (!f.Open("BlockTypes.xls", cFile::fmWrite)) { LOG("Cannot write to file Biomes.xls. Statistics not written."); return; } double TotalBlocks = ((double)(m_CombinedStats.m_BlockNumChunks)) * 16 * 16 * 256 / 100; // Total number of blocks processed; convert into percent if (TotalBlocks < 1) { // Avoid division by zero TotalBlocks = 1; } for (int i = 0; i <= 255; i++) { UInt64 Count = 0; for (int Biome = 0; Biome <= 255; ++Biome) { Count += m_CombinedStats.m_BlockCounts[Biome][i]; } AString Line; Printf(Line, "%s\t%d\t%llu\t%.08f\n", GetBlockTypeString(i), i, Count, ((double)Count) / TotalBlocks); f.Write(Line.c_str(), Line.length()); } } void cStatisticsFactory::SavePerHeightBlockTypes(void) { // Export as two tables: biomes 0-127 and 128-255, because OpenOffice doesn't support more than 256 columns cFile f; if (!f.Open("PerHeightBlockTypes.xls", cFile::fmWrite)) { LOG("Cannot write to file PerHeightBlockTypes.xls. Statistics not written."); return; } // Write header: f.Printf("Blocks 0 - 127:\nHeight"); for (int i = 0; i < 128; i++) { f.Printf("\t%s(%d)", GetBlockTypeString(i), i); } f.Printf("\n"); // Write first half: for (int y = 0; y < 256; y++) { f.Printf("%d", y); for (int BlockType = 0; BlockType < 128; BlockType++) { f.Printf("\t%llu", m_CombinedStats.m_PerHeightBlockCounts[y][BlockType]); } // for BlockType f.Printf("\n"); } // for y - height (0 - 127) f.Printf("\n"); // Write second header: f.Printf("Blocks 128 - 255:\nHeight"); for (int i = 128; i < 256; i++) { f.Printf("\t%s(%d)", GetBlockTypeString(i), i); } f.Printf("\n"); // Write second half: for (int y = 0; y < 256; y++) { f.Printf("%d", y); for (int BlockType = 128; BlockType < 256; BlockType++) { f.Printf("\t%llu", m_CombinedStats.m_PerHeightBlockCounts[y][BlockType]); } // for BlockType f.Printf("\n"); } // for y - height (0 - 127) } void cStatisticsFactory::SaveBiomeBlockTypes(void) { // Export as two tables: biomes 0-127 and 128-255, because OpenOffice doesn't support more than 256 columns cFile f; if (!f.Open("BiomeBlockTypes.xls", cFile::fmWrite)) { LOG("Cannot write to file BiomeBlockTypes.xls. Statistics not written."); return; } AString FileHeader("Biomes 0-127:\n"); f.Write(FileHeader.c_str(), FileHeader.length()); AString Header("BlockType\tBlockType"); for (int Biome = 0; Biome <= 127; Biome++) { const char * BiomeName = GetBiomeString(Biome); if ((BiomeName != NULL) && (BiomeName[0] != 0)) { AppendPrintf(Header, "\t%s (%d)", BiomeName, Biome); } else { AppendPrintf(Header, "\t%d", Biome); } } Header.append("\n"); f.Write(Header.c_str(), Header.length()); for (int BlockType = 0; BlockType <= 255; BlockType++) { AString Line; Printf(Line, "%s\t%d", GetBlockTypeString(BlockType), BlockType); for (int Biome = 0; Biome <= 127; Biome++) { AppendPrintf(Line, "\t%llu", m_CombinedStats.m_BlockCounts[Biome][BlockType]); } Line.append("\n"); f.Write(Line.c_str(), Line.length()); } Header.assign("\n\nBiomes 127-255:\nBlockType\tBlockType"); for (int Biome = 0; Biome <= 127; Biome++) { const char * BiomeName = GetBiomeString(Biome); if ((BiomeName != NULL) && (BiomeName[0] != 0)) { AppendPrintf(Header, "\t%s (%d)", BiomeName, Biome); } else { AppendPrintf(Header, "\t%d", Biome); } } Header.append("\n"); f.Write(Header.c_str(), Header.length()); for (int BlockType = 0; BlockType <= 255; BlockType++) { AString Line; Printf(Line, "%s\t%d", GetBlockTypeString(BlockType), BlockType); for (int Biome = 128; Biome <= 255; Biome++) { AppendPrintf(Line, "\t%llu", m_CombinedStats.m_BlockCounts[Biome][BlockType]); } Line.append("\n"); f.Write(Line.c_str(), Line.length()); } } void cStatisticsFactory::SaveStatistics(void) { cFile f; if (!f.Open("Statistics.txt", cFile::fmWrite)) { LOG("Cannot write to file Statistics.txt. Statistics not written."); return; } int Elapsed = (clock() - m_BeginTick) / CLOCKS_PER_SEC; f.Printf("Time elapsed: %d seconds (%d hours, %d minutes and %d seconds)\n", Elapsed, Elapsed / 3600, (Elapsed / 60) % 60, Elapsed % 60); f.Printf("Total chunks processed: %llu\n", m_CombinedStats.m_TotalChunks); if (Elapsed > 0) { f.Printf("Chunk processing speed: %.02f chunks per second\n", (double)(m_CombinedStats.m_TotalChunks) / Elapsed); } f.Printf("Biomes counted for %llu chunks.\n", m_CombinedStats.m_BiomeNumChunks); f.Printf("Blocktypes counted for %llu chunks.\n", m_CombinedStats.m_BlockNumChunks); f.Printf("Total blocks counted: %llu\n", m_CombinedStats.m_BlockNumChunks * 16 * 16 * 256); f.Printf("Total biomes counted: %llu\n", m_CombinedStats.m_BiomeNumChunks * 16 * 16); f.Printf("Total entities counted: %llu\n", m_CombinedStats.m_NumEntities); f.Printf("Total tile entities counted: %llu\n", m_CombinedStats.m_NumTileEntities); f.Printf("Total tile ticks counted: %llu\n", m_CombinedStats.m_NumTileTicks); f.Printf("Chunk coord ranges:\n"); f.Printf("\tX: %d .. %d\n", m_CombinedStats.m_MinChunkX, m_CombinedStats.m_MaxChunkX); f.Printf("\tZ: %d .. %d\n", m_CombinedStats.m_MinChunkZ, m_CombinedStats.m_MaxChunkZ); } void cStatisticsFactory::SaveSpawners(void) { cFile f; if (!f.Open("Spawners.xls", cFile::fmWrite)) { LOG("Cannot write to file Spawners.xls. Statistics not written."); return; } f.Printf("Entity type\tTotal count\tCount per chunk\n"); for (int i = 0; i < entMax; i++) { f.Printf("%s\t%llu\t%0.4f\n", GetEntityTypeString((eEntityType)i), m_CombinedStats.m_SpawnerEntity[i], (double)(m_CombinedStats.m_SpawnerEntity[i]) / m_CombinedStats.m_BlockNumChunks); } } void cStatisticsFactory::SavePerHeightSpawners(void) { cFile f; if (!f.Open("PerHeightSpawners.xls", cFile::fmWrite)) { LOG("Cannot write to file PerHeightSpawners.xls. Statistics not written."); return; } // Write header: f.Printf("Height\tTotal"); for (int i = 0; i < entMax; i++) { f.Printf("\t%s", GetEntityTypeString((eEntityType)i)); } f.Printf("\n"); // Write individual lines: for (int y = 0; y < 256; y++) { UInt64 Total = 0; for (int i = 0; i < entMax; i++) { Total += m_CombinedStats.m_PerHeightSpawners[y][i]; } f.Printf("%d\t%llu", y, Total); for (int i = 0; i < entMax; i++) { f.Printf("\t%llu", m_CombinedStats.m_PerHeightSpawners[y][i]); } f.Printf("\n"); } } ================================================ FILE: Tools/AnvilStats/Statistics.h ================================================ // Statistics.h // Interfaces to the cStatistics class representing a statistics-collecting callback #pragma once #include "Callback.h" #include "Utils.h" class cStatistics : public cCallback { public: class cStats { public: UInt64 m_TotalChunks; // Total number of chunks that go through this callback (OnNewChunk()) UInt64 m_BiomeCounts[256]; UInt64 m_BlockCounts[256][256]; // First dimension is the biome, second dimension is BlockType UInt64 m_BiomeNumChunks; // Num chunks that have been processed for biome stats UInt64 m_BlockNumChunks; // Num chunks that have been processed for block stats UInt64 m_NumEntities; UInt64 m_NumTileEntities; UInt64 m_NumTileTicks; UInt64 m_PerHeightBlockCounts[256][256]; // First dimension is the height, second dimension is BlockType UInt64 m_PerHeightSpawners[256][entMax + 1]; // First dimension is the height, second dimension is spawned entity type int m_MinChunkX, m_MaxChunkX; // X coords range int m_MinChunkZ, m_MaxChunkZ; // Z coords range Int64 m; UInt64 m_SpawnerEntity[entMax + 1]; cStats(void); void Add(const cStats & a_Stats); void UpdateCoordsRange(int a_ChunkX, int a_ChunkZ); } ; cStatistics(void); const cStats & GetStats(void) const { return m_Stats; } protected: cStats m_Stats; bool m_IsBiomesValid; // Set to true in OnBiomes(), reset to false in OnNewChunk(); if true, the m_BiomeData is valid for the current chunk unsigned char m_BiomeData[16 * 16]; bool m_IsFirstSectionInChunk; // True if there was no section in the chunk yet. Set by OnNewChunk(), reset by OnSection() // cCallback overrides: virtual bool OnNewChunk(int a_ChunkX, int a_ChunkZ) override; virtual bool OnHeader(int a_FileOffset, unsigned char a_NumSectors, int a_Timestamp) override { return false; } virtual bool OnCompressedDataSizePos(int a_CompressedDataSize, int a_DataOffset, char a_CompressionMethod) override { return false; } virtual bool OnDecompressedData(const char * a_DecompressedNBT, int a_DataSize) override { return false; } virtual bool OnRealCoords(int a_ChunkX, int a_ChunkZ) override { return false; } virtual bool OnLastUpdate(Int64 a_LastUpdate) override { return false; } virtual bool OnTerrainPopulated(bool a_Populated) override { return !a_Populated; } // If not populated, we don't want it! virtual bool OnBiomes(const unsigned char * a_BiomeData) override; virtual bool OnHeightMap(const int * a_HeightMap) override { return false; } virtual bool OnSection( unsigned char a_Y, const BLOCKTYPE * a_BlockTypes, const NIBBLETYPE * a_BlockAdditional, const NIBBLETYPE * a_BlockMeta, const NIBBLETYPE * a_BlockLight, const NIBBLETYPE * a_BlockSkyLight ) override; virtual bool OnEmptySection(unsigned char a_Y) override; virtual bool OnSectionsFinished(void) override { return false; } // continue processing virtual bool OnEntity( const AString & a_EntityType, double a_PosX, double a_PosY, double a_PosZ, double a_SpeedX, double a_SpeedY, double a_SpeedZ, float a_Yaw, float a_Pitch, float a_FallDistance, short a_FireTicksLeft, short a_AirTicks, char a_IsOnGround, cParsedNBT & a_NBT, int a_NBTTag ) override; virtual bool OnTileEntity( const AString & a_EntityType, int a_PosX, int a_PosY, int a_PosZ, cParsedNBT & a_NBT, int a_NBTTag ) override; virtual bool OnTileTick( int a_BlockType, int a_TicksLeft, int a_PosX, int a_PosY, int a_PosZ ) override; void OnSpawner(cParsedNBT & a_NBT, int a_TileEntityTag); } ; class cStatisticsFactory : public cCallbackFactory { public: cStatisticsFactory(void); virtual ~cStatisticsFactory(); virtual cCallback * CreateNewCallback(void) { return new cStatistics; } protected: // The results, combined, are stored here: cStatistics::cStats m_CombinedStats; clock_t m_BeginTick; void JoinResults(void); void SaveBiomes(void); void SaveBlockTypes(void); void SavePerHeightBlockTypes(void); void SaveBiomeBlockTypes(void); void SaveStatistics(void); void SaveSpawners(void); void SavePerHeightSpawners(void); } ; ================================================ FILE: Tools/AnvilStats/Utils.cpp ================================================ // Utils.cpp // Implements utility functions #include "Globals.h" #include "Utils.h" struct { eEntityType Type; const char * String; } g_EntityTypes[] = { {entBat, "Bat"}, {entBlaze, "Blaze"}, {entCaveSpider, "CaveSpider"}, {entChicken, "Chicken"}, {entCow, "Cow"}, {entCreeper, "Creeper"}, {entEnderDragon, "EnderDragon"}, {entEnderman, "Enderman"}, {entGhast, "Ghast"}, {entGiant, "Giant"}, {entGuardian, "Guardian"}, {entLavaSlime, "LavaSlime"}, {entMushroomCow, "MushroomCow"}, {entOzelot, "Ozelot"}, {entPig, "Pig"}, {entPigZombie, "PigZombie"}, {entRabbit, "Rabbit"}, {entSheep, "Sheep"}, {entSilverfish, "Slverfish"}, {entSkeleton, "Skeleton"}, {entSlime, "Slime"}, {entSnowMan, "SnowMan"}, {entSpider, "Spider"}, {entSquid, "Squid"}, {entVillager, "Villager"}, {entVillagerGolem, "VillagerGolem"}, {entWitch, "Witch"}, {entWitherBoss, "WitherBoss"}, {entWolf, "Wolf"}, {entZombie, "Zombie"}, {entZombieVillager, "ZombieVillager"}, {entUnknown, "Unknown"}, } ; const char * GetBiomeString(unsigned char a_Biome) { static const char * BiomeNames[] = // Biome names, as equivalent to their index { "Ocean", "Plains", "Desert", "Extreme Hills", "Forest", "Taiga", "Swampland", "River", "Hell", "Sky", "Frozen Ocean", "Frozen River", "Ice Plains", "Ice Mountains", "Mushroom Island", "Mushroom Island Shore", "Beach", "Desert Hills", "Forest Hills", "Taiga Hills", "Extreme Hills Edge", "Jungle", "Jungle Hills", } ; return (a_Biome < ARRAYCOUNT(BiomeNames)) ? BiomeNames[a_Biome] : ""; } const char * GetBlockTypeString(unsigned char a_BlockType) { static const char * BlockTypeNames[] = // Block type names, as equivalent to their index { "air", "stone", "grass", "dirt", "cobblestone", "planks", "sapling", "bedrock", "water", "stillwater", "lava", "stilllava", "sand", "gravel", "goldore", "ironore", "coalore", "log", "leaves", "sponge", "glass", "lapisore", "lapisblock", "dispenser", "sandstone", "noteblock", "bedblock", "poweredrail", "detectorrail", "stickypiston", "cobweb", "tallgrass", "deadbush", "piston", "pistonhead", "wool", "pistonmovedblock", "flower", "rose", "brownmushroom", "redmushroom", "goldblock", "ironblock", "doubleslab", "slab", "brickblock", "tnt", "bookcase", "mossycobblestone", "obsidian", "torch", "fire", "mobspawner", "woodstairs", "chest", "redstonedust", "diamondore", "diamondblock", "workbench", "crops", "soil", "furnace", "litfurnace", "signblock", "wooddoorblock", "ladder", "tracks", "cobblestonestairs", "wallsign", "lever", "stoneplate", "irondoorblock", "woodplate", "redstoneore", "redstoneorealt", "redstonetorchoff", "redstonetorchon", "button", "snow", "ice", "snowblock", "cactus", "clayblock", "reedblock", "jukebox", "fence", "pumpkin", "netherrack", "soulsand", "glowstone", "portal", "jack-o-lantern", "cakeblock", "repeateroff", "repeateron", "lockedchest", "trapdoor", "silverfishblock", "stonebricks", "hugebrownmushroom", "hugeredmushroom", "ironbars", "glasspane", "melon", "pumpkinstem", "melonstem", "vines", "fencegate", "brickstairs", "stonebrickstairs", "mycelium", "lilypad", "netherbrick", "netherbrickfence", "netherbrickstairs", "netherwartblock", "enchantmenttable", "brewingstandblock", "cauldronblock", "endportal", "endportalframe", "endstone", "dragonegg", "redstonelampoff", "redstonelampon", "woodendoubleslab", "woodenslab", "cocoapod", "sandstonestairs", /* 128 */ "Emerald Ore", "Ender Chest", "Tripwire Hook", "Tripwire", "Block of Emerald", "Spruce Wood Stairs", "Birch Wood Stairs", "Jungle Wood Stairs", "Command Block", "Beacon", "Cobblestone Wall", "Flower Pot", "Carrots", "Potatoes", "Wooden Button", "Head", } ; return (a_BlockType < ARRAYCOUNT(BlockTypeNames)) ? BlockTypeNames[a_BlockType] : ""; } eEntityType GetEntityType(const AString & a_EntityTypeString) { for (int i = 0; i < ARRAYCOUNT(g_EntityTypes); i++) { if (a_EntityTypeString == g_EntityTypes[i].String) { return g_EntityTypes[i].Type; } } return entUnknown; } extern const char * GetEntityTypeString(eEntityType a_EntityType) { return g_EntityTypes[a_EntityType].String; } int GetNumCores(void) { // Get number of cores by querying the system process affinity mask (Windows-specific) DWORD_PTR Affinity, ProcAffinity; GetProcessAffinityMask(GetCurrentProcess(), &ProcAffinity, &Affinity); int NumCores = 0; while (Affinity > 0) { if ((Affinity & 1) == 1) { ++NumCores; } Affinity >>= 1; } // while (Affinity > 0) return NumCores; } ================================================ FILE: Tools/AnvilStats/Utils.h ================================================ // Utils.h // Interfaces to utility functions #pragma once enum eEntityType { entBat, entBlaze, entCaveSpider, entChicken, entCow, entCreeper, entEnderDragon, entEnderman, entGhast, entGiant, entGuardian, entLavaSlime, entMushroomCow, entOzelot, entPig, entPigZombie, entRabbit, entSheep, entSilverfish, entSkeleton, entSlime, entSnowMan, entSpider, entSquid, entVillager, entVillagerGolem, entWitch, entWitherBoss, entWolf, entZombie, entZombieVillager, entUnknown, entMax = entUnknown, } ; extern const char * GetBiomeString(unsigned char a_Biome); extern const char * GetBlockTypeString(unsigned char a_BlockType); extern eEntityType GetEntityType(const AString & a_EntityTypeString); extern const char * GetEntityTypeString(eEntityType a_EntityType); extern int GetNumCores(void); ================================================ FILE: Tools/AnvilStats/profile_run.cmd ================================================ @echo off :: :: Profiling using a MSVC standalone profiler :: :: See https://www.codeproject.com/Articles/144643/Profiling-of-C-Applications-in-Visual-Studio-for-F for details :: set pt="C:\Program Files\Microsoft Visual Studio 9.0\Team Tools\Performance Tools" set appdir="Release profiled" set app="Release profiled\AnvilStats.exe" set args="0 c:\Games\MLG\world\region" :: outputdir is relative to appdir! set outputdir=Profiling set output=profile.vsp ::Create the output directory, if it didn't exist mkdir %outputdir% :: Start the profiler %pt%\vsperfcmd /start:sample /output:%outputdir%\%output% if errorlevel 1 goto haderror :: Launch the application via the profiler %pt%\vsperfcmd /launch:%app% /args:%args% if errorlevel 1 goto haderror :: Shut down the profiler (this command waits, until the application is terminated) %pt%\vsperfcmd /shutdown if errorlevel 1 goto haderror :: cd to outputdir, so that the reports are generated there cd %outputdir% :: generate the report files (.csv) %pt%\vsperfreport /summary:all %output% /symbolpath:"srv*C:\Programovani\Symbols*https://msdl.microsoft.com/download/symbols" if errorlevel 1 goto haderror goto finished :haderror echo An error was encountered pause :finished ================================================ FILE: Tools/BlockTypePaletteGenerator/.gitignore ================================================ # Ignore the scripts' outputs: *.json *.btp.txt UpgradeBlockTypePalette.txt ================================================ FILE: Tools/BlockTypePaletteGenerator/Generator.lua ================================================ -- Generator.lua --[[ Crafts an intermediate block palette format to be read by Cuberite. It processes the blocks.json report file (https://wiki.vg/Data_Generators) into a file that can be loaded into a BlockTypePalette (and is to be stored as Server/Protocol//base.btp.txt). The output format is the regular TSV BlockTypePalette, described in the $/src/BlockTypePalette.h file. --]] -- Allow Lua to load libraries in our subfolder: package.path = 'lib/lunajson/src/?.lua;' .. package.path; --- Prints usage instructions to stdout. -- If the optional `aMessage` is passed, output is prepended by message _and_ -- redirected to stderr. local function usage(aMessage) if aMessage then io.output(io.stderr); io.write(aMessage, "\n\n"); end io.write( "Usage: lua Generator.lua INPUTFILE OUTPUTFILE\n".. "Converts the Minecraft blocks.json report format to the cuberite ".. "block type palette format.\n".. "\n".. "INPUTFILE and OUTPUTFILE must point to a valid path. INPUTFILE must ".. "be readable and OUTPUTFILE must be writable. Either can be replaced ".. "with `-` (dash character) to point to standard-input or -output.\n"); os.exit(message and 1 or 0); end --- Parses the JSON registry into a Lua table --[[ The returned array-table has the following format: { { id = 1, blockTypeName = "minecraft:stone", properties = {key = value, ...} }, ... } --]] local function parseRegistry(aBlockRegistryJsonStr) assert(type(aBlockRegistryJsonStr) == "string") local lj = require("lunajson") local input = lj.decode(aBlockRegistryJsonStr) local registry = {} local idx = 1 for blockTypeName, blockData in pairs(input) do for _, state in pairs(blockData.states) do registry[idx] = { id = state.id, blockTypeName = blockTypeName, properties = state.properties, } idx = idx + 1 end end return registry end --- Serializes the properties from the JSON / array table format into a single output string -- Concatenates all properties with \t as the delimiting character local function serializeProperties(aProperties) local res = {} local idx = 1 for k, v in pairs(aProperties or {}) do res[idx] = k res[idx + 1] = v idx = idx + 2 end return table.concat(res, "\t") end --- Returns the prefix that is common for all block type names in the registry -- aRegistry is the parsed registry, as returned from parseRegistry() local function findCommonPrefix(aRegistryTable) local prefix = aRegistryTable[1].blockTypeName local len = string.len(prefix) local sub = string.sub for _, block in ipairs(aRegistryTable) do while (sub(block.blockTypeName, 1, len) ~= prefix) do len = len - 1 if (len == 0) then return "" end prefix = sub(prefix, 1, len) end end return prefix end -- Test whether the script is run in a path where it can load it's libraries if not(pcall(function() require("lunajson") end)) then usage( "Could not load required libraries, please run `Generator.lua` " .. "within its directory and make sure to run `git submodule update`." ) end -- Check/Prepare CLI arguments local inpath, outpath = ...; inpath = inpath or "blocks.json" outpath = outpath or "base.btp.txt" if (inpath ~= "-") then local handle, err = io.open(inpath, "r") io.input(handle or usage(err)) end if (outpath ~= "-") then local handle, err = io.open(outpath, "w") io.output(handle or usage(err)) end -- Parse the registry: local registry = parseRegistry(io.input():read("*a")) local commonPrefix = findCommonPrefix(registry) -- Sort the entries: table.sort(registry, function (entry1, entry2) return (entry1.id < entry2.id) end ) -- Write out the output format: io.write("BlockTypePalette\n") io.write("FileVersion\t1\n") io.write("CommonPrefix\t", commonPrefix, "\n") io.write("\n") local prefixLen = string.len(commonPrefix) + 1 for _, entry in ipairs(registry) do local props = serializeProperties(entry.properties) if (props ~= "") then props = "\t" .. props end io.write( entry.id, "\t", string.sub(entry.blockTypeName, prefixLen), props, "\n" ) end ================================================ FILE: Tools/BlockTypePaletteGenerator/UpgradeGenerator.lua ================================================ -- UpgradeGenerator.lua --[[ Creates the UpgradeBlockTypePalette out of JSON data of the Minutor project (https://github.com/mrkite/minutor/blob/master/definitions/vanilla_ids.json Parses the JSON into memory, then walks each block's "id" member and possibly the "variants" sub-member to read the block types. The name is either present as "flatname", or is synthesized from the internal Minutor "name" by lowercasing and replacing spaces with underscores. Expects two parameters, the input file and output file; either can be replaced by a "-" to use stdin / stdout instead. If not given, the input file defaults to "vanilla_ids.json" and the output file defaults to "UpgradeBlockTypePalette.txt" The output format is the upgrade TSV BlockTypePalette, described in the $/src/BlockTypePalette.h file. --]] -- Allow Lua to load libraries in our subfolder: package.path = 'lib/lunajson/src/?.lua;' .. package.path; --- Splits the full flat name into flat name and properties -- "minecraft:carrots:age:0" -> "minecraft:carrots", {age = 0} local function splitFlatName(aFullFlatName) local props = {} local numParts = 0 local flatName = "" local propKey = "" aFullFlatName:gsub("([^:]+)", function (aPart) if (numParts == 0) then flatName = aPart elseif (numParts == 1) then flatName = flatName .. ":" .. aPart elseif (numParts % 2 == 0) then propKey = aPart else props[propKey] = aPart end numParts = numParts + 1 end ) return flatName, props end --- Returns the minecraft block name, created from the flat name if present, or synthesized -- from the Minutor name -- If the flat name contains encoded block properties, it returns those properties as a dict-table -- in the second return value local function processBlockName(aFlatName, aMinutorName) if (aFlatName) then assert(type(aFlatName) == "string") return splitFlatName(aFlatName) end if not(type(aMinutorName) == "string") then return nil end return "minecraft:" .. (aMinutorName:lower():gsub(" ", "_")), {} end --- Serializes the properties from the JSON / array table format into a single output string -- Concatenates all properties with \t as the delimiting character local function serializeProperties(aProperties) local res = {} local idx = 1 for k, v in pairs(aProperties or {}) do res[idx] = k res[idx + 1] = v idx = idx + 2 end return table.concat(res, "\t") end --- Parses the vanilla_ids.json into a common registry format -- The returned registry is an array-table of -- {blockType = 1, blockMeta = 2, blockTypeName = "name", properties = {key = value, ...}} local function parseRegistry(aJsonString) assert(type(aJsonString) == "string") -- Parse the JSON: local lj = require("lunajson") local input = lj.decode(aJsonString) if (not(input) or (input["type"] ~= "block") or not(input["data"])) then error("The input file doesn't contain vanilla IDs.") end -- Create the registry: local registry = {} local idx = 1 for _, entry in pairs(input["data"]) do local id = entry["id"] local parentBlockTypeName, props = processBlockName(entry["flatname"], entry["name"]) registry[idx] = { blockType = id, blockMeta = 0, blockTypeName = parentBlockTypeName, properties = props, } idx = idx + 1 for _, variant in pairs(entry["variants"] or {}) do local blockTypeName, props = processBlockName(variant["flatname"], variant["name"]) if not(blockTypeName) then -- Some blocks don't have all their variants named ("brown mushroom block"), use the parent name in such a case blockTypeName = parentBlockTypeName end registry[idx] = { blockType = id, blockMeta = variant["data"], blockTypeName = blockTypeName, properties = props, } idx = idx + 1 end end return registry end --- Returns the prefix that is common for all block type names in the registry -- aRegistry is the parsed registry, as returned from parseRegistry() local function findCommonPrefix(aRegistryTable) local prefix = aRegistryTable[1].blockTypeName local len = string.len(prefix) local sub = string.sub for _, block in ipairs(aRegistryTable) do while (sub(block.blockTypeName, 1, len) ~= prefix) do len = len - 1 if (len == 0) then return "" end prefix = sub(prefix, 1, len) end end return prefix end -- Test whether the script is run in a path where it can load it's libraries if not(pcall(function() require("lunajson") end)) then error( "Could not load required libraries, please run `UpgradeGenerator.lua` " .. "within its directory and make sure to run `git submodule update`." ) end -- Check/Prepare CLI arguments local inpath, outpath = ...; inpath = inpath or "vanilla_ids.json" outpath = outpath or "UpgradeBlockTypePalette.txt" if (inpath ~= "-") then local handle, err = io.open(inpath, "r") io.input(handle or usage(err)) end if (outpath ~= "-") then local handle, err = io.open(outpath, "w") io.output(handle or usage(err)) end -- Parse the registry: local registry = parseRegistry(io.input():read("*a")) local commonPrefix = findCommonPrefix(registry) -- Sort the entries: table.sort(registry, function (entry1, entry2) if (entry1.blockType < entry2.blockType) then return true elseif (entry1.blockType > entry2.blockType) then return false else return (entry1.blockMeta < entry2.blockMeta) end end ) -- Write out the output format: io.write("UpgradeBlockTypePalette\n") io.write("FileVersion\t1\n") io.write("CommonPrefix\t", commonPrefix, "\n") io.write("\n") local prefixLen = string.len(commonPrefix) + 1 for _, entry in ipairs(registry) do local props = serializeProperties(entry.properties) if (props ~= "") then props = "\t" .. props end io.write( entry.blockType, "\t", entry.blockMeta, "\t", string.sub(entry.blockTypeName, prefixLen), props, "\n" ) end ================================================ FILE: Tools/BlockTypePaletteGenerator/UpgradePaletteCheck.lua ================================================ -- UpgradePaletteCheck.lua --[[ Implements a check that lists all entries in the UpgradeBlockTypePalette that are not present in the 1.13 protocol palette. The palette files are expected to be in folders relative to this script like they are in the git repo: ../../Server/Protocol/UpgradeBlockTypePalette.txt ../../Server/Protocol/1.13/base.btp.txt --]] --- Partially loads a BlockTypePalette file -- Parses the specified file into headers (returned as a key-value table) and data (returned as array of strings) -- Returns a table, {headers = {}, data = {}} local function loadPalSplitHeader(aFileName) local f = assert(io.open(aFileName, "r")) local isFileIdentLine = true local isInHeaders = false local headers = {} local data = {} local idx = 1 for ln in f:lines() do if (isFileIdentLine) then assert(not(isInHeaders)) assert((ln == "BlockTypePalette") or (ln == "UpgradeBlockTypePalette")) isFileIdentLine = false isInHeaders = true elseif (ln == "") then assert(not(isFileIdentLine)) assert(isInHeaders) -- data must not contain an empty line isInHeaders = false elseif (isInHeaders) then assert(not(isFileIdentLine)) local key, val = ln:match("(.-)\t(.*)") assert(key) assert(val) headers[key] = val else data[idx] = ln idx = idx + 1 end end return { headers = headers, data = data} end --- Normalizes the block description -- aRawDesc is the description read from the palette file, "grass_block\tsnowy\tfalse" -- Returns the normalized description "grass_block:snowy:false", where the block state keys are alpha-sorted local function normalizeDesc(aRawDesc) local blockTypeName, blockStates = aRawDesc:match("(.-)\t(.*)") if not(blockTypeName) then -- There's no TABs in the raw desc, only simple block return aRawDesc end local blockStatesTab = {} local idx = 1 blockStates = blockStates .. "\t" for k, v in blockStates:gmatch("(.-)\t(.-)\t") do blockStatesTab[idx] = k .. ":" .. v idx = idx + 1 end table.sort(blockStatesTab) return blockTypeName .. ":" .. table.concat(blockStatesTab, ":") end --- Loads the 1.13 palette --[[ Returns the palette loaded as a table: { numberToDesc = {[1] = "minecraft:stone", [8] = "minecraft:grass_block:snowy:false", ...}, descToNumber = {["minecraft:stone"] = 1, ...} } --]] local function loadPalette() local pal = loadPalSplitHeader("../../Server/Protocol/1.13/base.btp.txt") local numberToDesc = {} local descToNumber = {} local prefix = pal.headers["CommonPrefix"] or "" for _, ln in ipairs(pal.data) do local number, desc = ln:match("(.-)\t(.*)") desc = normalizeDesc(desc) desc = prefix .. desc number = tonumber(number) or error("Index is not a number: " .. ln) numberToDesc[number] = desc descToNumber[desc] = number end return { numberToDesc = numberToDesc, descToNumber = descToNumber} end local function runCheck() -- Load the palettes: local pal = loadPalette() local upg = loadPalSplitHeader("../../Server/Protocol/UpgradeBlockTypePalette.txt") -- Check the UpgradePalette's BlockDescs against the 1.13 palette: local prefix = upg.headers["CommonPrefix"] or "" local notFound = {} local idx = 1 local totalCnt = 0 for _, ln in ipairs(upg.data) do local blockType, blockMeta, desc = ln:match("(.-)\t(.-)\t(.*)") local normDesc = normalizeDesc(prefix .. desc) if not(pal.descToNumber[normDesc]) then notFound[idx] = {blockType = blockType, blockMeta = blockMeta, desc = desc} idx = idx + 1 end totalCnt = totalCnt + 1 end idx = idx - 1 -- Print the findings: print("Blocks not found: " .. idx .. " out of " .. totalCnt) for _, nf in ipairs(notFound) do print(nf.blockType .. "\t" .. nf.blockMeta .. "\t" .. nf.desc) end print("Blocks not found: " .. idx .. " out of " .. totalCnt) end -- MAIN: runCheck() ================================================ FILE: Tools/BlockZapper/.gitignore ================================================ Debug/ logs/ Release/ ================================================ FILE: Tools/BlockZapper/BlockZapper.cpp ================================================ // BlockZapper.cpp // Implements the main app entrypoint #include "Globals.h" #include #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 ]\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 ; 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; } ; ================================================ FILE: Tools/BlockZapper/BlockZapper.txt ================================================ // 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 Cuberite that may be under other licenses. */ ================================================ FILE: Tools/BlockZapper/GNUmakefile ================================================ ################################################### # # 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 https://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../../src\ -I../../lib\ ################################################### # Build BlockZapper # SOURCES := $(shell find . '(' -name '*.cpp' -o -name '*.c' ')') SHAREDSOURCES := \ src/Log.cpp \ src/MCLogger.cpp \ src/Noise.cpp \ src/StringCompression.cpp \ src/StringUtils.cpp \ src/OSSupport/CriticalSection.cpp \ src/OSSupport/File.cpp \ src/OSSupport/IsThread.cpp \ src/OSSupport/MakeDir.cpp \ src/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 ################################################### # 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)src/%.o: ../../src/%.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 ================================================ FILE: Tools/BlockZapper/Globals.cpp ================================================ // Globals.cpp // Used for precompiled header generation in MSVC #include "Globals.h" ================================================ FILE: Tools/BlockZapper/Globals.h ================================================ // Globals.h // This file is used for precompiled header generation in MSVC #include "../../src/Globals.h" ================================================ FILE: Tools/BlockZapper/Regions.cpp ================================================ // 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)); } ================================================ FILE: Tools/BlockZapper/Regions.h ================================================ // Regions.h // Declares the cRegions class representing individual regions to zap #pragma once #include 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 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); } ; ================================================ FILE: Tools/BlockZapper/Zapper.cpp ================================================ // 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/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[4]); 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 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; } } } ================================================ FILE: Tools/BlockZapper/Zapper.h ================================================ // 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); } ; ================================================ FILE: Tools/GeneratorPerformanceTest/CMakeLists.txt ================================================ project(GeneratorPerformanceTest) include_directories(../../src/Generating) include_directories(../../src) include_directories(../../lib) add_executable(GeneratorPerformanceTest GeneratorPerformanceTest.cpp ../../src/StringUtils ../../src/MCLogger ../../src/Log ../../src/BlockID ../../src/Noise ../../src/Enchantments ../../src/BlockArea) target_link_libraries(GeneratorPerformanceTest Generating) ================================================ FILE: Tools/GeneratorPerformanceTest/GeneratorPerformanceTest.cpp ================================================ #include "Globals.h" #include "ChunkGenerator.h" int main(int argc, char * argv[]) { cChunkGenerator Generator = cChunkGenerator(); } ================================================ FILE: Tools/GrownBiomeGenVisualiser/.gitignore ================================================ # Ignore the output images: *.ppm ================================================ FILE: Tools/GrownBiomeGenVisualiser/CMakeLists.txt ================================================ project (GrownBiomeGenVisualiser) find_package(Threads REQUIRED) # Set include paths to the used libraries: include_directories(SYSTEM "../../lib") include_directories("../../src") function(flatten_files arg1) set(res "") foreach(f ${${arg1}}) get_filename_component(f ${f} ABSOLUTE) list(APPEND res ${f}) endforeach() set(${arg1} "${res}" PARENT_SCOPE) endfunction() # Include the shared files: set(SHARED_SRC ../../src/StringUtils.cpp ../../src/Logger.cpp ../../src/Noise/Noise.cpp ../../src/BiomeDef.cpp ) set(SHARED_HDR ../../src/StringUtils.h ) flatten_files(SHARED_SRC) flatten_files(SHARED_HDR) source_group("Shared" FILES ${SHARED_SRC} ${SHARED_HDR}) set(SHARED_OSS_SRC ../../src/OSSupport/CriticalSection.cpp ../../src/OSSupport/Event.cpp ../../src/OSSupport/File.cpp ../../src/OSSupport/IsThread.cpp ../../src/OSSupport/StackTrace.cpp ../../src/OSSupport/WinStackWalker.cpp ) set(SHARED_OSS_HDR ../../src/OSSupport/CriticalSection.h ../../src/OSSupport/Event.h ../../src/OSSupport/File.h ../../src/OSSupport/IsThread.h ../../src/OSSupport/StackTrace.h ../../src/OSSupport/WinStackWalker.h ) flatten_files(SHARED_OSS_SRC) flatten_files(SHARED_OSS_HDR) source_group("Shared\\OSSupport" FILES ${SHARED_OSS_SRC} ${SHARED_OSS_HDR}) # Include the main source files: set(SOURCES GrownBiomeGenVisualiser.cpp Globals.cpp ) set(HEADERS Globals.h ) source_group("" FILES ${SOURCES} ${HEADERS}) add_executable(GrownBiomeGenVisualiser ${SOURCES} ${HEADERS} ${SHARED_SRC} ${SHARED_HDR} ${SHARED_OSS_SRC} ${SHARED_OSS_HDR} ) target_link_libraries(GrownBiomeGenVisualiser fmt::fmt Threads::Threads) set_target_properties(GrownBiomeGenVisualiser PROPERTIES FOLDER Tools) if (WIN32) target_link_libraries(GrownBiomeGenVisualiser ws2_32) endif() include(../../SetFlags.cmake) set_exe_flags(GrownBiomeGenVisualiser) ================================================ FILE: Tools/GrownBiomeGenVisualiser/Globals.cpp ================================================ // Globals.cpp // This file is used for precompiled header generation in MSVC environments #include "Globals.h" ================================================ FILE: Tools/GrownBiomeGenVisualiser/Globals.h ================================================ // Globals.h // This file gets included from every module in the project, so that global symbols may be introduced easily // Also used for precompiled header generation in MSVC environments // Compiler-dependent stuff: #if defined(_MSC_VER) // MSVC produces warning C4481 on the override keyword usage, so disable the warning altogether #pragma warning(disable:4481) // Disable some warnings that we don't care about: #pragma warning(disable:4100) #elif defined(__GNUC__) // TODO: Can GCC explicitly mark classes as abstract (no instances can be created)? #define abstract #else #error "You are using an unsupported compiler, you might need to #define some stuff here for your compiler" #endif #ifndef TOLUA_TEMPLATE_BIND #define TOLUA_TEMPLATE_BIND(x) #endif // Integral types with predefined sizes: typedef long long Int64; typedef int Int32; typedef short Int16; typedef unsigned long long UInt64; typedef unsigned int UInt32; typedef unsigned short UInt16; typedef unsigned char Byte; // A macro to disallow the copy constructor and operator= functions // This should be used in the private: declarations for any class that shouldn't allow copying itself #define DISALLOW_COPY_AND_ASSIGN(TypeName) \ TypeName(const TypeName &); \ void operator=(const TypeName &) // A macro that is used to mark unused function parameters, to avoid pedantic warnings in gcc #define UNUSED(X) (void)(X) // OS-dependent stuff: #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN #include #include #include // Windows SDK defines min and max macros, messing up with our std::min and std::max usage #undef min #undef max // Windows SDK defines GetFreeSpace as a constant, probably a Win16 API remnant #ifdef GetFreeSpace #undef GetFreeSpace #endif // GetFreeSpace #define SocketError WSAGetLastError() #else #include #include // for mkdir #include #include #include #include #include #include #include #include #include #include #include #include #include typedef int SOCKET; enum { INVALID_SOCKET = -1, }; #define closesocket close #define SocketError errno #endif // CRT stuff: #include #include #include #include #include #include // STL stuff: #include #include #include #include #include #include #include #include #include #include #include // Common headers (without macros): #include "fmt.h" #include "StringUtils.h" // Common definitions: /** Evaluates to the number of elements in an array (compile-time!) */ #define ARRAYCOUNT(X) (sizeof(X) / sizeof(*(X))) /** Allows arithmetic expressions like "32 KiB" (but consider using parenthesis around it, "(32 KiB)") */ #define KiB * 1024 #define MiB * 1024 * 1024 /** Faster than (int)floorf((float)x / (float)div) */ #define FAST_FLOOR_DIV(x, div) ((x) < 0 ? (((int)x / div) - 1) : ((int)x / div)) /** Own version of assert() that writes failed assertions to the log for review */ #ifdef NDEBUG #define ASSERT(x) ((void)0) #else #define ASSERT assert #endif // Pretty much the same as ASSERT() but stays in Release builds #define VERIFY(x) (!!(x) || (LOGERROR("Verification failed: %s, file %s, line %i", #x, __FILE__, __LINE__), exit(1), 0)) /** Clamp X to the specified range. */ template T Clamp(T a_Value, T a_Min, T a_Max) { return (a_Value < a_Min) ? a_Min : ((a_Value > a_Max) ? a_Max : a_Value); } template auto ToUnsigned(T a_Val) { ASSERT(a_Val >= 0); return static_cast>(a_Val); } ================================================ FILE: Tools/GrownBiomeGenVisualiser/GrownBiomeGenVisualiser.cpp ================================================ // GrownBiomeGenVisualiser.cpp // Implements the main app entrypoint #include "Globals.h" #include #include #include #define PROT_INT_BUFFER_SIZE (130 * 130) #include "Generating/ProtIntGen.h" #include "fmt/printf.h" typedef int Color[3]; // Color is an array of 3 ints // Forward declarations, needed for GCC and Clang: void outputBitmapFile( const AString & a_FileName, unsigned a_ImageSizeX, unsigned a_ImageSizeY, const int * a_ColorIndices, unsigned a_IndicesSizeX, unsigned a_IndicesSizeY, const Color * a_Colors, size_t a_NumColors ); void initializeBiomeColors(void); void generateZoomLevels(int a_Seed); void generateSmoothLevels(int a_Seed); void generateExamples(int a_Seed); /** Color palette used for algorithm examples. No relevance to biomes whatsoever. */ static const Color spectrumColors[] = { {0, 0, 0}, {255, 0, 0}, {0, 255, 0}, {0, 0, 255}, {255, 255, 0}, {255, 0, 255}, {0, 255, 255}, }; /** Color palette used for displaying biome groups. */ static const Color biomeGroupColors[] = { /* bgOcean */ {0x00, 0x00, 0x70}, /* bgDesert */ {0xfa, 0x94, 0x18}, /* bgTemperate */ {0x05, 0x66, 0x21}, /* bgMountains */ {0x60, 0x60, 0x60}, /* bgIce */ {0xa0, 0xa0, 0xff}, }; /** Color palette used for outputting biome images. Initialized from biomeColorMap[] in initializeBiomeColors(). */ static Color biomeColors[255]; /** Map of biome -> color, used to initialize biomeColorMap[]. */ static const struct { EMCSBiome biome; Color color; } biomeColorMap[] = { { biOcean, { 0x00, 0x00, 0x70 }, }, { biPlains, { 0x8d, 0xb3, 0x60 }, }, { biDesert, { 0xfa, 0x94, 0x18 }, }, { biExtremeHills, { 0x60, 0x60, 0x60 }, }, { biForest, { 0x05, 0x66, 0x21 }, }, { biTaiga, { 0x0b, 0x66, 0x59 }, }, { biSwampland, { 0x2f, 0xff, 0xda }, }, { biRiver, { 0x30, 0x30, 0xaf }, }, { biHell, { 0x7f, 0x00, 0x00 }, }, { biSky, { 0x00, 0x7f, 0xff }, }, { biFrozenOcean, { 0xa0, 0xa0, 0xdf }, }, { biFrozenRiver, { 0xa0, 0xa0, 0xff }, }, { biIcePlains, { 0xff, 0xff, 0xff }, }, { biIceMountains, { 0xa0, 0xa0, 0xa0 }, }, { biMushroomIsland, { 0xff, 0x00, 0xff }, }, { biMushroomShore, { 0xa0, 0x00, 0xff }, }, { biBeach, { 0xfa, 0xde, 0x55 }, }, { biDesertHills, { 0xd2, 0x5f, 0x12 }, }, { biForestHills, { 0x22, 0x55, 0x1c }, }, { biTaigaHills, { 0x16, 0x39, 0x33 }, }, { biExtremeHillsEdge, { 0x7f, 0x8f, 0x7f }, }, { biJungle, { 0x53, 0x7b, 0x09 }, }, { biJungleHills, { 0x2c, 0x42, 0x05 }, }, { biJungleEdge, { 0x62, 0x8b, 0x17 }, }, { biDeepOcean, { 0x00, 0x00, 0x30 }, }, { biStoneBeach, { 0xa2, 0xa2, 0x84 }, }, { biColdBeach, { 0xfa, 0xf0, 0xc0 }, }, { biBirchForest, { 0x30, 0x74, 0x44 }, }, { biBirchForestHills, { 0x1f, 0x5f, 0x32 }, }, { biRoofedForest, { 0x40, 0x51, 0x1a }, }, { biColdTaiga, { 0x31, 0x55, 0x4a }, }, { biColdTaigaHills, { 0x59, 0x7d, 0x72 }, }, { biMegaTaiga, { 0x59, 0x66, 0x51 }, }, { biMegaTaigaHills, { 0x59, 0x66, 0x59 }, }, { biExtremeHillsPlus, { 0x50, 0x70, 0x50 }, }, { biSavanna, { 0xbd, 0xb2, 0x5f }, }, { biSavannaPlateau, { 0xa7, 0x9d, 0x64 }, }, { biMesa, { 0xd9, 0x45, 0x15 }, }, { biMesaPlateauF, { 0xb0, 0x97, 0x65 }, }, { biMesaPlateau, { 0xca, 0x8c, 0x65 }, }, // M variants: { biSunflowerPlains, { 0xb5, 0xdb, 0x88 }, }, { biDesertM, { 0xff, 0xbc, 0x40 }, }, { biExtremeHillsM, { 0x88, 0x88, 0x88 }, }, { biFlowerForest, { 0x2d, 0x8e, 0x49 }, }, { biTaigaM, { 0x33, 0x8e, 0x81 }, }, { biSwamplandM, { 0x07, 0xf9, 0xb2 }, }, { biIcePlainsSpikes, { 0xb4, 0xdc, 0xdc }, }, { biJungleM, { 0x7b, 0xa3, 0x31 }, }, { biJungleEdgeM, { 0x62, 0x8b, 0x17 }, }, { biBirchForestM, { 0x58, 0x9c, 0x6c }, }, { biBirchForestHillsM, { 0x47, 0x87, 0x5a }, }, { biRoofedForestM, { 0x68, 0x79, 0x42 }, }, { biColdTaigaM, { 0x24, 0x3f, 0x36 }, }, { biMegaSpruceTaiga, { 0x45, 0x4f, 0x3e }, }, { biMegaSpruceTaigaHills, { 0x45, 0x4f, 0x4e }, }, { biExtremeHillsPlusM, { 0x78, 0x98, 0x78 }, }, { biSavannaM, { 0xe5, 0xda, 0x87 }, }, { biSavannaPlateauM, { 0xa7, 0x9d, 0x74 }, }, { biMesaBryce, { 0xff, 0x6d, 0x3d }, }, { biMesaPlateauFM, { 0xd8, 0xbf, 0x8d }, }, { biMesaPlateauM, { 0xf2, 0xb4, 0x8d }, }, }; template void log(const char * a_Fmt, const Args & ... a_Args) { fmt::printf(a_Fmt, a_Args...); putchar('\n'); fflush(stdout); } void outputBitmapFile( const AString & a_FileName, unsigned a_ImageSizeX, unsigned a_ImageSizeY, const int * a_ColorIndices, unsigned a_IndicesSizeX, unsigned a_IndicesSizeY, const Color * a_Colors, size_t a_NumColors ) { std::ofstream f(a_FileName, std::ios::out | std::ios::binary); if (!f.good()) { log("Cannot open file %s for writing. Skipping.", a_FileName.c_str()); return; } f << "P3\r\n" << a_ImageSizeX << " " << a_ImageSizeY << "\r\n255\r\n"; unsigned oldIndY = 0; for (unsigned y = 0; y < a_ImageSizeY; y++) { unsigned indY = y * a_IndicesSizeY / a_ImageSizeY; if (oldIndY != indY) { // Output a horizontal divider line: for (unsigned x = 0; x < a_ImageSizeX; x++) { f << "128 128 128 "; } f << "\r\n"; oldIndY = indY; continue; } unsigned oldIndX = 0; for (unsigned x = 0; x < a_ImageSizeX; x++) { unsigned indX = x * a_IndicesSizeX / a_ImageSizeX; if (indX == oldIndX) { auto & color = a_Colors[a_ColorIndices[indX + a_IndicesSizeX * indY]]; f << color[0] << " " << color[1] << " " << color[2] << " "; } else { // vertical divider line: f << "128 128 128 "; } oldIndX = indX; } f << "\r\n"; } } /** Initializes biomeColors[] using the biomeColorMap[]. */ void initializeBiomeColors(void) { // Initialize all colors to red, so that anything unassigned is visible: for (size_t i = 0; i < ARRAYCOUNT(biomeColors); i++) { auto & color = biomeColors[i]; color[0] = 0; color[1] = 0xff; color[2] = 0; } // Initialize per-biome: for (size_t i = 0; i < ARRAYCOUNT(biomeColorMap); i++) { auto & dst = biomeColors[biomeColorMap[i].biome]; const auto & src = biomeColorMap[i].color; dst[0] = src[0]; dst[1] = src[1]; dst[2] = src[2]; } } /** Generates a series of images showing the "zoom" effect of the IntGen zoom operation. Each image is the same size, the integer arrays are scaled to fit the image. */ void generateZoomLevels(int a_Seed) { log("Generating zoom levels..."); const unsigned NumImages = 7; ///< Number of images to generate. The more images, the larger they will be const unsigned maxArrSize = (1 << NumImages) + 1; for (unsigned i = 1; i <= NumImages; i++) { unsigned arrSize = (1 << i) + 1; // Dimensions of the actually generated array ASSERT(arrSize <= maxArrSize); int workspace[maxArrSize * maxArrSize]; // Workspace for the generated array // Chain the zoom operation as many times as the image number: std::shared_ptr gen = std::make_shared(a_Seed, static_cast(ARRAYCOUNT(spectrumColors) + 1)); for (unsigned j = 1; j < i; j++) { gen = std::make_shared(a_Seed + static_cast(j), gen); } gen->GetInts(0, 0, arrSize, arrSize, workspace); // Output to a bitmap file: AString fnam = fmt::format(FMT_STRING("zoomedgrown_{}.pbm"), i); outputBitmapFile(fnam, 257, 257, workspace, arrSize, arrSize, spectrumColors, ARRAYCOUNT(spectrumColors)); log(" zoom level %u complete", i); } // for i - Image } void generateSmoothLevels(int a_Seed) { log("Generating smooth levels..."); const unsigned NumImages = 7; ///< Number of images to generate. The more images, the larger they will be const unsigned maxArrSize = 65; ///< Size of the underlying generated array // Initialize the underlying generator: std::shared_ptr underlyingGen = std::make_shared(a_Seed, static_cast(ARRAYCOUNT(spectrumColors) + 1)); for (int j = 1; j < 4; j++) { underlyingGen = std::make_shared(a_Seed + j, underlyingGen); } // Generate smooth levels: for (unsigned i = 1; i <= NumImages; i++) { unsigned arrSize = maxArrSize - 2 * i; // Dimensions of the actually generated array int workspace[maxArrSize * maxArrSize]; // Workspace for the generated array // Chain the zoom operation as many times as the image number: std::shared_ptr gen = underlyingGen; for (unsigned j = 1; j < i; j++) { gen = std::make_shared(a_Seed, gen); } gen->GetInts(static_cast(i), static_cast(i), arrSize, arrSize, workspace); // Output to a bitmap file: AString fnam = fmt::format(FMT_STRING("smoothedgrown_{}.ppm"), i); outputBitmapFile(fnam, 257, 257, workspace, arrSize, arrSize, spectrumColors, ARRAYCOUNT(spectrumColors)); log(" smooth level %u complete", i); } // for i - Image } void generateExamples(int a_Seed) { log("Generating examples"); const int maxArrSize = 65; const int inArrSize = 24; const int imgSize = 256; // Create the inputs: auto in1 = std::make_shared(a_Seed + 1, std::make_shared(a_Seed + 2000, 200, std::make_shared(a_Seed + 9, 300, bgOcean, std::make_shared(a_Seed + 2, std::make_shared(a_Seed + 1, 30 ))))); auto in2 = std::make_shared(a_Seed + 1, std::make_shared(in1 )); auto in3 = std::make_shared(a_Seed + 1, std::make_shared(a_Seed + 2, std::make_shared(a_Seed + 3000, in2 ))); auto inAlt = std::make_shared(a_Seed, std::make_shared(a_Seed, 30 )); auto inRiver = std::make_shared(a_Seed, in2); int workspace[maxArrSize * maxArrSize]; in1->GetInts(0, 0, inArrSize, inArrSize, workspace); outputBitmapFile("grownexample_in1.ppm", imgSize, imgSize, workspace, inArrSize, inArrSize, biomeGroupColors, ARRAYCOUNT(biomeGroupColors)); log(" Created example input 1"); in2->GetInts(0, 0, inArrSize, inArrSize, workspace); outputBitmapFile("grownexample_in2.ppm", imgSize, imgSize, workspace, inArrSize, inArrSize, biomeGroupColors, ARRAYCOUNT(biomeGroupColors)); log(" Created example input 2"); in3->GetInts(0, 0, inArrSize, inArrSize, workspace); outputBitmapFile("grownexample_in3.ppm", imgSize, imgSize, workspace, inArrSize, inArrSize, biomeColors, ARRAYCOUNT(biomeColors)); log(" Created example input 3"); inAlt->GetInts(0, 0, inArrSize, inArrSize, workspace); outputBitmapFile("grownexample_in_alt.ppm", imgSize, imgSize, workspace, inArrSize, inArrSize, biomeGroupColors, ARRAYCOUNT(biomeGroupColors)); log(" Created example input alt"); inRiver->GetInts(0, 0, inArrSize, inArrSize, workspace); outputBitmapFile("grownexample_in_river.ppm", imgSize, imgSize, workspace, inArrSize, inArrSize, biomeColors, ARRAYCOUNT(biomeColors)); log(" Created example input river"); // Shortcuts for colormaps used for the outputs: struct ColorMap { const Color * colors; size_t count; }; static const ColorMap cmGroups = { biomeGroupColors, ARRAYCOUNT(biomeGroupColors) }; static const ColorMap cmBiomes = { biomeColors, ARRAYCOUNT(biomeColors) }; // Create the result generators: struct { const char * name; unsigned size; int offset; const ColorMap & colormap; std::shared_ptr gen; } gens[] = { {"add_islands", inArrSize, 0, cmGroups, std::make_shared (a_Seed, 400, in1)}, {"alt_biomes", inArrSize, 0, cmBiomes, std::make_shared(a_Seed, inAlt, in3)}, {"beaches", inArrSize - 2, 1, cmBiomes, std::make_shared (in3)}, {"biome_edges", inArrSize - 2, 1, cmBiomes, std::make_shared (a_Seed, in3)}, {"biomes", inArrSize, 0, cmBiomes, std::make_shared (a_Seed, in2)}, {"grp_edges", inArrSize - 2, 0, cmGroups, std::make_shared(in1)}, {"m_biomes", inArrSize, 0, cmBiomes, std::make_shared (a_Seed, inAlt, in3)}, {"mix_river", inArrSize, 0, cmBiomes, std::make_shared (in3, inRiver)}, {"river", inArrSize - 2, 1, cmBiomes, inRiver}, {"set_rnd", inArrSize, 0, cmBiomes, std::make_shared (a_Seed, 500, bgOcean, in3)}, {"smooth", inArrSize - 2, 1, cmBiomes, std::make_shared (a_Seed, in3)}, {"zoom", inArrSize * 2 - 1, 0, cmBiomes, std::make_shared (a_Seed, in3)}, }; // Create the outputs: for (const auto & gen: gens) { gen.gen->GetInts(gen.offset, gen.offset, gen.size, gen.size, workspace); AString fnam = fmt::format(FMT_STRING("grownexample_{}.ppm"), gen.name); outputBitmapFile(fnam, 256, 256, workspace, gen.size, gen.size, gen.colormap.colors, gen.colormap.count); log(" Created example \"%s\"", gen.name); } // for gen - gens[] log("Examples generated"); } int main(int argc, char ** argv) { log("GrownBiomeGenVisualiser starting"); // Parse the seed from the command line, if present: int seed; if (argc > 1) { if (!StringToInteger(argv[1], seed)) { log("Cannot parse seed from \"%s\", bailing out.", argv[1]); return 1; } } else { // Get a random seed: std::random_device rd; seed = static_cast(rd()); } log("Seed = %d", seed); initializeBiomeColors(); generateZoomLevels(seed); generateSmoothLevels(seed); generateExamples(seed); log("GrownBiomeGenVisualiser finished"); return 0; } ================================================ FILE: Tools/GrownBiomeGenVisualiser/README.md ================================================ GrownBiomeGenVisualiser ---- This project aims to provide the visualisation of "Grown" biome generator used in Cuberite. It uses the generator to generate several bitmaps showcasing the generator; these images are then used in the generator documentation ($/docs/Generator.html) ================================================ FILE: Tools/MCADefrag/.gitignore ================================================ *.mca ================================================ FILE: Tools/MCADefrag/CMakeLists.txt ================================================ cmake_minimum_required(VERSION 3.13) project (MCADefrag) find_package(Threads REQUIRED) # Set include paths to the used libraries: include_directories(SYSTEM "../../lib") include_directories("../../src") function(flatten_files arg1) set(res "") foreach(f ${${arg1}}) get_filename_component(f ${f} ABSOLUTE) list(APPEND res ${f}) endforeach() set(${arg1} "${res}" PARENT_SCOPE) endfunction() # Include the shared files: set(SHARED_SRC ../../src/StringCompression.cpp ../../src/StringUtils.cpp ../../src/LoggerListeners.cpp ../../src/Logger.cpp ) set(SHARED_HDR ../../src/ByteBuffer.h ../../src/StringUtils.h ) flatten_files(SHARED_SRC) flatten_files(SHARED_HDR) source_group("Shared" FILES ${SHARED_SRC} ${SHARED_HDR}) set(SHARED_OSS_SRC ../../src/OSSupport/CriticalSection.cpp ../../src/OSSupport/Event.cpp ../../src/OSSupport/File.cpp ../../src/OSSupport/IsThread.cpp ../../src/OSSupport/StackTrace.cpp ../../src/OSSupport/WinStackWalker.cpp ) set(SHARED_OSS_HDR ../../src/OSSupport/CriticalSection.h ../../src/OSSupport/Event.h ../../src/OSSupport/File.h ../../src/OSSupport/IsThread.h ../../src/OSSupport/StackTrace.h ../../src/OSSupport/WinStackWalker.h ) flatten_files(SHARED_OSS_SRC) flatten_files(SHARED_OSS_HDR) source_group("Shared\\OSSupport" FILES ${SHARED_OSS_SRC} ${SHARED_OSS_HDR}) # Include the main source files: set(SOURCES MCADefrag.cpp ) set(HEADERS MCADefrag.h ) source_group("" FILES ${SOURCES} ${HEADERS}) add_executable(MCADefrag ${SOURCES} ${HEADERS} ${SHARED_SRC} ${SHARED_HDR} ${SHARED_OSS_SRC} ${SHARED_OSS_HDR} ) target_link_libraries(MCADefrag fmt::fmt libdeflate Threads::Threads) if (WIN32) target_link_libraries(MCADefrag ws2_32) endif() include(../../SetFlags.cmake) set_exe_flags(MCADefrag) ================================================ FILE: Tools/MCADefrag/MCADefrag.cpp ================================================ // MCADefrag.cpp // Implements the main app entrypoint and the cMCADefrag class representing the entire app #include "Globals.h" #include "MCADefrag.h" #include "Logger.h" #include "LoggerSimple.h" #include "LoggerListeners.h" // An array of 4096 zero bytes, used for writing the padding static const Byte g_Zeroes[4096] = {0}; int main(int argc, char ** argv) { auto consoleLogListener = MakeConsoleListener(false); auto consoleAttachment = cLogger::GetInstance().AttachListener(std::move(consoleLogListener)); auto fileLogListenerRet = MakeFileListener(); if (!fileLogListenerRet.first) { LOGERROR("Failed to open log file, aborting"); return EXIT_FAILURE; } auto fileAttachment = cLogger::GetInstance().AttachListener(std::move(fileLogListenerRet.second)); cLogger::InitiateMultithreading(); cMCADefrag Defrag; if (!Defrag.Init(argc, argv)) { return EXIT_FAILURE; } Defrag.Run(); return 0; } //////////////////////////////////////////////////////////////////////////////// // cMCADefrag: cMCADefrag::cMCADefrag(void) : m_NumThreads(4), m_ShouldRecompress(true) { } bool cMCADefrag::Init(int argc, char ** argv) { // Nothing needed yet return true; } void cMCADefrag::Run(void) { // Fill the queue with MCA files m_Queue = cFile::GetFolderContents("."); // Start the processing threads: for (int i = 0; i < m_NumThreads; i++) { StartThread(); } // Wait for all the threads to finish: while (!m_Threads.empty()) { m_Threads.front()->Stop(); delete m_Threads.front(); m_Threads.pop_front(); } } void cMCADefrag::StartThread(void) { cThread * Thread = new cThread(*this); m_Threads.push_back(Thread); Thread->Start(); } AString cMCADefrag::GetNextFileName(void) { cCSLock Lock(m_CS); if (m_Queue.empty()) { return AString(); } AString res = m_Queue.back(); m_Queue.pop_back(); return res; } //////////////////////////////////////////////////////////////////////////////// // cMCADefrag::cThread: cMCADefrag::cThread::cThread(cMCADefrag & a_Parent) : super("MCA Defragmentor"), m_Parent(a_Parent), m_IsChunkUncompressed(false), m_Compressor(12) // Set the highest compression factor { } void cMCADefrag::cThread::Execute(void) { for (;;) { AString FileName = m_Parent.GetNextFileName(); if (FileName.empty()) { return; } ProcessFile(FileName); } } void cMCADefrag::cThread::ProcessFile(const AString & a_FileName) { // Filter out non-MCA files: if ((a_FileName.length() < 4) || (a_FileName.substr(a_FileName.length() - 4, 4) != ".mca")) { return; } LOGINFO("%s", a_FileName.c_str()); // Open input and output files: AString OutFileName = a_FileName + ".new"; cFile In, Out; if (!In.Open(a_FileName, cFile::fmRead)) { LOGWARNING("Cannot open file %s for reading, skipping file.", a_FileName.c_str()); return; } if (!Out.Open(OutFileName.c_str(), cFile::fmWrite)) { LOGWARNING("Cannot open file %s for writing, skipping file.", OutFileName.c_str()); return; } // Read the Locations and Timestamps from the input file: Byte Locations[4096]; UInt32 Timestamps[1024]; if (In.Read(Locations, sizeof(Locations)) != sizeof(Locations)) { LOGWARNING("Cannot read Locations in file %s, skipping file.", a_FileName.c_str()); return; } if (In.Read(Timestamps, sizeof(Timestamps)) != sizeof(Timestamps)) { LOGWARNING("Cannot read Timestamps in file %s, skipping file.", a_FileName.c_str()); return; } // Write dummy Locations to the Out file (will be overwritten once the correct ones are known) if (Out.Write(Locations, sizeof(Locations)) != sizeof(Locations)) { LOGWARNING("Cannot write Locations to file %s, skipping file.", OutFileName.c_str()); return; } m_CurrentSectorOut = 2; // Write a copy of the Timestamps into the Out file: if (Out.Write(Timestamps, sizeof(Timestamps)) != sizeof(Timestamps)) { LOGWARNING("Cannot write Timestamps to file %s, skipping file.", OutFileName.c_str()); return; } // Process each chunk: for (size_t i = 0; i < 1024; i++) { size_t idx = i * 4; if ( (Locations[idx] == 0) && (Locations[idx + 1] == 0) && (Locations[idx + 2] == 0) && (Locations[idx + 3] == 0) ) { // Chunk not present continue; } m_IsChunkUncompressed = false; if (!ReadChunk(In, Locations + idx)) { LOGWARNING("Cannot read chunk #%d from file %s. Skipping file.", i, a_FileName.c_str()); return; } if (!WriteChunk(Out, Locations + idx)) { LOGWARNING("Cannot write chunk #%d to file %s. Skipping file.", i, OutFileName.c_str()); return; } } // Write the new Locations into the MCA header: Out.Seek(0); if (Out.Write(Locations, sizeof(Locations)) != sizeof(Locations)) { LOGWARNING("Cannot write updated Locations to file %s, skipping file.", OutFileName.c_str()); return; } // Close the files, delete orig, rename new: In.Close(); Out.Close(); cFile::Delete(a_FileName); cFile::Rename(OutFileName, a_FileName); } bool cMCADefrag::cThread::ReadChunk(cFile & a_File, const Byte * a_LocationRaw) { int SectorNum = (a_LocationRaw[0] << 16) | (a_LocationRaw[1] << 8) | a_LocationRaw[2]; int SizeInSectors = a_LocationRaw[3] * (4 KiB); if (a_File.Seek(SectorNum * (4 KiB)) < 0) { LOGWARNING("Failed to seek to chunk data - file pos %llu (%d KiB, %.02f MiB)!", static_cast(SectorNum) * (4 KiB), SectorNum * 4, static_cast(SectorNum) / 256 ); return false; } // Read the exact size: Byte Buf[4]; if (a_File.Read(Buf, 4) != 4) { LOGWARNING("Failed to read chunk data length"); return false; } m_CompressedChunkDataSize = (Buf[0] << 24) | (Buf[1] << 16) | (Buf[2] << 8) | Buf[3]; if ((m_CompressedChunkDataSize > SizeInSectors) || (m_CompressedChunkDataSize < 0)) { LOGWARNING("Invalid chunk data - SizeInSectors (%d) smaller that RealSize (%d)", SizeInSectors, m_CompressedChunkDataSize); return false; } // Read the data: if (a_File.Read(m_CompressedChunkData, static_cast(m_CompressedChunkDataSize)) != m_CompressedChunkDataSize) { LOGWARNING("Failed to read chunk data!"); return false; } // Uncompress the data if recompression is active if (m_Parent.m_ShouldRecompress) { m_IsChunkUncompressed = UncompressChunk(); if (!m_IsChunkUncompressed) { LOGINFO("Chunk failed to uncompress, will be copied verbatim instead."); } } return true; } bool cMCADefrag::cThread::WriteChunk(cFile & a_File, Byte * a_LocationRaw) { // Recompress the data if recompression is active: if (m_Parent.m_ShouldRecompress) { if (!CompressChunk()) { LOGINFO("Chunk failed to recompress, will be coped verbatim instead."); } } // Update the Location: a_LocationRaw[0] = static_cast(m_CurrentSectorOut >> 16); a_LocationRaw[1] = (m_CurrentSectorOut >> 8) & 0xff; a_LocationRaw[2] = m_CurrentSectorOut & 0xff; a_LocationRaw[3] = static_cast((m_CompressedChunkDataSize + (4 KiB) + 3) / (4 KiB)); // +3 because the m_CompressedChunkDataSize doesn't include the exact-length m_CurrentSectorOut += a_LocationRaw[3]; // Write the data length: Byte Buf[4]; Buf[0] = static_cast(m_CompressedChunkDataSize >> 24); Buf[1] = (m_CompressedChunkDataSize >> 16) & 0xff; Buf[2] = (m_CompressedChunkDataSize >> 8) & 0xff; Buf[3] = m_CompressedChunkDataSize & 0xff; if (a_File.Write(Buf, 4) != 4) { LOGWARNING("Failed to write chunk length!"); return false; } // Write the data: if (a_File.Write(m_CompressedChunkData, static_cast(m_CompressedChunkDataSize)) != m_CompressedChunkDataSize) { LOGWARNING("Failed to write chunk data!"); return false; } // Pad onto the next sector: int NumPadding = a_LocationRaw[3] * 4096 - (m_CompressedChunkDataSize + 4); ASSERT(NumPadding >= 0); if ((NumPadding > 0) && (a_File.Write(g_Zeroes, static_cast(NumPadding)) != NumPadding)) { LOGWARNING("Failed to write padding"); return false; } return true; } bool cMCADefrag::cThread::UncompressChunk(void) { switch (m_CompressedChunkData[0]) { case COMPRESSION_GZIP: return UncompressChunkGzip(); case COMPRESSION_ZLIB: return UncompressChunkZlib(); } LOGINFO("Chunk is compressed with in an unknown algorithm"); return false; } bool cMCADefrag::cThread::UncompressChunkGzip(void) { // TODO // This format is not used in practice return false; } bool cMCADefrag::cThread::UncompressChunkZlib(void) { try { // Uncompress the data const auto ExtractedData = m_Extractor.ExtractZLib( { reinterpret_cast(m_CompressedChunkData + 1), // The first byte is the compression method, skip it static_cast(m_CompressedChunkDataSize - 1) }); const auto Extracted = ExtractedData.GetView(); if (Extracted.size() > MAX_RAW_CHUNK_DATA_SIZE) { LOGINFO("Too much data for the internal decompression buffer!"); return false; } std::copy(Extracted.begin(), Extracted.end(), reinterpret_cast(m_RawChunkData)); m_RawChunkDataSize = static_cast(Extracted.size()); return true; } catch (const std::exception & Oops) { LOGWARNING("Failed to uncompress chunk data. %s", Oops.what()); return false; } } bool cMCADefrag::cThread::CompressChunk(void) { try { // Compress the data (using the highest compression factor, as set in the constructor) const auto CompressedData = m_Compressor.CompressZLib( { reinterpret_cast(m_RawChunkData), static_cast(m_RawChunkDataSize) }); const auto Compressed = CompressedData.GetView(); // Check that the compressed data can fit: if (Compressed.size() > MAX_COMPRESSED_CHUNK_DATA_SIZE) { LOGINFO("Too much data for the internal compression buffer!"); return false; } m_CompressedChunkData[0] = COMPRESSION_ZLIB; std::copy(Compressed.begin(), Compressed.end(), reinterpret_cast(m_CompressedChunkData + 1)); m_CompressedChunkDataSize = static_cast(Compressed.size()) + 1; return true; } catch (const std::exception & Oops) { LOGWARNING("Recompression failed. %s", Oops.what()); return false; } } ================================================ FILE: Tools/MCADefrag/MCADefrag.h ================================================ // MCADefrag.h // Interfaces to the cMCADefrag class encapsulating the entire app #pragma once #include "OSSupport/IsThread.h" #include "StringCompression.h" class cMCADefrag { public: enum { MAX_COMPRESSED_CHUNK_DATA_SIZE = (1 MiB), MAX_RAW_CHUNK_DATA_SIZE = (100 MiB), } ; cMCADefrag(void); /** Reads the cmdline params and initializes the app. Returns true if the app should continue, false if not. */ bool Init(int argc, char ** argv); /** Runs the entire app. */ void Run(void); protected: /** A single thread processing MCA files from the queue */ class cThread : public cIsThread { typedef cIsThread super; public: cThread(cMCADefrag & a_Parent); protected: /** The compression methods, as specified by the MCA compression method byte. */ enum { COMPRESSION_GZIP = 1, COMPRESSION_ZLIB = 2, } ; cMCADefrag & m_Parent; /** The current compressed chunk data. Valid after a successful ReadChunk(). This contains only the compression method byte and the compressed data, but not the exact-length preceding the data in the MCA file. */ unsigned char m_CompressedChunkData[MAX_COMPRESSED_CHUNK_DATA_SIZE]; /** Size of the actual current compressed chunk data, excluding the 4 exact-length bytes. This is the amount of bytes in m_CompressedChunkData[] that are valid. */ int m_CompressedChunkDataSize; /** The current raw chunk data. Valid after a successful ReadChunk(), if recompression is active. */ unsigned char m_RawChunkData[MAX_RAW_CHUNK_DATA_SIZE]; /** Size of the actual current raw chunk data. */ int m_RawChunkDataSize; /** Number of the sector where the next chunk will be written by WriteChunk(). */ int m_CurrentSectorOut; /** Set to true when the chunk has been successfully uncompressed. Only used if recompression is active. WriteChunk() tests this flag to decide whether to call Compress(). */ bool m_IsChunkUncompressed; /** An instance of the compressor. */ Compression::Compressor m_Compressor; /** An instance of the extractor. */ Compression::Extractor m_Extractor; /** Processes the specified file. */ void ProcessFile(const AString & a_FileName); /** Reads the chunk data into m_CompressedChunkData. Calls DecompressChunkData() if recompression is active. a_LocationRaw is the pointer to the first byte of the Location data in the MCA header. Returns true if successful. */ bool ReadChunk(cFile & a_File, const Byte * a_LocationRaw); /** Writes the chunk data from m_CompressedData or m_RawChunkData (performing recompression) into file. Calls CompressChunkData() for the actual compression, if recompression is active. a_LocationRaw is the pointer to the first byte of the Location data to be put into the MCA header, the chunk's location is stored in that memory area. Updates m_CurrentSectorOut. Returns true if successful. */ bool WriteChunk(cFile & a_File, Byte * a_LocationRaw); /** Uncompresses the chunk data from m_CompressedChunkData into m_RawChunkData. Returns true if successful, false on failure. */ bool UncompressChunk(void); /** Uncompresses the chunk data from m_CompressedChunkData into m_RawChunkData, using Gzip. Returns true if successful, false on failure. */ bool UncompressChunkGzip(void); /** Uncompresses the chunk data from m_CompressedChunkData into m_RawChunkData, using Zlib. Returns true if successful, false on failure. */ bool UncompressChunkZlib(void); /** Compresses the chunk data from m_RawChunkData into m_CompressedChunkData. Returns true if successful, false on failure. */ bool CompressChunk(void); // cIsThread overrides: virtual void Execute(void) override; } ; typedef std::list cThreads; /** The mutex protecting m_Files agains multithreaded access. */ cCriticalSection m_CS; /** The queue of MCA files to be processed by the threads. Protected by m_CS. */ AStringVector m_Queue; /** List of threads that the server has running. */ cThreads m_Threads; /** The number of threads that should be started. Configurable on the command line. */ int m_NumThreads; /** If set to true, the chunk data is recompressed while saving each MCA file. */ bool m_ShouldRecompress; /** Starts a new processing thread and adds it to cThreads. */ void StartThread(void); /** Retrieves one file from the queue (and removes it from the queue). Returns an empty string when queue empty. */ AString GetNextFileName(void); } ; ================================================ FILE: Tools/MemDumpAnalysis/.gitignore ================================================ Debug/ logs/ Release/ ================================================ FILE: Tools/MemDumpAnalysis/Globals.cpp ================================================ // Globals.cpp // Used for precompiled header generation #include "Globals.h" ================================================ FILE: Tools/MemDumpAnalysis/Globals.h ================================================ // Globals.h // Used for precompiled header generation #pragma once #include "../../src/Globals.h" /* // System headers: #include "targetver.h" #include // STL headers: #include #include #include #include // Common: #include "../src/StringUtils.h" #include "../src/OSSupport/File.h" */ // Libraries: #include "expat/expat.h" ================================================ FILE: Tools/MemDumpAnalysis/MemDumpAnalysis.cpp ================================================ // MemDumpAnalysis.cpp // Defines the entry point for the console application. #include "Globals.h" #ifdef _WIN32 #pragma comment(lib, "ws2_32.lib") // Needed for StringUtils' RawBEToUtf8() et al. #endif // _WIN32 typedef std::set AStringSet; class cFunction { public: int m_Size; ///< Sum of memory block sizes allocated by this function or its children int m_Count; ///< Total number of memory blocks allocated by this function or its children AStringSet m_ChildrenNames; cFunction(void) : m_Size(0), m_Count(0) { } } ; typedef std::map FunctionMap; int g_CurrentID = 0; int g_CurrentSize = 0; FunctionMap g_FnMap; AString g_PrevFunctionName; bool IsFnBlackListed(const char * a_FnName) { static const char * BlackList[] = { "MyAllocHook", "_heap_alloc_dbg_impl", "_nh_malloc_dbg_impl", "_nh_malloc_dbg", "malloc", "operator new", "_malloc_dbg", "realloc_help", "_realloc_dbg", "realloc", "l_alloc", "luaM_realloc_", "", } ; for (int i = 0; i < ARRAYCOUNT(BlackList); i++) { if (strcmp(BlackList[i], a_FnName) == 0) { return true; } } return false; } const char * FindAttr(const char ** a_Attrs, const char * a_AttrName) { for (const char ** Attr = a_Attrs; *Attr != NULL; Attr += 2) { if (strcmp(*Attr, a_AttrName) == 0) { return *(Attr + 1); } } // for Attr - a_Attrs[] return NULL; } void OnStartElement(void * a_Data, const char * a_Element, const char ** a_Attrs) { if (strcmp(a_Element, "LEAK") == 0) { const char * attrID = FindAttr(a_Attrs, "requestID"); const char * attrSize = FindAttr(a_Attrs, "size"); g_CurrentID = atoi((attrID == NULL) ? "-1" : attrID); g_CurrentSize = atoi((attrSize == NULL) ? "-1" : attrSize); g_PrevFunctionName.clear(); return; } if (strcmp(a_Element, "STACKENTRY") == 0) { const char * fnName = FindAttr(a_Attrs, "decl"); if (fnName == NULL) { g_CurrentID = -1; g_CurrentSize = -1; return; } if (g_CurrentSize < 0) { return; } if (IsFnBlackListed(fnName)) { return; } AString FunctionName = fnName; cFunction & Function = g_FnMap[FunctionName]; Function.m_Size += g_CurrentSize; Function.m_Count += 1; if (!g_PrevFunctionName.empty()) { Function.m_ChildrenNames.insert(g_PrevFunctionName); } std::swap(g_PrevFunctionName, FunctionName); // We only care about moving FunctionName into g_PrevFunctionName return; } } void OnEndElement(void * a_Data, const char * a_Element) { if (strcmp(a_Element, "LEAK") == 0) { g_CurrentID = -1; g_CurrentSize = -1; return; } } bool CompareFnInt(const std::pair & a_First, const std::pair & a_Second) { return (a_First.second < a_Second.second); } void WriteSizeStatistics(void) { typedef std::vector > StringIntPairs; StringIntPairs FnSizes; cFile f("memdump_totals.txt", cFile::fmWrite); if (!f.IsOpen()) { LOGERROR("Cannot open memdump_totals.txt"); return; } for (FunctionMap::iterator itr = g_FnMap.begin(), end = g_FnMap.end(); itr != end; ++itr) { FnSizes.push_back(std::pair(itr->first, itr->second.m_Size)); } // for itr - g_FnSizes[] std::sort(FnSizes.begin(), FnSizes.end(), CompareFnInt); for (StringIntPairs::const_iterator itr = FnSizes.begin(), end = FnSizes.end(); itr != end; ++itr) { f.Printf("%d\t%s\n", itr->second, itr->first.c_str()); } // for itr - FnSizes[] } void WriteCountStatistics(void) { typedef std::vector > StringIntPairs; StringIntPairs FnCounts; cFile f("memdump_counts.txt", cFile::fmWrite); if (!f.IsOpen()) { LOGERROR("Cannot open memdump_counts.txt"); return; } for (FunctionMap::iterator itr = g_FnMap.begin(), end = g_FnMap.end(); itr != end; ++itr) { FnCounts.push_back(std::pair(itr->first, itr->second.m_Count)); } // for itr - g_FnSizes[] std::sort(FnCounts.begin(), FnCounts.end(), CompareFnInt); for (StringIntPairs::const_iterator itr = FnCounts.begin(), end = FnCounts.end(); itr != end; ++itr) { f.Printf("%d\t%s\n", itr->second, itr->first.c_str()); } // for itr - FnSizes[] } AString HTMLEscape(const AString & a_Text) { AString res; res.reserve(a_Text.size()); size_t len = a_Text.length(); for (size_t i = 0; i < len; i++) { switch (a_Text[i]) { case '<': res.append("<
    "); break; case '>': res.append("
    >"); break; case '&': res.append("&"); break; default: { res.push_back(a_Text[i]); } } } // for i - a_Text[] return res; } void WriteDotGraph(void) { cFile f("memdump.dot", cFile::fmWrite); if (!f.IsOpen()) { LOGERROR("Cannot open memdump.dot"); return; } f.Printf("digraph {\n\tnode [shape=plaintext]\n\n"); for (FunctionMap::const_iterator itrF = g_FnMap.begin(), endF = g_FnMap.end(); itrF != endF; ++itrF) { f.Printf("\t\"%s\" [label=<%s
    %d bytes (%d KiB)
    %d blocks>]\n", itrF->first.c_str(), HTMLEscape(itrF->first).c_str(), itrF->second.m_Size, (itrF->second.m_Size + 1023) / 1024, itrF->second.m_Count ); const AStringSet & Children = itrF->second.m_ChildrenNames; for (AStringSet::const_iterator itrN = Children.begin(), endN = Children.end(); itrN != endN; ++itrN) { f.Printf("\t\t\"%s\" -> \"%s\"\n", itrF->first.c_str(), itrN->c_str()); } f.Printf("\n"); } // for itr f.Printf("}\n"); } int main(int argc, char * argv[]) { // Open the dump file: cFile f("memdump.xml", cFile::fmRead); if (!f.IsOpen()) { printf("Cannot open memdump.xml\n"); return 1; } // Create the XML parser: XML_Parser Parser = XML_ParserCreate(NULL); XML_SetElementHandler(Parser, OnStartElement, OnEndElement); // Feed the file through XML parser: char Buffer[512 KiB]; while (true) { int NumBytes = f.Read(Buffer, sizeof(Buffer)); if (NumBytes <= 0) { break; } XML_Parse(Parser, Buffer, NumBytes, false); putc('.', stdout); } XML_Parse(Parser, "", 0, true); f.Close(); // Output the statistics WriteSizeStatistics(); WriteCountStatistics(); WriteDotGraph(); return 0; } ================================================ FILE: Tools/MemDumpAnalysis/targetver.h ================================================ // targetver.h // Used by MSWin builds to target the appropriate OS version #pragma once // The following macros define the minimum required platform. The minimum required platform // is the earliest version of Windows, Internet Explorer etc. that has the necessary features to run // your application. The macros work by enabling all features available on platform versions up to and // including the version specified. // Modify the following defines if you have to target a platform prior to the ones specified below. // Refer to MSDN for the latest info on corresponding values for different platforms. #ifndef _WIN32_WINNT // Specifies that the minimum required platform is Windows Vista. #define _WIN32_WINNT 0x0600 // Change this to the appropriate value to target other versions of Windows. #endif ================================================ FILE: Tools/NoiseSpeedTest/CMakeLists.txt ================================================ project (NoiseSpeedTest) # Set include paths to the used libraries: include_directories(SYSTEM "../../lib") include_directories("../../src") # Include the shared files: set(SHARED_SRC ../../src/Logger.cpp ../../src/LoggerListeners.cpp ../../src/OSSupport/CriticalSection.cpp ../../src/OSSupport/File.cpp ../../src/OSSupport/StackTrace.cpp ../../src/OSSupport/WinStackWalker.cpp ../../src/Noise/Noise.cpp ../../src/StringUtils.cpp ) set(SHARED_HDR ../../src/Noise/Noise.h ../../src/Noise/OctavedNoise.h ../../src/Noise/RidgedNoise.h ../../src/OSSupport/CriticalSection.h ../../src/OSSupport/File.h ../../src/OSSupport/StackTrace.h ../../src/OSSupport/WinStackWalker.h ../../src/StringUtils.h ) source_group("Shared" FILES ${SHARED_SRC} ${SHARED_HDR}) # Include the main source files: set(SOURCES NoiseSpeedTest.cpp ) set(HEADERS NoiseSpeedTest.h SimplexNoise.h ) source_group("" FILES ${SOURCES} ${HEADERS}) add_executable(NoiseSpeedTest ${SOURCES} ${HEADERS} ${SHARED_SRC} ${SHARED_HDR} ) target_link_libraries(NoiseSpeedTest fmt::fmt) if (WIN32) target_link_libraries(NoiseSpeedTest ws2_32) endif() set_target_properties( NoiseSpeedTest PROPERTIES FOLDER Tools ) include(../../SetFlags.cmake) set_exe_flags(NoiseSpeedTest) ================================================ FILE: Tools/NoiseSpeedTest/NoiseSpeedTest.cpp ================================================ // NoiseSpeedTest.cpp // Implements the main app entrypoint /* This program compares the performance of the highly-optimized noise implementation in Cuberite, and the Simplex noise. Since the Simplex noise is not yet implemented in Cuberite, an own implementation is provided. Also, the performance difference between using a float and double as datatype is measured, by using a templatized Simplex noise. The testing is done on a usage of the generator that is typical for the Cuberite's terrain generator: generate a 3D array of numbers with not much variance in the coords. The exact sizes and coord ranges were adapted from the cNoise3DComposable generator. */ #include "Globals.h" #include "Noise/Noise.h" #include "Noise/InterpolNoise.h" #include "SimplexNoise.h" /** The sizes of the interpolated noise that are calculated: */ static const int SIZE_X = 33; static const int SIZE_Y = 5; static const int SIZE_Z = 5; static void measureClassicNoise(int a_NumIterations) { cInterp5DegNoise noise(1); NOISE_DATATYPE total = 0; auto timeStart = std::chrono::high_resolution_clock::now(); for (int i = 0; i < a_NumIterations; ++i) { NOISE_DATATYPE out[SIZE_X * SIZE_Y * SIZE_Z]; int blockX = i * 16; int blockZ = i * 16; NOISE_DATATYPE startX = 0; NOISE_DATATYPE endX = 257 / 80.0f; NOISE_DATATYPE startY = blockX / 40.0f; NOISE_DATATYPE endY = (blockX + 16) / 40.0f; NOISE_DATATYPE startZ = blockZ / 40.0f; NOISE_DATATYPE endZ = (blockZ + 16) / 40.0f; noise.Generate3D(out, SIZE_X, SIZE_Y, SIZE_Z, startX, endX, startY, endY, startZ, endZ); total += out[0]; // Do not let the optimizer optimize the whole calculation away } auto timeEnd = std::chrono::high_resolution_clock::now(); auto msec = std::chrono::duration_cast(timeEnd - timeStart); printf("Classic noise took %d milliseconds, returned total %f\n", static_cast(msec.count()), total); } /** Calculates the specified number of iterations of the Simplex noise. a_TypeStr is a string representing the DATATYPE (for logging purposes). */ template static void measureSimplexNoise(int a_NumIterations, const char * a_TypeStr) { cSimplexNoise noise(1); DATATYPE total = 0; auto timeStart = std::chrono::high_resolution_clock::now(); for (int i = 0; i < a_NumIterations; ++i) { DATATYPE out[SIZE_X * SIZE_Y * SIZE_Z]; int blockX = i * 16; int blockZ = i * 16; DATATYPE startX = 0; DATATYPE endX = 257 / 80.0f; DATATYPE startY = blockX / 40.0f; DATATYPE endY = (blockX + 16) / 40.0f; DATATYPE startZ = blockZ / 40.0f; DATATYPE endZ = (blockZ + 16) / 40.0f; noise.Generate3D(out, SIZE_X, SIZE_Y, SIZE_Z, startX, endX, startY, endY, startZ, endZ); total += out[0]; // Do not let the optimizer optimize the whole calculation away } auto timeEnd = std::chrono::high_resolution_clock::now(); auto msec = std::chrono::duration_cast(timeEnd - timeStart); printf("SimplexNoise<%s> took %d milliseconds, returned total %f\n", a_TypeStr, static_cast(msec.count()), total); } int main(int argc, char ** argv) { int numIterations = 10000; if (argc > 1) { numIterations = std::atoi(argv[1]); if (numIterations < 10) { printf("Invalid number of iterations, using 1000 instead\n"); numIterations = 1000; } } // Perform each test twice, to account for cache-warmup: measureClassicNoise(numIterations); measureClassicNoise(numIterations); measureSimplexNoise(numIterations, "float"); measureSimplexNoise(numIterations, "float"); measureSimplexNoise(numIterations, "double"); measureSimplexNoise(numIterations, "double"); // If build on Windows using MSVC, wait for a keypress before ending: #ifdef _MSC_VER getchar(); #endif return 0; } ================================================ FILE: Tools/NoiseSpeedTest/NoiseSpeedTest.h ================================================ // NoiseSpeedTest.h ================================================ FILE: Tools/NoiseSpeedTest/SimplexNoise.h ================================================ // SimplexNoise.h // Declares and implements the simplex noise, using a template parameter for the underlying datatype /* Note: This code has been adapted from the public domain code by Stefan Gustavson, available at http://staffwww.itn.liu.se/~stegu/simplexnoise/simplexnoise.pdf */ #include template class cSimplexNoise { public: cSimplexNoise(unsigned a_Seed) { // Based on the seed, initialize the permutation table, using a simple LCG and swapping // Initialize with sorted sequence: for (size_t i = 0; i < ARRAYCOUNT(m_Perm) / 2; i++) { m_Perm[i] = static_cast(i); } // Use swaps to randomize: std::minstd_rand lcg(a_Seed); for (size_t i = 0; i < 2000; i++) { std::swap(m_Perm[lcg() % (ARRAYCOUNT(m_Perm) / 2)], m_Perm[lcg() % (ARRAYCOUNT(m_Perm) / 2)]); } // Copy to the upper half of the buffer (to avoid the need for modulo when accessing neighbors): for (size_t i = ARRAYCOUNT(m_Perm) / 2; i < ARRAYCOUNT(m_Perm); i++) { m_Perm[i] = m_Perm[i - ARRAYCOUNT(m_Perm) / 2]; } // Copy to the "modulo 12" table to optimize away four modulo ops per value calculation: for (size_t i = 0; i < ARRAYCOUNT(m_Perm); i++) { m_PermMod12[i] = m_Perm[i] % 12; } } /** Returns a dot product of an int vector with a Datatype vector. */ inline Datatype dot(const int * g, const Datatype x, const Datatype y, const Datatype z) { return g[0] * x + g[1] * y + g[2] * z; } /** Returns a dot product of two Datatype vectors. */ inline Datatype dot(const Datatype * g, const Datatype x, const Datatype y, const Datatype z) { return g[0] * x + g[1] * y + g[2] * z; } /** Returns the floor of the specified value, already type-cast to proper int type. */ inline int datafloor(const Datatype a_Val) { return (a_Val > 0) ? static_cast(a_Val) : static_cast(a_Val - 1); // This is faster than std::floor() } /** Returns a single noise value based on the 3D coords. */ Datatype GetValueAt3D(const Datatype a_X, const Datatype a_Y, const Datatype a_Z) { // The gradients are the midpoints of the vertices of a cube. static const Datatype grad3[12][3] = { {1, 1, 0}, {-1, 1, 0}, {1, -1, 0}, {-1, -1, 0}, {1, 0, 1}, {-1, 0, 1}, {1, 0, -1}, {-1, 0, -1}, {0, 1, 1}, { 0, -1, 1}, {0, 1, -1}, { 0, -1, -1} }; // Skew factors: static const Datatype F3 = static_cast(1.0 / 3.0); static const Datatype G3 = static_cast(1.0 / 6.0); // Noise contributions from the four corners: Datatype n0, n1, n2, n3; // Skew the input space to determine which simplex cell we're in Datatype s = (a_X + a_Y + a_Z) * F3; int i = datafloor(a_X + s); int j = datafloor(a_Y + s); int k = datafloor(a_Z + s); // Unskew back into the XYZ space to calculate the distances from cell origin: Datatype t = (i + j + k) * G3; Datatype X0 = i - t; Datatype Y0 = j - t; Datatype Z0 = k - t; Datatype x0 = a_X - X0; Datatype y0 = a_Y - Y0; Datatype z0 = a_Z - Z0; // For the 3D case, the simplex shape is a slightly irregular tetrahedron. // Determine which simplex we are in. int i1, j1, k1; // Offsets for second corner of simplex in IJK coords int i2, j2, k2; // Offsets for third corner of simplex in IJK coords if (x0 >= y0) { if (y0 >= z0) { // X Y Z order i1 = 1; j1 = 0; k1 = 0; i2 = 1; j2 = 1; k2 = 0; } else if (x0 >= z0) { // X Z Y order i1 = 1; j1 = 0; k1 = 0; i2 = 1; j2 = 0; k2 = 1; } else { // Z X Y order i1 = 0; j1 = 0; k1 = 1; i2 = 1; j2 = 0; k2 = 1; } } else { if (y0 < z0) { // Z Y X order i1 = 0; j1 = 0; k1 = 1; i2 = 0; j2 = 1; k2 = 1; } else if (x0 < z0) { // Y Z X order i1 = 0; j1 = 1; k1 = 0; i2 = 0; j2 = 1; k2 = 1; } else { // Y X Z order i1 = 0; j1 = 1; k1 = 0; i2 = 1; j2 = 1; k2 = 0; } } // A step of (1, 0, 0) in IJK means a step of (1 - c, -c, -c) in XYZ, // a step of (0, 1, 0) in IJK means a step of (-c, 1 - c, -c) in XYZ, and // a step of (0, 0, 1) in IJK means a step of (-c, -c, 1 - c) in XYZ, where c = G3 = 1 / 6. Datatype x1 = x0 - i1 + G3; // Offsets for second corner in XYZ coords Datatype y1 = y0 - j1 + G3; Datatype z1 = z0 - k1 + G3; Datatype x2 = x0 - i2 + static_cast(2) * G3; // Offsets for third corner in XYZ coords Datatype y2 = y0 - j2 + static_cast(2) * G3; Datatype z2 = z0 - k2 + static_cast(2) * G3; Datatype x3 = x0 - static_cast(1) + static_cast(3) * G3; // Offsets for last corner in XYZ coords Datatype y3 = y0 - static_cast(1) + static_cast(3) * G3; Datatype z3 = z0 - static_cast(1) + static_cast(3) * G3; // Work out the hashed gradient indices of the four simplex corners int ii = i & 255; int jj = j & 255; int kk = k & 255; int gi0 = m_PermMod12[ii + m_Perm[jj + m_Perm[kk]]]; int gi1 = m_PermMod12[ii + i1 + m_Perm[jj + j1 + m_Perm[kk + k1]]]; int gi2 = m_PermMod12[ii + i2 + m_Perm[jj + j2 + m_Perm[kk + k2]]]; int gi3 = m_PermMod12[ii + 1 + m_Perm[jj + 1 + m_Perm[kk + 1]]]; // Calculate the contribution from the four corners Datatype t0 = static_cast(0.6) - x0 * x0 - y0 * y0 - z0 * z0; if (t0 < 0) { n0 = 0.0; } else { t0 *= t0; n0 = t0 * t0 * dot(grad3[gi0], x0, y0, z0); } Datatype t1 = static_cast(0.6) - x1 * x1 - y1 * y1 - z1 * z1; if (t1 < 0) { n1 = 0.0; } else { t1 *= t1; n1 = t1 * t1 * dot(grad3[gi1], x1, y1, z1); } Datatype t2 = static_cast(0.6) - x2 * x2 - y2 * y2 - z2 * z2; if (t2 < 0) { n2 = 0.0; } else { t2 *= t2; n2 = t2 * t2 * dot(grad3[gi2], x2, y2, z2); } Datatype t3 = static_cast(0.6) - x3 * x3 - y3 * y3 - z3 * z3; if (t3 < 0) { n3 = 0.0; } else { t3 *= t3; n3 = t3 * t3 * dot(grad3[gi3], x3, y3, z3); } // Add contributions from each corner to get the final noise value. // The result is scaled to stay just inside [-1, 1] return static_cast(32) * (n0 + n1 + n2 + n3); } /** Generates the 3D version of the SImplex noise. a_Out is the 3D array into which the noise is output. Organized as [x + a_SizeX * y + a_SizeX * a_SizeY * z]. a_SizeX, a_SizeY, a_SizeZ are the dimensions of the a_Out array. a_Start and a_End are the coords of the 3D array in the noise-space. */ void Generate3D( Datatype * a_Out, int a_SizeX, int a_SizeY, int a_SizeZ, Datatype a_StartX, Datatype a_EndX, Datatype a_StartY, Datatype a_EndY, Datatype a_StartZ, Datatype a_EndZ ) { Datatype * out = a_Out; for (int z = 0; z < a_SizeZ; ++z) { Datatype nz = a_StartZ + z * (a_EndZ - a_StartZ) / a_SizeZ; for (int y = 0; y < a_SizeY; ++y) { Datatype ny = a_StartY + y * (a_EndY - a_StartY) / a_SizeY; for (int x = 0; x < a_SizeX; ++x) { Datatype nx = a_StartX + x * (a_EndX - a_StartX) / a_SizeX; *out = GetValueAt3D(nx, ny, nz); ++out; } // for x } // for y } // for z } protected: /** The permutation table, initialized by the seed. */ int m_Perm[512]; /** A copy of the permutation table, with each item modulo 12, to avoid 4 modulo operations per value calculation. */ int m_PermMod12[512]; }; ================================================ FILE: Tools/ProtoProxy/.gitignore ================================================ Debug Release Logs/ lib/ *.log *.nbt *.sln *.vcproj *.vcxproj ================================================ FILE: Tools/ProtoProxy/CMakeLists.txt ================================================ project (ProtoProxy) find_package(Threads REQUIRED) # Set include paths to the used libraries: include_directories(SYSTEM "../../lib") include_directories(SYSTEM "../../lib/mbedtls/include") include_directories("../../src") function(flatten_files arg1) set(res "") foreach(f ${${arg1}}) get_filename_component(f ${f} ABSOLUTE) list(APPEND res ${f}) endforeach() set(${arg1} "${res}" PARENT_SCOPE) endfunction() # Include the shared files: set(SHARED_SRC ../../src/ByteBuffer.cpp ../../src/StringUtils.cpp ../../src/UUID.cpp ../../src/mbedTLS++/AesCfb128Decryptor.cpp ../../src/mbedTLS++/AesCfb128Encryptor.cpp ../../src/mbedTLS++/CryptoKey.cpp ../../src/mbedTLS++/CtrDrbgContext.cpp ../../src/mbedTLS++/EntropyContext.cpp ../../src/mbedTLS++/RsaPrivateKey.cpp ../../src/LoggerListeners.cpp ../../src/Logger.cpp ) set(SHARED_HDR ../../src/ByteBuffer.h ../../src/Globals.h ../../src/StringUtils.h ../../src/UUID.h ../../src/mbedTLS++/AesCfb128Decryptor.h ../../src/mbedTLS++/AesCfb128Encryptor.h ../../src/mbedTLS++/CryptoKey.h ../../src/mbedTLS++/CtrDrbgContext.h ../../src/mbedTLS++/EntropyContext.h ../../src/mbedTLS++/RsaPrivateKey.h ) set(SHARED_OSS_SRC ../../src/OSSupport/CriticalSection.cpp ../../src/OSSupport/Event.cpp ../../src/OSSupport/File.cpp ../../src/OSSupport/IsThread.cpp ../../src/OSSupport/StackTrace.cpp ../../src/OSSupport/WinStackWalker.cpp ) set(SHARED_OSS_HDR ../../src/OSSupport/CriticalSection.h ../../src/OSSupport/Event.h ../../src/OSSupport/File.h ../../src/OSSupport/IsThread.h ../../src/OSSupport/StackTrace.h ../../src/OSSupport/WinStackWalker.h ) flatten_files(SHARED_SRC) flatten_files(SHARED_HDR) flatten_files(SHARED_OSS_SRC) flatten_files(SHARED_OSS_HDR) source_group("Shared" FILES ${SHARED_SRC} ${SHARED_HDR}) source_group("Shared\\OSSupport" FILES ${SHARED_OSS_SRC} ${SHARED_OSS_HDR}) # Include the main source files: set(SOURCES Connection.cpp ProtoProxy.cpp Server.cpp ) set(HEADERS Connection.h Server.h ) source_group("" FILES ${SOURCES} ${HEADERS}) add_executable(ProtoProxy ${SOURCES} ${HEADERS} ${SHARED_SRC} ${SHARED_HDR} ${SHARED_OSS_SRC} ${SHARED_OSS_HDR} ) target_link_libraries(ProtoProxy fmt::fmt libdeflate mbedtls Threads::Threads) include(../../SetFlags.cmake) set_exe_flags(ProtoProxy) ================================================ FILE: Tools/ProtoProxy/Connection.cpp ================================================ // Connection.cpp // Interfaces to the cConnection class representing a single pair of connected sockets #include "Globals.h" #include "Connection.h" #include "Server.h" #include #include "mbedTLS++/CryptoKey.h" #include "../../src/Logger.h" #ifdef _WIN32 #include // For _mkdir() #else #include // for mkdir #endif /** When defined, the following macro causes a sleep after each parsed packet (DEBUG-mode only) */ // #define SLEEP_AFTER_PACKET #if defined(_DEBUG) && defined(SLEEP_AFTER_PACKET) #define DebugSleep Sleep #else #define DebugSleep(X) #endif // else _DEBUG #define HANDLE_CLIENT_PACKET_READ(Proc, Type, Var) \ Type Var; \ do { \ if (!m_ClientBuffer.Proc(Var)) \ { \ return false; \ } \ } while (false) #define HANDLE_SERVER_PACKET_READ(Proc, Type, Var) \ Type Var; \ do { \ if (!m_ServerBuffer.Proc(Var)) \ { \ return false; \ } \ } while (false) #define CLIENTSEND(...) SendData(m_ClientSocket, __VA_ARGS__, "Client") #define SERVERSEND(...) SendData(m_ServerSocket, __VA_ARGS__, "Server") #define CLIENTENCRYPTSEND(...) SendData(m_ClientSocket, __VA_ARGS__, "Client") // The client conn is always unencrypted #define SERVERENCRYPTSEND(...) SendEncryptedData(m_ServerSocket, m_ServerEncryptor, __VA_ARGS__, "Server") #define COPY_TO_SERVER() \ do { \ ContiguousByteBuffer ToServer; \ m_ClientBuffer.ReadAgain(ToServer); \ switch (m_ServerState) \ { \ case csUnencrypted: \ { \ SERVERSEND(ToServer); \ break; \ } \ case csEncryptedUnderstood: \ case csEncryptedUnknown: \ { \ SERVERENCRYPTSEND(ToServer); \ break; \ } \ case csWaitingForEncryption: \ { \ Log("Waiting for server encryption, queued %u bytes", ToServer.size()); \ m_ServerEncryptionBuffer += ToServer; \ break; \ } \ } \ DebugSleep(50); \ } while (false) #define COPY_TO_CLIENT() \ do { \ ContiguousByteBuffer ToClient; \ m_ServerBuffer.ReadAgain(ToClient); \ switch (m_ClientState) \ { \ case csUnencrypted: \ { \ CLIENTSEND(ToClient); \ break; \ } \ case csEncryptedUnderstood: \ case csEncryptedUnknown: \ { \ CLIENTENCRYPTSEND(ToClient); \ break; \ } \ case csWaitingForEncryption: \ { \ break; \ } \ \ } \ DebugSleep(50); \ } while (false) #define HANDLE_CLIENT_READ(Proc) \ do { \ if (!Proc) \ { \ ContiguousByteBuffer Leftover; \ m_ClientBuffer.ReadAgain(Leftover); \ DataLog(Leftover.data(), Leftover.size(), "Leftover data after client packet parsing, %d bytes:", Leftover.size()); \ m_ClientBuffer.ResetRead(); \ return true; \ } \ } while (false) #define HANDLE_SERVER_READ(Proc) \ do { \ if (!Proc) \ { \ m_ServerBuffer.ResetRead(); \ return true; \ } \ } while (false) typedef unsigned char Byte; // fwd declarations, to avoid clang warnings: AString PrintableAbsIntTriplet(int a_X, int a_Y, int a_Z, double a_Divisor = 32); AString PrintableAbsIntTriplet(int a_X, int a_Y, int a_Z, double a_Divisor) { return fmt::format( FMT_STRING("<{}, {}, {}> ~ {{{}, {}, {}}}"), a_X, a_Y, a_Z, static_cast(a_X) / a_Divisor, static_cast(a_Y) / a_Divisor, static_cast(a_Z) / a_Divisor ); } struct sCoords { int x, y, z; sCoords(int a_X, int a_Y, int a_Z) : x(a_X), y(a_Y), z(a_Z) {} } ; struct sChunkMeta { int m_ChunkX, m_ChunkZ; short m_PrimaryBitmap; short m_AddBitmap; sChunkMeta(int a_ChunkX, int a_ChunkZ, short a_PrimaryBitmap, short a_AddBitmap) : m_ChunkX(a_ChunkX), m_ChunkZ(a_ChunkZ), m_PrimaryBitmap(a_PrimaryBitmap), m_AddBitmap(a_AddBitmap) { } } ; //////////////////////////////////////////////////////////////////////////////// // cConnection: cConnection::cConnection(SOCKET a_ClientSocket, cServer & a_Server) : m_ItemIdx(0), m_LogFile(nullptr), m_Server(a_Server), m_ClientSocket(a_ClientSocket), m_ServerSocket(-1), m_BeginTick(std::chrono::steady_clock::now()), m_ClientState(csUnencrypted), m_ServerState(csUnencrypted), m_Nonce(0), m_ClientBuffer(1024 KiB), m_ServerBuffer(1024 KiB), m_HasClientPinged(false), m_ServerProtocolState(-1), m_ClientProtocolState(-1), m_IsServerEncrypted(false) { // Create the Logs subfolder, if not already created: #if defined(_WIN32) _mkdir("Logs"); #else mkdir("Logs", 0777); #endif m_LogNameBase = fmt::format(FMT_STRING("Logs/Log_{}_{}"), time(nullptr), a_ClientSocket); AString fnam(m_LogNameBase); fnam.append(".log"); #ifdef _WIN32 fopen_s(&m_LogFile, fnam.c_str(), "w"); #else m_LogFile = fopen(fnam.c_str(), "w"); #endif Log("Log file created"); fmt::print(FMT_STRING("Connection is logged to file \"{}\"\n"), fnam); } cConnection::~cConnection() { fclose(m_LogFile); } void cConnection::Run(void) { if (!ConnectToServer()) { Log("Cannot connect to server; aborting"); return; } while (true) { fd_set ReadFDs; FD_ZERO(&ReadFDs); FD_SET(m_ServerSocket, &ReadFDs); FD_SET(m_ClientSocket, &ReadFDs); SOCKET MaxSocket = std::max(m_ServerSocket, m_ClientSocket); int res = select(MaxSocket + 1, &ReadFDs, nullptr, nullptr, nullptr); if (res <= 0) { printf("select() failed: %d; aborting client", SocketError); break; } if (FD_ISSET(m_ServerSocket, &ReadFDs)) { if (!RelayFromServer()) { break; } } if (FD_ISSET(m_ClientSocket, &ReadFDs)) { if (!RelayFromClient()) { break; } } } Log("Relaying ended, closing sockets"); closesocket(m_ServerSocket); closesocket(m_ClientSocket); } void cConnection::vLog(const char * a_Format, fmt::printf_args a_ArgList) { // Log to file: cCSLock Lock(m_CSLog); fmt::fprintf(m_LogFile, "[%5.3f] ", GetRelativeTime()); fmt::vfprintf(m_LogFile, a_Format, a_ArgList); fmt::fprintf(m_LogFile, "\n"); #ifdef _DEBUG fflush(m_LogFile); #endif // _DEBUG // Log to screen: // std::cout << FullMsg; } void cConnection::vDataLog(const void * a_Data, size_t a_Size, const char * a_Format, fmt::printf_args a_ArgList) { AString Hex; CreateHexDump(Hex, a_Data, a_Size, 16); // Log to file: cCSLock Lock(m_CSLog); fmt::fprintf(m_LogFile, "[%5.3f] ", GetRelativeTime()); fmt::vfprintf(m_LogFile, a_Format, a_ArgList); fmt::fprintf(m_LogFile, "\n%s\n", Hex); // Log to screen: // std::cout << FullMsg; } void cConnection::LogFlush(void) { fflush(m_LogFile); } bool cConnection::ConnectToServer(void) { m_ServerSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (m_ServerSocket == INVALID_SOCKET) { return false; } sockaddr_in localhost; localhost.sin_family = AF_INET; localhost.sin_port = htons(m_Server.GetConnectPort()); localhost.sin_addr.s_addr = htonl(0x7f000001); // localhost if (connect(m_ServerSocket, reinterpret_cast(&localhost), sizeof(localhost)) != 0) { printf("connection to server failed: %d\n", SocketError); return false; } Log("Connected to SERVER"); return true; } bool cConnection::RelayFromServer(void) { char Buffer[64 KiB]; int res = static_cast(recv(m_ServerSocket, Buffer, sizeof(Buffer), 0)); // recv returns int on windows, ssize_t on linux if (res <= 0) { Log("Server closed the socket: %d; %d; aborting connection", res, SocketError); return false; } DataLog(Buffer, static_cast(res), "Received %d bytes from the SERVER", res); switch (m_ServerState) { case csUnencrypted: case csWaitingForEncryption: { return DecodeServersPackets(Buffer, res); } case csEncryptedUnderstood: { m_ServerDecryptor.ProcessData(reinterpret_cast(Buffer), static_cast(res)); DataLog(Buffer, static_cast(res), "Decrypted %d bytes from the SERVER", res); return DecodeServersPackets(Buffer, res); } case csEncryptedUnknown: { m_ServerDecryptor.ProcessData(reinterpret_cast(Buffer), static_cast(res)); DataLog(Buffer, static_cast(res), "Decrypted %d bytes from the SERVER", res); return CLIENTSEND({ reinterpret_cast(Buffer), static_cast(res) }); } } ASSERT(!"Unhandled server state while relaying from server"); return false; } bool cConnection::RelayFromClient(void) { char Buffer[64 KiB]; int res = static_cast(recv(m_ClientSocket, Buffer, sizeof(Buffer), 0)); // recv returns int on Windows, ssize_t on Linux if (res <= 0) { Log("Client closed the socket: %d; %d; aborting connection", res, SocketError); return false; } DataLog(Buffer, static_cast(res), "Received %d bytes from the CLIENT", res); switch (m_ClientState) { case csUnencrypted: case csWaitingForEncryption: { return DecodeClientsPackets(Buffer, res); } case csEncryptedUnderstood: { return DecodeClientsPackets(Buffer, res); } case csEncryptedUnknown: { DataLog(Buffer, static_cast(res), "Decrypted %d bytes from the CLIENT", res); m_ServerEncryptor.ProcessData(reinterpret_cast(Buffer), static_cast(res)); return SERVERSEND({ reinterpret_cast(Buffer), static_cast(res) }); } } ASSERT(!"Unhandled server state while relaying from client"); return false; } double cConnection::GetRelativeTime(void) { Int64 msec = std::chrono::duration_cast(std::chrono::steady_clock::now() - m_BeginTick).count(); return static_cast(msec) / 1000; } bool cConnection::SendData(SOCKET a_Socket, const ContiguousByteBufferView a_Data, const char * a_Peer) { DataLog(a_Data.data(), a_Data.size(), "Sending data to %s, %zu bytes", a_Peer, a_Data.size()); int res = static_cast(send(a_Socket, reinterpret_cast(a_Data.data()), a_Data.size(), 0)); // Windows uses int for a_Size, Linux uses size_t; but Windows doesn't complain. Return type is int on Windows and ssize_t on Linux if (res <= 0) { Log("%s closed the socket: %d, %d; aborting connection", a_Peer, res, SocketError); return false; } return true; } bool cConnection::SendData(SOCKET a_Socket, cByteBuffer & a_Data, const char * a_Peer) { ContiguousByteBuffer All; a_Data.ReadAll(All); a_Data.CommitRead(); return SendData(a_Socket, All, a_Peer); } bool cConnection::SendEncryptedData(SOCKET a_Socket, cAesCfb128Encryptor & a_Encryptor, ContiguousByteBuffer & a_Data, const char * a_Peer) { DataLog(a_Data.data(), a_Data.size(), "Encrypting %zu bytes to %s", a_Data.size(), a_Peer); a_Encryptor.ProcessData(a_Data.data(), a_Data.size()); return SendData(a_Socket, a_Data, a_Peer); } bool cConnection::SendEncryptedData(SOCKET a_Socket, cAesCfb128Encryptor & a_Encryptor, cByteBuffer & a_Data, const char * a_Peer) { ContiguousByteBuffer All; a_Data.ReadAll(All); a_Data.CommitRead(); return SendEncryptedData(a_Socket, a_Encryptor, All, a_Peer); } bool cConnection::DecodeClientsPackets(const char * a_Data, int a_Size) { if (!m_ClientBuffer.Write(a_Data, static_cast(a_Size))) { Log("Too much queued data for the server, aborting connection"); return false; } while (m_ClientBuffer.CanReadBytes(1)) { UInt32 PacketLen; if ( !m_ClientBuffer.ReadVarInt(PacketLen) || !m_ClientBuffer.CanReadBytes(PacketLen) ) { // Not a complete packet yet break; } UInt32 PacketType, PacketReadSoFar; PacketReadSoFar = static_cast(m_ClientBuffer.GetReadableSpace()); VERIFY(m_ClientBuffer.ReadVarInt(PacketType)); PacketReadSoFar -= m_ClientBuffer.GetReadableSpace(); Log("Decoding client's packets, there are now %u bytes in the queue; next packet is 0x%02x, %u bytes long", static_cast(m_ClientBuffer.GetReadableSpace()), PacketType, PacketLen ); switch (m_ClientProtocolState) { case -1: { // No initial handshake received yet switch (PacketType) { case 0x00: HANDLE_CLIENT_READ(HandleClientHandshake()); break; default: HANDLE_CLIENT_READ(HandleClientUnknownPacket(PacketType, PacketLen, PacketReadSoFar)); break; } break; } // case -1 case 1: { // Status query switch (PacketType) { case 0x00: HANDLE_CLIENT_READ(HandleClientStatusRequest()); break; case 0x01: HANDLE_CLIENT_READ(HandleClientStatusPing()); break; default: HANDLE_CLIENT_READ(HandleClientUnknownPacket(PacketType, PacketLen, PacketReadSoFar)); break; } break; } case 2: { // Login switch (PacketType) { case 0x00: HANDLE_CLIENT_READ(HandleClientLoginStart()); break; case 0x01: HANDLE_CLIENT_READ(HandleClientLoginEncryptionKeyResponse()); break; default: HANDLE_CLIENT_READ(HandleClientUnknownPacket(PacketType, PacketLen, PacketReadSoFar)); break; } break; } case 3: { // Game: switch (PacketType) { case 0x00: HANDLE_CLIENT_READ(HandleClientKeepAlive()); break; case 0x01: HANDLE_CLIENT_READ(HandleClientChatMessage()); break; case 0x02: HANDLE_CLIENT_READ(HandleClientUseEntity()); break; case 0x03: HANDLE_CLIENT_READ(HandleClientPlayerOnGround()); break; case 0x04: HANDLE_CLIENT_READ(HandleClientPlayerPosition()); break; case 0x05: HANDLE_CLIENT_READ(HandleClientPlayerLook()); break; case 0x06: HANDLE_CLIENT_READ(HandleClientPlayerPositionLook()); break; case 0x07: HANDLE_CLIENT_READ(HandleClientBlockDig()); break; case 0x08: HANDLE_CLIENT_READ(HandleClientBlockPlace()); break; case 0x09: HANDLE_CLIENT_READ(HandleClientSlotSelect()); break; case 0x0a: HANDLE_CLIENT_READ(HandleClientAnimation()); break; case 0x0b: HANDLE_CLIENT_READ(HandleClientEntityAction()); break; case 0x0d: HANDLE_CLIENT_READ(HandleClientWindowClose()); break; case 0x0e: HANDLE_CLIENT_READ(HandleClientWindowClick()); break; case 0x10: HANDLE_CLIENT_READ(HandleClientCreativeInventoryAction()); break; case 0x12: HANDLE_CLIENT_READ(HandleClientUpdateSign()); break; case 0x13: HANDLE_CLIENT_READ(HandleClientPlayerAbilities()); break; case 0x14: HANDLE_CLIENT_READ(HandleClientTabCompletion()); break; case 0x15: HANDLE_CLIENT_READ(HandleClientLocaleAndView()); break; case 0x16: HANDLE_CLIENT_READ(HandleClientClientStatuses()); break; case 0x17: HANDLE_CLIENT_READ(HandleClientPluginMessage()); break; default: HANDLE_CLIENT_READ(HandleClientUnknownPacket(PacketType, PacketLen, PacketReadSoFar)); break; } break; } // case 3 - Game default: { Log("Receiving server packets while in an unknown protocol state (%d)!", m_ClientProtocolState); HANDLE_CLIENT_READ(HandleClientUnknownPacket(PacketType, PacketLen, PacketReadSoFar)); break; } } // switch (m_ProtocolState) m_ClientBuffer.CommitRead(); } // while (true) return true; } bool cConnection::DecodeServersPackets(const char * a_Data, int a_Size) { if (!m_ServerBuffer.Write(a_Data, static_cast(a_Size))) { Log("Too much queued data for the client, aborting connection"); return false; } if ( (m_ServerState == csEncryptedUnderstood) && (m_ClientState == csUnencrypted) ) { // Client hasn't finished encryption handshake yet, don't send them any data yet } while (true) { UInt32 PacketLen; if ( !m_ServerBuffer.ReadVarInt(PacketLen) || !m_ServerBuffer.CanReadBytes(PacketLen) ) { // Not a complete packet yet m_ServerBuffer.ResetRead(); break; } if (PacketLen == 0) { m_ServerBuffer.ResetRead(); ContiguousByteBuffer All; m_ServerBuffer.ReadAll(All); DataLog(All.data(), All.size(), "====== Received a bad packet length? Inspect the contents below ======"); m_ServerBuffer.CommitRead(); // Try to recover by marking everything as read break; } UInt32 PacketType, PacketReadSoFar; PacketReadSoFar = static_cast(m_ServerBuffer.GetReadableSpace()); VERIFY(m_ServerBuffer.ReadVarInt(PacketType)); PacketReadSoFar -= m_ServerBuffer.GetReadableSpace(); Log("Decoding server's packets, there are now %d bytes in the queue; next packet is 0x%0x, %u bytes long", m_ServerBuffer.GetReadableSpace(), PacketType, PacketLen); LogFlush(); switch (m_ServerProtocolState) { case -1: { Log("Receiving data from the server without an initial handshake message!"); HANDLE_SERVER_READ(HandleServerUnknownPacket(PacketType, PacketLen, PacketReadSoFar)); break; } case 1: { // Status query: switch (PacketType) { case 0x00: HANDLE_SERVER_READ(HandleServerStatusResponse()); break; case 0x01: HANDLE_SERVER_READ(HandleServerStatusPing()); break; default: HANDLE_SERVER_READ(HandleServerUnknownPacket(PacketType, PacketLen, PacketReadSoFar)); break; } break; } case 2: { // Login: switch (PacketType) { case 0x00: HANDLE_SERVER_READ(HandleServerLoginDisconnect()); break; case 0x01: HANDLE_SERVER_READ(HandleServerLoginEncryptionKeyRequest()); break; case 0x02: HANDLE_SERVER_READ(HandleServerLoginSuccess()); break; default: HANDLE_SERVER_READ(HandleServerUnknownPacket(PacketType, PacketLen, PacketReadSoFar)); break; } break; } case 3: { // Game: switch (PacketType) { case 0x00: HANDLE_SERVER_READ(HandleServerKeepAlive()); break; case 0x01: HANDLE_SERVER_READ(HandleServerJoinGame()); break; case 0x02: HANDLE_SERVER_READ(HandleServerChatMessage()); break; case 0x03: HANDLE_SERVER_READ(HandleServerTimeUpdate()); break; case 0x04: HANDLE_SERVER_READ(HandleServerEntityEquipment()); break; case 0x05: HANDLE_SERVER_READ(HandleServerCompass()); break; case 0x06: HANDLE_SERVER_READ(HandleServerUpdateHealth()); break; case 0x07: HANDLE_SERVER_READ(HandleServerRespawn()); break; case 0x08: HANDLE_SERVER_READ(HandleServerPlayerPositionLook()); break; case 0x09: HANDLE_SERVER_READ(HandleServerSlotSelect()); break; case 0x0a: HANDLE_SERVER_READ(HandleServerUseBed()); break; case 0x0b: HANDLE_SERVER_READ(HandleServerPlayerAnimation()); break; case 0x0c: HANDLE_SERVER_READ(HandleServerSpawnNamedEntity()); break; case 0x0d: HANDLE_SERVER_READ(HandleServerCollectPickup()); break; case 0x0e: HANDLE_SERVER_READ(HandleServerSpawnObjectVehicle()); break; case 0x0f: HANDLE_SERVER_READ(HandleServerSpawnMob()); break; case 0x10: HANDLE_SERVER_READ(HandleServerSpawnPainting()); break; case 0x11: HANDLE_SERVER_READ(HandleServerSpawnExperienceOrbs()); break; case 0x12: HANDLE_SERVER_READ(HandleServerEntityVelocity()); break; case 0x13: HANDLE_SERVER_READ(HandleServerDestroyEntities()); break; case 0x14: HANDLE_SERVER_READ(HandleServerEntity()); break; case 0x15: HANDLE_SERVER_READ(HandleServerEntityRelativeMove()); break; case 0x16: HANDLE_SERVER_READ(HandleServerEntityLook()); break; case 0x17: HANDLE_SERVER_READ(HandleServerEntityRelativeMoveLook()); break; case 0x18: HANDLE_SERVER_READ(HandleServerEntityTeleport()); break; case 0x19: HANDLE_SERVER_READ(HandleServerEntityHeadLook()); break; case 0x1a: HANDLE_SERVER_READ(HandleServerEntityStatus()); break; case 0x1b: HANDLE_SERVER_READ(HandleServerAttachEntity()); break; case 0x1c: HANDLE_SERVER_READ(HandleServerEntityMetadata()); break; case 0x1f: HANDLE_SERVER_READ(HandleServerSetExperience()); break; case 0x20: HANDLE_SERVER_READ(HandleServerEntityProperties()); break; case 0x21: HANDLE_SERVER_READ(HandleServerMapChunk()); break; case 0x22: HANDLE_SERVER_READ(HandleServerMultiBlockChange()); break; case 0x23: HANDLE_SERVER_READ(HandleServerBlockChange()); break; case 0x24: HANDLE_SERVER_READ(HandleServerBlockAction()); break; case 0x26: HANDLE_SERVER_READ(HandleServerMapChunkBulk()); break; case 0x27: HANDLE_SERVER_READ(HandleServerExplosion()); break; case 0x28: HANDLE_SERVER_READ(HandleServerSoundEffect()); break; case 0x29: HANDLE_SERVER_READ(HandleServerNamedSoundEffect()); break; case 0x2b: HANDLE_SERVER_READ(HandleServerChangeGameState()); break; case 0x2d: HANDLE_SERVER_READ(HandleServerWindowOpen()); break; case 0x2e: HANDLE_SERVER_READ(HandleServerWindowClose()); break; case 0x2f: HANDLE_SERVER_READ(HandleServerSetSlot()); break; case 0x30: HANDLE_SERVER_READ(HandleServerWindowContents()); break; case 0x33: HANDLE_SERVER_READ(HandleServerUpdateSign()); break; case 0x35: HANDLE_SERVER_READ(HandleServerUpdateTileEntity()); break; case 0x37: HANDLE_SERVER_READ(HandleServerStatistics()); break; case 0x38: HANDLE_SERVER_READ(HandleServerPlayerListItem()); break; case 0x39: HANDLE_SERVER_READ(HandleServerPlayerAbilities()); break; case 0x3a: HANDLE_SERVER_READ(HandleServerTabCompletion()); break; case 0x3f: HANDLE_SERVER_READ(HandleServerPluginMessage()); break; case 0x40: HANDLE_SERVER_READ(HandleServerKick()); break; default: HANDLE_SERVER_READ(HandleServerUnknownPacket(PacketType, PacketLen, PacketReadSoFar)); break; } // switch (PacketType) break; } // case 3 - Game // TODO: Move this elsewhere default: { Log("Received a packet from the server while in an unknown state: %d", m_ServerProtocolState); HANDLE_SERVER_READ(HandleServerUnknownPacket(PacketType, PacketLen, PacketReadSoFar)); break; } } // switch (m_ProtocolState) m_ServerBuffer.CommitRead(); } // while (CanReadBytes(1)) return true; } //////////////////////////////////////////////////////////////////////////////// // packet handling, client-side, initial handshake: bool cConnection::HandleClientHandshake(void) { // Read the packet from the client: HANDLE_CLIENT_PACKET_READ(ReadVarInt, UInt32, ProtocolVersion); HANDLE_CLIENT_PACKET_READ(ReadVarUTF8String, AString, ServerHost); HANDLE_CLIENT_PACKET_READ(ReadBEUInt16, UInt16, ServerPort); HANDLE_CLIENT_PACKET_READ(ReadVarInt, UInt32, NextState); m_ClientBuffer.CommitRead(); Log("Received an initial handshake packet from the client:"); Log(" ProtocolVersion = %u", ProtocolVersion); Log(" ServerHost = \"%s\"", ServerHost.c_str()); Log(" ServerPort = %u", ServerPort); Log(" NextState = %u", NextState); // Send the same packet to the server, but with our port: cByteBuffer Packet(512); Packet.WriteVarInt32(0); // Packet type - initial handshake Packet.WriteVarInt32(ProtocolVersion); Packet.WriteVarUTF8String(ServerHost); Packet.WriteBEUInt16(m_Server.GetConnectPort()); Packet.WriteVarInt32(NextState); ContiguousByteBuffer Pkt; Packet.ReadAll(Pkt); cByteBuffer ToServer(512); ToServer.WriteVarInt32(static_cast(Pkt.size())); ToServer.Write(Pkt.data(), Pkt.size()); SERVERSEND(ToServer); m_ClientProtocolState = static_cast(NextState); m_ServerProtocolState = static_cast(NextState); return true; } //////////////////////////////////////////////////////////////////////////////// // packet handling, client-side, login: bool cConnection::HandleClientLoginEncryptionKeyResponse(void) { Log("Client: Unexpected packet: encryption key response"); return true; } bool cConnection::HandleClientLoginStart(void) { HANDLE_CLIENT_PACKET_READ(ReadVarUTF8String, AString, UserName); Log("Received a login start packet from the client:"); Log(" Username = \"%s\"", UserName.c_str()); COPY_TO_SERVER(); return true; } //////////////////////////////////////////////////////////////////////////////// // packet handling, client-side, game: bool cConnection::HandleClientAnimation(void) { HANDLE_CLIENT_PACKET_READ(ReadBEUInt32, UInt32, EntityID); HANDLE_CLIENT_PACKET_READ(ReadBEInt8, Int8, Animation); Log("Received a PACKET_ANIMATION from the client:"); Log(" EntityID: %u", EntityID); Log(" Animation: %d", Animation); COPY_TO_SERVER(); return true; } bool cConnection::HandleClientBlockDig(void) { HANDLE_CLIENT_PACKET_READ(ReadBEUInt8, UInt8, Status); HANDLE_CLIENT_PACKET_READ(ReadBEInt32, Int32, BlockX); HANDLE_CLIENT_PACKET_READ(ReadBEUInt8, UInt8, BlockY); HANDLE_CLIENT_PACKET_READ(ReadBEInt32, Int32, BlockZ); HANDLE_CLIENT_PACKET_READ(ReadBEUInt8, UInt8, BlockFace); Log("Received a PACKET_BLOCK_DIG from the client:"); Log(" Status = %u (0x%02x)", Status, Status); Log(" Pos = <%d, %u, %d>", BlockX, BlockY, BlockZ); Log(" BlockFace = %u (0x%02x)", BlockFace, BlockFace); COPY_TO_SERVER(); return true; } bool cConnection::HandleClientBlockPlace(void) { HANDLE_CLIENT_PACKET_READ(ReadBEInt32, Int32, BlockX); HANDLE_CLIENT_PACKET_READ(ReadBEUInt8, UInt8, BlockY); HANDLE_CLIENT_PACKET_READ(ReadBEInt32, Int32, BlockZ); HANDLE_CLIENT_PACKET_READ(ReadBEUInt8, UInt8, Face); AString Desc; if (!ParseSlot(m_ClientBuffer, Desc)) { return false; } HANDLE_CLIENT_PACKET_READ(ReadBEUInt8, UInt8, CursorX); HANDLE_CLIENT_PACKET_READ(ReadBEUInt8, UInt8, CursorY); HANDLE_CLIENT_PACKET_READ(ReadBEUInt8, UInt8, CursorZ); Log("Received a PACKET_BLOCK_PLACE from the client:"); Log(" Block = {%d, %u, %d}", BlockX, BlockY, BlockZ); Log(" Face = %u (0x%02x)", Face, Face); Log(" Item = %s", Desc.c_str()); Log(" Cursor = <%u, %u, %u>", CursorX, CursorY, CursorZ); COPY_TO_SERVER(); return true; } bool cConnection::HandleClientChatMessage(void) { HANDLE_CLIENT_PACKET_READ(ReadVarUTF8String, AString, Message); Log("Received a PACKET_CHAT_MESSAGE from the client:"); Log(" Message = \"%s\"", Message.c_str()); COPY_TO_SERVER(); return true; } bool cConnection::HandleClientClientStatuses(void) { HANDLE_CLIENT_PACKET_READ(ReadBEUInt8, UInt8, Statuses); Log("Received a PACKET_CLIENT_STATUSES from the CLIENT:"); Log(" Statuses = %u (0x%02x)", Statuses, Statuses); COPY_TO_SERVER(); return true; } bool cConnection::HandleClientCreativeInventoryAction(void) { HANDLE_CLIENT_PACKET_READ(ReadBEUInt16, UInt16, SlotNum); AString Item; if (!ParseSlot(m_ClientBuffer, Item)) { return false; } Log("Received a PACKET_CREATIVE_INVENTORY_ACTION from the client:"); Log(" SlotNum = %u", SlotNum); Log(" Item = %s", Item.c_str()); COPY_TO_SERVER(); return true; } bool cConnection::HandleClientDisconnect(void) { HANDLE_CLIENT_PACKET_READ(ReadVarUTF8String, AString, Reason); Log("Received a PACKET_DISCONNECT from the client:"); Log(" Reason = \"%s\"", Reason.c_str()); COPY_TO_SERVER(); return true; } bool cConnection::HandleClientEntityAction(void) { HANDLE_CLIENT_PACKET_READ(ReadBEInt32, Int32, PlayerID); HANDLE_CLIENT_PACKET_READ(ReadBEUInt8, UInt8, ActionType); HANDLE_CLIENT_PACKET_READ(ReadBEInt32, Int32, HorseJumpBoost); Log("Received a PACKET_ENTITY_ACTION from the client:"); Log(" PlayerID = %d", PlayerID); Log(" ActionType = %u", ActionType); Log(" HorseJumpBoost = %d (0x%08x)", HorseJumpBoost, HorseJumpBoost); COPY_TO_SERVER(); return true; } bool cConnection::HandleClientKeepAlive(void) { HANDLE_CLIENT_PACKET_READ(ReadBEInt32, Int32, ID); Log("Received a PACKET_KEEPALIVE from the client"); COPY_TO_SERVER(); return true; } bool cConnection::HandleClientLocaleAndView(void) { HANDLE_CLIENT_PACKET_READ(ReadVarUTF8String, AString, Locale); HANDLE_CLIENT_PACKET_READ(ReadBEInt8, Int8, ViewDistance); HANDLE_CLIENT_PACKET_READ(ReadBEInt8, Int8, ChatFlags); HANDLE_CLIENT_PACKET_READ(ReadBEInt8, Int8, Unused); HANDLE_CLIENT_PACKET_READ(ReadBEInt8, Int8, Difficulty); HANDLE_CLIENT_PACKET_READ(ReadBEInt8, Int8, ShowCape); Log("Received a PACKET_LOCALE_AND_VIEW from the client"); COPY_TO_SERVER(); return true; } bool cConnection::HandleClientPing(void) { m_HasClientPinged = true; Log("Received a PACKET_PING from the client"); m_ClientBuffer.ResetRead(); SERVERSEND(m_ClientBuffer); return true; } bool cConnection::HandleClientPlayerAbilities(void) { HANDLE_CLIENT_PACKET_READ(ReadBEUInt8, UInt8, Flags); HANDLE_CLIENT_PACKET_READ(ReadBEFloat, float, FlyingSpeed); HANDLE_CLIENT_PACKET_READ(ReadBEFloat, float, WalkingSpeed); Log("Receives a PACKET_PLAYER_ABILITIES from the client:"); Log(" Flags = %u (0x%02x)", Flags, Flags); Log(" FlyingSpeed = %f", FlyingSpeed); Log(" WalkingSpeed = %f", WalkingSpeed); COPY_TO_SERVER(); return true; } bool cConnection::HandleClientPlayerLook(void) { HANDLE_CLIENT_PACKET_READ(ReadBEFloat, float, Yaw); HANDLE_CLIENT_PACKET_READ(ReadBEFloat, float, Pitch); HANDLE_CLIENT_PACKET_READ(ReadBEUInt8, UInt8, OnGround); Log("Received a PACKET_PLAYER_LOOK from the client"); COPY_TO_SERVER(); return true; } bool cConnection::HandleClientPlayerOnGround(void) { HANDLE_CLIENT_PACKET_READ(ReadBEUInt8, UInt8, OnGround); Log("Received a PACKET_PLAYER_ON_GROUND from the client"); COPY_TO_SERVER(); return true; } bool cConnection::HandleClientPlayerPosition(void) { HANDLE_CLIENT_PACKET_READ(ReadBEDouble, double, PosX); HANDLE_CLIENT_PACKET_READ(ReadBEDouble, double, PosY); HANDLE_CLIENT_PACKET_READ(ReadBEDouble, double, Stance); HANDLE_CLIENT_PACKET_READ(ReadBEDouble, double, PosZ); HANDLE_CLIENT_PACKET_READ(ReadBEUInt8, UInt8, IsOnGround); Log("Received a PACKET_PLAYER_POSITION from the client"); // TODO: list packet contents COPY_TO_SERVER(); return true; } bool cConnection::HandleClientPlayerPositionLook(void) { HANDLE_CLIENT_PACKET_READ(ReadBEDouble, double, PosX); HANDLE_CLIENT_PACKET_READ(ReadBEDouble, double, PosY); HANDLE_CLIENT_PACKET_READ(ReadBEDouble, double, Stance); HANDLE_CLIENT_PACKET_READ(ReadBEDouble, double, PosZ); HANDLE_CLIENT_PACKET_READ(ReadBEFloat, float, Yaw); HANDLE_CLIENT_PACKET_READ(ReadBEFloat, float, Pitch); HANDLE_CLIENT_PACKET_READ(ReadBEUInt8, UInt8, IsOnGround); Log("Received a PACKET_PLAYER_POSITION_LOOK from the client"); Log(" Pos = {%.03f, %.03f, %.03f}", PosX, PosY, PosZ); Log(" Stance = %.03f", Stance); Log(" Yaw, Pitch = <%.03f, %.03f>", Yaw, Pitch); Log(" IsOnGround = %s", IsOnGround ? "true" : "false"); COPY_TO_SERVER(); return true; } bool cConnection::HandleClientPluginMessage(void) { HANDLE_CLIENT_PACKET_READ(ReadVarUTF8String, AString, ChannelName); HANDLE_CLIENT_PACKET_READ(ReadBEUInt16, UInt16, Length); ContiguousByteBuffer Data; if (!m_ClientBuffer.ReadSome(Data, Length)) { return false; } Log("Received a PACKET_PLUGIN_MESSAGE from the client"); Log(" ChannelName = \"%s\"", ChannelName.c_str()); DataLog(Data.data(), Length, " Data: %u bytes", Length); COPY_TO_SERVER(); return true; } bool cConnection::HandleClientSlotSelect(void) { HANDLE_CLIENT_PACKET_READ(ReadBEInt16, Int16, SlotNum); Log("Received a PACKET_SLOT_SELECT from the client"); Log(" SlotNum = %d", SlotNum); COPY_TO_SERVER(); return true; } bool cConnection::HandleClientStatusPing(void) { HANDLE_CLIENT_PACKET_READ(ReadBEInt64, Int64, Time); Log("Received the status ping packet from the client:"); Log(" Time = %lld", Time); COPY_TO_SERVER(); return true; } bool cConnection::HandleClientStatusRequest(void) { Log("Received the status request packet from the client"); COPY_TO_SERVER(); return true; } bool cConnection::HandleClientTabCompletion(void) { HANDLE_CLIENT_PACKET_READ(ReadVarUTF8String, AString, Query); Log("Received a PACKET_TAB_COMPLETION query from the client"); Log(" Query = \"%s\"", Query.c_str()); COPY_TO_SERVER(); return true; } bool cConnection::HandleClientUpdateSign(void) { HANDLE_CLIENT_PACKET_READ(ReadBEInt32, Int32, BlockX); HANDLE_CLIENT_PACKET_READ(ReadBEInt16, Int16, BlockY); HANDLE_CLIENT_PACKET_READ(ReadBEInt32, Int32, BlockZ); HANDLE_CLIENT_PACKET_READ(ReadVarUTF8String, AString, Line1); HANDLE_CLIENT_PACKET_READ(ReadVarUTF8String, AString, Line2); HANDLE_CLIENT_PACKET_READ(ReadVarUTF8String, AString, Line3); HANDLE_CLIENT_PACKET_READ(ReadVarUTF8String, AString, Line4); Log("Received a PACKET_UPDATE_SIGN from the client:"); Log(" Block = {%d, %d, %d}", BlockX, BlockY, BlockZ); Log(" Lines = \"%s\", \"%s\", \"%s\", \"%s\"", Line1.c_str(), Line2.c_str(), Line3.c_str(), Line4.c_str()); COPY_TO_SERVER(); return true; } bool cConnection::HandleClientUseEntity(void) { HANDLE_CLIENT_PACKET_READ(ReadBEUInt32, UInt32, EntityID); HANDLE_CLIENT_PACKET_READ(ReadBEUInt8, UInt8, MouseButton); Log("Received a PACKET_USE_ENTITY from the client:"); Log(" EntityID = %d", EntityID); Log(" MouseButton = %u", MouseButton); COPY_TO_SERVER(); return true; } bool cConnection::HandleClientWindowClick(void) { HANDLE_CLIENT_PACKET_READ(ReadBEUInt8, UInt8, WindowID); HANDLE_CLIENT_PACKET_READ(ReadBEUInt16, UInt16, SlotNum); HANDLE_CLIENT_PACKET_READ(ReadBEUInt8, UInt8, Button); HANDLE_CLIENT_PACKET_READ(ReadBEUInt16, UInt16, TransactionID); HANDLE_CLIENT_PACKET_READ(ReadBEUInt8, UInt8, Mode); AString Item; if (!ParseSlot(m_ClientBuffer, Item)) { return false; } Log("Received a PACKET_WINDOW_CLICK from the client"); Log(" WindowID = %u", WindowID); Log(" SlotNum = %u", SlotNum); Log(" Button = %u, Mode = %u", Button, Mode); Log(" TransactionID = 0x%x", TransactionID); Log(" ClickedItem = %s", Item.c_str()); COPY_TO_SERVER(); return true; } bool cConnection::HandleClientWindowClose(void) { HANDLE_CLIENT_PACKET_READ(ReadBEUInt8, UInt8, WindowID); Log("Received a PACKET_WINDOW_CLOSE from the client:"); Log(" WindowID = %u", WindowID); COPY_TO_SERVER(); return true; } bool cConnection::HandleClientUnknownPacket(UInt32 a_PacketType, UInt32 a_PacketLen, UInt32 a_PacketReadSoFar) { ContiguousByteBuffer Data; if (!m_ClientBuffer.ReadSome(Data, a_PacketLen - a_PacketReadSoFar)) { return false; } DataLog(Data.data(), Data.size(), "****************** Unknown packet 0x%x from the client; relaying and ignoring", a_PacketType); COPY_TO_SERVER(); return true; } //////////////////////////////////////////////////////////////////////////////// // packet handling, server-side, login: bool cConnection::HandleServerLoginDisconnect(void) { HANDLE_SERVER_PACKET_READ(ReadVarUTF8String, AString, Reason); Log("Received a login-disconnect packet from the server:"); Log(" Reason = \"%s\"", Reason.c_str()); COPY_TO_CLIENT(); return true; } bool cConnection::HandleServerLoginEncryptionKeyRequest(void) { // Read the packet from the server: HANDLE_SERVER_PACKET_READ(ReadVarUTF8String, AString, ServerID); HANDLE_SERVER_PACKET_READ(ReadBEUInt16, UInt16, PublicKeyLength); ContiguousByteBuffer PublicKey; if (!m_ServerBuffer.ReadSome(PublicKey, PublicKeyLength)) { return false; } HANDLE_SERVER_PACKET_READ(ReadBEUInt16, UInt16, NonceLength); ContiguousByteBuffer Nonce; if (!m_ServerBuffer.ReadSome(Nonce, NonceLength)) { return false; } Log("Got PACKET_ENCRYPTION_KEY_REQUEST from the SERVER:"); Log(" ServerID = %s", ServerID.c_str()); DataLog(PublicKey.data(), PublicKey.size(), " Public key (%u bytes)", static_cast(PublicKey.size())); // Reply to the server: SendEncryptionKeyResponse({ reinterpret_cast(PublicKey.data()), PublicKey.size() }, { reinterpret_cast(Nonce.data()), Nonce.size() }); // Do not send to client - we want the client connection open return true; } bool cConnection::HandleServerLoginSuccess(void) { HANDLE_SERVER_PACKET_READ(ReadVarUTF8String, AString, UUID); HANDLE_SERVER_PACKET_READ(ReadVarUTF8String, AString, Username); Log("Received a login success packet from the server:"); Log(" UUID = \"%s\"", UUID.c_str()); Log(" Username = \"%s\"", Username.c_str()); Log("Server is now in protocol state Game."); m_ServerProtocolState = 3; if (m_IsServerEncrypted) { Log("Server communication is now encrypted"); m_ServerState = csEncryptedUnderstood; DataLog(m_ServerEncryptionBuffer.data(), m_ServerEncryptionBuffer.size(), "Sending the queued data to server (%u bytes):", m_ServerEncryptionBuffer.size()); SERVERENCRYPTSEND(m_ServerEncryptionBuffer); m_ServerEncryptionBuffer.clear(); } COPY_TO_CLIENT(); Log("Client is now in protocol state Game."); m_ClientProtocolState = 3; return true; } //////////////////////////////////////////////////////////////////////////////// // packet handling, server-side, game: bool cConnection::HandleServerAttachEntity(void) { HANDLE_SERVER_PACKET_READ(ReadBEUInt32, UInt32, EntityID); HANDLE_SERVER_PACKET_READ(ReadBEUInt32, UInt32, VehicleID); HANDLE_SERVER_PACKET_READ(ReadBool, bool, IsOnLeash); Log("Received a PACKET_ATTACH_ENTITY from the server:"); Log(" EntityID = %u (0x%x)", EntityID, EntityID); Log(" VehicleID = %u (0x%x)", VehicleID, VehicleID); Log(" IsOnLeash = %s", IsOnLeash ? "true" : "false"); COPY_TO_CLIENT(); return true; } bool cConnection::HandleServerBlockAction(void) { HANDLE_SERVER_PACKET_READ(ReadBEInt32, Int32, BlockX); HANDLE_SERVER_PACKET_READ(ReadBEInt16, Int16, BlockY); HANDLE_SERVER_PACKET_READ(ReadBEInt32, Int32, BlockZ); HANDLE_SERVER_PACKET_READ(ReadBEUInt8, UInt8, Byte1); HANDLE_SERVER_PACKET_READ(ReadBEUInt8, UInt8, Byte2); HANDLE_SERVER_PACKET_READ(ReadVarInt, UInt32, BlockID); Log("Received a PACKET_BLOCK_ACTION from the server:"); Log(" Pos = {%d, %d, %d}", BlockX, BlockY, BlockZ); Log(" Bytes = (%u, %u) == (0x%x, 0x%x)", Byte1, Byte2, Byte1, Byte2); Log(" BlockID = %u", BlockID); COPY_TO_CLIENT(); return true; } bool cConnection::HandleServerBlockChange(void) { HANDLE_SERVER_PACKET_READ(ReadBEInt32, Int32, BlockX); HANDLE_SERVER_PACKET_READ(ReadBEUInt8, UInt8, BlockY); HANDLE_SERVER_PACKET_READ(ReadBEInt32, Int32, BlockZ); HANDLE_SERVER_PACKET_READ(ReadVarInt, UInt32, BlockType); HANDLE_SERVER_PACKET_READ(ReadBEUInt8, UInt8, BlockMeta); Log("Received a PACKET_BLOCK_CHANGE from the server"); Log(" Pos = {%d, %u, %d}", BlockX, BlockY, BlockZ); Log(" BlockType = %u (0x%x", BlockType, BlockType); Log(" BlockMeta = %u", BlockMeta); COPY_TO_CLIENT(); return true; } bool cConnection::HandleServerChangeGameState(void) { HANDLE_SERVER_PACKET_READ(ReadBEUInt8, UInt8, Reason); HANDLE_SERVER_PACKET_READ(ReadBEFloat, float, Data); Log("Received a PACKET_CHANGE_GAME_STATE from the server:"); Log(" Reason = %u", Reason); Log(" Data = %f", Data); COPY_TO_CLIENT(); return true; } bool cConnection::HandleServerChatMessage(void) { HANDLE_SERVER_PACKET_READ(ReadVarUTF8String, AString, Message); Log("Received a PACKET_CHAT_MESSAGE from the server:"); Log(" Message = \"%s\"", Message.c_str()); COPY_TO_CLIENT(); return true; } bool cConnection::HandleServerCollectPickup(void) { HANDLE_SERVER_PACKET_READ(ReadBEUInt32, UInt32, CollectedID); HANDLE_SERVER_PACKET_READ(ReadBEUInt32, UInt32, CollectorID); Log("Received a PACKET_COLLECT_PICKUP from the server:"); Log(" CollectedID = %u", CollectedID); Log(" CollectorID = %u", CollectorID); COPY_TO_CLIENT(); return true; } bool cConnection::HandleServerCompass(void) { HANDLE_SERVER_PACKET_READ(ReadBEInt32, Int32, SpawnX); HANDLE_SERVER_PACKET_READ(ReadBEInt32, Int32, SpawnY); HANDLE_SERVER_PACKET_READ(ReadBEInt32, Int32, SpawnZ); Log("Received PACKET_COMPASS from the server:"); Log(" Spawn = {%d, %d, %d}", SpawnX, SpawnY, SpawnZ); COPY_TO_CLIENT(); return true; } bool cConnection::HandleServerDestroyEntities(void) { HANDLE_SERVER_PACKET_READ(ReadBEUInt8, UInt8, NumEntities); if (!m_ServerBuffer.SkipRead(static_cast(NumEntities) * 4)) { return false; } Log("Received PACKET_DESTROY_ENTITIES from the server:"); Log(" NumEntities = %u", NumEntities); COPY_TO_CLIENT(); return true; } bool cConnection::HandleServerEntity(void) { HANDLE_SERVER_PACKET_READ(ReadBEUInt32, UInt32, EntityID); Log("Received a PACKET_ENTITY from the server:"); Log(" EntityID = %u", EntityID); COPY_TO_CLIENT(); return true; } bool cConnection::HandleServerEntityEquipment(void) { HANDLE_SERVER_PACKET_READ(ReadBEUInt32, UInt32, EntityID); HANDLE_SERVER_PACKET_READ(ReadBEUInt16, UInt16, SlotNum); AString Item; if (!ParseSlot(m_ServerBuffer, Item)) { return false; } Log("Received a PACKET_ENTITY_EQUIPMENT from the server:"); Log(" EntityID = %u", EntityID); Log(" SlotNum = %u", SlotNum); Log(" Item = %s", Item.c_str()); COPY_TO_CLIENT(); return true; } bool cConnection::HandleServerEntityHeadLook(void) { HANDLE_SERVER_PACKET_READ(ReadBEUInt32, UInt32, EntityID); HANDLE_SERVER_PACKET_READ(ReadBEUInt8, UInt8, HeadYaw); Log("Received a PACKET_ENTITY_HEAD_LOOK from the server:"); Log(" EntityID = %u", EntityID); Log(" HeadYaw = %u", HeadYaw); COPY_TO_CLIENT(); return true; } bool cConnection::HandleServerEntityLook(void) { HANDLE_SERVER_PACKET_READ(ReadBEUInt32, UInt32, EntityID); HANDLE_SERVER_PACKET_READ(ReadBEUInt8, UInt8, Yaw); HANDLE_SERVER_PACKET_READ(ReadBEUInt8, UInt8, Pitch); Log("Received a PACKET_ENTITY_LOOK from the server:"); Log(" EntityID = %u", EntityID); Log(" Yaw = %u", Yaw); Log(" Pitch = %u", Pitch); COPY_TO_CLIENT(); return true; } bool cConnection::HandleServerEntityMetadata(void) { HANDLE_SERVER_PACKET_READ(ReadBEUInt32, UInt32, EntityID); AString Metadata; if (!ParseMetadata(m_ServerBuffer, Metadata)) { return false; } AString HexDump; CreateHexDump(HexDump, Metadata.data(), Metadata.size(), 32); Log("Received a PACKET_ENTITY_METADATA from the server:"); Log(" EntityID = %u", EntityID); auto len = static_cast(Metadata.length()); Log(" Metadata, length = %u (0x%x):\n%s", len, len, HexDump.c_str()); LogMetadata(Metadata, 4); COPY_TO_CLIENT(); return true; } bool cConnection::HandleServerEntityProperties(void) { HANDLE_SERVER_PACKET_READ(ReadBEUInt32, UInt32, EntityID); HANDLE_SERVER_PACKET_READ(ReadBEUInt32, UInt32, Count); Log("Received a PACKET_ENTITY_PROPERTIES from the server:"); Log(" EntityID = %u", EntityID); Log(" Count = %u", Count); for (UInt32 i = 0; i < Count; i++) { HANDLE_SERVER_PACKET_READ(ReadVarUTF8String, AString, Key); HANDLE_SERVER_PACKET_READ(ReadBEDouble, double, Value); HANDLE_SERVER_PACKET_READ(ReadBEUInt16, UInt16, ListLength); Log(" \"%s\" = %f; %u modifiers", Key.c_str(), Value, ListLength); for (UInt16 j = 0; j < ListLength; j++) { HANDLE_SERVER_PACKET_READ(ReadBEUInt64, UInt64, UUIDHi); HANDLE_SERVER_PACKET_READ(ReadBEUInt64, UInt64, UUIDLo); HANDLE_SERVER_PACKET_READ(ReadBEDouble, double, DblVal); HANDLE_SERVER_PACKET_READ(ReadBEUInt8, UInt8, ByteVal); Log(" [%d] = {0x%08llx%08llx, %f, %u}", j, UUIDHi, UUIDLo, DblVal, ByteVal); } } // for i COPY_TO_CLIENT(); return true; } bool cConnection::HandleServerEntityRelativeMove(void) { HANDLE_SERVER_PACKET_READ(ReadBEUInt32, UInt32, EntityID); HANDLE_SERVER_PACKET_READ(ReadBEInt8, Int8, dx); HANDLE_SERVER_PACKET_READ(ReadBEInt8, Int8, dy); HANDLE_SERVER_PACKET_READ(ReadBEInt8, Int8, dz); Log("Received a PACKET_ENTITY_RELATIVE_MOVE from the server:"); Log(" EntityID = %u", EntityID); Log(" RelMove = %s", PrintableAbsIntTriplet(dx, dy, dz).c_str()); COPY_TO_CLIENT(); return true; } bool cConnection::HandleServerEntityRelativeMoveLook(void) { HANDLE_SERVER_PACKET_READ(ReadBEUInt32, UInt32, EntityID); HANDLE_SERVER_PACKET_READ(ReadBEInt8, Int8, dx); HANDLE_SERVER_PACKET_READ(ReadBEInt8, Int8, dy); HANDLE_SERVER_PACKET_READ(ReadBEInt8, Int8, dz); HANDLE_SERVER_PACKET_READ(ReadBEUInt8, UInt8, Yaw); HANDLE_SERVER_PACKET_READ(ReadBEUInt8, UInt8, Pitch); Log("Received a PACKET_ENTITY_RELATIVE_MOVE_LOOK from the server:"); Log(" EntityID = %u", EntityID); Log(" RelMove = %s", PrintableAbsIntTriplet(dx, dy, dz).c_str()); Log(" Yaw = %u", Yaw); Log(" Pitch = %u", Pitch); COPY_TO_CLIENT(); return true; } bool cConnection::HandleServerEntityStatus(void) { HANDLE_SERVER_PACKET_READ(ReadBEUInt32, UInt32, EntityID); HANDLE_SERVER_PACKET_READ(ReadBEUInt8, UInt8, Status); Log("Received a PACKET_ENTITY_STATUS from the server:"); Log(" EntityID = %u", EntityID); Log(" Status = %u (0x%02x)", Status, Status); COPY_TO_CLIENT(); return true; } bool cConnection::HandleServerEntityTeleport(void) { HANDLE_SERVER_PACKET_READ(ReadBEUInt32, UInt32, EntityID); HANDLE_SERVER_PACKET_READ(ReadBEInt32, Int32, AbsX); HANDLE_SERVER_PACKET_READ(ReadBEInt32, Int32, AbsY); HANDLE_SERVER_PACKET_READ(ReadBEInt32, Int32, AbsZ); HANDLE_SERVER_PACKET_READ(ReadBEUInt8, UInt8, Yaw); HANDLE_SERVER_PACKET_READ(ReadBEUInt8, UInt8, Pitch); Log("Received a PACKET_ENTITY_TELEPORT from the server:"); Log(" EntityID = %u", EntityID); Log(" Pos = %s", PrintableAbsIntTriplet(AbsX, AbsY, AbsZ).c_str()); Log(" Yaw = %u", Yaw); Log(" Pitch = %u", Pitch); COPY_TO_CLIENT(); return true; } bool cConnection::HandleServerEntityVelocity(void) { HANDLE_SERVER_PACKET_READ(ReadBEUInt32, UInt32, EntityID); HANDLE_SERVER_PACKET_READ(ReadBEInt16, Int16, VelocityX); HANDLE_SERVER_PACKET_READ(ReadBEInt16, Int16, VelocityY); HANDLE_SERVER_PACKET_READ(ReadBEInt16, Int16, VelocityZ); Log("Received a PACKET_ENTITY_VELOCITY from the server:"); Log(" EntityID = %u", EntityID); Log(" Velocity = %s", PrintableAbsIntTriplet(VelocityX, VelocityY, VelocityZ, 8000).c_str()); COPY_TO_CLIENT(); return true; } bool cConnection::HandleServerExplosion(void) { HANDLE_SERVER_PACKET_READ(ReadBEFloat, float, PosX); HANDLE_SERVER_PACKET_READ(ReadBEFloat, float, PosY); HANDLE_SERVER_PACKET_READ(ReadBEFloat, float, PosZ); HANDLE_SERVER_PACKET_READ(ReadBEFloat, float, Force); HANDLE_SERVER_PACKET_READ(ReadBEUInt32, UInt32, NumRecords); std::vector Records; Records.reserve(NumRecords); int PosXI = static_cast(PosX), PosYI = static_cast(PosY), PosZI = static_cast(PosZ); for (UInt32 i = 0; i < NumRecords; i++) { HANDLE_SERVER_PACKET_READ(ReadBEInt8, Int8, rx); HANDLE_SERVER_PACKET_READ(ReadBEInt8, Int8, ry); HANDLE_SERVER_PACKET_READ(ReadBEInt8, Int8, rz); Records.push_back(sCoords(PosXI + rx, PosYI + ry, PosZI + rz)); } HANDLE_SERVER_PACKET_READ(ReadBEFloat, float, PlayerMotionX); HANDLE_SERVER_PACKET_READ(ReadBEFloat, float, PlayerMotionY); HANDLE_SERVER_PACKET_READ(ReadBEFloat, float, PlayerMotionZ); Log("Received a PACKET_EXPLOSION from the server:"); Log(" Pos = {%.02f, %.02f, %.02f}", PosX, PosY, PosZ); Log(" Force = %.02f", Force); Log(" NumRecords = %u", NumRecords); for (UInt32 i = 0; i < NumRecords; i++) { Log(" Records[%u] = {%d, %d, %d}", i, Records[i].x, Records[i].y, Records[i].z); } Log(" Player motion = <%.02f, %.02f, %.02f>", PlayerMotionX, PlayerMotionY, PlayerMotionZ); COPY_TO_CLIENT(); return true; } bool cConnection::HandleServerIncrementStatistic(void) { // 0xc8 HANDLE_SERVER_PACKET_READ(ReadBEUInt32, UInt32, StatisticID); HANDLE_SERVER_PACKET_READ(ReadBEInt32, Int32, Amount); Log("Received a PACKET_INCREMENT_STATISTIC from the server:"); Log(" StatisticID = %u (0x%x)", StatisticID, StatisticID); Log(" Amount = %d", Amount); COPY_TO_CLIENT(); return true; } bool cConnection::HandleServerJoinGame(void) { HANDLE_SERVER_PACKET_READ(ReadBEUInt32, UInt32, EntityID); HANDLE_SERVER_PACKET_READ(ReadBEUInt8, UInt8, GameMode); HANDLE_SERVER_PACKET_READ(ReadBEUInt8, UInt8, Dimension); HANDLE_SERVER_PACKET_READ(ReadBEUInt8, UInt8, Difficulty); HANDLE_SERVER_PACKET_READ(ReadBEUInt8, UInt8, MaxPlayers); HANDLE_SERVER_PACKET_READ(ReadVarUTF8String, AString, LevelType); Log("Received a PACKET_LOGIN from the server:"); Log(" EntityID = %u", EntityID); Log(" GameMode = %u", GameMode); Log(" Dimension = %u", Dimension); Log(" Difficulty = %u", Difficulty); Log(" MaxPlayers = %u", MaxPlayers); Log(" LevelType = \"%s\"", LevelType.c_str()); COPY_TO_CLIENT(); return true; } bool cConnection::HandleServerKeepAlive(void) { HANDLE_SERVER_PACKET_READ(ReadBEUInt32, UInt32, PingID); Log("Received a PACKET_KEEP_ALIVE from the server:"); Log(" ID = %u", PingID); COPY_TO_CLIENT(); return true; } bool cConnection::HandleServerKick(void) { HANDLE_SERVER_PACKET_READ(ReadVarUTF8String, AString, Reason); Log("Received PACKET_KICK from the SERVER:"); if (m_HasClientPinged) { Log(" This was a std reply to client's PING"); AStringVector Split; // Split by NULL chars (StringSplit() won't work here): size_t Last = 0; size_t Len = Reason.size(); for (size_t i = 0; i < Len; i++) { if (Reason[i] == 0) { Split.push_back(Reason.substr(Last, i - Last)); Last = i + 1; } } if (Last < Len) { Split.push_back(Reason.substr(Last)); } if (Split.size() == 6) { Log(" Preamble: \"%s\"", Split[0]); Log(" Protocol version: \"%s\"", Split[1]); Log(" Server version: \"%s\"", Split[2]); Log(" MOTD: \"%s\"", Split[3]); Log(" Cur players: \"%s\"", Split[4]); Log(" Max players: \"%s\"", Split[5]); // Modify the MOTD to show that it's being ProtoProxied: Reason.assign(Split[0]); Reason.push_back(0); Reason.append(Split[1]); Reason.push_back(0); Reason.append(Split[2]); Reason.push_back(0); Reason.append(fmt::format(FMT_STRING("ProtoProxy: {}"), Split[3])); Reason.push_back(0); Reason.append(Split[4]); Reason.push_back(0); Reason.append(Split[5]); auto ReasonBE16 = UTF8ToRawBEUTF16(Reason); AString PacketStart("\xff"); PacketStart.push_back(static_cast(ReasonBE16.size() / 256)); PacketStart.push_back(static_cast(ReasonBE16.size() % 256)); CLIENTSEND({ reinterpret_cast(PacketStart.data()), PacketStart.size() }); CLIENTSEND({ reinterpret_cast(ReasonBE16.data()), ReasonBE16.size() * sizeof(char16_t) }); return true; } else { DataLog(Reason.data(), Reason.size(), " Unknown reply format, dumping hex:"); } } else { Log(" Reason = \"%s\"", Reason); } COPY_TO_CLIENT(); return true; } bool cConnection::HandleServerMapChunk(void) { HANDLE_SERVER_PACKET_READ(ReadBEInt32, Int32, ChunkX); HANDLE_SERVER_PACKET_READ(ReadBEInt32, Int32, ChunkZ); HANDLE_SERVER_PACKET_READ(ReadBEUInt8, UInt8, IsContiguous); HANDLE_SERVER_PACKET_READ(ReadBEUInt16, UInt16, PrimaryBitmap); HANDLE_SERVER_PACKET_READ(ReadBEUInt16, UInt16, AdditionalBitmap); HANDLE_SERVER_PACKET_READ(ReadBEUInt32, UInt32, CompressedSize); ContiguousByteBuffer CompressedData; if (!m_ServerBuffer.ReadSome(CompressedData, CompressedSize)) { return false; } Log("Received a PACKET_MAP_CHUNK from the server:"); Log(" ChunkPos = [%d, %d]", ChunkX, ChunkZ); Log(" Compressed size = %u (0x%x)", CompressedSize, CompressedSize); // TODO: Save the compressed data into a file for later analysis COPY_TO_CLIENT(); return true; } bool cConnection::HandleServerMapChunkBulk(void) { HANDLE_SERVER_PACKET_READ(ReadBEUInt16, UInt16, ChunkCount); HANDLE_SERVER_PACKET_READ(ReadBEUInt32, UInt32, CompressedSize); HANDLE_SERVER_PACKET_READ(ReadBool, bool, IsSkyLightSent); ContiguousByteBuffer CompressedData; if (!m_ServerBuffer.ReadSome(CompressedData, CompressedSize)) { return false; } // Read individual chunk metas. // Need to read them first and only then start logging (in case we don't have the full packet yet) typedef std::vector sChunkMetas; sChunkMetas ChunkMetas; ChunkMetas.reserve(ChunkCount); for (short i = 0; i < ChunkCount; i++) { HANDLE_SERVER_PACKET_READ(ReadBEInt32, Int32, ChunkX); HANDLE_SERVER_PACKET_READ(ReadBEInt32, Int32, ChunkZ); HANDLE_SERVER_PACKET_READ(ReadBEInt16, Int16, PrimaryBitmap); HANDLE_SERVER_PACKET_READ(ReadBEInt16, Int16, AddBitmap); ChunkMetas.push_back(sChunkMeta(ChunkX, ChunkZ, PrimaryBitmap, AddBitmap)); } Log("Received a PACKET_MAP_CHUNK_BULK from the server:"); Log(" ChunkCount = %u", ChunkCount); Log(" Compressed size = %u (0x%x)", CompressedSize, CompressedSize); Log(" IsSkyLightSent = %s", IsSkyLightSent ? "true" : "false"); // Log individual chunk coords: int idx = 0; for (sChunkMetas::iterator itr = ChunkMetas.begin(), end = ChunkMetas.end(); itr != end; ++itr, ++idx) { Log(" [%d]: [%d, %d], primary bitmap 0x%02x, add bitmap 0x%02x", idx, itr->m_ChunkX, itr->m_ChunkZ, itr->m_PrimaryBitmap, itr->m_AddBitmap ); } // for itr - ChunkMetas[] // TODO: Save the compressed data into a file for later analysis COPY_TO_CLIENT(); return true; } bool cConnection::HandleServerMultiBlockChange(void) { HANDLE_SERVER_PACKET_READ(ReadBEInt32, Int32, ChunkX); HANDLE_SERVER_PACKET_READ(ReadBEInt32, Int32, ChunkZ); HANDLE_SERVER_PACKET_READ(ReadBEUInt16, UInt16, NumBlocks); HANDLE_SERVER_PACKET_READ(ReadBEUInt32, UInt32, DataSize); ContiguousByteBuffer BlockChangeData; if (!m_ServerBuffer.ReadSome(BlockChangeData, DataSize)) { return false; } Log("Received a PACKET_MULTI_BLOCK_CHANGE packet from the server:"); Log(" Chunk = [%d, %d]", ChunkX, ChunkZ); Log(" NumBlocks = %u", NumBlocks); COPY_TO_CLIENT(); return true; } bool cConnection::HandleServerNamedSoundEffect(void) { HANDLE_SERVER_PACKET_READ(ReadVarUTF8String, AString, SoundName); HANDLE_SERVER_PACKET_READ(ReadBEInt32, Int32, PosX); HANDLE_SERVER_PACKET_READ(ReadBEInt32, Int32, PosY); HANDLE_SERVER_PACKET_READ(ReadBEInt32, Int32, PosZ); HANDLE_SERVER_PACKET_READ(ReadBEFloat, float, Volume); HANDLE_SERVER_PACKET_READ(ReadBEUInt8, UInt8, Pitch); Log("Received a PACKET_NAMED_SOUND_EFFECT from the server:"); Log(" SoundName = \"%s\"", SoundName.c_str()); Log(" Pos = %s", PrintableAbsIntTriplet(PosX, PosY, PosZ, 8).c_str()); Log(" Volume = %f", Volume); Log(" Pitch = %u", Pitch); COPY_TO_CLIENT(); return true; } bool cConnection::HandleServerPlayerAbilities(void) { HANDLE_SERVER_PACKET_READ(ReadBEUInt8, UInt8, Flags); HANDLE_SERVER_PACKET_READ(ReadBEFloat, float, FlyingSpeed); HANDLE_SERVER_PACKET_READ(ReadBEFloat, float, WalkingSpeed); Log("Received a PACKET_PLAYER_ABILITIES from the server:"); Log(" Flags = %u (0x%02x)", Flags, Flags); Log(" FlyingSpeed = %f", FlyingSpeed); Log(" WalkingSpeed = %f", WalkingSpeed); COPY_TO_CLIENT(); return true; } bool cConnection::HandleServerPlayerAnimation(void) { HANDLE_SERVER_PACKET_READ(ReadVarInt, UInt32, PlayerID); HANDLE_SERVER_PACKET_READ(ReadBEUInt8, UInt8, AnimationID); Log("Received a PACKET_PLAYER_ANIMATION from the server:"); Log(" PlayerID: %u (0x%x)", PlayerID, PlayerID); Log(" Animation: %u", AnimationID); COPY_TO_CLIENT(); return true; } bool cConnection::HandleServerPlayerListItem(void) { HANDLE_SERVER_PACKET_READ(ReadVarUTF8String, AString, PlayerName); HANDLE_SERVER_PACKET_READ(ReadBool, bool, IsOnline); HANDLE_SERVER_PACKET_READ(ReadBEUInt16, UInt16, Ping); Log("Received a PACKET_PLAYERLIST_ITEM from the server:"); Log(" PlayerName = \"%s\" (%s)", PlayerName.c_str(), IsOnline ? "online" : "offline"); Log(" Ping = %d", Ping); COPY_TO_CLIENT(); return true; } bool cConnection::HandleServerPlayerPositionLook(void) { HANDLE_SERVER_PACKET_READ(ReadBEDouble, double, PosX); HANDLE_SERVER_PACKET_READ(ReadBEDouble, double, PosY); HANDLE_SERVER_PACKET_READ(ReadBEDouble, double, PosZ); HANDLE_SERVER_PACKET_READ(ReadBEFloat, float, Yaw); HANDLE_SERVER_PACKET_READ(ReadBEFloat, float, Pitch); HANDLE_SERVER_PACKET_READ(ReadBool, bool, IsOnGround); Log("Received a PACKET_PLAYER_POSITION_LOOK from the server"); // TODO: list packet contents COPY_TO_CLIENT(); return true; } bool cConnection::HandleServerPluginMessage(void) { HANDLE_SERVER_PACKET_READ(ReadVarUTF8String, AString, ChannelName); HANDLE_SERVER_PACKET_READ(ReadBEUInt16, UInt16, Length); ContiguousByteBuffer Data; if (!m_ServerBuffer.ReadSome(Data, Length)) { return false; } Log("Received a PACKET_PLUGIN_MESSAGE from the server"); Log(" ChannelName = \"%s\"", ChannelName.c_str()); DataLog(Data.data(), Length, " Data: %u bytes", Length); COPY_TO_CLIENT(); return true; } bool cConnection::HandleServerRespawn(void) { HANDLE_SERVER_PACKET_READ(ReadBEInt32, Int32, Dimension); HANDLE_SERVER_PACKET_READ(ReadBEUInt8, UInt8, Difficulty); HANDLE_SERVER_PACKET_READ(ReadBEUInt8, UInt8, GameMode); HANDLE_SERVER_PACKET_READ(ReadVarUTF8String, AString, LevelType); Log("Received a respawn packet from the server:"); Log(" Dimension = %d", Dimension); Log(" Difficulty = %u", Difficulty); Log(" GameMode = %u", GameMode); Log(" LevelType = \"%s\"", LevelType.c_str()); COPY_TO_CLIENT(); return true; } bool cConnection::HandleServerSetExperience(void) { HANDLE_SERVER_PACKET_READ(ReadBEFloat, float, ExperienceBar); HANDLE_SERVER_PACKET_READ(ReadBEUInt16, UInt16, Level); HANDLE_SERVER_PACKET_READ(ReadBEUInt16, UInt16, TotalExperience); Log("Received a PACKET_SET_EXPERIENCE from the server:"); Log(" ExperienceBar = %.05f", ExperienceBar); Log(" Level = %u", Level); Log(" TotalExperience = %u", TotalExperience); COPY_TO_CLIENT(); return true; } bool cConnection::HandleServerSetSlot(void) { HANDLE_SERVER_PACKET_READ(ReadBEUInt8, UInt8, WindowID); HANDLE_SERVER_PACKET_READ(ReadBEUInt16, UInt16, SlotNum); AString Item; if (!ParseSlot(m_ServerBuffer, Item)) { return false; } Log("Received a PACKET_SET_SLOT from the server:"); Log(" WindowID = %u", WindowID); Log(" SlotNum = %u", SlotNum); Log(" Item = %s", Item.c_str()); COPY_TO_CLIENT(); return true; } bool cConnection::HandleServerSlotSelect(void) { HANDLE_SERVER_PACKET_READ(ReadBEUInt8, UInt8, SlotNum); Log("Received a PACKET_SLOT_SELECT from the server:"); Log(" SlotNum = %u", SlotNum); COPY_TO_CLIENT(); return true; } bool cConnection::HandleServerSoundEffect(void) { HANDLE_SERVER_PACKET_READ(ReadBEInt32, Int32, EffectID); HANDLE_SERVER_PACKET_READ(ReadBEInt32, Int32, PosX); HANDLE_SERVER_PACKET_READ(ReadBEUInt8, UInt8, PosY); HANDLE_SERVER_PACKET_READ(ReadBEInt32, Int32, PosZ); HANDLE_SERVER_PACKET_READ(ReadBEInt32, Int32, Data); HANDLE_SERVER_PACKET_READ(ReadBool, bool, NoVolumeDecrease); Log("Received a PACKET_SOUND_EFFECT from the server:"); Log(" EffectID = %d", EffectID); Log(" Pos = {%d, %d, %d}", PosX, PosY, PosZ); Log(" Data = %d", Data); Log(" NoVolumeDecrease = %s", NoVolumeDecrease ? "true" : "false"); COPY_TO_CLIENT(); return true; } bool cConnection::HandleServerSpawnExperienceOrbs(void) { HANDLE_SERVER_PACKET_READ(ReadVarInt, UInt32, EntityID); HANDLE_SERVER_PACKET_READ(ReadBEInt32, Int32, PosX); HANDLE_SERVER_PACKET_READ(ReadBEInt32, Int32, PosY); HANDLE_SERVER_PACKET_READ(ReadBEInt32, Int32, PosZ); HANDLE_SERVER_PACKET_READ(ReadBEUInt16, UInt16, Count); Log("Received a SPAWN_EXPERIENCE_ORBS packet from the server:"); Log(" EntityID = %u (0x%x)", EntityID, EntityID); Log(" Pos = %s", PrintableAbsIntTriplet(PosX, PosY, PosZ).c_str()); Log(" Count = %u", Count); COPY_TO_CLIENT(); return true; } bool cConnection::HandleServerSpawnMob(void) { HANDLE_SERVER_PACKET_READ(ReadVarInt, UInt32, EntityID); HANDLE_SERVER_PACKET_READ(ReadBEUInt8, UInt8, MobType); HANDLE_SERVER_PACKET_READ(ReadBEInt32, Int32, PosX); HANDLE_SERVER_PACKET_READ(ReadBEInt32, Int32, PosY); HANDLE_SERVER_PACKET_READ(ReadBEInt32, Int32, PosZ); HANDLE_SERVER_PACKET_READ(ReadBEUInt8, UInt8, Yaw); HANDLE_SERVER_PACKET_READ(ReadBEUInt8, UInt8, Pitch); HANDLE_SERVER_PACKET_READ(ReadBEUInt8, UInt8, HeadYaw); HANDLE_SERVER_PACKET_READ(ReadBEInt16, Int16, VelocityX); HANDLE_SERVER_PACKET_READ(ReadBEInt16, Int16, VelocityY); HANDLE_SERVER_PACKET_READ(ReadBEInt16, Int16, VelocityZ); AString Metadata; if (!ParseMetadata(m_ServerBuffer, Metadata)) { return false; } AString HexDump; CreateHexDump(HexDump, Metadata.data(), Metadata.size(), 32); Log("Received a PACKET_SPAWN_MOB from the server:"); Log(" EntityID = %u (0x%x)", EntityID, EntityID); Log(" MobType = %u (0x%x)", MobType, MobType); Log(" Pos = %s", PrintableAbsIntTriplet(PosX, PosY, PosZ).c_str()); Log(" Angles = [%u, %u, %u]", Yaw, Pitch, HeadYaw); Log(" Velocity = %s", PrintableAbsIntTriplet(VelocityX, VelocityY, VelocityZ, 8000).c_str()); auto len = static_cast(Metadata.length()); Log(" Metadata, length = %u (0x%x):\n%s", len, len, HexDump.c_str()); LogMetadata(Metadata, 4); COPY_TO_CLIENT(); return true; } struct sSpawnData { AString m_Name; AString m_Value; AString m_Signature; sSpawnData(const AString & a_Name, const AString & a_Value, const AString & a_Signature) : m_Name(a_Name), m_Value(a_Value), m_Signature(a_Signature) { } }; typedef std::vector sSpawnDatas; bool cConnection::HandleServerSpawnNamedEntity(void) { HANDLE_SERVER_PACKET_READ(ReadVarInt, UInt32, EntityID); HANDLE_SERVER_PACKET_READ(ReadVarUTF8String, AString, EntityUUID); HANDLE_SERVER_PACKET_READ(ReadVarUTF8String, AString, EntityName); HANDLE_SERVER_PACKET_READ(ReadVarInt, UInt32, DataCount); sSpawnDatas Data; for (UInt32 i = 0; i < DataCount; i++) { HANDLE_SERVER_PACKET_READ(ReadVarUTF8String, AString, Name); HANDLE_SERVER_PACKET_READ(ReadVarUTF8String, AString, Value); HANDLE_SERVER_PACKET_READ(ReadVarUTF8String, AString, Signature); Data.push_back(sSpawnData(Name, Value, Signature)); } HANDLE_SERVER_PACKET_READ(ReadBEInt32, Int32, PosX); HANDLE_SERVER_PACKET_READ(ReadBEInt32, Int32, PosY); HANDLE_SERVER_PACKET_READ(ReadBEInt32, Int32, PosZ); HANDLE_SERVER_PACKET_READ(ReadBEUInt8, UInt8, Yaw); HANDLE_SERVER_PACKET_READ(ReadBEUInt8, UInt8, Pitch); HANDLE_SERVER_PACKET_READ(ReadBEUInt16, UInt16, SelectedItem); AString Metadata; if (!ParseMetadata(m_ServerBuffer, Metadata)) { return false; } AString HexDump; CreateHexDump(HexDump, Metadata.data(), Metadata.size(), 32); Log("Received a PACKET_SPAWN_NAMED_ENTITY from the server:"); Log(" EntityID = %u (0x%x)", EntityID, EntityID); Log(" UUID = \"%s\"", EntityUUID.c_str()); Log(" Name = \"%s\"", EntityName.c_str()); Log(" NumData = %u", DataCount); for (sSpawnDatas::const_iterator itr = Data.begin(), end = Data.end(); itr != end; ++itr) { Log(" Name = \"%s\", Value = \"%s\", Signature = \"%s\"", itr->m_Name.c_str(), itr->m_Value.c_str(), itr->m_Signature.c_str() ); } // for itr - Data[] Log(" Pos = %s", PrintableAbsIntTriplet(PosX, PosY, PosZ).c_str()); Log(" Rotation = ", Yaw, Pitch); Log(" SelectedItem = %u", SelectedItem); auto len = static_cast(Metadata.length()); Log(" Metadata, length = %u (0x%x):\n%s", len, len, HexDump.c_str()); LogMetadata(Metadata, 4); COPY_TO_CLIENT(); return true; } bool cConnection::HandleServerSpawnObjectVehicle(void) { #ifdef _DEBUG // DEBUG: // This packet is still troublesome when DataIndicator != 0 ContiguousByteBuffer Buffer; m_ServerBuffer.ResetRead(); m_ServerBuffer.ReadAll(Buffer); m_ServerBuffer.ResetRead(); UInt32 PacketLen, PacketType; m_ServerBuffer.ReadVarInt(PacketLen); m_ServerBuffer.ReadVarInt(PacketType); if (Buffer.size() > 128) { // Only log up to 128 bytes Buffer.erase(128, AString::npos); } DataLog(Buffer.data(), Buffer.size(), "Buffer while parsing the PACKET_SPAWN_OBJECT_VEHICLE packet (%u bytes):", static_cast(Buffer.size())); #endif // _DEBUG HANDLE_SERVER_PACKET_READ(ReadVarInt, UInt32, EntityID); HANDLE_SERVER_PACKET_READ(ReadBEUInt8, UInt8, ObjType); HANDLE_SERVER_PACKET_READ(ReadBEInt32, Int32, PosX); HANDLE_SERVER_PACKET_READ(ReadBEInt32, Int32, PosY); HANDLE_SERVER_PACKET_READ(ReadBEInt32, Int32, PosZ); HANDLE_SERVER_PACKET_READ(ReadBEUInt8, UInt8, Pitch); HANDLE_SERVER_PACKET_READ(ReadBEUInt8, UInt8, Yaw); HANDLE_SERVER_PACKET_READ(ReadBEUInt32, UInt32, DataIndicator); AString ExtraData; Int16 VelocityX = 0; Int16 VelocityY = 0; Int16 VelocityZ = 0; if (DataIndicator != 0) { HANDLE_SERVER_PACKET_READ(ReadBEInt16, Int16, SpeedX); HANDLE_SERVER_PACKET_READ(ReadBEInt16, Int16, SpeedY); HANDLE_SERVER_PACKET_READ(ReadBEInt16, Int16, SpeedZ); VelocityX = SpeedX; VelocityY = SpeedY; VelocityZ = SpeedZ; // Speed vars are local to this scope, but we need them available later /* // This doesn't seem to work - for a falling block I'm getting no extra data at all int ExtraLen = 0; switch (ObjType) { case OBJECT_FALLING_BLOCK: ExtraLen = 4; break; // int: BlockType | (BlockMeta << 12) case OBJECT_ARROW: case OBJECT_SNOWBALL: case OBJECT_EGG: case OBJECT_EYE_OF_ENDER: case OBJECT_DRAGON_EGG: case OBJECT_FISHING_FLOAT: { ExtraLen = 4; break; // int: EntityID of the thrower } // TODO: Splash potions } if ((ExtraLen > 0) && !m_ServerBuffer.ReadSome(ExtraData, ExtraLen)) { return false; } */ } Log("Received a PACKET_SPAWN_OBJECT_VEHICLE from the server:"); Log(" EntityID = %u (0x%x)", EntityID, EntityID); Log(" ObjType = %u (0x%x)", ObjType, ObjType); Log(" Pos = %s", PrintableAbsIntTriplet(PosX, PosY, PosZ).c_str()); Log(" Rotation = ", Yaw, Pitch); Log(" DataIndicator = %u (0x%x)", DataIndicator, DataIndicator); if (DataIndicator != 0) { Log(" Velocity = %s", PrintableAbsIntTriplet(VelocityX, VelocityY, VelocityZ, 8000).c_str()); DataLog(ExtraData.data(), ExtraData.size(), " ExtraData size = %u:", static_cast(ExtraData.size())); } COPY_TO_CLIENT(); return true; } bool cConnection::HandleServerSpawnPainting(void) { HANDLE_SERVER_PACKET_READ(ReadVarInt, UInt32, EntityID); HANDLE_SERVER_PACKET_READ(ReadVarUTF8String, AString, ImageName); HANDLE_SERVER_PACKET_READ(ReadBEInt32, Int32, PosX); HANDLE_SERVER_PACKET_READ(ReadBEInt32, Int32, PosY); HANDLE_SERVER_PACKET_READ(ReadBEInt32, Int32, PosZ); HANDLE_SERVER_PACKET_READ(ReadBEInt32, Int32, Direction); Log("Received a PACKET_SPAWN_PAINTING from the server:"); Log(" EntityID = %u", EntityID); Log(" ImageName = \"%s\"", ImageName.c_str()); Log(" Pos = %s", PrintableAbsIntTriplet(PosX, PosY, PosZ).c_str()); Log(" Direction = %d", Direction); COPY_TO_CLIENT(); return true; } bool cConnection::HandleServerSpawnPickup(void) { HANDLE_SERVER_PACKET_READ(ReadBEUInt32, UInt32, EntityID); AString ItemDesc; if (!ParseSlot(m_ServerBuffer, ItemDesc)) { return false; } HANDLE_SERVER_PACKET_READ(ReadBEInt32, Int32, PosX); HANDLE_SERVER_PACKET_READ(ReadBEInt32, Int32, PosY); HANDLE_SERVER_PACKET_READ(ReadBEInt32, Int32, PosZ); HANDLE_SERVER_PACKET_READ(ReadBEUInt8, UInt8, Yaw); HANDLE_SERVER_PACKET_READ(ReadBEUInt8, UInt8, Pitch); HANDLE_SERVER_PACKET_READ(ReadBEUInt8, UInt8, Roll); Log("Received a PACKET_SPAWN_PICKUP from the server:"); Log(" EntityID = %d", EntityID); Log(" Item = %s", ItemDesc.c_str()); Log(" Pos = %s", PrintableAbsIntTriplet(PosX, PosY, PosZ).c_str()); Log(" Angles = [%u, %u, %u]", Yaw, Pitch, Roll); COPY_TO_CLIENT(); return true; } bool cConnection::HandleServerStatistics(void) { HANDLE_SERVER_PACKET_READ(ReadVarInt, UInt32, NumEntries); for (UInt32 i = 0; i < NumEntries; i++) { HANDLE_SERVER_PACKET_READ(ReadVarUTF8String, AString, StatName); HANDLE_SERVER_PACKET_READ(ReadVarInt, UInt32, StatValue); } COPY_TO_CLIENT(); return true; } bool cConnection::HandleServerStatusPing(void) { HANDLE_SERVER_PACKET_READ(ReadBEInt64, Int64, Time); Log("Received server's ping response:"); Log(" Time = %lld", Time); COPY_TO_CLIENT(); return true; } bool cConnection::HandleServerStatusResponse(void) { HANDLE_SERVER_PACKET_READ(ReadVarUTF8String, AString, Response); Log("Received server's status response:"); Log(" Response: %s", Response.c_str()); // Modify the response to show that it's being proto-proxied: const char DescSearch[] = "\"description\":{\"text\":\""; size_t idx = Response.find(DescSearch); if (idx != AString::npos) { Response.assign(Response.substr(0, idx + sizeof(DescSearch) - 1) + "ProtoProxy: " + Response.substr(idx + sizeof(DescSearch) - 1)); } else { Log("Cannot find the description json element, ProtoProxy signature not inserted"); } cByteBuffer Packet(Response.size() + 50); Packet.WriteVarInt32(0); // Packet type - status response Packet.WriteVarUTF8String(Response); ContiguousByteBuffer Pkt; Packet.ReadAll(Pkt); cByteBuffer ToClient(Response.size() + 50); ToClient.WriteVarInt32(static_cast(Pkt.size())); ToClient.Write(Pkt.data(), Pkt.size()); CLIENTSEND(ToClient); return true; } bool cConnection::HandleServerTabCompletion(void) { HANDLE_SERVER_PACKET_READ(ReadVarInt, UInt32, NumResults); HANDLE_SERVER_PACKET_READ(ReadVarUTF8String, AString, Results); Log("Received a PACKET_TAB_COMPLETION from the server, results given:"); // Parse the zero-terminated list of results: size_t len = Results.size(); size_t last = 0; for (size_t i = 0; i < len; i++) { if (Results[i] == 0) { Log(" \"%s\"", Results.substr(last, i - last).c_str()); last = i + 1; } } if (last < len) { Log(" \"%s\"", Results.substr(last, len - last).c_str()); } COPY_TO_CLIENT(); return true; } bool cConnection::HandleServerTimeUpdate(void) { HANDLE_SERVER_PACKET_READ(ReadBEUInt64, UInt64, WorldAge); HANDLE_SERVER_PACKET_READ(ReadBEUInt64, UInt64, TimeOfDay); Log("Received a PACKET_TIME_UPDATE from the server"); COPY_TO_CLIENT(); return true; } bool cConnection::HandleServerUpdateHealth(void) { HANDLE_SERVER_PACKET_READ(ReadBEFloat, float, Health); HANDLE_SERVER_PACKET_READ(ReadBEInt16, Int16, Food); HANDLE_SERVER_PACKET_READ(ReadBEFloat, float, Saturation); Log("Received a PACKET_UPDATE_HEALTH from the server"); COPY_TO_CLIENT(); return true; } bool cConnection::HandleServerUpdateSign(void) { HANDLE_SERVER_PACKET_READ(ReadBEInt32, Int32, BlockX); HANDLE_SERVER_PACKET_READ(ReadBEInt16, Int16, BlockY); HANDLE_SERVER_PACKET_READ(ReadBEInt32, Int32, BlockZ); HANDLE_SERVER_PACKET_READ(ReadVarUTF8String, AString, Line1); HANDLE_SERVER_PACKET_READ(ReadVarUTF8String, AString, Line2); HANDLE_SERVER_PACKET_READ(ReadVarUTF8String, AString, Line3); HANDLE_SERVER_PACKET_READ(ReadVarUTF8String, AString, Line4); Log("Received a PACKET_UPDATE_SIGN from the server:"); Log(" Block = {%d, %d, %d}", BlockX, BlockY, BlockZ); Log(" Lines = \"%s\", \"%s\", \"%s\", \"%s\"", Line1.c_str(), Line2.c_str(), Line3.c_str(), Line4.c_str()); COPY_TO_CLIENT(); return true; } bool cConnection::HandleServerUpdateTileEntity(void) { HANDLE_SERVER_PACKET_READ(ReadBEInt32, Int32, BlockX); HANDLE_SERVER_PACKET_READ(ReadBEInt16, Int16, BlockY); HANDLE_SERVER_PACKET_READ(ReadBEInt32, Int32, BlockZ); HANDLE_SERVER_PACKET_READ(ReadBEUInt8, UInt8, Action); HANDLE_SERVER_PACKET_READ(ReadBEUInt16, UInt16, DataLength); ContiguousByteBuffer Data; if ((DataLength > 0) && !m_ServerBuffer.ReadSome(Data, DataLength)) { return false; } Log("Received a PACKET_UPDATE_TILE_ENTITY from the server:"); Log(" Block = {%d, %d, %d}", BlockX, BlockY, BlockZ); Log(" Action = %u", Action); DataLog(Data.data(), Data.size(), " Data (%u bytes)", DataLength); // Save metadata to a file: auto fnam = fmt::format(FMT_STRING("{}_tile_{:08x}.nbt"), m_LogNameBase, m_ItemIdx++); FILE * f = fopen(fnam.c_str(), "wb"); if (f != nullptr) { fwrite(Data.data(), 1, Data.size(), f); fclose(f); Log("(saved to file \"%s\")", fnam.c_str()); } COPY_TO_CLIENT(); return true; } bool cConnection::HandleServerUseBed(void) { HANDLE_SERVER_PACKET_READ(ReadBEUInt32, UInt32, EntityID); HANDLE_SERVER_PACKET_READ(ReadBEInt32, Int32, BedX); HANDLE_SERVER_PACKET_READ(ReadBEUInt8, UInt8, BedY); HANDLE_SERVER_PACKET_READ(ReadBEInt32, Int32, BedZ); Log("Received a use bed packet from the server:"); Log(" EntityID = %u", EntityID); Log(" Bed = {%d, %u, %d}", BedX, BedY, BedZ); COPY_TO_CLIENT(); return true; } bool cConnection::HandleServerWindowClose(void) { HANDLE_SERVER_PACKET_READ(ReadBEUInt8, UInt8, WindowID); Log("Received a PACKET_WINDOW_CLOSE from the server:"); Log(" WindowID = %u", WindowID); COPY_TO_CLIENT(); return true; } bool cConnection::HandleServerWindowContents(void) { HANDLE_SERVER_PACKET_READ(ReadBEUInt8, UInt8, WindowID); HANDLE_SERVER_PACKET_READ(ReadBEUInt16, UInt16, NumSlots); Log("Received a PACKET_WINDOW_CONTENTS from the server:"); Log(" WindowID = %u", WindowID); Log(" NumSlots = %u", NumSlots); AStringVector Items; for (UInt16 i = 0; i < NumSlots; i++) { AString Item; if (!ParseSlot(m_ServerBuffer, Item)) { return false; } Log(" %u: %s", i, Item.c_str()); } COPY_TO_CLIENT(); return true; } bool cConnection::HandleServerWindowOpen(void) { HANDLE_SERVER_PACKET_READ(ReadBEUInt8, UInt8, WindowID); HANDLE_SERVER_PACKET_READ(ReadBEUInt8, UInt8, WindowType); HANDLE_SERVER_PACKET_READ(ReadVarUTF8String, AString, Title); HANDLE_SERVER_PACKET_READ(ReadBEUInt8, UInt8, NumSlots); HANDLE_SERVER_PACKET_READ(ReadBEUInt8, UInt8, UseProvidedTitle); UInt32 HorseEntityID = 0; if (WindowType == 11) // Horse / Donkey / Mule { HANDLE_SERVER_PACKET_READ(ReadBEUInt32, UInt32, intHorseInt); HorseEntityID = intHorseInt; } Log("Received a PACKET_WINDOW_OPEN from the server:"); Log(" WindowID = %u", WindowID); Log(" WindowType = %u (0x%02x)", WindowType, WindowType); Log(" Title = \"%s\", Use = %u", Title.c_str(), UseProvidedTitle); Log(" NumSlots = %u", NumSlots); if (WindowType == 11) { Log(" HorseEntityID = %u (0x%08x)", HorseEntityID, HorseEntityID); } COPY_TO_CLIENT(); return true; } bool cConnection::HandleServerUnknownPacket(UInt32 a_PacketType, UInt32 a_PacketLen, UInt32 a_PacketReadSoFar) { ContiguousByteBuffer Data; ASSERT(a_PacketLen >= a_PacketReadSoFar); if (!m_ServerBuffer.ReadSome(Data, a_PacketLen - a_PacketReadSoFar)) { return false; } DataLog(Data.data(), Data.size(), "****************** Unknown packet 0x%x from the server; relaying and ignoring", a_PacketType); COPY_TO_CLIENT(); return true; } bool cConnection::ParseSlot(cByteBuffer & a_Buffer, AString & a_ItemDesc) { short ItemType; if (!a_Buffer.ReadBEInt16(ItemType)) { return false; } if (ItemType <= 0) { a_ItemDesc = ""; return true; } if (!a_Buffer.CanReadBytes(5)) { return false; } Int8 ItemCount; Int16 ItemDamage; UInt16 MetadataLength; a_Buffer.ReadBEInt8(ItemCount); // We already know we can read these bytes - we checked before. a_Buffer.ReadBEInt16(ItemDamage); a_Buffer.ReadBEUInt16(MetadataLength); a_ItemDesc = fmt::format(FMT_STRING("{}:{} * {}"), ItemType, ItemDamage, ItemCount); if (MetadataLength <= 0) { return true; } AString Metadata; Metadata.resize(MetadataLength); if (!a_Buffer.ReadBuf(const_cast(Metadata.data()), MetadataLength)) { return false; } AString MetaHex; CreateHexDump(MetaHex, Metadata.data(), Metadata.size(), 16); a_ItemDesc.append(fmt::format(FMT_STRING("; {} bytes of meta:\n{}"), MetadataLength, MetaHex)); // Save metadata to a file: auto fnam = fmt::format(FMT_STRING("{}_item_{:08x}.nbt"), m_LogNameBase, m_ItemIdx++); FILE * f = fopen(fnam.c_str(), "wb"); if (f != nullptr) { fwrite(Metadata.data(), 1, Metadata.size(), f); fclose(f); a_ItemDesc.append(fmt::format(FMT_STRING("\n (saved to file \"{}\")"), fnam)); } return true; } bool cConnection::ParseMetadata(cByteBuffer & a_Buffer, AString & a_Metadata) { UInt8 x; if (!a_Buffer.ReadBEUInt8(x)) { return false; } a_Metadata.push_back(static_cast(x)); while (x != 0x7f) { // int Index = static_cast(x) & 0x1f; // Lower 5 bits = index int Type = static_cast(x) >> 5; // Upper 3 bits = type // Get the length of the data for this item: UInt32 Length = 0; switch (Type) { case 0: Length = 1; break; // Byte case 1: Length = 2; break; // short case 2: Length = 4; break; // int case 3: Length = 4; break; // float case 4: // UTF-8 string with VarInt length { UInt32 Len; int rs = static_cast(a_Buffer.GetReadableSpace()); if (!a_Buffer.ReadVarInt(Len)) { return false; } rs = rs - static_cast(a_Buffer.GetReadableSpace()); cByteBuffer LenBuf(8); LenBuf.WriteVarInt32(Len); ContiguousByteBuffer VarLen; LenBuf.ReadAll(VarLen); a_Metadata += { reinterpret_cast(VarLen.data()), VarLen.size() }; Length = Len; break; } case 5: // Item, in "slot" format { size_t Before = a_Buffer.GetReadableSpace(); AString ItemDesc; if (!ParseSlot(a_Buffer, ItemDesc)) { return false; } size_t After = a_Buffer.GetReadableSpace(); a_Buffer.ResetRead(); a_Buffer.SkipRead(a_Buffer.GetReadableSpace() - Before); Length = static_cast(Before - After); break; } case 6: Length = 12; break; // 3 * int case 7: default: { ASSERT(!"Unknown metadata type"); break; } } // switch (Type) // Read the data in this item: ContiguousByteBuffer data; if (!a_Buffer.ReadSome(data, Length)) { return false; } a_Metadata += { reinterpret_cast(data.data()), data.size() }; if (!a_Buffer.ReadBEUInt8(x)) { return false; } a_Metadata.push_back(static_cast(x)); } // while (x != 0x7f) return true; } void cConnection::LogMetadata(const AString & a_Metadata, size_t a_IndentCount) { AString Indent(a_IndentCount, ' '); size_t pos = 0; while (a_Metadata[pos] != 0x7f) { unsigned Index = static_cast(static_cast(a_Metadata[pos])) & 0x1f; // Lower 5 bits = index unsigned Type = static_cast(static_cast(a_Metadata[pos])) >> 5; // Upper 3 bits = type // int Length = 0; switch (Type) { case 0: { Log("%sbyte[%u] = %u", Indent.c_str(), Index, static_cast(a_Metadata[pos + 1])); pos += 1; break; } case 1: { Log("%sshort[%u] = %d", Indent.c_str(), Index, (a_Metadata[pos + 1] << 8) | a_Metadata[pos + 2]); pos += 2; break; } case 2: { Log("%sint[%u] = %d", Indent.c_str(), Index, (a_Metadata[pos + 1] << 24) | (a_Metadata[pos + 2] << 16) | (a_Metadata[pos + 3] << 8) | a_Metadata[pos + 4]); pos += 4; break; } case 3: { Log("%sfloat[%u] = 0x%x", Indent.c_str(), Index, (a_Metadata[pos + 1] << 24) | (a_Metadata[pos + 2] << 16) | (a_Metadata[pos + 3] << 8) | a_Metadata[pos + 4]); pos += 4; break; } case 4: // UTF-8 string with VarInt length { cByteBuffer bb(10); size_t RestLen = a_Metadata.size() - pos - 1; if (RestLen > 8) { RestLen = 8; } bb.Write(a_Metadata.data() + pos + 1, RestLen); UInt32 Length; size_t rs = bb.GetReadableSpace(); if (!bb.ReadVarInt(Length)) { Log("Invalid metadata value, was supposed to be a varint-prefixed string, but cannot read the varint"); break; } rs = rs - bb.GetReadableSpace(); Log("%sstring[%u] = \"%*s\"", Indent.c_str(), Index, Length, a_Metadata.c_str() + pos + rs + 1); pos += Length + rs + 2; break; } case 5: { size_t BytesLeft = a_Metadata.size() - pos - 1; cByteBuffer bb(BytesLeft); bb.Write(a_Metadata.data() + pos + 1, BytesLeft); AString ItemDesc; if (!ParseSlot(bb, ItemDesc)) { ASSERT(!"Cannot parse item description from metadata"); return; } // size_t After = bb.GetReadableSpace(); size_t BytesConsumed = BytesLeft - bb.GetReadableSpace(); Log("%sslot[%u] = %s (%u bytes)", Indent.c_str(), Index, ItemDesc.c_str(), static_cast(BytesConsumed)); pos += BytesConsumed; break; } case 6: { Log("%spos[%u] = <%d, %d, %d>", Indent.c_str(), Index, (a_Metadata[pos + 1] << 24) | (a_Metadata[pos + 2] << 16) | (a_Metadata[pos + 3] << 8) | a_Metadata[pos + 4], (a_Metadata[pos + 5] << 24) | (a_Metadata[pos + 6] << 16) | (a_Metadata[pos + 7] << 8) | a_Metadata[pos + 8], (a_Metadata[pos + 9] << 24) | (a_Metadata[pos + 10] << 16) | (a_Metadata[pos + 11] << 8) | a_Metadata[pos + 12] ); pos += 12; break; } default: { ASSERT(!"Unknown metadata type"); break; } } // switch (Type) pos += 1; } // while (x != 0x7f) } void cConnection::SendEncryptionKeyResponse(const AString & a_ServerPublicKey, const AString & a_Nonce) { // Generate the shared secret and encrypt using the server's public key Byte SharedSecret[16]; Byte EncryptedSecret[128]; memset(SharedSecret, 0, sizeof(SharedSecret)); // Use all zeroes for the initial secret cCryptoKey PubKey(a_ServerPublicKey); int res = PubKey.Encrypt(SharedSecret, sizeof(SharedSecret), EncryptedSecret, sizeof(EncryptedSecret)); if (res < 0) { Log("Shared secret encryption failed: %d (0x%x)", res, res); return; } m_ServerEncryptor.Init(SharedSecret, SharedSecret); m_ServerDecryptor.Init(SharedSecret, SharedSecret); // Encrypt the nonce: Byte EncryptedNonce[128]; res = PubKey.Encrypt(reinterpret_cast(a_Nonce.data()), a_Nonce.size(), EncryptedNonce, sizeof(EncryptedNonce)); if (res < 0) { Log("Nonce encryption failed: %d (0x%x)", res, res); return; } // Send the packet to the server: Log("Sending PACKET_ENCRYPTION_KEY_RESPONSE to the SERVER"); cByteBuffer ToServer(1024); ToServer.WriteBEUInt8(0x01); // To server: Encryption key response ToServer.WriteBEUInt16(static_cast(sizeof(EncryptedSecret))); ToServer.WriteBuf(EncryptedSecret, sizeof(EncryptedSecret)); ToServer.WriteBEUInt16(static_cast(sizeof(EncryptedNonce))); ToServer.WriteBuf(EncryptedNonce, sizeof(EncryptedNonce)); DataLog(EncryptedSecret, sizeof(EncryptedSecret), "Encrypted secret (%u bytes)", static_cast(sizeof(EncryptedSecret))); DataLog(EncryptedNonce, sizeof(EncryptedNonce), "Encrypted nonce (%u bytes)", static_cast(sizeof(EncryptedNonce))); cByteBuffer Len(5); Len.WriteVarInt32(static_cast(ToServer.GetReadableSpace())); SERVERSEND(Len); SERVERSEND(ToServer); m_ServerState = csEncryptedUnderstood; m_IsServerEncrypted = true; } ================================================ FILE: Tools/ProtoProxy/Connection.h ================================================ // Connection.h // Interfaces to the cConnection class representing a single pair of connected sockets #pragma once #include "ByteBuffer.h" #include "mbedTLS++/AesCfb128Decryptor.h" #include "mbedTLS++/AesCfb128Encryptor.h" #ifndef _WIN32 typedef int SOCKET; #endif class cServer; class cConnection { /** Base for the log filename and all files connected to this log */ AString m_LogNameBase; /** Index for the next file into which item metadata should be written (ParseSlot() function) */ int m_ItemIdx; cCriticalSection m_CSLog; FILE * m_LogFile; cServer & m_Server; SOCKET m_ClientSocket; SOCKET m_ServerSocket; std::chrono::steady_clock::time_point m_BeginTick; // Tick when the relative time was first retrieved (used for GetRelativeTime()) enum eConnectionState { csUnencrypted, // The connection is not encrypted. Packets must be decoded in order to be able to start decryption. csEncryptedUnderstood, // The communication is encrypted and so far all packets have been understood, so they can be still decoded csEncryptedUnknown, // The communication is encrypted, but an unknown packet has been received, so packets cannot be decoded anymore csWaitingForEncryption, // The communication is waiting for the other line to establish encryption }; eConnectionState m_ClientState; eConnectionState m_ServerState; int m_Nonce; public: cConnection(SOCKET a_ClientSocket, cServer & a_Server); ~cConnection(); void Run(void); void vLog(const char * a_Format, fmt::printf_args a_ArgList); template void Log(const char * a_Format, const Args & ... a_Args) { vLog(a_Format, fmt::make_printf_args(a_Args...)); } void vDataLog(const void * a_Data, size_t a_Size, const char * a_Format, fmt::printf_args a_ArgList); template void DataLog(const void * a_Data, size_t a_Size, const char * a_Format, const Args & ... a_Args) { vDataLog(a_Data, a_Size, a_Format, fmt::make_printf_args(a_Args...)); } void LogFlush(void); protected: cByteBuffer m_ClientBuffer; cByteBuffer m_ServerBuffer; cAesCfb128Decryptor m_ServerDecryptor; cAesCfb128Encryptor m_ServerEncryptor; ContiguousByteBuffer m_ServerEncryptionBuffer; // Buffer for the data to be sent to the server once encryption is established /** Set to true when PACKET_PING is received from the client; will cause special parsing for server kick */ bool m_HasClientPinged; /* The protocol states can be one of: -1: no initial handshake received yet 1: status 2: login 3: game */ /** State the to-server protocol is in (as defined by the initial handshake / login), -1 if no initial handshake received yet */ int m_ServerProtocolState; /** State the to-client protocol is in (as defined by the initial handshake / login), -1 if no initial handshake received yet */ int m_ClientProtocolState; /** True if the server connection has provided encryption keys */ bool m_IsServerEncrypted; bool ConnectToServer(void); /** Relays data from server to client; returns false if connection aborted */ bool RelayFromServer(void); /** Relays data from client to server; returns false if connection aborted */ bool RelayFromClient(void); /** Returns the time relative to the first call of this function, in the fractional seconds elapsed */ double GetRelativeTime(void); /** Sends data to the specified socket. If sending fails, prints a fail message using a_Peer and returns false. */ bool SendData(SOCKET a_Socket, ContiguousByteBufferView a_Data, const char * a_Peer); /** Sends data to the specified socket. If sending fails, prints a fail message using a_Peer and returns false. */ bool SendData(SOCKET a_Socket, cByteBuffer & a_Data, const char * a_Peer); /** Sends data to the specfied socket, after encrypting it using a_Encryptor. If sending fails, prints a fail message using a_Peer and returns false */ bool SendEncryptedData(SOCKET a_Socket, cAesCfb128Encryptor & a_Encryptor, ContiguousByteBuffer & a_Data, const char * a_Peer); /** Sends data to the specfied socket, after encrypting it using a_Encryptor. If sending fails, prints a fail message using a_Peer and returns false */ bool SendEncryptedData(SOCKET a_Socket, cAesCfb128Encryptor & a_Encryptor, cByteBuffer & a_Data, const char * a_Peer); /** Decodes packets coming from the client, sends appropriate counterparts to the server; returns false if the connection is to be dropped */ bool DecodeClientsPackets(const char * a_Data, int a_Size); /** Decodes packets coming from the server, sends appropriate counterparts to the client; returns false if the connection is to be dropped */ bool DecodeServersPackets(const char * a_Data, int a_Size); // Packet handling, client-side, initial: bool HandleClientHandshake(void); // Packet handling, client-side, status: bool HandleClientStatusPing(void); bool HandleClientStatusRequest(void); // Packet handling, client-side, login: bool HandleClientLoginEncryptionKeyResponse(void); bool HandleClientLoginStart(void); // Packet handling, client-side, game: bool HandleClientAnimation(void); bool HandleClientBlockDig(void); bool HandleClientBlockPlace(void); bool HandleClientChatMessage(void); bool HandleClientClientStatuses(void); bool HandleClientCreativeInventoryAction(void); bool HandleClientDisconnect(void); bool HandleClientEntityAction(void); bool HandleClientKeepAlive(void); bool HandleClientLocaleAndView(void); bool HandleClientPing(void); bool HandleClientPlayerAbilities(void); bool HandleClientPlayerLook(void); bool HandleClientPlayerOnGround(void); bool HandleClientPlayerPosition(void); bool HandleClientPlayerPositionLook(void); bool HandleClientPluginMessage(void); bool HandleClientSlotSelect(void); bool HandleClientTabCompletion(void); bool HandleClientUpdateSign(void); bool HandleClientUseEntity(void); bool HandleClientWindowClick(void); bool HandleClientWindowClose(void); bool HandleClientUnknownPacket(UInt32 a_PacketType, UInt32 a_PacketLen, UInt32 a_PacketReadSoFar); // Packet handling, server-side, login: bool HandleServerLoginDisconnect(void); bool HandleServerLoginEncryptionKeyRequest(void); bool HandleServerLoginSuccess(void); // Packet handling, server-side, game: bool HandleServerAttachEntity(void); bool HandleServerBlockAction(void); bool HandleServerBlockChange(void); bool HandleServerChangeGameState(void); bool HandleServerChatMessage(void); bool HandleServerCollectPickup(void); bool HandleServerCompass(void); bool HandleServerDestroyEntities(void); bool HandleServerEntity(void); bool HandleServerEntityEquipment(void); bool HandleServerEntityHeadLook(void); bool HandleServerEntityLook(void); bool HandleServerEntityMetadata(void); bool HandleServerEntityProperties(void); bool HandleServerEntityRelativeMove(void); bool HandleServerEntityRelativeMoveLook(void); bool HandleServerEntityStatus(void); bool HandleServerEntityTeleport(void); bool HandleServerEntityVelocity(void); bool HandleServerExplosion(void); bool HandleServerIncrementStatistic(void); bool HandleServerJoinGame(void); bool HandleServerKeepAlive(void); bool HandleServerKick(void); bool HandleServerLogin(void); bool HandleServerMapChunk(void); bool HandleServerMapChunkBulk(void); bool HandleServerMultiBlockChange(void); bool HandleServerNamedSoundEffect(void); bool HandleServerPlayerAbilities(void); bool HandleServerPlayerAnimation(void); bool HandleServerPlayerListItem(void); bool HandleServerPlayerPositionLook(void); bool HandleServerPluginMessage(void); bool HandleServerRespawn(void); bool HandleServerSetExperience(void); bool HandleServerSetSlot(void); bool HandleServerSlotSelect(void); bool HandleServerSoundEffect(void); bool HandleServerSpawnExperienceOrbs(void); bool HandleServerSpawnMob(void); bool HandleServerSpawnNamedEntity(void); bool HandleServerSpawnObjectVehicle(void); bool HandleServerSpawnPainting(void); bool HandleServerSpawnPickup(void); bool HandleServerStatistics(void); bool HandleServerStatusPing(void); bool HandleServerStatusResponse(void); bool HandleServerTabCompletion(void); bool HandleServerTimeUpdate(void); bool HandleServerUpdateHealth(void); bool HandleServerUpdateSign(void); bool HandleServerUpdateTileEntity(void); bool HandleServerUseBed(void); bool HandleServerWindowClose(void); bool HandleServerWindowContents(void); bool HandleServerWindowOpen(void); bool HandleServerUnknownPacket(UInt32 a_PacketType, UInt32 a_PacketLen, UInt32 a_PacketReadSoFar); /** Parses the slot data in a_Buffer into item description; returns true if successful, false if not enough data */ bool ParseSlot(cByteBuffer & a_Buffer, AString & a_ItemDesc); /** Parses the metadata in a_Buffer into raw metadata in an AString; returns true if successful, false if not enough data */ bool ParseMetadata(cByteBuffer & a_Buffer, AString & a_Metadata); /** Logs the contents of the metadata in the AString, using Log(). Assumes a_Metadata is valid (parsed by ParseMetadata()). The log is indented by a_IndentCount spaces */ void LogMetadata(const AString & a_Metadata, size_t a_IndentCount); /** Send EKResp to the server: */ void SendEncryptionKeyResponse(const AString & a_ServerPublicKey, const AString & a_Nonce); /** Starts client encryption based on the parameters received */ void StartClientEncryption(const AString & a_EncryptedSecret, const AString & a_EncryptedNonce); } ; ================================================ FILE: Tools/ProtoProxy/ProtoProxy.cpp ================================================ // ProtoProxy.cpp // Implements the main app entrypoint #include "Globals.h" #include "Server.h" #include "../../src/Logger.h" #include "../../src/LoggerListeners.h" int main(int argc, char ** argv) { // Initialize logging subsystem: auto consoleLogListener = MakeConsoleListener(false); auto consoleAttachment = cLogger::GetInstance().AttachListener(std::move(consoleLogListener)); auto fileLogListenerRet = MakeFileListener(); if (!fileLogListenerRet.first) { LOGERROR("Failed to open log file, aborting"); return EXIT_FAILURE; } auto fileAttachment = cLogger::GetInstance().AttachListener(std::move(fileLogListenerRet.second)); cLogger::InitiateMultithreading(); UInt16 ListenPort = 25564; UInt16 ConnectPort = 25565; if (argc > 1) { if (!StringToInteger(argv[1], ListenPort)) { LOGERROR("Invalid argument 1, expected port number, got \"%s\". Aborting.", argv[1]); return 1; } if (argc > 2) { if (!StringToInteger(argv[2], ConnectPort)) { LOGERROR("Invalid argument 2, expected port number, got \"%s\". Aborting.", argv[2]); return 2; } } } cServer Server; int res = Server.Init(ListenPort, ConnectPort); if (res != 0) { LOGERROR("Server initialization failed: %d", res); return res; } Server.Run(); return 0; } ================================================ FILE: Tools/ProtoProxy/ProtoProxy.txt ================================================ // ProtoProxy.txt // A readme for the project /* ProtoProxy ========== This is a project to create a proxy for the MineCraft protocol, allowing anyone to view the data sent over a network connection between a client and a server. This, in fact, performs a kind of Man-In-The-Middle (MITM) attack on the protocol by tapping in between the connection points and providing a decrypter and an encrypter for each. In order to catch the encryption parameters, the MC protocol needs to be understood at least a little bit at the beginning, when the cryptography parameters are exchanged. This project is currently Windows-only and I don't plan on making it multi-platform, although the effort needed for doing so should be minimal. The proxy only works on the localhost connection. It listens on port 25564 and expects the underlying MC server to run on port 25565. Ports can be changed by cmdline args: ProtoProxy . You need to set the server *not* to verify usernames ("online-mode=false" in server.properties) in order to be able to connect through ProtoProxy - since the full server name, including the port, is used for verification, the client uses different servername than the server and thus the verification fails. ProtoProxy is not much dependent on the protocol - it will work with unknown packets, it just won't parse them into human-readable format. The latest protocol which has been tested is 1.7.9 (#5). */ ================================================ FILE: Tools/ProtoProxy/Server.cpp ================================================ // Server.cpp // Interfaces to the cServer class encapsulating the entire "server" #include "Globals.h" #include "Server.h" #include "Connection.h" #include "../../src/Logger.h" cServer::cServer(void) { } int cServer::Init(UInt16 a_ListenPort, UInt16 a_ConnectPort) { m_ConnectPort = a_ConnectPort; #ifdef _WIN32 WSAData wsa; int res = WSAStartup(0x0202, &wsa); if (res != 0) { LOGERROR("Cannot initialize WinSock: %d", res); return res; } #endif // _WIN32 m_ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (m_ListenSocket < 0) { #ifdef _WIN32 int err = WSAGetLastError(); #else int err = errno; #endif LOGERROR("Failed to create listener socket: %d", err); return err; } sockaddr_in local; memset(&local, 0, sizeof(local)); local.sin_family = AF_INET; local.sin_addr.s_addr = INADDR_ANY; // All interfaces local.sin_port = htons(a_ListenPort); if (bind(m_ListenSocket, reinterpret_cast(&local), sizeof(local)) != 0) { #ifdef _WIN32 int err = WSAGetLastError(); #else int err = errno; #endif LOGERROR("Failed to bind listener socket: %d", err); return err; } if (listen(m_ListenSocket, 1) != 0) { #ifdef _WIN32 int err = WSAGetLastError(); #else int err = errno; #endif printf("Failed to listen on socket: %d\n", err); return err; } LOGINFO("Listening for client connections on port %d, connecting to server at localhost:%d", a_ListenPort, a_ConnectPort); LOGINFO("Generating protocol encryption keypair..."); m_PrivateKey.Generate(); m_PublicKeyDER = m_PrivateKey.GetPubKeyDER(); return 0; } void cServer::Run(void) { LOGINFO("Server running."); while (true) { sockaddr_in Addr; memset(&Addr, 0, sizeof(Addr)); socklen_t AddrSize = sizeof(Addr); SOCKET client = accept(m_ListenSocket, reinterpret_cast(&Addr), &AddrSize); if (client == INVALID_SOCKET) { printf("accept returned an error: %d; bailing out.\n", SocketError); return; } LOGINFO("Client connected, proxying..."); cConnection Connection(client, *this); Connection.Run(); LOGINFO("Client disconnected. Ready for another connection."); } } ================================================ FILE: Tools/ProtoProxy/Server.h ================================================ // Server.h // Interfaces to the cServer class encapsulating the entire "server" #pragma once #include "Globals.h" #include "mbedTLS++/RsaPrivateKey.h" #ifdef _WIN32 #define SocketError WSAGetLastError() #else typedef int SOCKET; enum { INVALID_SOCKET = -1, }; #define closesocket close #define SocketError errno #endif class cServer { SOCKET m_ListenSocket; cRsaPrivateKey m_PrivateKey; ContiguousByteBuffer m_PublicKeyDER; UInt16 m_ConnectPort; public: cServer(void); int Init(UInt16 a_ListenPort, UInt16 a_ConnectPort); void Run(void); cRsaPrivateKey & GetPrivateKey(void) { return m_PrivateKey; } ContiguousByteBufferView GetPublicKeyDER (void) { return m_PublicKeyDER; } UInt16 GetConnectPort(void) const { return m_ConnectPort; } } ; ================================================ FILE: Tools/QtBiomeVisualiser/.gitignore ================================================ *.pro.user *.pro.user.* ================================================ FILE: Tools/QtBiomeVisualiser/BiomeView.cpp ================================================ #include "Globals.h" #include "BiomeView.h" #include #include #include "Region.h" static const int DELTA_STEP = 120; // The normal per-notch wheel delta /** Map for converting biome values to colors. Initialized from biomeColors[]. */ static uchar biomeToColor[256 * 4]; /** Map for converting biome values to colors. Used to initialize biomeToColor[]. */ static struct { EMCSBiome m_Biome; uchar m_Color[3]; } biomeColors[] = { { biOcean, { 0x00, 0x00, 0x70 }, }, { biPlains, { 0x8d, 0xb3, 0x60 }, }, { biDesert, { 0xfa, 0x94, 0x18 }, }, { biExtremeHills, { 0x60, 0x60, 0x60 }, }, { biForest, { 0x05, 0x66, 0x21 }, }, { biTaiga, { 0x0b, 0x66, 0x59 }, }, { biSwampland, { 0x2f, 0xff, 0xda }, }, { biRiver, { 0x30, 0x30, 0xaf }, }, { biHell, { 0x7f, 0x00, 0x00 }, }, { biSky, { 0x00, 0x7f, 0xff }, }, { biFrozenOcean, { 0xa0, 0xa0, 0xdf }, }, { biFrozenRiver, { 0xa0, 0xa0, 0xff }, }, { biIcePlains, { 0xff, 0xff, 0xff }, }, { biIceMountains, { 0xa0, 0xa0, 0xa0 }, }, { biMushroomIsland, { 0xff, 0x00, 0xff }, }, { biMushroomShore, { 0xa0, 0x00, 0xff }, }, { biBeach, { 0xfa, 0xde, 0x55 }, }, { biDesertHills, { 0xd2, 0x5f, 0x12 }, }, { biForestHills, { 0x22, 0x55, 0x1c }, }, { biTaigaHills, { 0x16, 0x39, 0x33 }, }, { biExtremeHillsEdge, { 0x7f, 0x8f, 0x7f }, }, { biJungle, { 0x53, 0x7b, 0x09 }, }, { biJungleHills, { 0x2c, 0x42, 0x05 }, }, { biJungleEdge, { 0x62, 0x8b, 0x17 }, }, { biDeepOcean, { 0x00, 0x00, 0x30 }, }, { biStoneBeach, { 0xa2, 0xa2, 0x84 }, }, { biColdBeach, { 0xfa, 0xf0, 0xc0 }, }, { biBirchForest, { 0x30, 0x74, 0x44 }, }, { biBirchForestHills, { 0x1f, 0x5f, 0x32 }, }, { biRoofedForest, { 0x40, 0x51, 0x1a }, }, { biColdTaiga, { 0x31, 0x55, 0x4a }, }, { biColdTaigaHills, { 0x59, 0x7d, 0x72 }, }, { biMegaTaiga, { 0x59, 0x66, 0x51 }, }, { biMegaTaigaHills, { 0x59, 0x66, 0x59 }, }, { biExtremeHillsPlus, { 0x50, 0x70, 0x50 }, }, { biSavanna, { 0xbd, 0xb2, 0x5f }, }, { biSavannaPlateau, { 0xa7, 0x9d, 0x64 }, }, { biMesa, { 0xd9, 0x45, 0x15 }, }, { biMesaPlateauF, { 0xb0, 0x97, 0x65 }, }, { biMesaPlateau, { 0xca, 0x8c, 0x65 }, }, // M variants: { biSunflowerPlains, { 0xb5, 0xdb, 0x88 }, }, { biDesertM, { 0xff, 0xbc, 0x40 }, }, { biExtremeHillsM, { 0x88, 0x88, 0x88 }, }, { biFlowerForest, { 0x2d, 0x8e, 0x49 }, }, { biTaigaM, { 0x33, 0x8e, 0x81 }, }, { biSwamplandM, { 0x07, 0xf9, 0xb2 }, }, { biIcePlainsSpikes, { 0xb4, 0xdc, 0xdc }, }, { biJungleM, { 0x7b, 0xa3, 0x31 }, }, { biJungleEdgeM, { 0x62, 0x8b, 0x17 }, }, { biBirchForestM, { 0x58, 0x9c, 0x6c }, }, { biBirchForestHillsM, { 0x47, 0x87, 0x5a }, }, { biRoofedForestM, { 0x68, 0x79, 0x42 }, }, { biColdTaigaM, { 0x24, 0x3f, 0x36 }, }, { biMegaSpruceTaiga, { 0x45, 0x4f, 0x3e }, }, { biMegaSpruceTaigaHills, { 0x45, 0x4f, 0x4e }, }, { biExtremeHillsPlusM, { 0x78, 0x98, 0x78 }, }, { biSavannaM, { 0xe5, 0xda, 0x87 }, }, { biSavannaPlateauM, { 0xa7, 0x9d, 0x74 }, }, { biMesaBryce, { 0xff, 0x6d, 0x3d }, }, { biMesaPlateauFM, { 0xd8, 0xbf, 0x8d }, }, { biMesaPlateauM, { 0xf2, 0xb4, 0x8d }, }, } ; static class BiomeColorsInitializer { public: BiomeColorsInitializer(void) { // Reset all colors to gray: for (size_t i = 0; i < ARRAYCOUNT(biomeToColor); i++) { biomeToColor[i] = 0x7f; } // Set known biomes to their colors: for (size_t i = 0; i < ARRAYCOUNT(biomeColors); i++) { uchar * color = &biomeToColor[4 * biomeColors[i].m_Biome]; color[0] = biomeColors[i].m_Color[2]; color[1] = biomeColors[i].m_Color[1]; color[2] = biomeColors[i].m_Color[0]; color[3] = 0xff; } } } biomeColorInitializer; //////////////////////////////////////////////////////////////////////////////// // BiomeView: BiomeView::BiomeView(QWidget * parent) : super(parent), m_X(0), m_Z(0), m_Zoom(1), m_IsMouseDragging(false), m_MouseWheelDelta(0) { // Create the image used for undefined chunks: int offset = 0; for (int y = 0; y < 16; y++) { for (int x = 0; x < 16; x++) { uchar color = (((x & 8) ^ (y & 8)) == 0) ? 0x44 : 0x88; m_EmptyChunkImage[offset++] = color; m_EmptyChunkImage[offset++] = color; m_EmptyChunkImage[offset++] = color; m_EmptyChunkImage[offset++] = 0xff; } } // Create the startup image: redraw(); // Add a chunk-update callback mechanism: connect(&m_Cache, SIGNAL(regionAvailable(int, int)), this, SLOT(regionAvailable(int, int))); // Allow mouse and keyboard interaction: setFocusPolicy(Qt::StrongFocus); setMouseTracking(true); } QSize BiomeView::minimumSizeHint() const { return QSize(300, 300); } QSize BiomeView::sizeHint() const { return QSize(800, 600); } void BiomeView::setChunkSource(std::shared_ptr a_ChunkSource) { // Replace the source in the cache: m_Cache.setChunkSource(a_ChunkSource); // Redraw with the new source: redraw(); } void BiomeView::setPosition(int a_BlockX, int a_BlockZ) { m_X = a_BlockX; m_Z = a_BlockZ; redraw(); } void BiomeView::setZoomLevel(double a_ZoomLevel) { m_Zoom = a_ZoomLevel; redraw(); } void BiomeView::redraw() { if (!hasData()) { // No data means no image is displayed, no need to compose: update(); return; } int chunksize = 16 * m_Zoom; // first find the center block position int centerchunkx = floor(m_X / 16); int centerchunkz = floor(m_Z / 16); // and the center of the screen int centerx = m_Image.width() / 2; int centery = m_Image.height() / 2; // and align for panning centerx -= (m_X - centerchunkx * 16) * m_Zoom; centery -= (m_Z - centerchunkz * 16) * m_Zoom; // now calculate the topleft block on the screen int startx = centerchunkx - centerx / chunksize - 1; int startz = centerchunkz - centery / chunksize - 1; // and the dimensions of the screen in blocks int blockswide = m_Image.width() / chunksize + 3; int blockstall = m_Image.height() / chunksize + 3; for (int z = startz; z < startz + blockstall; z++) { for (int x = startx; x < startx + blockswide; x++) { drawChunk(x, z); } } update(); } void BiomeView::regionAvailable(int a_RegionX, int a_RegionZ) { for (int z = 0; z < 32; z++) { for (int x = 0; x < 32; x++) { drawChunk(a_RegionX * 32 + x, a_RegionZ * 32 + z); } } update(); } void BiomeView::reload() { if (!hasData()) { return; } m_Cache.reload(); redraw(); } void BiomeView::drawChunk(int a_ChunkX, int a_ChunkZ) { if (!hasData()) { return; } // Fetch the region: int regionX; int regionZ; Region::chunkToRegion(a_ChunkX, a_ChunkZ, regionX, regionZ); RegionPtr region = m_Cache.fetch(regionX, regionZ); // Figure out where on the screen this chunk should be drawn: // first find the center chunk int centerchunkx = floor(m_X / 16); int centerchunkz = floor(m_Z / 16); // and the center chunk screen coordinates int centerx = m_Image.width() / 2; int centery = m_Image.height() / 2; // which need to be shifted to account for panning inside that chunk centerx -= (m_X - centerchunkx * 16) * m_Zoom; centery -= (m_Z - centerchunkz * 16) * m_Zoom; // centerx, centery now points to the top left corner of the center chunk // so now calculate our x, y in relation double chunksize = 16 * m_Zoom; centerx += (a_ChunkX - centerchunkx) * chunksize; centery += (a_ChunkZ - centerchunkz) * chunksize; uchar * bits = m_Image.bits(); int imgstride = m_Image.bytesPerLine(); int skipx = 0, skipy = 0; int blockwidth = chunksize, blockheight = chunksize; // now if we're off the screen we need to crop if (centerx < 0) { skipx = -centerx; centerx = 0; } if (centery < 0) { skipy = -centery; centery = 0; } // or the other side, we need to trim if (centerx + blockwidth > m_Image.width()) { blockwidth = m_Image.width() - centerx; } if (centery + blockheight > m_Image.height()) { blockheight = m_Image.height() - centery; } if ((blockwidth <= 0) || (skipx >= blockwidth)) { return; } int imgoffset = centerx * 4 + centery * imgstride; // If the chunk is valid, use its data; otherwise use the empty placeholder: const short * src = m_EmptyChunkBiomes; if (region.get() != nullptr) { int relChunkX = a_ChunkX - regionX * 32; int relChunkZ = a_ChunkZ - regionZ * 32; Chunk & chunk = region->getRelChunk(relChunkX, relChunkZ); if (chunk.isValid()) { src = chunk.getBiomes(); } } // Scale-blit the image: for (int z = skipy; z < blockheight; z++, imgoffset += imgstride) { size_t srcoffset = static_cast(std::floor((double)z / m_Zoom)) * 16; int imgxoffset = imgoffset; for (int x = skipx; x < blockwidth; x++) { short biome = src[srcoffset + static_cast(std::floor((double)x / m_Zoom))]; const uchar * color; if (biome < 0) { static const uchar emptyBiome1[] = { 0x44, 0x44, 0x44, 0xff }; static const uchar emptyBiome2[] = { 0x88, 0x88, 0x88, 0xff }; color = ((x & 8) ^ (z & 8)) ? emptyBiome1 : emptyBiome2; } else { if (biome * 4 >= ARRAYCOUNT(biomeToColor)) { static const uchar errorImage[] = { 0xff, 0x00, 0x00, 0xff }; color = errorImage; } else { color = biomeToColor + biome * 4; } } bits[imgxoffset] = color[0]; bits[imgxoffset + 1] = color[1]; bits[imgxoffset + 2] = color[2]; bits[imgxoffset + 3] = color[3]; imgxoffset += 4; } // for x } // for z } void BiomeView::resizeEvent(QResizeEvent * a_Event) { m_Image = QImage(a_Event->size(), QImage::Format_RGB32); redraw(); } void BiomeView::paintEvent(QPaintEvent * a_Event) { QPainter p(this); if (hasData()) { p.drawImage(QPoint(0, 0), m_Image); } else { p.drawText(a_Event->rect(), Qt::AlignCenter, "No chunk source selected"); } p.end(); } void BiomeView::mousePressEvent(QMouseEvent * a_Event) { m_LastX = a_Event->x(); m_LastY = a_Event->y(); m_IsMouseDragging = true; } void BiomeView::mouseMoveEvent(QMouseEvent * a_Event) { // If there's no data displayed, bail out: if (!hasData()) { return; } if (m_IsMouseDragging) { // The user is dragging the mouse, move the view around: m_X += (m_LastX - a_Event->x()) / m_Zoom; m_Z += (m_LastY - a_Event->y()) / m_Zoom; m_LastX = a_Event->x(); m_LastY = a_Event->y(); redraw(); return; } // Update the status bar info text: int blockX = floor((a_Event->x() - width() / 2) / m_Zoom + m_X); int blockZ = floor((a_Event->y() - height() / 2) / m_Zoom + m_Z); int regionX, regionZ; Region::blockToRegion(blockX, blockZ, regionX, regionZ); int relX = blockX - regionX * 512; int relZ = blockZ - regionZ * 512; auto region = m_Cache.fetch(regionX, regionZ); int biome = (region.get() != nullptr) ? region->getRelBiome(relX, relZ) : biInvalidBiome; emit hoverChanged(blockX, blockZ, biome); } void BiomeView::mouseReleaseEvent(QMouseEvent *) { m_IsMouseDragging = false; } void BiomeView::wheelEvent(QWheelEvent * a_Event) { m_MouseWheelDelta += a_Event->delta(); while (m_MouseWheelDelta >= DELTA_STEP) { emit wheelUp(); m_MouseWheelDelta -= DELTA_STEP; } while (m_MouseWheelDelta <= -DELTA_STEP) { emit wheelDown(); m_MouseWheelDelta += DELTA_STEP; } } void BiomeView::keyPressEvent(QKeyEvent * a_Event) { switch (a_Event->key()) { case Qt::Key_Up: case Qt::Key_W: { m_Z -= 10.0 / m_Zoom; redraw(); break; } case Qt::Key_Down: case Qt::Key_S: { m_Z += 10.0 / m_Zoom; redraw(); break; } case Qt::Key_Left: case Qt::Key_A: { m_X -= 10.0 / m_Zoom; redraw(); break; } case Qt::Key_Right: case Qt::Key_D: { m_X += 10.0 / m_Zoom; redraw(); break; } case Qt::Key_PageUp: case Qt::Key_Q: { emit increaseZoom(); break; } case Qt::Key_PageDown: case Qt::Key_E: { emit decreaseZoom(); break; } } } ================================================ FILE: Tools/QtBiomeVisualiser/BiomeView.h ================================================ #pragma once #include #include #include "RegionCache.h" #include "ChunkSource.h" class BiomeView : public QWidget { typedef QWidget super; Q_OBJECT public: explicit BiomeView(QWidget * parent = NULL); QSize minimumSizeHint() const; QSize sizeHint() const; /** Replaces the chunk source used by the biome view to get the chunk biome data. The entire view is then invalidated and regenerated. */ void setChunkSource(std::shared_ptr a_ChunkSource); /** Sets the position of the central pixel of the map to the specified point and redraws the view. */ void setPosition(int a_BlockX, int a_BlockZ); /** Sets the zoom level to the specified value and redraws the view. */ void setZoomLevel(double a_ZoomLevel); signals: /** Signalled when the user uses the wheel to scroll upwards. */ void wheelUp(); /** Signalled when the user uses the wheel to scroll downwards. */ void wheelDown(); /** Signalled when the user presses a key to increase zoom. */ void increaseZoom(); /** Signalled when the user presses a key to decrease zoom. */ void decreaseZoom(); /** Emitted when the user moves the mouse, to reflect the current block under the cursor. */ void hoverChanged(int a_BlockX, int a_BlockZ, int a_Biome); public slots: /** Redraw the entire widget area. */ void redraw(); /** A specified region has become available, redraw it. */ void regionAvailable(int a_RegionX, int a_RegionZ); /** Reloads the current chunk source and redraws the entire workspace. */ void reload(); protected: double m_X, m_Z; double m_Zoom; /** Cache for the loaded chunk data. */ RegionCache m_Cache; /** The entire view's contents in an offscreen image. */ QImage m_Image; /** Coords of the mouse for the previous position, used while dragging. */ int m_LastX, m_LastY; /** Set to true when the user has a mouse button depressed, and is dragging the view. */ bool m_IsMouseDragging; /** Accumulator for the mouse wheel's delta. When the accumulator hits a threshold, the view zooms. */ int m_MouseWheelDelta; /** Data used for rendering a chunk that hasn't been loaded yet */ uchar m_EmptyChunkImage[16 * 16 * 4]; /** Data placeholder for chunks that aren't valid. */ short m_EmptyChunkBiomes[16 * 16]; /** Draws the specified chunk into m_Image */ void drawChunk(int a_ChunkX, int a_ChunkZ); /** Returns true iff the biome view has been initialized to contain proper biome data. */ bool hasData(void) const { return m_Cache.hasData(); } /** Called when the widget is resized */ virtual void resizeEvent(QResizeEvent *) override; /** Paints the entire widget */ virtual void paintEvent(QPaintEvent *) override; /** Called when the user presses any mouse button. */ virtual void mousePressEvent(QMouseEvent * a_Event); /** Called when the user moves the mouse. */ virtual void mouseMoveEvent(QMouseEvent * a_Event); /** Called when the user releases a previously held mouse button. */ virtual void mouseReleaseEvent(QMouseEvent * a_Event) override; /** Called when the user rotates the mouse wheel. */ virtual void wheelEvent(QWheelEvent * a_Event) override; /** Called when the user presses a key. */ virtual void keyPressEvent(QKeyEvent * a_Event) override; }; ================================================ FILE: Tools/QtBiomeVisualiser/ChunkSource.cpp ================================================ #include "Globals.h" #include "ChunkSource.h" #include #include "src/Generating/BioGen.h" #include "src/StringCompression.h" #include "src/WorldStorage/FastNBT.h" #include "src/IniFile.h" #include "src/Endianness.h" //////////////////////////////////////////////////////////////////////////////// // BioGenSource: BioGenSource::BioGenSource(cIniFilePtr a_IniFile) : m_IniFile(a_IniFile), m_Mtx(QMutex::Recursive) { reload(); } void BioGenSource::getChunkBiomes(int a_ChunkX, int a_ChunkZ, Chunk & a_DestChunk) { cChunkDef::BiomeMap biomes; int tag; cBiomeGenPtr biomeGen = getBiomeGen(tag); biomeGen->GenBiomes(a_ChunkX, a_ChunkZ, biomes); releaseBiomeGen(std::move(biomeGen), tag); a_DestChunk.setBiomes(biomes); } void BioGenSource::reload() { QMutexLocker lock(&m_Mtx); m_CurrentTag += 1; m_BiomeGens.clear(); } cBiomeGenPtr BioGenSource::getBiomeGen(int & a_Tag) { QMutexLocker lock(&m_Mtx); a_Tag = m_CurrentTag; if (m_BiomeGens.empty()) { // Create a new biogen: lock.unlock(); int seed = m_IniFile->GetValueSetI("Seed", "Seed", 0); bool unused; cBiomeGenPtr res = cBiomeGen::CreateBiomeGen(*m_IniFile, seed, unused); return res; } else { // Return an existing biogen: cBiomeGenPtr res = m_BiomeGens.back(); m_BiomeGens.pop_back(); return res; } } void BioGenSource::releaseBiomeGen(cBiomeGenPtr && a_BiomeGen, int a_Tag) { QMutexLocker lock(&m_Mtx); // If the tag differs, the source has been reloaded and this biogen is old, dispose: if (a_Tag != m_CurrentTag) { return; } // The tag is the same, put the biogen back to list: m_BiomeGens.push_back(std::move(a_BiomeGen)); } //////////////////////////////////////////////////////////////////////////////// // AnvilSource::AnvilFile class AnvilSource::AnvilFile { public: /** Coordinates of the region file. */ int m_RegionX, m_RegionZ; /** True iff the file contains proper data. */ bool m_IsValid; /** Creates a new instance with the specified region coords. Reads the file header. */ AnvilFile(int a_RegionX, int a_RegionZ, const AString & a_WorldPath) : m_RegionX(a_RegionX), m_RegionZ(a_RegionZ), m_IsValid(false) { readFile(Printf("%s/r.%d.%d.mca", a_WorldPath.c_str(), a_RegionX, a_RegionZ)); } /** Returns the compressed data of the specified chunk. Returns an empty string when chunk not present. */ AString getChunkData(int a_ChunkX, int a_ChunkZ) { if (!m_IsValid) { return ""; } // Translate to local coords: int RelChunkX = a_ChunkX - m_RegionX * 32; int RelChunkZ = a_ChunkZ - m_RegionZ * 32; ASSERT((RelChunkX >= 0) && (RelChunkX < 32)); ASSERT((RelChunkZ >= 0) && (RelChunkZ < 32)); // Get the chunk data location: UInt32 chunkOffset = m_Header[RelChunkX + 32 * RelChunkZ] >> 8; UInt32 numChunkSectors = m_Header[RelChunkX + 32 * RelChunkZ] & 0xff; if ((chunkOffset < 2) || (numChunkSectors == 0)) { return ""; } // Get the real data size: const char * chunkData = m_FileData.data() + chunkOffset * 4096; UInt32 chunkSize = NetworkBufToHost(chunkData); if ((chunkSize < 2) || (chunkSize / 4096 > numChunkSectors)) { // Bad data, bail out return ""; } // Check the compression method: if (chunkData[4] != 2) { // Chunk is in an unknown compression return ""; } chunkSize--; // Read the chunk data: return m_FileData.substr(chunkOffset * 4096 + 5, chunkSize); } protected: AString m_FileData; UInt32 m_Header[2048]; /** Reads the whole specified file contents and parses the header. */ void readFile(const AString & a_FileName) { // Read the entire file: m_FileData = cFile::ReadWholeFile(a_FileName); if (m_FileData.size() < sizeof(m_Header)) { return; } // Parse the header - change endianness: const char * hdr = m_FileData.data(); for (size_t i = 0; i < ARRAYCOUNT(m_Header); i++) { m_Header[i] = NetworkBufToHost(hdr + 4 * i); } m_IsValid = true; } }; //////////////////////////////////////////////////////////////////////////////// // AnvilSource: AnvilSource::AnvilSource(QString a_WorldRegionFolder) : m_WorldRegionFolder(a_WorldRegionFolder) { } void AnvilSource::getChunkBiomes(int a_ChunkX, int a_ChunkZ, Chunk & a_DestChunk) { // Load the compressed data: AString compressedChunkData = getCompressedChunkData(a_ChunkX, a_ChunkZ); if (compressedChunkData.empty()) { return; } // Uncompress the chunk data: AString uncompressed; int res = InflateString(compressedChunkData.data(), compressedChunkData.size(), uncompressed); if (res != Z_OK) { return; } // Parse the NBT data: cParsedNBT nbt(uncompressed.data(), uncompressed.size()); if (!nbt.IsValid()) { return; } // Get the biomes out of the NBT: int Level = nbt.FindChildByName(0, "Level"); if (Level < 0) { return; } cChunkDef::BiomeMap biomeMap; int mcsBiomes = nbt.FindChildByName(Level, "MCSBiomes"); if ((mcsBiomes >= 0) && (nbt.GetDataLength(mcsBiomes) == sizeof(biomeMap))) { // Convert the biomes from BigEndian to platform native numbers: const char * beBiomes = nbt.GetData(mcsBiomes); for (size_t i = 0; i < ARRAYCOUNT(biomeMap); i++) { biomeMap[i] = (EMCSBiome)NetworkBufToHost(beBiomes + 4 * i); } a_DestChunk.setBiomes(biomeMap); return; } // MCS biomes not found, load Vanilla biomes instead: int biomes = nbt.FindChildByName(Level, "Biomes"); if ((biomes < 0) || (nbt.GetDataLength(biomes) != ARRAYCOUNT(biomeMap))) { return; } // Convert the biomes from Vanilla to EMCSBiome: const char * vanillaBiomes = nbt.GetData(biomes); for (size_t i = 0; i < ARRAYCOUNT(biomeMap); i++) { biomeMap[i] = EMCSBiome(vanillaBiomes[i]); } a_DestChunk.setBiomes(biomeMap); } void AnvilSource::reload() { // Remove all files from the cache: QMutexLocker lock(&m_Mtx); m_Files.clear(); } void AnvilSource::chunkToRegion(int a_ChunkX, int a_ChunkZ, int & a_RegionX, int & a_RegionZ) { a_RegionX = a_ChunkX >> 5; a_RegionZ = a_ChunkZ >> 5; } AString AnvilSource::getCompressedChunkData(int a_ChunkX, int a_ChunkZ) { return getAnvilFile(a_ChunkX, a_ChunkZ)->getChunkData(a_ChunkX, a_ChunkZ); } AnvilSource::AnvilFilePtr AnvilSource::getAnvilFile(int a_ChunkX, int a_ChunkZ) { int RegionX, RegionZ; chunkToRegion(a_ChunkX, a_ChunkZ, RegionX, RegionZ); // Search the cache for the file: QMutexLocker lock(&m_Mtx); for (auto itr = m_Files.begin(), end = m_Files.end(); itr != end; ++itr) { if (((*itr)->m_RegionX == RegionX) && ((*itr)->m_RegionZ == RegionZ)) { // Found the file in the cache, move it to front and return it: AnvilFilePtr file(*itr); m_Files.erase(itr); m_Files.push_front(file); return file; } } // File not in cache, create it: AnvilFilePtr file(new AnvilFile(RegionX, RegionZ, m_WorldRegionFolder.toStdString())); m_Files.push_front(file); return file; } ================================================ FILE: Tools/QtBiomeVisualiser/ChunkSource.h ================================================ #pragma once #include "Globals.h" #include #include #include "QtChunk.h" // fwd: class cBiomeGen; typedef SharedPtr cBiomeGenPtr; class cIniFile; typedef std::shared_ptr cIniFilePtr; /** Abstract interface for getting biome data for chunks. */ class ChunkSource { public: virtual ~ChunkSource() {} /** Fills the a_DestChunk with the biomes for the specified coords. It is expected to be thread-safe and re-entrant. Usually QThread::idealThreadCount() threads are used. */ virtual void getChunkBiomes(int a_ChunkX, int a_ChunkZ, Chunk & a_DestChunk) = 0; /** Forces a fresh reload of the source. Useful mainly for the generator, whose underlying definition file may have been changed. */ virtual void reload() = 0; }; class BioGenSource : public ChunkSource { public: /** Constructs a new BioGenSource based on the biome generator that is defined in the specified world.ini file. */ BioGenSource(cIniFilePtr a_IniFile); // ChunkSource overrides: virtual void getChunkBiomes(int a_ChunkX, int a_ChunkZ, Chunk & a_DestChunk) override; virtual void reload(void) override; protected: /** The world.ini contents from which the generator is created and re-created on reload(). */ cIniFilePtr m_IniFile; /** The generator used for generating biomes. */ std::vector m_BiomeGens; /** Guards m_BiomeGens against multithreaded access. */ QMutex m_Mtx; /** Keeps track of the current settings of the biomegens. Incremented by one each time reload() is called. Provides the means of releasing old biomegens that were in use while reload() was being processed and thus couldn't be changed back then. releaseBiomeGen() does the job of filtering the biogens before reusing them. */ int m_CurrentTag; /** Retrieves one cBiomeGenPtr from m_BiomeGens. If there's no biogen available there, creates a new one based on the ini file. When done with it, the caller should call releaseBiomeGen() to put the biogen back to m_BiomeGens. a_Tag receives the value of m_CurrentTag from when the lock was held; it should be passed to releaseBiomeGen() together with the biogen. */ cBiomeGenPtr getBiomeGen(int & a_Tag); /** Marks the specified biogen as available for reuse (puts it back into m_BiomeGens). a_Tag is the value of m_CurrentTag from the time when the biogen was retrieved; if it is different from current m_CurrentTagValue, the biogen will be disposed of (because reload() has been called in the meantime). */ void releaseBiomeGen(cBiomeGenPtr && a_BiomeGen, int a_Tag); }; class AnvilSource : public ChunkSource { public: /** Constructs a new AnvilSource based on the world path. */ AnvilSource(QString a_WorldRegionFolder); // ChunkSource overrides: virtual void getChunkBiomes(int a_ChunkX, int a_ChunkZ, Chunk & a_DestChunk) override; virtual void reload() override; protected: class AnvilFile; typedef std::shared_ptr AnvilFilePtr; /** Folder where the individual Anvil Region files are located. */ QString m_WorldRegionFolder; /** List of currently loaded files. Acts as a cache so that a file is not opened and closed over and over again. Protected against multithreaded access by m_Mtx. */ std::list m_Files; /** Guards m_Files agains multithreaded access. */ QMutex m_Mtx; /** Converts chunk coords to region coords. */ void chunkToRegion(int a_ChunkX, int a_ChunkZ, int & a_RegionX, int & a_RegionZ); /** Returns the compressed data of the specified chunk. Returns an empty string if the chunk is not available. */ AString getCompressedChunkData(int a_ChunkX, int a_ChunkZ); /** Returns the file object that contains the specified chunk. The file is taken from the cache if available there, otherwise it is created anew. */ AnvilFilePtr getAnvilFile(int a_ChunkX, int a_ChunkZ); }; ================================================ FILE: Tools/QtBiomeVisualiser/GeneratorSetup.cpp ================================================ #include "Globals.h" #include "GeneratorSetup.h" #include #include #include "src/Generating/BioGen.h" #include "src/IniFile.h" static const QString s_GeneratorNames[] = { QString("Checkerboard"), QString("Constant"), QString("DistortedVoronoi"), QString("Grown"), QString("GrownProt"), QString("MultiStepMap"), QString("TwoLevel"), QString("Voronoi"), }; GeneratorSetup::GeneratorSetup(const AString & a_IniFileName, QWidget * a_Parent) : super(a_Parent), m_IniFile(new cIniFile()) { // The seed and generator name is in a separate form layout at the top, always present: m_eSeed = new QLineEdit(); m_eSeed->setValidator(new QIntValidator()); m_eSeed->setText("0"); m_eSeed->setProperty("INI.SectionName", QVariant("Seed")); m_eSeed->setProperty("INI.ItemName", QVariant("Seed")); m_cbGenerator = new QComboBox(); m_cbGenerator->setMinimumWidth(120); for (size_t i = 0; i < ARRAYCOUNT(s_GeneratorNames); i++) { m_cbGenerator->addItem(s_GeneratorNames[i]); } QFormLayout * baseLayout = new QFormLayout(); baseLayout->addRow(new QLabel(tr("Seed")), m_eSeed); baseLayout->addRow(new QLabel(tr("Generator")), m_cbGenerator); // The rest of the controls are in a dynamically created form layout: m_FormLayout = new QFormLayout(); // The main layout joins these two vertically: m_MainLayout = new QVBoxLayout(); m_MainLayout->addLayout(baseLayout); m_MainLayout->addLayout(m_FormLayout); m_MainLayout->addStretch(); setLayout(m_MainLayout); // Load the INI file, if specified, otherwise set defaults: if (a_IniFileName.empty() || !m_IniFile->ReadFile(a_IniFileName)) { m_IniFile->SetValue("Generator", "Generator", "Composable"); m_IniFile->SetValue("Generator", "BiomeGen", m_cbGenerator->currentText().toStdString()); bool dummy; cBiomeGen::CreateBiomeGen(*m_IniFile, 0, dummy); } updateFromIni(); // Connect the change events only after the data has been loaded: connect(m_cbGenerator, SIGNAL(currentIndexChanged(QString)), this, SLOT(generatorChanged(QString))); connect(m_eSeed, SIGNAL(textChanged(QString)), this, SLOT(editChanged(QString))); } void GeneratorSetup::generatorChanged(const QString & a_NewName) { // Clear the current contents of the form layout by assigning it to a stack temporary: { m_MainLayout->takeAt(1); QWidget().setLayout(m_FormLayout); } // Re-create the layout: m_FormLayout = new QFormLayout(); m_MainLayout->insertLayout(1, m_FormLayout); // Recreate the INI file: m_IniFile->Clear(); m_IniFile->SetValue("Generator", "Generator", "Composable"); m_IniFile->SetValue("Generator", "BiomeGen", a_NewName.toStdString()); // Create a dummy biome gen from the INI file, this will create the defaults in the INI file: bool dummy; cBiomeGen::CreateBiomeGen(*m_IniFile, m_Seed, dummy); // Read all values from the INI file and put them into the form layout: updateFromIni(); // Notify of the changes: emit generatorUpdated(); } void GeneratorSetup::editChanged(const QString & a_NewValue) { QString sectionName = sender()->property("INI.SectionName").toString(); QString itemName = sender()->property("INI.ItemName").toString(); m_IniFile->SetValue(sectionName.toStdString(), itemName.toStdString(), a_NewValue.toStdString()); emit generatorUpdated(); } void GeneratorSetup::updateFromIni() { // Set the seed editbox: int seed = m_IniFile->GetValueI("Seed", "Seed", 0); m_eSeed->setText(QString::number(seed)); int keyID = m_IniFile->FindKey("Generator"); if (keyID <= -1) { return; } // Set the Generator combobox: AString generatorName = m_IniFile->GetValue("Generator", "BiomeGen"); size_t generatorNameLen = generatorName.length(); int index = m_cbGenerator->findText(QString::fromStdString(generatorName)); m_cbGenerator->setCurrentIndex(index); // Create the controls for all the generator settings in the INI file: int numItems = m_IniFile->GetNumValues(keyID); for (int i = 0; i < numItems; i++) { AString itemName = m_IniFile->GetValueName(keyID, i); if ((itemName == "Generator") || (itemName == "BiomeGen")) { // These special cases are not to be added continue; } AString itemValue = m_IniFile->GetValue(keyID, i); QLineEdit * edit = new QLineEdit(); edit->setText(QString::fromStdString(itemValue)); edit->setProperty("INI.SectionName", QVariant("Generator")); edit->setProperty("INI.ItemName", QVariant(QString::fromStdString(itemName))); // Remove the generator name prefix from the item name, for clarity purposes: if (NoCaseCompare(itemName.substr(0, generatorNameLen), generatorName) == 0) { itemName.erase(0, generatorNameLen); } connect(edit, SIGNAL(textChanged(QString)), this, SLOT(editChanged(QString))); m_FormLayout->addRow(new QLabel(QString::fromStdString(itemName)), edit); } // for i - INI values[] } ================================================ FILE: Tools/QtBiomeVisualiser/GeneratorSetup.h ================================================ #pragma once #include #include #include #include #include class cIniFile; typedef std::shared_ptr cIniFilePtr; class GeneratorSetup : public QWidget { typedef QWidget super; Q_OBJECT public: /** Creates the widget and loads the contents of the INI file, if not empty. */ explicit GeneratorSetup(const std::string & a_IniFileName, QWidget * parent = nullptr); /** Returns the cIniFile instance that is being edited by this widget. */ cIniFilePtr getIniFile() { return m_IniFile; } signals: /** Emitted when the generator parameters have changed. */ void generatorUpdated(); public slots: /** Called when the user selects a different generator from the top combobox. Re-creates m_IniFile and updates the form layout. */ void generatorChanged(const QString & a_NewName); protected slots: /** Called when any of the edit widgets are changed. */ void editChanged(const QString & a_NewValue); protected: QComboBox * m_cbGenerator; QLineEdit * m_eSeed; QVBoxLayout * m_MainLayout; QFormLayout * m_FormLayout; cIniFilePtr m_IniFile; int m_Seed; /** Updates the form layout with the values from m_IniFile. */ void updateFromIni(); }; ================================================ FILE: Tools/QtBiomeVisualiser/Globals.h ================================================ #pragma once // Compiler-dependent stuff: #if defined(_MSC_VER) // MSVC produces warning C4481 on the override keyword usage, so disable the warning altogether #pragma warning(disable:4481) // Disable some warnings that we don't care about: #pragma warning(disable:4100) // Unreferenced formal parameter // Useful warnings from warning level 4: #pragma warning(3 : 4127) // Conditional expression is constant #pragma warning(3 : 4189) // Local variable is initialized but not referenced #pragma warning(3 : 4245) // Conversion from 'type1' to 'type2', signed / unsigned mismatch #pragma warning(3 : 4310) // Cast truncates constant value #pragma warning(3 : 4389) // Signed / unsigned mismatch #pragma warning(3 : 4505) // Unreferenced local function has been removed #pragma warning(3 : 4701) // Potentially unitialized local variable used #pragma warning(3 : 4702) // Unreachable code #pragma warning(3 : 4706) // Assignment within conditional expression // Disabling this warning, because we know what we're doing when we're doing this: #pragma warning(disable: 4355) // 'this' used in initializer list // Disabled because it's useless: #pragma warning(disable: 4512) // 'class': assignment operator could not be generated - reported for each class that has a reference-type member // 2014_01_06 xoft: Disabled this warning because MSVC is stupid and reports it in obviously wrong places // #pragma warning(3 : 4244) // Conversion from 'type1' to 'type2', possible loss of data #define FORMATSTRING(formatIndex, va_argsIndex) #elif defined(__GNUC__) // TODO: Can GCC explicitly mark classes as abstract (no instances can be created)? #define abstract #define FORMATSTRING(formatIndex, va_argsIndex) __attribute__((format (printf, formatIndex, va_argsIndex))) #else #error "You are using an unsupported compiler, you might need to #define some stuff here for your compiler" #endif #include // Integral types with predefined sizes: typedef long long Int64; typedef int Int32; typedef short Int16; typedef unsigned long long UInt64; typedef unsigned int UInt32; typedef unsigned short UInt16; typedef unsigned char Byte; // If you get an error about specialization check the size of integral types template class SizeChecker; template class SizeChecker { T v; }; template class SizeChecker; template class SizeChecker; template class SizeChecker; template class SizeChecker; template class SizeChecker; template class SizeChecker; // A macro to disallow the copy constructor and operator = functions // This should be used in the private: declarations for any class that shouldn't allow copying itself #define DISALLOW_COPY_AND_ASSIGN(TypeName) \ TypeName(const TypeName &); \ void operator =(const TypeName &) // A macro that is used to mark unused local variables, to avoid pedantic warnings in gcc / clang / MSVC // Note that in MSVC it requires the full type of X to be known #define UNUSED_VAR(X) (void)(X) // A macro that is used to mark unused function parameters, to avoid pedantic warnings in gcc // Written so that the full type of param needn't be known #ifdef _MSC_VER #define UNUSED(X) #else #define UNUSED UNUSED_VAR #endif // OS-dependent stuff: #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN #define _WIN32_WINNT _WIN32_WINNT_WS03 // We want to target Windows XP with Service Pack 2 & Windows Server 2003 with Service Pack 1 and higher #include #include #include // IPv6 stuff // Windows SDK defines min and max macros, messing up with our std::min and std::max usage #undef min #undef max // Windows SDK defines GetFreeSpace as a constant, probably a Win16 API remnant #ifdef GetFreeSpace #undef GetFreeSpace #endif // GetFreeSpace #else #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #endif // CRT stuff: #include #include #include #include #include // STL stuff: #include #include #include #include #include #include #include #include #include #include #ifndef TEST_GLOBALS // Common headers (part 1, without macros): #include "src/StringUtils.h" #include "src/OSSupport/CriticalSection.h" #include "src/OSSupport/Semaphore.h" #include "src/OSSupport/Event.h" #include "src/OSSupport/File.h" #include "src/Logger.h" #else // Logging functions void inline LOGERROR(const char * a_Format, ...) FORMATSTRING(1, 2); void inline LOGERROR(const char * a_Format, ...) { va_list argList; va_start(argList, a_Format); vprintf(a_Format, argList); va_end(argList); } #endif // Common definitions: /** Evaluates to the number of elements in an array (compile-time!) */ #define ARRAYCOUNT(X) (sizeof(X) / sizeof(*(X))) /** Allows arithmetic expressions like "32 KiB" (but consider using parenthesis around it, "(32 KiB)") */ #define KiB * 1024 #define MiB * 1024 * 1024 /** Faster than (int)floorf((float)x / (float)div) */ #define FAST_FLOOR_DIV( x, div) (((x) - (((x) < 0) ? ((div) - 1) : 0)) / (div)) // Own version of assert() that writes failed assertions to the log for review #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 #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 #define VERIFY( x) ( !!(x) || ( LOGERROR("Verification failed: %s, file %s, line %i", #x, __FILE__, __LINE__), exit(1), 0)) // C++11 has std::shared_ptr in , included earlier #define SharedPtr std::shared_ptr /** Clamp X to the specified range. */ template T Clamp(T a_Value, T a_Min, T a_Max) { return (a_Value < a_Min) ? a_Min : ((a_Value > a_Max) ? a_Max : a_Value); } #ifndef TOLUA_TEMPLATE_BIND #define TOLUA_TEMPLATE_BIND(x) #endif // Common headers (part 2, with macros): #include "src/BlockID.h" #include "src/BlockInfo.h" ================================================ FILE: Tools/QtBiomeVisualiser/MainWindow.cpp ================================================ #include "Globals.h" #include "MainWindow.h" #include #include #include #include #include #include #include #include #include "ChunkSource.h" #include "src/IniFile.h" #include "src/Generating/BioGen.h" #include "src/StringCompression.h" #include "src/WorldStorage/FastNBT.h" #include "GeneratorSetup.h" #include "RegionLoader.h" const double MainWindow::m_ViewZooms[] = { 0.0625, 0.125, 0.25, 0.5, 1, 2, 4, 8, 16, 24, }; MainWindow::MainWindow(QWidget * parent) : QMainWindow(parent), m_GeneratorSetup(nullptr), m_LineSeparator(nullptr), m_CurrentZoomLevel(2) { initMinecraftPath(); m_BiomeView = new BiomeView(); connect(m_BiomeView, SIGNAL(increaseZoom()), this, SLOT(increaseZoom())); connect(m_BiomeView, SIGNAL(decreaseZoom()), this, SLOT(decreaseZoom())); connect(m_BiomeView, SIGNAL(wheelUp()), this, SLOT(increaseZoom())); connect(m_BiomeView, SIGNAL(wheelDown()), this, SLOT(decreaseZoom())); m_BiomeView->setZoomLevel(m_ViewZooms[m_CurrentZoomLevel]); m_StatusBar = new QStatusBar(); this->setStatusBar(m_StatusBar); m_StatusBlockX = new QLabel(tr("X")); m_StatusBlockZ = new QLabel(tr("Z")); m_StatusBiome = new QLabel(tr("B")); m_StatusBar->addPermanentWidget(m_StatusBlockX); m_StatusBar->addPermanentWidget(m_StatusBlockZ); m_StatusBar->addPermanentWidget(m_StatusBiome); m_MainLayout = new QHBoxLayout(); m_MainLayout->addWidget(m_BiomeView, 1); m_MainLayout->setMenuBar(menuBar()); m_MainLayout->setMargin(0); QWidget * central = new QWidget(); central->setLayout(m_MainLayout); setCentralWidget(central); createActions(); createMenus(); connect(m_BiomeView, SIGNAL(hoverChanged(int, int, int)), this, SLOT(hoverChanged(int, int, int))); } MainWindow::~MainWindow() { RegionLoader::shutdown(); } void MainWindow::newGenerator() { // (Re-)open the generator setup dialog with empty settings: openGeneratorSetup(""); // Set the chunk source: cIniFilePtr iniFile = m_GeneratorSetup->getIniFile(); m_BiomeView->setChunkSource(std::make_shared(iniFile)); m_BiomeView->redraw(); } void MainWindow::openGenerator() { // Let the user specify the world.ini file: QString worldIni = QFileDialog::getOpenFileName(this, tr("Open world.ini"), QString(), tr("world.ini (world.ini)")); if (worldIni.isEmpty()) { return; } // (Re-)open the generator setup dialog: openGeneratorSetup(worldIni.toStdString()); // Set the chunk source: m_BiomeView->setChunkSource(std::make_shared(m_GeneratorSetup->getIniFile())); m_BiomeView->redraw(); } void MainWindow::openWorld() { // Let the user specify the world: QString regionFolder = QFileDialog::getExistingDirectory(this, tr("Select the region folder"), QString()); if (regionFolder.isEmpty()) { return; } // Remove the generator setup dialog, if open: closeGeneratorSetup(); // Set the chunk source: m_BiomeView->setChunkSource(std::make_shared(regionFolder)); m_BiomeView->redraw(); } void MainWindow::openVanillaWorld() { // The world is stored in the sender action's data, retrieve it: QAction * action = qobject_cast(sender()); if (action == nullptr) { return; } // Remove the generator setup dialog, if open: closeGeneratorSetup(); // Set the chunk source: m_BiomeView->setChunkSource(std::make_shared(action->data().toString())); m_BiomeView->redraw(); } void MainWindow::centerView() { m_BiomeView->setPosition(0, 0); } void MainWindow::setViewZoom() { // The zoom level is stored in the sender action's data, retrieve it: QAction * action = qobject_cast(sender()); if (action == nullptr) { return; } m_CurrentZoomLevel = action->data().toInt(); double newZoom = m_ViewZooms[m_CurrentZoomLevel]; m_BiomeView->setZoomLevel(newZoom); action->setChecked(true); } void MainWindow::increaseZoom() { // If already at max zoom, bail out: if (m_CurrentZoomLevel >= ARRAYCOUNT(m_ViewZooms) - 1) { return; } // Increase the zoom level: m_CurrentZoomLevel += 1; m_actViewZoom[m_CurrentZoomLevel]->setChecked(true); m_BiomeView->setZoomLevel(m_ViewZooms[m_CurrentZoomLevel]); } void MainWindow::decreaseZoom() { // If already at min zoom, bail out: if (m_CurrentZoomLevel == 0) { return; } // Decrease the zoom level: m_CurrentZoomLevel -= 1; m_actViewZoom[m_CurrentZoomLevel]->setChecked(true); m_BiomeView->setZoomLevel(m_ViewZooms[m_CurrentZoomLevel]); } void MainWindow::hoverChanged(int a_BlockX, int a_BlockZ, int a_Biome) { m_StatusBlockX->setText(tr("X: %1").arg(a_BlockX)); m_StatusBlockZ->setText(tr("Z: %1").arg(a_BlockZ)); m_StatusBiome->setText (tr("B: %1 (%2)").arg(BiomeToString(a_Biome).c_str()).arg(a_Biome)); } void MainWindow::initMinecraftPath() { #ifdef Q_OS_MAC m_MinecraftPath = QDir::homePath() + QDir::toNativeSeparators("/Library/Application Support/minecraft"); #elif defined Q_OS_WIN32 QSettings ini(QSettings::IniFormat, QSettings::UserScope, ".minecraft", "minecraft1"); m_MinecraftPath = QFileInfo(ini.fileName()).absolutePath(); #else m_MinecraftPath = QDir::homePath() + QDir::toNativeSeparators("/.minecraft"); #endif } void MainWindow::createActions() { // Map menu: createWorldActions(); m_actNewGen = new QAction(tr("&New generator"), this); m_actNewGen->setShortcut(tr("Ctrl+N")); m_actNewGen->setStatusTip(tr("Open a generator INI file and display the generated biomes")); connect(m_actNewGen, SIGNAL(triggered()), this, SLOT(newGenerator())); m_actOpenGen = new QAction(tr("&Open generator..."), this); m_actOpenGen->setShortcut(tr("Ctrl+G")); m_actOpenGen->setStatusTip(tr("Open a generator INI file and display the generated biomes")); connect(m_actOpenGen, SIGNAL(triggered()), this, SLOT(openGenerator())); m_actOpenWorld = new QAction(tr("&Open world..."), this); m_actOpenWorld->setShortcut(tr("Ctrl+O")); m_actOpenWorld->setStatusTip(tr("Open an existing world and display its biomes")); connect(m_actOpenWorld, SIGNAL(triggered()), this, SLOT(openWorld())); m_actReload = new QAction(tr("&Reload"), this); m_actReload->setShortcut(tr("F5")); m_actReload->setStatusTip(tr("Clear the view cache and force a reload of all the data")); connect(m_actReload, SIGNAL(triggered()), m_BiomeView, SLOT(reload())); m_actExit = new QAction(tr("E&xit"), this); m_actExit->setShortcut(tr("Alt+X")); m_actExit->setStatusTip(tr("Exit %1").arg(QApplication::instance()->applicationName())); connect(m_actExit, SIGNAL(triggered()), this, SLOT(close())); // View menu: m_actViewCenter = new QAction(tr("&Reset to center"), this); m_actViewCenter->setStatusTip(tr("Scrolls the view back to the map center")); connect(m_actViewCenter, SIGNAL(triggered()), this, SLOT(centerView())); QActionGroup * zoomGroup = new QActionGroup(this); for (int i = 0; i < ARRAYCOUNT(m_ViewZooms); i++) { m_actViewZoom[i] = new QAction(tr("&Zoom %1%").arg(std::floor(m_ViewZooms[i] * 100)), this); m_actViewZoom[i]->setCheckable(true); m_actViewZoom[i]->setData(QVariant(i)); zoomGroup->addAction(m_actViewZoom[i]); connect(m_actViewZoom[i], SIGNAL(triggered()), this, SLOT(setViewZoom())); } m_actViewZoom[m_CurrentZoomLevel]->setChecked(true); } void MainWindow::createWorldActions() { QDir mc(m_MinecraftPath); if (!mc.cd("saves")) { return; } QDirIterator it(mc); int key = 1; while (it.hasNext()) { it.next(); if (!it.fileInfo().isDir()) { continue; } QString name = getWorldName(it.filePath().toStdString()); if (name.isEmpty()) { continue; } QAction * w = new QAction(this); w->setText(name); w->setData(it.filePath() + "/region"); if (key < 10) { w->setShortcut("Ctrl+" + QString::number(key)); key++; } connect(w, SIGNAL(triggered()), this, SLOT(openVanillaWorld())); m_WorldActions.append(w); } } void MainWindow::createMenus() { // Map menu: QMenu * file = menuBar()->addMenu(tr("&Map")); file->addAction(m_actNewGen); file->addAction(m_actOpenGen); file->addSeparator(); QMenu * worlds = file->addMenu(tr("Open &existing")); worlds->addActions(m_WorldActions); if (m_WorldActions.empty()) { worlds->setEnabled(false); } file->addAction(m_actOpenWorld); file->addSeparator(); file->addAction(m_actReload); file->addSeparator(); file->addAction(m_actExit); // View menu: QMenu * view = menuBar()->addMenu(tr("&View")); view->addAction(m_actViewCenter); view->addSeparator(); for (size_t i = 0; i < ARRAYCOUNT(m_actViewZoom); i++) { view->addAction(m_actViewZoom[i]); } } QString MainWindow::getWorldName(const AString & a_Path) { AString levelData = cFile::ReadWholeFile(a_Path + "/level.dat"); if (levelData.empty()) { // No such file / no data return QString(); } AString uncompressed; if (UncompressStringGZIP(levelData.data(), levelData.size(), uncompressed) != Z_OK) { return QString(); } cParsedNBT nbt(uncompressed.data(), uncompressed.size()); if (!nbt.IsValid()) { return QString(); } AString name = nbt.GetName(1); int levelNameTag = nbt.FindTagByPath(nbt.GetRoot(), "Data\\LevelName"); if ((levelNameTag <= 0) || (nbt.GetType(levelNameTag) != TAG_String)) { return QString(); } return QString::fromStdString(nbt.GetString(levelNameTag)); } void MainWindow::openGeneratorSetup(const AString & a_IniFileName) { // Close any previous editor: closeGeneratorSetup(); // Open up a new editor: m_GeneratorSetup = new GeneratorSetup(a_IniFileName); m_LineSeparator = new QWidget(); m_LineSeparator->setFixedWidth(2); m_LineSeparator->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding); m_LineSeparator->setStyleSheet(QString("background-color: #c0c0c0;")); m_MainLayout->addWidget(m_LineSeparator); m_MainLayout->addWidget(m_GeneratorSetup); // Connect the signals from the setup pane: connect(m_GeneratorSetup, SIGNAL(generatorUpdated()), m_BiomeView, SLOT(reload())); } void MainWindow::closeGeneratorSetup() { delete m_MainLayout->takeAt(2); delete m_MainLayout->takeAt(1); delete m_GeneratorSetup; delete m_LineSeparator; m_GeneratorSetup = nullptr; m_LineSeparator = nullptr; } ================================================ FILE: Tools/QtBiomeVisualiser/MainWindow.h ================================================ #pragma once #include #include #include #include #include #include "BiomeView.h" // fwd: class GeneratorSetup; class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget * parent = nullptr); ~MainWindow(); private slots: /** Creates a generator definition from scratch, lets user modify generator params in realtime. */ void newGenerator(); /** Opens a generator definition and generates the biomes based on that. */ void openGenerator(); /** Opens an existing world and displays the loaded biomes. */ void openWorld(); /** Opens a vanilla world that is specified by the calling action. */ void openVanillaWorld(); /** Moves the view to the map's center. */ void centerView(); /** Sets the zoom level specified in the triggering action. */ void setViewZoom(); /** Sets a zoom level one step larger than current, if allowed. */ void increaseZoom(); /** Sets a zoom level one step smaller than current, if allowed. */ void decreaseZoom(); /** Updates the statusbar for the specified info about the current block under the cursor. */ void hoverChanged(int a_BlockX, int a_BlockZ, int a_Biome); protected: /** The zoom levels */ static const double m_ViewZooms[10]; // Actions: QAction * m_actNewGen; QAction * m_actOpenGen; QAction * m_actOpenWorld; QAction * m_actReload; QAction * m_actExit; QAction * m_actViewCenter; QAction * m_actViewZoom[ARRAYCOUNT(m_ViewZooms)]; /** List of actions that open the specific vanilla world. */ QList m_WorldActions; /** Path to the vanilla folder. */ QString m_MinecraftPath; /** The pane for setting up the generator, available when visualising a generator. */ GeneratorSetup * m_GeneratorSetup; /** The main biome display widget. */ BiomeView * m_BiomeView; /** The layout for the window. */ QHBoxLayout * m_MainLayout; /** The status bar that displays the current hover information. */ QStatusBar * m_StatusBar; QLabel * m_StatusBlockX; QLabel * m_StatusBlockZ; QLabel * m_StatusBiome; /** The separator line between biome view and generator setup. */ QWidget * m_LineSeparator; /** Index into m_ViewZooms[] for the current zoom level. */ size_t m_CurrentZoomLevel; /** Initializes the m_MinecraftPath based on the proper MC path */ void initMinecraftPath(); /** Creates the actions that the UI supports. */ void createActions(); /** Creates the actions that open a specific vanilla world. Iterates over the minecraft saves folder. */ void createWorldActions(); /** Creates the menu bar and connects its events. */ void createMenus(); /** Returns the name of the vanilla world in the specified path. Reads the level.dat file for the name. Returns an empty string on failure. */ QString getWorldName(const AString & a_Path); /** Opens the generator setup pane, if not already open, and loads the specified INI file to it. */ void openGeneratorSetup(const AString & a_IniFileName); /** Closes and destroys the generator setup pane, if there is one. */ void closeGeneratorSetup(); }; ================================================ FILE: Tools/QtBiomeVisualiser/QtBiomeVisualiser.cpp ================================================ #include "Globals.h" #include "MainWindow.h" #include int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow w; w.show(); return a.exec(); } ================================================ FILE: Tools/QtBiomeVisualiser/QtBiomeVisualiser.pro ================================================ #------------------------------------------------- # # Project created by QtCreator 2014-09-11T15:22:43 # #------------------------------------------------- QT += core gui greaterThan(QT_MAJOR_VERSION, 4): QT += widgets TARGET = QtBiomeVisualiser TEMPLATE = app SOURCES += \ MainWindow.cpp \ BiomeView.cpp \ ../../src/Generating/BioGen.cpp \ ../../src/VoronoiMap.cpp \ ../../src/Noise/Noise.cpp \ ../../src/StringUtils.cpp \ ../../src/LoggerListeners.cpp \ ../../src/Logger.cpp \ ../../src/IniFile.cpp \ ../../src/OSSupport/Event.cpp \ ../../src/OSSupport/File.cpp \ ../../src/OSSupport/CriticalSection.cpp \ ../../src/OSSupport/IsThread.cpp \ ../../src/OSSupport/StackTrace.cpp \ ../../src/BiomeDef.cpp \ ../../src/StackWalker.cpp \ ../../src/StringCompression.cpp \ ../../src/WorldStorage/FastNBT.cpp \ ../../lib/zlib/adler32.c \ ../../lib/zlib/compress.c \ ../../lib/zlib/crc32.c \ ../../lib/zlib/deflate.c \ ../../lib/zlib/gzclose.c \ ../../lib/zlib/gzlib.c \ ../../lib/zlib/gzread.c \ ../../lib/zlib/gzwrite.c \ ../../lib/zlib/infback.c \ ../../lib/zlib/inffast.c \ ../../lib/zlib/inflate.c \ ../../lib/zlib/inftrees.c \ ../../lib/zlib/trees.c \ ../../lib/zlib/uncompr.c \ ../../lib/zlib/zutil.c \ GeneratorSetup.cpp \ QtBiomeVisualiser.cpp \ QtChunk.cpp \ RegionCache.cpp \ Region.cpp \ ChunkSource.cpp \ RegionLoader.cpp HEADERS += \ MainWindow.h \ QtChunk.h \ Globals.h \ BiomeView.h \ ../../src/Generating/BioGen.h \ ../../src/Generating/IntGen.h \ ../../src/Generating/ProtIntGen.h \ ../../src/VoronoiMap.h \ ../../src/Noise/Noise.h \ ../../src/StringUtils.h \ ../../src/LoggerListeners.h \ ../../src/Logger.h \ ../../src/IniFile.h \ ../../src/OSSupport/Event.h \ ../../src/OSSupport/File.h \ ../../src/OSSupport/CriticalSection.h \ ../../src/OSSupport/IsThread.h \ ../../src/OSSupport/StackTrace.h \ ../../src/BiomeDef.h \ ../../src/StackWalker.h \ ../../src/StringCompression.h \ ../../src/WorldStorage/FastNBT.h \ ../../lib/zlib/crc32.h \ ../../lib/zlib/deflate.h \ ../../lib/zlib/gzguts.h \ ../../lib/zlib/inffast.h \ ../../lib/zlib/inffixed.h \ ../../lib/zlib/inflate.h \ ../../lib/zlib/inftrees.h \ ../../lib/zlib/trees.h \ ../../lib/zlib/zconf.h \ ../../lib/zlib/zlib.h \ ../../lib/zlib/zutil.h \ GeneratorSetup.h \ QtChunk.h \ RegionCache.h \ Region.h \ ChunkSource.h \ RegionLoader.h INCLUDEPATH += $$_PRO_FILE_PWD_ \ $$_PRO_FILE_PWD_/../../lib \ $$_PRO_FILE_PWD_/../../lib/jsoncpp/include \ $$_PRO_FILE_PWD_/../../lib/polarssl/include \ $$_PRO_FILE_PWD_/../../lib/sqlite \ $$_PRO_FILE_PWD_/../../lib/SQLiteCpp/include \ $$_PRO_FILE_PWD_/../../ CONFIG += C++11 OTHER_FILES += win* { # Add the advapi32 library for windows compiles; needed for the StackWalker: LIBS += advapi32.lib # StackWalker doesn't like how Qt inconsistently defines only UNICODE, but not _UNICODE: DEFINES -= UNICODE } ================================================ FILE: Tools/QtBiomeVisualiser/QtChunk.cpp ================================================ #include "Globals.h" #include "QtChunk.h" Chunk::Chunk() : m_IsValid(false) { } void Chunk::setBiomes(const cChunkDef::BiomeMap & a_Biomes) { for (size_t idx = 0; idx < ARRAYCOUNT(a_Biomes); ++idx) { m_Biomes[idx] = static_cast(a_Biomes[idx]); } m_IsValid = true; } EMCSBiome Chunk::getBiome(int a_RelX, int a_RelZ) { if (!m_IsValid) { return biInvalidBiome; } return static_cast(m_Biomes[a_RelX + 16 * a_RelZ]); } ================================================ FILE: Tools/QtBiomeVisualiser/QtChunk.h ================================================ #pragma once #include class Chunk { public: /** The type used for storing image data for a chunk. */ typedef uchar Image[16 * 16 * 4]; Chunk(void); /** Returns true iff the chunk data is valid - loaded or generated. */ bool isValid(void) const { return m_IsValid; } /** Sets the biomes to m_Biomes and renders them into m_Image. */ void setBiomes(const cChunkDef::BiomeMap & a_Biomes); /** Returns the biome at the specified relative coords, or biInvalidBiome if not valid. Coords must be valid inside this chunk. */ EMCSBiome getBiome(int a_RelX, int a_RelZ); /** Returns the raw biome data for this chunk. */ const short * getBiomes(void) const { return m_Biomes; } protected: /** Flag that specifies if the chunk data is valid - loaded or generated. */ bool m_IsValid; /** Biomes comprising the chunk, in the X + 16 * Z ordering. Typed as short to save on memory, converted automatically when needed. */ short m_Biomes[16 * 16]; }; typedef std::shared_ptr ChunkPtr; ================================================ FILE: Tools/QtBiomeVisualiser/Region.cpp ================================================ #include "Globals.h" #include "Region.h" Region::Region() { } Chunk & Region::getRelChunk(int a_RelChunkX, int a_RelChunkZ) { ASSERT(a_RelChunkX >= 0); ASSERT(a_RelChunkZ >= 0); ASSERT(a_RelChunkX < 32); ASSERT(a_RelChunkZ < 32); return m_Chunks[a_RelChunkX + a_RelChunkZ * 32]; } int Region::getRelBiome(int a_RelBlockX, int a_RelBlockZ) { ASSERT(a_RelBlockX >= 0); ASSERT(a_RelBlockZ >= 0); ASSERT(a_RelBlockX < 512); ASSERT(a_RelBlockZ < 512); int chunkX = a_RelBlockX / 16; int chunkZ = a_RelBlockZ / 16; Chunk & chunk = m_Chunks[chunkX + 32 * chunkZ]; if (chunk.isValid()) { return chunk.getBiome(a_RelBlockX - 16 * chunkX, a_RelBlockZ - 16 * chunkZ); } else { return biInvalidBiome; } } void Region::blockToRegion(int a_BlockX, int a_BlockZ, int & a_RegionX, int & a_RegionZ) { a_RegionX = static_cast(std::floor(static_cast(a_BlockX) / 512)); a_RegionZ = static_cast(std::floor(static_cast(a_BlockZ) / 512)); } void Region::chunkToRegion(int a_ChunkX, int a_ChunkZ, int & a_RegionX, int & a_RegionZ) { a_RegionX = static_cast(std::floor(static_cast(a_ChunkX) / 32)); a_RegionZ = static_cast(std::floor(static_cast(a_ChunkZ) / 32)); } ================================================ FILE: Tools/QtBiomeVisualiser/Region.h ================================================ #pragma once #include "QtChunk.h" class Region { public: Region(); /** Retrieves the chunk with the specified relative coords. */ Chunk & getRelChunk(int a_RelChunkX, int a_RelChunkZ); /** Returns true iff the chunk data for all chunks has been loaded. This doesn't mean that all the chunks are valid, only that the entire region has been processed and should be displayed. */ bool isValid(void) const { return m_IsValid; } /** Returns the biome in the block coords relative to this region. Returns biInvalidBiome if the underlying chunk is not valid. */ int getRelBiome(int a_RelBlockX, int a_RelBlockZ); /** Converts block coordinates into region coordinates. */ static void blockToRegion(int a_BlockX, int a_BlockZ, int & a_RegionX, int & a_RegionZ); /** Converts chunk coordinates into region coordinates. */ static void chunkToRegion(int a_ChunkX, int a_ChunkZ, int & a_RegionX, int & a_RegionZ); protected: friend class RegionLoader; Chunk m_Chunks[32 * 32]; /** True iff the data for all the chunks has been loaded. This doesn't mean that all the chunks are valid, only that the entire region has been processed and should be displayed. */ bool m_IsValid; }; ================================================ FILE: Tools/QtBiomeVisualiser/RegionCache.cpp ================================================ #include "Globals.h" #include "RegionCache.h" #include #include #include "ChunkSource.h" #include "RegionLoader.h" #include "Region.h" RegionCache::RegionCache(QObject * parent) : super(parent) { m_Cache.setMaxCost(1024 * 1024 * 1024); // 1 GiB of memory for the cache } RegionPtr RegionCache::fetch(int a_RegionX, int a_RegionZ) { // Retrieve from the cache: quint32 hash = getRegionHash(a_RegionX, a_RegionZ); RegionPtr * res; { QMutexLocker lock(&m_Mtx); res = m_Cache[hash]; // If succesful and region loaded, return the retrieved value: if ((res != nullptr) && (*res)->isValid()) { return *res; } } // If the region is in cache but not valid, it means it has been already queued for rendering, do nothing now: if (res != nullptr) { return RegionPtr(nullptr); } // There's no such item in the cache, create it now: try { res = new RegionPtr(new Region); } catch (const std::bad_alloc &) { /* Allocation failed (32-bit process hit the 2 GiB barrier?) This may happen even with the cache set to 1 GiB, because it contains shared ptrs and so they may be held by another place in the code even when they are removed from cache. */ return RegionPtr(nullptr); } if (res == nullptr) { return RegionPtr(nullptr); } { QMutexLocker lock(&m_Mtx); m_Cache.insert(hash, res, sizeof(Region)); } // Queue the region for rendering: queueRegionRender(a_RegionX, a_RegionZ, *res); // Return failure, the region is not yet rendered: return RegionPtr(nullptr); } void RegionCache::setChunkSource(std::shared_ptr a_ChunkSource) { // Replace the chunk source: m_ChunkSource = a_ChunkSource; // Clear the cache: QMutexLocker lock(&m_Mtx); m_Cache.clear(); } void RegionCache::reload() { assert(m_ChunkSource.get() != nullptr); // Reload the chunk source: m_ChunkSource->reload(); // Clear the cache: QMutexLocker lock(&m_Mtx); m_Cache.clear(); } void RegionCache::gotRegion(int a_RegionX, int a_RegionZ) { emit regionAvailable(a_RegionX, a_RegionZ); } quint32 RegionCache::getRegionHash(int a_RegionX, int a_RegionZ) { // Simply join the two coords into a single int // The coords will never be larger than 16-bits, so we can do this safely return (((static_cast(a_RegionX) & 0xffff) << 16) | (static_cast(a_RegionZ) & 0xffff)); } void RegionCache::queueRegionRender(int a_RegionX, int a_RegionZ, RegionPtr & a_Region) { // Create a new loader task: RegionLoader * loader = new RegionLoader(a_RegionX, a_RegionZ, a_Region, m_ChunkSource); connect(loader, SIGNAL(loaded(int, int)), this, SLOT(gotRegion(int, int))); QThreadPool::globalInstance()->start(loader); } ================================================ FILE: Tools/QtBiomeVisualiser/RegionCache.h ================================================ #pragma once #include #include #include #include // fwd: class Region; typedef std::shared_ptr RegionPtr; class ChunkSource; /** Caches regions' chunk data for reuse */ class RegionCache : public QObject { typedef QObject super; Q_OBJECT public: explicit RegionCache(QObject * parent = NULL); /** Retrieves the specified region from the cache. Only returns valid regions; if the region is invalid, queues it for rendering and returns an empty ptr. */ RegionPtr fetch(int a_RegionX, int a_RegionZ); /** Replaces the chunk source used by the biome view to get the chunk biome data. The cache is then invalidated. */ void setChunkSource(std::shared_ptr a_ChunkSource); /** Returns true iff the chunk source has been initialized. */ bool hasData() const { return (m_ChunkSource.get() != nullptr); } /** Reloads the current chunk source. */ void reload(); signals: void regionAvailable(int a_RegionX, int a_RegionZ); protected slots: void gotRegion(int a_RegionX, int a_RegionZ); protected: /** The cache of the chunks */ QCache m_Cache; /** Locks the cache against multithreaded access */ QMutex m_Mtx; /** The source used to get the biome data. */ std::shared_ptr m_ChunkSource; /** Returns the hash used by the chunk in the cache */ quint32 getRegionHash(int a_RegionX, int a_RegionZ); /** Queues the specified region for rendering by m_RegionSource. */ void queueRegionRender(int a_RegionX, int a_RegionZ, RegionPtr & a_Region); }; ================================================ FILE: Tools/QtBiomeVisualiser/RegionLoader.cpp ================================================ #include "Globals.h" #include "RegionLoader.h" #include "ChunkSource.h" #include "Region.h" volatile bool RegionLoader::m_IsShuttingDown = false; RegionLoader::RegionLoader(int a_RegionX, int a_RegionZ, RegionPtr a_Region, ChunkSourcePtr a_ChunkSource) : m_RegionX(a_RegionX), m_RegionZ(a_RegionZ), m_Region(a_Region), m_ChunkSource(a_ChunkSource) { } void RegionLoader::run() { // Load all the chunks in this region: for (int z = 0; z < 32; z++) { for (int x = 0; x < 32; x++) { m_ChunkSource->getChunkBiomes(m_RegionX * 32 + x, m_RegionZ * 32 + z, m_Region->getRelChunk(x, z)); if (m_IsShuttingDown) { return; } } } m_Region->m_IsValid = true; emit loaded(m_RegionX, m_RegionZ); } ================================================ FILE: Tools/QtBiomeVisualiser/RegionLoader.h ================================================ #pragma once #include #include #include // fwd: class Region; typedef std::shared_ptr RegionPtr; class ChunkSource; typedef std::shared_ptr ChunkSourcePtr; class RegionLoader : public QObject, public QRunnable { Q_OBJECT public: RegionLoader(int a_RegionX, int a_RegionZ, RegionPtr a_Region, ChunkSourcePtr a_ChunkSource); virtual ~RegionLoader() {} /** Signals to all loaders that the app is shutting down and the loading should be aborted. */ static void shutdown() { m_IsShuttingDown = true; } signals: void loaded(int a_RegionX, int a_RegionZ); protected: virtual void run() override; private: /** Coords of the region to be loaded. */ int m_RegionX, m_RegionZ; /** The region to be loaded. */ RegionPtr m_Region; /** The chunk source to be used for individual chunks within the region. */ ChunkSourcePtr m_ChunkSource; /** Flag that is set upon app exit to terminate the queued loaders faster. */ static volatile bool m_IsShuttingDown; }; ================================================ FILE: Tools/RCONClient/.gitignore ================================================ Debug/ logs/ Release/ *.suo *.user *.ncb *.sdf ================================================ FILE: Tools/RCONClient/Globals.cpp ================================================ // Globals.cpp // This file is used for precompiled header generation in MSVC environments #include "Globals.h" ================================================ FILE: Tools/RCONClient/Globals.h ================================================ // Globals.h // This file gets included from every module in the project, so that global symbols may be introduced easily // Also used for precompiled header generation in MSVC environments // Compiler-dependent stuff: #if defined(_MSC_VER) // MSVC produces warning C4481 on the override keyword usage, so disable the warning altogether #pragma warning(disable:4481) // Disable some warnings that we don't care about: #pragma warning(disable:4100) // Use non-standard defines in #define _USE_MATH_DEFINES #elif defined(__GNUC__) // TODO: Can GCC explicitly mark classes as abstract (no instances can be created)? #define abstract #else #error "You are using an unsupported compiler, you might need to #define some stuff here for your compiler" #endif // Integral types with predefined sizes: typedef long long Int64; typedef int Int32; typedef short Int16; typedef unsigned long long UInt64; typedef unsigned int UInt32; typedef unsigned short UInt16; typedef unsigned char Byte; // A macro to disallow the copy constructor and operator= functions // This should be used in the private: declarations for any class that shouldn't allow copying itself #define DISALLOW_COPY_AND_ASSIGN(TypeName) \ TypeName(const TypeName &); \ void operator=(const TypeName &) // A macro that is used to mark unused function parameters, to avoid pedantic warnings in gcc #define UNUSED(X) (void)(X) // OS-dependent stuff: #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN #define _WIN32_WINNT 0x502 // We want to target WinXP SP2 and higher #include #include #include // IPv6 stuff // Windows SDK defines min and max macros, messing up with our std::min and std::max usage #undef min #undef max // Windows SDK defines GetFreeSpace as a constant, probably a Win16 API remnant #ifdef GetFreeSpace #undef GetFreeSpace #endif // GetFreeSpace #else #include #include // for mkdir #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #endif // CRT stuff: #include #include #include #include #include #include // STL stuff: #include #include #include #include #include #include #include // Common headers (part 1, without macros): #include "StringUtils.h" #include "OSSupport/CriticalSection.h" #include "OSSupport/File.h" #include "OSSupport/Event.h" #include "Logger.h" // Common definitions: /** Evaluates to the number of elements in an array (compile-time!) */ #define ARRAYCOUNT(X) (sizeof(X) / sizeof(*(X))) /** Allows arithmetic expressions like "32 KiB" (but consider using parenthesis around it, "(32 KiB)") */ #define KiB * 1024 /** Faster than (int)floorf((float)x / (float)div) */ #define FAST_FLOOR_DIV(x, div) ((x) < 0 ? (((int)x / div) - 1) : ((int)x / div)) // Own version of assert() that writes failed assertions to the log for review #ifdef NDEBUG #define ASSERT(x) ((void)0) #else #define ASSERT assert #endif // Pretty much the same as ASSERT() but stays in Release builds #define VERIFY(x) (!!(x) || (LOGERROR("Verification failed: %s, file %s, line %i", #x, __FILE__, __LINE__), exit(1), 0)) ================================================ FILE: Tools/RCONClient/RCONClient.cpp ================================================ // RCONClient.cpp // Implements the main app entrypoint #include "Globals.h" #include "OSSupport/Socket.h" #include "ByteBuffer.h" // If set to true, verbose messages are output to stderr. Use the "-v" or "--verbose" param to turn on bool g_IsVerbose = false; /** This class can read and write RCON packets to / from a connected socket */ class cRCONPacketizer { public: enum { ptCommand = 2, ptLogin = 3, } ; cRCONPacketizer(cSocket & a_Socket); /** Sends the packet to the socket and waits until the response is received. Returns true if response successfully received, false if the client disconnected or protocol error. Dumps the reply payload to stdout. */ bool SendPacket(int a_PacketType, const AString & a_PacketPayload); protected: /** The socket to use for reading incoming data and writing outgoing data: */ cSocket & m_Socket; /** The RequestID of the packet that is being sent. Incremented when the reply is received */ int m_RequestID; /** Receives the full response and dumps its payload to stdout. Returns true if successful, false if the client disconnected or protocol error. */ bool ReceiveResponse(void); /** Parses the received response packet and dumps its payload to stdout. Returns true if successful, false on protocol error Assumes that the packet length has already been read from the packet If the packet is successfully parsed, increments m_RequestID */ bool ParsePacket(cByteBuffer & a_Buffer, int a_PacketLength); } ; cRCONPacketizer::cRCONPacketizer(cSocket & a_Socket) : m_Socket(a_Socket), m_RequestID(0) { } bool cRCONPacketizer::SendPacket(int a_PacketType, const AString & a_PacketPayload) { // Send the packet: cByteBuffer bb(a_PacketPayload.size() + 30); bb.WriteLEInt(m_RequestID); bb.WriteLEInt(a_PacketType); bb.WriteBuf(a_PacketPayload.data(), a_PacketPayload.size()); bb.WriteBEShort(0); // Padding AString Packet; bb.ReadAll(Packet); size_t Length = Packet.size(); if (!m_Socket.Send((const char *)&Length, 4)) { fprintf(stderr, "Network error while sending packet: %d (%s). Aborting.\n", cSocket::GetLastError(), cSocket::GetLastErrorString().c_str() ); return false; } if (!m_Socket.Send(Packet.data(), Packet.size())) { fprintf(stderr, "Network error while sending packet: %d (%s). Aborting.\n", cSocket::GetLastError(), cSocket::GetLastErrorString().c_str() ); return false; } return ReceiveResponse(); } bool cRCONPacketizer::ReceiveResponse(void) { // Receive the response: cByteBuffer Buffer(64 KiB); while (true) { char buf[1024]; int NumReceived = m_Socket.Receive(buf, sizeof(buf), 0); if (NumReceived == 0) { fprintf(stderr, "The remote end closed the connection. Aborting.\n"); return false; } if (NumReceived < 0) { fprintf(stderr, "Network error while receiving response: %d, %d (%s). Aborting.\n", NumReceived, cSocket::GetLastError(), cSocket::GetLastErrorString().c_str() ); return false; } Buffer.Write(buf, NumReceived); Buffer.ResetRead(); // Check if the buffer contains the full packet: if (!Buffer.CanReadBytes(14)) { // 14 is the minimum packet size for RCON continue; } int PacketSize; VERIFY(Buffer.ReadLEInt(PacketSize)); if (!Buffer.CanReadBytes(PacketSize)) { // The packet is not complete yet continue; } // Parse the packet return ParsePacket(Buffer, PacketSize); } } bool cRCONPacketizer::ParsePacket(cByteBuffer & a_Buffer, int a_PacketLength) { // Check that the request ID is equal bool IsValid = true; int RequestID = 0; VERIFY(a_Buffer.ReadLEInt(RequestID)); if (RequestID != m_RequestID) { if ((RequestID == -1) && (m_RequestID == 0)) { fprintf(stderr, "Login failed. Aborting.\n"); IsValid = false; // Continue, so that the payload is printed before the program aborts. } else { fprintf(stderr, "The server returned an invalid request ID, got %d, exp. %d. Aborting.\n", RequestID, m_RequestID); return false; } } // Check the packet type: int PacketType = 0; VERIFY(a_Buffer.ReadLEInt(PacketType)); if (PacketType != ptCommand) { fprintf(stderr, "The server returned an unknown packet type: %d. Aborting.\n", PacketType); IsValid = false; // Continue, so that the payload is printed before the program aborts. } AString Payload; VERIFY(a_Buffer.ReadString(Payload, a_PacketLength - 10)); // Dump the payload to stdout, in a binary mode fwrite(Payload.data(), Payload.size(), 1, stdout); if (IsValid) { m_RequestID++; return true; } return false; } //////////////////////////////////////////////////////////////////////////////// // main: int RealMain(int argc, char * argv[]) { cLogger::InitiateMultithreading(); // Parse the cmdline params for server IP, port, password and the commands to send: AString ServerAddress, Password; int ServerPort = -1; AStringVector Commands; for (int i = 1; i < argc; i++) { if (((NoCaseCompare(argv[i], "-s") == 0) || (NoCaseCompare(argv[i], "--server") == 0)) && (i < argc - 1)) { ServerAddress = argv[i + 1]; i++; continue; } if (((NoCaseCompare(argv[i], "-p") == 0) || (NoCaseCompare(argv[i], "--port") == 0)) && (i < argc - 1)) { ServerPort = atoi(argv[i + 1]); i++; continue; } if (((NoCaseCompare(argv[i], "-w") == 0) || (NoCaseCompare(argv[i], "--password") == 0)) && (i < argc - 1)) { Password = argv[i + 1]; i++; continue; } if (((NoCaseCompare(argv[i], "-c") == 0) || (NoCaseCompare(argv[i], "--cmd") == 0) || (NoCaseCompare(argv[i], "--command") == 0)) && (i < argc - 1)) { Commands.push_back(argv[i + 1]); i++; continue; } if (((NoCaseCompare(argv[i], "-f") == 0) || (NoCaseCompare(argv[i], "--file") == 0)) && (i < argc - 1)) { i++; cFile f(argv[i], cFile::fmRead); if (!f.IsOpen()) { fprintf(stderr, "Cannot read commands from file \"%s\", aborting.", argv[i]); return 2; } AString cmd; f.ReadRestOfFile(cmd); Commands.push_back(cmd); continue; } if ((NoCaseCompare(argv[i], "-v") == 0) || (NoCaseCompare(argv[i], "--verbose") == 0)) { fprintf(stderr, "Verbose output enabled\n"); g_IsVerbose = true; continue; } fprintf(stderr, "Unknown parameter: \"%s\". Aborting.", argv[i]); return 1; } // for i - argv[] if (ServerAddress.empty() || (ServerPort < 0)) { fprintf(stderr, "Server address or port not set. Use the --server and --port parameters to set them. Aborting."); return 1; } // Connect: if (cSocket::WSAStartup() != 0) { fprintf(stderr, "Cannot initialize network stack. Aborting\n"); return 6; } if (g_IsVerbose) { fprintf(stderr, "Connecting to \"%s:%d\"...\n", ServerAddress.c_str(), ServerPort); } cSocket s = cSocket::CreateSocket(cSocket::IPv4); if (!s.ConnectIPv4(ServerAddress, (unsigned short)ServerPort)) { fprintf(stderr, "Cannot connect to \"%s:%d\": %s\n", ServerAddress.c_str(), ServerPort, cSocket::GetLastErrorString().c_str()); return 3; } cRCONPacketizer Packetizer(s); // Authenticate using the provided password: if (!Password.empty()) { if (g_IsVerbose) { fprintf(stderr, "Sending the login packet...\n"); } if (!Packetizer.SendPacket(cRCONPacketizer::ptLogin, Password)) { // Error message has already been printed, bail out return 4; } } else { if (g_IsVerbose) { fprintf(stderr, "No password provided, not sending a login packet.\n"); } } // Send each command: for (AStringVector::const_iterator itr = Commands.begin(), end = Commands.end(); itr != end; ++itr) { if (g_IsVerbose) { fprintf(stderr, "Sending command \"%s\"...\n", itr->c_str()); } if (!Packetizer.SendPacket(cRCONPacketizer::ptCommand, *itr)) { return 5; } } return 0; } int main(int argc, char * argv[]) { // This redirection function is only so that debugging the program is easier in MSVC - when RealMain exits, it's still possible to place a breakpoint int res = RealMain(argc, argv); return res; } ================================================ FILE: Tools/ToLuaDoxy/Doxyfile ================================================ # Doxyfile 1.8.1.2 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project # # All text after a hash (#) is considered a comment and will be ignored # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" ") #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file # that follow. The default is UTF-8 which is also the encoding used for all # text before the first occurrence of this tag. Doxygen uses libiconv (or the # iconv built into libc) for the transcoding. See # https://www.gnu.org/software/libiconv for the list of possible encodings. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or sequence of words) that should # identify the project. Note that if you do not use Doxywizard you need # to put quotes around the project name if it contains spaces. PROJECT_NAME = API # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer # a quick idea about the purpose of the project. Keep the description short. PROJECT_BRIEF = "Functions and classes available in the Lua API" # With the PROJECT_LOGO tag one can specify an logo or icon that is # included in the documentation. The maximum height of the logo should not # exceed 55 pixels and the maximum width should not exceed 200 pixels. # Doxygen will copy the logo to the output directory. PROJECT_LOGO = # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = doxy # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output # format and will distribute the generated files over these directories. # Enabling this option can be useful when feeding doxygen a huge amount of # source files, where putting all generated files in the same directory would # otherwise cause performance problems for the file system. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, # Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, # Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English # messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, # Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, # Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will # include brief member descriptions after the members that are listed in # the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # the brief description of a member or function before the detailed description. # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator # that is used to form the text in various listings. Each string # in this list, if found as the leading text of the brief description, will be # stripped from the text and the result after processing the whole list, is # used as the annotated text. Otherwise, the brief description is used as-is. # If left blank, the following values are used ("$name" is automatically # replaced with the name of the entity): "The $name class" "The $name widget" # "The $name file" "is" "provides" "specifies" "contains" # "represents" "a" "an" "the" ABBREVIATE_BRIEF = "The $name class" \ "The $name widget" \ "The $name file" \ is \ provides \ specifies \ contains \ represents \ a \ an \ the # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full # path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = YES # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag # can be used to strip a user-defined part of the path. Stripping is # only done if one of the specified strings matches the left-hand part of # the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the # path to strip. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells # the reader which header file to include in order to use a class. # If left blank only the name of the header file containing the class # definition is used. Otherwise one should specify the include paths that # are normally passed to the compiler using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful if your file system # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = YES # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style # comment as the brief description. If set to NO, the JavaDoc # comments will behave just like regular Qt-style comments # (thus requiring an explicit @brief command for a brief description.) JAVADOC_AUTOBRIEF = NO # If the QT_AUTOBRIEF tag is set to YES then Doxygen will # interpret the first line (until the first dot) of a Qt-style # comment as the brief description. If set to NO, the comments # will behave just like regular Qt-style comments (thus requiring # an explicit \brief command for a brief description.) QT_AUTOBRIEF = YES # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen # treat a multi-line C++ special comment block (i.e. a block of //! or /// # comments) as a brief description. This used to be the default behaviour. # The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = NO # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # re-implements. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce # a new page for each member. If set to NO, the documentation of a member will # be part of the file/class/namespace that contains it. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 2 # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" will allow you to # put the command \sideeffect (or @sideeffect) in the documentation, which # will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. ALIASES = # This tag can be used to specify a number of word-keyword mappings (TCL only). # A mapping has the form "name=value". For example adding # "class=itcl::class" will allow you to use the command class in the # itcl::class meaning. TCL_SUBST = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C # sources only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = NO # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java # sources only. Doxygen will then generate output that is more tailored for # Java. For instance, namespaces will be presented as packages, qualified # scopes will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources only. Doxygen will then generate output that is more tailored for # Fortran. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for # VHDL. OPTIMIZE_OUTPUT_VHDL = NO # Doxygen selects the parser to use depending on the extension of the files it # parses. With this tag you can assign which parser to use for a given extension. # Doxygen has a built-in mapping, but you can override or extend it using this # tag. The format is ext=language, where ext is a file extension, and language # is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, # C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make # doxygen treat .inc files as Fortran files (default is PHP), and .f files as C # (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions # you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. EXTENSION_MAPPING = # If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all # comments according to the Markdown format, which allows for more readable # documentation. See https://daringfireball.net/projects/markdown/ for details. # The output of markdown processing is further processed by doxygen, so you # can mix doxygen, HTML, and XML commands with Markdown formatting. # Disable only in case of backward compatibilities issues. MARKDOWN_SUPPORT = YES # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should # set this tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); v.s. # func(std::string) {}). This also makes the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. BUILTIN_STL_SUPPORT = NO # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. # Doxygen will parse them like normal C++ but will assume all classes use public # instead of private inheritance when no explicit protection keyword is present. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate getter # and setter methods for a property. Setting this option to YES (the default) # will make doxygen replace the get and set methods by a property in the # documentation. This will only work if the methods are indeed getting or # setting a simple type. If this is not the case, or you want to show the # methods anyway, you should set this option to NO. IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = NO # Set the SUBGROUPING tag to YES (the default) to allow class member groups of # the same type (for instance a group of public functions) to be put as a # subgroup of that type (e.g. under the Public Functions section). Set it to # NO to prevent subgrouping. Alternatively, this can be done per class using # the \nosubgrouping command. SUBGROUPING = YES # When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and # unions are shown inside the group in which they are included (e.g. using # @ingroup) instead of on a separate page (for HTML and Man pages) or # section (for LaTeX and RTF). INLINE_GROUPED_CLASSES = NO # When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and # unions with only public data fields will be shown inline in the documentation # of the scope in which they are defined (i.e. file, namespace, or group # documentation), provided this scope is documented. If set to NO (the default), # structs, classes, and unions are shown on a separate page (for HTML and Man # pages) or section (for LaTeX and RTF). INLINE_SIMPLE_STRUCTS = NO # When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum # is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically # be useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. TYPEDEF_HIDES_STRUCT = NO # The SYMBOL_CACHE_SIZE determines the size of the internal cache use to # determine which symbols to keep in memory and which to flush to disk. # When the cache is full, less often used symbols will be written to disk. # For small to medium size projects (<1000 input files) the default value is # probably good enough. For larger projects a too small cache size can cause # doxygen to be busy swapping symbols to and from disk most of the time # causing a significant performance penalty. # If the system has enough physical memory increasing the cache will improve the # performance by keeping more symbols in memory. Note that the value works on # a logarithmic scale so increasing the size by one will roughly double the # memory usage. The cache size is given by this formula: # 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, # corresponding to a cache size of 2^16 = 65536 symbols. SYMBOL_CACHE_SIZE = 0 # Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be # set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given # their name and scope. Since this can be an expensive process and often the # same symbol appear multiple times in the code, doxygen keeps a cache of # pre-resolved symbols. If the cache is too small doxygen will become slower. # If the cache is too large, memory is wasted. The cache size is given by this # formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0, # corresponding to a cache size of 2^16 = 65536 symbols. LOOKUP_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES EXTRACT_ALL = YES # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = NO # If the EXTRACT_PACKAGE tag is set to YES all members with package or internal # scope will be included in the documentation. EXTRACT_PACKAGE = NO # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = YES # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. When set to YES local # methods, which are defined in the implementation section but not in # the interface are included in the documentation. # If set to NO (the default) only methods in the interface are included. EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base # name of the file that contains the anonymous namespace. By default # anonymous namespaces are hidden. EXTRACT_ANON_NSPACES = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) these members will be included in the # various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. # If set to NO (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all # friend (class|struct|union) declarations. # If set to NO (the default) these declarations will be included in the # documentation. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any # documentation blocks found inside the body of a function. # If set to NO (the default) these blocks will be appended to the # function's detailed documentation block. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation # that is typed after a \internal command is included. If the tag is set # to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. CASE_SENSE_NAMES = NO # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = YES # If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen # will list include files with double quotes in the documentation # rather than with sharp brackets. FORCE_LOCAL_INCLUDES = NO # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen # will sort the (detailed) documentation of file and class members # alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the # brief documentation of file, namespace and class members alphabetically # by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = YES # If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen # will sort the (brief and detailed) documentation of class members so that # constructors and destructors are listed first. If set to NO (the default) # the constructors will appear in the respective orders defined by # SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. # This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO # and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. SORT_MEMBERS_CTORS_1ST = NO # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the # hierarchy of group names into alphabetical order. If set to NO (the default) # the group names will appear in their defined order. SORT_GROUP_NAMES = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be # sorted by fully-qualified names, including namespaces. If set to # NO (the default), the class list will be sorted only by class name, # not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the # alphabetical list. SORT_BY_SCOPE_NAME = NO # If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to # do proper type resolution of all parameters of a function it will reject a # match between the prototype and the implementation of a member function even # if there is only one candidate or it is obvious which candidate to choose # by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen # will still accept a match between prototype and implementation in such cases. STRICT_PROTO_MATCHING = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or # disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or macro consists of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. # The appearance of the initializer of individual variables and macros in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated # at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = NO # Set the SHOW_FILES tag to NO to disable the generation of the Files page. # This will remove the Files entry from the Quick Index and from the # Folder Tree View (if specified). The default is YES. SHOW_FILES = NO # Set the SHOW_NAMESPACES tag to NO to disable the generation of the # Namespaces page. This will remove the Namespaces entry from the Quick Index # and from the Folder Tree View (if specified). The default is YES. SHOW_NAMESPACES = NO # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command , where is the value of # the FILE_VERSION_FILTER tag, and is the name of an input file # provided by doxygen. Whatever the program writes to standard output # is used as the file version. See the manual for examples. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed # by doxygen. The layout file controls the global structure of the generated # output files in an output format independent way. To create the layout file # that represents doxygen's defaults, run doxygen with the -l option. # You can optionally specify a file name after the option, if omitted # DoxygenLayout.xml will be used as the name of the layout file. LAYOUT_FILE = # The CITE_BIB_FILES tag can be used to specify one or more bib files # containing the references data. This must be a list of .bib files. The # .bib extension is automatically appended if omitted. Using this command # requires the bibtex tool to be installed. See also # https://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style # of the bibliography can be controlled using LATEX_BIB_STYLE. To use this # feature you need bibtex and perl available in the search path. CITE_BIB_FILES = #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings # for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = YES # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some # parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES # The WARN_NO_PARAMDOC option can be enabled to get warnings for # functions that are documented, but have no documentation for their parameters # or return value. If set to NO (the default) doxygen will only warn about # wrong or incomplete parameter documentation, but not about the absence of # documentation. WARN_NO_PARAMDOC = NO # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text # tags, which will be replaced by the file and line number from which the # warning originated and the warning text. Optionally the format may contain # $version, which will be replaced by the version of the file (if it could # be obtained via FILE_VERSION_FILTER) WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written # to stderr. WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be used to specify the files and/or directories that contain # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # with spaces. INPUT = Out # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is # also the default input encoding. Doxygen uses libiconv (or the iconv built # into libc) for the transcoding. See https://www.gnu.org/software/libiconv for # the list of possible encodings. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh # *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py # *.f90 *.f *.for *.vhd *.vhdl FILE_PATTERNS = *.c \ *.cc \ *.cxx \ *.cpp \ *.c++ \ *.d \ *.java \ *.ii \ *.ixx \ *.ipp \ *.i++ \ *.inl \ *.h \ *.hh \ *.hxx \ *.hpp \ *.h++ \ *.idl \ *.odl \ *.cs \ *.php \ *.php3 \ *.inc \ *.m \ *.markdown \ *.md \ *.mm \ *.dox \ *.py \ *.f90 \ *.f \ *.for \ *.vhd \ *.vhdl # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = NO # The EXCLUDE tag can be used to specify files and/or directories that should be # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. # Note that relative paths are relative to the directory from which doxygen is # run. EXCLUDE = source/SQLite \ source/squirrelbindings # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded # from the input. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. Note that the wildcards are matched # against the file with absolute path, so to exclude all test directories # for example use the pattern */test/* EXCLUDE_PATTERNS = *StackWalker.* \ *LeakFinder.* \ *Bindings.* \ *ManualBindings.* # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test EXCLUDE_SYMBOLS = _* \ __* \ abstract # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. EXAMPLE_PATTERNS = * # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command , where # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. If FILTER_PATTERNS is specified, this tag will be # ignored. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. Doxygen will compare the file name with each pattern and apply the # filter if there is a match. The filters are a list of the form: # pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further # info on how filters are used. If FILTER_PATTERNS is empty or if # non of the patterns match the file name, INPUT_FILTER is applied. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO # The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file # pattern. A pattern will override the setting for FILTER_PATTERN (if any) # and it is also possible to disable source filtering for a specific pattern # using *.ext= (so without naming a filter). This option only has effect when # FILTER_SOURCE_FILES is enabled. FILTER_SOURCE_PATTERNS = #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. # Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. SOURCE_BROWSER = NO # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C, C++ and Fortran comments will always remain visible. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = NO # If the REFERENCES_RELATION tag is set to YES # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = NO # If the REFERENCES_LINK_SOURCE tag is set to YES (the default) # and SOURCE_BROWSER tag is set to YES, then the hyperlinks from # functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will # link to the source code. Otherwise they will link to the documentation. REFERENCES_LINK_SOURCE = NO # If the USE_HTAGS tag is set to YES then the references to source code # will point to the HTML generated by the htags(1) tool instead of doxygen # built-in source browser. The htags tool is part of GNU's global source # tagging system (see https://www.gnu.org/software/global/global.html). You # will need version 4.8.6 or higher. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen # will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = NO #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = YES # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = c #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. Note that when using a custom header you are responsible # for the proper inclusion of any scripts and style sheets that doxygen # needs, which is dependent on the configuration options used. # It is advised to generate a default header using "doxygen -w html # header.html footer.html stylesheet.css YourConfigFile" and then modify # that header. Note that the header is subject to change so you typically # have to redo this when upgrading to a newer version of doxygen or when # changing the value of configuration settings such as GENERATE_TREEVIEW! HTML_HEADER = # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If the tag is left blank doxygen # will generate a default style sheet. Note that doxygen will try to copy # the style sheet file to the HTML output directory, so don't put your own # style sheet in the HTML output directory as well, or it will be erased! HTML_STYLESHEET = # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the HTML output directory. Note # that these files will be copied to the base HTML output directory. Use the # $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these # files. In the HTML_STYLESHEET file, use the file name only. Also note that # the files will be copied as-is; there are no commands or markers available. HTML_EXTRA_FILES = # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. # Doxygen will adjust the colors in the style sheet and background images # according to this color. Hue is specified as an angle on a colorwheel, # see https://en.wikipedia.org/wiki/Hue for more information. # For instance the value 0 represents red, 60 is yellow, 120 is green, # 180 is cyan, 240 is blue, 300 purple, and 360 is red again. # The allowed range is 0 to 359. HTML_COLORSTYLE_HUE = 220 # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of # the colors in the HTML output. For a value of 0 the output will use # grayscales only. A value of 255 will produce the most vivid colors. HTML_COLORSTYLE_SAT = 100 # The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to # the luminance component of the colors in the HTML output. Values below # 100 gradually make the output lighter, whereas values above 100 make # the output darker. The value divided by 100 is the actual gamma applied, # so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, # and 100 does not change the gamma. HTML_COLORSTYLE_GAMMA = 80 # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML # page will contain the date and time when the page was generated. Setting # this to NO can help when comparing the output of multiple runs. HTML_TIMESTAMP = YES # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. HTML_DYNAMIC_SECTIONS = NO # With HTML_INDEX_NUM_ENTRIES one can control the preferred number of # entries shown in the various tree structured indices initially; the user # can expand and collapse entries dynamically later on. Doxygen will expand # the tree to such a level that at most the specified number of entries are # visible (unless a fully collapsed tree already exceeds this amount). # So setting the number of entries 1 will produce a full collapsed tree by # default. 0 is a special value representing an infinite number of entries # and will result in a full expanded tree by default. HTML_INDEX_NUM_ENTRIES = 100 # If the GENERATE_DOCSET tag is set to YES, additional index files # will be generated that can be used as input for Apple's Xcode 3 # integrated development environment, introduced with OSX 10.5 (Leopard). # To create a documentation set, doxygen will generate a Makefile in the # HTML output directory. Running make will produce the docset in that # directory and running "make install" will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find # it at startup. # See https://developer.apple.com/tools/creatingdocsetswithdoxygen.html # for more information. GENERATE_DOCSET = NO # When GENERATE_DOCSET tag is set to YES, this tag determines the name of the # feed. A documentation feed provides an umbrella under which multiple # documentation sets from a single provider (such as a company or product suite) # can be grouped. DOCSET_FEEDNAME = "Doxygen generated docs" # When GENERATE_DOCSET tag is set to YES, this tag specifies a string that # should uniquely identify the documentation set bundle. This should be a # reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen # will append .docset to the name. DOCSET_BUNDLE_ID = org.doxygen.Project # When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify # the documentation publisher. This should be a reverse domain-name style # string, e.g. com.mycompany.MyDocSet.documentation. DOCSET_PUBLISHER_ID = org.doxygen.Publisher # The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. DOCSET_PUBLISHER_NAME = Publisher # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compiled HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You # can add a path in front of the file if the result should not be # written to the html output directory. CHM_FILE = # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can # be used to specify the location (absolute path including file name) of # the HTML help compiler (hhc.exe). If non-empty doxygen will try to run # the HTML help compiler on the generated index.hhp. HHC_LOCATION = # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING # is used to encode HtmlHelp index (hhk), content (hhc) and project file # content. CHM_INDEX_ENCODING = # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = NO # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and # QHP_VIRTUAL_FOLDER are set, an additional index file will be generated # that can be used as input for Qt's qhelpgenerator to generate a # Qt Compressed Help (.qch) of the generated HTML documentation. GENERATE_QHP = NO # If the QHG_LOCATION tag is specified, the QCH_FILE tag can # be used to specify the file name of the resulting .qch file. # The path specified is relative to the HTML output folder. QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # https://doc.qt.io/qt-5/qthelpproject.html#namespace QHP_NAMESPACE = org.doxygen.Project # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # https://doc.qt.io/qt-5/qthelpproject.html#virtual-folders QHP_VIRTUAL_FOLDER = doc # If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to # add. For more information please see # https://doc.qt.io/qt-5/qthelpproject.html#custom-filters QHP_CUST_FILTER_NAME = # The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the # custom filter to add. For more information please see # # Qt Help Project / Custom Filters. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # project's # filter section matches. # # Qt Help Project / Filter Attributes. QHP_SECT_FILTER_ATTRS = # If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can # be used to specify the location of Qt's qhelpgenerator. # If non-empty doxygen will try to run qhelpgenerator on the generated # .qhp file. QHG_LOCATION = # If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files # will be generated, which together with the HTML files, form an Eclipse help # plugin. To install this plugin and make it available under the help contents # menu in Eclipse, the contents of the directory containing the HTML and XML # files needs to be copied into the plugins directory of eclipse. The name of # the directory within the plugins directory should be the same as # the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before # the help appears. GENERATE_ECLIPSEHELP = NO # A unique identifier for the eclipse help plugin. When installing the plugin # the directory name containing the HTML and XML files should also have # this name. ECLIPSE_DOC_ID = org.doxygen.Project # The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) # at top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. Since the tabs have the same information as the # navigation tree you can set this option to NO if you already set # GENERATE_TREEVIEW to YES. DISABLE_INDEX = NO # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. # If the tag value is set to YES, a side panel will be generated # containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). # Windows users are probably better off using the HTML help feature. # Since the tree basically has the same information as the tab index you # could consider to set DISABLE_INDEX to NO when enabling this option. GENERATE_TREEVIEW = NO # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values # (range [0,1..20]) that doxygen will group on one line in the generated HTML # documentation. Note that a value of 0 will completely suppress the enum # values from appearing in the overview section. ENUM_VALUES_PER_LINE = 4 # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 # When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open # links to external symbols imported via tag files in a separate window. EXT_LINKS_IN_WINDOW = NO # Use this tag to change the font size of Latex formulas included # as images in the HTML documentation. The default is 10. Note that # when you change the font size after a successful doxygen run you need # to manually remove any form_*.png images from the HTML output directory # to force them to be regenerated. FORMULA_FONTSIZE = 10 # Use the FORMULA_TRANPARENT tag to determine whether or not the images # generated for formulas are transparent PNGs. Transparent PNGs are # not supported properly for IE 6.0, but are supported on all modern browsers. # Note that when changing this option you need to delete any form_*.png files # in the HTML output before the changes have effect. FORMULA_TRANSPARENT = YES # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax # (see https://www.mathjax.org) which uses client side Javascript for the # rendering instead of using prerendered bitmaps. Use this if you do not # have LaTeX installed or if you want to formulas look prettier in the HTML # output. When enabled you may also need to install MathJax separately and # configure the path to it using the MATHJAX_RELPATH option. USE_MATHJAX = NO # When MathJax is enabled you need to specify the location relative to the # HTML output directory using the MATHJAX_RELPATH option. The destination # directory should contain the MathJax.js script. For instance, if the mathjax # directory is located at the same level as the HTML output directory, then # MATHJAX_RELPATH should be ../mathjax. The default value points to # the MathJax Content Delivery Network so you can quickly see the result without # installing MathJax. However, it is strongly recommended to install a local # copy of MathJax from https://www.mathjax.org before deployment. MATHJAX_RELPATH = https://cdn.mathjax.org/mathjax/latest # The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension # names that should be enabled during MathJax rendering. MATHJAX_EXTENSIONS = # When the SEARCHENGINE tag is enabled doxygen will generate a search box # for the HTML output. The underlying search engine uses javascript # and DHTML and should work on any modern browser. Note that when using # HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets # (GENERATE_DOCSET) there is already a search function so this one should # typically be disabled. For large projects the javascript based search engine # can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. SEARCHENGINE = NO # When the SERVER_BASED_SEARCH tag is enabled the search engine will be # implemented using a PHP enabled web server instead of at the web client # using Javascript. Doxygen will generate the search PHP script and index # file to put on the web server. The advantage of the server # based approach is that it scales better to large projects and allows # full text search. The disadvantages are that it is more difficult to setup # and does not have live searching capabilities. SERVER_BASED_SEARCH = NO #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = NO # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. # Note that when enabling USE_PDFLATEX this option is only used for # generating bitmaps for formulas in the HTML output, but not in the # Makefile that is written to the output directory. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4 # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = # The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for # the generated latex document. The footer should contain everything after # the last chapter. If it is left blank doxygen will generate a # standard footer. Notice: only use this tag if you know what you are doing! LATEX_FOOTER = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = YES # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = YES # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO # If LATEX_HIDE_INDICES is set to YES then doxygen will not # include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = NO # If LATEX_SOURCE_CODE is set to YES then doxygen will include # source code with syntax highlighting in the LaTeX output. # Note that which sources are shown also depends on other settings # such as SOURCE_BROWSER. LATEX_SOURCE_CODE = NO # The LATEX_BIB_STYLE tag can be used to specify the style to use for the # bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See # https://en.wikipedia.org/wiki/BibTeX for more info. LATEX_BIB_STYLE = plain #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load style sheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = NO # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = NO # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml # The XML_SCHEMA tag can be used to specify an XML schema, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- # If the GENERATE_PERLMOD tag is set to YES Doxygen will # generate a Perl module file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO # If the PERLMOD_LATEX tag is set to YES Doxygen will generate # the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be # nicely formatted so it can be parsed by a human reader. This is useful # if you want to understand what is going on. On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES # The names of the make variables in the generated doxyrules.make file # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. # This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = NO # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_DEFINED tags. EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # pointed to by INCLUDE_PATH will be searched when a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. To prevent a macro definition from being # undefined via #undef or recursively expanded use the := operator # instead of the = operator. PREDEFINED = # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition that # overrules the definition found in the source code. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all references to function-like macros # that are alone on a line, have an all uppercase name, and do not end with a # semicolon, because these will confuse the parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # The TAGFILES option can be used to specify one or more tagfiles. For each # tag file the location of the external documentation should be added. The # format of a tag file without this location is as follows: # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # TAGFILES = file1=loc1 "file2 = loc2" ... # where "loc1" and "loc2" can be relative or absolute paths # or URLs. Note that each tag file must have a unique name (where the name does # NOT include the path). If a tag file is not located in the directory in which # doxygen is run, you must also specify the path to the tagfile here. TAGFILES = # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base # or super classes. Setting the tag to NO turns the diagrams off. Note that # this option also works with HAVE_DOT disabled, but it is recommended to # install and use dot, since it yields more powerful graphs. CLASS_DIAGRAMS = YES # You can define message sequence charts within doxygen comments using the \msc # command. Doxygen will then run the mscgen tool (see # http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the # documentation. The MSCGEN_PATH tag allows you to specify the directory where # the mscgen tool resides. If left empty the tool is assumed to be found in the # default search path. MSCGEN_PATH = # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = YES # The DOT_NUM_THREADS specifies the number of dot invocations doxygen is # allowed to run in parallel. When set to 0 (the default) doxygen will # base this on the number of processors available in the system. You can set it # explicitly to a value larger than 0 to get control over the balance # between CPU load and processing speed. DOT_NUM_THREADS = 12 # By default doxygen will use the Helvetica font for all dot files that # doxygen generates. When you want a differently looking font you can specify # the font name using DOT_FONTNAME. You need to make sure dot is able to find # the font, which can be done by putting it in a standard location or by setting # the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the # directory containing the font. DOT_FONTNAME = Helvetica # The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. # The default size is 10pt. DOT_FONTSIZE = 10 # By default doxygen will tell dot to use the Helvetica font. # If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to # set the path where dot can find it. DOT_FONTPATH = # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = NO # If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen # will generate a graph for groups, showing the direct groups dependencies GROUP_GRAPHS = YES # If the UML_LOOK tag is set to YES doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = NO # If the UML_LOOK tag is enabled, the fields and methods are shown inside # the class node. If there are many fields or methods and many nodes the # graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS # threshold limits the number of items for each type to make the size more # managable. Set this to 0 for no limit. Note that the threshold may be # exceeded by 50% before the limit is enforced. UML_LIMIT_NUM_FIELDS = 10 # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = NO # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES # If the CALL_GRAPH and HAVE_DOT options are set to YES then # doxygen will generate a call dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable call graphs # for selected functions only using the \callgraph command. CALL_GRAPH = NO # If the CALLER_GRAPH and HAVE_DOT tags are set to YES then # doxygen will generate a caller dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable caller # graphs for selected functions only using the \callergraph command. CALLER_GRAPH = NO # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will generate a graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES # If the DIRECTORY_GRAPH and HAVE_DOT tags are set to YES # then doxygen will show the dependencies a directory has on other directories # in a graphical way. The dependency relations are determined by the #include # relations between the files in the directories. DIRECTORY_GRAPH = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are svg, png, jpg, or gif. # If left blank png will be used. If you choose svg you need to set # HTML_FILE_EXTENSION to xhtml in order to make the SVG files # visible in IE 9+ (other browsers do not have this requirement). DOT_IMAGE_FORMAT = png # If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to # enable generation of interactive SVG images that allow zooming and panning. # Note that this requires a modern browser other than Internet Explorer. # Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you # need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files # visible. Older versions of IE do not have SVG support. INTERACTIVE_SVG = NO # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found in the path. DOT_PATH = # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The MSCFILE_DIRS tag can be used to specify one or more directories that # contain msc files that are included in the documentation (see the # \mscfile command). MSCFILE_DIRS = # The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of # nodes that will be shown in the graph. If the number of nodes in a graph # becomes larger than this value, doxygen will truncate the graph, which is # visualized by representing a node as a red box. Note that doxygen if the # number of direct children of the root node in a graph is already larger than # DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note # that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. DOT_GRAPH_MAX_NODES = 500 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the # graphs generated by dot. A depth value of 3 means that only nodes reachable # from the root by following a path via at most 3 edges will be shown. Nodes # that lay further from the root node will be omitted. Note that setting this # option to 1 or 2 may greatly reduce the computation time needed for large # code bases. Also note that the size of a graph can be further restricted by # DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. MAX_DOT_GRAPH_DEPTH = 0 # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent # background. This is disabled by default, because dot on Windows does not # seem to support this out of the box. Warning: Depending on the platform used, # enabling this option may lead to badly anti-aliased labels on the edges of # a graph (i.e. they become hard to read). DOT_TRANSPARENT = NO # Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output # files in one run (i.e. multiple -o and -T options on the command line). This # makes dot run faster, but since only newer versions of dot (>1.8.10) # support this, this feature is disabled by default. DOT_MULTI_TARGETS = YES # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES ================================================ FILE: Tools/ToLuaDoxy/Globals.cpp ================================================ // Globals.cpp // Used for precompiled header generation in MSVC #include "Globals.h" ================================================ FILE: Tools/ToLuaDoxy/Globals.h ================================================ // Globals.h // This file is used for precompiled header generation in MSVC // OS-dependent stuff: #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN #define _WIN32_WINNT 0x501 // We want to target WinXP and higher #include #include #include // IPv6 stuff // Windows SDK defines min and max macros, messing up with our std::min and std::max usage #undef min #undef max // Windows SDK defines GetFreeSpace as a constant, probably a Win16 API remnant #ifdef GetFreeSpace #undef GetFreeSpace #endif // GetFreeSpace #else #include #include // for mkdir #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #endif // CRT stuff: #include #include #include #include // STL stuff: #include #include #include #include #include #include #include #include #include // Common headers (part 1, without macros): #include "../../src/StringUtils.h" // Common definitions: /** Evaluates to the number of elements in an array (compile-time!) */ #define ARRAYCOUNT(X) (sizeof(X) / sizeof(*(X))) /** Allows arithmetic expressions like "32 KiB" (but consider using parenthesis around it, "(32 KiB)") */ #define KiB * 1024 #define MiB * 1024 * 1024 #define ASSERT assert ================================================ FILE: Tools/ToLuaDoxy/ToLuaDoxy.cpp ================================================ // ToLuaDoxy.cpp // Implements the main app entrypoint #include "Globals.h" #include #include typedef std::vector AStrings; class cProcessor { public: cProcessor(const AString & a_FileOut) : m_Out(a_FileOut.c_str(), std::ios::out), m_IsInToLua(false), m_IsInComment(false) { } bool IsGood(void) const { return !m_Out.fail(); } void ProcessFile(const AString & a_FileIn) { std::ifstream In(a_FileIn.c_str()); if (In.fail()) { std::cerr << "Cannot open input file " << a_FileIn << "." << std::endl; return; } while (!In.eof()) { AString Line; std::getline(In, Line); PushLine(Line); } } protected: std::ofstream m_Out; bool m_IsInToLua; ///< Set to true if inside a tolua_begin .. tolua_end block bool m_IsInComment; ///< Set to true if previous line has started a multiline comment; only outside tolua blocks AString m_LastComment; ///< Accumulator for a multiline comment preceding a tolua block void PushLine(const AString & a_Line) { if (m_IsInToLua) { // Inside a tolua block if (TrimString(a_Line) == "// tolua_end") { // End of a tolua block m_IsInToLua = false; return; } m_Out << a_Line << std::endl; return; } if (m_IsInComment) { // Inside a multiline comment block, outside of a tolua block; accumulate m_LastComment m_LastComment += a_Line + "\n"; m_IsInComment = (a_Line.find("*/") == AString::npos); return; } AString Trimmed(TrimString(a_Line)); if (Trimmed == "// tolua_begin") { // Beginning of a tolua block m_IsInToLua = true; if (!m_LastComment.empty()) { m_Out << m_LastComment << std::endl; m_LastComment.clear(); } return; } size_t CommentBegin = a_Line.find("/*"); if (CommentBegin != AString::npos) { m_IsInComment = (a_Line.find("*/", CommentBegin) == AString::npos); m_LastComment = a_Line; } size_t ExportIdx = a_Line.find("// tolua_export"); if (ExportIdx != AString::npos) { // Single-line tolua block // Strip the export comment and right-trim the line: AString Stripped(a_Line.substr(0, ExportIdx)); int End = Stripped.length() - 1; while ((End > 0) && (Stripped[End] <= 32)) { End--; } Stripped.erase(End + 1); if (!m_LastComment.empty()) { m_Out << m_LastComment << std::endl; m_LastComment.clear(); } m_Out << Stripped << std::endl; return; } if (!m_IsInComment) { m_LastComment.clear(); } } } ; /** Parses the specified package file into a list of $cfile-included files and all the other contents Returns true if successful. Returns false and prints error if unsuccessful */ bool ParsePackageFile(const AString & a_FileName, AStrings & a_CFiles, AStrings & a_DirectContentsLines) { std::ifstream PkgFile(a_FileName.c_str()); if (PkgFile.fail()) { std::cerr << "Cannot open the package file " << a_FileName << "." << std::endl; return false; } while (!PkgFile.eof()) { AString Line; std::getline(PkgFile, Line); Line = TrimString(Line); if (strncmp(Line.c_str(), "$cfile \"", 8) == 0) { a_CFiles.push_back(Line.substr(8, Line.length() - 9)); } else { a_DirectContentsLines.push_back(Line); } } return true; } /** Processes the specified input header file into the output file */ void ProcessCFile(const AString & a_CFileIn, const AString & a_CFileOut) { cProcessor p(a_CFileOut); if (!p.IsGood()) { std::cerr << "Cannot open output file " << a_CFileOut << "." << std::endl; return; } p.ProcessFile(a_CFileIn); } int main(int argc, char * argv[]) { AString BaseDir = (argc > 1) ? argv[1] : "."; AString OutDir = (argc > 2) ? argv[2] : "Out"; // Create the output directory: #ifdef _WIN32 CreateDirectory(OutDir.c_str(), NULL); #else mkdir(OutDir.c_str(), S_IRWXU | S_IRWXG | S_IRWXO); #endif // Parse the package file AStrings CFiles; AStrings DirectLines; if (!ParsePackageFile(Printf("%s/AllToLua.pkg", BaseDir.c_str()), CFiles, DirectLines)) { return 1; } // Process header files: for (AStrings::const_iterator itr = CFiles.begin(), end = CFiles.end(); itr != end; ++itr) { static int cnt = 0; AString In = Printf("%s/%s", BaseDir.c_str(), itr->c_str()); AString Out = Printf("%s/%04x.h", OutDir.c_str(), cnt++); ProcessCFile(In, Out); } // for itr - CFiles[] return 0; } ================================================ FILE: android/.gitignore ================================================ /Cuberite/ Server ================================================ FILE: android/CMakeLists.txt ================================================ cmake_minimum_required (VERSION 3.12.4) project(Cuberite) # Set up Android parameters set(ANDROID TRUE) set(CMAKE_POSITION_INDEPENDENT_CODE TRUE) # We're crosscompiling for Android set(NO_NATIVE_OPTIMIZATION TRUE) # Build the rest of the server add_subdirectory(../ Cuberite) # Strip debug symbols to reduce binary size set_target_properties(${CMAKE_PROJECT_NAME} PROPERTIES LINK_FLAGS_RELEASE -s) ================================================ FILE: android/compile.sh ================================================ #!/bin/bash set -e # This script cross-compiles cuberite for the android platform. It uses # the following enviroment variables # CMAKE: Should be the path to a cmake executable of version 3.12.4+ # NDK: Should be the path to the android ndk root # (optional) TYPE: either Release or Debug, sets the build type # (optional) THREADS: The number of threads to use, default 4 function usage() { echo "Usage: NDK= CMAKE= $0 (clean|)"; exit 1 } BASEDIR="$(realpath $(dirname $0))" BUILDDIR="$BASEDIR/../android-build" SELF="./$(basename $0)" # Clean doesn't need CMAKE and NDK, so it's handled here if [ "$1" == "clean" ]; then rm -rf $BUILDDIR exit 0 fi if [ -z "$CMAKE" -o -z "$NDK" ]; then usage; fi # CMake wants absolute path CMAKE="$(realpath $CMAKE)" NDK="$(realpath $NDK)" if [ -z "$TYPE" ]; then TYPE="Release" fi if [ -z "$THREADS" ]; then THREADS="4" fi cd "$BASEDIR" case "$1" in armeabi-v7a) APILEVEL=16 ;; arm64-v8a) APILEVEL=21 ;; x86) APILEVEL=16 ;; x86_64) APILEVEL=21 ;; all) echo "Packing server.zip ..." rm -rf Server mkdir -p Server for arch in armeabi-v7a arm64-v8a x86 x86_64; do echo "Doing ... $arch ..." && \ cd $BASEDIR && \ "$SELF" clean && \ "$SELF" "$arch" && \ cd $BUILDDIR/Server && \ zip $BASEDIR/Server/"$arch".zip Cuberite done echo "Packing server.zip ..." cd $BUILDDIR/Server zip -r $BASEDIR/Server/server.zip -@ -x Cuberite < Install/UnixExecutables.list cd $BASEDIR/Server for file in server.zip armeabi-v7a.zip arm64-v8a.zip x86.zip x86_64.zip; do echo "Generating sha1 sum for ... $file ..." && \ sha1sum "$file" > "$file".sha1 done echo "Done! The built zip files await you in the Server/ directory" exit; ;; *) usage; ;; esac mkdir -p "$BUILDDIR" cd "$BUILDDIR" "$CMAKE" "$BASEDIR/../android" -DCMAKE_TOOLCHAIN_FILE="$NDK/build/cmake/android.toolchain.cmake" \ -DANDROID_ABI="$1" \ -DANDROID_NATIVE_API_LEVEL="$APILEVEL" \ -DCMAKE_BUILD_TYPE="$TYPE" \ -DWHOLE_PROGRAM_OPTIMISATION=No make -j "$THREADS" ================================================ FILE: app.yml ================================================ name: Cuberite image: ubuntu-15-04-x64 config: #cloud-config packages: - git runcmd: - cd /tmp && git clone https://github.com/cuberite/cuberite-ocean.git - cd /tmp/cuberite-ocean && ./initialinstall.sh ================================================ FILE: appveyor.yml ================================================ version: 1.0.{build} clone_depth: 50 image: - Visual Studio 2022 branches: only: - master # Set up environment variables for build info environment: CUBERITE_BUILD_SERIES_NAME: AppVeyor CUBERITE_BUILD_ID: "%APPVEYOR_BUILD_NUMBER%" CUBERITE_BUILD_DATETIME: "%APPVEYOR_REPO_COMMIT_TIMESTAMP%" matrix: - job_name: Windows-x64-Debug configuration: Debug BUILD_DIR: Debug x64 - job_name: Windows-x86 configuration: Release BUILD_DIR: Release x86 - job_name: Windows-x64 configuration: Release BUILD_DIR: Release x64 build: project: '%BUILD_DIR%\Cuberite.sln' parallel: true verbosity: minimal pull_requests: do_not_increment_build_number: true install: - git submodule update --init - if not exist "%BUILD_DIR%" mkdir "%BUILD_DIR%" - cd "%BUILD_DIR%" for: ############################## # Windows 64-bit debug build # ############################## - matrix: only: - job_name: Windows-x64-Debug before_build: # TODO: re-add -DSELF_TEST=YES -DBUILD_TOOLS=YES once PCH for tools enabled (too slow otherwise) - cmake -G "Visual Studio 17 2022" -DSELF_TEST=No -DBUILD_TOOLS=No .. ################################ # Windows 32-bit release build # ################################ - matrix: only: - job_name: Windows-x86 before_build: - cmake -G "Visual Studio 17 2022" -A "Win32" .. ################################ # Windows 64-bit release build # ################################ - matrix: only: - job_name: Windows-x64 before_build: - cmake -G "Visual Studio 17 2022" -A "x64" .. ########################################### # Cache for speeding up subsequent builds # ########################################### cache: - '%BUILD_DIR%\CMakeCache.txt' ##################### # Package artifacts # ##################### after_build: - cd Server - Install\PackWindowsExecutables.cmd ================================================ FILE: cibuild.sh ================================================ #!/usr/bin/env bash set -e export CUBERITE_BUILD_SERIES_NAME="CI $CC $CI_CUBERITE_BUILD_TYPE" export CUBERITE_BUILD_ID=$CI_JOB_NUMBER export CUBERITE_BUILD_DATETIME=`date` # Use ccache if available if [ `which ccache` ]; then # Re-run compile on pre-processed sources on cache miss # "It's slower actually, but clang builds fail without it." export CCACHE_CPP2=true # Tell CMake of ccache's existence CACHE_ARGS="-DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache" echo "Using ccache installed at $(which ccache)" ccache --max-size=1G ccache --zero-stats fi workdir="$CC"_"$CI_CUBERITE_BUILD_TYPE" mkdir "$workdir" cd "$workdir" # Work around a Clang + ccache issue with failing builds by disabling # precompiled headers. Turn off LTO for faster build speeds cmake .. -DCMAKE_BUILD_TYPE=${CI_CUBERITE_BUILD_TYPE} \ -DBUILD_TOOLS=Yes \ -DPRECOMPILE_HEADERS=No \ -DSELF_TEST=Yes \ -DUNITY_BUILDS=${CI_CUBERITE_UNITY_BUILDS-Yes} \ -DWHOLE_PROGRAM_OPTIMISATION=No \ ${CACHE_ARGS}; echo "Building..." cmake --build . --parallel 3; if [ `which ccache` ]; then echo "Built with ccache, outputting cache stats..." ccache --show-stats --verbose fi echo "Testing..." ctest --output-on-failure --parallel 2; cd Server/; touch apiCheckFailed.flag if [ "$CI_CUBERITE_BUILD_TYPE" != "COVERAGE" ]; then ./Cuberite <<- EOF load APIDump api apicheck restart stop EOF if [ -f ./NewlyUndocumented.lua ]; then echo "ERROR: Newly undocumented API symbols found:" cat ./NewlyUndocumented.lua exit 1 fi if [ -f ./DuplicateDocs.txt ]; then echo "ERROR: API documentation has duplicate symbol warnings:" cat ./DuplicateDocs.txt exit 1 fi if [ -f ./apiCheckFailed.flag ]; then echo "ERROR: API check has failed with an unknown error" exit 1 fi fi ================================================ FILE: clang-tidy.sh ================================================ #!/bin/sh set -e LOCALSTRING="local" if [ "$3" = "$LOCALSTRING" ]; then REGEX="/cuberite/src/\.?[^\.]" else REGEX="cuberite_[^/\.]+/src/\.?[^\.]" fi FIXES_FILE="tidy-fixes.yaml" ARGS="-header-filter $REGEX -quiet -export-fixes $FIXES_FILE $* $REGEX" # Generate the compilation database mkdir -p tidy-build cd tidy-build # Disable precompiled headers since they aren't generated during linting which causes an error # Disable unity builds since clang-tidy needs the full list of compiled files to check each one cmake --target Cuberite -DCMAKE_EXPORT_COMPILE_COMMANDS=Yes -DPRECOMPILE_HEADERS=No -DUNITY_BUILDS=No .. # Ensure LuaState_Typedefs.inc has been generated (cd ../src/Bindings && lua BindingsProcessor.lua) if run-clang-tidy $ARGS; then echo "clang-tidy: No violations found" else echo "clang-tidy: Found violations" exit 1 fi ================================================ FILE: cloc-exclude.txt ================================================ lib Tools Tests src/Bindings/docs src/Bindings/Bindings.cpp src/Bindings/Bindings.h doxy dev-docs Server Install build ================================================ FILE: compile.sh ================================================ #!/bin/sh #|| goto :windows_detected { # put the whole thing in a block so as not to behave weirdly if interrupted set -e # Global variables: # CHOICE_BUILDTYPE - Either "Release" or "Debug". # CHOICE_THREADS - A numerical value, the amount of threads to be used for the make command. # CHOICE_BRANCH - The branch to use. Currently locked on "master". # STATE_INTERACTIVE - 1 If we're running interactively. 0 otherwise. # STATE_NEW - Whether this is the first run. If 1, then no GIT repo exists yet. 0 otherwise. # Constants: DEFAULT_BUILDTYPE="Release" # Other options: "Debug" DEFAULT_BRANCH="master" # Other options: None currently DEFAULT_THREADS=1 # Constants not modifiable through command line: UPSTREAM_REPO="origin" UPSTREAM_LINK="https://github.com/cuberite/cuberite.git" #=================== Error functions =================== errorCompile () { echo echoInt "-----------------" echo "Compilation failed. Failed command:" echo "$@" exit 1 } errorGit () { echo echoInt "-----------------" echo "Code fetch failed. (Check your network connection). Failed command:" echo "$@" exit 2 } errorDependencies () { # The error messages are complex and OS-dependant, and are printed in the dependencies section before this is called. exit 3 } errorArguments () { echo "Usage: ./compile.sh [options]" echo "Compiles Cuberite. Updates the GIT repository if needed, and downloads it if it does not exist." echo "Runs interactively, unless one or more options are specified." echo echo "options:" echo " -m The compilation mode. Either \"Release\" or \"Debug\". Defaults to \"$DEFAULT_BUILDTYPE\"" echo ' -t The number of threads to use for compiling' echo " If unspecified, a default of $DEFAULT_THREADS threads is used. The special value AUTO attempts to set the number of" echo ' compilation threads equal to the number of CPU threads.' echo ' -b The branch to compile. (Currently unused and pinned to MASTER)' echo ' -n yes: Prevent interactive mode. Unnecessary in combination with other arguments.' echo ' Use without any other argument to build with the default settings.' echo ' -d yes: Dry run. Print the chosen settings and exit' echo echo "Usage examples:" echo " ./compile.sh" echo " ./compile.sh -m Debug" echo " ./compile.sh -m Release -t 2" echo echo "Return codes: (non 0 returns are accompanied by useful stderr info)" echo "0 - Success - Success! Code was updated and compiled" echo "1 - Compilation failed - cmake, make, or source code issue" echo "2 - Code fetch failed - Network issue or, far more rarely, a git issue" echo "3 - Dependencies missing - Some compilation tools are missing" echo "4 - Bad arguments - Bad commandline arguments were passed" echo "5 - Bad user input - Invalid user input in interactive mode" echo "6 - other - An error not listed above" exit 4 } errorInput () { echo echoInt "-----------------" echo "Unrecognized user input" echo "$@" exit 5 } errorOther () { echo echoInt "-----------------" echo "$@" exit 6 } #=================== Echo functions =================== echoInt () # echo only if interactive mode. { if [ $STATE_INTERACTIVE -eq 1 ]; then echo "$1" fi } echoErr () # Echo to stderr. { echo "$1" 1>&2 } #=================== Commandline Parsing =================== STATE_INTERACTIVE=1 # Interactive, unless one or more command line options are passed. while getopts ":m:t:b:d:n:" name; do value=$OPTARG STATE_INTERACTIVE=0 case "$name" in m) if [ ! -z "$CHOICE_BUILDTYPE" ]; then errorArguments; fi # Argument duplication. if [ "$value" = "Debug" ] || [ "$value" = "Release" ]; then CHOICE_BUILDTYPE="$value" else errorArguments fi ;; t) if [ ! -z "$CHOICE_THREADS" ]; then errorArguments; fi # Argument duplication. if [ "$value" -gt 0 ] 2>/dev/null || [ "$value" = "AUTO" ]; then # If a positive integer or the special value "AUTO". CHOICE_THREADS="$value" else errorArguments fi ;; b) if [ ! -z "$CHOICE_BRANCH" ]; then errorArguments; fi # Argument duplication. CHOICE_BRANCH=1 # Only used for dupe checking, overridden below. echoErr "Warning: The -b option is currently unused, it was ignored" ;; d) if [ ! -z "$DRY_RUN" ]; then errorArguments; fi # Argument duplication. DRY_RUN="yes" ;; n) if [ "$dummy" = "1" ]; then errorArguments; fi # Argument duplication. dummy=1 # we just want to disable interactive mode, passing an argument already did this. No need to do anything. ;; *) errorArguments ;; esac done if [ -z "$DRY_RUN" ]; then DRY_RUN="no"; fi #=================== Dependency checks and greeting =================== # Do we already have a repo? checkCuberiteDir () { [ -d .git ] && [ -f easyinstall.sh ] && [ -f src/BlockArea.cpp ] # A good enough indicator that we're in the Cuberite git repo. } STATE_NEW=1 if checkCuberiteDir; then # Check if we're in the Cuberite directory... STATE_NEW=0 elif [ -d cuberite ]; then # If there's a directory named "cuberite"... cd cuberite if checkCuberiteDir; then # Check if we're in the Cuberite directory... STATE_NEW=0 else errorOther "A directory is named 'cuberite' which has no Cuberite assets exists. Please run the script elsewhere or move/delete that directory." fi fi if [ $STATE_NEW -eq 0 ]; then echoInt "Cuberite repository detected. This should make the process faster, especially if you compiled before." fi # Echo: Greetings. echoInt " Hello, this script will download and compile Cuberite. On subsequent runs, it will update Cuberite. The compilation and download will occur in the current directory. If you're updating, you should run: /compile.sh Compiling from source takes time, but it usually generates faster executables. If you prefer ready-to-use binaries or if you want more info, please visit: https://cuberite.org/" doDependencyCheck() { MISSING_PACKAGES="" # Most distros have the following default compiler names. GCC_EXE_NAME="g++" CLANG_EXE_NAME="clang" COMPILER_PACKAGE_NAME="gcc g++" # Most distros have the following package and executable names. # Left side: Executable Name, Right side: Package Name. Note that this is SPACE delimited now, unlike in the past. PROGRAMS='git git make make cmake cmake' # If any OS deviates from the defaults, we detect the OS here, and change PROGRAMS, COMPILER_PACKAGE_NAME, etc. as needed. # Fedora, CentOS, RHEL, Mageia, openSUSE, Mandriva. if (rpm --help > /dev/null 2> /dev/null); then COMPILER_PACKAGE_NAME="gcc-c++" fi # Make sure at least one compiler exists. GCC_EXISTS=0 CLANG_EXISTS=0 $GCC_EXE_NAME --help > /dev/null 2> /dev/null && GCC_EXISTS=1 $CLANG_EXE_NAME --help > /dev/null 2> /dev/null && CLANG_EXISTS=1 if [ "$GCC_EXISTS" -eq 0 ] && [ "$CLANG_EXISTS" -eq 0 ]; then MISSING_PACKAGES=" $COMPILER_PACKAGE_NAME" fi # Depdendency check. checkPackages () { echo "$PROGRAMS" | while read line; do EXE_NAME=`echo "$line" | cut -f 1 -d " "` PACKAGE_NAME=`echo "$line" | cut -f 2 -d " "` command -v $EXE_NAME > /dev/null 2> /dev/null || printf %s " $PACKAGE_NAME" done } MISSING_PACKAGES="$MISSING_PACKAGES`checkPackages`" missingDepsExit () { if [ "$1" != "" ]; then echoErr "You can install the missing depndencies via:" echoErr "$1" fi echoErr echoErr "Please install the dependencies, then come back." echoErr errorDependencies } if [ "$MISSING_PACKAGES" != "" ]; then echoInt echoInt "-----------------" echoErr "You have missing compilation dependencies:" echoErr $MISSING_PACKAGES echoErr # apt-get guide. apt-get --help > /dev/null 2> /dev/null && \ missingDepsExit "apt-get install$MISSING_PACKAGES" # dnf guide. dnf --help > /dev/null 2> /dev/null && \ missingDepsExit "dnf install$MISSING_PACKAGES" # zypper guide. zypper --help > /dev/null 2> /dev/null && \ missingDepsExit "zypper install$MISSING_PACKAGES" # pacman guide. pacman --help > /dev/null 2> /dev/null && \ missingDepsExit "pacman -S$MISSING_PACKAGES" # urpmi guide. urpmi --help > /dev/null 2> /dev/null && \ missingDepsExit "urpmi$MISSING_PACKAGES" missingDepsExit "" fi } doDependencyCheck #=================== Choice: Branch (Currently unused and simply skipped) =================== # Bypass Branch choice and choose master. Because it's the only branch right now. CHOICE_BRANCH=$DEFAULT_BRANCH ### Inactive code start. ### inactiveCode () { echo " You can choose between 3 branches: * (S)Stable: Choose the stable branch if you want the most reliable server. * (T)Testing: The testing branch is less stable, but using it and reporting bugs helps us a lot! * (D)Dev: The least stable of the three. (Master branch) Choose the development branch if you want to try new, bleeding-edge features. " printf %s "Choose the branch (s/t/d): " read CHOICE_BRANCH case $CHOICE_BRANCH in s|S) errorOther "We don't have a stable branch yet, please use testing, sorry." ;; t|T) CHOICE_BRANCH="testing" ;; d|D) CHOICE_BRANCH="master" ;; *) errorInput ;; esac } ### Inactive code end. ### #=================== Choice: Compile mode =================== if [ $STATE_INTERACTIVE -eq 1 ]; then echo " Choose compile mode: * (R)Release: Compiles normally. Generates the fastest build. * (D)Debug: Compiles in debug mode. Makes your console and crashes more verbose. A bit slower than Release mode. If you plan to help development by reporting bugs, this is preferred. " printf %s "Choose compile mode: (r/d) (Default: \"$DEFAULT_BUILDTYPE\"): " read CHOICE_BUILDTYPE case $CHOICE_BUILDTYPE in d|D) CHOICE_BUILDTYPE="Debug" ;; r|N) CHOICE_BUILDTYPE="Release" ;; esac fi if [ -z "$CHOICE_BUILDTYPE" ]; then # No buildtype specified. CHOICE_BUILDTYPE="$DEFAULT_BUILDTYPE" fi #=================== Choice: Thread amount =================== numberOfThreads() { KERNEL=`uname -s` if [ "$KERNEL" = "Linux" ] || [ "$KERNEL" = "Darwin" ]; then echo `getconf _NPROCESSORS_ONLN` elif [ "$KERNEL" = "FreeBSD" ]; then echo `getconf NPROCESSORS_ONLN` else echo "unknown" fi } CPU_THREAD_COUNT=`numberOfThreads` if [ $STATE_INTERACTIVE -eq 1 ]; then echo "" echo "Choose the number of compilation threads." if [ "$CPU_THREAD_COUNT" = "unknown" ]; then echo "Could not detect the number of CPU threads." elif [ "$CPU_THREAD_COUNT" -eq 1 ]; then echo "You have 1 thread." else echo "You have $CPU_THREAD_COUNT CPU threads." fi echo "If you have enough RAM, it is wise to choose your CPU's thread count. " echo "Otherwise choose lower. Old Raspberry Pis should choose 1. If in doubt, choose 1." printf %s "Please enter the number of compilation threads to use (Default: $DEFAULT_THREADS): " read CHOICE_THREADS fi if [ -z "$CHOICE_THREADS" ] 2> /dev/null; then CHOICE_THREADS="$DEFAULT_THREADS" elif [ "$CHOICE_THREADS" = "AUTO" ] 2> /dev/null; then if [ $CPU_THREAD_COUNT = "unknown" ]; then CHOICE_THREADS="$DEFAULT_THREADS" echo "WARNING: could not detect number of threads. Using the default ($DEFAULT_THREADS) ." >&2 else CHOICE_THREADS="$CPU_THREAD_COUNT" fi elif [ "$CHOICE_THREADS" -lt 0 ] 2> /dev/null; then errorInput fi #=================== Print settings summary =================== if [ "$STATE_NEW" = 1 ]; then previousCompilation="Not detected. We are assuming this is the first compile.sh run." else previousCompilation="Detected. This should make fetching and compiling faster." fi THREAD_WARNING="" if [ "$CPU_THREAD_COUNT" != "unknown" ] && [ "$CPU_THREAD_COUNT" -lt "$CHOICE_THREADS" ]; then THREAD_WARNING=" - Warning: More threads assigned than there are CPU threads." fi echo "" echoInt "#### Settings Summary ####" echo "Build Type: " "$CHOICE_BUILDTYPE" echo "Branch: " "$CHOICE_BRANCH" "(Currently the only choice)" echo "Compilation threads: " "$CHOICE_THREADS$THREAD_WARNING" echo "CPU Threads: " "$CPU_THREAD_COUNT" echo "Previous compilation: " "$previousCompilation" echo "Upstream Link: " "$UPSTREAM_LINK" echo "Upstream Repo: " "$UPSTREAM_REPO" if [ "$DRY_RUN" = "yes" ]; then echo "This is a dry run. Exiting now." exit 0; fi # Ask the user's permission to connect to the net. if [ $STATE_INTERACTIVE -eq 1 ]; then echo echo "After pressing ENTER, the script will connect to $UPSTREAM_LINK" echo "to check for updates and/or fetch code. It will then compile your program." echo "If you compiled before, make sure you're in the proper directory and that \"Previous compilation\" is detected." printf $s "Press ENTER to continue... " read dummy fi #=================== Code download / update via git =================== echoInt echoInt " --- Downloading Cuberite's source code from the $CHOICE_BRANCH branch..." if [ $STATE_NEW -eq 1 ]; then # Git: Clone. echo " --- Looks like your first run, cloning the whole code..." git clone --depth 1 "$UPSTREAM_LINK" -b "$CHOICE_BRANCH" || errorGit "git clone --depth 1 $UPSTREAM_LINK -b $CHOICE_BRANCH" cd cuberite else # Git: Fetch. echo " --- Updating the $CHOICE_BRANCH branch..." git fetch "$UPSTREAM_REPO" "$CHOICE_BRANCH" || errorGit "git fetch $UPSTREAM_REPO $CHOICE_BRANCH" git checkout "$CHOICE_BRANCH" || errorGit "git checkout $CHOICE_BRANCH" git merge "$UPSTREAM_REPO"/"$CHOICE_BRANCH" || errorGit "git merge $UPSTREAM_REPO/$CHOICE_BRANCH" fi # Git: Submodules. echo " --- Updating submodules..." git submodule sync git submodule update --init #=================== Compilation via cmake and make =================== # Cmake. echo " --- Running cmake..." if [ ! -d build-cuberite ]; then mkdir build-cuberite; fi cd build-cuberite cmake .. -DCMAKE_BUILD_TYPE="$CHOICE_BUILDTYPE" || errorCompile "cmake .. -DCMAKE_BUILD_TYPE=$CHOICE_BUILDTYPE" # Make. echo " --- Compiling..." make -j "$CHOICE_THREADS" || errorCompile "make -j $CHOICE_THREADS" echo #=================== Print success message =================== cd Server echo echo "-----------------" echo "Compilation done!" echo echo "Cuberite awaits you at:" echo "$PWD/Cuberite" cd ../.. echo " You can always update Cuberite by executing: $PWD/compile.sh Enjoy :)" exit 0 #=================== Windows fallback =================== # Called via hack in line 2. :windows_detected @echo off cls echo This script is not available for Windows yet, sorry. echo You can still download the Windows binaries from: https://cuberite.org/ echo You can also manually compile for Windows. See: https://github.com/cuberite/cuberite rem windows_exit goto :EOF } ================================================ FILE: dev-docs/.gitignore ================================================ # PNG file with no filename is created by the GraphViz's GVEdit when displaying .gv files .png # The PNG files generated from their .gv sources by GraphViz: API class inheritance - blockentities.png API class inheritance - entities.png SocketThreads states.png ================================================ FILE: dev-docs/API class inheritance - blockentities.gv ================================================ digraph { rankdir=LR cBlockEntity -> cBlockEntityWithItems cBlockEntity -> cJukeboxEntity cBlockEntity -> cNoteEntity cBlockEntity -> cSignEntity cBlockEntityWithItems -> cChestEntity cBlockEntityWithItems -> cDropSpenserEntity cBlockEntityWithItems -> cFurnaceEntity cBlockEntityWithItems -> cHopperEntity cDropSpenserEntity -> cDropperEntity cDropSpenserEntity -> cDispenserEntity } ================================================ FILE: dev-docs/API class inheritance - entities.gv ================================================ digraph { rankdir=LR # Entities: cEntity -> cFallingBlock cEntity -> cMinecart cEntity -> cPawn cEntity -> cPickup cEntity -> cTNT cMinecart -> cEmptyMinecart cMinecart -> cMinecartWithChest cMinecart -> cMinecartWithFurnace # Mobs: cPawn -> cMonster cMonster -> cAggressiveMonster cMonster -> cPassiveMonster cAggressiveMonster -> cPassiveAggressiveMonster cPassiveMonster -> cBat cAggressiveMonster -> cBlaze cAggressiveMonster -> cCaveSpider cPassiveMonster -> cChicken cPassiveMonster -> cCow cAggressiveMonster -> cCreeper cPassiveAggressiveMonster -> cEnderman cAggressiveMonster -> cGhast cAggressiveMonster -> cMagmaCube cPassiveMonster -> cMooshroom cPassiveMonster -> cOcelot cPassiveMonster -> cPig cPassiveMonster -> cSheep cAggressiveMonster -> cSilverfish cAggressiveMonster -> cSkeleton cAggressiveMonster -> cSlime cAggressiveMonster -> cSpider cPassiveMonster -> cSquid cPassiveMonster -> cVillager cAggressiveMonster -> cWitch cPassiveAggressiveMonster -> cWolf cAggressiveMonster -> cZombie cPassiveAggressiveMonster -> cZombiePigman cPawn -> cPlayer } ================================================ FILE: dev-docs/Cubeset file format.html ================================================ Cubeset file format

    Contents


    Abstract - what and why

    We're seeing an increased need to store "prefabs" - little areas with predefined block contents, such as village houses or fortress rooms - in collections. We have one collection of village houses for the plains village, one collection for the desert village, one collection for the nether fortress... And there are plans in the future to use even more collections - trees, overworld fortresses, more village types and even custom structures. The point that they have in common is that they need to store not only the prefabs, but also metadata for those prefabs - how often they generate, how they connect together. There's even need for metadata for the entire collection, such as what the accepted biomes are, what block should village roads use, and various other generator parameters. So we need a file format that could store all this information together.

    There are some existing formats available to consider first:

    • schematic - file format native to MCEdit / Bukkit / WorldEdit communities. Can store the prefab, the block entities and regular entities, and any metadata. Cannot store multiple prefabs. No effort to read or write, there's already code to do that (except for the entities) in the server.
    • bob / bo2 / bo3 - file format created for prefabs in the Terrain Control mod. Can store the prefab and any metadata. Support for block entities and regular entities is unknown. Cannot store multiple prefabs. Medium difficulty for reading and writing, would need new parser and serializer. Unknown (but assumed true) whether the format truly supports any metadata.
    • cpp - export from our Gallery server directly into C++ source files. Can store the prefab and any metadata, block entities and regular entities currently not implemented but could be added. Very difficult for reading, writing already implemented. Only usable when compiling directly into the server. Can store multiple prefabs and metadata for the entire set.
    Obviously none of these fully satisfy our needs, so we'll need to either extend one of them or create yet another one. Extending the .schematic file would mean that the exporter plugin would need to change most of the export code, which was deemed too unmaintainable. Because the bob format is not implemented at all, it wasn't even considered. The cpp format would have been a great candidate if it weren't so difficult to parse. However, it sparked an idea - something similar in form to the cpp format, but easily parsed. Since we already have the Lua interpreter, why not base the new format in Lua?

    With Lua, we could store any metadata for the prefabs, any additional information related to the entire set of prefabs. There's nothing stopping us from adding more items in a backward- and forward-compatible way. The prefabs can be stored very similar to the cpp format, an array of strings plus a charmap, or they can be stored externally in individual .schematic files and the Lua file would provide just the metadata. The server has already vast amounts of Lua-related support code that can be used for accessing the data. In the end this became the chosen solution. The format has been named "Cubeset" - a set of cube-based prefabs.


    Detailed description of the format

    The Cubeset file has a .cubeset extension. Internally it is a Lua source file that provides a global value, Cubeset, which is a table containing the structured data. The loader checks the file's first 8 KiB to see if there is a "CubesetFormatVersion =" string in it (note the space between the word and the equals-sign), and if it is, the file is considered a Cubeset file and further loading is attempted. It is therefore crucial that tools producing this file format include this string as early as possible in the file.

    The top-level Cubeset table must contain at least two sub-tables: Metadata and Pieces. The Metadata table contains the metadata relevant to the entire set of prefabs in the file, the Pieces table contains the definitions and metadata for the individual prefabs. It is advised to make the Metadata table the first one, because it contains the signature used to identify the file ("CubesetFormatVersion ="). Apart from these two subtables the server ignores everything else.

    Cubeset metadata

    The Cubeset.Metadata table is used to store metadata for the entire set of prefabs, and also for the format and version identification. It is a regular dictionary-style Lua table; the following elements are recognized:
    NameTypeContent
    CubesetFormatVersionnumberThis is the format identification and at the same time it specifies the version of the file. Currently the file version is 1. Note that Cuberite checks the presence of the string "CubesetFormatVersion =", including the space between the word and the equals-sign, within the first 8 KiB of the file.
    ExportDatestringThe date when this file was exported, in the ISO format ("2015-06-16 13:34:03"). Inserted by GalExport for versioning purposes. Ignored elsewhere.
    ExternalSchematicbooleanFlag inserted by GalExport to indicate that the individual prefabs are stored in separate .schematic files. Ignored elsewhere.
    IntendedUsestringString identifying the generator part that the cubeset file is intended for. The server logs a warning when loading a cubeset file without an IntendedUse metadata; individual generators log a warning if a wrong IntendedUse is detected in a file they are asked to use.

    Additional values are recognized by the specific generator (which is indicated by the IntendedUse value):

    Generator (IntendedUse)NameTypeContentNotes
    Village / PieceStructures / TreesAllowedBiomesstringComma-separated list of biomesThe generator only generates the structure / village / tree in the specified biomes. If empty, all biomes are eligible.
    VillageMaxDensitynumberMaximum density (0 - 100) at which the connectors are populated.The village generator picks a density between Min and Max, and then only that many percent of the free connectors are actually attempted. This eventually reduces the number of houses to make the village look more "roomy".
    MinDensitynumberMinimum density (0 - 100) at which the connectors are populated.
    VillageRoadBlockTypenumberThe block type used in the village for regular roads on the solid surfaceThe generator replaces the top terrain block with the specified block type and meta to form the roads. The generator can distinguish when it's replacing water and when it's replacing regular terrain, allowing the villages to include "bridges" as their roads.
    VillageRoadBlockMetanumberThe block meta used in the village for regular roads on the solid surface
    VillageWaterRoadBlockTypenumberThe block type used in the village for roads on the surface of water
    VillageWaterRoadBlockMetanumberThe block meta used in the village for roads on the surface of water
    PieceStructuresGridSizeXnumberSize, in blocks, of the seed gridThe generator starts each generated structure in a "seed", these two parameters control the (average) distances between two adjacent seeds.
    GridSizeZnumber
    MaxOffsetXnumberMaximum offset, in blocks, of the seed from the grid's centerThe generator starts each generated structure in a "seed", these two parameters control the maximum distance of the seed from the regular grid (specified by GridSizeX and GridSizeZ). When zero, the structures are generated exactly on a rectangular grid. Recommended value is about half of the grid's size.
    MaxOffsetZnumber
    MaxStructureSizeXnumberSize, in blocks, of the bounding box for a single structure.The generator will not connect any prefab to the rest of the structure if it crosses the bounding box.
    MaxStructureSizeZnumber
    MaxDepthnumberMaximum depth of the generated piece treeThe maximum number of connectors, away from the starting piece
    SeedOffsetnumberNumber that is added to world's seed for this generatorEach cubeset file should have a different seed offset, otherwise it runs the risk of its structures being generated directly over other cubeset file's that the server admin has enabled. Since the seed is used for placement, if two cubeset files share the same seed, they will share the structure placement as well.

    Individual piece

    The Cubeset.Pieces table is an array containing individual prefabs. Each element describes a single prefab and its associated metadata. The following values are recognized:
    NameTypeContent
    OriginDatatableInserted by GalExport to identify the gallery area from which the prefab is exported. Ignored elsewhere.
    HitboxtableThe relative coords of the prefab's hitbox (where the prefab is not allowed to overlap another prefab when generating). Members: MinX, MinY, MinZ, MaxX, MaxY, MaxZ, all numbers.
    ConnectorstableArray of connector definitions. The table must be present for each prefab, even if the prefab doesn't have any connectors (use an empty table, then).
    SchematicFileNamestringName of the .schematic file that contains the block data for the prefab.
    SizetableTable containing the dimensions of the prefab, if it is inlined into the BlockData element. Contains three members, x, y, z, each is a number.
    BlockDatatableArray of strings that are processed to produce the block data for the prefab. Each letter in the string corresponds to one block, the type of the block is translated through the BlockDefinitions table. The blocks are ordered YZX, that is, the X coord varies the most.
    BlockDefinitionstableArray of strings that defines the mapping of each letter in BlockData to a specific blocktype. Each string should have the format "Letter: BlockType: BlockMeta".
    MetadatatableDictionary-style table of various per-prefab metadata values.
    The prefab can either have the SchematicFileName element, in which case the specified schematic file is loaded as the block data, or it can have the Size, BlockData and BlockDefinitions elements, then the server parses the block data from those. If both data members are included, the SchematicFileName takes precedence and the server loads the data from the schematic file (note that this behavior may change, having both definitions is considered "undefined behavior").

    The connector definitions table is an array of tables, each element describing one connector. The following values are recognized:
    NametypeContent
    TypenumberThe connector's type. The piece generator will only connect the connectors of inverse types ('1'-type connector will connect only to '-1'-type connector).
    RelXnumberX coord of the connector, relative to the prefab's zero point ({0, 0, 0} - the first block in the image).
    RelYnumberY coord of the connector, relative to the prefab's zero point ({0, 0, 0} - the first block in the image).
    RelZnumberZ coord of the connector, relative to the prefab's zero point ({0, 0, 0} - the first block in the image).
    DirectionnumberThe direction in which the connector is facing. Corresponds to the eBlockFace constants:
    ValueDirection
    0Y-
    1Y+
    2Z-
    3Z+
    4X-
    5X+
    If a connector definition is missing any of the fields, the server will not add the connector to the prefab upon loading. If a prefab doesn't have any connectors, it still needs to provide an empty Connectors table.

    Piece metadata

    Each piece contains additional metadata describing its properties. The server ignores metadata that it doesn't understand. The following values are recognized:
    NameTypeIsRequiredContents
    IsStartingnumberYesZero means that the piece is a regular piece, nonzero means that the piece is a starting piece (the "seed" of the structure). Required even for cubesets that don't represent a piece-generator data (such as trees).
    AllowedRotationsnumber Number representing a bitmask for which rotations the piece supports. Defaults to 0 (no rotations). Bit 0 (value 1) represents whether 1 counter-clockwise rotation is allowed, bit 1 (value 2) represents whether 2 rotations (180 degrees) are allowed, bit 2 (value 4) represents whether 1 clockwise rotation is allowed.
    AddWeightIfSamenumber How much weight (chance to generate) should the piece generator add to this piece when the parent piece is the same. It is possible to have negative values, meaning that the piece doesn't like repeating itself. Defaults to 0.
    DefaultWeightnumber How much weight (chance to generate) does the piece have by default, without any modifiers (AddWeightIfSame, DepthWeight). Defaults to 0.
    DepthWeightstring Override for DefaultWeight for specific depth (in the tree used by the piece generator). String in the format "Depth1:Weight1|Depth2:Weight2|...". Each unlisted depth gets the DefaultWeight. Defaults to empty string (no override).
    MergeStrategystring Which merge strategy should be used when drawing the prefab into the world. String representation of one of the cBlockArea:eMergeStrategy constants: "msOverwrite", "msFillAir", "msImprint", "msLake", "msSpongePrint", "msDifference", "msSimpleCompare", "msMask". Defaults to "msSpongePrint".
    MoveToGroundnumber Zero means that the piece will stay where generated by the piece generator, nonzero means that the piece will be moved Y-wise so that its first connector will be on the top block of the existing terrain. Useful for village houses. Defaults to 0.
    ShouldExpandFloornumber Nonzero means that the prefab's lowest slice will be repeated downwards until it hits a solid block, effectively creating a foundation for the piece. Useful for nether fortresses and village houses. Defaults to 0.
    Each value that should be a number also allows a string that represents a number. This makes it easier for automated exporters - they can export all values as strings.


    Example

    The following example defines a cubeset with two pieces. The first piece is inlined into the cubeset file, the second piece uses an external schematic file.

    Cubeset =
    {
    	Metadata =
    	{
    		CubesetFormatVersion = 1,
    		IntendedUse = "PieceStructures",
    		GridSizeX = 128,
    		GridSizeZ = 128,
    		MaxStructureSizeX = 64,
    		MaxStructureSizeZ = 64,
    		MaxOffsetX = 16,
    		MaxOffsetZ = 16,
    		MaxDepth = 4,
    		SeedOffset = 13,
    	},
    
    	Pieces =
    	{
    		-- The following piece was exported from the Gallery server by the GalExport plugin in the "cubeset" format:
    		{
    			OriginData =
    			{
    				ExportName   = "DarkCorridor",
    				Name         = "Nether 3",
    				GalleryName  = "Nether",
    				GalleryIndex = "3",
    				ID           = "30",
    				CreatorName  = "STR_Warrior",
    			},
    			Size =
    			{
    				x = 14,
    				y = 6,
    				z = 5,
    			},
    			Hitbox =
    			{
    				MinX = 0,
    				MinY = 0,
    				MinZ = 0,
    				MaxX = 13,
    				MaxY = 5,
    				MaxZ = 4,
    			},
    			Connectors =
    			{
    				{
    					Type = 1,
    					RelX = 0,
    					RelY = 1,
    					RelZ = 2,
    					Direction = 4,  -- X-
    				},
    				{
    					Type = 1,
    					RelX = 13,
    					RelY = 1,
    					RelZ = 2,
    					Direction = 5,  -- X+
    				},
    				{
    					Type = -1,
    					RelX = 0,
    					RelY = 1,
    					RelZ = 2,
    					Direction = 4,  -- X-
    				},
    				{
    					Type = -1,
    					RelX = 13,
    					RelY = 1,
    					RelZ = 2,
    					Direction = 5,  -- X+
    				},
    			},
    			Metadata =
    			{
    				["DefaultWeight"] = "100",
    				["IsStarting"] = "0",
    				["AllowedRotations"] = "7",
    				["MergeStrategy"] = "msSpongePrint",
    				["DepthWeight"] = "",
    				["ShouldExpandFloor"] = "1",
    				["MoveToGround"] = "0",
    				["AddWeightIfSame"] = "0",
    			},
    			BlockDefinitions =
    			{
    				".:  0: 0",  -- air
    				"a:112: 0",  -- netherbrick
    				"b:113: 0",  -- netherbrickfence
    				"c:114: 2",  -- netherbrickstairs
    				"d:114: 3",  -- netherbrickstairs
    				"m: 19: 0",  -- sponge
    			},
    			BlockData =
    			{
    				-- Level 0
    				"aaaaaaaaaaaaaa",  --  0
    				"aaaaaaaaaaaaaa",  --  1
    				"aaaaaaaaaaaaaa",  --  2
    				"aaaaaaaaaaaaaa",  --  3
    				"aaaaaaaaaaaaaa",  --  4
    
    				-- Level 1
    				"aaaaaaaaaaaaaa",  --  0
    				"..............",  --  1
    				"..............",  --  2
    				"..............",  --  3
    				"aaaaaaaaaaaaaa",  --  4
    
    				-- Level 2
    				"aabaaaaaaaabaa",  --  0
    				"..............",  --  1
    				"..............",  --  2
    				"..............",  --  3
    				"aabaaaaaaaabaa",  --  4
    
    				-- Level 3
    				"aabaaaaaaaabaa",  --  0
    				"..............",  --  1
    				"..............",  --  2
    				"..............",  --  3
    				"aabaaaaaaaabaa",  --  4
    
    				-- Level 4
    				"aabaaaaaaaabaa",  --  0
    				"..............",  --  1
    				"..............",  --  2
    				"..............",  --  3
    				"aabaaaaaaaabaa",  --  4
    
    				-- Level 5
    				"cccccccccccccc",  --  0
    				"aaaaaaaaaaaaaa",  --  1
    				"aaaaaaaaaaaaaa",  --  2
    				"aaaaaaaaaaaaaa",  --  3
    				"dddddddddddddd",  --  4
    			},
    		},  -- DarkCorridor
    
    		-- The following piece was exported from the Gallery server by the GalExport plugin in the "cubesetext" format:
    		{
    			OriginData =
    			{
    				ExportName   = "DoublePlantBed",
    				Name         = "Plains 5",
    				GalleryName  = "Plains",
    				GalleryIndex = "5",
    				ID           = "20",
    				CreatorName  = "tonibm1999",
    			},
    			Size =
    			{
    				x = 15,
    				y = 8,
    				z = 9,
    			},
    			Hitbox =
    			{
    				MinX = 0,
    				MinY = 0,
    				MinZ = 0,
    				MaxX = 14,
    				MaxY = 7,
    				MaxZ = 8,
    			},
    			Connectors =
    			{
    				{
    					Type = -1,
    					RelX = 7,
    					RelY = 2,
    					RelZ = 8,
    					Direction = 3,  -- Z+
    				},
    			},
    			Metadata =
    			{
    				["DefaultWeight"] = "100",
    				["IsStarting"] = "0",
    				["AllowedRotations"] = "7",
    				["MergeStrategy"] = "msSpongePrint",
    				["DepthWeight"] = "",
    				["ShouldExpandFloor"] = "1",
    				["MoveToGround"] = "1",
    				["AddWeightIfSame"] = "0",
    			},
    			SchematicFile = "PlainsVillage/20.schematic",
    		},  -- DoublePlantBed
    	}  -- Pieces
    }
    
    ================================================ FILE: dev-docs/ExportingAPI.html ================================================ Cuberite - Exporting symbols from C++ to Lua API

    Exporting symbols from C++ to Lua API

    Cuberite has a powerful plugin system which makes available hundreds of functions, variables and constants (symbols). When adding or removing functionality, these need to be taken into account - do we want to make this function available to the plugins? Did we remove a function that plugins could have used in the past?

    The API maintenance is pretty straightforward once you figure out how to do it. This text will guide you through the process.


    Introduction to ToLua++

    Cuberite uses ToLua++ for handling bindings. Unfortunately this tool is no longer maintained, so we had to hack it ourselves whenever we needed a specific feature that it didn't support. Luckily, it turns out ToLua++ is greatly extensible and can quite easily be made to do our bidding.

    This tool consists of a Lua script to parse C++ code and generate the glue code, and a runtime library providing support for the generated code. The C++ code parser doesn't implement full C++ syntax, just a reasonable subset that most if not all source files can be made to fit. Since it parses the C++ code using Lua patterns, it is only expected that some wild corner cases will confuse the parser. Therefore, all files that are to be processed by the parser need to be written in a simple subset of C++.

    Once run, the tool generates a giant C++ source code file, src/Bindings/Bindings.cpp, which implements all the glue code needed for Lua plugins to interface with the C++ code.

    Auto-export

    The simplest way to export a symbol is to mark it for exporting and let ToLua++ do all the work. Basically, when ToLua++ parses files, it ignores everything that is not in between special comments, // tolua_begin and // tolua_end . There's a special comment, // tolua_export , that says "consider this single line". So adding new symbols in between existing tolua_begin / tolua_end comment pair, or marking them with tolua_export, is the simplest way to export them. However, since ToLua++ is limited, this works only for simple things: variables, constants and (overloaded) (member) functions, all of which must use only numbers, strings or enums or classes known to ToLua++. Note that this means that arrays, vectors, lists and callbacks are not supported by this simple export, all of those need to be exported manually. Based on experience, about 90 % of API functions can be exported this way.

    The following piece of code shows how to export a class with some of its functions:

    // tolua_begin
    class ExportedClass
    {
    public:
    	// tolua_end
    
    	ExportedClass();  // NOT exported
    	void notExported();
    	void exported(int a_Param1);  // tolua_export
    	void anotherNotExported();
    
    	// tolua_begin
    
    	void exported(int a_Param1, int a_Param2);  // Note that overloads are supported
    	void anotherExported(const AString & a_Text);
    };
    // tolua_end
    

    From this input, the ToLua++ sees the following "preprocessed" code, for which it will generate the bindings:

    class ExportedClass
    {
    public:
    	void exported(int a_Param1);
    	void exported(int a_Param1, int a_Param2);
    	void anotherExported(const AString & a_Text);
    };
    

    Manual export

    First, a quick primer on binding Lua in general. You can have a look at the Lua manual for details, since this is only a summary.

    Lua uses a concept of stack. It keeps a stack through the lifetime of program, and calling a function means that under the hood the parameters are first pushed onto the stack, then the function implementation is called, it can read the values on the stack and it can push return values onto the same stack, and when it returns, Lua reads the return values from the top of that stack. This allows Lua to have functions that take a variable amount of parameters, return any number of values, and all of these parameters / values can be of any Lua-supported type. If you consider the datatype a "variant", it's good enough.

    The signature for a function call, therefore, is simple - it takes an opaque pointer to a Lua engine (struct lua_State *), and it returns a single number that specifies how many return values there are on the stack. In C/C++ terms:

    static int fnImplementation(lua_State * a_LuaState)
    {
    	// ...
    
    	// Push return values onto the stack
    
    	return numReturnValues;
    }
    

    Although it is referred to as The Stack, it can be manipulated in any way - a value can be read from any position, and it supports insertion to and deletion from any position.

    A typical API function should do these actions:

    • Check that parameter types are correct
    • Read the parameter values
    • Execute the C++ function
    • Publish any return values

    Cuberite wraps the lua_State pointer into a nice interface, cLuaState, that (among other things) provides easy functions for interfacing with Lua. Checking parameter types is done using the cLuaState::CheckParam...() family of functions. Each of these functions checks the type of the specified parameter / parameter range, returns true if the parameters are okay, or logs an error message to console and returns false if they aren't. Note that this is not usable for overloaded functions, they need to use tolua_is...() functions for checking.

    Example code doing the parameter check:

    static int tolua_cRoot_DoWithPlayerByUUID(lua_State * tolua_S)
    {
    	// Function signature: cRoot:DoWithPlayerByUUID(cUUID, function)
    
    	// Check params:
    	cLuaState L(tolua_S);
    	if (
    		!L.CheckParamSelf("cRoot") ||
    		!L.CheckParamUUID(2) ||
    		!L.CheckParamFunction(3) ||
    		!L.CheckParamEnd(4)
    	)
    	{
    		return 0;
    	}
    

    This code checks that the API function is called on a cRoot instance (first hidden parameter) and has a UUID and a callback function as its parameters. It also checks that there are no more parameters on the stack.

    Reading the parameter values is rather simple: Declare variables to hold the parameter values, then use cLuaState::GetStackValues() to read them all at once. This function will return true if successful, false on an error. The return value should be checked even if parameter types were correct, because a failure can be due to other means as well - the number in Lua might be too large to fit the C++ datatype, or the enum value is out of range. Note that GetStackValues() doesn't report which parameter failed, so it should not be used for reporting problems to the user (plugin dev).

    The following example is a continuation of the previous example function that reads the parameters into local variables:

    	// Get parameters:
    	cRoot * Self;
    	cUUID PlayerUUID;
    	cLuaState::cRef FnRef;  // Holds a Lua function (callback)
    	L.GetStackValues(1, Self, PlayerUUID, FnRef);
    
    	// Check parameters validity:
    	if (PlayerUUID.IsNil())
    	{
    		return L.ApiParamError("Expected a non-nil UUID for parameter #1");
    	}
    	if (!FnRef.IsValid())
    	{
    		return L.ApiParamError("Expected a valid callback function for parameter #2");
    	}
    

    After executing the C++ function, if there are any return values, they should be pushed onto the Lua stack using the cLuaState::Push() function, and finally the returned number should indicate the number of return values. Note that it is up to you to keep the stack counts. If your code pushes more values onto the stack than it reports as return values, it will cause a memory leak.

    The following example contains the rest of the previous example function, it executes the C++ code and gives the return value back to Lua:

    	// Call the function:
    	bool res = Self->DoWithPlayerByUUID(PlayerUUID, [&](cPlayer & a_Player)
    		{
    			bool ret = false;
    			L.Call(FnRef, &a_Player, cLuaState::Return, ret);
    			return ret;
    		}
    	);
    
    	// Push the result as the return value:
    	L.Push(res);
    	return 1;
    }
    

    The manual API function export glue should be written into one of src/Bindings/ManualBindings*.cpp files, based on the group it belongs to (or into src/Bindings/DeprecatedBindings.cpp if it is an obsolete function, see the Removing a symbol chapter). There are a lot of examples already in those files. Note that there was some development in the process of writing manual bindings, and some of the manual bindings use old code. Do not copy code that makes use of tolua_Error struct, or tolua_push...() or tolua_to...() functions.

    Finally, after writing the API function, it needs to be registered ("bound" in our terminology). Each of the CPP files has a cManualBindings::Bind...() function at the bottom for this purpose. The function first registers classes (tolua_usertype(), tolua_cclass()) and then fills each class with manually-exported functions. A call to tolua_beginmodule() signifies start of class, tolua_endmodule() ends the class. In between, calls to tolua_function() register the API functions. It is good practice to keep the classes and the sybmols within classes alpha-sorted and tabulated.

    The following code is an example of binding our previous example function:

    	tolua_beginmodule(tolua_S, "cRoot");
    		// ...
    		tolua_function(tolua_S, "DoWithPlayerByUUID",  tolua_cRoot_DoWithPlayerByUUID);
    		// ...
    	tolua_endmodule(tolua_S);
    

    Cuberite conventions

    Specifically for Cuberite, we've built some conventions over the years. They are in place for good reasons - to make the API well documented, somewhat stable and reasonably fool-proof

    New symbols

    When adding a new symbol to the API, there's no version number to bump up to indicate this. Plugins can simply check the symbol's existence in the runtime, if they wish to do so. However, it is necessary to properly document the symbol, so that the automatically-generated documentation stays up to date.

    The API documentation is handled by the APIDump plugin, contained in the main repository in the Server/Plugins/APIDump folder. It can automatically generate the HTML API documentation locally, based on the actual API that it detects Cuberite is giving it, and joins it with developer-provided per-symbol descriptions. Most of the description is in the Server/Plugins/APIDump/APIDesc.lua file, but some well-defined groups of symbols have been pulled out into separate files in the Server/Plugins/APIDump/Classes folder and Server/Plugins/APIDump/Hooks folder. The format of the files is pretty self-explanatory - they each return a Lua table containing the descriptions, organized in sub-tables.

    To generate the documentation locally, start up Cuberite, load the APIDump plugin (if not already enabled) and execute the "api" command. It will create an API subfolder next to the Cuberite executable and write the HTML files into it.

    The APIDump plugin can also check the difference between official documentation and local documentation, and can report if any symbol is new locally, without proper description. Execute the "apicheck" command to do that; note that this requires "wget" to be installed, since the official API description needs to be downloaded from the Internet. This command is used as part of Cuberite CI builds to detect any forgotten API description.

    Removing a symbol

    To keep the API from changing too much under plugin devs' hands, the recommendation is not to remove API symbols, but rather mark them as obsolete, while keeping the functionality (possibly emulating it through a new API, if the old symbol was replaced with a new way of doing things). The preffered way is to export the old symbol mnually in a specific file, src/Bindings/DeprecatedBindings.cpp, and add a warning message to the function implementation, together with the Lua stacktrace, to aid plugin authors with the migration. It is always a good idea to add a hint as to what the developers should use instead ("Warning in function call 'StringToMobType': StringToMobType() is deprecated. Please use cMonster:StringToMobType()").

    After a reasonable amount of time (typically, on the order of a year) the removed symbol can be considered unused and will be removed from the API. Usually this happens in batches as a cleanup of the codebase.

    ZeroBrane Studio API description

    The APIDump plugin also outputs API description for the ZeroBrane Studio IDE. It is written into the cuberite_api.lua file next to the Cuberite executable. See the Docs article about ZBS for details on how to use that file.

    Plugin Checker

    There is a CuberitePluginChecker project that aims to provide automatic testing to plugins. It uses the APIDump's descriptions to provide dummy implementations for all API functions. See the project page for details.

    ================================================ FILE: dev-docs/Generator.html ================================================ Generating terrain in Cuberite

    Generating terrain in Cuberite

    This article explains the principles behind the terrain generator in Cuberite. It is not strictly specific to Cuberite, though, it can be viewed as a generic guide to various terrain-generating algorithms, with specific implementation notes regarding Cuberite.

    Contents:


    Preface: How it's done in real life

    The nature has many complicated geological, physical and biological processes working on all scales from microscopic to planet-wide scale, that have shaped the terrain into what we see today. The tectonic plates collide, push mountain ranges up and ocean trenches down. Erosion dulls the sharp shapes. Plantlife takes over to further change the overall look of the world.

    Generally speaking, the processes take what's there and change it. Unlike computer generating, which usually creates a finished terrain from scratch, or maybe with only a few iterations. It would be unfeasible for software to emulate all the natural processes in enough detail to provide world generation for a game, mainly because in the nature everything interacts with everything. If a mountain range rises, it changes the way that the precipitation is carried by the wind to the lands beyond the mountains, thus changing the erosion rate there and the vegetation type.


    Expected properties

    For a MineCraft-like game terrain generator we need the generator to have several properties:

    • The generator must be able to generate terrain in small chunks. This means it must be possible to generate each of the chunks separately, without dependencies on the neighboring chunks. Note that this doesn't mean chunks cannot coordinate together, it means that "a tree in one chunk cannot ask if there's a building in the neighbor chunk", simply because the neighbor chunk may not be generated yet.
    • The generated chunk needs to be the same if re-generated. This property is not exactly required, but it makes available several techniques that wouldn't be possible otherwise.
    • The generator needs to be reasonably fast. For a server application this means at least some 20 chunks per second for chunks close to each other, and 5 chunks per second for distant chunks. The reason for this distinction will be discussed later.


    Reversing the flow

    As already mentioned, the nature works basically by generating raw terrain composition, then "applying" erosion, vegetation and finally this leads to biomes being formed. Let's now try a somewhat inverse approach: First generate biomes, then fit them with appropriate terrain, and finally cover in vegetation and all the other stuff.

    Splitting the parts like this suddenly makes it possible to create a generator with the required properties. We can generate a reasonable biome map chunk-wise, independently of all the other data. Once we have the biomes, we can compose the terrain for the chunk by using the biome data for the chunk, and possibly even for neighboring chunks. Note that we're not breaking the first property, the biomes can be generated separately so a neighboring chunk's biome map can be generated without the need for the entire neighboring chunk to be present. Similarly, once we have the terrain composition for a chunk, we can generate all the vegetation and structures in it, and those can again use the terrain composition in neighboring chunks.


    The ComposableGenerator pipeline

    This leads us directly to the main pipeline that is used for generating terrain in Cuberite. For technical reasons, the terrain composition step is further subdivided into Height generation and Composition generation, and the structures are really called Finishers. For each chunk the generator generates, in this sequence:

    • Biomes
    • Terrain height
    • Terrain composition
    • Finishers

    The beautiful thing about this is that the individual components can be changed independently. You can have 5 biome generators and 3 height generators and you can let the users mix'n'match.

    This pipeline had been used in Cuberite for about a year, before we realized that is has a flaw: There is no way for it to generate overhangs. We tried to implement a Finisher that would actually carve overhangs into the terrain; this approach has several problems, most severe one of those is that tree and village generation becomes unbelievably difficult - those finishers need to know the basic terrain composition of the neighboring chunks in order to generate, and the composition would be different after the overhangs are carved. So we need to come up with a better way, something that directly generates the overhangs at latest by the Terrain composition stage.

    Luckily we have just the thing. Instead of generating a 2D heightmap, we generate a 3D "density map" - we decide about each block in the chunk being generated, whether it is a solid block or an air block. The following pictures try to illustrate this in one less dimension - the heightmap is a 1D function and the density map is a 2D function:

    This way we can have generators that produce overhangs and yet allow finishers that need the entire composition of the neighboring chunks. However, we pay the price for this in performance, because a 3D noise for the density map needs order of magnitude more CPU cycles than 2D noise for heightmap. Also the RAM usage is increased because instead of storing 16 * 16 height values we need to store 16 * 256 * 16 density values.


    Using coherent noise for the generation

    For a great tutorial on coherent noise, see the LibNoise documentation.

    Coherent noise is a type of noise that has three important properties that we can use to our advantage:

    • The noise is smooth - small change in the input coord produces only a small change in the output value
    • The noise is algorithmically generated, which means that the same data is generated when the same inputs are given to the noise functions.
    • The noise can be seamlessly extended in any direction

    We'll be mostly using Perlin noise in this article. It is the easiest one to visualise and use and is one of the most useful kinds of coherent noises. Here's an example of a Perlin noise generated in 2 dimensions:

    It comes only naturally that such a 2D noise can be used as a terrain height map directly:

    However, this is not the only use for this noise, and 2 dimensions is not the limit - this noise can be generated for any number of dimensions.


    Generating biomes

    The easiest way to generate biomes is to not generate them at all - simply assign a single constant biome to everywhere. And indeed there are times when this kind of "generator" is useful - for the MineCraft's Flat world type, or for testing purposes, or for tematic maps. In Cuberite, this is exactly what the Constant biome generator does.

    Of course, there are more interesting test scenarios for which multiple biomes must be generated as easy as possible. For these special needs, there's a CheckerBoard biome generator. As the name suggests, it generates a grid of alternating biomes.

    Voronoi diagram

    Those two generators were more of a technicality, we need to make something more interesting if we're going for a natural look. The Voronoi generator is the first step towards such a change. Recall that a Voronoi diagram is a construct that creates a set of areas where each point in an area is closer to the appropriate seed of the area than the seeds of any other area:

    To generate biomes using this approach, you select random "seeds", assign a biome to each one, and then for each "column" of the world you find the seed that is the nearest to that column, and use that seed's biome.

    The overall shape of a Voronoi diagram is governed by the placement of the seeds. In extreme cases, a seed could affect the entire diagram, which is what we don't want - we need our locality, so that we can generate a chunk's worth of biome data. We also don't want the too much irregular diagrams that are produced when the seeds are in small clusters. We need our seeds to come in random, yet somewhat uniform fashion.

    Luckily, we have just the tool: Grid with jitter. Originally used in antialiasing techniques, they can be successfully applied as a source of the seeds for a Voronoi diagram. Simply take a regular 2D grid of seeds with the grid distance being N, and move each seed along the X and Y axis by a random distance, usually in the range [-N / 2, +N / 2]:

    Such a grid is the ideal seed source for a Voronoi biome generator, because not only are the Voronoi cells "reasonable", but the seed placement's effect on the diagram is localized - each pixel in the diagram depends on at most 4 x 4 seeds around it. In the following picture, the seed for the requested point (blue) must be within the indicated circle. Even the second-nearest seed, which we will need later, is inside that circle.

    Calculating the jitter for each cell can be done easily by using a 2D Perlin noise for each coord. We calculate the noise's value at [X, Z], which gives us a number in the range [-1; 1]. We then multiply the number by N / 2, this gives us the required range of [-N / 2, +N / 2]. Adding this number to the X coord gives us the seed's X position. We use another Perlin noise and the same calculation for the Z coord of the seed.

    Here's an example of a biome map generated using the Voronoi + jitter grid, as implemented by the Voronoi biome generator in Cuberite:

    Distorted Voronoi

    The biomes are starting to look interesting, but now they have straight-line borders, which looks rather weird and the players will most likely notice very soon. We need to somehow distort the borders to make them look more natural. By far the easiest way to achieve that is to use a little trick: When the generator is asked for the biome at column [X, Z], instead of calculating the Voronoi biome for column [X, Z], we first calculate a random offset for each coord, and add it to the coordinates. So the generator actually responds with the biome for [X + rndX, Z + rndZ].

    In order to keep the property that generating for the second time gives us the same result, we need the "random offset" to be replicatable - same output for the same input. This is where we use yet another Perlin noise - just like with the jitter for the Voronoi grid, we add a value from a separate noise to each coordinate before sending the coordinates down to the Voronoi generator:

    DistortedVoronoiBiome(X, Z) := VoronoiBiome(X + PerlinX(X, Z), Z + PerlinZ(X, Z))

    The following image shows the effects of the change, as generated by Cuberite's DistortedVoronoi biome generator. It is actually using the very same Voronoi map as the previous image, the only change has been the addition of the distortion:

    As you can see, this already looks reasonable enough, it could be considered natural biomes, if it weren't for several drawbacks:

    • There's no way to limit the neighbors. A desert biome can neighbor a tundra biome.
    • All the biomes are considered equal. There's no way to make oceans larger. A mushroom biome is generated right next to other land biomes.

    MultiStepMap

    Our next goal is to remove the first defect of the distorted Voronoi generator: unrelated biomes generating next to each other. You are highly unlikely to find a jungle biome next to a desert biome in the real world, so we want to have as few of those borders as possible in our generator, too. We could further improve on the selection of biome-to-seed in the Voronoi generator. Or we can try a completely different idea altogether.

    Recall how we talked about the nature, where the biomes are formed by the specific conditions of a place. What if we could make a similar dependency, but without the terrain? It turns out this is possible rather easily - instead of depending on the terrain, we choose two completely artificial measures. Let's call them Temperature and Humidity. If we knew the temperature of the place, we know what set of biomes are possible for such temperatures - we won't place deserts in the cold and tundra in the hot anymore. Similarly, the humidity will help us sort out the desert vs jungle issue. But how do we get a temperature and humidity? Once again, the Perlin noise comes to the rescue. We can use a simple 2D Perlin noise as the temperature map, and another one as the humidity map.

    What we need next is a decision of what biome to generate in certain temperature and humidity combinations. The fastest way for a computer is to have a 2D array, where the temperature is one dimension and humidity the other, and the values in the array specify the biome to generate:

    We can even "misuse" the above diagram to include the hill variants of the biomes and have those hills neighbor each other properly, simply by declaring some of the decision diagram's parts as hills:

    The problem with this approach is that there are biomes that should not depend on temperature or humidity, they generate across all of their values. Biomes like Oceans, Rivers and Mushroom. We could either add them somewhere into the decision diagram, or we can make the generator use a multi-step decision:

    • Decide whether the point is in the ocean, land or mushroom
    • If it's land, decide if it's real land or river.
    • If it's real land, use a TemperatureHumidity approach to generate land-biomes

    This is the approach implemented in Cuberite's MultiStepMap biome generator. It generates biome maps like this:

    To decide whether the point is in the ocean, land or mushroom, the generator first chooses seeds in a grid that will be later fed to a DistortedVoronoi algorithm, the seeds get the "ocean" and "land" values. Then it considers all the "ocean" seeds that are surrounded by 8 other "ocean" seeds and turns a random few of them into "mushroom". This special seed processing makes the mushroom biomes mostly surrounded by ocean. The following image shows an example seeds grid that the generator might consider, only the two framed cells are allowed to change into mushroom. L = land, O = ocean:

    Next, the generator calculates the DistortedVoronoi for the seeds. For the areas that are calculated as mushroom, the distance to the nearest-seed is used to further shrink the mushroom biome and then to distinguish between mushroom and mushroom-shore (image depicts a Voronoi cell for illustration purposes, it works similarly with DistortedVoronoi). O = ocean, M = mushroom, MS = mushroom shore:

    The rivers are added only to the areas that have been previously marked as land. A simple 2D Perlin noise is used as the base, where its value is between 0 and a configured threshold value, a river is created. This creates the rivers in a closed-loop-like shapes, occasionally splitting two branches off:

    For the leftover land biomes, the two Perlin noises, representing temperature and humidity, are used to generate the biomes, as described earlier. Additionally, the temperature map is used to turn the Ocean biome into FrozenOcean, and the River biome into FrozenRiver, wherever the temperature drops below a threshold.

    TwoLevel

    The 1.7 MineCraft update brought a completely new terrain generation, which has sparked renewed interest in the biome generation. A new, potentially simpler way of generating biomes was found, the two-level DistortedVoronoi generator.

    The main idea behind it all is that we create large areas of similar biomes. There are several groups of related biomes that can be generated near each other: Desert biomes, Ice biomes, Forest biomes, Mesa biomes. Technically, the Ocean biomes were added as yet another group, so that the oceans will generate in approximately the size of the larger areas, too.

    For each column a DistortedVoronoi is used to select, which large area to use. This in turn results in the list of biomes from which to choose. Another DistortedVoronoi, this time with a smaller grid size, is used to select one biome out of that list. Additionally, the smaller DistortedVoronoi calculates not only the nearest seed's distance, but also the distance to the second-nearest seed; the ratio between these two is used as an indicator whether the column is in the "inside" or on the "outskirt" of the smaller Voronoi cell. This allows us to give certain biomes an "edge" biome - the Mushroom biome has a MushroomShore edge, the ExtremeHills biome have an ExtremeHillsEdge biome on the edge, etc.

    The images below illustrate the process with regular Voronoi diagrams, for clarity purposes. The real generator uses distortion before querying the small areas.




    The following image shows an example output of a TwoLevel biome generator in Cuberite. Note how the mushroom biomes (violet) have mushroom shores (pink) on their edges.

    Note that rivers are currently not implemented in this generator in Cuberite, but they could be added using the same approach as in MultiStepMap - by using a thresholded 2D Perlin noise.

    Grown biomes

    This generator uses a completely new approach to biome generation. Internally, it uses 2D arrays of integers of varying sizes, and defines a few operations on those arrays. At various points in the generator's pipeline, the integers are interpreted as having a different meaning. At the first stage, they diffentiate between ocean and land. Later on they are interpreted as biome groups - ocean biomes, dry biomes, temperate biomes, mountain biomes or ice biomes. In the final stages they represent individual biomes, each number in the array representing the biome of a single-block-wide column in the world. Still, most of the operations are agnostic of this interpretation, they only "see numbers".

    At the core of the generator is the "Zoom" operation, that enlarges the array almost twice in size (N -> 2*N - 1). For each 2x2 neighboring numbers in the original array it produces a 3x3 array, where the corner values inherit from their corner counterparts of the original array, and the values in the middle get chosen randomly from their appropriate neighbors:

    ab
    cd
    --- zooom -->
    aa or bb
    a or ca or b or c or db or d
    cc or dd

    This scheme is repeated for larger arrays accordingly, for example (highlighted values are the ones directly copied from the source array):

    0011
    0101
    1100
    0110
    --- Zooom -->
    0001111
    01 01 01 1
    0011001
    01 11 00 1
    1110000
    11 11 00 0
    0011110

    The basic idea is that we're having a low-resolution image of the "land" and we're zooming in; in each zoom iteration we're adding random details - the randomly chosen numbers. This becomes apparent when we enlarge each image to the same dimensions:

    As you can see, the areas take a nice random-looking shape, but the edges are a little bit too noisy. There's where the second most important operation comes in: the "Smooth" slightly reduces the array size (N -> N - 2), losing the values on the edge of the array, and for the internal numbers it considers their 4 neighbors. If both the horizontal neighbors are the same and the vertical neighbors are the same (but not necessarily the same as the horizontal ones), the value is set randomly to either the horizontal or the vertical neihbors' value. If both the horizontal neighbors are the same, the value is set to the value of those neighbors, otherwise if both the vertical neighbors are the same, the value is set to the value of those neighbors. In all the rest cases, the value is kept at its original.

    a
    bXc
    d
    ConditionX becomes
    (a == d) && (b == c)a or b (random)
    a == da
    b == cb
    otherwiseX (unchanged)

    The following examples show how the decisions work:

    InputOutputNotes
     
       
     
     
    Neither pair of neighbors are the same, so the value is left intact
     
       
     
     
    Horizontal neighbors are the same, so the value is copied from them
     
       
     
     
    Vertical neighbors are the same, so the value is copied from them
     
       
     
     
    Each pair of neighbors are the same, so the value is chosen from one of the pairs randomly

    This decision is repeated for each value in the array, for example:

    0 0 0 1 1 11
    0101011
    0011001
    0111001
    1110000
    1111000
    0 0 1 1 1 10
    --- Smooth -->
    01011
    11100
    11100
    11100
    11100
    Highlighted area is processed into output Original value kept
    Value forced by both horizontal and vertical neighbors, random
    Value forced by horizontal neighbors
    Value forced by vertical neighbors

    The following example shows multiple successive Smooth operations performed on the same data set over and over again:

    As you can see, the smoothing operation doesn't make much difference after its first pass, so it usually isn't used more than once after each zoom.

    One important thing to note is that both the Zoom and Smooth operations only output the numbers already present in the array, they don't create new numbers. This is important because it allows the late stages of the generator to grow indepent biomes next to each other without them "bleeding" into different biomes on their edges.

    The Grown generator uses several more supplementary operations, such as "AddIslands", "ReplaceRandomly", "River", "Beaches" and more. There isn't anything too special to those, they perform mostly trivial operations, manipulating the numbers in some way; the main power of the generator lies in the zoom and smooth operations. Perhaps noteworthy is the generation of rivers: it starts with the regular bitmap (only 0 and 1 used), zooms in and smooths for a while and then performs edge detection - a river biome is set in pixels whose neighbors are different, and no change applied when the neighbors are the same. Among other things, this means that there are actually two chains of array operations, and their results are combined together in the "MixRivers" operation.

    The following table summarizes the operations, visually:

    OperationInput 1Input 2OutputNotes
    AddIslands - Adds a configurable (by percentage) amount of islands to ocean biome group.
    AlternateBiomes Mostly copies the first input, but where the second input has non-ocean biome group, turns the first input's biomes into their alternatives.
    Beaches - Any biome neighboring an ocean is turned into a corresponding beach.
    BiomeEdges - If the neighbors of a biome are incompatible (such as desert vs ice plains, or jungle vs anything etc.), turns the biome into a corresponding neutral biome (plains, jungle-edge etc.)
    Biomes - Input is interpreted as biome groups, for each point a random biome corresponding to the group is chosen for the output.
    BiomeGroupEdges - Converts biome groups on an edge between two incompatible groups (such as desert and ice) into a neutral one (temperate).
    MBiomes Where the second input is zero, copies the first input's biomes; where the second input is nonzero, converts first input's biomes into their M variants.
    MixRivers Copies first input's biomes into the output, unless there's a river biome in the second input and a land biome in the first input - then it sets a river biome in the output instead.
    River - Somewhat of an edge detector - wherever the input has a different biome neighbors, sets a river biome; otherwise sets an ocean biome.
    SetRandomly - Randomly sets points to a specified biome. The amount of changed points is settable as a percentage.

    Of further note is the existence of two sets of the IntGen classes, representing the individual operations. There are the cProtIntGen class descendants, which are used for prototyping the connections between the operations - it's easy to just chain several operations after each other and they automatically use the correct array dimensions. However, it is possible to further optimize the calculations by moving the array dimensions into template parameters (so that they are, in fact, constant from the code's point of view, and so highly optimizable). This is what the cIntGen class descendants do. Unfortunately, this optimization makes it difficult to change the operation chain - when a new operation is added or removed in the chain, the array sizes for the rest of the chain change and they all have to be updated manually. So the optimal strategy was to use the cProtIntGen classes to find out the best-looking combination of operations, and once the combination was found, to rewrite it using cIntGen classes for performance.


    Here is a visualizer where you can play with the algorithm that the Grown biome generator uses. Note that rendering the map takes way longer than the zoom/smooth operation.

    Terrain height

    As with biomes, the easiest way to generate terrain height is not generating at all - assigning a constant height value to all columns. This is again useful either for internal tests, and for worlds like MineCraft's Flat world.

    For a somewhat more realistic landscape, we will employ the good old 2D Perlin noise. We can use it directly as a heightmap - each value we get from the noise is stretched into the desired range (usually from 40 to 120 blocks for regular MineCraft worlds) and used as the height value. However, this doesn't play too well with the biomes we've just generated. If the biome says "ocean" and the Perlin noise says "mountain", the end result will be unpleasant.

    So we want a height generator that is biome-aware. The easiest way of doing this is to have a separate generator for each biome. Simply use the biome map to select which generator to use, then ask the appropriate generator for the height value. Again, this doesn't work too well - imagine an ExtremeHills biome right next to an Ocean biome. If no extra care is taken, the border between these two will be a high wall. The following image shows a 2D representation (for simplification purposes) of the problem:

    This requires some further processing. What we need is for the terrain height to be dependent not only on the immediate biome for that column, but also on the close surroundings of the column. This is exactly the kind of task that averaging is designed for. If we take the area of 9x9 biomes centered around the queried column, generate height for each of the biomes therein, sum them up and divide by 81 (the number of biomes summed), we will be effectively making a 9-long running average over the terrain, and all the borders will suddenly become smooth. The following image shows the situation from the previous paragraph after applying the averaging process:

    The approach used in Cuberite's Biomal generator is based on this idea, with two slight modifications. Instead of using a separate generator for each biome, one generator is used with a different set of input parameters for each biomes. These input parameters modify the overall amplitude and frequency of the Perlin noise that the generator produces, thus modifying the final terrain with regards to biomes. Additionally, the averaging process is weighted - columns closer to the queried column get a more powerful weight in the sum than the columns further away. The following image shows the output of Cuberite's Biomal terrain height generator (each block type represents a different biome - ocean in the front (stone), plains and ice plains behind it (lapis, whitewool), extreme hills back right (soulsand), desert hills back left (mossy cobble)):

    One key observation about this whole approach is that in order for it to work, the biomes must be available for columns outside the currently generated chunk, otherwise the columns at the chunk's edge would not be able to properly average their height. This requirement can be fulfilled only by biome generators that adhere to the second Expected property - that re-generating will produce the same data. If the biome generator returned different data for the same chunk each time it was invoked, it would become impossible to apply the averaging.

    (TODO: height with variations (N/A in MCS yet)


    Terrain composition

    As with the other generators, the composition generator category has its easy and debugging items, too. There's the "special" composition of "all the blocks are the same type", which fills the entire column, from the bottom to the height, with a single blocktype. This generator is useful when testing the generators in the other categories, to speed up the generation by leaving out unnecessary calculations. Another special compositor is a similar one, that fills all blocks with the same type, but the type varies for each biome. This way it's easy to see the generated biomes and possibly the heights for those biomes, as shown in the previous section on the height averaging screenshot.

    For a natural look, we need to put together a more complicated algorithm. The standard set forth in MineCraft is that the top of the world is covered in grass, then there are a few blocks of dirt and finally stone. This basic layout is then varied for different biomes - deserts have sand and sandstone instead of the grass and dirt layer. Mushroom biomes have mycelium in place of the grass. This per-biome dependency is trivial to implement - when compositing, simply use the appropriate layout for the column's biome.

    The next change concerns oceans. The generated heightmap doesn't include any waterlevel indication whatsoever. So it's up to the terrain compositor to actually decide where to place water. We do this by configuration - simply have a value in the config file specifying the sealevel height. The compositor then has to add water above any column which has a height lower than that. Additionally, the water needs to override per-biome layout selection - we don't want grass blocks to generate under water when the terrain height in the plains biome drops below the sealevel accidentally.

    The final feature in the compositor is the decision between multiple composition layouts within a single biome. A megataiga biome contains patches of non-grass dirt and podzol blocks, and the ocean floor can be made of dirt, gravel, sand or clay. A simple 2D Perlin noise can be used to select the layout to use for a specific column - simply threshold the noise's value by as many thresholds as there are layout variations, and use the layout corresponding to the threshold:

    Nether composition

    So far we've been discussing only the Overworld generator. But MineCraft contains more than that. The Nether has a completely different look and feel, and quite different processes are required to generate that. Recall that MineCraft's Nether is 128 blocks high, with bedrock both at the top and the bottom. Between these two, the terrain looks more like a cavern than a surface. Not surprisingly, the Nether doesn't need a complicated height generator, it can use the flat height. However, the terrain composition must take an altogether different approach.

    The very first idea is to use the Perlin noise, but generate it in 3D, rather than 2D. Then, for each block, evaluate the noise value, if below 0, make it air, if not, make it netherrack.

    To make it so that the bedrock at the top and at the bottom is never revealed, we can add a value increasing the more the Y coord gets towards the bottom or the top. This way the thresholding then guarantees that there will be no air anywhere near the bedrock.

    (TODO)


    Finishers

    Finishers are a vast category of various additions to the terrain generator. They range from very easy ones, such as generating snow on top of the terrain in cold biomes, through medium ones, such as growing patches of flowers, complicated ones, such as placing trees and generating caves, all the way to very complicated ones such as villages and nether fortresses. There is no formal distinction between all these "categories", the only thing they have in common is that they take a chunk of blocks and modify it in some way.

    Snow

    Snow is probably the easiest of the finishers. It generates a block of snow on top of each block that is on top of the terrain and is not marked as non-snowable. It checks the chunk's heightmap to determine the top block, then checks whether the block supports snow on its top. Rails, levers and tall grass don't support snow, for example.

    Ice

    Another example of an easy finisher. This scans through the world and turn each water block on the surface into an ice block if the biome is cold. This means that any water block that is under any kind of other block, such as under a tree's leaves, will still stay water. Thus an additional improvement could be made by scanning down from the surface block through blocks that we deem as non-surface, such as leaves, torches, ladders, fences etc. Note that Cuberite currently implements only the easy solution.

    Bottom lava

    Most worlds in MineCraft have lava lakes at their bottom. Generating these is pretty straightforward: Use the user-configured depth and replace all the air blocks below this depth with lava blocks. Note however, that this makes this generator dependent on the order in which the finishers are applied. If the mineshafts generate before bottom lava, the mineshafts that are below the lava level will get filled with lava. On the other hand, if bottom lava is generated before the mineshafts, it is possible for a mineshaft to "drill through" a lake of lava. Cuberite doesn't try to solve this and instead lets the admin choose whichever they prefer.

    Specific foliage

    There are generators for specific kinds of foliage. The dead bushes in the desert biome and lilypads in the swamp biome both share the same generating pattern. They are both specific to a single biome and they both require a specific block underneath them in order to generate. Their implementation is simple: pick several random columns in the chunk. If the column is of the correct biome and has the correct top block, add the foliage block on top.

    In order to generate the same set of coordinates when the chunk is re-generated, we use the Perlin noise's basis functions (the ones providing the random values for Perlin cell vertices). These basically work as a hash function for the coorinates - the same input coordinates generate the same output value. We use the chunk's coordinates as two of the coords, and the iteration number as the third coordinate, to generate a random number. We then check the biome and the top block at those coordinates, if they allow, we generate the foliage block on top.

    Another example of specific foliage is the tall grass in the plains biome. There are quite a lot of these tall grass blocks, it would be inefficient to generate them using the random-coords approach described above. Instead, we will use a 2D Perlin noise again, with a threshold defining where to put the grass and where not.

    Small foliage

    For the flowers, grass, mushrooms in caves etc. we want to use a slightly different algorithm. These foliage blocks are customarily generated in small "clumps" - there are several blocks of the same type near together. To generate these, we first select random coords, using the coord hash functions, for a center of a clump. Then we select the type of block to generate. Finally, we loop over adding a random (coord hash) number to the clump center coords to get the block where to generate the foliage block:

    In order to make the clump more "round" and "centered", we want the offsets to be closer to the clump center more often. This is done using a thing called Gaussian function distribution. Instead of having each random number generate with the same probability, we want higher probability for the numbers around zero, like this:

    Instead of doing complicated calculations to match this shape exactly, we will use a much easier shape. By adding together two random numbers in the same range, we get the probability distribution that has a "roof" shape, enough for our needs:

    (For the curious, there is a proof that adding together infinitely many uniform-distributed random numbers produces random numbers with the Gaussian distribution.)

    This scheme can be used to produce clumps of flowers, when we select the 2D coords of the clump center on the top surface of the terrain. We simply generate the 2D coords of the foliage blocks and use the terrain height to find the third coord. If we want to generate clumps of mushrooms in the caves, however, we need to generate the clump center coords in 3D and either use 3 offsets for the mushrooms, or use 2 offsets plus searching for the closest opening Y-wise in the terrain.

    Note that the clumps generated by this scheme may overlap several chunks. Therefore it's crucial to actually check the surrounding chunks if their clumps overlap into the currently generated chunk, and apply those as well, otherwise there will be visible cuts in the foliage along the chunks borders.

    Springs

    Water and lava springs are essential for making the underground quite a lot more interesting. They are rather easy to generate, but a bit more difficult to get right. Generating simply means that a few random locations (obtained by our familiar coord hashing) are checked and if the block type in there is stone. Then we see all the horizontal neighbors of the block, plus the block underneath. If all of them except one are stone, and the one left is air, our block is suitable for turning into a spring. If there were more air neighbors, the spring would look somewhat unnatural; if there were no air neighbors, the spring won't flow anywhere, so it would be rather useless.

    The difficult part about springs is the amount of them to generate. There should be a few springs on the surface, perhaps a bit more in the mountaineous biomes. There should be quite a few more springs underground, but there should definitely be more water springs than lava springs in the upper levels of the terrain, while there should be more lava springs and almost no water springs near the bottom. To accomodate this, the Cuberite team has made a tool that scanned through MineCraft's terrain and counted the amount of both types of springs in relation to their height. Two curves have been found for the distribution of each type of the spring:

    Cuberite uses an approximation of the above curves to choose the height at which to generate the spring.

    Caves

    Caves are definitely one of the main things people notice about MineCraft terrain. There are quite a lot of different algorithms available to generate terrain with caves, each with different results. Cuberite currently implements three finishers that generate caves:

    • MarbleCaves
    • DualRidgeCaves
    • WormNestCaves


    Making it all faster

    (TODO)

    Executing on a GPU

    Much of the terain generation consists of doing the same thing for every single column or block in a chunk. This sort of computation is much faster on a GPU as GPUs are massively parallel. High end GPUs can execute up to 30,000 threads simultaneously, which would allow them to generate every block in half a chunk in parallel or every column in over 100 chunks in parallel. A naive comparison suggests that a 800MHz GPU with 15,000 threads can execute parallel code 250 times faster than a 3GHz CPU with 128 bit SIMD. Obviously we want to harness that power.

    ================================================ FILE: dev-docs/Login sequence.txt ================================================ This is the connection sequence of the 1.6.2 client to a vanilla server, after the encryption has been established: S->C: 0xfc (encryption key response) empty payload (4 * 0x00) C->S: 0xcd (client statuses) S->C: 0x01 (login) S->C: 0xfa (plugin message) - "MC|Brand": "vanilla" S->C: 0x06 (compass) S->C: 0xca (player capabilities) S->C: 0x10 (slot select) S->C: 0x04 (time update) S->C: 0xc9 (player list item) S->C: 0x0d (player pos + look) S->C: 0x04 (time update) S->C: 0x68 (window contents) S->C: 0x67 (slot contents) - Window -1, slot -1 S->C: 0x67 (slot contents) - Window 0, slot 9 .. 44, only occupied slots S->C: 0x38 (chunk bulk) S->C: 0x28 (entity metadata) player metadata S->C: 0x2c (entity properties) player properties S->C: 0x04 (time update) S->C: 0x38 (chunk bulk) C->S: 0xcc (client settings / locale and view) C->S: 0xfa (plugin message) - "MC|Brand": "vanilla" C->S: 0x0d (player pos + look) S->C: 0x38 (chunk bulk) ================================================ FILE: dev-docs/NBT Examples/single chunk NBT data.txt ================================================ TAG_Compound(""): 1 items { TAG_Compound("Level"): 10 items { TAG_List("TileTicks"): 0 items of type 1 { } TAG_List("Entities"): 0 items of type 1 { } TAG_ByteArray("Biomes"): 256 bytes TAG_Long("LastUpdate"): 1041959 TAG_Int("xPos"): 0 TAG_Int("zPos"): 0 TAG_List("TileEntities"): 0 items of type 1 { } TAG_Byte("TerrainPopulated"): 1 TAG_List("Sections"): 6 items of type 10 { TAG_Compound(""): 5 items { TAG_ByteArray("Data"): 2048 bytes TAG_ByteArray("SkyLight"): 2048 bytes TAG_ByteArray("BlockLight"): 2048 bytes TAG_Byte("Y"): 0 TAG_ByteArray("Blocks"): 4096 bytes } TAG_Compound(""): 5 items { TAG_ByteArray("Data"): 2048 bytes TAG_ByteArray("SkyLight"): 2048 bytes TAG_ByteArray("BlockLight"): 2048 bytes TAG_Byte("Y"): 1 TAG_ByteArray("Blocks"): 4096 bytes } TAG_Compound(""): 5 items { TAG_ByteArray("Data"): 2048 bytes TAG_ByteArray("SkyLight"): 2048 bytes TAG_ByteArray("BlockLight"): 2048 bytes TAG_Byte("Y"): 2 TAG_ByteArray("Blocks"): 4096 bytes } TAG_Compound(""): 5 items { TAG_ByteArray("Data"): 2048 bytes TAG_ByteArray("SkyLight"): 2048 bytes TAG_ByteArray("BlockLight"): 2048 bytes TAG_Byte("Y"): 3 TAG_ByteArray("Blocks"): 4096 bytes } TAG_Compound(""): 5 items { TAG_ByteArray("Data"): 2048 bytes TAG_ByteArray("SkyLight"): 2048 bytes TAG_ByteArray("BlockLight"): 2048 bytes TAG_Byte("Y"): 4 TAG_ByteArray("Blocks"): 4096 bytes } TAG_Compound(""): 5 items { TAG_ByteArray("Data"): 2048 bytes TAG_ByteArray("SkyLight"): 2048 bytes TAG_ByteArray("BlockLight"): 2048 bytes TAG_Byte("Y"): 5 TAG_ByteArray("Blocks"): 4096 bytes } } } } ================================================ FILE: dev-docs/NBT Examples/tile entities.txt ================================================ TAG_List("TileEntities"): 3 items of type 10 { TAG_Compound(""): 6 items { TAG_String("id"): 10 bytes: "MobSpawner" TAG_Short("Delay"): 20 TAG_Int("z"): 180 TAG_String("EntityId"): 6 bytes: "Spider" TAG_Int("y"): 11 TAG_Int("x"): -6 } TAG_Compound(""): 5 items { TAG_List("Items"): 6 items of type 10 { TAG_Compound(""): 4 items { TAG_Short("id"): 325 TAG_Short("Damage"): 0 TAG_Byte("Count"): 1 TAG_Byte("Slot"): 3 } TAG_Compound(""): 4 items { TAG_Short("id"): 296 TAG_Short("Damage"): 0 TAG_Byte("Count"): 4 TAG_Byte("Slot"): 5 } TAG_Compound(""): 4 items { TAG_Short("id"): 325 TAG_Short("Damage"): 0 TAG_Byte("Count"): 1 TAG_Byte("Slot"): 11 } TAG_Compound(""): 4 items { TAG_Short("id"): 351 TAG_Short("Damage"): 3 TAG_Byte("Count"): 1 TAG_Byte("Slot"): 13 } TAG_Compound(""): 4 items { TAG_Short("id"): 296 TAG_Short("Damage"): 0 TAG_Byte("Count"): 1 TAG_Byte("Slot"): 14 } TAG_Compound(""): 4 items { TAG_Short("id"): 287 TAG_Short("Damage"): 0 TAG_Byte("Count"): 2 TAG_Byte("Slot"): 15 } } TAG_String("id"): 5 bytes: "Chest" TAG_Int("z"): 182 TAG_Int("y"): 11 TAG_Int("x"): -7 } TAG_Compound(""): 5 items { TAG_List("Items"): 5 items of type 10 { TAG_Compound(""): 4 items { TAG_Short("id"): 289 TAG_Short("Damage"): 0 TAG_Byte("Count"): 1 TAG_Byte("Slot"): 5 } TAG_Compound(""): 4 items { TAG_Short("id"): 329 TAG_Short("Damage"): 0 TAG_Byte("Count"): 1 TAG_Byte("Slot"): 12 } TAG_Compound(""): 4 items { TAG_Short("id"): 265 TAG_Short("Damage"): 0 TAG_Byte("Count"): 4 TAG_Byte("Slot"): 17 } TAG_Compound(""): 4 items { TAG_Short("id"): 296 TAG_Short("Damage"): 0 TAG_Byte("Count"): 4 TAG_Byte("Slot"): 21 } TAG_Compound(""): 4 items { TAG_Short("id"): 289 TAG_Short("Damage"): 0 TAG_Byte("Count"): 2 TAG_Byte("Slot"): 22 } } TAG_String("id"): 5 bytes: "Chest" TAG_Int("z"): 181 TAG_Int("y"): 11 TAG_Int("x"): -8 } } ================================================ FILE: dev-docs/Object ownership.gv ================================================ digraph { rankdir=LR Root -> Server Root -> MonsterConfig Root -> GroupManager Root -> CraftingRecipes Root -> FurnaceRecipe Root -> PluginManager Root -> Authenticator Root -> World Server -> ListenThreadIPv4 Server -> ListenThreadIPv6 Server -> ClientHandle Server -> RCONServer PluginManager -> Plugin_NewLua PluginManager -> Plugin World -> SimulatorManager World -> SandSimulator World -> WaterSimulator World -> LavaSimulator World -> FireSimulator World -> RedstoneSimulator World -> WorldStorage World -> Player World -> Generator World -> ChunkSender World -> LightingThread } ================================================ FILE: dev-docs/Plugin API.md ================================================ # Looking for the API documentation for Lua plugins? See the [cuberite website](https://api.cuberite.org/) or browse the [source](https://github.com/cuberite/cuberite/tree/master/Server/Plugins/APIDump). ================================================ FILE: dev-docs/SocketThreads states.gv ================================================ digraph { node [ shape="box" ] edge [ d ] // Forward-declarations of nodes (so that they are laid out in a specific order: ssNormal ssWritingRestOut ssShuttingDown ssShuttingDown2 // Nodes with special labels / shapes: ForceClose [ label="Force close" shape="ellipse" ] X [ label="Socket closed" shape="ellipse" ] // Edges: ssNormal -> ssWritingRestOut [ label="cSocketThreads::RemoveClient()" ] ssWritingRestOut -> ssShuttingDown [ label="All outgoing data written" ] ssShuttingDown -> ssShuttingDown2 [ label="One thread loop" ] ssShuttingDown2 -> ForceClose [ label="One thread loop" ] ssNormal -> ssRemoteClosed [ label="Remote closed" color="red" fontcolor="red" ] ssWritingRestOut -> X [ label="Remote closed" color="red" fontcolor="red" ] ssShuttingDown -> X [ label="Remote closed" color="red" fontcolor="red" ] ssShuttingDown2 -> X [ label="Remote closed" color="red" fontcolor="red" ] ssRemoteClosed -> X [ label="cSocketThreads::RemoveClient()" ] ForceClose -> X } ================================================ FILE: dev-docs/_files.txt ================================================ Contents of this folder: API class inheritance - blockentities.gv - a GraphViz file to visualise inheritance in the API classes in the Wiki for the cBlockEntity class' descendants API class inheritance - entities.gv - a GraphViz file to visualise inheritance in the API classes in the Wiki for the cEntity class' descendants Login Sequence.txt - Annotated log of packets exchanged between the client and server for login; 1.6.2 protocol Object ownership.gv - a GraphViz file to visualise ownership relations in the Cuberite code architecture SocketThreads states.gv - a GraphViz file documenting the states for individual sockets in cSocketThreads, and transitions between them Springs.ods - a spreadsheet with collected statistics about the occurrence of lava / water springs based on height. ================================================ FILE: dev-docs/js/ValueMap.js ================================================ const g_DistanceBetweenSquares = 0;//.01; const g_Colors = [ "#0000FF", "#00FF00", "#FF0000", "#FF00FF", "#00FFFF", "#FFFF00", "#000000", "#9BADFF" ] class ValueMap { constructor() { this.values = new Uint8Array(4 * 4); this.sizeX = 4; this.sizeZ = 4; this.reset(); } reset() { this.sizeX = 4; this.sizeZ = 4; this.values = new Uint8Array(this.sizeX * this.sizeZ); for (let x = 0; x < this.sizeX; x++) { for (let z = 0; z < this.sizeZ; z++) { this.values[x + this.sizeZ * z] = Math.floor(Math.random() * 8); } } } chooseRandomNumber() { let numArguments = arguments.length; return arguments[Math.floor(Math.random() * arguments.length)]; } smooth() { let sizeZ = this.sizeZ - 2; let sizeX = this.sizeX - 2; let cache = new Uint8Array((this.sizeX - 2) * (this.sizeZ - 2)); for (let z = 0; z < sizeZ; z++) { for (let x = 0; x < sizeX; x++) { let val = this.values[x + 1 + (z + 1) * this.sizeX]; let above = this.values[x + 1 + z * this.sizeX]; let below = this.values[x + 1 + (z + 2) * this.sizeX]; let left = this.values[x + (z + 1) * this.sizeX]; let right = this.values[x + 2 + (z + 1) * this.sizeX]; if ((left == right) && (above == below)) { if (Math.random() < 0.5) { val = left; } else { val = below; } } else { if (left == right) { val = left; } if (above == below) { val = above; } } cache[x + z * sizeX] = val; } } this.values = cache; this.sizeX -= 2; this.sizeZ -= 2; } zoom() { let lowStepX = (this.sizeX - 1) * 2; let lowStepZ = (this.sizeZ - 1) * 2; let cache = new Uint8Array(lowStepX * lowStepZ); for (let z = 0; z < this.sizeZ - 1; z++) { let idx = (z * 2) * lowStepX; let PrevZ0 = this.values[z * this.sizeX]; let PrevZ1 = this.values[(z + 1) * this.sizeX]; for (let x = 0; x < this.sizeX - 1; x++) { let ValX1Z0 = this.values[x + 1 + z * this.sizeX]; let ValX1Z1 = this.values[x + 1 + (z + 1) * this.sizeX]; cache[idx] = PrevZ0; cache[idx + lowStepX] = this.chooseRandomNumber(PrevZ0, PrevZ1); cache[idx + 1] = this.chooseRandomNumber(PrevZ0, ValX1Z0); cache[idx + 1 + lowStepX] = this.chooseRandomNumber(PrevZ0, ValX1Z0, PrevZ1, ValX1Z1); idx += 2; PrevZ0 = ValX1Z0; PrevZ1 = ValX1Z1; } } this.values = cache; this.sizeX = lowStepX; this.sizeZ = lowStepZ; } visualize(context, canvas) { context.clearRect(0, 0, canvas.width, canvas.height); const squareSizeX = canvas.width / (this.sizeX - 1) - g_DistanceBetweenSquares; const squareSizeY = canvas.height / (this.sizeZ - 1) - g_DistanceBetweenSquares; for (let x = 0; x < this.sizeX - 1; x++) { for (let y = 0; y < this.sizeZ - 1; y++) { let renderX = canvas.width / (this.sizeX - 1) * x + g_DistanceBetweenSquares; let renderY = canvas.height / (this.sizeZ - 1) * y + g_DistanceBetweenSquares; context.fillStyle = g_Colors[this.values[x + y * this.sizeZ]]; context.fillRect(renderX, renderY, squareSizeX, squareSizeY); } } context.save(); context.globalCompositeOperation = 'difference'; context.fillStyle = 'white'; context.fillText("Size: " + (this.sizeX - 1) + "x" + (this.sizeZ - 1), 5, 10); context.restore(); } } ================================================ FILE: dev-docs/js/grown.js ================================================ let g_Canvas = null; let g_Context = null; let g_ValueMap = null; function init() { g_Canvas = document.getElementById("stage"); g_Context = g_Canvas.getContext("2d"); g_ValueMap = new ValueMap(); g_ValueMap.visualize(g_Context, g_Canvas); } function btnZoom(btn) { g_ValueMap.zoom(); g_ValueMap.visualize(g_Context, g_Canvas); if ( (g_ValueMap.sizeX * 2 - 1 > 600) || (g_ValueMap.sizeZ * 2 - 1 > 600) ) { btn.disabled = true; } } function btnSmooth() { g_ValueMap.smooth(); g_ValueMap.visualize(g_Context, g_Canvas); } function btnReset() { g_ValueMap.reset(); g_ValueMap.visualize(g_Context, g_Canvas); document.getElementById("grownZoomButton").disabled = false; } function btnAutomatic(target) { target.disabled = true; document.getElementById("grownZoomButton").disabled = true; // Reset the valuemap. We don't want to continue on a 500x500 map. g_ValueMap.reset(); g_ValueMap.visualize(g_Context, g_Canvas); const animationTimeBetween = 350; let zoom = () => { g_ValueMap.zoom() }; let smooth = () => { g_ValueMap.smooth() }; let actions = []; for (let i = 0; i < 6; i++) actions.push(zoom); // First zoom 6 times for (let i = 0; i < 3; i++) actions.push(smooth); // Then smooth 3 times for (let i = 0; i < 2; i++) actions.push(zoom); // Zoom 2 times for (let i = 0; i < 2; i++) actions.push(smooth); // And finally smooth 2 more times. let update = () => { if (actions[0] == null) { target.disabled = false; return; } actions[0].call(); g_ValueMap.visualize(g_Context, g_Canvas); actions.splice(0, 1); setTimeout(update, animationTimeBetween); }; setTimeout(update, animationTimeBetween + 500); } window.onload = init; ================================================ FILE: dev-docs/style.css ================================================ table { border: 1px outset; border-spacing: 0px; border-collapse: separate; } td, th { border: 1px inset } // Copied over from Server/Plugins/APIDump/main.css to make the pages look like the API docs: html { background-color: #C0C0C0; } pre { border: 1px solid #ccc; background-color: #eee; -moz-tab-size: 2; -o-tab-size: 2; -webkit-tab-size: 2; -ms-tab-size: 2; tab-size: 2; } body { min-width: 400px; max-width: 1200px; width: 95%; margin: 10px auto; background-color: white; border: 4px #FF8C00 solid; border-radius: 20px; font-family: Calibri, Trebuchet MS; } header { text-align: center; font-family: Segoe UI Light, Helvetica; } footer { text-align: center; font-family: Segoe UI Light, Helvetica; } #content, #timestamp { padding: 0px 25px 25px 25px; } ================================================ FILE: easyinstall.sh ================================================ #!/bin/sh { # NOTE: compile.sh looks for this file in order to determine if this is the Cuberite folder. # Please modify compile.sh if you want to rename or remove this file. # This file was chosen arbitrarily and it is a good enough indicator that we are in the Cuberite folder. set -e KERNEL=$(uname -s) echo "Identifying kernel: $KERNEL" if [ "$KERNEL" = "Linux" ]; then PLATFORM=$(uname -m) echo "Identifying platform: $PLATFORM" case $PLATFORM in "i686") DOWNLOADURL="https://download.cuberite.org/linux-i686/Cuberite.tar.gz" ;; "x86_64") DOWNLOADURL="https://download.cuberite.org/linux-x86_64/Cuberite.tar.gz" ;; # Assume that all arm devices are a raspi for now. arm*) DOWNLOADURL="https://download.cuberite.org/linux-armhf-raspbian/Cuberite.tar.gz" ;; # Allow install on Raspberry Pi 4 Ubuntu x64 (AArch64) using the ARM builds. "aarch64") DOWNLOADURL="https://download.cuberite.org/linux-aarch64/Cuberite.tar.gz" esac elif [ "$KERNEL" = "Darwin" ]; then # All Darwins we care about are x86_64 DOWNLOADURL="https://download.cuberite.org/darwin-x86_64/Cuberite.tar.gz" #elif [ "$KERNEL" = "FreeBSD" ]; then # DOWNLOADURL="https://builds.cuberite.org/job/Cuberite%20FreeBSD%20x64%20Master/lastSuccessfulBuild/artifact/Cuberite.tar.gz" else echo "Unsupported kernel." exit 1 fi echo "Downloading precompiled binaries." curl -Ls $DOWNLOADURL | tar -xzf - echo "Done." echo "Cuberite is now installed, run using 'cd Server; ./Cuberite'." } ================================================ FILE: nightlybuild.sh ================================================ #!/usr/bin/env bash set -ex # Parse arguments. while [[ $# -gt 1 ]] do key="$1" case $key in -s|--server-name) SERVERNAME="$2" shift ;; -t|--target) TARGET="$2" shift ;; -c|--compiler) CCOMP="$2" shift ;; -cxx|--cxx-compiler) CXXCOMP="$2" shift ;; -m|--compile-mode) COMPILEMODE="-DCMAKE_BUILD_TYPE=$2" shift ;; -n|--build-number) BUILDID="$2" shift ;; -p|--toolchain-file) TOOLCHAINFILE="-DCMAKE_TOOLCHAIN_FILE=$2" shift ;; -b|--branch) BRANCH="$2" shift ;; -32|--force-32) FORCE32="-DFORCE_32=$2" shift ;; *) ;; esac shift done git submodule update --init # Set up build information. export CUBERITE_BUILD_SERIES_NAME="$SERVERNAME $TARGET $COMPILEMODE ($BRANCH)" export CUBERITE_BUILD_ID="$BUILDID" export CUBERITE_BUILD_DATETIME="`date`" if [ -x "$(command -v ccache)" ] then export CCACHE_CPP2=true CACHE_ARGS="-DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache" fi # Build CXX=$CXXCOMP CC=$CCOMP cmake . -DNO_NATIVE_OPTIMIZATION=1 ${CACHE_ARGS} ${TOOLCHAINFILE} ${COMPILEMODE} ${FORCE32} make -j 4 # Package Server echo Cuberite "$CUBERITE_BUILD_SERIES_NAME-$CUBERITE_BUILD_ID\n$BUILD_URL" > Server/buildinfo.txt # h: dereference (archive file/folder instead of symlink) # z: gzip (compress) # c: create # v: verbose # T: files-from (list of server files accepted for release archives) # f: file (output file location) pushd Server tar -hzcv --exclude .git -T Install/UnixExecutables.list -f ../Cuberite.tar.gz popd sha1sum Cuberite.tar.gz > Cuberite.tar.gz.sha1 # Package ProtoProxy # This tool is very out of date, uncomment when it's being worked on again # pushd Tools/ProtoProxy # sha1sum ProtoProxy > ProtoProxy.sha1 # popd ================================================ FILE: src/Bindings/.gitignore ================================================ docs/ lua51.dll LuaState_Declaration.inc LuaState_Implementation.cpp LuaState_Typedefs.inc ================================================ FILE: src/Bindings/AllToLua.bat ================================================ :: AllToLua.bat :: This scripts updates the automatically-generates Lua bindings in Bindings.cpp / Bindings.h :: When called without any parameters, it will pause for a keypress at the end :: Call with any parameter to disable the wait (for buildserver use) @echo off :: Regenerate the files: echo Regenerating LUA bindings . . . "tolua++.exe" -L BindingsProcessor.lua -o Bindings.cpp -H Bindings.h AllToLua.pkg : Wait for keypress, if no param given: echo. if %ALLTOLUA_WAIT%N == N pause ================================================ FILE: src/Bindings/AllToLua.pkg ================================================ // AllToLua.pkg // Defines the bindings that are exported to Lua by the ToLua processor /* Each file referenced in the $cfile is parsed by ToLua, and bindings are generated for classes and functions marked with "// tolua_export", or between the "// tolua_begin" and "// tolua_end" markers. Note that if class D inherits from class B, then class B needs to be parsed before class D, otherwise the inheritance doesn't work properly (#1789). */ $#include "../Globals.h" // Typedefs from Globals.h, so that we don't have to process that file: typedef signed long long Int64; typedef signed int Int32; typedef signed short Int16; typedef signed char Int8; typedef unsigned long long UInt64; typedef unsigned int UInt32; typedef unsigned short UInt16; typedef unsigned char UInt8; $cfile "../Vector3.h" $cfile "../ChunkDef.h" $cfile "../BiomeDef.h" $cfile "../IniFile.h" $cfile "../OSSupport/File.h" $cfile "LuaFunctions.h" $cfile "PluginManager.h" $cfile "Plugin.h" $cfile "PluginLua.h" $cfile "LuaWindow.h" $cfile "../BlockType.h" $cfile "../BlockInfo.h" $cfile "../StringUtils.h" $cfile "../Defines.h" $cfile "../ChatColor.h" $cfile "../ClientHandle.h" $cfile "../Color.h" $cfile "../EffectID.h" $cfile "../Server.h" $cfile "../World.h" $cfile "../Inventory.h" $cfile "../Enchantments.h" $cfile "../Item.h" $cfile "../ItemGrid.h" $cfile "../WebAdmin.h" $cfile "../Root.h" $cfile "../Cuboid.h" $cfile "../BoundingBox.h" $cfile "../BlockArea.h" $cfile "../Generating/ChunkDesc.h" $cfile "../CraftingRecipes.h" $cfile "../UI/Window.h" $cfile "../CompositeChat.h" $cfile "../Map.h" $cfile "../MapManager.h" $cfile "../Scoreboard.h" $cfile "../StatisticsManager.h" $cfile "../Protocol/MojangAPI.h" $cfile "../UUID.h" // Entities: $cfile "../Entities/Entity.h" $cfile "../Entities/EnderCrystal.h" $cfile "../Entities/Boat.h" $cfile "../Entities/Pawn.h" $cfile "../Entities/ProjectileEntity.h" $cfile "../Entities/ArrowEntity.h" $cfile "../Entities/EntityEffect.h" $cfile "../Entities/ExpBottleEntity.h" $cfile "../Entities/ExpOrb.h" $cfile "../Entities/FallingBlock.h" $cfile "../Entities/FireChargeEntity.h" $cfile "../Entities/FireworkEntity.h" $cfile "../Entities/Floater.h" $cfile "../Entities/GhastFireballEntity.h" $cfile "../Entities/HangingEntity.h" $cfile "../Entities/ItemFrame.h" $cfile "../Entities/LeashKnot.h" $cfile "../Entities/Player.h" $cfile "../Entities/Painting.h" $cfile "../Entities/Pickup.h" $cfile "../Entities/SplashPotionEntity.h" $cfile "../Entities/ThrownEggEntity.h" $cfile "../Entities/ThrownEnderPearlEntity.h" $cfile "../Entities/ThrownSnowballEntity.h" $cfile "../Entities/TNTEntity.h" $cfile "../Entities/WitherSkullEntity.h" $cfile "../Mobs/MonsterTypes.h" $cfile "../Mobs/Monster.h" // Block entities: $cfile "../BlockEntities/BlockEntity.h" $cfile "../BlockEntities/BeaconEntity.h" $cfile "../BlockEntities/BedEntity.h" $cfile "../BlockEntities/BlockEntityWithItems.h" $cfile "../BlockEntities/BrewingstandEntity.h" $cfile "../BlockEntities/ChestEntity.h" $cfile "../BlockEntities/CommandBlockEntity.h" $cfile "../BlockEntities/DropSpenserEntity.h" $cfile "../BlockEntities/DispenserEntity.h" $cfile "../BlockEntities/DropperEntity.h" $cfile "../BlockEntities/FurnaceEntity.h" $cfile "../BlockEntities/HopperEntity.h" $cfile "../BlockEntities/JukeboxEntity.h" $cfile "../BlockEntities/NoteEntity.h" $cfile "../BlockEntities/SignEntity.h" $cfile "../BlockEntities/MobHeadEntity.h" $cfile "../BlockEntities/MobSpawnerEntity.h" $cfile "../BlockEntities/FlowerPotEntity.h" // Registries: $cfile "../Registries/CustomStatistics.h" // To avoid tolua treating Byte as a class, and avoid the need to $cfile entire Globals.h: typedef unsigned char Byte; // Aliases $renaming Vector3 @ Vector3d $renaming Vector3 @ Vector3f $renaming Vector3 @ Vector3i ================================================ FILE: src/Bindings/AllToLua.sh ================================================ #!/bin/bash /usr/bin/tolua++ -L BindingsProcessor.lua -o Bindings.cpp -H Bindings.h AllToLua.pkg ================================================ FILE: src/Bindings/AllToLua_lua.bat ================================================ :: AllToLua_Lua.bat :: This scripts updates the automatically-generates Lua bindings in Bindings.cpp / Bindings.h :: When called without any parameters, it will pause for a keypress at the end :: Call with any parameter to disable the wait (for buildserver use) :: This script assumes "lua" executable to be in PATH, it uses a pure-lua implementation of the ToLua processor @echo off :: Regenerate the files: echo Regenerating LUA bindings . . . lua ..\..\lib\tolua++\src\bin\lua\_driver.lua -L BindingsProcessor.lua -o Bindings.cpp -H Bindings.h AllToLua.pkg : Wait for keypress, if no param given: echo. if %ALLTOLUA_WAIT%N == N pause ================================================ FILE: src/Bindings/BindingsProcessor.lua ================================================ -- BindingsProcessor.lua -- Implements additional processing that is done while generating the Lua bindings --[[ The primary purpose of this file is to provide transformations for ToLua - it is loaded by ToLua++ before processing the C++ code. This file can also be used as a standalone Lua program to actually generate the bindings, it invokes ToLua++ if executed by a regular Lua interpreter The transformations implemented: - Modify ToLua++ behavior so that it doesn't generate bindings for private and protected members - Export additional files to be included in cLuaState: - Forward declarations and typedefs for custom classes' pointers - Pushing and popping of bindings' classes To parse DoxyComments, the preprocessor first replaces them with markers and then the parser uses those markers to apply the DoxyComment to the next or previous item in the container, based on the DoxyComment type. Placeholders in use (i = internal ToLua++): - \1 and \2: (i) Embedded Lua code - \3 and \4: (i) Embedded C code ("<>") - \5 and \6: (i) Embedded C code ("{}") - \17 and \18: DoxyComment for next item ("/** ... */") via an ID lookup - \19 and \20: DoxyComment for previous item ("///< ... \n") via an ID lookup --]] --- Invokes the ToLua++ parser -- Called when this script detects it has been run outside of ToLua++'s processing local function invokeToLua() -- The values used by ToLua scripts, normally filled from the cmdline params: flags = { L = "BindingsProcessor.lua", o = "Bindings.cpp", H = "Bindings.h", f = "AllToLua.pkg", -- P = true, -- Prints the structure to stdout, doesn't generate cpp file } _extra_parameters = {} TOLUA_VERSION = "tolua++-1.0.92" TOLUA_LUA_VERSION = "Lua 5.1" -- Path to the ToLua scripts path = "../../lib/tolua++/src/bin/lua/" -- Run the ToLua processing: dofile(path .. "all.lua") end local access = { public = 0, protected = 1, private = 2 } --- Defines classes that have a custom manual Push() implementation and should not generate the automatic one -- Map of classname -> true local g_HasCustomPushImplementation = { cEntity = true, } --- Defines classes that have a custom manual GetStackValue() implementation and should not generate the automatic one -- Map of classname -> true local g_HasCustomGetImplementation = { Vector3d = true, Vector3f = true, Vector3i = true, } --- Array-table of forward DoxyComments that are replaced in preprocess_hook() and substituted back in parser_hook() -- We need to use a lookup table because the comments themselves may contain "//" which the preprocessor -- would eliminate, thus breaking the code -- The "n" member is a counter for faster insertion local g_ForwardDoxyComments = { n = 0 } --- Array-table of backward DoxyComments that are replaced in preprocess_hook() and substituted back in parser_hook() -- We need to use a lookup table because the comments themselves may contain "//" which the preprocessor -- would eliminate, thus breaking the code -- The "n" member is a counter for faster insertion local g_BackwardDoxyComments = { n = 0, } --- Provides extra parsing in addition to ToLua++'s own -- Called by ToLua++ each time it extracts the next piece of code to parse -- a_Code is the string representing the code to be parsed -- The return value is the remaining code to be parsed in the next iteration -- Processes the class access specifiers (public, protected, private), and doxycomments function parser_hook(a_Code) -- Process access-specifying labels (public, private, etc) do local b, e, label = string.find(a_Code, "^%s*(%w*)%s*:[^:]") -- we need to check for [^:], otherwise it would match 'namespace::type' if b then -- Found a label, get the new access value for it: if access[label] then classContainer.curr.curr_member_access = access[label] end -- else ? return strsub(a_Code, e) -- normally we would use 'e + 1', but we need to preserve the [^:] end end -- Process forward DoxyComments: do local b, e, comment = a_Code:find("^%s*(%b\17\18)") if (b) then local curr = classContainer.curr if (curr.n and (curr.n > 0)) then curr[curr.n].next_DoxyComment = g_ForwardDoxyComments[tonumber(comment:sub(2, -2))] else curr.first_child_DoxyComment = g_ForwardDoxyComments[tonumber(comment:sub(2, -2))] end return strsub(a_Code, e + 1) end end -- Process backward DoxyComments: do local b, e, comment = a_Code:find("^%s*(%b\19\20)") if (b) then comment = g_BackwardDoxyComments[tonumber(comment:sub(2, -2))] local currContainer = classContainer.curr if (currContainer.n > 0) then currContainer[currContainer.n].DoxyComment = comment else print("Backward DoxyComment lost in " .. (currContainer.name or currContainer.lname or currContainer.cname or "")) end return strsub(a_Code, e + 1) end end end --- Outputs the helper files supplementing the cLuaState class -- Writes: -- LuaState_Declaration.inc -- LuaState_Implementation.cpp -- LuaState_Typedefs.inc local function OutputLuaStateHelpers(a_Package) -- Collect all class types from ToLua: local types = {} for idx, item in ipairs(a_Package) do local mt = getmetatable(item) or {} if (mt.classtype == "class") then table.insert(types, {name = item.name, lname = item.lname}) end end table.sort(types, function(a_Item1, a_Item2) return (a_Item1.name:lower() < a_Item2.name:lower()) end ) -- Output the typedefs: do local f = assert(io.open("LuaState_Typedefs.inc", "w")) f:write("\n// LuaState_Typedefs.inc\n\n// This file is generated along with the Lua bindings by ToLua. Do not edit manually, do not commit to repo.\n") f:write("// Provides a forward declaration and a typedef for a pointer to each class exported to the Lua API.\n") f:write("\n\n\n\n\n") for _, item in ipairs(types) do if not(item.name:match(".*<.*")) then -- Skip templates altogether -- Classes start with a "c", everything else is a struct: if (item.name:sub(1, 1) == "c") then f:write("class " .. item.name .. ";\n") else f:write("struct " .. item.name .. ";\n") end end end f:write("\n\n\n\n\n") for _, item in ipairs(types) do f:write("typedef " .. item.name .. " * Ptr" .. item.lname .. ";\n") f:write("typedef const " .. item.name .. " * ConstPtr" .. item.lname .. ";\n") end f:write("\n\n\n\n\n") f:close() end -- Output the Push() and GetStackValue() function declarations: do local f = assert(io.open("LuaState_Declaration.inc", "w")) f:write("\n// LuaState_Declaration.inc\n\n// This file is generated along with the Lua bindings by ToLua. Do not edit manually, do not commit to repo.\n") f:write("// Implements a Push() and GetStackValue() function for each class exported to the Lua API.\n") f:write("// This file expects to be included form inside the cLuaState class definition\n") f:write("\n\n\n\n\n") for _, item in ipairs(types) do if not(g_HasCustomPushImplementation[item.lname]) then f:write("void Push(" .. item.name .. " * a_Value);\n") end end for _, item in ipairs(types) do if not(g_HasCustomGetImplementation[item.lname]) then f:write("bool GetStackValue(int a_StackPos, Ptr" .. item.lname .. " & a_ReturnedVal);\n") f:write("bool GetStackValue(int a_StackPos, ConstPtr" .. item.lname .. " & a_ReturnedVal);\n") end end f:write("\n\n\n\n\n") f:close() end -- Output the Push() and GetStackValue() function implementations: do local f = assert(io.open("LuaState_Implementation.cpp", "w")) f:write("\n// LuaState_Implementation.cpp\n\n// This file is generated along with the Lua bindings by ToLua. Do not edit manually, do not commit to repo.\n") f:write("// Implements a Push() and GetStackValue() function for each class exported to the Lua API.\n") f:write("// This file expects to be compiled as a separate translation unit\n") f:write("\n\n\n\n\n") f:write("#include \"Globals.h\"\n#include \"LuaState.h\"\n#include \"tolua++/include/tolua++.h\"\n") f:write("\n\n\n\n\n") for _, item in ipairs(types) do if not(g_HasCustomPushImplementation[item.lname]) then f:write("void cLuaState::Push(" .. item.name .. " * a_Value)\n{\n\tASSERT(IsValid());\n") f:write("\ttolua_pushusertype(m_LuaState, a_Value, \"" .. item.name .. "\");\n"); f:write("}\n\n\n\n\n\n") end end for _, item in ipairs(types) do if not(g_HasCustomGetImplementation[item.lname]) then f:write("bool cLuaState::GetStackValue(int a_StackPos, Ptr" .. item.lname .. " & a_ReturnedVal)\n{\n\tASSERT(IsValid());\n") f:write("\tif (lua_isnil(m_LuaState, a_StackPos))\n\t{\n") f:write("\t\ta_ReturnedVal = nullptr;\n") f:write("\t\treturn false;\n\t}\n") f:write("\ttolua_Error err;\n") f:write("\tif (tolua_isusertype(m_LuaState, a_StackPos, \"" .. item.name .. "\", false, &err))\n") f:write("\t{\n") f:write("\t\ta_ReturnedVal = *(static_cast<" .. item.name .. " **>(lua_touserdata(m_LuaState, a_StackPos)));\n") f:write("\t\treturn true;\n"); f:write("\t}\n") f:write("\treturn false;\n") f:write("}\n\n\n\n\n\n") f:write("bool cLuaState::GetStackValue(int a_StackPos, ConstPtr" .. item.lname .. " & a_ReturnedVal)\n{\n\tASSERT(IsValid());\n") f:write("\tif (lua_isnil(m_LuaState, a_StackPos))\n\t{\n") f:write("\t\ta_ReturnedVal = nullptr;\n") f:write("\t\treturn false;\n\t}\n") f:write("\ttolua_Error err;\n") f:write("\tif (tolua_isusertype(m_LuaState, a_StackPos, \"const " .. item.name .. "\", false, &err))\n") f:write("\t{\n") f:write("\t\ta_ReturnedVal = *(static_cast(lua_touserdata(m_LuaState, a_StackPos)));\n") f:write("\t\treturn true;\n"); f:write("\t}\n") f:write("\treturn false;\n") f:write("}\n\n\n\n\n\n") end end f:close() end end local function FormatString(a_Str) local fmt = string.format("%q", a_Str) return (string.gsub(string.gsub(fmt, "\\\n", "\\n"), "\\\r\n", "\\r\\n")) end local function OutputTable(a_File, a_Table, a_Name, a_Indent, a_Visited, a_Metas) -- Check and update the "visited" status: if (a_Visited[a_Table]) then a_File:write(a_Indent .. "{ \"visited: " .. a_Visited[a_Table] .. "\", }") return end a_Visited[a_Table] = a_Name -- Output the table contents: a_File:write(a_Indent .. "{\n") local indent = a_Indent .. "\t" for k, v in pairs(a_Table) do if (type(k) == "string") then a_File:write(indent .. "[" .. FormatString(k) .. "] =") else a_File:write(indent .. "[" .. tostring(k) .. "] =") end local t = type(v) if ( (t == "number") or (t == "boolean") ) then a_File:write(" ", tostring(v)) elseif (t == "string") then a_File:write(" ", FormatString(v)) elseif (t == "table") then local metatab = getmetatable(v) if (metatab) then a_File:write(" -- meta: " .. tostring(metatab)) a_Metas[metatab] = metatab end a_File:write("\n") OutputTable(a_File, v, a_Name .. "." .. tostring(k), indent, a_Visited, a_Metas) else print("Unhandled type: " .. t .. ": " .. tostring(v)) a_File:write(" ", tostring(v)) end a_File:write(",\n") end -- for k, v - a_Table a_File:write(a_Indent .. "}") end --- Outputs the docs for all the functions in the specified class -- a_File is the output file -- a_Class is the ToLua's classClass object -- a_Functions is a dictionary of function descriptions: "name" -> { {}, ...} local function outputClassFunctionDocs(a_File, a_Class, a_Functions) -- Sort the functions by name: local functions = {} for name, descs in pairs(a_Functions) do table.insert(functions, { Name = name, Descs = descs }) end table.sort(functions, function (a_Fn1, a_Fn2) return (a_Fn1.Name < a_Fn2.Name) end ) -- If there are no functions, bail out: if not(functions[1]) then return end -- Output the descriptions: a_File:write("\t\tFunctions =\n\t\t{\n") for _, fn in ipairs(functions) do local name = fn.Name if (name:sub(1, 1) == ".") then name = "[\"" .. name .. "\"]" end a_File:write("\t\t\t", name, " =\n\t\t\t{\n") for _, desc in ipairs(fn.Descs) do a_File:write("\t\t\t\t{\n\t\t\t\t\tParams =\n\t\t\t\t\t{\n") for _, param in ipairs(desc.Parameters) do a_File:write("\t\t\t\t\t\t{\n") a_File:write("\t\t\t\t\t\t\tType = \"", param.Type, "\",\n") a_File:write("\t\t\t\t\t\t\tName = \"", param.Name, "\",\n") a_File:write("\t\t\t\t\t\t},\n") end a_File:write("\t\t\t\t\t},\n\t\t\t\t\tReturns =\n\t\t\t\t\t{\n") for _, ret in ipairs(desc.Returns) do a_File:write("\t\t\t\t\t\t{\n\t\t\t\t\t\t\tType = \"", ret.Type, "\",\n\t\t\t\t\t\t},\n") end a_File:write("\t\t\t\t\t},\n") if (desc.IsStatic) then a_File:write("\t\t\t\t\tIsStatic = true,\n") end if (desc.DoxyComment) then a_File:write("\t\t\t\t\tDesc = ", string.format("%q", desc.DoxyComment), ",\n") end a_File:write("\t\t\t\t},\n") end a_File:write("\t\t\t},\n") end a_File:write("\t\t},\n") end --- Outputs the docs for all the member variables in the specified class -- a_File is the output file -- a_Class is the ToLua's classClass object -- a_Variables is a dictionary of variable descriptions: "name" -> {} local function outputClassVariableDocs(a_File, a_Class, a_Variables) -- Sort the variables by name: local variables = {} for name, desc in pairs(a_Variables) do table.insert(variables, { Name = name, Desc = desc }) end table.sort(variables, function (a_Var1, a_Var2) return (a_Var1.Name < a_Var2.Name) end ) -- If there are no variables, bail out: if not(variables[1]) then return end -- Output the descriptions: a_File:write("\t\tVariables =\n\t\t{\n") for _, v in ipairs(variables) do a_File:write("\t\t\t", v.Name, " =\n\t\t\t{\n") a_File:write("\t\t\t\tType = \"", v.Desc.Type, "\",\n") if (v.Desc.DoxyComment) then a_File:write("\t\t\t\tDesc = ", string.format("%q", v.Desc.DoxyComment), ",\n") end a_File:write("\t\t\t},\n") end a_File:write("\t\t},\n") end --- Outputs the docs for all the member constants in the specified class -- a_File is the output file -- a_Class is the ToLua's classClass object -- a_Constants is a dictionary of constant descriptions: "name" -> {} -- a_IgnoredConstants is a dictionary of constants not to be exported: "name" -> true (used for ToLua++'s multi-inheritance) local function outputClassConstantDocs(a_File, a_Class, a_Constants, a_IgnoredConstants) -- Sort the constants by name: local constants = {} for name, desc in pairs(a_Constants) do if not(a_IgnoredConstants[name]) then table.insert(constants, { Name = name, Desc = desc }) end end table.sort(constants, function (a_Var1, a_Var2) return (a_Var1.Name < a_Var2.Name) end ) -- If there are no constants, bail out: if not(constants[1]) then return end -- Output the descriptions: a_File:write("\t\tConstants =\n\t\t{\n") for _, con in ipairs(constants) do a_File:write("\t\t\t", con.Name, " =\n\t\t\t{\n") a_File:write("\t\t\t\tType = \"", con.Desc.Type, "\",\n") if (con.Desc.DoxyComment) then a_File:write("\t\t\t\tDesc = ", string.format("%q", con.Desc.DoxyComment), ",\n") end a_File:write("\t\t\t},\n") end a_File:write("\t\t},\n") end --- Outputs the docs for all the member enums in the specified class -- a_File is the output file -- a_Class is the ToLua's classClass object -- a_Enums is an array of ToLua's classEnum objects local function outputClassEnumDocs(a_File, a_Class, a_Enums) -- If there are no enums, bail out: if (not(a_Enums) or not(a_Enums[1])) then return end -- Sort the enums by name: table.sort(a_Enums, function (a_Enum1, a_Enum2) return (a_Enum1.name < a_Enum2.name) end ) -- Output the enums: a_File:write("\t\tEnums =\n\t\t{\n") for i, enum in ipairs(a_Enums) do local name = enum.name if (not(name) or (name == "")) then name = string.format("unnamedEnum_%d", i) end a_File:write("\t\t\t", name, " =\n\t\t\t{\n") local valnames = {} -- Make a copy of enum.lnames so that we can sort it: local idx = 1 for i, valname in ipairs(enum.lnames) do valnames[idx] = { Name = valname, DoxyComment = enum.DoxyComments[i] } idx = idx + 1 end table.sort(valnames, function (a_Val1, a_Val2) return (a_Val1.Name < a_Val2.Name) end ) for _, valname in ipairs(valnames) do assert(not(valname.Name:find("\17"))) assert(not(valname.Name:find("\18"))) assert(not(valname.Name:find("\19"))) assert(not(valname.Name:find("\20"))) a_File:write("\t\t\t\t{\n") a_File:write("\t\t\t\t\tName = \"", valname.Name, "\",\n") if (valname.DoxyComment) then a_File:write("\t\t\t\t\tDesc = ", string.format("%q", valname.DoxyComment), ",\n") end a_File:write("\t\t\t\t},\n") end a_File:write("\t\t\t},\n") end a_File:write("\t\t},\n") end --- Outputs the docs for the specified class, which has been parsed for its functions, variables and constants -- a_Class is the ToLua's classClass object -- a_Functions is a dictionary of function descriptions: "name" -> { {}, ...} -- a_Variables is a dictionary of variable descriptions: "name" -> {} -- a_Constants is a dictionary of constant descriptions: "name" -> {} -- a_Filenames is an array into which the name of the docs file is to be appended local function outputClassDocs(a_Class, a_Functions, a_Variables, a_Constants, a_Filenames) -- Add the output file to list of filenames: local fnam = a_Class.lname .. ".lua" table.insert(a_Filenames, fnam) -- Output the header: local f = assert(io.open("docs/" .. fnam, "w")) f:write("return\n{\n\t", a_Class.lname, " =\n\t{\n") if (a_Class.DoxyComment) then f:write("\t\tDesc = ", string.format("%q", a_Class.DoxyComment), ",\n") end -- If the class inherits from anything, output it here: local ignoredConstants = {} if (a_Class.base and (a_Class.base ~= "")) then local bases = {a_Class.base} local idx = 2 for _, b in ipairs(a_Class.extra_bases or {}) do bases[idx] = b idx = idx + 1 -- ToLua++ handles multiple inheritance by adding "constants" for the base types; ignore those: ignoredConstants["__" .. b .. "__"] = true end table.sort(bases) f:write("\t\tInherits =\n\t\t{\n") for _, b in ipairs(bases) do f:write("\t\t\t", string.format("%q", b), ",\n") end f:write("\t\t},\n") end -- Output the functions: outputClassFunctionDocs(f, a_Class, a_Functions) -- Output the variables: outputClassVariableDocs(f, a_Class, a_Variables) -- Output the constants: outputClassConstantDocs(f, a_Class, a_Constants, ignoredConstants) -- Output the enums: outputClassEnumDocs(f, a_Class, a_Class.enums) -- Output the footer: f:write("\t},\n}\n") f:close() end --- Recursively applies the next_DoxyComment member to the next item, and first_child_DoxyComment to first child item in the container. -- a_Container is the ToLua++'s table potentially containing children as its array members local function applyNextDoxyComments(a_Container) -- Apply the DoxyComment to the first child, if appropriate: if (a_Container[1] and a_Container.first_child_DoxyComment) then a_Container[1].DoxyComment = a_Container.first_child_DoxyComment end -- Apply each child's next_DoxyComment to the actual next child: local i = 1 while (a_Container[i]) do if (a_Container[i].next_DoxyComment) then if (a_Container[i + 1]) then a_Container[i + 1].DoxyComment = a_Container[i].next_DoxyComment end end applyNextDoxyComments(a_Container[i]) i = i + 1 end end --- Generates documentation for a package. local function genPackageDocs(a_Self) -- DEBUG: Output the raw package object: do local f = io.open("docs/_raw.lua", "w") if (f) then OutputTable(f, a_Self, "", "", {}, {}) f:close() end end applyNextDoxyComments(a_Self) -- Generate docs for each member: local i = 1 local filenames = {} while (a_Self[i]) do if ( a_Self[i]:check_public_access() and -- Do not export private and protected members a_Self[i].genDocs ) then a_Self[i]:genDocs(filenames) end i = i + 1 end -- Output the globals' docs: local functions = {} local variables = {} local constants = {} while (a_Self[i]) do if (a_Self[i].genMemberDocs) then a_Self[i]:genMemberDocs(functions, variables, constants) end i = i + 1 end local oldName = a_Self.lname a_Self.lname = "Globals" outputClassDocs(a_Self, functions, variables, constants, filenames) a_Self.lname = oldName -- Output the list of docs files: table.sort(filenames) local f = assert(io.open("docs/_files.lua", "w")) f:write("return\n{\n") for _, fnam in ipairs(filenames) do f:write("\t\"", fnam, "\",\n") end f:write("}\n") f:close() end local function genClassDocs(a_Self, a_Filenames) assert(a_Self.lname) assert(type(a_Filenames) == "table") --[[ print("\n\nGenerating docs for class " .. a_Self.lname) local visited = {[a_Self.parent] = ""} local metas = {} OutputTable(io.stdout, a_Self, a_Self.lname, "", visited, metas) --]] -- Collect the function, variable and constant docs: local i = 1 local functions = {} local variables = {} local constants = {} while (a_Self[i]) do if ( a_Self[i]:check_public_access() and -- Don't export private and protected members a_Self[i].genMemberDocs ) then a_Self[i]:genMemberDocs(functions, variables, constants) end i = i + 1 end -- Output the individual docs outputClassDocs(a_Self, functions, variables, constants, a_Filenames) end --- Parses the specified function's parameters and returns their description as a table -- a_Function is the ToLua's classFunction object local function parseFunctionParameters(a_Function) -- If the only param is a "void", then report no params: if ( a_Function.args and -- The params are present (#(a_Function.args) == 1) and -- There is exactly one param (a_Function.args[1].type == "void") -- The param is a void ) then return {} end local res = {} local idx = 1 for _, param in ipairs(a_Function.args or {}) do local t = param.type t = t:gsub("^const ", "") -- Remove the "const" keyword, if present res[idx] = { Name = param.name, Type = t, IsConst = (param.type:match("^const ") ~= nil), } idx = idx + 1 end return res end --- Parses the specified function's return values and returns their description as a table -- a_Function is the ToLua's classFunction object local function parseFunctionReturns(a_Function) local res = {} local idx = 1 if (a_Function.type and (a_Function.type ~= "void")) then res[idx] = { Type = a_Function.type } idx = idx + 1 end for _, param in ipairs(a_Function.args or {}) do if ((param.mod == "&") or (param.ret == "&")) then res[idx] = { Type = param.type:gsub("^const ", "") } idx = idx + 1 end end return res end local function genFunctionMemberDocs(a_Self, a_Functions, a_Variables, a_Constants) assert(a_Self.lname) local fn = a_Functions[a_Self.lname] or {} a_Functions[a_Self.lname] = fn local desc = { LuaName = a_Self.lname, CType = a_Self.type, DoxyComment = a_Self.DoxyComment, Parameters = parseFunctionParameters(a_Self), Returns = parseFunctionReturns(a_Self), } local _, _, hasStatic = string.find(a_Self.mod, "^%s*(static)") if (hasStatic) then desc.IsStatic = true end table.insert(fn, desc) end local function genVariableMemberDocs(a_Self, a_Functions, a_Variables, a_Constants) assert(a_Self.lname) local desc = { Name = a_Self.lname, Type = a_Self.type, DoxyComment = a_Self.DoxyComment, } if (string.find(a_Self.type,'const%s+') or string.find(a_Self.mod, 'tolua_readonly') or string.find(a_Self.mod, 'tolua_inherits')) then a_Constants[a_Self.lname] = desc else a_Variables[a_Self.lname] = desc end end --- Generates the entire documentation for the API -- a_Package is ToLua++'s classPackage object -- Checks if the documentation folder is writable, if not, skips the docs generation -- Returns true if documentation was generated, false and message if not local function generateDocs(a_Package) -- Check if the docs folder is writable: local f, msg = io.open("docs/_files.lua", "w") if not(f) then return false, "Cannot access the docs folder: " .. msg end f:close() -- Generate the docs: classPackage.genDocs = genPackageDocs classClass.genDocs = genClassDocs classFunction.genMemberDocs = genFunctionMemberDocs classVariable.genMemberDocs = genVariableMemberDocs a_Package:genDocs() return true end --- Outputs the cLuaState helper files. -- Called by ToLua++ before it starts outputting its generated files. -- a_Package is ToLua++'s classPackage object function pre_output_hook(a_Package) OutputLuaStateHelpers(a_Package) -- Generate the documentation: -- (must generate documentation before ToLua++ writes the bindings, because "static" information is lost at that point) local isSuccess, msg = generateDocs(a_Package) if not(isSuccess) then print("API docs haven't been generated due to an error: " .. (msg or "")) else print("API docs have been generated."); end end --- Outputs the documentation files. -- Called by ToLua++ after writing its generated files. -- a_Package is ToLua++'s classPackage object function post_output_hook(a_Package) print("Lua bindings have been generated.") end --- Provides DoxyComment processing while parsing the C++ code. -- Called by ToLua++ parser before it starts parsing the code. -- a_Package is the ToLua++'s classPackage object, currently unparsed -- The C++ code to be parsed is in a_Packade.code function preprocess_hook(a_Package) assert(a_Package) assert(type(a_Package.code) == "string") -- Replace all DoxyComments with placeholders so that they aren't erased later on: a_Package.code = a_Package.code :gsub("/%*%*%s*(.-)%s*%*/", function (a_Comment) local n = g_ForwardDoxyComments.n + 1 g_ForwardDoxyComments[n] = a_Comment g_ForwardDoxyComments.n = n return "\17" .. n .."\18" end ) -- Replace /** ... */ with an ID into a lookup table wrapped in DC1 and DC2 :gsub("///<%s*(.-)%s*\n%s*", function (a_Comment) local n = g_BackwardDoxyComments.n + 1 g_BackwardDoxyComments[n] = a_Comment g_BackwardDoxyComments.n = n return "\19" .. n .."\20\n" end ) -- Replace ///< comments with an ID into a lookup table wrapped in DC3 and DC4 --[[ -- Output the preprocessed code out to a file for manual inspection: local f = io.open("code_out.cpp", "wb") f:write(a_Package.code) f:close() --]] end --- Chooses the smaller of the indices, and the number indicating whether it chose the first or the second -- If one of the indices is nil, returns the other one -- If both indices are nil, returns nil local function chooseNextIndex(a_Index1, a_Index2) if not(a_Index1) then return a_Index2, 2 end if not(a_Index2) then return a_Index1, 1 end if (a_Index1 > a_Index2) then return a_Index2, 2 else return a_Index1, 1 end end --- Override for ToLua++'s own code extraction -- Called for each "$cfile" and "$hfile" directive in the package file -- a_FileName is the C++ header filename -- a_Contents is the code contents of the header file -- The function returns the code to be parsed by ToLua++ -- In addition to the original function, this override extracts all DoxyComments as well -- This is needed when a function is marked with "// tolua_export" but its DoxyComment is not included function extract_code(a_FileName, a_Contents) local code = '\n$#include "' .. a_FileName .. '"\n' a_Contents= "\n" .. a_Contents .. "\n" -- add blank lines as sentinels local _, e, c, t = strfind(a_Contents, "\n([^\n]-)[Tt][Oo][Ll][Uu][Aa]_([^%s]*)[^\n]*\n") local dcb, dce, dc = strfind(a_Contents, "/%*%*.-%*/") local nextEnd, whichOne = chooseNextIndex(e, dce) while (nextEnd) do if (whichOne == 2) then code = code .. a_Contents:sub(dcb, dce) .. "\n" else t = strlower(t) if (t == "begin") then _, nextEnd, c = strfind(a_Contents,"(.-)\n[^\n]*[Tt][Oo][Ll][Uu][Aa]_[Ee][Nn][Dd][^\n]*\n", e) if not(nextEnd) then tolua_error("Unbalanced 'tolua_begin' directive in header file " .. a_FileName) end end code = code .. c .. "\n" end _, e, c, t = strfind(a_Contents, "\n([^\n]-)[Tt][Oo][Ll][Uu][Aa]_([^%s]*)[^\n]*\n", nextEnd) dcb, dce, dc = strfind(a_Contents, "/%*%*.-%*/", nextEnd) nextEnd, whichOne = chooseNextIndex(e, dce) end return code end --- Installs a hook that is called by ToLua++ for each instantiation of classEnumerate -- The hook is used to fix DoxyComments in enums local function installEnumHook() --Hook for normal enums local oldEnumerate = Enumerate Enumerate = function (a_Name, a_Body, a_VarName, a_Type) -- We need to remove the DoxyComment items from the enum -- otherwise ToLua++ parser would make an enum value out of them a_Body = string.gsub(a_Body, ",[%s\n]*}", "\n}") -- eliminate last ',' local t = split(strsub(a_Body, 2, -2), ',') -- eliminate braces local doxyComments = {} local enumValues = {} local numEnumValues = 0 for _, txt in ipairs(t) do txt = txt:gsub("(%b\17\18)", function (a_CommentID) doxyComments[numEnumValues + 1] = g_ForwardDoxyComments[tonumber(a_CommentID:sub(2, -2))] return "" end ):gsub("(%b\19\20)", function (a_CommentID) doxyComments[numEnumValues] = g_BackwardDoxyComments[tonumber(a_CommentID:sub(2, -2))] return "" end ) if (txt ~= "") then numEnumValues = numEnumValues + 1 enumValues[numEnumValues] = txt end end local res = oldEnumerate(a_Name, "{" .. table.concat(enumValues, ",") .. "}", a_VarName, a_Type) res.DoxyComments = doxyComments return res end --Hook for scoped enums local oldScopedEnum = ScopedEnum ScopedEnum = function (a_Name, a_Body, a_VarName, a_Type) -- We need to remove the DoxyComment items from the enum class -- otherwise ToLua++ parser would make an enum value out of them a_Body = string.gsub(a_Body, ",[%s\n]*}", "\n}") -- eliminate last ',' local t = split(strsub(a_Body, 2, -2), ',') -- eliminate braces local doxyComments = {} local enumValues = {} local numEnumValues = 0 for _, txt in ipairs(t) do txt = txt:gsub("(%b\17\18)", function (a_CommentID) doxyComments[numEnumValues + 1] = g_ForwardDoxyComments[tonumber(a_CommentID:sub(2, -2))] return "" end ):gsub("(%b\19\20)", function (a_CommentID) doxyComments[numEnumValues] = g_BackwardDoxyComments[tonumber(a_CommentID:sub(2, -2))] return "" end ) if (txt ~= "") then numEnumValues = numEnumValues + 1 enumValues[numEnumValues] = txt end end local res = oldScopedEnum(a_Name, "{" .. table.concat(enumValues, ",") .. "}", a_VarName, a_Type) res.DoxyComments = doxyComments return res end end if not(TOLUA_VERSION) then -- BindingsProcessor has been called standalone, invoke the entire ToLua++ machinery: print("Generating Lua bindings and docs...") invokeToLua() return else -- We're being executed from inside the ToLua++ parser. Install the needed hooks: installEnumHook() end ================================================ FILE: src/Bindings/BlockState.cpp ================================================ #include "Globals.h" #include "BlockState.h" BlockState::BlockState(): mChecksum(initializeChecksum()) { // Nothing needed yet } BlockState::BlockState(const AString & aKey, const AString & aValue): mState({{aKey, aValue}}), mChecksum(initializeChecksum()) { } BlockState::BlockState(std::initializer_list> aKeysAndValues): mState(aKeysAndValues), mChecksum(initializeChecksum()) { } BlockState::BlockState(const std::map & aKeysAndValues): mState(aKeysAndValues), mChecksum(initializeChecksum()) { } BlockState::BlockState(std::map && aKeysAndValues): mState(std::move(aKeysAndValues)), mChecksum(initializeChecksum()) { } BlockState::BlockState(const BlockState & aCopyFrom, std::initializer_list> aAdditionalKeysAndValues): mState(aCopyFrom.mState) { for (const auto & kav: aAdditionalKeysAndValues) { mState[kav.first] = kav.second; } mChecksum = initializeChecksum(); } BlockState::BlockState(const BlockState & aCopyFrom, const std::map & aAdditionalKeysAndValues): mState(aCopyFrom.mState) { for (const auto & kav: aAdditionalKeysAndValues) { mState[kav.first] = kav.second; } mChecksum = initializeChecksum(); } bool BlockState::operator <(const BlockState & aOther) const { // Fast-return this using checksum if (mChecksum != aOther.mChecksum) { return (mChecksum < aOther.mChecksum); } // Can fast-return this due to how comparison works if (mState.size() != aOther.mState.size()) { return (mState.size() < aOther.mState.size()); } auto itA = mState.begin(); auto itOther = aOther.mState.begin(); // don't need to check itOther, size checks above ensure size(A) == size(O) while (itA != mState.end()) { { const auto cmp = itA->first.compare(itOther->first); if (cmp != 0) { return (cmp < 0); } } { const auto cmp = itA->second.compare(itOther->second); if (cmp != 0) { return (cmp < 0); } } ++itA; ++itOther; } return false; } bool BlockState::operator ==(const BlockState & aOther) const { // Fast-fail if the checksums differ or differrent counts: if ((mChecksum != aOther.mChecksum) || (mState.size() != aOther.mState.size())) { return false; } // Slow-check everything if the checksums match: return std::equal(mState.begin(), mState.end(), aOther.mState.begin()); } const AString & BlockState::value(const AString & aKey) const { auto itr = mState.find(aKey); if (itr == mState.end()) { static AString empty; return empty; } return itr->second; } UInt32 BlockState::initializeChecksum() { removeEmptyKeys(); // Calculate the checksum as a XOR of all mState keys' and values' checksums // This way we don't depend on the std::map's ordering UInt32 res = 0; for (const auto & kv: mState) { auto partial = partialChecksum(kv.first) ^ partialChecksum(kv.second); res = res ^ partial; } return res; } void BlockState::removeEmptyKeys() { for (auto itr = mState.begin(); itr != mState.end();) { if (itr->second.empty()) { itr = mState.erase(itr); } else { ++itr; } } } UInt32 BlockState::partialChecksum(const AString & aString) { UInt32 shift = 0; UInt32 res = 0; for (auto ch: aString) { UInt32 v = static_cast(ch); v = v << shift; shift = (shift + 1) % 24; res = res ^ v; } return res; } ================================================ FILE: src/Bindings/BlockState.h ================================================ #pragma once #include /** Represents the state of a single block (previously known as "block meta"). The state consists of a map of string -> string, plus a mechanism for fast equality checks between two BlockState instances. Once a BlockState instance is created, it is then immutable - there's no way of changing it, only by creating a (modified) copy. A BlockState instance can be created from hard-coded data or from dynamic data: BlockState bs({{"key1", "value1"}, {key2", "value2"}}); // Hard-coded - or - std::map map({{"key1", "value1"}, {key2", "value2"}}); map["key3"] = "value3"; BlockState bs(map); // From dynamic data */ class BlockState { public: /** Creates a new instance with an empty map. */ BlockState(); /** Creates a new instance consisting of a single key-value pair. If the value is empty, it is not stored wihin the map. */ BlockState(const AString & aKey, const AString & aValue); /** Creates a new instance initialized with several (hard-coded) key-value pairs. Any key with an empty value is not stored within the map. */ BlockState(std::initializer_list> aKeysAndValues); /** Creates a new instance initialized with several (dynamic) key-value pairs. Makes a copy of aKeysAndValues for this object. Any key with an empty value is not stored within the map. */ BlockState(const std::map & aKeysAndValues); /** Creates a new instance initialized with several (dynamic) key-value pairs. Any key with an empty value is not stored within the map. */ BlockState(std::map && aKeysAndValues); /** Creates a copy of the specified BlockState with the (hard-coded) additional keys and values added to it. Any key in aAdditionalKeysAndValues that is already present in aCopyFrom is overwritten with the aAdditionalKeysAndValues' one. Any key with an empty value is not stored in the map. (it's possible to erase a key from aCopyFrom by setting it to empty string in aAdditionalKeysAndValues). */ BlockState(const BlockState & aCopyFrom, std::initializer_list> aAdditionalKeysAndValues); /** Creates a copy of the specified BlockState with the (dynamic) additional keys and values added to it. Any key in aAdditionalKeysAndValues that is already present in aCopyFrom is overwritten with the aAdditionalKeysAndValues' one. Any key with an empty value is not stored in the map. (it's possible to erase a key from aCopyFrom by setting it to empty string in aAdditionalKeysAndValues). */ BlockState(const BlockState & aCopyFrom, const std::map & aAdditionalKeysAndValues); /** Less-than comparison. */ bool operator <(const BlockState & aOther) const; /** Fast equality check. */ bool operator ==(const BlockState & aOther) const; /** Fast inequality check. */ bool operator !=(const BlockState & aOther) const { return !(operator ==(aOther)); } /** Returns the value at the specified key. If the key is not present, returns an empty string. */ const AString & value(const AString & aKey) const; protected: /** The state, represented as a string->string map. */ std::map mState; /** The checksum used for the fast equality check. This is calculated upon creation. */ UInt32 mChecksum; /** Normalizes mState and calculates the checksum from it. Removes all the empty values from mState. Used only from constructors. */ UInt32 initializeChecksum(); /** Removes all the keys from mState that have an empty value. */ void removeEmptyKeys(); /** Calculates the partial checksum of a single string. Used from within initializeChecksum(). */ UInt32 partialChecksum(const AString & aString); }; ================================================ FILE: src/Bindings/BlockTypePalette.cpp ================================================ #include "Globals.h" #include "BlockTypePalette.h" #include "json/value.h" #include "JsonUtils.h" /** Returns the index into aString >= aStartIdx at which the next separator occurs. Separator is one of \t, \n or \r. Returns AString::npos if no such separator. */ static size_t findNextSeparator(const AString & aString, size_t aStartIdx = 0) { for (size_t i = aStartIdx, len = aString.length(); i < len; ++i) { switch (aString[i]) { case '\t': case '\n': case '\r': { return i; } } } return AString::npos; } BlockTypePalette::BlockTypePalette(): mMaxIndex(0) { } UInt32 BlockTypePalette::index(const AString & aBlockTypeName, const BlockState & aBlockState) { auto idx = maybeIndex(aBlockTypeName, aBlockState); if (idx.second) { return idx.first; } // Not found, append: auto index = mMaxIndex++; mBlockToNumber[aBlockTypeName][aBlockState] = index; mNumberToBlock[index] = {aBlockTypeName, aBlockState}; return index; } std::pair BlockTypePalette::maybeIndex(const AString & aBlockTypeName, const BlockState & aBlockState) const { auto itr1 = mBlockToNumber.find(aBlockTypeName); if (itr1 == mBlockToNumber.end()) { return {0, false}; } auto itr2 = itr1->second.find(aBlockState); if (itr2 == itr1->second.end()) { return {0, false}; } return {itr2->second, true}; } UInt32 BlockTypePalette::count() const { return static_cast(mNumberToBlock.size()); } const std::pair & BlockTypePalette::entry(UInt32 aIndex) const { auto itr = mNumberToBlock.find(aIndex); if (itr == mNumberToBlock.end()) { throw NoSuchIndexException(aIndex); } return itr->second; } std::map BlockTypePalette::createTransformMapAddMissing(const BlockTypePalette & aFrom) { std::map res; for (const auto & fromEntry: aFrom.mNumberToBlock) { auto fromIndex = fromEntry.first; const auto & blockTypeName = fromEntry.second.first; const auto & blockState = fromEntry.second.second; res[fromIndex] = index(blockTypeName, blockState); } return res; } std::map BlockTypePalette::createTransformMapWithFallback(const BlockTypePalette & aFrom, UInt32 aFallbackIndex) const { std::map res; for (const auto & fromEntry: aFrom.mNumberToBlock) { auto fromIndex = fromEntry.first; const auto & blockTypeName = fromEntry.second.first; const auto & blockState = fromEntry.second.second; auto thisIndex = maybeIndex(blockTypeName, blockState); if (thisIndex.second) { // The entry was found in this res[fromIndex] = thisIndex.first; } else { // The entry was NOT found in this, replace with fallback: res[fromIndex] = aFallbackIndex; } } return res; } void BlockTypePalette::loadFromString(const AString & aString) { static const AString hdrTsvRegular = "BlockTypePalette"; static const AString hdrTsvUpgrade = "UpgradeBlockTypePalette"; // Detect format by checking the header line (none -> JSON): if (aString.substr(0, hdrTsvRegular.length()) == hdrTsvRegular) { return loadFromTsv(aString, false); } else if (aString.substr(0, hdrTsvUpgrade.length()) == hdrTsvUpgrade) { return loadFromTsv(aString, true); } return loadFromJsonString(aString); } void BlockTypePalette::loadFromJsonString(const AString & aJsonPalette) { // Parse the string into JSON object: Json::Value root; std::string errs; if (!JsonUtils::ParseString(aJsonPalette, root, &errs)) { throw LoadFailedException(errs); } // Sanity-check the JSON's structure: if (!root.isObject()) { throw LoadFailedException("Incorrect palette format, expected an object at root."); } // Load the palette: for (auto itr = root.begin(), end = root.end(); itr != end; ++itr) { const auto & blockTypeName = itr.name(); const auto & states = (*itr)["states"]; if (states == Json::Value()) { throw LoadFailedException(fmt::format(FMT_STRING("Missing \"states\" for block type \"{}\""), blockTypeName)); } for (const auto & state: states) { auto id = static_cast(std::stoul(state["id"].asString())); std::map props; if (state.isMember("properties")) { const auto & properties = state["properties"]; if (!properties.isObject()) { throw LoadFailedException(fmt::format(FMT_STRING("Member \"properties\" is not a JSON object (block type \"{}\", id {})."), blockTypeName, id)); } for (const auto & key: properties.getMemberNames()) { props[key] = properties[key].asString(); } } addMapping(id, blockTypeName, props); } } } void BlockTypePalette::loadFromTsv(const AString & aTsvPalette, bool aIsUpgrade) { static const AString hdrTsvRegular = "BlockTypePalette"; static const AString hdrTsvUpgrade = "UpgradeBlockTypePalette"; // Check the file signature: auto idx = findNextSeparator(aTsvPalette); if ((idx == AString::npos) || (aTsvPalette[idx] == '\t')) { throw LoadFailedException("Invalid signature"); } auto signature = aTsvPalette.substr(0, idx); bool isUpgrade = (signature == hdrTsvUpgrade); if (!isUpgrade && (signature != hdrTsvRegular)) { throw LoadFailedException("Unknown signature"); } if (aTsvPalette[idx] == '\r') // CR of the CRLF pair, skip the LF: { idx += 1; } // Parse the header: bool hasHadVersion = false; AString commonPrefix; int line = 2; auto len = aTsvPalette.length(); while (true) { auto keyStart = idx + 1; auto keyEnd = findNextSeparator(aTsvPalette, idx + 1); if (keyEnd == AString::npos) { throw LoadFailedException(fmt::format(FMT_STRING("Invalid header key format on line {}"), line)); } if (keyEnd == idx + 1) // Empty line, end of headers { if (aTsvPalette[keyEnd] == '\r') // CR of the CRLF pair, skip the LF: { ++keyEnd; } idx = keyEnd; ++line; break; } auto valueEnd = findNextSeparator(aTsvPalette, keyEnd + 1); if ((valueEnd == AString::npos) || (aTsvPalette[valueEnd] == '\t')) { throw LoadFailedException(fmt::format(FMT_STRING("Invalid header value format on line {}"), line)); } auto key = aTsvPalette.substr(keyStart, keyEnd - keyStart); if (key == "FileVersion") { unsigned version = 0; auto value = aTsvPalette.substr(keyEnd + 1, valueEnd - keyEnd - 1); if (!StringToInteger(value, version)) { throw LoadFailedException("Invalid FileVersion value"); } else if (version != 1) { throw LoadFailedException(fmt::format(FMT_STRING("Unknown FileVersion: {}. Only version 1 is supported."), version)); } hasHadVersion = true; } else if (key == "CommonPrefix") { commonPrefix = aTsvPalette.substr(keyEnd + 1, valueEnd - keyEnd - 1); } idx = valueEnd; if (aTsvPalette[idx] == '\r') // CR of the CRLF pair, skip the LF: { ++idx; } ++line; } if (!hasHadVersion) { throw LoadFailedException("No FileVersion value"); } // Parse the data: while (idx + 1 < len) { auto lineStart = idx + 1; auto idEnd = findNextSeparator(aTsvPalette, lineStart); if ((idEnd == AString::npos) || (aTsvPalette[idEnd] != '\t')) { throw LoadFailedException(fmt::format(FMT_STRING("Incomplete data on line {} (id)"), line)); } UInt32 id; if (!StringToInteger(aTsvPalette.substr(lineStart, idEnd - lineStart), id)) { throw LoadFailedException(fmt::format(FMT_STRING("Failed to parse id on line {}"), line)); } size_t metaEnd = idEnd; if (isUpgrade) { metaEnd = findNextSeparator(aTsvPalette, idEnd + 1); if ((metaEnd == AString::npos) || (aTsvPalette[metaEnd] != '\t')) { throw LoadFailedException(fmt::format(FMT_STRING("Incomplete data on line {} (meta)"), line)); } UInt32 meta = 0; if (!StringToInteger(aTsvPalette.substr(idEnd + 1, metaEnd - idEnd - 1), meta)) { throw LoadFailedException(fmt::format(FMT_STRING("Failed to parse meta on line {}"), line)); } if (meta > 15) { throw LoadFailedException(fmt::format(FMT_STRING("Invalid meta value on line {}: {}"), line, meta)); } id = (id * 16) | meta; } auto blockTypeEnd = findNextSeparator(aTsvPalette, metaEnd + 1); if (blockTypeEnd == AString::npos) { throw LoadFailedException(fmt::format(FMT_STRING("Incomplete data on line {} (blockTypeName)"), line)); } auto blockTypeName = aTsvPalette.substr(metaEnd + 1, blockTypeEnd - metaEnd - 1); auto blockStateEnd = blockTypeEnd; AStringMap blockState; while (aTsvPalette[blockStateEnd] == '\t') { auto keyEnd = findNextSeparator(aTsvPalette, blockStateEnd + 1); if ((keyEnd == AString::npos) || (aTsvPalette[keyEnd] != '\t')) { throw LoadFailedException(fmt::format(FMT_STRING("Incomplete data on line {} (blockState key)"), line)); } auto valueEnd = findNextSeparator(aTsvPalette, keyEnd + 1); if (valueEnd == AString::npos) { throw LoadFailedException(fmt::format(FMT_STRING("Incomplete data on line {} (blockState value)"), line)); } auto key = aTsvPalette.substr(blockStateEnd + 1, keyEnd - blockStateEnd - 1); auto value = aTsvPalette.substr(keyEnd + 1, valueEnd - keyEnd - 1); blockState[key] = value; blockStateEnd = valueEnd; } addMapping(id, commonPrefix + blockTypeName, std::move(blockState)); ++line; if (aTsvPalette[blockStateEnd] == '\r') // CR of the CRLF pair, skip the LF: { ++blockStateEnd; } idx = blockStateEnd; } } void BlockTypePalette::addMapping(UInt32 aID, const AString & aBlockTypeName, const BlockState & aBlockState) { mNumberToBlock[aID] = {aBlockTypeName, aBlockState}; mBlockToNumber[aBlockTypeName][aBlockState] = aID; if (aID > mMaxIndex) { mMaxIndex = aID; } } ================================================ FILE: src/Bindings/BlockTypePalette.h ================================================ #pragma once #include #include "BlockState.h" /** Holds a palette that maps between block type + state and numbers. Used primarily by PalettedBlockArea to map from stringular block representation to numeric, and by protocols to map from stringular block representation to protocol-numeric. The object itself provides no thread safety, users of this class need to handle locking, if required. Note that the palette itself doesn't support erasing; to erase, create a new instance and re-add only the wanted items. Internally, the object uses two synced maps, one for each translation direction. The palette can be loaded from a string (file). The loader supports either the blocks.json file exported by the vanilla server itself (https://wiki.vg/Data_Generators), or a processed text file generated by our tool $/Tools/BlockTypePaletteGenerator/, or a hand-written text file describing the upgrade from 1.12 BlockType + BlockMeta to 1.13 string representations. The text file is a TSV (tab-separated values), which basically means the data is generally structured as ..., where eol is the platform's CR / CRLF / LF lineend. The file starts with a single value on the first line, "BlockTypePalette" or "UpgradeBlockTypePalette", which is used to detect the file format. The following lines are "headers", simple entries that contain the metadata about the file. "FileVersion" is a compulsory key, "CommonPrefix" is supported, others are ignored. The headers are followed by an empty line (that signalizes the end of headers) and then the actual data. For regular BlockTypePalette TSV file of version 1, the data is in the format: ... For the UpgradeBlockTypePalette TSV file of version 1, the data is in the format: ... If a CommonPrefix header is present, its value is pre-pended to each blockTypeName loaded (thus allowing the file to be overall smaller). */ class BlockTypePalette { public: /** Exception that is thrown if requiesting an index not present in the palette. */ class NoSuchIndexException: public std::runtime_error { using Super = std::runtime_error; public: NoSuchIndexException(UInt32 aIndex): Super(fmt::format(FMT_STRING("No such palette index: {}"), aIndex)) { } }; /** Exception that is thrown when loading the palette fails hard (bad format). */ class LoadFailedException: public std::runtime_error { using Super = std::runtime_error; public: LoadFailedException(const AString & aReason): Super(aReason) { } }; /** Create a new empty instance. */ BlockTypePalette(); /** Returns the index of the specified block type name and state. If the combination is not found, it is added to the palette and the new index is returned. */ UInt32 index(const AString & aBlockTypeName, const BlockState & aBlockState); /** Returns the of the specified block type name and state, if it exists. If the combination is not found, returns . */ std::pair maybeIndex(const AString & aBlockTypeName, const BlockState & aBlockState) const; /** Returns the total number of entries in the palette. */ UInt32 count() const; /** Returns the blockspec represented by the specified palette index. If the index is not valid, throws a NoSuchIndexException. */ const std::pair & entry(UInt32 aIndex) const; /** Returns an index-transform map from aFrom to this (this.entry(idx) == aFrom.entry(res[idx])). Entries from aFrom that are not present in this are added. Used when pasting two areas, to transform the src palette to dst palette. */ std::map createTransformMapAddMissing(const BlockTypePalette & aFrom); /** Returns an index-transform map from aFrom to this (this.entry(idx) == aFrom.entry(res[idx])). Entries from aFrom that are not present in this are assigned the fallback index. Used for protocol block type mapping. */ std::map createTransformMapWithFallback(const BlockTypePalette & aFrom, UInt32 aFallbackIndex) const; /** Loads the palette from the string representation. Throws a LoadFailedException if the loading fails hard (bad string format); but still a part of the data may already be loaded at that point. If the string specifies duplicate entries (either to already existing entries, or to itself), the duplicates replace the current values silently (this allows us to chain multiple files as "overrides". Auto-detects the string format (json / tsv, normal / upgrade palette) and calls the appropriate load function. */ void loadFromString(const AString & aString); protected: /** The mapping from numeric to stringular representation. mNumberToBlock[index] = {"blockTypeName", blockState}. */ std::map> mNumberToBlock; /** The mapping from stringular to numeric representation. mStringToNumber["blockTypeName"][blockState] = index. */ std::unordered_map> mBlockToNumber; /** The maximum index ever used in the maps. Used when adding new entries through the index() call. */ UInt32 mMaxIndex; /** Loads the palette from the JSON representation, https://wiki.vg/Data_Generators Throws a LoadFailedException if the loading fails hard (bad string format); but still a part of the data may already be loaded at that point. See also: loadFromString(). */ void loadFromJsonString(const AString & aJsonPalette); /** Loads the palette from the regular or upgrade TSV representation. aIsUpgrade specifies whether the format is an upgrade TSV (true) or a regular one (false) Throws a LoadFailedException if the loading fails hard (bad string format); but still a part of the data may already be loaded at that point. See also: loadFromString(). */ void loadFromTsv(const AString & aTsvPalette, bool aIsUpgrade); /** Adds a mapping between the numeric and stringular representation into both maps, updates the mMaxIndex, if appropriate. Silently overwrites any previous mapping for the ID, if present, but keeps the old string->id mapping. */ void addMapping(UInt32 aID, const AString & aBlockTypeName, const BlockState & aBlockState); }; ================================================ FILE: src/Bindings/BlockTypeRegistry.cpp ================================================ #include "Globals.h" #include "BlockTypeRegistry.h" //////////////////////////////////////////////////////////////////////////////// // BlockInfo: BlockInfo::BlockInfo( const AString & aPluginName, const AString & aBlockTypeName, std::shared_ptr aHandler, const std::map & aHints, const std::map & aHintCallbacks ): m_PluginName(aPluginName), m_BlockTypeName(aBlockTypeName), m_Handler(std::move(aHandler)), m_Hints(aHints), m_HintCallbacks(aHintCallbacks) { } AString BlockInfo::hintValue( const AString & aHintName, const BlockState & aBlockState ) { // Search the hint callbacks first: auto itrC = m_HintCallbacks.find(aHintName); if (itrC != m_HintCallbacks.end()) { // Hint callback found, use it: return itrC->second(m_BlockTypeName, aBlockState); } // Search the static hints: auto itr = m_Hints.find(aHintName); if (itr != m_Hints.end()) { // Hint found, use it: return itr->second; } // Nothing found, return empty string: return AString(); } void BlockInfo::setHint(const AString & aHintKey, const AString & aHintValue) { m_Hints[aHintKey] = aHintValue; // Warn if the hint is already provided by a callback (aHintValue will be ignored when evaluating the hint): auto itrC = m_HintCallbacks.find(aHintKey); if (itrC != m_HintCallbacks.end()) { LOGINFO("Setting a static hint %s for block type %s, but there's already a callback for that hint. The static hint will be ignored.", aHintKey.c_str(), m_BlockTypeName.c_str() ); } } void BlockInfo::removeHint(const AString & aHintKey) { m_Hints.erase(aHintKey); } //////////////////////////////////////////////////////////////////////////////// // BlockTypeRegistry: void BlockTypeRegistry::registerBlockType( const AString & aPluginName, const AString & aBlockTypeName, std::shared_ptr aHandler, const std::map & aHints, const std::map & aHintCallbacks ) { auto blockInfo = std::make_shared( aPluginName, aBlockTypeName, std::move(aHandler), aHints, aHintCallbacks ); // Check previous registrations: cCSLock lock(m_CSRegistry); auto itr = m_Registry.find(aBlockTypeName); if (itr != m_Registry.end()) { if (itr->second->pluginName() != aPluginName) { throw AlreadyRegisteredException(itr->second, blockInfo); } } // Store the registration: m_Registry[aBlockTypeName] = blockInfo; } std::shared_ptr BlockTypeRegistry::blockInfo(const AString & aBlockTypeName) { cCSLock lock(m_CSRegistry); auto itr = m_Registry.find(aBlockTypeName); if (itr == m_Registry.end()) { return nullptr; } return itr->second; } void BlockTypeRegistry::removeAllByPlugin(const AString & aPluginName) { cCSLock lock(m_CSRegistry); for (auto itr = m_Registry.begin(); itr != m_Registry.end();) { if (itr->second->pluginName() == aPluginName) { itr = m_Registry.erase(itr); } else { ++itr; } } } void BlockTypeRegistry::setBlockTypeHint( const AString & aBlockTypeName, const AString & aHintKey, const AString & aHintValue ) { cCSLock lock(m_CSRegistry); auto blockInfo = m_Registry.find(aBlockTypeName); if (blockInfo == m_Registry.end()) { throw NotRegisteredException(aBlockTypeName, aHintKey, aHintValue); } blockInfo->second->setHint(aHintKey, aHintValue); } void BlockTypeRegistry::removeBlockTypeHint( const AString & aBlockTypeName, const AString & aHintKey ) { cCSLock lock(m_CSRegistry); auto blockInfo = m_Registry.find(aBlockTypeName); if (blockInfo == m_Registry.end()) { return; } blockInfo->second->removeHint(aHintKey); } //////////////////////////////////////////////////////////////////////////////// // BlockTypeRegistry::AlreadyRegisteredException: BlockTypeRegistry::AlreadyRegisteredException::AlreadyRegisteredException( const std::shared_ptr & aPreviousRegistration, const std::shared_ptr & aNewRegistration ) : Super(message(aPreviousRegistration, aNewRegistration)), m_PreviousRegistration(aPreviousRegistration), m_NewRegistration(aNewRegistration) { } AString BlockTypeRegistry::AlreadyRegisteredException::message( const std::shared_ptr & aPreviousRegistration, const std::shared_ptr & aNewRegistration ) { return fmt::format( FMT_STRING("Attempting to register BlockTypeName {} from plugin {}, while it is already registered in plugin {}"), aNewRegistration->blockTypeName(), aNewRegistration->pluginName(), aPreviousRegistration->pluginName() ); } //////////////////////////////////////////////////////////////////////////////// // BlockTypeRegistry::NotRegisteredException: BlockTypeRegistry::NotRegisteredException::NotRegisteredException( const AString & aBlockTypeName, const AString & aHintKey, const AString & aHintValue ): Super(fmt::format( FMT_STRING("Attempting to set a hint of nonexistent BlockTypeName.\n\tBlockTypeName = {}\n\tHintKey = {}\n\tHintValue = {}"), aBlockTypeName, aHintKey, aHintValue )) { } ================================================ FILE: src/Bindings/BlockTypeRegistry.h ================================================ #pragma once #include #include // fwd: class cBlockHandler; class BlockState; /** Complete information about a single block type. The BlockTypeRegistry uses this structure to store the registered information. */ class BlockInfo { public: /** Callback is used to query block hints dynamically, based on the current BlockState. Useful for example for redstone lamps that can be turned on or off. */ using HintCallback = std::function; /** Creates a new instance with the specified BlockTypeName and handler / hints / callbacks. aPluginName specifies the name of the plugin to associate with the block type (to allow unload / reload). */ BlockInfo( const AString & aPluginName, const AString & aBlockTypeName, std::shared_ptr aHandler, const std::map & aHints = std::map(), const std::map & aHintCallbacks = std::map() ); /** Retrieves the value associated with the specified hint for this specific BlockTypeName and BlockState. Queries hint callbacks first, then static hints if a callback doesn't exist. Returns an empty string if hint not found at all. */ AString hintValue( const AString & aHintName, const BlockState & aBlockState ); // Simple getters: const AString & pluginName() const { return m_PluginName; } const AString & blockTypeName() const { return m_BlockTypeName; } std::shared_ptr handler() const { return m_Handler; } /** Sets (creates or updates) a static hint. Hints provided by callbacks are unaffected by this - callbacks are "higher priority", they overwrite anything set here. Logs an info message if the hint is already provided by a hint callback. */ void setHint(const AString & aHintKey, const AString & aHintValue); /** Removes a hint. Silently ignored if the hint hasn't been previously set. */ void removeHint(const AString & aHintKey); private: /** The name of the plugin that registered the block. */ AString m_PluginName; /** The name of the block type, such as "minecraft:redstone_lamp" */ AString m_BlockTypeName; /** The callbacks to call for various interaction. */ std::shared_ptr m_Handler; /** Optional static hints for any subsystem to use, such as "IsSnowable" -> "1". Hint callbacks are of higher priority than m_Hints - if a hint is provided by a m_HintCallback, its value in m_Hints is ignored. */ std::map m_Hints; /** The callbacks for dynamic evaluation of hints, such as "LightValue" -> function(BlockTypeName, BlockState). Hint callbacks are of higher priority than m_Hints - if a hint is provided by a m_HintCallback, its value in m_Hints is ignored. */ std::map m_HintCallbacks; }; /** Stores information on all known block types. Can dynamically add and remove block types. Block types are identified using BlockTypeName. Supports unregistering and re-registering the same type by the same plugin. Stores the name of the plugin that registered the type, for better plugin error messages ("already registered in X") and so that we can unload and reload plugins. */ class BlockTypeRegistry { public: // fwd: class AlreadyRegisteredException; class NotRegisteredException; /** Creates an empty new instance of the block type registry */ BlockTypeRegistry() = default; /** Registers the specified block type. If the block type already exists and the plugin is the same, updates the registration. If the block type already exists and the plugin is different, throws an AlreadyRegisteredException. */ void registerBlockType( const AString & aPluginName, const AString & aBlockTypeName, std::shared_ptr aHandler, const std::map & aHints = std::map(), const std::map & aHintCallbacks = std::map() ); /** Returns the registration information for the specified BlockTypeName. Returns nullptr if BlockTypeName not found. */ std::shared_ptr blockInfo(const AString & aBlockTypeName); /** Removes all registrations done by the specified plugin. */ void removeAllByPlugin(const AString & aPluginName); /** Sets (adds or overwrites) a single Hint value for a BlockType. Throws NotRegisteredException if the BlockTypeName is not registered. */ void setBlockTypeHint( const AString & aBlockTypeName, const AString & aHintKey, const AString & aHintValue ); /** Removes a previously registered single Hint value for a BlockType. Throws NotRegisteredException if the BlockTypeName is not registered. Silently ignored if the Hint hasn't been previously set. */ void removeBlockTypeHint( const AString & aBlockTypeName, const AString & aHintKey ); private: /** The actual block type registry. Maps the BlockTypeName to the BlockInfo instance. */ std::map> m_Registry; /** The CS that protects m_Registry against multithreaded access. */ cCriticalSection m_CSRegistry; }; /** The exception thrown from BlockTypeRegistry::registerBlockType() if the same block type is being registered from a different plugin. */ class BlockTypeRegistry::AlreadyRegisteredException: public std::runtime_error { using Super = std::runtime_error; public: /** Creates a new instance of the exception that provides info on both the original registration and the newly attempted registration that caused the failure. */ AlreadyRegisteredException( const std::shared_ptr & aPreviousRegistration, const std::shared_ptr & aNewRegistration ); // Simple getters: std::shared_ptr previousRegistration() const { return m_PreviousRegistration; } std::shared_ptr newRegistration() const { return m_NewRegistration; } private: std::shared_ptr m_PreviousRegistration; std::shared_ptr m_NewRegistration; /** Returns the general exception message formatted by the two registrations. The output is used when logging. */ static AString message( const std::shared_ptr & aPreviousRegistration, const std::shared_ptr & aNewRegistration ); }; /** The exception thrown from BlockTypeRegistry::setBlockTypeHint() if the block type has not been registered before. */ class BlockTypeRegistry::NotRegisteredException: public std::runtime_error { using Super = std::runtime_error; public: /** Creates a new instance of the exception that provides info on both the original registration and the newly attempted registration that caused the failure. */ NotRegisteredException( const AString & aBlockTypeName, const AString & aHintKey, const AString & aHintValue ); // Simple getters: const AString & blockTypeName() const { return m_BlockTypeName; } private: const AString m_BlockTypeName; }; ================================================ FILE: src/Bindings/CMakeLists.txt ================================================ target_sources( ${CMAKE_PROJECT_NAME} PRIVATE Bindings.cpp DeprecatedBindings.cpp LuaChunkStay.cpp LuaJson.cpp LuaNameLookup.cpp LuaServerHandle.cpp LuaState.cpp LuaState_Implementation.cpp LuaTCPLink.cpp LuaUDPEndpoint.cpp LuaWindow.cpp ManualBindings.cpp ManualBindings_BlockArea.cpp ManualBindings_Network.cpp ManualBindings_RankManager.cpp ManualBindings_World.cpp Plugin.cpp PluginLua.cpp PluginManager.cpp Bindings.h DeprecatedBindings.h LuaChunkStay.h LuaFunctions.h LuaJson.h LuaNameLookup.h LuaServerHandle.h LuaState.h LuaState_Declaration.inc LuaState_Typedefs.inc LuaTCPLink.h LuaUDPEndpoint.h LuaWindow.h ManualBindings.h Plugin.h PluginLua.h PluginManager.h tolua++.h ) ================================================ FILE: src/Bindings/CheckBindingsDependencies.lua ================================================ -- CheckBindingsDependencies.lua -- This script checks whether all files listed in AllToLua.pkg are also in the dependencies for bindings regeneration. -- This script is run as part of the CircleCI tests --- Filenames that should be ignored in the AllToLua.pkg file: -- Dictionary of "filename" -> true for each ignored filename local g_ShouldIgnorePkg = { -- ["../IniFile.h"] = true, } --- Filenames that should be ignored in the CMakeLists.txt file: -- Dictionary of "filename" -> true for each ignored filename local g_ShouldIgnoreCMake = { ["tolua"] = true, ["Bindings/AllToLua.pkg"] = true, ["Bindings/BindingsProcessor.lua"] = true, } --- Returns a sorted list of all files listed in AllToLua.pkg -- The returned table has both an array part (list of files) and a dictionary part ("filename" -> true) local function getAllToLuaPkgFiles() local res = {} for line in io.lines("AllToLua.pkg") do line:gsub("$cfile \"(.+)\"", -- Parse each line with a $cfile directive function (a_FileName) if (g_ShouldIgnorePkg[a_FileName]) then return end -- Normalize the path: AllToLua is relative to src\Bindings -- but the CMake dependencies list is relative to src\ a_FileName, cnt = a_FileName:gsub("%.%./", "") -- If no replacements were done, this entry must point to a file -- inside the Bindings folder; normalize it if cnt == 0 then a_FileName = "Bindings/" .. a_FileName end table.insert(res, a_FileName) res[a_FileName] = true end ) end table.sort(res) return res end --- Returns a sorted list of all files listed as dependencies in CMakeLists.txt -- The returned table has both an array part (list of files) and a dictionary part ("filename" -> true) local function getCMakeListsFiles() local f = assert(io.open("../../CMake/GenerateBindings.cmake", "r")) local contents = f:read("*all") f:close() local res = {} contents:gsub("set%s*(%b())", -- Process each CMake's "set" statement function (a_SetStatement) if not(a_SetStatement:find("%(BINDING_DEPENDENCIES")) then return end -- This is the statement setting the dependencies, parse the files: a_SetStatement:gsub("%s(%S+)%s", function (a_FileName) if (g_ShouldIgnoreCMake[a_FileName]) then return end table.insert(res, a_FileName) res[a_FileName] = true end ) end ) table.sort(res) return res end -- Check each set of files against the other: local pkgFiles = getAllToLuaPkgFiles() local cmakeFiles = getCMakeListsFiles() local numMissingFiles = 0 for _, fnam in ipairs(pkgFiles) do if not(cmakeFiles[fnam]) then io.stderr:write("Bindings dependency file ", fnam, " is not listed in CMake/GenerateBindings.cmake\n") numMissingFiles = numMissingFiles + 1 end end for _, fnam in ipairs(cmakeFiles) do if not(pkgFiles[fnam]) then io.stderr:write("Bindings dependency file ", fnam, " is not listed in src/Bindings/AllToLua.pkg\n") numMissingFiles = numMissingFiles + 1 end end -- If any mismatch was found, exit with an error code: if (numMissingFiles > 0) then io.stderr:write("Bindings dependency mismatches found: ", numMissingFiles, "\n") os.exit(1) end ================================================ FILE: src/Bindings/DeprecatedBindings.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "DeprecatedBindings.h" extern "C" { #include "lua/src/lua.h" #include "lua/src/lauxlib.h" } #undef TOLUA_TEMPLATE_BIND #include "tolua++/include/tolua++.h" #include "../World.h" #include "../Entities/Player.h" #include "LuaState.h" #include "../BlockInfo.h" #include "../BlockEntities/NoteEntity.h" /* get function: g_BlockLightValue */ #ifndef TOLUA_DISABLE_tolua_get_AllToLua_g_BlockLightValue static int tolua_get_AllToLua_g_BlockLightValue(lua_State* tolua_S) { cLuaState LuaState(tolua_S); int BlockType = 0; #ifndef TOLUA_RELEASE { tolua_Error tolua_err; if (!tolua_isnumber(tolua_S, 2, 0, &tolua_err)) { tolua_error(tolua_S, "#vinvalid type in array indexing.", &tolua_err); } } #endif LuaState.GetStackValue(2, BlockType); if ((BlockType < 0) || (BlockType > E_BLOCK_MAX_TYPE_ID)) { tolua_error(tolua_S, "array indexing out of range.", nullptr); } LuaState.Push(cBlockInfo::GetLightValue(static_cast(BlockType))); return 1; } #endif // #ifndef TOLUA_DISABLE /* get function: g_BlockSpreadLightFalloff */ #ifndef TOLUA_DISABLE_tolua_get_AllToLua_g_BlockSpreadLightFalloff static int tolua_get_AllToLua_g_BlockSpreadLightFalloff(lua_State* tolua_S) { cLuaState LuaState(tolua_S); int BlockType = 0; #ifndef TOLUA_RELEASE { tolua_Error tolua_err; if (!tolua_isnumber(tolua_S, 2, 0, &tolua_err)) { tolua_error(tolua_S, "#vinvalid type in array indexing.", &tolua_err); } } #endif LuaState.GetStackValue(2, BlockType); if ((BlockType < 0) || (BlockType > E_BLOCK_MAX_TYPE_ID)) { tolua_error(tolua_S, "array indexing out of range.", nullptr); } LuaState.Push(cBlockInfo::GetSpreadLightFalloff(static_cast(BlockType))); return 1; } #endif // #ifndef TOLUA_DISABLE /* get function: g_BlockTransparent */ #ifndef TOLUA_DISABLE_tolua_get_AllToLua_g_BlockTransparent static int tolua_get_AllToLua_g_BlockTransparent(lua_State* tolua_S) { cLuaState LuaState(tolua_S); int BlockType = 0; #ifndef TOLUA_RELEASE { tolua_Error tolua_err; if (!tolua_isnumber(tolua_S, 2, 0, &tolua_err)) { tolua_error(tolua_S, "#vinvalid type in array indexing.", &tolua_err); } } #endif LuaState.GetStackValue(2, BlockType); if ((BlockType < 0) || (BlockType > E_BLOCK_MAX_TYPE_ID)) { tolua_error(tolua_S, "array indexing out of range.", nullptr); } LuaState.Push(cBlockInfo::IsTransparent(static_cast(BlockType))); return 1; } #endif // #ifndef TOLUA_DISABLE /* get function: g_BlockOneHitDig */ #ifndef TOLUA_DISABLE_tolua_get_AllToLua_g_BlockOneHitDig static int tolua_get_AllToLua_g_BlockOneHitDig(lua_State* tolua_S) { cLuaState LuaState(tolua_S); int BlockType = 0; #ifndef TOLUA_RELEASE { tolua_Error tolua_err; if (!tolua_isnumber(tolua_S, 2, 0, &tolua_err)) { tolua_error(tolua_S, "#vinvalid type in array indexing.", &tolua_err); } } #endif LuaState.GetStackValue(2, BlockType); if ((BlockType < 0) || (BlockType > E_BLOCK_MAX_TYPE_ID)) { tolua_error(tolua_S, "array indexing out of range.", nullptr); } LuaState.Push(cBlockInfo::IsOneHitDig(static_cast(BlockType))); return 1; } #endif // #ifndef TOLUA_DISABLE /* get function: g_BlockPistonBreakable */ #ifndef TOLUA_DISABLE_tolua_get_AllToLua_g_BlockPistonBreakable static int tolua_get_AllToLua_g_BlockPistonBreakable(lua_State* tolua_S) { cLuaState LuaState(tolua_S); int BlockType = 0; #ifndef TOLUA_RELEASE { tolua_Error tolua_err; if (!tolua_isnumber(tolua_S, 2, 0, &tolua_err)) { tolua_error(tolua_S, "#vinvalid type in array indexing.", &tolua_err); } } #endif LuaState.GetStackValue(2, BlockType); if ((BlockType < 0) || (BlockType > E_BLOCK_MAX_TYPE_ID)) { tolua_error(tolua_S, "array indexing out of range.", nullptr); } LuaState.Push(cBlockInfo::IsPistonBreakable(static_cast(BlockType))); return 1; } #endif // #ifndef TOLUA_DISABLE /* get function: g_BlockIsSnowable */ #ifndef TOLUA_DISABLE_tolua_get_AllToLua_g_BlockIsSnowable static int tolua_get_AllToLua_g_BlockIsSnowable(lua_State* tolua_S) { cLuaState LuaState(tolua_S); int BlockType = 0; #ifndef TOLUA_RELEASE { tolua_Error tolua_err; if (!tolua_isnumber(tolua_S, 2, 0, &tolua_err)) { tolua_error(tolua_S, "#vinvalid type in array indexing.", &tolua_err); } } #endif LuaState.GetStackValue(2, BlockType); if ((BlockType < 0) || (BlockType > E_BLOCK_MAX_TYPE_ID)) { tolua_error(tolua_S, "array indexing out of range.", nullptr); } LuaState.Push(cBlockInfo::IsSnowable(static_cast(BlockType))); return 1; } #endif // #ifndef TOLUA_DISABLE /* get function: g_BlockIsSolid */ #ifndef TOLUA_DISABLE_tolua_get_AllToLua_g_BlockIsSolid static int tolua_get_AllToLua_g_BlockIsSolid(lua_State* tolua_S) { cLuaState LuaState(tolua_S); int BlockType = 0; #ifndef TOLUA_RELEASE { tolua_Error tolua_err; if (!tolua_isnumber(tolua_S, 2, 0, &tolua_err)) { tolua_error(tolua_S, "#vinvalid type in array indexing.", &tolua_err); } } #endif LuaState.GetStackValue(2, BlockType); if ((BlockType < 0) || (BlockType > E_BLOCK_MAX_TYPE_ID)) { tolua_error(tolua_S, "array indexing out of range.", nullptr); } LuaState.Push(cBlockInfo::IsSolid(static_cast(BlockType))); return 1; } #endif // #ifndef TOLUA_DISABLE /* get function: g_BlockFullyOccupiesVoxel */ #ifndef TOLUA_DISABLE_tolua_get_AllToLua_g_BlockFullyOccupiesVoxel static int tolua_get_AllToLua_g_BlockFullyOccupiesVoxel(lua_State* tolua_S) { cLuaState LuaState(tolua_S); int BlockType = 0; #ifndef TOLUA_RELEASE { tolua_Error tolua_err; if (!tolua_isnumber(tolua_S, 2, 0, &tolua_err)) { tolua_error(tolua_S, "#vinvalid type in array indexing.", &tolua_err); } } #endif LuaState.GetStackValue(2, BlockType); if ((BlockType < 0) || (BlockType > E_BLOCK_MAX_TYPE_ID)) { tolua_error(tolua_S, "array indexing out of range.", nullptr); } LuaState.Push(cBlockInfo::FullyOccupiesVoxel(static_cast(BlockType))); return 1; } #endif // #ifndef TOLUA_DISABLE /* function: StringToMobType */ static int tolua_AllToLua_StringToMobType00(lua_State* tolua_S) { cLuaState LuaState(tolua_S); #ifndef TOLUA_RELEASE tolua_Error tolua_err; if ( !tolua_iscppstring(tolua_S, 1, 0, &tolua_err) || !tolua_isnoobj(tolua_S, 2, &tolua_err) ) goto tolua_lerror; else #endif { const AString a_MobString = tolua_tocppstring(LuaState, 1, nullptr); eMonsterType MobType = cMonster::StringToMobType(a_MobString); tolua_pushnumber(LuaState, static_cast(MobType)); tolua_pushcppstring(LuaState, a_MobString); } LOGWARNING("Warning in function call 'StringToMobType': StringToMobType() is deprecated. Please use cMonster:StringToMobType()"); LuaState.LogStackTrace(0); return 2; #ifndef TOLUA_RELEASE tolua_lerror: tolua_error(LuaState, "#ferror in function 'StringToMobType'.", &tolua_err); return 0; #endif } static int tolua_cBlockInfo_GetPlaceSound(lua_State * tolua_S) { cLuaState L(tolua_S); if ( !L.CheckParamStaticSelf("cBlockInfo") || !L.CheckParamNumber(2) ) { return 0; } L.Push(""); LOGWARNING("cBlockInfo:GetPlaceSound() is deprecated"); L.LogStackTrace(0); return 1; } static int tolua_get_cItem_m_Lore(lua_State * tolua_S) { // Maintain legacy m_Lore variable as Lore table split by ` (grave-accent) cLuaState L(tolua_S); if (!L.CheckParamSelf("const cItem")) { return 0; } const cItem * Self = nullptr; L.GetStackValue(1, Self); AString LoreString = StringJoin(Self->m_LoreTable, "`"); L.Push(LoreString); LOGWARNING("cItem.m_Lore is deprecated, use cItem.m_LoreTable instead"); L.LogStackTrace(0); return 1; } static int tolua_set_cItem_m_Lore(lua_State * tolua_S) { // Maintain legacy m_Lore variable as Lore table split by ` (grave-accent) cLuaState L(tolua_S); if ( !L.CheckParamSelf("cItem") || !L.CheckParamString(2) ) { return 0; } cItem * Self = nullptr; AString LoreString; L.GetStackValues(1, Self, LoreString); Self->m_LoreTable = StringSplit(LoreString, "`"); LOGWARNING("cItem.m_Lore is deprecated, use cItem.m_LoreTable instead"); L.LogStackTrace(0); return 0; } /** function: cNoteEntity: GetNote */ static int tolua_cNoteEntity_GetPitch(lua_State * tolua_S) { cLuaState LuaState(tolua_S); if ( !LuaState.CheckParamUserType(1, "cNoteEntity") || !LuaState.CheckParamEnd(2) ) { return 0; } cNoteEntity * Self = nullptr; if (!LuaState.GetStackValues(1, Self)) { tolua_error(LuaState, "Failed to read parameters", nullptr); } if (Self == nullptr) { tolua_error(LuaState, "invalid 'self' in function 'GetPitch'", nullptr); } LuaState.Push(Self->GetNote()); LOGWARNING("Warning: 'cNoteEntity:GetPitch' function is deprecated. Please use 'cNoteEntity:GetNote' instead."); LuaState.LogStackTrace(0); return 1; } /** function: cNoteEntity: IncrementNote */ static int tolua_cNoteEntity_IncrementPitch(lua_State * tolua_S) { cLuaState LuaState(tolua_S); if ( !LuaState.CheckParamUserType(1, "cNoteEntity") || !LuaState.CheckParamEnd(2) ) { return 0; } cNoteEntity * Self = nullptr; if (!LuaState.GetStackValues(1, Self)) { tolua_error(LuaState, "Failed to read parameters", nullptr); } if (Self == nullptr) { tolua_error(LuaState, "invalid 'self' in function 'SetPitch'", nullptr); } Self->IncrementNote(); LOGWARNING("Warning: 'cNoteEntity:IncrementPitch' function is deprecated. Please use 'cNoteEntity:IncrementNote' instead."); LuaState.LogStackTrace(0); return 1; } /** function: cNoteEntity: SetNote */ static int tolua_cNoteEntity_SetPitch(lua_State * tolua_S) { cLuaState LuaState(tolua_S); if ( !LuaState.CheckParamUserType(1, "cNoteEntity") || !LuaState.CheckParamNumber(2) || !LuaState.CheckParamEnd(3) ) { return 0; } cNoteEntity * Self = nullptr; int Note = -1; if (!LuaState.GetStackValues(1, Self, Note)) { tolua_error(LuaState, "Failed to read parameters", nullptr); } if (Self == nullptr) { tolua_error(LuaState, "invalid 'self' in function 'SetPitch'", nullptr); } Self->SetNote(static_cast(Note % 25)); LOGWARNING("Warning: 'cNoteEntity:SetPitch' function is deprecated. Please use 'cNoteEntity:SetNote' instead."); LuaState.LogStackTrace(0); return 1; } /** function: cWorld:SetSignLines */ static int tolua_cWorld_SetSignLines(lua_State * tolua_S) { cLuaState LuaState(tolua_S); #ifndef TOLUA_RELEASE if ( !LuaState.CheckParamUserType(1, "cWorld") || !LuaState.CheckParamNumber(2, 4) || !LuaState.CheckParamString(5, 8) || !LuaState.CheckParamUserType(9, "cPlayer") || !LuaState.CheckParamEnd(10) ) return 0; else #endif { cWorld * self = nullptr; cPlayer * Player = nullptr; int BlockX = 0; int BlockY = 0; int BlockZ = 0; AString Line1; AString Line2; AString Line3; AString Line4; LuaState.GetStackValues(1, self, BlockX, BlockY, BlockZ, Line1, Line2, Line3, Line4, Player); #ifndef TOLUA_RELEASE if (self == nullptr) { tolua_error(LuaState, "invalid 'self' in function 'UpdateSign'", nullptr); } #endif { bool res = self->SetSignLines({BlockX, BlockY, BlockZ}, Line1, Line2, Line3, Line4, Player); tolua_pushboolean(LuaState, res ? 1 : 0); } } LOGWARNING("Warning in function call 'UpdateSign': UpdateSign() is deprecated. Please use SetSignLines()"); LuaState.LogStackTrace(0); return 1; } /** Function: cWorld:GrowTree. Exported manually because of the obsolete int-based overload. When removing from DeprecatedBindings, make sure the function is exported automatically. */ static int tolua_cWorld_GrowTree(lua_State * a_LuaState) { cLuaState LuaState(a_LuaState); if (lua_isnumber(LuaState, 2)) { // This is the obsolete signature, warn and translate: LOGWARNING("Warning: cWorld:GrowTree function expects Vector3i-based coords rather than int-based coords. Emulating old-style call."); LuaState.LogStackTrace(0); cWorld * Self = nullptr; int BlockX, BlockY, BlockZ; if (!LuaState.GetStackValues(1, Self, BlockX, BlockY, BlockZ)) { return LuaState.ApiParamError("Failed to read int-based coord parameters"); } LuaState.Push(Self->GrowTree({BlockX, BlockY, BlockZ})); return 1; } // This is the correct signature, execute: cWorld * Self = nullptr; Vector3i BlockPos; if (!LuaState.GetStackValues(1, Self, BlockPos)) { return LuaState.ApiParamError("Failed to read Vector3i-based coord parameters"); } LuaState.Push(Self->GrowTree(BlockPos)); return 1; } /** Function: cWorld:GrowTreeByBiome. Exported manually because of the obsolete int-based overload. When removing from DeprecatedBindings, make sure the function is exported automatically. */ static int tolua_cWorld_GrowTreeByBiome(lua_State * a_LuaState) { cLuaState LuaState(a_LuaState); if (lua_isnumber(LuaState, 2)) { // This is the obsolete signature, warn and translate: LOGWARNING("Warning: cWorld:GrowTreeByBiome function expects Vector3i-based coords rather than int-based coords. Emulating old-style call."); LuaState.LogStackTrace(0); cWorld * Self = nullptr; int BlockX, BlockY, BlockZ; if (!LuaState.GetStackValues(1, Self, BlockX, BlockY, BlockZ)) { return LuaState.ApiParamError("Failed to read int-based coord parameters"); } LuaState.Push(Self->GrowTreeByBiome({BlockX, BlockY, BlockZ})); return 1; } // This is the correct signature, execute: cWorld * Self = nullptr; Vector3i BlockPos; if (!LuaState.GetStackValues(1, Self, BlockPos)) { return LuaState.ApiParamError("Failed to read Vector3i-based coord parameters"); } LuaState.Push(Self->GrowTreeByBiome(BlockPos)); return 1; } /** Function: cWorld:GrowTreeFromSapling. Exported manually because of the obsolete int-based overload and obsolete SaplingMeta parameter. When removing from DeprecatedBindings, make sure the function is exported automatically. */ static int tolua_cWorld_GrowTreeFromSapling(lua_State * a_LuaState) { cLuaState LuaState(a_LuaState); if (lua_isnumber(LuaState, 2)) { // This is the obsolete signature, warn and translate: LOGWARNING("Warning: cWorld:GrowTreeFromSapling function expects Vector3i-based coords rather than int-based coords. Emulating old-style call."); LuaState.LogStackTrace(0); cWorld * Self = nullptr; int BlockX, BlockY, BlockZ; if (!LuaState.GetStackValues(1, Self, BlockX, BlockY, BlockZ)) { return LuaState.ApiParamError("Failed to read int-based coord parameters"); } LuaState.Push(Self->GrowTreeFromSapling({BlockX, BlockY, BlockZ})); return 1; } // This is the correct signature, execute: cWorld * Self = nullptr; Vector3i BlockPos; if (!LuaState.GetStackValues(1, Self, BlockPos)) { return LuaState.ApiParamError("Failed to read Vector3i-based coord parameters"); } if (lua_isnumber(LuaState, 3)) { // There's an extra parameter, the obsolete SaplingMeta LOGWARNING("Warning: cWorld:GrowTreeFromSapling function no longer has the SaplingMeta parameter. Ignoring it now."); LuaState.LogStackTrace(0); } LuaState.Push(Self->GrowTreeFromSapling(BlockPos)); return 1; } /** function: cWorld:SetNextBlockTick */ static int tolua_cWorld_SetNextBlockTick(lua_State * tolua_S) { cLuaState LuaState(tolua_S); if ( !LuaState.CheckParamUserType(1, "cWorld") || !LuaState.CheckParamNumber(2, 4) || !LuaState.CheckParamEnd(5) ) { return 0; } cWorld * Self = nullptr; int BlockX = 0; int BlockY = 0; int BlockZ = 0; if (!LuaState.GetStackValues(1, Self, BlockX, BlockY, BlockZ)) { tolua_error(LuaState, "Failed to read parameters", nullptr); } if (Self == nullptr) { tolua_error(LuaState, "invalid 'self' in function 'SetNextBlockTick'", nullptr); } Self->SetNextBlockToTick({BlockX, BlockY, BlockZ}); LOGWARNING("Warning: 'cWorld:SetNextBlockTick' function is deprecated. Please use 'cWorld:SetNextBlockToTick' instead."); LuaState.LogStackTrace(0); return 1; } void DeprecatedBindings::Bind(lua_State * tolua_S) { tolua_beginmodule(tolua_S, nullptr); tolua_array(tolua_S, "g_BlockLightValue", tolua_get_AllToLua_g_BlockLightValue, nullptr); tolua_array(tolua_S, "g_BlockSpreadLightFalloff", tolua_get_AllToLua_g_BlockSpreadLightFalloff, nullptr); tolua_array(tolua_S, "g_BlockTransparent", tolua_get_AllToLua_g_BlockTransparent, nullptr); tolua_array(tolua_S, "g_BlockOneHitDig", tolua_get_AllToLua_g_BlockOneHitDig, nullptr); tolua_array(tolua_S, "g_BlockPistonBreakable", tolua_get_AllToLua_g_BlockPistonBreakable, nullptr); tolua_array(tolua_S, "g_BlockIsSnowable", tolua_get_AllToLua_g_BlockIsSnowable, nullptr); tolua_array(tolua_S, "g_BlockIsSolid", tolua_get_AllToLua_g_BlockIsSolid, nullptr); tolua_array(tolua_S, "g_BlockFullyOccupiesVoxel", tolua_get_AllToLua_g_BlockFullyOccupiesVoxel, nullptr); tolua_function(tolua_S, "StringToMobType", tolua_AllToLua_StringToMobType00); tolua_beginmodule(tolua_S, "cBlockInfo"); tolua_function(tolua_S, "GetPlaceSound", tolua_cBlockInfo_GetPlaceSound); tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "cItem"); tolua_variable(tolua_S, "m_Lore", tolua_get_cItem_m_Lore, tolua_set_cItem_m_Lore); tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "cNoteEntity"); tolua_function(tolua_S, "GetPitch", tolua_cNoteEntity_GetPitch); tolua_function(tolua_S, "IncrementPitch", tolua_cNoteEntity_IncrementPitch); tolua_function(tolua_S, "SetPitch", tolua_cNoteEntity_SetPitch); tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "cWorld"); tolua_function(tolua_S, "GrowTree", tolua_cWorld_GrowTree); tolua_function(tolua_S, "GrowTreeByBiome", tolua_cWorld_GrowTreeByBiome); tolua_function(tolua_S, "GrowTreeFromSapling", tolua_cWorld_GrowTreeFromSapling); tolua_function(tolua_S, "SetNextBlockTick", tolua_cWorld_SetNextBlockTick); tolua_function(tolua_S, "UpdateSign", tolua_cWorld_SetSignLines); tolua_endmodule(tolua_S); tolua_endmodule(tolua_S); } ================================================ FILE: src/Bindings/DeprecatedBindings.h ================================================ #pragma once struct lua_State; class DeprecatedBindings { public: static void Bind( lua_State* tolua_S); }; ================================================ FILE: src/Bindings/DiffAPIDesc.lua ================================================ -- DiffAPIDesc.lua -- Creates a diff file containing documentation that is available from ToLua++'s doxycomment parsing, but not yet included in APIDesc.lua require("lfs") --- Translation for function names whose representation in APIDesc is different from the one in Docs -- Dictionary of "DocsName" -> "DescName" local g_FunctionNameDocsToDesc = { ["new"] = "constructor", ["delete"] = "destructor", [".add"] = "operator_plus", [".div"] = "operator_div", [".eq"] = "operator_eq", [".mul"] = "operator_mul", [".sub"] = "operator_sub", } --- Translation from C types to Lua types -- Dictionary of "CType" -> "LuaType" local g_CTypeToLuaType = { AString = "string", bool = "boolean", Byte = "number", char = "number", double = "number", float = "number", ForEachChunkProvider = "cWorld", int = "number", size_t = "number", unsigned = "number", ["const AString"] = "string", ["const char*"] = "string", ["std::string"] = "string", ["Vector3"] = "Vector3i", ["Vector3"] = "Vector3f", ["Vector3"] = "Vector3d", } --- Functions that should be ignored -- Dictionary of "FunctionName" -> true for each ignored function local g_IgnoreFunction = { destructor = true, } local function caseInsensitiveCompare(a_Text1, a_Text2) return (a_Text1:lower() < a_Text2:lower()) end --- Loads the APIDesc.lua and its child files, returns the complete description -- Returns a table with Classes and Hooks members, Classes being a dictionary of "ClassName" -> { desc } local function loadAPIDesc() -- Load the main APIDesc.lua file: local apiDescPath = "../../Server/Plugins/APIDump/" local desc = dofile(apiDescPath .. "APIDesc.lua") if not(desc) then error("Failed to load APIDesc") end -- Merge in the information from all files in the Classes subfolder: local classesPath = apiDescPath .. "Classes/" for fnam in lfs.dir(apiDescPath .. "Classes") do if (string.find(fnam, ".*%.lua$")) then local tbls = dofile(classesPath .. fnam) for k, cls in pairs(tbls) do desc.Classes[k] = cls; end end end return desc end --- Loads the API documentation generated by ToLua++'s parser -- Returns a dictionary of "ClassName" -> { docs } local function loadAPIDocs() -- Get the filelist: local files = dofile("docs/_files.lua") if not(files) then error("Failed to load _files.lua from docs") end -- Load the docs from all files, merge into a single dictionary: local res = {} for _, fnam in ipairs(files) do local docs = dofile("docs/" .. fnam) if (docs) then for k, v in pairs(docs) do assert(not(res[k])) -- Do we have a duplicate documentation entry? res[k] = v end end end return res end --- Returns whether the function signature in the description matches the function documentation -- a_FunctionDesc is a single description for a function, as loaded from APIDesc.lua (one item) -- a_FunctionDoc is a single documentation item for a function, as loaded from ToLua++'s parser local function functionDescMatchesDocs(a_FunctionDesc, a_FunctionDoc) -- Check the number of parameters: local numParams = 0 local numOptionalParams = 0 if (not(a_FunctionDesc.Params) or (a_FunctionDesc.Params == "")) then numParams = 0 else for _, Param in pairs(a_FunctionDesc.Params) do numParams = numParams + 1 if Param.IsOptional then numOptionalParams = numOptionalParams + 1 end end end local numDocParams = #(a_FunctionDoc.Params) if ((numDocParams > numParams) or (numDocParams < numParams - numOptionalParams)) then return false end return true end --- Returns an array of function descriptions that are in a_FunctionDocs but are missing from a_FunctionDescs -- a_FunctionDescs is an array of function descriptions, as loaded from APIDesc.lua (normalized into array) -- a_FunctionDocs is an array of function documentation items, as loaded from ToLua++'s parser -- If all descriptions match, nil is returned instead local function listMissingClassSingleFunctionDescs(a_FunctionDescs, a_FunctionDocs) -- For each documentation item, try to find a match in a_FunctionDescs: local res = {} for _, docs in ipairs(a_FunctionDocs) do local hasFound = false for _, desc in ipairs(a_FunctionDescs) do if (functionDescMatchesDocs(desc, docs)) then hasFound = true break end end -- for idx - freeDescs[] if not(hasFound) then table.insert(res, docs) end end -- for docs - a_FunctionDocs[] -- If no result, return nil instead of an empty table: if not(res[1]) then return nil end return res end --- Returns a dict of "FnName" -> { { }, ... } that are documented in a_FunctionDocs but missing from a_FunctionDescs -- If there are no such descriptions, returns nil instead -- a_FunctionDescs is a dict of "FnName" -> { } loaded from APIDesc.lua et al -- may be a single desc or an array of those -- a_FunctionDocs is a dict og "FnName" -> { { }, ... } loaded from ToLua++'s parser local function listMissingClassFunctionDescs(a_FunctionDescs, a_FunctionDocs) -- Match the docs and descriptions for each separate function: local res = {} local hasSome = false a_FunctionDescs = a_FunctionDescs or {} a_FunctionDocs = a_FunctionDocs or {} for fnName, fnDocs in pairs(a_FunctionDocs) do local fnDescName = g_FunctionNameDocsToDesc[fnName] or fnName if not(g_IgnoreFunction[fnDescName]) then local fnDescs = a_FunctionDescs[fnDescName] if not(fnDescs) then -- Function not described at all, insert a dummy empty description for the matching: fnDescs = {} elseif not(fnDescs[1]) then -- Function has a single description, convert it to the same format as multi-overload functions use: fnDescs = { fnDescs } end local missingDocs = listMissingClassSingleFunctionDescs(fnDescs, fnDocs) if (missingDocs) then res[fnName] = missingDocs hasSome = true end end -- not ignored end -- for fnName, fnDocs - a_FunctionDocs[] if not(hasSome) then return nil end return res end --- Returns a dictionary of "SymbolName" -> { } for any variable or constant that is documented but not described -- a_VarConstDescs is an array of variable or constant descriptions, as loaded from APIDesc.lua -- a_VarConstDocs is an array of variable or constant documentation items, as loaded from ToLua++'s parser -- If no symbol is to be returned, returns nil instead local function listMissingClassVarConstDescs(a_VarConstDescs, a_VarConstDocs) -- Match the docs and descriptions for each separate function: local res = {} local hasSome = false a_VarConstDescs = a_VarConstDescs or {} a_VarConstDocs = a_VarConstDocs or {} for symName, symDocs in pairs(a_VarConstDocs) do local symDesc = a_VarConstDescs[symName] if ( not(symDesc) or -- Symbol not described at all not(symDesc.Notes) or -- Non-existent description ( (symDesc.Notes == "") and -- Empty description (type(symDocs.Notes) == "string") and -- Docs has a string ... (symDocs.Notes ~= "") -- ... that is not empty ) ) then res[symName] = symDocs hasSome = true end end if not(hasSome) then return nil end return res end --- Fills a_Missing with descriptions that are documented in a_ClassDocs but missing from a_ClassDesc -- a_ClassDesc is the class' description loaded from APIDesc et al -- a_ClassDocs is the class' documentation loaded from ToLua++'s parser local function listMissingClassDescs(a_ClassName, a_ClassDesc, a_ClassDocs, a_Missing) local missing = { Functions = listMissingClassFunctionDescs(a_ClassDesc.Functions, a_ClassDocs.Functions), Constants = listMissingClassVarConstDescs(a_ClassDesc.Constants, a_ClassDocs.Constants), Variables = listMissingClassVarConstDescs(a_ClassDesc.Variables, a_ClassDocs.Variables), } if ( not(missing.Functions) and not(missing.Constants) and not(missing.Variables) ) then -- Nothing missing, don't add anything return end a_Missing[a_ClassName] = missing end --- Returns a dictionary of "ClassName" -> { { }, ... } of descriptions that are documented in a_Docs but missing from a_Descs -- a_Descs is the descriptions loaded from APIDesc et al -- a_Docs is the documentation loaded from ToLua++'s parser local function findMissingDescs(a_Descs, a_Docs) local descClasses = a_Descs.Classes local res = {} for clsName, clsDocs in pairs(a_Docs) do local clsDesc = descClasses[clsName] or {} listMissingClassDescs(clsName, clsDesc, clsDocs, res) end return res end local function outputTable(a_File, a_Table, a_Indent) -- Extract all indices first: local allIndices = {} for k, _ in pairs(a_Table) do table.insert(allIndices, k) end -- Sort the indices: table.sort(allIndices, function (a_Index1, a_Index2) if (type(a_Index1) == "number") then if (type(a_Index2) == "number") then -- Both indices are numeric, sort by value return (a_Index1 < a_Index2) end -- a_Index2 is non-numeric, always goes after a_Index1 return true end if (type(a_Index2) == "number") then -- a_Index2 is numeric, a_Index1 is not return false end -- Neither index is numeric, use regular string comparison: return caseInsensitiveCompare(tostring(a_Index1), tostring(a_Index2)) end ) -- Output by using the index order: a_File:write(a_Indent, "{\n") local indent = a_Indent .. "\t" for _, index in ipairs(allIndices) do -- Write the index: a_File:write(indent, "[") if (type(index) == "string") then a_File:write(string.format("%q", index)) else a_File:write(index) end a_File:write("] =") -- Write the value: local v = a_Table[index] if (type(v) == "table") then a_File:write("\n") outputTable(a_File, v, indent) elseif (type(v) == "string") then a_File:write(string.format(" %q", v)) else a_File:write(" ", tostring(v)) end a_File:write(",\n") end a_File:write(a_Indent, "}") end --- Returns a description of function params, as used for output -- a_Params is nil or an array of parameters from ToLua++'s parser -- a_ClassMap is a dictionary of "ClassName" -> true for all known classes local function extractParamsForOutput(a_Params, a_ClassMap) if not(a_Params) then return "" end assert(a_ClassMap) local params = {} for _, param in ipairs(a_Params) do local paramType = param.Type or "" paramType = g_CTypeToLuaType[paramType] or paramType -- Translate from C type to Lua type local paramName = param.Name or paramType or "[unknown]" paramName = paramName:gsub("^a_", "") -- Remove the "a_" prefix, if present local idxColon = paramType:find("::") -- Extract children classes and enums within classes local paramTypeAnchor = "" if (idxColon) then paramTypeAnchor = "#" .. paramType:sub(idxColon + 2) paramType = paramType:sub(1, idxColon - 1) end if (a_ClassMap[paramType]) then -- Param type is a class name, make it a link if not(param.Name) then paramName = "{{" .. paramType .. paramTypeAnchor .. "}}" else paramName = "{{" .. paramType .. paramTypeAnchor .. "|" .. paramName .. "}}" end end table.insert(params, paramName) end return table.concat(params, ", ") end --- Returns a single line of function description for output -- a_Desc is the function description -- a_ClassMap is a dictionary of "ClassName" -> true for all known classes local function formatFunctionDesc(a_Docs, a_ClassMap) local staticClause = "" if (a_Docs.IsStatic) then staticClause = "IsStatic = true, " end return string.format("{ Params = %q, Return = %q, %sNotes = %q },\n", extractParamsForOutput(a_Docs.Params, a_ClassMap), extractParamsForOutput(a_Docs.Returns, a_ClassMap), staticClause, (a_Docs.Desc or ""):gsub("%.\n", ". "):gsub("\n", ". "):gsub("%s+", " ") ) end --- Outputs differences in function descriptions into a file -- a_File is the output file -- a_Functions is nil or a dictionary of "FunctionName" -> { { }, ... } -- a_ClassMap is a dictionary of "ClassName" -> true for all known classes local function outputFunctions(a_File, a_Functions, a_ClassMap) assert(a_File) if not(a_Functions) then return end -- Get a sorted array of all function names: local fnNames = {} for fnName, _ in pairs(a_Functions) do table.insert(fnNames, fnName) end table.sort(fnNames, caseInsensitiveCompare) -- Output the function descs: a_File:write("\t\tFunctions =\n\t\t{\n") for _, fnName in ipairs(fnNames) do a_File:write("\t\t\t", g_FunctionNameDocsToDesc[fnName] or fnName, " =") local docs = a_Functions[fnName] if (docs[2]) then -- There are at least two descriptions, use the array format: a_File:write("\n\t\t\t{\n") for _, doc in ipairs(docs) do a_File:write("\t\t\t\t", formatFunctionDesc(doc, a_ClassMap)) end a_File:write("\t\t\t},\n") else -- There's only one description, use the simpler one-line format: a_File:write(" ", formatFunctionDesc(docs[1], a_ClassMap)) end end a_File:write("\t\t},\n") end --- Returns the description of a single variable or constant -- a_Docs is the ToLua++'s documentation of the symbol -- a_ClassMap is a dictionary of "ClassName" -> true for all known classes local function formatVarConstDesc(a_Docs, a_ClassMap) local descType = "" if (a_Docs.Type) then local luaType = g_CTypeToLuaType[a_Docs.Type] or a_Docs.Type if (a_ClassMap[a_Docs.Type]) then descType = string.format("Type = {{%q}}, ", luaType); else descType = string.format("Type = %q, ", luaType); end end return string.format("{ %sNotes = %q },\n", descType, a_Docs.Desc or "") end --- Outputs differences in variables' or constants' descriptions into a file -- a_File is the output file -- a_VarConst is nil or a dictionary of "VariableOrConstantName" -> { } -- a_Header is a string, either "Variables" or "Constants" -- a_ClassMap is a dictionary of "ClassName" -> true for all known classes local function outputVarConst(a_File, a_VarConst, a_Header, a_ClassMap) assert(a_File) assert(type(a_Header) == "string") if not(a_VarConst) then return end -- Get a sorted array of all symbol names: local symNames = {} for symName, _ in pairs(a_VarConst) do table.insert(symNames, symName) end table.sort(symNames, caseInsensitiveCompare) -- Output the symbol descs: a_File:write("\t\t", a_Header, " =\n\t\t{\n") for _, symName in ipairs(symNames) do local docs = a_VarConst[symName] a_File:write("\t\t\t", symName, " = ", formatVarConstDesc(docs, a_ClassMap)) end a_File:write("\t\t},\n") end --- Outputs the diff into a file -- a_Diff is the diff calculated by findMissingDescs() -- The output file is written as a Lua source file formatted to match APIDesc.lua local function outputDiff(a_Diff) -- Sort the classnames: local classNames = {} local classMap = {} for clsName, _ in pairs(a_Diff) do table.insert(classNames, clsName) classMap[clsName] = true end table.sort(classNames, caseInsensitiveCompare) -- Output each class: local f = assert(io.open("APIDiff.lua", "w")) -- outputTable(f, diff, "") f:write("return\n{\n") for _, clsName in ipairs(classNames) do f:write("\t", clsName, " =\n\t{\n") local desc = a_Diff[clsName] outputFunctions(f, desc.Functions, classMap) outputVarConst(f, desc.Variables, "Variables", classMap) outputVarConst(f, desc.Constants, "Constants", classMap) f:write("\t},\n") end f:write("}\n") f:close() end local apiDesc = loadAPIDesc() local apiDocs = loadAPIDocs() local diff = findMissingDescs(apiDesc, apiDocs) outputDiff(diff) print("Diff has been output to file APIDiff.lua.") ================================================ FILE: src/Bindings/LuaChunkStay.cpp ================================================ // LuaChunkStay.cpp // Implements the cLuaChunkStay class representing a cChunkStay binding for plugins, used by cWorld:ChunkStay() Lua API #include "Globals.h" #include "LuaChunkStay.h" #include "PluginLua.h" cLuaChunkStay::cLuaChunkStay() { } bool cLuaChunkStay::AddChunks(const cLuaState::cStackTable & a_ChunkCoordsTable) { // This function is expected to be called just once, with all the coords in a table ASSERT(m_Chunks.empty()); // Add each set of coords: a_ChunkCoordsTable.ForEachArrayElement([=](cLuaState & a_LuaState, int a_Index) { if (!lua_istable(a_LuaState, -1)) { LOGWARNING("%s: Element #%d is not a table (got %s). Ignoring the element.", __FUNCTION__, a_Index, lua_typename(a_LuaState, -1) ); a_LuaState.LogStackTrace(); lua_pop(a_LuaState, 1); return false; } AddChunkCoord(a_LuaState, a_Index); return false; } ); // If there are no chunks, log a warning and return failure: if (m_Chunks.empty()) { LOGWARNING("%s: No valid chunk coords.", __FUNCTION__); a_ChunkCoordsTable.GetLuaState().LogStackTrace(); return false; } // All ok return true; } void cLuaChunkStay::AddChunkCoord(cLuaState & L, int a_Index) { // Check that the element has 2 coords: int NumCoords = luaL_getn(L, -1); if (NumCoords != 2) { LOGWARNING("%s: Element #%d doesn't contain 2 coords (got %d). Ignoring the element.", __FUNCTION__, a_Index, NumCoords ); return; } // Read the two coords from the element: lua_rawgeti(L, -1, 1); lua_rawgeti(L, -2, 2); int ChunkX = luaL_checkint(L, -2); int ChunkZ = luaL_checkint(L, -1); lua_pop(L, 2); // Check that a coord is not yet present: for (cChunkCoordsVector::iterator itr = m_Chunks.begin(), end = m_Chunks.end(); itr != end; ++itr) { if ((itr->m_ChunkX == ChunkX) && (itr->m_ChunkZ == ChunkZ)) { LOGWARNING("%s: Element #%d is a duplicate, ignoring it.", __FUNCTION__, a_Index ); return; } } // for itr - m_Chunks[] m_Chunks.emplace_back(ChunkX, ChunkZ); } void cLuaChunkStay::Enable(cChunkMap & a_ChunkMap, cLuaState::cCallbackPtr a_OnChunkAvailable, cLuaState::cCallbackPtr a_OnAllChunksAvailable) { m_OnChunkAvailable = std::move(a_OnChunkAvailable); m_OnAllChunksAvailable = std::move(a_OnAllChunksAvailable); // Enable the ChunkStay: Super::Enable(a_ChunkMap); } void cLuaChunkStay::OnChunkAvailable(int a_ChunkX, int a_ChunkZ) { if (m_OnChunkAvailable != nullptr) { m_OnChunkAvailable->Call(a_ChunkX, a_ChunkZ); } } bool cLuaChunkStay::OnAllChunksAvailable(void) { if (m_OnAllChunksAvailable != nullptr) { // Call the callback: m_OnAllChunksAvailable->Call(); // Remove the callback references - they won't be needed anymore m_OnChunkAvailable.reset(); m_OnAllChunksAvailable.reset(); } // Disable the ChunkStay by returning true return true; } void cLuaChunkStay::OnDisabled(void) { // This object is no longer needed, delete it delete this; } ================================================ FILE: src/Bindings/LuaChunkStay.h ================================================ // LuaChunkStay.h // Declares the cLuaChunkStay class representing a cChunkStay binding for plugins, used by cWorld:ChunkStay() Lua API #pragma once #include "LuaState.h" #include "../ChunkStay.h" // fwd: class cChunkMap; class cLuaChunkStay: public cChunkStay { using Super = cChunkStay; public: cLuaChunkStay(); virtual ~cLuaChunkStay() override { } /** Adds chunks in the specified Lua table. Can be called only once. Returns true if any chunk added, false (plus log warning) if none. */ bool AddChunks(const cLuaState::cStackTable & a_ChunkCoords); /** Enables the ChunkStay for the specified chunkmap, with the specified Lua callbacks. */ void Enable(cChunkMap & a_ChunkMap, cLuaState::cCallbackPtr a_OnChunkAvailable, cLuaState::cCallbackPtr a_OnAllChunksAvailable); protected: /** The Lua function to call in OnChunkAvailable. Only valid when enabled. */ cLuaState::cCallbackPtr m_OnChunkAvailable; /** The Lua function to call in OnAllChunksAvailable. Only valid when enabled. */ cLuaState::cCallbackPtr m_OnAllChunksAvailable; // cChunkStay overrides: virtual void OnChunkAvailable(int a_ChunkX, int a_ChunkZ) override; virtual bool OnAllChunksAvailable(void) override; virtual void OnDisabled(void) override; /** Adds a single chunk coord from the table at the top of the Lua stack. Expects the top element to be a table, checks that it contains two numbers. Uses those two numbers as chunk coords appended to m_Chunks. If the coords are already present, gives a warning and ignores the pair. The a_Index parameter is only for the error messages. */ void AddChunkCoord(cLuaState & a_LuaState, int a_Index); } ; ================================================ FILE: src/Bindings/LuaFunctions.h ================================================ #pragma once #include // tolua_begin inline unsigned int GetTime() { // NB: For caveats, please see https://stackoverflow.com/a/14505248 return static_cast(std::chrono::seconds(time(nullptr)).count()); } // tolua_end ================================================ FILE: src/Bindings/LuaJson.cpp ================================================ // LuaJson.cpp // Implements the Json exposure bindings to Lua #include "Globals.h" #include #include "LuaJson.h" #include "LuaState.h" #include "tolua++/include/tolua++.h" #include "json/json.h" #include "../JsonUtils.h" // fwd: static void PushJsonValue(const Json::Value & a_Value, cLuaState & a_LuaState); static Json::Value JsonSerializeValue(cLuaState & a_LuaState); /** Exception thrown when the input cannot be serialized. Keeps track of the error message and the problematic value's path in the table. */ class CannotSerializeException: public std::runtime_error { using Super = std::runtime_error; public: /** Constructs a new instance of the exception based on the provided values directly. */ explicit CannotSerializeException(const AString & a_ValueName, const char * a_ErrorMsg): Super(a_ErrorMsg), m_ValueName(a_ValueName) { } /** Constructs a new instance of the exception based on the provided values directly. */ explicit CannotSerializeException(int a_ValueIndex, const char * a_ErrorMsg): Super(a_ErrorMsg), m_ValueName(fmt::format(FMT_STRING("{}"), a_ValueIndex)) { } /** Constructs a new instance of the exception that takes the error message and value name from the parent, and prefix the value name with the specified prefix. Used for prefixing the value name's path along the call stack that lead to the main exception. */ explicit CannotSerializeException(const CannotSerializeException & a_Parent, const AString & a_ValueNamePrefix): Super(a_Parent.what()), m_ValueName(a_ValueNamePrefix + "." + a_Parent.m_ValueName) { } /** Constructs a new instance of the exception that takes the error message and value name from the parent, and prefix the value name with the specified prefix. Used for prefixing the value name's path along the call stack that lead to the main exception. */ explicit CannotSerializeException(const CannotSerializeException & a_Parent, int a_ValueNamePrefixIndex): Super(a_Parent.what()), m_ValueName(fmt::format(FMT_STRING("{}"), a_ValueNamePrefixIndex) + "." + a_Parent.m_ValueName) { } const AString & GetValueName() const { return m_ValueName; } protected: AString m_ValueName; }; /** Pushes the specified Json array as a table on top of the specified Lua state. Assumes that a_Value is an array. */ static void PushJsonArray(const Json::Value & a_Value, cLuaState & a_LuaState) { // Create the appropriately-sized Lua table: lua_createtable(a_LuaState, static_cast(a_Value.size()), 0); // Insert each value to the appropriate index (1-based): int idx = 1; for (const auto & v: a_Value) { // Include Json null values in the array - it will have holes, but indices will stay the same PushJsonValue(v, a_LuaState); lua_rawseti(a_LuaState, -2, idx); idx += 1; } // for v: a_Value[] } /** Pushes the specified Json object as a table on top of the specified Lua state. Assumes that a_Value is an object. */ static void PushJsonObject(const Json::Value & a_Value, cLuaState & a_LuaState) { // Create the appropriately-sized Lua table: lua_createtable(a_LuaState, 0, static_cast(a_Value.size())); // Json::Value has no means of iterating over children with their names included. // We need to iterate over names and "find" them in the object again: auto names = a_Value.getMemberNames(); for (const auto & n: names) { auto v = a_Value[n]; if (v.isNull()) { // Skip null values continue; } // Set the value in Lua's table: a_LuaState.Push(n); PushJsonValue(v, a_LuaState); lua_rawset(a_LuaState, -3); } // for itr - a_Value[] } /** Pushes the specified Json value as an appropriate type on top of the specified Lua state. */ void PushJsonValue(const Json::Value & a_Value, cLuaState & a_LuaState) { switch (a_Value.type()) { case Json::nullValue: { a_LuaState.Push(cLuaState::Nil); break; } case Json::intValue: case Json::uintValue: case Json::realValue: { a_LuaState.Push(static_cast(a_Value.asDouble())); break; } case Json::booleanValue: { a_LuaState.Push(a_Value.asBool()); break; } case Json::stringValue: { a_LuaState.Push(a_Value.asString()); break; } case Json::arrayValue: { PushJsonArray(a_Value, a_LuaState); break; } case Json::objectValue: { PushJsonObject(a_Value, a_LuaState); break; } } // switch (v.type()) } /** Serializes the Lua table at the top of the specified Lua state's stack into a Json value. Lets jsoncpp decides whether to serialize into an object or an array. */ static Json::Value JsonSerializeTable(cLuaState & a_LuaState) { Json::Value res; lua_pushnil(a_LuaState); while (lua_next(a_LuaState, -2) != 0) { if (lua_type(a_LuaState, -2) == LUA_TNUMBER) { int idx; a_LuaState.GetStackValue(-2, idx); try { res[idx - 1] = JsonSerializeValue(a_LuaState); } catch (const CannotSerializeException & exc) { throw CannotSerializeException(exc, idx); } catch (const std::exception & exc) // Cannot catch Json::Exception, because it's not properly defined { throw CannotSerializeException(idx, exc.what()); } } else { AString name; if (a_LuaState.GetStackValue(-2, name)) { try { res[name] = JsonSerializeValue(a_LuaState); } catch (const CannotSerializeException & exc) { throw CannotSerializeException(exc, name); } catch (const std::exception & exc) // Cannot catch Json::Exception, because it's not properly defined { throw CannotSerializeException(name, exc.what()); } } } lua_pop(a_LuaState, 1); } return res; } /** Serializes the Lua value at the top of the specified Lua state into a Json value. */ static Json::Value JsonSerializeValue(cLuaState & a_LuaState) { switch (lua_type(a_LuaState, -1)) { case LUA_TBOOLEAN: { bool v; a_LuaState.GetStackValue(-1, v); return Json::Value(v); } case LUA_TNIL: { return Json::Value(Json::nullValue); } case LUA_TNUMBER: { lua_Number v; a_LuaState.GetStackValue(-1, v); return Json::Value(v); } case LUA_TSTRING: { AString v; a_LuaState.GetStackValue(-1, v); return Json::Value(v); } case LUA_TTABLE: { return JsonSerializeTable(a_LuaState); } default: { LOGD("Attempting to serialize an unhandled Lua value type: %d", lua_type(a_LuaState, -1)); return Json::Value(Json::nullValue); } } } static int tolua_cJson_Parse(lua_State * a_LuaState) { // Function signature: // cJson:Parse("string") -> table // Check the param types: cLuaState L(a_LuaState); if ( !L.CheckParamUserTable(1, "cJson") || !L.CheckParamString(2) || !L.CheckParamEnd(3) ) { return 0; } // Get the input string: AString input; if (!L.GetStackValue(2, input)) { LOGWARNING("cJson:Parse(): Cannot read input string"); L.LogStackTrace(); return 0; } // Parse the string: Json::Value root; AString ParseError; if (!JsonUtils::ParseString(input, root, &ParseError)) { L.Push(cLuaState::Nil, fmt::format(FMT_STRING("Parsing Json failed: {}"), ParseError)); return 2; } // Push the Json value onto Lua stack: PushJsonValue(root, L); return 1; } static int tolua_cJson_Serialize(lua_State * a_LuaState) { // Function signature: // cJson:Serialize({table}, [{option1 = value1, option2 = value2}]) -> string // Check the param types: cLuaState L(a_LuaState); if ( !L.CheckParamUserTable(1, "cJson") || !L.CheckParamTable(2) || !L.CheckParamEnd(4) ) { return 0; } // Push the table to the top of the Lua stack, and call the serializing function: lua_pushvalue(L, 2); Json::Value root; try { root = JsonSerializeValue(L); } catch (const CannotSerializeException & exc) { lua_pushnil(L); L.Push(fmt::format( FMT_STRING("Cannot serialize into Json, value \"{}\" caused an error \"{}\""), exc.GetValueName(), exc.what() )); return 2; } lua_pop(L, 1); // Create the writer, with all properties (optional param 3) applied to it: Json::StreamWriterBuilder builder; if (lua_istable(L, 3)) { lua_pushnil(L); while (lua_next(L, -2) != 0) { if (lua_type(L, -2) == LUA_TSTRING) { AString propName, propValue; if (L.GetStackValues(-2, propName, propValue)) { builder[propName] = propValue; } } lua_pop(L, 1); } // Check for invalid settings: Json::Value invalid; if (!builder.validate(&invalid)) { LOGINFO("cJson:Serialize(): detected invalid settings:"); for (const auto & n: invalid.getMemberNames()) { LOGINFO(" \"%s\" (\"%s\")", n.c_str(), invalid[n].asCString()); } } } auto writer(builder.newStreamWriter()); // Serialize the string and push it as the return value: std::stringstream ss; writer->write(root, &ss); L.Push(ss.str()); return 1; } void cLuaJson::Bind(cLuaState & a_LuaState) { tolua_beginmodule(a_LuaState, nullptr); // Create the cJson API class: tolua_usertype(a_LuaState, "cJson"); tolua_cclass(a_LuaState, "cJson", "cJson", "", nullptr); // Fill in the functions (alpha-sorted): tolua_beginmodule(a_LuaState, "cJson"); tolua_function(a_LuaState, "Parse", tolua_cJson_Parse); tolua_function(a_LuaState, "Serialize", tolua_cJson_Serialize); tolua_endmodule(a_LuaState); tolua_endmodule(a_LuaState); } ================================================ FILE: src/Bindings/LuaJson.h ================================================ // LuaJson.h // Declares the Json exposure bindings to Lua #pragma once // fwd: class cLuaState; class cLuaJson { public: /** Registers the Json library in the specified Lua state. */ static void Bind(cLuaState & a_LuaState); }; ================================================ FILE: src/Bindings/LuaNameLookup.cpp ================================================ // LuaNameLookup.cpp // Implements the cLuaNameLookup class used as the cNetwork API callbacks for name and IP lookups from Lua #include "Globals.h" #include "LuaNameLookup.h" cLuaNameLookup::cLuaNameLookup(const AString & a_Query, cLuaState::cTableRefPtr && a_Callbacks): m_Callbacks(std::move(a_Callbacks)), m_Query(a_Query) { } void cLuaNameLookup::OnNameResolved(const AString & a_Name, const AString & a_IP) { m_Callbacks->CallTableFn("OnNameResolved", a_Name, a_IP); } void cLuaNameLookup::OnError(int a_ErrorCode, const AString & a_ErrorMsg) { m_Callbacks->CallTableFn("OnError", m_Query, a_ErrorCode, a_ErrorMsg); } void cLuaNameLookup::OnFinished(void) { m_Callbacks->CallTableFn("OnFinished", m_Query); } ================================================ FILE: src/Bindings/LuaNameLookup.h ================================================ // LuaNameLookup.h // Declares the cLuaNameLookup class used as the cNetwork API callbacks for name and IP lookups from Lua #pragma once #include "../OSSupport/Network.h" #include "LuaState.h" class cLuaNameLookup: public cNetwork::cResolveNameCallbacks { public: /** Creates a new instance of the lookup callbacks for the specified query, using the callbacks that are in the specified table. */ cLuaNameLookup(const AString & a_Query, cLuaState::cTableRefPtr && a_Callbacks); protected: /** The Lua table that holds the callbacks to be invoked. */ cLuaState::cTableRefPtr m_Callbacks; /** The query used to start the lookup (either hostname or IP). */ AString m_Query; // cNetwork::cResolveNameCallbacks overrides: virtual void OnNameResolved(const AString & a_Name, const AString & a_IP) override; virtual void OnError(int a_ErrorCode, const AString & a_ErrorMsg) override; virtual void OnFinished(void) override; }; ================================================ FILE: src/Bindings/LuaServerHandle.cpp ================================================ // LuaServerHandle.cpp // Implements the cLuaServerHandle class wrapping the cServerHandle functionality for Lua API #include "Globals.h" #include "LuaServerHandle.h" #include "LuaTCPLink.h" #include "tolua++/include/tolua++.h" cLuaServerHandle::cLuaServerHandle(UInt16 a_Port, cLuaState::cTableRefPtr && a_Callbacks): m_Callbacks(std::move(a_Callbacks)), m_Port(a_Port) { } cLuaServerHandle::~cLuaServerHandle() { // If the server handle is still open, close it explicitly: Close(); } void cLuaServerHandle::SetServerHandle(cServerHandlePtr a_ServerHandle, cLuaServerHandlePtr a_Self) { ASSERT(m_ServerHandle == nullptr); // The handle can be set only once m_ServerHandle = std::move(a_ServerHandle); m_Self = std::move(a_Self); } void cLuaServerHandle::Close(void) { // Safely grab a copy of the server handle: cServerHandlePtr ServerHandle = m_ServerHandle; if (ServerHandle == nullptr) { return; } // Close the underlying server handle: ServerHandle->Close(); // Close all connections at this server: cLuaTCPLinkPtrs Connections; { cCSLock Lock(m_CSConnections); std::swap(Connections, m_Connections); } for (auto & conn: Connections) { conn->Close(); } Connections.clear(); // Allow the internal server handle to be deallocated: m_ServerHandle.reset(); } bool cLuaServerHandle::IsListening(void) { // Safely grab a copy of the server handle: cServerHandlePtr ServerHandle = m_ServerHandle; if (ServerHandle == nullptr) { return false; } // Query the underlying server handle: return ServerHandle->IsListening(); } void cLuaServerHandle::RemoveLink(cLuaTCPLink * a_Link) { cCSLock Lock(m_CSConnections); for (auto itr = m_Connections.begin(), end = m_Connections.end(); itr != end; ++itr) { if (itr->get() == a_Link) { m_Connections.erase(itr); break; } } // for itr - m_Connections[] } void cLuaServerHandle::Release(void) { // Close the server, if it isn't closed yet: Close(); // Allow self to deallocate: m_Self.reset(); } cTCPLink::cCallbacksPtr cLuaServerHandle::OnIncomingConnection(const AString & a_RemoteIPAddress, UInt16 a_RemotePort) { // Ask the plugin for link callbacks: cLuaState::cTableRefPtr LinkCallbacks; if ( !m_Callbacks->CallTableFn("OnIncomingConnection", a_RemoteIPAddress, a_RemotePort, m_Port, cLuaState::Return, LinkCallbacks) || !LinkCallbacks->IsValid() ) { LOGINFO("cNetwork server (port %d) OnIncomingConnection callback failed. Dropping connection.", m_Port); return nullptr; } // Create the link wrapper to use with the callbacks: auto res = std::make_shared(std::move(LinkCallbacks), m_Self); // Add the link to the list of our connections: cCSLock Lock(m_CSConnections); m_Connections.push_back(res); return res; } void cLuaServerHandle::OnAccepted(cTCPLink & a_Link) { // Notify the plugin: m_Callbacks->CallTableFn("OnAccepted", static_cast(a_Link.GetCallbacks().get())); } void cLuaServerHandle::OnError(int a_ErrorCode, const AString & a_ErrorMsg) { // Notify the plugin: m_Callbacks->CallTableFn("OnError", a_ErrorCode, a_ErrorMsg); } ================================================ FILE: src/Bindings/LuaServerHandle.h ================================================ // LuaServerHandle.h // Declares the cLuaServerHandle class wrapping the cServerHandle functionality for Lua API #pragma once #include "../OSSupport/Network.h" #include "LuaState.h" // fwd: class cLuaTCPLink; typedef std::shared_ptr cLuaTCPLinkPtr; typedef std::vector cLuaTCPLinkPtrs; class cLuaServerHandle; typedef std::shared_ptr cLuaServerHandlePtr; class cLuaServerHandle: public cNetwork::cListenCallbacks { public: /** Creates a new instance of the server handle, wrapping the (listen-) callbacks that are in the specified table. */ cLuaServerHandle(UInt16 a_Port, cLuaState::cTableRefPtr && a_Callbacks); virtual ~cLuaServerHandle() override; /** Called by cNetwork::Listen()'s binding. Sets the server handle around which this instance is wrapped, and a self SharedPtr for link management. */ void SetServerHandle(cServerHandlePtr a_ServerHandle, cLuaServerHandlePtr a_Self); /** Terminates all connections and closes the listening socket. */ void Close(void); /** Returns true if the server is currently listening. */ bool IsListening(void); /** Removes the link from the list of links that the server is currently tracking. */ void RemoveLink(cLuaTCPLink * a_Link); /** Called when Lua garbage-collects the object. Releases the internal SharedPtr to self, so that the instance may be deallocated. */ void Release(void); protected: /** The Lua table that holds the callbacks to be invoked. */ cLuaState::cTableRefPtr m_Callbacks; /** The port on which the server is listening. Used mainly for better error reporting. */ UInt16 m_Port; /** The cServerHandle around which this instance is wrapped. */ cServerHandlePtr m_ServerHandle; /** Protects m_Connections against multithreaded access. */ cCriticalSection m_CSConnections; /** All connections that are currently active in this server. Protected by m_CSConnections. */ cLuaTCPLinkPtrs m_Connections; /** SharedPtr to self, given out to newly created links. */ cLuaServerHandlePtr m_Self; // cNetwork::cListenCallbacks overrides: virtual cTCPLink::cCallbacksPtr OnIncomingConnection(const AString & a_RemoteIPAddress, UInt16 a_RemotePort) override; virtual void OnAccepted(cTCPLink & a_Link) override; virtual void OnError(int a_ErrorCode, const AString & a_ErrorMsg) override; }; ================================================ FILE: src/Bindings/LuaState.cpp ================================================ // LuaState.cpp // Implements the cLuaState class representing the wrapper over lua_State *, provides associated helper functions #include "Globals.h" #include "LuaState.h" extern "C" { #include "lua/src/lualib.h" } #undef TOLUA_TEMPLATE_BIND #include "tolua++/include/tolua++.h" #include "Bindings.h" #include "ManualBindings.h" #include "DeprecatedBindings.h" #include "LuaJson.h" #include "../Entities/Entity.h" #include "../BlockEntities/BlockEntity.h" #include "../DeadlockDetect.h" #include "../UUID.h" // Hotpatching the Macro to prevent a Clang Warning (0 for pointer used) #undef lua_tostring #define lua_tostring(L, i) lua_tolstring(L, (i), nullptr) // fwd: "SQLite/lsqlite3.cpp" extern "C" { int luaopen_lsqlite3(lua_State * L); } // fwd: "LuaExpat/lxplib.cpp": int luaopen_lxp(lua_State * L); const cLuaState::cRet cLuaState::Return = {}; const cLuaState::cNil cLuaState::Nil = {}; //////////////////////////////////////////////////////////////////////////////// // cCanonLuaStates: /** Tracks the canon cLuaState instances for each lua_State pointer. Used for tracked refs - the ref needs to be tracked by a single cLuaState (the canon state), despite being created from a different (attached) cLuaState. The canon state must be available without accessing the Lua state itself (so it cannot be stored within Lua). */ class cCanonLuaStates { public: /** Returns the canon Lua state for the specified lua_State pointer. */ static cLuaState * GetCanonState(lua_State * a_LuaState) { auto & inst = GetInstance(); cCSLock lock(inst.m_CS); auto itr = inst.m_CanonStates.find(a_LuaState); if (itr == inst.m_CanonStates.end()) { return nullptr; } return itr->second; } /** Adds a new canon cLuaState instance to the map. Used when a new Lua state is created, this informs the map that a new canon Lua state should be tracked. */ static void Add(cLuaState & a_LuaState) { auto & inst = GetInstance(); cCSLock lock(inst.m_CS); ASSERT(inst.m_CanonStates.find(a_LuaState) == inst.m_CanonStates.end()); inst.m_CanonStates[a_LuaState.operator lua_State *()] = &a_LuaState; } /** Removes the bindings between the specified canon state and its lua_State pointer. Used when a Lua state is being closed. */ static void Remove(cLuaState & a_LuaState) { auto & inst = GetInstance(); cCSLock lock(inst.m_CS); auto itr = inst.m_CanonStates.find(a_LuaState); ASSERT(itr != inst.m_CanonStates.end()); inst.m_CanonStates.erase(itr); } protected: /** The mutex protecting m_CanonStates against multithreaded access. */ cCriticalSection m_CS; /** Map of lua_State pointers to their canon cLuaState instances. */ std::map m_CanonStates; /** Returns the singleton instance of this class. */ static cCanonLuaStates & GetInstance(void) { static cCanonLuaStates canonLuaStates; return canonLuaStates; } }; //////////////////////////////////////////////////////////////////////////////// // cLuaStateTracker: void cLuaStateTracker::Add(cLuaState & a_LuaState) { auto & Instance = Get(); cCSLock Lock(Instance.m_CSLuaStates); Instance.m_LuaStates.push_back(&a_LuaState); } void cLuaStateTracker::Del(cLuaState & a_LuaState) { auto & Instance = Get(); cCSLock Lock(Instance.m_CSLuaStates); Instance.m_LuaStates.erase( std::remove_if( Instance.m_LuaStates.begin(), Instance.m_LuaStates.end(), [&a_LuaState](cLuaStatePtr a_StoredLuaState) { return (&a_LuaState == a_StoredLuaState); } ), Instance.m_LuaStates.end() ); } AString cLuaStateTracker::GetStats() { auto & Instance = Get(); cCSLock Lock(Instance.m_CSLuaStates); AString res; int Total = 0; for (auto state: Instance.m_LuaStates) { int Mem = 0; if (!state->Call("collectgarbage", "count", cLuaState::Return, Mem)) { res.append(fmt::format(FMT_STRING("Cannot query memory for state \"{}\"\n"), state->GetSubsystemName())); } else { res.append(fmt::format(FMT_STRING("State \"{}\" is using {} KiB of memory\n"), state->GetSubsystemName(), Mem)); Total += Mem; } } res.append(fmt::format(FMT_STRING("Total memory used by Lua: {} KiB\n"), Total)); return res; } cLuaStateTracker & cLuaStateTracker::Get() { static cLuaStateTracker Inst; // The singleton return Inst; } //////////////////////////////////////////////////////////////////////////////// // cLuaState::cTrackedRef: cLuaState::cTrackedRef::cTrackedRef(void): m_CS(nullptr) { } bool cLuaState::cTrackedRef::RefStack(cLuaState & a_LuaState, int a_StackPos) { // Clear any previous callback: Clear(); // Add self to LuaState's callback-tracking: auto canonState = a_LuaState.QueryCanonLuaState(); canonState->TrackRef(*this); // Store the new callback: m_CS = &(canonState->m_CS); m_Ref.RefStack(*canonState, a_StackPos); return true; } void cLuaState::cTrackedRef::Clear(void) { // Free the reference: lua_State * luaState = nullptr; { auto cs = m_CS.load(); if (cs != nullptr) { cCSLock Lock(*cs); if (!m_Ref.IsValid()) { return; } luaState = m_Ref.GetLuaState(); m_Ref.UnRef(); } } m_CS = nullptr; // Remove from LuaState's callback-tracking: if (luaState == nullptr) { return; } cLuaState(luaState).UntrackRef(*this); } bool cLuaState::cTrackedRef::IsValid(void) { auto cs = m_CS.load(); if (cs == nullptr) { return false; } cCSLock lock(*cs); return m_Ref.IsValid(); } bool cLuaState::cTrackedRef::IsSameLuaState(cLuaState & a_LuaState) { auto cs = m_CS.load(); if (cs == nullptr) { return false; } cCSLock lock(*cs); if (!m_Ref.IsValid()) { return false; } auto canonState = a_LuaState.QueryCanonLuaState(); if (canonState == nullptr) { return false; } return (m_Ref.GetLuaState() == static_cast(*canonState)); } void cLuaState::cTrackedRef::Invalidate(void) { auto cs = m_CS.load(); if (cs == nullptr) { // Already invalid return; } cCSLock Lock(*cs); if (!m_Ref.IsValid()) { LOGD("%s: Inconsistent callback at %p, has a CS but an invalid Ref. This should not happen", __FUNCTION__, static_cast(this) ); return; } m_Ref.UnRef(); m_CS = nullptr; } //////////////////////////////////////////////////////////////////////////////// // cLuaState::cCallback: bool cLuaState::cCallback::RefStack(cLuaState & a_LuaState, int a_StackPos) { // Check if the stack contains a function: if (!lua_isfunction(a_LuaState, a_StackPos)) { return false; } return Super::RefStack(a_LuaState, a_StackPos); } //////////////////////////////////////////////////////////////////////////////// // cLuaState::cOptionalCallback: bool cLuaState::cOptionalCallback::RefStack(cLuaState & a_LuaState, int a_StackPos) { // If the stack pos is nil, make this an empty callback: if (lua_isnil(a_LuaState, a_StackPos)) { Clear(); return true; } // Use default cCallback implementation: return Super::RefStack(a_LuaState, a_StackPos); } //////////////////////////////////////////////////////////////////////////////// // cLuaState::cTableRef: bool cLuaState::cTableRef::RefStack(cLuaState & a_LuaState, int a_StackPos) { // Check if the stack contains a table: if (!lua_istable(a_LuaState, a_StackPos)) { return false; } return Super::RefStack(a_LuaState, a_StackPos); } //////////////////////////////////////////////////////////////////////////////// // cLuaState::cStackTable: cLuaState::cStackTable::cStackTable(cLuaState & a_LuaState, int a_StackPos): m_LuaState(a_LuaState), m_StackPos(a_StackPos) { ASSERT(lua_istable(a_LuaState, a_StackPos)); } void cLuaState::cStackTable::ForEachArrayElement(cFunctionRef a_ElementCallback) const { const auto numElements = luaL_getn(m_LuaState, m_StackPos); [[maybe_unused]] const auto stackTop = lua_gettop(m_LuaState); for (int idx = 1; idx <= numElements; idx++) { // Push the idx-th element of the array onto stack top and call the callback: lua_rawgeti(m_LuaState, m_StackPos, idx); auto shouldAbort = a_ElementCallback(m_LuaState, idx); ASSERT(lua_gettop(m_LuaState) == stackTop + 1); // The element callback must not change the Lua stack below the value lua_pop(m_LuaState, 1); if (shouldAbort) { // The callback wants to abort return; } } } void cLuaState::cStackTable::ForEachElement(cFunctionRef a_ElementCallback) const { [[maybe_unused]] const auto stackTop = lua_gettop(m_LuaState); lua_pushvalue(m_LuaState, m_StackPos); // Stk: lua_pushnil(m_LuaState); // Stk:
    nil while (lua_next(m_LuaState, -2)) // Stk:
    { auto shouldAbort = a_ElementCallback(m_LuaState); ASSERT(lua_gettop(m_LuaState) == stackTop + 3); // The element callback must not change the Lua stack below the value lua_pop(m_LuaState, 1); // Stk:
    if (shouldAbort) { // The callback wants to abort lua_pop(m_LuaState, 2); // Stk: empty return; } } // Stk:
    lua_pop(m_LuaState, 1); // Stk: empty } //////////////////////////////////////////////////////////////////////////////// // cLuaState: cLuaState::cLuaState(const AString & a_SubsystemName) : m_LuaState(nullptr), m_IsOwned(false), m_SubsystemName(a_SubsystemName), m_NumCurrentFunctionArgs(-1) { } cLuaState::cLuaState(lua_State * a_AttachState) : m_LuaState(a_AttachState), m_IsOwned(false), m_SubsystemName(""), m_NumCurrentFunctionArgs(-1) { } cLuaState::~cLuaState() { if (IsValid()) { if (m_IsOwned) { Close(); } else { Detach(); } } } void cLuaState::Create(void) { if (m_LuaState != nullptr) { LOGWARNING("%s: Trying to create an already-existing LuaState, ignoring.", __FUNCTION__); return; } m_LuaState = lua_open(); luaL_openlibs(m_LuaState); m_IsOwned = true; cLuaStateTracker::Add(*this); cCanonLuaStates::Add(*this); } void cLuaState::RegisterAPILibs(void) { auto top = lua_gettop(m_LuaState); tolua_AllToLua_open(m_LuaState); ASSERT(top == lua_gettop(m_LuaState)); cManualBindings::Bind(m_LuaState); ASSERT(top == lua_gettop(m_LuaState)); DeprecatedBindings::Bind(m_LuaState); ASSERT(top == lua_gettop(m_LuaState)); cLuaJson::Bind(*this); ASSERT(top == lua_gettop(m_LuaState)); luaopen_lsqlite3(m_LuaState); if (top == lua_gettop(m_LuaState) - 1) { // lsqlite3 left the "sqlite3" table on the stack, pop it: lua_pop(m_LuaState, 1); } ASSERT(top == lua_gettop(m_LuaState)); luaopen_lxp(m_LuaState); if (top == lua_gettop(m_LuaState) - 1) { // lxp left the unregistered "lxp" table on the stack, register and pop it (#3304): lua_setglobal(m_LuaState, "lxp"); } ASSERT(top == lua_gettop(m_LuaState)); } void cLuaState::Close(void) { if (m_LuaState == nullptr) { LOGWARNING("%s: Trying to close an invalid LuaState, ignoring.", __FUNCTION__); return; } if (!m_IsOwned) { LOGWARNING( "%s: Detected mis-use, calling Close() on an attached state (0x%p). Detaching instead.", __FUNCTION__, static_cast(m_LuaState) ); Detach(); return; } // Invalidate all tracked refs: { cCSLock Lock(m_CSTrackedRefs); for (auto & r: m_TrackedRefs) { r->Invalidate(); } m_TrackedRefs.clear(); } cCanonLuaStates::Remove(*this); cLuaStateTracker::Del(*this); lua_close(m_LuaState); m_LuaState = nullptr; m_IsOwned = false; } void cLuaState::Attach(lua_State * a_State) { if (m_LuaState != nullptr) { LOGINFO("%s: Already contains a LuaState (0x%p), will be closed / detached.", __FUNCTION__, static_cast(m_LuaState)); if (m_IsOwned) { Close(); } else { Detach(); } } m_LuaState = a_State; m_IsOwned = false; } void cLuaState::Detach(void) { if (m_LuaState == nullptr) { return; } if (m_IsOwned) { LOGWARNING( "%s: Detected a mis-use, calling Detach() when the state is owned. Closing the owned state (0x%p).", __FUNCTION__, static_cast(m_LuaState) ); Close(); return; } m_LuaState = nullptr; } void cLuaState::AddPackagePath(const AString & a_PathVariable, const AString & a_Path) { ASSERT_LUA_STACK_BALANCE(m_LuaState); // Get the current path: lua_getfield(m_LuaState, LUA_GLOBALSINDEX, "package"); // Stk: lua_getfield(m_LuaState, -1, a_PathVariable.c_str()); // Stk: size_t len = 0; const char * PackagePath = lua_tolstring(m_LuaState, -1, &len); // Append the new path: AString NewPackagePath(PackagePath, len); NewPackagePath.append(LUA_PATHSEP); NewPackagePath.append(a_Path); // Set the new path to the environment: lua_pop(m_LuaState, 1); // Stk: lua_pushlstring(m_LuaState, NewPackagePath.c_str(), NewPackagePath.length()); // Stk: lua_setfield(m_LuaState, -2, a_PathVariable.c_str()); // Stk: lua_pop(m_LuaState, 1); // Stk: - } bool cLuaState::LoadFile(const AString & a_FileName, bool a_LogWarnings) { ASSERT(IsValid()); ASSERT_LUA_STACK_BALANCE(m_LuaState); // Load the file: int s = luaL_loadfile(m_LuaState, a_FileName.c_str()); if (s != 0) { if (a_LogWarnings) { LOGWARNING("Can't load %s because of a load error in file %s: %d (%s)", m_SubsystemName.c_str(), a_FileName.c_str(), s, lua_tostring(m_LuaState, -1)); } lua_pop(m_LuaState, 1); return false; } // Execute the globals: s = lua_pcall(m_LuaState, 0, 0, 0); if (s != 0) { if (a_LogWarnings) { LOGWARNING("Can't load %s because of an initialization error in file %s: %d (%s)", m_SubsystemName.c_str(), a_FileName.c_str(), s, lua_tostring(m_LuaState, -1)); } lua_pop(m_LuaState, 1); return false; } return true; } bool cLuaState::LoadString(const AString & a_StringToLoad, const AString & a_FileName, bool a_LogWarnings) { ASSERT(IsValid()); ASSERT_LUA_STACK_BALANCE(m_LuaState); // Load the file: int s = luaL_loadstring(m_LuaState, a_StringToLoad.c_str()); if (s != 0) { if (a_LogWarnings) { LOGWARNING("Can't load %s because of a load error in string from \"%s\": %d (%s)", m_SubsystemName.c_str(), a_FileName.c_str(), s, lua_tostring(m_LuaState, -1)); } lua_pop(m_LuaState, 1); return false; } // Execute the globals: s = lua_pcall(m_LuaState, 0, LUA_MULTRET, 0); if (s != 0) { if (a_LogWarnings) { LOGWARNING("Can't load %s because of an initialization error in string from \"%s\": %d (%s)", m_SubsystemName.c_str(), a_FileName.c_str(), s, lua_tostring(m_LuaState, -1)); } lua_pop(m_LuaState, 1); return false; } return true; } bool cLuaState::HasFunction(const char * a_FunctionName) { if (!IsValid()) { // This happens if cPlugin::Initialize() fails with an error return false; } ASSERT_LUA_STACK_BALANCE(m_LuaState); lua_getglobal(m_LuaState, a_FunctionName); bool res = (!lua_isnil(m_LuaState, -1) && lua_isfunction(m_LuaState, -1)); lua_pop(m_LuaState, 1); return res; } bool cLuaState::PushFunction(const char * a_FunctionName) { ASSERT(m_NumCurrentFunctionArgs == -1); // If not, there's already something pushed onto the stack if (!IsValid()) { // This happens if cPlugin::Initialize() fails with an error return false; } // Push the error handler for lua_pcall() lua_pushcfunction(m_LuaState, &ReportFnCallErrors); lua_getglobal(m_LuaState, a_FunctionName); if (!lua_isfunction(m_LuaState, -1)) { LOGWARNING("Error in %s: Could not find function %s()", m_SubsystemName.c_str(), a_FunctionName); lua_pop(m_LuaState, 2); return false; } m_CurrentFunctionName.assign(a_FunctionName); m_NumCurrentFunctionArgs = 0; return true; } bool cLuaState::PushFunction(const cRef & a_FnRef) { ASSERT(IsValid()); ASSERT(m_NumCurrentFunctionArgs == -1); // If not, there's already something pushed onto the stack // Push the error handler for lua_pcall() lua_pushcfunction(m_LuaState, &ReportFnCallErrors); lua_rawgeti(m_LuaState, LUA_REGISTRYINDEX, static_cast(a_FnRef)); // same as lua_getref() if (!lua_isfunction(m_LuaState, -1)) { lua_pop(m_LuaState, 2); return false; } m_CurrentFunctionName = ""; m_NumCurrentFunctionArgs = 0; return true; } bool cLuaState::PushFunction(const cRef & a_TableRef, const char * a_FnName) { ASSERT(IsValid()); ASSERT(m_NumCurrentFunctionArgs == -1); // If not, there's already something pushed onto the stack if (!a_TableRef.IsValid()) { return false; } // Push the error handler for lua_pcall() lua_pushcfunction(m_LuaState, &ReportFnCallErrors); // Get the function from the table: lua_rawgeti(m_LuaState, LUA_REGISTRYINDEX, static_cast(a_TableRef)); if (!lua_istable(m_LuaState, -1)) { // Not a table, bail out lua_pop(m_LuaState, 2); return false; } lua_getfield(m_LuaState, -1, a_FnName); if (lua_isnil(m_LuaState, -1) || !lua_isfunction(m_LuaState, -1)) { // Not a valid function, bail out lua_pop(m_LuaState, 3); return false; } // Pop the table off the stack: lua_remove(m_LuaState, -2); m_CurrentFunctionName = fmt::format(FMT_STRING(""), a_FnName); m_NumCurrentFunctionArgs = 0; return true; } void cLuaState::Push(const AString & a_String) { ASSERT(IsValid()); lua_pushlstring(m_LuaState, a_String.data(), a_String.size()); } void cLuaState::Push(const AStringMap & a_Dictionary) { ASSERT(IsValid()); lua_createtable(m_LuaState, 0, static_cast(a_Dictionary.size())); int newTable = lua_gettop(m_LuaState); for (const auto & item: a_Dictionary) { Push(item.first); // key Push(item.second); // value lua_rawset(m_LuaState, newTable); } } void cLuaState::Push(const AStringVector & a_Vector) { ASSERT(IsValid()); lua_createtable(m_LuaState, static_cast(a_Vector.size()), 0); int newTable = lua_gettop(m_LuaState); int index = 1; for (AStringVector::const_iterator itr = a_Vector.begin(), end = a_Vector.end(); itr != end; ++itr, ++index) { Push(*itr); lua_rawseti(m_LuaState, newTable, index); } } void cLuaState::Push(const char * a_Value) { ASSERT(IsValid()); tolua_pushstring(m_LuaState, a_Value); } void cLuaState::Push(const cItem & a_Item) { ASSERT(IsValid()); auto c = new cItem(a_Item); tolua_pushusertype_and_takeownership(m_LuaState, c, "cItem"); } void cLuaState::Push(const cNil & a_Nil) { ASSERT(IsValid()); lua_pushnil(m_LuaState); } void cLuaState::Push(const cLuaState::cRef & a_Ref) { ASSERT(IsValid()); lua_rawgeti(m_LuaState, LUA_REGISTRYINDEX, static_cast(a_Ref)); } void cLuaState::Push(const ContiguousByteBufferView a_Data) { ASSERT(IsValid()); lua_pushlstring(m_LuaState, reinterpret_cast(a_Data.data()), a_Data.size()); } void cLuaState::Push(const Vector3d & a_Vector) { ASSERT(IsValid()); auto c = new Vector3d(a_Vector); tolua_pushusertype_and_takeownership(m_LuaState, c, "Vector3"); } void cLuaState::Push(const Vector3i & a_Vector) { ASSERT(IsValid()); auto c = new Vector3i(a_Vector); tolua_pushusertype_and_takeownership(m_LuaState, c, "Vector3"); } void cLuaState::Push(bool a_Value) { ASSERT(IsValid()); tolua_pushboolean(m_LuaState, a_Value ? 1 : 0); } void cLuaState::Push(const cEntity * a_Entity) { // Once we can make Lua understand constness, this function shall receive a corresponding function body Push(const_cast(a_Entity)); } void cLuaState::Push(cEntity * a_Entity) { ASSERT(IsValid()); if (a_Entity == nullptr) { lua_pushnil(m_LuaState); } else { const char * ClassName = [&] { switch (a_Entity->GetEntityType()) { case cEntity::etBoat: return "cBoat"; case cEntity::etExpOrb: return "cExpOrb"; case cEntity::etFallingBlock: return "cFallingBlock"; case cEntity::etFloater: return "cFloater"; case cEntity::etItemFrame: return "cItemFrame"; case cEntity::etLeashKnot: return "cLeashKnot"; case cEntity::etPainting: return "cPainting"; case cEntity::etPickup: return "cPickup"; case cEntity::etPlayer: return "cPlayer"; case cEntity::etTNT: return "cTNTEntity"; case cEntity::etMonster: { // Don't push specific mob types, as those are not exported in the API: return "cMonster"; } case cEntity::etProjectile: { // Push the specific projectile type: return a_Entity->GetClass(); } case cEntity::etEntity: case cEntity::etEnderCrystal: case cEntity::etMinecart: { // Push the generic entity class type: return "cEntity"; } } // switch (EntityType) UNREACHABLE("Unsupported entity type"); }(); tolua_pushusertype(m_LuaState, a_Entity, ClassName); } } void cLuaState::Push(cLuaServerHandle * a_ServerHandle) { ASSERT(IsValid()); tolua_pushusertype(m_LuaState, a_ServerHandle, "cServerHandle"); } void cLuaState::Push(cLuaTCPLink * a_TCPLink) { ASSERT(IsValid()); tolua_pushusertype(m_LuaState, a_TCPLink, "cTCPLink"); } void cLuaState::Push(cLuaUDPEndpoint * a_UDPEndpoint) { ASSERT(IsValid()); tolua_pushusertype(m_LuaState, a_UDPEndpoint, "cUDPEndpoint"); } void cLuaState::Push(double a_Value) { ASSERT(IsValid()); tolua_pushnumber(m_LuaState, a_Value); } void cLuaState::Push(int a_Value) { ASSERT(IsValid()); tolua_pushnumber(m_LuaState, a_Value); } void cLuaState::Push(long a_Value) { ASSERT(IsValid()); tolua_pushnumber(m_LuaState, static_cast(a_Value)); } void cLuaState::Push(UInt32 a_Value) { ASSERT(IsValid()); tolua_pushnumber(m_LuaState, a_Value); } void cLuaState::Push(std::chrono::milliseconds a_Value) { ASSERT(IsValid()); tolua_pushnumber(m_LuaState, static_cast(a_Value.count())); } void cLuaState::Pop(int a_NumValuesToPop) { ASSERT(IsValid()); lua_pop(m_LuaState, a_NumValuesToPop); } bool cLuaState::GetStackValue(int a_StackPos, AString & a_Value) { size_t len = 0; const char * data = lua_tolstring(m_LuaState, a_StackPos, &len); if (data != nullptr) { a_Value.assign(data, len); return true; } return false; } bool cLuaState::GetStackValue(int a_StackPos, AStringMap & a_Value) { // Retrieve all values in a string => string dictionary table: if (!lua_istable(m_LuaState, a_StackPos)) { return false; } cStackTable tbl(*this, a_StackPos); bool isValid = true; tbl.ForEachElement([&isValid, &a_Value](cLuaState & a_LuaState) { AString key, val; if (a_LuaState.GetStackValues(-2, key, val)) { a_Value[key] = val; } else { isValid = false; return true; } return false; } ); return isValid; } bool cLuaState::GetStackValue(int a_StackPos, AStringVector & a_Value) { // Retrieve all values in an array of string table: if (!lua_istable(m_LuaState, a_StackPos)) { return false; } cStackTable tbl(*this, a_StackPos); bool isValid = true; tbl.ForEachArrayElement([&](cLuaState & a_LuaState, int a_Index) { AString tempStr; if (a_LuaState.GetStackValue(-1, tempStr)) { a_Value.push_back(std::move(tempStr)); } else { isValid = false; return true; } return false; } ); return isValid; } bool cLuaState::GetStackValue(int a_StackPos, bool & a_ReturnedVal) { a_ReturnedVal = (tolua_toboolean(m_LuaState, a_StackPos, a_ReturnedVal ? 1 : 0) > 0); return true; } bool cLuaState::GetStackValue(int a_StackPos, cCallback & a_Callback) { return a_Callback.RefStack(*this, a_StackPos); } bool cLuaState::GetStackValue(int a_StackPos, cCallbackPtr & a_Callback) { if (a_Callback == nullptr) { a_Callback = std::make_unique(); } return a_Callback->RefStack(*this, a_StackPos); } bool cLuaState::GetStackValue(int a_StackPos, cOptionalCallback & a_Callback) { return a_Callback.RefStack(*this, a_StackPos); } bool cLuaState::GetStackValue(int a_StackPos, cOptionalCallbackPtr & a_Callback) { if (a_Callback == nullptr) { a_Callback = std::make_unique(); } return a_Callback->RefStack(*this, a_StackPos); } bool cLuaState::GetStackValue(int a_StackPos, cCallbackSharedPtr & a_Callback) { if (a_Callback == nullptr) { a_Callback = std::make_shared(); } return a_Callback->RefStack(*this, a_StackPos); } bool cLuaState::GetStackValue(int a_StackPos, cPluginManager::CommandResult & a_Result) { if (lua_isnumber(m_LuaState, a_StackPos)) { a_Result = static_cast(static_cast((tolua_tonumber(m_LuaState, a_StackPos, a_Result)))); return true; } return false; } bool cLuaState::GetStackValue(int a_StackPos, cRef & a_Ref) { a_Ref.RefStack(*this, a_StackPos); return true; } bool cLuaState::GetStackValue(int a_StackPos, cStackTablePtr & a_StackTable) { // Only allow tables to be stored in a_StackTable: if (!lua_istable(m_LuaState, a_StackPos)) { return false; } // Assign the StackTable to the specified stack position: a_StackTable = std::make_unique(*this, a_StackPos); return true; } bool cLuaState::GetStackValue(int a_StackPos, cTableRef & a_TableRef) { return a_TableRef.RefStack(*this, a_StackPos); } bool cLuaState::GetStackValue(int a_StackPos, cTableRefPtr & a_TableRef) { if (a_TableRef == nullptr) { a_TableRef = std::make_unique(); } return a_TableRef->RefStack(*this, a_StackPos); } bool cLuaState::GetStackValue(int a_StackPos, cTrackedRef & a_Ref) { return a_Ref.RefStack(*this, a_StackPos); } bool cLuaState::GetStackValue(int a_StackPos, cTrackedRefPtr & a_Ref) { if (a_Ref == nullptr) { a_Ref = std::make_unique(); } return a_Ref->RefStack(*this, a_StackPos); } bool cLuaState::GetStackValue(int a_StackPos, cTrackedRefSharedPtr & a_Ref) { if (a_Ref == nullptr) { a_Ref = std::make_shared(); } return a_Ref->RefStack(*this, a_StackPos); } bool cLuaState::GetStackValue(int a_StackPos, ContiguousByteBuffer & a_Data) { size_t Length = 0; const char * const Data = lua_tolstring(m_LuaState, a_StackPos, &Length); if (Data != nullptr) { a_Data.assign(reinterpret_cast(Data), Length); return true; } return false; } bool cLuaState::GetStackValue(int a_StackPos, CustomStatistic & a_Value) { if (lua_isnumber(m_LuaState, a_StackPos)) { a_Value = static_cast(static_cast>(lua_tonumber(m_LuaState, a_StackPos))); return true; } return true; } bool cLuaState::GetStackValue(int a_StackPos, double & a_ReturnedVal) { if (lua_isnumber(m_LuaState, a_StackPos)) { a_ReturnedVal = tolua_tonumber(m_LuaState, a_StackPos, a_ReturnedVal); return true; } return false; } bool cLuaState::GetStackValue(int a_StackPos, eBlockFace & a_ReturnedVal) { if (!lua_isnumber(m_LuaState, a_StackPos)) { return false; } a_ReturnedVal = static_cast(Clamp( static_cast(tolua_tonumber(m_LuaState, a_StackPos, a_ReturnedVal)), static_cast(BLOCK_FACE_MIN), static_cast(BLOCK_FACE_MAX)) ); return true; } bool cLuaState::GetStackValue(int a_StackPos, eWeather & a_ReturnedVal) { if (!lua_isnumber(m_LuaState, a_StackPos)) { return false; } a_ReturnedVal = static_cast(Clamp( static_cast(tolua_tonumber(m_LuaState, a_StackPos, a_ReturnedVal)), static_cast(wSunny), static_cast(wThunderstorm)) ); return true; } bool cLuaState::GetStackValue(int a_StackPos, float & a_ReturnedVal) { if (lua_isnumber(m_LuaState, a_StackPos)) { a_ReturnedVal = static_cast(tolua_tonumber(m_LuaState, a_StackPos, a_ReturnedVal)); return true; } return false; } bool cLuaState::GetStackValue(int a_StackPos, cUUID & a_Value) { if (lua_isnil(m_LuaState, a_StackPos)) { return false; } tolua_Error tolua_Err; if (tolua_isusertype(m_LuaState, a_StackPos, "cUUID", 0, &tolua_Err)) { // Found a cUUID, copy into output value cUUID * PtrUUID = nullptr; GetStackValue(a_StackPos, PtrUUID); if (PtrUUID == nullptr) { return false; } a_Value = *PtrUUID; return true; } // Try to get a string and parse as a UUID into the output AString StrUUID; if (!GetStackValue(a_StackPos, StrUUID)) { return false; } return a_Value.FromString(StrUUID); } bool cLuaState::GetStackValue(int a_StackPos, std::string_view & a_Value) { size_t Length = 0; const char * const Value = lua_tolstring(m_LuaState, a_StackPos, &Length); if (Value != nullptr) { a_Value = { Value, Length }; return true; } return false; } template bool cLuaState::GetStackValue(int a_StackPos, Vector3 & a_ReturnedVal) { tolua_Error err; if (lua_isnil(m_LuaState, a_StackPos)) { return false; } if (tolua_isusertype(m_LuaState, a_StackPos, "Vector3", 0, &err)) { a_ReturnedVal = **(static_cast(lua_touserdata(m_LuaState, a_StackPos))); return true; } if (tolua_isusertype(m_LuaState, a_StackPos, "Vector3", 0, &err)) { a_ReturnedVal = **(static_cast(lua_touserdata(m_LuaState, a_StackPos))); return true; } if (tolua_isusertype(m_LuaState, a_StackPos, "Vector3", 0, &err)) { a_ReturnedVal = **(static_cast(lua_touserdata(m_LuaState, a_StackPos))); return true; } // Bonus: Allow simple tables to work as Vector3: if (lua_istable(m_LuaState, a_StackPos)) { lua_rawgeti(m_LuaState, a_StackPos, 1); lua_rawgeti(m_LuaState, a_StackPos, 2); lua_rawgeti(m_LuaState, a_StackPos, 3); T x, y, z; if (!GetStackValues(-3, x, y, z)) { return false; } a_ReturnedVal = Vector3(x, y, z); return true; } return false; } // Explicitly instantiate the previous function for all Vector3 types: template bool cLuaState::GetStackValue(int a_StackPos, Vector3d & a_ReturnedVal); template bool cLuaState::GetStackValue(int a_StackPos, Vector3f & a_ReturnedVal); template bool cLuaState::GetStackValue(int a_StackPos, Vector3i & a_ReturnedVal); cLuaState::cStackValue cLuaState::WalkToValue(const AString & a_Name) { // There needs to be at least one value on the stack: ASSERT(lua_gettop(m_LuaState) > 0); // Iterate over path and replace the top of the stack with the walked element lua_pushvalue(m_LuaState, -1); // Copy the stack value into the "working area" auto path = StringSplit(a_Name, "."); for (const auto & elem: path) { // If the value is not a table, bail out (error): if (!lua_istable(m_LuaState, -1)) { lua_pop(m_LuaState, 1); return cStackValue(); } // Get the next part of the path: lua_getfield(m_LuaState, -1, elem.c_str()); // Remove the previous value from the stack (keep only the new one): lua_remove(m_LuaState, -2); } // for elem - path[] if (lua_isnil(m_LuaState, -1)) { lua_pop(m_LuaState, 1); return cStackValue(); } return cStackValue(*this); } cLuaState::cStackValue cLuaState::WalkToNamedGlobal(const AString & a_Name) { // Iterate over path and replace the top of the stack with the walked element lua_getglobal(m_LuaState, "_G"); auto path = StringSplit(a_Name, "."); for (const auto & elem: path) { // If the value is not a table, bail out (error): if (!lua_istable(m_LuaState, -1)) { lua_pop(m_LuaState, 1); return cStackValue(); } // Get the next part of the path: lua_getfield(m_LuaState, -1, elem.c_str()); // Remove the previous value from the stack (keep only the new one): lua_remove(m_LuaState, -2); } // for elem - path[] if (lua_isnil(m_LuaState, -1)) { lua_pop(m_LuaState, 1); return cStackValue(); } return cStackValue(*this); } bool cLuaState::CallFunction(int a_NumResults) { ASSERT (m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first ASSERT(lua_isfunction(m_LuaState, -m_NumCurrentFunctionArgs - 1)); // The function to call ASSERT(lua_isfunction(m_LuaState, -m_NumCurrentFunctionArgs - 2)); // The error handler // Save the current "stack" state and reset, in case the callback calls another function: AString CurrentFunctionName; std::swap(m_CurrentFunctionName, CurrentFunctionName); int NumArgs = m_NumCurrentFunctionArgs; m_NumCurrentFunctionArgs = -1; // Call the function: int s = lua_pcall(m_LuaState, NumArgs, a_NumResults, -NumArgs - 2); if (s != 0) { // The error has already been printed together with the stacktrace LOGWARNING("Error in %s calling function %s()", m_SubsystemName, CurrentFunctionName); // Remove the error handler and error message from the stack: auto top = lua_gettop(m_LuaState); if (top < 2) { LogStackValues(fmt::format(FMT_STRING("The Lua stack is in an unexpected state, expected at least two values there, but got {}"), top).c_str()); } lua_pop(m_LuaState, std::min(2, top)); return false; } // Remove the error handler from the stack: lua_remove(m_LuaState, -a_NumResults - 1); return true; } bool cLuaState::CheckParamUserTable(int a_StartParam, const char * a_UserTable, int a_EndParam) { ASSERT(IsValid()); if (a_EndParam < 0) { a_EndParam = a_StartParam; } tolua_Error tolua_err; for (int i = a_StartParam; i <= a_EndParam; i++) { if (tolua_isusertable(m_LuaState, i, a_UserTable, 0, &tolua_err)) { continue; } // Not the correct parameter lua_Debug entry; VERIFY(lua_getstack(m_LuaState, 0, &entry)); VERIFY(lua_getinfo (m_LuaState, "n", &entry)); AString ErrMsg = fmt::format(FMT_STRING("#ferror in function '{}'."), (entry.name != nullptr) ? entry.name : "?"); tolua_error(m_LuaState, ErrMsg.c_str(), &tolua_err); return false; } // for i - Param // All params checked ok return true; } bool cLuaState::CheckParamUserType(int a_StartParam, const char * a_UserType, int a_EndParam) { ASSERT(IsValid()); if (a_EndParam < 0) { a_EndParam = a_StartParam; } tolua_Error tolua_err; for (int i = a_StartParam; i <= a_EndParam; i++) { if (tolua_isusertype(m_LuaState, i, a_UserType, 0, &tolua_err)) { continue; } // Not the correct parameter lua_Debug entry; VERIFY(lua_getstack(m_LuaState, 0, &entry)); VERIFY(lua_getinfo (m_LuaState, "n", &entry)); AString ErrMsg = fmt::format(FMT_STRING("#ferror in function '{}'."), (entry.name != nullptr) ? entry.name : "?"); tolua_error(m_LuaState, ErrMsg.c_str(), &tolua_err); return false; } // for i - Param // All params checked ok return true; } bool cLuaState::CheckParamTable(int a_StartParam, int a_EndParam) { ASSERT(IsValid()); if (a_EndParam < 0) { a_EndParam = a_StartParam; } tolua_Error tolua_err; for (int i = a_StartParam; i <= a_EndParam; i++) { if (tolua_istable(m_LuaState, i, 0, &tolua_err)) { continue; } // Not the correct parameter lua_Debug entry; VERIFY(lua_getstack(m_LuaState, 0, &entry)); VERIFY(lua_getinfo (m_LuaState, "n", &entry)); AString ErrMsg = fmt::format(FMT_STRING("#ferror in function '{}'."), (entry.name != nullptr) ? entry.name : "?"); BreakIntoDebugger(m_LuaState); tolua_error(m_LuaState, ErrMsg.c_str(), &tolua_err); return false; } // for i - Param // All params checked ok return true; } bool cLuaState::CheckParamNumber(int a_StartParam, int a_EndParam) { ASSERT(IsValid()); if (a_EndParam < 0) { a_EndParam = a_StartParam; } tolua_Error tolua_err; for (int i = a_StartParam; i <= a_EndParam; i++) { if (tolua_isnumber(m_LuaState, i, 0, &tolua_err)) { continue; } // Not the correct parameter lua_Debug entry; VERIFY(lua_getstack(m_LuaState, 0, &entry)); VERIFY(lua_getinfo (m_LuaState, "n", &entry)); AString ErrMsg = fmt::format(FMT_STRING("#ferror in function '{}'."), (entry.name != nullptr) ? entry.name : "?"); tolua_error(m_LuaState, ErrMsg.c_str(), &tolua_err); return false; } // for i - Param // All params checked ok return true; } bool cLuaState::CheckParamBool(int a_StartParam, int a_EndParam) { ASSERT(IsValid()); if (a_EndParam < 0) { a_EndParam = a_StartParam; } tolua_Error tolua_err; for (int i = a_StartParam; i <= a_EndParam; i++) { if (tolua_isboolean(m_LuaState, i, 0, &tolua_err)) { continue; } // Not the correct parameter lua_Debug entry; VERIFY(lua_getstack(m_LuaState, 0, &entry)); VERIFY(lua_getinfo (m_LuaState, "n", &entry)); AString ErrMsg = fmt::format(FMT_STRING("#ferror in function '{}'."), (entry.name != nullptr) ? entry.name : "?"); tolua_error(m_LuaState, ErrMsg.c_str(), &tolua_err); return false; } // for i - Param // All params checked ok return true; } bool cLuaState::CheckParamString(int a_StartParam, int a_EndParam) { ASSERT(IsValid()); if (a_EndParam < 0) { a_EndParam = a_StartParam; } tolua_Error tolua_err; for (int i = a_StartParam; i <= a_EndParam; i++) { if (lua_isstring(m_LuaState, i)) { continue; } // Not the correct parameter lua_Debug entry; VERIFY(lua_getstack(m_LuaState, 0, &entry)); VERIFY(lua_getinfo (m_LuaState, "n", &entry)); tolua_err.array = 0; tolua_err.type = "string"; tolua_err.index = i; AString ErrMsg = fmt::format(FMT_STRING("#ferror in function '{}'."), (entry.name != nullptr) ? entry.name : "?"); tolua_error(m_LuaState, ErrMsg.c_str(), &tolua_err); return false; } // for i - Param // All params checked ok return true; } bool cLuaState::CheckParamFunction(int a_StartParam, int a_EndParam) { ASSERT(IsValid()); if (a_EndParam < 0) { a_EndParam = a_StartParam; } for (int i = a_StartParam; i <= a_EndParam; i++) { if (lua_isfunction(m_LuaState, i)) { continue; } // Not the correct parameter lua_Debug entry; VERIFY(lua_getstack(m_LuaState, 0, &entry)); VERIFY(lua_getinfo (m_LuaState, "n", &entry)); luaL_error(m_LuaState, "Error in function '%s' parameter #%d. Function expected, got %s", (entry.name != nullptr) ? entry.name : "?", i, GetTypeText(i).c_str() ); return false; } // for i - Param // All params checked ok return true; } bool cLuaState::CheckParamFunctionOrNil(int a_StartParam, int a_EndParam) { ASSERT(IsValid()); if (a_EndParam < 0) { a_EndParam = a_StartParam; } for (int i = a_StartParam; i <= a_EndParam; i++) { if (lua_isfunction(m_LuaState, i) || lua_isnil(m_LuaState, i)) { continue; } // Not the correct parameter lua_Debug entry; VERIFY(lua_getstack(m_LuaState, 0, &entry)); VERIFY(lua_getinfo (m_LuaState, "n", &entry)); luaL_error(m_LuaState, "Error in function '%s' parameter #%d. Function expected, got %s", (entry.name != nullptr) ? entry.name : "?", i, GetTypeText(i).c_str() ); return false; } // for i - Param // All params checked ok return true; } bool cLuaState::CheckParamVector3(int a_StartParam, int a_EndParam) { ASSERT(IsValid()); if (a_EndParam < 0) { a_EndParam = a_StartParam; } for (int i = a_StartParam; i <= a_EndParam; ++i) { if (IsParamVector3(a_StartParam)) { continue; } ApiParamError(fmt::format(FMT_STRING("Failed to read parameter #{}. Vector3 expected, got {}"), i, GetTypeText(i))); return false; } return true; } bool cLuaState::CheckParamUUID(int a_StartParam, int a_EndParam) { ASSERT(IsValid()); if (a_EndParam < 0) { a_EndParam = a_StartParam; } cUUID tempUUID; AString tempStr; // Accept either a cUUID or a string that contains a valid UUID for (int i = a_StartParam; i <= a_EndParam; ++i) { tolua_Error err; if (tolua_isusertype(m_LuaState, i, "cUUID", 0, &err) && !lua_isnil(m_LuaState, i)) { continue; } if (!tolua_iscppstring(m_LuaState, i, 0, &err)) { ApiParamError(fmt::format(FMT_STRING("Failed to read parameter #{}. UUID expected, got {}"), i, GetTypeText(i))); return false; } // Check string is a valid UUID GetStackValue(i, tempStr); if (!tempUUID.FromString(tempStr)) { ApiParamError(fmt::format(FMT_STRING("Failed to read parameter #{}. UUID expected, got non-UUID string:\n\t\"{}\""), i, tempStr)); return false; } } return true; } bool cLuaState::CheckParamEnd(int a_Param) { tolua_Error tolua_err; if (tolua_isnoobj(m_LuaState, a_Param, &tolua_err) == 1) { return true; } // Not the correct parameter lua_Debug entry; VERIFY(lua_getstack(m_LuaState, 0, &entry)); VERIFY(lua_getinfo (m_LuaState, "n", &entry)); AString ErrMsg = fmt::format(FMT_STRING("#ferror in function '{}': Too many arguments."), (entry.name != nullptr) ? entry.name : "?"); tolua_error(m_LuaState, ErrMsg.c_str(), &tolua_err); return false; } bool cLuaState::CheckParamSelf(const char * a_SelfClassName) { tolua_Error tolua_err; if (tolua_isusertype(m_LuaState, 1, a_SelfClassName, 0, &tolua_err) && !lua_isnil(m_LuaState, 1)) { return true; } // Not the correct parameter lua_Debug entry; VERIFY(lua_getstack(m_LuaState, 0, &entry)); VERIFY(lua_getinfo (m_LuaState, "n", &entry)); AString ErrMsg = fmt::format( FMT_STRING("Error in function '{}'. The 'self' parameter is not of the expected type, \"instance of {}\". " \ "Make sure you're using the correct calling convention (obj:fn() instead of obj.fn())."), (entry.name != nullptr) ? entry.name : "", a_SelfClassName ); tolua_error(m_LuaState, ErrMsg.c_str(), &tolua_err); return false; } bool cLuaState::CheckParamStaticSelf(const char * a_SelfClassName) { tolua_Error tolua_err; if (tolua_isusertable(m_LuaState, 1, a_SelfClassName, 0, &tolua_err) && !lua_isnil(m_LuaState, 1)) { return true; } // Not the correct parameter lua_Debug entry; VERIFY(lua_getstack(m_LuaState, 0, &entry)); VERIFY(lua_getinfo (m_LuaState, "n", &entry)); AString ErrMsg = fmt::format( FMT_STRING("Error in function '{}'. The 'self' parameter is not of the expected type, \"class {}\". " \ "Make sure you're using the correct calling convention (cClassName:fn() instead of cClassName.fn() or obj:fn())."), (entry.name != nullptr) ? entry.name : "", a_SelfClassName ); tolua_error(m_LuaState, ErrMsg.c_str(), &tolua_err); return false; } bool cLuaState::IsParamUserType(int a_ParamIdx, const AString & a_UserType) { ASSERT(IsValid()); tolua_Error tolua_err; return (tolua_isusertype(m_LuaState, a_ParamIdx, a_UserType.c_str(), 0, &tolua_err) == 1); } bool cLuaState::IsParamNumber(int a_ParamIdx) { ASSERT(IsValid()); tolua_Error tolua_err; return (tolua_isnumber(m_LuaState, a_ParamIdx, 0, &tolua_err) == 1); } bool cLuaState::IsParamVector3(int a_ParamIdx) { ASSERT(IsValid()); return ( IsParamUserType(a_ParamIdx, "Vector3") || IsParamUserType(a_ParamIdx, "Vector3") || IsParamUserType(a_ParamIdx, "Vector3") || lua_istable(m_LuaState, a_ParamIdx) // Assume any table is good enough ); } bool cLuaState::ReportErrors(int a_Status) { return ReportErrors(m_LuaState, a_Status); } bool cLuaState::ReportErrors(lua_State * a_LuaState, int a_Status) { if (a_Status == 0) { // No error to report return false; } LOGWARNING("LUA: %d - %s", a_Status, lua_tostring(a_LuaState, -1)); lua_pop(a_LuaState, 1); return true; } void cLuaState::LogStackTrace(int a_StartingDepth) { LogStackTrace(m_LuaState, a_StartingDepth); } void cLuaState::LogStackTrace(lua_State * a_LuaState, int a_StartingDepth) { LOGWARNING("Stack trace:"); lua_Debug entry; int depth = a_StartingDepth; while (lua_getstack(a_LuaState, depth, &entry)) { lua_getinfo(a_LuaState, "Sln", &entry); LOGWARNING(" %s(%d): %s", entry.short_src, entry.currentline, entry.name ? entry.name : "(no name)"); depth++; } LOGWARNING("Stack trace end"); } int cLuaState::ApiParamError(std::string_view a_Msg) { // Retrieve current function name lua_Debug entry; VERIFY(lua_getstack(m_LuaState, 0, &entry)); VERIFY(lua_getinfo(m_LuaState, "n", &entry)); // Compose the error message: AString errorMsg = fmt::format("{0}: {1}", (entry.name != nullptr) ? entry.name : "", a_Msg); // Log everything into the console: LOGWARNING("%s", errorMsg.c_str()); // cLuaState::LogStackTrace(a_LuaState); // Do NOT log stack trace, it is already output as part of the Lua error handling LogStackValues(m_LuaState, "Parameters on the stack"); // Raise Lua error: lua_pushstring(m_LuaState, errorMsg.c_str()); return lua_error(m_LuaState); } AString cLuaState::GetTypeText(int a_StackPos) { return lua_typename(m_LuaState, lua_type(m_LuaState, a_StackPos)); } int cLuaState::CallFunctionWithForeignParams( const AString & a_FunctionName, cLuaState & a_SrcLuaState, int a_SrcParamStart, int a_SrcParamEnd ) { ASSERT(IsValid()); ASSERT(a_SrcLuaState.IsValid()); // Store the stack position before any changes int OldTop = lua_gettop(m_LuaState); // Push the function to call, including the error handler: if (!PushFunction(a_FunctionName.c_str())) { LOGWARNING("Function '%s' not found", a_FunctionName.c_str()); lua_settop(m_LuaState, OldTop); return -1; } // Copy the function parameters to the target state if (CopyStackFrom(a_SrcLuaState, a_SrcParamStart, a_SrcParamEnd) < 0) { // Something went wrong, fix the stack and exit lua_settop(m_LuaState, OldTop); m_NumCurrentFunctionArgs = -1; m_CurrentFunctionName.clear(); return -1; } // Call the function, with an error handler: int s = lua_pcall(m_LuaState, a_SrcParamEnd - a_SrcParamStart + 1, LUA_MULTRET, OldTop + 1); if (ReportErrors(s)) { LOGWARN("Error while calling function '%s' in '%s'", a_FunctionName.c_str(), m_SubsystemName.c_str()); // Reset the stack: lua_settop(m_LuaState, OldTop); // Reset the internal checking mechanisms: m_NumCurrentFunctionArgs = -1; m_CurrentFunctionName.clear(); // Make Lua think everything is okay and return 0 values, so that plugins continue executing. // The failure is indicated by the zero return values. return 0; } // Reset the internal checking mechanisms: m_NumCurrentFunctionArgs = -1; m_CurrentFunctionName.clear(); // Remove the error handler from the stack: lua_remove(m_LuaState, OldTop + 1); // Return the number of return values: return lua_gettop(m_LuaState) - OldTop; } int cLuaState::CopyStackFrom(cLuaState & a_SrcLuaState, int a_SrcStart, int a_SrcEnd, int a_NumAllowedNestingLevels) { /* // DEBUG: LOGD("Copying stack values from %d to %d", a_SrcStart, a_SrcEnd); a_SrcLuaState.LogStack("Src stack before copying:"); LogStack("Dst stack before copying:"); */ for (int i = a_SrcStart; i <= a_SrcEnd; ++i) { if (!CopySingleValueFrom(a_SrcLuaState, i, a_NumAllowedNestingLevels)) { lua_pop(m_LuaState, i - a_SrcStart); return -1; } } return a_SrcEnd - a_SrcStart + 1; } bool cLuaState::CopyTableFrom(cLuaState & a_SrcLuaState, int a_SrcStackIdx, int a_NumAllowedNestingLevels) { [[maybe_unused]] const auto srcTop = lua_gettop(a_SrcLuaState); [[maybe_unused]] const auto dstTop = lua_gettop(m_LuaState); // Create the dest table: lua_createtable(m_LuaState, 0, 0); // DST:
    lua_pushvalue(a_SrcLuaState, a_SrcStackIdx); // SRC:
    lua_pushnil(a_SrcLuaState); // SRC:
    while (lua_next(a_SrcLuaState, -2) != 0) // SRC:
    { ASSERT(lua_gettop(a_SrcLuaState) == srcTop + 3); ASSERT(lua_gettop(m_LuaState) == dstTop + 1); // Copy the key: if (!CopySingleValueFrom(a_SrcLuaState, -2, a_NumAllowedNestingLevels)) // DST:
    { lua_pop(m_LuaState, 1); lua_pop(a_SrcLuaState, 3); ASSERT(lua_gettop(a_SrcLuaState) == srcTop); ASSERT(lua_gettop(m_LuaState) == dstTop); return false; } ASSERT(lua_gettop(a_SrcLuaState) == srcTop + 3); ASSERT(lua_gettop(m_LuaState) == dstTop + 2); // Copy the value: if (!CopySingleValueFrom(a_SrcLuaState, -1, a_NumAllowedNestingLevels - 1)) // DST:
    { lua_pop(m_LuaState, 2); // DST: empty lua_pop(a_SrcLuaState, 3); // SRC: empty ASSERT(lua_gettop(a_SrcLuaState) == srcTop); ASSERT(lua_gettop(m_LuaState) == dstTop); return false; } ASSERT(lua_gettop(a_SrcLuaState) == srcTop + 3); ASSERT(lua_gettop(m_LuaState) == dstTop + 3); // Set the value and fix up stacks: lua_rawset(m_LuaState, -3); // DST:
    lua_pop(a_SrcLuaState, 1); // SRC:
    ASSERT(lua_gettop(a_SrcLuaState) == srcTop + 2); ASSERT(lua_gettop(m_LuaState) == dstTop + 1); } lua_pop(a_SrcLuaState, 1); // SRC: empty ASSERT(lua_gettop(a_SrcLuaState) == srcTop); ASSERT(lua_gettop(m_LuaState) == dstTop + 1); return true; } bool cLuaState::CopySingleValueFrom(cLuaState & a_SrcLuaState, int a_StackIdx, int a_NumAllowedNestingLevels) { int t = lua_type(a_SrcLuaState, a_StackIdx); switch (t) { case LUA_TNIL: { lua_pushnil(m_LuaState); return true; } case LUA_TSTRING: { AString s; a_SrcLuaState.ToString(a_StackIdx, s); Push(s); return true; } case LUA_TBOOLEAN: { bool b = (tolua_toboolean(a_SrcLuaState, a_StackIdx, false) != 0); Push(b); return true; } case LUA_TNUMBER: { lua_Number d = tolua_tonumber(a_SrcLuaState, a_StackIdx, 0); Push(d); return true; } case LUA_TUSERDATA: { // Get the class name: const char * type = nullptr; if (lua_getmetatable(a_SrcLuaState, a_StackIdx) == 0) { LOGWARNING("%s: Unknown class in pos %d, cannot copy.", __FUNCTION__, a_StackIdx); return false; } lua_rawget(a_SrcLuaState, LUA_REGISTRYINDEX); // Stack +1 type = lua_tostring(a_SrcLuaState, -1); lua_pop(a_SrcLuaState, 1); // Stack -1 // Copy the value: void * ud = tolua_touserdata(a_SrcLuaState, a_StackIdx, nullptr); tolua_pushusertype(m_LuaState, ud, type); return true; } case LUA_TTABLE: { if (!CopyTableFrom(a_SrcLuaState, a_StackIdx, a_NumAllowedNestingLevels - 1)) { LOGWARNING("%s: Failed to copy table in pos %d.", __FUNCTION__, a_StackIdx); return false; } return true; } default: { LOGWARNING("%s: Unsupported value: '%s' at stack position %d. Can only copy numbers, strings, bools, classes and simple tables!", __FUNCTION__, lua_typename(a_SrcLuaState, t), a_StackIdx ); return false; } } } void cLuaState::ToString(int a_StackPos, AString & a_String) { size_t len; const char * s = lua_tolstring(m_LuaState, a_StackPos, &len); if (s != nullptr) { a_String.assign(s, len); } } void cLuaState::LogStackValues(const char * a_Header) { LogStackValues(m_LuaState, a_Header); } void cLuaState::LogStackValues(lua_State * a_LuaState, const char * a_Header) { // Format string consisting only of %s is used to appease the compiler ASSERT_LUA_STACK_BALANCE(a_LuaState, false); LOG("%s", (a_Header != nullptr) ? a_Header : "Lua C API Stack contents:"); for (int i = lua_gettop(a_LuaState); i > 0; i--) { AString Value; int Type = lua_type(a_LuaState, i); switch (Type) { case LUA_TBOOLEAN: Value.assign((lua_toboolean(a_LuaState, i) != 0) ? "true" : "false"); break; case LUA_TLIGHTUSERDATA: Value = fmt::format(FMT_STRING("{}"), lua_touserdata(a_LuaState, i)); break; case LUA_TNUMBER: Value = fmt::format(FMT_STRING("{}"), lua_tonumber(a_LuaState, i)); break; case LUA_TSTRING: { size_t len; const char * txt = lua_tolstring(a_LuaState, i, &len); Value.assign(txt, std::min(len, 50)); // Only log up to 50 characters of the string break; } case LUA_TTABLE: Value = fmt::format(FMT_STRING("{}"), lua_topointer(a_LuaState, i)); break; case LUA_TFUNCTION: Value = fmt::format(FMT_STRING("{}"), lua_topointer(a_LuaState, i)); break; case LUA_TUSERDATA: { Value = fmt::format(FMT_STRING("{} ({})"), lua_touserdata(a_LuaState, i), tolua_typename(a_LuaState, i)); // tolua_typename pushes the string onto Lua stack, pop it off again: lua_pop(a_LuaState, 1); break; } default: break; } LOGD(" Idx %d: type %d (%s) %s", i, Type, lua_typename(a_LuaState, Type), Value.c_str()); } // for i - stack idx } cLuaState * cLuaState::QueryCanonLuaState(void) const { return cCanonLuaStates::GetCanonState(m_LuaState); } void cLuaState::LogApiCallParamFailure(const char * a_FnName, const char * a_ParamNames) { LOGWARNING("%s: Cannot read params: %s, bailing out.", a_FnName, a_ParamNames); LogStackTrace(); LogStackValues("Values on the stack"); } void cLuaState::TrackInDeadlockDetect(cDeadlockDetect & a_DeadlockDetect) { a_DeadlockDetect.TrackCriticalSection(m_CS, fmt::format(FMT_STRING("cLuaState {}"), m_SubsystemName)); } void cLuaState::UntrackInDeadlockDetect(cDeadlockDetect & a_DeadlockDetect) { a_DeadlockDetect.UntrackCriticalSection(m_CS); } int cLuaState::ReportFnCallErrors(lua_State * a_LuaState) { LOGWARNING("LUA: %s", lua_tostring(a_LuaState, -1)); LogStackTrace(a_LuaState, 1); BreakIntoDebugger(a_LuaState); return 1; // We left the error message on the stack as the return value } int cLuaState::BreakIntoDebugger(lua_State * a_LuaState) { ASSERT_LUA_STACK_BALANCE(a_LuaState); // Call the BreakIntoDebugger function, if available: lua_getglobal(a_LuaState, "BreakIntoDebugger"); if (!lua_isfunction(a_LuaState, -1)) { LOGD("LUA: BreakIntoDebugger() not found / not a function"); lua_pop(a_LuaState, 1); return 1; } lua_pushvalue(a_LuaState, -2); // Copy the string that has been passed to us LOGD("Calling BreakIntoDebugger()..."); lua_call(a_LuaState, 1, 0); LOGD("Returned from BreakIntoDebugger()."); return 0; } void cLuaState::TrackRef(cTrackedRef & a_Ref) { // Get the CanonLuaState global from Lua: auto canonState = QueryCanonLuaState(); if (canonState == nullptr) { LOGWARNING("%s: Lua state %p has invalid CanonLuaState!", __FUNCTION__, static_cast(m_LuaState)); return; } // Add the callback: cCSLock Lock(canonState->m_CSTrackedRefs); canonState->m_TrackedRefs.push_back(&a_Ref); } void cLuaState::UntrackRef(cTrackedRef & a_Ref) { // Get the CanonLuaState global from Lua: auto canonState = QueryCanonLuaState(); if (canonState == nullptr) { LOGWARNING("%s: Lua state %p has invalid CanonLuaState!", __FUNCTION__, static_cast(m_LuaState)); return; } // Remove the callback (note that another thread may have cleared the callbacks by closing the LuaState): cCSLock Lock(canonState->m_CSTrackedRefs); auto & trackedRefs = canonState->m_TrackedRefs; for (auto itr = trackedRefs.begin(), end = trackedRefs.end(); itr != end; ++itr) { if (*itr == &a_Ref) { trackedRefs.erase(itr); break; } } } //////////////////////////////////////////////////////////////////////////////// // cLuaState::cRef: cLuaState::cRef::cRef(void) : m_LuaState(nullptr), m_Ref(LUA_REFNIL) { } cLuaState::cRef::cRef(cLuaState & a_LuaState, int a_StackPos) : m_LuaState(nullptr), m_Ref(LUA_REFNIL) { RefStack(a_LuaState, a_StackPos); } cLuaState::cRef::cRef(cRef && a_FromRef): m_LuaState(a_FromRef.m_LuaState), m_Ref(a_FromRef.m_Ref) { a_FromRef.m_LuaState = nullptr; a_FromRef.m_Ref = LUA_REFNIL; } cLuaState::cRef::~cRef() { if (m_LuaState != nullptr) { UnRef(); } } void cLuaState::cRef::RefStack(cLuaState & a_LuaState, int a_StackPos) { ASSERT(a_LuaState.IsValid()); if (m_LuaState != nullptr) { UnRef(); } ASSERT(cCanonLuaStates::GetCanonState(a_LuaState)->m_CS.IsLockedByCurrentThread()); m_LuaState = a_LuaState; lua_pushvalue(a_LuaState, a_StackPos); // Push a copy of the value at a_StackPos onto the stack m_Ref = luaL_ref(a_LuaState, LUA_REGISTRYINDEX); } void cLuaState::cRef::UnRef(void) { if (IsValid()) { ASSERT(cCanonLuaStates::GetCanonState(m_LuaState)->m_CS.IsLockedByCurrentThread()); luaL_unref(m_LuaState, LUA_REGISTRYINDEX, m_Ref); } m_LuaState = nullptr; m_Ref = LUA_REFNIL; } ================================================ FILE: src/Bindings/LuaState.h ================================================ // LuaState.h // Declares the cLuaState class representing the wrapper over lua_State *, provides associated helper functions /* The contained lua_State can be either owned or attached. Owned lua_State is created by calling Create() and the cLuaState automatically closes the state Or, lua_State can be attached by calling Attach(), the cLuaState doesn't close such a state If owning a state, trying to attach a state will automatically close the previously owned state. Calling a Lua function is done internally by pushing the function using PushFunction(), then pushing the arguments and finally executing CallFunction(). cLuaState automatically keeps track of the number of arguments and the name of the function (for logging purposes). After the call the return values are read from the stack using GetStackValue(). All of this is wrapped in a templated function overloads cLuaState::Call(). Reference management is provided by the cLuaState::cRef class. This is used when you need to hold a reference to any Lua object across several function calls. The class is RAII-like, with automatic resource management. Note that the cRef object is not inherently thread-safe and is not notified when its cLuaState is closed. For those purposes, cTrackedRef can be used. Callbacks management is provided by the cLuaState::cCallback class. Use a GetStackValue() with cCallbackPtr parameter to store the callback, and then at any time you can use the cCallback's Call() templated function to call the callback. The callback management takes care of cLuaState being destroyed - the cCallback object stays valid but doesn't call into Lua code anymore, returning false for "failure" instead. */ #pragma once extern "C" { #include "lua/src/lauxlib.h" } #include "../Defines.h" #include "../FunctionRef.h" #include "../Registries/CustomStatistics.h" #include "PluginManager.h" #include "LuaState_Typedefs.inc" // fwd: class cLuaServerHandle; class cLuaTCPLink; class cLuaUDPEndpoint; class cDeadlockDetect; /** Encapsulates a Lua state and provides some syntactic sugar for common operations */ class cLuaState { public: #ifndef NDEBUG /** Asserts that the Lua stack has the same amount of entries when this object is destructed, as when it was constructed. Used for checking functions that should preserve Lua stack balance. */ class cStackBalanceCheck { public: cStackBalanceCheck(const char * a_FileName, int a_LineNum, lua_State * a_LuaState, bool a_ShouldLogStack = true): m_FileName(a_FileName), m_LineNum(a_LineNum), m_LuaState(a_LuaState), m_StackPos(lua_gettop(a_LuaState)) { if (a_ShouldLogStack) { // DEBUG: If an unbalanced stack is reported, uncommenting the next line can help debug the imbalance // cLuaState::LogStackValues(a_LuaState, fmt::format(FMT_STRING("Started checking Lua stack balance, currently {} items:"), m_StackPos).c_str()); // Since LogStackValues() itself uses the balance check, we must not call it recursively } } ~cStackBalanceCheck() noexcept(false) { auto currStackPos = lua_gettop(m_LuaState); if (currStackPos != m_StackPos) { LOGD("Lua stack not balanced. Expected %d items, found %d items. Stack watching started in %s:%d", m_StackPos, currStackPos, m_FileName.c_str(), m_LineNum ); cLuaState::LogStackValues(m_LuaState); ASSERT(!"Lua stack unbalanced"); // If this assert fires, the Lua stack is inbalanced, check the callstack / m_FileName / m_LineNum } } protected: const AString m_FileName; int m_LineNum; lua_State * m_LuaState; int m_StackPos; }; #define STRINGIFY2(X, Y) X##Y #define STRINGIFY(X, Y) STRINGIFY2(X, Y) #define ASSERT_LUA_STACK_BALANCE(...) cStackBalanceCheck STRINGIFY(Check, __COUNTER__)(__FILE__, __LINE__, __VA_ARGS__) #else #define ASSERT_LUA_STACK_BALANCE(...) #endif /** Makes sure that the Lua state's stack has the same number of elements on destruction as it had on construction of this object (RAII). Can only remove elements, if there are less than expected, throws. */ class cStackBalancePopper { public: cStackBalancePopper(cLuaState & a_LuaState): m_LuaState(a_LuaState), m_Count(lua_gettop(a_LuaState)) { } ~cStackBalancePopper() noexcept(false) { auto curTop = lua_gettop(m_LuaState); if (curTop > m_Count) { // There are some leftover elements, adjust the stack: m_LuaState.LogStackValues(fmt::format(FMT_STRING("Re-balancing Lua stack, expected {} values, got {}:"), m_Count, curTop).c_str()); lua_pop(m_LuaState, curTop - m_Count); } else if (curTop < m_Count) { // This is an irrecoverable error, rather than letting the Lua engine crash undefinedly later on, abort now: LOGERROR("Unable to re-balance Lua stack, there are elements missing. Expected at least %d elements, got %d.", m_Count, curTop); throw std::runtime_error(fmt::format(FMT_STRING("Unable to re-balance Lua stack, there are elements missing. Expected at least {} elements, got {}."), m_Count, curTop)); } } protected: cLuaState & m_LuaState; int m_Count; }; /** Provides a RAII-style locking for the LuaState. Used mainly by the cPluginLua internals to provide the actual locking for interface operations, such as callbacks. */ class cLock { public: cLock(cLuaState & a_LuaState): m_Lock(a_LuaState.m_CS) { } protected: cCSLock m_Lock; }; /** Used for storing references to object in the global registry. Can be bound (contains a reference) or unbound (doesn't contain reference). The reference can also be reset by calling RefStack(). */ class cRef { public: /** Creates an unbound reference object. */ cRef(void); /** Creates a reference in the specified LuaState for object at the specified StackPos */ cRef(cLuaState & a_LuaState, int a_StackPos); /** Moves the reference from the specified instance into a newly created instance. The old instance is then "!IsValid()". */ cRef(cRef && a_FromRef); ~cRef(); /** Creates a reference to Lua object at the specified stack pos, binds this object to it. Calls UnRef() first if previously bound to another reference. */ void RefStack(cLuaState & a_LuaState, int a_StackPos); /** Removes the bound reference, resets the object to Unbound state. */ void UnRef(void); /** Returns true if the reference is valid */ bool IsValid(void) const {return (m_Ref != LUA_REFNIL); } /** Allows to use this class wherever an int (i. e. ref) is to be used */ explicit operator int(void) const { return m_Ref; } /** Returns the Lua state associated with the value. */ lua_State * GetLuaState(void) { return m_LuaState; } /** Creates a Lua reference to the specified object instance in the specified Lua state. This is useful to make anti-GC references for objects that were created by Lua and need to stay alive longer than Lua GC would normally guarantee. */ template void CreateFromObject(cLuaState & a_LuaState, T && a_Object) { a_LuaState.Push(std::forward(a_Object)); RefStack(a_LuaState, -1); a_LuaState.Pop(); } protected: lua_State * m_LuaState; int m_Ref; // Remove the copy-constructor: cRef(const cRef &) = delete; } ; /** Represents a reference to a Lua object that has a tracked lifetime - - when the Lua state to which it belongs is closed, the object is kept alive, but invalidated. Is thread-safe and unload-safe. To receive the cTrackedRef instance from the Lua side, use RefStack() or (better) cLuaState::GetStackValue(). Note that instances of this class are tracked in the canon LuaState instance, so that they can be invalidated when the LuaState is unloaded; due to multithreading issues they can only be tracked by-ptr, which has an unfortunate effect of disabling the copy and move constructors. */ class cTrackedRef { friend class ::cLuaState; public: /** Creates an unbound ref instance. */ cTrackedRef(void); ~cTrackedRef() { Clear(); } /** Set the contained reference to the object at the specified Lua state's stack position. If another reference has been previously contained, it is Clear()-ed first. */ bool RefStack(cLuaState & a_LuaState, int a_StackPos); /** Frees the contained reference, if any. Untracks the reference from its canon Lua state. */ void Clear(void); /** Returns true if the contained reference is valid. (Note that depending on this value is not thread-safe, another thread may invalidate the ref in the meantime. It is meant for quick ASSERTs only). */ bool IsValid(void); /** Returns true if the reference resides in the specified Lua state. Internally, compares the reference's canon Lua state. (Note that depending on this value is not thread-safe, another thread may modify the ref in the meantime. It is meant for quick ASSERTs only). */ bool IsSameLuaState(cLuaState & a_LuaState); protected: friend class cLuaState; /** The mutex protecting m_Ref against multithreaded access. Actually points to the canon Lua state's m_CriticalSection. Is nullptr when ref is empty (not bound). */ std::atomic m_CS; /** Reference to the Lua callback */ cRef m_Ref; /** Invalidates the callback, without untracking it from the cLuaState. Called only from cLuaState when closing the Lua state. */ void Invalidate(void); /** Returns the internal reference. Only to be used when the cLuaState's CS is held and the cLuaState is known to be valid. */ cRef & GetRef() { return m_Ref; } /** This class cannot be copied, because it is tracked in the LuaState by-ptr. Use a smart pointer for a copyable object. */ cTrackedRef(const cTrackedRef &) = delete; /** This class cannot be moved, because it is tracked in the LuaState by-ptr. Use a smart pointer for a copyable object. */ cTrackedRef(cTrackedRef &&) = delete; }; typedef std::unique_ptr cTrackedRefPtr; typedef std::shared_ptr cTrackedRefSharedPtr; /** Represents a stored callback to Lua that C++ code can call. Is thread-safe and unload-safe. When the Lua state is unloaded, the callback returns an error instead of calling into non-existent code. To receive the callback instance from the Lua side, use RefStack() or (better) cLuaState::GetStackValue() with a cCallbackPtr. Note that instances of this class are tracked in the canon LuaState instance, so that they can be invalidated when the LuaState is unloaded; due to multithreading issues they can only be tracked by-ptr, which has an unfortunate effect of disabling the copy and move constructors. */ class cCallback: public cTrackedRef { using Super = cTrackedRef; public: cCallback(void) {} /** Calls the Lua callback, if still available. Returns true if callback has been called. Returns false if the Lua state isn't valid anymore. */ template bool Call(Args &&... args) { auto cs = m_CS.load(); if (cs == nullptr) { return false; } cCSLock Lock(*cs); if (!m_Ref.IsValid()) { return false; } return cLuaState(m_Ref.GetLuaState()).Call(m_Ref, std::forward(args)...); } /** Set the contained callback to the function in the specified Lua state's stack position. If a callback has been previously contained, it is unreferenced first. Returns true on success, false on failure (not a function at the specified stack pos). */ bool RefStack(cLuaState & a_LuaState, int a_StackPos); protected: /** This class cannot be copied, because it is tracked in the LuaState by-ptr. Use cCallbackPtr for a copyable object. */ cCallback(const cCallback &) = delete; /** This class cannot be moved, because it is tracked in the LuaState by-ptr. Use cCallbackPtr for a copyable object. */ cCallback(cCallback &&) = delete; }; typedef std::unique_ptr cCallbackPtr; typedef std::shared_ptr cCallbackSharedPtr; /** Same thing as cCallback, but GetStackValue() won't fail if the callback value is nil. Used for callbacks that are optional - they needn't be present and in such a case they won't get called. */ class cOptionalCallback: public cCallback { using Super = cCallback; public: cOptionalCallback(void) {} /** Set the contained callback to the function in the specified Lua state's stack position. If a callback has been previously contained, it is unreferenced first. Returns true on success, false on failure (not a function at the specified stack pos). */ bool RefStack(cLuaState & a_LuaState, int a_StackPos); protected: /** This class cannot be copied, because it is tracked in the LuaState by-ptr. Use cCallbackPtr for a copyable object. */ cOptionalCallback(const cOptionalCallback &) = delete; /** This class cannot be moved, because it is tracked in the LuaState by-ptr. Use cCallbackPtr for a copyable object. */ cOptionalCallback(cOptionalCallback &&) = delete; }; typedef std::unique_ptr cOptionalCallbackPtr; /** Represents a stored Lua table with callback functions that C++ code can call. Is thread-safe and unload-safe. When Lua state is unloaded, the CallFn() will return failure instead of calling into non-existent code. To receive the cTableRef instance from the Lua side, use RefStack() or (better) cLuaState::GetStackValue() with a cTableRefPtr. Note that instances of this class are tracked in the canon LuaState instance, so that they can be invalidated when the LuaState is unloaded; due to multithreading issues they can only be tracked by-ptr, which has an unfortunate effect of disabling the copy and move constructors. */ class cTableRef: public cTrackedRef { using Super = cTrackedRef; public: cTableRef(void) {} /** Calls the Lua function stored under the specified name in the referenced table, if still available. Returns true if callback has been called. Returns false if the Lua state isn't valid anymore, or the function doesn't exist. */ template bool CallTableFn(const char * a_FnName, Args &&... args) { auto cs = m_CS.load(); if (cs == nullptr) { return false; } cCSLock Lock(*cs); if (!m_Ref.IsValid()) { return false; } return cLuaState(m_Ref.GetLuaState()).CallTableFn(m_Ref, a_FnName, std::forward(args)...); } /** Calls the Lua function stored under the specified name in the referenced table, if still available. A "self" parameter is injected in front of all the given parameters and is set to the callback table. Returns true if callback has been called. Returns false if the Lua state isn't valid anymore, or the function doesn't exist. */ template bool CallTableFnWithSelf(const char * a_FnName, Args &&... args) { auto cs = m_CS.load(); if (cs == nullptr) { return false; } cCSLock Lock(*cs); if (!m_Ref.IsValid()) { return false; } return cLuaState(m_Ref.GetLuaState()).CallTableFn(m_Ref, a_FnName, m_Ref, std::forward(args)...); } /** Set the contained reference to the table in the specified Lua state's stack position. If another table has been previously contained, it is unreferenced first. Returns true on success, false on failure (not a table at the specified stack pos). */ bool RefStack(cLuaState & a_LuaState, int a_StackPos); }; typedef std::unique_ptr cTableRefPtr; /** Represents a parameter that is optional - calling a GetStackValue() with this object will not fail if the value on the Lua stack is nil. Note that the GetStackValue() will still fail if the param is present but of a different type. The class itself is just a marker so that the template magic will select the correct GetStackValue() overload. */ template class cOptionalParam { public: explicit cOptionalParam(T & a_Dest): m_Dest(a_Dest) { } T & GetDest(void) { return m_Dest; } protected: T & m_Dest; }; /** A dummy class that's used only to delimit function args from return values for cLuaState::Call() */ class cRet { } ; static const cRet Return; // Use this constant to delimit function args from return values for cLuaState::Call() /** A dummy class that's used only to push a constant nil as a function parameter in Call(). */ class cNil { }; static const cNil Nil; // Use this constant to give a function a nil parameter in Call() /** A RAII class for values pushed onto the Lua stack. Will pop the value off the stack in the destructor. */ class cStackValue { public: cStackValue(void): m_LuaState(nullptr) { } cStackValue(cLuaState & a_LuaState): m_LuaState(a_LuaState) { m_StackLen = lua_gettop(a_LuaState); } cStackValue(cStackValue && a_Src): m_LuaState(nullptr), m_StackLen(-1) { std::swap(m_LuaState, a_Src.m_LuaState); std::swap(m_StackLen, a_Src.m_StackLen); } ~cStackValue() noexcept(false) { if (m_LuaState != nullptr) { ASSERT(m_StackLen == lua_gettop(m_LuaState)); lua_pop(m_LuaState, 1); } } void Set(cLuaState & a_LuaState) { m_LuaState = a_LuaState; m_StackLen = lua_gettop(a_LuaState); } bool IsValid(void) const { return (m_LuaState != nullptr); } protected: lua_State * m_LuaState; /** Used for debugging, Lua state's stack size is checked against this number to make sure it is the same as when the value was pushed. */ int m_StackLen; // Remove the copy-constructor: cStackValue(const cStackValue &) = delete; }; /** Represents a table on the Lua stack. Provides easy access to the elements in the table. Note that this class doesn't have cTrackedRef's thread-safeness and unload-safeness, it is expected to be used for immediate queries in API bindings. */ class cStackTable { public: cStackTable(cLuaState & a_LuaState, int a_StackPos); /** Iterates over all array elements in the table consecutively and calls the a_ElementCallback for each. The callback receives the LuaState in which the table resides, and the element's index. The LuaState has the element on top of its stack. If the callback returns true, the iteration is aborted, if it returns false, the iteration continues with the next element. */ void ForEachArrayElement(cFunctionRef a_ElementCallback) const; /** Iterates over all dictionary elements in the table in random order, and calls the a_ElementCallback for each of them. The callback receives the LuaState in which the table reside. The LuaState has the element on top of its stack, and the element's key just below it. If the callback returns true, the iteration is aborted, if it returns false, the iteration continues with the next element. */ void ForEachElement(cFunctionRef a_ElementCallback) const; cLuaState & GetLuaState(void) const { return m_LuaState; } protected: /** The Lua state in which the table resides. */ cLuaState & m_LuaState; /** The stack index where the table resides in the Lua state. */ int m_StackPos; }; typedef std::unique_ptr cStackTablePtr; /** Creates a new instance. The LuaState is not initialized. a_SubsystemName is used for reporting problems in the console, it is "plugin %s" for plugins, or "LuaScript" for the cLuaScript template */ cLuaState(const AString & a_SubsystemName); /** Creates a new instance. The a_AttachState is attached. Subsystem name is set to "". */ explicit cLuaState(lua_State * a_AttachState); ~cLuaState(); /** Allows this object to be used in the same way as a lua_State *, for example in the LuaLib functions */ operator lua_State * (void) { return m_LuaState; } /** Creates the m_LuaState, if not created already. This state will be automatically closed in the destructor. The regular Lua libs are registered, but the MCS API is not registered (so that Lua can be used as lite-config as well), use RegisterAPILibs() to do that. */ void Create(void); /** Registers all the API libraries that MCS provides into m_LuaState. */ void RegisterAPILibs(void); /** Closes the m_LuaState, if not closed already */ void Close(void); /** Attaches the specified state. Operations will be carried out on this state, but it will not be closed in the destructor */ void Attach(lua_State * a_State); /** Detaches a previously attached state. */ void Detach(void); /** Returns true if the m_LuaState is valid */ bool IsValid(void) const { return (m_LuaState != nullptr); } /** Returns the name of the subsystem, as specified when the instance was created. */ AString GetSubsystemName(void) const { return m_SubsystemName; } /** Adds the specified path to package. */ void AddPackagePath(const AString & a_PathVariable, const AString & a_Path); /** Loads the specified file Returns false and optionally logs a warning to the console if not successful (but the LuaState is kept open). m_SubsystemName is displayed in the warning log message. */ bool LoadFile(const AString & a_FileName, bool a_LogWarnings = true); /** Loads the specified string. Returns false and optionally logs a warning to the console if not successful (but the LuaState is kept open). a_FileName is the original filename from where the string was read, and is used only for logging. It may be empty. m_SubsystemName is displayed in the warning log message. */ bool LoadString(const AString & a_StringToLoad, const AString & a_FileName, bool a_LogWarnings = true); /** Returns true if a_FunctionName is a valid Lua function that can be called */ bool HasFunction(const char * a_FunctionName); /** Pushes multiple arguments onto the Lua stack. */ template void Push(Arg1 && a_Arg1, Arg2 && a_Arg2, Args &&... a_Args) { Push(std::forward(a_Arg1)); Push(std::forward(a_Arg2), std::forward(a_Args)...); } // Push a const value onto the stack (keep alpha-sorted): // Note that these functions will make a copy of the actual value, because Lua doesn't have the concept // of "const", and there would be lifetime management problems if they didn't. void Push(const AString & a_String); void Push(const AStringMap & a_Dictionary); void Push(const AStringVector & a_Vector); void Push(const char * a_Value); void Push(const cItem & a_Item); void Push(const cNil & a_Nil); void Push(const cRef & a_Ref); void Push(ContiguousByteBufferView a_Data); void Push(const Vector3d & a_Vector); void Push(const Vector3i & a_Vector); // Push a simple value onto the stack (keep alpha-sorted): void Push(bool a_Value); void Push(cEntity * a_Entity); void Push(const cEntity * a_Entity); void Push(cLuaServerHandle * a_ServerHandle); void Push(cLuaTCPLink * a_TCPLink); void Push(cLuaUDPEndpoint * a_UDPEndpoint); void Push(double a_Value); void Push(int a_Value); void Push(long a_Value); void Push(const UInt32 a_Value); void Push(std::chrono::milliseconds a_time); /** Pops the specified number of values off the top of the Lua stack. */ void Pop(int a_NumValuesToPop = 1); // GetStackValue() retrieves the value at a_StackPos, if it is a valid type. If not, a_Value is unchanged. // Returns whether value was changed // Enum values are checked for their allowed values and fail if the value is not assigned. bool GetStackValue(int a_StackPos, AString & a_Value); bool GetStackValue(int a_StackPos, AStringMap & a_Value); bool GetStackValue(int a_StackPos, AStringVector & a_Value); bool GetStackValue(int a_StackPos, bool & a_Value); bool GetStackValue(int a_StackPos, cCallback & a_Callback); bool GetStackValue(int a_StackPos, cCallbackPtr & a_Callback); bool GetStackValue(int a_StackPos, cCallbackSharedPtr & a_Callback); bool GetStackValue(int a_StackPos, cOptionalCallback & a_Callback); bool GetStackValue(int a_StackPos, cOptionalCallbackPtr & a_Callback); bool GetStackValue(int a_StackPos, cPluginManager::CommandResult & a_Result); bool GetStackValue(int a_StackPos, cRef & a_Ref); bool GetStackValue(int a_StackPos, cStackTablePtr & a_StackTable); bool GetStackValue(int a_StackPos, cTableRef & a_TableRef); bool GetStackValue(int a_StackPos, cTableRefPtr & a_TableRef); bool GetStackValue(int a_StackPos, cTrackedRef & a_Ref); bool GetStackValue(int a_StackPos, cTrackedRefPtr & a_Ref); bool GetStackValue(int a_StackPos, cTrackedRefSharedPtr & a_Ref); bool GetStackValue(int a_StackPos, ContiguousByteBuffer & a_Data); bool GetStackValue(int a_StackPos, CustomStatistic & a_Value); bool GetStackValue(int a_StackPos, double & a_Value); bool GetStackValue(int a_StackPos, eBlockFace & a_Value); bool GetStackValue(int a_StackPos, eWeather & a_Value); bool GetStackValue(int a_StackPos, float & a_ReturnedVal); bool GetStackValue(int a_StackPos, cUUID & a_Value); bool GetStackValue(int a_StackPos, std::string_view & a_Value); // template to catch all of the various c++ integral types without overload conflicts template >> bool GetStackValue(int a_StackPos, T & a_ReturnedVal) { if (!lua_isnumber(m_LuaState, a_StackPos)) // Also accepts strings representing a number: https://pgl.yoyo.org/luai/i/lua_isnumber { return false; } lua_Number Val = lua_tonumber(m_LuaState, a_StackPos); if (Val > std::numeric_limits::max()) { return false; } if (Val < std::numeric_limits::min()) { return false; } a_ReturnedVal = static_cast(Val); return true; } /** Retrieves an optional value on the stack - doesn't fail if the stack contains nil instead of the value. */ template bool GetStackValue(int a_StackPos, cOptionalParam && a_ReturnedVal) { if (lua_isnoneornil(m_LuaState, a_StackPos)) { return true; } return GetStackValue(a_StackPos, a_ReturnedVal.GetDest()); } /** Retrieves any Vector3 value and coerces it into a Vector3. */ template bool GetStackValue(int a_StackPos, Vector3 & a_ReturnedVal); /** Pushes the named value in the table at the top of the stack. a_Name may be a path containing multiple table levels, such as "cChatColor.Blue". If the value is found, it is pushed on top of the stack and the returned cStackValue is valid. If the value is not found, the stack is unchanged and the returned cStackValue is invalid. */ cStackValue WalkToValue(const AString & a_Name); /** Pushes the named value in the global table to the top of the stack. a_Name may be a path containing multiple table levels, such as "cChatColor.Blue". If the value is found in the global table, it is pushed to the top of the stack and the returned cStackValue is valid. If the value is not found, the stack is unchanged and the returned cStackValue is invalid. */ cStackValue WalkToNamedGlobal(const AString & a_Name); /** Retrieves the named value in the table at the top of the Lua stack. a_Name may be a path containing multiple table levels, such as "_G.cChatColor.Blue". Returns true if the value was successfully retrieved, false on error. */ template bool GetNamedValue(const AString & a_Name, T & a_Value) { auto stk = WalkToValue(a_Name); if (!stk.IsValid()) { // Name not found return false; } return GetStackValue(-1, a_Value); } /** Retrieves the named global value. a_Name may be a path containing multiple table levels, such as "_G.cChatColor.Blue". Returns true if the value was successfully retrieved, false on error. */ template bool GetNamedGlobal(const AString & a_Name, T & a_Value) { // Push the globals table onto the stack and make it RAII-removed: lua_getglobal(m_LuaState, "_G"); cStackValue stk(*this); // Get the named global: return GetNamedValue(a_Name, a_Value); } // Include the auto-generated Push and GetStackValue() functions: #include "LuaState_Declaration.inc" /** Call the specified Lua function. Returns true if call succeeded, false if there was an error. A special param of cRet & signifies the end of param list and the start of return values. Example call: Call(Fn, Param1, Param2, Param3, cLuaState::Return, Ret1, Ret2) */ template bool Call(const FnT & a_Function, Args &&... args) { cStackBalancePopper balancer(*this); m_NumCurrentFunctionArgs = -1; if (!PushFunction(std::forward(a_Function))) { // Pushing the function failed return false; } auto res = PushCallPop(std::forward(args)...); return res; } /** Retrieves a list of values from the Lua stack, starting at the specified index. */ template inline bool GetStackValues(int a_StartStackPos, Arg1 && a_Arg1, Args &&... args) { if (!GetStackValue(a_StartStackPos, std::forward(a_Arg1))) { return false; } return GetStackValues(a_StartStackPos + 1, std::forward(args)...); } /** Returns true if the specified parameters on the stack are of the specified usertable type; also logs warning if not. Used for static functions */ bool CheckParamUserTable(int a_StartParam, const char * a_UserTable, int a_EndParam = -1); /** Returns true if the specified parameters on the stack are of the specified usertype; also logs warning if not. Used for regular functions */ bool CheckParamUserType(int a_StartParam, const char * a_UserType, int a_EndParam = -1); /** Returns true if the specified parameters on the stack are tables; also logs warning if not */ bool CheckParamTable(int a_StartParam, int a_EndParam = -1); /** Returns true if the specified parameters on the stack are numbers; also logs warning if not */ bool CheckParamNumber(int a_StartParam, int a_EndParam = -1); /** Returns true if the specified parameters on the stack are bools; also logs warning if not */ bool CheckParamBool(int a_StartParam, int a_EndParam = -1); /** Returns true if the specified parameters on the stack are strings; also logs warning if not */ bool CheckParamString(int a_StartParam, int a_EndParam = -1); /** Returns true if the specified parameters on the stack are functions; also logs warning if not */ bool CheckParamFunction(int a_StartParam, int a_EndParam = -1); /** Returns true if the specified parameters on the stack are functions or nils; also logs warning if not */ bool CheckParamFunctionOrNil(int a_StartParam, int a_EndParam = -1); /** Returns true if the specified parameters on the stack are UUIDs; also logs warning if not Accepts either cUUID instances or strings that contain UUIDs */ bool CheckParamUUID(int a_StartParam, int a_EndParam = -1); /** Returns true if the specified parameters on the stack are Vector3s; also logs warning if not. Accepts any Vector3 type instances or tables. */ bool CheckParamVector3(int a_StartParam, int a_EndParam = -1); /** Returns true if the specified parameter on the stack is nil (indicating an end-of-parameters) */ bool CheckParamEnd(int a_Param); /** Returns true if the first parameter is an instance of the expected class name. Returns false and logs a special warning ("wrong calling convention") if not. */ bool CheckParamSelf(const char * a_SelfClassName); /** Returns true if the first parameter is the expected class (static). Returns false and logs a special warning ("wrong calling convention") if not. */ bool CheckParamStaticSelf(const char * a_SelfClassName); /** Returns true if the specified parameter is of the specified class. */ bool IsParamUserType(int a_ParamIdx, const AString & a_UserType); /** Returns true if the specified parameter is a number. */ bool IsParamNumber(int a_ParamIdx); /** Returns true if the specified parameter is any of the Vector3 types. */ bool IsParamVector3(int a_ParamIdx); /** If the status is nonzero, prints the text on the top of Lua stack and returns true */ bool ReportErrors(int status); /** If the status is nonzero, prints the text on the top of Lua stack and returns true */ static bool ReportErrors(lua_State * a_LuaState, int status); /** Logs all items in the current stack trace to the server console */ void LogStackTrace(int a_StartingDepth = 0); /** Logs all items in the current stack trace to the server console */ static void LogStackTrace(lua_State * a_LuaState, int a_StartingDepth = 0); /** Prints the message, prefixed with the current function name, then logs the stack contents and raises a Lua error. To be used for bindings when they detect bad parameters. Doesn't return, but a dummy return type is provided so that Lua API functions may do "return ApiParamError(...)". */ int ApiParamError(std::string_view a_Msg); /** Returns the type of the item on the specified position in the stack */ AString GetTypeText(int a_StackPos); /** Calls the function specified by its name, with arguments copied off the foreign state. If successful, keeps the return values on the stack and returns their number. If unsuccessful, returns a negative number and keeps the stack position unchanged. */ int CallFunctionWithForeignParams( const AString & a_FunctionName, cLuaState & a_SrcLuaState, int a_SrcParamStart, int a_SrcParamEnd ); /** Copies objects on the stack from the specified state. Only numbers, bools, strings, API classes and simple tables containing these (recursively) are copied. a_NumAllowedNestingLevels specifies how many table nesting levels are allowed, copying fails if there's a deeper table. If successful, returns the number of objects copied. If failed, returns a negative number and rewinds the stack position. */ int CopyStackFrom(cLuaState & a_SrcLuaState, int a_SrcStart, int a_SrcEnd, int a_NumAllowedNestingLevels = 16); /** Copies a table at the specified stack index of the source Lua state to the top of this Lua state's stack. a_NumAllowedNestingLevels specifies how many table nesting levels are allowed, copying fails if there's a deeper table. Returns true if successful, false on failure. Can copy only simple values - numbers, bools, strings and recursively simple tables. */ bool CopyTableFrom(cLuaState & a_SrcLuaState, int a_TableIdx, int a_NumAllowedNestingLevels); /** Copies a single value from the specified stack index of the source Lua state to the top of this Lua state's stack. a_NumAllowedNestingLevels specifies how many table nesting levels are allowed, copying fails if there's a deeper table. Returns true if the value was copied, false on failure. */ bool CopySingleValueFrom(cLuaState & a_SrcLuaState, int a_StackIdx, int a_NumAllowedNestingLevels); /** Reads the value at the specified stack position as a string and sets it to a_String. */ void ToString(int a_StackPos, AString & a_String); /** Logs all the elements' types on the API stack, with an optional header for the listing. */ void LogStackValues(const char * a_Header = nullptr); /** Logs all the elements' types on the API stack, with an optional header for the listing. */ static void LogStackValues(lua_State * a_LuaState, const char * a_Header = nullptr); /** Returns the canon Lua state (the primary cLuaState instance that was used to create, rather than attach, the lua_State structure). Returns nullptr if the canon Lua state cannot be queried. */ cLuaState * QueryCanonLuaState(void) const; /** Outputs to log a warning about API call being unable to read its parameters from the stack, logs the stack trace and stack values. */ void LogApiCallParamFailure(const char * a_FnName, const char * a_ParamNames); /** Adds this object's CS to the DeadlockDetect's tracked CSs. */ void TrackInDeadlockDetect(cDeadlockDetect & a_DeadlockDetect); /** Removes this object's CS from the DeadlockDetect's tracked CSs. */ void UntrackInDeadlockDetect(cDeadlockDetect & a_DeadlockDetect); protected: cCriticalSection m_CS; lua_State * m_LuaState; /** If true, the state is owned by this object and will be auto-Closed. False => attached state */ bool m_IsOwned; /** The subsystem name is used for reporting errors to the console, it is either "plugin %s" or "LuaScript" whatever is given to the constructor. */ AString m_SubsystemName; /** Name of the currently pushed function (for the Push / Call chain) */ AString m_CurrentFunctionName; /** Number of arguments currently pushed (for the Push / Call chain) */ int m_NumCurrentFunctionArgs; /** The tracked references. The cLuaState will invalidate all of these when it is about to be closed. Protected against multithreaded access by m_CSTrackedRefs. */ std::vector m_TrackedRefs; /** Protects m_TrackedRefs against multithreaded access. */ cCriticalSection m_CSTrackedRefs; /** Call the Lua function specified by name in the table stored as a reference. Returns true if call succeeded, false if there was an error (not a table ref, function name not found). A special param of cRet & signifies the end of param list and the start of return values. Example call: CallTableFn(TableRef, "FnName", Param1, Param2, Param3, cLuaState::Return, Ret1, Ret2) */ template bool CallTableFn(const cRef & a_TableRef, const char * a_FnName, Args &&... args) { if (!PushFunction(a_TableRef, a_FnName)) { // Pushing the function failed return false; } return PushCallPop(std::forward(args)...); } /** Variadic template terminator: If there's nothing more to push / pop, just call the function. Note that there are no return values either, because those are prefixed by a cRet value, so the arg list is never empty. */ bool PushCallPop(void) { return CallFunction(0); } /** Variadic template recursor: More params to push. Push them and recurse. */ template inline bool PushCallPop(T && a_Param, Args &&... args) { Push(std::forward(a_Param)); m_NumCurrentFunctionArgs += 1; return PushCallPop(std::forward(args)...); } /** Variadic template terminator: If there's nothing more to push, but return values to collect, call the function and collect the returns. */ template bool PushCallPop(cLuaState::cRet, Args &&... args) { // Calculate the number of return values (number of args left): int NumReturns = sizeof...(args); // Call the function: if (!CallFunction(NumReturns)) { return false; } // Collect the return values: GetStackValues(-NumReturns, std::forward(args)...); lua_pop(m_LuaState, NumReturns); // All successful: return true; } /** Variadic template terminator: If there are no more values to get, bail out. This function is not available in the public API, because it's an error to request no values directly; only internal functions can do that. If you get a compile error saying this function is not accessible, check your calling code, you aren't reading any stack values. */ bool GetStackValues(int a_StartingStackPos) { return true; } /** Pushes the function of the specified name onto the stack. Returns true if successful. Logs a warning on failure (incl. m_SubsystemName) */ bool PushFunction(const char * a_FunctionName); /** Pushes a function that has been saved as a reference. Returns true if successful. Logs a warning on failure */ bool PushFunction(const cRef & a_FnRef); /** Pushes a function that is stored under the specified name in a table that has been saved as a reference. Returns true if successful. */ bool PushFunction(const cRef & a_TableRef, const char * a_FnName); /** Pushes a usertype of the specified class type onto the stack */ // void PushUserType(void * a_Object, const char * a_Type); /** Calls the function that has been pushed onto the stack by PushFunction(), with arguments pushed by PushXXX(). Returns true if successful, returns false and logs a warning on failure. Pops the function params, the function itself and the error handler off the stack. If successful, leaves a_NumReturnValues new values on Lua stack, corresponding to the return values. On failure, leaves no new values on the Lua stack. */ bool CallFunction(int a_NumReturnValues); /** Used as the error reporting function for function calls */ static int ReportFnCallErrors(lua_State * a_LuaState); /** Tries to break into the MobDebug debugger, if it is installed. */ static int BreakIntoDebugger(lua_State * a_LuaState); /** Adds the specified reference to tracking. The reference will be invalidated when this Lua state is about to be closed. */ void TrackRef(cTrackedRef & a_Ref); /** Removes the specified reference from tracking. The reference will no longer be invalidated when this Lua state is about to be closed. */ void UntrackRef(cTrackedRef & a_Ref); }; // cLuaState // Instantiate the GetStackValue(Vector3<>) function for all Vector3 types: extern template bool cLuaState::GetStackValue(int a_StackPos, Vector3d & a_ReturnedVal); extern template bool cLuaState::GetStackValue(int a_StackPos, Vector3f & a_ReturnedVal); extern template bool cLuaState::GetStackValue(int a_StackPos, Vector3i & a_ReturnedVal); /** Keeps track of all create cLuaState instances. Can query each for the amount of currently used memory. */ class cLuaStateTracker { public: /** Adds the specified Lua state to the internal list of LuaStates. */ static void Add(cLuaState & a_LuaState); /** Deletes the specified Lua state from the internal list of LuaStates. */ static void Del(cLuaState & a_LuaState); /** Returns the statistics for all the registered LuaStates. */ static AString GetStats(void); protected: typedef cLuaState * cLuaStatePtr; typedef std::vector cLuaStatePtrs; /** The internal list of LuaStates. Protected against multithreaded access by m_CSLuaStates. */ cLuaStatePtrs m_LuaStates; /** Protects m_LuaStates against multithreaded access. */ cCriticalSection m_CSLuaStates; /** Returns the single instance of this class. */ static cLuaStateTracker & Get(void); }; ================================================ FILE: src/Bindings/LuaTCPLink.cpp ================================================ // LuaTCPLink.cpp // Implements the cLuaTCPLink class representing a Lua wrapper for the cTCPLink class and the callbacks it needs #include "Globals.h" #include "LuaTCPLink.h" #include "LuaServerHandle.h" #include "../mbedTLS++/X509Cert.h" #include "../mbedTLS++/CryptoKey.h" cLuaTCPLink::cLuaTCPLink(cLuaState::cTableRefPtr && a_Callbacks): m_Callbacks(std::move(a_Callbacks)) { } cLuaTCPLink::cLuaTCPLink(cLuaState::cTableRefPtr && a_Callbacks, cLuaServerHandleWPtr a_ServerHandle): m_Callbacks(std::move(a_Callbacks)), m_Server(std::move(a_ServerHandle)) { } cLuaTCPLink::~cLuaTCPLink() { // If the link is still open, close it: auto link = m_Link; if (link != nullptr) { link->Close(); } Terminated(); } bool cLuaTCPLink::Send(const AString & a_Data) { // Safely grab a copy of the link: auto link = m_Link; if (link == nullptr) { return false; } // Send the data: return link->Send(a_Data); } AString cLuaTCPLink::GetLocalIP(void) const { // Safely grab a copy of the link: auto link = m_Link; if (link == nullptr) { return ""; } // Get the IP address: return link->GetLocalIP(); } UInt16 cLuaTCPLink::GetLocalPort(void) const { // Safely grab a copy of the link: auto link = m_Link; if (link == nullptr) { return 0; } // Get the port: return link->GetLocalPort(); } AString cLuaTCPLink::GetRemoteIP(void) const { // Safely grab a copy of the link: cTCPLinkPtr link = m_Link; if (link == nullptr) { return ""; } // Get the IP address: return link->GetRemoteIP(); } UInt16 cLuaTCPLink::GetRemotePort(void) const { // Safely grab a copy of the link: cTCPLinkPtr link = m_Link; if (link == nullptr) { return 0; } // Get the port: return link->GetRemotePort(); } void cLuaTCPLink::Shutdown(void) { // Safely grab a copy of the link and shut it down: cTCPLinkPtr link = m_Link; if (link != nullptr) { link->Shutdown(); } } void cLuaTCPLink::Close(void) { // If the link is still open, close it: cTCPLinkPtr link = m_Link; if (link != nullptr) { link->Close(); } Terminated(); } AString cLuaTCPLink::StartTLSClient( const AString & a_OwnCertData, const AString & a_OwnPrivKeyData, const AString & a_OwnPrivKeyPassword, const AString & a_TrustedRootCAs ) { auto link = m_Link; if (link != nullptr) { cX509CertPtr ownCert; if (!a_OwnCertData.empty()) { ownCert = std::make_shared(); auto res = ownCert->Parse(a_OwnCertData.data(), a_OwnCertData.size()); if (res != 0) { return fmt::format(FMT_STRING("Cannot parse client certificate: -0x{:x}"), -res); } } cCryptoKeyPtr ownPrivKey; if (!a_OwnPrivKeyData.empty()) { ownPrivKey = std::make_shared(); auto res = ownPrivKey->ParsePrivate(a_OwnPrivKeyData.data(), a_OwnPrivKeyData.size(), a_OwnPrivKeyPassword); if (res != 0) { return fmt::format(FMT_STRING("Cannot parse client private key: -0x{:x}"), -res); } } cX509CertPtr trustedRootCAs; if (!a_TrustedRootCAs.empty()) { trustedRootCAs = std::make_shared(); auto res = trustedRootCAs->Parse(a_TrustedRootCAs.data(), a_TrustedRootCAs.size()); if (res != 0) { return fmt::format("Cannot parse trusted root CAs: {}", res); } } return link->StartTLSClient(ownCert, ownPrivKey, trustedRootCAs); } return ""; } AString cLuaTCPLink::StartTLSServer( const AString & a_OwnCertData, const AString & a_OwnPrivKeyData, const AString & a_OwnPrivKeyPassword, const AString & a_StartTLSData ) { auto link = m_Link; if (link != nullptr) { // Create the peer cert: auto OwnCert = std::make_shared(); int res = OwnCert->Parse(a_OwnCertData.data(), a_OwnCertData.size()); if (res != 0) { return fmt::format(FMT_STRING("Cannot parse server certificate: -0x{:x}"), -res); } auto OwnPrivKey = std::make_shared(); res = OwnPrivKey->ParsePrivate(a_OwnPrivKeyData.data(), a_OwnPrivKeyData.size(), a_OwnPrivKeyPassword); if (res != 0) { return fmt::format(FMT_STRING("Cannot parse server private key: -0x{:x}"), -res); } return link->StartTLSServer(OwnCert, OwnPrivKey, a_StartTLSData); } return ""; } void cLuaTCPLink::Terminated(void) { // Disable the callbacks: if (m_Callbacks->IsValid()) { m_Callbacks->Clear(); } // If the managing server is still alive, let it know we're terminating: auto Server = m_Server.lock(); if (Server != nullptr) { Server->RemoveLink(this); } // If the link is still open, close it: { auto link= m_Link; if (link != nullptr) { link->Close(); m_Link.reset(); } } } void cLuaTCPLink::ReceivedCleartextData(const char * a_Data, size_t a_NumBytes) { // Call the callback: m_Callbacks->CallTableFn("OnReceivedData", this, AString(a_Data, a_NumBytes)); } void cLuaTCPLink::OnConnected(cTCPLink & a_Link) { // Call the callback: m_Callbacks->CallTableFn("OnConnected", this); } void cLuaTCPLink::OnError(int a_ErrorCode, const AString & a_ErrorMsg) { // Call the callback: m_Callbacks->CallTableFn("OnError", this, a_ErrorCode, a_ErrorMsg); // Terminate all processing on the link: Terminated(); } void cLuaTCPLink::OnLinkCreated(cTCPLinkPtr a_Link) { // Store the cTCPLink for later use: m_Link = a_Link; } void cLuaTCPLink::OnReceivedData(const char * a_Data, size_t a_Length) { // Call the callback: m_Callbacks->CallTableFn("OnReceivedData", this, AString(a_Data, a_Length)); } void cLuaTCPLink::OnRemoteClosed(void) { // Call the callback: m_Callbacks->CallTableFn("OnRemoteClosed", this); // Terminate all processing on the link: Terminated(); } ================================================ FILE: src/Bindings/LuaTCPLink.h ================================================ // LuaTCPLink.h // Declares the cLuaTCPLink class representing a Lua wrapper for the cTCPLink class and the callbacks it needs #pragma once #include "../OSSupport/Network.h" #include "LuaState.h" // fwd: class cLuaServerHandle; typedef std::weak_ptr cLuaServerHandleWPtr; class cLuaTCPLink: public cNetwork::cConnectCallbacks, public cTCPLink::cCallbacks { public: /** Creates a new instance of the link, wrapping the callbacks that are in the specified table. */ cLuaTCPLink(cLuaState::cTableRefPtr && a_Callbacks); /** Creates a new instance of the link, attached to the specified plugin and wrapping the callbacks that are in the specified referenced table. */ cLuaTCPLink(cLuaState::cTableRefPtr && a_Callbacks, cLuaServerHandleWPtr a_Server); virtual ~cLuaTCPLink() override; /** Sends the data contained in the string to the remote peer. Returns true if successful, false on immediate failure (queueing the data failed or link not available). */ bool Send(const AString & a_Data); /** Returns the IP address of the local endpoint of the connection. */ AString GetLocalIP(void) const; /** Returns the port used by the local endpoint of the connection. */ UInt16 GetLocalPort(void) const; /** Returns the IP address of the remote endpoint of the connection. */ AString GetRemoteIP(void) const; /** Returns the port used by the remote endpoint of the connection. */ UInt16 GetRemotePort(void) const; /** Closes the link gracefully. The link will send any queued outgoing data, then it will send the FIN packet. The link will still receive incoming data from remote until the remote closes the connection. */ void Shutdown(void); /** Drops the connection without any more processing. Sends the RST packet, queued outgoing and incoming data is lost. */ void Close(void); /** Starts a TLS handshake as a client connection. If a client certificate should be used for the connection, set the certificate into a_OwnCertData and its corresponding private key to a_OwnPrivKeyData. If both are empty, no client cert is presented. a_OwnPrivKeyPassword is the password to be used for decoding PrivKey, empty if not passworded. a_TrustedRootCAs is a \n-delimited concatenation of trusted root CAs' certificates in PEM format Returns empty string on success, non-empty error description on failure. */ AString StartTLSClient( const AString & a_OwnCertData, const AString & a_OwnPrivKeyData, const AString & a_OwnPrivKeyPassword, const AString & a_TrustedRootCAs ); /** Starts a TLS handshake as a server connection. Set the server certificate into a_CertData and its corresponding private key to a_OwnPrivKeyData. a_OwnPrivKeyPassword is the password to be used for decoding PrivKey, empty if not passworded. a_StartTLSData is any data that should be pushed into the TLS before reading more data from the remote. This is used mainly for protocols starting TLS in the middle of communication, when the TLS start command can be received together with the TLS Client Hello message in one OnReceivedData() call, to re-queue the Client Hello message into the TLS handshake buffer. Returns empty string on success, non-empty error description on failure. */ AString StartTLSServer( const AString & a_OwnCertData, const AString & a_OwnPrivKeyData, const AString & a_OwnPrivKeyPassword, const AString & a_StartTLSData ); protected: /** The Lua table that holds the callbacks to be invoked. */ cLuaState::cTableRefPtr m_Callbacks; /** The underlying link representing the connection. May be nullptr. */ cTCPLinkPtr m_Link; /** The server that is responsible for this link, if any. */ cLuaServerHandleWPtr m_Server; /** Common code called when the link is considered as terminated. Releases m_Link, m_Callbacks and this from m_Server, each when applicable. */ void Terminated(void); /** Called by the SSL context when there's incoming data available in the cleartext. Reports the data via the Lua callback function. */ void ReceivedCleartextData(const char * a_Data, size_t a_NumBytes); // cNetwork::cConnectCallbacks overrides: virtual void OnConnected(cTCPLink & a_Link) override; virtual void OnError(int a_ErrorCode, const AString & a_ErrorMsg) override; // cTCPLink::cCallbacks overrides: virtual void OnLinkCreated(cTCPLinkPtr a_Link) override; virtual void OnReceivedData(const char * a_Data, size_t a_Length) override; virtual void OnRemoteClosed(void) override; // The OnError() callback is shared with cNetwork::cConnectCallbacks }; ================================================ FILE: src/Bindings/LuaUDPEndpoint.cpp ================================================ // LuaUDPEndpoint.cpp // Implements the cLuaUDPEndpoint class representing a Lua wrapper for the cUDPEndpoint class and the callbacks it needs #include "Globals.h" #include "LuaUDPEndpoint.h" cLuaUDPEndpoint::cLuaUDPEndpoint(cLuaState::cTableRefPtr && a_Callbacks): m_Callbacks(std::move(a_Callbacks)) { } cLuaUDPEndpoint::~cLuaUDPEndpoint() { // If the endpoint is still open, close it: auto endpoint = m_Endpoint; if (endpoint != nullptr) { endpoint->Close(); } Terminated(); } bool cLuaUDPEndpoint::Open(UInt16 a_Port, cLuaUDPEndpointPtr a_Self) { ASSERT(m_Self == nullptr); // Must not be opened yet ASSERT(m_Endpoint == nullptr); m_Self = std::move(a_Self); m_Endpoint = cNetwork::CreateUDPEndpoint(a_Port, *this); return m_Endpoint->IsOpen(); } bool cLuaUDPEndpoint::Send(const AString & a_Data, const AString & a_RemotePeer, UInt16 a_RemotePort) { // Safely grab a copy of the endpoint: auto endpoint = m_Endpoint; if (endpoint == nullptr) { return false; } // Send the data: return endpoint->Send(a_Data, a_RemotePeer, a_RemotePort); } UInt16 cLuaUDPEndpoint::GetPort(void) const { // Safely grab a copy of the endpoint: auto endpoint = m_Endpoint; if (endpoint == nullptr) { return 0; } // Get the port: return endpoint->GetPort(); } bool cLuaUDPEndpoint::IsOpen(void) const { // Safely grab a copy of the endpoint: auto endpoint = m_Endpoint; if (endpoint == nullptr) { // No endpoint means that we're not open return false; } // Get the state: return endpoint->IsOpen(); } void cLuaUDPEndpoint::Close(void) { // If the endpoint is still open, close it: auto endpoint = m_Endpoint; if (endpoint != nullptr) { endpoint->Close(); m_Endpoint.reset(); } Terminated(); } void cLuaUDPEndpoint::EnableBroadcasts(void) { // Safely grab a copy of the endpoint: auto endpoint = m_Endpoint; if (endpoint != nullptr) { endpoint->EnableBroadcasts(); } } void cLuaUDPEndpoint::Release(void) { // Close the endpoint, if not already closed: Close(); // Allow self to deallocate: m_Self.reset(); } void cLuaUDPEndpoint::Terminated(void) { // Disable the callbacks: m_Callbacks.reset(); // If the endpoint is still open, close it: { auto endpoint = m_Endpoint; if (endpoint != nullptr) { endpoint->Close(); m_Endpoint.reset(); } } } void cLuaUDPEndpoint::OnReceivedData(const char * a_Data, size_t a_NumBytes, const AString & a_RemotePeer, UInt16 a_RemotePort) { m_Callbacks->CallTableFn("OnReceivedData", this, AString(a_Data, a_NumBytes), a_RemotePeer, a_RemotePort); } void cLuaUDPEndpoint::OnError(int a_ErrorCode, const AString & a_ErrorMsg) { // Notify the plugin: m_Callbacks->CallTableFn("OnError", a_ErrorCode, a_ErrorMsg); // Terminate all processing on the endpoint: Terminated(); } ================================================ FILE: src/Bindings/LuaUDPEndpoint.h ================================================ // LuaUDPEndpoint.h // Declares the cLuaUDPEndpoint class representing a Lua wrapper for the cUDPEndpoint class and the callbacks it needs #pragma once #include "../OSSupport/Network.h" #include "LuaState.h" // fwd: class cLuaUDPEndpoint; typedef std::shared_ptr cLuaUDPEndpointPtr; class cLuaUDPEndpoint: public cUDPEndpoint::cCallbacks { public: /** Creates a new instance of the endpoint, wrapping the callbacks that are in the specified table. */ cLuaUDPEndpoint(cLuaState::cTableRefPtr && a_Callbacks); virtual ~cLuaUDPEndpoint() override; /** Opens the endpoint so that it starts listening for incoming data on the specified port. a_Self is the shared pointer to self that the object keeps to keep itself alive for as long as it needs (for Lua). */ bool Open(UInt16 a_Port, cLuaUDPEndpointPtr a_Self); /** Sends the data contained in the string to the specified remote peer. Returns true if successful, false on immediate failure (queueing the data failed etc.) */ bool Send(const AString & a_Data, const AString & a_RemotePeer, UInt16 a_RemotePort); /** Returns the port on which endpoint is listening for incoming data. */ UInt16 GetPort(void) const; /** Returns true if the endpoint is open for incoming data. */ bool IsOpen(void) const; /** Closes the UDP listener. */ void Close(void); /** Enables outgoing broadcasts to be made using this endpoint. */ void EnableBroadcasts(void); /** Called when Lua garbage-collects the object. Releases the internal SharedPtr to self, so that the instance may be deallocated. */ void Release(void); protected: /** The Lua table that holds the callbacks to be invoked. */ cLuaState::cTableRefPtr m_Callbacks; /** SharedPtr to self, so that the object can keep itself alive for as long as it needs (for Lua). */ cLuaUDPEndpointPtr m_Self; /** The underlying network endpoint. May be nullptr. */ cUDPEndpointPtr m_Endpoint; /** Common code called when the endpoint is considered as terminated. Releases m_Endpoint and m_Callbacks, each when applicable. */ void Terminated(void); // cUDPEndpoint::cCallbacks overrides: virtual void OnError(int a_ErrorCode, const AString & a_ErrorMsg) override; virtual void OnReceivedData(const char * a_Data, size_t a_Size, const AString & a_RemotePeer, UInt16 a_RemotePort) override; }; ================================================ FILE: src/Bindings/LuaWindow.cpp ================================================ // LuaWindow.cpp // Implements the cLuaWindow class representing a virtual window that plugins may create and open for the player #include "Globals.h" #include "LuaWindow.h" #include "../Entities/Player.h" #include "../UI/SlotArea.h" #include "PluginLua.h" extern "C" { #include "lua/src/lauxlib.h" // Needed for LUA_REFNIL } #include "../Root.h" #include "../ClientHandle.h" //////////////////////////////////////////////////////////////////////////////// // cLuaWindow: cLuaWindow::cLuaWindow(cLuaState & a_LuaState, cWindow::WindowType a_WindowType, int a_SlotsX, int a_SlotsY, const AString & a_Title) : Super(a_WindowType, a_Title), m_Contents(a_SlotsX, a_SlotsY), m_LuaState(a_LuaState.QueryCanonLuaState()) { ASSERT(m_LuaState != nullptr); // We must have a valid Lua state; this assert fails only if there was no Canon Lua state m_Contents.AddListener(*this); m_SlotAreas.push_back(new cSlotAreaItemGrid(m_Contents, *this)); // If appropriate, add an Armor slot area: switch (a_WindowType) { case cWindow::wtInventory: case cWindow::wtWorkbench: { m_SlotAreas.push_back(new cSlotAreaArmor(*this)); break; } default: { break; } } m_SlotAreas.push_back(new cSlotAreaInventory(*this)); m_SlotAreas.push_back(new cSlotAreaHotBar(*this)); } cLuaWindow::~cLuaWindow() { m_Contents.RemoveListener(*this); // Close open lua window from players, to avoid dangling pointers cRoot::Get()->ForEachPlayer([this](cPlayer & a_Player) { if (a_Player.GetWindow() == this) { a_Player.CloseWindow(false); } return false; } ); // Must delete slot areas now, because they are referencing this->m_Contents and would try to access it in cWindow's // destructor, when the member is already gone. for (cSlotAreas::iterator itr = m_SlotAreas.begin(), end = m_SlotAreas.end(); itr != end; ++itr) { delete *itr; } m_SlotAreas.clear(); ASSERT(m_OpenedBy.empty()); } void cLuaWindow::SetOnClicked(cLuaState::cCallbackPtr && a_OnClicked) { // Only one Lua state can be a cLuaWindow object callback: ASSERT(a_OnClicked->IsSameLuaState(*m_LuaState)); // Store the new reference, releasing the old one if appropriate: m_OnClicked = std::move(a_OnClicked); } void cLuaWindow::SetOnClosing(cLuaState::cCallbackPtr && a_OnClosing) { // Only one Lua state can be a cLuaWindow object callback: ASSERT(a_OnClosing->IsSameLuaState(*m_LuaState)); // Store the new reference, releasing the old one if appropriate: m_OnClosing = std::move(a_OnClosing); } void cLuaWindow::SetOnSlotChanged(cLuaState::cCallbackPtr && a_OnSlotChanged) { // Only one Lua state can be a cLuaWindow object callback: ASSERT(a_OnSlotChanged->IsSameLuaState(*m_LuaState)); // Store the new reference, releasing the old one if appropriate: m_OnSlotChanged = std::move(a_OnSlotChanged); } void cLuaWindow::OpenedByPlayer(cPlayer & a_Player) { // If the first player is opening the window, create a Lua Reference to the window object so that Lua will not GC it until the last player closes the window: if (m_PlayerCount == 0) { m_LuaRef.CreateFromObject(*m_LuaState, this); } ++m_PlayerCount; Super::OpenedByPlayer(a_Player); } bool cLuaWindow::ClosedByPlayer(cPlayer & a_Player, bool a_CanRefuse) { // First notify the plugin through the registered callback: if (m_OnClosing != nullptr) { bool res; if ( m_OnClosing->Call(this, &a_Player, a_CanRefuse, cLuaState::Return, res) && // The callback succeeded res // The callback says not to close the window ) { // The callback disagrees (the higher levels check the CanRefuse flag compliance) return false; } } // If the last player has closed the window, release the Lua reference, so that Lua may GC the object: --m_PlayerCount; if (m_PlayerCount == 0) { m_LuaRef.UnRef(); } return Super::ClosedByPlayer(a_Player, a_CanRefuse); } void cLuaWindow::Destroy(void) { Super::Destroy(); // Lua will take care of this object, it will garbage-collect it, so we must not delete it! m_IsDestroyed = false; } void cLuaWindow::DistributeStack(cItem & a_ItemStack, int a_Slot, cPlayer & a_Player, cSlotArea * a_ClickedArea, bool a_ShouldApply) { cSlotAreas Areas; for (auto && Area : m_SlotAreas) { if (Area != a_ClickedArea) { Areas.push_back(Area); } } Super::DistributeStackToAreas(a_ItemStack, a_Player, Areas, a_ShouldApply, false); } void cLuaWindow::OnSlotChanged(cItemGrid * a_ItemGrid, int a_SlotNum) { ASSERT(a_ItemGrid == &m_Contents); // If an OnSlotChanged callback has been registered, call it: if (m_OnSlotChanged != nullptr) { m_OnSlotChanged->Call(this, a_SlotNum); } } void cLuaWindow::Clicked(cPlayer & a_Player, int a_WindowID, short a_SlotNum, eClickAction a_ClickAction, const cItem & a_ClickedItem) { if (m_OnClicked != nullptr) { // Plugin can stop a click bool res; if (m_OnClicked->Call(this, &a_Player, a_SlotNum, a_ClickAction, a_ClickedItem, cLuaState::Return, res) && res) { // Tell the client the actual state of the window a_Player.GetClientHandle()->SendInventorySlot(-1, -1, a_Player.GetDraggingItem()); BroadcastWholeWindow(); return; } } cWindow::Clicked(a_Player, a_WindowID, a_SlotNum, a_ClickAction, a_ClickedItem); } ================================================ FILE: src/Bindings/LuaWindow.h ================================================ // LuaWindow.h // Declares the cLuaWindow class representing a virtual window that plugins may create and open for the player #pragma once #include "LuaState.h" #include "../UI/Window.h" #include "../ItemGrid.h" class cPlayer; typedef cFunctionRef cPlayerListCallback; /** A window that has been created by a Lua plugin and is handled entirely by that plugin This object needs extra care with its lifetime management: - It is created by Lua, so Lua expects to garbage-collect it later - Normal cWindow objects are deleted in their ClosedByPlayer() function if the last player closes them To overcome this, this object overloads the Destroy functions, which doesn't let the ClosedByPlayer() delete the window, but rather leaves it dangling, with only Lua having the reference to it. - Lua could GC the window while a player is still using it The object creates a Lua reference to itself when opened by a player and removes the reference when the last player closes the window. */ // tolua_begin class cLuaWindow : public cWindow // tolua_end , public cItemGrid::cListener { // tolua_export using Super = cWindow; public: /** Create a window of the specified type, with a slot grid of a_SlotsX * a_SlotsY size. Exported in ManualBindings.cpp */ cLuaWindow(cLuaState & a_LuaState, cWindow::WindowType a_WindowType, int a_SlotsX, int a_SlotsY, const AString & a_Title); // tolua_begin virtual ~cLuaWindow() override; /** Returns the internal representation of the contents that are manipulated by Lua */ cItemGrid & GetContents(void) { return m_Contents; } // tolua_end /** Sets the Lua callback to call when the player clicks on the window. The window can stop the click from propogating. */ void SetOnClicked(cLuaState::cCallbackPtr && a_OnClicked); /** Sets the Lua callback function to call when the window is about to close */ void SetOnClosing(cLuaState::cCallbackPtr && a_OnClosing); /** Sets the Lua callback function to call when a slot is changed */ void SetOnSlotChanged(cLuaState::cCallbackPtr && a_OnSlotChanged); protected: /** Contents of the non-inventory part */ cItemGrid m_Contents; /** The canon Lua state that has opened the window and owns the m_LuaRef */ cLuaState * m_LuaState; /** The Lua callback to call when the player clicked on a slot */ cLuaState::cCallbackPtr m_OnClicked; /** The Lua callback to call when the window is closing for any player */ cLuaState::cCallbackPtr m_OnClosing; /** The Lua callback to call when a slot has changed */ cLuaState::cCallbackPtr m_OnSlotChanged; /** Number of players that are currently using the window. Used to manager the m_LuaRef lifetime. */ std::atomic m_PlayerCount; /** Reference to self, to keep Lua from GCing the object while a player is still using it. Created when the first player opens the window, destroyed when the last player closes the window. */ cLuaState::cRef m_LuaRef; // cWindow overrides: virtual void OpenedByPlayer(cPlayer & a_Player) override; virtual void Clicked( cPlayer & a_Player, int a_WindowID, short a_SlotNum, eClickAction a_ClickAction, const cItem & a_ClickedItem ) override; virtual bool ClosedByPlayer(cPlayer & a_Player, bool a_CanRefuse) override; virtual void Destroy(void) override; virtual void DistributeStack(cItem & a_ItemStack, int a_Slot, cPlayer & a_Player, cSlotArea * a_ClickedArea, bool a_ShouldApply) override; // cItemGrid::cListener overrides: virtual void OnSlotChanged(cItemGrid * a_ItemGrid, int a_SlotNum) override; } ; // tolua_export ================================================ FILE: src/Bindings/ManualBindings.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "ManualBindings.h" #undef TOLUA_TEMPLATE_BIND #include #include #include "tolua++/include/tolua++.h" #include "mbedtls/md5.h" #include "mbedtls/sha1.h" #include "PluginLua.h" #include "PluginManager.h" #include "LuaWindow.h" #include "../BlockArea.h" #include "../BlockEntities/BeaconEntity.h" #include "../BlockEntities/BrewingstandEntity.h" #include "../BlockEntities/ChestEntity.h" #include "../BlockEntities/CommandBlockEntity.h" #include "../BlockEntities/DispenserEntity.h" #include "../BlockEntities/DropperEntity.h" #include "../BlockEntities/FurnaceEntity.h" #include "../BlockEntities/HopperEntity.h" #include "../BlockEntities/NoteEntity.h" #include "../BlockEntities/MobHeadEntity.h" #include "../BlockEntities/FlowerPotEntity.h" #include "../BoundingBox.h" #include "BuildInfo.h" #include "../ClientHandle.h" #include "../CommandOutput.h" #include "../CompositeChat.h" #include "../Entities/Player.h" #include "../Generating/ChunkDesc.h" #include "../HTTP/UrlParser.h" #include "../Item.h" #include "../LineBlockTracer.h" #include "../Server.h" #include "../Root.h" #include "../StringCompression.h" #include "../WebAdmin.h" #include "../World.h" // Hotpatching the Macro to prevent a Clang Warning (0 for pointer used) #undef lua_tostring #define lua_tostring(L, i) lua_tolstring(L, (i), nullptr) //////////////////////////////////////////////////////////////////////////////// // LuaCommandHandler: /** Defines a bridge between cPluginManager::cCommandHandler and cLuaState::cCallback. */ class LuaCommandHandler: public cPluginManager::cCommandHandler { public: LuaCommandHandler(cLuaState::cCallbackPtr && a_Callback): m_Callback(std::move(a_Callback)) { } virtual bool ExecuteCommand( const AStringVector & a_Split, cPlayer * a_Player, const AString & a_Command, cCommandOutputCallback * a_Output ) override { bool res = false; AString s; if (!m_Callback->Call(a_Split, a_Player, a_Command, cLuaState::Return, res, s)) { return false; } if (res && (a_Output != nullptr) && !s.empty()) { a_Output->Out(s); } return res; } protected: cLuaState::cCallbackPtr m_Callback; }; //////////////////////////////////////////////////////////////////////////////// // cManualBindings: // Better error reporting for Lua int cManualBindings::tolua_do_error(lua_State * L, const char * a_pMsg, tolua_Error * a_pToLuaError) { // Retrieve current function name lua_Debug entry; VERIFY(lua_getstack(L, 0, &entry)); VERIFY(lua_getinfo(L, "n", &entry)); // Insert function name into error msg AString msg(a_pMsg); ReplaceString(msg, "#funcname#", entry.name?entry.name:"?"); // Send the error to Lua tolua_error(L, msg.c_str(), a_pToLuaError); return 0; } int cManualBindings::vlua_do_error(lua_State * L, const char * a_pFormat, fmt::printf_args a_ArgList) { // Retrieve current function name lua_Debug entry; VERIFY(lua_getstack(L, 0, &entry)); VERIFY(lua_getinfo(L, "n", &entry)); // Insert function name into error msg AString msg(a_pFormat); ReplaceString(msg, "#funcname#", (entry.name != nullptr) ? entry.name : "?"); // Copied from luaL_error and modified luaL_where(L, 1); auto Msg = fmt::vsprintf(msg, a_ArgList); lua_pushlstring(L, Msg.data(), Msg.size()); lua_concat(L, 2); return lua_error(L); } // Lua bound functions with special return types static int tolua_Clamp(lua_State * tolua_S) { cLuaState LuaState(tolua_S); int NumArgs = lua_gettop(LuaState); if (NumArgs != 3) { return cManualBindings::lua_do_error(LuaState, "Error in function call '#funcname#': Requires 3 arguments, got %i", NumArgs); } if (!lua_isnumber(LuaState, 1) || !lua_isnumber(LuaState, 2) || !lua_isnumber(LuaState, 3)) { return cManualBindings::lua_do_error(LuaState, "Error in function call '#funcname#': Expected a number for parameters #1, #2 and #3"); } lua_Number Number = tolua_tonumber(LuaState, 1, 0); lua_Number Min = tolua_tonumber(LuaState, 2, 0); lua_Number Max = tolua_tonumber(LuaState, 3, 0); lua_Number Result = Clamp(Number, Min, Max); LuaState.Push(Result); return 1; } static int tolua_CompressStringZLIB(lua_State * tolua_S) { cLuaState S(tolua_S); if ( !S.CheckParamString(1) || ( !S.CheckParamNumber(2) && !S.CheckParamEnd(2) ) ) { cLuaState::LogStackTrace(tolua_S); return 0; } // Get the params: AString ToCompress; int CompressionLevel = 5; S.GetStackValues(1, ToCompress, CompressionLevel); // Compress the string: S.Push(Compression::Compressor(CompressionLevel).CompressZLib(ToCompress.data(), ToCompress.size()).GetView()); return 1; } static int tolua_UncompressStringZLIB(lua_State * tolua_S) { cLuaState S(tolua_S); if ( !S.CheckParamString(1) || !S.CheckParamNumber(2) ) { cLuaState::LogStackTrace(tolua_S); return 0; } // Get the params: ContiguousByteBuffer ToUncompress; size_t UncompressedSize = 0; S.GetStackValues(1, ToUncompress, UncompressedSize); try { // Decompress the string: S.Push(Compression::Extractor().ExtractZLib(ToUncompress, UncompressedSize).GetView()); } catch (const std::exception & Oops) { LOGWARNING(Oops.what()); cLuaState::LogStackTrace(tolua_S); return 0; } return 1; } static int tolua_CompressStringGZIP(lua_State * tolua_S) { cLuaState S(tolua_S); if ( !S.CheckParamString(1) || !S.CheckParamEnd(2) ) { cLuaState::LogStackTrace(tolua_S); return 0; } // Get the params: ContiguousByteBuffer ToCompress; S.GetStackValues(1, ToCompress); // Compress the string: S.Push(Compression::Compressor().CompressGZip(ToCompress).GetView()); return 1; } static int tolua_InflateString(lua_State * tolua_S) { cLuaState S(tolua_S); if ( !S.CheckParamString(1) || !S.CheckParamEnd(2) ) { cLuaState::LogStackTrace(tolua_S); return 0; } // Get the params: ContiguousByteBuffer ToUncompress; S.GetStackValues(1, ToUncompress); try { // Decompress the string: S.Push(Compression::Extractor().ExtractZLib(ToUncompress).GetView()); } catch (const std::exception & Oops) { LOGWARNING(Oops.what()); cLuaState::LogStackTrace(tolua_S); return 0; } return 1; } static int tolua_StringSplit(lua_State * tolua_S) { // Get the params: cLuaState LuaState(tolua_S); AString str, delim; LuaState.GetStackValues(1, str, delim); // Execute and push the result: LuaState.Push(StringSplit(str, delim)); return 1; } static int tolua_StringSplitWithQuotes(lua_State * tolua_S) { cLuaState S(tolua_S); AString str; AString delim; S.GetStackValues(1, str, delim); AStringVector Split = StringSplitWithQuotes(str, delim); S.Push(Split); return 1; } static int tolua_StringSplitAndTrim(lua_State * tolua_S) { // Check params: cLuaState L(tolua_S); if ( !L.CheckParamString(1, 2) || !L.CheckParamEnd(3) ) { return 0; } // Process: AString str, delim; L.GetStackValues(1, str, delim); L.Push(StringSplitAndTrim(str, delim)); return 1; } /** Prints the message to the console, optionally formatting it with a plugin name prefix if the second param on the Lua stack is true. */ static void LogFromLuaStack(lua_State * tolua_S, const std::string_view a_Message, const eLogLevel a_LogLevel) { if (lua_isboolean(tolua_S, 2) && (lua_toboolean(tolua_S, 2) == 1)) { Logger::LogSimple(a_Message, a_LogLevel); } else { Logger::LogSimple(fmt::format("[{}] {}", cManualBindings::GetLuaPlugin(tolua_S)->GetName(), a_Message), a_LogLevel); } } /** Retrieves a string log message from the first param on the Lua stack, optionally prefixes it with plugin name, and prints it to the console. */ static void LogFromLuaStack(lua_State * tolua_S, const eLogLevel a_LogLevel) { cLuaState L(tolua_S); // If there's no param, spit out an error message instead of crashing: if (!L.CheckParamString(1)) { return; } std::string_view Message; L.GetStackValue(1, Message); LogFromLuaStack(tolua_S, Message, a_LogLevel); } static int tolua_LOG(lua_State * tolua_S) { // If the param is a cCompositeChat, read the data from it: tolua_Error err; if (tolua_isusertype(tolua_S, 1, "cCompositeChat", false, &err)) { const auto CompositeChat = static_cast(tolua_tousertype(tolua_S, 1, nullptr)); if (CompositeChat != nullptr) // isusertype returns true for nil values { LogFromLuaStack(tolua_S, CompositeChat->ExtractText(), cCompositeChat::MessageTypeToLogLevel(CompositeChat->GetMessageType())); return 0; } } // Log the message: LogFromLuaStack(tolua_S, eLogLevel::Regular); return 0; } static int tolua_LOGINFO(lua_State * tolua_S) { LogFromLuaStack(tolua_S, eLogLevel::Info); return 0; } static int tolua_LOGWARN(lua_State * tolua_S) { LogFromLuaStack(tolua_S, eLogLevel::Warning); return 0; } static int tolua_LOGERROR(lua_State * tolua_S) { LogFromLuaStack(tolua_S, eLogLevel::Error); return 0; } static int tolua_Base64Encode(lua_State * tolua_S) { cLuaState L(tolua_S); if ( !L.CheckParamString(1) || !L.CheckParamEnd(2) ) { return 0; } AString Src; L.GetStackValue(1, Src); AString res = Base64Encode(Src); L.Push(res); return 1; } static int tolua_Base64Decode(lua_State * tolua_S) { cLuaState L(tolua_S); if ( !L.CheckParamString(1) || !L.CheckParamEnd(2) ) { return 0; } AString Src; L.GetStackValue(1, Src); AString res = Base64Decode(Src); L.Push(res); return 1; } cPluginLua * cManualBindings::GetLuaPlugin(lua_State * L) { // Get the plugin identification out of LuaState: lua_getglobal(L, LUA_PLUGIN_INSTANCE_VAR_NAME); if (!lua_islightuserdata(L, -1)) { LOGWARNING("%s: cannot get plugin instance, what have you done to my Lua state?", __FUNCTION__); lua_pop(L, 1); return nullptr; } cPluginLua * Plugin = static_cast(const_cast(lua_topointer(L, -1))); lua_pop(L, 1); return Plugin; } static int tolua_cFile_ChangeFileExt(lua_State * tolua_S) { // API signature: // ChangeFileExt(string, string) -> string // Check params: cLuaState L(tolua_S); if ( !L.CheckParamUserTable(1, "cFile") || !L.CheckParamString(2, 3) || !L.CheckParamEnd(4) ) { return 0; } // Execute: AString FileName, NewExt; VERIFY(L.GetStackValues(2, FileName, NewExt)); L.Push(cFile::ChangeFileExt(FileName, NewExt)); return 1; } static int tolua_cFile_Copy(lua_State * tolua_S) { // API signature: // cFile:Copy(string, string) -> bool // Check params: cLuaState L(tolua_S); if ( !L.CheckParamUserTable(1, "cFile") || !L.CheckParamString(2, 3) || !L.CheckParamEnd(4) ) { return 0; } // Execute: AString SrcFile, DstFile; VERIFY(L.GetStackValues(2, SrcFile, DstFile)); L.Push(cFile::Copy(SrcFile, DstFile)); return 1; } static int tolua_cFile_CreateFolder(lua_State * tolua_S) { // API signature: // cFile:CreateFolder(string) -> bool // Check params: cLuaState L(tolua_S); if ( !L.CheckParamUserTable(1, "cFile") || !L.CheckParamString(2) || !L.CheckParamEnd(3) ) { return 0; } // Execute: AString FolderPath; VERIFY(L.GetStackValues(2, FolderPath)); L.Push(cFile::CreateFolder(FolderPath)); return 1; } static int tolua_cFile_CreateFolderRecursive(lua_State * tolua_S) { // API signature: // cFile:CreateFolderRecursive(string) -> bool // Check params: cLuaState L(tolua_S); if ( !L.CheckParamUserTable(1, "cFile") || !L.CheckParamString(2) || !L.CheckParamEnd(3) ) { return 0; } // Execute: AString FolderPath; VERIFY(L.GetStackValues(2, FolderPath)); L.Push(cFile::CreateFolderRecursive(FolderPath)); return 1; } static int tolua_cFile_Delete(lua_State * tolua_S) { // API signature: // cFile:Delete(string) -> bool // Check params: cLuaState L(tolua_S); if ( !L.CheckParamUserTable(1, "cFile") || !L.CheckParamString(2) || !L.CheckParamEnd(3) ) { return 0; } // Execute: AString Path; VERIFY(L.GetStackValues(2, Path)); L.Push(cFile::Delete(Path)); return 1; } static int tolua_cFile_DeleteFile(lua_State * tolua_S) { // API signature: // cFile:DeleteFile(string) -> bool // Check params: cLuaState L(tolua_S); if ( !L.CheckParamUserTable(1, "cFile") || !L.CheckParamString(2) || !L.CheckParamEnd(3) ) { return 0; } // Execute: AString Path; VERIFY(L.GetStackValues(2, Path)); L.Push(cFile::DeleteFile(Path)); return 1; } static int tolua_cFile_DeleteFolder(lua_State * tolua_S) { // API signature: // cFile:DeleteFolder(string) -> bool // Check params: cLuaState L(tolua_S); if ( !L.CheckParamUserTable(1, "cFile") || !L.CheckParamString(2) || !L.CheckParamEnd(3) ) { return 0; } // Execute: AString Path; VERIFY(L.GetStackValues(2, Path)); L.Push(cFile::DeleteFolder(Path)); return 1; } static int tolua_cFile_DeleteFolderContents(lua_State * tolua_S) { // API signature: // cFile:DeleteFolderContents(string) -> bool // Check params: cLuaState L(tolua_S); if ( !L.CheckParamUserTable(1, "cFile") || !L.CheckParamString(2) || !L.CheckParamEnd(3) ) { return 0; } // Execute: AString Path; VERIFY(L.GetStackValues(2, Path)); L.Push(cFile::DeleteFolderContents(Path)); return 1; } static int tolua_cFile_Exists(lua_State * tolua_S) { // API signature: // cFile:Exists(string) -> bool // Obsolete, use IsFile() or IsFolder() instead cLuaState L(tolua_S); LOGWARNING("cFile:Exists() is obsolete, use cFile:IsFolder() or cFile:IsFile() instead!"); L.LogStackTrace(); // Check params: if ( !L.CheckParamUserTable(1, "cFile") || !L.CheckParamString(2) || !L.CheckParamEnd(3) ) { return 0; } // Execute: AString Path; VERIFY(L.GetStackValues(2, Path)); L.Push(cFile::Exists(Path)); return 1; } static int tolua_cFile_GetFolderContents(lua_State * tolua_S) { // API signature: // cFile:GetFolderContents(string) -> {string, string, ...} // Check params: cLuaState LuaState(tolua_S); if ( !LuaState.CheckParamUserTable(1, "cFile") || !LuaState.CheckParamString (2) || !LuaState.CheckParamEnd (3) ) { return 0; } // Get params: AString Folder; VERIFY(LuaState.GetStackValues(2, Folder)); // Execute and push result: LuaState.Push(cFile::GetFolderContents(Folder)); return 1; } static int tolua_cFile_GetLastModificationTime(lua_State * tolua_S) { // API signature: // cFile:GetLastModificationTime(string) -> number // Check params: cLuaState L(tolua_S); if ( !L.CheckParamUserTable(1, "cFile") || !L.CheckParamString(2) || !L.CheckParamEnd(3) ) { return 0; } // Execute: AString Path; VERIFY(L.GetStackValues(2, Path)); L.Push(cFile::GetLastModificationTime(Path)); return 1; } static int tolua_cFile_GetSize(lua_State * tolua_S) { // API signature: // cFile:GetSize(string) -> number // Check params: cLuaState L(tolua_S); if ( !L.CheckParamUserTable(1, "cFile") || !L.CheckParamString(2) || !L.CheckParamEnd(3) ) { return 0; } // Execute: AString Path; VERIFY(L.GetStackValues(2, Path)); L.Push(cFile::GetSize(Path)); return 1; } static int tolua_cFile_IsFile(lua_State * tolua_S) { // API signature: // cFile:IsFile(string) -> bool // Check params: cLuaState L(tolua_S); if ( !L.CheckParamUserTable(1, "cFile") || !L.CheckParamString(2) || !L.CheckParamEnd(3) ) { return 0; } // Execute: AString Path; VERIFY(L.GetStackValues(2, Path)); L.Push(cFile::IsFile(Path)); return 1; } static int tolua_cFile_IsFolder(lua_State * tolua_S) { // API signature: // cFile:IsFolder(string) -> bool // Check params: cLuaState L(tolua_S); if ( !L.CheckParamUserTable(1, "cFile") || !L.CheckParamString(2) || !L.CheckParamEnd(3) ) { return 0; } // Execute: AString Path; VERIFY(L.GetStackValues(2, Path)); L.Push(cFile::IsFolder(Path)); return 1; } static int tolua_cFile_ReadWholeFile(lua_State * tolua_S) { // API signature: // cFile:ReadWholeFile(string) -> string // Check params: cLuaState LuaState(tolua_S); if ( !LuaState.CheckParamUserTable(1, "cFile") || !LuaState.CheckParamString (2) || !LuaState.CheckParamEnd (3) ) { return 0; } // Get params: AString FileName; VERIFY(LuaState.GetStackValues(2, FileName)); // Execute and push result: LuaState.Push(cFile::ReadWholeFile(FileName)); return 1; } static int tolua_cFile_Rename(lua_State * tolua_S) { // API signature: // cFile:Rename(string, string) -> bool // Check params: cLuaState L(tolua_S); if ( !L.CheckParamUserTable(1, "cFile") || !L.CheckParamString(2, 3) || !L.CheckParamEnd(4) ) { return 0; } // Execute: AString SrcPath, DstPath; VERIFY(L.GetStackValues(2, SrcPath, DstPath)); L.Push(cFile::Rename(SrcPath, DstPath)); return 1; } static int tolua_cPluginManager_GetAllPlugins(lua_State * tolua_S) { // API function no longer available: LOGWARNING("cPluginManager:GetAllPlugins() is no longer available, use cPluginManager:ForEachPlugin() instead"); cLuaState::LogStackTrace(tolua_S); // Return an empty table: lua_newtable(tolua_S); return 1; } static int tolua_cPluginManager_GetCurrentPlugin(lua_State * S) { cPluginLua * Plugin = cManualBindings::GetLuaPlugin(S); if (Plugin == nullptr) { // An error message has already been printed in GetLuaPlugin() return 0; } tolua_pushusertype(S, Plugin, "cPluginLua"); return 1; } static int tolua_cPluginManager_GetPlugin(lua_State * tolua_S) { // API function no longer available: LOGWARNING("cPluginManager:GetPlugin() is no longer available. Use cPluginManager:DoWithPlugin() or cPluginManager:CallPlugin() instead."); cLuaState::LogStackTrace(tolua_S); return 0; } static int tolua_cPluginManager_LogStackTrace(lua_State * S) { cLuaState::LogStackTrace(S); return 0; } static int tolua_cPluginManager_AddHook_FnRef(cPluginManager * a_PluginManager, cLuaState & S, int a_ParamIdx) { // Helper function for cPluginmanager:AddHook() binding // Takes care of the new case (#121): args are HOOK_TYPE and CallbackFunction // The arg types have already been checked // Retrieve the cPlugin from the LuaState: cPluginLua * Plugin = cManualBindings::GetLuaPlugin(S); if (Plugin == nullptr) { // An error message has been already printed in GetLuaPlugin() return 0; } // Retrieve and check the hook type int HookType; if (!S.GetStackValue(a_ParamIdx, HookType)) { LOGWARNING("cPluginManager.AddHook(): Cannot read the hook type."); S.LogStackTrace(); return 0; } if (!a_PluginManager->IsValidHookType(HookType)) { LOGWARNING("cPluginManager.AddHook(): Invalid HOOK_TYPE parameter: %d", HookType); S.LogStackTrace(); return 0; } // Add the hook to the plugin cLuaState::cCallbackPtr callback; if (!S.GetStackValue(a_ParamIdx + 1, callback)) { LOGWARNING("cPluginManager.AddHook(): Cannot read the callback parameter"); S.LogStackTrace(); return 0; } if (!Plugin->AddHookCallback(HookType, std::move(callback))) { LOGWARNING("cPluginManager.AddHook(): Cannot add hook %d, unknown error.", HookType); S.LogStackTrace(); return 0; } a_PluginManager->AddHook(Plugin, HookType); // Success return 0; } static int tolua_cPluginManager_AddHook_DefFn(cPluginManager * a_PluginManager, cLuaState & S, int a_ParamIdx) { // Helper function for cPluginmanager:AddHook() binding // Takes care of the old case (#121): args are cPluginLua and HOOK_TYPE // The arg types have already been checked // Retrieve and check the cPlugin parameter cPluginLua * Plugin = static_cast(tolua_tousertype(S, a_ParamIdx, nullptr)); if (Plugin == nullptr) { LOGWARNING("cPluginManager.AddHook(): Invalid Plugin parameter, expected a valid cPlugin object. Hook not added"); S.LogStackTrace(); return 0; } if (Plugin != cManualBindings::GetLuaPlugin(S)) { // The plugin parameter passed to us is not our stored plugin. Disallow this! LOGWARNING("cPluginManager.AddHook(): Invalid Plugin parameter, cannot add hook to foreign plugins. Hook not added."); S.LogStackTrace(); return 0; } // Retrieve and check the hook type int HookType = static_cast(tolua_tonumber(S, a_ParamIdx + 1, -1)); if (!a_PluginManager->IsValidHookType(HookType)) { LOGWARNING("cPluginManager.AddHook(): Invalid HOOK_TYPE parameter: %d", HookType); S.LogStackTrace(); return 0; } // Get the standard name for the callback function: const char * FnName = cPluginLua::GetHookFnName(HookType); if (FnName == nullptr) { LOGWARNING("cPluginManager.AddHook(): Unknown hook type (%d). Hook not added.", HookType); S.LogStackTrace(); return 0; } // Retrieve the function to call and add it to the plugin: cLuaState::cCallbackPtr callback; lua_getglobal(S, FnName); bool res = S.GetStackValue(-1, callback); lua_pop(S, 1); if (!res || !callback->IsValid()) { LOGWARNING("cPluginManager.AddHook(): Function %s not found. Hook not added.", FnName); S.LogStackTrace(); return 0; } a_PluginManager->AddHook(Plugin, HookType); // Success return 0; } static int tolua_cPluginManager_AddHook(lua_State * tolua_S) { /* Function signatures: cPluginManager:AddHook(HOOK_TYPE, CallbackFunction) -- (1) recommended cPluginManager.AddHook(HOOK_TYPE, CallbackFunction) -- (2) accepted silently (#401 deprecates this) cPluginManager:Get():AddHook(HOOK_TYPE, CallbackFunction) -- (3) accepted silently cPluginManager:Get():AddHook(Plugin, HOOK_TYPE) -- (4) old style (#121), accepted but complained about in the console cPluginManager.AddHook(Plugin, HOOK_TYPE) -- (5) old style (#121) mangled, accepted but complained about in the console */ cLuaState S(tolua_S); cPluginManager * PlgMgr = cPluginManager::Get(); // If the first param is a cPluginManager instance, use it instead of the global one: int ParamIdx = 1; tolua_Error err; if (tolua_isusertype(S, 1, "cPluginManager", 0, &err)) { // Style 2 or 3, retrieve the PlgMgr instance PlgMgr = static_cast(tolua_tousertype(S, 1, nullptr)); if (PlgMgr == nullptr) { LOGWARNING("Malformed plugin, use cPluginManager.AddHook(HOOK_TYPE, CallbackFunction). Fixing the call for you."); S.LogStackTrace(); PlgMgr = cPluginManager::Get(); } ParamIdx += 1; } else if (tolua_isusertable(S, 1, "cPluginManager", 0, &err)) { // Style 1, use the global PlgMgr, but increment ParamIdx ParamIdx++; } if (lua_isnumber(S, ParamIdx) && lua_isfunction(S, ParamIdx + 1)) { // The next params are a number and a function, assume style 1 or 2 return tolua_cPluginManager_AddHook_FnRef(PlgMgr, S, ParamIdx); } else if (tolua_isusertype(S, ParamIdx, "cPlugin", 0, &err) && lua_isnumber(S, ParamIdx + 1)) { // The next params are a cPlugin and a number, assume style 3 or 4 LOGINFO("cPluginManager.AddHook(): Deprecated format used, use cPluginManager.AddHook(HOOK_TYPE, CallbackFunction) instead. Fixing the call for you."); S.LogStackTrace(); return tolua_cPluginManager_AddHook_DefFn(PlgMgr, S, ParamIdx); } auto ParamDesc = fmt::format(FMT_STRING("{}, {}, {}"), S.GetTypeText(1), S.GetTypeText(2), S.GetTypeText(3)); LOGWARNING("cPluginManager:AddHook(): bad parameters. Expected HOOK_TYPE and CallbackFunction, got %s. Hook not added.", ParamDesc); S.LogStackTrace(); return 0; } static int tolua_cPluginManager_ForEachCommand(lua_State * tolua_S) { /* Function signature: cPluginManager:Get():ForEachCommand(a_CallbackFn) -> bool */ // Check params: cLuaState L(tolua_S); if ( !L.CheckParamUserType(1, "cPluginManager") || !L.CheckParamFunction(2) || !L.CheckParamEnd(3) ) { return 0; } // Get the params: cLuaState::cRef FnRef; L.GetStackValues(2, FnRef); if (!FnRef.IsValid()) { LOGWARN("Error in function call 'ForEachCommand': Could not get function reference of parameter #1"); return 0; } // Callback for enumerating all commands: class cLuaCallback : public cPluginManager::cCommandEnumCallback { public: cLuaCallback(cLuaState & a_LuaState, cLuaState::cRef & a_FnRef): m_LuaState(a_LuaState), m_FnRef(a_FnRef) { } private: virtual bool Command(const AString & a_Command, const cPlugin * a_Plugin, const AString & a_Permission, const AString & a_HelpString) override { UNUSED(a_Plugin); bool ret = false; m_LuaState.Call(m_FnRef, a_Command, a_Permission, a_HelpString, cLuaState::Return, ret); return ret; } cLuaState & m_LuaState; cLuaState::cRef & m_FnRef; } Callback(L, FnRef); // Execute and push the returned value: L.Push(cPluginManager::Get()->ForEachCommand(Callback)); return 1; } static int tolua_cPluginManager_ForEachConsoleCommand(lua_State * tolua_S) { /* Function signature: cPluginManager:Get():ForEachConsoleCommand(a_CallbackFn) -> bool */ // Check params: cLuaState L(tolua_S); if ( !L.CheckParamUserType(1, "cPluginManager") || !L.CheckParamFunction(2) || !L.CheckParamEnd(3) ) { return 0; } // Get the params: cLuaState::cRef FnRef; L.GetStackValues(2, FnRef); if (!FnRef.IsValid()) { LOGWARN("Error in function call 'ForEachConsoleCommand': Could not get function reference of parameter #1"); return 0; } // Callback for enumerating all commands: class cLuaCallback : public cPluginManager::cCommandEnumCallback { public: cLuaCallback(cLuaState & a_LuaState, cLuaState::cRef & a_FnRef): m_LuaState(a_LuaState), m_FnRef(a_FnRef) { } private: virtual bool Command(const AString & a_Command, const cPlugin * a_Plugin, const AString & a_Permission, const AString & a_HelpString) override { UNUSED(a_Plugin); UNUSED(a_Permission); bool ret = false; m_LuaState.Call(m_FnRef, a_Command, a_HelpString, cLuaState::Return, ret); return ret; } cLuaState & m_LuaState; cLuaState::cRef & m_FnRef; } Callback(L, FnRef); // Execute and push the returned value: L.Push(cPluginManager::Get()->ForEachConsoleCommand(Callback)); return 1; } static int tolua_cPluginManager_BindCommand(lua_State * a_LuaState) { /* Function signatures: cPluginManager:Get():BindCommand(Command, Permission, Function, HelpString) -- regular cPluginManager:BindCommand(Command, Permission, Function, HelpString) -- static cPluginManager.BindCommand(Command, Permission, Function, HelpString) -- without the "self" param */ cLuaState L(a_LuaState); cPluginLua * Plugin = cManualBindings::GetLuaPlugin(L); if (Plugin == nullptr) { return 0; } // Read the arguments to this API call: tolua_Error tolua_err; int idx = 1; if ( tolua_isusertype (L, 1, "cPluginManager", 0, &tolua_err) || tolua_isusertable(L, 1, "cPluginManager", 0, &tolua_err) ) { idx++; } if ( !tolua_iscppstring(L, idx, 0, &tolua_err) || !tolua_iscppstring(L, idx + 1, 0, &tolua_err) || !tolua_iscppstring(L, idx + 3, 0, &tolua_err) || !tolua_isnoobj (L, idx + 4, &tolua_err) ) { tolua_error(L, "#ferror in function 'BindCommand'.", &tolua_err); return 0; } if (!lua_isfunction(L, idx + 2)) { luaL_error(L, "\"BindCommand\" function expects a function as its 3rd parameter. Command-binding aborted."); return 0; } cPluginManager * self = cPluginManager::Get(); AString Command, Permission, HelpString; cLuaState::cCallbackPtr Handler; L.GetStackValues(idx, Command, Permission, Handler, HelpString); if (!Handler->IsValid()) { LOGERROR("\"BindCommand\": Cannot create a function reference. Command \"%s\" not bound.", Command.c_str()); return 0; } auto CommandHandler = std::make_shared(std::move(Handler)); if (!self->BindCommand(Command, Plugin, CommandHandler, Permission, HelpString)) { // Refused. Possibly already bound. Error message has been given, display the callstack: L.LogStackTrace(); return 0; } L.Push(true); return 1; } static int tolua_cPluginManager_BindConsoleCommand(lua_State * a_LuaState) { /* Function signatures: cPluginManager:Get():BindConsoleCommand(Command, Function, HelpString) -- regular cPluginManager:BindConsoleCommand(Command, Function, HelpString) -- static cPluginManager.BindConsoleCommand(Command, Function, HelpString) -- without the "self" param */ // Get the plugin identification out of LuaState: cLuaState L(a_LuaState); cPluginLua * Plugin = cManualBindings::GetLuaPlugin(L); if (Plugin == nullptr) { return 0; } // Read the arguments to this API call: tolua_Error tolua_err; int idx = 1; if ( tolua_isusertype(L, 1, "cPluginManager", 0, &tolua_err) || tolua_isusertable(L, 1, "cPluginManager", 0, &tolua_err) ) { idx++; } if ( !tolua_iscppstring(L, idx, 0, &tolua_err) || // Command !tolua_iscppstring(L, idx + 2, 0, &tolua_err) || // HelpString !tolua_isnoobj (L, idx + 3, &tolua_err) ) { tolua_error(L, "#ferror in function 'BindConsoleCommand'.", &tolua_err); return 0; } if (!lua_isfunction(L, idx + 1)) { luaL_error(L, "\"BindConsoleCommand\" function expects a function as its 2nd parameter. Command-binding aborted."); return 0; } cPluginManager * self = cPluginManager::Get(); AString Command, HelpString; cLuaState::cCallbackPtr Handler; L.GetStackValues(idx, Command, Handler, HelpString); if (!Handler->IsValid()) { LOGERROR("\"BindConsoleCommand\": Cannot create a function reference. Console command \"%s\" not bound.", Command.c_str()); return 0; } auto CommandHandler = std::make_shared(std::move(Handler)); if (!self->BindConsoleCommand(Command, Plugin, CommandHandler, HelpString)) { // Refused. Possibly already bound. Error message has been given, display the callstack: L.LogStackTrace(); return 0; } L.Push(true); return 1; } static int tolua_cPluginManager_CallPlugin(lua_State * tolua_S) { /* Function signature: cPluginManager:CallPlugin("PluginName", "FunctionName", args...) */ // Check the parameters: cLuaState L(tolua_S); if ( !L.CheckParamUserTable(1, "cPluginManager") || !L.CheckParamString(2, 3)) { return 0; } // Retrieve the plugin name and function name AString PluginName, FunctionName; L.ToString(2, PluginName); L.ToString(3, FunctionName); if (PluginName.empty() || FunctionName.empty()) { LOGWARNING("cPluginManager:CallPlugin(): Invalid plugin name or function name"); L.LogStackTrace(); return 0; } // If requesting calling the current plugin, refuse: cPluginLua * ThisPlugin = cManualBindings::GetLuaPlugin(L); if (ThisPlugin == nullptr) { return 0; } if (ThisPlugin->GetName() == PluginName) { LOGWARNING("cPluginManager::CallPlugin(): Calling self is not implemented (why would it?)"); L.LogStackTrace(); return 0; } // Call the destination plugin using a plugin callback: int NumReturns = 0; auto PluginCallback = [&](cPlugin & a_Plugin) { if (!a_Plugin.IsLoaded()) { return false; } NumReturns = static_cast(a_Plugin).CallFunctionFromForeignState( FunctionName, L, 4, lua_gettop(L) ); return true; }; if (!cPluginManager::Get()->DoWithPlugin(PluginName, PluginCallback)) { return 0; } if (NumReturns < 0) { // The call has failed, there are zero return values. Do NOT return negative number (Lua considers that a "yield") return 0; } return NumReturns; } static int tolua_cPluginManager_ExecuteConsoleCommand(lua_State * tolua_S) { /* Function signature: cPluginManager:ExecuteConsoleCommand(EntireCommandStr) -> OutputString */ // Check params: cLuaState L(tolua_S); if ( !L.CheckParamUserTable(1, "cPluginManager") || !L.CheckParamString(2) || !L.CheckParamEnd(3) ) { return 0; } // Get the params: AString Command; L.GetStackValues(2, Command); auto Split = StringSplit(Command, " "); // Store the command output in a string: cStringAccumCommandOutputCallback CommandOutput; L.Push(cPluginManager::Get()->ExecuteConsoleCommand(Split, CommandOutput, Command)); L.Push(CommandOutput.GetAccum()); return 2; } static int tolua_cPluginManager_FindPlugins(lua_State * tolua_S) { // API function no longer exists: LOGWARNING("cPluginManager:FindPlugins() is obsolete, use cPluginManager:RefreshPluginList() instead!"); cLuaState::LogStackTrace(tolua_S); // Still, do the actual work performed by the API function when it existed: cPluginManager::Get()->RefreshPluginList(); return 0; } static int tolua_cPlayer_GetPermissions(lua_State * tolua_S) { // Function signature: cPlayer:GetPermissions() -> {permissions-array} // Check the params: cLuaState L(tolua_S); if ( !L.CheckParamUserType(1, "cPlayer") || !L.CheckParamEnd (2) ) { return 0; } // Get the params: cPlayer * self = static_cast(tolua_tousertype(tolua_S, 1, nullptr)); if (self == nullptr) { LOGWARNING("%s: invalid self (%p)", __FUNCTION__, static_cast(self)); return 0; } // Push the permissions: L.Push(self->GetPermissions()); return 1; } static int tolua_cPlayer_GetRestrictions(lua_State * tolua_S) { // Function signature: cPlayer:GetRestrictions() -> {restrictions-array} // Check the params: cLuaState L(tolua_S); if ( !L.CheckParamUserType(1, "cPlayer") || !L.CheckParamEnd (2) ) { return 0; } // Get the params: cPlayer * self = static_cast(tolua_tousertype(tolua_S, 1, nullptr)); if (self == nullptr) { LOGWARNING("%s: invalid self (%p)", __FUNCTION__, static_cast(self)); return 0; } // Push the permissions: L.Push(self->GetRestrictions()); return 1; } static int tolua_cPlayer_GetUUID(lua_State * tolua_S) { // Check the params: cLuaState L(tolua_S); if (!L.CheckParamSelf("cPlayer")) { return 0; } // Get the params: cPlayer * Self = nullptr; L.GetStackValue(1, Self); // Return the UUID as a string L.Push(Self->GetUUID().ToShortString()); return 1; } static int tolua_cPlayer_PlaceBlock(lua_State * tolua_S) { // Check the params: cLuaState L(tolua_S); if ( !L.CheckParamSelf("cPlayer") || !L.CheckParamUserType(2, "Vector3") || !L.CheckParamNumber(3, 4) || !L.CheckParamEnd(5) ) { return 0; } // Get the params: cPlayer * Self; Vector3i Position; BLOCKTYPE BlockType; NIBBLETYPE BlockMeta; L.GetStackValues(1, Self, Position, BlockType, BlockMeta); if (!cChunkDef::IsValidHeight(Position)) { return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'position'"); } // Return the result of placement: L.Push(Self->PlaceBlock(Position, BlockType, BlockMeta)); return 1; } static int tolua_cPlayer_PermissionMatches(lua_State * tolua_S) { // Function signature: cPlayer:PermissionMatches(PermissionStr, TemplateStr) -> bool // Check the params: cLuaState L(tolua_S); if ( !L.CheckParamUserTable(1, "cPlayer") || !L.CheckParamString (2, 3) || !L.CheckParamEnd (4) ) { return 0; } // Get the params: AString Permission, Template; L.GetStackValues(2, Permission, Template); // Push the result of the match: L.Push(cPlayer::PermissionMatches(StringSplit(Permission, "."), StringSplit(Template, "."))); return 1; } template < class OBJTYPE, void (OBJTYPE::*SetCallback)(cLuaState::cCallbackPtr && a_CallbackFn) > static int tolua_SetObjectCallback(lua_State * tolua_S) { // Function signature: OBJTYPE:SetWhateverCallback(CallbackFunction) // Get the parameters - self and the function reference: cLuaState L(tolua_S); OBJTYPE * self; cLuaState::cCallbackPtr callback; if (!L.GetStackValues(1, self, callback)) { LOGWARNING("%s: Cannot get parameters", __FUNCTION__); L.LogStackTrace(); return 0; } // Set the callback (self->*SetCallback)(std::move(callback)); return 0; } // Callback class used for the WebTab: class cWebTabCallback: public cWebAdmin::cWebTabCallback { public: /** The Lua callback to call to generate the page contents. */ cLuaState::cCallback m_Callback; virtual bool Call( const HTTPRequest & a_Request, const AString & a_UrlPath, AString & a_Content, AString & a_ContentType ) override { AString content, contentType; return m_Callback.Call(const_cast(&a_Request), a_UrlPath, cLuaState::Return, a_Content, a_ContentType); } }; static int tolua_cPluginLua_AddWebTab(lua_State * tolua_S) { // OBSOLETE, use cWebAdmin:AddWebTab() instead! // Function signature: // cPluginLua:AddWebTab(Title, CallbackFn, [UrlPath]) // TODO: Warn about obsolete API usage // Only implement after merging the new API change and letting some time for changes in the plugins // Check params: cLuaState LuaState(tolua_S); cPluginLua * self = cManualBindings::GetLuaPlugin(tolua_S); if (self == nullptr) { return 0; } if ( !LuaState.CheckParamString(2) || !LuaState.CheckParamFunction(3) || // Optional string as param 4 !LuaState.CheckParamEnd(5) ) { return 0; } // Read the params: AString title, urlPath; auto callback = std::make_shared(); if (!LuaState.GetStackValues(2, title, callback->m_Callback)) { LOGWARNING("cPlugin:AddWebTab(): Cannot read required parameters"); return 0; } if (!LuaState.GetStackValue(4, urlPath)) { urlPath = cWebAdmin::GetURLEncodedString(title); } cRoot::Get()->GetWebAdmin()->AddWebTab(title, urlPath, self->GetName(), callback); return 0; } static int tolua_cPlugin_GetDirectory(lua_State * tolua_S) { cLuaState L(tolua_S); // Log the obsoletion warning: LOGWARNING("cPlugin:GetDirectory() is obsolete, use cPlugin:GetFolderName() instead."); L.LogStackTrace(); // Retrieve the params: cPlugin * Plugin = static_cast(tolua_tousertype(tolua_S, 1, nullptr)); // Get the folder name: L.Push(Plugin->GetFolderName()); return 1; } static int tolua_cPlugin_GetLocalDirectory(lua_State * tolua_S) { cLuaState L(tolua_S); // Log the obsoletion warning: LOGWARNING("cPlugin:GetLocalDirectory() is obsolete, use cPlugin:GetLocalFolder() instead."); L.LogStackTrace(); // Retrieve the params: cPlugin * Plugin = static_cast(tolua_tousertype(tolua_S, 1, nullptr)); // Get the folder: L.Push(Plugin->GetLocalFolder()); return 1; } static int tolua_md5(lua_State * tolua_S) { // Calculate the raw md5 checksum byte array: unsigned char Output[16]; size_t len = 0; const unsigned char * SourceString = reinterpret_cast(lua_tolstring(tolua_S, 1, &len)); if (SourceString == nullptr) { return 0; } mbedtls_md5(SourceString, len, Output); lua_pushlstring(tolua_S, reinterpret_cast(Output), ARRAYCOUNT(Output)); return 1; } /** Does the same as tolua_md5, but reports that the usage is obsolete and the plugin should use cCrypto.md5(). */ static int tolua_md5_obsolete(lua_State * tolua_S) { LOGWARNING("Using md5() is obsolete, please change your plugin to use cCryptoHash.md5()"); cLuaState::LogStackTrace(tolua_S); return tolua_md5(tolua_S); } static int tolua_md5HexString(lua_State * tolua_S) { // Calculate the raw md5 checksum byte array: unsigned char md5Output[16]; size_t len = 0; const unsigned char * SourceString = reinterpret_cast(lua_tolstring(tolua_S, 1, &len)); if (SourceString == nullptr) { return 0; } mbedtls_md5(SourceString, len, md5Output); // Convert the md5 checksum to hex string: std::stringstream Output; Output << std::hex << std::setfill('0'); for (size_t i = 0; i < ARRAYCOUNT(md5Output); i++) { Output << std::setw(2) << static_cast(md5Output[i]); // Need to cast to a number, otherwise a char is output } lua_pushlstring(tolua_S, Output.str().c_str(), Output.str().size()); return 1; } static int tolua_sha1(lua_State * tolua_S) { // Calculate the raw SHA1 checksum byte array from the input string: unsigned char Output[20]; size_t len = 0; const unsigned char * SourceString = reinterpret_cast(lua_tolstring(tolua_S, 1, &len)); if (SourceString == nullptr) { return 0; } mbedtls_sha1(SourceString, len, Output); lua_pushlstring(tolua_S, reinterpret_cast(Output), ARRAYCOUNT(Output)); return 1; } static int tolua_sha1HexString(lua_State * tolua_S) { // Calculate the raw SHA1 checksum byte array from the input string: unsigned char sha1Output[20]; size_t len = 0; const unsigned char * SourceString = reinterpret_cast(lua_tolstring(tolua_S, 1, &len)); if (SourceString == nullptr) { return 0; } mbedtls_sha1(SourceString, len, sha1Output); // Convert the sha1 checksum to hex string: std::stringstream Output; Output << std::hex << std::setfill('0'); for (size_t i = 0; i < ARRAYCOUNT(sha1Output); i++) { Output << std::setw(2) << static_cast(sha1Output[i]); // Need to cast to a number, otherwise a char is output } lua_pushlstring(tolua_S, Output.str().c_str(), Output.str().size()); return 1; } static int tolua_get_HTTPRequest_Params(lua_State * a_LuaState) { cLuaState L(a_LuaState); HTTPRequest * self; if (!L.GetStackValues(1, self)) { tolua_Error err; tolua_error(a_LuaState, "Invalid self parameter, expected a HTTPRequest instance", &err); return 0; } L.Push(self->Params); return 1; } static int tolua_get_HTTPRequest_PostParams(lua_State * a_LuaState) { cLuaState L(a_LuaState); HTTPRequest * self; if (!L.GetStackValues(1, self)) { tolua_Error err; tolua_error(a_LuaState, "Invalid self parameter, expected a HTTPRequest instance", &err); return 0; } L.Push(self->PostParams); return 1; } static int tolua_get_HTTPRequest_FormData(lua_State* a_LuaState) { cLuaState L(a_LuaState); HTTPRequest * self; if (!L.GetStackValues(1, self)) { tolua_Error err; tolua_error(a_LuaState, "Invalid self parameter, expected a HTTPRequest instance", &err); return 0; } auto & FormData = self->FormData; lua_newtable(a_LuaState); int top = lua_gettop(a_LuaState); for (auto & Data : FormData) { lua_pushstring(a_LuaState, Data.first.c_str()); tolua_pushusertype(a_LuaState, &Data.second, "HTTPFormData"); // lua_pushlstring(a_LuaState, Data.second.Value.c_str(), Data.second.Value.size()); // Might contain binary data lua_settable(a_LuaState, top); } return 1; } static int tolua_cUrlParser_GetDefaultPort(lua_State * a_LuaState) { // API function signature: // cUrlParser:GetDefaultPort("scheme") -> number // Check params: cLuaState L(a_LuaState); if ( !L.CheckParamUserTable(1, "cUrlParser") || !L.CheckParamString(2) || !L.CheckParamEnd(3) ) { return 0; } // Read params from Lua: AString scheme; L.GetStackValue(2, scheme); // Execute and push result: L.Push(cUrlParser::GetDefaultPort(scheme)); return 1; } static int tolua_cUrlParser_IsKnownScheme(lua_State * a_LuaState) { // API function signature: // cUrlParser:IsKnownScheme("scheme") -> bool // Check params: cLuaState L(a_LuaState); if ( !L.CheckParamUserTable(1, "cUrlParser") || !L.CheckParamString(2) || !L.CheckParamEnd(3) ) { return 0; } // Read params from Lua: AString scheme; L.GetStackValue(2, scheme); // Execute and push result: L.Push(cUrlParser::IsKnownScheme(scheme)); return 1; } static int tolua_cUrlParser_Parse(lua_State * a_LuaState) { // API function signature: // cUrlParser:Parse("url") -> "scheme", "user", "password", "host", portnum, "path", "query", "fragment" // On error, returns nil and error message // Check params: cLuaState L(a_LuaState); if ( !L.CheckParamUserTable(1, "cUrlParser") || !L.CheckParamString(2) || !L.CheckParamEnd(3) ) { return 0; } // Read params from Lua: AString url; L.GetStackValue(2, url); // Execute and push result: AString scheme, username, password, host, path, query, fragment; UInt16 port; auto res = cUrlParser::Parse(url, scheme, username, password, host, port, path, query, fragment); if (!res.first) { // Error, return nil and error msg: L.Push(cLuaState::Nil, res.second); return 2; } L.Push(scheme, username, password, host, port, path, query, fragment); return 8; } static int tolua_cUrlParser_ParseAuthorityPart(lua_State * a_LuaState) { // API function signature: // cUrlParser:ParseAuthorityPart("authority") -> "user", "password", "host", portnum // On error, returns nil and error message // Parts not specified in the "authority" are left empty / zero // Check params: cLuaState L(a_LuaState); if ( !L.CheckParamUserTable(1, "cUrlParser") || !L.CheckParamString(2) || !L.CheckParamEnd(3) ) { return 0; } // Read params from Lua: AString authPart; L.GetStackValue(2, authPart); // Execute and push result: AString username, password, host; UInt16 port; auto res = cUrlParser::ParseAuthorityPart(authPart, username, password, host, port); if (!res.first) { // Error, return nil and error msg: L.Push(cLuaState::Nil, res.second); return 2; } L.Push(username, password, host, port); return 4; } static int tolua_cUrlParser_UrlDecode(lua_State * tolua_S) { // Check the param types: cLuaState S(tolua_S); if ( // Don't care about the first param !S.CheckParamString(2) || !S.CheckParamEnd(3) ) { return 0; } // Get the parameters: AString Input; S.GetStackValue(2, Input); // Convert and return: auto res = URLDecode(Input); if (res.first) { S.Push(res.second); } else { S.Push(cLuaState::Nil); } return 1; } static int tolua_cUrlParser_UrlEncode(lua_State * tolua_S) { // Check the param types: cLuaState S(tolua_S); if ( // Don't care about the first param !S.CheckParamString(2) || !S.CheckParamEnd(3) ) { return 0; } // Get the parameters: AString Input; S.GetStackValue(2, Input); // Convert and return: S.Push(URLEncode(Input)); return 1; } static int tolua_cWebAdmin_AddWebTab(lua_State * tolua_S) { // Function signatures: // cWebAdmin:AddWebTab(Title, UrlPath, CallbackFn) // Check params: cLuaState LuaState(tolua_S); cPluginLua * self = cManualBindings::GetLuaPlugin(tolua_S); if (self == nullptr) { return 0; } if ( // Don't care whether the first param is a cWebAdmin instance or class !LuaState.CheckParamString(2, 3) || !LuaState.CheckParamFunction(4) || !LuaState.CheckParamEnd(5) ) { return 0; } // Read the params: AString title, urlPath; auto callback = std::make_shared(); if (!LuaState.GetStackValues(2, title, urlPath, callback->m_Callback)) { LOGWARNING("cWebAdmin:AddWebTab(): Cannot read required parameters"); return 0; } cRoot::Get()->GetWebAdmin()->AddWebTab(title, urlPath, self->GetName(), callback); return 0; } static int tolua_cWebAdmin_GetAllWebTabs(lua_State * tolua_S) { // Function signature: // cWebAdmin:GetAllWebTabs() -> { {"PluginName", "UrlPath", "Title"}, {"PluginName", "UrlPath", "Title"}, ...} // Don't care about params at all auto webTabs = cRoot::Get()->GetWebAdmin()->GetAllWebTabs(); lua_createtable(tolua_S, static_cast(webTabs.size()), 0); int newTable = lua_gettop(tolua_S); int index = 1; cLuaState L(tolua_S); for (const auto & wt: webTabs) { lua_createtable(tolua_S, 0, 3); L.Push(wt->m_PluginName); lua_setfield(tolua_S, -2, "PluginName"); L.Push(wt->m_UrlPath); lua_setfield(tolua_S, -2, "UrlPath"); L.Push(wt->m_Title); lua_setfield(tolua_S, -2, "Title"); lua_rawseti(tolua_S, newTable, index); ++index; } return 1; } /** Binding for cWebAdmin::GetPage. */ static int tolua_cWebAdmin_GetPage(lua_State * tolua_S) { /* Function signature: cWebAdmin:GetPage(a_HTTPRequest) -> { Content = "", // Content generated by the plugin ContentType = "", // Content type generated by the plugin (default: "text/html") UrlPath = "", // URL path of the tab TabTitle = "", // Tab's title, as register via cWebAdmin:AddWebTab() PluginName = "", // Plugin's API name PluginFolder = "", // Plugin's folder name (display name) } */ // Check the param types: cLuaState S(tolua_S); if ( // Don't care about first param, whether it's cWebAdmin instance or class !S.CheckParamUserType(2, "HTTPRequest") || !S.CheckParamEnd(3) ) { return 0; } // Get the parameters: HTTPRequest * request = nullptr; if (!S.GetStackValue(2, request)) { LOGWARNING("cWebAdmin:GetPage(): Cannot read the HTTPRequest parameter."); return 0; } // Generate the page and push the results as a dictionary-table: auto page = cRoot::Get()->GetWebAdmin()->GetPage(*request); lua_createtable(S, 0, 6); S.Push(page.Content); lua_setfield(S, -2, "Content"); S.Push(page.ContentType); lua_setfield(S, -2, "ContentType"); S.Push(page.TabUrlPath); lua_setfield(S, -2, "UrlPath"); S.Push(page.TabTitle); lua_setfield(S, -2, "TabTitle"); S.Push(page.PluginName); lua_setfield(S, -2, "PluginName"); S.Push(cPluginManager::Get()->GetPluginFolderName(page.PluginName)); lua_setfield(S, -2, "PluginFolder"); return 1; } /** Binding for cWebAdmin::GetURLEncodedString. */ static int tolua_cWebAdmin_GetURLEncodedString(lua_State * tolua_S) { // Emit the obsoletion warning: cLuaState S(tolua_S); LOGWARNING("cWebAdmin:GetURLEncodedString() is obsolete, use cUrlParser:UrlEncode() instead."); S.LogStackTrace(); return tolua_cUrlParser_UrlEncode(tolua_S); } static int tolua_cClientHandle_SendPluginMessage(lua_State * L) { cLuaState S(L); if ( !S.CheckParamSelf("cClientHandle") || !S.CheckParamString(2, 3) || !S.CheckParamEnd(4) ) { return 0; } cClientHandle * Client = static_cast(tolua_tousertype(L, 1, nullptr)); if (Client == nullptr) { LOGWARNING("ClientHandle is nil in cClientHandle:SendPluginMessage()"); S.LogStackTrace(); return 0; } AString Channel, Message; Channel.assign(lua_tostring(L, 2), lua_strlen(L, 2)); Message.assign(lua_tostring(L, 3), lua_strlen(L, 3)); Client->SendPluginMessage(Channel, Message); return 0; } static int tolua_cClientHandle_SendTimeUpdate(lua_State * L) { cLuaState S(L); if ( !S.CheckParamSelf("cClientHandle") || !S.CheckParamNumber(2, 3) || !S.CheckParamBool(4) || !S.CheckParamEnd(5) ) { return 0; } cClientHandle * Client; cTickTimeLong::rep WorldAge, WorldDate; bool DoDayLightCycle; S.GetStackValues(1, Client, WorldAge, WorldDate, DoDayLightCycle); if (Client == nullptr) { return S.ApiParamError("Invalid 'self'"); } Client->SendTimeUpdate(cTickTimeLong(WorldAge), cTickTimeLong(WorldDate), DoDayLightCycle); return 0; } static int tolua_cClientHandle_GetForgeMods(lua_State * L) { cLuaState S(L); if ( !S.CheckParamSelf("cClientHandle") || !S.CheckParamEnd(2) ) { return 0; } cClientHandle * Client; S.GetStackValue(1, Client); S.Push(Client->GetForgeMods()); return 1; } static int tolua_cClientHandle_GetUUID(lua_State * tolua_S) { // Check the params: cLuaState L(tolua_S); if ( !L.CheckParamSelf("cClientHandle") || !L.CheckParamEnd(2) ) { return 0; } // Get the params: cClientHandle * Self; L.GetStackValue(1, Self); // Return the UUID as a string: L.Push(Self->GetUUID().ToShortString()); return 1; } static int tolua_cClientHandle_GenerateOfflineUUID(lua_State * tolua_S) { // Check the params: cLuaState L(tolua_S); if ( !L.CheckParamStaticSelf("cClientHandle") || !L.CheckParamString(2) || !L.CheckParamEnd(3) ) { return 0; } // Get the params: AString Username; L.GetStackValue(2, Username); // Return the UUID as a string: L.Push(cClientHandle::GenerateOfflineUUID(Username).ToShortString()); return 1; } static int tolua_cClientHandle_IsUUIDOnline(lua_State * tolua_S) { // Check the params: cLuaState L(tolua_S); if ( !L.CheckParamStaticSelf("cClientHandle") || !L.CheckParamUUID(2) || !L.CheckParamEnd(3) ) { return 0; } // Get the params: cUUID UUID; L.GetStackValue(2, UUID); // Return the result: L.Push(cClientHandle::IsUUIDOnline(UUID)); return 1; } static int tolua_cMobHeadEntity_SetOwner(lua_State * tolua_S) { // Check params: cLuaState L(tolua_S); if ( !L.CheckParamSelf("cMobHeadEntity") || !L.CheckParamUUID(2) || !L.CheckParamString(3, 5) || !L.CheckParamEnd(6) ) { return 0; } // Get the params: cMobHeadEntity * Self; cUUID OwnerUUID; AString OwnerName, OwnerTexture, OwnerTextureSignature; L.GetStackValues(1, Self, OwnerUUID, OwnerName, OwnerTexture, OwnerTextureSignature); // Set the owner: Self->SetOwner(OwnerUUID, OwnerName, OwnerTexture, OwnerTextureSignature); return 0; } static int tolua_cMobHeadEntity_GetOwnerUUID(lua_State * tolua_S) { // Check params: cLuaState L(tolua_S); if ( !L.CheckParamSelf("cMobHeadEntity") || !L.CheckParamEnd(2) ) { return 0; } // Get the params: cMobHeadEntity * Self; L.GetStackValue(1, Self); // Return the UUID as a string: cUUID Owner = Self->GetOwnerUUID(); L.Push(Owner.IsNil() ? AString{} : Owner.ToShortString()); return 1; } static int tolua_cMojangAPI_AddPlayerNameToUUIDMapping(lua_State * L) { cLuaState S(L); if ( !S.CheckParamStaticSelf("cMojangAPI") || !S.CheckParamString(2) || !S.CheckParamUUID(3) || !S.CheckParamEnd(4) ) { return 0; } // Retrieve the parameters: AString PlayerName; cUUID UUID; S.GetStackValues(2, PlayerName, UUID); // Store in the cache: cRoot::Get()->GetMojangAPI().AddPlayerNameToUUIDMapping(PlayerName, UUID); return 0; } static int tolua_cMojangAPI_GetPlayerNameFromUUID(lua_State * L) { cLuaState S(L); if ( !S.CheckParamStaticSelf("cMojangAPI") || !S.CheckParamUUID(2) || !S.CheckParamEnd(4) ) { return 0; } cUUID UUID; S.GetStackValue(2, UUID); // If the UseOnlyCached param was given, read it; default to false bool ShouldUseCacheOnly = false; if (lua_gettop(L) == 3) { ShouldUseCacheOnly = (lua_toboolean(L, 3) != 0); lua_pop(L, 1); } // Return the PlayerName: AString PlayerName = cRoot::Get()->GetMojangAPI().GetPlayerNameFromUUID(UUID, ShouldUseCacheOnly); S.Push(PlayerName); return 1; } static int tolua_cMojangAPI_GetUUIDFromPlayerName(lua_State * L) { cLuaState S(L); if ( !S.CheckParamStaticSelf("cMojangAPI") || !S.CheckParamString(2) || !S.CheckParamEnd(4) ) { return 0; } AString PlayerName; S.GetStackValue(2, PlayerName); // If the UseOnlyCached param was given, read it; default to false bool ShouldUseCacheOnly = false; if (lua_gettop(L) == 3) { ShouldUseCacheOnly = (lua_toboolean(L, 3) != 0); lua_pop(L, 1); } // Return the UUID as a string: cUUID UUID = cRoot::Get()->GetMojangAPI().GetUUIDFromPlayerName(PlayerName, ShouldUseCacheOnly); S.Push(UUID.IsNil() ? AString{} : UUID.ToShortString()); return 1; } static int tolua_cMojangAPI_GetUUIDsFromPlayerNames(lua_State * L) { cLuaState S(L); if ( !S.CheckParamStaticSelf("cMojangAPI") || !S.CheckParamTable(2) || !S.CheckParamEnd(4) ) { return 0; } // Convert the input table into AStringVector: AStringVector PlayerNames; int NumNames = luaL_getn(L, 2); PlayerNames.reserve(static_cast(NumNames)); for (int i = 1; i <= NumNames; i++) { lua_rawgeti(L, 2, i); AString Name; S.GetStackValue(-1, Name); if (!Name.empty()) { PlayerNames.push_back(Name); } lua_pop(L, 1); } // If the UseOnlyCached param was given, read it; default to false bool ShouldUseCacheOnly = false; if (lua_gettop(L) == 3) { ShouldUseCacheOnly = (lua_toboolean(L, 3) != 0); lua_pop(L, 1); } // Push the output table onto the stack: lua_newtable(L); // Get the UUIDs: auto UUIDs = cRoot::Get()->GetMojangAPI().GetUUIDsFromPlayerNames(PlayerNames, ShouldUseCacheOnly); if (UUIDs.size() != PlayerNames.size()) { // A hard error has occured while processing the request, no UUIDs were returned. Return an empty table: return 1; } // Convert to output table, PlayerName -> UUID string: size_t len = UUIDs.size(); for (size_t i = 0; i < len; i++) { if (UUIDs[i].IsNil()) { // No UUID was provided for PlayerName[i], skip it in the resulting table continue; } S.Push(UUIDs[i].ToShortString()); lua_setfield(L, 3, PlayerNames[i].c_str()); } return 1; } static int tolua_cMojangAPI_MakeUUIDDashed(lua_State * L) { // Function now non-existant but kept for API compatibility // Check params: cLuaState S(L); if ( !S.CheckParamStaticSelf("cMojangAPI") || !S.CheckParamUUID(2) || !S.CheckParamEnd(3) ) { return 0; } // Get the params: cUUID UUID; S.GetStackValue(2, UUID); // Push the result: S.Push(UUID.ToLongString()); return 1; } static int tolua_cMojangAPI_MakeUUIDShort(lua_State * L) { // Function now non-existant but kept for API compatibility // Check params: cLuaState S(L); if ( !S.CheckParamUserTable(1, "cMojangAPI") || !S.CheckParamUUID(2) || !S.CheckParamEnd(3) ) { return 0; } // Get the params: cUUID UUID; S.GetStackValue(2, UUID); // Push the result: S.Push(UUID.ToShortString()); return 1; } static int tolua_get_cItem_m_LoreTable(lua_State * tolua_S) { // Check params: cLuaState L(tolua_S); if (!L.CheckParamSelf("const cItem")) { return 0; } // Get the params: const cItem * Self = nullptr; L.GetStackValue(1, Self); // Push the result: L.Push(Self->m_LoreTable); return 1; } static int tolua_cItem_EnchantByXPLevels(lua_State * tolua_S) { // Check params: cLuaState L(tolua_S); if ( !L.CheckParamSelf("cItem") || !L.CheckParamNumber(2) ) { return 0; } // Get the params: cItem * Self; unsigned NumXPLevels; L.GetStackValue(1, Self); L.GetStackValue(2, NumXPLevels); // Call: L.Push(Self->EnchantByXPLevels(NumXPLevels, GetRandomProvider())); return 1; } static int tolua_set_cItem_m_LoreTable(lua_State * tolua_S) { // Check params: cLuaState L(tolua_S); if ( !L.CheckParamSelf("cItem") || !L.CheckParamTable(2) ) { return 0; } // Get the params: cItem * Self = nullptr; L.GetStackValue(1, Self); // Set the value: Self->m_LoreTable.clear(); if (!L.GetStackValue(2, Self->m_LoreTable)) { return L.ApiParamError("cItem.m_LoreTable: Could not read value as an array of strings"); } return 0; } static int Lua_ItemGrid_GetSlotCoords(lua_State * L) { tolua_Error tolua_err; if ( !tolua_isusertype(L, 1, "const cItemGrid", 0, &tolua_err) || !tolua_isnumber (L, 2, 0, &tolua_err) || !tolua_isnoobj (L, 3, &tolua_err) ) { goto tolua_lerror; } { const cItemGrid * self = static_cast(tolua_tousertype(L, 1, nullptr)); int SlotNum = static_cast(tolua_tonumber(L, 2, 0)); if (self == nullptr) { tolua_error(L, "invalid 'self' in function 'cItemGrid:GetSlotCoords'", nullptr); return 0; } int X, Y; self->GetSlotCoords(SlotNum, X, Y); tolua_pushnumber(L, static_cast(X)); tolua_pushnumber(L, static_cast(Y)); return 2; } tolua_lerror: tolua_error(L, "#ferror in function 'cItemGrid:GetSlotCoords'.", &tolua_err); return 0; } /** Provides interface between a Lua table of callbacks and the cBlockTracer::cCallbacks */ class cLuaBlockTracerCallbacks : public cBlockTracer::cCallbacks { public: cLuaBlockTracerCallbacks(cLuaState::cTableRefPtr && a_Callbacks): m_Callbacks(std::move(a_Callbacks)) { } virtual bool OnNextBlock(Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, eBlockFace a_EntryFace) override { bool res = false; if (m_Callbacks->CallTableFn( "OnNextBlock", a_BlockPos, a_BlockType, a_BlockMeta, a_EntryFace, cLuaState::Return, res) ) { return res; } // No such function in the table, skip the callback return false; } virtual bool OnNextBlockNoData(Vector3i a_BlockPos, eBlockFace a_EntryFace) override { bool res = false; if (m_Callbacks->CallTableFn( "OnNextBlockNoData", a_BlockPos, a_EntryFace, cLuaState::Return, res) ) { return res; } // No such function in the table, skip the callback return false; } virtual bool OnOutOfWorld(Vector3d a_BlockPos) override { bool res = false; if (m_Callbacks->CallTableFn( "OnOutOfWorld", a_BlockPos, cLuaState::Return, res) ) { return res; } // No such function in the table, skip the callback return false; } virtual bool OnIntoWorld(Vector3d a_BlockPos) override { bool res = false; if (m_Callbacks->CallTableFn("OnIntoWorld", a_BlockPos, cLuaState::Return, res) ) { return res; } // No such function in the table, skip the callback return false; } virtual void OnNoMoreHits(void) override { m_Callbacks->CallTableFn("OnNoMoreHits"); } virtual void OnNoChunk(void) override { m_Callbacks->CallTableFn("OnNoChunk"); } protected: cLuaState::cTableRefPtr m_Callbacks; }; /** Provides interface between a Lua table of callbacks and the cBlockTracer::cCallbacks This is the deprecated version of cLuaBlockTracerCallback, used when the plugin calls the Trace function with number-based coords. */ class cLuaBlockTracerCallbacksOld : public cLuaBlockTracerCallbacks { public: cLuaBlockTracerCallbacksOld(cLuaState::cTableRefPtr && a_Callbacks): cLuaBlockTracerCallbacks(std::move(a_Callbacks)) { } virtual bool OnNextBlock(Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, eBlockFace a_EntryFace) override { bool res = false; if (m_Callbacks->CallTableFn( "OnNextBlock", a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, a_BlockType, a_BlockMeta, a_EntryFace, cLuaState::Return, res) ) { return res; } // No such function in the table, skip the callback return false; } virtual bool OnNextBlockNoData(Vector3i a_BlockPos, eBlockFace a_EntryFace) override { bool res = false; if (m_Callbacks->CallTableFn( "OnNextBlockNoData", a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, a_EntryFace, cLuaState::Return, res) ) { return res; } // No such function in the table, skip the callback return false; } virtual bool OnOutOfWorld(Vector3d a_BlockPos) override { bool res = false; if (m_Callbacks->CallTableFn( "OnOutOfWorld", a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, cLuaState::Return, res) ) { return res; } // No such function in the table, skip the callback return false; } virtual bool OnIntoWorld(Vector3d a_BlockPos) override { bool res = false; if (m_Callbacks->CallTableFn( "OnIntoWorld", a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, cLuaState::Return, res) ) { return res; } // No such function in the table, skip the callback return false; } }; static int tolua_cLineBlockTracer_FirstSolidHitTrace(lua_State * tolua_S) { /* Supported function signatures: cLineBlockTracer:FirstSolidHitTrace(World, StartX, StartY, StartZ, EndX, EndY, EndZ) -> bool, [Vector3d, Vector3i, eBlockFace] // Canonical cLineBlockTracer:FirstSolidHitTrace(World, Start, End) -> bool, [Vector3d, Vector3i, eBlockFace] // Canonical cLineBlockTracer.FirstSolidHitTrace(World, StartX, StartY, StartZ, EndX, EndY, EndZ) -> bool, [Vector3d, Vector3i, eBlockFace] cLineBlockTracer.FirstSolidHitTrace(World, Start, End) -> bool, [Vector3d, Vector3i, eBlockFace] */ // If the first param is the cLineBlockTracer class, shift param index by one: int idx = 1; tolua_Error err; if (tolua_isusertable(tolua_S, 1, "cLineBlockTracer", 0, &err)) { idx = 2; } // Check params: cLuaState L(tolua_S); if ( !L.CheckParamUserType(idx, "cWorld") ) { return 0; } if (L.IsParamNumber(idx + 1)) { // This is the number variant of the call: if ( !L.CheckParamNumber(idx + 1, idx + 6) || !L.CheckParamEnd(idx + 7) ) { return 0; } // Get the params: cWorld * world; double startX, startY, startZ; double endX, endY, endZ; if (!L.GetStackValues(idx, world, startX, startY, startZ, endX, endY, endZ)) { LOGWARNING("cLineBlockTracer:FirstSolidHitTrace(): Cannot read parameters, aborting the trace."); L.LogStackTrace(); L.LogStackValues("Values on the stack"); return 0; } Vector3d hitCoords; Vector3i hitBlockCoords; eBlockFace hitBlockFace; auto isHit = cLineBlockTracer::FirstSolidHitTrace(*world, Vector3d(startX, startY, startZ), Vector3d(endX, endY, endZ), hitCoords, hitBlockCoords, hitBlockFace); L.Push(isHit); if (!isHit) { return 1; } L.Push(hitCoords); L.Push(hitBlockCoords); L.Push(hitBlockFace); return 4; } if (L.IsParamVector3(idx + 1)) { // This is the Vector3-based variant of the call: if ( !L.CheckParamVector3(idx + 1, idx + 2) || !L.CheckParamEnd(idx + 3) ) { return 0; } // Get the params: cWorld * world; Vector3d start; Vector3d end; if (!L.GetStackValues(idx, world, start, end)) { LOGWARNING("cLineBlockTracer:FirstSolidHitTrace(): Cannot read parameters, aborting the trace."); L.LogStackTrace(); L.LogStackValues("Values on the stack"); return 0; } Vector3d hitCoords; Vector3i hitBlockCoords; eBlockFace hitBlockFace; auto isHit = cLineBlockTracer::FirstSolidHitTrace(*world, start, end, hitCoords, hitBlockCoords, hitBlockFace); L.Push(isHit); if (!isHit) { return 1; } L.Push(hitCoords); L.Push(hitBlockCoords); L.Push(hitBlockFace); return 4; } tolua_error(L, "cLineBlockTracer:FirstSolidHitTrace(): Invalid parameters, expected either a set of coords, or two Vector3's", nullptr); return 0; } static int tolua_cLineBlockTracer_LineOfSightTrace(lua_State * tolua_S) { /* Supported function signatures: cLineBlockTracer:LineOfSightTrace(World, StartX, StartY, StartZ, EndX, EndY, EndZ, Sight) -> bool // Canonical cLineBlockTracer:LineOfSightTrace(World, Start, End, Sight) -> bool // Canonical cLineBlockTracer.LineOfSightTrace(World, StartX, StartY, StartZ, EndX, EndY, EndZ, Sight) -> bool cLineBlockTracer.LineOfSightTrace(World, Start, End, Sight) -> bool */ // If the first param is the cLineBlockTracer class, shift param index by one: int idx = 1; tolua_Error err; if (tolua_isusertable(tolua_S, 1, "cLineBlockTracer", 0, &err)) { idx = 2; } // Check params: cLuaState L(tolua_S); if ( !L.CheckParamUserType(idx, "cWorld") ) { return 0; } if (L.IsParamNumber(idx + 1)) { // This is the number variant of the call: if ( !L.CheckParamNumber(idx + 1, idx + 6) || // Optional param lineOfSight is not checked !L.CheckParamEnd(idx + 8) ) { return 0; } // Get the params: cWorld * world; double startX, startY, startZ; double endX, endY, endZ; if (!L.GetStackValues(idx, world, startX, startY, startZ, endX, endY, endZ)) { LOGWARNING("cLineBlockTracer:LineOfSightTrace(): Cannot read parameters, aborting the trace."); L.LogStackTrace(); L.LogStackValues("Values on the stack"); return 0; } int lineOfSight = cLineBlockTracer::losAir | cLineBlockTracer::losWater; L.GetStackValue(idx + 7, lineOfSight); L.Push(cLineBlockTracer::LineOfSightTrace(*world, Vector3d(startX, startY, startZ), Vector3d(endX, endY, endZ), lineOfSight)); return 1; } if (L.IsParamVector3(idx + 1)) { // This is the Vector3-based variant of the call: if ( !L.CheckParamVector3(idx + 1, idx + 2) || // Optional param lineOfSight is not checked !L.CheckParamEnd(idx + 4) ) { return 0; } // Get the params: cWorld * world; Vector3d start; Vector3d end; if (!L.GetStackValues(idx, world, start, end)) { LOGWARNING("cLineBlockTracer:LineOfSightTrace(): Cannot read parameters, aborting the trace."); L.LogStackTrace(); L.LogStackValues("Values on the stack"); return 0; } int lineOfSight = cLineBlockTracer::losAirWater; L.GetStackValue(idx + 7, lineOfSight); L.Push(cLineBlockTracer::LineOfSightTrace(*world, start, end, lineOfSight)); return 1; } tolua_error(L, "cLineBlockTracer:LineOfSightTrace(): Invalid parameters, expected either a set of coords, or two Vector3's", nullptr); return 0; } static int tolua_cLineBlockTracer_Trace(lua_State * tolua_S) { /* Supported function signatures: cLineBlockTracer:Trace(World, Callbacks, StartX, StartY, StartZ, EndX, EndY, EndZ) // Canonical // DEPRECATED cLineBlockTracer.Trace(World, Callbacks, StartX, StartY, StartZ, EndX, EndY, EndZ) // DEPRECATED cLineBlockTracer:Trace(World, Callbacks, Start, End) // Canonical cLineBlockTracer.Trace(World, Callbacks, Start, End) */ // If the first param is the cLineBlockTracer class, shift param index by one: int idx = 1; tolua_Error err; if (tolua_isusertable(tolua_S, 1, "cLineBlockTracer", 0, &err)) { idx = 2; } // Check params: cLuaState L(tolua_S); if ( !L.CheckParamUserType(idx, "cWorld") || !L.CheckParamTable (idx + 1) ) { return 0; } // Get the params: cWorld * world; Vector3d start; Vector3d end; cLuaState::cTableRefPtr callbacks; if ( L.IsParamNumber (idx + 2) && L.IsParamNumber (idx + 3) && L.IsParamNumber (idx + 4) && L.IsParamNumber (idx + 5) && L.IsParamNumber (idx + 6) && L.IsParamNumber (idx + 7) && L.CheckParamEnd (idx + 8) ) { if (!L.GetStackValues(idx, world, callbacks, start.x, start.y, start.z, end.x, end.y, end.z)) { LOGWARNING("cLineBlockTracer:Trace(): Cannot read parameters (starting at idx %d), aborting the trace.", idx); L.LogStackTrace(); L.LogStackValues("Values on the stack"); return 0; } LOGWARNING("cLineBlockTracer:Trace(): Using plain numbers is deprecated, use Vector3 coords instead."); L.LogStackTrace(); // Trace: cLuaBlockTracerCallbacksOld tracerCallbacks(std::move(callbacks)); bool res = cLineBlockTracer::Trace(*world, tracerCallbacks, start, end); tolua_pushboolean(L, res ? 1 : 0); return 1; } else if ( L.IsParamVector3(idx + 2) && L.IsParamVector3(idx + 3) && L.CheckParamEnd (idx + 4) ) { if (!L.GetStackValues(idx, world, callbacks, start, end)) { LOGWARNING("cLineBlockTracer:Trace(): Cannot read parameters (starting at idx %d), aborting the trace.", idx); L.LogStackTrace(); L.LogStackValues("Values on the stack"); return 0; } // Trace: cLuaBlockTracerCallbacks tracerCallbacks(std::move(callbacks)); bool res = cLineBlockTracer::Trace(*world, tracerCallbacks, start, end); tolua_pushboolean(L, res ? 1 : 0); return 1; } return L.ApiParamError("Invalid overload of cLineBlockTracer:Trace()"); } static int tolua_cLuaWindow_new(lua_State * tolua_S) { // Function signature: // cLuaWindow:new(type, slotsX, slotsY, title) // Check params: cLuaState L(tolua_S); if ( !L.CheckParamUserTable(1, "cLuaWindow") || !L.CheckParamNumber(2, 4) || !L.CheckParamString(5) || !L.CheckParamEnd(6) ) { return 0; } // Read params: int windowType, slotsX, slotsY; AString title; if (!L.GetStackValues(2, windowType, slotsX, slotsY, title)) { LOGWARNING("%s: Cannot read Lua parameters", __FUNCTION__); L.LogStackValues(); L.LogStackTrace(); } // Create the window and return it: L.Push(new cLuaWindow(L, static_cast(windowType), slotsX, slotsY, title)); return 1; } static int tolua_cLuaWindow_new_local(lua_State * tolua_S) { // Function signature: // cLuaWindow:new(type, slotsX, slotsY, title) // Check params: cLuaState L(tolua_S); if ( !L.CheckParamUserTable(1, "cLuaWindow") || !L.CheckParamNumber(2, 4) || !L.CheckParamString(5) || !L.CheckParamEnd(6) ) { return 0; } // Read params: int windowType, slotsX, slotsY; AString title; if (!L.GetStackValues(2, windowType, slotsX, slotsY, title)) { LOGWARNING("%s: Cannot read Lua parameters", __FUNCTION__); L.LogStackValues(); L.LogStackTrace(); } // Create the window, register it for GC and return it: L.Push(new cLuaWindow(L, static_cast(windowType), slotsX, slotsY, title)); tolua_register_gc(tolua_S, lua_gettop(tolua_S)); return 1; } static int tolua_cRoot_DoWithPlayerByUUID(lua_State * tolua_S) { // Check params: cLuaState L(tolua_S); if ( !L.CheckParamSelf("cRoot") || !L.CheckParamUUID(2) || !L.CheckParamFunction(3) || !L.CheckParamEnd(4) ) { return 0; } // Get parameters: cRoot * Self; cUUID PlayerUUID; cLuaState::cRef FnRef; L.GetStackValues(1, Self, PlayerUUID, FnRef); if (PlayerUUID.IsNil()) { return L.ApiParamError("Expected a non-nil UUID for parameter #1"); } if (!FnRef.IsValid()) { return L.ApiParamError("Expected a valid callback function for parameter #2"); } // Call the function: bool res = Self->DoWithPlayerByUUID(PlayerUUID, [&](cPlayer & a_Player) { bool ret = false; L.Call(FnRef, &a_Player, cLuaState::Return, ret); return ret; } ); // Push the result as the return value: L.Push(res); return 1; } static int tolua_cRoot_GetBuildCommitID(lua_State * tolua_S) { cLuaState L(tolua_S); L.Push(BUILD_COMMIT_ID); return 1; } static int tolua_cRoot_GetBuildDateTime(lua_State * tolua_S) { cLuaState L(tolua_S); L.Push(BUILD_DATETIME); return 1; } static int tolua_cRoot_GetBuildID(lua_State * tolua_S) { cLuaState L(tolua_S); L.Push(BUILD_ID); return 1; } static int tolua_cRoot_GetBuildSeriesName(lua_State * tolua_S) { cLuaState L(tolua_S); L.Push(BUILD_SERIES_NAME); return 1; } static int tolua_cRoot_GetBrewingRecipe(lua_State * tolua_S) { cLuaState L(tolua_S); if ( !L.CheckParamUserTable(1, "cRoot") || !L.CheckParamUserType (2, "const cItem") || !L.CheckParamUserType (3, "const cItem") || !L.CheckParamEnd (4) ) { return 0; } // Check the bottle param: cItem * Bottle = nullptr; L.GetStackValue(2, Bottle); if (Bottle == nullptr) { LOGWARNING("cRoot:GetBrewingRecipe: the Bottle parameter is nil or missing."); return 0; } cItem * Ingredient = nullptr; L.GetStackValue(3, Ingredient); if (Ingredient == nullptr) { LOGWARNING("cRoot:GetBrewingRecipe: the Ingredient parameter is nil or missing."); return 0; } // Get the recipe for the input cBrewingRecipes * BR = cRoot::Get()->GetBrewingRecipes(); const cBrewingRecipes::cRecipe * Recipe = BR->GetRecipeFrom(*Bottle, *Ingredient); if (Recipe == nullptr) { // There is no such brewing recipe for this bottle and ingredient, return no value return 0; } // Push the output item cItem & OutItem = const_cast(Recipe->Output); L.Push(&OutItem); return 1; } static int tolua_cRoot_GetFurnaceRecipe(lua_State * tolua_S) { cLuaState L(tolua_S); if ( !L.CheckParamUserTable(1, "cRoot") || !L.CheckParamUserType (2, "const cItem") || !L.CheckParamEnd (3) ) { return 0; } // Check the input param: cItem * Input = nullptr; L.GetStackValue(2, Input); if (Input == nullptr) { LOGWARNING("cRoot:GetFurnaceRecipe: the Input parameter is nil or missing."); return 0; } // Get the recipe for the input cFurnaceRecipe * FR = cRoot::Get()->GetFurnaceRecipe(); const cFurnaceRecipe::cRecipe * Recipe = FR->GetRecipeFrom(*Input); if (Recipe == nullptr) { // There is no such furnace recipe for this input, return no value return 0; } // Push the output, number of ticks and input as the three return values: L.Push(Recipe->Out, Recipe->CookTime, Recipe->In); return 3; } static int tolua_cServer_RegisterForgeMod(lua_State * a_LuaState) { cLuaState L(a_LuaState); if ( !L.CheckParamSelf("cServer") || !L.CheckParamString(2, 3) || !L.CheckParamNumber(4) || !L.CheckParamEnd(5) ) { return 0; } cServer * Server; AString Name, Version; UInt32 Protocol; L.GetStackValues(1, Server, Name, Version, Protocol); if (!Server->RegisterForgeMod(Name, Version, Protocol)) { tolua_error(L, "duplicate Forge mod name registration", nullptr); return 0; } return 0; } static int tolua_cServer_ScheduleTask(lua_State * a_LuaState) { // Function signature: // Server:ScheduleTask(NumTicks, Callback) // Retrieve the args: cLuaState L(a_LuaState); if ( !L.CheckParamUserType(1, "cServer") || !L.CheckParamNumber(2) || !L.CheckParamFunction(3) ) { return 0; } cServer * Server; int NumTicks; auto Task = std::make_shared(); if (!L.GetStackValues(1, Server, NumTicks, Task)) { return cManualBindings::lua_do_error(a_LuaState, "Error in function call '#funcname#': Cannot read parameters"); } if (Server == nullptr) { return cManualBindings::lua_do_error(a_LuaState, "Error in function call '#funcname#': Not called on an object instance"); } if (!Task->IsValid()) { return cManualBindings::lua_do_error(a_LuaState, "Error in function call '#funcname#': Could not store the callback parameter"); } Server->ScheduleTask(cTickTime(NumTicks), [Task](cServer & a_Server) { Task->Call(&a_Server); }); return 0; } static int tolua_cScoreboard_GetTeamNames(lua_State * L) { cLuaState S(L); if ( !S.CheckParamUserType(1, "cScoreboard") || !S.CheckParamEnd(2) ) { return 0; } // Get the groups: cScoreboard * Scoreboard = static_cast(tolua_tousertype(L, 1, nullptr)); AStringVector Teams = Scoreboard->GetTeamNames(); // Push the results: S.Push(Teams); return 1; } static int tolua_cHopperEntity_GetOutputBlockPos(lua_State * tolua_S) { // function cHopperEntity::GetOutputBlockPos() // Exported manually because tolua would require meaningless params cLuaState L(tolua_S); if ( !L.CheckParamUserType(1, "cHopperEntity") || !L.CheckParamNumber (2) || !L.CheckParamEnd (3) ) { return 0; } cHopperEntity * self = static_cast(tolua_tousertype(tolua_S, 1, nullptr)); if (self == nullptr) { tolua_error(tolua_S, "invalid 'self' in function 'cHopperEntity::GetOutputBlockPos()'", nullptr); return 0; } NIBBLETYPE a_BlockMeta = static_cast(tolua_tonumber(tolua_S, 2, 0)); auto res = self->GetOutputBlockPos(a_BlockMeta); tolua_pushboolean(tolua_S, res.first); if (res.first) { tolua_pushnumber(tolua_S, static_cast(res.second.x)); tolua_pushnumber(tolua_S, static_cast(res.second.y)); tolua_pushnumber(tolua_S, static_cast(res.second.z)); return 4; } return 1; } static int tolua_cBoundingBox_CalcLineIntersection(lua_State * a_LuaState) { /* Function signatures: bbox:CalcLineIntersection(pt1, pt2) -> bool, [number, blockface] cBoundingBox:CalcLineIntersection(min, max, pt1, pt2) -> bool, [number, blockface] (static) */ cLuaState L(a_LuaState); Vector3d min; Vector3d max; Vector3d pt1; Vector3d pt2; double lineCoeff; eBlockFace blockFace; bool res; if (L.GetStackValues(2, min, max, pt1, pt2)) // Try the static signature first { res = cBoundingBox::CalcLineIntersection(min, max, pt1, pt2, lineCoeff, blockFace); } else { const cBoundingBox * bbox; if (!L.GetStackValues(1, bbox, pt1, pt2)) // Try the regular signature { L.LogStackValues(); tolua_error(a_LuaState, "Invalid function params. Expected either bbox:CalcLineIntersection(pt1, pt2) or cBoundingBox:CalcLineIntersection(min, max, pt1, pt2).", nullptr); return 0; } res = bbox->CalcLineIntersection(pt1, pt2, lineCoeff, blockFace); } L.Push(res); if (res) { L.Push(lineCoeff, blockFace); return 3; } return 1; } static int tolua_cBoundingBox_Intersect(lua_State * a_LuaState) { /* Function signature: bbox:Intersect(a_OtherBbox) -> bool, cBoundingBox */ cLuaState L(a_LuaState); const cBoundingBox * self; const cBoundingBox * other; if (!L.GetStackValues(1, self, other)) { L.LogStackValues(); tolua_error(a_LuaState, "Invalid function params. Expected bbox:Intersect(otherBbox).", nullptr); return 0; } auto intersection = new cBoundingBox(*self); auto res = self->Intersect(*other, *intersection); L.Push(res); if (!res) { delete intersection; return 1; } L.Push(intersection); tolua_register_gc(L, lua_gettop(L)); // Make Lua own the "intersection" object return 2; } static int tolua_cChunkDesc_GetBlockTypeMeta(lua_State * a_LuaState) { /* Function signature: ChunkDesc:GetBlockTypeMeta(RelX, RelY, RelZ) -> BlockType, BlockMeta */ cLuaState L(a_LuaState); const cChunkDesc * self; int relX, relY, relZ; if (!L.GetStackValues(1, self, relX, relY, relZ)) { L.LogStackValues(); tolua_error(a_LuaState, "Invalid function params. Expected chunkDesc:GetBlockTypeMeta(relX, relY, relZ)", nullptr); return 0; } BLOCKTYPE blockType; NIBBLETYPE blockMeta; self->GetBlockTypeMeta(relX, relY, relZ, blockType, blockMeta); L.Push(blockType, blockMeta); return 2; } static int tolua_cColor_GetColor(lua_State * tolua_S) { cLuaState L(tolua_S); cColor * self; if (!L.CheckParamSelf("cColor") || !L.GetStackValue(1, self)) { return 0; } L.Push(self->GetRed(), self->GetGreen(), self->GetBlue()); return 3; } static int tolua_cCompositeChat_new(lua_State * a_LuaState) { /* Function signatures: cCompositeChat() cCompositeChat(a_ParseText, a_MessageType) */ // Check if it's the no-param version: cLuaState L(a_LuaState); if (lua_isnone(a_LuaState, 2)) { auto * res = static_cast(Mtolua_new(cCompositeChat())); L.Push(res); return 1; } // Check the second signature: AString parseText; if (!L.GetStackValue(2, parseText)) { tolua_Error err; tolua_error(a_LuaState, "Invalid ParseText parameter (1) in cCompositeChat constructor.", &err); return 0; } int messageTypeInt = mtCustom; if (!lua_isnone(a_LuaState, 3)) { if (!L.GetStackValue(3, messageTypeInt)) { tolua_Error err; tolua_error(a_LuaState, "Invalid type of the MessageType parameter (2) in cCompositeChat constructor.", &err); return 0; } if ((messageTypeInt < 0) || (messageTypeInt >= mtMaxPlusOne)) { tolua_Error err; tolua_error(a_LuaState, "Invalid MessageType parameter (2) value in cCompositeChat constructor.", &err); return 0; } } L.Push(static_cast(Mtolua_new(cCompositeChat(parseText, static_cast(messageTypeInt))))); return 1; } static int tolua_cCompositeChat_new_local(lua_State * a_LuaState) { // Use the same constructor as global, just register it for GC: auto res = tolua_cCompositeChat_new(a_LuaState); if (res == 1) { tolua_register_gc(a_LuaState, lua_gettop(a_LuaState)); } return res; } static int tolua_cCompositeChat_AddShowAchievementPart(lua_State * tolua_S) { // function cCompositeChat:AddShowAchievementPart(PlayerName, Achievement, [Style]) // Exported manually to support call-chaining (return *this) // Check params: cLuaState L(tolua_S); if ( !L.CheckParamUserType(1, "cCompositeChat") || !L.CheckParamString(2, 3) ) { return 0; } cCompositeChat * self = static_cast(tolua_tousertype(tolua_S, 1, nullptr)); if (self == nullptr) { tolua_error(tolua_S, "invalid 'self' in function call cCompositeChat::AddShowAchievementPart(string, string, string) const.", nullptr); return 0; } // Add the part: AString PlayerName, Achievement, Style; L.GetStackValues(2, PlayerName); L.GetStackValues(3, Achievement); L.GetStackValues(4, Style); self->AddShowAchievementPart(PlayerName, Achievement, Style); // Cut away everything from the stack except for the cCompositeChat instance; return that: lua_settop(tolua_S, 1); return 1; } static int tolua_cCompositeChat_AddRunCommandPart(lua_State * tolua_S) { // function cCompositeChat:AddRunCommandPart(Message, Command, [Style]) // Exported manually to support call-chaining (return *this) // Check params: cLuaState L(tolua_S); if ( !L.CheckParamUserType(1, "cCompositeChat") || !L.CheckParamString(2, 3) ) { return 0; } cCompositeChat * self = static_cast(tolua_tousertype(tolua_S, 1, nullptr)); if (self == nullptr) { tolua_error(tolua_S, "invalid 'self' in function 'cCompositeChat:AddRunCommandPart'", nullptr); return 0; } // Add the part: AString Text, Command, Style = "na"; L.GetStackValue(2, Text); L.GetStackValue(3, Command); L.GetStackValue(4, Style); self->AddRunCommandPart(Text, Command, Style); // Cut away everything from the stack except for the cCompositeChat instance; return that: lua_settop(L, 1); return 1; } static int tolua_cCompositeChat_AddSuggestCommandPart(lua_State * tolua_S) { // function cCompositeChat:AddSuggestCommandPart(Message, Command, [Style]) // Exported manually to support call-chaining (return *this) // Check params: cLuaState L(tolua_S); if ( !L.CheckParamUserType(1, "cCompositeChat") || !L.CheckParamString(2, 3) ) { return 0; } cCompositeChat * self = static_cast(tolua_tousertype(tolua_S, 1, nullptr)); if (self == nullptr) { tolua_error(tolua_S, "invalid 'self' in function 'cCompositeChat:AddSuggestCommandPart'", nullptr); return 0; } // Add the part: AString Text, Command, Style; L.GetStackValue(2, Text); L.GetStackValue(3, Command); L.GetStackValue(4, Style); self->AddSuggestCommandPart(Text, Command, Style); // Cut away everything from the stack except for the cCompositeChat instance; return that: lua_settop(L, 1); return 1; } static int tolua_cCompositeChat_AddTextPart(lua_State * tolua_S) { // function cCompositeChat:AddTextPart(Message, [Style]) // Exported manually to support call-chaining (return *this) // Check params: cLuaState L(tolua_S); if ( !L.CheckParamUserType(1, "cCompositeChat") || !L.CheckParamString(2) ) { return 0; } cCompositeChat * self = static_cast(tolua_tousertype(tolua_S, 1, nullptr)); if (self == nullptr) { tolua_error(tolua_S, "invalid 'self' in function 'cCompositeChat:AddTextPart'", nullptr); return 0; } // Add the part: AString Text, Style; L.GetStackValue(2, Text); L.GetStackValue(3, Style); self->AddTextPart(Text, Style); // Cut away everything from the stack except for the cCompositeChat instance; return that: lua_settop(L, 1); return 1; } static int tolua_cCompositeChat_AddUrlPart(lua_State * tolua_S) { // function cCompositeChat:AddTextPart(Message, Url, [Style]) // Exported manually to support call-chaining (return *this) // Check params: cLuaState L(tolua_S); if ( !L.CheckParamUserType(1, "cCompositeChat") || !L.CheckParamString(2, 3) ) { return 0; } cCompositeChat * self = static_cast(tolua_tousertype(tolua_S, 1, nullptr)); if (self == nullptr) { tolua_error(tolua_S, "invalid 'self' in function 'cCompositeChat:AddUrlPart'", nullptr); return 0; } // Add the part: AString Text, Url, Style; L.GetStackValue(2, Text); L.GetStackValue(3, Url); L.GetStackValue(4, Style); self->AddUrlPart(Text, Url, Style); // Cut away everything from the stack except for the cCompositeChat instance; return that: lua_settop(L, 1); return 1; } static int tolua_cCompositeChat_Clear(lua_State * tolua_S) { // function cCompositeChat:Clear() // Exported manually to support call-chaining (return *this) // Check params: cLuaState L(tolua_S); if ( !L.CheckParamUserType(1, "cCompositeChat") || !L.CheckParamEnd(2) ) { return 0; } cCompositeChat * self = static_cast(tolua_tousertype(tolua_S, 1, nullptr)); if (self == nullptr) { tolua_error(tolua_S, "invalid 'self' in function 'cCompositeChat:ParseText'", nullptr); return 0; } // Clear all the parts: self->Clear(); // Cut away everything from the stack except for the cCompositeChat instance; return that: lua_settop(L, 1); return 1; } static int tolua_cCompositeChat_ParseText(lua_State * tolua_S) { // function cCompositeChat:ParseText(TextMessage) // Exported manually to support call-chaining (return *this) // Check params: cLuaState L(tolua_S); if ( !L.CheckParamUserType(1, "cCompositeChat") || !L.CheckParamString(2) ) { return 0; } cCompositeChat * self = static_cast(tolua_tousertype(tolua_S, 1, nullptr)); if (self == nullptr) { tolua_error(tolua_S, "invalid 'self' in function 'cCompositeChat:ParseText'", nullptr); return 0; } // Parse the text: AString Text; L.GetStackValue(2, Text); self->ParseText(Text); // Cut away everything from the stack except for the cCompositeChat instance; return that: lua_settop(L, 1); return 1; } static int tolua_cCompositeChat_SetMessageType(lua_State * tolua_S) { // function cCompositeChat:SetMessageType(MessageType) // Exported manually to support call-chaining (return *this) // Check params: cLuaState L(tolua_S); if ( !L.CheckParamUserType(1, "cCompositeChat") || !L.CheckParamNumber(2) ) { return 0; } cCompositeChat * self = static_cast(tolua_tousertype(tolua_S, 1, nullptr)); if (self == nullptr) { tolua_error(tolua_S, "invalid 'self' in function 'cCompositeChat:SetMessageType'", nullptr); return 0; } // Set the type: int MessageType = mtCustom; L.GetStackValue(2, MessageType); self->SetMessageType(static_cast(MessageType)); // Cut away everything from the stack except for the cCompositeChat instance; return that: lua_settop(L, 1); return 1; } static int tolua_cCompositeChat_UnderlineUrls(lua_State * tolua_S) { // function cCompositeChat:UnderlineUrls() // Exported manually to support call-chaining (return self) // Check params: cLuaState L(tolua_S); if (!L.CheckParamUserType(1, "cCompositeChat")) { return 0; } cCompositeChat * self = static_cast(tolua_tousertype(tolua_S, 1, nullptr)); if (self == nullptr) { tolua_error(tolua_S, "invalid 'self' in function 'cCompositeChat:UnderlineUrls'", nullptr); return 0; } // Call the processing self->UnderlineUrls(); // Cut away everything from the stack except for the cCompositeChat instance; return that: lua_settop(L, 1); return 1; } static int tolua_cCuboid_Assign(lua_State * tolua_S) { cLuaState L(tolua_S); if (!L.CheckParamSelf("cCuboid")) { return 0; } cCuboid * self = nullptr; L.GetStackValue(1, self); // Check the old coord-based signature: int x1, y1, z1, x2, y2, z2; if (L.GetStackValues(2, x1, y1, z1, x2, y2, z2)) { LOGWARNING("cCuboid:Assign(x1, y1, z1, x2, y2, z2) is deprecated, use cCuboid:Assign(Vector3i, Vector3i) instead."); L.LogStackTrace(); self->Assign({x1, y1, z1}, {x2, y2, z2}); return 0; } // Try the (cCuboid) param version: cCuboid * other = nullptr; if (L.GetStackValue(2, other) && (other != nullptr)) { self->Assign(*other); return 0; } // Try the (Vector3i, Vector3i) param version: Vector3i pt1; Vector3i pt2; if (L.GetStackValues(2, pt1, pt2)) { self->Assign(pt1, pt2); return 0; } return L.ApiParamError("Invalid parameter, expected either a cCuboid or two Vector3i-s."); } static int tolua_cCuboid_IsInside(lua_State * tolua_S) { cLuaState L(tolua_S); if (!L.CheckParamSelf("cCuboid")) { return 0; } cCuboid * self = nullptr; L.GetStackValue(1, self); // Check the old coord-based signature: int x, y, z; if (L.GetStackValues(2, x, y, z)) { LOGWARNING("cCuboid:IsInside(x, y, z) is deprecated, use cCuboid:IsInside(Vector3) instead."); L.LogStackTrace(); L.Push(self->IsInside(Vector3i{x, y, z})); return 1; } // Try the Vector3 param version: Vector3d pt; if (L.GetStackValue(2, pt)) { L.Push(self->IsInside(pt)); return 1; } return L.ApiParamError("Invalid parameter #2, expected a Vector3."); } static int tolua_cCuboid_Move(lua_State * tolua_S) { cLuaState L(tolua_S); if (!L.CheckParamSelf("cCuboid")) { return 0; } cCuboid * self = nullptr; L.GetStackValue(1, self); // Check the old coord-based signature: int x, y, z; if (L.GetStackValues(2, x, y, z)) { LOGWARNING("cCuboid:Move(x, y, z) is deprecated, use cCuboid:Move(Vector3i) instead."); L.LogStackTrace(); self->Move({x, y, z}); return 0; } Vector3i offset; if (!L.GetStackValue(2, offset)) { return L.ApiParamError("Invalid parameter #2, expected a Vector3."); } self->Move(offset); return 0; } static int tolua_cEntity_Destroy(lua_State * tolua_S) { // Check the params: cLuaState L(tolua_S); if (!L.CheckParamSelf("cEntity")) { return 0; } // Get the params: cEntity * self = nullptr; L.GetStackValue(1, self); if (lua_gettop(L) == 2) { LOGWARNING("cEntity:Destroy(bool) is deprecated, use cEntity:Destroy() instead."); } if (self->IsPlayer()) { return L.ApiParamError("Cannot call cEntity:Destroy() on a cPlayer, use cClientHandle:Kick() instead."); } self->Destroy(); return 0; } static int tolua_cEntity_IsSubmerged(lua_State * tolua_S) { // Check the params: cLuaState L(tolua_S); if (!L.CheckParamSelf("cEntity")) { return 0; } // Get the params: cEntity * self = nullptr; L.GetStackValue(1, self); // API function deprecated: LOGWARNING("cEntity:IsSubmerged() is deprecated. Use cEntity:IsHeadInWater() instead."); cLuaState::LogStackTrace(tolua_S); L.Push(self->IsHeadInWater()); return 1; } static int tolua_cEntity_IsSwimming(lua_State * tolua_S) { // Check the params: cLuaState L(tolua_S); if (!L.CheckParamSelf("cEntity")) { return 0; } // Get the params: cEntity * self = nullptr; L.GetStackValue(1, self); // API function deprecated LOGWARNING("cEntity:IsSwimming() is deprecated. Use cEntity:IsInWater() instead."); cLuaState::LogStackTrace(tolua_S); L.Push(self->IsInWater()); return 1; } static int tolua_cEntity_GetPosition(lua_State * tolua_S) { cLuaState L(tolua_S); // Get the params: cEntity * self = static_cast(tolua_tousertype(tolua_S, 1, nullptr)); if (self == nullptr) { LOGWARNING("%s: invalid self (%p)", __FUNCTION__, static_cast(self)); return 0; } L.Push(Mtolua_new((Vector3d)(self->GetPosition()))); tolua_register_gc(L, lua_gettop(L)); // Make Lua own the object return 1; } static int tolua_cEntity_GetSpeed(lua_State * tolua_S) { cLuaState L(tolua_S); // Get the params: cEntity * self = static_cast(tolua_tousertype(tolua_S, 1, nullptr)); if (self == nullptr) { LOGWARNING("%s: invalid self (%p)", __FUNCTION__, static_cast(self)); return 0; } L.Push(Mtolua_new((Vector3d)(self->GetSpeed()))); tolua_register_gc(L, lua_gettop(L)); // Make Lua own the object return 1; } static int tolua_get_StatisticsManager_Custom(lua_State * tolua_S) { // Check the params: cLuaState L(tolua_S); if (!L.CheckParamNumber(2)) { return 0; } // Get the params: lua_pushstring(tolua_S, ".self"); lua_rawget(tolua_S, 1); StatisticsManager * Self = static_cast(lua_touserdata(tolua_S, -1)); CustomStatistic Statistic; if (!L.GetStackValue(2, Statistic)) { return L.ApiParamError("Expected a valid custom statistic ID"); } // Push result if statistic exists: if (const auto Result = Self->Custom.find(Statistic); Result != Self->Custom.end()) { L.Push(Result->second); return 1; } return 0; } static int tolua_set_StatisticsManager_Custom(lua_State * tolua_S) { // Check the params: cLuaState L(tolua_S); if (!L.CheckParamNumber(2)) { return 0; } // Get the params: lua_pushstring(tolua_S, ".self"); lua_rawget(tolua_S, 1); StatisticsManager * Self = static_cast(lua_touserdata(tolua_S, -1)); CustomStatistic Statistic; StatisticsManager::StatValue Value; if (!L.GetStackValues(2, Statistic, Value)) { return L.ApiParamError("Expected a valid custom statistic ID and value"); } // Set the value: Self->Custom[Statistic] = Value; return 0; } void cManualBindings::Bind(lua_State * tolua_S) { tolua_beginmodule(tolua_S, nullptr); // Create the new classes: tolua_usertype(tolua_S, "cCryptoHash"); tolua_usertype(tolua_S, "cLineBlockTracer"); tolua_usertype(tolua_S, "cStringCompression"); tolua_usertype(tolua_S, "cUrlParser"); // StatisticsManager was already created by cPlayer::GetStatistics' autogenerated bindings. tolua_cclass(tolua_S, "cCryptoHash", "cCryptoHash", "", nullptr); tolua_cclass(tolua_S, "cLineBlockTracer", "cLineBlockTracer", "", nullptr); tolua_cclass(tolua_S, "cStringCompression", "cStringCompression", "", nullptr); tolua_cclass(tolua_S, "cUrlParser", "cUrlParser", "", nullptr); tolua_cclass(tolua_S, "StatisticsManager", "StatisticsManager", "", nullptr); // Globals: tolua_function(tolua_S, "Clamp", tolua_Clamp); tolua_function(tolua_S, "StringSplit", tolua_StringSplit); tolua_function(tolua_S, "StringSplitWithQuotes", tolua_StringSplitWithQuotes); tolua_function(tolua_S, "StringSplitAndTrim", tolua_StringSplitAndTrim); tolua_function(tolua_S, "LOG", tolua_LOG); tolua_function(tolua_S, "LOGINFO", tolua_LOGINFO); tolua_function(tolua_S, "LOGWARN", tolua_LOGWARN); tolua_function(tolua_S, "LOGWARNING", tolua_LOGWARN); tolua_function(tolua_S, "LOGERROR", tolua_LOGERROR); tolua_function(tolua_S, "Base64Encode", tolua_Base64Encode); tolua_function(tolua_S, "Base64Decode", tolua_Base64Decode); tolua_function(tolua_S, "md5", tolua_md5_obsolete); // OBSOLETE, use cCryptoHash.md5() instead tolua_beginmodule(tolua_S, "cBoundingBox"); tolua_function(tolua_S, "CalcLineIntersection", tolua_cBoundingBox_CalcLineIntersection); tolua_function(tolua_S, "Intersect", tolua_cBoundingBox_Intersect); tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "cChunkDesc"); tolua_function(tolua_S, "GetBlockTypeMeta", tolua_cChunkDesc_GetBlockTypeMeta); tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "cClientHandle"); tolua_constant(tolua_S, "MAX_VIEW_DISTANCE", cClientHandle::MAX_VIEW_DISTANCE); tolua_constant(tolua_S, "MIN_VIEW_DISTANCE", cClientHandle::MIN_VIEW_DISTANCE); tolua_function(tolua_S, "GetForgeMods", tolua_cClientHandle_GetForgeMods); tolua_function(tolua_S, "SendPluginMessage", tolua_cClientHandle_SendPluginMessage); tolua_function(tolua_S, "SendTimeUpdate", tolua_cClientHandle_SendTimeUpdate); tolua_function(tolua_S, "GetUUID", tolua_cClientHandle_GetUUID); tolua_function(tolua_S, "GenerateOfflineUUID", tolua_cClientHandle_GenerateOfflineUUID); tolua_function(tolua_S, "IsUUIDOnline", tolua_cClientHandle_IsUUIDOnline); tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "cColor"); tolua_function(tolua_S, "GetColor", tolua_cColor_GetColor); tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "cCompositeChat"); tolua_function(tolua_S, "new", tolua_cCompositeChat_new); tolua_function(tolua_S, "new_local", tolua_cCompositeChat_new_local); tolua_function(tolua_S, ".call", tolua_cCompositeChat_new_local); tolua_function(tolua_S, "AddShowAchievementPart", tolua_cCompositeChat_AddShowAchievementPart); tolua_function(tolua_S, "AddRunCommandPart", tolua_cCompositeChat_AddRunCommandPart); tolua_function(tolua_S, "AddSuggestCommandPart", tolua_cCompositeChat_AddSuggestCommandPart); tolua_function(tolua_S, "AddTextPart", tolua_cCompositeChat_AddTextPart); tolua_function(tolua_S, "AddUrlPart", tolua_cCompositeChat_AddUrlPart); tolua_function(tolua_S, "Clear", tolua_cCompositeChat_Clear); tolua_function(tolua_S, "ParseText", tolua_cCompositeChat_ParseText); tolua_function(tolua_S, "SetMessageType", tolua_cCompositeChat_SetMessageType); tolua_function(tolua_S, "UnderlineUrls", tolua_cCompositeChat_UnderlineUrls); tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "cCryptoHash"); tolua_function(tolua_S, "md5", tolua_md5); tolua_function(tolua_S, "md5HexString", tolua_md5HexString); tolua_function(tolua_S, "sha1", tolua_sha1); tolua_function(tolua_S, "sha1HexString", tolua_sha1HexString); tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "cCuboid"); tolua_function(tolua_S, "Assign", tolua_cCuboid_Assign); tolua_function(tolua_S, "IsInside", tolua_cCuboid_IsInside); tolua_function(tolua_S, "Move", tolua_cCuboid_Move); tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "cEntity"); tolua_constant(tolua_S, "INVALID_ID", cEntity::INVALID_ID); tolua_function(tolua_S, "Destroy", tolua_cEntity_Destroy); tolua_function(tolua_S, "IsSubmerged", tolua_cEntity_IsSubmerged); tolua_function(tolua_S, "IsSwimming", tolua_cEntity_IsSwimming); tolua_function(tolua_S, "GetPosition", tolua_cEntity_GetPosition); tolua_function(tolua_S, "GetSpeed", tolua_cEntity_GetSpeed); tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "cFile"); tolua_function(tolua_S, "ChangeFileExt", tolua_cFile_ChangeFileExt); tolua_function(tolua_S, "Copy", tolua_cFile_Copy); tolua_function(tolua_S, "CreateFolder", tolua_cFile_CreateFolder); tolua_function(tolua_S, "CreateFolderRecursive", tolua_cFile_CreateFolderRecursive); tolua_function(tolua_S, "Delete", tolua_cFile_Delete); tolua_function(tolua_S, "DeleteFile", tolua_cFile_DeleteFile); tolua_function(tolua_S, "DeleteFolder", tolua_cFile_DeleteFolder); tolua_function(tolua_S, "DeleteFolderContents", tolua_cFile_DeleteFolderContents); tolua_function(tolua_S, "Exists", tolua_cFile_Exists); tolua_function(tolua_S, "GetFolderContents", tolua_cFile_GetFolderContents); tolua_function(tolua_S, "GetLastModificationTime", tolua_cFile_GetLastModificationTime); tolua_function(tolua_S, "GetSize", tolua_cFile_GetSize); tolua_function(tolua_S, "IsFile", tolua_cFile_IsFile); tolua_function(tolua_S, "IsFolder", tolua_cFile_IsFolder); tolua_function(tolua_S, "ReadWholeFile", tolua_cFile_ReadWholeFile); tolua_function(tolua_S, "Rename", tolua_cFile_Rename); tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "cHopperEntity"); tolua_function(tolua_S, "GetOutputBlockPos", tolua_cHopperEntity_GetOutputBlockPos); tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "cItem"); tolua_function(tolua_S, "EnchantByXPLevels", tolua_cItem_EnchantByXPLevels); tolua_variable(tolua_S, "m_LoreTable", tolua_get_cItem_m_LoreTable, tolua_set_cItem_m_LoreTable); tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "cItemGrid"); tolua_function(tolua_S, "GetSlotCoords", Lua_ItemGrid_GetSlotCoords); tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "cLineBlockTracer"); tolua_function(tolua_S, "FirstSolidHitTrace", tolua_cLineBlockTracer_FirstSolidHitTrace); tolua_function(tolua_S, "LineOfSightTrace", tolua_cLineBlockTracer_LineOfSightTrace); tolua_function(tolua_S, "Trace", tolua_cLineBlockTracer_Trace); tolua_constant(tolua_S, "losAir", cLineBlockTracer::losAir); tolua_constant(tolua_S, "losWater", cLineBlockTracer::losWater); tolua_constant(tolua_S, "losLava", cLineBlockTracer::losLava); tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "cLuaWindow"); tolua_function(tolua_S, "new", tolua_cLuaWindow_new); tolua_function(tolua_S, "new_local", tolua_cLuaWindow_new_local); tolua_function(tolua_S, ".call", tolua_cLuaWindow_new_local); tolua_function(tolua_S, "SetOnClicked", tolua_SetObjectCallback); tolua_function(tolua_S, "SetOnClosing", tolua_SetObjectCallback); tolua_function(tolua_S, "SetOnSlotChanged", tolua_SetObjectCallback); tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "cMapManager"); tolua_function(tolua_S, "DoWithMap", DoWithID); tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "cMobHeadEntity"); tolua_function(tolua_S, "SetOwner", tolua_cMobHeadEntity_SetOwner); tolua_function(tolua_S, "GetOwnerUUID", tolua_cMobHeadEntity_GetOwnerUUID); tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "cMojangAPI"); tolua_function(tolua_S, "AddPlayerNameToUUIDMapping", tolua_cMojangAPI_AddPlayerNameToUUIDMapping); tolua_function(tolua_S, "GetPlayerNameFromUUID", tolua_cMojangAPI_GetPlayerNameFromUUID); tolua_function(tolua_S, "GetUUIDFromPlayerName", tolua_cMojangAPI_GetUUIDFromPlayerName); tolua_function(tolua_S, "GetUUIDsFromPlayerNames", tolua_cMojangAPI_GetUUIDsFromPlayerNames); tolua_function(tolua_S, "MakeUUIDDashed", tolua_cMojangAPI_MakeUUIDDashed); tolua_function(tolua_S, "MakeUUIDShort", tolua_cMojangAPI_MakeUUIDShort); tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "cPlayer"); tolua_function(tolua_S, "GetPermissions", tolua_cPlayer_GetPermissions); tolua_function(tolua_S, "GetRestrictions", tolua_cPlayer_GetRestrictions); tolua_function(tolua_S, "GetUUID", tolua_cPlayer_GetUUID); tolua_function(tolua_S, "PermissionMatches", tolua_cPlayer_PermissionMatches); tolua_function(tolua_S, "PlaceBlock", tolua_cPlayer_PlaceBlock); tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "cPlugin"); tolua_function(tolua_S, "GetDirectory", tolua_cPlugin_GetDirectory); tolua_function(tolua_S, "GetLocalDirectory", tolua_cPlugin_GetLocalDirectory); tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "cPluginLua"); tolua_function(tolua_S, "AddWebTab", tolua_cPluginLua_AddWebTab); tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "cPluginManager"); tolua_function(tolua_S, "AddHook", tolua_cPluginManager_AddHook); tolua_function(tolua_S, "BindCommand", tolua_cPluginManager_BindCommand); tolua_function(tolua_S, "BindConsoleCommand", tolua_cPluginManager_BindConsoleCommand); tolua_function(tolua_S, "CallPlugin", tolua_cPluginManager_CallPlugin); tolua_function(tolua_S, "DoWithPlugin", StaticDoWith); tolua_function(tolua_S, "ExecuteConsoleCommand", tolua_cPluginManager_ExecuteConsoleCommand); tolua_function(tolua_S, "FindPlugins", tolua_cPluginManager_FindPlugins); tolua_function(tolua_S, "ForEachCommand", tolua_cPluginManager_ForEachCommand); tolua_function(tolua_S, "ForEachConsoleCommand", tolua_cPluginManager_ForEachConsoleCommand); tolua_function(tolua_S, "ForEachPlugin", StaticForEach); tolua_function(tolua_S, "GetAllPlugins", tolua_cPluginManager_GetAllPlugins); tolua_function(tolua_S, "GetCurrentPlugin", tolua_cPluginManager_GetCurrentPlugin); tolua_function(tolua_S, "GetPlugin", tolua_cPluginManager_GetPlugin); tolua_function(tolua_S, "LogStackTrace", tolua_cPluginManager_LogStackTrace); tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "cRoot"); tolua_function(tolua_S, "DoWithPlayerByUUID", tolua_cRoot_DoWithPlayerByUUID); tolua_function(tolua_S, "FindAndDoWithPlayer", DoWith ); tolua_function(tolua_S, "ForEachPlayer", ForEach); tolua_function(tolua_S, "ForEachWorld", ForEach); tolua_function(tolua_S, "GetBrewingRecipe", tolua_cRoot_GetBrewingRecipe); tolua_function(tolua_S, "GetBuildCommitID", tolua_cRoot_GetBuildCommitID); tolua_function(tolua_S, "GetBuildDateTime", tolua_cRoot_GetBuildDateTime); tolua_function(tolua_S, "GetBuildID", tolua_cRoot_GetBuildID); tolua_function(tolua_S, "GetBuildSeriesName", tolua_cRoot_GetBuildSeriesName); tolua_function(tolua_S, "GetFurnaceRecipe", tolua_cRoot_GetFurnaceRecipe); tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "cScoreboard"); tolua_function(tolua_S, "ForEachObjective", ForEach); tolua_function(tolua_S, "ForEachTeam", ForEach); tolua_function(tolua_S, "GetTeamNames", tolua_cScoreboard_GetTeamNames); tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "cServer"); tolua_function(tolua_S, "RegisterForgeMod", tolua_cServer_RegisterForgeMod); tolua_function(tolua_S, "ScheduleTask", tolua_cServer_ScheduleTask); tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "cStringCompression"); tolua_function(tolua_S, "CompressStringZLIB", tolua_CompressStringZLIB); tolua_function(tolua_S, "UncompressStringZLIB", tolua_UncompressStringZLIB); tolua_function(tolua_S, "CompressStringGZIP", tolua_CompressStringGZIP); tolua_function(tolua_S, "UncompressStringGZIP", tolua_InflateString); tolua_function(tolua_S, "InflateString", tolua_InflateString); tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "cUrlParser"); tolua_function(tolua_S, "GetDefaultPort", tolua_cUrlParser_GetDefaultPort); tolua_function(tolua_S, "IsKnownScheme", tolua_cUrlParser_IsKnownScheme); tolua_function(tolua_S, "Parse", tolua_cUrlParser_Parse); tolua_function(tolua_S, "ParseAuthorityPart", tolua_cUrlParser_ParseAuthorityPart); tolua_function(tolua_S, "UrlDecode", tolua_cUrlParser_UrlDecode); tolua_function(tolua_S, "UrlEncode", tolua_cUrlParser_UrlEncode); tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "cWebAdmin"); tolua_function(tolua_S, "AddWebTab", tolua_cWebAdmin_AddWebTab); tolua_function(tolua_S, "GetAllWebTabs", tolua_cWebAdmin_GetAllWebTabs); tolua_function(tolua_S, "GetPage", tolua_cWebAdmin_GetPage); tolua_function(tolua_S, "GetURLEncodedString", tolua_cWebAdmin_GetURLEncodedString); tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "HTTPRequest"); tolua_variable(tolua_S, "FormData", tolua_get_HTTPRequest_FormData, nullptr); tolua_variable(tolua_S, "Params", tolua_get_HTTPRequest_Params, nullptr); tolua_variable(tolua_S, "PostParams", tolua_get_HTTPRequest_PostParams, nullptr); tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "StatisticsManager"); tolua_array(tolua_S, "Custom", tolua_get_StatisticsManager_Custom, tolua_set_StatisticsManager_Custom); tolua_endmodule(tolua_S); BindNetwork(tolua_S); BindRankManager(tolua_S); BindWorld(tolua_S); BindBlockArea(tolua_S); tolua_endmodule(tolua_S); } ================================================ FILE: src/Bindings/ManualBindings.h ================================================ // ManualBindings.h // Declares the cManualBindings class used as a namespace for functions exported to the Lua API manually #pragma once #include "LuaState.h" // fwd: struct tolua_Error; class cPluginLua; /** Provides namespace for the bindings. */ class cManualBindings { public: /** Binds all the manually implemented functions to tolua_S. */ static void Bind(lua_State * tolua_S); protected: /** Binds the manually implemented cNetwork-related API to tolua_S. Implemented in ManualBindings_Network.cpp. */ static void BindNetwork(lua_State * tolua_S); /** Binds the manually implemented cRankManager glue code to tolua_S. Implemented in ManualBindings_RankManager.cpp. */ static void BindRankManager(lua_State * tolua_S); /** Binds the manually implemented cWorld API functions to tolua_S. Implemented in ManualBindings_World.cpp. */ static void BindWorld(lua_State * tolua_S); /** Binds the manually implemented cBlockArea API functions to tlua_S. Implemented in ManualBindings_BlockArea.cpp. */ static void BindBlockArea(lua_State * tolua_S); public: // Helper functions: static cPluginLua * GetLuaPlugin(lua_State * L); static int tolua_do_error(lua_State * L, const char * a_pMsg, tolua_Error * a_pToLuaError); static int vlua_do_error(lua_State * L, const char * a_pFormat, fmt::printf_args a_ArgList); template static int lua_do_error(lua_State * L, const char * a_Format, const Args & ... a_Args) { return vlua_do_error(L, a_Format, fmt::make_printf_args(a_Args...)); } /** Binds the DoWith(ItemName) functions of regular classes. */ template < class Ty1, class Ty2, bool (Ty1::*DoWithFn)(const AString &, cFunctionRef) > static int DoWith(lua_State * tolua_S) { // Check params: cLuaState L(tolua_S); if ( !L.CheckParamString(2) || !L.CheckParamFunction(3) ) { return 0; } // Get parameters: Ty1 * Self; AString ItemName; cLuaState::cRef FnRef; L.GetStackValues(1, Self, ItemName, FnRef); if (Self == nullptr) { return lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'self'"); } if (ItemName.empty() || (ItemName[0] == 0)) { return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a non-empty string for parameter #1"); } if (!FnRef.IsValid()) { return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a valid callback function for parameter #2"); } // Call the DoWith function: bool res = (Self->*DoWithFn)(ItemName, [&](Ty2 & a_Item) { bool ret = false; L.Call(FnRef, &a_Item, cLuaState::Return, ret); return ret; } ); // Push the result as the return value: L.Push(res); return 1; } /** Template for static functions DoWith(ItemName), on a type that has a static ::Get() function. */ template < class Ty1, class Ty2, bool (Ty1::*DoWithFn)(const AString &, cFunctionRef) > static int StaticDoWith(lua_State * tolua_S) { // Check params: cLuaState L(tolua_S); if ( !L.CheckParamString(2) || !L.CheckParamFunction(3) ) { return 0; } // Get parameters: AString ItemName; cLuaState::cRef FnRef; L.GetStackValues(2, ItemName, FnRef); if (ItemName.empty() || (ItemName[0] == 0)) { return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a non-empty string for parameter #1"); } if (!FnRef.IsValid()) { return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a valid callback function for parameter #2"); } // Call the DoWith function: bool res = (Ty1::Get()->*DoWithFn)(ItemName, [&](Ty2 & a_Item) { bool ret = false; L.Call(FnRef, &a_Item, cLuaState::Return, ret); return ret; } ); // Push the result as the return value: L.Push(res); return 1; } template < class Ty1, class Ty2, bool (Ty1::*DoWithFn)(UInt32, cFunctionRef) > static int DoWithID(lua_State * tolua_S) { // Check params: cLuaState L(tolua_S); if ( !L.CheckParamNumber(2) || !L.CheckParamFunction(3) ) { return 0; } // Get parameters: Ty1 * Self = nullptr; UInt32 ItemID = 0; cLuaState::cRef FnRef; L.GetStackValues(1, Self, ItemID, FnRef); if (Self == nullptr) { return lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'self'"); } if (!FnRef.IsValid()) { return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a valid callback function for parameter #2"); } // Call the DoWith function: bool res = (Self->*DoWithFn)(ItemID, [&](Ty2 & a_Item) { bool ret = false; L.Call(FnRef, &a_Item, cLuaState::Return, ret); return ret; } ); // Push the result as the return value: L.Push(res); return 1; } template < class Ty1, class Ty2, bool (Ty1::*ForEachFn)(cFunctionRef) > static int ForEach(lua_State * tolua_S) { // Check params: cLuaState L(tolua_S); if ( !L.CheckParamFunction(2) || !L.CheckParamEnd(3) ) { return 0; } // Get the params: Ty1 * Self = nullptr; cLuaState::cRef FnRef; L.GetStackValues(1, Self, FnRef); if (Self == nullptr) { return lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'self'."); } if (!FnRef.IsValid()) { return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a valid callback function for parameter #1"); } // Call the enumeration: bool res = (Self->*ForEachFn)([&](Ty2 & a_Item) { bool ret = false; // By default continue the enumeration L.Call(FnRef, &a_Item, cLuaState::Return, ret); return ret; } ); // Push the return value: L.Push(res); return 1; } /** Implements bindings for ForEach() functions in a class that is static (has a ::Get() static function). */ template < class Ty1, class Ty2, bool (Ty1::*ForEachFn)(cFunctionRef) > static int StaticForEach(lua_State * tolua_S) { // Check params: cLuaState L(tolua_S); if ( !L.CheckParamFunction(2) || !L.CheckParamEnd(3) ) { return 0; } // Get the params: cLuaState::cRef FnRef(L, 2); if (!FnRef.IsValid()) { return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a valid callback function for parameter #1"); } // Call the enumeration: bool res = (Ty1::Get()->*ForEachFn)([&](Ty2 & a_Item) { bool ret = false; // By default continue the enumeration L.Call(FnRef, &a_Item, cLuaState::Return, ret); return ret; } ); // Push the return value: L.Push(res); return 1; } }; ================================================ FILE: src/Bindings/ManualBindings_BlockArea.cpp ================================================ // ManualBindings_BlockArea.cpp // Implements the manual bindings for functions in the cBlockArea class #include "Globals.h" #include "tolua++/include/tolua++.h" #include "../BlockArea.h" #include "../World.h" #include "ManualBindings.h" #include "LuaState.h" #include "PluginLua.h" #include "../WorldStorage/SchematicFileSerializer.h" /** Template for the bindings for the DoWithXYZAt(X, Y, Z) functions that need to check their coords. */ template < class SELF, class ITEM, bool (SELF::*DoWithFn)(int, int, int, cFunctionRef), bool (SELF::*CoordCheckFn)(int, int, int) const > static int DoWithXYZ(lua_State * tolua_S) { // Check params: cLuaState L(tolua_S); if ( !L.CheckParamNumber(2, 4) || !L.CheckParamFunction(5) || !L.CheckParamEnd(6) ) { return 0; } // Get parameters: SELF * Self = nullptr; int BlockX = 0; int BlockY = 0; int BlockZ = 0; cLuaState::cRef FnRef; L.GetStackValues(1, Self, BlockX, BlockY, BlockZ, FnRef); if (Self == nullptr) { return L.ApiParamError("Invalid 'self'"); } if (!FnRef.IsValid()) { return L.ApiParamError("Expected a valid callback function for parameter #5"); } if (!(Self->*CoordCheckFn)(BlockX, BlockY, BlockZ)) { return L.ApiParamError(fmt::format(FMT_STRING("The provided coordinates ({0}) are not valid"), Vector3i{BlockX, BlockY, BlockZ} )); } // Call the DoWith function: bool res = (Self->*DoWithFn)(BlockX, BlockY, BlockZ, [&](ITEM & a_Item) { bool ret = false; L.Call(FnRef, &a_Item, cLuaState::Return, ret); return ret; } ); // Push the result as the return value: L.Push(res); return 1; } /** Reads params that together form a Cuboid. These can be: - 6 numbers (MinX, MaxX, MinY, MaxY, MinZ, MaxZ) - 2 Vector3-s (Min, Max) - cCuboid Returns the index of the first parameter following the Cuboid spec. Raises an Api error if the params don't specify a Cuboid. */ static int readCuboidOverloadParams(cLuaState & a_LuaState, int a_StartParam, cCuboid & a_Cuboid) { if (a_LuaState.IsParamNumber(a_StartParam)) { // Assume the 6-number version: if (!a_LuaState.GetStackValues(a_StartParam, a_Cuboid.p1.x, a_Cuboid.p2.x, a_Cuboid.p1.y, a_Cuboid.p2.y, a_Cuboid.p1.z, a_Cuboid.p2.z)) { return a_LuaState.ApiParamError("Cannot read the bounds parameters, expected 6 numbers"); } return a_StartParam + 6; } else if (a_LuaState.IsParamUserType(a_StartParam, "cCuboid")) { // Assume the cCuboid version: cCuboid * c; if (!a_LuaState.GetStackValues(a_StartParam, c)) { return a_LuaState.ApiParamError("Cannot read the bounds parameter, expected a cCuboid instance"); } a_Cuboid = *c; return a_StartParam + 1; } else { // Assume the 2-Vector3i version: if (!a_LuaState.GetStackValues(a_StartParam, a_Cuboid.p1, a_Cuboid.p2)) { return a_LuaState.ApiParamError("Cannot read the bounds parameter, expected two Vector3i instances"); } return a_StartParam + 2; } } /** Reads params that together form a Vector3i. These can be: - 3 numbers (x, y, z) - Vector3i Returns the index of the first parameter following the Vector3i spec. Raises an Api error if the params don't specify a Vector3i. */ static int readVector3iOverloadParams(cLuaState & a_LuaState, int a_StartParam, Vector3i & a_Coords, const char * a_ParamName) { if (a_LuaState.IsParamNumber(a_StartParam)) { // Assume the 3-number version: if (!a_LuaState.GetStackValues(a_StartParam, a_Coords.x, a_Coords.y, a_Coords.z)) { return a_LuaState.ApiParamError(fmt::format(FMT_STRING("Cannot read the {}, expected 3 numbers"), a_ParamName)); } return a_StartParam + 3; } else { // Assume the Vector3i version: if (!a_LuaState.GetStackValues(a_StartParam, a_Coords)) { return a_LuaState.ApiParamError(fmt::format(FMT_STRING("Cannot read the {}, expected a Vector3i instance"), a_ParamName)); } return a_StartParam + 1; } } /** Binding for the cBlockArea::Create() functions. Supports two overloads and one default parameter. */ static int tolua_cBlockArea_Create(lua_State * a_LuaState) { cLuaState L(a_LuaState); if (!L.CheckParamSelf("cBlockArea")) { return 0; } cBlockArea * self = nullptr; if (!L.GetStackValues(1, self)) { return L.ApiParamError("Cannot read self"); } if (self == nullptr) { return L.ApiParamError("Invalid 'self', must not be nil"); } int dataTypes = cBlockArea::baTypes | cBlockArea::baMetas | cBlockArea::baBlockEntities; Vector3i size; auto dataTypesIdx = readVector3iOverloadParams(L, 2, size, "size"); L.GetStackValue(dataTypesIdx, dataTypes); if (!cBlockArea::IsValidDataTypeCombination(dataTypes)) { return L.ApiParamError(fmt::format(FMT_STRING("Invalid combination of baDataTypes specified (0x{:02x})"), dataTypes)); } // Create the area: if ((size.x <= 0) || (size.y <= 0) || (size.z <= 0)) { return L.ApiParamError(fmt::format(FMT_STRING("Invalid sizes, must be greater than zero, got {}"), size)); } ASSERT(self != nullptr); self->Create(size, dataTypes); return 0; } /** Bindings for the cBlockArea:FillRelCuboid() functions. Supports coord overloads and one default parameter. */ static int tolua_cBlockArea_FillRelCuboid(lua_State * a_LuaState) { // Check the common params: cLuaState L(a_LuaState); if (!L.CheckParamSelf("cBlockArea")) { return 0; } // Get the common params: cBlockArea * self = nullptr; if (!L.GetStackValues(1, self)) { return L.ApiParamError("Cannot read self"); } if (self == nullptr) { return L.ApiParamError("Invalid 'self', must not be nil"); } // Check and get the overloaded params: cCuboid bounds; auto nextIdx = readCuboidOverloadParams(L, 2, bounds); bounds.Sort(); if (!(self->IsValidRelCoords(bounds.p1) && self->IsValidRelCoords(bounds.p2))) { return L.ApiParamError(fmt::format( FMT_STRING("The bounds ({0} - {1}) are out of range ({2} - {3})"), bounds.p1, bounds.p2, Vector3i(0, 0, 0), (self->GetSize() - Vector3i{1, 1, 1}) )); } int dataTypes = cBlockArea::baTypes | cBlockArea::baMetas | cBlockArea::baBlockEntities; BLOCKTYPE blockType; NIBBLETYPE blockMeta = 0, blockLight = 0, blockSkyLight = 0x0f; if (!L.GetStackValues(nextIdx, dataTypes, blockType)) { return L.ApiParamError("Cannot read the datatypes or block type params"); } L.GetStackValues(nextIdx + 2, blockMeta, blockLight, blockSkyLight); // These values are optional if (!cBlockArea::IsValidDataTypeCombination(dataTypes)) { return L.ApiParamError(fmt::format(FMT_STRING("Invalid baDataTypes combination (0x{:02x})"), dataTypes)); } // Do the actual Fill: self->FillRelCuboid(bounds, dataTypes, blockType, blockMeta, blockLight, blockSkyLight); return 0; } static int tolua_cBlockArea_GetBlockTypeMeta(lua_State * a_LuaState) { // function cBlockArea::GetBlockTypeMeta() cLuaState L(a_LuaState); if (!L.CheckParamSelf("cBlockArea")) { return 0; } cBlockArea * self; if (!L.GetStackValues(1, self)) { return L.ApiParamError("Cannot read 'self'"); } if (self == nullptr) { return L.ApiParamError("Invalid 'self', must not be nil"); } Vector3i coords; readVector3iOverloadParams(L, 2, coords, "coords"); if (!self->IsValidCoords(coords)) { return L.ApiParamError(fmt::format(FMT_STRING("Coords ({0}) out of range ({1} - {2})"), coords, self->GetOrigin(), self->GetOrigin() + self->GetSize() - Vector3i{1, 1, 1} )); } BLOCKTYPE blockType; NIBBLETYPE blockMeta; self->GetBlockTypeMeta(coords.x, coords.y, coords.z, blockType, blockMeta); L.Push(blockType, blockMeta); return 2; } static int tolua_cBlockArea_GetCoordRange(lua_State * a_LuaState) { // function cBlockArea::GetCoordRange() // Returns all three sizes of the area, each minus one, so that they represent the maximum coord value // Exported manually because there's no direct C++ equivalent, // plus tolua would generate extra input params for the outputs cLuaState L(a_LuaState); if (!L.CheckParamSelf("cBlockArea")) { return 0; } cBlockArea * self; if (!L.GetStackValues(1, self)) { return L.ApiParamError("Cannot read the 'self' parameter"); } if (self == nullptr) { return L.ApiParamError("Invalid 'self', must not be nil"); } L.Push(self->GetSizeX() - 1, self->GetSizeY() - 1, self->GetSizeZ() - 1); return 3; } static int tolua_cBlockArea_GetNonAirCropRelCoords(lua_State * a_LuaState) { // function cBlockArea::GetNonAirCropRelCoords() // Exported manually because tolua would generate extra input params for the outputs cLuaState L(a_LuaState); if (!L.CheckParamSelf("cBlockArea")) { return 0; } cBlockArea * self = nullptr; BLOCKTYPE ignoreBlockType = E_BLOCK_AIR; if (!L.GetStackValues(1, self, ignoreBlockType)) { return L.ApiParamError("Cannot read params"); } if (self == nullptr) { return L.ApiParamError("Invalid 'self', must not be nil"); } if (!self->HasBlockTypes()) { return L.ApiParamError("The area doesn't contain baTypes datatype"); } // Calculate the crop coords: int minRelX, minRelY, minRelZ, maxRelX, maxRelY, maxRelZ; self->GetNonAirCropRelCoords(minRelX, minRelY, minRelZ, maxRelX, maxRelY, maxRelZ, ignoreBlockType); // Push the six crop coords: L.Push(minRelX, minRelY, minRelZ, maxRelX, maxRelY, maxRelZ); return 6; } static int tolua_cBlockArea_GetOrigin(lua_State * a_LuaState) { // function cBlockArea::GetOrigin() // Returns all three coords of the origin point // Exported manually because there's no direct C++ equivalent, // plus tolua would generate extra input params for the outputs cLuaState L(a_LuaState); if (!L.CheckParamSelf("cBlockArea")) { return 0; } cBlockArea * self; if (!L.GetStackValues(1, self)) { return L.ApiParamError("Cannot read the 'self' parameter"); } if (self == nullptr) { return L.ApiParamError("Invalid 'self', must not be nil"); } // Push the three origin coords: L.Push(self->GetOriginX(), self->GetOriginY(), self->GetOriginZ()); return 3; } static int tolua_cBlockArea_GetRelBlockTypeMeta(lua_State * a_LuaState) { // function cBlockArea::GetRelBlockTypeMeta() // Exported manually because tolua generates extra input params for the outputs cLuaState L(a_LuaState); if (!L.CheckParamSelf("cBlockArea")) { return 0; } cBlockArea * self; if (!L.GetStackValues(1, self)) { return L.ApiParamError("Cannot read the 'self' parameter"); } if (self == nullptr) { return L.ApiParamError("Invalid 'self', must not be nil"); } if (!self->HasBlockTypes()) { return L.ApiParamError("The area doesn't contain baTypes datatype"); } if (!self->HasBlockMetas()) { return L.ApiParamError("The area doesn't contain baMetas datatype"); } Vector3i coords; readVector3iOverloadParams(L, 2, coords, "coords"); if (!self->IsValidRelCoords(coords)) { return L.ApiParamError(fmt::format(FMT_STRING("The coords ({0}) are out of range (max {1})"), coords, (self->GetSize() - Vector3i{1, 1, 1}) )); } BLOCKTYPE blockType; NIBBLETYPE blockMeta; self->GetRelBlockTypeMeta(coords.x, coords.y, coords.z, blockType, blockMeta); L.Push(blockType, blockMeta); return 2; } static int tolua_cBlockArea_GetSize(lua_State * a_LuaState) { // function cBlockArea::GetSize() // Returns all three sizes of the area // Exported manually because there's no direct C++ equivalent, // plus tolua would generate extra input params for the outputs cLuaState L(a_LuaState); if (!L.CheckParamSelf("cBlockArea")) { return 0; } cBlockArea * self; if (!L.GetStackValues(1, self)) { return L.ApiParamError("Cannot read the 'self' parameter"); } if (self == nullptr) { return L.ApiParamError("Invalid 'self', must not be nil"); } L.Push(self->GetSizeX(), self->GetSizeY(), self->GetSizeZ()); return 3; } static int tolua_cBlockArea_LoadFromSchematicFile(lua_State * a_LuaState) { // function cBlockArea::LoadFromSchematicFile // Exported manually because function has been moved to SchematicFileSerializer.cpp cLuaState L(a_LuaState); if ( !L.CheckParamSelf("cBlockArea") || !L.CheckParamString(2) || !L.CheckParamEnd(3) ) { return 0; } cBlockArea * self; AString fileName; if (!L.GetStackValues(1, self, fileName)) { return L.ApiParamError("Cannot read the parameters"); } if (self == nullptr) { return L.ApiParamError("Invalid 'self', must not be nil"); } try { cSchematicFileSerializer::LoadFromSchematicFile(*self, fileName); L.Push(true); } catch (const std::exception & Oops) { LOGWARNING(Oops.what()); L.LogStackTrace(); L.Push(false); } return 1; } static int tolua_cBlockArea_LoadFromSchematicString(lua_State * a_LuaState) { // function cBlockArea::LoadFromSchematicString // Exported manually because function has been moved to SchematicFileSerializer.cpp cLuaState L(a_LuaState); if ( !L.CheckParamSelf("cBlockArea") || !L.CheckParamString(2) || !L.CheckParamEnd(3) ) { return 0; } cBlockArea * self; ContiguousByteBuffer data; if (!L.GetStackValues(1, self, data)) { return L.ApiParamError("Cannot read the parameters"); } if (self == nullptr) { return L.ApiParamError("Invalid 'self', must not be nil"); } try { cSchematicFileSerializer::LoadFromSchematicString(*self, data); L.Push(true); } catch (const std::exception & Oops) { LOGWARNING(Oops.what()); L.LogStackTrace(); L.Push(false); } return 1; } /** Bindings for the cBlockArea:Read() functions. Supports three overloads and one default parameter. */ static int tolua_cBlockArea_Read(lua_State * a_LuaState) { // Check the common params: cLuaState L(a_LuaState); if ( !L.CheckParamSelf("cBlockArea") || !L.CheckParamUserType(2, "cWorld") ) { return 0; } // Get the common params: cBlockArea * self = nullptr; cWorld * world = nullptr; if (!L.GetStackValues(1, self, world)) { return L.ApiParamError("Cannot read self or world"); } if (world == nullptr) { return L.ApiParamError("Invalid world instance. The world must be not nil"); } // Check and get the overloaded params: cCuboid bounds; int dataTypes = cBlockArea::baTypes | cBlockArea::baMetas | cBlockArea::baBlockEntities; auto dataTypesIdx = readCuboidOverloadParams(L, 3, bounds); L.GetStackValues(dataTypesIdx, dataTypes); if (!cBlockArea::IsValidDataTypeCombination(dataTypes)) { return L.ApiParamError(fmt::format(FMT_STRING("Invalid baDataTypes combination (0x{:02x})"), dataTypes)); } // Check the coords: if (!cChunkDef::IsValidHeight(bounds.p1) || !cChunkDef::IsValidHeight(bounds.p2)) { return L.ApiParamError(fmt::format(FMT_STRING("Coordinates {0} - {1} exceed world bounds"), bounds.p1, bounds.p2)); } bounds.Sort(); // Do the actual read: L.Push(self->Read(*world, bounds, dataTypes)); return 1; } /** Bindings for the cBlockArea:RelLine() functions. Supports two overloads and one default parameter. Also supports "bastard overloads" (Vector3i, x, y, z), but we don't advertise those. */ static int tolua_cBlockArea_RelLine(lua_State * a_LuaState) { // Check the common params: cLuaState L(a_LuaState); if (!L.CheckParamSelf("cBlockArea")) { return 0; } // Get the common params: cBlockArea * self = nullptr; if (!L.GetStackValues(1, self)) { return L.ApiParamError("Cannot read self"); } // Check and get the overloaded params: Vector3i p1; auto idx = readVector3iOverloadParams(L, 2, p1, "start coords"); Vector3i p2; idx = readVector3iOverloadParams(L, idx, p2, "end coords"); int dataTypes = cBlockArea::baTypes | cBlockArea::baMetas | cBlockArea::baBlockEntities; BLOCKTYPE blockType; NIBBLETYPE blockMeta, blockLight, blockSkyLight; L.GetStackValues(idx, dataTypes, blockType, blockMeta, blockLight, blockSkyLight); if (!cBlockArea::IsValidDataTypeCombination(dataTypes)) { return L.ApiParamError(fmt::format(FMT_STRING("Invalid baDataTypes combination (0x{:02x})"), dataTypes)); } if ((self->GetDataTypes() & dataTypes) != dataTypes) { return L.ApiParamError(fmt::format( FMT_STRING("Requested datatypes not present in the cBlockArea. Got only 0x{:02x}, requested 0x{:02x}"), self->GetDataTypes(), dataTypes )); } // Draw the line: self->RelLine(p1, p2, dataTypes, blockType, blockMeta, blockLight, blockSkyLight); return 0; } static int tolua_cBlockArea_SaveToSchematicFile(lua_State * a_LuaState) { // function cBlockArea::SaveToSchematicFile // Exported manually because function has been moved to SchematicFileSerializer.cpp cLuaState L(a_LuaState); if ( !L.CheckParamSelf("cBlockArea") || !L.CheckParamString(2) || !L.CheckParamEnd(3) ) { return 0; } cBlockArea * self; AString fileName; if (!L.GetStackValues(1, self, fileName)) { return L.ApiParamError("Cannot read the parameters"); } if (self == nullptr) { return L.ApiParamError("Invalid 'self', must not be nil"); } try { cSchematicFileSerializer::SaveToSchematicFile(*self, fileName); L.Push(true); } catch (const std::exception & Oops) { LOGWARNING(Oops.what()); L.LogStackTrace(); L.Push(false); } return 1; } static int tolua_cBlockArea_SaveToSchematicString(lua_State * a_LuaState) { // function cBlockArea::SaveToSchematicString // Exported manually because function has been moved to SchematicFileSerializer.cpp cLuaState L(a_LuaState); if ( !L.CheckParamSelf("cBlockArea") || !L.CheckParamEnd(2) ) { return 0; } cBlockArea * self; if (!L.GetStackValues(1, self)) { return L.ApiParamError("Cannot read the 'self' parameter"); } if (self == nullptr) { return L.ApiParamError("Invalid 'self', must not be nil"); } try { L.Push(cSchematicFileSerializer::SaveToSchematicString(*self).GetView()); return 1; } catch (const std::exception & Oops) { LOGWARNING(Oops.what()); L.LogStackTrace(); return 0; } } /** Bindings for the cBlockArea:Write() functions. Supports two overloads and one default parameter. */ static int tolua_cBlockArea_Write(lua_State * a_LuaState) { // Check the common params: cLuaState L(a_LuaState); if ( !L.CheckParamSelf("cBlockArea") || !L.CheckParamUserType(2, "cWorld") ) { return 0; } // Get the common params: cBlockArea * self = nullptr; cWorld * world = nullptr; if (!L.GetStackValues(1, self, world)) { return L.ApiParamError("Cannot read self or world"); } if (world == nullptr) { return L.ApiParamError("Invalid world instance. The world must be not nil"); } // Check and get the overloaded params: Vector3i coords; int dataTypes = 0; auto dataTypesIdx = readVector3iOverloadParams(L, 3, coords, "coords"); auto HasDataTypes = L.GetStackValues(dataTypesIdx, dataTypes); // Check the dataType parameter validity: if (HasDataTypes) { if (!cBlockArea::IsValidDataTypeCombination(dataTypes)) { return L.ApiParamError(fmt::format(FMT_STRING("Invalid datatype combination (0x{:02x})"), dataTypes)); } if ((self->GetDataTypes() & dataTypes) != dataTypes) { return L.ApiParamError(fmt::format( FMT_STRING("Requesting datatypes not present in the cBlockArea. Got only 0x{:02x}, requested 0x{:02x}"), self->GetDataTypes(), dataTypes )); } } // Check and adjust the coord params: // TODO: Should we report this as a failure? Because the result is definitely not what the plugin assumed // ... Or should we silently clone-crop-write the cBlockArea so that the API call does what would be naturally expected? // ... Or should we change the cBlockArea::Write() to allow out-of-range Y coords and do the cropping there? // ... NOTE: We already support auto-crop in cBlockArea::Merge() itself if (coords.y < 0) { LOGWARNING("cBlockArea:Write(): MinBlockY less than zero, adjusting to zero"); L.LogStackTrace(); coords.y = 0; } else if (coords.y > cChunkDef::Height - self->GetSizeY()) { LOGWARNING("cBlockArea:Write(): MinBlockY + m_SizeY more than chunk height, adjusting to chunk height"); L.LogStackTrace(); coords.y = cChunkDef::Height - self->GetSizeY(); } // Do the actual write: if (HasDataTypes) { L.Push(self->Write(*world, coords, dataTypes)); } else { L.Push(self->Write(*world, coords)); } return 1; } /** Templated bindings for the GetBlock___() functions. DataType is either BLOCKTYPE or NIBBLETYPE. DataTypeFlag is the ba___ constant used for the datatype being queried. Fn is the getter function. Also supports the Vector3i overloads (TODO: document these (?)). */ template < typename DataType, int DataTypeFlag, DataType (cBlockArea::*Fn)(int, int, int) const > static int GetBlock(lua_State * a_LuaState) { // Check the common params: cLuaState L(a_LuaState); if (!L.CheckParamSelf("cBlockArea")) { return 0; } // Read the common params: cBlockArea * self; if (!L.GetStackValues(1, self)) { return L.ApiParamError("Cannot read the 'self' param"); } // Check the datatype's presence: if ((self->GetDataTypes() & DataTypeFlag) == 0) { return L.ApiParamError(fmt::format(FMT_STRING("The area doesn't contain the datatype (0x{:02x})"), DataTypeFlag)); } // Read the overloaded params: Vector3i coords; readVector3iOverloadParams(L, 2, coords, "coords"); if (!self->IsValidCoords(coords)) { return L.ApiParamError(fmt::format(FMT_STRING("The coords ({0}) are out of range ({1} - {2})"), coords, self->GetOrigin(), self->GetOrigin() + self->GetSize() - Vector3i{1, 1, 1} )); } // Get the block info: L.Push((self->*Fn)(coords.x, coords.y, coords.z)); return 1; } /** Templated bindings for the GetRelBlock___() functions. DataType is either BLOCKTYPE or NIBBLETYPE. DataTypeFlag is the ba___ constant used for the datatype being queried. Fn is the getter function. Also supports the Vector3i overloads (TODO: document these (?)). */ template < typename DataType, int DataTypeFlag, DataType (cBlockArea::*Fn)(int, int, int) const > static int GetRelBlock(lua_State * a_LuaState) { // Check the common params: cLuaState L(a_LuaState); if (!L.CheckParamSelf("cBlockArea")) { return 0; } // Read the common params: cBlockArea * self; if (!L.GetStackValues(1, self)) { return L.ApiParamError("Cannot read the 'self' param"); } // Check the datatype's presence: if ((self->GetDataTypes() & DataTypeFlag) == 0) { return L.ApiParamError(fmt::format(FMT_STRING("The area doesn't contain the datatype (0x{:02x})"), DataTypeFlag)); } // Read the overloaded params: Vector3i coords; readVector3iOverloadParams(L, 2, coords, "coords"); if (!self->IsValidRelCoords(coords)) { return L.ApiParamError(fmt::format(FMT_STRING("The coords ({0}) are out of range ({1})"), coords, (self->GetSize() - Vector3i(1, 1, 1)) )); } // Get the block info: L.Push((self->*Fn)(coords.x, coords.y, coords.z)); return 1; } /** Templated bindings for the SetBlock___() functions. DataType is either BLOCKTYPE or NIBBLETYPE. DataTypeFlag is the ba___ constant used for the datatypebeing manipulated. Fn is the setter function. Also supports the Vector3i overloads (TODO: document these (?)). */ template < typename DataType, int DataTypeFlag, void (cBlockArea::*Fn)(int, int, int, DataType) > static int SetBlock(lua_State * a_LuaState) { // Check the common params: cLuaState L(a_LuaState); if (!L.CheckParamSelf("cBlockArea")) { return 0; } // Read the common params: cBlockArea * self; if (!L.GetStackValues(1, self)) { return L.ApiParamError("Cannot read the 'self' param"); } // Check the datatype's presence: if ((self->GetDataTypes() & DataTypeFlag) == 0) { return L.ApiParamError(fmt::format(FMT_STRING("The area doesn't contain the datatype (0x{:02x})"), DataTypeFlag)); } // Read the overloaded params: Vector3i coords; auto idx = readVector3iOverloadParams(L, 2, coords, "coords"); if (!self->IsValidCoords(coords)) { return L.ApiParamError(fmt::format(FMT_STRING("The coords ({0}) are out of range ({1} - {2})"), coords, self->GetOrigin(), self->GetOrigin() + self->GetSize() - Vector3i{1, 1, 1} )); } DataType data; L.GetStackValues(idx, data); // Set the block info: (self->*Fn)(coords.x, coords.y, coords.z, data); return 0; } /** Templated bindings for the SetRelBlock___() functions. DataType is either BLOCKTYPE or NIBBLETYPE. DataTypeFlag is the ba___ constant used for the datatypebeing manipulated. Fn is the setter function. Also supports the Vector3i overloads (TODO: document these (?)). */ template < typename DataType, int DataTypeFlag, void (cBlockArea::*Fn)(int, int, int, DataType) > static int SetRelBlock(lua_State * a_LuaState) { // Check the common params: cLuaState L(a_LuaState); if (!L.CheckParamSelf("cBlockArea")) { return 0; } // Read the common params: cBlockArea * self; if (!L.GetStackValues(1, self)) { return L.ApiParamError("Cannot read the 'self' param"); } // Check the datatype's presence: if ((self->GetDataTypes() & DataTypeFlag) == 0) { return L.ApiParamError(fmt::format(FMT_STRING("The area doesn't contain the datatype (0x{:02x})"), DataTypeFlag)); } // Read the overloaded params: Vector3i coords; auto idx = readVector3iOverloadParams(L, 2, coords, "coords"); if (!self->IsValidRelCoords(coords)) { return L.ApiParamError(fmt::format( FMT_STRING("The coords ({0}) are out of range ({1})"), coords, (self->GetSize() - Vector3i(1, 1, 1)) )); } DataType data; L.GetStackValues(idx, data); // Set the block info: (self->*Fn)(coords.x, coords.y, coords.z, data); return 0; } static int tolua_cBlockArea_SetBlockTypeMeta(lua_State * a_LuaState) { // Check the common params: cLuaState L(a_LuaState); if (!L.CheckParamSelf("cBlockArea")) { return 0; } // Read the common params: cBlockArea * self; if (!L.GetStackValues(1, self)) { return L.ApiParamError("Cannot read the 'self' param"); } // Check if block types and metas are present: if (!self->HasBlockTypes() || !self->HasBlockMetas()) { return L.ApiParamError("The area doesn't contain the datatypes baTypes and baMetas"); } // Read the overloaded params: Vector3i coords; auto idx = readVector3iOverloadParams(L, 2, coords, "coords"); if (!self->IsValidCoords(coords)) { return L.ApiParamError(fmt::format(FMT_STRING("The coords ({0}) are out of range ({1} - {2})"), coords, self->GetOrigin(), self->GetOrigin() + self->GetSize() - Vector3i{1, 1, 1} )); } BLOCKTYPE block; NIBBLETYPE meta; if (!L.GetStackValues(idx, block, meta)) { return L.ApiParamError("Bad number for block type or meta type"); } // Set block type and meta: self->SetBlockTypeMeta(coords.x, coords.y, coords.z, block, meta); return 0; } static int tolua_cBlockArea_SetRelBlockTypeMeta(lua_State * a_LuaState) { // Check the common params: cLuaState L(a_LuaState); if (!L.CheckParamSelf("cBlockArea")) { return 0; } // Read the common params: cBlockArea * self; if (!L.GetStackValues(1, self)) { return L.ApiParamError("Cannot read the 'self' param"); } // Check if block types and metas are present: if (!self->HasBlockTypes() || !self->HasBlockMetas()) { return L.ApiParamError(fmt::format(FMT_STRING("The area doesn't contain the baTypes or baMetas datatypes (0x{:02x})"), self->GetDataTypes())); } // Read the overloaded params: Vector3i coords; auto idx = readVector3iOverloadParams(L, 2, coords, "coords"); if (!self->IsValidRelCoords(coords)) { return L.ApiParamError(fmt::format(FMT_STRING("The coords ({0}) are out of range ({1})"), coords, (self->GetSize() - Vector3i(1, 1, 1)) )); } BLOCKTYPE block; NIBBLETYPE meta; if (!L.GetStackValues(idx, block, meta)) { return L.ApiParamError("Bad number for block type or meta type"); } // Set block type and meta: self->SetRelBlockTypeMeta(coords.x, coords.y, coords.z, block, meta); return 0; } void cManualBindings::BindBlockArea(lua_State * a_LuaState) { tolua_beginmodule(a_LuaState, nullptr); tolua_beginmodule(a_LuaState, "cBlockArea"); tolua_function(a_LuaState, "Create", tolua_cBlockArea_Create); tolua_function(a_LuaState, "DoWithBlockEntityAt", DoWithXYZ); tolua_function(a_LuaState, "DoWithBlockEntityRelAt", DoWithXYZ); tolua_function(a_LuaState, "FillRelCuboid", tolua_cBlockArea_FillRelCuboid); tolua_function(a_LuaState, "ForEachBlockEntity", ForEach< cBlockArea, cBlockEntity, &cBlockArea::ForEachBlockEntity>); tolua_function(a_LuaState, "GetBlockLight", GetBlock); tolua_function(a_LuaState, "GetBlockMeta", GetBlock); tolua_function(a_LuaState, "GetBlockSkyLight", GetBlock); tolua_function(a_LuaState, "GetBlockType", GetBlock); tolua_function(a_LuaState, "GetBlockTypeMeta", tolua_cBlockArea_GetBlockTypeMeta); tolua_function(a_LuaState, "GetCoordRange", tolua_cBlockArea_GetCoordRange); tolua_function(a_LuaState, "GetNonAirCropRelCoords", tolua_cBlockArea_GetNonAirCropRelCoords); tolua_function(a_LuaState, "GetOrigin", tolua_cBlockArea_GetOrigin); tolua_function(a_LuaState, "GetRelBlockLight", GetRelBlock); tolua_function(a_LuaState, "GetRelBlockMeta", GetRelBlock); tolua_function(a_LuaState, "GetRelBlockSkyLight", GetRelBlock); tolua_function(a_LuaState, "GetRelBlockType", GetRelBlock); tolua_function(a_LuaState, "GetRelBlockTypeMeta", tolua_cBlockArea_GetRelBlockTypeMeta); tolua_function(a_LuaState, "GetSize", tolua_cBlockArea_GetSize); tolua_function(a_LuaState, "LoadFromSchematicFile", tolua_cBlockArea_LoadFromSchematicFile); tolua_function(a_LuaState, "LoadFromSchematicString", tolua_cBlockArea_LoadFromSchematicString); tolua_function(a_LuaState, "Read", tolua_cBlockArea_Read); tolua_function(a_LuaState, "RelLine", tolua_cBlockArea_RelLine); tolua_function(a_LuaState, "SaveToSchematicFile", tolua_cBlockArea_SaveToSchematicFile); tolua_function(a_LuaState, "SaveToSchematicString", tolua_cBlockArea_SaveToSchematicString); tolua_function(a_LuaState, "SetBlockType", SetBlock); tolua_function(a_LuaState, "SetBlockMeta", SetBlock); tolua_function(a_LuaState, "SetBlockLight", SetBlock); tolua_function(a_LuaState, "SetBlockSkyLight", SetBlock); tolua_function(a_LuaState, "SetBlockTypeMeta", tolua_cBlockArea_SetBlockTypeMeta); tolua_function(a_LuaState, "SetRelBlockType", SetRelBlock); tolua_function(a_LuaState, "SetRelBlockMeta", SetRelBlock); tolua_function(a_LuaState, "SetRelBlockLight", SetRelBlock); tolua_function(a_LuaState, "SetRelBlockSkyLight", SetRelBlock); tolua_function(a_LuaState, "SetRelBlockTypeMeta", tolua_cBlockArea_SetRelBlockTypeMeta); tolua_function(a_LuaState, "Write", tolua_cBlockArea_Write); tolua_endmodule(a_LuaState); tolua_endmodule(a_LuaState); } ================================================ FILE: src/Bindings/ManualBindings_Network.cpp ================================================ // ManualBindings_Network.cpp // Implements the cNetwork-related API bindings for Lua // Also implements the cUrlClient bindings #include "Globals.h" #include "ManualBindings.h" #include "tolua++/include/tolua++.h" #include "LuaState.h" #include "LuaTCPLink.h" #include "LuaNameLookup.h" #include "LuaServerHandle.h" #include "LuaUDPEndpoint.h" #include "../HTTP/UrlClient.h" //////////////////////////////////////////////////////////////////////////////// // cNetwork API functions: /** Binds cNetwork::Connect */ static int tolua_cNetwork_Connect(lua_State * L) { // Function signature: // cNetwork:Connect(Host, Port, Callbacks) -> bool cLuaState S(L); if ( !S.CheckParamStaticSelf("cNetwork") || !S.CheckParamString(2) || !S.CheckParamNumber(3) || !S.CheckParamTable(4) || !S.CheckParamEnd(5) ) { return 0; } // Read the params: AString host; int port = 0; cLuaState::cTableRefPtr callbacks; if (!S.GetStackValues(2, host, port, callbacks)) { return S.ApiParamError("Cannot read parameters."); } // Check validity: if ((port < 0) || (port > 65535)) { return S.ApiParamError(fmt::format(FMT_STRING("Port number out of range (got {}, range 0 - 65535)"), port)); } ASSERT(callbacks != nullptr); // Invalid callbacks would have resulted in GetStackValues() returning false // Create the LuaTCPLink glue class: auto link = std::make_shared(std::move(callbacks)); // Try to connect: bool res = cNetwork::Connect(host, static_cast(port), link, link); S.Push(res); return 1; } /** Binds cNetwork::CreateUDPEndpoint */ static int tolua_cNetwork_CreateUDPEndpoint(lua_State * L) { // Function signature: // cNetwork:CreateUDPEndpoint(Port, Callbacks) -> cUDPEndpoint cLuaState S(L); if ( !S.CheckParamStaticSelf("cNetwork") || !S.CheckParamNumber(2) || !S.CheckParamTable(3) || !S.CheckParamEnd(4) ) { return 0; } // Read the params: int port; cLuaState::cTableRefPtr callbacks; if (!S.GetStackValues(2, port, callbacks)) { return S.ApiParamError("Cannot read parameters"); } // Check validity: if ((port < 0) || (port > 65535)) { return S.ApiParamError(fmt::format(FMT_STRING("Port number out of range (got {}, range 0 - 65535)"), port)); } ASSERT(callbacks != nullptr); // Invalid callbacks would have resulted in GetStackValues() returning false // Create the LuaUDPEndpoint glue class: auto endpoint = std::make_shared(std::move(callbacks)); endpoint->Open(static_cast(port), endpoint); // Register the endpoint to be garbage-collected by Lua: tolua_pushusertype(L, endpoint.get(), "cUDPEndpoint"); tolua_register_gc(L, lua_gettop(L)); // Return the endpoint object: S.Push(endpoint.get()); return 1; } /** Binds cNetwork::EnumLocalIPAddresses */ static int tolua_cNetwork_EnumLocalIPAddresses(lua_State * L) { // Function signature: // cNetwork:EnumLocalIPAddresses() -> {string, ...} cLuaState S(L); if ( !S.CheckParamStaticSelf("cNetwork") || !S.CheckParamEnd(2) ) { return 0; } // Push the enumerated addresses: S.Push(cNetwork::EnumLocalIPAddresses()); return 1; } /** Binds cNetwork::HostnameToIP */ static int tolua_cNetwork_HostnameToIP(lua_State * L) { // Function signature: // cNetwork:HostnameToIP(Host, Callbacks) -> bool cLuaState S(L); if ( !S.CheckParamStaticSelf("cNetwork") || !S.CheckParamString(2) || !S.CheckParamTable(3) || !S.CheckParamEnd(4) ) { return 0; } // Read the params: AString host; cLuaState::cTableRefPtr callbacks; if (!S.GetStackValues(2, host, callbacks)) { return S.ApiParamError("Cannot read parameters."); } ASSERT(callbacks != nullptr); // Invalid callbacks would have resulted in GetStackValues() returning false // Try to look up: bool res = cNetwork::HostnameToIP(host, std::make_shared(host, std::move(callbacks))); S.Push(res); return 1; } /** Binds cNetwork::IPToHostname */ static int tolua_cNetwork_IPToHostname(lua_State * L) { // Function signature: // cNetwork:IPToHostname(IP, Callbacks) -> bool cLuaState S(L); if ( !S.CheckParamStaticSelf("cNetwork") || !S.CheckParamString(2) || !S.CheckParamTable(3) || !S.CheckParamEnd(4) ) { return 0; } // Read the params: AString ip; cLuaState::cTableRefPtr callbacks; if (!S.GetStackValues(2, ip, callbacks)) { return S.ApiParamError("Cannot read parameters."); } ASSERT(callbacks != nullptr); // Invalid callbacks would have resulted in GetStackValues() returning false // Try to look up: bool res = cNetwork::IPToHostName(ip, std::make_shared(ip, std::move(callbacks))); S.Push(res); return 1; } /** Binds cNetwork::Listen */ static int tolua_cNetwork_Listen(lua_State * L) { // Function signature: // cNetwork:Listen(Port, Callbacks) -> cServerHandle cLuaState S(L); if ( !S.CheckParamStaticSelf("cNetwork") || !S.CheckParamNumber(2) || !S.CheckParamTable(3) || !S.CheckParamEnd(4) ) { return 0; } // Read the params: int port = 0; cLuaState::cTableRefPtr callbacks; if (!S.GetStackValues(2, port, callbacks)) { return S.ApiParamError("Cannot read parameters"); } // Check the validity: if ((port < 0) || (port > 65535)) { return S.ApiParamError(fmt::format(FMT_STRING("Port number out of range (got {}, range 0 - 65535)"), port)); } auto port16 = static_cast(port); // Create the LuaTCPLink glue class: auto srv = std::make_shared(port16, std::move(callbacks)); // Listen: srv->SetServerHandle(cNetwork::Listen(port16, srv), srv); // Register the server to be garbage-collected by Lua: tolua_pushusertype(L, srv.get(), "cServerHandle"); tolua_register_gc(L, lua_gettop(L)); // Return the server handle wrapper: S.Push(srv.get()); return 1; } //////////////////////////////////////////////////////////////////////////////// // cServerHandle bindings (routed through cLuaServerHandle): /** Called when Lua destroys the object instance. Close the server and let it deallocate on its own (it's in a SharedPtr). */ static int tolua_collect_cServerHandle(lua_State * L) { auto Srv = static_cast(tolua_tousertype(L, 1, nullptr)); ASSERT(Srv != nullptr); Srv->Release(); return 0; } /** Binds cLuaServerHandle::Close */ static int tolua_cServerHandle_Close(lua_State * L) { // Function signature: // ServerInstance:Close() cLuaState S(L); if ( !S.CheckParamSelf("cServerHandle") || !S.CheckParamEnd(2) ) { return 0; } // Get the server handle: auto Srv = *static_cast(lua_touserdata(L, 1)); ASSERT(Srv != nullptr); // Checked by CheckParamSelf() // Close it: Srv->Close(); return 0; } /** Binds cLuaServerHandle::IsListening */ static int tolua_cServerHandle_IsListening(lua_State * L) { // Function signature: // ServerInstance:IsListening() -> bool cLuaState S(L); if ( !S.CheckParamSelf("cServerHandle") || !S.CheckParamEnd(2) ) { return 0; } // Get the server handle: auto Srv = *static_cast(lua_touserdata(L, 1)); ASSERT(Srv != nullptr); // Checked by CheckParamSelf() // Query it: S.Push(Srv->IsListening()); return 1; } //////////////////////////////////////////////////////////////////////////////// // cTCPLink bindings (routed through cLuaTCPLink): /** Binds cLuaTCPLink::Close */ static int tolua_cTCPLink_Close(lua_State * L) { // Function signature: // LinkInstance:Close() cLuaState S(L); if ( !S.CheckParamSelf("cTCPLink") || !S.CheckParamEnd(2) ) { return 0; } // Get the link: auto Link = *static_cast(lua_touserdata(L, 1)); ASSERT(Link != nullptr); // Checked by CheckParamSelf() // Close the link: Link->Close(); return 0; } /** Binds cLuaTCPLink::GetLocalIP */ static int tolua_cTCPLink_GetLocalIP(lua_State * L) { // Function signature: // LinkInstance:GetLocalIP() -> string cLuaState S(L); if ( !S.CheckParamSelf("cTCPLink") || !S.CheckParamEnd(2) ) { return 0; } // Get the link: auto Link = *static_cast(lua_touserdata(L, 1)); ASSERT(Link != nullptr); // Checked by CheckParamSelf() // Get the IP: S.Push(Link->GetLocalIP()); return 1; } /** Binds cLuaTCPLink::GetLocalPort */ static int tolua_cTCPLink_GetLocalPort(lua_State * L) { // Function signature: // LinkInstance:GetLocalPort() -> number cLuaState S(L); if ( !S.CheckParamSelf("cTCPLink") || !S.CheckParamEnd(2) ) { return 0; } // Get the link: auto Link = *static_cast(lua_touserdata(L, 1)); ASSERT(Link != nullptr); // Checked by CheckParamSelf() // Get the Port: S.Push(Link->GetLocalPort()); return 1; } /** Binds cLuaTCPLink::GetRemoteIP */ static int tolua_cTCPLink_GetRemoteIP(lua_State * L) { // Function signature: // LinkInstance:GetRemoteIP() -> string cLuaState S(L); if ( !S.CheckParamSelf("cTCPLink") || !S.CheckParamEnd(2) ) { return 0; } // Get the link: auto Link = *static_cast(lua_touserdata(L, 1)); ASSERT(Link != nullptr); // Checked by CheckParamSelf() // Get the IP: S.Push(Link->GetRemoteIP()); return 1; } /** Binds cLuaTCPLink::GetRemotePort */ static int tolua_cTCPLink_GetRemotePort(lua_State * L) { // Function signature: // LinkInstance:GetRemotePort() -> number cLuaState S(L); if ( !S.CheckParamSelf("cTCPLink") || !S.CheckParamEnd(2) ) { return 0; } // Get the link: auto Link = *static_cast(lua_touserdata(L, 1)); ASSERT(Link != nullptr); // Checked by CheckParamSelf() // Get the Port: S.Push(Link->GetRemotePort()); return 1; } /** Binds cLuaTCPLink::Send */ static int tolua_cTCPLink_Send(lua_State * L) { // Function signature: // LinkInstance:Send(DataString) cLuaState S(L); if ( !S.CheckParamSelf("cTCPLink") || !S.CheckParamString(2) || !S.CheckParamEnd(3) ) { return 0; } // Get the link: auto Link = *static_cast(lua_touserdata(L, 1)); ASSERT(Link != nullptr); // Checked by CheckParamSelf() // Get the data to send: AString Data; S.GetStackValues(2, Data); // Send the data: Link->Send(Data); return 0; } /** Binds cLuaTCPLink::Shutdown */ static int tolua_cTCPLink_Shutdown(lua_State * L) { // Function signature: // LinkInstance:Shutdown() cLuaState S(L); if ( !S.CheckParamSelf("cTCPLink") || !S.CheckParamEnd(2) ) { return 0; } // Get the link: auto Link = *static_cast(lua_touserdata(L, 1)); ASSERT(Link != nullptr); // Checked by CheckParamSelf() // Shutdown the link: Link->Shutdown(); return 0; } /** Binds cLuaTCPLink::StartTLSClient */ static int tolua_cTCPLink_StartTLSClient(lua_State * L) { // Function signature: // LinkInstance:StartTLSClient(OwnCert, OwnPrivKey, OwnPrivKeyPassword, TrustedRootCAs) -> [true] or [nil, ErrMsg] // Get the link: cLuaState S(L); if (!S.CheckParamSelf("cTCPLink")) { return 0; } auto Link = *static_cast(lua_touserdata(L, 1)); ASSERT(Link != nullptr); // Checked by CheckParamSelf() // Read the (optional) params: AString OwnCert, OwnPrivKey, OwnPrivKeyPassword, TrustedRootCAs; S.GetStackValues(2, OwnCert, OwnPrivKey, OwnPrivKeyPassword, cLuaState::cOptionalParam(TrustedRootCAs)); // Start the TLS handshake: AString res = Link->StartTLSClient(OwnCert, OwnPrivKey, OwnPrivKeyPassword, TrustedRootCAs); if (!res.empty()) { S.Push(cLuaState::Nil, fmt::format( FMT_STRING("Cannot start TLS on link to {}:{}: {}"), Link->GetRemoteIP(), Link->GetRemotePort(), res )); return 2; } return 1; } /** Binds cLuaTCPLink::StartTLSServer */ static int tolua_cTCPLink_StartTLSServer(lua_State * L) { // Function signature: // LinkInstance:StartTLSServer(OwnCert, OwnPrivKey, OwnPrivKeyPassword, StartTLSData) -> [true] or [nil, ErrMsg] cLuaState S(L); if ( !S.CheckParamSelf("cTCPLink") || !S.CheckParamString(2, 4) || // Param 5 is optional, don't check !S.CheckParamEnd(6) ) { return 0; } // Get the link: auto Link = *static_cast(lua_touserdata(L, 1)); ASSERT(Link != nullptr); // Checked by CheckParamSelf() // Read the params: AString OwnCert, OwnPrivKey, OwnPrivKeyPassword, StartTLSData; S.GetStackValues(2, OwnCert, OwnPrivKey, OwnPrivKeyPassword, StartTLSData); // Start the TLS handshake: AString res = Link->StartTLSServer(OwnCert, OwnPrivKey, OwnPrivKeyPassword, StartTLSData); if (!res.empty()) { S.Push(cLuaState::Nil, fmt::format( FMT_STRING("Cannot start TLS on link to {}:{}: {}"), Link->GetRemoteIP(), Link->GetRemotePort(), res )); return 2; } S.Push(true); return 1; } //////////////////////////////////////////////////////////////////////////////// // cUDPEndpoint bindings (routed through cLuaUDPEndpoint): /** Called when Lua destroys the object instance. Close the endpoint and let it deallocate on its own (it's in a SharedPtr). */ static int tolua_collect_cUDPEndpoint(lua_State * L) { auto endpoint = static_cast(tolua_tousertype(L, 1, nullptr)); ASSERT(endpoint != nullptr); endpoint->Release(); return 0; } /** Binds cLuaUDPEndpoint::Close */ static int tolua_cUDPEndpoint_Close(lua_State * L) { // Function signature: // EndpointInstance:Close() cLuaState S(L); if ( !S.CheckParamSelf("cUDPEndpoint") || !S.CheckParamEnd(2) ) { return 0; } // Get the endpoint: auto endpoint = *static_cast(lua_touserdata(L, 1)); ASSERT(endpoint != nullptr); // Close it: endpoint->Close(); return 0; } /** Binds cLuaUDPEndpoint::EnableBroadcasts */ static int tolua_cUDPEndpoint_EnableBroadcasts(lua_State * L) { // Function signature: // EndpointInstance:EnableBroadcasts() cLuaState S(L); if ( !S.CheckParamSelf("cUDPEndpoint") || !S.CheckParamEnd(2) ) { return 0; } // Get the endpoint: auto endpoint = *static_cast(lua_touserdata(L, 1)); ASSERT(endpoint != nullptr); // Enable the broadcasts: endpoint->EnableBroadcasts(); return 0; } /** Binds cLuaUDPEndpoint::GetPort */ static int tolua_cUDPEndpoint_GetPort(lua_State * L) { // Function signature: // Endpoint:GetPort() -> number cLuaState S(L); if ( !S.CheckParamSelf("cUDPEndpoint") || !S.CheckParamEnd(2) ) { return 0; } // Get the endpoint: auto endpoint = *static_cast(lua_touserdata(L, 1)); ASSERT(endpoint != nullptr); // Get the Port: S.Push(endpoint->GetPort()); return 1; } /** Binds cLuaUDPEndpoint::IsOpen */ static int tolua_cUDPEndpoint_IsOpen(lua_State * L) { // Function signature: // Endpoint:IsOpen() -> bool cLuaState S(L); if ( !S.CheckParamSelf("cUDPEndpoint") || !S.CheckParamEnd(2) ) { return 0; } // Get the endpoint: auto endpoint = *static_cast(lua_touserdata(L, 1)); ASSERT(endpoint != nullptr); // Close it: S.Push(endpoint->IsOpen()); return 1; } /** Binds cLuaUDPEndpoint::Send */ static int tolua_cUDPEndpoint_Send(lua_State * L) { // Function signature: // Endpoint:Send(DataString) cLuaState S(L); if ( !S.CheckParamSelf("cUDPEndpoint") || !S.CheckParamString(2, 3) || !S.CheckParamNumber(4) || !S.CheckParamEnd(5) ) { return 0; } // Get the link: auto endpoint = *static_cast(lua_touserdata(L, 1)); ASSERT(endpoint != nullptr); // Get the data to send: AString data, remotePeer; int remotePort = 0; S.GetStackValues(2, data, remotePeer, remotePort); // Check the port: if ((remotePort < 0) || (remotePort > USHRT_MAX)) { return S.ApiParamError(fmt::format(FMT_STRING("Port number out of range (got {}, range 0 - 65535)"), remotePort)); } // Send the data: S.Push(endpoint->Send(data, remotePeer, static_cast(remotePort))); return 1; } /** Used when the cUrlClient Lua request wants all the callbacks. Maps each callback onto a Lua function callback in the callback table. */ class cFullUrlClientCallbacks: public cUrlClient::cCallbacks { public: /** Creates a new instance bound to the specified table of callbacks. */ cFullUrlClientCallbacks(cLuaState::cTableRefPtr && a_Callbacks): m_Callbacks(std::move(a_Callbacks)) { } // cUrlClient::cCallbacks overrides: virtual void OnConnected(cTCPLink & a_Link) override { // TODO: Cannot push a cTCPLink to Lua, need to translate via cLuaTCPLink m_Callbacks->CallTableFnWithSelf("OnConnected", cLuaState::Nil, a_Link.GetRemoteIP(), a_Link.GetRemotePort()); } virtual bool OnCertificateReceived() override { // TODO: The received cert needs proper type specification from the underlying cUrlClient framework and in the Lua engine as well bool res = true; m_Callbacks->CallTableFnWithSelf("OnCertificateReceived", cLuaState::Return, res); return res; } virtual void OnTlsHandshakeCompleted() override { m_Callbacks->CallTableFnWithSelf("OnTlsHandshakeCompleted"); } virtual void OnRequestSent() override { m_Callbacks->CallTableFnWithSelf("OnRequestSent"); } virtual void OnStatusLine(const AString & a_HttpVersion, int a_StatusCode, const AString & a_Rest) override { m_Callbacks->CallTableFnWithSelf("OnStatusLine", a_HttpVersion, a_StatusCode, a_Rest); } virtual void OnHeader(const AString & a_Key, const AString & a_Value) override { m_Callbacks->CallTableFnWithSelf("OnHeader", a_Key, a_Value); m_Headers[a_Key] = a_Value; } virtual void OnHeadersFinished() override { m_Callbacks->CallTableFnWithSelf("OnHeadersFinished", m_Headers); } virtual void OnBodyData(const void * a_Data, size_t a_Size) override { m_Callbacks->CallTableFnWithSelf("OnBodyData", AString(static_cast(a_Data), a_Size)); } virtual void OnBodyFinished() override { m_Callbacks->CallTableFnWithSelf("OnBodyFinished"); } virtual void OnError(const AString & a_ErrorMsg) override { m_Callbacks->CallTableFnWithSelf("OnError", a_ErrorMsg); } virtual void OnRedirecting(const AString & a_NewLocation) override { m_Callbacks->CallTableFnWithSelf("OnRedirecting", a_NewLocation); } protected: /** The Lua table containing the callbacks. */ cLuaState::cTableRefPtr m_Callbacks; /** Accumulator for all the headers to be reported in the OnHeadersFinished() callback. */ AStringMap m_Headers; }; /** Used when the cUrlClient Lua request has just a single callback. The callback is used to report the entire body at once, together with the HTTP headers, or to report an error: callback("BodyContents", {headers}) callback(nil, "ErrorMessage") Accumulates the body contents into a single string until the body is finished. Accumulates all HTTP headers into an AStringMap. */ class cSimpleUrlClientCallbacks: public cUrlClient::cCallbacks { public: /** Creates a new instance that uses the specified callback to report when request finishes. */ cSimpleUrlClientCallbacks(cLuaState::cCallbackPtr && a_Callback): m_Callback(std::move(a_Callback)) { } virtual void OnHeader(const AString & a_Key, const AString & a_Value) override { m_Headers[a_Key] = a_Value; } virtual void OnBodyData(const void * a_Data, size_t a_Size) override { m_ResponseBody.append(static_cast(a_Data), a_Size); } virtual void OnBodyFinished() override { m_Callback->Call(m_ResponseBody, m_Headers); } virtual void OnError(const AString & a_ErrorMsg) override { m_Callback->Call(cLuaState::Nil, a_ErrorMsg); } protected: /** The callback to call when the request finishes. */ cLuaState::cCallbackPtr m_Callback; /** The accumulator for the partial body data, so that OnBodyFinished() can send the entire thing at once. */ AString m_ResponseBody; /** Accumulator for all the headers to be reported in the combined callback. */ AStringMap m_Headers; }; /** Common code shared among the cUrlClient request methods. a_Method is the method name to be used in the request. a_UrlStackIdx is the position on the Lua stack of the Url parameter. */ static int tolua_cUrlClient_Request_Common(lua_State * a_LuaState, const AString & a_Method, int a_UrlStackIdx) { // Check params: cLuaState L(a_LuaState); if (!L.CheckParamString(a_UrlStackIdx)) { return 0; } // Read params: AString url, requestBody; AStringMap headers, options; cLuaState::cTableRefPtr callbacks; cLuaState::cCallbackPtr onCompleteBodyCallback; if (!L.GetStackValues(a_UrlStackIdx, url)) { return L.ApiParamError(fmt::format(FMT_STRING("Cannot read URL parameter at idx {}"), a_UrlStackIdx)); } cUrlClient::cCallbacksPtr urlClientCallbacks; if (lua_istable(L, a_UrlStackIdx + 1)) { if (!L.GetStackValue(a_UrlStackIdx + 1, callbacks)) { return L.ApiParamError(fmt::format(FMT_STRING("Cannot read the CallbacksTable parameter at idx {}"), a_UrlStackIdx + 1)); } urlClientCallbacks = std::make_unique(std::move(callbacks)); } else if (lua_isfunction(L, a_UrlStackIdx + 1)) { if (!L.GetStackValue(a_UrlStackIdx + 1, onCompleteBodyCallback)) { return L.ApiParamError(fmt::format(FMT_STRING("Cannot read the CallbackFn parameter at idx {}"), a_UrlStackIdx + 1)); } urlClientCallbacks = std::make_unique(std::move(onCompleteBodyCallback)); } else { L.ApiParamError(fmt::format( FMT_STRING("Invalid Callbacks parameter at {}, expected a table or function, got {}"), a_UrlStackIdx + 1, L.GetTypeText(a_UrlStackIdx + 1) )); } if (!L.GetStackValues(a_UrlStackIdx + 2, cLuaState::cOptionalParam(headers), cLuaState::cOptionalParam(requestBody), cLuaState::cOptionalParam(options))) { L.ApiParamError(fmt::format( FMT_STRING("Cannot read the Header, Body or Options parameter at idx {}, {}, {}."), a_UrlStackIdx + 2, a_UrlStackIdx + 3, a_UrlStackIdx + 4 )); } // Make the request: auto res = cUrlClient::Request(a_Method, url, std::move(urlClientCallbacks), std::move(headers), std::move(requestBody), std::move(options)); if (!res.first) { L.Push(false); L.Push(res.second); return 2; } L.Push(true); return 1; } /** Implements cUrlClient:Get() using cUrlClient::Request(). */ static int tolua_cUrlClient_Delete(lua_State * a_LuaState) { /* Function signatures: cUrlClient:Delete(URL, {CallbacksFnTable}, [{HeadersMapTable}], [RequestBody], [{OptionsMapTable}]) -> true / false + string cUrlClient:Delete(URL, OnCompleteBodyCallback, [{HeadersMapTable}], [RequestBody], [{OptionsMapTable}]) -> true / false + string */ return tolua_cUrlClient_Request_Common(a_LuaState, "DELETE", 2); } /** Implements cUrlClient:Get() using cUrlClient::Request(). */ static int tolua_cUrlClient_Get(lua_State * a_LuaState) { /* Function signatures: cUrlClient:Get(URL, {CallbacksFnTable}, [{HeadersMapTable}], [RequestBody], [{OptionsMapTable}]) -> true / false + string cUrlClient:Get(URL, OnCompleteBodyCallback, [{HeadersMapTable}], [RequestBody], [{OptionsMapTable}]) -> true / false + string */ return tolua_cUrlClient_Request_Common(a_LuaState, "GET", 2); } /** Implements cUrlClient:Post() using cUrlClient::Request(). */ static int tolua_cUrlClient_Post(lua_State * a_LuaState) { /* Function signatures: cUrlClient:Post(URL, {CallbacksFnTable}, [{HeadersMapTable}], [RequestBody], [{OptionsMapTable}]) -> true / false + string cUrlClient:Post(URL, OnCompleteBodyCallback, [{HeadersMapTable}], [RequestBody], [{OptionsMapTable}]) -> true / false + string */ return tolua_cUrlClient_Request_Common(a_LuaState, "POST", 2); } /** Implements cUrlClient:Put() using cUrlClient::Request(). */ static int tolua_cUrlClient_Put(lua_State * a_LuaState) { /* Function signatures: cUrlClient:Put(URL, {CallbacksFnTable}, [{HeadersMapTable}], [RequestBody], [{OptionsMapTable}]) -> true / false + string cUrlClient:Put(URL, OnCompleteBodyCallback, [{HeadersMapTable}], [RequestBody], [{OptionsMapTable}]) -> true / false + string */ return tolua_cUrlClient_Request_Common(a_LuaState, "PUT", 2); } /** Binds cUrlClient::Request(). */ static int tolua_cUrlClient_Request(lua_State * a_LuaState) { /* Function signatures: cUrlClient:Request(Method, URL, {CallbacksFnTable}, [{HeadersMapTable}], [RequestBody], [{OptionsMapTable}]) -> true / false + string cUrlClient:Request(Method, URL, OnCompleteBodyCallback, [{HeadersMapTable}], [RequestBody], [{OptionsMapTable}]) -> true / false + string */ // Check that the Method param is a string: cLuaState L(a_LuaState); if ( !L.CheckParamStaticSelf("cUrlClient") || !L.CheckParamString(2)) { return 0; } // Redirect the rest to the common code: AString method; if (!L.GetStackValue(2, method)) { L.ApiParamError("Cannot read the Method parameter"); } return tolua_cUrlClient_Request_Common(a_LuaState, method, 3); } //////////////////////////////////////////////////////////////////////////////// // Register the bindings: void cManualBindings::BindNetwork(lua_State * tolua_S) { // Create the cNetwork API classes: tolua_usertype(tolua_S, "cNetwork"); tolua_usertype(tolua_S, "cServerHandle"); tolua_usertype(tolua_S, "cTCPLink"); tolua_usertype(tolua_S, "cUDPEndpoint"); tolua_usertype(tolua_S, "cUrlClient"); tolua_cclass(tolua_S, "cNetwork", "cNetwork", "", nullptr); tolua_cclass(tolua_S, "cServerHandle", "cServerHandle", "", tolua_collect_cServerHandle); tolua_cclass(tolua_S, "cTCPLink", "cTCPLink", "", nullptr); tolua_cclass(tolua_S, "cUDPEndpoint", "cUDPEndpoint", "", tolua_collect_cUDPEndpoint); tolua_cclass(tolua_S, "cUrlClient", "cUrlClient", "", nullptr); // Fill in the functions (alpha-sorted): tolua_beginmodule(tolua_S, "cNetwork"); tolua_function(tolua_S, "Connect", tolua_cNetwork_Connect); tolua_function(tolua_S, "CreateUDPEndpoint", tolua_cNetwork_CreateUDPEndpoint); tolua_function(tolua_S, "EnumLocalIPAddresses", tolua_cNetwork_EnumLocalIPAddresses); tolua_function(tolua_S, "HostnameToIP", tolua_cNetwork_HostnameToIP); tolua_function(tolua_S, "IPToHostname", tolua_cNetwork_IPToHostname); tolua_function(tolua_S, "Listen", tolua_cNetwork_Listen); tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "cServerHandle"); tolua_function(tolua_S, "Close", tolua_cServerHandle_Close); tolua_function(tolua_S, "IsListening", tolua_cServerHandle_IsListening); tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "cTCPLink"); tolua_function(tolua_S, "Close", tolua_cTCPLink_Close); tolua_function(tolua_S, "GetLocalIP", tolua_cTCPLink_GetLocalIP); tolua_function(tolua_S, "GetLocalPort", tolua_cTCPLink_GetLocalPort); tolua_function(tolua_S, "GetRemoteIP", tolua_cTCPLink_GetRemoteIP); tolua_function(tolua_S, "GetRemotePort", tolua_cTCPLink_GetRemotePort); tolua_function(tolua_S, "Send", tolua_cTCPLink_Send); tolua_function(tolua_S, "Shutdown", tolua_cTCPLink_Shutdown); tolua_function(tolua_S, "StartTLSClient", tolua_cTCPLink_StartTLSClient); tolua_function(tolua_S, "StartTLSServer", tolua_cTCPLink_StartTLSServer); tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "cUDPEndpoint"); tolua_function(tolua_S, "Close", tolua_cUDPEndpoint_Close); tolua_function(tolua_S, "EnableBroadcasts", tolua_cUDPEndpoint_EnableBroadcasts); tolua_function(tolua_S, "GetPort", tolua_cUDPEndpoint_GetPort); tolua_function(tolua_S, "IsOpen", tolua_cUDPEndpoint_IsOpen); tolua_function(tolua_S, "Send", tolua_cUDPEndpoint_Send); tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "cUrlClient"); tolua_function(tolua_S, "Delete", tolua_cUrlClient_Delete); tolua_function(tolua_S, "Get", tolua_cUrlClient_Get); tolua_function(tolua_S, "Post", tolua_cUrlClient_Post); tolua_function(tolua_S, "Put", tolua_cUrlClient_Put); tolua_function(tolua_S, "Request", tolua_cUrlClient_Request); tolua_endmodule(tolua_S); } ================================================ FILE: src/Bindings/ManualBindings_RankManager.cpp ================================================ // ManualBindings_RankManager.cpp // Implements the cRankManager Lua bindings #include "Globals.h" #include "ManualBindings.h" #include "tolua++/include/tolua++.h" #include "LuaState.h" #include "../Root.h" #include "../UUID.h" /** Binds cRankManager::AddGroup */ static int tolua_cRankManager_AddGroup(lua_State * L) { // Function signature: // cRankManager:AddGroup(GroupName) cLuaState S(L); if ( !S.CheckParamUserTable(1, "cRankManager") || !S.CheckParamString(2) || !S.CheckParamEnd(3) ) { return 0; } // Read the params: AString GroupName; S.GetStackValue(2, GroupName); // Add the group: cRoot::Get()->GetRankManager()->AddGroup(GroupName); return 0; } /** Binds cRankManager::AddGroupToRank */ static int tolua_cRankManager_AddGroupToRank(lua_State * L) { // Function signature: // cRankManager:AddGroupToRank(GroupName, RankName) -> bool cLuaState S(L); if ( !S.CheckParamUserTable(1, "cRankManager") || !S.CheckParamString(2, 3) || !S.CheckParamEnd(4) ) { return 0; } // Read the params: AString GroupName, RankName; S.GetStackValues(2, GroupName, RankName); // Add the group to the rank: S.Push(cRoot::Get()->GetRankManager()->AddGroupToRank(GroupName, RankName)); return 1; } /** Binds cRankManager::AddPermissionToGroup */ static int tolua_cRankManager_AddPermissionToGroup(lua_State * L) { // Function signature: // cRankManager:AddPermissionToGroup(Permission, GroupName) -> bool cLuaState S(L); if ( !S.CheckParamUserTable(1, "cRankManager") || !S.CheckParamString(2, 3) || !S.CheckParamEnd(4) ) { return 0; } // Read the params: AString GroupName, Permission; S.GetStackValues(2, Permission, GroupName); // Add the group to the rank: S.Push(cRoot::Get()->GetRankManager()->AddPermissionToGroup(Permission, GroupName)); return 1; } /** Binds cRankManager::AddRank */ static int tolua_cRankManager_AddRank(lua_State * L) { // Function signature: // cRankManager:AddRank(RankName) cLuaState S(L); if ( !S.CheckParamUserTable(1, "cRankManager") || !S.CheckParamString(2, 5) || !S.CheckParamEnd(6) ) { return 0; } // Read the params: AString RankName, MsgPrefix, MsgSuffix, MsgNameColorCode; S.GetStackValues(2, RankName, MsgPrefix, MsgSuffix, MsgNameColorCode); // Add the rank: cRoot::Get()->GetRankManager()->AddRank(RankName, MsgPrefix, MsgSuffix, MsgNameColorCode); return 0; } /** Binds cRankManager::AddRestrictionToGroup */ static int tolua_cRankManager_AddRestrictionToGroup(lua_State * L) { // Function signature: // cRankManager:AddRestrictionToGroup(Restriction, GroupName) -> bool cLuaState S(L); if ( !S.CheckParamUserTable(1, "cRankManager") || !S.CheckParamString(2, 3) || !S.CheckParamEnd(4) ) { return 0; } // Read the params: AString GroupName, Restriction; S.GetStackValues(2, Restriction, GroupName); // Add the group to the rank: S.Push(cRoot::Get()->GetRankManager()->AddRestrictionToGroup(Restriction, GroupName)); return 1; } /** Binds cRankManager::ClearPlayerRanks */ static int tolua_cRankManager_ClearPlayerRanks(lua_State * L) { cLuaState S(L); if ( !S.CheckParamUserTable(1, "cRankManager") || !S.CheckParamEnd(2) ) { return 0; } // Remove all players: cRoot::Get()->GetRankManager()->ClearPlayerRanks(); return 1; } /** Binds cRankManager::GetAllGroups */ static int tolua_cRankManager_GetAllGroups(lua_State * L) { // Function signature: // cRankManager:GetAllGroups() -> arraytable of GroupNames cLuaState S(L); if ( !S.CheckParamUserTable(1, "cRankManager") || !S.CheckParamEnd(2) ) { return 0; } // Get the groups: AStringVector Groups = cRoot::Get()->GetRankManager()->GetAllGroups(); // Push the results: S.Push(Groups); return 1; } /** Binds cRankManager::GetAllPermissions */ static int tolua_cRankManager_GetAllPermissions(lua_State * L) { // Function signature: // cRankManager:GetAllPermissions() -> arraytable of Permissions cLuaState S(L); if ( !S.CheckParamUserTable(1, "cRankManager") || !S.CheckParamEnd(2) ) { return 0; } // Get the permissions: AStringVector Permissions = cRoot::Get()->GetRankManager()->GetAllPermissions(); // Push the results: S.Push(Permissions); return 1; } /** Binds cRankManager::GetAllPermissionsRestrictions */ static int tolua_cRankManager_GetAllPermissionsRestrictions(lua_State * L) { // Function signature: // cRankManager:GetAllPermissionsRestrictions() -> arraytable of Permissions and Restrictions together cLuaState S(L); if ( !S.CheckParamUserTable(1, "cRankManager") || !S.CheckParamEnd(2) ) { return 0; } // Push the results: S.Push(cRoot::Get()->GetRankManager()->GetAllPermissionsRestrictions()); return 1; } /** Binds cRankManager::GetAllPlayerUUIDs */ static int tolua_cRankManager_GetAllPlayerUUIDs(lua_State * L) { // Function signature: // cRankManager:GetAllPlayerUUIDs() -> arraytable of Player UUID's cLuaState S(L); if ( !S.CheckParamStaticSelf("cRankManager") || !S.CheckParamEnd(2) ) { return 0; } // Get the player uuid's: std::vector Players = cRoot::Get()->GetRankManager()->GetAllPlayerUUIDs(); // Convert to string UUIDs std::vector StrUUIDs; StrUUIDs.reserve(Players.size()); for (const auto & UUID : Players) { StrUUIDs.push_back(UUID.ToShortString()); } // Push the results: S.Push(StrUUIDs); return 1; } /** Binds cRankManager::GetAllRanks */ static int tolua_cRankManager_GetAllRanks(lua_State * L) { // Function signature: // cRankManager:GetAllRanks() -> arraytable of RankNames cLuaState S(L); if ( !S.CheckParamUserTable(1, "cRankManager") || !S.CheckParamEnd(2) ) { return 0; } // Push the results: S.Push(cRoot::Get()->GetRankManager()->GetAllRanks()); return 1; } /** Binds cRankManager::GetAllRestrictions */ static int tolua_cRankManager_GetAllRestrictions(lua_State * L) { // Function signature: // cRankManager:GetAllRestrictions() -> arraytable of Restrictions cLuaState S(L); if ( !S.CheckParamUserTable(1, "cRankManager") || !S.CheckParamEnd(2) ) { return 0; } // Push the results: S.Push(cRoot::Get()->GetRankManager()->GetAllRestrictions()); return 1; } /** Binds cRankManager::GetDefaultRank */ static int tolua_cRankManager_GetDefaultRank(lua_State * L) { // Function signature: // cRankManager:GetDefaultRank() -> string cLuaState S(L); if ( !S.CheckParamUserTable(1, "cRankManager") || !S.CheckParamEnd(2) ) { return 0; } // Return the rank name: S.Push(cRoot::Get()->GetRankManager()->GetDefaultRank()); return 1; } /** Binds cRankManager::GetGroupPermissions */ static int tolua_cRankManager_GetGroupPermissions(lua_State * L) { // Function signature: // cRankManager:GetGroupPermissions(GroupName) -> arraytable of permissions cLuaState S(L); if ( !S.CheckParamUserTable(1, "cRankManager") || !S.CheckParamString(2) || !S.CheckParamEnd(3) ) { return 0; } // Get the params: AString GroupName; S.GetStackValue(2, GroupName); // Get the permissions: AStringVector Permissions = cRoot::Get()->GetRankManager()->GetGroupPermissions(GroupName); // Push the results: S.Push(Permissions); return 1; } /** Binds cRankManager::GetGroupRestrictions */ static int tolua_cRankManager_GetGroupRestrictions(lua_State * L) { // Function signature: // cRankManager:GetGroupRestrictions(GroupName) -> arraytable of restrictions cLuaState S(L); if ( !S.CheckParamUserTable(1, "cRankManager") || !S.CheckParamString(2) || !S.CheckParamEnd(3) ) { return 0; } // Get the params: AString GroupName; S.GetStackValue(2, GroupName); // Get the restrictions: AStringVector Restrictions = cRoot::Get()->GetRankManager()->GetGroupRestrictions(GroupName); // Push the results: S.Push(Restrictions); return 1; } /** Binds cRankManager::GetPlayerGroups */ static int tolua_cRankManager_GetPlayerGroups(lua_State * L) { // Function signature: // cRankManager:GetPlayerGroups(PlayerUUID) -> arraytable of GroupNames cLuaState S(L); if ( !S.CheckParamStaticSelf("cRankManager") || !S.CheckParamUUID(2) || !S.CheckParamEnd(3) ) { return 0; } // Get the params: cUUID PlayerUUID; S.GetStackValue(2, PlayerUUID); // Get the groups: AStringVector Groups = cRoot::Get()->GetRankManager()->GetPlayerGroups(PlayerUUID); // Push the results: S.Push(Groups); return 1; } /** Binds cRankManager::GetPlayerMsgVisuals */ static int tolua_cRankManager_GetPlayerMsgVisuals(lua_State * L) { // Function signature: // cRankManager:GetPlayerMsgVisuals(PlayerUUID) -> string, string, string cLuaState S(L); if ( !S.CheckParamStaticSelf("cRankManager") || !S.CheckParamUUID(2) || !S.CheckParamEnd(3) ) { return 0; } // Get the params: cUUID PlayerUUID; S.GetStackValue(2, PlayerUUID); // Get the permissions: AString MsgPrefix, MsgSuffix, MsgNameColorCode; if (!cRoot::Get()->GetRankManager()->GetPlayerMsgVisuals(PlayerUUID, MsgPrefix, MsgSuffix, MsgNameColorCode)) { return 0; } // Push the results: S.Push(MsgPrefix, MsgSuffix, MsgNameColorCode); return 3; } /** Binds cRankManager::GetPlayerPermissions */ static int tolua_cRankManager_GetPlayerPermissions(lua_State * L) { // Function signature: // cRankManager:GetPlayerPermissions(PlayerUUID) -> arraytable of permissions cLuaState S(L); if ( !S.CheckParamStaticSelf("cRankManager") || !S.CheckParamUUID(2) || !S.CheckParamEnd(3) ) { return 0; } // Get the params: cUUID PlayerUUID; S.GetStackValue(2, PlayerUUID); // Get the permissions: AStringVector Permissions = cRoot::Get()->GetRankManager()->GetPlayerPermissions(PlayerUUID); // Push the results: S.Push(Permissions); return 1; } /** Binds cRankManager::GetPlayerRestrictions */ static int tolua_cRankManager_GetPlayerRestrictions(lua_State * L) { // Function signature: // cRankManager:GetPlayerRestrictions(PlayerUUID) -> arraytable of restrictions cLuaState S(L); if ( !S.CheckParamStaticSelf("cRankManager") || !S.CheckParamUUID(2) || !S.CheckParamEnd(3) ) { return 0; } // Get the params: cUUID PlayerUUID; S.GetStackValue(2, PlayerUUID); // Get the permissions: AStringVector Restrictions = cRoot::Get()->GetRankManager()->GetPlayerRestrictions(PlayerUUID); // Push the results: S.Push(Restrictions); return 1; } /** Binds cRankManager::GetPlayerRankName */ static int tolua_cRankManager_GetPlayerRankName(lua_State * L) { // Function signature: // cRankManager:GetPlayerRankName(PlayerUUID) -> string cLuaState S(L); if ( !S.CheckParamStaticSelf("cRankManager") || !S.CheckParamUUID(2) || !S.CheckParamEnd(3) ) { return 0; } // Get the params: cUUID PlayerUUID; S.GetStackValue(2, PlayerUUID); // Get the rank name: AString RankName = cRoot::Get()->GetRankManager()->GetPlayerRankName(PlayerUUID); // Push the result: S.Push(RankName); return 1; } /** Binds cRankManager::GetPlayerName */ static int tolua_cRankManager_GetPlayerName(lua_State * L) { // Function signature: // cRankManager:GetPlayerName(PlayerUUID) -> string cLuaState S(L); if ( !S.CheckParamStaticSelf("cRankManager") || !S.CheckParamUUID(2) || !S.CheckParamEnd(3) ) { return 0; } // Get the params: cUUID PlayerUUID; S.GetStackValue(2, PlayerUUID); // Get the player name: AString PlayerName = cRoot::Get()->GetRankManager()->GetPlayerName(PlayerUUID); // Push the result: S.Push(PlayerName); return 1; } /** Binds cRankManager::GetRankGroups */ static int tolua_cRankManager_GetRankGroups(lua_State * L) { // Function signature: // cRankManager:GetRankGroups(RankName) -> arraytable of groupnames cLuaState S(L); if ( !S.CheckParamUserTable(1, "cRankManager") || !S.CheckParamString(2) || !S.CheckParamEnd(3) ) { return 0; } // Get the params: AString RankName; S.GetStackValue(2, RankName); // Get the groups: AStringVector Groups = cRoot::Get()->GetRankManager()->GetRankGroups(RankName); // Push the results: S.Push(Groups); return 1; } /** Binds cRankManager::GetRankPermissions */ static int tolua_cRankManager_GetRankPermissions(lua_State * L) { // Function signature: // cRankManager:GetRankPermissions(RankName) -> arraytable of permissions cLuaState S(L); if ( !S.CheckParamUserTable(1, "cRankManager") || !S.CheckParamString(2) || !S.CheckParamEnd(3) ) { return 0; } // Get the params: AString RankName; S.GetStackValue(2, RankName); // Get the permissions: AStringVector Permissions = cRoot::Get()->GetRankManager()->GetRankPermissions(RankName); // Push the results: S.Push(Permissions); return 1; } /** Binds cRankManager::GetRankRestrictions */ static int tolua_cRankManager_GetRankRestrictions(lua_State * L) { // Function signature: // cRankManager:GetRankRestrictions(RankName) -> arraytable of restrictions cLuaState S(L); if ( !S.CheckParamUserTable(1, "cRankManager") || !S.CheckParamString(2) || !S.CheckParamEnd(3) ) { return 0; } // Get the params: AString RankName; S.GetStackValue(2, RankName); // Get the permissions: AStringVector Restrictions = cRoot::Get()->GetRankManager()->GetRankRestrictions(RankName); // Push the results: S.Push(Restrictions); return 1; } /** Binds cRankManager::GetRankVisuals */ static int tolua_cRankManager_GetRankVisuals(lua_State * L) { // Function signature: // cRankManager:GetRankVisuals(RankName) -> MsgPrefix, MsgSuffix, MsgNameColorCode cLuaState S(L); if ( !S.CheckParamUserTable(1, "cRankManager") || !S.CheckParamString(2) || !S.CheckParamEnd(3) ) { return 0; } // Get the params: AString RankName; S.GetStackValue(2, RankName); // Get the visuals: AString MsgPrefix, MsgSuffix, MsgNameColorCode; if (!cRoot::Get()->GetRankManager()->GetRankVisuals(RankName, MsgPrefix, MsgSuffix, MsgNameColorCode)) { // No such rank, return nothing: return 0; } // Push the results: S.Push(MsgPrefix, MsgSuffix, MsgNameColorCode); return 3; } /** Binds cRankManager::GroupExists */ static int tolua_cRankManager_GroupExists(lua_State * L) { // Function signature: // cRankManager:GroupExists(GroupName) -> bool cLuaState S(L); if ( !S.CheckParamUserTable(1, "cRankManager") || !S.CheckParamString(2) || !S.CheckParamEnd(3) ) { return 0; } // Get the params: AString GroupName; S.GetStackValue(2, GroupName); // Get the response: bool res = cRoot::Get()->GetRankManager()->GroupExists(GroupName); // Push the result: S.Push(res); return 1; } /** Binds cRankManager::IsGroupInRank */ static int tolua_cRankManager_IsGroupInRank(lua_State * L) { // Function signature: // cRankManager:IsGroupInRank(GroupName, RankName) -> bool cLuaState S(L); if ( !S.CheckParamUserTable(1, "cRankManager") || !S.CheckParamString(2, 3) || !S.CheckParamEnd(4) ) { return 0; } // Get the params: AString GroupName, RankName; S.GetStackValues(2, GroupName, RankName); // Get the response: bool res = cRoot::Get()->GetRankManager()->IsGroupInRank(GroupName, RankName); // Push the result: S.Push(res); return 1; } /** Binds cRankManager::IsPermissionInGroup */ static int tolua_cRankManager_IsPermissionInGroup(lua_State * L) { // Function signature: // cRankManager:IsPermissionInGroup(Permission, GroupName) -> bool cLuaState S(L); if ( !S.CheckParamUserTable(1, "cRankManager") || !S.CheckParamString(2, 3) || !S.CheckParamEnd(4) ) { return 0; } // Get the params: AString GroupName, Permission; S.GetStackValues(2, Permission, GroupName); // Get the response: bool res = cRoot::Get()->GetRankManager()->IsPermissionInGroup(Permission, GroupName); // Push the result: S.Push(res); return 1; } /** Binds cRankManager::IsRestrictionInGroup */ static int tolua_cRankManager_IsRestrictionInGroup(lua_State * L) { // Function signature: // cRankManager:IsRestrictionInGroup(Restriction, GroupName) -> bool cLuaState S(L); if ( !S.CheckParamUserTable(1, "cRankManager") || !S.CheckParamString(2, 3) || !S.CheckParamEnd(4) ) { return 0; } // Get the params: AString GroupName, Restriction; S.GetStackValues(2, Restriction, GroupName); // Get the response: bool res = cRoot::Get()->GetRankManager()->IsRestrictionInGroup(Restriction, GroupName); // Push the result: S.Push(res); return 1; } /** Binds cRankManager::IsPlayerRankSet */ static int tolua_cRankManager_IsPlayerRankSet(lua_State * L) { // Function signature: // cRankManager:IsPlayerRankSet(PlayerUUID) -> bool cLuaState S(L); if ( !S.CheckParamStaticSelf("cRankManager") || !S.CheckParamUUID(2) || !S.CheckParamEnd(3) ) { return 0; } // Get the params: cUUID PlayerUUID; S.GetStackValue(2, PlayerUUID); // Get the response: bool res = cRoot::Get()->GetRankManager()->IsPlayerRankSet(PlayerUUID); // Push the result: S.Push(res); return 1; } /** Binds cRankManager::RankExists */ static int tolua_cRankManager_RankExists(lua_State * L) { // Function signature: // cRankManager:RankExists(RankName) -> bool cLuaState S(L); if ( !S.CheckParamUserTable(1, "cRankManager") || !S.CheckParamString(2) || !S.CheckParamEnd(3) ) { return 0; } // Get the params: AString RankName; S.GetStackValue(2, RankName); // Get the response: bool res = cRoot::Get()->GetRankManager()->RankExists(RankName); // Push the result: S.Push(res); return 1; } /** Binds cRankManager::RemoveGroup */ static int tolua_cRankManager_RemoveGroup(lua_State * L) { // Function signature: // cRankManager:RemoveGroup(GroupName) cLuaState S(L); if ( !S.CheckParamUserTable(1, "cRankManager") || !S.CheckParamString(2) || !S.CheckParamEnd(3) ) { return 0; } // Get the params: AString GroupName; S.GetStackValue(2, GroupName); // Remove the group: cRoot::Get()->GetRankManager()->RemoveGroup(GroupName); return 0; } /** Binds cRankManager::RemoveGroupFromRank */ static int tolua_cRankManager_RemoveGroupFromRank(lua_State * L) { // Function signature: // cRankManager:RemoveGroupFromRank(GroupName, RankName) cLuaState S(L); if ( !S.CheckParamUserTable(1, "cRankManager") || !S.CheckParamString(2, 3) || !S.CheckParamEnd(4) ) { return 0; } // Get the params: AString GroupName, RankName; S.GetStackValues(2, GroupName, RankName); // Remove the group: cRoot::Get()->GetRankManager()->RemoveGroupFromRank(GroupName, RankName); return 0; } /** Binds cRankManager::RemovePermissionFromGroup */ static int tolua_cRankManager_RemovePermissionFromGroup(lua_State * L) { // Function signature: // cRankManager:RemovePermissionFromGroup(Permission, GroupName) cLuaState S(L); if ( !S.CheckParamUserTable(1, "cRankManager") || !S.CheckParamString(2, 3) || !S.CheckParamEnd(4) ) { return 0; } // Get the params: AString GroupName, Permission; S.GetStackValues(2, Permission, GroupName); // Remove the permission: cRoot::Get()->GetRankManager()->RemovePermissionFromGroup(Permission, GroupName); return 0; } /** Binds cRankManager::RemoveRestrictionFromGroup */ static int tolua_cRankManager_RemoveRestrictionFromGroup(lua_State * L) { // Function signature: // cRankManager:RemoveRestrictionFromGroup(Restriction, GroupName) cLuaState S(L); if ( !S.CheckParamUserTable(1, "cRankManager") || !S.CheckParamString(2, 3) || !S.CheckParamEnd(4) ) { return 0; } // Get the params: AString GroupName, Restriction; S.GetStackValues(2, Restriction, GroupName); // Remove the restriction: cRoot::Get()->GetRankManager()->RemoveRestrictionFromGroup(Restriction, GroupName); return 0; } /** Binds cRankManager::RemovePlayerRank */ static int tolua_cRankManager_RemovePlayerRank(lua_State * L) { // Function signature: // cRankManager:RemovePlayerRank(PlayerUUID) cLuaState S(L); if ( !S.CheckParamStaticSelf("cRankManager") || !S.CheckParamUUID(2) || !S.CheckParamEnd(3) ) { return 0; } // Get the params: cUUID PlayerUUID; S.GetStackValue(2, PlayerUUID); // Remove the player's rank: cRoot::Get()->GetRankManager()->RemovePlayerRank(PlayerUUID); return 0; } /** Binds cRankManager::RemoveRank */ static int tolua_cRankManager_RemoveRank(lua_State * L) { // Function signature: // cRankManager:RemoveRank(RankName, [ReplacementRankName]) cLuaState S(L); if ( !S.CheckParamUserTable(1, "cRankManager") || !S.CheckParamString(2) || // Param 3 is otpional, defaults to nil -> empty string !S.CheckParamEnd(4) ) { return 0; } // Get the params: AString RankName, ReplacementRankName; S.GetStackValues(2, RankName, ReplacementRankName); // Remove the rank: cRoot::Get()->GetRankManager()->RemoveRank(RankName, ReplacementRankName); return 0; } /** Binds cRankManager::RenameGroup */ static int tolua_cRankManager_RenameGroup(lua_State * L) { // Function signature: // cRankManager:RenameGroup(OldName, NewName) cLuaState S(L); if ( !S.CheckParamUserTable(1, "cRankManager") || !S.CheckParamString(2, 3) || !S.CheckParamEnd(4) ) { return 0; } // Get the params: AString OldName, NewName; S.GetStackValues(2, OldName, NewName); // Remove the group: bool res = cRoot::Get()->GetRankManager()->RenameGroup(OldName, NewName); // Push the result: S.Push(res); return 1; } /** Binds cRankManager::RenameRank */ static int tolua_cRankManager_RenameRank(lua_State * L) { // Function signature: // cRankManager:RenameRank(OldName, NewName) cLuaState S(L); if ( !S.CheckParamUserTable(1, "cRankManager") || !S.CheckParamString(2, 3) || !S.CheckParamEnd(4) ) { return 0; } // Get the params: AString OldName, NewName; S.GetStackValues(2, OldName, NewName); // Remove the rank: bool res = cRoot::Get()->GetRankManager()->RenameRank(OldName, NewName); // Push the result: S.Push(res); return 1; } /** Binds cRankManager::SetDefaultRank */ static int tolua_cRankManager_SetDefaultRank(lua_State * L) { // Function signature: // cRankManager:SetDefaultRank(RankName) -> bool cLuaState S(L); if ( !S.CheckParamUserTable(1, "cRankManager") || !S.CheckParamString(2) || !S.CheckParamEnd(3) ) { return 0; } // Get the params: AString RankName; S.GetStackValue(2, RankName); // Set the rank, return the result: S.Push(cRoot::Get()->GetRankManager()->SetDefaultRank(RankName)); return 1; } /** Binds cRankManager::SetPlayerRank */ static int tolua_cRankManager_SetPlayerRank(lua_State * L) { // Function signature: // cRankManager:SetPlayerRank(PlayerUUID, PlayerName, RankName) cLuaState S(L); if ( !S.CheckParamStaticSelf("cRankManager") || !S.CheckParamUUID(2) || !S.CheckParamString(3, 4) || !S.CheckParamEnd(5) ) { return 0; } // Get the params: AString PlayerName, RankName; cUUID PlayerUUID; S.GetStackValues(2, PlayerUUID, PlayerName, RankName); // Set the rank: cRoot::Get()->GetRankManager()->SetPlayerRank(PlayerUUID, PlayerName, RankName); return 0; } /** Binds cRankManager::SetRankVisuals */ static int tolua_cRankManager_SetRankVisuals(lua_State * L) { // Function signature: // cRankManager:SetRankVisuals(RankName, MsgPrefix, MsgSuffix, MsgNameColorCode) cLuaState S(L); if ( !S.CheckParamUserTable(1, "cRankManager") || !S.CheckParamString(2, 5) || !S.CheckParamEnd(6) ) { return 0; } // Get the params: AString RankName, MsgPrefix, MsgSuffix, MsgNameColorCode; S.GetStackValues(2, RankName, MsgPrefix, MsgSuffix, MsgNameColorCode); // Set the visuals: cRoot::Get()->GetRankManager()->SetRankVisuals(RankName, MsgPrefix, MsgSuffix, MsgNameColorCode); return 0; } void cManualBindings::BindRankManager(lua_State * tolua_S) { // Create the cRankManager class in the API: tolua_usertype(tolua_S, "cRankManager"); tolua_cclass(tolua_S, "cRankManager", "cRankManager", "", nullptr); // Fill in the functions (alpha-sorted): tolua_beginmodule(tolua_S, "cRankManager"); tolua_function(tolua_S, "AddGroup", tolua_cRankManager_AddGroup); tolua_function(tolua_S, "AddGroupToRank", tolua_cRankManager_AddGroupToRank); tolua_function(tolua_S, "AddPermissionToGroup", tolua_cRankManager_AddPermissionToGroup); tolua_function(tolua_S, "AddRestrictionToGroup", tolua_cRankManager_AddRestrictionToGroup); tolua_function(tolua_S, "AddRank", tolua_cRankManager_AddRank); tolua_function(tolua_S, "ClearPlayerRanks", tolua_cRankManager_ClearPlayerRanks); tolua_function(tolua_S, "GetAllGroups", tolua_cRankManager_GetAllGroups); tolua_function(tolua_S, "GetAllPermissions", tolua_cRankManager_GetAllPermissions); tolua_function(tolua_S, "GetAllRestrictions", tolua_cRankManager_GetAllRestrictions); tolua_function(tolua_S, "GetAllPermissionsRestrictions", tolua_cRankManager_GetAllPermissionsRestrictions); tolua_function(tolua_S, "GetAllPlayerUUIDs", tolua_cRankManager_GetAllPlayerUUIDs); tolua_function(tolua_S, "GetAllRanks", tolua_cRankManager_GetAllRanks); tolua_function(tolua_S, "GetDefaultRank", tolua_cRankManager_GetDefaultRank); tolua_function(tolua_S, "GetGroupPermissions", tolua_cRankManager_GetGroupPermissions); tolua_function(tolua_S, "GetGroupRestrictions", tolua_cRankManager_GetGroupRestrictions); tolua_function(tolua_S, "GetPlayerGroups", tolua_cRankManager_GetPlayerGroups); tolua_function(tolua_S, "GetPlayerMsgVisuals", tolua_cRankManager_GetPlayerMsgVisuals); tolua_function(tolua_S, "GetPlayerPermissions", tolua_cRankManager_GetPlayerPermissions); tolua_function(tolua_S, "GetPlayerPermissions", tolua_cRankManager_GetPlayerRestrictions); tolua_function(tolua_S, "GetPlayerRankName", tolua_cRankManager_GetPlayerRankName); tolua_function(tolua_S, "GetPlayerName", tolua_cRankManager_GetPlayerName); tolua_function(tolua_S, "GetRankGroups", tolua_cRankManager_GetRankGroups); tolua_function(tolua_S, "GetRankPermissions", tolua_cRankManager_GetRankPermissions); tolua_function(tolua_S, "GetRankRestrictions", tolua_cRankManager_GetRankRestrictions); tolua_function(tolua_S, "GetRankVisuals", tolua_cRankManager_GetRankVisuals); tolua_function(tolua_S, "GroupExists", tolua_cRankManager_GroupExists); tolua_function(tolua_S, "IsGroupInRank", tolua_cRankManager_IsGroupInRank); tolua_function(tolua_S, "IsPermissionInGroup", tolua_cRankManager_IsPermissionInGroup); tolua_function(tolua_S, "IsRestrictionInGroup", tolua_cRankManager_IsRestrictionInGroup); tolua_function(tolua_S, "IsPlayerRankSet", tolua_cRankManager_IsPlayerRankSet); tolua_function(tolua_S, "RankExists", tolua_cRankManager_RankExists); tolua_function(tolua_S, "RemoveGroup", tolua_cRankManager_RemoveGroup); tolua_function(tolua_S, "RemoveGroupFromRank", tolua_cRankManager_RemoveGroupFromRank); tolua_function(tolua_S, "RemovePermissionFromGroup", tolua_cRankManager_RemovePermissionFromGroup); tolua_function(tolua_S, "RemoveRestrictionFromGroup", tolua_cRankManager_RemoveRestrictionFromGroup); tolua_function(tolua_S, "RemovePlayerRank", tolua_cRankManager_RemovePlayerRank); tolua_function(tolua_S, "RemoveRank", tolua_cRankManager_RemoveRank); tolua_function(tolua_S, "RenameGroup", tolua_cRankManager_RenameGroup); tolua_function(tolua_S, "RenameRank", tolua_cRankManager_RenameRank); tolua_function(tolua_S, "SetDefaultRank", tolua_cRankManager_SetDefaultRank); tolua_function(tolua_S, "SetPlayerRank", tolua_cRankManager_SetPlayerRank); tolua_function(tolua_S, "SetRankVisuals", tolua_cRankManager_SetRankVisuals); tolua_endmodule(tolua_S); } ================================================ FILE: src/Bindings/ManualBindings_World.cpp ================================================ // ManualBindings_World.cpp // Implements the manual Lua API bindings for the cWorld class #include "Globals.h" #include "tolua++/include/tolua++.h" #include "../World.h" #include "../UUID.h" #include "ManualBindings.h" #include "LuaState.h" #include "PluginLua.h" #include "LuaChunkStay.h" #include "BlockEntities/BeaconEntity.h" #include "BlockEntities/BedEntity.h" #include "BlockEntities/BrewingstandEntity.h" #include "BlockEntities/ChestEntity.h" #include "BlockEntities/CommandBlockEntity.h" #include "BlockEntities/DispenserEntity.h" #include "BlockEntities/DropSpenserEntity.h" #include "BlockEntities/DropperEntity.h" #include "BlockEntities/FlowerPotEntity.h" #include "BlockEntities/FurnaceEntity.h" #include "BlockEntities/HopperEntity.h" #include "BlockEntities/MobHeadEntity.h" #include "BlockEntities/NoteEntity.h" /** Check that a Lua parameter is either a vector or 3 numbers in sequence \param L The Lua state \param a_VectorName name of the vector class e.g. "Vector3" \param a_Index Index to the start of the vector in the parameter list \param[out] a_NextIndex Index of the next parameter after the vector \retval true if the parameter is a vector or 3 numbers */ static bool CheckParamVectorOr3Numbers(cLuaState & L, const char * a_VectorName, int a_Index, int & a_NextIndex) { if (L.IsParamUserType(a_Index, a_VectorName)) { a_NextIndex = a_Index + 1; return L.CheckParamUserType(a_Index, a_VectorName); } a_NextIndex = a_Index + 3; return L.CheckParamNumber(a_Index, a_Index + 2); } /** Get a vector from the stack, which may be represented in lua as either a `Vector3` or 3 numbers */ template static bool GetStackVectorOr3Numbers(cLuaState & L, int a_Index, Vector3 & a_Return) { if (L.GetStackValue(a_Index, a_Return)) { return true; } return L.GetStackValues(a_Index, a_Return.x, a_Return.y, a_Return.z); } /** Template for the bindings for the DoWithXYZAt(X, Y, Z) functions that don't need to check their coords. */ template static int DoWithBlockEntityAt(lua_State * tolua_S) { cLuaState L(tolua_S); int OffsetIndex; // Check params: if ( !L.CheckParamSelf("cWorld") || !CheckParamVectorOr3Numbers(L, "Vector3", 2, OffsetIndex) || !L.CheckParamFunction(OffsetIndex) || !L.CheckParamEnd(OffsetIndex + 1) ) { return 0; } cWorld * Self = nullptr; Vector3i Position; cLuaState::cRef FnRef; // Get parameters: if ( !L.GetStackValues(1, Self) || !GetStackVectorOr3Numbers(L, 2, Position) || !L.GetStackValues(OffsetIndex, FnRef) ) { return 0; } if (Self == nullptr) { return L.ApiParamError("Invalid 'self'"); } if (!FnRef.IsValid()) { return L.ApiParamError(fmt::format(FMT_STRING("Expected a valid callback function for parameter {}"), OffsetIndex)); } // Call the DoWith function: bool res = Self->DoWithBlockEntityAt(Position, [&L, &FnRef](cBlockEntity & a_BlockEntity) { if constexpr (sizeof...(BlockTypes) != 0) { if (((a_BlockEntity.GetBlockType() != BlockTypes) && ...)) { return false; } } bool ret = false; L.Call(FnRef, static_cast(&a_BlockEntity), cLuaState::Return, ret); return ret; }); // Push the result as the return value: L.Push(res); return 1; } template < class Ty1, class Ty2, bool (Ty1::*ForEachFn)(const cBoundingBox &, cFunctionRef) > static int ForEachInBox(lua_State * tolua_S) { // Check params: cLuaState L(tolua_S); if ( !L.CheckParamUserType(1, "cWorld") || !L.CheckParamUserType(2, "cBoundingBox") || !L.CheckParamFunction(3) || !L.CheckParamEnd(4) ) { return 0; } // Get the params: Ty1 * Self = nullptr; cBoundingBox * Box = nullptr; cLuaState::cRef FnRef; L.GetStackValues(1, Self, Box, FnRef); if ((Self == nullptr) || (Box == nullptr)) { return L.ApiParamError(fmt::format(FMT_STRING("Invalid world ({}) or boundingbox ({})"), fmt::ptr(Self), fmt::ptr(Box))); } if (!FnRef.IsValid()) { return L.ApiParamError("Expected a valid callback function for parameter #2"); } bool res = (Self->*ForEachFn)(*Box, [&](Ty2 & a_Item) { bool ret = false; if (!L.Call(FnRef, &a_Item, cLuaState::Return, ret)) { LOGWARNING("Failed to call Lua callback"); L.LogStackTrace(); return true; // Abort enumeration } return ret; } ); // Push the result as the return value: L.Push(res); return 1; } template static int ForEachBlockEntityInChunk(lua_State * tolua_S) { // Check params: cLuaState L(tolua_S); if ( !L.CheckParamSelf("cWorld") || !L.CheckParamNumber(2, 3) || !L.CheckParamFunction(4) || !L.CheckParamEnd(5) ) { return 0; } // Get parameters: cWorld * Self = nullptr; int ChunkX = 0; int ChunkZ = 0; cLuaState::cRef FnRef; L.GetStackValues(1, Self, ChunkX, ChunkZ, FnRef); if (Self == nullptr) { return L.ApiParamError("Error in function call '#funcname#': Invalid 'self'"); } if (!FnRef.IsValid()) { return L.ApiParamError("Expected a valid callback function for parameter #4"); } // Call the ForEach function: bool res = Self->ForEachBlockEntityInChunk(ChunkX, ChunkZ, [&L, &FnRef](cBlockEntity & a_BlockEntity) { if constexpr (sizeof...(BlockTypes) != 0) { if (((a_BlockEntity.GetBlockType() != BlockTypes) && ...)) { return false; } } bool ret = false; L.Call(FnRef, static_cast(&a_BlockEntity), cLuaState::Return, ret); return ret; }); // Push the result as the return value: L.Push(res); return 1; } static int tolua_cWorld_BroadcastBlockAction(lua_State * tolua_S) { /* Function signature: void BroadcastBlockAction(number a_BlockX, number a_BlockY, number a_BlockZ, number a_number1, number a_number2, number a_BlockType, cClientHandle a_Exclude) --or-- void BroadcastBlockAction(Vector3 a_BlockPos, number a_Byte1, number a_Byte2, number a_BlockType, cClientHandle a_Exclude) */ cLuaState L(tolua_S); int Byte1Index; if ( !L.CheckParamSelf("cWorld") || !CheckParamVectorOr3Numbers(L, "Vector3", 2, Byte1Index) || !L.CheckParamNumber(Byte1Index, Byte1Index + 2) ) { return 0; } if (Byte1Index != 3) // Not the vector overload { L.LogStackTrace(); LOGWARN("BroadcastBlockAction with 3 position arguments is deprecated, use vector-parametered version instead."); } // Read the params: cWorld * Self; Vector3i BlockPos; Byte Byte1, Byte2; BLOCKTYPE BlockType; const cClientHandle * Exclude = nullptr; if ( !L.GetStackValues(1, Self) || !GetStackVectorOr3Numbers(L, 2, BlockPos) || !L.GetStackValues(Byte1Index, Byte1, Byte2, BlockType) ) { return 0; } // Optional param L.GetStackValue(Byte1Index + 3, Exclude); Self->BroadcastBlockAction(BlockPos, Byte1, Byte2, BlockType, Exclude); return 0; } static int tolua_cWorld_BroadcastSoundEffect(lua_State * tolua_S) { /* Function signature: void BroadcastSoundEffect(string a_SoundName, number a_X, number a_Y, number a_Z, number a_Volume, number a_Pitch, [cClientHandle * a_Exclude]) --or-- void BroadcastSoundEffect(string a_SoundName, Vector3d, number a_Volume, number a_Pitch, [cClientHandle a_Exclude]) */ cLuaState L(tolua_S); int VolumeIndex; if ( !L.CheckParamSelf("cWorld") || !L.CheckParamString(2) || !CheckParamVectorOr3Numbers(L, "Vector3", 3, VolumeIndex) || !L.CheckParamNumber(VolumeIndex, VolumeIndex + 1) ) { return 0; } if (VolumeIndex != 4) // Not the vector overload { L.LogStackTrace(); LOGWARN("BroadcastSoundEffect with 3 position arguments is deprecated, use vector-parametered version instead."); } // Read the params: cWorld * Self; AString SoundName; Vector3d BlockPos; float Volume, Pitch; const cClientHandle * Exclude = nullptr; if ( !L.GetStackValues(1, Self, SoundName) || !GetStackVectorOr3Numbers(L, 3, BlockPos) || !L.GetStackValues(VolumeIndex, Volume, Pitch) ) { return 0; } // Optional param L.GetStackValue(VolumeIndex + 2, Exclude); Self->BroadcastSoundEffect(SoundName, BlockPos, Volume, Pitch, Exclude); return 0; } static int tolua_cWorld_BroadcastSoundParticleEffect(lua_State * tolua_S) { /* Function signature: World:BroadcastSoundParticleEffect(EffectID a_EffectID, Vector3i a_SrcPos, number a_Data, [cClientHandle a_Exclude]) --or-- void BroadcastSoundParticleEffect(EffectID a_EffectID, number a_SrcX, number a_SrcY, number a_SrcZ, number a_Data, [cClientHandle a_Exclude]) */ cLuaState L(tolua_S); int DataIndex; if ( !L.CheckParamSelf("cWorld") || !L.CheckParamNumber(2) || !CheckParamVectorOr3Numbers(L, "Vector3", 3, DataIndex) || !L.CheckParamNumber(DataIndex) ) { return 0; } if (DataIndex != 4) // Not the vector overload { L.LogStackTrace(); LOGWARN("BroadcastSoundParticleEffect with 3 position arguments is deprecated, use vector-parametered version instead."); } // Read the params: cWorld * World = nullptr; Int32 EffectId; Vector3i SrcPos; int Data; cClientHandle * ExcludeClient = nullptr; if ( !L.GetStackValues(1, World, EffectId) || !GetStackVectorOr3Numbers(L, 3, SrcPos) || !L.GetStackValue(DataIndex, Data) ) { return 0; } // Optional param L.GetStackValue(DataIndex + 1, ExcludeClient); World->BroadcastSoundParticleEffect(static_cast(EffectId), SrcPos, Data, ExcludeClient); return 0; } static int tolua_cWorld_BroadcastParticleEffect(lua_State * tolua_S) { /* Function signature: World:BroadcastParticleEffect("Name", PosX, PosY, PosZ, OffX, OffY, OffZ, ParticleData, ParticleAmount, [ExcludeClient], [OptionalParam1], [OptionalParam2]) --or-- World:BroadcastParticleEffect("Name", SrcPos, Offset, ParticleData, ParticleAmount, [ExcludeClient], [OptionalParam1], [OptionalParam2]) */ cLuaState L(tolua_S); int OffsetIndex, ParticleDataIndex; if ( !L.CheckParamSelf("cWorld") || !L.CheckParamString(2) || !CheckParamVectorOr3Numbers(L, "Vector3", 3, OffsetIndex) || !CheckParamVectorOr3Numbers(L, "Vector3", OffsetIndex, ParticleDataIndex) ) { return 0; } if ((OffsetIndex != 4) || (ParticleDataIndex != 5)) // Not the vector overload { L.LogStackTrace(); LOGWARN("BroadcastParticleEffect with 3 position and 3 offset arguments is deprecated, use vector-parametered version instead."); } // Read the params: cWorld * World = nullptr; AString Name; Vector3f SrcPos, Offset; float ParticleData; int ParticleAmount; cClientHandle * ExcludeClient = nullptr; if ( !L.GetStackValues(1, World, Name) || !GetStackVectorOr3Numbers(L, 3, SrcPos) || !GetStackVectorOr3Numbers(L, OffsetIndex, Offset) || !L.GetStackValues(ParticleDataIndex, ParticleData, ParticleAmount) ) { return 0; } // Read up to 3 more optional params: L.GetStackValue(ParticleDataIndex + 2, ExcludeClient); std::array Data; bool HasData = L.GetStackValues(ParticleDataIndex + 3, Data[0], Data[1]); if (HasData) { World->BroadcastParticleEffect(Name, SrcPos, Offset, ParticleData, ParticleAmount, Data, ExcludeClient); } else { World->BroadcastParticleEffect(Name, SrcPos, Offset, ParticleData, ParticleAmount, ExcludeClient); } return 0; } static int tolua_cWorld_ChunkStay(lua_State * tolua_S) { /* Function signature: World:ChunkStay(ChunkCoordTable, OnChunkAvailable, OnAllChunksAvailable) ChunkCoordTable == { {Chunk1x, Chunk1z}, {Chunk2x, Chunk2z}, ... } */ cLuaState L(tolua_S); if ( !L.CheckParamUserType (1, "cWorld") || !L.CheckParamTable (2) || !L.CheckParamFunctionOrNil(3, 4) ) { return 0; } // Read the params: cWorld * world; cLuaState::cStackTablePtr chunkCoords; cLuaState::cOptionalCallbackPtr onChunkAvailable, onAllChunksAvailable; // Callbacks may be unassigned at all - as a request to load / generate chunks if (!L.GetStackValues(1, world, chunkCoords, onChunkAvailable, onAllChunksAvailable)) { LOGWARNING("cWorld:ChunkStay(): Cannot read parameters, bailing out."); L.LogStackTrace(); L.LogStackValues("Values on the stack"); return 0; } if (world == nullptr) { LOGWARNING("World:ChunkStay(): invalid world parameter"); L.LogStackTrace(); return 0; } ASSERT(chunkCoords != nullptr); // If the table was invalid, GetStackValues() would have failed // Read the chunk coords: auto chunkStay = std::make_unique(); if (!chunkStay->AddChunks(*chunkCoords)) { return 0; } // Activate the ChunkStay: chunkStay.release()->Enable(*world->GetChunkMap(), std::move(onChunkAvailable), std::move(onAllChunksAvailable)); return 0; } static int tolua_cWorld_DoExplosionAt(lua_State * tolua_S) { /* Function signature: World:DoExplosionAt(ExplosionSize, BlockX, BlockY, BlockZ, CanCauseFire, SourceType, [SourceData]) */ cLuaState L(tolua_S); if ( !L.CheckParamUserType (1, "cWorld") || !L.CheckParamNumber (2, 5) || !L.CheckParamBool (6) || !L.CheckParamNumber (7) || !L.CheckParamEnd (9) ) { return 0; } // Read the params: cWorld * World; double ExplosionSize; int BlockX, BlockY, BlockZ; bool CanCauseFire; int SourceTypeInt; if (!L.GetStackValues(1, World, ExplosionSize, BlockX, BlockY, BlockZ, CanCauseFire, SourceTypeInt)) { LOGWARNING("World:DoExplosionAt(): invalid parameters"); L.LogStackTrace(); return 0; } if ((SourceTypeInt < 0) || (SourceTypeInt >= esMax)) { LOGWARNING("World:DoExplosionAt(): Invalid source type"); L.LogStackTrace(); return 0; } eExplosionSource SourceType; void * SourceData; switch (SourceTypeInt) { case esBed: { // esBed receives a Vector3i SourceData param: Vector3i pos; L.GetStackValue(8, pos); SourceType = esBed; SourceData = &pos; break; } case esEnderCrystal: case esGhastFireball: case esMonster: case esPrimedTNT: case esWitherBirth: case esWitherSkull: { // These all receive a cEntity descendant SourceData param: cEntity * ent = nullptr; L.GetStackValue(8, ent); SourceType = static_cast(SourceTypeInt); SourceData = ent; break; } case esOther: case esPlugin: { // esOther and esPlugin ignore their SourceData params SourceType = static_cast(SourceTypeInt); SourceData = nullptr; break; } default: { LOGWARNING("cWorld:DoExplosionAt(): invalid SourceType parameter: %d", SourceTypeInt); L.LogStackTrace(); return 0; } } // Create the actual explosion: World->DoExplosionAt(ExplosionSize, BlockX, BlockY, BlockZ, CanCauseFire, SourceType, SourceData); return 0; } static int tolua_cWorld_DoWithPlayerByUUID(lua_State * tolua_S) { // Check params: cLuaState L(tolua_S); if ( !L.CheckParamSelf("cWorld") || !L.CheckParamUUID(2) || !L.CheckParamFunction(3) || !L.CheckParamEnd(4) ) { return 0; } // Get parameters: cWorld * Self; cUUID PlayerUUID; cLuaState::cRef FnRef; L.GetStackValues(1, Self, PlayerUUID, FnRef); if (PlayerUUID.IsNil()) { return L.ApiParamError("Expected a non-nil UUID for parameter #1"); } if (!FnRef.IsValid()) { return L.ApiParamError("Expected a valid callback function for parameter #2"); } // Call the function: bool res = Self->DoWithPlayerByUUID(PlayerUUID, [&](cPlayer & a_Player) { bool ret = false; L.Call(FnRef, &a_Player, cLuaState::Return, ret); return ret; } ); // Push the result as the return value: L.Push(res); return 1; } static int tolua_cWorld_DoWithNearestPlayer(lua_State * tolua_S) { // Check params: cLuaState L(tolua_S); if ( !L.CheckParamSelf("cWorld") || !L.CheckParamUserType(2, "Vector3") || !L.CheckParamNumber(3) || !L.CheckParamFunction(4) || // Params 5 and 6 are optional bools, no check for those !L.CheckParamEnd(7) ) { return 0; } // Get parameters: cWorld * Self; Vector3d Position; double RangeLimit; cLuaState::cRef FnRef; bool CheckLineOfSight = true, IgnoreSpectators = true; // Defaults for the optional params L.GetStackValues(1, Self, Position, RangeLimit, FnRef, CheckLineOfSight, IgnoreSpectators); if (!FnRef.IsValid()) { return L.ApiParamError("Expected a valid callback function for parameter #3"); } // Call the function: bool res = Self->DoWithNearestPlayer(Position, RangeLimit, [&](cPlayer & a_Player) { bool ret = false; L.Call(FnRef, &a_Player, cLuaState::Return, ret); return ret; }, CheckLineOfSight, IgnoreSpectators); // Push the result as the return value: L.Push(res); return 1; } static int tolua_cWorld_FastSetBlock(lua_State * tolua_S) { /* Function signature: World:FastSetBlock(BlockX, BlockY, BlockZ) --or-- World:FastSetBlock(Position) */ cLuaState L(tolua_S); int OffsetIndex; if ( !L.CheckParamSelf("cWorld") || !CheckParamVectorOr3Numbers(L, "Vector3", 2, OffsetIndex) || !L.CheckParamNumber(OffsetIndex, OffsetIndex + 1) || !L.CheckParamEnd(OffsetIndex + 2) ) { return 0; } if (OffsetIndex != 3) // Not the vector overload { L.LogStackTrace(); LOGWARN("FastSetBlock with 3 position arguments is deprecated, use vector-parametered version instead."); } cWorld * World; Vector3i Position; BLOCKTYPE Type; NIBBLETYPE Meta; // Read the params: if ( !L.GetStackValues(1, World) || !GetStackVectorOr3Numbers(L, 2, Position) || !L.GetStackValues(OffsetIndex, Type, Meta) ) { return 0; } if (World == nullptr) { return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'self'"); } if (!cChunkDef::IsValidHeight(Position)) { return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'position'"); } World->FastSetBlock(Position, Type, Meta); return 0; } static int tolua_cWorld_ForEachEntityInChunk(lua_State * tolua_S) { // Check params: cLuaState L(tolua_S); if ( !L.CheckParamUserType(1, "cWorld") || !L.CheckParamNumber(2, 3) || !L.CheckParamFunction(4) || !L.CheckParamEnd(5) ) { return 0; } // Get parameters: cWorld * Self = nullptr; int ChunkX = 0; int ChunkZ = 0; cLuaState::cRef FnRef; L.GetStackValues(1, Self, ChunkX, ChunkZ, FnRef); if (Self == nullptr) { return L.ApiParamError("Invalid 'self'"); } if (!FnRef.IsValid()) { return L.ApiParamError("Expected a valid callback function for parameter #4"); } // Call the DoWith function: bool res = Self->ForEachEntityInChunk(ChunkX, ChunkZ, [&](cEntity & a_Item) { bool ret = false; L.Call(FnRef, &a_Item, cLuaState::Return, ret); return ret; } ); // Push the result as the return value: L.Push(res); return 1; } static int tolua_cWorld_ForEachLoadedChunk(lua_State * tolua_S) { // Exported manually, because tolua doesn't support converting functions to functor types. // Function signature: ForEachLoadedChunk(callback) -> bool cLuaState L(tolua_S); if ( !L.CheckParamUserType(1, "cWorld") || !L.CheckParamFunction(2) ) { return 0; } cPluginLua * Plugin = cManualBindings::GetLuaPlugin(tolua_S); if (Plugin == nullptr) { return 0; } // Read the params: cWorld * World = static_cast(tolua_tousertype(tolua_S, 1, nullptr)); if (World == nullptr) { LOGWARNING("World:ForEachLoadedChunk(): invalid world parameter"); L.LogStackTrace(); return 0; } cLuaState::cRef FnRef; L.GetStackValues(2, FnRef); if (!FnRef.IsValid()) { return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Could not get function reference of parameter #2"); } // Call the enumeration: bool ret = World->ForEachLoadedChunk( [&L, &FnRef](int a_ChunkX, int a_ChunkZ) -> bool { bool res = false; // By default continue the enumeration L.Call(FnRef, a_ChunkX, a_ChunkZ, cLuaState::Return, res); return res; } ); // Push the return value: L.Push(ret); return 1; } static int tolua_cWorld_GetBlock(lua_State * tolua_S) { /* Function signature: World:GetBlock(BlockX, BlockY, BlockZ) -> BlockType --or-- World:GetBlock(Position) -> BlockType */ cLuaState L(tolua_S); int OffsetIndex; if ( !L.CheckParamSelf("cWorld") || !CheckParamVectorOr3Numbers(L, "Vector3", 2, OffsetIndex) || !L.CheckParamEnd(OffsetIndex) ) { return 0; } if (OffsetIndex != 3) // Not the vector overload { L.LogStackTrace(); LOGWARN("GetBlock with 3 position arguments is deprecated, use vector-parametered version instead."); } cWorld * World; Vector3i Position; // Read the params: if ( !L.GetStackValues(1, World) || !GetStackVectorOr3Numbers(L, 2, Position) ) { return 0; } if (World == nullptr) { return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'self'"); } if (!cChunkDef::IsValidHeight(Position)) { L.Push(E_BLOCK_AIR); return 1; } L.Push(World->GetBlock(Position)); return 1; } static int tolua_cWorld_GetBlockBlockLight(lua_State * tolua_S) { /* Function signature: World:GetBlockBlockLight(BlockX, BlockY, BlockZ) -> BlockLight --or-- World:GetBlockBlockLight(Position) -> BlockLight */ cLuaState L(tolua_S); int OffsetIndex; if ( !L.CheckParamSelf("cWorld") || !CheckParamVectorOr3Numbers(L, "Vector3", 2, OffsetIndex) || !L.CheckParamEnd(OffsetIndex) ) { return 0; } if (OffsetIndex != 3) // Not the vector overload { L.LogStackTrace(); LOGWARN("GetBlockBlockLight with 3 position arguments is deprecated, use vector-parametered version instead."); } cWorld * World; Vector3i Position; // Read the params: if ( !L.GetStackValues(1, World) || !GetStackVectorOr3Numbers(L, 2, Position) ) { return 0; } if (World == nullptr) { return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'self'"); } if (!cChunkDef::IsValidHeight(Position)) { return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'position'"); } L.Push(World->GetBlockBlockLight(Position)); return 1; } static int tolua_cWorld_GetBlockInfo(lua_State * tolua_S) { /* Exported manually, because tolua would generate useless additional parameters (a_BlockType .. a_BlockSkyLight) Function signature: GetBlockInfo(BlockX, BlockY, BlockZ) -> BlockValid, [BlockType, BlockMeta, BlockSkyLight, BlockBlockLight] --or-- GetBlockInfo(Position) -> BlockValid, [BlockType, BlockMeta, BlockSkyLight, BlockBlockLight] */ // Check params: cLuaState L(tolua_S); int OffsetIndex; if ( !L.CheckParamSelf("cWorld") || !CheckParamVectorOr3Numbers(L, "Vector3", 2, OffsetIndex) || !L.CheckParamEnd(OffsetIndex) ) { return 0; } if (OffsetIndex != 3) // Not the vector overload { L.LogStackTrace(); LOGWARN("GetBlockInfo with 3 position arguments is deprecated, use vector-parametered version instead."); } cWorld * World; Vector3i Position; // Read the params: if ( !L.GetStackValues(1, World) || !GetStackVectorOr3Numbers(L, 2, Position) ) { return 0; } if (World == nullptr) { return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'self'"); } if (!cChunkDef::IsValidHeight(Position)) { return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'position'"); } BLOCKTYPE BlockType; NIBBLETYPE BlockMeta, BlockSkyLight, BlockBlockLight; // Call the function: bool res = World->GetBlockInfo(Position, BlockType, BlockMeta, BlockSkyLight, BlockBlockLight); // Push the returned values: L.Push(res); if (res) { L.Push(BlockType, BlockMeta, BlockSkyLight, BlockBlockLight); return 5; } return 1; } static int tolua_cWorld_GetBlockMeta(lua_State * tolua_S) { /* Function signature: World:GetBlockMeta(BlockX, BlockY, BlockZ) -> BlockMeta --or-- World:GetBlockMeta(Position) -> BlockMeta */ cLuaState L(tolua_S); int OffsetIndex; if ( !L.CheckParamSelf("cWorld") || !CheckParamVectorOr3Numbers(L, "Vector3", 2, OffsetIndex) || !L.CheckParamEnd(OffsetIndex) ) { return 0; } if (OffsetIndex != 3) // Not the vector overload { L.LogStackTrace(); LOGWARN("GetBlockMeta with 3 position arguments is deprecated, use vector-parametered version instead."); } cWorld * World; Vector3i Position; // Read the params: if ( !L.GetStackValues(1, World) || !GetStackVectorOr3Numbers(L, 2, Position) ) { return 0; } if (World == nullptr) { return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'self'"); } if (!cChunkDef::IsValidHeight(Position)) { L.Push(0); return 1; } L.Push(World->GetBlockMeta(Position)); return 1; } static int tolua_cWorld_GetBlockSkyLight(lua_State * tolua_S) { /* Function signature: World:GetBlockSkyLight(BlockX, BlockY, BlockZ) -> BlockLight --or-- World:GetBlockSkyLight(Position) -> BlockLight */ cLuaState L(tolua_S); int OffsetIndex; if ( !L.CheckParamSelf("cWorld") || !CheckParamVectorOr3Numbers(L, "Vector3", 2, OffsetIndex) || !L.CheckParamEnd(OffsetIndex) ) { return 0; } if (OffsetIndex != 3) // Not the vector overload { L.LogStackTrace(); LOGWARN("GetBlockSkyLight with 3 position arguments is deprecated, use vector-parametered version instead."); } cWorld * World; Vector3i Position; // Read the params: if ( !L.GetStackValues(1, World) || !GetStackVectorOr3Numbers(L, 2, Position) ) { return 0; } if (World == nullptr) { return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'self'"); } if (!cChunkDef::IsValidHeight(Position)) { return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'position'"); } L.Push(World->GetBlockSkyLight(Position)); return 1; } static int tolua_cWorld_GetBlockTypeMeta(lua_State * tolua_S) { /* Exported manually, because tolua would generate useless additional parameters (a_BlockType, a_BlockMeta) Function signature: GetBlockTypeMeta(BlockX, BlockY, BlockZ) -> BlockValid, [BlockType, BlockMeta] --or-- GetBlockTypeMeta(Position) -> BlockValid, [BlockType, BlockMeta] */ // Check params: cLuaState L(tolua_S); int OffsetIndex; if ( !L.CheckParamSelf("cWorld") || !CheckParamVectorOr3Numbers(L, "Vector3", 2, OffsetIndex) || !L.CheckParamEnd(OffsetIndex) ) { return 0; } if (OffsetIndex != 3) // Not the vector overload { L.LogStackTrace(); LOGWARN("GetBlockTypeMeta with 3 position arguments is deprecated, use vector-parametered version instead."); } cWorld * World; Vector3i Position; // Read the params: if ( !L.GetStackValues(1, World) || !GetStackVectorOr3Numbers(L, 2, Position) ) { return 0; } if (World == nullptr) { return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'self'"); } if (!cChunkDef::IsValidHeight(Position)) { L.Push(E_BLOCK_AIR, 0); return 2; } BLOCKTYPE BlockType; NIBBLETYPE BlockMeta; // Call the function: bool res = World->GetBlockTypeMeta(Position, BlockType, BlockMeta); // Push the returned values: L.Push(res); if (res) { L.Push(BlockType, BlockMeta); return 3; } return 1; } static int tolua_cWorld_GetSignLines(lua_State * tolua_S) { // Exported manually, because tolua would generate useless additional parameters (a_Line1 .. a_Line4) // Check params: cLuaState L(tolua_S); if ( !L.CheckParamUserType(1, "cWorld") || !L.CheckParamNumber(2, 4) || !L.CheckParamEnd(5) ) { return 0; } // Get params: cWorld * Self = nullptr; int BlockX = 0; int BlockY = 0; int BlockZ = 0; L.GetStackValues(1, Self, BlockX, BlockY, BlockZ); if (Self == nullptr) { return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'self'"); } // Call the function: AString Line1, Line2, Line3, Line4; bool res = Self->GetSignLines(BlockX, BlockY, BlockZ, Line1, Line2, Line3, Line4); // Push the returned values: L.Push(res); if (res) { L.Push(Line1, Line2, Line3, Line4); return 5; } return 1; } static int tolua_cWorld_GetTimeOfDay(lua_State * tolua_S) { // Check params: cLuaState L(tolua_S); if ( !L.CheckParamSelf("cWorld") || !L.CheckParamEnd(2) ) { return 0; } // Get params: cWorld * Self = nullptr; L.GetStackValues(1, Self); if (Self == nullptr) { return L.ApiParamError("Invalid 'self'"); } // Call the function: const auto Time = Self->GetTimeOfDay(); // Push the returned value: L.Push(Time.count()); return 1; } static int tolua_cWorld_GetWorldAge(lua_State * tolua_S) { // Check params: cLuaState L(tolua_S); if ( !L.CheckParamSelf("cWorld") || !L.CheckParamEnd(2) ) { return 0; } // Get params: cWorld * Self = nullptr; L.GetStackValues(1, Self); if (Self == nullptr) { return L.ApiParamError("Invalid 'self'"); } // Call the function: const auto Time = Self->GetWorldAge(); // Push the returned value: L.Push(static_cast(Time.count())); return 1; } static int tolua_cWorld_PrepareChunk(lua_State * tolua_S) { /* Function signature: World:PrepareChunk(ChunkX, ChunkZ, Callback) */ // Check the param types: cLuaState L(tolua_S); if ( !L.CheckParamUserType (1, "cWorld") || !L.CheckParamNumber (2, 3) || !L.CheckParamFunctionOrNil(4) ) { return 0; } // Wrap the Lua callback inside a C++ callback class: class cCallback: public cChunkCoordCallback { public: // cChunkCoordCallback override: virtual void Call(cChunkCoords a_Coords, bool a_IsSuccess) override { m_LuaCallback.Call(a_Coords.m_ChunkX, a_Coords.m_ChunkZ, a_IsSuccess); } cLuaState::cOptionalCallback m_LuaCallback; }; // Read the params: cWorld * world = nullptr; int chunkX = 0; int chunkZ = 0; auto Callback = std::make_unique(); L.GetStackValues(1, world, chunkX, chunkZ, Callback->m_LuaCallback); if (world == nullptr) { LOGWARNING("World:PrepareChunk(): invalid world parameter"); L.LogStackTrace(); return 0; } // Call the chunk preparation: world->PrepareChunk(chunkX, chunkZ, std::move(Callback)); return 0; } static int tolua_cWorld_QueueTask(lua_State * tolua_S) { // Function signature: // World:QueueTask(Callback) // Retrieve the args: cLuaState L(tolua_S); if ( !L.CheckParamUserType(1, "cWorld") || !L.CheckParamFunction(2) ) { return 0; } cWorld * World; cLuaState::cCallbackSharedPtr Task; if (!L.GetStackValues(1, World, Task)) { return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Cannot read parameters"); } if (World == nullptr) { return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Not called on an object instance"); } if (!Task->IsValid()) { return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Could not store the callback parameter"); } World->QueueTask([Task](cWorld & a_World) { Task->Call(&a_World); } ); return 0; } static int tolua_cWorld_SetBlock(lua_State * tolua_S) { /* Function signature: World:SetBlock(BlockX, BlockY, BlockZ, BlockType, BlockMeta) --or-- World:SetBlock(Position, BlockType, BlockMeta) */ cLuaState L(tolua_S); int OffsetIndex; if ( !L.CheckParamSelf("cWorld") || !CheckParamVectorOr3Numbers(L, "Vector3", 2, OffsetIndex) || !L.CheckParamNumber(OffsetIndex, OffsetIndex + 1) || !L.CheckParamEnd(OffsetIndex + 2) ) { return 0; } if (OffsetIndex != 3) // Not the vector overload { L.LogStackTrace(); LOGWARN("SetBlock with 3 position arguments is deprecated, use vector-parametered version instead."); } cWorld * World; Vector3i Position; BLOCKTYPE Type; NIBBLETYPE Meta; // Read the params: if ( !L.GetStackValues(1, World) || !GetStackVectorOr3Numbers(L, 2, Position) || !L.GetStackValues(OffsetIndex, Type, Meta) ) { return 0; } if (World == nullptr) { return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'self'"); } if (!cChunkDef::IsValidHeight(Position)) { return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'position'"); } World->SetBlock(Position, Type, Meta); return 0; } static int tolua_cWorld_SetBlockMeta(lua_State * tolua_S) { /* Function signature: World:SetBlockMeta(BlockX, BlockY, BlockZ, BlockMeta) --or-- World:SetBlockMeta(Position, BlockMeta) */ cLuaState L(tolua_S); int OffsetIndex; if ( !L.CheckParamSelf("cWorld") || !CheckParamVectorOr3Numbers(L, "Vector3", 2, OffsetIndex) || !L.CheckParamNumber(OffsetIndex) || !L.CheckParamEnd(OffsetIndex + 1) ) { return 0; } if (OffsetIndex != 3) // Not the vector overload { L.LogStackTrace(); LOGWARN("SetBlockMeta with 3 position arguments is deprecated, use vector-parametered version instead."); } cWorld * World; Vector3i Position; NIBBLETYPE Meta; // Read the params: if ( !L.GetStackValue(1, World) || !GetStackVectorOr3Numbers(L, 2, Position) || !L.GetStackValue(OffsetIndex, Meta) ) { return 0; } if (World == nullptr) { return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'self'"); } if (!cChunkDef::IsValidHeight(Position)) { return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'position'"); } World->SetBlockMeta(Position, Meta); return 0; } static int tolua_cWorld_SetSignLines(lua_State * tolua_S) { // Exported manually, because tolua would generate useless additional return values (a_Line1 .. a_Line4) // Check params: cLuaState L(tolua_S); if ( !L.CheckParamUserType(1, "cWorld") || !L.CheckParamNumber(2, 4) || !L.CheckParamString(5, 8) || !L.CheckParamEnd(9) ) { return 0; } // Get params: cWorld * Self = nullptr; int BlockX = 0; int BlockY = 0; int BlockZ = 0; AString Line1, Line2, Line3, Line4; L.GetStackValues(1, Self, BlockX, BlockY, BlockZ, Line1, Line2, Line3, Line4); if (Self == nullptr) { return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'self'"); } // Call the function: bool res = Self->SetSignLines({BlockX, BlockY, BlockZ}, Line1, Line2, Line3, Line4); // Push the returned values: L.Push(res); return 1; } static int tolua_cWorld_SetTimeOfDay(lua_State * tolua_S) { // Check params: cLuaState L(tolua_S); if ( !L.CheckParamSelf("cWorld") || !L.CheckParamNumber(2) || !L.CheckParamEnd(3) ) { return 0; } // Get params: cWorld * Self = nullptr; cTickTime::rep Time; L.GetStackValues(1, Self, Time); if (Self == nullptr) { return L.ApiParamError("Invalid 'self'"); } // Call the function: Self->SetTimeOfDay(cTickTime(Time)); return 0; } static int tolua_cWorld_ScheduleTask(lua_State * tolua_S) { // Function signature: // World:ScheduleTask(NumTicks, Callback) // Retrieve the args: cLuaState L(tolua_S); if ( !L.CheckParamUserType(1, "cWorld") || !L.CheckParamNumber (2) || !L.CheckParamFunction(3) ) { return 0; } cWorld * World; int NumTicks; auto Task = std::make_shared(); if (!L.GetStackValues(1, World, NumTicks, Task)) { return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Cannot read parameters"); } if (World == nullptr) { return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Not called on an object instance"); } if (!Task->IsValid()) { return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Could not store the callback parameter"); } World->ScheduleTask(cTickTime(NumTicks), [Task](cWorld & a_World) { Task->Call(&a_World); } ); return 0; } static int tolua_cWorld_SpawnSplitExperienceOrbs(lua_State* tolua_S) { cLuaState L(tolua_S); if ( !L.CheckParamSelf("cWorld") || !L.CheckParamUserType(2, "Vector3") || !L.CheckParamNumber(3) || !L.CheckParamEnd(4) ) { return 0; } cWorld * self = nullptr; Vector3d Position; int Reward; L.GetStackValues(1, self, Position, Reward); if (self == nullptr) { tolua_error(tolua_S, "Invalid 'self' in function 'SpawnSplitExperienceOrbs'", nullptr); return 0; } // Execute and push result: L.Push(self->SpawnExperienceOrb(Position, Reward)); return 1; } static int tolua_cWorld_TryGetHeight(lua_State * tolua_S) { /* Exported manually because we don't export optional Function signature: world:TryGetHeight(a_World, a_BlockX, a_BlockZ) -> IsValid, Height */ // Check params: cLuaState L(tolua_S); if ( !L.CheckParamUserType(1, "cWorld") || !L.CheckParamNumber(2, 3) || !L.CheckParamEnd(4) ) { return 0; } // Get params: cWorld * self = nullptr; int BlockX = 0; int BlockZ = 0; L.GetStackValues(1, self, BlockX, BlockZ); if (self == nullptr) { tolua_error(tolua_S, "Invalid 'self' in function 'TryGetHeight'", nullptr); return 0; } // Call the implementation: auto Height = self->GetHeight(BlockX, BlockZ); L.Push(Height.has_value()); if (Height.has_value()) { L.Push(Height.value()); return 2; } return 1; } static int tolua_cWorld_GetHeight(lua_State * tolua_S) { // Signature: world:GetHeight(a_World, a_BlockX, a_BlockZ) -> Height // Check params: cLuaState L(tolua_S); if ( !L.CheckParamSelf("cWorld") || !L.CheckParamNumber(2, 3) || !L.CheckParamEnd(4) ) { return 0; } // Get params: cWorld * self = nullptr; int BlockX = 0; int BlockZ = 0; L.GetStackValues(1, self, BlockX, BlockZ); // Call the implementation: L.LogStackTrace(); FLOGWARN("cWorld:GetHeight is DEPRECATED, use TryGetHeight instead"); auto Height = self->GetHeight(BlockX, BlockZ); L.Push(Height.value_or(0)); return 1; } void cManualBindings::BindWorld(lua_State * tolua_S) { tolua_beginmodule(tolua_S, nullptr); tolua_beginmodule(tolua_S, "cWorld"); tolua_function(tolua_S, "BroadcastBlockAction", tolua_cWorld_BroadcastBlockAction); tolua_function(tolua_S, "BroadcastSoundEffect", tolua_cWorld_BroadcastSoundEffect); tolua_function(tolua_S, "BroadcastSoundParticleEffect", tolua_cWorld_BroadcastSoundParticleEffect); tolua_function(tolua_S, "BroadcastParticleEffect", tolua_cWorld_BroadcastParticleEffect); tolua_function(tolua_S, "ChunkStay", tolua_cWorld_ChunkStay); tolua_function(tolua_S, "DoExplosionAt", tolua_cWorld_DoExplosionAt); tolua_function(tolua_S, "DoWithBeaconAt", DoWithBlockEntityAt); tolua_function(tolua_S, "DoWithBedAt", DoWithBlockEntityAt); tolua_function(tolua_S, "DoWithBlockEntityAt", DoWithBlockEntityAt); tolua_function(tolua_S, "DoWithBrewingstandAt", DoWithBlockEntityAt); tolua_function(tolua_S, "DoWithChestAt", DoWithBlockEntityAt); tolua_function(tolua_S, "DoWithCommandBlockAt", DoWithBlockEntityAt); tolua_function(tolua_S, "DoWithDispenserAt", DoWithBlockEntityAt); tolua_function(tolua_S, "DoWithDropSpenserAt", DoWithBlockEntityAt); tolua_function(tolua_S, "DoWithDropperAt", DoWithBlockEntityAt); tolua_function(tolua_S, "DoWithEntityByID", DoWithID); tolua_function(tolua_S, "DoWithFlowerPotAt", DoWithBlockEntityAt); tolua_function(tolua_S, "DoWithFurnaceAt", DoWithBlockEntityAt); tolua_function(tolua_S, "DoWithHopperAt", DoWithBlockEntityAt); tolua_function(tolua_S, "DoWithMobHeadAt", DoWithBlockEntityAt); tolua_function(tolua_S, "DoWithNearestPlayer", tolua_cWorld_DoWithNearestPlayer); tolua_function(tolua_S, "DoWithNoteBlockAt", DoWithBlockEntityAt); tolua_function(tolua_S, "DoWithPlayer", DoWith); tolua_function(tolua_S, "DoWithPlayerByUUID", tolua_cWorld_DoWithPlayerByUUID); tolua_function(tolua_S, "FastSetBlock", tolua_cWorld_FastSetBlock); tolua_function(tolua_S, "FindAndDoWithPlayer", DoWith); tolua_function(tolua_S, "ForEachBlockEntityInChunk", ForEachBlockEntityInChunk); tolua_function(tolua_S, "ForEachBrewingstandInChunk", ForEachBlockEntityInChunk); tolua_function(tolua_S, "ForEachChestInChunk", ForEachBlockEntityInChunk); tolua_function(tolua_S, "ForEachEntity", ForEach); tolua_function(tolua_S, "ForEachEntityInBox", ForEachInBox); tolua_function(tolua_S, "ForEachEntityInChunk", tolua_cWorld_ForEachEntityInChunk); tolua_function(tolua_S, "ForEachFurnaceInChunk", ForEachBlockEntityInChunk); tolua_function(tolua_S, "ForEachLoadedChunk", tolua_cWorld_ForEachLoadedChunk); tolua_function(tolua_S, "ForEachPlayer", ForEach); tolua_function(tolua_S, "GetBlock", tolua_cWorld_GetBlock); tolua_function(tolua_S, "GetBlockBlockLight", tolua_cWorld_GetBlockBlockLight); tolua_function(tolua_S, "GetBlockInfo", tolua_cWorld_GetBlockInfo); tolua_function(tolua_S, "GetBlockMeta", tolua_cWorld_GetBlockMeta); tolua_function(tolua_S, "GetBlockSkyLight", tolua_cWorld_GetBlockSkyLight); tolua_function(tolua_S, "GetBlockTypeMeta", tolua_cWorld_GetBlockTypeMeta); tolua_function(tolua_S, "GetHeight", tolua_cWorld_GetHeight); tolua_function(tolua_S, "GetSignLines", tolua_cWorld_GetSignLines); tolua_function(tolua_S, "GetTimeOfDay", tolua_cWorld_GetTimeOfDay); tolua_function(tolua_S, "GetWorldAge", tolua_cWorld_GetWorldAge); tolua_function(tolua_S, "PrepareChunk", tolua_cWorld_PrepareChunk); tolua_function(tolua_S, "QueueTask", tolua_cWorld_QueueTask); tolua_function(tolua_S, "ScheduleTask", tolua_cWorld_ScheduleTask); tolua_function(tolua_S, "SetBlock", tolua_cWorld_SetBlock); tolua_function(tolua_S, "SetBlockMeta", tolua_cWorld_SetBlockMeta); tolua_function(tolua_S, "SetSignLines", tolua_cWorld_SetSignLines); tolua_function(tolua_S, "SetTimeOfDay", tolua_cWorld_SetTimeOfDay); tolua_function(tolua_S, "SpawnSplitExperienceOrbs", tolua_cWorld_SpawnSplitExperienceOrbs); tolua_function(tolua_S, "TryGetHeight", tolua_cWorld_TryGetHeight); tolua_endmodule(tolua_S); tolua_endmodule(tolua_S); } ================================================ FILE: src/Bindings/Plugin.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "Plugin.h" cPlugin::cPlugin(const AString & a_FolderName) : m_Status(cPluginManager::psDisabled), m_Name(a_FolderName), m_Version(0), m_FolderName(a_FolderName) { } cPlugin::~cPlugin() { LOGD("Destroying plugin \"%s\".", m_Name.c_str()); } void cPlugin::Unload(void) { auto pm = cPluginManager::Get(); pm->RemovePluginCommands(this); pm->RemovePluginConsoleCommands(this); pm->RemoveHooks(this); OnDisable(); m_Status = cPluginManager::psUnloaded; m_LoadError.clear(); } AString cPlugin::GetLocalFolder(void) const { return "Plugins" + cFile::GetPathSeparator() + m_FolderName; } void cPlugin::SetLoadError(const AString & a_LoadError) { m_Status = cPluginManager::psError; m_LoadError = a_LoadError; } ================================================ FILE: src/Bindings/Plugin.h ================================================ // Plugin.h // Declares the cPlugin class representing an interface that a plugin implementation needs to expose, with some helping functions #pragma once #include "../Defines.h" #include "PluginManager.h" // tolua_begin class cPlugin { public: // tolua_end /** Creates a new instance. a_FolderName is the name of the folder (in the Plugins folder) from which the plugin is loaded. The plugin's name defaults to the folder name. */ cPlugin(const AString & a_FolderName); virtual ~cPlugin(); /** Called as the last call into the plugin before it is unloaded. */ virtual void OnDisable(void) {} /** Loads and initializes the plugin. Sets m_Status to psLoaded or psError accordingly. Returns true if the initialization succeeded, false otherwise. */ virtual bool Load(void) = 0; /** Unloads the plugin. Sets m_Status to psDisabled. The default implementation removes the plugin's associations with cPluginManager, descendants should call it as well. */ virtual void Unload(void); // Called each tick virtual void Tick(float a_Dt) = 0; /** Calls the specified hook with the params given. Returns the bool that the hook callback returns. */ virtual bool OnBlockSpread (cWorld & a_World, int a_BlockX, int a_BlockY, int a_BlockZ, eSpreadSource a_Source) = 0; virtual bool OnBlockToPickups (cWorld & a_World, Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, const cBlockEntity * a_BlockEntity, const cEntity * a_Digger, const cItem * a_Tool, cItems & a_Pickups) = 0; virtual bool OnBrewingCompleting (cWorld & a_World, cBrewingstandEntity & a_BrewingstandEntity) = 0; virtual bool OnBrewingCompleted (cWorld & a_World, cBrewingstandEntity & a_BrewingstandEntity) = 0; virtual bool OnChat (cPlayer & a_Player, AString & a_Message) = 0; virtual bool OnChunkAvailable (cWorld & a_World, int a_ChunkX, int a_ChunkZ) = 0; virtual bool OnChunkGenerated (cWorld & a_World, int a_ChunkX, int a_ChunkZ, cChunkDesc * a_ChunkDesc) = 0; virtual bool OnChunkGenerating (cWorld & a_World, int a_ChunkX, int a_ChunkZ, cChunkDesc * a_ChunkDesc) = 0; virtual bool OnChunkUnloaded (cWorld & a_World, int a_ChunkX, int a_ChunkZ) = 0; virtual bool OnChunkUnloading (cWorld & a_World, int a_ChunkX, int a_ChunkZ) = 0; virtual bool OnCollectingPickup (cPlayer & a_Player, cPickup & a_Pickup) = 0; virtual bool OnCraftingNoRecipe (cPlayer & a_Player, cCraftingGrid & a_Grid, cCraftingRecipe & a_Recipe) = 0; virtual bool OnDisconnect (cClientHandle & a_Client, const AString & a_Reason) = 0; virtual bool OnEntityAddEffect (cEntity & a_Entity, int a_EffectType, int a_EffectDurationTicks, int a_EffectIntensity, double a_DistanceModifier) = 0; virtual bool OnEntityTeleport (cEntity & a_Entity, const Vector3d & a_OldPosition, const Vector3d & a_NewPosition) = 0; virtual bool OnEntityChangingWorld (cEntity & a_Entity, cWorld & a_World) = 0; virtual bool OnEntityChangedWorld (cEntity & a_Entity, cWorld & a_World) = 0; virtual bool OnExecuteCommand (cPlayer * a_Player, const AStringVector & a_Split, const AString & a_EntireCommand, cPluginManager::CommandResult & a_Result) = 0; virtual bool OnExploded (cWorld & a_World, double a_ExplosionSize, bool a_CanCauseFire, double a_X, double a_Y, double a_Z, eExplosionSource a_Source, void * a_SourceData) = 0; virtual bool OnExploding (cWorld & a_World, double & a_ExplosionSize, bool & a_CanCauseFire, double a_X, double a_Y, double a_Z, eExplosionSource a_Source, void * a_SourceData) = 0; virtual bool OnHandshake (cClientHandle & a_Client, const AString & a_Username) = 0; virtual bool OnHopperPullingItem (cWorld & a_World, cHopperEntity & a_Hopper, int a_DstSlotNum, cBlockEntityWithItems & a_SrcEntity, int a_SrcSlotNum) = 0; virtual bool OnHopperPushingItem (cWorld & a_World, cHopperEntity & a_Hopper, int a_SrcSlotNum, cBlockEntityWithItems & a_DstEntity, int a_DstSlotNum) = 0; virtual bool OnDropSpense (cWorld & a_World, cDropSpenserEntity & a_DropSpenser, int a_SlotNum) = 0; virtual bool OnKilled (cEntity & a_Victim, TakeDamageInfo & a_TDI, AString & a_DeathMessage) = 0; virtual bool OnKilling (cEntity & a_Victim, cEntity * a_Killer, TakeDamageInfo & a_TDI) = 0; virtual bool OnLogin (cClientHandle & a_Client, UInt32 a_ProtocolVersion, const AString & a_Username) = 0; virtual bool OnLoginForge (cClientHandle & a_Client, const AStringMap & a_Mods) = 0; virtual bool OnPlayerAnimation (cPlayer & a_Player, int a_Animation) = 0; virtual bool OnPlayerBreakingBlock (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) = 0; virtual bool OnPlayerBrokenBlock (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) = 0; virtual bool OnPlayerDestroyed (cPlayer & a_Player) = 0; virtual bool OnPlayerEating (cPlayer & a_Player) = 0; virtual bool OnPlayerFished (cPlayer & a_Player, const cItems & a_Reward, const int ExperienceAmount) = 0; virtual bool OnPlayerFishing (cPlayer & a_Player, cItems & a_Reward, int & ExperienceAmount) = 0; virtual bool OnPlayerFoodLevelChange (cPlayer & a_Player, int a_NewFoodLevel) = 0; virtual bool OnPlayerJoined (cPlayer & a_Player) = 0; virtual bool OnPlayerLeftClick (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, char a_Status) = 0; virtual bool OnPlayerMoving (cPlayer & a_Player, const Vector3d & a_OldPosition, const Vector3d & a_NewPosition, bool a_PreviousIsOnGround) = 0; virtual bool OnPlayerOpeningWindow (cPlayer & a_Player, cWindow & a_Window) = 0; virtual bool OnPlayerPlacedBlock (cPlayer & a_Player, const sSetBlock & a_BlockChange) = 0; virtual bool OnPlayerPlacingBlock (cPlayer & a_Player, const sSetBlock & a_BlockChange) = 0; virtual bool OnPlayerCrouched (cPlayer & a_Player) = 0; virtual bool OnPlayerRightClick (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) = 0; virtual bool OnPlayerRightClickingEntity(cPlayer & a_Player, cEntity & a_Entity) = 0; virtual bool OnPlayerShooting (cPlayer & a_Player) = 0; virtual bool OnPlayerSpawned (cPlayer & a_Player) = 0; virtual bool OnPlayerTossingItem (cPlayer & a_Player) = 0; virtual bool OnPlayerUsedBlock (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) = 0; virtual bool OnPlayerUsedItem (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) = 0; virtual bool OnPlayerUsingBlock (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) = 0; virtual bool OnPlayerUsingItem (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) = 0; virtual bool OnPluginMessage (cClientHandle & a_Client, const AString & a_Channel, ContiguousByteBufferView a_Message) = 0; virtual bool OnPluginsLoaded (void) = 0; virtual bool OnPostCrafting (cPlayer & a_Player, cCraftingGrid & a_Grid, cCraftingRecipe & a_Recipe) = 0; virtual bool OnPreCrafting (cPlayer & a_Player, cCraftingGrid & a_Grid, cCraftingRecipe & a_Recipe) = 0; virtual bool OnProjectileHitBlock (cProjectileEntity & a_Projectile, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_Face, const Vector3d & a_BlockHitPos) = 0; virtual bool OnProjectileHitEntity (cProjectileEntity & a_Projectile, cEntity & a_HitEntity) = 0; virtual bool OnServerPing (cClientHandle & a_ClientHandle, AString & a_ServerDescription, int & a_OnlinePlayersCount, int & a_MaxPlayersCount, AString & a_Favicon) = 0; virtual bool OnSpawnedEntity (cWorld & a_World, cEntity & a_Entity) = 0; virtual bool OnSpawnedMonster (cWorld & a_World, cMonster & a_Monster) = 0; virtual bool OnSpawningEntity (cWorld & a_World, cEntity & a_Entity) = 0; virtual bool OnSpawningMonster (cWorld & a_World, cMonster & a_Monster) = 0; virtual bool OnTakeDamage (cEntity & a_Receiver, TakeDamageInfo & a_TakeDamageInfo) = 0; virtual bool OnUpdatedSign (cWorld & a_World, int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4, cPlayer * a_Player) = 0; virtual bool OnUpdatingSign (cWorld & a_World, int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4, cPlayer * a_Player) = 0; virtual bool OnWeatherChanged (cWorld & a_World) = 0; virtual bool OnWeatherChanging (cWorld & a_World, eWeather & a_NewWeather) = 0; virtual bool OnWorldStarted (cWorld & a_World) = 0; virtual bool OnWorldTick (cWorld & a_World, std::chrono::milliseconds a_Dt, std::chrono::milliseconds a_LastTickDurationMSec) = 0; // tolua_begin const AString & GetName(void) const { return m_Name; } void SetName(const AString & a_Name) { m_Name = a_Name; } int GetVersion(void) const { return m_Version; } void SetVersion(int a_Version) { m_Version = a_Version; } /** Returns the name of the folder (in the Plugins folder) from which the plugin is loaded. */ const AString & GetFolderName(void) const {return m_FolderName; } /** Returns the folder relative to the MCS Executable, from which the plugin is loaded. */ AString GetLocalFolder(void) const; /** Returns the error encountered while loading the plugin. Only valid if m_Status == psError. */ const AString & GetLoadError(void) const { return m_LoadError; } cPluginManager::ePluginStatus GetStatus(void) const { return m_Status; } bool IsLoaded(void) const { return (m_Status == cPluginManager::psLoaded); } // tolua_end // Needed for ManualBindings' tolua_ForEach<> static const char * GetClassStatic(void) { return "cPlugin"; } protected: friend class cPluginManager; cPluginManager::ePluginStatus m_Status; /** The name of the plugin, used to identify the plugin in the system and for inter-plugin calls. */ AString m_Name; int m_Version; /** Name of the folder (in the Plugins folder) from which the plugin is loaded. */ AString m_FolderName; /** The error encountered while loading the plugin. Only valid if m_Status == psError. */ AString m_LoadError; /** Sets m_LoadError to the specified string and m_Status to psError. */ void SetLoadError(const AString & a_LoadError); }; // tolua_export ================================================ FILE: src/Bindings/PluginLua.cpp ================================================ // PluginLua.cpp // Implements the cPluginLua class representing a plugin written in Lua #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "Defines.h" #include "Entities/Minecart.h" #ifdef __APPLE__ #define LUA_USE_MACOSX #else #define LUA_USE_POSIX #endif #include "PluginLua.h" #include "../CommandOutput.h" #include "PluginManager.h" #include "../Item.h" #include "../Root.h" #include "../WebAdmin.h" extern "C" { #include "lua/src/lauxlib.h" } #undef TOLUA_TEMPLATE_BIND #include "tolua++/include/tolua++.h" //////////////////////////////////////////////////////////////////////////////// // cPluginLua: cPluginLua::cPluginLua(const AString & a_PluginDirectory, cDeadlockDetect & a_DeadlockDetect) : cPlugin(a_PluginDirectory), m_LuaState(fmt::format(FMT_STRING("plugin {}"), a_PluginDirectory)), m_DeadlockDetect(a_DeadlockDetect) { m_LuaState.TrackInDeadlockDetect(a_DeadlockDetect); } cPluginLua::~cPluginLua() { Close(); m_LuaState.UntrackInDeadlockDetect(m_DeadlockDetect); } void cPluginLua::Close(void) { cOperation op(*this); // If already closed, bail out: if (!op().IsValid()) { ASSERT(m_HookMap.empty()); return; } // Remove the web tabs: ClearWebTabs(); // Release all the references in the hook map: m_HookMap.clear(); // Close the Lua engine: op().Close(); } bool cPluginLua::Load(void) { cOperation op(*this); if (!op().IsValid()) { m_LuaState.Create(); m_LuaState.RegisterAPILibs(); // Inject the identification global variables into the state: lua_pushlightuserdata(m_LuaState, this); lua_setglobal(m_LuaState, LUA_PLUGIN_INSTANCE_VAR_NAME); // Add the plugin's folder to the package.path and package.cpath variables (#693): m_LuaState.AddPackagePath("path", GetLocalFolder() + "/?.lua"); #ifdef _WIN32 m_LuaState.AddPackagePath("cpath", GetLocalFolder() + "\\?.dll"); #else m_LuaState.AddPackagePath("cpath", GetLocalFolder() + "/?.so"); #endif tolua_pushusertype(m_LuaState, this, "cPluginLua"); lua_setglobal(m_LuaState, "g_Plugin"); } std::string PluginPath = GetLocalFolder() + "/"; // List all Lua files for this plugin. Info.lua has a special handling - make it the last to load: AStringVector Files = cFile::GetFolderContents(PluginPath); AStringVector LuaFiles; bool HasInfoLua = false; for (AStringVector::const_iterator itr = Files.begin(), end = Files.end(); itr != end; ++itr) { size_t ExtensionStart = itr->find_last_of('.'); if ((ExtensionStart != std::string::npos) && (itr->substr(ExtensionStart) == ".lua")) { if (*itr == "Info.lua") { HasInfoLua = true; } else { LuaFiles.push_back(*itr); } } } std::sort(LuaFiles.begin(), LuaFiles.end()); // Warn if there are no Lua files in the plugin folder: if (LuaFiles.empty()) { SetLoadError("No lua files found, plugin is probably missing."); LOGWARNING("No lua files found: plugin %s is missing.", GetName().c_str()); Close(); return false; } // Load all files in the list, including the Info.lua as last, if it exists: for (AStringVector::const_iterator itr = LuaFiles.begin(), end = LuaFiles.end(); itr != end; ++itr) { AString Path = PluginPath + *itr; if (!m_LuaState.LoadFile(Path)) { SetLoadError(fmt::format(FMT_STRING("Failed to load file {}."), *itr)); Close(); return false; } } // for itr - Files[] if (HasInfoLua) { AString Path = PluginPath + "Info.lua"; if (!m_LuaState.LoadFile(Path)) { SetLoadError("Failed to load file Info.lua."); Close(); return false; } } // Call the Initialize function: bool res = false; if (!m_LuaState.Call("Initialize", this, cLuaState::Return, res)) { SetLoadError("Cannot call the Initialize() function."); LOGWARNING("Error in plugin %s: Cannot call the Initialize() function. Plugin is temporarily disabled.", GetName().c_str()); Close(); return false; } if (!res) { SetLoadError("The Initialize() function failed."); LOGINFO("Plugin %s: Initialize() call failed, plugin is temporarily disabled.", GetName().c_str()); Close(); return false; } m_Status = cPluginManager::psLoaded; return true; } void cPluginLua::Unload(void) { ClearWebTabs(); Super::Unload(); Close(); } void cPluginLua::OnDisable(void) { cOperation op(*this); if (!op().HasFunction("OnDisable")) { return; } op().Call("OnDisable"); } void cPluginLua::Tick(float a_Dt) { CallSimpleHooks(cPluginManager::HOOK_TICK, a_Dt); } bool cPluginLua::OnBlockSpread(cWorld & a_World, int a_BlockX, int a_BlockY, int a_BlockZ, eSpreadSource a_Source) { return CallSimpleHooks(cPluginManager::HOOK_BLOCK_SPREAD, &a_World, a_BlockX, a_BlockY, a_BlockZ, a_Source); } bool cPluginLua::OnBlockToPickups( cWorld & a_World, Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, const cBlockEntity * a_BlockEntity, const cEntity * a_Digger, const cItem * a_Tool, cItems & a_Pickups ) { // TODO: Change the hook signature to reflect the real parameters to this function, once we are allowed to make breaking API changes return CallSimpleHooks( cPluginManager::HOOK_BLOCK_TO_PICKUPS, &a_World, a_Digger, a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, a_BlockType, a_BlockMeta, &a_Pickups ); } bool cPluginLua::OnBrewingCompleted(cWorld & a_World, cBrewingstandEntity & a_Brewingstand) { return CallSimpleHooks(cPluginManager::HOOK_BREWING_COMPLETED, &a_World, &a_Brewingstand); } bool cPluginLua::OnBrewingCompleting(cWorld & a_World, cBrewingstandEntity & a_Brewingstand) { return CallSimpleHooks(cPluginManager::HOOK_BREWING_COMPLETING, &a_World, &a_Brewingstand); } bool cPluginLua::OnChat(cPlayer & a_Player, AString & a_Message) { cOperation op(*this); if (!op().IsValid()) { return false; } bool res = false; auto & hooks = m_HookMap[cPluginManager::HOOK_CHAT]; for (auto & hook: hooks) { hook->Call(&a_Player, a_Message, cLuaState::Return, res, a_Message); if (res) { return true; } } return false; } bool cPluginLua::OnChunkAvailable(cWorld & a_World, int a_ChunkX, int a_ChunkZ) { return CallSimpleHooks(cPluginManager::HOOK_CHUNK_AVAILABLE, &a_World, a_ChunkX, a_ChunkZ); } bool cPluginLua::OnChunkGenerated(cWorld & a_World, int a_ChunkX, int a_ChunkZ, cChunkDesc * a_ChunkDesc) { return CallSimpleHooks(cPluginManager::HOOK_CHUNK_GENERATED, &a_World, a_ChunkX, a_ChunkZ, a_ChunkDesc); } bool cPluginLua::OnChunkGenerating(cWorld & a_World, int a_ChunkX, int a_ChunkZ, cChunkDesc * a_ChunkDesc) { return CallSimpleHooks(cPluginManager::HOOK_CHUNK_GENERATING, &a_World, a_ChunkX, a_ChunkZ, a_ChunkDesc); } bool cPluginLua::OnChunkUnloaded(cWorld & a_World, int a_ChunkX, int a_ChunkZ) { return CallSimpleHooks(cPluginManager::HOOK_CHUNK_UNLOADED, &a_World, a_ChunkX, a_ChunkZ); } bool cPluginLua::OnChunkUnloading(cWorld & a_World, int a_ChunkX, int a_ChunkZ) { return CallSimpleHooks(cPluginManager::HOOK_CHUNK_UNLOADING, &a_World, a_ChunkX, a_ChunkZ); } bool cPluginLua::OnCollectingPickup(cPlayer & a_Player, cPickup & a_Pickup) { return CallSimpleHooks(cPluginManager::HOOK_COLLECTING_PICKUP, &a_Player, &a_Pickup); } bool cPluginLua::OnCraftingNoRecipe(cPlayer & a_Player, cCraftingGrid & a_Grid, cCraftingRecipe & a_Recipe) { return CallSimpleHooks(cPluginManager::HOOK_CRAFTING_NO_RECIPE, &a_Player, &a_Grid, &a_Recipe); } bool cPluginLua::OnDisconnect(cClientHandle & a_Client, const AString & a_Reason) { return CallSimpleHooks(cPluginManager::HOOK_DISCONNECT, &a_Client, a_Reason); } bool cPluginLua::OnEntityAddEffect(cEntity & a_Entity, int a_EffectType, int a_EffectDurationTicks, int a_EffectIntensity, double a_DistanceModifier) { return CallSimpleHooks(cPluginManager::HOOK_ENTITY_ADD_EFFECT, &a_Entity, a_EffectType, a_EffectDurationTicks, a_EffectIntensity, a_DistanceModifier); } bool cPluginLua::OnEntityChangingWorld(cEntity & a_Entity, cWorld & a_World) { return CallSimpleHooks(cPluginManager::HOOK_ENTITY_CHANGING_WORLD, &a_Entity, &a_World); } bool cPluginLua::OnEntityChangedWorld(cEntity & a_Entity, cWorld & a_World) { return CallSimpleHooks(cPluginManager::HOOK_ENTITY_CHANGED_WORLD, &a_Entity, &a_World); } bool cPluginLua::OnExecuteCommand(cPlayer * a_Player, const AStringVector & a_Split, const AString & a_EntireCommand, cPluginManager::CommandResult & a_Result) { cOperation op(*this); if (!op().IsValid()) { return false; } bool res = false; auto & hooks = m_HookMap[cPluginManager::HOOK_EXECUTE_COMMAND]; for (auto & hook: hooks) { hook->Call(a_Player, a_Split, a_EntireCommand, cLuaState::Return, res, a_Result); if (res) { return true; } } return false; } bool cPluginLua::OnExploded(cWorld & a_World, double a_ExplosionSize, bool a_CanCauseFire, double a_X, double a_Y, double a_Z, eExplosionSource a_Source, void * a_SourceData) { cOperation op(*this); if (!op().IsValid()) { return false; } bool res = false; auto & hooks = m_HookMap[cPluginManager::HOOK_EXPLODED]; for (auto & hook: hooks) { switch (a_Source) { case esBed: hook->Call(&a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, static_cast (a_SourceData), cLuaState::Return, res); break; case esEnderCrystal: hook->Call(&a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, static_cast (a_SourceData), cLuaState::Return, res); break; case esGhastFireball: hook->Call(&a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, static_cast(a_SourceData), cLuaState::Return, res); break; case esMonster: hook->Call(&a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, static_cast (a_SourceData), cLuaState::Return, res); break; case esOther: hook->Call(&a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, cLuaState::Return, res); break; case esPlugin: hook->Call(&a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, cLuaState::Return, res); break; case esPrimedTNT: hook->Call(&a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, static_cast (a_SourceData), cLuaState::Return, res); break; case esTNTMinecart: hook->Call(&a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, static_cast (a_SourceData), cLuaState::Return, res); break; case esWitherBirth: hook->Call(&a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, static_cast (a_SourceData), cLuaState::Return, res); break; case esWitherSkull: hook->Call(&a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, static_cast (a_SourceData), cLuaState::Return, res); break; case esMax: { ASSERT(!"Invalid explosion source"); return false; } } if (res) { return true; } } return false; } bool cPluginLua::OnExploding(cWorld & a_World, double & a_ExplosionSize, bool & a_CanCauseFire, double a_X, double a_Y, double a_Z, eExplosionSource a_Source, void * a_SourceData) { cOperation op(*this); if (!op().IsValid()) { return false; } bool res = false; auto & hooks = m_HookMap[cPluginManager::HOOK_EXPLODING]; for (auto & hook: hooks) { switch (a_Source) { case esBed: hook->Call(&a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, static_cast (a_SourceData), cLuaState::Return, res, a_CanCauseFire, a_ExplosionSize); break; case esEnderCrystal: hook->Call(&a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, static_cast (a_SourceData), cLuaState::Return, res, a_CanCauseFire, a_ExplosionSize); break; case esGhastFireball: hook->Call(&a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, static_cast(a_SourceData), cLuaState::Return, res, a_CanCauseFire, a_ExplosionSize); break; case esMonster: hook->Call(&a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, static_cast (a_SourceData), cLuaState::Return, res, a_CanCauseFire, a_ExplosionSize); break; case esOther: hook->Call(&a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, cLuaState::Return, res, a_CanCauseFire, a_ExplosionSize); break; case esPlugin: hook->Call(&a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, cLuaState::Return, res, a_CanCauseFire, a_ExplosionSize); break; case esPrimedTNT: hook->Call(&a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, static_cast (a_SourceData), cLuaState::Return, res, a_CanCauseFire, a_ExplosionSize); break; case esTNTMinecart: hook->Call(&a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, static_cast (a_SourceData), cLuaState::Return, res, a_CanCauseFire, a_ExplosionSize); break; case esWitherBirth: hook->Call(&a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, static_cast (a_SourceData), cLuaState::Return, res, a_CanCauseFire, a_ExplosionSize); break; case esWitherSkull: hook->Call(&a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, static_cast (a_SourceData), cLuaState::Return, res, a_CanCauseFire, a_ExplosionSize); break; case esMax: { ASSERT(!"Invalid explosion source"); return false; } } if (res) { return true; } } return false; } bool cPluginLua::OnHandshake(cClientHandle & a_Client, const AString & a_Username) { return CallSimpleHooks(cPluginManager::HOOK_HANDSHAKE, &a_Client, a_Username); } bool cPluginLua::OnHopperPullingItem(cWorld & a_World, cHopperEntity & a_Hopper, int a_DstSlotNum, cBlockEntityWithItems & a_SrcEntity, int a_SrcSlotNum) { return CallSimpleHooks(cPluginManager::HOOK_HOPPER_PULLING_ITEM, &a_World, &a_Hopper, a_DstSlotNum, &a_SrcEntity, a_SrcSlotNum); } bool cPluginLua::OnHopperPushingItem(cWorld & a_World, cHopperEntity & a_Hopper, int a_SrcSlotNum, cBlockEntityWithItems & a_DstEntity, int a_DstSlotNum) { return CallSimpleHooks(cPluginManager::HOOK_HOPPER_PUSHING_ITEM, &a_World, &a_Hopper, a_SrcSlotNum, &a_DstEntity, a_DstSlotNum); } bool cPluginLua::OnDropSpense(cWorld & a_World, cDropSpenserEntity & a_DropSpenser, int a_SlotNum) { return CallSimpleHooks(cPluginManager::HOOK_DROPSPENSE, &a_World, &a_DropSpenser, a_SlotNum); } bool cPluginLua::OnKilled(cEntity & a_Victim, TakeDamageInfo & a_TDI, AString & a_DeathMessage) { cOperation op(*this); if (!op().IsValid()) { return false; } bool res = false; auto & hooks = m_HookMap[cPluginManager::HOOK_KILLED]; for (auto & hook: hooks) { hook->Call(&a_Victim, &a_TDI, a_DeathMessage, cLuaState::Return, res, a_DeathMessage); if (res) { return true; } } return false; } bool cPluginLua::OnKilling(cEntity & a_Victim, cEntity * a_Killer, TakeDamageInfo & a_TDI) { return CallSimpleHooks(cPluginManager::HOOK_KILLING, &a_Victim, a_Killer, &a_TDI); } bool cPluginLua::OnLogin(cClientHandle & a_Client, UInt32 a_ProtocolVersion, const AString & a_Username) { return CallSimpleHooks(cPluginManager::HOOK_LOGIN, &a_Client, a_ProtocolVersion, a_Username); } bool cPluginLua::OnLoginForge(cClientHandle & a_Client, const AStringMap & a_Mods) { return CallSimpleHooks(cPluginManager::HOOK_LOGIN_FORGE, &a_Client, a_Mods); } bool cPluginLua::OnPlayerAnimation(cPlayer & a_Player, int a_Animation) { return CallSimpleHooks(cPluginManager::HOOK_PLAYER_ANIMATION, &a_Player, a_Animation); } bool cPluginLua::OnPlayerBreakingBlock(cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) { return CallSimpleHooks(cPluginManager::HOOK_PLAYER_BREAKING_BLOCK, &a_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_BlockType, a_BlockMeta); } bool cPluginLua::OnPlayerBrokenBlock(cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) { return CallSimpleHooks(cPluginManager::HOOK_PLAYER_BROKEN_BLOCK, &a_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_BlockType, a_BlockMeta); } bool cPluginLua::OnPlayerDestroyed(cPlayer & a_Player) { return CallSimpleHooks(cPluginManager::HOOK_PLAYER_DESTROYED, &a_Player); } bool cPluginLua::OnPlayerEating(cPlayer & a_Player) { return CallSimpleHooks(cPluginManager::HOOK_PLAYER_EATING, &a_Player); } bool cPluginLua::OnPlayerFoodLevelChange(cPlayer & a_Player, int a_NewFoodLevel) { return CallSimpleHooks(cPluginManager::HOOK_PLAYER_FOOD_LEVEL_CHANGE, &a_Player, a_NewFoodLevel); } bool cPluginLua::OnPlayerFished(cPlayer & a_Player, const cItems & a_Reward, const int ExperienceAmount) { cItems reward(a_Reward); return CallSimpleHooks(cPluginManager::HOOK_PLAYER_FISHED, &a_Player, &reward, ExperienceAmount); } bool cPluginLua::OnPlayerFishing(cPlayer & a_Player, cItems & a_Reward, int & ExperienceAmount) { return CallSimpleHooks(cPluginManager::HOOK_PLAYER_FISHING, &a_Player, &a_Reward, &ExperienceAmount); } bool cPluginLua::OnPlayerJoined(cPlayer & a_Player) { return CallSimpleHooks(cPluginManager::HOOK_PLAYER_JOINED, &a_Player); } bool cPluginLua::OnPlayerLeftClick(cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, char a_Status) { return CallSimpleHooks(cPluginManager::HOOK_PLAYER_LEFT_CLICK, &a_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_Status); } bool cPluginLua::OnPlayerMoving(cPlayer & a_Player, const Vector3d & a_OldPosition, const Vector3d & a_NewPosition, bool a_PreviousIsOnGround) { return CallSimpleHooks(cPluginManager::HOOK_PLAYER_MOVING, &a_Player, a_OldPosition, a_NewPosition, a_PreviousIsOnGround); } bool cPluginLua::OnEntityTeleport(cEntity & a_Entity, const Vector3d & a_OldPosition, const Vector3d & a_NewPosition) { return CallSimpleHooks(cPluginManager::HOOK_ENTITY_TELEPORT, &a_Entity, a_OldPosition, a_NewPosition); } bool cPluginLua::OnPlayerOpeningWindow(cPlayer & a_Player, cWindow & a_Window) { return CallSimpleHooks(cPluginManager::HOOK_PLAYER_OPENING_WINDOW, &a_Player, &a_Window); } bool cPluginLua::OnPlayerPlacedBlock(cPlayer & a_Player, const sSetBlock & a_BlockChange) { return CallSimpleHooks(cPluginManager::HOOK_PLAYER_PLACED_BLOCK, &a_Player, a_BlockChange.GetX(), a_BlockChange.GetY(), a_BlockChange.GetZ(), a_BlockChange.m_BlockType, a_BlockChange.m_BlockMeta ); } bool cPluginLua::OnPlayerPlacingBlock(cPlayer & a_Player, const sSetBlock & a_BlockChange) { return CallSimpleHooks(cPluginManager::HOOK_PLAYER_PLACING_BLOCK, &a_Player, a_BlockChange.GetX(), a_BlockChange.GetY(), a_BlockChange.GetZ(), a_BlockChange.m_BlockType, a_BlockChange.m_BlockMeta ); } bool cPluginLua::OnPlayerCrouched(cPlayer & a_Player) { return CallSimpleHooks(cPluginManager::HOOK_PLAYER_CROUCHED, &a_Player); } bool cPluginLua::OnPlayerRightClick(cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) { return CallSimpleHooks(cPluginManager::HOOK_PLAYER_RIGHT_CLICK, &a_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ); } bool cPluginLua::OnPlayerRightClickingEntity(cPlayer & a_Player, cEntity & a_Entity) { return CallSimpleHooks(cPluginManager::HOOK_PLAYER_RIGHT_CLICKING_ENTITY, &a_Player, &a_Entity); } bool cPluginLua::OnPlayerShooting(cPlayer & a_Player) { return CallSimpleHooks(cPluginManager::HOOK_PLAYER_SHOOTING, &a_Player); } bool cPluginLua::OnPlayerSpawned(cPlayer & a_Player) { return CallSimpleHooks(cPluginManager::HOOK_PLAYER_SPAWNED, &a_Player); } bool cPluginLua::OnPlayerTossingItem(cPlayer & a_Player) { return CallSimpleHooks(cPluginManager::HOOK_PLAYER_TOSSING_ITEM, &a_Player); } bool cPluginLua::OnPlayerUsedBlock(cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) { return CallSimpleHooks(cPluginManager::HOOK_PLAYER_USED_BLOCK, &a_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, a_BlockType, a_BlockMeta); } bool cPluginLua::OnPlayerUsedItem(cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) { return CallSimpleHooks(cPluginManager::HOOK_PLAYER_USED_ITEM, &a_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ); } bool cPluginLua::OnPlayerUsingBlock(cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) { return CallSimpleHooks(cPluginManager::HOOK_PLAYER_USING_BLOCK, &a_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, a_BlockType, a_BlockMeta); } bool cPluginLua::OnPlayerUsingItem(cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) { return CallSimpleHooks(cPluginManager::HOOK_PLAYER_USING_ITEM, &a_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ); } bool cPluginLua::OnPluginMessage(cClientHandle & a_Client, const AString & a_Channel, const ContiguousByteBufferView a_Message) { return CallSimpleHooks(cPluginManager::HOOK_PLUGIN_MESSAGE, &a_Client, a_Channel, a_Message); } bool cPluginLua::OnPluginsLoaded(void) { cOperation op(*this); if (!op().IsValid()) { return false; } bool res = false; auto & hooks = m_HookMap[cPluginManager::HOOK_PLUGINS_LOADED]; for (auto & hook: hooks) { bool ret = false; hook->Call(cLuaState::Return, ret); res = res || ret; } return res; } bool cPluginLua::OnPostCrafting(cPlayer & a_Player, cCraftingGrid & a_Grid, cCraftingRecipe & a_Recipe) { return CallSimpleHooks(cPluginManager::HOOK_POST_CRAFTING, &a_Player, &a_Grid, &a_Recipe); } bool cPluginLua::OnPreCrafting(cPlayer & a_Player, cCraftingGrid & a_Grid, cCraftingRecipe & a_Recipe) { return CallSimpleHooks(cPluginManager::HOOK_PRE_CRAFTING, &a_Player, &a_Grid, &a_Recipe); } bool cPluginLua::OnProjectileHitBlock(cProjectileEntity & a_Projectile, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_Face, const Vector3d & a_BlockHitPos) { return CallSimpleHooks(cPluginManager::HOOK_PROJECTILE_HIT_BLOCK, &a_Projectile, a_BlockX, a_BlockY, a_BlockZ, a_Face, a_BlockHitPos); } bool cPluginLua::OnProjectileHitEntity(cProjectileEntity & a_Projectile, cEntity & a_HitEntity) { return CallSimpleHooks(cPluginManager::HOOK_PROJECTILE_HIT_ENTITY, &a_Projectile, &a_HitEntity); } bool cPluginLua::OnServerPing(cClientHandle & a_ClientHandle, AString & a_ServerDescription, int & a_OnlinePlayersCount, int & a_MaxPlayersCount, AString & a_Favicon) { cOperation op(*this); if (!op().IsValid()) { return false; } bool res = false; auto & hooks = m_HookMap[cPluginManager::HOOK_SERVER_PING]; for (auto & hook: hooks) { hook->Call(&a_ClientHandle, a_ServerDescription, a_OnlinePlayersCount, a_MaxPlayersCount, a_Favicon, cLuaState::Return, res, a_ServerDescription, a_OnlinePlayersCount, a_MaxPlayersCount, a_Favicon); if (res) { return true; } } return false; } bool cPluginLua::OnSpawnedEntity(cWorld & a_World, cEntity & a_Entity) { return CallSimpleHooks(cPluginManager::HOOK_SPAWNED_ENTITY, &a_World, &a_Entity); } bool cPluginLua::OnSpawnedMonster(cWorld & a_World, cMonster & a_Monster) { return CallSimpleHooks(cPluginManager::HOOK_SPAWNED_MONSTER, &a_World, &a_Monster); } bool cPluginLua::OnSpawningEntity(cWorld & a_World, cEntity & a_Entity) { return CallSimpleHooks(cPluginManager::HOOK_SPAWNING_ENTITY, &a_World, &a_Entity); } bool cPluginLua::OnSpawningMonster(cWorld & a_World, cMonster & a_Monster) { return CallSimpleHooks(cPluginManager::HOOK_SPAWNING_MONSTER, &a_World, &a_Monster); } bool cPluginLua::OnTakeDamage(cEntity & a_Receiver, TakeDamageInfo & a_TDI) { return CallSimpleHooks(cPluginManager::HOOK_TAKE_DAMAGE, &a_Receiver, &a_TDI); } bool cPluginLua::OnUpdatedSign( cWorld & a_World, int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4, cPlayer * a_Player ) { return CallSimpleHooks(cPluginManager::HOOK_UPDATED_SIGN, &a_World, a_BlockX, a_BlockY, a_BlockZ, a_Line1, a_Line2, a_Line3, a_Line4, a_Player); } bool cPluginLua::OnUpdatingSign( cWorld & a_World, int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4, cPlayer * a_Player ) { cOperation op(*this); if (!op().IsValid()) { return false; } bool res = false; auto & hooks = m_HookMap[cPluginManager::HOOK_UPDATING_SIGN]; for (auto & hook: hooks) { hook->Call(&a_World, a_BlockX, a_BlockY, a_BlockZ, a_Line1, a_Line2, a_Line3, a_Line4, a_Player, cLuaState::Return, res, a_Line1, a_Line2, a_Line3, a_Line4); if (res) { return true; } } return false; } bool cPluginLua::OnWeatherChanged(cWorld & a_World) { return CallSimpleHooks(cPluginManager::HOOK_WEATHER_CHANGED, &a_World); } bool cPluginLua::OnWeatherChanging(cWorld & a_World, eWeather & a_NewWeather) { cOperation op(*this); if (!op().IsValid()) { return false; } bool res = false; auto & hooks = m_HookMap[cPluginManager::HOOK_WEATHER_CHANGING]; for (auto & hook: hooks) { hook->Call(&a_World, a_NewWeather, cLuaState::Return, res, a_NewWeather); if (res) { return true; } } return false; } bool cPluginLua::OnWorldStarted(cWorld & a_World) { return CallSimpleHooks(cPluginManager::HOOK_WORLD_STARTED, &a_World); } bool cPluginLua::OnWorldTick(cWorld & a_World, std::chrono::milliseconds a_Dt, std::chrono::milliseconds a_LastTickDurationMSec) { return CallSimpleHooks(cPluginManager::HOOK_WORLD_TICK, &a_World, a_Dt, a_LastTickDurationMSec); } bool cPluginLua::CanAddOldStyleHook(int a_HookType) { const char * FnName = GetHookFnName(a_HookType); if (FnName == nullptr) { // Unknown hook ID LOGWARNING("Plugin %s wants to add an unknown hook ID (%d). The plugin need not work properly.", GetName().c_str(), a_HookType ); m_LuaState.LogStackTrace(); return false; } // Check if the function is available if (m_LuaState.HasFunction(FnName)) { return true; } LOGWARNING("Plugin %s wants to add a hook (%d), but it doesn't provide the callback function \"%s\" for it. The plugin need not work properly.", GetName().c_str(), a_HookType, FnName ); m_LuaState.LogStackTrace(); return false; } const char * cPluginLua::GetHookFnName(int a_HookType) { switch (a_HookType) { case cPluginManager::HOOK_BLOCK_SPREAD: return "OnBlockSpread"; case cPluginManager::HOOK_BLOCK_TO_PICKUPS: return "OnBlockToPickups"; case cPluginManager::HOOK_CHAT: return "OnChat"; case cPluginManager::HOOK_CHUNK_AVAILABLE: return "OnChunkAvailable"; case cPluginManager::HOOK_CHUNK_GENERATED: return "OnChunkGenerated"; case cPluginManager::HOOK_CHUNK_GENERATING: return "OnChunkGenerating"; case cPluginManager::HOOK_CHUNK_UNLOADED: return "OnChunkUnloaded"; case cPluginManager::HOOK_CHUNK_UNLOADING: return "OnChunkUnloading"; case cPluginManager::HOOK_COLLECTING_PICKUP: return "OnCollectingPickup"; case cPluginManager::HOOK_CRAFTING_NO_RECIPE: return "OnCraftingNoRecipe"; case cPluginManager::HOOK_DISCONNECT: return "OnDisconnect"; case cPluginManager::HOOK_PLAYER_ANIMATION: return "OnPlayerAnimation"; case cPluginManager::HOOK_ENTITY_ADD_EFFECT: return "OnEntityAddEffect"; case cPluginManager::HOOK_ENTITY_CHANGING_WORLD: return "OnEntityChangingWorld"; case cPluginManager::HOOK_ENTITY_CHANGED_WORLD: return "OnEntityChangedWorld"; case cPluginManager::HOOK_ENTITY_TELEPORT: return "OnEntityTeleport"; case cPluginManager::HOOK_EXECUTE_COMMAND: return "OnExecuteCommand"; case cPluginManager::HOOK_HANDSHAKE: return "OnHandshake"; case cPluginManager::HOOK_KILLING: return "OnKilling"; case cPluginManager::HOOK_LOGIN: return "OnLogin"; case cPluginManager::HOOK_LOGIN_FORGE: return "OnLoginForge"; case cPluginManager::HOOK_PLAYER_BREAKING_BLOCK: return "OnPlayerBreakingBlock"; case cPluginManager::HOOK_PLAYER_BROKEN_BLOCK: return "OnPlayerBrokenBlock"; case cPluginManager::HOOK_PLAYER_EATING: return "OnPlayerEating"; case cPluginManager::HOOK_PLAYER_JOINED: return "OnPlayerJoined"; case cPluginManager::HOOK_PLAYER_LEFT_CLICK: return "OnPlayerLeftClick"; case cPluginManager::HOOK_PLAYER_MOVING: return "OnPlayerMoving"; case cPluginManager::HOOK_PLAYER_OPENING_WINDOW: return "OnPlayerOpeningWindow"; case cPluginManager::HOOK_PLAYER_PLACED_BLOCK: return "OnPlayerPlacedBlock"; case cPluginManager::HOOK_PLAYER_PLACING_BLOCK: return "OnPlayerPlacingBlock"; case cPluginManager::HOOK_PLAYER_CROUCHED: return "OnPlayerCrouched"; case cPluginManager::HOOK_PLAYER_RIGHT_CLICK: return "OnPlayerRightClick"; case cPluginManager::HOOK_PLAYER_RIGHT_CLICKING_ENTITY: return "OnPlayerRightClickingEntity"; case cPluginManager::HOOK_PLAYER_SHOOTING: return "OnPlayerShooting"; case cPluginManager::HOOK_PLAYER_SPAWNED: return "OnPlayerSpawned"; case cPluginManager::HOOK_PLAYER_TOSSING_ITEM: return "OnPlayerTossingItem"; case cPluginManager::HOOK_PLAYER_USED_BLOCK: return "OnPlayerUsedBlock"; case cPluginManager::HOOK_PLAYER_USED_ITEM: return "OnPlayerUsedItem"; case cPluginManager::HOOK_PLAYER_USING_BLOCK: return "OnPlayerUsingBlock"; case cPluginManager::HOOK_PLAYER_USING_ITEM: return "OnPlayerUsingItem"; case cPluginManager::HOOK_PLUGIN_MESSAGE: return "OnPluginMessage"; case cPluginManager::HOOK_PLUGINS_LOADED: return "OnPluginsLoaded"; case cPluginManager::HOOK_POST_CRAFTING: return "OnPostCrafting"; case cPluginManager::HOOK_PRE_CRAFTING: return "OnPreCrafting"; case cPluginManager::HOOK_SERVER_PING: return "OnServerPing"; case cPluginManager::HOOK_SPAWNED_ENTITY: return "OnSpawnedEntity"; case cPluginManager::HOOK_SPAWNED_MONSTER: return "OnSpawnedMonster"; case cPluginManager::HOOK_SPAWNING_ENTITY: return "OnSpawningEntity"; case cPluginManager::HOOK_SPAWNING_MONSTER: return "OnSpawningMonster"; case cPluginManager::HOOK_TAKE_DAMAGE: return "OnTakeDamage"; case cPluginManager::HOOK_TICK: return "OnTick"; case cPluginManager::HOOK_UPDATED_SIGN: return "OnUpdatedSign"; case cPluginManager::HOOK_UPDATING_SIGN: return "OnUpdatingSign"; case cPluginManager::HOOK_WEATHER_CHANGED: return "OnWeatherChanged"; case cPluginManager::HOOK_WEATHER_CHANGING: return "OnWeatherChanging"; case cPluginManager::HOOK_WORLD_TICK: return "OnWorldTick"; case cPluginManager::HOOK_NUM_HOOKS: { // Satisfy a warning that all enum values should be used in a switch // but don't want a default branch, so that we catch new hooks missing from this list. break; } } // switch (a_Hook) LOGWARNING("Requested name of an unknown hook type function: %d (max is %d)", a_HookType, cPluginManager::HOOK_MAX); ASSERT(!"Unknown hook requested!"); return nullptr; } bool cPluginLua::AddHookCallback(int a_HookType, cLuaState::cCallbackPtr && a_Callback) { m_HookMap[a_HookType].push_back(std::move(a_Callback)); return true; } int cPluginLua::CallFunctionFromForeignState( const AString & a_FunctionName, cLuaState & a_ForeignState, int a_ParamStart, int a_ParamEnd ) { cOperation op(*this); // Call the function: int NumReturns = op().CallFunctionWithForeignParams(a_FunctionName, a_ForeignState, a_ParamStart, a_ParamEnd); if (NumReturns < 0) { // The call has failed, an error has already been output to the log, so just silently bail out with the same error return NumReturns; } // Copy all the return values: int Top = lua_gettop(m_LuaState); int res = a_ForeignState.CopyStackFrom(m_LuaState, Top - NumReturns + 1, Top); // Remove the return values off this stack: if (NumReturns > 0) { lua_pop(m_LuaState, NumReturns); } return res; } void cPluginLua::ClearWebTabs(void) { auto webAdmin = cRoot::Get()->GetWebAdmin(); if (webAdmin != nullptr) // can be nullptr when shutting down the server { webAdmin->RemoveAllPluginWebTabs(m_Name); } } ================================================ FILE: src/Bindings/PluginLua.h ================================================ // PluginLua.h // Declares the cPluginLua class representing a plugin written in Lua #pragma once #include "Plugin.h" #include "LuaState.h" // Names for the global variables through which the plugin is identified in its LuaState #define LUA_PLUGIN_INSTANCE_VAR_NAME "_CuberiteInternal_PluginInstance" // tolua_begin class cPluginLua: public cPlugin { // tolua_end using Super = cPlugin; public: /** A RAII-style mutex lock for accessing the internal LuaState. This will be the only way to retrieve the plugin's LuaState; therefore it directly supports accessing the LuaState of the locked plugin. Usage: cPluginLua::cOperation Op(SomePlugin); Op().Call(...) // Call a function in the plugin's LuaState */ class cOperation { public: cOperation(cPluginLua & a_Plugin) : m_Plugin(a_Plugin), m_Lock(a_Plugin.m_LuaState) { } cLuaState & operator ()(void) { return m_Plugin.m_LuaState; } protected: cPluginLua & m_Plugin; /** RAII lock for the Lua state. */ cLuaState::cLock m_Lock; } ; cPluginLua(const AString & a_PluginDirectory, cDeadlockDetect & a_DeadlockDetect); virtual ~cPluginLua() override; virtual void OnDisable(void) override; virtual bool Load(void) override; virtual void Unload(void) override; virtual void Tick(float a_Dt) override; virtual bool OnBlockSpread (cWorld & a_World, int a_BlockX, int a_BlockY, int a_BlockZ, eSpreadSource a_Source) override; virtual bool OnBlockToPickups (cWorld & a_World, Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, const cBlockEntity * a_BlockEntity, const cEntity * a_Digger, const cItem * a_Tool, cItems & a_Pickups) override; virtual bool OnBrewingCompleting (cWorld & a_World, cBrewingstandEntity & a_BrewingstandEntity) override; virtual bool OnBrewingCompleted (cWorld & a_World, cBrewingstandEntity & a_BrewingstandEntity) override; virtual bool OnChat (cPlayer & a_Player, AString & a_Message) override; virtual bool OnChunkAvailable (cWorld & a_World, int a_ChunkX, int a_ChunkZ) override; virtual bool OnChunkGenerated (cWorld & a_World, int a_ChunkX, int a_ChunkZ, cChunkDesc * a_ChunkDesc) override; virtual bool OnChunkGenerating (cWorld & a_World, int a_ChunkX, int a_ChunkZ, cChunkDesc * a_ChunkDesc) override; virtual bool OnChunkUnloaded (cWorld & a_World, int a_ChunkX, int a_ChunkZ) override; virtual bool OnChunkUnloading (cWorld & a_World, int a_ChunkX, int a_ChunkZ) override; virtual bool OnCollectingPickup (cPlayer & a_Player, cPickup & a_Pickup) override; virtual bool OnCraftingNoRecipe (cPlayer & a_Player, cCraftingGrid & a_Grid, cCraftingRecipe & a_Recipe) override; virtual bool OnDisconnect (cClientHandle & a_Client, const AString & a_Reason) override; virtual bool OnEntityAddEffect (cEntity & a_Entity, int a_EffectType, int a_EffectDurationTicks, int a_EffectIntensity, double a_DistanceModifier) override; virtual bool OnEntityChangingWorld (cEntity & a_Entity, cWorld & a_World) override; virtual bool OnEntityChangedWorld (cEntity & a_Entity, cWorld & a_World) override; virtual bool OnExecuteCommand (cPlayer * a_Player, const AStringVector & a_Split, const AString & a_EntireCommand, cPluginManager::CommandResult & a_Result) override; virtual bool OnExploded (cWorld & a_World, double a_ExplosionSize, bool a_CanCauseFire, double a_X, double a_Y, double a_Z, eExplosionSource a_Source, void * a_SourceData) override; virtual bool OnExploding (cWorld & a_World, double & a_ExplosionSize, bool & a_CanCauseFire, double a_X, double a_Y, double a_Z, eExplosionSource a_Source, void * a_SourceData) override; virtual bool OnHandshake (cClientHandle & a_Client, const AString & a_Username) override; virtual bool OnHopperPullingItem (cWorld & a_World, cHopperEntity & a_Hopper, int a_DstSlotNum, cBlockEntityWithItems & a_SrcEntity, int a_SrcSlotNum) override; virtual bool OnHopperPushingItem (cWorld & a_World, cHopperEntity & a_Hopper, int a_SrcSlotNum, cBlockEntityWithItems & a_DstEntity, int a_DstSlotNum) override; virtual bool OnDropSpense (cWorld & a_World, cDropSpenserEntity & a_DropSpenser, int a_SlotNum) override; virtual bool OnKilled (cEntity & a_Victim, TakeDamageInfo & a_TDI, AString & a_DeathMessage) override; virtual bool OnKilling (cEntity & a_Victim, cEntity * a_Killer, TakeDamageInfo & a_TDI) override; virtual bool OnLogin (cClientHandle & a_Client, UInt32 a_ProtocolVersion, const AString & a_Username) override; virtual bool OnLoginForge (cClientHandle & a_Client, const AStringMap & a_Mods) override; virtual bool OnPlayerAnimation (cPlayer & a_Player, int a_Animation) override; virtual bool OnPlayerBreakingBlock (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override; virtual bool OnPlayerBrokenBlock (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override; virtual bool OnPlayerDestroyed (cPlayer & a_Player) override; virtual bool OnPlayerEating (cPlayer & a_Player) override; virtual bool OnPlayerFished (cPlayer & a_Player, const cItems & a_Reward, const int ExperienceAmount) override; virtual bool OnPlayerFishing (cPlayer & a_Player, cItems & a_Reward, int & ExperienceAmount) override; virtual bool OnPlayerFoodLevelChange (cPlayer & a_Player, int a_NewFoodLevel) override; virtual bool OnPlayerJoined (cPlayer & a_Player) override; virtual bool OnPlayerLeftClick (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, char a_Status) override; virtual bool OnPlayerMoving (cPlayer & a_Player, const Vector3d & a_OldPosition, const Vector3d & a_NewPosition, bool a_PreviousIsOnGround) override; virtual bool OnPlayerOpeningWindow (cPlayer & a_Player, cWindow & a_Window) override; virtual bool OnPlayerPlacedBlock (cPlayer & a_Player, const sSetBlock & a_BlockChange) override; virtual bool OnPlayerPlacingBlock (cPlayer & a_Player, const sSetBlock & a_BlockChange) override; virtual bool OnPlayerCrouched (cPlayer & a_Player) override; virtual bool OnPlayerRightClick (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override; virtual bool OnPlayerRightClickingEntity(cPlayer & a_Player, cEntity & a_Entity) override; virtual bool OnPlayerShooting (cPlayer & a_Player) override; virtual bool OnPlayerSpawned (cPlayer & a_Player) override; virtual bool OnEntityTeleport (cEntity & a_Entity, const Vector3d & a_OldPosition, const Vector3d & a_NewPosition) override; virtual bool OnPlayerTossingItem (cPlayer & a_Player) override; virtual bool OnPlayerUsedBlock (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override; virtual bool OnPlayerUsedItem (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override; virtual bool OnPlayerUsingBlock (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override; virtual bool OnPlayerUsingItem (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override; virtual bool OnPluginMessage (cClientHandle & a_Client, const AString & a_Channel, ContiguousByteBufferView a_Message) override; virtual bool OnPluginsLoaded (void) override; virtual bool OnPostCrafting (cPlayer & a_Player, cCraftingGrid & a_Grid, cCraftingRecipe & a_Recipe) override; virtual bool OnPreCrafting (cPlayer & a_Player, cCraftingGrid & a_Grid, cCraftingRecipe & a_Recipe) override; virtual bool OnProjectileHitBlock (cProjectileEntity & a_Projectile, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_Face, const Vector3d & a_BlockHitPos) override; virtual bool OnProjectileHitEntity (cProjectileEntity & a_Projectile, cEntity & a_HitEntity) override; virtual bool OnServerPing (cClientHandle & a_ClientHandle, AString & a_ServerDescription, int & a_OnlinePlayersCount, int & a_MaxPlayersCount, AString & a_Favicon) override; virtual bool OnSpawnedEntity (cWorld & a_World, cEntity & a_Entity) override; virtual bool OnSpawnedMonster (cWorld & a_World, cMonster & a_Monster) override; virtual bool OnSpawningEntity (cWorld & a_World, cEntity & a_Entity) override; virtual bool OnSpawningMonster (cWorld & a_World, cMonster & a_Monster) override; virtual bool OnTakeDamage (cEntity & a_Receiver, TakeDamageInfo & a_TakeDamageInfo) override; virtual bool OnUpdatedSign (cWorld & a_World, int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4, cPlayer * a_Player) override; virtual bool OnUpdatingSign (cWorld & a_World, int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4, cPlayer * a_Player) override; virtual bool OnWeatherChanged (cWorld & a_World) override; virtual bool OnWeatherChanging (cWorld & a_World, eWeather & a_NewWeather) override; virtual bool OnWorldStarted (cWorld & a_World) override; virtual bool OnWorldTick (cWorld & a_World, std::chrono::milliseconds a_Dt, std::chrono::milliseconds a_LastTickDurationMSec) override; /** Returns true if the plugin contains the function for the specified hook type, using the old-style registration (#121) */ bool CanAddOldStyleHook(int a_HookType); /** Returns the name of Lua function that should handle the specified hook type in the older (#121) API */ static const char * GetHookFnName(int a_HookType); /** Adds a Lua callback to be called for the specified hook. Returns true if the hook was added successfully. */ bool AddHookCallback(int a_HookType, cLuaState::cCallbackPtr && a_Callback); /** Calls a function in this plugin's LuaState with parameters copied over from a_ForeignState. The values that the function returns are placed onto a_ForeignState. Returns the number of values returned, if successful, or negative number on failure. */ int CallFunctionFromForeignState( const AString & a_FunctionName, cLuaState & a_ForeignState, int a_ParamStart, int a_ParamEnd ); /** Call a Lua function residing in the plugin. */ template bool Call(FnT a_Fn, Args && ... a_Args) { return cOperation(*this)().Call(a_Fn, a_Args...); } protected: /** Provides an array of Lua function references */ typedef std::vector cLuaCallbacks; /** Maps hook types into arrays of Lua function references to call for each hook type */ typedef std::map cHookMap; /** The plugin's Lua state. */ cLuaState m_LuaState; /** Hooks that the plugin has registered. */ cHookMap m_HookMap; /** The DeadlockDetect object to which the plugin's CS is tracked. */ cDeadlockDetect & m_DeadlockDetect; /** Releases all Lua references, notifies and removes all m_Resettables[] and closes the m_LuaState. */ void Close(void); /** Removes all WebTabs currently registered for this plugin from the WebAdmin. */ void ClearWebTabs(void); /** Calls a hook that has the simple format - single bool return value specifying whether the chain should continue. The advanced hook types that need more processing implement a similar loop manually instead. Returns true if any of hook calls wants to abort the hook (returned true), false if all hook calls returned false. */ template bool CallSimpleHooks(int a_HookType, Args && ... a_Args) { cOperation op(*this); auto & hooks = m_HookMap[a_HookType]; bool res = false; for (auto & hook: hooks) { hook->Call(std::forward(a_Args)..., cLuaState::Return, res); if (res) { // Hook wants to terminate the chain processing return true; } } return false; } }; // tolua_export ================================================ FILE: src/Bindings/PluginManager.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "PluginManager.h" #include "Plugin.h" #include "PluginLua.h" #include "../Item.h" #include "../Root.h" #include "../Server.h" #include "../CommandOutput.h" #include "../IniFile.h" #include "../Entities/Player.h" cPluginManager * cPluginManager::Get(void) { return cRoot::Get()->GetPluginManager(); } cPluginManager::cPluginManager(cDeadlockDetect & a_DeadlockDetect) : m_bReloadPlugins(false), m_DeadlockDetect(a_DeadlockDetect) { } cPluginManager::~cPluginManager() { UnloadPluginsNow(); } void cPluginManager::ReloadPlugins(void) { m_bReloadPlugins = true; } void cPluginManager::RefreshPluginList(void) { // Get a list of currently available folders: AString PluginsPath = GetPluginsPath() + "/"; AStringVector Contents = cFile::GetFolderContents(PluginsPath); AStringVector Folders; for (auto & item: Contents) { if (!cFile::IsFolder(PluginsPath + item)) { // We only want folders, and don't want "." or ".." continue; } Folders.push_back(item); } // for item - Contents[] // Set all plugins with invalid folders as psNotFound: for (auto & plugin: m_Plugins) { if (std::find(Folders.cbegin(), Folders.cend(), plugin->GetFolderName()) == Folders.end()) { plugin->m_Status = psNotFound; } } // for plugin - m_Plugins[] // Add all newly discovered plugins: for (auto & folder: Folders) { bool hasFound = false; for (auto & plugin: m_Plugins) { if (plugin->GetFolderName() == folder) { hasFound = true; break; } } // for plugin - m_Plugins[] if (!hasFound) { m_Plugins.push_back(std::make_shared(folder, m_DeadlockDetect)); } } // for folder - Folders[] } void cPluginManager::ReloadPluginsNow(void) { cIniFile a_SettingsIni; a_SettingsIni.ReadFile(cRoot::Get()->m_SettingsFilename); ReloadPluginsNow(a_SettingsIni); } void cPluginManager::ReloadPluginsNow(cSettingsRepositoryInterface & a_Settings) { LOG("-- Loading Plugins --"); // Unload any existing plugins: m_bReloadPlugins = false; UnloadPluginsNow(); // Refresh the list of plugins to load new ones from disk / remove the deleted ones: RefreshPluginList(); // Load the plugins: AStringVector ToLoad = GetFoldersToLoad(a_Settings); for (auto & pluginFolder: ToLoad) { LoadPlugin(pluginFolder); } // for pluginFolder - ToLoad[] // Log a report of the loading process size_t NumLoadedPlugins = GetNumLoadedPlugins(); if (NumLoadedPlugins == 0) { LOG("-- No Plugins Loaded --"); } else if (NumLoadedPlugins == 1) { LOG("-- Loaded 1 Plugin --"); } else { LOG("-- Loaded %u Plugins --", static_cast(NumLoadedPlugins)); } CallHookPluginsLoaded(); } void cPluginManager::InsertDefaultPlugins(cSettingsRepositoryInterface & a_Settings) { a_Settings.AddKeyName("Plugins"); a_Settings.AddValue("Plugins", "Core", "1"); a_Settings.AddValue("Plugins", "ChatLog", "1"); a_Settings.AddValue("Plugins", "ProtectionAreas", "0"); } void cPluginManager::Tick(float a_Dt) { decltype(m_PluginsNeedAction) PluginsNeedAction; { cCSLock Lock(m_CSPluginsNeedAction); std::swap(m_PluginsNeedAction, PluginsNeedAction); } // Process deferred actions: for (auto & CurrentPlugin : PluginsNeedAction) { auto & Action = CurrentPlugin.first; auto & Folder = CurrentPlugin.second; bool WasLoaded = false; bool WasFound = false; for (auto & Plugin: m_Plugins) { if (Plugin->GetFolderName() == Folder) { WasFound = true; if (Plugin->IsLoaded()) { switch (Action) { case PluginAction::Reload : { // Reload plugins by unloading, then loading: Plugin->Unload(); Plugin->Load(); break; } case PluginAction::Unload : { // Unload plugins that have been scheduled for unloading: Plugin->Unload(); break; } } WasLoaded = true; } } } if (!WasFound) { LOG("Cannot act on plugin in folder \"%s\", there's no such plugin folder", Folder.c_str()); } else if (!WasLoaded) { LOG("Cannot act on plugin in folder \"%s\", it has not been loaded.", Folder.c_str()); } } // for plugin - m_Plugins[] // If a plugin reload has been scheduled, reload now: if (m_bReloadPlugins) { ReloadPluginsNow(); } auto Plugins = m_Hooks.find(HOOK_TICK); if (Plugins == m_Hooks.end()) { return; } for (auto * Plugin : Plugins->second) { Plugin->Tick(a_Dt); } } template bool cPluginManager::GenericCallHook(PluginHook a_HookName, HookFunction a_HookFunction) { auto Plugins = m_Hooks.find(a_HookName); if (Plugins == m_Hooks.end()) { return false; } return std::any_of(Plugins->second.begin(), Plugins->second.end(), a_HookFunction); } bool cPluginManager::CallHookBlockSpread(cWorld & a_World, Vector3i a_BlockPos, eSpreadSource a_Source) { return GenericCallHook(HOOK_BLOCK_SPREAD, [&](cPlugin * a_Plugin) { return a_Plugin->OnBlockSpread(a_World, a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, a_Source); } ); } bool cPluginManager::CallHookBlockToPickups( cWorld & a_World, Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, const cBlockEntity * a_BlockEntity, const cEntity * a_Digger, const cItem * a_Tool, cItems & a_Pickups ) { return GenericCallHook(HOOK_BLOCK_TO_PICKUPS, [&](cPlugin * a_Plugin) { return a_Plugin->OnBlockToPickups(a_World, a_BlockPos, a_BlockType, a_BlockMeta, a_BlockEntity, a_Digger, a_Tool, a_Pickups); } ); } bool cPluginManager::CallHookBrewingCompleted(cWorld & a_World, cBrewingstandEntity & a_Brewingstand) { return GenericCallHook(HOOK_BREWING_COMPLETED, [&](cPlugin * a_Plugin) { return a_Plugin->OnBrewingCompleted(a_World, a_Brewingstand); } ); } bool cPluginManager::CallHookBrewingCompleting(cWorld & a_World, cBrewingstandEntity & a_Brewingstand) { return GenericCallHook(HOOK_BREWING_COMPLETING, [&](cPlugin * a_Plugin) { return a_Plugin->OnBrewingCompleting(a_World, a_Brewingstand); } ); } bool cPluginManager::CallHookChat(cPlayer & a_Player, AString & a_Message) { // Check if the message contains a command, execute it: switch (HandleCommand(a_Player, a_Message, true)) { case crExecuted: { // The command has executed successfully return true; } case crBlocked: { // The command was blocked by a plugin using HOOK_EXECUTE_COMMAND // The plugin has most likely sent a message to the player already return true; } case crError: { // An error in the plugin has prevented the command from executing. Report the error to the player: a_Player.SendMessageFailure(fmt::format(FMT_STRING("Something went wrong while executing command \"{}\""), a_Message)); return true; } case crNoPermission: { // The player is not allowed to execute this command a_Player.SendMessageFailure(fmt::format(FMT_STRING("Forbidden command; insufficient privileges: \"{}\""), a_Message)); return true; } case crUnknownCommand: { // This was not a known command, keep processing as a message break; } } // Check if the message is a command (starts with a slash). If it is, we know that it wasn't recognised: if (!a_Message.empty() && (a_Message[0] == '/')) { AStringVector Split(StringSplit(a_Message, " ")); ASSERT(!Split.empty()); // This should not happen - we know there's at least one char in the message so the split needs to be at least one item long a_Player.SendMessageInfo(fmt::format(FMT_STRING("Unknown command: \"{}\""), a_Message)); LOGINFO("Player %s issued an unknown command: \"%s\"", a_Player.GetName(), a_Message); return true; // Cancel sending } return GenericCallHook(HOOK_CHAT, [&](cPlugin * a_Plugin) { return a_Plugin->OnChat(a_Player, a_Message); } ); } bool cPluginManager::CallHookChunkAvailable(cWorld & a_World, int a_ChunkX, int a_ChunkZ) { return GenericCallHook(HOOK_CHUNK_AVAILABLE, [&](cPlugin * a_Plugin) { return a_Plugin->OnChunkAvailable(a_World, a_ChunkX, a_ChunkZ); } ); } bool cPluginManager::CallHookChunkGenerated(cWorld & a_World, int a_ChunkX, int a_ChunkZ, cChunkDesc * a_ChunkDesc) { return GenericCallHook(HOOK_CHUNK_GENERATED, [&](cPlugin * a_Plugin) { return a_Plugin->OnChunkGenerated(a_World, a_ChunkX, a_ChunkZ, a_ChunkDesc); } ); } bool cPluginManager::CallHookChunkGenerating(cWorld & a_World, int a_ChunkX, int a_ChunkZ, cChunkDesc * a_ChunkDesc) { return GenericCallHook(HOOK_CHUNK_GENERATING, [&](cPlugin * a_Plugin) { return a_Plugin->OnChunkGenerating(a_World, a_ChunkX, a_ChunkZ, a_ChunkDesc); } ); } bool cPluginManager::CallHookChunkUnloaded(cWorld & a_World, int a_ChunkX, int a_ChunkZ) { return GenericCallHook(HOOK_CHUNK_UNLOADED, [&](cPlugin * a_Plugin) { return a_Plugin->OnChunkUnloaded(a_World, a_ChunkX, a_ChunkZ); } ); } bool cPluginManager::CallHookChunkUnloading(cWorld & a_World, int a_ChunkX, int a_ChunkZ) { return GenericCallHook(HOOK_CHUNK_UNLOADING, [&](cPlugin * a_Plugin) { return a_Plugin->OnChunkUnloading(a_World, a_ChunkX, a_ChunkZ); } ); } bool cPluginManager::CallHookCollectingPickup(cPlayer & a_Player, cPickup & a_Pickup) { return GenericCallHook(HOOK_COLLECTING_PICKUP, [&](cPlugin * a_Plugin) { return a_Plugin->OnCollectingPickup(a_Player, a_Pickup); } ); } bool cPluginManager::CallHookCraftingNoRecipe(cPlayer & a_Player, cCraftingGrid & a_Grid, cCraftingRecipe & a_Recipe) { return GenericCallHook(HOOK_CRAFTING_NO_RECIPE, [&](cPlugin * a_Plugin) { return a_Plugin->OnCraftingNoRecipe(a_Player, a_Grid, a_Recipe); } ); } bool cPluginManager::CallHookDisconnect(cClientHandle & a_Client, const AString & a_Reason) { return GenericCallHook(HOOK_DISCONNECT, [&](cPlugin * a_Plugin) { return a_Plugin->OnDisconnect(a_Client, a_Reason); } ); } bool cPluginManager::CallHookEntityAddEffect(cEntity & a_Entity, int a_EffectType, int a_EffectDurationTicks, int a_EffectIntensity, double a_DistanceModifier) { return GenericCallHook(HOOK_ENTITY_ADD_EFFECT, [&](cPlugin * a_Plugin) { return a_Plugin->OnEntityAddEffect(a_Entity, a_EffectType, a_EffectDurationTicks, a_EffectIntensity, a_DistanceModifier); } ); } bool cPluginManager::CallHookEntityTeleport(cEntity & a_Entity, const Vector3d & a_OldPosition, const Vector3d & a_NewPosition) { return GenericCallHook(HOOK_ENTITY_TELEPORT, [&](cPlugin * a_Plugin) { return a_Plugin->OnEntityTeleport(a_Entity, a_OldPosition, a_NewPosition); } ); } bool cPluginManager::CallHookEntityChangingWorld(cEntity & a_Entity, cWorld & a_World) { return GenericCallHook(HOOK_ENTITY_CHANGING_WORLD, [&](cPlugin * a_Plugin) { return a_Plugin->OnEntityChangingWorld(a_Entity, a_World); } ); } bool cPluginManager::CallHookEntityChangedWorld(cEntity & a_Entity, cWorld & a_World) { return GenericCallHook(HOOK_ENTITY_CHANGED_WORLD, [&](cPlugin * a_Plugin) { return a_Plugin->OnEntityChangedWorld(a_Entity, a_World); } ); } bool cPluginManager::CallHookExecuteCommand(cPlayer * a_Player, const AStringVector & a_Split, const AString & a_EntireCommand, CommandResult & a_Result) { // Output the command being executed to log (for troubleshooting deadlocks-in-commands): if (a_Player != nullptr) { auto world = a_Player->GetWorld(); AString worldName; Int64 worldAge; if (world != nullptr) { worldName = world->GetName(); worldAge = world->GetWorldAge().count(); } else { worldName = ""; worldAge = 0; } LOG("Player %s is executing command \"%s\" in world \"%s\" at world age %lld.", a_Player->GetName().c_str(), a_EntireCommand.c_str(), worldName.c_str(), worldAge ); } return GenericCallHook(HOOK_EXECUTE_COMMAND, [&](cPlugin * a_Plugin) { return a_Plugin->OnExecuteCommand(a_Player, a_Split, a_EntireCommand, a_Result); } ); } bool cPluginManager::CallHookExploded(cWorld & a_World, double a_ExplosionSize, bool a_CanCauseFire, double a_X, double a_Y, double a_Z, eExplosionSource a_Source, void * a_SourceData) { return GenericCallHook(HOOK_EXPLODED, [&](cPlugin * a_Plugin) { return a_Plugin->OnExploded(a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, a_SourceData); } ); } bool cPluginManager::CallHookExploding(cWorld & a_World, double & a_ExplosionSize, bool & a_CanCauseFire, double a_X, double a_Y, double a_Z, eExplosionSource a_Source, void * a_SourceData) { return GenericCallHook(HOOK_EXPLODING, [&](cPlugin * a_Plugin) { return a_Plugin->OnExploding(a_World, a_ExplosionSize, a_CanCauseFire, a_X, a_Y, a_Z, a_Source, a_SourceData); } ); } bool cPluginManager::CallHookHandshake(cClientHandle & a_ClientHandle, const AString & a_Username) { return GenericCallHook(HOOK_HANDSHAKE, [&](cPlugin * a_Plugin) { return a_Plugin->OnHandshake(a_ClientHandle, a_Username); } ); } bool cPluginManager::CallHookHopperPullingItem(cWorld & a_World, cHopperEntity & a_Hopper, int a_DstSlotNum, cBlockEntityWithItems & a_SrcEntity, int a_SrcSlotNum) { return GenericCallHook(HOOK_HOPPER_PULLING_ITEM, [&](cPlugin * a_Plugin) { return a_Plugin->OnHopperPullingItem(a_World, a_Hopper, a_DstSlotNum, a_SrcEntity, a_SrcSlotNum); } ); } bool cPluginManager::CallHookHopperPushingItem(cWorld & a_World, cHopperEntity & a_Hopper, int a_SrcSlotNum, cBlockEntityWithItems & a_DstEntity, int a_DstSlotNum) { return GenericCallHook(HOOK_HOPPER_PUSHING_ITEM, [&](cPlugin * a_Plugin) { return a_Plugin->OnHopperPushingItem(a_World, a_Hopper, a_SrcSlotNum, a_DstEntity, a_DstSlotNum); } ); } bool cPluginManager::CallHookDropSpense(cWorld & a_World, cDropSpenserEntity & a_DropSpenser, int a_SlotNum) { return GenericCallHook(HOOK_DROPSPENSE, [&](cPlugin * a_Plugin) { return a_Plugin->OnDropSpense(a_World, a_DropSpenser, a_SlotNum); } ); } bool cPluginManager::CallHookKilled(cEntity & a_Victim, TakeDamageInfo & a_TDI, AString & a_DeathMessage) { return GenericCallHook(HOOK_KILLED, [&](cPlugin * a_Plugin) { return a_Plugin->OnKilled(a_Victim, a_TDI, a_DeathMessage); } ); } bool cPluginManager::CallHookKilling(cEntity & a_Victim, cEntity * a_Killer, TakeDamageInfo & a_TDI) { return GenericCallHook(HOOK_KILLING, [&](cPlugin * a_Plugin) { return a_Plugin->OnKilling(a_Victim, a_Killer, a_TDI); } ); } bool cPluginManager::CallHookLogin(cClientHandle & a_Client, UInt32 a_ProtocolVersion, const AString & a_Username) { return GenericCallHook(HOOK_LOGIN, [&](cPlugin * a_Plugin) { return a_Plugin->OnLogin(a_Client, a_ProtocolVersion, a_Username); } ); } bool cPluginManager::CallHookLoginForge(cClientHandle & a_Client, AStringMap & a_Mods) { return GenericCallHook(HOOK_LOGIN_FORGE, [&](cPlugin * a_Plugin) { return a_Plugin->OnLoginForge(a_Client, a_Mods); } ); } bool cPluginManager::CallHookPlayerAnimation(cPlayer & a_Player, int a_Animation) { return GenericCallHook(HOOK_PLAYER_ANIMATION, [&](cPlugin * a_Plugin) { return a_Plugin->OnPlayerAnimation(a_Player, a_Animation); } ); } bool cPluginManager::CallHookPlayerBreakingBlock(cPlayer & a_Player, Vector3i a_BlockPos, eBlockFace a_BlockFace, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) { return GenericCallHook(HOOK_PLAYER_BREAKING_BLOCK, [&](cPlugin * a_Plugin) { return a_Plugin->OnPlayerBreakingBlock(a_Player, a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, a_BlockFace, a_BlockType, a_BlockMeta); } ); } bool cPluginManager::CallHookPlayerBrokenBlock(cPlayer & a_Player, Vector3i a_BlockPos, eBlockFace a_BlockFace, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) { return GenericCallHook(HOOK_PLAYER_BROKEN_BLOCK, [&](cPlugin * a_Plugin) { return a_Plugin->OnPlayerBrokenBlock(a_Player, a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, a_BlockFace, a_BlockType, a_BlockMeta); } ); } bool cPluginManager::CallHookPlayerDestroyed(cPlayer & a_Player) { return GenericCallHook(HOOK_PLAYER_DESTROYED, [&](cPlugin * a_Plugin) { return a_Plugin->OnPlayerDestroyed(a_Player); } ); } bool cPluginManager::CallHookPlayerEating(cPlayer & a_Player) { return GenericCallHook(HOOK_PLAYER_EATING, [&](cPlugin * a_Plugin) { return a_Plugin->OnPlayerEating(a_Player); } ); } bool cPluginManager::CallHookPlayerFoodLevelChange(cPlayer & a_Player, int a_NewFoodLevel) { return GenericCallHook(HOOK_PLAYER_FOOD_LEVEL_CHANGE, [&](cPlugin * a_Plugin) { return a_Plugin->OnPlayerFoodLevelChange(a_Player, a_NewFoodLevel); } ); } bool cPluginManager::CallHookPlayerFished(cPlayer & a_Player, const cItems & a_Reward, const int ExperienceAmount) { return GenericCallHook(HOOK_PLAYER_FISHED, [&](cPlugin * a_Plugin) { return a_Plugin->OnPlayerFished(a_Player, a_Reward, ExperienceAmount); } ); } bool cPluginManager::CallHookPlayerFishing(cPlayer & a_Player, cItems & a_Reward, int & ExperienceAmount) { return GenericCallHook(HOOK_PLAYER_FISHING, [&](cPlugin * a_Plugin) { return a_Plugin->OnPlayerFishing(a_Player, a_Reward, ExperienceAmount); } ); } bool cPluginManager::CallHookPlayerJoined(cPlayer & a_Player) { return GenericCallHook(HOOK_PLAYER_JOINED, [&](cPlugin * a_Plugin) { return a_Plugin->OnPlayerJoined(a_Player); } ); } bool cPluginManager::CallHookPlayerLeftClick(cPlayer & a_Player, Vector3i a_BlockPos, eBlockFace a_BlockFace, char a_Status) { return GenericCallHook(HOOK_PLAYER_LEFT_CLICK, [&](cPlugin * a_Plugin) { return a_Plugin->OnPlayerLeftClick(a_Player, a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, a_BlockFace, a_Status); } ); } bool cPluginManager::CallHookPlayerMoving(cPlayer & a_Player, const Vector3d & a_OldPosition, const Vector3d & a_NewPosition, bool a_PreviousIsOnGround) { return GenericCallHook(HOOK_PLAYER_MOVING, [&](cPlugin * a_Plugin) { return a_Plugin->OnPlayerMoving(a_Player, a_OldPosition, a_NewPosition, a_PreviousIsOnGround); } ); } bool cPluginManager::CallHookPlayerOpeningWindow(cPlayer & a_Player, cWindow & a_Window) { return GenericCallHook(HOOK_PLAYER_OPENING_WINDOW, [&](cPlugin * a_Plugin) { return a_Plugin->OnPlayerOpeningWindow(a_Player, a_Window); } ); } bool cPluginManager::CallHookPlayerPlacedBlock(cPlayer & a_Player, const sSetBlock & a_BlockChange) { return GenericCallHook(HOOK_PLAYER_PLACED_BLOCK, [&](cPlugin * a_Plugin) { return a_Plugin->OnPlayerPlacedBlock(a_Player, a_BlockChange); } ); } bool cPluginManager::CallHookPlayerPlacingBlock(cPlayer & a_Player, const sSetBlock & a_BlockChange) { return GenericCallHook(HOOK_PLAYER_PLACING_BLOCK, [&](cPlugin * a_Plugin) { return a_Plugin->OnPlayerPlacingBlock(a_Player, a_BlockChange); } ); } bool cPluginManager::CallHookPlayerCrouched(cPlayer & a_Player) { return GenericCallHook(HOOK_PLAYER_CROUCHED, [&](cPlugin * a_Plugin) { return a_Plugin->OnPlayerCrouched(a_Player); } ); } bool cPluginManager::CallHookPlayerRightClick(cPlayer & a_Player, Vector3i a_BlockPos, eBlockFace a_BlockFace, Vector3i a_CursorPos) { return GenericCallHook(HOOK_PLAYER_RIGHT_CLICK, [&](cPlugin * a_Plugin) { return a_Plugin->OnPlayerRightClick(a_Player, a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, a_BlockFace, a_CursorPos.x, a_CursorPos.y, a_CursorPos.z); } ); } bool cPluginManager::CallHookPlayerRightClickingEntity(cPlayer & a_Player, cEntity & a_Entity) { return GenericCallHook(HOOK_PLAYER_RIGHT_CLICKING_ENTITY, [&](cPlugin * a_Plugin) { return a_Plugin->OnPlayerRightClickingEntity(a_Player, a_Entity); } ); } bool cPluginManager::CallHookPlayerShooting(cPlayer & a_Player) { return GenericCallHook(HOOK_PLAYER_SHOOTING, [&](cPlugin * a_Plugin) { return a_Plugin->OnPlayerShooting(a_Player); } ); } bool cPluginManager::CallHookPlayerSpawned(cPlayer & a_Player) { return GenericCallHook(HOOK_PLAYER_SPAWNED, [&](cPlugin * a_Plugin) { return a_Plugin->OnPlayerSpawned(a_Player); } ); } bool cPluginManager::CallHookPlayerTossingItem(cPlayer & a_Player) { return GenericCallHook(HOOK_PLAYER_TOSSING_ITEM, [&](cPlugin * a_Plugin) { return a_Plugin->OnPlayerTossingItem(a_Player); } ); } bool cPluginManager::CallHookPlayerUsedBlock(cPlayer & a_Player, Vector3i a_BlockPos, eBlockFace a_BlockFace, Vector3i a_CursorPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) { return GenericCallHook(HOOK_PLAYER_USED_BLOCK, [&](cPlugin * a_Plugin) { return a_Plugin->OnPlayerUsedBlock(a_Player, a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, a_BlockFace, a_CursorPos.x, a_CursorPos.y, a_CursorPos.z, a_BlockType, a_BlockMeta); } ); } bool cPluginManager::CallHookPlayerUsedItem(cPlayer & a_Player, Vector3i a_BlockPos, eBlockFace a_BlockFace, Vector3i a_CursorPos) { return GenericCallHook(HOOK_PLAYER_USED_ITEM, [&](cPlugin * a_Plugin) { return a_Plugin->OnPlayerUsedItem(a_Player, a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, a_BlockFace, a_CursorPos.x, a_CursorPos.y, a_CursorPos.z); } ); } bool cPluginManager::CallHookPlayerUsingBlock(cPlayer & a_Player, Vector3i a_BlockPos, eBlockFace a_BlockFace, Vector3i a_CursorPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) { return GenericCallHook(HOOK_PLAYER_USING_BLOCK, [&](cPlugin * a_Plugin) { return a_Plugin->OnPlayerUsingBlock(a_Player, a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, a_BlockFace, a_CursorPos.x, a_CursorPos.y, a_CursorPos.z, a_BlockType, a_BlockMeta); } ); } bool cPluginManager::CallHookPlayerUsingItem(cPlayer & a_Player, Vector3i a_BlockPos, eBlockFace a_BlockFace, Vector3i a_CursorPos) { return GenericCallHook(HOOK_PLAYER_USING_ITEM, [&](cPlugin * a_Plugin) { return a_Plugin->OnPlayerUsingItem(a_Player, a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, a_BlockFace, a_CursorPos.x, a_CursorPos.y, a_CursorPos.z); } ); } bool cPluginManager::CallHookPluginMessage(cClientHandle & a_Client, const AString & a_Channel, const ContiguousByteBufferView a_Message) { return GenericCallHook(HOOK_PLUGIN_MESSAGE, [&](cPlugin * a_Plugin) { return a_Plugin->OnPluginMessage(a_Client, a_Channel, a_Message); } ); } bool cPluginManager::CallHookPluginsLoaded(void) { auto Plugins = m_Hooks.find(HOOK_PLUGINS_LOADED); if (Plugins == m_Hooks.end()) { return false; } bool res = false; for (auto * Plugin : Plugins->second) { if (!Plugin->OnPluginsLoaded()) { res = true; } } return res; } bool cPluginManager::CallHookPostCrafting(cPlayer & a_Player, cCraftingGrid & a_Grid, cCraftingRecipe & a_Recipe) { return GenericCallHook(HOOK_POST_CRAFTING, [&](cPlugin * a_Plugin) { return a_Plugin->OnPostCrafting(a_Player, a_Grid, a_Recipe); } ); } bool cPluginManager::CallHookPreCrafting(cPlayer & a_Player, cCraftingGrid & a_Grid, cCraftingRecipe & a_Recipe) { return GenericCallHook(HOOK_PRE_CRAFTING, [&](cPlugin * a_Plugin) { return a_Plugin->OnPreCrafting(a_Player, a_Grid, a_Recipe); } ); } bool cPluginManager::CallHookProjectileHitBlock(cProjectileEntity & a_Projectile, Vector3i a_BlockPos, eBlockFace a_Face, const Vector3d & a_BlockHitPos) { return GenericCallHook(HOOK_PROJECTILE_HIT_BLOCK, [&](cPlugin * a_Plugin) { return a_Plugin->OnProjectileHitBlock(a_Projectile, a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, a_Face, a_BlockHitPos); } ); } bool cPluginManager::CallHookProjectileHitEntity(cProjectileEntity & a_Projectile, cEntity & a_HitEntity) { return GenericCallHook(HOOK_PROJECTILE_HIT_ENTITY, [&](cPlugin * a_Plugin) { return a_Plugin->OnProjectileHitEntity(a_Projectile, a_HitEntity); } ); } bool cPluginManager::CallHookServerPing(cClientHandle & a_ClientHandle, AString & a_ServerDescription, int & a_OnlinePlayersCount, int & a_MaxPlayersCount, AString & a_Favicon) { return GenericCallHook(HOOK_SERVER_PING, [&](cPlugin * a_Plugin) { return a_Plugin->OnServerPing(a_ClientHandle, a_ServerDescription, a_OnlinePlayersCount, a_MaxPlayersCount, a_Favicon); } ); } bool cPluginManager::CallHookSpawnedEntity(cWorld & a_World, cEntity & a_Entity) { return GenericCallHook(HOOK_SPAWNED_ENTITY, [&](cPlugin * a_Plugin) { return a_Plugin->OnSpawnedEntity(a_World, a_Entity); } ); } bool cPluginManager::CallHookSpawnedMonster(cWorld & a_World, cMonster & a_Monster) { return GenericCallHook(HOOK_SPAWNED_MONSTER, [&](cPlugin * a_Plugin) { return a_Plugin->OnSpawnedMonster(a_World, a_Monster); } ); } bool cPluginManager::CallHookSpawningEntity(cWorld & a_World, cEntity & a_Entity) { return GenericCallHook(HOOK_SPAWNING_ENTITY, [&](cPlugin * a_Plugin) { return a_Plugin->OnSpawningEntity(a_World, a_Entity); } ); } bool cPluginManager::CallHookSpawningMonster(cWorld & a_World, cMonster & a_Monster) { return GenericCallHook(HOOK_SPAWNING_MONSTER, [&](cPlugin * a_Plugin) { return a_Plugin->OnSpawningMonster(a_World, a_Monster); } ); } bool cPluginManager::CallHookTakeDamage(cEntity & a_Receiver, TakeDamageInfo & a_TDI) { return GenericCallHook(HOOK_TAKE_DAMAGE, [&](cPlugin * a_Plugin) { return a_Plugin->OnTakeDamage(a_Receiver, a_TDI); } ); } bool cPluginManager::CallHookUpdatingSign(cWorld & a_World, Vector3i a_BlockPos, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4, cPlayer * a_Player) { return GenericCallHook(HOOK_UPDATING_SIGN, [&](cPlugin * a_Plugin) { return a_Plugin->OnUpdatingSign(a_World, a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, a_Line1, a_Line2, a_Line3, a_Line4, a_Player); } ); } bool cPluginManager::CallHookUpdatedSign(cWorld & a_World, Vector3i a_BlockPos, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4, cPlayer * a_Player) { return GenericCallHook(HOOK_UPDATED_SIGN, [&](cPlugin * a_Plugin) { return a_Plugin->OnUpdatedSign(a_World, a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, a_Line1, a_Line2, a_Line3, a_Line4, a_Player); } ); } bool cPluginManager::CallHookWeatherChanged(cWorld & a_World) { return GenericCallHook(HOOK_WEATHER_CHANGED, [&](cPlugin * a_Plugin) { return a_Plugin->OnWeatherChanged(a_World); } ); } bool cPluginManager::CallHookWeatherChanging(cWorld & a_World, eWeather & a_NewWeather) { return GenericCallHook(HOOK_WEATHER_CHANGING, [&](cPlugin * a_Plugin) { return a_Plugin->OnWeatherChanging(a_World, a_NewWeather); } ); } bool cPluginManager::CallHookWorldStarted(cWorld & a_World) { return GenericCallHook(HOOK_WORLD_STARTED, [&](cPlugin * a_Plugin) { return a_Plugin->OnWorldStarted(a_World); } ); } bool cPluginManager::CallHookWorldTick(cWorld & a_World, std::chrono::milliseconds a_Dt, std::chrono::milliseconds a_LastTickDurationMSec) { return GenericCallHook(HOOK_WORLD_TICK, [&](cPlugin * a_Plugin) { return a_Plugin->OnWorldTick(a_World, a_Dt, a_LastTickDurationMSec); } ); } cPluginManager::CommandResult cPluginManager::HandleCommand(cPlayer & a_Player, const AString & a_Command, bool a_ShouldCheckPermissions) { AStringVector Split(StringSplit(a_Command, " ")); if (Split.empty()) { return crUnknownCommand; } CommandMap::iterator cmd = m_Commands.find(Split[0]); if (cmd == m_Commands.end()) { // Command not found // If it started with a slash, ask the plugins if they still want to handle it: if (!a_Command.empty() && (a_Command[0] == '/')) { CommandResult Result = crUnknownCommand; CallHookExecuteCommand(&a_Player, Split, a_Command, Result); return Result; } return crUnknownCommand; } // Ask plugins first if a command is okay to execute the command: CommandResult Result = crBlocked; if (CallHookExecuteCommand(&a_Player, Split, a_Command, Result)) { if (Result == crBlocked) { LOGINFO("Player %s tried executing command \"%s\" that was stopped by the HOOK_EXECUTE_COMMAND hook", a_Player.GetName().c_str(), Split[0].c_str()); } return Result; } if ( a_ShouldCheckPermissions && !cmd->second.m_Permission.empty() && !a_Player.HasPermission(cmd->second.m_Permission) ) { LOGINFO("Player %s tried to execute forbidden command: \"%s\"", a_Player.GetName().c_str(), Split[0].c_str()); return crNoPermission; } ASSERT(cmd->second.m_Handler != nullptr); if (!cmd->second.m_Handler->ExecuteCommand(Split, &a_Player, a_Command, nullptr)) { return crError; } return crExecuted; } void cPluginManager::UnloadPluginsNow() { // Remove all bindings: m_Hooks.clear(); m_Commands.clear(); m_ConsoleCommands.clear(); // Re-bind built-in console commands: cServer::BindBuiltInConsoleCommands(); // Unload all loaded plugins: for (auto & plugin: m_Plugins) { if (plugin->IsLoaded()) { plugin->Unload(); } } } void cPluginManager::UnloadPlugin(const AString & a_PluginFolder) { cCSLock Lock(m_CSPluginsNeedAction); m_PluginsNeedAction.emplace_back(PluginAction::Unload, a_PluginFolder); } void cPluginManager::ReloadPlugin(const AString & a_PluginFolder) { cCSLock Lock(m_CSPluginsNeedAction); m_PluginsNeedAction.emplace_back(PluginAction::Reload, a_PluginFolder); } bool cPluginManager::LoadPlugin(const AString & a_FolderName) { for (auto & plugin: m_Plugins) { if (plugin->GetFolderName() == a_FolderName) { if (!plugin->IsLoaded()) { return plugin->Load(); } return true; } } // for plugin - m_Plugins[] // Plugin not found LOG("Cannot load plugin, folder \"%s\" not found.", a_FolderName.c_str()); return false; } void cPluginManager::RemoveHooks(cPlugin * a_Plugin) { for (auto & Hook : m_Hooks) { Hook.second.remove(a_Plugin); } } void cPluginManager::RemovePluginCommands(cPlugin * a_Plugin) { for (CommandMap::iterator itr = m_Commands.begin(); itr != m_Commands.end();) { if (itr->second.m_Plugin == a_Plugin) { CommandMap::iterator EraseMe = itr; // Stupid GCC doesn't have a std::map::erase() that would return the next iterator ++itr; m_Commands.erase(EraseMe); } else { ++itr; } } // for itr - m_Commands[] } bool cPluginManager::IsPluginLoaded(const AString & a_PluginName) { for (auto & plugin: m_Plugins) { if (plugin->GetName() == a_PluginName) { return true; } } return false; } bool cPluginManager::BindCommand( const AString & a_Command, cPlugin * a_Plugin, cCommandHandlerPtr a_Handler, const AString & a_Permission, const AString & a_HelpString ) { CommandMap::iterator cmd = m_Commands.find(a_Command); if (cmd != m_Commands.end()) { LOGWARNING("Command \"%s\" is already bound to plugin \"%s\".", a_Command.c_str(), cmd->second.m_Plugin->GetName().c_str()); return false; } auto & reg = m_Commands[a_Command]; reg.m_Plugin = a_Plugin; reg.m_Handler = std::move(a_Handler); reg.m_Permission = a_Permission; reg.m_HelpString = a_HelpString; return true; } bool cPluginManager::ForEachCommand(cCommandEnumCallback & a_Callback) { for (auto & itr : m_Commands) { if (a_Callback.Command(itr.first, itr.second.m_Plugin, itr.second.m_Permission, itr.second.m_HelpString)) { return false; } } // for itr - m_Commands[] return true; } bool cPluginManager::IsCommandBound(const AString & a_Command) { return (m_Commands.find(a_Command) != m_Commands.end()); } AString cPluginManager::GetCommandPermission(const AString & a_Command) { CommandMap::iterator cmd = m_Commands.find(a_Command); return (cmd == m_Commands.end()) ? "" : cmd->second.m_Permission; } cPluginManager::CommandResult cPluginManager::ExecuteCommand(cPlayer & a_Player, const AString & a_Command) { return HandleCommand(a_Player, a_Command, true); } cPluginManager::CommandResult cPluginManager::ForceExecuteCommand(cPlayer & a_Player, const AString & a_Command) { return HandleCommand(a_Player, a_Command, false); } void cPluginManager::RemovePluginConsoleCommands(cPlugin * a_Plugin) { for (CommandMap::iterator itr = m_ConsoleCommands.begin(); itr != m_ConsoleCommands.end();) { if (itr->second.m_Plugin == a_Plugin) { CommandMap::iterator EraseMe = itr; // Stupid GCC doesn't have a std::map::erase() that would return the next iterator ++itr; m_ConsoleCommands.erase(EraseMe); } else { ++itr; } } // for itr - m_Commands[] } bool cPluginManager::BindConsoleCommand( const AString & a_Command, cPlugin * a_Plugin, cCommandHandlerPtr a_Handler, const AString & a_HelpString ) { CommandMap::iterator cmd = m_ConsoleCommands.find(a_Command); if (cmd != m_ConsoleCommands.end()) { if (cmd->second.m_Plugin == nullptr) { LOGWARNING("Console command \"%s\" is already bound internally by Cuberite, cannot bind in plugin \"%s\".", a_Command.c_str(), a_Plugin->GetName().c_str()); } else { LOGWARNING("Console command \"%s\" is already bound to plugin \"%s\", cannot bind in plugin \"%s\".", a_Command.c_str(), cmd->second.m_Plugin->GetName().c_str(), a_Plugin->GetName().c_str()); } return false; } auto & reg = m_ConsoleCommands[a_Command]; reg.m_Plugin = a_Plugin; reg.m_Handler = std::move(a_Handler); reg.m_Permission = ""; reg.m_HelpString = a_HelpString; return true; } bool cPluginManager::ForEachConsoleCommand(cCommandEnumCallback & a_Callback) { for (auto & itr : m_ConsoleCommands) { if (a_Callback.Command(itr.first, itr.second.m_Plugin, "", itr.second.m_HelpString)) { return false; } } // for itr - m_Commands[] return true; } bool cPluginManager::IsConsoleCommandBound(const AString & a_Command) { return (m_ConsoleCommands.find(a_Command) != m_ConsoleCommands.end()); } bool cPluginManager::ExecuteConsoleCommand(const AStringVector & a_Split, cCommandOutputCallback & a_Output, const AString & a_Command) { if (a_Split.empty()) { return false; } CommandMap::iterator cmd = m_ConsoleCommands.find(a_Split[0]); if (cmd == m_ConsoleCommands.end()) { // Command not found // Still notify the plugins (so that plugins such as Aliases can intercept unknown commands). CommandResult res = crBlocked; CallHookExecuteCommand(nullptr, a_Split, a_Command, res); return (res == crExecuted); } if (cmd->second.m_Plugin == nullptr) { // This is a built-in command return false; } // Ask plugins first if a command is okay to execute the console command: CommandResult res = crBlocked; if (CallHookExecuteCommand(nullptr, a_Split, a_Command, res)) { return (res == crExecuted); } return cmd->second.m_Handler->ExecuteCommand(a_Split, nullptr, a_Command, &a_Output); } void cPluginManager::TabCompleteCommand(const AString & a_Text, AStringVector & a_Results, cPlayer * a_Player) { for (auto & Command : m_Commands) { if (NoCaseCompare(Command.first.substr(0, a_Text.length()), a_Text) != 0) { // Command name doesn't match continue; } if ((a_Player != nullptr) && !a_Player->HasPermission(Command.second.m_Permission)) { // Player doesn't have permission for the command continue; } /* Client expects to only get back the last part of a space separated command. Find the position of the beginning of the last part: Position of last space + 1 for space separated commands string::npos + 1 = 0 for commands that are not separated Then skip all commands that have too many subcommands. When the client asks for suggestions for "/time s" the server must skip all commands that consist of more than 2 words just as "/time set day". Or in other words, the position of the last space (separator) in the strings must be equal or string::npos for both. */ size_t LastSpaceInText = a_Text.find_last_of(' ') + 1; size_t LastSpaceInSuggestion = Command.first.find_last_of(' ') + 1; if (LastSpaceInText != LastSpaceInSuggestion) { // Suggestion has more subcommands than a_Text continue; } a_Results.push_back(Command.first.substr(LastSpaceInSuggestion)); } } bool cPluginManager::IsValidHookType(int a_HookType) { return ((a_HookType >= 0) && (a_HookType <= HOOK_MAX)); } bool cPluginManager::DoWithPlugin(const AString & a_PluginName, cPluginCallback a_Callback) { // TODO: Implement locking for plugins for (auto & plugin: m_Plugins) { if (plugin->GetName() == a_PluginName) { return a_Callback(*plugin); } } return false; } bool cPluginManager::ForEachPlugin(cPluginCallback a_Callback) { // TODO: Implement locking for plugins for (auto & plugin: m_Plugins) { if (a_Callback(*plugin)) { return false; } } return true; } AString cPluginManager::GetPluginFolderName(const AString & a_PluginName) { // TODO: Implement locking for plugins for (auto & plugin: m_Plugins) { if (plugin->GetName() == a_PluginName) { return plugin->GetFolderName(); } } return AString(); } void cPluginManager::AddHook(cPlugin * a_Plugin, int a_Hook) { if (a_Plugin == nullptr) { LOGWARN("Called cPluginManager::AddHook() with a_Plugin == nullptr"); return; } PluginList & Plugins = m_Hooks[a_Hook]; if (std::find(Plugins.cbegin(), Plugins.cend(), a_Plugin) == Plugins.cend()) { Plugins.push_back(a_Plugin); } } size_t cPluginManager::GetNumPlugins(void) const { return m_Plugins.size(); } size_t cPluginManager::GetNumLoadedPlugins(void) const { size_t res = 0; for (auto & plugin: m_Plugins) { if (plugin->IsLoaded()) { res += 1; } } return res; } AStringVector cPluginManager::GetFoldersToLoad(cSettingsRepositoryInterface & a_Settings) { // Check if the Plugins section exists. if (!a_Settings.KeyExists("Plugins")) { InsertDefaultPlugins(a_Settings); } AStringVector res; // Get the old format plugin list, and migrate it. // Upgrade path added on 2020-03-27 auto OldValues = a_Settings.GetValues("Plugins"); for (const auto & NameValue : OldValues) { AString ValueName = NameValue.first; if (ValueName.compare("Plugin") == 0) { AString PluginFile = NameValue.second; if ( !PluginFile.empty() && (PluginFile != "0") && (PluginFile != "1") ) { a_Settings.DeleteValue("Plugins", ValueName); a_Settings.SetValue("Plugins", PluginFile, "1"); } } } // for i - ini values // Get the list of plugins to load: auto Values = a_Settings.GetValues("Plugins"); for (const auto & NameValue : Values) { AString Enabled = NameValue.second; if (Enabled == "1") { res.push_back(NameValue.first); } } // for i - ini values return res; } ================================================ FILE: src/Bindings/PluginManager.h ================================================ #pragma once #include "../BlockType.h" #include "../Defines.h" #include "../FunctionRef.h" // fwd: class cBlockEntityWithItems; class cBrewingstandEntity; class cChunkDesc; class cClientHandle; class cCommandOutputCallback; class cCraftingGrid; class cCraftingRecipe; class cDropSpenserEntity; class cEntity; class cHopperEntity; class cItems; class cMonster; class cPickup; class cPlayer; class cPlugin; class cProjectileEntity; class cWindow; class cWorld; class cSettingsRepositoryInterface; class cDeadlockDetect; struct TakeDamageInfo; typedef std::shared_ptr cPluginPtr; typedef std::vector cPluginPtrs; // tolua_begin class cPluginManager { public: enum CommandResult { crExecuted, crUnknownCommand, crError, crBlocked, crNoPermission, } ; /** Defines the status of a single plugin - whether it is loaded, disabled or errored. */ enum ePluginStatus { /** The plugin has been loaded successfully. */ psLoaded, /** The plugin is disabled in settings.ini. */ psDisabled, /** The plugin is enabled in settings.ini but has been unloaded (by a command). */ psUnloaded, /** The plugin is enabled in settings.ini but has failed to load. m_LoadError is the description of the error. */ psError, /** The plugin has been loaded before, but after a folder refresh it is no longer present. The plugin will be unloaded in the next call to ReloadPlugins(). */ psNotFound, }; enum PluginHook { HOOK_BLOCK_SPREAD, HOOK_BLOCK_TO_PICKUPS, HOOK_BREWING_COMPLETING, HOOK_BREWING_COMPLETED, HOOK_CHAT, HOOK_CHUNK_AVAILABLE, HOOK_CHUNK_GENERATED, HOOK_CHUNK_GENERATING, HOOK_CHUNK_UNLOADED, HOOK_CHUNK_UNLOADING, HOOK_COLLECTING_PICKUP, HOOK_CRAFTING_NO_RECIPE, HOOK_DISCONNECT, HOOK_PLAYER_ANIMATION, HOOK_ENTITY_ADD_EFFECT, HOOK_ENTITY_CHANGING_WORLD, HOOK_ENTITY_CHANGED_WORLD, HOOK_EXECUTE_COMMAND, HOOK_EXPLODED, HOOK_EXPLODING, HOOK_HANDSHAKE, HOOK_HOPPER_PULLING_ITEM, HOOK_HOPPER_PUSHING_ITEM, HOOK_DROPSPENSE, HOOK_KILLED, HOOK_KILLING, HOOK_LOGIN, HOOK_LOGIN_FORGE, HOOK_PLAYER_BREAKING_BLOCK, HOOK_PLAYER_BROKEN_BLOCK, HOOK_PLAYER_DESTROYED, HOOK_PLAYER_EATING, HOOK_PLAYER_FISHED, HOOK_PLAYER_FISHING, HOOK_PLAYER_FOOD_LEVEL_CHANGE, HOOK_PLAYER_JOINED, HOOK_PLAYER_LEFT_CLICK, HOOK_PLAYER_MOVING, HOOK_PLAYER_OPENING_WINDOW, HOOK_PLAYER_PLACED_BLOCK, HOOK_PLAYER_PLACING_BLOCK, HOOK_PLAYER_CROUCHED, HOOK_PLAYER_RIGHT_CLICK, HOOK_PLAYER_RIGHT_CLICKING_ENTITY, HOOK_PLAYER_SHOOTING, HOOK_PLAYER_SPAWNED, HOOK_ENTITY_TELEPORT, HOOK_PLAYER_TOSSING_ITEM, HOOK_PLAYER_USED_BLOCK, HOOK_PLAYER_USED_ITEM, HOOK_PLAYER_USING_BLOCK, HOOK_PLAYER_USING_ITEM, HOOK_PLUGIN_MESSAGE, HOOK_PLUGINS_LOADED, HOOK_POST_CRAFTING, HOOK_PRE_CRAFTING, HOOK_PROJECTILE_HIT_BLOCK, HOOK_PROJECTILE_HIT_ENTITY, HOOK_SERVER_PING, HOOK_SPAWNED_ENTITY, HOOK_SPAWNED_MONSTER, HOOK_SPAWNING_ENTITY, HOOK_SPAWNING_MONSTER, HOOK_TAKE_DAMAGE, HOOK_TICK, HOOK_UPDATED_SIGN, HOOK_UPDATING_SIGN, HOOK_WEATHER_CHANGED, HOOK_WEATHER_CHANGING, HOOK_WORLD_STARTED, HOOK_WORLD_TICK, // tolua_end // Note that if a hook type is added, it may need processing in cPlugin::CanAddHook() descendants, // and it definitely needs adding in cPluginLua::GetHookFnName() ! // Keep these two as the last items, they are used for validity checking and get their values automagically HOOK_NUM_HOOKS, HOOK_MAX = HOOK_NUM_HOOKS - 1, } ; // tolua_export /** Defines the deferred actions needed for a plugin */ enum class PluginAction { Reload, Unload }; /** Used as a callback for enumerating bound commands */ class cCommandEnumCallback { public: virtual ~cCommandEnumCallback() {} /** Called for each command; return true to abort enumeration For console commands, a_Permission is not used (set to empty string) */ virtual bool Command(const AString & a_Command, const cPlugin * a_Plugin, const AString & a_Permission, const AString & a_HelpString) = 0; } ; /** Interface that must be provided by any class that implements a command handler, either in-game or console command. */ class cCommandHandler { public: // Force a virtual destructor in descendants virtual ~cCommandHandler() {} /** Executes the specified in-game command. a_Split is the command string, split at the spaces. a_Player is the player executing the command, nullptr in case of the console. a_Command is the entire command string. a_Output is the sink into which the additional text returned by the command handler should be sent; only used for console commands. */ virtual bool ExecuteCommand( const AStringVector & a_Split, cPlayer * a_Player, const AString & a_Command, cCommandOutputCallback * a_Output = nullptr ) = 0; }; typedef std::shared_ptr cCommandHandlerPtr; /** The interface used for enumerating and extern-calling plugins */ using cPluginCallback = cFunctionRef; typedef std::list PluginList; /** Called each tick, calls the plugins' OnTick hook, as well as processes plugin events (addition, removal) */ void Tick(float a_Dt); /** Returns the instance of the Plugin Manager (there is only ever one) */ static cPluginManager * Get(void); // tolua_export /** Refreshes the m_Plugins list based on the current contents of the Plugins folder. If an active plugin's folder is not found anymore, the plugin is set as psNotFound, but not yet unloaded. */ void RefreshPluginList(); // tolua_export /** Schedules a reload of the plugins to happen within the next call to Tick(). */ void ReloadPlugins(); // tolua_export /** Adds the plugin to the list of plugins called for the specified hook type. If a plugin adds multiple handlers for a single hook, it is added only once (ignore-duplicates). */ void AddHook(cPlugin * a_Plugin, int a_HookType); /** Returns the number of all plugins in m_Plugins (includes disabled, unloaded and errored plugins). */ size_t GetNumPlugins() const; // tolua_export /** Returns the number of plugins that are psLoaded. */ size_t GetNumLoadedPlugins(void) const; // tolua_export // Calls for individual hooks. Each returns false if the action is to continue or true if the plugin wants to abort bool CallHookBlockSpread (cWorld & a_World, Vector3i a_BlockPos, eSpreadSource a_Source); bool CallHookBlockToPickups (cWorld & a_World, Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, const cBlockEntity * a_BlockEntity, const cEntity * a_Digger, const cItem * a_Tool, cItems & a_Pickups); bool CallHookBrewingCompleting (cWorld & a_World, cBrewingstandEntity & a_Brewingstand); bool CallHookBrewingCompleted (cWorld & a_World, cBrewingstandEntity & a_Brewingstand); bool CallHookChat (cPlayer & a_Player, AString & a_Message); bool CallHookChunkAvailable (cWorld & a_World, int a_ChunkX, int a_ChunkZ); bool CallHookChunkGenerated (cWorld & a_World, int a_ChunkX, int a_ChunkZ, cChunkDesc * a_ChunkDesc); bool CallHookChunkGenerating (cWorld & a_World, int a_ChunkX, int a_ChunkZ, cChunkDesc * a_ChunkDesc); bool CallHookChunkUnloaded (cWorld & a_World, int a_ChunkX, int a_ChunkZ); bool CallHookChunkUnloading (cWorld & a_World, int a_ChunkX, int a_ChunkZ); bool CallHookCollectingPickup (cPlayer & a_Player, cPickup & a_Pickup); bool CallHookCraftingNoRecipe (cPlayer & a_Player, cCraftingGrid & a_Grid, cCraftingRecipe & a_Recipe); bool CallHookDisconnect (cClientHandle & a_Client, const AString & a_Reason); bool CallHookEntityAddEffect (cEntity & a_Entity, int a_EffectType, int a_EffectDurationTicks, int a_EffectIntensity, double a_DistanceModifier); bool CallHookEntityTeleport (cEntity & a_Entity, const Vector3d & a_OldPosition, const Vector3d & a_NewPosition); bool CallHookEntityChangingWorld (cEntity & a_Entity, cWorld & a_World); bool CallHookEntityChangedWorld (cEntity & a_Entity, cWorld & a_World); bool CallHookExecuteCommand (cPlayer * a_Player, const AStringVector & a_Split, const AString & a_EntireCommand, CommandResult & a_Result); // If a_Player == nullptr, it is a console cmd bool CallHookExploded (cWorld & a_World, double a_ExplosionSize, bool a_CanCauseFire, double a_X, double a_Y, double a_Z, eExplosionSource a_Source, void * a_SourceData); bool CallHookExploding (cWorld & a_World, double & a_ExplosionSize, bool & a_CanCauseFire, double a_X, double a_Y, double a_Z, eExplosionSource a_Source, void * a_SourceData); bool CallHookHandshake (cClientHandle & a_ClientHandle, const AString & a_Username); bool CallHookHopperPullingItem (cWorld & a_World, cHopperEntity & a_Hopper, int a_DstSlotNum, cBlockEntityWithItems & a_SrcEntity, int a_SrcSlotNum); bool CallHookHopperPushingItem (cWorld & a_World, cHopperEntity & a_Hopper, int a_SrcSlotNum, cBlockEntityWithItems & a_DstEntity, int a_DstSlotNum); bool CallHookDropSpense (cWorld & a_World, cDropSpenserEntity & a_DropSpenser, int a_SlotNum); bool CallHookKilled (cEntity & a_Victim, TakeDamageInfo & a_TDI, AString & a_DeathMessage); bool CallHookKilling (cEntity & a_Victim, cEntity * a_Killer, TakeDamageInfo & a_TDI); bool CallHookLogin (cClientHandle & a_Client, UInt32 a_ProtocolVersion, const AString & a_Username); bool CallHookLoginForge (cClientHandle & a_Client, AStringMap & a_Mods); bool CallHookPlayerAnimation (cPlayer & a_Player, int a_Animation); bool CallHookPlayerBreakingBlock (cPlayer & a_Player, Vector3i a_BlockPos, eBlockFace a_BlockFace, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta); bool CallHookPlayerBrokenBlock (cPlayer & a_Player, Vector3i a_BlockPos, eBlockFace a_BlockFace, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta); bool CallHookPlayerDestroyed (cPlayer & a_Player); bool CallHookPlayerEating (cPlayer & a_Player); bool CallHookPlayerFished (cPlayer & a_Player, const cItems & a_Reward, const int ExperienceAmount); bool CallHookPlayerFishing (cPlayer & a_Player, cItems & a_Reward, int & ExperienceAmount); bool CallHookPlayerFoodLevelChange (cPlayer & a_Player, int a_NewFoodLevel); bool CallHookPlayerJoined (cPlayer & a_Player); bool CallHookPlayerLeftClick (cPlayer & a_Player, Vector3i a_BlockPos, eBlockFace a_BlockFace, char a_Status); bool CallHookPlayerMoving (cPlayer & a_Player, const Vector3d & a_OldPosition, const Vector3d & a_NewPosition, bool a_PreviousIsOnGround); bool CallHookPlayerOpeningWindow (cPlayer & a_Player, cWindow & a_Window); bool CallHookPlayerPlacedBlock (cPlayer & a_Player, const sSetBlock & a_BlockChange); bool CallHookPlayerPlacingBlock (cPlayer & a_Player, const sSetBlock & a_BlockChange); bool CallHookPlayerCrouched (cPlayer & a_Player); bool CallHookPlayerRightClick (cPlayer & a_Player, Vector3i a_BlockPos, eBlockFace a_BlockFace, Vector3i a_CursorPos); bool CallHookPlayerRightClickingEntity(cPlayer & a_Player, cEntity & a_Entity); bool CallHookPlayerShooting (cPlayer & a_Player); bool CallHookPlayerSpawned (cPlayer & a_Player); bool CallHookPlayerTossingItem (cPlayer & a_Player); bool CallHookPlayerUsedBlock (cPlayer & a_Player, Vector3i a_BlockPos, eBlockFace a_BlockFace, Vector3i a_CursorPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta); bool CallHookPlayerUsedItem (cPlayer & a_Player, Vector3i a_BlockPos, eBlockFace a_BlockFace, Vector3i a_CursorPos); bool CallHookPlayerUsingBlock (cPlayer & a_Player, Vector3i a_BlockPos, eBlockFace a_BlockFace, Vector3i a_CursorPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta); bool CallHookPlayerUsingItem (cPlayer & a_Player, Vector3i a_BlockPos, eBlockFace a_BlockFace, Vector3i a_CursorPos); bool CallHookPluginMessage (cClientHandle & a_Client, const AString & a_Channel, ContiguousByteBufferView a_Message); bool CallHookPluginsLoaded (void); bool CallHookPostCrafting (cPlayer & a_Player, cCraftingGrid & a_Grid, cCraftingRecipe & a_Recipe); bool CallHookPreCrafting (cPlayer & a_Player, cCraftingGrid & a_Grid, cCraftingRecipe & a_Recipe); bool CallHookProjectileHitBlock (cProjectileEntity & a_Projectile, Vector3i a_BlockPos, eBlockFace a_Face, const Vector3d & a_BlockHitPos); bool CallHookProjectileHitEntity (cProjectileEntity & a_Projectile, cEntity & a_HitEntity); bool CallHookServerPing (cClientHandle & a_ClientHandle, AString & a_ServerDescription, int & a_OnlinePlayersCount, int & a_MaxPlayersCount, AString & a_Favicon); bool CallHookSpawnedEntity (cWorld & a_World, cEntity & a_Entity); bool CallHookSpawnedMonster (cWorld & a_World, cMonster & a_Monster); bool CallHookSpawningEntity (cWorld & a_World, cEntity & a_Entity); bool CallHookSpawningMonster (cWorld & a_World, cMonster & a_Monster); bool CallHookTakeDamage (cEntity & a_Receiver, TakeDamageInfo & a_TDI); bool CallHookUpdatedSign (cWorld & a_World, Vector3i a_BlockPos, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4, cPlayer * a_Player); bool CallHookUpdatingSign (cWorld & a_World, Vector3i a_BlockPos, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4, cPlayer * a_Player); bool CallHookWeatherChanged (cWorld & a_World); bool CallHookWeatherChanging (cWorld & a_World, eWeather & a_NewWeather); bool CallHookWorldStarted (cWorld & a_World); bool CallHookWorldTick (cWorld & a_World, std::chrono::milliseconds a_Dt, std::chrono::milliseconds a_LastTickDurationMSec); /** Queues the specified plugin to be unloaded in the next call to Tick(). Note that this function returns before the plugin is unloaded, to avoid deadlocks. */ void UnloadPlugin(const AString & a_PluginFolder); // tolua_export /** Queues the specified plugin to be reloaded in the next call to Tick(). Note that this function returns before the plugin is unloaded, to avoid deadlocks. */ void ReloadPlugin(const AString & a_PluginFolder); // tolua_export /** Loads the plugin from the specified plugin folder. Returns true if the plugin was loaded successfully or was already loaded before, false otherwise. */ bool LoadPlugin(const AString & a_PluginFolder); // tolua_export /** Removes all hooks the specified plugin has registered */ void RemoveHooks(cPlugin * a_Plugin); /** Removes the plugin of the specified name from the internal structures and deletes its object. */ void RemovePlugin(const AString & a_PluginName); /** Removes all command bindings that the specified plugin has made */ void RemovePluginCommands(cPlugin * a_Plugin); /** Returns true if the specified plugin is loaded. */ bool IsPluginLoaded(const AString & a_PluginName); // tolua_export /** Binds a command to the specified handler. Returns true if successful, false if command already bound. Exported in ManualBindings.cpp. */ bool BindCommand( const AString & a_Command, cPlugin * a_Plugin, cCommandHandlerPtr a_Handler, const AString & a_Permission, const AString & a_HelpString ); /** Calls a_Callback for each bound command, returns true if all commands were enumerated */ bool ForEachCommand(cCommandEnumCallback & a_Callback); // Exported in ManualBindings.cpp /** Returns true if the command is in the command map */ bool IsCommandBound(const AString & a_Command); // tolua_export /** Returns the permission needed for the specified command; empty string if command not found */ AString GetCommandPermission(const AString & a_Command); // tolua_export /** Executes the command, as if it was requested by a_Player. Checks permissions first. Returns crExecuted if executed. */ CommandResult ExecuteCommand(cPlayer & a_Player, const AString & a_Command); // tolua_export /** Executes the command, as if it was requested by a_Player. Permisssions are not checked. Returns crExecuted if executed. */ CommandResult ForceExecuteCommand(cPlayer & a_Player, const AString & a_Command); // tolua_export /** Removes all console command bindings that the specified plugin has made */ void RemovePluginConsoleCommands(cPlugin * a_Plugin); /** Binds a console command to the specified handler. Returns true if successful, false if command already bound. Exported in ManualBindings.cpp. */ bool BindConsoleCommand( const AString & a_Command, cPlugin * a_Plugin, cCommandHandlerPtr a_Handler, const AString & a_HelpString ); /** Calls a_Callback for each bound console command, returns true if all commands were enumerated */ bool ForEachConsoleCommand(cCommandEnumCallback & a_Callback); // Exported in ManualBindings.cpp /** Returns true if the console command is in the command map */ bool IsConsoleCommandBound(const AString & a_Command); // tolua_export /** Executes the command split into a_Split, as if it was given on the console. Returns true if executed. Output is sent to the a_Output callback Exported in ManualBindings.cpp with a different signature. */ bool ExecuteConsoleCommand(const AStringVector & a_Split, cCommandOutputCallback & a_Output, const AString & a_Command); /** Appends all commands beginning with a_Text (case-insensitive) into a_Results. If a_Player is not nullptr, only commands for which the player has permissions are added. */ void TabCompleteCommand(const AString & a_Text, AStringVector & a_Results, cPlayer * a_Player); /** Returns true if the specified hook type is within the allowed range */ static bool IsValidHookType(int a_HookType); /** Calls the specified callback with the plugin object of the specified plugin. Returns false if plugin not found, otherwise returns the value that the callback has returned. */ bool DoWithPlugin(const AString & a_PluginName, cPluginCallback a_Callback); /** Calls the specified callback for each plugin in m_Plugins. Returns true if all plugins have been reported, false if the callback has aborted the enumeration by returning true. */ bool ForEachPlugin(cPluginCallback a_Callback); /** Returns the name of the folder (cPlugin::GetFolderName()) from which the specified plugin was loaded. */ AString GetPluginFolderName(const AString & a_PluginName); // tolua_export /** Returns the path where individual plugins' folders are expected. The path doesn't end in a slash. */ static AString GetPluginsPath(void) { return "Plugins"; } // tolua_export private: friend class cRoot; class cCommandReg { public: cPlugin * m_Plugin; AString m_Permission; // Not used for console commands AString m_HelpString; cCommandHandlerPtr m_Handler; } ; typedef std::map HookMap; typedef std::map CommandMap; /** FolderNames of plugins that need an action (unload, reload, ...). The plugins will be acted upon within the next call to Tick(), to avoid multithreading issues. Protected against multithreaded access by m_CSPluginsNeedAction. */ std::vector> m_PluginsNeedAction; /** Protects m_PluginsToUnload against multithreaded access. */ mutable cCriticalSection m_CSPluginsNeedAction; /** All plugins that have been found in the Plugins folder. */ cPluginPtrs m_Plugins; HookMap m_Hooks; CommandMap m_Commands; CommandMap m_ConsoleCommands; /** If set to true, all the plugins will be reloaded within the next call to Tick(). */ bool m_bReloadPlugins; /** The deadlock detect in which all plugins should track their CSs. */ cDeadlockDetect & m_DeadlockDetect; cPluginManager(cDeadlockDetect & a_DeadlockDetect); virtual ~cPluginManager(); /** Reloads all plugins, defaulting to settings.ini for settings location */ void ReloadPluginsNow(void); /** Reloads all plugins with a settings repo expected to be initialised to settings.ini */ void ReloadPluginsNow(cSettingsRepositoryInterface & a_Settings); /** Unloads all plugins */ void UnloadPluginsNow(void); /** Handles writing default plugins if 'Plugins' key not found using a settings repo expected to be intialised to settings.ini */ void InsertDefaultPlugins(cSettingsRepositoryInterface & a_Settings); /** Tries to match a_Command to the internal table of commands, if a match is found, the corresponding plugin is called. Returns crExecuted if the command is executed. */ CommandResult HandleCommand(cPlayer & a_Player, const AString & a_Command, bool a_ShouldCheckPermissions); /** Returns the folders that are specified in the settings ini to load plugins from. */ AStringVector GetFoldersToLoad(cSettingsRepositoryInterface & a_Settings); /** Calls a_HookFunction on each plugin registered to the hook HookName. Returns false if the action is to continue or true if the plugin wants to abort. Accessible only from within PluginManager.cpp */ template bool GenericCallHook(PluginHook a_HookName, HookFunction a_HookFunction); } ; // tolua_export ================================================ FILE: src/Bindings/tolua++.h ================================================ // tolua++.h // Redirection file, needed because ToLua++ generates the Bindings.cpp file with >> #include "tolua++.h" << // Only used from Bindings.cpp #include "tolua++/include/tolua++.h" #ifdef _MSC_VER // Disable specific warnings for the generated Bindings.cpp file: #pragma warning(disable: 4800) // 'int' : forcing value to bool 'true' or 'false' (performance warning) #endif // _MSC_VER ================================================ FILE: src/BiomeDef.cpp ================================================ // BiomeDef.cpp // Implements biome helper functions #include "Globals.h" #include "BiomeDef.h" // The "map" used for biome <-> string conversions: static struct { EMCSBiome m_Biome; const char * m_String; } g_BiomeMap[] = { {biOcean, "Ocean"}, {biPlains, "Plains"}, {biDesert, "Desert"}, {biExtremeHills, "ExtremeHills"}, {biForest, "Forest"}, {biTaiga, "Taiga"}, {biSwampland, "Swampland"}, {biRiver, "River"}, {biNether, "Hell"}, {biNether, "Nether"}, {biEnd, "Sky"}, {biEnd, "End"}, {biFrozenOcean, "FrozenOcean"}, {biFrozenRiver, "FrozenRiver"}, {biIcePlains, "IcePlains"}, {biIcePlains, "Tundra"}, {biIceMountains, "IceMountains"}, {biMushroomIsland, "MushroomIsland"}, {biMushroomShore, "MushroomShore"}, {biBeach, "Beach"}, {biDesertHills, "DesertHills"}, {biForestHills, "ForestHills"}, {biTaigaHills, "TaigaHills"}, {biExtremeHillsEdge, "ExtremeHillsEdge"}, {biJungle, "Jungle"}, {biJungleHills, "JungleHills"}, // Release 1.7 biomes: {biJungleEdge, "JungleEdge"}, {biDeepOcean, "DeepOcean"}, {biStoneBeach, "StoneBeach"}, {biColdBeach, "ColdBeach"}, {biBirchForest, "BirchForest"}, {biBirchForestHills, "BirchForestHills"}, {biRoofedForest, "RoofedForest"}, {biColdTaiga, "ColdTaiga"}, {biColdTaigaHills, "ColdTaigaHills"}, {biMegaTaiga, "MegaTaiga"}, {biMegaTaigaHills, "MegaTaigaHills"}, {biExtremeHillsPlus, "ExtremeHillsPlus"}, {biSavanna, "Savanna"}, {biSavannaPlateau, "SavannaPlateau"}, {biMesa, "Mesa"}, {biMesaPlateauF, "MesaPlateauF"}, {biMesaPlateau, "MesaPlateau"}, // Release 1.7 variants: {biSunflowerPlains, "SunflowerPlains"}, {biDesertM, "DesertM"}, {biExtremeHillsM, "ExtremeHillsM"}, {biFlowerForest, "FlowerForest"}, {biTaigaM, "TaigaM"}, {biSwamplandM, "SwamplandM"}, {biIcePlainsSpikes, "IcePlainsSpikes"}, {biJungleM, "JungleM"}, {biJungleEdgeM, "JungleEdgeM"}, {biBirchForestM, "BirchForestM"}, {biBirchForestHillsM, "BirchForestHillsM"}, {biRoofedForestM, "RoofedForestM"}, {biColdTaigaM, "ColdTaigaM"}, {biMegaSpruceTaiga, "MegaSpruceTaiga"}, {biMegaSpruceTaigaHills, "MegaSpruceTaigaHills"}, {biExtremeHillsPlusM, "ExtremeHillsPlusM"}, {biSavannaM, "SavannaM"}, {biSavannaPlateauM, "SavannaPlateauM"}, {biMesaBryce, "MesaBryce"}, {biMesaPlateauFM, "MesaPlateauFM"}, {biMesaPlateauM, "MesaPlateauM"}, } ; EMCSBiome StringToBiome(const AString & a_BiomeString) { // If it is a number, return it: int res = atoi(a_BiomeString.c_str()); if ((res != 0) || (a_BiomeString.compare("0") == 0)) { if ((res >= biFirstBiome) && (res < biNumBiomes)) { return static_cast(res); } else if ((res >= biFirstVariantBiome) && (res < biNumVariantBiomes)) { return static_cast(res); } // It was an invalid number return biInvalidBiome; } for (size_t i = 0; i < ARRAYCOUNT(g_BiomeMap); i++) { if (NoCaseCompare(g_BiomeMap[i].m_String, a_BiomeString) == 0) { return g_BiomeMap[i].m_Biome; } } // for i - BiomeMap[] return biInvalidBiome; } AString BiomeToString(int a_Biome) { for (size_t i = 0; i < ARRAYCOUNT(g_BiomeMap); i++) { if (g_BiomeMap[i].m_Biome == a_Biome) { return g_BiomeMap[i].m_String; } } return AString(); } bool IsBiomeNoDownfall(EMCSBiome a_Biome) { switch (a_Biome) { case biDesert: case biDesertHills: case biDesertM: case biSavanna: case biSavannaM: case biSavannaPlateau: case biSavannaPlateauM: case biNether: case biEnd: { return true; } default: { return false; } } } bool IsBiomeVeryCold(EMCSBiome a_Biome) { switch (a_Biome) { case biFrozenOcean: case biFrozenRiver: case biIcePlains: case biIceMountains: case biColdBeach: case biColdTaiga: case biColdTaigaHills: case biIcePlainsSpikes: case biColdTaigaM: { return true; } default: { return false; } } } bool IsBiomeCold(EMCSBiome a_Biome) { switch (a_Biome) { case biExtremeHills: case biTaiga: case biTaigaHills: case biExtremeHillsEdge: case biStoneBeach: case biMegaTaiga: case biMegaTaigaHills: case biExtremeHillsPlus: case biExtremeHillsM: case biTaigaM: case biColdTaigaM: case biMegaSpruceTaiga: case biMegaSpruceTaigaHills: case biExtremeHillsPlusM: { return true; } default: { return false; } } } bool IsBiomeMountain(EMCSBiome a_Biome) { switch (a_Biome) { case biExtremeHills: case biExtremeHillsEdge: case biExtremeHillsM: case biExtremeHillsPlus: case biExtremeHillsPlusM: { return true; } default: { return false; } } } bool IsBiomeMesa(EMCSBiome a_Biome) { switch (a_Biome) { case biMesa: case biMesaPlateauF: case biMesaPlateau: case biMesaBryce: case biMesaPlateauFM: case biMesaPlateauM: { return true; } default: { return false; } } } int GetSnowStartHeight(EMCSBiome a_Biome) { switch (a_Biome) { case biIcePlainsSpikes: case biIcePlains: case biIceMountains: case biFrozenRiver: case biColdBeach: case biColdTaiga: case biColdTaigaHills: case biColdTaigaM: { // Always snow return 0; } case biExtremeHills: case biExtremeHillsM: case biExtremeHillsPlus: case biExtremeHillsPlusM: case biStoneBeach: { // Starts snowing at 96 return 96; } case biTaiga: case biTaigaHills: case biTaigaM: { // Start snowing at 130 return 130; } case biMegaTaiga: case biMegaSpruceTaiga: case biMegaTaigaHills: case biMegaSpruceTaigaHills: { // Start snowing at 160 return 160; } case biRiver: case biOcean: case biDeepOcean: { // Starts snowing at 280 return 280; } case biBirchForest: case biBirchForestHills: case biBirchForestM: case biBirchForestHillsM: { // Starts snowing at 335 return 335; } case biForest: case biForestHills: case biFlowerForest: case biRoofedForest: case biRoofedForestM: { // Starts snowing at 400 return 400; } case biPlains: case biSunflowerPlains: case biSwampland: case biSwamplandM: case biBeach: { // Starts snowing at 460 return 460; } case biMushroomIsland: case biMushroomShore: { // Starts snowing at 520 return 520; } case biJungle: case biJungleHills: case biJungleM: case biJungleEdge: case biJungleEdgeM: { // Starts snowing at 550 return 550; } case biDesert: case biDesertHills: case biDesertM: case biSavanna: case biSavannaM: case biSavannaPlateau: case biSavannaPlateauM: case biMesa: case biMesaBryce: case biMesaPlateau: case biMesaPlateauF: case biMesaPlateauFM: case biMesaPlateauM: { // These biomes don't actualy have any downfall. return 1000; } case biNether: case biEnd: { // These shouldn't get any snow at all. return 9999; } default: { return 0; } } } ================================================ FILE: src/BiomeDef.h ================================================ // BiomeDef.h // Defines relevant information and methods related to biomes #pragma once // tolua_begin /** Biome IDs The first batch corresponds to the clientside biomes, used by MineCraft. BiomeIDs over 255 are used by Cuberite internally and are translated to MC biomes before sending them to client */ enum EMCSBiome { biInvalidBiome = -1, biFirstBiome = 0, biOcean = 0, biPlains = 1, biDesert = 2, biExtremeHills = 3, biForest = 4, biTaiga = 5, biSwampland = 6, biRiver = 7, biHell = 8, // same as Nether biNether = 8, biSky = 9, // same as biEnd biEnd = 9, biFrozenOcean = 10, biFrozenRiver = 11, biIcePlains = 12, biTundra = 12, // same as Ice Plains biIceMountains = 13, biMushroomIsland = 14, biMushroomShore = 15, biBeach = 16, biDesertHills = 17, biForestHills = 18, biTaigaHills = 19, biExtremeHillsEdge = 20, biJungle = 21, biJungleHills = 22, // Release 1.7 biomes: biJungleEdge = 23, biDeepOcean = 24, biStoneBeach = 25, biColdBeach = 26, biBirchForest = 27, biBirchForestHills = 28, biRoofedForest = 29, biColdTaiga = 30, biColdTaigaHills = 31, biMegaTaiga = 32, biMegaTaigaHills = 33, biExtremeHillsPlus = 34, biSavanna = 35, biSavannaPlateau = 36, biMesa = 37, biMesaPlateauF = 38, biMesaPlateau = 39, // Automatically capture the maximum consecutive biome value into biMaxBiome: biNumBiomes, // True number of biomes, since they are zero-based biMaxBiome = biNumBiomes - 1, // The maximum biome value // Add this number to the biomes to get the variant biVariant = 128, // Release 1.7 biome variants: biFirstVariantBiome = 129, biSunflowerPlains = 129, biDesertM = 130, biExtremeHillsM = 131, biFlowerForest = 132, biTaigaM = 133, biSwamplandM = 134, biIcePlainsSpikes = 140, biJungleM = 149, biJungleEdgeM = 151, biBirchForestM = 155, biBirchForestHillsM = 156, biRoofedForestM = 157, biColdTaigaM = 158, biMegaSpruceTaiga = 160, biMegaSpruceTaigaHills = 161, biExtremeHillsPlusM = 162, biSavannaM = 163, biSavannaPlateauM = 164, biMesaBryce = 165, biMesaPlateauFM = 166, biMesaPlateauM = 167, // Automatically capture the maximum consecutive biome value into biVarientMaxBiome: biNumVariantBiomes, // True number of biomes, since they are zero-based biMaxVariantBiome = biNumVariantBiomes - 1, // The maximum biome value } ; // tolua_end /** Hash for EMCSBiome, so that it can be used in std::unordered_map etc. */ struct BiomeHasher { public: std::size_t operator() (const EMCSBiome a_Biome) const { return static_cast(a_Biome); } }; // tolua_begin /** Translates a biome string to biome enum. Takes either a number or a biome alias (built-in). Returns biInvalidBiome on failure. */ extern EMCSBiome StringToBiome(const AString & a_BiomeString); /** Translates biome enum into biome string. Returns empty string on failure (unknown biome). */ extern AString BiomeToString(int a_Biome); /** Returns true if the biome has no downfall - deserts and savannas */ extern bool IsBiomeNoDownfall(EMCSBiome a_Biome); /** Returns true if the biome is an ocean biome. */ inline bool IsBiomeOcean(int a_Biome) { return ((a_Biome == biOcean) || (a_Biome == biDeepOcean)); } /** Returns true if the biome is very cold (has snow on ground everywhere, turns top water to ice, has snowfall instead of rain everywhere). Doesn't report mildly cold biomes (where it snows above certain elevation), use IsBiomeCold() for those. */ extern bool IsBiomeVeryCold(EMCSBiome a_Biome); /** Returns true if the biome is cold (has snow and snowfall at higher elevations but not at regular heights). Doesn't report Very Cold biomes, use IsBiomeVeryCold() for those. */ extern bool IsBiomeCold(EMCSBiome a_Biome); /** Returns true if the biome is mountainous (mutations of the extreme hills biome) */ extern bool IsBiomeMountain(EMCSBiome a_Biome); /** Returns true if the biome is Mesa or one of its mutations. */ extern bool IsBiomeMesa(EMCSBiome a_Biome); /** Returns the height when a biome when a biome starts snowing. */ extern int GetSnowStartHeight(EMCSBiome a_Biome); // tolua_end ================================================ FILE: src/BlockArea.cpp ================================================ // BlockArea.cpp // NOTE: compile.sh checks for this file in order to determine if this is the Cuberite folder. // Please modify compile.sh if you want to rename or remove this file. // This file was chosen arbitrarily and it's a good enough indicator we're in the Cuberite folder. // Implements the cBlockArea object representing an area of block data that can be queried from cWorld and then accessed again without further queries // The object also supports writing the blockdata back into cWorld, even into other coords #include "Globals.h" #include "BlockArea.h" #include "OSSupport/GZipFile.h" #include "Blocks/BlockHandler.h" #include "ChunkData.h" #include "BlockEntities/BlockEntity.h" #include "Item.h" #include "BlockInfo.h" // Disable MSVC warnings: "conditional expression is constant" #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable:4127) #endif typedef void (CombinatorFunc)(BLOCKTYPE & a_DstType, BLOCKTYPE a_SrcType, NIBBLETYPE & a_DstMeta, NIBBLETYPE a_SrcMeta); /** Merges two blocktypes and blockmetas of the specified sizes and offsets using the specified combinator function This wild construct allows us to pass a function argument and still have it inlined by the compiler. */ template void InternalMergeBlocks( BLOCKTYPE * a_DstTypes, const BLOCKTYPE * a_SrcTypes, NIBBLETYPE * a_DstMetas, const NIBBLETYPE * a_SrcMetas, int a_SizeX, int a_SizeY, int a_SizeZ, int a_SrcOffX, int a_SrcOffY, int a_SrcOffZ, int a_DstOffX, int a_DstOffY, int a_DstOffZ, int a_SrcSizeX, int a_SrcSizeY, int a_SrcSizeZ, int a_DstSizeX, int a_DstSizeY, int a_DstSizeZ ) { UNUSED(a_SrcSizeY); UNUSED(a_DstSizeY); for (int y = 0; y < a_SizeY; y++) { int SrcBaseY = (y + a_SrcOffY) * a_SrcSizeX * a_SrcSizeZ; int DstBaseY = (y + a_DstOffY) * a_DstSizeX * a_DstSizeZ; for (int z = 0; z < a_SizeZ; z++) { int SrcBaseZ = SrcBaseY + (z + a_SrcOffZ) * a_SrcSizeX; int DstBaseZ = DstBaseY + (z + a_DstOffZ) * a_DstSizeX; int SrcIdx = SrcBaseZ + a_SrcOffX; int DstIdx = DstBaseZ + a_DstOffX; for (int x = 0; x < a_SizeX; x++) { if (MetasValid) { Combinator(a_DstTypes[DstIdx], a_SrcTypes[SrcIdx], a_DstMetas[DstIdx], a_SrcMetas[SrcIdx]); } else { NIBBLETYPE FakeDestMeta = 0; Combinator(a_DstTypes[DstIdx], a_SrcTypes[SrcIdx], FakeDestMeta, static_cast(0)); } ++DstIdx; ++SrcIdx; } // for x } // for z } // for y } /** Combinator used for cBlockArea::msOverwrite merging */ template void MergeCombinatorOverwrite(BLOCKTYPE & a_DstType, BLOCKTYPE a_SrcType, NIBBLETYPE & a_DstMeta, NIBBLETYPE a_SrcMeta) { a_DstType = a_SrcType; if (MetaValid) { a_DstMeta = a_SrcMeta; } } /** Combinator used for cBlockArea::msFillAir merging */ template void MergeCombinatorFillAir(BLOCKTYPE & a_DstType, BLOCKTYPE a_SrcType, NIBBLETYPE & a_DstMeta, NIBBLETYPE a_SrcMeta) { if (a_DstType == E_BLOCK_AIR) { a_DstType = a_SrcType; if (MetaValid) { a_DstMeta = a_SrcMeta; } } // "else" is the default, already in place } /** Combinator used for cBlockArea::msImprint merging */ template void MergeCombinatorImprint(BLOCKTYPE & a_DstType, BLOCKTYPE a_SrcType, NIBBLETYPE & a_DstMeta, NIBBLETYPE a_SrcMeta) { if (a_SrcType != E_BLOCK_AIR) { a_DstType = a_SrcType; if (MetaValid) { a_DstMeta = a_SrcMeta; } } // "else" is the default, already in place } /** Combinator used for cBlockArea::msLake merging */ template void MergeCombinatorLake(BLOCKTYPE & a_DstType, BLOCKTYPE a_SrcType, NIBBLETYPE & a_DstMeta, NIBBLETYPE a_SrcMeta) { // Sponge is the NOP block if (a_SrcType == E_BLOCK_SPONGE) { return; } // Air is always hollowed out if (a_SrcType == E_BLOCK_AIR) { a_DstType = E_BLOCK_AIR; if (MetaValid) { a_DstMeta = 0; } return; } // Water and lava are never overwritten switch (a_DstType) { case E_BLOCK_WATER: case E_BLOCK_STATIONARY_WATER: case E_BLOCK_LAVA: case E_BLOCK_STATIONARY_LAVA: { return; } } // Water and lava always overwrite switch (a_SrcType) { case E_BLOCK_WATER: case E_BLOCK_STATIONARY_WATER: case E_BLOCK_LAVA: case E_BLOCK_STATIONARY_LAVA: { a_DstType = a_SrcType; if (MetaValid) { a_DstMeta = a_SrcMeta; } return; } } if (a_SrcType == E_BLOCK_STONE) { switch (a_DstType) { case E_BLOCK_DIRT: case E_BLOCK_GRASS: case E_BLOCK_MYCELIUM: { a_DstType = E_BLOCK_STONE; if (MetaValid) { a_DstMeta = 0; } return; } } } // Everything else is left as it is } /** Combinator used for cBlockArea::msSpongePrint merging */ template void MergeCombinatorSpongePrint(BLOCKTYPE & a_DstType, BLOCKTYPE a_SrcType, NIBBLETYPE & a_DstMeta, NIBBLETYPE a_SrcMeta) { // Sponge overwrites nothing, everything else overwrites anything if (a_SrcType != E_BLOCK_SPONGE) { a_DstType = a_SrcType; if (MetaValid) { a_DstMeta = a_SrcMeta; } } } /** Combinator used for cBlockArea::msDifference merging */ template void MergeCombinatorDifference(BLOCKTYPE & a_DstType, BLOCKTYPE a_SrcType, NIBBLETYPE & a_DstMeta, NIBBLETYPE a_SrcMeta) { if ((a_DstType == a_SrcType) && (!MetaValid || (a_DstMeta == a_SrcMeta))) { a_DstType = E_BLOCK_AIR; if (MetaValid) { a_DstMeta = 0; } } else { a_DstType = a_SrcType; if (MetaValid) { a_DstMeta = a_SrcMeta; } } } /** Combinator used for cBlockArea::msSimpleCompare merging */ template void MergeCombinatorSimpleCompare(BLOCKTYPE & a_DstType, BLOCKTYPE a_SrcType, NIBBLETYPE & a_DstMeta, NIBBLETYPE a_SrcMeta) { if ((a_DstType == a_SrcType) && (!MetaValid || (a_DstMeta == a_SrcMeta))) { // The blocktypes are the same, and the blockmetas are not present or are the same a_DstType = E_BLOCK_AIR; } else { // The blocktypes or blockmetas differ a_DstType = E_BLOCK_STONE; } } /** Combinator used for cBlockArea::msMask merging */ template void MergeCombinatorMask(BLOCKTYPE & a_DstType, BLOCKTYPE a_SrcType, NIBBLETYPE & a_DstMeta, NIBBLETYPE a_SrcMeta) { // If the blocks are the same, keep the dest; otherwise replace with air if ((a_SrcType != a_DstType) || !MetaValid || (a_SrcMeta != a_DstMeta)) { a_DstType = E_BLOCK_AIR; if (MetaValid) { a_DstMeta = 0; } } } // Re-enable previously disabled MSVC warnings #ifdef _MSC_VER #pragma warning(pop) #endif //////////////////////////////////////////////////////////////////////////////// // cBlockArea: cBlockArea::cBlockArea(void) = default; bool cBlockArea::IsValidDataTypeCombination(int a_DataTypes) { // BlockEntities require that BlockTypes be present, too if ((a_DataTypes & baBlockEntities) != 0) { if ((a_DataTypes & baTypes) == 0) { return false; } } // All other combinations are considered valid return true; } void cBlockArea::Clear(void) { m_BlockTypes.reset(); m_BlockMetas.reset(); m_BlockLight.reset(); m_BlockSkyLight.reset(); m_BlockEntities.reset(); m_Origin.Set(0, 0, 0); m_Size.Set(0, 0, 0); } void cBlockArea::Create(int a_SizeX, int a_SizeY, int a_SizeZ, int a_DataTypes) { ASSERT(a_SizeX > 0); ASSERT(a_SizeY > 0); ASSERT(a_SizeZ > 0); ASSERT(IsValidDataTypeCombination(a_DataTypes)); // Warn if the height is too much, but proceed with the creation: if (a_SizeY > cChunkDef::Height) { LOGWARNING("Creating a cBlockArea with height larger than world height (%d). Continuing, but the area may misbehave.", a_SizeY); } Clear(); SetSize(a_SizeX, a_SizeY, a_SizeZ, a_DataTypes); Fill(a_DataTypes, E_BLOCK_AIR); } void cBlockArea::Create(const Vector3i & a_Size, int a_DataTypes) { Create(a_Size.x, a_Size.y, a_Size.z, a_DataTypes); } void cBlockArea::SetWEOffset(int a_OffsetX, int a_OffsetY, int a_OffsetZ) { m_WEOffset.Set(a_OffsetX, a_OffsetY, a_OffsetZ); } void cBlockArea::SetWEOffset(const Vector3i & a_Offset) { m_WEOffset.Set(a_Offset.x, a_Offset.y, a_Offset.z); } void cBlockArea::SetOrigin(int a_OriginX, int a_OriginY, int a_OriginZ) { m_Origin.Set(a_OriginX, a_OriginY, a_OriginZ); } void cBlockArea::SetOrigin(const Vector3i & a_Origin) { m_Origin.Set(a_Origin.x, a_Origin.y, a_Origin.z); } bool cBlockArea::IsValidRelCoords(int a_RelX, int a_RelY, int a_RelZ) const { return ( (a_RelX >= 0) && (a_RelX < m_Size.x) && (a_RelY >= 0) && (a_RelY < m_Size.y) && (a_RelZ >= 0) && (a_RelZ < m_Size.z) ); } bool cBlockArea::IsValidRelCoords(const Vector3i & a_RelCoords) const { return IsValidRelCoords(a_RelCoords.x, a_RelCoords.y, a_RelCoords.z); } bool cBlockArea::IsValidCoords(int a_BlockX, int a_BlockY, int a_BlockZ) const { return IsValidRelCoords(a_BlockX - m_Origin.x, a_BlockY - m_Origin.y, a_BlockZ - m_Origin.z); } bool cBlockArea::IsValidCoords(const Vector3i & a_Coords) const { return IsValidRelCoords(a_Coords - m_Origin); } bool cBlockArea::Read(cForEachChunkProvider & a_ForEachChunkProvider, int a_MinBlockX, int a_MaxBlockX, int a_MinBlockY, int a_MaxBlockY, int a_MinBlockZ, int a_MaxBlockZ, int a_DataTypes) { ASSERT(IsValidDataTypeCombination(a_DataTypes)); ASSERT(cChunkDef::IsValidHeight({a_MinBlockX, a_MinBlockY, a_MinBlockZ})); ASSERT(cChunkDef::IsValidHeight({a_MaxBlockX, a_MaxBlockY, a_MaxBlockZ})); ASSERT(a_MinBlockX <= a_MaxBlockX); ASSERT(a_MinBlockY <= a_MaxBlockY); ASSERT(a_MinBlockZ <= a_MaxBlockZ); // Include the Max coords: a_MaxBlockX += 1; a_MaxBlockY += 1; a_MaxBlockZ += 1; // Allocate the needed memory: Clear(); if (!SetSize(a_MaxBlockX - a_MinBlockX, a_MaxBlockY - a_MinBlockY, a_MaxBlockZ - a_MinBlockZ, a_DataTypes)) { return false; } m_Origin.Set(a_MinBlockX, a_MinBlockY, a_MinBlockZ); cChunkReader Reader(*this); // Convert block coords to chunks coords: int MinChunkX, MaxChunkX; int MinChunkZ, MaxChunkZ; cChunkDef::AbsoluteToRelative(a_MinBlockX, a_MinBlockY, a_MinBlockZ, MinChunkX, MinChunkZ); cChunkDef::AbsoluteToRelative(a_MaxBlockX, a_MaxBlockY, a_MaxBlockZ, MaxChunkX, MaxChunkZ); // Query block data: if (!a_ForEachChunkProvider.ForEachChunkInRect(MinChunkX, MaxChunkX, MinChunkZ, MaxChunkZ, Reader)) { Clear(); return false; } return true; } bool cBlockArea::Read(cForEachChunkProvider & a_ForEachChunkProvider, const cCuboid & a_Bounds, int a_DataTypes) { return Read( a_ForEachChunkProvider, a_Bounds.p1.x, a_Bounds.p2.x, a_Bounds.p1.y, a_Bounds.p2.y, a_Bounds.p1.z, a_Bounds.p2.z, a_DataTypes ); } bool cBlockArea::Read(cForEachChunkProvider & a_ForEachChunkProvider, const Vector3i & a_Point1, const Vector3i & a_Point2, int a_DataTypes) { return Read( a_ForEachChunkProvider, a_Point1.x, a_Point2.x, a_Point1.y, a_Point2.y, a_Point1.z, a_Point2.z, a_DataTypes ); } bool cBlockArea::Write(cForEachChunkProvider & a_ForEachChunkProvider, int a_MinBlockX, int a_MinBlockY, int a_MinBlockZ, int a_DataTypes) { ASSERT((a_DataTypes & GetDataTypes()) == a_DataTypes); // Are you requesting only the data that I have? ASSERT(cChunkDef::IsValidHeight({a_MinBlockX, a_MinBlockY, a_MinBlockZ})); ASSERT(cChunkDef::IsValidHeight({a_MinBlockX, a_MinBlockY + m_Size.y - 1, a_MinBlockZ})); return a_ForEachChunkProvider.WriteBlockArea(*this, a_MinBlockX, a_MinBlockY, a_MinBlockZ, a_DataTypes); } bool cBlockArea::Write(cForEachChunkProvider & a_ForEachChunkProvider, const Vector3i & a_MinCoords, int a_DataTypes) { return Write( a_ForEachChunkProvider, a_MinCoords.x, a_MinCoords.y, a_MinCoords.z, a_DataTypes ); } void cBlockArea::CopyTo(cBlockArea & a_Into) const { if (&a_Into == this) { LOGWARNING("Trying to copy a cBlockArea into self, ignoring."); return; } a_Into.Clear(); a_Into.SetSize(m_Size.x, m_Size.y, m_Size.z, GetDataTypes()); a_Into.m_Origin = m_Origin; size_t BlockCount = GetBlockCount(); if (HasBlockTypes()) { memcpy(a_Into.GetBlockTypes(), GetBlockTypes(), BlockCount * sizeof(BLOCKTYPE)); } if (HasBlockMetas()) { memcpy(a_Into.GetBlockMetas(), GetBlockMetas(), BlockCount * sizeof(NIBBLETYPE)); } if (HasBlockLights()) { memcpy(a_Into.GetBlockLight(), GetBlockLight(), BlockCount * sizeof(NIBBLETYPE)); } if (HasBlockSkyLights()) { memcpy(a_Into.GetBlockSkyLight(), GetBlockSkyLight(), BlockCount * sizeof(NIBBLETYPE)); } if (HasBlockEntities()) { a_Into.m_BlockEntities->clear(); for (const auto & keyPair: *m_BlockEntities) { const auto & pos = keyPair.second->GetPos(); a_Into.m_BlockEntities->emplace(keyPair.first, keyPair.second->Clone(pos)); } } } void cBlockArea::CopyFrom(const cBlockArea & a_From) { a_From.CopyTo(*this); } void cBlockArea::DumpToRawFile(const AString & a_FileName) { cFile f; if (!f.Open(a_FileName, cFile::fmWrite)) { LOGWARNING("cBlockArea: Cannot open file \"%s\" for raw dump", a_FileName.c_str()); return; } UInt32 SizeX = ntohl(static_cast(m_Size.x)); UInt32 SizeY = ntohl(static_cast(m_Size.y)); UInt32 SizeZ = ntohl(static_cast(m_Size.z)); f.Write(&SizeX, 4); f.Write(&SizeY, 4); f.Write(&SizeZ, 4); unsigned char DataTypes = static_cast(GetDataTypes()); f.Write(&DataTypes, 1); size_t NumBlocks = GetBlockCount(); if (HasBlockTypes()) { f.Write(GetBlockTypes(), NumBlocks * sizeof(BLOCKTYPE)); } if (HasBlockMetas()) { f.Write(GetBlockMetas(), NumBlocks); } if (HasBlockLights()) { f.Write(GetBlockLight(), NumBlocks); } if (HasBlockSkyLights()) { f.Write(GetBlockSkyLight(), NumBlocks); } } void cBlockArea::Crop(int a_AddMinX, int a_SubMaxX, int a_AddMinY, int a_SubMaxY, int a_AddMinZ, int a_SubMaxZ) { if ( (a_AddMinX + a_SubMaxX >= m_Size.x) || (a_AddMinY + a_SubMaxY >= m_Size.y) || (a_AddMinZ + a_SubMaxZ >= m_Size.z) ) { LOGWARNING("cBlockArea:Crop called with more croping than the dimensions: %d x %d x %d with cropping %d, %d and %d", m_Size.x, m_Size.y, m_Size.z, a_AddMinX + a_SubMaxX, a_AddMinY + a_SubMaxY, a_AddMinZ + a_SubMaxZ ); return; } if (HasBlockTypes()) { CropBlockTypes(a_AddMinX, a_SubMaxX, a_AddMinY, a_SubMaxY, a_AddMinZ, a_SubMaxZ); } if (HasBlockMetas()) { CropNibbles(m_BlockMetas, a_AddMinX, a_SubMaxX, a_AddMinY, a_SubMaxY, a_AddMinZ, a_SubMaxZ); } if (HasBlockLights()) { CropNibbles(m_BlockLight, a_AddMinX, a_SubMaxX, a_AddMinY, a_SubMaxY, a_AddMinZ, a_SubMaxZ); } if (HasBlockSkyLights()) { CropNibbles(m_BlockSkyLight, a_AddMinX, a_SubMaxX, a_AddMinY, a_SubMaxY, a_AddMinZ, a_SubMaxZ); } if (HasBlockEntities()) { const Vector3i AddMin{ a_AddMinX, a_AddMinY, a_AddMinZ }; const cCuboid CropBox{ AddMin, m_Size - Vector3i{a_SubMaxX, a_SubMaxY, a_SubMaxZ} }; // Move and crop block Entities: cBlockEntities oldBE; std::swap(oldBE, *m_BlockEntities); for (auto & keyPair: oldBE) { auto & be = keyPair.second; auto Pos = be->GetPos(); if (CropBox.IsInside(Pos)) { // The block entity is within the new coords, recalculate its coords to match the new area: Pos -= AddMin; be->SetPos(Pos); m_BlockEntities->emplace(MakeIndex(Pos.x, Pos.y, Pos.z), std::move(be)); } } } m_Origin.Move(a_AddMinX, a_AddMinY, a_AddMinZ); m_Size.x -= a_AddMinX + a_SubMaxX; m_Size.y -= a_AddMinY + a_SubMaxY; m_Size.z -= a_AddMinZ + a_SubMaxZ; } void cBlockArea::Expand(int a_SubMinX, int a_AddMaxX, int a_SubMinY, int a_AddMaxY, int a_SubMinZ, int a_AddMaxZ) { if (HasBlockTypes()) { ExpandBlockTypes(a_SubMinX, a_AddMaxX, a_SubMinY, a_AddMaxY, a_SubMinZ, a_AddMaxZ); } if (HasBlockMetas()) { ExpandNibbles(m_BlockMetas, a_SubMinX, a_AddMaxX, a_SubMinY, a_AddMaxY, a_SubMinZ, a_AddMaxZ); } if (HasBlockLights()) { ExpandNibbles(m_BlockLight, a_SubMinX, a_AddMaxX, a_SubMinY, a_AddMaxY, a_SubMinZ, a_AddMaxZ); } if (HasBlockSkyLights()) { ExpandNibbles(m_BlockSkyLight, a_SubMinX, a_AddMaxX, a_SubMinY, a_AddMaxY, a_SubMinZ, a_AddMaxZ); } if (HasBlockEntities()) { // Move block entities: cBlockEntities oldBE; std::swap(oldBE, *m_BlockEntities); for (auto & keyPair: oldBE) { auto & be = keyPair.second; auto posX = be->GetPosX() + a_SubMinX; auto posY = be->GetPosY() + a_SubMinY; auto posZ = be->GetPosZ() + a_SubMinZ; be->SetPos({posX, posY, posZ}); m_BlockEntities->emplace(MakeIndex(posX, posY, posZ), std::move(be)); } } m_Origin.Move(-a_SubMinX, -a_SubMinY, -a_SubMinZ); m_Size.x += a_SubMinX + a_AddMaxX; m_Size.y += a_SubMinY + a_AddMaxY; m_Size.z += a_SubMinZ + a_AddMaxZ; } void cBlockArea::Merge(const cBlockArea & a_Src, int a_RelX, int a_RelY, int a_RelZ, eMergeStrategy a_Strategy) { const NIBBLETYPE * SrcMetas = a_Src.GetBlockMetas(); NIBBLETYPE * DstMetas = GetBlockMetas(); bool IsDummyMetas = ((SrcMetas == nullptr) || (DstMetas == nullptr)); if (IsDummyMetas) { MergeByStrategy(a_Src, a_RelX, a_RelY, a_RelZ, a_Strategy, SrcMetas, DstMetas); } else { MergeByStrategy(a_Src, a_RelX, a_RelY, a_RelZ, a_Strategy, SrcMetas, DstMetas); } } void cBlockArea::Merge(const cBlockArea & a_Src, const Vector3i & a_RelMinCoords, eMergeStrategy a_Strategy) { Merge(a_Src, a_RelMinCoords.x, a_RelMinCoords.y, a_RelMinCoords.z, a_Strategy); } void cBlockArea::Fill(int a_DataTypes, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, NIBBLETYPE a_BlockLight, NIBBLETYPE a_BlockSkyLight) { if ((a_DataTypes & GetDataTypes()) != a_DataTypes) { LOGWARNING("%s: requested datatypes that are not present in the BlockArea object, trimming those away (req 0x%x, stor 0x%x)", __FUNCTION__, a_DataTypes, GetDataTypes() ); a_DataTypes = a_DataTypes & GetDataTypes(); } size_t BlockCount = GetBlockCount(); if ((a_DataTypes & baTypes) != 0) { for (size_t i = 0; i < BlockCount; i++) { m_BlockTypes[i] = a_BlockType; } } if ((a_DataTypes & baMetas) != 0) { for (size_t i = 0; i < BlockCount; i++) { m_BlockMetas[i] = a_BlockMeta; } } if ((a_DataTypes & baLight) != 0) { for (size_t i = 0; i < BlockCount; i++) { m_BlockLight[i] = a_BlockLight; } } if ((a_DataTypes & baSkyLight) != 0) { for (size_t i = 0; i < BlockCount; i++) { m_BlockSkyLight[i] = a_BlockSkyLight; } } // If the area contains block entities, remove those not matching and replace with whatever block entity block was filled if (HasBlockEntities() && ((a_DataTypes & baTypes) != 0)) { if (cBlockEntity::IsBlockEntityBlockType(a_BlockType)) { RescanBlockEntities(); } else { m_BlockEntities->clear(); } } } void cBlockArea::FillRelCuboid(int a_MinRelX, int a_MaxRelX, int a_MinRelY, int a_MaxRelY, int a_MinRelZ, int a_MaxRelZ, int a_DataTypes, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, NIBBLETYPE a_BlockLight, NIBBLETYPE a_BlockSkyLight ) { if ((a_DataTypes & GetDataTypes()) != a_DataTypes) { LOGWARNING("%s: requested datatypes that are not present in the BlockArea object, trimming those away (req 0x%x, stor 0x%x)", __FUNCTION__, a_DataTypes, GetDataTypes() ); a_DataTypes = a_DataTypes & GetDataTypes(); } if ((a_DataTypes & baTypes) != 0) { for (int y = a_MinRelY; y <= a_MaxRelY; y++) for (int z = a_MinRelZ; z <= a_MaxRelZ; z++) for (int x = a_MinRelX; x <= a_MaxRelX; x++) { m_BlockTypes[MakeIndex(x, y, z)] = a_BlockType; } // for x, z, y } if ((a_DataTypes & baMetas) != 0) { for (int y = a_MinRelY; y <= a_MaxRelY; y++) for (int z = a_MinRelZ; z <= a_MaxRelZ; z++) for (int x = a_MinRelX; x <= a_MaxRelX; x++) { m_BlockMetas[MakeIndex(x, y, z)] = a_BlockMeta; } // for x, z, y } if ((a_DataTypes & baLight) != 0) { for (int y = a_MinRelY; y <= a_MaxRelY; y++) for (int z = a_MinRelZ; z <= a_MaxRelZ; z++) for (int x = a_MinRelX; x <= a_MaxRelX; x++) { m_BlockLight[MakeIndex(x, y, z)] = a_BlockLight; } // for x, z, y } if ((a_DataTypes & baSkyLight) != 0) { for (int y = a_MinRelY; y <= a_MaxRelY; y++) for (int z = a_MinRelZ; z <= a_MaxRelZ; z++) for (int x = a_MinRelX; x <= a_MaxRelX; x++) { m_BlockSkyLight[MakeIndex(x, y, z)] = a_BlockSkyLight; } // for x, z, y } // If the area contains block entities, remove those in the affected cuboid and replace with whatever block entity block was filled: if (HasBlockEntities() && ((a_DataTypes & baTypes) != 0)) { if (cBlockEntity::IsBlockEntityBlockType(a_BlockType)) { RescanBlockEntities(); } else { m_BlockEntities->clear(); } } } void cBlockArea::FillRelCuboid(const cCuboid & a_RelCuboid, int a_DataTypes, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, NIBBLETYPE a_BlockLight, NIBBLETYPE a_BlockSkyLight ) { FillRelCuboid( a_RelCuboid.p1.x, a_RelCuboid.p2.x, a_RelCuboid.p1.y, a_RelCuboid.p2.y, a_RelCuboid.p1.z, a_RelCuboid.p2.z, a_DataTypes, a_BlockType, a_BlockMeta, a_BlockLight, a_BlockSkyLight ); } void cBlockArea::RelLine(int a_RelX1, int a_RelY1, int a_RelZ1, int a_RelX2, int a_RelY2, int a_RelZ2, int a_DataTypes, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, NIBBLETYPE a_BlockLight, NIBBLETYPE a_BlockSkyLight ) { // Bresenham-3D algorithm for drawing lines: int dx = abs(a_RelX2 - a_RelX1); int dy = abs(a_RelY2 - a_RelY1); int dz = abs(a_RelZ2 - a_RelZ1); int sx = (a_RelX1 < a_RelX2) ? 1 : -1; int sy = (a_RelY1 < a_RelY2) ? 1 : -1; int sz = (a_RelZ1 < a_RelZ2) ? 1 : -1; if (dx >= std::max(dy, dz)) // x dominant { int yd = dy - dx / 2; int zd = dz - dx / 2; for (;;) { RelSetData(a_RelX1, a_RelY1, a_RelZ1, a_DataTypes, a_BlockType, a_BlockMeta, a_BlockLight, a_BlockSkyLight); if (a_RelX1 == a_RelX2) { break; } if (yd >= 0) // move along y { a_RelY1 += sy; yd -= dx; } if (zd >= 0) // move along z { a_RelZ1 += sz; zd -= dx; } // move along x a_RelX1 += sx; yd += dy; zd += dz; } } else if (dy >= std::max(dx, dz)) // y dominant { int xd = dx - dy / 2; int zd = dz - dy / 2; for (;;) { RelSetData(a_RelX1, a_RelY1, a_RelZ1, a_DataTypes, a_BlockType, a_BlockMeta, a_BlockLight, a_BlockSkyLight); if (a_RelY1 == a_RelY2) { break; } if (xd >= 0) // move along x { a_RelX1 += sx; xd -= dy; } if (zd >= 0) // move along z { a_RelZ1 += sz; zd -= dy; } // move along y a_RelY1 += sy; xd += dx; zd += dz; } } else { // z dominant ASSERT(dz >= std::max(dx, dy)); int xd = dx - dz / 2; int yd = dy - dz / 2; for (;;) { RelSetData(a_RelX1, a_RelY1, a_RelZ1, a_DataTypes, a_BlockType, a_BlockMeta, a_BlockLight, a_BlockSkyLight); if (a_RelZ1 == a_RelZ2) { break; } if (xd >= 0) // move along x { a_RelX1 += sx; xd -= dz; } if (yd >= 0) // move along y { a_RelY1 += sy; yd -= dz; } // move along z a_RelZ1 += sz; xd += dx; yd += dy; } } // if (which dimension is dominant) } void cBlockArea::RelLine(const Vector3i & a_Point1, const Vector3i & a_Point2, int a_DataTypes, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, NIBBLETYPE a_BlockLight, NIBBLETYPE a_BlockSkyLight ) { RelLine( a_Point1.x, a_Point1.y, a_Point1.z, a_Point2.x, a_Point2.y, a_Point2.z, a_DataTypes, a_BlockType, a_BlockMeta, a_BlockLight, a_BlockSkyLight ); } void cBlockArea::RotateCCW(void) { if (!HasBlockTypes()) { LOGWARNING("cBlockArea: Cannot rotate blockmeta without blocktypes!"); return; } if (!HasBlockMetas()) { // There are no blockmetas to rotate, just use the NoMeta function RotateCCWNoMeta(); return; } // We are guaranteed that both blocktypes and blockmetas exist; rotate both at the same time: BLOCKARRAY NewTypes{ new BLOCKTYPE[GetBlockCount()] }; NIBBLEARRAY NewMetas{ new NIBBLETYPE[GetBlockCount()] }; for (int x = 0; x < m_Size.x; x++) { int NewZ = m_Size.x - x - 1; for (int z = 0; z < m_Size.z; z++) { int NewX = z; for (int y = 0; y < m_Size.y; y++) { auto NewIdx = MakeIndexForSize({ NewX, y, NewZ }, { m_Size.z, m_Size.y, m_Size.x }); auto OldIdx = MakeIndex(x, y, z); NewTypes[NewIdx] = m_BlockTypes[OldIdx]; NewMetas[NewIdx] = cBlockHandler::For(m_BlockTypes[OldIdx]).MetaRotateCCW(m_BlockMetas[OldIdx]); } // for y } // for z } // for x m_BlockTypes = std::move(NewTypes); m_BlockMetas = std::move(NewMetas); // Rotate the BlockEntities: if (HasBlockEntities()) { cBlockEntities oldBE; std::swap(oldBE, *m_BlockEntities); for (auto & keyPair: oldBE) { auto & be = keyPair.second; auto newX = be->GetPosZ(); auto newY = be->GetPosY(); auto newZ = m_Size.x - be->GetPosX() - 1; auto newIdx = newX + newZ * m_Size.z + newY * m_Size.x * m_Size.z; be->SetPos({newX, newY, newZ}); m_BlockEntities->emplace(newIdx, std::move(be)); } } std::swap(m_Size.x, m_Size.z); } void cBlockArea::RotateCW(void) { if (!HasBlockTypes()) { LOGWARNING("cBlockArea: Cannot rotate blockmeta without blocktypes!"); return; } if (!HasBlockMetas()) { // There are no blockmetas to rotate, just use the NoMeta function RotateCWNoMeta(); return; } // We are guaranteed that both blocktypes and blockmetas exist; rotate both at the same time: BLOCKARRAY NewTypes{ new BLOCKTYPE[GetBlockCount()] }; NIBBLEARRAY NewMetas{ new NIBBLETYPE[GetBlockCount()] }; for (int x = 0; x < m_Size.x; x++) { int NewZ = x; for (int z = 0; z < m_Size.z; z++) { int NewX = m_Size.z - z - 1; for (int y = 0; y < m_Size.y; y++) { auto NewIdx = MakeIndexForSize({ NewX, y, NewZ }, { m_Size.z, m_Size.y, m_Size.x }); auto OldIdx = MakeIndex(x, y, z); NewTypes[NewIdx] = m_BlockTypes[OldIdx]; NewMetas[NewIdx] = cBlockHandler::For(m_BlockTypes[OldIdx]).MetaRotateCW(m_BlockMetas[OldIdx]); } // for y } // for z } // for x m_BlockTypes = std::move(NewTypes); m_BlockMetas = std::move(NewMetas); // Rotate the BlockEntities: if (HasBlockEntities()) { cBlockEntities oldBE; std::swap(oldBE, *m_BlockEntities); for (auto & keyPair: oldBE) { auto & be = keyPair.second; auto newX = m_Size.z - be->GetPosZ() - 1; auto newY = be->GetPosY(); auto newZ = be->GetPosX(); auto newIdx = newX + newZ * m_Size.z + newY * m_Size.x * m_Size.z; be->SetPos({newX, newY, newZ}); m_BlockEntities->emplace(newIdx, std::move(be)); } } std::swap(m_Size.x, m_Size.z); } void cBlockArea::MirrorXY(void) { if (!HasBlockTypes()) { LOGWARNING("cBlockArea: Cannot mirror meta without blocktypes!"); return; } if (!HasBlockMetas()) { // There are no blockmetas to mirror, just use the NoMeta function MirrorXYNoMeta(); return; } // We are guaranteed that both blocktypes and blockmetas exist; mirror both at the same time: int HalfZ = m_Size.z / 2; int MaxZ = m_Size.z - 1; for (int y = 0; y < m_Size.y; y++) { for (int z = 0; z < HalfZ; z++) { for (int x = 0; x < m_Size.x; x++) { auto Idx1 = MakeIndex(x, y, z); auto Idx2 = MakeIndex(x, y, MaxZ - z); std::swap(m_BlockTypes[Idx1], m_BlockTypes[Idx2]); NIBBLETYPE Meta1 = cBlockHandler::For(m_BlockTypes[Idx2]).MetaMirrorXY(m_BlockMetas[Idx1]); NIBBLETYPE Meta2 = cBlockHandler::For(m_BlockTypes[Idx1]).MetaMirrorXY(m_BlockMetas[Idx2]); m_BlockMetas[Idx1] = Meta2; m_BlockMetas[Idx2] = Meta1; } // for x } // for z } // for y // Mirror the BlockEntities: if (HasBlockEntities()) { cBlockEntities oldBE; std::swap(oldBE, *m_BlockEntities); for (auto & keyPair: oldBE) { auto & be = keyPair.second; auto newX = be->GetPosX(); auto newY = be->GetPosY(); auto newZ = MaxZ - be->GetPosZ(); auto newIdx = MakeIndex(newX, newY, newZ); be->SetPos({newX, newY, newZ}); m_BlockEntities->emplace(newIdx, std::move(be)); } } } void cBlockArea::MirrorXZ(void) { if (!HasBlockTypes()) { LOGWARNING("cBlockArea: Cannot mirror meta without blocktypes!"); return; } if (!HasBlockMetas()) { // There are no blockmetas to mirror, just use the NoMeta function MirrorXZNoMeta(); return; } // We are guaranteed that both blocktypes and blockmetas exist; mirror both at the same time: int HalfY = m_Size.y / 2; int MaxY = m_Size.y - 1; for (int y = 0; y < HalfY; y++) { for (int z = 0; z < m_Size.z; z++) { for (int x = 0; x < m_Size.x; x++) { auto Idx1 = MakeIndex(x, y, z); auto Idx2 = MakeIndex(x, MaxY - y, z); std::swap(m_BlockTypes[Idx1], m_BlockTypes[Idx2]); NIBBLETYPE Meta1 = cBlockHandler::For(m_BlockTypes[Idx2]).MetaMirrorXZ(m_BlockMetas[Idx1]); NIBBLETYPE Meta2 = cBlockHandler::For(m_BlockTypes[Idx1]).MetaMirrorXZ(m_BlockMetas[Idx2]); m_BlockMetas[Idx1] = Meta2; m_BlockMetas[Idx2] = Meta1; } // for x } // for z } // for y // Mirror the BlockEntities: if (HasBlockEntities()) { cBlockEntities oldBE; std::swap(oldBE, *m_BlockEntities); for (auto & keyPair: oldBE) { auto & be = keyPair.second; auto newX = be->GetPosX(); auto newY = MaxY - be->GetPosY(); auto newZ = be->GetPosZ(); auto newIdx = MakeIndex(newX, newY, newZ); be->SetPos({newX, newY, newZ}); m_BlockEntities->emplace(newIdx, std::move(be)); } } } void cBlockArea::MirrorYZ(void) { if (!HasBlockTypes()) { LOGWARNING("cBlockArea: Cannot mirror meta without blocktypes!"); return; } if (!HasBlockMetas()) { // There are no blockmetas to mirror, just use the NoMeta function MirrorYZNoMeta(); return; } // We are guaranteed that both blocktypes and blockmetas exist; mirror both at the same time: int HalfX = m_Size.x / 2; int MaxX = m_Size.x - 1; for (int y = 0; y < m_Size.y; y++) { for (int z = 0; z < m_Size.z; z++) { for (int x = 0; x < HalfX; x++) { auto Idx1 = MakeIndex(x, y, z); auto Idx2 = MakeIndex(MaxX - x, y, z); std::swap(m_BlockTypes[Idx1], m_BlockTypes[Idx2]); NIBBLETYPE Meta1 = cBlockHandler::For(m_BlockTypes[Idx2]).MetaMirrorYZ(m_BlockMetas[Idx1]); NIBBLETYPE Meta2 = cBlockHandler::For(m_BlockTypes[Idx1]).MetaMirrorYZ(m_BlockMetas[Idx2]); m_BlockMetas[Idx1] = Meta2; m_BlockMetas[Idx2] = Meta1; } // for x } // for z } // for y // Mirror the BlockEntities: if (HasBlockEntities()) { cBlockEntities oldBE; std::swap(oldBE, *m_BlockEntities); for (auto & keyPair: oldBE) { auto & be = keyPair.second; auto newX = MaxX - be->GetPosX(); auto newY = be->GetPosY(); auto newZ = be->GetPosZ(); auto newIdx = MakeIndex(newX, newY, newZ); be->SetPos({newX, newY, newZ}); m_BlockEntities->emplace(newIdx, std::move(be)); } } } void cBlockArea::RotateCCWNoMeta(void) { if (HasBlockTypes()) { BLOCKARRAY NewTypes{ new BLOCKTYPE[GetBlockCount()] }; for (int x = 0; x < m_Size.x; x++) { int NewZ = m_Size.x - x - 1; for (int z = 0; z < m_Size.z; z++) { int NewX = z; for (int y = 0; y < m_Size.y; y++) { NewTypes[MakeIndexForSize({ NewX, y, NewZ }, { m_Size.z, m_Size.y, m_Size.x })] = m_BlockTypes[MakeIndex(x, y, z)]; } // for y } // for z } // for x m_BlockTypes = std::move(NewTypes); } if (HasBlockMetas()) { NIBBLEARRAY NewMetas{ new NIBBLETYPE[GetBlockCount()] }; for (int x = 0; x < m_Size.x; x++) { int NewZ = m_Size.x - x - 1; for (int z = 0; z < m_Size.z; z++) { int NewX = z; for (int y = 0; y < m_Size.y; y++) { NewMetas[MakeIndexForSize({ NewX, y, NewZ }, { m_Size.z, m_Size.y, m_Size.x })] = m_BlockMetas[MakeIndex(x, y, z)]; } // for y } // for z } // for x m_BlockMetas = std::move(NewMetas); } // Rotate the BlockEntities: if (HasBlockEntities()) { cBlockEntities oldBE; std::swap(oldBE, *m_BlockEntities); for (auto & keyPair: oldBE) { auto & be = keyPair.second; auto newX = be->GetPosZ(); auto newY = be->GetPosY(); auto newZ = m_Size.x - be->GetPosX() - 1; auto newIdx = newX + newZ * m_Size.z + newY * m_Size.x * m_Size.z; be->SetPos({newX, newY, newZ}); m_BlockEntities->emplace(newIdx, std::move(be)); } } std::swap(m_Size.x, m_Size.z); } void cBlockArea::RotateCWNoMeta(void) { if (HasBlockTypes()) { BLOCKARRAY NewTypes{ new BLOCKTYPE[GetBlockCount()] }; for (int z = 0; z < m_Size.z; z++) { int NewX = m_Size.z - z - 1; for (int x = 0; x < m_Size.x; x++) { int NewZ = x; for (int y = 0; y < m_Size.y; y++) { NewTypes[MakeIndexForSize({ NewX, y, NewZ }, { m_Size.z, m_Size.y, m_Size.x })] = m_BlockTypes[MakeIndex(x, y, z)]; } // for y } // for x } // for z m_BlockTypes = std::move(NewTypes); } if (HasBlockMetas()) { NIBBLEARRAY NewMetas{ new NIBBLETYPE[GetBlockCount()] }; for (int z = 0; z < m_Size.z; z++) { int NewX = m_Size.z - z - 1; for (int x = 0; x < m_Size.x; x++) { int NewZ = x; for (int y = 0; y < m_Size.y; y++) { NewMetas[MakeIndexForSize({ NewX, y, NewZ }, { m_Size.z, m_Size.y, m_Size.x })] = m_BlockMetas[MakeIndex(x, y, z)]; } // for y } // for x } // for z m_BlockMetas = std::move(NewMetas); } // Rotate the BlockEntities: if (HasBlockEntities()) { cBlockEntities oldBE; std::swap(oldBE, *m_BlockEntities); for (auto & keyPair: oldBE) { auto & be = keyPair.second; auto newX = m_Size.z - be->GetPosZ() - 1; auto newY = be->GetPosY(); auto newZ = be->GetPosX(); auto newIdx = newX + newZ * m_Size.z + newY * m_Size.x * m_Size.z; be->SetPos({newX, newY, newZ}); m_BlockEntities->emplace(newIdx, std::move(be)); } } std::swap(m_Size.x, m_Size.z); } void cBlockArea::MirrorXYNoMeta(void) { int HalfZ = m_Size.z / 2; int MaxZ = m_Size.z - 1; if (HasBlockTypes()) { for (int y = 0; y < m_Size.y; y++) { for (int z = 0; z < HalfZ; z++) { for (int x = 0; x < m_Size.x; x++) { std::swap(m_BlockTypes[MakeIndex(x, y, z)], m_BlockTypes[MakeIndex(x, y, MaxZ - z)]); } // for x } // for z } // for y } // if (HasBlockTypes) if (HasBlockMetas()) { for (int y = 0; y < m_Size.y; y++) { for (int z = 0; z < HalfZ; z++) { for (int x = 0; x < m_Size.x; x++) { std::swap(m_BlockMetas[MakeIndex(x, y, z)], m_BlockMetas[MakeIndex(x, y, MaxZ - z)]); } // for x } // for z } // for y } // if (HasBlockMetas) // Mirror the BlockEntities: if (HasBlockEntities()) { cBlockEntities oldBE; std::swap(oldBE, *m_BlockEntities); for (auto & keyPair: oldBE) { auto & be = keyPair.second; auto newX = be->GetPosX(); auto newY = be->GetPosY(); auto newZ = MaxZ - be->GetPosZ(); auto newIdx = MakeIndex(newX, newY, newZ); be->SetPos({newX, newY, newZ}); m_BlockEntities->emplace(newIdx, std::move(be)); } } } void cBlockArea::MirrorXZNoMeta(void) { int HalfY = m_Size.y / 2; int MaxY = m_Size.y - 1; if (HasBlockTypes()) { for (int y = 0; y < HalfY; y++) { for (int z = 0; z < m_Size.z; z++) { for (int x = 0; x < m_Size.x; x++) { std::swap(m_BlockTypes[MakeIndex(x, y, z)], m_BlockTypes[MakeIndex(x, MaxY - y, z)]); } // for x } // for z } // for y } // if (HasBlockTypes) if (HasBlockMetas()) { for (int y = 0; y < HalfY; y++) { for (int z = 0; z < m_Size.z; z++) { for (int x = 0; x < m_Size.x; x++) { std::swap(m_BlockMetas[MakeIndex(x, y, z)], m_BlockMetas[MakeIndex(x, MaxY - y, z)]); } // for x } // for z } // for y } // if (HasBlockMetas) // Mirror the BlockEntities: if (HasBlockEntities()) { cBlockEntities oldBE; std::swap(oldBE, *m_BlockEntities); for (auto & keyPair: oldBE) { auto & be = keyPair.second; auto newX = be->GetPosX(); auto newY = MaxY - be->GetPosY(); auto newZ = be->GetPosZ(); auto newIdx = MakeIndex(newX, newY, newZ); be->SetPos({newX, newY, newZ}); m_BlockEntities->emplace(newIdx, std::move(be)); } } } void cBlockArea::MirrorYZNoMeta(void) { int HalfX = m_Size.x / 2; int MaxX = m_Size.x - 1; if (HasBlockTypes()) { for (int y = 0; y < m_Size.y; y++) { for (int z = 0; z < m_Size.z; z++) { for (int x = 0; x < HalfX; x++) { std::swap(m_BlockTypes[MakeIndex(x, y, z)], m_BlockTypes[MakeIndex(MaxX - x, y, z)]); } // for x } // for z } // for y } // if (HasBlockTypes) if (HasBlockMetas()) { for (int y = 0; y < m_Size.y; y++) { for (int z = 0; z < m_Size.z; z++) { for (int x = 0; x < HalfX; x++) { std::swap(m_BlockMetas[MakeIndex(x, y, z)], m_BlockMetas[MakeIndex(MaxX - x, y, z)]); } // for x } // for z } // for y } // if (HasBlockMetas) // Mirror the BlockEntities: if (HasBlockEntities()) { cBlockEntities oldBE; std::swap(oldBE, *m_BlockEntities); for (auto & keyPair: oldBE) { auto & be = keyPair.second; auto newX = MaxX - be->GetPosX(); auto newY = be->GetPosY(); auto newZ = be->GetPosZ(); auto newIdx = MakeIndex(newX, newY, newZ); be->SetPos({newX, newY, newZ}); m_BlockEntities->emplace(newIdx, std::move(be)); } } } void cBlockArea::SetRelBlockType(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType) { ASSERT(m_BlockTypes != nullptr); auto idx = MakeIndex(a_RelX, a_RelY, a_RelZ); m_BlockTypes[idx] = a_BlockType; // Update the block entities, if appropriate: if (HasBlockEntities()) { auto itr = m_BlockEntities->find(idx); if (itr != m_BlockEntities->end()) { if (itr->second->GetBlockType() == a_BlockType) { // The block entity is for the same block type, keep the current one return; } m_BlockEntities->erase(itr); } if (cBlockEntity::IsBlockEntityBlockType(a_BlockType)) { NIBBLETYPE meta = HasBlockMetas() ? m_BlockMetas[idx] : 0; m_BlockEntities->emplace(idx, cBlockEntity::CreateByBlockType(a_BlockType, meta, {a_RelX, a_RelY, a_RelZ})); } } } void cBlockArea::SetBlockType(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType) { SetRelBlockType(a_BlockX - m_Origin.x, a_BlockY - m_Origin.y, a_BlockZ - m_Origin.z, a_BlockType); } void cBlockArea::SetRelBlockMeta(int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_BlockMeta) { SetRelNibble(a_RelX, a_RelY, a_RelZ, a_BlockMeta, GetBlockMetas()); } void cBlockArea::SetBlockMeta(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_BlockMeta) { SetNibble(a_BlockX, a_BlockY, a_BlockZ, a_BlockMeta, GetBlockMetas()); } void cBlockArea::SetRelBlockLight(int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_BlockLight) { SetRelNibble(a_RelX, a_RelY, a_RelZ, a_BlockLight, GetBlockLight()); } void cBlockArea::SetBlockLight(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_BlockLight) { SetNibble(a_BlockX, a_BlockY, a_BlockZ, a_BlockLight, GetBlockLight()); } void cBlockArea::SetRelBlockSkyLight(int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_BlockSkyLight) { SetRelNibble(a_RelX, a_RelY, a_RelZ, a_BlockSkyLight, GetBlockSkyLight()); } void cBlockArea::SetBlockSkyLight(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_BlockSkyLight) { SetNibble(a_BlockX, a_BlockY, a_BlockZ, a_BlockSkyLight, GetBlockSkyLight()); } BLOCKTYPE cBlockArea::GetRelBlockType(int a_RelX, int a_RelY, int a_RelZ) const { if (m_BlockTypes == nullptr) { LOGWARNING("cBlockArea: BlockTypes have not been read!"); return E_BLOCK_AIR; } return m_BlockTypes[MakeIndex(a_RelX, a_RelY, a_RelZ)]; } BLOCKTYPE cBlockArea::GetBlockType(int a_BlockX, int a_BlockY, int a_BlockZ) const { return GetRelBlockType(a_BlockX - m_Origin.x, a_BlockY - m_Origin.y, a_BlockZ - m_Origin.z); } NIBBLETYPE cBlockArea::GetRelBlockMeta(int a_RelX, int a_RelY, int a_RelZ) const { return GetRelNibble(a_RelX, a_RelY, a_RelZ, GetBlockMetas()); } NIBBLETYPE cBlockArea::GetBlockMeta(int a_BlockX, int a_BlockY, int a_BlockZ) const { return GetNibble(a_BlockX, a_BlockY, a_BlockZ, GetBlockMetas()); } NIBBLETYPE cBlockArea::GetRelBlockLight(int a_RelX, int a_RelY, int a_RelZ) const { return GetRelNibble(a_RelX, a_RelY, a_RelZ, GetBlockLight()); } NIBBLETYPE cBlockArea::GetBlockLight(int a_BlockX, int a_BlockY, int a_BlockZ) const { return GetNibble(a_BlockX, a_BlockY, a_BlockZ, GetBlockLight()); } NIBBLETYPE cBlockArea::GetRelBlockSkyLight(int a_RelX, int a_RelY, int a_RelZ) const { return GetRelNibble(a_RelX, a_RelY, a_RelZ, GetBlockSkyLight()); } NIBBLETYPE cBlockArea::GetBlockSkyLight(int a_BlockX, int a_BlockY, int a_BlockZ) const { return GetNibble(a_BlockX, a_BlockY, a_BlockZ, GetBlockSkyLight()); } void cBlockArea::SetBlockTypeMeta(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) { SetRelBlockTypeMeta(a_BlockX - m_Origin.x, a_BlockY - m_Origin.y, a_BlockZ - m_Origin.z, a_BlockType, a_BlockMeta); } void cBlockArea::SetRelBlockTypeMeta(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) { auto idx = MakeIndex(a_RelX, a_RelY, a_RelZ); if (m_BlockTypes == nullptr) { LOGWARNING("%s: BlockTypes not available but requested to be written to.", __FUNCTION__); } else { m_BlockTypes[idx] = a_BlockType; } if (m_BlockMetas == nullptr) { LOGWARNING("%s: BlockMetas not available but requested to be written to.", __FUNCTION__); } else { m_BlockMetas[idx] = a_BlockMeta; } // Update the block entities, if appropriate: if (HasBlockEntities()) { auto itr = m_BlockEntities->find(idx); if (itr != m_BlockEntities->end()) { if (itr->second->GetBlockType() == a_BlockType) { // The block entity is for the same block type, keep the current one return; } m_BlockEntities->erase(itr); } if (cBlockEntity::IsBlockEntityBlockType(a_BlockType)) { m_BlockEntities->emplace(idx, cBlockEntity::CreateByBlockType(a_BlockType, a_BlockMeta, {a_RelX, a_RelY, a_RelZ})); } } } void cBlockArea::GetBlockTypeMeta(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta) const { return GetRelBlockTypeMeta(a_BlockX - m_Origin.x, a_BlockY - m_Origin.y, a_BlockZ - m_Origin.z, a_BlockType, a_BlockMeta); } void cBlockArea::GetRelBlockTypeMeta(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta) const { auto idx = MakeIndex(a_RelX, a_RelY, a_RelZ); if (m_BlockTypes == nullptr) { LOGWARNING("cBlockArea: BlockTypes have not been read!"); a_BlockType = E_BLOCK_AIR; } else { a_BlockType = m_BlockTypes[idx]; } if (m_BlockMetas == nullptr) { LOGWARNING("cBlockArea: BlockMetas have not been read!"); a_BlockMeta = 0; } else { a_BlockMeta = m_BlockMetas[idx]; } } cCuboid cBlockArea::GetBounds(void) const { return cCuboid( m_Origin, m_Origin + m_Size - Vector3i(1, 1, 1) ); } size_t cBlockArea::CountNonAirBlocks(void) const { // Check if blocktypes are valid: if (m_BlockTypes == nullptr) { LOGWARNING("%s: BlockTypes have not been read!", __FUNCTION__); return 0; } // Count the blocks: size_t res = 0; for (int y = 0; y < m_Size.y; y++) { for (int z = 0; z < m_Size.z; z++) { for (int x = 0; x < m_Size.x; x++) { if (m_BlockTypes[MakeIndex(x, y, z)] != E_BLOCK_AIR) { ++res; } } // for x } // for z } // for y return res; } size_t cBlockArea::CountSpecificBlocks(BLOCKTYPE a_BlockType) const { // If blocktypes are not valid, log a warning and return zero occurences: if (m_BlockTypes == nullptr) { LOGWARNING("%s: BlockTypes not available!", __FUNCTION__); return 0; } // Count the blocks: size_t num = GetBlockCount(); size_t res = 0; for (size_t i = 0; i < num; i++) { if (m_BlockTypes[i] == a_BlockType) { res++; } } return res; } size_t cBlockArea::CountSpecificBlocks(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) const { // If blocktypes are not valid, log a warning and return zero occurences: if (m_BlockTypes == nullptr) { LOGWARNING("%s: BlockTypes not available!", __FUNCTION__); return 0; } // If blockmetas are not valid, log a warning and count only blocktypes: if (m_BlockMetas == nullptr) { LOGWARNING("%s: BlockMetas not available, comparing blocktypes only!", __FUNCTION__); return CountSpecificBlocks(a_BlockType); } // Count the blocks: size_t num = GetBlockCount(); size_t res = 0; for (size_t i = 0; i < num; i++) { if ((m_BlockTypes[i] == a_BlockType) && (m_BlockMetas[i] == a_BlockMeta)) { res++; } } return res; } void cBlockArea::GetNonAirCropRelCoords(int & a_MinRelX, int & a_MinRelY, int & a_MinRelZ, int & a_MaxRelX, int & a_MaxRelY, int & a_MaxRelZ, BLOCKTYPE a_IgnoreBlockType) { // Check if blocktypes are valid: if (m_BlockTypes == nullptr) { LOGWARNING("%s: BlockTypes have not been read!", __FUNCTION__); a_MinRelX = 1; a_MaxRelX = 0; return; } // Walk all the blocks and find the min and max coords for the non-ignored ones: int MaxX = 0, MinX = m_Size.x - 1; int MaxY = 0, MinY = m_Size.y - 1; int MaxZ = 0, MinZ = m_Size.z - 1; for (int y = 0; y < m_Size.y; y++) { for (int z = 0; z < m_Size.z; z++) { for (int x = 0; x < m_Size.x; x++) { if (m_BlockTypes[MakeIndex(x, y, z)] == a_IgnoreBlockType) { continue; } // The block is not ignored, update any coords that need updating: if (x < MinX) { MinX = x; } if (x > MaxX) { MaxX = x; } if (y < MinY) { MinY = y; } if (y > MaxY) { MaxY = y; } if (z < MinZ) { MinZ = z; } if (z > MaxZ) { MaxZ = z; } } // for x } // for z } // for y // Assign to the output: a_MinRelX = MinX; a_MinRelY = MinY; a_MinRelZ = MinZ; a_MaxRelX = MaxX; a_MaxRelY = MaxY; a_MaxRelZ = MaxZ; } int cBlockArea::GetDataTypes(void) const { int res = 0; if (m_BlockTypes != nullptr) { res |= baTypes; } if (m_BlockMetas != nullptr) { res |= baMetas; } if (m_BlockLight != nullptr) { res |= baLight; } if (m_BlockSkyLight != nullptr) { res |= baSkyLight; } if (m_BlockEntities != nullptr) { res |= baBlockEntities; } return res; } bool cBlockArea::SetSize(int a_SizeX, int a_SizeY, int a_SizeZ, int a_DataTypes) { ASSERT(IsValidDataTypeCombination(a_DataTypes)); BLOCKARRAY NewBlocks; NIBBLEARRAY NewMetas; NIBBLEARRAY NewLight; NIBBLEARRAY NewSkyLight; cBlockEntitiesPtr NewBlockEntities; // Try to allocate the new storage if ((a_DataTypes & baTypes) != 0) { NewBlocks.reset(new BLOCKTYPE[ToUnsigned(a_SizeX * a_SizeY * a_SizeZ)]); if (NewBlocks == nullptr) { return false; } } if ((a_DataTypes & baMetas) != 0) { NewMetas.reset(new NIBBLETYPE[ToUnsigned(a_SizeX * a_SizeY * a_SizeZ)]); if (NewMetas == nullptr) { return false; } } if ((a_DataTypes & baLight) != 0) { NewLight.reset(new NIBBLETYPE[ToUnsigned(a_SizeX * a_SizeY * a_SizeZ)]); if (NewLight == nullptr) { return false; } } if ((a_DataTypes & baSkyLight) != 0) { NewSkyLight.reset(new NIBBLETYPE[ToUnsigned(a_SizeX * a_SizeY * a_SizeZ)]); if (NewSkyLight == nullptr) { return false; } } if ((a_DataTypes & baBlockEntities) != 0) { NewBlockEntities.reset(new cBlockEntities); if (NewBlockEntities == nullptr) { return false; } } // Commit changes m_BlockTypes = std::move(NewBlocks); m_BlockMetas = std::move(NewMetas); m_BlockLight = std::move(NewLight); m_BlockSkyLight = std::move(NewSkyLight); m_BlockEntities = std::move(NewBlockEntities); m_Size.Set(a_SizeX, a_SizeY, a_SizeZ); return true; } size_t cBlockArea::MakeIndexForSize(Vector3i a_RelPos, Vector3i a_Size) { ASSERT(a_RelPos.x >= 0); ASSERT(a_RelPos.x < a_Size.x); ASSERT(a_RelPos.y >= 0); ASSERT(a_RelPos.y < a_Size.y); ASSERT(a_RelPos.z >= 0); ASSERT(a_RelPos.z < a_Size.z); return static_cast(a_RelPos.x + a_RelPos.z * a_Size.x + a_RelPos.y * a_Size.x * a_Size.z); } bool cBlockArea::DoWithBlockEntityRelAt(int a_RelX, int a_RelY, int a_RelZ, cBlockEntityCallback a_Callback) { ASSERT(IsValidRelCoords(a_RelX, a_RelY, a_RelZ)); if (!HasBlockEntities()) { return false; } auto idx = MakeIndex(a_RelX, a_RelY, a_RelZ); auto itr = m_BlockEntities->find(idx); if (itr == m_BlockEntities->end()) { return false; } return a_Callback(*itr->second); } bool cBlockArea::DoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBlockEntityCallback a_Callback) { return DoWithBlockEntityRelAt(a_BlockX - m_Origin.x, a_BlockY - m_Origin.y, a_BlockZ - m_Origin.z, a_Callback); } bool cBlockArea::ForEachBlockEntity(cBlockEntityCallback a_Callback) { if (!HasBlockEntities()) { return true; } for (auto & keyPair: *m_BlockEntities) { if (a_Callback(*keyPair.second)) { return false; } } return true; } void cBlockArea::SetRelNibble(int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_Value, NIBBLETYPE * a_Array) { if (a_Array == nullptr) { LOGWARNING("cBlockArea: datatype has not been read!"); return; } a_Array[MakeIndex(a_RelX, a_RelY, a_RelZ)] = a_Value; } void cBlockArea::SetNibble(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_Value, NIBBLETYPE * a_Array) { SetRelNibble(a_BlockX - m_Origin.x, a_BlockY - m_Origin.y, a_BlockZ - m_Origin.z, a_Value, a_Array); } NIBBLETYPE cBlockArea::GetRelNibble(int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE * a_Array) const { if (a_Array == nullptr) { LOGWARNING("cBlockArea: datatype has not been read!"); return 16; } return a_Array[MakeIndex(a_RelX, a_RelY, a_RelZ)]; } NIBBLETYPE cBlockArea::GetNibble(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE * a_Array) const { return GetRelNibble(a_BlockX - m_Origin.x, a_BlockY - m_Origin.y, a_BlockZ - m_Origin.z, a_Array); } void cBlockArea::CropBlockTypes(int a_AddMinX, int a_SubMaxX, int a_AddMinY, int a_SubMaxY, int a_AddMinZ, int a_SubMaxZ) { int NewSizeX = GetSizeX() - a_AddMinX - a_SubMaxX; int NewSizeY = GetSizeY() - a_AddMinY - a_SubMaxY; int NewSizeZ = GetSizeZ() - a_AddMinZ - a_SubMaxZ; BLOCKARRAY NewBlockTypes{ new BLOCKTYPE[ToUnsigned(NewSizeX * NewSizeY * NewSizeZ)] }; size_t idx = 0; for (int y = 0; y < NewSizeY; y++) { for (int z = 0; z < NewSizeZ; z++) { for (int x = 0; x < NewSizeX; x++) { auto OldIndex = MakeIndex(x + a_AddMinX, y + a_AddMinY, z + a_AddMinZ); NewBlockTypes[idx++] = m_BlockTypes[OldIndex]; } // for x } // for z } // for y m_BlockTypes = std::move(NewBlockTypes); } void cBlockArea::CropNibbles(NIBBLEARRAY & a_Array, int a_AddMinX, int a_SubMaxX, int a_AddMinY, int a_SubMaxY, int a_AddMinZ, int a_SubMaxZ) { int NewSizeX = GetSizeX() - a_AddMinX - a_SubMaxX; int NewSizeY = GetSizeY() - a_AddMinY - a_SubMaxY; int NewSizeZ = GetSizeZ() - a_AddMinZ - a_SubMaxZ; NIBBLEARRAY NewNibbles{ new NIBBLETYPE[ToUnsigned(NewSizeX * NewSizeY * NewSizeZ)] }; size_t idx = 0; for (int y = 0; y < NewSizeY; y++) { for (int z = 0; z < NewSizeZ; z++) { for (int x = 0; x < NewSizeX; x++) { NewNibbles[idx++] = a_Array[MakeIndex(x + a_AddMinX, y + a_AddMinY, z + a_AddMinZ)]; } // for x } // for z } // for y a_Array = std::move(NewNibbles); } void cBlockArea::ExpandBlockTypes(int a_SubMinX, int a_AddMaxX, int a_SubMinY, int a_AddMaxY, int a_SubMinZ, int a_AddMaxZ) { int NewSizeX = m_Size.x + a_SubMinX + a_AddMaxX; int NewSizeY = m_Size.y + a_SubMinY + a_AddMaxY; int NewSizeZ = m_Size.z + a_SubMinZ + a_AddMaxZ; size_t BlockCount = static_cast(NewSizeX * NewSizeY * NewSizeZ); BLOCKARRAY NewBlockTypes{ new BLOCKTYPE[BlockCount] }; memset(NewBlockTypes.get(), 0, BlockCount * sizeof(BLOCKTYPE)); size_t OldIndex = 0; for (int y = 0; y < m_Size.y; y++) { int IndexBaseY = (y + a_SubMinY) * m_Size.x * m_Size.z; for (int z = 0; z < m_Size.z; z++) { int IndexBaseZ = IndexBaseY + (z + a_SubMinZ) * m_Size.x; auto idx = static_cast(IndexBaseZ + a_SubMinX); for (int x = 0; x < m_Size.x; x++) { NewBlockTypes[idx++] = m_BlockTypes[OldIndex++]; } // for x } // for z } // for y m_BlockTypes = std::move(NewBlockTypes); } void cBlockArea::ExpandNibbles(NIBBLEARRAY & a_Array, int a_SubMinX, int a_AddMaxX, int a_SubMinY, int a_AddMaxY, int a_SubMinZ, int a_AddMaxZ) { int NewSizeX = m_Size.x + a_SubMinX + a_AddMaxX; int NewSizeY = m_Size.y + a_SubMinY + a_AddMaxY; int NewSizeZ = m_Size.z + a_SubMinZ + a_AddMaxZ; size_t BlockCount = static_cast(NewSizeX * NewSizeY * NewSizeZ); NIBBLEARRAY NewNibbles{ new NIBBLETYPE[BlockCount] }; memset(NewNibbles.get(), 0, BlockCount * sizeof(NIBBLETYPE)); size_t OldIndex = 0; for (int y = 0; y < m_Size.y; y++) { int IndexBaseY = (y + a_SubMinY) * m_Size.x * m_Size.z; for (int z = 0; z < m_Size.z; z++) { int IndexBaseZ = IndexBaseY + (z + a_SubMinZ) * m_Size.x; auto idx = static_cast(IndexBaseZ + a_SubMinX); for (int x = 0; x < m_Size.x; x++) { NewNibbles[idx++] = a_Array[OldIndex++]; } // for x } // for z } // for y a_Array = std::move(NewNibbles); } void cBlockArea::RelSetData( int a_RelX, int a_RelY, int a_RelZ, int a_DataTypes, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, NIBBLETYPE a_BlockLight, NIBBLETYPE a_BlockSkyLight ) { if (!IsValidCoords(a_RelX, a_RelY, a_RelZ)) { return; } auto Index = MakeIndex(a_RelX, a_RelY, a_RelZ); if ((a_DataTypes & baTypes) != 0) { m_BlockTypes[Index] = a_BlockType; } if ((a_DataTypes & baMetas) != 0) { m_BlockMetas[Index] = a_BlockMeta; } if ((a_DataTypes & baLight) != 0) { m_BlockLight[Index] = a_BlockLight; } if ((a_DataTypes & baSkyLight) != 0) { m_BlockSkyLight[Index] = a_BlockSkyLight; } // Update the block entities, if appropriate: if (HasBlockEntities()) { auto itr = m_BlockEntities->find(Index); if (itr != m_BlockEntities->end()) { if (itr->second->GetBlockType() == a_BlockType) { // The block entity is for the same block type, keep the current one return; } // The block entity is for a different block type, remove it: m_BlockEntities->erase(itr); } if (cBlockEntity::IsBlockEntityBlockType(a_BlockType)) { // The block type should have a block entity attached to it, create an empty one: m_BlockEntities->emplace(Index, cBlockEntity::CreateByBlockType(a_BlockType, a_BlockMeta, {a_RelX, a_RelY, a_RelZ})); } } } template void cBlockArea::MergeByStrategy(const cBlockArea & a_Src, int a_RelX, int a_RelY, int a_RelZ, eMergeStrategy a_Strategy, const NIBBLETYPE * SrcMetas, NIBBLETYPE * DstMetas) { // Block types are compulsory, block metas are optional if (!HasBlockTypes() || !a_Src.HasBlockTypes()) { LOGWARNING("%s: cannot merge because one of the areas doesn't have blocktypes.", __FUNCTION__); return; } // Dst is *this, Src is a_Src int SrcOffX = std::max(0, -a_RelX); // Offset in Src where to start reading int DstOffX = std::max(0, a_RelX); // Offset in Dst where to start writing int SizeX = std::min(a_Src.GetSizeX() - SrcOffX, GetSizeX() - DstOffX); // How many blocks to copy int SrcOffY = std::max(0, -a_RelY); // Offset in Src where to start reading int DstOffY = std::max(0, a_RelY); // Offset in Dst where to start writing int SizeY = std::min(a_Src.GetSizeY() - SrcOffY, GetSizeY() - DstOffY); // How many blocks to copy int SrcOffZ = std::max(0, -a_RelZ); // Offset in Src where to start reading int DstOffZ = std::max(0, a_RelZ); // Offset in Dst where to start writing int SizeZ = std::min(a_Src.GetSizeZ() - SrcOffZ, GetSizeZ() - DstOffZ); // How many blocks to copy [&] { switch (a_Strategy) { case cBlockArea::msOverwrite: { InternalMergeBlocks >( GetBlockTypes(), a_Src.GetBlockTypes(), DstMetas, SrcMetas, SizeX, SizeY, SizeZ, SrcOffX, SrcOffY, SrcOffZ, DstOffX, DstOffY, DstOffZ, a_Src.GetSizeX(), a_Src.GetSizeY(), a_Src.GetSizeZ(), m_Size.x, m_Size.y, m_Size.z ); return; } // case msOverwrite case cBlockArea::msFillAir: { InternalMergeBlocks >( GetBlockTypes(), a_Src.GetBlockTypes(), DstMetas, SrcMetas, SizeX, SizeY, SizeZ, SrcOffX, SrcOffY, SrcOffZ, DstOffX, DstOffY, DstOffZ, a_Src.GetSizeX(), a_Src.GetSizeY(), a_Src.GetSizeZ(), m_Size.x, m_Size.y, m_Size.z ); return; } // case msFillAir case cBlockArea::msImprint: { InternalMergeBlocks >( GetBlockTypes(), a_Src.GetBlockTypes(), DstMetas, SrcMetas, SizeX, SizeY, SizeZ, SrcOffX, SrcOffY, SrcOffZ, DstOffX, DstOffY, DstOffZ, a_Src.GetSizeX(), a_Src.GetSizeY(), a_Src.GetSizeZ(), m_Size.x, m_Size.y, m_Size.z ); return; } // case msImprint case cBlockArea::msLake: { InternalMergeBlocks >( GetBlockTypes(), a_Src.GetBlockTypes(), DstMetas, SrcMetas, SizeX, SizeY, SizeZ, SrcOffX, SrcOffY, SrcOffZ, DstOffX, DstOffY, DstOffZ, a_Src.GetSizeX(), a_Src.GetSizeY(), a_Src.GetSizeZ(), m_Size.x, m_Size.y, m_Size.z ); return; } // case msLake case cBlockArea::msSpongePrint: { InternalMergeBlocks >( GetBlockTypes(), a_Src.GetBlockTypes(), DstMetas, SrcMetas, SizeX, SizeY, SizeZ, SrcOffX, SrcOffY, SrcOffZ, DstOffX, DstOffY, DstOffZ, a_Src.GetSizeX(), a_Src.GetSizeY(), a_Src.GetSizeZ(), m_Size.x, m_Size.y, m_Size.z ); return; } // case msSpongePrint case cBlockArea::msDifference: { InternalMergeBlocks >( GetBlockTypes(), a_Src.GetBlockTypes(), DstMetas, SrcMetas, SizeX, SizeY, SizeZ, SrcOffX, SrcOffY, SrcOffZ, DstOffX, DstOffY, DstOffZ, a_Src.GetSizeX(), a_Src.GetSizeY(), a_Src.GetSizeZ(), m_Size.x, m_Size.y, m_Size.z ); return; } // case msDifference case cBlockArea::msSimpleCompare: { InternalMergeBlocks >( GetBlockTypes(), a_Src.GetBlockTypes(), DstMetas, SrcMetas, SizeX, SizeY, SizeZ, SrcOffX, SrcOffY, SrcOffZ, DstOffX, DstOffY, DstOffZ, a_Src.GetSizeX(), a_Src.GetSizeY(), a_Src.GetSizeZ(), m_Size.x, m_Size.y, m_Size.z ); return; } // case msSimpleCompare case cBlockArea::msMask: { InternalMergeBlocks >( GetBlockTypes(), a_Src.GetBlockTypes(), DstMetas, SrcMetas, SizeX, SizeY, SizeZ, SrcOffX, SrcOffY, SrcOffZ, DstOffX, DstOffY, DstOffZ, a_Src.GetSizeX(), a_Src.GetSizeY(), a_Src.GetSizeZ(), m_Size.x, m_Size.y, m_Size.z ); return; } // case msMask } // switch (a_Strategy) UNREACHABLE("Unsupported block area merge strategy"); }(); if (HasBlockEntities()) { if (a_Src.HasBlockEntities()) { MergeBlockEntities(a_RelX, a_RelY, a_RelZ, a_Src); } else { RescanBlockEntities(); } } } void cBlockArea::MergeBlockEntities(int a_RelX, int a_RelY, int a_RelZ, const cBlockArea & a_Src) { // Only supported with both BlockEntities and BlockTypes (caller should check): ASSERT(HasBlockTypes()); ASSERT(HasBlockEntities()); ASSERT(a_Src.HasBlockTypes()); ASSERT(a_Src.HasBlockEntities()); // Remove block entities that no longer match the block at their coords: RemoveNonMatchingBlockEntities(); // Clone BEs from a_Src wherever a BE is missing: for (int y = 0; y < m_Size.y; ++y) for (int z = 0; z < m_Size.z; ++z) for (int x = 0; x < m_Size.x; ++x) { auto idx = MakeIndex(x, y, z); auto type = m_BlockTypes[idx]; if (!cBlockEntity::IsBlockEntityBlockType(type)) { continue; } // This block should have a block entity, check that there is one: auto itr = m_BlockEntities->find(idx); if (itr != m_BlockEntities->end()) { // There is one already continue; } // Copy a BE from a_Src, if it exists there: auto srcX = x + a_RelX; auto srcY = y + a_RelY; auto srcZ = z + a_RelZ; if (a_Src.IsValidRelCoords(srcX, srcY, srcZ)) { auto srcIdx = a_Src.MakeIndex(srcX, srcY, srcZ); auto itrSrc = a_Src.m_BlockEntities->find(srcIdx); if (itrSrc != a_Src.m_BlockEntities->end()) { m_BlockEntities->emplace(idx, itrSrc->second->Clone({x, y, z})); continue; } } // No BE found in a_Src, insert a new empty one: NIBBLETYPE meta = HasBlockMetas() ? m_BlockMetas[idx] : 0; m_BlockEntities->emplace(idx, cBlockEntity::CreateByBlockType(type, meta, {x, y, z})); } // for x, z, y } void cBlockArea::RescanBlockEntities(void) { // Only supported with both BlockEntities and BlockTypes if (!HasBlockEntities() || !HasBlockTypes()) { return; } // Remove block entities that no longer match the block at their coords: RemoveNonMatchingBlockEntities(); // Add block entities for all block types that should have a BE assigned to them: for (int y = 0; y < m_Size.y; ++y) for (int z = 0; z < m_Size.z; ++z) for (int x = 0; x < m_Size.x; ++x) { auto idx = MakeIndex(x, y, z); auto type = m_BlockTypes[idx]; if (!cBlockEntity::IsBlockEntityBlockType(type)) { continue; } // This block should have a block entity, check that there is one: auto itr = m_BlockEntities->find(idx); if (itr != m_BlockEntities->end()) { continue; } // Create a new BE for this block: NIBBLETYPE meta = HasBlockMetas() ? m_BlockMetas[idx] : 0; m_BlockEntities->emplace(idx, cBlockEntity::CreateByBlockType(type, meta, {x, y, z})); } // for x, z, y } void cBlockArea::RemoveNonMatchingBlockEntities(void) { // Only supported with both BlockEntities and BlockTypes: ASSERT(HasBlockTypes()); ASSERT(HasBlockEntities()); cBlockEntities oldBE; std::swap(oldBE, *m_BlockEntities); for (auto & keyPair: oldBE) { auto type = m_BlockTypes[static_cast(keyPair.first)]; if (type == keyPair.second->GetBlockType()) { m_BlockEntities->insert(std::move(keyPair)); } } } cBlockEntity * cBlockArea::GetBlockEntityRel(Vector3i a_RelPos) { if (!HasBlockEntities()) { return nullptr; } auto itr = m_BlockEntities->find(MakeIndex(a_RelPos)); return (itr == m_BlockEntities->end()) ? nullptr : itr->second.get(); } //////////////////////////////////////////////////////////////////////////////// // cBlockArea::cChunkReader: cBlockArea::cChunkReader::cChunkReader(cBlockArea & a_Area) : m_Area(a_Area), m_AreaBounds(cCuboid(a_Area.GetOrigin(), a_Area.GetOrigin() + a_Area.GetSize() - Vector3i(1, 1, 1))), m_Origin(a_Area.m_Origin.x, a_Area.m_Origin.y, a_Area.m_Origin.z), m_CurrentChunkX(0), m_CurrentChunkZ(0) { } void cBlockArea::cChunkReader::CopyNibbles(NIBBLETYPE * a_AreaDst, const NIBBLETYPE * a_ChunkSrc) { int SizeY = m_Area.m_Size.y; int MinY = m_Origin.y; // SizeX, SizeZ are the dmensions of the block data to copy from the current chunk (size of the geometric union) // OffX, OffZ are the offsets of the current chunk data from the area origin // BaseX, BaseZ are the offsets of the area data within the current chunk from the chunk borders int SizeX = cChunkDef::Width; int SizeZ = cChunkDef::Width; int OffX, OffZ; int BaseX, BaseZ; OffX = m_CurrentChunkX * cChunkDef::Width - m_Origin.x; if (OffX < 0) { BaseX = -OffX; SizeX += OffX; // SizeX is decreased, OffX is negative OffX = 0; } else { BaseX = 0; } OffZ = m_CurrentChunkZ * cChunkDef::Width - m_Origin.z; if (OffZ < 0) { BaseZ = -OffZ; SizeZ += OffZ; // SizeZ is decreased, OffZ is negative OffZ = 0; } else { BaseZ = 0; } // If the chunk extends beyond the area in the X or Z axis, cut off the Size: if ((m_CurrentChunkX + 1) * cChunkDef::Width > m_Origin.x + m_Area.m_Size.x) { SizeX -= (m_CurrentChunkX + 1) * cChunkDef::Width - (m_Origin.x + m_Area.m_Size.x); } if ((m_CurrentChunkZ + 1) * cChunkDef::Width > m_Origin.z + m_Area.m_Size.z) { SizeZ -= (m_CurrentChunkZ + 1) * cChunkDef::Width - (m_Origin.z + m_Area.m_Size.z); } for (int y = 0; y < SizeY; y++) { int ChunkY = MinY + y; int AreaY = y; for (int z = 0; z < SizeZ; z++) { int ChunkZ = BaseZ + z; int AreaZ = OffZ + z; for (int x = 0; x < SizeX; x++) { int ChunkX = BaseX + x; int AreaX = OffX + x; a_AreaDst[m_Area.MakeIndex(AreaX, AreaY, AreaZ)] = cChunkDef::GetNibble(a_ChunkSrc, ChunkX, ChunkY, ChunkZ); } // for x } // for z } // for y } bool cBlockArea::cChunkReader::Coords(int a_ChunkX, int a_ChunkZ) { m_CurrentChunkX = a_ChunkX; m_CurrentChunkZ = a_ChunkZ; return true; } void cBlockArea::cChunkReader::ChunkData(const ChunkBlockData & a_BlockData, const ChunkLightData & a_LightData) { 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) { 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); } // Copy the blocktypes: if (m_Area.m_BlockTypes != nullptr) { for (int y = 0; y < SizeY; y++) { int InChunkY = MinY + y; int AreaY = y; for (int z = 0; z < SizeZ; z++) { int InChunkZ = BaseZ + z; int AreaZ = OffZ + z; for (int x = 0; x < SizeX; x++) { int InChunkX = BaseX + x; int AreaX = OffX + x; m_Area.m_BlockTypes[m_Area.MakeIndex(AreaX, AreaY, AreaZ)] = a_BlockData.GetBlock({ InChunkX, InChunkY, InChunkZ }); } // for x } // for z } // for y } // Copy the block metas: if (m_Area.m_BlockMetas != nullptr) { for (int y = 0; y < SizeY; y++) { int InChunkY = MinY + y; int AreaY = y; for (int z = 0; z < SizeZ; z++) { int InChunkZ = BaseZ + z; int AreaZ = OffZ + z; for (int x = 0; x < SizeX; x++) { int InChunkX = BaseX + x; int AreaX = OffX + x; m_Area.m_BlockMetas[m_Area.MakeIndex(AreaX, AreaY, AreaZ)] = a_BlockData.GetMeta({ InChunkX, InChunkY, InChunkZ }); } // for x } // for z } // for y } // Copy the blocklight: if (m_Area.m_BlockLight != nullptr) { for (int y = 0; y < SizeY; y++) { int InChunkY = MinY + y; int AreaY = y; for (int z = 0; z < SizeZ; z++) { int InChunkZ = BaseZ + z; int AreaZ = OffZ + z; for (int x = 0; x < SizeX; x++) { int InChunkX = BaseX + x; int AreaX = OffX + x; m_Area.m_BlockLight[m_Area.MakeIndex(AreaX, AreaY, AreaZ)] = a_LightData.GetBlockLight({ InChunkX, InChunkY, InChunkZ }); } // for x } // for z } // for y } // Copy the skylight: if (m_Area.m_BlockSkyLight != nullptr) { for (int y = 0; y < SizeY; y++) { int InChunkY = MinY + y; int AreaY = y; for (int z = 0; z < SizeZ; z++) { int InChunkZ = BaseZ + z; int AreaZ = OffZ + z; for (int x = 0; x < SizeX; x++) { int InChunkX = BaseX + x; int AreaX = OffX + x; m_Area.m_BlockSkyLight[m_Area.MakeIndex(AreaX, AreaY, AreaZ)] = a_LightData.GetSkyLight({ InChunkX, InChunkY, InChunkZ }); } // for x } // for z } // for y } } void cBlockArea::cChunkReader::BlockEntity(cBlockEntity * a_BlockEntity) { if (!m_Area.HasBlockEntities()) { return; } if (!m_AreaBounds.IsInside(a_BlockEntity->GetPos())) { return; } auto areaPos = a_BlockEntity->GetPos() - m_Area.m_Origin; auto Idx = m_Area.MakeIndex(areaPos); m_Area.m_BlockEntities->emplace(Idx, a_BlockEntity->Clone(areaPos)); } ================================================ FILE: src/BlockArea.h ================================================ // BlockArea.h // Interfaces to the cBlockArea object representing an area of block data that can be queried from cWorld and then accessed again without further queries // The object also supports writing the blockdata back into cWorld, even into other coords // NOTE: All Nibble values (meta, blocklight, skylight) are stored one-nibble-per-byte for faster access / editting! // NOTE: Lua bindings for this object explicitly check parameter values. C++ code is expected to pass in valid params, so the functions ASSERT on invalid params. // This includes the datatypes (must be present / valid combination), coords and sizes. #pragma once #include "BlockType.h" #include "ForEachChunkProvider.h" #include "ChunkDataCallback.h" #include "Cuboid.h" #include "FunctionRef.h" #include "BlockEntities/BlockEntity.h" // fwd: class cCuboid; class cItem; class cItems; using cBlockEntityCallback = cFunctionRef; // tolua_begin class cBlockArea { // tolua_end DISALLOW_COPY_AND_ASSIGN(cBlockArea); // tolua_begin public: /** What data is to be queried (bit-mask) */ enum { baTypes = 1, baMetas = 2, baLight = 4, baSkyLight = 8, // baEntities = 16, // Not supported yet baBlockEntities = 32, } ; /** The per-block strategy to use when merging another block area into this object. See the Merge function for the description of these */ enum eMergeStrategy { msOverwrite, msFillAir, msImprint, msLake, msSpongePrint, msDifference, msSimpleCompare, msMask, } ; cBlockArea(void); /** Returns true if the datatype combination is valid. Invalid combinations include BlockEntities without BlockTypes. */ static bool IsValidDataTypeCombination(int a_DataTypes); /** Clears the data stored to reclaim memory */ void Clear(void); // tolua_end /** Creates a new area of the specified size and contents. Origin is set to all zeroes. BlockTypes are set to air, block metas to zero, blocklights to zero and skylights to full light. */ void Create(int a_SizeX, int a_SizeY, int a_SizeZ, int a_DataTypes = baTypes | baMetas | baBlockEntities); /** Creates a new area of the specified size and contents. Origin is set to all zeroes. BlockTypes are set to air, block metas to zero, blocklights to zero and skylights to full light. */ void Create(const Vector3i & a_Size, int a_DataTypes = baTypes | baMetas | baBlockEntities); // tolua_begin /** Resets the origin. No other changes are made, contents are untouched. */ void SetOrigin(int a_OriginX, int a_OriginY, int a_OriginZ); /** Resets the origin. No other changes are made, contents are untouched. */ void SetOrigin(const Vector3i & a_Origin); /** Returns true if the specified relative coords are within this area's coord range (0 - m_Size). */ bool IsValidRelCoords(int a_RelX, int a_RelY, int a_RelZ) const; /** Returns true if the specified relative coords are within this area's coord range (0 - m_Size). */ bool IsValidRelCoords(const Vector3i & a_RelCoords) const; /** Returns true if the specified coords are within this area's coord range (as indicated by m_Origin). */ bool IsValidCoords(int a_BlockX, int a_BlockY, int a_BlockZ) const; /** Returns true if the specified coords are within this area's coord range (as indicated by m_Origin). */ bool IsValidCoords(const Vector3i & a_Coords) const; // tolua_end /** Reads an area of blocks specified. Returns true if successful. All coords are inclusive. */ bool Read(cForEachChunkProvider & a_ForEachChunkProvider, int a_MinBlockX, int a_MaxBlockX, int a_MinBlockY, int a_MaxBlockY, int a_MinBlockZ, int a_MaxBlockZ, int a_DataTypes = baTypes | baMetas | baBlockEntities); /** Reads an area of blocks specified. Returns true if successful. The bounds are included in the read area. */ bool Read(cForEachChunkProvider & a_ForEachChunkProvider, const cCuboid & a_Bounds, int a_DataTypes = baTypes | baMetas | baBlockEntities); /** Reads an area of blocks specified. Returns true if successful. The bounds are included in the read area. */ bool Read(cForEachChunkProvider & a_ForEachChunkProvider, const Vector3i & a_Point1, const Vector3i & a_Point2, int a_DataTypes = baTypes | baMetas | baBlockEntities); // TODO: Write() is not too good an interface: if it fails, there's no way to repeat only for the parts that didn't write // A better way may be to return a list of cBlockAreas for each part that didn't succeed writing, so that the caller may try again /** Writes the area back into cWorld at the coords specified. Returns true if successful in all chunks, false if only partially / not at all. Doesn't wake up the simulators. */ bool Write(cForEachChunkProvider & a_ForEachChunkProvider, int a_MinBlockX, int a_MinBlockY, int a_MinBlockZ, int a_DataTypes); /** Writes the area back into cWorld at the coords specified. Returns true if successful in all chunks, false if only partially / not at all. Doesn't wake up the simulators. */ bool Write(cForEachChunkProvider & a_ForEachChunkProvider, int a_MinBlockX, int a_MinBlockY, int a_MinBlockZ) { // Write all available data return Write(a_ForEachChunkProvider, a_MinBlockX, a_MinBlockY, a_MinBlockZ, GetDataTypes()); } /** Writes the area back into cWorld at the coords specified. Returns true if successful in all chunks, false if only partially / not at all. Doesn't wake up the simulators. */ bool Write(cForEachChunkProvider & a_ForEachChunkProvider, const Vector3i & a_MinCoords, int a_DataTypes); /** Writes the area back into cWorld at the coords specified. Returns true if successful in all chunks, false if only partially / not at all. Doesn't wake up the simulators. */ bool Write(cForEachChunkProvider & a_ForEachChunkProvider, const Vector3i & a_MinCoords) { // Write all available data return Write(a_ForEachChunkProvider, a_MinCoords.x, a_MinCoords.y, a_MinCoords.z, GetDataTypes()); } // tolua_begin /** Copies this object's contents into the specified BlockArea. */ void CopyTo(cBlockArea & a_Into) const; /** Copies the contents from the specified BlockArea into this object. */ void CopyFrom(const cBlockArea & a_From); /** For testing purposes only, dumps the area into a file. */ void DumpToRawFile(const AString & a_FileName); /** Crops the internal contents by the specified amount of blocks from each border. */ void Crop(int a_AddMinX, int a_SubMaxX, int a_AddMinY, int a_SubMaxY, int a_AddMinZ, int a_SubMaxZ); /** Expands the internal contents by the specified amount of blocks from each border */ void Expand(int a_SubMinX, int a_AddMaxX, int a_SubMinY, int a_AddMaxY, int a_SubMinZ, int a_AddMaxZ); /** Merges another block area into this one, using the specified block combining strategy This function combines another BlockArea into the current object. The a_RelX, a_RelY and a_RelZ parameters specify the coords of this BA where a_Src should be copied. If both areas contain baBlockEntities, the BEs are merged (with preference of keeping this' ones) (MergeBlockEntities()). If only this contains BEs, but a_Src doesn't, the BEs are checked after merge to remove the overwritten ones and create the missing ones (UpdateBlockEntities()). The strategy parameter specifies how individual blocks are combined together, using the table below. | area block | result | | this | Src | msOverwrite | msFillAir | msImprint | +------+-----+-------------+-----------+-----------+ | air | air | air | air | air | | A | air | air | A | A | | air | B | B | B | B | | A | B | B | A | B | So to sum up: - msOverwrite completely overwrites all blocks with the Src's blocks - msFillAir overwrites only those blocks that were air - msImprint overwrites with only those blocks that are non-air Special strategies (evaluate top-down, first match wins): msLake: | area block | | | this | Src | result | +----------+--------+--------+ | A | sponge | A | Sponge is the NOP block | * | air | air | Air always gets hollowed out, even under the oceans | water | * | water | Water is never overwritten | lava | * | lava | Lava is never overwritten | * | water | water | Water always overwrites anything | * | lava | lava | Lava always overwrites anything | dirt | stone | stone | Stone overwrites dirt | grass | stone | stone | ... and grass | mycelium | stone | stone | ... and mycelium | A | stone | A | ... but nothing else | A | * | A | Everything else is left as it is msSpongePrint: Used for most generators, it allows carving out air pockets, too, and uses the Sponge as the NOP block | area block | | | this | Src | result | +----------+--------+--------+ | A | sponge | A | Sponge is the NOP block | * | B | B | Everything else overwrites anything msDifference: Used to determine the differences between two areas. Only the differring blocks are preserved: | area block | | | this | Src | result | +------+-------+--------+ | A | A | air | Same blocks are replaced with air | A | non-A | A | Differring blocks are kept from "this" msSimpleCompare: Used to determine the differences between two areas. Blocks that differ are replaced with stone, same blocks are replaced with air | area block | | | this | Src | result | +------+-------+--------+ | A | A | air | Same blocks are replaced with air | A | non-A | stone | Differring blocks are replaced with stone msMask: Combines two areas, the blocks that are the same are kept, differing ones are reset to air | area block | | | this | Src | result | +------+-------+--------+ | A | A | A | Same blocks are kept | A | non-A | air | Everything else is replaced with air */ void Merge(const cBlockArea & a_Src, int a_RelX, int a_RelY, int a_RelZ, eMergeStrategy a_Strategy); /** Merges another block area into this one, using the specified block combining strategy. See Merge() above for details. */ void Merge(const cBlockArea & a_Src, const Vector3i & a_RelMinCoords, eMergeStrategy a_Strategy); /** Fills the entire block area with the specified data */ void Fill(int a_DataTypes, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta = 0, NIBBLETYPE a_BlockLight = 0, NIBBLETYPE a_BlockSkyLight = 0x0f); // tolua_end /** Fills a cuboid inside the block area with the specified data */ void FillRelCuboid(int a_MinRelX, int a_MaxRelX, int a_MinRelY, int a_MaxRelY, int a_MinRelZ, int a_MaxRelZ, int a_DataTypes, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta = 0, NIBBLETYPE a_BlockLight = 0, NIBBLETYPE a_BlockSkyLight = 0x0f ); /** Fills a cuboid inside the block area with the specified data. a_Cuboid must be sorted. */ void FillRelCuboid(const cCuboid & a_RelCuboid, int a_DataTypes, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta = 0, NIBBLETYPE a_BlockLight = 0, NIBBLETYPE a_BlockSkyLight = 0x0f ); /** Draws a line between two points with the specified data. The line endpoints needn't be valid coords inside the area. */ void RelLine(int a_RelX1, int a_RelY1, int a_RelZ1, int a_RelX2, int a_RelY2, int a_RelZ2, int a_DataTypes, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta = 0, NIBBLETYPE a_BlockLight = 0, NIBBLETYPE a_BlockSkyLight = 0x0f ); /** Draws a line between two points with the specified data. The line endpoints needn't be valid coords inside the area. */ void RelLine(const Vector3i & a_Point1, const Vector3i & a_Point2, int a_DataTypes, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta = 0, NIBBLETYPE a_BlockLight = 0, NIBBLETYPE a_BlockSkyLight = 0x0f ); // tolua_begin /** Rotates the entire area counter-clockwise around the Y axis */ void RotateCCW(void); /** Rotates the entire area clockwise around the Y axis */ void RotateCW(void); /** Mirrors the entire area around the XY plane */ void MirrorXY(void); /** Mirrors the entire area around the XZ plane */ void MirrorXZ(void); /** Mirrors the entire area around the YZ plane */ void MirrorYZ(void); /** Rotates the entire area counter-clockwise around the Y axis, doesn't use blockhandlers for block meta */ void RotateCCWNoMeta(void); /** Rotates the entire area clockwise around the Y axis, doesn't use blockhandlers for block meta */ void RotateCWNoMeta(void); /** Mirrors the entire area around the XY plane, doesn't use blockhandlers for block meta */ void MirrorXYNoMeta(void); /** Mirrors the entire area around the XZ plane, doesn't use blockhandlers for block meta */ void MirrorXZNoMeta(void); /** Mirrors the entire area around the YZ plane, doesn't use blockhandlers for block meta */ void MirrorYZNoMeta(void); // tolua_end // Setters: void SetRelBlockType (int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType); void SetBlockType (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType); void SetRelBlockMeta (int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_BlockMeta); void SetBlockMeta (int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_BlockMeta); void SetRelBlockLight (int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_BlockLight); void SetBlockLight (int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_BlockLight); void SetRelBlockSkyLight(int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_BlockSkyLight); void SetBlockSkyLight (int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_BlockSkyLight); // tolua_begin void SetWEOffset (int a_OffsetX, int a_OffsetY, int a_OffsetZ); void SetWEOffset (const Vector3i & a_Offset); const Vector3i & GetWEOffset (void) const {return m_WEOffset;} // tolua_end // Getters: BLOCKTYPE GetRelBlockType (int a_RelX, int a_RelY, int a_RelZ) const; BLOCKTYPE GetBlockType (int a_BlockX, int a_BlockY, int a_BlockZ) const; NIBBLETYPE GetRelBlockMeta (int a_RelX, int a_RelY, int a_RelZ) const; NIBBLETYPE GetBlockMeta (int a_BlockX, int a_BlockY, int a_BlockZ) const; NIBBLETYPE GetRelBlockLight (int a_RelX, int a_RelY, int a_RelZ) const; NIBBLETYPE GetBlockLight (int a_BlockX, int a_BlockY, int a_BlockZ) const; NIBBLETYPE GetRelBlockSkyLight(int a_RelX, int a_RelY, int a_RelZ) const; NIBBLETYPE GetBlockSkyLight (int a_BlockX, int a_BlockY, int a_BlockZ) const; void SetBlockTypeMeta (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta); void SetRelBlockTypeMeta(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta); void GetBlockTypeMeta (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta) const; void GetRelBlockTypeMeta(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta) const; const Vector3i & GetSize(void) const { return m_Size; } const Vector3i & GetOrigin(void) const { return m_Origin; } // tolua_begin cCuboid GetBounds(void) const; int GetSizeX(void) const { return m_Size.x; } int GetSizeY(void) const { return m_Size.y; } int GetSizeZ(void) const { return m_Size.z; } /** Returns the volume of the area, as number of blocks */ int GetVolume(void) const { return m_Size.x * m_Size.y * m_Size.z; } int GetOriginX(void) const { return m_Origin.x; } int GetOriginY(void) const { return m_Origin.y; } int GetOriginZ(void) const { return m_Origin.z; } /** Returns the datatypes that are stored in the object (bitmask of baXXX values) */ int GetDataTypes(void) const; bool HasBlockTypes (void) const { return (m_BlockTypes != nullptr); } bool HasBlockMetas (void) const { return (m_BlockMetas != nullptr); } bool HasBlockLights (void) const { return (m_BlockLight != nullptr); } bool HasBlockSkyLights(void) const { return (m_BlockSkyLight != nullptr); } bool HasBlockEntities (void) const { return m_BlockEntities.operator bool(); } /** Returns the count of blocks that are not air. Returns 0 if blocktypes not available. Block metas are ignored (if present, air with any meta is still considered air). */ size_t CountNonAirBlocks(void) const; /** Returns how many times the specified block is contained in the area. The blocks' meta values are ignored, only the blocktype is compared. */ size_t CountSpecificBlocks(BLOCKTYPE a_BlockType) const; /** Returns how many times the specified block is contained in the area. Both the block's type and meta must match in order to be counted in. If the block metas aren't present in the area, logs a warning and ignores the meta specification. */ size_t CountSpecificBlocks(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) const; // tolua_end /** Returns the minimum and maximum coords in each direction for the first non-ignored block in each direction. If there are no non-ignored blocks within the area, or blocktypes are not present, the returned values are reverse-ranges (MinX <- m_RangeX, MaxX <- 0 etc.) Exported to Lua in ManualBindings.cpp. */ void GetNonAirCropRelCoords(int & a_MinRelX, int & a_MinRelY, int & a_MinRelZ, int & a_MaxRelX, int & a_MaxRelY, int & a_MaxRelZ, BLOCKTYPE a_IgnoreBlockType = E_BLOCK_AIR); // Clients can use these for faster access to all blocktypes. Be careful though! /** Returns the internal pointer to the block types */ BLOCKTYPE * GetBlockTypes (void) const { return m_BlockTypes.get(); } NIBBLETYPE * GetBlockMetas (void) const { return m_BlockMetas.get(); } // NOTE: one byte per block! NIBBLETYPE * GetBlockLight (void) const { return m_BlockLight.get(); } // NOTE: one byte per block! NIBBLETYPE * GetBlockSkyLight(void) const { return m_BlockSkyLight.get(); } // NOTE: one byte per block! size_t GetBlockCount(void) const { return static_cast(m_Size.x * m_Size.y * m_Size.z); } static size_t MakeIndexForSize(Vector3i a_RelPos, Vector3i a_Size); /** Returns the index into the internal arrays for the specified coords */ size_t MakeIndex(Vector3i a_RelPos) const { return MakeIndexForSize(a_RelPos, m_Size); } /** OBSOLETE, use the Vector3i-based overload instead. Returns the index into the internal arrays for the specified coords */ size_t MakeIndex(int a_RelX, int a_RelY, int a_RelZ) const { return MakeIndexForSize({ a_RelX, a_RelY, a_RelZ }, m_Size); } /** Calls the callback for the block entity at the specified coords. Returns false if there is no block entity at those coords, or the block area doesn't have baBlockEntities. Returns the value that the callback has returned if there is a block entity. */ bool DoWithBlockEntityRelAt(int a_RelX, int a_RelY, int a_RelZ, cBlockEntityCallback a_Callback); /** Calls the callback for the block entity at the specified coords. Returns false if there is no block entity at those coords. Returns the value that the callback has returned if there is a block entity. */ bool DoWithBlockEntityAt (int a_BlockX, int a_BlockY, int a_BlockZ, cBlockEntityCallback a_Callback); /** Calls the callback for all the block entities. If the callback returns true, aborts the enumeration and returns false. If the callback returns true, continues with the next BE. Returns true if all block entities have been enumerated (including the case when there is none or the area is without baBlockEntities). */ bool ForEachBlockEntity(cBlockEntityCallback a_Callback); /** Direct read-only access to block entities. */ const cBlockEntities & GetBlockEntities(void) const { ASSERT(HasBlockEntities()); return *m_BlockEntities.get(); } cBlockEntities & GetBlockEntities(void) { ASSERT(HasBlockEntities()); return *m_BlockEntities.get(); } protected: friend class cChunkDesc; friend class cSchematicFileSerializer; class cChunkReader: public cChunkDataCallback { public: cChunkReader(cBlockArea & a_Area); protected: cBlockArea & m_Area; cCuboid m_AreaBounds; ///< Bounds of the whole area being read, in world coords Vector3i m_Origin; int m_CurrentChunkX; int m_CurrentChunkZ; void CopyNibbles(NIBBLETYPE * a_AreaDst, const NIBBLETYPE * a_ChunkSrc); // cChunkDataCallback overrides: virtual bool Coords(int a_ChunkX, int a_ChunkZ) override; virtual void ChunkData(const ChunkBlockData & a_BlockData, const ChunkLightData & a_LightData) override; virtual void BlockEntity(cBlockEntity * a_BlockEntity) override; } ; using NIBBLEARRAY = std::unique_ptr; using BLOCKARRAY = std::unique_ptr; using cBlockEntitiesPtr = std::unique_ptr; Vector3i m_Origin; Vector3i m_Size; /** An extra data value sometimes stored in the .schematic file. Used mainly by the WorldEdit plugin. cBlockArea doesn't use this value in any way. */ Vector3i m_WEOffset; BLOCKARRAY m_BlockTypes; NIBBLEARRAY m_BlockMetas; // Each meta is stored as a separate byte for faster access NIBBLEARRAY m_BlockLight; // Each light value is stored as a separate byte for faster access NIBBLEARRAY m_BlockSkyLight; // Each light value is stored as a separate byte for faster access /** The block entities contained within the area. Only valid if the area was created / read with the baBlockEntities flag. The block entities are owned by this object. */ cBlockEntitiesPtr m_BlockEntities; /** Clears the data stored and prepares a fresh new block area with the specified dimensions */ bool SetSize(int a_SizeX, int a_SizeY, int a_SizeZ, int a_DataTypes); // Basic Setters: void SetRelNibble(int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_Value, NIBBLETYPE * a_Array); void SetNibble (int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_Value, NIBBLETYPE * a_Array); // Basic Getters: NIBBLETYPE GetRelNibble(int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE * a_Array) const; NIBBLETYPE GetNibble (int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE * a_Array) const; // Crop helpers: void CropBlockTypes(int a_AddMinX, int a_SubMaxX, int a_AddMinY, int a_SubMaxY, int a_AddMinZ, int a_SubMaxZ); void CropNibbles (NIBBLEARRAY & a_Array, int a_AddMinX, int a_SubMaxX, int a_AddMinY, int a_SubMaxY, int a_AddMinZ, int a_SubMaxZ); // Expand helpers: void ExpandBlockTypes(int a_SubMinX, int a_AddMaxX, int a_SubMinY, int a_AddMaxY, int a_SubMinZ, int a_AddMaxZ); void ExpandNibbles (NIBBLEARRAY & a_Array, int a_SubMinX, int a_AddMaxX, int a_SubMinY, int a_AddMaxY, int a_SubMinZ, int a_AddMaxZ); /** Sets the specified datatypes at the specified location. If the coords are not valid, ignores the call (so that RelLine() can work simply). */ void RelSetData( int a_RelX, int a_RelY, int a_RelZ, int a_DataTypes, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, NIBBLETYPE a_BlockLight, NIBBLETYPE a_BlockSkyLight ); template void MergeByStrategy(const cBlockArea & a_Src, int a_RelX, int a_RelY, int a_RelZ, eMergeStrategy a_Strategy, const NIBBLETYPE * SrcMetas, NIBBLETYPE * DstMetas); /** Updates m_BlockEntities to remove BEs that no longer match the blocktype at their coords, and clones from a_Src the BEs that are missing. a_RelX, a_RelY and a_RelZ are relative coords that should be added to all BEs from a_Src before checking them. If a block should have a BE but one cannot be found in either this or a_Src, a new one is created. */ void MergeBlockEntities(int a_RelX, int a_RelY, int a_RelZ, const cBlockArea & a_Src); /** Updates m_BlockEntities to remove BEs that no longer match the blocktype at their coords, and add new BEs that are missing. */ void RescanBlockEntities(void); /** Removes from m_BlockEntities those BEs that no longer match the blocktype at their coords. */ void RemoveNonMatchingBlockEntities(void); /** Returns the cBlockEntity at the specified coords, or nullptr if none. */ cBlockEntity * GetBlockEntityRel(Vector3i a_RelPos); // tolua_begin } ; // tolua_end ================================================ FILE: src/BlockEntities/BannerEntity.cpp ================================================ // BannerEntity.cpp // Implements the cBannerEntity class representing a banner block in the world #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "BannerEntity.h" #include "../World.h" #include "../ClientHandle.h" cBannerEntity::cBannerEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World, unsigned char a_BaseColor, AString a_CustomName): Super(a_BlockType, a_BlockMeta, a_Pos, a_World), m_BaseColor(a_BaseColor), m_CustomName(std::move(a_CustomName)) { ASSERT((a_BlockType == E_BLOCK_WALL_BANNER) || (a_BlockType == E_BLOCK_STANDING_BANNER)); } cItems cBannerEntity::ConvertToPickups() const { cItem Item(E_ITEM_BANNER, 1, static_cast(GetBaseColor())); Item.m_CustomName = m_CustomName; return Item; } void cBannerEntity::CopyFrom(const cBlockEntity & a_Src) { Super::CopyFrom(a_Src); auto & src = static_cast(a_Src); m_BaseColor = src.m_BaseColor; m_CustomName = src.m_CustomName; } void cBannerEntity::SendTo(cClientHandle & a_Client) { a_Client.SendBlockChange(m_Pos, m_BlockType, m_BlockMeta); a_Client.SendUpdateBlockEntity(*this); } bool cBannerEntity::UsedBy(cPlayer * a_Player) { UNUSED(a_Player); return false; } ================================================ FILE: src/BlockEntities/BannerEntity.h ================================================ // BannerEntity.h // Declares the cBannerEntity class representing a single banner in the world #pragma once #include "BlockEntity.h" // tolua_begin class cBannerEntity : public cBlockEntity { // tolua_end using Super = cBlockEntity; public: cBannerEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World, unsigned char a_BaseColor = 1, AString a_CustomName = ""); unsigned char GetBaseColor() const { return m_BaseColor; } void SetBaseColor(unsigned char a_Color) { m_BaseColor = a_Color; } const AString & GetCustomName() const { return m_CustomName; } void SetCustomName(const AString & a_CustomName) { m_CustomName = a_CustomName; } private: unsigned char m_BaseColor; AString m_CustomName; // cBlockEntity overrides: virtual cItems ConvertToPickups() const override; virtual void CopyFrom(const cBlockEntity & a_Src) override; virtual void SendTo(cClientHandle & a_Client) override; virtual bool UsedBy(cPlayer * a_Player) override; } ; // tolua_export ================================================ FILE: src/BlockEntities/BeaconEntity.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "BeaconEntity.h" #include "../BlockInfo.h" #include "../BlockArea.h" #include "../Entities/Player.h" #include "../UI/BeaconWindow.h" #include "../ClientHandle.h" cBeaconEntity::cBeaconEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World): Super(a_BlockType, a_BlockMeta, a_Pos, 1, 1, a_World), m_IsActive(false), m_BeaconLevel(0), m_PrimaryEffect(cEntityEffect::effNoEffect), m_SecondaryEffect(cEntityEffect::effNoEffect) { ASSERT(a_BlockType == E_BLOCK_BEACON); if (m_World != nullptr) { UpdateBeacon(); } } char cBeaconEntity::CalculatePyramidLevel(void) { cBlockArea Area; int MinY = std::max(GetPosY() - 4, 0); int MaxY = std::max(GetPosY() - 1, 0); Area.Read( *m_World, GetPosX() - 4, GetPosX() + 4, MinY, MaxY, GetPosZ() - 4, GetPosZ() + 4, cBlockArea::baTypes ); int Layer = 1; int MiddleXZ = 4; for (int Y = (Area.GetSizeY() - 1); Y >= 0; Y--) { for (int X = MiddleXZ - Layer; X <= (MiddleXZ + Layer); X++) { for (int Z = MiddleXZ - Layer; Z <= (MiddleXZ + Layer); Z++) { if (!IsMineralBlock(Area.GetRelBlockType(X, Y, Z))) { return static_cast(Layer - 1); } } } Layer++; } return static_cast(Layer - 1); } bool cBeaconEntity::IsValidEffect(cEntityEffect::eType a_Effect, char a_BeaconLevel) { switch (a_Effect) { case cEntityEffect::effRegeneration: return (a_BeaconLevel >= 4); case cEntityEffect::effStrength: return (a_BeaconLevel >= 3); case cEntityEffect::effResistance: return (a_BeaconLevel >= 2); case cEntityEffect::effJumpBoost: return (a_BeaconLevel >= 2); case cEntityEffect::effSpeed: return (a_BeaconLevel >= 1); case cEntityEffect::effHaste: return (a_BeaconLevel >= 1); case cEntityEffect::effNoEffect: return true; default: { LOGD("%s: Invalid beacon effect: %d", __FUNCTION__, static_cast(a_Effect)); return false; } } } bool cBeaconEntity::SetPrimaryEffect(cEntityEffect::eType a_Effect) { if (!IsValidEffect(a_Effect, m_BeaconLevel)) { m_PrimaryEffect = cEntityEffect::effNoEffect; return false; } m_PrimaryEffect = a_Effect; // Send window update: if (GetWindow() != nullptr) { GetWindow()->SetProperty(1, static_cast(m_PrimaryEffect)); } return true; } bool cBeaconEntity::SetSecondaryEffect(cEntityEffect::eType a_Effect) { if (!IsValidEffect(a_Effect, m_BeaconLevel)) { m_SecondaryEffect = cEntityEffect::effNoEffect; return false; } m_SecondaryEffect = a_Effect; // Send window update: if (GetWindow() != nullptr) { GetWindow()->SetProperty(2, static_cast(m_SecondaryEffect)); } return true; } bool cBeaconEntity::IsBeaconBlocked(void) { for (int Y = m_Pos.y; Y < cChunkDef::Height; ++Y) { BLOCKTYPE Block = m_World->GetBlock({m_Pos.x, Y, m_Pos.z}); if (!cBlockInfo::IsTransparent(Block)) { return true; } } return false; } bool cBeaconEntity::IsMineralBlock(BLOCKTYPE a_BlockType) { switch (a_BlockType) { case E_BLOCK_DIAMOND_BLOCK: case E_BLOCK_GOLD_BLOCK: case E_BLOCK_IRON_BLOCK: case E_BLOCK_EMERALD_BLOCK: { return true; } } return false; } void cBeaconEntity::UpdateBeacon(void) { int OldBeaconLevel = m_BeaconLevel; if (IsBeaconBlocked()) { m_IsActive = false; m_BeaconLevel = 0; } else { m_BeaconLevel = CalculatePyramidLevel(); m_IsActive = (m_BeaconLevel > 0); } if ((m_BeaconLevel != OldBeaconLevel) && (m_BeaconLevel == 4)) { // Send window update: if (GetWindow() != nullptr) { GetWindow()->SetProperty(0, m_BeaconLevel); } Vector3d BeaconPosition(m_Pos); GetWorld()->ForEachPlayer([=](cPlayer & a_Player) { Vector3d Distance = BeaconPosition - a_Player.GetPosition(); if ( (std::abs(Distance.y) <= 14) && (std::abs(Distance.x) <= 20) && (std::abs(Distance.z) <= 20) ) { a_Player.AwardAchievement(CustomStatistic::AchFullBeacon); } return false; } ); } } void cBeaconEntity::GiveEffects(void) { if (!m_IsActive || (m_BeaconLevel < 0)) { return; } double Radius = static_cast(m_BeaconLevel) * 10 + 10; short EffectLevel = 0; if ((m_BeaconLevel >= 4) && (m_PrimaryEffect == m_SecondaryEffect)) { EffectLevel = 1; } bool HasSecondaryEffect = (m_BeaconLevel >= 4) && (m_PrimaryEffect != m_SecondaryEffect) && (m_SecondaryEffect > 0); auto Area = cBoundingBox(m_Pos, Radius, Radius + static_cast(cChunkDef::Height), -Radius); GetWorld()->ForEachEntityInBox(Area, [&](cEntity & a_Entity) { if (!a_Entity.IsPlayer()) { return false; } auto & Player = static_cast(a_Entity); Player.AddEntityEffect(m_PrimaryEffect, 180, EffectLevel); if (HasSecondaryEffect) { Player.AddEntityEffect(m_SecondaryEffect, 180, 0); } return false; }); } void cBeaconEntity::CopyFrom(const cBlockEntity & a_Src) { Super::CopyFrom(a_Src); auto & src = static_cast(a_Src); m_BeaconLevel = src.m_BeaconLevel; m_Contents.CopyFrom(src.m_Contents); m_IsActive = src.m_IsActive; m_PrimaryEffect = src.m_PrimaryEffect; m_SecondaryEffect = src.m_SecondaryEffect; } void cBeaconEntity::OnRemoveFromWorld() { const auto Window = GetWindow(); if (Window != nullptr) { // Tell window its owner is destroyed: Window->OwnerDestroyed(); } } void cBeaconEntity::SendTo(cClientHandle & a_Client) { a_Client.SendUpdateBlockEntity(*this); } bool cBeaconEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { using namespace std::chrono_literals; // Update the beacon every 4 seconds: if ((GetWorld()->GetWorldTickAge() % 4s) == 0s) { UpdateBeacon(); GiveEffects(); } return false; } bool cBeaconEntity::UsedBy(cPlayer * a_Player) { a_Player->GetStatistics().Custom[CustomStatistic::InteractWithBeacon]++; cWindow * Window = GetWindow(); if (Window == nullptr) { OpenWindow(new cBeaconWindow(this)); Window = GetWindow(); } if (Window != nullptr) { // if (a_Player->GetWindow() != Window) // -> Because mojang doesn't send a 'close window' packet when you click the cancel button in the beacon inventory ... { a_Player->OpenWindow(*Window); } } return true; } ================================================ FILE: src/BlockEntities/BeaconEntity.h ================================================ // BeaconEntity.h // Declares the cBeaconEntity class representing a single beacon in the world #pragma once #include "BlockEntityWithItems.h" // tolua_begin class cBeaconEntity : public cBlockEntityWithItems { // tolua_end using Super = cBlockEntityWithItems; public: // tolua_export cBeaconEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World); // cBlockEntity overrides: virtual void CopyFrom(const cBlockEntity & a_Src) override; virtual void OnRemoveFromWorld() override; virtual void SendTo(cClientHandle & a_Client) override; virtual bool Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; virtual bool UsedBy(cPlayer * a_Player) override; /** Modify the beacon level. (It is needed to load the beacon corectly) */ void SetBeaconLevel(char a_Level) { m_BeaconLevel = a_Level; } // tolua_begin /** Is the beacon active? */ bool IsActive(void) const { return m_IsActive; } /** Returns the beacon level. (0 - 4) */ char GetBeaconLevel(void) const { return m_BeaconLevel; } cEntityEffect::eType GetPrimaryEffect(void) const { return m_PrimaryEffect; } cEntityEffect::eType GetSecondaryEffect(void) const { return m_SecondaryEffect; } /** Sets the primary effect. Returns false when the effect is invalid. */ bool SetPrimaryEffect(cEntityEffect::eType a_Effect); /** Sets the secondary effect. Returns false when the effect is invalid. */ bool SetSecondaryEffect(cEntityEffect::eType a_Effect); /** Calculate the amount of layers the pyramid below the beacon has. */ char CalculatePyramidLevel(void); /** Is the beacon blocked by non-transparent blocks that are higher than the beacon? */ bool IsBeaconBlocked(void); /** Update the beacon. */ void UpdateBeacon(void); /** Give the near-players the effects. */ void GiveEffects(void); /** Returns true if the block is a diamond block, a golden block, an iron block or an emerald block. */ static bool IsMineralBlock(BLOCKTYPE a_BlockType); /** Returns true if the effect can be used. */ static bool IsValidEffect(cEntityEffect::eType a_Effect, char a_BeaconLevel); // tolua_end protected: bool m_IsActive; char m_BeaconLevel; cEntityEffect::eType m_PrimaryEffect, m_SecondaryEffect; } ; // tolua_export ================================================ FILE: src/BlockEntities/BedEntity.cpp ================================================ // BedEntity.cpp #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "BedEntity.h" #include "../World.h" #include "../Entities/Player.h" #include "../ClientHandle.h" #include "../Blocks/BlockBed.h" cBedEntity::cBedEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World, short a_Color): Super(a_BlockType, a_BlockMeta, a_Pos, a_World), m_Color(a_Color) { ASSERT(a_BlockType == E_BLOCK_BED); } cItems cBedEntity::ConvertToPickups() const { return cItem(E_ITEM_BED, 1, m_Color); } void cBedEntity::CopyFrom(const cBlockEntity & a_Src) { Super::CopyFrom(a_Src); auto & src = static_cast(a_Src); m_Color = src.m_Color; } void cBedEntity::SendTo(cClientHandle & a_Client) { a_Client.SendUpdateBlockEntity(*this); } void cBedEntity::SetColor(short a_Color) { m_Color = a_Color; } ================================================ FILE: src/BlockEntities/BedEntity.h ================================================ // BedEntity.h #pragma once #include "BlockEntity.h" #include "../BlockType.h" // tolua_begin class cBedEntity : public cBlockEntity { // tolua_end using Super = cBlockEntity; public: // tolua_export cBedEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World, short a_Color = E_META_WOOL_RED); // tolua_begin /** Returns the color of the bed */ short GetColor(void) const { return m_Color; } /** Set the color of the bed. */ void SetColor(short a_Color); /** Returns true if this is the pillow block, it has then the meta 8. */ bool IsPillowBlock(void) { return ((m_BlockMeta & 0x08) == 0x08); } // tolua_end // cBlockEntity overrides: virtual cItems ConvertToPickups() const override; virtual void CopyFrom(const cBlockEntity & a_Src) override; virtual bool UsedBy(cPlayer * a_Player) override { return false; } virtual void SendTo(cClientHandle & a_Client) override; private: short m_Color; }; // tolua_export ================================================ FILE: src/BlockEntities/BlockEntity.cpp ================================================ // BlockEntity.cpp // Implements the cBlockEntity class that is the common ancestor for all block entities #include "Globals.h" #include "BannerEntity.h" #include "BeaconEntity.h" #include "BedEntity.h" #include "BlockEntity.h" #include "EnchantingTableEntity.h" #include "BrewingstandEntity.h" #include "ChestEntity.h" #include "CommandBlockEntity.h" #include "DispenserEntity.h" #include "DropperEntity.h" #include "EnderChestEntity.h" #include "EndPortalEntity.h" #include "FlowerPotEntity.h" #include "FurnaceEntity.h" #include "HopperEntity.h" #include "MobHeadEntity.h" #include "MobSpawnerEntity.h" #include "JukeboxEntity.h" #include "NoteEntity.h" #include "SignEntity.h" cBlockEntity::cBlockEntity(const BLOCKTYPE a_BlockType, const NIBBLETYPE a_BlockMeta, const Vector3i a_Pos, cWorld * const a_World) : m_Pos(a_Pos), m_RelX(a_Pos.x - cChunkDef::Width * FAST_FLOOR_DIV(a_Pos.x, cChunkDef::Width)), m_RelZ(a_Pos.z - cChunkDef::Width * FAST_FLOOR_DIV(a_Pos.z, cChunkDef::Width)), m_BlockType(a_BlockType), m_BlockMeta(a_BlockMeta), m_World(a_World) { } OwnedBlockEntity cBlockEntity::Clone(const Vector3i a_Pos) { auto res = CreateByBlockType(m_BlockType, m_BlockMeta, a_Pos, nullptr); res->CopyFrom(*this); return res; } cItems cBlockEntity::ConvertToPickups() const { return {}; } void cBlockEntity::CopyFrom(const cBlockEntity & a_Src) { // Nothing to copy, but check that we're copying the right entity: ASSERT(m_BlockType == a_Src.m_BlockType); ASSERT(m_BlockMeta == a_Src.m_BlockMeta); } OwnedBlockEntity cBlockEntity::CreateByBlockType(const BLOCKTYPE a_BlockType, const NIBBLETYPE a_BlockMeta, const Vector3i a_Pos, cWorld * const a_World) { switch (a_BlockType) { // Banners: case E_BLOCK_STANDING_BANNER: case E_BLOCK_WALL_BANNER: return std::make_unique(a_BlockType, a_BlockMeta, a_Pos, a_World); // Others: case E_BLOCK_BEACON: return std::make_unique(a_BlockType, a_BlockMeta, a_Pos, a_World); case E_BLOCK_BED: return std::make_unique(a_BlockType, a_BlockMeta, a_Pos, a_World); case E_BLOCK_BREWING_STAND: return std::make_unique(a_BlockType, a_BlockMeta, a_Pos, a_World); case E_BLOCK_CHEST: return std::make_unique(a_BlockType, a_BlockMeta, a_Pos, a_World); case E_BLOCK_COMMAND_BLOCK: return std::make_unique(a_BlockType, a_BlockMeta, a_Pos, a_World); case E_BLOCK_DISPENSER: return std::make_unique(a_BlockType, a_BlockMeta, a_Pos, a_World); case E_BLOCK_DROPPER: return std::make_unique(a_BlockType, a_BlockMeta, a_Pos, a_World); case E_BLOCK_ENCHANTMENT_TABLE: return std::make_unique(a_BlockType, a_BlockMeta, a_Pos, a_World); case E_BLOCK_ENDER_CHEST: return std::make_unique(a_BlockType, a_BlockMeta, a_Pos, a_World); case E_BLOCK_END_PORTAL: return std::make_unique(a_BlockType, a_BlockMeta, a_Pos, a_World); case E_BLOCK_FLOWER_POT: return std::make_unique(a_BlockType, a_BlockMeta, a_Pos, a_World); case E_BLOCK_FURNACE: return std::make_unique(a_BlockType, a_BlockMeta, a_Pos, a_World); case E_BLOCK_HEAD: return std::make_unique(a_BlockType, a_BlockMeta, a_Pos, a_World); case E_BLOCK_HOPPER: return std::make_unique(a_BlockType, a_BlockMeta, a_Pos, a_World); case E_BLOCK_JUKEBOX: return std::make_unique(a_BlockType, a_BlockMeta, a_Pos, a_World); case E_BLOCK_LIT_FURNACE: return std::make_unique(a_BlockType, a_BlockMeta, a_Pos, a_World); case E_BLOCK_MOB_SPAWNER: return std::make_unique(a_BlockType, a_BlockMeta, a_Pos, a_World); case E_BLOCK_NOTE_BLOCK: return std::make_unique(a_BlockType, a_BlockMeta, a_Pos, a_World); case E_BLOCK_SIGN_POST: return std::make_unique(a_BlockType, a_BlockMeta, a_Pos, a_World); case E_BLOCK_TRAPPED_CHEST: return std::make_unique(a_BlockType, a_BlockMeta, a_Pos, a_World); case E_BLOCK_WALLSIGN: return std::make_unique(a_BlockType, a_BlockMeta, a_Pos, a_World); default: { LOGD("%s: Requesting creation of an unknown block entity - block type %d (%s)", __FUNCTION__, a_BlockType, ItemTypeToString(a_BlockType).c_str() ); ASSERT(!"Requesting creation of an unknown block entity"); return nullptr; } } } void cBlockEntity::Destroy() { } bool cBlockEntity::IsBlockEntityBlockType(const BLOCKTYPE a_BlockType) { switch (a_BlockType) { case E_BLOCK_BEACON: case E_BLOCK_BED: case E_BLOCK_BREWING_STAND: case E_BLOCK_CHEST: case E_BLOCK_COMMAND_BLOCK: case E_BLOCK_DISPENSER: case E_BLOCK_DROPPER: case E_BLOCK_ENCHANTMENT_TABLE: case E_BLOCK_ENDER_CHEST: case E_BLOCK_END_PORTAL: case E_BLOCK_FLOWER_POT: case E_BLOCK_FURNACE: case E_BLOCK_HEAD: case E_BLOCK_HOPPER: case E_BLOCK_JUKEBOX: case E_BLOCK_LIT_FURNACE: case E_BLOCK_MOB_SPAWNER: case E_BLOCK_NOTE_BLOCK: case E_BLOCK_SIGN_POST: case E_BLOCK_STANDING_BANNER: case E_BLOCK_TRAPPED_CHEST: case E_BLOCK_WALL_BANNER: case E_BLOCK_WALLSIGN: { return true; } default: { return false; } } } void cBlockEntity::OnAddToWorld(cWorld & a_World, cChunk & a_Chunk) { m_World = &a_World; } void cBlockEntity::OnRemoveFromWorld() { } void cBlockEntity::SetPos(const Vector3i a_NewPos) { ASSERT(m_World == nullptr); // Cannot move block entities that represent world blocks (only use this for cBlockArea's BEs) m_Pos = a_NewPos; } void cBlockEntity::SetWorld(cWorld * const a_World) { m_World = a_World; } bool cBlockEntity::Tick(const std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { UNUSED(a_Dt); return false; } ================================================ FILE: src/BlockEntities/BlockEntity.h ================================================ #pragma once #include "ChunkDef.h" class cChunk; class cItems; class cPlayer; class cWorld; class cBlockEntity; using OwnedBlockEntity = std::unique_ptr; using cBlockEntities = std::unordered_map; // tolua_begin class cBlockEntity { protected: cBlockEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World); public: // tolua_end virtual ~cBlockEntity() = default; // force a virtual destructor in all descendants /** Makes an exact copy of this block entity, except for its m_World (set to nullptr), and at a new position. Uses CopyFrom() to copy the properties. */ OwnedBlockEntity Clone(Vector3i a_Pos); /** Returns the contents of this block entity that it would drop if broken. Note that the block handler will usually handle pickups for the block itself, in addition to any items returned here. */ virtual cItems ConvertToPickups() const; /** Copies all properties of a_Src into this entity, except for its m_World and location. Each non-abstract descendant should override to copy its specific properties, and call Super::CopyFrom(a_Src) to copy the common ones. */ virtual void CopyFrom(const cBlockEntity & a_Src); /** Creates a new block entity for the specified block type at the specified absolute pos. If a_World is valid, then the entity is created bound to that world Returns nullptr for unknown block types. */ static OwnedBlockEntity CreateByBlockType(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World = nullptr); /** Called when this block entity's associated block is destroyed. It is guaranteed that this function is called before OnRemoveFromWorld. */ virtual void Destroy(); /** Returns true if the specified blocktype is supposed to have an associated block entity. */ static bool IsBlockEntityBlockType(BLOCKTYPE a_BlockType); /** Called when the block entity object is added to a world. */ virtual void OnAddToWorld(cWorld & a_World, cChunk & a_Chunk); /** Called when the block entity object is removed from a world. This occurs when the chunk it resides in is unloaded, or when the associated block is destroyed. If it is the latter, Destroy() is guaranteed to be called first. */ virtual void OnRemoveFromWorld(); /** Sends the packet defining the block entity to the client specified. To send to all eligible clients, use cWorld::BroadcastBlockEntity() */ virtual void SendTo(cClientHandle & a_Client) = 0; /** Updates the internally stored position. Note that this should not ever be used for world-contained block entities, it is meant only for when BEs in a cBlockArea are manipulated. Asserts that the block entity is not assigned to a world. */ void SetPos(Vector3i a_NewPos); void SetWorld(cWorld * a_World); /** Ticks the entity; returns true if the chunk should be marked as dirty as a result of this ticking. By default does nothing. */ virtual bool Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk); /** Called when a player uses this entity; should open the UI window. returns true if the use was successful, return false to use the block as a "normal" block */ virtual bool UsedBy(cPlayer * a_Player) = 0; // tolua_begin // Position, in absolute block coordinates: Vector3i GetPos() const { return m_Pos; } int GetPosX() const { return m_Pos.x; } int GetPosY() const { return m_Pos.y; } int GetPosZ() const { return m_Pos.z; } Vector3i GetRelPos() const { return Vector3i(m_RelX, m_Pos.y, m_RelZ); } BLOCKTYPE GetBlockType() const { return m_BlockType; } cWorld * GetWorld() const { return m_World; } int GetChunkX() const { return FAST_FLOOR_DIV(m_Pos.x, cChunkDef::Width); } int GetChunkZ() const { return FAST_FLOOR_DIV(m_Pos.z, cChunkDef::Width); } int GetRelX() const { return m_RelX; } int GetRelZ() const { return m_RelZ; } // tolua_end protected: /** Position in absolute block coordinates */ Vector3i m_Pos; /** Position relative to the chunk, used to speed up ticking */ int m_RelX, m_RelZ; /** The blocktype representing this particular instance in the world. Mainly used for multi-block-type entities, such as furnaces / lit furnaces. */ BLOCKTYPE m_BlockType; /** The block meta representing this particular instance in the world Mainly used for directional entities, such as dispensers. */ NIBBLETYPE m_BlockMeta; cWorld * m_World; } ; // tolua_export ================================================ FILE: src/BlockEntities/BlockEntityWithItems.cpp ================================================ // BlockEntityWithItems.cpp #include "Globals.h" #include "BlockEntityWithItems.h" #include "../Simulator/RedstoneSimulator.h" cBlockEntityWithItems::cBlockEntityWithItems( BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, int a_ItemGridWidth, int a_ItemGridHeight, cWorld * a_World ): Super(a_BlockType, a_BlockMeta, a_Pos, a_World), cBlockEntityWindowOwner(this), m_Contents(a_ItemGridWidth, a_ItemGridHeight) { m_Contents.AddListener(*this); } cItems cBlockEntityWithItems::ConvertToPickups() const { cItems Pickups; Pickups.AddItemGrid(m_Contents); return Pickups; } void cBlockEntityWithItems::CopyFrom(const cBlockEntity & a_Src) { Super::CopyFrom(a_Src); auto & src = static_cast(a_Src); m_Contents.CopyFrom(src.m_Contents); } void cBlockEntityWithItems::OnSlotChanged(cItemGrid * a_Grid, int a_SlotNum) { UNUSED(a_SlotNum); ASSERT(a_Grid == &m_Contents); if (m_World == nullptr) { return; } if (GetWindow() != nullptr) { GetWindow()->BroadcastWholeWindow(); } m_World->MarkChunkDirty(GetChunkX(), GetChunkZ()); // Notify comparators: m_World->WakeUpSimulators(m_Pos); } ================================================ FILE: src/BlockEntities/BlockEntityWithItems.h ================================================ // BlockEntityWithItems.h // Declares the cBlockEntityWithItems class representing a common ancestor for all block entities that have an ItemGrid #pragma once #include "BlockEntity.h" #include "../ItemGrid.h" #include "../UI/WindowOwner.h" #include "../World.h" // tolua_begin class cBlockEntityWithItems : public cBlockEntity, // tolua_end public cItemGrid::cListener, // tolua_begin public cBlockEntityWindowOwner { // tolua_end using Super = cBlockEntity; public: // tolua_export cBlockEntityWithItems( BLOCKTYPE a_BlockType, // Type of the block that the entity represents NIBBLETYPE a_BlockMeta, // Meta of the block that the entity represents Vector3i a_Pos, // Abs position of the block entity int a_ItemGridWidth, int a_ItemGridHeight, // Dimensions of the ItemGrid cWorld * a_World // Optional world to assign to the entity ); // cBlockEntity overrides: virtual cItems ConvertToPickups() const override; virtual void CopyFrom(const cBlockEntity & a_Src) override; // tolua_begin const cItem & GetSlot(int a_SlotNum) const { return m_Contents.GetSlot(a_SlotNum); } const cItem & GetSlot(int a_X, int a_Y) const { return m_Contents.GetSlot(a_X, a_Y); } void SetSlot(int a_SlotNum, const cItem & a_Item) { m_Contents.SetSlot(a_SlotNum, a_Item); } void SetSlot(int a_X, int a_Y, const cItem & a_Item) { m_Contents.SetSlot(a_X, a_Y, a_Item); } /** Returns the ItemGrid used for storing the contents */ cItemGrid & GetContents(void) { return m_Contents; } // tolua_end /** Const version of the GetContents() function for C++ type-safety */ const cItemGrid & GetContents(void) const { return m_Contents; } protected: cItemGrid m_Contents; // cItemGrid::cListener overrides: virtual void OnSlotChanged(cItemGrid * a_Grid, int a_SlotNum) override; } ; // tolua_export ================================================ FILE: src/BlockEntities/BrewingstandEntity.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "BrewingstandEntity.h" #include "../Bindings/PluginManager.h" #include "../UI/BrewingstandWindow.h" #include "../Entities/Player.h" #include "../Chunk.h" cBrewingstandEntity::cBrewingstandEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World): Super(a_BlockType, a_BlockMeta, a_Pos, ContentsWidth, ContentsHeight, a_World), m_IsBrewing(false), m_TimeBrewed(0), m_RemainingFuel(0) { m_Contents.AddListener(*this); } void cBrewingstandEntity::CopyFrom(const cBlockEntity & a_Src) { Super::CopyFrom(a_Src); auto & src = static_cast(a_Src); m_IsBrewing = src.m_IsBrewing; m_CurrentBrewingRecipes = src.m_CurrentBrewingRecipes; m_Results = src.m_Results; m_TimeBrewed = src.m_TimeBrewed; m_RemainingFuel = src.m_RemainingFuel; } void cBrewingstandEntity::OnRemoveFromWorld() { const auto Window = GetWindow(); if (Window != nullptr) { // Tell window its owner is destroyed: Window->OwnerDestroyed(); } } void cBrewingstandEntity::SendTo(cClientHandle & a_Client) { // Nothing needs to be sent UNUSED(a_Client); } bool cBrewingstandEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { UNUSED(a_Dt); if (!m_IsBrewing) { return false; } // The necessary brewing time, has been reached if (m_TimeBrewed >= m_NeedBrewingTime) { BroadcastProgress(0, 0); m_IsBrewing = false; m_TimeBrewed = 0; // Return if the hook has been cancelled if (cPluginManager::Get()->CallHookBrewingCompleting(*m_World, *this)) { return false; } // Decrease item count, full stacks are allowed in the ingredient slot cItem Ingredient = m_Contents.GetSlot(bsIngredient); Ingredient.m_ItemCount -= 1; m_Contents.SetSlot(bsIngredient, Ingredient); // Fuel slot m_RemainingFuel--; if (m_RemainingFuel <= 0) { if (!m_Contents.GetSlot(bsFuel).IsEmpty()) { cItem Fuel = m_Contents.GetSlot(bsFuel); Fuel.m_ItemCount -= 1; m_Contents.SetSlot(bsFuel, Fuel); m_RemainingFuel = 20; BroadcastProgress(1, m_RemainingFuel); } } else { BroadcastProgress(1, m_RemainingFuel); } // Loop over all bottle slots and update available bottles const cBrewingRecipes::cRecipe * Recipe = nullptr; for (std::size_t i = 0; i < 3; i++) { if (m_Contents.GetSlot(static_cast(i)).IsEmpty() || (m_CurrentBrewingRecipes[i] == nullptr)) { continue; } Recipe = m_CurrentBrewingRecipes[i]; m_Contents.SetSlot(static_cast(i), Recipe->Output.CopyOne()); } // Brewing process completed m_World->BroadcastSoundEffect("block.brewing_stand.brew", m_Pos, 1.0f, 1.0f); cPluginManager::Get()->CallHookBrewingCompleted(*m_World, *this); return true; } m_TimeBrewed++; UpdateProgressBars(false); return false; } bool cBrewingstandEntity::UsedBy(cPlayer * a_Player) { a_Player->GetStatistics().Custom[CustomStatistic::InteractWithBrewingstand]++; cWindow * Window = GetWindow(); if (Window == nullptr) { OpenWindow(new cBrewingstandWindow(this)); Window = GetWindow(); } if (Window != nullptr) { if (a_Player->GetWindow() != Window) { a_Player->OpenWindow(*Window); } } if (m_IsBrewing) { BroadcastProgress(0, m_NeedBrewingTime - m_TimeBrewed); } else { BroadcastProgress(0, 0); } BroadcastProgress(1, m_RemainingFuel); return true; } void cBrewingstandEntity::BroadcastProgress(size_t a_ProgressbarID, short a_Value) { cWindow * Window = GetWindow(); if (Window != nullptr) { Window->SetProperty(a_ProgressbarID, a_Value); } } void cBrewingstandEntity::OnSlotChanged(cItemGrid * a_ItemGrid, int a_SlotNum) { Super::OnSlotChanged(a_ItemGrid, a_SlotNum); ASSERT(a_ItemGrid == &m_Contents); // Check for fuel if (m_RemainingFuel <= 0) { if (GetSlot(bsFuel).IsEmpty()) { // No remaining fuel stop brewing and bail out m_IsBrewing = false; return; } else { // Fuel is available, refill m_RemainingFuel = 20; BroadcastProgress(1, m_RemainingFuel); cItem Fuel = m_Contents.GetSlot(bsFuel); Fuel.m_ItemCount -= 1; m_Contents.SetSlot(bsFuel, Fuel); } } // Check if still a item is in the ingredient slot if (GetSlot(bsIngredient).IsEmpty()) { if (m_IsBrewing) { // Cancel brewing BroadcastProgress(0, 0); m_IsBrewing = false; m_TimeBrewed = 0; } return; } // Recheck the bottles cBrewingRecipes * BR = cRoot::Get()->GetBrewingRecipes(); const cBrewingRecipes::cRecipe * Recipe = nullptr; bool Stop = true; for (std::size_t i = 0; i < 3; i++) { if (GetSlot(static_cast(i)).IsEmpty()) { m_CurrentBrewingRecipes[i] = nullptr; m_Results[i].Clear(); continue; } if (m_CurrentBrewingRecipes[i] != nullptr) { Recipe = m_CurrentBrewingRecipes[i]; if (Recipe->Ingredient.IsEqual(GetSlot(bsIngredient)) && Recipe->Input.IsEqual(GetSlot(static_cast(i)))) { Stop = false; continue; } } Recipe = BR->GetRecipeFrom(m_Contents.GetSlot(static_cast(i)), m_Contents.GetSlot(bsIngredient)); if (Recipe != nullptr) { // Found a brewing recipe for the items m_CurrentBrewingRecipes[i] = Recipe; m_Results[i] = Recipe->Output.CopyOne(); Stop = false; } } if (Stop) { if (m_IsBrewing) { // Cancel brewing BroadcastProgress(0, 0); m_IsBrewing = false; m_TimeBrewed = 0; } return; } // Start brewing process, if not running if (!m_IsBrewing) { m_IsBrewing = true; } } void cBrewingstandEntity::UpdateProgressBars(bool a_ForceUpdate) { // Send an update every 3rd tick, using a higher value makes the progressbar look ugly: if (!a_ForceUpdate && ((m_World->GetWorldTickAge() % 3_tick) != 0_tick)) { return; } BroadcastProgress(0, m_NeedBrewingTime - m_TimeBrewed); } void cBrewingstandEntity::ContinueBrewing(void) { // Continue brewing if number is greater than 0 if ((m_TimeBrewed > 0) && (m_RemainingFuel > 0)) { m_IsBrewing = true; } } void cBrewingstandEntity::LoadRecipes(void) { if (GetSlot(bsIngredient).IsEmpty()) { return; } cBrewingRecipes * BR = cRoot::Get()->GetBrewingRecipes(); const cBrewingRecipes::cRecipe * Recipe = nullptr; for (std::size_t i = 0; i < 3; i++) { if (GetSlot(static_cast(i)).IsEmpty()) { continue; } Recipe = BR->GetRecipeFrom(GetSlot(static_cast(i)), GetSlot(bsIngredient)); if (Recipe != nullptr) { m_CurrentBrewingRecipes[i] = Recipe; m_Results[i] = Recipe->Output.CopyOne(); } } } ================================================ FILE: src/BlockEntities/BrewingstandEntity.h ================================================ #pragma once #include "BlockEntityWithItems.h" #include "../BrewingRecipes.h" #include "../Root.h" class cClientHandle; // tolua_begin class cBrewingstandEntity : public cBlockEntityWithItems { // tolua_end using Super = cBlockEntityWithItems; // tolua_begin public: enum { bsLeftBottle = 0, // Left bottle slot number bsMiddleBottle = 1, // Middle bottle slot number bsRightBottle = 2, // Right bottle slot number bsIngredient = 3, // Top ingredient slot number bsFuel = 4, // Top left fuel slot number ContentsWidth = 5, ContentsHeight = 1, }; // tolua_end /** Constructor used for normal operation */ cBrewingstandEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World); // cBlockEntity overrides: virtual void CopyFrom(const cBlockEntity & a_Src) override; virtual void OnRemoveFromWorld() override; virtual void SendTo(cClientHandle & a_Client) override; virtual bool Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; virtual bool UsedBy(cPlayer * a_Player) override; // tolua_begin /** Returns the time until the current items finishes brewing, in ticks */ short GetBrewingTimeLeft(void) const { return m_NeedBrewingTime - m_TimeBrewed; } /** Returns the time that the current items has been brewing, in ticks */ short GetTimeBrewed(void) { return m_TimeBrewed; } /** Returns the remaining fuel that is left. */ short GetRemainingFuel(void) { return m_RemainingFuel; } /** Returns the item in the left bottle slot */ const cItem & GetLeftBottleSlot(void) const { return GetSlot(bsLeftBottle); } /** Returns the item in the middle bottle slot */ const cItem & GetMiddleBottleSlot(void) const { return GetSlot(bsMiddleBottle); } /** Returns the item in the right bottle slot */ const cItem & GetRightBottleSlot(void) const { return GetSlot(bsRightBottle); } /** Returns the item in the ingredient slot */ const cItem & GetIndgredientSlot(void) const { return GetSlot(bsIngredient); } /** Returns the item in the fuel slot. */ const cItem & GetFuelSlot(void) const { return GetSlot(bsFuel); } /** Get the expected result item for the given slot number */ const cItem & GetResultItem(size_t a_SlotNumber) { return m_Results[a_SlotNumber]; } /** Sets the item in the left bottle slot */ void SetLeftBottleSlot(const cItem & a_Item) { SetSlot(bsLeftBottle, a_Item); } /** Sets the item in the middle bottle slot */ void SetMiddleBottleSlot(const cItem & a_Item) { SetSlot(bsMiddleBottle, a_Item); } /** Sets the item in the right bottle slot */ void SetRightBottleSlot(const cItem & a_Item) { SetSlot(bsRightBottle, a_Item); } /** Sets the item in the ingredient slot */ void SetIngredientSlot(const cItem & a_Item) { SetSlot(bsIngredient, a_Item); } /** Sets the item in the fuel slot */ void SetFuelSlot(const cItem & a_Item) { SetSlot(bsFuel, a_Item); } // tolua_end /** Sets the current brewing time. Will be called if the brewing stand gets loaded from the world. */ void SetTimeBrewed(short a_TimeBrewed) { m_TimeBrewed = a_TimeBrewed; } /** Sets the remaining fuel. Will be called if the brewing stand gets loaded from the world. */ void SetRemainingFuel(short a_RemainingFuel) { m_RemainingFuel = a_RemainingFuel; } /** Starts the brewing proccess. Will be called if the brewing stand gets loaded from the world. */ void ContinueBrewing(void); /** Gets the recipes. Will be called if the brewing stand gets loaded from the world. */ void LoadRecipes(void); protected: /** Set to true if the brewing stand is brewing an item */ bool m_IsBrewing; /** Brewing time is 400 ticks */ const short m_NeedBrewingTime = 400; /** Store the current brewing recipes */ std::array m_CurrentBrewingRecipes = {}; /** Result items for the bottle inputs */ std::array m_Results; /** Amount of ticks that the current item has been brewed */ short m_TimeBrewed; /** The remaining fuel for the brewing stand. It's the amount of brewing operations that can be done. */ short m_RemainingFuel; /** Sends the specified progressbar value to all clients of the window */ void BroadcastProgress(size_t a_ProgressbarID, short a_Value); // /** Broadcasts progressbar updates, if needed */ void UpdateProgressBars(bool a_ForceUpdate = false); // cItemGrid::cListener overrides: virtual void OnSlotChanged(cItemGrid * a_ItemGrid, int a_SlotNum) override; } ; // tolua_export ================================================ FILE: src/BlockEntities/CMakeLists.txt ================================================ target_sources( ${CMAKE_PROJECT_NAME} PRIVATE BannerEntity.cpp BeaconEntity.cpp BedEntity.cpp BlockEntity.cpp BlockEntityWithItems.cpp BrewingstandEntity.cpp ChestEntity.cpp CommandBlockEntity.cpp DispenserEntity.cpp DropSpenserEntity.cpp DropperEntity.cpp EnchantingTableEntity.cpp EndPortalEntity.cpp EnderChestEntity.cpp FlowerPotEntity.cpp FurnaceEntity.cpp HopperEntity.cpp JukeboxEntity.cpp MobHeadEntity.cpp MobSpawnerEntity.cpp NoteEntity.cpp SignEntity.cpp BannerEntity.h BeaconEntity.h BedEntity.h BlockEntity.h BlockEntityWithItems.h BrewingstandEntity.h ChestEntity.h CommandBlockEntity.h DispenserEntity.h DropSpenserEntity.h DropperEntity.h EnchantingTableEntity.h EndPortalEntity.h EnderChestEntity.h FlowerPotEntity.h FurnaceEntity.h HopperEntity.h JukeboxEntity.h MobHeadEntity.h MobSpawnerEntity.h NoteEntity.h SignEntity.h ) ================================================ FILE: src/BlockEntities/ChestEntity.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "ChestEntity.h" #include "../Chunk.h" #include "../BlockInfo.h" #include "../Item.h" #include "../Entities/Player.h" #include "../UI/ChestWindow.h" #include "../ClientHandle.h" #include "../Mobs/Ocelot.h" cChestEntity::cChestEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World): Super(a_BlockType, a_BlockMeta, a_Pos, ContentsWidth, ContentsHeight, a_World), m_NumActivePlayers(0), m_Neighbour(nullptr) { } cChestEntity & cChestEntity::GetPrimaryChest() { if (m_Neighbour == nullptr) { return *this; } // The primary chest should be the one with lesser X or Z coord: return ( (m_Neighbour->GetPosX() < GetPosX()) || (m_Neighbour->GetPosZ() < GetPosZ()) ) ? *m_Neighbour : *this; } cChestEntity * cChestEntity::GetSecondaryChest() { // If we're the primary, then our neighbour is the secondary, and vice versa: return (&GetPrimaryChest() == this) ? m_Neighbour : this; } bool cChestEntity::ScanNeighbour(cChunk & a_Chunk, Vector3i a_Position) { const auto Chunk = a_Chunk.GetRelNeighborChunkAdjustCoords(a_Position); if ((Chunk == nullptr) || !Chunk->IsValid()) { // If a chest was in fact there, they'll find us when their chunk loads. return false; } const auto BlockEntity = Chunk->GetBlockEntityRel(a_Position); if ((BlockEntity == nullptr) || (BlockEntity->GetBlockType() != m_BlockType)) { // Neighbouring block is not the same type of chest: return false; } m_Neighbour = static_cast(BlockEntity); return true; } void cChestEntity::DestroyWindow() { const auto Window = GetWindow(); if (Window != nullptr) { Window->OwnerDestroyed(); } } bool cChestEntity::IsBlocked() { return ( (GetPosY() < cChunkDef::Height - 1) && ( !cBlockInfo::IsTransparent(GetWorld()->GetBlock(GetPos().addedY(1))) || !cOcelot::IsCatSittingOnBlock(GetWorld(), Vector3d(GetPos())) ) ); } void cChestEntity::OpenNewWindow(void) { if (m_Neighbour != nullptr) { ASSERT(&GetPrimaryChest() == this); // Should only open windows for the primary chest. OpenWindow(new cChestWindow(this, m_Neighbour)); } else { // There is no chest neighbour, open a single-chest window: OpenWindow(new cChestWindow(this)); } } void cChestEntity::CopyFrom(const cBlockEntity & a_Src) { Super::CopyFrom(a_Src); auto & src = static_cast(a_Src); m_Contents.CopyFrom(src.m_Contents); // Reset the neighbor and player count, there's no sense in copying these: m_Neighbour = nullptr; m_NumActivePlayers = 0; } void cChestEntity::OnAddToWorld(cWorld & a_World, cChunk & a_Chunk) { Super::OnAddToWorld(a_World, a_Chunk); // Scan horizontally adjacent blocks for any neighbouring chest of the same type: if ( const auto Position = GetRelPos(); ScanNeighbour(a_Chunk, Position.addedX(-1)) || ScanNeighbour(a_Chunk, Position.addedX(+1)) || ScanNeighbour(a_Chunk, Position.addedZ(-1)) || ScanNeighbour(a_Chunk, Position.addedZ(+1)) ) { m_Neighbour->m_Neighbour = this; m_Neighbour->DestroyWindow(); // Force neighbour's window shut. Does Mojang server do this or should a double window open? } } void cChestEntity::OnRemoveFromWorld() { if (m_Neighbour != nullptr) { // Neighbour may share a window with us, force the window shut: m_Neighbour->DestroyWindow(); m_Neighbour->m_Neighbour = nullptr; } DestroyWindow(); } void cChestEntity::SendTo(cClientHandle & a_Client) { a_Client.SendUpdateBlockEntity(*this); } bool cChestEntity::UsedBy(cPlayer * a_Player) { if (IsBlocked()) { // Obstruction, don't open return true; } if ((m_Neighbour != nullptr) && m_Neighbour->IsBlocked()) { return true; } if (m_BlockType == E_BLOCK_CHEST) { a_Player->GetStatistics().Custom[CustomStatistic::OpenChest]++; } else // E_BLOCK_TRAPPED_CHEST { a_Player->GetStatistics().Custom[CustomStatistic::TriggerTrappedChest]++; } auto & PrimaryChest = GetPrimaryChest(); cWindow * Window = PrimaryChest.GetWindow(); // If the window is not created, open it anew: if (Window == nullptr) { PrimaryChest.OpenNewWindow(); Window = PrimaryChest.GetWindow(); } // Open the window for the player: if (Window != nullptr) { if (a_Player->GetWindow() != Window) { a_Player->OpenWindow(*Window); } } return true; } void cChestEntity::OnSlotChanged(cItemGrid * a_Grid, int a_SlotNum) { ASSERT(a_Grid == &m_Contents); // Have cBlockEntityWithItems update redstone and try to broadcast our window: Super::OnSlotChanged(a_Grid, a_SlotNum); cWindow * Window = GetWindow(); if ((Window == nullptr) && (m_Neighbour != nullptr)) { // Window was null, Super will have failed. // Neighbour might own the window: Window = m_Neighbour->GetWindow(); } if (Window != nullptr) { Window->BroadcastWholeWindow(); } } ================================================ FILE: src/BlockEntities/ChestEntity.h ================================================ #pragma once #include "BlockEntityWithItems.h" #include "../Simulator/RedstoneSimulator.h" class cClientHandle; // tolua_begin class cChestEntity : public cBlockEntityWithItems { // tolua_end using Super = cBlockEntityWithItems; // tolua_begin public: enum { ContentsHeight = 3, ContentsWidth = 9, } ; // tolua_end cChestEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World); /** Gets the number of players who currently have this chest open */ int GetNumberOfPlayers(void) const { return m_NumActivePlayers; } /** Returns the associated primary chest. */ cChestEntity & GetPrimaryChest(); /** Returns the associated secondary chest, if any. */ cChestEntity * GetSecondaryChest(); /** Search the given horizontally adjacent relative position for a neighbouring chest of the same type. If found, links them together with ourselves and returns true. */ bool ScanNeighbour(cChunk & a_Chunk, Vector3i a_Position); /** Sets the number of players who currently have this chest open */ void SetNumberOfPlayers(int a_NumActivePlayers) { m_NumActivePlayers = a_NumActivePlayers; } private: /** Number of players who currently have this chest open */ int m_NumActivePlayers; /** Neighbouring chest that links to form a double chest */ cChestEntity * m_Neighbour; /** Forces any players to close the owned window. */ void DestroyWindow(); /** Returns true if the chest should not be accessible by players. */ bool IsBlocked(); /** Opens a new chest window where this is the primary chest and any neighbour is the secondary. */ void OpenNewWindow(); // cBlockEntity overrides: virtual void CopyFrom(const cBlockEntity & a_Src) override; virtual void OnAddToWorld(cWorld & a_World, cChunk & a_Chunk) override; virtual void OnRemoveFromWorld() override; virtual void SendTo(cClientHandle & a_Client) override; virtual bool UsedBy(cPlayer * a_Player) override; /** cItemGrid::cListener overrides: */ virtual void OnSlotChanged(cItemGrid * a_Grid, int a_SlotNum) override; } ; // tolua_export ================================================ FILE: src/BlockEntities/CommandBlockEntity.cpp ================================================ // CommandBlockEntity.cpp // Implements the cCommandBlockEntity class representing a single command block in the world #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "CommandBlockEntity.h" #include "../CommandOutput.h" #include "../Root.h" #include "../Server.h" // ExecuteConsoleCommand() #include "../ChatColor.h" #include "../World.h" #include "../ClientHandle.h" cCommandBlockEntity::cCommandBlockEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World): Super(a_BlockType, a_BlockMeta, a_Pos, a_World), m_ShouldExecute(false), m_Result(0) { ASSERT(a_BlockType == E_BLOCK_COMMAND_BLOCK); } bool cCommandBlockEntity::UsedBy(cPlayer * a_Player) { // Nothing to do UNUSED(a_Player); return true; } void cCommandBlockEntity::SetCommand(const AString & a_Cmd) { m_Command = a_Cmd; } void cCommandBlockEntity::SetLastOutput(const AString & a_LastOut) { m_LastOutput = a_LastOut; } void cCommandBlockEntity::SetResult(const NIBBLETYPE a_Result) { m_Result = a_Result; } const AString & cCommandBlockEntity::GetCommand(void) const { return m_Command; } const AString & cCommandBlockEntity::GetLastOutput(void) const { return m_LastOutput; } NIBBLETYPE cCommandBlockEntity::GetResult(void) const { return m_Result; } void cCommandBlockEntity::Activate(void) { m_ShouldExecute = true; } void cCommandBlockEntity::CopyFrom(const cBlockEntity & a_Src) { Super::CopyFrom(a_Src); auto & src = static_cast(a_Src); m_Command = src.m_Command; m_LastOutput = src.m_LastOutput; m_Result = src.m_Result; m_ShouldExecute = src.m_ShouldExecute; } bool cCommandBlockEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { UNUSED(a_Dt); UNUSED(a_Chunk); if (!m_ShouldExecute) { return false; } m_ShouldExecute = false; Execute(); return true; } void cCommandBlockEntity::SendTo(cClientHandle & a_Client) { a_Client.SendUpdateBlockEntity(*this); } void cCommandBlockEntity::Execute() { ASSERT(m_World != nullptr); // Execute should not be called before the command block is attached to a world if (!m_World->AreCommandBlocksEnabled()) { return; } if (m_Command.empty()) { return; } class CommandBlockOutCb : public cLogCommandDeleteSelfOutputCallback { cCommandBlockEntity * m_CmdBlock; public: CommandBlockOutCb(cCommandBlockEntity * a_CmdBlock) : m_CmdBlock(a_CmdBlock) {} virtual void Out(const AString & a_Text) override { // Overwrite field m_CmdBlock->SetLastOutput(cClientHandle::FormatChatPrefix(m_CmdBlock->GetWorld()->ShouldUseChatPrefixes(), "SUCCESS", cChatColor::Green, cChatColor::White) + a_Text); } }; AString RealCommand = m_Command; // Remove leading slash if it exists, since console commands don't use them if (RealCommand[0] == '/') { RealCommand = RealCommand.substr(1, RealCommand.length()); } // Administrator commands are not executable by command blocks: if ( (RealCommand != "stop") && (RealCommand != "restart") && (RealCommand != "kick") && (RealCommand != "ban") && (RealCommand != "ipban") ) { cServer * Server = cRoot::Get()->GetServer(); LOGD("cCommandBlockEntity: Executing command %s", m_Command.c_str()); Server->QueueExecuteConsoleCommand(RealCommand, *new CommandBlockOutCb(this)); } else { SetLastOutput(cClientHandle::FormatChatPrefix(GetWorld()->ShouldUseChatPrefixes(), "FAILURE", cChatColor::Rose, cChatColor::White) + "Adminstration commands can not be executed"); LOGD("cCommandBlockEntity: Prevented execution of administration command %s", m_Command.c_str()); } // TODO 2014-01-18 xdot: Update the signal strength. m_Result = 0; } ================================================ FILE: src/BlockEntities/CommandBlockEntity.h ================================================ // CommandBlockEntity.h // Declares the cCommandBlockEntity class representing a single command block in the world #pragma once #include "BlockEntity.h" // tolua_begin class cCommandBlockEntity : public cBlockEntity { // tolua_end using Super = cBlockEntity; public: // tolua_export /** Creates a new empty command block entity */ cCommandBlockEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World); // cBlockEntity overrides: virtual void CopyFrom(const cBlockEntity & a_Src) override; virtual bool Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; virtual void SendTo(cClientHandle & a_Client) override; virtual bool UsedBy(cPlayer * a_Player) override; void SetLastOutput(const AString & a_LastOut); void SetResult(const NIBBLETYPE a_Result); // tolua_begin /** Sets the command block to execute a command in the next tick */ void Activate(void); /** Sets the command */ void SetCommand(const AString & a_Cmd); /** Retrieves stored command */ const AString & GetCommand(void) const; /** Retrieves the last line of output generated by the command block */ const AString & GetLastOutput(void) const; /** Retrieves the result (signal strength) of the last operation */ NIBBLETYPE GetResult(void) const; // tolua_end private: /** Executes the associated command */ void Execute(); bool m_ShouldExecute; AString m_Command; AString m_LastOutput; NIBBLETYPE m_Result; } ; // tolua_export ================================================ FILE: src/BlockEntities/DispenserEntity.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "DispenserEntity.h" #include "../Chunk.h" #include "../BlockInfo.h" #include "../Defines.h" #include "../World.h" #include "../Entities/Boat.h" #include "../Entities/ProjectileEntity.h" #include "../Simulator/FluidSimulator.h" #include "../Items/ItemSpawnEgg.h" #include "../Items/ItemDye.h" cDispenserEntity::cDispenserEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World): Super(a_BlockType, a_BlockMeta, a_Pos, a_World) { ASSERT(a_BlockType == E_BLOCK_DISPENSER); } void cDispenserEntity::DropSpenseFromSlot(cChunk & a_Chunk, int a_SlotNum) { Vector3i DispRelCoord(GetRelPos()); auto Meta = a_Chunk.GetMeta(DispRelCoord); AddDropSpenserDir(DispRelCoord, Meta); auto DispChunk = a_Chunk.GetRelNeighborChunkAdjustCoords(DispRelCoord); if (DispChunk == nullptr) { // Would dispense into / interact with a non-loaded chunk, ignore the tick return; } BLOCKTYPE DispBlock = DispChunk->GetBlock(DispRelCoord); auto DispAbsCoord = DispChunk->RelativeToAbsolute(DispRelCoord); // Dispense the item: const cItem & SlotItem = m_Contents.GetSlot(a_SlotNum); if (ItemCategory::IsMinecart(SlotItem.m_ItemType) && IsBlockRail(DispBlock)) // only actually place the minecart if there are rails! { if (m_World->SpawnMinecart(DispAbsCoord.x + 0.5, DispAbsCoord.y + 0.5, DispAbsCoord.z + 0.5, SlotItem.m_ItemType) != cEntity::INVALID_ID) { m_Contents.ChangeSlotCount(a_SlotNum, -1); } return; } switch (SlotItem.m_ItemType) { case E_ITEM_BUCKET: { LOGD("Dispensing empty bucket in slot %d; DispBlock is \"%s\" (%d).", a_SlotNum, ItemTypeToString(DispBlock).c_str(), DispBlock); switch (DispBlock) { case E_BLOCK_STATIONARY_WATER: case E_BLOCK_WATER: { if (ScoopUpLiquid(a_SlotNum, E_ITEM_WATER_BUCKET)) { DispChunk->SetBlock(DispRelCoord, E_BLOCK_AIR, 0); } break; } case E_BLOCK_STATIONARY_LAVA: case E_BLOCK_LAVA: { if (ScoopUpLiquid(a_SlotNum, E_ITEM_LAVA_BUCKET)) { DispChunk->SetBlock(DispRelCoord, E_BLOCK_AIR, 0); } break; } default: { DropFromSlot(a_Chunk, a_SlotNum); break; } } break; } // E_ITEM_BUCKET case E_ITEM_WATER_BUCKET: { LOGD("Dispensing water bucket in slot %d; DispBlock is \"%s\" (%d).", a_SlotNum, ItemTypeToString(DispBlock).c_str(), DispBlock); if (EmptyLiquidBucket(DispBlock, a_SlotNum)) { DispChunk->SetBlock(DispRelCoord, E_BLOCK_WATER, 0); } else { DropFromSlot(a_Chunk, a_SlotNum); } break; } case E_ITEM_LAVA_BUCKET: { LOGD("Dispensing lava bucket in slot %d; DispBlock is \"%s\" (%d).", a_SlotNum, ItemTypeToString(DispBlock).c_str(), DispBlock); if (EmptyLiquidBucket(DispBlock, a_SlotNum)) { DispChunk->SetBlock(DispRelCoord, E_BLOCK_LAVA, 0); } else { DropFromSlot(a_Chunk, a_SlotNum); } break; } case E_ITEM_SPAWN_EGG: { double MobX = 0.5 + DispAbsCoord.x; double MobZ = 0.5 + DispAbsCoord.z; auto MonsterType = cItemSpawnEggHandler::ItemDamageToMonsterType(m_Contents.GetSlot(a_SlotNum).m_ItemDamage); if (m_World->SpawnMob(MobX, DispAbsCoord.y, MobZ, MonsterType, false) != cEntity::INVALID_ID) { m_Contents.ChangeSlotCount(a_SlotNum, -1); } break; } case E_BLOCK_TNT: { // Spawn a primed TNT entity, if space allows: if (!cBlockInfo::IsSolid(DispBlock)) { m_World->SpawnPrimedTNT(Vector3d(0.5, 0.5, 0.5) + DispAbsCoord, 80, 0); // 80 ticks fuse, no initial velocity m_Contents.ChangeSlotCount(a_SlotNum, -1); } break; } case E_ITEM_FLINT_AND_STEEL: { // Spawn fire if the block in front is air. if (DispBlock == E_BLOCK_AIR) { DispChunk->SetBlock(DispRelCoord, E_BLOCK_FIRE, 0); bool ItemBroke = m_Contents.DamageItem(a_SlotNum, 1); if (ItemBroke) { m_Contents.ChangeSlotCount(a_SlotNum, -1); } } break; } case E_ITEM_FIRE_CHARGE: { if (SpawnProjectileFromDispenser(DispAbsCoord, cProjectileEntity::pkFireCharge, GetShootVector(Meta) * 20) != cEntity::INVALID_ID) { m_Contents.ChangeSlotCount(a_SlotNum, -1); } break; } case E_ITEM_ARROW: { if (SpawnProjectileFromDispenser(DispAbsCoord, cProjectileEntity::pkArrow, GetShootVector(Meta) * 30 + Vector3d(0, 1, 0)) != cEntity::INVALID_ID) { m_Contents.ChangeSlotCount(a_SlotNum, -1); } break; } case E_ITEM_SNOWBALL: { if (SpawnProjectileFromDispenser(DispAbsCoord, cProjectileEntity::pkSnowball, GetShootVector(Meta) * 20 + Vector3d(0, 1, 0)) != cEntity::INVALID_ID) { m_Contents.ChangeSlotCount(a_SlotNum, -1); } break; } case E_ITEM_EGG: { if (SpawnProjectileFromDispenser(DispAbsCoord, cProjectileEntity::pkEgg, GetShootVector(Meta) * 20 + Vector3d(0, 1, 0)) != cEntity::INVALID_ID) { m_Contents.ChangeSlotCount(a_SlotNum, -1); } break; } case E_ITEM_BOTTLE_O_ENCHANTING: { if (SpawnProjectileFromDispenser(DispAbsCoord, cProjectileEntity::pkExpBottle, GetShootVector(Meta) * 20 + Vector3d(0, 1, 0)) != cEntity::INVALID_ID) { m_Contents.ChangeSlotCount(a_SlotNum, -1); } break; } case E_ITEM_POTION: { if (SpawnProjectileFromDispenser(DispAbsCoord, cProjectileEntity::pkSplashPotion, GetShootVector(Meta) * 20 + Vector3d(0, 1, 0), &SlotItem) != cEntity::INVALID_ID) { m_Contents.ChangeSlotCount(a_SlotNum, -1); } break; } case E_ITEM_DYE: { if (SlotItem.m_ItemDamage != E_META_DYE_WHITE) { DropFromSlot(a_Chunk, a_SlotNum); break; } // Simulate a right-click with bonemeal: if (cItemDyeHandler::FertilizePlant(*m_World, DispAbsCoord)) { m_Contents.ChangeSlotCount(a_SlotNum, -1); } break; } case E_ITEM_BOAT: case E_ITEM_SPRUCE_BOAT: case E_ITEM_BIRCH_BOAT: case E_ITEM_JUNGLE_BOAT: case E_ITEM_ACACIA_BOAT: case E_ITEM_DARK_OAK_BOAT: { Vector3d spawnPos = DispAbsCoord; if (IsBlockWater(DispBlock)) { // Water next to the dispenser, spawn a boat above the water block spawnPos.y += 1; } else if (IsBlockWater(DispChunk->GetBlock(DispRelCoord.addedY(-1)))) { // Water one block below the dispenser, spawn a boat at the dispenser's Y level // No adjustment needed } else { // There's no eligible water block, drop the boat as a pickup DropFromSlot(a_Chunk, a_SlotNum); break; } spawnPos += GetShootVector(Meta) * 0.8; // A boat is bigger than one block. Add the shoot vector to put it outside the dispenser. spawnPos += Vector3d(0.5, 0.5, 0.5); if (m_World->SpawnBoat(spawnPos, cBoat::ItemToMaterial(SlotItem))) { m_Contents.ChangeSlotCount(a_SlotNum, -1); } break; } case E_ITEM_FIREWORK_ROCKET: { if (SpawnProjectileFromDispenser(DispAbsCoord, cProjectileEntity::pkFirework, GetShootVector(Meta) * 20 + Vector3d(0, 1, 0), &SlotItem) != cEntity::INVALID_ID) { m_Contents.ChangeSlotCount(a_SlotNum, -1); } break; } default: { DropFromSlot(a_Chunk, a_SlotNum); break; } } // switch (SlotItem.m_ItemType) } UInt32 cDispenserEntity::SpawnProjectileFromDispenser(Vector3i a_BlockPos, cProjectileEntity::eKind a_Kind, const Vector3d & a_ShootVector, const cItem * a_Item) { return m_World->CreateProjectile(Vector3d(0.5, 0.5, 0.5) + a_BlockPos, a_Kind, nullptr, a_Item, &a_ShootVector ); } Vector3d cDispenserEntity::GetShootVector(NIBBLETYPE a_Meta) { switch (a_Meta & E_META_DROPSPENSER_FACING_MASK) { case E_META_DROPSPENSER_FACING_YP: return Vector3d( 0, 1, 0); case E_META_DROPSPENSER_FACING_YM: return Vector3d( 0, -1, 0); case E_META_DROPSPENSER_FACING_XM: return Vector3d(-1, 0, 0); case E_META_DROPSPENSER_FACING_XP: return Vector3d( 1, 0, 0); case E_META_DROPSPENSER_FACING_ZM: return Vector3d( 0, 0, -1); case E_META_DROPSPENSER_FACING_ZP: return Vector3d( 0, 0, 1); } LOGWARNING("Unhandled dispenser meta: %d", a_Meta); ASSERT(!"Unhandled dispenser facing"); return Vector3d(0, 1, 0); } bool cDispenserEntity::ScoopUpLiquid(int a_SlotNum, short a_ResultingBucketItemType) { cItem LiquidBucket(a_ResultingBucketItemType); if (m_Contents.GetSlot(a_SlotNum).m_ItemCount == 1) { // Special case: replacing one empty bucket with one full bucket m_Contents.SetSlot(a_SlotNum, LiquidBucket); return true; } // There are stacked buckets at the selected slot, see if a full bucket will fit somewhere else if (m_Contents.HowManyCanFit(LiquidBucket) < 1) { // Cannot fit into m_Contents return false; } m_Contents.ChangeSlotCount(a_SlotNum, -1); m_Contents.AddItem(LiquidBucket); return true; } bool cDispenserEntity::EmptyLiquidBucket(BLOCKTYPE a_BlockInFront, int a_SlotNum) { if ( (a_BlockInFront != E_BLOCK_AIR) && !IsBlockLiquid(a_BlockInFront) && !cFluidSimulator::CanWashAway(a_BlockInFront) ) { // Not a suitable block in front return false; } cItem EmptyBucket(E_ITEM_BUCKET, 1); if (m_Contents.GetSlot(a_SlotNum).m_ItemCount == 1) { // Change the single full bucket present into a single empty bucket m_Contents.SetSlot(a_SlotNum, EmptyBucket); return true; } // There are full buckets stacked at this slot, check if we can fit in the empty bucket if (m_Contents.HowManyCanFit(EmptyBucket) < 1) { // The empty bucket wouldn't fit into m_Contents return false; } // The empty bucket fits in, remove one full bucket and add the empty one m_Contents.ChangeSlotCount(a_SlotNum, -1); m_Contents.AddItem(EmptyBucket); return true; } ================================================ FILE: src/BlockEntities/DispenserEntity.h ================================================ #pragma once #include "DropSpenserEntity.h" // tolua_begin class cDispenserEntity : public cDropSpenserEntity { // tolua_end using Super = cDropSpenserEntity; public: // tolua_export /** Constructor used for normal operation */ cDispenserEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World); // tolua_begin /** Spawns a projectile of the given kind in front of the dispenser with the specified speed. a_Item is the item from the internal storage from which the projectile originated. Returns the UniqueID of the spawned projectile, or cEntity::INVALID_ID on failure. */ UInt32 SpawnProjectileFromDispenser( Vector3i a_BlockPos, cProjectileEntity::eKind a_Kind, const Vector3d & a_Speed, const cItem * a_Item = nullptr ); /** OBSOLETE, use the Vector3i-based overload instead. Spawns a projectile of the given kind in front of the dispenser with the specified speed. a_Item is the item from the internal storage from which the projectile originated. Returns the UniqueID of the spawned projectile, or cEntity::INVALID_ID on failure. */ UInt32 SpawnProjectileFromDispenser( int a_BlockX, int a_BlockY, int a_BlockZ, cProjectileEntity::eKind a_Kind, const Vector3d & a_Speed, const cItem * a_Item = nullptr ) { return SpawnProjectileFromDispenser({a_BlockX, a_BlockY, a_BlockZ}, a_Kind, a_Speed, a_Item); } /** Returns a unit vector in the cardinal direction of where the dispenser with the specified meta would be facing. */ static Vector3d GetShootVector(NIBBLETYPE a_BlockMeta); // tolua_end private: // cDropSpenser overrides: virtual void DropSpenseFromSlot(cChunk & a_Chunk, int a_SlotNum) override; /** If such a bucket can fit, adds it to m_Contents and returns true */ bool ScoopUpLiquid(int a_SlotNum, short a_ResultingBucketItemType); /** If the a_BlockInFront can be washed away by liquid and the empty bucket can fit, does the m_Contents processing and returns true. Returns false otherwise. */ bool EmptyLiquidBucket(BLOCKTYPE a_BlockInFront, int a_SlotNum); } ; // tolua_export ================================================ FILE: src/BlockEntities/DropSpenserEntity.cpp ================================================ // DropSpenserEntity.cpp // Declares the cDropSpenserEntity class representing a common ancestor to the cDispenserEntity and cDropperEntity // The dropper and dispenser only needs to override the DropSpenseFromSlot() function to provide the specific item behavior #include "Globals.h" #include "DropSpenserEntity.h" #include "../Bindings/PluginManager.h" #include "../EffectID.h" #include "../Entities/Player.h" #include "../Chunk.h" #include "../UI/DropSpenserWindow.h" cDropSpenserEntity::cDropSpenserEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World): Super(a_BlockType, a_BlockMeta, a_Pos, ContentsWidth, ContentsHeight, a_World), m_ShouldDropSpense(false) { } void cDropSpenserEntity::AddDropSpenserDir(Vector3i & a_RelCoord, NIBBLETYPE a_Direction) { switch (a_Direction & E_META_DROPSPENSER_FACING_MASK) { case E_META_DROPSPENSER_FACING_YM: a_RelCoord.y--; return; case E_META_DROPSPENSER_FACING_YP: a_RelCoord.y++; return; case E_META_DROPSPENSER_FACING_ZM: a_RelCoord.z--; return; case E_META_DROPSPENSER_FACING_ZP: a_RelCoord.z++; return; case E_META_DROPSPENSER_FACING_XM: a_RelCoord.x--; return; case E_META_DROPSPENSER_FACING_XP: a_RelCoord.x++; return; } LOGWARNING("%s: Unhandled direction: %d", __FUNCTION__, a_Direction); } void cDropSpenserEntity::DropSpense(cChunk & a_Chunk) { // Pick one of the occupied slots: std::array OccupiedSlots; size_t SlotsCnt = 0; for (int i = m_Contents.GetNumSlots() - 1; i >= 0; i--) { if (!m_Contents.GetSlot(i).IsEmpty()) { OccupiedSlots[SlotsCnt] = i; SlotsCnt++; } } // for i - m_Contents[] if (SlotsCnt == 0) { // Nothing in the dropspenser, play the click sound m_World->BroadcastSoundEffect("block.dispenser.fail", m_Pos, 1.0f, 1.2f); return; } const size_t RandomSlot = GetRandomProvider().RandInt(SlotsCnt - 1); const int SpenseSlot = OccupiedSlots[RandomSlot]; if (cPluginManager::Get()->CallHookDropSpense(*m_World, *this, SpenseSlot)) { // Plugin disagrees with the move return; } // DropSpense the item, using the specialized behavior in the subclasses: DropSpenseFromSlot(a_Chunk, SpenseSlot); // Broadcast a smoke and click effects: NIBBLETYPE Meta = a_Chunk.GetMeta(GetRelPos()); int SmokeDir = 0; switch (Meta & E_META_DROPSPENSER_FACING_MASK) { case E_META_DROPSPENSER_FACING_YP: SmokeDir = static_cast(SmokeDirection::CENTRE); break; // YP & YM don't have associated smoke dirs, just do 4 (centre of block) case E_META_DROPSPENSER_FACING_YM: SmokeDir = static_cast(SmokeDirection::CENTRE); break; case E_META_DROPSPENSER_FACING_XM: SmokeDir = static_cast(SmokeDirection::EAST); break; case E_META_DROPSPENSER_FACING_XP: SmokeDir = static_cast(SmokeDirection::WEST); break; case E_META_DROPSPENSER_FACING_ZM: SmokeDir = static_cast(SmokeDirection::SOUTH); break; case E_META_DROPSPENSER_FACING_ZP: SmokeDir = static_cast(SmokeDirection::NORTH); break; } m_World->BroadcastSoundParticleEffect(EffectID::PARTICLE_SMOKE, GetPos(), SmokeDir); m_World->BroadcastSoundEffect("block.dispenser.dispense", m_Pos, 1.0f, 1.0f); } void cDropSpenserEntity::Activate(void) { m_ShouldDropSpense = true; } void cDropSpenserEntity::CopyFrom(const cBlockEntity & a_Src) { Super::CopyFrom(a_Src); auto & src = static_cast(a_Src); m_Contents.CopyFrom(src.m_Contents); m_ShouldDropSpense = src.m_ShouldDropSpense; } void cDropSpenserEntity::OnRemoveFromWorld() { const auto Window = GetWindow(); if (Window != nullptr) { // Tell window its owner is destroyed: Window->OwnerDestroyed(); } } bool cDropSpenserEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { UNUSED(a_Dt); if (!m_ShouldDropSpense) { return false; } m_ShouldDropSpense = false; DropSpense(a_Chunk); return true; } void cDropSpenserEntity::SendTo(cClientHandle & a_Client) { // Nothing needs to be sent UNUSED(a_Client); } bool cDropSpenserEntity::UsedBy(cPlayer * a_Player) { if (m_BlockType == E_BLOCK_DISPENSER) { a_Player->GetStatistics().Custom[CustomStatistic::InspectDispenser]++; } else // E_BLOCK_DROPPER { a_Player->GetStatistics().Custom[CustomStatistic::InspectDropper]++; } cWindow * Window = GetWindow(); if (Window == nullptr) { OpenWindow(new cDropSpenserWindow(this)); Window = GetWindow(); } if (Window != nullptr) { if (a_Player->GetWindow() != Window) { a_Player->OpenWindow(*Window); } } return true; } void cDropSpenserEntity::DropFromSlot(cChunk & a_Chunk, int a_SlotNum) { Vector3i dispCoord(m_Pos); auto Meta = a_Chunk.GetMeta(GetRelPos()); AddDropSpenserDir(dispCoord, Meta); cItems Pickups; Pickups.push_back(m_Contents.RemoveOneItem(a_SlotNum)); const int PickupSpeed = GetRandomProvider().RandInt(2, 6); // At least 2, at most 6 int PickupSpeedX = 0, PickupSpeedY = 0, PickupSpeedZ = 0; switch (Meta & E_META_DROPSPENSER_FACING_MASK) { case E_META_DROPSPENSER_FACING_YP: PickupSpeedY = PickupSpeed; break; case E_META_DROPSPENSER_FACING_YM: PickupSpeedY = -PickupSpeed; break; case E_META_DROPSPENSER_FACING_XM: PickupSpeedX = -PickupSpeed; break; case E_META_DROPSPENSER_FACING_XP: PickupSpeedX = PickupSpeed; break; case E_META_DROPSPENSER_FACING_ZM: PickupSpeedZ = -PickupSpeed; break; case E_META_DROPSPENSER_FACING_ZP: PickupSpeedZ = PickupSpeed; break; } double MicroX, MicroY, MicroZ; MicroX = dispCoord.x + 0.5; MicroY = dispCoord.y + 0.4; // Slightly less than half, to accomodate actual texture hole on DropSpenser MicroZ = dispCoord.z + 0.5; m_World->SpawnItemPickups(Pickups, MicroX, MicroY, MicroZ, PickupSpeedX, PickupSpeedY, PickupSpeedZ); } ================================================ FILE: src/BlockEntities/DropSpenserEntity.h ================================================ // DropSpenser.h // Declares the cDropSpenser class representing a common ancestor to the cDispenserEntity and cDropperEntity // The dropper and dispenser only needs to override the DropSpenseFromSlot() function to provide the specific item behavior #pragma once #include "BlockEntityWithItems.h" class cClientHandle; // tolua_begin class cDropSpenserEntity : public cBlockEntityWithItems { // tolua_end using Super = cBlockEntityWithItems; // tolua_begin public: enum { ContentsHeight = 3, ContentsWidth = 3, } ; // tolua_end cDropSpenserEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World); // cBlockEntity overrides: virtual void CopyFrom(const cBlockEntity & a_Src) override; virtual void OnRemoveFromWorld() override; virtual bool Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; virtual void SendTo(cClientHandle & a_Client) override; virtual bool UsedBy(cPlayer * a_Player) override; // tolua_begin /** Modifies the block coords to match the dropspenser direction given (where the dropspensed pickups should materialize) */ void AddDropSpenserDir(Vector3i & a_RelCoord, NIBBLETYPE a_Direction); /** Sets the dropspenser to dropspense an item in the next tick */ void Activate(void); // tolua_end protected: bool m_ShouldDropSpense; ///< If true, the dropspenser will dropspense an item in the next tick /** Does the actual work on dropspensing an item. Chooses the slot, calls DropSpenseFromSlot() and handles smoke / sound effects */ void DropSpense(cChunk & a_Chunk); /** Override this function to provide the specific behavior for item dropspensing (drop / shoot / pour / ...) */ virtual void DropSpenseFromSlot(cChunk & a_Chunk, int a_SlotNum) = 0; /** Helper function, drops one item from the specified slot (like a dropper) */ void DropFromSlot(cChunk & a_Chunk, int a_SlotNum); } ; // tolua_export ================================================ FILE: src/BlockEntities/DropperEntity.cpp ================================================ // DropperEntity.cpp // Implements the cRtopperEntity class representing a Dropper block entity #include "Globals.h" #include "DropperEntity.h" cDropperEntity::cDropperEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World): Super(a_BlockType, a_BlockMeta, a_Pos, a_World) { ASSERT(a_BlockType == E_BLOCK_DROPPER); } void cDropperEntity::DropSpenseFromSlot(cChunk & a_Chunk, int a_SlotNum) { DropFromSlot(a_Chunk, a_SlotNum); } ================================================ FILE: src/BlockEntities/DropperEntity.h ================================================ // DropperEntity.h // Declares the cDropperEntity class representing a dropper block entity #pragma once #include "DropSpenserEntity.h" // tolua_begin class cDropperEntity : public cDropSpenserEntity { // tolua_end using Super = cDropSpenserEntity; public: // tolua_export /** Constructor used for normal operation */ cDropperEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World); protected: // cDropSpenserEntity overrides: virtual void DropSpenseFromSlot(cChunk & a_Chunk, int a_SlotNum) override; } ; // tolua_export ================================================ FILE: src/BlockEntities/EnchantingTableEntity.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "EnchantingTableEntity.h" #include "../ClientHandle.h" cEnchantingTableEntity::cEnchantingTableEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World, AString a_CustomName) : Super(a_BlockType, a_BlockMeta, a_Pos, a_World), m_CustomName(std::move(a_CustomName)) { ASSERT(a_BlockType == E_BLOCK_ENCHANTMENT_TABLE); } cItems cEnchantingTableEntity::ConvertToPickups() const { cItem Item(E_BLOCK_ENCHANTMENT_TABLE); Item.m_CustomName = m_CustomName; return Item; } void cEnchantingTableEntity::CopyFrom(const cBlockEntity & a_Src) { Super::CopyFrom(a_Src); auto & Src = static_cast(a_Src); m_CustomName = Src.m_CustomName; } bool cEnchantingTableEntity::UsedBy(cPlayer * a_Player) { UNUSED(a_Player); return true; } void cEnchantingTableEntity::SendTo(cClientHandle & a_Client) { a_Client.SendUpdateBlockEntity(*this); } ================================================ FILE: src/BlockEntities/EnchantingTableEntity.h ================================================ #pragma once #include "BlockEntity.h" class cEnchantingTableEntity : public cBlockEntity { using Super = cBlockEntity; public: cEnchantingTableEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World, AString a_CustomName = ""); const AString & GetCustomName() const { return m_CustomName; } void SetCustomName(const AString & a_CustomName) { m_CustomName = a_CustomName; } private: // cBlockEntity overrides: virtual cItems ConvertToPickups() const override; virtual void CopyFrom(const cBlockEntity & a_Src) override; virtual bool UsedBy(cPlayer * a_Player) override; virtual void SendTo(cClientHandle & a_Client) override; AString m_CustomName; }; ================================================ FILE: src/BlockEntities/EndPortalEntity.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "EndPortalEntity.h" #include "../ClientHandle.h" cEndPortalEntity::cEndPortalEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World) : Super(a_BlockType, a_BlockMeta, a_Pos, a_World) { ASSERT(a_BlockType == E_BLOCK_END_PORTAL); } void cEndPortalEntity::CopyFrom(const cBlockEntity & a_Src) { Super::CopyFrom(a_Src); } bool cEndPortalEntity::UsedBy(cPlayer * a_Player) { UNUSED(a_Player); return true; } void cEndPortalEntity::SendTo(cClientHandle & a_Client) { a_Client.SendUpdateBlockEntity(*this); } ================================================ FILE: src/BlockEntities/EndPortalEntity.h ================================================ #pragma once #include "BlockEntity.h" class cEndPortalEntity : public cBlockEntity { using Super = cBlockEntity; public: cEndPortalEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World); private: // cBlockEntity overrides: virtual void CopyFrom(const cBlockEntity & a_Src) override; virtual bool UsedBy(cPlayer * a_Player) override; virtual void SendTo(cClientHandle & a_Client) override; }; ================================================ FILE: src/BlockEntities/EnderChestEntity.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "EnderChestEntity.h" #include "json/json.h" #include "../BlockInfo.h" #include "../Item.h" #include "../Entities/Player.h" #include "../UI/EnderChestWindow.h" #include "../ClientHandle.h" #include "../Mobs/Ocelot.h" cEnderChestEntity::cEnderChestEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World): Super(a_BlockType, a_BlockMeta, a_Pos, a_World), cBlockEntityWindowOwner(this) { ASSERT(a_BlockType == E_BLOCK_ENDER_CHEST); } void cEnderChestEntity::SendTo(cClientHandle & a_Client) { // Send a dummy "number of players with chest open" packet to make the chest visible: a_Client.SendBlockAction(m_Pos, 1, 0, m_BlockType); } void cEnderChestEntity::OnRemoveFromWorld() { const auto Window = GetWindow(); if (Window != nullptr) { Window->OwnerDestroyed(); } } bool cEnderChestEntity::UsedBy(cPlayer * a_Player) { if ( (GetPosY() < cChunkDef::Height - 1) && ( !cBlockInfo::IsTransparent(GetWorld()->GetBlock(GetPos().addedY(1))) || !cOcelot::IsCatSittingOnBlock(GetWorld(), Vector3d(GetPos())) ) ) { // Obstruction, don't open return false; } a_Player->GetStatistics().Custom[CustomStatistic::OpenEnderchest]++; // If the window is not created, open it anew: cWindow * Window = GetWindow(); if (Window == nullptr) { OpenNewWindow(); Window = GetWindow(); } // Open the window for the player: if (Window != nullptr) { if (a_Player->GetWindow() != Window) { a_Player->OpenWindow(*Window); } } return true; } void cEnderChestEntity::OpenNewWindow() { OpenWindow(new cEnderChestWindow(this)); } void cEnderChestEntity::LoadFromJson(const Json::Value & a_Value, cItemGrid & a_Grid) { int SlotIdx = 0; for (auto & Node : a_Value) { cItem Item; Item.FromJson(Node); a_Grid.SetSlot(SlotIdx, Item); SlotIdx++; } } void cEnderChestEntity::SaveToJson(Json::Value & a_Value, const cItemGrid & a_Grid) { for (int i = 0; i < a_Grid.GetNumSlots(); i++) { Json::Value Slot; a_Grid.GetSlot(i).GetJson(Slot); a_Value.append(Slot); } } ================================================ FILE: src/BlockEntities/EnderChestEntity.h ================================================ #pragma once #include "BlockEntity.h" #include "../UI/WindowOwner.h" // tolua_begin class cEnderChestEntity : public cBlockEntity, public cBlockEntityWindowOwner { // tolua_end using Super = cBlockEntity; public: // tolua_export cEnderChestEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World); // cBlockEntity overrides: virtual void OnRemoveFromWorld() override; virtual bool UsedBy(cPlayer * a_Player) override; virtual void SendTo(cClientHandle & a_Client) override; static void LoadFromJson(const Json::Value & a_Value, cItemGrid & a_Grid); static void SaveToJson(Json::Value & a_Value, const cItemGrid & a_Grid); /** Opens a new enderchest window for this enderchest */ void OpenNewWindow(void); } ; // tolua_export ================================================ FILE: src/BlockEntities/FlowerPotEntity.cpp ================================================ // FlowerPotEntity.cpp // Implements the cFlowerPotEntity class representing a single flower pot in the world #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "FlowerPotEntity.h" #include "../Entities/Player.h" #include "../ClientHandle.h" #include "../Item.h" cFlowerPotEntity::cFlowerPotEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World): Super(a_BlockType, a_BlockMeta, a_Pos, a_World) { ASSERT(a_BlockType == E_BLOCK_FLOWER_POT); } cItems cFlowerPotEntity::ConvertToPickups() const { return cItem(m_Item); } void cFlowerPotEntity::CopyFrom(const cBlockEntity & a_Src) { Super::CopyFrom(a_Src); auto & src = static_cast(a_Src); m_Item = src.m_Item; } bool cFlowerPotEntity::UsedBy(cPlayer * a_Player) { if (IsItemInPot()) { return false; } a_Player->GetStatistics().Custom[CustomStatistic::PotFlower]++; cItem SelectedItem = a_Player->GetInventory().GetEquippedItem(); if (IsFlower(SelectedItem.m_ItemType, SelectedItem.m_ItemDamage)) { m_Item = SelectedItem.CopyOne(); if (!a_Player->IsGameModeCreative()) { a_Player->GetInventory().RemoveOneEquippedItem(); } m_World->BroadcastBlockEntity(GetPos(), a_Player->GetClientHandle()); } return true; } void cFlowerPotEntity::SendTo(cClientHandle & a_Client) { a_Client.SendUpdateBlockEntity(*this); } bool cFlowerPotEntity::IsFlower(short m_ItemType, short m_ItemData) { switch (m_ItemType) { case E_BLOCK_DANDELION: case E_BLOCK_FLOWER: case E_BLOCK_CACTUS: case E_BLOCK_BROWN_MUSHROOM: case E_BLOCK_RED_MUSHROOM: case E_BLOCK_SAPLING: case E_BLOCK_DEAD_BUSH: { return true; } case E_BLOCK_TALL_GRASS: { return (m_ItemData == static_cast(2)); } default: { return false; } } } ================================================ FILE: src/BlockEntities/FlowerPotEntity.h ================================================ // FlowerPotEntity.h // Declares the cFlowerPotEntity class representing a single sign in the world #pragma once #include "BlockEntity.h" #include "../Item.h" // tolua_begin class cFlowerPotEntity : public cBlockEntity { // tolua_end using Super = cBlockEntity; public: // tolua_export /** Creates a new flowerpot entity at the specified block coords. a_World may be nullptr */ cFlowerPotEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World); // tolua_begin /** Is a flower in the pot? */ bool IsItemInPot(void) { return !m_Item.IsEmpty(); } /** Get the item in the flower pot */ cItem GetItem(void) const { return m_Item; } /** Set the item in the flower pot */ void SetItem(const cItem & a_Item) { m_Item = a_Item; } // tolua_end // cBlockEntity overrides: virtual cItems ConvertToPickups() const override; virtual void CopyFrom(const cBlockEntity & a_Src) override; virtual bool UsedBy(cPlayer * a_Player) override; virtual void SendTo(cClientHandle & a_Client) override; static bool IsFlower(short m_ItemType, short m_ItemData); private: cItem m_Item; } ; // tolua_export ================================================ FILE: src/BlockEntities/FurnaceEntity.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "FurnaceEntity.h" #include "../UI/FurnaceWindow.h" #include "../Entities/Player.h" #include "../Root.h" #include "../Chunk.h" enum { PROGRESSBAR_FUEL = 0, PROGRESSBAR_SMELTING = 2, PROGRESSBAR_SMELTING_CONFIRM = 3, } ; cFurnaceEntity::cFurnaceEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World): Super(a_BlockType, a_BlockMeta, a_Pos, ContentsWidth, ContentsHeight, a_World), m_CurrentRecipe(nullptr), m_IsCooking(a_BlockType == E_BLOCK_LIT_FURNACE), m_NeedCookTime(0), m_TimeCooked(0), m_FuelBurnTime(0), m_TimeBurned(0), m_RewardCounter(0), m_IsLoading(false) { m_Contents.AddListener(*this); } void cFurnaceEntity::CopyFrom(const cBlockEntity & a_Src) { Super::CopyFrom(a_Src); auto & src = static_cast(a_Src); m_Contents.CopyFrom(src.m_Contents); m_CurrentRecipe = src.m_CurrentRecipe; m_FuelBurnTime = src.m_FuelBurnTime; m_IsCooking = src.m_IsCooking; m_IsLoading = src.m_IsLoading; m_LastInput = src.m_LastInput; m_NeedCookTime = src.m_NeedCookTime; m_TimeBurned = src.m_TimeBurned; m_TimeCooked = src.m_TimeCooked; } void cFurnaceEntity::OnRemoveFromWorld() { const auto Window = GetWindow(); if (Window != nullptr) { // Tell window its owner is destroyed: Window->OwnerDestroyed(); } } void cFurnaceEntity::SendTo(cClientHandle & a_Client) { // Nothing needs to be sent UNUSED(a_Client); } bool cFurnaceEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { UNUSED(a_Dt); if (m_FuelBurnTime <= 0) { // If a furnace is out of fuel, the progress bar reverses at twice the speed of cooking. m_TimeCooked = std::max((m_TimeCooked - 2), 0); // Reset progressbars, block type, and bail out m_BlockType = E_BLOCK_FURNACE; a_Chunk.FastSetBlock(GetRelPos(), E_BLOCK_FURNACE, m_BlockMeta); UpdateProgressBars(); return false; } if (m_IsCooking) { m_TimeCooked++; if (m_TimeCooked >= m_NeedCookTime) { // Finished smelting one item FinishOne(); } } m_TimeBurned++; if (m_TimeBurned >= m_FuelBurnTime) { // The current fuel has been exhausted, use another one, if possible BurnNewFuel(); } UpdateProgressBars(); return true; } bool cFurnaceEntity::UsedBy(cPlayer * a_Player) { a_Player->GetStatistics().Custom[CustomStatistic::InteractWithFurnace]++; cWindow * Window = GetWindow(); if (Window == nullptr) { OpenWindow(new cFurnaceWindow(this)); Window = GetWindow(); } if (Window != nullptr) { if (a_Player->GetWindow() != Window) { a_Player->OpenWindow(*Window); } } UpdateProgressBars(true); return true; } bool cFurnaceEntity::ContinueCooking(void) { UpdateInput(); UpdateFuel(); return m_IsCooking; } int cFurnaceEntity::GetAndResetReward(void) { int Reward = FloorC(m_RewardCounter); float Remainder = m_RewardCounter - static_cast(Reward); // Remainder is used as the percent chance of getting an extra xp point if (GetRandomProvider().RandBool(Remainder)) { Reward++; } m_RewardCounter = 0.0; return Reward; } void cFurnaceEntity::BroadcastProgress(size_t a_ProgressbarID, short a_Value) { cWindow * Window = GetWindow(); if (Window != nullptr) { Window->SetProperty(a_ProgressbarID, a_Value); } } void cFurnaceEntity::FinishOne() { m_TimeCooked = 0; m_RewardCounter += m_CurrentRecipe->Reward; if (m_Contents.GetSlot(fsOutput).IsEmpty()) { m_Contents.SetSlot(fsOutput, *m_CurrentRecipe->Out); } else { m_Contents.ChangeSlotCount(fsOutput, m_CurrentRecipe->Out->m_ItemCount); } m_Contents.ChangeSlotCount(fsInput, -m_CurrentRecipe->In->m_ItemCount); } void cFurnaceEntity::BurnNewFuel(void) { cFurnaceRecipe * FR = cRoot::Get()->GetFurnaceRecipe(); int NewTime = FR->GetBurnTime(m_Contents.GetSlot(fsFuel)); if ((NewTime == 0) || !CanCookInputToOutput()) { // The item in the fuel slot is not suitable // or the input and output isn't available for cooking SetBurnTimes(0, 0); SetIsCooking(false); return; } // Burn one new fuel: SetBurnTimes(NewTime, 0); SetIsCooking(true); if (m_Contents.GetSlot(fsFuel).m_ItemType == E_ITEM_LAVA_BUCKET) { m_Contents.SetSlot(fsFuel, cItem(E_ITEM_BUCKET)); } else { m_Contents.ChangeSlotCount(fsFuel, -1); } } void cFurnaceEntity::OnSlotChanged(cItemGrid * a_ItemGrid, int a_SlotNum) { Super::OnSlotChanged(a_ItemGrid, a_SlotNum); if (m_IsLoading) { return; } ASSERT(a_ItemGrid == &m_Contents); switch (a_SlotNum) { case fsInput: UpdateInput(); break; case fsFuel: UpdateFuel(); break; case fsOutput: UpdateOutput(); break; default: ASSERT(!"Invalid furnace slot update!"); break; } } void cFurnaceEntity::UpdateInput(void) { if (!m_Contents.GetSlot(fsInput).IsEqual(m_LastInput)) { // The input is different from what we had before, reset the cooking time if (!m_IsLoading) { m_TimeCooked = 0; } } m_LastInput = m_Contents.GetSlot(fsInput); cFurnaceRecipe * FR = cRoot::Get()->GetFurnaceRecipe(); m_CurrentRecipe = FR->GetRecipeFrom(m_Contents.GetSlot(fsInput)); if (!CanCookInputToOutput()) { // This input cannot be cooked, reset cook counter immediately SetCookTimes(0, 0); SetIsCooking(false); } else { m_NeedCookTime = m_CurrentRecipe->CookTime; // Start burning new fuel if there's no flame now: if (GetFuelBurnTimeLeft() <= 0) { BurnNewFuel(); } // Already burning, set cooking to ensure that cooking is occuring else { SetIsCooking(true); } } } void cFurnaceEntity::UpdateFuel(void) { if (m_FuelBurnTime > m_TimeBurned) { // The current fuel is still burning, don't modify anything: return; } // The current fuel is spent, try to burn some more: BurnNewFuel(); } void cFurnaceEntity::UpdateOutput(void) { if (!CanCookInputToOutput()) { // Cannot cook anymore: SetCookTimes(0, 0); SetIsCooking(false); return; } // Can cook, start cooking if not already underway: m_NeedCookTime = m_CurrentRecipe->CookTime; // Check if fuel needs to start a burn if (GetFuelBurnTimeLeft() <= 0) { BurnNewFuel(); } // Already burning, set cooking to ensure that cooking is occuring else { SetIsCooking(true); } } bool cFurnaceEntity::CanCookInputToOutput(void) const { if (m_CurrentRecipe == nullptr) { // This input cannot be cooked return false; } const cItem & Slot = m_Contents.GetSlot(fsOutput); if (Slot.IsEmpty()) { // The output is empty, can cook return true; } if (!Slot.IsEqual(*m_CurrentRecipe->Out)) { // The output slot is blocked with something that cannot be stacked with the recipe's output return false; } if (Slot.IsFullStack()) { // Cannot add any more items to the output slot return false; } return true; } void cFurnaceEntity::UpdateProgressBars(bool a_ForceUpdate) { // In order to preserve bandwidth, an update is sent only every 10th tick: if (!a_ForceUpdate && ((m_World->GetWorldTickAge() % 10_tick) != 0_tick)) { return; } int CurFuel = (m_FuelBurnTime > 0) ? 200 - (200 * m_TimeBurned / m_FuelBurnTime) : 0; BroadcastProgress(PROGRESSBAR_FUEL, static_cast(CurFuel)); int CurCook = (m_NeedCookTime > 0) ? (200 * m_TimeCooked / m_NeedCookTime) : 0; BroadcastProgress(PROGRESSBAR_SMELTING_CONFIRM, 200); // Post 1.8, Mojang requires a random packet with an ID of three and value of 200. Wat. Wat. Wat. BroadcastProgress(PROGRESSBAR_SMELTING, static_cast(CurCook)); } void cFurnaceEntity::SetIsCooking(bool a_IsCooking) { if (a_IsCooking == m_IsCooking) { return; } m_IsCooking = a_IsCooking; // Only light the furnace as it is extinguished only when the fuel runs out, not when cooking stops - handled in this::Tick() if (m_IsCooking) { m_BlockType = E_BLOCK_LIT_FURNACE; m_World->FastSetBlock(m_Pos, E_BLOCK_LIT_FURNACE, m_BlockMeta); } } ================================================ FILE: src/BlockEntities/FurnaceEntity.h ================================================ #pragma once #include "BlockEntityWithItems.h" #include "../FurnaceRecipe.h" class cClientHandle; // tolua_begin class cFurnaceEntity : public cBlockEntityWithItems { // tolua_end using Super = cBlockEntityWithItems; // tolua_begin public: enum { fsInput = 0, // Input slot number fsFuel = 1, // Fuel slot number fsOutput = 2, // Output slot number ContentsWidth = 3, ContentsHeight = 1, }; // tolua_end /** Constructor used for normal operation */ cFurnaceEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World); // cBlockEntity overrides: virtual void CopyFrom(const cBlockEntity & a_Src) override; virtual void OnRemoveFromWorld() override; virtual void SendTo(cClientHandle & a_Client) override; virtual bool Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; virtual bool UsedBy(cPlayer * a_Player) override; /** Restarts cooking Used after the furnace is loaded from storage to set up the internal variables so that cooking continues, if it was active Returns true if cooking */ bool ContinueCooking(void); // tolua_begin /** Returns the item in the input slot */ const cItem & GetInputSlot(void) const { return GetSlot(fsInput); } /** Returns the item in the fuel slot */ const cItem & GetFuelSlot(void) const { return GetSlot(fsFuel); } /** Returns the item in the output slot */ const cItem & GetOutputSlot(void) const { return GetSlot(fsOutput); } /** Sets the item in the input slot */ void SetInputSlot(const cItem & a_Item) { SetSlot(fsInput, a_Item); } /** Sets the item in the fuel slot */ void SetFuelSlot(const cItem & a_Item) { SetSlot(fsFuel, a_Item); } /** Sets the item in the output slot */ void SetOutputSlot(const cItem & a_Item) { SetSlot(fsOutput, a_Item); } /** Returns the time that the current item has been cooking, in ticks */ int GetTimeCooked(void) const { return m_TimeCooked; } /** Returns the time until the current item finishes cooking, in ticks */ int GetCookTimeLeft(void) const { return m_NeedCookTime - m_TimeCooked; } /** Returns the time until the current fuel is depleted, in ticks */ int GetFuelBurnTimeLeft(void) const { return m_FuelBurnTime - m_TimeBurned; } /** Returns true if there's time left before the current fuel is depleted */ bool HasFuelTimeLeft(void) const { return (GetFuelBurnTimeLeft() > 0); } /** Calculates, resets, and returns the experience reward in this furnace */ int GetAndResetReward(void); // tolua_end void SetBurnTimes(int a_FuelBurnTime, int a_TimeBurned) { m_FuelBurnTime = a_FuelBurnTime; m_TimeBurned = a_TimeBurned; } void SetCookTimes(int a_NeedCookTime, int a_TimeCooked) { m_NeedCookTime = a_NeedCookTime; m_TimeCooked = a_TimeCooked; } void SetLoading(bool a_IsLoading) { m_IsLoading = a_IsLoading; } protected: /** The recipe for the current input slot */ const cFurnaceRecipe::cRecipe * m_CurrentRecipe; /** The item that is being smelted */ cItem m_LastInput; /** Set to true if the furnace is cooking an item */ bool m_IsCooking; /** Amount of ticks needed to fully cook current item */ int m_NeedCookTime; /** Amount of ticks that the current item has been cooking */ int m_TimeCooked; /** Amount of ticks that the current fuel can burn (in total); zero if no fuel burning */ int m_FuelBurnTime; /** Amount of ticks that the current fuel has been burning */ int m_TimeBurned; /** Running total of experience that can be picked up */ float m_RewardCounter; /** Is the block currently being loaded into the world? */ bool m_IsLoading; /** Sends the specified progressbar value to all clients of the window */ void BroadcastProgress(size_t a_ProgressbarID, short a_Value); /** One item finished cooking */ void FinishOne(); /** Starts burning a new fuel, if possible */ void BurnNewFuel(void); /** Updates the recipe, based on the current input */ void UpdateInput(void); /** Called when the fuel slot changes or when the fuel is spent, burns another piece of fuel if appropriate */ void UpdateFuel(void); /** Called when the output slot changes */ void UpdateOutput(void); /** Returns true if the input can be cooked into output and the item counts allow for another cooking operation */ bool CanCookInputToOutput(void) const; /** Broadcasts progressbar updates, if needed */ void UpdateProgressBars(bool a_ForceUpdate = false); /** Sets the m_IsCooking variable, updates the furnace block type based on the value */ void SetIsCooking(bool a_IsCooking); // cItemGrid::cListener overrides: virtual void OnSlotChanged(cItemGrid * a_ItemGrid, int a_SlotNum) override; } ; // tolua_export ================================================ FILE: src/BlockEntities/HopperEntity.cpp ================================================ // HopperEntity.cpp // Implements the cHopperEntity representing a hopper block entity #include "Globals.h" #include "HopperEntity.h" #include "../Chunk.h" #include "../Entities/Player.h" #include "../Entities/Pickup.h" #include "../Bindings/PluginManager.h" #include "../UI/HopperWindow.h" #include "ChestEntity.h" #include "FurnaceEntity.h" // How many ticks at minimum between two item transfers to or from the hopper. #define TICKS_PER_TRANSFER 8_tick cHopperEntity::cHopperEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World): Super(a_BlockType, a_BlockMeta, a_Pos, ContentsWidth, ContentsHeight, a_World), m_LastMoveItemsInTick(0), m_LastMoveItemsOutTick(0), m_Locked(false) { ASSERT(a_BlockType == E_BLOCK_HOPPER); } void cHopperEntity::SetLocked(bool a_Value) { m_Locked = a_Value; } std::pair cHopperEntity::GetOutputBlockPos(NIBBLETYPE a_BlockMeta) { auto pos = GetPos(); switch (a_BlockMeta) { case E_META_HOPPER_FACING_XM: return {true, pos.addedX(-1)}; case E_META_HOPPER_FACING_XP: return {true, pos.addedX( 1)}; case E_META_HOPPER_FACING_YM: return {true, pos.addedY(-1)}; case E_META_HOPPER_FACING_ZM: return {true, pos.addedZ(-1)}; case E_META_HOPPER_FACING_ZP: return {true, pos.addedZ( 1)}; default: { // Not attached return {false, pos}; } } } void cHopperEntity::CopyFrom(const cBlockEntity & a_Src) { Super::CopyFrom(a_Src); auto & src = static_cast(a_Src); m_LastMoveItemsInTick = src.m_LastMoveItemsInTick; m_LastMoveItemsOutTick = src.m_LastMoveItemsOutTick; } bool cHopperEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { UNUSED(a_Dt); bool isDirty = false; if (!m_Locked) { const auto CurrentTick = a_Chunk.GetWorld()->GetWorldAge(); isDirty = MoveItemsIn(a_Chunk, CurrentTick) || isDirty; isDirty = MovePickupsIn(a_Chunk) || isDirty; isDirty = MoveItemsOut(a_Chunk, CurrentTick) || isDirty; } return isDirty; } void cHopperEntity::SendTo(cClientHandle & a_Client) { // The hopper entity doesn't need anything sent to the client when it's created / gets in the viewdistance // All the actual handling is in the cWindow UI code that gets called when the hopper is right-clicked UNUSED(a_Client); } bool cHopperEntity::UsedBy(cPlayer * a_Player) { a_Player->GetStatistics().Custom[CustomStatistic::InspectHopper]++; // If the window is not created, open it anew: cWindow * Window = GetWindow(); if (Window == nullptr) { OpenNewWindow(); Window = GetWindow(); } // Open the window for the player: if (Window != nullptr) { if (a_Player->GetWindow() != Window) { a_Player->OpenWindow(*Window); } } return true; } void cHopperEntity::OpenNewWindow(void) { OpenWindow(new cHopperWindow(this)); } bool cHopperEntity::MoveItemsIn(cChunk & a_Chunk, const cTickTimeLong a_CurrentTick) { if (m_Pos.y >= cChunkDef::Height) { // This hopper is at the top of the world, no more blocks above return false; } if ((a_CurrentTick - m_LastMoveItemsInTick) < TICKS_PER_TRANSFER) { // Too early after the previous transfer return false; } // Try moving an item in: bool res = false; switch (a_Chunk.GetBlock(GetRelPos().addedY(1))) { case E_BLOCK_CHEST: case E_BLOCK_TRAPPED_CHEST: { // Chests have special handling because of double-chests res = MoveItemsFromChest(a_Chunk); break; } case E_BLOCK_FURNACE: case E_BLOCK_LIT_FURNACE: { // Furnaces have special handling because only the output and leftover fuel buckets shall be moved res = MoveItemsFromFurnace(a_Chunk); break; } case E_BLOCK_DISPENSER: case E_BLOCK_DROPPER: case E_BLOCK_HOPPER: { res = MoveItemsFromGrid(*static_cast(a_Chunk.GetBlockEntity(this->GetPos().addedY(1)))); break; } } // If the item has been moved, reset the last tick: if (res) { m_LastMoveItemsInTick = a_CurrentTick; } return res; } bool cHopperEntity::MovePickupsIn(cChunk & a_Chunk) { class cHopperPickupSearchCallback { public: cHopperPickupSearchCallback(Vector3i a_Pos, cItemGrid & a_Contents) : m_Pos(a_Pos), m_bFoundPickupsAbove(false), m_Contents(a_Contents) { } bool operator () (cEntity & a_Entity) { if (!a_Entity.IsPickup()) { return false; } Vector3f EntityPos = a_Entity.GetPosition(); Vector3f BlockPos(m_Pos.x + 0.5f, static_cast(m_Pos.y) + 1, m_Pos.z + 0.5f); // One block above hopper, and search from center outwards double Distance = (EntityPos - BlockPos).Length(); if (Distance < 0.5) { if (TrySuckPickupIn(static_cast(a_Entity))) { return false; } } return false; } bool TrySuckPickupIn(cPickup & a_Pickup) { cItem & Item = a_Pickup.GetItem(); for (int i = 0; i < ContentsWidth * ContentsHeight; i++) { if (m_Contents.IsSlotEmpty(i)) { m_bFoundPickupsAbove = true; m_Contents.SetSlot(i, Item); a_Pickup.Destroy(); // Kill pickup return true; } else if (m_Contents.GetSlot(i).IsEqual(Item) && !m_Contents.GetSlot(i).IsFullStack()) { m_bFoundPickupsAbove = true; auto PreviousCount = m_Contents.GetSlot(i).m_ItemCount; Item.m_ItemCount -= m_Contents.ChangeSlotCount(i, Item.m_ItemCount) - PreviousCount; // Set count to however many items were added if (Item.IsEmpty()) { a_Pickup.Destroy(); // Kill pickup if all items were added } return true; } } return false; } bool FoundPickupsAbove(void) const { return m_bFoundPickupsAbove; } protected: Vector3i m_Pos; bool m_bFoundPickupsAbove; cItemGrid & m_Contents; }; cHopperPickupSearchCallback HopperPickupSearchCallback(Vector3i(GetPosX(), GetPosY(), GetPosZ()), m_Contents); a_Chunk.ForEachEntity(HopperPickupSearchCallback); return HopperPickupSearchCallback.FoundPickupsAbove(); } bool cHopperEntity::MoveItemsOut(cChunk & a_Chunk, const cTickTimeLong a_CurrentTick) { if ((a_CurrentTick - m_LastMoveItemsOutTick) < TICKS_PER_TRANSFER) { // Too early after the previous transfer return false; } // Get the coords of the block where to output items: auto meta = a_Chunk.GetMeta(GetRelPos()); auto out = GetOutputBlockPos(meta); if (!out.first) { // Not attached to another container return false; } if (out.second.y < 0) { // Cannot output below the zero-th block level return false; } // Convert coords to relative: auto relCoord = cChunkDef::AbsoluteToRelative(out.second); auto destChunk = a_Chunk.GetRelNeighborChunkAdjustCoords(relCoord); if (destChunk == nullptr) { // The destination chunk has been unloaded, don't tick return false; } // Call proper moving function, based on the blocktype present at the coords: bool res = false; auto absCoord = destChunk->RelativeToAbsolute(relCoord); switch (destChunk->GetBlock(relCoord)) { case E_BLOCK_CHEST: case E_BLOCK_TRAPPED_CHEST: { // Chests have special handling because of double-chests res = MoveItemsToChest(*destChunk, absCoord); break; } case E_BLOCK_FURNACE: case E_BLOCK_LIT_FURNACE: { // Furnaces have special handling because of the direction-to-slot relation res = MoveItemsToFurnace(*destChunk, absCoord, meta); break; } case E_BLOCK_DISPENSER: case E_BLOCK_DROPPER: case E_BLOCK_HOPPER: { auto blockEntity = static_cast(destChunk->GetBlockEntity(absCoord)); if (blockEntity == nullptr) { FLOGWARNING("{0}: A block entity was not found where expected at {1}", __FUNCTION__, absCoord); return false; } res = MoveItemsToGrid(*blockEntity); break; } } // If the item has been moved, reset the last tick: if (res) { m_LastMoveItemsOutTick = a_CurrentTick; } return res; } bool cHopperEntity::MoveItemsFromChest(cChunk & a_Chunk) { const auto ConnectedBlockEntity = a_Chunk.GetBlockEntityRel(GetRelPos().addedY(1)); if (ConnectedBlockEntity == nullptr) { return false; } const auto ConnectedChest = static_cast(ConnectedBlockEntity); if (MoveItemsFromGrid(ConnectedChest->GetPrimaryChest())) { return true; } const auto SecondaryChest = ConnectedChest->GetSecondaryChest(); return (SecondaryChest != nullptr) && MoveItemsFromGrid(*SecondaryChest); } bool cHopperEntity::MoveItemsFromFurnace(cChunk & a_Chunk) { auto furnace = static_cast(a_Chunk.GetBlockEntity(m_Pos.addedY(1))); if (furnace == nullptr) { FLOGWARNING("{0}: A furnace entity was not found where expected, at {1}", __FUNCTION__, m_Pos.addedY(1)); return false; } // Try move from the output slot: if (MoveItemsFromSlot(*furnace, cFurnaceEntity::fsOutput)) { cItem NewOutput(furnace->GetOutputSlot()); furnace->SetOutputSlot(NewOutput.AddCount(-1)); return true; } // No output moved, check if we can move an empty bucket out of the fuel slot: if (furnace->GetFuelSlot().m_ItemType == E_ITEM_BUCKET) { if (MoveItemsFromSlot(*furnace, cFurnaceEntity::fsFuel)) { furnace->SetFuelSlot(cItem()); return true; } } // Nothing can be moved return false; } bool cHopperEntity::MoveItemsFromGrid(cBlockEntityWithItems & a_Entity) { auto & Grid = a_Entity.GetContents(); int NumSlots = Grid.GetNumSlots(); for (int i = 0; i < NumSlots; i++) { if (Grid.IsSlotEmpty(i)) { continue; } if (MoveItemsFromSlot(a_Entity, i)) { Grid.ChangeSlotCount(i, -1); return true; } } return false; } bool cHopperEntity::MoveItemsFromSlot(cBlockEntityWithItems & a_Entity, int a_SlotNum) { cItem One(a_Entity.GetSlot(a_SlotNum).CopyOne()); for (int i = 0; i < ContentsWidth * ContentsHeight; i++) { if (m_Contents.IsSlotEmpty(i)) { if (cPluginManager::Get()->CallHookHopperPullingItem(*m_World, *this, i, a_Entity, a_SlotNum)) { // Plugin disagrees with the move continue; } m_Contents.SetSlot(i, One); return true; } else if (m_Contents.GetSlot(i).IsEqual(One)) { if (cPluginManager::Get()->CallHookHopperPullingItem(*m_World, *this, i, a_Entity, a_SlotNum)) { // Plugin disagrees with the move continue; } auto PreviousCount = m_Contents.GetSlot(i).m_ItemCount; m_Contents.ChangeSlotCount(i, 1); if (PreviousCount + 1 == m_Contents.GetSlot(i).m_ItemCount) { // Successfully added a new item. (Failure condition consistutes: stack full) return true; } } } return false; } bool cHopperEntity::MoveItemsToChest(cChunk & a_Chunk, Vector3i a_Coords) { const auto ConnectedBlockEntity = a_Chunk.GetBlockEntity(a_Coords); if (ConnectedBlockEntity == nullptr) { return false; } const auto ConnectedChest = static_cast(ConnectedBlockEntity); if (MoveItemsToGrid(ConnectedChest->GetPrimaryChest())) { return true; } const auto SecondaryChest = ConnectedChest->GetSecondaryChest(); return (SecondaryChest != nullptr) && MoveItemsToGrid(*SecondaryChest); } bool cHopperEntity::MoveItemsToFurnace(cChunk & a_Chunk, Vector3i a_Coords, NIBBLETYPE a_HopperMeta) { auto furnace = static_cast(a_Chunk.GetBlockEntity(a_Coords)); if (a_HopperMeta == E_META_HOPPER_FACING_YM) { // Feed the input slot of the furnace return MoveItemsToSlot(*furnace, cFurnaceEntity::fsInput); } else { // Feed the fuel slot of the furnace return MoveItemsToSlot(*furnace, cFurnaceEntity::fsFuel); } } bool cHopperEntity::MoveItemsToGrid(cBlockEntityWithItems & a_Entity) { // Iterate through our slots, try to move from each one: int NumSlots = a_Entity.GetContents().GetNumSlots(); for (int i = 0; i < NumSlots; i++) { if (MoveItemsToSlot(a_Entity, i)) { return true; } } return false; } bool cHopperEntity::MoveItemsToSlot(cBlockEntityWithItems & a_Entity, int a_DstSlotNum) { cItemGrid & Grid = a_Entity.GetContents(); if (Grid.IsSlotEmpty(a_DstSlotNum)) { // The slot is empty, move the first non-empty slot from our contents: for (int i = 0; i < ContentsWidth * ContentsHeight; i++) { if (!m_Contents.IsSlotEmpty(i)) { if (cPluginManager::Get()->CallHookHopperPushingItem(*m_World, *this, i, a_Entity, a_DstSlotNum)) { // A plugin disagrees with the move continue; } Grid.SetSlot(a_DstSlotNum, m_Contents.GetSlot(i).CopyOne()); m_Contents.ChangeSlotCount(i, -1); return true; } } return false; } else { // The slot is taken, try to top it up: const cItem & DestSlot = Grid.GetSlot(a_DstSlotNum); if (DestSlot.IsFullStack()) { return false; } for (int i = 0; i < ContentsWidth * ContentsHeight; i++) { if (m_Contents.GetSlot(i).IsEqual(DestSlot)) { if (cPluginManager::Get()->CallHookHopperPushingItem(*m_World, *this, i, a_Entity, a_DstSlotNum)) { // A plugin disagrees with the move continue; } Grid.ChangeSlotCount(a_DstSlotNum, 1); m_Contents.ChangeSlotCount(i, -1); return true; } } return false; } } ================================================ FILE: src/BlockEntities/HopperEntity.h ================================================ // HopperEntity.h // Declares the cHopperEntity representing a hopper block entity #pragma once #include "BlockEntityWithItems.h" // tolua_begin class cHopperEntity : public cBlockEntityWithItems { // tolua_end using Super = cBlockEntityWithItems; // tolua_begin public: enum { ContentsHeight = 1, ContentsWidth = 5 } ; // tolua_end /** Constructor used for normal operation */ cHopperEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World); /** Returns the block coords of the block receiving the output items, based on the meta Returns if unattached. Exported in ManualBindings.cpp. */ std::pair GetOutputBlockPos(NIBBLETYPE a_BlockMeta); void SetLocked(bool a_Value); protected: cTickTimeLong m_LastMoveItemsInTick; cTickTimeLong m_LastMoveItemsOutTick; // cBlockEntity overrides: virtual void CopyFrom(const cBlockEntity & a_Src) override; virtual bool Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; virtual void SendTo(cClientHandle & a_Client) override; virtual bool UsedBy(cPlayer * a_Player) override; /** Opens a new chest window for this chest. Scans for neighbors to open a double chest window, if appropriate. */ void OpenNewWindow(void); /** Moves items from the container above it into this hopper. Returns true if the contents have changed. */ bool MoveItemsIn(cChunk & a_Chunk, cTickTimeLong a_CurrentTick); /** Moves pickups from above this hopper into it. Returns true if the contents have changed. */ bool MovePickupsIn(cChunk & a_Chunk); /** Moves items out from this hopper into the destination. Returns true if the contents have changed. */ bool MoveItemsOut(cChunk & a_Chunk, cTickTimeLong a_CurrentTick); /** Moves items from a chest (dblchest) above the hopper into this hopper. Returns true if contents have changed. */ bool MoveItemsFromChest(cChunk & a_Chunk); /** Moves items from a furnace above the hopper into this hopper. Returns true if contents have changed. */ bool MoveItemsFromFurnace(cChunk & a_Chunk); /** Moves items from the specified a_Entity's Contents into this hopper. Returns true if contents have changed. */ bool MoveItemsFromGrid(cBlockEntityWithItems & a_Entity); /** Moves one piece from the specified itemstack into this hopper. Returns true if contents have changed. Doesn't change the itemstack. */ bool MoveItemsFromSlot(cBlockEntityWithItems & a_Entity, int a_SrcSlotNum); /** Moves items to the chest at the specified absolute coords. Returns true if contents have changed */ bool MoveItemsToChest(cChunk & a_Chunk, Vector3i a_Coords); /** Moves items to the furnace at the specified absolute coords. Returns true if contents have changed */ bool MoveItemsToFurnace(cChunk & a_Chunk, Vector3i a_Coords, NIBBLETYPE a_HopperMeta); /** Moves items to the specified ItemGrid. Returns true if contents have changed */ bool MoveItemsToGrid(cBlockEntityWithItems & a_Entity); /** Moves one piece to the specified entity's contents' slot. Returns true if contents have changed. */ bool MoveItemsToSlot(cBlockEntityWithItems & a_Entity, int a_DstSlotNum); private: bool m_Locked; } ; // tolua_export ================================================ FILE: src/BlockEntities/JukeboxEntity.cpp ================================================ // JukeboxEntity.cpp // Implements the cJukeboxEntity class representing a single jukebox in the world #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "JukeboxEntity.h" #include "../World.h" #include "../EffectID.h" #include "json/value.h" #include "../Entities/Player.h" cJukeboxEntity::cJukeboxEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World): Super(a_BlockType, a_BlockMeta, a_Pos, a_World), m_Record(0) { ASSERT(a_BlockType == E_BLOCK_JUKEBOX); } void cJukeboxEntity::Destroy(void) { ASSERT(m_World != nullptr); m_World->BroadcastSoundParticleEffect(EffectID::SFX_RANDOM_PLAY_MUSIC_DISC, GetPos(), 0); } cItems cJukeboxEntity::ConvertToPickups() const { return IsPlayingRecord() ? cItem(static_cast(m_Record)) : cItems(); } void cJukeboxEntity::CopyFrom(const cBlockEntity & a_Src) { Super::CopyFrom(a_Src); auto & src = static_cast(a_Src); m_Record = src.m_Record; } bool cJukeboxEntity::UsedBy(cPlayer * a_Player) { if (IsPlayingRecord()) { EjectRecord(); return true; } const cItem & HeldItem = a_Player->GetEquippedItem(); if (PlayRecord(HeldItem.m_ItemType)) { a_Player->GetStatistics().Custom[CustomStatistic::PlayRecord]++; if (!a_Player->IsGameModeCreative()) { a_Player->GetInventory().RemoveOneEquippedItem(); } return true; } // No state change, continue with block placement: return false; } bool cJukeboxEntity::PlayRecord(int a_Record) { if (!IsRecordItem(a_Record)) { // This isn't a Record Item return false; } if (IsPlayingRecord()) { // A Record is already in the Jukebox. EjectRecord(); } m_Record = a_Record; m_World->BroadcastSoundParticleEffect(EffectID::SFX_RANDOM_PLAY_MUSIC_DISC, GetPos(), m_Record); m_World->SetBlockMeta(m_Pos, E_META_JUKEBOX_ON); return true; } bool cJukeboxEntity::EjectRecord(void) { if (!IsPlayingRecord()) { // There's no record here return false; } m_World->SpawnItemPickups(cItem(static_cast(m_Record)), Vector3d(0.5, 0.5, 0.5) + m_Pos, 10); m_World->SetBlockMeta(m_Pos, E_META_JUKEBOX_OFF); m_World->BroadcastSoundParticleEffect(EffectID::SFX_RANDOM_PLAY_MUSIC_DISC, GetPos(), 0); m_Record = 0; return true; } bool cJukeboxEntity::IsPlayingRecord(void) const { return m_Record != 0; } int cJukeboxEntity::GetRecord(void) { return m_Record; } void cJukeboxEntity::SetRecord(int a_Record) { m_Record = a_Record; } ================================================ FILE: src/BlockEntities/JukeboxEntity.h ================================================ #pragma once #include "BlockEntity.h" #include "../BlockType.h" // tolua_begin class cJukeboxEntity : public cBlockEntity { // tolua_end using Super = cBlockEntity; public: // tolua_export cJukeboxEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World); // tolua_begin int GetRecord(void); void SetRecord(int a_Record); /** Plays the specified Record. Return false if a_Record isn't a playable Record (E_ITEM_XXX_DISC). If there is a record already playing, ejects it first. */ bool PlayRecord(int a_Record); /** Ejects the currently held record as a pickup. Return false when no record had been inserted. */ bool EjectRecord(void); /** Is in the Jukebox a Record? */ bool IsPlayingRecord(void) const; static bool IsRecordItem(int a_Item) { return ((a_Item >= E_ITEM_FIRST_DISC) && (a_Item <= E_ITEM_LAST_DISC)); } // tolua_end // cBlockEntity overrides: virtual void Destroy(void) override; virtual cItems ConvertToPickups() const override; virtual void CopyFrom(const cBlockEntity & a_Src) override; virtual bool UsedBy(cPlayer * a_Player) override; virtual void SendTo(cClientHandle &) override {} private: int m_Record; } ; // tolua_end ================================================ FILE: src/BlockEntities/MobHeadEntity.cpp ================================================ // MobHeadEntity.cpp // Implements the cMobHeadEntity class representing a single skull / head in the world #include "Globals.h" #include "MobHeadEntity.h" #include "json/json.h" #include "../Entities/Player.h" #include "../ClientHandle.h" cMobHeadEntity::cMobHeadEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World): Super(a_BlockType, a_BlockMeta, a_Pos, a_World), m_Type(SKULL_TYPE_SKELETON), m_Rotation(SKULL_ROTATION_NORTH) { ASSERT(a_BlockType == E_BLOCK_HEAD); } void cMobHeadEntity::SetType(const eMobHeadType & a_Type) { if ((!m_OwnerName.empty()) && (a_Type != SKULL_TYPE_PLAYER)) { m_OwnerName = m_OwnerTexture = m_OwnerTextureSignature = ""; m_OwnerUUID = cUUID{}; } m_Type = a_Type; } void cMobHeadEntity::SetRotation(eMobHeadRotation a_Rotation) { m_Rotation = a_Rotation; } void cMobHeadEntity::SetOwner(const cPlayer & a_Owner) { if (m_Type != SKULL_TYPE_PLAYER) { return; } m_OwnerName = a_Owner.GetName(); m_OwnerUUID = a_Owner.GetUUID(); const Json::Value & Properties = a_Owner.GetClientHandle()->GetProperties(); for (auto & Node : Properties) { if (Node.get("name", "").asString() == "textures") { m_OwnerTexture = Node.get("value", "").asString(); m_OwnerTextureSignature = Node.get("signature", "").asString(); break; } } } void cMobHeadEntity::SetOwner(const cUUID & a_OwnerUUID, const AString & a_OwnerName, const AString & a_OwnerTexture, const AString & a_OwnerTextureSignature) { if (m_Type != SKULL_TYPE_PLAYER) { return; } m_OwnerUUID = a_OwnerUUID; m_OwnerName = a_OwnerName; m_OwnerTexture = a_OwnerTexture; m_OwnerTextureSignature = a_OwnerTextureSignature; } cItems cMobHeadEntity::ConvertToPickups() const { return cItem(E_ITEM_HEAD, 1, static_cast(m_Type)); } void cMobHeadEntity::CopyFrom(const cBlockEntity & a_Src) { Super::CopyFrom(a_Src); auto & src = static_cast(a_Src); m_OwnerName = src.m_OwnerName; m_OwnerTexture = src.m_OwnerTexture; m_OwnerTextureSignature = src.m_OwnerTextureSignature; m_OwnerUUID = src.m_OwnerUUID; m_Rotation = src.m_Rotation; m_Type = src.m_Type; } void cMobHeadEntity::SendTo(cClientHandle & a_Client) { cWorld * World = a_Client.GetPlayer()->GetWorld(); a_Client.SendBlockChange(m_Pos, m_BlockType, World->GetBlockMeta(GetPos())); a_Client.SendUpdateBlockEntity(*this); } bool cMobHeadEntity::UsedBy(cPlayer * a_Player) { UNUSED(a_Player); return false; } ================================================ FILE: src/BlockEntities/MobHeadEntity.h ================================================ // MobHeadEntity.h // Declares the cMobHeadEntity class representing a single skull / head in the world #pragma once #include "BlockEntity.h" #include "../Defines.h" #include "../UUID.h" // tolua_begin class cMobHeadEntity : public cBlockEntity { // tolua_end using Super = cBlockEntity; public: // tolua_export /** Creates a new mob head entity at the specified block coords. a_World may be nullptr */ cMobHeadEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World); // tolua_begin /** Set the type of the mob head */ void SetType(const eMobHeadType & a_SkullType); /** Set the rotation of the mob head */ void SetRotation(eMobHeadRotation a_Rotation); /** Set the player for mob heads with player type */ void SetOwner(const cPlayer & a_Owner); /** Returns the type of the mob head */ eMobHeadType GetType(void) const { return m_Type; } /** Returns the rotation of the mob head */ eMobHeadRotation GetRotation(void) const { return m_Rotation; } /** Returns the player name of the mob head */ AString GetOwnerName(void) const { return m_OwnerName; } /** Returns the texture of the mob head */ AString GetOwnerTexture(void) const { return m_OwnerTexture; } /** Returns the texture signature of the mob head */ AString GetOwnerTextureSignature(void) const { return m_OwnerTextureSignature; } // tolua_end /** Sets the player components for the mob heads with player type. */ void SetOwner( const cUUID & a_OwnerUUID, const AString & a_OwnerName, const AString & a_OwnerTexture, const AString & a_OwnerTextureSignature ); // Exported in ManualBindings.cpp /** Returns the player UUID of the mob head */ cUUID GetOwnerUUID(void) const { return m_OwnerUUID; } // Exported in ManualBindings.cpp private: eMobHeadType m_Type; eMobHeadRotation m_Rotation; AString m_OwnerName; cUUID m_OwnerUUID; AString m_OwnerTexture; AString m_OwnerTextureSignature; // cBlockEntity overrides: virtual cItems ConvertToPickups() const override; virtual void CopyFrom(const cBlockEntity & a_Src) override; virtual void SendTo(cClientHandle & a_Client) override; virtual bool UsedBy(cPlayer * a_Player) override; } ; // tolua_export ================================================ FILE: src/BlockEntities/MobSpawnerEntity.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "MobSpawnerEntity.h" #include "../World.h" #include "../FastRandom.h" #include "../MobSpawner.h" #include "../ClientHandle.h" #include "../Items/ItemSpawnEgg.h" cMobSpawnerEntity::cMobSpawnerEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World): Super(a_BlockType, a_BlockMeta, a_Pos, a_World), m_Entity(mtPig), m_SpawnDelay(100), m_IsActive(false) { ASSERT(a_BlockType == E_BLOCK_MOB_SPAWNER); } void cMobSpawnerEntity::CopyFrom(const cBlockEntity & a_Src) { Super::CopyFrom(a_Src); auto & src = static_cast(a_Src); m_Entity = src.m_Entity; m_IsActive = src.m_IsActive; m_SpawnDelay = src.m_SpawnDelay; m_SpawnCount = src.m_SpawnCount; m_SpawnRange = src.m_SpawnRange; m_MinSpawnDelay = src.m_MinSpawnDelay; m_MaxSpawnDelay = src.m_MaxSpawnDelay; m_MaxNearbyEntities = src.m_MaxNearbyEntities; m_RequiredPlayerRange = src.m_RequiredPlayerRange; } void cMobSpawnerEntity::SendTo(cClientHandle & a_Client) { a_Client.SendUpdateBlockEntity(*this); } bool cMobSpawnerEntity::UsedBy(cPlayer * a_Player) { if (a_Player->GetEquippedItem().m_ItemType == E_ITEM_SPAWN_EGG) { eMonsterType MonsterType = cItemSpawnEggHandler::ItemDamageToMonsterType(a_Player->GetEquippedItem().m_ItemDamage); if (MonsterType == eMonsterType::mtInvalidType) { return false; } m_Entity = MonsterType; ResetTimer(); if (!a_Player->IsGameModeCreative()) { a_Player->GetInventory().RemoveOneEquippedItem(); } m_World->BroadcastBlockEntity(GetPos()); FLOGD("Changed monster spawner at {0} to type {1}.", GetPos(), cMonster::MobTypeToString(MonsterType)); return true; } return false; } void cMobSpawnerEntity::UpdateActiveState(void) { m_IsActive = (GetNearbyPlayersNum() > 0); } bool cMobSpawnerEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { using namespace std::chrono_literals; // Update the active flag every 5 seconds: if ((m_World->GetWorldTickAge() % 5s) == 0s) { UpdateActiveState(); } if (!m_IsActive) { return false; } if (m_SpawnDelay <= 0) { SpawnEntity(); m_World->BroadcastBlockEntity(GetPos()); return true; } else { m_SpawnDelay--; } return false; } void cMobSpawnerEntity::ResetTimer(void) { m_SpawnDelay = GetRandomProvider().RandInt(m_MinSpawnDelay, m_MaxSpawnDelay); } void cMobSpawnerEntity::SpawnEntity(void) { auto NearbyEntities = GetNearbyMonsterNum(m_Entity); if (NearbyEntities >= m_MaxNearbyEntities) { ResetTimer(); return; } bool EntitiesSpawned = m_World->DoWithChunk(GetChunkX(), GetChunkZ(), [this, NearbyEntities](cChunk & a_Chunk) { auto & Random = GetRandomProvider(); auto EntitySpawnTally = NearbyEntities; bool HaveSpawnedEntity = false; for (short I = 0; I < m_SpawnCount; I++) { if (EntitySpawnTally >= m_MaxNearbyEntities) { break; } auto SpawnRelPos(GetRelPos()); SpawnRelPos += Vector3i( static_cast((Random.RandReal() - Random.RandReal()) * static_cast(m_SpawnRange)), Random.RandInt(-1, 1), static_cast((Random.RandReal() - Random.RandReal()) * static_cast(m_SpawnRange)) ); auto Chunk = a_Chunk.GetRelNeighborChunkAdjustCoords(SpawnRelPos); if ((Chunk == nullptr) || !Chunk->IsValid()) { continue; } EMCSBiome Biome = Chunk->GetBiomeAt(SpawnRelPos.x, SpawnRelPos.z); if (cMobSpawner::CanSpawnHere(Chunk, SpawnRelPos, m_Entity, Biome, true)) { auto AbsPos = Chunk->RelativeToAbsolute(SpawnRelPos); auto Monster = cMonster::NewMonsterFromType(m_Entity); if (Monster == nullptr) { continue; } Monster->SetPosition(AbsPos); Monster->SetYaw(Random.RandReal(360.0f)); if (Chunk->GetWorld()->SpawnMobFinalize(std::move(Monster)) != cEntity::INVALID_ID) { HaveSpawnedEntity = true; m_World->BroadcastSoundParticleEffect(EffectID::PARTICLE_MOBSPAWN, AbsPos, 0); EntitySpawnTally++; } } } return HaveSpawnedEntity; } ); if (EntitiesSpawned) { ResetTimer(); } } int cMobSpawnerEntity::GetNearbyPlayersNum(void) { int NumPlayers = 0; auto Callback = [this, &NumPlayers](cEntity & a_Entity) { if (!a_Entity.IsPlayer()) { return false; } if ((m_Pos - a_Entity.GetPosition()).Length() <= m_RequiredPlayerRange) { NumPlayers++; } return false; }; const cBoundingBox PlayerBoundingBox(Vector3d(m_Pos.x, m_Pos.y - m_RequiredPlayerRange, m_Pos.z), m_RequiredPlayerRange, m_RequiredPlayerRange * 2); m_World->ForEachEntityInBox(PlayerBoundingBox, Callback); return NumPlayers; } int cMobSpawnerEntity::GetNearbyMonsterNum(eMonsterType a_EntityType) { int NumEntities = 0; auto Callback = [this, &NumEntities](cEntity & a_Entity) { if (!a_Entity.IsMob()) { return false; } auto & Mob = static_cast(a_Entity); if (Mob.GetMobType() == m_Entity) { NumEntities++; } return false; }; const cBoundingBox EntityBoundingBox(Vector3d(m_Pos.x, m_Pos.y - 4, m_Pos.z), m_SpawnRange, 8); m_World->ForEachEntityInBox(EntityBoundingBox, Callback); return NumEntities; } ================================================ FILE: src/BlockEntities/MobSpawnerEntity.h ================================================ // MobSpawnerEntity.h // Declares the cMobSpawnerEntity class representing a single mob spawner in the world #pragma once #include "BlockEntity.h" #include "../Entities/Player.h" // tolua_begin class cMobSpawnerEntity : public cBlockEntity { // tolua_end using Super = cBlockEntity; public: // tolua_export cMobSpawnerEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World); // cBlockEntity overrides: virtual void CopyFrom(const cBlockEntity & a_Src) override; virtual void SendTo(cClientHandle & a_Client) override; virtual bool UsedBy(cPlayer * a_Player) override; virtual bool Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; // tolua_begin /** Update the active flag from the mob spawner. This function will called every 5 seconds from the Tick() function. */ void UpdateActiveState(void); /** Sets the spawn delay to a new random value. */ void ResetTimer(void); /** Spawns the entity. This function automatically change the spawn delay! */ void SpawnEntity(void); // Getters int GetNearbyMonsterNum(eMonsterType a_EntityType); int GetNearbyPlayersNum(void); eMonsterType GetEntity(void) const { return m_Entity; } short GetSpawnCount(void) const { return m_SpawnCount; } short GetSpawnRange(void) const { return m_SpawnRange; } short GetSpawnDelay(void) const { return m_SpawnDelay; } short GetMinSpawnDelay(void) const { return m_MinSpawnDelay; } short GetMaxSpawnDelay(void) const { return m_MaxSpawnDelay; } short GetMaxNearbyEntities(void) const { return m_MaxNearbyEntities; } short GetRequiredPlayerRange(void) const { return m_RequiredPlayerRange; } // Setters void SetEntity(eMonsterType a_EntityType) { m_Entity = a_EntityType; } void SetSpawnDelay(short a_Delay) { m_SpawnDelay = a_Delay; } void SetSpawnCount(short a_SpawnCount) { m_SpawnCount = a_SpawnCount; } void SetSpawnRange(short a_SpawnRange) { m_SpawnRange = a_SpawnRange; } void SetMinSpawnDelay(short a_Min) { m_MinSpawnDelay = a_Min; } void SetMaxSpawnDelay(short a_Max) { m_MaxSpawnDelay = a_Max; } void SetMaxNearbyEntities(short a_MaxNearbyEntities) { m_MaxNearbyEntities = a_MaxNearbyEntities; } void SetRequiredPlayerRange(short a_RequiredPlayerRange) { m_RequiredPlayerRange = a_RequiredPlayerRange; } // tolua_end private: /** The entity to spawn. */ eMonsterType m_Entity; /** Time in ticks until the next entity spawns */ short m_SpawnDelay; bool m_IsActive; /** Number of entities the spawner tries to spawn each activation. */ short m_SpawnCount = 4; /** Diameter of the square the new monsters are spawned in */ short m_SpawnRange = 8; short m_MinSpawnDelay = 200; short m_MaxSpawnDelay = 800; /** Maximum amount of the same entity type in proximity. */ short m_MaxNearbyEntities = 6; /** Maximum distance to player for activation */ short m_RequiredPlayerRange = 16; } ; // tolua_end ================================================ FILE: src/BlockEntities/NoteEntity.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "NoteEntity.h" #include "../World.h" #include "json/value.h" #include "../Entities/Player.h" cNoteEntity::cNoteEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World): Super(a_BlockType, a_BlockMeta, a_Pos, a_World), m_Note(0) { ASSERT(a_BlockType == E_BLOCK_NOTE_BLOCK); } void cNoteEntity::CopyFrom(const cBlockEntity & a_Src) { Super::CopyFrom(a_Src); auto & src = static_cast(a_Src); m_Note = src.m_Note; } bool cNoteEntity::UsedBy(cPlayer * a_Player) { a_Player->GetStatistics().Custom[CustomStatistic::TuneNoteblock]++; IncrementNote(); MakeSound(); return true; } void cNoteEntity::MakeSound(void) { char Instrument; AString SampleName; switch (m_World->GetBlock(m_Pos.addedY(-1))) { case E_BLOCK_ACACIA_DOOR: case E_BLOCK_ACACIA_FENCE: case E_BLOCK_ACACIA_FENCE_GATE: case E_BLOCK_ACACIA_WOOD_STAIRS: case E_BLOCK_BIRCH_DOOR: case E_BLOCK_BIRCH_FENCE: case E_BLOCK_BIRCH_FENCE_GATE: case E_BLOCK_BIRCH_WOOD_STAIRS: case E_BLOCK_BOOKCASE: case E_BLOCK_CHEST: case E_BLOCK_CRAFTING_TABLE: case E_BLOCK_DARK_OAK_DOOR: case E_BLOCK_DARK_OAK_FENCE: case E_BLOCK_DARK_OAK_FENCE_GATE: case E_BLOCK_DARK_OAK_WOOD_STAIRS: case E_BLOCK_DAYLIGHT_SENSOR: case E_BLOCK_DOUBLE_WOODEN_SLAB: case E_BLOCK_FENCE: case E_BLOCK_HUGE_BROWN_MUSHROOM: case E_BLOCK_HUGE_RED_MUSHROOM: case E_BLOCK_INVERTED_DAYLIGHT_SENSOR: case E_BLOCK_JUKEBOX: case E_BLOCK_JUNGLE_DOOR: case E_BLOCK_JUNGLE_FENCE: case E_BLOCK_JUNGLE_FENCE_GATE: case E_BLOCK_JUNGLE_WOOD_STAIRS: case E_BLOCK_LOG: case E_BLOCK_NEW_LOG: case E_BLOCK_NOTE_BLOCK: case E_BLOCK_OAK_DOOR: case E_BLOCK_OAK_FENCE_GATE: case E_BLOCK_OAK_WOOD_STAIRS: case E_BLOCK_PLANKS: case E_BLOCK_SIGN_POST: case E_BLOCK_SPRUCE_DOOR: case E_BLOCK_SPRUCE_FENCE: case E_BLOCK_SPRUCE_FENCE_GATE: case E_BLOCK_SPRUCE_WOOD_STAIRS: case E_BLOCK_STANDING_BANNER: case E_BLOCK_TRAPDOOR: case E_BLOCK_TRAPPED_CHEST: case E_BLOCK_WALL_BANNER: case E_BLOCK_WALLSIGN: case E_BLOCK_WOODEN_PRESSURE_PLATE: case E_BLOCK_WOODEN_SLAB: { Instrument = E_INST_DOUBLE_BASS; SampleName = "block.note.bass"; break; } case E_BLOCK_GRAVEL: case E_BLOCK_SAND: case E_BLOCK_SOULSAND: { Instrument = E_INST_SNARE_DRUM; SampleName = "block.note.snare"; break; } case E_BLOCK_BEACON: case E_BLOCK_GLASS: case E_BLOCK_GLASS_PANE: case E_BLOCK_GLOWSTONE: case E_BLOCK_SEA_LANTERN: case E_BLOCK_STAINED_GLASS: case E_BLOCK_STAINED_GLASS_PANE: { Instrument = E_INST_CLICKS; SampleName = "block.note.hat"; break; } case E_BLOCK_BEDROCK: case E_BLOCK_BLACK_SHULKER_BOX: case E_BLOCK_BLOCK_OF_COAL: case E_BLOCK_BLUE_SHULKER_BOX: case E_BLOCK_BRICK: case E_BLOCK_BRICK_STAIRS: case E_BLOCK_BROWN_SHULKER_BOX: case E_BLOCK_COAL_ORE: case E_BLOCK_COBBLESTONE: case E_BLOCK_COBBLESTONE_STAIRS: case E_BLOCK_COBBLESTONE_WALL: case E_BLOCK_CYAN_SHULKER_BOX: case E_BLOCK_DIAMOND_ORE: case E_BLOCK_DISPENSER: case E_BLOCK_DOUBLE_RED_SANDSTONE_SLAB: case E_BLOCK_DOUBLE_STONE_SLAB: case E_BLOCK_DROPPER: case E_BLOCK_EMERALD_ORE: case E_BLOCK_ENCHANTMENT_TABLE: case E_BLOCK_END_BRICKS: case E_BLOCK_END_PORTAL_FRAME: case E_BLOCK_END_STONE: case E_BLOCK_ENDER_CHEST: case E_BLOCK_FURNACE: case E_BLOCK_GOLD_ORE: case E_BLOCK_GRAY_SHULKER_BOX: case E_BLOCK_GREEN_SHULKER_BOX: case E_BLOCK_IRON_ORE: case E_BLOCK_LAPIS_ORE: case E_BLOCK_LIGHT_BLUE_SHULKER_BOX: case E_BLOCK_LIGHT_GRAY_SHULKER_BOX: case E_BLOCK_LIME_SHULKER_BOX: case E_BLOCK_LIT_FURNACE: case E_BLOCK_MAGENTA_SHULKER_BOX: case E_BLOCK_MAGMA: case E_BLOCK_MOB_SPAWNER: case E_BLOCK_MOSSY_COBBLESTONE: case E_BLOCK_NETHER_BRICK: case E_BLOCK_NETHER_BRICK_FENCE: case E_BLOCK_NETHER_BRICK_STAIRS: case E_BLOCK_NETHER_QUARTZ_ORE: case E_BLOCK_NETHERRACK: case E_BLOCK_OBSERVER: case E_BLOCK_OBSIDIAN: case E_BLOCK_ORANGE_SHULKER_BOX: case E_BLOCK_PINK_SHULKER_BOX: case E_BLOCK_PRISMARINE_BLOCK: case E_BLOCK_PURPLE_SHULKER_BOX: case E_BLOCK_PURPUR_BLOCK: case E_BLOCK_PURPUR_DOUBLE_SLAB: case E_BLOCK_PURPUR_PILLAR: case E_BLOCK_PURPUR_SLAB: case E_BLOCK_PURPUR_STAIRS: case E_BLOCK_QUARTZ_BLOCK: case E_BLOCK_QUARTZ_STAIRS: case E_BLOCK_RED_NETHER_BRICK: case E_BLOCK_RED_SANDSTONE: case E_BLOCK_RED_SANDSTONE_SLAB: case E_BLOCK_RED_SANDSTONE_STAIRS: case E_BLOCK_RED_SHULKER_BOX: case E_BLOCK_REDSTONE_ORE: case E_BLOCK_REDSTONE_ORE_GLOWING: case E_BLOCK_SANDSTONE: case E_BLOCK_SANDSTONE_STAIRS: case E_BLOCK_STONE: case E_BLOCK_STONE_BRICK_STAIRS: case E_BLOCK_STONE_BRICKS: case E_BLOCK_STONE_PRESSURE_PLATE: case E_BLOCK_STONE_SLAB: case E_BLOCK_WHITE_SHULKER_BOX: case E_BLOCK_YELLOW_SHULKER_BOX: { Instrument = E_INST_BASS_DRUM; SampleName = "block.note.basedrum"; break; } case E_BLOCK_CLAY: { Instrument = E_INST_FLUTE; SampleName = "block.note.flute"; break; } case E_BLOCK_GOLD_BLOCK: { Instrument = E_INST_BELL; SampleName = "block.note.bell"; break; } case E_BLOCK_WOOL: { Instrument = E_INST_GUITAR; SampleName = "block.note.guitar"; break; } case E_BLOCK_PACKED_ICE: { Instrument = E_INST_CHIME; SampleName = "block.note.chime"; break; } case E_BLOCK_BONE_BLOCK: { Instrument = E_INST_XYLOPHONE; SampleName = "block.note.xylophone"; break; } default: { Instrument = E_INST_HARP_PIANO; SampleName = "block.note.harp"; break; } } m_World->BroadcastBlockAction(m_Pos, static_cast(Instrument), static_cast(m_Note), E_BLOCK_NOTE_BLOCK); m_World->BroadcastSoundEffect( SampleName, m_Pos, 3.0f, PitchFromNote(m_Note) ); } unsigned char cNoteEntity::GetNote(void) { return m_Note; } void cNoteEntity::SetNote(unsigned char a_Note) { m_Note = a_Note % 25; } void cNoteEntity::IncrementNote(void) { SetNote(m_Note + 1); } float cNoteEntity::PitchFromNote(unsigned char a_Pitch) { // This replaces the calculation of: // float calcPitch = static_cast(pow(2.0f, static_cast(m_Note - 12.0f) / 12.0f)); // So 2 ^ ((m_Note - 12) / 12) switch (a_Pitch) { case 0: return 0.5f; case 1: return 0.5297315471796477f; case 2: return 0.5612310241546865f; case 3: return 0.5946035575013605f; case 4: return 0.6299605249474366f; case 5: return 0.6674199270850172f; case 6: return 0.7071067811865476f; case 7: return 0.7491535384383408f; case 8: return 0.7937005259840998f; case 9: return 0.8408964152537145f; case 10: return 0.8908987181403393f; case 11: return 0.9438743126816935f; case 12: return 1.0f; case 13: return 1.0594630943592953f; case 14: return 1.122462048309373f; case 15: return 1.189207115002721f; case 16: return 1.2599210498948732f; case 17: return 1.3348398541700344f; case 18: return 1.4142135623730951f; case 19: return 1.4983070768766815f; case 20: return 1.5874010519681994f; case 21: return 1.681792830507429f; case 22: return 1.7817974362806785f; case 23: return 1.887748625363387f; case 24: return 2.0f; } UNREACHABLE("Converted unknown pitch value"); } ================================================ FILE: src/BlockEntities/NoteEntity.h ================================================ #pragma once #include "BlockEntity.h" enum ENUM_NOTE_INSTRUMENTS { E_INST_HARP_PIANO = 0, E_INST_DOUBLE_BASS = 1, E_INST_SNARE_DRUM = 2, E_INST_CLICKS = 3, E_INST_BASS_DRUM = 4, E_INST_FLUTE = 5, E_INST_BELL = 6, E_INST_GUITAR = 7, E_INST_CHIME = 8, E_INST_XYLOPHONE = 9 }; // tolua_begin class cNoteEntity : public cBlockEntity { // tolua_end using Super = cBlockEntity; public: // tolua_export /** Creates a new note entity. a_World may be nullptr */ cNoteEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World); // tolua_begin unsigned char GetNote(void); void SetNote(unsigned char a_Note); void IncrementNote(void); void MakeSound(void); // tolua_end // cBlockEntity overrides: virtual void CopyFrom(const cBlockEntity & a_Src) override; virtual bool UsedBy(cPlayer * a_Player) override; virtual void SendTo(cClientHandle &) override {} /** Returns the relative pitch (used in the protocol) from a note value between 0 and 24 (used in m_Note). */ static float PitchFromNote(unsigned char a_Note); private: unsigned char m_Note; } ; // tolua_export ================================================ FILE: src/BlockEntities/SignEntity.cpp ================================================ // SignEntity.cpp // Implements the cSignEntity class representing a single sign in the world #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "json/value.h" #include "SignEntity.h" #include "../ClientHandle.h" cSignEntity::cSignEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World): Super(a_BlockType, a_BlockMeta, a_Pos, a_World) { ASSERT((a_BlockType == E_BLOCK_WALLSIGN) || (a_BlockType == E_BLOCK_SIGN_POST)); ASSERT(cChunkDef::IsValidHeight(a_Pos)); } void cSignEntity::CopyFrom(const cBlockEntity & a_Src) { Super::CopyFrom(a_Src); auto & src = static_cast(a_Src); m_Line = src.m_Line; } bool cSignEntity::UsedBy(cPlayer * a_Player) { UNUSED(a_Player); return true; } void cSignEntity::SetLines(const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4) { m_Line[0] = a_Line1; m_Line[1] = a_Line2; m_Line[2] = a_Line3; m_Line[3] = a_Line4; } void cSignEntity::SetLine(size_t a_Index, const AString & a_Line) { if (a_Index >= m_Line.size()) { LOGWARNING("%s: setting a non-existent line %d (value \"%s\"", __FUNCTION__, a_Index, a_Line.c_str()); return; } m_Line[a_Index] = a_Line; } AString cSignEntity::GetLine(size_t a_Index) const { if (a_Index >= m_Line.size()) { LOGWARNING("%s: requesting a non-existent line %d", __FUNCTION__, a_Index); return ""; } return m_Line[a_Index]; } void cSignEntity::SendTo(cClientHandle & a_Client) { a_Client.SendUpdateSign(m_Pos, m_Line[0], m_Line[1], m_Line[2], m_Line[3]); } ================================================ FILE: src/BlockEntities/SignEntity.h ================================================ // SignEntity.h // Declares the cSignEntity class representing a single sign in the world #pragma once #include "BlockEntity.h" // tolua_begin class cSignEntity : public cBlockEntity { // tolua_end using Super = cBlockEntity; public: // tolua_export /** Creates a new empty sign entity at the specified block coords and block type (wall or standing). a_World may be nullptr */ cSignEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World); // tolua_begin /** Sets all the sign's lines */ void SetLines(const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4); /** Sets individual line (zero-based index) */ void SetLine(size_t a_Index, const AString & a_Line); /** Retrieves individual line (zero-based index) */ AString GetLine(size_t a_Index) const; // tolua_end // cBlockEntity overrides: virtual void CopyFrom(const cBlockEntity & a_Src) override; virtual bool UsedBy(cPlayer * a_Player) override; virtual void SendTo(cClientHandle & a_Client) override; private: std::array m_Line; } ; // tolua_export ================================================ FILE: src/BlockInServerPluginInterface.h ================================================ // BlockInServerPluginInterface.h // Defines the cBlockInServerPluginInterface class that implements the cBlockPluginInterface for blocks, using the plugin manager #pragma once #include "Blocks/BlockPluginInterface.h" #include "Bindings/PluginManager.h" class cWorld; class cBlockInServerPluginInterface : public cBlockPluginInterface { public: cBlockInServerPluginInterface(cWorld & a_World) : m_World(a_World) {} virtual bool CallHookBlockSpread(Vector3i a_BlockPos, eSpreadSource a_Source) override { return cPluginManager::Get()->CallHookBlockSpread(m_World, a_BlockPos, a_Source); } virtual bool CallHookPlayerBreakingBlock(cPlayer & a_Player, Vector3i a_BlockPos, eBlockFace a_BlockFace, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override { return cPluginManager::Get()->CallHookPlayerBreakingBlock(a_Player, a_BlockPos, a_BlockFace, a_BlockType, a_BlockMeta); } virtual bool CallHookPlayerBrokenBlock(cPlayer & a_Player, Vector3i a_BlockPos, eBlockFace a_BlockFace, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override { return cPluginManager::Get()->CallHookPlayerBrokenBlock(a_Player, a_BlockPos, a_BlockFace, a_BlockType, a_BlockMeta); } private: cWorld & m_World; }; ================================================ FILE: src/BlockInfo.cpp ================================================ #include "Globals.h" #include "BlockInfo.h" #include "BlockType.h" bool IsBlockWater(BLOCKTYPE a_BlockType) { return ((a_BlockType == E_BLOCK_WATER) || (a_BlockType == E_BLOCK_STATIONARY_WATER)); } bool IsBlockIce(BLOCKTYPE a_BlockType) { switch (a_BlockType) { case E_BLOCK_FROSTED_ICE: case E_BLOCK_ICE: case E_BLOCK_PACKED_ICE: { return true; } default: { return false; } } } bool IsBlockWaterOrIce(BLOCKTYPE a_BlockType) { return (IsBlockWater(a_BlockType) || IsBlockIce(a_BlockType)); } bool IsBlockLava(BLOCKTYPE a_BlockType) { return ((a_BlockType == E_BLOCK_LAVA) || (a_BlockType == E_BLOCK_STATIONARY_LAVA)); } bool IsBlockLiquid(BLOCKTYPE a_BlockType) { return IsBlockWater(a_BlockType) || IsBlockLava(a_BlockType); } bool IsBlockRail(BLOCKTYPE a_BlockType) { switch (a_BlockType) { case E_BLOCK_ACTIVATOR_RAIL: case E_BLOCK_DETECTOR_RAIL: case E_BLOCK_POWERED_RAIL: case E_BLOCK_RAIL: { return true; } default: return false; } } bool IsBlockTypeOfDirt(BLOCKTYPE a_BlockType) { switch (a_BlockType) { case E_BLOCK_DIRT: case E_BLOCK_FARMLAND: case E_BLOCK_GRASS: case E_BLOCK_GRASS_PATH: { return true; } } return false; } bool IsBlockFence(BLOCKTYPE a_BlockType) { switch (a_BlockType) { case E_BLOCK_ACACIA_FENCE: case E_BLOCK_ACACIA_FENCE_GATE: case E_BLOCK_BIRCH_FENCE: case E_BLOCK_BIRCH_FENCE_GATE: case E_BLOCK_COBBLESTONE_WALL: case E_BLOCK_DARK_OAK_FENCE: case E_BLOCK_DARK_OAK_FENCE_GATE: case E_BLOCK_FENCE: case E_BLOCK_JUNGLE_FENCE: case E_BLOCK_JUNGLE_FENCE_GATE: case E_BLOCK_NETHER_BRICK_FENCE: case E_BLOCK_OAK_FENCE_GATE: case E_BLOCK_SPRUCE_FENCE: case E_BLOCK_SPRUCE_FENCE_GATE: { return true; } default: { return false; } } } bool IsBlockShulkerBox(BLOCKTYPE a_BlockType) { return ((a_BlockType >= E_BLOCK_WHITE_SHULKER_BOX) && (a_BlockType <= E_BLOCK_BLACK_SHULKER_BOX)); } bool IsBlockMaterialWood(BLOCKTYPE a_BlockType) { switch (a_BlockType) { case E_BLOCK_ACACIA_DOOR: case E_BLOCK_ACACIA_FENCE: case E_BLOCK_ACACIA_FENCE_GATE: case E_BLOCK_ACACIA_WOOD_STAIRS: case E_BLOCK_BIRCH_DOOR: case E_BLOCK_BIRCH_FENCE: case E_BLOCK_BIRCH_FENCE_GATE: case E_BLOCK_BIRCH_WOOD_STAIRS: case E_BLOCK_BOOKCASE: case E_BLOCK_CHEST: case E_BLOCK_CRAFTING_TABLE: case E_BLOCK_DARK_OAK_DOOR: case E_BLOCK_DARK_OAK_FENCE: case E_BLOCK_DARK_OAK_FENCE_GATE: case E_BLOCK_DARK_OAK_WOOD_STAIRS: case E_BLOCK_DAYLIGHT_SENSOR: case E_BLOCK_DOUBLE_WOODEN_SLAB: case E_BLOCK_FENCE: case E_BLOCK_HUGE_BROWN_MUSHROOM: case E_BLOCK_HUGE_RED_MUSHROOM: case E_BLOCK_INVERTED_DAYLIGHT_SENSOR: case E_BLOCK_JUKEBOX: case E_BLOCK_JUNGLE_DOOR: case E_BLOCK_JUNGLE_FENCE: case E_BLOCK_JUNGLE_FENCE_GATE: case E_BLOCK_JUNGLE_WOOD_STAIRS: case E_BLOCK_LOG: case E_BLOCK_NEW_LOG: case E_BLOCK_NOTE_BLOCK: case E_BLOCK_OAK_DOOR: case E_BLOCK_OAK_FENCE_GATE: case E_BLOCK_OAK_WOOD_STAIRS: case E_BLOCK_PLANKS: case E_BLOCK_SIGN_POST: case E_BLOCK_SPRUCE_DOOR: case E_BLOCK_SPRUCE_FENCE: case E_BLOCK_SPRUCE_FENCE_GATE: case E_BLOCK_SPRUCE_WOOD_STAIRS: case E_BLOCK_STANDING_BANNER: case E_BLOCK_TRAPDOOR: case E_BLOCK_TRAPPED_CHEST: case E_BLOCK_WALLSIGN: case E_BLOCK_WALL_BANNER: case E_BLOCK_WOODEN_PRESSURE_PLATE: case E_BLOCK_WOODEN_SLAB: { return true; } default: { return false; } } } bool IsBlockMaterialPlants(BLOCKTYPE a_BlockType) { switch (a_BlockType) { case E_BLOCK_BEETROOTS: case E_BLOCK_BROWN_MUSHROOM: case E_BLOCK_CARROTS: case E_BLOCK_CHORUS_FLOWER: case E_BLOCK_CHORUS_PLANT: case E_BLOCK_COCOA_POD: case E_BLOCK_CROPS: case E_BLOCK_DANDELION: case E_BLOCK_FLOWER: case E_BLOCK_LILY_PAD: case E_BLOCK_MELON_STEM: case E_BLOCK_NETHER_WART: case E_BLOCK_POTATOES: case E_BLOCK_PUMPKIN_STEM: case E_BLOCK_RED_MUSHROOM: case E_BLOCK_REEDS: case E_BLOCK_SAPLING: { return true; } default: { return false; } } } bool IsBlockMaterialVine(BLOCKTYPE a_BlockType) { switch (a_BlockType) { case E_BLOCK_BIG_FLOWER: case E_BLOCK_DEAD_BUSH: case E_BLOCK_TALL_GRASS: case E_BLOCK_VINES: { return true; } default: { return false; } } } bool IsBlockMaterialIron(BLOCKTYPE a_BlockType) { switch (a_BlockType) { case E_BLOCK_BLOCK_OF_REDSTONE: case E_BLOCK_BREWING_STAND: case E_BLOCK_CAULDRON: case E_BLOCK_CHAIN_COMMAND_BLOCK: case E_BLOCK_COMMAND_BLOCK: case E_BLOCK_DIAMOND_BLOCK: case E_BLOCK_EMERALD_BLOCK: case E_BLOCK_GOLD_BLOCK: case E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE: case E_BLOCK_HOPPER: case E_BLOCK_IRON_BARS: case E_BLOCK_IRON_BLOCK: case E_BLOCK_IRON_DOOR: case E_BLOCK_IRON_TRAPDOOR: case E_BLOCK_LAPIS_BLOCK: case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE: case E_BLOCK_REPEATING_COMMAND_BLOCK: case E_BLOCK_STRUCTURE_BLOCK: { return true; } default: { return false; } } } bool IsBlockMaterialLeaves(BLOCKTYPE a_BlockType) { return (a_BlockType == E_BLOCK_LEAVES) || (a_BlockType == E_BLOCK_NEW_LEAVES); } bool IsBlockMaterialGourd(BLOCKTYPE a_BlockType) { switch (a_BlockType) { case E_BLOCK_JACK_O_LANTERN: case E_BLOCK_MELON: case E_BLOCK_PUMPKIN: { return true; } default: { return false; } } } bool IsBlockMaterialRock(BLOCKTYPE a_BlockType) { switch (a_BlockType) { case E_BLOCK_BEDROCK: case E_BLOCK_BLOCK_OF_COAL: case E_BLOCK_BONE_BLOCK: case E_BLOCK_BRICK: case E_BLOCK_BRICK_STAIRS: case E_BLOCK_COAL_ORE: case E_BLOCK_COBBLESTONE: case E_BLOCK_COBBLESTONE_STAIRS: case E_BLOCK_COBBLESTONE_WALL: case E_BLOCK_DIAMOND_ORE: case E_BLOCK_DISPENSER: case E_BLOCK_DOUBLE_RED_SANDSTONE_SLAB: case E_BLOCK_DOUBLE_STONE_SLAB: case E_BLOCK_DROPPER: case E_BLOCK_EMERALD_ORE: case E_BLOCK_ENCHANTMENT_TABLE: case E_BLOCK_ENDER_CHEST: case E_BLOCK_END_BRICKS: case E_BLOCK_END_PORTAL_FRAME: case E_BLOCK_END_STONE: case E_BLOCK_FURNACE: case E_BLOCK_GOLD_ORE: case E_BLOCK_HARDENED_CLAY: case E_BLOCK_IRON_ORE: case E_BLOCK_LAPIS_ORE: case E_BLOCK_LIT_FURNACE: case E_BLOCK_MAGMA: case E_BLOCK_MOB_SPAWNER: case E_BLOCK_MOSSY_COBBLESTONE: case E_BLOCK_NETHERRACK: case E_BLOCK_NETHER_BRICK: case E_BLOCK_NETHER_BRICK_FENCE: case E_BLOCK_NETHER_BRICK_STAIRS: case E_BLOCK_NETHER_QUARTZ_ORE: case E_BLOCK_OBSERVER: case E_BLOCK_OBSIDIAN: case E_BLOCK_PRISMARINE_BLOCK: case E_BLOCK_PURPUR_BLOCK: case E_BLOCK_PURPUR_DOUBLE_SLAB: case E_BLOCK_PURPUR_PILLAR: case E_BLOCK_PURPUR_SLAB: case E_BLOCK_PURPUR_STAIRS: case E_BLOCK_QUARTZ_BLOCK: case E_BLOCK_QUARTZ_STAIRS: case E_BLOCK_REDSTONE_ORE: case E_BLOCK_REDSTONE_ORE_GLOWING: case E_BLOCK_RED_NETHER_BRICK: case E_BLOCK_RED_SANDSTONE: case E_BLOCK_RED_SANDSTONE_SLAB: case E_BLOCK_RED_SANDSTONE_STAIRS: case E_BLOCK_SANDSTONE: case E_BLOCK_SANDSTONE_STAIRS: case E_BLOCK_STAINED_CLAY: case E_BLOCK_STONE: case E_BLOCK_STONE_BRICKS: case E_BLOCK_STONE_BRICK_STAIRS: case E_BLOCK_STONE_PRESSURE_PLATE: case E_BLOCK_STONE_SLAB: { return true; } default: { return false; } } } //////////////////////////////////////////////////////////////////////////////// // cBlockInfo: NIBBLETYPE cBlockInfo::GetLightValue(const BLOCKTYPE Block) { // Emissive blocks: switch (Block) { case E_BLOCK_ACTIVE_COMPARATOR: return 9; case E_BLOCK_BEACON: return 15; case E_BLOCK_BREWING_STAND: return 1; case E_BLOCK_BROWN_MUSHROOM: return 1; case E_BLOCK_BURNING_FURNACE: return 13; case E_BLOCK_DRAGON_EGG: return 1; case E_BLOCK_ENDER_CHEST: return 7; case E_BLOCK_END_PORTAL: return 15; case E_BLOCK_END_PORTAL_FRAME: return 1; case E_BLOCK_END_ROD: return 14; case E_BLOCK_FIRE: return 15; case E_BLOCK_GLOWSTONE: return 15; case E_BLOCK_JACK_O_LANTERN: return 15; case E_BLOCK_LAVA: return 15; case E_BLOCK_MAGMA: return 3; case E_BLOCK_NETHER_PORTAL: return 11; case E_BLOCK_REDSTONE_LAMP_ON: return 15; case E_BLOCK_REDSTONE_ORE_GLOWING: return 9; case E_BLOCK_REDSTONE_REPEATER_ON: return 9; case E_BLOCK_REDSTONE_TORCH_ON: return 7; case E_BLOCK_SEA_LANTERN: return 15; case E_BLOCK_STATIONARY_LAVA: return 15; case E_BLOCK_TORCH: return 14; default: return 0; } } NIBBLETYPE cBlockInfo::GetSpreadLightFalloff(const BLOCKTYPE Block) { switch (Block) { // Spread blocks: case E_BLOCK_ACACIA_DOOR: case E_BLOCK_ACACIA_FENCE: case E_BLOCK_ACACIA_FENCE_GATE: case E_BLOCK_ACTIVATOR_RAIL: case E_BLOCK_ACTIVE_COMPARATOR: case E_BLOCK_AIR: case E_BLOCK_ANVIL: case E_BLOCK_BARRIER: case E_BLOCK_BEACON: case E_BLOCK_BED: case E_BLOCK_BEETROOTS: case E_BLOCK_BIG_FLOWER: case E_BLOCK_BIRCH_DOOR: case E_BLOCK_BIRCH_FENCE: case E_BLOCK_BIRCH_FENCE_GATE: case E_BLOCK_BREWING_STAND: case E_BLOCK_BROWN_MUSHROOM: case E_BLOCK_CACTUS: case E_BLOCK_CAKE: case E_BLOCK_CARPET: case E_BLOCK_CARROTS: case E_BLOCK_CAULDRON: case E_BLOCK_CHEST: case E_BLOCK_CHORUS_FLOWER: case E_BLOCK_CHORUS_PLANT: case E_BLOCK_COBBLESTONE_WALL: case E_BLOCK_COBWEB: case E_BLOCK_COCOA_POD: case E_BLOCK_CROPS: case E_BLOCK_DANDELION: case E_BLOCK_DARK_OAK_DOOR: case E_BLOCK_DARK_OAK_FENCE: case E_BLOCK_DARK_OAK_FENCE_GATE: case E_BLOCK_DAYLIGHT_SENSOR: case E_BLOCK_DEAD_BUSH: case E_BLOCK_DETECTOR_RAIL: case E_BLOCK_DRAGON_EGG: case E_BLOCK_ENCHANTMENT_TABLE: case E_BLOCK_ENDER_CHEST: case E_BLOCK_END_PORTAL: case E_BLOCK_END_PORTAL_FRAME: case E_BLOCK_END_ROD: case E_BLOCK_FENCE: case E_BLOCK_FIRE: case E_BLOCK_FLOWER: case E_BLOCK_FLOWER_POT: case E_BLOCK_GLASS: case E_BLOCK_GLASS_PANE: case E_BLOCK_HEAD: case E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE: case E_BLOCK_HOPPER: case E_BLOCK_INACTIVE_COMPARATOR: case E_BLOCK_INVERTED_DAYLIGHT_SENSOR: case E_BLOCK_IRON_BARS: case E_BLOCK_IRON_DOOR: case E_BLOCK_IRON_TRAPDOOR: case E_BLOCK_JUNGLE_DOOR: case E_BLOCK_JUNGLE_FENCE: case E_BLOCK_JUNGLE_FENCE_GATE: case E_BLOCK_LADDER: case E_BLOCK_LEAVES: case E_BLOCK_LEVER: case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE: case E_BLOCK_LILY_PAD: case E_BLOCK_MELON_STEM: case E_BLOCK_MOB_SPAWNER: case E_BLOCK_NETHER_PORTAL: case E_BLOCK_NETHER_WART: case E_BLOCK_NEW_LEAVES: case E_BLOCK_OAK_DOOR: case E_BLOCK_OAK_FENCE_GATE: case E_BLOCK_PISTON: case E_BLOCK_PISTON_EXTENSION: case E_BLOCK_PISTON_MOVED_BLOCK: case E_BLOCK_POTATOES: case E_BLOCK_POWERED_RAIL: case E_BLOCK_PUMPKIN_STEM: case E_BLOCK_RAIL: case E_BLOCK_REDSTONE_REPEATER_OFF: case E_BLOCK_REDSTONE_REPEATER_ON: case E_BLOCK_REDSTONE_TORCH_OFF: case E_BLOCK_REDSTONE_TORCH_ON: case E_BLOCK_REDSTONE_WIRE: case E_BLOCK_RED_MUSHROOM: case E_BLOCK_SAPLING: case E_BLOCK_SIGN_POST: case E_BLOCK_SNOW: case E_BLOCK_SPRUCE_DOOR: case E_BLOCK_SPRUCE_FENCE: case E_BLOCK_SPRUCE_FENCE_GATE: case E_BLOCK_STAINED_GLASS: case E_BLOCK_STAINED_GLASS_PANE: case E_BLOCK_STANDING_BANNER: case E_BLOCK_STICKY_PISTON: case E_BLOCK_STONE_BUTTON: case E_BLOCK_STONE_PRESSURE_PLATE: case E_BLOCK_SUGARCANE: case E_BLOCK_TALL_GRASS: case E_BLOCK_TORCH: case E_BLOCK_TRAPDOOR: case E_BLOCK_TRAPPED_CHEST: case E_BLOCK_TRIPWIRE: case E_BLOCK_TRIPWIRE_HOOK: case E_BLOCK_VINES: case E_BLOCK_WALLSIGN: case E_BLOCK_WALL_BANNER: case E_BLOCK_WOODEN_BUTTON: case E_BLOCK_WOODEN_PRESSURE_PLATE: return 1; // Light in ice and water disappears faster: case E_BLOCK_ICE: case E_BLOCK_STATIONARY_WATER: case E_BLOCK_WATER: return 3; // Light does not pass through anything else (note: including tilled farmland, stairs, and slabs): default: return 15; } } bool cBlockInfo::CanBeTerraformed(const BLOCKTYPE Block) { // Blocks that can be terraformed: switch (Block) { case E_BLOCK_COAL_ORE: case E_BLOCK_COBBLESTONE: case E_BLOCK_DIAMOND_ORE: case E_BLOCK_DIRT: case E_BLOCK_GOLD_ORE: case E_BLOCK_GRASS: case E_BLOCK_GRAVEL: case E_BLOCK_HARDENED_CLAY: case E_BLOCK_IRON_ORE: case E_BLOCK_MYCELIUM: case E_BLOCK_NETHERRACK: case E_BLOCK_REDSTONE_ORE: case E_BLOCK_REDSTONE_ORE_GLOWING: case E_BLOCK_SAND: case E_BLOCK_SANDSTONE: case E_BLOCK_SOULSAND: case E_BLOCK_STAINED_CLAY: case E_BLOCK_STONE: return true; default: return false; } } bool cBlockInfo::FullyOccupiesVoxel(const BLOCKTYPE Block) { // Blocks that fully occupy their voxel - used as a guide for torch placeable blocks, amongst other things: switch (Block) { case E_BLOCK_BARRIER: case E_BLOCK_BEDROCK: case E_BLOCK_BLACK_GLAZED_TERRACOTTA: case E_BLOCK_BLOCK_OF_COAL: case E_BLOCK_BLOCK_OF_REDSTONE: case E_BLOCK_BLUE_GLAZED_TERRACOTTA: case E_BLOCK_BONE_BLOCK: case E_BLOCK_BOOKCASE: case E_BLOCK_BRICK: case E_BLOCK_BROWN_GLAZED_TERRACOTTA: case E_BLOCK_CHAIN_COMMAND_BLOCK: case E_BLOCK_CLAY: case E_BLOCK_COAL_ORE: case E_BLOCK_COBBLESTONE: case E_BLOCK_COMMAND_BLOCK: case E_BLOCK_CONCRETE: case E_BLOCK_CONCRETE_POWDER: case E_BLOCK_CRAFTING_TABLE: case E_BLOCK_CYAN_GLAZED_TERRACOTTA: case E_BLOCK_DIAMOND_BLOCK: case E_BLOCK_DIAMOND_ORE: case E_BLOCK_DIRT: case E_BLOCK_DISPENSER: case E_BLOCK_DOUBLE_RED_SANDSTONE_SLAB: case E_BLOCK_DOUBLE_STONE_SLAB: case E_BLOCK_DOUBLE_WOODEN_SLAB: case E_BLOCK_DROPPER: case E_BLOCK_EMERALD_BLOCK: case E_BLOCK_EMERALD_ORE: case E_BLOCK_END_BRICKS: case E_BLOCK_END_STONE: case E_BLOCK_FROSTED_ICE: case E_BLOCK_FURNACE: case E_BLOCK_GLASS: case E_BLOCK_GLOWSTONE: case E_BLOCK_GOLD_BLOCK: case E_BLOCK_GOLD_ORE: case E_BLOCK_GRASS: case E_BLOCK_GRAVEL: case E_BLOCK_GRAY_GLAZED_TERRACOTTA: case E_BLOCK_GREEN_GLAZED_TERRACOTTA: case E_BLOCK_HARDENED_CLAY: case E_BLOCK_HAY_BALE: case E_BLOCK_HUGE_BROWN_MUSHROOM: case E_BLOCK_HUGE_RED_MUSHROOM: case E_BLOCK_ICE: case E_BLOCK_IRON_BLOCK: case E_BLOCK_IRON_ORE: case E_BLOCK_JACK_O_LANTERN: case E_BLOCK_JUKEBOX: case E_BLOCK_LAPIS_BLOCK: case E_BLOCK_LAPIS_ORE: case E_BLOCK_LIGHT_BLUE_GLAZED_TERRACOTTA: case E_BLOCK_LIGHT_GRAY_GLAZED_TERRACOTTA: case E_BLOCK_LIME_GLAZED_TERRACOTTA: case E_BLOCK_LOG: case E_BLOCK_MAGENTA_GLAZED_TERRACOTTA: case E_BLOCK_MAGMA: case E_BLOCK_MELON: case E_BLOCK_MOB_SPAWNER: case E_BLOCK_MOSSY_COBBLESTONE: case E_BLOCK_MYCELIUM: case E_BLOCK_NETHERRACK: case E_BLOCK_NETHER_BRICK: case E_BLOCK_NETHER_QUARTZ_ORE: case E_BLOCK_NETHER_WART_BLOCK: case E_BLOCK_NEW_LOG: case E_BLOCK_NOTE_BLOCK: case E_BLOCK_OBSERVER: case E_BLOCK_OBSIDIAN: case E_BLOCK_ORANGE_GLAZED_TERRACOTTA: case E_BLOCK_PACKED_ICE: case E_BLOCK_PINK_GLAZED_TERRACOTTA: case E_BLOCK_PLANKS: case E_BLOCK_PRISMARINE_BLOCK: case E_BLOCK_PUMPKIN: case E_BLOCK_PURPLE_GLAZED_TERRACOTTA: case E_BLOCK_PURPUR_BLOCK: case E_BLOCK_PURPUR_DOUBLE_SLAB: case E_BLOCK_PURPUR_PILLAR: case E_BLOCK_QUARTZ_BLOCK: case E_BLOCK_REDSTONE_LAMP_OFF: case E_BLOCK_REDSTONE_LAMP_ON: case E_BLOCK_REDSTONE_ORE: case E_BLOCK_REDSTONE_ORE_GLOWING: case E_BLOCK_RED_GLAZED_TERRACOTTA: case E_BLOCK_RED_NETHER_BRICK: case E_BLOCK_RED_SANDSTONE: case E_BLOCK_REPEATING_COMMAND_BLOCK: case E_BLOCK_SAND: case E_BLOCK_SANDSTONE: case E_BLOCK_SILVERFISH_EGG: case E_BLOCK_SPONGE: case E_BLOCK_STAINED_CLAY: case E_BLOCK_STAINED_GLASS: case E_BLOCK_STONE: case E_BLOCK_STONE_BRICKS: case E_BLOCK_STRUCTURE_BLOCK: case E_BLOCK_WHITE_GLAZED_TERRACOTTA: case E_BLOCK_WOOL: case E_BLOCK_YELLOW_GLAZED_TERRACOTTA: return true; default: return false; } } bool cBlockInfo::IsClickedThrough(const BLOCKTYPE a_Block) { // TODO: Nether Fire too. return a_Block == E_BLOCK_FIRE; } bool cBlockInfo::IsOneHitDig(const BLOCKTYPE Block) { #ifdef __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wfloat-equal" #endif // GetHardness returns exactly 0 for one hit break blocks: return GetHardness(Block) == 0; #ifdef __clang__ #pragma clang diagnostic pop #endif } bool cBlockInfo::IsPistonBreakable(const BLOCKTYPE Block) { // Blocks that break when pushed by piston: switch (Block) { case E_BLOCK_ACACIA_DOOR: case E_BLOCK_ACTIVE_COMPARATOR: case E_BLOCK_AIR: case E_BLOCK_BED: case E_BLOCK_BEETROOTS: case E_BLOCK_BIG_FLOWER: case E_BLOCK_BIRCH_DOOR: case E_BLOCK_BLACK_SHULKER_BOX: case E_BLOCK_BLUE_SHULKER_BOX: case E_BLOCK_BROWN_MUSHROOM: case E_BLOCK_BROWN_SHULKER_BOX: case E_BLOCK_CACTUS: case E_BLOCK_CAKE: case E_BLOCK_CARROTS: case E_BLOCK_CHORUS_FLOWER: case E_BLOCK_CHORUS_PLANT: case E_BLOCK_COBWEB: case E_BLOCK_COCOA_POD: case E_BLOCK_CROPS: case E_BLOCK_CYAN_SHULKER_BOX: case E_BLOCK_DANDELION: case E_BLOCK_DARK_OAK_DOOR: case E_BLOCK_DEAD_BUSH: case E_BLOCK_DRAGON_EGG: case E_BLOCK_FIRE: case E_BLOCK_FLOWER: case E_BLOCK_FLOWER_POT: case E_BLOCK_GRAY_SHULKER_BOX: case E_BLOCK_GREEN_SHULKER_BOX: case E_BLOCK_HEAD: case E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE: case E_BLOCK_INACTIVE_COMPARATOR: case E_BLOCK_IRON_DOOR: case E_BLOCK_IRON_TRAPDOOR: case E_BLOCK_JACK_O_LANTERN: case E_BLOCK_JUNGLE_DOOR: case E_BLOCK_LADDER: case E_BLOCK_LAVA: case E_BLOCK_LEAVES: case E_BLOCK_LEVER: case E_BLOCK_LIGHT_BLUE_SHULKER_BOX: case E_BLOCK_LIGHT_GRAY_SHULKER_BOX: case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE: case E_BLOCK_LILY_PAD: case E_BLOCK_LIME_SHULKER_BOX: case E_BLOCK_MAGENTA_SHULKER_BOX: case E_BLOCK_MELON: case E_BLOCK_MELON_STEM: case E_BLOCK_NETHER_WART: case E_BLOCK_OAK_DOOR: case E_BLOCK_ORANGE_SHULKER_BOX: case E_BLOCK_PINK_SHULKER_BOX: case E_BLOCK_POTATOES: case E_BLOCK_PUMPKIN: case E_BLOCK_PUMPKIN_STEM: case E_BLOCK_PURPLE_SHULKER_BOX: case E_BLOCK_REDSTONE_REPEATER_OFF: case E_BLOCK_REDSTONE_REPEATER_ON: case E_BLOCK_REDSTONE_TORCH_OFF: case E_BLOCK_REDSTONE_TORCH_ON: case E_BLOCK_REDSTONE_WIRE: case E_BLOCK_RED_MUSHROOM: case E_BLOCK_RED_SHULKER_BOX: case E_BLOCK_REEDS: case E_BLOCK_SAPLING: case E_BLOCK_SIGN_POST: case E_BLOCK_SNOW: case E_BLOCK_SPRUCE_DOOR: case E_BLOCK_STATIONARY_LAVA: case E_BLOCK_STATIONARY_WATER: case E_BLOCK_STONE_BUTTON: case E_BLOCK_STONE_PRESSURE_PLATE: case E_BLOCK_TALL_GRASS: case E_BLOCK_TORCH: case E_BLOCK_TRAPDOOR: case E_BLOCK_TRIPWIRE: case E_BLOCK_TRIPWIRE_HOOK: case E_BLOCK_VINES: case E_BLOCK_WALLSIGN: case E_BLOCK_WATER: case E_BLOCK_WHITE_SHULKER_BOX: case E_BLOCK_WOODEN_BUTTON: case E_BLOCK_WOODEN_PRESSURE_PLATE: case E_BLOCK_YELLOW_SHULKER_BOX: return true; default: return false; } } bool cBlockInfo::IsRainBlocker(const BLOCKTYPE Block) { // Blocks that block rain or snow's passage: switch (Block) { case E_BLOCK_SIGN_POST: case E_BLOCK_STANDING_BANNER: case E_BLOCK_WALLSIGN: case E_BLOCK_WALL_BANNER: return true; default: return IsSolid(Block); } } bool cBlockInfo::IsSkylightDispersant(const BLOCKTYPE Block) { // Skylight dispersant blocks: switch (Block) { case E_BLOCK_COBWEB: case E_BLOCK_LEAVES: return true; default: return GetSpreadLightFalloff(Block) > 1; } } bool cBlockInfo::IsSnowable(BLOCKTYPE a_BlockType) { return ( (a_BlockType == E_BLOCK_ICE) || (a_BlockType == E_BLOCK_LEAVES) || (!IsTransparent(a_BlockType) && (a_BlockType != E_BLOCK_PACKED_ICE)) ); } bool cBlockInfo::IsSolid(const BLOCKTYPE Block) { // Nonsolid blocks: switch (Block) { case E_BLOCK_ACTIVATOR_RAIL: case E_BLOCK_ACTIVE_COMPARATOR: case E_BLOCK_AIR: case E_BLOCK_BEETROOTS: case E_BLOCK_BIG_FLOWER: case E_BLOCK_BROWN_MUSHROOM: case E_BLOCK_CARPET: case E_BLOCK_CARROTS: case E_BLOCK_CHORUS_FLOWER: case E_BLOCK_CHORUS_PLANT: case E_BLOCK_COBWEB: case E_BLOCK_CROPS: case E_BLOCK_DANDELION: case E_BLOCK_DEAD_BUSH: case E_BLOCK_DETECTOR_RAIL: case E_BLOCK_END_GATEWAY: case E_BLOCK_END_PORTAL: case E_BLOCK_END_ROD: case E_BLOCK_FIRE: case E_BLOCK_FLOWER: case E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE: case E_BLOCK_INACTIVE_COMPARATOR: case E_BLOCK_LADDER: case E_BLOCK_LAVA: case E_BLOCK_LEVER: case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE: case E_BLOCK_MELON_STEM: case E_BLOCK_NETHER_PORTAL: case E_BLOCK_POTATOES: case E_BLOCK_POWERED_RAIL: case E_BLOCK_RAIL: case E_BLOCK_REDSTONE_REPEATER_OFF: case E_BLOCK_REDSTONE_REPEATER_ON: case E_BLOCK_REDSTONE_TORCH_OFF: case E_BLOCK_REDSTONE_TORCH_ON: case E_BLOCK_REDSTONE_WIRE: case E_BLOCK_RED_MUSHROOM: case E_BLOCK_SAPLING: case E_BLOCK_SIGN_POST: case E_BLOCK_SNOW: case E_BLOCK_STANDING_BANNER: case E_BLOCK_STATIONARY_LAVA: case E_BLOCK_STATIONARY_WATER: case E_BLOCK_STONE_BUTTON: case E_BLOCK_STONE_PRESSURE_PLATE: case E_BLOCK_SUGARCANE: case E_BLOCK_TALL_GRASS: case E_BLOCK_TORCH: case E_BLOCK_TRIPWIRE: case E_BLOCK_TRIPWIRE_HOOK: case E_BLOCK_VINES: case E_BLOCK_WALLSIGN: case E_BLOCK_WALL_BANNER: case E_BLOCK_WATER: case E_BLOCK_WOODEN_BUTTON: case E_BLOCK_WOODEN_PRESSURE_PLATE: return false; default: return true; } } bool cBlockInfo::IsTransparent(const BLOCKTYPE Block) { // Transparent blocks: switch (Block) { case E_BLOCK_ACACIA_DOOR: case E_BLOCK_ACACIA_FENCE: case E_BLOCK_ACACIA_FENCE_GATE: case E_BLOCK_ACACIA_WOOD_STAIRS: case E_BLOCK_ACTIVATOR_RAIL: case E_BLOCK_ACTIVE_COMPARATOR: case E_BLOCK_AIR: case E_BLOCK_ANVIL: case E_BLOCK_BARRIER: case E_BLOCK_BEACON: case E_BLOCK_BED: case E_BLOCK_BEETROOTS: case E_BLOCK_BIG_FLOWER: case E_BLOCK_BIRCH_DOOR: case E_BLOCK_BIRCH_FENCE: case E_BLOCK_BIRCH_FENCE_GATE: case E_BLOCK_BIRCH_WOOD_STAIRS: case E_BLOCK_BLACK_SHULKER_BOX: case E_BLOCK_BLOCK_OF_REDSTONE: case E_BLOCK_BLUE_SHULKER_BOX: case E_BLOCK_BREWING_STAND: case E_BLOCK_BRICK_STAIRS: case E_BLOCK_BROWN_MUSHROOM: case E_BLOCK_BROWN_SHULKER_BOX: case E_BLOCK_CACTUS: case E_BLOCK_CAKE: case E_BLOCK_CARPET: case E_BLOCK_CARROTS: case E_BLOCK_CAULDRON: case E_BLOCK_CHEST: case E_BLOCK_CHORUS_FLOWER: case E_BLOCK_CHORUS_PLANT: case E_BLOCK_COBBLESTONE_STAIRS: case E_BLOCK_COBBLESTONE_WALL: case E_BLOCK_COBWEB: case E_BLOCK_COCOA_POD: case E_BLOCK_CROPS: case E_BLOCK_CYAN_SHULKER_BOX: case E_BLOCK_DANDELION: case E_BLOCK_DARK_OAK_DOOR: case E_BLOCK_DARK_OAK_FENCE: case E_BLOCK_DARK_OAK_FENCE_GATE: case E_BLOCK_DARK_OAK_WOOD_STAIRS: case E_BLOCK_DAYLIGHT_SENSOR: case E_BLOCK_DEAD_BUSH: case E_BLOCK_DETECTOR_RAIL: case E_BLOCK_DRAGON_EGG: case E_BLOCK_ENCHANTMENT_TABLE: case E_BLOCK_ENDER_CHEST: case E_BLOCK_END_GATEWAY: case E_BLOCK_END_PORTAL: case E_BLOCK_END_PORTAL_FRAME: case E_BLOCK_END_ROD: case E_BLOCK_FARMLAND: case E_BLOCK_FENCE: case E_BLOCK_FIRE: case E_BLOCK_FLOWER: case E_BLOCK_FLOWER_POT: case E_BLOCK_FROSTED_ICE: case E_BLOCK_GLASS: case E_BLOCK_GLASS_PANE: case E_BLOCK_GLOWSTONE: case E_BLOCK_GRASS_PATH: case E_BLOCK_GRAY_SHULKER_BOX: case E_BLOCK_GREEN_SHULKER_BOX: case E_BLOCK_HEAD: case E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE: case E_BLOCK_HOPPER: case E_BLOCK_ICE: case E_BLOCK_INACTIVE_COMPARATOR: case E_BLOCK_INVERTED_DAYLIGHT_SENSOR: case E_BLOCK_IRON_BARS: case E_BLOCK_IRON_DOOR: case E_BLOCK_IRON_TRAPDOOR: case E_BLOCK_JACK_O_LANTERN: case E_BLOCK_JUNGLE_DOOR: case E_BLOCK_JUNGLE_FENCE: case E_BLOCK_JUNGLE_FENCE_GATE: case E_BLOCK_JUNGLE_WOOD_STAIRS: case E_BLOCK_LADDER: case E_BLOCK_LAVA: case E_BLOCK_LEAVES: case E_BLOCK_LEVER: case E_BLOCK_LIGHT_BLUE_SHULKER_BOX: case E_BLOCK_LIGHT_GRAY_SHULKER_BOX: case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE: case E_BLOCK_LILY_PAD: case E_BLOCK_LIME_SHULKER_BOX: case E_BLOCK_LIT_FURNACE: case E_BLOCK_MAGENTA_SHULKER_BOX: case E_BLOCK_MELON_STEM: case E_BLOCK_MOB_SPAWNER: case E_BLOCK_NETHER_BRICK_FENCE: case E_BLOCK_NETHER_BRICK_STAIRS: case E_BLOCK_NETHER_PORTAL: case E_BLOCK_NETHER_WART: case E_BLOCK_NEW_LEAVES: case E_BLOCK_OAK_DOOR: case E_BLOCK_OAK_FENCE_GATE: case E_BLOCK_OAK_WOOD_STAIRS: case E_BLOCK_OBSERVER: case E_BLOCK_ORANGE_SHULKER_BOX: case E_BLOCK_PINK_SHULKER_BOX: case E_BLOCK_PISTON: case E_BLOCK_PISTON_EXTENSION: case E_BLOCK_PISTON_MOVED_BLOCK: case E_BLOCK_POTATOES: case E_BLOCK_POWERED_RAIL: case E_BLOCK_PUMPKIN_STEM: case E_BLOCK_PURPLE_SHULKER_BOX: case E_BLOCK_PURPUR_SLAB: case E_BLOCK_PURPUR_STAIRS: case E_BLOCK_QUARTZ_STAIRS: case E_BLOCK_RAIL: case E_BLOCK_REDSTONE_ORE_GLOWING: case E_BLOCK_REDSTONE_REPEATER_OFF: case E_BLOCK_REDSTONE_REPEATER_ON: case E_BLOCK_REDSTONE_TORCH_OFF: case E_BLOCK_REDSTONE_TORCH_ON: case E_BLOCK_REDSTONE_WIRE: case E_BLOCK_RED_MUSHROOM: case E_BLOCK_RED_SANDSTONE_SLAB: case E_BLOCK_RED_SANDSTONE_STAIRS: case E_BLOCK_RED_SHULKER_BOX: case E_BLOCK_SANDSTONE_STAIRS: case E_BLOCK_SAPLING: case E_BLOCK_SEA_LANTERN: case E_BLOCK_SIGN_POST: case E_BLOCK_SNOW: case E_BLOCK_SPRUCE_DOOR: case E_BLOCK_SPRUCE_FENCE: case E_BLOCK_SPRUCE_FENCE_GATE: case E_BLOCK_SPRUCE_WOOD_STAIRS: case E_BLOCK_STAINED_GLASS: case E_BLOCK_STAINED_GLASS_PANE: case E_BLOCK_STANDING_BANNER: case E_BLOCK_STATIONARY_LAVA: case E_BLOCK_STATIONARY_WATER: case E_BLOCK_STICKY_PISTON: case E_BLOCK_STONE_BRICK_STAIRS: case E_BLOCK_STONE_BUTTON: case E_BLOCK_STONE_PRESSURE_PLATE: case E_BLOCK_STONE_SLAB: case E_BLOCK_SUGARCANE: case E_BLOCK_TALL_GRASS: case E_BLOCK_TNT: case E_BLOCK_TORCH: case E_BLOCK_TRAPDOOR: case E_BLOCK_TRAPPED_CHEST: case E_BLOCK_TRIPWIRE: case E_BLOCK_TRIPWIRE_HOOK: case E_BLOCK_VINES: case E_BLOCK_WALLSIGN: case E_BLOCK_WALL_BANNER: case E_BLOCK_WATER: case E_BLOCK_WHITE_SHULKER_BOX: case E_BLOCK_WOODEN_BUTTON: case E_BLOCK_WOODEN_PRESSURE_PLATE: case E_BLOCK_WOODEN_SLAB: case E_BLOCK_YELLOW_SHULKER_BOX: return true; default: return false; } } bool cBlockInfo::IsUseableBySpectator(const BLOCKTYPE Block) { // Blocks, which a spectator is allowed to interact with: switch (Block) { case E_BLOCK_BEACON: case E_BLOCK_BREWING_STAND: case E_BLOCK_CHEST: case E_BLOCK_DISPENSER: case E_BLOCK_DROPPER: case E_BLOCK_HOPPER: return true; default: return false; } } float cBlockInfo::GetBlockHeight(const BLOCKTYPE Block) { // Block heights: switch (Block) { case E_BLOCK_ACACIA_FENCE: return 1.5; case E_BLOCK_ACACIA_FENCE_GATE: return 1.5; case E_BLOCK_BED: return 0.5625; // 9 pixels case E_BLOCK_BIRCH_FENCE: return 1.5; case E_BLOCK_BIRCH_FENCE_GATE: return 1.5; case E_BLOCK_CAKE: return 0.5; // 8 pixels case E_BLOCK_DARK_OAK_FENCE: return 1.5; case E_BLOCK_DARK_OAK_FENCE_GATE: return 1.5; case E_BLOCK_ENCHANTMENT_TABLE: return 0.75; // 12 pixels // case E_BLOCK_FARMLAND: return 0.9375; // prevents trampling for mobs (#2015) and older clients (MC-85162) case E_BLOCK_FENCE: return 1.5; case E_BLOCK_JUNGLE_FENCE: return 1.5; case E_BLOCK_JUNGLE_FENCE_GATE: return 1.5; case E_BLOCK_OAK_FENCE_GATE: return 1.5; case E_BLOCK_PURPUR_SLAB: return 0.5; case E_BLOCK_RED_SANDSTONE_SLAB: return 0.5; case E_BLOCK_SNOW: return 0.125; // one layer is 1 / 8 (2 pixels) tall case E_BLOCK_SPRUCE_FENCE: return 1.5; case E_BLOCK_SPRUCE_FENCE_GATE: return 1.5; case E_BLOCK_STONE_SLAB: return 0.5; case E_BLOCK_WOODEN_SLAB: return 0.5; default: return 1; } } float cBlockInfo::GetHardness(const BLOCKTYPE Block) { // Block hardness: switch (Block) { case E_BLOCK_ACACIA_DOOR: return 3.0f; case E_BLOCK_ACACIA_FENCE: return 2.0f; case E_BLOCK_ACACIA_FENCE_GATE: return 2.0f; case E_BLOCK_ACACIA_WOOD_STAIRS: return 2.0f; case E_BLOCK_ACTIVATOR_RAIL: return 0.7f; case E_BLOCK_ACTIVE_COMPARATOR: return 0.0f; case E_BLOCK_AIR: return 0.0f; case E_BLOCK_ANVIL: return 5.0f; case E_BLOCK_BARRIER: return INFINITY; case E_BLOCK_BEACON: return 3.0f; case E_BLOCK_BED: return 0.2f; case E_BLOCK_BEDROCK: return INFINITY; case E_BLOCK_BEETROOTS: return 0.0f; case E_BLOCK_BIG_FLOWER: return 0.0f; case E_BLOCK_BIRCH_DOOR: return 3.0f; case E_BLOCK_BIRCH_FENCE: return 2.0f; case E_BLOCK_BIRCH_FENCE_GATE: return 2.0f; case E_BLOCK_BIRCH_WOOD_STAIRS: return 2.0f; case E_BLOCK_BLACK_GLAZED_TERRACOTTA: return 1.4f; case E_BLOCK_BLACK_SHULKER_BOX: return 2.0f; case E_BLOCK_BLOCK_OF_COAL: return 5.0f; case E_BLOCK_BLOCK_OF_REDSTONE: return 5.0f; case E_BLOCK_BLUE_GLAZED_TERRACOTTA: return 1.4f; case E_BLOCK_BLUE_SHULKER_BOX: return 2.0f; case E_BLOCK_BONE_BLOCK: return 2.0f; case E_BLOCK_BOOKCASE: return 1.5f; case E_BLOCK_BREWING_STAND: return 0.5f; case E_BLOCK_BRICK: return 2.0f; case E_BLOCK_BRICK_STAIRS: return 2.0f; case E_BLOCK_BROWN_GLAZED_TERRACOTTA: return 1.4f; case E_BLOCK_BROWN_MUSHROOM: return 0.0f; case E_BLOCK_BROWN_SHULKER_BOX: return 2.0f; case E_BLOCK_CACTUS: return 0.4f; case E_BLOCK_CAKE: return 0.5f; case E_BLOCK_CARPET: return 0.1f; case E_BLOCK_CARROTS: return 0.0f; case E_BLOCK_CAULDRON: return 2.0f; case E_BLOCK_CHAIN_COMMAND_BLOCK: return INFINITY; case E_BLOCK_CHEST: return 2.5f; case E_BLOCK_CHORUS_FLOWER: return 0.4f; case E_BLOCK_CHORUS_PLANT: return 0.4f; case E_BLOCK_CLAY: return 0.6f; case E_BLOCK_COAL_ORE: return 3.0f; case E_BLOCK_COBBLESTONE: return 2.0f; case E_BLOCK_COBBLESTONE_STAIRS: return 2.0f; case E_BLOCK_COBBLESTONE_WALL: return 2.0f; case E_BLOCK_COBWEB: return 4.0f; case E_BLOCK_COCOA_POD: return 0.2f; case E_BLOCK_COMMAND_BLOCK: return INFINITY; case E_BLOCK_CONCRETE: return 1.8f; case E_BLOCK_CONCRETE_POWDER: return 0.5f; case E_BLOCK_CRAFTING_TABLE: return 2.5f; case E_BLOCK_CROPS: return 0.0f; case E_BLOCK_CYAN_GLAZED_TERRACOTTA: return 1.4f; case E_BLOCK_CYAN_SHULKER_BOX: return 2.0f; case E_BLOCK_DANDELION: return 0.0f; case E_BLOCK_DARK_OAK_DOOR: return 3.0f; case E_BLOCK_DARK_OAK_FENCE: return 2.0f; case E_BLOCK_DARK_OAK_FENCE_GATE: return 2.0f; case E_BLOCK_DARK_OAK_WOOD_STAIRS: return 2.0f; case E_BLOCK_DAYLIGHT_SENSOR: return 0.2f; case E_BLOCK_DEAD_BUSH: return 0.0f; case E_BLOCK_DETECTOR_RAIL: return 0.7f; case E_BLOCK_DIAMOND_BLOCK: return 5.0f; case E_BLOCK_DIAMOND_ORE: return 3.0f; case E_BLOCK_DIRT: return 0.5f; case E_BLOCK_DISPENSER: return 3.5f; case E_BLOCK_DOUBLE_RED_SANDSTONE_SLAB: return 2.0f; case E_BLOCK_DOUBLE_STONE_SLAB: return 2.0f; case E_BLOCK_DOUBLE_WOODEN_SLAB: return 2.0f; case E_BLOCK_DRAGON_EGG: return 3.0f; case E_BLOCK_DROPPER: return 3.5f; case E_BLOCK_EMERALD_BLOCK: return 5.0f; case E_BLOCK_EMERALD_ORE: return 3.0f; case E_BLOCK_ENCHANTMENT_TABLE: return 5.0f; case E_BLOCK_ENDER_CHEST: return 22.5f; case E_BLOCK_END_BRICKS: return 0.8f; case E_BLOCK_END_GATEWAY: return INFINITY; case E_BLOCK_END_PORTAL: return INFINITY; case E_BLOCK_END_PORTAL_FRAME: return INFINITY; case E_BLOCK_END_ROD: return 0.0f; case E_BLOCK_END_STONE: return 3.0f; case E_BLOCK_FARMLAND: return 0.6f; case E_BLOCK_FENCE: return 2.0f; case E_BLOCK_FIRE: return 0.0f; case E_BLOCK_FLOWER: return 0.0f; case E_BLOCK_FLOWER_POT: return 0.0f; case E_BLOCK_FROSTED_ICE: return 0.5f; case E_BLOCK_FURNACE: return 3.5f; case E_BLOCK_GLASS: return 0.3f; case E_BLOCK_GLASS_PANE: return 0.3f; case E_BLOCK_GLOWSTONE: return 0.3f; case E_BLOCK_GOLD_BLOCK: return 3.0f; case E_BLOCK_GOLD_ORE: return 3.0f; case E_BLOCK_GRASS: return 0.6f; case E_BLOCK_GRASS_PATH: return 0.6f; case E_BLOCK_GRAVEL: return 0.6f; case E_BLOCK_GRAY_GLAZED_TERRACOTTA: return 1.4f; case E_BLOCK_GRAY_SHULKER_BOX: return 2.0f; case E_BLOCK_GREEN_GLAZED_TERRACOTTA: return 1.4f; case E_BLOCK_GREEN_SHULKER_BOX: return 2.0f; case E_BLOCK_HARDENED_CLAY: return 1.25f; case E_BLOCK_HAY_BALE: return 0.5f; case E_BLOCK_HEAD: return 1.0f; case E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE: return 0.5f; case E_BLOCK_HOPPER: return 3.0f; case E_BLOCK_HUGE_BROWN_MUSHROOM: return 0.2f; case E_BLOCK_HUGE_RED_MUSHROOM: return 0.2f; case E_BLOCK_ICE: return 0.5f; case E_BLOCK_INACTIVE_COMPARATOR: return 0.0f; case E_BLOCK_INVERTED_DAYLIGHT_SENSOR: return 0.2f; case E_BLOCK_IRON_BARS: return 5.0f; case E_BLOCK_IRON_BLOCK: return 5.0f; case E_BLOCK_IRON_DOOR: return 5.0f; case E_BLOCK_IRON_ORE: return 3.0f; case E_BLOCK_IRON_TRAPDOOR: return 5.0f; case E_BLOCK_JACK_O_LANTERN: return 1.0f; case E_BLOCK_JUKEBOX: return 2.0f; case E_BLOCK_JUNGLE_DOOR: return 3.0f; case E_BLOCK_JUNGLE_FENCE: return 2.0f; case E_BLOCK_JUNGLE_FENCE_GATE: return 2.0f; case E_BLOCK_JUNGLE_WOOD_STAIRS: return 2.0f; case E_BLOCK_LADDER: return 0.4f; case E_BLOCK_LAPIS_BLOCK: return 3.0f; case E_BLOCK_LAPIS_ORE: return 3.0f; case E_BLOCK_LAVA: return 100.0f; case E_BLOCK_LEAVES: return 0.2f; case E_BLOCK_LEVER: return 0.5f; case E_BLOCK_LIGHT_BLUE_GLAZED_TERRACOTTA: return 1.4f; case E_BLOCK_LIGHT_BLUE_SHULKER_BOX: return 2.0f; case E_BLOCK_LIGHT_GRAY_GLAZED_TERRACOTTA: return 1.4f; case E_BLOCK_LIGHT_GRAY_SHULKER_BOX: return 2.0f; case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE: return 0.5f; case E_BLOCK_LILY_PAD: return 0.0f; case E_BLOCK_LIME_GLAZED_TERRACOTTA: return 1.4f; case E_BLOCK_LIME_SHULKER_BOX: return 2.0f; case E_BLOCK_LIT_FURNACE: return 3.5f; case E_BLOCK_LOG: return 2.0f; case E_BLOCK_MAGENTA_GLAZED_TERRACOTTA: return 1.4f; case E_BLOCK_MAGENTA_SHULKER_BOX: return 2.0f; case E_BLOCK_MAGMA: return 0.5f; case E_BLOCK_MELON: return 1.0f; case E_BLOCK_MELON_STEM: return 0.0f; case E_BLOCK_MOB_SPAWNER: return 5.0f; case E_BLOCK_MOSSY_COBBLESTONE: return 2.0f; case E_BLOCK_MYCELIUM: return 0.6f; case E_BLOCK_NETHERRACK: return 0.4f; case E_BLOCK_NETHER_BRICK: return 2.0f; case E_BLOCK_NETHER_BRICK_FENCE: return 2.0f; case E_BLOCK_NETHER_BRICK_STAIRS: return 2.0f; case E_BLOCK_NETHER_PORTAL: return INFINITY; case E_BLOCK_NETHER_QUARTZ_ORE: return 3.0f; case E_BLOCK_NETHER_WART: return 0.0f; case E_BLOCK_NETHER_WART_BLOCK: return 1.0f; case E_BLOCK_NEW_LEAVES: return 0.2f; case E_BLOCK_NEW_LOG: return 2.0f; case E_BLOCK_NOTE_BLOCK: return 0.8f; case E_BLOCK_OAK_DOOR: return 3.0f; case E_BLOCK_OAK_FENCE_GATE: return 2.0f; case E_BLOCK_OAK_WOOD_STAIRS: return 2.0f; case E_BLOCK_OBSERVER: return 3.5f; case E_BLOCK_OBSIDIAN: return 50.0f; case E_BLOCK_ORANGE_GLAZED_TERRACOTTA: return 1.4f; case E_BLOCK_ORANGE_SHULKER_BOX: return 2.0f; case E_BLOCK_PACKED_ICE: return 0.5f; case E_BLOCK_PINK_GLAZED_TERRACOTTA: return 1.4f; case E_BLOCK_PINK_SHULKER_BOX: return 2.0f; case E_BLOCK_PISTON: return 0.5f; case E_BLOCK_PISTON_EXTENSION: return 0.5f; case E_BLOCK_PISTON_MOVED_BLOCK: return INFINITY; case E_BLOCK_PLANKS: return 2.0f; case E_BLOCK_POTATOES: return 0.0f; case E_BLOCK_POWERED_RAIL: return 0.7f; case E_BLOCK_PRISMARINE_BLOCK: return 1.5f; case E_BLOCK_PUMPKIN: return 1.0f; case E_BLOCK_PUMPKIN_STEM: return 0.0f; case E_BLOCK_PURPLE_GLAZED_TERRACOTTA: return 1.4f; case E_BLOCK_PURPLE_SHULKER_BOX: return 2.0f; case E_BLOCK_PURPUR_BLOCK: return 1.5f; case E_BLOCK_PURPUR_DOUBLE_SLAB: return 2.0f; case E_BLOCK_PURPUR_PILLAR: return 1.5f; case E_BLOCK_PURPUR_SLAB: return 2.0f; case E_BLOCK_PURPUR_STAIRS: return 1.5f; case E_BLOCK_QUARTZ_BLOCK: return 0.8f; case E_BLOCK_QUARTZ_STAIRS: return 0.8f; case E_BLOCK_RAIL: return 0.7f; case E_BLOCK_REDSTONE_LAMP_OFF: return 0.3f; case E_BLOCK_REDSTONE_LAMP_ON: return 0.3f; case E_BLOCK_REDSTONE_ORE: return 3.0f; case E_BLOCK_REDSTONE_ORE_GLOWING: return 0.625f; case E_BLOCK_REDSTONE_REPEATER_OFF: return 0.0f; case E_BLOCK_REDSTONE_REPEATER_ON: return 0.0f; case E_BLOCK_REDSTONE_TORCH_OFF: return 0.0f; case E_BLOCK_REDSTONE_TORCH_ON: return 0.0f; case E_BLOCK_REDSTONE_WIRE: return 0.0f; case E_BLOCK_RED_GLAZED_TERRACOTTA: return 1.4f; case E_BLOCK_RED_MUSHROOM: return 0.0f; case E_BLOCK_RED_NETHER_BRICK: return 2.0f; case E_BLOCK_RED_SANDSTONE: return 0.8f; case E_BLOCK_RED_SANDSTONE_SLAB: return 2.0f; case E_BLOCK_RED_SANDSTONE_STAIRS: return 0.8f; case E_BLOCK_RED_SHULKER_BOX: return 2.0f; case E_BLOCK_REPEATING_COMMAND_BLOCK: return INFINITY; case E_BLOCK_SAND: return 0.5f; case E_BLOCK_SANDSTONE: return 0.8f; case E_BLOCK_SANDSTONE_STAIRS: return 0.8f; case E_BLOCK_SAPLING: return 0.0f; case E_BLOCK_SEA_LANTERN: return 0.3f; case E_BLOCK_SIGN_POST: return 1.0f; case E_BLOCK_SILVERFISH_EGG: return 0.75f; case E_BLOCK_SLIME_BLOCK: return 0.0f; case E_BLOCK_SNOW: return 0.1f; case E_BLOCK_SNOW_BLOCK: return 0.2f; case E_BLOCK_SOULSAND: return 0.5f; case E_BLOCK_SPONGE: return 0.6f; case E_BLOCK_SPRUCE_DOOR: return 3.0f; case E_BLOCK_SPRUCE_FENCE: return 2.0f; case E_BLOCK_SPRUCE_FENCE_GATE: return 2.0f; case E_BLOCK_SPRUCE_WOOD_STAIRS: return 2.0f; case E_BLOCK_STAINED_CLAY: return 4.2f; case E_BLOCK_STAINED_GLASS: return 0.3f; case E_BLOCK_STAINED_GLASS_PANE: return 0.3f; case E_BLOCK_STANDING_BANNER: return 1.0f; case E_BLOCK_STATIONARY_LAVA: return 100.0f; case E_BLOCK_STATIONARY_WATER: return 100.0f; case E_BLOCK_STICKY_PISTON: return 0.5f; case E_BLOCK_STONE: return 1.5f; case E_BLOCK_STONE_BRICKS: return 1.5f; case E_BLOCK_STONE_BRICK_STAIRS: return 1.5f; case E_BLOCK_STONE_BUTTON: return 0.5f; case E_BLOCK_STONE_PRESSURE_PLATE: return 0.5f; case E_BLOCK_STONE_SLAB: return 2.0f; case E_BLOCK_STRUCTURE_BLOCK: return INFINITY; case E_BLOCK_STRUCTURE_VOID: return 0.0f; case E_BLOCK_SUGARCANE: return 0.0f; case E_BLOCK_TALL_GRASS: return 0.0f; case E_BLOCK_TNT: return 0.0f; case E_BLOCK_TORCH: return 0.0f; case E_BLOCK_TRAPDOOR: return 3.0f; case E_BLOCK_TRAPPED_CHEST: return 2.5f; case E_BLOCK_TRIPWIRE: return 0.0f; case E_BLOCK_TRIPWIRE_HOOK: return 0.0f; case E_BLOCK_VINES: return 0.2f; case E_BLOCK_WALLSIGN: return 1.0f; case E_BLOCK_WALL_BANNER: return 1.0f; case E_BLOCK_WATER: return 100.0f; case E_BLOCK_WHITE_GLAZED_TERRACOTTA: return 1.4f; case E_BLOCK_WHITE_SHULKER_BOX: return 2.0f; case E_BLOCK_WOODEN_BUTTON: return 0.5f; case E_BLOCK_WOODEN_PRESSURE_PLATE: return 0.5f; case E_BLOCK_WOODEN_SLAB: return 2.0f; case E_BLOCK_WOOL: return 0.8f; case E_BLOCK_YELLOW_GLAZED_TERRACOTTA: return 1.4f; case E_BLOCK_YELLOW_SHULKER_BOX: return 2.0f; default: return 0; } } ================================================ FILE: src/BlockInfo.h ================================================ #pragma once #include "ChunkDef.h" // tolua_begin class cBlockInfo { public: /** How much light do the blocks emit on their own? */ static NIBBLETYPE GetLightValue(BLOCKTYPE Block); /** How much light do the blocks consume? */ static NIBBLETYPE GetSpreadLightFalloff(BLOCKTYPE Block); /** Can a finisher change it? */ static bool CanBeTerraformed(BLOCKTYPE Block); /** Does this block fully occupy its voxel - is it a 'full' block? */ static bool FullyOccupiesVoxel(BLOCKTYPE Block); /** Does the client pretend the block doesn't exist when clicking? For example, digging a fire will hit the block below the fire, so fire is "clicked through". */ static bool IsClickedThrough(BLOCKTYPE a_Block); /** Is a block destroyed after a single hit? Warning: IsOneHitDig does not take into account enchantments / status effects / swim state / floating state and therefore may be incorrect. Only use to check if hardness is 0. If you want to check if a player would instantly mine a_Block use cPlayer::CanInstantlyMine(a_Block) */ static bool IsOneHitDig(BLOCKTYPE Block); /** Can a piston break this block? */ static bool IsPistonBreakable(BLOCKTYPE Block); /** Does this block block the passage of rain? */ static bool IsRainBlocker(BLOCKTYPE Block); /** Does this block disperse sky light? (only relevant for transparent blocks) */ static bool IsSkylightDispersant(BLOCKTYPE Block); static bool IsSnowable(BLOCKTYPE Block); /** Is this block solid (player cannot walk through)? */ static bool IsSolid(BLOCKTYPE Block); /** Is a block transparent? (https://minecraft.wiki/w/Opacity) */ static bool IsTransparent(BLOCKTYPE Block); /** Can a spectator interact with this block? */ static bool IsUseableBySpectator(BLOCKTYPE Block); /** Block's height. */ static float GetBlockHeight(BLOCKTYPE Block); /** Block's hardness. The greater the value the longer the player needs to break the block. */ static float GetHardness(BLOCKTYPE Block); }; // tolua_end bool IsBlockWater(BLOCKTYPE a_BlockType); bool IsBlockIce(BLOCKTYPE a_BlockType); bool IsBlockWaterOrIce(BLOCKTYPE a_BlockType); bool IsBlockLava(BLOCKTYPE a_BlockType); bool IsBlockLiquid(BLOCKTYPE a_BlockType); bool IsBlockRail(BLOCKTYPE a_BlockType); bool IsBlockTypeOfDirt(BLOCKTYPE a_BlockType); bool IsBlockFence(BLOCKTYPE a_BlockType); bool IsBlockShulkerBox(BLOCKTYPE a_BlockType); bool IsBlockMaterialWood(BLOCKTYPE a_BlockType); bool IsBlockMaterialPlants(BLOCKTYPE a_BlockType); bool IsBlockMaterialVine(BLOCKTYPE a_BlockType); bool IsBlockMaterialIron(BLOCKTYPE a_BlockType); bool IsBlockMaterialLeaves(BLOCKTYPE a_BlockType); bool IsBlockMaterialGourd(BLOCKTYPE a_BlockType); bool IsBlockMaterialRock(BLOCKTYPE a_BlockType); ================================================ FILE: src/BlockState.h ================================================ #pragma once #include "Registries/BlockTypes.h" struct BlockState { constexpr BlockState(uint_least16_t StateID) : ID(StateID) { } /** Gets the block type of this block state. */ BlockType Type() const; bool operator == (BlockState Block) const { return ID == Block.ID; } bool operator != (BlockState Block) const { return ID != Block.ID; } /** The state ID of the block state. */ uint_least16_t ID; }; ================================================ FILE: src/BlockTracer.h ================================================ // BlockTracer.h // Declares the classes common for all blocktracers #pragma once #include "Defines.h" #include "ChunkDef.h" // fwd: World.h class cWorld; class cBlockTracer abstract { public: /** The callback class is used to notify the caller of individual events that are being traced. */ class cCallbacks abstract { public: // Force a virtual destructor in descendants: virtual ~cCallbacks() {} /** Called on each block encountered along the path, including the first block (path start) When this callback returns true, the tracing is aborted. */ virtual bool OnNextBlock(Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, eBlockFace a_EntryFace) = 0; /** Called on each block encountered along the path, including the first block (path start), if chunk data is not loaded When this callback returns true, the tracing is aborted. */ virtual bool OnNextBlockNoData(Vector3i a_BlockPos, eBlockFace a_EntryFace) { UNUSED(a_BlockPos); UNUSED(a_EntryFace); return false; } /** Called when the path goes out of world, either below (a_BlockPos.y < 0) or above (a_BlockPos.y >= cChunkDef::Height) The coords specify the exact point at which the path exited the world. If this callback returns true, the tracing is aborted. Note that some paths can go out of the world and come back again (parabola), in such a case this callback is followed by OnIntoWorld() and further OnNextBlock() calls */ virtual bool OnOutOfWorld(Vector3d a_BlockPos) { UNUSED(a_BlockPos); return false; } /** Called when the path goes into the world, from either below (a_BlockPos.y < 0) or above (a_BlockPos.y >= cChunkDef::Height) The coords specify the exact point at which the path entered the world. If this callback returns true, the tracing is aborted. Note that some paths can go out of the world and come back again (parabola), in such a case this callback is followed by further OnNextBlock() calls */ virtual bool OnIntoWorld(Vector3d a_BlockPos) { UNUSED(a_BlockPos); return false; } /** Called when the path is sure not to hit any more blocks. Note that for some shapes this might never happen (line with constant Y) */ virtual void OnNoMoreHits(void) {} /** Called when the block tracing walks into a chunk that is not allocated. This usually means that the tracing is aborted. */ virtual void OnNoChunk(void) {} } ; /** Creates the BlockTracer parent with the specified callbacks */ cBlockTracer(cWorld & a_World, cCallbacks & a_Callbacks) : m_World(&a_World), m_Callbacks(&a_Callbacks) { } /** Sets new world, returns the old one. Note that both need to be valid */ cWorld & SetWorld(cWorld & a_World) { cWorld & Old = *m_World; m_World = &a_World; return Old; } /** Sets new callbacks, returns the old ones. Note that both need to be valid */ cCallbacks & SetCallbacks(cCallbacks & a_NewCallbacks) { cCallbacks & Old = *m_Callbacks; m_Callbacks = &a_NewCallbacks; return Old; } protected: /** The world upon which to operate */ cWorld * m_World; /** The callback to use for reporting */ cCallbacks * m_Callbacks; } ; ================================================ FILE: src/BlockType.cpp ================================================ // BlockType.cpp // Implements the helper functions for converting Block Type string to int etc. #include "Globals.h" #include "IniFile.h" #include "Item.h" #include "Mobs/Monster.h" class cBlockIDMap { // Making the map case-insensitive: struct Comparator { bool operator ()(const AString & a_Item1, const AString & a_Item2) const { return (NoCaseCompare(a_Item1, a_Item2) > 0); } } ; typedef std::map, Comparator> ItemMap; public: cBlockIDMap(void) { cIniFile Ini; if (!Ini.ReadFile("items.ini")) { return; } int KeyID = Ini.FindKey("Items"); if (KeyID == cIniFile::noID) { return; } int NumValues = Ini.GetNumValues(KeyID); for (int i = 0; i < NumValues; i++) { AString Name = Ini.GetValueName(KeyID, i); if (Name.empty()) { continue; } AString Value = Ini.GetValue(KeyID, i); AddToMap(Name, Value); } // for i - Ini.Values[] } int Resolve(const AString & a_ItemName) { ItemMap::iterator itr = m_Map.find(a_ItemName); if (itr == m_Map.end()) { return -1; } return itr->second.first; } bool ResolveItem(const AString & a_ItemName, cItem & a_Item) { // Split into parts divided by either ':' or '^' AStringVector Split = StringSplitAndTrim(a_ItemName, ":^"); if (Split.empty()) { return false; } ItemMap::iterator itr = m_Map.find(Split[0]); if (itr != m_Map.end()) { // Resolved as a string, assign the type and the default damage / count a_Item.m_ItemType = itr->second.first; a_Item.m_ItemDamage = itr->second.second; if (a_Item.m_ItemDamage == -1) { a_Item.m_ItemDamage = 0; } } else { // Not a resolvable string, try pure numbers: "45:6", "45^6" etc. if (!StringToInteger(Split[0], a_Item.m_ItemType)) { // Parsing the number failed return false; } } // Parse the damage, if present: if (Split.size() < 2) { // Not present, set the item as valid and return success: a_Item.m_ItemCount = 1; return true; } if (!StringToInteger(Split[1], a_Item.m_ItemDamage)) { // Parsing the number failed return false; } a_Item.m_ItemCount = 1; return true; } AString Desolve(short a_ItemType, short a_ItemDamage) { // First try an exact match, both ItemType and ItemDamage ("birchplanks=5:2"): for (ItemMap::iterator itr = m_Map.begin(), end = m_Map.end(); itr != end; ++itr) { if ((itr->second.first == a_ItemType) && (itr->second.second == a_ItemDamage)) { return itr->first; } } // for itr - m_Map[] // There is no exact match, try matching ItemType only ("planks=5"): if (a_ItemDamage == 0) { for (ItemMap::iterator itr = m_Map.begin(), end = m_Map.end(); itr != end; ++itr) { if ((itr->second.first == a_ItemType) && (itr->second.second == -1)) { return itr->first; } } // for itr - m_Map[] } // No match at all, synthesize a string ("5:1"): AString res; if (a_ItemDamage == -1) { res = fmt::format(FMT_STRING("{}"), a_ItemType); } else { res = fmt::format(FMT_STRING("{}:{}"), a_ItemType, a_ItemDamage); } return res; } protected: ItemMap m_Map; void AddToMap(const AString & a_Name, const AString & a_Value) { AStringVector Split = StringSplit(a_Value, ":"); if (Split.size() == 1) { Split = StringSplit(a_Value, "^"); } if (Split.empty()) { return; } short ItemType; if (!StringToInteger(Split[0], ItemType)) { ASSERT(!"Invalid item type"); } short ItemDamage = -1; if (Split.size() > 1 && !StringToInteger(Split[1], ItemDamage)) { ASSERT(!"Invalid item damage"); } m_Map[a_Name] = std::make_pair(ItemType, ItemDamage); } } ; static cBlockIDMap & GetBlockIDMap() { static cBlockIDMap IDMap; return IDMap; } /* // Quick self-test: class Tester { public: Tester(void) { cItem Item; gsBlockIDMap.ResolveItem("charcoal", Item); AString Charcoal = gsBlockIDMap.Desolve(Item.m_ItemType, Item.m_ItemDamage); ASSERT(Charcoal == "charcoal"); } } test; //*/ int BlockStringToType(const AString & a_BlockTypeString) { int res = atoi(a_BlockTypeString.c_str()); if ((res != 0) || (a_BlockTypeString.compare("0") == 0)) { // It was a valid number, return that return res; } return GetBlockIDMap().Resolve(TrimString(a_BlockTypeString)); } bool StringToItem(const AString & a_ItemTypeString, cItem & a_Item) { AString ItemName = TrimString(a_ItemTypeString); if (ItemName.substr(0, 10) == "minecraft:") { ItemName = ItemName.substr(10); } return GetBlockIDMap().ResolveItem(ItemName, a_Item); } AString ItemToString(const cItem & a_Item) { return GetBlockIDMap().Desolve(a_Item.m_ItemType, a_Item.m_ItemDamage); } AString ItemTypeToString(short a_ItemType) { return GetBlockIDMap().Desolve(a_ItemType, -1); } AString ItemToFullString(const cItem & a_Item) { return fmt::format(FMT_STRING("{}:{} * {:d}"), ItemToString(a_Item), a_Item.m_ItemDamage, a_Item.m_ItemCount); } cItem GetIniItemSet(cIniFile & a_IniFile, const char * a_Section, const char * a_Key, const char * a_Default) { AString ItemStr = a_IniFile.GetValueSet(a_Section, a_Key, a_Default); cItem res; if (!StringToItem(ItemStr, res)) { res.Empty(); } return res; } ================================================ FILE: src/BlockType.h ================================================ #pragma once #include "ChunkDef.h" // tolua_begin enum ENUM_BLOCK_TYPE : BLOCKTYPE { E_BLOCK_AIR = 0, E_BLOCK_STONE = 1, E_BLOCK_GRASS = 2, E_BLOCK_DIRT = 3, E_BLOCK_COBBLESTONE = 4, E_BLOCK_PLANKS = 5, E_BLOCK_SAPLING = 6, E_BLOCK_BEDROCK = 7, E_BLOCK_WATER = 8, E_BLOCK_STATIONARY_WATER = 9, E_BLOCK_LAVA = 10, E_BLOCK_STATIONARY_LAVA = 11, E_BLOCK_SAND = 12, E_BLOCK_GRAVEL = 13, E_BLOCK_GOLD_ORE = 14, E_BLOCK_IRON_ORE = 15, E_BLOCK_COAL_ORE = 16, E_BLOCK_LOG = 17, E_BLOCK_LEAVES = 18, E_BLOCK_SPONGE = 19, E_BLOCK_GLASS = 20, E_BLOCK_LAPIS_ORE = 21, E_BLOCK_LAPIS_BLOCK = 22, E_BLOCK_DISPENSER = 23, E_BLOCK_SANDSTONE = 24, E_BLOCK_NOTE_BLOCK = 25, E_BLOCK_BED = 26, E_BLOCK_POWERED_RAIL = 27, E_BLOCK_DETECTOR_RAIL = 28, E_BLOCK_STICKY_PISTON = 29, E_BLOCK_COBWEB = 30, E_BLOCK_TALL_GRASS = 31, E_BLOCK_DEAD_BUSH = 32, E_BLOCK_PISTON = 33, E_BLOCK_PISTON_EXTENSION = 34, E_BLOCK_WOOL = 35, E_BLOCK_PISTON_MOVED_BLOCK = 36, E_BLOCK_DANDELION = 37, E_BLOCK_FLOWER = 38, E_BLOCK_BROWN_MUSHROOM = 39, E_BLOCK_RED_MUSHROOM = 40, E_BLOCK_GOLD_BLOCK = 41, E_BLOCK_IRON_BLOCK = 42, E_BLOCK_DOUBLE_STONE_SLAB = 43, E_BLOCK_STONE_SLAB = 44, E_BLOCK_BRICK = 45, E_BLOCK_TNT = 46, E_BLOCK_BOOKCASE = 47, E_BLOCK_MOSSY_COBBLESTONE = 48, E_BLOCK_OBSIDIAN = 49, E_BLOCK_TORCH = 50, E_BLOCK_FIRE = 51, E_BLOCK_MOB_SPAWNER = 52, E_BLOCK_OAK_WOOD_STAIRS = 53, E_BLOCK_CHEST = 54, E_BLOCK_REDSTONE_WIRE = 55, E_BLOCK_DIAMOND_ORE = 56, E_BLOCK_DIAMOND_BLOCK = 57, E_BLOCK_CRAFTING_TABLE = 58, E_BLOCK_WORKBENCH = 58, E_BLOCK_WHEAT = 59, E_BLOCK_CROPS = E_BLOCK_WHEAT, E_BLOCK_FARMLAND = 60, E_BLOCK_FURNACE = 61, E_BLOCK_LIT_FURNACE = 62, E_BLOCK_BURNING_FURNACE = 62, E_BLOCK_SIGN_POST = 63, E_BLOCK_OAK_DOOR = 64, E_BLOCK_LADDER = 65, E_BLOCK_RAIL = 66, E_BLOCK_MINECART_TRACKS = 66, E_BLOCK_COBBLESTONE_STAIRS = 67, E_BLOCK_WALLSIGN = 68, E_BLOCK_LEVER = 69, E_BLOCK_STONE_PRESSURE_PLATE = 70, E_BLOCK_IRON_DOOR = 71, E_BLOCK_WOODEN_PRESSURE_PLATE = 72, E_BLOCK_REDSTONE_ORE = 73, E_BLOCK_REDSTONE_ORE_GLOWING = 74, E_BLOCK_REDSTONE_TORCH_OFF = 75, E_BLOCK_REDSTONE_TORCH_ON = 76, E_BLOCK_STONE_BUTTON = 77, E_BLOCK_SNOW = 78, E_BLOCK_ICE = 79, E_BLOCK_SNOW_BLOCK = 80, E_BLOCK_CACTUS = 81, E_BLOCK_CLAY = 82, E_BLOCK_SUGARCANE = 83, E_BLOCK_REEDS = 83, E_BLOCK_JUKEBOX = 84, E_BLOCK_FENCE = 85, E_BLOCK_PUMPKIN = 86, E_BLOCK_NETHERRACK = 87, E_BLOCK_SOULSAND = 88, E_BLOCK_GLOWSTONE = 89, E_BLOCK_NETHER_PORTAL = 90, E_BLOCK_JACK_O_LANTERN = 91, E_BLOCK_CAKE = 92, E_BLOCK_REDSTONE_REPEATER_OFF = 93, E_BLOCK_REDSTONE_REPEATER_ON = 94, E_BLOCK_STAINED_GLASS = 95, E_BLOCK_TRAPDOOR = 96, E_BLOCK_SILVERFISH_EGG = 97, E_BLOCK_STONE_BRICKS = 98, E_BLOCK_HUGE_BROWN_MUSHROOM = 99, E_BLOCK_HUGE_RED_MUSHROOM = 100, E_BLOCK_IRON_BARS = 101, E_BLOCK_GLASS_PANE = 102, E_BLOCK_MELON = 103, E_BLOCK_PUMPKIN_STEM = 104, E_BLOCK_MELON_STEM = 105, E_BLOCK_VINES = 106, E_BLOCK_OAK_FENCE_GATE = 107, E_BLOCK_BRICK_STAIRS = 108, E_BLOCK_STONE_BRICK_STAIRS = 109, E_BLOCK_MYCELIUM = 110, E_BLOCK_LILY_PAD = 111, E_BLOCK_NETHER_BRICK = 112, E_BLOCK_NETHER_BRICK_FENCE = 113, E_BLOCK_NETHER_BRICK_STAIRS = 114, E_BLOCK_NETHER_WART = 115, E_BLOCK_ENCHANTMENT_TABLE = 116, E_BLOCK_BREWING_STAND = 117, E_BLOCK_CAULDRON = 118, E_BLOCK_END_PORTAL = 119, E_BLOCK_END_PORTAL_FRAME = 120, E_BLOCK_END_STONE = 121, E_BLOCK_DRAGON_EGG = 122, E_BLOCK_REDSTONE_LAMP_OFF = 123, E_BLOCK_REDSTONE_LAMP_ON = 124, E_BLOCK_DOUBLE_WOODEN_SLAB = 125, E_BLOCK_WOODEN_SLAB = 126, E_BLOCK_COCOA_POD = 127, E_BLOCK_SANDSTONE_STAIRS = 128, E_BLOCK_EMERALD_ORE = 129, E_BLOCK_ENDER_CHEST = 130, E_BLOCK_TRIPWIRE_HOOK = 131, E_BLOCK_TRIPWIRE = 132, E_BLOCK_EMERALD_BLOCK = 133, E_BLOCK_SPRUCE_WOOD_STAIRS = 134, E_BLOCK_BIRCH_WOOD_STAIRS = 135, E_BLOCK_JUNGLE_WOOD_STAIRS = 136, E_BLOCK_COMMAND_BLOCK = 137, E_BLOCK_BEACON = 138, E_BLOCK_COBBLESTONE_WALL = 139, E_BLOCK_FLOWER_POT = 140, E_BLOCK_CARROTS = 141, E_BLOCK_POTATOES = 142, E_BLOCK_WOODEN_BUTTON = 143, E_BLOCK_HEAD = 144, E_BLOCK_ANVIL = 145, E_BLOCK_TRAPPED_CHEST = 146, E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE = 147, E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE = 148, E_BLOCK_INACTIVE_COMPARATOR = 149, E_BLOCK_ACTIVE_COMPARATOR = 150, E_BLOCK_DAYLIGHT_SENSOR = 151, E_BLOCK_BLOCK_OF_REDSTONE = 152, E_BLOCK_NETHER_QUARTZ_ORE = 153, E_BLOCK_HOPPER = 154, E_BLOCK_QUARTZ_BLOCK = 155, E_BLOCK_QUARTZ_STAIRS = 156, E_BLOCK_ACTIVATOR_RAIL = 157, E_BLOCK_DROPPER = 158, E_BLOCK_STAINED_CLAY = 159, // Synonym to terracotta E_BLOCK_TERRACOTTA = 159, // Synonym to stained clay E_BLOCK_STAINED_GLASS_PANE = 160, E_BLOCK_NEW_LEAVES = 161, // Acacia and Dark Oak IDs in Minecraft 1.7.x E_BLOCK_NEW_LOG = 162, E_BLOCK_ACACIA_WOOD_STAIRS = 163, E_BLOCK_DARK_OAK_WOOD_STAIRS = 164, E_BLOCK_SLIME_BLOCK = 165, E_BLOCK_BARRIER = 166, E_BLOCK_IRON_TRAPDOOR = 167, E_BLOCK_PRISMARINE_BLOCK = 168, E_BLOCK_SEA_LANTERN = 169, E_BLOCK_HAY_BALE = 170, E_BLOCK_CARPET = 171, E_BLOCK_HARDENED_CLAY = 172, E_BLOCK_BLOCK_OF_COAL = 173, E_BLOCK_PACKED_ICE = 174, E_BLOCK_BIG_FLOWER = 175, E_BLOCK_STANDING_BANNER = 176, E_BLOCK_WALL_BANNER = 177, E_BLOCK_INVERTED_DAYLIGHT_SENSOR = 178, E_BLOCK_RED_SANDSTONE = 179, E_BLOCK_RED_SANDSTONE_STAIRS = 180, E_BLOCK_DOUBLE_RED_SANDSTONE_SLAB = 181, E_BLOCK_RED_SANDSTONE_SLAB = 182, E_BLOCK_SPRUCE_FENCE_GATE = 183, E_BLOCK_BIRCH_FENCE_GATE = 184, E_BLOCK_JUNGLE_FENCE_GATE = 185, E_BLOCK_DARK_OAK_FENCE_GATE = 186, E_BLOCK_ACACIA_FENCE_GATE = 187, E_BLOCK_SPRUCE_FENCE = 188, E_BLOCK_BIRCH_FENCE = 189, E_BLOCK_JUNGLE_FENCE = 190, E_BLOCK_DARK_OAK_FENCE = 191, E_BLOCK_ACACIA_FENCE = 192, E_BLOCK_SPRUCE_DOOR = 193, E_BLOCK_BIRCH_DOOR = 194, E_BLOCK_JUNGLE_DOOR = 195, E_BLOCK_ACACIA_DOOR = 196, E_BLOCK_DARK_OAK_DOOR = 197, E_BLOCK_END_ROD = 198, E_BLOCK_CHORUS_PLANT = 199, E_BLOCK_CHORUS_FLOWER = 200, E_BLOCK_PURPUR_BLOCK = 201, E_BLOCK_PURPUR_PILLAR = 202, E_BLOCK_PURPUR_STAIRS = 203, E_BLOCK_PURPUR_DOUBLE_SLAB = 204, E_BLOCK_PURPUR_SLAB = 205, E_BLOCK_END_BRICKS = 206, E_BLOCK_BEETROOTS = 207, E_BLOCK_GRASS_PATH = 208, E_BLOCK_END_GATEWAY = 209, E_BLOCK_REPEATING_COMMAND_BLOCK = 210, E_BLOCK_CHAIN_COMMAND_BLOCK = 211, E_BLOCK_FROSTED_ICE = 212, E_BLOCK_MAGMA = 213, E_BLOCK_NETHER_WART_BLOCK = 214, E_BLOCK_RED_NETHER_BRICK = 215, E_BLOCK_BONE_BLOCK = 216, E_BLOCK_STRUCTURE_VOID = 217, E_BLOCK_OBSERVER = 218, E_BLOCK_WHITE_SHULKER_BOX = 219, E_BLOCK_ORANGE_SHULKER_BOX = 220, E_BLOCK_MAGENTA_SHULKER_BOX = 221, E_BLOCK_LIGHT_BLUE_SHULKER_BOX = 222, E_BLOCK_YELLOW_SHULKER_BOX = 223, E_BLOCK_LIME_SHULKER_BOX = 224, E_BLOCK_PINK_SHULKER_BOX = 225, E_BLOCK_GRAY_SHULKER_BOX = 226, E_BLOCK_LIGHT_GRAY_SHULKER_BOX = 227, E_BLOCK_CYAN_SHULKER_BOX = 228, E_BLOCK_PURPLE_SHULKER_BOX = 229, E_BLOCK_BLUE_SHULKER_BOX = 230, E_BLOCK_BROWN_SHULKER_BOX = 231, E_BLOCK_GREEN_SHULKER_BOX = 232, E_BLOCK_RED_SHULKER_BOX = 233, E_BLOCK_BLACK_SHULKER_BOX = 234, E_BLOCK_WHITE_GLAZED_TERRACOTTA = 235, E_BLOCK_ORANGE_GLAZED_TERRACOTTA = 236, E_BLOCK_MAGENTA_GLAZED_TERRACOTTA = 237, E_BLOCK_LIGHT_BLUE_GLAZED_TERRACOTTA = 238, E_BLOCK_YELLOW_GLAZED_TERRACOTTA = 239, E_BLOCK_LIME_GLAZED_TERRACOTTA = 240, E_BLOCK_PINK_GLAZED_TERRACOTTA = 241, E_BLOCK_GRAY_GLAZED_TERRACOTTA = 242, E_BLOCK_LIGHT_GRAY_GLAZED_TERRACOTTA = 243, E_BLOCK_CYAN_GLAZED_TERRACOTTA = 244, E_BLOCK_PURPLE_GLAZED_TERRACOTTA = 245, E_BLOCK_BLUE_GLAZED_TERRACOTTA = 246, E_BLOCK_BROWN_GLAZED_TERRACOTTA = 247, E_BLOCK_GREEN_GLAZED_TERRACOTTA = 248, E_BLOCK_RED_GLAZED_TERRACOTTA = 249, E_BLOCK_BLACK_GLAZED_TERRACOTTA = 250, E_BLOCK_CONCRETE = 251, E_BLOCK_CONCRETE_POWDER = 252, // ... E_BLOCK_STRUCTURE_BLOCK = 255, // Keep these two as the last values. Update the last block value to the last block with an id less than 255 when adding another block // IsValidBlock() depends on this (255 gets checked additionally because there is a gap. See https://minecraft.wiki/w/Data_values#Block_IDs E_BLOCK_NUMBER_OF_TYPES = E_BLOCK_CONCRETE_POWDER + 1, ///< Number of individual (different) blocktypes E_BLOCK_MAX_TYPE_ID = E_BLOCK_NUMBER_OF_TYPES - 1, ///< Maximum BlockType number used E_BLOCK_UNFINISHED = 254, // Special type used as a placeholder, signifying that the block lacks implementation // Synonym or ID compatibility E_BLOCK_YELLOW_FLOWER = E_BLOCK_DANDELION, E_BLOCK_RED_ROSE = E_BLOCK_FLOWER, E_BLOCK_WOODEN_DOOR = E_BLOCK_OAK_DOOR, E_BLOCK_FENCE_GATE = E_BLOCK_OAK_FENCE_GATE, E_BLOCK_WOODEN_STAIRS = E_BLOCK_OAK_WOOD_STAIRS, }; enum ENUM_ITEM_TYPE : short { E_ITEM_EMPTY = -1, E_ITEM_FIRST = 256, // First true item type E_ITEM_IRON_SHOVEL = 256, E_ITEM_IRON_PICKAXE = 257, E_ITEM_IRON_AXE = 258, E_ITEM_FLINT_AND_STEEL = 259, E_ITEM_RED_APPLE = 260, E_ITEM_BOW = 261, E_ITEM_ARROW = 262, E_ITEM_COAL = 263, E_ITEM_DIAMOND = 264, E_ITEM_IRON = 265, E_ITEM_GOLD = 266, E_ITEM_IRON_SWORD = 267, E_ITEM_WOODEN_SWORD = 268, E_ITEM_WOODEN_SHOVEL = 269, E_ITEM_WOODEN_PICKAXE = 270, E_ITEM_WOODEN_AXE = 271, E_ITEM_STONE_SWORD = 272, E_ITEM_STONE_SHOVEL = 273, E_ITEM_STONE_PICKAXE = 274, E_ITEM_STONE_AXE = 275, E_ITEM_DIAMOND_SWORD = 276, E_ITEM_DIAMOND_SHOVEL = 277, E_ITEM_DIAMOND_PICKAXE = 278, E_ITEM_DIAMOND_AXE = 279, E_ITEM_STICK = 280, E_ITEM_BOWL = 281, E_ITEM_MUSHROOM_SOUP = 282, E_ITEM_GOLD_SWORD = 283, E_ITEM_GOLD_SHOVEL = 284, E_ITEM_GOLD_PICKAXE = 285, E_ITEM_GOLD_AXE = 286, E_ITEM_STRING = 287, E_ITEM_FEATHER = 288, E_ITEM_GUNPOWDER = 289, E_ITEM_WOODEN_HOE = 290, E_ITEM_STONE_HOE = 291, E_ITEM_IRON_HOE = 292, E_ITEM_DIAMOND_HOE = 293, E_ITEM_GOLD_HOE = 294, E_ITEM_SEEDS = 295, E_ITEM_WHEAT = 296, E_ITEM_BREAD = 297, E_ITEM_LEATHER_CAP = 298, E_ITEM_LEATHER_TUNIC = 299, E_ITEM_LEATHER_PANTS = 300, E_ITEM_LEATHER_BOOTS = 301, E_ITEM_CHAIN_HELMET = 302, E_ITEM_CHAIN_CHESTPLATE = 303, E_ITEM_CHAIN_LEGGINGS = 304, E_ITEM_CHAIN_BOOTS = 305, E_ITEM_IRON_HELMET = 306, E_ITEM_IRON_CHESTPLATE = 307, E_ITEM_IRON_LEGGINGS = 308, E_ITEM_IRON_BOOTS = 309, E_ITEM_DIAMOND_HELMET = 310, E_ITEM_DIAMOND_CHESTPLATE = 311, E_ITEM_DIAMOND_LEGGINGS = 312, E_ITEM_DIAMOND_BOOTS = 313, E_ITEM_GOLD_HELMET = 314, E_ITEM_GOLD_CHESTPLATE = 315, E_ITEM_GOLD_LEGGINGS = 316, E_ITEM_GOLD_BOOTS = 317, E_ITEM_FLINT = 318, E_ITEM_RAW_PORKCHOP = 319, E_ITEM_COOKED_PORKCHOP = 320, E_ITEM_PAINTING = 321, E_ITEM_GOLDEN_APPLE = 322, E_ITEM_SIGN = 323, E_ITEM_WOODEN_DOOR = 324, E_ITEM_BUCKET = 325, E_ITEM_WATER_BUCKET = 326, E_ITEM_LAVA_BUCKET = 327, E_ITEM_MINECART = 328, E_ITEM_SADDLE = 329, E_ITEM_IRON_DOOR = 330, E_ITEM_REDSTONE_DUST = 331, E_ITEM_SNOWBALL = 332, E_ITEM_BOAT = 333, E_ITEM_LEATHER = 334, E_ITEM_MILK = 335, E_ITEM_CLAY_BRICK = 336, E_ITEM_CLAY = 337, E_ITEM_SUGARCANE = 338, E_ITEM_SUGAR_CANE = 338, E_ITEM_PAPER = 339, E_ITEM_BOOK = 340, E_ITEM_SLIMEBALL = 341, E_ITEM_CHEST_MINECART = 342, E_ITEM_FURNACE_MINECART = 343, E_ITEM_EGG = 344, E_ITEM_COMPASS = 345, E_ITEM_FISHING_ROD = 346, E_ITEM_CLOCK = 347, E_ITEM_GLOWSTONE_DUST = 348, E_ITEM_RAW_FISH = 349, E_ITEM_COOKED_FISH = 350, E_ITEM_DYE = 351, E_ITEM_BONE = 352, E_ITEM_SUGAR = 353, E_ITEM_CAKE = 354, E_ITEM_BED = 355, E_ITEM_REDSTONE_REPEATER = 356, E_ITEM_COOKIE = 357, E_ITEM_MAP = 358, E_ITEM_SHEARS = 359, E_ITEM_MELON_SLICE = 360, E_ITEM_PUMPKIN_SEEDS = 361, E_ITEM_MELON_SEEDS = 362, E_ITEM_RAW_BEEF = 363, E_ITEM_STEAK = 364, E_ITEM_RAW_CHICKEN = 365, E_ITEM_COOKED_CHICKEN = 366, E_ITEM_ROTTEN_FLESH = 367, E_ITEM_ENDER_PEARL = 368, E_ITEM_BLAZE_ROD = 369, E_ITEM_GHAST_TEAR = 370, E_ITEM_GOLD_NUGGET = 371, E_ITEM_NETHER_WART = 372, E_ITEM_POTION = 373, E_ITEM_POTIONS = 373, // OBSOLETE, use E_ITEM_POTION instead E_ITEM_GLASS_BOTTLE = 374, E_ITEM_SPIDER_EYE = 375, E_ITEM_FERMENTED_SPIDER_EYE = 376, E_ITEM_BLAZE_POWDER = 377, E_ITEM_MAGMA_CREAM = 378, E_ITEM_BREWING_STAND = 379, E_ITEM_CAULDRON = 380, E_ITEM_EYE_OF_ENDER = 381, E_ITEM_GLISTERING_MELON = 382, E_ITEM_SPAWN_EGG = 383, E_ITEM_BOTTLE_O_ENCHANTING = 384, E_ITEM_FIRE_CHARGE = 385, E_ITEM_BOOK_AND_QUILL = 386, E_ITEM_WRITTEN_BOOK = 387, E_ITEM_EMERALD = 388, E_ITEM_ITEM_FRAME = 389, E_ITEM_FLOWER_POT = 390, E_ITEM_CARROT = 391, E_ITEM_POTATO = 392, E_ITEM_BAKED_POTATO = 393, E_ITEM_POISONOUS_POTATO = 394, E_ITEM_EMPTY_MAP = 395, E_ITEM_GOLDEN_CARROT = 396, E_ITEM_HEAD = 397, E_ITEM_CARROT_ON_STICK = 398, E_ITEM_NETHER_STAR = 399, E_ITEM_PUMPKIN_PIE = 400, E_ITEM_FIREWORK_ROCKET = 401, E_ITEM_FIREWORK_STAR = 402, E_ITEM_ENCHANTED_BOOK = 403, E_ITEM_COMPARATOR = 404, E_ITEM_NETHER_BRICK = 405, E_ITEM_NETHER_QUARTZ = 406, E_ITEM_MINECART_WITH_TNT = 407, E_ITEM_MINECART_WITH_HOPPER = 408, E_ITEM_PRISMARINE_SHARD = 409, E_ITEM_PRISMARINE_CRYSTALS = 410, E_ITEM_RAW_RABBIT = 411, E_ITEM_COOKED_RABBIT = 412, E_ITEM_RABBIT_STEW = 413, E_ITEM_RABBITS_FOOT = 414, E_ITEM_RABBIT_HIDE = 415, E_ITEM_ARMOR_STAND = 416, E_ITEM_IRON_HORSE_ARMOR = 417, E_ITEM_GOLD_HORSE_ARMOR = 418, E_ITEM_DIAMOND_HORSE_ARMOR = 419, E_ITEM_LEAD = 420, E_ITEM_LEASH = E_ITEM_LEAD, E_ITEM_NAME_TAG = 421, E_ITEM_MINECART_WITH_COMMAND_BLOCK = 422, E_ITEM_RAW_MUTTON = 423, E_ITEM_COOKED_MUTTON = 424, E_ITEM_BANNER = 425, E_ITEM_END_CRYSTAL = 426, E_ITEM_SPRUCE_DOOR = 427, E_ITEM_BIRCH_DOOR = 428, E_ITEM_JUNGLE_DOOR = 429, E_ITEM_ACACIA_DOOR = 430, E_ITEM_DARK_OAK_DOOR = 431, E_ITEM_CHORUS_FRUIT = 432, E_ITEM_POPPED_CHORUS_FRUIT = 433, E_ITEM_BEETROOT = 434, E_ITEM_BEETROOT_SEEDS = 435, E_ITEM_BEETROOT_SOUP = 436, E_ITEM_DRAGON_BREATH = 437, E_ITEM_SPLASH_POTION = 438, E_ITEM_SPECTRAL_ARROW = 439, E_ITEM_TIPPED_ARROW = 440, E_ITEM_LINGERING_POTION = 441, E_ITEM_SHIELD = 442, E_ITEM_ELYTRA = 443, E_ITEM_SPRUCE_BOAT = 444, E_ITEM_BIRCH_BOAT = 445, E_ITEM_JUNGLE_BOAT = 446, E_ITEM_ACACIA_BOAT = 447, E_ITEM_DARK_OAK_BOAT = 448, E_ITEM_TOTEM_OF_UNDYING = 449, E_ITEM_SHULKER_SHELL = 450, E_ITEM_IRON_NUGGET = 452, // Keep these two as the last values of the consecutive list, without a number - they will get their correct number assigned automagically by C++ // IsValidItem() depends on this! E_ITEM_NUMBER_OF_CONSECUTIVE_TYPES, ///< Number of individual (different) consecutive itemtypes E_ITEM_MAX_CONSECUTIVE_TYPE_ID = E_ITEM_NUMBER_OF_CONSECUTIVE_TYPES - 1, ///< Maximum consecutive ItemType number used E_ITEM_FIRST_DISC = 2256, E_ITEM_13_DISC = 2256, E_ITEM_CAT_DISC = 2257, E_ITEM_BLOCKS_DISC = 2258, E_ITEM_CHIRP_DISC = 2259, E_ITEM_FAR_DISC = 2260, E_ITEM_MALL_DISC = 2261, E_ITEM_MELLOHI_DISC = 2262, E_ITEM_STAL_DISC = 2263, E_ITEM_STRAD_DISC = 2264, E_ITEM_WARD_DISC = 2265, E_ITEM_11_DISC = 2266, E_ITEM_WAIT_DISC = 2267, // Keep these two as the last values of the disc list, without a number - they will get their correct number assigned automagically by C++ // IsValidItem() depends on this! E_ITEM_LAST_DISC_PLUS_ONE, ///< Useless, really, but needs to be present for the following value E_ITEM_LAST_DISC = E_ITEM_LAST_DISC_PLUS_ONE - 1, ///< Maximum disc itemtype number used E_ITEM_LAST = E_ITEM_LAST_DISC, ///< Maximum valid ItemType }; enum ENUM_BLOCK_META : NIBBLETYPE { // Please keep this list alpha-sorted by the blocktype part // then number-sorted for the same block //////////////////////////////////////////////////////////////////////////////// // Block metas: // E_BLOCK_ANVIL metas E_BLOCK_ANVIL_Z = 0, E_BLOCK_ANVIL_X = 1, E_BLOCK_ANVIL_NO_DAMAGE = 0, E_BLOCK_ANVIL_LOW_DAMAGE = 4, E_BLOCK_ANVIL_HIGH_DAMAGE = 8, // E_BLOCK_BED metas: E_BLOCK_BED_ZP = 0, E_BLOCK_BED_XM = 1, E_BLOCK_BED_ZM = 2, E_BLOCK_BED_XP = 3, E_BLOCK_BED_OCCUPIED = 4, E_BLOCK_BED_BED_HEAD = 8, // E_BLOCK_BIG_FLOWER metas: E_META_BIG_FLOWER_SUNFLOWER = 0, E_META_BIG_FLOWER_LILAC = 1, E_META_BIG_FLOWER_DOUBLE_TALL_GRASS = 2, E_META_BIG_FLOWER_LARGE_FERN = 3, E_META_BIG_FLOWER_ROSE_BUSH = 4, E_META_BIG_FLOWER_PEONY = 5, // 0x8 is supposedly a bit flag but all vanilla plants have this value E_META_BIG_FLOWER_TOP = 10, // E_BLOCK_BREWING_STAND metas E_META_BREWING_STAND_FILLED_SLOT_XP = 1, E_META_BREWING_STAND_FILLED_SLOT_XM_ZP = 2, E_META_BREWING_STAND_FILLED_SLOT_XM_ZM = 4, // E_BLOCK_BUTTON metas E_BLOCK_BUTTON_YM = 0, E_BLOCK_BUTTON_XP = 1, E_BLOCK_BUTTON_XM = 2, E_BLOCK_BUTTON_ZP = 3, E_BLOCK_BUTTON_ZM = 4, E_BLOCK_BUTTON_YP = 5, E_BLOCK_BUTTON_PRESSED = 8, // E_BLOCK_CARPET metas: E_META_CARPET_WHITE = 0, E_META_CARPET_ORANGE = 1, E_META_CARPET_MAGENTA = 2, E_META_CARPET_LIGHTBLUE = 3, E_META_CARPET_YELLOW = 4, E_META_CARPET_LIGHTGREEN = 5, E_META_CARPET_PINK = 6, E_META_CARPET_GRAY = 7, E_META_CARPET_LIGHTGRAY = 8, E_META_CARPET_CYAN = 9, E_META_CARPET_PURPLE = 10, E_META_CARPET_BLUE = 11, E_META_CARPET_BROWN = 12, E_META_CARPET_GREEN = 13, E_META_CARPET_RED = 14, E_META_CARPET_BLACK = 15, // E_BLOCK_CHEST metas: E_META_CHEST_FACING_ZM = 2, E_META_CHEST_FACING_ZP = 3, E_META_CHEST_FACING_XM = 4, E_META_CHEST_FACING_XP = 5, // E_BLOCK_CONCRETE metas: E_META_CONCRETE_WHITE = 0, E_META_CONCRETE_ORANGE = 1, E_META_CONCRETE_MAGENTA = 2, E_META_CONCRETE_LIGHTBLUE = 3, E_META_CONCRETE_YELLOW = 4, E_META_CONCRETE_LIGHTGREEN = 5, E_META_CONCRETE_PINK = 6, E_META_CONCRETE_GRAY = 7, E_META_CONCRETE_LIGHTGRAY = 8, E_META_CONCRETE_CYAN = 9, E_META_CONCRETE_PURPLE = 10, E_META_CONCRETE_BLUE = 11, E_META_CONCRETE_BROWN = 12, E_META_CONCRETE_GREEN = 13, E_META_CONCRETE_RED = 14, E_META_CONCRETE_BLACK = 15, // E_BLOCK_CONCRETE_POWDER metas: E_META_CONCRETE_POWDER_WHITE = 0, E_META_CONCRETE_POWDER_ORANGE = 1, E_META_CONCRETE_POWDER_MAGENTA = 2, E_META_CONCRETE_POWDER_LIGHTBLUE = 3, E_META_CONCRETE_POWDER_YELLOW = 4, E_META_CONCRETE_POWDER_LIGHTGREEN = 5, E_META_CONCRETE_POWDER_PINK = 6, E_META_CONCRETE_POWDER_GRAY = 7, E_META_CONCRETE_POWDER_LIGHTGRAY = 8, E_META_CONCRETE_POWDER_CYAN = 9, E_META_CONCRETE_POWDER_PURPLE = 10, E_META_CONCRETE_POWDER_BLUE = 11, E_META_CONCRETE_POWDER_BROWN = 12, E_META_CONCRETE_POWDER_GREEN = 13, E_META_CONCRETE_POWDER_RED = 14, E_META_CONCRETE_POWDER_BLACK = 15, // E_BLOCK_DIRT metas: E_META_DIRT_NORMAL = 0, E_META_DIRT_GRASSLESS = 1, E_META_DIRT_COARSE = 1, E_META_DIRT_PODZOL = 2, // E_BLOCK_DISPENSER / E_BLOCK_DROPPER metas: E_META_DROPSPENSER_FACING_YM = 0, E_META_DROPSPENSER_FACING_YP = 1, E_META_DROPSPENSER_FACING_ZM = 2, E_META_DROPSPENSER_FACING_ZP = 3, E_META_DROPSPENSER_FACING_XM = 4, E_META_DROPSPENSER_FACING_XP = 5, E_META_DROPSPENSER_FACING_MASK = 7, E_META_DROPSPENSER_ACTIVATED = 8, // E_BLOCK_DOUBLE_STONE_SLAB metas: E_META_DOUBLE_STONE_SLAB_STONE = 0, E_META_DOUBLE_STONE_SLAB_SANDSTON = 1, E_META_DOUBLE_STONE_SLAB_WOODEN = 2, E_META_DOUBLE_STONE_SLAB_COBBLESTONE = 3, E_META_DOUBLE_STONE_SLAB_BRICK = 4, E_META_DOUBLE_STONE_SLAB_STONE_BRICK = 5, E_META_DOUBLE_STONE_SLAB_NETHER_BRICK = 6, E_META_DOUBLE_STONE_SLAB_QUARTZ = 7, E_META_DOUBLE_STONE_SLAB_SMOOTH_STONE = 8, E_META_DOUBLE_STONE_SLAB_SMOOTH_SANDSTONE = 9, E_META_DOUBLE_STONE_SLAB_TILE_QUARTZ = 10, // E_BLOCK_END_PORTAL_FRAME metas: E_META_END_PORTAL_FRAME_ZP = 0, // Faces towards centre of portal E_META_END_PORTAL_FRAME_XM = 1, E_META_END_PORTAL_FRAME_ZM = 2, E_META_END_PORTAL_FRAME_XP = 3, E_META_END_PORTAL_FRAME_ZP_EYE = 4, // Frames with ender eye E_META_END_PORTAL_FRAME_XM_EYE = 5, E_META_END_PORTAL_FRAME_ZM_EYE = 6, E_META_END_PORTAL_FRAME_XP_EYE = 7, E_META_END_PORTAL_FRAME_NO_EYE = 0, // Just the eye bitflag E_META_END_PORTAL_FRAME_EYE = 4, // E_BLOCK_FLOWER metas: E_META_FLOWER_POPPY = 0, E_META_FLOWER_BLUE_ORCHID = 1, E_META_FLOWER_ALLIUM = 2, E_META_FLOWER_RED_TULIP = 4, E_META_FLOWER_ORANGE_TULIP = 5, E_META_FLOWER_WHITE_TULIP = 6, E_META_FLOWER_PINK_TULIP = 7, E_META_FLOWER_OXEYE_DAISY = 8, // E_BLOCK_JUKEBOX metas: E_META_JUKEBOX_OFF = 0, E_META_JUKEBOX_ON = 1, // E_BLOCK_HOPPER metas: E_META_HOPPER_FACING_YM = 0, E_META_HOPPER_UNATTACHED = 1, // Hopper doesn't move items up, there's no YP E_META_HOPPER_FACING_ZM = 2, E_META_HOPPER_FACING_ZP = 3, E_META_HOPPER_FACING_XM = 4, E_META_HOPPER_FACING_XP = 5, // E_BLOCK_LEAVES metas: E_META_LEAVES_APPLE = 0, E_META_LEAVES_CONIFER = 1, E_META_LEAVES_BIRCH = 2, E_META_LEAVES_JUNGLE = 3, E_META_LEAVES_APPLE_NO_DECAY = 4, E_META_LEAVES_CONIFER_NO_DECAY = 5, E_META_LEAVES_BIRCH_NO_DECAY = 6, E_META_LEAVES_JUNGLE_NO_DECAY = 7, E_META_LEAVES_APPLE_CHECK_DECAY = 8, E_META_LEAVES_CONIFER_CHECK_DECAY = 9, E_META_LEAVES_BIRCH_CHECK_DECAY = 10, E_META_LEAVES_JUNGLE_CHECK_DECAY = 11, // E_BLOCK_MUSHROOM metas: E_META_MUSHROOM_ALL_SIDES = 0, E_META_MUSHROOM_NORTH_WEST = 1, E_META_MUSHROOM_NORTH = 2, E_META_MUSHROOM_NORTH_EAST = 3, E_META_MUSHROOM_WEST = 4, E_META_MUSHROOM_CENTER = 5, E_META_MUSHROOM_EAST = 6, E_META_MUSHROOM_SOUTH_WEST = 7, E_META_MUSHROOM_SOUTH = 8, E_META_MUSHROOM_SOUTH_EAST = 9, E_META_MUSHROOM_STEM = 10, E_META_MUSHROOM_CAP = 14, E_META_MUSHROOM_FULL_STEM = 15, // E_BLOCK_LEAVES meta cont. (Block ID 161): E_META_NEWLEAVES_ACACIA = 0, E_META_NEWLEAVES_DARK_OAK = 1, E_META_NEWLEAVES_ACACIA_NO_DECAY = 4, E_META_NEWLEAVES_DARK_OAK_NO_DECAY = 5, E_META_NEWLEAVES_ACACIA_CHECK_DECAY = 8, E_META_NEWLEAVES_DARK_OAK_CHECK_DECAY = 9, // E_BLOCK_LOG metas: E_META_LOG_APPLE = 0, E_META_LOG_CONIFER = 1, E_META_LOG_BIRCH = 2, E_META_LOG_JUNGLE = 3, // E_BLOCK_NEW_LOG metas: E_META_NEW_LOG_ACACIA_WOOD = 0, E_META_NEW_LOG_DARK_OAK_WOOD = 1, // E_BLOCK_PISTON metas: E_META_PISTON_DOWN = 0, E_META_PISTON_U = 1, E_META_PISTON_ZM = 2, E_META_PISTON_ZP = 3, E_META_PISTON_XM = 4, E_META_PISTON_XP = 5, E_META_PISTON_HEAD_STICKY = 8, E_META_PISTON_EXTENDED = 8, // E_BLOCK_PLANKS metas: E_META_PLANKS_OAK = 0, E_META_PLANKS_SPRUCE = 1, E_META_PLANKS_BIRCH = 2, E_META_PLANKS_JUNGLE = 3, E_META_PLANKS_ACACIA = 4, E_META_PLANKS_DARK_OAK = 5, // E_BLOCK_(XXX_WEIGHTED)_PRESSURE_PLATE metas: E_META_PRESSURE_PLATE_RAISED = 0, E_META_PRESSURE_PLATE_DEPRESSED = 1, // E_BLOCK_PRISMARINE_BLOCK metas: E_META_PRISMARINE_BLOCK_ROUGH = 0, E_META_PRISMARINE_BLOCK_BRICKS = 1, E_META_PRISMARINE_BLOCK_DARK = 2, // E_BLOCK_QUARTZ_BLOCK metas: E_META_QUARTZ_NORMAL = 0, E_META_QUARTZ_CHISELLED = 1, E_META_QUARTZ_PILLAR = 2, // E_BLOCK_RAIL metas E_META_RAIL_ZM_ZP = 0, E_META_RAIL_XM_XP = 1, E_META_RAIL_ASCEND_XP = 2, E_META_RAIL_ASCEND_XM = 3, E_META_RAIL_ASCEND_ZM = 4, E_META_RAIL_ASCEND_ZP = 5, E_META_RAIL_CURVED_ZP_XP = 6, E_META_RAIL_CURVED_ZP_XM = 7, E_META_RAIL_CURVED_ZM_XM = 8, E_META_RAIL_CURVED_ZM_XP = 9, // E_BLOCK_RED_SANDSTONE metas: E_META_RED_SANDSTONE_NORMAL = 0, E_META_RED_SANDSTONE_ORNAMENT = 1, E_META_RED_SANDSTONE_SMOOTH = 2, // E_BLOCK_REDSTONE_REPEATER_ON / E_BLOCK_REDSTONE_REPEATER_OFF metas: E_META_REDSTONE_REPEATER_FACING_ZM = 0, E_META_REDSTONE_REPEATER_FACING_XP = 1, E_META_REDSTONE_REPEATER_FACING_ZP = 2, E_META_REDSTONE_REPEATER_FACING_XM = 3, E_META_REDSTONE_REPEATER_FACING_MASK = 3, // E_BLOCK_SAND metas: E_META_SAND_NORMAL = 0, E_META_SAND_RED = 1, // E_BLOCK_SANDSTONE metas: E_META_SANDSTONE_NORMAL = 0, E_META_SANDSTONE_ORNAMENT = 1, E_META_SANDSTONE_SMOOTH = 2, // E_BLOCK_SAPLING metas (lowest 3 bits): E_META_SAPLING_APPLE = 0, E_META_SAPLING_CONIFER = 1, E_META_SAPLING_BIRCH = 2, E_META_SAPLING_JUNGLE = 3, E_META_SAPLING_ACACIA = 4, E_META_SAPLING_DARK_OAK = 5, // E_BLOCK_SILVERFISH_EGG metas: E_META_SILVERFISH_EGG_STONE = 0, E_META_SILVERFISH_EGG_COBBLESTONE = 1, E_META_SILVERFISH_EGG_STONE_BRICK = 2, E_META_SILVERFISH_EGG_MOSSY_STONE_BRICK = 3, E_META_SILVERFISH_EGG_CRACKED_STONE_BRICK = 4, E_META_SILVERFISH_EGG_CHISELED_STONE_BRICK = 5, // E_BLOCK_SNOW metas: E_META_SNOW_LAYER_ONE = 0, E_META_SNOW_LAYER_TWO = 1, E_META_SNOW_LAYER_THREE = 2, E_META_SNOW_LAYER_FOUR = 3, E_META_SNOW_LAYER_FIVE = 4, E_META_SNOW_LAYER_SIX = 5, E_META_SNOW_LAYER_SEVEN = 6, E_META_SNOW_LAYER_EIGHT = 7, // E_BLOCK_SPONGE metas: E_META_SPONGE_DRY = 0, E_META_SPONGE_WET = 1, // E_BLOCK_STAINED_CLAY metas: E_META_STAINED_CLAY_WHITE = 0, E_META_STAINED_CLAY_ORANGE = 1, E_META_STAINED_CLAY_MAGENTA = 2, E_META_STAINED_CLAY_LIGHTBLUE = 3, E_META_STAINED_CLAY_YELLOW = 4, E_META_STAINED_CLAY_LIGHTGREEN = 5, E_META_STAINED_CLAY_PINK = 6, E_META_STAINED_CLAY_GRAY = 7, E_META_STAINED_CLAY_LIGHTGRAY = 8, E_META_STAINED_CLAY_CYAN = 9, E_META_STAINED_CLAY_PURPLE = 10, E_META_STAINED_CLAY_BLUE = 11, E_META_STAINED_CLAY_BROWN = 12, E_META_STAINED_CLAY_GREEN = 13, E_META_STAINED_CLAY_RED = 14, E_META_STAINED_CLAY_BLACK = 15, // E_BLOCK_STAINED_GLASS metas: E_META_STAINED_GLASS_WHITE = 0, E_META_STAINED_GLASS_ORANGE = 1, E_META_STAINED_GLASS_MAGENTA = 2, E_META_STAINED_GLASS_LIGHTBLUE = 3, E_META_STAINED_GLASS_YELLOW = 4, E_META_STAINED_GLASS_LIGHTGREEN = 5, E_META_STAINED_GLASS_PINK = 6, E_META_STAINED_GLASS_GRAY = 7, E_META_STAINED_GLASS_LIGHTGRAY = 8, E_META_STAINED_GLASS_CYAN = 9, E_META_STAINED_GLASS_PURPLE = 10, E_META_STAINED_GLASS_BLUE = 11, E_META_STAINED_GLASS_BROWN = 12, E_META_STAINED_GLASS_GREEN = 13, E_META_STAINED_GLASS_RED = 14, E_META_STAINED_GLASS_BLACK = 15, // E_BLOCK_STAINED_GLASS_PANE metas: E_META_STAINED_GLASS_PANE_WHITE = 0, E_META_STAINED_GLASS_PANE_ORANGE = 1, E_META_STAINED_GLASS_PANE_MAGENTA = 2, E_META_STAINED_GLASS_PANE_LIGHTBLUE = 3, E_META_STAINED_GLASS_PANE_YELLOW = 4, E_META_STAINED_GLASS_PANE_LIGHTGREEN = 5, E_META_STAINED_GLASS_PANE_PINK = 6, E_META_STAINED_GLASS_PANE_GRAY = 7, E_META_STAINED_GLASS_PANE_LIGHTGRAY = 8, E_META_STAINED_GLASS_PANE_CYAN = 9, E_META_STAINED_GLASS_PANE_PURPLE = 10, E_META_STAINED_GLASS_PANE_BLUE = 11, E_META_STAINED_GLASS_PANE_BROWN = 12, E_META_STAINED_GLASS_PANE_GREEN = 13, E_META_STAINED_GLASS_PANE_RED = 14, E_META_STAINED_GLASS_PANE_BLACK = 15, // E_BLOCK_STAIRS metas: E_BLOCK_STAIRS_XP = 0, E_BLOCK_STAIRS_XM = 1, E_BLOCK_STAIRS_ZP = 2, E_BLOCK_STAIRS_ZM = 3, E_BLOCK_STAIRS_UPSIDE_DOWN = 4, // E_BLOCK_STONE metas: E_META_STONE_STONE = 0, E_META_STONE_GRANITE = 1, E_META_STONE_POLISHED_GRANITE = 2, E_META_STONE_DIORITE = 3, E_META_STONE_POLISHED_DIORITE = 4, E_META_STONE_ANDESITE = 5, E_META_STONE_POLISHED_ANDESITE = 6, // E_BLOCK_STONE_SLAB metas: E_META_STONE_SLAB_STONE = 0, E_META_STONE_SLAB_SANDSTONE = 1, E_META_STONE_SLAB_PLANKS = 2, E_META_STONE_SLAB_COBBLESTONE = 3, E_META_STONE_SLAB_BRICK = 4, E_META_STONE_SLAB_STONE_BRICK = 5, E_META_STONE_SLAB_NETHER_BRICK = 6, E_META_STONE_SLAB_QUARTZ = 7, // E_BLOCK_STONE_BRICKS metas: E_META_STONE_BRICK_NORMAL = 0, E_META_STONE_BRICK_MOSSY = 1, E_META_STONE_BRICK_CRACKED = 2, E_META_STONE_BRICK_ORNAMENT = 3, // E_BLOCK_TALL_GRASS metas: E_META_TALL_GRASS_DEAD_SHRUB = 0, E_META_TALL_GRASS_GRASS = 1, E_META_TALL_GRASS_FERN = 2, E_META_TALL_GRASS_BIOME = 3, // E_BLOCK_TORCH, E_BLOCK_REDSTONE_TORCH_OFF, E_BLOCK_REDSTONE_TORCH_ON metas: E_META_TORCH_EAST = 1, // east face of the block, pointing east E_META_TORCH_WEST = 2, E_META_TORCH_SOUTH = 3, E_META_TORCH_NORTH = 4, E_META_TORCH_FLOOR = 5, E_META_TORCH_XM = 1, // Torch attached to the XM side of its block E_META_TORCH_XP = 2, // Torch attached to the XP side of its block E_META_TORCH_ZM = 3, // Torch attached to the ZM side of its block E_META_TORCH_ZP = 4, // Torch attached to the ZP side of its block // E_META_LOG metas: E_META_LOG_OAK_UP_DOWN = 0, E_META_LOG_SPRUCE_UP_DOWN = 1, E_META_LOG_BIRCH_UP_DOWN = 2, E_META_LOG_JUNGLE_UP_DOWN = 3, E_META_LOG_OAK_X = 4, E_META_LOG_SPRUCE_X = 5, E_META_LOG_BIRCH_X = 6, E_META_LOG_JUNGLE_X = 7, E_META_LOG_OAK_Z = 8, E_META_LOG_SPRUCE_Z = 9, E_META_LOG_BIRCH_Z = 10, E_META_LOG_JUNGLE_Z = 11, E_META_LOG_OAK_BARK_ONLY = 12, E_META_LOG_SPRUCE_BARK_ONLY = 13, E_META_LOG_BIRCH_BARK_ONLY = 14, E_META_LOG_JUNGLE_BARK_ONLY = 15, // E_META_LOG metas cont. (Block ID 162): E_META_NEWLOG_ACACIA_UP_DOWN = 0, E_META_NEWLOG_DARK_OAK_UP_DOWN = 1, E_META_NEWLOG_ACACIA_X = 4, E_META_NEWLOG_DARK_OAK_X = 5, E_META_NEWLOG_ACACIA_Z = 8, E_META_NEWLOG_DARK_OAK_Z = 9, E_META_NEWLOG_ACACIA_BARK_ONLY = 12, E_META_NEWLOG_DARK_OAK_BARK_ONLY = 13, // E_BLOCK_WOODEN_DOUBLE_SLAB metas: E_META_WOODEN_DOUBLE_SLAB_OAK = 0, E_META_WOODEN_DOUBLE_SLAB_SPRUCE = 1, E_META_WOODEN_DOUBLE_SLAB_BIRCH = 2, E_META_WOODEN_DOUBLE_SLAB_JUNGLE = 3, E_META_WOODEN_DOUBLE_SLAB_ACACIA = 4, E_META_WOODEN_DOUBLE_SLAB_DARK_OAK = 5, // E_BLOCK_WOODEN_SLAB metas: E_META_WOODEN_SLAB_OAK = 0, E_META_WOODEN_SLAB_SPRUCE = 1, E_META_WOODEN_SLAB_BIRCH = 2, E_META_WOODEN_SLAB_JUNGLE = 3, E_META_WOODEN_SLAB_ACACIA = 4, E_META_WOODEN_SLAB_DARK_OAK = 5, E_META_WOODEN_SLAB_UPSIDE_DOWN = 8, // E_BLOCK_WOOL metas: E_META_WOOL_WHITE = 0, E_META_WOOL_ORANGE = 1, E_META_WOOL_MAGENTA = 2, E_META_WOOL_LIGHTBLUE = 3, E_META_WOOL_YELLOW = 4, E_META_WOOL_LIGHTGREEN = 5, E_META_WOOL_PINK = 6, E_META_WOOL_GRAY = 7, E_META_WOOL_LIGHTGRAY = 8, E_META_WOOL_CYAN = 9, E_META_WOOL_PURPLE = 10, E_META_WOOL_BLUE = 11, E_META_WOOL_BROWN = 12, E_META_WOOL_GREEN = 13, E_META_WOOL_RED = 14, E_META_WOOL_BLACK = 15, }; enum ENUM_ITEM_META : short { // Please keep this list alpha-sorted by the itemtype part // then number-sorted for the same item //////////////////////////////////////////////////////////////////////////////// // Item metas: // E_ITEM_BANNER metas: E_META_BANNER_BLACK = 0, E_META_BANNER_RED = 1, E_META_BANNER_GREEN = 2, E_META_BANNER_BROWN = 3, E_META_BANNER_BLUE = 4, E_META_BANNER_PURPLE = 5, E_META_BANNER_CYAN = 6, E_META_BANNER_LIGHTGRAY = 7, E_META_BANNER_GRAY = 8, E_META_BANNER_PINK = 9, E_META_BANNER_LIGHTGREEN = 10, E_META_BANNER_YELLOW = 11, E_META_BANNER_LIGHTBLUE = 12, E_META_BANNER_MAGENTA = 13, E_META_BANNER_ORANGE = 14, E_META_BANNER_WHITE = 15, // E_ITEM_COAL metas: E_META_COAL_NORMAL = 0, E_META_COAL_CHARCOAL = 1, // E_ITEM_DYE metas: E_META_DYE_BLACK = 0, E_META_DYE_RED = 1, E_META_DYE_GREEN = 2, E_META_DYE_BROWN = 3, E_META_DYE_BLUE = 4, E_META_DYE_PURPLE = 5, E_META_DYE_CYAN = 6, E_META_DYE_LIGHTGRAY = 7, E_META_DYE_GRAY = 8, E_META_DYE_PINK = 9, E_META_DYE_LIGHTGREEN = 10, E_META_DYE_YELLOW = 11, E_META_DYE_LIGHTBLUE = 12, E_META_DYE_MAGENTA = 13, E_META_DYE_ORANGE = 14, E_META_DYE_WHITE = 15, // E_ITEM_GOLDEN_APPLE metas: E_META_GOLDEN_APPLE_NORMAL = 0, E_META_GOLDEN_APPLE_ENCHANTED = 1, // E_ITEM_HEAD metas: E_META_HEAD_SKELETON = 0, E_META_HEAD_WITHER = 1, E_META_HEAD_ZOMBIE = 2, E_META_HEAD_PLAYER = 3, E_META_HEAD_CREEPER = 4, E_META_HEAD_DRAGON = 5, // E_ITEM_RAW_FISH metas: E_META_RAW_FISH_FISH = 0, E_META_RAW_FISH_SALMON = 1, E_META_RAW_FISH_CLOWNFISH = 2, E_META_RAW_FISH_PUFFERFISH = 3, // E_ITEM_COOKED_FISH metas: E_META_COOKED_FISH_FISH = 0, E_META_COOKED_FISH_SALMON = 1, // E_ITEM_MINECART_TRACKS metas: E_META_TRACKS_X = 1, E_META_TRACKS_Z = 0, // E_ITEM_SPAWN_EGG metas: // See also cMonster::eType, since monster type and spawn egg meta are the same E_META_SPAWN_EGG_PICKUP = 1, E_META_SPAWN_EGG_EXPERIENCE_ORB = 2, E_META_SPAWN_EGG_WITHER_SKELETON = 5, E_META_SPAWN_EGG_LEASH_KNOT = 8, E_META_SPAWN_EGG_PAINTING = 9, E_META_SPAWN_EGG_ARROW = 10, E_META_SPAWN_EGG_SNOWBALL = 11, E_META_SPAWN_EGG_FIREBALL = 12, E_META_SPAWN_EGG_SMALL_FIREBALL = 13, E_META_SPAWN_EGG_ENDER_PEARL = 14, E_META_SPAWN_EGG_EYE_OF_ENDER = 15, E_META_SPAWN_EGG_SPLASH_POTION = 16, E_META_SPAWN_EGG_EXP_BOTTLE = 17, E_META_SPAWN_EGG_ITEM_FRAME = 18, E_META_SPAWN_EGG_WITHER_SKULL = 19, E_META_SPAWN_EGG_PRIMED_TNT = 20, E_META_SPAWN_EGG_FALLING_BLOCK = 21, E_META_SPAWN_EGG_FIREWORK = 22, E_META_SPAWN_EGG_ZOMBIE_VILLAGER = 27, E_META_SPAWN_EGG_BOAT = 41, E_META_SPAWN_EGG_MINECART = 42, E_META_SPAWN_EGG_MINECART_CHEST = 43, E_META_SPAWN_EGG_MINECART_FURNACE = 44, E_META_SPAWN_EGG_MINECART_TNT = 45, E_META_SPAWN_EGG_MINECART_HOPPER = 46, E_META_SPAWN_EGG_MINECART_SPAWNER = 47, E_META_SPAWN_EGG_CREEPER = 50, E_META_SPAWN_EGG_SKELETON = 51, E_META_SPAWN_EGG_SPIDER = 52, E_META_SPAWN_EGG_GIANT = 53, E_META_SPAWN_EGG_ZOMBIE = 54, E_META_SPAWN_EGG_SLIME = 55, E_META_SPAWN_EGG_GHAST = 56, E_META_SPAWN_EGG_ZOMBIE_PIGMAN = 57, E_META_SPAWN_EGG_ENDERMAN = 58, E_META_SPAWN_EGG_CAVE_SPIDER = 59, E_META_SPAWN_EGG_SILVERFISH = 60, E_META_SPAWN_EGG_BLAZE = 61, E_META_SPAWN_EGG_MAGMA_CUBE = 62, E_META_SPAWN_EGG_ENDER_DRAGON = 63, E_META_SPAWN_EGG_WITHER = 64, E_META_SPAWN_EGG_BAT = 65, E_META_SPAWN_EGG_WITCH = 66, E_META_SPAWN_EGG_ENDERMITE = 67, E_META_SPAWN_EGG_GUARDIAN = 68, E_META_SPAWN_EGG_PIG = 90, E_META_SPAWN_EGG_SHEEP = 91, E_META_SPAWN_EGG_COW = 92, E_META_SPAWN_EGG_CHICKEN = 93, E_META_SPAWN_EGG_SQUID = 94, E_META_SPAWN_EGG_WOLF = 95, E_META_SPAWN_EGG_MOOSHROOM = 96, E_META_SPAWN_EGG_SNOW_GOLEM = 97, E_META_SPAWN_EGG_OCELOT = 98, E_META_SPAWN_EGG_IRON_GOLEM = 99, E_META_SPAWN_EGG_HORSE = 100, E_META_SPAWN_EGG_RABBIT = 101, E_META_SPAWN_EGG_VILLAGER = 120, E_META_SPAWN_EGG_ENDER_CRYSTAL = 200, } ; // tolua_end // fwd: class cItem; class cIniFile; // tolua_begin /** Translates a blocktype string into blocktype. Takes either a number or an items.ini alias as input. Returns -1 on failure. */ extern int BlockStringToType(const AString & a_BlockTypeString); /** Translates an itemtype string into an item. Takes either a number, number^number, number:number or an items.ini alias as input. Returns true if successful. */ extern bool StringToItem(const AString & a_ItemTypeString, cItem & a_Item); /** Translates a full item into a string. If the ItemType is not recognized, the ItemType number is output into the string. */ extern AString ItemToString(const cItem & a_Item); /** Translates itemtype into a string. If the type is not recognized, the itemtype number is output into the string. */ extern AString ItemTypeToString(short a_ItemType); /** Translates a full item into a fully-specified string (including meta and count). If the ItemType is not recognized, the ItemType number is output into the string. */ extern AString ItemToFullString(const cItem & a_Item); /** Returns a cItem representing the item described in an IniFile's value; if the value doesn't exist, creates it with the provided default. */ extern cItem GetIniItemSet(cIniFile & a_IniFile, const char * a_Section, const char * a_Key, const char * a_Default); // tolua_end ================================================ FILE: src/Blocks/BlockAir.h ================================================ #pragma once class cBlockAirHandler final : public cBlockHandler { public: using cBlockHandler::cBlockHandler; private: virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override { // Don't drop anything: return {}; } }; ================================================ FILE: src/Blocks/BlockAnvil.h ================================================ #pragma once #include "BlockHandler.h" #include "Mixins/Mixins.h" #include "../Entities/Player.h" #include "../UI/AnvilWindow.h" class cBlockAnvilHandler final : public cYawRotator { using Super = cYawRotator; public: using Super::Super; private: virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override { return cItem(m_BlockType, 1, a_BlockMeta >> 2); } virtual bool OnUse( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, const Vector3i a_BlockPos, eBlockFace a_BlockFace, const Vector3i a_CursorPos ) const override { cWindow * Window = new cAnvilWindow(a_BlockPos); a_Player.OpenWindow(*Window); return true; } virtual bool IsUseable() const override { return true; } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 6; } } ; ================================================ FILE: src/Blocks/BlockBed.cpp ================================================ // BlockBed.cpp #include "Globals.h" #include "BlockBed.h" #include "BroadcastInterface.h" #include "../Entities/Player.h" #include "../World.h" #include "../BoundingBox.h" #include "../Mobs/Monster.h" void cBlockBedHandler::OnBroken( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, const Vector3i a_BlockPos, BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta, const cEntity * a_Digger ) const { UNUSED(a_Digger); auto Direction = MetaDataToDirection(a_OldBlockMeta & 0x03); if ((a_OldBlockMeta & 0x08) != 0) { // Was pillow Vector3i FootPos(a_BlockPos - Direction); if (a_ChunkInterface.GetBlock(FootPos) == E_BLOCK_BED) { // First replace the bed with air a_ChunkInterface.FastSetBlock(FootPos, E_BLOCK_AIR, 0); // Then destroy the bed entity a_ChunkInterface.SetBlock(FootPos, E_BLOCK_AIR, 0); } } else { // Was foot end Vector3i PillowPos(a_BlockPos + Direction); if (a_ChunkInterface.GetBlock(PillowPos) == E_BLOCK_BED) { // First replace the bed with air a_ChunkInterface.FastSetBlock(PillowPos, E_BLOCK_AIR, 0); // Then destroy the bed entity a_ChunkInterface.SetBlock(PillowPos, E_BLOCK_AIR, 0); } } } bool cBlockBedHandler::OnUse( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, Vector3i a_BlockPos, eBlockFace a_BlockFace, const Vector3i a_CursorPos ) const { // Source: https://minecraft.wiki/w/Bed#Sleeping // Sleeping in bed only allowed in Overworld, beds explode elsewhere: if (a_WorldInterface.GetDimension() != dimOverworld) { auto PosCopy = a_BlockPos; a_WorldInterface.DoExplosionAt(5, a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, true, esBed, &PosCopy); return true; } auto Meta = a_ChunkInterface.GetBlockMeta(a_BlockPos); if ((Meta & 0x8) == 0) { // Clicked on the foot of the bed, adjust to the head: a_BlockPos += MetaDataToDirection(Meta & 0x03); BLOCKTYPE Type; a_ChunkInterface.GetBlockTypeMeta(a_BlockPos, Type, Meta); if (Type != E_BLOCK_BED) { // Bed was incomplete, bail: return true; } } // Set the bed position to the pillow block: a_Player.SetBedPos(a_BlockPos); // Sleeping is allowed only during night and thunderstorms: if ( !(((a_WorldInterface.GetTimeOfDay() > 12541_tick) && (a_WorldInterface.GetTimeOfDay() < 23458_tick)) || (a_Player.GetWorld()->GetWeather() == wThunderstorm)) ) { a_Player.SendAboveActionBarMessage("You can only sleep at night and during thunderstorms"); return true; } // Check if the bed is occupied: if ((Meta & 0x04) == 0x04) { a_Player.SendAboveActionBarMessage("This bed is occupied"); return true; } // Cannot sleep if there are hostile mobs nearby: if ( !a_Player.GetWorld()->ForEachEntityInBox({ a_Player.GetPosition().addedY(-5), 8, 10 }, [](cEntity & a_Entity) { return a_Entity.IsMob() && (static_cast(a_Entity).GetMobFamily() == cMonster::mfHostile); }) ) { a_Player.SendAboveActionBarMessage("You may not rest now, there are monsters nearby"); return true; } // This will broadcast "use bed" for the pillow block, if the player can sleep: a_Player.SetIsInBed(true); // Check sleeping was successful, if not, bail: if (!a_Player.IsInBed()) { return true; } // Occupy the bed, where 0x4 = occupied bit: a_ChunkInterface.SetBlockMeta(a_BlockPos, Meta | 0x04); a_Player.GetStatistics().Custom[CustomStatistic::SleepInBed]++; // When sleeping, the player's bounding box moves to approximately where his head is. // Set the player's position to somewhere close to the edge of the pillow block: a_Player.SetPosition(Vector3f(0.4f, 1, 0.4f) * MetaDataToDirection(Meta & 0x03) + Vector3f(0.5f, 0.6875, 0.5f) + a_BlockPos); // Fast-forward the time if all players in the world are in their beds: if (a_WorldInterface.ForEachPlayer([](cPlayer & a_OtherPlayer) { return !a_OtherPlayer.IsInBed(); })) { a_WorldInterface.ForEachPlayer([&a_ChunkInterface](cPlayer & a_OtherPlayer) { VacateBed(a_ChunkInterface, a_OtherPlayer); return false; }); a_WorldInterface.SetTimeOfDay(0_tick); } return true; } cItems cBlockBedHandler::ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const { // Drops handled by the block entity: return {}; } ================================================ FILE: src/Blocks/BlockBed.h ================================================ // BlockBed.h #pragma once #include "BlockEntity.h" #include "ChunkInterface.h" #include "Entities/Player.h" #include "Mixins/Mixins.h" class cEntity; class cWorldInterface; class cBlockBedHandler final : public cYawRotator { using Super = cYawRotator; public: using Super::Super; static Vector3i MetaDataToDirection(NIBBLETYPE a_MetaData) { switch (a_MetaData) { case 0: return Vector3i(0, 0, 1); case 1: return Vector3i(-1, 0, 0); case 2: return Vector3i(0, 0, -1); case 3: return Vector3i(1, 0, 0); } return Vector3i(); } static void VacateBed(cChunkInterface & a_ChunkInterface, cPlayer & a_Player) { auto BedPosition = a_Player.GetLastBedPos(); BLOCKTYPE Type; NIBBLETYPE Meta; a_ChunkInterface.GetBlockTypeMeta(BedPosition, Type, Meta); if (Type != E_BLOCK_BED) { // Bed was incomplete, just wake: a_Player.SetIsInBed(false); return; } if ((Meta & 0x8) == 0) { // BedPosition is the foot of the bed, adjust to the head: BedPosition += MetaDataToDirection(Meta & 0x03); a_ChunkInterface.GetBlockTypeMeta(BedPosition, Type, Meta); if (Type != E_BLOCK_BED) { // Bed was incomplete, just wake: a_Player.SetIsInBed(false); return; } } // Clear the "occupied" bit of the bed's pillow block: a_ChunkInterface.SetBlockMeta(BedPosition, Meta & 0x0b); // Wake the player: a_Player.SetIsInBed(false); } private: // Overrides: virtual void OnBroken( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, const Vector3i a_BlockPos, BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta, const cEntity * a_Digger ) const override; virtual bool OnUse( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, const Vector3i a_ClickedBlockPos, eBlockFace a_ClickedBlockFace, const Vector3i a_CursorPos ) const override; virtual cItems ConvertToPickups(NIBBLETYPE a_BlockMeta, const cItem * a_Tool) const override; virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 28; } } ; ================================================ FILE: src/Blocks/BlockBigFlower.h ================================================ #pragma once #include "BlockHandler.h" #include "ChunkInterface.h" #include "../BlockInfo.h" #include "../Items/ItemHandler.h" class cBlockBigFlowerHandler final : public cBlockHandler { using Super = cBlockHandler; public: using Super::Super; private: virtual bool DoesIgnoreBuildCollision(const cWorld & a_World, const cItem & a_HeldItem, const Vector3i a_Position, NIBBLETYPE a_Meta, const eBlockFace a_ClickedBlockFace, const bool a_ClickedDirectly) const override { if (IsMetaTopPart(a_Meta)) { BLOCKTYPE BottomType; const auto BottomPosition = a_Position.addedY(-1); if ( !cChunkDef::IsValidHeight(BottomPosition) || !a_World.GetBlockTypeMeta(BottomPosition, BottomType, a_Meta) || (BottomType != E_BLOCK_BIG_FLOWER) ) { // Can't find the flower meta so assume grass return true; } } NIBBLETYPE FlowerMeta = a_Meta & 0x07; return ( (FlowerMeta == E_META_BIG_FLOWER_DOUBLE_TALL_GRASS) || (FlowerMeta == E_META_BIG_FLOWER_LARGE_FERN) ); } virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override { if (IsMetaTopPart(a_BlockMeta)) { return {}; } // With shears, drop self (even tall grass and fern): if ((a_Tool != nullptr) && (a_Tool->m_ItemType == E_ITEM_SHEARS)) { // Bit 0x08 specifies whether this is a top part or bottom; cut it off from the pickup: return cItem(m_BlockType, 1, a_BlockMeta & 0x07); } // Tall grass drops seeds, large fern drops nothing, others drop self: auto flowerType = a_BlockMeta & 0x07; if (flowerType == E_META_BIG_FLOWER_DOUBLE_TALL_GRASS) { // Drop seeds, depending on bernoulli trial result: if (GetRandomProvider().RandBool(0.875)) { // 87.5% chance of dropping nothing: return {}; } // 12.5% chance of dropping some seeds. const auto DropNum = FortuneDiscreteRandom(1, 1, 2 * ToolFortuneLevel(a_Tool)); return cItem(E_ITEM_SEEDS, DropNum); } else if (flowerType != E_META_BIG_FLOWER_LARGE_FERN) { return cItem(m_BlockType, 1, static_cast(flowerType)); } return {}; } static bool IsMetaTopPart(NIBBLETYPE a_Meta) { return ((a_Meta & 0x08) != 0); } virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override { // CanBeAt is also called on placement, so the top part can't check for the bottom part. // Both parts can only that they're rooted in grass. const auto RootPosition = a_Position.addedY(IsMetaTopPart(a_Meta) ? -2 : -1); return cChunkDef::IsValidHeight(RootPosition) && IsBlockTypeOfDirt(a_Chunk.GetBlock(RootPosition)); } virtual void OnBroken( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, const Vector3i a_BlockPos, BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta, const cEntity * a_Digger ) const override { if (IsMetaTopPart(a_OldBlockMeta)) { const auto LowerPart = a_BlockPos.addedY(-1); if (a_ChunkInterface.GetBlock(LowerPart) == a_OldBlockType) { // Prevent creative punches from dropping pickups. // TODO: Simplify to SetBlock and remove the IsMetaTopPart check in DropBlockAsPickups when 1.13 blockstates arrive. if ((a_Digger != nullptr) && a_Digger->IsPlayer() && static_cast(a_Digger)->IsGameModeCreative()) { a_ChunkInterface.SetBlock(LowerPart, E_BLOCK_AIR, 0); } else { a_ChunkInterface.DropBlockAsPickups(LowerPart); } } } else { const auto UpperPart = a_BlockPos.addedY(1); if (a_ChunkInterface.GetBlock(UpperPart) == a_OldBlockType) { a_ChunkInterface.SetBlock(UpperPart, E_BLOCK_AIR, 0); } } } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 7; } } ; ================================================ FILE: src/Blocks/BlockBookShelf.h ================================================ #pragma once #include "BlockHandler.h" class cBlockBookShelfHandler final : public cBlockHandler { public: using cBlockHandler::cBlockHandler; private: virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override { if (ToolHasSilkTouch(a_Tool)) { return cItem(m_BlockType, 1); } return cItem(E_ITEM_BOOK, 3); } }; ================================================ FILE: src/Blocks/BlockBrewingStand.h ================================================ #pragma once #include "Mixins/Mixins.h" class cBlockBrewingStandHandler final : public cBlockEntityHandler { using Super = cBlockEntityHandler; public: using Super::Super; private: virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override { return cItem(E_ITEM_BREWING_STAND); // We have to drop the item form of a brewing stand } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 6; } } ; ================================================ FILE: src/Blocks/BlockButton.h ================================================ #pragma once #include "BlockHandler.h" #include "BlockSlab.h" #include "BlockStairs.h" #include "../BlockInfo.h" #include "../Chunk.h" #include "Defines.h" #include "Entities/Player.h" #include "Mixins/Mixins.h" #include "ChunkInterface.h" #include "World.h" class cBlockButtonHandler final : public cClearMetaOnDrop> { using Super = cClearMetaOnDrop>; public: using Super::Super; /** Extracts the ON bit from metadata and returns if true if it is set */ static bool IsButtonOn(NIBBLETYPE a_Meta) { return (a_Meta & 0x08) == 0x08; } /** Event handler for an arrow striking a block. Performs appropriate handling if the arrow intersected a wooden button. */ static void OnArrowHit(cWorld & a_World, const Vector3i a_Position, const eBlockFace a_HitFace) { BLOCKTYPE Type; NIBBLETYPE Meta; const auto Pos = AddFaceDirection(a_Position, a_HitFace); if ( !a_World.GetBlockTypeMeta(Pos, Type, Meta) || IsButtonOn(Meta) || !IsButtonPressedByArrow(a_World, Pos, Type, Meta) ) { // Bail if we're not specifically a wooden button, or it's already on // or if the arrow didn't intersect. It is very important that nothing is // done if the button is depressed, since the release task will already be queued return; } a_World.SetBlockMeta(Pos, Meta | 0x08); a_World.WakeUpSimulators(Pos); // sound name is ok to be wood, because only wood gets triggered by arrow a_World.GetBroadcastManager().BroadcastSoundEffect("block.wood_button.click_on", Pos, 0.5f, 0.6f); // Queue a button reset QueueButtonRelease(a_World, Pos, Type); } private: virtual bool OnUse( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, const Vector3i a_BlockPos, eBlockFace a_BlockFace, const Vector3i a_CursorPos ) const override { NIBBLETYPE Meta = a_ChunkInterface.GetBlockMeta(a_BlockPos); // If button is already on, do nothing: if (IsButtonOn(Meta)) { return false; } // Set the ON bit to on Meta |= 0x08; const auto SoundToPlay = (m_BlockType == E_BLOCK_STONE_BUTTON) ? "block.stone_button.click_on" : "block.wood_button.click_on"; a_ChunkInterface.SetBlockMeta(a_BlockPos, Meta); a_WorldInterface.WakeUpSimulators(a_BlockPos); a_WorldInterface.GetBroadcastManager().BroadcastSoundEffect(SoundToPlay, a_BlockPos, 0.5f, 0.6f, a_Player.GetClientHandle()); // Queue a button reset (unpress) QueueButtonRelease(*a_Player.GetWorld(), a_BlockPos, m_BlockType); return true; } virtual bool IsUseable(void) const override { return true; } /** Converts the block meta of this button into a block face of the neighbor to which the button is attached. */ inline static eBlockFace BlockMetaDataToBlockFace(NIBBLETYPE a_Meta) { switch (a_Meta & 0x7) { case 0x0: return BLOCK_FACE_YM; case 0x1: return BLOCK_FACE_XP; case 0x2: return BLOCK_FACE_XM; case 0x3: return BLOCK_FACE_ZP; case 0x4: return BLOCK_FACE_ZM; case 0x5: return BLOCK_FACE_YP; default: { ASSERT(!"Unhandled block meta!"); return BLOCK_FACE_NONE; } } } virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override { auto SupportRelPos = AddFaceDirection(a_Position, BlockMetaDataToBlockFace(a_Meta), true); if (!cChunkDef::IsValidHeight(SupportRelPos)) { return false; } BLOCKTYPE SupportBlockType; NIBBLETYPE SupportBlockMeta; a_Chunk.UnboundedRelGetBlock(SupportRelPos, SupportBlockType, SupportBlockMeta); eBlockFace Face = BlockMetaDataToBlockFace(a_Meta); // upside down slabs if (cBlockSlabHandler::IsAnySlabType(SupportBlockType)) { return (Face == BLOCK_FACE_YP) && (SupportBlockMeta & E_META_WOODEN_SLAB_UPSIDE_DOWN); } // stairs (top and sides) if (cBlockStairsHandler::IsAnyStairType(SupportBlockType)) { switch (Face) { case eBlockFace::BLOCK_FACE_YP: return (SupportBlockMeta & E_BLOCK_STAIRS_UPSIDE_DOWN); case eBlockFace::BLOCK_FACE_XP: return ((SupportBlockMeta & 0b11) == E_BLOCK_STAIRS_XP); case eBlockFace::BLOCK_FACE_XM: return ((SupportBlockMeta & 0b11) == E_BLOCK_STAIRS_XM); case eBlockFace::BLOCK_FACE_ZP: return ((SupportBlockMeta & 0b11) == E_BLOCK_STAIRS_ZP); case eBlockFace::BLOCK_FACE_ZM: return ((SupportBlockMeta & 0b11) == E_BLOCK_STAIRS_ZM); default: { return false; } } } return cBlockInfo::FullyOccupiesVoxel(SupportBlockType); } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 0; } /** Schedules a recurring event at appropriate intervals to release a button at a given position. The given block type is checked when the task is executed to ensure the position still contains a button. */ static void QueueButtonRelease(cWorld & a_ButtonWorld, const Vector3i a_Position, const BLOCKTYPE a_BlockType) { const auto TickDelay = (a_BlockType == E_BLOCK_STONE_BUTTON) ? 20_tick : 30_tick; a_ButtonWorld.ScheduleTask( TickDelay, [a_Position, a_BlockType](cWorld & a_World) { BLOCKTYPE Type; NIBBLETYPE Meta; if ( !a_World.GetBlockTypeMeta(a_Position, Type, Meta) || (Type != a_BlockType) || !IsButtonOn(Meta) ) { // Total failure or block changed, bail return; } if (IsButtonPressedByArrow(a_World, a_Position, Type, Meta)) { // Try again in a little while QueueButtonRelease(a_World, a_Position, a_BlockType); return; } // Block hasn't change in the meantime; release it const auto SoundToPlayOnRelease = (Type == E_BLOCK_STONE_BUTTON) ? "block.stone_button.click_off" : "block.wood_button.click_off"; a_World.SetBlockMeta(a_Position, Meta & 0x07); a_World.WakeUpSimulators(a_Position); a_World.BroadcastSoundEffect(SoundToPlayOnRelease, a_Position, 0.5f, 0.5f); } ); } /** Returns true if an arrow was found in the wooden button */ static bool IsButtonPressedByArrow(cWorld & a_World, const Vector3i a_ButtonPosition, const BLOCKTYPE a_BlockType, const NIBBLETYPE a_Meta) { if (a_BlockType != E_BLOCK_WOODEN_BUTTON) { return false; } const auto FaceOffset = GetButtonOffsetOnBlock(a_Meta); const bool FoundArrow = !a_World.ForEachEntityInBox( cBoundingBox(FaceOffset + a_ButtonPosition, 0.2, 0.2), [](cEntity & a_Entity) { return a_Entity.IsArrow(); } ); return FoundArrow; } /** Returns an offset to the integer world coordinates of a button. Applying this offset yields the centre of the button's bounding box, in terms of the position within the block the button with given meta occupies. TODO: this is only approximate, return the exact bbox instead. */ static Vector3d GetButtonOffsetOnBlock(NIBBLETYPE a_Meta) { switch (BlockMetaDataToBlockFace(a_Meta)) { case BLOCK_FACE_YM: return { 0.5, 1, 0.5 }; case BLOCK_FACE_XP: return { 0, 0.5, 0.5 }; case BLOCK_FACE_XM: return { 1, 0.5, 0.5 }; case BLOCK_FACE_ZP: return { 0.5, 0.5, 0 }; case BLOCK_FACE_ZM: return { 0.5, 0.5, 1 }; case BLOCK_FACE_YP: return { 0.5, 0, 0.5 }; case BLOCK_FACE_NONE: { break; } } UNREACHABLE("Unhandled block face!"); } } ; ================================================ FILE: src/Blocks/BlockCactus.h ================================================ #pragma once #include "BlockPlant.h" #include "../BlockInfo.h" class cBlockCactusHandler final : public cClearMetaOnDrop> { using Super = cClearMetaOnDrop>; public: using Super::Super; private: virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override { const auto SurfacePosition = a_Position.addedY(-1); if (!cChunkDef::IsValidHeight(SurfacePosition)) { return false; } BLOCKTYPE Surface = a_Chunk.GetBlock(SurfacePosition); if ((Surface != E_BLOCK_SAND) && (Surface != E_BLOCK_CACTUS)) { // Cactus can only be placed on sand and itself return false; } // Check surroundings. Cacti may ONLY be surrounded by non-solid blocks static const Vector3i Coords[] = { {-1, 0, 0}, { 1, 0, 0}, { 0, 0, -1}, { 0, 0, 1}, }; for (size_t i = 0; i < ARRAYCOUNT(Coords); i++) { BLOCKTYPE BlockType; NIBBLETYPE BlockMeta; if ( a_Chunk.UnboundedRelGetBlock(a_Position + Coords[i], BlockType, BlockMeta) && ( cBlockInfo::IsSolid(BlockType) || (BlockType == E_BLOCK_LAVA) || (BlockType == E_BLOCK_STATIONARY_LAVA) ) ) { return false; } } // for i - Coords[] return true; } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 7; } virtual int Grow(cChunk & a_Chunk, Vector3i a_RelPos, int a_NumStages = 1) const override { // Check the total height of the cacti blocks here: auto Top = a_RelPos.addedY(1); while ( cChunkDef::IsValidHeight(Top) && (a_Chunk.GetBlock(Top) == E_BLOCK_CACTUS) ) { Top.y++; } auto Bottom = a_RelPos.addedY(-1); while ( cChunkDef::IsValidHeight(Bottom) && (a_Chunk.GetBlock(Bottom) == E_BLOCK_CACTUS) ) { --Bottom.y; } // Refuse if already too high: auto numToGrow = std::min(a_NumStages, a_Chunk.GetWorld()->GetMaxCactusHeight() + 1 - (Top.y - Bottom.y)); if (numToGrow <= 0) { return 0; } BLOCKTYPE blockType; for (int i = 0; i < numToGrow; ++i) { auto NewTop = Top.addedY(i); if (!a_Chunk.UnboundedRelGetBlockType(NewTop, blockType) || (blockType != E_BLOCK_AIR)) { // Cannot grow there return i; } a_Chunk.UnboundedRelFastSetBlock(NewTop, E_BLOCK_CACTUS, 0); // Check surroundings. Cacti may ONLY be surrounded by non-solid blocks; if they aren't, drop as pickup and bail out the growing static const Vector3i neighborOffsets[] = { {-1, 0, 0}, { 1, 0, 0}, { 0, 0, -1}, { 0, 0, 1}, } ; for (const auto & ofs: neighborOffsets) { if ( a_Chunk.UnboundedRelGetBlockType(NewTop + ofs, blockType) && ( cBlockInfo::IsSolid(blockType) || (blockType == E_BLOCK_LAVA) || (blockType == E_BLOCK_STATIONARY_LAVA) ) ) { // Remove the cactus auto absPos = a_Chunk.RelativeToAbsolute(NewTop); a_Chunk.GetWorld()->DropBlockAsPickups(absPos); return i + 1; } } // for neighbor } // for i - numToGrow return numToGrow; } virtual PlantAction CanGrow(cChunk & a_Chunk, Vector3i a_RelPos) const override { // Only allow growing if there's an air block above: const auto RelPosAbove = a_RelPos.addedY(1); if (cChunkDef::IsValidHeight(RelPosAbove) && (a_Chunk.GetBlock(RelPosAbove) == E_BLOCK_AIR)) { return Super::CanGrow(a_Chunk, a_RelPos); } return paStay; } } ; ================================================ FILE: src/Blocks/BlockCake.h ================================================ #pragma once #include "BlockHandler.h" class cBlockCakeHandler final : public cBlockHandler { using Super = cBlockHandler; public: using Super::Super; private: virtual bool OnUse( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, const Vector3i a_BlockPos, eBlockFace a_BlockFace, const Vector3i a_CursorPos ) const override { NIBBLETYPE Meta = a_ChunkInterface.GetBlockMeta(a_BlockPos); if (!a_Player.Feed(2, 0.4)) { return false; } a_Player.GetStatistics().Custom[CustomStatistic::EatCakeSlice]++; if (Meta >= 5) { a_ChunkInterface.DigBlock(a_WorldInterface, a_BlockPos, &a_Player); } else { a_ChunkInterface.SetBlockMeta(a_BlockPos, Meta + 1); } return true; } virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override { // Give nothing return {}; } virtual bool IsUseable(void) const override { return true; } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 14; } } ; ================================================ FILE: src/Blocks/BlockCarpet.h ================================================ // BlockCarpet.h // Declares the cBlockCarpetHandler class representing the handler for the carpet block #pragma once #include "BlockHandler.h" class cBlockCarpetHandler final : public cBlockHandler { using Super = cBlockHandler; public: using Super::Super; private: virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override { const auto PosBelow = a_Position.addedY(-1); return cChunkDef::IsValidHeight(PosBelow) && (a_Chunk.GetBlock(PosBelow) != E_BLOCK_AIR); } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { switch (a_Meta) { case E_META_CARPET_WHITE: return 14; case E_META_CARPET_ORANGE: return 15; case E_META_CARPET_MAGENTA: return 16; case E_META_CARPET_LIGHTBLUE: return 17; case E_META_CARPET_YELLOW: return 18; case E_META_CARPET_LIGHTGREEN: return 19; case E_META_CARPET_PINK: return 20; case E_META_CARPET_GRAY: return 21; case E_META_CARPET_LIGHTGRAY: return 22; case E_META_CARPET_CYAN: return 23; case E_META_CARPET_PURPLE: return 24; case E_META_CARPET_BLUE: return 25; case E_META_CARPET_BROWN: return 26; case E_META_CARPET_GREEN: return 27; case E_META_CARPET_RED: return 28; case E_META_CARPET_BLACK: return 29; default: { ASSERT(!"Unhandled meta in carpet handler!"); return 0; } } } } ; ================================================ FILE: src/Blocks/BlockCauldron.h ================================================ #pragma once #include "BlockHandler.h" #include "../Entities/Player.h" #include "../ClientHandle.h" class cBlockCauldronHandler final : public cBlockHandler { using Super = cBlockHandler; public: using Super::Super; private: virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override { return cItem(E_ITEM_CAULDRON, 1, 0); } virtual bool OnUse( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, const Vector3i a_BlockPos, eBlockFace a_BlockFace, const Vector3i a_CursorPos ) const override { NIBBLETYPE Meta = a_ChunkInterface.GetBlockMeta(a_BlockPos); auto EquippedItem = a_Player.GetEquippedItem(); switch (EquippedItem.m_ItemType) { case E_ITEM_BUCKET: { if (Meta == 3) { a_ChunkInterface.SetBlockMeta(a_BlockPos, 0); // Give new bucket, filled with fluid when the gamemode is not creative: if (!a_Player.IsGameModeCreative()) { a_Player.ReplaceOneEquippedItemTossRest(cItem(E_ITEM_WATER_BUCKET)); } } break; } case E_ITEM_WATER_BUCKET: { if (Meta < 3) { a_ChunkInterface.SetBlockMeta(a_BlockPos, 3); // Give empty bucket back when the gamemode is not creative: if (!a_Player.IsGameModeCreative()) { a_Player.ReplaceOneEquippedItemTossRest(cItem(E_ITEM_BUCKET)); } a_Player.GetStatistics().Custom[CustomStatistic::FillCauldron]++; } break; } case E_ITEM_GLASS_BOTTLE: { if (Meta > 0) { a_ChunkInterface.SetBlockMeta(a_BlockPos, --Meta); // Give new potion when the gamemode is not creative: if (!a_Player.IsGameModeCreative()) { a_Player.ReplaceOneEquippedItemTossRest(cItem(E_ITEM_POTION)); } a_Player.GetStatistics().Custom[CustomStatistic::UseCauldron]++; } break; } case E_ITEM_POTION: { // Refill cauldron with water bottles. if ((Meta < 3) && (EquippedItem.m_ItemDamage == 0)) { a_ChunkInterface.SetBlockMeta(Vector3i(a_BlockPos), ++Meta); // Give back an empty bottle when the gamemode is not creative: if (!a_Player.IsGameModeCreative()) { a_Player.ReplaceOneEquippedItemTossRest(cItem(E_ITEM_GLASS_BOTTLE)); } } break; } case E_ITEM_LEATHER_BOOTS: case E_ITEM_LEATHER_CAP: case E_ITEM_LEATHER_PANTS: case E_ITEM_LEATHER_TUNIC: { // Resets any color to default: if ((Meta > 0) && ((EquippedItem.m_ItemColor.GetRed() != 255) || (EquippedItem.m_ItemColor.GetBlue() != 255) || (EquippedItem.m_ItemColor.GetGreen() != 255))) { a_ChunkInterface.SetBlockMeta(a_BlockPos, --Meta); auto NewItem = cItem(EquippedItem); NewItem.m_ItemColor.Clear(); a_Player.ReplaceOneEquippedItemTossRest(NewItem); } break; } case E_BLOCK_BLACK_SHULKER_BOX: case E_BLOCK_BLUE_SHULKER_BOX: case E_BLOCK_BROWN_SHULKER_BOX: case E_BLOCK_CYAN_SHULKER_BOX: case E_BLOCK_GRAY_SHULKER_BOX: case E_BLOCK_GREEN_SHULKER_BOX: case E_BLOCK_LIGHT_BLUE_SHULKER_BOX: case E_BLOCK_LIGHT_GRAY_SHULKER_BOX: case E_BLOCK_LIME_SHULKER_BOX: case E_BLOCK_MAGENTA_SHULKER_BOX: case E_BLOCK_ORANGE_SHULKER_BOX: case E_BLOCK_PINK_SHULKER_BOX: case E_BLOCK_RED_SHULKER_BOX: case E_BLOCK_YELLOW_SHULKER_BOX: { // Resets shulker box color. // TODO: When there is an actual default shulker box add the appropriate changes here! - 19.09.2020 - 12xx12 if (Meta == 0) { // The cauldron is empty: break; } // Proceed with normal cleaning: a_ChunkInterface.SetBlockMeta(a_BlockPos, --Meta); auto NewShulker = cItem(EquippedItem); NewShulker.m_ItemType = E_BLOCK_PURPLE_SHULKER_BOX; a_Player.ReplaceOneEquippedItemTossRest(NewShulker); break; } } if (!EquippedItem.GetHandler().IsPlaceable()) { // Item not placeable in the first place, our work is done: return true; } // This is a workaround for versions < 1.13, where rclking a cauldron with a block, places a block. // Using cauldrons with blocks was added in 1.13 as part of shulker cleaning. const auto ResendPosition = AddFaceDirection(a_BlockPos, a_BlockFace); a_Player.GetClientHandle()->SendBlockChange( ResendPosition, a_ChunkInterface.GetBlock(ResendPosition), a_ChunkInterface.GetBlockMeta(ResendPosition) ); return true; } virtual bool IsUseable() const override { return true; } virtual void OnUpdate( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cBlockPluginInterface & a_PluginInterface, cChunk & a_Chunk, const Vector3i a_RelPos ) const override { auto WorldPos = a_Chunk.RelativeToAbsolute(a_RelPos); if (!a_WorldInterface.IsWeatherWetAtXYZ(WorldPos.addedY(1))) { // It's not raining at our current location or we do not have a direct view of the sky return; } auto Meta = a_Chunk.GetMeta(a_RelPos); if (Meta < 3) { a_Chunk.SetMeta(a_RelPos, Meta + 1); } } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 21; } } ; ================================================ FILE: src/Blocks/BlockChest.h ================================================ #pragma once #include "../BlockArea.h" #include "../Entities/Player.h" #include "Mixins/Mixins.h" class cBlockChestHandler final : public cYawRotator, 0x07, 0x03, 0x04, 0x02, 0x05> { using Super = cYawRotator, 0x07, 0x03, 0x04, 0x02, 0x05>; public: using Super::Super; virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 13; } } ; ================================================ FILE: src/Blocks/BlockCloth.h ================================================ #pragma once #include "BlockHandler.h" class cBlockClothHandler final : public cBlockHandler { public: using cBlockHandler::cBlockHandler; private: virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { switch (a_Meta) { case E_META_WOOL_WHITE: return 14; case E_META_WOOL_ORANGE: return 15; case E_META_WOOL_MAGENTA: return 16; case E_META_WOOL_LIGHTBLUE: return 17; case E_META_WOOL_YELLOW: return 18; case E_META_WOOL_LIGHTGREEN: return 19; case E_META_WOOL_PINK: return 20; case E_META_WOOL_GRAY: return 21; case E_META_WOOL_LIGHTGRAY: return 22; case E_META_WOOL_CYAN: return 23; case E_META_WOOL_PURPLE: return 24; case E_META_WOOL_BLUE: return 25; case E_META_WOOL_BROWN: return 26; case E_META_WOOL_GREEN: return 27; case E_META_WOOL_RED: return 28; case E_META_WOOL_BLACK: return 29; default: { ASSERT(!"Unhandled meta in wool handler!"); return 0; } } } } ; ================================================ FILE: src/Blocks/BlockCobWeb.h ================================================ // BlockCobWeb.h // Declares the cBlockCobWebHandler object representing the BlockHandler for cobwebs #pragma once class cBlockCobWebHandler final : public cBlockHandler { public: using cBlockHandler::cBlockHandler; private: virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override { // Silk touch gives cobweb, anything else gives just string: if (ToolHasSilkTouch(a_Tool)) { return cItem(m_BlockType, 1, 0); } else { return cItem(E_ITEM_STRING, 1, 0); } } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 3; } } ; ================================================ FILE: src/Blocks/BlockCocoaPod.h ================================================ #pragma once #include "BlockHandler.h" #include "../FastRandom.h" class cBlockCocoaPodHandler final : public cBlockHandler { using Super = cBlockHandler; public: using Super::Super; static NIBBLETYPE BlockFaceToMeta(eBlockFace a_BlockFace) { switch (a_BlockFace) { case BLOCK_FACE_ZM: return 0; case BLOCK_FACE_XM: return 3; case BLOCK_FACE_XP: return 1; case BLOCK_FACE_ZP: return 2; case BLOCK_FACE_NONE: case BLOCK_FACE_YM: case BLOCK_FACE_YP: { break; } } UNREACHABLE("Unsupported block face"); } private: virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override { // Check that we're attached to a jungle log block: eBlockFace BlockFace = MetaToBlockFace(a_Meta); auto LogPos = AddFaceDirection(a_Position, BlockFace, true); BLOCKTYPE BlockType; NIBBLETYPE BlockMeta; if (!a_Chunk.UnboundedRelGetBlock(LogPos, BlockType, BlockMeta)) { // Don't pop if chunk not loaded. return true; } return ((BlockType == E_BLOCK_LOG) && ((BlockMeta & 0x03) == E_META_LOG_JUNGLE)); } virtual void OnUpdate( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cBlockPluginInterface & a_PluginInterface, cChunk & a_Chunk, const Vector3i a_RelPos ) const override { if (GetRandomProvider().RandBool(0.20)) { Grow(a_Chunk, a_RelPos); } } virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override { // If fully grown, give 3 items, otherwise just one: auto growState = a_BlockMeta >> 2; return cItem(E_ITEM_DYE, ((growState >= 2) ? 3 : 1), E_META_DYE_BROWN); } virtual int Grow(cChunk & a_Chunk, Vector3i a_RelPos, int a_NumStages = 1) const override { auto meta = a_Chunk.GetMeta(a_RelPos); auto typeMeta = meta & 0x03; auto growState = meta >> 2; if (growState >= 2) { return 0; } auto newState = std::min(growState + a_NumStages, 2); a_Chunk.SetMeta(a_RelPos, static_cast(newState << 2 | typeMeta)); return newState - growState; } static eBlockFace MetaToBlockFace(NIBBLETYPE a_Meta) { switch (a_Meta & 0x03) { case 0: return BLOCK_FACE_ZM; case 1: return BLOCK_FACE_XP; case 2: return BLOCK_FACE_ZP; case 3: return BLOCK_FACE_XM; default: { ASSERT(!"Bad meta"); return BLOCK_FACE_NONE; } } } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 34; } } ; ================================================ FILE: src/Blocks/BlockCommandBlock.h ================================================ #pragma once #include "BlockEntity.h" class cBlockCommandBlockHandler final : public cBlockEntityHandler { using Super = cBlockEntityHandler; public: using Super::Super; private: virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override { // Don't allow as a pickup: return {}; } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 10; } } ; ================================================ FILE: src/Blocks/BlockComparator.h ================================================ #pragma once #include "BlockHandler.h" #include "Mixins/Mixins.h" #include "Mixins/SolidSurfaceUnderneath.h" class cBlockComparatorHandler final : public cSolidSurfaceUnderneath> { using Super = cSolidSurfaceUnderneath>; public: using Super::Super; inline static bool IsInSubtractionMode(NIBBLETYPE a_Meta) { return ((a_Meta & 0x4) == 0x4); } inline static Vector3i GetFrontCoordinate(Vector3i a_Position, NIBBLETYPE a_Meta) { switch (a_Meta) { case 0x0: a_Position.z--; break; case 0x1: a_Position.x++; break; case 0x2: a_Position.z++; break; case 0x3: a_Position.x--; break; default: { LOGWARNING("%s: Unknown metadata: %d", __FUNCTION__, a_Meta); ASSERT(!"Unknown metadata while determining orientation of comparator!"); break; } } return a_Position; } inline static Vector3i GetSideCoordinate(Vector3i a_Position, NIBBLETYPE a_Meta, bool a_bInverse) { if (!a_bInverse) { switch (a_Meta) { case 0x0: a_Position.x++; break; case 0x1: a_Position.z--; break; case 0x2: a_Position.x--; break; case 0x3: a_Position.z++; break; default: { LOGWARNING("%s: Unknown metadata: %d", __FUNCTION__, a_Meta); ASSERT(!"Unknown metadata while determining orientation of comparator!"); break; } } } else { switch (a_Meta) { case 0x0: a_Position.x--; break; case 0x1: a_Position.z++; break; case 0x2: a_Position.x++; break; case 0x3: a_Position.z--; break; default: { LOGWARNING("%s: Unknown metadata: %d", __FUNCTION__, a_Meta); ASSERT(!"Unknown metadata while determining orientation of comparator!"); break; } } } return a_Position; } inline static Vector3i GetRearCoordinate(Vector3i a_Position, NIBBLETYPE a_Meta) { switch (a_Meta) { case 0x0: a_Position.z++; break; case 0x1: a_Position.x--; break; case 0x2: a_Position.z--; break; case 0x3: a_Position.x++; break; default: { LOGWARNING("%s: Unknown metadata: %d", __FUNCTION__, a_Meta); ASSERT(!"Unknown metadata while determining orientation of comparator!"); break; } } return a_Position; } private: virtual bool OnUse( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, const Vector3i a_BlockPos, eBlockFace a_BlockFace, const Vector3i a_CursorPos ) const override { const auto Meta = a_ChunkInterface.GetBlockMeta(a_BlockPos); // Toggle the 3rd bit (addition / subtraction): a_ChunkInterface.SetBlockMeta(a_BlockPos, Meta ^ 0x04); // Update simulators: a_WorldInterface.WakeUpSimulators(a_BlockPos); return true; } virtual void OnCancelRightClick( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, const Vector3i a_BlockPos, eBlockFace a_BlockFace ) const override { UNUSED(a_ChunkInterface); UNUSED(a_BlockFace); a_WorldInterface.WakeUpSimulators(a_BlockPos); a_WorldInterface.SendBlockTo(a_BlockPos, a_Player); } virtual bool IsUseable(void) const override { return true; } virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override { return cItem(E_ITEM_COMPARATOR, 1, 0); } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 11; } } ; ================================================ FILE: src/Blocks/BlockConcretePowder.h ================================================ #pragma once #include "BlockHandler.h" class cBlockConcretePowderHandler final : public cBlockHandler { using Super = cBlockHandler; public: using Super::Super; private: virtual void OnPlaced( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta ) const override { OnNeighborChanged(a_ChunkInterface, a_BlockPos, BLOCK_FACE_NONE); } virtual void OnNeighborChanged(cChunkInterface & a_ChunkInterface, Vector3i a_BlockPos, eBlockFace a_WhichNeighbor) const override { a_ChunkInterface.DoWithChunkAt(a_BlockPos, [&](cChunk & a_Chunk) { CheckSoaked(cChunkDef::AbsoluteToRelative(a_BlockPos), a_Chunk); return true; }); } /** Check blocks above and around to see if they are water. If one is, converts this into concrete block. */ static void CheckSoaked(Vector3i a_Rel, cChunk & a_Chunk) { const auto & WaterCheck = cSimulator::AdjacentOffsets; const bool ShouldSoak = std::any_of(WaterCheck.cbegin(), WaterCheck.cend(), [a_Rel, & a_Chunk](Vector3i a_Offset) { BLOCKTYPE NeighborType; return ( a_Chunk.UnboundedRelGetBlockType(a_Rel.x + a_Offset.x, a_Rel.y + a_Offset.y, a_Rel.z + a_Offset.z, NeighborType) && IsBlockWater(NeighborType) ); }); if (ShouldSoak) { NIBBLETYPE BlockMeta; BlockMeta = a_Chunk.GetMeta(a_Rel.x, a_Rel.y, a_Rel.z); a_Chunk.SetBlock(a_Rel, E_BLOCK_CONCRETE, BlockMeta); } } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { switch (a_Meta) { case E_META_CONCRETE_POWDER_WHITE: return 8; case E_META_CONCRETE_POWDER_ORANGE: return 15; case E_META_CONCRETE_POWDER_MAGENTA: return 16; case E_META_CONCRETE_POWDER_LIGHTBLUE: return 17; case E_META_CONCRETE_POWDER_YELLOW: return 18; case E_META_CONCRETE_POWDER_LIGHTGREEN: return 19; case E_META_CONCRETE_POWDER_PINK: return 20; case E_META_CONCRETE_POWDER_GRAY: return 21; case E_META_CONCRETE_POWDER_LIGHTGRAY: return 22; case E_META_CONCRETE_POWDER_CYAN: return 23; case E_META_CONCRETE_POWDER_PURPLE: return 24; case E_META_CONCRETE_POWDER_BLUE: return 25; case E_META_CONCRETE_POWDER_BROWN: return 26; case E_META_CONCRETE_POWDER_GREEN: return 27; case E_META_CONCRETE_POWDER_RED: return 28; case E_META_CONCRETE_POWDER_BLACK: return 29; default: { ASSERT(!"Unhandled meta in concrete powder handler!"); return 0; } } } }; ================================================ FILE: src/Blocks/BlockCrops.h ================================================ #pragma once #include "BlockPlant.h" #include "../FastRandom.h" /** Common class that takes care of beetroots, carrots, potatoes and wheat */ template class cBlockCropsHandler final : public cBlockPlant { using Super = cBlockPlant; public: using Super::Super; private: /** Calculate the number of seeds to drop when the crop is broken. */ static char CalculateSeedCount(char a_Min, char a_BaseRolls, unsigned char a_FortuneLevel) { std::binomial_distribution<> Binomial(a_BaseRolls + a_FortuneLevel, 0.57); return static_cast(a_Min + Binomial(GetRandomProvider().Engine())); } virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override { auto & rand = GetRandomProvider(); // If not fully grown, drop the "seed" of whatever is growing: if (a_BlockMeta < RipeMeta) { switch (m_BlockType) { case E_BLOCK_BEETROOTS: return cItem(E_ITEM_BEETROOT_SEEDS); case E_BLOCK_CROPS: return cItem(E_ITEM_SEEDS); case E_BLOCK_CARROTS: return cItem(E_ITEM_CARROT); case E_BLOCK_POTATOES: return cItem(E_ITEM_POTATO); } ASSERT(!"Unhandled block type"); return {}; } // Fully grown, drop the crop's produce: cItems Res; switch (m_BlockType) { case E_BLOCK_BEETROOTS: { const auto SeedCount = CalculateSeedCount(0, 3, ToolFortuneLevel(a_Tool)); Res.Add(E_ITEM_BEETROOT_SEEDS, SeedCount); Res.Add(E_ITEM_BEETROOT); break; } case E_BLOCK_CROPS: { // https://minecraft.wiki/w/Seeds_(Wheat) Res.Add(E_ITEM_WHEAT); const auto SeedCount = CalculateSeedCount(1, 3, ToolFortuneLevel(a_Tool)); Res.Add(E_ITEM_SEEDS, SeedCount); break; } case E_BLOCK_CARROTS: { // https://minecraft.wiki/w/Carrot#Breaking const auto CarrotCount = CalculateSeedCount(1, 4, ToolFortuneLevel(a_Tool)); Res.Add(E_ITEM_CARROT, CarrotCount); break; } case E_BLOCK_POTATOES: { // https://minecraft.wiki/w/Potato#Breaking const auto PotatoCount = CalculateSeedCount(2, 3, ToolFortuneLevel(a_Tool)); Res.Add(E_ITEM_POTATO, PotatoCount); if (rand.RandBool(0.02)) { // https://minecraft.wiki/w/Poisonous_Potato#Obtaining // With a 2% chance, drop a poisonous potato as well: Res.Add(E_ITEM_POISONOUS_POTATO); } break; } default: { ASSERT(!"Unhandled block type"); break; } } // switch (m_BlockType) return Res; } virtual int Grow(cChunk & a_Chunk, Vector3i a_RelPos, int a_NumStages = 1) const override { const auto OldMeta = a_Chunk.GetMeta(a_RelPos); const auto NewMeta = std::clamp(static_cast(OldMeta + a_NumStages), 0, RipeMeta); a_Chunk.SetMeta(a_RelPos, NewMeta); return NewMeta - OldMeta; } virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override { const auto BlockBelow = a_Position.addedY(-1); if (!cChunkDef::IsValidHeight(BlockBelow)) { return false; } return a_Chunk.GetBlock(BlockBelow) == E_BLOCK_FARMLAND; } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 7; } }; ================================================ FILE: src/Blocks/BlockDaylightSensor.h ================================================ #pragma once #include "BlockHandler.h" class cBlockDaylightSensorHandler final : public cBlockHandler { using Super = cBlockHandler; public: using Super::Super; private: virtual bool OnUse( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, const Vector3i a_BlockPos, eBlockFace a_BlockFace, const Vector3i a_CursorPos ) const override { if (a_ChunkInterface.GetBlock(a_BlockPos) == E_BLOCK_DAYLIGHT_SENSOR) { a_ChunkInterface.SetBlock(a_BlockPos, E_BLOCK_INVERTED_DAYLIGHT_SENSOR, 0); } else { a_ChunkInterface.SetBlock(a_BlockPos, E_BLOCK_DAYLIGHT_SENSOR, 0); } return true; } virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override { // Always drop the regular daylight sensor: return { E_BLOCK_DAYLIGHT_SENSOR }; } virtual bool IsUseable(void) const override { return true; } }; ================================================ FILE: src/Blocks/BlockDeadBush.h ================================================ #pragma once #include "BlockHandler.h" class cBlockDeadBushHandler final : public cBlockHandler { using Super = cBlockHandler; public: using Super::Super; private: virtual bool DoesIgnoreBuildCollision(const cWorld & a_World, const cItem & a_HeldItem, const Vector3i a_Position, const NIBBLETYPE a_Meta, const eBlockFace a_ClickedBlockFace, const bool a_ClickedDirectly) const override { return true; } virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override { const auto PosBelow = a_Position.addedY(-1); if (!cChunkDef::IsValidHeight(PosBelow)) { return false; } BLOCKTYPE BelowBlock = a_Chunk.GetBlock(PosBelow); switch (BelowBlock) { case E_BLOCK_CLAY: case E_BLOCK_HARDENED_CLAY: case E_BLOCK_STAINED_CLAY: case E_BLOCK_SAND: { return true; } default: return false; } } virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override { // If cutting down with shears, drop self: if ((a_Tool != nullptr) && (a_Tool->m_ItemType == E_ITEM_SHEARS)) { return cItem(m_BlockType, 1, a_BlockMeta); } // Drop 0-3 sticks: auto chance = GetRandomProvider().RandInt(3); if (chance > 0) { return cItem(E_ITEM_STICK, chance, 0); } return {}; } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 0; } } ; ================================================ FILE: src/Blocks/BlockDefaultBlock.h ================================================ #pragma once class cDefaultBlockHandler final : public cBlockHandler { public: using cBlockHandler::cBlockHandler; }; ================================================ FILE: src/Blocks/BlockDirt.h ================================================ #pragma once #include "BlockHandler.h" class cBlockDirtHandler final : public cBlockHandler { using Super = cBlockHandler; public: using Super::Super; private: virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override { if (a_BlockMeta == E_META_DIRT_COARSE) { // Drop the coarse block (dirt, meta 1) return cItem(E_BLOCK_DIRT, 1, E_META_DIRT_COARSE); } else { return cItem(E_BLOCK_DIRT, 1, E_META_DIRT_NORMAL); } } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 10; } } ; ================================================ FILE: src/Blocks/BlockDoor.cpp ================================================ #include "Globals.h" #include "BlockDoor.h" #include "../EffectID.h" void cBlockDoorHandler::OnBroken( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, Vector3i a_BlockPos, BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta, const cEntity * a_Digger ) const { UNUSED(a_Digger); // A part of the multiblock door was broken; the relevant half will drop any pickups as required. // All that is left to do is to delete the other half of the multiblock. if ((a_OldBlockMeta & 0x08) != 0) { const auto Lower = a_BlockPos.addedY(-1); if ((Lower.y >= 0) && IsDoorBlockType(a_ChunkInterface.GetBlock(Lower))) { // Was upper part of door, remove lower: a_ChunkInterface.SetBlock(Lower, E_BLOCK_AIR, 0); } } else { const auto Upper = a_BlockPos.addedY(1); if ((Upper.y < cChunkDef::Height) && IsDoorBlockType(a_ChunkInterface.GetBlock(Upper))) { // Was lower part, remove upper: a_ChunkInterface.SetBlock(Upper, E_BLOCK_AIR, 0); } } } bool cBlockDoorHandler::OnUse( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, const Vector3i a_BlockPos, eBlockFace a_BlockFace, const Vector3i a_CursorPos ) const { UNUSED(a_WorldInterface); UNUSED(a_BlockFace); UNUSED(a_CursorPos); switch (a_ChunkInterface.GetBlock(a_BlockPos)) { default: { ASSERT(!"Unhandled door block type"); } case E_BLOCK_ACACIA_DOOR: case E_BLOCK_BIRCH_DOOR: case E_BLOCK_DARK_OAK_DOOR: case E_BLOCK_JUNGLE_DOOR: case E_BLOCK_SPRUCE_DOOR: case E_BLOCK_OAK_DOOR: { ChangeDoor(a_ChunkInterface, a_BlockPos); a_Player.GetWorld()->BroadcastSoundParticleEffect(EffectID::SFX_RANDOM_WOODEN_DOOR_OPEN, a_BlockPos, 0, a_Player.GetClientHandle()); break; } case E_BLOCK_IRON_DOOR: { // Prevent iron door from opening on player click (#2415): OnCancelRightClick(a_ChunkInterface, a_WorldInterface, a_Player, a_BlockPos, a_BlockFace); // Allow placement actions to instead take place: return false; } } return true; } void cBlockDoorHandler::OnCancelRightClick( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, const Vector3i a_BlockPos, eBlockFace a_BlockFace ) const { UNUSED(a_ChunkInterface); UNUSED(a_BlockFace); a_WorldInterface.SendBlockTo(a_BlockPos, a_Player); NIBBLETYPE Meta = a_ChunkInterface.GetBlockMeta(a_BlockPos); if (Meta & 0x08) { // Current block is top of the door, send the bottom part: a_WorldInterface.SendBlockTo(a_BlockPos.addedY(-1), a_Player); } else { // Current block is bottom of the door, send the top part: a_WorldInterface.SendBlockTo(a_BlockPos.addedY(1), a_Player); } } cBoundingBox cBlockDoorHandler::GetPlacementCollisionBox(BLOCKTYPE a_XM, BLOCKTYPE a_XP, BLOCKTYPE a_YM, BLOCKTYPE a_YP, BLOCKTYPE a_ZM, BLOCKTYPE a_ZP) const { // Doors can be placed inside the player return cBoundingBox(0, 0, 0, 0, 0, 0); } NIBBLETYPE cBlockDoorHandler::MetaRotateCCW(NIBBLETYPE a_Meta) const { if (a_Meta & 0x08) { // The meta doesn't change for the top block return a_Meta; } else { // Rotate the bottom block return Super::MetaRotateCCW(a_Meta); } } NIBBLETYPE cBlockDoorHandler::MetaRotateCW(NIBBLETYPE a_Meta) const { if (a_Meta & 0x08) { // The meta doesn't change for the top block return a_Meta; } else { // Rotate the bottom block return Super::MetaRotateCW(a_Meta); } } NIBBLETYPE cBlockDoorHandler::MetaMirrorXY(NIBBLETYPE a_Meta) const { /* Top bit (0x08) contains door block position (Top / Bottom). Only Bottom blocks contain position data Return a_Meta if panel is a top panel (0x08 bit is set to 1) */ // Note: Currently, you can not properly mirror the hinges on a double door. The orientation of the door is stored // in only the bottom tile while the hinge position is in the top tile. This function only operates on one tile at a time, // so the function can only see either the hinge position or orientation, but not both, at any given time. The class itself // needs extra datamembers. if (a_Meta & 0x08) { return a_Meta; } // Holds open / closed meta data. 0x0C == 1100. NIBBLETYPE OtherMeta = a_Meta & 0x0C; // Mirrors according to a table. 0x03 == 0011. switch (a_Meta & 0x03) { case 0x03: return 0x01 + OtherMeta; // South -> North case 0x01: return 0x03 + OtherMeta; // North -> South } // Not Facing North or South; No change. return a_Meta; } NIBBLETYPE cBlockDoorHandler::MetaMirrorYZ(NIBBLETYPE a_Meta) const { // Top bit (0x08) contains door panel type (Top / Bottom panel) Only Bottom panels contain position data // Return a_Meta if panel is a top panel (0x08 bit is set to 1) // Note: Currently, you can not properly mirror the hinges on a double door. The orientation of the door is stored // in only the bottom tile while the hinge position is in the top tile. This function only operates on one tile at a time, // so the function can only see either the hinge position or orientation, but not both, at any given time.The class itself // needs extra datamembers. if (a_Meta & 0x08) { return a_Meta; } // Holds open / closed meta data. 0x0C == 1100. NIBBLETYPE OtherMeta = a_Meta & 0x0C; // Mirrors according to a table. 0x03 == 0011. switch (a_Meta & 0x03) { case 0x00: return 0x02 + OtherMeta; // West -> East case 0x02: return 0x00 + OtherMeta; // East -> West } // Not Facing North or South; No change. return a_Meta; } ================================================ FILE: src/Blocks/BlockDoor.h ================================================ #pragma once #include "BlockHandler.h" #include "../BlockInfo.h" #include "../Entities/Player.h" #include "../Chunk.h" #include "Mixins/Mixins.h" #include "ChunkInterface.h" #include "BlockSlab.h" class cBlockDoorHandler final : public cYawRotator { using Super = cYawRotator; public: using Super::Super; /** Returns true if door can be placed on the specified block type. */ static bool CanBeOn(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) { // Vanilla refuses to place doors on transparent blocks, except top-half slabs and other doors // We need to keep the door compatible with itself, otherwise the top half drops while the bottom half stays // Doors can be placed on upside-down slabs if (cBlockSlabHandler::IsAnySlabType(a_BlockType) && ((a_BlockMeta & 0x08) != 0)) { return true; } // Doors can also be placed on other doors else if (IsDoorBlockType(a_BlockType)) { return true; } // Doors can not be placed on transparent blocks, but on any other block else { return !cBlockInfo::IsTransparent(a_BlockType); } } /** Returns a vector pointing one block in the direction the door is facing (where the outside is). */ inline static Vector3i GetRelativeDirectionToOutside(NIBBLETYPE a_BlockMeta) { switch (a_BlockMeta & 0x03) { case 0: return Vector3i(-1, 0, 0); // Facing West / XM case 1: return Vector3i(0, 0, -1); // Facing North / ZM case 2: return Vector3i(1, 0, 0); // Facing East / XP default: return Vector3i(0, 0, 1); // Facing South / ZP } } /** Returns true if the specified blocktype is any kind of door */ inline static bool IsDoorBlockType(BLOCKTYPE a_Block) { switch (a_Block) { case E_BLOCK_ACACIA_DOOR: case E_BLOCK_BIRCH_DOOR: case E_BLOCK_DARK_OAK_DOOR: case E_BLOCK_IRON_DOOR: case E_BLOCK_JUNGLE_DOOR: case E_BLOCK_SPRUCE_DOOR: case E_BLOCK_OAK_DOOR: { return true; } default: { return false; } } } /** Returns true iff the door at the specified coords is open. The coords may point to either the top part or the bottom part of the door. */ static bool IsOpen(cChunkInterface & a_ChunkInterface, const Vector3i a_BlockPos) { const auto Meta = GetCompleteDoorMeta(a_ChunkInterface, a_BlockPos); return (Meta & 0x04) != 0; } /** Sets the door to the specified state. If the door is already in that state, does nothing. */ static void SetOpen(cChunkInterface & a_ChunkInterface, const Vector3i a_BlockPos, bool a_Open) { BLOCKTYPE Block = a_ChunkInterface.GetBlock(a_BlockPos); if (!IsDoorBlockType(Block)) { return; } NIBBLETYPE Meta = GetCompleteDoorMeta(a_ChunkInterface, a_BlockPos); bool IsOpened = ((Meta & 0x04) != 0); if (IsOpened == a_Open) { return; } // Change the door NIBBLETYPE NewMeta = (Meta & 0x07) ^ 0x04; // Flip the "IsOpen" bit (0x04) if ((Meta & 0x08) == 0) { // The block is the bottom part of the door a_ChunkInterface.SetBlockMeta(a_BlockPos, NewMeta); } else { // The block is the top part of the door, set the meta to the corresponding top part if (a_BlockPos.y > 0) { a_ChunkInterface.SetBlockMeta(a_BlockPos.addedY(-1), NewMeta); } } } private: virtual void OnBroken( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, Vector3i a_BlockPos, BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta, const cEntity * a_Digger ) const override; virtual bool OnUse( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, const Vector3i a_BlockPos, eBlockFace a_BlockFace, const Vector3i a_CursorPos ) const override; virtual void OnCancelRightClick( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, const Vector3i a_BlockPos, eBlockFace a_BlockFace ) const override; virtual NIBBLETYPE MetaRotateCCW(NIBBLETYPE a_Meta) const override; virtual NIBBLETYPE MetaRotateCW(NIBBLETYPE a_Meta) const override; virtual NIBBLETYPE MetaMirrorXY(NIBBLETYPE a_Meta) const override; virtual NIBBLETYPE MetaMirrorYZ(NIBBLETYPE a_Meta) const override; virtual cBoundingBox GetPlacementCollisionBox(BLOCKTYPE a_XM, BLOCKTYPE a_XP, BLOCKTYPE a_YM, BLOCKTYPE a_YP, BLOCKTYPE a_ZM, BLOCKTYPE a_ZP) const override; virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override { switch (m_BlockType) { case E_BLOCK_OAK_DOOR: return cItem(E_ITEM_WOODEN_DOOR); case E_BLOCK_ACACIA_DOOR: return cItem(E_ITEM_ACACIA_DOOR); case E_BLOCK_BIRCH_DOOR: return cItem(E_ITEM_BIRCH_DOOR); case E_BLOCK_DARK_OAK_DOOR: return cItem(E_ITEM_DARK_OAK_DOOR); case E_BLOCK_JUNGLE_DOOR: return cItem(E_ITEM_JUNGLE_DOOR); case E_BLOCK_SPRUCE_DOOR: return cItem(E_ITEM_SPRUCE_DOOR); case E_BLOCK_IRON_DOOR: return cItem(E_ITEM_IRON_DOOR); default: { ASSERT(!"Unhandled door type!"); return {}; } } } virtual bool IsUseable(void) const override { return true; } virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override { // CanBeAt is also called on placement, so the top part can't check for the bottom part. // Both parts can only check that the base of the door (i.e. -2 for a door top) is a valid block. const auto BasePosition = a_Position.addedY(((a_Meta & 0x8) == 0x8) ? -2 : -1); if (!cChunkDef::IsValidHeight(BasePosition)) { return false; } BLOCKTYPE BlockType; NIBBLETYPE BlockMeta; a_Chunk.GetBlockTypeMeta(BasePosition, BlockType, BlockMeta); return CanBeOn(BlockType, BlockMeta); } /** Returns the complete meta composed from the both parts of the door as (TopMeta << 4) | BottomMeta The coords may point to either part of the door. The returned value has bit 3 (0x08) set iff the coords point to the top part of the door. Fails silently for (invalid) doors on the world's top and bottom. */ static NIBBLETYPE GetCompleteDoorMeta(cChunkInterface & a_ChunkInterface, const Vector3i a_BlockPos) { NIBBLETYPE Meta = a_ChunkInterface.GetBlockMeta(a_BlockPos); if ((Meta & 0x08) != 0) { // The coords are pointing at the top part of the door const auto BottomPos = a_BlockPos.addedY(-1); if (cChunkDef::IsValidHeight(BottomPos)) { NIBBLETYPE DownMeta = a_ChunkInterface.GetBlockMeta(BottomPos); return static_cast((DownMeta & 0x07) | 0x08 | (Meta << 4)); } // This is the top part of the door at the bottommost layer of the world, there's no bottom: return static_cast(0x08 | (Meta << 4)); } else { // The coords are pointing at the bottom part of the door const auto TopPos = a_BlockPos.addedY(1); if (cChunkDef::IsValidHeight(TopPos)) { NIBBLETYPE UpMeta = a_ChunkInterface.GetBlockMeta(TopPos); return static_cast(Meta | (UpMeta << 4)); } // This is the bottom part of the door at the topmost layer of the world, there's no top: return Meta; } } /** Changes the door at the specified coords from open to close or vice versa */ static void ChangeDoor(cChunkInterface & a_ChunkInterface, const Vector3i a_BlockPos) { SetOpen(a_ChunkInterface, a_BlockPos, !IsOpen(a_ChunkInterface, a_BlockPos)); } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); switch (m_BlockType) { case E_BLOCK_OAK_DOOR: return 13; case E_BLOCK_SPRUCE_DOOR: return 34; case E_BLOCK_BIRCH_DOOR: return 2; case E_BLOCK_JUNGLE_DOOR: return 10; case E_BLOCK_DARK_OAK_DOOR: return 26; case E_BLOCK_ACACIA_DOOR: return 15; case E_BLOCK_IRON_DOOR: return 6; default: { ASSERT(!"Unhandled blocktype in door handler!"); return 0; } } } } ; ================================================ FILE: src/Blocks/BlockDropSpenser.h ================================================ // BlockDropSpenser.h // Declares the cBlockDropSpenserHandler class representing the BlockHandler for Dropper and Dispenser blocks #pragma once #include "Mixins/Mixins.h" class cBlockDropSpenserHandler final : public cDisplacementYawRotator, 0x07, 0x03, 0x04, 0x02, 0x05, 0x01, 0x00> { using Super = cDisplacementYawRotator, 0x07, 0x03, 0x04, 0x02, 0x05, 0x01, 0x00>; public: using Super::Super; private: virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 11; } } ; ================================================ FILE: src/Blocks/BlockEnchantingTable.h ================================================ #pragma once #include "BlockHandler.h" #include "../Item.h" #include "../UI/EnchantingWindow.h" #include "../BlockEntities/EnchantingTableEntity.h" #include "../Entities/Player.h" class cBlockEnchantingTableHandler final : public cBlockHandler { using Super = cBlockHandler; public: using Super::Super; private: virtual bool OnUse( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, const Vector3i a_BlockPos, eBlockFace a_BlockFace, const Vector3i a_CursorPos ) const override { AString WindowName = "Enchant"; a_WorldInterface.DoWithBlockEntityAt(a_BlockPos, [&WindowName](cBlockEntity & a_Entity) { ASSERT(a_Entity.GetBlockType() == E_BLOCK_ENCHANTMENT_TABLE); const auto & EnchantingTable = static_cast(a_Entity); const auto & CustomName = EnchantingTable.GetCustomName(); if (!CustomName.empty()) { WindowName = CustomName; } return false; }); cWindow * Window = new cEnchantingWindow(a_BlockPos, std::move(WindowName)); a_Player.OpenWindow(*Window); return true; } virtual bool IsUseable(void) const override { return true; } virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override { // Drops handled by the block entity: return {}; } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 29; } }; ================================================ FILE: src/Blocks/BlockEndPortalFrame.h ================================================ #pragma once #include "BlockHandler.h" class cBlockEndPortalFrameHandler final : public cYawRotator { using Super = cYawRotator< cBlockHandler, 0x03, E_META_END_PORTAL_FRAME_ZP, E_META_END_PORTAL_FRAME_XM, E_META_END_PORTAL_FRAME_ZM, E_META_END_PORTAL_FRAME_XP >; public: using Super::Super; private: virtual void OnPlaced(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) const override { // E_META_END_PORTAL_FRAME_EYE is the bit which signifies the eye of ender is in it. // LOG("PortalPlaced, meta %d", a_BlockMeta); if ((a_BlockMeta & E_META_END_PORTAL_FRAME_EYE) == E_META_END_PORTAL_FRAME_EYE) { // LOG("Location is %d %d %d", a_BlockX, a_BlockY, a_BlockZ); // Direction is the first two bits, masked by 0x3 FindAndSetPortal(a_BlockPos, a_BlockMeta & 3, a_ChunkInterface, a_WorldInterface); } } /** Returns false if portal cannot be made, true if portal was made. */ static bool FindAndSetPortal(Vector3i a_FirstFrame, NIBBLETYPE a_Direction, cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface) { /* PORTAL FINDING ALGORITH ======================= - Get clicked base block - Check diagonally (clockwise) for another portal block - if exists, and has eye, Continue. Abort if any are facing the wrong direction. - if doesn't exist, check horizontally (the block to the left of this block). Abort if there is no horizontal block. - After a corner has been met, traverse the portal clockwise, ensuring valid portal frames connect the rectangle. - Track the NorthWest Corner, and the dimensions. - If dimensions are valid, create the portal. */ static_assert((E_META_END_PORTAL_FRAME_ZM - E_META_END_PORTAL_FRAME_XM) == 1, "Should be going clockwise"); const int MIN_PORTAL_WIDTH = 3; const int MAX_PORTAL_WIDTH = 4; // Directions to use for the clockwise traversal. static const Vector3i Left[] = { { 1, 0, 0}, // 0, South, left block is East / XP { 0, 0, 1}, // 1, West, left block is South / ZP {-1, 0, 0}, // 2, North, left block is West / XM { 0, 0, -1}, // 3, East, left block is North / ZM }; static const Vector3i LeftForward[] = { { 1, 0, 1}, // 0, South, left block is SouthEast / XP ZP {-1, 0, 1}, // 1, West, left block is SouthWest / XM ZP {-1, 0, -1}, // 2, North, left block is NorthWest / XM ZM { 1, 0, -1}, // 3, East, left block is NorthEast / XP ZM }; int EdgesComplete = -1; // We start search _before_ finding the first edge Vector3i NorthWestCorner; int EdgeWidth[4] = { 1, 1, 1, 1 }; NIBBLETYPE CurrentDirection = a_Direction; Vector3i CurrentPos = a_FirstFrame; // Scan clockwise until we have seen all 4 edges while (EdgesComplete < 4) { // Check if we are at a corner Vector3i NextPos = CurrentPos + LeftForward[CurrentDirection]; if (IsPortalFrame(a_ChunkInterface.GetBlock(NextPos))) { // We have found the corner, move clockwise to next edge if (CurrentDirection == E_META_END_PORTAL_FRAME_XP) { // We are on the NW (XM, ZM) Corner // Relative to the previous frame, the portal should appear to the right of this portal frame. NorthWestCorner = NextPos - Left[CurrentDirection]; } if (EdgesComplete == -1) { // Reset current width, we will revisit it last EdgeWidth[CurrentDirection] = 1; } // Rotate 90 degrees clockwise CurrentDirection = (CurrentDirection + 1) % 4; EdgesComplete++; } else { // We are not at a corner, keep walking the edge NextPos = CurrentPos + Left[CurrentDirection]; EdgeWidth[CurrentDirection]++; if (EdgeWidth[CurrentDirection] > MAX_PORTAL_WIDTH) { // Don't build a portal that is too long. return false; } } if (!IsValidFrameAtPos(a_ChunkInterface, NextPos, CurrentDirection)) { // Neither the edge nor the corner are valid portal blocks. return false; } CurrentPos = NextPos; } if ((EdgeWidth[0] != EdgeWidth[2]) || (EdgeWidth[1] != EdgeWidth[3])) { // Mismatched Portal Dimensions. return false; } if ((EdgeWidth[0] < MIN_PORTAL_WIDTH) || (EdgeWidth[1] < MIN_PORTAL_WIDTH)) { // Portal too small. return false; } // LOG("NW corner (low corner) %d %d %d", Corner.x, Corner.y, Corner.z); // LOG("%d by %d", Width[0], Width[1]); for (int i = 0; i < EdgeWidth[0]; i++) { for (int j = 0; j < EdgeWidth[1]; j++) { a_ChunkInterface.SetBlock(NorthWestCorner.x + i, NorthWestCorner.y, NorthWestCorner.z + j, E_BLOCK_END_PORTAL, 0); // TODO: Create block entity so portal doesn't become invisible on relog. } } return true; } /** Return true if this block is a portal frame, has an eye, and is facing the correct direction. */ static bool IsValidFrameAtPos(cChunkInterface & a_ChunkInterface, Vector3i a_BlockPos, NIBBLETYPE a_ShouldFace) { BLOCKTYPE BlockType; NIBBLETYPE BlockMeta; return ( a_ChunkInterface.GetBlockTypeMeta(a_BlockPos, BlockType, BlockMeta) && (BlockType == E_BLOCK_END_PORTAL_FRAME) && (BlockMeta == (a_ShouldFace | E_META_END_PORTAL_FRAME_EYE)) ); } /** Return true if this block is a portal frame. */ static bool IsPortalFrame(BLOCKTYPE BlockType) { return (BlockType == E_BLOCK_END_PORTAL_FRAME); } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 27; } }; ================================================ FILE: src/Blocks/BlockEnderChest.h ================================================ #pragma once #include "Mixins/Mixins.h" class cBlockEnderChestHandler final : public cYawRotator { using Super = cYawRotator; public: using Super::Super; private: virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override { // Only drop something when mined with a pickaxe: if ( (a_Tool != nullptr) && ItemCategory::IsPickaxe(a_Tool->m_ItemType) ) { // Only drop self when mined with a silk-touch pickaxe: if (a_Tool->m_Enchantments.GetLevel(cEnchantments::enchSilkTouch) > 0) { return cItem(E_BLOCK_ENDER_CHEST); } return cItem(E_BLOCK_OBSIDIAN, 8); } return {}; } }; ================================================ FILE: src/Blocks/BlockEntity.h ================================================ #pragma once #include "BlockHandler.h" #include "ChunkInterface.h" #include "../Item.h" /** Wrapper for blocks that have a cBlockEntity descendant attached to them and can be "used" by the player. Forwards the "use" event to the block entity. */ class cBlockEntityHandler : public cBlockHandler { using Super = cBlockHandler; public: using Super::Super; protected: ~cBlockEntityHandler() = default; private: virtual bool OnUse( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, const Vector3i a_BlockPos, eBlockFace a_BlockFace, const Vector3i a_CursorPos ) const override { return a_ChunkInterface.UseBlockEntity(&a_Player, a_BlockPos.x, a_BlockPos.y, a_BlockPos.z); } virtual bool IsUseable() const override { return true; } }; class cDefaultBlockEntityHandler final : public cBlockEntityHandler { public: using cBlockEntityHandler::cBlockEntityHandler; }; ================================================ FILE: src/Blocks/BlockFarmland.h ================================================ // BlockFarmland.h // Declares the cBlcokFarmlandHandler representing the block handler for farmland #pragma once #include "BlockHandler.h" #include "ChunkInterface.h" #include "../BlockArea.h" #include "../Chunk.h" #include "../ClientHandle.h" class cBlockFarmlandHandler final : public cBlockHandler { using Super = cBlockHandler; public: using Super::Super; /** Turns farmland into dirt. Will first check for any colliding entities and teleport them to a higher position. */ static void TurnToDirt(cChunk & a_Chunk, Vector3i a_AbsPos) { auto RelPos = cChunkDef::AbsoluteToRelative(a_AbsPos); TurnToDirt(a_Chunk, a_AbsPos, RelPos); } /** Turns farmland into dirt. Will first check for any colliding entities and teleport them to a higher position. */ static void TurnToDirt(cChunk & a_Chunk, const Vector3i a_AbsPos, const Vector3i a_RelPos) { // Use cBlockInfo::GetBlockHeight when it doesn't break trampling for // mobs and older clients anymore static const auto FarmlandHeight = 0.9375; static const auto FullHeightDelta = 0.0625; a_Chunk.ForEachEntityInBox( cBoundingBox(Vector3d(0.5, FarmlandHeight, 0.5) + a_AbsPos, 0.5, FullHeightDelta), [&](cEntity & Entity) { const auto GroundHeight = a_AbsPos.y + 1; // A simple IsOnGround isn't enough. It will return true when // e.g. a piston pushes a farmland block into an entity's head. // Maybe it's also possible than an entity is falling, it's // still not on the ground, but it's less than 0.0625 blocks // higher than the farmland block if ((Entity.GetPosY() < a_AbsPos.y + FarmlandHeight) || (Entity.GetPosY() >= GroundHeight)) { return false; } // Players need a packet that will update their position if (Entity.IsPlayer()) { const auto HeightIncrease = GroundHeight - Entity.GetPosY(); const auto Player = static_cast(&Entity); Player->GetClientHandle()->SendPlayerMoveLook(Vector3d(0.0, HeightIncrease, 0.0), 0.0f, 0.0f, true); } Entity.SetPosY(GroundHeight); return false; }); a_Chunk.SetBlock(a_RelPos, E_BLOCK_DIRT, 0); } private: virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override { return cItem(E_BLOCK_DIRT, 1, 0); } virtual void OnUpdate( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cBlockPluginInterface & a_PluginInterface, cChunk & a_Chunk, const Vector3i a_RelPos ) const override { auto BlockMeta = a_Chunk.GetMeta(a_RelPos); if (IsWaterInNear(a_Chunk, a_RelPos)) { // Water was found, set block meta to 7 a_Chunk.FastSetBlock(a_RelPos, m_BlockType, 7); return; } // Water wasn't found, de-hydrate block: if (BlockMeta > 0) { a_Chunk.FastSetBlock(a_RelPos, E_BLOCK_FARMLAND, --BlockMeta); return; } // Farmland too dry. If nothing is growing on top, turn back to dirt: auto UpperBlock = cChunkDef::IsValidHeight(a_RelPos.addedY(1)) ? a_Chunk.GetBlock(a_RelPos.addedY(1)) : E_BLOCK_AIR; switch (UpperBlock) { case E_BLOCK_BEETROOTS: case E_BLOCK_CROPS: case E_BLOCK_POTATOES: case E_BLOCK_CARROTS: case E_BLOCK_MELON_STEM: case E_BLOCK_PUMPKIN_STEM: { // Produce on top, don't revert break; } default: { auto AbsPos = a_Chunk.RelativeToAbsolute(a_RelPos); TurnToDirt(a_Chunk, AbsPos, a_RelPos); break; } } } virtual void OnNeighborChanged(cChunkInterface & a_ChunkInterface, Vector3i a_BlockPos, eBlockFace a_WhichNeighbor) const override { // Don't care about any neighbor but the one above us (fix recursion loop in #2213): if (a_WhichNeighbor != BLOCK_FACE_YP) { return; } // Don't care about anything if we're at the top of the world: if (a_BlockPos.y >= cChunkDef::Height) { return; } // Check whether we should revert to dirt: // TODO: fix for signs and slabs (possibly more blocks) - they should destroy farmland auto upperBlock = a_ChunkInterface.GetBlock(a_BlockPos.addedY(1)); if (cBlockInfo::FullyOccupiesVoxel(upperBlock)) { // Until the fix above is done, this line should also suffice: // a_ChunkInterface.SetBlock(a_BlockPos, E_BLOCK_DIRT, 0); a_ChunkInterface.DoWithChunkAt(a_BlockPos, [&](cChunk & Chunk) { TurnToDirt(Chunk, a_BlockPos); return true; }); } } /** Returns true if there's either a water source block close enough to hydrate the specified position, or it's raining there. */ static bool IsWaterInNear(const cChunk & a_Chunk, const Vector3i a_RelPos) { if (a_Chunk.IsWeatherWetAt(a_RelPos.addedY(1))) { // Rain hydrates farmland, too return true; } const auto WorldPos = a_Chunk.RelativeToAbsolute(a_RelPos); // Search for water in a close proximity: // Ref.: https://minecraft.wiki/w/Farmland#Hydration // TODO: Rewrite this to use the chunk and its neighbors directly cBlockArea Area; if (!Area.Read(*a_Chunk.GetWorld(), WorldPos - Vector3i(4, 0, 4), WorldPos + Vector3i(4, 1, 4))) { // Too close to the world edge, cannot check surroundings return false; } size_t NumBlocks = Area.GetBlockCount(); BLOCKTYPE * BlockTypes = Area.GetBlockTypes(); for (size_t i = 0; i < NumBlocks; i++) { if (IsBlockWater(BlockTypes[i])) { return true; } } // for i - BlockTypes[] return false; } virtual bool CanSustainPlant(BLOCKTYPE a_Plant) const override { return ( (a_Plant == E_BLOCK_BEETROOTS) || (a_Plant == E_BLOCK_CROPS) || (a_Plant == E_BLOCK_CARROTS) || (a_Plant == E_BLOCK_POTATOES) || (a_Plant == E_BLOCK_MELON_STEM) || (a_Plant == E_BLOCK_PUMPKIN_STEM) ); } } ; ================================================ FILE: src/Blocks/BlockFence.h ================================================ #pragma once #include "BlockHandler.h" #include "../BoundingBox.h" #include "../EffectID.h" #include "../Entities/LeashKnot.h" #include "../BoundingBox.h" #include "../Mobs/PassiveMonster.h" class cBlockFenceHandler final : public cBlockHandler { using Super = cBlockHandler; public: using Super::Super; private: // These are the min and max coordinates (X and Z) for a straight fence. // 0.4 and 0.6 are really just guesses, but they seem pretty good. // (0.4 to 0.6 is a fence that's 0.2 wide, down the center of the block) static constexpr double MIN_COORD = 0.4; static constexpr double MAX_COORD = 0.6; virtual cBoundingBox GetPlacementCollisionBox(BLOCKTYPE a_XM, BLOCKTYPE a_XP, BLOCKTYPE a_YM, BLOCKTYPE a_YP, BLOCKTYPE a_ZM, BLOCKTYPE a_ZP) const override { bool XMSolid = cBlockInfo::IsSolid(a_XM); bool XPSolid = cBlockInfo::IsSolid(a_XP); bool ZMSolid = cBlockInfo::IsSolid(a_ZM); bool ZPSolid = cBlockInfo::IsSolid(a_ZP); double FENCE_HEIGHT = cBlockInfo::GetBlockHeight(m_BlockType); // Entities can never be in the center cBoundingBox PlacementBox(MIN_COORD, MAX_COORD, 0, FENCE_HEIGHT, MIN_COORD, MAX_COORD); // For each solid neighbor, the hitbox extends that way if (XMSolid) { PlacementBox = PlacementBox.Union(cBoundingBox(0, 0.5, 0, FENCE_HEIGHT, MIN_COORD, MAX_COORD)); } if (XPSolid) { PlacementBox = PlacementBox.Union(cBoundingBox(0.5, 1.0, 0, FENCE_HEIGHT, MIN_COORD, MAX_COORD)); } if (ZMSolid) { PlacementBox = PlacementBox.Union(cBoundingBox(MIN_COORD, MAX_COORD, 0, FENCE_HEIGHT, 0.0, 0.5)); } if (ZPSolid) { PlacementBox = PlacementBox.Union(cBoundingBox(MIN_COORD, MAX_COORD, 0, FENCE_HEIGHT, 0.5, 1.0)); } // For each corner, fill in the corner if (XMSolid && ZMSolid) { PlacementBox = PlacementBox.Union(cBoundingBox(0, 0.5, 0, FENCE_HEIGHT, 0, 0.5)); } if (XPSolid && ZMSolid) { PlacementBox = PlacementBox.Union(cBoundingBox(0.5, 1.0, 0, FENCE_HEIGHT, 0, 0.5)); } if (XPSolid && ZPSolid) { PlacementBox = PlacementBox.Union(cBoundingBox(0.5, 1.0, 0, FENCE_HEIGHT, 0.5, 1.0)); } if (XMSolid && ZPSolid) { PlacementBox = PlacementBox.Union(cBoundingBox(0, 0.5, 0, FENCE_HEIGHT, 0.5, 1.0)); } return PlacementBox; } virtual bool OnUse( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, const Vector3i a_BlockPos, eBlockFace a_BlockFace, const Vector3i a_CursorPos ) const override { auto LeashKnot = cLeashKnot::FindKnotAtPos(*a_Player.GetWorld(), a_BlockPos); auto KnotAlreadyExists = (LeashKnot != nullptr); if (KnotAlreadyExists) { // Check leashed nearby mobs to leash them to the knot LeashKnot->TiePlayersLeashedMobs(a_Player, KnotAlreadyExists); } // New knot? needs to init and produce sound effect else { auto NewLeashKnot = std::make_unique(a_BlockFace, a_BlockPos); auto NewLeashKnotPtr = NewLeashKnot.get(); NewLeashKnotPtr->TiePlayersLeashedMobs(a_Player, KnotAlreadyExists); // Only put the knot in the world if any mob has been leashed to if (NewLeashKnotPtr->HasAnyMobLeashed()) { if (!NewLeashKnotPtr->Initialize(std::move(NewLeashKnot), *a_Player.GetWorld())) { return false; } a_Player.GetWorld()->BroadcastSoundEffect("entity.leashknot.place", a_Player.GetPosition(), 1, 1); } else { return false; } } return true; } virtual void OnCancelRightClick( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, const Vector3i a_BlockPos, eBlockFace a_BlockFace ) const override { a_WorldInterface.SendBlockTo(a_BlockPos, a_Player); } virtual bool IsUseable(void) const override { return true; } virtual void OnBroken( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, Vector3i a_BlockPos, BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta, const cEntity * a_Digger ) const override { UNUSED(a_Digger); // Destroy any leash knot tied to the fence: auto leashKnot = cLeashKnot::FindKnotAtPos(a_WorldInterface, a_BlockPos); if (leashKnot != nullptr) { leashKnot->SetShouldSelfDestroy(); } } }; ================================================ FILE: src/Blocks/BlockFenceGate.h ================================================ #pragma once #include "BlockHandler.h" #include "Mixins/Mixins.h" #include "../EffectID.h" class cBlockFenceGateHandler final : public cClearMetaOnDrop> { using Super = cClearMetaOnDrop>; public: using Super::Super; private: virtual bool OnUse( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, const Vector3i a_BlockPos, eBlockFace a_BlockFace, const Vector3i a_CursorPos ) const override { NIBBLETYPE OldMetaData = a_ChunkInterface.GetBlockMeta(a_BlockPos); NIBBLETYPE NewMetaData = YawToMetaData(a_Player.GetYaw()); OldMetaData ^= 4; // Toggle the gate if ((OldMetaData & 1) == (NewMetaData & 1)) { // Standing in front of the gate - apply new direction a_ChunkInterface.SetBlockMeta(a_BlockPos, (OldMetaData & 4) | (NewMetaData & 3)); } else { // Standing aside - use last direction a_ChunkInterface.SetBlockMeta(a_BlockPos, OldMetaData); } a_Player.GetWorld()->BroadcastSoundParticleEffect(EffectID::SFX_RANDOM_FENCE_GATE_OPEN, a_BlockPos, 0, a_Player.GetClientHandle()); return true; } virtual void OnCancelRightClick( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, const Vector3i a_BlockPos, eBlockFace a_BlockFace ) const override { a_WorldInterface.SendBlockTo(a_BlockPos, a_Player); } virtual bool IsUseable(void) const override { return true; } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); switch (m_BlockType) { case E_BLOCK_OAK_FENCE_GATE: return 13; case E_BLOCK_SPRUCE_FENCE_GATE: return 34; case E_BLOCK_BIRCH_FENCE_GATE: return 2; case E_BLOCK_JUNGLE_FENCE_GATE: return 10; case E_BLOCK_DARK_OAK_FENCE_GATE: return 26; case E_BLOCK_ACACIA_FENCE_GATE: return 15; default: { ASSERT(!"Unhandled blocktype in fence gate handler!"); return 0; } } } } ; ================================================ FILE: src/Blocks/BlockFire.h ================================================ #pragma once #include "BlockHandler.h" class cBlockFireHandler final : public cBlockHandler { public: using cBlockHandler::cBlockHandler; private: struct Scratch { /** Portal boundary and direction variables */ int XZP = 0, XZM = 0; NIBBLETYPE Dir = 0; }; virtual void OnPlaced(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) const override { /* PORTAL FINDING ALGORITH ======================= - Get clicked base block - Trace upwards to find first obsidian block; aborts if anything other than obsidian or air is encountered. Uses this value as a reference (the 'ceiling') - For both directions (if one fails, try the other), BASE (clicked) block: - Go in one direction, only stop if a non obsidian block is encountered (abort) OR a portal border is encountered (FindObsidianCeiling returns -1) - If a border was encountered, go the other direction and repeat above - Write borders to XZP and XZM, write direction portal faces to Dir - Loop through boundary variables, and fill with portal blocks based on Dir with meta from Dir */ if (a_WorldInterface.GetDimension() == dimEnd) { // Can only create portals in the Nether and Overworld (GH #5009): return; } Scratch Scratch; // a_BlockY - 1: Because we want the block below the fire FindAndSetPortalFrame(a_BlockPos.x, a_BlockPos.y - 1, a_BlockPos.z, a_ChunkInterface, a_WorldInterface, Scratch); } virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override { // No pickups from this block return {}; } /** Traces along YP until it finds an obsidian block, returns Y difference or 0 if no portal, and -1 for border Takes the X, Y, and Z of the base block; with an optional MaxY for portal border finding */ static int FindObsidianCeiling(int X, int Y, int Z, cChunkInterface & a_ChunkInterface, int MaxY = 0) { if (a_ChunkInterface.GetBlock({X, Y, Z}) != E_BLOCK_OBSIDIAN) { return 0; } for (int newY = Y + 1; newY < cChunkDef::Height; newY++) { BLOCKTYPE Block = a_ChunkInterface.GetBlock({X, newY, Z}); if ((Block == E_BLOCK_AIR) || (Block == E_BLOCK_FIRE)) { continue; } else if (Block == E_BLOCK_OBSIDIAN) { // We found an obsidian ceiling // Make sure MaxY has a value and newY ('ceiling' location) is at one above the base block // This is because the frame is a solid obsidian pillar if ((MaxY != 0) && (newY == Y + 1)) { return EvaluatePortalBorder(X, newY, Z, MaxY, a_ChunkInterface) ? -1 /* -1 = found a frame */ : 0; } else { // Return ceiling Y, whoever called this function will decide if it's part of a portal or not return newY; } } } return 0; } /** Evaluates if coords have a valid border on top, based on MaxY */ static bool EvaluatePortalBorder(int X, int FoundObsidianY, int Z, int MaxY, cChunkInterface & a_ChunkInterface) { for (int checkBorder = FoundObsidianY + 1; checkBorder <= MaxY - 1; checkBorder++) // FoundObsidianY + 1: FoundObsidianY has already been checked in FindObsidianCeiling; MaxY - 1: portal doesn't need corners { if (a_ChunkInterface.GetBlock({X, checkBorder, Z}) != E_BLOCK_OBSIDIAN) { // Base obsidian, base + 1 obsidian, base + x NOT obsidian -> not complete portal return false; } } // Everything was obsidian, found a border! return true; } /** Finds entire frame in any direction with the coordinates of a base block and fills hole with nether portal (START HERE) */ static void FindAndSetPortalFrame(int X, int Y, int Z, cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, Scratch & a_Scratch) { int MaxY = FindObsidianCeiling(X, Y, Z, a_ChunkInterface); // Get topmost obsidian block as reference for all other checks int X1 = X + 1, Z1 = Z + 1, X2 = X - 1, Z2 = Z - 1; // Duplicate XZ values, add / subtract one as we've checked the original already the line above if (MaxY == 0) // Oh noes! Not a portal coordinate :( { return; } if (!FindPortalSliceX(X1, X2, Y, Z, MaxY, a_ChunkInterface, a_Scratch)) { if (!FindPortalSliceZ(X, Y, Z1, Z2, MaxY, a_ChunkInterface, a_Scratch)) { return; // No eligible portal construct, abort abort abort!! } } int PortalHeight = MaxY - Y - 1; int PortalWidth = a_Scratch.XZP - a_Scratch.XZM + 1; if ((PortalHeight < a_WorldInterface.GetMinNetherPortalHeight()) || (PortalHeight > a_WorldInterface.GetMaxNetherPortalHeight())) { // The portal isn't high enough, or is too high return; } if ((PortalWidth < a_WorldInterface.GetMinNetherPortalWidth()) || (PortalWidth > a_WorldInterface.GetMaxNetherPortalWidth())) { // The portal isn't wide enough, or is too wide return; } for (int Height = Y + 1; Height <= MaxY - 1; Height++) // Loop through boundary to set portal blocks { for (int Width = a_Scratch.XZM; Width <= a_Scratch.XZP; Width++) { if (a_Scratch.Dir == 1) { a_ChunkInterface.SetBlock(Width, Height, Z, E_BLOCK_NETHER_PORTAL, a_Scratch.Dir); } else { a_ChunkInterface.SetBlock(X, Height, Width, E_BLOCK_NETHER_PORTAL, a_Scratch.Dir); } } } } /** Evaluates if coordinates are a portal going XP / XM; returns true if so, and writes boundaries to variable Takes coordinates of base block and Y coord of target obsidian ceiling */ static bool FindPortalSliceX(int X1, int X2, int Y, int Z, int MaxY, cChunkInterface & a_ChunkInterface, Scratch & a_Scratch) { a_Scratch.Dir = 1; // Set assumed direction (will change if portal turns out to be facing the other direction) bool FoundFrameXP = false, FoundFrameXM = false; for (; ((a_ChunkInterface.GetBlock({X1, Y, Z}) == E_BLOCK_OBSIDIAN) || (a_ChunkInterface.GetBlock({X1, Y + 1, Z}) == E_BLOCK_OBSIDIAN)); X1++) // Check XP for obsidian blocks, exempting corners { int Value = FindObsidianCeiling(X1, Y, Z, a_ChunkInterface, MaxY); int ValueTwo = FindObsidianCeiling(X1, Y + 1, Z, a_ChunkInterface, MaxY); // For corners without obsidian if ((Value == -1) || (ValueTwo == -1)) // FindObsidianCeiling returns -1 upon frame-find { FoundFrameXP = true; // Found a frame border in this direction, proceed in other direction (don't go further) break; } else if ((Value != MaxY) && (ValueTwo != MaxY)) // Make sure that there is a valid portal 'slice' { return false; // Not valid slice, no portal can be formed } } a_Scratch.XZP = X1 - 1; // Set boundary of frame interior for (; ((a_ChunkInterface.GetBlock({X2, Y, Z}) == E_BLOCK_OBSIDIAN) || (a_ChunkInterface.GetBlock({X2, Y + 1, Z}) == E_BLOCK_OBSIDIAN)); X2--) // Go the other direction (XM) { int Value = FindObsidianCeiling(X2, Y, Z, a_ChunkInterface, MaxY); int ValueTwo = FindObsidianCeiling(X2, Y + 1, Z, a_ChunkInterface, MaxY); if ((Value == -1) || (ValueTwo == -1)) { FoundFrameXM = true; break; } else if ((Value != MaxY) && (ValueTwo != MaxY)) { return false; } } a_Scratch.XZM = X2 + 1; // Set boundary, see previous return (FoundFrameXP && FoundFrameXM); } /** Evaluates if coords are a portal going ZP / ZM; returns true if so, and writes boundaries to variable */ static bool FindPortalSliceZ(int X, int Y, int Z1, int Z2, int MaxY, cChunkInterface & a_ChunkInterface, Scratch & a_Scratch) { a_Scratch.Dir = 2; bool FoundFrameZP = false, FoundFrameZM = false; for (; ((a_ChunkInterface.GetBlock({X, Y, Z1}) == E_BLOCK_OBSIDIAN) || (a_ChunkInterface.GetBlock({X, Y + 1, Z1}) == E_BLOCK_OBSIDIAN)); Z1++) { int Value = FindObsidianCeiling(X, Y, Z1, a_ChunkInterface, MaxY); int ValueTwo = FindObsidianCeiling(X, Y + 1, Z1, a_ChunkInterface, MaxY); if ((Value == -1) || (ValueTwo == -1)) { FoundFrameZP = true; break; } else if ((Value != MaxY) && (ValueTwo != MaxY)) { return false; } } a_Scratch.XZP = Z1 - 1; for (; ((a_ChunkInterface.GetBlock({X, Y, Z2}) == E_BLOCK_OBSIDIAN) || (a_ChunkInterface.GetBlock({X, Y + 1, Z2}) == E_BLOCK_OBSIDIAN)); Z2--) { int Value = FindObsidianCeiling(X, Y, Z2, a_ChunkInterface, MaxY); int ValueTwo = FindObsidianCeiling(X, Y + 1, Z2, a_ChunkInterface, MaxY); if ((Value == -1) || (ValueTwo == -1)) { FoundFrameZM = true; break; } else if ((Value != MaxY) && (ValueTwo != MaxY)) { return false; } } a_Scratch.XZM = Z2 + 1; return (FoundFrameZP && FoundFrameZM); } virtual bool DoesIgnoreBuildCollision(const cWorld & a_World, const cItem & a_HeldItem, const Vector3i a_Position, const NIBBLETYPE a_Meta, const eBlockFace a_ClickedBlockFace, const bool a_ClickedDirectly) const override { return true; } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 15; } }; ================================================ FILE: src/Blocks/BlockFlower.h ================================================ #pragma once #include "BlockHandler.h" #include "Mixins/DirtLikeUnderneath.h" class cBlockFlowerHandler final : public cDirtLikeUnderneath { using Super = cDirtLikeUnderneath; public: using Super::Super; private: virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override { NIBBLETYPE meta = a_BlockMeta & 0x7; return cItem(m_BlockType, 1, meta); } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 7; } } ; ================================================ FILE: src/Blocks/BlockFlowerPot.h ================================================ #pragma once class cBlockFlowerPotHandler final : public cBlockEntityHandler { using Super = cBlockEntityHandler; public: using Super::Super; private: virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override { return cItem(E_ITEM_FLOWER_POT, 1, 0); } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 0; } } ; ================================================ FILE: src/Blocks/BlockFluid.h ================================================ #pragma once #include "BlockHandler.h" class cBlockFluidHandler : public cBlockHandler { using Super = cBlockHandler; public: using Super::Super; protected: ~cBlockFluidHandler() = default; private: virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override { // No pickups return {}; } virtual bool DoesIgnoreBuildCollision(const cWorld & a_World, const cItem & a_HeldItem, const Vector3i a_Position, const NIBBLETYPE a_Meta, const eBlockFace a_ClickedBlockFace, const bool a_ClickedDirectly) const override { return true; } } ; class cBlockLavaHandler final : public cBlockFluidHandler { using Super = cBlockFluidHandler; public: using Super::Super; private: virtual void OnUpdate( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cBlockPluginInterface & a_PluginInterface, cChunk & a_Chunk, const Vector3i a_RelPos ) const override { if (a_Chunk.GetWorld()->ShouldLavaSpawnFire()) { // Try to start up to 5 fires: for (int i = 0; i < 5; i++) { TryStartFireNear(a_RelPos, a_Chunk); } } } /** Tries to start a fire near the lava at given coords. Returns true if fire started. */ static bool TryStartFireNear(const Vector3i a_RelPos, cChunk & a_Chunk) { // Pick a random block next to this lava block: int rnd = a_Chunk.GetWorld()->GetTickRandomNumber(cChunkDef::NumBlocks * 8) / 7; int x = (rnd % 3) - 1; // -1 .. 1 int y = ((rnd / 4) % 4) - 1; // -1 .. 2 int z = ((rnd / 16) % 3) - 1; // -1 .. 1 auto Pos = a_RelPos + Vector3i(x, y, z); // Check if it's fuel: BLOCKTYPE BlockType; if ( !cChunkDef::IsValidHeight(Pos) || !a_Chunk.UnboundedRelGetBlockType(Pos, BlockType) || !cFireSimulator::IsFuel(BlockType) ) { return false; } // Try to set it on fire: static Vector3i CrossCoords[] = { {-1, 0, 0}, { 1, 0, 0}, { 0, -1, 0}, { 0, 1, 0}, { 0, 0, -1}, { 0, 0, 1}, } ; for (size_t i = 0; i < ARRAYCOUNT(CrossCoords); i++) { auto NeighborPos = Pos + CrossCoords[i]; if ( cChunkDef::IsValidHeight(NeighborPos) && a_Chunk.UnboundedRelGetBlockType(NeighborPos, BlockType) && (BlockType == E_BLOCK_AIR) ) { // This is an air block next to a fuel next to lava, light the fuel block up: a_Chunk.UnboundedRelSetBlock(NeighborPos, E_BLOCK_FIRE, 0); return true; } } // for i - CrossCoords[] return false; } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 4; } virtual bool CanSustainPlant(BLOCKTYPE a_Plant) const override { return false; } } ; class cBlockWaterHandler final : public cBlockFluidHandler { public: using cBlockFluidHandler::cBlockFluidHandler; private: virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); if (IsBlockWater(m_BlockType)) { return 12; } ASSERT(!"Unhandled blocktype in fluid/water handler!"); return 0; } virtual bool CanSustainPlant(BLOCKTYPE a_Plant) const override { return ( (a_Plant == E_BLOCK_BEETROOTS) || (a_Plant == E_BLOCK_CROPS) || (a_Plant == E_BLOCK_CARROTS) || (a_Plant == E_BLOCK_POTATOES) || (a_Plant == E_BLOCK_MELON_STEM) || (a_Plant == E_BLOCK_PUMPKIN_STEM) ); } }; ================================================ FILE: src/Blocks/BlockFurnace.h ================================================ #pragma once #include "Mixins/Mixins.h" class cBlockFurnaceHandler final : public cYawRotator { using Super = cYawRotator; public: using Super::Super; private: virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override { return cItem(E_BLOCK_FURNACE); // We can't drop a lit furnace } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 11; } } ; ================================================ FILE: src/Blocks/BlockGlass.h ================================================ #pragma once #include "BlockHandler.h" class cBlockGlassHandler final : public cBlockHandler { public: using cBlockHandler::cBlockHandler; private: virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override { // Only drop self when mined with silk-touch: if (ToolHasSilkTouch(a_Tool)) { return cItem(m_BlockType, 1, a_BlockMeta); } return {}; } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 0; } } ; ================================================ FILE: src/Blocks/BlockGlazedTerracotta.h ================================================ #pragma once #include "Mixins/Mixins.h" class cBlockGlazedTerracottaHandler final : public cClearMetaOnDrop> { using Super = cClearMetaOnDrop>; public: using Super::Super; }; ================================================ FILE: src/Blocks/BlockGlowstone.h ================================================ #pragma once #include "BlockHandler.h" class cBlockGlowstoneHandler final : public cBlockHandler { public: using cBlockHandler::cBlockHandler; private: virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override { // Drop self only when using silk-touch: if (ToolHasSilkTouch(a_Tool)) { return cItem(E_BLOCK_GLOWSTONE); } // Number of dust to drop, capped at the max amount of 4. const auto DropNum = FortuneDiscreteRandom(2, 4, ToolFortuneLevel(a_Tool), 4); return cItem(E_ITEM_GLOWSTONE_DUST, DropNum); } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 2; } } ; ================================================ FILE: src/Blocks/BlockGrass.h ================================================ #pragma once #include "BlockHandler.h" #include "../FastRandom.h" #include "../Root.h" #include "../Bindings/PluginManager.h" class cBlockGrassHandler final : public cBlockHandler { public: using cBlockHandler::cBlockHandler; private: enum class Survivability { // Light level so good that the grass can try to spread to neighbours CanSpread, // Stay put, light is enough to live on but not propagate DoNothing, // Insufficient light, death is upon us DieInDarkness }; virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override { if (!ToolHasSilkTouch(a_Tool)) { return cItem(E_BLOCK_DIRT, 1, 0); } return cItem(E_BLOCK_GRASS, 1, 0); } virtual void OnUpdate( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cBlockPluginInterface & a_PluginInterface, cChunk & a_Chunk, const Vector3i a_RelPos ) const override { if (!a_Chunk.IsLightValid()) { a_Chunk.GetWorld()->QueueLightChunk(a_Chunk.GetPosX(), a_Chunk.GetPosZ()); return; } switch (cBlockGrassHandler::DetermineSurvivability(a_Chunk, a_RelPos)) { case Survivability::CanSpread: break; case Survivability::DoNothing: return; case Survivability::DieInDarkness: { a_Chunk.FastSetBlock(a_RelPos, E_BLOCK_DIRT, E_META_DIRT_NORMAL); return; } } // Grass spreads to adjacent dirt blocks: for (unsigned i = 0; i < 2; i++) // Pick two blocks to grow to { auto & Random = GetRandomProvider(); int OfsX = Random.RandInt(-1, 1); int OfsY = Random.RandInt(-3, 1); int OfsZ = Random.RandInt(-1, 1); cBlockGrassHandler::TrySpreadTo(a_Chunk, a_RelPos + Vector3i(OfsX, OfsY, OfsZ)); } // for i - repeat twice } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 1; } private: /** Check if conditions are favourable to a grass block at the given position. If they are not, the grass dies and is turned to dirt. Returns whether conditions are so good that the grass can try to spread to neighbours. */ static Survivability DetermineSurvivability(cChunk & a_Chunk, const Vector3i a_RelPos) { const auto AbovePos = a_RelPos.addedY(1); if (!cChunkDef::IsValidHeight(AbovePos)) { return Survivability::CanSpread; } // Grass turns back to dirt when the block above it is not transparent or water. // It does not turn to dirt when a snow layer is above. const auto Above = a_Chunk.GetBlock(AbovePos); if ( (Above != E_BLOCK_SNOW) && (!cBlockInfo::IsTransparent(Above) || IsBlockWater(Above))) { return Survivability::DieInDarkness; } // Make sure that there is enough light at the source block to spread const auto Light = std::max(a_Chunk.GetBlockLight(AbovePos), a_Chunk.GetSkyLightAltered(AbovePos)); return (Light >= 9) ? Survivability::CanSpread : Survivability::DoNothing; } /** Attempt to spread grass to a block at the given position. */ static void TrySpreadTo(cChunk & a_Chunk, Vector3i a_RelPos) { if (!cChunkDef::IsValidHeight(a_RelPos)) { // Y Coord out of range return; } auto Chunk = a_Chunk.GetRelNeighborChunkAdjustCoords(a_RelPos); if ((Chunk == nullptr) || !Chunk->IsValid()) { // Unloaded chunk return; } BLOCKTYPE DestBlock; NIBBLETYPE DestMeta; Chunk->GetBlockTypeMeta(a_RelPos, DestBlock, DestMeta); if ((DestBlock != E_BLOCK_DIRT) || (DestMeta != E_META_DIRT_NORMAL)) { // Not a regular dirt block return; } const auto AbovePos = a_RelPos.addedY(1); const auto Above = Chunk->GetBlock(AbovePos); const auto Light = std::max(Chunk->GetBlockLight(AbovePos), Chunk->GetSkyLightAltered(AbovePos)); if ( (Light > 4) && cBlockInfo::IsTransparent(Above) && !IsBlockLava(Above) && !IsBlockWaterOrIce(Above) ) { const auto AbsPos = Chunk->RelativeToAbsolute(a_RelPos); if (!cRoot::Get()->GetPluginManager()->CallHookBlockSpread(*Chunk->GetWorld(), AbsPos, ssGrassSpread)) { Chunk->FastSetBlock(a_RelPos, E_BLOCK_GRASS, 0); } } } } ; ================================================ FILE: src/Blocks/BlockGravel.h ================================================ #pragma once #include "BlockHandler.h" class cBlockGravelHandler final : public cBlockHandler { public: using cBlockHandler::cBlockHandler; private: virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override { if (ToolHasSilkTouch(a_Tool)) { return cItem(E_BLOCK_GRAVEL); } // Denominator of probability from wiki, don't let it go below 1. const auto Denominator = std::max(10 - 3 * ToolFortuneLevel(a_Tool), 1); if (GetRandomProvider().RandBool(1.0 / Denominator)) { return cItem(E_ITEM_FLINT); } return cItem(E_BLOCK_GRAVEL); } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 11; } } ; ================================================ FILE: src/Blocks/BlockHandler.cpp ================================================ #include "Globals.h" #include "BlockHandler.h" #include "../Item.h" #include "../World.h" #include "../Chunk.h" #include "BlockPluginInterface.h" #include "BlockAir.h" #include "BlockAnvil.h" #include "BlockBed.h" #include "BlockBigFlower.h" #include "BlockBookShelf.h" #include "BlockBrewingStand.h" #include "BlockButton.h" #include "BlockCactus.h" #include "BlockCake.h" #include "BlockCarpet.h" #include "BlockCauldron.h" #include "BlockChest.h" #include "BlockCloth.h" #include "BlockCobWeb.h" #include "BlockCocoaPod.h" #include "BlockCommandBlock.h" #include "BlockComparator.h" #include "BlockConcretePowder.h" #include "BlockCrops.h" #include "BlockDaylightSensor.h" #include "BlockDeadBush.h" #include "BlockDefaultBlock.h" #include "BlockDirt.h" #include "BlockDoor.h" #include "BlockDropSpenser.h" #include "BlockEnchantingTable.h" #include "BlockEndPortalFrame.h" #include "BlockEnderChest.h" #include "BlockEntity.h" #include "BlockFarmland.h" #include "BlockFence.h" #include "BlockFenceGate.h" #include "BlockFire.h" #include "BlockFlower.h" #include "BlockFlowerPot.h" #include "BlockFluid.h" #include "BlockFurnace.h" #include "BlockGlass.h" #include "BlockGlazedTerracotta.h" #include "BlockGlowstone.h" #include "BlockGrass.h" #include "BlockGravel.h" #include "BlockHopper.h" #include "BlockHugeMushroom.h" #include "BlockIce.h" #include "BlockJukebox.h" #include "BlockLadder.h" #include "BlockLeaves.h" #include "BlockLever.h" #include "BlockLilypad.h" #include "BlockMelon.h" #include "BlockMobHead.h" #include "BlockMobSpawner.h" #include "BlockInfested.h" #include "BlockMushroom.h" #include "BlockMycelium.h" #include "BlockNetherWart.h" #include "BlockNetherrack.h" #include "BlockNoteBlock.h" #include "BlockObserver.h" #include "BlockOre.h" #include "BlockPackedIce.h" #include "BlockPiston.h" #include "BlockPlanks.h" #include "BlockPortal.h" #include "BlockPressurePlate.h" #include "BlockPumpkin.h" #include "BlockQuartz.h" #include "BlockRail.h" #include "BlockRedstoneWire.h" #include "BlockRedstoneLamp.h" #include "BlockRedstoneOre.h" #include "BlockRedstoneRepeater.h" #include "BlockSand.h" #include "BlockSapling.h" #include "BlockSeaLantern.h" #include "BlockSideways.h" #include "BlockSignPost.h" #include "BlockSlab.h" #include "BlockSlime.h" #include "BlockSnow.h" #include "BlockSponge.h" #include "BlockStairs.h" #include "BlockStandingBanner.h" #include "BlockStems.h" #include "BlockStone.h" #include "BlockSugarCane.h" #include "BlockTNT.h" #include "BlockTallGrass.h" #include "BlockTorch.h" #include "BlockTrapdoor.h" #include "BlockTripwire.h" #include "BlockTripwireHook.h" #include "BlockVines.h" #include "BlockWallBanner.h" #include "BlockWallSign.h" #include "BlockWorkbench.h" /* // Tests the meta rotation and mirroring. // Note that the cMetaRotator needs to have its assert paths disabled for this test to work! static class cBlockHandlerRotationTester { public: cBlockHandlerRotationTester(void) { printf("Performing block handlers test...\n"); for (BLOCKTYPE Type = 0; Type < E_BLOCK_MAX_TYPE_ID; Type++) { cBlockHandler * Handler = cBlockInfo::GetHandler(Type); if (Handler == nullptr) { printf("nullptr handler for block type %d!\n", Type); continue; } AString BlockName = ItemTypeToString(Type); for (NIBBLETYPE Meta = 0; Meta < 16; Meta++) { // Test the CW / CCW rotations: NIBBLETYPE TestMeta; TestMeta = Handler->MetaRotateCW(Handler->MetaRotateCW(Handler->MetaRotateCW(Handler->MetaRotateCW(Meta)))); if (TestMeta != Meta) { // 4 CW rotations should produce no change in the meta printf("Handler for blocktype %d (%s) fails CW 4-rotation test for meta %d: got back %d\n", Type, BlockName.c_str(), Meta, TestMeta); } TestMeta = Handler->MetaRotateCCW(Handler->MetaRotateCCW(Handler->MetaRotateCCW(Handler->MetaRotateCCW(Meta)))); if (TestMeta != Meta) { // 4 CCW rotations should produce no change in the meta printf("Handler for blocktype %d (%s) fails CCW 4-rotation test for meta %d: got back %d\n", Type, BlockName.c_str(), Meta, TestMeta); } TestMeta = Handler->MetaRotateCCW(Handler->MetaRotateCW(Meta)); if (TestMeta != Meta) { // CCW rotation of a CW rotation should produce no change in the meta printf("Handler for blocktype %d (%s) fails CCW(CW) rotation test for meta %d: got back %d\n", Type, BlockName.c_str(), Meta, TestMeta); } TestMeta = Handler->MetaRotateCW(Handler->MetaRotateCCW(Meta)); if (TestMeta != Meta) { // CW rotation of a CCW rotation should produce no change in the meta printf("Handler for blocktype %d (%s) fails CW(CCW) rotation test for meta %d: got back %d\n", Type, BlockName.c_str(), Meta, TestMeta); } // Test the mirroring: TestMeta = Handler->MetaMirrorXY(Handler->MetaMirrorXY(Meta)); if (TestMeta != Meta) { // Double-mirroring should produce the same meta: printf("Handler for blocktype %d (%s) fails XY mirror test for meta %d: got back %d\n", Type, BlockName.c_str(), Meta, TestMeta); } TestMeta = Handler->MetaMirrorXZ(Handler->MetaMirrorXZ(Meta)); if (TestMeta != Meta) { // Double-mirroring should produce the same meta: printf("Handler for blocktype %d (%s) fails XZ mirror test for meta %d: got back %d\n", Type, BlockName.c_str(), Meta, TestMeta); } TestMeta = Handler->MetaMirrorYZ(Handler->MetaMirrorYZ(Meta)); if (TestMeta != Meta) { // Double-mirroring should produce the same meta: printf("Handler for blocktype %d (%s) fails YZ mirror test for meta %d: got back %d\n", Type, BlockName.c_str(), Meta, TestMeta); } // Test mirror-rotating: TestMeta = Handler->MetaRotateCW(Handler->MetaRotateCW(Handler->MetaMirrorXY(Handler->MetaMirrorYZ(Meta)))); if (TestMeta != Meta) { // 2 CW rotations should be the same as XY, YZ mirroring: printf("Handler for blocktype %d (%s) fails rotation-mirror test for meta %d: got back %d\n", Type, BlockName.c_str(), Meta, TestMeta); } } } // for Type printf("Block handlers test complete.\n"); } } g_BlockHandlerRotationTester; //*/ /** Static list of all block handlers. Ensures that a handler can never be nullptr (FS #243) on invalid during restarts or other transition periods. */ namespace { constexpr cBlockDoorHandler BlockAcaciaDoorHandler (E_BLOCK_ACACIA_DOOR); constexpr cBlockFenceGateHandler BlockAcaciaFenceGateHandler (E_BLOCK_ACACIA_FENCE_GATE); constexpr cBlockFenceHandler BlockAcaciaFenceHandler (E_BLOCK_ACACIA_FENCE); constexpr cBlockStairsHandler BlockAcaciaWoodStairsHandler (E_BLOCK_ACACIA_WOOD_STAIRS); constexpr cBlockRailHandler BlockActivatorRailHandler (E_BLOCK_ACTIVATOR_RAIL); constexpr cBlockComparatorHandler BlockActiveComparatorHandler (E_BLOCK_ACTIVE_COMPARATOR); constexpr cBlockAirHandler BlockAirHandler (E_BLOCK_AIR); constexpr cBlockAnvilHandler BlockAnvilHandler (E_BLOCK_ANVIL); constexpr cDefaultBlockHandler BlockBarrierHandler (E_BLOCK_BARRIER); constexpr cDefaultBlockEntityHandler BlockBeaconHandler (E_BLOCK_BEACON); constexpr cBlockBedHandler BlockBedHandler (E_BLOCK_BED); constexpr cDefaultBlockHandler BlockBedrockHandler (E_BLOCK_BEDROCK); constexpr cBlockCropsHandler<3> BlockBeetrootsHandler (E_BLOCK_BEETROOTS); // 4 stages of growth constexpr cBlockBigFlowerHandler BlockBigFlowerHandler (E_BLOCK_BIG_FLOWER); constexpr cBlockDoorHandler BlockBirchDoorHandler (E_BLOCK_BIRCH_DOOR); constexpr cBlockFenceGateHandler BlockBirchFenceGateHandler (E_BLOCK_BIRCH_FENCE_GATE); constexpr cBlockFenceHandler BlockBirchFenceHandler (E_BLOCK_BIRCH_FENCE); constexpr cBlockStairsHandler BlockBirchWoodStairsHandler (E_BLOCK_BIRCH_WOOD_STAIRS); constexpr cBlockGlazedTerracottaHandler BlockBlackGlazedTerracottaHandler (E_BLOCK_BLACK_GLAZED_TERRACOTTA); constexpr cDefaultBlockHandler BlockBlackShulkerBoxHandler (E_BLOCK_BLACK_SHULKER_BOX); constexpr cBlockGlazedTerracottaHandler BlockBlueGlazedTerracottaHandler (E_BLOCK_BLUE_GLAZED_TERRACOTTA); constexpr cDefaultBlockHandler BlockBlueShulkerBoxHandler (E_BLOCK_BLUE_SHULKER_BOX); constexpr cDefaultBlockHandler BlockBoneBlockHandler (E_BLOCK_BONE_BLOCK); constexpr cBlockBookShelfHandler BlockBookcaseHandler (E_BLOCK_BOOKCASE); constexpr cBlockBrewingStandHandler BlockBrewingStandHandler (E_BLOCK_BREWING_STAND); constexpr cDefaultBlockHandler BlockBricksHandler (E_BLOCK_BRICK); constexpr cBlockStairsHandler BlockBrickStairsHandler (E_BLOCK_BRICK_STAIRS); constexpr cBlockGlazedTerracottaHandler BlockBrownGlazedTerracottaHandler (E_BLOCK_BROWN_GLAZED_TERRACOTTA); constexpr cBlockMushroomHandler BlockBrownMushroomHandler (E_BLOCK_BROWN_MUSHROOM); constexpr cDefaultBlockHandler BlockBrownShulkerBoxHandler (E_BLOCK_BROWN_SHULKER_BOX); constexpr cBlockCactusHandler BlockCactusHandler (E_BLOCK_CACTUS); constexpr cBlockCakeHandler BlockCakeHandler (E_BLOCK_CAKE); constexpr cBlockCarpetHandler BlockCarpetHandler (E_BLOCK_CARPET); constexpr cBlockCropsHandler<7> BlockCarrotsHandler (E_BLOCK_CARROTS); // 8 stages of growth constexpr cBlockCauldronHandler BlockCauldronHandler (E_BLOCK_CAULDRON); constexpr cBlockCommandBlockHandler BlockChainCommandBlockHandler (E_BLOCK_CHAIN_COMMAND_BLOCK); constexpr cBlockChestHandler BlockChestHandler (E_BLOCK_CHEST); constexpr cDefaultBlockHandler BlockChorusFlowerHandler (E_BLOCK_CHORUS_FLOWER); constexpr cDefaultBlockHandler BlockChorusPlantHandler (E_BLOCK_CHORUS_PLANT); constexpr cDefaultOreHandler BlockClayHandler (E_BLOCK_CLAY); constexpr cDefaultBlockHandler BlockCoalBlockHandler (E_BLOCK_BLOCK_OF_COAL); constexpr cDefaultOreHandler BlockCoalOreHandler (E_BLOCK_COAL_ORE); constexpr cDefaultBlockHandler BlockCobblestoneHandler (E_BLOCK_COBBLESTONE); constexpr cBlockStairsHandler BlockCobblestoneStairsHandler (E_BLOCK_COBBLESTONE_STAIRS); constexpr cDefaultBlockHandler BlockCobblestoneWallHandler (E_BLOCK_COBBLESTONE_WALL); constexpr cBlockCobWebHandler BlockCobwebHandler (E_BLOCK_COBWEB); constexpr cBlockCocoaPodHandler BlockCocoaPodHandler (E_BLOCK_COCOA_POD); constexpr cBlockCommandBlockHandler BlockCommandBlockHandler (E_BLOCK_COMMAND_BLOCK); constexpr cDefaultBlockHandler BlockConcreteHandler (E_BLOCK_CONCRETE); constexpr cBlockConcretePowderHandler BlockConcretePowderHandler (E_BLOCK_CONCRETE_POWDER); constexpr cBlockCropsHandler<7> BlockCropsHandler (E_BLOCK_CROPS); // 8 stages of growth constexpr cBlockGlazedTerracottaHandler BlockCyanGlazedTerracottaHandler (E_BLOCK_CYAN_GLAZED_TERRACOTTA); constexpr cDefaultBlockHandler BlockCyanShulkerBoxHandler (E_BLOCK_CYAN_SHULKER_BOX); constexpr cBlockDoorHandler BlockDarkOakDoorHandler (E_BLOCK_DARK_OAK_DOOR); constexpr cBlockFenceGateHandler BlockDarkOakFenceGateHandler (E_BLOCK_DARK_OAK_FENCE_GATE); constexpr cBlockFenceHandler BlockDarkOakFenceHandler (E_BLOCK_DARK_OAK_FENCE); constexpr cBlockStairsHandler BlockDarkOakWoodStairsHandler (E_BLOCK_DARK_OAK_WOOD_STAIRS); constexpr cBlockDaylightSensorHandler BlockDaylightSensorHandler (E_BLOCK_DAYLIGHT_SENSOR); constexpr cBlockDeadBushHandler BlockDeadBushHandler (E_BLOCK_DEAD_BUSH); constexpr cBlockRailHandler BlockDetectorRailHandler (E_BLOCK_DETECTOR_RAIL); constexpr cDefaultBlockHandler BlockDiamondBlockHandler (E_BLOCK_DIAMOND_BLOCK); constexpr cDefaultOreHandler BlockDiamondOreHandler (E_BLOCK_DIAMOND_ORE); constexpr cBlockDirtHandler BlockDirtHandler (E_BLOCK_DIRT); constexpr cBlockDropSpenserHandler BlockDispenserHandler (E_BLOCK_DISPENSER); constexpr cBlockDoubleSlabHandler BlockDoubleRedSandstoneSlabHandler(E_BLOCK_DOUBLE_RED_SANDSTONE_SLAB); constexpr cBlockDoubleSlabHandler BlockDoubleStoneSlabHandler (E_BLOCK_DOUBLE_STONE_SLAB); constexpr cBlockDoubleSlabHandler BlockDoubleWoodenSlabHandler (E_BLOCK_DOUBLE_WOODEN_SLAB); constexpr cDefaultBlockHandler BlockDragonEggHandler (E_BLOCK_DRAGON_EGG); constexpr cBlockDropSpenserHandler BlockDropperHandler (E_BLOCK_DROPPER); constexpr cDefaultBlockHandler BlockEmeraldBlockHandler (E_BLOCK_EMERALD_BLOCK); constexpr cDefaultOreHandler BlockEmeraldOreHandler (E_BLOCK_EMERALD_ORE); constexpr cBlockEnchantingTableHandler BlockEnchantingTableHandler (E_BLOCK_ENCHANTMENT_TABLE); constexpr cDefaultBlockHandler BlockEndBricksHandler (E_BLOCK_END_BRICKS); constexpr cBlockEnderChestHandler BlockEnderChestHandler (E_BLOCK_ENDER_CHEST); constexpr cDefaultBlockHandler BlockEndGatewayHandler (E_BLOCK_END_GATEWAY); constexpr cBlockEndPortalFrameHandler BlockEndPortalFrameHandler (E_BLOCK_END_PORTAL_FRAME); constexpr cDefaultBlockHandler BlockEndPortalHandler (E_BLOCK_END_PORTAL); constexpr cDefaultBlockHandler BlockEndRodHandler (E_BLOCK_END_ROD); constexpr cDefaultBlockHandler BlockEndStoneHandler (E_BLOCK_END_STONE); constexpr cBlockFarmlandHandler BlockFarmlandHandler (E_BLOCK_FARMLAND); constexpr cBlockFenceHandler BlockFenceHandler (E_BLOCK_FENCE); constexpr cBlockFireHandler BlockFireHandler (E_BLOCK_FIRE); constexpr cBlockFlowerPotHandler BlockFlowerPotHandler (E_BLOCK_FLOWER_POT); constexpr cBlockIceHandler BlockFrostedIceHandler (E_BLOCK_FROSTED_ICE); constexpr cBlockFurnaceHandler BlockFurnaceHandler (E_BLOCK_FURNACE); constexpr cBlockGlassHandler BlockGlassHandler (E_BLOCK_GLASS); constexpr cBlockGlassHandler BlockGlassPaneHandler (E_BLOCK_GLASS_PANE); constexpr cBlockGlowstoneHandler BlockGlowstoneHandler (E_BLOCK_GLOWSTONE); constexpr cDefaultBlockHandler BlockGoldBlockHandler (E_BLOCK_GOLD_BLOCK); constexpr cDefaultOreHandler BlockGoldOreHandler (E_BLOCK_GOLD_ORE); constexpr cBlockGrassHandler BlockGrassHandler (E_BLOCK_GRASS); constexpr cDefaultBlockHandler BlockGrassPathHandler (E_BLOCK_GRASS_PATH); constexpr cBlockGravelHandler BlockGravelHandler (E_BLOCK_GRAVEL); constexpr cBlockGlazedTerracottaHandler BlockGrayGlazedTerracottaHandler (E_BLOCK_GRAY_GLAZED_TERRACOTTA); constexpr cDefaultBlockHandler BlockGrayShulkerBoxHandler (E_BLOCK_GRAY_SHULKER_BOX); constexpr cBlockGlazedTerracottaHandler BlockGreenGlazedTerracottaHandler (E_BLOCK_GREEN_GLAZED_TERRACOTTA); constexpr cDefaultBlockHandler BlockGreenShulkerBoxHandler (E_BLOCK_GREEN_SHULKER_BOX); constexpr cDefaultBlockHandler BlockHardenedClayHandler (E_BLOCK_HARDENED_CLAY); constexpr cBlockSidewaysHandler BlockHayBaleHandler (E_BLOCK_HAY_BALE); constexpr cBlockMobHeadHandler BlockHeadHandler (E_BLOCK_HEAD); constexpr cBlockPressurePlateHandler BlockHeavyWeightedPressurePHandler(E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE); constexpr cBlockHopperHandler BlockHopperHandler (E_BLOCK_HOPPER); constexpr cBlockHugeMushroomHandler BlockHugeBrownMushroomHandler (E_BLOCK_HUGE_BROWN_MUSHROOM); constexpr cBlockHugeMushroomHandler BlockHugeRedMushroomHandler (E_BLOCK_HUGE_RED_MUSHROOM); constexpr cBlockIceHandler BlockIceHandler (E_BLOCK_ICE); constexpr cBlockComparatorHandler BlockInactiveComparatorHandler (E_BLOCK_INACTIVE_COMPARATOR); constexpr cBlockInfestedHandler BlockInfestedBlockHandler (E_BLOCK_SILVERFISH_EGG); constexpr cDefaultBlockHandler BlockIronBarsHandler (E_BLOCK_IRON_BARS); constexpr cDefaultBlockHandler BlockIronBlockHandler (E_BLOCK_IRON_BLOCK); constexpr cBlockDoorHandler BlockIronDoorHandler (E_BLOCK_IRON_DOOR); constexpr cDefaultOreHandler BlockIronOreHandler (E_BLOCK_IRON_ORE); constexpr cBlockTrapdoorHandler BlockIronTrapdoorHandler (E_BLOCK_IRON_TRAPDOOR); constexpr cBlockPumpkinHandler BlockJackOLanternHandler (E_BLOCK_JACK_O_LANTERN); constexpr cBlockJukeboxHandler BlockJukeboxHandler (E_BLOCK_JUKEBOX); constexpr cBlockDoorHandler BlockJungleDoorHandler (E_BLOCK_JUNGLE_DOOR); constexpr cBlockFenceGateHandler BlockJungleFenceGateHandler (E_BLOCK_JUNGLE_FENCE_GATE); constexpr cBlockFenceHandler BlockJungleFenceHandler (E_BLOCK_JUNGLE_FENCE); constexpr cBlockStairsHandler BlockJungleWoodStairsHandler (E_BLOCK_JUNGLE_WOOD_STAIRS); constexpr cBlockLadderHandler BlockLadderHandler (E_BLOCK_LADDER); constexpr cDefaultBlockHandler BlockLapisBlockHandler (E_BLOCK_LAPIS_BLOCK); constexpr cDefaultOreHandler BlockLapisOreHandler (E_BLOCK_LAPIS_ORE); constexpr cBlockLavaHandler BlockLavaHandler (E_BLOCK_LAVA); constexpr cBlockLeavesHandler BlockLeavesHandler (E_BLOCK_LEAVES); constexpr cBlockLeverHandler BlockLeverHandler (E_BLOCK_LEVER); constexpr cBlockGlazedTerracottaHandler BlockLightBlueGlazedTerracoHandler(E_BLOCK_LIGHT_BLUE_GLAZED_TERRACOTTA); constexpr cDefaultBlockHandler BlockLightBlueShulkerBoxHandler (E_BLOCK_LIGHT_BLUE_SHULKER_BOX); constexpr cBlockGlazedTerracottaHandler BlockLightGrayGlazedTerracoHandler(E_BLOCK_LIGHT_GRAY_GLAZED_TERRACOTTA); constexpr cDefaultBlockHandler BlockLightGrayShulkerBoxHandler (E_BLOCK_LIGHT_GRAY_SHULKER_BOX); constexpr cBlockPressurePlateHandler BlockLightWeightedPressurePHandler(E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE); constexpr cBlockLilypadHandler BlockLilyPadHandler (E_BLOCK_LILY_PAD); constexpr cBlockGlazedTerracottaHandler BlockLimeGlazedTerracottaHandler (E_BLOCK_LIME_GLAZED_TERRACOTTA); constexpr cDefaultBlockHandler BlockLimeShulkerBoxHandler (E_BLOCK_LIME_SHULKER_BOX); constexpr cBlockFurnaceHandler BlockLitFurnaceHandler (E_BLOCK_LIT_FURNACE); constexpr cBlockSidewaysHandler BlockLogHandler (E_BLOCK_LOG); constexpr cBlockGlazedTerracottaHandler BlockMagentaGlazedTerracottHandler(E_BLOCK_MAGENTA_GLAZED_TERRACOTTA); constexpr cDefaultBlockHandler BlockMagentaShulkerBoxHandler (E_BLOCK_MAGENTA_SHULKER_BOX); constexpr cDefaultBlockHandler BlockMagmaHandler (E_BLOCK_MAGMA); constexpr cBlockMelonHandler BlockMelonHandler (E_BLOCK_MELON); constexpr cBlockMelonStemHandler BlockMelonStemHandler (E_BLOCK_MELON_STEM); constexpr cBlockMobSpawnerHandler BlockMobSpawnerHandler (E_BLOCK_MOB_SPAWNER); constexpr cDefaultBlockHandler BlockMossyCobblestoneHandler (E_BLOCK_MOSSY_COBBLESTONE); constexpr cBlockMyceliumHandler BlockMyceliumHandler (E_BLOCK_MYCELIUM); constexpr cBlockFenceHandler BlockNetherBrickFenceHandler (E_BLOCK_NETHER_BRICK_FENCE); constexpr cDefaultBlockHandler BlockNetherBricksHandler (E_BLOCK_NETHER_BRICK); constexpr cBlockStairsHandler BlockNetherBrickStairsHandler (E_BLOCK_NETHER_BRICK_STAIRS); constexpr cBlockPortalHandler BlockNetherPortalHandler (E_BLOCK_NETHER_PORTAL); constexpr cDefaultOreHandler BlockNetherQuartzOreHandler (E_BLOCK_NETHER_QUARTZ_ORE); constexpr cBlockNetherrack BlockNetherrackHandler (E_BLOCK_NETHERRACK); constexpr cDefaultBlockHandler BlockNetherWartBlockHandler (E_BLOCK_NETHER_WART_BLOCK); constexpr cBlockNetherWartHandler BlockNetherWartHandler (E_BLOCK_NETHER_WART); constexpr cBlockLeavesHandler BlockNewLeavesHandler (E_BLOCK_NEW_LEAVES); constexpr cBlockSidewaysHandler BlockNewLogHandler (E_BLOCK_NEW_LOG); constexpr cBlockNoteBlockHandler BlockNoteBlockHandler (E_BLOCK_NOTE_BLOCK); constexpr cBlockDoorHandler BlockOakDoorHandler (E_BLOCK_OAK_DOOR); constexpr cBlockFenceGateHandler BlockOakFenceGateHandler (E_BLOCK_OAK_FENCE_GATE); constexpr cBlockStairsHandler BlockOakWoodStairsHandler (E_BLOCK_OAK_WOOD_STAIRS); constexpr cBlockObserverHandler BlockObserverHandler (E_BLOCK_OBSERVER); constexpr cDefaultBlockHandler BlockObsidianHandler (E_BLOCK_OBSIDIAN); constexpr cBlockGlazedTerracottaHandler BlockOrangeGlazedTerracottaHandler(E_BLOCK_ORANGE_GLAZED_TERRACOTTA); constexpr cDefaultBlockHandler BlockOrangeShulkerBoxHandler (E_BLOCK_ORANGE_SHULKER_BOX); constexpr cBlockPackedIceHandler BlockPackedIceHandler (E_BLOCK_PACKED_ICE); constexpr cBlockGlazedTerracottaHandler BlockPinkGlazedTerracottaHandler (E_BLOCK_PINK_GLAZED_TERRACOTTA); constexpr cDefaultBlockHandler BlockPinkShulkerBoxHandler (E_BLOCK_PINK_SHULKER_BOX); constexpr cBlockPistonHandler BlockPistonHandler (E_BLOCK_PISTON); constexpr cBlockPistonHeadHandler BlockPistonHeadHandler; constexpr cDefaultBlockHandler BlockPistonMovedBlockHandler (E_BLOCK_PISTON_MOVED_BLOCK); constexpr cBlockPlanksHandler BlockPlanksHandler (E_BLOCK_PLANKS); constexpr cBlockCropsHandler<7> BlockPotatoesHandler (E_BLOCK_POTATOES); // 8 stages of growth constexpr cBlockRailHandler BlockPoweredRailHandler (E_BLOCK_POWERED_RAIL); constexpr cDefaultBlockHandler BlockPrismarineBlockHandler (E_BLOCK_PRISMARINE_BLOCK); constexpr cBlockPumpkinHandler BlockPumpkinHandler (E_BLOCK_PUMPKIN); constexpr cBlockPumpkinStemHandler BlockPumpkinStemHandler (E_BLOCK_PUMPKIN_STEM); constexpr cBlockGlazedTerracottaHandler BlockPurpleGlazedTerracottaHandler(E_BLOCK_PURPLE_GLAZED_TERRACOTTA); constexpr cDefaultBlockHandler BlockPurpleShulkerBoxHandler (E_BLOCK_PURPLE_SHULKER_BOX); constexpr cDefaultBlockHandler BlockPurpurBlockHandler (E_BLOCK_PURPUR_BLOCK); constexpr cBlockDoubleSlabHandler BlockPurpurDoubleSlabHandler (E_BLOCK_PURPUR_DOUBLE_SLAB); constexpr cDefaultBlockHandler BlockPurpurPillarHandler (E_BLOCK_PURPUR_PILLAR); constexpr cBlockSlabHandler BlockPurpurSlabHandler (E_BLOCK_PURPUR_SLAB); constexpr cBlockStairsHandler BlockPurpurStairsHandler (E_BLOCK_PURPUR_STAIRS); constexpr cBlockQuartzHandler BlockQuartzBlockHandler (E_BLOCK_QUARTZ_BLOCK); constexpr cBlockStairsHandler BlockQuartzStairsHandler (E_BLOCK_QUARTZ_STAIRS); constexpr cBlockRailHandler BlockRailHandler (E_BLOCK_RAIL); constexpr cBlockGlazedTerracottaHandler BlockRedGlazedTerracottaHandler (E_BLOCK_RED_GLAZED_TERRACOTTA); constexpr cBlockMushroomHandler BlockRedMushroomHandler (E_BLOCK_RED_MUSHROOM); constexpr cDefaultBlockHandler BlockRedNetherBricksHandler (E_BLOCK_RED_NETHER_BRICK); constexpr cBlockFlowerHandler BlockRedRoseHandler (E_BLOCK_RED_ROSE); constexpr cDefaultBlockHandler BlockRedSandstoneHandler (E_BLOCK_RED_SANDSTONE); constexpr cBlockSlabHandler BlockRedSandstoneSlabHandler (E_BLOCK_RED_SANDSTONE_SLAB); constexpr cBlockStairsHandler BlockRedSandstoneStairsHandler (E_BLOCK_RED_SANDSTONE_STAIRS); constexpr cDefaultBlockHandler BlockRedShulkerBoxHandler (E_BLOCK_RED_SHULKER_BOX); constexpr cDefaultBlockHandler BlockRedstoneBlockHandler (E_BLOCK_BLOCK_OF_REDSTONE); constexpr cBlockRedstoneLampHandler BlockRedstoneLampHandler (E_BLOCK_REDSTONE_LAMP_ON); constexpr cBlockGlowingRedstoneOreHandler BlockRedstoneOreGlowingHandler (E_BLOCK_REDSTONE_ORE_GLOWING); constexpr cBlockRedstoneOreHandler BlockRedstoneOreHandler (E_BLOCK_REDSTONE_ORE); constexpr cBlockRedstoneRepeaterHandler BlockRedstoneRepeaterOffHandler (E_BLOCK_REDSTONE_REPEATER_OFF); constexpr cBlockRedstoneRepeaterHandler BlockRedstoneRepeaterOnHandler (E_BLOCK_REDSTONE_REPEATER_ON); constexpr cBlockRedstoneTorchHandler BlockRedstoneTorchOffHandler (E_BLOCK_REDSTONE_TORCH_OFF); constexpr cBlockRedstoneTorchHandler BlockRedstoneTorchOnHandler (E_BLOCK_REDSTONE_TORCH_ON); constexpr cBlockRedstoneWireHandler BlockRedstoneWireHandler (E_BLOCK_REDSTONE_WIRE); constexpr cBlockCommandBlockHandler BlockRepeatingCommandBlockHandler (E_BLOCK_REPEATING_COMMAND_BLOCK); constexpr cBlockSandHandler BlockSandHandler (E_BLOCK_SAND); constexpr cDefaultBlockHandler BlockSandstoneHandler (E_BLOCK_SANDSTONE); constexpr cBlockStairsHandler BlockSandstoneStairsHandler (E_BLOCK_SANDSTONE_STAIRS); constexpr cBlockSaplingHandler BlockSaplingHandler (E_BLOCK_SAPLING); constexpr cBlockSeaLanternHandler BlockSeaLanternHandler (E_BLOCK_SEA_LANTERN); constexpr cBlockSignPostHandler BlockSignPostHandler (E_BLOCK_SIGN_POST); constexpr cBlockSlimeHandler BlockSlimeBlockHandler (E_BLOCK_SLIME_BLOCK); constexpr cDefaultBlockHandler BlockSnowBlockHandler (E_BLOCK_SNOW_BLOCK); constexpr cBlockSnowHandler BlockSnowHandler (E_BLOCK_SNOW); constexpr cDefaultBlockHandler BlockSoulSandHandler (E_BLOCK_SOULSAND); constexpr cBlockSpongeHandler BlockSpongeHandler (E_BLOCK_SPONGE); constexpr cBlockDoorHandler BlockSpruceDoorHandler (E_BLOCK_SPRUCE_DOOR); constexpr cBlockFenceGateHandler BlockSpruceFenceGateHandler (E_BLOCK_SPRUCE_FENCE_GATE); constexpr cBlockFenceHandler BlockSpruceFenceHandler (E_BLOCK_SPRUCE_FENCE); constexpr cBlockStairsHandler BlockSpruceWoodStairsHandler (E_BLOCK_SPRUCE_WOOD_STAIRS); constexpr cDefaultBlockHandler BlockStainedClayHandler (E_BLOCK_STAINED_CLAY); constexpr cBlockGlassHandler BlockStainedGlassHandler (E_BLOCK_STAINED_GLASS); constexpr cBlockGlassHandler BlockStainedGlassPaneHandler (E_BLOCK_STAINED_GLASS_PANE); constexpr cBlockStandingBannerHandler BlockStandingBannerHandler (E_BLOCK_STANDING_BANNER); constexpr cBlockLavaHandler BlockStationaryLavaHandler (E_BLOCK_STATIONARY_LAVA); constexpr cBlockWaterHandler BlockStationaryWaterHandler (E_BLOCK_STATIONARY_WATER); constexpr cBlockPistonHandler BlockStickyPistonHandler (E_BLOCK_STICKY_PISTON); constexpr cDefaultBlockHandler BlockStoneBricksHandler (E_BLOCK_STONE_BRICKS); constexpr cBlockStairsHandler BlockStoneBrickStairsHandler (E_BLOCK_STONE_BRICK_STAIRS); constexpr cBlockButtonHandler BlockStoneButtonHandler (E_BLOCK_STONE_BUTTON); constexpr cBlockStoneHandler BlockStoneHandler (E_BLOCK_STONE); constexpr cBlockPressurePlateHandler BlockStonePressurePlateHandler (E_BLOCK_STONE_PRESSURE_PLATE); constexpr cBlockSlabHandler BlockStoneSlabHandler (E_BLOCK_STONE_SLAB); constexpr cDefaultBlockHandler BlockStructureBlockHandler (E_BLOCK_STRUCTURE_BLOCK); constexpr cDefaultBlockHandler BlockStructureVoidHandler (E_BLOCK_STRUCTURE_VOID); constexpr cBlockSugarCaneHandler BlockSugarCaneHandler (E_BLOCK_SUGARCANE); constexpr cBlockTallGrassHandler BlockTallGrassHandler (E_BLOCK_TALL_GRASS); constexpr cBlockTNTHandler BlockTNTHandler (E_BLOCK_TNT); constexpr cBlockTorchHandler BlockTorchHandler (E_BLOCK_TORCH); constexpr cBlockTrapdoorHandler BlockTrapdoorHandler (E_BLOCK_TRAPDOOR); constexpr cBlockChestHandler BlockTrappedChestHandler (E_BLOCK_TRAPPED_CHEST); constexpr cBlockTripwireHandler BlockTripwireHandler (E_BLOCK_TRIPWIRE); constexpr cBlockTripwireHookHandler BlockTripwireHookHandler (E_BLOCK_TRIPWIRE_HOOK); constexpr cBlockVinesHandler BlockVinesHandler (E_BLOCK_VINES); constexpr cBlockWallBannerHandler BlockWallBannerHandler (E_BLOCK_WALL_BANNER); constexpr cBlockWallSignHandler BlockWallsignHandler (E_BLOCK_WALLSIGN); constexpr cBlockWaterHandler BlockWaterHandler (E_BLOCK_WATER); constexpr cBlockGlazedTerracottaHandler BlockWhiteGlazedTerracottaHandler (E_BLOCK_WHITE_GLAZED_TERRACOTTA); constexpr cDefaultBlockHandler BlockWhiteShulkerBoxHandler (E_BLOCK_WHITE_SHULKER_BOX); constexpr cBlockButtonHandler BlockWoodenButtonHandler (E_BLOCK_WOODEN_BUTTON); constexpr cBlockPressurePlateHandler BlockWoodenPressurePlateHandler (E_BLOCK_WOODEN_PRESSURE_PLATE); constexpr cBlockSlabHandler BlockWoodenSlabHandler (E_BLOCK_WOODEN_SLAB); constexpr cBlockClothHandler BlockWoolHandler (E_BLOCK_WOOL); constexpr cBlockWorkbenchHandler BlockWorkbenchHandler (E_BLOCK_WORKBENCH); constexpr cBlockFlowerHandler BlockYellowFlowerHandler (E_BLOCK_YELLOW_FLOWER); constexpr cBlockGlazedTerracottaHandler BlockYellowGlazedTerracottaHandler(E_BLOCK_YELLOW_GLAZED_TERRACOTTA); constexpr cDefaultBlockHandler BlockYellowShulkerBoxHandler (E_BLOCK_YELLOW_SHULKER_BOX); } //////////////////////////////////////////////////////////////////////////////// // cBlockHandler: void cBlockHandler::OnUpdate( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cBlockPluginInterface & a_PluginInterface, cChunk & a_Chunk, const Vector3i a_RelPos ) const { } void cBlockHandler::OnNeighborChanged(cChunkInterface & a_ChunkInterface, Vector3i a_BlockPos, eBlockFace a_WhichNeighbor) const { if (a_ChunkInterface.DoWithChunkAt(a_BlockPos, [&](cChunk & a_Chunk) { return CanBeAt(a_Chunk, cChunkDef::AbsoluteToRelative(a_BlockPos), a_Chunk.GetMeta(cChunkDef::AbsoluteToRelative(a_BlockPos))); })) { return; } a_ChunkInterface.DropBlockAsPickups(a_BlockPos); } void cBlockHandler::NeighborChanged(cChunkInterface & a_ChunkInterface, Vector3i a_NeighborPos, eBlockFace a_WhichNeighbor) { if (!cChunkDef::IsValidHeight(a_NeighborPos)) { return; } cBlockHandler::For(a_ChunkInterface.GetBlock(a_NeighborPos)).OnNeighborChanged(a_ChunkInterface, a_NeighborPos, a_WhichNeighbor); } cItems cBlockHandler::ConvertToPickups(NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const { UNUSED(a_Tool); // Add self: return cItem(m_BlockType, 1, a_BlockMeta); } bool cBlockHandler::CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const { return true; } bool cBlockHandler::IsUseable() const { return false; } bool cBlockHandler::DoesIgnoreBuildCollision(const cWorld & a_World, const cItem & a_HeldItem, const Vector3i a_Position, const NIBBLETYPE a_Meta, const eBlockFace a_ClickedBlockFace, const bool a_ClickedDirectly) const { return m_BlockType == E_BLOCK_AIR; } bool cBlockHandler::IsInsideBlock(const Vector3d a_RelPosition, const NIBBLETYPE a_BlockMeta) const { // Default functionality: Test the height, since we assume full voxels with varying height return (a_RelPosition.y < cBlockInfo::GetBlockHeight(m_BlockType)); } cBoundingBox cBlockHandler::GetPlacementCollisionBox(BLOCKTYPE a_XM, BLOCKTYPE a_XP, BLOCKTYPE a_YM, BLOCKTYPE a_YP, BLOCKTYPE a_ZM, BLOCKTYPE a_ZP) const { if (!cBlockInfo::IsSolid(m_BlockType)) { // Non-solid things can be placed within entities return cBoundingBox(0, 0, 0, 0, 0, 0); } return cBoundingBox(0, 1, 0, cBlockInfo::GetBlockHeight(m_BlockType), 0, 1); } void cBlockHandler::Check( cChunkInterface & a_ChunkInterface, cBlockPluginInterface & a_PluginInterface, Vector3i a_RelPos, cChunk & a_Chunk ) const { const auto Position = cChunkDef::RelativeToAbsolute(a_RelPos, a_Chunk.GetPos()); NeighborChanged(a_ChunkInterface, Position.addedX(-1), BLOCK_FACE_XP); NeighborChanged(a_ChunkInterface, Position.addedX(1), BLOCK_FACE_XM); NeighborChanged(a_ChunkInterface, Position.addedY(-1), BLOCK_FACE_YP); NeighborChanged(a_ChunkInterface, Position.addedY(1), BLOCK_FACE_YM); NeighborChanged(a_ChunkInterface, Position.addedZ(-1), BLOCK_FACE_ZP); NeighborChanged(a_ChunkInterface, Position.addedZ(1), BLOCK_FACE_ZM); } ColourID cBlockHandler::GetMapBaseColourID(NIBBLETYPE a_Meta) const { // Zero for transparent return 0; } bool cBlockHandler::ToolHasSilkTouch(const cItem * a_Tool) { return ((a_Tool != nullptr) && (a_Tool->m_Enchantments.GetLevel(cEnchantments::enchSilkTouch) > 0)); } unsigned char cBlockHandler::ToolFortuneLevel(const cItem * a_Tool) { if ((a_Tool != nullptr) && ItemCategory::IsTool(a_Tool->m_ItemType)) { // Return enchantment level, limited to avoid spawning excessive pickups (crashing the server) when modified items are used: return static_cast(std::min(8U, a_Tool->m_Enchantments.GetLevel(cEnchantments::enchFortune))); } // Not a tool: return 0; } char cBlockHandler::FortuneDiscreteRandom(char a_MinDrop, char a_DefaultMax, unsigned char a_BonusMax, char a_DropCap) { // First sample the discrete random distribution. char DropNum = GetRandomProvider().RandInt(a_MinDrop, static_cast(a_DefaultMax + a_BonusMax)); // Then clamp to within range (clamp instead of min incase of overflow): return std::clamp(DropNum, a_MinDrop, a_DropCap); } const cBlockHandler & cBlockHandler::For(BLOCKTYPE a_BlockType) { // Switch on the block type, as an enumeration // Clang will fail if any type is unhandled: switch (static_cast(a_BlockType)) { // Block handlers, alphabetically sorted: case E_BLOCK_ACACIA_DOOR: return BlockAcaciaDoorHandler; case E_BLOCK_ACACIA_FENCE: return BlockAcaciaFenceHandler; case E_BLOCK_ACACIA_FENCE_GATE: return BlockAcaciaFenceGateHandler; case E_BLOCK_ACACIA_WOOD_STAIRS: return BlockAcaciaWoodStairsHandler; case E_BLOCK_ACTIVATOR_RAIL: return BlockActivatorRailHandler; case E_BLOCK_ACTIVE_COMPARATOR: return BlockActiveComparatorHandler; case E_BLOCK_AIR: return BlockAirHandler; case E_BLOCK_ANVIL: return BlockAnvilHandler; case E_BLOCK_BARRIER: return BlockBarrierHandler; case E_BLOCK_BEACON: return BlockBeaconHandler; case E_BLOCK_BED: return BlockBedHandler; case E_BLOCK_BEDROCK: return BlockBedrockHandler; case E_BLOCK_BEETROOTS: return BlockBeetrootsHandler; case E_BLOCK_BIG_FLOWER: return BlockBigFlowerHandler; case E_BLOCK_BIRCH_DOOR: return BlockBirchDoorHandler; case E_BLOCK_BIRCH_FENCE: return BlockBirchFenceHandler; case E_BLOCK_BIRCH_FENCE_GATE: return BlockBirchFenceGateHandler; case E_BLOCK_BIRCH_WOOD_STAIRS: return BlockBirchWoodStairsHandler; case E_BLOCK_BLACK_GLAZED_TERRACOTTA: return BlockBlackGlazedTerracottaHandler; case E_BLOCK_BLACK_SHULKER_BOX: return BlockBlackShulkerBoxHandler; case E_BLOCK_BLOCK_OF_COAL: return BlockCoalBlockHandler; case E_BLOCK_BLOCK_OF_REDSTONE: return BlockRedstoneBlockHandler; case E_BLOCK_BLUE_GLAZED_TERRACOTTA: return BlockBlueGlazedTerracottaHandler; case E_BLOCK_BLUE_SHULKER_BOX: return BlockBlueShulkerBoxHandler; case E_BLOCK_BONE_BLOCK: return BlockBoneBlockHandler; case E_BLOCK_BOOKCASE: return BlockBookcaseHandler; case E_BLOCK_BREWING_STAND: return BlockBrewingStandHandler; case E_BLOCK_BRICK: return BlockBricksHandler; case E_BLOCK_BRICK_STAIRS: return BlockBrickStairsHandler; case E_BLOCK_BROWN_GLAZED_TERRACOTTA: return BlockBrownGlazedTerracottaHandler; case E_BLOCK_BROWN_MUSHROOM: return BlockBrownMushroomHandler; case E_BLOCK_BROWN_SHULKER_BOX: return BlockBrownShulkerBoxHandler; case E_BLOCK_CACTUS: return BlockCactusHandler; case E_BLOCK_CAKE: return BlockCakeHandler; case E_BLOCK_CARPET: return BlockCarpetHandler; case E_BLOCK_CARROTS: return BlockCarrotsHandler; case E_BLOCK_CAULDRON: return BlockCauldronHandler; case E_BLOCK_CHAIN_COMMAND_BLOCK: return BlockChainCommandBlockHandler; case E_BLOCK_CHEST: return BlockChestHandler; case E_BLOCK_CHORUS_FLOWER: return BlockChorusFlowerHandler; case E_BLOCK_CHORUS_PLANT: return BlockChorusPlantHandler; case E_BLOCK_CLAY: return BlockClayHandler; case E_BLOCK_COAL_ORE: return BlockCoalOreHandler; case E_BLOCK_COBBLESTONE: return BlockCobblestoneHandler; case E_BLOCK_COBBLESTONE_STAIRS: return BlockCobblestoneStairsHandler; case E_BLOCK_COBBLESTONE_WALL: return BlockCobblestoneWallHandler; case E_BLOCK_COBWEB: return BlockCobwebHandler; case E_BLOCK_COCOA_POD: return BlockCocoaPodHandler; case E_BLOCK_COMMAND_BLOCK: return BlockCommandBlockHandler; case E_BLOCK_CONCRETE: return BlockConcreteHandler; case E_BLOCK_CONCRETE_POWDER: return BlockConcretePowderHandler; case E_BLOCK_CROPS: return BlockCropsHandler; case E_BLOCK_CYAN_GLAZED_TERRACOTTA: return BlockCyanGlazedTerracottaHandler; case E_BLOCK_CYAN_SHULKER_BOX: return BlockCyanShulkerBoxHandler; case E_BLOCK_DARK_OAK_DOOR: return BlockDarkOakDoorHandler; case E_BLOCK_DARK_OAK_FENCE: return BlockDarkOakFenceHandler; case E_BLOCK_DARK_OAK_FENCE_GATE: return BlockDarkOakFenceGateHandler; case E_BLOCK_DARK_OAK_WOOD_STAIRS: return BlockDarkOakWoodStairsHandler; case E_BLOCK_DAYLIGHT_SENSOR: return BlockDaylightSensorHandler; case E_BLOCK_DEAD_BUSH: return BlockDeadBushHandler; case E_BLOCK_DETECTOR_RAIL: return BlockDetectorRailHandler; case E_BLOCK_DIAMOND_BLOCK: return BlockDiamondBlockHandler; case E_BLOCK_DIAMOND_ORE: return BlockDiamondOreHandler; case E_BLOCK_DIRT: return BlockDirtHandler; case E_BLOCK_DISPENSER: return BlockDispenserHandler; case E_BLOCK_DOUBLE_RED_SANDSTONE_SLAB: return BlockDoubleRedSandstoneSlabHandler; case E_BLOCK_DOUBLE_STONE_SLAB: return BlockDoubleStoneSlabHandler; case E_BLOCK_DOUBLE_WOODEN_SLAB: return BlockDoubleWoodenSlabHandler; case E_BLOCK_DRAGON_EGG: return BlockDragonEggHandler; case E_BLOCK_DROPPER: return BlockDropperHandler; case E_BLOCK_EMERALD_BLOCK: return BlockEmeraldBlockHandler; case E_BLOCK_EMERALD_ORE: return BlockEmeraldOreHandler; case E_BLOCK_ENCHANTMENT_TABLE: return BlockEnchantingTableHandler; case E_BLOCK_ENDER_CHEST: return BlockEnderChestHandler; case E_BLOCK_END_BRICKS: return BlockEndBricksHandler; case E_BLOCK_END_GATEWAY: return BlockEndGatewayHandler; case E_BLOCK_END_PORTAL: return BlockEndPortalHandler; case E_BLOCK_END_PORTAL_FRAME: return BlockEndPortalFrameHandler; case E_BLOCK_END_ROD: return BlockEndRodHandler; case E_BLOCK_END_STONE: return BlockEndStoneHandler; case E_BLOCK_FARMLAND: return BlockFarmlandHandler; case E_BLOCK_FENCE: return BlockFenceHandler; case E_BLOCK_FIRE: return BlockFireHandler; case E_BLOCK_FLOWER_POT: return BlockFlowerPotHandler; case E_BLOCK_FROSTED_ICE: return BlockFrostedIceHandler; case E_BLOCK_FURNACE: return BlockFurnaceHandler; case E_BLOCK_GLASS: return BlockGlassHandler; case E_BLOCK_GLASS_PANE: return BlockGlassPaneHandler; case E_BLOCK_GLOWSTONE: return BlockGlowstoneHandler; case E_BLOCK_GOLD_BLOCK: return BlockGoldBlockHandler; case E_BLOCK_GOLD_ORE: return BlockGoldOreHandler; case E_BLOCK_GRASS: return BlockGrassHandler; case E_BLOCK_GRASS_PATH: return BlockGrassPathHandler; case E_BLOCK_GRAVEL: return BlockGravelHandler; case E_BLOCK_GRAY_GLAZED_TERRACOTTA: return BlockGrayGlazedTerracottaHandler; case E_BLOCK_GRAY_SHULKER_BOX: return BlockGrayShulkerBoxHandler; case E_BLOCK_GREEN_GLAZED_TERRACOTTA: return BlockGreenGlazedTerracottaHandler; case E_BLOCK_GREEN_SHULKER_BOX: return BlockGreenShulkerBoxHandler; case E_BLOCK_HARDENED_CLAY: return BlockHardenedClayHandler; case E_BLOCK_HAY_BALE: return BlockHayBaleHandler; case E_BLOCK_HEAD: return BlockHeadHandler; case E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE: return BlockHeavyWeightedPressurePHandler; case E_BLOCK_HOPPER: return BlockHopperHandler; case E_BLOCK_HUGE_BROWN_MUSHROOM: return BlockHugeBrownMushroomHandler; case E_BLOCK_HUGE_RED_MUSHROOM: return BlockHugeRedMushroomHandler; case E_BLOCK_ICE: return BlockIceHandler; case E_BLOCK_INACTIVE_COMPARATOR: return BlockInactiveComparatorHandler; case E_BLOCK_INVERTED_DAYLIGHT_SENSOR: return BlockDaylightSensorHandler; case E_BLOCK_IRON_BARS: return BlockIronBarsHandler; case E_BLOCK_IRON_BLOCK: return BlockIronBlockHandler; case E_BLOCK_IRON_DOOR: return BlockIronDoorHandler; case E_BLOCK_IRON_ORE: return BlockIronOreHandler; case E_BLOCK_IRON_TRAPDOOR: return BlockIronTrapdoorHandler; case E_BLOCK_JACK_O_LANTERN: return BlockJackOLanternHandler; case E_BLOCK_JUKEBOX: return BlockJukeboxHandler; case E_BLOCK_JUNGLE_DOOR: return BlockJungleDoorHandler; case E_BLOCK_JUNGLE_FENCE: return BlockJungleFenceHandler; case E_BLOCK_JUNGLE_FENCE_GATE: return BlockJungleFenceGateHandler; case E_BLOCK_JUNGLE_WOOD_STAIRS: return BlockJungleWoodStairsHandler; case E_BLOCK_LADDER: return BlockLadderHandler; case E_BLOCK_LAPIS_BLOCK: return BlockLapisBlockHandler; case E_BLOCK_LAPIS_ORE: return BlockLapisOreHandler; case E_BLOCK_LAVA: return BlockLavaHandler; case E_BLOCK_LEAVES: return BlockLeavesHandler; case E_BLOCK_LEVER: return BlockLeverHandler; case E_BLOCK_LIGHT_BLUE_GLAZED_TERRACOTTA: return BlockLightBlueGlazedTerracoHandler; case E_BLOCK_LIGHT_BLUE_SHULKER_BOX: return BlockLightBlueShulkerBoxHandler; case E_BLOCK_LIGHT_GRAY_GLAZED_TERRACOTTA: return BlockLightGrayGlazedTerracoHandler; case E_BLOCK_LIGHT_GRAY_SHULKER_BOX: return BlockLightGrayShulkerBoxHandler; case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE: return BlockLightWeightedPressurePHandler; case E_BLOCK_LILY_PAD: return BlockLilyPadHandler; case E_BLOCK_LIME_GLAZED_TERRACOTTA: return BlockLimeGlazedTerracottaHandler; case E_BLOCK_LIME_SHULKER_BOX: return BlockLimeShulkerBoxHandler; case E_BLOCK_LIT_FURNACE: return BlockLitFurnaceHandler; case E_BLOCK_LOG: return BlockLogHandler; case E_BLOCK_MAGENTA_GLAZED_TERRACOTTA: return BlockMagentaGlazedTerracottHandler; case E_BLOCK_MAGENTA_SHULKER_BOX: return BlockMagentaShulkerBoxHandler; case E_BLOCK_MAGMA: return BlockMagmaHandler; case E_BLOCK_MELON: return BlockMelonHandler; case E_BLOCK_MELON_STEM: return BlockMelonStemHandler; case E_BLOCK_MOB_SPAWNER: return BlockMobSpawnerHandler; case E_BLOCK_MOSSY_COBBLESTONE: return BlockMossyCobblestoneHandler; case E_BLOCK_MYCELIUM: return BlockMyceliumHandler; case E_BLOCK_NETHERRACK: return BlockNetherrackHandler; case E_BLOCK_NETHER_BRICK: return BlockNetherBricksHandler; case E_BLOCK_NETHER_BRICK_FENCE: return BlockNetherBrickFenceHandler; case E_BLOCK_NETHER_BRICK_STAIRS: return BlockNetherBrickStairsHandler; case E_BLOCK_NETHER_PORTAL: return BlockNetherPortalHandler; case E_BLOCK_NETHER_QUARTZ_ORE: return BlockNetherQuartzOreHandler; case E_BLOCK_NETHER_WART: return BlockNetherWartHandler; case E_BLOCK_NETHER_WART_BLOCK: return BlockNetherWartBlockHandler; case E_BLOCK_NEW_LEAVES: return BlockNewLeavesHandler; case E_BLOCK_NEW_LOG: return BlockNewLogHandler; case E_BLOCK_NOTE_BLOCK: return BlockNoteBlockHandler; case E_BLOCK_OAK_DOOR: return BlockOakDoorHandler; case E_BLOCK_OAK_FENCE_GATE: return BlockOakFenceGateHandler; case E_BLOCK_OAK_WOOD_STAIRS: return BlockOakWoodStairsHandler; case E_BLOCK_OBSERVER: return BlockObserverHandler; case E_BLOCK_OBSIDIAN: return BlockObsidianHandler; case E_BLOCK_ORANGE_GLAZED_TERRACOTTA: return BlockOrangeGlazedTerracottaHandler; case E_BLOCK_ORANGE_SHULKER_BOX: return BlockOrangeShulkerBoxHandler; case E_BLOCK_PACKED_ICE: return BlockPackedIceHandler; case E_BLOCK_PINK_GLAZED_TERRACOTTA: return BlockPinkGlazedTerracottaHandler; case E_BLOCK_PINK_SHULKER_BOX: return BlockPinkShulkerBoxHandler; case E_BLOCK_PISTON: return BlockPistonHandler; case E_BLOCK_PISTON_EXTENSION: return BlockPistonHeadHandler; case E_BLOCK_PISTON_MOVED_BLOCK: return BlockPistonMovedBlockHandler; case E_BLOCK_PLANKS: return BlockPlanksHandler; case E_BLOCK_POTATOES: return BlockPotatoesHandler; case E_BLOCK_POWERED_RAIL: return BlockPoweredRailHandler; case E_BLOCK_PRISMARINE_BLOCK: return BlockPrismarineBlockHandler; case E_BLOCK_PUMPKIN: return BlockPumpkinHandler; case E_BLOCK_PUMPKIN_STEM: return BlockPumpkinStemHandler; case E_BLOCK_PURPLE_GLAZED_TERRACOTTA: return BlockPurpleGlazedTerracottaHandler; case E_BLOCK_PURPLE_SHULKER_BOX: return BlockPurpleShulkerBoxHandler; case E_BLOCK_PURPUR_BLOCK: return BlockPurpurBlockHandler; case E_BLOCK_PURPUR_DOUBLE_SLAB: return BlockPurpurDoubleSlabHandler; case E_BLOCK_PURPUR_PILLAR: return BlockPurpurPillarHandler; case E_BLOCK_PURPUR_SLAB: return BlockPurpurSlabHandler; case E_BLOCK_PURPUR_STAIRS: return BlockPurpurStairsHandler; case E_BLOCK_QUARTZ_BLOCK: return BlockQuartzBlockHandler; case E_BLOCK_QUARTZ_STAIRS: return BlockQuartzStairsHandler; case E_BLOCK_RAIL: return BlockRailHandler; case E_BLOCK_REDSTONE_LAMP_OFF: return BlockRedstoneLampHandler; case E_BLOCK_REDSTONE_LAMP_ON: return BlockRedstoneLampHandler; case E_BLOCK_REDSTONE_ORE: return BlockRedstoneOreHandler; case E_BLOCK_REDSTONE_ORE_GLOWING: return BlockRedstoneOreGlowingHandler; case E_BLOCK_REDSTONE_REPEATER_OFF: return BlockRedstoneRepeaterOffHandler; case E_BLOCK_REDSTONE_REPEATER_ON: return BlockRedstoneRepeaterOnHandler; case E_BLOCK_REDSTONE_TORCH_OFF: return BlockRedstoneTorchOffHandler; case E_BLOCK_REDSTONE_TORCH_ON: return BlockRedstoneTorchOnHandler; case E_BLOCK_REDSTONE_WIRE: return BlockRedstoneWireHandler; case E_BLOCK_RED_GLAZED_TERRACOTTA: return BlockRedGlazedTerracottaHandler; case E_BLOCK_RED_MUSHROOM: return BlockRedMushroomHandler; case E_BLOCK_RED_NETHER_BRICK: return BlockRedNetherBricksHandler; case E_BLOCK_RED_ROSE: return BlockRedRoseHandler; case E_BLOCK_RED_SANDSTONE: return BlockRedSandstoneHandler; case E_BLOCK_RED_SANDSTONE_SLAB: return BlockRedSandstoneSlabHandler; case E_BLOCK_RED_SANDSTONE_STAIRS: return BlockRedSandstoneStairsHandler; case E_BLOCK_RED_SHULKER_BOX: return BlockRedShulkerBoxHandler; case E_BLOCK_REPEATING_COMMAND_BLOCK: return BlockRepeatingCommandBlockHandler; case E_BLOCK_SAND: return BlockSandHandler; case E_BLOCK_SANDSTONE: return BlockSandstoneHandler; case E_BLOCK_SANDSTONE_STAIRS: return BlockSandstoneStairsHandler; case E_BLOCK_SAPLING: return BlockSaplingHandler; case E_BLOCK_SEA_LANTERN: return BlockSeaLanternHandler; case E_BLOCK_SIGN_POST: return BlockSignPostHandler; case E_BLOCK_SILVERFISH_EGG: return BlockInfestedBlockHandler; case E_BLOCK_SLIME_BLOCK: return BlockSlimeBlockHandler; case E_BLOCK_SNOW: return BlockSnowHandler; case E_BLOCK_SNOW_BLOCK: return BlockSnowBlockHandler; case E_BLOCK_SOULSAND: return BlockSoulSandHandler; case E_BLOCK_SPONGE: return BlockSpongeHandler; case E_BLOCK_SPRUCE_DOOR: return BlockSpruceDoorHandler; case E_BLOCK_SPRUCE_FENCE: return BlockSpruceFenceHandler; case E_BLOCK_SPRUCE_FENCE_GATE: return BlockSpruceFenceGateHandler; case E_BLOCK_SPRUCE_WOOD_STAIRS: return BlockSpruceWoodStairsHandler; case E_BLOCK_STAINED_CLAY: return BlockStainedClayHandler; case E_BLOCK_STAINED_GLASS: return BlockStainedGlassHandler; case E_BLOCK_STAINED_GLASS_PANE: return BlockStainedGlassPaneHandler; case E_BLOCK_STANDING_BANNER: return BlockStandingBannerHandler; case E_BLOCK_STATIONARY_LAVA: return BlockStationaryLavaHandler; case E_BLOCK_STATIONARY_WATER: return BlockStationaryWaterHandler; case E_BLOCK_STICKY_PISTON: return BlockStickyPistonHandler; case E_BLOCK_STONE: return BlockStoneHandler; case E_BLOCK_STONE_BRICKS: return BlockStoneBricksHandler; case E_BLOCK_STONE_BRICK_STAIRS: return BlockStoneBrickStairsHandler; case E_BLOCK_STONE_BUTTON: return BlockStoneButtonHandler; case E_BLOCK_STONE_PRESSURE_PLATE: return BlockStonePressurePlateHandler; case E_BLOCK_STONE_SLAB: return BlockStoneSlabHandler; case E_BLOCK_STRUCTURE_BLOCK: return BlockStructureBlockHandler; case E_BLOCK_STRUCTURE_VOID: return BlockStructureVoidHandler; case E_BLOCK_SUGARCANE: return BlockSugarCaneHandler; case E_BLOCK_TALL_GRASS: return BlockTallGrassHandler; case E_BLOCK_TNT: return BlockTNTHandler; case E_BLOCK_TORCH: return BlockTorchHandler; case E_BLOCK_TRAPDOOR: return BlockTrapdoorHandler; case E_BLOCK_TRAPPED_CHEST: return BlockTrappedChestHandler; case E_BLOCK_TRIPWIRE: return BlockTripwireHandler; case E_BLOCK_TRIPWIRE_HOOK: return BlockTripwireHookHandler; case E_BLOCK_VINES: return BlockVinesHandler; case E_BLOCK_WALLSIGN: return BlockWallsignHandler; case E_BLOCK_WALL_BANNER: return BlockWallBannerHandler; case E_BLOCK_WATER: return BlockWaterHandler; case E_BLOCK_WHITE_GLAZED_TERRACOTTA: return BlockWhiteGlazedTerracottaHandler; case E_BLOCK_WHITE_SHULKER_BOX: return BlockWhiteShulkerBoxHandler; case E_BLOCK_WOODEN_BUTTON: return BlockWoodenButtonHandler; case E_BLOCK_WOODEN_PRESSURE_PLATE: return BlockWoodenPressurePlateHandler; case E_BLOCK_WOODEN_SLAB: return BlockWoodenSlabHandler; case E_BLOCK_WOOL: return BlockWoolHandler; case E_BLOCK_WORKBENCH: return BlockWorkbenchHandler; case E_BLOCK_YELLOW_FLOWER: return BlockYellowFlowerHandler; case E_BLOCK_YELLOW_GLAZED_TERRACOTTA: return BlockYellowGlazedTerracottaHandler; case E_BLOCK_YELLOW_SHULKER_BOX: return BlockYellowShulkerBoxHandler; // TODO: these will be removed in 1.13+ migration case E_BLOCK_NUMBER_OF_TYPES: case E_BLOCK_UNFINISHED: return BlockAirHandler; } UNREACHABLE("Getting handler for unexpected block type"); } ================================================ FILE: src/Blocks/BlockHandler.h ================================================ #pragma once #include "../Defines.h" #include "../Item.h" #include "../BoundingBox.h" // fwd: class cPlayer; class cChunk; class cBlockPluginInterface; class cChunkInterface; class cWorld; class cWorldInterface; class cItems; class cBlockHandler { public: constexpr cBlockHandler(BLOCKTYPE a_BlockType) : m_BlockType(a_BlockType) { } /** Called when the block gets ticked either by a random tick or by a queued tick. Note that the coords in a_RelPos are chunk-relative! */ virtual void OnUpdate( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cBlockPluginInterface & a_BlockPluginInterface, cChunk & a_Chunk, const Vector3i a_RelPos ) const; /** Returns the relative bounding box that must be entity-free in order for the block to be placed. a_XM, a_XP, etc. stand for the blocktype of the minus-X neighbor, the positive-X neighbor, etc. */ virtual cBoundingBox GetPlacementCollisionBox(BLOCKTYPE a_XM, BLOCKTYPE a_XP, BLOCKTYPE a_YM, BLOCKTYPE a_YP, BLOCKTYPE a_ZM, BLOCKTYPE a_ZP) const; /** Called by cWorld::SetBlock() after the block has been set */ virtual void OnPlaced( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta ) const {} /** Called after a block gets broken (replaced with air), by natural means. The block is already dug up in the world, the original block type and meta is passed in a_OldBlockType and a_OldBlockMeta. By default notifies all direct neighbors via their OnNeighborChanged() callbacks. You can determine what kind of entity broke the block (e.g. player) by checking a_Digger! */ virtual void OnBroken( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, Vector3i a_BlockPos, BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta, const cEntity * a_Digger ) const {} /** Called when a direct neighbor of this block has been changed. The position is the block's own position, NOT the changed neighbor's position. a_WhichNeighbor indicates which neighbor has changed. For example, BLOCK_FACE_YP meant the neighbor above has changed. BLOCK_FACE_NONE means that it is a neighbor not directly adjacent (diagonal, etc.) */ virtual void OnNeighborChanged(cChunkInterface & a_ChunkInterface, Vector3i a_BlockPos, eBlockFace a_WhichNeighbor) const; /** Notifies the specified neighbor that the current block has changed. a_NeighborPos are the coords of the neighbor to be notified a_WhichNeighbor specifies which neighbor (relative to a_NeighborPos) has changed. For example BLOCK_FACE_YP means that the block at {a_NeighborX, a_NeighborY + 1, a_NeighborZ} has changed. BLOCK_FACE_NONE means that it is a neighbor not directly adjacent (diagonal, etc.) */ static void NeighborChanged(cChunkInterface & a_ChunkInterface, Vector3i a_NeighborPos, eBlockFace a_WhichNeighbor); /** Called when the player starts digging the block. */ virtual void OnDigging( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, const Vector3i a_BlockPos ) const { } /** Called when the user right clicks the block and the block is useable. a_CursorPos is the cursor position within the clicked block face. Returns true if the use was successful, return false to use the block as a "normal" block */ virtual bool OnUse( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, const Vector3i a_BlockPos, eBlockFace a_BlockFace, const Vector3i a_CursorPos ) const { return false; } /** Called when a right click to this block is cancelled. Descendants should force the server to send the real state of a block to the client to prevent client assuming the operation was successfull. */ virtual void OnCancelRightClick( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, const Vector3i a_BlockPos, eBlockFace a_BlockFace ) const { } /** Returns the pickups that would result if the block was mined by a_Digger using a_Tool. Doesn't do any actual block change / mining, only calculates the pickups. a_Digger is the entity that caused the conversion, usually the player digging. a_Tool is the tool used for the digging. The default implementation drops a single item created from m_BlockType and the current meta. */ virtual cItems ConvertToPickups(NIBBLETYPE a_BlockMeta, const cItem * a_Tool = nullptr) const; /** Checks if the block can stay at the specified relative coords in the chunk */ virtual bool CanBeAt(const cChunk & a_Chunk, Vector3i a_Position, NIBBLETYPE a_Meta) const; /** Checks whether the block has an effect on growing the plant */ virtual bool CanSustainPlant(BLOCKTYPE a_Plant) const { return false; } /** Called to check whether this block supports a rclk action. If it returns true, OnUse() is called */ virtual bool IsUseable(void) const; /** Checks if the player can build "inside" this block. For example blocks placed "on" snow will be placed at the same position. So: Snow ignores Build collision @param a_Pos Position of the block @param a_Player Player trying to build on the block @param a_Meta Meta value of the block currently at a_Pos */ virtual bool DoesIgnoreBuildCollision(const cWorld & a_World, const cItem & a_HeldItem, Vector3i a_Position, NIBBLETYPE a_Meta, eBlockFace a_ClickedBlockFace, bool a_ClickedDirectly) const; /** Tests if a_RelPosition is inside the block, where a_RelPosition is relative to the origin of the block. Coords in a_RelPosition are guaranteed to be in the [0..1] range. */ virtual bool IsInsideBlock(const Vector3d a_RelPosition, const NIBBLETYPE a_BlockMeta) const; /** Called when one of the neighbors gets set; equivalent to MC block update. By default drops (DropBlockAsPickup() / SetBlock()) if the position is no longer suitable (CanBeAt(), DoesDropOnUnsuitable()), otherwise wakes up all simulators on the block. */ void Check( cChunkInterface & ChunkInterface, cBlockPluginInterface & a_PluginInterface, Vector3i a_RelPos, cChunk & a_Chunk ) const; /** Returns the base colour ID of the block, as will be represented on a map, as per documentation: https://minecraft.wiki/w/Map_item_format */ virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const; /** Rotates a given block meta counter-clockwise. Default: no change Returns block meta following rotation */ virtual NIBBLETYPE MetaRotateCCW(NIBBLETYPE a_Meta) const { return a_Meta; } /** Rotates a given block meta clockwise. Default: no change Returns block meta following rotation */ virtual NIBBLETYPE MetaRotateCW(NIBBLETYPE a_Meta) const { return a_Meta; } /** Mirrors a given block meta around the XY plane. Default: no change Returns block meta following rotation */ virtual NIBBLETYPE MetaMirrorXY(NIBBLETYPE a_Meta) const { return a_Meta; } /** Mirros a given block meta around the XZ plane. Default: no change Returns block meta following rotation */ virtual NIBBLETYPE MetaMirrorXZ(NIBBLETYPE a_Meta) const { return a_Meta; } /** Mirros a given block meta around the YZ plane. Default: no change Returns block meta following rotation */ virtual NIBBLETYPE MetaMirrorYZ(NIBBLETYPE a_Meta) const { return a_Meta; } /** Grows this block, if it supports growing, by the specified amount of stages (at most). Returns the number of stages actually grown, zero if not supported (default). */ virtual int Grow(cChunk & a_Chunk, Vector3i a_RelPos, int a_NumStages = 1) const { return 0; } /** Returns true if the specified tool is valid and has a non-zero silk-touch enchantment. Helper used in many ConvertToPickups() implementations. */ static bool ToolHasSilkTouch(const cItem * a_Tool); /** Returns the fortune level of a tool, if it is a valid tool. Can be used in ConvertToPickups() implementations. */ static unsigned char ToolFortuneLevel(const cItem * a_Tool); /** Returns a random number of drops taking into account fortune. Only applies to drops following clamped discrete random distribution. a_DefaultMax is the maximum items from one block without fortune. a_BonusMax is the amount to increase the max of randInt by, usually the fortune level (but not always) a_DropCap is the maximum items from one block with fortune, if unspecified set to 25 to prevent lag or crash with high level tools. Similar to uniform_bonus_count at https://minecraft.wiki/w/Loot_table#Functions */ static char FortuneDiscreteRandom(char a_MinDrop, char a_DefaultMax, unsigned char a_BonusMax, char a_DropCap = 25); // Gets the blockhandler for the given block type. static const cBlockHandler & For(BLOCKTYPE a_BlockType); protected: ~cBlockHandler() = default; const BLOCKTYPE m_BlockType; }; ================================================ FILE: src/Blocks/BlockHopper.h ================================================ // BlockHopper.h // Declares the cBlockHopperHandler class representing the handler for the Hopper block #include "Mixins/Mixins.h" class cBlockHopperHandler final : public cClearMetaOnDrop> { using Super = cClearMetaOnDrop>; public: using Super::Super; private: virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 11; } } ; ================================================ FILE: src/Blocks/BlockHugeMushroom.h ================================================ #pragma once #include "BlockHandler.h" /** Handler for huge mushroom blocks. */ class cBlockHugeMushroomHandler final : public cBlockHandler { using Super = cBlockHandler; public: using Super::Super; private: virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override { if (ToolHasSilkTouch(a_Tool)) { return cItem(m_BlockType); } else if ((a_BlockMeta == E_META_MUSHROOM_FULL_STEM) || (a_BlockMeta == E_META_MUSHROOM_STEM)) { // Stems don't drop anything return cItem(); } const auto MushroomType = (m_BlockType == E_BLOCK_HUGE_BROWN_MUSHROOM) ? E_BLOCK_BROWN_MUSHROOM : E_BLOCK_RED_MUSHROOM; const auto DropNum = GetRandomProvider().RandInt(2); return cItem(MushroomType, DropNum); } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return (m_BlockType == E_BLOCK_HUGE_BROWN_MUSHROOM) ? 10 : 28; } } ; ================================================ FILE: src/Blocks/BlockIce.h ================================================ #pragma once #include "BlockHandler.h" class cBlockIceHandler final : public cBlockHandler { using Super = cBlockHandler; public: using Super::Super; private: virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override { // Only drop self when using silk-touch: if (ToolHasSilkTouch(a_Tool)) { return cItem(m_BlockType); } return {}; } virtual void OnUpdate( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cBlockPluginInterface & a_PluginInterface, cChunk & a_Chunk, const Vector3i a_RelPos ) const override { // Disappears instantly in nether: if (a_WorldInterface.GetDimension() == dimNether) { a_Chunk.SetBlock(a_RelPos, E_BLOCK_AIR, 0); return; } // Artificial light on any of the surrounding block > 11 leads to melting the ice. static const std::array Adjacents { { { 1, 0, 0 }, { -1, 0, 0 }, { 0, 1, 0 }, { 0, -1, 0 }, { 0, 0, 1 }, { 0, 0, -1 } } }; for (const auto & Offset : Adjacents) { auto Position = a_RelPos + Offset; const auto Chunk = a_Chunk.GetRelNeighborChunkAdjustCoords(Position); if ((Chunk == nullptr) || !Chunk->IsValid()) { continue; } if (!Chunk->IsLightValid()) { Chunk->GetWorld()->QueueLightChunk(Chunk->GetPosX(), Chunk->GetPosZ()); continue; } if (Chunk->GetBlockLight(Position) > 11) { a_Chunk.SetBlock(a_RelPos, E_BLOCK_STATIONARY_WATER, 0); return; } } } virtual void OnBroken( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, Vector3i a_BlockPos, BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta, const cEntity * a_Digger ) const override { UNUSED(a_Digger); // If there's a solid block or a liquid underneath, convert to water, rather than air if (a_BlockPos.y <= 0) { return; } const auto Below = a_ChunkInterface.GetBlock(a_BlockPos.addedY(-1)); if (cBlockInfo::FullyOccupiesVoxel(Below) || IsBlockLiquid(Below)) { a_ChunkInterface.SetBlock(a_BlockPos, E_BLOCK_WATER, 0); } } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 5; } } ; ================================================ FILE: src/Blocks/BlockInfested.h ================================================ // BlockInfested.h // Declares the cBlockInfestedHandler class representing the handler for Silverfish blocks (Mojang calls them Monster Eggs) #include "../Entities/Player.h" class cBlockInfestedHandler final: public cBlockHandler { using Super = cBlockHandler; public: using Super::Super; private: static void SpawnSilverfish(cWorldInterface & a_WorldInterface, Vector3i a_BlockPos) { // TODO: only display animation if the difficulty allows mob spawns - Add when difficulty is implemented const auto Position = Vector3f(a_BlockPos.x + 0.5f, static_cast(a_BlockPos.y), a_BlockPos.z + 0.5f); a_WorldInterface.SpawnMob(Position.x, Position.y, Position.z, mtSilverfish, false); a_WorldInterface.GetBroadcastManager().BroadcastParticleEffect("explode", Position, Vector3f(), 0.1f, 50); } virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override { switch (a_BlockMeta) { case E_META_SILVERFISH_EGG_STONE: { if (ToolHasSilkTouch(a_Tool)) { return { E_BLOCK_STONE }; } else { return { E_BLOCK_COBBLESTONE }; } } case E_META_SILVERFISH_EGG_COBBLESTONE: return { E_BLOCK_COBBLESTONE }; case E_META_SILVERFISH_EGG_STONE_BRICK: return { E_BLOCK_STONE_BRICKS }; case E_META_SILVERFISH_EGG_MOSSY_STONE_BRICK: return cItem(E_BLOCK_STONE_BRICKS, 1, E_META_STONE_BRICK_MOSSY); case E_META_SILVERFISH_EGG_CRACKED_STONE_BRICK: return cItem(E_BLOCK_STONE_BRICKS, 1, E_META_STONE_BRICK_CRACKED); case E_META_SILVERFISH_EGG_CHISELED_STONE_BRICK: return cItem(E_BLOCK_STONE_BRICKS, 1, E_META_STONE_BRICK_ORNAMENT); } return {}; } virtual void OnBroken( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, Vector3i a_BlockPos, BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta, const cEntity * a_Digger ) const override { if (a_Digger != nullptr) { if (a_Digger->IsPlayer()) { const auto Player = static_cast(a_Digger); if (Player->IsGameModeCreative()) { return; } } if (a_Digger->IsMob() || a_Digger->IsTNT()) { return; } } SpawnSilverfish(a_WorldInterface, a_BlockPos); } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { return 11; } } ; ================================================ FILE: src/Blocks/BlockJukebox.h ================================================ #pragma once #include "BlockEntity.h" #include "Mixins/Mixins.h" class cBlockJukeboxHandler final : public cClearMetaOnDrop { public: using cClearMetaOnDrop::cClearMetaOnDrop; private: virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 10; } } ; ================================================ FILE: src/Blocks/BlockLadder.h ================================================ #pragma once #include "BlockHandler.h" #include "BlockInfo.h" #include "Mixins/Mixins.h" class cBlockLadderHandler final : public cClearMetaOnDrop > { using Super = cClearMetaOnDrop>; public: using Super::Super; /** Returns true if the ladder will be supported by the block through the given blockface. */ static bool CanBePlacedOn(const BLOCKTYPE a_BlockType, const eBlockFace a_BlockFace) { if ( (a_BlockFace == BLOCK_FACE_NONE) || (a_BlockFace == BLOCK_FACE_BOTTOM) || (a_BlockFace == BLOCK_FACE_TOP) ) { return false; } return cBlockInfo::FullyOccupiesVoxel(a_BlockType); } private: /** Converts the ladder block's meta to the block face of the neighbor to which the ladder is attached. */ static eBlockFace MetaDataToBlockFace(NIBBLETYPE a_MetaData) { switch (a_MetaData) { case 0x2: return BLOCK_FACE_ZM; case 0x3: return BLOCK_FACE_ZP; case 0x4: return BLOCK_FACE_XM; case 0x5: return BLOCK_FACE_XP; default: return BLOCK_FACE_ZM; } } virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override { auto Face = MetaDataToBlockFace(a_Meta); auto NeighborRelPos = AddFaceDirection(a_Position, Face, true); BLOCKTYPE NeighborBlockType; a_Chunk.UnboundedRelGetBlockType(NeighborRelPos, NeighborBlockType); return CanBePlacedOn(NeighborBlockType, Face); } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 0; } } ; ================================================ FILE: src/Blocks/BlockLeaves.h ================================================ #pragma once #include "BlockHandler.h" #include "../FastRandom.h" #include "../BlockArea.h" // Leaves can be this many blocks that away (inclusive) from the log not to decay #define LEAVES_CHECK_DISTANCE 6 class cBlockLeavesHandler final : public cBlockHandler { using Super = cBlockHandler; public: using Super::Super; private: static double FortuneDropProbability(unsigned char a_DefaultDenominator, unsigned char a_FirstDenominatorReduction, unsigned char a_FortuneLevel) { // Fortune 3 behaves like fortune 4 for some reason if (a_FortuneLevel == 3) { a_FortuneLevel++; } // Denominator, capped at minimum of 10. const auto Denominator = std::max(10, a_DefaultDenominator - a_FortuneLevel * a_FirstDenominatorReduction); return 1.0 / Denominator; } /** Returns true if the area contains a continous path from the specified block to a log block entirely made out of leaves blocks. */ static bool HasNearLog(cBlockArea & a_Area, const Vector3i a_BlockPos) { // Filter the blocks into a {leaves, log, other (air)} set: auto * Types = a_Area.GetBlockTypes(); for (size_t i = a_Area.GetBlockCount() - 1; i > 0; i--) { switch (Types[i]) { case E_BLOCK_LEAVES: case E_BLOCK_LOG: case E_BLOCK_NEW_LEAVES: case E_BLOCK_NEW_LOG: { break; } default: { Types[i] = E_BLOCK_AIR; break; } } } // for i - Types[] // Perform a breadth-first search to see if there's a log connected within 4 blocks of the leaves block: // Simply replace all reachable leaves blocks with a sponge block plus iteration (in the Area) and see if we can reach a log a_Area.SetBlockType(a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, E_BLOCK_SPONGE); for (int i = 0; i < LEAVES_CHECK_DISTANCE; i++) { auto ProcessNeighbor = [&a_Area, i](int cbx, int cby, int cbz) -> bool { switch (a_Area.GetBlockType(cbx, cby, cbz)) { case E_BLOCK_LEAVES: a_Area.SetBlockType(cbx, cby, cbz, static_cast(E_BLOCK_SPONGE + i + 1)); break; case E_BLOCK_LOG: return true; case E_BLOCK_NEW_LEAVES: a_Area.SetBlockType(cbx, cby, cbz, static_cast(E_BLOCK_SPONGE + i + 1)); break; case E_BLOCK_NEW_LOG: return true; } return false; }; for (int y = std::max(a_BlockPos.y - i, 0); y <= std::min(a_BlockPos.y + i, cChunkDef::Height - 1); y++) { for (int z = a_BlockPos.z - i; z <= a_BlockPos.z + i; z++) { for (int x = a_BlockPos.x - i; x <= a_BlockPos.x + i; x++) { if (a_Area.GetBlockType(x, y, z) != E_BLOCK_SPONGE + i) { continue; } if ( ProcessNeighbor(x - 1, y, z) || ProcessNeighbor(x + 1, y, z) || ProcessNeighbor(x, y, z - 1) || ProcessNeighbor(x, y, z + 1) || ProcessNeighbor(x, y + 1, z) || ProcessNeighbor(x, y - 1, z) ) { return true; } } // for x } // for z } // for y } // for i - BFS iterations return false; } virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override { // If breaking with shears, drop self: if ((a_Tool != nullptr) && (a_Tool->m_ItemType == E_ITEM_SHEARS)) { return cItem(m_BlockType, 1, a_BlockMeta & 0x03); } // There is a chance to drop a sapling that varies depending on the type of leaf broken. // Note: It is possible (though very rare) for a single leaves block to drop both a sapling and an apple double DropProbability; const auto FortuneLevel = ToolFortuneLevel(a_Tool); auto & Random = GetRandomProvider(); cItems Res; if ((m_BlockType == E_BLOCK_LEAVES) && ((a_BlockMeta & 0x03) == E_META_LEAVES_JUNGLE)) { // Jungle leaves have a 2.5% default chance of dropping a sapling. DropProbability = FortuneDropProbability(40, 4, FortuneLevel); } else { // Other leaves have a 5% default chance of dropping a sapling. DropProbability = FortuneDropProbability(20, 4, FortuneLevel); } if (Random.RandBool(DropProbability)) { Res.Add( E_BLOCK_SAPLING, 1, (m_BlockType == E_BLOCK_LEAVES) ? (a_BlockMeta & 0x03) : static_cast(4 + (a_BlockMeta & 0x01)) ); } // 0.5 % chance of dropping an apple, increased by fortune, if the leaves' type is Apple Leaves if ((m_BlockType == E_BLOCK_LEAVES) && ((a_BlockMeta & 0x03) == E_META_LEAVES_APPLE)) { DropProbability = FortuneDropProbability(200, 20, FortuneLevel); if (Random.RandBool(DropProbability)) { Res.Add(E_ITEM_RED_APPLE); } } // 2% chance of dropping sticks (yuck) in 1.14 DropProbability = FortuneDropProbability(50, 5, FortuneLevel); if (Random.RandBool(DropProbability)) { // 1 or 2 sticks are dropped on success: Res.Add(E_ITEM_STICK, Random.RandInt(1, 2)); } return Res; } virtual void OnNeighborChanged(cChunkInterface & a_ChunkInterface, Vector3i a_BlockPos, eBlockFace a_WhichNeighbor) const override { auto meta = a_ChunkInterface.GetBlockMeta(a_BlockPos); // Set bit 0x08, so this block gets checked for decay: if ((meta & 0x08) == 0) { a_ChunkInterface.SetBlockMeta(a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, meta | 0x8); } } virtual void OnUpdate( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cBlockPluginInterface & a_PluginInterface, cChunk & a_Chunk, const Vector3i a_RelPos ) const override { auto Meta = a_Chunk.GetMeta(a_RelPos); if ((Meta & 0x04) != 0) { // Player-placed leaves, don't decay return; } if ((Meta & 0x08) == 0) { // These leaves have been checked for decay lately and nothing around them changed return; } // Get the data around the leaves: auto worldPos = a_Chunk.RelativeToAbsolute(a_RelPos); cBlockArea Area; if (!Area.Read( *a_Chunk.GetWorld(), worldPos - Vector3i(LEAVES_CHECK_DISTANCE, LEAVES_CHECK_DISTANCE, LEAVES_CHECK_DISTANCE), worldPos + Vector3i(LEAVES_CHECK_DISTANCE, LEAVES_CHECK_DISTANCE, LEAVES_CHECK_DISTANCE), cBlockArea::baTypes) ) { // Cannot check leaves, a chunk is missing too close return; } if (HasNearLog(Area, worldPos)) { // Wood found, the leaves stay; unset the check bit a_Chunk.SetMeta(a_RelPos, Meta ^ 0x08); return; } // Decay the leaves: a_ChunkInterface.DropBlockAsPickups(worldPos); } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 7; } } ; ================================================ FILE: src/Blocks/BlockLever.h ================================================ #pragma once #include "BlockHandler.h" #include "../Chunk.h" #include "Blocks/BlockStairs.h" #include "ChunkDef.h" #include "Defines.h" #include "Mixins/Mixins.h" #include "BlockSlab.h" class cBlockLeverHandler final : public cMetaRotator { using Super = cMetaRotator; public: using Super::Super; /** Extracts the ON bit from metadata and returns if true if it is set */ static bool IsLeverOn(NIBBLETYPE a_BlockMeta) { return ((a_BlockMeta & 0x8) == 0x8); } private: virtual bool OnUse( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, const Vector3i a_BlockPos, eBlockFace a_BlockFace, const Vector3i a_CursorPos ) const override { // Flip the ON bit on / off using the XOR bitwise operation NIBBLETYPE Meta = (a_ChunkInterface.GetBlockMeta(a_BlockPos) ^ 0x08); a_ChunkInterface.SetBlockMeta(a_BlockPos, Meta); a_WorldInterface.WakeUpSimulators(a_BlockPos); a_WorldInterface.GetBroadcastManager().BroadcastSoundEffect("block.lever.click", a_BlockPos, 0.5f, (Meta & 0x08) ? 0.6f : 0.5f); return true; } virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override { // Reset meta to zero: return cItem(E_BLOCK_LEVER, 1, 0); } virtual bool IsUseable(void) const override { return true; } /** Converts the leve block's meta to the block face of the neighbor to which the lever is attached. */ inline static eBlockFace BlockMetaDataToBlockFace(NIBBLETYPE a_Meta) { switch (a_Meta & 0x7) { case 0x1: return BLOCK_FACE_XP; case 0x2: return BLOCK_FACE_XM; case 0x3: return BLOCK_FACE_ZP; case 0x4: return BLOCK_FACE_ZM; case 0x5: case 0x6: return BLOCK_FACE_YP; case 0x7: case 0x0: return BLOCK_FACE_YM; default: { ASSERT(!"Unhandled block meta!"); return BLOCK_FACE_NONE; } } } virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override { // Find the type of block the lever is attached to: auto NeighborFace = BlockMetaDataToBlockFace(a_Meta); auto NeighborPos = AddFaceDirection(a_Position, NeighborFace, true); if (!cChunkDef::IsValidHeight(NeighborPos)) { return false; } BLOCKTYPE NeighborBlockType; NIBBLETYPE NeighborMeta; if (!a_Chunk.UnboundedRelGetBlock(NeighborPos, NeighborBlockType, NeighborMeta)) { return false; } // Allow any full block or the "good" side of a half-slab: if (cBlockInfo::FullyOccupiesVoxel(NeighborBlockType)) { return true; } else if (cBlockSlabHandler::IsAnySlabType(NeighborBlockType)) { return ( (((NeighborMeta & 0x08) == 0x08) && (NeighborFace == BLOCK_FACE_TOP)) || (((NeighborMeta & 0x08) == 0) && (NeighborFace == BLOCK_FACE_BOTTOM)) ); } else if (cBlockStairsHandler::IsAnyStairType(NeighborBlockType)) { switch (NeighborFace) { case eBlockFace::BLOCK_FACE_YM: return !(NeighborMeta & E_BLOCK_STAIRS_UPSIDE_DOWN); case eBlockFace::BLOCK_FACE_YP: return (NeighborMeta & E_BLOCK_STAIRS_UPSIDE_DOWN); case eBlockFace::BLOCK_FACE_XP: return ((NeighborMeta & 0b11) == E_BLOCK_STAIRS_XP); case eBlockFace::BLOCK_FACE_XM: return ((NeighborMeta & 0b11) == E_BLOCK_STAIRS_XM); case eBlockFace::BLOCK_FACE_ZP: return ((NeighborMeta & 0b11) == E_BLOCK_STAIRS_ZP); case eBlockFace::BLOCK_FACE_ZM: return ((NeighborMeta & 0b11) == E_BLOCK_STAIRS_ZM); default: { return false; } } } return false; } virtual NIBBLETYPE MetaRotateCCW(NIBBLETYPE a_Meta) const override { switch (a_Meta) { case 0x00: return 0x07; // Ceiling rotation case 0x07: return 0x00; case 0x05: return 0x06; // Ground rotation case 0x06: return 0x05; default: return Super::MetaRotateCCW(a_Meta); // Wall Rotation } } virtual NIBBLETYPE MetaRotateCW(NIBBLETYPE a_Meta) const override { switch (a_Meta) { case 0x00: return 0x07; // Ceiling rotation case 0x07: return 0x00; case 0x05: return 0x06; // Ground rotation case 0x06: return 0x05; default: return Super::MetaRotateCW(a_Meta); // Wall Rotation } } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 0; } } ; ================================================ FILE: src/Blocks/BlockLilypad.h ================================================ #pragma once #include "BlockHandler.h" class cBlockLilypadHandler final : public cClearMetaOnDrop { using Super = cClearMetaOnDrop; public: using Super::Super; private: virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 7; } virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override { auto UnderPos = a_Position.addedY(-1); if (!cChunkDef::IsValidHeight(UnderPos)) { return false; } BLOCKTYPE UnderType; NIBBLETYPE UnderMeta; a_Chunk.GetBlockTypeMeta(UnderPos, UnderType, UnderMeta); return ( (((UnderType == E_BLOCK_STATIONARY_WATER) || (UnderType == E_BLOCK_WATER)) && (UnderMeta == 0)) || // A water source is below (UnderType == E_BLOCK_ICE) || (UnderType == E_BLOCK_FROSTED_ICE) // Or (frosted) ice ); } }; ================================================ FILE: src/Blocks/BlockMelon.h ================================================ #pragma once #include "BlockHandler.h" class cBlockMelonHandler final : public cBlockHandler { using Super = cBlockHandler; public: using Super::Super; private: virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override { const auto DropNum = FortuneDiscreteRandom(3, 7, ToolFortuneLevel(a_Tool), 9); return cItem(E_ITEM_MELON_SLICE, DropNum); } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 19; } } ; ================================================ FILE: src/Blocks/BlockMobHead.h ================================================ #pragma once #include "BlockEntity.h" class cBlockMobHeadHandler final : public cBlockEntityHandler { using Super = cBlockEntityHandler; public: using Super::Super; private: virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override { // Drops handled by the block entity: return {}; } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 0; } } ; ================================================ FILE: src/Blocks/BlockMobSpawner.h ================================================ #pragma once #include "BlockHandler.h" #include "../Items/ItemHandler.h" class cBlockMobSpawnerHandler final : public cBlockHandler { using Super = cBlockHandler; public: using Super::Super; private: virtual bool OnUse( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, const Vector3i a_BlockPos, eBlockFace a_BlockFace, const Vector3i a_CursorPos ) const override { return a_ChunkInterface.UseBlockEntity(&a_Player, a_BlockPos.x, a_BlockPos.y, a_BlockPos.z); } virtual bool IsUseable() const override { return true; } virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override { // No pickups return {}; } virtual void OnBroken( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, Vector3i a_BlockPos, BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta, const cEntity * a_Digger ) const override { if (a_Digger == nullptr) { return; } if (!a_Digger->IsPlayer()) { return; } const auto Player = static_cast(a_Digger); auto & Handler = Player->GetEquippedItem().GetHandler(); if (!Player->IsGameModeSurvival() || !Handler.CanHarvestBlock(E_BLOCK_MOB_SPAWNER)) { return; } auto & Random = GetRandomProvider(); int Reward = 15 + Random.RandInt(14) + Random.RandInt(14); a_WorldInterface.SpawnSplitExperienceOrbs(Vector3d(0.5, 0.5, 0.5) + a_BlockPos, Reward); } } ; ================================================ FILE: src/Blocks/BlockMushroom.h ================================================ #pragma once #include "BlockHandler.h" /** Handler for the small (singleblock) mushrooms. */ class cBlockMushroomHandler final : public cClearMetaOnDrop { using Super = cClearMetaOnDrop; public: using Super::Super; private: // TODO: Add Mushroom Spread virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override { const auto BasePos = a_Position.addedY(-1); if (!cChunkDef::IsValidHeight(BasePos)) { return false; } // TODO: Cannot be at too much daylight switch (a_Chunk.GetBlock(BasePos)) { case E_BLOCK_GLASS: case E_BLOCK_CACTUS: case E_BLOCK_ICE: case E_BLOCK_LEAVES: case E_BLOCK_NEW_LEAVES: case E_BLOCK_AIR: { return false; } } return true; } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 0; } } ; ================================================ FILE: src/Blocks/BlockMycelium.h ================================================ #pragma once #include "BlockHandler.h" class cBlockMyceliumHandler final : public cBlockHandler { public: using cBlockHandler::cBlockHandler; private: // TODO: Add Mycel Spread virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override { return cItem(E_BLOCK_DIRT, 1, 0); } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 24; } } ; ================================================ FILE: src/Blocks/BlockNetherWart.h ================================================ #pragma once #include "BlockPlant.h" #include "../FastRandom.h" class cBlockNetherWartHandler final : public cBlockPlant { using Super = cBlockPlant; public: using Super::Super; private: virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override { if (a_BlockMeta == 0x03) { // Fully grown, drop the entire produce: const auto DropNum = FortuneDiscreteRandom(2, 4, ToolFortuneLevel(a_Tool)); return cItem(E_ITEM_NETHER_WART, DropNum); } return cItem(E_ITEM_NETHER_WART); } virtual int Grow(cChunk & a_Chunk, Vector3i a_RelPos, int a_NumStages = 1) const override { auto oldMeta = a_Chunk.GetMeta(a_RelPos); auto meta = std::min(oldMeta + a_NumStages, 3); if ((oldMeta < 3) && (CanGrow(a_Chunk, a_RelPos) == paGrowth)) { a_Chunk.SetBlock(a_RelPos, m_BlockType, static_cast(meta)); return meta - oldMeta; } // In older versions of cuberite, there was a bug which made wart grow too much. This check fixes previously saved buggy warts. if (oldMeta > 3) { a_Chunk.FastSetBlock(a_RelPos, m_BlockType, 3); } return 0; } virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override { // Needs to be placed on top of a Soulsand block: const auto BasePos = a_Position.addedY(-1); return cChunkDef::IsValidHeight(BasePos) && (a_Chunk.GetBlock(BasePos) == E_BLOCK_SOULSAND); } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 35; } } ; ================================================ FILE: src/Blocks/BlockNetherrack.h ================================================ #pragma once #include "BlockHandler.h" class cBlockNetherrack final : public cBlockHandler { public: using cBlockHandler::cBlockHandler; private: virtual bool CanSustainPlant(BLOCKTYPE a_Plant) const override { return a_Plant == E_BLOCK_NETHER_WART; } }; ================================================ FILE: src/Blocks/BlockNoteBlock.h ================================================ #pragma once #include "BlockEntity.h" #include "../BlockEntities/NoteEntity.h" class cBlockNoteBlockHandler final : public cBlockEntityHandler { using Super = cBlockEntityHandler; public: using Super::Super; private: virtual void OnDigging( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, const Vector3i a_BlockPos ) const override { a_WorldInterface.DoWithBlockEntityAt(a_BlockPos, [](cBlockEntity & a_BlockEntity) { ASSERT(a_BlockEntity.GetBlockType() == E_BLOCK_NOTE_BLOCK); static_cast(a_BlockEntity).MakeSound(); return false; }); } }; ================================================ FILE: src/Blocks/BlockObserver.h ================================================ #pragma once #include "BlockHandler.h" #include "Mixins/Mixins.h" class cBlockObserverHandler final : public cClearMetaOnDrop> { using Super = cClearMetaOnDrop>; public: using Super::Super; inline static Vector3i GetObservingFaceOffset(NIBBLETYPE a_Meta) { return -GetSignalOutputOffset(a_Meta); } inline static Vector3i GetSignalOutputOffset(NIBBLETYPE a_Meta) { switch (a_Meta & 0x7) { case 0x00: return { 0, 1, 0 }; case 0x01: return { 0, -1, 0 }; case 0x02: return { 0, 0, 1 }; case 0x03: return { 0, 0, -1 }; case 0x04: return { 1, 0, 0 }; case 0x05: return { -1, 0, 0 }; default: { LOGWARNING("%s: Unknown metadata: %d", __FUNCTION__, a_Meta); ASSERT(!"Unknown metadata while determining orientation of observer!"); return { 0, 0, 0 }; } } } }; ================================================ FILE: src/Blocks/BlockOre.h ================================================ #pragma once #include "Blocks/BlockHandler.h" #include "Items/ItemHandler.h" class cBlockOreHandler : public cBlockHandler { using Super = cBlockHandler; public: using Super::Super; protected: ~cBlockOreHandler() = default; private: virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override { // If using silk-touch, drop self rather than the resource: if (ToolHasSilkTouch(a_Tool)) { switch (m_BlockType) { // If it was a glowing redstone ore, drop a normal redstone ore: case E_BLOCK_REDSTONE_ORE_GLOWING: return cItem(E_BLOCK_REDSTONE_ORE); default: return cItem(m_BlockType); } } const auto FortuneLevel = ToolFortuneLevel(a_Tool); if ((m_BlockType == E_BLOCK_REDSTONE_ORE) || (m_BlockType == E_BLOCK_REDSTONE_ORE_GLOWING)) { // Redstone follows the discrete random distribution, unlike other ores const auto DropNum = FortuneDiscreteRandom(4, 5, FortuneLevel); return cItem(E_ITEM_REDSTONE_DUST, DropNum); } auto & Random = GetRandomProvider(); const auto DropMult = std::max(static_cast(1), FloorC(Random.RandReal(FortuneLevel + 2.0))); switch (m_BlockType) { case E_BLOCK_LAPIS_ORE: return cItem(E_ITEM_DYE, DropMult * Random.RandInt(4, 9), 4); case E_BLOCK_DIAMOND_ORE: return cItem(E_ITEM_DIAMOND, DropMult); case E_BLOCK_EMERALD_ORE: return cItem(E_ITEM_EMERALD, DropMult); case E_BLOCK_COAL_ORE: return cItem(E_ITEM_COAL, DropMult); case E_BLOCK_NETHER_QUARTZ_ORE: return cItem(E_ITEM_NETHER_QUARTZ, DropMult); case E_BLOCK_CLAY: return cItem(E_ITEM_CLAY, 4); default: { return cItem(m_BlockType); } } } virtual void OnBroken( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, Vector3i a_BlockPos, BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta, const cEntity * a_Digger ) const override { if (a_Digger == nullptr) { return; } if (!a_Digger->IsPlayer()) { return; } const auto Player = static_cast(a_Digger); if (!Player->IsGameModeSurvival()) { // Don't drop XP unless the player is in survival mode. return; } if (Player->GetEquippedItem().m_Enchantments.GetLevel(cEnchantments::enchSilkTouch) != 0) { // Don't drop XP when the ore is mined with the Silk Touch enchantment return; } if (!Player->GetEquippedItem().GetHandler().CanHarvestBlock(m_BlockType)) { return; } auto & Random = GetRandomProvider(); int Reward = 0; switch (a_OldBlockType) { case E_BLOCK_NETHER_QUARTZ_ORE: case E_BLOCK_LAPIS_ORE: { // Lapis and nether quartz get 2 - 5 experience Reward = Random.RandInt(2, 5); break; } case E_BLOCK_REDSTONE_ORE: case E_BLOCK_REDSTONE_ORE_GLOWING: { // Redstone gets 1 - 5 experience Reward = Random.RandInt(1, 5); break; } case E_BLOCK_DIAMOND_ORE: case E_BLOCK_EMERALD_ORE: { // Diamond and emerald get 3 - 7 experience Reward = Random.RandInt(3, 7); break; } case E_BLOCK_COAL_ORE: { // Coal gets 0 - 2 experience Reward = Random.RandInt(2); break; } default: break; } if (Reward > 0) { a_WorldInterface.SpawnSplitExperienceOrbs(Vector3d(0.5, 0.5, 0.5) + a_BlockPos, Reward); } } } ; class cDefaultOreHandler final : public cBlockOreHandler { public: using cBlockOreHandler::cBlockOreHandler; }; ================================================ FILE: src/Blocks/BlockPackedIce.h ================================================ #pragma once #include "BlockHandler.h" class cBlockPackedIceHandler final : public cBlockHandler { using Super = cBlockHandler; public: using Super::Super; private: virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override { // Only drop self when using silk-touch: if (ToolHasSilkTouch(a_Tool)) { return cItem(m_BlockType); } return {}; } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 5; } } ; ================================================ FILE: src/Blocks/BlockPiston.cpp ================================================ #include "Globals.h" #include "BlockPiston.h" #include "../BlockInfo.h" #include "../Item.h" #include "../World.h" #include "../Entities/Player.h" #include "../BlockInServerPluginInterface.h" #include "ChunkInterface.h" #define PISTON_MAX_PUSH_DISTANCE 12 Vector3i cBlockPistonHandler::MetadataToOffset(NIBBLETYPE a_PistonMeta) { switch (a_PistonMeta & 0x07) { case 0: return Vector3i( 0, -1, 0); case 1: return Vector3i( 0, 1, 0); case 2: return Vector3i( 0, 0, -1); case 3: return Vector3i( 0, 0, 1); case 4: return Vector3i(-1, 0, 0); case 5: return Vector3i( 1, 0, 0); default: { LOGWARNING("%s: invalid direction %d, ignoring", __FUNCTION__, a_PistonMeta & 0x07); ASSERT(!"Invalid direction"); return Vector3i(); } } } void cBlockPistonHandler::ExtendPiston(Vector3i a_BlockPos, cWorld & a_World) { { // Broadcast block action first. Will do nothing if piston cannot in fact push BLOCKTYPE pistonBlock; NIBBLETYPE pistonMeta; if (a_World.GetBlockTypeMeta(a_BlockPos, pistonBlock, pistonMeta)) { a_World.BroadcastBlockAction( a_BlockPos, PistonExtendAction, pistonMeta, pistonBlock ); } } // Client expects the server to "play" the animation before setting the final blocks // However, we don't confuse animation with the underlying state of the world, so emulate by delaying 1 tick // (Probably why vanilla has so many dupe glitches with sand and pistons lolol) a_World.ScheduleTask(1_tick, [a_BlockPos](cWorld & World) { BLOCKTYPE pistonBlock; NIBBLETYPE pistonMeta; if ( !World.GetBlockTypeMeta(a_BlockPos, pistonBlock, pistonMeta) || ((pistonBlock != E_BLOCK_PISTON) && !IsSticky(pistonBlock)) ) { // Ensure we operate on a piston to avoid spurious behaviour // Note that the scheduled task may result in the block type of a_BlockPos changing return; } if (IsExtended(pistonMeta)) { // Already extended, bail out return; } Vector3i pushDir = MetadataToOffset(pistonMeta); Vector3iSet blocksPushed; if (!CanPushBlock(a_BlockPos + pushDir, World, true, blocksPushed, pushDir)) { // Can't push anything, bail out return; } PushBlocks(blocksPushed, World, pushDir); // Set the extension and the piston base correctly Vector3i extensionPos = a_BlockPos + pushDir; World.SetBlock(a_BlockPos, pistonBlock, pistonMeta | 0x8); World.SetBlock(extensionPos, E_BLOCK_PISTON_EXTENSION, pistonMeta | (IsSticky(pistonBlock) ? 8 : 0)); // Play sound effect only if extended successfully World.BroadcastSoundEffect("block.piston.extend", a_BlockPos, 0.5f, 0.7f); } ); } void cBlockPistonHandler::RetractPiston(Vector3i a_BlockPos, cWorld & a_World) { { BLOCKTYPE pistonBlock; NIBBLETYPE pistonMeta; if (a_World.GetBlockTypeMeta(a_BlockPos, pistonBlock, pistonMeta)) { a_World.BroadcastBlockAction( a_BlockPos, PistonRetractAction, pistonMeta, pistonBlock ); } } a_World.ScheduleTask(1_tick, [a_BlockPos](cWorld & World) { BLOCKTYPE pistonBlock; NIBBLETYPE pistonMeta; if ( !World.GetBlockTypeMeta(a_BlockPos, pistonBlock, pistonMeta) || ((pistonBlock != E_BLOCK_PISTON) && !IsSticky(pistonBlock)) ) { // Ensure we operate on a piston to avoid spurious behaviour // Note that the scheduled task may result in the block type of a_BlockPos changing return; } if (!IsExtended(pistonMeta)) { // Already retracted, bail out return; } Vector3i pushDir = MetadataToOffset(pistonMeta); // Check the extension: Vector3i extensionPos = a_BlockPos + pushDir; if (World.GetBlock(extensionPos) != E_BLOCK_PISTON_EXTENSION) { LOGD("%s: Piston without an extension - still extending, or just in an invalid state?", __FUNCTION__); return; } // Remove extension, update base state: World.SetBlock(extensionPos, E_BLOCK_AIR, 0); World.SetBlock(a_BlockPos, pistonBlock, pistonMeta & ~(8)); // (Retraction is always successful, but play in the task for consistency) World.BroadcastSoundEffect("block.piston.contract", a_BlockPos, 0.5f, 0.7f); if (!IsSticky(pistonBlock)) { // No need for block pulling, bail out return; } // Get the block to pull Vector3i AdjustedPosition = a_BlockPos + pushDir * 2; // Try to "push" the pulling block in the opposite direction pushDir *= -1; Vector3iSet pushedBlocks; if (!CanPushBlock(AdjustedPosition, World, false, pushedBlocks, pushDir)) { // Not pushable, bail out return; } PushBlocks(pushedBlocks, World, pushDir); } ); } void cBlockPistonHandler::PushBlocks( const Vector3iSet & a_BlocksToPush, cWorld & a_World, const Vector3i & a_PushDir ) { // Sort blocks to move the blocks first, which are farthest away from the piston // This prevents the overwriting of existing blocks std::vector sortedBlocks(a_BlocksToPush.begin(), a_BlocksToPush.end()); std::sort(sortedBlocks.begin(), sortedBlocks.end(), [a_PushDir](const Vector3i & a, const Vector3i & b) { return (a.Dot(a_PushDir) > b.Dot(a_PushDir)); }); // Move every block BLOCKTYPE moveBlock; NIBBLETYPE moveMeta; for (auto & moveBlockPos : sortedBlocks) { if (a_World.GetBlockTypeMeta(moveBlockPos, moveBlock, moveMeta)) { if (cBlockInfo::IsPistonBreakable(moveBlock)) { // Block is breakable, drop it: a_World.DropBlockAsPickups(moveBlockPos, nullptr, nullptr); } else { // Not breakable, just move it a_World.SetBlock(moveBlockPos, E_BLOCK_AIR, 0); moveBlockPos += a_PushDir; a_World.SetBlock(moveBlockPos, moveBlock, moveMeta); } } } } bool cBlockPistonHandler::CanPushBlock( const Vector3i & a_BlockPos, cWorld & a_World, bool a_RequirePushable, Vector3iSet & a_BlocksPushed, const Vector3i & a_PushDir ) { if (!cChunkDef::IsValidHeight(a_BlockPos)) { // Can't push a void block. return false; } const static std::array pushingDirs = { { Vector3i(-1, 0, 0), Vector3i(1, 0, 0), Vector3i( 0, -1, 0), Vector3i(0, 1, 0), Vector3i( 0, 0, -1), Vector3i(0, 0, 1) } }; BLOCKTYPE currBlock; NIBBLETYPE currMeta; if (!a_World.GetBlockTypeMeta(a_BlockPos, currBlock, currMeta)) { return !a_RequirePushable; } if (currBlock == E_BLOCK_AIR) { // Air can be pushed return true; } if (!a_RequirePushable && cBlockInfo::IsPistonBreakable(currBlock)) { // Block should not be broken, when it's not in the pushing direction return true; } if (!CanPush(currBlock, currMeta)) { // When it's not required to push this block, don't fail return !a_RequirePushable; } if (a_BlocksPushed.size() >= PISTON_MAX_PUSH_DISTANCE) { // Do not allow to push too much blocks return false; } if (!a_BlocksPushed.insert(a_BlockPos).second || cBlockInfo::IsPistonBreakable(currBlock)) { return true; // Element exist already } if (currBlock == E_BLOCK_SLIME_BLOCK) { // Try to push the other directions for (const auto & testDir : pushingDirs) { if (!CanPushBlock(a_BlockPos + testDir, a_World, false, a_BlocksPushed, a_PushDir)) { // When it's not possible for a direction, then fail return false; } } } // Try to push the block in front of this block return CanPushBlock(a_BlockPos + a_PushDir, a_World, true, a_BlocksPushed, a_PushDir); } void cBlockPistonHandler::OnBroken( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, Vector3i a_BlockPos, BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta, const cEntity * a_Digger ) const { UNUSED(a_Digger); if (!IsExtended(a_OldBlockMeta)) { return; } const auto Extension = a_BlockPos + MetadataToOffset(a_OldBlockMeta); if ( cChunkDef::IsValidHeight(Extension) && (a_ChunkInterface.GetBlock(Extension) == E_BLOCK_PISTON_EXTENSION) ) { // If the piston is extended, destroy the extension as well: a_ChunkInterface.SetBlock(Extension, E_BLOCK_AIR, 0); } } //////////////////////////////////////////////////////////////////////////////// // cBlockPistonHeadHandler: void cBlockPistonHeadHandler::OnBroken( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, Vector3i a_BlockPos, BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta, const cEntity * a_Digger ) const { UNUSED(a_Digger); const auto Base = a_BlockPos - cBlockPistonHandler::MetadataToOffset(a_OldBlockMeta); if (!cChunkDef::IsValidHeight(Base)) { return; } const auto Block = a_ChunkInterface.GetBlock(Base); if ((Block == E_BLOCK_PISTON) || (Block == E_BLOCK_STICKY_PISTON)) { // Remove the base of the piston: a_ChunkInterface.SetBlock(Base, E_BLOCK_AIR, 0); } } cItems cBlockPistonHeadHandler::ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const { // Give a normal\sticky piston base, not piston extension // With 1.7, the item forms of these technical blocks have been removed, so giving someone this will crash their client... return { cItem(((a_BlockMeta & 0x8) == 0x8) ? E_BLOCK_STICKY_PISTON : E_BLOCK_PISTON) }; } ================================================ FILE: src/Blocks/BlockPiston.h ================================================ #pragma once #include "BlockHandler.h" #include "Mixins/Mixins.h" #include "../Item.h" // fwd: class cWorld; class cBlockPistonHandler final : public cClearMetaOnDrop> { using Super = cClearMetaOnDrop>; public: using Super::Super; static eBlockFace MetaDataToDirection(NIBBLETYPE a_MetaData) { switch (a_MetaData & 0x7) // We only want the bottom three bits (4th controls extended-ness)) { case 0x0: return BLOCK_FACE_YM; case 0x1: return BLOCK_FACE_YP; case 0x2: return BLOCK_FACE_ZM; case 0x3: return BLOCK_FACE_ZP; case 0x4: return BLOCK_FACE_XM; case 0x5: return BLOCK_FACE_XP; default: { ASSERT(!"Invalid Metadata"); return BLOCK_FACE_NONE; } } } /** Converts piston block's metadata into a unit vector representing the direction in which the piston will extend. */ static Vector3i MetadataToOffset(NIBBLETYPE a_PistonMeta); static void ExtendPiston(Vector3i a_BlockPos, cWorld & a_World); static void RetractPiston(Vector3i a_BlockPos, cWorld & a_World); /** Returns true if the piston (with the specified meta) is extended */ static inline bool IsExtended(NIBBLETYPE a_PistonMeta) { return ((a_PistonMeta & 0x8) != 0x0); } private: typedef std::unordered_set> Vector3iSet; /** Piston extension block action */ static const Byte PistonExtendAction = 0U; /** Piston retraction block action */ static const Byte PistonRetractAction = 1U; /** Returns true if the piston (specified by blocktype) is a sticky piston */ static inline bool IsSticky(BLOCKTYPE a_BlockType) { return (a_BlockType == E_BLOCK_STICKY_PISTON); } /** Returns true if the specified block can be pushed by a piston (and left intact) */ static inline bool CanPush(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) { switch (a_BlockType) { case E_BLOCK_ANVIL: case E_BLOCK_BARRIER: case E_BLOCK_BEACON: case E_BLOCK_BEDROCK: case E_BLOCK_BREWING_STAND: case E_BLOCK_CHAIN_COMMAND_BLOCK: case E_BLOCK_CHEST: case E_BLOCK_COMMAND_BLOCK: case E_BLOCK_DAYLIGHT_SENSOR: case E_BLOCK_DISPENSER: case E_BLOCK_DROPPER: case E_BLOCK_ENCHANTMENT_TABLE: case E_BLOCK_END_GATEWAY: case E_BLOCK_END_PORTAL: case E_BLOCK_END_PORTAL_FRAME: case E_BLOCK_ENDER_CHEST: case E_BLOCK_FURNACE: case E_BLOCK_LIT_FURNACE: case E_BLOCK_INVERTED_DAYLIGHT_SENSOR: case E_BLOCK_HOPPER: case E_BLOCK_JUKEBOX: case E_BLOCK_MOB_SPAWNER: case E_BLOCK_NETHER_PORTAL: case E_BLOCK_NOTE_BLOCK: case E_BLOCK_OBSIDIAN: case E_BLOCK_PISTON_EXTENSION: case E_BLOCK_REPEATING_COMMAND_BLOCK: case E_BLOCK_STANDING_BANNER: case E_BLOCK_STRUCTURE_BLOCK: case E_BLOCK_TRAPPED_CHEST: case E_BLOCK_WALL_BANNER: { return false; } case E_BLOCK_STICKY_PISTON: case E_BLOCK_PISTON: { // A piston can only be pushed if retracted: return !IsExtended(a_BlockMeta); } } return true; } /** Tries to push a block and increases the pushed blocks variable. Returns true if the block is pushable */ static bool CanPushBlock( const Vector3i & a_BlockPos, cWorld & a_World, bool a_RequirePushable, Vector3iSet & a_BlocksPushed, const Vector3i & a_PushDir ); virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 11; } virtual void OnBroken( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, Vector3i a_BlockPos, BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta, const cEntity * a_Digger ) const override; /** Moves a list of blocks in a specific direction */ static void PushBlocks(const Vector3iSet & a_BlocksToPush, cWorld & a_World, const Vector3i & a_PushDir ); } ; class cBlockPistonHeadHandler final : public cBlockHandler { using Super = cBlockHandler; public: constexpr cBlockPistonHeadHandler(void) : Super(E_BLOCK_PISTON_EXTENSION) { } virtual void OnBroken( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, Vector3i a_BlockPos, BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta, const cEntity * a_Digger ) const override; virtual cItems ConvertToPickups(NIBBLETYPE a_BlockMeta, const cItem * a_Tool) const override; } ; ================================================ FILE: src/Blocks/BlockPlanks.h ================================================ #pragma once #include "BlockHandler.h" class cBlockPlanksHandler final : public cBlockHandler { using Super = cBlockHandler; public: using Super::Super; private: virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { switch (a_Meta) { case E_META_PLANKS_BIRCH: return 2; case E_META_PLANKS_JUNGLE: return 10; case E_META_PLANKS_OAK: return 13; case E_META_PLANKS_ACACIA: return 15; case E_META_PLANKS_DARK_OAK: return 26; case E_META_PLANKS_SPRUCE: return 34; default: { ASSERT(!"Unhandled meta in planks handler!"); return 0; } } } } ; ================================================ FILE: src/Blocks/BlockPlant.h ================================================ #pragma once #include "BlockHandler.h" /** Base class for plants that use light values to decide whether to grow or not. On block update, the plant decides whether to grow, die or stay as-is, based on the CanGrow() overridable method result. */ template class cBlockPlant : public cBlockHandler { using Super = cBlockHandler; public: using Super::Super; protected: ~cBlockPlant() = default; /** The action the plant can take on an update. */ enum PlantAction { paDeath, paGrowth, paStay }; /** Checks whether there is enough light for the plant to grow. If the plant doesn't require light to grow, then it returns paGrowth. If the plant requires light to grow and there is enough light, it returns paGrowth. If the plant requires light to grow and there isn't enough light, it returns paStay. If the plant requires light to grow and there is too little light, it returns paDeath. */ static PlantAction HasEnoughLight(cChunk & a_Chunk, Vector3i a_RelPos) { // If the plant requires light to grow, check to see if there is enough light // Otherwise, return true if (!NeedsLightToGrow) { return paGrowth; } NIBBLETYPE Blocklight = a_Chunk.GetBlockLight(a_RelPos); NIBBLETYPE SkyLight = a_Chunk.GetSkyLight (a_RelPos); NIBBLETYPE Light = a_Chunk.GetTimeAlteredLight(SkyLight); // If the amount of light provided by blocks is greater than the sky light, use it instead if (Blocklight > Light) { Light = Blocklight; } // Based on light levels, decide between growth, stay and death: if (Light > 8) { return paGrowth; } else if ((Blocklight < 9) && (SkyLight < 9)) { return paDeath; } return paStay; } /** Checks whether a plant can grow grow, based on what is returned from cBlockPlant::HasEnoughLight and a random check based on what is returned from cBlockPlant::GetGrowthChance. Can return three values. paGrowth when the conditions are right for the plant to grow. paStay when the conditions are not quite right. paDeath is returned when there isn't enough light for the plant to survive. Plants that don't require light will never have a paDeath returned */ virtual PlantAction CanGrow(cChunk & a_Chunk, Vector3i a_RelPos) const { // Plant can grow if it has the required amount of light, and it passes a random chance based on surrounding blocks auto action = HasEnoughLight(a_Chunk, a_RelPos); if ((action == paGrowth) && !GetRandomProvider().RandBool(1.0 / GetGrowthChance(a_Chunk, a_RelPos))) { action = paStay; } return action; } /** Generates an int value between 4 and 25 based on surrounding blocks that affect how quickly the plant grows. The higher the value, the less likely the plant is to grow */ virtual int GetGrowthChance(cChunk & a_Chunk, Vector3i a_RelPos) const { float Chance = 1.0f; a_RelPos.y -= 1; for (int x = -1; x < 2; ++x) { for (int z = -1; z < 2; ++z) { float Adjustment = 0.0f; BLOCKTYPE Block; NIBBLETYPE Meta; // If the chunk we are trying to get the block information from is loaded if (a_Chunk.UnboundedRelGetBlock(a_RelPos + Vector3i(x, 0, z), Block, Meta)) { // If the block affects growth, add to the adjustment if (cBlockHandler::For(Block).CanSustainPlant(m_BlockType)) { Adjustment = 1.0f; // Farmland alters the chance further if it is watered if ((Block == E_BLOCK_FARMLAND) && (Meta != 0)) { Adjustment = 3.0f; } } } // If this is not the block right underneath the plant, it has little effect on the growth if ((x != 0) || (z != 0)) { Adjustment /= 4.0f; } Chance += Adjustment; } } return FloorC(24.0f / Chance) + 1; } private: virtual void OnUpdate( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cBlockPluginInterface & a_PluginInterface, cChunk & a_Chunk, const Vector3i a_RelPos ) const override { auto Action = CanGrow(a_Chunk, a_RelPos); switch (Action) { case paGrowth: { if (Grow(a_Chunk, a_RelPos) == 0) { BearFruit(a_Chunk, a_RelPos); } break; } case paDeath: { a_ChunkInterface.SetBlock(a_Chunk.RelativeToAbsolute(a_RelPos), E_BLOCK_AIR, 0); break; } case paStay: break; // do nothing } } /** Grows the final produce next to the stem at the specified position. */ virtual void BearFruit(cChunk & a_Chunk, const Vector3i a_StemRelPos) const { // Nothing to do by default } }; ================================================ FILE: src/Blocks/BlockPluginInterface.h ================================================ // BlockPluginInterface.h // Declares the cBlockPluginInterface class representing an interface that the blockhandlers and itemhandlers use for calling plugins #pragma once // fwd: class cPlayer; /** This interface is used to decouple block handlers from the cPluginManager dependency through cWorld. The block handlers call this interface, which is then implemented by the specific classes that the caller provides. */ class cBlockPluginInterface { public: virtual ~cBlockPluginInterface() {} virtual bool CallHookBlockSpread(Vector3i a_BlockPos, eSpreadSource a_Source) = 0; virtual bool CallHookPlayerBreakingBlock(cPlayer & a_Player, Vector3i a_BlockPos, eBlockFace a_BlockFace, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) = 0; virtual bool CallHookPlayerBrokenBlock(cPlayer & a_Player, Vector3i a_BlockPos, eBlockFace a_BlockFace, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) = 0; }; ================================================ FILE: src/Blocks/BlockPortal.h ================================================ #pragma once #include "BlockHandler.h" class cBlockPortalHandler final : public cBlockHandler { using Super = cBlockHandler; public: using Super::Super; private: virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override { // No pickups return {}; } virtual void OnUpdate( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cBlockPluginInterface & a_PluginInterface, cChunk & a_Chunk, const Vector3i a_RelPos ) const override { // Spawn zombie pigmen with a 0.05% chance: if (GetRandomProvider().RandBool(0.9995)) { return; } auto WorldPos = a_Chunk.RelativeToAbsolute(a_RelPos); a_WorldInterface.SpawnMob(WorldPos.x, WorldPos.y, WorldPos.z, mtZombiePigman, false); } virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override { if (!cChunkDef::IsValidHeight(a_Position.addedY(-1)) || !cChunkDef::IsValidHeight(a_Position.addedY(1))) { return false; // Must be 1 away from the boundary, there will always be another portal or an obsidian between the portal block and the boundary. } switch (a_Meta) { case 0x1: { static const std::array PortalCheck { { { 0, 1, 0 }, { 0, -1, 0 }, { 1, 0, 0 }, { -1, 0, 0 }, } }; for (const auto & Direction : PortalCheck) { BLOCKTYPE Block; a_Chunk.UnboundedRelGetBlockType(a_Position + Direction, Block); if ((Block != E_BLOCK_NETHER_PORTAL) && (Block != E_BLOCK_OBSIDIAN)) { return false; } } break; } case 0x2: { static const std::array PortalCheck { { { 0, 1, 0 }, { 0, -1, 0 }, { 0, 0, -1 }, { 0, 0, 1 }, } }; for (const auto & Direction : PortalCheck) { BLOCKTYPE Block; a_Chunk.UnboundedRelGetBlockType(a_Position + Direction, Block); if ((Block != E_BLOCK_NETHER_PORTAL) && (Block != E_BLOCK_OBSIDIAN)) { return false; } } break; } } return true; } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 24; } } ; ================================================ FILE: src/Blocks/BlockPressurePlate.h ================================================ #pragma once #include "BlockHandler.h" #include "BlockSlab.h" #include "../Chunk.h" #include "BlockStairs.h" class cBlockPressurePlateHandler final : public cClearMetaOnDrop { using Super = cClearMetaOnDrop; public: using Super::Super; private: virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override { const auto PosBelow = a_Position.addedY(-1); if (!cChunkDef::IsValidHeight(PosBelow)) { return false; } BLOCKTYPE Block; NIBBLETYPE BlockMeta; a_Chunk.GetBlockTypeMeta(PosBelow, Block, BlockMeta); // upside down slabs if (cBlockSlabHandler::IsAnySlabType(Block)) { return BlockMeta & E_META_WOODEN_SLAB_UPSIDE_DOWN; } // upside down stairs if (cBlockStairsHandler::IsAnyStairType(Block)) { return BlockMeta & E_BLOCK_STAIRS_UPSIDE_DOWN; } switch (Block) { case E_BLOCK_ACACIA_FENCE: case E_BLOCK_BIRCH_FENCE: case E_BLOCK_DARK_OAK_FENCE: case E_BLOCK_FENCE: case E_BLOCK_HOPPER: case E_BLOCK_JUNGLE_FENCE: case E_BLOCK_NETHER_BRICK_FENCE: case E_BLOCK_SPRUCE_FENCE: { return true; } default: { return !cBlockInfo::IsTransparent(Block); } } } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); switch (m_BlockType) { case E_BLOCK_STONE_PRESSURE_PLATE: return 11; case E_BLOCK_WOODEN_PRESSURE_PLATE: return 13; case E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE: return 6; case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE: return 30; default: { ASSERT(!"Unhandled blocktype in pressure plate handler!"); return 0; } } } } ; ================================================ FILE: src/Blocks/BlockPumpkin.h ================================================ #pragma once #include "BlockHandler.h" #include "Mixins/Mixins.h" class cBlockPumpkinHandler final : public cClearMetaOnDrop> { using Super = cClearMetaOnDrop>; public: using Super::Super; private: virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 15; } } ; ================================================ FILE: src/Blocks/BlockQuartz.h ================================================ #pragma once #include "BlockHandler.h" class cBlockQuartzHandler final : public cBlockHandler { using Super = cBlockHandler; public: using Super::Super; private: virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 8; } } ; ================================================ FILE: src/Blocks/BlockRail.h ================================================ #pragma once #include "BlockHandler.h" #include "BlockType.h" #include "Mixins/Mixins.h" #include "Mixins/SolidSurfaceUnderneath.h" #include "../BlockInfo.h" #include "../Chunk.h" #include "ChunkDef.h" enum ENUM_PURE { E_PURE_UPDOWN = 0, E_PURE_DOWN = 1, E_PURE_NONE = 2 }; class cBlockRailHandler final : public cSolidSurfaceUnderneath> { using Super = cSolidSurfaceUnderneath>; public: using Super::Super; static NIBBLETYPE FindMeta(cChunkInterface & a_ChunkInterface, Vector3i a_BlockPos, BLOCKTYPE a_RailType) { NIBBLETYPE Meta = 0; char RailsCnt = 0; bool Neighbors[8]; // 0 - EAST, 1 - WEST, 2 - NORTH, 3 - SOUTH, 4 - EAST UP, 5 - WEST UP, 6 - NORTH UP, 7 - SOUTH UP memset(Neighbors, 0, sizeof(Neighbors)); Neighbors[0] = (IsUnstable(a_ChunkInterface, a_BlockPos + Vector3i(1, 0, 0)) || !IsNotConnected(a_ChunkInterface, a_BlockPos, BLOCK_FACE_EAST, E_PURE_DOWN)); Neighbors[1] = (IsUnstable(a_ChunkInterface, a_BlockPos + Vector3i(-1, 0, 0)) || !IsNotConnected(a_ChunkInterface, a_BlockPos, BLOCK_FACE_WEST, E_PURE_DOWN)); Neighbors[2] = (IsUnstable(a_ChunkInterface, a_BlockPos + Vector3i(0, 0, -1)) || !IsNotConnected(a_ChunkInterface, a_BlockPos, BLOCK_FACE_NORTH, E_PURE_DOWN)); Neighbors[3] = (IsUnstable(a_ChunkInterface, a_BlockPos + Vector3i(0, 0, 1)) || !IsNotConnected(a_ChunkInterface, a_BlockPos, BLOCK_FACE_SOUTH, E_PURE_DOWN)); Neighbors[4] = (IsUnstable(a_ChunkInterface, a_BlockPos + Vector3i(1, 1, 0)) || !IsNotConnected(a_ChunkInterface, a_BlockPos + Vector3i(0, 1, 0), BLOCK_FACE_EAST, E_PURE_NONE)); Neighbors[5] = (IsUnstable(a_ChunkInterface, a_BlockPos + Vector3i(-1, 1, 0)) || !IsNotConnected(a_ChunkInterface, a_BlockPos + Vector3i(0, 1, 0), BLOCK_FACE_WEST, E_PURE_NONE)); Neighbors[6] = (IsUnstable(a_ChunkInterface, a_BlockPos + Vector3i(0, 1, -1)) || !IsNotConnected(a_ChunkInterface, a_BlockPos + Vector3i(0, 1, 0), BLOCK_FACE_NORTH, E_PURE_NONE)); Neighbors[7] = (IsUnstable(a_ChunkInterface, a_BlockPos + Vector3i(0, 1, 1)) || !IsNotConnected(a_ChunkInterface, a_BlockPos + Vector3i(0, 1, 0), BLOCK_FACE_SOUTH, E_PURE_NONE)); if (IsUnstable(a_ChunkInterface, a_BlockPos + Vector3i(1, -1, 0)) || !IsNotConnected(a_ChunkInterface, a_BlockPos - Vector3i(0, 1, 0), BLOCK_FACE_EAST)) { Neighbors[0] = true; } if (IsUnstable(a_ChunkInterface, a_BlockPos - Vector3i(1, 1, 0)) || !IsNotConnected(a_ChunkInterface, a_BlockPos - Vector3i(0, 1, 0), BLOCK_FACE_WEST)) { Neighbors[1] = true; } if (IsUnstable(a_ChunkInterface, a_BlockPos - Vector3i(0, 1, 1)) || !IsNotConnected(a_ChunkInterface, a_BlockPos - Vector3i(0, 1, 0), BLOCK_FACE_NORTH)) { Neighbors[2] = true; } if (IsUnstable(a_ChunkInterface, a_BlockPos + Vector3i(0, -1, 1)) || !IsNotConnected(a_ChunkInterface, a_BlockPos - Vector3i(0, 1, 0), BLOCK_FACE_SOUTH)) { Neighbors[3] = true; } for (int i = 0; i < 8; i++) { if (Neighbors[i]) { RailsCnt++; } } if (RailsCnt == 1) { if (Neighbors[7]) { return E_META_RAIL_ASCEND_ZP; } else if (Neighbors[6]) { return E_META_RAIL_ASCEND_ZM; } else if (Neighbors[5]) { return E_META_RAIL_ASCEND_XM; } else if (Neighbors[4]) { return E_META_RAIL_ASCEND_XP; } else if (Neighbors[0] || Neighbors[1]) { return E_META_RAIL_XM_XP; } else if (Neighbors[2] || Neighbors[3]) { return E_META_RAIL_ZM_ZP; } ASSERT(!"Weird neighbor count"); return Meta; } for (int i = 0; i < 4; i++) { if (Neighbors[i + 4]) { Neighbors[i] = true; } } if (RailsCnt > 1) { const bool CanCurve = a_RailType == E_BLOCK_RAIL; if (Neighbors[3] && Neighbors[0] && CanCurve) { return E_META_RAIL_CURVED_ZP_XP; } else if (Neighbors[3] && Neighbors[1] && CanCurve) { return E_META_RAIL_CURVED_ZP_XM; } else if (Neighbors[2] && Neighbors[0] && CanCurve) { return E_META_RAIL_CURVED_ZM_XP; } else if (Neighbors[2] && Neighbors[1] && CanCurve) { return E_META_RAIL_CURVED_ZM_XM; } else if (Neighbors[7] && Neighbors[2]) { return E_META_RAIL_ASCEND_ZP; } else if (Neighbors[3] && Neighbors[6]) { return E_META_RAIL_ASCEND_ZM; } else if (Neighbors[5] && Neighbors[0]) { return E_META_RAIL_ASCEND_XM; } else if (Neighbors[4] && Neighbors[1]) { return E_META_RAIL_ASCEND_XP; } else if (Neighbors[0] && Neighbors[1]) { return E_META_RAIL_XM_XP; } else if (Neighbors[2] && Neighbors[3]) { return E_META_RAIL_ZM_ZP; } if (CanCurve) { ASSERT(!"Weird neighbor count"); } } return Meta; } private: virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, NIBBLETYPE a_Meta) const override { if (!Super::CanBeAt(a_Chunk, a_Position, a_Meta)) { return false; } switch (a_Meta) { case E_META_RAIL_ASCEND_XP: case E_META_RAIL_ASCEND_XM: case E_META_RAIL_ASCEND_ZM: case E_META_RAIL_ASCEND_ZP: { // Mapping between the meta and the neighbors that need checking a_Meta -= E_META_RAIL_ASCEND_XP; // Base index at zero static const Vector3i Coords[] = { { 1, 0, 0}, // east, XP {-1, 0, 0}, // west, XM { 0, 0, -1}, // north, ZM { 0, 0, 1}, // south, ZP } ; BLOCKTYPE BlockType; NIBBLETYPE BlockMeta; if (!a_Chunk.UnboundedRelGetBlock(a_Position + Coords[a_Meta], BlockType, BlockMeta)) { // Too close to the edge, cannot simulate return true; } return cBlockInfo::FullyOccupiesVoxel(BlockType); } } return true; } static bool IsUnstable(cChunkInterface & a_ChunkInterface, Vector3i a_Pos) { if (!IsBlockRail(a_ChunkInterface.GetBlock(a_Pos))) { return false; } NIBBLETYPE Meta = a_ChunkInterface.GetBlockMeta(a_Pos); switch (Meta) { case E_META_RAIL_ZM_ZP: { if ( IsNotConnected(a_ChunkInterface, a_Pos, BLOCK_FACE_NORTH, E_PURE_DOWN) || IsNotConnected(a_ChunkInterface, a_Pos, BLOCK_FACE_SOUTH, E_PURE_DOWN) ) { return true; } break; } case E_META_RAIL_XM_XP: { if ( IsNotConnected(a_ChunkInterface, a_Pos, BLOCK_FACE_EAST, E_PURE_DOWN) || IsNotConnected(a_ChunkInterface, a_Pos, BLOCK_FACE_WEST, E_PURE_DOWN) ) { return true; } break; } case E_META_RAIL_ASCEND_XP: { if ( IsNotConnected(a_ChunkInterface, a_Pos + Vector3i(0, 1, 0), BLOCK_FACE_EAST) || IsNotConnected(a_ChunkInterface, a_Pos, BLOCK_FACE_WEST) ) { return true; } break; } case E_META_RAIL_ASCEND_XM: { if ( IsNotConnected(a_ChunkInterface, a_Pos, BLOCK_FACE_EAST) || IsNotConnected(a_ChunkInterface, a_Pos + Vector3i(0, 1, 0), BLOCK_FACE_WEST) ) { return true; } break; } case E_META_RAIL_ASCEND_ZM: { if ( IsNotConnected(a_ChunkInterface, a_Pos + Vector3i(0, 1, 0), BLOCK_FACE_NORTH) || IsNotConnected(a_ChunkInterface, a_Pos, BLOCK_FACE_SOUTH) ) { return true; } break; } case E_META_RAIL_ASCEND_ZP: { if ( IsNotConnected(a_ChunkInterface, a_Pos, BLOCK_FACE_NORTH) || IsNotConnected(a_ChunkInterface, a_Pos + Vector3i(0, 1, 0), BLOCK_FACE_SOUTH) ) { return true; } break; } case E_META_RAIL_CURVED_ZP_XP: { if ( IsNotConnected(a_ChunkInterface, a_Pos, BLOCK_FACE_SOUTH) || IsNotConnected(a_ChunkInterface, a_Pos, BLOCK_FACE_EAST) ) { return true; } break; } case E_META_RAIL_CURVED_ZP_XM: { if ( IsNotConnected(a_ChunkInterface, a_Pos, BLOCK_FACE_SOUTH) || IsNotConnected(a_ChunkInterface, a_Pos, BLOCK_FACE_WEST) ) { return true; } break; } case E_META_RAIL_CURVED_ZM_XM: { if ( IsNotConnected(a_ChunkInterface, a_Pos, BLOCK_FACE_NORTH) || IsNotConnected(a_ChunkInterface, a_Pos, BLOCK_FACE_WEST) ) { return true; } break; } case E_META_RAIL_CURVED_ZM_XP: { if ( IsNotConnected(a_ChunkInterface, a_Pos, BLOCK_FACE_NORTH) || IsNotConnected(a_ChunkInterface, a_Pos, BLOCK_FACE_EAST) ) { return true; } break; } } return false; } static bool IsNotConnected(cChunkInterface & a_ChunkInterface, Vector3i a_Pos, eBlockFace a_BlockFace, char a_Pure = 0) { a_Pos = AddFaceDirection(a_Pos, a_BlockFace, false); NIBBLETYPE Meta; if (!IsBlockRail(a_ChunkInterface.GetBlock(a_Pos))) { if (!IsBlockRail(a_ChunkInterface.GetBlock(a_Pos + Vector3i(0, 1, 0))) || (a_Pure != E_PURE_UPDOWN)) { if (!IsBlockRail(a_ChunkInterface.GetBlock(a_Pos - Vector3i(0, 1, 0))) || (a_Pure == E_PURE_NONE)) { return true; } else { Meta = a_ChunkInterface.GetBlockMeta(a_Pos - Vector3i(0, 1, 0)); } } else { Meta = a_ChunkInterface.GetBlockMeta(a_Pos + Vector3i(0, 1, 0)); } } else { Meta = a_ChunkInterface.GetBlockMeta(a_Pos); } switch (a_BlockFace) { case BLOCK_FACE_NORTH: { if ( (Meta == E_META_RAIL_ZM_ZP) || (Meta == E_META_RAIL_ASCEND_ZM) || (Meta == E_META_RAIL_ASCEND_ZP) || (Meta == E_META_RAIL_CURVED_ZP_XP) || (Meta == E_META_RAIL_CURVED_ZP_XM) ) { return false; } break; } case BLOCK_FACE_SOUTH: { if ( (Meta == E_META_RAIL_ZM_ZP) || (Meta == E_META_RAIL_ASCEND_ZM) || (Meta == E_META_RAIL_ASCEND_ZP) || (Meta == E_META_RAIL_CURVED_ZM_XP) || (Meta == E_META_RAIL_CURVED_ZM_XM) ) { return false; } break; } case BLOCK_FACE_EAST: { if ( (Meta == E_META_RAIL_XM_XP) || (Meta == E_META_RAIL_ASCEND_XP) || (Meta == E_META_RAIL_ASCEND_XM) || (Meta == E_META_RAIL_CURVED_ZP_XM) || (Meta == E_META_RAIL_CURVED_ZM_XM) ) { return false; } break; } case BLOCK_FACE_WEST: { if ( (Meta == E_META_RAIL_XM_XP) || (Meta == E_META_RAIL_ASCEND_XP) || (Meta == E_META_RAIL_ASCEND_XM) || (Meta == E_META_RAIL_CURVED_ZP_XP) || (Meta == E_META_RAIL_CURVED_ZM_XP) ) { return false; } break; } case BLOCK_FACE_NONE: case BLOCK_FACE_YM: case BLOCK_FACE_YP: { break; } } return true; } virtual void OnBroken( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, Vector3i a_BlockPos, BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta, const cEntity * a_Digger ) const override { Super::OnBroken(a_ChunkInterface, a_WorldInterface, a_BlockPos, a_OldBlockType, a_OldBlockMeta, a_Digger); // Alert diagonal rails: NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 1, 1, 0), BLOCK_FACE_NONE); NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i(-1, 1, 0), BLOCK_FACE_NONE); NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 0, +1, 1), BLOCK_FACE_NONE); NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 0, +1, -1), BLOCK_FACE_NONE); NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 1, -1, 0), BLOCK_FACE_NONE); NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i(-1, -1, 0), BLOCK_FACE_NONE); NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 0, -1, 1), BLOCK_FACE_NONE); NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 0, -1, -1), BLOCK_FACE_NONE); } virtual void OnNeighborChanged(cChunkInterface & a_ChunkInterface, Vector3i a_BlockPos, eBlockFace a_WhichNeighbor) const override { const auto Meta = a_ChunkInterface.GetBlockMeta(a_BlockPos); const auto NewMeta = FindMeta(a_ChunkInterface, a_BlockPos, m_BlockType); if ((Meta != NewMeta) && IsUnstable(a_ChunkInterface, a_BlockPos)) { a_ChunkInterface.FastSetBlock(a_BlockPos, m_BlockType, (m_BlockType == E_BLOCK_RAIL) ? NewMeta : NewMeta | (Meta & 0x08)); } Super::OnNeighborChanged(a_ChunkInterface, a_BlockPos, a_WhichNeighbor); } virtual void OnPlaced( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta ) const override { Super::OnPlaced(a_ChunkInterface, a_WorldInterface, a_BlockPos, a_BlockType, a_BlockMeta); // Alert diagonal rails: NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 1, 1, 0), BLOCK_FACE_NONE); NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i(-1, 1, 0), BLOCK_FACE_NONE); NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 0, +1, 1), BLOCK_FACE_NONE); NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 0, +1, -1), BLOCK_FACE_NONE); NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 1, -1, 0), BLOCK_FACE_NONE); NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i(-1, -1, 0), BLOCK_FACE_NONE); NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 0, -1, 1), BLOCK_FACE_NONE); NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 0, -1, -1), BLOCK_FACE_NONE); } virtual NIBBLETYPE MetaRotateCCW(NIBBLETYPE a_Meta) const override { // Bit 0x08 is a flag when a_Meta is in the range 0x00--0x05 and 0x0A--0x0F. // Bit 0x08 specifies direction when a_Meta is in the range 0x06-0x09. if ((a_Meta < 0x06) || (a_Meta > 0x09)) { // Save powered rail flag. NIBBLETYPE OtherMeta = a_Meta & 0x08; // Rotates according to table; 0x07 == 0111. // Rails can either be flat (North / South) or Ascending (Asc. East) switch (a_Meta & 0x07) { case 0x00: return 0x01 + OtherMeta; // North / South -> East / West case 0x01: return 0x00 + OtherMeta; // East / West -> North / South case 0x02: return 0x04 + OtherMeta; // Asc. East -> Asc. North case 0x04: return 0x03 + OtherMeta; // Asc. North -> Asc. West case 0x03: return 0x05 + OtherMeta; // Asc. West -> Asc. South case 0x05: return 0x02 + OtherMeta; // Asc. South -> Asc. East } } else { switch (a_Meta) { // Corner Directions case 0x06: return 0x09; // Northwest Cnr. -> Southwest Cnr. case 0x07: return 0x06; // Northeast Cnr. -> Northwest Cnr. case 0x08: return 0x07; // Southeast Cnr. -> Northeast Cnr. case 0x09: return 0x08; // Southwest Cnr. -> Southeast Cnr. } } // To avoid a compiler warning; return a_Meta; } virtual NIBBLETYPE MetaRotateCW(NIBBLETYPE a_Meta) const override { // Bit 0x08 is a flag for value in the range 0x00--0x05 and specifies direction for values withint 0x006--0x09. if ((a_Meta < 0x06) || (a_Meta > 0x09)) { // Save powered rail flag. NIBBLETYPE OtherMeta = a_Meta & 0x08; // Rotates according to table; 0x07 == 0111. // Rails can either be flat (North / South) or Ascending (Asc. East) switch (a_Meta & 0x07) { case 0x00: return 0x01 + OtherMeta; // North / South -> East / West case 0x01: return 0x00 + OtherMeta; // East / West -> North / South case 0x02: return 0x05 + OtherMeta; // Asc. East -> Asc. South case 0x05: return 0x03 + OtherMeta; // Asc. South -> Asc. West case 0x03: return 0x04 + OtherMeta; // Asc. West -> Asc. North case 0x04: return 0x02 + OtherMeta; // Asc. North -> Asc. East } } else { switch (a_Meta) { // Corner Directions case 0x06: return 0x07; // Northwest Cnr. -> Northeast Cnr. case 0x07: return 0x08; // Northeast Cnr. -> Southeast Cnr. case 0x08: return 0x09; // Southeast Cnr. -> Southwest Cnr. case 0x09: return 0x06; // Southwest Cnr. -> Northwest Cnr. } } // To avoid a compiler warning; return a_Meta; } virtual NIBBLETYPE MetaMirrorXY(NIBBLETYPE a_Meta) const override { // MirrorXY basically flips the ZP and ZM parts of the meta if (m_BlockType == E_BLOCK_RAIL) { // Basic rails can have curves and thus their meta behaves differently from specialized rails: switch (a_Meta) { case E_META_RAIL_ASCEND_XM: return E_META_RAIL_ASCEND_XM; case E_META_RAIL_ASCEND_XP: return E_META_RAIL_ASCEND_XP; case E_META_RAIL_ASCEND_ZM: return E_META_RAIL_ASCEND_ZP; case E_META_RAIL_ASCEND_ZP: return E_META_RAIL_ASCEND_ZM; case E_META_RAIL_CURVED_ZM_XM: return E_META_RAIL_CURVED_ZP_XM; case E_META_RAIL_CURVED_ZM_XP: return E_META_RAIL_CURVED_ZP_XP; case E_META_RAIL_CURVED_ZP_XM: return E_META_RAIL_CURVED_ZM_XM; case E_META_RAIL_CURVED_ZP_XP: return E_META_RAIL_CURVED_ZM_XP; case E_META_RAIL_XM_XP: return E_META_RAIL_XM_XP; case E_META_RAIL_ZM_ZP: return E_META_RAIL_ZM_ZP; } } else { // Specialized rails don't have curves, instead they use bit 0x08 as a flag NIBBLETYPE flag = a_Meta & 0x08; switch (a_Meta & 0x07) { case E_META_RAIL_ASCEND_XM: return flag | E_META_RAIL_ASCEND_XM; case E_META_RAIL_ASCEND_XP: return flag | E_META_RAIL_ASCEND_XP; case E_META_RAIL_ASCEND_ZM: return flag | E_META_RAIL_ASCEND_ZP; case E_META_RAIL_ASCEND_ZP: return flag | E_META_RAIL_ASCEND_ZM; case E_META_RAIL_XM_XP: return flag | E_META_RAIL_XM_XP; case E_META_RAIL_ZM_ZP: return flag | E_META_RAIL_ZM_ZP; } } ASSERT(!"Unknown rail meta"); return a_Meta; } virtual NIBBLETYPE MetaMirrorYZ(NIBBLETYPE a_Meta) const override { // MirrorYZ basically flips the XP and XM parts of the meta if (m_BlockType == E_BLOCK_RAIL) { // Basic rails can have curves and thus their meta behaves differently from specialized rails: switch (a_Meta) { case E_META_RAIL_ASCEND_XM: return E_META_RAIL_ASCEND_XP; case E_META_RAIL_ASCEND_XP: return E_META_RAIL_ASCEND_XM; case E_META_RAIL_ASCEND_ZM: return E_META_RAIL_ASCEND_ZM; case E_META_RAIL_ASCEND_ZP: return E_META_RAIL_ASCEND_ZP; case E_META_RAIL_CURVED_ZM_XM: return E_META_RAIL_CURVED_ZM_XP; case E_META_RAIL_CURVED_ZM_XP: return E_META_RAIL_CURVED_ZM_XM; case E_META_RAIL_CURVED_ZP_XM: return E_META_RAIL_CURVED_ZP_XP; case E_META_RAIL_CURVED_ZP_XP: return E_META_RAIL_CURVED_ZP_XM; case E_META_RAIL_XM_XP: return E_META_RAIL_XM_XP; case E_META_RAIL_ZM_ZP: return E_META_RAIL_ZM_ZP; } } else { // Specialized rails don't have curves, instead they use bit 0x08 as a flag NIBBLETYPE flag = a_Meta & 0x08; switch (a_Meta & 0x07) { case E_META_RAIL_ASCEND_XM: return flag | E_META_RAIL_ASCEND_XP; case E_META_RAIL_ASCEND_XP: return flag | E_META_RAIL_ASCEND_XM; case E_META_RAIL_ASCEND_ZM: return flag | E_META_RAIL_ASCEND_ZM; case E_META_RAIL_ASCEND_ZP: return flag | E_META_RAIL_ASCEND_ZP; case E_META_RAIL_XM_XP: return flag | E_META_RAIL_XM_XP; case E_META_RAIL_ZM_ZP: return flag | E_META_RAIL_ZM_ZP; } } ASSERT(!"Unknown rail meta"); return a_Meta; } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 0; } } ; ================================================ FILE: src/Blocks/BlockRedstoneLamp.h ================================================ #pragma once #include "BlockHandler.h" class cBlockRedstoneLampHandler final : public cBlockHandler { public: using cBlockHandler::cBlockHandler; private: virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override { // Always drop the Off variant: return(cItem(E_BLOCK_REDSTONE_LAMP_OFF, 1, 0)); } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 15; } }; ================================================ FILE: src/Blocks/BlockRedstoneOre.h ================================================ #pragma once #include "BlockHandler.h" #include "BlockOre.h" class cBlockRedstoneOreHandler final : public cBlockOreHandler { using Super = cBlockOreHandler; public: using Super::Super; // Inherit constructor from base virtual bool OnUse( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, const Vector3i a_BlockPos, eBlockFace a_BlockFace, const Vector3i a_CursorPos ) const override { a_ChunkInterface.SetBlock(a_BlockPos, E_BLOCK_REDSTONE_ORE_GLOWING, 0); return false; } virtual void OnDigging( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, const Vector3i a_BlockPos ) const override { a_ChunkInterface.SetBlock(a_BlockPos, E_BLOCK_REDSTONE_ORE_GLOWING, 0); } virtual bool IsUseable() const override { return true; } }; class cBlockGlowingRedstoneOreHandler final : public cBlockOreHandler { using Super = cBlockOreHandler; public: using Super::Super; // Inherit constructor from base virtual void OnUpdate( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cBlockPluginInterface & a_BlockPluginInterface, cChunk & a_Chunk, const Vector3i a_RelPos ) const override { auto BlockPos = a_Chunk.RelativeToAbsolute(a_RelPos); a_ChunkInterface.SetBlock(BlockPos, E_BLOCK_REDSTONE_ORE, 0); } }; ================================================ FILE: src/Blocks/BlockRedstoneRepeater.h ================================================ #pragma once #include "BlockHandler.h" #include "BlockType.h" #include "Mixins/Mixins.h" #include "Mixins/SolidSurfaceUnderneath.h" #include "ChunkInterface.h" #include "../Chunk.h" class cBlockRedstoneRepeaterHandler final : public cSolidSurfaceUnderneath> { using Super = cSolidSurfaceUnderneath>; public: using Super::Super; inline static Vector3i GetFrontCoordinateOffset(NIBBLETYPE a_Meta) { return -GetRearCoordinateOffset(a_Meta); } inline static Vector3i GetLeftCoordinateOffset(NIBBLETYPE a_Meta) { switch (a_Meta & E_META_REDSTONE_REPEATER_FACING_MASK) // We only want the direction (bottom) bits { case E_META_REDSTONE_REPEATER_FACING_ZM: return { -1, 0, 0 }; case E_META_REDSTONE_REPEATER_FACING_XP: return { 0, 0, -1 }; case E_META_REDSTONE_REPEATER_FACING_ZP: return { 1, 0, 0 }; case E_META_REDSTONE_REPEATER_FACING_XM: return { 0, 0, 1 }; default: { LOGWARNING("%s: Unknown metadata: %d", __FUNCTION__, a_Meta); ASSERT(!"Unknown metadata while determining orientation of repeater!"); return { 0, 0, 0 }; } } } inline static Vector3i GetRearCoordinateOffset(NIBBLETYPE a_Meta) { switch (a_Meta & E_META_REDSTONE_REPEATER_FACING_MASK) // We only want the direction (bottom) bits { case E_META_REDSTONE_REPEATER_FACING_ZM: return { 0, 0, 1 }; case E_META_REDSTONE_REPEATER_FACING_XP: return { -1, 0, 0 }; case E_META_REDSTONE_REPEATER_FACING_ZP: return { 0, 0, -1 }; case E_META_REDSTONE_REPEATER_FACING_XM: return { 1, 0, 0 }; default: { LOGWARNING("%s: Unknown metadata: %d", __FUNCTION__, a_Meta); ASSERT(!"Unknown metadata while determining orientation of repeater!"); return { 0, 0, 0 }; } } } private: virtual bool OnUse( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, const Vector3i a_BlockPos, eBlockFace a_BlockFace, const Vector3i a_CursorPos ) const override { // Increment the delay setting: a_ChunkInterface.SetBlockMeta(a_BlockPos, ((a_ChunkInterface.GetBlockMeta(a_BlockPos) + 0x04) & 0x0f)); return true; } virtual void OnCancelRightClick( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, const Vector3i a_BlockPos, eBlockFace a_BlockFace ) const override { UNUSED(a_ChunkInterface); a_WorldInterface.SendBlockTo(a_BlockPos, a_Player); } virtual bool IsUseable(void) const override { return true; } virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override { return cItem(E_ITEM_REDSTONE_REPEATER, 1, 0); } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 11; } } ; ================================================ FILE: src/Blocks/BlockRedstoneWire.h ================================================ #pragma once #include "BlockHandler.h" #include "Mixins/SolidSurfaceUnderneath.h" class cBlockRedstoneWireHandler final : public cSolidSurfaceUnderneath { using Super = cSolidSurfaceUnderneath; public: using Super::Super; private: virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override { return cItem(E_ITEM_REDSTONE_DUST, 1, 0); } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 0; } } ; ================================================ FILE: src/Blocks/BlockSand.h ================================================ #pragma once #include "BlockHandler.h" class cBlockSandHandler final : public cBlockHandler { public: using cBlockHandler::cBlockHandler; private: virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 2; } }; ================================================ FILE: src/Blocks/BlockSapling.h ================================================ #pragma once #include "BlockHandler.h" #include "../FastRandom.h" #include "Mixins/DirtLikeUnderneath.h" class cBlockSaplingHandler final : public cDirtLikeUnderneath { using Super = cDirtLikeUnderneath; public: using Super::Super; private: virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override { // The low 3 bits store the sapling type; bit 0x08 is the growth timer (not used in pickups) return cItem(m_BlockType, 1, a_BlockMeta & 0x07); } virtual void OnUpdate( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cBlockPluginInterface & a_PluginInterface, cChunk & a_Chunk, const Vector3i a_RelPos ) const override { auto Meta = a_Chunk.GetMeta(a_RelPos); auto Light = std::max(a_Chunk.GetBlockLight(a_RelPos), a_Chunk.GetTimeAlteredLight(a_Chunk.GetSkyLight(a_RelPos))); // Only grow if we have the right amount of light if (Light > 8) { auto & random = GetRandomProvider(); // Only grow if we are in the right growth stage and have the right amount of space around them. if (((Meta & 0x08) != 0) && random.RandBool(0.45) && CanGrowAt(a_Chunk, a_RelPos.x, a_RelPos.y, a_RelPos.z, Meta)) { auto WorldPos = a_Chunk.RelativeToAbsolute(a_RelPos); a_Chunk.GetWorld()->GrowTree(WorldPos); } // Only move to the next growth stage if we haven't gone there yet else if (((Meta & 0x08) == 0) && random.RandBool(0.45)) { a_Chunk.SetMeta(a_RelPos, Meta | 0x08); } } } static bool CanGrowAt(cChunk & a_Chunk, int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_Meta) { a_Meta = a_Meta & 0x07; int CheckHeight = 0; bool LargeTree = false; // Get the height to check against switch (a_Meta) { case E_META_SAPLING_APPLE: { CheckHeight = 5; break; } case E_META_SAPLING_CONIFER: { CheckHeight = 7; if (IsLargeTree(a_Chunk, a_RelX, a_RelY, a_RelZ, a_Meta)) { CheckHeight = 16; LargeTree = true; } break; } case E_META_SAPLING_BIRCH: { CheckHeight = 6; break; } case E_META_SAPLING_JUNGLE: { CheckHeight = 7; if (IsLargeTree(a_Chunk, a_RelX, a_RelY, a_RelZ, a_Meta)) { CheckHeight = 13; LargeTree = true; } break; } // Acacias don't need horizontal clearance case E_META_SAPLING_ACACIA: { if (!IsLargeTree(a_Chunk, a_RelX, a_RelY, a_RelZ, a_Meta)) { return false; } CheckHeight = 7; LargeTree = true; break; } // Dark Oaks don't need horizontal clearance case E_META_SAPLING_DARK_OAK: { if (!IsLargeTree(a_Chunk, a_RelX, a_RelY, a_RelZ, a_Meta)) { return false; } CheckHeight = 7; LargeTree = true; break; } } // We should always get a valid CheckHeight ASSERT(CheckHeight != 0); // Don't grow a tree if we don't have enough space left above it in the chunk if ((a_RelY + CheckHeight) > cChunkDef::Height) { return false; } bool CanGrow = true; // Validate the neighbor blocks. They cannot be solid. BLOCKTYPE check = E_BLOCK_AIR; a_Chunk.UnboundedRelGetBlockType(a_RelX - 1, a_RelY, a_RelZ, check); CanGrow = CanGrow && cBlockInfo::IsTransparent(check); a_Chunk.UnboundedRelGetBlockType(a_RelX + 1, a_RelY, a_RelZ, check); CanGrow = CanGrow && cBlockInfo::IsTransparent(check); a_Chunk.UnboundedRelGetBlockType(a_RelX, a_RelY, a_RelZ - 1, check); CanGrow = CanGrow && cBlockInfo::IsTransparent(check); a_Chunk.UnboundedRelGetBlockType(a_RelX, a_RelY, a_RelZ + 1, check); CanGrow = CanGrow && cBlockInfo::IsTransparent(check); while (CheckHeight && CanGrow) { check = a_Chunk.GetBlock(a_RelX, a_RelY + CheckHeight, a_RelZ); CanGrow = CanGrow && ((check == E_BLOCK_AIR) || (check == E_BLOCK_LEAVES)); // We have to check above the neighboring saplings as well if (LargeTree) { a_Chunk.UnboundedRelGetBlockType(a_RelX + 1, a_RelY + CheckHeight, a_RelZ, check); CanGrow = CanGrow && ((check == E_BLOCK_AIR) || (check == E_BLOCK_LEAVES)); a_Chunk.UnboundedRelGetBlockType(a_RelX, a_RelY + CheckHeight, a_RelZ + 1, check); CanGrow = CanGrow && ((check == E_BLOCK_AIR) || (check == E_BLOCK_LEAVES)); a_Chunk.UnboundedRelGetBlockType(a_RelX + 1, a_RelY + CheckHeight, a_RelZ + 1, check); CanGrow = CanGrow && ((check == E_BLOCK_AIR) || (check == E_BLOCK_LEAVES)); } --CheckHeight; } return CanGrow; } virtual int Grow(cChunk & a_Chunk, Vector3i a_RelPos, int a_NumStages = 1) const override { auto blockMeta = a_Chunk.GetMeta(a_RelPos); auto typeMeta = blockMeta & 0x07; auto growState = blockMeta >> 3; int res = 0; // Try to increase the sapling's growState: if (growState < 1) { ++growState; a_Chunk.FastSetBlock(a_RelPos, m_BlockType, static_cast(growState << 3 | typeMeta)); if (a_NumStages == 1) { // Only asked to grow one stage, which we did. Bail out. return 1; } res = 1; } // The sapling is grown, now it becomes a tree: a_Chunk.GetWorld()->GrowTreeFromSapling(a_Chunk.RelativeToAbsolute(a_RelPos)); return res + 1; } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 7; } static bool IsLargeTree(cChunk & a_Chunk, int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_Meta) { BLOCKTYPE type; NIBBLETYPE meta; bool LargeTree = true; a_Chunk.UnboundedRelGetBlock(a_RelX + 1, a_RelY, a_RelZ, type, meta); LargeTree = LargeTree && (type == E_BLOCK_SAPLING) && ((a_Meta & meta) == a_Meta); a_Chunk.UnboundedRelGetBlock(a_RelX + 1, a_RelY, a_RelZ + 1, type, meta); LargeTree = LargeTree && (type == E_BLOCK_SAPLING) && ((a_Meta & meta) == a_Meta); a_Chunk.UnboundedRelGetBlock(a_RelX, a_RelY, a_RelZ + 1, type, meta); LargeTree = LargeTree && (type == E_BLOCK_SAPLING) && ((a_Meta & meta) == a_Meta); return LargeTree; } } ; ================================================ FILE: src/Blocks/BlockSeaLantern.h ================================================ #pragma once #include "BlockHandler.h" class cBlockSeaLanternHandler final : public cBlockHandler { using Super = cBlockHandler; public: using Super::Super; private: virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override { // Drop self only when using silk-touch: if (ToolHasSilkTouch(a_Tool)) { return cItem(E_BLOCK_SEA_LANTERN); } // Number of crystals to drop, capped at the max amount of 5. const auto DropNum = FortuneDiscreteRandom(2, 3, ToolFortuneLevel(a_Tool), 5); return cItem(E_ITEM_PRISMARINE_CRYSTALS, DropNum); } } ; ================================================ FILE: src/Blocks/BlockSideways.h ================================================ #pragma once #include "BlockHandler.h" /** Handler for blocks that have 3 orientations (hay bale, log), specified by the upper 2 bits in meta. Additionally supports the metadata specifying block sub-type in its lower 2 bits. */ class cBlockSidewaysHandler final : public cBlockHandler { using Super = cBlockHandler; public: using Super::Super; private: virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override { // Reset the orientation part of meta, keep the sub-type part of meta: return cItem(m_BlockType, 1, a_BlockMeta & 0x03); } } ; ================================================ FILE: src/Blocks/BlockSignPost.h ================================================ #pragma once #include "BlockHandler.h" #include "../Chunk.h" class cBlockSignPostHandler final : public cBlockHandler { using Super = cBlockHandler; public: using Super::Super; private: virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override { return cItem(E_ITEM_SIGN, 1, 0); } virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override { const auto BelowPos = a_Position.addedY(-1); if (!cChunkDef::IsValidHeight(BelowPos)) { return false; } BLOCKTYPE Type = a_Chunk.GetBlock(BelowPos); return (Type == E_BLOCK_SIGN_POST) || (Type == E_BLOCK_WALLSIGN) || cBlockInfo::IsSolid(Type); } virtual NIBBLETYPE MetaRotateCW(NIBBLETYPE a_Meta) const override { return (a_Meta + 4) & 0x0f; } virtual NIBBLETYPE MetaRotateCCW(NIBBLETYPE a_Meta) const override { return (a_Meta + 12) & 0x0f; } virtual NIBBLETYPE MetaMirrorXY(NIBBLETYPE a_Meta) const override { // Mirrors signs over the XY plane (North-South Mirroring) // There are 16 meta values which correspond to different directions. // These values are equated to angles on a circle; 0x08 = 180 degrees. return (a_Meta < 0x08) ? (0x08 - a_Meta) : (0x18 - a_Meta); } virtual NIBBLETYPE MetaMirrorYZ(NIBBLETYPE a_Meta) const override { // Mirrors signs over the YZ plane (East-West Mirroring) // There are 16 meta values which correspond to different directions. // These values are equated to angles on a circle; 0x10 = 360 degrees. return 0x0f - a_Meta; } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 13; } } ; ================================================ FILE: src/Blocks/BlockSlab.h ================================================ // BlockSlab.h // Declares cBlockSlabHandler and cBlockDoubleSlabHandler classes #pragma once #include "BlockHandler.h" #include "ChunkInterface.h" #include "../BlockInfo.h" #include "../Entities/Player.h" #include "../BlockInfo.h" class cBlockSlabHandler final : public cBlockHandler { using Super = cBlockHandler; public: using Super::Super; /** Returns true if the specified blocktype is one of the slabs handled by this handler */ static bool IsAnySlabType(BLOCKTYPE a_BlockType) { return ( (a_BlockType == E_BLOCK_WOODEN_SLAB) || (a_BlockType == E_BLOCK_STONE_SLAB) || (a_BlockType == E_BLOCK_RED_SANDSTONE_SLAB) || (a_BlockType == E_BLOCK_PURPUR_SLAB) ); } private: virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override { // Reset the "top half" flag: return cItem(m_BlockType, 1, a_BlockMeta & 0x07); } virtual bool DoesIgnoreBuildCollision(const cWorld & a_World, const cItem & a_HeldItem, const Vector3i a_Position, const NIBBLETYPE a_Meta, const eBlockFace a_ClickedBlockFace, const bool a_ClickedDirectly) const override { /* Double slab combining uses build collision checks to replace single slabs with double slabs in the right conditions. For us to be replaced, the player must be: 1. Placing the same slab material. 2. Placing the same slab sub-kind (and existing slab is single). */ if ((m_BlockType != a_HeldItem.m_ItemType) || ((a_Meta & 0x07) != a_HeldItem.m_ItemDamage)) { return false; } const bool IsTopSlab = (a_Meta & 0x08) == 0x08; const auto CanClickCombine = ((a_ClickedBlockFace == BLOCK_FACE_TOP) && !IsTopSlab) || ((a_ClickedBlockFace == BLOCK_FACE_BOTTOM) && IsTopSlab); /* When the player clicks on us directly, we'll combine if we're a bottom slab and he clicked the top, or vice versa. Clicking on the sides will not combine. However, when indirectly clicked (on the side of another block, that caused placement to go to us) the conditions are exactly the opposite. */ return a_ClickedDirectly ? CanClickCombine : !CanClickCombine; } virtual void OnCancelRightClick( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, const Vector3i a_BlockPos, eBlockFace a_BlockFace ) const override { if ((a_BlockFace == BLOCK_FACE_NONE) || (a_Player.GetEquippedItem().m_ItemType != static_cast(m_BlockType))) { return; } // Sends the slab back to the client. It's to refuse a doubleslab placement. */ a_Player.GetWorld()->SendBlockTo(a_BlockPos, a_Player); } virtual NIBBLETYPE MetaMirrorXZ(NIBBLETYPE a_Meta) const override { // Toggle the 4th bit - up / down: return (a_Meta ^ 0x08); } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { a_Meta &= 0x7; switch (m_BlockType) { case E_BLOCK_STONE_SLAB: { switch (a_Meta) { case E_META_STONE_SLAB_SANDSTONE: return 2; case E_META_STONE_SLAB_PLANKS: return 13; case E_META_STONE_SLAB_STONE_BRICK: case E_META_STONE_SLAB_STONE: case E_META_STONE_SLAB_COBBLESTONE: return 11; case E_META_STONE_SLAB_BRICK: return 28; case E_META_STONE_SLAB_NETHER_BRICK: return 35; case E_META_STONE_SLAB_QUARTZ: return 8; default: { ASSERT(!"Unhandled meta in slab handler!"); return 0; } } } case E_BLOCK_WOODEN_SLAB: { switch (a_Meta) { case E_META_WOODEN_SLAB_BIRCH: return 2; case E_META_WOODEN_SLAB_JUNGLE: return 10; case E_META_WOODEN_SLAB_OAK: return 13; case E_META_WOODEN_SLAB_ACACIA: return 15; case E_META_WOODEN_SLAB_DARK_OAK: return 26; case E_META_WOODEN_SLAB_SPRUCE: return 34; default: { ASSERT(!"Unhandled meta in slab handler!"); return 0; } } } case E_BLOCK_RED_SANDSTONE_SLAB: { return 10; } case E_BLOCK_PURPUR_SLAB: { return 16; } default: { ASSERT(!"Unhandled blocktype in slab handler!"); return 0; } } } virtual bool IsInsideBlock(Vector3d a_Position, const NIBBLETYPE a_BlockMeta) const override { if (a_BlockMeta & 0x08) // top half { return true; } return cBlockHandler::IsInsideBlock(a_Position, a_BlockMeta); } } ; class cBlockDoubleSlabHandler final : public cBlockHandler { using Super = cBlockHandler; public: using Super::Super; private: virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override { BLOCKTYPE Block = GetSingleSlabType(m_BlockType); return cItem(Block, 2, a_BlockMeta & 0x7); } inline static BLOCKTYPE GetSingleSlabType(BLOCKTYPE a_BlockType) { switch (a_BlockType) { case E_BLOCK_DOUBLE_STONE_SLAB: return E_BLOCK_STONE_SLAB; case E_BLOCK_DOUBLE_WOODEN_SLAB: return E_BLOCK_WOODEN_SLAB; case E_BLOCK_DOUBLE_RED_SANDSTONE_SLAB: return E_BLOCK_RED_SANDSTONE_SLAB; case E_BLOCK_PURPUR_DOUBLE_SLAB: return E_BLOCK_PURPUR_SLAB; } ASSERT(!"Unhandled double slab type!"); return a_BlockType; } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { // For doule slabs, the meta values are the same. Only the meaning of the 4th bit changes, but that's ignored in the below handler return cBlockHandler::For(GetSingleSlabType(m_BlockType)).GetMapBaseColourID(a_Meta); } } ; ================================================ FILE: src/Blocks/BlockSlime.h ================================================ #pragma once #include "BlockHandler.h" class cBlockSlimeHandler final : public cClearMetaOnDrop { public: using cClearMetaOnDrop::cClearMetaOnDrop; private: virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 1; } }; ================================================ FILE: src/Blocks/BlockSnow.h ================================================ #pragma once #include "BlockHandler.h" class cBlockSnowHandler final : public cBlockHandler { using Super = cBlockHandler; public: using Super::Super; private: enum { FullBlockMeta = 7 // Meta value of a full-height snow block. }; virtual bool DoesIgnoreBuildCollision(const cWorld & a_World, const cItem & a_HeldItem, const Vector3i a_Position, const NIBBLETYPE a_Meta, const eBlockFace a_ClickedBlockFace, const bool a_ClickedDirectly) const override { if (a_Meta == 0) { return true; // If at normal snowfall height (lowest), we ignore collision. } // Special case if a player is holding a (thin) snow block and its size can be increased: if ((a_HeldItem.m_ItemType == E_BLOCK_SNOW) && (a_Meta < FullBlockMeta)) { return !a_ClickedDirectly || (a_ClickedBlockFace == BLOCK_FACE_YP); // If clicked an adjacent block, or clicked YP directly, we ignore collision. } return false; } virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override { // No drop unless dug up with a shovel: if ((a_Tool == nullptr) || !ItemCategory::IsShovel(a_Tool->m_ItemType)) { return {}; } if (ToolHasSilkTouch(a_Tool)) { return cItem(m_BlockType, 1, 0); } else { // Drop as many snowballs as there were "layers" of snow: return cItem(E_ITEM_SNOWBALL, 1 + (a_BlockMeta & 0x07), 0); } } virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override { const auto BelowPos = a_Position.addedY(-1); if (!cChunkDef::IsValidHeight(BelowPos)) { return false; } auto BlockBelow = a_Chunk.GetBlock(BelowPos); auto MetaBelow = a_Chunk.GetMeta(BelowPos); return CanBeOn(BlockBelow, MetaBelow); } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 14; } virtual bool IsInsideBlock(const Vector3d a_RelPosition, const NIBBLETYPE a_BlockMeta) const override { return a_RelPosition.y < (cBlockInfo::GetBlockHeight(m_BlockType) * (a_BlockMeta & 0x07)); } private: /** Returns true if snow can be placed on top of a block with the given type and meta. */ static bool CanBeOn(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) { // If block below is snowable, or it is a thin snow block and is a full thin snow block, say yay: return ( cBlockInfo::IsSnowable(a_BlockType) || ( (a_BlockType == E_BLOCK_SNOW) && (a_BlockMeta == FullBlockMeta) ) ); } } ; ================================================ FILE: src/Blocks/BlockSponge.h ================================================ #pragma once #include "BlockHandler.h" class cBlockSpongeHandler final : public cBlockHandler { using Super = cBlockHandler; public: using Super::Super; private: virtual void OnPlaced( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta ) const override { OnNeighborChanged(a_ChunkInterface, a_BlockPos, BLOCK_FACE_NONE); } virtual void OnNeighborChanged(cChunkInterface & a_ChunkInterface, Vector3i a_BlockPos, eBlockFace a_WhichNeighbor) const override { a_ChunkInterface.DoWithChunkAt(a_BlockPos, [&](cChunk & a_Chunk) { CheckSoaked(cChunkDef::AbsoluteToRelative(a_BlockPos), a_Chunk); return true; }); } /** Check blocks around the sponge to see if they are water. If a dry sponge is touching water, soak up up to 65 blocks of water, with a taxicab distance of 7, and turn the sponge into a wet sponge. */ static void CheckSoaked(Vector3i a_Rel, cChunk & a_Chunk) { struct sSeed { sSeed(Vector3i pos, int d) { m_Pos = pos; m_Depth = d; } Vector3i m_Pos; int m_Depth; }; // Check if this is a dry sponge next to a water block. NIBBLETYPE TargetMeta = a_Chunk.GetMeta(a_Rel.x, a_Rel.y, a_Rel.z); if (TargetMeta != E_META_SPONGE_DRY) { return; } const auto & WaterCheck = cSimulator::AdjacentOffsets; const bool ShouldSoak = std::any_of(WaterCheck.cbegin(), WaterCheck.cend(), [a_Rel, &a_Chunk](Vector3i a_Offset) { return IsWet(a_Rel + a_Offset, a_Chunk); }); // Early return if the sponge isn't touching any water. if (!ShouldSoak) { return; } // Use a queue to hold blocks that we want to check, so our search is breadth-first. std::queue Seeds; int count = 0; // Only go 7 blocks away from the center block. const int maxDepth = 7; // Start with the 6 blocks around the sponge. for (unsigned int i = 0; i < 6; i++) { Seeds.emplace(a_Rel + WaterCheck[i], maxDepth - 1); } // Keep checking blocks that are touching water blocks, or until 65 have been soaked up. while (!Seeds.empty() && count < 65) { sSeed seed = Seeds.front(); Vector3i checkRel = seed.m_Pos; if (IsWet(checkRel, a_Chunk)) { count++; DryUp(checkRel, a_Chunk); if (seed.m_Depth > 0) { // If this block was water, and we haven't yet gone too far away, // add its neighbors to the queue to check. for (unsigned int i = 0; i < 6; i++) { Seeds.emplace(checkRel + WaterCheck[i], seed.m_Depth - 1); } } } Seeds.pop(); } a_Chunk.SetBlock(a_Rel, E_BLOCK_SPONGE, E_META_SPONGE_WET); } static void DryUp(Vector3i a_Rel, cChunk & a_Chunk) { // TODO: support evaporating waterlogged blocks. a_Chunk.UnboundedRelSetBlock(a_Rel.x, a_Rel.y, a_Rel.z, E_BLOCK_AIR, 0); } static bool IsWet(Vector3i a_Rel, cChunk & a_Chunk) { // TODO: support detecting waterlogged blocks. BLOCKTYPE Type; return(a_Chunk.UnboundedRelGetBlockType(a_Rel.x, a_Rel.y, a_Rel.z, Type) && IsBlockWater(Type)); } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 18; } }; ================================================ FILE: src/Blocks/BlockStairs.h ================================================ #pragma once #include "BlockHandler.h" #include "Mixins/Mixins.h" class cBlockStairsHandler final : public cClearMetaOnDrop> { using Super = cClearMetaOnDrop>; public: using Super::Super; static bool IsAnyStairType(BLOCKTYPE a_Block) { switch (a_Block) { case E_BLOCK_SANDSTONE_STAIRS: case E_BLOCK_BIRCH_WOOD_STAIRS: case E_BLOCK_QUARTZ_STAIRS: case E_BLOCK_JUNGLE_WOOD_STAIRS: case E_BLOCK_RED_SANDSTONE_STAIRS: case E_BLOCK_COBBLESTONE_STAIRS: case E_BLOCK_STONE_BRICK_STAIRS: case E_BLOCK_OAK_WOOD_STAIRS: case E_BLOCK_ACACIA_WOOD_STAIRS: case E_BLOCK_PURPUR_STAIRS: case E_BLOCK_DARK_OAK_WOOD_STAIRS: case E_BLOCK_BRICK_STAIRS: case E_BLOCK_NETHER_BRICK_STAIRS: case E_BLOCK_SPRUCE_WOOD_STAIRS: return true; default: { return false; } } } private: virtual NIBBLETYPE MetaMirrorXZ(NIBBLETYPE a_Meta) const override { // Toggle bit 3: return (a_Meta & 0x0b) | ((~a_Meta) & 0x04); } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); switch (m_BlockType) { case E_BLOCK_SANDSTONE_STAIRS: case E_BLOCK_BIRCH_WOOD_STAIRS: return 2; case E_BLOCK_QUARTZ_STAIRS: return 8; case E_BLOCK_JUNGLE_WOOD_STAIRS: case E_BLOCK_RED_SANDSTONE_STAIRS: return 10; case E_BLOCK_COBBLESTONE_STAIRS: case E_BLOCK_STONE_BRICK_STAIRS: return 11; case E_BLOCK_OAK_WOOD_STAIRS: return 13; case E_BLOCK_ACACIA_WOOD_STAIRS: return 15; case E_BLOCK_PURPUR_STAIRS: return 16; case E_BLOCK_DARK_OAK_WOOD_STAIRS: return 26; case E_BLOCK_BRICK_STAIRS: return 28; case E_BLOCK_NETHER_BRICK_STAIRS: return 35; case E_BLOCK_SPRUCE_WOOD_STAIRS: return 34; default: { ASSERT(!"Unhandled blocktype in stairs handler!"); return 0; } } } /** EXCEPTION a.k.a. why is this removed: This collision-detection is actually more accurate than the client, but since the client itself sends inaccurate / sparse data, it's easier to just err on the side of the client and keep the two in sync by assuming that if a player hit ANY of the stair's bounding cube, it counts as the ground. */ #if 0 bool IsInsideBlock(Vector3d a_RelPosition, const BLOCKTYPE a_BlockType, const NIBBLETYPE a_BlockMeta) { if (a_BlockMeta & 0x4) // upside down { return true; } else if ((a_BlockMeta & 0x3) == 0) // tall side is east (+X) { return (a_RelPosition.y < ((a_RelPosition.x > 0.5) ? 1.0 : 0.5)); } else if ((a_BlockMeta & 0x3) == 1) // tall side is west (-X) { return (a_RelPosition.y < ((a_RelPosition.x < 0.5) ? 1.0 : 0.5)); } else if ((a_BlockMeta & 0x3) == 2) // tall side is south (+Z) { return (a_RelPosition.y < ((a_RelPosition.z > 0.5) ? 1.0 : 0.5)); } else if ((a_BlockMeta & 0x3) == 3) // tall side is north (-Z) { return (a_RelPosition.y < ((a_RelPosition.z < 0.5) ? 1.0 : 0.5)); } return false; } #endif } ; ================================================ FILE: src/Blocks/BlockStandingBanner.h ================================================ // BlockStandingBanner.h #pragma once #include "../BlockInfo.h" #include "BlockEntity.h" #include "Mixins/SolidSurfaceUnderneath.h" class cBlockStandingBannerHandler final : public cSolidSurfaceUnderneath { using Super = cSolidSurfaceUnderneath; public: using Super::Super; virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override { // Drops handled by the block entity: return {}; } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 0; } } ; ================================================ FILE: src/Blocks/BlockStems.h ================================================ #pragma once #include "BlockPlant.h" /** Handler for stems from which produce grows in an adjacent block (melon, pumpkin) after it becomes ripe (meta == 7). ProduceBlockType is the blocktype for the produce to be grown. StemPickupType is the item type for the pickup resulting from breaking the stem. */ template class cBlockStemsHandler final : public cBlockPlant { using Super = cBlockPlant; public: using Super::Super; private: virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override { /* Use correct percent: https://minecraft.wiki/w/Melon_Seeds#Breaking https://minecraft.wiki/w/Pumpkin_Seeds#Breaking */ // Age > 7 (Impossible) if (a_BlockMeta > 7) { return cItem(StemPickupType); } const auto Threshold = GetRandomProvider().RandReal(100); double Cumulative = 0; char Count = 0; for (; Count < 4; Count++) { Cumulative += m_AgeSeedDropProbability[static_cast(a_BlockMeta)][static_cast(Count)]; if (Cumulative > Threshold) { break; } } return cItem(StemPickupType, Count); } virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override { const auto BelowPos = a_Position.addedY(-1); return cChunkDef::IsValidHeight(BelowPos) && (a_Chunk.GetBlock(BelowPos) == E_BLOCK_FARMLAND); } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 7; } virtual int Grow(cChunk & a_Chunk, Vector3i a_RelPos, int a_NumStages = 1) const override { const auto OldMeta = a_Chunk.GetMeta(a_RelPos); const auto NewMeta = std::clamp(static_cast(OldMeta + a_NumStages), 0, 7); a_Chunk.SetMeta(a_RelPos, NewMeta); return NewMeta - OldMeta; } virtual void BearFruit(cChunk & a_Chunk, const Vector3i a_StemRelPos) const override { auto & Random = GetRandomProvider(); // Check if there's another produce around the stem, if so, abort: static constexpr std::array NeighborOfs = { { { 1, 0, 0}, {-1, 0, 0}, { 0, 0, 1}, { 0, 0, -1}, } }; std::array BlockType; if ( !a_Chunk.UnboundedRelGetBlockType(a_StemRelPos + NeighborOfs[0], BlockType[0]) || !a_Chunk.UnboundedRelGetBlockType(a_StemRelPos + NeighborOfs[1], BlockType[1]) || !a_Chunk.UnboundedRelGetBlockType(a_StemRelPos + NeighborOfs[2], BlockType[2]) || !a_Chunk.UnboundedRelGetBlockType(a_StemRelPos + NeighborOfs[3], BlockType[3]) || (BlockType[0] == ProduceBlockType) || (BlockType[1] == ProduceBlockType) || (BlockType[2] == ProduceBlockType) || (BlockType[3] == ProduceBlockType) ) { // Neighbors not valid or already taken by the same produce: return; } // Pick a direction in which to place the produce: int x = 0, z = 0; const auto CheckType = Random.RandInt(3); // The index to the neighbors array which should be checked for emptiness switch (CheckType) { case 0: x = 1; break; case 1: x = -1; break; case 2: z = 1; break; case 3: z = -1; break; } // Check that the block in that direction is empty: switch (BlockType[CheckType]) { case E_BLOCK_AIR: case E_BLOCK_SNOW: case E_BLOCK_TALL_GRASS: case E_BLOCK_DEAD_BUSH: { break; } default: return; } // Check if there's soil under the neighbor. We already know the neighbors are valid. Place produce if ok BLOCKTYPE SoilType; const auto ProduceRelPos = a_StemRelPos + Vector3i(x, 0, z); VERIFY(a_Chunk.UnboundedRelGetBlockType(ProduceRelPos.addedY(-1), SoilType)); switch (SoilType) { case E_BLOCK_DIRT: case E_BLOCK_GRASS: case E_BLOCK_FARMLAND: { const NIBBLETYPE Meta = (ProduceBlockType == E_BLOCK_MELON) ? 0 : static_cast(Random.RandInt(4) % 4); FLOGD("Growing melon / pumpkin at {0} (<{1}, {2}> from stem), overwriting {3}, growing on top of {4}, meta {5}", a_Chunk.RelativeToAbsolute(ProduceRelPos), x, z, ItemTypeToString(BlockType[CheckType]), ItemTypeToString(SoilType), Meta ); // Place a randomly-facing produce: a_Chunk.SetBlock(ProduceRelPos, ProduceBlockType, Meta); } } } private: // https://minecraft.wiki/w/Pumpkin_Seeds#Breaking // https://minecraft.wiki/w/Melon_Seeds#Breaking /** The array describes how many seed may be dropped at which age. The inner arrays describe the probability to drop 0, 1, 2, 3 seeds. The outer describes the age of the stem. */ static constexpr std::array, 8> m_AgeSeedDropProbability { { { 81.3, 17.42, 1.24, 0.03 }, { 65.1, 30.04, 4.62, 0.24 }, { 51.2, 38.4, 9.6, 0.8 }, { 39.44, 43.02, 15.64, 1.9 }, { 29.13, 44.44, 22.22, 3.7 }, { 21.6, 43.2, 28.8, 6.4 }, { 15.17, 39.82, 34.84, 10.16 }, { 10.16, 34.84, 39.82, 15.17 } } }; } ; using cBlockMelonStemHandler = cBlockStemsHandler; using cBlockPumpkinStemHandler = cBlockStemsHandler; ================================================ FILE: src/Blocks/BlockStone.h ================================================ #pragma once #include "BlockHandler.h" class cBlockStoneHandler final : public cBlockHandler { using Super = cBlockHandler; public: using Super::Super; private: virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override { // Convert stone to cobblestone, unless using silk-touch: if ( (a_BlockMeta == E_META_STONE_STONE) && !ToolHasSilkTouch(a_Tool) ) { return cItem(E_BLOCK_COBBLESTONE, 1, 0); } return cItem(m_BlockType, 1, a_BlockMeta); } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 11; } }; ================================================ FILE: src/Blocks/BlockSugarCane.h ================================================ #pragma once #include "BlockPlant.h" class cBlockSugarCaneHandler final : public cBlockPlant { using Super = cBlockPlant; public: using Super::Super; private: virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override { return cItem(E_ITEM_SUGARCANE, 1, 0); } virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override { const auto BelowPos = a_Position.addedY(-1); if (!cChunkDef::IsValidHeight(BelowPos)) { return false; } switch (a_Chunk.GetBlock(BelowPos)) { case E_BLOCK_DIRT: case E_BLOCK_GRASS: case E_BLOCK_FARMLAND: case E_BLOCK_SAND: { static const Vector3i Coords[] = { {-1, 0, 0}, { 1, 0, 0}, { 0, 0, -1}, { 0, 0, 1}, } ; for (size_t i = 0; i < ARRAYCOUNT(Coords); i++) { BLOCKTYPE BlockType; NIBBLETYPE BlockMeta; if (!a_Chunk.UnboundedRelGetBlock(BelowPos + Coords[i], BlockType, BlockMeta)) { // Too close to the edge, cannot simulate return true; } if (IsBlockWater(BlockType) || (BlockType == E_BLOCK_FROSTED_ICE)) { return true; } } // for i - Coords[] // Not directly neighboring a water block return false; } case E_BLOCK_SUGARCANE: { return true; } } return false; } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 7; } virtual int Grow(cChunk & a_Chunk, Vector3i a_RelPos, int a_NumStages = 1) const override { // Check the total height of the sugarcane blocks here: auto top = a_RelPos.addedY(1); while ( cChunkDef::IsValidHeight(top) && (a_Chunk.GetBlock(top) == E_BLOCK_SUGARCANE) ) { ++top.y; } auto bottom = a_RelPos.addedY(-1); while ( cChunkDef::IsValidHeight(bottom) && (a_Chunk.GetBlock(bottom) == E_BLOCK_SUGARCANE) ) { --bottom.y; } // Grow by at most a_NumStages, but no more than max height: auto toGrow = std::min(a_NumStages, a_Chunk.GetWorld()->GetMaxSugarcaneHeight() + 1 - (top.y - bottom.y)); for (int i = 0; i < toGrow; i++) { const auto NewTop = top.addedY(i); if (!cChunkDef::IsValidHeight(NewTop)) { return i; } if (a_Chunk.GetBlock(NewTop) == E_BLOCK_AIR) { a_Chunk.SetBlock(NewTop, E_BLOCK_SUGARCANE, 0); } else { return i; } } // for i return toGrow; } virtual PlantAction CanGrow(cChunk & a_Chunk, Vector3i a_RelPos) const override { // Only allow growing if there's an air block above: if (((a_RelPos.y + 1) < cChunkDef::Height) && (a_Chunk.GetBlock(a_RelPos.addedY(1)) == E_BLOCK_AIR)) { return Super::CanGrow(a_Chunk, a_RelPos); } return paStay; } } ; ================================================ FILE: src/Blocks/BlockTNT.h ================================================ #pragma once #include "BlockHandler.h" class cBlockTNTHandler final : public cBlockHandler { using Super = cBlockHandler; public: using Super::Super; private: virtual void OnCancelRightClick( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, const Vector3i a_BlockPos, eBlockFace a_BlockFace ) const override { a_WorldInterface.SendBlockTo(a_BlockPos, a_Player); } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 4; } }; ================================================ FILE: src/Blocks/BlockTallGrass.h ================================================ #pragma once #include "BlockHandler.h" #include "Mixins/DirtLikeUnderneath.h" #include "ChunkInterface.h" /** Handles the grass that is 1 block tall */ class cBlockTallGrassHandler final : public cDirtLikeUnderneath { using Super = cDirtLikeUnderneath; public: using Super::Super; private: virtual bool DoesIgnoreBuildCollision(const cWorld & a_World, const cItem & a_HeldItem, const Vector3i a_Position, const NIBBLETYPE a_Meta, const eBlockFace a_ClickedBlockFace, const bool a_ClickedDirectly) const override { return true; } virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override { // If using shears, drop self: if ((a_Tool != nullptr) && (a_Tool->m_ItemType == E_ITEM_SHEARS)) { return cItem(m_BlockType, 1, a_BlockMeta); } // Drop seeds, depending on bernoulli trial result: if (GetRandomProvider().RandBool(0.875)) // 87.5% chance of dropping nothing { return {}; } // 12.5% chance of dropping 0 or more seeds. const auto DropNum = FortuneDiscreteRandom(1, 1, 2 * ToolFortuneLevel(a_Tool)); return cItem(E_ITEM_SEEDS, DropNum); } /** Growing a tall grass produces a big flower (2-block high fern or double-tall grass). */ virtual int Grow(cChunk & a_Chunk, Vector3i a_RelPos, int a_NumStages = 1) const override { const auto TopPos = a_RelPos.addedY(1); if (!cChunkDef::IsValidHeight(TopPos)) { return 0; } auto blockMeta = a_Chunk.GetMeta(a_RelPos); NIBBLETYPE largeFlowerMeta; switch (blockMeta) { case E_META_TALL_GRASS_GRASS: largeFlowerMeta = E_META_BIG_FLOWER_DOUBLE_TALL_GRASS; break; case E_META_TALL_GRASS_FERN: largeFlowerMeta = E_META_BIG_FLOWER_LARGE_FERN; break; default: return 0; } a_Chunk.SetBlock(a_RelPos, E_BLOCK_BIG_FLOWER, largeFlowerMeta); a_Chunk.SetBlock(TopPos, E_BLOCK_BIG_FLOWER, E_META_BIG_FLOWER_TOP); return 1; } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 7; } } ; ================================================ FILE: src/Blocks/BlockTorch.h ================================================ #pragma once #include "BlockHandler.h" #include "BlockSlab.h" #include "BlockStairs.h" #include "../Chunk.h" #include "BlockType.h" #include "ChunkInterface.h" #include "Defines.h" #include "Mixins/Mixins.h" class cBlockTorchBaseHandler : public cMetaRotator { using Super = cMetaRotator; public: using Super::Super; /** Returns true if the torch can be placed on the specified block's face. */ static bool CanBePlacedOn(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, eBlockFace a_BlockFace) { // upside down slabs if (cBlockSlabHandler::IsAnySlabType(a_BlockType)) { return (a_BlockFace == BLOCK_FACE_YP) && (a_BlockMeta & E_META_WOODEN_SLAB_UPSIDE_DOWN); } // stairs (top and sides) if (cBlockStairsHandler::IsAnyStairType(a_BlockType)) { switch (a_BlockFace) { case eBlockFace::BLOCK_FACE_YP: return (a_BlockMeta & E_BLOCK_STAIRS_UPSIDE_DOWN); case eBlockFace::BLOCK_FACE_XP: return ((a_BlockMeta & 0b11) == E_BLOCK_STAIRS_XP); case eBlockFace::BLOCK_FACE_XM: return ((a_BlockMeta & 0b11) == E_BLOCK_STAIRS_XM); case eBlockFace::BLOCK_FACE_ZP: return ((a_BlockMeta & 0b11) == E_BLOCK_STAIRS_ZP); case eBlockFace::BLOCK_FACE_ZM: return ((a_BlockMeta & 0b11) == E_BLOCK_STAIRS_ZM); default: { return false; } } } switch (a_BlockType) { case E_BLOCK_END_PORTAL_FRAME: case E_BLOCK_SOULSAND: { // Exceptional vanilla behaviour return true; } case E_BLOCK_GLASS: case E_BLOCK_STAINED_GLASS: case E_BLOCK_FENCE: case E_BLOCK_NETHER_BRICK_FENCE: case E_BLOCK_SPRUCE_FENCE: case E_BLOCK_BIRCH_FENCE: case E_BLOCK_JUNGLE_FENCE: case E_BLOCK_DARK_OAK_FENCE: case E_BLOCK_ACACIA_FENCE: case E_BLOCK_COBBLESTONE_WALL: { // Torches can only be placed on top of these blocks return (a_BlockFace == BLOCK_FACE_YP); } default: { if (cBlockInfo::FullyOccupiesVoxel(a_BlockType)) { // Torches can be placed on all sides of full blocks except the bottom return (a_BlockFace != BLOCK_FACE_YM); } return false; } } } protected: ~cBlockTorchBaseHandler() = default; private: /** Converts the torch block's meta to the block face of the neighbor to which the torch is attached. */ inline static eBlockFace MetaDataToBlockFace(NIBBLETYPE a_MetaData) { switch (a_MetaData) { case 0: return BLOCK_FACE_TOP; // By default, the torches stand on the ground case E_META_TORCH_FLOOR: return BLOCK_FACE_TOP; case E_META_TORCH_EAST: return BLOCK_FACE_EAST; case E_META_TORCH_WEST: return BLOCK_FACE_WEST; case E_META_TORCH_NORTH: return BLOCK_FACE_NORTH; case E_META_TORCH_SOUTH: return BLOCK_FACE_SOUTH; default: { ASSERT(!"Unhandled torch metadata"); break; } } return BLOCK_FACE_TOP; } virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override { auto Face = MetaDataToBlockFace(a_Meta); auto NeighborRelPos = AddFaceDirection(a_Position, Face, true); BLOCKTYPE NeighborBlockType; NIBBLETYPE NeighborBlockMeta; if (!a_Chunk.UnboundedRelGetBlock(NeighborRelPos, NeighborBlockType, NeighborBlockMeta)) { // Neighbor in an unloaded chunk, bail out without changing this. return false; } return CanBePlacedOn(NeighborBlockType, NeighborBlockMeta, Face); } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 0; } } ; class cBlockTorchHandler final : public cClearMetaOnDrop { using Super = cClearMetaOnDrop; public: using Super::Super; }; class cBlockRedstoneTorchHandler final : public cBlockTorchBaseHandler { using Super = cBlockTorchBaseHandler; public: using Super::Super; private: virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override { // Always drop the ON torch, meta 0: return { E_BLOCK_REDSTONE_TORCH_ON }; } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 0; } }; ================================================ FILE: src/Blocks/BlockTrapdoor.h ================================================ #pragma once #include "BlockHandler.h" #include "Mixins/Mixins.h" #include "../EffectID.h" class cBlockTrapdoorHandler final : public cClearMetaOnDrop> { using Super = cClearMetaOnDrop>; public: using Super::Super; private: virtual bool IsUseable(void) const override { return true; } virtual bool OnUse( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, const Vector3i a_BlockPos, eBlockFace a_BlockFace, const Vector3i a_CursorPos ) const override { if (m_BlockType == E_BLOCK_IRON_TRAPDOOR) { // Iron doors can only be toggled by redstone, not by right-clicking return false; } // Flip the ON bit on / off using the XOR bitwise operation NIBBLETYPE Meta = (a_ChunkInterface.GetBlockMeta(a_BlockPos) ^ 0x04); a_ChunkInterface.SetBlockMeta(a_BlockPos, Meta); a_WorldInterface.GetBroadcastManager().BroadcastSoundParticleEffect(EffectID::SFX_RANDOM_FENCE_GATE_OPEN, a_BlockPos, 0, a_Player.GetClientHandle()); return true; } virtual void OnCancelRightClick( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, const Vector3i a_BlockPos, eBlockFace a_BlockFace ) const override { UNUSED(a_ChunkInterface); a_WorldInterface.SendBlockTo(a_BlockPos, a_Player); } inline static eBlockFace BlockMetaDataToBlockFace(NIBBLETYPE a_Meta) { switch (a_Meta & 0x3) { case 0x0: return BLOCK_FACE_ZM; case 0x1: return BLOCK_FACE_ZP; case 0x2: return BLOCK_FACE_XM; case 0x3: return BLOCK_FACE_XP; default: { ASSERT(!"Unhandled block meta!"); return BLOCK_FACE_NONE; } } } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); switch (m_BlockType) { case E_BLOCK_TRAPDOOR: return 13; case E_BLOCK_IRON_TRAPDOOR: return 6; default: { ASSERT(!"Unhandled blocktype in trapdoor handler!"); return 0; } } } }; ================================================ FILE: src/Blocks/BlockTripwire.h ================================================ #pragma once #include "BlockHandler.h" class cBlockTripwireHandler final : public cBlockHandler { using Super = cBlockHandler; public: using Super::Super; private: virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override { return cItem(E_ITEM_STRING, 1, 0); } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 0; } }; ================================================ FILE: src/Blocks/BlockTripwireHook.h ================================================ #pragma once #include "BlockHandler.h" #include "Mixins/Mixins.h" class cBlockTripwireHookHandler final : public cMetaRotator, 0x03, 0x02, 0x03, 0x00, 0x01> { using Super = cMetaRotator, 0x03, 0x02, 0x03, 0x00, 0x01>; public: using Super::Super; inline static eBlockFace MetadataToDirection(NIBBLETYPE a_Meta) { switch (a_Meta & 0x03) { case 0x1: return BLOCK_FACE_XM; case 0x3: return BLOCK_FACE_XP; case 0x2: return BLOCK_FACE_ZM; case 0x0: return BLOCK_FACE_ZP; default: ASSERT(!"Unhandled tripwire hook metadata!"); return BLOCK_FACE_NONE; } } private: virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override { const auto RearPosition = AddFaceDirection(a_Position, MetadataToDirection(a_Meta), true); BLOCKTYPE NeighborBlockType; if (!a_Chunk.UnboundedRelGetBlockType(RearPosition, NeighborBlockType)) { return false; } return cBlockInfo::FullyOccupiesVoxel(NeighborBlockType); } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 0; } }; ================================================ FILE: src/Blocks/BlockVines.h ================================================ #pragma once #include "BlockHandler.h" class cBlockVinesHandler final : public cBlockHandler { using Super = cBlockHandler; public: using Super::Super; private: static const NIBBLETYPE VINE_LOST_SUPPORT = 16; static const NIBBLETYPE VINE_UNCHANGED = 17; virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override { return GetMaxMeta(a_Chunk, a_Position, a_Meta) != VINE_LOST_SUPPORT; } virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override { // Only drops self when using shears, otherwise drops nothing: if ((a_Tool == nullptr) || (a_Tool->m_ItemType != E_ITEM_SHEARS)) { return {}; } return cItem(E_BLOCK_VINES, 1, 0); } static char MetaDataToDirection(NIBBLETYPE a_MetaData) { switch (a_MetaData) { case 0x1: return BLOCK_FACE_NORTH; case 0x4: return BLOCK_FACE_SOUTH; case 0x8: return BLOCK_FACE_WEST; case 0x2: return BLOCK_FACE_EAST; default: return BLOCK_FACE_TOP; } } /** Returns true if the specified block type is good for vines to attach to */ static bool IsBlockAttachable(BLOCKTYPE a_BlockType) { switch (a_BlockType) { case E_BLOCK_CHEST: case E_BLOCK_ENDER_CHEST: case E_BLOCK_GLASS: case E_BLOCK_PISTON: case E_BLOCK_PISTON_EXTENSION: case E_BLOCK_REDSTONE_REPEATER_OFF: case E_BLOCK_REDSTONE_REPEATER_ON: case E_BLOCK_STAINED_GLASS: case E_BLOCK_STICKY_PISTON: case E_BLOCK_TRAPPED_CHEST: { // You can't attach a vine to this solid blocks. return false; } default: { return cBlockInfo::IsSolid(a_BlockType); } } } /** Returns the meta that has the maximum allowable sides of the vine, given the surroundings and current vine meta. Returns special values for a vine that can continue to exist unchanged, or must die completely. */ static NIBBLETYPE GetMaxMeta(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_CurrentMeta) { static const struct { int x, z; NIBBLETYPE Bit; } Coords[] = { { 0, 1, 1}, // south, ZP {-1, 0, 2}, // west, XM { 0, -1, 4}, // north, ZM { 1, 0, 8}, // east, XP } ; NIBBLETYPE MaxMeta = 0; for (auto & Coord : Coords) { BLOCKTYPE BlockType; NIBBLETYPE BlockMeta; auto checkPos = a_Position.addedXZ(Coord.x, Coord.z); if ( a_Chunk.UnboundedRelGetBlock(checkPos.x, checkPos.y, checkPos.z, BlockType, BlockMeta) && IsBlockAttachable(BlockType) ) { MaxMeta |= Coord.Bit; } } // Check if vine above us, add its meta to MaxMeta: const auto AbovePos = a_Position.addedY(1); if (cChunkDef::IsValidHeight(AbovePos) && (a_Chunk.GetBlock(AbovePos) == E_BLOCK_VINES)) { MaxMeta |= a_Chunk.GetMeta(AbovePos); } NIBBLETYPE Common = a_CurrentMeta & MaxMeta; // Neighbors that we have and are legal. if (Common != a_CurrentMeta) { bool HasTop = cChunkDef::IsValidHeight(AbovePos) && IsBlockAttachable(a_Chunk.GetBlock(AbovePos)); if ((Common == 0) && !HasTop) // Meta equals 0 also means top. Make a last-ditch attempt to save the vine. { return VINE_LOST_SUPPORT; } return Common; } return VINE_UNCHANGED; } virtual void OnNeighborChanged(cChunkInterface & a_ChunkInterface, Vector3i a_BlockPos, eBlockFace a_WhichNeighbor) const override { a_ChunkInterface.DoWithChunkAt(a_BlockPos, [&](cChunk & a_Chunk) { const auto Position = cChunkDef::AbsoluteToRelative(a_BlockPos); const auto MaxMeta = GetMaxMeta(a_Chunk, Position, a_Chunk.GetMeta(Position)); if (MaxMeta == VINE_UNCHANGED) { return false; } // There is a neighbor missing, need to update the meta or even destroy the block. if (MaxMeta == VINE_LOST_SUPPORT) { // The vine just lost all its support, destroy the block: a_Chunk.SetBlock(Position, E_BLOCK_AIR, 0); } else { // It lost some of its support, set it to what remains (SetBlock to notify neighbors): a_Chunk.SetBlock(Position, E_BLOCK_VINES, MaxMeta); } return false; }); } virtual bool DoesIgnoreBuildCollision(const cWorld & a_World, const cItem & a_HeldItem, const Vector3i a_Position, const NIBBLETYPE a_Meta, const eBlockFace a_ClickedBlockFace, const bool a_ClickedDirectly) const override { return !a_ClickedDirectly || (a_HeldItem.m_ItemType != m_BlockType); } virtual void OnUpdate( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cBlockPluginInterface & a_PluginInterface, cChunk & a_Chunk, const Vector3i a_RelPos ) const override { UNUSED(a_ChunkInterface); UNUSED(a_WorldInterface); // Vine cannot grow down if at the bottom: auto GrowPos = a_RelPos.addedY(-1); if (!cChunkDef::IsValidHeight(GrowPos)) { return; } // Grow one block down, if possible: BLOCKTYPE Block; a_Chunk.UnboundedRelGetBlockType(GrowPos, Block); if (Block == E_BLOCK_AIR) { auto WorldPos = a_Chunk.RelativeToAbsolute(GrowPos); if (!a_PluginInterface.CallHookBlockSpread(WorldPos, ssVineSpread)) { a_Chunk.UnboundedRelSetBlock(GrowPos, E_BLOCK_VINES, a_Chunk.GetMeta(a_RelPos)); } } } virtual NIBBLETYPE MetaRotateCCW(NIBBLETYPE a_Meta) const override { return ((a_Meta >> 1) | (a_Meta << 3)) & 0x0f; // Rotate bits to the right } virtual NIBBLETYPE MetaRotateCW(NIBBLETYPE a_Meta) const override { return ((a_Meta << 1) | (a_Meta >> 3)) & 0x0f; // Rotate bits to the left } virtual NIBBLETYPE MetaMirrorXY(NIBBLETYPE a_Meta) const override { // Bits 2 and 4 stay, bits 1 and 3 swap return static_cast((a_Meta & 0x0a) | ((a_Meta & 0x01) << 2) | ((a_Meta & 0x04) >> 2)); } virtual NIBBLETYPE MetaMirrorYZ(NIBBLETYPE a_Meta) const override { // Bits 1 and 3 stay, bits 2 and 4 swap return static_cast((a_Meta & 0x05) | ((a_Meta & 0x02) << 2) | ((a_Meta & 0x08) >> 2)); } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 7; } } ; ================================================ FILE: src/Blocks/BlockWallBanner.h ================================================ // BlockWallBanner.h #pragma once #include "../BlockInfo.h" #include "BlockEntity.h" class cBlockWallBannerHandler final : public cBlockEntityHandler { using Super = cBlockEntityHandler; public: using Super::Super; virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override { // Drops handled by the block entity: return {}; } virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override { Vector3i Offset; switch (a_Meta) { case BLOCK_FACE_ZM: Offset = Vector3i( 0, 0, 1); break; case BLOCK_FACE_ZP: Offset = Vector3i( 0, 0, -1); break; case BLOCK_FACE_XM: Offset = Vector3i( 1, 0, 0); break; case BLOCK_FACE_XP: Offset = Vector3i(-1, 0, 0); break; default: return false; } auto NeighborPos = a_Position + Offset; BLOCKTYPE NeighborType; if (!a_Chunk.UnboundedRelGetBlockType(NeighborPos, NeighborType)) { // The neighbour is not accessible (unloaded chunk), we'll allow it for now. return true; } return cBlockInfo::IsSolid(NeighborType); } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 0; } } ; ================================================ FILE: src/Blocks/BlockWallSign.h ================================================ #pragma once #include "BlockHandler.h" #include "../Chunk.h" class cBlockWallSignHandler final : public cBlockHandler { using Super = cBlockHandler; public: using Super::Super; private: virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override { return cItem(E_ITEM_SIGN, 1, 0); } virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override { auto NeighborPos = a_Position + GetOffsetBehindTheSign(a_Meta); BLOCKTYPE NeighborType; if (!a_Chunk.UnboundedRelGetBlockType(NeighborPos, NeighborType)) { // The neighbor is not accessible (unloaded chunk), bail out without changing this return true; } return (NeighborType == E_BLOCK_WALLSIGN) || (NeighborType == E_BLOCK_SIGN_POST) || cBlockInfo::IsSolid(NeighborType); } /** Returns the offset from the sign coords to the block to which the wallsign is attached, based on the wallsign's block meta. Asserts / returns a zero vector on wrong meta. */ static Vector3i GetOffsetBehindTheSign(NIBBLETYPE a_BlockMeta) { switch (a_BlockMeta) { case 2: return Vector3i( 0, 0, 1); case 3: return Vector3i( 0, 0, -1); case 4: return Vector3i( 1, 0, 0); case 5: return Vector3i(-1, 0, 0); } ASSERT(!"Invalid wallsign block meta"); return Vector3i(); } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 13; } } ; ================================================ FILE: src/Blocks/BlockWorkbench.h ================================================ #pragma once #include "BlockHandler.h" #include "../UI/CraftingWindow.h" #include "../Entities/Player.h" class cBlockWorkbenchHandler final : public cBlockHandler { using Super = cBlockHandler; public: using Super::Super; private: virtual bool OnUse( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, const Vector3i a_BlockPos, eBlockFace a_BlockFace, const Vector3i a_CursorPos ) const override { a_Player.GetStatistics().Custom[CustomStatistic::InteractWithCraftingTable]++; cWindow * Window = new cCraftingWindow(); a_Player.OpenWindow(*Window); return true; } virtual bool IsUseable(void) const override { return true; } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); return 13; } } ; ================================================ FILE: src/Blocks/BroadcastInterface.h ================================================ #pragma once #include "../Defines.h" #include "../Scoreboard.h" // fwd: class cClientHandle; class cCompositeChat; class cPlayer; class cWorld; enum class EffectID : Int32; class cBroadcastInterface { public: virtual ~cBroadcastInterface() {} // Broadcast respective packets to all clients of the chunk where the event is taking place // (Please keep these alpha-sorted) virtual void BroadcastAttachEntity (const cEntity & a_Entity, const cEntity & a_Vehicle) = 0; virtual void BroadcastBlockAction (Vector3i a_BlockPos, Byte a_Byte1, Byte a_Byte2, BLOCKTYPE a_BlockType, const cClientHandle * a_Exclude = nullptr) = 0; virtual void BroadcastBlockBreakAnimation (UInt32 a_EntityID, Vector3i a_BlockPos, Int8 a_Stage, const cClientHandle * a_Exclude = nullptr) = 0; virtual void BroadcastBlockEntity (Vector3i a_BlockPos, const cClientHandle * a_Exclude = nullptr) = 0; virtual void BroadcastBossBarUpdateHealth (const cEntity & a_Entity, UInt32 a_UniqueID, float a_FractionFilled) = 0; virtual void BroadcastChat (const AString & a_Message, const cClientHandle * a_Exclude = nullptr, eMessageType a_ChatPrefix = mtCustom) = 0; virtual void BroadcastChatInfo (const AString & a_Message, const cClientHandle * a_Exclude = nullptr) = 0; virtual void BroadcastChatFailure (const AString & a_Message, const cClientHandle * a_Exclude = nullptr) = 0; virtual void BroadcastChatSuccess (const AString & a_Message, const cClientHandle * a_Exclude = nullptr) = 0; virtual void BroadcastChatWarning (const AString & a_Message, const cClientHandle * a_Exclude = nullptr) = 0; virtual void BroadcastChatFatal (const AString & a_Message, const cClientHandle * a_Exclude = nullptr) = 0; virtual void BroadcastChatDeath (const AString & a_Message, const cClientHandle * a_Exclude = nullptr) = 0; virtual void BroadcastChat (const cCompositeChat & a_Message, const cClientHandle * a_Exclude = nullptr) = 0; virtual void BroadcastCollectEntity (const cEntity & a_Collected, const cEntity & a_Collector, unsigned a_Count, const cClientHandle * a_Exclude = nullptr) = 0; virtual void BroadcastDestroyEntity (const cEntity & a_Entity, const cClientHandle * a_Exclude = nullptr) = 0; virtual void BroadcastDetachEntity (const cEntity & a_Entity, const cEntity & a_PreviousVehicle) = 0; virtual void BroadcastEntityEffect (const cEntity & a_Entity, int a_EffectID, int a_Amplifier, int a_Duration, const cClientHandle * a_Exclude = nullptr) = 0; virtual void BroadcastEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item, const cClientHandle * a_Exclude = nullptr) = 0; virtual void BroadcastEntityHeadLook (const cEntity & a_Entity, const cClientHandle * a_Exclude = nullptr) = 0; virtual void BroadcastEntityLook (const cEntity & a_Entity, const cClientHandle * a_Exclude = nullptr) = 0; virtual void BroadcastEntityMetadata (const cEntity & a_Entity, const cClientHandle * a_Exclude = nullptr) = 0; virtual void BroadcastEntityPosition (const cEntity & a_Entity, const cClientHandle * a_Exclude = nullptr) = 0; virtual void BroadcastEntityVelocity (const cEntity & a_Entity, const cClientHandle * a_Exclude = nullptr) = 0; virtual void BroadcastEntityAnimation (const cEntity & a_Entity, EntityAnimation a_Animation, const cClientHandle * a_Exclude = nullptr) = 0; virtual void BroadcastLeashEntity (const cEntity & a_Entity, const cEntity & a_EntityLeashedTo) = 0; virtual void BroadcastParticleEffect (const AString & a_ParticleName, Vector3f a_Src, Vector3f a_Offset, float a_ParticleData, int a_ParticleAmount, const cClientHandle * a_Exclude = nullptr) = 0; virtual void BroadcastParticleEffect (const AString & a_ParticleName, Vector3f a_Src, Vector3f a_Offset, float a_ParticleData, int a_ParticleAmount, std::array a_Data, const cClientHandle * a_Exclude = nullptr) = 0; virtual void BroadcastPlayerListAddPlayer (const cPlayer & a_Player, const cClientHandle * a_Exclude = nullptr) = 0; virtual void BroadcastPlayerListHeaderFooter (const cCompositeChat & a_Header, const cCompositeChat & a_Footer) = 0; virtual void BroadcastPlayerListRemovePlayer (const cPlayer & a_Player, const cClientHandle * a_Exclude = nullptr) = 0; virtual void BroadcastPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_CustomName, const cClientHandle * a_Exclude = nullptr) = 0; virtual void BroadcastPlayerListUpdateGameMode (const cPlayer & a_Player, const cClientHandle * a_Exclude = nullptr) = 0; virtual void BroadcastPlayerListUpdatePing () = 0; virtual void BroadcastRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID, const cClientHandle * a_Exclude = nullptr) = 0; virtual void BroadcastScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) = 0; virtual void BroadcastScoreUpdate (const AString & a_Objective, const AString & a_PlayerName, cObjective::Score a_Score, Byte a_Mode) = 0; virtual void BroadcastDisplayObjective (const AString & a_Objective, cScoreboard::eDisplaySlot a_Display) = 0; virtual void BroadcastSoundEffect (const AString & a_SoundName, Vector3d a_Position, float a_Volume, float a_Pitch, const cClientHandle * a_Exclude = nullptr) = 0; virtual void BroadcastSoundParticleEffect (const EffectID a_EffectID, Vector3i a_SrcPos, int a_Data, const cClientHandle * a_Exclude = nullptr) = 0; virtual void BroadcastSpawnEntity (cEntity & a_Entity, const cClientHandle * a_Exclude = nullptr) = 0; virtual void BroadcastThunderbolt (Vector3i a_BlockPos, const cClientHandle * a_Exclude = nullptr) = 0; virtual void BroadcastTimeUpdate (const cClientHandle * a_Exclude = nullptr) = 0; virtual void BroadcastUnleashEntity (const cEntity & a_Entity) = 0; virtual void BroadcastWeather (eWeather a_Weather, const cClientHandle * a_Exclude = nullptr) = 0; }; ================================================ FILE: src/Blocks/CMakeLists.txt ================================================ target_sources( ${CMAKE_PROJECT_NAME} PRIVATE BlockBed.cpp BlockDoor.cpp BlockHandler.cpp BlockPiston.cpp ChunkInterface.cpp BlockAir.h BlockAnvil.h BlockBed.h BlockBigFlower.h BlockBookShelf.h BlockBrewingStand.h BlockButton.h BlockCactus.h BlockCake.h BlockCarpet.h BlockCauldron.h BlockChest.h BlockCloth.h BlockCobWeb.h BlockCocoaPod.h BlockCommandBlock.h BlockComparator.h BlockConcretePowder.h BlockCrops.h BlockDaylightSensor.h BlockDeadBush.h BlockDefaultBlock.h BlockDirt.h BlockDoor.h BlockDropSpenser.h BlockEnchantingTable.h BlockEnderChest.h BlockEndPortalFrame.h BlockEntity.h BlockFarmland.h BlockFence.h BlockFenceGate.h BlockFire.h BlockFlower.h BlockFlowerPot.h BlockFluid.h BlockFurnace.h BlockGlass.h BlockGlazedTerracotta.h BlockGlowstone.h BlockGrass.h BlockGravel.h BlockHandler.h BlockHopper.h BlockHugeMushroom.h BlockIce.h BlockJukebox.h BlockLadder.h BlockLeaves.h BlockLever.h BlockLilypad.h BlockMelon.h BlockMobHead.h BlockMobSpawner.h BlockInfested.h BlockMushroom.h BlockMycelium.h BlockNetherrack.h BlockNetherWart.h BlockNoteBlock.h BlockObserver.h BlockOre.h BlockPackedIce.h BlockPiston.h BlockPlanks.h BlockPlant.h BlockPluginInterface.h BlockPortal.h BlockPressurePlate.h BlockPumpkin.h BlockQuartz.h BlockRail.h BlockRedstoneWire.h BlockRedstoneLamp.h BlockRedstoneOre.h BlockRedstoneRepeater.h BlockSand.h BlockSapling.h BlockSeaLantern.h BlockSideways.h BlockSignPost.h BlockSlab.h BlockSlime.h BlockSnow.h BlockSponge.h BlockStairs.h BlockStandingBanner.h BlockStems.h BlockStone.h BlockSugarCane.h BlockTNT.h BlockTallGrass.h BlockTorch.h BlockTrapdoor.h BlockTripwire.h BlockTripwireHook.h BlockVines.h BlockWallBanner.h BlockWallSign.h BlockWorkbench.h BroadcastInterface.h ChunkInterface.h GetHandlerCompileTimeTemplate.h Mixins/Mixins.h WorldInterface.h ) ================================================ FILE: src/Blocks/ChunkInterface.cpp ================================================ #include "Globals.h" #include "ChunkInterface.h" #include "BlockHandler.h" #include "WorldInterface.h" #include "../ChunkMap.h" #include "../World.h" bool cChunkInterface::DoWithChunkAt(Vector3i a_BlockPos, cChunkCallback a_Callback) { return m_ChunkMap->DoWithChunkAt(a_BlockPos, a_Callback); } BLOCKTYPE cChunkInterface::GetBlock(Vector3i a_Pos) { return m_ChunkMap->GetBlock(a_Pos); } NIBBLETYPE cChunkInterface::GetBlockMeta(Vector3i a_Pos) { return m_ChunkMap->GetBlockMeta(a_Pos); } bool cChunkInterface::GetBlockTypeMeta(Vector3i a_Pos, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta) { return m_ChunkMap->GetBlockTypeMeta(a_Pos, a_BlockType, a_BlockMeta); } void cChunkInterface::SetBlock(Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) { m_ChunkMap->SetBlock(a_BlockPos, a_BlockType, a_BlockMeta); } void cChunkInterface::SetBlockMeta(Vector3i a_BlockPos, NIBBLETYPE a_MetaData) { m_ChunkMap->SetBlockMeta(a_BlockPos, a_MetaData); } void cChunkInterface::FastSetBlock(Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) { m_ChunkMap->FastSetBlock(a_BlockPos, a_BlockType, a_BlockMeta); } bool cChunkInterface::UseBlockEntity(cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ) { return m_ChunkMap->UseBlockEntity(a_Player, a_BlockX, a_BlockY, a_BlockZ); } bool cChunkInterface::ForEachChunkInRect(int a_MinChunkX, int a_MaxChunkX, int a_MinChunkZ, int a_MaxChunkZ, cChunkDataCallback & a_Callback) { return m_ChunkMap->ForEachChunkInRect(a_MinChunkX, a_MaxChunkX, a_MinChunkZ, a_MaxChunkZ, a_Callback); } bool cChunkInterface::WriteBlockArea(cBlockArea & a_Area, int a_MinBlockX, int a_MinBlockY, int a_MinBlockZ, int a_DataTypes) { return m_ChunkMap->WriteBlockArea(a_Area, a_MinBlockX, a_MinBlockY, a_MinBlockZ, a_DataTypes); } bool cChunkInterface::DigBlock(cWorldInterface & a_WorldInterface, Vector3i a_BlockPos, cEntity * a_Digger) { BLOCKTYPE BlockType; NIBBLETYPE BlockMeta; GetBlockTypeMeta(a_BlockPos, BlockType, BlockMeta); if (!m_ChunkMap->DigBlock(a_BlockPos)) { return false; } cBlockHandler::For(BlockType).OnBroken(*this, a_WorldInterface, a_BlockPos, BlockType, BlockMeta, a_Digger); return true; } void cChunkInterface::DropBlockAsPickups(Vector3i a_BlockPos, const cEntity * a_Digger, const cItem * a_Tool) { m_ChunkMap->GetWorld()->DropBlockAsPickups(a_BlockPos, a_Digger, a_Tool); } ================================================ FILE: src/Blocks/ChunkInterface.h ================================================ #pragma once #include "../ForEachChunkProvider.h" #include "../FunctionRef.h" #include "ChunkDef.h" // fwd: class cItem; class cChunk; class cChunkMap; class cWorldInterface; class cPlayer; class cChunkInterface: public cForEachChunkProvider { public: cChunkInterface(cChunkMap * a_ChunkMap) : m_ChunkMap(a_ChunkMap) {} bool DoWithChunkAt(Vector3i a_BlockPos, cFunctionRef a_Callback); BLOCKTYPE GetBlock(Vector3i a_Pos); NIBBLETYPE GetBlockMeta(Vector3i a_Pos); bool GetBlockTypeMeta(Vector3i a_Pos, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta); /** Sets the block at the specified coords to the specified value. Full processing, incl. updating neighbors, is performed. */ void SetBlock(Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta); /** OBSOLETE, use the Vector3i-based overload instead. Sets the block at the specified coords to the specified value. Full processing, incl. updating neighbors, is performed. */ void SetBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) { return SetBlock({a_BlockX, a_BlockY, a_BlockZ}, a_BlockType, a_BlockMeta); } /** Sets the meta for the specified block, while keeping the blocktype. Ignored if the chunk is invalid. */ void SetBlockMeta(Vector3i a_BlockPos, NIBBLETYPE a_MetaData); /** OBSOLETE, Use the Vector3-based overload instead. Sets the meta for the specified block, while keeping the blocktype. Ignored if the chunk is invalid. */ void SetBlockMeta(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_MetaData) { return SetBlockMeta({a_BlockX, a_BlockY, a_BlockZ}, a_MetaData); } /** Sets the block at the specified coords to the specified value. The replacement doesn't trigger block updates. The replaced blocks aren't checked for block entities (block entity is leaked if it exists at this block). */ void FastSetBlock(Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta); /** Use block entity on coordinate. returns true if the use was successful, return false to use the block as a "normal" block */ bool UseBlockEntity(cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ); virtual bool ForEachChunkInRect(int a_MinChunkX, int a_MaxChunkX, int a_MinChunkZ, int a_MaxChunkZ, cChunkDataCallback & a_Callback) override; virtual bool WriteBlockArea(cBlockArea & a_Area, int a_MinBlockX, int a_MinBlockY, int a_MinBlockZ, int a_DataTypes) override; bool DigBlock(cWorldInterface & a_WorldInterface, Vector3i a_BlockPos, cEntity * a_Digger); /** Digs the block and spawns the relevant pickups, as if a_Digger used a_Tool to dig the block. */ void DropBlockAsPickups(Vector3i a_BlockPos, const cEntity * a_Digger = nullptr, const cItem * a_Tool = nullptr); private: cChunkMap * m_ChunkMap; }; ================================================ FILE: src/Blocks/GetHandlerCompileTimeTemplate.h ================================================ #pragma once class cBlockTorchHandler; class cBlockLeverHandler; class cBlockButtonHandler; class cBlockTripwireHookHandler; class cBlockDoorHandler; class cBlockPistonHandler; template class GetHandlerCompileTime; template<> class GetHandlerCompileTime { public: typedef cBlockTorchHandler type; }; template<> class GetHandlerCompileTime { public: typedef cBlockLeverHandler type; }; template<> class GetHandlerCompileTime { public: typedef cBlockButtonHandler type; }; template<> class GetHandlerCompileTime { public: typedef cBlockTripwireHookHandler type; }; template<> class GetHandlerCompileTime { public: typedef cBlockDoorHandler type; }; template<> class GetHandlerCompileTime { public: typedef cBlockPistonHandler type; }; ================================================ FILE: src/Blocks/Mixins/DirtLikeUnderneath.h ================================================ #pragma once #include "../../Chunk.h" /** Mixin to ensure the block has a dirt-like block underneath. */ template class cDirtLikeUnderneath : public Base { using Super = Base; public: using Super::Super; constexpr cDirtLikeUnderneath(BLOCKTYPE a_BlockType): Base(a_BlockType) { } protected: ~cDirtLikeUnderneath() = default; protected: virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override { if (!Super::CanBeAt(a_Chunk, a_Position, a_Meta)) { return false; } const auto BelowPos = a_Position.addedY(-1); if (!cChunkDef::IsValidHeight(BelowPos)) { return false; } return IsBlockTypeOfDirt(a_Chunk.GetBlock(BelowPos)); } }; ================================================ FILE: src/Blocks/Mixins/Mixins.h ================================================ // Mixins.h // Provides various mixins for easier cBlockHandler descendant implementations /* The general use case is to derive a handler from these mixins, providing a suitable base to them: class cBlockAir: public cBlockWithNoDrops; class cBlockLadder: public cMetaRotator */ #pragma once #include "../../Item.h" // MSVC generates warnings for the templated AssertIfNotMatched parameter conditions, so disable it: #ifdef _MSC_VER #pragma warning(disable: 4127) // Conditional expression is constant #endif /** Mixin to clear the block's meta value when converting to a pickup. */ template class cClearMetaOnDrop : public Base { public: constexpr cClearMetaOnDrop(BLOCKTYPE a_BlockType): Base(a_BlockType) { } protected: ~cClearMetaOnDrop() = default; private: virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override { // Reset the meta to zero: return cItem(this->m_BlockType); } }; /** Mixin for rotations and reflections following the standard pattern of "apply mask, then use a switch". Inherit from this class providing your base class as Base, the BitMask for the direction bits in bitmask and the masked value for the directions in North, East, South, West. There is also an aptional parameter AssertIfNotMatched, set this if it is invalid for a block to exist in any other state. */ template class cMetaRotator : public Base { public: constexpr cMetaRotator(BLOCKTYPE a_BlockType): Base(a_BlockType) { } protected: ~cMetaRotator() = default; virtual NIBBLETYPE MetaRotateCCW(NIBBLETYPE a_Meta) const override { NIBBLETYPE OtherMeta = a_Meta & (~BitMask); switch (a_Meta & BitMask) { case South: return East | OtherMeta; case East: return North | OtherMeta; case North: return West | OtherMeta; case West: return South | OtherMeta; } if (AssertIfNotMatched) { ASSERT(!"Invalid Meta value"); } return a_Meta; } virtual NIBBLETYPE MetaRotateCW(NIBBLETYPE a_Meta) const override { NIBBLETYPE OtherMeta = a_Meta & (~BitMask); switch (a_Meta & BitMask) { case South: return West | OtherMeta; case West: return North | OtherMeta; case North: return East | OtherMeta; case East: return South | OtherMeta; } if (AssertIfNotMatched) { ASSERT(!"Invalid Meta value"); } return a_Meta; } virtual NIBBLETYPE MetaMirrorXY(NIBBLETYPE a_Meta) const override { NIBBLETYPE OtherMeta = a_Meta & (~BitMask); switch (a_Meta & BitMask) { case South: return North | OtherMeta; case North: return South | OtherMeta; } // Not Facing North or South; No change. return a_Meta; } virtual NIBBLETYPE MetaMirrorYZ(NIBBLETYPE a_Meta) const override { NIBBLETYPE OtherMeta = a_Meta & (~BitMask); switch (a_Meta & BitMask) { case West: return East | OtherMeta; case East: return West | OtherMeta; } // Not Facing East or West; No change. return a_Meta; } }; /** Mixin for blocks whose meta on placement depends on the yaw of the player placing the block. BitMask selects the direction bits from the block's meta values. */ template < class Base, NIBBLETYPE BitMask = 0x07, NIBBLETYPE North = 0x02, NIBBLETYPE East = 0x05, NIBBLETYPE South = 0x03, NIBBLETYPE West = 0x04, bool AssertIfNotMatched = false > class cYawRotator : public cMetaRotator { using Super = cMetaRotator; public: using Super::Super; /** Converts the rotation value as returned by cPlayer::GetYaw() to the appropriate metadata value for a block placed by a player facing that way. */ static NIBBLETYPE YawToMetaData(double a_Rotation) { if ((a_Rotation >= -135) && (a_Rotation < -45)) { return East; } else if ((a_Rotation >= -45) && (a_Rotation < 45)) { return South; } else if ((a_Rotation >= 45) && (a_Rotation < 135)) { return West; } else // degrees jumping from 180 to -180 { return North; } } protected: ~cYawRotator() = default; }; /** Mixin for blocks whose meta on placement depends on the relative position of the player to the block in addition to the yaw of the player placing the block. BitMask selects the direction bits from the block's meta values. */ template < class Base, NIBBLETYPE BitMask = 0x07, NIBBLETYPE North = 0x02, NIBBLETYPE East = 0x05, NIBBLETYPE South = 0x03, NIBBLETYPE West = 0x04, NIBBLETYPE Up = 0x00, NIBBLETYPE Down = 0x01 > class cDisplacementYawRotator: public cYawRotator { using Super = cYawRotator; public: using Super::Super; /** Converts the placement position, eye position as returned by cPlayer::GetEyePosition(), and rotation value as returned by cPlayer::GetYaw() to the appropriate metadata value for a block placed by a player facing that way. */ static NIBBLETYPE DisplacementYawToMetaData(const Vector3d a_PlacePosition, const Vector3d a_EyePosition, const double a_Rotation) { if ( const auto Displacement = a_EyePosition - a_PlacePosition.addedXZ(0.5, 0.5); (std::abs(Displacement.x) < 2) && (std::abs(Displacement.z) < 2) ) { if (Displacement.y > 2) { return Up; } if (Displacement.y < 0) { return Down; } } return Super::YawToMetaData(a_Rotation); } protected: ~cDisplacementYawRotator() = default; virtual NIBBLETYPE MetaMirrorXZ(NIBBLETYPE a_Meta) const override { NIBBLETYPE OtherMeta = a_Meta & (~BitMask); switch (a_Meta & BitMask) { case Down: return Up | OtherMeta; // Down -> Up case Up: return Down | OtherMeta; // Up -> Down } // Not Facing Up or Down; No change. return a_Meta; } }; ================================================ FILE: src/Blocks/Mixins/SolidSurfaceUnderneath.h ================================================ #pragma once #include "../../Chunk.h" #include "../BlockSlab.h" #include "../BlockStairs.h" /** Mixin to ensure the block has a solid surface underneath. */ template class cSolidSurfaceUnderneath : public Base { using Super = Base; public: using Super::Super; constexpr cSolidSurfaceUnderneath(BLOCKTYPE a_BlockType): Base(a_BlockType) { } protected: ~cSolidSurfaceUnderneath() = default; protected: virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const override { if (!Super::CanBeAt(a_Chunk, a_Position, a_Meta)) { return false; } const auto BelowPos = a_Position.addedY(-1); if (!cChunkDef::IsValidHeight(BelowPos)) { return false; } BLOCKTYPE BelowBlock; NIBBLETYPE BelowBlockMeta; a_Chunk.GetBlockTypeMeta(BelowPos, BelowBlock, BelowBlockMeta); if (cBlockInfo::FullyOccupiesVoxel(BelowBlock)) { return true; } // upside down slabs if (cBlockSlabHandler::IsAnySlabType(BelowBlock)) { return BelowBlockMeta & E_META_WOODEN_SLAB_UPSIDE_DOWN; } // upside down stairs if (cBlockStairsHandler::IsAnyStairType(BelowBlock)) { return BelowBlockMeta & E_BLOCK_STAIRS_UPSIDE_DOWN; } return false; } }; ================================================ FILE: src/Blocks/WorldInterface.h ================================================ #pragma once #include "../FunctionRef.h" #include "../Mobs/MonsterTypes.h" #include class cBlockEntity; class cBroadcastInterface; class cItems; class cPlayer; using cBlockEntityCallback = cFunctionRef; using cPlayerListCallback = cFunctionRef; using cEntityCallback = cFunctionRef; class cWorldInterface { public: virtual ~cWorldInterface() {} virtual cTickTime GetTimeOfDay(void) const = 0; virtual cTickTimeLong GetWorldAge(void) const = 0; virtual eDimension GetDimension(void) const = 0; virtual cBroadcastInterface & GetBroadcastManager() = 0; virtual void DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_BlockY, double a_BlockZ, bool a_CanCauseFire, eExplosionSource a_Source, void * a_SourceData) = 0; /** Calls the callback for the block entity at the specified coords; returns false if there's no block entity at those coords, true if found */ virtual bool DoWithBlockEntityAt(Vector3i a_Position, cBlockEntityCallback a_Callback) = 0; /** Spawns item pickups for each item in the list. May compress pickups if too many entities: */ virtual void SpawnItemPickups(const cItems & a_Pickups, double a_BlockX, double a_BlockY, double a_BlockZ, double a_FlyAwaySpeed = 1.0, bool IsPlayerCreated = false) = 0; /** Spawns item pickups for each item in the list. May compress pickups if too many entities. All pickups get the speed specified. */ virtual void SpawnItemPickups(const cItems & a_Pickups, double a_BlockX, double a_BlockY, double a_BlockZ, double a_SpeedX, double a_SpeedY, double a_SpeedZ, bool IsPlayerCreated = false) = 0; virtual UInt32 SpawnItemPickup(double a_PosX, double a_PosY, double a_PosZ, const cItem & a_Item, float a_SpeedX = 0.f, float a_SpeedY = 0.f, float a_SpeedZ = 0.f, int a_LifetimeTicks = 6000, bool a_CanCombine = true) = 0; /** Spawns a mob of the specified type. Returns the mob's UniqueID if recognized and spawned, or cEntity::INVALID_ID on failure. */ virtual UInt32 SpawnMob(double a_PosX, double a_PosY, double a_PosZ, eMonsterType a_MonsterType, bool a_Baby) = 0; /** Spawns an experience orb at the given location with the given reward. Returns the UniqueID of the spawned experience orb, or cEntity::INVALID_ID on failure. */ virtual UInt32 SpawnExperienceOrb(double a_X, double a_Y, double a_Z, int a_Reward) = 0; /** Spawns experience orbs of the specified total value at the given location. The orbs' values are split according to regular Minecraft rules. Returns an vector of UniqueID of all the orbs. */ virtual std::vector SpawnSplitExperienceOrbs(Vector3d a_Pos, int a_Reward) = 0; /** Sends the block on those coords to the player */ virtual void SendBlockTo(int a_BlockX, int a_BlockY, int a_BlockZ, const cPlayer & a_Player) = 0; /** Sends the block on those coords to the player */ inline void SendBlockTo(const Vector3i a_BlockPos, const cPlayer & a_Player) { SendBlockTo(a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, a_Player); } /** Calls the callback for each player in the list; returns true if all players processed, false if the callback aborted by returning true */ virtual bool ForEachPlayer(cPlayerListCallback a_Callback) = 0; /** Calls the callback for each entity that has a nonempty intersection with the specified boundingbox. Returns true if all entities processed, false if the callback aborted by returning true. If any chunk in the box is missing, ignores the entities in that chunk silently. */ virtual bool ForEachEntityInBox(const cBoundingBox & a_Box, cEntityCallback a_Callback) = 0; virtual void SetTimeOfDay(cTickTime a_TimeOfDay) = 0; /** Returns true if it is raining or storming at the specified location. This takes into account biomes. */ virtual bool IsWeatherWetAt(int a_BlockX, int a_BlockZ) = 0; /** Returns true if it is raining or storming at the specified location, and the rain reaches the specified block position. Returns the global weather state for unloaded chunks. */ virtual bool IsWeatherWetAtXYZ(Vector3i a_Pos) = 0; /** Returns or sets the minumim or maximum netherportal width */ virtual int GetMinNetherPortalWidth(void) const = 0; virtual int GetMaxNetherPortalWidth(void) const = 0; virtual void SetMinNetherPortalWidth(int a_NewMinWidth) = 0; virtual void SetMaxNetherPortalWidth(int a_NewMaxWidth) = 0; /** Returns or sets the minumim or maximum netherportal height */ virtual int GetMinNetherPortalHeight(void) const = 0; virtual int GetMaxNetherPortalHeight(void) const = 0; virtual void SetMinNetherPortalHeight(int a_NewMinHeight) = 0; virtual void SetMaxNetherPortalHeight(int a_NewMaxHeight) = 0; /** Returns the world height at the specified coords; returns nullopt for unloaded / generated chunks */ virtual std::optional GetHeight(int a_BlockX, int a_BlockZ) = 0; /** Wakes up the simulators for the specified block */ virtual void WakeUpSimulators(Vector3i a_Block) = 0; }; ================================================ FILE: src/BoundingBox.cpp ================================================ // BoundingBox.cpp // Implements the cBoundingBox class representing an axis-aligned bounding box with floatingpoint coords #include "Globals.h" #include "BoundingBox.h" cBoundingBox::cBoundingBox(double a_MinX, double a_MaxX, double a_MinY, double a_MaxY, double a_MinZ, double a_MaxZ) : m_Min(a_MinX, a_MinY, a_MinZ), m_Max(a_MaxX, a_MaxY, a_MaxZ) { } cBoundingBox::cBoundingBox(Vector3d a_Min, Vector3d a_Max) : m_Min(a_Min), m_Max(a_Max) { } cBoundingBox::cBoundingBox(Vector3d a_Pos, double a_Radius, double a_Height) : m_Min(a_Pos.x - a_Radius, a_Pos.y, a_Pos.z - a_Radius), m_Max(a_Pos.x + a_Radius, a_Pos.y + a_Height, a_Pos.z + a_Radius) { } cBoundingBox::cBoundingBox(Vector3d a_Pos, double a_Radius, double a_Height, double a_VerticalOffset) : m_Min(a_Pos.x - a_Radius, a_Pos.y + a_VerticalOffset, a_Pos.z - a_Radius), m_Max(a_Pos.x + a_Radius, a_Pos.y + a_VerticalOffset + a_Height, a_Pos.z + a_Radius) { } cBoundingBox::cBoundingBox(Vector3d a_Pos, double a_CubeLength) : m_Min(a_Pos.x - a_CubeLength / 2, a_Pos.y - a_CubeLength / 2, a_Pos.z - a_CubeLength / 2), m_Max(a_Pos.x + a_CubeLength / 2, a_Pos.y + a_CubeLength / 2, a_Pos.z + a_CubeLength / 2) { } void cBoundingBox::Move(double a_OffX, double a_OffY, double a_OffZ) { m_Min.x += a_OffX; m_Min.y += a_OffY; m_Min.z += a_OffZ; m_Max.x += a_OffX; m_Max.y += a_OffY; m_Max.z += a_OffZ; } void cBoundingBox::Move(Vector3d a_Off) { m_Min.x += a_Off.x; m_Min.y += a_Off.y; m_Min.z += a_Off.z; m_Max.x += a_Off.x; m_Max.y += a_Off.y; m_Max.z += a_Off.z; } void cBoundingBox::Expand(double a_ExpandX, double a_ExpandY, double a_ExpandZ) { m_Min.x -= a_ExpandX; m_Min.y -= a_ExpandY; m_Min.z -= a_ExpandZ; m_Max.x += a_ExpandX; m_Max.y += a_ExpandY; m_Max.z += a_ExpandZ; } bool cBoundingBox::DoesIntersect(const cBoundingBox & a_Other) { return ( ((a_Other.m_Min.x <= m_Max.x) && (a_Other.m_Max.x >= m_Min.x)) && // X coords intersect ((a_Other.m_Min.y <= m_Max.y) && (a_Other.m_Max.y >= m_Min.y)) && // Y coords intersect ((a_Other.m_Min.z <= m_Max.z) && (a_Other.m_Max.z >= m_Min.z)) // Z coords intersect ); } cBoundingBox cBoundingBox::Union(const cBoundingBox & a_Other) { return cBoundingBox( std::min(m_Min.x, a_Other.m_Min.x), std::max(m_Max.x, a_Other.m_Max.x), std::min(m_Min.y, a_Other.m_Min.y), std::max(m_Max.y, a_Other.m_Max.y), std::min(m_Min.z, a_Other.m_Min.z), std::max(m_Max.z, a_Other.m_Max.z) ); } bool cBoundingBox::IsInside(Vector3d a_Point) { return IsInside(m_Min, m_Max, a_Point); } bool cBoundingBox::IsInside(double a_X, double a_Y, double a_Z) { return IsInside(m_Min, m_Max, a_X, a_Y, a_Z); } bool cBoundingBox::IsInside(cBoundingBox & a_Other) { // If both a_Other's coords are inside this, then the entire a_Other is inside return (IsInside(a_Other.m_Min) && IsInside(a_Other.m_Max)); } bool cBoundingBox::IsInside(Vector3d a_Min, Vector3d a_Max) { // If both coords are inside this, then the entire a_Other is inside return (IsInside(a_Min) && IsInside(a_Max)); } bool cBoundingBox::IsInside(Vector3d a_Min, Vector3d a_Max, Vector3d a_Point) { return ( ((a_Point.x >= a_Min.x) && (a_Point.x <= a_Max.x)) && ((a_Point.y >= a_Min.y) && (a_Point.y <= a_Max.y)) && ((a_Point.z >= a_Min.z) && (a_Point.z <= a_Max.z)) ); } bool cBoundingBox::IsInside(Vector3d a_Min, Vector3d a_Max, double a_X, double a_Y, double a_Z) { return ( ((a_X >= a_Min.x) && (a_X <= a_Max.x)) && ((a_Y >= a_Min.y) && (a_Y <= a_Max.y)) && ((a_Z >= a_Min.z) && (a_Z <= a_Max.z)) ); } bool cBoundingBox::CalcLineIntersection(Vector3d a_Line1, Vector3d a_Line2, double & a_LineCoeff, eBlockFace & a_Face) const { return CalcLineIntersection(m_Min, m_Max, a_Line1, a_Line2, a_LineCoeff, a_Face); } bool cBoundingBox::CalcLineIntersection(Vector3d a_Min, Vector3d a_Max, Vector3d a_Line1, Vector3d a_Line2, double & a_LineCoeff, eBlockFace & a_Face) { if (IsInside(a_Min, a_Max, a_Line1)) { // The starting point is inside the bounding box. a_LineCoeff = 0; a_Face = BLOCK_FACE_NONE; // No faces hit return true; } eBlockFace Face = BLOCK_FACE_NONE; double Coeff = Vector3d::NO_INTERSECTION; // Check each individual bbox face for intersection with the line, remember the one with the lowest coeff double c = a_Line1.LineCoeffToXYPlane(a_Line2, a_Min.z); if ((c >= 0) && (c < Coeff) && IsInside(a_Min, a_Max, a_Line1 + (a_Line2 - a_Line1) * c)) { Face = (a_Line1.z > a_Line2.z) ? BLOCK_FACE_ZP : BLOCK_FACE_ZM; Coeff = c; } c = a_Line1.LineCoeffToXYPlane(a_Line2, a_Max.z); if ((c >= 0) && (c < Coeff) && IsInside(a_Min, a_Max, a_Line1 + (a_Line2 - a_Line1) * c)) { Face = (a_Line1.z > a_Line2.z) ? BLOCK_FACE_ZP : BLOCK_FACE_ZM; Coeff = c; } c = a_Line1.LineCoeffToXZPlane(a_Line2, a_Min.y); if ((c >= 0) && (c < Coeff) && IsInside(a_Min, a_Max, a_Line1 + (a_Line2 - a_Line1) * c)) { Face = (a_Line1.y > a_Line2.y) ? BLOCK_FACE_YP : BLOCK_FACE_YM; Coeff = c; } c = a_Line1.LineCoeffToXZPlane(a_Line2, a_Max.y); if ((c >= 0) && (c < Coeff) && IsInside(a_Min, a_Max, a_Line1 + (a_Line2 - a_Line1) * c)) { Face = (a_Line1.y > a_Line2.y) ? BLOCK_FACE_YP : BLOCK_FACE_YM; Coeff = c; } c = a_Line1.LineCoeffToYZPlane(a_Line2, a_Min.x); if ((c >= 0) && (c < Coeff) && IsInside(a_Min, a_Max, a_Line1 + (a_Line2 - a_Line1) * c)) { Face = (a_Line1.x > a_Line2.x) ? BLOCK_FACE_XP : BLOCK_FACE_XM; Coeff = c; } c = a_Line1.LineCoeffToYZPlane(a_Line2, a_Max.x); if ((c >= 0) && (c < Coeff) && IsInside(a_Min, a_Max, a_Line1 + (a_Line2 - a_Line1) * c)) { Face = (a_Line1.x > a_Line2.x) ? BLOCK_FACE_XP : BLOCK_FACE_XM; Coeff = c; } if (Coeff >= Vector3d::NO_INTERSECTION) { // There has been no intersection return false; } a_LineCoeff = Coeff; a_Face = Face; return true; } bool cBoundingBox::Intersect(const cBoundingBox & a_Other, cBoundingBox & a_Intersection) const { a_Intersection.m_Min.x = std::max(m_Min.x, a_Other.m_Min.x); a_Intersection.m_Max.x = std::min(m_Max.x, a_Other.m_Max.x); if (a_Intersection.m_Min.x >= a_Intersection.m_Max.x) { return false; } a_Intersection.m_Min.y = std::max(m_Min.y, a_Other.m_Min.y); a_Intersection.m_Max.y = std::min(m_Max.y, a_Other.m_Max.y); if (a_Intersection.m_Min.y >= a_Intersection.m_Max.y) { return false; } a_Intersection.m_Min.z = std::max(m_Min.z, a_Other.m_Min.z); a_Intersection.m_Max.z = std::min(m_Max.z, a_Other.m_Max.z); return (a_Intersection.m_Min.z < a_Intersection.m_Max.z); } ================================================ FILE: src/BoundingBox.h ================================================ // BoundingBox.h // Declares the cBoundingBox class representing an axis-aligned bounding box with floatingpoint coords #pragma once #include "Defines.h" // tolua_begin /** Represents two sets of coords, minimum and maximum for each direction. All the coords within those limits (inclusive the edges) are considered "inside" the box. For intersection purposes, though, if the intersection is "sharp" in any coord (i. e. zero volume), the boxes are considered non-intersecting. */ class cBoundingBox { public: cBoundingBox(double a_MinX, double a_MaxX, double a_MinY, double a_MaxY, double a_MinZ, double a_MaxZ); cBoundingBox(Vector3d a_Min, Vector3d a_Max); cBoundingBox(Vector3d a_Pos, double a_Radius, double a_Height); /** Constructor that allows to define a bounding box given a center point (a_Pos), a horizontal radius (a_Radius), a height starting from given center point (a_Height) and a vertical offset (a_VerticalOffset) to adjust the vertical starting point. For example: cBoundingBox([0, 0, 0], 6, 6, -3) would create a bounding cube from (-3, -3, -3) to (3, 3, 3). */ cBoundingBox(Vector3d a_Pos, double a_Radius, double a_Height, double a_VerticalOffset); cBoundingBox(Vector3d a_Pos, double a_CubeLength); #ifdef TOLUA_EXPOSITION // tolua isn't aware of implicitly generated copy constructors cBoundingBox(const cBoundingBox & a_Orig); #endif /** Moves the entire boundingbox by the specified offset */ void Move(double a_OffX, double a_OffY, double a_OffZ); /** Moves the entire boundingbox by the specified offset */ void Move(Vector3d a_Off); /** Expands the bounding box by the specified amount in each direction (so the box becomes larger by 2 * Expand in each direction) */ void Expand(double a_ExpandX, double a_ExpandY, double a_ExpandZ); /** Returns true if the two bounding boxes intersect */ bool DoesIntersect(const cBoundingBox & a_Other); /** Returns the union of the two bounding boxes */ cBoundingBox Union(const cBoundingBox & a_Other); /** Returns true if the point is inside the bounding box */ bool IsInside(Vector3d a_Point); /** Returns true if the point is inside the bounding box */ bool IsInside(double a_X, double a_Y, double a_Z); /** Returns true if a_Other is inside this bounding box */ bool IsInside(cBoundingBox & a_Other); /** Returns true if a boundingbox specified by a_Min and a_Max is inside this bounding box */ bool IsInside(Vector3d a_Min, Vector3d a_Max); /** Returns true if the specified point is inside the bounding box specified by its min / max corners */ static bool IsInside(Vector3d a_Min, Vector3d a_Max, Vector3d a_Point); /** Returns true if the specified point is inside the bounding box specified by its min / max corners */ static bool IsInside(Vector3d a_Min, Vector3d a_Max, double a_X, double a_Y, double a_Z); // tolua_end /** Returns true if this bounding box is intersected by the line specified by its two points Also calculates the distance along the line in which the intersection occurs, and the face hit (BLOCK_FACE_ constants) Only forward collisions (a_LineCoeff >= 0) are returned. Exported to Lua manually, because ToLua++ would generate needless input params (a_LineCoeff, a_Face). */ bool CalcLineIntersection(Vector3d a_LinePoint1, Vector3d a_LinePoint2, double & a_LineCoeff, eBlockFace & a_Face) const; /** Returns true if the specified bounding box is intersected by the line specified by its two points Also calculates the distance along the line in which the intersection occurs, and the face hit (BLOCK_FACE_ constants) Only forward collisions (a_LineCoeff >= 0) are returned. Exported to Lua manually, because ToLua++ would generate needless input params (a_LineCoeff, a_Face). */ static bool CalcLineIntersection(Vector3d a_Min, Vector3d a_Max, Vector3d a_LinePoint1, Vector3d a_LinePoint2, double & a_LineCoeff, eBlockFace & a_Face); /** Calculates the intersection of the two bounding boxes; returns true if nonempty. Exported manually, because ToLua++ would generate needless input params (a_Intersection). */ bool Intersect(const cBoundingBox & a_Other, cBoundingBox & a_Intersection) const; // tolua_begin double GetMinX(void) const { return m_Min.x; } double GetMinY(void) const { return m_Min.y; } double GetMinZ(void) const { return m_Min.z; } double GetMaxX(void) const { return m_Max.x; } double GetMaxY(void) const { return m_Max.y; } double GetMaxZ(void) const { return m_Max.z; } Vector3d GetMin(void) const { return m_Min; } Vector3d GetMax(void) const { return m_Max; } // tolua_end protected: Vector3d m_Min; Vector3d m_Max; } ; // tolua_export ================================================ FILE: src/BrewingRecipes.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "BrewingRecipes.h" #include #define BREWING_RECIPE_FILE "brewing.txt" cBrewingRecipes::cBrewingRecipes() { ReloadRecipes(); } void cBrewingRecipes::ReloadRecipes(void) { ClearRecipes(); LOGD("Loading brewing recipes..."); std::ifstream f(BREWING_RECIPE_FILE, std::ios::in); if (!f.good()) { LOG("Could not open the brewing recipes file \"%s\". No brewing recipes are available.", BREWING_RECIPE_FILE); return; } unsigned int LineNum = 0; AString ParsingLine; while (std::getline(f, ParsingLine)) { LineNum++; // Remove comments from the line: size_t FirstCommentSymbol = ParsingLine.find('#'); if (FirstCommentSymbol != AString::npos) { ParsingLine.erase(FirstCommentSymbol); } if (IsOnlyWhitespace(ParsingLine)) { // Ignore empty and whitespace only lines continue; } AddRecipeFromLine(ParsingLine, LineNum); } // while (getline(ParsingLine)) LOG("Loaded %zu brewing recipes", m_Recipes.size()); } void cBrewingRecipes::AddRecipeFromLine(AString a_Line, unsigned int a_LineNum) { a_Line.erase(std::remove_if(a_Line.begin(), a_Line.end(), isspace), a_Line.end()); auto Recipe = std::make_unique(); const AStringVector & InputAndIngredient = StringSplit(a_Line, "+"); if (InputAndIngredient.size() != 2) { LOGWARNING("brewing.txt: line %d: A line with '+' was expected", a_LineNum); LOGINFO("Offending line: \"%s\"", a_Line.c_str()); return; } const AStringVector & IngredientAndOutput = StringSplit(InputAndIngredient[1], "="); if (IngredientAndOutput.size() != 2) { LOGWARNING("brewing.txt: line %d: A line with '=' was expected", a_LineNum); LOGINFO("Offending line: \"%s\"", a_Line.c_str()); return; } if (!ParseItem(IngredientAndOutput[0], Recipe->Ingredient)) { LOGWARNING("brewing.txt: Parsing of the item didn't worked."); LOGINFO("Offending line: \"%s\"", a_Line.c_str()); return; } if (!StringToInteger(InputAndIngredient[0], Recipe->Input.m_ItemDamage)) { LOGWARNING("brewing.txt: line %d: Cannot parse the damage value for the input item\"%s\".", a_LineNum, InputAndIngredient[0].c_str()); LOGINFO("Offending line: \"%s\"", a_Line.c_str()); return; } if (!StringToInteger(IngredientAndOutput[1], Recipe->Output.m_ItemDamage)) { LOGWARNING("brewing.txt: line %d: Cannot parse the damage value for the output item\"%s\".", a_LineNum, IngredientAndOutput[1].c_str()); LOGINFO("Offending line: \"%s\"", a_Line.c_str()); return; } m_Recipes.push_back(std::move(Recipe)); } bool cBrewingRecipes::ParseItem(const AString & a_String, cItem & a_Item) { return StringToItem(a_String, a_Item); } void cBrewingRecipes::ClearRecipes(void) { m_Recipes.clear(); } const cBrewingRecipes::cRecipe * cBrewingRecipes::GetRecipeFrom(const cItem & a_Input, const cItem & a_Ingredient) const { for (const auto & Recipe : m_Recipes) { if ((Recipe->Input.IsEqual(a_Input)) && (Recipe->Ingredient.IsEqual(a_Ingredient))) { return Recipe.get(); } } // Check for gunpowder if (a_Ingredient.m_ItemType == E_ITEM_GUNPOWDER) { if (a_Input.m_ItemDamage & 0x2000) { // Create new recipe and add it to list auto Recipe = std::make_unique(); Recipe->Input.m_ItemType = a_Input.m_ItemDamage; Recipe->Output.m_ItemDamage = a_Input.m_ItemDamage + 8192; Recipe->Ingredient.m_ItemType = E_ITEM_GUNPOWDER; auto RecipePtr = Recipe.get(); m_Recipes.push_back(std::move(Recipe)); return RecipePtr; } return nullptr; } // Check for splash potion if (a_Input.m_ItemDamage & 0x4000) { // Search for the drinkable potion, the ingredients are the same short SplashItemDamage = a_Input.m_ItemDamage - 8192; auto FoundRecipe = std::find_if(m_Recipes.cbegin(), m_Recipes.cend(), [&](const std::unique_ptr& a_Recipe) { return ( (a_Recipe->Input.m_ItemDamage == SplashItemDamage) && (a_Recipe->Ingredient.IsEqual(a_Ingredient)) ); }); if (FoundRecipe == m_Recipes.cend()) { return nullptr; } // Create new recipe and add it to list auto Recipe = std::make_unique(); Recipe->Input.m_ItemDamage = a_Input.m_ItemDamage; Recipe->Output.m_ItemDamage = (*FoundRecipe)->Output.m_ItemDamage + 8192; Recipe->Ingredient.m_ItemType = (*FoundRecipe)->Ingredient.m_ItemType; auto RecipePtr = Recipe.get(); m_Recipes.push_back(std::move(Recipe)); return RecipePtr; } return nullptr; } bool cBrewingRecipes::IsIngredient(const cItem & a_Ingredient) const { // Check for gunpowder if (a_Ingredient.m_ItemType == E_ITEM_GUNPOWDER) { return true; } for (const auto & Recipe : m_Recipes) { if (Recipe->Ingredient.IsEqual(a_Ingredient)) { return true; } } return false; } bool cBrewingRecipes::IsBottle(const cItem & a_Item) const { return (a_Item.m_ItemType == E_ITEM_POTION); } bool cBrewingRecipes::IsFuel(const cItem & a_Item) const { return (a_Item.m_ItemType == E_ITEM_BLAZE_POWDER); } ================================================ FILE: src/BrewingRecipes.h ================================================ #pragma once #include "Item.h" class cBrewingRecipes { public: cBrewingRecipes(void); void ReloadRecipes(void); struct cRecipe { cRecipe() { // These items always have the same type Input.m_ItemType = E_ITEM_POTION; Output.m_ItemType = E_ITEM_POTION; } cItem Input; cItem Output; cItem Ingredient; }; /** Returns a recipe for the specified input, nullptr if no recipe found */ const cRecipe * GetRecipeFrom(const cItem & a_Input, const cItem & a_Ingredient) const; /** Returns true if the item is a ingredient, false if not. */ bool IsIngredient(const cItem & a_Ingredient) const; /** Returns true if the item is a bottle / potion, false if not. */ bool IsBottle(const cItem & a_Item) const; /** Returns true if the item is the fuel, false if not. */ bool IsFuel(const cItem & a_Item) const; private: using cRecipes = std::vector>; void ClearRecipes(void); /** Parses the recipe contained in the line, adds it to m_pState's recipes. Logs a warning to the console on input error. */ void AddRecipeFromLine(AString a_Line, unsigned int a_LineNum); /** Parses an item string, returns true if successful. */ bool ParseItem(const AString & a_String, cItem & a_Item); /** The collection of parsed recipes. GetRecipeFrom may cache splash variants of recipes here but the observable behaviour is constant, so this should be mutable. */ mutable cRecipes m_Recipes; }; ================================================ FILE: src/Broadcaster.cpp ================================================ // Broadcaster.cpp // Implements the broadcasting functions for cWorld #include "Globals.h" #include "World.h" #include "Chunk.h" #include "ClientHandle.h" #include "Entities/Entity.h" #include "Entities/Player.h" #include "BlockEntities/BlockEntity.h" namespace { /** Calls the function object a_Func for every active client in the world \param a_World World the clients are in \param a_Exclude Client for which a_Func should not be called \param a_Func Function to be called with each non-excluded client */ template void ForClientsInWorld(cWorld & a_World, const cClientHandle * a_Exclude, Func a_Func) { a_World.ForEachPlayer([&](cPlayer & a_Player) { cClientHandle * Client = a_Player.GetClientHandle(); if ((Client != a_Exclude) && (Client != nullptr) && Client->IsLoggedIn() && !Client->IsDestroyed()) { a_Func(*Client); } return false; } ); } /** Calls the function object a_Func for every client who has the specified chunk \param a_ChunkCoords Coords of the chunk to query for clients \param a_World World that the chunk is in \param a_Exclude Client for which a_Func should not be called \param a_Func Function to be called with each non-excluded client */ template void ForClientsWithChunk(const cChunkCoords a_ChunkCoords, cWorld & a_World, const cClientHandle * a_Exclude, Func a_Func) { a_World.DoWithChunk(a_ChunkCoords.m_ChunkX, a_ChunkCoords.m_ChunkZ, [&](cChunk & a_Chunk) { for (auto * Client : a_Chunk.GetAllClients()) { if (Client != a_Exclude) { a_Func(*Client); } } return true; } ); } /** Calls the function object a_Func for every client who has the chunk at the specified block position \param a_WorldPos Coordinates of the block to query for clients \param a_World World that the block is in \param a_Exclude Client for which a_Func should not be called \param a_Func Function to be called with each non-excluded client */ template void ForClientsWithChunkAtPos(const Vector3i a_WorldPos, cWorld & a_World, const cClientHandle * a_Exclude, Func a_Func) { ForClientsWithChunk(cChunkDef::BlockToChunk(a_WorldPos), a_World, a_Exclude, std::move(a_Func)); } /** Calls the function object a_Func for every client who has the specified entity \param a_Entity Entity to query for clients \param a_World World that the block is in \param a_Exclude Client for which a_Func should not be called \param a_Func Function to be called with each non-excluded client */ template void ForClientsWithEntity(const cEntity & a_Entity, cWorld & a_World, const cClientHandle * a_Exclude, Func a_Func) { cWorld::cLock Lock(a_World); // Lock world before accessing a_Entity auto Chunk = a_Entity.GetParentChunk(); if (Chunk != nullptr) { for (auto * Client : Chunk->GetAllClients()) { if (Client != a_Exclude) { a_Func(*Client); } } } else // Some broadcasts happen before the entity's first tick sets its ParentChunk { ForClientsWithChunk({ a_Entity.GetChunkX(), a_Entity.GetChunkZ() }, a_World, a_Exclude, std::move(a_Func)); } } } // namespace (anonymous) void cWorld::BroadcastAttachEntity(const cEntity & a_Entity, const cEntity & a_Vehicle) { ForClientsWithEntity(a_Entity, *this, nullptr, [&](cClientHandle & a_Client) { a_Client.SendAttachEntity(a_Entity, a_Vehicle); } ); } void cWorld::BroadcastBlockAction(Vector3i a_BlockPos, Byte a_Byte1, Byte a_Byte2, BLOCKTYPE a_BlockType, const cClientHandle * a_Exclude) { ForClientsWithChunkAtPos(a_BlockPos, *this, a_Exclude, [&](cClientHandle & a_Client) { a_Client.SendBlockAction(a_BlockPos, static_cast(a_Byte1), static_cast(a_Byte2), a_BlockType); } ); } void cWorld::BroadcastBlockBreakAnimation(UInt32 a_EntityID, Vector3i a_BlockPos, Int8 a_Stage, const cClientHandle * a_Exclude) { ForClientsWithChunkAtPos(a_BlockPos, *this, a_Exclude, [&](cClientHandle & a_Client) { a_Client.SendBlockBreakAnim(a_EntityID, a_BlockPos, a_Stage); } ); } void cWorld::BroadcastBlockEntity(Vector3i a_BlockPos, const cClientHandle * a_Exclude) { DoWithChunkAt(a_BlockPos, [&](cChunk & a_Chunk) { cBlockEntity * Entity = a_Chunk.GetBlockEntity(a_BlockPos); if (Entity == nullptr) { return false; } for (auto * Client : a_Chunk.GetAllClients()) { if (Client != a_Exclude) { Entity->SendTo(*Client); } } return true; } ); } void cWorld::BroadcastBossBarUpdateHealth(const cEntity & a_Entity, UInt32 a_UniqueID, float a_FractionFilled) { ForClientsWithEntity(a_Entity, *this, nullptr, [&](cClientHandle & a_Client) { a_Client.SendBossBarUpdateHealth(a_UniqueID, a_FractionFilled); } ); } void cWorld::BroadcastChat(const AString & a_Message, const cClientHandle * a_Exclude, eMessageType a_ChatPrefix) { if ((a_ChatPrefix == mtDeath) && !ShouldBroadcastDeathMessages()) { return; } ForClientsInWorld(*this, a_Exclude, [&](cClientHandle & a_Client) { a_Client.SendChat(a_Message, a_ChatPrefix); } ); } void cWorld::BroadcastChat(const cCompositeChat & a_Message, const cClientHandle * a_Exclude) { ForClientsInWorld(*this, a_Exclude, [&](cClientHandle & a_Client) { a_Client.SendChat(a_Message); } ); } void cWorld::BroadcastCollectEntity(const cEntity & a_Collected, const cEntity & a_Collector, unsigned a_Count, const cClientHandle * a_Exclude) { ForClientsWithEntity(a_Collected, *this, a_Exclude, [&](cClientHandle & a_Client) { a_Client.SendCollectEntity(a_Collected, a_Collector, a_Count); } ); } void cWorld::BroadcastDestroyEntity(const cEntity & a_Entity, const cClientHandle * a_Exclude) { ForClientsWithEntity(a_Entity, *this, a_Exclude, [&](cClientHandle & a_Client) { a_Client.SendDestroyEntity(a_Entity); } ); } void cWorld::BroadcastDetachEntity(const cEntity & a_Entity, const cEntity & a_PreviousVehicle) { ForClientsWithEntity(a_Entity, *this, nullptr, [&](cClientHandle & a_Client) { a_Client.SendDetachEntity(a_Entity, a_PreviousVehicle); } ); } void cWorld::BroadcastDisplayObjective(const AString & a_Objective, cScoreboard::eDisplaySlot a_Display) { ForClientsInWorld(*this, nullptr, [&](cClientHandle & a_Client) { a_Client.SendDisplayObjective(a_Objective, a_Display); } ); } void cWorld::BroadcastEntityEffect(const cEntity & a_Entity, int a_EffectID, int a_Amplifier, int a_Duration, const cClientHandle * a_Exclude) { ForClientsWithEntity(a_Entity, *this, a_Exclude, [&](cClientHandle & a_Client) { a_Client.SendEntityEffect(a_Entity, a_EffectID, a_Amplifier, a_Duration); } ); } void cWorld::BroadcastEntityEquipment(const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item, const cClientHandle * a_Exclude) { ForClientsWithEntity(a_Entity, *this, a_Exclude, [&](cClientHandle & a_Client) { a_Client.SendEntityEquipment(a_Entity, a_SlotNum, a_Item); } ); } void cWorld::BroadcastEntityHeadLook(const cEntity & a_Entity, const cClientHandle * a_Exclude) { ForClientsWithEntity(a_Entity, *this, a_Exclude, [&](cClientHandle & a_Client) { a_Client.SendEntityHeadLook(a_Entity); } ); } void cWorld::BroadcastEntityLook(const cEntity & a_Entity, const cClientHandle * a_Exclude) { ForClientsWithEntity(a_Entity, *this, a_Exclude, [&](cClientHandle & a_Client) { a_Client.SendEntityLook(a_Entity); } ); } void cWorld::BroadcastEntityMetadata(const cEntity & a_Entity, const cClientHandle * a_Exclude) { ForClientsWithEntity(a_Entity, *this, a_Exclude, [&](cClientHandle & a_Client) { a_Client.SendEntityMetadata(a_Entity); } ); } void cWorld::BroadcastEntityPosition(const cEntity & a_Entity, const cClientHandle * a_Exclude) { ForClientsWithEntity(a_Entity, *this, a_Exclude, [&](cClientHandle & a_Client) { a_Client.SendEntityPosition(a_Entity); } ); } void cWorld::BroadcastEntityProperties(const cEntity & a_Entity) { ForClientsWithEntity(a_Entity, *this, nullptr, [&](cClientHandle & a_Client) { a_Client.SendEntityProperties(a_Entity); } ); } void cWorld::BroadcastEntityVelocity(const cEntity & a_Entity, const cClientHandle * a_Exclude) { ForClientsWithEntity(a_Entity, *this, a_Exclude, [&](cClientHandle & a_Client) { a_Client.SendEntityVelocity(a_Entity); } ); } void cWorld::BroadcastEntityAnimation(const cEntity & a_Entity, EntityAnimation a_Animation, const cClientHandle * a_Exclude) { ForClientsWithEntity(a_Entity, *this, a_Exclude, [&](cClientHandle & a_Client) { a_Client.SendEntityAnimation(a_Entity, a_Animation); } ); } void cWorld::BroadcastLeashEntity(const cEntity & a_Entity, const cEntity & a_EntityLeashedTo) { ForClientsWithEntity(a_Entity, *this, nullptr, [&](cClientHandle & a_Client) { a_Client.SendLeashEntity(a_Entity, a_EntityLeashedTo); } ); } void cWorld::BroadcastParticleEffect(const AString & a_ParticleName, const Vector3f a_Src, const Vector3f a_Offset, float a_ParticleData, int a_ParticleAmount, const cClientHandle * a_Exclude) { ForClientsWithChunkAtPos(a_Src, *this, a_Exclude, [&](cClientHandle & a_Client) { a_Client.SendParticleEffect(a_ParticleName, a_Src, a_Offset, a_ParticleData, a_ParticleAmount); } ); } void cWorld::BroadcastParticleEffect(const AString & a_ParticleName, const Vector3f a_Src, const Vector3f a_Offset, float a_ParticleData, int a_ParticleAmount, std::array a_Data, const cClientHandle * a_Exclude) { ForClientsWithChunkAtPos(a_Src, *this, a_Exclude, [&](cClientHandle & a_Client) { a_Client.SendParticleEffect(a_ParticleName, a_Src, a_Offset, a_ParticleData, a_ParticleAmount, a_Data); } ); } void cWorld::BroadcastPlayerListAddPlayer(const cPlayer & a_Player, const cClientHandle * a_Exclude) { ForClientsInWorld(*this, a_Exclude, [&](cClientHandle & a_Client) { a_Client.SendPlayerListAddPlayer(a_Player); } ); } void cWorld::BroadcastPlayerListHeaderFooter(const cCompositeChat & a_Header, const cCompositeChat & a_Footer) { ForClientsInWorld(*this, nullptr, [&](cClientHandle & a_Client) { a_Client.SendPlayerListHeaderFooter(a_Header, a_Footer); } ); } void cWorld::BroadcastPlayerListRemovePlayer(const cPlayer & a_Player, const cClientHandle * a_Exclude) { ForClientsInWorld(*this, a_Exclude, [&](cClientHandle & a_Client) { a_Client.SendPlayerListRemovePlayer(a_Player); } ); } void cWorld::BroadcastPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_CustomName, const cClientHandle * a_Exclude) { ForClientsInWorld(*this, a_Exclude, [&](cClientHandle & a_Client) { a_Client.SendPlayerListUpdateDisplayName(a_Player, a_CustomName); } ); } void cWorld::BroadcastPlayerListUpdateGameMode(const cPlayer & a_Player, const cClientHandle * a_Exclude) { ForClientsInWorld(*this, a_Exclude, [&](cClientHandle & a_Client) { a_Client.SendPlayerListUpdateGameMode(a_Player); } ); } void cWorld::BroadcastPlayerListUpdatePing() { ForClientsInWorld(*this, nullptr, [&](cClientHandle & a_Client) { a_Client.SendPlayerListUpdatePing(); } ); } void cWorld::BroadcastRemoveEntityEffect(const cEntity & a_Entity, int a_EffectID, const cClientHandle * a_Exclude) { ForClientsWithEntity(a_Entity, *this, a_Exclude, [&](cClientHandle & a_Client) { a_Client.SendRemoveEntityEffect(a_Entity, a_EffectID); } ); } void cWorld::BroadcastScoreboardObjective(const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) { ForClientsInWorld(*this, nullptr, [&](cClientHandle & a_Client) { a_Client.SendScoreboardObjective(a_Name, a_DisplayName, a_Mode); } ); } void cWorld::BroadcastScoreUpdate(const AString & a_Objective, const AString & a_PlayerName, cObjective::Score a_Score, Byte a_Mode) { ForClientsInWorld(*this, nullptr, [&](cClientHandle & a_Client) { a_Client.SendScoreUpdate(a_Objective, a_PlayerName, a_Score, a_Mode); } ); } void cWorld::BroadcastSoundEffect(const AString & a_SoundName, Vector3d a_Position, float a_Volume, float a_Pitch, const cClientHandle * a_Exclude) { ForClientsWithChunkAtPos(a_Position, *this, a_Exclude, [&](cClientHandle & a_Client) { a_Client.SendSoundEffect(a_SoundName, a_Position, a_Volume, a_Pitch); } ); } void cWorld::BroadcastSoundParticleEffect(const EffectID a_EffectID, Vector3i a_SrcPos, int a_Data, const cClientHandle * a_Exclude) { ForClientsWithChunkAtPos(a_SrcPos, *this, a_Exclude, [&](cClientHandle & a_Client) { a_Client.SendSoundParticleEffect(a_EffectID, a_SrcPos, a_Data); } ); } void cWorld::BroadcastSpawnEntity(cEntity & a_Entity, const cClientHandle * a_Exclude) { ForClientsWithEntity(a_Entity, *this, a_Exclude, [&](cClientHandle & a_Client) { a_Entity.SpawnOn(a_Client); } ); } void cWorld::BroadcastThunderbolt(Vector3i a_BlockPos, const cClientHandle * a_Exclude) { ForClientsWithChunkAtPos(a_BlockPos, *this, a_Exclude, [&](cClientHandle & a_Client) { a_Client.SendThunderbolt(a_BlockPos); } ); } void cWorld::BroadcastTimeUpdate(const cClientHandle * a_Exclude) { ForClientsInWorld(*this, a_Exclude, [&](cClientHandle & a_Client) { a_Client.SendTimeUpdate(GetWorldAge(), GetWorldDate(), IsDaylightCycleEnabled()); } ); } void cWorld::BroadcastUnleashEntity(const cEntity & a_Entity) { ForClientsWithEntity(a_Entity, *this, nullptr, [&](cClientHandle & a_Client) { a_Client.SendUnleashEntity(a_Entity); } ); } void cWorld::BroadcastWeather(eWeather a_Weather, const cClientHandle * a_Exclude) { ForClientsInWorld(*this, a_Exclude, [&](cClientHandle & a_Client) { a_Client.SendWeather(a_Weather); } ); } ================================================ FILE: src/BuildInfo.h.cmake ================================================ #pragma once #cmakedefine BUILD_ID #ifdef BUILD_ID #undef BUILD_ID #define BUILD_SERIES_NAME "@BUILD_SERIES_NAME@" #define BUILD_ID "@BUILD_ID@" #define BUILD_COMMIT_ID "@BUILD_COMMIT_ID@" #define BUILD_DATETIME "@BUILD_DATETIME@" #endif ================================================ FILE: src/ByteBuffer.cpp ================================================ // ByteBuffer.cpp // Implements the cByteBuffer class representing a ringbuffer of bytes #include "Globals.h" #include "ByteBuffer.h" #include "Endianness.h" #include "UUID.h" #include "OSSupport/IsThread.h" /** When defined, each access to a cByteBuffer object is checked whether it's done in the same thread. cByteBuffer assumes that it is not used by multiple threads at once, this macro adds a runtime check for that. Unfortunately it is very slow, so it is disabled even for regular DEBUG builds. */ // #define DEBUG_SINGLE_THREAD_ACCESS /** Constants encoding some values to reduce the amount of magic numbers */ namespace VarInt { constexpr unsigned char SEGMENT_BITS = 0x7F; constexpr unsigned char CONTINUE_BIT = 0x80; constexpr std::size_t MOVE_BITS = 7; constexpr std::size_t BYTE_COUNT = 5; // A 32-bit integer can be encoded by at most 5 bytes constexpr std::size_t BYTE_COUNT_LONG = 10; // A 64-bit integer can be encoded by at most 10 bytes } namespace Position { // If the bit indicated in the mask is 0, the the matching offset is applied. constexpr int BIT_MASK_IS_NEGATIVE_XZ = 0x02000000; constexpr int BIT_MASK_IS_NEGATIVE_Y = 0x0800; constexpr int NEGATIVE_OFFSET_XZ = 0x04000000; constexpr int NEGATIVE_OFFSET_Y = 0x01000; // Bit masks when reading the requested bits constexpr UInt32 BIT_MASK_XZ = 0x03ffffff; // 26 bits constexpr UInt32 BIT_MASK_Y = 0x0fff; // 12 bits } namespace XYZPosition { constexpr std::size_t BIT_COUNT_X = 38; constexpr std::size_t BIT_COUNT_Y = 26; } namespace XZYPosition { constexpr std::size_t BIT_COUNT_X = 38; constexpr std::size_t BIT_COUNT_Z = 12; } // If a string sent over the protocol is larger than this, a warning is emitted to the console #define MAX_STRING_SIZE (512 KiB) #define NEEDBYTES(Num) if (!CanReadBytes(Num)) return false // Check if at least Num bytes can be read from the buffer, return false if not #define PUTBYTES(Num) if (!CanWriteBytes(Num)) return false // Check if at least Num bytes can be written to the buffer, return false if not #ifdef DEBUG_SINGLE_THREAD_ACCESS /** Simple RAII class that is used for checking that no two threads are using an object simultanously. It requires the monitored object to provide the storage for a thread ID. It uses that storage to check if the thread ID of consecutive calls is the same all the time. */ class cSingleThreadAccessChecker { public: cSingleThreadAccessChecker(std::thread::id * a_ThreadID) : m_ThreadID(a_ThreadID) { ASSERT( (*a_ThreadID == std::this_thread::get_id()) || // Either the object is used by current thread... (*a_ThreadID == m_EmptyThreadID) // ... or by no thread at all ); // Mark as being used by this thread: *m_ThreadID = std::this_thread::get_id(); } ~cSingleThreadAccessChecker() { // Mark as not being used by any thread: *m_ThreadID = std::thread::id(); } protected: /** Points to the storage used for ID of the thread using the object. */ std::thread::id * m_ThreadID; /** The value of an unassigned thread ID, used to speed up checking. */ static std::thread::id m_EmptyThreadID; }; std::thread::id cSingleThreadAccessChecker::m_EmptyThreadID; #define CHECK_THREAD cSingleThreadAccessChecker Checker(&m_ThreadID); #else #define CHECK_THREAD #endif //////////////////////////////////////////////////////////////////////////////// // cByteBuffer: cByteBuffer::cByteBuffer(size_t a_BufferSize) : m_Buffer(new std::byte[a_BufferSize + 1]), m_BufferSize(a_BufferSize + 1) { // Allocating one byte more than the buffer size requested, so that we can distinguish between // completely-full and completely-empty states } cByteBuffer::~cByteBuffer() { CheckValid(); } bool cByteBuffer::Write(const void * a_Bytes, size_t a_Count) { CHECK_THREAD CheckValid(); // Store the current free space for a check after writing: auto CurFreeSpace = GetFreeSpace(); #ifndef NDEBUG auto CurReadableSpace = GetReadableSpace(); size_t WrittenBytes = 0; #endif if (CurFreeSpace < a_Count) { return false; } ASSERT(m_BufferSize >= m_WritePos); auto TillEnd = m_BufferSize - m_WritePos; auto Bytes = static_cast(a_Bytes); if (TillEnd <= a_Count) { // Need to wrap around the ringbuffer end if (TillEnd > 0) { memcpy(m_Buffer.get() + m_WritePos, Bytes, TillEnd); Bytes += TillEnd; a_Count -= TillEnd; #ifndef NDEBUG WrittenBytes = TillEnd; #endif } m_WritePos = 0; } // We're guaranteed that we'll fit in a single write op if (a_Count > 0) { memcpy(m_Buffer.get() + m_WritePos, Bytes, a_Count); m_WritePos += a_Count; #ifndef NDEBUG WrittenBytes += a_Count; #endif } ASSERT(GetFreeSpace() == CurFreeSpace - WrittenBytes); ASSERT(GetReadableSpace() == CurReadableSpace + WrittenBytes); return true; } size_t cByteBuffer::GetFreeSpace(void) const { CHECK_THREAD CheckValid(); if (m_WritePos >= m_DataStart) { // Wrap around the buffer end: ASSERT(m_BufferSize >= m_WritePos); ASSERT((m_BufferSize - m_WritePos + m_DataStart) >= 1); return m_BufferSize - m_WritePos + m_DataStart - 1; // -1 Offset since the last byte is used to indicate fullness or emptiness. } // Single free space partition: ASSERT(m_BufferSize >= m_WritePos); ASSERT(m_BufferSize - m_WritePos >= 1); return m_DataStart - m_WritePos - 1; // -1 Offset since the last byte is used to indicate fullness or emptiness. } size_t cByteBuffer::GetUsedSpace(void) const { CHECK_THREAD CheckValid(); ASSERT(m_BufferSize >= GetFreeSpace()); ASSERT((m_BufferSize - GetFreeSpace()) >= 1); return m_BufferSize - GetFreeSpace() - 1; // -1 Offset since the last byte is used to indicate fullness or emptiness. } size_t cByteBuffer::GetReadableSpace(void) const { CHECK_THREAD CheckValid(); if (m_ReadPos > m_WritePos) { // Wrap around the buffer end: ASSERT(m_BufferSize >= m_ReadPos); return m_BufferSize - m_ReadPos + m_WritePos; } // Single readable space partition: ASSERT(m_WritePos >= m_ReadPos); return m_WritePos - m_ReadPos; } bool cByteBuffer::CanBEInt8Represent(int a_Value) { return (std::numeric_limits::min() <= a_Value) && (a_Value <= std::numeric_limits::max()); } bool cByteBuffer::CanBEInt16Represent(int a_Value) { return (std::numeric_limits::min() <= a_Value) && (a_Value <= std::numeric_limits::max()); } bool cByteBuffer::CanReadBytes(size_t a_Count) const { CHECK_THREAD CheckValid(); return (a_Count <= GetReadableSpace()); } bool cByteBuffer::CanWriteBytes(size_t a_Count) const { CHECK_THREAD CheckValid(); return (a_Count <= GetFreeSpace()); } bool cByteBuffer::ReadBEInt8(Int8 & a_Value) { CHECK_THREAD CheckValid(); NEEDBYTES(1); ReadBuf(&a_Value, 1); return true; } bool cByteBuffer::ReadBEUInt8(UInt8 & a_Value) { CHECK_THREAD CheckValid(); NEEDBYTES(1); ReadBuf(&a_Value, 1); return true; } bool cByteBuffer::ReadBEInt16(Int16 & a_Value) { CHECK_THREAD CheckValid(); NEEDBYTES(2); Bytes bytes; ReadBuf(bytes.data(), bytes.size()); a_Value = NetworkToHost(bytes); return true; } bool cByteBuffer::ReadBEUInt16(UInt16 & a_Value) { CHECK_THREAD CheckValid(); NEEDBYTES(2); Bytes bytes; ReadBuf(bytes.data(), bytes.size()); a_Value = NetworkToHost(bytes); return true; } bool cByteBuffer::ReadBEInt32(Int32 & a_Value) { CHECK_THREAD CheckValid(); NEEDBYTES(4); Bytes bytes; ReadBuf(bytes.data(), bytes.size()); a_Value = NetworkToHost(bytes); return true; } bool cByteBuffer::ReadBEUInt32(UInt32 & a_Value) { CHECK_THREAD CheckValid(); NEEDBYTES(4); Bytes bytes; ReadBuf(bytes.data(), bytes.size()); a_Value = NetworkToHost(bytes); return true; } bool cByteBuffer::ReadBEInt64(Int64 & a_Value) { CHECK_THREAD CheckValid(); NEEDBYTES(8); Bytes bytes; ReadBuf(bytes.data(), bytes.size()); a_Value = NetworkToHost(bytes); return true; } bool cByteBuffer::ReadBEUInt64(UInt64 & a_Value) { CHECK_THREAD CheckValid(); NEEDBYTES(8); Bytes bytes; ReadBuf(bytes.data(), bytes.size()); a_Value = NetworkToHost(bytes); return true; } bool cByteBuffer::ReadBEFloat(float & a_Value) { CHECK_THREAD CheckValid(); NEEDBYTES(4); Bytes bytes; ReadBuf(bytes.data(), bytes.size()); a_Value = NetworkToHost(bytes); return true; } bool cByteBuffer::ReadBEDouble(double & a_Value) { CHECK_THREAD CheckValid(); NEEDBYTES(8); Bytes bytes; ReadBuf(bytes.data(), bytes.size()); a_Value = NetworkToHost(bytes); return true; } bool cByteBuffer::ReadBool(bool & a_Value) { CHECK_THREAD CheckValid(); NEEDBYTES(1); UInt8 Value = 0; ReadBuf(&Value, 1); a_Value = (Value != 0); return true; } bool cByteBuffer::ReadVarInt32(UInt32 & a_Value) { CHECK_THREAD CheckValid(); UInt32 Value = 0; std::size_t Shift = 0; unsigned char CurrentByte = 0; do { NEEDBYTES(1); ReadBuf(&CurrentByte, 1); Value |= ((static_cast(CurrentByte & VarInt::SEGMENT_BITS)) << Shift); Shift += VarInt::MOVE_BITS; } while ((CurrentByte & VarInt::CONTINUE_BIT) != 0); a_Value = Value; return true; } bool cByteBuffer::ReadVarInt64(UInt64 & a_Value) { CHECK_THREAD CheckValid(); UInt64 Value = 0; int Shift = 0; unsigned char b = 0; do { NEEDBYTES(1); ReadBuf(&b, 1); Value = Value | ((static_cast(b & VarInt::SEGMENT_BITS)) << Shift); Shift += 7; } while ((b & VarInt::CONTINUE_BIT) != 0); a_Value = Value; return true; } bool cByteBuffer::ReadVarUTF8String(AString & a_Value) { CHECK_THREAD CheckValid(); UInt32 Size = 0; if (!ReadVarInt(Size)) { return false; } if (Size > MAX_STRING_SIZE) { LOGWARNING("%s: String too large: %u (%u KiB)", __FUNCTION__, Size, Size / 1024); } ContiguousByteBuffer Buffer; if (!ReadSome(Buffer, static_cast(Size))) { return false; } // "Convert" a UTF-8 encoded string into system-native char. // This isn't great, better would be to use codecvt: a_Value = { reinterpret_cast(Buffer.data()), Buffer.size() }; return true; } bool cByteBuffer::ReadLEInt(int & a_Value) { CHECK_THREAD CheckValid(); NEEDBYTES(4); ReadBuf(&a_Value, 4); #ifdef IS_BIG_ENDIAN // Convert: a_Value = ((a_Value >> 24) & 0xff) | ((a_Value >> 16) & 0xff00) | ((a_Value >> 8) & 0xff0000) | (a_Value & 0xff000000); #endif return true; } bool cByteBuffer::ReadXYZPosition64(int & a_BlockX, int & a_BlockY, int & a_BlockZ) { CHECK_THREAD UInt64 Value; if (!ReadBEUInt64(Value)) { return false; } // Convert the 64 received bits into 3 coords: UInt32 BlockXRaw = (Value >> XYZPosition::BIT_COUNT_X) & Position::BIT_MASK_XZ; UInt32 BlockYRaw = (Value >> XYZPosition::BIT_COUNT_Y) & Position::BIT_MASK_Y; UInt32 BlockZRaw = (Value & Position::BIT_MASK_XZ); // If the highest bit in the number's range is set, convert the number into negative: a_BlockX = ((BlockXRaw & Position::BIT_MASK_IS_NEGATIVE_XZ) == 0) ? static_cast(BlockXRaw) : -(Position::NEGATIVE_OFFSET_XZ - static_cast(BlockXRaw)); a_BlockY = ((BlockYRaw & Position::BIT_MASK_IS_NEGATIVE_Y) == 0) ? static_cast(BlockYRaw) : -(Position::NEGATIVE_OFFSET_Y - static_cast(BlockYRaw)); a_BlockZ = ((BlockZRaw & Position::BIT_MASK_IS_NEGATIVE_XZ) == 0) ? static_cast(BlockZRaw) : -(Position::NEGATIVE_OFFSET_XZ - static_cast(BlockZRaw)); return true; } bool cByteBuffer::ReadXYZPosition64(Vector3i & a_Position) { return ReadXYZPosition64(a_Position.x, a_Position.y, a_Position.z); } bool cByteBuffer::ReadXZYPosition64(int & a_BlockX, int & a_BlockY, int & a_BlockZ) { CHECK_THREAD UInt64 Value; if (!ReadBEUInt64(Value)) { return false; } // Convert the 64 received bits into 3 coords: UInt32 BlockXRaw = (Value >> XZYPosition::BIT_COUNT_X) & Position::BIT_MASK_XZ; UInt32 BlockZRaw = (Value >> XZYPosition::BIT_COUNT_Z) & Position::BIT_MASK_XZ; UInt32 BlockYRaw = (Value & Position::BIT_MASK_Y); // If the highest bit in the number's range is set, convert the number into negative: a_BlockX = ((BlockXRaw & Position::BIT_MASK_IS_NEGATIVE_XZ) == 0) ? static_cast(BlockXRaw) : (static_cast(BlockXRaw) - Position::NEGATIVE_OFFSET_XZ); a_BlockY = ((BlockYRaw & Position::BIT_MASK_IS_NEGATIVE_Y) == 0) ? static_cast(BlockYRaw) : (static_cast(BlockYRaw) - Position::NEGATIVE_OFFSET_Y); a_BlockZ = ((BlockZRaw & Position::BIT_MASK_IS_NEGATIVE_XZ) == 0) ? static_cast(BlockZRaw) : (static_cast(BlockZRaw) - Position::NEGATIVE_OFFSET_XZ); return true; } bool cByteBuffer::ReadXZYPosition64(Vector3i & a_Position) { return ReadXZYPosition64(a_Position.x, a_Position.y, a_Position.z); } bool cByteBuffer::ReadUUID(cUUID & a_Value) { CHECK_THREAD std::array UUIDBuf; if (!ReadBuf(UUIDBuf.data(), UUIDBuf.size())) { return false; } a_Value.FromRaw(UUIDBuf); return true; } bool cByteBuffer::WriteBEInt8(Int8 a_Value) { CHECK_THREAD CheckValid(); PUTBYTES(1); return WriteBuf(&a_Value, 1); } bool cByteBuffer::WriteBEInt8(const std::byte a_Value) { CHECK_THREAD CheckValid(); PUTBYTES(1); return WriteBuf(&a_Value, 1); } bool cByteBuffer::WriteBEUInt8(UInt8 a_Value) { CHECK_THREAD CheckValid(); PUTBYTES(1); return WriteBuf(&a_Value, 1); } bool cByteBuffer::WriteBEInt16(Int16 a_Value) { CHECK_THREAD CheckValid(); PUTBYTES(2); auto Converted = HostToNetwork(a_Value); return WriteBuf(Converted.data(), Converted.size()); } bool cByteBuffer::WriteBEUInt16(UInt16 a_Value) { CHECK_THREAD CheckValid(); PUTBYTES(2); auto Converted = HostToNetwork(a_Value); return WriteBuf(Converted.data(), Converted.size()); } bool cByteBuffer::WriteBEInt32(Int32 a_Value) { CHECK_THREAD CheckValid(); PUTBYTES(4); auto Converted = HostToNetwork(a_Value); return WriteBuf(Converted.data(), Converted.size()); } bool cByteBuffer::WriteBEUInt32(UInt32 a_Value) { CHECK_THREAD CheckValid(); PUTBYTES(4); auto Converted = HostToNetwork(a_Value); return WriteBuf(Converted.data(), Converted.size()); } bool cByteBuffer::WriteBEInt64(Int64 a_Value) { CHECK_THREAD CheckValid(); PUTBYTES(8); auto Converted = HostToNetwork(a_Value); return WriteBuf(Converted.data(), Converted.size()); } bool cByteBuffer::WriteBEUInt64(UInt64 a_Value) { CHECK_THREAD CheckValid(); PUTBYTES(8); auto Converted = HostToNetwork(a_Value); return WriteBuf(Converted.data(), Converted.size()); } bool cByteBuffer::WriteBEFloat(float a_Value) { CHECK_THREAD CheckValid(); PUTBYTES(4); auto Converted = HostToNetwork(a_Value); return WriteBuf(Converted.data(), Converted.size()); } bool cByteBuffer::WriteBEDouble(double a_Value) { CHECK_THREAD CheckValid(); PUTBYTES(8); auto Converted = HostToNetwork(a_Value); return WriteBuf(Converted.data(), Converted.size()); } bool cByteBuffer::WriteBool(bool a_Value) { CHECK_THREAD CheckValid(); UInt8 val = a_Value ? 1 : 0; return Write(&val, 1); } bool cByteBuffer::WriteVarInt32(UInt32 a_Value) { CHECK_THREAD CheckValid(); // A 32-bit integer can be encoded by at most 5 bytes: std::array Buffer = {}; std::size_t Pos = 0; do { // Write to buffer either the raw 7 lsb or the 7 lsb and a bit that indicates the number continues Buffer[Pos] = ((a_Value & VarInt::SEGMENT_BITS) | ((a_Value > VarInt::SEGMENT_BITS) ? VarInt::CONTINUE_BIT : 0x00)); a_Value >>= VarInt::MOVE_BITS; Pos++; } while (a_Value > 0); return WriteBuf(Buffer.data(), Pos); } bool cByteBuffer::WriteVarInt64(UInt64 a_Value) { CHECK_THREAD CheckValid(); // A 64-bit integer can be encoded by at most 10 bytes: std::array Buffer = {}; std::size_t Pos = 0; do { // Write to buffer either the raw 7 lsb or the 7 lsb and a bit that indicates the number continues Buffer[Pos] = (a_Value & VarInt::SEGMENT_BITS) | ((a_Value > VarInt::SEGMENT_BITS) ? VarInt::CONTINUE_BIT : 0x00); a_Value = a_Value >> VarInt::MOVE_BITS; Pos++; } while (a_Value > 0); return WriteBuf(Buffer.data(), Pos); } bool cByteBuffer::WriteVarUTF8String(const std::string_view & a_Value) { CHECK_THREAD CheckValid(); PUTBYTES(a_Value.size() + 1); // This is a lower-bound on the bytes that will be actually written. Fail early. if (!WriteVarInt32(static_cast(a_Value.size()))) { return false; } return WriteBuf(a_Value.data(), a_Value.size()); } bool cByteBuffer::WriteXYZPosition64(Int32 a_BlockX, Int32 a_BlockY, Int32 a_BlockZ) { CHECK_THREAD CheckValid(); return WriteBEUInt64( ((static_cast(a_BlockX) & Position::BIT_MASK_XZ) << XYZPosition::BIT_COUNT_X) | ((static_cast(a_BlockY) & Position::BIT_MASK_Y) << XYZPosition::BIT_COUNT_Y) | (static_cast(a_BlockZ) & Position::BIT_MASK_XZ) ); } bool cByteBuffer::WriteXZYPosition64(Int32 a_BlockX, Int32 a_BlockY, Int32 a_BlockZ) { CHECK_THREAD CheckValid(); return WriteBEUInt64( ((static_cast(a_BlockX) & Position::BIT_MASK_XZ) << XZYPosition::BIT_COUNT_X) | ((static_cast(a_BlockZ) & Position::BIT_MASK_XZ) << XZYPosition::BIT_COUNT_Z) | (static_cast(a_BlockY) & Position::BIT_MASK_Y) ); } bool cByteBuffer::ReadBuf(void * a_Buffer, size_t a_Count) { CHECK_THREAD CheckValid(); NEEDBYTES(a_Count); auto Dst = static_cast(a_Buffer); // So that we can do byte math ASSERT(m_BufferSize >= m_ReadPos); size_t BytesToEndOfBuffer = m_BufferSize - m_ReadPos; if (BytesToEndOfBuffer <= a_Count) { // Reading across the ringbuffer end, read the first part and adjust parameters: if (BytesToEndOfBuffer > 0) { memcpy(Dst, m_Buffer.get() + m_ReadPos, BytesToEndOfBuffer); Dst += BytesToEndOfBuffer; a_Count -= BytesToEndOfBuffer; } m_ReadPos = 0; } // Read the rest of the bytes in a single read (guaranteed to fit): if (a_Count > 0) { memcpy(Dst, m_Buffer.get() + m_ReadPos, a_Count); m_ReadPos += a_Count; } return true; } bool cByteBuffer::WriteBuf(const void * a_Buffer, size_t a_Count) { CHECK_THREAD CheckValid(); PUTBYTES(a_Count); auto Src = static_cast(a_Buffer); // So that we can do byte math ASSERT(m_BufferSize >= m_ReadPos); size_t BytesToEndOfBuffer = m_BufferSize - m_WritePos; if (BytesToEndOfBuffer <= a_Count) { // Reading across the ringbuffer end, read the first part and adjust parameters: memcpy(m_Buffer.get() + m_WritePos, Src, BytesToEndOfBuffer); Src += BytesToEndOfBuffer; a_Count -= BytesToEndOfBuffer; m_WritePos = 0; } // Read the rest of the bytes in a single read (guaranteed to fit): if (a_Count > 0) { memcpy(m_Buffer.get() + m_WritePos, Src, a_Count); m_WritePos += a_Count; } return true; } bool cByteBuffer::WriteBuf(size_t a_Count, unsigned char a_Value) { CHECK_THREAD CheckValid(); PUTBYTES(a_Count); ASSERT(m_BufferSize >= m_ReadPos); size_t BytesToEndOfBuffer = m_BufferSize - m_WritePos; if (BytesToEndOfBuffer <= a_Count) { // Reading across the ringbuffer end, read the first part and adjust parameters: memset(m_Buffer.get() + m_WritePos, a_Value, BytesToEndOfBuffer); a_Count -= BytesToEndOfBuffer; m_WritePos = 0; } // Read the rest of the bytes in a single read (guaranteed to fit): if (a_Count > 0) { memset(m_Buffer.get() + m_WritePos, a_Value, a_Count); m_WritePos += a_Count; } return true; } bool cByteBuffer::ReadSome(ContiguousByteBuffer & a_String, size_t a_Count) { CHECK_THREAD CheckValid(); NEEDBYTES(a_Count); a_String.clear(); a_String.reserve(a_Count); ASSERT(m_BufferSize >= m_ReadPos); size_t BytesToEndOfBuffer = m_BufferSize - m_ReadPos; if (BytesToEndOfBuffer <= a_Count) { // Reading across the ringbuffer end, read the first part and adjust parameters: if (BytesToEndOfBuffer > 0) { a_String.assign(m_Buffer.get() + m_ReadPos, BytesToEndOfBuffer); ASSERT(a_Count >= BytesToEndOfBuffer); a_Count -= BytesToEndOfBuffer; } m_ReadPos = 0; } // Read the rest of the bytes in a single read (guaranteed to fit): if (a_Count > 0) { a_String.append(m_Buffer.get() + m_ReadPos, a_Count); m_ReadPos += a_Count; } return true; } bool cByteBuffer::SkipRead(size_t a_Count) { CHECK_THREAD CheckValid(); if (!CanReadBytes(a_Count)) { return false; } AdvanceReadPos(a_Count); return true; } void cByteBuffer::ReadAll(ContiguousByteBuffer & a_Data) { CHECK_THREAD CheckValid(); ReadSome(a_Data, GetReadableSpace()); } bool cByteBuffer::ReadToByteBuffer(cByteBuffer & a_Dst, size_t a_NumBytes) { CHECK_THREAD if (!a_Dst.CanWriteBytes(a_NumBytes) || !CanReadBytes(a_NumBytes)) { // There's not enough source bytes or space in the dest BB return false; } char buf[1024]; // > 0 without generating warnings about unsigned comparisons where size_t is unsigned while (a_NumBytes != 0) { size_t num = (a_NumBytes > sizeof(buf)) ? sizeof(buf) : a_NumBytes; VERIFY(ReadBuf(buf, num)); VERIFY(a_Dst.Write(buf, num)); ASSERT(a_NumBytes >= num); a_NumBytes -= num; } return true; } void cByteBuffer::CommitRead(void) { CHECK_THREAD CheckValid(); m_DataStart = m_ReadPos; } void cByteBuffer::ResetRead(void) { CHECK_THREAD CheckValid(); m_ReadPos = m_DataStart; } void cByteBuffer::ReadAgain(ContiguousByteBuffer & a_Out) const { // Return the data between m_DataStart and m_ReadPos (the data that has been read but not committed) // Used by ProtoProxy to repeat communication twice, once for parsing and the other time for the remote party CHECK_THREAD CheckValid(); size_t DataStart = m_DataStart; if (m_ReadPos < m_DataStart) { // Across the ringbuffer end, read the first part and adjust next part's start: ASSERT(m_BufferSize >= m_DataStart); a_Out.append(m_Buffer.get() + m_DataStart, m_BufferSize - m_DataStart); DataStart = 0; } ASSERT(m_ReadPos >= DataStart); a_Out.append(m_Buffer.get() + DataStart, m_ReadPos - DataStart); } void cByteBuffer::AdvanceReadPos(size_t a_Count) { CHECK_THREAD CheckValid(); m_ReadPos += a_Count; if (m_ReadPos >= m_BufferSize) { m_ReadPos -= m_BufferSize; } } void cByteBuffer::CheckValid(void) const { ASSERT(m_ReadPos < m_BufferSize); ASSERT(m_WritePos < m_BufferSize); } size_t cByteBuffer::GetVarIntSize(UInt32 a_Value) { size_t Count = 0; do { // If the value cannot be expressed in 7 bits, it needs to take up another byte Count++; a_Value >>= VarInt::MOVE_BITS; } while (a_Value != 0); return Count; } ================================================ FILE: src/ByteBuffer.h ================================================ // ByteStream.h // Interfaces to the cByteBuffer class representing a ringbuffer of bytes #pragma once // fwd: class cUUID; /** An object that can store incoming bytes and lets its clients read the bytes sequentially The bytes are stored in a ringbuffer of constant size; if more than that size is requested, the write operation fails. The bytes stored can be retrieved using various ReadXXX functions; these assume that the needed number of bytes are present in the buffer (ASSERT; for performance reasons). The reading doesn't actually remove the bytes, it only moves the internal read ptr. To remove the bytes, call CommitRead(). To re-start reading from the beginning, call ResetRead(). This class doesn't implement thread safety, the clients of this class need to provide their own synchronization. */ class cByteBuffer { public: explicit cByteBuffer(size_t a_BufferSize); ~cByteBuffer(); /** cByteBuffer should not be copied or moved. Use ReadToByteBuffer instead. */ cByteBuffer(const cByteBuffer & a_ByteBuffer) = delete; cByteBuffer(cByteBuffer && a_ByteBuffer) = delete; /** Writes the bytes specified to the ringbuffer. Returns true if successful, false if not */ bool Write(const void * a_Bytes, size_t a_Count); /** Returns the number of bytes that can be successfully written to the ringbuffer */ size_t GetFreeSpace(void) const; /** Returns the number of bytes that are currently in the ringbuffer. Note GetReadableBytes() */ size_t GetUsedSpace(void) const; /** Returns the number of bytes that are currently available for reading (may be less than UsedSpace due to some data having been read already) */ size_t GetReadableSpace(void) const; /** Returns the current data start index. For debugging purposes. */ size_t GetDataStart(void) const { return m_DataStart; } /** Returns if the given value can fit in a protocol big-endian 8 bit integer. */ static bool CanBEInt8Represent(int a_Value); /** Returns if the given value can fit in a protocol big-endian 16 bit integer. */ static bool CanBEInt16Represent(int a_Value); /** Returns true if the specified amount of bytes are available for reading */ bool CanReadBytes(size_t a_Count) const; /** Returns true if the specified amount of bytes are available for writing */ bool CanWriteBytes(size_t a_Count) const; // Read the specified datatype and advance the read pointer; return true if successfully read: bool ReadBEInt8 (Int8 & a_Value); bool ReadBEInt16 (Int16 & a_Value); bool ReadBEInt32 (Int32 & a_Value); bool ReadBEInt64 (Int64 & a_Value); bool ReadBEUInt8 (UInt8 & a_Value); bool ReadBEUInt16 (UInt16 & a_Value); bool ReadBEUInt32 (UInt32 & a_Value); bool ReadBEUInt64 (UInt64 & a_Value); bool ReadBEFloat (float & a_Value); bool ReadBEDouble (double & a_Value); bool ReadBool (bool & a_Value); bool ReadVarInt32 (UInt32 & a_Value); bool ReadVarInt64 (UInt64 & a_Value); bool ReadVarUTF8String (AString & a_Value); // string length as VarInt, then string as UTF-8 bool ReadLEInt (int & a_Value); bool ReadXYZPosition64 (int & a_BlockX, int & a_BlockY, int & a_BlockZ); bool ReadXYZPosition64 (Vector3i & a_Position); bool ReadXZYPosition64 (int & a_BlockX, int & a_BlockY, int & a_BlockZ); bool ReadXZYPosition64 (Vector3i & a_Position); bool ReadUUID (cUUID & a_Value); /** Reads VarInt, assigns it to anything that can be assigned from an UInt64 (unsigned short, char, Byte, double, ...) */ template bool ReadVarInt(T & a_Value) { UInt64 v; bool res = ReadVarInt64(v); if (res) { a_Value = static_cast(v); } return res; } // Write the specified datatype; return true if successfully written bool WriteBEInt8 (Int8 a_Value); bool WriteBEInt8 (std::byte a_Value); bool WriteBEInt16 (Int16 a_Value); bool WriteBEInt32 (Int32 a_Value); bool WriteBEInt64 (Int64 a_Value); bool WriteBEUInt8 (UInt8 a_Value); bool WriteBEUInt16 (UInt16 a_Value); bool WriteBEUInt32 (UInt32 a_Value); bool WriteBEUInt64 (UInt64 a_Value); bool WriteBEFloat (float a_Value); bool WriteBEDouble (double a_Value); bool WriteBool (bool a_Value); bool WriteVarInt32 (UInt32 a_Value); bool WriteVarInt64 (UInt64 a_Value); bool WriteVarUTF8String (const std::string_view & a_Value); // string length as VarInt, then string as UTF-8 bool WriteXYZPosition64 (Int32 a_BlockX, Int32 a_BlockY, Int32 a_BlockZ); bool WriteXZYPosition64 (Int32 a_BlockX, Int32 a_BlockY, Int32 a_BlockZ); /** Reads a_Count bytes into a_Buffer; returns true if successful */ bool ReadBuf(void * a_Buffer, size_t a_Count); /** Writes a_Count bytes into a_Buffer; returns true if successful */ bool WriteBuf(const void * a_Buffer, size_t a_Count); /** Writes a_Count bytes into a_Buffer; returns true if successful */ bool WriteBuf(size_t a_Count, unsigned char a_Value); /** Reads a_Count bytes into a_String; returns true if successful */ bool ReadSome(ContiguousByteBuffer & a_String, size_t a_Count); /** Skips reading by a_Count bytes; returns false if not enough bytes in the ringbuffer */ bool SkipRead(size_t a_Count); /** Reads all available data into a_Data */ void ReadAll(ContiguousByteBuffer & a_Data); /** Reads the specified number of bytes and writes it into the destination bytebuffer. Returns true on success. */ bool ReadToByteBuffer(cByteBuffer & a_Dst, size_t a_NumBytes); /** Removes the bytes that have been read from the ringbuffer */ void CommitRead(void); /** Restarts next reading operation at the start of the ringbuffer */ void ResetRead(void); /** Re-reads the data that has been read since the last commit to the current readpos. Used by ProtoProxy to duplicate communication */ void ReadAgain(ContiguousByteBuffer & a_Out) const; /** Checks if the internal state is valid (read and write positions in the correct bounds) using ASSERTs */ void CheckValid(void) const; /** Gets the number of bytes that are needed to represent the given VarInt */ static size_t GetVarIntSize(UInt32 a_Value); protected: std::unique_ptr m_Buffer; size_t m_BufferSize; // Total size of the ringbuffer size_t m_DataStart = 0; // Where the data starts in the ringbuffer size_t m_WritePos = 0; // Where the data ends in the ringbuffer size_t m_ReadPos = 0; // Where the next read will start in the ringbuffer #ifndef NDEBUG /** The ID of the thread currently accessing the object. Used for checking that only one thread accesses the object at a time, via cSingleThreadAccessChecker. */ mutable std::thread::id m_ThreadID; #endif /** Advances the m_ReadPos by a_Count bytes */ void AdvanceReadPos(size_t a_Count); } ; ================================================ FILE: src/CMakeLists.txt ================================================ target_sources( ${CMAKE_PROJECT_NAME} PRIVATE Resources/Cuberite.rc BiomeDef.cpp BlockArea.cpp BlockInfo.cpp BlockType.cpp BrewingRecipes.cpp Broadcaster.cpp BoundingBox.cpp ByteBuffer.cpp ChatColor.cpp Chunk.cpp ChunkData.cpp ChunkGeneratorThread.cpp ChunkMap.cpp ChunkSender.cpp ChunkStay.cpp CircularBufferCompressor.cpp ClientHandle.cpp Color.cpp CommandOutput.cpp CompositeChat.cpp CraftingRecipes.cpp Cuboid.cpp DeadlockDetect.cpp Defines.cpp Enchantments.cpp FastRandom.cpp FurnaceRecipe.cpp Globals.cpp IniFile.cpp Inventory.cpp Item.cpp ItemGrid.cpp JsonUtils.cpp LightingThread.cpp LineBlockTracer.cpp LinearInterpolation.cpp LoggerListeners.cpp Logger.cpp Map.cpp MapManager.cpp MemorySettingsRepository.cpp MobCensus.cpp MobFamilyCollecter.cpp MobProximityCounter.cpp MobSpawner.cpp MonsterConfig.cpp NetherPortalScanner.cpp OverridesSettingsRepository.cpp ProbabDistrib.cpp RankManager.cpp RCONServer.cpp Root.cpp Scoreboard.cpp Server.cpp SetChunkData.cpp SpawnPrepare.cpp StatisticsManager.cpp StringCompression.cpp StringUtils.cpp UUID.cpp VoronoiMap.cpp WebAdmin.cpp World.cpp main.cpp BiomeDef.h BlockArea.h BlockInServerPluginInterface.h BlockInfo.h BlockState.h BlockTracer.h BlockType.h BrewingRecipes.h BoundingBox.h BuildInfo.h.cmake ByteBuffer.h ChatColor.h Chunk.h ChunkData.h ChunkDataCallback.h ChunkDef.h ChunkGeneratorThread.h ChunkMap.h ChunkSender.h ChunkStay.h CircularBufferCompressor.h ClientHandle.h Color.h CommandOutput.h CompositeChat.h CraftingRecipes.h Cuboid.h DeadlockDetect.h Defines.h EffectID.h Enchantments.h Endianness.h FastRandom.h ForEachChunkProvider.h FurnaceRecipe.h FunctionRef.h Globals.h IniFile.h Inventory.h Item.h ItemGrid.h LazyArray.h JsonUtils.h LightingThread.h LineBlockTracer.h LinearInterpolation.h LinearUpscale.h Logger.h LoggerListeners.h LoggerSimple.h Map.h MapManager.h Matrix4.h MemorySettingsRepository.h MobCensus.h MobFamilyCollecter.h MobProximityCounter.h MobSpawner.h MonsterConfig.h NetherPortalScanner.h OpaqueWorld.h OverridesSettingsRepository.h ProbabDistrib.h RankManager.h RCONServer.h Root.h Scoreboard.h Server.h SetChunkData.h SettingsRepositoryInterface.h SpawnPrepare.h StatisticsManager.h StringCompression.h StringUtils.h UUID.h Vector3.h VoronoiMap.h WebAdmin.h World.h XMLParser.h main.h ) set(FOLDERS Bindings BlockEntities Blocks Entities Generating HTTP Items mbedTLS++ Mobs Noise OSSupport Physics Protocol Registries Simulator Simulator/IncrementalRedstoneSimulator UI WorldStorage ) # Add all child source directories: foreach(folder ${FOLDERS}) add_subdirectory(${folder}) endforeach(folder) file(WRITE "${CMAKE_BINARY_DIR}/include/Globals.h" "/* This file allows Globals.h to be included with an absolute path */\n#include \"${PROJECT_SOURCE_DIR}/src/Globals.h\"\n") configure_file("BuildInfo.h.cmake" "${CMAKE_BINARY_DIR}/include/BuildInfo.h") target_include_directories(${CMAKE_PROJECT_NAME} PRIVATE "${CMAKE_BINARY_DIR}/include/" ".") # Generate AllFiles.lst for CheckBasicStyle.lua get_target_property(ALL_FILES ${CMAKE_PROJECT_NAME} SOURCES) foreach(FILE ${ALL_FILES}) # target_sources converts to absolute but CheckBasicStyle expects relative file(RELATIVE_PATH RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" ${FILE}) # Convert CMake list into newline-delimited string set(ALL_FILES_AS_LINES "${ALL_FILES_AS_LINES}${RELATIVE}\n") endforeach() file(WRITE AllFiles.lst "${ALL_FILES_AS_LINES}") # Output the executable into the $/Server folder, so that it has access to external resources: SET_TARGET_PROPERTIES(${CMAKE_PROJECT_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/Server RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/Server RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/Server RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_BINARY_DIR}/Server RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL ${CMAKE_BINARY_DIR}/Server RUNTIME_OUTPUT_DIRECTORY_DEBUGPROFILE ${CMAKE_BINARY_DIR}/Server RUNTIME_OUTPUT_DIRECTORY_RELEASEPROFILE ${CMAKE_BINARY_DIR}/Server ) # Enable "-rdynamic" on Linux, so that external Lua modules can import Lua API symbols from the main executable: # ( https://stackoverflow.com/questions/24015025/resolving-symbols-in-shared-object-to-executable ) if (NOT WIN32) target_link_options(${CMAKE_PROJECT_NAME} PRIVATE "-rdynamic") endif() MACRO(TO_NATIVE_PATH PATH OUT) FILE(TO_NATIVE_PATH "${PATH}" "${OUT}") IF(MINGW) STRING(REPLACE "/" "\\" "${OUT}" "${${OUT}}") ENDIF(MINGW) ENDMACRO(TO_NATIVE_PATH) # Create a symbolic link from ${orig} to ${link} # If the orig and link point to the same thing, does nothing (-> in-source build) # If ${link} already exists, does nothing. function(make_symlink orig link) # If both are the same, or link already exists, bail out: if ("${orig}" STREQUAL "${link}") return() endif() if (EXISTS ${link}) return() endif() # Create the symlink (platform-dependent): message(STATUS "Creating symlink, orig = ${orig}; link = ${link}") if (CMAKE_HOST_UNIX) set(command ln -s ${orig} ${link}) else() TO_NATIVE_PATH("${orig}" orig) TO_NATIVE_PATH("${link}" link) if (IS_DIRECTORY ${orig}) set(command cmd.exe /c mklink /j ${link} ${orig}) else() set(command cmd.exe /c mklink /h ${link} ${orig}) endif() endif() execute_process( COMMAND ${command} RESULT_VARIABLE result ERROR_VARIABLE stderr OUTPUT_VARIABLE stdout ) if (NOT ${result} EQUAL 0) message(FATAL_ERROR "Could not create symbolic link for: ${link} --> ${orig}: ${stderr} ${stdout}") endif() endfunction(make_symlink) # Populate the output folder with symlinks to the Server folder's internals: set(symlinks Install Plugins Prefabs Protocol webadmin brewing.txt crafting.txt favicon.png furnace.txt items.ini monsters.ini README.txt ) message(STATUS "Creating output folder and symlinks...") file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/Server") foreach (symlink ${symlinks}) make_symlink("${CMAKE_CURRENT_SOURCE_DIR}/../Server/${symlink}" "${CMAKE_BINARY_DIR}/Server/${symlink}") endforeach(symlink) make_symlink("${CMAKE_CURRENT_SOURCE_DIR}/../BACKERS" "${CMAKE_BINARY_DIR}/Server/BACKERS") make_symlink("${CMAKE_CURRENT_SOURCE_DIR}/../CONTRIBUTORS" "${CMAKE_BINARY_DIR}/Server/CONTRIBUTORS") make_symlink("${CMAKE_CURRENT_SOURCE_DIR}/../LICENSE" "${CMAKE_BINARY_DIR}/Server/LICENSE") make_symlink("${CMAKE_CURRENT_SOURCE_DIR}/../Server/Install/ThirdPartyLicenses" "${CMAKE_BINARY_DIR}/Server/ThirdPartyLicenses") # Create a folder for Bindings' documentation: FILE(MAKE_DIRECTORY "Bindings/docs") make_symlink("${CMAKE_CURRENT_SOURCE_DIR}/Bindings/docs" "${CMAKE_BINARY_DIR}/Server/BindingsDocs") ================================================ FILE: src/ChatColor.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "ChatColor.h" const char * cChatColor::Color = "\xc2\xa7"; // The paragraph / section symbol in UTF-8 const char * cChatColor::Delimiter = "\xc2\xa7"; // The paragraph / section symbol in UTF-8 const char * cChatColor::Black = "\xc2\xa7""0"; const char * cChatColor::Navy = "\xc2\xa7""1"; const char * cChatColor::Green = "\xc2\xa7""2"; const char * cChatColor::Blue = "\xc2\xa7""3"; const char * cChatColor::Red = "\xc2\xa7""4"; const char * cChatColor::Purple = "\xc2\xa7""5"; const char * cChatColor::Gold = "\xc2\xa7""6"; const char * cChatColor::LightGray = "\xc2\xa7""7"; const char * cChatColor::Gray = "\xc2\xa7""8"; const char * cChatColor::DarkPurple = "\xc2\xa7""9"; const char * cChatColor::LightGreen = "\xc2\xa7""a"; const char * cChatColor::LightBlue = "\xc2\xa7""b"; const char * cChatColor::Rose = "\xc2\xa7""c"; const char * cChatColor::LightPurple = "\xc2\xa7""d"; const char * cChatColor::Yellow = "\xc2\xa7""e"; const char * cChatColor::White = "\xc2\xa7""f"; const char * cChatColor::Random = "\xc2\xa7""k"; const char * cChatColor::Bold = "\xc2\xa7""l"; const char * cChatColor::Strikethrough = "\xc2\xa7""m"; const char * cChatColor::Underlined = "\xc2\xa7""n"; const char * cChatColor::Italic = "\xc2\xa7""o"; const char * cChatColor::Plain = "\xc2\xa7""r"; ================================================ FILE: src/ChatColor.h ================================================ #pragma once // tolua_begin class cChatColor { public: static const char * Delimiter; /** @deprecated use ChatColor::Delimiter instead */ static const char * Color; static const char * Black; static const char * Navy; static const char * Green; static const char * Blue; static const char * Red; static const char * Purple; static const char * Gold; static const char * LightGray; static const char * Gray; static const char * DarkPurple; static const char * LightGreen; static const char * LightBlue; static const char * Rose; static const char * LightPurple; static const char * Yellow; static const char * White; // Styles // source: http://wiki.vg/Chat static const char * Random; static const char * Bold; static const char * Strikethrough; static const char * Underlined; static const char * Italic; static const char * Plain; }; // tolua_end ================================================ FILE: src/CheckBasicStyle.lua ================================================ #!/usr/bin/env lua -- CheckBasicStyle.lua --[[ Checks that all source files (*.cpp, *.h) use the basic style requirements of the project: - Tabs for indentation, spaces for alignment - Trailing whitespace on non-empty lines - Two spaces between code and line-end comment ("//") - Spaces after comma, not before - Opening braces not at the end of a code line - Spaces after if, for, while - Line dividers (////...) exactly 80 slashes - Multi-level indent change - (TODO) Spaces before *, /, & - (TODO) Hex numbers with even digit length - (TODO) Hex numbers in lowercase - (TODO) Not using "* "-style doxy comment continuation lines Violations that cannot be checked easily: - Spaces around "+" (there are things like "a++", "++a", "a += 1", "X+", "stack +1" and ascii-drawn tables) Reports all violations on stdout in a form that is readable by Visual Studio's parser, so that dblclicking the line brings the editor directly to the violation. Returns 0 on success, 1 on internal failure, 2 if any violations found --]] -- The list of file extensions that are processed: local g_ShouldProcessExt = { ["h"] = true, ["cpp"] = true, } --- The list of files not to be processed: local g_IgnoredFiles = { "Bindings/Bindings.cpp", "Bindings/Bindings.h", "Bindings/LuaState_Implementation.cpp", "Registries/BlockStates.cpp", "Registries/BlockStates.h" } --- The list of files not to be processed, as a dictionary (filename => true), built from g_IgnoredFiles local g_ShouldIgnoreFile = {} -- Initialize the g_ShouldIgnoreFile map: for _, fnam in ipairs(g_IgnoredFiles) do g_ShouldIgnoreFile[fnam] = true end --- Keeps track of the number of violations for this folder local g_NumViolations = 0 --- Reports one violation -- Pretty-prints the message -- Also increments g_NumViolations local function ReportViolation(a_FileName, a_LineNumber, a_PatStart, a_PatEnd, a_Message) print(a_FileName .. "(" .. a_LineNumber .. "): " .. a_PatStart .. " .. " .. a_PatEnd .. ": " .. a_Message) g_NumViolations = g_NumViolations + 1 end --- Searches for the specified pattern, if found, reports it as a violation with the given message local function ReportViolationIfFound(a_Line, a_FileName, a_LineNum, a_Pattern, a_Message) local patStart, patEnd = a_Line:find(a_Pattern) if not(patStart) then return end ReportViolation(a_FileName, a_LineNum, patStart, patEnd, a_Message) end local g_ViolationPatterns = { -- Parenthesis around comparisons: {"==[^)]+&&", "Add parenthesis around comparison"}, {"&&[^(]+==", "Add parenthesis around comparison"}, {"==[^)]+||", "Add parenthesis around comparison"}, {"||[^(]+==", "Add parenthesis around comparison"}, {"!=[^)]+&&", "Add parenthesis around comparison"}, {"&&[^(]+!=", "Add parenthesis around comparison"}, {"!=[^)]+||", "Add parenthesis around comparison"}, {"||[^(]+!=", "Add parenthesis around comparison"}, {"<[^)>]*&&", "Add parenthesis around comparison"}, -- Must take special care of templates: "template fn(Args && ...)" -- Cannot check a < following a && due to functions of the form x fn(y&& a, z c) {"<[^)>]*||", "Add parenthesis around comparison"}, -- Must take special care of templates: "template fn(Args && ...)" {"||[^(]+<", "Add parenthesis around comparison"}, -- Cannot check ">" because of "obj->m_Flag &&". Check at least ">=": {">=[^)]+&&", "Add parenthesis around comparison"}, {"&&[^(]+>=", "Add parenthesis around comparison"}, {">=[^)]+||", "Add parenthesis around comparison"}, {"||[^(]+>=", "Add parenthesis around comparison"}, -- Check against indenting using spaces: {"^\t* +", "Indenting with a space"}, -- Check against alignment using tabs: {"[^%s]\t+[^%s]", "Aligning with a tab"}, -- Check against trailing whitespace: {"%s+\n", "Trailing whitespace or whitespace-only line"}, -- Check that all "//"-style comments have at least two spaces in front (unless alone on line): {"[^%s] //", "Needs at least two spaces in front of a \"//\"-style comment"}, -- Check that all "//"-style comments have at least one spaces after: {"%s//[^%s/*<]", "Needs a space after a \"//\"-style comment"}, -- Check that doxy-comments are used only in the double-asterisk form: {"/// ", "Use doxycomments in the form /** Comment */"}, -- Check that /* */ comments have whitespace around the insides: {"%*%*/", "Wrong comment termination, use */"}, {"/%*[^%s*/\"]", "Needs a space after /*"}, -- Need to take care of the special "//*/" comment ends {"/%*%*[^%s*<]", "Needs a space after /**"}, {"[^%s/*]%*/", "Needs a space before */"}, -- Check against MS XML doxycomments: {"/%*%* <", "Remove the MS XML markers from comment"}, -- Check that all commas have spaces after them and not in front of them: {" ,", "Extra space before a \",\""}, {",[^%s\"%%\']", "Needs a space after a \",\""}, -- Report all except >> "," << needed for splitting and >>,%s<< needed for formatting -- Check that opening braces are not at the end of a code line: {"[^%s].-{\n?$", "Brace should be on a separate line"}, -- Space after keywords: {"[^_]if%(", "Needs a space after \"if\""}, {"%sfor%(", "Needs a space after \"for\""}, {"%swhile%(", "Needs a space after \"while\""}, {"%sswitch%(", "Needs a space after \"switch\""}, {"%scatch%(", "Needs a space after \"catch\""}, {"%stemplate<", "Needs a space after \"template\""}, -- No space after keyword's parenthesis: {"[^%a#]if %( ", "Remove the space after \"(\""}, {"for %( ", "Remove the space after \"(\""}, {"while %( ", "Remove the space after \"(\""}, {"catch %( ", "Remove the space after \"(\""}, -- No space before a closing parenthesis: {" %)", "Remove the space before \")\""}, -- Check spaces around "+": {"^[a-zA-Z0-9]+%+[a-zA-Z0-9]+", "Add space around +"}, {"[!@#$%%%^&*() %[%]\t][a-zA-Z0-9]+%+[a-zA-Z0-9]+", "Add space around +"}, --[[ -- Cannot check these because of text such as "X+" and "+2" appearing in some comments. {"^[a-zA-Z0-9]+ %+[a-zA-Z0-9]+", "Add space after +"}, {"[!@#$%%%^&*() %[%]\t][a-zA-Z0-9]+ %+[a-zA-Z0-9]+", "Add space after +"}, {"^[a-zA-Z0-9]+%+ [a-zA-Z0-9]+", "Add space before +"}, {"[!@#$%%%^&*() %[%]\t][a-zA-Z0-9]+%+ [a-zA-Z0-9]+", "Add space before +"}, --]] -- Cannot check spaces around "-", because the minus is sometimes used as a hyphen between-words -- Check spaces around "*": {"^[a-zA-Z0-9]+%*[a-zA-Z0-9]+", "Add space around *"}, {"^[^\"]*[!@#$%%%^&*() %[%]\t][a-zA-Z0-9]+%*[a-zA-Z0-9]+", "Add space around *"}, {"^[a-zB-Z0-9]+%* [a-zA-Z0-9]+", "Add space before *"}, {"^[^\"]*[!@#$%%%^&*() %[%]\t][a-zB-Z0-9]+%* [a-zA-Z0-9]+", "Add space before *"}, -- Check spaces around "/": {"^[a-zA-Z0-9]+%/[a-zA-Z0-9]+", "Add space around /"}, {"^[^\"]*[!@#$%%%^&*() %[%]\t][a-zA-Z0-9]+%/[a-zA-Z0-9]+", "Add space around /"}, -- Check spaces around "&": {"^[a-zA-Z0-9]+%&[a-zA-Z0-9]+", "Add space around &"}, {"^[^\"]*[!@#$%%%^&*() %[%]\t][a-zA-Z0-9]+%&[a-zA-Z0-9]+", "Add space around &"}, {"^[a-zA-Z0-9]+%& [a-zA-Z0-9]+", "Add space before &"}, {"^[^\"]*[!@#$%%%^&*() %[%]\t][a-zA-Z0-9]+%& [a-zA-Z0-9]+", "Add space before &"}, -- Check spaces around "==", "<=" and ">=": {"==[a-zA-Z0-9]+", "Add space after =="}, {"[a-zA-Z0-9]+==[^\\]", "Add space before =="}, {"<=[a-zA-Z0-9]+", "Add space after <="}, {"[a-zA-Z0-9]+<=", "Add space before <="}, {">=[a-zA-Z0-9]+", "Add space after >="}, {"[a-zA-Z0-9]+>=", "Add space before >="}, -- We don't like "Type const *" and "Type const &". Use "const Type *" and "const Type &" instead: {"const %&", "Use 'const Type &' instead of 'Type const &'"}, {"const %*", "Use 'const Type *' instead of 'Type const *'"}, -- Check if "else" is on the same line as a brace. {"}%s*else", "else has to be on a separate line"}, {"else%s*{", "else has to be on a separate line"}, -- Don't allow characters other than ASCII 0 - 127: {"[" .. string.char(128) .. "-" .. string.char(255) .. "]", "Character in the extended ASCII range (128 - 255) not allowed"}, } --- Processes one file local function ProcessFile(a_FileName) assert(type(a_FileName) == "string") -- Read the whole file: local f, err = io.open(a_FileName, "r") if (f == nil) then print("Cannot open file \"" .. a_FileName .. "\": " .. err) print("Aborting") os.exit(1) end local all = f:read("*all") f:close() -- Check that the last line is empty - otherwise processing won't work properly: local lastChar = string.byte(all, string.len(all)) if ((lastChar ~= 13) and (lastChar ~= 10)) then local numLines = 1 string.gsub(all, "\n", function() numLines = numLines + 1 end) -- Count the number of line-ends ReportViolation(a_FileName, numLines, 1, 1, "Missing empty line at file end") return end -- Process each line separately: -- Ref.: https://stackoverflow.com/questions/10416869/iterate-over-possibly-empty-lines-in-a-way-that-matches-the-expectations-of-exis local lineCounter = 1 local lastIndentLevel = 0 local isLastLineControl = false local lastNonEmptyLine = 0 local isAfterFunction = false local isSourceFile = a_FileName:match("%.cpp") all = all:gsub("\r\n", "\n") -- normalize CRLF into LF-only string.gsub(all .. "\n", "[^\n]*\n", -- Iterate over each line, while preserving empty lines function(a_Line) -- Check against each violation pattern: for _, pat in ipairs(g_ViolationPatterns) do ReportViolationIfFound(a_Line, a_FileName, lineCounter, pat[1], pat[2]) end -- Check that divider comments are well formed - 80 slashes plus optional indent: local dividerStart, dividerEnd = a_Line:find("/////*") if (dividerStart) then if (dividerEnd ~= dividerStart + 79) then ReportViolation(a_FileName, lineCounter, 1, 80, "Divider comment should have exactly 80 slashes") end if (dividerStart > 1) then if ( (a_Line:sub(1, dividerStart - 1) ~= string.rep("\t", dividerStart - 1)) or -- The divider should have only indent in front of it (a_Line:len() > dividerEnd + 1) -- The divider should have no other text following it ) then ReportViolation(a_FileName, lineCounter, 1, 80, "Divider comment shouldn't have any extra text around it") end end end -- Check the indent level change from the last line, if it's too much, report: local indentStart, indentEnd = a_Line:find("\t+") local indentLevel = 0 if (indentStart) then indentLevel = indentEnd - indentStart end if (indentLevel > 0) then if ((lastIndentLevel - indentLevel >= 2) or (lastIndentLevel - indentLevel <= -2)) then ReportViolation(a_FileName, lineCounter, 1, indentStart or 1, "Indent changed more than a single level between the previous line and this one: from " .. lastIndentLevel .. " to " .. indentLevel) end lastIndentLevel = indentLevel end -- Check that control statements have braces on separate lines after them: -- Note that if statements can be broken into multiple lines, in which case this test is not taken if (isLastLineControl) then if not(a_Line:find("^%s*{") or a_Line:find("^%s*#")) then -- Not followed by a brace, not followed by a preprocessor ReportViolation(a_FileName, lineCounter - 1, 1, 1, "Control statement needs a brace on separate line") end end local lineWithSpace = " " .. a_Line isLastLineControl = lineWithSpace:find("^%s+if %b()") or lineWithSpace:find("^%s+else if %b()") or lineWithSpace:find("^%s+for %b()") or lineWithSpace:find("^%s+switch %b()") or lineWithSpace:find("^%s+else\n") or lineWithSpace:find("^%s+else //") or lineWithSpace:find("^%s+do %b()") -- Check that exactly 5 empty lines are left beteen functions and no more than 5 elsewhere if not(a_Line:find("^\n")) then local numEmptyLines = (lineCounter - lastNonEmptyLine) - 1 local isStartOfFunction = ( isAfterFunction and a_Line:find("^[%s%w]") ) if (isSourceFile and isStartOfFunction and (numEmptyLines ~= 5)) then ReportViolation(a_FileName, lineCounter - 1, 1, 1, "Leave exactly 5 empty lines between functions (found " .. numEmptyLines ..")") elseif (numEmptyLines > 5) then ReportViolation(a_FileName, lineCounter - 1, 1, 1, "Leave at most 5 consecutive empty lines (found " .. numEmptyLines .. ")") end lastNonEmptyLine = lineCounter isAfterFunction = (a_Line == "}\n") end lineCounter = lineCounter + 1 end ) end --- Processes one item - a file or a folder local function ProcessItem(a_ItemName) assert(type(a_ItemName) == "string") -- Skip files / folders that should be ignored if (g_ShouldIgnoreFile[a_ItemName]) then return end local ext = a_ItemName:match("%.([^/%.]-)$") if (g_ShouldProcessExt[ext]) then ProcessFile(a_ItemName) end end --- Array of files to process. Filled from cmdline arguments local ToProcess = {} --- Handlers for the command-line arguments -- Maps flag => function local CmdLineHandlers = { -- "-f file" checks the specified file ["-f"] = function (a_Args, a_Idx) local fnam = a_Args[a_Idx + 1] if not(fnam) then error("Invalid flag: '-f' needs a filename following it.") end table.insert(ToProcess, fnam) return a_Idx + 2 -- skip the filename in param parsing end, -- "-g" checks files reported by git as being committed. ["-g"] = function (a_Args, a_Idx) local f = io.popen("git diff --cached --name-only --diff-filter=ACMR") for fnam in f:lines() do table.insert(ToProcess, fnam) end end, -- "-h" prints help and exits ["-h"] = function (a_Args, a_Idx) print([[ Usage:") "CheckBasicStyle [] Available options: -f - checks the specified filename -g - checks files reported by Git as being committed -h - prints this help and exits -l - checks all files listed in the specified listfile -- - reads the list of files to check from stdin When no options are given, the script checks all files listed in the AllFiles.lst file. Only .cpp and .h files are ever checked. ]]) os.exit(0) end, -- "-l listfile" loads the list of files to check from the specified listfile ["-l"] = function (a_Args, a_Idx) local listFile = a_Args[a_Idx + 1] if not(listFile) then error("Invalid flag: '-l' needs a filename following it.") end for fnam in io.lines(listFile) do table.insert(ToProcess, fnam) end return a_Idx + 2 -- Skip the listfile in param parsing end, -- "--" reads the list of files from stdin ["--"] = function (a_Args, a_Idx) for fnam in io.lines() do table.insert(ToProcess, fnam) end end, } -- Remove buffering from stdout, so that the output appears immediately in IDEs: io.stdout:setvbuf("no") -- Parse the cmdline arguments to see what files to check: local idx = 1 while (arg[idx]) do local handler = CmdLineHandlers[arg[idx]] if not(handler) then error("Unknown command-line argument #" .. idx .. ": " .. arg[idx]) end idx = handler(arg, idx) or (idx + 1) -- Call the handler, let it change the next index if it wants end -- By default process all files in the AllFiles.lst file (generated by cmake): if not(arg[1]) then for fnam in io.lines("AllFiles.lst") do table.insert(ToProcess, fnam) end end -- Process the files in the list: for _, fnam in ipairs(ToProcess) do -- Remove the optional "./" prefix: if (fnam:sub(1, 2) == "./") then fnam = fnam:sub(3) end ProcessItem(fnam) end -- Report final verdict: print("Number of violations found: " .. g_NumViolations) if (g_NumViolations > 0) then os.exit(2) else os.exit(0) end ================================================ FILE: src/Chunk.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #ifndef _WIN32 #include #endif #include "Chunk.h" #include "BlockInfo.h" #include "World.h" #include "ClientHandle.h" #include "Server.h" #include "Defines.h" #include "Entities/Pickup.h" #include "Item.h" #include "Noise/Noise.h" #include "Root.h" #include "Entities/Player.h" #include "BlockArea.h" #include "Bindings/PluginManager.h" #include "Blocks/BlockHandler.h" #include "Simulator/FluidSimulator.h" #include "Simulator/RedstoneSimulator.h" #include "MobCensus.h" #include "MobSpawner.h" #include "BlockInServerPluginInterface.h" #include "SetChunkData.h" #include "BoundingBox.h" #include "Blocks/ChunkInterface.h" #include "json/json.h" //////////////////////////////////////////////////////////////////////////////// // cChunk: cChunk::cChunk( int a_ChunkX, int a_ChunkZ, cChunkMap * a_ChunkMap, cWorld * a_World ): m_Presence(cpInvalid), m_IsLightValid(false), m_IsDirty(false), m_IsSaving(false), m_StayCount(0), m_PosX(a_ChunkX), m_PosZ(a_ChunkZ), m_World(a_World), m_ChunkMap(a_ChunkMap), m_WaterSimulatorData(a_World->GetWaterSimulator()->CreateChunkData()), m_LavaSimulatorData (a_World->GetLavaSimulator ()->CreateChunkData()), m_RedstoneSimulatorData(a_World->GetRedstoneSimulator()->CreateChunkData()), m_AlwaysTicked(0) { m_NeighborXM = a_ChunkMap->FindChunk(a_ChunkX - 1, a_ChunkZ); m_NeighborXP = a_ChunkMap->FindChunk(a_ChunkX + 1, a_ChunkZ); m_NeighborZM = a_ChunkMap->FindChunk(a_ChunkX, a_ChunkZ - 1); m_NeighborZP = a_ChunkMap->FindChunk(a_ChunkX, a_ChunkZ + 1); if (m_NeighborXM != nullptr) { m_NeighborXM->m_NeighborXP = this; } if (m_NeighborXP != nullptr) { m_NeighborXP->m_NeighborXM = this; } if (m_NeighborZM != nullptr) { m_NeighborZM->m_NeighborZP = this; } if (m_NeighborZP != nullptr) { m_NeighborZP->m_NeighborZM = this; } } cChunk::~cChunk() { // LOGINFO("### delete cChunk() (%i, %i) from %p, thread 0x%x ###", m_PosX, m_PosZ, this, GetCurrentThreadId()); // Inform our neighbours that we're no longer valid: if (m_NeighborXM != nullptr) { m_NeighborXM->m_NeighborXP = nullptr; } if (m_NeighborXP != nullptr) { m_NeighborXP->m_NeighborXM = nullptr; } if (m_NeighborZM != nullptr) { m_NeighborZM->m_NeighborZP = nullptr; } if (m_NeighborZP != nullptr) { m_NeighborZP->m_NeighborZM = nullptr; } delete m_WaterSimulatorData; m_WaterSimulatorData = nullptr; delete m_LavaSimulatorData; m_LavaSimulatorData = nullptr; delete m_RedstoneSimulatorData; m_RedstoneSimulatorData = nullptr; } void cChunk::BroadcastPendingChanges(void) { if (const auto PendingBlocksCount = m_PendingSendBlocks.size(); PendingBlocksCount >= 10240) { // Resend the full chunk: for (const auto ClientHandle : m_LoadedByClient) { m_World->ForceSendChunkTo(m_PosX, m_PosZ, cChunkSender::Priority::Medium, ClientHandle); } } else if (PendingBlocksCount == 0) { // Only send block entity changes: for (const auto ClientHandle : m_LoadedByClient) { for (const auto BlockEntity : m_PendingSendBlockEntities) { BlockEntity->SendTo(*ClientHandle); } } } else { // Send block and block entity changes: for (const auto ClientHandle : m_LoadedByClient) { ClientHandle->SendBlockChanges(m_PosX, m_PosZ, m_PendingSendBlocks); for (const auto BlockEntity : m_PendingSendBlockEntities) { BlockEntity->SendTo(*ClientHandle); } } } m_PendingSendBlocks.clear(); m_PendingSendBlockEntities.clear(); } void cChunk::SetPresence(cChunk::ePresence a_Presence) { m_Presence = a_Presence; if (a_Presence == cpPresent) { m_World->GetChunkMap()->ChunkValidated(); } } void cChunk::MarkRegenerating(void) { // Set as queued again: SetPresence(cpQueued); // Tell all clients attached to this chunk that they want this chunk: for (auto ClientHandle : m_LoadedByClient) { ClientHandle->AddWantedChunk(m_PosX, m_PosZ); } // for itr - m_LoadedByClient[] } bool cChunk::HasPlayerEntities() const { return std::any_of( m_Entities.begin(), m_Entities.end(), [](const auto & Entity) { return Entity->IsPlayer(); } ); } bool cChunk::CanUnload(void) const { return m_LoadedByClient.empty() && // The chunk is not used by any client !HasPlayerEntities() && // Ensure not only the absence of ClientHandlers, but also of cPlayer objects !m_IsDirty && // The chunk has been saved properly or hasn't been touched since the load / gen (m_StayCount == 0) && // The chunk is not in a ChunkStay (m_Presence != cpQueued) ; // The chunk is not queued for loading / generating (otherwise multi-load / multi-gen could occur) } bool cChunk::CanUnloadAfterSaving(void) const { return m_LoadedByClient.empty() && // The chunk is not used by any client !HasPlayerEntities() && // Ensure not only the absence of ClientHandlers, but also of cPlayer objects m_IsDirty && // The chunk is dirty (m_StayCount == 0) && // The chunk is not in a ChunkStay (m_Presence != cpQueued) ; // The chunk is not queued for loading / generating (otherwise multi-load / multi-gen could occur) } void cChunk::OnUnload() { // Note: this is only called during normal operation, not during shutdown // Notify all entities of imminent unload: for (auto & Entity : m_Entities) { // Chunks cannot be unloaded when they still contain players: ASSERT(!Entity->IsPlayer()); // Notify the entity: Entity->OnRemoveFromWorld(*Entity->GetWorld()); } // Notify all block entities of imminent unload: for (auto & KeyPair : m_BlockEntities) { KeyPair.second->OnRemoveFromWorld(); } } void cChunk::MarkSaving(void) { m_IsSaving = true; } void cChunk::MarkSaved(void) { if (!m_IsSaving) { return; } m_IsDirty = false; } void cChunk::MarkLoaded(void) { m_IsDirty = false; SetPresence(cpPresent); } void cChunk::MarkLoadFailed(void) { ASSERT(m_Presence == cpQueued); // Mark dirty before generating, so that we get saved and don't have to later generate again: MarkDirty(); // The chunk is always needed, generate it: m_World->GetGenerator().QueueGenerateChunk({ m_PosX, m_PosZ }, false); } void cChunk::GetAllData(cChunkDataCallback & a_Callback) const { ASSERT(m_Presence == cpPresent); a_Callback.LightIsValid(m_IsLightValid); a_Callback.ChunkData(m_BlockData, m_LightData); a_Callback.HeightMap(m_HeightMap); a_Callback.BiomeMap(m_BiomeMap); for (const auto & Entity : m_Entities) { a_Callback.Entity(Entity.get()); } for (auto & KeyPair : m_BlockEntities) { a_Callback.BlockEntity(KeyPair.second.get()); } } void cChunk::SetAllData(SetChunkData && a_SetChunkData) { std::copy_n(a_SetChunkData.HeightMap, std::size(a_SetChunkData.HeightMap), m_HeightMap); std::copy_n(a_SetChunkData.BiomeMap, std::size(a_SetChunkData.BiomeMap), m_BiomeMap); m_BlockData = std::move(a_SetChunkData.BlockData); m_LightData = std::move(a_SetChunkData.LightData); m_IsLightValid = a_SetChunkData.IsLightValid; m_PendingSendBlocks.clear(); m_PendingSendBlockEntities.clear(); // Entities need some extra steps to destroy, so here we're keeping the old ones. // Move the entities already in the chunk, including player entities, so that we don't lose any: a_SetChunkData.Entities.insert( a_SetChunkData.Entities.end(), std::make_move_iterator(m_Entities.begin()), std::make_move_iterator(m_Entities.end()) ); // Store the augmented result: m_Entities = std::move(a_SetChunkData.Entities); // Set all the entity variables again: for (const auto & Entity : m_Entities) { Entity->SetWorld(m_World); Entity->SetParentChunk(this); Entity->SetIsTicking(true); } // Remove the block entities present - either the loader / saver has better, or we'll create empty ones: for (auto & KeyPair : m_BlockEntities) { KeyPair.second->Destroy(); KeyPair.second->OnRemoveFromWorld(); } // Clear the old ones: m_BlockEntities = std::move(a_SetChunkData.BlockEntities); // Check that all block entities have a valid blocktype at their respective coords (DEBUG-mode only): for (auto & KeyPair : m_BlockEntities) { #ifndef NDEBUG cBlockEntity * Block = KeyPair.second.get(); BLOCKTYPE EntityBlockType = Block->GetBlockType(); BLOCKTYPE WorldBlockType = GetBlock(Block->GetRelX(), Block->GetPosY(), Block->GetRelZ()); ASSERT(WorldBlockType == EntityBlockType); #endif // Reset Pointer KeyPair.second->SetWorld(nullptr); auto Pos = cChunkDef::RelativeToAbsolute({KeyPair.second->GetRelX(), 0, KeyPair.second->GetRelZ()}, {m_PosX, m_PosZ}); if ((Pos.x != KeyPair.second->GetPosX()) || (Pos.z != KeyPair.second->GetPosZ())) { KeyPair.second->SetPos(Pos.addedY(KeyPair.second->GetPosY())); } KeyPair.second->SetWorld(m_World); } // Set the chunk data as valid. // This may be needed for some simulators that perform actions upon block adding (Vaporize), // as well as some block entities upon being added to the chunk (Chests). SetPresence(cpPresent); // Initialise all block entities: for (auto & KeyPair : m_BlockEntities) { KeyPair.second->OnAddToWorld(*m_World, *this); } // Wake up all simulators for their respective blocks: WakeUpSimulators(); } void cChunk::SetLight( const cChunkDef::BlockNibbles & a_BlockLight, const cChunkDef::BlockNibbles & a_SkyLight ) { // 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 :) m_LightData.SetAll(a_BlockLight, a_SkyLight); MarkDirty(); m_IsLightValid = true; } void cChunk::WriteBlockArea(cBlockArea & a_Area, int a_MinBlockX, int a_MinBlockY, int a_MinBlockZ, int a_DataTypes) { if ((a_DataTypes & (cBlockArea::baTypes | cBlockArea::baMetas)) != (cBlockArea::baTypes | cBlockArea::baMetas)) { LOGWARNING("cChunk::WriteBlockArea(): unsupported datatype request, can write only types + metas together (0x%x), requested 0x%x. Ignoring.", (cBlockArea::baTypes | cBlockArea::baMetas), a_DataTypes & (cBlockArea::baTypes | cBlockArea::baMetas) ); return; } // SizeX, SizeZ are the dimensions of the block data to copy to the chunk (size of the geometric union) int BlockStartX = std::max(a_MinBlockX, m_PosX * cChunkDef::Width); int BlockEndX = std::min(a_MinBlockX + a_Area.GetSizeX(), (m_PosX + 1) * cChunkDef::Width); int BlockStartZ = std::max(a_MinBlockZ, m_PosZ * cChunkDef::Width); int BlockEndZ = std::min(a_MinBlockZ + a_Area.GetSizeZ(), (m_PosZ + 1) * cChunkDef::Width); int SizeX = BlockEndX - BlockStartX; // Size of the union int SizeZ = BlockEndZ - BlockStartZ; int SizeY = std::min(a_Area.GetSizeY(), cChunkDef::Height - a_MinBlockY); int OffX = BlockStartX - m_PosX * cChunkDef::Width; // Offset within the chunk where the union starts int OffZ = BlockStartZ - m_PosZ * cChunkDef::Width; int BaseX = BlockStartX - a_MinBlockX; // Offset within the area where the union starts int BaseZ = BlockStartZ - a_MinBlockZ; // Copy blocktype and blockmeta: BLOCKTYPE * AreaBlockTypes = a_Area.GetBlockTypes(); NIBBLETYPE * AreaBlockMetas = a_Area.GetBlockMetas(); for (int y = 0; y < SizeY; y++) { int ChunkY = a_MinBlockY + y; int AreaY = y; for (int z = 0; z < SizeZ; z++) { int ChunkZ = OffZ + z; int AreaZ = BaseZ + z; for (int x = 0; x < SizeX; x++) { int ChunkX = OffX + x; int AreaX = BaseX + x; auto idx = a_Area.MakeIndex(AreaX, AreaY, AreaZ); BLOCKTYPE BlockType = AreaBlockTypes[idx]; NIBBLETYPE BlockMeta = AreaBlockMetas[idx]; FastSetBlock(ChunkX, ChunkY, ChunkZ, BlockType, BlockMeta); } // for x } // for z } // for y // Erase all affected block entities: { // The affected area, in world coordinates. cCuboid affectedArea( { BlockStartX, a_MinBlockY, BlockStartZ }, { BlockEndX, a_MinBlockY + SizeY - 1, BlockEndZ } ); // Where in the pending block entity send list to start removing the invalidated elements from. auto PendingRemove = m_PendingSendBlockEntities.end(); for (auto itr = m_BlockEntities.begin(); itr != m_BlockEntities.end();) { if (affectedArea.IsInside(itr->second->GetPos())) { itr->second->Destroy(); itr->second->OnRemoveFromWorld(); PendingRemove = std::remove(m_PendingSendBlockEntities.begin(), PendingRemove, itr->second.get()); // Search the remaining valid pending sends. itr = m_BlockEntities.erase(itr); } else { ++itr; } } // Remove all the deleted block entities from the pending send list: m_PendingSendBlockEntities.erase(PendingRemove, m_PendingSendBlockEntities.end()); } // Clone block entities from a_Area into this chunk: if ((a_DataTypes & cBlockArea::baBlockEntities) != 0) { for (const auto & keyPair: a_Area.GetBlockEntities()) { auto & be = keyPair.second; auto posX = be->GetPosX() + a_MinBlockX; auto posY = be->GetPosY() + a_MinBlockY; auto posZ = be->GetPosZ() + a_MinBlockZ; if ( (posX < m_PosX * cChunkDef::Width) || (posX >= m_PosX * cChunkDef::Width + cChunkDef::Width) || (posZ < m_PosZ * cChunkDef::Width) || (posZ >= m_PosZ * cChunkDef::Width + cChunkDef::Width) ) { continue; } // This block entity is inside the chunk. // The code above should have removed any that were here before: ASSERT(GetBlockEntityRel(cChunkDef::AbsoluteToRelative({ posX, posY, posZ })) == nullptr); // Clone, and add the new one: AddBlockEntity(be->Clone({posX, posY, posZ})); } } } void cChunk::Stay(bool a_Stay) { if (a_Stay) { m_StayCount++; } else { ASSERT(m_StayCount != 0); m_StayCount--; } } void cChunk::CollectMobCensus(cMobCensus & toFill) { toFill.CollectSpawnableChunk(*this); std::vector PlayerPositions; PlayerPositions.reserve(m_LoadedByClient.size()); for (auto ClientHandle : m_LoadedByClient) { const cPlayer * currentPlayer = ClientHandle->GetPlayer(); PlayerPositions.push_back(currentPlayer->GetPosition()); } Vector3d currentPosition; for (auto & entity : m_Entities) { // LOGD("Counting entity #%i (%s)", (*itr)->GetUniqueID(), (*itr)->GetClass()); if (entity->IsMob()) { auto & Monster = static_cast(*entity); currentPosition = Monster.GetPosition(); for (const auto & PlayerPos : PlayerPositions) { toFill.CollectMob(Monster, *this, (currentPosition - PlayerPos).SqrLength()); } } } // for itr - m_Entitites[] } void cChunk::GetThreeRandomNumbers(int & a_X, int & a_Y, int & a_Z, int a_MaxX, int a_MaxY, int a_MaxZ) { ASSERT( (a_MaxX > 0) && (a_MaxY > 0) && (a_MaxZ > 0) && (a_MaxX <= std::numeric_limits::max() / a_MaxY) && // a_MaxX * a_MaxY doesn't overflow (a_MaxX * a_MaxY <= std::numeric_limits::max() / a_MaxZ) // a_MaxX * a_MaxY * a_MaxZ doesn't overflow ); // MTRand gives an inclusive range [0, Max] but this gives the exclusive range [0, Max) int OverallMax = (a_MaxX * a_MaxY * a_MaxZ) - 1; int Random = m_World->GetTickRandomNumber(OverallMax); a_X = Random % a_MaxX; a_Y = (Random / a_MaxX) % a_MaxY; a_Z = ((Random / a_MaxX) / a_MaxY) % a_MaxZ; } void cChunk::GetRandomBlockCoords(int & a_X, int & a_Y, int & a_Z) { // MG TODO : check if this kind of optimization (only one random call) is still needed // MG TODO : if so propagate it GetThreeRandomNumbers(a_X, a_Y, a_Z, cChunkDef::Width, cChunkDef::Height - 2, cChunkDef::Width); a_Y++; } void cChunk::SpawnMobs(cMobSpawner & a_MobSpawner) { int CenterX, CenterY, CenterZ; GetRandomBlockCoords(CenterX, CenterY, CenterZ); BLOCKTYPE PackCenterBlock = GetBlock(CenterX, CenterY, CenterZ); if (!a_MobSpawner.CheckPackCenter(PackCenterBlock)) { return; } a_MobSpawner.NewPack(); int NumberOfTries = 0; int NumberOfSuccess = 0; int MaxNbOfSuccess = 4; // This can be changed during the process for Wolves and Ghasts while ((NumberOfTries < 12) && (NumberOfSuccess < MaxNbOfSuccess)) { const int HorizontalRange = 20; // MG TODO : relocate const int VerticalRange = 0; // MG TODO : relocate int TryX, TryY, TryZ; GetThreeRandomNumbers(TryX, TryY, TryZ, 2 * HorizontalRange + 1, 2 * VerticalRange + 1, 2 * HorizontalRange + 1); TryX -= HorizontalRange; TryY -= VerticalRange; TryZ -= HorizontalRange; TryX += CenterX; TryY += CenterY; TryZ += CenterZ; ASSERT(TryY > 0); ASSERT(TryY < cChunkDef::Height - 1); int WorldX, WorldY, WorldZ; PositionToWorldPosition(TryX, TryY, TryZ, WorldX, WorldY, WorldZ); // MG TODO : // Moon cycle (for slime) // check player and playerspawn presence < 24 blocks // check mobs presence on the block // MG TODO : check that "Level" really means Y /* NIBBLETYPE SkyLight = 0; NIBBLETYPE BlockLight = 0; */ NumberOfTries++; Vector3i Try(TryX, TryY, TryZ); const auto Chunk = GetRelNeighborChunkAdjustCoords(Try); if ((Chunk == nullptr) || !Chunk->IsValid() || !Chunk->IsLightValid()) { continue; } auto newMob = a_MobSpawner.TryToSpawnHere(this, Try, GetBiomeAt(Try.x, Try.z), MaxNbOfSuccess); if (newMob == nullptr) { continue; } double ActualX = WorldX + 0.5; double ActualZ = WorldZ + 0.5; newMob->SetPosition(ActualX, WorldY, ActualZ); FLOGD("Spawning {0} #{1} at {2}", newMob->GetClass(), newMob->GetUniqueID(), Vector3i{WorldX, WorldY, WorldZ}); NumberOfSuccess++; } // while (retry) } void cChunk::Tick(std::chrono::milliseconds a_Dt) { TickBlocks(); // Tick all block entities in this chunk: for (auto & KeyPair : m_BlockEntities) { m_IsDirty = KeyPair.second->Tick(a_Dt, *this) | m_IsDirty; } for (auto itr = m_Entities.begin(); itr != m_Entities.end();) { // Do not tick mobs that are detached from the world. They're either scheduled for teleportation or for removal. if (!(*itr)->IsTicking()) { ++itr; continue; } if (!((*itr)->IsMob())) // Mobs are ticked inside cWorld::TickMobs() (as we don't have to tick them if they are far away from players) { // Tick all entities in this chunk (except mobs): ASSERT((*itr)->GetParentChunk() == this); (*itr)->Tick(a_Dt, *this); ASSERT((*itr)->GetParentChunk() == this); } // Do not move mobs that are detached from the world to neighbors. They're either scheduled for teleportation or for removal. // Because the schedulded destruction is going to look for them in this chunk. See cEntity::destroy. if (!(*itr)->IsTicking()) { ++itr; continue; } if ( ((*itr)->GetChunkX() != m_PosX) || ((*itr)->GetChunkZ() != m_PosZ) ) { // Mark as dirty if it was a server-generated entity: if (!(*itr)->IsPlayer()) { MarkDirty(); } // This block is very similar to RemoveEntity, except it uses an iterator to avoid scanning the whole m_Entities // The entity moved out of the chunk, move it to the neighbor (*itr)->SetParentChunk(nullptr); MoveEntityToNewChunk(std::move(*itr)); itr = m_Entities.erase(itr); } else { ++itr; } } // for itr - m_Entitites[] ApplyWeatherToTop(); // Tick simulators: m_World->GetSimulatorManager()->SimulateChunk(a_Dt, m_PosX, m_PosZ, this); // Check blocks after everything else to apply at least one round of queued ticks (i.e. cBlockHandler::Check) this tick: CheckBlocks(); } void cChunk::TickBlock(const Vector3i a_RelPos) { cChunkInterface ChunkInterface(this->GetWorld()->GetChunkMap()); cBlockInServerPluginInterface PluginInterface(*this->GetWorld()); cBlockHandler::For(GetBlock(a_RelPos)).OnUpdate(ChunkInterface, *this->GetWorld(), PluginInterface, *this, a_RelPos); } void cChunk::MoveEntityToNewChunk(OwnedEntity a_Entity) { cChunk * Neighbor = GetNeighborChunk(a_Entity->GetChunkX() * cChunkDef::Width, a_Entity->GetChunkZ() * cChunkDef::Width); if (Neighbor == nullptr) { LOGWARNING("%s: Entity at %p (%s, ID %d) moving to a non-existent chunk.", __FUNCTION__, static_cast(a_Entity.get()), a_Entity->GetClass(), a_Entity->GetUniqueID() ); Neighbor = &m_ChunkMap->ConstructChunk(a_Entity->GetChunkX(), a_Entity->GetChunkZ()); } ASSERT(Neighbor != this); // Moving into the same chunk? wtf? auto & Entity = *a_Entity; Neighbor->AddEntity(std::move(a_Entity)); class cMover : public cClientDiffCallback { virtual void Removed(cClientHandle * a_Client) override { a_Client->SendDestroyEntity(m_Entity); } virtual void Added(cClientHandle * a_Client) override { m_Entity.SpawnOn(*a_Client); } cEntity & m_Entity; public: cMover(cEntity & a_CallbackEntity) : m_Entity(a_CallbackEntity) {} } Mover(Entity); m_ChunkMap->CompareChunkClients(this, Neighbor, Mover); } void cChunk::CheckBlocks() { cChunkInterface ChunkInterface(m_World->GetChunkMap()); cBlockInServerPluginInterface PluginInterface(*m_World); // Process a limited number of blocks since cBlockHandler::Check may queue more to tick auto Count = m_BlocksToCheck.size(); while (Count != 0) { const auto Pos = m_BlocksToCheck.front(); m_BlocksToCheck.pop(); Count--; cBlockHandler::For(GetBlock(Pos)).Check(ChunkInterface, PluginInterface, Pos, *this); } } void cChunk::TickBlocks(void) { cChunkInterface ChunkInterface(m_World->GetChunkMap()); cBlockInServerPluginInterface PluginInterface(*m_World); // Tick random blocks, but the first one should be m_BlockToTick (so that SetNextBlockToTick() works): cBlockHandler::For(GetBlock(m_BlockToTick)).OnUpdate(ChunkInterface, *m_World, PluginInterface, *this, m_BlockToTick); auto & Random = GetRandomProvider(); // Set a new random coord for the next tick: m_BlockToTick = cChunkDef::IndexToCoordinate(Random.RandInt(cChunkDef::NumBlocks - 1)); // Choose a number of blocks for each section to randomly tick. // http://minecraft.wiki/w/Tick#Random_tick for (size_t Y = 0; Y < cChunkDef::NumSections; ++Y) { const auto Section = m_BlockData.GetSection(Y); if (Section == nullptr) { continue; } for (int Tick = 0; Tick != 3; Tick++) // TODO: configurability via gamerule randomTickSpeed { const auto Index = Random.RandInt(ChunkBlockData::SectionBlockCount - 1); const auto Position = cChunkDef::IndexToCoordinate(Y * ChunkBlockData::SectionBlockCount + Index); cBlockHandler::For((*Section)[Index]).OnUpdate(ChunkInterface, *m_World, PluginInterface, *this, Position); } } } void cChunk::ApplyWeatherToTop() { if ( (GetRandomProvider().RandBool(0.99)) || ( (m_World->GetWeather() != eWeather_Rain) && (m_World->GetWeather() != eWeather_ThunderStorm) ) ) { // Not the right weather, or not at this tick; bail out return; } int X = m_World->GetTickRandomNumber(15); int Z = m_World->GetTickRandomNumber(15); int Height = GetHeight(X, Z); if (GetSnowStartHeight(GetBiomeAt(X, Z)) > Height) { return; } if (GetBlockLight(X, Height, Z) > 10) { // Snow only generates on blocks with a block light level of 10 or less. // Ref: https://minecraft.wiki/w/Snow_(layer)#Snowfall return; } BLOCKTYPE TopBlock = GetBlock(X, Height, Z); NIBBLETYPE TopMeta = GetMeta (X, Height, Z); if (m_World->IsDeepSnowEnabled() && (TopBlock == E_BLOCK_SNOW)) { int MaxSize = 7; BLOCKTYPE BlockType[4]; NIBBLETYPE BlockMeta[4]; UnboundedRelGetBlock(X - 1, Height, Z, BlockType[0], BlockMeta[0]); UnboundedRelGetBlock(X + 1, Height, Z, BlockType[1], BlockMeta[1]); UnboundedRelGetBlock(X, Height, Z - 1, BlockType[2], BlockMeta[2]); UnboundedRelGetBlock(X, Height, Z + 1, BlockType[3], BlockMeta[3]); for (int i = 0; i < 4; i++) { switch (BlockType[i]) { case E_BLOCK_AIR: { MaxSize = 0; break; } case E_BLOCK_SNOW: { MaxSize = std::min(BlockMeta[i] + 1, MaxSize); break; } } } if (TopMeta < MaxSize) { FastSetBlock(X, Height, Z, E_BLOCK_SNOW, TopMeta + 1); } else if (TopMeta > MaxSize) { FastSetBlock(X, Height, Z, E_BLOCK_SNOW, TopMeta - 1); } } else if (cBlockInfo::IsSnowable(TopBlock) && (Height < cChunkDef::Height - 1)) { SetBlock({X, Height + 1, Z}, E_BLOCK_SNOW, 0); } else if (IsBlockWater(TopBlock) && (TopMeta == 0)) { SetBlock({X, Height, Z}, E_BLOCK_ICE, 0); } else if ( (m_World->IsDeepSnowEnabled()) && ( (TopBlock == E_BLOCK_RED_ROSE) || (TopBlock == E_BLOCK_YELLOW_FLOWER) || (TopBlock == E_BLOCK_RED_MUSHROOM) || (TopBlock == E_BLOCK_BROWN_MUSHROOM) ) ) { SetBlock({X, Height, Z}, E_BLOCK_SNOW, 0); } } cItems cChunk::PickupsFromBlock(Vector3i a_RelPos, const cEntity * a_Digger, const cItem * a_Tool) { BLOCKTYPE BlockType; NIBBLETYPE BlockMeta; GetBlockTypeMeta(a_RelPos, BlockType, BlockMeta); cItems Pickups; const auto BlockEntity = GetBlockEntityRel(a_RelPos); if ((a_Tool == nullptr) || a_Tool->GetHandler().CanHarvestBlock(BlockType)) { Pickups = cBlockHandler::For(BlockType).ConvertToPickups(BlockMeta, a_Tool); if (BlockEntity != nullptr) { auto BlockEntityPickups = BlockEntity->ConvertToPickups(); Pickups.insert(Pickups.end(), std::make_move_iterator(BlockEntityPickups.begin()), std::make_move_iterator(BlockEntityPickups.end())); } } // TODO: this should be in cWorld::DropBlockAsPickups. When it's here we can't check the return value and cancel spawning: cRoot::Get()->GetPluginManager()->CallHookBlockToPickups( *m_World, cChunkDef::RelativeToAbsolute(a_RelPos, GetPos()), BlockType, BlockMeta, BlockEntity, a_Digger, a_Tool, Pickups ); return Pickups; } int cChunk::GrowPlantAt(Vector3i a_RelPos, int a_NumStages) { return cBlockHandler::For(GetBlock(a_RelPos)).Grow(*this, a_RelPos, a_NumStages); } bool cChunk::UnboundedRelGetBlock(Vector3i a_RelPos, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta) const { if (!cChunkDef::IsValidHeight(a_RelPos)) { LOGWARNING("%s: requesting a block with a_RelY out of range: %d", __FUNCTION__, a_RelPos.y); return false; } auto chunk = GetRelNeighborChunkAdjustCoords(a_RelPos); if ((chunk == nullptr) || !chunk->IsValid()) { // The chunk is not available, bail out return false; } chunk->GetBlockTypeMeta(a_RelPos, a_BlockType, a_BlockMeta); return true; } bool cChunk::UnboundedRelGetBlockType(Vector3i a_RelPos, BLOCKTYPE & a_BlockType) const { if (!cChunkDef::IsValidHeight(a_RelPos)) { LOGWARNING("%s: requesting a block with a_RelY out of range: %d", __FUNCTION__, a_RelPos.y); return false; } auto chunk = GetRelNeighborChunkAdjustCoords(a_RelPos); if ((chunk == nullptr) || !chunk->IsValid()) { // The chunk is not available, bail out return false; } a_BlockType = chunk->GetBlock(a_RelPos); return true; } bool cChunk::UnboundedRelGetBlockMeta(Vector3i a_RelPos, NIBBLETYPE & a_BlockMeta) const { if (!cChunkDef::IsValidHeight(a_RelPos)) { LOGWARNING("%s: requesting a block with a_RelY out of range: %d", __FUNCTION__, a_RelPos.y); return false; } auto chunk = GetRelNeighborChunkAdjustCoords(a_RelPos); if ((chunk == nullptr) || !chunk->IsValid()) { // The chunk is not available, bail out return false; } a_BlockMeta = chunk->GetMeta(a_RelPos); return true; } bool cChunk::UnboundedRelGetBlockBlockLight(Vector3i a_RelPos, NIBBLETYPE & a_BlockBlockLight) const { if (!cChunkDef::IsValidHeight(a_RelPos)) { LOGWARNING("%s: requesting a block with a_RelY out of range: %d", __FUNCTION__, a_RelPos.y); return false; } auto chunk = GetRelNeighborChunkAdjustCoords(a_RelPos); if ((chunk == nullptr) || !chunk->IsValid()) { // The chunk is not available, bail out return false; } a_BlockBlockLight = chunk->GetBlockLight(a_RelPos); return true; } bool cChunk::UnboundedRelGetBlockSkyLight(Vector3i a_RelPos, NIBBLETYPE & a_BlockSkyLight) const { if (!cChunkDef::IsValidHeight(a_RelPos)) { LOGWARNING("%s: requesting a block with a_RelY out of range: %d", __FUNCTION__, a_RelPos.y); return false; } auto chunk = GetRelNeighborChunkAdjustCoords(a_RelPos); if ((chunk == nullptr) || !chunk->IsValid()) { // The chunk is not available, bail out return false; } a_BlockSkyLight = chunk->GetSkyLight(a_RelPos); return true; } bool cChunk::UnboundedRelGetBlockLights(Vector3i a_RelPos, NIBBLETYPE & a_BlockLight, NIBBLETYPE & a_SkyLight) const { if (!cChunkDef::IsValidHeight(a_RelPos)) { LOGWARNING("%s: requesting a block with a_RelY out of range: %d", __FUNCTION__, a_RelPos.y); return false; } auto chunk = GetRelNeighborChunkAdjustCoords(a_RelPos); if ((chunk == nullptr) || !chunk->IsValid()) { // The chunk is not available, bail out return false; } a_BlockLight = chunk->GetBlockLight(a_RelPos); a_SkyLight = chunk->GetSkyLight (a_RelPos); return true; } bool cChunk::UnboundedRelSetBlock(Vector3i a_RelPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) { if (!cChunkDef::IsValidHeight(a_RelPos)) { LOGWARNING("%s: requesting a block with a_RelY out of range: %d", __FUNCTION__, a_RelPos.y); return false; } auto chunk = GetRelNeighborChunkAdjustCoords(a_RelPos); if ((chunk == nullptr) || !chunk->IsValid()) { // The chunk is not available, bail out return false; } chunk->SetBlock(a_RelPos, a_BlockType, a_BlockMeta); return true; } bool cChunk::UnboundedRelFastSetBlock(Vector3i a_RelPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) { if (!cChunkDef::IsValidHeight(a_RelPos)) { LOGWARNING("%s: requesting a block with a_RelY out of range: %d", __FUNCTION__, a_RelPos.y); return false; } auto chunk = GetRelNeighborChunkAdjustCoords(a_RelPos); if ((chunk == nullptr) || !chunk->IsValid()) { // The chunk is not available, bail out return false; } chunk->FastSetBlock(a_RelPos, a_BlockType, a_BlockMeta); return true; } int cChunk::GetHeight(int a_X, int a_Z) const { ASSERT((a_X >= 0) && (a_X < cChunkDef::Width) && (a_Z >= 0) && (a_Z < cChunkDef::Width)); return m_HeightMap[a_X + a_Z * cChunkDef::Width]; } bool cChunk::IsWeatherSunnyAt(int a_RelX, int a_RelZ) const { return m_World->IsWeatherSunny() || IsBiomeNoDownfall(GetBiomeAt(a_RelX, a_RelZ)); } bool cChunk::IsWeatherWetAt(const int a_RelX, const int a_RelZ) const { const auto Biome = GetBiomeAt(a_RelX, a_RelZ); return m_World->IsWeatherWet() && !IsBiomeNoDownfall(Biome) && !IsBiomeCold(Biome); } bool cChunk::IsWeatherWetAt(const Vector3i a_Position) const { if ((a_Position.y < 0) || !IsWeatherWetAt(a_Position.x, a_Position.z)) { return false; } if (a_Position.y >= cChunkDef::Height) { return true; } for (int y = GetHeight(a_Position.x, a_Position.z); y >= a_Position.y; y--) { if (cBlockInfo::IsRainBlocker(GetBlock({ a_Position.x, y, a_Position.z }))) { return false; } } return true; } void cChunk::WakeUpSimulators(void) { auto * WaterSimulator = m_World->GetWaterSimulator(); auto * LavaSimulator = m_World->GetLavaSimulator(); auto * RedstoneSimulator = m_World->GetRedstoneSimulator(); for (size_t SectionIdx = 0; SectionIdx != cChunkDef::NumSections; ++SectionIdx) { const auto * Section = m_BlockData.GetSection(SectionIdx); if (Section == nullptr) { continue; } for (size_t BlockIdx = 0; BlockIdx != ChunkBlockData::SectionBlockCount; ++BlockIdx) { const auto BlockType = (*Section)[BlockIdx]; const auto Position = cChunkDef::IndexToCoordinate(BlockIdx + SectionIdx * ChunkBlockData::SectionBlockCount); RedstoneSimulator->AddBlock(*this, Position, BlockType); WaterSimulator->AddBlock(*this, Position, BlockType); LavaSimulator->AddBlock(*this, Position, BlockType); } } } void cChunk::SetBlock(Vector3i a_RelPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) { FastSetBlock(a_RelPos, a_BlockType, a_BlockMeta); // Queue a check of this block's neighbors: m_BlocksToCheck.push(a_RelPos); // Wake up the simulators for this block: GetWorld()->GetSimulatorManager()->WakeUp(*this, a_RelPos); // If there was a block entity, remove it: if (const auto FindResult = m_BlockEntities.find(cChunkDef::MakeIndex(a_RelPos)); FindResult != m_BlockEntities.end()) { auto & BlockEntity = *FindResult->second; BlockEntity.Destroy(); BlockEntity.OnRemoveFromWorld(); m_BlockEntities.erase(FindResult); m_PendingSendBlockEntities.erase(std::remove(m_PendingSendBlockEntities.begin(), m_PendingSendBlockEntities.end(), &BlockEntity), m_PendingSendBlockEntities.end()); } // If the new block is a block entity, create the entity object: if (cBlockEntity::IsBlockEntityBlockType(a_BlockType)) { AddBlockEntity(cBlockEntity::CreateByBlockType(a_BlockType, a_BlockMeta, RelativeToAbsolute(a_RelPos), m_World)); } } void cChunk::FastSetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, BLOCKTYPE a_BlockMeta) { ASSERT(cChunkDef::IsValidRelPos({ a_RelX, a_RelY, a_RelZ })); ASSERT(IsValid()); const BLOCKTYPE OldBlockType = GetBlock(a_RelX, a_RelY, a_RelZ); const BLOCKTYPE OldBlockMeta = m_BlockData.GetMeta({ a_RelX, a_RelY, a_RelZ }); if ((OldBlockType == a_BlockType) && (OldBlockMeta == a_BlockMeta)) { return; } bool ReplacingLiquids = ( ((OldBlockType == E_BLOCK_STATIONARY_WATER) && (a_BlockType == E_BLOCK_WATER)) || // Replacing stationary water with water ((OldBlockType == E_BLOCK_WATER) && (a_BlockType == E_BLOCK_STATIONARY_WATER)) || // Replacing water with stationary water ((OldBlockType == E_BLOCK_STATIONARY_LAVA) && (a_BlockType == E_BLOCK_LAVA)) || // Replacing stationary lava with lava ((OldBlockType == E_BLOCK_LAVA) && (a_BlockType == E_BLOCK_STATIONARY_LAVA)) // Replacing lava with stationary lava ); if (!ReplacingLiquids) { MarkDirty(); } m_BlockData.SetBlock({ a_RelX, a_RelY, a_RelZ }, a_BlockType); // Queue block to be sent only if ... if ( !( // ... the old and new blocktypes AREN'T leaves (because the client doesn't need meta updates) ((OldBlockType == E_BLOCK_LEAVES) && (a_BlockType == E_BLOCK_LEAVES)) || ((OldBlockType == E_BLOCK_NEW_LEAVES) && (a_BlockType == E_BLOCK_NEW_LEAVES)) ) && // ... AND ... ( (OldBlockMeta != a_BlockMeta) || (!ReplacingLiquids) ) ) { m_PendingSendBlocks.emplace_back(m_PosX, m_PosZ, a_RelX, a_RelY, a_RelZ, a_BlockType, a_BlockMeta); } m_BlockData.SetMeta({ a_RelX, a_RelY, a_RelZ }, a_BlockMeta); // ONLY recalculate lighting if it's necessary! if ( (cBlockInfo::GetLightValue (OldBlockType) != cBlockInfo::GetLightValue (a_BlockType)) || (cBlockInfo::GetSpreadLightFalloff(OldBlockType) != cBlockInfo::GetSpreadLightFalloff(a_BlockType)) || (cBlockInfo::IsTransparent (OldBlockType) != cBlockInfo::IsTransparent (a_BlockType)) ) { m_IsLightValid = false; } // Update heightmap, if needed: if (a_RelY >= m_HeightMap[a_RelX + a_RelZ * cChunkDef::Width]) { if (a_BlockType != E_BLOCK_AIR) { m_HeightMap[a_RelX + a_RelZ * cChunkDef::Width] = static_cast(a_RelY); } else { for (int y = a_RelY - 1; y > 0; --y) { if (GetBlock(a_RelX, y, a_RelZ) != E_BLOCK_AIR) { m_HeightMap[a_RelX + a_RelZ * cChunkDef::Width] = static_cast(y); break; } } // for y - column in m_BlockData } } } void cChunk::SendBlockTo(int a_RelX, int a_RelY, int a_RelZ, cClientHandle * a_Client) { const auto BlockEntity = GetBlockEntityRel({ a_RelX, a_RelY, a_RelZ }); if (a_Client == nullptr) { // Queue the block (entity) for all clients in the chunk (will be sent in BroadcastPendingBlockChanges()): m_PendingSendBlocks.emplace_back(m_PosX, m_PosZ, a_RelX, a_RelY, a_RelZ, GetBlock(a_RelX, a_RelY, a_RelZ), GetMeta(a_RelX, a_RelY, a_RelZ)); if (BlockEntity != nullptr) { m_PendingSendBlockEntities.push_back(BlockEntity); } return; } const auto Position = PositionToWorldPosition(a_RelX, a_RelY, a_RelZ); a_Client->SendBlockChange(Position, 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: if (BlockEntity != nullptr) { BlockEntity->SendTo(*a_Client); } } void cChunk::AddBlockEntity(OwnedBlockEntity a_BlockEntity) { const auto BlockEntityPtr = a_BlockEntity.get(); [[maybe_unused]] const auto Result = m_BlockEntities.emplace( cChunkDef::MakeIndex(a_BlockEntity->GetRelX(), a_BlockEntity->GetPosY(), a_BlockEntity->GetRelZ()), std::move(a_BlockEntity) ); ASSERT(Result.second); // No block entity already at this position. BlockEntityPtr->OnAddToWorld(*m_World, *this); } cBlockEntity * cChunk::GetBlockEntity(Vector3i a_AbsPos) { const auto relPos = cChunkDef::AbsoluteToRelative(a_AbsPos); if (!cChunkDef::IsValidRelPos(relPos)) { // Coordinates are outside outside this chunk, no block entities here return nullptr; } auto itr = m_BlockEntities.find(cChunkDef::MakeIndex(relPos)); return (itr == m_BlockEntities.end()) ? nullptr : itr->second.get(); } cBlockEntity * cChunk::GetBlockEntityRel(Vector3i a_RelPos) { ASSERT(cChunkDef::IsValidRelPos(a_RelPos)); auto itr = m_BlockEntities.find(cChunkDef::MakeIndex(a_RelPos)); return (itr == m_BlockEntities.end()) ? nullptr : itr->second.get(); } bool cChunk::ShouldBeTicked(void) const { return IsValid() && (HasAnyClients() || (m_AlwaysTicked > 0)); } void cChunk::SetAlwaysTicked(bool a_AlwaysTicked) { if (a_AlwaysTicked) { m_AlwaysTicked += 1; Stay(a_AlwaysTicked); } else { m_AlwaysTicked -= 1; Stay(a_AlwaysTicked); } } bool cChunk::UseBlockEntity(cPlayer * a_Player, int a_X, int a_Y, int a_Z) { cBlockEntity * be = GetBlockEntity(a_X, a_Y, a_Z); if (be != nullptr) { return be->UsedBy(a_Player); } return false; } void cChunk::SetBiomeAt(int a_RelX, int a_RelZ, EMCSBiome a_Biome) { cChunkDef::SetBiome(m_BiomeMap, a_RelX, a_RelZ, a_Biome); MarkDirty(); } void cChunk::SetAreaBiome(int a_MinRelX, int a_MaxRelX, int a_MinRelZ, int a_MaxRelZ, EMCSBiome a_Biome) { for (int z = a_MinRelZ; z <= a_MaxRelZ; z++) { for (int x = a_MinRelX; x <= a_MaxRelX; x++) { cChunkDef::SetBiome(m_BiomeMap, x, z, a_Biome); } } MarkDirty(); // Re-send the chunk to all clients: for (auto ClientHandle : m_LoadedByClient) { m_World->ForceSendChunkTo(m_PosX, m_PosZ, cChunkSender::Priority::Medium, ClientHandle); } // for itr - m_LoadedByClient[] } bool cChunk::AddClient(cClientHandle * a_Client) { if (std::find(m_LoadedByClient.begin(), m_LoadedByClient.end(), a_Client) != m_LoadedByClient.end()) { // Already there, nothing needed return false; } m_LoadedByClient.push_back(a_Client); return true; } void cChunk::RemoveClient(cClientHandle * a_Client) { auto itr = std::remove(m_LoadedByClient.begin(), m_LoadedByClient.end(), a_Client); // We should always remove at most one client. ASSERT(std::distance(itr, m_LoadedByClient.end()) <= 1); // Note: itr can equal m_LoadedByClient.end() m_LoadedByClient.erase(itr, m_LoadedByClient.end()); if (!a_Client->IsDestroyed()) { for (auto & Entity : m_Entities) { /* // DEBUG: LOGD("chunk [%i, %i] destroying entity #%i for player \"%s\"", m_PosX, m_PosZ, (*itr)->GetUniqueID(), a_Client->GetUsername().c_str() ); */ a_Client->SendDestroyEntity(*Entity); } } } bool cChunk::HasClient(cClientHandle * a_Client) { return std::find(m_LoadedByClient.begin(), m_LoadedByClient.end(), a_Client) != m_LoadedByClient.end(); } bool cChunk::HasAnyClients(void) const { return !m_LoadedByClient.empty(); } void cChunk::AddEntity(OwnedEntity a_Entity) { if (!a_Entity->IsPlayer()) { MarkDirty(); } auto EntityPtr = a_Entity.get(); ASSERT(std::find(m_Entities.begin(), m_Entities.end(), a_Entity) == m_Entities.end()); // Not there already m_Entities.emplace_back(std::move(a_Entity)); ASSERT(EntityPtr->GetParentChunk() == nullptr); EntityPtr->SetParentChunk(this); } OwnedEntity cChunk::RemoveEntity(cEntity & a_Entity) { ASSERT(a_Entity.GetParentChunk() == this); ASSERT(!a_Entity.IsTicking()); a_Entity.SetParentChunk(nullptr); // Mark as dirty if it was a server-generated entity: if (!a_Entity.IsPlayer()) { MarkDirty(); } OwnedEntity Removed; m_Entities.erase( std::remove_if( m_Entities.begin(), m_Entities.end(), [&a_Entity, &Removed](decltype(m_Entities)::value_type & a_Value) { if (a_Value.get() == &a_Entity) { ASSERT(!Removed); Removed = std::move(a_Value); return true; } return false; } ), m_Entities.end() ); return Removed; } bool cChunk::HasEntity(UInt32 a_EntityID) const { for (const auto & Entity : m_Entities) { if (Entity->GetUniqueID() == a_EntityID) { return true; } } return false; } bool cChunk::ForEachEntity(cEntityCallback a_Callback) const { // The entity list is locked by the parent chunkmap's CS for (const auto & Entity : m_Entities) { if (Entity->IsTicking() && a_Callback(*Entity)) { return false; } } // for itr - m_Entitites[] return true; } bool cChunk::ForEachEntityInBox(const cBoundingBox & a_Box, cEntityCallback a_Callback) const { // The entity list is locked by the parent chunkmap's CS for (const auto & Entity : m_Entities) { if (!Entity->IsTicking()) { continue; } if (!Entity->GetBoundingBox().DoesIntersect(a_Box)) { // The entity is not in the specified box continue; } if (a_Callback(*Entity)) { return false; } } // for itr - m_Entitites[] return true; } bool cChunk::DoWithEntityByID(UInt32 a_EntityID, cEntityCallback a_Callback, bool & a_CallbackResult) const { // The entity list is locked by the parent chunkmap's CS for (const auto & Entity : m_Entities) { if ((Entity->GetUniqueID() == a_EntityID) && (Entity->IsTicking())) { a_CallbackResult = a_Callback(*Entity); return true; } } // for itr - m_Entitites[] return false; } bool cChunk::ForEachBlockEntity(cBlockEntityCallback a_Callback) { // The blockentity list is locked by the parent chunkmap's CS for (auto & KeyPair : m_BlockEntities) { if (a_Callback(*KeyPair.second)) { return false; } } return true; } bool cChunk::DoWithBlockEntityAt(Vector3i a_Position, cBlockEntityCallback a_Callback) { // The blockentity list is locked by the parent chunkmap's CS const auto BlockEntity = GetBlockEntityRel(a_Position); if (BlockEntity == nullptr) { return false; // No block entity here } const bool Result = a_Callback(*BlockEntity); m_PendingSendBlockEntities.push_back(BlockEntity); MarkDirty(); return Result; } void cChunk::GetBlockTypeMeta(Vector3i a_RelPos, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta) const { a_BlockType = GetBlock(a_RelPos); a_BlockMeta = GetMeta(a_RelPos); } void cChunk::GetBlockInfo(Vector3i a_RelPos, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_Meta, NIBBLETYPE & a_SkyLight, NIBBLETYPE & a_BlockLight) const { a_BlockType = GetBlock(a_RelPos); a_Meta = m_BlockData.GetMeta(a_RelPos); a_SkyLight = m_LightData.GetSkyLight(a_RelPos); a_BlockLight = m_LightData.GetBlockLight(a_RelPos); } bool cChunk::GetChunkAndRelByAbsolute(const Vector3d & a_Position, cChunk ** a_Chunk, Vector3i & a_Rel) { return GetChunkAndRelByAbsolute(Vector3i(FloorC(a_Position.x), FloorC(a_Position.y), FloorC(a_Position.z)), a_Chunk, a_Rel); } bool cChunk::GetChunkAndRelByAbsolute(const Vector3i & a_Position, cChunk ** a_Chunk, Vector3i & a_Rel) { *a_Chunk = this->GetNeighborChunk(a_Position.x, a_Position.z); if ((*a_Chunk == nullptr) || !(*a_Chunk)->IsValid()) { return false; } a_Rel.x = a_Position.x - (*a_Chunk)->GetPosX() * cChunkDef::Width; a_Rel.y = a_Position.y; a_Rel.z = a_Position.z - (*a_Chunk)->GetPosZ() * cChunkDef::Width; return true; } cChunk * cChunk::GetNeighborChunk(int a_BlockX, int a_BlockZ) { // Convert coords to relative, then call the relative version: a_BlockX -= m_PosX * cChunkDef::Width; a_BlockZ -= m_PosZ * cChunkDef::Width; return GetRelNeighborChunk(a_BlockX, a_BlockZ); } cChunk * cChunk::GetRelNeighborChunk(int a_RelX, int a_RelZ) { // If the relative coords are too far away, use the parent's chunk lookup instead: if ((a_RelX < -128) || (a_RelX > 128) || (a_RelZ < -128) || (a_RelZ > 128)) { int BlockX = m_PosX * cChunkDef::Width + a_RelX; int BlockZ = m_PosZ * cChunkDef::Width + a_RelZ; int ChunkX, ChunkZ; cChunkDef::BlockToChunk(BlockX, BlockZ, ChunkX, ChunkZ); return m_ChunkMap->FindChunk(ChunkX, ChunkZ); } // Walk the neighbors: bool ReturnThis = true; if (a_RelX < 0) { if (m_NeighborXM != nullptr) { cChunk * Candidate = m_NeighborXM->GetRelNeighborChunk(a_RelX + cChunkDef::Width, a_RelZ); if (Candidate != nullptr) { return Candidate; } } // Going X first failed, but if the request is crossing Z as well, let's try the Z first later on. ReturnThis = false; } else if (a_RelX >= cChunkDef::Width) { if (m_NeighborXP != nullptr) { cChunk * Candidate = m_NeighborXP->GetRelNeighborChunk(a_RelX - cChunkDef::Width, a_RelZ); if (Candidate != nullptr) { return Candidate; } } // Going X first failed, but if the request is crossing Z as well, let's try the Z first later on. ReturnThis = false; } if (a_RelZ < 0) { if (m_NeighborZM != nullptr) { return m_NeighborZM->GetRelNeighborChunk(a_RelX, a_RelZ + cChunkDef::Width); // For requests crossing both X and Z, the X-first way has been already tried } return nullptr; } else if (a_RelZ >= cChunkDef::Width) { if (m_NeighborZP != nullptr) { return m_NeighborZP->GetRelNeighborChunk(a_RelX, a_RelZ - cChunkDef::Width); // For requests crossing both X and Z, the X-first way has been already tried } return nullptr; } return (ReturnThis ? this : nullptr); } cChunk * cChunk::GetRelNeighborChunkAdjustCoords(Vector3i & a_RelPos) const { cChunk * ToReturn = const_cast(this); // The most common case: inside this chunk: if ( (a_RelPos.x >= 0) && (a_RelPos.x < cChunkDef::Width) && (a_RelPos.z >= 0) && (a_RelPos.z < cChunkDef::Width) ) { return ToReturn; } // Request for a different chunk, calculate chunk offset: int RelX = a_RelPos.x; // Make a local copy of the coords (faster access) int RelZ = a_RelPos.z; while ((RelX >= cChunkDef::Width) && (ToReturn != nullptr)) { RelX -= cChunkDef::Width; ToReturn = ToReturn->m_NeighborXP; } while ((RelX < 0) && (ToReturn != nullptr)) { RelX += cChunkDef::Width; ToReturn = ToReturn->m_NeighborXM; } while ((RelZ >= cChunkDef::Width) && (ToReturn != nullptr)) { RelZ -= cChunkDef::Width; ToReturn = ToReturn->m_NeighborZP; } while ((RelZ < 0) && (ToReturn != nullptr)) { RelZ += cChunkDef::Width; ToReturn = ToReturn->m_NeighborZM; } if (ToReturn != nullptr) { a_RelPos.x = RelX; a_RelPos.z = RelZ; return ToReturn; } // The chunk cannot be walked through neighbors, find it through the chunkmap: int AbsX = a_RelPos.x + m_PosX * cChunkDef::Width; int AbsZ = a_RelPos.z + m_PosZ * cChunkDef::Width; int DstChunkX, DstChunkZ; cChunkDef::BlockToChunk(AbsX, AbsZ, DstChunkX, DstChunkZ); ToReturn = m_ChunkMap->FindChunk(DstChunkX, DstChunkZ); a_RelPos.x = AbsX - DstChunkX * cChunkDef::Width; a_RelPos.z = AbsZ - DstChunkZ * cChunkDef::Width; return ToReturn; } void cChunk::SendBlockEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cClientHandle & a_Client) { cBlockEntity * Entity = GetBlockEntity(a_BlockX, a_BlockY, a_BlockZ); if (Entity == nullptr) { return; } Entity->SendTo(a_Client); } void cChunk::PositionToWorldPosition(int a_RelX, int a_RelY, int a_RelZ, int & a_BlockX, int & a_BlockY, int & a_BlockZ) { a_BlockY = a_RelY; a_BlockX = m_PosX * cChunkDef::Width + a_RelX; a_BlockZ = m_PosZ * cChunkDef::Width + a_RelZ; } Vector3i cChunk::PositionToWorldPosition(int a_RelX, int a_RelY, int a_RelZ) { return Vector3i(m_PosX * cChunkDef::Width + a_RelX, a_RelY, m_PosZ * cChunkDef::Width + a_RelZ); } NIBBLETYPE cChunk::GetTimeAlteredLight(NIBBLETYPE a_Skylight) const { a_Skylight -= m_World->GetSkyDarkness(); // Because NIBBLETYPE is unsigned, we clamp it to 0 .. 15 by checking for values above 15 return (a_Skylight < 16)? a_Skylight : 0; } bool cChunk::IsSlimeChunk() const { return m_World->IsSlimeChunk(m_PosX, m_PosZ); } ================================================ FILE: src/Chunk.h ================================================ #pragma once #include "BlockEntities/BlockEntity.h" #include "ChunkData.h" #include "Simulator/FireSimulator.h" #include "Simulator/SandSimulator.h" #include "ChunkMap.h" class cWorld; class cClientHandle; class cPlayer; class cChunkMap; class cBoundingBox; class cChunkDataCallback; class cBlockArea; class cBlockArea; class cFluidSimulatorData; class cMobCensus; class cMobSpawner; class cRedstoneSimulatorChunkData; struct SetChunkData; // A convenience macro for calling GetChunkAndRelByAbsolute. #define PREPARE_REL_AND_CHUNK(Position, OriginalChunk) cChunk * Chunk; Vector3i Rel; bool RelSuccess = (OriginalChunk).GetChunkAndRelByAbsolute(Position, &Chunk, Rel) class cChunk { public: /** Represents the presence state of the chunk */ enum ePresence { cpInvalid, /**< The chunk is not present at all and is not queued in the loader / generator */ cpQueued, /**< The chunk is not present, but is queued for loading / generation */ cpPresent, /**< The chunk is present */ }; cChunk( int a_ChunkX, int a_ChunkZ, // Chunk coords cChunkMap * a_ChunkMap, cWorld * a_World // Parent objects ); cChunk(const cChunk & Other) = delete; ~cChunk(); /** Flushes the pending block (entity) queue, and clients' outgoing data buffers. */ void BroadcastPendingChanges(void); /** Returns true iff the chunk block data is valid (loaded / generated) */ bool IsValid(void) const {return (m_Presence == cpPresent); } /** Returns true iff the chunk is in the queue for loading / generating */ bool IsQueued(void) const {return (m_Presence == cpQueued); } /** Sets the chunk's presence. Wakes up any calls to cChunkMap::GetHeight() when setting to cpPresent. */ void SetPresence(ePresence a_Presence); /** Marks all clients attached to this chunk as wanting this chunk. Also sets presence to cpQueued. */ void MarkRegenerating(void); /** Returns true iff the chunk has changed since it was last saved. */ bool IsDirty(void) const {return m_IsDirty; } bool CanUnload(void) const; /** Returns true if the chunk could have been unloaded if it weren't dirty */ bool CanUnloadAfterSaving(void) const; /** Called when the chunkmap unloads unused chunks. Notifies contained entities that they are being unloaded and should for example, broadcast a destroy packet. Not called during server shutdown; such cleanup during shutdown is unnecessary. */ void OnUnload(); bool IsLightValid(void) const {return m_IsLightValid; } /* To save a chunk, the WSSchema must: 1. Mark the chunk as being saved (MarkSaving()) 2. Get the chunk's data using GetAllData() 3. Mark the chunk as saved (MarkSaved()) If anywhere inside this sequence another thread mmodifies the chunk, the chunk will not get marked as saved in MarkSaved() */ void MarkSaving(void); // Marks the chunk as being saved. void MarkSaved(void); // Marks the chunk as saved, if it didn't change from the last call to MarkSaving() void MarkLoaded(void); // Marks the chunk as freshly loaded. Fails if the chunk is already valid /** Queues the chunk for generating. */ void MarkLoadFailed(void); /** Gets all chunk data, calls the a_Callback's methods for each data type */ void GetAllData(cChunkDataCallback & a_Callback) const; /** Sets all chunk data as either loaded from the storage or generated. BlockLight and BlockSkyLight are optional, if not present, chunk will be marked as unlighted. Modifies the BlockEntity list in a_SetChunkData - moves the block entities into the chunk. */ void SetAllData(SetChunkData && a_SetChunkData); void SetLight( const cChunkDef::BlockNibbles & a_BlockLight, const cChunkDef::BlockNibbles & a_SkyLight ); /** Writes the specified cBlockArea at the coords specified. Note that the coords may extend beyond the chunk! */ void WriteBlockArea(cBlockArea & a_Area, int a_MinBlockX, int a_MinBlockY, int a_MinBlockZ, int a_DataTypes); /** Sets or resets the internal flag that prevents chunk from being unloaded. The flag is cumulative - it can be set multiple times and then needs to be un-set that many times before the chunk is unloadable again. */ void Stay(bool a_Stay = true); /** Recence all mobs proximities to players in order to know what to do with them */ void CollectMobCensus(cMobCensus & toFill); /** Try to Spawn Monsters inside chunk */ void SpawnMobs(cMobSpawner & a_MobSpawner); void Tick(std::chrono::milliseconds a_Dt); /** Ticks a single block. Used by cWorld::TickQueuedBlocks() to tick the queued blocks */ void TickBlock(const Vector3i a_RelPos); int GetPosX(void) const { return m_PosX; } int GetPosZ(void) const { return m_PosZ; } cChunkCoords GetPos() const { return {m_PosX, m_PosZ}; } cWorld * GetWorld(void) const { return m_World; } void SetBlock(Vector3i a_RelBlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta); // SetBlock() does a lot of work (heightmap, tickblocks, blockentities) so a BlockIdx version doesn't make sense void FastSetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, BLOCKTYPE a_BlockMeta); // Doesn't force block updates on neighbors, use for simple changes such as grass growing etc. void FastSetBlock(Vector3i a_RelPos, BLOCKTYPE a_BlockType, BLOCKTYPE a_BlockMeta) { FastSetBlock(a_RelPos.x, a_RelPos.y, a_RelPos.z, a_BlockType, a_BlockMeta); } BLOCKTYPE GetBlock(int a_RelX, int a_RelY, int a_RelZ) const { return m_BlockData.GetBlock({ a_RelX, a_RelY, a_RelZ }); } BLOCKTYPE GetBlock(Vector3i a_RelCoords) const { return m_BlockData.GetBlock(a_RelCoords); } void GetBlockTypeMeta(Vector3i a_RelPos, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta) const; void GetBlockTypeMeta(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta) const { GetBlockTypeMeta({ a_RelX, a_RelY, a_RelZ }, a_BlockType, a_BlockMeta); } void GetBlockInfo(Vector3i a_RelPos, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_Meta, NIBBLETYPE & a_SkyLight, NIBBLETYPE & a_BlockLight) const; /** Convert absolute coordinates into relative coordinates. Returns false on failure to obtain a valid chunk. Returns true otherwise. @param a_Position The position you'd like to convert, a_Position need not be in the calling chunk and can safely be out of its bounds, but for best performance, it should not be too far from the calling chunk. @param a_Chunk Returns the chunk in which a_Position is in. If a_Position is within the calling chunk's bounds, returns the calling chunk. For best performance, a_Position shouldn't be too far from the calling chunk. @param a_Rel Returns the converted relative position. Note that it is relative to the returned a_Chunk. The vector will not be modified if the function returns false. */ bool GetChunkAndRelByAbsolute(const Vector3d & a_Position, cChunk ** a_Chunk, Vector3i & a_Rel); /** Convert absolute coordinates into relative coordinates. Returns false on failure to obtain a valid chunk. Returns true otherwise. @param a_Position The position you'd like to convert, a_Position need not be in the calling chunk and can safely be out of its bounds, but for best performance, it should not be too far from the calling chunk. @param a_Chunk Returns the chunk in which a_Position is in. If a_Position is within the calling chunk's bounds, returns the calling chunk. For best performance, a_Position shouldn't be too far from the calling chunk. @param a_Rel Returns the converted relative position. Note that it is relative to the returned a_Chunk. The vector will not be modified if the function returns false. */ bool GetChunkAndRelByAbsolute(const Vector3i & a_Position, cChunk ** a_Chunk, Vector3i & a_Rel); /** Returns the chunk into which the specified block belongs, by walking the neighbors. Will return self if appropriate. Returns nullptr if not reachable through neighbors. */ cChunk * GetNeighborChunk(int a_BlockX, int a_BlockZ); /** Returns the chunk into which the relatively-specified block belongs, by walking the neighbors. Will return self if appropriate. Returns nullptr if not reachable through neighbors. */ cChunk * GetRelNeighborChunk(int a_RelX, int a_RelZ); /** Returns the chunk into which the relatively-specified block belongs. Also modifies the relative coords from this-relative to return-relative. Will return self if appropriate. Will try walking the neighbors first; if that fails, will query the chunkmap. */ cChunk * GetRelNeighborChunkAdjustCoords(Vector3i & a_RelPos) const; EMCSBiome GetBiomeAt(int a_RelX, int a_RelZ) const {return cChunkDef::GetBiome(m_BiomeMap, a_RelX, a_RelZ); } /** Sets the biome at the specified relative coords. Doesn't resend the chunk to clients. */ void SetBiomeAt(int a_RelX, int a_RelZ, EMCSBiome a_Biome); /** Sets the biome in the specified relative coords area. All the coords are inclusive. Sends the chunk to all relevant clients. */ void SetAreaBiome(int a_MinRelX, int a_MaxRelX, int a_MinRelZ, int a_MaxRelZ, EMCSBiome a_Biome); int GetHeight( int a_X, int a_Z) const; /** Returns true if it is sunny at the specified location. This takes into account biomes. */ bool IsWeatherSunnyAt(int a_RelX, int a_RelZ) const; /** Returns true if it is raining or storming at the specified location, taking into account biomes. */ bool IsWeatherWetAt(int a_RelX, int a_RelZ) const; /** Returns true if it is raining or storming at the specified location, and the rain reaches (the bottom of) the specified block position. */ bool IsWeatherWetAt(Vector3i a_Position) const; void SendBlockTo(int a_RelX, int a_RelY, int a_RelZ, cClientHandle * a_Client); /** Adds a client to the chunk; returns true if added, false if already there */ bool AddClient(cClientHandle * a_Client); /** Removes the specified client from the chunk; ignored if client not in chunk. */ void RemoveClient(cClientHandle * a_Client); /** Returns true if the specified client is present in this chunk. */ bool HasClient(cClientHandle * a_Client); /** Returns true if theres any client in the chunk; false otherwise */ bool HasAnyClients(void) const; void AddEntity(OwnedEntity a_Entity); /** Releases ownership of the given entity if it was found in this chunk. Returns an owning reference to the found entity. */ OwnedEntity RemoveEntity(cEntity & a_Entity); bool HasEntity(UInt32 a_EntityID) const; /** Calls the callback for each entity; returns true if all entities processed, false if the callback aborted by returning true */ bool ForEachEntity(cEntityCallback a_Callback) const; // Lua-accessible /** Calls the callback for each entity that has a nonempty intersection with the specified boundingbox. Returns true if all entities processed, false if the callback aborted by returning true. */ bool ForEachEntityInBox(const cBoundingBox & a_Box, cEntityCallback a_Callback) const; // Lua-accessible /** Calls the callback if the entity with the specified ID is found, with the entity object as the callback param. Returns true if entity found. */ bool DoWithEntityByID(UInt32 a_EntityID, cEntityCallback a_Callback, bool & a_CallbackResult) const; // Lua-accessible /** Calls the callback for each block entity; returns true if all block entities processed, false if the callback aborted by returning true */ bool ForEachBlockEntity(cBlockEntityCallback a_Callback); // Lua-accessible /** Calls the callback for the block entity at the specified coords; returns false if there's no block entity at those coords, and whatever the callback returns if found. */ bool DoWithBlockEntityAt(Vector3i a_Position, cBlockEntityCallback a_Callback); // Lua-acessible /** Use block entity on coordinate. returns true if the use was successful, return false to use the block as a "normal" block */ bool UseBlockEntity(cPlayer * a_Player, int a_X, int a_Y, int a_Z); // [x, y, z] in world block coords void SendBlockEntity (int a_BlockX, int a_BlockY, int a_BlockZ, cClientHandle & a_Client); Vector3i PositionToWorldPosition(Vector3i a_RelPos) { return PositionToWorldPosition(a_RelPos.x, a_RelPos.y, a_RelPos.z); } void PositionToWorldPosition(int a_RelX, int a_RelY, int a_RelZ, int & a_BlockX, int & a_BlockY, int & a_BlockZ); Vector3i PositionToWorldPosition(int a_RelX, int a_RelY, int a_RelZ); inline void MarkDirty(void) { m_IsDirty = true; m_IsSaving = false; } /** Causes the specified block to be ticked on the next Tick() call. Plugins can use this via the cWorld:SetNextBlockToTick() API. Only one block coord per chunk may be set, a second call overwrites the first call */ inline void SetNextBlockToTick(const Vector3i a_RelPos) { m_BlockToTick = a_RelPos; } inline NIBBLETYPE GetMeta(int a_RelX, int a_RelY, int a_RelZ) const { return m_BlockData.GetMeta({ a_RelX, a_RelY, a_RelZ }); } NIBBLETYPE GetMeta(Vector3i a_RelPos) const { return m_BlockData.GetMeta(a_RelPos); } void SetMeta(int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_Meta) { SetMeta({ a_RelX, a_RelY, a_RelZ }, a_Meta); } inline void SetMeta(Vector3i a_RelPos, NIBBLETYPE a_Meta) { m_BlockData.SetMeta(a_RelPos, a_Meta); MarkDirty(); m_PendingSendBlocks.emplace_back(m_PosX, m_PosZ, a_RelPos.x, a_RelPos.y, a_RelPos.z, GetBlock(a_RelPos), a_Meta); } /** Light alterations based on time */ NIBBLETYPE GetTimeAlteredLight(NIBBLETYPE a_Skylight) const; /** Get the level of artificial light illuminating the block (0 - 15) */ inline NIBBLETYPE GetBlockLight(Vector3i a_RelPos) const { return m_LightData.GetBlockLight(a_RelPos); } inline NIBBLETYPE GetBlockLight(int a_RelX, int a_RelY, int a_RelZ) const { return m_LightData.GetBlockLight({ a_RelX, a_RelY, a_RelZ }); } /** Get the level of sky light illuminating the block (0 - 15) independent of daytime. */ inline NIBBLETYPE GetSkyLight(Vector3i a_RelPos) const { return m_LightData.GetSkyLight(a_RelPos); } inline NIBBLETYPE GetSkyLight(int a_RelX, int a_RelY, int a_RelZ) const { return m_LightData.GetSkyLight({ a_RelX, a_RelY, a_RelZ }); } /** Get the level of sky light illuminating the block (0 - 15), taking daytime into a account. */ inline NIBBLETYPE GetSkyLightAltered(Vector3i a_RelPos) const { return GetTimeAlteredLight(m_LightData.GetSkyLight(a_RelPos)); } inline NIBBLETYPE GetSkyLightAltered(int a_RelX, int a_RelY, int a_RelZ) const { return GetSkyLightAltered({ 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, false if queried chunk not loaded. */ bool UnboundedRelGetBlock(Vector3i a_RelCoords, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta) const; /** OBSOLETE, use the Vector3i-based overload. 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, false if queried chunk not loaded. */ bool UnboundedRelGetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta) const { return UnboundedRelGetBlock({a_RelX, a_RelY, a_RelZ}, a_BlockType, a_BlockMeta); } /** Same as GetBlockType(), but relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in such a case) Returns true on success, false if queried chunk not loaded. */ bool UnboundedRelGetBlockType(Vector3i a_RelCoords, BLOCKTYPE & a_BlockType) const; /** OBSOLETE, use the Vector3i-based overload. Same as GetBlockType(), but relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in such a case) Returns true on success, false if queried chunk not loaded. */ bool UnboundedRelGetBlockType(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE & a_BlockType) const { return UnboundedRelGetBlockType({a_RelX, a_RelY, a_RelZ}, a_BlockType); } /** Same as GetBlockMeta(), but relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in such a case) Returns true on success, false if queried chunk not loaded. */ bool UnboundedRelGetBlockMeta(Vector3i a_RelPos, NIBBLETYPE & a_BlockMeta) const; /** OBSOLETE, use the Vector3i-based overload. Same as GetBlockMeta(), but relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in such a case) Returns true on success, false if queried chunk not loaded. */ bool UnboundedRelGetBlockMeta(int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE & a_BlockMeta) const { return UnboundedRelGetBlockMeta({a_RelX, a_RelY, a_RelZ}, a_BlockMeta); } /** Same as GetBlockBlockLight(), but relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in such a case) Returns true on success, false if queried chunk not loaded. */ bool UnboundedRelGetBlockBlockLight(Vector3i a_RelPos, NIBBLETYPE & a_BlockLight) const; /** OBSOLETE, use the Vector3i-based overload. Same as GetBlockBlockLight(), but relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in such a case) Returns true on success, false if queried chunk not loaded. */ bool UnboundedRelGetBlockBlockLight(int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE & a_BlockLight) const { return UnboundedRelGetBlockBlockLight({a_RelX, a_RelY, a_RelZ}, a_BlockLight); } /** Same as GetBlockSkyLight(), but relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in such a case) Returns true on success, false if queried chunk not loaded. */ bool UnboundedRelGetBlockSkyLight(Vector3i a_RelPos, NIBBLETYPE & a_SkyLight) const; /** OBSOLETE, use the Vector3i-based overload. Same as GetBlockSkyLight(), but relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in such a case) Returns true on success, false if queried chunk not loaded. */ bool UnboundedRelGetBlockSkyLight(int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE & a_SkyLight) const { return UnboundedRelGetBlockSkyLight({a_RelX, a_RelY, a_RelZ}, a_SkyLight); } /** Queries both BlockLight and SkyLight, relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in such a case) Returns true on success, false if queried chunk not loaded. */ bool UnboundedRelGetBlockLights(Vector3i a_RelPos, NIBBLETYPE & a_BlockLight, NIBBLETYPE & a_SkyLight) const; /** OBSOLETE, use the Vector3i-based overload. Queries both BlockLight and SkyLight, relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in such a case) Returns true on success, false if queried chunk not loaded. */ bool UnboundedRelGetBlockLights(int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE & a_BlockLight, NIBBLETYPE & a_SkyLight) const { return UnboundedRelGetBlockLights({a_RelX, a_RelY, a_RelZ}, a_BlockLight, a_SkyLight); } /** Same as SetBlock(), but relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in such a case) Returns true on success, false if queried chunk not loaded. */ bool UnboundedRelSetBlock(Vector3i a_RelPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta); /** OBSOLETE, use the Vector3i-based overload. Same as SetBlock(), but relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in such a case) Returns true on success, false if queried chunk not loaded. */ bool UnboundedRelSetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) { return UnboundedRelSetBlock({a_RelX, a_RelY, a_RelZ}, a_BlockType, a_BlockMeta); } /** Same as FastSetBlock(), but relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in such a case) Returns true on success, false if queried chunk not loaded. */ bool UnboundedRelFastSetBlock(Vector3i a_RelPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta); /** OBSOLETE, use the Vector3i-based overload. Same as FastSetBlock(), but relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in such a case) Returns true on success, false if queried chunk not loaded. */ bool UnboundedRelFastSetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) { return UnboundedRelFastSetBlock({a_RelX, a_RelY, a_RelZ}, a_BlockType, a_BlockMeta); } // Per-chunk simulator data: cFireSimulatorChunkData & GetFireSimulatorData (void) { return m_FireSimulatorData; } cFluidSimulatorData * GetWaterSimulatorData(void) const { return m_WaterSimulatorData; } cFluidSimulatorData * GetLavaSimulatorData (void) const { return m_LavaSimulatorData; } cSandSimulatorChunkData & GetSandSimulatorData (void) { return m_SandSimulatorData; } cRedstoneSimulatorChunkData * GetRedstoneSimulatorData(void) const { return m_RedstoneSimulatorData; } /** Returns the block entity at the specified (absolute) coords. Returns nullptr if no such BE or outside this chunk. */ cBlockEntity * GetBlockEntity(Vector3i a_AbsPos); /** OBSOLETE, use the Vector3i-based overload instead. Returns the block entity at the specified (absolute) coords. Returns nullptr if no such BE or outside this chunk. */ cBlockEntity * GetBlockEntity(int a_BlockX, int a_BlockY, int a_BlockZ) { return GetBlockEntity({a_BlockX, a_BlockY, a_BlockZ}); } /** Returns the block entity at the specified (relative) coords. Returns nullptr if no such BE. Asserts that the position is a valid relative position. */ cBlockEntity * GetBlockEntityRel(Vector3i a_RelPos); /** Returns true if the chunk should be ticked in the tick-thread. Checks if there are any clients and if the always-tick flag is set */ bool ShouldBeTicked(void) const; /** Increments (a_AlwaysTicked == true) or decrements (false) the m_AlwaysTicked counter. If the m_AlwaysTicked counter is greater than zero, the chunk is ticked in the tick-thread regardless of whether it has any clients or not. When this is set, the chunk never unloads. This function allows nesting and task-concurrency (multiple separate tasks can request ticking and as long as at least one requests is active the chunk will be ticked). */ void SetAlwaysTicked(bool a_AlwaysTicked); const auto & GetAllClients(void) const { return m_LoadedByClient; } /** Converts the coord relative to this chunk into an absolute coord. Doesn't check relative coord validity. */ Vector3i RelativeToAbsolute(Vector3i a_RelBlockPosition) const { return cChunkDef::RelativeToAbsolute(a_RelBlockPosition, {m_PosX, m_PosZ}); } /** Returns true if slimes should spawn in the chunk. */ bool IsSlimeChunk() const; private: friend class cChunkMap; struct sSetBlockQueueItem { Int64 m_Tick; int m_RelX, m_RelY, m_RelZ; BLOCKTYPE m_BlockType; NIBBLETYPE m_BlockMeta; BLOCKTYPE m_PreviousType; sSetBlockQueueItem(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Int64 a_Tick, BLOCKTYPE a_PreviousBlockType) : m_Tick(a_Tick), m_RelX(a_RelX), m_RelY(a_RelY), m_RelZ(a_RelZ), m_BlockType(a_BlockType), m_BlockMeta(a_BlockMeta), m_PreviousType(a_PreviousBlockType) { } } ; typedef std::vector sSetBlockQueueVector; /** Holds the presence status of the chunk - if it is present, or in the loader / generator queue, or unloaded */ ePresence m_Presence; bool m_IsLightValid; // True if the blocklight and skylight are calculated bool m_IsDirty; // True if the chunk has changed since it was last saved bool m_IsSaving; // True if the chunk is being saved /** Blocks that have changed and need to be sent to all clients. The protocol has a provision for coalescing block changes, and this is the buffer. It will collect the block changes that occur in a tick, before being flushed in BroadcastPendingSendBlocks. */ sSetBlockVector m_PendingSendBlocks; /** Block entities that have been touched and need to be sent to all clients. Because block changes are buffered and we need to happen after them, this buffer exists too. Pointers to block entities that were destroyed are guaranteed to be removed from this array by SetAllData, SetBlock, WriteBlockArea. */ std::vector m_PendingSendBlockEntities; /** A queue of relative positions to call cBlockHandler::Check on. Processed at the end of each tick by CheckBlocks. */ std::queue m_BlocksToCheck; // A critical section is not needed, because all chunk access is protected by its parent ChunkMap's csLayers std::vector m_LoadedByClient; std::vector m_Entities; cBlockEntities m_BlockEntities; /** Number of times the chunk has been requested to stay (by various cChunkStay objects); if zero, the chunk can be unloaded */ unsigned m_StayCount; int m_PosX, m_PosZ; cWorld * m_World; cChunkMap * m_ChunkMap; ChunkBlockData m_BlockData; ChunkLightData m_LightData; cChunkDef::HeightMap m_HeightMap; cChunkDef::BiomeMap m_BiomeMap; /** Relative coords of the block to tick first in the next Tick() call. Plugins can use this to force a tick in a specific block, using cWorld:SetNextBlockToTick() API. */ Vector3i m_BlockToTick; cChunk * m_NeighborXM; // Neighbor at [X - 1, Z] cChunk * m_NeighborXP; // Neighbor at [X + 1, Z] cChunk * m_NeighborZM; // Neighbor at [X, Z - 1] cChunk * m_NeighborZP; // Neighbor at [X, Z + 1] // Per-chunk simulator data: cFireSimulatorChunkData m_FireSimulatorData; cFluidSimulatorData * m_WaterSimulatorData; cFluidSimulatorData * m_LavaSimulatorData; cSandSimulatorChunkData m_SandSimulatorData; cRedstoneSimulatorChunkData * m_RedstoneSimulatorData; /** If greater than zero, the chunk is ticked even if it has no clients. Manipulated by the SetAlwaysTicked() function, allows for nested calls of the function. This is the support for plugin-accessible chunk tick forcing. */ unsigned m_AlwaysTicked; // Pick up a random block of this chunk void GetRandomBlockCoords(int & a_X, int & a_Y, int & a_Z); void GetThreeRandomNumbers(int & a_X, int & a_Y, int & a_Z, int a_MaxX, int a_MaxY, int a_MaxZ); /** Takes ownership of a block entity, which MUST actually reside in this chunk. */ void AddBlockEntity(OwnedBlockEntity a_BlockEntity); /** Wakes up each simulator for its specific blocks; through all the blocks in the chunk */ void WakeUpSimulators(void); /** Checks the block scheduled for checking in m_ToTickBlocks[] */ void CheckBlocks(); /** Ticks several random blocks in the chunk. */ void TickBlocks(void); /** Adds snow to the top of snowy biomes and hydrates farmland / fills cauldrons in rainy biomes */ void ApplyWeatherToTop(void); /** Returns the pickups that would be produced, if the specified block was dug up by a_Digger using a_Tool. Doesn't dig the block, only queries the block handlers and then plugins for the pickups. */ cItems PickupsFromBlock(Vector3i a_RelPos, const cEntity * a_Digger, const cItem * a_Tool); /** Grows the plant at the specified position by at most a_NumStages. The block's Grow handler is invoked. Returns the number of stages the plant has grown, 0 if not a plant. */ int GrowPlantAt(Vector3i a_RelPos, int a_NumStages = 1); /** Called by Tick() when an entity moves out of this chunk into a neighbor; moves the entity and sends spawn / despawn packet to clients */ void MoveEntityToNewChunk(OwnedEntity a_Entity); /** Check m_Entities for cPlayer objects. */ bool HasPlayerEntities() const; }; ================================================ FILE: src/ChunkData.cpp ================================================ // 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" #include "BlockType.h" namespace { struct SectionIndices { size_t Section = 0; // Index into m_Sections size_t Index = 0; // Index into a single sChunkSection }; inline SectionIndices IndicesFromRelPos(const Vector3i a_RelPos) { ASSERT(cChunkDef::IsValidRelPos(a_RelPos)); return { static_cast(a_RelPos.y / cChunkDef::SectionHeight), cChunkDef::MakeIndex(a_RelPos.x, a_RelPos.y % cChunkDef::SectionHeight, a_RelPos.z) }; } bool IsCompressed(const size_t ElementCount) { return ElementCount != ChunkBlockData::SectionBlockCount; } template ValueType UnpackDefaultValue(const ValueType DefaultValue) { if (IsCompressed(ElementCount)) { return DefaultValue & 0xF; } return DefaultValue; } } // namespace (anonymous) template void ChunkDataStore::Assign(const ChunkDataStore & a_Other) { for (size_t Y = 0; Y != cChunkDef::NumSections; Y++) { Store[Y].reset(); if (const auto & Other = a_Other.Store[Y]; Other != nullptr) { Store[Y] = std::make_unique(*Other); } } } template ElementType ChunkDataStore::Get(const Vector3i a_Position) const { const auto Indices = IndicesFromRelPos(a_Position); const auto & Section = Store[Indices.Section]; if (Section != nullptr) { if (IsCompressed(ElementCount)) { return cChunkDef::ExpandNibble(Section->data(), Indices.Index); } else { return (*Section)[Indices.Index]; } } return UnpackDefaultValue(DefaultValue); } template typename ChunkDataStore::Type * ChunkDataStore::GetSection(const size_t a_Y) const { return Store[a_Y].get(); } template void ChunkDataStore::Set(const Vector3i a_Position, const ElementType a_Value) { const auto Indices = IndicesFromRelPos(a_Position); auto & Section = Store[Indices.Section]; if (Section == nullptr) { if (a_Value == UnpackDefaultValue(DefaultValue)) { return; } Section = cpp20::make_unique_for_overwrite(); std::fill(Section->begin(), Section->end(), DefaultValue); } if (IsCompressed(ElementCount)) { cChunkDef::PackNibble(Section->data(), Indices.Index, a_Value); } else { (*Section)[Indices.Index] = a_Value; } } template void ChunkDataStore::SetSection(const ElementType (& a_Source)[ElementCount], const size_t a_Y) { auto & Section = Store[a_Y]; const auto SourceEnd = std::end(a_Source); if (Section != nullptr) { std::copy(a_Source, SourceEnd, Section->begin()); } else if (std::any_of(a_Source, SourceEnd, [](const auto Value) { return Value != DefaultValue; })) { Section = cpp20::make_unique_for_overwrite(); std::copy(a_Source, SourceEnd, Section->begin()); } } template void ChunkDataStore::SetAll(const ElementType (& a_Source)[cChunkDef::NumSections * ElementCount]) { for (size_t Y = 0; Y != cChunkDef::NumSections; Y++) { SetSection(*reinterpret_cast(a_Source + Y * ElementCount), Y); } } void ChunkBlockData::Assign(const ChunkBlockData & a_Other) { m_Blocks.Assign(a_Other.m_Blocks); m_Metas.Assign(a_Other.m_Metas); } void ChunkBlockData::SetAll(const cChunkDef::BlockTypes & a_BlockSource, const cChunkDef::BlockNibbles & a_MetaSource) { m_Blocks.SetAll(a_BlockSource); m_Metas.SetAll(a_MetaSource); } void ChunkBlockData::SetSection(const SectionType & a_BlockSource, const SectionMetaType & a_MetaSource, const size_t a_Y) { m_Blocks.SetSection(a_BlockSource, a_Y); m_Metas.SetSection(a_MetaSource, a_Y); } void ChunkLightData::Assign(const ChunkLightData & a_Other) { m_BlockLights.Assign(a_Other.m_BlockLights); m_SkyLights.Assign(a_Other.m_SkyLights); } void ChunkLightData::SetAll(const cChunkDef::BlockNibbles & a_BlockLightSource, const cChunkDef::BlockNibbles & a_SkyLightSource) { m_BlockLights.SetAll(a_BlockLightSource); m_SkyLights.SetAll(a_SkyLightSource); } void ChunkLightData::SetSection(const SectionType & a_BlockLightSource, const SectionType & a_SkyLightSource, const size_t a_Y) { m_BlockLights.SetSection(a_BlockLightSource, a_Y); m_SkyLights.SetSection(a_SkyLightSource, a_Y); } template struct ChunkDataStore; template struct ChunkDataStore; template struct ChunkDataStore; ================================================ FILE: src/ChunkData.h ================================================ // ChunkData.h // Declares the cChunkData class that represents the block's type, meta, blocklight and skylight storage for a chunk #pragma once #include "FunctionRef.h" #include "ChunkDef.h" template struct ChunkDataStore { using Type = std::array; /** Copy assign from another ChunkDataStore. */ void Assign(const ChunkDataStore & a_Other); /** Gets one value at the given position. Returns DefaultValue if the section is not allocated. */ ElementType Get(Vector3i a_Position) const; /** Returns a raw pointer to the internal representation of the specified section. Will be nullptr if the section is not allocated. */ Type * GetSection(size_t a_Y) const; /** Sets one value at the given position. Allocates a section if needed for the operation. */ void Set(Vector3i a_Position, ElementType a_Value); /** Copies the data from the specified flat section array into the internal representation. Allocates a section if needed for the operation. */ void SetSection(const ElementType (& a_Source)[ElementCount], size_t a_Y); /** Copies the data from the specified flat array into the internal representation. Allocates sections that are needed for the operation. */ void SetAll(const ElementType (& a_Source)[cChunkDef::NumSections * ElementCount]); /** Contains all the sections this ChunkDataStore manages. */ std::unique_ptr Store[cChunkDef::NumSections]; }; class ChunkBlockData { public: static constexpr size_t SectionBlockCount = cChunkDef::SectionHeight * cChunkDef::Width * cChunkDef::Width; static constexpr size_t SectionMetaCount = SectionBlockCount / 2; static constexpr BLOCKTYPE DefaultValue = 0x00; static constexpr NIBBLETYPE DefaultMetaValue = 0x00; using SectionType = BLOCKTYPE[SectionBlockCount]; using SectionMetaType = NIBBLETYPE[SectionMetaCount]; private: ChunkDataStore m_Blocks; ChunkDataStore m_Metas; public: using BlockArray = decltype(m_Blocks)::Type; using MetaArray = decltype(m_Metas)::Type; void Assign(const ChunkBlockData & a_Other); BLOCKTYPE GetBlock(Vector3i a_Position) const { return m_Blocks.Get(a_Position); } NIBBLETYPE GetMeta(Vector3i a_Position) const { return m_Metas.Get(a_Position); } BlockArray * GetSection(size_t a_Y) const { return m_Blocks.GetSection(a_Y); } MetaArray * GetMetaSection(size_t a_Y) const { return m_Metas.GetSection(a_Y); } void SetBlock(Vector3i a_Position, BLOCKTYPE a_Block) { m_Blocks.Set(a_Position, a_Block); } void SetMeta(Vector3i a_Position, NIBBLETYPE a_Meta) { m_Metas.Set(a_Position, a_Meta); } void SetAll(const cChunkDef::BlockTypes & a_BlockSource, const cChunkDef::BlockNibbles & a_MetaSource); void SetSection(const SectionType & a_BlockSource, const SectionMetaType & a_MetaSource, size_t a_Y); }; class ChunkLightData { public: static constexpr size_t SectionLightCount = (cChunkDef::SectionHeight * cChunkDef::Width * cChunkDef::Width) / 2; static constexpr NIBBLETYPE DefaultBlockLightValue = 0x00; static constexpr NIBBLETYPE DefaultSkyLightValue = 0xFF; using SectionType = NIBBLETYPE[SectionLightCount]; private: ChunkDataStore m_BlockLights; ChunkDataStore m_SkyLights; public: using LightArray = decltype(m_BlockLights)::Type; void Assign(const ChunkLightData & a_Other); NIBBLETYPE GetBlockLight(Vector3i a_Position) const { return m_BlockLights.Get(a_Position); } NIBBLETYPE GetSkyLight(Vector3i a_Position) const { return m_SkyLights.Get(a_Position); } LightArray * GetBlockLightSection(size_t a_Y) const { return m_BlockLights.GetSection(a_Y); } LightArray * GetSkyLightSection(size_t a_Y) const { return m_SkyLights.GetSection(a_Y); } void SetAll(const cChunkDef::BlockNibbles & a_BlockLightSource, const cChunkDef::BlockNibbles & a_SkyLightSource); void SetSection(const SectionType & a_BlockLightSource, const SectionType & a_SkyLightSource, size_t a_Y); }; /** Invokes the callback functor for every chunk section containing at least one present block or light section data. This is used to collect all data for all sections. In macro form to work around a Visual Studio 2017 ICE bug. */ #define ChunkDef_ForEachSection(BlockData, LightData, Callback) \ do \ { \ for (size_t Y = 0; Y < cChunkDef::NumSections; ++Y) \ { \ const auto Blocks = BlockData.GetSection(Y); \ const auto Metas = BlockData.GetMetaSection(Y); \ const auto BlockLights = LightData.GetBlockLightSection(Y); \ const auto SkyLights = LightData.GetSkyLightSection(Y); \ if ((Blocks != nullptr) || (Metas != nullptr) || (BlockLights != nullptr) || (SkyLights != nullptr)) \ { \ Callback \ } \ } \ } while (false) extern template struct ChunkDataStore; extern template struct ChunkDataStore; extern template struct ChunkDataStore; ================================================ FILE: src/ChunkDataCallback.h ================================================ // 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 { 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 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 data. */ virtual void ChunkData(const ChunkBlockData & a_BlockData, const ChunkLightData & a_LightData) { UNUSED(a_BlockData); UNUSED(a_LightData); } /** 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 BiomeMap(const cChunkDef::BiomeMap & a_BiomeMap) { UNUSED(a_BiomeMap); } /** Called for each entity in the chunk */ virtual void Entity(cEntity * a_Entity) { UNUSED(a_Entity); } /** Called for each block entity in the chunk */ virtual void BlockEntity(cBlockEntity * a_Entity) { UNUSED(a_Entity); } } ; /** A simple implementation of the cChunkDataCallback interface that just copies the cChunkData */ class cChunkDataCopyCollector : public cChunkDataCallback { public: ChunkBlockData m_BlockData; ChunkLightData m_LightData; private: virtual void ChunkData(const ChunkBlockData & a_BlockData, const ChunkLightData & a_LightData) override { m_BlockData.Assign(a_BlockData); m_LightData.Assign(a_LightData); } }; ================================================ FILE: src/ChunkDef.h ================================================ // ChunkDef.h // Interfaces to helper types for chunk definitions. Most modules want to include this instead of cChunk.h #pragma once #include "BiomeDef.h" // Used to smoothly convert to new axis ordering. One will be removed when deemed stable. #define AXIS_ORDER_YZX 1 // Original (1.1-) #define AXIS_ORDER_XZY 2 // New (1.2+) #define AXIS_ORDER AXIS_ORDER_XZY // fwd class cBlockEntity; class cEntity; class cClientHandle; class cBlockEntity; class cChunkCoords; using OwnedEntity = std::unique_ptr; using cEntityList = std::vector; // tolua_begin /** The datatype used by blockdata */ typedef unsigned char BLOCKTYPE; /** The datatype used by nibbledata (meta, light, skylight) */ typedef unsigned char NIBBLETYPE; /** The type used by the heightmap */ typedef unsigned char HEIGHTTYPE; // tolua_end /** Wraps the chunk coords into a single structure. */ class cChunkCoords { public: int m_ChunkX; int m_ChunkZ; cChunkCoords(int a_ChunkX, int a_ChunkZ) : m_ChunkX(a_ChunkX), m_ChunkZ(a_ChunkZ) {} bool operator == (const cChunkCoords & a_Other) const { return ((m_ChunkX == a_Other.m_ChunkX) && (m_ChunkZ == a_Other.m_ChunkZ)); } bool operator != (const cChunkCoords & a_Other) const { return !(operator == (a_Other)); } /** Simple comparison, to support ordering. */ bool operator < (const cChunkCoords & a_Other) const { if (a_Other.m_ChunkX == m_ChunkX) { return (m_ChunkZ < a_Other.m_ChunkZ); } else { return (m_ChunkX < a_Other.m_ChunkX); } } /** Returns a string that describes the chunk coords, suitable for logging. */ AString ToString() const { return fmt::format(FMT_STRING("[{}, {}]"), m_ChunkX, m_ChunkZ); } } ; /** Implements custom fmtlib formatting for cChunkCoords. */ namespace fmt { template <> struct formatter: formatter { auto format(cChunkCoords a_Coords, format_context & a_Ctx) { return format_to(a_Ctx.out(), "[{}, {}]", a_Coords.m_ChunkX, a_Coords.m_ChunkZ); } }; } /** Constants used throughout the code, useful typedefs and utility functions */ class cChunkDef { public: // Chunk dimensions: static const int Width = 16; static const int Height = 256; static const int NumBlocks = Width * Height * Width; static const int SectionHeight = 16; static const size_t NumSections = (cChunkDef::Height / SectionHeight); /** The type used for any heightmap operations and storage; idx = x + Width * z; Height points to the highest non-air block in the column */ typedef HEIGHTTYPE HeightMap[Width * Width]; /** The type used for any biomemap operations and storage inside Cuberite, using Cuberite biomes (need not correspond to client representation!) idx = x + Width * z */ typedef EMCSBiome BiomeMap[Width * Width]; /** The type used for block type operations and storage, AXIS_ORDER ordering */ typedef BLOCKTYPE BlockTypes[NumBlocks]; /** The type used for block data in nibble format, AXIS_ORDER ordering */ typedef NIBBLETYPE BlockNibbles[NumBlocks / 2]; /** Converts absolute block coords into relative (chunk + block) coords: */ inline static void AbsoluteToRelative(/* in-out */ int & a_X, int & a_Y, int & a_Z, /* out */ int & a_ChunkX, int & a_ChunkZ) { UNUSED(a_Y); BlockToChunk(a_X, a_Z, a_ChunkX, a_ChunkZ); a_X = a_X - a_ChunkX * Width; a_Z = a_Z - a_ChunkZ * Width; } /** Converts the specified absolute position into a relative position within its chunk. Use BlockToChunk to query the chunk coords. */ inline static Vector3i AbsoluteToRelative(Vector3i a_BlockPosition) { cChunkCoords chunkPos = BlockToChunk(a_BlockPosition); return AbsoluteToRelative(a_BlockPosition, chunkPos); } /** Converts the absolute coords into coords relative to the specified chunk. */ inline static Vector3i AbsoluteToRelative(Vector3i a_BlockPosition, cChunkCoords a_ChunkPos) { return { a_BlockPosition.x - a_ChunkPos.m_ChunkX * Width, a_BlockPosition.y, a_BlockPosition.z - a_ChunkPos.m_ChunkZ * Width }; } /** Converts relative block coordinates into absolute coordinates with a known chunk location */ inline static Vector3i RelativeToAbsolute(Vector3i a_RelBlockPosition, cChunkCoords a_ChunkCoords) { return Vector3i( a_RelBlockPosition.x + a_ChunkCoords.m_ChunkX * Width, a_RelBlockPosition.y, a_RelBlockPosition.z + a_ChunkCoords.m_ChunkZ * Width ); } /** Validates a height-coordinate. Returns false if height-coordinate is out of height bounds */ inline static bool IsValidHeight(Vector3i a_BlockPosition) { return ((a_BlockPosition.y >= 0) && (a_BlockPosition.y < Height)); } /** Validates a width-coordinate. Returns false if width-coordiante is out of width bounds */ inline static bool IsValidWidth(int a_Width) { return ((a_Width >= 0) && (a_Width < Width)); } /** Validates a chunk relative coordinate. Returns false if the coordiante is out of bounds for a chunk. */ inline static bool IsValidRelPos(Vector3i a_RelPos) { return ( IsValidWidth(a_RelPos.x) && IsValidHeight(a_RelPos) && IsValidWidth(a_RelPos.z) ); } /** Converts absolute block coords to chunk coords: */ inline static void BlockToChunk(int a_X, int a_Z, int & a_ChunkX, int & a_ChunkZ) { // This version is deprecated in favor of the vector version // If you're developing new code, use the other version. const auto ChunkCoords = BlockToChunk({ a_X, 0, a_Z }); a_ChunkX = ChunkCoords.m_ChunkX; a_ChunkZ = ChunkCoords.m_ChunkZ; } /** The Y coordinate of a_Pos is ignored */ inline static cChunkCoords BlockToChunk(const Vector3i a_Position) { return { FAST_FLOOR_DIV(a_Position.x, Width), FAST_FLOOR_DIV(a_Position.z, Width) }; } inline static size_t MakeIndex(int x, int y, int z) { ASSERT(IsValidRelPos({ x, y, z })); #if AXIS_ORDER == AXIS_ORDER_XZY // For some reason, NOT using the Horner schema is faster. Weird. return static_cast(x + (z * Width) + (y * Width * Width)); // 1.2 uses XZY #elif AXIS_ORDER == AXIS_ORDER_YZX return static_cast(y + (z * Width) + (x * Height * Width)); // 1.1 uses YZX #endif } inline static size_t MakeIndex(Vector3i a_RelPos) { return MakeIndex(a_RelPos.x, a_RelPos.y, a_RelPos.z); } inline static Vector3i IndexToCoordinate(size_t index) { #if AXIS_ORDER == AXIS_ORDER_XZY return Vector3i( // 1.2 static_cast(index % cChunkDef::Width), // X static_cast(index / (cChunkDef::Width * cChunkDef::Width)), // Y static_cast((index / cChunkDef::Width) % cChunkDef::Width) // Z ); #elif AXIS_ORDER == AXIS_ORDER_YZX return Vector3i( // 1.1 static_cast(index / (cChunkDef::Height * cChunkDef::Width)), // X static_cast(index % cChunkDef::Height), // Y static_cast((index / cChunkDef::Height) % cChunkDef::Width) // Z ); #endif } inline static void SetBlock(BLOCKTYPE * a_BlockTypes, int a_X, int a_Y, int a_Z, BLOCKTYPE a_Type) { ASSERT((a_X >= 0) && (a_X < Width)); ASSERT((a_Y >= 0) && (a_Y < Height)); ASSERT((a_Z >= 0) && (a_Z < Width)); a_BlockTypes[MakeIndex(a_X, a_Y, a_Z)] = a_Type; } inline static void SetBlock(BLOCKTYPE * a_BlockTypes, int a_Index, BLOCKTYPE a_Type) { ASSERT((a_Index >= 0) && (a_Index <= NumBlocks)); a_BlockTypes[a_Index] = a_Type; } inline static BLOCKTYPE GetBlock(const BLOCKTYPE * a_BlockTypes, Vector3i a_RelPos) { ASSERT(IsValidRelPos(a_RelPos)); return a_BlockTypes[MakeIndex(a_RelPos)]; } inline static BLOCKTYPE GetBlock(const BLOCKTYPE * a_BlockTypes, int a_X, int a_Y, int a_Z) { ASSERT((a_X >= 0) && (a_X < Width)); ASSERT((a_Y >= 0) && (a_Y < Height)); ASSERT((a_Z >= 0) && (a_Z < Width)); return a_BlockTypes[MakeIndex(a_X, a_Y, a_Z)]; } inline static BLOCKTYPE GetBlock(const BLOCKTYPE * a_BlockTypes, int a_Idx) { ASSERT((a_Idx >= 0) && (a_Idx < NumBlocks)); return a_BlockTypes[a_Idx]; } inline static HEIGHTTYPE GetHeight(const HeightMap & a_HeightMap, int a_X, int a_Z) { ASSERT((a_X >= 0) && (a_X < Width)); ASSERT((a_Z >= 0) && (a_Z < Width)); return a_HeightMap[a_X + Width * a_Z]; } inline static void SetHeight(HeightMap & a_HeightMap, int a_X, int a_Z, HEIGHTTYPE a_Height) { ASSERT((a_X >= 0) && (a_X < Width)); ASSERT((a_Z >= 0) && (a_Z < Width)); a_HeightMap[a_X + Width * a_Z] = a_Height; } inline static EMCSBiome GetBiome(const BiomeMap & a_BiomeMap, int a_X, int a_Z) { ASSERT((a_X >= 0) && (a_X < Width)); ASSERT((a_Z >= 0) && (a_Z < Width)); return a_BiomeMap[a_X + Width * a_Z]; } inline static void SetBiome(BiomeMap & a_BiomeMap, int a_X, int a_Z, EMCSBiome a_Biome) { ASSERT((a_X >= 0) && (a_X < Width)); ASSERT((a_Z >= 0) && (a_Z < Width)); a_BiomeMap[a_X + Width * a_Z] = a_Biome; } static NIBBLETYPE GetNibble(const NIBBLETYPE * a_Buffer, int x, int y, int z) { if ((x < Width) && (x > -1) && (y < Height) && (y > -1) && (z < Width) && (z > -1)) { return ExpandNibble(a_Buffer, MakeIndex(x, y, z)); } ASSERT(!"cChunkDef::GetNibble(): coords out of chunk range!"); return 0; } inline static void PackNibble(NIBBLETYPE * const a_Buffer, const size_t a_Index, const NIBBLETYPE a_Nibble) { ASSERT((a_Nibble & 0xF) == a_Nibble); // Only the lower bits should be set a_Buffer[a_Index / 2] = static_cast( (a_Buffer[a_Index / 2] & (0xf0 >> ((a_Index & 1) * 4))) | // The untouched nibble ((a_Nibble & 0x0f) << ((a_Index & 1) * 4)) // The nibble being set ); } inline static NIBBLETYPE ExpandNibble(const NIBBLETYPE * const a_Buffer, const size_t a_Index) { return (a_Buffer[a_Index / 2] >> ((a_Index & 1) * 4)) & 0x0f; } } ; /** Interface class used for comparing clients of two chunks. Used primarily for entity moving while both chunks are locked. */ class cClientDiffCallback { public: virtual ~cClientDiffCallback() {} /** Called for clients that are in Chunk1 and not in Chunk2, */ virtual void Removed(cClientHandle * a_Client) = 0; /** Called for clients that are in Chunk2 and not in Chunk1. */ virtual void Added(cClientHandle * a_Client) = 0; } ; struct sSetBlock { int m_RelX, m_RelY, m_RelZ; int m_ChunkX, m_ChunkZ; BLOCKTYPE m_BlockType; NIBBLETYPE m_BlockMeta; sSetBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta): m_RelX(a_BlockX), m_RelY(a_BlockY), m_RelZ(a_BlockZ), m_BlockType(a_BlockType), m_BlockMeta(a_BlockMeta) { cChunkDef::AbsoluteToRelative(m_RelX, m_RelY, m_RelZ, m_ChunkX, m_ChunkZ); } sSetBlock(Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) : sSetBlock(a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, a_BlockType, a_BlockMeta) { } sSetBlock(int a_ChunkX, int a_ChunkZ, int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) : m_RelX(a_RelX), m_RelY(a_RelY), m_RelZ(a_RelZ), m_ChunkX(a_ChunkX), m_ChunkZ(a_ChunkZ), m_BlockType(a_BlockType), m_BlockMeta(a_BlockMeta) { ASSERT((a_RelX >= 0) && (a_RelX < cChunkDef::Width)); ASSERT((a_RelZ >= 0) && (a_RelZ < cChunkDef::Width)); } /** Returns the absolute X coord of the stored block. */ int GetX(void) const { return m_RelX + cChunkDef::Width * m_ChunkX; } /** Returns the absolute Y coord of the stored block. Is the same as relative Y coords, because there's no Y relativization. */ int GetY(void) const { return m_RelY; } /** Returns the absolute Z coord of the stored block. */ int GetZ(void) const { return m_RelZ + cChunkDef::Width * m_ChunkZ; } /** Returns the absolute coords of the stored block. */ Vector3i GetAbsolutePos() const { return Vector3i(GetX(), GetY(), GetZ()); } /** Returns the relative position of the stored block within its chunk. */ Vector3i GetRelativePos() const { return Vector3i(m_RelX, m_RelY, m_RelZ); } }; typedef std::vector sSetBlockVector; typedef std::list cChunkCoordsList; typedef std::vector cChunkCoordsVector; /** A simple hash function for chunk coords, we assume that chunk coords won't use more than 16 bits, so the hash is almost an identity. Used for std::unordered_map */ class cChunkCoordsHash { public: size_t operator () (const cChunkCoords & a_Coords) const { return (static_cast(a_Coords.m_ChunkX) << 16) ^ static_cast(a_Coords.m_ChunkZ); } }; /** Interface class used as a callback for operations that involve chunk coords */ class cChunkCoordCallback { public: virtual ~cChunkCoordCallback() {} /** Called with the chunk's coords, and an optional operation status flag for operations that support it. */ virtual void Call(cChunkCoords a_Coords, bool a_IsSuccess) = 0; } ; /** Generic template that can store any kind of data together with a triplet of 3 coords */ template class cCoordWithData { public: int x; int y; int z; X Data; cCoordWithData(int a_X, int a_Y, int a_Z) : x(a_X), y(a_Y), z(a_Z), Data() { } cCoordWithData(int a_X, int a_Y, int a_Z, const X & a_Data) : x(a_X), y(a_Y), z(a_Z), Data(a_Data) { } } ; typedef cCoordWithData cCoordWithInt; typedef std::list cCoordWithIntList; typedef std::vector cCoordWithIntVector; ================================================ FILE: src/ChunkGeneratorThread.cpp ================================================ #include "Globals.h" #include "ChunkGeneratorThread.h" #include "Generating/ChunkGenerator.h" #include "Generating/ChunkDesc.h" /** If the generation queue size exceeds this number, a warning will be output */ const size_t QUEUE_WARNING_LIMIT = 1000; /** If the generation queue size exceeds this number, chunks with no clients will be skipped */ const size_t QUEUE_SKIP_LIMIT = 500; cChunkGeneratorThread::cChunkGeneratorThread(void) : Super("Chunk Generator"), m_Generator(nullptr), m_PluginInterface(nullptr), m_ChunkSink(nullptr) { } cChunkGeneratorThread::~cChunkGeneratorThread() { Stop(); } bool cChunkGeneratorThread::Initialize(cPluginInterface & a_PluginInterface, cChunkSink & a_ChunkSink, cIniFile & a_IniFile) { m_PluginInterface = &a_PluginInterface; m_ChunkSink = &a_ChunkSink; m_Generator = cChunkGenerator::CreateFromIniFile(a_IniFile); if (m_Generator == nullptr) { LOGERROR("Generator could not start, aborting the server"); return false; } return true; } void cChunkGeneratorThread::Stop(void) { m_ShouldTerminate = true; m_Event.Set(); m_evtRemoved.Set(); // Wake up anybody waiting for empty queue Super::Stop(); m_Generator.reset(); } void cChunkGeneratorThread::QueueGenerateChunk( cChunkCoords a_Coords, bool a_ForceRegeneration, cChunkCoordCallback * a_Callback ) { ASSERT(m_ChunkSink->IsChunkQueued(a_Coords)); { cCSLock Lock(m_CS); // Add to queue, issue a warning if too many: if (m_Queue.size() >= QUEUE_WARNING_LIMIT) { LOGWARN("WARNING: Adding chunk %s to generation queue; Queue is too big! (%zu)", a_Coords.ToString().c_str(), m_Queue.size()); } m_Queue.emplace_back(a_Coords, a_ForceRegeneration, a_Callback); } m_Event.Set(); } void cChunkGeneratorThread::GenerateBiomes(cChunkCoords a_Coords, cChunkDef::BiomeMap & a_BiomeMap) { if (m_Generator != nullptr) { m_Generator->GenerateBiomes(a_Coords, a_BiomeMap); } } void cChunkGeneratorThread::WaitForQueueEmpty(void) { cCSLock Lock(m_CS); while (!m_ShouldTerminate && !m_Queue.empty()) { cCSUnlock Unlock(Lock); m_evtRemoved.Wait(); } } size_t cChunkGeneratorThread::GetQueueLength(void) const { cCSLock Lock(m_CS); return m_Queue.size(); } int cChunkGeneratorThread::GetSeed() const { return m_Generator->GetSeed(); } EMCSBiome cChunkGeneratorThread::GetBiomeAt(int a_BlockX, int a_BlockZ) { ASSERT(m_Generator != nullptr); return m_Generator->GetBiomeAt(a_BlockX, a_BlockZ); } void cChunkGeneratorThread::Execute(void) { // To be able to display performance information, the generator counts the chunks generated. // When the queue gets empty, the count is reset, so that waiting for the queue is not counted into the total time. int NumChunksGenerated = 0; // Number of chunks generated since the queue was last empty clock_t GenerationStart = clock(); // Clock tick when the queue started to fill clock_t LastReportTick = clock(); // Clock tick of the last report made (so that performance isn't reported too often) while (!m_ShouldTerminate) { cCSLock Lock(m_CS); while (m_Queue.empty()) { if ((NumChunksGenerated > 16) && (clock() - LastReportTick > CLOCKS_PER_SEC)) { /* LOG("Chunk generator performance: %.2f ch / sec (%d ch total)", static_cast(NumChunksGenerated) * CLOCKS_PER_SEC/ (clock() - GenerationStart), NumChunksGenerated ); */ } cCSUnlock Unlock(Lock); m_Event.Wait(); if (m_ShouldTerminate) { return; } NumChunksGenerated = 0; GenerationStart = clock(); LastReportTick = clock(); } if (m_Queue.empty()) { // Sometimes the queue remains empty // If so, we can't do any front() operations on it! continue; } auto item = m_Queue.front(); // Get next chunk from the queue bool SkipEnabled = (m_Queue.size() > QUEUE_SKIP_LIMIT); m_Queue.erase(m_Queue.begin()); // Remove the item from the queue Lock.Unlock(); // Unlock ASAP m_evtRemoved.Set(); // Display perf info once in a while: if ((NumChunksGenerated > 512) && (clock() - LastReportTick > 2 * CLOCKS_PER_SEC)) { LOG("Chunk generator performance: %.2f ch / sec (%d ch total)", static_cast(NumChunksGenerated) * CLOCKS_PER_SEC / (clock() - GenerationStart), NumChunksGenerated ); LastReportTick = clock(); } // Skip the chunk if it's already generated and regeneration is not forced. Report as success: if (!item.m_ForceRegeneration && m_ChunkSink->IsChunkValid(item.m_Coords)) { LOGD("Chunk %s already generated, skipping generation", item.m_Coords.ToString().c_str()); if (item.m_Callback != nullptr) { item.m_Callback->Call(item.m_Coords, true); } continue; } // Skip the chunk if the generator is overloaded: if (SkipEnabled && !m_ChunkSink->HasChunkAnyClients(item.m_Coords)) { LOGWARNING("Chunk generator overloaded, skipping chunk %s", item.m_Coords.ToString().c_str()); if (item.m_Callback != nullptr) { item.m_Callback->Call(item.m_Coords, false); } continue; } // Generate the chunk: DoGenerate(item.m_Coords); if (item.m_Callback != nullptr) { item.m_Callback->Call(item.m_Coords, true); } NumChunksGenerated++; } // while (!bStop) } void cChunkGeneratorThread::DoGenerate(cChunkCoords a_Coords) { ASSERT(m_PluginInterface != nullptr); ASSERT(m_ChunkSink != nullptr); cChunkDesc ChunkDesc(a_Coords); m_PluginInterface->CallHookChunkGenerating(ChunkDesc); m_Generator->Generate(ChunkDesc); m_PluginInterface->CallHookChunkGenerated(ChunkDesc); #ifndef NDEBUG // Verify that the generator has produced valid data: ChunkDesc.VerifyHeightmap(); #endif m_ChunkSink->OnChunkGenerated(ChunkDesc); } ================================================ FILE: src/ChunkGeneratorThread.h ================================================ #pragma once #include "OSSupport/IsThread.h" #include "ChunkDef.h" // fwd: class cIniFile; class cChunkDesc; class cChunkGenerator; /** Takes requests for generating chunks and processes them in a separate thread one by one. The requests are not added to the queue if there is already a request with the same coords. Before generating, the thread checks if the chunk hasn't been already generated. It is theoretically possible to have multiple generator threads by having multiple instances of this object, but then it MAY happen that the chunk is generated twice. If the generator queue is overloaded, the generator skips chunks with no clients in them. */ class cChunkGeneratorThread : public cIsThread { using Super = cIsThread; public: /** The interface through which the plugins are called for their OnChunkGenerating / OnChunkGenerated hooks. */ class cPluginInterface { public: // Force a virtual destructor virtual ~cPluginInterface() {} /** Called when the chunk is about to be generated. The generator may be partly or fully overriden by the implementation. */ virtual void CallHookChunkGenerating(cChunkDesc & a_ChunkDesc) = 0; /** Called after the chunk is generated, before it is handed to the chunk sink. a_ChunkDesc contains the generated chunk data. Implementation may modify this data. */ virtual void CallHookChunkGenerated(cChunkDesc & a_ChunkDesc) = 0; } ; /** The interface through which the generated chunks are handed to the cWorld or whoever created us. */ class cChunkSink { public: // Force a virtual destructor virtual ~cChunkSink() {} /** Called after the chunk has been generated The interface may store the chunk, send it over network, whatever. The chunk is not expected to be modified, but the generator will survive if the implementation changes the data within. All changes are ignored, though. */ virtual void OnChunkGenerated(cChunkDesc & a_ChunkDesc) = 0; /** Called just before the chunk generation is started, to verify that it hasn't been generated in the meantime. If this callback returns true, the chunk is not generated. */ virtual bool IsChunkValid(cChunkCoords a_Coords) = 0; /** Called when the generator is overloaded to skip chunks that are no longer needed. If this callback returns false, the chunk is not generated. */ virtual bool HasChunkAnyClients(cChunkCoords a_Coords) = 0; /** Called to check whether the specified chunk is in the queued state. Currently used only in Debug-mode asserts. */ virtual bool IsChunkQueued(cChunkCoords a_Coords) = 0; } ; cChunkGeneratorThread (void); virtual ~cChunkGeneratorThread() override; /** Read settings from the ini file and initialize in preperation for being started. */ bool Initialize(cPluginInterface & a_PluginInterface, cChunkSink & a_ChunkSink, cIniFile & a_IniFile); void Stop(void); /** Queues the chunk for generation If a-ForceGenerate is set, the chunk is regenerated even if the data is already present in the chunksink. a_Callback is called after the chunk is generated. If the chunk was already present, the callback is still called, even if not regenerating. It is legal to set the callback to nullptr, no callback is called then. If the generator becomes overloaded and skips this chunk, the callback is still called. */ void QueueGenerateChunk(cChunkCoords a_Coords, bool a_ForceRegeneration, cChunkCoordCallback * a_Callback = nullptr); /** Generates the biomes for the specified chunk (directly, not in a separate thread). Used by the world loader if biomes failed loading. */ void GenerateBiomes(cChunkCoords a_Coords, cChunkDef::BiomeMap & a_BiomeMap); void WaitForQueueEmpty(); size_t GetQueueLength() const; int GetSeed() const; /** Returns the biome at the specified coords. Used by ChunkMap if an invalid chunk is queried for biome */ EMCSBiome GetBiomeAt(int a_BlockX, int a_BlockZ); private: struct QueueItem { /** The chunk coords */ cChunkCoords m_Coords; /** Force the regeneration of an already existing chunk */ bool m_ForceRegeneration; /** Callback to call after generating. */ cChunkCoordCallback * m_Callback; QueueItem(cChunkCoords a_Coords, bool a_ForceRegeneration, cChunkCoordCallback * a_Callback): m_Coords(a_Coords), m_ForceRegeneration(a_ForceRegeneration), m_Callback(a_Callback) { } }; using Queue = std::list; /** CS protecting access to the queue. */ mutable cCriticalSection m_CS; /** Queue of the chunks to be generated. Protected against multithreaded access by m_CS. */ Queue m_Queue; /** Set when an item is added to the queue or the thread should terminate. */ cEvent m_Event; /** Set when an item is removed from the queue. */ cEvent m_evtRemoved; /** The actual chunk generator engine used. */ std::unique_ptr m_Generator; /** The plugin interface that may modify the generated chunks */ cPluginInterface * m_PluginInterface; /** The destination where the generated chunks are sent */ cChunkSink * m_ChunkSink; // cIsThread override: virtual void Execute(void) override; /** Generates the specified chunk and sets it into the chunksink. */ void DoGenerate(cChunkCoords a_Coords); }; ================================================ FILE: src/ChunkMap.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "ChunkMap.h" #include "BlockInfo.h" #include "World.h" #include "Root.h" #include "Entities/Player.h" #include "Item.h" #include "Chunk.h" #include "Generating/Trees.h" // used in cChunkMap::ReplaceTreeBlocks() for tree block discrimination #include "BlockArea.h" #include "Bindings/PluginManager.h" #include "Blocks/BlockHandler.h" #include "MobCensus.h" #include "MobSpawner.h" #include "BoundingBox.h" #include "SetChunkData.h" #include "Blocks/ChunkInterface.h" #include "Entities/Pickup.h" #include "DeadlockDetect.h" //////////////////////////////////////////////////////////////////////////////// // cChunkMap: cChunkMap::cChunkMap(cWorld * a_World) : m_World(a_World) { } cChunk & cChunkMap::ConstructChunk(int a_ChunkX, int a_ChunkZ) { // If not exists insert. Then, return the chunk at these coordinates: return m_Chunks.try_emplace( { a_ChunkX, a_ChunkZ }, a_ChunkX, a_ChunkZ, this, m_World ).first->second; } cChunk & cChunkMap::GetChunk(int a_ChunkX, int a_ChunkZ) { ASSERT(m_CSChunks.IsLockedByCurrentThread()); // m_CSChunks should already be locked by the operation that called us auto & Chunk = ConstructChunk(a_ChunkX, a_ChunkZ); if (!Chunk.IsValid() && !Chunk.IsQueued()) { Chunk.SetPresence(cChunk::cpQueued); m_World->GetStorage().QueueLoadChunk(a_ChunkX, a_ChunkZ); } return Chunk; } cChunk * cChunkMap::FindChunk(int a_ChunkX, int a_ChunkZ) { ASSERT(m_CSChunks.IsLockedByCurrentThread()); const auto Chunk = m_Chunks.find({ a_ChunkX, a_ChunkZ }); return (Chunk == m_Chunks.end()) ? nullptr : &Chunk->second; } const cChunk * cChunkMap::FindChunk(int a_ChunkX, int a_ChunkZ) const { ASSERT(m_CSChunks.IsLockedByCurrentThread()); const auto Chunk = m_Chunks.find({ a_ChunkX, a_ChunkZ }); return (Chunk == m_Chunks.end()) ? nullptr : &Chunk->second; } void cChunkMap::SendBlockEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cClientHandle & a_Client) { cCSLock Lock(m_CSChunks); int ChunkX, ChunkZ; cChunkDef::BlockToChunk(a_BlockX, a_BlockZ, ChunkX, ChunkZ); const auto Chunk = FindChunk(ChunkX, ChunkZ); if ((Chunk == nullptr) || !Chunk->IsValid()) { return; } Chunk->SendBlockEntity(a_BlockX, a_BlockY, a_BlockZ, a_Client); } bool cChunkMap::UseBlockEntity(cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ) { // a_Player rclked block entity at the coords specified, handle it cCSLock Lock(m_CSChunks); int ChunkX, ChunkZ; cChunkDef::BlockToChunk(a_BlockX, a_BlockZ, ChunkX, ChunkZ); const auto Chunk = FindChunk(ChunkX, ChunkZ); if ((Chunk == nullptr) || !Chunk->IsValid()) { return false; } return Chunk->UseBlockEntity(a_Player, a_BlockX, a_BlockY, a_BlockZ); } bool cChunkMap::DoWithChunk(int a_ChunkX, int a_ChunkZ, cChunkCallback a_Callback) { cCSLock Lock(m_CSChunks); const auto Chunk = FindChunk(a_ChunkX, a_ChunkZ); if ((Chunk == nullptr) || !Chunk->IsValid()) { return false; } return a_Callback(*Chunk); } bool cChunkMap::DoWithChunkAt(Vector3i a_BlockPos, cChunkCallback a_Callback) { const auto Position = cChunkDef::BlockToChunk(a_BlockPos); return DoWithChunk(Position.m_ChunkX, Position.m_ChunkZ, a_Callback); } void cChunkMap::WakeUpSimulators(Vector3i a_Block) { cCSLock Lock(m_CSChunks); const auto Position = cChunkDef::BlockToChunk(a_Block); const auto Chunk = FindChunk(Position.m_ChunkX, Position.m_ChunkZ); if ((Chunk == nullptr) || !Chunk->IsValid()) { return; } m_World->GetSimulatorManager()->WakeUp(*Chunk, cChunkDef::AbsoluteToRelative(a_Block, Position)); } void cChunkMap::MarkChunkDirty(int a_ChunkX, int a_ChunkZ) { cCSLock Lock(m_CSChunks); const auto Chunk = FindChunk(a_ChunkX, a_ChunkZ); if ((Chunk == nullptr) || !Chunk->IsValid()) { return; } Chunk->MarkDirty(); } void cChunkMap::MarkChunkSaving(int a_ChunkX, int a_ChunkZ) { cCSLock Lock(m_CSChunks); const auto Chunk = FindChunk(a_ChunkX, a_ChunkZ); if ((Chunk == nullptr) || !Chunk->IsValid()) { return; } Chunk->MarkSaving(); } void cChunkMap::MarkChunkSaved (int a_ChunkX, int a_ChunkZ) { cCSLock Lock(m_CSChunks); const auto Chunk = FindChunk(a_ChunkX, a_ChunkZ); if ((Chunk == nullptr) || !Chunk->IsValid()) { return; } Chunk->MarkSaved(); } void cChunkMap::SetChunkData(struct SetChunkData && a_SetChunkData) { const int ChunkX = a_SetChunkData.Chunk.m_ChunkX; const int ChunkZ = a_SetChunkData.Chunk.m_ChunkZ; { cCSLock Lock(m_CSChunks); const auto Chunk = FindChunk(ChunkX, ChunkZ); ASSERT(Chunk != nullptr); // Chunk cannot have unloaded since it is marked as queued Chunk->SetAllData(std::move(a_SetChunkData)); // Notify relevant ChunkStays: cChunkStays ToBeDisabled; for (cChunkStays::iterator itr = m_ChunkStays.begin(), end = m_ChunkStays.end(); itr != end; ++itr) { if ((*itr)->ChunkAvailable(ChunkX, ChunkZ)) { // The chunkstay wants to be disabled, add it to a list of to-be-disabled chunkstays for later processing: ToBeDisabled.push_back(*itr); } } // for itr - m_ChunkStays[] // Disable (and possibly remove) the chunkstays that chose to get disabled: for (cChunkStays::iterator itr = ToBeDisabled.begin(), end = ToBeDisabled.end(); itr != end; ++itr) { (*itr)->Disable(); } } // Notify plugins of the chunk becoming available cPluginManager::Get()->CallHookChunkAvailable(*m_World, ChunkX, ChunkZ); } void cChunkMap::ChunkLighted( int a_ChunkX, int a_ChunkZ, const cChunkDef::BlockNibbles & a_BlockLight, const cChunkDef::BlockNibbles & a_SkyLight ) { cCSLock Lock(m_CSChunks); const auto Chunk = FindChunk(a_ChunkX, a_ChunkZ); if (Chunk == nullptr) { // Chunk probably unloaded in the meantime return; } Chunk->SetLight(a_BlockLight, a_SkyLight); } bool cChunkMap::GetChunkData(cChunkCoords a_Coords, cChunkDataCallback & a_Callback) const { if (!a_Callback.Coords(a_Coords.m_ChunkX, a_Coords.m_ChunkZ)) { // The callback doesn't want the data return false; } cCSLock Lock(m_CSChunks); const auto Chunk = FindChunk(a_Coords.m_ChunkX, a_Coords.m_ChunkZ); if ((Chunk == nullptr) || !Chunk->IsValid()) { // The chunk is not present return false; } Chunk->GetAllData(a_Callback); return true; } bool cChunkMap::IsChunkQueued(int a_ChunkX, int a_ChunkZ) const { cCSLock Lock(m_CSChunks); const auto Chunk = FindChunk(a_ChunkX, a_ChunkZ); return (Chunk != nullptr) && Chunk->IsQueued(); } bool cChunkMap::IsWeatherSunnyAt(int a_BlockX, int a_BlockZ) const { int ChunkX, ChunkZ, BlockY = 0; cChunkDef::AbsoluteToRelative(a_BlockX, BlockY, a_BlockZ, ChunkX, ChunkZ); cCSLock Lock(m_CSChunks); const auto Chunk = FindChunk(ChunkX, ChunkZ); if ((Chunk == nullptr) || !Chunk->IsValid()) { return m_World->IsWeatherSunny(); } return Chunk->IsWeatherSunnyAt(a_BlockX, a_BlockZ); } bool cChunkMap::IsWeatherWetAt(int a_BlockX, int a_BlockZ) const { int ChunkX, ChunkZ, BlockY = 0; cChunkDef::AbsoluteToRelative(a_BlockX, BlockY, a_BlockZ, ChunkX, ChunkZ); cCSLock Lock(m_CSChunks); const auto Chunk = FindChunk(ChunkX, ChunkZ); if ((Chunk == nullptr) || !Chunk->IsValid()) { return m_World->IsWeatherWet(); } return Chunk->IsWeatherWetAt(a_BlockX, a_BlockZ); } bool cChunkMap::IsWeatherWetAt(const Vector3i a_Position) const { const auto ChunkPosition = cChunkDef::BlockToChunk(a_Position); const auto Position = cChunkDef::AbsoluteToRelative(a_Position, ChunkPosition); cCSLock Lock(m_CSChunks); const auto Chunk = FindChunk(ChunkPosition.m_ChunkX, ChunkPosition.m_ChunkZ); if ((Chunk == nullptr) || !Chunk->IsValid()) { return m_World->IsWeatherWet(); } return Chunk->IsWeatherWetAt(Position); } bool cChunkMap::IsChunkValid(int a_ChunkX, int a_ChunkZ) const { cCSLock Lock(m_CSChunks); const auto Chunk = FindChunk(a_ChunkX, a_ChunkZ); return (Chunk != nullptr) && Chunk->IsValid(); } bool cChunkMap::HasChunkAnyClients(int a_ChunkX, int a_ChunkZ) const { cCSLock Lock(m_CSChunks); const auto Chunk = FindChunk(a_ChunkX, a_ChunkZ); return (Chunk != nullptr) && Chunk->HasAnyClients(); } std::optional cChunkMap::GetHeight(int a_BlockX, int a_BlockZ) { // Returns std::nullopt if chunk not loaded / generated. cCSLock Lock(m_CSChunks); int ChunkX, ChunkZ, BlockY = 0; cChunkDef::AbsoluteToRelative(a_BlockX, BlockY, a_BlockZ, ChunkX, ChunkZ); const auto Chunk = FindChunk(ChunkX, ChunkZ); if ((Chunk == nullptr) || !Chunk->IsValid()) { return std::nullopt; } return Chunk->GetHeight(a_BlockX, a_BlockZ); } void cChunkMap::FastSetBlock(Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) { auto chunkPos = cChunkDef::BlockToChunk(a_BlockPos); auto relPos = cChunkDef::AbsoluteToRelative(a_BlockPos, chunkPos); cCSLock Lock(m_CSChunks); const auto Chunk = FindChunk(chunkPos.m_ChunkX, chunkPos.m_ChunkZ); if ((Chunk != nullptr) && Chunk->IsValid()) { Chunk->FastSetBlock(relPos, a_BlockType, a_BlockMeta); } } void cChunkMap::CollectPickupsByEntity(cEntity & a_Entity) { cCSLock Lock(m_CSChunks); auto BoundingBox = a_Entity.GetBoundingBox(); BoundingBox.Expand(1, 0.5, 1); ForEachEntityInBox(BoundingBox, [&a_Entity](cEntity & Entity) { // Only pickups and projectiles can be picked up: if (Entity.IsPickup()) { /* LOG("Pickup %d being collected by player \"%s\", distance %f", (*itr)->GetUniqueID(), a_Player->GetName().c_str(), SqrDist ); */ static_cast(Entity).CollectedBy(a_Entity); } else if (Entity.IsProjectile() && a_Entity.IsPlayer()) { static_cast(Entity).CollectedBy(static_cast(a_Entity)); } // The entities will MarkDirty when they Destroy themselves return false; }); } BLOCKTYPE cChunkMap::GetBlock(Vector3i a_BlockPos) const { if (!cChunkDef::IsValidHeight(a_BlockPos)) { return 0; } auto chunkPos = cChunkDef::BlockToChunk(a_BlockPos); auto relPos = cChunkDef::AbsoluteToRelative(a_BlockPos, chunkPos); // Query the chunk, if loaded: cCSLock Lock(m_CSChunks); const auto Chunk = FindChunk(chunkPos.m_ChunkX, chunkPos.m_ChunkZ); if ((Chunk != nullptr) && Chunk->IsValid()) { return Chunk->GetBlock(relPos); } return 0; } NIBBLETYPE cChunkMap::GetBlockMeta(Vector3i a_BlockPos) const { if (!cChunkDef::IsValidHeight(a_BlockPos)) { return 0; } auto chunkPos = cChunkDef::BlockToChunk(a_BlockPos); auto relPos = cChunkDef::AbsoluteToRelative(a_BlockPos, chunkPos); // Query the chunk, if loaded: cCSLock Lock(m_CSChunks); const auto Chunk = FindChunk(chunkPos.m_ChunkX, chunkPos.m_ChunkZ); if ((Chunk != nullptr) && Chunk->IsValid()) { return Chunk->GetMeta(relPos); } return 0; } NIBBLETYPE cChunkMap::GetBlockSkyLight(Vector3i a_BlockPos) const { auto chunkPos = cChunkDef::BlockToChunk(a_BlockPos); auto relPos = cChunkDef::AbsoluteToRelative(a_BlockPos, chunkPos); // Query the chunk, if loaded: cCSLock Lock(m_CSChunks); const auto Chunk = FindChunk(chunkPos.m_ChunkX, chunkPos.m_ChunkZ); if ((Chunk != nullptr) && Chunk->IsValid()) { return Chunk->GetSkyLight(relPos); } return 0; } NIBBLETYPE cChunkMap::GetBlockBlockLight(Vector3i a_BlockPos) const { auto chunkPos = cChunkDef::BlockToChunk(a_BlockPos); auto relPos = cChunkDef::AbsoluteToRelative(a_BlockPos, chunkPos); // Query the chunk, if loaded: cCSLock Lock(m_CSChunks); const auto Chunk = FindChunk(chunkPos.m_ChunkX, chunkPos.m_ChunkZ); if ((Chunk != nullptr) && Chunk->IsValid()) { return Chunk->GetBlockLight(relPos); } return 0; } void cChunkMap::SetBlockMeta(Vector3i a_BlockPos, NIBBLETYPE a_BlockMeta) { auto chunkPos = cChunkDef::BlockToChunk(a_BlockPos); auto relPos = cChunkDef::AbsoluteToRelative(a_BlockPos, chunkPos); // Query the chunk, if loaded: cCSLock Lock(m_CSChunks); const auto Chunk = FindChunk(chunkPos.m_ChunkX, chunkPos.m_ChunkZ); if ((Chunk != nullptr) && Chunk->IsValid()) { Chunk->SetMeta(relPos, a_BlockMeta); } } void cChunkMap::SetBlock(Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) { auto chunkPos = cChunkDef::BlockToChunk(a_BlockPos); auto relPos = cChunkDef::AbsoluteToRelative(a_BlockPos, chunkPos); cCSLock Lock(m_CSChunks); const auto Chunk = FindChunk(chunkPos.m_ChunkX, chunkPos.m_ChunkZ); if ((Chunk != nullptr) && Chunk->IsValid()) { Chunk->SetBlock(relPos, a_BlockType, a_BlockMeta); } } bool cChunkMap::GetBlockTypeMeta(Vector3i a_BlockPos, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta) const { if (!cChunkDef::IsValidHeight(a_BlockPos)) { // Initialise the params to fulfil our contract. a_BlockType = 0; a_BlockMeta = 0; return false; } auto chunkCoord = cChunkDef::BlockToChunk(a_BlockPos); auto relPos = cChunkDef::AbsoluteToRelative(a_BlockPos, chunkCoord); cCSLock Lock(m_CSChunks); const auto Chunk = FindChunk(chunkCoord.m_ChunkX, chunkCoord.m_ChunkZ); if ((Chunk != nullptr) && Chunk->IsValid()) { Chunk->GetBlockTypeMeta(relPos, a_BlockType, a_BlockMeta); return true; } // Initialise the params to fulfil our contract. a_BlockType = 0; a_BlockMeta = 0; return false; } bool cChunkMap::GetBlockInfo(Vector3i a_BlockPos, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_Meta, NIBBLETYPE & a_SkyLight, NIBBLETYPE & a_BlockLight) const { auto chunkPos = cChunkDef::BlockToChunk(a_BlockPos); auto relPos = cChunkDef::AbsoluteToRelative(a_BlockPos, chunkPos); // Query the chunk, if loaded: cCSLock Lock(m_CSChunks); const auto Chunk = FindChunk(chunkPos.m_ChunkX, chunkPos.m_ChunkZ); if ((Chunk != nullptr) && Chunk->IsValid()) { Chunk->GetBlockInfo(relPos, a_BlockType, a_Meta, a_SkyLight, a_BlockLight); return true; } return false; } void cChunkMap::ReplaceTreeBlocks(const sSetBlockVector & a_Blocks) { cCSLock Lock(m_CSChunks); for (sSetBlockVector::const_iterator itr = a_Blocks.begin(); itr != a_Blocks.end(); ++itr) { const auto Chunk = FindChunk(itr->m_ChunkX, itr->m_ChunkZ); if ((Chunk == nullptr) || !Chunk->IsValid()) { continue; } Vector3i relPos(itr->m_RelX, itr->m_RelY, itr->m_RelZ); switch (Chunk->GetBlock(relPos)) { CASE_TREE_OVERWRITTEN_BLOCKS: { Chunk->SetBlock(relPos, itr->m_BlockType, itr->m_BlockMeta); break; } case E_BLOCK_LEAVES: case E_BLOCK_NEW_LEAVES: { if ((itr->m_BlockType == E_BLOCK_LOG) || (itr->m_BlockType == E_BLOCK_NEW_LOG)) { Chunk->SetBlock(relPos, itr->m_BlockType, itr->m_BlockMeta); } break; } } } // for itr - a_Blocks[] } EMCSBiome cChunkMap::GetBiomeAt(int a_BlockX, int a_BlockZ) const { int ChunkX, ChunkZ, X = a_BlockX, Y = 0, Z = a_BlockZ; cChunkDef::AbsoluteToRelative(X, Y, Z, ChunkX, ChunkZ); cCSLock Lock(m_CSChunks); const auto Chunk = FindChunk(ChunkX, ChunkZ); if ((Chunk != nullptr) && Chunk->IsValid()) { return Chunk->GetBiomeAt(X, Z); } return EMCSBiome::biInvalidBiome; } bool cChunkMap::SetBiomeAt(int a_BlockX, int a_BlockZ, EMCSBiome a_Biome) { int ChunkX, ChunkZ, X = a_BlockX, Y = 0, Z = a_BlockZ; cChunkDef::AbsoluteToRelative(X, Y, Z, ChunkX, ChunkZ); cCSLock Lock(m_CSChunks); const auto Chunk = FindChunk(ChunkX, ChunkZ); if ((Chunk != nullptr) && Chunk->IsValid()) { Chunk->SetBiomeAt(X, Z, a_Biome); return true; } return false; } bool cChunkMap::SetAreaBiome(int a_MinX, int a_MaxX, int a_MinZ, int a_MaxZ, EMCSBiome a_Biome) { // Translate coords to relative: int Y = 0; int MinChunkX, MinChunkZ, MinX = a_MinX, MinZ = a_MinZ; int MaxChunkX, MaxChunkZ, MaxX = a_MaxX, MaxZ = a_MaxZ; cChunkDef::AbsoluteToRelative(MinX, Y, MinZ, MinChunkX, MinChunkZ); cChunkDef::AbsoluteToRelative(MaxX, Y, MaxZ, MaxChunkX, MaxChunkZ); // Go through all chunks, set: bool res = true; cCSLock Lock(m_CSChunks); for (int x = MinChunkX; x <= MaxChunkX; x++) { int MinRelX = (x == MinChunkX) ? MinX : 0; int MaxRelX = (x == MaxChunkX) ? MaxX : cChunkDef::Width - 1; for (int z = MinChunkZ; z <= MaxChunkZ; z++) { int MinRelZ = (z == MinChunkZ) ? MinZ : 0; int MaxRelZ = (z == MaxChunkZ) ? MaxZ : cChunkDef::Width - 1; const auto Chunk = FindChunk(x, z); if ((Chunk != nullptr) && Chunk->IsValid()) { Chunk->SetAreaBiome(MinRelX, MaxRelX, MinRelZ, MaxRelZ, a_Biome); } else { res = false; } } // for z } // for x return res; } bool cChunkMap::GetBlocks(sSetBlockVector & a_Blocks, bool a_ContinueOnFailure) { bool res = true; cCSLock Lock(m_CSChunks); for (sSetBlockVector::iterator itr = a_Blocks.begin(); itr != a_Blocks.end(); ++itr) { const auto Chunk = FindChunk(itr->m_ChunkX, itr->m_ChunkZ); if ((Chunk == nullptr) || !Chunk->IsValid()) { if (!a_ContinueOnFailure) { return false; } res = false; continue; } if (!cChunkDef::IsValidHeight(itr->GetRelativePos())) { continue; } itr->m_BlockType = Chunk->GetBlock(itr->m_RelX, itr->m_RelY, itr->m_RelZ); itr->m_BlockMeta = Chunk->GetMeta(itr->m_RelX, itr->m_RelY, itr->m_RelZ); } return res; } bool cChunkMap::DigBlock(Vector3i a_BlockPos) { auto chunkCoords = cChunkDef::BlockToChunk(a_BlockPos); auto relPos = cChunkDef::AbsoluteToRelative(a_BlockPos, chunkCoords); { cCSLock Lock(m_CSChunks); const auto Chunk = FindChunk(chunkCoords.m_ChunkX, chunkCoords.m_ChunkZ); if ((Chunk == nullptr) || !Chunk->IsValid()) { return false; } Chunk->SetBlock(relPos, E_BLOCK_AIR, 0); } return true; } cItems cChunkMap::PickupsFromBlock(Vector3i a_BlockPos, const cEntity * a_Digger, const cItem * a_Tool) { auto chunkCoords = cChunkDef::BlockToChunk(a_BlockPos); auto relPos = cChunkDef::AbsoluteToRelative(a_BlockPos, chunkCoords); cCSLock Lock(m_CSChunks); const auto Chunk = FindChunk(chunkCoords.m_ChunkX, chunkCoords.m_ChunkZ); if ((Chunk == nullptr) || !Chunk->IsValid()) { return {}; } return Chunk->PickupsFromBlock(relPos, a_Digger, a_Tool); } void cChunkMap::SendBlockTo(int a_X, int a_Y, int a_Z, const cPlayer & a_Player) { int ChunkX, ChunkZ; cChunkDef::AbsoluteToRelative(a_X, a_Y, a_Z, ChunkX, ChunkZ); cCSLock Lock(m_CSChunks); const auto Chunk = FindChunk(ChunkX, ChunkZ); if ((Chunk != nullptr) && (Chunk->IsValid())) { Chunk->SendBlockTo(a_X, a_Y, a_Z, a_Player.GetClientHandle()); } } void cChunkMap::CompareChunkClients(int a_ChunkX1, int a_ChunkZ1, int a_ChunkX2, int a_ChunkZ2, cClientDiffCallback & a_Callback) { cCSLock Lock(m_CSChunks); const auto Chunk1 = FindChunk(a_ChunkX1, a_ChunkZ1); if (Chunk1 == nullptr) { return; } const auto Chunk2 = FindChunk(a_ChunkX2, a_ChunkZ2); if (Chunk2 == nullptr) { return; } CompareChunkClients(Chunk1, Chunk2, a_Callback); } void cChunkMap::CompareChunkClients(cChunk * a_Chunk1, cChunk * a_Chunk2, cClientDiffCallback & a_Callback) { const auto & Clients1 = a_Chunk1->GetAllClients(); const auto & Clients2 = a_Chunk2->GetAllClients(); // Find "removed" clients: for (auto * Client : Clients1) { bool Found = (std::find(Clients2.begin(), Clients2.end(), Client) != Clients2.end()); if (!Found) { a_Callback.Removed(Client); } } // for Client - Clients1[] // Find "added" clients: for (auto * Client : Clients2) { bool Found = (std::find(Clients1.begin(), Clients1.end(), Client) != Clients1.end()); if (!Found) { a_Callback.Added(Client); } } // for Client - Clients2[] } bool cChunkMap::AddChunkClient(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Client) { cCSLock Lock(m_CSChunks); return GetChunk(a_ChunkX, a_ChunkZ).AddClient(a_Client); } void cChunkMap::RemoveChunkClient(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Client) { cCSLock Lock(m_CSChunks); const auto Chunk = FindChunk(a_ChunkX, a_ChunkZ); ASSERT(Chunk != nullptr); Chunk->RemoveClient(a_Client); } void cChunkMap::RemoveClientFromChunks(cClientHandle * a_Client) { cCSLock Lock(m_CSChunks); for (auto & Chunk : m_Chunks) { Chunk.second.RemoveClient(a_Client); } } void cChunkMap::AddEntity(OwnedEntity a_Entity) { cCSLock Lock(m_CSChunks); if (FindChunk(a_Entity->GetChunkX(), a_Entity->GetChunkZ()) == nullptr) { LOGWARNING("%s: Entity at %p (%s, ID %d) spawning in a non-existent chunk.", __FUNCTION__, static_cast(a_Entity.get()), a_Entity->GetClass(), a_Entity->GetUniqueID() ); } const auto EntityPtr = a_Entity.get(); ASSERT(EntityPtr->GetWorld() == m_World); auto & Chunk = ConstructChunk(a_Entity->GetChunkX(), a_Entity->GetChunkZ()); Chunk.AddEntity(std::move(a_Entity)); EntityPtr->OnAddToWorld(*m_World); ASSERT(!EntityPtr->IsTicking()); EntityPtr->SetIsTicking(true); cPluginManager::Get()->CallHookSpawnedEntity(*m_World, *EntityPtr); } void cChunkMap::AddPlayer(std::unique_ptr a_Player) { cCSLock Lock(m_CSChunks); auto & Chunk = ConstructChunk(a_Player->GetChunkX(), a_Player->GetChunkZ()); // Always construct the chunk for players ASSERT(!Chunk.HasEntity(a_Player->GetUniqueID())); Chunk.AddEntity(std::move(a_Player)); } bool cChunkMap::HasEntity(UInt32 a_UniqueID) const { cCSLock Lock(m_CSChunks); for (const auto & Chunk : m_Chunks) { if (Chunk.second.IsValid() && Chunk.second.HasEntity(a_UniqueID)) { return true; } } return false; } OwnedEntity cChunkMap::RemoveEntity(cEntity & a_Entity) { cCSLock Lock(m_CSChunks); const auto Chunk = a_Entity.GetParentChunk(); if (Chunk == nullptr) { return nullptr; } // Remove the entity no matter whether the chunk itself is valid or not (#1190) return Chunk->RemoveEntity(a_Entity); } bool cChunkMap::ForEachEntity(cEntityCallback a_Callback) const { cCSLock Lock(m_CSChunks); for (const auto & Chunk : m_Chunks) { if (Chunk.second.IsValid() && !Chunk.second.ForEachEntity(a_Callback)) { return false; } } return true; } bool cChunkMap::ForEachEntityInChunk(int a_ChunkX, int a_ChunkZ, cEntityCallback a_Callback) { cCSLock Lock(m_CSChunks); const auto Chunk = FindChunk(a_ChunkX, a_ChunkZ); if ((Chunk == nullptr) || !Chunk->IsValid()) { return false; } return Chunk->ForEachEntity(a_Callback); } bool cChunkMap::ForEachEntityInBox(const cBoundingBox & a_Box, cEntityCallback a_Callback) { // Calculate the chunk range for the box: int MinChunkX = FloorC(a_Box.GetMinX() / cChunkDef::Width); int MinChunkZ = FloorC(a_Box.GetMinZ() / cChunkDef::Width); int MaxChunkX = FloorC((a_Box.GetMaxX() + cChunkDef::Width) / cChunkDef::Width); int MaxChunkZ = FloorC((a_Box.GetMaxZ() + cChunkDef::Width) / cChunkDef::Width); // Iterate over each chunk in the range: cCSLock Lock(m_CSChunks); for (int z = MinChunkZ; z <= MaxChunkZ; z++) { for (int x = MinChunkX; x <= MaxChunkX; x++) { const auto Chunk = FindChunk(x, z); if ((Chunk == nullptr) || !Chunk->IsValid()) { continue; } if (!Chunk->ForEachEntityInBox(a_Box, a_Callback)) { return false; } } // for x } // for z return true; } bool cChunkMap::DoWithEntityByID(UInt32 a_UniqueID, cEntityCallback a_Callback) const { cCSLock Lock(m_CSChunks); bool res = false; for (const auto & Chunk : m_Chunks) { if (Chunk.second.IsValid() && Chunk.second.DoWithEntityByID(a_UniqueID, a_Callback, res)) { return res; } } return false; } bool cChunkMap::ForEachBlockEntityInChunk(int a_ChunkX, int a_ChunkZ, cBlockEntityCallback a_Callback) { cCSLock Lock(m_CSChunks); const auto Chunk = FindChunk(a_ChunkX, a_ChunkZ); if ((Chunk == nullptr) || !Chunk->IsValid()) { return false; } return Chunk->ForEachBlockEntity(a_Callback); } bool cChunkMap::DoWithBlockEntityAt(const Vector3i a_Position, cBlockEntityCallback a_Callback) { const auto ChunkPosition = cChunkDef::BlockToChunk(a_Position); const auto Relative = cChunkDef::AbsoluteToRelative(a_Position, ChunkPosition); cCSLock Lock(m_CSChunks); const auto Chunk = FindChunk(ChunkPosition.m_ChunkX, ChunkPosition.m_ChunkZ); if ((Chunk == nullptr) || !Chunk->IsValid()) { return false; } return Chunk->DoWithBlockEntityAt(Relative, a_Callback); } void cChunkMap::PrepareChunk(int a_ChunkX, int a_ChunkZ, std::unique_ptr a_Callback) { cCSLock Lock(m_CSChunks); const auto Chunk = FindChunk(a_ChunkX, a_ChunkZ); // If the chunk is not prepared, queue it in the lighting thread, that will do all the needed processing: if ((Chunk == nullptr) || !Chunk->IsValid() || !Chunk->IsLightValid()) { m_World->GetLightingThread().QueueChunk(a_ChunkX, a_ChunkZ, std::move(a_Callback)); return; } // The chunk is present and lit, just call the callback, report as success: if (a_Callback != nullptr) { a_Callback->Call({a_ChunkX, a_ChunkZ}, true); } } void cChunkMap::GenerateChunk(int a_ChunkX, int a_ChunkZ) { cCSLock Lock(m_CSChunks); GetChunk(a_ChunkX, a_ChunkZ); // Touches the chunk, loading or generating it } void cChunkMap::ChunkLoadFailed(int a_ChunkX, int a_ChunkZ) { cCSLock Lock(m_CSChunks); const auto Chunk = FindChunk(a_ChunkX, a_ChunkZ); ASSERT(Chunk != nullptr); // Chunk cannot have unloaded since it is marked as queued Chunk->MarkLoadFailed(); } void cChunkMap::MarkChunkRegenerating(int a_ChunkX, int a_ChunkZ) { cCSLock Lock(m_CSChunks); ConstructChunk(a_ChunkX, a_ChunkZ).MarkRegenerating(); } bool cChunkMap::IsChunkLighted(int a_ChunkX, int a_ChunkZ) { cCSLock Lock(m_CSChunks); const auto Chunk = FindChunk(a_ChunkX, a_ChunkZ); if (Chunk == nullptr) { // Not present return false; } return Chunk->IsLightValid(); } bool cChunkMap::ForEachChunkInRect(int a_MinChunkX, int a_MaxChunkX, int a_MinChunkZ, int a_MaxChunkZ, cChunkDataCallback & a_Callback) { bool Result = true; cCSLock Lock(m_CSChunks); for (int z = a_MinChunkZ; z <= a_MaxChunkZ; z++) { for (int x = a_MinChunkX; x <= a_MaxChunkX; x++) { const auto Chunk = FindChunk(x, z); if ((Chunk == nullptr) || !Chunk->IsValid()) { // Not present / not valid Result = false; continue; } if (!a_Callback.Coords(x, z)) { continue; } Chunk->GetAllData(a_Callback); } } return Result; } bool cChunkMap::ForEachLoadedChunk(cFunctionRef a_Callback) const { cCSLock Lock(m_CSChunks); for (const auto & Chunk : m_Chunks) { if (Chunk.second.IsValid()) { if (a_Callback(Chunk.first.m_ChunkX, Chunk.first.m_ChunkZ)) { return false; } } } return true; } bool cChunkMap::WriteBlockArea(cBlockArea & a_Area, int a_MinBlockX, int a_MinBlockY, int a_MinBlockZ, int a_DataTypes) { // Convert block coords to chunks coords: int MinChunkX, MaxChunkX; int MinChunkZ, MaxChunkZ; int MinBlockX = a_MinBlockX; int MinBlockY = a_MinBlockY; int MinBlockZ = a_MinBlockZ; int MaxBlockX = a_MinBlockX + a_Area.GetSizeX(); int MaxBlockY = a_MinBlockY + a_Area.GetSizeY(); int MaxBlockZ = a_MinBlockZ + a_Area.GetSizeZ(); cChunkDef::AbsoluteToRelative(MinBlockX, MinBlockY, MinBlockZ, MinChunkX, MinChunkZ); cChunkDef::AbsoluteToRelative(MaxBlockX, MaxBlockY, MaxBlockZ, MaxChunkX, MaxChunkZ); // Iterate over chunks, write data into each: bool Result = true; cCSLock Lock(m_CSChunks); for (int z = MinChunkZ; z <= MaxChunkZ; z++) { for (int x = MinChunkX; x <= MaxChunkX; x++) { const auto Chunk = FindChunk(x, z); if ((Chunk == nullptr) || !Chunk->IsValid()) { // Not present / not valid Result = false; continue; } Chunk->WriteBlockArea(a_Area, a_MinBlockX, a_MinBlockY, a_MinBlockZ, a_DataTypes); } // for x } // for z return Result; } void cChunkMap::GetChunkStats(int & a_NumChunksValid, int & a_NumChunksDirty) const { a_NumChunksValid = 0; a_NumChunksDirty = 0; cCSLock Lock(m_CSChunks); for (const auto & Chunk : m_Chunks) { a_NumChunksValid++; if (Chunk.second.IsDirty()) { a_NumChunksDirty++; } } } int cChunkMap::GrowPlantAt(Vector3i a_BlockPos, int a_NumStages) { auto chunkPos = cChunkDef::BlockToChunk(a_BlockPos); auto relPos = cChunkDef::AbsoluteToRelative(a_BlockPos, chunkPos); cCSLock lock(m_CSChunks); const auto Chunk = FindChunk(chunkPos.m_ChunkX, chunkPos.m_ChunkZ); if ((Chunk == nullptr) || !Chunk->IsValid()) { return 0; } return Chunk->GrowPlantAt(relPos, a_NumStages); } void cChunkMap::SetNextBlockToTick(const Vector3i a_BlockPos) { auto ChunkPos = cChunkDef::BlockToChunk(a_BlockPos); auto RelPos = cChunkDef::AbsoluteToRelative(a_BlockPos, ChunkPos); cCSLock Lock(m_CSChunks); const auto Chunk = FindChunk(ChunkPos.m_ChunkX, ChunkPos.m_ChunkZ); if (Chunk != nullptr) { Chunk->SetNextBlockToTick(RelPos); } } void cChunkMap::CollectMobCensus(cMobCensus & a_ToFill) { cCSLock Lock(m_CSChunks); for (auto & Chunk : m_Chunks) { // We do count every Mobs in the world. But we are assuming that every chunk not loaded by any client // doesn't affect us. Normally they should not have mobs because every "too far" mobs despawn // If they have (f.i. when player disconnect) we assume we don't have to make them live or despawn if (Chunk.second.IsValid() && Chunk.second.HasAnyClients()) { Chunk.second.CollectMobCensus(a_ToFill); } } } void cChunkMap::SpawnMobs(cMobSpawner & a_MobSpawner) { cCSLock Lock(m_CSChunks); for (auto & Chunk : m_Chunks) { // We only spawn close to players if (Chunk.second.IsValid() && Chunk.second.HasAnyClients()) { Chunk.second.SpawnMobs(a_MobSpawner); } } } void cChunkMap::Tick(std::chrono::milliseconds a_Dt) { cCSLock Lock(m_CSChunks); // Do the magic of updating the world: for (auto & Chunk : m_Chunks) { if (Chunk.second.ShouldBeTicked()) { Chunk.second.Tick(a_Dt); } } // Finally, only after all chunks are ticked, tell the client about all aggregated changes: for (auto & Chunk : m_Chunks) { Chunk.second.BroadcastPendingChanges(); } } void cChunkMap::TickBlock(const Vector3i a_BlockPos) { auto ChunkPos = cChunkDef::BlockToChunk(a_BlockPos); auto RelPos = cChunkDef::AbsoluteToRelative(a_BlockPos, ChunkPos); cCSLock Lock(m_CSChunks); const auto Chunk = FindChunk(ChunkPos.m_ChunkX, ChunkPos.m_ChunkZ); if ((Chunk == nullptr) || !Chunk->IsValid()) { return; } Chunk->TickBlock(RelPos); } void cChunkMap::UnloadUnusedChunks(void) { cCSLock Lock(m_CSChunks); for (auto itr = m_Chunks.begin(); itr != m_Chunks.end();) { if ( itr->second.CanUnload() && // Can unload !cPluginManager::Get()->CallHookChunkUnloading(*GetWorld(), itr->first.m_ChunkX, itr->first.m_ChunkZ) // Plugins agree ) { // First notify plugins: cPluginManager::Get()->CallHookChunkUnloaded(*m_World, itr->first.m_ChunkX, itr->first.m_ChunkZ); // Notify entities within the chunk, while everything's still valid: itr->second.OnUnload(); // Kill the chunk: itr = m_Chunks.erase(itr); } else { ++itr; } } } void cChunkMap::SaveAllChunks(void) const { cCSLock Lock(m_CSChunks); for (const auto & Chunk : m_Chunks) { if (Chunk.second.IsValid() && Chunk.second.IsDirty()) { GetWorld()->GetStorage().QueueSaveChunk(Chunk.first.m_ChunkX, Chunk.first.m_ChunkZ); } } } size_t cChunkMap::GetNumChunks(void) const { cCSLock Lock(m_CSChunks); return m_Chunks.size(); } size_t cChunkMap::GetNumUnusedDirtyChunks(void) const { cCSLock Lock(m_CSChunks); size_t res = 0; for (const auto & Chunk : m_Chunks) { if (Chunk.second.IsValid() && Chunk.second.CanUnloadAfterSaving()) { res += 1; } } return res; } void cChunkMap::ChunkValidated(void) { m_evtChunkValid.Set(); } void cChunkMap::SetChunkAlwaysTicked(int a_ChunkX, int a_ChunkZ, bool a_AlwaysTicked) { cCSLock Lock(m_CSChunks); GetChunk(a_ChunkX, a_ChunkZ).SetAlwaysTicked(a_AlwaysTicked); } void cChunkMap::TrackInDeadlockDetect(cDeadlockDetect & a_DeadlockDetect, const AString & a_WorldName) { a_DeadlockDetect.TrackCriticalSection(m_CSChunks, fmt::format(FMT_STRING("World {} chunkmap"), a_WorldName)); } void cChunkMap::UntrackInDeadlockDetect(cDeadlockDetect & a_DeadlockDetect) { a_DeadlockDetect.UntrackCriticalSection(m_CSChunks); } void cChunkMap::AddChunkStay(cChunkStay & a_ChunkStay) { cCSLock Lock(m_CSChunks); // Add it to the list: ASSERT(std::find(m_ChunkStays.begin(), m_ChunkStays.end(), &a_ChunkStay) == m_ChunkStays.end()); // Has not yet been added m_ChunkStays.push_back(&a_ChunkStay); // Schedule all chunks to be loaded / generated, and mark each as locked: const cChunkCoordsVector & WantedChunks = a_ChunkStay.GetChunks(); for (cChunkCoordsVector::const_iterator itr = WantedChunks.begin(); itr != WantedChunks.end(); ++itr) { auto & Chunk = GetChunk(itr->m_ChunkX, itr->m_ChunkZ); Chunk.Stay(true); if (Chunk.IsValid()) { if (a_ChunkStay.ChunkAvailable(itr->m_ChunkX, itr->m_ChunkZ)) { // The chunkstay wants to be deactivated, disable it and bail out: a_ChunkStay.Disable(); return; } } } // for itr - WantedChunks[] } /** Removes the specified cChunkStay descendant from the internal list of ChunkStays. */ void cChunkMap::DelChunkStay(cChunkStay & a_ChunkStay) { cCSLock Lock(m_CSChunks); // Remove from the list of active chunkstays: bool HasFound = false; for (cChunkStays::iterator itr = m_ChunkStays.begin(), end = m_ChunkStays.end(); itr != end; ++itr) { if (*itr == &a_ChunkStay) { m_ChunkStays.erase(itr); HasFound = true; break; } } // for itr - m_ChunkStays[] if (!HasFound) { ASSERT(!"Removing a cChunkStay that hasn't been added!"); return; } // Unmark all contained chunks: const cChunkCoordsVector & Chunks = a_ChunkStay.GetChunks(); for (cChunkCoordsVector::const_iterator itr = Chunks.begin(), end = Chunks.end(); itr != end; ++itr) { const auto Chunk = FindChunk(itr->m_ChunkX, itr->m_ChunkZ); ASSERT(Chunk != nullptr); // Stayed chunks cannot unload Chunk->Stay(false); } // for itr - Chunks[] a_ChunkStay.OnDisabled(); } ================================================ FILE: src/ChunkMap.h ================================================ // cChunkMap.h // Interfaces to the cChunkMap class representing the chunk storage for a single world #pragma once #include #include "ChunkDataCallback.h" #include "EffectID.h" #include "FunctionRef.h" class cWorld; class cItem; class cItems; class cChunkStay; class cChunk; class cPlayer; class cBlockArea; class cMobCensus; class cMobSpawner; class cBoundingBox; class cDeadlockDetect; struct SetChunkData; using cChunkCallback = cFunctionRef; using cEntityCallback = cFunctionRef; using cBlockEntityCallback = cFunctionRef; class cChunkMap { public: cChunkMap(cWorld * a_World); /** Sends the block entity, if it is at the coords specified, to a_Client */ void SendBlockEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cClientHandle & a_Client); /** a_Player rclked block entity at the coords specified, handle it returns true if the use was successful, return false to use the block as a "normal" block */ bool UseBlockEntity(cPlayer * a_Player, int a_X, int a_Y, int a_Z); /** Calls the callback for the chunk specified, with ChunkMapCS locked; returns false if the chunk doesn't exist, otherwise returns the same value as the callback */ bool DoWithChunk(int a_ChunkX, int a_ChunkZ, cChunkCallback a_Callback); /** Calls the callback for the chunk at the block position specified, with ChunkMapCS locked; returns false if the chunk doesn't exist, otherwise returns the same value as the callback */ bool DoWithChunkAt(Vector3i a_BlockPos, cChunkCallback a_Callback); /** Wakes up simulators for the specified block */ void WakeUpSimulators(Vector3i a_Block); // DEPRECATED, use the vector-parametered version instead. void WakeUpSimulators(int a_BlockX, int a_BlockY, int a_BlockZ) { LOGWARNING("cChunkMap::WakeUpSimulators(int, int, int) is deprecated, use cChunkMap::WakeUpSimulators(Vector3i) instead."); WakeUpSimulators(Vector3i(a_BlockX, a_BlockY, a_BlockZ)); } void MarkChunkDirty (int a_ChunkX, int a_ChunkZ); void MarkChunkSaving (int a_ChunkX, int a_ChunkZ); void MarkChunkSaved (int a_ChunkX, int a_ChunkZ); /** Sets the chunk data as either loaded from the storage or generated. BlockLight and BlockSkyLight are optional, if not present, chunk will be marked as unlighted. If MarkDirty is set, the chunk is set as dirty (used after generating) Modifies the BlockEntity list in a_SetChunkData - moves the block entities into the chunk. */ void SetChunkData(SetChunkData && a_SetChunkData); void ChunkLighted( int a_ChunkX, int a_ChunkZ, const cChunkDef::BlockNibbles & a_BlockLight, const cChunkDef::BlockNibbles & a_SkyLight ); /** Calls the callback with the chunk's data, if available (with ChunkCS locked). Returns true if the chunk was reported successfully, false if not (chunk not present or callback failed). */ bool GetChunkData(cChunkCoords a_Coords, cChunkDataCallback & a_Callback) const; /** Returns true iff the chunk is in the loader / generator queue. */ bool IsChunkQueued(int a_ChunkX, int a_ChunkZ) const; bool IsWeatherSunnyAt(int a_BlockX, int a_BlockZ) const; bool IsWeatherWetAt(int a_BlockX, int a_BlockZ) const; bool IsWeatherWetAt(Vector3i a_Position) const; bool IsChunkValid (int a_ChunkX, int a_ChunkZ) const; bool HasChunkAnyClients (int a_ChunkX, int a_ChunkZ) const; std::optional GetHeight(int a_BlockX, int a_BlockZ); // Returns nullopt if chunk not loaded / generated /** Sets the block at the specified coords to the specified value. The replacement doesn't trigger block updates, nor wake up simulators. The replaced blocks aren't checked for block entities (block entity is leaked if it exists at this block). If the chunk is invalid, the operation is ignored silently. */ void FastSetBlock(Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta); /** Makes the specified entity collect all the pickups around them. */ void CollectPickupsByEntity(cEntity & a_Entity); BLOCKTYPE GetBlock (Vector3i a_BlockPos) const; NIBBLETYPE GetBlockMeta (Vector3i a_BlockPos) const; NIBBLETYPE GetBlockSkyLight (Vector3i a_BlockPos) const; NIBBLETYPE GetBlockBlockLight(Vector3i a_BlockPos) const; /** Sets the meta for the specified block, while keeping the blocktype. Ignored if the chunk is invalid. */ void SetBlockMeta(Vector3i a_BlockPos, NIBBLETYPE a_BlockMeta); void SetBlock (Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta); /** Get the block type and meta at the specified coords Will always initialise a_BlockType and a_BlockMeta if called. Returns false if the data could not be retrieved, either because the chunk is invalid or the height is invalid. Otherwise, returns true. */ bool GetBlockTypeMeta (Vector3i a_BlockPos, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta) const; bool GetBlockInfo (Vector3i, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_Meta, NIBBLETYPE & a_SkyLight, NIBBLETYPE & a_BlockLight) const; /** Special function used for growing trees, replaces only blocks that tree may overwrite */ void ReplaceTreeBlocks(const sSetBlockVector & a_Blocks); /** Returns the biome at the specified coords. Reads the biome from the chunk, if loaded, invalid otherwise. */ EMCSBiome GetBiomeAt(int a_BlockX, int a_BlockZ) const; /** Sets the biome at the specified coords. Returns true if successful, false if not (chunk not loaded). Doesn't resend the chunk to clients. */ bool SetBiomeAt(int a_BlockX, int a_BlockZ, EMCSBiome a_Biome); /** Sets the biome at the area. Returns true if successful, false if any subarea failed (chunk not loaded). (Re)sends the chunks to their relevant clients if successful. */ bool SetAreaBiome(int a_MinX, int a_MaxX, int a_MinZ, int a_MaxZ, EMCSBiome a_Biome); /** Retrieves block types and metas of the specified blocks. If a chunk is not loaded, doesn't modify the block and consults a_ContinueOnFailure whether to process the rest of the array. Returns true if all blocks were read, false if any one failed. */ bool GetBlocks(sSetBlockVector & a_Blocks, bool a_ContinueOnFailure); /** Removes the block at the specified coords and wakes up simulators. Returns false if the chunk is not loaded (and the block is not dug). Returns true if successful. */ bool DigBlock(Vector3i a_BlockPos); /** Returns all the pickups that would result if the a_Digger dug up the block at a_BlockPos using a_Tool. a_Digger is usually a player, but can be nullptr for natural causes. a_Tool is an optional item used to dig up the block, used by the handlers (empty hand vs shears produce different pickups from leaves). An empty hand is assumed if a_Tool is nullptr. Returns an empty cItems object if the chunk is not present. */ cItems PickupsFromBlock(Vector3i a_BlockPos, const cEntity * a_Digger, const cItem * a_Tool); /** Sends the block at the specified coords to the specified player. Uses a blockchange packet to send the block. If the relevant chunk isn't loaded, doesn't do anything. */ void SendBlockTo(int a_BlockX, int a_BlockY, int a_BlockZ, const cPlayer & a_Player); /** Compares clients of two chunks, calls the callback accordingly */ void CompareChunkClients(int a_ChunkX1, int a_ChunkZ1, int a_ChunkX2, int a_ChunkZ2, cClientDiffCallback & a_Callback); /** Compares clients of two chunks, calls the callback accordingly */ void CompareChunkClients(cChunk * a_Chunk1, cChunk * a_Chunk2, cClientDiffCallback & a_Callback); /** Adds client to a chunk, if not already present; returns true if added, false if present */ bool AddChunkClient(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Client); /** Removes the client from the chunk */ void RemoveChunkClient(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Client); /** Removes the client from all chunks it is present in */ void RemoveClientFromChunks(cClientHandle * a_Client); /** Adds the entity to its appropriate chunk, takes ownership of the entity pointer */ void AddEntity(OwnedEntity a_Entity); /** Adds the player to its appropriate chunk, takes ownership of the player pointer */ void AddPlayer(std::unique_ptr a_Player); /** Returns true if the entity with specified ID is present in the chunks */ bool HasEntity(UInt32 a_EntityID) const; /** Removes the entity from its appropriate chunk Returns an owning reference to the found entity. */ OwnedEntity RemoveEntity(cEntity & a_Entity); /** Calls the callback for each entity in the entire world; returns true if all entities processed, false if the callback aborted by returning true */ bool ForEachEntity(cEntityCallback a_Callback) const; // Lua-accessible /** Calls the callback for each entity in the specified chunk; returns true if all entities processed, false if the callback aborted by returning true */ bool ForEachEntityInChunk(int a_ChunkX, int a_ChunkZ, cEntityCallback a_Callback); // Lua-accessible /** Calls the callback for each entity that has a nonempty intersection with the specified boundingbox. Returns true if all entities processed, false if the callback aborted by returning true. If any chunk in the box is missing, ignores the entities in that chunk silently. */ bool ForEachEntityInBox(const cBoundingBox & a_Box, cEntityCallback a_Callback); // Lua-accessible /** Calls the callback if the entity with the specified ID is found, with the entity object as the callback param. Returns true if entity found and callback returned false. */ bool DoWithEntityByID(UInt32 a_EntityID, cEntityCallback a_Callback) const; // Lua-accessible /** Calls the callback for each block entity in the specified chunk. Returns true if all block entities processed, false if the callback aborted by returning true. */ bool ForEachBlockEntityInChunk(int a_ChunkX, int a_ChunkZ, cBlockEntityCallback a_Callback); // Lua-accessible /** Calls the callback for the block entity at the specified coords. Returns false if there's no block entity at those coords, and whatever the callback returns if found. */ bool DoWithBlockEntityAt(Vector3i a_Position, cBlockEntityCallback a_Callback); // Lua-acessible /** Queues the chunk for preparing - making sure that it's generated and lit. The specified chunk is queued to be loaded or generated, and lit if needed. The specified callback is called after the chunk has been prepared. If there's no preparation to do, only the callback is called. It is legal to call without the callback. */ void PrepareChunk(int a_ChunkX, int a_ChunkZ, std::unique_ptr a_CallAfter = {}); // Lua-accessible /** Queues the chunk for generating. First attempts to load the chunk from the storage. If that fails, queues the chunk for generating. */ void GenerateChunk(int a_ChunkX, int a_ChunkZ); // Lua-accessible /** Marks the chunk as failed-to-load */ void ChunkLoadFailed(int a_ChunkX, int a_ChunkZ); /** Marks the chunk as being regenerated - all its clients want that chunk again (used by cWorld::RegenerateChunk()) */ void MarkChunkRegenerating(int a_ChunkX, int a_ChunkZ); bool IsChunkLighted(int a_ChunkX, int a_ChunkZ); /** Calls the callback for each chunk in the coords specified (all cords are inclusive). Returns true if all chunks have been processed successfully */ bool ForEachChunkInRect(int a_MinChunkX, int a_MaxChunkX, int a_MinChunkZ, int a_MaxChunkZ, cChunkDataCallback & a_Callback); /** Calls the callback for each loaded chunk. Returns true if all chunks have been processed successfully */ bool ForEachLoadedChunk(cFunctionRef a_Callback) const; /** Writes the block area into the specified coords. Returns true if all chunks have been processed. Prefer cBlockArea::Write() instead. */ bool WriteBlockArea(cBlockArea & a_Area, int a_MinBlockX, int a_MinBlockY, int a_MinBlockZ, int a_DataTypes); /** Returns the number of valid chunks and the number of dirty chunks */ void GetChunkStats(int & a_NumChunksValid, int & a_NumChunksDirty) const; /** Grows the plant at the specified position by at most a_NumStages. The block's Grow handler is invoked. Returns the number of stages the plant has grown, 0 if not a plant. */ int GrowPlantAt(Vector3i a_BlockPos, int a_NumStages = 1); /** Causes the specified block to be ticked on the next Tick() call. Plugins can use this via the cWorld:SetNextBlockToTick() API. Only one block coord per chunk may be set, a second call overwrites the first call */ void SetNextBlockToTick(const Vector3i a_BlockPos); /** Make a Mob census, of all mobs, their family, their chunk and their distance to closest player */ void CollectMobCensus(cMobCensus & a_ToFill); /** Try to Spawn Monsters inside all Chunks */ void SpawnMobs(cMobSpawner & a_MobSpawner); void Tick(std::chrono::milliseconds a_Dt); /** Ticks a single block. Used by cWorld::TickQueuedBlocks() to tick the queued blocks */ void TickBlock(const Vector3i a_BlockPos); void UnloadUnusedChunks(void); void SaveAllChunks(void) const; cWorld * GetWorld(void) const { return m_World; } size_t GetNumChunks(void) const; /** Returns the number of unused dirty chunks. Those are chunks that we can save and then unload */ size_t GetNumUnusedDirtyChunks(void) const; void ChunkValidated(void); // Called by chunks that have become valid /** Returns the CS for locking the chunkmap; only cWorld::cLock may use this function! */ cCriticalSection & GetCS(void) const { return m_CSChunks; } /** Increments (a_AlwaysTicked == true) or decrements (false) the m_AlwaysTicked counter for the specified chunk. If the m_AlwaysTicked counter is greater than zero, the chunk is ticked in the tick-thread regardless of whether it has any clients or not. This function allows nesting and task-concurrency (multiple separate tasks can request ticking and as long as at least one requests is active the chunk will be ticked). */ void SetChunkAlwaysTicked(int a_ChunkX, int a_ChunkZ, bool a_AlwaysTicked); /** Adds this chunkmap's CS to the DeadlockDetect's tracked CSs. */ void TrackInDeadlockDetect(cDeadlockDetect & a_DeadlockDetect, const AString & a_WorldName); /** Removes this chunkmap's CS from the DeadlockDetect's tracked CSs. */ void UntrackInDeadlockDetect(cDeadlockDetect & a_DeadlockDetect); private: // Chunks query their neighbors using FindChunk(), while being ticked friend class cChunk; // The chunkstay can (de-)register itself using AddChunkStay() and DelChunkStay() friend class cChunkStay; typedef std::list cChunkStays; mutable cCriticalSection m_CSChunks; /** A map of chunk coordinates to chunks. Uses a map (as opposed to unordered_map) because sorted maps are apparently faster. */ std::map m_Chunks; cEvent m_evtChunkValid; // Set whenever any chunk becomes valid, via ChunkValidated() cWorld * m_World; /** The cChunkStay descendants that are currently enabled in this chunkmap */ cChunkStays m_ChunkStays; /** Returns or creates and returns a chunk pointer corresponding to the given chunk coordinates. Emplaces this chunk in the chunk map. */ cChunk & ConstructChunk(int a_ChunkX, int a_ChunkZ); /** Constructs a chunk and queues it for loading / generating if not valid, returning it */ cChunk & GetChunk(int a_ChunkX, int a_ChunkZ); /** Locates a chunk ptr in the chunkmap; doesn't create it when not found; assumes m_CSChunks is locked. To be called only from cChunkMap. */ cChunk * FindChunk(int a_ChunkX, int a_ChunkZ); /** Locates a chunk ptr in the chunkmap; doesn't create it when not found; assumes m_CSChunks is locked. To be called only from cChunkMap. */ const cChunk * FindChunk(int a_ChunkX, int a_ChunkZ) const; /** Adds a new cChunkStay descendant to the internal list of ChunkStays; loads its chunks. To be used only by cChunkStay; others should use cChunkStay::Enable() instead */ void AddChunkStay(cChunkStay & a_ChunkStay); /** Removes the specified cChunkStay descendant from the internal list of ChunkStays. To be used only by cChunkStay; others should use cChunkStay::Disable() instead */ void DelChunkStay(cChunkStay & a_ChunkStay); }; ================================================ FILE: src/ChunkSender.cpp ================================================ // ChunkSender.cpp // Interfaces to the cChunkSender class representing the thread that waits for chunks becoming ready (loaded / generated) and sends them to clients #include "Globals.h" #include "ChunkSender.h" #include "World.h" #include "BlockEntities/BlockEntity.h" #include "ClientHandle.h" #include "Chunk.h" //////////////////////////////////////////////////////////////////////////////// // cNotifyChunkSender: /** Callback that can be used to notify chunk sender upon another chunkcoord notification */ class cNotifyChunkSender : public cChunkCoordCallback { virtual void Call(cChunkCoords a_Coords, bool a_IsSuccess) override { cChunkSender & ChunkSender = m_ChunkSender; m_World.DoWithChunk( a_Coords.m_ChunkX, a_Coords.m_ChunkZ, [&ChunkSender] (cChunk & a_Chunk) -> bool { ChunkSender.QueueSendChunkTo(a_Chunk.GetPosX(), a_Chunk.GetPosZ(), cChunkSender::Priority::High, a_Chunk.GetAllClients()); return true; } ); } cChunkSender & m_ChunkSender; cWorld & m_World; public: cNotifyChunkSender(cChunkSender & a_ChunkSender, cWorld & a_World): m_ChunkSender(a_ChunkSender), m_World(a_World) { } }; //////////////////////////////////////////////////////////////////////////////// // cChunkSender: cChunkSender::cChunkSender(cWorld & a_World) : Super("Chunk Sender"), m_World(a_World), m_Serializer(m_World.GetDimension()) { } cChunkSender::~cChunkSender() { Stop(); } void cChunkSender::Stop(void) { m_ShouldTerminate = true; m_evtQueue.Set(); Super::Stop(); } void cChunkSender::QueueSendChunkTo(int a_ChunkX, int a_ChunkZ, Priority a_Priority, cClientHandle * a_Client) { ASSERT(a_Client != nullptr); { cChunkCoords Chunk{a_ChunkX, a_ChunkZ}; cCSLock Lock(m_CS); auto iter = m_ChunkInfo.find(Chunk); if (iter != m_ChunkInfo.end()) { auto & info = iter->second; if (info.m_Priority < a_Priority) // Was the chunk's priority boosted? { m_SendChunks.push(sChunkQueue{a_Priority, Chunk}); info.m_Priority = a_Priority; } info.m_Clients.insert(a_Client->shared_from_this()); } else { m_SendChunks.push(sChunkQueue{a_Priority, Chunk}); auto info = sSendChunk{Chunk, a_Priority}; info.m_Clients.insert(a_Client->shared_from_this()); m_ChunkInfo.emplace(Chunk, info); } } m_evtQueue.Set(); } void cChunkSender::QueueSendChunkTo(int a_ChunkX, int a_ChunkZ, Priority a_Priority, const std::vector & a_Clients) { { cChunkCoords Chunk{a_ChunkX, a_ChunkZ}; cCSLock Lock(m_CS); auto iter = m_ChunkInfo.find(Chunk); if (iter != m_ChunkInfo.end()) { auto & info = iter->second; if (info.m_Priority < a_Priority) // Was the chunk's priority boosted? { m_SendChunks.push(sChunkQueue{a_Priority, Chunk}); info.m_Priority = a_Priority; } for (const auto & Client : a_Clients) { info.m_Clients.insert(Client->shared_from_this()); } } else { m_SendChunks.push(sChunkQueue{a_Priority, Chunk}); auto info = sSendChunk{Chunk, a_Priority}; for (const auto & Client : a_Clients) { info.m_Clients.insert(Client->shared_from_this()); } m_ChunkInfo.emplace(Chunk, info); } } m_evtQueue.Set(); } void cChunkSender::Execute(void) { while (!m_ShouldTerminate) { m_evtQueue.Wait(); { cCSLock Lock(m_CS); while (!m_SendChunks.empty()) { // Take one from the queue: auto Chunk = m_SendChunks.top().m_Chunk; m_SendChunks.pop(); auto itr = m_ChunkInfo.find(Chunk); if (itr == m_ChunkInfo.end()) { continue; } auto clients = std::move(itr->second.m_Clients); m_ChunkInfo.erase(itr); cCSUnlock Unlock(Lock); SendChunk(Chunk.m_ChunkX, Chunk.m_ChunkZ, clients); } } } // while (!m_ShouldTerminate) } void cChunkSender::SendChunk(int a_ChunkX, int a_ChunkZ, const WeakClients & a_Clients) { // Contains strong pointers to clienthandles. std::vector> Clients; // Ask the client if it still wants the chunk: for (const auto & WeakClient : a_Clients) { auto Client = WeakClient.lock(); if ((Client != nullptr) && Client->WantsSendChunk(a_ChunkX, a_ChunkZ)) { Clients.push_back(std::move(Client)); } } // Bail early if every requester disconnected: if (Clients.empty()) { return; } // If the chunk has no clients, no need to packetize it: if (!m_World.HasChunkAnyClients(a_ChunkX, a_ChunkZ)) { return; } // If the chunk is not valid, do nothing - whoever needs it has queued it for loading / generating if (!m_World.IsChunkValid(a_ChunkX, a_ChunkZ)) { return; } // If the chunk is not lighted, queue it for relighting and get notified when it's ready: if (!m_World.IsChunkLighted(a_ChunkX, a_ChunkZ)) { m_World.QueueLightChunk(a_ChunkX, a_ChunkZ, std::make_unique(*this, m_World)); return; } // Query and prepare chunk data: if (!m_World.GetChunkData({a_ChunkX, a_ChunkZ}, *this)) { return; } // Send: m_Serializer.SendToClients(a_ChunkX, a_ChunkZ, m_BlockData, m_LightData, m_BiomeMap, Clients); for (const auto & Client : Clients) { // Send block-entity packets: for (const auto & Pos : m_BlockEntities) { m_World.SendBlockEntity(Pos.x, Pos.y, Pos.z, *Client); } // for itr - m_Packets[] // Send entity packets: for (const auto EntityID : m_EntityIDs) { m_World.DoWithEntityByID(EntityID, [Client](cEntity & a_Entity) { /* // DEBUG: LOGD("cChunkSender: Entity #%d (%s) at [%f, %f, %f] spawning for player \"%s\"", a_Entity.GetUniqueID(), a_Entity.GetClass(), a_Entity.GetPosition().x, a_Entity.GetPosition().y, a_Entity.GetPosition().z, Client->GetUsername().c_str() ); */ /* This check looks highly suspect. Its purpose is to check the client still has a valid player object associated, since the player destroys itself when the client is destroyed. It's done within the world lock to ensure correctness. A better way involves fixing chunk sending (GH #3696) to obviate calling SpawnOn from this thread in the first place. */ if (!Client->IsDestroyed()) { a_Entity.SpawnOn(*Client); } return true; }); } } m_BlockEntities.clear(); m_EntityIDs.clear(); } void cChunkSender::BlockEntity(cBlockEntity * a_Entity) { m_BlockEntities.push_back(a_Entity->GetPos()); } void cChunkSender::Entity(cEntity * a_Entity) { m_EntityIDs.push_back(a_Entity->GetUniqueID()); } void cChunkSender::BiomeMap(const cChunkDef::BiomeMap & a_BiomeMap) { for (size_t i = 0; i < ARRAYCOUNT(m_BiomeMap); i++) { if (a_BiomeMap[i] < 255) { // Normal MC biome, copy as-is: m_BiomeMap[i] = static_cast(a_BiomeMap[i]); } else { // TODO: MCS-specific biome, need to map to some basic MC biome: ASSERT(!"Unimplemented MCS-specific biome"); } } // for i - m_BiomeMap[] } ================================================ FILE: src/ChunkSender.h ================================================ // ChunkSender.h // Interfaces to the cChunkSender class representing the thread that waits for chunks becoming ready (loaded / generated) and sends them to clients /* The whole thing is a thread that runs in a loop, waiting for either: "finished chunks" (ChunkReady()), or "chunks to send" (QueueSendChunkTo()) to come to a queue. And once they do, it requests the chunk data and sends it all away, either broadcasting (ChunkReady), or sends to a specific client (QueueSendChunkTo) Chunk data is queried using the cChunkDataCallback interface. It is cached inside the ChunkSender object during the query and then processed after the query ends. Note that the data needs to be compressed only after the query finishes, because the query callbacks run with ChunkMap's CS locked. A client may remove itself from all direct requests(QueueSendChunkTo()) by calling RemoveClient(); this ensures that the client's Send() won't be called anymore by ChunkSender. Note that it may be called by world's BroadcastToChunk() if the client is still in the chunk. */ #pragma once #include "OSSupport/IsThread.h" #include "ChunkDataCallback.h" #include "Protocol/ChunkDataSerializer.h" class cWorld; class cClientHandle; // fwd: class cChunkSender; class cChunkSender final : public cIsThread, public cChunkDataCopyCollector { using Super = cIsThread; public: cChunkSender(cWorld & a_World); virtual ~cChunkSender() override; /** Tag indicating urgency of chunk to be sent. Order MUST be from least to most urgent. */ enum class Priority { Low, Medium, High, Critical }; void Stop(void); /** Queues a chunk to be sent to a specific client */ void QueueSendChunkTo(int a_ChunkX, int a_ChunkZ, Priority a_Priority, cClientHandle * a_Client); void QueueSendChunkTo(int a_ChunkX, int a_ChunkZ, Priority a_Priority, const std::vector & a_Clients); protected: using WeakClients = std::set, std::owner_less>>; struct sChunkQueue { Priority m_Priority; cChunkCoords m_Chunk; bool operator <(const sChunkQueue & a_Other) const { // The operator will return true to affirm we're less urgent than Other // This comparison depends on the Priority enum ordering lower priority as smaller: return m_Priority < a_Other.m_Priority; } }; /** Used for sending chunks to specific clients */ struct sSendChunk { cChunkCoords m_Chunk; WeakClients m_Clients; Priority m_Priority; sSendChunk(cChunkCoords a_Chunk, Priority a_Priority) : m_Chunk(a_Chunk), m_Priority(a_Priority) { } }; cWorld & m_World; /** An instance of a chunk serializer, held to maintain its internal cache. */ cChunkDataSerializer m_Serializer; cCriticalSection m_CS; std::priority_queue m_SendChunks; std::unordered_map m_ChunkInfo; cEvent m_evtQueue; // Set when anything is added to m_ChunksReady // Data about the chunk that is being sent: // NOTE that m_BlockData[] is inherited from the cChunkDataCollector unsigned char m_BiomeMap[cChunkDef::Width * cChunkDef::Width]; std::vector m_BlockEntities; // Coords of the block entities to send std::vector m_EntityIDs; // Entity-IDs of the entities to send // cIsThread override: virtual void Execute(void) override; // cChunkDataCollector overrides: // (Note that they are called while the ChunkMap's CS is locked - don't do heavy calculations here!) virtual void BiomeMap (const cChunkDef::BiomeMap & a_BiomeMap) override; virtual void Entity (cEntity * a_Entity) override; virtual void BlockEntity (cBlockEntity * a_Entity) override; /** Sends the specified chunk to all the specified clients */ void SendChunk(int a_ChunkX, int a_ChunkZ, const WeakClients & a_Clients); } ; ================================================ FILE: src/ChunkStay.cpp ================================================ // ChunkStay.cpp // Implements the cChunkStay class representing a base for classes that keep chunks loaded #include "Globals.h" #include "ChunkStay.h" #include "ChunkMap.h" cChunkStay::cChunkStay(void) : m_ChunkMap(nullptr) { } cChunkStay::~cChunkStay() { Clear(); } void cChunkStay::Clear(void) { ASSERT(m_ChunkMap == nullptr); m_Chunks.clear(); } void cChunkStay::Add(int a_ChunkX, int a_ChunkZ) { ASSERT(m_ChunkMap == nullptr); for (cChunkCoordsVector::const_iterator itr = m_Chunks.begin(); itr != m_Chunks.end(); ++itr) { if ((itr->m_ChunkX == a_ChunkX) && (itr->m_ChunkZ == a_ChunkZ)) { // Already present return; } } // for itr - Chunks[] m_Chunks.emplace_back(a_ChunkX, a_ChunkZ); } void cChunkStay::Remove(int a_ChunkX, int a_ChunkZ) { ASSERT(m_ChunkMap == nullptr); for (cChunkCoordsVector::iterator itr = m_Chunks.begin(); itr != m_Chunks.end(); ++itr) { if ((itr->m_ChunkX == a_ChunkX) && (itr->m_ChunkZ == a_ChunkZ)) { // Found, un-"stay" m_Chunks.erase(itr); return; } } // for itr - m_Chunks[] } void cChunkStay::Enable(cChunkMap & a_ChunkMap) { ASSERT(m_ChunkMap == nullptr); m_OutstandingChunks = m_Chunks; m_ChunkMap = &a_ChunkMap; a_ChunkMap.AddChunkStay(*this); } void cChunkStay::Disable(void) { ASSERT(m_ChunkMap != nullptr); cChunkMap * ChunkMap = m_ChunkMap; m_ChunkMap = nullptr; ChunkMap->DelChunkStay(*this); } bool cChunkStay::ChunkAvailable(int a_ChunkX, int a_ChunkZ) { // Check if this is a chunk that we want: bool IsMine = false; for (cChunkCoordsVector::iterator itr = m_OutstandingChunks.begin(), end = m_OutstandingChunks.end(); itr != end; ++itr) { if ((itr->m_ChunkX == a_ChunkX) && (itr->m_ChunkZ == a_ChunkZ)) { m_OutstandingChunks.erase(itr); IsMine = true; break; } } // for itr - m_OutstandingChunks[] if (!IsMine) { return false; } // Call the appropriate callbacks: OnChunkAvailable(a_ChunkX, a_ChunkZ); if (m_OutstandingChunks.empty()) { return OnAllChunksAvailable(); } return false; } ================================================ FILE: src/ChunkStay.h ================================================ // ChunkStay.h /* Declares the cChunkStay class representing a base for classes that want to wait for certain chunks to load, then do some action on them. While the object is enabled, the chunks contained within are locked and will not unload */ #pragma once #include "ChunkDef.h" // fwd class cChunkMap; /** Makes chunks stay loaded until this object is cleared or destroyed Works by setting internal flags in the cChunk that it should not be unloaded. To optimize for speed, cChunkStay has an Enabled flag, it will "stay" the chunks only when enabled and it will refuse chunk-list manipulations when enabled. The object itself is not made thread-safe, it's supposed to be used from a single thread only. This class is abstract, the descendants are expected to provide the OnChunkAvailable() and the OnAllChunksAvailable() callback implementations. Note that those are called from the contexts of different threads' - the caller, the Loader or the Generator thread. */ class cChunkStay { public: cChunkStay(void); /** Deletes the object. Note that this calls Clear(), which means that the ChunkStay needs to be disabled. */ virtual ~cChunkStay(); /** Clears all the chunks that have been added. To be used only while the ChunkStay object is not enabled. */ void Clear(void); /** Adds a chunk to be locked from unloading. To be used only while the ChunkStay object is not enabled. */ void Add(int a_ChunkX, int a_ChunkZ); /** Releases the chunk so that it's no longer locked from unloading. To be used only while the ChunkStay object is not enabled. */ void Remove(int a_ChunkX, int a_ChunkZ); /** Enables the ChunkStay on the specified chunkmap, causing it to load and generate chunks. All the contained chunks are queued for loading / generating. */ void Enable (cChunkMap & a_ChunkMap); /** Disables the ChunkStay, the chunks are released and the ChunkStay object can be edited with Add() and Remove() again */ virtual void Disable(void); /** Returns all the chunks that should be kept */ const cChunkCoordsVector & GetChunks(void) const { return m_Chunks; } /** Called when a specific chunk become available. */ virtual void OnChunkAvailable(int a_ChunkX, int a_ChunkZ) = 0; /** Called once all of the contained chunks are available. If returns true, the ChunkStay is automatically disabled by the ChunkMap; if it returns false, the ChunkStay is kept. */ virtual bool OnAllChunksAvailable(void) = 0; /** Called by the ChunkMap when the ChunkStay is disabled. The object may choose to delete itself. */ virtual void OnDisabled(void) = 0; protected: friend class cChunkMap; /** The chunkmap where the object is enabled. Valid only after call to Enable() and before Disable(). */ cChunkMap * m_ChunkMap; /** The list of chunks to lock from unloading. */ cChunkCoordsVector m_Chunks; /** The chunks that still need loading */ cChunkCoordsVector m_OutstandingChunks; /** Called by cChunkMap when a chunk is available, checks m_NumLoaded and triggers the appropriate callbacks. May be called for chunks outside this ChunkStay. Returns true if the ChunkStay is to be automatically disabled by the ChunkMap; returns false to keep the ChunkStay. */ bool ChunkAvailable(int a_ChunkX, int a_ChunkZ); } ; ================================================ FILE: src/CircularBufferCompressor.cpp ================================================ #include "Globals.h" #include "CircularBufferCompressor.h" #include "ByteBuffer.h" ContiguousByteBufferView CircularBufferCompressor::GetView() const { return m_ContiguousIntermediate; } Compression::Result CircularBufferCompressor::Compress() { return m_Compressor.CompressZLib(m_ContiguousIntermediate); } void CircularBufferCompressor::ReadFrom(cByteBuffer & Buffer) { Buffer.ReadAll(m_ContiguousIntermediate); } void CircularBufferCompressor::ReadFrom(cByteBuffer & Buffer, size_t Size) { Buffer.ReadSome(m_ContiguousIntermediate, Size); } ContiguousByteBufferView CircularBufferExtractor::GetView() const { return m_ContiguousIntermediate; } Compression::Result CircularBufferExtractor::Extract(size_t UncompressedSize) { return m_Extractor.ExtractZLib(m_ContiguousIntermediate, UncompressedSize); } void CircularBufferExtractor::ReadFrom(cByteBuffer & Buffer, size_t Size) { Buffer.ReadSome(m_ContiguousIntermediate, Size); } ================================================ FILE: src/CircularBufferCompressor.h ================================================ #pragma once #include "StringCompression.h" class cByteBuffer; class CircularBufferCompressor { public: ContiguousByteBufferView GetView() const; Compression::Result Compress(); void ReadFrom(cByteBuffer & Buffer); void ReadFrom(cByteBuffer & Buffer, size_t Size); private: Compression::Compressor m_Compressor; std::basic_string m_ContiguousIntermediate; }; class CircularBufferExtractor { public: ContiguousByteBufferView GetView() const; Compression::Result Extract(size_t UncompressedSize); void ReadFrom(cByteBuffer & Buffer, size_t Size); private: Compression::Extractor m_Extractor; std::basic_string m_ContiguousIntermediate; }; ================================================ FILE: src/ClientHandle.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "ClientHandle.h" #include "BlockInfo.h" #include "Server.h" #include "World.h" #include "Chunk.h" #include "Entities/Pickup.h" #include "Bindings/PluginManager.h" #include "Entities/Player.h" #include "Entities/Minecart.h" #include "Inventory.h" #include "BlockEntities/BeaconEntity.h" #include "BlockEntities/ChestEntity.h" #include "BlockEntities/CommandBlockEntity.h" #include "BlockEntities/SignEntity.h" #include "UI/InventoryWindow.h" #include "UI/CraftingWindow.h" #include "UI/Window.h" #include "UI/AnvilWindow.h" #include "UI/BeaconWindow.h" #include "UI/EnchantingWindow.h" #include "Item.h" #include "Mobs/Monster.h" #include "ChatColor.h" #include "Items/ItemHandler.h" #include "Blocks/BlockHandler.h" #include "Blocks/BlockBed.h" #include "Blocks/ChunkInterface.h" #include "BlockInServerPluginInterface.h" #include "Root.h" #include "Protocol/Authenticator.h" #include "Protocol/Protocol.h" #include "CompositeChat.h" #include "Items/ItemSword.h" #include "mbedtls/md5.h" /** Maximum number of explosions to send this tick, server will start dropping if exceeded. */ #define MAX_EXPLOSIONS_PER_TICK 20 /** Maximum number of block change interactions a player can perform per tick - exceeding this causes a kick. */ #define MAX_BLOCK_CHANGE_INTERACTIONS 20 /** Maximum number of bytes that a chat message sent by a player may consist of. */ #define MAX_CHAT_MSG_LENGTH 1024 /** Maximum number of chunks to stream per tick. */ #define MAX_CHUNKS_STREAMED_PER_TICK 4 int cClientHandle::s_ClientCount = 0; float cClientHandle::FASTBREAK_PERCENTAGE; Vector3i cClientHandle::s_IllegalPosition = {0, cChunkDef::Height + 1, 0}; //////////////////////////////////////////////////////////////////////////////// // cClientHandle: cClientHandle::cClientHandle(const AString & a_IPString, int a_ViewDistance) : m_CurrentViewDistance(a_ViewDistance), m_RequestedViewDistance(a_ViewDistance), m_IPString(a_IPString), m_Player(nullptr), m_CachedSentChunk(std::numeric_limits::max(), std::numeric_limits::max()), m_ProxyConnection(false), m_HasSentDC(false), m_LastStreamedChunkX(std::numeric_limits::max()), // bogus chunk coords to force streaming upon login m_LastStreamedChunkZ(std::numeric_limits::max()), m_TicksSinceLastPacket(0), m_TimeSinceLastUnloadCheck(0), m_Ping(1000), m_PingID(1), m_BlockDigAnimStage(-1), m_BlockDigAnimSpeed(0), m_BlockDigAnimPos(s_IllegalPosition), m_HasStartedDigging(false), m_LastDigBlockPos(s_IllegalPosition), m_State(csConnected), m_NumExplosionsThisTick(0), m_NumBlockChangeInteractionsThisTick(0), m_UniqueID(0), m_HasSentPlayerChunk(false), m_Locale("en_GB"), m_LastPlacedSign(s_IllegalPosition), m_ProtocolVersion(0) { s_ClientCount++; // Not protected by CS because clients are always constructed from the same thread m_UniqueID = s_ClientCount; LOGD("New ClientHandle created at %p", static_cast(this)); } cClientHandle::~cClientHandle() { ASSERT(m_State == csDestroyed); // Has Destroy() been called? LOGD("Deleting client \"%s\" at %p", GetUsername().c_str(), static_cast(this)); LOGD("ClientHandle at %p deleted", static_cast(this)); } void cClientHandle::Destroy(void) { if (!SetState(csDestroyed)) { // Already called LOGD("%s: client %p, \"%s\" already destroyed, bailing out", __FUNCTION__, static_cast(this), m_Username.c_str()); return; } LOGD("%s: destroying client %p, \"%s\" @ %s", __FUNCTION__, static_cast(this), m_Username.c_str(), m_IPString.c_str()); { cCSLock Lock(m_CSOutgoingData); m_Protocol.HandleOutgoingData(m_OutgoingData); // Finalise any encryption. m_Link->Send(m_OutgoingData.data(), m_OutgoingData.size()); // Flush remaining data. m_Link->Shutdown(); // Cleanly close the connection. m_Link.reset(); // Release the strong reference cTCPLink holds to ourself. } } AString cClientHandle::FormatChatPrefix( bool ShouldAppendChatPrefixes, const AString & a_ChatPrefixS, const AString & m_Color1, const AString & m_Color2 ) { if (ShouldAppendChatPrefixes) { return fmt::format(FMT_STRING("{}[{}] {}"), m_Color1, a_ChatPrefixS, m_Color2); } else { return m_Color1; } } AString cClientHandle::FormatMessageType(bool ShouldAppendChatPrefixes, eMessageType a_ChatPrefix, const AString & a_AdditionalData) { switch (a_ChatPrefix) { case mtCustom: return ""; case mtFailure: return FormatChatPrefix(ShouldAppendChatPrefixes, "INFO", cChatColor::Rose, cChatColor::White); case mtInformation: return FormatChatPrefix(ShouldAppendChatPrefixes, "INFO", cChatColor::Yellow, cChatColor::White); case mtSuccess: return FormatChatPrefix(ShouldAppendChatPrefixes, "INFO", cChatColor::Green, cChatColor::White); case mtWarning: return FormatChatPrefix(ShouldAppendChatPrefixes, "WARN", cChatColor::Rose, cChatColor::White); case mtFatal: return FormatChatPrefix(ShouldAppendChatPrefixes, "FATAL", cChatColor::Red, cChatColor::White); case mtDeath: return FormatChatPrefix(ShouldAppendChatPrefixes, "DEATH", cChatColor::Gray, cChatColor::White); case mtJoin: return FormatChatPrefix(ShouldAppendChatPrefixes, "JOIN", cChatColor::Yellow, cChatColor::White); case mtLeave: return FormatChatPrefix(ShouldAppendChatPrefixes, "LEAVE", cChatColor::Yellow, cChatColor::White); case mtPrivateMessage: { if (ShouldAppendChatPrefixes) { return fmt::format(FMT_STRING("{}[MSG: {}] {}{}"), cChatColor::LightBlue, a_AdditionalData, cChatColor::White, cChatColor::Italic); } else { return fmt::format(FMT_STRING("{}: {}"), a_AdditionalData, cChatColor::LightBlue); } } case mtMaxPlusOne: break; } return ""; } cUUID cClientHandle::GenerateOfflineUUID(const AString & a_Username) { // Online UUIDs are always version 4 (random) // We use Version 3 (MD5 hash) UUIDs for the offline UUIDs // This guarantees that they will never collide with an online UUID and can be distinguished. // This is also consistent with the vanilla offline UUID scheme. return cUUID::GenerateVersion3("OfflinePlayer:" + a_Username); } bool cClientHandle::IsUUIDOnline(const cUUID & a_UUID) { // Online UUIDs are always version 4 (random) // We use Version 3 (MD5 hash) UUIDs for the offline UUIDs // This guarantees that they will never collide with an online UUID and can be distinguished. return (a_UUID.Version() == 4); } void cClientHandle::ProxyInit(const AString & a_IPString, const cUUID & a_UUID) { this->SetIPString(a_IPString); this->SetUUID(a_UUID); this->m_ProxyConnection = true; } void cClientHandle::ProxyInit(const AString & a_IPString, const cUUID & a_UUID, const Json::Value & a_Properties) { this->SetProperties(a_Properties); this->ProxyInit(a_IPString, a_UUID); } void cClientHandle::ProcessProtocolIn(void) { // Process received network data: decltype(m_IncomingData) IncomingData; { cCSLock Lock(m_CSIncomingData); // Bail out when nothing was received: if (m_IncomingData.empty()) { return; } std::swap(IncomingData, m_IncomingData); } try { m_Protocol.HandleIncomingData(*this, IncomingData); } catch (const std::exception & Oops) { Kick(Oops.what()); } } void cClientHandle::ProcessProtocolOut() { decltype(m_OutgoingData) OutgoingData; { cCSLock Lock(m_CSOutgoingData); // Bail out when there's nothing to send to avoid TCPLink::Send overhead: if (m_OutgoingData.empty()) { return; } std::swap(OutgoingData, m_OutgoingData); } // Due to cTCPLink's design of holding a strong pointer to ourself, we need to explicitly reset m_Link. // This means we need to check it's not nullptr before trying to send, but also capture the link, // to prevent it being reset between the null check and the Send: if (auto Link = m_Link; Link != nullptr) { m_Protocol.HandleOutgoingData(OutgoingData); Link->Send(OutgoingData.data(), OutgoingData.size()); } } void cClientHandle::Kick(const AString & a_Reason) { if (m_State >= csAuthenticating) // Don't log pings { LOGINFO("Kicking player %s for \"%s\"", m_Username.c_str(), StripColorCodes(a_Reason).c_str()); } SendDisconnect(a_Reason); } bool cClientHandle::BungeeAuthenticate() { if (!m_ProxyConnection && cRoot::Get()->GetServer()->OnlyAllowBungeeCord()) { Kick("You can only connect to this server using a Proxy."); return false; } cServer * Server = cRoot::Get()->GetServer(); // Proxy Shared Secret Check (BungeeGuard) const AString & ForwardSecret = Server->GetProxySharedSecret(); const bool AllowBungee = Server->ShouldAllowBungeeCord(); const bool RequireForwardSecret = AllowBungee && !ForwardSecret.empty(); if (RequireForwardSecret) { for (auto & Node : GetProperties()) { if (Node.get("name", "").asString() == "bungeeguard-token") { AString SentToken = Node.get("value", "").asString(); if (ForwardSecret.compare(SentToken) == 0) { return true; } break; } } Kick("Unable to authenticate."); return false; } else if (m_ProxyConnection) { LOG("A player connected through a proxy without requiring a forwarding secret. If open to the internet, this is very insecure!"); } return true; } void cClientHandle::Authenticate(AString && a_Name, const cUUID & a_UUID, Json::Value && a_Properties) { cCSLock Lock(m_CSState); /* LOGD("Processing authentication for client %s @ %s (%p), state = %d", m_Username.c_str(), m_IPString.c_str(), static_cast(this), m_State.load() ); //*/ if (m_State != csAuthenticating) { return; } ASSERT(m_Player == nullptr); if (!BungeeAuthenticate()) { return; } m_Username = std::move(a_Name); // Only assign UUID and properties if not already pre-assigned (BungeeCord sends those in the Handshake packet): if (m_UUID.IsNil()) { m_UUID = a_UUID; } if (m_Properties.empty()) { m_Properties = std::move(a_Properties); } // Send login success (if the protocol supports it): m_Protocol->SendLoginSuccess(); if (m_ForgeHandshake.IsForgeClient) { m_ForgeHandshake.BeginForgeHandshake(*this); } else { FinishAuthenticate(); } } void cClientHandle::FinishAuthenticate() { // Serverside spawned player (so data are loaded). std::unique_ptr Player; try { Player = std::make_unique(shared_from_this()); } catch (const std::exception & Oops) { LOGWARNING("Player \"%s\" save or statistics file loading failed: %s", GetUsername().c_str(), Oops.what()); Kick("Contact an operator.\n\nYour player's save files could not be parsed.\nTo avoid data loss you are prevented from joining."); return; } m_Player = Player.get(); /* LOGD("Created a new cPlayer object at %p for client %s @ %s (%p)", static_cast(m_Player), m_Username.c_str(), m_IPString.c_str(), static_cast(this) ); //*/ cWorld * World = cRoot::Get()->GetWorld(m_Player->GetLoadedWorldName()); if (World == nullptr) { World = cRoot::Get()->GetDefaultWorld(); } // Atomically increment player count (in server thread): cRoot::Get()->GetServer()->PlayerCreated(); if (!cRoot::Get()->GetPluginManager()->CallHookPlayerJoined(*m_Player)) { cRoot::Get()->BroadcastChatJoin(fmt::format(FMT_STRING("{} has joined the game"), m_Username)); LOGINFO("Player %s has joined the game", m_Username); } // TODO: this accesses the world spawn from the authenticator thread // World spawn should be sent in OnAddedToWorld. // Return a server login packet: m_Protocol->SendLogin(*m_Player, *World); // Send the player's permission level. // The key effect is to allow 1.9+ clients to open the command block UI. SendPlayerPermissionLevel(); if (m_Player->GetKnownRecipes().empty()) { SendInitRecipes(0); } else { for (const auto KnownRecipe : m_Player->GetKnownRecipes()) { SendInitRecipes(KnownRecipe); } } // Send player list items: SendPlayerListAddPlayer(*m_Player); // Add ourself cRoot::Get()->BroadcastPlayerListsAddPlayer(*m_Player); // Add ourself to everyone else cRoot::Get()->SendPlayerLists(m_Player); // Add everyone else to ourself // Send statistics: SendStatistics(m_Player->GetStatistics()); // Delay the first ping until the client "settles down" // This should fix #889, "BadCast exception, cannot convert bit to fm" error in client m_PingStartTime = std::chrono::steady_clock::now() + std::chrono::seconds(3); // Send the first KeepAlive packet in 3 seconds // Remove the client handle from the server, it will be ticked from its cPlayer object from now on: cRoot::Get()->GetServer()->ClientMovedToWorld(this); SetState(csDownloadingWorld); m_Player->Initialize(std::move(Player), *World); // LOGD("Client %s @ %s (%p) has been fully authenticated", m_Username.c_str(), m_IPString.c_str(), static_cast(this)); } void cClientHandle::StreamNextChunks(void) { ASSERT(m_Player != nullptr); int ChunkPosX = m_Player->GetChunkX(); int ChunkPosZ = m_Player->GetChunkZ(); if ((m_LastStreamedChunkX == ChunkPosX) && (m_LastStreamedChunkZ == ChunkPosZ)) { // All chunks are already loaded and the player has not moved, work is done: return; } // Player moved chunks and / or loading is not finished, reset to bogus (GH #4531): m_LastStreamedChunkX = std::numeric_limits::max(); m_LastStreamedChunkZ = std::numeric_limits::max(); int StreamedChunks = 0; Vector3d Position = m_Player->GetEyePosition(); Vector3d LookVector = m_Player->GetLookVector(); // Get the look vector and normalize it. LookVector.Normalize(); // High priority: Load the chunks that are in the view-direction of the player (with a radius of 3) for (int Range = 0; Range < m_CurrentViewDistance; Range++) { Vector3d Vector = Position + LookVector * cChunkDef::Width * Range; // Get the chunk from the x / z coords. int RangeX, RangeZ = 0; cChunkDef::BlockToChunk(FloorC(Vector.x), FloorC(Vector.z), RangeX, RangeZ); for (int X = 0; X < 7; X++) { for (int Z = 0; Z < 7; Z++) { int ChunkX = RangeX + ((X >= 4) ? (3 - X) : X); int ChunkZ = RangeZ + ((Z >= 4) ? (3 - Z) : Z); cChunkCoords Coords(ChunkX, ChunkZ); // Checks if the chunk is in distance if ((Diff(ChunkX, ChunkPosX) > m_CurrentViewDistance) || (Diff(ChunkZ, ChunkPosZ) > m_CurrentViewDistance)) { continue; } // If the chunk already loading / loaded -> skip { cCSLock Lock(m_CSChunkLists); if ( (m_ChunksToSend.find(Coords) != m_ChunksToSend.end()) || (m_LoadedChunks.find(Coords) != m_LoadedChunks.end()) ) { continue; } } // Unloaded chunk found -> Send it to the client. StreamChunk(ChunkX, ChunkZ, ((Range <= 2) ? cChunkSender::Priority::Critical : cChunkSender::Priority::Medium)); if (++StreamedChunks == MAX_CHUNKS_STREAMED_PER_TICK) { return; } } } } // Low priority: Add all chunks that are in range. (From the center out to the edge) for (int d = 0; d <= m_CurrentViewDistance; ++d) // cycle through (square) distance, from nearest to furthest { const auto StreamIfUnloaded = [this](const cChunkCoords Chunk) { // If the chunk already loading / loaded -> skip { cCSLock Lock(m_CSChunkLists); if ( (m_ChunksToSend.find(Chunk) != m_ChunksToSend.end()) || (m_LoadedChunks.find(Chunk) != m_LoadedChunks.end()) ) { return false; } } // Unloaded chunk found -> Send it to the client. StreamChunk(Chunk.m_ChunkX, Chunk.m_ChunkZ, cChunkSender::Priority::Low); return true; }; // For each distance, send the first unloaded chunk in a hollow square centered around current position: for (int i = -d; i <= d; ++i) { if (StreamIfUnloaded({ ChunkPosX + d, ChunkPosZ + i }) || StreamIfUnloaded({ ChunkPosX - d, ChunkPosZ + i })) { if (++StreamedChunks == MAX_CHUNKS_STREAMED_PER_TICK) { return; } } } for (int i = -d + 1; i < d; ++i) { if (StreamIfUnloaded({ ChunkPosX + i, ChunkPosZ + d }) || StreamIfUnloaded({ ChunkPosX + i, ChunkPosZ - d })) { if (++StreamedChunks == MAX_CHUNKS_STREAMED_PER_TICK) { return; } } } } // All chunks are loaded -> Sets the last loaded chunk coordinates to current coordinates m_LastStreamedChunkX = ChunkPosX; m_LastStreamedChunkZ = ChunkPosZ; } void cClientHandle::UnloadOutOfRangeChunks(void) { int ChunkPosX = FAST_FLOOR_DIV(static_cast(m_Player->GetPosX()), cChunkDef::Width); int ChunkPosZ = FAST_FLOOR_DIV(static_cast(m_Player->GetPosZ()), cChunkDef::Width); cChunkCoordsList ChunksToRemove; { cCSLock Lock(m_CSChunkLists); for (auto itr = m_LoadedChunks.begin(); itr != m_LoadedChunks.end();) { const auto DiffX = Diff((*itr).m_ChunkX, ChunkPosX); const auto DiffZ = Diff((*itr).m_ChunkZ, ChunkPosZ); if ((DiffX > m_CurrentViewDistance) || (DiffZ > m_CurrentViewDistance)) { ChunksToRemove.push_back(*itr); itr = m_LoadedChunks.erase(itr); } else { ++itr; } } for (auto itr = m_ChunksToSend.begin(); itr != m_ChunksToSend.end();) { const auto DiffX = Diff((*itr).m_ChunkX, ChunkPosX); const auto DiffZ = Diff((*itr).m_ChunkZ, ChunkPosZ); if ((DiffX > m_CurrentViewDistance) || (DiffZ > m_CurrentViewDistance)) { itr = m_ChunksToSend.erase(itr); } else { ++itr; } } } for (cChunkCoordsList::iterator itr = ChunksToRemove.begin(); itr != ChunksToRemove.end(); ++itr) { m_Player->GetWorld()->RemoveChunkClient(itr->m_ChunkX, itr->m_ChunkZ, this); SendUnloadChunk(itr->m_ChunkX, itr->m_ChunkZ); } } void cClientHandle::StreamChunk(int a_ChunkX, int a_ChunkZ, cChunkSender::Priority a_Priority) { cWorld * World = m_Player->GetWorld(); ASSERT(World != nullptr); if (World->AddChunkClient(a_ChunkX, a_ChunkZ, this)) { { cCSLock Lock(m_CSChunkLists); m_LoadedChunks.emplace(a_ChunkX, a_ChunkZ); m_ChunksToSend.emplace(a_ChunkX, a_ChunkZ); } World->SendChunkTo(a_ChunkX, a_ChunkZ, a_Priority, this); } } void cClientHandle::HandleAnimation(const bool a_SwingMainHand) { if (cPluginManager::Get()->CallHookPlayerAnimation(*m_Player, a_SwingMainHand ? 0 : 1)) { // Plugin disagrees, bail out: return; } m_Player->GetWorld()->BroadcastEntityAnimation(*m_Player, a_SwingMainHand ? EntityAnimation::PlayerMainHandSwings : EntityAnimation::PlayerOffHandSwings, this); } void cClientHandle::HandleNPCTrade(int a_SlotNum) { // TODO LOGWARNING("%s: Not implemented yet", __FUNCTION__); } void cClientHandle::HandleOpenHorseInventory() { m_Player->OpenHorseInventory(); } void cClientHandle::HandlePing(void) { /* TODO: unused function, handles Legacy Server List Ping http://wiki.vg/Protocol#Legacy_Server_List_Ping suggests that servers SHOULD handle this packet */ // Somebody tries to retrieve information about the server const cServer & Server = *cRoot::Get()->GetServer(); auto Reply = fmt::format(FMT_STRING("{}{}{}{}{}"), Server.GetDescription(), cChatColor::Delimiter, Server.GetNumPlayers(), cChatColor::Delimiter, Server.GetMaxPlayers() ); Kick(Reply); } bool cClientHandle::HandleLogin() { { cCSLock lock(m_CSState); if (m_State != csConnected) { /* LOGD("Client %s @ %s (%p, state %d) has disconnected before logging in, bailing out of login", a_Username.c_str(), m_IPString.c_str(), static_cast(this), m_State.load() ); //*/ return false; } // LOGD("Handling login for client %s @ %s (%p), state = %d", a_Username.c_str(), m_IPString.c_str(), static_cast(this), m_State.load()); // Let the plugins know about this event, they may refuse the player: if (cRoot::Get()->GetPluginManager()->CallHookLogin(*this, m_ProtocolVersion, GetUsername())) { SendDisconnect("Login Rejected!"); return false; } m_State = csAuthenticating; } // lock(m_CSState) // Schedule for authentication; until then, let the player wait (but do not block): cRoot::Get()->GetAuthenticator().Authenticate(GetUniqueID(), m_Username, m_Protocol->GetAuthServerID()); return true; } void cClientHandle::HandleCreativeInventory(Int16 a_SlotNum, const cItem & a_HeldItem, eClickAction a_ClickAction) { // This is for creative Inventory changes if (!m_Player->IsGameModeCreative()) { LOGWARNING("Got a CreativeInventoryAction packet from user \"%s\" while not in creative mode. Ignoring.", m_Username.c_str()); return; } if (m_Player->GetWindow()->GetWindowType() != cWindow::wtInventory) { LOGWARNING("Got a CreativeInventoryAction packet from user \"%s\" while not in the inventory window. Ignoring.", m_Username.c_str()); return; } m_Player->GetWindow()->Clicked(*m_Player, 0, a_SlotNum, a_ClickAction, a_HeldItem); } void cClientHandle::HandleCrouch(const bool a_IsCrouching) { m_Player->SetCrouch(a_IsCrouching); } void cClientHandle::HandleEnchantItem(UInt8 a_WindowID, UInt8 a_Enchantment) { if (a_Enchantment > 2) { LOGD("Player \"%s\" tried to select an invalid enchantment - hacked client?", m_Username.c_str()); return; } // Bail out if something's wrong with the window: if ( (m_Player->GetWindow() == nullptr) || (m_Player->GetWindow()->GetWindowID() != a_WindowID) || (m_Player->GetWindow()->GetWindowType() != cWindow::wtEnchantment) ) { LOGD("Player \"%s\" tried to enchant without a valid window - hacked client?", m_Username.c_str()); return; } cEnchantingWindow * Window = static_cast(m_Player->GetWindow()); const auto BaseEnchantmentLevel = Window->GetProperty(a_Enchantment); // Survival players must be checked they can afford enchantment and have lapis removed: if (!m_Player->IsGameModeCreative()) { const auto XpRequired = m_Player->XpForLevel(BaseEnchantmentLevel); auto LapisStack = *Window->m_SlotArea->GetSlot(1, *m_Player); // A copy of the lapis stack. const auto LapisRequired = a_Enchantment + 1; // Only allow enchantment if the player has sufficient levels and lapis to enchant: if ((m_Player->GetCurrentXp() >= XpRequired) && (LapisStack.m_ItemCount >= LapisRequired)) { // We need to reduce the player's level by the number of lapis required. // However we need to keep the resulting percentage filled the same. const auto TargetLevel = m_Player->GetXpLevel() - LapisRequired; const auto CurrentFillPercent = m_Player->GetXpPercentage(); // The experience to remove in order to reach the start (0% fill) of the target level. const auto DeltaForLevel = -m_Player->GetCurrentXp() + m_Player->XpForLevel(TargetLevel); // The experience to add to get the same fill percent. const auto DeltaForPercent = CurrentFillPercent * (m_Player->XpForLevel(TargetLevel + 1) - m_Player->XpForLevel(TargetLevel)); // Apply the experience delta, rounded for greater accuracy: m_Player->DeltaExperience(static_cast(std::lround(DeltaForLevel + DeltaForPercent))); // Now reduce the lapis in our stack and send it back: LapisStack.AddCount(static_cast(-LapisRequired)); Window->m_SlotArea->SetSlot(1, *m_Player, LapisStack); } else { // Not creative and can't afford enchantment, so exit: LOGD("Player \"%s\" selected unavailable enchantment - hacked client?", m_Username.c_str()); return; } } // The enchanted item corresponding to our chosen option (top, middle, bottom). cItem EnchantedItem = Window->m_SlotArea->SelectEnchantedOption(a_Enchantment); // Set the item slot to our new enchanted item: Window->m_SlotArea->SetSlot(0, *m_Player, EnchantedItem); m_Player->PermuteEnchantmentSeed(); } void cClientHandle::HandlePlayerAbilities(bool a_IsFlying, float FlyingSpeed, float WalkingSpeed) { UNUSED(FlyingSpeed); // Ignore the client values for these UNUSED(WalkingSpeed); m_Player->SetFlying(a_IsFlying); } void cClientHandle::HandlePluginMessage(const AString & a_Channel, const ContiguousByteBufferView a_Message) { if (a_Channel == "REGISTER") { if (HasPluginChannel(a_Channel)) { SendPluginMessage("UNREGISTER", a_Channel); return; // Can't register again if already taken - kinda defeats the point of plugin messaging! } RegisterPluginChannels(BreakApartPluginChannels(a_Message)); } else if (a_Channel == "UNREGISTER") { UnregisterPluginChannels(BreakApartPluginChannels(a_Message)); } else if (a_Channel == "FML|HS") { m_ForgeHandshake.DataReceived(*this, a_Message); } else if (!HasPluginChannel(a_Channel)) { // Ignore if client sent something but didn't register the channel first LOGD("Player %s sent a plugin message on channel \"%s\", but didn't REGISTER it first", GetUsername().c_str(), a_Channel.c_str()); SendPluginMessage("UNREGISTER", a_Channel); return; } cPluginManager::Get()->CallHookPluginMessage(*this, a_Channel, a_Message); } AStringVector cClientHandle::BreakApartPluginChannels(const ContiguousByteBufferView a_PluginChannels) { // Break the string on each NUL character. // Note that StringSplit() doesn't work on this because NUL is a special char - string terminator size_t len = a_PluginChannels.size(); size_t first = 0; AStringVector res; for (size_t i = 0; i < len; i++) { if (a_PluginChannels[i] != std::byte(0)) { continue; } if (i > first) { const auto Part = a_PluginChannels.substr(first, i - first); res.emplace_back(reinterpret_cast(Part.data()), Part.size()); } first = i + 1; } // for i - a_PluginChannels[] if (first < len) { const auto Part = a_PluginChannels.substr(first, len - first); res.emplace_back(reinterpret_cast(Part.data()), Part.size()); } return res; } void cClientHandle::RegisterPluginChannels(const AStringVector & a_ChannelList) { for (AStringVector::const_iterator itr = a_ChannelList.begin(), end = a_ChannelList.end(); itr != end; ++itr) { m_PluginChannels.insert(*itr); } // for itr - a_ChannelList[] } void cClientHandle::UnregisterPluginChannels(const AStringVector & a_ChannelList) { for (AStringVector::const_iterator itr = a_ChannelList.begin(), end = a_ChannelList.end(); itr != end; ++itr) { m_PluginChannels.erase(*itr); } // for itr - a_ChannelList[] } void cClientHandle::HandleBeaconSelection(unsigned a_PrimaryEffect, unsigned a_SecondaryEffect) { cWindow * Window = m_Player->GetWindow(); if ((Window == nullptr) || (Window->GetWindowType() != cWindow::wtBeacon)) { return; } cBeaconWindow * BeaconWindow = static_cast(Window); if (Window->GetSlot(*m_Player, 0)->IsEmpty()) { return; } cEntityEffect::eType PrimaryEffect = cEntityEffect::effNoEffect; if (a_PrimaryEffect <= static_cast(cEntityEffect::effSaturation)) { PrimaryEffect = static_cast(a_PrimaryEffect); } cEntityEffect::eType SecondaryEffect = cEntityEffect::effNoEffect; if (a_SecondaryEffect <= static_cast(cEntityEffect::effSaturation)) { SecondaryEffect = static_cast(a_SecondaryEffect); } Window->SetSlot(*m_Player, 0, cItem()); BeaconWindow->GetBeaconEntity()->SetPrimaryEffect(PrimaryEffect); // Valid effect check. Vanilla don't check this, but we do it :) if ( (SecondaryEffect == cEntityEffect::effNoEffect) || (SecondaryEffect == cEntityEffect::effRegeneration) || (SecondaryEffect == BeaconWindow->GetBeaconEntity()->GetPrimaryEffect()) ) { BeaconWindow->GetBeaconEntity()->SetSecondaryEffect(SecondaryEffect); } else { BeaconWindow->GetBeaconEntity()->SetSecondaryEffect(cEntityEffect::effNoEffect); } m_Player->CloseWindow(true); } void cClientHandle::HandleCommandBlockBlockChange(Vector3i a_BlockPos, const AString & a_NewCommand) { if (a_NewCommand.empty()) { LOGD("Player \"%s\" send an empty command block string - hacked client?", m_Username.c_str()); return; } if ((m_Player == nullptr) || !m_Player->HasPermission("cuberite.commandblock.set")) { SendChat("You cannot edit command blocks on this server", mtFailure); return; } cWorld * World = m_Player->GetWorld(); if (World->AreCommandBlocksEnabled()) { World->SetCommandBlockCommand(a_BlockPos, a_NewCommand); SendChat("Successfully set command block command", mtSuccess); } else { SendChat("Command blocks are not enabled on this server", mtFailure); } } void cClientHandle::HandleCommandBlockEntityChange(UInt32 a_EntityID, const AString & a_NewCommand) { // TODO LOGWARNING("%s: Not implemented yet", __FUNCTION__); } void cClientHandle::HandleAnvilItemName(const AString & a_ItemName) { if ((m_Player->GetWindow() == nullptr) || (m_Player->GetWindow()->GetWindowType() != cWindow::wtAnvil)) { return; } if (a_ItemName.length() <= 30) { static_cast(m_Player->GetWindow())->SetRepairedItemName(a_ItemName, m_Player); } } void cClientHandle::HandleLeftClick(Vector3i a_BlockPos, eBlockFace a_BlockFace, UInt8 a_Status) { FLOGD("HandleLeftClick: {0}; Face: {1}; Stat: {2}", a_BlockPos, a_BlockFace, a_Status ); m_NumBlockChangeInteractionsThisTick++; if (!CheckBlockInteractionsRate()) { Kick("Too many blocks were destroyed per unit time - hacked client?"); return; } if ((a_Status == DIG_STATUS_STARTED) || (a_Status == DIG_STATUS_FINISHED)) { if (a_BlockFace == BLOCK_FACE_NONE) { return; } /* Check for clickthrough-blocks: When the user breaks a fire block, the client send the wrong block location. We must find the right block with the face direction. */ if ( const auto InterferingPosition = AddFaceDirection(a_BlockPos, a_BlockFace); cChunkDef::IsValidHeight(InterferingPosition) && cBlockInfo::IsClickedThrough(m_Player->GetWorld()->GetBlock(InterferingPosition)) ) { a_BlockPos = InterferingPosition; } if (!IsWithinReach(a_BlockPos)) { m_Player->SendBlocksAround(a_BlockPos, 2); return; } } cPluginManager * PlgMgr = cRoot::Get()->GetPluginManager(); if (m_Player->IsFrozen() || PlgMgr->CallHookPlayerLeftClick(*m_Player, a_BlockPos, a_BlockFace, static_cast(a_Status))) { // A plugin doesn't agree with the action, replace the block on the client and quit: m_Player->SendBlocksAround(a_BlockPos, 2); SendPlayerPosition(); // Prevents the player from falling through the block that was temporarily broken client side. return; } switch (a_Status) { case DIG_STATUS_DROP_HELD: // Drop held item { if (PlgMgr->CallHookPlayerTossingItem(*m_Player)) { // A plugin doesn't agree with the tossing. The plugin itself is responsible for handling the consequences (possible inventory mismatch) return; } m_Player->TossEquippedItem(); return; } case DIG_STATUS_SHOOT_EAT: { auto & ItemHandler = m_Player->GetEquippedItem().GetHandler(); if (ItemHandler.IsFood() || ItemHandler.IsDrinkable(m_Player->GetEquippedItem().m_ItemDamage)) { m_Player->AbortEating(); return; } else { if (PlgMgr->CallHookPlayerShooting(*m_Player)) { // A plugin doesn't agree with the action. The plugin itself is responsible for handling the consequences (possible inventory mismatch) return; } // When bow is in off-hand / shield slot if (m_Player->GetInventory().GetShieldSlot().m_ItemType == E_ITEM_BOW) { m_Player->GetInventory().GetShieldSlot().GetHandler().OnItemShoot(m_Player, a_BlockPos, a_BlockFace); } else { ItemHandler.OnItemShoot(m_Player, a_BlockPos, a_BlockFace); } } return; } case DIG_STATUS_STARTED: { HandleBlockDigStarted(a_BlockPos, a_BlockFace); return; } case DIG_STATUS_FINISHED: { HandleBlockDigFinished(a_BlockPos, a_BlockFace); return; } case DIG_STATUS_CANCELLED: { // Block breaking cancelled by player FinishDigAnimation(); return; } case DIG_STATUS_DROP_STACK: { if (PlgMgr->CallHookPlayerTossingItem(*m_Player)) { // A plugin doesn't agree with the tossing. The plugin itself is responsible for handling the consequences (possible inventory mismatch) return; } m_Player->TossEquippedItem(64); // Toss entire slot - if there aren't enough items, the maximum will be ejected return; } case DIG_STATUS_SWAP_ITEM_IN_HAND: { cItem EquippedItem = m_Player->GetEquippedItem(); cItem OffhandItem = m_Player->GetOffHandEquipedItem(); cInventory & Inventory = m_Player->GetInventory(); Inventory.SetShieldSlot(EquippedItem); Inventory.SetEquippedItem(OffhandItem); return; } default: { ASSERT(!"Unhandled DIG_STATUS"); return; } } // switch (a_Status) } void cClientHandle::HandleBlockDigStarted(Vector3i a_BlockPos, eBlockFace a_BlockFace) { if (m_Player->IsGameModeAdventure()) { // Players in adventure mode can't destroy blocks return; } if ( m_HasStartedDigging && (a_BlockPos == m_LastDigBlockPos) ) { // It is a duplicate packet, drop it right away return; } BLOCKTYPE DiggingBlock; NIBBLETYPE DiggingMeta; if (!m_Player->GetWorld()->GetBlockTypeMeta(a_BlockPos, DiggingBlock, DiggingMeta)) { return; } if ( m_Player->IsGameModeCreative() && ItemCategory::IsSword(m_Player->GetInventory().GetEquippedItem().m_ItemType) && (DiggingBlock != E_BLOCK_FIRE) ) { // Players can't destroy blocks with a sword in the hand. return; } // Set the last digging coords to the block being dug, so that they can be checked in DIG_FINISHED to avoid dig / aim bug in the client: m_HasStartedDigging = true; m_LastDigBlockPos = a_BlockPos; if ( m_Player->IsGameModeCreative() || // In creative mode, digging is done immediately m_Player->CanInstantlyMine(DiggingBlock) // Sometimes the player is fast enough to instantly mine ) { // Immediately done: m_BreakProgress = 1; HandleBlockDigFinished(a_BlockPos, a_BlockFace); return; } m_BreakProgress = 0; // Start dig animation // TODO: calculate real animation speed // TODO: Send animation packets even without receiving any other packets m_BlockDigAnimSpeed = 10; m_BlockDigAnimPos = a_BlockPos; m_BlockDigAnimStage = 0; m_Player->GetWorld()->BroadcastBlockBreakAnimation(static_cast(m_UniqueID), m_BlockDigAnimPos, 0, this); cWorld * World = m_Player->GetWorld(); cChunkInterface ChunkInterface(World->GetChunkMap()); cBlockHandler::For(DiggingBlock).OnDigging(ChunkInterface, *World, *m_Player, a_BlockPos); m_Player->GetEquippedItem().GetHandler().OnDiggingBlock(World, m_Player, m_Player->GetEquippedItem(), a_BlockPos, a_BlockFace); } void cClientHandle::HandleBlockDigFinished(Vector3i a_BlockPos, eBlockFace a_BlockFace) { if ( !m_HasStartedDigging || // Hasn't received the DIG_STARTED packet (m_LastDigBlockPos != a_BlockPos) // DIG_STARTED has had different pos ) { FLOGD("Prevented a dig / aim bug in the client (finish {0} vs start {1}, HSD: {2})", a_BlockPos, m_LastDigBlockPos, (m_HasStartedDigging ? "True" : "False") ); return; } FinishDigAnimation(); BLOCKTYPE DugBlock; NIBBLETYPE DugMeta; if (!m_Player->GetWorld()->GetBlockTypeMeta(a_BlockPos, DugBlock, DugMeta)) { return; } if (!m_Player->IsGameModeCreative()) { m_BreakProgress += m_Player->GetMiningProgressPerTick(DugBlock); // Check for very fast tools. Maybe instead of FASTBREAK_PERCENTAGE we should check we are within x multiplied by the progress per tick if (m_BreakProgress < FASTBREAK_PERCENTAGE) { LOGD("Break progress of player %s was less than expected: %f < %f\n", m_Player->GetName().c_str(), m_BreakProgress * 100, FASTBREAK_PERCENTAGE * 100); // AntiFastBreak doesn't agree with the breaking. Bail out. Send the block back to the client, so that it knows: m_Player->SendBlocksAround(a_BlockPos, 2); SendPlayerPosition(); // Prevents the player from falling through the block that was temporarily broken client side. m_Player->SendMessage("FastBreak?"); // TODO Anticheat hook return; } } cWorld * World = m_Player->GetWorld(); if (cRoot::Get()->GetPluginManager()->CallHookPlayerBreakingBlock(*m_Player, a_BlockPos, a_BlockFace, DugBlock, DugMeta)) { // A plugin doesn't agree with the breaking. Bail out. Send the block back to the client, so that it knows: m_Player->SendBlocksAround(a_BlockPos, 2); SendPlayerPosition(); // Prevents the player from falling through the block that was temporarily broken client side. return; } if (DugBlock == E_BLOCK_AIR) { return; } // Apply hunger: m_Player->AddFoodExhaustion(0.025); // Damage the tool, but not for 0 hardness blocks: m_Player->UseEquippedItem(cBlockInfo::IsOneHitDig(DugBlock) ? cItemHandler::dlaBreakBlockInstant : cItemHandler::dlaBreakBlock); cChunkInterface ChunkInterface(World->GetChunkMap()); Vector3i absPos(a_BlockPos); if (m_Player->IsGameModeSurvival()) { World->DropBlockAsPickups(absPos, m_Player, &m_Player->GetEquippedItem()); } else { World->DigBlock(absPos, m_Player); } World->BroadcastSoundParticleEffect(EffectID::PARTICLE_BLOCK_BREAK, absPos, DugBlock, this); cRoot::Get()->GetPluginManager()->CallHookPlayerBrokenBlock(*m_Player, a_BlockPos, a_BlockFace, DugBlock, DugMeta); } void cClientHandle::FinishDigAnimation() { if (!m_HasStartedDigging) // Hasn't received the DIG_STARTED packet { return; } m_HasStartedDigging = false; if (m_BlockDigAnimStage != -1) { // End dig animation m_BlockDigAnimStage = -1; // It seems that 10 ends block animation m_Player->GetWorld()->BroadcastBlockBreakAnimation(static_cast(m_UniqueID), m_LastDigBlockPos, 10, this); } m_LastDigBlockPos = s_IllegalPosition; } void cClientHandle::HandleRightClick(Vector3i a_BlockPos, eBlockFace a_BlockFace, Vector3i a_CursorPos, bool a_UsedMainHand) { /* This function handles three actions: (1) Place a block; (2) "Use" a block: Interactive with the block, like opening a chest/crafting table/furnace; (3) Use the held item targeting a block. E.g. farming. Sneaking player will not use the block if hand is not empty. Frozen player can do nothing. In Game Mode Spectator, player cannot use item or place block, but can interactive with some block depending on cBlockInfo::IsUseableBySpectator(BlockType) If the action failed, we need to send an update of the placed block or inventory to the client. Actions rejected by plugin will not lead to other attempts. E.g., when opening a chest with a dirt in hand, if the plugin rejects opening the chest, the dirt will not be placed. */ if ((a_BlockFace == BLOCK_FACE_NONE) || !cChunkDef::IsValidHeight(a_BlockPos)) { LOGD("Player \"%s\" sent an invalid click - hacked client?", m_Username.c_str()); return; } // TODO: We are still consuming the items in main hand. Remove this override when the off-hand consumption is handled correctly. a_UsedMainHand = true; cWorld * World = m_Player->GetWorld(); cPluginManager * PlgMgr = cRoot::Get()->GetPluginManager(); const cItem & HeldItem = a_UsedMainHand ? m_Player->GetEquippedItem() : m_Player->GetInventory().GetShieldSlot(); FLOGD("HandleRightClick: {0}, face {1}, Cursor {2}, Hand: {3}, HeldItem: {4}", a_BlockPos, a_BlockFace, a_CursorPos, a_UsedMainHand, ItemToFullString(HeldItem)); if (!PlgMgr->CallHookPlayerRightClick(*m_Player, a_BlockPos, a_BlockFace, a_CursorPos) && IsWithinReach(a_BlockPos) && !m_Player->IsFrozen()) { BLOCKTYPE BlockType; NIBBLETYPE BlockMeta; if (!World->GetBlockTypeMeta(a_BlockPos, BlockType, BlockMeta)) { return; } const auto & ItemHandler = HeldItem.GetHandler(); const auto & BlockHandler = cBlockHandler::For(BlockType); const bool BlockUsable = BlockHandler.IsUseable() && (m_Player->IsGameModeSpectator() ? cBlockInfo::IsUseableBySpectator(BlockType) : !(m_Player->IsCrouched() && !HeldItem.IsEmpty())); const bool ItemPlaceable = ItemHandler.IsPlaceable() && !m_Player->IsGameModeAdventure() && !m_Player->IsGameModeSpectator(); const bool ItemUseable = !m_Player->IsGameModeSpectator(); if (BlockUsable) { cChunkInterface ChunkInterface(World->GetChunkMap()); if (!PlgMgr->CallHookPlayerUsingBlock(*m_Player, a_BlockPos, a_BlockFace, a_CursorPos, BlockType, BlockMeta)) { // Use a block: if (BlockHandler.OnUse(ChunkInterface, *World, *m_Player, a_BlockPos, a_BlockFace, a_CursorPos)) { PlgMgr->CallHookPlayerUsedBlock(*m_Player, a_BlockPos, a_BlockFace, a_CursorPos, BlockType, BlockMeta); return; // Block use was successful, we're done. } // If block use failed, fall back to placement: if (ItemPlaceable) { // Place a block: ItemHandler.OnPlayerPlace(*m_Player, HeldItem, a_BlockPos, BlockType, BlockMeta, a_BlockFace, a_CursorPos); } return; } } else if (ItemPlaceable) { // TODO: Double check that we don't need this for using item and for packet out of range m_NumBlockChangeInteractionsThisTick++; if (!CheckBlockInteractionsRate()) { Kick("Too many blocks were placed / interacted with per unit time - hacked client?"); return; } // Place a block: ItemHandler.OnPlayerPlace(*m_Player, HeldItem, a_BlockPos, BlockType, BlockMeta, a_BlockFace, a_CursorPos); return; } else if (ItemUseable) { if (!PlgMgr->CallHookPlayerUsingItem(*m_Player, a_BlockPos, a_BlockFace, a_CursorPos)) { // All plugins agree with using the item. // Use an item in hand with a target block. cBlockInServerPluginInterface PluginInterface(*World); ItemHandler.OnItemUse(World, m_Player, PluginInterface, HeldItem, a_BlockPos, a_BlockFace); PlgMgr->CallHookPlayerUsedItem(*m_Player, a_BlockPos, a_BlockFace, a_CursorPos); return; } } else { // (x) None of the above. return; } } // TODO: delete OnItemUse bool return, delete onCancelRightClick // Update the target block including the block above and below for 2 block high things: m_Player->SendBlocksAround(a_BlockPos, 2); // TODO: Send corresponding slot based on hand m_Player->GetInventory().SendEquippedSlot(); } void cClientHandle::HandleChat(const AString & a_Message) { if ((a_Message.size()) > MAX_CHAT_MSG_LENGTH) { LOGD("Player \"%s\" sent a chat message exceeding the maximum length - hacked client?", m_Username.c_str()); return; } // If a command, perform it: AString Message(a_Message); if (cRoot::Get()->GetServer()->Command(*this, Message)) { return; } // Not a command, broadcast as a message: cCompositeChat Msg; AString Color = m_Player->GetColor(); if (Color.length() == 3) { Color = AString("@") + Color[2]; } else { Color.clear(); } Msg.AddTextPart("<"); Msg.ParseText(m_Player->GetPrefix()); Msg.AddTextPart(m_Player->GetName(), Color); Msg.ParseText(m_Player->GetSuffix()); Msg.AddTextPart("> "); if (m_Player->HasPermission("cuberite.chat.format")) { Msg.ParseText(Message); } else { Msg.AddTextPart(Message); } Msg.UnderlineUrls(); cRoot::Get()->BroadcastChat(Msg); } void cClientHandle::HandlePlayerLook(float a_Rotation, float a_Pitch, bool a_IsOnGround) { m_Player->SetYaw (a_Rotation); m_Player->SetHeadYaw (a_Rotation); m_Player->SetPitch (a_Pitch); m_Player->SetTouchGround(a_IsOnGround); } void cClientHandle::HandlePlayerMove(Vector3d a_Pos, bool a_IsOnGround) { const Vector3d OldPosition = GetPlayer()->GetPosition(); const auto PreviousIsOnGround = GetPlayer()->IsOnGround(); #ifdef __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wfloat-equal" #endif if ( (OldPosition == a_Pos) && (PreviousIsOnGround == a_IsOnGround) ) { // Nothing changed, no need to do anything: return; } #ifdef __clang__ #pragma clang diagnostic pop #endif if (m_Player->IsFrozen() || (m_Player->GetHealth() <= 0)) { // "Repair" if the client tries to move while frozen or dead: SendPlayerMoveLook(); return; } // If the player has moved too far, "repair" them: if ((OldPosition - a_Pos).SqrLength() > 100 * 100) { LOGD("Too far away (%0.2f), \"repairing\" the client", (OldPosition - a_Pos).Length()); SendPlayerMoveLook(); return; } if (cRoot::Get()->GetPluginManager()->CallHookPlayerMoving(*m_Player, OldPosition, a_Pos, PreviousIsOnGround)) { SendPlayerMoveLook(); return; } // TODO: should do some checks to see if player is not moving through terrain // TODO: Official server refuses position packets too far away from each other, kicking "hacked" clients; we should, too m_Player->SetPosition(a_Pos); m_Player->SetTouchGround(a_IsOnGround); m_Player->UpdateMovementStats(a_Pos - OldPosition, PreviousIsOnGround); } void cClientHandle::HandlePlayerMoveLook(Vector3d a_Pos, float a_Rotation, float a_Pitch, bool a_IsOnGround) { HandlePlayerMove(a_Pos, a_IsOnGround); HandlePlayerLook(a_Rotation, a_Pitch, a_IsOnGround); } void cClientHandle::HandleSlotSelected(Int16 a_SlotNum) { m_Player->GetInventory().SetEquippedSlotNum(a_SlotNum); m_Player->GetWorld()->BroadcastEntityEquipment(*m_Player, 0, m_Player->GetInventory().GetEquippedItem(), this); } void cClientHandle::HandleSpectate(const cUUID & a_PlayerUUID) { if (!m_Player->IsGameModeSpectator()) { LOGD("Player \"%s\" tried to spectate when not in spectator mode - hacked client?", m_Username.c_str()); return; } m_Player->GetWorld()->DoWithPlayerByUUID(a_PlayerUUID, [=](cPlayer & a_ToSpectate) { m_Player->TeleportToEntity(a_ToSpectate); return true; }); } void cClientHandle::HandleSprint(const bool a_IsSprinting) { m_Player->SetSprint(a_IsSprinting); } void cClientHandle::HandleStartElytraFlight() { m_Player->SetElytraFlight(true); } void cClientHandle::HandleSteerVehicle(float a_Forward, float a_Sideways) { m_Player->SteerVehicle(a_Forward, a_Sideways); } void cClientHandle::HandleWindowClose(UInt8 a_WindowID) { m_Player->CloseWindowIfID(static_cast(a_WindowID)); } void cClientHandle::HandleWindowClick(UInt8 a_WindowID, Int16 a_SlotNum, eClickAction a_ClickAction, const cItem & a_HeldItem) { LOGD("WindowClick: WinID %d, SlotNum %d, action: %s, Item %s x %d", a_WindowID, a_SlotNum, ClickActionToString(a_ClickAction), ItemToString(a_HeldItem).c_str(), a_HeldItem.m_ItemCount ); cWindow * Window = m_Player->GetWindow(); if (Window == nullptr) { LOGWARNING("Player \"%s\" clicked in a non-existent window. Ignoring", m_Username.c_str()); return; } m_Player->AddKnownItem(a_HeldItem); Window->Clicked(*m_Player, a_WindowID, a_SlotNum, a_ClickAction, a_HeldItem); } void cClientHandle::HandleUpdateSign( Vector3i a_BlockPos, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4 ) { if (m_LastPlacedSign.Equals(a_BlockPos)) { m_LastPlacedSign.Set(0, -1, 0); m_Player->GetWorld()->SetSignLines(a_BlockPos, a_Line1, a_Line2, a_Line3, a_Line4, m_Player); } } void cClientHandle::HandleUseEntity(UInt32 a_TargetEntityID, bool a_IsLeftClick) { // TODO: Let plugins interfere via a hook // If the player is a spectator, let him spectate if (m_Player->IsGameModeSpectator() && a_IsLeftClick) { m_Player->GetWorld()->DoWithEntityByID(a_TargetEntityID, [=](cEntity & a_Entity) { m_Player->SpectateEntity(&a_Entity); return true; }); return; } // If it is a right click, call the entity's OnRightClicked() handler: if (!a_IsLeftClick) { cWorld * World = m_Player->GetWorld(); World->DoWithEntityByID(a_TargetEntityID, [=](cEntity & a_Entity) { if ( cPluginManager::Get()->CallHookPlayerRightClickingEntity(*m_Player, a_Entity) || ( m_Player->IsGameModeSpectator() && // Spectators cannot interact with every entity ( !a_Entity.IsMinecart() || // They can only interact with minecarts ( (static_cast(a_Entity).GetPayload() != cMinecart::mpChest) && // And only if the type matches a minecart with a chest or (static_cast(a_Entity).GetPayload() != cMinecart::mpHopper) // a minecart with a hopper ) ) ) ) { return false; } a_Entity.OnRightClicked(*m_Player); return false; } ); return; } // If it is a left click, attack the entity: m_Player->GetWorld()->DoWithEntityByID(a_TargetEntityID, [=](cEntity & a_Entity) { if (!a_Entity.GetWorld()->IsPVPEnabled()) { // PVP is disabled, disallow players hurting other players: if (a_Entity.IsPlayer()) { // Player is hurting another player which is not allowed when PVP is disabled so ignore it return true; } } a_Entity.TakeDamage(*m_Player); m_Player->AddFoodExhaustion(0.3); if (a_Entity.IsPawn()) { m_Player->NotifyNearbyWolves(static_cast(&a_Entity), true); } return true; } ); } void cClientHandle::HandleUseItem(bool a_UsedMainHand) { // Use the held item without targeting a block: eating, drinking, charging a bow, using buckets // In version 1.8.x, this function shares the same packet id with HandleRightClick. // In version >= 1.9, there is a new packet id for "Use Item". // TODO: We are still consuming the items in main hand. Remove this override when the off-hand consumption is handled correctly. a_UsedMainHand = true; const cItem & HeldItem = a_UsedMainHand ? m_Player->GetEquippedItem() : m_Player->GetInventory().GetShieldSlot(); auto & ItemHandler = HeldItem.GetHandler(); cWorld * World = m_Player->GetWorld(); cPluginManager * PlgMgr = cRoot::Get()->GetPluginManager(); LOGD("HandleUseItem: Hand: %d; HeldItem: %s", a_UsedMainHand, ItemToFullString(HeldItem).c_str()); constexpr Vector3i DefaultBlockPos(-1, 255, -1); constexpr Vector3i DefaultCursorPos(0, 0, 0); if (PlgMgr->CallHookPlayerRightClick(*m_Player, DefaultBlockPos, BLOCK_FACE_NONE, DefaultCursorPos)) { return; // Plugin denied click action } // Use item in main / off hand // TODO: do we need to sync the current inventory with client if it fails? if (m_Player->IsFrozen() || m_Player->IsGameModeSpectator()) { return; } if (ItemHandler.IsFood() || ItemHandler.IsDrinkable(HeldItem.m_ItemDamage)) { if ( ItemHandler.IsFood() && (m_Player->IsSatiated() || m_Player->IsGameModeCreative()) && // Only non-creative or hungry players can eat (HeldItem.m_ItemType != E_ITEM_GOLDEN_APPLE) && // Golden apple is a special case, it is used instead of eaten (HeldItem.m_ItemType != E_ITEM_CHORUS_FRUIT) // Chorus fruit is a special case, it is used instead of eaten ) { // The player is satiated or in creative, and trying to eat return; } if (!PlgMgr->CallHookPlayerEating(*m_Player)) { m_Player->StartEating(); } } else { // Use an item in hand without a target block if (!PlgMgr->CallHookPlayerUsingItem(*m_Player, DefaultBlockPos, BLOCK_FACE_NONE, DefaultCursorPos)) { // All plugins agree with using the item cBlockInServerPluginInterface PluginInterface(*World); ItemHandler.OnItemUse(World, m_Player, PluginInterface, HeldItem, DefaultBlockPos, BLOCK_FACE_NONE); PlgMgr->CallHookPlayerUsedItem(*m_Player, DefaultBlockPos, BLOCK_FACE_NONE, DefaultCursorPos); } } } void cClientHandle::HandleResourcePack(UInt8 a_Status) { // Kick player if client declined the resource pack if ((a_Status == 1) && cRoot::Get()->GetServer()->ShouldRequireResourcePack()) { Kick("You must accept the resource pack"); } } void cClientHandle::HandleRespawn(void) { if (m_Player->GetHealth() > 0) { LOGD("Player \"%s\" tried to respawn while alive - hacked client?", m_Username.c_str()); return; } m_Player->Respawn(); cRoot::Get()->GetPluginManager()->CallHookPlayerSpawned(*m_Player); } void cClientHandle::HandleKeepAlive(UInt32 a_KeepAliveID) { if (a_KeepAliveID == m_PingID) { m_Ping = std::chrono::steady_clock::now() - m_PingStartTime; } } bool cClientHandle::CheckMultiLogin(const AString & a_Username) { // If the multilogin is allowed, skip this check entirely: if ((cRoot::Get()->GetServer()->DoesAllowMultiLogin())) { return true; } // Check if the player is waiting to be transferred to the World. if (cRoot::Get()->GetServer()->IsPlayerInQueue(a_Username)) { Kick("A player of the username is already logged in"); return false; } // Check if the player is in any World. if (cRoot::Get()->DoWithPlayer(a_Username, [](cPlayer &) { return true; })) { Kick("A player of the username is already logged in"); return false; } return true; } bool cClientHandle::HandleHandshake(const AString & a_Username) { if (a_Username.length() > 16) { Kick("Your username is too long (>16 characters)"); return false; } if (cRoot::Get()->GetPluginManager()->CallHookHandshake(*this, a_Username)) { Kick("Entry denied by plugin"); return false; } return CheckMultiLogin(a_Username); } void cClientHandle::HandleLeaveBed() { cChunkInterface Interface(m_Player->GetWorld()->GetChunkMap()); cBlockBedHandler::VacateBed(Interface, *m_Player); } void cClientHandle::HandleUnmount(void) { m_Player->Detach(); } void cClientHandle::HandleTabCompletion(const AString & a_Text) { AStringVector Results; // Get player name completions. if (cRoot::Get()->GetServer()->ShouldAllowMultiWorldTabCompletion()) { Results = cRoot::Get()->GetPlayerTabCompletionMultiWorld(a_Text); } else { m_Player->GetWorld()->TabCompleteUserName(a_Text, Results); } // Get command completions. cRoot::Get()->GetPluginManager()->TabCompleteCommand(a_Text, Results, m_Player); if (Results.empty()) { return; } // Sort and send results. std::sort(Results.begin(), Results.end()); SendTabCompletionResults(Results); } void cClientHandle::SendData(const ContiguousByteBufferView a_Data) { if (m_HasSentDC) { // This could crash the client, because they've already unloaded the world etc., and suddenly a wild packet appears (#31) return; } cCSLock Lock(m_CSOutgoingData); m_OutgoingData += a_Data; } void cClientHandle::RemoveFromWorld(void) { // Remove all associated chunks: { cCSLock Lock(m_CSChunkLists); m_LoadedChunks.clear(); m_ChunksToSend.clear(); m_SentChunks.clear(); } // Flush outgoing data: ProcessProtocolOut(); // No need to send Unload Chunk packets, the client unloads automatically. // Here, we set last streamed values to bogus ones so everything is resent: m_LastStreamedChunkX = std::numeric_limits::max(); m_LastStreamedChunkZ = std::numeric_limits::max(); // Restart player unloaded chunk checking and freezing: m_CachedSentChunk = cChunkCoords(std::numeric_limits::max(), std::numeric_limits::max()); } bool cClientHandle::IsPlayerChunkSent() { return m_HasSentPlayerChunk; } bool cClientHandle::CheckBlockInteractionsRate(void) { ASSERT(m_Player != nullptr); ASSERT(m_Player->GetWorld() != nullptr); if (!cRoot::Get()->GetServer()->ShouldLimitPlayerBlockChanges()) { return true; } return (m_NumBlockChangeInteractionsThisTick <= MAX_BLOCK_CHANGE_INTERACTIONS); } bool cClientHandle::IsWithinReach(const Vector3i a_Position) const { // Distance from the block's center to the player's eye height. const double Distance = (Vector3d(0.5, 0.5, 0.5) + a_Position - m_Player->GetEyePosition()).SqrLength(); // _X 2014-11-25: I've maxed at 5.26 with a Survival client and 5.78 with a Creative client in my tests. return Distance <= (m_Player->IsGameModeCreative() ? 33.4084 : 27.6676); } void cClientHandle::Tick(std::chrono::milliseconds a_Dt) { using namespace std::chrono_literals; if (IsDestroyed()) { return; } m_TicksSinceLastPacket += 1; if (m_TicksSinceLastPacket > 600) // 30 seconds time-out { SendDisconnect("Nooooo!! You timed out! D: Come back!"); return; } // Freeze the player if they are standing in a chunk not yet sent to the client m_HasSentPlayerChunk = false; if (m_Player->GetParentChunk() != nullptr) { // If the chunk is invalid, it has definitely not been sent to the client yet if (m_Player->GetParentChunk()->IsValid()) { // Before iterating m_SentChunks, see if the player's coords equal m_CachedSentChunk // If so, the chunk has been sent to the client. This is an optimization that saves an iteration of m_SentChunks. if (cChunkCoords(m_Player->GetChunkX(), m_Player->GetChunkZ()) == m_CachedSentChunk) { m_HasSentPlayerChunk = true; } else { // This block is entered only when the player moves to a new chunk, invalidating the cached coords. // Otherwise the cached coords are used. cCSLock Lock(m_CSChunkLists); auto itr = std::find(m_SentChunks.begin(), m_SentChunks.end(), cChunkCoords(m_Player->GetChunkX(), m_Player->GetChunkZ())); if (itr != m_SentChunks.end()) { m_CachedSentChunk = *itr; m_HasSentPlayerChunk = true; } } } } // If the chunk the player's in was just sent, spawn the player: { cCSLock lock(m_CSState); if (m_HasSentPlayerChunk && (m_State == csDownloadingWorld)) { m_Protocol->SendPlayerMoveLook(); m_State = csPlaying; // Send resource pack (after a MoveLook, because sending it before the initial MoveLook cancels the download screen): if (const auto & ResourcePackUrl = cRoot::Get()->GetServer()->GetResourcePackUrl(); !ResourcePackUrl.empty()) { SendResourcePack(ResourcePackUrl); } } } // lock(m_CSState) // Send a ping packet: if (m_State == csPlaying) { const auto Now = std::chrono::steady_clock::now(); if ((m_PingStartTime + std::chrono::seconds(2)) <= Now) // 2 second interval between pings { m_PingID++; m_PingStartTime = Now; m_Protocol->SendKeepAlive(m_PingID); } } // Send a couple of chunks to the player: StreamNextChunks(); // Unload all chunks that are out of the view distance (every 5 seconds): if ((m_TimeSinceLastUnloadCheck += a_Dt) > 5s) { UnloadOutOfRangeChunks(); m_TimeSinceLastUnloadCheck = 0s; } // anticheat fastbreak if (m_HasStartedDigging) { BLOCKTYPE Block = m_Player->GetWorld()->GetBlock(m_LastDigBlockPos); m_BreakProgress += m_Player->GetMiningProgressPerTick(Block); } // Handle block break animation: if (m_BlockDigAnimStage > -1) { int lastAnimVal = m_BlockDigAnimStage; m_BlockDigAnimStage += static_cast(m_BlockDigAnimSpeed * a_Dt.count()); if (m_BlockDigAnimStage > 9000) { m_BlockDigAnimStage = 9000; } if (m_BlockDigAnimStage / 1000 != lastAnimVal / 1000) { m_Player->GetWorld()->BroadcastBlockBreakAnimation(static_cast(m_UniqueID), m_BlockDigAnimPos, static_cast(m_BlockDigAnimStage / 1000), this); } } // Reset explosion & block change counters: m_NumExplosionsThisTick = 0; m_NumBlockChangeInteractionsThisTick = 0; } void cClientHandle::ServerTick(float a_Dt) { ProcessProtocolIn(); ProcessProtocolOut(); m_TicksSinceLastPacket += 1; if (m_TicksSinceLastPacket > 600) // 30 seconds { SendDisconnect("Nooooo!! You timed out! D: Come back!"); } } void cClientHandle::SendAttachEntity(const cEntity & a_Entity, const cEntity & a_Vehicle) { m_Protocol->SendAttachEntity(a_Entity, a_Vehicle); } void cClientHandle::SendLeashEntity(const cEntity & a_Entity, const cEntity & a_EntityLeashedTo) { m_Protocol->SendLeashEntity(a_Entity, a_EntityLeashedTo); } void cClientHandle::SendUnleashEntity(const cEntity & a_Entity) { m_Protocol->SendUnleashEntity(a_Entity); } void cClientHandle::SendBlockAction(Vector3i a_BlockPos, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType) { m_Protocol->SendBlockAction(a_BlockPos, a_Byte1, a_Byte2, a_BlockType); } void cClientHandle::SendBlockBreakAnim(UInt32 a_EntityID, Vector3i a_BlockPos, char a_Stage) { m_Protocol->SendBlockBreakAnim(a_EntityID, a_BlockPos, a_Stage); } void cClientHandle::SendBlockChange(Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) { auto ChunkCoords = cChunkDef::BlockToChunk(a_BlockPos); // Do not send block changes in chunks that weren't sent to the client yet: cCSLock Lock(m_CSChunkLists); if (std::find(m_SentChunks.begin(), m_SentChunks.end(), ChunkCoords) != m_SentChunks.end()) { Lock.Unlock(); m_Protocol->SendBlockChange(a_BlockPos, a_BlockType, a_BlockMeta); } } void cClientHandle::SendBlockChanges(int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes) { ASSERT(!a_Changes.empty()); // We don't want to be sending empty change packets! // Do not send block changes in chunks that weren't sent to the client yet: { cCSLock Lock(m_CSChunkLists); if (std::find(m_SentChunks.begin(), m_SentChunks.end(), cChunkCoords(a_ChunkX, a_ChunkZ)) == m_SentChunks.end()) { return; } } // Use a dedicated packet for single changes: if (a_Changes.size() == 1) { const auto & Change = a_Changes[0]; m_Protocol->SendBlockChange(Change.GetAbsolutePos(), Change.m_BlockType, Change.m_BlockMeta); return; } m_Protocol->SendBlockChanges(a_ChunkX, a_ChunkZ, a_Changes); } void cClientHandle::SendBossBarAdd(UInt32 a_UniqueID, const cCompositeChat & a_Title, float a_FractionFilled, BossBarColor a_Color, BossBarDivisionType a_DivisionType, bool a_DarkenSky, bool a_PlayEndMusic, bool a_CreateFog) { m_Protocol->SendBossBarAdd(a_UniqueID, a_Title, a_FractionFilled, a_Color, a_DivisionType, a_DarkenSky, a_PlayEndMusic, a_CreateFog); } void cClientHandle::SendBossBarUpdateFlags(UInt32 a_UniqueID, bool a_DarkenSky, bool a_PlayEndMusic, bool a_CreateFog) { m_Protocol->SendBossBarUpdateFlags(a_UniqueID, a_DarkenSky, a_PlayEndMusic, a_CreateFog); } void cClientHandle::SendBossBarUpdateStyle(UInt32 a_UniqueID, BossBarColor a_Color, BossBarDivisionType a_DivisionType) { m_Protocol->SendBossBarUpdateStyle(a_UniqueID, a_Color, a_DivisionType); } void cClientHandle::SendBossBarUpdateTitle(UInt32 a_UniqueID, const cCompositeChat & a_Title) { m_Protocol->SendBossBarUpdateTitle(a_UniqueID, a_Title); } void cClientHandle::SendBossBarRemove(UInt32 a_UniqueID) { m_Protocol->SendBossBarRemove(a_UniqueID); } void cClientHandle::SendBossBarUpdateHealth(UInt32 a_UniqueID, float a_FractionFilled) { m_Protocol->SendBossBarUpdateHealth(a_UniqueID, a_FractionFilled); } void cClientHandle::SendCameraSetTo(const cEntity & a_Entity) { m_Protocol->SendCameraSetTo(a_Entity); } void cClientHandle::SendChat(const AString & a_Message, eMessageType a_ChatPrefix, const AString & a_AdditionalData) { cWorld * World = GetPlayer()->GetWorld(); if (World == nullptr) { World = cRoot::Get()->GetWorld(GetPlayer()->GetLoadedWorldName()); if (World == nullptr) { World = cRoot::Get()->GetDefaultWorld(); } } bool ShouldUsePrefixes = World->ShouldUseChatPrefixes(); AString Message = FormatMessageType(ShouldUsePrefixes, a_ChatPrefix, a_AdditionalData); m_Protocol->SendChat(Message.append(a_Message), ctChatBox, ShouldUsePrefixes); } void cClientHandle::SendChat(const cCompositeChat & a_Message) { cWorld * World = GetPlayer()->GetWorld(); if (World == nullptr) { World = cRoot::Get()->GetWorld(GetPlayer()->GetLoadedWorldName()); if (World == nullptr) { World = cRoot::Get()->GetDefaultWorld(); } } bool ShouldUsePrefixes = World->ShouldUseChatPrefixes(); m_Protocol->SendChat(a_Message, ctChatBox, ShouldUsePrefixes); } void cClientHandle::SendChatRaw(const AString & a_MessageRaw, eChatType a_Type) { m_Protocol->SendChatRaw(a_MessageRaw, a_Type); } void cClientHandle::SendChatAboveActionBar(const AString & a_Message, eMessageType a_ChatPrefix, const AString & a_AdditionalData) { cWorld * World = GetPlayer()->GetWorld(); if (World == nullptr) { World = cRoot::Get()->GetWorld(GetPlayer()->GetLoadedWorldName()); if (World == nullptr) { World = cRoot::Get()->GetDefaultWorld(); } } AString Message = FormatMessageType(World->ShouldUseChatPrefixes(), a_ChatPrefix, a_AdditionalData); m_Protocol->SendChat(Message.append(a_Message), ctAboveActionBar); } void cClientHandle::SendChatAboveActionBar(const cCompositeChat & a_Message) { m_Protocol->SendChat(a_Message, ctAboveActionBar, GetPlayer()->GetWorld()->ShouldUseChatPrefixes()); } void cClientHandle::SendChatSystem(const AString & a_Message, eMessageType a_ChatPrefix, const AString & a_AdditionalData) { cWorld * World = GetPlayer()->GetWorld(); if (World == nullptr) { World = cRoot::Get()->GetWorld(GetPlayer()->GetLoadedWorldName()); if (World == nullptr) { World = cRoot::Get()->GetDefaultWorld(); } } auto ShouldUsePrefixes = World->ShouldUseChatPrefixes(); AString Message = FormatMessageType(ShouldUsePrefixes, a_ChatPrefix, a_AdditionalData); m_Protocol->SendChat(Message.append(a_Message), ctSystem, ShouldUsePrefixes); } void cClientHandle::SendChatSystem(const cCompositeChat & a_Message) { m_Protocol->SendChat(a_Message, ctSystem, GetPlayer()->GetWorld()->ShouldUseChatPrefixes()); } void cClientHandle::SendChunkData(int a_ChunkX, int a_ChunkZ, const ContiguousByteBufferView a_ChunkData) { ASSERT(m_Player != nullptr); // Check chunks being sent, erase them from m_ChunksToSend: bool Found = false; { cCSLock Lock(m_CSChunkLists); auto itr = m_ChunksToSend.find(cChunkCoords{a_ChunkX, a_ChunkZ}); if (itr != m_ChunksToSend.end()) { m_ChunksToSend.erase(itr); Found = true; } } if (!Found) { // This just sometimes happens. If you have a reliably replicatable situation for this, go ahead and fix it // It's not a big issue anyway, just means that some chunks may be compressed several times // LOG("Refusing to send chunk [%d, %d] to client \"%s\" at [%d, %d].", a_ChunkX, a_ChunkZ, m_Username.c_str(), m_Player->GetChunkX(), m_Player->GetChunkZ()); // 2020 08 21: seems to happen going through nether portals on 1.8.9 return; } if (!m_Protocol.VersionRecognitionSuccessful()) { // TODO (#2588): investigate if and why this occurs return; } m_Protocol->SendChunkData(a_ChunkData); // Add the chunk to the list of chunks sent to the player: { cCSLock Lock(m_CSChunkLists); m_SentChunks.emplace_back(a_ChunkX, a_ChunkZ); } } void cClientHandle::SendCollectEntity(const cEntity & a_Collected, const cEntity & a_Collector, unsigned a_Count) { m_Protocol->SendCollectEntity(a_Collected, a_Collector, a_Count); } void cClientHandle::SendDestroyEntity(const cEntity & a_Entity) { m_Protocol->SendDestroyEntity(a_Entity); } void cClientHandle::SendDetachEntity(const cEntity & a_Entity, const cEntity & a_PreviousVehicle) { m_Protocol->SendDetachEntity(a_Entity, a_PreviousVehicle); } void cClientHandle::SendDisconnect(const AString & a_Reason) { LOGD("Sending a DC: \"%s\"", StripColorCodes(a_Reason).c_str()); m_Protocol.SendDisconnect(*this, a_Reason); m_HasSentDC = true; Destroy(); } void cClientHandle::SendEditSign(Vector3i a_BlockPos) { m_LastPlacedSign = a_BlockPos; m_Protocol->SendEditSign(a_BlockPos); } void cClientHandle::SendEntityEffect(const cEntity & a_Entity, int a_EffectID, int a_Amplifier, int a_Duration) { m_Protocol->SendEntityEffect(a_Entity, a_EffectID, a_Amplifier, a_Duration); } void cClientHandle::SendEntityEquipment(const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item) { m_Protocol->SendEntityEquipment(a_Entity, a_SlotNum, a_Item); } void cClientHandle::SendEntityHeadLook(const cEntity & a_Entity) { ASSERT(a_Entity.GetUniqueID() != m_Player->GetUniqueID()); // Must not send for self m_Protocol->SendEntityHeadLook(a_Entity); } void cClientHandle::SendEntityLook(const cEntity & a_Entity) { ASSERT(a_Entity.GetUniqueID() != m_Player->GetUniqueID()); // Must not send for self m_Protocol->SendEntityLook(a_Entity); } void cClientHandle::SendEntityMetadata(const cEntity & a_Entity) { m_Protocol->SendEntityMetadata(a_Entity); } void cClientHandle::SendEntityPosition(const cEntity & a_Entity) { m_Protocol->SendEntityPosition(a_Entity); } void cClientHandle::SendEntityProperties(const cEntity & a_Entity) { m_Protocol->SendEntityProperties(a_Entity); } void cClientHandle::SendEntityVelocity(const cEntity & a_Entity) { m_Protocol->SendEntityVelocity(a_Entity); } void cClientHandle::SendExplosion(const Vector3f a_Position, const float a_Power) { if (m_NumExplosionsThisTick > MAX_EXPLOSIONS_PER_TICK) { LOGD("Dropped an explosion!"); return; } // Update the statistics: m_NumExplosionsThisTick++; auto & Random = GetRandomProvider(); const auto SoundPitchMultiplier = 1.0f + (Random.RandReal() - Random.RandReal()) * 0.2f; // Sound: SendSoundEffect("entity.generic.explode", a_Position, 4.0f, SoundPitchMultiplier * 0.7f); const auto ParticleFormula = a_Power * 0.33f; auto Spread = ParticleFormula * 0.5f; auto ParticleCount = std::min(static_cast(ParticleFormula * 125), 600); // Dark smoke particles: SendParticleEffect("largesmoke", a_Position, {0.f, 0.f, 0.f}, Spread, static_cast(ParticleCount)); Spread = ParticleFormula * 0.35f; ParticleCount = std::min(static_cast(ParticleFormula * 550), 1800); // Light smoke particles: SendParticleEffect("explode", a_Position, {0.f, 0.f, 0.f}, Spread, static_cast(ParticleCount)); // Shockwave effect: m_Protocol->SendExplosion(a_Position, a_Power); } void cClientHandle::SendGameMode(eGameMode a_GameMode) { m_Protocol->SendGameMode(a_GameMode); } void cClientHandle::SendHealth(void) { m_Protocol->SendHealth(); } void cClientHandle::SendHeldItemChange(int a_ItemIndex) { m_Protocol->SendHeldItemChange(a_ItemIndex); } void cClientHandle::SendHideTitle(void) { m_Protocol->SendHideTitle(); } void cClientHandle::SendInventorySlot(char a_WindowID, short a_SlotNum, const cItem & a_Item) { m_Protocol->SendInventorySlot(a_WindowID, a_SlotNum, a_Item); } void cClientHandle::SendMapData(const cMap & a_Map, int a_DataStartX, int a_DataStartY) { m_Protocol->SendMapData(a_Map, a_DataStartX, a_DataStartY); } void cClientHandle::SendParticleEffect(const AString & a_ParticleName, Vector3f a_Source, Vector3f a_Offset, float a_ParticleData, int a_ParticleAmount) { m_Protocol->SendParticleEffect(a_ParticleName, a_Source, a_Offset, a_ParticleData, a_ParticleAmount); } void cClientHandle::SendParticleEffect(const AString & a_ParticleName, const Vector3f a_Src, const Vector3f a_Offset, float a_ParticleData, int a_ParticleAmount, std::array a_Data) { m_Protocol->SendParticleEffect(a_ParticleName, a_Src, a_Offset, a_ParticleData, a_ParticleAmount, a_Data); } void cClientHandle::SendPaintingSpawn(const cPainting & a_Painting) { m_Protocol->SendPaintingSpawn(a_Painting); } void cClientHandle::SendEntityAnimation(const cEntity & a_Entity, EntityAnimation a_Animation) { m_Protocol->SendEntityAnimation(a_Entity, a_Animation); } void cClientHandle::SendPlayerAbilities() { m_Protocol->SendPlayerAbilities(); } void cClientHandle::SendPlayerListAddPlayer(const cPlayer & a_Player) { m_Protocol->SendPlayerListAddPlayer(a_Player); } void cClientHandle::SendPlayerListHeaderFooter(const cCompositeChat & a_Header, const cCompositeChat & a_Footer) { m_Protocol->SendPlayerListHeaderFooter(a_Header, a_Footer); } void cClientHandle::SendPlayerListRemovePlayer(const cPlayer & a_Player) { m_Protocol->SendPlayerListRemovePlayer(a_Player); } void cClientHandle::SendPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_CustomName) { m_Protocol->SendPlayerListUpdateDisplayName(a_Player, a_CustomName); } void cClientHandle::SendPlayerListUpdateGameMode(const cPlayer & a_Player) { m_Protocol->SendPlayerListUpdateGameMode(a_Player); } void cClientHandle::SendPlayerListUpdatePing() { m_Protocol->SendPlayerListUpdatePing(); } void cClientHandle::SendPlayerMoveLook (const Vector3d a_Pos, const float a_Yaw, const float a_Pitch, const bool a_IsRelative) { m_Protocol->SendPlayerMoveLook(a_Pos, a_Yaw, a_Pitch, a_IsRelative); } void cClientHandle::SendPlayerMoveLook(void) { /* FLOGD("Sending PlayerMoveLook: {0:0.2f}, stance {1:0.2f}, OnGround: {2}", m_Player->GetPosition(), m_Player->GetStance(), m_Player->IsOnGround() ); */ m_Protocol->SendPlayerMoveLook(); } void cClientHandle::SendPlayerPermissionLevel() { m_Protocol->SendPlayerPermissionLevel(); } void cClientHandle::SendPlayerPosition(void) { m_Protocol->SendPlayerPosition(); } void cClientHandle::SendPlayerSpawn(const cPlayer & a_Player) { if (a_Player.GetUniqueID() == m_Player->GetUniqueID()) { // Do NOT send this packet to myself return; } LOGD("Spawning player \"%s\" on client \"%s\" @ %s", a_Player.GetName().c_str(), GetPlayer()->GetName().c_str(), GetIPString().c_str() ); m_Protocol->SendPlayerSpawn(a_Player); } void cClientHandle::SendPluginMessage(const AString & a_Channel, const std::string_view a_Message) { m_Protocol->SendPluginMessage(a_Channel, { reinterpret_cast(a_Message.data()), a_Message.size() }); } void cClientHandle::SendPluginMessage(const AString & a_Channel, const ContiguousByteBufferView a_Message) { m_Protocol->SendPluginMessage(a_Channel, a_Message); } void cClientHandle::SendRemoveEntityEffect(const cEntity & a_Entity, int a_EffectID) { m_Protocol->SendRemoveEntityEffect(a_Entity, a_EffectID); } void cClientHandle::SendResetTitle() { m_Protocol->SendResetTitle(); } void cClientHandle::SendRespawn(const eDimension a_Dimension, const bool a_IsRespawningFromDeath) { if (!a_IsRespawningFromDeath && (a_Dimension == m_Player->GetWorld()->GetDimension())) { // The client goes crazy if we send a respawn packet with the dimension of the current world // So we send a temporary one first. // This is not needed when the player dies, hence the a_IsRespawningFromDeath flag. // a_IsRespawningFromDeath is true only at cPlayer::Respawn, which is called after the player dies. // First send a temporary dimension to placate the client: m_Protocol->SendRespawn((a_Dimension == dimOverworld) ? dimNether : dimOverworld); } m_Protocol->SendRespawn(a_Dimension); } void cClientHandle::SendExperience(void) { m_Protocol->SendExperience(); } void cClientHandle::SendExperienceOrb(const cExpOrb & a_ExpOrb) { m_Protocol->SendExperienceOrb(a_ExpOrb); } void cClientHandle::SendResourcePack(const AString & a_ResourcePackUrl) { m_Protocol->SendResourcePack(a_ResourcePackUrl); } void cClientHandle::SendScoreboardObjective(const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) { m_Protocol->SendScoreboardObjective(a_Name, a_DisplayName, a_Mode); } void cClientHandle::SendScoreUpdate(const AString & a_Objective, const AString & a_Player, cObjective::Score a_Score, Byte a_Mode) { m_Protocol->SendScoreUpdate(a_Objective, a_Player, a_Score, a_Mode); } void cClientHandle::SendDisplayObjective(const AString & a_Objective, cScoreboard::eDisplaySlot a_Display) { m_Protocol->SendDisplayObjective(a_Objective, a_Display); } void cClientHandle::SendSetSubTitle(const cCompositeChat & a_SubTitle) { m_Protocol->SendSetSubTitle(a_SubTitle); } void cClientHandle::SendSetRawSubTitle(const AString & a_SubTitle) { m_Protocol->SendSetRawSubTitle(a_SubTitle); } void cClientHandle::SendSetTitle(const cCompositeChat & a_Title) { m_Protocol->SendSetTitle(a_Title); } void cClientHandle::SendSetRawTitle(const AString & a_Title) { m_Protocol->SendSetRawTitle(a_Title); } void cClientHandle::SendSoundEffect(const AString & a_SoundName, double a_X, double a_Y, double a_Z, float a_Volume, float a_Pitch) { LOG("SendSoundEffect with double args is deprecated, use version with vector position parameter."); SendSoundEffect(a_SoundName, {a_X, a_Y, a_Z}, a_Volume, a_Pitch); } void cClientHandle::SendSoundEffect(const AString & a_SoundName, Vector3d a_Position, float a_Volume, float a_Pitch) { m_Protocol->SendSoundEffect(a_SoundName, a_Position, a_Volume, a_Pitch); } void cClientHandle::SendSoundParticleEffect(const EffectID a_EffectID, Vector3i a_Source, int a_Data) { m_Protocol->SendSoundParticleEffect(a_EffectID, a_Source, a_Data); } void cClientHandle::SendSpawnEntity(const cEntity & a_Entity) { m_Protocol->SendSpawnEntity(a_Entity); } void cClientHandle::SendSpawnMob(const cMonster & a_Mob) { m_Protocol->SendSpawnMob(a_Mob); } void cClientHandle::SendStatistics(const StatisticsManager & a_Manager) { m_Protocol->SendStatistics(a_Manager); } void cClientHandle::SendTabCompletionResults(const AStringVector & a_Results) { m_Protocol->SendTabCompletionResults(a_Results); } void cClientHandle::SendThunderbolt(Vector3i a_BlockPos) { m_Protocol->SendThunderbolt(a_BlockPos); } void cClientHandle::SendTitleTimes(int a_FadeInTicks, int a_DisplayTicks, int a_FadeOutTicks) { m_Protocol->SendTitleTimes(a_FadeInTicks, a_DisplayTicks, a_FadeOutTicks); } void cClientHandle::SendTimeUpdate(const cTickTimeLong a_WorldAge, const cTickTimeLong a_WorldDate, const bool a_DoDaylightCycle) { m_Protocol->SendTimeUpdate(a_WorldAge, a_WorldDate, a_DoDaylightCycle); } void cClientHandle::SendUnloadChunk(int a_ChunkX, int a_ChunkZ) { // Remove the chunk from the list of chunks sent to the client: { cCSLock Lock(m_CSChunkLists); m_SentChunks.remove(cChunkCoords(a_ChunkX, a_ChunkZ)); } m_Protocol->SendUnloadChunk(a_ChunkX, a_ChunkZ); } void cClientHandle::SendUpdateBlockEntity(cBlockEntity & a_BlockEntity) { m_Protocol->SendUpdateBlockEntity(a_BlockEntity); } void cClientHandle::SendUpdateSign( Vector3i a_BlockPos, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4 ) { m_Protocol->SendUpdateSign( a_BlockPos, a_Line1, a_Line2, a_Line3, a_Line4 ); } void cClientHandle::SendUnlockRecipe(UInt32 a_RecipeId) { m_Protocol->SendUnlockRecipe(a_RecipeId); } void cClientHandle::SendInitRecipes(UInt32 a_RecipeId) { m_Protocol->SendInitRecipes(a_RecipeId); } void cClientHandle::HandleCraftRecipe(UInt32 a_RecipeId) { auto * Window = m_Player->GetWindow(); if (Window == nullptr) { return; } if (Window->GetWindowType() == cWindow::wtInventory) { static_cast(Window)->LoadRecipe(*m_Player, a_RecipeId); } else if (Window->GetWindowType() == cWindow::wtWorkbench) { static_cast(Window)->LoadRecipe(*m_Player, a_RecipeId); } } void cClientHandle::SendWeather(eWeather a_Weather) { m_Protocol->SendWeather(a_Weather); } void cClientHandle::SendWholeInventory(const cWindow & a_Window) { m_Protocol->SendWholeInventory(a_Window); } void cClientHandle::SendWindowClose(const cWindow & a_Window) { m_Protocol->SendWindowClose(a_Window); } void cClientHandle::SendWindowOpen(const cWindow & a_Window) { m_Protocol->SendWindowOpen(a_Window); } void cClientHandle::SendWindowProperty(const cWindow & a_Window, size_t a_Property, short a_Value) { m_Protocol->SendWindowProperty(a_Window, a_Property, a_Value); } const AString & cClientHandle::GetUsername(void) const { return m_Username; } void cClientHandle::SetUsername(AString && a_Username) { m_Username = std::move(a_Username); } void cClientHandle::SetViewDistance(int a_ViewDistance) { m_RequestedViewDistance = a_ViewDistance; LOGD("%s is requesting ViewDistance of %d!", GetUsername().c_str(), m_RequestedViewDistance); cWorld * world = m_Player->GetWorld(); if (world != nullptr) { // Set the current view distance based on the requested VD and world max VD: m_CurrentViewDistance = Clamp(a_ViewDistance, cClientHandle::MIN_VIEW_DISTANCE, world->GetMaxViewDistance()); // Restart chunk streaming to respond to new view distance: m_LastStreamedChunkX = std::numeric_limits::max(); m_LastStreamedChunkZ = std::numeric_limits::max(); } } bool cClientHandle::HasPluginChannel(const AString & a_PluginChannel) { return (m_PluginChannels.find(a_PluginChannel) != m_PluginChannels.end()); } bool cClientHandle::WantsSendChunk(int a_ChunkX, int a_ChunkZ) { if (m_State >= csDestroyed) { return false; } cCSLock Lock(m_CSChunkLists); return m_ChunksToSend.find(cChunkCoords(a_ChunkX, a_ChunkZ)) != m_ChunksToSend.end(); } void cClientHandle::AddWantedChunk(int a_ChunkX, int a_ChunkZ) { if (m_State >= csDestroyed) { return; } LOGD("Adding chunk [%d, %d] to wanted chunks for client %p", a_ChunkX, a_ChunkZ, static_cast(this)); cCSLock Lock(m_CSChunkLists); if (m_ChunksToSend.find(cChunkCoords(a_ChunkX, a_ChunkZ)) == m_ChunksToSend.end()) { m_ChunksToSend.emplace(a_ChunkX, a_ChunkZ); } } void cClientHandle::PacketBufferFull(void) { // Too much data in the incoming queue, the server is probably too busy, kick the client: LOGERROR("Too much data in queue for client \"%s\" @ %s, kicking them.", m_Username, m_IPString); SendDisconnect("The server is busy; please try again later."); } void cClientHandle::PacketUnknown(UInt32 a_PacketType) { LOGERROR("Unknown packet type 0x%x from client \"%s\" @ %s", a_PacketType, m_Username, m_IPString); SendDisconnect(fmt::format(FMT_STRING("Unknown [C->S] PacketType: 0x{:x}"), a_PacketType)); } void cClientHandle::PacketError(UInt32 a_PacketType) { LOGERROR("Protocol error while parsing packet type 0x%02x; disconnecting client \"%s\"", a_PacketType, m_Username); SendDisconnect("Protocol error"); } void cClientHandle::SocketClosed(void) { // The socket has been closed for any reason /* LOGD("SocketClosed for client %s @ %s (%p), state = %d, m_Player = %p", m_Username.c_str(), m_IPString.c_str(), static_cast(this), m_State.load(), static_cast(m_Player) ); //*/ // Log into console, unless it's a client ping: if (!m_Username.empty()) { LOGD("Client %s @ %s disconnected", m_Username.c_str(), m_IPString.c_str()); cRoot::Get()->GetPluginManager()->CallHookDisconnect(*this, "Player disconnected"); } // Queue self for destruction: Destroy(); } bool cClientHandle::SetState(eState a_NewState) { cCSLock Lock(m_CSState); if (a_NewState <= m_State) { return false; // Can only advance the state machine } m_State = a_NewState; return true; } void cClientHandle::OnLinkCreated(cTCPLinkPtr a_Link) { m_Link = a_Link; } void cClientHandle::OnReceivedData(const char * a_Data, size_t a_Length) { // Reset the timeout: m_TicksSinceLastPacket = 0; // Queue the incoming data to be processed in the tick thread: cCSLock Lock(m_CSIncomingData); m_IncomingData.append(reinterpret_cast(a_Data), a_Length); } void cClientHandle::OnRemoteClosed(void) { /* LOGD("Client socket for %s @ %s has been closed.", m_Username.c_str(), m_IPString.c_str() ); //*/ SocketClosed(); } void cClientHandle::OnError(int a_ErrorCode, const AString & a_ErrorMsg) { LOGD("An error has occurred on client link for %s @ %s: %d (%s). Client disconnected.", m_Username.c_str(), m_IPString.c_str(), a_ErrorCode, a_ErrorMsg.c_str() ); SocketClosed(); } ================================================ FILE: src/ClientHandle.h ================================================ // cClientHandle.h // Interfaces to the cClientHandle class representing a client connected to this server. The client need not be a player yet #pragma once #include "OSSupport/Network.h" #include "Defines.h" #include "Scoreboard.h" #include "UI/SlotArea.h" #include "json/json.h" #include "ChunkSender.h" #include "EffectID.h" #include "Protocol/ForgeHandshake.h" #include "Protocol/ProtocolRecognizer.h" #include "UUID.h" // fwd: class cChunkDataSerializer; class cMonster; class cExpOrb; class cPainting; class cPickup; class cPlayer; class cProtocol; class cWindow; class cFallingBlock; class cCompositeChat; class cMap; class cClientHandle; struct StatisticsManager; typedef std::shared_ptr cClientHandlePtr; class cClientHandle // tolua_export : public cTCPLink::cCallbacks, public std::enable_shared_from_this { // tolua_export public: // tolua_export #if defined(ANDROID) static const int DEFAULT_VIEW_DISTANCE = 4; // The default ViewDistance (used when no value is set in Settings.ini) #else static const int DEFAULT_VIEW_DISTANCE = 10; #endif static const int MAX_VIEW_DISTANCE = 32; static const int MIN_VIEW_DISTANCE = 1; /** The percentage how much a block has to be broken. Should be a value between 0.7 (70% broken) and 1 (100% broken) depending on lag. Can be set in settings.ini [AntiCheat] FastBreakPercentage=(from 0 to 100) */ static float FASTBREAK_PERCENTAGE; /** Creates a new client with the specified IP address in its description and the specified initial view distance. */ cClientHandle(const AString & a_IPString, int a_ViewDistance); virtual ~cClientHandle() override; const AString & GetIPString(void) const { return m_IPString; } // tolua_export /** Sets the IP string that the client is using. Overrides the IP string that was read from the socket. Used mainly by BungeeCord compatibility code. */ void SetIPString(const AString & a_IPString) { m_IPString = a_IPString; } cPlayer * GetPlayer(void) { return m_Player; } // tolua_export /** Returns the player's UUID, as used by the protocol */ const cUUID & GetUUID(void) const { return m_UUID; } // Exported in ManualBindings.cpp /** Sets the player's UUID, as used by the protocol. Used mainly by BungeeCord compatibility code - when authenticating is done on the BungeeCord server and the results are passed to MCS running in offline mode. */ void SetUUID(const cUUID & a_UUID) { ASSERT(!a_UUID.IsNil()); m_UUID = a_UUID; } const Json::Value & GetProperties(void) const { return m_Properties; } /** Sets the player's properties, such as skin image and signature. Used mainly by BungeeCord compatibility code - property querying is done on the BungeeCord server and the results are passed to MCS running in offline mode. */ void SetProperties(const Json::Value & a_Properties) { m_Properties = a_Properties; } /** Generates an UUID based on the player name provided. This is used for the offline (non-auth) mode, when there's no UUID source. Each username generates a unique and constant UUID, so that when the player reconnects with the same name, their UUID is the same. */ static cUUID GenerateOfflineUUID(const AString & a_Username); // Exported in ManualBindings.cpp /** Returns true if the UUID is generated by online auth, false if it is an offline-generated UUID. We use Version-3 UUIDs for offline UUIDs, online UUIDs are Version-4, thus we can tell them apart. */ static bool IsUUIDOnline(const cUUID & a_UUID); // Exported in ManualBindings.cpp /** Function to mark bungee / proxy connection on this client, and to add proxy-related data */ void ProxyInit(const AString & a_IPString, const cUUID & a_UUID); void ProxyInit(const AString & a_IPString, const cUUID & a_UUID, const Json::Value & a_Properties); /** Processes the data in the network input buffer. Called by both cWorld::Tick() and ServerTick(). */ void ProcessProtocolIn(void); /** Flushes all buffered outgoing data to the network. */ void ProcessProtocolOut(); /** Formats the type of message with the proper color and prefix for sending to the client. */ static AString FormatMessageType(bool ShouldAppendChatPrefixes, eMessageType a_ChatPrefix, const AString & a_AdditionalData); static AString FormatChatPrefix( bool ShouldAppendChatPrefixes, const AString & a_ChatPrefixS, const AString & m_Color1, const AString & m_Color2 ); void Kick(const AString & a_Reason); // tolua_export /** Authenticates the specified user with the bungee proxy server */ bool BungeeAuthenticate(); /** Authenticates ourselves, called by cAuthenticator supplying player details from Mojang. */ void Authenticate(AString && a_Name, const cUUID & a_UUID, Json::Value && a_Properties); /** Sends a set number of new chunks to the player on every invocation, until all chunks in the view distance have been sent. */ void StreamNextChunks(); /** Remove all loaded chunks that are no longer in range */ void UnloadOutOfRangeChunks(void); inline bool IsLoggedIn(void) const { return (m_State >= csAuthenticating); } /** Called while the client is being ticked from the world via its cPlayer object */ void Tick(std::chrono::milliseconds a_Dt); /** Called while the client is being ticked from the cServer object */ void ServerTick(float a_Dt); void Destroy(void); bool IsPlaying (void) const { return (m_State == csPlaying); } bool IsDestroyed (void) const { return (m_State == csDestroyed); } // The following functions send the various packets: // (Please keep these alpha-sorted) void SendAttachEntity (const cEntity & a_Entity, const cEntity & a_Vehicle); void SendBlockAction (Vector3i a_BlockPos, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType); void SendBlockBreakAnim (UInt32 a_EntityID, Vector3i a_BlockPos, char a_Stage); // tolua_export void SendBlockChange (Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta); // tolua_export void SendBlockChanges (int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes); void SendBossBarAdd (UInt32 a_UniqueID, const cCompositeChat & a_Title, float a_FractionFilled, BossBarColor a_Color, BossBarDivisionType a_DivisionType, bool a_DarkenSky, bool a_PlayEndMusic, bool a_CreateFog); // tolua_export void SendBossBarUpdateFlags (UInt32 a_UniqueID, bool a_DarkenSky, bool a_PlayEndMusic, bool a_CreateFog); // tolua_export void SendBossBarUpdateStyle (UInt32 a_UniqueID, BossBarColor a_Color, BossBarDivisionType a_DivisionType); // tolua_export void SendBossBarUpdateTitle (UInt32 a_UniqueID, const cCompositeChat & a_Title); // tolua_export void SendBossBarRemove (UInt32 a_UniqueID); // tolua_export void SendBossBarUpdateHealth (UInt32 a_UniqueID, float a_FractionFilled); // tolua_export void SendCameraSetTo (const cEntity & a_Entity); void SendChat (const AString & a_Message, eMessageType a_ChatPrefix, const AString & a_AdditionalData = ""); void SendChat (const cCompositeChat & a_Message); void SendChatRaw (const AString & a_MessageRaw, eChatType a_Type); void SendChatAboveActionBar (const AString & a_Message, eMessageType a_ChatPrefix, const AString & a_AdditionalData = ""); void SendChatAboveActionBar (const cCompositeChat & a_Message); void SendChatSystem (const AString & a_Message, eMessageType a_ChatPrefix, const AString & a_AdditionalData = ""); void SendChatSystem (const cCompositeChat & a_Message); void SendChunkData (int a_ChunkX, int a_ChunkZ, ContiguousByteBufferView a_ChunkData); void SendCollectEntity (const cEntity & a_Collected, const cEntity & a_Collector, unsigned a_Count); // tolua_export void SendDestroyEntity (const cEntity & a_Entity); // tolua_export void SendDetachEntity (const cEntity & a_Entity, const cEntity & a_PreviousVehicle); // tolua_export void SendDisconnect (const AString & a_Reason); void SendDisplayObjective (const AString & a_Objective, cScoreboard::eDisplaySlot a_Display); void SendEditSign (Vector3i a_BlockPos); // tolua_export void SendEntityAnimation (const cEntity & a_Entity, EntityAnimation a_Animation); // tolua_export void SendEntityEffect (const cEntity & a_Entity, int a_EffectID, int a_Amplifier, int a_Duration); void SendEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item); void SendEntityHeadLook (const cEntity & a_Entity); void SendEntityLook (const cEntity & a_Entity); void SendEntityMetadata (const cEntity & a_Entity); void SendEntityPosition (const cEntity & a_Entity); void SendEntityProperties (const cEntity & a_Entity); void SendEntityVelocity (const cEntity & a_Entity); void SendExperience (void); void SendExperienceOrb (const cExpOrb & a_ExpOrb); void SendExplosion (Vector3f a_Position, float a_Power); void SendGameMode (eGameMode a_GameMode); void SendHealth (void); void SendHeldItemChange (int a_ItemIndex); void SendHideTitle (void); // tolua_export void SendInventorySlot (char a_WindowID, short a_SlotNum, const cItem & a_Item); void SendLeashEntity (const cEntity & a_Entity, const cEntity & a_EntityLeashedTo); // tolua_export void SendMapData (const cMap & a_Map, int a_DataStartX, int a_DataStartY); void SendPaintingSpawn (const cPainting & a_Painting); void SendParticleEffect (const AString & a_ParticleName, Vector3f a_Source, Vector3f a_Offset, float a_ParticleData, int a_ParticleAmount); void SendParticleEffect (const AString & a_ParticleName, const Vector3f a_Src, const Vector3f a_Offset, float a_ParticleData, int a_ParticleAmount, std::array a_Data); void SendPlayerAbilities (void); void SendPlayerListAddPlayer (const cPlayer & a_Player); void SendPlayerListHeaderFooter (const cCompositeChat & a_Header, const cCompositeChat & a_Footer); // tolua_export void SendPlayerListRemovePlayer (const cPlayer & a_Player); void SendPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_CustomName); void SendPlayerListUpdateGameMode (const cPlayer & a_Player); void SendPlayerListUpdatePing (); void SendPlayerMoveLook (Vector3d a_Pos, float a_Yaw, float a_Pitch, bool a_IsRelative); void SendPlayerMoveLook (void); void SendPlayerPermissionLevel (void); void SendPlayerPosition (void); void SendPlayerSpawn (const cPlayer & a_Player); void SendPluginMessage (const AString & a_Channel, std::string_view a_Message); // Exported in ManualBindings.cpp void SendPluginMessage (const AString & a_Channel, ContiguousByteBufferView a_Message); void SendRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID); void SendResourcePack (const AString & a_ResourcePackUrl); // tolua_export void SendResetTitle (void); // tolua_export void SendRespawn (eDimension a_Dimension, bool a_IsRespawningFromDeath); void SendScoreUpdate (const AString & a_Objective, const AString & a_Player, cObjective::Score a_Score, Byte a_Mode); void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode); void SendSetSubTitle (const cCompositeChat & a_SubTitle); // tolua_export void SendSetRawSubTitle (const AString & a_SubTitle); // tolua_export void SendSetTitle (const cCompositeChat & a_Title); // tolua_export void SendSetRawTitle (const AString & a_Title); // tolua_export void SendSoundEffect (const AString & a_SoundName, double a_X, double a_Y, double a_Z, float a_Volume, float a_Pitch); // tolua_export void SendSoundEffect (const AString & a_SoundName, Vector3d a_Position, float a_Volume, float a_Pitch); // tolua_export void SendSoundParticleEffect (const EffectID a_EffectID, Vector3i a_Source, int a_Data); void SendSpawnEntity (const cEntity & a_Entity); void SendSpawnMob (const cMonster & a_Mob); void SendStatistics (const StatisticsManager & a_Manager); void SendTabCompletionResults (const AStringVector & a_Results); void SendThunderbolt (Vector3i a_BlockPos); // tolua_export void SendTitleTimes (int a_FadeInTicks, int a_DisplayTicks, int a_FadeOutTicks); // tolua_export void SendTimeUpdate (cTickTimeLong a_WorldAge, cTickTimeLong a_WorldDate, bool a_DoDaylightCycle); void SendUnleashEntity (const cEntity & a_Entity); // tolua_export void SendUnloadChunk (int a_ChunkX, int a_ChunkZ); void SendUpdateBlockEntity (cBlockEntity & a_BlockEntity); void SendUpdateSign (Vector3i a_BlockPos, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4); /** Send a newly discovered recipe to show the notification and unlock in the recipe book */ void SendUnlockRecipe (UInt32 a_RecipeId); /** Send already known recipes without notification but visible in the recipe book */ void SendInitRecipes (UInt32 a_RecipeId); void SendWeather (eWeather a_Weather); void SendWholeInventory (const cWindow & a_Window); void SendWindowClose (const cWindow & a_Window); void SendWindowOpen (const cWindow & a_Window); void SendWindowProperty (const cWindow & a_Window, size_t a_Property, short a_Value); const AString & GetUsername(void) const; // tolua_export void SetUsername(AString && a_Username); // tolua_begin inline short GetPing(void) const { return static_cast(std::chrono::duration_cast(m_Ping).count()); } /** Sets the maximal view distance. */ void SetViewDistance(int a_ViewDistance); /** Returns the view distance that the player currently have. */ int GetViewDistance(void) const { return m_CurrentViewDistance; } /** Returns the view distance that the player request, not the used view distance. */ int GetRequestedViewDistance(void) const { return m_RequestedViewDistance; } void SetLocale(const AString & a_Locale) { m_Locale = a_Locale; } AString GetLocale(void) const { return m_Locale; } int GetUniqueID(void) const { return m_UniqueID; } bool HasPluginChannel(const AString & a_PluginChannel); /** Called by the protocol when it receives the MC|Brand plugin message. Also callable by plugins. Simply stores the string value. */ void SetClientBrand(const AString & a_ClientBrand) { m_ClientBrand = a_ClientBrand; } /** Returns the client brand received in the MC|Brand plugin message or set by a plugin. */ const AString & GetClientBrand(void) const { return m_ClientBrand; } /** Returns the Forge mods installed on the client. */ const AStringMap & GetForgeMods(void) const { return m_ForgeMods; } /** Returns true if the client is modded with Forge. */ bool IsForgeClient(void) const { return m_ForgeHandshake.IsForgeClient; } // tolua_end /** Add the Forge mod list to the server ping response. */ void ForgeAugmentServerListPing(Json::Value & a_Response) { m_ForgeHandshake.AugmentServerListPing(*this, a_Response); } /** Mark a client connection as using Forge. Set by the protocol. */ void SetIsForgeClient() { m_ForgeHandshake.IsForgeClient = true; } /** Returns true if the client wants the chunk specified to be sent (in m_ChunksToSend) */ bool WantsSendChunk(int a_ChunkX, int a_ChunkZ); /** Adds the chunk specified to the list of chunks wanted for sending (m_ChunksToSend) */ void AddWantedChunk(int a_ChunkX, int a_ChunkZ); // Calls that cProtocol descendants use to report state: void PacketBufferFull(void); void PacketUnknown(UInt32 a_PacketType); void PacketError(UInt32 a_PacketType); /** Called when the protocol receives a (hand swing) animation packet. */ void HandleAnimation(bool a_SwingMainHand); /** Called when the protocol receives a MC|ItemName plugin message, indicating that the player named an item in the anvil UI. */ void HandleAnvilItemName(const AString & a_ItemName); /** Called when the protocol receives a MC|Beacon plugin message, indicating that the player set an effect in the beacon UI. */ void HandleBeaconSelection(unsigned a_PrimaryEffect, unsigned a_SecondaryEffect); /** Called when the protocol detects a chat packet. */ void HandleChat(const AString & a_Message); /** Called when the protocol receives a message, indicating that the player set a new command in the command block UI, for a block-based commandblock. */ void HandleCommandBlockBlockChange(Vector3i a_BlockPos, const AString & a_NewCommand); /** Called when the protocol receives a message, indicating that the player set a new command in the command block UI, for an entity-based commandblock (minecart?). */ void HandleCommandBlockEntityChange(UInt32 a_EntityID, const AString & a_NewCommand); /** Called when the client clicks the creative inventory window. a_ClickAction specifies whether the click was inside the window or not (caLeftClick or caLeftClickOutside). */ void HandleCreativeInventory(Int16 a_SlotNum, const cItem & a_HeldItem, eClickAction a_ClickAction); /** Handles a player sneaking or unsneaking. */ void HandleCrouch(bool a_IsCrouching); /** Called when the player enchants an Item in the Enchanting table UI. */ void HandleEnchantItem(UInt8 a_WindowID, UInt8 a_Enchantment); /** Kicks the client if the same username is already logged in. Returns false if the client has been kicked, true otherwise. */ bool CheckMultiLogin(const AString & a_Username); /** Called when the protocol handshake has been received (for protocol versions that support it; otherwise the first instant when a username is received). Returns true if the player is to be let in, false if they were disconnected */ bool HandleHandshake (const AString & a_Username); /** Handles a player exiting his bed. */ void HandleLeaveBed(); void HandleKeepAlive (UInt32 a_KeepAliveID); void HandleLeftClick (Vector3i a_BlockPos, eBlockFace a_BlockFace, UInt8 a_Status); /** Called when the protocol receives a MC|TrSel packet, indicating that the player used a trade in the NPC UI. */ void HandleNPCTrade(int a_SlotNum); /** Handles a player opening his inventory while riding a horse. */ void HandleOpenHorseInventory(); void HandlePing (void); void HandlePlayerAbilities (bool a_IsFlying, float FlyingSpeed, float WalkingSpeed); void HandlePlayerLook (float a_Rotation, float a_Pitch, bool a_IsOnGround); /** Verifies and sets player position, performing relevant checks. Calls relevant methods to process movement related statistics. Requires state of previous position and on-ground status, so must be called when these are still intact. */ void HandlePlayerMove(Vector3d a_Pos, bool a_IsOnGround); void HandlePlayerMoveLook(Vector3d a_Pos, float a_Rotation, float a_Pitch, bool a_IsOnGround); void HandlePluginMessage (const AString & a_Channel, ContiguousByteBufferView a_Message); void HandleResourcePack (UInt8 a_Status); void HandleRespawn (void); void HandleRightClick (Vector3i a_BlockPos, eBlockFace a_BlockFace, Vector3i a_Cursor, bool a_UsedMainHand); void HandleSlotSelected (Int16 a_SlotNum); void HandleSpectate (const cUUID & a_PlayerUUID); /** Handles a player sprinting or slowing back down. */ void HandleSprint(bool a_IsSprinting); /** Handles a player starting elytra flight while falling. */ void HandleStartElytraFlight(); void HandleSteerVehicle (float Forward, float Sideways); void HandleTabCompletion (const AString & a_Text); void HandleUpdateSign ( Vector3i a_BlockPos, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4 ); void HandleUnmount (void); void HandleUseEntity (UInt32 a_TargetEntityID, bool a_IsLeftClick); void HandleUseItem (bool a_UsedMainHand); void HandleWindowClick (UInt8 a_WindowID, Int16 a_SlotNum, eClickAction a_ClickAction, const cItem & a_HeldItem); void HandleWindowClose (UInt8 a_WindowID); /** Called when a recipe from the recipe book is selected */ void HandleCraftRecipe (UInt32 a_RecipeId); /** Called when the protocol has finished logging the user in. Return true to allow the user in; false to kick them. */ bool HandleLogin(); void SendData(ContiguousByteBufferView a_Data); /** Called when the player moves into a different world. Sends an UnloadChunk packet for each loaded chunk and resets the streamed chunks. */ void RemoveFromWorld(void); /** Called by the protocol recognizer when the protocol version is known. */ void SetProtocolVersion(UInt32 a_ProtocolVersion) { m_ProtocolVersion = a_ProtocolVersion; } /** Returns the protocol version number of the protocol that the client is talking. Returns zero if the protocol version is not (yet) known. */ UInt32 GetProtocolVersion(void) const { return m_ProtocolVersion; } // tolua_export bool IsPlayerChunkSent(); private: friend class cForgeHandshake; // Needs access to FinishAuthenticate() /** The type used for storing the names of registered plugin channels. */ typedef std::set cChannels; /** Forge handshake state machine. */ cForgeHandshake m_ForgeHandshake; /** Forge mods and versions installed on this client. */ AStringMap m_ForgeMods; /** The actual view distance used, the minimum of client's requested view distance and world's max view distance. */ int m_CurrentViewDistance; /** The requested view distance from the player. It isn't clamped with 1 and the max view distance of the world. */ int m_RequestedViewDistance; AString m_IPString; AString m_Username; AString m_Password; Json::Value m_Properties; cCriticalSection m_CSChunkLists; std::unordered_set m_LoadedChunks; // Chunks that the player belongs to std::unordered_set m_ChunksToSend; // Chunks that need to be sent to the player (queued because they weren't generated yet or there's not enough time to send them) cChunkCoordsList m_SentChunks; // Chunks that are currently sent to the client cMultiVersionProtocol m_Protocol; /** Protects m_IncomingData against multithreaded access. */ cCriticalSection m_CSIncomingData; /** Queue for the incoming data received on the link until it is processed in ProcessProtocolIn(). Protected by m_CSIncomingData. */ ContiguousByteBuffer m_IncomingData; /** Protects m_OutgoingData against multithreaded access. */ cCriticalSection m_CSOutgoingData; /** Buffer for storing outgoing data from any thread; will get sent in ProcessProtocolOut() at the end of each tick. Protected by m_CSOutgoingData. */ ContiguousByteBuffer m_OutgoingData; /** A pointer to a World-owned player object, created in FinishAuthenticate when authentication succeeds. The player should only be accessed from the tick thread of the World that owns him. After the player object is handed off to the World, its lifetime is managed automatically, and strongly owns this client handle. The player self-destructs some time after the client handle enters the Destroyed state. We are therefore guaranteed that while m_State < Destroyed, that is when when we need to access m_Player, m_Player is valid. */ cPlayer * m_Player; /** This is an optimization which saves you an iteration of m_SentChunks if you just want to know whether or not the player is standing at a sent chunk. If this is equal to the coordinates of the chunk the player is currrently standing at, then this must be a sent chunk and a member of m_SentChunks. Otherwise, this contains an arbitrary value which should not be used. */ cChunkCoords m_CachedSentChunk; bool m_ProxyConnection; ///< True if player connected from a proxy (Bungee / Velocity) bool m_HasSentDC; ///< True if a Disconnect packet has been sent in either direction // Chunk position when the last StreamChunks() was called; used to avoid re-streaming while in the same chunk int m_LastStreamedChunkX; int m_LastStreamedChunkZ; /** Number of ticks since the last network packet was received (increased in Tick(), reset in OnReceivedData()) */ std::atomic m_TicksSinceLastPacket; /** The time since UnloadOutOfRangeChunks was last called. */ std::chrono::milliseconds m_TimeSinceLastUnloadCheck; /** Duration of the last completed client ping. */ std::chrono::steady_clock::duration m_Ping; /** ID of the last ping request sent to the client. */ UInt32 m_PingID; /** Time of the last ping request sent to the client. */ std::chrono::steady_clock::time_point m_PingStartTime; // Values required for block dig animation int m_BlockDigAnimStage; // Current stage of the animation; -1 if not digging int m_BlockDigAnimSpeed; // Current speed of the animation (units ???) Vector3i m_BlockDigAnimPos; // To avoid dig / aim bug in the client, store the last position given in a DIG_START packet and compare to that when processing the DIG_FINISH packet: bool m_HasStartedDigging; Vector3i m_LastDigBlockPos; enum eState { csConnected, ///< The client has just connected, waiting for their handshake / login csAuthenticating, ///< The client has logged in, waiting for external authentication csDownloadingWorld, ///< The client is waiting for chunks, we're waiting for the loader to provide and send them csPlaying, ///< Normal gameplay csDestroyed, ///< The client has been destroyed, the destructor is to be called from the owner thread } ; /* Mutex protecting m_State from concurrent writes. */ cCriticalSection m_CSState; /** The current (networking) state of the client. Protected from concurrent writes by m_CSState; but may be read by other threads concurrently. If a function depends on m_State or wants to change m_State, it needs to lock m_CSState. However, if it only uses m_State for a quick bail out, or it doesn't break if the client disconnects in the middle of it, it may just read m_State without locking m_CSState. */ std::atomic m_State; /** Number of explosions sent this tick */ int m_NumExplosionsThisTick; /** Number of place or break interactions this tick */ int m_NumBlockChangeInteractionsThisTick; static int s_ClientCount; static Vector3i s_IllegalPosition; /** ID used for identification during authenticating. Assigned sequentially for each new instance. */ int m_UniqueID; /** Contains the UUID used by Mojang to identify the player's account. */ cUUID m_UUID; /** Set to true when the chunk where the player is is sent to the client. Used for spawning the player */ bool m_HasSentPlayerChunk; /** Client Settings */ AString m_Locale; /** The positions from the last sign that the player placed. It's needed to verify the sign text change. */ Vector3i m_LastPlacedSign; /** The plugin channels that the client has registered. */ cChannels m_PluginChannels; /** The brand identification of the client, as received in the MC|Brand plugin message or set from a plugin. */ AString m_ClientBrand; /** The version of the protocol that the client is talking, or 0 if unknown. */ UInt32 m_ProtocolVersion; /** The link that is used for network communication. m_CSOutgoingData is used to synchronize access for sending data. */ cTCPLinkPtr m_Link; /** The fraction between 0 and 1 (or above), of how far through mining the currently mined block is. 0 for just started, 1 and above for broken. Used for anti-cheat. */ float m_BreakProgress; /** Finish logging the user in after authenticating. */ void FinishAuthenticate(); /** Returns true if the rate block interactions is within a reasonable limit (bot protection) */ bool CheckBlockInteractionsRate(void); /** Returns whether the player could in fact reach the position they're attempting to interact with. */ bool IsWithinReach(Vector3i a_Position) const; /** Adds a single chunk to be streamed to the client; used by StreamChunks() */ void StreamChunk(int a_ChunkX, int a_ChunkZ, cChunkSender::Priority a_Priority); /** Handles the DIG_STARTED dig packet: */ void HandleBlockDigStarted (Vector3i a_BlockPos, eBlockFace a_BlockFace); /** Handles the DIG_FINISHED dig packet: */ void HandleBlockDigFinished(Vector3i a_BlockPos, eBlockFace a_BlockFace); /** The clients will receive a finished dig animation */ void FinishDigAnimation(); /** Converts the protocol-formatted channel list (NUL-separated) into a proper string vector. */ AStringVector BreakApartPluginChannels(ContiguousByteBufferView a_PluginChannels); /** Adds all of the channels to the list of current plugin channels. Handles duplicates gracefully. */ void RegisterPluginChannels(const AStringVector & a_ChannelList); /** Removes all of the channels from the list of current plugin channels. Ignores channels that are not found. */ void UnregisterPluginChannels(const AStringVector & a_ChannelList); /** Called when the network socket has been closed. */ void SocketClosed(void); /** Called to update m_State. Only succeeds if a_NewState > m_State, otherwise returns false. */ bool SetState(eState a_NewState); // cTCPLink::cCallbacks overrides: virtual void OnLinkCreated(cTCPLinkPtr a_Link) override; virtual void OnReceivedData(const char * a_Data, size_t a_Length) override; virtual void OnRemoteClosed(void) override; virtual void OnError(int a_ErrorCode, const AString & a_ErrorMsg) override; }; // tolua_export ================================================ FILE: src/Color.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "Color.h" #define COLOR_RED_BITS 0x00FF0000 #define COLOR_GREEN_BITS 0x0000FF00 #define COLOR_BLUE_BITS 0x000000FF #define COLOR_RED_OFFSET 16 #define COLOR_GREEN_OFFSET 8 void cColor::SetColor(unsigned char a_Red, unsigned char a_Green, unsigned char a_Blue) { m_Color = (static_cast(a_Red) << COLOR_RED_OFFSET) + (static_cast(a_Green) << COLOR_GREEN_OFFSET) + (static_cast(a_Blue)); } void cColor::SetRed(unsigned char a_Red) { m_Color = (static_cast(a_Red) << COLOR_RED_OFFSET) + ((COLOR_GREEN_BITS | COLOR_BLUE_BITS) & m_Color); } void cColor::SetGreen(unsigned char a_Green) { m_Color = (static_cast(a_Green) << COLOR_GREEN_OFFSET) + ((COLOR_RED_BITS | COLOR_BLUE_BITS) & m_Color); } void cColor::SetBlue(unsigned char a_Blue) { m_Color = static_cast(a_Blue) + ((COLOR_RED_BITS | COLOR_GREEN_BITS) & m_Color); } unsigned char cColor::GetRed() const { return static_cast((m_Color & COLOR_RED_BITS) >> COLOR_RED_OFFSET); } unsigned char cColor::GetGreen() const { return (m_Color & COLOR_GREEN_BITS) >> COLOR_GREEN_OFFSET; } unsigned char cColor::GetBlue() const { return m_Color & COLOR_BLUE_BITS; } ================================================ FILE: src/Color.h ================================================ // Color.h // Declares a class to handle item color related code #pragma once // tolua_begin class cColor { public: enum eColorLimits : unsigned int { COLOR_MIN = 0, COLOR_MAX = 255, COLOR_LIMIT = 256, COLOR_NONE = 0xFFFFFFFF, }; cColor() { m_Color = static_cast(COLOR_NONE);} cColor(unsigned char a_Red, unsigned char a_Green, unsigned char a_Blue) { SetColor(a_Red, a_Green, a_Blue); } /** Returns whether the color is a valid color */ bool IsValid() const { return m_Color != COLOR_NONE; } /** Changes the color */ void SetColor(unsigned char a_Red, unsigned char a_Green, unsigned char a_Blue); /** Alters the red value of the color */ void SetRed(unsigned char a_Red); /** Alters the green value of the color */ void SetGreen(unsigned char a_Green); /** Alters the blue value of the color */ void SetBlue(unsigned char a_Blue); /** Returns the red value of the color */ unsigned char GetRed() const; /** Returns the green value of the color */ unsigned char GetGreen() const; /** Returns the blue value of the color */ unsigned char GetBlue() const; /** Resets the color */ void Clear() { m_Color = static_cast(COLOR_NONE); } // tolua_end unsigned int m_Color; }; // tolua_export ================================================ FILE: src/CommandOutput.cpp ================================================ // CommandOutput.cpp // Implements the various classes that process command output #include "Globals.h" #include "CommandOutput.h" //////////////////////////////////////////////////////////////////////////////// // cStringAccumCommandOutputCallback: void cStringAccumCommandOutputCallback::Out(const AString & a_Text) { m_Accum.append(a_Text); } //////////////////////////////////////////////////////////////////////////////// // cLogCommandOutputCallback: void cLogCommandOutputCallback::Finished() { // Log each line separately: size_t len = m_Accum.length(); size_t last = 0; for (size_t i = 0; i < len; i++) { switch (m_Accum[i]) { case '\n': { LOG("%s", m_Accum.substr(last, i - last)); last = i + 1; break; } } } // for i - m_Buffer[] if (last < len) { LOG("%s", m_Accum.substr(last)); } // Clear the buffer for the next command output: m_Accum.clear(); } ================================================ FILE: src/CommandOutput.h ================================================ // CommandOutput.h // Declares various classes that process command output #pragma once /** Interface for a callback that receives command output The Out() function is called for any output the command has produced. Descendants override that function to provide specific processing of the output. */ class cCommandOutputCallback { public: virtual ~cCommandOutputCallback() {} // Force a virtual destructor in subclasses /** Called when the command wants to output anything; may be called multiple times */ virtual void Out(const AString & a_Text) = 0; /** Outputs the specified text, plus a newline. */ void OutLn(const AString & aText) { Out(aText); Out("\n"); } /** Called when the command processing has been finished */ virtual void Finished() {} } ; /** Class that discards all command output */ class cNullCommandOutputCallback : public cCommandOutputCallback { // cCommandOutputCallback overrides: virtual void Out(const AString & a_Text) override { // Do nothing UNUSED(a_Text); } } ; /** Accumulates all command output into a string. */ class cStringAccumCommandOutputCallback: public cCommandOutputCallback { using Super = cCommandOutputCallback; public: // cCommandOutputCallback overrides: virtual void Out(const AString & a_Text) override; virtual void Finished() override {} /** Returns the accumulated command output in a string. */ const AString & GetAccum() const { return m_Accum; } protected: /** Output is stored here until the command finishes processing */ AString m_Accum; } ; /** Sends all command output to a log, line by line, when the command finishes processing */ class cLogCommandOutputCallback : public cStringAccumCommandOutputCallback { public: // cStringAccumCommandOutputCallback overrides: virtual void Finished() override; } ; /** Sends all command output to a log, line by line; deletes self when command finishes processing */ class cLogCommandDeleteSelfOutputCallback: public cLogCommandOutputCallback { using Super = cLogCommandOutputCallback; virtual void Finished() override { Super::Finished(); delete this; } } ; ================================================ FILE: src/CompositeChat.cpp ================================================ // CompositeChat.cpp // Implements the cCompositeChat class used to wrap a chat message with multiple parts (text, url, cmd) #include "Globals.h" #include "CompositeChat.h" #include "ClientHandle.h" #include "JsonUtils.h" //////////////////////////////////////////////////////////////////////////////// // cCompositeChat: cCompositeChat::cCompositeChat(void) : m_MessageType(mtCustom) { } cCompositeChat::cCompositeChat(const AString & a_ParseText, eMessageType a_MessageType) : m_MessageType(a_MessageType) { ParseText(a_ParseText); } void cCompositeChat::Clear(void) { m_Parts.clear(); } void cCompositeChat::AddTextPart(const AString & a_Message, const AString & a_Style) { m_Parts.push_back(TextPart{{ a_Message, a_Style, {} } }); } void cCompositeChat::AddClientTranslatedPart(const AString & a_TranslationID, const AStringVector & a_Parameters, const AString & a_Style) { m_Parts.push_back(ClientTranslatedPart{{ a_TranslationID, a_Style, {} }, a_Parameters }); } void cCompositeChat::AddUrlPart(const AString & a_Text, const AString & a_Url, const AString & a_Style) { m_Parts.push_back(UrlPart{{ a_Text, a_Style, {} }, a_Url }); } void cCompositeChat::AddRunCommandPart(const AString & a_Text, const AString & a_Command, const AString & a_Style) { m_Parts.push_back(RunCommandPart{{{ a_Text, a_Style, {} }, a_Command } }); } void cCompositeChat::AddSuggestCommandPart(const AString & a_Text, const AString & a_SuggestedCommand, const AString & a_Style) { m_Parts.push_back(SuggestCommandPart{{{ a_Text, a_Style, {} }, a_SuggestedCommand } }); } void cCompositeChat::AddShowAchievementPart(const AString & a_PlayerName, const AString & a_Achievement, const AString & a_Style) { m_Parts.push_back(ShowAchievementPart{{ a_Achievement, a_Style, {} }, a_PlayerName }); } /** * Parse the input message to add colors or link then add it to the object. * * It detects every & of the message and the next character for it to colorize. * It detect : in the text to detect link structures. * * @param a_ParseText The input text to parse */ void cCompositeChat::ParseText(const AString & a_ParseText) { size_t len = a_ParseText.length(); size_t cursor = 0; AString CurrentStyle; AString CurrentText; for (size_t i = 0; i < len; i++) { switch (a_ParseText[i]) { case '&': //< Color code { if ((i != 0) && (a_ParseText[i-1] == '\\')) { CurrentText.append(a_ParseText, cursor, i - cursor - 1).append("&"); AddTextPart(CurrentText, CurrentStyle); CurrentText.clear(); cursor = ++i; continue; } if (cursor < i) { CurrentText.append(a_ParseText, cursor, i - cursor); AddTextPart(CurrentText, CurrentStyle); CurrentText.clear(); } i++; cursor = i + 1; if (a_ParseText[i] == 'r') { CurrentStyle = ""; } else { CurrentStyle.push_back(a_ParseText[i]); } break; } case ':': { static const constexpr std::array LinkPrefixes = { { "http", "https" } }; for (const auto & Prefix : LinkPrefixes) { size_t PrefixLen = Prefix.size(); if ( (i >= cursor + PrefixLen) && // There is enough space in front of the colon for the prefix (std::string_view(a_ParseText).substr(i - PrefixLen, PrefixLen) == Prefix) // the prefix matches ) { // Add everything before this as a text part: if (i > cursor+ PrefixLen) { CurrentText.append(a_ParseText.c_str() + cursor, i - cursor - PrefixLen); cursor= i - PrefixLen; } if (!CurrentText.empty()) { AddTextPart(CurrentText, CurrentStyle); CurrentText.clear(); } // Go till the last non-whitespace char in the text: for (; i < len; i++) { if (isspace(a_ParseText[i])) { break; } } AddUrlPart(a_ParseText.substr(cursor, i - cursor), a_ParseText.substr(cursor, i - cursor), CurrentStyle); cursor = i; break; } } // for Prefix - LinkPrefix[] break; } // case ':' } // switch (a_ParseText[i]) } // for i - a_ParseText[] if (cursor < len) { CurrentText.clear(); CurrentText.append(a_ParseText, cursor, len - cursor); AddTextPart(CurrentText, CurrentStyle); } } void cCompositeChat::SetMessageType(eMessageType a_MessageType, const AString & a_AdditionalMessageTypeData) { m_MessageType = a_MessageType; m_AdditionalMessageTypeData = a_AdditionalMessageTypeData; } void cCompositeChat::UnderlineUrls(void) { for (auto & Part : m_Parts) { std::visit(OverloadedVariantAccess { [](TextPart & a_Part) { }, [](ClientTranslatedPart & a_Part) { }, [](UrlPart & a_Part) { a_Part.Style += 'n'; }, [](RunCommandPart & a_Part) { }, [](SuggestCommandPart & a_Part) { }, [](ShowAchievementPart & a_Part) { }, }, Part); } } AString cCompositeChat::ExtractText(void) const { AString Msg; for (const auto & Part : m_Parts) { std::visit(OverloadedVariantAccess { [&Msg](const TextPart & a_Part) { Msg.append(a_Part.Text); }, [&Msg](const ClientTranslatedPart & a_Part) { Msg.append(a_Part.Text); }, [&Msg](const UrlPart & a_Part) { Msg.append(a_Part.Url); }, [&Msg](const RunCommandPart & a_Part) { Msg.append(a_Part.Text); }, [&Msg](const SuggestCommandPart & a_Part) { Msg.append(a_Part.Text); }, [ ](const ShowAchievementPart & a_Part) { }, }, Part); } return Msg; } eLogLevel cCompositeChat::MessageTypeToLogLevel(eMessageType a_MessageType) { switch (a_MessageType) { case mtCustom: return eLogLevel::Regular; case mtFailure: return eLogLevel::Warning; case mtInformation: return eLogLevel::Info; case mtSuccess: return eLogLevel::Regular; case mtWarning: return eLogLevel::Warning; case mtFatal: return eLogLevel::Error; case mtDeath: return eLogLevel::Regular; case mtPrivateMessage: return eLogLevel::Regular; case mtJoin: return eLogLevel::Regular; case mtLeave: return eLogLevel::Regular; case mtMaxPlusOne: break; } ASSERT(!"Unhandled MessageType"); return eLogLevel::Error; } AString cCompositeChat::CreateJsonString(bool a_ShouldUseChatPrefixes) const { Json::Value Message; Message["text"] = cClientHandle::FormatMessageType(a_ShouldUseChatPrefixes, GetMessageType(), GetAdditionalMessageTypeData()); // The client crashes without this field being present for (const auto & Part : m_Parts) { Json::Value JsonPart; std::visit(OverloadedVariantAccess { [this, &JsonPart](const TextPart & a_Part) { JsonPart["text"] = a_Part.Text; AddChatPartStyle(JsonPart, a_Part.Style); }, [this, &JsonPart](const ClientTranslatedPart & a_Part) { JsonPart["translate"] = a_Part.Text; Json::Value With; for (const auto & Parameter : a_Part.Parameters) { With.append(Parameter); } if (!a_Part.Parameters.empty()) { JsonPart["with"] = With; } AddChatPartStyle(JsonPart, a_Part.Style); }, [this, &JsonPart](const UrlPart & a_Part) { JsonPart["text"] = a_Part.Text; Json::Value Url; Url["action"] = "open_url"; Url["value"] = a_Part.Url; JsonPart["clickEvent"] = Url; AddChatPartStyle(JsonPart, a_Part.Style); }, [this, &JsonPart](const RunCommandPart & a_Part) { JsonPart["text"] = a_Part.Text; Json::Value Cmd; Cmd["action"] = "run_command"; Cmd["value"] = a_Part.Command; JsonPart["clickEvent"] = Cmd; AddChatPartStyle(JsonPart, a_Part.Style); }, [this, &JsonPart](const SuggestCommandPart & a_Part) { JsonPart["text"] = a_Part.Text; Json::Value Cmd; Cmd["action"] = "suggest_command"; Cmd["value"] = a_Part.Command; JsonPart["clickEvent"] = Cmd; AddChatPartStyle(JsonPart, a_Part.Style); }, [this, &JsonPart](const ShowAchievementPart & a_Part) { JsonPart["translate"] = "chat.type.achievement"; Json::Value Ach; Ach["action"] = "show_achievement"; Ach["value"] = a_Part.Text; Json::Value AchColourAndName; AchColourAndName["color"] = "green"; AchColourAndName["translate"] = a_Part.Text; AchColourAndName["hoverEvent"] = Ach; Json::Value Extra; Extra.append(AchColourAndName); Json::Value Name; Name["text"] = a_Part.PlayerName; Json::Value With; With.append(Name); With.append(Extra); JsonPart["with"] = With; AddChatPartStyle(JsonPart, a_Part.Style); }, }, Part); Message["extra"].append(JsonPart); } // for itr - Parts[] #if 1 // Serialize as machine-readable string (no whitespace): return JsonUtils::WriteFastString(Message); #else // Serialize as human-readable string (pretty-printed): return JsonUtils::WriteStyledString(msg); #endif } void cCompositeChat::AddChatPartStyle(Json::Value & a_Value, const AString & a_PartStyle) const { size_t len = a_PartStyle.length(); for (size_t i = 0; i < len; i++) { switch (a_PartStyle[i]) { case 'k': a_Value["obfuscated"] = Json::Value(true); break; case 'l': a_Value["bold"] = Json::Value(true); break; case 's': // Deprecated LOGERROR("Value s in AddChatPartStyle() is deprecated"); case 'm': a_Value["strikethrough"] = Json::Value(true); break; case 'u': // Deprecated LOGERROR("Value u in AddChatPartStyle() is deprecated"); case 'n': a_Value["underlined"] = Json::Value(true); break; case 'i': // Deprecated LOGERROR("Value i in AddChatPartStyle() is deprecated"); case 'o': a_Value["italic"] = Json::Value(true); break; case '0': a_Value["color"] = Json::Value("black"); break; case '1': a_Value["color"] = Json::Value("dark_blue"); break; case '2': a_Value["color"] = Json::Value("dark_green"); break; case '3': a_Value["color"] = Json::Value("dark_aqua"); break; case '4': a_Value["color"] = Json::Value("dark_red"); break; case '5': a_Value["color"] = Json::Value("dark_purple"); break; case '6': a_Value["color"] = Json::Value("gold"); break; case '7': a_Value["color"] = Json::Value("gray"); break; case '8': a_Value["color"] = Json::Value("dark_gray"); break; case '9': a_Value["color"] = Json::Value("blue"); break; case 'a': a_Value["color"] = Json::Value("green"); break; case 'b': a_Value["color"] = Json::Value("aqua"); break; case 'c': a_Value["color"] = Json::Value("red"); break; case 'd': a_Value["color"] = Json::Value("light_purple"); break; case 'e': a_Value["color"] = Json::Value("yellow"); break; case 'f': a_Value["color"] = Json::Value("white"); break; } // switch (Style[i]) } // for i - a_PartStyle[] } ================================================ FILE: src/CompositeChat.h ================================================ // CompositeChat.h // Declares the cCompositeChat class used to wrap a chat message with multiple parts (text, url, cmd) #pragma once #include "Defines.h" #include "json/json.h" // tolua_begin /** Container for a single chat message composed of multiple functional parts. Each part corresponds roughly to the behavior supported by the client messaging: - plain text, optionaly colorized / styled - clickable URLs - clickable commands (run) - clickable commands (suggest) Each part has a text assigned to it that can be styled. The style is specified using a string, each character / character combination in the string specifies the style to use: - (char from 0 - 9 or a - f) = color X - k = obfuscated - l = bold - m = strikethrough - n = underlined - o = italic - r = reset If the protocol version doesn't support all the features, it degrades gracefully. */ class cCompositeChat { public: // tolua_end struct BasePart { AString Text; AString Style; AString AdditionalStyleData; } ; struct TextPart: public BasePart { } ; struct ClientTranslatedPart: public BasePart { AStringVector Parameters; } ; struct UrlPart: public BasePart { AString Url; } ; struct CommandPart: public BasePart { AString Command; } ; struct RunCommandPart: public CommandPart { } ; struct SuggestCommandPart: public CommandPart { } ; struct ShowAchievementPart: public BasePart { AString PlayerName; } ; /** Creates a new empty chat message. Exported manually due to the other overload needing a manual export. */ cCompositeChat(void); /** Creates a new chat message and parses the text into parts. Recognizes "http:" and "https:" links and &format-character. Uses ParseText() for the actual parsing. Exported manually due to ToLua++ generating extra output parameter. */ cCompositeChat(const AString & a_ParseText, eMessageType a_MessageType = mtCustom); // The following are exported in ManualBindings in order to support chaining - they return "self" in Lua (#755) /** Removes all parts from the object. */ void Clear(void); /** Adds a plain text part, with optional style. The default style is plain white text. */ void AddTextPart(const AString & a_Message, const AString & a_Style = ""); /** Adds a part that is translated client-side, with the formatting parameters and optional style. */ void AddClientTranslatedPart(const AString & a_TranslationID, const AStringVector & a_Parameters, const AString & a_Style = ""); /** Adds a part that opens an URL when clicked. The default style is underlined light blue text. */ void AddUrlPart(const AString & a_Text, const AString & a_Url, const AString & a_Style = "nc"); /** Adds a part that runs a command when clicked. The default style is underlined light green text. */ void AddRunCommandPart(const AString & a_Text, const AString & a_Command, const AString & a_Style = "na"); /** Adds a part that suggests a command (enters it into the chat message area, but doesn't send) when clicked. The default style is underlined yellow text. */ void AddSuggestCommandPart(const AString & a_Text, const AString & a_SuggestedCommand, const AString & a_Style = "nb"); /** Adds a part that fully formats a specified achievement using client translatable strings Takes achievement name and player awarded to. Displays as {player} has earned the achievement {achievement_name}. */ void AddShowAchievementPart(const AString & a_PlayerName, const AString & a_Achievement, const AString & a_Style = ""); /** Parses text into various parts, adds those. Recognizes "http:" and "https:" URLs and &color-codes. */ void ParseText(const AString & a_ParseText); /** Adds the "underline" style to each part that is an URL. */ void UnderlineUrls(void); /** Sets the message type, which is indicated by prefixes added to the message when serializing Takes optional AdditionalMessageTypeData to set m_AdditionalMessageTypeData. See said variable for more documentation. Exported manually, because ToLua++ would generate extra return values. */ void SetMessageType(eMessageType a_MessageType, const AString & a_AdditionalMessageTypeData = ""); // tolua_begin /** Returns the message type set previously by SetMessageType(). */ eMessageType GetMessageType(void) const { return m_MessageType; } /** Returns additional data pertaining to message type, for example, the name of a mtPrivateMsg sender */ AString GetAdditionalMessageTypeData(void) const { return m_AdditionalMessageTypeData; } /** Returns the text from the parts that comprises the human-readable data. Used for older protocols that don't support composite chat and for console-logging. */ AString ExtractText(void) const; AString CreateJsonString(bool a_ShouldUseChatPrefixes = true) const; // tolua_end const auto & GetParts(void) const { return m_Parts; } /** Converts the MessageType to a LogLevel value. Used by the logging bindings when logging a cCompositeChat object. */ static eLogLevel MessageTypeToLogLevel(eMessageType a_MessageType); /** Adds the chat part's style (represented by the part's stylestring) into the Json object. */ void AddChatPartStyle(Json::Value & a_Value, const AString & a_PartStyle) const; protected: /** All the parts that */ std::vector> m_Parts; /** The message type, as indicated by prefixes. */ eMessageType m_MessageType; /** Additional data pertaining to message type, for example, the name of a mtPrivateMsg sender */ AString m_AdditionalMessageTypeData; } ; // tolua_export ================================================ FILE: src/CraftingRecipes.cpp ================================================ // CraftingRecipes.cpp // Interfaces to the cCraftingRecipes class representing the storage of crafting recipes #include "Globals.h" #include "CraftingRecipes.h" #include "Root.h" #include "Bindings/PluginManager.h" //////////////////////////////////////////////////////////////////////////////// // cCraftingGrid: cCraftingGrid::cCraftingGrid(int a_Width, int a_Height) : m_Width(a_Width), m_Height(a_Height), m_Items(new cItem[ToUnsigned(a_Width * a_Height)]) { } cCraftingGrid::cCraftingGrid(const cItem * a_Items, int a_Width, int a_Height) : cCraftingGrid(a_Width, a_Height) { for (int i = a_Width * a_Height - 1; i >= 0; i--) { m_Items[i] = a_Items[i]; } } cCraftingGrid::cCraftingGrid(const cCraftingGrid & a_Original) : cCraftingGrid(a_Original.m_Width, a_Original.m_Height) { for (int i = m_Width * m_Height - 1; i >= 0; i--) { m_Items[i] = a_Original.m_Items[i]; } } cCraftingGrid::~cCraftingGrid() { delete[] m_Items; m_Items = nullptr; } cItem & cCraftingGrid::GetItem(int x, int y) const { // Accessible through scripting, must verify parameters: if ((x < 0) || (x >= m_Width) || (y < 0) || (y >= m_Height)) { LOGERROR("Attempted to get an invalid item from a crafting grid: (%d, %d), grid dimensions: (%d, %d).", x, y, m_Width, m_Height ); return m_Items[0]; } return m_Items[x + m_Width * y]; } void cCraftingGrid::SetItem(int x, int y, ENUM_ITEM_TYPE a_ItemType, char a_ItemCount, short a_ItemHealth) { // Accessible through scripting, must verify parameters: if ((x < 0) || (x >= m_Width) || (y < 0) || (y >= m_Height)) { LOGERROR("Attempted to set an invalid item in a crafting grid: (%d, %d), grid dimensions: (%d, %d).", x, y, m_Width, m_Height ); return; } m_Items[x + m_Width * y] = cItem(a_ItemType, a_ItemCount, a_ItemHealth); } void cCraftingGrid::SetItem(int x, int y, const cItem & a_Item) { // Accessible through scripting, must verify parameters: if ((x < 0) || (x >= m_Width) || (y < 0) || (y >= m_Height)) { LOGERROR("Attempted to set an invalid item in a crafting grid: (%d, %d), grid dimensions: (%d, %d).", x, y, m_Width, m_Height ); return; } m_Items[x + m_Width * y] = a_Item; } void cCraftingGrid::Clear(void) { for (int y = 0; y < m_Height; y++) for (int x = 0; x < m_Width; x++) { m_Items[x + m_Width * y].Empty(); } } void cCraftingGrid::ConsumeGrid(const cCraftingGrid & a_Grid) { if ((a_Grid.m_Width != m_Width) || (a_Grid.m_Height != m_Height)) { LOGWARNING("Consuming a grid of different dimensions: (%d, %d) vs (%d, %d)", a_Grid.m_Width, a_Grid.m_Height, m_Width, m_Height ); } int MinX = std::min(a_Grid.m_Width, m_Width); int MinY = std::min(a_Grid.m_Height, m_Height); for (int y = 0; y < MinY; y++) for (int x = 0; x < MinX; x++) { int ThatIdx = x + a_Grid.m_Width * y; if (a_Grid.m_Items[ThatIdx].IsEmpty()) { continue; } int ThisIdx = x + m_Width * y; if (a_Grid.m_Items[ThatIdx].m_ItemType != m_Items[ThisIdx].m_ItemType) { LOGWARNING("Consuming incompatible grids: item at (%d, %d) is %d in grid and %d in ingredients. Item not consumed.", x, y, m_Items[ThisIdx].m_ItemType, a_Grid.m_Items[ThatIdx].m_ItemType ); continue; } char NumWantedItems = a_Grid.m_Items[ThatIdx].m_ItemCount; if (NumWantedItems > m_Items[ThisIdx].m_ItemCount) { LOGWARNING("Consuming more items than there actually are in slot (%d, %d), item %d (want %d, have %d). Item zeroed out.", x, y, m_Items[ThisIdx].m_ItemType, NumWantedItems, m_Items[ThisIdx].m_ItemCount ); NumWantedItems = m_Items[ThisIdx].m_ItemCount; } m_Items[ThisIdx].m_ItemCount -= NumWantedItems; if (m_Items[ThisIdx].m_ItemCount == 0) { if ((m_Items[ThisIdx].m_ItemType == E_ITEM_MILK) || (m_Items[ThisIdx].m_ItemType == E_ITEM_WATER_BUCKET) || (m_Items[ThisIdx].m_ItemType == E_ITEM_LAVA_BUCKET)) { m_Items[ThisIdx] = cItem(E_ITEM_BUCKET); } else { m_Items[ThisIdx].Clear(); } } } // for x, for y } void cCraftingGrid::CopyToItems(cItem * a_Items) const { for (int i = m_Height * m_Width - 1; i >= 0; i--) { a_Items[i] = m_Items[i]; } // for x, for y } void cCraftingGrid::Dump(void) { for (int y = 0; y < m_Height; y++) for (int x = 0; x < m_Width; x++) { [[maybe_unused]] const int idx = x + m_Width * y; LOGD("Slot (%d, %d): Type %d, health %d, count %d", x, y, m_Items[idx].m_ItemType, m_Items[idx].m_ItemDamage, m_Items[idx].m_ItemCount ); } } //////////////////////////////////////////////////////////////////////////////// // cCraftingRecipe: cCraftingRecipe::cCraftingRecipe(const cCraftingGrid & a_CraftingGrid) : m_Ingredients(a_CraftingGrid) { } void cCraftingRecipe::Clear(void) { m_Ingredients.Clear(); m_Result.Clear(); } void cCraftingRecipe::SetResult(ENUM_ITEM_TYPE a_ItemType, char a_ItemCount, short a_ItemHealth) { m_Result = cItem(a_ItemType, a_ItemCount, a_ItemHealth); } void cCraftingRecipe::ConsumeIngredients(cCraftingGrid & a_CraftingGrid) { a_CraftingGrid.ConsumeGrid(m_Ingredients); } void cCraftingRecipe::Dump(void) { LOGD("Recipe ingredients:"); m_Ingredients.Dump(); LOGD("Result: Type %d, health %d, count %d", m_Result.m_ItemType, m_Result.m_ItemDamage, m_Result.m_ItemCount ); } //////////////////////////////////////////////////////////////////////////////// // cCraftingRecipes: cCraftingRecipes::cCraftingRecipes(void) { LoadRecipes(); PopulateRecipeNameMap(); } cCraftingRecipes::~cCraftingRecipes() { ClearRecipes(); } bool cCraftingRecipes::IsNewCraftableRecipe(const cRecipe * a_Recipe, const cItem & a_Item, const std::set & a_KnownItems) { bool ContainsNewItem = false; for (const auto & Ingredient : a_Recipe->m_Ingredients) { if ( (Ingredient.m_Item.m_ItemType == a_Item.m_ItemType) && ( (Ingredient.m_Item.m_ItemDamage == a_Item.m_ItemDamage) || (Ingredient.m_Item.m_ItemDamage == -1) ) ) { ContainsNewItem = true; } if (a_KnownItems.find(Ingredient.m_Item) == a_KnownItems.end()) { return false; } } return ContainsNewItem; } std::vector cCraftingRecipes::FindNewRecipesForItem(const cItem & a_Item, const std::set & a_KnownItems) { std::vector Recipes; for (UInt32 i = 0; i < m_Recipes.size(); i++) { if (m_Recipes[i]->m_RecipeName.empty()) { continue; } if (IsNewCraftableRecipe(m_Recipes[i], a_Item, a_KnownItems)) { Recipes.push_back(i); } } return Recipes; } const std::map & cCraftingRecipes::GetRecipeNameMap() { return m_RecipeNameMap; } cCraftingRecipes::cRecipe * cCraftingRecipes::GetRecipeById(UInt32 a_RecipeId) { return m_Recipes[a_RecipeId]; } void cCraftingRecipes::GetRecipe(cPlayer & a_Player, cCraftingGrid & a_CraftingGrid, cCraftingRecipe & a_Recipe) { // Allow plugins to intercept recipes using a pre-craft hook: if (cRoot::Get()->GetPluginManager()->CallHookPreCrafting(a_Player, a_CraftingGrid, a_Recipe)) { return; } // Built-in recipes: std::unique_ptr Recipe(FindRecipe(a_CraftingGrid.GetItems(), a_CraftingGrid.GetWidth(), a_CraftingGrid.GetHeight())); a_Recipe.Clear(); if (Recipe.get() == nullptr) { // Allow plugins to intercept a no-recipe-found situation: cRoot::Get()->GetPluginManager()->CallHookCraftingNoRecipe(a_Player, a_CraftingGrid, a_Recipe); return; } for (cRecipeSlots::const_iterator itr = Recipe->m_Ingredients.begin(); itr != Recipe->m_Ingredients.end(); ++itr) { a_Recipe.SetIngredient(itr->x, itr->y, itr->m_Item); } // for itr a_Recipe.SetResult(Recipe->m_Result); // Allow plugins to intercept recipes after they are processed: cRoot::Get()->GetPluginManager()->CallHookPostCrafting(a_Player, a_CraftingGrid, a_Recipe); } void cCraftingRecipes::LoadRecipes(void) { LOGD("Loading crafting recipes from crafting.txt..."); ClearRecipes(); // Load the crafting.txt file: cFile f; if (!f.Open("crafting.txt", cFile::fmRead)) { LOGWARNING("Cannot open file \"crafting.txt\", no crafting recipes will be available!"); return; } AString Everything; if (!f.ReadRestOfFile(Everything)) { LOGWARNING("Cannot read file \"crafting.txt\", no crafting recipes will be available!"); return; } f.Close(); // Split it into lines, then process each line as a single recipe: AStringVector Split = StringSplit(Everything, "\n"); int LineNum = 1; for (AStringVector::const_iterator itr = Split.begin(); itr != Split.end(); ++itr, ++LineNum) { // Remove anything after a '#' sign and trim away the whitespace: AString Recipe = TrimString(itr->substr(0, itr->find('#'))); if (Recipe.empty()) { // Empty recipe continue; } AddRecipeLine(LineNum, Recipe); } // for itr - Split[] LOG("Loaded %zu crafting recipes", m_Recipes.size()); } void cCraftingRecipes::PopulateRecipeNameMap(void) { for (UInt32 i = 0; i < m_Recipes.size(); i++) { if (!m_Recipes[i]->m_RecipeName.empty()) { m_RecipeNameMap.emplace(m_Recipes[i]->m_RecipeName, i); } } } void cCraftingRecipes::ClearRecipes(void) { for (cRecipes::iterator itr = m_Recipes.begin(); itr != m_Recipes.end(); ++itr) { delete *itr; } m_Recipes.clear(); } void cCraftingRecipes::AddRecipeLine(int a_LineNum, const AString & a_RecipeLine) { // Remove any spaces within the line: AString RecipeLine(a_RecipeLine); RecipeLine.erase(std::remove_if(RecipeLine.begin(), RecipeLine.end(), isspace), RecipeLine.end()); AStringVector Sides = StringSplit(RecipeLine, "="); if (Sides.size() != 2) { LOGWARNING("crafting.txt: line %d: A single '=' was expected, got %zu", a_LineNum, Sides.size() - 1); LOGINFO("Offending line: \"%s\"", a_RecipeLine.c_str()); return; } std::unique_ptr Recipe = std::make_unique(); AStringVector RecipeSplit = StringSplit(Sides[0], ":"); const auto * resultPart = &RecipeSplit[0]; if (RecipeSplit.size() > 1) { resultPart = &RecipeSplit[1]; Recipe->m_RecipeName = RecipeSplit[0]; } // Parse the result: AStringVector ResultSplit = StringSplit(*resultPart, ","); if (ResultSplit.empty()) { LOGWARNING("crafting.txt: line %d: Result is empty, ignoring the recipe.", a_LineNum); LOGINFO("Offending line: \"%s\"", a_RecipeLine.c_str()); return; } if (!ParseItem(ResultSplit[0], Recipe->m_Result)) { LOGWARNING("crafting.txt: line %d: Cannot parse result item, ignoring the recipe.", a_LineNum); LOGINFO("Offending line: \"%s\"", a_RecipeLine.c_str()); return; } if (ResultSplit.size() > 1) { if (!StringToInteger(ResultSplit[1], Recipe->m_Result.m_ItemCount)) { LOGWARNING("crafting.txt: line %d: Cannot parse result count, ignoring the recipe.", a_LineNum); LOGINFO("Offending line: \"%s\"", a_RecipeLine.c_str()); return; } } else { Recipe->m_Result.m_ItemCount = 1; } // Parse each ingredient: AStringVector Ingredients = StringSplit(Sides[1], "|"); int Num = 1; for (AStringVector::const_iterator itr = Ingredients.begin(); itr != Ingredients.end(); ++itr, ++Num) { if (!ParseIngredient(*itr, Recipe.get())) { LOGWARNING("crafting.txt: line %d: Cannot parse ingredient #%d, ignoring the recipe.", a_LineNum, Num); LOGINFO("Offending line: \"%s\"", a_RecipeLine.c_str()); return; } } // for itr - Ingredients[] NormalizeIngredients(Recipe.get()); m_Recipes.push_back(Recipe.release()); } bool cCraftingRecipes::ParseItem(const AString & a_String, cItem & a_Item) { // The caller provides error logging AStringVector Split = StringSplit(a_String, "^"); if (Split.empty()) { return false; } if (!StringToItem(Split[0], a_Item)) { return false; } if (Split.size() > 1) { AString Damage = TrimString(Split[1]); if (!StringToInteger(Damage, a_Item.m_ItemDamage)) { // Parsing the number failed return false; } } // Success return true; } bool cCraftingRecipes::ParseIngredient(const AString & a_String, cRecipe * a_Recipe) { // a_String is in this format: "ItemType^damage, X:Y, X:Y, X:Y..." AStringVector Split = StringSplit(a_String, ","); if (Split.size() < 2) { // Not enough split items return false; } cItem Item; if (!ParseItem(Split[0], Item)) { return false; } Item.m_ItemCount = 1; cCraftingRecipes::cRecipeSlots TempSlots; for (AStringVector::const_iterator itr = Split.begin() + 1; itr != Split.end(); ++itr) { // Parse the coords in the split item: AStringVector Coords = StringSplit(*itr, ":"); if ((Coords.size() == 1) && (TrimString(Coords[0]) == "*")) { cCraftingRecipes::cRecipeSlot Slot; Slot.m_Item = Item; Slot.x = -1; Slot.y = -1; TempSlots.push_back(Slot); continue; } if (Coords.size() != 2) { return false; } Coords[0] = TrimString(Coords[0]); Coords[1] = TrimString(Coords[1]); if (Coords[0].empty() || Coords[1].empty()) { return false; } cCraftingRecipes::cRecipeSlot Slot; Slot.m_Item = Item; switch (Coords[0][0]) { case '1': Slot.x = 0; break; case '2': Slot.x = 1; break; case '3': Slot.x = 2; break; case '*': Slot.x = -1; break; default: { return false; } } switch (Coords[1][0]) { case '1': Slot.y = 0; break; case '2': Slot.y = 1; break; case '3': Slot.y = 2; break; case '*': Slot.y = -1; break; default: { return false; } } TempSlots.push_back(Slot); } // for itr - Split[] // Append the ingredients: a_Recipe->m_Ingredients.insert(a_Recipe->m_Ingredients.end(), TempSlots.begin(), TempSlots.end()); return true; } void cCraftingRecipes::NormalizeIngredients(cCraftingRecipes::cRecipe * a_Recipe) { // Calculate the minimum coords for ingredients, excluding the "anywhere" items: int MinX = MAX_GRID_WIDTH, MaxX = 0; int MinY = MAX_GRID_HEIGHT, MaxY = 0; for (cRecipeSlots::const_iterator itr = a_Recipe->m_Ingredients.begin(); itr != a_Recipe->m_Ingredients.end(); ++itr) { if (itr->x >= 0) { MinX = std::min(itr->x, MinX); MaxX = std::max(itr->x, MaxX); } if (itr->y >= 0) { MinY = std::min(itr->y, MinY); MaxY = std::max(itr->y, MaxY); } } // for itr - a_Recipe->m_Ingredients[] // Move ingredients so that the minimum coords are 0:0 for (cRecipeSlots::iterator itr = a_Recipe->m_Ingredients.begin(); itr != a_Recipe->m_Ingredients.end(); ++itr) { if (itr->x >= 0) { itr->x -= MinX; } if (itr->y >= 0) { itr->y -= MinY; } } // for itr - a_Recipe->m_Ingredients[] a_Recipe->m_Width = std::max(MaxX - MinX + 1, 1); a_Recipe->m_Height = std::max(MaxY - MinY + 1, 1); // TODO: Compress two same ingredients with the same coords into a single ingredient with increased item count } cCraftingRecipes::cRecipe * cCraftingRecipes::FindRecipe(const cItem * a_CraftingGrid, int a_GridWidth, int a_GridHeight) { ASSERT(a_GridWidth <= MAX_GRID_WIDTH); ASSERT(a_GridHeight <= MAX_GRID_HEIGHT); // Get the real bounds of the crafting grid: int GridLeft = MAX_GRID_WIDTH, GridTop = MAX_GRID_HEIGHT; int GridRight = 0, GridBottom = 0; for (int y = 0; y < a_GridHeight; y++) for (int x = 0; x < a_GridWidth; x++) { if (!a_CraftingGrid[x + y * a_GridWidth].IsEmpty()) { GridRight = std::max(x, GridRight); GridBottom = std::max(y, GridBottom); GridLeft = std::min(x, GridLeft); GridTop = std::min(y, GridTop); } } int GridWidth = GridRight - GridLeft + 1; int GridHeight = GridBottom - GridTop + 1; // Search in the possibly minimized grid, but keep the stride: const cItem * Grid = a_CraftingGrid + GridLeft + (a_GridWidth * GridTop); cRecipe * Recipe = FindRecipeCropped(Grid, GridWidth, GridHeight, a_GridWidth); if (Recipe == nullptr) { return nullptr; } // A recipe has been found, move it to correspond to the original crafting grid: for (cRecipeSlots::iterator itrS = Recipe->m_Ingredients.begin(); itrS != Recipe->m_Ingredients.end(); ++itrS) { itrS->x += GridLeft; itrS->y += GridTop; } // for itrS - Recipe->m_Ingredients[] return Recipe; } cCraftingRecipes::cRecipe * cCraftingRecipes::FindRecipeCropped(const cItem * a_CraftingGrid, int a_GridWidth, int a_GridHeight, int a_GridStride) { for (cRecipes::const_iterator itr = m_Recipes.begin(); itr != m_Recipes.end(); ++itr) { // Both the crafting grid and the recipes are normalized. The only variable possible is the "anywhere" items. // This still means that the "anywhere" item may be the one that is offsetting the grid contents to the right or downwards, so we need to check all possible positions. // E. g. recipe "A, * | B, 1:1 | ..." still needs to check grid for B at 2:2 (in case A was in grid's 1:1) // Calculate the maximum offsets for this recipe relative to the grid size, and iterate through all combinations of offsets. // Also, this calculation automatically filters out recipes that are too large for the current grid - the loop won't be entered at all. int MaxOfsX = a_GridWidth - (*itr)->m_Width; int MaxOfsY = a_GridHeight - (*itr)->m_Height; for (int x = 0; x <= MaxOfsX; x++) for (int y = 0; y <= MaxOfsY; y++) { cRecipe * Recipe = MatchRecipe(a_CraftingGrid, a_GridWidth, a_GridHeight, a_GridStride, *itr, x, y); if (Recipe != nullptr) { return Recipe; } } // for y, for x } // for itr - m_Recipes[] // No matching recipe found return nullptr; } cCraftingRecipes::cRecipe * cCraftingRecipes::MatchRecipe(const cItem * a_CraftingGrid, int a_GridWidth, int a_GridHeight, int a_GridStride, const cRecipe * a_Recipe, int a_OffsetX, int a_OffsetY) { // Check the regular items first: bool HasMatched[MAX_GRID_WIDTH][MAX_GRID_HEIGHT]; memset(HasMatched, 0, sizeof(HasMatched)); for (cRecipeSlots::const_iterator itrS = a_Recipe->m_Ingredients.begin(); itrS != a_Recipe->m_Ingredients.end(); ++itrS) { if ((itrS->x < 0) || (itrS->y < 0)) { // "Anywhere" item, process later continue; } ASSERT(itrS->x + a_OffsetX < a_GridWidth); ASSERT(itrS->y + a_OffsetY < a_GridHeight); int GridID = (itrS->x + a_OffsetX) + a_GridStride * (itrS->y + a_OffsetY); const cItem & Item = itrS->m_Item; if ( (itrS->x >= a_GridWidth) || (itrS->y >= a_GridHeight) || (Item.m_ItemType != a_CraftingGrid[GridID].m_ItemType) || // same item type? (Item.m_ItemCount > a_CraftingGrid[GridID].m_ItemCount) || // not enough items ( (Item.m_ItemDamage >= 0) && // should compare damage values? (Item.m_ItemDamage != a_CraftingGrid[GridID].m_ItemDamage) ) ) { // Doesn't match return nullptr; } HasMatched[itrS->x + a_OffsetX][itrS->y + a_OffsetY] = true; } // for itrS - Recipe->m_Ingredients[] // Process the "Anywhere" items now, and only in the cells that haven't matched yet // The "anywhere" items are processed on a first-come-first-served basis. // Do not use a recipe with one horizontal and one vertical "anywhere" ("*:1, 1:*") as it may not match properly! cRecipeSlots MatchedSlots; // Stores the slots of "anywhere" items that have matched, with the match coords for (cRecipeSlots::const_iterator itrS = a_Recipe->m_Ingredients.begin(); itrS != a_Recipe->m_Ingredients.end(); ++itrS) { if ((itrS->x >= 0) && (itrS->y >= 0)) { // Regular item, already processed continue; } int StartX = 0, EndX = a_GridWidth - 1; int StartY = 0, EndY = a_GridHeight - 1; if (itrS->x >= 0) { StartX = itrS->x; EndX = itrS->x; } else if (itrS->y >= 0) { StartY = itrS->y; EndY = itrS->y; } bool Found = false; for (int x = StartX; x <= EndX; x++) { for (int y = StartY; y <= EndY; y++) { if (HasMatched[x][y]) { // Already matched some other item continue; } int GridIdx = x + a_GridStride * y; if ( (a_CraftingGrid[GridIdx].m_ItemType == itrS->m_Item.m_ItemType) && ( (itrS->m_Item.m_ItemDamage < 0) || // doesn't want damage comparison (itrS->m_Item.m_ItemDamage == a_CraftingGrid[GridIdx].m_ItemDamage) // the damage matches ) ) { HasMatched[x][y] = true; Found = true; MatchedSlots.push_back(*itrS); MatchedSlots.back().x = x; MatchedSlots.back().y = y; break; } } // for y if (Found) { break; } } // for x if (!Found) { return nullptr; } } // for itrS - a_Recipe->m_Ingredients[] // Check if the whole grid has matched: for (int x = 0; x < a_GridWidth; x++) for (int y = 0; y < a_GridHeight; y++) { if (!HasMatched[x][y] && !a_CraftingGrid[x + a_GridStride * y].IsEmpty()) { // There's an unmatched item in the grid return nullptr; } } // for y, for x // The recipe has matched. Create a copy of the recipe and set its coords to match the crafting grid: std::unique_ptr Recipe = std::make_unique(); Recipe->m_Result = a_Recipe->m_Result; Recipe->m_Width = a_Recipe->m_Width; Recipe->m_Height = a_Recipe->m_Height; for (cRecipeSlots::const_iterator itrS = a_Recipe->m_Ingredients.begin(); itrS != a_Recipe->m_Ingredients.end(); ++itrS) { if ((itrS->x < 0) || (itrS->y < 0)) { // "Anywhere" item, process later continue; } Recipe->m_Ingredients.push_back(*itrS); Recipe->m_Ingredients.back().x += a_OffsetX; Recipe->m_Ingredients.back().y += a_OffsetY; } Recipe->m_Ingredients.insert(Recipe->m_Ingredients.end(), MatchedSlots.begin(), MatchedSlots.end()); // Handle the fireworks-related effects: // We use Recipe instead of a_Recipe because we want the wildcard ingredients' slot numbers as well, which was just added previously HandleFireworks(a_CraftingGrid, Recipe.get(), a_GridStride, a_OffsetX, a_OffsetY); // Handle Dyed Leather HandleDyedLeather(a_CraftingGrid, Recipe.get(), a_GridStride, a_GridWidth, a_GridHeight); return Recipe.release(); } void cCraftingRecipes::HandleFireworks(const cItem * a_CraftingGrid, cCraftingRecipes::cRecipe * a_Recipe, int a_GridStride, int a_OffsetX, int a_OffsetY) { // TODO: add support for more than one dye in the recipe // A manual and temporary solution (listing everything) is in crafting.txt for fade colours, but a programmatic solutions needs to be done for everything else if (a_Recipe->m_Result.m_ItemType == E_ITEM_FIREWORK_ROCKET) { for (cRecipeSlots::const_iterator itr = a_Recipe->m_Ingredients.begin(); itr != a_Recipe->m_Ingredients.end(); ++itr) { switch (itr->m_Item.m_ItemType) { case E_ITEM_FIREWORK_STAR: { // Result was a rocket, found a star - copy star data to rocket data int GridID = (itr->x + a_OffsetX) + a_GridStride * (itr->y + a_OffsetY); a_Recipe->m_Result.m_FireworkItem.CopyFrom(a_CraftingGrid[GridID].m_FireworkItem); break; } case E_ITEM_GUNPOWDER: { // Gunpowder - increase flight time a_Recipe->m_Result.m_FireworkItem.m_FlightTimeInTicks += 20; break; } case E_ITEM_PAPER: break; default: LOG("Unexpected item in firework rocket recipe, was the crafting file's fireworks section changed?"); break; } } } else if (a_Recipe->m_Result.m_ItemType == E_ITEM_FIREWORK_STAR) { std::vector DyeColours; bool FoundStar = false; for (cRecipeSlots::const_iterator itr = a_Recipe->m_Ingredients.begin(); itr != a_Recipe->m_Ingredients.end(); ++itr) { switch (itr->m_Item.m_ItemType) { case E_ITEM_FIREWORK_STAR: { // Result was star, found another star - probably adding fade colours, but copy data over anyhow FoundStar = true; int GridID = (itr->x + a_OffsetX) + a_GridStride * (itr->y + a_OffsetY); a_Recipe->m_Result.m_FireworkItem.CopyFrom(a_CraftingGrid[GridID].m_FireworkItem); break; } case E_ITEM_DYE: { int GridID = (itr->x + a_OffsetX) + a_GridStride * (itr->y + a_OffsetY); DyeColours.push_back(cFireworkItem::GetVanillaColourCodeFromDye(static_cast(a_CraftingGrid[GridID].m_ItemDamage & 0x0f))); break; } case E_ITEM_GUNPOWDER: break; case E_ITEM_DIAMOND: a_Recipe->m_Result.m_FireworkItem.m_HasTrail = true; break; case E_ITEM_GLOWSTONE_DUST: a_Recipe->m_Result.m_FireworkItem.m_HasFlicker = true; break; case E_ITEM_FIRE_CHARGE: a_Recipe->m_Result.m_FireworkItem.m_Type = 1; break; case E_ITEM_GOLD_NUGGET: a_Recipe->m_Result.m_FireworkItem.m_Type = 2; break; case E_ITEM_FEATHER: a_Recipe->m_Result.m_FireworkItem.m_Type = 4; break; case E_ITEM_HEAD: a_Recipe->m_Result.m_FireworkItem.m_Type = 3; break; default: LOG("Unexpected item in firework star recipe, was the crafting file's fireworks section changed?"); break; // ermahgerd BARD ardmins } } if (FoundStar && (!DyeColours.empty())) { // Found a star and a dye? Fade colours. a_Recipe->m_Result.m_FireworkItem.m_FadeColours = DyeColours; } else if (!DyeColours.empty()) { // Only dye? Normal colours. a_Recipe->m_Result.m_FireworkItem.m_Colours = DyeColours; } } } void cCraftingRecipes::HandleDyedLeather(const cItem * a_CraftingGrid, cCraftingRecipes::cRecipe * a_Recipe, int a_GridStride, int a_GridWidth, int a_GridHeight) { short result_type = a_Recipe->m_Result.m_ItemType; if ((result_type == E_ITEM_LEATHER_CAP) || (result_type == E_ITEM_LEATHER_TUNIC) || (result_type == E_ITEM_LEATHER_PANTS) || (result_type == E_ITEM_LEATHER_BOOTS)) { bool found = false; cItem temp; float red = 0; float green = 0; float blue = 0; float dye_count = 0; for (int x = 0; x < a_GridWidth; ++x) { for (int y = 0; y < a_GridHeight; ++y) { int GridIdx = x + a_GridStride * y; if ((a_CraftingGrid[GridIdx].m_ItemType == result_type) && !found) { found = true; temp = a_CraftingGrid[GridIdx].CopyOne(); // The original color of the item affects the result if (temp.m_ItemColor.IsValid()) { red += temp.m_ItemColor.GetRed(); green += temp.m_ItemColor.GetGreen(); blue += temp.m_ItemColor.GetBlue(); ++dye_count; } } else if (a_CraftingGrid[GridIdx].m_ItemType == E_ITEM_DYE) { switch (a_CraftingGrid[GridIdx].m_ItemDamage) { case E_META_DYE_BLACK: { red += 23; green += 23; blue += 23; break; } case E_META_DYE_RED: { red += 142; green += 47; blue += 47; break; } case E_META_DYE_GREEN: { red += 95; green += 118; blue += 47; break; } case E_META_DYE_BROWN: { red += 95; green += 71; blue += 47; break; } case E_META_DYE_BLUE: { red += 47; green += 71; blue += 165; break; } case E_META_DYE_PURPLE: { red += 118; green += 59; blue += 165; break; } case E_META_DYE_CYAN: { red += 71; green += 118; blue += 142; break; } case E_META_DYE_LIGHTGRAY: { red += 142; green += 142; blue += 142; break; } case E_META_DYE_GRAY: { red += 71; green += 71; blue += 71; break; } case E_META_DYE_PINK: { red += 225; green += 118; blue += 153; break; } case E_META_DYE_LIGHTGREEN: { red += 118; green += 190; blue += 23; break; } case E_META_DYE_YELLOW: { red += 213; green += 213; blue += 47; break; } case E_META_DYE_LIGHTBLUE: { red += 95; green += 142; blue += 201; break; } case E_META_DYE_MAGENTA: { red += 165; green += 71; blue += 201; break; } case E_META_DYE_ORANGE: { red += 201; green += 118; blue += 47; break; } case E_META_DYE_WHITE: { red += 237; green += 237; blue += 237; break; } } ++dye_count; } else if (a_CraftingGrid[GridIdx].m_ItemType != E_ITEM_EMPTY) { return; } } } if (!found) { return; } // Calculate the rgb values double maximum = static_cast(std::max({red, green, blue})); double average_red = red / dye_count; double average_green = green / dye_count; double average_blue = blue / dye_count; double average_max = maximum / dye_count; double max_average = std::max({average_red, average_green, average_blue}); double gain_factor = average_max / max_average; unsigned char result_red = static_cast(average_red * gain_factor); unsigned char result_green = static_cast(average_green * gain_factor); unsigned char result_blue = static_cast(average_blue * gain_factor); // Set the results values a_Recipe->m_Result = temp; a_Recipe->m_Result.m_ItemColor.SetColor(result_red, result_green, result_blue); } } ================================================ FILE: src/CraftingRecipes.h ================================================ // CraftingRecipes.h // Interfaces to the cCraftingRecipes class representing the storage of crafting recipes #pragma once #include "Item.h" // fwd: cPlayer.h class cPlayer; class cCraftingGrid // tolua_export { // tolua_export public: cCraftingGrid(const cCraftingGrid & a_Original); cCraftingGrid(int a_Width, int a_Height); // tolua_export cCraftingGrid(const cItem * a_Items, int a_Width, int a_Height); ~cCraftingGrid(); // tolua_begin int GetWidth (void) const {return m_Width; } int GetHeight(void) const {return m_Height; } cItem & GetItem (int x, int y) const; void SetItem (int x, int y, ENUM_ITEM_TYPE a_ItemType, char a_ItemCount, short a_ItemHealth); void SetItem (int x, int y, const cItem & a_Item); void Clear (void); /** Removes items in a_Grid from m_Items[] (used by cCraftingRecipe::ConsumeIngredients()) */ void ConsumeGrid(const cCraftingGrid & a_Grid); /** Dumps the entire crafting grid using LOGD() */ void Dump(void); // tolua_end cItem * GetItems(void) const {return m_Items; } /** Copies internal contents into the item array specified. Assumes that the array has the same dimensions as self */ void CopyToItems(cItem * a_Items) const; protected: int m_Width; int m_Height; cItem * m_Items; } ; // tolua_export class cCraftingRecipe // tolua_export { // tolua_export public: cCraftingRecipe(const cCraftingGrid & a_CraftingGrid); // tolua_begin void Clear (void); int GetIngredientsWidth (void) const {return m_Ingredients.GetWidth(); } int GetIngredientsHeight(void) const {return m_Ingredients.GetHeight(); } cItem & GetIngredient (int x, int y) const {return m_Ingredients.GetItem(x, y); } const cItem & GetResult (void) const {return m_Result; } void SetResult (ENUM_ITEM_TYPE a_ItemType, char a_ItemCount, short a_ItemHealth); void SetResult (const cItem & a_Item) { m_Result = a_Item; } void SetIngredient (int x, int y, ENUM_ITEM_TYPE a_ItemType, char a_ItemCount, short a_ItemHealth) { m_Ingredients.SetItem(x, y, a_ItemType, a_ItemCount, a_ItemHealth); } void SetIngredient (int x, int y, const cItem & a_Item) { m_Ingredients.SetItem(x, y, a_Item); } /** Consumes ingredients from the crafting grid specified */ void ConsumeIngredients(cCraftingGrid & a_CraftingGrid); /** Dumps the entire recipe using LOGD() */ void Dump(void); // tolua_end protected: cCraftingGrid m_Ingredients; // Adjusted to correspond to the input crafting grid! cItem m_Result; } ; // tolua_export /** The crafting recipes are the configurations to build a result item out of a set of ingredient items. The recipes are configured in the `crafting.txt`. When populating the crafting grid in game (inventory or crafting table), the items are compared to the ingredients to find a matching recipe and show and craft the result. Each recipe is defined via the result, the ingredients and the minecraft recipe name. To handle the crafting recipes internally efficient the vector index of the `cRecipes` is used as `RecipeId`. */ class cCraftingRecipes { public: static const int MAX_GRID_WIDTH = 3; static const int MAX_GRID_HEIGHT = 3; cCraftingRecipes(void); ~cCraftingRecipes(); /** Returns the recipe for current crafting grid. Doesn't modify the grid. Clears a_Recipe if no recipe found. */ void GetRecipe(cPlayer & a_Player, cCraftingGrid & a_CraftingGrid, cCraftingRecipe & a_Recipe); /** Find recipes and returns the RecipeIds which contain the new item and all ingredients are in the known items */ std::vector FindNewRecipesForItem(const cItem & a_Item, const std::set & a_KnownItems); struct cRecipeSlot { cItem m_Item; int x, y; // 1..3, or -1 for "any" } ; typedef std::vector cRecipeSlots; /** A single recipe, stored. Each recipe is normalized right after parsing (NormalizeIngredients()) A normalized recipe starts at (0, 0) */ struct cRecipe { cRecipeSlots m_Ingredients; cItem m_Result; AString m_RecipeName; // Size of the regular items in the recipe; "anywhere" items are excluded: int m_Width; int m_Height; } ; /** Returns the recipe by id */ cRecipe * GetRecipeById(UInt32 a_RecipeId); /** Gets a map of all recipes with name and recipe id */ const std::map & GetRecipeNameMap(); protected: typedef std::vector cRecipes; cRecipes m_Recipes; void LoadRecipes(void); void ClearRecipes(void); /** Parses the recipe line and adds it into m_Recipes. a_LineNum is used for diagnostic warnings only */ void AddRecipeLine(int a_LineNum, const AString & a_RecipeLine); /** Parses an item string in the format "[^]", returns true if successful. */ bool ParseItem(const AString & a_String, cItem & a_Item); /** Parses one ingredient and adds it to the specified recipe. Returns true if successful. */ bool ParseIngredient(const AString & a_String, cRecipe * a_Recipe); /** Moves the recipe to top-left corner, sets its MinWidth / MinHeight */ void NormalizeIngredients(cRecipe * a_Recipe); /** Finds a recipe matching the crafting grid. Returns a newly allocated recipe (with all its coords set) or nullptr if not found. Caller must delete return value! */ cRecipe * FindRecipe(const cItem * a_CraftingGrid, int a_GridWidth, int a_GridHeight); /** Same as FindRecipe, but the grid is guaranteed to be of minimal dimensions needed */ cRecipe * FindRecipeCropped(const cItem * a_CraftingGrid, int a_GridWidth, int a_GridHeight, int a_GridStride); /** Checks if the grid matches the specified recipe, offset by the specified offsets. Returns a matched cRecipe * if so, or nullptr if not matching. Caller must delete the return value! */ cRecipe * MatchRecipe(const cItem * a_CraftingGrid, int a_GridWidth, int a_GridHeight, int a_GridStride, const cRecipe * a_Recipe, int a_OffsetX, int a_OffsetY); /** Searches for anything firework related, and does the data setting if appropriate */ void HandleFireworks(const cItem * a_CraftingGrid, cCraftingRecipes::cRecipe * a_Recipe, int a_GridStride, int a_OffsetX, int a_OffsetY); /** Searches for anything dye related for leather, calculates the appropriate color value, and sets the resulting value. */ void HandleDyedLeather(const cItem * a_CraftingGrid, cCraftingRecipes::cRecipe * a_Recipe, int a_GridStride, int a_GridWidth, int a_GridHeight); private: /** Mapping the minecraft recipe names to the internal cuberite recipe Ids */ std::map m_RecipeNameMap; /** Checks if all ingredients of the a_Recipe are within the a_KnownItems list and if the a_NewItem is part of the ingredients. This makes sure to only find 'newly discovered' recipes. */ bool IsNewCraftableRecipe( const cRecipe * a_Recipe, const cItem & a_NewItem, const std::set & a_KnownItems ); /** Populates the RecipeNameMap */ void PopulateRecipeNameMap(void); } ; ================================================ FILE: src/Cuboid.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "Cuboid.h" //////////////////////////////////////////////////////////////////////////////// // cCuboid: void cCuboid::Assign(Vector3i a_Point1, Vector3i a_Point2) { p1 = a_Point1; p2 = a_Point2; } void cCuboid::Sort(void) { if (p1.x > p2.x) { std::swap(p1.x, p2.x); } if (p1.y > p2.y) { std::swap(p1.y, p2.y); } if (p1.z > p2.z) { std::swap(p1.z, p2.z); } } int cCuboid::GetVolume(void) const { int DifX = abs(p2.x - p1.x) + 1; int DifY = abs(p2.y - p1.y) + 1; int DifZ = abs(p2.z - p1.z) + 1; return DifX * DifY * DifZ; } bool cCuboid::IsCompletelyInside(const cCuboid & a_Outer) const { ASSERT(IsSorted()); ASSERT(a_Outer.IsSorted()); return ( (p1.x >= a_Outer.p1.x) && (p2.x <= a_Outer.p2.x) && (p1.y >= a_Outer.p1.y) && (p2.y <= a_Outer.p2.y) && (p1.z >= a_Outer.p1.z) && (p2.z <= a_Outer.p2.z) ); } void cCuboid::Move(Vector3i a_Offset) { p1.Move(a_Offset); p2.Move(a_Offset); } void cCuboid::Expand(int a_SubMinX, int a_AddMaxX, int a_SubMinY, int a_AddMaxY, int a_SubMinZ, int a_AddMaxZ) { if (p1.x < p2.x) { p1.x -= a_SubMinX; p2.x += a_AddMaxX; } else { p2.x -= a_SubMinX; p1.x += a_AddMaxX; } if (p1.y < p2.y) { p1.y -= a_SubMinY; p2.y += a_AddMaxY; } else { p2.y -= a_SubMinY; p1.y += a_AddMaxY; } if (p1.z < p2.z) { p1.z -= a_SubMinZ; p2.z += a_AddMaxZ; } else { p2.z -= a_SubMinZ; p1.z += a_AddMaxZ; } } void cCuboid::Clamp(const cCuboid & a_Limits) { ASSERT(IsSorted()); ASSERT(a_Limits.IsSorted()); p1.x = ::Clamp(p1.x, a_Limits.p1.x, a_Limits.p2.x); p1.y = ::Clamp(p1.y, a_Limits.p1.y, a_Limits.p2.y); p1.z = ::Clamp(p1.z, a_Limits.p1.z, a_Limits.p2.z); p2.x = ::Clamp(p2.x, a_Limits.p1.x, a_Limits.p2.x); p2.y = ::Clamp(p2.y, a_Limits.p1.y, a_Limits.p2.y); p2.z = ::Clamp(p2.z, a_Limits.p1.z, a_Limits.p2.z); } void cCuboid::ClampSize(Vector3i a_MaxSize) { ASSERT(IsSorted()); if (p2.x - p1.x > a_MaxSize.x) { p2.x = p1.x + a_MaxSize.x; } if (p2.y - p1.y > a_MaxSize.y) { p2.y = p1.y + a_MaxSize.y; } if (p2.z - p1.z > a_MaxSize.z) { p2.z = p1.z + a_MaxSize.z; } } void cCuboid::ClampX(int a_MinX, int a_MaxX) { p1.x = ::Clamp(p1.x, a_MinX, a_MaxX); p2.x = ::Clamp(p2.x, a_MinX, a_MaxX); } void cCuboid::ClampY(int a_MinY, int a_MaxY) { p1.y = ::Clamp(p1.y, a_MinY, a_MaxY); p2.y = ::Clamp(p2.y, a_MinY, a_MaxY); } void cCuboid::ClampZ(int a_MinZ, int a_MaxZ) { p1.z = ::Clamp(p1.z, a_MinZ, a_MaxZ); p2.z = ::Clamp(p2.z, a_MinZ, a_MaxZ); } bool cCuboid::IsSorted(void) const { return ( (p1.x <= p2.x) && (p1.y <= p2.y) && (p1.z <= p2.z) ); } void cCuboid::Engulf(Vector3i a_Point) { if (a_Point.x < p1.x) { p1.x = a_Point.x; } else if (a_Point.x > p2.x) { p2.x = a_Point.x; } if (a_Point.y < p1.y) { p1.y = a_Point.y; } else if (a_Point.y > p2.y) { p2.y = a_Point.y; } if (a_Point.z < p1.z) { p1.z = a_Point.z; } else if (a_Point.z > p2.z) { p2.z = a_Point.z; } } ================================================ FILE: src/Cuboid.h ================================================ #pragma once // tolua_begin class cCuboid { public: // p1 is expected to have the smaller of the coords; Sort() swaps coords to match this Vector3i p1, p2; cCuboid(void) {} cCuboid(Vector3i a_p1, Vector3i a_p2) : p1(a_p1), p2(a_p2) {} cCuboid(int a_X1, int a_Y1, int a_Z1) : p1(a_X1, a_Y1, a_Z1), p2(a_X1, a_Y1, a_Z1) {} #ifdef TOLUA_EXPOSITION // tolua isn't aware of implicitly generated copy constructors cCuboid(const cCuboid & a_Cuboid); #endif // tolua_end // Exported in ManualBindings.cpp to support the old deprecated coord-based overload. void Assign(Vector3i a_Point1, Vector3i a_Point2); void Assign(const cCuboid & a_SrcCuboid) { *this = a_SrcCuboid; } // tolua_begin void Sort(void); int DifX(void) const { return p2.x - p1.x; } int DifY(void) const { return p2.y - p1.y; } int DifZ(void) const { return p2.z - p1.z; } /** Returns the volume of the cuboid, in blocks. Note that the volume considers both coords inclusive. Works on unsorted cuboids, too. */ int GetVolume(void) const; /** Returns true if the cuboids have at least one voxel in common. Both coords are considered inclusive. Assumes both cuboids are sorted. */ inline bool DoesIntersect(const cCuboid & a_Other) const { ASSERT(IsSorted()); ASSERT(a_Other.IsSorted()); // In order for cuboids to intersect, each of their coord intervals need to intersect return ( DoIntervalsIntersect(p1.x, p2.x, a_Other.p1.x, a_Other.p2.x) && DoIntervalsIntersect(p1.y, p2.y, a_Other.p1.y, a_Other.p2.y) && DoIntervalsIntersect(p1.z, p2.z, a_Other.p1.z, a_Other.p2.z) ); } // tolua_end // Exported in ManualBindings.cpp to support the old deprecated coord-based overload. bool IsInside(Vector3i v) const { return ( (v.x >= p1.x) && (v.x <= p2.x) && (v.y >= p1.y) && (v.y <= p2.y) && (v.z >= p1.z) && (v.z <= p2.z) ); } bool IsInside(Vector3d v) const { return ( (v.x >= p1.x) && (v.x <= p2.x) && (v.y >= p1.y) && (v.y <= p2.y) && (v.z >= p1.z) && (v.z <= p2.z) ); } // tolua_begin /** Returns true if this cuboid is completely inside the specified cuboid (in all 6 coords). Assumes both cuboids are sorted. */ bool IsCompletelyInside(const cCuboid & a_Outer) const; // tolua_end /** Moves the cuboid by the specified offset. Exported in ManualBindings to support the old deprecated coord-based overload. */ void Move(Vector3i a_Offset); // tolua_begin /** Expands the cuboid by the specified amount in each direction. Works on unsorted cuboids as well. Note that this function doesn't check for underflows when using negative amounts. */ void Expand(int a_SubMinX, int a_AddMaxX, int a_SubMinY, int a_AddMaxY, int a_SubMinZ, int a_AddMaxZ); /** Clamps this cuboid, so that it doesn't reach outside of a_Limits in any direction. Assumes both this and a_Limits are sorted. */ void Clamp(const cCuboid & a_Limits); /** Clamps this cuboid's p2 so that the cuboid's size doesn't exceed the specified max size. Assumes this cuboid is sorted. */ void ClampSize(Vector3i a_MaxSize); /** Clamps both X coords to the specified range. Works on unsorted cuboids, too. */ void ClampX(int a_MinX, int a_MaxX); /** Clamps both Y coords to the specified range. Works on unsorted cuboids, too. */ void ClampY(int a_MinY, int a_MaxY); /** Clamps both Z coords to the specified range. Works on unsorted cuboids, too. */ void ClampZ(int a_MinZ, int a_MaxZ); /** Returns true if the coords are properly sorted (lesser in p1, greater in p2) */ bool IsSorted(void) const; /** If needed, expands the cuboid so that it contains the specified point. Assumes sorted. Doesn't contract. */ void Engulf(Vector3i a_Point); // tolua_end /** Checks the two cuboids for equality. */ bool operator == (const cCuboid & aOther) const { return ( (p1.x == aOther.p1.x) && (p1.y == aOther.p1.y) && (p1.z == aOther.p1.z) && (p2.x == aOther.p2.x) && (p2.y == aOther.p2.y) && (p2.z == aOther.p2.z) ); } bool operator != (const cCuboid & aOther) const { return !operator ==(aOther); } // tolua_begin private: /** Returns true if the two specified intervals have a non-empty union */ inline static bool DoIntervalsIntersect(int a_Min1, int a_Max1, int a_Min2, int a_Max2) { ASSERT(a_Min1 <= a_Max1); ASSERT(a_Min2 <= a_Max2); return ((a_Min1 <= a_Max2) && (a_Max1 >= a_Min2)); } } ; // tolua_end ================================================ FILE: src/DeadlockDetect.cpp ================================================ // DeadlockDetect.cpp // Declares the cDeadlockDetect class that tries to detect deadlocks and aborts the server when it detects one #include "Globals.h" #include "DeadlockDetect.h" #include "Root.h" #include "World.h" #include /** Number of milliseconds per cycle */ const int CYCLE_MILLISECONDS = 100; cDeadlockDetect::cDeadlockDetect(void) : Super("Deadlock Detector"), m_IntervalSec(1000) { } cDeadlockDetect::~cDeadlockDetect() { // Check that all tracked CSs have been removed, report any remaining: cCSLock lock(m_CS); if (!m_TrackedCriticalSections.empty()) { LOGWARNING("DeadlockDetect: Some CS objects (%u) haven't been removed from tracking", static_cast(m_TrackedCriticalSections.size())); for (const auto & tcs: m_TrackedCriticalSections) { LOGWARNING(" CS %p / %s", static_cast(tcs.first), tcs.second.c_str() ); } } } void cDeadlockDetect::Start(int a_IntervalSec) { m_IntervalSec = a_IntervalSec; // Read the initial world data: cRoot::Get()->ForEachWorld([=](cWorld & a_World) { SetWorldAge(a_World.GetName(), a_World.GetWorldAge()); return false; }); Super::Start(); } void cDeadlockDetect::TrackCriticalSection(cCriticalSection & a_CS, const AString & a_Name) { cCSLock lock(m_CS); m_TrackedCriticalSections.emplace_back(&a_CS, a_Name); } void cDeadlockDetect::UntrackCriticalSection(cCriticalSection & a_CS) { cCSLock lock(m_CS); for (auto itr = m_TrackedCriticalSections.begin(), end = m_TrackedCriticalSections.end(); itr != end; ++itr) { if (itr->first == &a_CS) { m_TrackedCriticalSections.erase(itr); return; } } } void cDeadlockDetect::Execute(void) { // Loop until the signal to terminate: while (!m_ShouldTerminate) { // Check the world ages: cRoot::Get()->ForEachWorld([=](cWorld & a_World) { CheckWorldAge(a_World.GetName(), a_World.GetWorldAge()); return false; }); std::this_thread::sleep_for(std::chrono::milliseconds(CYCLE_MILLISECONDS)); } // while (should run) } void cDeadlockDetect::SetWorldAge(const AString & a_WorldName, const cTickTimeLong a_Age) { m_WorldAges[a_WorldName].m_Age = a_Age; m_WorldAges[a_WorldName].m_NumCyclesSame = 0; } void cDeadlockDetect::CheckWorldAge(const AString & a_WorldName, const cTickTimeLong a_Age) { WorldAges::iterator itr = m_WorldAges.find(a_WorldName); if (itr == m_WorldAges.end()) { SetWorldAge(a_WorldName, a_Age); return; } cDeadlockDetect::sWorldAge & WorldAge = itr->second; if (WorldAge.m_Age == a_Age) { WorldAge.m_NumCyclesSame += 1; if (WorldAge.m_NumCyclesSame > (m_IntervalSec * 1000) / CYCLE_MILLISECONDS) { DeadlockDetected(a_WorldName, a_Age); } } else { WorldAge.m_Age = a_Age; WorldAge.m_NumCyclesSame = 0; } } void cDeadlockDetect::DeadlockDetected(const AString & a_WorldName, const cTickTimeLong a_WorldAge) { LOGERROR("Deadlock detected: world %s has been stuck at age %lld. Aborting the server.", a_WorldName.c_str(), static_cast(a_WorldAge.count()) ); ListTrackedCSs(); ASSERT(!"Deadlock detected"); std::abort(); } void cDeadlockDetect::ListTrackedCSs(void) { cCSLock lock(m_CS); for (const auto & cs: m_TrackedCriticalSections) { LOG("CS at %p, %s: RecursionCount = %d, ThreadIDHash = %04llx", static_cast(cs.first), cs.second.c_str(), cs.first->m_RecursionCount, static_cast(std::hash()(cs.first->m_OwningThreadID)) ); } } ================================================ FILE: src/DeadlockDetect.h ================================================ // DeadlockDetect.h // Declares the cDeadlockDetect class that tries to detect deadlocks and aborts the server when it detects one /* This class simply monitors each world's m_WorldAge, which is expected to grow on each tick. If the world age doesn't grow for several seconds, it's either because the server is Super-overloaded, or because the world tick thread hangs in a deadlock. We presume the latter and therefore kill the server. Once we learn to write crashdumps programmatically, we should do so just before killing, to enable debugging. */ #pragma once #include "OSSupport/IsThread.h" class cDeadlockDetect: public cIsThread { using Super = cIsThread; public: cDeadlockDetect(); virtual ~cDeadlockDetect() override; /** Starts the detection. Hides cIsThread's Start, because we need some initialization */ void Start(int a_IntervalSec); /** Adds the critical section for tracking. Tracked CSs are listed, together with ownership details, when a deadlock is detected. A tracked CS must be untracked before it is destroyed. a_Name is an arbitrary name that is listed along with the CS in the output. */ void TrackCriticalSection(cCriticalSection & a_CS, const AString & a_Name); /** Removes the CS from the tracking. */ void UntrackCriticalSection(cCriticalSection & a_CS); protected: struct sWorldAge { /** Last m_WorldAge that has been detected in this world */ cTickTimeLong m_Age; /** Number of cycles for which the age has been the same */ int m_NumCyclesSame; } ; /** Maps world name -> sWorldAge */ typedef std::map WorldAges; /** Protects m_TrackedCriticalSections from multithreaded access. */ cCriticalSection m_CS; /** CriticalSections that are tracked (their status output on deadlock). Protected against multithreaded access by m_CS. */ std::vector> m_TrackedCriticalSections; WorldAges m_WorldAges; /** Number of secods for which the ages must be the same for the detection to trigger */ int m_IntervalSec; // cIsThread overrides: virtual void Execute(void) override; /** Sets the initial world age. */ void SetWorldAge(const AString & a_WorldName, cTickTimeLong a_Age); /** Checks if the world's age has changed, updates the world's stats; calls DeadlockDetected() if deadlock detected. */ void CheckWorldAge(const AString & a_WorldName, cTickTimeLong a_Age); /** Called when a deadlock is detected in a world. Aborts the server. a_WorldName is the name of the world whose age has triggered the detection. a_WorldAge is the age (in ticks) in which the world is stuck. */ [[noreturn]] void DeadlockDetected(const AString & a_WorldName, cTickTimeLong a_WorldAge); /** Outputs a listing of the tracked CSs, together with their name and state. */ void ListTrackedCSs(); } ; ================================================ FILE: src/Defines.cpp ================================================ #include "Globals.h" #include "Defines.h" #include "BlockType.h" const char * ClickActionToString(int a_ClickAction) { switch (a_ClickAction) { case caLeftClick: return "caLeftClick"; case caRightClick: return "caRightClick"; case caShiftLeftClick: return "caShiftLeftClick"; case caShiftRightClick: return "caShiftRightClick"; case caNumber1: return "caNumber1"; case caNumber2: return "caNumber2"; case caNumber3: return "caNumber3"; case caNumber4: return "caNumber4"; case caNumber5: return "caNumber5"; case caNumber6: return "caNumber6"; case caNumber7: return "caNumber7"; case caNumber8: return "caNumber8"; case caNumber9: return "caNumber9"; case caMiddleClick: return "caMiddleClick"; case caDropKey: return "caDropKey"; case caCtrlDropKey: return "caCtrlDropKey"; case caLeftClickOutside: return "caLeftClickOutside"; case caRightClickOutside: return "caRightClickOutside"; case caLeftClickOutsideHoldNothing: return "caLeftClickOutsideHoldNothing"; case caRightClickOutsideHoldNothing: return "caRightClickOutsideHoldNothing"; case caLeftPaintBegin: return "caLeftPaintBegin"; case caRightPaintBegin: return "caRightPaintBegin"; case caMiddlePaintBegin: return "caMiddlePaintBegin"; case caLeftPaintProgress: return "caLeftPaintProgress"; case caRightPaintProgress: return "caRightPaintProgress"; case caMiddlePaintProgress: return "caMiddlePaintProgress"; case caLeftPaintEnd: return "caLeftPaintEnd"; case caRightPaintEnd: return "caRightPaintEnd"; case caMiddlePaintEnd: return "caMiddlePaintEnd"; case caDblClick: return "caDblClick"; case caUnknown: return "caUnknown"; } UNREACHABLE("Unknown click action"); } /** Returns a blockface mirrored around the Y axis (doesn't change up / down). */ eBlockFace MirrorBlockFaceY(eBlockFace a_BlockFace) { switch (a_BlockFace) { case BLOCK_FACE_XM: return BLOCK_FACE_XP; case BLOCK_FACE_XP: return BLOCK_FACE_XM; case BLOCK_FACE_ZM: return BLOCK_FACE_ZP; case BLOCK_FACE_ZP: return BLOCK_FACE_ZM; case BLOCK_FACE_NONE: case BLOCK_FACE_YM: case BLOCK_FACE_YP: { return a_BlockFace; } } UNREACHABLE("Unsupported block face"); } /** Returns a blockface rotated around the Y axis counter-clockwise. */ eBlockFace RotateBlockFaceCCW(eBlockFace a_BlockFace) { switch (a_BlockFace) { case BLOCK_FACE_XM: return BLOCK_FACE_ZP; case BLOCK_FACE_XP: return BLOCK_FACE_ZM; case BLOCK_FACE_ZM: return BLOCK_FACE_XM; case BLOCK_FACE_ZP: return BLOCK_FACE_XP; case BLOCK_FACE_NONE: case BLOCK_FACE_YM: case BLOCK_FACE_YP: { return a_BlockFace; } } UNREACHABLE("Unsupported block face"); } eBlockFace RotateBlockFaceCW(eBlockFace a_BlockFace) { switch (a_BlockFace) { case BLOCK_FACE_XM: return BLOCK_FACE_ZM; case BLOCK_FACE_XP: return BLOCK_FACE_ZP; case BLOCK_FACE_ZM: return BLOCK_FACE_XP; case BLOCK_FACE_ZP: return BLOCK_FACE_XM; case BLOCK_FACE_NONE: case BLOCK_FACE_YM: case BLOCK_FACE_YP: { return a_BlockFace; } } UNREACHABLE("Unsupported block face"); } eBlockFace ReverseBlockFace(eBlockFace a_BlockFace) { switch (a_BlockFace) { case BLOCK_FACE_YP: return BLOCK_FACE_YM; case BLOCK_FACE_XP: return BLOCK_FACE_XM; case BLOCK_FACE_ZP: return BLOCK_FACE_ZM; case BLOCK_FACE_YM: return BLOCK_FACE_YP; case BLOCK_FACE_XM: return BLOCK_FACE_XP; case BLOCK_FACE_ZM: return BLOCK_FACE_ZP; case BLOCK_FACE_NONE: return a_BlockFace; } UNREACHABLE("Unsupported block face"); } /** Returns the textual representation of the BlockFace constant. */ AString BlockFaceToString(eBlockFace a_BlockFace) { switch (a_BlockFace) { case BLOCK_FACE_XM: return "BLOCK_FACE_XM"; case BLOCK_FACE_XP: return "BLOCK_FACE_XP"; case BLOCK_FACE_YM: return "BLOCK_FACE_YM"; case BLOCK_FACE_YP: return "BLOCK_FACE_YP"; case BLOCK_FACE_ZM: return "BLOCK_FACE_ZM"; case BLOCK_FACE_ZP: return "BLOCK_FACE_ZP"; case BLOCK_FACE_NONE: return "BLOCK_FACE_NONE"; } UNREACHABLE("Unsupported block face"); } bool IsValidBlock(int a_BlockType) { return ( ((a_BlockType > -1) && (a_BlockType <= E_BLOCK_MAX_TYPE_ID)) || (a_BlockType == 255) // the blocks 253-254 don't exist yet -> https://minecraft.wiki/w/Data_values#Block_IDs ); } bool IsValidItem(int a_ItemType) { if ( ((a_ItemType >= E_ITEM_FIRST) && (a_ItemType <= E_ITEM_MAX_CONSECUTIVE_TYPE_ID)) || // Basic items range ((a_ItemType >= E_ITEM_FIRST_DISC) && (a_ItemType <= E_ITEM_LAST_DISC)) // Music discs' special range ) { return true; } if (a_ItemType == 0) { return false; } return IsValidBlock(a_ItemType); } eDimension StringToDimension(const AString & a_DimensionString) { // First try decoding as a number int res; if (StringToInteger(a_DimensionString, res)) { // It was a valid number return static_cast(res); } // Decode using a built-in map: static struct { eDimension m_Dimension; const char * m_String; } DimensionMap [] = { { dimOverworld, "Overworld"}, { dimOverworld, "Normal"}, { dimOverworld, "World"}, { dimNether, "Nether"}, { dimNether, "Hell"}, // Alternate name for Nether { dimEnd, "End"}, { dimEnd, "Sky"}, // Old name for End } ; for (size_t i = 0; i < ARRAYCOUNT(DimensionMap); i++) { if (NoCaseCompare(DimensionMap[i].m_String, a_DimensionString) == 0) { return DimensionMap[i].m_Dimension; } } // for i - DimensionMap[] // Not found LOGWARNING("Unknown dimension: \"%s\". Setting to Overworld", a_DimensionString.c_str()); return dimOverworld; } AString DimensionToString(eDimension a_Dimension) { // Decode using a built-in map: static struct { eDimension m_Dimension; const char * m_String; } DimensionMap[] = { { dimOverworld, "Overworld" }, { dimNether, "Nether" }, { dimEnd, "End" }, }; for (size_t i = 0; i < ARRAYCOUNT(DimensionMap); i++) { if (DimensionMap[i].m_Dimension == a_Dimension) { return DimensionMap[i].m_String; } } // for i - DimensionMap[] // Not found LOGWARNING("Unknown dimension: \"%i\". Setting to Overworld", static_cast(a_Dimension)); return "Overworld"; } AString DamageTypeToString(eDamageType a_DamageType) { // Make sure to keep this alpha-sorted. switch (a_DamageType) { case dtAdmin: return "dtAdmin"; case dtAttack: return "dtAttack"; case dtCactusContact: return "dtCactusContact"; case dtMagmaContact: return "dtMagmaContact"; case dtDrowning: return "dtDrowning"; case dtEnderPearl: return "dtEnderPearl"; case dtEnvironment: return "dtEnvironment"; case dtFalling: return "dtFalling"; case dtFireContact: return "dtFireContact"; case dtInVoid: return "dtInVoid"; case dtLavaContact: return "dtLavaContact"; case dtLightning: return "dtLightning"; case dtOnFire: return "dtOnFire"; case dtPoisoning: return "dtPoisoning"; case dtWithering: return "dtWithering"; case dtPotionOfHarming: return "dtPotionOfHarming"; case dtRangedAttack: return "dtRangedAttack"; case dtStarving: return "dtStarving"; case dtSuffocating: return "dtSuffocation"; case dtExplosion: return "dtExplosion"; } UNREACHABLE("Unsupported damage type"); } eDamageType StringToDamageType(const AString & a_DamageTypeString) { // First try decoding as a number: int res; if (!StringToInteger(a_DamageTypeString, res)) { // It was a valid number return static_cast(res); } // Decode using a built-in map: static struct { eDamageType m_DamageType; const char * m_String; } DamageTypeMap [] = { // Cannonical names: { dtAttack, "dtAttack"}, { dtRangedAttack, "dtRangedAttack"}, { dtLightning, "dtLightning"}, { dtFalling, "dtFalling"}, { dtDrowning, "dtDrowning"}, { dtSuffocating, "dtSuffocation"}, { dtStarving, "dtStarving"}, { dtCactusContact, "dtCactusContact"}, { dtMagmaContact, "dtMagmaContact"}, { dtLavaContact, "dtLavaContact"}, { dtPoisoning, "dtPoisoning"}, { dtWithering, "dtWithering"}, { dtOnFire, "dtOnFire"}, { dtFireContact, "dtFireContact"}, { dtInVoid, "dtInVoid"}, { dtPotionOfHarming, "dtPotionOfHarming"}, { dtAdmin, "dtAdmin"}, { dtExplosion, "dtExplosion"}, { dtEnvironment, "dtEnvironment"}, // Common synonyms: { dtAttack, "dtPawnAttack"}, { dtAttack, "dtEntityAttack"}, { dtAttack, "dtMob"}, { dtAttack, "dtMobAttack"}, { dtRangedAttack, "dtArrowAttack"}, { dtRangedAttack, "dtArrow"}, { dtRangedAttack, "dtProjectile"}, { dtFalling, "dtFall"}, { dtDrowning, "dtDrown"}, { dtSuffocating, "dtSuffocation"}, { dtStarving, "dtStarvation"}, { dtStarving, "dtHunger"}, { dtCactusContact, "dtCactus"}, { dtCactusContact, "dtCactuses"}, { dtCactusContact, "dtCacti"}, { dtMagmaContact, "dtMagma"}, { dtLavaContact, "dtLava"}, { dtPoisoning, "dtPoison"}, { dtWithering, "dtWither"}, { dtOnFire, "dtBurning"}, { dtFireContact, "dtInFire"}, { dtAdmin, "dtPlugin"}, } ; for (size_t i = 0; i < ARRAYCOUNT(DamageTypeMap); i++) { if (NoCaseCompare(DamageTypeMap[i].m_String, a_DamageTypeString) == 0) { return DamageTypeMap[i].m_DamageType; } } // for i - DamageTypeMap[] // Not found: return static_cast(-1); } void AddFaceDirection(int & a_BlockX, int & a_BlockY, int & a_BlockZ, eBlockFace a_BlockFace, bool a_bInverse) { LOGWARNING("AddFaceDirection with X/Y/Z parameters is deprecated, use the vector version"); const auto Offset = AddFaceDirection({ a_BlockX, a_BlockY, a_BlockZ }, a_BlockFace, a_bInverse); a_BlockX = Offset.x; a_BlockY = Offset.y; a_BlockZ = Offset.z; } Vector3i AddFaceDirection(const Vector3i a_Position, const eBlockFace a_BlockFace, const bool a_InvertDirection) { const int Offset = a_InvertDirection ? -1 : 1; switch (a_BlockFace) { case BLOCK_FACE_YP: return a_Position.addedY(+Offset); case BLOCK_FACE_YM: return a_Position.addedY(-Offset); case BLOCK_FACE_ZM: return a_Position.addedZ(-Offset); case BLOCK_FACE_ZP: return a_Position.addedZ(+Offset); case BLOCK_FACE_XP: return a_Position.addedX(+Offset); case BLOCK_FACE_XM: return a_Position.addedX(-Offset); case BLOCK_FACE_NONE: break; } UNREACHABLE("Unsupported block face"); } bool ItemCategory::IsPickaxe(short a_ItemType) { switch (a_ItemType) { case E_ITEM_WOODEN_PICKAXE: case E_ITEM_STONE_PICKAXE: case E_ITEM_IRON_PICKAXE: case E_ITEM_GOLD_PICKAXE: case E_ITEM_DIAMOND_PICKAXE: { return true; } default: { return false; } } } bool ItemCategory::IsAxe(short a_ItemType) { switch (a_ItemType) { case E_ITEM_WOODEN_AXE: case E_ITEM_STONE_AXE: case E_ITEM_IRON_AXE: case E_ITEM_GOLD_AXE: case E_ITEM_DIAMOND_AXE: { return true; } default: { return false; } } } bool ItemCategory::IsSword(short a_ItemID) { return (a_ItemID == E_ITEM_WOODEN_SWORD) || (a_ItemID == E_ITEM_STONE_SWORD) || (a_ItemID == E_ITEM_IRON_SWORD) || (a_ItemID == E_ITEM_GOLD_SWORD) || (a_ItemID == E_ITEM_DIAMOND_SWORD); } bool ItemCategory::IsHoe(short a_ItemID) { return (a_ItemID == E_ITEM_WOODEN_HOE) || (a_ItemID == E_ITEM_STONE_HOE) || (a_ItemID == E_ITEM_IRON_HOE) || (a_ItemID == E_ITEM_GOLD_HOE) || (a_ItemID == E_ITEM_DIAMOND_HOE); } bool ItemCategory::IsShovel(short a_ItemID) { return (a_ItemID == E_ITEM_WOODEN_SHOVEL) || (a_ItemID == E_ITEM_STONE_SHOVEL) || (a_ItemID == E_ITEM_IRON_SHOVEL) || (a_ItemID == E_ITEM_GOLD_SHOVEL) || (a_ItemID == E_ITEM_DIAMOND_SHOVEL); } bool ItemCategory::IsTool(short a_ItemID) { return IsPickaxe( a_ItemID) || IsAxe ( a_ItemID) || IsSword ( a_ItemID) || IsHoe ( a_ItemID) || IsShovel ( a_ItemID); } bool ItemCategory::IsHelmet(short a_ItemType) { return ( (a_ItemType == E_ITEM_LEATHER_CAP) || (a_ItemType == E_ITEM_GOLD_HELMET) || (a_ItemType == E_ITEM_CHAIN_HELMET) || (a_ItemType == E_ITEM_IRON_HELMET) || (a_ItemType == E_ITEM_DIAMOND_HELMET) ); } bool ItemCategory::IsChestPlate(short a_ItemType) { return ( (a_ItemType == E_ITEM_ELYTRA) || (a_ItemType == E_ITEM_LEATHER_TUNIC) || (a_ItemType == E_ITEM_GOLD_CHESTPLATE) || (a_ItemType == E_ITEM_CHAIN_CHESTPLATE) || (a_ItemType == E_ITEM_IRON_CHESTPLATE) || (a_ItemType == E_ITEM_DIAMOND_CHESTPLATE) ); } bool ItemCategory::IsLeggings(short a_ItemType) { return ( (a_ItemType == E_ITEM_LEATHER_PANTS) || (a_ItemType == E_ITEM_GOLD_LEGGINGS) || (a_ItemType == E_ITEM_CHAIN_LEGGINGS) || (a_ItemType == E_ITEM_IRON_LEGGINGS) || (a_ItemType == E_ITEM_DIAMOND_LEGGINGS) ); } bool ItemCategory::IsBoots(short a_ItemType) { return ( (a_ItemType == E_ITEM_LEATHER_BOOTS) || (a_ItemType == E_ITEM_GOLD_BOOTS) || (a_ItemType == E_ITEM_CHAIN_BOOTS) || (a_ItemType == E_ITEM_IRON_BOOTS) || (a_ItemType == E_ITEM_DIAMOND_BOOTS) ); } bool ItemCategory::IsMinecart(short a_ItemType) { return ( (a_ItemType == E_ITEM_MINECART) || (a_ItemType == E_ITEM_CHEST_MINECART) || (a_ItemType == E_ITEM_FURNACE_MINECART) || (a_ItemType == E_ITEM_MINECART_WITH_TNT) || (a_ItemType == E_ITEM_MINECART_WITH_HOPPER) ); } bool ItemCategory::IsArmor(short a_ItemType) { return ( IsHelmet(a_ItemType) || IsChestPlate(a_ItemType) || IsLeggings(a_ItemType) || IsBoots(a_ItemType) ); } bool ItemCategory::IsHorseArmor(short a_ItemType) { switch (a_ItemType) { case E_ITEM_IRON_HORSE_ARMOR: case E_ITEM_GOLD_HORSE_ARMOR: case E_ITEM_DIAMOND_HORSE_ARMOR: { return true; } default: { return false; } } } bool ItemCategory::IsVillagerFood(short a_ItemType) { switch (a_ItemType) { case E_ITEM_CARROT: case E_ITEM_POTATO: case E_ITEM_BREAD: case E_ITEM_BEETROOT: case E_ITEM_SEEDS: case E_ITEM_BEETROOT_SEEDS: case E_ITEM_WHEAT: { return true; } default: { return false; } } } ================================================ FILE: src/Defines.h ================================================ #pragma once /** List of slot numbers, used for inventory-painting */ typedef std::vector cSlotNums; /** Constant to calculate ticks from seconds "ticks per second" */ constexpr inline const int TPS = 20; // This is not added to the lua API because it broke the build // tolua_begin /** Experience Orb setup */ enum { // Open to suggestion on naming convention here :) MAX_EXPERIENCE_ORB_SIZE = 2000 } ; /** Block face constants, used in PlayerDigging and PlayerBlockPlacement packets and bbox collision calc */ enum eBlockFace { BLOCK_FACE_NONE = -1, // Interacting with no block face - swinging the item in the air BLOCK_FACE_XM = 4, // Interacting with the X- face of the block BLOCK_FACE_XP = 5, // Interacting with the X+ face of the block BLOCK_FACE_YM = 0, // Interacting with the Y- face of the block BLOCK_FACE_YP = 1, // Interacting with the Y+ face of the block BLOCK_FACE_ZM = 2, // Interacting with the Z- face of the block BLOCK_FACE_ZP = 3, // Interacting with the Z+ face of the block // Synonyms using the (deprecated) world directions: BLOCK_FACE_BOTTOM = BLOCK_FACE_YM, // Interacting with the bottom face of the block BLOCK_FACE_TOP = BLOCK_FACE_YP, // Interacting with the top face of the block BLOCK_FACE_NORTH = BLOCK_FACE_ZM, // Interacting with the northern face of the block BLOCK_FACE_SOUTH = BLOCK_FACE_ZP, // Interacting with the southern face of the block BLOCK_FACE_WEST = BLOCK_FACE_XM, // Interacting with the western face of the block BLOCK_FACE_EAST = BLOCK_FACE_XP, // Interacting with the eastern face of the block // Bounds, used for range-checking: BLOCK_FACE_MIN = -1, BLOCK_FACE_MAX = 5, } ; /** PlayerDigging status constants */ enum { DIG_STATUS_STARTED = 0, DIG_STATUS_CANCELLED = 1, DIG_STATUS_FINISHED = 2, DIG_STATUS_DROP_STACK = 3, DIG_STATUS_DROP_HELD = 4, DIG_STATUS_SHOOT_EAT = 5, DIG_STATUS_SWAP_ITEM_IN_HAND = 6, } ; /** Individual actions sent in the WindowClick packet */ enum eClickAction { // Sorted by occurrence in the 1.5 protocol caLeftClick, caRightClick, caShiftLeftClick, caShiftRightClick, caNumber1, caNumber2, caNumber3, caNumber4, caNumber5, caNumber6, caNumber7, caNumber8, caNumber9, caMiddleClick, caDropKey, caCtrlDropKey, caLeftClickOutside, caRightClickOutside, caLeftClickOutsideHoldNothing, caRightClickOutsideHoldNothing, caLeftPaintBegin, caRightPaintBegin, caMiddlePaintBegin, caLeftPaintProgress, caRightPaintProgress, caMiddlePaintProgress, caLeftPaintEnd, caRightPaintEnd, caMiddlePaintEnd, caDblClick, // Add new actions here caUnknown = 255, // Keep this list in sync with ClickActionToString() function below! } ; enum eGameMode { eGameMode_NotSet = -1, eGameMode_Survival = 0, eGameMode_Creative = 1, eGameMode_Adventure = 2, eGameMode_Spectator = 3, // Easier-to-use synonyms: gmNotSet = eGameMode_NotSet, gmSurvival = eGameMode_Survival, gmCreative = eGameMode_Creative, gmAdventure = eGameMode_Adventure, gmSpectator = eGameMode_Spectator, // These two are used to check GameMode for validity when converting from integers. gmMax, // Gets automatically assigned gmMin = 0, } ; enum eChatType { ctChatBox = 0, ctSystem = 1, ctAboveActionBar = 2, } ; enum eWeather { eWeather_Sunny = 0, eWeather_Rain = 1, eWeather_ThunderStorm = 2, // Easier-to-use synonyms: wSunny = eWeather_Sunny, wRain = eWeather_Rain, wThunderstorm = eWeather_ThunderStorm, wStorm = wThunderstorm, } ; enum eMobHeadType { SKULL_TYPE_SKELETON = 0, SKULL_TYPE_WITHER = 1, SKULL_TYPE_ZOMBIE = 2, SKULL_TYPE_PLAYER = 3, SKULL_TYPE_CREEPER = 4, SKULL_TYPE_DRAGON = 5, } ; enum eMobHeadRotation { SKULL_ROTATION_NORTH = 0, SKULL_ROTATION_NORTH_NORTH_EAST = 1, SKULL_ROTATION_NORTH_EAST = 2, SKULL_ROTATION_EAST_NORTH_EAST = 3, SKULL_ROTATION_EAST = 4, SKULL_ROTATION_EAST_SOUTH_EAST = 5, SKULL_ROTATION_SOUTH_EAST = 6, SKULL_ROTATION_SOUTH_SOUTH_EAST = 7, SKULL_ROTATION_SOUTH = 8, SKULL_ROTATION_SOUTH_SOUTH_WEST = 9, SKULL_ROTATION_SOUTH_WEST = 10, SKULL_ROTATION_WEST_SOUTH_WEST = 11, SKULL_ROTATION_WEST = 12, SKULL_ROTATION_WEST_NORTH_WEST = 13, SKULL_ROTATION_NORTH_WEST = 14, SKULL_ROTATION_NORTH_NORTH_WEST = 15, } ; enum eSkinPart { spCape = 0x01, spJacket = 0x02, spLeftSleeve = 0x04, spRightSleeve = 0x08, spLeftPants = 0x10, spRightPants = 0x20, spHat = 0x40, spMask = 0x7F, }; /** Dimension of a world */ enum eDimension { dimNether = -1, dimOverworld = 0, dimEnd = 1, dimNotSet = 255, // For things that need an "indeterminate" state, such as cProtocol's LastSentDimension } ; /** Damage type, used in the TakeDamageInfo structure and related functions */ enum eDamageType { // Canonical names for the types (as documented in the plugin wiki): dtAttack, // Being attacked by a mob dtRangedAttack, // Being attacked by a projectile, possibly from a mob dtLightning, // Hit by a lightning strike dtFalling, // Falling down; dealt when hitting the ground dtDrowning, // Drowning in water / lava dtSuffocating, // Suffocating inside a block dtStarving, // Hunger dtCactusContact, // Contact with a cactus block dtMagmaContact, // Contact with a magma block dtLavaContact, // Contact with a lava block dtPoisoning, // Having the poison effect dtWithering, // Having the wither effect dtOnFire, // Being on fire dtFireContact, // Standing inside a fire block dtInVoid, // Falling into the Void (Y < 0) dtPotionOfHarming, dtEnderPearl, // Thrown an ender pearl, teleported by it dtAdmin, // Damage applied by an admin command dtExplosion, // Damage applied by an explosion dtEnvironment, // Damage dealt to mobs from environment: enderman in rain, snow golem in desert // Some common synonyms: dtPawnAttack = dtAttack, dtEntityAttack = dtAttack, dtMob = dtAttack, dtMobAttack = dtAttack, dtArrowAttack = dtRangedAttack, dtArrow = dtRangedAttack, dtProjectile = dtRangedAttack, dtFall = dtFalling, dtDrown = dtDrowning, dtSuffocation = dtSuffocating, dtStarvation = dtStarving, dtHunger = dtStarving, dtCactus = dtCactusContact, dtCactuses = dtCactusContact, dtCacti = dtCactusContact, dtMagma = dtMagmaContact, dtLava = dtLavaContact, dtPoison = dtPoisoning, dtWither = dtWithering, dtBurning = dtOnFire, dtInFire = dtFireContact, dtPlugin = dtAdmin, } ; /** The source of an explosion. Also dictates the type of the additional data passed to the explosion handlers: | esBed | Vector3i * | Bed exploding in the Nether or in the End | esEnderCrystal | cEnderCrystal * | | esGhastFireball | cGhastFireballEntity * | | esMonster | cMonster * | | esOther | nullptr | Any other explosion unaccounted for | esPlugin | nullptr | Explosion primarily attributed to a plugin | esPrimedTNT | cTNTEntity * | | esWitherBirth | cMonster * | | esWitherSkull | cProjectileEntity * | */ enum eExplosionSource { esBed, esEnderCrystal, esGhastFireball, esMonster, esOther, esPlugin, esPrimedTNT, esTNTMinecart, esWitherBirth, esWitherSkull, esMax, } ; enum eShrapnelLevel { slNone, slGravityAffectedOnly, slAll } ; enum eSpreadSource { ssFireSpread, ssGrassSpread, ssMushroomSpread, ssMycelSpread, ssVineSpread, } ; enum eMessageType { // https://forum.cuberite.org/thread-1212.html // MessageType... mtCustom, // Send raw data without any processing mtFailure, // Something could not be done (i.e. command not executed due to insufficient privilege) mtInformation, // Informational message (i.e. command usage) mtSuccess, // Something executed successfully mtWarning, // Something concerning (i.e. reload) is about to happen mtFatal, // Something catastrophic occured (i.e. plugin crash) mtDeath, // Denotes death of player mtPrivateMessage, // Player to player messaging identifier mtJoin, // A player has joined the server mtLeave, // A player has left the server mtMaxPlusOne, // The first invalid type, used for checking on LuaAPI boundaries // Common aliases: mtFail = mtFailure, mtError = mtFailure, mtInfo = mtInformation, mtPM = mtPrivateMessage, }; enum class BannerPattern { BottomStripe, TopStripe, LeftStripe, RightStripe, CenterStripeVertical, MiddleStripeHorizontal, DownRightStripe, DownLeftStripe, SmallVerticalStripes, DiagonalCross, SquareCross, LeftOfDiagonal, RightOfUpsideDownDiagonal, LeftOfUpsideDownDiagonal, RightOfDiagonal, VerticalHalfLeft, VerticalHalfRight, HorizontalHalfTop, HorizontalHalfBottom, BottomLeftCorner, BottomRightCorner, TopLeftCorner, TopRightCorner, BottomTriangle, TopTriangle, BottomTriangleSawtooth, TopTriangleSawtooth, MiddleCircle, MiddleRhombus, Border, CurlyBorder, Brick, Gradient, GradientUpsideDown, Creeper, Skull, Flower, Mojang, Globe, Piglin }; enum class BossBarColor { Pink, Blue, Red, Green, Yellow, Purple, White }; enum class BossBarDivisionType { None, SixNotches, TenNotches, TwelveNotches, TwentyNotches }; // tolua_end enum class EntityAnimation { AnimalFallsInLove, ArmorStandGetsHit, ArrowTipSparkles, DolphinShowsHappiness, EggCracks, EntityGetsCriticalHit, EntityGetsMagicalCriticalHit, EntityTrailsHoney, EvokerFangsAttacks, FireworkRocketExplodes, // FishingHookReels, FoxChews, GuardianAttacks, HoglinAttacks, HorseTamingFails, HorseTamingSucceeds, IronGolemAttacks, IronGolemOffersGift, IronGolemStashesGift, MinecartSpawnerDelayResets, MinecartTNTIgnites, MobSpawns, OcelotTrusts, OcelotDistrusts, PawnBerryBushPricks, PawnBurns, PawnChestEquipmentBreaks, PawnDies, PawnDrowns, PawnFeetEquipmentBreaks, PawnHandItemSwaps, PawnHeadEquipmentBreaks, PawnHurts, PawnLegsEquipmentBreaks, PawnMainHandEquipmentBreaks, PawnOffHandEquipmentBreaks, PawnShieldBlocks, PawnShieldBreaks, PawnTeleports, PawnThornsPricks, PawnTotemActivates, PlayerBadOmenActivates, PlayerEntersBed, PlayerFinishesEating, PlayerLeavesBed, PlayerMainHandSwings, // PlayerReducedDebugScreenDisables, // PlayerReducedDebugScreenEnables, PlayerOffHandSwings, RabbitJumps, RavagerAttacks, RavagerBecomesStunned, SheepEatsGrass, SnowballPoofs, // SquidResetsRotation, VillagerKisses, VillagerShowsAnger, VillagerShowsHappiness, VillagerSweats, WitchMagicks, WolfShakesWater, WolfTamingFails, WolfTamingSucceeds, ZoglinAttacks, ZombieVillagerCureFinishes }; // tolua_begin /** Returns a textual representation of the click action. */ const char * ClickActionToString(int a_ClickAction); /** Returns a blockface mirrored around the Y axis (doesn't change up / down). */ eBlockFace MirrorBlockFaceY(eBlockFace a_BlockFace); /** Returns a blockface rotated around the Y axis counter-clockwise. */ eBlockFace RotateBlockFaceCCW(eBlockFace a_BlockFace); /** Returns a blockface rotated around the Y axis clockwise. */ eBlockFace RotateBlockFaceCW(eBlockFace a_BlockFace); /** Returns a blockface opposite to the one specified. */ eBlockFace ReverseBlockFace(eBlockFace a_BlockFace); /** Returns the textual representation of the BlockFace constant. */ AString BlockFaceToString(eBlockFace a_BlockFace); /** Returns true if the specified block type is valid (known). */ bool IsValidBlock(int a_BlockType); /** Returns true if the specified item type is valid (known). */ bool IsValidItem(int a_ItemType); /** Translates a dimension string to dimension enum. Takes either a number or a dimension alias (built-in). Returns dimOverworld on failure */ extern eDimension StringToDimension(const AString & a_DimensionString); /** Translates a dimension enum to dimension string. Takes an eDimension enum value and returns "Overworld" on failure. */ extern AString DimensionToString(eDimension a_Dimension); /** Translates damage type constant to a string representation (built-in). */ extern AString DamageTypeToString(eDamageType a_DamageType); /** Translates a damage type string to damage type. Takes either a number or a damage type alias (built-in). Returns -1 on failure */ extern eDamageType StringToDamageType(const AString & a_DamageString); /** Modifies the specified coords so that they point to the block adjacent to the one specified through its specified face. If a_Inverse is true, the opposite direction is used instead. */ void AddFaceDirection(int & a_BlockX, int & a_BlockY, int & a_BlockZ, eBlockFace a_BlockFace, bool a_bInverse = false); /** Returns the coords of a block that is neighboring the specified position through its specified face. If a_InvertDirection is true, the opposite direction is used instead. */ Vector3i AddFaceDirection(Vector3i a_Pos, eBlockFace a_BlockFace, bool a_InvertDirection = false); // tolua_end inline void EulerToVector(double a_Pan, double a_Pitch, double & a_X, double & a_Y, double & a_Z) { // a_X = sinf ( a_Pan / 180 * PI) * cosf ( a_Pitch / 180 * PI); // a_Y = -sinf ( a_Pitch / 180 * PI); // a_Z = -cosf ( a_Pan / 180 * PI) * cosf ( a_Pitch / 180 * PI); a_X = cos(a_Pan / 180 * M_PI) * cos(a_Pitch / 180 * M_PI); a_Y = sin(a_Pan / 180 * M_PI) * cos(a_Pitch / 180 * M_PI); a_Z = sin(a_Pitch / 180 * M_PI); } inline void VectorToEuler(double a_X, double a_Y, double a_Z, double & a_Pan, double & a_Pitch) { double r = sqrt((a_X * a_X) + (a_Z * a_Z)); if (r < std::numeric_limits::epsilon()) { a_Pan = 0; } else { a_Pan = atan2(a_Z, a_X) * 180 / M_PI - 90; } a_Pitch = atan2(a_Y, r) * 180 / M_PI; } template inline T Diff(T a_Val1, T a_Val2) { return std::abs(a_Val1 - a_Val2); } // tolua_begin /** Normalizes an angle in degrees to the [-180, +180) range: */ inline double NormalizeAngleDegrees(const double a_Degrees) { double Norm = fmod(a_Degrees + 180, 360); if (Norm < 0) { Norm += 360; } return Norm - 180; } namespace ItemCategory { bool IsPickaxe(short a_ItemType); bool IsAxe(short a_ItemType); bool IsSword(short a_ItemType); bool IsHoe(short a_ItemType); bool IsShovel(short a_ItemType); bool IsTool(short a_ItemType); bool IsHelmet(short a_ItemType); bool IsChestPlate(short a_ItemType); bool IsLeggings(short a_ItemType); bool IsBoots(short a_ItemType); bool IsMinecart(short a_ItemType); bool IsArmor(short a_ItemType); bool IsHorseArmor(short a_ItemType); bool IsVillagerFood(short a_ItemType); } // tolua_end ================================================ FILE: src/EffectID.h ================================================ #pragma once // tolua_begin enum class EffectID : Int32 { SFX_RANDOM_DISPENSER_DISPENSE = 1000, SFX_RANDOM_DISPENSER_DISPENSE_FAIL = 1001, SFX_RANDOM_DISPENSER_SHOOT = 1002, SFX_RANDOM_ENDER_EYE_LAUNCH = 1003, SFX_RANDOM_FIREWORK_SHOT = 1004, SFX_RANDOM_IRON_DOOR_OPEN = 1005, SFX_RANDOM_WOODEN_DOOR_OPEN = 1006, SFX_RANDOM_WOODEN_TRAPDOOR_OPEN = 1007, SFX_RANDOM_FENCE_GATE_OPEN = 1008, SFX_RANDOM_FIRE_EXTINGUISH = 1009, SFX_RANDOM_PLAY_MUSIC_DISC = 1010, SFX_RANDOM_IRON_DOOR_CLOSE = 1011, SFX_RANDOM_WOODEN_DOOR_CLOSE = 1012, SFX_RANDOM_WOODEN_TRAPDOOR_CLOSE = 1013, SFX_RANDOM_FENCE_GATE_CLOSE = 1014, SFX_MOB_GHAST_WARN = 1015, SFX_MOB_GHAST_SHOOT = 1016, SFX_MOB_ENDERDRAGON_SHOOT = 1017, SFX_MOB_BLAZE_SHOOT = 1018, SFX_MOB_ZOMBIE_WOOD = 1019, SFX_MOB_ZOMBIE_METAL = 1020, SFX_MOB_ZOMBIE_WOOD_BREAK = 1021, SFX_MOB_WITHER_BREAK_BLOCK = 1022, SFX_MOB_WITHER_SPAWN = 1023, SFX_MOB_WITHER_SHOOT = 1024, SFX_MOB_BAT_TAKEOFF = 1025, SFX_MOB_ZOMBIE_INFECT = 1026, SFX_MOB_ZOMBIE_UNFECT = 1027, SFX_MOB_ENDERDRAGON_DEATH = 1028, SFX_RANDOM_ANVIL_BREAK = 1029, SFX_RANDOM_ANVIL_USE = 1030, SFX_RANDOM_ANVIL_LAND = 1031, SFX_RANDOM_PORTAL_TRAVEL = 1032, SFX_RANDOM_CHORUS_FLOWER_GROW = 1033, SFX_RANDOM_CHORUS_FLOWER_DEATH = 1034, SFX_RANDOM_BREWING_STAND_BREW = 1035, SFX_RANDOM_IRON_TRAPDOOR_OPEN = 1036, SFX_RANDOM_IRON_TRAPDOOR_CLOSE = 1037, PARTICLE_SMOKE = 2000, PARTICLE_BLOCK_BREAK = 2001, PARTICLE_SPLASH_POTION = 2002, PARTICLE_EYE_OF_ENDER = 2003, PARTICLE_MOBSPAWN = 2004, PARTICLE_HAPPY_VILLAGER = 2005, PARTICLE_DRAGON_BREATH = 2006, PARTICLE_END_GATEWAY_SPAWN = 3000, PARTICLE_ENDERDRAGON_GROWL = 3001, }; enum class SmokeDirection : Int32 { SOUTH_EAST = 0, SOUTH = 1, SOUTH_WEST = 2, EAST = 3, CENTRE = 4, WEST = 5, NORTH_EAST = 6, NORTH = 7, NORTH_WEST = 8, }; // tolua_end ================================================ FILE: src/Enchantments.cpp ================================================ // Enchantments.cpp // Implements the cEnchantments class representing a storage for item enchantments and stored-enchantments #include "Globals.h" #include "Enchantments.h" #include "WorldStorage/FastNBT.h" #include "FastRandom.h" #include "Noise/Noise.h" #include "BlockType.h" cEnchantments::cEnchantments(void) { // Nothing needed yet, but the constructor needs to be declared and impemented in order to be usable } cEnchantments::cEnchantments(const AString & a_StringSpec) { AddFromString(a_StringSpec); } void cEnchantments::Add(const cEnchantments & a_Other) { for (cEnchantments::cMap::const_iterator itr = a_Other.m_Enchantments.begin(), end = a_Other.m_Enchantments.end(); itr != end; ++itr) { SetLevel(itr->first, itr->second); } // for itr - a_Other.m_Enchantments[] } void cEnchantments::AddFromString(const AString & a_StringSpec) { // Add enchantments in the stringspec; if a specified enchantment already exists, overwrites it // Split the StringSpec into separate declarations, each in the form "id=lvl": AStringVector Decls = StringSplit(a_StringSpec, ";"); for (AStringVector::const_iterator itr = Decls.begin(), end = Decls.end(); itr != end; ++itr) { // Split each declaration into the id and lvl part: if (itr->empty()) { // The decl is empty (may happen if there's an extra semicolon at the end), ignore silently continue; } AStringVector Split = StringSplitAndTrim(*itr, "="); if (Split.size() != 2) { // Malformed decl LOG("%s: Malformed enchantment decl: \"%s\", skipping.", __FUNCTION__, itr->c_str()); continue; } int id = StringToEnchantmentID(Split[0]); if (id < 0) { LOG("%s: Failed to parse enchantment \"%s\", skipping.", __FUNCTION__, Split[0].c_str()); continue; } unsigned int lvl; if (!StringToInteger(Split[1], lvl)) { // Level failed to parse LOG("%s: Failed to parse enchantment level \"%s\", skipping.", __FUNCTION__, Split[1].c_str()); continue; } SetLevel(id, lvl); } // for itr - Decls[] } size_t cEnchantments::Count() const { return m_Enchantments.size(); } AString cEnchantments::ToString() const { // Serialize all the enchantments into a string AString res; for (cEnchantments::cMap::const_iterator itr = m_Enchantments.begin(), end = m_Enchantments.end(); itr != end; ++itr) { res.append(fmt::format(FMT_STRING("{}={};"), itr->first, itr->second)); } // for itr - m_Enchantments[] return res; } unsigned int cEnchantments::GetLevel(int a_EnchantmentID) const { // Return the level for the specified enchantment; 0 if not stored cMap::const_iterator itr = m_Enchantments.find(a_EnchantmentID); if (itr != m_Enchantments.end()) { return itr->second; } // Not stored, return zero return 0; } void cEnchantments::SetLevel(int a_EnchantmentID, unsigned int a_Level) { // Sets the level for the specified enchantment, adding it if not stored before or removing it if level <= 0 if (a_Level == 0) { // Delete enchantment, if present: cMap::iterator itr = m_Enchantments.find(a_EnchantmentID); if (itr != m_Enchantments.end()) { m_Enchantments.erase(itr); } } else { // Add / overwrite enchantment m_Enchantments[a_EnchantmentID] = a_Level; } } void cEnchantments::Clear(void) { m_Enchantments.clear(); } bool cEnchantments::IsEmpty(void) const { return m_Enchantments.empty(); } unsigned int cEnchantments::GetLevelCap(int a_EnchantmentID) { switch (a_EnchantmentID) { case enchProtection: return 4; case enchFireProtection: return 4; case enchFeatherFalling: return 4; case enchBlastProtection: return 4; case enchProjectileProtection: return 4; case enchRespiration: return 3; case enchAquaAffinity: return 1; case enchThorns: return 3; case enchDepthStrider: return 3; case enchSharpness: return 5; case enchSmite: return 5; case enchBaneOfArthropods: return 5; case enchKnockback: return 2; case enchFireAspect: return 2; case enchLooting: return 3; case enchEfficiency: return 5; case enchSilkTouch: return 1; case enchUnbreaking: return 3; case enchFortune: return 3; case enchPower: return 5; case enchPunch: return 2; case enchFlame: return 1; case enchInfinity: return 1; case enchLuckOfTheSea: return 3; case enchLure: return 3; } LOGWARNING("Unknown enchantment ID %d", a_EnchantmentID); return 0; } int cEnchantments::GetXPCostMultiplier(int a_EnchantmentID, bool FromBook) { if (FromBook) { switch (a_EnchantmentID) { case enchProtection: return 1; case enchFireProtection: return 1; case enchFeatherFalling: return 1; case enchBlastProtection: return 2; case enchProjectileProtection: return 1; case enchRespiration: return 2; case enchAquaAffinity: return 2; case enchThorns: return 4; case enchDepthStrider: return 2; case enchSharpness: return 1; case enchSmite: return 1; case enchBaneOfArthropods: return 1; case enchKnockback: return 1; case enchFireAspect: return 2; case enchLooting: return 2; case enchEfficiency: return 1; case enchSilkTouch: return 4; case enchUnbreaking: return 1; case enchFortune: return 1; case enchPower: return 1; case enchPunch: return 2; case enchFlame: return 2; case enchInfinity: return 4; case enchLuckOfTheSea: return 2; case enchLure: return 2; } } else // Without book { switch (a_EnchantmentID) { case enchProtection: return 1; case enchFireProtection: return 2; case enchFeatherFalling: return 2; case enchBlastProtection: return 4; case enchProjectileProtection: return 2; case enchRespiration: return 4; case enchAquaAffinity: return 4; case enchThorns: return 8; case enchDepthStrider: return 4; case enchSharpness: return 1; case enchSmite: return 2; case enchBaneOfArthropods: return 2; case enchKnockback: return 2; case enchFireAspect: return 4; case enchLooting: return 4; case enchEfficiency: return 1; case enchSilkTouch: return 8; case enchUnbreaking: return 2; case enchFortune: return 4; case enchPower: return 1; case enchPunch: return 4; case enchFlame: return 4; case enchInfinity: return 8; case enchLuckOfTheSea: return 4; case enchLure: return 4; } } LOGWARNING("Unknown enchantment ID %d", a_EnchantmentID); return 0; } bool cEnchantments::CanAddEnchantment(int a_EnchantmentID) const { if (GetLevel(a_EnchantmentID) > 0) { return true; } static const std::vector > IncompatibleEnchantments = { // Armor { enchProtection, enchFireProtection, enchBlastProtection, enchProjectileProtection }, // Tool { enchFortune, enchSilkTouch }, // Sword { enchSharpness, enchSmite, enchBaneOfArthropods }, // Boots // {enchDepthStrider, enchFrostWalker}, // Bow // {enchInfinity, enchMending} }; for (const auto & excl: IncompatibleEnchantments) { if (excl.count(a_EnchantmentID) != 0) { // See if we also have any of the enchantments for (auto ench: excl) { if (GetLevel(ench) > 0) { return false; } } } } return true; } int cEnchantments::StringToEnchantmentID(const AString & a_EnchantmentName) { static const struct { int m_Value; const char * m_Name; } EnchantmentNames[] = { { enchProtection, "Protection" }, { enchFireProtection, "FireProtection" }, { enchFeatherFalling, "FeatherFalling" }, { enchBlastProtection, "BlastProtection" }, { enchProjectileProtection, "ProjectileProtection" }, { enchRespiration, "Respiration" }, { enchAquaAffinity, "AquaAffinity" }, { enchThorns, "Thorns" }, { enchDepthStrider, "DepthStrider" }, { enchSharpness, "Sharpness" }, { enchSmite, "Smite" }, { enchBaneOfArthropods, "BaneOfArthropods" }, { enchKnockback, "Knockback" }, { enchFireAspect, "FireAspect" }, { enchLooting, "Looting" }, { enchEfficiency, "Efficiency" }, { enchSilkTouch, "SilkTouch" }, { enchUnbreaking, "Unbreaking" }, { enchFortune, "Fortune" }, { enchPower, "Power" }, { enchPunch, "Punch" }, { enchFlame, "Flame" }, { enchInfinity, "Infinity" }, { enchLuckOfTheSea, "LuckOfTheSea" }, { enchLure, "Lure" }, } ; // First try to parse as a number: int id = atoi(a_EnchantmentName.c_str()); if ((id != 0) || (a_EnchantmentName == "0")) { return id; } // It wasn't a number, do a lookup: for (size_t i = 0; i < ARRAYCOUNT(EnchantmentNames); i++) { if (NoCaseCompare(EnchantmentNames[i].m_Name, a_EnchantmentName) == 0) { return EnchantmentNames[i].m_Value; } } // for i - EnchantmentNames[] return -1; } bool cEnchantments::operator ==(const cEnchantments & a_Other) const { return m_Enchantments == a_Other.m_Enchantments; } bool cEnchantments::operator !=(const cEnchantments & a_Other) const { return m_Enchantments != a_Other.m_Enchantments; } void cEnchantments::AddItemEnchantmentWeights(cWeightedEnchantments & a_Enchantments, short a_ItemType, unsigned a_EnchantmentLevel) { if (ItemCategory::IsSword(a_ItemType)) { // Sharpness if ((a_EnchantmentLevel >= 34) && (a_EnchantmentLevel <= 54)) { AddEnchantmentWeightToVector(a_Enchantments, 10, enchSharpness, 4); } else if ((a_EnchantmentLevel >= 23) && (a_EnchantmentLevel <= 43)) { AddEnchantmentWeightToVector(a_Enchantments, 10, enchSharpness, 3); } else if ((a_EnchantmentLevel >= 12) && (a_EnchantmentLevel <= 32)) { AddEnchantmentWeightToVector(a_Enchantments, 10, enchSharpness, 2); } else if ((a_EnchantmentLevel >= 1) && (a_EnchantmentLevel <= 21)) { AddEnchantmentWeightToVector(a_Enchantments, 10, enchSharpness, 1); } // Smite if ((a_EnchantmentLevel >= 29) && (a_EnchantmentLevel <= 49)) { AddEnchantmentWeightToVector(a_Enchantments, 5, enchSmite, 4); } else if ((a_EnchantmentLevel >= 21) && (a_EnchantmentLevel <= 41)) { AddEnchantmentWeightToVector(a_Enchantments, 5, enchSmite, 3); } else if ((a_EnchantmentLevel >= 13) && (a_EnchantmentLevel <= 33)) { AddEnchantmentWeightToVector(a_Enchantments, 5, enchSmite, 2); } else if ((a_EnchantmentLevel >= 5) && (a_EnchantmentLevel <= 25)) { AddEnchantmentWeightToVector(a_Enchantments, 5, enchSmite, 1); } // Bane of Arthropods if ((a_EnchantmentLevel >= 29) && (a_EnchantmentLevel <= 49)) { AddEnchantmentWeightToVector(a_Enchantments, 5, enchBaneOfArthropods, 4); } else if ((a_EnchantmentLevel >= 21) && (a_EnchantmentLevel <= 41)) { AddEnchantmentWeightToVector(a_Enchantments, 5, enchBaneOfArthropods, 3); } else if ((a_EnchantmentLevel >= 13) && (a_EnchantmentLevel <= 33)) { AddEnchantmentWeightToVector(a_Enchantments, 5, enchBaneOfArthropods, 2); } else if ((a_EnchantmentLevel >= 5) && (a_EnchantmentLevel <= 25)) { AddEnchantmentWeightToVector(a_Enchantments, 5, enchBaneOfArthropods, 1); } // Knockback if ((a_EnchantmentLevel >= 25) && (a_EnchantmentLevel <= 75)) { AddEnchantmentWeightToVector(a_Enchantments, 5, enchKnockback, 2); } else if ((a_EnchantmentLevel >= 5) && (a_EnchantmentLevel <= 55)) { AddEnchantmentWeightToVector(a_Enchantments, 5, enchKnockback, 1); } // Fire Aspect if ((a_EnchantmentLevel >= 30) && (a_EnchantmentLevel <= 80)) { AddEnchantmentWeightToVector(a_Enchantments, 2, enchFireAspect, 2); } else if ((a_EnchantmentLevel >= 10) && (a_EnchantmentLevel <= 60)) { AddEnchantmentWeightToVector(a_Enchantments, 2, enchFireAspect, 1); } // Looting if ((a_EnchantmentLevel >= 33) && (a_EnchantmentLevel <= 83)) { AddEnchantmentWeightToVector(a_Enchantments, 2, enchLooting, 3); } else if ((a_EnchantmentLevel >= 24) && (a_EnchantmentLevel <= 74)) { AddEnchantmentWeightToVector(a_Enchantments, 2, enchLooting, 2); } else if ((a_EnchantmentLevel >= 15) && (a_EnchantmentLevel <= 65)) { AddEnchantmentWeightToVector(a_Enchantments, 2, enchLooting, 1); } } else if (ItemCategory::IsTool(a_ItemType)) { // Efficiency if ((a_EnchantmentLevel >= 31) && (a_EnchantmentLevel <= 81)) { AddEnchantmentWeightToVector(a_Enchantments, 10, enchEfficiency, 4); } else if ((a_EnchantmentLevel >= 21) && (a_EnchantmentLevel <= 71)) { AddEnchantmentWeightToVector(a_Enchantments, 10, enchEfficiency, 3); } else if ((a_EnchantmentLevel >= 11) && (a_EnchantmentLevel <= 61)) { AddEnchantmentWeightToVector(a_Enchantments, 10, enchEfficiency, 2); } else if ((a_EnchantmentLevel >= 1) && (a_EnchantmentLevel <= 51)) { AddEnchantmentWeightToVector(a_Enchantments, 10, enchEfficiency, 1); } // Silk Touch if ((a_EnchantmentLevel >= 15) && (a_EnchantmentLevel <= 65)) { AddEnchantmentWeightToVector(a_Enchantments, 1, enchSilkTouch, 1); } // Fortune if ((a_EnchantmentLevel >= 33) && (a_EnchantmentLevel <= 83)) { AddEnchantmentWeightToVector(a_Enchantments, 2, enchFortune, 3); } else if ((a_EnchantmentLevel >= 24) && (a_EnchantmentLevel <= 74)) { AddEnchantmentWeightToVector(a_Enchantments, 2, enchFortune, 2); } else if ((a_EnchantmentLevel >= 15) && (a_EnchantmentLevel <= 65)) { AddEnchantmentWeightToVector(a_Enchantments, 2, enchFortune, 1); } } else if (ItemCategory::IsArmor(a_ItemType)) { // Protection if ((a_EnchantmentLevel >= 34) && (a_EnchantmentLevel <= 54)) { AddEnchantmentWeightToVector(a_Enchantments, 10, enchProtection, 4); } else if ((a_EnchantmentLevel >= 23) && (a_EnchantmentLevel <= 43)) { AddEnchantmentWeightToVector(a_Enchantments, 10, enchProtection, 3); } else if ((a_EnchantmentLevel >= 12) && (a_EnchantmentLevel <= 32)) { AddEnchantmentWeightToVector(a_Enchantments, 10, enchProtection, 2); } else if ((a_EnchantmentLevel >= 1) && (a_EnchantmentLevel <= 21)) { AddEnchantmentWeightToVector(a_Enchantments, 10, enchProtection, 1); } // Fire Protection if ((a_EnchantmentLevel >= 34) && (a_EnchantmentLevel <= 46)) { AddEnchantmentWeightToVector(a_Enchantments, 5, enchFireProtection, 4); } else if ((a_EnchantmentLevel >= 26) && (a_EnchantmentLevel <= 38)) { AddEnchantmentWeightToVector(a_Enchantments, 5, enchFireProtection, 3); } else if ((a_EnchantmentLevel >= 18) && (a_EnchantmentLevel <= 30)) { AddEnchantmentWeightToVector(a_Enchantments, 5, enchFireProtection, 2); } else if ((a_EnchantmentLevel >= 10) && (a_EnchantmentLevel <= 22)) { AddEnchantmentWeightToVector(a_Enchantments, 5, enchFireProtection, 1); } // Blast Protection if ((a_EnchantmentLevel >= 29) && (a_EnchantmentLevel <= 41)) { AddEnchantmentWeightToVector(a_Enchantments, 2, enchBlastProtection, 4); } else if ((a_EnchantmentLevel >= 21) && (a_EnchantmentLevel <= 33)) { AddEnchantmentWeightToVector(a_Enchantments, 2, enchBlastProtection, 3); } else if ((a_EnchantmentLevel >= 13) && (a_EnchantmentLevel <= 25)) { AddEnchantmentWeightToVector(a_Enchantments, 2, enchBlastProtection, 2); } else if ((a_EnchantmentLevel >= 5) && (a_EnchantmentLevel <= 17)) { AddEnchantmentWeightToVector(a_Enchantments, 2, enchBlastProtection, 1); } // Projectile Protection if ((a_EnchantmentLevel >= 21) && (a_EnchantmentLevel <= 36)) { AddEnchantmentWeightToVector(a_Enchantments, 5, enchProjectileProtection, 4); } else if ((a_EnchantmentLevel >= 15) && (a_EnchantmentLevel <= 30)) { AddEnchantmentWeightToVector(a_Enchantments, 5, enchProjectileProtection, 3); } else if ((a_EnchantmentLevel >= 9) && (a_EnchantmentLevel <= 24)) { AddEnchantmentWeightToVector(a_Enchantments, 5, enchProjectileProtection, 2); } else if ((a_EnchantmentLevel >= 3) && (a_EnchantmentLevel <= 18)) { AddEnchantmentWeightToVector(a_Enchantments, 5, enchProjectileProtection, 1); } // Thorns if ((a_EnchantmentLevel >= 50) && (a_EnchantmentLevel <= 100)) { AddEnchantmentWeightToVector(a_Enchantments, 1, enchThorns, 3); } else if ((a_EnchantmentLevel >= 30) && (a_EnchantmentLevel <= 80)) { AddEnchantmentWeightToVector(a_Enchantments, 1, enchThorns, 2); } else if ((a_EnchantmentLevel >= 10) && (a_EnchantmentLevel <= 60)) { AddEnchantmentWeightToVector(a_Enchantments, 1, enchThorns, 1); } if (ItemCategory::IsHelmet(a_ItemType)) { // Respiration if ((a_EnchantmentLevel >= 30) && (a_EnchantmentLevel <= 60)) { AddEnchantmentWeightToVector(a_Enchantments, 2, enchRespiration, 3); } else if ((a_EnchantmentLevel >= 20) && (a_EnchantmentLevel <= 50)) { AddEnchantmentWeightToVector(a_Enchantments, 2, enchRespiration, 2); } else if ((a_EnchantmentLevel >= 10) && (a_EnchantmentLevel <= 40)) { AddEnchantmentWeightToVector(a_Enchantments, 2, enchRespiration, 1); } // Aqua Affinity if ((a_EnchantmentLevel >= 1) && (a_EnchantmentLevel <= 41)) { AddEnchantmentWeightToVector(a_Enchantments, 2, enchAquaAffinity, 1); } } else if (ItemCategory::IsBoots(a_ItemType)) { // Feather Fall if ((a_EnchantmentLevel >= 23) && (a_EnchantmentLevel <= 33)) { AddEnchantmentWeightToVector(a_Enchantments, 5, enchFeatherFalling, 4); } else if ((a_EnchantmentLevel >= 17) && (a_EnchantmentLevel <= 27)) { AddEnchantmentWeightToVector(a_Enchantments, 5, enchFeatherFalling, 3); } else if ((a_EnchantmentLevel >= 11) && (a_EnchantmentLevel <= 21)) { AddEnchantmentWeightToVector(a_Enchantments, 5, enchFeatherFalling, 2); } else if ((a_EnchantmentLevel >= 5) && (a_EnchantmentLevel <= 15)) { AddEnchantmentWeightToVector(a_Enchantments, 5, enchFeatherFalling, 1); } // Depth Strider if ((a_EnchantmentLevel >= 30) && (a_EnchantmentLevel <= 45)) { AddEnchantmentWeightToVector(a_Enchantments, 2, enchDepthStrider, 3); } else if ((a_EnchantmentLevel >= 20) && (a_EnchantmentLevel <= 35)) { AddEnchantmentWeightToVector(a_Enchantments, 2, enchDepthStrider, 2); } else if ((a_EnchantmentLevel >= 10) && (a_EnchantmentLevel <= 25)) { AddEnchantmentWeightToVector(a_Enchantments, 2, enchDepthStrider, 1); } } } else if (a_ItemType == E_ITEM_BOW) { // Power if ((a_EnchantmentLevel >= 31) && (a_EnchantmentLevel <= 46)) { AddEnchantmentWeightToVector(a_Enchantments, 10, enchPower, 4); } else if ((a_EnchantmentLevel >= 21) && (a_EnchantmentLevel <= 36)) { AddEnchantmentWeightToVector(a_Enchantments, 10, enchPower, 3); } else if ((a_EnchantmentLevel >= 11) && (a_EnchantmentLevel <= 26)) { AddEnchantmentWeightToVector(a_Enchantments, 10, enchPower, 2); } else if ((a_EnchantmentLevel >= 1) && (a_EnchantmentLevel <= 16)) { AddEnchantmentWeightToVector(a_Enchantments, 10, enchPower, 1); } // Punch if ((a_EnchantmentLevel >= 32) && (a_EnchantmentLevel <= 57)) { AddEnchantmentWeightToVector(a_Enchantments, 2, enchPunch, 2); } else if ((a_EnchantmentLevel >= 12) && (a_EnchantmentLevel <= 37)) { AddEnchantmentWeightToVector(a_Enchantments, 2, enchPunch, 1); } // Flame and Infinity if ((a_EnchantmentLevel >= 20) && (a_EnchantmentLevel <= 50)) { AddEnchantmentWeightToVector(a_Enchantments, 2, enchFlame, 1); AddEnchantmentWeightToVector(a_Enchantments, 1, enchInfinity, 1); } } else if (a_ItemType == E_ITEM_FISHING_ROD) { // Luck of the Sea and Lure if ((a_EnchantmentLevel >= 33) && (a_EnchantmentLevel <= 83)) { AddEnchantmentWeightToVector(a_Enchantments, 1, enchLuckOfTheSea, 3); AddEnchantmentWeightToVector(a_Enchantments, 1, enchLure, 3); } else if ((a_EnchantmentLevel >= 24) && (a_EnchantmentLevel <= 74)) { AddEnchantmentWeightToVector(a_Enchantments, 1, enchLuckOfTheSea, 2); AddEnchantmentWeightToVector(a_Enchantments, 1, enchLure, 2); } else if ((a_EnchantmentLevel >= 15) && (a_EnchantmentLevel <= 65)) { AddEnchantmentWeightToVector(a_Enchantments, 1, enchLuckOfTheSea, 1); AddEnchantmentWeightToVector(a_Enchantments, 1, enchLure, 1); } } else if (a_ItemType == E_ITEM_BOOK) { // All Enchantments // Sharpness if ((a_EnchantmentLevel >= 34) && (a_EnchantmentLevel <= 54)) { AddEnchantmentWeightToVector(a_Enchantments, 10, enchSharpness, 4); } else if ((a_EnchantmentLevel >= 23) && (a_EnchantmentLevel <= 43)) { AddEnchantmentWeightToVector(a_Enchantments, 10, enchSharpness, 3); } else if ((a_EnchantmentLevel >= 12) && (a_EnchantmentLevel <= 32)) { AddEnchantmentWeightToVector(a_Enchantments, 10, enchSharpness, 2); } else if ((a_EnchantmentLevel >= 1) && (a_EnchantmentLevel <= 21)) { AddEnchantmentWeightToVector(a_Enchantments, 10, enchSharpness, 1); } // Smite if ((a_EnchantmentLevel >= 29) && (a_EnchantmentLevel <= 49)) { AddEnchantmentWeightToVector(a_Enchantments, 5, enchSmite, 4); } else if ((a_EnchantmentLevel >= 21) && (a_EnchantmentLevel <= 41)) { AddEnchantmentWeightToVector(a_Enchantments, 5, enchSmite, 3); } else if ((a_EnchantmentLevel >= 13) && (a_EnchantmentLevel <= 33)) { AddEnchantmentWeightToVector(a_Enchantments, 5, enchSmite, 2); } else if ((a_EnchantmentLevel >= 5) && (a_EnchantmentLevel <= 25)) { AddEnchantmentWeightToVector(a_Enchantments, 5, enchSmite, 1); } // Bane of Arthropods if ((a_EnchantmentLevel >= 29) && (a_EnchantmentLevel <= 49)) { AddEnchantmentWeightToVector(a_Enchantments, 5, enchBaneOfArthropods, 4); } else if ((a_EnchantmentLevel >= 21) && (a_EnchantmentLevel <= 41)) { AddEnchantmentWeightToVector(a_Enchantments, 5, enchBaneOfArthropods, 3); } else if ((a_EnchantmentLevel >= 13) && (a_EnchantmentLevel <= 33)) { AddEnchantmentWeightToVector(a_Enchantments, 5, enchBaneOfArthropods, 2); } else if ((a_EnchantmentLevel >= 5) && (a_EnchantmentLevel <= 25)) { AddEnchantmentWeightToVector(a_Enchantments, 5, enchBaneOfArthropods, 1); } // Knockback if ((a_EnchantmentLevel >= 25) && (a_EnchantmentLevel <= 75)) { AddEnchantmentWeightToVector(a_Enchantments, 5, enchKnockback, 2); } else if ((a_EnchantmentLevel >= 5) && (a_EnchantmentLevel <= 55)) { AddEnchantmentWeightToVector(a_Enchantments, 5, enchKnockback, 1); } // Fire Aspect if ((a_EnchantmentLevel >= 30) && (a_EnchantmentLevel <= 80)) { AddEnchantmentWeightToVector(a_Enchantments, 2, enchFireAspect, 2); } else if ((a_EnchantmentLevel >= 10) && (a_EnchantmentLevel <= 60)) { AddEnchantmentWeightToVector(a_Enchantments, 2, enchFireAspect, 1); } // Looting if ((a_EnchantmentLevel >= 33) && (a_EnchantmentLevel <= 83)) { AddEnchantmentWeightToVector(a_Enchantments, 2, enchLooting, 3); } else if ((a_EnchantmentLevel >= 24) && (a_EnchantmentLevel <= 74)) { AddEnchantmentWeightToVector(a_Enchantments, 2, enchLooting, 2); } else if ((a_EnchantmentLevel >= 15) && (a_EnchantmentLevel <= 65)) { AddEnchantmentWeightToVector(a_Enchantments, 2, enchLooting, 1); } // Efficiency if ((a_EnchantmentLevel >= 31) && (a_EnchantmentLevel <= 81)) { AddEnchantmentWeightToVector(a_Enchantments, 10, enchEfficiency, 4); } else if ((a_EnchantmentLevel >= 21) && (a_EnchantmentLevel <= 71)) { AddEnchantmentWeightToVector(a_Enchantments, 10, enchEfficiency, 3); } else if ((a_EnchantmentLevel >= 11) && (a_EnchantmentLevel <= 61)) { AddEnchantmentWeightToVector(a_Enchantments, 10, enchEfficiency, 2); } else if ((a_EnchantmentLevel >= 1) && (a_EnchantmentLevel <= 51)) { AddEnchantmentWeightToVector(a_Enchantments, 10, enchEfficiency, 1); } // Silk Touch if ((a_EnchantmentLevel >= 15) && (a_EnchantmentLevel <= 65)) { AddEnchantmentWeightToVector(a_Enchantments, 1, enchSilkTouch, 1); } // Fortune if ((a_EnchantmentLevel >= 33) && (a_EnchantmentLevel <= 83)) { AddEnchantmentWeightToVector(a_Enchantments, 2, enchFortune, 3); } else if ((a_EnchantmentLevel >= 24) && (a_EnchantmentLevel <= 74)) { AddEnchantmentWeightToVector(a_Enchantments, 2, enchFortune, 2); } else if ((a_EnchantmentLevel >= 15) && (a_EnchantmentLevel <= 65)) { AddEnchantmentWeightToVector(a_Enchantments, 2, enchFortune, 1); } // Protection if ((a_EnchantmentLevel >= 34) && (a_EnchantmentLevel <= 54)) { AddEnchantmentWeightToVector(a_Enchantments, 10, enchProtection, 4); } else if ((a_EnchantmentLevel >= 23) && (a_EnchantmentLevel <= 43)) { AddEnchantmentWeightToVector(a_Enchantments, 10, enchProtection, 3); } else if ((a_EnchantmentLevel >= 12) && (a_EnchantmentLevel <= 32)) { AddEnchantmentWeightToVector(a_Enchantments, 10, enchProtection, 2); } else if ((a_EnchantmentLevel >= 1) && (a_EnchantmentLevel <= 21)) { AddEnchantmentWeightToVector(a_Enchantments, 10, enchProtection, 1); } // Fire Protection if ((a_EnchantmentLevel >= 34) && (a_EnchantmentLevel <= 46)) { AddEnchantmentWeightToVector(a_Enchantments, 5, enchFireProtection, 4); } else if ((a_EnchantmentLevel >= 26) && (a_EnchantmentLevel <= 38)) { AddEnchantmentWeightToVector(a_Enchantments, 5, enchFireProtection, 3); } else if ((a_EnchantmentLevel >= 18) && (a_EnchantmentLevel <= 30)) { AddEnchantmentWeightToVector(a_Enchantments, 5, enchFireProtection, 2); } else if ((a_EnchantmentLevel >= 10) && (a_EnchantmentLevel <= 22)) { AddEnchantmentWeightToVector(a_Enchantments, 5, enchFireProtection, 1); } // Blast Protection if ((a_EnchantmentLevel >= 29) && (a_EnchantmentLevel <= 41)) { AddEnchantmentWeightToVector(a_Enchantments, 2, enchBlastProtection, 4); } else if ((a_EnchantmentLevel >= 21) && (a_EnchantmentLevel <= 33)) { AddEnchantmentWeightToVector(a_Enchantments, 2, enchBlastProtection, 3); } else if ((a_EnchantmentLevel >= 13) && (a_EnchantmentLevel <= 25)) { AddEnchantmentWeightToVector(a_Enchantments, 2, enchBlastProtection, 2); } else if ((a_EnchantmentLevel >= 5) && (a_EnchantmentLevel <= 17)) { AddEnchantmentWeightToVector(a_Enchantments, 2, enchBlastProtection, 1); } // Projectile Protection if ((a_EnchantmentLevel >= 21) && (a_EnchantmentLevel <= 36)) { AddEnchantmentWeightToVector(a_Enchantments, 5, enchProjectileProtection, 4); } else if ((a_EnchantmentLevel >= 15) && (a_EnchantmentLevel <= 30)) { AddEnchantmentWeightToVector(a_Enchantments, 5, enchProjectileProtection, 3); } else if ((a_EnchantmentLevel >= 9) && (a_EnchantmentLevel <= 24)) { AddEnchantmentWeightToVector(a_Enchantments, 5, enchProjectileProtection, 2); } else if ((a_EnchantmentLevel >= 3) && (a_EnchantmentLevel <= 18)) { AddEnchantmentWeightToVector(a_Enchantments, 5, enchProjectileProtection, 1); } // Thorns if ((a_EnchantmentLevel >= 50) && (a_EnchantmentLevel <= 100)) { AddEnchantmentWeightToVector(a_Enchantments, 1, enchThorns, 3); } else if ((a_EnchantmentLevel >= 30) && (a_EnchantmentLevel <= 80)) { AddEnchantmentWeightToVector(a_Enchantments, 1, enchThorns, 2); } else if ((a_EnchantmentLevel >= 10) && (a_EnchantmentLevel <= 60)) { AddEnchantmentWeightToVector(a_Enchantments, 1, enchThorns, 1); } // Respiration if ((a_EnchantmentLevel >= 30) && (a_EnchantmentLevel <= 60)) { AddEnchantmentWeightToVector(a_Enchantments, 2, enchRespiration, 3); } else if ((a_EnchantmentLevel >= 20) && (a_EnchantmentLevel <= 50)) { AddEnchantmentWeightToVector(a_Enchantments, 2, enchRespiration, 2); } else if ((a_EnchantmentLevel >= 10) && (a_EnchantmentLevel <= 40)) { AddEnchantmentWeightToVector(a_Enchantments, 2, enchRespiration, 1); } // Aqua Affinity if ((a_EnchantmentLevel >= 1) && (a_EnchantmentLevel <= 41)) { AddEnchantmentWeightToVector(a_Enchantments, 2, enchAquaAffinity, 1); } // Feather Fall if ((a_EnchantmentLevel >= 23) && (a_EnchantmentLevel <= 33)) { AddEnchantmentWeightToVector(a_Enchantments, 5, enchFeatherFalling, 4); } else if ((a_EnchantmentLevel >= 17) && (a_EnchantmentLevel <= 27)) { AddEnchantmentWeightToVector(a_Enchantments, 5, enchFeatherFalling, 3); } else if ((a_EnchantmentLevel >= 11) && (a_EnchantmentLevel <= 21)) { AddEnchantmentWeightToVector(a_Enchantments, 5, enchFeatherFalling, 2); } else if ((a_EnchantmentLevel >= 5) && (a_EnchantmentLevel <= 15)) { AddEnchantmentWeightToVector(a_Enchantments, 5, enchFeatherFalling, 1); } // Power if ((a_EnchantmentLevel >= 31) && (a_EnchantmentLevel <= 46)) { AddEnchantmentWeightToVector(a_Enchantments, 10, enchPower, 4); } else if ((a_EnchantmentLevel >= 21) && (a_EnchantmentLevel <= 36)) { AddEnchantmentWeightToVector(a_Enchantments, 10, enchPower, 3); } else if ((a_EnchantmentLevel >= 11) && (a_EnchantmentLevel <= 26)) { AddEnchantmentWeightToVector(a_Enchantments, 10, enchPower, 2); } else if ((a_EnchantmentLevel >= 1) && (a_EnchantmentLevel <= 16)) { AddEnchantmentWeightToVector(a_Enchantments, 10, enchPower, 1); } // Punch if ((a_EnchantmentLevel >= 32) && (a_EnchantmentLevel <= 57)) { AddEnchantmentWeightToVector(a_Enchantments, 2, enchPunch, 2); } else if ((a_EnchantmentLevel >= 12) && (a_EnchantmentLevel <= 37)) { AddEnchantmentWeightToVector(a_Enchantments, 2, enchPunch, 1); } // Flame and Infinity if ((a_EnchantmentLevel >= 20) && (a_EnchantmentLevel <= 50)) { AddEnchantmentWeightToVector(a_Enchantments, 2, enchFlame, 1); AddEnchantmentWeightToVector(a_Enchantments, 1, enchInfinity, 1); } // Luck of the Sea and Lure if ((a_EnchantmentLevel >= 33) && (a_EnchantmentLevel <= 83)) { AddEnchantmentWeightToVector(a_Enchantments, 1, enchLuckOfTheSea, 3); AddEnchantmentWeightToVector(a_Enchantments, 1, enchLure, 3); } else if ((a_EnchantmentLevel >= 24) && (a_EnchantmentLevel <= 74)) { AddEnchantmentWeightToVector(a_Enchantments, 1, enchLuckOfTheSea, 2); AddEnchantmentWeightToVector(a_Enchantments, 1, enchLure, 2); } else if ((a_EnchantmentLevel >= 15) && (a_EnchantmentLevel <= 65)) { AddEnchantmentWeightToVector(a_Enchantments, 1, enchLuckOfTheSea, 1); AddEnchantmentWeightToVector(a_Enchantments, 1, enchLure, 1); } } // Unbreaking if ((a_EnchantmentLevel >= 21) && (a_EnchantmentLevel <= 71)) { AddEnchantmentWeightToVector(a_Enchantments, 5, enchUnbreaking, 3); } else if ((a_EnchantmentLevel >= 13) && (a_EnchantmentLevel <= 63)) { AddEnchantmentWeightToVector(a_Enchantments, 5, enchUnbreaking, 2); } else if ((a_EnchantmentLevel >= 5) && (a_EnchantmentLevel <= 55)) { AddEnchantmentWeightToVector(a_Enchantments, 5, enchUnbreaking, 1); } } void cEnchantments::AddEnchantmentWeightToVector(cWeightedEnchantments & a_Enchantments, int a_Weight, int a_EnchantmentID, unsigned int a_EnchantmentLevel) { cWeightedEnchantment weightedenchantment; weightedenchantment.m_Weight = a_Weight; cEnchantments enchantment; enchantment.SetLevel(a_EnchantmentID, a_EnchantmentLevel); weightedenchantment.m_Enchantments = enchantment; a_Enchantments.push_back(weightedenchantment); } void cEnchantments::RemoveEnchantmentWeightFromVector(cWeightedEnchantments & a_Enchantments, int a_EnchantmentID) { for (cWeightedEnchantments::iterator it = a_Enchantments.begin(); it != a_Enchantments.end(); ++it) { if ((*it).m_Enchantments.GetLevel(a_EnchantmentID) > 0) { a_Enchantments.erase(it); break; } } } void cEnchantments::RemoveEnchantmentWeightFromVector(cWeightedEnchantments & a_Enchantments, const cEnchantments & a_Enchantment) { for (cWeightedEnchantments::iterator it = a_Enchantments.begin(); it != a_Enchantments.end(); ++it) { if ((*it).m_Enchantments == a_Enchantment) { a_Enchantments.erase(it); break; } } } void cEnchantments::CheckEnchantmentConflictsFromVector( cWeightedEnchantments & a_Enchantments, const cEnchantments & a_FirstEnchantment ) { if (a_FirstEnchantment.GetLevel(cEnchantments::enchProtection) > 0) { RemoveEnchantmentWeightFromVector(a_Enchantments, cEnchantments::enchFireProtection); RemoveEnchantmentWeightFromVector(a_Enchantments, cEnchantments::enchBlastProtection); RemoveEnchantmentWeightFromVector(a_Enchantments, cEnchantments::enchProjectileProtection); } else if (a_FirstEnchantment.GetLevel(cEnchantments::enchFireProtection) > 0) { RemoveEnchantmentWeightFromVector(a_Enchantments, cEnchantments::enchProtection); RemoveEnchantmentWeightFromVector(a_Enchantments, cEnchantments::enchBlastProtection); RemoveEnchantmentWeightFromVector(a_Enchantments, cEnchantments::enchProjectileProtection); } else if (a_FirstEnchantment.GetLevel(cEnchantments::enchBlastProtection) > 0) { RemoveEnchantmentWeightFromVector(a_Enchantments, cEnchantments::enchProtection); RemoveEnchantmentWeightFromVector(a_Enchantments, cEnchantments::enchFireProtection); RemoveEnchantmentWeightFromVector(a_Enchantments, cEnchantments::enchProjectileProtection); } else if (a_FirstEnchantment.GetLevel(cEnchantments::enchProjectileProtection) > 0) { RemoveEnchantmentWeightFromVector(a_Enchantments, cEnchantments::enchProtection); RemoveEnchantmentWeightFromVector(a_Enchantments, cEnchantments::enchFireProtection); RemoveEnchantmentWeightFromVector(a_Enchantments, cEnchantments::enchBlastProtection); } else if (a_FirstEnchantment.GetLevel(cEnchantments::enchSharpness) > 0) { RemoveEnchantmentWeightFromVector(a_Enchantments, cEnchantments::enchSmite); RemoveEnchantmentWeightFromVector(a_Enchantments, cEnchantments::enchBaneOfArthropods); } else if (a_FirstEnchantment.GetLevel(cEnchantments::enchSmite) > 0) { RemoveEnchantmentWeightFromVector(a_Enchantments, cEnchantments::enchSharpness); RemoveEnchantmentWeightFromVector(a_Enchantments, cEnchantments::enchBaneOfArthropods); } else if (a_FirstEnchantment.GetLevel(cEnchantments::enchBaneOfArthropods) > 0) { RemoveEnchantmentWeightFromVector(a_Enchantments, cEnchantments::enchSharpness); RemoveEnchantmentWeightFromVector(a_Enchantments, cEnchantments::enchSmite); } else if (a_FirstEnchantment.GetLevel(cEnchantments::enchSilkTouch) > 0) { RemoveEnchantmentWeightFromVector(a_Enchantments, cEnchantments::enchFortune); } else if (a_FirstEnchantment.GetLevel(cEnchantments::enchFortune) > 0) { RemoveEnchantmentWeightFromVector(a_Enchantments, cEnchantments::enchSilkTouch); } } cEnchantments cEnchantments::GetRandomEnchantmentFromVector(const cWeightedEnchantments & a_Enchantments, MTRand & a_Random) { int AllWeights = 0; for (const auto & Enchantment: a_Enchantments) { AllWeights += Enchantment.m_Weight; } int RandomNumber = a_Random.RandInt(AllWeights - 1); for (const auto & Enchantment: a_Enchantments) { RandomNumber -= Enchantment.m_Weight; if (RandomNumber < 0) { return Enchantment.m_Enchantments; } } return cEnchantments(); } cEnchantments cEnchantments::SelectEnchantmentFromVector(const cWeightedEnchantments & a_Enchantments, int a_Seed) { // Sum up all the enchantments' weights: int AllWeights = 0; for (const auto & Enchantment : a_Enchantments) { AllWeights += Enchantment.m_Weight; } // If there's no weight for any of the enchantments, return an empty enchantment if (AllWeights <= 0) { return cEnchantments(); } // Pick a random enchantment: cNoise Noise(a_Seed); int RandomNumber = Noise.IntNoise1DInt(AllWeights) / 7 % AllWeights; for (const auto & Enchantment : a_Enchantments) { RandomNumber -= Enchantment.m_Weight; if (RandomNumber <= 0) { return Enchantment.m_Enchantments; } } // No enchantment picked, return an empty one (we probably shouldn't ever get here): return cEnchantments(); } ================================================ FILE: src/Enchantments.h ================================================ // Enchantments.h // Declares the cEnchantments class representing a storage for item enchantments and stored-enchantments #pragma once #include "Defines.h" #include "FastRandom.h" #include "WorldStorage/EnchantmentSerializer.h" // fwd: "WorldStorage/FastNBT.h" class cFastNBTWriter; class cParsedNBT; // fwd: struct cWeightedEnchantment; typedef std::vector cWeightedEnchantments; /** Class that stores item enchantments or stored-enchantments The enchantments may be serialized to a stringspec and read back from such stringspec. The format for the stringspec is "id=lvl;id=lvl;id=lvl...", with an optional semicolon at the end, mapping each enchantment's id onto its level. ID may be either a number or the enchantment name. Level value of 0 means no such enchantment, and it will not be stored in the m_Enchantments. Serialization will never put zero-level enchantments into the stringspec and will always use numeric IDs. */ // tolua_begin class cEnchantments { public: /** Individual enchantment IDs, corresponding to their NBT IDs: https://minecraft.wiki/w/Data_values#Enchantment_IDs */ enum eEnchantment { // Currently missing: Frost walker, curse of binding, sweeping edge, mending, and curse of vanishing. enchProtection = 0, enchFireProtection = 1, enchFeatherFalling = 2, enchBlastProtection = 3, enchProjectileProtection = 4, enchRespiration = 5, enchAquaAffinity = 6, enchThorns = 7, enchDepthStrider = 8, enchSharpness = 16, enchSmite = 17, enchBaneOfArthropods = 18, enchKnockback = 19, enchFireAspect = 20, enchLooting = 21, enchEfficiency = 32, enchSilkTouch = 33, enchUnbreaking = 34, enchFortune = 35, enchPower = 48, enchPunch = 49, enchFlame = 50, enchInfinity = 51, enchLuckOfTheSea = 61, enchLure = 62, } ; /** Creates an empty enchantments container */ cEnchantments(void); /** Creates an enchantments container filled with enchantments parsed from stringspec */ cEnchantments(const AString & a_StringSpec); /** Adds the enchantments contained in a_Other into this object. Existing enchantments are preserved, unless a_Other specifies a different level, in which case the level is changed to the a_Other's one. */ void Add(const cEnchantments & a_Other); /** Adds enchantments in the stringspec; if a specified enchantment already exists, overwrites it */ void AddFromString(const AString & a_StringSpec); /** Get the count of enchantments */ size_t Count(void) const; /** Serializes all the enchantments into a string */ AString ToString(void) const; /** Returns the level for the specified enchantment; 0 if not stored */ unsigned int GetLevel(int a_EnchantmentID) const; /** Sets the level for the specified enchantment, adding it if not stored before or removing it if level <= 0 */ void SetLevel(int a_EnchantmentID, unsigned int a_Level); /** Removes all enchantments */ void Clear(void); /** Returns true if there are no enchantments */ bool IsEmpty(void) const; /** Returns true if the given enchantment could be legally added to this object. Note that adding the enchantment may not actually increase the level. */ bool CanAddEnchantment(int a_EnchantmentID) const; /** Converts enchantment name or ID (number in string) to the numeric representation; returns -1 if enchantment name not found; case insensitive */ static int StringToEnchantmentID(const AString & a_EnchantmentName); /** Returns true if a_Other contains exactly the same enchantments and levels */ bool operator ==(const cEnchantments & a_Other) const; // tolua_end /** Get the XP cost multiplier for the enchantment (for anvils). If FromBook is true, then this function returns the XP multiplier if the enchantment is coming from a book, otherwise it returns the normal item multiplier. */ static int GetXPCostMultiplier(int a_EnchantmentID, bool FromBook); /** Get the maximum level the enchantment can have */ static unsigned int GetLevelCap(int a_EnchantmentID); /** Add enchantment weights from item to the vector */ static void AddItemEnchantmentWeights(cWeightedEnchantments & a_Enchantments, short a_ItemType, unsigned a_EnchantmentLevel); /** Add a enchantment with weight to the vector */ static void AddEnchantmentWeightToVector(cWeightedEnchantments & a_Enchantments, int a_Weight, int a_EnchantmentID, unsigned int a_EnchantmentLevel); /** Remove the entire enchantment (with weight) from the vector */ static void RemoveEnchantmentWeightFromVector(cWeightedEnchantments & a_Enchantments, int a_EnchantmentID); /** Remove the entire enchantment (with weight) from the vector */ static void RemoveEnchantmentWeightFromVector(cWeightedEnchantments & a_Enchantments, const cEnchantments & a_Enchantment); /** Check enchantment conflicts from enchantments from the vector */ static void CheckEnchantmentConflictsFromVector(cWeightedEnchantments & a_Enchantments, const cEnchantments & a_FirstEnchantment); /** Gets random enchantment from Vector and returns it, with randomness derived from the provided PRNG. */ static cEnchantments GetRandomEnchantmentFromVector(const cWeightedEnchantments & a_Enchantments, MTRand & a_Random); /** Selects one enchantment from a Vector using cNoise. Mostly used for generators. Uses the enchantments' weights for the random distribution. If a_Enchantments is empty, returns an empty enchantment. */ static cEnchantments SelectEnchantmentFromVector(const cWeightedEnchantments & a_Enchantments, int a_Seed); /** Returns true if a_Other doesn't contain exactly the same enchantments and levels */ bool operator !=(const cEnchantments & a_Other) const; /** Writes the enchantments into the specified NBT writer; begins with the LIST tag of the specified name ("ench" or "StoredEnchantments") */ friend void EnchantmentSerializer::WriteToNBTCompound(const cEnchantments & a_Enchantments, cFastNBTWriter & a_Writer, const AString & a_ListTagName); /** Reads the enchantments from the specified NBT list tag (ench or StoredEnchantments) */ friend void EnchantmentSerializer::ParseFromNBT(cEnchantments & a_Enchantments, const cParsedNBT & a_NBT, int a_EnchListTagIdx); protected: /** Maps enchantment ID -> enchantment level */ typedef std::map cMap; /** Currently stored enchantments */ cMap m_Enchantments; public: /** Make this class iterable */ cMap::const_iterator begin() const { return m_Enchantments.begin(); } cMap::const_iterator end() const { return m_Enchantments.end(); } }; // tolua_export // Define the cWeightedEnchantment struct for the Enchanting System to store the EnchantmentWeights: struct cWeightedEnchantment { int m_Weight; cEnchantments m_Enchantments; }; ================================================ FILE: src/Endianness.h ================================================ #pragma once #include template using Bytes = std::array; // bit_cast used for going between ulong, float, etc. It's a new C++20 feature #ifdef __cpp_lib_bit_cast #include using std::bit_cast; // Fallback in case we're using C++17 #else // bit-for-bit convert one type to another. In C++ the only non-UB way to do this is *memcpy*. Nearly every other // option is a strict aliasing violation. template std::enable_if_t< sizeof(To) == sizeof(From), To> bit_cast(const From &src) noexcept { To dst; std::memcpy(&dst, &src, sizeof(To)); return dst; } #endif /** Converts a 16-bit host integer or float value to bytes in big-endian (Network) order. @tparam Value The host 16-bit type (Int16, UInt16). Usually inferred. @param a_Value The input integer or float value. @return The resulting bytes. */ template = true> inline Bytes HostToNetwork(Value a_Value) { UInt16 Bits = bit_cast(a_Value); return { std::byte(Bits >> 8), std::byte(Bits) }; } /** Converts a 32-bit host integer or float value to bytes in big-endian (Network) order. @tparam Value The host 32-bit type (Int32, UInt32, float). Usually inferred. @param a_Value The input integer or float value. @return The resulting bytes. */ template = true> inline Bytes HostToNetwork(Value a_Value) { UInt32 Bits = bit_cast(a_Value); return { std::byte(Bits >> 24), std::byte(Bits >> 16), std::byte(Bits >> 8), std::byte(Bits) }; } /** Converts a 64-bit host integer or float value to bytes in big-endian (Network) order. @tparam Value The host 64-bit type (Int64, UInt64, double). Usually inferred. @param a_Value The input integer or float value. @return The resulting bytes. */ template = true> inline Bytes HostToNetwork(Value a_Value) { UInt64 Bits = bit_cast(a_Value); return { std::byte(Bits >> 56), std::byte(Bits >> 48), std::byte(Bits >> 40), std::byte(Bits >> 32), std::byte(Bits >> 24), std::byte(Bits >> 16), std::byte(Bits >> 8), std::byte(Bits) }; } /** Reads a 16-bit integer or float value from big-endian (Network) bytes. @tparam Value The desired 16-bit type (Int16, UInt16) @param a_Value The input bytes. @return The resulting integer or float value. */ template = true> inline Value NetworkToHost(Bytes a_Value) { UInt16 val = UInt16( UInt16(a_Value[0]) << 8 | UInt16(a_Value[1])); return bit_cast(val); } /** Reads a 32-bit integer or float value from big-endian (Network) bytes. @tparam Value The desired 32-bit type (Int32, UInt32, float) @param a_Value The input bytes. @return The resulting integer or float value. */ template = true> inline Value NetworkToHost(Bytes a_Value) { UInt32 val = UInt32( UInt32(a_Value[0]) << 24 | UInt32(a_Value[1]) << 16 | UInt32(a_Value[2]) << 8 | UInt32(a_Value[3])); return bit_cast(val); } /** Reads a 64-bit integer or float value from big-endian (Network) bytes. @tparam Value The desired 64-bit type (Int64, UInt64, double) @param a_Value The input bytes. @return The resulting integer or float value. */ template = true> inline Value NetworkToHost(Bytes a_Value) { UInt64 val = UInt64( UInt64(a_Value[0]) << 56 | UInt64(a_Value[1]) << 48 | UInt64(a_Value[2]) << 40 | UInt64(a_Value[3]) << 32 | UInt64(a_Value[4]) << 24 | UInt64(a_Value[5]) << 16 | UInt64(a_Value[6]) << 8 | UInt64(a_Value[7])); return bit_cast(val); } /** Reads an integer or float type from its big-endian (Network) bytes. @tparam Value The desired result type (Int16 / 32 / 64, UInt16 / 32 / 64, float, double). @param a_Mem A pointer to the first input byte. Length is inferred from the result type. @return The resulting integer or float value. Consider using NetworkToHost when the data is owned since it provides additional type safety (length is known). */ template inline Value NetworkBufToHost(const std::byte* a_Mem) { // Copy unfortunately needed to add the length information required by the rest of the API. // Gets completely optimised out in my testing. Bytes bytes; std::copy(a_Mem, a_Mem + sizeof(Value), bytes.begin()); return NetworkToHost(bytes); } ================================================ FILE: src/Entities/ArrowEntity.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "Player.h" #include "ArrowEntity.h" #include "../Chunk.h" #include "../Blocks/BlockButton.h" cArrowEntity::cArrowEntity(cEntity * a_Creator, Vector3d a_Pos, Vector3d a_Speed): Super(pkArrow, a_Creator, a_Pos, a_Speed, 0.5f, 0.5f), m_PickupState(psNoPickup), m_DamageCoeff(2), m_IsCritical(false), m_Timer(0), m_bIsCollected(false) { SetMass(0.1); SetGravity(-20.0f); FLOGD("Created arrow {0} with speed {1:.02f} and rot {{{2:.02f}, {3:.02f}}}", m_UniqueID, GetSpeed(), GetYaw(), GetPitch() ); } cArrowEntity::cArrowEntity(cPlayer & a_Player, double a_Force) : cArrowEntity(&a_Player, a_Player.GetThrowStartPos(), a_Player.GetThrowSpeed(a_Force * 1.5 * 20)) { m_IsCritical = a_Force >= 1; m_PickupState = a_Player.IsGameModeCreative() ? psInCreative : psInSurvivalOrCreative; } bool cArrowEntity::CanPickup(const cPlayer & a_Player) const { switch (m_PickupState) { case psNoPickup: return false; case psInSurvivalOrCreative: return (a_Player.IsGameModeSurvival() || a_Player.IsGameModeCreative()); case psInCreative: return a_Player.IsGameModeCreative(); } UNREACHABLE("Unsupported arrow pickup state"); } void cArrowEntity::OnHitSolidBlock(Vector3d a_HitPos, eBlockFace a_HitFace) { // Save the direction we're going in before Super resets it auto Speed = GetSpeed(); Speed.Normalize(); /* The line tracer returns the arrow hit position located on the face of a block; if the arrow hit a block at -5, 95, -5 then a_HitPos would start off as -4, 95.5, -4.1, i.e. it collided with the X face. First we subtract a bit of speed vector so it doesn't appear black clientside. Then we add a bit of speed vector to make a_HitPos -4.0001, 95.5, -4.1 and floor to get exactly -5, 95, -5 which is stored in m_HitBlockPos. */ // Shift the arrow's position slightly back so that less than 50% of the hitbox // is in the block. Otherwise the arrow can appear black Super::OnHitSolidBlock(a_HitPos - (Speed / 100), a_HitFace); // Nudge into the block a tiny bit according to its direction of travel // Floor to give the coordinates of the block it crashed into m_HitBlockPos = (a_HitPos + (Speed / 100000)).Floor(); // Broadcast arrow hit sound m_World->BroadcastSoundEffect("entity.arrow.hit", m_HitBlockPos, 0.5f, static_cast(0.75 + (static_cast((GetUniqueID() * 23) % 32)) / 64)); // Trigger any buttons that were hit // Wooden buttons will be depressed by the arrow cBlockButtonHandler::OnArrowHit(*m_World, m_HitBlockPos, a_HitFace); if ((m_World->GetBlock(m_HitBlockPos) == E_BLOCK_TNT) && IsOnFire()) { m_World->SetBlock(m_HitBlockPos, E_BLOCK_AIR, 0); m_World->SpawnPrimedTNT(m_HitBlockPos); } } void cArrowEntity::OnHitEntity(cEntity & a_EntityHit, Vector3d a_HitPos) { Super::OnHitEntity(a_EntityHit, a_HitPos); int Damage = static_cast(GetSpeed().Length() / 20 * m_DamageCoeff + 0.5); if (m_IsCritical) { Damage += m_World->GetTickRandomNumber(Damage / 2 + 2); } unsigned int PowerLevel = m_CreatorData.m_Enchantments.GetLevel(cEnchantments::enchPower); if (PowerLevel > 0) { int ExtraDamage = static_cast(ceil(0.25 * (PowerLevel + 1))); Damage += ExtraDamage; } double Knockback = 10; unsigned int PunchLevel = m_CreatorData.m_Enchantments.GetLevel(cEnchantments::enchPunch); unsigned int PunchLevelMultiplier = 8; Knockback += PunchLevelMultiplier * PunchLevel; a_EntityHit.TakeDamage(dtRangedAttack, GetCreatorUniqueID(), Damage, Knockback); if (IsOnFire() && !a_EntityHit.IsInWater()) { a_EntityHit.StartBurning(100); } // Broadcast successful hit sound GetWorld()->BroadcastSoundEffect("entity.arrow.hit", GetPosition(), 0.5, static_cast(0.75 + (static_cast((GetUniqueID() * 23) % 32)) / 64)); Destroy(); } void cArrowEntity::CollectedBy(cPlayer & a_Dest) { if (m_IsInGround && !m_bIsCollected && CanPickup(a_Dest)) { // Do not add the arrow to the inventory when the player is in creative: if (!a_Dest.IsGameModeCreative()) { int NumAdded = a_Dest.GetInventory().AddItem(cItem(E_ITEM_ARROW)); if (NumAdded == 0) { // No space in the inventory return; } } GetWorld()->BroadcastCollectEntity(*this, a_Dest, 1); GetWorld()->BroadcastSoundEffect("entity.item.pickup", GetPosition(), 0.3f, (1.2f + (static_cast((GetUniqueID() * 23) % 32)) / 64)); m_bIsCollected = true; } } void cArrowEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { Super::Tick(a_Dt, a_Chunk); if (!IsTicking()) { // The base class tick destroyed us return; } m_Timer += a_Dt; if (m_bIsCollected) { if (m_Timer > std::chrono::milliseconds(500)) { Destroy(); return; } } else if (m_Timer > std::chrono::minutes(5)) { Destroy(); return; } if (m_IsInGround) { if (m_World->GetBlock(m_HitBlockPos) == E_BLOCK_AIR) // Block attached to was destroyed? { m_IsInGround = false; // Yes, begin simulating physics again } } else if (IsInWater()) // Arrow in water? { ApplyFriction(m_Speed, ARROW_WATER_FRICTION, static_cast(a_Dt.count())); // Yes, slow down arrow } } bool cArrowEntity::DoesPreventBlockPlacement(void) const { return false; } ================================================ FILE: src/Entities/ArrowEntity.h ================================================ // ArrowEntity.h // Declares the cArrowEntity representing the arrow that has been shot by the player or by a skeleton #pragma once #include "ProjectileEntity.h" // tolua_begin class cArrowEntity : public cProjectileEntity { // tolua_end using Super = cProjectileEntity; // tolua_begin public: /** Determines when the arrow can be picked up (depending on player gamemode). Corresponds to the MCA file "pickup" field */ enum ePickupState { psNoPickup = 0, psInSurvivalOrCreative = 1, psInCreative = 2, } ; // tolua_end static constexpr float ARROW_WATER_FRICTION = 50.0f; ///< Value used to calculate arrow speed in water CLASS_PROTODEF(cArrowEntity) /** Creates a new arrow with psNoPickup state and default damage modifier coeff */ cArrowEntity(cEntity * a_Creator, Vector3d a_Pos, Vector3d a_Speed); /** Creates a new arrow as shot by a player, initializes it from the player object */ cArrowEntity(cPlayer & a_Player, double a_Force); // tolua_begin /** Returns whether the arrow can be picked up by players */ ePickupState GetPickupState(void) const { return m_PickupState; } /** Sets a new pickup state */ void SetPickupState(ePickupState a_PickupState) { m_PickupState = a_PickupState; } /** Returns the damage modifier coeff. */ double GetDamageCoeff(void) const { return m_DamageCoeff; } /** Sets the damage modifier coeff */ void SetDamageCoeff(double a_DamageCoeff) { m_DamageCoeff = a_DamageCoeff; } /** Returns true if the specified player can pick the arrow up */ bool CanPickup(const cPlayer & a_Player) const; /** Returns true if the arrow is set as critical */ bool IsCritical(void) const { return m_IsCritical; } /** Sets the IsCritical flag */ void SetIsCritical(bool a_IsCritical) { m_IsCritical = a_IsCritical; } /** Gets the block arrow is in */ Vector3i GetBlockHit(void) const { return m_HitBlockPos; } // tolua_end /** Sets the block arrow is in. To be used by the MCA loader only! */ void SetBlockHit(const Vector3i & a_BlockHit) { m_HitBlockPos = a_BlockHit; } protected: /** Determines when the arrow can be picked up by players */ ePickupState m_PickupState; /** The coefficient applied to the damage that the arrow will deal, based on the bow enchantment. 2.0 for normal arrow */ double m_DamageCoeff; /** If true, the arrow deals more damage */ bool m_IsCritical; /** Timer for pickup collection animation or five minute timeout */ std::chrono::milliseconds m_Timer; /** If true, the arrow is in the process of being collected - don't go to anyone else */ bool m_bIsCollected; /** Stores the block position that arrow is lodged into, sets m_IsInGround to false if it becomes air */ Vector3i m_HitBlockPos; // cProjectileEntity overrides: virtual void OnHitSolidBlock(Vector3d a_HitPos, eBlockFace a_HitFace) override; virtual void OnHitEntity(cEntity & a_EntityHit, Vector3d a_HitPos) override; virtual void CollectedBy(cPlayer & a_Player) override; virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; // cEntity overrides: virtual bool DoesPreventBlockPlacement(void) const override; }; // tolua_export ================================================ FILE: src/Entities/Boat.cpp ================================================ // Boat.cpp // Implements the cBoat class representing a boat in the world #include "Globals.h" #include "Boat.h" #include "../BlockInfo.h" #include "../World.h" #include "../ClientHandle.h" #include "Player.h" class cBoatCollisionCallback { public: cBoatCollisionCallback(cBoat & a_Boat, cEntity * a_Attachee) : m_Boat(a_Boat), m_Attachee(a_Attachee) { } bool operator()(cEntity & a_Entity) { // Checks if boat is empty and if given entity is a mob: if ((m_Attachee == nullptr) && a_Entity.IsMob()) { // If so attach and stop iterating: a_Entity.AttachTo(m_Boat); return true; } return false; } protected: cBoat & m_Boat; cEntity * m_Attachee; }; cBoat::cBoat(Vector3d a_Pos, eMaterial a_Material) : Super(etBoat, a_Pos, 1.375f, 0.5625f), m_LastDamage(0), m_ForwardDirection(0), m_DamageTaken(0.0f), m_Material(a_Material), m_RightPaddleUsed(false), m_LeftPaddleUsed(false) { SetMass(20.0f); SetGravity(-16.0f); SetAirDrag(0.05f); SetMaxHealth(6); SetHealth(6); } void cBoat::SpawnOn(cClientHandle & a_ClientHandle) { a_ClientHandle.SendSpawnEntity(*this); a_ClientHandle.SendEntityMetadata(*this); // Boat colour } void cBoat::BroadcastMovementUpdate(const cClientHandle * a_Exclude) { // Cannot use super::BroadcastMovementUpdate here, broadcasting position when not // expected by the client breaks things. See https://github.com/cuberite/cuberite/pull/4488 // Process packet sending every two ticks: if ((GetWorld()->GetWorldTickAge() % 2_tick) != 0_tick) { return; } Vector3i Diff = (GetPosition() * 32.0).Floor() - (m_LastSentPosition * 32.0).Floor(); if (Diff.HasNonZeroLength()) // Have we moved? { m_World->BroadcastEntityPosition(*this, a_Exclude); m_LastSentPosition = GetPosition(); m_bDirtyOrientation = false; } } bool cBoat::DoTakeDamage(TakeDamageInfo & TDI) { m_LastDamage = 10; if (!Super::DoTakeDamage(TDI)) { return false; } m_World->BroadcastEntityMetadata(*this); if ((TDI.Attacker != nullptr) && (TDI.Attacker->IsPlayer())) { cPlayer * Destroyer = static_cast(TDI.Attacker); if (Destroyer->IsGameModeCreative()) { Destroy(); return true; } } if (GetHealth() <= 0) { if (TDI.Attacker != nullptr) { if (TDI.Attacker->IsPlayer()) { cItems Pickups; Pickups.Add(MaterialToItem(m_Material)); m_World->SpawnItemPickups(Pickups, GetPosX(), GetPosY(), GetPosZ(), 0, 0, 0, true); } } Destroy(); } return true; } void cBoat::OnRightClicked(cPlayer & a_Player) { Super::OnRightClicked(a_Player); if (m_Attachee != nullptr) { if (m_Attachee->GetUniqueID() == a_Player.GetUniqueID()) { // This player is already sitting in, they want out. a_Player.Detach(); return; } if (m_Attachee->IsPlayer()) { // Another player is already sitting in here, cannot attach return; } // Detach whatever is sitting in this boat now: m_Attachee->Detach(); } // Attach the player to this boat a_Player.AttachTo(*this); } void cBoat::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { Super::Tick(a_Dt, a_Chunk); if (!IsTicking()) { // The base class tick destroyed us return; } BroadcastMovementUpdate(); SetSpeed(GetSpeed() * 0.97); // Slowly decrease the speed if ((POSY_TOINT < 0) || (POSY_TOINT >= cChunkDef::Height)) { return; } if (IsBlockWater(m_World->GetBlock(POS_TOINT))) { if (GetSpeedY() < 2) { AddSpeedY(0.2); } } if (GetLastDamage() > 0) { SetLastDamage(GetLastDamage() - 1); } } void cBoat::HandleSpeedFromAttachee(float a_Forward, float a_Sideways) { if (GetSpeed().Length() > 7.5) { return; } Vector3d ToAddSpeed = m_Attachee->GetLookVector() * (a_Sideways * 0.4) ; ToAddSpeed.y = 0; AddSpeed(ToAddSpeed); } void cBoat::SetLastDamage(int TimeSinceLastHit) { m_LastDamage = TimeSinceLastHit; // Tell the client to play the shaking animation m_World->BroadcastEntityMetadata(*this); } void cBoat::UpdatePaddles(bool a_RightPaddleUsed, bool a_LeftPaddleUsed) { // Avoid telling client what it already knows since it may reset animation 1.13+ const bool Changed = (m_RightPaddleUsed != a_RightPaddleUsed) || (m_LeftPaddleUsed != a_LeftPaddleUsed); m_RightPaddleUsed = a_RightPaddleUsed; m_LeftPaddleUsed = a_LeftPaddleUsed; if (Changed) { m_World->BroadcastEntityMetadata(*this); } } cBoat::eMaterial cBoat::ItemToMaterial(const cItem & a_Item) { switch (a_Item.m_ItemType) { case E_ITEM_BOAT: return bmOak; case E_ITEM_SPRUCE_BOAT: return bmSpruce; case E_ITEM_BIRCH_BOAT: return bmBirch; case E_ITEM_JUNGLE_BOAT: return bmJungle; case E_ITEM_ACACIA_BOAT: return bmAcacia; case E_ITEM_DARK_OAK_BOAT: return bmDarkOak; default: { LOGWARNING("%s: Item type not handled %d.", __FUNCTION__, a_Item.m_ItemType); return cBoat::bmOak; } } } AString cBoat::MaterialToString(eMaterial a_Material) { switch (a_Material) { case bmOak: return "oak"; case bmSpruce: return "spruce"; case bmBirch: return "birch"; case bmJungle: return "jungle"; case bmAcacia: return "acacia"; case bmDarkOak: return "dark_oak"; } UNREACHABLE("Unsupported boat material"); } cBoat::eMaterial cBoat::StringToMaterial(const AString & a_Material) { if (a_Material == "oak") { return bmOak; } else if (a_Material == "spruce") { return bmSpruce; } else if (a_Material == "birch") { return bmBirch; } else if (a_Material == "jungle") { return bmJungle; } else if (a_Material == "acacia") { return bmAcacia; } else if (a_Material == "dark_oak") { return bmDarkOak; } else { return bmOak; } } cItem cBoat::MaterialToItem(eMaterial a_Material) { switch (a_Material) { case bmOak: return cItem(E_ITEM_BOAT); case bmSpruce: return cItem(E_ITEM_SPRUCE_BOAT); case bmBirch: return cItem(E_ITEM_BIRCH_BOAT); case bmJungle: return cItem(E_ITEM_JUNGLE_BOAT); case bmAcacia: return cItem(E_ITEM_ACACIA_BOAT); case bmDarkOak: return cItem(E_ITEM_DARK_OAK_BOAT); } UNREACHABLE("Unsupported boat material"); } void cBoat::HandlePhysics(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { /** Special version of cEntity::HandlePhysics(...) function for boats, checks if mobs colliding with the boat can be attached and does if that's the case, then returns to normal physics calcualtions */ // Calculate boat's bounding box, run collision callback on all entities in said box cBoatCollisionCallback BoatCollisionCallback(*this, m_Attachee); Vector3d BoatPosition = GetPosition(); cBoundingBox bbBoat( Vector3d(BoatPosition.x, floor(BoatPosition.y), BoatPosition.z), GetWidth() / 2, GetHeight()); m_World->ForEachEntityInBox(bbBoat, BoatCollisionCallback); // Return to calculating physics normally Super::HandlePhysics(a_Dt, a_Chunk); } ================================================ FILE: src/Entities/Boat.h ================================================ // Boat.h // Declares the cBoat class representing a boat in the world #pragma once #include "Entity.h" // tolua_begin class cBoat: public cEntity { // tolua_end using Super = cEntity; // tolua_begin public: enum eMaterial { bmOak, bmSpruce, bmBirch, bmJungle, bmAcacia, bmDarkOak }; // tolua_end CLASS_PROTODEF(cBoat) cBoat(Vector3d a_Pos, eMaterial a_Material); // cEntity overrides: virtual void SpawnOn(cClientHandle & a_ClientHandle) override; virtual void BroadcastMovementUpdate(const cClientHandle * a_Exclude = nullptr) override; virtual void OnRightClicked(cPlayer & a_Player) override; virtual bool DoTakeDamage(TakeDamageInfo & TDI) override; virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; virtual void HandleSpeedFromAttachee(float a_Forward, float a_Sideways) override; virtual void HandlePhysics(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; int GetLastDamage(void) const { return m_LastDamage; } int GetForwardDirection(void) const { return m_ForwardDirection; } float GetDamageTaken(void) const { return m_DamageTaken; } // tolua_begin /** Returns the eMaterial of the boat */ eMaterial GetMaterial(void) const { return m_Material; } /** Sets the eMaterial of the boat */ void SetMaterial(cBoat::eMaterial a_Material) { m_Material = a_Material; } /** Returns the eMaterial that should be used for a boat created from the specified item. Returns bmOak if not a boat item */ static eMaterial ItemToMaterial(const cItem & a_Item); /** Returns the boat item of the boat material */ static cItem MaterialToItem(eMaterial a_Material); /** Returns the eMaterial as string */ static AString MaterialToString(const eMaterial a_Material); /** Returns the boat material for the passed string. Returns oak if not valid */ static eMaterial StringToMaterial(const AString & a_Material); // tolua_end bool IsRightPaddleUsed(void) const { return m_RightPaddleUsed; } bool IsLeftPaddleUsed(void) const { return m_LeftPaddleUsed; } void SetLastDamage(int TimeSinceLastHit); void UpdatePaddles(bool rightPaddleUsed, bool leftPaddleUsed); private: int m_LastDamage; int m_ForwardDirection; float m_DamageTaken; eMaterial m_Material; bool m_RightPaddleUsed; bool m_LeftPaddleUsed; } ; // tolua_export ================================================ FILE: src/Entities/CMakeLists.txt ================================================ target_sources( ${CMAKE_PROJECT_NAME} PRIVATE ArrowEntity.cpp Boat.cpp EnderCrystal.cpp Entity.cpp EntityEffect.cpp ExpBottleEntity.cpp ExpOrb.cpp FallingBlock.cpp FireChargeEntity.cpp FireworkEntity.cpp Floater.cpp GhastFireballEntity.cpp HangingEntity.cpp ItemFrame.cpp LeashKnot.cpp Minecart.cpp Painting.cpp Pawn.cpp Pickup.cpp Player.cpp ProjectileEntity.cpp SplashPotionEntity.cpp TNTEntity.cpp ThrownEggEntity.cpp ThrownEnderPearlEntity.cpp ThrownSnowballEntity.cpp WitherSkullEntity.cpp ArrowEntity.h Boat.h EnderCrystal.h Entity.h EntityEffect.h ExpBottleEntity.h ExpOrb.h FallingBlock.h FireChargeEntity.h FireworkEntity.h Floater.h GhastFireballEntity.h HangingEntity.h ItemFrame.h LeashKnot.h Minecart.h Painting.h Pawn.h Pickup.h Player.h ProjectileEntity.h SplashPotionEntity.h TNTEntity.h ThrownEggEntity.h ThrownEnderPearlEntity.h ThrownSnowballEntity.h WitherSkullEntity.h ) ================================================ FILE: src/Entities/EnderCrystal.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "EnderCrystal.h" #include "../ClientHandle.h" #include "../Chunk.h" #include "../World.h" cEnderCrystal::cEnderCrystal(Vector3d a_Pos, bool a_ShowBottom) : cEnderCrystal(a_Pos, {}, false, a_ShowBottom) { } cEnderCrystal::cEnderCrystal(Vector3d a_Pos, Vector3i a_BeamTarget, bool a_DisplayBeam, bool a_ShowBottom) : Super(etEnderCrystal, a_Pos, 2.0f, 2.0f), m_BeamTarget(a_BeamTarget), m_DisplayBeam(a_DisplayBeam), m_ShowBottom(a_ShowBottom) { SetMaxHealth(5); } void cEnderCrystal::SetShowBottom(bool a_ShowBottom) { m_ShowBottom = a_ShowBottom; m_World->BroadcastEntityMetadata(*this); } void cEnderCrystal::SetBeamTarget(Vector3i a_BeamTarget) { m_BeamTarget = a_BeamTarget; m_World->BroadcastEntityMetadata(*this); } void cEnderCrystal::SetDisplayBeam(bool a_DisplayBeam) { m_DisplayBeam = a_DisplayBeam; m_World->BroadcastEntityMetadata(*this); } void cEnderCrystal::SpawnOn(cClientHandle & a_ClientHandle) { a_ClientHandle.SendSpawnEntity(*this); a_ClientHandle.SendEntityMetadata(*this); } void cEnderCrystal::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { UNUSED(a_Dt); if ((m_World->GetDimension() == dimEnd) && (m_World->GetBlock(POS_TOINT) != E_BLOCK_FIRE)) { m_World->SetBlock(POS_TOINT, E_BLOCK_FIRE, 0); } } void cEnderCrystal::KilledBy(TakeDamageInfo & a_TDI) { Super::KilledBy(a_TDI); // Destroy first so the Explodinator doesn't find us (when iterating through entities): Destroy(); m_World->DoExplosionAt(6.0, GetPosX(), GetPosY() + GetHeight() / 2, GetPosZ(), true, esEnderCrystal, this); const auto Position = GetPosition().Floor(); if (cChunkDef::IsValidHeight(Position)) { m_World->SetBlock(Position, E_BLOCK_FIRE, 0); } } ================================================ FILE: src/Entities/EnderCrystal.h ================================================ #pragma once #include "Entity.h" // tolua_begin class cEnderCrystal : public cEntity { // tolua_end using Super = cEntity; public: CLASS_PROTODEF(cEnderCrystal) cEnderCrystal(Vector3d a_Pos, bool a_ShowBottom); cEnderCrystal(Vector3d a_Pos, Vector3i a_BeamTarget, bool a_DisplayBeam, bool a_ShowBottom); // tolua_begin Vector3i GetBeamTarget() const { return m_BeamTarget; } void SetBeamTarget(Vector3i a_BeamTarget); /** If the EnderCrystal should send it's beam to the client and save it. */ bool DisplaysBeam() const { return m_DisplayBeam; } void SetDisplayBeam(bool a_DisplayBeam); bool ShowsBottom() const { return m_ShowBottom; } void SetShowBottom(bool a_ShowBottom); // tolua_end private: Vector3i m_BeamTarget; bool m_DisplayBeam; // If the bedrock base should be displayed. bool m_ShowBottom; // cEntity overrides: virtual void SpawnOn(cClientHandle & a_ClientHandle) override; virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; virtual void KilledBy(TakeDamageInfo & a_TDI) override; }; // tolua_export ================================================ FILE: src/Entities/Entity.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "Entity.h" #include "Player.h" #include "../BlockInfo.h" #include "../World.h" #include "../Root.h" #include "../Matrix4.h" #include "../ClientHandle.h" #include "../Chunk.h" #include "../Simulator/FluidSimulator.h" #include "../Bindings/PluginManager.h" #include "../LineBlockTracer.h" #include "../Items/ItemHandler.h" #include "../FastRandom.h" #include "../NetherPortalScanner.h" #include "../BoundingBox.h" #include "../WorldStorage/NamespaceSerializer.h" static UInt32 GetNextUniqueID(void) { static std::atomic counter(1); return counter.fetch_add(1); } //////////////////////////////////////////////////////////////////////////////// // cEntity: cEntity::cEntity(eEntityType a_EntityType, Vector3d a_Pos, float a_Width, float a_Height): m_UniqueID(GetNextUniqueID()), m_Health(1), m_MaxHealth(1), m_AttachedTo(nullptr), m_Attachee(nullptr), m_bDirtyHead(false), m_bDirtyOrientation(false), m_bHasSentNoSpeed(true), m_bOnGround(false), m_Gravity(-9.81f), m_AirDrag(0.02f), m_LastSentPosition(a_Pos), m_LastPosition(a_Pos), m_EntityType(a_EntityType), m_World(nullptr), m_IsFireproof(false), m_TicksSinceLastBurnDamage(0), m_TicksSinceLastLavaDamage(0), m_TicksSinceLastFireDamage(0), m_TicksLeftBurning(0), m_TicksSinceLastVoidDamage(0), m_IsInFire(false), m_IsInLava(false), m_IsInWater(false), m_IsHeadInWater(false), m_AirLevel(MAX_AIR_LEVEL), m_AirTickTimer(DROWNING_TICKS), m_TicksAlive(0), m_IsTicking(false), m_ParentChunk(nullptr), m_HeadYaw(0.0), m_Rot(0.0, 0.0, 0.0), m_Position(a_Pos), m_WaterSpeed(0, 0, 0), m_Mass (0.001), // Default 1g m_Width(a_Width), m_Height(a_Height), m_InvulnerableTicks(0) { m_WorldChangeInfo.m_NewWorld = nullptr; } const char * cEntity::GetClass(void) const { return "cEntity"; } const char * cEntity::GetClassStatic(void) { return "cEntity"; } const char * cEntity::GetParentClass(void) const { return ""; } bool cEntity::Initialize(OwnedEntity a_Self, cWorld & a_EntityWorld) { if (cPluginManager::Get()->CallHookSpawningEntity(a_EntityWorld, *this)) { return false; } /* // DEBUG: FLOGD("Initializing entity #{0} ({1}) at {2:.02f}", m_UniqueID, GetClass(), m_Pos ); */ ASSERT(a_Self->IsPlayer() || (m_World == nullptr)); // Players' worlds are loaded from disk. ASSERT(GetParentChunk() == nullptr); SetWorld(&a_EntityWorld); a_EntityWorld.AddEntity(std::move(a_Self)); return true; } void cEntity::OnAcquireSpectator(cPlayer & a_Player) { m_Spectators.push_back(&a_Player); } void cEntity::OnAddToWorld(cWorld & a_World) { // Spawn the entity on the clients: m_LastSentPosition = GetPosition(); a_World.BroadcastSpawnEntity(*this); BroadcastLeashedMobs(); } void cEntity::OnLoseSpectator(cPlayer & a_Player) { const auto Spectator = std::find(m_Spectators.begin(), m_Spectators.end(), &a_Player); ASSERT(Spectator != m_Spectators.end()); std::swap(*Spectator, m_Spectators.back()); m_Spectators.pop_back(); } void cEntity::OnRemoveFromWorld(cWorld & a_World) { // Remove all mobs from the leashed list of mobs: while (!m_LeashedMobs.empty()) { m_LeashedMobs.front()->Unleash(false, true); } for (const auto Player : m_Spectators) { Player->OnLoseSpectated(); } m_Spectators.clear(); if (m_AttachedTo != nullptr) { Detach(); } if (m_Attachee != nullptr) { m_Attachee->Detach(); } a_World.BroadcastDestroyEntity(*this); } void cEntity::WrapHeadYaw(void) { m_HeadYaw = NormalizeAngleDegrees(m_HeadYaw); } void cEntity::WrapRotation(void) { m_Rot.x = NormalizeAngleDegrees(m_Rot.x); m_Rot.y = NormalizeAngleDegrees(m_Rot.y); } void cEntity::WrapSpeed(void) { m_Speed.x = Clamp(m_Speed.x, -78.0, 78.0); m_Speed.y = Clamp(m_Speed.y, -78.0, 78.0); m_Speed.z = Clamp(m_Speed.z, -78.0, 78.0); } void cEntity::SetParentChunk(cChunk * a_Chunk) { m_ParentChunk = a_Chunk; } void cEntity::Destroy() { SetIsTicking(false); // Unleash leashed mobs while (!m_LeashedMobs.empty()) { m_LeashedMobs.front()->Unleash(true, true); } auto ParentChunkCoords = cChunkDef::BlockToChunk(GetPosition()); m_World->QueueTask([this, ParentChunkCoords](cWorld & a_World) { LOGD("Destroying entity #%i (%s) from chunk (%d, %d)", this->GetUniqueID(), this->GetClass(), ParentChunkCoords.m_ChunkX, ParentChunkCoords.m_ChunkZ ); UNUSED(ParentChunkCoords); // Non Debug mode only // Make sure that RemoveEntity returned a valid smart pointer // Also, not storing the returned pointer means automatic destruction VERIFY(a_World.RemoveEntity(*this)); }); } void cEntity::TakeDamage(cEntity & a_Attacker) { int RawDamage = a_Attacker.GetRawDamageAgainst(*this); TakeDamage(dtAttack, &a_Attacker, RawDamage, a_Attacker.GetKnockbackAmountAgainst(*this)); } void cEntity::TakeDamage(eDamageType a_DamageType, cEntity * a_Attacker, int a_RawDamage, double a_KnockbackAmount) { float FinalDamage = static_cast(a_RawDamage); float ArmorCover = GetArmorCoverAgainst(a_Attacker, a_DamageType, a_RawDamage); ApplyArmorDamage(static_cast(ArmorCover)); cEntity::TakeDamage(a_DamageType, a_Attacker, a_RawDamage, FinalDamage, a_KnockbackAmount); } void cEntity::TakeDamage(eDamageType a_DamageType, UInt32 a_AttackerID, int a_RawDamage, double a_KnockbackAmount) { m_World->DoWithEntityByID(a_AttackerID, [=](cEntity & a_Attacker) { cPawn * Attacker; if (a_Attacker.IsPawn()) { Attacker = static_cast(&a_Attacker); } else { Attacker = nullptr; } TakeDamage(a_DamageType, Attacker, a_RawDamage, a_KnockbackAmount); return true; } ); } void cEntity::TakeDamage(eDamageType a_DamageType, cEntity * a_Attacker, int a_RawDamage, float a_FinalDamage, double a_KnockbackAmount) { TakeDamageInfo TDI; TDI.DamageType = a_DamageType; if ((a_Attacker != nullptr) && a_Attacker->IsPawn()) { TDI.Attacker = a_Attacker; } else { TDI.Attacker = nullptr; } if (a_RawDamage <= 0) { a_RawDamage = 0; } TDI.RawDamage = a_RawDamage; if (a_FinalDamage <= 0) { a_FinalDamage = 0; } TDI.FinalDamage = a_FinalDamage; Vector3d Heading(0, 0, 0); if (a_Attacker != nullptr) { Heading = a_Attacker->GetLookVector(); } int KnockbackHeight = 3; if (IsPlayer()) { KnockbackHeight = 8; } // Apply slight height to knockback Vector3d FinalKnockback = Vector3d(Heading.x * a_KnockbackAmount, Heading.y + KnockbackHeight, Heading.z * a_KnockbackAmount); TDI.Knockback = FinalKnockback; DoTakeDamage(TDI); } void cEntity::SetYawFromSpeed(void) { const double EPS = 0.0000001; if ((std::abs(m_Speed.x) < EPS) && (std::abs(m_Speed.z) < EPS)) { // atan2() may overflow or is undefined, pick any number SetYaw(0); return; } SetYaw(atan2(m_Speed.x, m_Speed.z) * 180 / M_PI); } void cEntity::SetPitchFromSpeed(void) { const double EPS = 0.0000001; double xz = sqrt(m_Speed.x * m_Speed.x + m_Speed.z * m_Speed.z); // Speed XZ-plane component if ((std::abs(xz) < EPS) && (std::abs(m_Speed.y) < EPS)) { // atan2() may overflow or is undefined, pick any number SetPitch(0); return; } SetPitch(atan2(m_Speed.y, xz) * 180 / M_PI); } bool cEntity::DoTakeDamage(TakeDamageInfo & a_TDI) { if (m_Health <= 0) { // Can't take damage if already dead return false; } if (m_InvulnerableTicks > 0) { // Entity is invulnerable return false; } if (cRoot::Get()->GetPluginManager()->CallHookTakeDamage(*this, a_TDI)) { return false; } if (IsPainting()) { KilledBy(a_TDI); if (a_TDI.Attacker != nullptr) { a_TDI.Attacker->Killed(*this, a_TDI.DamageType); } return true; } if ((a_TDI.Attacker != nullptr) && (a_TDI.Attacker->IsPlayer())) { cPlayer * Player = static_cast(a_TDI.Attacker); Player->GetEquippedItem().GetHandler().OnEntityAttack(Player, this); // Whether an enchantment boosted this attack's damage. bool MagicalCriticalHit = false; // IsOnGround() only is false if the player is moving downwards // Ref: https://minecraft.wiki/w/Damage#Critical_Hits if (!Player->IsOnGround()) { if ((a_TDI.DamageType == dtAttack) || (a_TDI.DamageType == dtArrowAttack)) { a_TDI.FinalDamage *= 1.5f; // 150% damage m_World->BroadcastEntityAnimation(*this, EntityAnimation::EntityGetsCriticalHit); } } const cEnchantments & Enchantments = Player->GetEquippedItem().m_Enchantments; int SharpnessLevel = static_cast(Enchantments.GetLevel(cEnchantments::enchSharpness)); int SmiteLevel = static_cast(Enchantments.GetLevel(cEnchantments::enchSmite)); int BaneOfArthropodsLevel = static_cast(Enchantments.GetLevel(cEnchantments::enchBaneOfArthropods)); if (SharpnessLevel > 0) { MagicalCriticalHit = true; a_TDI.FinalDamage += 1.25f * SharpnessLevel; } else if (SmiteLevel > 0) { if (IsMob()) { cMonster * Monster = static_cast(this); switch (Monster->GetMobType()) { case mtSkeleton: case mtWither: case mtZombie: case mtZombiePigman: case mtZombieVillager: { MagicalCriticalHit = true; a_TDI.FinalDamage += 2.5f * SmiteLevel; break; } default: break; } } } else if (BaneOfArthropodsLevel > 0) { if (IsMob()) { cMonster * Monster = static_cast(this); switch (Monster->GetMobType()) { case mtSpider: case mtCaveSpider: case mtSilverfish: case mtEndermite: { MagicalCriticalHit = true; a_TDI.FinalDamage += 2.5f * BaneOfArthropodsLevel; // The duration of the effect is a random value between 1 and 1.5 seconds at level I, // increasing the max duration by 0.5 seconds each level. // Ref: https://minecraft.wiki/w/Enchanting#Bane_of_Arthropods int Duration = 20 + GetRandomProvider().RandInt(BaneOfArthropodsLevel * 10); // Duration in ticks. Monster->AddEntityEffect(cEntityEffect::effSlowness, Duration, 4); break; } default: break; } } } int FireAspectLevel = static_cast(Enchantments.GetLevel(cEnchantments::enchFireAspect)); if (FireAspectLevel > 0) { int BurnTicks = 3; if (FireAspectLevel > 1) { BurnTicks += 4 * (FireAspectLevel - 1); } if (!IsMob() && !IsInWater()) { StartBurning(BurnTicks * 20); } else if (IsMob() && !IsInWater()) { cMonster * Monster = static_cast(this); switch (Monster->GetMobType()) { case mtGhast: case mtZombiePigman: case mtMagmaCube: { break; } default: { MagicalCriticalHit = true; StartBurning(BurnTicks * 20); } } } } if (MagicalCriticalHit) { m_World->BroadcastEntityAnimation(*this, EntityAnimation::EntityGetsMagicalCriticalHit); } unsigned int ThornsLevel = 0; const cItem ArmorItems[] = { GetEquippedHelmet(), GetEquippedChestplate(), GetEquippedLeggings(), GetEquippedBoots() }; for (size_t i = 0; i < ARRAYCOUNT(ArmorItems); i++) { const cItem & Item = ArmorItems[i]; ThornsLevel = std::max(ThornsLevel, Item.m_Enchantments.GetLevel(cEnchantments::enchThorns)); } if (ThornsLevel > 0) { int Chance = static_cast(ThornsLevel * 15); auto & Random = GetRandomProvider(); if (Random.RandBool(Chance / 100.0)) { a_TDI.Attacker->TakeDamage(dtAttack, this, 0, Random.RandReal(1.0f, 4.0f), 0); } } Player->GetStatistics().Custom[CustomStatistic::DamageDealt] += FloorC(a_TDI.FinalDamage * 10 + 0.5); } m_Health -= a_TDI.FinalDamage; m_Health = std::max(m_Health, 0.0f); // Add knockback: if ((IsMob() || IsPlayer()) && (a_TDI.Attacker != nullptr)) { SetSpeed(a_TDI.Knockback); } m_World->BroadcastEntityAnimation(*this, [&a_TDI] { switch (a_TDI.DamageType) { case eDamageType::dtBurning: return EntityAnimation::PawnBurns; case eDamageType::dtDrowning: return EntityAnimation::PawnDrowns; default: return EntityAnimation::PawnHurts; } }()); m_InvulnerableTicks = 10; if (m_Health <= 0) { KilledBy(a_TDI); if (a_TDI.Attacker != nullptr) { a_TDI.Attacker->Killed(*this, a_TDI.DamageType); } } return true; } int cEntity::GetRawDamageAgainst(const cEntity & a_Receiver) { // Returns the hitpoints that this pawn can deal to a_Receiver using its equipped items // Ref: https://minecraft.wiki/w/Damage#Dealing_damage as of 2012_12_20 switch (this->GetEquippedWeapon().m_ItemType) { case E_ITEM_WOODEN_SWORD: return 4; case E_ITEM_GOLD_SWORD: return 4; case E_ITEM_STONE_SWORD: return 5; case E_ITEM_IRON_SWORD: return 6; case E_ITEM_DIAMOND_SWORD: return 7; case E_ITEM_WOODEN_AXE: return 3; case E_ITEM_GOLD_AXE: return 3; case E_ITEM_STONE_AXE: return 4; case E_ITEM_IRON_AXE: return 5; case E_ITEM_DIAMOND_AXE: return 6; case E_ITEM_WOODEN_PICKAXE: return 2; case E_ITEM_GOLD_PICKAXE: return 2; case E_ITEM_STONE_PICKAXE: return 3; case E_ITEM_IRON_PICKAXE: return 4; case E_ITEM_DIAMOND_PICKAXE: return 5; case E_ITEM_WOODEN_SHOVEL: return 1; case E_ITEM_GOLD_SHOVEL: return 1; case E_ITEM_STONE_SHOVEL: return 2; case E_ITEM_IRON_SHOVEL: return 3; case E_ITEM_DIAMOND_SHOVEL: return 4; } // All other equipped items give a damage of 1: return 1; } void cEntity::ApplyArmorDamage(int DamageBlocked) { // cEntities don't necessarily have armor to damage. } bool cEntity::ArmorCoversAgainst(eDamageType a_DamageType) { // Ref.: https://minecraft.wiki/w/Armor#Effects as of 2012_12_20 switch (a_DamageType) { case dtOnFire: case dtSuffocating: case dtDrowning: // TODO: This one could be a special case - in various MC versions (PC vs XBox) it is and isn't armor-protected case dtEnderPearl: case dtStarving: case dtInVoid: case dtPoisoning: case dtWithering: case dtPotionOfHarming: case dtFalling: case dtLightning: case dtPlugin: case dtEnvironment: { return false; } case dtAttack: case dtArrowAttack: case dtCactusContact: case dtMagmaContact: case dtLavaContact: case dtFireContact: case dtExplosion: { return true; } } UNREACHABLE("Unsupported damage type"); } float cEntity::GetEnchantmentCoverAgainst(const cEntity * a_Attacker, eDamageType a_DamageType, int a_Damage) { int TotalEPF = 0; const cItem ArmorItems[] = { GetEquippedHelmet(), GetEquippedChestplate(), GetEquippedLeggings(), GetEquippedBoots() }; for (size_t i = 0; i < ARRAYCOUNT(ArmorItems); i++) { const cItem & Item = ArmorItems[i]; if ((a_DamageType != dtInVoid) && (a_DamageType != dtAdmin) && (a_DamageType != dtStarving)) { TotalEPF += static_cast(Item.m_Enchantments.GetLevel(cEnchantments::enchProtection)) * 1; } if ((a_DamageType == dtBurning) || (a_DamageType == dtFireContact) || (a_DamageType == dtLavaContact) || (a_DamageType == dtMagmaContact)) { TotalEPF += static_cast(Item.m_Enchantments.GetLevel(cEnchantments::enchFireProtection)) * 2; } if ((a_DamageType == dtFalling) || (a_DamageType == dtEnderPearl)) { TotalEPF += static_cast(Item.m_Enchantments.GetLevel(cEnchantments::enchFeatherFalling)) * 3; } if (a_DamageType == dtExplosion) { TotalEPF += static_cast(Item.m_Enchantments.GetLevel(cEnchantments::enchBlastProtection)) * 2; } // Note: Also blocks against fire charges, etc. if (a_DamageType == dtProjectile) { TotalEPF += static_cast(Item.m_Enchantments.GetLevel(cEnchantments::enchProjectileProtection)) * 2; } } int CappedEPF = std::min(20, TotalEPF); return (a_Damage * CappedEPF / 25.0f); } float cEntity::GetEnchantmentBlastKnockbackReduction() { UInt32 MaxLevel = 0; const cItem ArmorItems[] = { GetEquippedHelmet(), GetEquippedChestplate(), GetEquippedLeggings(), GetEquippedBoots() }; for (auto & Item : ArmorItems) { UInt32 Level = Item.m_Enchantments.GetLevel(cEnchantments::enchBlastProtection); if (Level > MaxLevel) { // Get max blast protection MaxLevel = Level; } } // Max blast protect level is 4, each level provide 15% knock back reduction MaxLevel = std::min(MaxLevel, 4); return MaxLevel * 0.15f; } float cEntity::GetArmorCoverAgainst(const cEntity * a_Attacker, eDamageType a_DamageType, int a_Damage) { // Returns the hitpoints out of a_RawDamage that the currently equipped armor would cover // Filter out damage types that are not protected by armor: if (!ArmorCoversAgainst(a_DamageType)) { return 0; } // Add up all armor points: // Ref.: https://minecraft.wiki/w/Armor#Defense_points int ArmorValue = 0; int Toughness = 0; switch (GetEquippedHelmet().m_ItemType) { case E_ITEM_LEATHER_CAP: ArmorValue += 1; break; case E_ITEM_GOLD_HELMET: ArmorValue += 2; break; case E_ITEM_CHAIN_HELMET: ArmorValue += 2; break; case E_ITEM_IRON_HELMET: ArmorValue += 2; break; case E_ITEM_DIAMOND_HELMET: ArmorValue += 3; Toughness += 2; break; } switch (GetEquippedChestplate().m_ItemType) { case E_ITEM_LEATHER_TUNIC: ArmorValue += 3; break; case E_ITEM_GOLD_CHESTPLATE: ArmorValue += 5; break; case E_ITEM_CHAIN_CHESTPLATE: ArmorValue += 5; break; case E_ITEM_IRON_CHESTPLATE: ArmorValue += 6; break; case E_ITEM_DIAMOND_CHESTPLATE: ArmorValue += 8; Toughness += 2; break; } switch (GetEquippedLeggings().m_ItemType) { case E_ITEM_LEATHER_PANTS: ArmorValue += 2; break; case E_ITEM_GOLD_LEGGINGS: ArmorValue += 3; break; case E_ITEM_CHAIN_LEGGINGS: ArmorValue += 4; break; case E_ITEM_IRON_LEGGINGS: ArmorValue += 5; break; case E_ITEM_DIAMOND_LEGGINGS: ArmorValue += 6; Toughness += 2; break; } switch (GetEquippedBoots().m_ItemType) { case E_ITEM_LEATHER_BOOTS: ArmorValue += 1; break; case E_ITEM_GOLD_BOOTS: ArmorValue += 1; break; case E_ITEM_CHAIN_BOOTS: ArmorValue += 1; break; case E_ITEM_IRON_BOOTS: ArmorValue += 2; break; case E_ITEM_DIAMOND_BOOTS: ArmorValue += 3; Toughness += 2; break; } // TODO: Special armor cases, such as wool, saddles, dog's collar // Ref.: https://minecraft.wiki/w/Armor#Mob_armor as of 2012_12_20 float Reduction = std::max(ArmorValue / 5.0f, ArmorValue - a_Damage / (2.0f + Toughness / 4.0f)); return (a_Damage * std::min(20.0f, Reduction) / 25.0f); } double cEntity::GetKnockbackAmountAgainst(const cEntity & a_Receiver) { // Default knockback for entities double Knockback = 10; // If we're sprinting, bump up the knockback if (IsSprinting()) { Knockback = 15; } // Check for knockback enchantments (punch only applies to shot arrows) unsigned int KnockbackLevel = GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchKnockback); unsigned int KnockbackLevelMultiplier = 8; Knockback += KnockbackLevelMultiplier * KnockbackLevel; return Knockback; } void cEntity::KilledBy(TakeDamageInfo & a_TDI) { m_Health = 0; cRoot::Get()->GetPluginManager()->CallHookKilling(*this, a_TDI.Attacker, a_TDI); if (m_Health > 0) { // Plugin wants to 'unkill' the pawn. Abort return; } // If the victim is a player the hook is handled by the cPlayer class if (!IsPlayer()) { AString emptystring; cRoot::Get()->GetPluginManager()->CallHookKilled(*this, a_TDI, emptystring); } // Drop loot, unless the attacker was a creative mode player: if ( (a_TDI.Attacker == nullptr) || !a_TDI.Attacker->IsPlayer() || !static_cast(a_TDI.Attacker)->IsGameModeCreative() ) { cItems Drops; GetDrops(Drops, a_TDI.Attacker); m_World->SpawnItemPickups(Drops, GetPosX(), GetPosY(), GetPosZ()); } m_TicksAlive = 0; m_World->BroadcastEntityAnimation(*this, EntityAnimation::PawnDies); } void cEntity::Heal(int a_HitPoints) { m_Health += a_HitPoints; m_Health = std::min(m_Health, m_MaxHealth); } void cEntity::SetHealth(float a_Health) { m_Health = Clamp(a_Health, 0.0f, m_MaxHealth); } void cEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { ASSERT(IsTicking()); ASSERT(GetWorld() != nullptr); m_TicksAlive++; if (m_InvulnerableTicks > 0) { m_InvulnerableTicks--; } // Non-players are destroyed as soon as they fall out of the world: if ((GetPosY() < 0) && (!IsPlayer())) { Destroy(); return; } if (m_AttachedTo != nullptr) { SetPosition(m_AttachedTo->GetPosition()); } else { if (!a_Chunk.IsValid()) { return; } // Position changed -> Super::Tick() called: GET_AND_VERIFY_CURRENT_CHUNK(NextChunk, POSX_TOINT, POSZ_TOINT); // Set swim states (water, lava, and fire): SetSwimState(*NextChunk); // Handle catching on fire and burning: TickBurning(*NextChunk); // Damage players if they are in the void if (GetPosY() < VOID_BOUNDARY) { TickInVoid(*NextChunk); } else { m_TicksSinceLastVoidDamage = 0; } // Handle cactus damage or destruction: if ( IsMob() || IsPickup() || (IsPlayer() && !((static_cast(this))->IsGameModeCreative() || (static_cast(this))->IsGameModeSpectator())) ) { DetectCacti(); } // Handle magma block damage if ( IsOnGround() && ( (IsMob() && !static_cast(this)->IsFireproof()) || ( IsPlayer() && !((static_cast(this))->IsGameModeCreative() || (static_cast(this))->IsGameModeSpectator()) && !static_cast(this)->IsFireproof() && !static_cast(this)->HasEntityEffect(cEntityEffect::effFireResistance) ) ) ) { DetectMagma(); } // Handle drowning: if (IsMob() || IsPlayer()) { HandleAir(); } if (!DetectPortal()) // Our chunk is invalid if we have moved to another world { // None of the above functions changed position, we remain in the chunk of NextChunk HandlePhysics(a_Dt, *NextChunk); } } } void cEntity::HandlePhysics(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { int BlockX = POSX_TOINT; int BlockY = POSY_TOINT; int BlockZ = POSZ_TOINT; // Position changed -> Super::HandlePhysics() called GET_AND_VERIFY_CURRENT_CHUNK(NextChunk, BlockX, BlockZ); // TODO Add collision detection with entities. auto DtSec = std::chrono::duration_cast>(a_Dt); Vector3d NextPos = Vector3d(GetPosX(), GetPosY(), GetPosZ()); Vector3d NextSpeed = Vector3d(GetSpeedX(), GetSpeedY(), GetSpeedZ()); if ((BlockY >= cChunkDef::Height) || (BlockY < 0)) { // Outside of the world AddSpeedY(m_Gravity * DtSec.count()); AddPosition(GetSpeed() * DtSec.count()); return; } int RelBlockX = BlockX - (NextChunk->GetPosX() * cChunkDef::Width); int RelBlockZ = BlockZ - (NextChunk->GetPosZ() * cChunkDef::Width); BLOCKTYPE BlockIn = NextChunk->GetBlock( RelBlockX, BlockY, RelBlockZ); BLOCKTYPE BlockBelow = (BlockY > 0) ? NextChunk->GetBlock(RelBlockX, BlockY - 1, RelBlockZ) : E_BLOCK_AIR; if (!cBlockInfo::IsSolid(BlockIn)) // Making sure we are not inside a solid block { if (m_bOnGround) // check if it's still on the ground { if (!cBlockInfo::IsSolid(BlockBelow)) // Check if block below is air or water. { m_bOnGround = false; } } } else if (!(IsMinecart() || IsTNT() || (IsPickup() && (m_TicksAlive < 15)))) { // Push out entity. BLOCKTYPE GotBlock; static const struct { int x, y, z; } gCrossCoords[] = { { 1, 0, 0}, {-1, 0, 0}, { 0, 0, 1}, { 0, 0, -1}, } ; bool IsNoAirSurrounding = true; for (size_t i = 0; i < ARRAYCOUNT(gCrossCoords); i++) { if (!NextChunk->UnboundedRelGetBlockType(RelBlockX + gCrossCoords[i].x, BlockY, RelBlockZ + gCrossCoords[i].z, GotBlock)) { // The pickup is too close to an unloaded chunk, bail out of any physics handling return; } if (!cBlockInfo::IsSolid(GotBlock)) { NextPos.x += gCrossCoords[i].x; NextPos.z += gCrossCoords[i].z; IsNoAirSurrounding = false; break; } } // for i - gCrossCoords[] if (IsNoAirSurrounding) { NextPos.y += 0.5; } m_bHasSentNoSpeed = false; // this unlocks movement sending to client in BroadcastMovementUpdate function m_bOnGround = true; /* // DEBUG: FLOGD("Entity #{0} ({1}) is inside a block at {{2}}", m_UniqueID, GetClass(), Vector3i{BlockX, BlockY, BlockZ} ); */ } if (!m_bOnGround) { double fallspeed; if (IsBlockWater(BlockIn)) { fallspeed = m_Gravity * DtSec.count() / 3; // Fall 3x slower in water ApplyFriction(NextSpeed, 0.7, static_cast(DtSec.count())); } else if (BlockIn == E_BLOCK_COBWEB) { NextSpeed.y *= 0.05; // Reduce overall falling speed fallspeed = 0; // No falling } else { // Normal gravity fallspeed = m_Gravity * DtSec.count(); NextSpeed -= NextSpeed * (m_AirDrag * 20.0f) * DtSec.count(); } NextSpeed.y += static_cast(fallspeed); // A real boat floats if (IsBoat()) { // Find top water block and sit there int NextBlockY = BlockY; BLOCKTYPE NextBlock = NextChunk->GetBlock(RelBlockX, NextBlockY, RelBlockZ); while (IsBlockWater(NextBlock)) { NextBlock = NextChunk->GetBlock(RelBlockX, ++NextBlockY, RelBlockZ); } NextPos.y = NextBlockY - 0.5; NextSpeed.y = 0; } } else { ApplyFriction(NextSpeed, 0.7, static_cast(DtSec.count())); } // Adjust X and Z speed for COBWEB temporary. This speed modification should be handled inside block handlers since we // might have different speed modifiers according to terrain. if (BlockIn == E_BLOCK_COBWEB) { NextSpeed.x *= 0.25; NextSpeed.z *= 0.25; } // Get water direction Vector3f WaterDir = m_World->GetWaterSimulator()->GetFlowingDirection({BlockX, BlockY, BlockZ}); m_WaterSpeed *= 0.9; // Reduce speed each tick auto AdjustSpeed = [](double & a_WaterSpeed, float a_WaterDir) { if (std::abs(a_WaterDir) > (0.05f / 0.4f)) { a_WaterSpeed = 0.4 * a_WaterDir; } else if (std::abs(a_WaterSpeed) < 0.05) { a_WaterSpeed = 0.0; } }; AdjustSpeed(m_WaterSpeed.x, WaterDir.x); AdjustSpeed(m_WaterSpeed.z, WaterDir.z); NextSpeed += m_WaterSpeed; if (NextSpeed.SqrLength() > 0.0f) { Vector3d HitCoords; Vector3i HitBlockCoords; eBlockFace HitBlockFace; Vector3d wantNextPos = NextPos + NextSpeed * DtSec.count(); auto isHit = cLineBlockTracer::FirstSolidHitTrace(*GetWorld(), NextPos, wantNextPos, HitCoords, HitBlockCoords, HitBlockFace); if (isHit) { // Set our position to where the block was hit: NextPos = HitCoords; // Avoid movement in the direction of the blockface that has been hit and correct for collision box: const auto HalfWidth = GetWidth() / 2; switch (HitBlockFace) { case BLOCK_FACE_XM: { NextSpeed.x = 0; NextPos.x -= HalfWidth; break; } case BLOCK_FACE_XP: { NextSpeed.x = 0; NextPos.x += HalfWidth; break; } case BLOCK_FACE_YM: { NextSpeed.y = 0; NextPos.y -= GetHeight(); break; } case BLOCK_FACE_YP: { NextSpeed.y = 0; // We hit the ground, adjust the position to the top of the block: m_bOnGround = true; NextPos.y = HitBlockCoords.y + 1; break; } case BLOCK_FACE_ZM: { NextSpeed.z = 0; NextPos.z -= HalfWidth; break; } case BLOCK_FACE_ZP: { NextSpeed.z = 0; NextPos.z += HalfWidth; break; } default: { break; } } } else { // We didn't hit anything, so move: NextPos += (NextSpeed * DtSec.count()); } } SetPosition(NextPos); SetSpeed(NextSpeed); } void cEntity::ApplyFriction(Vector3d & a_Speed, double a_SlowdownMultiplier, float a_Dt) { if (a_Speed.SqrLength() > 0.0004f) { a_Speed.x *= a_SlowdownMultiplier / (1 + a_Dt); if (fabs(a_Speed.x) < 0.05) { a_Speed.x = 0; } a_Speed.z *= a_SlowdownMultiplier / (1 + a_Dt); if (fabs(a_Speed.z) < 0.05) { a_Speed.z = 0; } } } void cEntity::TickBurning(cChunk & a_Chunk) { // Remember the current burning state: bool HasBeenBurning = (m_TicksLeftBurning > 0); // Fireproof entities burn out on the next tick if (IsFireproof()) { m_TicksLeftBurning = 0; } // Fire is extinguished by rain: if (a_Chunk.IsWeatherWetAt(cChunkDef::AbsoluteToRelative(GetPosition().Floor(), a_Chunk.GetPos()))) { m_TicksLeftBurning = 0; } // Do the burning damage: if (m_TicksLeftBurning > 0) { m_TicksSinceLastBurnDamage++; if (m_TicksSinceLastBurnDamage >= BURN_TICKS_PER_DAMAGE) { if (!IsFireproof()) { TakeDamage(dtOnFire, nullptr, BURN_DAMAGE, 0); } m_TicksSinceLastBurnDamage = 0; } m_TicksLeftBurning--; } if (IsInWater()) { // Extinguish the fire m_TicksLeftBurning = 0; } if (IsInLava()) { // Burn: m_TicksLeftBurning = BURN_TICKS; // Periodically damage: m_TicksSinceLastLavaDamage++; if (m_TicksSinceLastLavaDamage >= LAVA_TICKS_PER_DAMAGE) { if (!IsFireproof()) { TakeDamage(dtLavaContact, nullptr, LAVA_DAMAGE, 0); } m_TicksSinceLastLavaDamage = 0; } } else { m_TicksSinceLastLavaDamage = 0; } if (IsInFire()) { // Burn: m_TicksLeftBurning = BURN_TICKS; // Periodically damage: m_TicksSinceLastFireDamage++; if (m_TicksSinceLastFireDamage >= FIRE_TICKS_PER_DAMAGE) { if (!IsFireproof() && !IsInLava()) { TakeDamage(dtFireContact, nullptr, FIRE_DAMAGE, 0); } m_TicksSinceLastFireDamage = 0; } } else { m_TicksSinceLastFireDamage = 0; } // If just started / finished burning, notify descendants: if ((m_TicksLeftBurning > 0) && !HasBeenBurning) { OnStartedBurning(); } else if ((m_TicksLeftBurning <= 0) && HasBeenBurning) { OnFinishedBurning(); } } void cEntity::TickInVoid(cChunk & a_Chunk) { if (m_TicksSinceLastVoidDamage == 20) { TakeDamage(dtInVoid, nullptr, 2, 0); m_TicksSinceLastVoidDamage = 0; } else { m_TicksSinceLastVoidDamage++; } } void cEntity::DetectCacti(void) { int MinX = FloorC(GetPosX() - m_Width / 2); int MaxX = FloorC(GetPosX() + m_Width / 2); int MinZ = FloorC(GetPosZ() - m_Width / 2); int MaxZ = FloorC(GetPosZ() + m_Width / 2); int MinY = Clamp(POSY_TOINT, 0, cChunkDef::Height - 1); int MaxY = Clamp(FloorC(GetPosY() + m_Height), 0, cChunkDef::Height - 1); for (int x = MinX; x <= MaxX; x++) { for (int z = MinZ; z <= MaxZ; z++) { for (int y = MinY; y <= MaxY; y++) { if (GetWorld()->GetBlock({ x, y, z }) == E_BLOCK_CACTUS) { TakeDamage(dtCactusContact, nullptr, 1, 0); return; } } // for y } // for z } // for x } void cEntity::DetectMagma(void) { int MinX = FloorC(GetPosX() - m_Width / 2); int MaxX = FloorC(GetPosX() + m_Width / 2); int MinZ = FloorC(GetPosZ() - m_Width / 2); int MaxZ = FloorC(GetPosZ() + m_Width / 2); int MinY = Clamp(POSY_TOINT - 1, 0, cChunkDef::Height - 1); int MaxY = Clamp(FloorC(GetPosY() + m_Height), 0, cChunkDef::Height - 1); for (int x = MinX; x <= MaxX; x++) { for (int z = MinZ; z <= MaxZ; z++) { for (int y = MinY; y <= MaxY; y++) { if (GetWorld()->GetBlock({ x, y, z }) == E_BLOCK_MAGMA) { TakeDamage(dtMagmaContact, nullptr, 1, 0); return; } } // for y } // for z } // for x } bool cEntity::DetectPortal() { if (GetWorld()->GetDimension() == dimOverworld) { if (GetWorld()->GetLinkedNetherWorldName().empty() && GetWorld()->GetLinkedEndWorldName().empty()) { // Teleportation to either dimension not enabled, don't bother proceeding return false; } } else if (GetWorld()->GetLinkedOverworldName().empty()) { // Overworld teleportation disabled, abort return false; } if (const auto Position = m_Position.Floor(); cChunkDef::IsValidHeight(Position)) { switch (GetWorld()->GetBlock(Position)) { case E_BLOCK_NETHER_PORTAL: { if (m_PortalCooldownData.m_ShouldPreventTeleportation) { // Just exited a portal, don't teleport again return false; } if ((m_AttachedTo != nullptr) || (m_Attachee != nullptr)) { // Don't let attached entities change worlds, like players riding a minecart return false; } if (IsPlayer() && !(static_cast(this))->IsGameModeCreative() && (m_PortalCooldownData.m_TicksDelayed != 80)) { // Delay teleportation for four seconds if the entity is a non-creative player m_PortalCooldownData.m_TicksDelayed++; return false; } m_PortalCooldownData.m_TicksDelayed = 0; // Nether portal in the nether if (GetWorld()->GetDimension() == dimNether) { if (GetWorld()->GetLinkedOverworldName().empty()) { return false; } m_PortalCooldownData.m_ShouldPreventTeleportation = true; // Stop portals from working on respawn Vector3d TargetPos = GetPosition(); TargetPos.x *= 8.0; TargetPos.z *= 8.0; cWorld * TargetWorld = cRoot::Get()->GetWorld(GetWorld()->GetLinkedOverworldName()); ASSERT(TargetWorld != nullptr); // The linkage checker should have prevented this at startup. See cWorld::start() LOGD("Jumping %s -> %s", DimensionToString(dimNether).c_str(), DimensionToString(TargetWorld->GetDimension()).c_str()); new cNetherPortalScanner(*this, *TargetWorld, TargetPos, cChunkDef::Height); return true; } // Nether portal in the overworld else { if (GetWorld()->GetLinkedNetherWorldName().empty()) { return false; } m_PortalCooldownData.m_ShouldPreventTeleportation = true; Vector3d TargetPos = GetPosition(); TargetPos.x /= 8.0; TargetPos.z /= 8.0; cWorld * TargetWorld = cRoot::Get()->GetWorld(GetWorld()->GetLinkedNetherWorldName()); ASSERT(TargetWorld != nullptr); // The linkage checker should have prevented this at startup. See cWorld::start() LOGD("Jumping %s -> %s", DimensionToString(dimOverworld).c_str(), DimensionToString(TargetWorld->GetDimension()).c_str()); new cNetherPortalScanner(*this, *TargetWorld, TargetPos, (cChunkDef::Height / 2)); return true; } } case E_BLOCK_END_PORTAL: { if (m_PortalCooldownData.m_ShouldPreventTeleportation) { return false; } if ((m_AttachedTo != nullptr) || (m_Attachee != nullptr)) { // Don't let attached entities change worlds, like players riding a minecart return false; } // End portal in the end if (GetWorld()->GetDimension() == dimEnd) { if (GetWorld()->GetLinkedOverworldName().empty()) { return false; } m_PortalCooldownData.m_ShouldPreventTeleportation = true; cWorld * TargetWorld = cRoot::Get()->GetWorld(GetWorld()->GetLinkedOverworldName()); ASSERT(TargetWorld != nullptr); // The linkage checker should have prevented this at startup. See cWorld::start() LOGD("Jumping %s -> %s", DimensionToString(dimEnd).c_str(), DimensionToString(TargetWorld->GetDimension()).c_str()); if (IsPlayer()) { cPlayer * Player = static_cast(this); if (Player->GetRespawnWorld() == TargetWorld) { return MoveToWorld(*TargetWorld, Player->GetLastBedPos()); } } return MoveToWorld(*TargetWorld, false); } // End portal in the overworld else { if (GetWorld()->GetLinkedEndWorldName().empty()) { return false; } m_PortalCooldownData.m_ShouldPreventTeleportation = true; cWorld * TargetWorld = cRoot::Get()->GetWorld(GetWorld()->GetLinkedEndWorldName()); ASSERT(TargetWorld != nullptr); // The linkage checker should have prevented this at startup. See cWorld::start() LOGD("Jumping %s -> %s", DimensionToString(dimOverworld).c_str(), DimensionToString(TargetWorld->GetDimension()).c_str()); return MoveToWorld(*TargetWorld, false); } } default: break; } } // Allow portals to work again m_PortalCooldownData.m_ShouldPreventTeleportation = false; m_PortalCooldownData.m_TicksDelayed = 0; return false; } void cEntity::DoMoveToWorld(const sWorldChangeInfo & a_WorldChangeInfo) { ASSERT(a_WorldChangeInfo.m_NewWorld != nullptr); // Reset portal cooldown: if (a_WorldChangeInfo.m_SetPortalCooldown) { m_PortalCooldownData.m_TicksDelayed = 0; m_PortalCooldownData.m_ShouldPreventTeleportation = true; } if (m_World == a_WorldChangeInfo.m_NewWorld) { // Moving to same world, don't need to remove from world SetPosition(a_WorldChangeInfo.m_NewPosition); return; } LOGD("Warping entity #%i (%s) from world \"%s\" to \"%s\". Source chunk: (%d, %d) ", GetUniqueID(), GetClass(), m_World->GetName(), a_WorldChangeInfo.m_NewWorld->GetName(), GetChunkX(), GetChunkZ() ); // Stop ticking, in preperation for detaching from this world. SetIsTicking(false); // Remove from the old world const auto OldWorld = m_World; auto Self = m_World->RemoveEntity(*this); // Update entity: ResetPosition(a_WorldChangeInfo.m_NewPosition); SetWorld(a_WorldChangeInfo.m_NewWorld); // Don't do anything after adding as the old world's CS no longer protects us a_WorldChangeInfo.m_NewWorld->AddEntity(std::move(Self), OldWorld); } bool cEntity::MoveToWorld(cWorld & a_World, Vector3d a_NewPosition, bool a_SetPortalCooldown, bool a_ShouldSendRespawn) { // Ask the plugins if the entity is allowed to change world if (cRoot::Get()->GetPluginManager()->CallHookEntityChangingWorld(*this, a_World)) { // A Plugin isn't allowing the entity to change world return false; } const auto OldWorld = m_WorldChangeInfo.m_NewWorld; // Create new world change info // (The last warp command always takes precedence) m_WorldChangeInfo = { &a_World, a_NewPosition, a_SetPortalCooldown }; if (OldWorld != nullptr) { // Avoid scheduling multiple warp tasks // Only move ahead if we came from a "not warping" state return true; } // TODO: move to capture when C++14 const auto EntityID = GetUniqueID(); /* Requirements: Only one world change in-flight at any time No ticking during world changes The last invocation takes effect As of writing, cWorld ticks entities, clients, and then processes tasks We may call MoveToWorld (any number of times - consider multiple /portal commands within a tick) in the first and second stages Queue a task onto the third stage to invoke DoMoveToWorld ONCE with the last given destination world Store entity IDs in case client tick found the player disconnected and immediately destroys the object After the move begins, no further calls to MoveToWorld is possible since neither the client nor entity is ticked This remains until the warp is complete and the destination world resumes ticking. */ GetWorld()->QueueTask( [EntityID](cWorld & a_CurWorld) { a_CurWorld.DoWithEntityByID( EntityID, [](cEntity & a_Entity) { auto & WCI = a_Entity.m_WorldChangeInfo; a_Entity.DoMoveToWorld(WCI); WCI.m_NewWorld = nullptr; return true; } ); } ); return true; } bool cEntity::MoveToWorld(cWorld & a_World, bool a_ShouldSendRespawn) { return MoveToWorld(a_World, a_ShouldSendRespawn, Vector3i(a_World.GetSpawnX(), a_World.GetSpawnY(), a_World.GetSpawnZ())); } bool cEntity::MoveToWorld(const AString & a_WorldName, bool a_ShouldSendRespawn) { cWorld * World = cRoot::Get()->GetWorld(a_WorldName); if (World == nullptr) { LOG("%s: Couldn't find world \"%s\".", __FUNCTION__, a_WorldName.c_str()); return false; } return MoveToWorld(*World, Vector3i(World->GetSpawnX(), World->GetSpawnY(), World->GetSpawnZ()), false, a_ShouldSendRespawn); } void cEntity::SetSwimState(cChunk & a_Chunk) { m_IsInFire = false; m_IsInLava = false; m_IsInWater = false; m_IsHeadInWater = false; int RelY = FloorC(GetPosY() + 0.1); int HeadRelY = CeilC(GetPosY() + GetHeight()) - 1; ASSERT(RelY <= HeadRelY); if ((RelY < 0) || (HeadRelY >= cChunkDef::Height)) { return; } int MinRelX = FloorC(GetPosX() - m_Width / 2) - a_Chunk.GetPosX() * cChunkDef::Width; int MaxRelX = FloorC(GetPosX() + m_Width / 2) - a_Chunk.GetPosX() * cChunkDef::Width; int MinRelZ = FloorC(GetPosZ() - m_Width / 2) - a_Chunk.GetPosZ() * cChunkDef::Width; int MaxRelZ = FloorC(GetPosZ() + m_Width / 2) - a_Chunk.GetPosZ() * cChunkDef::Width; int MinY = Clamp(POSY_TOINT, 0, cChunkDef::Height - 1); int MaxY = Clamp(FloorC(GetPosY() + m_Height), 0, cChunkDef::Height - 1); for (int x = MinRelX; x <= MaxRelX; x++) { for (int z = MinRelZ; z <= MaxRelZ; z++) { for (int y = MinY; y <= MaxY; y++) { BLOCKTYPE Block; if (!a_Chunk.UnboundedRelGetBlockType(x, y, z, Block)) { /* LOGD("SetSwimState failure: RelX = %d, RelY = %d, RelZ = %d, Pos = %.02f, %.02f}", x, y, z, GetPosX(), GetPosZ() ); */ continue; } if (Block == E_BLOCK_FIRE) { m_IsInFire = true; } else if (IsBlockLava(Block)) { m_IsInLava = true; } else if (IsBlockWater(Block)) { m_IsInWater = true; } } // for y } // for z } // for x // Check if the entity's head is in water. int RelX = POSX_TOINT - a_Chunk.GetPosX() * cChunkDef::Width; int RelZ = POSZ_TOINT - a_Chunk.GetPosZ() * cChunkDef::Width; int HeadHeight = CeilC(GetPosY() + GetHeight()) - 1; BLOCKTYPE BlockIn; if (!a_Chunk.UnboundedRelGetBlockType(RelX, HeadHeight, RelZ, BlockIn)) { /* LOGD("SetSwimState failure: RelX = %d, RelY = %d, RelZ = %d, Pos = %.02f, %.02f}", RelX, HeadHeight, RelZ, GetPosX(), GetPosZ() ); */ return; } m_IsHeadInWater = IsBlockWater(BlockIn); } void cEntity::SetIsTicking(bool a_IsTicking) { m_IsTicking = a_IsTicking; ASSERT(!(m_IsTicking && (m_ParentChunk == nullptr))); // We shouldn't be ticking if we have no parent chunk } void cEntity::SetSize(const float a_Width, const float a_Height) { m_Width = a_Width; m_Height = a_Height; } void cEntity::HandleAir(void) { // Ref.: https://minecraft.wiki/w/Chunk_format // See if the entity is /submerged/ water (head is in water) // Get the type of block the entity is standing in: int RespirationLevel = static_cast(GetEquippedHelmet().m_Enchantments.GetLevel(cEnchantments::enchRespiration)); if (IsHeadInWater()) { if (!IsPlayer()) // Players control themselves { SetSpeedY(1); // Float in the water } if (RespirationLevel > 0) { static_cast(this)->AddEntityEffect(cEntityEffect::effNightVision, 200, 5, 0); } if (m_AirLevel <= 0) { // Runs the air tick timer to check whether the player should be damaged if (m_AirTickTimer <= 0) { // Damage player TakeDamage(dtDrowning, nullptr, 1, 1, 0); // Reset timer m_AirTickTimer = DROWNING_TICKS; } else { m_AirTickTimer--; } } else { // Reduce air supply m_AirLevel--; } } else { // Set the air back to maximum m_AirLevel = MAX_AIR_LEVEL; m_AirTickTimer = DROWNING_TICKS; if (RespirationLevel > 0) { m_AirTickTimer = DROWNING_TICKS + (RespirationLevel * 15 * 20); } } } void cEntity::ResetPosition(Vector3d a_NewPos) { SetPosition(a_NewPos); m_LastSentPosition = GetPosition(); } void cEntity::OnStartedBurning(void) { // Broadcast the change: m_World->BroadcastEntityMetadata(*this); } void cEntity::OnFinishedBurning(void) { // Broadcast the change: m_World->BroadcastEntityMetadata(*this); } void cEntity::SetMaxHealth(float a_MaxHealth) { m_MaxHealth = a_MaxHealth; // Reset health, if too high: m_Health = std::min(m_Health, a_MaxHealth); } void cEntity::SetIsFireproof(bool a_IsFireproof) { m_IsFireproof = a_IsFireproof; } void cEntity::StartBurning(int a_TicksLeftBurning) { if (m_TicksLeftBurning > 0) { // Already burning, top up the ticks left burning and bail out: m_TicksLeftBurning = std::max(m_TicksLeftBurning, a_TicksLeftBurning); return; } m_TicksLeftBurning = a_TicksLeftBurning; OnStartedBurning(); } void cEntity::StopBurning(void) { bool HasBeenBurning = (m_TicksLeftBurning > 0); m_TicksLeftBurning = 0; m_TicksSinceLastBurnDamage = 0; m_TicksSinceLastFireDamage = 0; m_TicksSinceLastLavaDamage = 0; // Notify if the entity has stopped burning if (HasBeenBurning) { OnFinishedBurning(); } } void cEntity::TeleportToEntity(cEntity & a_Entity) { TeleportToCoords(a_Entity.GetPosX(), a_Entity.GetPosY(), a_Entity.GetPosZ()); } void cEntity::TeleportToCoords(double a_PosX, double a_PosY, double a_PosZ) { // ask the plugins to allow teleport to the new position. if (!cRoot::Get()->GetPluginManager()->CallHookEntityTeleport(*this, m_LastPosition, Vector3d(a_PosX, a_PosY, a_PosZ))) { SetPosition({a_PosX, a_PosY, a_PosZ}); } } void cEntity::BroadcastMovementUpdate(const cClientHandle * a_Exclude) { // Process packet sending every two ticks: if ((GetWorld()->GetWorldTickAge() % 2_tick) != 0_tick) { return; } if (m_Speed.HasNonZeroLength()) { // Movin' m_World->BroadcastEntityVelocity(*this, a_Exclude); m_bHasSentNoSpeed = false; } else if (!m_bHasSentNoSpeed) { // Speed is zero, send this to clients once only as well as an absolute position m_World->BroadcastEntityVelocity(*this, a_Exclude); m_World->BroadcastEntityPosition(*this, a_Exclude); m_LastSentPosition = GetPosition(); m_bDirtyOrientation = false; m_bHasSentNoSpeed = true; } if ((m_Position - m_LastSentPosition).HasNonZeroLength()) // Have we moved? { m_World->BroadcastEntityPosition(*this, a_Exclude); // Clients seem to store two positions, one for the velocity packet and one for the teleport / relmove packet // The latter is only changed with a relmove / teleport, and m_LastSentPosition stores this position m_LastSentPosition = GetPosition(); m_bDirtyOrientation = false; } if (m_bDirtyHead) { m_World->BroadcastEntityHeadLook(*this, a_Exclude); m_bDirtyHead = false; } if (m_bDirtyOrientation) { // Send individual update in case above (sending with rel-move packet) wasn't done GetWorld()->BroadcastEntityLook(*this, a_Exclude); m_bDirtyOrientation = false; } } cEntity * cEntity::GetAttached() { return m_AttachedTo; } void cEntity::AttachTo(cEntity & a_AttachTo) { if (m_AttachedTo == &a_AttachTo) { // Already attached to that entity, nothing to do here: return; } if (m_AttachedTo != nullptr) { // Detach from any previous entity: Detach(); } // Update state information: m_AttachedTo = &a_AttachTo; a_AttachTo.m_Attachee = this; m_World->BroadcastAttachEntity(*this, a_AttachTo); } void cEntity::Detach(void) { if (m_AttachedTo == nullptr) { // Already not attached to any entity, our work is done: return; } m_World->BroadcastDetachEntity(*this, *m_AttachedTo); m_AttachedTo->m_Attachee = nullptr; m_AttachedTo = nullptr; OnDetach(); } bool cEntity::IsA(const char * a_ClassName) const { return ((a_ClassName != nullptr) && (strcmp(a_ClassName, "cEntity") == 0)); } bool cEntity::IsAttachedTo(const cEntity * a_Entity) const { return ( (m_AttachedTo != nullptr) && (a_Entity->GetUniqueID() == m_AttachedTo->GetUniqueID()) ); } bool cEntity::IsOrientationDirty() const { return m_bDirtyOrientation; } void cEntity::SetHeadYaw(double a_HeadYaw) { m_HeadYaw = a_HeadYaw; m_bDirtyHead = true; WrapHeadYaw(); } void cEntity::SetMass(double a_Mass) { // Make sure that mass is not zero. 1g is the default because we // have to choose a number. It's perfectly legal to have a mass // less than 1g as long as is NOT equal or less than zero. m_Mass = std::max(a_Mass, 0.001); } void cEntity::SetYaw(double a_Yaw) { m_Rot.x = a_Yaw; m_bDirtyOrientation = true; WrapRotation(); } void cEntity::SetPitch(double a_Pitch) { m_Rot.y = a_Pitch; m_bDirtyOrientation = true; WrapRotation(); } void cEntity::SetRoll(double a_Roll) { m_Rot.z = a_Roll; m_bDirtyOrientation = true; } void cEntity::SetSpeed(double a_SpeedX, double a_SpeedY, double a_SpeedZ) { m_Speed.Set(a_SpeedX, a_SpeedY, a_SpeedZ); WrapSpeed(); } void cEntity::SetSpeedX(double a_SpeedX) { SetSpeed(a_SpeedX, m_Speed.y, m_Speed.z); } void cEntity::SetSpeedY(double a_SpeedY) { SetSpeed(m_Speed.x, a_SpeedY, m_Speed.z); } void cEntity::SetSpeedZ(double a_SpeedZ) { SetSpeed(m_Speed.x, m_Speed.y, a_SpeedZ); } void cEntity::AddSpeed(double a_AddSpeedX, double a_AddSpeedY, double a_AddSpeedZ) { SetSpeed(m_Speed.x + a_AddSpeedX, m_Speed.y + a_AddSpeedY, m_Speed.z + a_AddSpeedZ); } void cEntity::AddSpeedX(double a_AddSpeedX) { AddSpeed(a_AddSpeedX, 0, 0); } void cEntity::AddSpeedY(double a_AddSpeedY) { AddSpeed(0, a_AddSpeedY, 0); } void cEntity::AddSpeedZ(double a_AddSpeedZ) { AddSpeed(0, 0, a_AddSpeedZ); } void cEntity::HandleSpeedFromAttachee(float a_Forward, float a_Sideways) { Vector3d LookVector = m_Attachee->GetLookVector(); double AddSpeedX = LookVector.x * a_Forward + LookVector.z * a_Sideways; double AddSpeedZ = LookVector.z * a_Forward - LookVector.x * a_Sideways; SetSpeed(AddSpeedX, 0, AddSpeedZ); BroadcastMovementUpdate(); } void cEntity::SteerVehicle(float a_Forward, float a_Sideways) { if (m_AttachedTo == nullptr) { return; } if ((a_Forward != 0.0f) || (a_Sideways != 0.0f)) { m_AttachedTo->HandleSpeedFromAttachee(a_Forward, a_Sideways); } } bool cEntity::IsTicking(void) const { ASSERT(!(m_IsTicking && (m_ParentChunk == nullptr))); // We shouldn't be ticking if we have no parent chunk return m_IsTicking; } //////////////////////////////////////////////////////////////////////////////// // Get look vector (this is NOT a rotation!) Vector3d cEntity::GetLookVector(void) const { Matrix4d m; m.Init(Vector3d(), 0, m_Rot.x, -m_Rot.y); Vector3d Look = m.Transform(Vector3d(0, 0, 1)); return Look; } //////////////////////////////////////////////////////////////////////////////// // Set position void cEntity::SetPosition(const Vector3d & a_Position) { // Clamp the positions to exactly representable single-precision floating point values // This is necessary to avoid rounding errors in the noise generator and overflows in the chunk loader const double MaxFloat = std::pow(2, std::numeric_limits().digits); const double ClampedPosX = Clamp(a_Position.x, -MaxFloat, MaxFloat); const double ClampedPosY = Clamp(a_Position.y, -MaxFloat, MaxFloat); const double ClampedPosZ = Clamp(a_Position.z, -MaxFloat, MaxFloat); m_LastPosition = m_Position; m_Position = {ClampedPosX, ClampedPosY, ClampedPosZ}; } void cEntity::AddLeashedMob(cMonster * a_Monster) { // Not there already ASSERT(std::find(m_LeashedMobs.begin(), m_LeashedMobs.end(), a_Monster) == m_LeashedMobs.end()); m_LeashedMobs.push_back(a_Monster); } void cEntity::RemoveLeashedMob(cMonster * a_Monster) { ASSERT(a_Monster->GetLeashedTo() == this); // Must exists ASSERT(std::find(m_LeashedMobs.begin(), m_LeashedMobs.end(), a_Monster) != m_LeashedMobs.end()); m_LeashedMobs.remove(a_Monster); } void cEntity::BroadcastLeashedMobs() { // If has any mob leashed broadcast every leashed entity to this if (HasAnyMobLeashed()) { for (auto LeashedMob : m_LeashedMobs) { m_World->BroadcastLeashEntity(*LeashedMob, *this); } } } void cEntity::OnDetach() { } void cEntity::BroadcastDeathMessage(TakeDamageInfo & a_TDI) { cPluginManager * PluginManager = cRoot::Get()->GetPluginManager(); AString Name; if (IsPlayer()) { cPlayer * Player = static_cast(this); Name = Player->GetName(); } else if (IsMob()) { cMonster * Monster = static_cast(this); if (Monster->HasCustomName()) { Name = Monster->GetCustomName(); } else { Name = NamespaceSerializer::PrettifyEntityName(AString(NamespaceSerializer::From(Monster->GetMobType())), Monster->IsTame()); } } else { // If the entity is neither a player nor a mob, we should quit. return; } if (a_TDI.Attacker == nullptr) { const AString DamageText = [&] { switch (a_TDI.DamageType) { case dtRangedAttack: return "was shot"; case dtLightning: return "was plasmified by lightining"; case dtFalling: return GetRandomProvider().RandBool() ? "fell to death" : "hit the ground too hard"; case dtDrowning: return "drowned"; case dtSuffocating: return GetRandomProvider().RandBool() ? "git merge'd into a block" : "fused with a block"; case dtStarving: return "forgot the importance of food"; case dtCactusContact: return "was impaled on a cactus"; case dtMagmaContact: return "discovered the floor was lava"; case dtLavaContact: return "was melted by lava"; case dtPoisoning: return "died from septicaemia"; case dtWithering: return "is a husk of their former selves"; case dtOnFire: return "forgot to stop, drop, and roll"; case dtFireContact: return "burnt themselves to death"; case dtInVoid: return "somehow fell out of the world"; case dtPotionOfHarming: return "was magicked to death"; case dtEnderPearl: return "misused an ender pearl"; case dtAdmin: return "was administrator'd"; case dtExplosion: return "blew up"; case dtAttack: return "was attacked by thin air"; case dtEnvironment: return "played too much dress up"; // This is not vanilla - added a own pun } UNREACHABLE("Unsupported damage type"); }(); auto DeathMessage = fmt::format(FMT_STRING("{} {}"), Name, DamageText); PluginManager->CallHookKilled(*this, a_TDI, DeathMessage); if (!DeathMessage.empty()) { GetWorld()->BroadcastChatDeath(DeathMessage); } } else if (a_TDI.Attacker->IsPlayer()) { cPlayer * Killer = static_cast(a_TDI.Attacker); auto DeathMessage = fmt::format(FMT_STRING("{0} was killed by {1}"), Name, Killer->GetName()); PluginManager->CallHookKilled(*this, a_TDI, DeathMessage); if (!DeathMessage.empty()) { GetWorld()->BroadcastChatDeath(DeathMessage); } } // This will trigger if a player / tamed pet has been killed by another mob / tamed pet. else if (a_TDI.Attacker->IsMob()) { cMonster * Monster = static_cast(a_TDI.Attacker); AString DeathMessage; if (Monster->HasCustomName()) { DeathMessage = fmt::format(FMT_STRING("{0} was killed by {1}"), Name, Monster->GetCustomName()); } else { AString KillerName = NamespaceSerializer::PrettifyEntityName(AString(NamespaceSerializer::From(Monster->GetMobType())), Monster->IsTame()); DeathMessage = fmt::format(FMT_STRING("{0} was killed by a {1}"), Name, KillerName); } PluginManager->CallHookKilled(*this, a_TDI, DeathMessage); if (!DeathMessage.empty()) { GetWorld()->BroadcastChatDeath(DeathMessage); } } } ================================================ FILE: src/Entities/Entity.h ================================================ #pragma once #include "../BoundingBox.h" #include "../Item.h" #include "../OSSupport/AtomicUniquePtr.h" // Place this macro in the public section of each cEntity descendant class and you're done :) #define CLASS_PROTODEF(classname) \ virtual bool IsA(const char * a_ClassName) const override\ { \ return ((a_ClassName != nullptr) && ((strcmp(a_ClassName, #classname) == 0) || Super::IsA(a_ClassName))); \ } \ virtual const char * GetClass(void) const override \ { \ return #classname; \ } \ static const char * GetClassStatic(void) \ { \ return #classname; \ } \ virtual const char * GetParentClass(void) const override \ { \ return Super::GetClass(); \ } #define POSX_TOINT FloorC(GetPosX()) #define POSY_TOINT FloorC(GetPosY()) #define POSZ_TOINT FloorC(GetPosZ()) #define POS_TOINT GetPosition().Floor() #define GET_AND_VERIFY_CURRENT_CHUNK(ChunkVarName, X, Z) \ cChunk * ChunkVarName = a_Chunk.GetNeighborChunk(X, Z); \ do { \ if ((ChunkVarName == nullptr) || !ChunkVarName->IsValid()) \ { \ return; \ } \ } while (false) class cWorld; class cClientHandle; class cPlayer; class cChunk; class cMonster; // tolua_begin struct TakeDamageInfo { eDamageType DamageType; // Where does the damage come from? Being hit / on fire / contact with cactus / ... cEntity * Attacker; // The attacking entity; valid only for dtAttack int RawDamage; // What damage would the receiver get without any armor. Usually: attacker mob type + weapons float FinalDamage; // What actual damage will be received. Usually: m_RawDamage minus armor Vector3d Knockback; // The amount and direction of knockback received from the damage // TODO: Effects - list of effects that the hit is causing. Unknown representation yet } ; // tolua_end // tolua_begin class cEntity { protected: /** State variables for MoveToWorld. */ struct sWorldChangeInfo { cWorld * m_NewWorld; Vector3d m_NewPosition; bool m_SetPortalCooldown; }; public: enum eEntityType { etEntity, // For all other types etEnderCrystal, etPlayer, etPickup, etMonster, etFallingBlock, etMinecart, etBoat, etTNT, etProjectile, etExpOrb, etFloater, etItemFrame, etPainting, etLeashKnot, // Common variations etMob = etMonster, // DEPRECATED, use etMonster instead! } ; // tolua_end static const int FIRE_TICKS_PER_DAMAGE = 10; ///< Ticks to wait between damaging an entity when it stands in fire static const int FIRE_DAMAGE = 1; ///< Damage to deal when standing in fire static const int LAVA_TICKS_PER_DAMAGE = 10; ///< Ticks to wait between damaging an entity when it stands in lava static const int LAVA_DAMAGE = 4; ///< Damage to deal when standing in lava static const int BURN_TICKS_PER_DAMAGE = 20; ///< Ticks to wait between damaging an entity when it is burning static const int BURN_DAMAGE = 1; ///< Damage to deal when the entity is burning static const int BURN_TICKS = 160; ///< Ticks to keep an entity burning after it has stood in lava / fire static const int MAX_AIR_LEVEL = 300; ///< Maximum air an entity can have static const int DROWNING_TICKS = 20; ///< Number of ticks per heart of damage static const int VOID_BOUNDARY = -64; ///< Y position to begin applying void damage static const int FALL_DAMAGE_HEIGHT = 4; ///< Y difference after which fall damage is applied /** Special ID that is considered an "invalid value", signifying no entity. */ static const UInt32 INVALID_ID = 0; // Exported to Lua in ManualBindings.cpp, ToLua doesn't parse initialized constants. cEntity(eEntityType a_EntityType, Vector3d a_Pos, float a_Width, float a_Height); virtual ~cEntity() = default; /** Spawns the entity in the world; returns true if spawned, false if not (plugin disallowed). Adds the entity to the world. */ bool Initialize(OwnedEntity a_Self, cWorld & a_EntityWorld); /** Called when a player begins spectating this entity. */ void OnAcquireSpectator(cPlayer & a_Player); /** Called when the entity is added to a world. e.g after first spawning or after successfuly moving between worlds. \param a_World The world being added to. */ virtual void OnAddToWorld(cWorld & a_World); /** Called when a player stops spectating this entity. */ void OnLoseSpectator(cPlayer & a_Player); /** Called when the entity is removed from a world. e.g. When the entity is destroyed or moved to a different world. \param a_World The world being removed from. */ virtual void OnRemoveFromWorld(cWorld & a_World); // tolua_begin eEntityType GetEntityType(void) const { return m_EntityType; } bool IsArrow (void) const { return IsA("cArrowEntity"); } bool IsEnderCrystal(void) const { return (m_EntityType == etEnderCrystal); } bool IsPlayer (void) const { return (m_EntityType == etPlayer); } bool IsPickup (void) const { return (m_EntityType == etPickup); } bool IsMob (void) const { return (m_EntityType == etMonster); } bool IsPawn (void) const { return (IsMob() || IsPlayer()); } bool IsFallingBlock(void) const { return (m_EntityType == etFallingBlock); } bool IsMinecart (void) const { return (m_EntityType == etMinecart); } bool IsBoat (void) const { return (m_EntityType == etBoat); } bool IsTNT (void) const { return (m_EntityType == etTNT); } bool IsProjectile (void) const { return (m_EntityType == etProjectile); } bool IsExpOrb (void) const { return (m_EntityType == etExpOrb); } bool IsFloater (void) const { return (m_EntityType == etFloater); } bool IsItemFrame (void) const { return (m_EntityType == etItemFrame); } bool IsLeashKnot (void) const { return (m_EntityType == etLeashKnot); } bool IsPainting (void) const { return (m_EntityType == etPainting); } /** Returns true if the entity is of the specified class or a subclass (cPawn's IsA("cEntity") returns true) */ virtual bool IsA(const char * a_ClassName) const; /** Returns the class name of this class */ static const char * GetClassStatic(void); /** Returns the topmost class name for the object */ virtual const char * GetClass(void) const; /** Returns the topmost class's parent class name for the object. cEntity returns an empty string (no parent). */ virtual const char * GetParentClass(void) const; /** Returns whether blocks can be placed intersecting this entities' hitbox */ virtual bool DoesPreventBlockPlacement(void) const { return true; } cWorld * GetWorld(void) const { return m_World; } double GetHeadYaw (void) const { return m_HeadYaw; } // In degrees float GetHeight (void) const { return m_Height; } double GetMass (void) const { return m_Mass; } double GetPosX (void) const { return m_Position.x; } double GetPosY (void) const { return m_Position.y; } double GetPosZ (void) const { return m_Position.z; } double GetYaw (void) const { return m_Rot.x; } // In degrees, [-180, +180) double GetPitch (void) const { return m_Rot.y; } // In degrees, [-180, +180), but normal client clips to [-90, +90] double GetRoll (void) const { return m_Rot.z; } // In degrees, unused in current client Vector3d GetLookVector(void) const; double GetSpeedX (void) const { return m_Speed.x; } double GetSpeedY (void) const { return m_Speed.y; } double GetSpeedZ (void) const { return m_Speed.z; } float GetWidth (void) const { return m_Width; } int GetChunkX(void) const { return FloorC(m_Position.x / cChunkDef::Width); } int GetChunkZ(void) const { return FloorC(m_Position.z / cChunkDef::Width); } // Get the Entity's axis aligned bounding box, with absolute (world-relative) coordinates. cBoundingBox GetBoundingBox() const { return cBoundingBox(GetPosition(), GetWidth() / 2, GetHeight()); } void SetHeadYaw (double a_HeadYaw); void SetMass (double a_Mass); void SetPosX (double a_PosX) { SetPosition({a_PosX, m_Position.y, m_Position.z}); } void SetPosY (double a_PosY) { SetPosition({m_Position.x, a_PosY, m_Position.z}); } void SetPosZ (double a_PosZ) { SetPosition({m_Position.x, m_Position.y, a_PosZ}); } void SetPosition(double a_PosX, double a_PosY, double a_PosZ) { SetPosition({a_PosX, a_PosY, a_PosZ}); } void SetPosition(const Vector3d & a_Position); void SetYaw (double a_Yaw); // In degrees, normalizes to [-180, +180) void SetPitch (double a_Pitch); // In degrees, normalizes to [-180, +180) void SetRoll (double a_Roll); // In degrees, normalizes to [-180, +180) /** Sets the speed of the entity, measured in m / sec */ void SetSpeed(double a_SpeedX, double a_SpeedY, double a_SpeedZ); /** Sets the speed of the entity, measured in m / sec */ void SetSpeed(Vector3d a_Speed) { SetSpeed(a_Speed.x, a_Speed.y, a_Speed.z); } /** Sets the speed in the X axis, leaving the other speed components intact. Measured in m / sec. */ void SetSpeedX(double a_SpeedX); /** Sets the speed in the Y axis, leaving the other speed components intact. Measured in m / sec. */ void SetSpeedY(double a_SpeedY); /** Sets the speed in the Z axis, leaving the other speed components intact. Measured in m / sec. */ void SetSpeedZ(double a_SpeedZ); void AddPosX (double a_AddPosX) { AddPosition(a_AddPosX, 0, 0); } void AddPosY (double a_AddPosY) { AddPosition(0, a_AddPosY, 0); } void AddPosZ (double a_AddPosZ) { AddPosition(0, 0, a_AddPosZ); } void AddPosition(double a_AddPosX, double a_AddPosY, double a_AddPosZ) { SetPosition(m_Position + Vector3d(a_AddPosX, a_AddPosY, a_AddPosZ)); } void AddPosition(const Vector3d & a_AddPos) { AddPosition(a_AddPos.x, a_AddPos.y, a_AddPos.z); } void AddSpeed (double a_AddSpeedX, double a_AddSpeedY, double a_AddSpeedZ); void AddSpeed (const Vector3d & a_AddSpeed) { AddSpeed(a_AddSpeed.x, a_AddSpeed.y, a_AddSpeed.z); } void AddSpeedX (double a_AddSpeedX); void AddSpeedY (double a_AddSpeedY); void AddSpeedZ (double a_AddSpeedZ); virtual void HandleSpeedFromAttachee(float a_Forward, float a_Sideways); void SteerVehicle(float a_Forward, float a_Sideways); inline UInt32 GetUniqueID(void) const { return m_UniqueID; } /** Deprecated. Use IsTicking instead. */ inline bool IsDestroyed() const {return !IsTicking();} /** Returns true if the entity is valid and ticking. Returns false if the entity is not ticking and is about to leave its current world either via teleportation or destruction. If this returns false, you must stop using the cEntity pointer you have. */ bool IsTicking(void) const; // tolua_end /** Destroys the entity, schedules it for memory freeing and broadcasts the DestroyEntity packet */ void Destroy(); // tolua_begin /** Makes this pawn take damage from an attack by a_Attacker. Damage values are calculated automatically and DoTakeDamage() called */ void TakeDamage(cEntity & a_Attacker); /** Makes this entity take the specified damage. The final damage is calculated using current armor, then DoTakeDamage() called */ void TakeDamage(eDamageType a_DamageType, cEntity * a_Attacker, int a_RawDamage, double a_KnockbackAmount); /** Makes this entity take the specified damage. The final damage is calculated using current armor, then DoTakeDamage() called */ void TakeDamage(eDamageType a_DamageType, UInt32 a_Attacker, int a_RawDamage, double a_KnockbackAmount); /** Makes this entity take the specified damage. The values are packed into a TDI, knockback calculated, then sent through DoTakeDamage() */ void TakeDamage(eDamageType a_DamageType, cEntity * a_Attacker, int a_RawDamage, float a_FinalDamage, double a_KnockbackAmount); float GetGravity(void) const { return m_Gravity; } void SetGravity(float a_Gravity) { m_Gravity = a_Gravity; } float GetAirDrag(void) const { return m_AirDrag; } void SetAirDrag(float a_AirDrag) { m_AirDrag = a_AirDrag; } /** Sets the rotation to match the speed vector (entity goes "face-forward") */ void SetYawFromSpeed(void); /** Sets the pitch to match the speed vector (entity gies "face-forward") */ void SetPitchFromSpeed(void); // tolua_end /** Exported in ManualBindings */ const Vector3d & GetPosition(void) const { return m_Position; } /** Exported in ManualBindings */ const Vector3d & GetSpeed(void) const { return m_Speed; } /** Returns the last position we sent to all the clients. Use this to initialize clients with our position. */ Vector3d GetLastSentPosition(void) const { return m_LastSentPosition; } /** Makes this entity take damage specified in the a_TDI. The TDI is sent through plugins first, then applied. If it returns false, the entity hasn't receive any damage. */ virtual bool DoTakeDamage(TakeDamageInfo & a_TDI); // tolua_begin /** Returns the hitpoints that this pawn can deal to a_Receiver using its equipped items */ virtual int GetRawDamageAgainst(const cEntity & a_Receiver); /** Returns whether armor will protect against the specified damage type */ virtual bool ArmorCoversAgainst(eDamageType a_DamageType); /** Returns the hitpoints out of a_RawDamage that the currently equipped armor would cover */ virtual float GetArmorCoverAgainst(const cEntity * a_Attacker, eDamageType a_DamageType, int a_RawDamage); /** Returns the hitpoints that the currently equipped armor's enchantments would cover */ virtual float GetEnchantmentCoverAgainst(const cEntity * a_Attacker, eDamageType a_DamageType, int a_Damage); /** Returns explosion knock back reduction percent from blast protection level @return knock back reduce percent */ virtual float GetEnchantmentBlastKnockbackReduction(); /** Returns the knockback amount that the currently equipped items would cause to a_Receiver on a hit */ virtual double GetKnockbackAmountAgainst(const cEntity & a_Receiver); /** Returns the curently equipped weapon; empty item if none */ virtual cItem GetEquippedWeapon(void) const { return cItem(); } /** Returns the currently equipped helmet; empty item if none */ virtual cItem GetEquippedHelmet(void) const { return cItem(); } /** Returns the currently equipped chestplate; empty item if none */ virtual cItem GetEquippedChestplate(void) const { return cItem(); } /** Returns the currently equipped leggings; empty item if none */ virtual cItem GetEquippedLeggings(void) const { return cItem(); } /** Returns the currently equipped boots; empty item if none */ virtual cItem GetEquippedBoots(void) const { return cItem(); } /** Returns the currently offhand equipped item; empty item if none */ virtual cItem GetOffHandEquipedItem(void) const { return cItem(); } /** Applies damage to the armor after the armor blocked the given amount */ virtual void ApplyArmorDamage(int DamageBlocked); // tolua_end /** Called when the health drops below zero. a_TDI's Attacker may be nullptr (environmental damage) */ virtual void KilledBy(TakeDamageInfo & a_TDI); // tolua_begin /** Called when the entity kills another entity. */ virtual void Killed(const cEntity & a_Victim, eDamageType a_DamageType) {} /** Heals the specified amount of HPs */ virtual void Heal(int a_HitPoints); /** Returns the health of this entity */ float GetHealth(void) const { return m_Health; } /** Sets the health of this entity; doesn't broadcast any hurt animation */ void SetHealth(float a_Health); // tolua_end virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk); /** Handles the physics of the entity - updates position based on speed, updates speed based on environment */ virtual void HandlePhysics(std::chrono::milliseconds a_Dt, cChunk & a_Chunk); /** Updates the state related to this entity being on fire */ virtual void TickBurning(cChunk & a_Chunk); /** Detects the time for application of cacti damage */ virtual void DetectCacti(void); /** Detects the time for application of magma block damage */ virtual void DetectMagma(void); /** Detects whether we are in a portal block and begins teleportation procedures if so Returns true if MoveToWorld() was called, false if not */ virtual bool DetectPortal(void); /** Handles when the entity is in the void */ virtual void TickInVoid(cChunk & a_Chunk); /** Called when the entity starts burning */ virtual void OnStartedBurning(void); /** Called when the entity finishes burning */ virtual void OnFinishedBurning(void); // tolua_begin /** Sets the maximum value for the health */ void SetMaxHealth(float a_MaxHealth); float GetMaxHealth(void) const { return m_MaxHealth; } /** Sets whether the entity is fireproof */ void SetIsFireproof(bool a_IsFireproof); virtual bool IsFireproof(void) const { return m_IsFireproof; } /** Puts the entity on fire for the specified amount of ticks */ void StartBurning(int a_TicksLeftBurning); /** Stops the entity from burning, resets all burning timers */ void StopBurning(void); // tolua_end /** Descendants override this function to send a command to the specified client to spawn the entity on the client. To spawn on all eligible clients, use cChunkMap::BroadcastSpawnEntity() */ virtual void SpawnOn(cClientHandle & a_Client) = 0; // tolua_begin /** Teleports to the entity specified */ virtual void TeleportToEntity(cEntity & a_Entity); /** Teleports to the coordinates specified */ virtual void TeleportToCoords(double a_PosX, double a_PosY, double a_PosZ); bool MoveToWorld(cWorld & a_World, Vector3d a_NewPosition, bool a_ShouldSetPortalCooldown = false, bool a_ShouldSendRespawn = true); bool MoveToWorld(cWorld & a_World, bool a_ShouldSendRespawn, Vector3d a_NewPosition) { return MoveToWorld(a_World, a_NewPosition, false, a_ShouldSendRespawn); } /** Moves entity to specified world, taking a world pointer */ bool MoveToWorld(cWorld & a_World, bool a_ShouldSendRespawn = true); /** Moves entity to specified world, taking a world name */ bool MoveToWorld(const AString & a_WorldName, bool a_ShouldSendRespawn = true); // tolua_end /** Returns true if a world change is scheduled to happen. */ bool IsWorldChangeScheduled() const { return (m_WorldChangeInfo.m_NewWorld != nullptr); } /** Updates clients of changes in the entity. */ virtual void BroadcastMovementUpdate(const cClientHandle * a_Exclude = nullptr); /** Gets entity (vehicle) attached to this entity */ cEntity * GetAttached(); /** Attaches to the specified entity; detaches from any previous one first. */ void AttachTo(cEntity & a_AttachTo); /** Detaches from the currently attached entity, if any. */ void Detach(void); /** Returns true if this entity is attached to the specified entity */ bool IsAttachedTo(const cEntity * a_Entity) const; /** Returns whether the entity's orientation has been set manually. Primarily inteded for protocol use. */ bool IsOrientationDirty() const; /** Makes sure head yaw is not over the specified range. */ void WrapHeadYaw(); /** Makes sure rotation is not over the specified range. */ void WrapRotation(); /** Makes speed is not over 20. Max speed is 20 blocks / second */ void WrapSpeed(); // tolua_begin // COMMON metadata flags; descendants may override the defaults: virtual bool IsCrouched (void) const { return false; } virtual bool IsElytraFlying(void) const { return false; } virtual bool IsInvisible (void) const { return false; } virtual bool IsOnFire (void) const { return m_TicksLeftBurning > 0; } virtual bool IsRclking (void) const { return false; } virtual bool IsRiding (void) const { return false; } virtual bool IsSprinting (void) const { return false; } /** Returns true if any part of the entity is in a fire block */ virtual bool IsInFire(void) const { return m_IsInFire; } /** Returns true if any part of the entity is in a lava block */ virtual bool IsInLava(void) const { return m_IsInLava; } /** Returns true if any part of the entity is in a water block */ virtual bool IsInWater(void) const { return m_IsInWater; } /** Returns true if any part of the entity is in a water block */ virtual bool IsHeadInWater(void) const { return m_IsHeadInWater; } /** Gets remaining air of a monster */ int GetAirLevel(void) const { return m_AirLevel; } /** Gets number of ticks this entity has been alive for */ long int GetTicksAlive(void) const { return m_TicksAlive; } /** Gets the invulnerable ticks from the entity */ int GetInvulnerableTicks(void) const { return m_InvulnerableTicks; } /** Set the invulnerable ticks from the entity */ void SetInvulnerableTicks(int a_InvulnerableTicks) { m_InvulnerableTicks = a_InvulnerableTicks; } /** Returns whether the entity is on ground or not */ virtual bool IsOnGround(void) const { return m_bOnGround; } // tolua_end /** Called when the specified player right-clicks this entity */ virtual void OnRightClicked(cPlayer & a_Player) {} /** Returns the list of drops for this pawn when it is killed. May check a_Killer for special handling (sword of looting etc.). Called from KilledBy(). */ virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) { UNUSED(a_Drops); UNUSED(a_Killer); } /** Sets the internal world pointer to a new cWorld, doesn't update anything else. */ void SetWorld(cWorld * a_World) { m_World = a_World; } /** Sets the parent chunk, which is the chunk responsible for ticking this entity. Only cChunk::AddEntity and cChunk::RemoveEntity cChunk::~cChunk should ever call this. */ void SetParentChunk(cChunk * a_Chunk); /** Returns the chunk responsible for ticking this entity. */ cChunk * GetParentChunk() { return m_ParentChunk; } const cChunk * GetParentChunk() const { return m_ParentChunk; } /** Set the entity's status to either ticking or not ticking. */ void SetIsTicking(bool a_IsTicking); /** Update an entity's size, for example, on body stance changes. */ void SetSize(float a_Width, float a_Height); /** Adds a mob to the leashed list of mobs. */ void AddLeashedMob(cMonster * a_Monster); /** Removes a mob from the leashed list of mobs. */ void RemoveLeashedMob(cMonster * a_Monster); /** Returs whether the entity has any mob leashed to it. */ bool HasAnyMobLeashed() const { return m_LeashedMobs.size() > 0; } /** Announces a death message on chat about killing the entity. */ void BroadcastDeathMessage(TakeDamageInfo & a_TDI); protected: /** Structure storing the portal delay timer and cooldown boolean */ struct sPortalCooldownData { /** Ticks since entry of portal, used to delay teleportation */ unsigned short m_TicksDelayed; /** Whether the entity has just exited the portal, and should therefore not be teleported again. This prevents teleportation loops, and is reset when the entity has moved out of the portal. */ bool m_ShouldPreventTeleportation; }; /** Measured in meters / second (m / s) */ Vector3d m_Speed; /** The ID of the entity that is guaranteed to be unique within a single run of the server. Always nonzero (a zero UniqueID (cEntity::INVALID_ID) is used for error reporting). Note that the UniqueID is not persisted through storage. */ UInt32 m_UniqueID; float m_Health; float m_MaxHealth; /** The entity to which this entity is attached (vehicle), nullptr if none. */ cEntity * m_AttachedTo; /** The entity which is attached to this entity (rider), nullptr if none. */ cEntity * m_Attachee; /** Stores whether head yaw has been set manually */ bool m_bDirtyHead; /** Stores whether our yaw / pitch / roll (body orientation) has been set manually */ bool m_bDirtyOrientation; /** Stores whether we have sent a Velocity packet with a speed of zero (no speed) to the client Ensures that said packet is sent only once */ bool m_bHasSentNoSpeed; /** Stores if the entity is on the ground */ bool m_bOnGround; /** Stores gravity that is applied to an entity every tick For realistic effects, this should be negative. For spaaaaaaace, this can be zero or even positive */ float m_Gravity; /** Stores the air drag that is applied to the entity every tick, measured in speed ratio per tick Acts as air friction and slows down flight Will be interpolated if the server tick rate varies Data: https://minecraft.wiki/w/Entity#Motion_of_entities */ float m_AirDrag; /** Last position sent to client via the Relative Move or Teleport packets (not Velocity) Only updated if cEntity::BroadcastMovementUpdate() is called! */ Vector3d m_LastSentPosition; Vector3d m_LastPosition; eEntityType m_EntityType; cWorld * m_World; /** If field m_NewWorld not nullptr, a world change is scheduled and a task is queued in the current world. */ sWorldChangeInfo m_WorldChangeInfo; /** Whether the entity is capable of taking fire or lava damage. */ bool m_IsFireproof; /** Time, in ticks, since the last damage dealt by being on fire. Valid only if on fire (IsOnFire()) */ int m_TicksSinceLastBurnDamage; /** Time, in ticks, since the last damage dealt by standing in lava. Reset to zero when moving out of lava. */ int m_TicksSinceLastLavaDamage; /** Time, in ticks, since the last damage dealt by standing in fire. Reset to zero when moving out of fire. */ int m_TicksSinceLastFireDamage; /** Time, in ticks, until the entity extinguishes its fire */ int m_TicksLeftBurning; /** Time, in ticks, since the last damage dealt by the void. Reset to zero when moving out of the void. */ int m_TicksSinceLastVoidDamage; /** If any part of the entity is in a fire block */ bool m_IsInFire; /** If any part of the entity is in a lava block */ bool m_IsInLava; /** If any part of the entity is in a water block */ bool m_IsInWater; /** If the entity's head is in a water block */ bool m_IsHeadInWater; /** Air level of a mobile */ int m_AirLevel; int m_AirTickTimer; /** Portal delay timer and cooldown boolean data */ sPortalCooldownData m_PortalCooldownData; /** The number of ticks this entity has been alive for */ long int m_TicksAlive; /** Handles the moving of this entity between worlds. Should handle degenerate cases such as moving to the same world. */ void DoMoveToWorld(const sWorldChangeInfo & a_WorldChangeInfo); /** Applies friction to an entity @param a_Speed The speed vector to apply changes to @param a_SlowdownMultiplier The factor to reduce the speed by */ static void ApplyFriction(Vector3d & a_Speed, double a_SlowdownMultiplier, float a_Dt); /** Called in each tick to handle air-related processing i.e. drowning */ virtual void HandleAir(void); /** Called once per tick to set m_IsInFire, m_IsInLava, m_IsInWater and m_IsHeadInWater */ virtual void SetSwimState(cChunk & a_Chunk); /** Set the entities position and last sent position. Only to be used when the caller will broadcast a teleport or equivalent to clients. */ virtual void ResetPosition(Vector3d a_NewPos); /** If has any mobs are leashed, broadcasts every leashed entity to this. */ void BroadcastLeashedMobs(); /** Called when this entity dismounts from m_AttachedTo. */ virtual void OnDetach(); private: /** Whether the entity is ticking or not. If not, it is scheduled for removal or world-teleportation. */ bool m_IsTicking; /** The chunk which is responsible for ticking this entity. */ cChunk * m_ParentChunk; /** Measured in degrees, [-180, +180) */ double m_HeadYaw; /** Measured in degrees, [-180, +180) */ Vector3d m_Rot; /** Position of the entity's XZ center and Y bottom */ Vector3d m_Position; /** Measured in meter / second */ Vector3d m_WaterSpeed; /** Measured in Kilograms (Kg) */ double m_Mass; /** Width of the entity, in the XZ plane. Since entities are represented as cylinders, this is more of a diameter. */ float m_Width; /** Height of the entity (Y axis). */ float m_Height; /** If a player hit a entity, the entity receive a invulnerable of 10 ticks. While this ticks, a player can't hit this entity. */ int m_InvulnerableTicks; typedef std::list cMonsterList; /** List of leashed mobs to this entity */ cMonsterList m_LeashedMobs; /** List of players who are spectating this entity. */ std::vector m_Spectators; } ; // tolua_export ================================================ FILE: src/Entities/EntityEffect.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "EntityEffect.h" #include "Player.h" #include "../Chunk.h" #include "../Mobs/Monster.h" int cEntityEffect::GetPotionColor(short a_ItemDamage) { // Lowest six bits return (a_ItemDamage & 0x3f); } cEntityEffect::eType cEntityEffect::GetPotionEffectType(short a_ItemDamage) { // Lowest four bits // Potion effect bits are different from entity effect values // For reference: https://minecraft.wiki/w/Java_Edition_data_values#.22Potion_effect.22_bits switch (a_ItemDamage & 0x0f) { case 0x01: return cEntityEffect::effRegeneration; case 0x02: return cEntityEffect::effSpeed; case 0x03: return cEntityEffect::effFireResistance; case 0x04: return cEntityEffect::effPoison; case 0x05: return cEntityEffect::effInstantHealth; case 0x06: return cEntityEffect::effNightVision; case 0x08: return cEntityEffect::effWeakness; case 0x09: return cEntityEffect::effStrength; case 0x0a: return cEntityEffect::effSlowness; case 0x0b: return cEntityEffect::effJumpBoost; case 0x0c: return cEntityEffect::effInstantDamage; case 0x0d: return cEntityEffect::effWaterBreathing; case 0x0e: return cEntityEffect::effInvisibility; // No effect potions case 0x00: case 0x07: case 0x0f: { break; } } return cEntityEffect::effNoEffect; } short cEntityEffect::GetPotionEffectIntensity(short a_ItemDamage) { // Level II potion if the fifth lowest bit is set return ((a_ItemDamage & 0x20) != 0) ? 1 : 0; } int cEntityEffect::GetPotionEffectDuration(short a_ItemDamage) { // Base duration in ticks int base = 0; double TierCoeff = 1, ExtCoeff = 1, SplashCoeff = 1; switch (GetPotionEffectType(a_ItemDamage)) { case cEntityEffect::effRegeneration: case cEntityEffect::effPoison: { base = 900; break; } case cEntityEffect::effSpeed: case cEntityEffect::effFireResistance: case cEntityEffect::effNightVision: case cEntityEffect::effStrength: case cEntityEffect::effWaterBreathing: case cEntityEffect::effJumpBoost: case cEntityEffect::effInvisibility: { base = 3600; break; } case cEntityEffect::effWeakness: case cEntityEffect::effSlowness: { base = 1800; break; } default: break; } // If potion is level II, half the duration. If not, stays the same TierCoeff = (GetPotionEffectIntensity(a_ItemDamage) > 0) ? 0.5 : 1; // If potion is extended, multiply duration by 8 / 3. If not, stays the same // Extended potion if sixth lowest bit is set ExtCoeff = (a_ItemDamage & 0x40) ? (8.0 / 3.0) : 1; // If potion is splash potion, multiply duration by 3 / 4. If not, stays the same SplashCoeff = IsPotionDrinkable(a_ItemDamage) ? 1 : 0.75; // Ref.: // https://minecraft.wiki/w/Java_Edition_data_values#.22Tier.22_bit // https://minecraft.wiki/w/Java_Edition_data_values#.22Extended_duration.22_bit // https://minecraft.wiki/w/Java_Edition_data_values#.22Splash_potion.22_bit return static_cast(base * TierCoeff * ExtCoeff * SplashCoeff); } bool cEntityEffect::IsPotionDrinkable(short a_ItemDamage) { // Potions are drinkable if they are not splash potions. // i.e. potions are drinkable if the 14th lowest bit is not set // Ref.: https://minecraft.wiki/w/Java_Edition_data_values#.22Splash_potion.22_bit return ((a_ItemDamage & 0x4000) == 0); } cEntityEffect::cEntityEffect(): m_Ticks(0), m_Duration(0), m_Intensity(0), m_DistanceModifier(1) { } cEntityEffect::cEntityEffect(int a_Duration, short a_Intensity, double a_DistanceModifier): m_Ticks(0), m_Duration(a_Duration), m_Intensity(a_Intensity), m_DistanceModifier(a_DistanceModifier) { } cEntityEffect::cEntityEffect(const cEntityEffect & a_OtherEffect): m_Ticks(a_OtherEffect.m_Ticks), m_Duration(a_OtherEffect.m_Duration), m_Intensity(a_OtherEffect.m_Intensity), m_DistanceModifier(a_OtherEffect.m_DistanceModifier) { } cEntityEffect & cEntityEffect::operator =(cEntityEffect a_OtherEffect) { std::swap(m_Ticks, a_OtherEffect.m_Ticks); std::swap(m_Duration, a_OtherEffect.m_Duration); std::swap(m_Intensity, a_OtherEffect.m_Intensity); std::swap(m_DistanceModifier, a_OtherEffect.m_DistanceModifier); return *this; } std::unique_ptr cEntityEffect::CreateEntityEffect(cEntityEffect::eType a_EffectType, int a_Duration, short a_Intensity, double a_DistanceModifier) { switch (a_EffectType) { case cEntityEffect::effNoEffect: return std::make_unique(a_Duration, a_Intensity, a_DistanceModifier); case cEntityEffect::effAbsorption: return std::make_unique(a_Duration, a_Intensity, a_DistanceModifier); case cEntityEffect::effBlindness: return std::make_unique(a_Duration, a_Intensity, a_DistanceModifier); case cEntityEffect::effFireResistance: return std::make_unique(a_Duration, a_Intensity, a_DistanceModifier); case cEntityEffect::effHaste: return std::make_unique(a_Duration, a_Intensity, a_DistanceModifier); case cEntityEffect::effHealthBoost: return std::make_unique(a_Duration, a_Intensity, a_DistanceModifier); case cEntityEffect::effHunger: return std::make_unique(a_Duration, a_Intensity, a_DistanceModifier); case cEntityEffect::effInstantDamage: return std::make_unique(a_Duration, a_Intensity, a_DistanceModifier); case cEntityEffect::effInstantHealth: return std::make_unique(a_Duration, a_Intensity, a_DistanceModifier); case cEntityEffect::effInvisibility: return std::make_unique(a_Duration, a_Intensity, a_DistanceModifier); case cEntityEffect::effJumpBoost: return std::make_unique(a_Duration, a_Intensity, a_DistanceModifier); case cEntityEffect::effMiningFatigue: return std::make_unique(a_Duration, a_Intensity, a_DistanceModifier); case cEntityEffect::effNausea: return std::make_unique(a_Duration, a_Intensity, a_DistanceModifier); case cEntityEffect::effNightVision: return std::make_unique(a_Duration, a_Intensity, a_DistanceModifier); case cEntityEffect::effPoison: return std::make_unique(a_Duration, a_Intensity, a_DistanceModifier); case cEntityEffect::effRegeneration: return std::make_unique(a_Duration, a_Intensity, a_DistanceModifier); case cEntityEffect::effResistance: return std::make_unique(a_Duration, a_Intensity, a_DistanceModifier); case cEntityEffect::effSaturation: return std::make_unique(a_Duration, a_Intensity, a_DistanceModifier); case cEntityEffect::effSlowness: return std::make_unique(a_Duration, a_Intensity, a_DistanceModifier); case cEntityEffect::effSpeed: return std::make_unique(a_Duration, a_Intensity, a_DistanceModifier); case cEntityEffect::effStrength: return std::make_unique(a_Duration, a_Intensity, a_DistanceModifier); case cEntityEffect::effWaterBreathing: return std::make_unique(a_Duration, a_Intensity, a_DistanceModifier); case cEntityEffect::effWeakness: return std::make_unique(a_Duration, a_Intensity, a_DistanceModifier); case cEntityEffect::effWither: return std::make_unique(a_Duration, a_Intensity, a_DistanceModifier); } UNREACHABLE("Unsupported entity effect"); } void cEntityEffect::OnTick(cPawn & a_Target) { // Reduce the effect's duration ++m_Ticks; } //////////////////////////////////////////////////////////////////////////////// // cEntityEffectSpeed: void cEntityEffectSpeed::OnActivate(cPawn & a_Target) { if (a_Target.IsMob()) { cMonster * Mob = static_cast(&a_Target); Mob->SetRelativeWalkSpeed(Mob->GetRelativeWalkSpeed() + 0.2 * m_Intensity); } else if (a_Target.IsPlayer()) { cPlayer * Player = static_cast(&a_Target); Player->SetNormalMaxSpeed(Player->GetNormalMaxSpeed() + 0.2 * m_Intensity); Player->SetSprintingMaxSpeed(Player->GetSprintingMaxSpeed() + 0.26 * m_Intensity); Player->SetFlyingMaxSpeed(Player->GetFlyingMaxSpeed() + 0.2 * m_Intensity); } } void cEntityEffectSpeed::OnDeactivate(cPawn & a_Target) { if (a_Target.IsMob()) { cMonster * Mob = static_cast(&a_Target); Mob->SetRelativeWalkSpeed(Mob->GetRelativeWalkSpeed() - 0.2 * m_Intensity); } else if (a_Target.IsPlayer()) { cPlayer * Player = static_cast(&a_Target); Player->SetNormalMaxSpeed(Player->GetNormalMaxSpeed() - 0.2 * m_Intensity); Player->SetSprintingMaxSpeed(Player->GetSprintingMaxSpeed() - 0.26 * m_Intensity); Player->SetFlyingMaxSpeed(Player->GetFlyingMaxSpeed() - 0.2 * m_Intensity); } } //////////////////////////////////////////////////////////////////////////////// // cEntityEffectSlowness: void cEntityEffectSlowness::OnActivate(cPawn & a_Target) { if (a_Target.IsMob()) { cMonster * Mob = static_cast(&a_Target); Mob->SetRelativeWalkSpeed(Mob->GetRelativeWalkSpeed() - 0.15 * m_Intensity); } else if (a_Target.IsPlayer()) { cPlayer * Player = static_cast(&a_Target); Player->SetNormalMaxSpeed(Player->GetNormalMaxSpeed() - 0.15 * m_Intensity); Player->SetSprintingMaxSpeed(Player->GetSprintingMaxSpeed() - 0.195 * m_Intensity); Player->SetFlyingMaxSpeed(Player->GetFlyingMaxSpeed() - 0.15 * m_Intensity); } } void cEntityEffectSlowness::OnDeactivate(cPawn & a_Target) { if (a_Target.IsMob()) { cMonster * Mob = static_cast(&a_Target); Mob->SetRelativeWalkSpeed(Mob->GetRelativeWalkSpeed() + 0.15 * m_Intensity); } else if (a_Target.IsPlayer()) { cPlayer * Player = static_cast(&a_Target); Player->SetNormalMaxSpeed(Player->GetNormalMaxSpeed() + 0.15 * m_Intensity); Player->SetSprintingMaxSpeed(Player->GetSprintingMaxSpeed() + 0.195 * m_Intensity); Player->SetFlyingMaxSpeed(Player->GetFlyingMaxSpeed() + 0.15 * m_Intensity); } } //////////////////////////////////////////////////////////////////////////////// // cEntityEffectInstantHealth: void cEntityEffectInstantHealth::OnActivate(cPawn & a_Target) { // Base amount = 6, doubles for every increase in intensity int amount = static_cast(6 * (1 << m_Intensity) * m_DistanceModifier); if (a_Target.IsMob() && static_cast(a_Target).IsUndead()) { a_Target.TakeDamage(dtPotionOfHarming, nullptr, amount, 0); // TODO: Store attacker in a pointer-safe way, pass to TakeDamage return; } a_Target.Heal(amount); } //////////////////////////////////////////////////////////////////////////////// // cEntityEffectInstantDamage: void cEntityEffectInstantDamage::OnActivate(cPawn & a_Target) { // Base amount = 6, doubles for every increase in intensity int amount = static_cast(6 * (1 << m_Intensity) * m_DistanceModifier); if (a_Target.IsMob() && static_cast(a_Target).IsUndead()) { a_Target.Heal(amount); return; } a_Target.TakeDamage(dtPotionOfHarming, nullptr, amount, 0); // TODO: Store attacker in a pointer-safe way, pass to TakeDamage } //////////////////////////////////////////////////////////////////////////////// // cEntityEffectRegeneration: void cEntityEffectRegeneration::OnTick(cPawn & a_Target) { Super::OnTick(a_Target); if (a_Target.IsMob() && static_cast(a_Target).IsUndead()) { return; } // Regen frequency = 50 ticks, divided by potion level (Regen II = 25 ticks) int frequency = std::max(1, FloorC(50.0 / static_cast(m_Intensity + 1))); if ((m_Ticks % frequency) != 0) { return; } a_Target.Heal(1); } //////////////////////////////////////////////////////////////////////////////// // cEntityEffectHunger: void cEntityEffectHunger::OnTick(cPawn & a_Target) { Super::OnTick(a_Target); if (a_Target.IsPlayer()) { cPlayer & Target = static_cast(a_Target); Target.AddFoodExhaustion(0.025 * (static_cast(GetIntensity()) + 1.0)); // 0.5 per second = 0.025 per tick } } //////////////////////////////////////////////////////////////////////////////// // cEntityEffectInvisibility: void cEntityEffectInvisibility::BroadcastMetadata(cPawn & a_Target) { auto World = a_Target.GetWorld(); if (World != nullptr) { World->BroadcastEntityMetadata(a_Target); } } //////////////////////////////////////////////////////////////////////////////// // cEntityEffectWeakness: void cEntityEffectWeakness::OnTick(cPawn & a_Target) { Super::OnTick(a_Target); // Damage reduction = 0.5 damage, multiplied by potion level (Weakness II = 1 damage) // double dmg_reduc = 0.5 * (a_Effect.GetIntensity() + 1); // TODO: Implement me! // TODO: Weakened villager zombies can be turned back to villagers with the god apple } //////////////////////////////////////////////////////////////////////////////// // cEntityEffectPoison: void cEntityEffectPoison::OnTick(cPawn & a_Target) { Super::OnTick(a_Target); if (a_Target.IsMob()) { cMonster & Target = static_cast(a_Target); // Doesn't effect undead mobs, spiders if ( Target.IsUndead() || (Target.GetMobType() == mtSpider) || (Target.GetMobType() == mtCaveSpider) ) { return; } } // Poison frequency = 25 ticks, divided by potion level (Poison II = 12 ticks) int frequency = std::max(1, FloorC(25.0 / static_cast(m_Intensity + 1))); if ((m_Ticks % frequency) == 0) { // Cannot take poison damage when health is at 1 if (a_Target.GetHealth() > 1) { a_Target.TakeDamage(dtPoisoning, nullptr, 1, 0); } } } //////////////////////////////////////////////////////////////////////////////// // cEntityEffectWither: void cEntityEffectWither::OnTick(cPawn & a_Target) { Super::OnTick(a_Target); // Damage frequency = 40 ticks, divided by effect level (Wither II = 20 ticks) int frequency = std::max(1, FloorC(40.0 / static_cast(m_Intensity + 1))); if ((m_Ticks % frequency) == 0) { a_Target.TakeDamage(dtWither, nullptr, 1, 0); } } //////////////////////////////////////////////////////////////////////////////// // cEntityEffectSaturation: void cEntityEffectSaturation::OnTick(cPawn & a_Target) { if (a_Target.IsPlayer()) { cPlayer & Target = static_cast(a_Target); Target.SetFoodSaturationLevel(Target.GetFoodSaturationLevel() + (1 + m_Intensity)); // Increase saturation 1 per tick, adds 1 for every increase in level } } ================================================ FILE: src/Entities/EntityEffect.h ================================================ #pragma once class cPawn; // tolua_begin class cEntityEffect { public: /** All types of entity effects (numbers correspond to protocol / storage types) */ enum eType { effNoEffect = 0, effSpeed = 1, effSlowness = 2, effHaste = 3, effMiningFatigue = 4, effStrength = 5, effInstantHealth = 6, effInstantDamage = 7, effJumpBoost = 8, effNausea = 9, effRegeneration = 10, effResistance = 11, effFireResistance = 12, effWaterBreathing = 13, effInvisibility = 14, effBlindness = 15, effNightVision = 16, effHunger = 17, effWeakness = 18, effPoison = 19, effWither = 20, effHealthBoost = 21, effAbsorption = 22, effSaturation = 23, } ; /** Returns the potion color (used by the client for visuals), based on the potion's damage value */ static int GetPotionColor(short a_ItemDamage); /** Translates the potion's damage value into the entity effect that the potion gives */ static cEntityEffect::eType GetPotionEffectType(short a_ItemDamage); /** Retrieves the intensity level from the potion's damage value. Returns 0 for level I potions, 1 for level II potions. */ static short GetPotionEffectIntensity(short a_ItemDamage); /** Returns the effect duration, in ticks, based on the potion's damage value */ static int GetPotionEffectDuration(short a_ItemDamage); /** Returns true if the potion with the given damage is drinkable */ static bool IsPotionDrinkable(short a_ItemDamage); // tolua_end /** Creates an empty entity effect */ cEntityEffect(void); /** Creates an entity effect of the specified type @param a_Duration How long this effect will last, in ticks @param a_Intensity How strong the effect will be applied @param a_DistanceModifier The distance modifier for affecting potency, defaults to 1 */ cEntityEffect(int a_Duration, short a_Intensity, double a_DistanceModifier = 1); /** Creates an entity effect by copying another @param a_OtherEffect The other effect to copy */ cEntityEffect(const cEntityEffect & a_OtherEffect); /** Creates an entity effect by copying another @param a_OtherEffect The other effect to copy */ cEntityEffect & operator =(cEntityEffect a_OtherEffect); virtual ~cEntityEffect(void) = default; /** Creates a pointer to the proper entity effect from the effect type @warning This function creates raw pointers that must be manually managed. @param a_EffectType The effect type to create the effect from @param a_Duration How long this effect will last, in ticks @param a_Intensity How strong the effect will be applied @param a_DistanceModifier The distance modifier for affecting potency, defaults to 1 */ static std::unique_ptr CreateEntityEffect(cEntityEffect::eType a_EffectType, int a_Duration, short a_Intensity, double a_DistanceModifier); /** Returns how many ticks this effect has been active for */ int GetTicks(void) const { return m_Ticks; } /** Returns the duration of the effect */ int GetDuration(void) const { return m_Duration; } /** Returns how strong the effect will be applied */ short GetIntensity(void) const { return m_Intensity; } /** Returns the distance modifier for affecting potency */ double GetDistanceModifier(void) const { return m_DistanceModifier; } void SetTicks(int a_Ticks) { m_Ticks = a_Ticks; } void SetDuration(int a_Duration) { m_Duration = a_Duration; } void SetIntensity(short a_Intensity) { m_Intensity = a_Intensity; } void SetDistanceModifier(double a_DistanceModifier) { m_DistanceModifier = a_DistanceModifier; } /** Called on each tick. By default increases the m_Ticks, descendants may override to provide additional processing. */ virtual void OnTick(cPawn & a_Target); /** Called when the effect is first added to an entity */ virtual void OnActivate(cPawn & a_Target) { } /** Called when the effect is removed from an entity */ virtual void OnDeactivate(cPawn & a_Target) { } protected: /** How many ticks this effect has been active for */ int m_Ticks; /** How long this effect will last, in ticks */ int m_Duration; /** How strong the effect will be applied */ short m_Intensity; /** The distance modifier for affecting potency */ double m_DistanceModifier; }; // tolua_export class cEntityEffectSpeed: public cEntityEffect { using Super = cEntityEffect; public: cEntityEffectSpeed(int a_Duration, short a_Intensity, double a_DistanceModifier = 1): Super(a_Duration, a_Intensity, a_DistanceModifier) { } virtual void OnActivate(cPawn & a_Target) override; virtual void OnDeactivate(cPawn & a_Target) override; }; class cEntityEffectSlowness: public cEntityEffect { using Super = cEntityEffect; public: cEntityEffectSlowness(int a_Duration, short a_Intensity, double a_DistanceModifier = 1): Super(a_Duration, a_Intensity, a_DistanceModifier) { } virtual void OnActivate(cPawn & a_Target) override; virtual void OnDeactivate(cPawn & a_Target) override; }; class cEntityEffectHaste: public cEntityEffect { using Super = cEntityEffect; public: cEntityEffectHaste(int a_Duration, short a_Intensity, double a_DistanceModifier = 1): Super(a_Duration, a_Intensity, a_DistanceModifier) { } }; class cEntityEffectMiningFatigue: public cEntityEffect { using Super = cEntityEffect; public: cEntityEffectMiningFatigue(int a_Duration, short a_Intensity, double a_DistanceModifier = 1): Super(a_Duration, a_Intensity, a_DistanceModifier) { } }; class cEntityEffectStrength: public cEntityEffect { using Super = cEntityEffect; public: cEntityEffectStrength(int a_Duration, short a_Intensity, double a_DistanceModifier = 1): Super(a_Duration, a_Intensity, a_DistanceModifier) { } }; class cEntityEffectInstantHealth: public cEntityEffect { using Super = cEntityEffect; public: cEntityEffectInstantHealth(int a_Duration, short a_Intensity, double a_DistanceModifier = 1): Super(a_Duration, a_Intensity, a_DistanceModifier) { } virtual void OnActivate(cPawn & a_Target) override; }; class cEntityEffectInstantDamage: public cEntityEffect { using Super = cEntityEffect; public: cEntityEffectInstantDamage(int a_Duration, short a_Intensity, double a_DistanceModifier = 1): Super(a_Duration, a_Intensity, a_DistanceModifier) { } virtual void OnActivate(cPawn & a_Target) override; }; class cEntityEffectJumpBoost: public cEntityEffect { using Super = cEntityEffect; public: cEntityEffectJumpBoost(int a_Duration, short a_Intensity, double a_DistanceModifier = 1): Super(a_Duration, a_Intensity, a_DistanceModifier) { } }; class cEntityEffectNausea: public cEntityEffect { using Super = cEntityEffect; public: cEntityEffectNausea(int a_Duration, short a_Intensity, double a_DistanceModifier = 1): Super(a_Duration, a_Intensity, a_DistanceModifier) { } }; class cEntityEffectRegeneration: public cEntityEffect { using Super = cEntityEffect; public: cEntityEffectRegeneration(int a_Duration, short a_Intensity, double a_DistanceModifier = 1): Super(a_Duration, a_Intensity, a_DistanceModifier) { } virtual void OnTick(cPawn & a_Target) override; }; class cEntityEffectResistance: public cEntityEffect { using Super = cEntityEffect; public: cEntityEffectResistance(int a_Duration, short a_Intensity, double a_DistanceModifier = 1): Super(a_Duration, a_Intensity, a_DistanceModifier) { } }; class cEntityEffectFireResistance: public cEntityEffect { using Super = cEntityEffect; public: cEntityEffectFireResistance(int a_Duration, short a_Intensity, double a_DistanceModifier = 1): Super(a_Duration, a_Intensity, a_DistanceModifier) { } }; class cEntityEffectWaterBreathing: public cEntityEffect { using Super = cEntityEffect; public: cEntityEffectWaterBreathing(int a_Duration, short a_Intensity, double a_DistanceModifier = 1): Super(a_Duration, a_Intensity, a_DistanceModifier) { } }; class cEntityEffectInvisibility: public cEntityEffect { using Super = cEntityEffect; public: cEntityEffectInvisibility(int a_Duration, short a_Intensity, double a_DistanceModifier = 1): Super(a_Duration, a_Intensity, a_DistanceModifier) { } virtual void OnActivate (cPawn & a_Target) override { BroadcastMetadata(a_Target); } virtual void OnDeactivate(cPawn & a_Target) override { BroadcastMetadata(a_Target); } private: static void BroadcastMetadata(cPawn & a_Target); }; class cEntityEffectBlindness: public cEntityEffect { using Super = cEntityEffect; public: cEntityEffectBlindness(int a_Duration, short a_Intensity, double a_DistanceModifier = 1): Super(a_Duration, a_Intensity, a_DistanceModifier) { } }; class cEntityEffectNightVision: public cEntityEffect { using Super = cEntityEffect; public: cEntityEffectNightVision(int a_Duration, short a_Intensity, double a_DistanceModifier = 1): Super(a_Duration, a_Intensity, a_DistanceModifier) { } }; class cEntityEffectHunger: public cEntityEffect { using Super = cEntityEffect; public: cEntityEffectHunger(int a_Duration, short a_Intensity, double a_DistanceModifier = 1): Super(a_Duration, a_Intensity, a_DistanceModifier) { } // cEntityEffect overrides: virtual void OnTick(cPawn & a_Target) override; }; class cEntityEffectWeakness: public cEntityEffect { using Super = cEntityEffect; public: cEntityEffectWeakness(int a_Duration, short a_Intensity, double a_DistanceModifier = 1): Super(a_Duration, a_Intensity, a_DistanceModifier) { } // cEntityEffect overrides: virtual void OnTick(cPawn & a_Target) override; }; class cEntityEffectPoison: public cEntityEffect { using Super = cEntityEffect; public: cEntityEffectPoison(int a_Duration, short a_Intensity, double a_DistanceModifier = 1): Super(a_Duration, a_Intensity, a_DistanceModifier) { } // cEntityEffect overrides: virtual void OnTick(cPawn & a_Target) override; }; class cEntityEffectWither: public cEntityEffect { using Super = cEntityEffect; public: cEntityEffectWither(int a_Duration, short a_Intensity, double a_DistanceModifier = 1): Super(a_Duration, a_Intensity, a_DistanceModifier) { } // cEntityEffect overrides: virtual void OnTick(cPawn & a_Target) override; }; class cEntityEffectHealthBoost: public cEntityEffect { using Super = cEntityEffect; public: cEntityEffectHealthBoost(int a_Duration, short a_Intensity, double a_DistanceModifier = 1): Super(a_Duration, a_Intensity, a_DistanceModifier) { } }; class cEntityEffectAbsorption: public cEntityEffect { using Super = cEntityEffect; public: cEntityEffectAbsorption(int a_Duration, short a_Intensity, double a_DistanceModifier = 1): Super(a_Duration, a_Intensity, a_DistanceModifier) { } }; class cEntityEffectSaturation: public cEntityEffect { using Super = cEntityEffect; public: cEntityEffectSaturation(int a_Duration, short a_Intensity, double a_DistanceModifier = 1): Super(a_Duration, a_Intensity, a_DistanceModifier) { } virtual void OnTick(cPawn & a_Target) override; }; ================================================ FILE: src/Entities/ExpBottleEntity.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "ExpBottleEntity.h" #include "../World.h" #include "../EffectID.h" cExpBottleEntity::cExpBottleEntity(cEntity * a_Creator, Vector3d a_Pos, Vector3d a_Speed) : Super(pkExpBottle, a_Creator, a_Pos, 0.25f, 0.25f) { SetSpeed(a_Speed); } void cExpBottleEntity::OnHitSolidBlock(Vector3d a_HitPos, eBlockFace a_HitFace) { Break(a_HitPos); } void cExpBottleEntity::OnHitEntity(cEntity & a_EntityHit, Vector3d a_HitPos) { Break(a_HitPos); } void cExpBottleEntity::Break(Vector3d a_HitPos) { // Spawn an experience orb with a reward between 3 and 11. m_World->BroadcastSoundParticleEffect(EffectID::PARTICLE_SPLASH_POTION, GetPosition().Floor(), 0); m_World->SpawnExperienceOrb(GetPosX(), GetPosY(), GetPosZ(), GetRandomProvider().RandInt(3, 11)); Destroy(); } ================================================ FILE: src/Entities/ExpBottleEntity.h ================================================ // ExpBottleEntity.h // Declares the cExpBottleEntity class representing the thrown exp bottle #pragma once #include "ProjectileEntity.h" // tolua_begin class cExpBottleEntity : public cProjectileEntity { // tolua_end using Super = cProjectileEntity; public: // tolua_export CLASS_PROTODEF(cExpBottleEntity) cExpBottleEntity(cEntity * a_Creator, Vector3d a_Pos, Vector3d a_Speed); protected: // cProjectileEntity overrides: virtual void OnHitSolidBlock(Vector3d a_HitPos, eBlockFace a_HitFace) override; virtual void OnHitEntity (cEntity & a_EntityHit, Vector3d a_HitPos) override; /** Breaks the bottle, fires its particle effects and sounds @param a_HitPos The position where the bottle will break */ void Break(Vector3d a_HitPos); }; // tolua_export ================================================ FILE: src/Entities/ExpOrb.cpp ================================================ #include "Globals.h" #include "ExpOrb.h" #include "Player.h" #include "../ClientHandle.h" cExpOrb::cExpOrb(Vector3d a_Pos, int a_Reward): Super(etExpOrb, a_Pos, 0.5f, 0.5f), m_Reward(a_Reward), m_Timer(0) { SetMaxHealth(5); SetHealth(5); SetGravity(-16); SetAirDrag(0.02f); } void cExpOrb::SpawnOn(cClientHandle & a_Client) { a_Client.SendExperienceOrb(*this); m_bDirtyOrientation = false; m_bDirtyHead = false; } void cExpOrb::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { DetectCacti(); m_TicksAlive++; // Find closest player within 6.5 meter (slightly increase detect range to have same effect in client) bool FoundPlayer = m_World->DoWithNearestPlayer(GetPosition(), 6.5, [&](cPlayer & a_Player) -> bool { Vector3f a_PlayerPos(a_Player.GetPosition()); a_PlayerPos.y += 0.8f; Vector3f a_Distance = a_PlayerPos - GetPosition(); double Distance = a_Distance.Length(); if (Distance < 0.7f) { a_Player.DeltaExperience(m_Reward); m_World->BroadcastSoundEffect("entity.experience_orb.pickup", GetPosition(), 0.5f, (0.75f + (static_cast((GetUniqueID() * 23) % 32)) / 64)); Destroy(); return true; } // Experience orb will "float" or glide toward the player up to a distance of 6 blocks. // speeding up as they get nearer to the player, Speed range 6 - 12 m per second, accelerate 60 m per second^2 Vector3d SpeedDelta(a_Distance); SpeedDelta.Normalize(); SpeedDelta *= 3; Vector3d CurrentSpeed = GetSpeed(); CurrentSpeed += SpeedDelta; if (CurrentSpeed.Length() > 12) { CurrentSpeed.Normalize(); CurrentSpeed *= 12; } SetSpeed(CurrentSpeed); m_Gravity = 0; return true; }, false, true); // Don't check line of sight, ignore spectator mode player if (!FoundPlayer) { m_Gravity = -16; } HandlePhysics(a_Dt, a_Chunk); BroadcastMovementUpdate(); m_Timer += a_Dt; if (m_Timer >= std::chrono::minutes(5)) { Destroy(); } } bool cExpOrb::DoTakeDamage(TakeDamageInfo & a_TDI) { if (a_TDI.DamageType == dtCactusContact) { Destroy(); return true; } return Super::DoTakeDamage(a_TDI); } std::vector cExpOrb::Split(int a_Reward) { const static std::array BaseValue = {{1, 3, 7, 17, 37, 73, 149, 307, 617, 1237, 2477}}; std::vector Rewards; size_t Index = BaseValue.size() - 1; // Last one while (a_Reward > 0) { while (a_Reward < BaseValue[Index]) { Index--; } a_Reward -= BaseValue[Index]; Rewards.push_back(BaseValue[Index]); } return Rewards; } ================================================ FILE: src/Entities/ExpOrb.h ================================================ #pragma once #include "Entity.h" // tolua_begin class cExpOrb: public cEntity { // tolua_end using Super = cEntity; public: // tolua_export CLASS_PROTODEF(cExpOrb) cExpOrb(Vector3d a_Pos, int a_Reward); // Override functions virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; virtual bool DoTakeDamage(TakeDamageInfo & a_TDI) override; virtual void SpawnOn(cClientHandle & a_Client) override; // tolua_begin /** Returns the number of ticks that this entity has existed */ int GetAge(void) const { return std::chrono::duration_cast(m_Timer).count(); } /** Set the number of ticks that this entity has existed */ void SetAge(int a_Age) { m_Timer = cTickTime(a_Age); } /** Get the exp amount */ int GetReward(void) const { return m_Reward; } /** Set the exp amount */ void SetReward(int a_Reward) { m_Reward = a_Reward; } // tolua_end /** Split reward into small values according to regular Minecraft rules */ static std::vector Split(int a_Reward); protected: int m_Reward; /** The number of ticks that the entity has existed / timer between collect and destroy; in msec */ std::chrono::milliseconds m_Timer; } ; // tolua_export ================================================ FILE: src/Entities/FallingBlock.cpp ================================================ #include "Globals.h" #include "FallingBlock.h" #include "../BlockInfo.h" #include "../World.h" #include "../ClientHandle.h" #include "../Simulator/SandSimulator.h" #include "../Chunk.h" cFallingBlock::cFallingBlock(Vector3d a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta): Super(etFallingBlock, a_Position, 0.98f, 0.98f), m_BlockType(a_BlockType), m_BlockMeta(a_BlockMeta) { SetGravity(-16.0f); SetAirDrag(0.02f); } void cFallingBlock::SpawnOn(cClientHandle & a_ClientHandle) { a_ClientHandle.SendSpawnEntity(*this); } void cFallingBlock::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { // GetWorld()->BroadcastTeleportEntity(*this); // Test position int BlockX = POSX_TOINT; int BlockY = static_cast(GetPosY() - 0.5); int BlockZ = POSZ_TOINT; if (BlockY < 0) { // Fallen out of this world, just continue falling until out of sight, then destroy: if (BlockY < VOID_BOUNDARY) { Destroy(); } return; } if (BlockY >= cChunkDef::Height) { // Above the world, just wait for it to fall back down return; } 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) // Must finish the fall with coords one below the block: cSandSimulator::FinishFalling(m_World, BlockX, BlockY, BlockZ, m_BlockType, m_BlockMeta); Destroy(); return; } else if (!cSandSimulator::CanContinueFallThrough(BlockBelow)) { // Fallen onto a solid block /* FLOGD( "Sand: Checked below at {0} (rel {1}), it's {2}, finishing the fall.", Vector3i{BlockX, BlockY, BlockZ}, cChunkDef::AbsoluteToRelative({BlockX, BlockY, BlockZ}, {a_Chunk.GetPosX(), a_Chunk.GetPosZ()}), ItemTypeToString(BlockBelow) ); */ if (BlockY < cChunkDef::Height - 1) { cSandSimulator::FinishFalling(m_World, BlockX, BlockY + 1, BlockZ, m_BlockType, m_BlockMeta); } Destroy(); return; } else if ((m_BlockType == E_BLOCK_CONCRETE_POWDER) && IsBlockWater(BlockBelow)) { // Concrete powder falling into water solidifies on the first water it touches cSandSimulator::FinishFalling(m_World, BlockX, BlockY, BlockZ, E_BLOCK_CONCRETE, m_BlockMeta); Destroy(); return; } float MilliDt = a_Dt.count() * 0.001f; AddSpeedY(MilliDt * -9.8f); AddPosition(GetSpeed() * MilliDt); // If not static (one billionth precision) broadcast movement if ((fabs(GetSpeedX()) > std::numeric_limits::epsilon()) || (fabs(GetSpeedZ()) > std::numeric_limits::epsilon())) { BroadcastMovementUpdate(); } } ================================================ FILE: src/Entities/FallingBlock.h ================================================ #pragma once #include "Entity.h" // tolua_begin class cFallingBlock : public cEntity { // tolua_end using Super = cEntity; public: // tolua_export CLASS_PROTODEF(cFallingBlock) /** Creates a new falling block. a_Position is expected in world coords */ cFallingBlock(Vector3d a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta); // tolua_begin BLOCKTYPE GetBlockType(void) const { return m_BlockType; } NIBBLETYPE GetBlockMeta(void) const { return m_BlockMeta; } // tolua_end // cEntity overrides: virtual void SpawnOn(cClientHandle & a_ClientHandle) override; virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; private: BLOCKTYPE m_BlockType; NIBBLETYPE m_BlockMeta; } ; // tolua_export ================================================ FILE: src/Entities/FireChargeEntity.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "FireChargeEntity.h" #include "../World.h" cFireChargeEntity::cFireChargeEntity(cEntity * a_Creator, Vector3d a_Pos, Vector3d a_Speed): Super(pkFireCharge, a_Creator, a_Pos, 0.3125f, 0.3125f) { SetSpeed(a_Speed); SetGravity(0); SetAirDrag(0); } void cFireChargeEntity::Explode(Vector3i a_Block) { if (m_World->GetBlock(a_Block) == E_BLOCK_AIR) { m_World->SetBlock(a_Block, E_BLOCK_FIRE, 1); } } void cFireChargeEntity::OnHitSolidBlock(Vector3d a_HitPos, eBlockFace a_HitFace) { Destroy(); Explode(a_HitPos.Floor()); } void cFireChargeEntity::OnHitEntity(cEntity & a_EntityHit, Vector3d a_HitPos) { Super::OnHitEntity(a_EntityHit, a_HitPos); Destroy(); Explode(a_HitPos.Floor()); if (!a_EntityHit.IsFireproof()) { // TODO Damage Entity with 5 damage(from https://minecraft.wiki/w/Blaze#Blaze_fireball) a_EntityHit.StartBurning(5 * 20); // 5 seconds of burning } } ================================================ FILE: src/Entities/FireChargeEntity.h ================================================ // FireChargeEntity.h // Declares the cFireChargeEntity representing the fire charge shot by the blaze #pragma once #include "ProjectileEntity.h" // tolua_begin class cFireChargeEntity : public cProjectileEntity { // tolua_end using Super = cProjectileEntity; public: // tolua_export CLASS_PROTODEF(cFireChargeEntity) cFireChargeEntity(cEntity * a_Creator, Vector3d a_Pos, Vector3d a_Speed); protected: void Explode(Vector3i a_Block); // cProjectileEntity overrides: virtual void OnHitSolidBlock(Vector3d a_HitPos, eBlockFace a_HitFace) override; virtual void OnHitEntity(cEntity & a_EntityHit, Vector3d a_HitPos) override; } ; // tolua_export ================================================ FILE: src/Entities/FireworkEntity.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "FireworkEntity.h" #include "../World.h" #include "../Chunk.h" cFireworkEntity::cFireworkEntity(cEntity * a_Creator, Vector3d a_Pos, const cItem & a_Item) : Super(pkFirework, a_Creator, a_Pos, 0.25f, 0.25f), m_TicksToExplosion(a_Item.m_FireworkItem.m_FlightTimeInTicks), m_FireworkItem(a_Item) { SetGravity(0); SetAirDrag(0); } void cFireworkEntity::HandlePhysics(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { int RelX = POSX_TOINT - a_Chunk.GetPosX() * cChunkDef::Width; int RelZ = POSZ_TOINT - a_Chunk.GetPosZ() * cChunkDef::Width; int PosY = POSY_TOINT; if ((PosY < 0) || (PosY >= cChunkDef::Height)) { AddSpeedY(1); AddPosition(GetSpeed() * (static_cast(a_Dt.count()) / 1000)); return; } if (m_IsInGround) { if (a_Chunk.GetBlock(RelX, POSY_TOINT + 1, RelZ) == E_BLOCK_AIR) { m_IsInGround = false; } else { return; } } else { if (a_Chunk.GetBlock(RelX, POSY_TOINT + 1, RelZ) != E_BLOCK_AIR) { OnHitSolidBlock(GetPosition(), BLOCK_FACE_YM); return; } } AddSpeedY(1); AddPosition(GetSpeed() * (static_cast(a_Dt.count()) / 1000)); } void cFireworkEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { Super::Tick(a_Dt, a_Chunk); if (!IsTicking()) { // The base class tick destroyed us return; } if (m_TicksToExplosion <= 0) { // TODO: Notify the plugins m_World->BroadcastEntityAnimation(*this, EntityAnimation::FireworkRocketExplodes); Destroy(); return; } m_TicksToExplosion -= 1; } ================================================ FILE: src/Entities/FireworkEntity.h ================================================ // FireworkEntity.h // Declares the cFireworkEntity class representing the flying firework rocket #pragma once #include "ProjectileEntity.h" // tolua_begin class cFireworkEntity : public cProjectileEntity { // tolua_end using Super = cProjectileEntity; public: // tolua_export CLASS_PROTODEF(cFireworkEntity) cFireworkEntity(cEntity * a_Creator, Vector3d a_Pos, const cItem & a_Item); // tolua_begin /** Returns the item used to create the rocket (has all the firework effects on it) */ const cItem & GetItem(void) const { return m_FireworkItem; } /** Sets the item that is used to create the rocket (has all the firework effects on it) */ void SetItem(const cItem & a_Item) { m_FireworkItem = a_Item; } /** Returns the number of ticks left until the firework explosion. */ int GetTicksToExplosion(void) const { return m_TicksToExplosion; } /** Sets the number of ticks left until the firework explosion. */ void SetTicksToExplosion(int a_TicksToExplosion) { m_TicksToExplosion = a_TicksToExplosion; } // tolua_end protected: // cProjectileEntity overrides: virtual void HandlePhysics(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; private: int m_TicksToExplosion; cItem m_FireworkItem; }; // tolua_export ================================================ FILE: src/Entities/Floater.cpp ================================================ #include "Globals.h" #include "../BlockInfo.h" #include "../BoundingBox.h" #include "../Chunk.h" #include "Floater.h" #include "Player.h" #include "../ClientHandle.h" //////////////////////////////////////////////////////////////////////////////// // cFloaterEntityCollisionCallback class cFloaterEntityCollisionCallback { public: cFloaterEntityCollisionCallback(cFloater * a_Floater, const Vector3d & a_Pos, const Vector3d & a_NextPos) : m_Floater(a_Floater), m_Pos(a_Pos), m_NextPos(a_NextPos), m_MinCoeff(1), m_HitEntity(nullptr) { } bool operator () (cEntity & a_Entity) { if (!a_Entity.IsMob()) // Floaters can only pull mobs not other entities. { return false; } auto EntBox = a_Entity.GetBoundingBox(); double LineCoeff; eBlockFace Face; EntBox.Expand(m_Floater->GetWidth() / 2, m_Floater->GetHeight() / 2, m_Floater->GetWidth() / 2); if (!EntBox.CalcLineIntersection(m_Pos, m_NextPos, LineCoeff, Face)) { // No intersection whatsoever return false; } if (LineCoeff < m_MinCoeff) { // The entity is closer than anything we've stored so far, replace it as the potential victim m_MinCoeff = LineCoeff; m_HitEntity = &a_Entity; } // Don't break the enumeration, we want all the entities return false; } /** Returns the nearest entity that was hit, after the enumeration has been completed */ cEntity * GetHitEntity(void) const { return m_HitEntity; } /** Returns true if the callback has encountered a true hit */ bool HasHit(void) const { return (m_MinCoeff < 1); } protected: cFloater * m_Floater; const Vector3d & m_Pos; const Vector3d & m_NextPos; double m_MinCoeff; // The coefficient of the nearest hit on the Pos line // Although it's bad(tm) to store entity ptrs from a callback, we can afford it here, because the entire callback // is processed inside the tick thread, so the entities won't be removed in between the calls and the final processing cEntity * m_HitEntity; // The nearest hit entity } ; cFloater::cFloater(Vector3d a_Pos, Vector3d a_Speed, UInt32 a_PlayerID, int a_CountDownTime) : Super(etFloater, a_Pos, 0.25f, 0.25f), m_BitePos(a_Pos), m_CanPickupItem(false), m_PickupCountDown(0), m_CountDownTime(a_CountDownTime), m_PlayerID(a_PlayerID), m_AttachedMobID(cEntity::INVALID_ID) { SetSpeed(a_Speed); } void cFloater::SpawnOn(cClientHandle & a_Client) { a_Client.SendSpawnEntity(*this); } void cFloater::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { HandlePhysics(a_Dt, a_Chunk); PREPARE_REL_AND_CHUNK(GetPosition().Floor(), a_Chunk); if (!RelSuccess) { return; } auto & Random = GetRandomProvider(); if (IsBlockWater(Chunk->GetBlock(Rel)) && (Chunk->GetMeta(Rel) == 0)) { if (!m_CanPickupItem && (m_AttachedMobID == cEntity::INVALID_ID)) // Check if you can't already pickup a fish and if the floater isn't attached to a mob. { if (m_CountDownTime <= 0) { m_BitePos = GetPosition(); m_World->BroadcastSoundEffect("entity.bobber.splash", GetPosition(), 1, 1); AddSpeedY(-10); m_CanPickupItem = true; m_PickupCountDown = 20; m_CountDownTime = Random.RandInt(100, 900); LOGD("Floater %i can be picked up", GetUniqueID()); } else if (m_CountDownTime == 20) // Calculate the position where the particles should spawn and start producing them. { LOGD("Started producing particles for floater %i", GetUniqueID()); m_ParticlePos.Set(GetPosX() + Random.RandInt(-4, 4), GetPosY(), GetPosZ() + Random.RandInt(-4, 4)); m_World->BroadcastParticleEffect("splash", static_cast(m_ParticlePos), Vector3f{}, 0, 15); } else if (m_CountDownTime < 20) { m_ParticlePos = (m_ParticlePos + (GetPosition() - m_ParticlePos) / 6); m_World->BroadcastParticleEffect("splash", static_cast(m_ParticlePos), Vector3f{}, 0, 15); } m_CountDownTime--; if (Chunk->IsWeatherWetAt(Rel)) { if (Random.RandBool(0.25)) // 25% chance of an extra countdown when being rained on. { m_CountDownTime--; } } else // if the floater is underground it has a 50% chance of not decreasing the countdown. { if (Random.RandBool()) { m_CountDownTime++; } } } } // Check water at the top of floater otherwise it floats into the air above the water if ( const auto Above = Rel.addedY(FloorC(GetPosY() + GetHeight())); (Above.y < cChunkDef::Height) && IsBlockWater(m_World->GetBlock(Above)) ) { SetSpeedY(0.7); } if (CanPickup()) // Make sure the floater "loses its fish" { m_PickupCountDown--; if (m_PickupCountDown == 0) { m_CanPickupItem = false; LOGD("The fish is gone. Floater %i can not pick an item up.", GetUniqueID()); } } if ((GetSpeed().Length() > 4) && (m_AttachedMobID == cEntity::INVALID_ID)) { cFloaterEntityCollisionCallback Callback(this, GetPosition(), GetPosition() + GetSpeed() / 20); a_Chunk.ForEachEntity(Callback); if (Callback.HasHit()) { AttachTo(*Callback.GetHitEntity()); Callback.GetHitEntity()->TakeDamage(*this); // TODO: the player attacked the mob not the floater. m_AttachedMobID = Callback.GetHitEntity()->GetUniqueID(); } } if (!m_World->DoWithEntityByID(m_PlayerID, [](cEntity &) { return true; })) // The owner doesn't exist anymore. Destroy the floater entity. { Destroy(); } if (m_AttachedMobID != cEntity::INVALID_ID) { if (!m_World->DoWithEntityByID(m_AttachedMobID, [](cEntity &) { return true; })) { // The mob the floater was attached to doesn't exist anymore. m_AttachedMobID = cEntity::INVALID_ID; } } SetSpeedX(GetSpeedX() * 0.95); SetSpeedZ(GetSpeedZ() * 0.95); BroadcastMovementUpdate(); } ================================================ FILE: src/Entities/Floater.h ================================================ #pragma once #include "Entity.h" // tolua_begin class cFloater : public cEntity { // tolua_end using Super = cEntity; public: // tolua_export CLASS_PROTODEF(cFloater) cFloater(Vector3d a_Pos, Vector3d a_Speed, UInt32 a_PlayerID, int a_CountDownTime); virtual void SpawnOn(cClientHandle & a_Client) override; virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; // tolua_begin bool CanPickup(void) const { return m_CanPickupItem; } UInt32 GetOwnerID(void) const { return m_PlayerID; } UInt32 GetAttachedMobID(void) const { return m_AttachedMobID; } Vector3d GetBitePos(void) const { return m_BitePos; } // tolua_end protected: // Position Vector3d m_ParticlePos; // Position just before the floater gets pulled under by a fish Vector3d m_BitePos; // Bool needed to check if you can get a fish. bool m_CanPickupItem; // Countdown times int m_PickupCountDown; int m_CountDownTime; // Entity IDs UInt32 m_PlayerID; UInt32 m_AttachedMobID; } ; // tolua_export ================================================ FILE: src/Entities/GhastFireballEntity.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "GhastFireballEntity.h" #include "../World.h" cGhastFireballEntity::cGhastFireballEntity(cEntity * a_Creator, Vector3d a_Pos, Vector3d a_Speed): Super(pkGhastFireball, a_Creator, a_Pos, 1, 1) { SetSpeed(a_Speed); SetGravity(0); SetAirDrag(0); } void cGhastFireballEntity::Explode(Vector3i a_Block) { m_World->DoExplosionAt(1, a_Block.x, a_Block.y, a_Block.z, true, esGhastFireball, this); } void cGhastFireballEntity::OnHitSolidBlock(Vector3d a_HitPos, eBlockFace a_HitFace) { Destroy(); Explode(a_HitPos.Floor()); } void cGhastFireballEntity::OnHitEntity(cEntity & a_EntityHit, Vector3d a_HitPos) { Destroy(); Explode(a_HitPos.Floor()); } ================================================ FILE: src/Entities/GhastFireballEntity.h ================================================ // GhastFireballEntity.h // Declares the cGhastFireballEntity class representing the ghast fireball in flight. #pragma once #include "ProjectileEntity.h" // tolua_begin class cGhastFireballEntity : public cProjectileEntity { // tolua_end using Super = cProjectileEntity; public: // tolua_export CLASS_PROTODEF(cGhastFireballEntity) cGhastFireballEntity(cEntity * a_Creator, Vector3d a_Pos, Vector3d a_Speed); protected: void Explode(Vector3i a_Block); // cProjectileEntity overrides: virtual void OnHitSolidBlock(Vector3d a_HitPos, eBlockFace a_HitFace) override; virtual void OnHitEntity(cEntity & a_EntityHit, Vector3d a_HitPos) override; // TODO: Deflecting the fireballs by arrow- or sword- hits } ; // tolua_export ================================================ FILE: src/Entities/HangingEntity.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "HangingEntity.h" #include "BlockInfo.h" #include "Player.h" #include "Chunk.h" #include "../ClientHandle.h" cHangingEntity::cHangingEntity(eEntityType a_EntityType, eBlockFace a_Facing, Vector3d a_Pos) : Super(a_EntityType, a_Pos, 0.5f, 0.5f), m_Facing(cHangingEntity::BlockFaceToProtocolFace(a_Facing)) { SetMaxHealth(1); SetHealth(1); } bool cHangingEntity::IsValidSupportBlock(const BLOCKTYPE a_BlockType) { return cBlockInfo::IsSolid(a_BlockType) && (a_BlockType != E_BLOCK_REDSTONE_REPEATER_OFF) && (a_BlockType != E_BLOCK_REDSTONE_REPEATER_ON); } void cHangingEntity::KilledBy(TakeDamageInfo & a_TDI) { Super::KilledBy(a_TDI); Destroy(); } void cHangingEntity::SpawnOn(cClientHandle & a_ClientHandle) { SetYaw(GetProtocolFacing() * 90); } void cHangingEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { UNUSED(a_Dt); // Check for a valid support block once every 64 ticks (3.2 seconds): if ((m_World->GetWorldTickAge() % 64_tick) != 0_tick) { return; } BLOCKTYPE Block; const auto SupportPosition = AddFaceDirection(cChunkDef::AbsoluteToRelative(GetPosition()), ProtocolFaceToBlockFace(m_Facing), true); if (!a_Chunk.UnboundedRelGetBlockType(SupportPosition, Block) || IsValidSupportBlock(Block)) { return; } // Take environmental damage, intending to self-destruct, with "take damage" handling done by child classes: TakeDamage(dtEnvironment, nullptr, static_cast(GetMaxHealth()), 0); } ================================================ FILE: src/Entities/HangingEntity.h ================================================ #pragma once #include "Entity.h" // tolua_begin class cHangingEntity : public cEntity { // tolua_end using Super = cEntity; public: // tolua_export CLASS_PROTODEF(cHangingEntity) cHangingEntity(eEntityType a_EntityType, eBlockFace a_BlockFace, Vector3d a_Pos); /** Returns the direction in which the entity is facing. */ eBlockFace GetFacing() const { return cHangingEntity::ProtocolFaceToBlockFace(m_Facing); } // tolua_export /** Returns the direction in which the entity is facing. */ Byte GetProtocolFacing() const { return m_Facing; } /** Returns if the given block can support hanging entity placements. */ static bool IsValidSupportBlock(BLOCKTYPE a_BlockType); // tolua_export /** Set the direction in which the entity is facing. */ void SetFacing(eBlockFace a_Facing) { m_Facing = cHangingEntity::BlockFaceToProtocolFace(a_Facing); } // tolua_export /** Set the direction in which the entity is facing. */ void SetProtocolFacing(Byte a_Facing) { ASSERT(a_Facing <= 3); m_Facing = a_Facing; } protected: Byte m_Facing; virtual void KilledBy(TakeDamageInfo & a_TDI) override; virtual void SpawnOn(cClientHandle & a_ClientHandle) override; virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; /** Converts protocol hanging item facing to eBlockFace values */ inline static eBlockFace ProtocolFaceToBlockFace(Byte a_ProtocolFace) { // The client uses different values for item frame directions and block faces. Our constants are for the block faces, so we convert them here to item frame faces switch (a_ProtocolFace) { case 0: return BLOCK_FACE_ZP; case 2: return BLOCK_FACE_ZM; case 1: return BLOCK_FACE_XM; case 3: return BLOCK_FACE_XP; default: { LOGINFO("Invalid facing (%d) in a cHangingEntity, adjusting to BLOCK_FACE_XP.", a_ProtocolFace); ASSERT(!"Tried to convert a bad facing!"); return cHangingEntity::ProtocolFaceToBlockFace(3); } } } /** Converts eBlockFace values to protocol hanging item faces */ inline static Byte BlockFaceToProtocolFace(eBlockFace a_BlockFace) { // The client uses different values for item frame directions and block faces. Our constants are for the block faces, so we convert them here to item frame faces switch (a_BlockFace) { case BLOCK_FACE_ZP: return 0; case BLOCK_FACE_ZM: return 2; case BLOCK_FACE_XM: return 1; case BLOCK_FACE_XP: return 3; case BLOCK_FACE_YP: case BLOCK_FACE_YM: case BLOCK_FACE_NONE: { // Uncomment when entities are initialised with their real data, instead of dummy values: // LOGINFO("Invalid facing (%d) in a cHangingEntity, adjusting to BLOCK_FACE_XP.", a_BlockFace); // ASSERT(!"Tried to convert a bad facing!"); return cHangingEntity::BlockFaceToProtocolFace(BLOCK_FACE_XP); } } UNREACHABLE("Unsupported block face"); } }; // tolua_export ================================================ FILE: src/Entities/ItemFrame.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "ItemFrame.h" #include "Player.h" #include "../ClientHandle.h" #include "Chunk.h" cItemFrame::cItemFrame(eBlockFace a_BlockFace, Vector3d a_Pos): Super(etItemFrame, a_BlockFace, a_Pos), m_Item(E_BLOCK_AIR), m_ItemRotation(0) { } bool cItemFrame::DoTakeDamage(TakeDamageInfo & a_TDI) { // Take environmental or non-player damage normally: if (m_Item.IsEmpty() || (a_TDI.Attacker == nullptr) || !a_TDI.Attacker->IsPlayer()) { return Super::DoTakeDamage(a_TDI); } // Only pop out a pickup if attacked by a non-creative player: if (!static_cast(a_TDI.Attacker)->IsGameModeCreative()) { // Where the pickup spawns, offset by half cPickup height to centre in the block. const auto SpawnPosition = GetPosition().addedY(-0.125); // The direction the pickup travels to simulate a pop-out effect. const auto FlyOutSpeed = AddFaceDirection(Vector3i(), ProtocolFaceToBlockFace(m_Facing)) * 2; // Spawn the frame's held item: GetWorld()->SpawnItemPickup(SpawnPosition, m_Item, FlyOutSpeed); } // In any case we have a held item and were hit by a player, so clear it: m_Item.Empty(); m_ItemRotation = 0; a_TDI.FinalDamage = 0; SetInvulnerableTicks(0); GetWorld()->BroadcastEntityMetadata(*this); return false; } void cItemFrame::GetDrops(cItems & a_Items, cEntity * a_Killer) { if (!m_Item.IsEmpty()) { a_Items.push_back(m_Item); } a_Items.emplace_back(E_ITEM_ITEM_FRAME); } void cItemFrame::OnRightClicked(cPlayer & a_Player) { Super::OnRightClicked(a_Player); if (!m_Item.IsEmpty()) { // Item not empty, rotate, clipping values to zero to seven inclusive m_ItemRotation++; if (m_ItemRotation >= 8) { m_ItemRotation = 0; } } else if (!a_Player.GetEquippedItem().IsEmpty()) { // Item empty, and player held item not empty - add this item to self m_Item = a_Player.GetEquippedItem(); m_Item.m_ItemCount = 1; if (!a_Player.IsGameModeCreative()) { a_Player.GetInventory().RemoveOneEquippedItem(); } } GetWorld()->BroadcastEntityMetadata(*this); // Update clients GetParentChunk()->MarkDirty(); // Mark chunk dirty to save rotation or item } void cItemFrame::SpawnOn(cClientHandle & a_ClientHandle) { Super::SpawnOn(a_ClientHandle); a_ClientHandle.SendSpawnEntity(*this); a_ClientHandle.SendEntityMetadata(*this); if (m_Item.m_ItemType == E_ITEM_MAP) { cMap * Map = GetWorld()->GetMapManager().GetMapData(static_cast(m_Item.m_ItemDamage)); if (Map != nullptr) { a_ClientHandle.SendMapData(*Map, 0, 0); } } } ================================================ FILE: src/Entities/ItemFrame.h ================================================ #pragma once #include "HangingEntity.h" // tolua_begin class cItemFrame : public cHangingEntity { // tolua_end using Super = cHangingEntity; public: // tolua_export CLASS_PROTODEF(cItemFrame) cItemFrame(eBlockFace a_BlockFace, Vector3d a_Pos); // tolua_begin /** Returns the item in the frame */ const cItem & GetItem(void) const { return m_Item; } /** Set the item in the frame */ void SetItem(cItem & a_Item) { m_Item = a_Item; } /** Returns the rotation from the item in the frame */ Byte GetItemRotation(void) const { return m_ItemRotation; } /** Set the rotation from the item in the frame */ void SetItemRotation(Byte a_ItemRotation) { m_ItemRotation = a_ItemRotation; } // tolua_end private: virtual bool DoTakeDamage(TakeDamageInfo & a_TDI) override; virtual void GetDrops(cItems & a_Items, cEntity * a_Killer) override; virtual void OnRightClicked(cPlayer & a_Player) override; virtual void SpawnOn(cClientHandle & a_ClientHandle) override; cItem m_Item; Byte m_ItemRotation; }; // tolua_export ================================================ FILE: src/Entities/LeashKnot.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "LeashKnot.h" #include "Player.h" #include "../Mobs/Monster.h" #include "../BoundingBox.h" #include "../ClientHandle.h" // Ticks to wait in Tick function to optimize calculations #define TICK_STEP 10 cLeashKnot::cLeashKnot(eBlockFace a_BlockFace, Vector3d a_Pos) : Super(etLeashKnot, a_BlockFace, a_Pos), m_ShouldSelfDestroy(false), m_TicksToSelfDestroy(20 * 1) { } void cLeashKnot::OnRightClicked(cPlayer & a_Player) { Super::OnRightClicked(a_Player); TiePlayersLeashedMobs(a_Player, true); GetWorld()->BroadcastEntityMetadata(*this); // Update clients } void cLeashKnot::TiePlayersLeashedMobs(cPlayer & a_Player, bool a_ShouldBroadcast) { // Check leashed nearby mobs to tie them to this knot // taking world from player (instead from this) because this can be called before entity was initialized a_Player.GetWorld()->ForEachEntityInBox(cBoundingBox(GetPosition(), 8, 8, -4), [&](cEntity & a_Entity) { // If the entity is not a monster skip it if (a_Entity.GetEntityType() != cEntity::eEntityType::etMonster) { return false; } auto & PotentialLeashed = static_cast(a_Entity); // If can't be leashed skip it if (!PotentialLeashed.CanBeLeashed()) { return false; } // If it's not leashed to the player skip it if ( !PotentialLeashed.IsLeashed() || !PotentialLeashed.GetLeashedTo()->IsPlayer() || (PotentialLeashed.GetLeashedTo()->GetUniqueID() != a_Player.GetUniqueID()) ) { return false; } // All conditions met, unleash from player and leash to fence PotentialLeashed.Unleash(false, false); PotentialLeashed.LeashTo(*this, a_ShouldBroadcast); return false; } ); } void cLeashKnot::KilledBy(TakeDamageInfo & a_TDI) { Super::KilledBy(a_TDI); m_World->BroadcastSoundEffect("entity.leashknot.break", GetPosition(), 1, 1); Destroy(); } void cLeashKnot::GetDrops(cItems & a_Items, cEntity * a_Killer) { if ((a_Killer != nullptr) && a_Killer->IsPlayer() && !static_cast(a_Killer)->IsGameModeCreative()) { a_Items.emplace_back(E_ITEM_LEASH); } } void cLeashKnot::SpawnOn(cClientHandle & a_ClientHandle) { Super::SpawnOn(a_ClientHandle); a_ClientHandle.SendSpawnEntity(*this); a_ClientHandle.SendEntityMetadata(*this); } void cLeashKnot::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { m_TicksAlive++; if ((m_TicksAlive % TICK_STEP) != 0) { return; } if (m_ShouldSelfDestroy) { m_TicksToSelfDestroy -= TICK_STEP; if (m_TicksToSelfDestroy <= 0) { Destroy(); m_World->BroadcastSoundEffect("entity.leashknot.break", GetPosition(), 1, 1); } } } cLeashKnot * cLeashKnot::FindKnotAtPos(cWorldInterface & a_WorldInterface, Vector3i a_BlockPos) { cLeashKnot * LeashKnot = nullptr; a_WorldInterface.ForEachEntityInBox(cBoundingBox(a_BlockPos, 0.5, 1), [&](cEntity & a_Entity) { if (a_Entity.IsLeashKnot()) { LeashKnot = static_cast(&a_Entity); return true; } return false; } ); return LeashKnot; } ================================================ FILE: src/Entities/LeashKnot.h ================================================ #pragma once #include "HangingEntity.h" class cWorldInterface; // tolua_begin class cLeashKnot : public cHangingEntity { // tolua_end using Super = cHangingEntity; public: // tolua_export CLASS_PROTODEF(cLeashKnot) cLeashKnot(eBlockFace a_BlockFace, Vector3d a_Pos); /** Looks for mobs leashed to a player and ties them to this knot */ void TiePlayersLeashedMobs(cPlayer & a_Player, bool a_ShouldBroadCast); void SetShouldSelfDestroy() { m_ShouldSelfDestroy = true; } /** Returns the leash knot entity representing the knot at the specified position. Returns nullptr if there's no knot. */ static cLeashKnot * FindKnotAtPos(cWorldInterface & a_WorldInterface, Vector3i a_BlockPos); private: /** When a fence is destroyed, the knot on it gets destroyed after a while. This flag turns on the countdown to self destroy. */ bool m_ShouldSelfDestroy; int m_TicksToSelfDestroy; virtual void OnRightClicked(cPlayer & a_Player) override; virtual void KilledBy(TakeDamageInfo & a_TDI) override; virtual void GetDrops(cItems & a_Items, cEntity * a_Killer) override; virtual void SpawnOn(cClientHandle & a_ClientHandle) override; virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; }; // tolua_export ================================================ FILE: src/Entities/Minecart.cpp ================================================ // Minecart.cpp // Implements the cMinecart class representing a minecart in the world // Handles physics when a minecart is on any type of rail (overrides simulator in Entity.cpp) // Indiana Jones! #include "Globals.h" #include "ChunkDef.h" #include "Defines.h" #include "Minecart.h" #include "../BlockInfo.h" #include "../ClientHandle.h" #include "../Chunk.h" #include "Player.h" #include "../BoundingBox.h" #include "../UI/MinecartWithChestWindow.h" #define NO_SPEED 0.0 #define MAX_SPEED 8 #define MAX_SPEED_NEGATIVE -MAX_SPEED #define DIR_NORTH_SOUTH 270 #define DIR_EAST_WEST 180 #define DIR_NORTH_WEST 315 #define DIR_NORTH_EAST 225 #define DIR_SOUTH_WEST 135 #define DIR_SOUTH_EAST 45 class cMinecartAttachCallback { public: cMinecartAttachCallback(cMinecart & a_Minecart, cEntity * a_Attachee) : m_Minecart(a_Minecart), m_Attachee(a_Attachee) { } bool operator()(cEntity & a_Entity) { // Check if minecart is empty and if given entity is a mob: if ((m_Attachee == nullptr) && a_Entity.IsMob()) { // If so, attach to minecart and stop iterating: a_Entity.AttachTo(m_Minecart); return true; } return false; } protected: cMinecart & m_Minecart; cEntity * m_Attachee; }; class cMinecartCollisionCallback { public: cMinecartCollisionCallback(Vector3d a_Pos, double a_Height, double a_Width, UInt32 a_UniqueID, UInt32 a_AttacheeUniqueID) : m_DoesIntersect(false), m_CollidedEntityPos(0, 0, 0), m_Pos(a_Pos), m_Height(a_Height), m_Width(a_Width), m_UniqueID(a_UniqueID), m_AttacheeUniqueID(a_AttacheeUniqueID) { } bool operator () (cEntity & a_Entity) { if ( ( !a_Entity.IsPlayer() || static_cast(a_Entity).IsGameModeSpectator() // Spectators doesn't collide with anything ) && !a_Entity.IsMob() && !a_Entity.IsMinecart() && !a_Entity.IsBoat() ) { return false; } else if ((a_Entity.GetUniqueID() == m_UniqueID) || (a_Entity.GetUniqueID() == m_AttacheeUniqueID)) { return false; } cBoundingBox bbEntity(a_Entity.GetPosition(), a_Entity.GetWidth() / 2, a_Entity.GetHeight()); cBoundingBox bbMinecart(Vector3d(m_Pos.x, floor(m_Pos.y), m_Pos.z), m_Width / 2, m_Height); if (bbEntity.DoesIntersect(bbMinecart)) { m_CollidedEntityPos = a_Entity.GetPosition(); m_DoesIntersect = true; return true; } return false; } bool FoundIntersection(void) const { return m_DoesIntersect; } Vector3d GetCollidedEntityPosition(void) const { return m_CollidedEntityPos; } protected: bool m_DoesIntersect; Vector3d m_CollidedEntityPos; Vector3d m_Pos; double m_Height, m_Width; UInt32 m_UniqueID; UInt32 m_AttacheeUniqueID; }; //////////////////////////////////////////////////////////////////////////////// // cMinecart: cMinecart::cMinecart(ePayload a_Payload, Vector3d a_Pos): Super(etMinecart, a_Pos, 0.98f, 0.7f), m_Payload(a_Payload), m_LastDamage(0), m_DetectorRailPosition(0, 0, 0), m_bIsOnDetectorRail(false) { SetMass(20.0f); SetGravity(-16.0f); SetAirDrag(0.05f); SetMaxHealth(6); SetHealth(6); } void cMinecart::SpawnOn(cClientHandle & a_ClientHandle) { a_ClientHandle.SendSpawnEntity(*this); a_ClientHandle.SendEntityMetadata(*this); } void cMinecart::HandlePhysics(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { ASSERT(IsTicking()); int PosY = POSY_TOINT; if ((PosY <= 0) || (PosY >= cChunkDef::Height)) { // Outside the world, just process normal falling physics Super::HandlePhysics(a_Dt, a_Chunk); BroadcastMovementUpdate(); return; } // pos need floor, then call vec3i overload func // if use default double -> int, will cast -1.xx -> -1(actually need to be -2) auto relPos = cChunkDef::AbsoluteToRelative(GetPosition().Floor()); auto chunk = a_Chunk.GetRelNeighborChunkAdjustCoords(relPos); if (chunk == nullptr) { // Inside an unloaded chunk, bail out all processing return; } if (m_bIsOnDetectorRail && !Vector3i(POSX_TOINT, POSY_TOINT, POSZ_TOINT).Equals(m_DetectorRailPosition)) { // Check if the rail is still there if (m_World->GetBlock(m_DetectorRailPosition) == E_BLOCK_DETECTOR_RAIL) { m_World->SetBlock(m_DetectorRailPosition, E_BLOCK_DETECTOR_RAIL, m_World->GetBlockMeta(m_DetectorRailPosition) & 0x07); } m_bIsOnDetectorRail = false; } BLOCKTYPE InsideType; NIBBLETYPE InsideMeta; chunk->GetBlockTypeMeta(relPos, InsideType, InsideMeta); if (!IsBlockRail(InsideType)) { // When a descending minecart hits a flat rail, it goes through the ground; check for this chunk->GetBlockTypeMeta(relPos.addedY(1), InsideType, InsideMeta); if (IsBlockRail(InsideType)) { // Push cart upwards AddPosY(1); } else { // When a minecart gets to a descending rail, it should go down. chunk->GetBlockTypeMeta(relPos.addedY(-1), InsideType, InsideMeta); if (IsBlockRail(InsideType)) { // Push cart downwards AddPosY(-1); } } } if (IsBlockRail(InsideType)) { if (InsideType == E_BLOCK_RAIL) { SnapToRail(InsideMeta); } else { SnapToRail(InsideMeta & 0x07); } switch (InsideType) { case E_BLOCK_RAIL: HandleRailPhysics(InsideMeta, a_Dt); break; case E_BLOCK_ACTIVATOR_RAIL: HandleActivatorRailPhysics(InsideMeta, a_Dt); break; case E_BLOCK_POWERED_RAIL: HandlePoweredRailPhysics(InsideMeta); break; case E_BLOCK_DETECTOR_RAIL: { m_DetectorRailPosition = Vector3i(POSX_TOINT, POSY_TOINT, POSZ_TOINT); m_bIsOnDetectorRail = true; HandleDetectorRailPhysics(InsideMeta, a_Dt); break; } default: VERIFY(!"Unhandled rail type despite checking if block was rail!"); break; } AddPosition(GetSpeed() * (static_cast(a_Dt.count()) / 1000)); // Commit changes; as we use our own engine when on rails, this needs to be done, whereas it is normally in Entity.cpp } else { // Not on rail, default physics SetPosY(floor(GetPosY()) + 0.35); // HandlePhysics overrides this if minecart can fall, else, it is to stop ground clipping minecart bottom when off-rail Super::HandlePhysics(a_Dt, *chunk); } // Enforce speed limit: m_Speed.Clamp(MAX_SPEED_NEGATIVE, MAX_SPEED); // Broadcast positioning changes to client BroadcastMovementUpdate(); } void cMinecart::HandleRailPhysics(NIBBLETYPE a_RailMeta, std::chrono::milliseconds a_Dt) { /* NOTE: Please bear in mind that taking away from negatives make them even more negative, adding to negatives make them positive, etc. */ switch (a_RailMeta) { case E_META_RAIL_ZM_ZP: // NORTHSOUTH { SetYaw(DIR_NORTH_SOUTH); SetPosY(floor(GetPosY()) + 0.55); SetSpeedY(NO_SPEED); // Don't move vertically as on ground SetSpeedX(NO_SPEED); // Correct diagonal movement from curved rails // Execute both the entity and block collision checks auto BlckCol = TestBlockCollision(a_RailMeta); auto EntCol = TestEntityCollision(a_RailMeta); if (EntCol || BlckCol) { return; } if (GetSpeedZ() != NO_SPEED) // Don't do anything if cart is stationary { if (GetSpeedZ() > 0) { // Going SOUTH, slow down ApplyAcceleration({ 0.0, 0.0, 1.0 }, -0.1); } else { // Going NORTH, slow down ApplyAcceleration({ 0.0, 0.0, -1.0 }, -0.1); } } return; } case E_META_RAIL_XM_XP: // EASTWEST { SetYaw(DIR_EAST_WEST); SetPosY(floor(GetPosY()) + 0.55); SetSpeedY(NO_SPEED); SetSpeedZ(NO_SPEED); auto BlckCol = TestBlockCollision(a_RailMeta); auto EntCol = TestEntityCollision(a_RailMeta); if (EntCol || BlckCol) { return; } if (GetSpeedX() != NO_SPEED) { if (GetSpeedX() > 0) { ApplyAcceleration({ 1.0, 0.0, 0.0 }, -0.1); } else { ApplyAcceleration({ -1.0, 0.0, 0.0 }, -0.1); } } return; } case E_META_RAIL_ASCEND_ZM: // ASCEND NORTH { SetYaw(DIR_NORTH_SOUTH); SetSpeedX(NO_SPEED); auto BlckCol = TestBlockCollision(a_RailMeta); auto EntCol = TestEntityCollision(a_RailMeta); if (EntCol || BlckCol) { return; } if (GetSpeedZ() >= 0) { // SpeedZ POSITIVE, going SOUTH AddSpeedZ(0.5); // Speed up SetSpeedY(-GetSpeedZ()); // Downward movement is negative (0 minus positive numbers is negative) } else { // SpeedZ NEGATIVE, going NORTH AddSpeedZ(1); // Slow down SetSpeedY(-GetSpeedZ()); // Upward movement is positive (0 minus negative number is positive number) } return; } case E_META_RAIL_ASCEND_ZP: // ASCEND SOUTH { SetYaw(DIR_NORTH_SOUTH); SetSpeedX(NO_SPEED); auto BlckCol = TestBlockCollision(a_RailMeta); auto EntCol = TestEntityCollision(a_RailMeta); if (EntCol || BlckCol) { return; } if (GetSpeedZ() > 0) { // SpeedZ POSITIVE, going SOUTH AddSpeedZ(-1); // Slow down SetSpeedY(GetSpeedZ()); // Upward movement positive } else { // SpeedZ NEGATIVE, going NORTH AddSpeedZ(-0.5); // Speed up SetSpeedY(GetSpeedZ()); // Downward movement negative } return; } case E_META_RAIL_ASCEND_XM: // ASCEND EAST { SetYaw(DIR_EAST_WEST); SetSpeedZ(NO_SPEED); auto BlckCol = TestBlockCollision(a_RailMeta); auto EntCol = TestEntityCollision(a_RailMeta); if (EntCol || BlckCol) { return; } if (GetSpeedX() >= NO_SPEED) { AddSpeedX(0.5); SetSpeedY(-GetSpeedX()); } else { AddSpeedX(1); SetSpeedY(-GetSpeedX()); } return; } case E_META_RAIL_ASCEND_XP: // ASCEND WEST { SetYaw(DIR_EAST_WEST); SetSpeedZ(NO_SPEED); auto BlckCol = TestBlockCollision(a_RailMeta); auto EntCol = TestEntityCollision(a_RailMeta); if (EntCol || BlckCol) { return; } if (GetSpeedX() > 0) { AddSpeedX(-1); SetSpeedY(GetSpeedX()); } else { AddSpeedX(-0.5); SetSpeedY(GetSpeedX()); } return; } case E_META_RAIL_CURVED_ZM_XM: // Ends pointing NORTH and WEST { SetYaw(DIR_NORTH_WEST); // Set correct rotation server side SetPosY(floor(GetPosY()) + 0.55); // Levitate dat cart SetSpeedY(NO_SPEED); auto BlckCol = TestBlockCollision(a_RailMeta); auto EntCol = TestEntityCollision(a_RailMeta); if (EntCol || BlckCol) { return; } // SnapToRail handles turning return; } case E_META_RAIL_CURVED_ZM_XP: // Curved NORTH EAST { SetYaw(DIR_NORTH_EAST); SetPosY(floor(GetPosY()) + 0.55); SetSpeedY(NO_SPEED); auto BlckCol = TestBlockCollision(a_RailMeta); auto EntCol = TestEntityCollision(a_RailMeta); if (EntCol || BlckCol) { return; } return; } case E_META_RAIL_CURVED_ZP_XM: // Curved SOUTH WEST { SetYaw(DIR_SOUTH_WEST); SetPosY(floor(GetPosY()) + 0.55); SetSpeedY(NO_SPEED); auto BlckCol = TestBlockCollision(a_RailMeta); auto EntCol = TestEntityCollision(a_RailMeta); if (EntCol || BlckCol) { return; } return; } case E_META_RAIL_CURVED_ZP_XP: // Curved SOUTH EAST { SetYaw(DIR_SOUTH_EAST); SetPosY(floor(GetPosY()) + 0.55); SetSpeedY(NO_SPEED); auto BlckCol = TestBlockCollision(a_RailMeta); auto EntCol = TestEntityCollision(a_RailMeta); if (EntCol || BlckCol) { return; } return; } } UNREACHABLE("Unsupported rail meta type"); } void cMinecart::HandlePoweredRailPhysics(NIBBLETYPE a_RailMeta) { // If the rail is powered set to speed up else slow down. const bool IsRailPowered = ((a_RailMeta & 0x8) == 0x8); const double Acceleration = IsRailPowered ? 1.0 : -2.0; // PoweredRail only has 5 status in low 3bit. so we need do a logical and to get correct powered rail meta data. NIBBLETYPE PoweredRailMeta = a_RailMeta & 0x7; switch (PoweredRailMeta) { case E_META_RAIL_ZM_ZP: // NORTHSOUTH { SetYaw(DIR_NORTH_SOUTH); SetPosY(floor(GetPosY()) + 0.55); SetSpeedY(0); SetSpeedX(0); bool BlckCol = TestBlockCollision(PoweredRailMeta), EntCol = TestEntityCollision(PoweredRailMeta); if (EntCol || BlckCol) { return; } if (GetSpeedZ() != NO_SPEED) { if (GetSpeedZ() > NO_SPEED) { ApplyAcceleration({ 0.0, 0.0, 1.0 }, Acceleration); } else { ApplyAcceleration({ 0.0, 0.0, -1.0 }, Acceleration); } } // If rail is powered check for nearby blocks that could kick-start the minecart else if (IsRailPowered) { bool IsBlockZP = IsSolidBlockAtOffset(0, 0, 1); bool IsBlockZM = IsSolidBlockAtOffset(0, 0, -1); // Only kick-start the minecart if a block is on one side, but not both if (IsBlockZM && !IsBlockZP) { ApplyAcceleration({ 0.0, 0.0, 1.0 }, Acceleration); } else if (!IsBlockZM && IsBlockZP) { ApplyAcceleration({ 0.0, 0.0, -1.0 }, Acceleration); } } break; } case E_META_RAIL_XM_XP: // EASTWEST { SetYaw(DIR_EAST_WEST); SetPosY(floor(GetPosY()) + 0.55); SetSpeedY(NO_SPEED); SetSpeedZ(NO_SPEED); bool BlckCol = TestBlockCollision(PoweredRailMeta), EntCol = TestEntityCollision(PoweredRailMeta); if (EntCol || BlckCol) { return; } if (GetSpeedX() != NO_SPEED) { if (GetSpeedX() > NO_SPEED) { ApplyAcceleration({ 1.0, 0.0, 0.0 }, Acceleration); } else { ApplyAcceleration({ -1.0, 0.0, 0.0 }, Acceleration); } } // If rail is powered check for nearby blocks that could kick-start the minecart else if (IsRailPowered) { bool IsBlockXP = IsSolidBlockAtOffset(1, 0, 0); bool IsBlockXM = IsSolidBlockAtOffset(-1, 0, 0); // Only kick-start the minecart if a block is on one side, but not both if (IsBlockXM && !IsBlockXP) { ApplyAcceleration({ 1.0, 0.0, 0.0 }, Acceleration); } else if (!IsBlockXM && IsBlockXP) { ApplyAcceleration({ -1.0, 0.0, 0.0 }, Acceleration); } } break; } case E_META_RAIL_ASCEND_XM: // ASCEND EAST { SetYaw(DIR_EAST_WEST); SetSpeedZ(NO_SPEED); if (GetSpeedX() >= NO_SPEED) { ApplyAcceleration({ 1.0, 0.0, 0.0 }, Acceleration); SetSpeedY(-GetSpeedX()); } else { ApplyAcceleration({ -1.0, 0.0, 0.0 }, Acceleration); SetSpeedY(-GetSpeedX()); } break; } case E_META_RAIL_ASCEND_XP: // ASCEND WEST { SetYaw(DIR_EAST_WEST); SetSpeedZ(NO_SPEED); if (GetSpeedX() > NO_SPEED) { ApplyAcceleration({ 1.0, 0.0, 0.0 }, Acceleration); SetSpeedY(GetSpeedX()); } else { ApplyAcceleration({ -1.0, 0.0, 0.0 }, Acceleration); SetSpeedY(GetSpeedX()); } break; } case E_META_RAIL_ASCEND_ZM: // ASCEND NORTH { SetYaw(DIR_NORTH_SOUTH); SetSpeedX(NO_SPEED); if (GetSpeedZ() >= NO_SPEED) { ApplyAcceleration({ 0.0, 0.0, 1.0 }, Acceleration); SetSpeedY(-GetSpeedZ()); } else { ApplyAcceleration({ 0.0, 0.0, -1.0 }, Acceleration); SetSpeedY(-GetSpeedZ()); } break; } case E_META_RAIL_ASCEND_ZP: // ASCEND SOUTH { SetYaw(DIR_NORTH_SOUTH); SetSpeedX(NO_SPEED); if (GetSpeedZ() > NO_SPEED) { ApplyAcceleration({ 0.0, 0.0, 1.0 }, Acceleration); SetSpeedY(GetSpeedZ()); } else { ApplyAcceleration({ 0.0, 0.0, -1.0 }, Acceleration); SetSpeedY(GetSpeedZ()); } break; } default: ASSERT(!"Unhandled powered rail metadata!"); break; } } void cMinecart::HandleDetectorRailPhysics(NIBBLETYPE a_RailMeta, std::chrono::milliseconds a_Dt) { m_World->SetBlockMeta(m_DetectorRailPosition, a_RailMeta | 0x08); // No special handling HandleRailPhysics(a_RailMeta & 0x07, a_Dt); } void cMinecart::HandleActivatorRailPhysics(NIBBLETYPE a_RailMeta, std::chrono::milliseconds a_Dt) { HandleRailPhysics(a_RailMeta & 0x07, a_Dt); // TODO - shake minecart, throw entities out } void cMinecart::SnapToRail(NIBBLETYPE a_RailMeta) { switch (a_RailMeta) { case E_META_RAIL_ASCEND_XM: case E_META_RAIL_ASCEND_XP: case E_META_RAIL_XM_XP: { SetSpeedZ(NO_SPEED); SetPosZ(floor(GetPosZ()) + 0.5); break; } case E_META_RAIL_ASCEND_ZM: case E_META_RAIL_ASCEND_ZP: case E_META_RAIL_ZM_ZP: { SetSpeedX(NO_SPEED); SetPosX(floor(GetPosX()) + 0.5); break; } // Curved rail physics: once minecart has reached more than half of the block in the direction that it is travelling in, jerk it in the direction of curvature case E_META_RAIL_CURVED_ZM_XM: { if (GetPosZ() > floor(GetPosZ()) + 0.5) { if (GetSpeedZ() > NO_SPEED) { SetSpeedX(-GetSpeedZ() * 0.7); } SetSpeedZ(NO_SPEED); SetPosZ(floor(GetPosZ()) + 0.5); } else if (GetPosX() > floor(GetPosX()) + 0.5) { if (GetSpeedX() > 0) { SetSpeedZ(-GetSpeedX() * 0.7); } SetSpeedX(NO_SPEED); SetPosX(floor(GetPosX()) + 0.5); } SetSpeedY(NO_SPEED); break; } case E_META_RAIL_CURVED_ZM_XP: { if (GetPosZ() > floor(GetPosZ()) + 0.5) { if (GetSpeedZ() > NO_SPEED) { SetSpeedX(GetSpeedZ() * 0.7); } SetSpeedZ(NO_SPEED); SetPosZ(floor(GetPosZ()) + 0.5); } else if (GetPosX() < floor(GetPosX()) + 0.5) { if (GetSpeedX() < NO_SPEED) { SetSpeedZ(GetSpeedX() * 0.7); } SetSpeedX(NO_SPEED); SetPosX(floor(GetPosX()) + 0.5); } SetSpeedY(NO_SPEED); break; } case E_META_RAIL_CURVED_ZP_XM: { if (GetPosZ() < floor(GetPosZ()) + 0.5) { if (GetSpeedZ() < NO_SPEED) { SetSpeedX(GetSpeedZ() * 0.7); } SetSpeedZ(NO_SPEED); SetPosZ(floor(GetPosZ()) + 0.5); } else if (GetPosX() > floor(GetPosX()) + 0.5) { if (GetSpeedX() > NO_SPEED) { SetSpeedZ(GetSpeedX() * 0.7); } SetSpeedX(NO_SPEED); SetPosX(floor(GetPosX()) + 0.5); } SetSpeedY(NO_SPEED); break; } case E_META_RAIL_CURVED_ZP_XP: { if (GetPosZ() < floor(GetPosZ()) + 0.5) { if (GetSpeedZ() < NO_SPEED) { SetSpeedX(-GetSpeedZ() * 0.7); } SetSpeedZ(NO_SPEED); SetPosZ(floor(GetPosZ()) + 0.5); } else if (GetPosX() < floor(GetPosX()) + 0.5) { if (GetSpeedX() < NO_SPEED) { SetSpeedZ(-GetSpeedX() * 0.7); } SetSpeedX(NO_SPEED); SetPosX(floor(GetPosX()) + 0.5); } SetSpeedY(0); break; } default: break; } } bool cMinecart::IsSolidBlockAtPosition(Vector3i a_Pos) { BLOCKTYPE Block = m_World->GetBlock(a_Pos); return !IsBlockRail(Block) && cBlockInfo::IsSolid(Block); } bool cMinecart::IsSolidBlockAtOffset(int a_XOffset, int a_YOffset, int a_ZOffset) { return IsSolidBlockAtPosition({POSX_TOINT + a_XOffset, POSY_TOINT + a_YOffset, POSZ_TOINT + a_ZOffset}); } bool cMinecart::IsBlockCollisionAtOffset(Vector3i a_Offset) { auto BlockPosition = GetPosition().Floor() + a_Offset; if (!IsSolidBlockAtPosition(BlockPosition)) { return false; } auto bbBlock = cBoundingBox( static_cast(BlockPosition), static_cast(BlockPosition + Vector3i(1, 1, 1)) ); return GetBoundingBox().DoesIntersect(bbBlock); } bool cMinecart::TestBlockCollision(NIBBLETYPE a_RailMeta) { auto SpeedX = GetSpeedX(); auto SpeedZ = GetSpeedZ(); // Don't do anything if minecarts aren't moving. #ifdef __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wfloat-equal" #endif if ((SpeedX == 0) && (SpeedZ == 0)) { return false; } #ifdef __clang__ #pragma clang diagnostic pop #endif auto StopTheCart = true; auto StopOffset = Vector3d(); switch (a_RailMeta) { case E_META_RAIL_ZM_ZP: { if (SpeedZ > 0) { StopOffset = Vector3d(0, 0, 0.4); StopTheCart = IsBlockCollisionAtOffset({0, 0, 1}); } else // SpeedZ < 0 { StopTheCart = IsBlockCollisionAtOffset({0, 0, -1}); StopOffset = Vector3d(0, 0, 0.65); } break; } case E_META_RAIL_XM_XP: { if (SpeedX > 0) { StopTheCart = IsBlockCollisionAtOffset({1, 0, 0}); StopOffset = Vector3d(0.4, 0, 0); } else // SpeedX < 0 { StopTheCart = IsBlockCollisionAtOffset({-1, 0, 0}); StopOffset = Vector3d(0.65, 0, 0); } break; } // Ascending rails check for one block on the way up, two on the way down. case E_META_RAIL_ASCEND_XM: { StopOffset = Vector3d(0.5, 0, 0); if (SpeedX < 0) { StopTheCart = IsBlockCollisionAtOffset({-1, 1, 0}); } else // SpeedX > 0 { StopTheCart = IsBlockCollisionAtOffset({1, 0, 0}) || IsBlockCollisionAtOffset({1, 1, 0}); } break; } case E_META_RAIL_ASCEND_XP: { StopOffset = Vector3d(0.5, 0, 0); if (SpeedX > 0) { StopTheCart = IsBlockCollisionAtOffset({1, 1, 0}); } else // SpeedX < 0 { StopTheCart = IsBlockCollisionAtOffset({-1, 0, 0}) || IsBlockCollisionAtOffset({-1, 1, 0}); } break; } case E_META_RAIL_ASCEND_ZM: { StopOffset = Vector3d(0, 0, 0.5); if (SpeedZ < 0) { StopTheCart = IsBlockCollisionAtOffset({0, 1, -1}); } else // SpeedZ > 0 { StopTheCart = IsBlockCollisionAtOffset({0, 0, 1}) || IsBlockCollisionAtOffset({0, 1, 1}); } break; } case E_META_RAIL_ASCEND_ZP: { StopOffset = Vector3d(0, 0, 0.5); if (SpeedZ > 0) { StopTheCart = IsBlockCollisionAtOffset({0, 1, 1}); } else // SpeedZ < 0 { StopTheCart = IsBlockCollisionAtOffset({0, 0, -1}) || IsBlockCollisionAtOffset({0, 1, -1}); } break; } // Curved rails allow movement across both the x and z axes. But when the cart is // moving towards one of the rail endpoints, it will always have velocity towards // the direction of that endpoint in the same axis. case E_META_RAIL_CURVED_ZP_XP: { StopOffset = Vector3d(0.5, 0, 0.5); if (SpeedZ > 0) { StopTheCart = IsBlockCollisionAtOffset({0, 0, 1}); break; } if (SpeedX > 0) { StopTheCart = IsBlockCollisionAtOffset({1, 0, 0}); break; } break; } case E_META_RAIL_CURVED_ZP_XM: { StopOffset = Vector3d(0.5, 0, 0.5); if (SpeedZ > 0) { StopTheCart = IsBlockCollisionAtOffset({0, 0, 1}); break; } if (SpeedX < 0) { StopTheCart = IsBlockCollisionAtOffset({-1, 0, 0}); break; } break; } case E_META_RAIL_CURVED_ZM_XM: { StopOffset = Vector3d(0.5, 0, 0.5); if (SpeedZ < 0) { StopTheCart = IsBlockCollisionAtOffset({0, 0, -1}); break; } if (SpeedX < 0) { StopTheCart = IsBlockCollisionAtOffset({-1, 0, 0}); break; } break; } case E_META_RAIL_CURVED_ZM_XP: { StopOffset = Vector3d(0.5, 0, 0.5); if (SpeedZ < 0) { StopTheCart = IsBlockCollisionAtOffset({0, 0, -1}); break; } if (SpeedX > 0) { StopTheCart = IsBlockCollisionAtOffset({1, 0, 0}); break; } break; } } if (StopTheCart) { SetSpeed(0, 0, 0); #ifdef __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wfloat-equal" #endif if (StopOffset.x != 0) { SetPosX(POSX_TOINT + StopOffset.x); } if (StopOffset.z != 0) { SetPosZ(POSZ_TOINT + StopOffset.z); } #ifdef __clang__ #pragma clang diagnostic pop #endif return true; } return false; } bool cMinecart::TestEntityCollision(NIBBLETYPE a_RailMeta) { cMinecartCollisionCallback MinecartCollisionCallback( GetPosition(), GetHeight(), GetWidth(), GetUniqueID(), ((m_Attachee == nullptr) ? cEntity::INVALID_ID : m_Attachee->GetUniqueID()) ); int ChunkX, ChunkZ; cChunkDef::BlockToChunk(POSX_TOINT, POSZ_TOINT, ChunkX, ChunkZ); m_World->ForEachEntityInChunk(ChunkX, ChunkZ, MinecartCollisionCallback); if (!MinecartCollisionCallback.FoundIntersection()) { return false; } // Collision was true, create bounding box for minecart, call attach callback for all entities within that box cMinecartAttachCallback MinecartAttachCallback(*this, m_Attachee); Vector3d MinecartPosition = GetPosition(); cBoundingBox bbMinecart(Vector3d(MinecartPosition.x, floor(MinecartPosition.y), MinecartPosition.z), GetWidth() / 2, GetHeight()); m_World->ForEachEntityInBox(bbMinecart, MinecartAttachCallback); switch (a_RailMeta) { case E_META_RAIL_ZM_ZP: { if (MinecartCollisionCallback.GetCollidedEntityPosition().z >= GetPosZ()) { if (GetSpeedZ() > 0) // True if minecart is moving into the direction of the entity { SetSpeedZ(0); // Entity handles the pushing } } else // if (MinecartCollisionCallback.GetCollidedEntityPosition().z < GetPosZ()) { if (GetSpeedZ() < 0) // True if minecart is moving into the direction of the entity { SetSpeedZ(0); // Entity handles the pushing } } return true; } case E_META_RAIL_XM_XP: { if (MinecartCollisionCallback.GetCollidedEntityPosition().x >= GetPosX()) { if (GetSpeedX() > 0) // True if minecart is moving into the direction of the entity { SetSpeedX(0); // Entity handles the pushing } } else // if (MinecartCollisionCallback.GetCollidedEntityPosition().x < GetPosX()) { if (GetSpeedX() < 0) // True if minecart is moving into the direction of the entity { SetSpeedX(0); // Entity handles the pushing } } return true; } case E_META_RAIL_CURVED_ZM_XM: case E_META_RAIL_CURVED_ZP_XP: { Vector3d Distance = MinecartCollisionCallback.GetCollidedEntityPosition() - Vector3d(GetPosX(), 0, GetPosZ()); // Prevent division by small numbers if (std::abs(Distance.z) < 0.001) { Distance.z = 0.001; } /* Check to which side the minecart is to be pushed. Let's consider a z-x-coordinate system where the minecart is the center (0, 0). The minecart moves along the line x = -z, the perpendicular line to this is x = z. In order to decide to which side the minecart is to be pushed, it must be checked on what side of the perpendicular line the pushing entity is located. */ if ( ((Distance.z > 0) && ((Distance.x / Distance.z) >= 1)) || ((Distance.z < 0) && ((Distance.x / Distance.z) <= 1)) ) { // Moving -X +Z if ((-GetSpeedX() * 0.4 / sqrt(2.0)) < 0.01) { // ~ SpeedX >= 0 Immobile or not moving in the "right" direction. Give it a bump! AddSpeedX(-4 / sqrt(2.0)); AddSpeedZ(4 / sqrt(2.0)); } else { // ~ SpeedX < 0 Moving in the "right" direction. Only accelerate it a bit. SetSpeedX(GetSpeedX() * 0.4 / sqrt(2.0)); SetSpeedZ(GetSpeedZ() * 0.4 / sqrt(2.0)); } } else if ((GetSpeedX() * 0.4 / sqrt(2.0)) < 0.01) { // Moving +X -Z // ~ SpeedX <= 0 Immobile or not moving in the "right" direction AddSpeedX(4 / sqrt(2.0)); AddSpeedZ(-4 / sqrt(2.0)); } else { // ~ SpeedX > 0 Moving in the "right" direction SetSpeedX(GetSpeedX() * 0.4 / sqrt(2.0)); SetSpeedZ(GetSpeedZ() * 0.4 / sqrt(2.0)); } break; } case E_META_RAIL_CURVED_ZM_XP: case E_META_RAIL_CURVED_ZP_XM: { Vector3d Distance = MinecartCollisionCallback.GetCollidedEntityPosition() - Vector3d(GetPosX(), 0, GetPosZ()); // Prevent division by small numbers if (std::abs(Distance.z) < 0.001) { Distance.z = 0.001; } /* Check to which side the minecart is to be pushed. Let's consider a z-x-coordinate system where the minecart is the center (0, 0). The minecart moves along the line x = z, the perpendicular line to this is x = -z. In order to decide to which side the minecart is to be pushed, it must be checked on what side of the perpendicular line the pushing entity is located. */ if ( ((Distance.z > 0) && ((Distance.x / Distance.z) <= -1)) || ((Distance.z < 0) && ((Distance.x / Distance.z) >= -1)) ) { // Moving +X +Z if ((GetSpeedX() * 0.4) < 0.01) { // ~ SpeedX <= 0 Immobile or not moving in the "right" direction AddSpeedX(4 / sqrt(2.0)); AddSpeedZ(4 / sqrt(2.0)); } else { // ~ SpeedX > 0 Moving in the "right" direction SetSpeedX(GetSpeedX() * 0.4 / sqrt(2.0)); SetSpeedZ(GetSpeedZ() * 0.4 / sqrt(2.0)); } } else if ((-GetSpeedX() * 0.4) < 0.01) { // Moving -X -Z // ~ SpeedX >= 0 Immobile or not moving in the "right" direction AddSpeedX(-4 / sqrt(2.0)); AddSpeedZ(-4 / sqrt(2.0)); } else { // ~ SpeedX < 0 Moving in the "right" direction SetSpeedX(GetSpeedX() * 0.4 / sqrt(2.0)); SetSpeedZ(GetSpeedZ() * 0.4 / sqrt(2.0)); } break; } default: break; } return false; } bool cMinecart::DoTakeDamage(TakeDamageInfo & TDI) { if ((TDI.Attacker != nullptr) && TDI.Attacker->IsPlayer() && static_cast(TDI.Attacker)->IsGameModeCreative()) { TDI.FinalDamage = GetMaxHealth(); // Instant hit for creative SetInvulnerableTicks(0); return Super::DoTakeDamage(TDI); // No drops for creative } m_LastDamage = static_cast(TDI.FinalDamage); if (!Super::DoTakeDamage(TDI)) { return false; } m_World->BroadcastEntityMetadata(*this); return true; } void cMinecart::KilledBy(TakeDamageInfo & a_TDI) { Super::KilledBy(a_TDI); Destroy(); } void cMinecart::OnRemoveFromWorld(cWorld & a_World) { if (m_bIsOnDetectorRail) { m_World->SetBlock(m_DetectorRailPosition, E_BLOCK_DETECTOR_RAIL, m_World->GetBlockMeta(m_DetectorRailPosition) & 0x07); } Super::OnRemoveFromWorld(a_World); } void cMinecart::HandleSpeedFromAttachee(float a_Forward, float a_Sideways) { // limit normal minecart speed max lower than 4 // once speed is higher than 4, no more add speed. if (GetSpeed().Length() > 4) { return; } Vector3d LookVector = m_Attachee->GetLookVector(); Vector3d ToAddSpeed = LookVector * (a_Forward * 0.4) ; ToAddSpeed.y = 0; AddSpeed(ToAddSpeed); } void cMinecart::ApplyAcceleration(Vector3d a_ForwardDirection, double a_Acceleration) { double CurSpeed = GetSpeed().Dot(a_ForwardDirection); double NewSpeed = CurSpeed + a_Acceleration; if (NewSpeed < 0.0) { // Prevent deceleration from turning the minecart around. NewSpeed = 0.0; } auto Acceleration = a_ForwardDirection * (NewSpeed - CurSpeed); AddSpeed(Acceleration); } //////////////////////////////////////////////////////////////////////////////// // cRideableMinecart: cRideableMinecart::cRideableMinecart(Vector3d a_Pos, const cItem & a_Content, int a_ContentHeight): Super(mpNone, a_Pos), m_Content(a_Content), m_ContentHeight(a_ContentHeight) { } void cRideableMinecart::GetDrops(cItems & a_Drops, cEntity * a_Killer) { a_Drops.emplace_back(E_ITEM_MINECART); } void cRideableMinecart::OnRightClicked(cPlayer & a_Player) { Super::OnRightClicked(a_Player); if (m_Attachee != nullptr) { if (m_Attachee->GetUniqueID() == a_Player.GetUniqueID()) { // This player is already sitting in, they want out. a_Player.Detach(); return; } if (m_Attachee->IsPlayer()) { // Another player is already sitting in here, cannot attach return; } // Detach whatever is sitting in this minecart now: m_Attachee->Detach(); } // Attach the player to this minecart: a_Player.AttachTo(*this); } //////////////////////////////////////////////////////////////////////////////// // cMinecartWithChest: cMinecartWithChest::cMinecartWithChest(Vector3d a_Pos): Super(mpChest, a_Pos), cEntityWindowOwner(this), m_Contents(ContentsWidth, ContentsHeight) { m_Contents.AddListener(*this); } void cMinecartWithChest::GetDrops(cItems & a_Drops, cEntity * a_Killer) { m_Contents.CopyToItems(a_Drops); a_Drops.emplace_back(E_ITEM_CHEST_MINECART); } void cMinecartWithChest::OnRemoveFromWorld(cWorld & a_World) { const auto Window = GetWindow(); if (Window != nullptr) { Window->OwnerDestroyed(); } Super::OnRemoveFromWorld(a_World); } void cMinecartWithChest::OnRightClicked(cPlayer & a_Player) { // If the window is not created, open it anew: cWindow * Window = GetWindow(); if (Window == nullptr) { OpenNewWindow(); Window = GetWindow(); } // Open the window for the player: if (Window != nullptr) { if (a_Player.GetWindow() != Window) { a_Player.OpenWindow(*Window); } } } void cMinecartWithChest::OpenNewWindow() { OpenWindow(new cMinecartWithChestWindow(this)); } //////////////////////////////////////////////////////////////////////////////// // cMinecartWithFurnace: cMinecartWithFurnace::cMinecartWithFurnace(Vector3d a_Pos): Super(mpFurnace, a_Pos), m_FueledTimeLeft(-1), m_IsFueled(false) { } void cMinecartWithFurnace::GetDrops(cItems & a_Drops, cEntity * a_Killer) { a_Drops.emplace_back(E_ITEM_FURNACE_MINECART); } void cMinecartWithFurnace::OnRightClicked(cPlayer & a_Player) { if (a_Player.GetEquippedItem().m_ItemType == E_ITEM_COAL) { if (!a_Player.IsGameModeCreative()) { a_Player.GetInventory().RemoveOneEquippedItem(); } if (!m_IsFueled) // We don't want to change the direction by right clicking it. { AddSpeed(a_Player.GetLookVector().x, 0, a_Player.GetLookVector().z); } m_IsFueled = true; m_FueledTimeLeft = m_FueledTimeLeft + 600; // The minecart will be active 600 more ticks. m_World->BroadcastEntityMetadata(*this); } } void cMinecartWithFurnace::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { Super::Tick(a_Dt, a_Chunk); if (!IsTicking()) { // The base class tick destroyed us return; } if (m_IsFueled) { m_FueledTimeLeft--; if (m_FueledTimeLeft < 0) { m_IsFueled = false; m_World->BroadcastEntityMetadata(*this); return; } if (GetSpeed().Length() > 6) { return; } AddSpeed(GetSpeed() / 4); } } //////////////////////////////////////////////////////////////////////////////// // cMinecartWithTNT: cMinecartWithTNT::cMinecartWithTNT(Vector3d a_Pos): Super(mpTNT, a_Pos) { } void cMinecartWithTNT::HandleActivatorRailPhysics(NIBBLETYPE a_RailMeta, std::chrono::milliseconds a_Dt) { Super::HandleActivatorRailPhysics(a_RailMeta, a_Dt); if ((a_RailMeta & 0x08) && !m_isTNTFused) { m_isTNTFused = true; m_TNTFuseTicksLeft = 80; m_World->BroadcastSoundEffect("entity.tnt.primed", GetPosition(), 1.0f, 1.0f); m_World->BroadcastEntityAnimation(*this, EntityAnimation::MinecartTNTIgnites); } } void cMinecartWithTNT::GetDrops(cItems & a_Drops, cEntity * a_Killer) { a_Drops.emplace_back(E_ITEM_MINECART_WITH_TNT); } void cMinecartWithTNT::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { Super::Tick(a_Dt, a_Chunk); if (!IsTicking()) { return; } if (m_isTNTFused) { if (m_TNTFuseTicksLeft > 0) { --m_TNTFuseTicksLeft; } else { Destroy(); m_World->DoExplosionAt(4.0, GetPosX(), GetPosY() + GetHeight() / 2, GetPosZ(), true, esTNTMinecart, this); } } } //////////////////////////////////////////////////////////////////////////////// // cMinecartWithHopper: cMinecartWithHopper::cMinecartWithHopper(Vector3d a_Pos): Super(mpHopper, a_Pos) { } // TODO: Make it suck up blocks and travel further than any other cart and physics and put and take blocks // AND AVARYTHING!! void cMinecartWithHopper::GetDrops(cItems & a_Drops, cEntity * a_Killer) { a_Drops.emplace_back(E_ITEM_MINECART_WITH_HOPPER); } ================================================ FILE: src/Entities/Minecart.h ================================================ // Minecart.h // Declares the cMinecart class representing a minecart in the world #pragma once #include "Entity.h" #include "../World.h" #include "../UI/WindowOwner.h" class cMinecart : public cEntity { using Super = cEntity; public: CLASS_PROTODEF(cMinecart) /** Minecart payload, values correspond to packet subtype */ enum ePayload { mpNone = 0, // Empty minecart, ridable by player or mobs mpChest = 1, // Minecart-with-chest, can store a grid of 3 * 8 items mpFurnace = 2, // Minecart-with-furnace, can be powered mpTNT = 3, // Minecart-with-TNT, can be blown up with activator rail mpHopper = 5, // Minecart-with-hopper, can be hopper // TODO: Spawner minecarts, (and possibly any block in a minecart with NBT editing) } ; // cEntity overrides: virtual void SpawnOn(cClientHandle & a_ClientHandle) override; virtual void HandlePhysics(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; virtual bool DoTakeDamage(TakeDamageInfo & TDI) override; virtual void KilledBy(TakeDamageInfo & a_TDI) override; virtual void OnRemoveFromWorld(cWorld & a_World) override; virtual void HandleSpeedFromAttachee(float a_Forward, float a_Sideways) override; int LastDamage(void) const { return m_LastDamage; } ePayload GetPayload(void) const { return m_Payload; } protected: ePayload m_Payload; int m_LastDamage; Vector3i m_DetectorRailPosition; bool m_bIsOnDetectorRail; /** Applies an acceleration to the minecart parallel to a_ForwardDirection but without allowing backward speed. */ void ApplyAcceleration(Vector3d a_ForwardDirection, double a_Acceleration); cMinecart(ePayload a_Payload, Vector3d a_Pos); /** Handles physics on normal rails For each tick, slow down on flat rails, speed up or slow down on ascending / descending rails (depending on direction), and turn on curved rails. */ void HandleRailPhysics(NIBBLETYPE a_RailMeta, std::chrono::milliseconds a_Dt); /** Handles powered rail physics Each tick, speed up or slow down cart, depending on metadata of rail (powered or not) */ void HandlePoweredRailPhysics(NIBBLETYPE a_RailMeta); /** Handles detector rail activation Activates detector rails when a minecart is on them. Calls HandleRailPhysics() for physics simulations */ void HandleDetectorRailPhysics(NIBBLETYPE a_RailMeta, std::chrono::milliseconds a_Dt); /** Handles activator rails */ virtual void HandleActivatorRailPhysics(NIBBLETYPE a_RailMeta, std::chrono::milliseconds a_Dt); /** Snaps a mincecart to a rail's axis, resetting its speed For curved rails, it changes the cart's direction as well as snapping it to axis */ void SnapToRail(NIBBLETYPE a_RailMeta); /** Tests if a solid block is in front of a cart, and stops the cart (and returns true) if so; returns false if no obstruction */ bool TestBlockCollision(NIBBLETYPE a_RailMeta); /** Tests if there is a block at the specified position which is impassable to minecarts */ bool IsSolidBlockAtPosition(Vector3i a_Offset); /** Tests if a solid block is at a specific offset of the minecart position */ bool IsSolidBlockAtOffset(int a_XOffset, int a_YOffset, int a_ZOffset); bool IsBlockCollisionAtOffset(Vector3i a_Offset); /** Tests if this mincecart's bounding box is intersecting another entity's bounding box (collision) and pushes mincecart away if necessary */ bool TestEntityCollision(NIBBLETYPE a_RailMeta); } ; class cRideableMinecart final : public cMinecart { using Super = cMinecart; public: CLASS_PROTODEF(cRideableMinecart) cRideableMinecart(Vector3d a_Pos, const cItem & a_Content, int a_ContentHeight); const cItem & GetContent(void) const { return m_Content; } int GetBlockHeight(void) const { return m_ContentHeight; } // cEntity overrides: virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override; virtual void OnRightClicked(cPlayer & a_Player) override; protected: cItem m_Content; int m_ContentHeight; } ; class cMinecartWithChest final : public cMinecart, public cItemGrid::cListener, public cEntityWindowOwner { using Super = cMinecart; public: CLASS_PROTODEF(cMinecartWithChest) cMinecartWithChest(Vector3d a_Pos); enum { ContentsHeight = 3, ContentsWidth = 9, }; const cItem & GetSlot(int a_Idx) const { return m_Contents.GetSlot(a_Idx); } void SetSlot(int a_Idx, const cItem & a_Item) { m_Contents.SetSlot(a_Idx, a_Item); } protected: cItemGrid m_Contents; void OpenNewWindow(void); // cItemGrid::cListener overrides: virtual void OnSlotChanged(cItemGrid * a_Grid, int a_SlotNum) override { UNUSED(a_SlotNum); ASSERT(a_Grid == &m_Contents); if (m_World != nullptr) { if (GetWindow() != nullptr) { GetWindow()->BroadcastWholeWindow(); } m_World->MarkChunkDirty(GetChunkX(), GetChunkZ()); } } // cEntity overrides: virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override; virtual void OnRemoveFromWorld(cWorld & a_World) override; virtual void OnRightClicked(cPlayer & a_Player) override; } ; class cMinecartWithFurnace final : public cMinecart { using Super = cMinecart; public: CLASS_PROTODEF(cMinecartWithFurnace) cMinecartWithFurnace(Vector3d a_Pos); // cEntity overrides: virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override; virtual void OnRightClicked(cPlayer & a_Player) override; virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; // Set functions. void SetIsFueled(bool a_IsFueled, int a_FueledTimeLeft = -1) {m_IsFueled = a_IsFueled; m_FueledTimeLeft = a_FueledTimeLeft;} // Get functions. int GetFueledTimeLeft(void) const {return m_FueledTimeLeft; } bool IsFueled (void) const {return m_IsFueled;} private: int m_FueledTimeLeft; bool m_IsFueled; } ; class cMinecartWithTNT final : public cMinecart { using Super = cMinecart; public: CLASS_PROTODEF(cMinecartWithTNT) cMinecartWithTNT(Vector3d a_Pos); void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; private: int m_TNTFuseTicksLeft; bool m_isTNTFused = false; virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override; void HandleActivatorRailPhysics(NIBBLETYPE a_RailMeta, std::chrono::milliseconds a_Dt) override; } ; class cMinecartWithHopper final : public cMinecart { using Super = cMinecart; public: CLASS_PROTODEF(cMinecartWithHopper) cMinecartWithHopper(Vector3d a_Pos); private: virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override; } ; ================================================ FILE: src/Entities/Painting.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "Painting.h" #include "Player.h" #include "../ClientHandle.h" #include "../Chunk.h" cPainting::cPainting(const AString & a_Name, eBlockFace a_Direction, Vector3d a_Pos): Super(etPainting, a_Direction, a_Pos), m_Name(a_Name) { } void cPainting::SpawnOn(cClientHandle & a_Client) { Super::SpawnOn(a_Client); a_Client.SendPaintingSpawn(*this); m_World->BroadcastSoundEffect("entity.painting.place", GetPosition(), 1, 1); } void cPainting::GetDrops(cItems & a_Items, cEntity * a_Killer) { a_Items.emplace_back(E_ITEM_PAINTING); } void cPainting::KilledBy(TakeDamageInfo & a_TDI) { Super::KilledBy(a_TDI); m_World->BroadcastSoundEffect("entity.painting.break", GetPosition(), 1, 1); } ================================================ FILE: src/Entities/Painting.h ================================================ #pragma once #include "HangingEntity.h" // tolua_begin class cPainting : public cHangingEntity { // tolua_end using Super = cHangingEntity; public: // tolua_export CLASS_PROTODEF(cPainting) cPainting(const AString & a_Name, eBlockFace a_Direction, Vector3d a_Pos); /** Returns the protocol name of the painting */ const AString & GetName(void) const { return m_Name; } // tolua_export private: virtual void SpawnOn(cClientHandle & a_Client) override; virtual void GetDrops(cItems & a_Items, cEntity * a_Killer) override; virtual void KilledBy(TakeDamageInfo & a_TDI) override; AString m_Name; }; // tolua_export ================================================ FILE: src/Entities/Pawn.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "Pawn.h" #include "Player.h" #include "../BlockInfo.h" #include "../World.h" #include "../Bindings/PluginManager.h" #include "../BoundingBox.h" #include "../Blocks/BlockHandler.h" #include "../Blocks/BlockFarmland.h" #include "../EffectID.h" #include "../Mobs/Monster.h" cPawn::cPawn(eEntityType a_EntityType, float a_Width, float a_Height) : Super(a_EntityType, Vector3d(), a_Width, a_Height), m_EntityEffects(tEffectMap()), m_LastGroundHeight(0), m_bTouchGround(false) { SetGravity(-32.0f); SetAirDrag(0.02f); } void cPawn::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { std::vector EffectsToTick; // Iterate through this entity's applied effects for (tEffectMap::iterator iter = m_EntityEffects.begin(); iter != m_EntityEffects.end();) { // Copies values to prevent pesky wrong accesses and erasures cEntityEffect::eType EffectType = iter->first; cEntityEffect * Effect = iter->second.get(); // Iterates (must be called before any possible erasure) ++iter; // Remove effect if duration has elapsed if (Effect->GetDuration() - Effect->GetTicks() <= 0) { RemoveEntityEffect(EffectType); } // Call OnTick later to make sure the iterator won't be invalid else { EffectsToTick.push_back(Effect); } // TODO: Check for discrepancies between client and server effect values } for (auto * Effect : EffectsToTick) { Effect->OnTick(*this); } // Spectators cannot push entities around if ((!IsPlayer()) || (!static_cast(this)->IsGameModeSpectator())) { m_World->ForEachEntityInBox(GetBoundingBox(), [=](cEntity & a_Entity) { if (a_Entity.GetUniqueID() == GetUniqueID()) { return false; } // we only push other mobs, boats and minecarts if ((a_Entity.GetEntityType() != etMonster) && (a_Entity.GetEntityType() != etMinecart) && (a_Entity.GetEntityType() != etBoat)) { return false; } // do not push a boat / minecart you're sitting in if (IsAttachedTo(&a_Entity)) { return false; } Vector3d v3Delta = a_Entity.GetPosition() - GetPosition(); v3Delta.y = 0.0; // we only push sideways v3Delta *= 1.0 / (v3Delta.Length() + 0.01); // we push harder if we're close // QUESTION: is there an additional multiplier for this? current shoving seems a bit weak a_Entity.AddSpeed(v3Delta); return false; } ); } Super::Tick(a_Dt, a_Chunk); if (!IsTicking()) { // The base class tick destroyed us return; } HandleFalling(); // Handle item pickup if (m_Health > 0) { if (IsPlayer()) { m_World->CollectPickupsByEntity(*this); } else if (IsMob()) { cMonster & Mob = static_cast(*this); if (Mob.CanPickUpLoot()) { m_World->CollectPickupsByEntity(*this); } } } } void cPawn::KilledBy(TakeDamageInfo & a_TDI) { ClearEntityEffects(); // Is death eligible for totem reanimation? if (DeductTotem(a_TDI.DamageType)) { m_World->BroadcastEntityAnimation(*this, EntityAnimation::PawnTotemActivates); AddEntityEffect(cEntityEffect::effAbsorption, 100, 1); AddEntityEffect(cEntityEffect::effRegeneration, 900, 1); AddEntityEffect(cEntityEffect::effFireResistance, 800, 0); m_Health = 1; return; } Super::KilledBy(a_TDI); } bool cPawn::IsFireproof(void) const { return Super::IsFireproof() || HasEntityEffect(cEntityEffect::effFireResistance); } bool cPawn::IsInvisible() const { return HasEntityEffect(cEntityEffect::effInvisibility); } void cPawn::HandleAir(void) { if (IsHeadInWater() && HasEntityEffect(cEntityEffect::effWaterBreathing)) { // Prevent the oxygen from decreasing return; } Super::HandleAir(); } void cPawn::AddEntityEffect(cEntityEffect::eType a_EffectType, int a_Duration, short a_Intensity, double a_DistanceModifier) { // Check if the plugins allow the addition: if (cPluginManager::Get()->CallHookEntityAddEffect(*this, a_EffectType, a_Duration, a_Intensity, a_DistanceModifier)) { // A plugin disallows the addition, bail out. return; } // No need to add empty effects: if (a_EffectType == cEntityEffect::effNoEffect) { return; } a_Duration = static_cast(a_Duration * a_DistanceModifier); // If we already have the effect, we have to deactivate it or else it will act cumulatively auto ExistingEffect = m_EntityEffects.find(a_EffectType); if (ExistingEffect != m_EntityEffects.end()) { ExistingEffect->second->OnDeactivate(*this); } auto Res = m_EntityEffects.emplace(a_EffectType, cEntityEffect::CreateEntityEffect(a_EffectType, a_Duration, a_Intensity, a_DistanceModifier)); m_World->BroadcastEntityEffect(*this, a_EffectType, a_Intensity, a_Duration); cEntityEffect * Effect = Res.first->second.get(); Effect->OnActivate(*this); } void cPawn::RemoveEntityEffect(cEntityEffect::eType a_EffectType) { m_World->BroadcastRemoveEntityEffect(*this, a_EffectType); auto itr = m_EntityEffects.find(a_EffectType); if (itr != m_EntityEffects.end()) { // Erase from effect map before calling OnDeactivate to allow metadata broadcasts (e.g. for invisibility effect) auto Effect = std::move(itr->second); m_EntityEffects.erase(itr); Effect->OnDeactivate(*this); } } bool cPawn::HasEntityEffect(cEntityEffect::eType a_EffectType) const { return m_EntityEffects.find(a_EffectType) != m_EntityEffects.end(); } void cPawn::ClearEntityEffects() { // Iterate through this entity's applied effects for (tEffectMap::iterator iter = m_EntityEffects.begin(); iter != m_EntityEffects.end();) { // Copy values to prevent pesky wrong erasures cEntityEffect::eType EffectType = iter->first; // Iterates (must be called before any possible erasure) ++iter; // Remove effect RemoveEntityEffect(EffectType); } } void cPawn::NoLongerTargetingMe(cMonster * a_Monster) { ASSERT(IsTicking()); // Our destroy override is supposed to clear all targets before we're destroyed. for (auto i = m_TargetingMe.begin(); i != m_TargetingMe.end(); ++i) { cMonster * Monster = *i; if (Monster == a_Monster) { ASSERT(Monster->GetTarget() != this); // The monster is notifying us it is no longer targeting us, assert if that's a lie m_TargetingMe.erase(i); return; } } ASSERT(false); // If this happens, something is wrong. Perhaps the monster never called TargetingMe() or called NoLongerTargetingMe() twice. } void cPawn::TargetingMe(cMonster * a_Monster) { ASSERT(IsTicking()); ASSERT(m_TargetingMe.size() < 10000); ASSERT(a_Monster->GetTarget() == this); m_TargetingMe.push_back(a_Monster); } void cPawn::HandleFalling(void) { /* Not pretty looking, and is more suited to wherever server-sided collision detection is implemented. The following condition sets on-ground-ness if The player isn't swimming or flying (client hardcoded conditions) and they're on a block (Y is exact) - ensure any they could be standing on (including on the edges) is solid or they're on a slab (Y significand is 0.5) - ditto with slab check they're on a snow layer (Y divisible by 0.125) - ditto with snow layer check */ static const auto HalfWidth = GetWidth() / 2; static const auto EPS = 0.0001; /* Since swimming is decided in a tick and is asynchronous to this, we have to check for dampeners ourselves. The behaviour as of 1.8.9 is the following: - Landing in water alleviates all fall damage - Passing through any liquid (water + lava) and cobwebs "slows" the player down, i.e. resets the fall distance to that block, but only after checking for fall damage (this means that plummeting into lava will still kill the player via fall damage, although cobwebs will slow players down enough to have multiple updates that keep them alive) - Slime blocks reverse falling velocity, unless it's a crouching player, in which case they act as standard blocks. They also reset the topmost point of the damage calculation with each bounce, so if the block is removed while the player is bouncing or crouches after a bounce, the last bounce's zenith is considered as fall damage. With this in mind, we first check the block at the player's feet, then the one below that (because fences), and decide which behaviour we want to go with. */ const auto BlockAtFoot = (cChunkDef::IsValidHeight(POS_TOINT)) ? GetWorld()->GetBlock(POS_TOINT) : static_cast(E_BLOCK_AIR); /* We initialize these with what the foot is really IN, because for sampling we will move down with the epsilon above */ bool IsFootInWater = IsBlockWater(BlockAtFoot); bool IsFootOnSlimeBlock = false; /* The "cross" we sample around to account for the player width/girth */ static const struct { int x, z; } CrossSampleCoords[] = { { 0, 0 }, { 1, 0 }, { -1, 0 }, { 0, 1 }, { 0, -1 }, }; /* The blocks we're interested in relative to the player to account for larger than 1 blocks. This can be extended to do additional checks in case there are blocks that are represented as one block in memory but have a hitbox larger than 1 (like fences) */ static const Vector3i BlockSampleOffsets[] = { { 0, 0, 0 }, // TODO: something went wrong here (offset 0?) { 0, -1, 0 }, // Potentially causes mis-detection (IsFootInWater) when player stands on block diagonal to water (i.e. on side of pool) }; /* Here's the rough outline of how this mechanism works: We take the player's pointlike position (sole of feet), and expand it into a crosslike shape. If any of the five points hit a block, we consider the player to be "on" (or "in") the ground. */ bool OnGround = false; for (size_t i = 0; i < ARRAYCOUNT(CrossSampleCoords); i++) { /* We calculate from the player's position, one of the cross-offsets above, and we move it down slightly so it's beyond inaccuracy. The added advantage of this method is that if the player is simply standing on the floor, the point will move into the next block, and the floor() will retrieve that instead of air. */ Vector3d CrossTestPosition = GetPosition() + Vector3d(CrossSampleCoords[i].x * HalfWidth, -EPS, CrossSampleCoords[i].z * HalfWidth); /* We go through the blocks that we consider "relevant" */ for (size_t j = 0; j < ARRAYCOUNT(BlockSampleOffsets); j++) { Vector3i BlockTestPosition = CrossTestPosition.Floor() + BlockSampleOffsets[j]; if (!cChunkDef::IsValidHeight(BlockTestPosition)) { continue; } BLOCKTYPE BlockType = GetWorld()->GetBlock(BlockTestPosition); NIBBLETYPE BlockMeta = GetWorld()->GetBlockMeta(BlockTestPosition); /* we do the cross-shaped sampling to check for water / liquids, but only on our level because water blocks are never bigger than unit voxels */ if (j == 0) { IsFootInWater |= IsBlockWater(BlockType); IsFootOnSlimeBlock |= (BlockType == E_BLOCK_SLIME_BLOCK); } /* If the block is solid, and the blockhandler confirms the block to be inside, we're officially on the ground. */ if ((cBlockInfo::IsSolid(BlockType)) && (cBlockHandler::For(BlockType).IsInsideBlock(CrossTestPosition - BlockTestPosition, BlockMeta))) { OnGround = true; } } } /* So here's the use of the rules above: */ /* 1. Falling in water absorbs all fall damage */ bool FallDamageAbsorbed = IsFootInWater; /* 2. Falling in liquid (lava, water, cobweb) or hitting a slime block resets the "fall zenith". Note: Even though the pawn bounces back with no damage after hitting the slime block, the "fall zenith" will continue to increase back up when flying upwards - which is good */ bool ShouldBounceOnSlime = true; if (IsPlayer()) { auto Player = static_cast(this); /* 3. If the player is flying or climbing, absorb fall damage */ FallDamageAbsorbed |= Player->IsFlying() || Player->IsClimbing() || Player->GetIsTeleporting(); /* 4. If the player is about to bounce on a slime block and is not crouching, absorb all fall damage */ ShouldBounceOnSlime = !Player->IsCrouched(); FallDamageAbsorbed |= (IsFootOnSlimeBlock && ShouldBounceOnSlime); } else { /* 5. Bouncing on a slime block absorbs all fall damage */ FallDamageAbsorbed |= IsFootOnSlimeBlock; } /* If the player is not crouching or is not a player, shoot them back up. NOTE: this will only work in some cases; should be done in HandlePhysics() */ if (IsFootOnSlimeBlock && ShouldBounceOnSlime) { // TODO: doesn't work too well, causes dissatisfactory experience for players on slime blocks - SetSpeedY(-GetSpeedY()); } // TODO: put player speed into GetSpeedY, and use that. // If flying, climbing, swimming, or going up... if (FallDamageAbsorbed || ((GetPosition() - m_LastPosition).y > 0)) { // ...update the ground height to have the highest position of the player (i.e. jumping up adds to the eventual fall damage) m_LastGroundHeight = GetPosY(); } if (OnGround) { const auto FallHeight = m_LastGroundHeight - GetPosY(); auto Damage = static_cast(FallHeight - 3.0); const auto Below = POS_TOINT.addedY(-1); const auto BlockBelow = (cChunkDef::IsValidHeight(Below)) ? GetWorld()->GetBlock(Below) : static_cast(E_BLOCK_AIR); if ((Damage > 0) && !FallDamageAbsorbed) { if (IsElytraFlying()) { Damage = static_cast(static_cast(Damage) * 0.33); } if (BlockBelow == E_BLOCK_HAY_BALE) { Damage = std::clamp(static_cast(static_cast(Damage) * 0.2), 1, 20); } // Fall particles // TODO: falling on a partial (e.g. slab) block shouldn't broadcast particles of the block below GetWorld()->BroadcastParticleEffect( "blockdust", GetPosition(), { 0, 0, 0 }, (Damage - 1.f) * ((0.3f - 0.1f) / (15.f - 1.f)) + 0.1f, // Map damage (1 - 15) to particle speed (0.1 - 0.3) static_cast((Damage - 1.f) * ((50.f - 20.f) / (15.f - 1.f)) + 20.f), // Map damage (1 - 15) to particle quantity (20 - 50) { { BlockBelow, 0 } } ); TakeDamage(dtFalling, nullptr, Damage, static_cast(Damage), 0); } m_bTouchGround = true; m_LastGroundHeight = GetPosY(); // Farmland trampling. Mobs smaller than 0.512 cubic blocks won't trample (Java Edition's behavior) // We only have width and height, so we have to calculate Width^2 if (GetWorld()->IsFarmlandTramplingEnabled()) { HandleFarmlandTrampling(FallHeight, BlockAtFoot, BlockBelow); } } else { m_bTouchGround = false; } /* Note: it is currently possible to fall through lava and still die from fall damage because of the client skipping an update about the lava block. This can only be resolved by somehow integrating these above checks into the tracer in HandlePhysics. */ } void cPawn::HandleFarmlandTrampling(const double a_FallHeight, const BLOCKTYPE a_BlockAtFoot, const BLOCKTYPE a_BlockBelow) { // No trampling if FallHeight <= 0.6875 if (a_FallHeight <= 0.6875) { return; } // No trampling for mobs smaller than 0.512 cubic blocks if (GetWidth() * GetWidth() * GetHeight() < 0.512) { return; } auto AbsPos = POS_TOINT; // Check if the foot is "inside" a farmland - for 1.10.1 and newer clients // If it isn't, check if the block below is a farmland - for mobs and older clients if (a_BlockAtFoot != E_BLOCK_FARMLAND) { // These are probably the only blocks which: // - can be placed on a farmland and shouldn't destroy it // - will stop the player from falling down further // - are less than 1 block high if ((a_BlockAtFoot == E_BLOCK_HEAD) || (a_BlockAtFoot == E_BLOCK_FLOWER_POT)) { return; } // Finally, check whether the block below is farmland if (a_BlockBelow != E_BLOCK_FARMLAND) { return; } // If we haven't returned, decrease the height AbsPos.y -= 1; } bool ShouldTrample = true; auto & Random = GetRandomProvider(); // For FallHeight <= 1.5625 we need to get a random bool if (a_FallHeight <= 1.0625) { ShouldTrample = Random.RandBool(0.25); } else if (a_FallHeight <= 1.5625) { ShouldTrample = Random.RandBool(0.66); } // For FallHeight > 1.5625 we always trample - ShouldTrample remains true if (ShouldTrample) { GetWorld()->DoWithChunkAt(AbsPos, [&](cChunk & Chunk) { cBlockFarmlandHandler::TurnToDirt(Chunk, AbsPos); return true; }); } } void cPawn::OnRemoveFromWorld(cWorld & a_World) { StopEveryoneFromTargetingMe(); Super::OnRemoveFromWorld(a_World); } void cPawn::StopEveryoneFromTargetingMe() { std::vector::iterator i = m_TargetingMe.begin(); while (i != m_TargetingMe.end()) { cMonster * Monster = *i; ASSERT(Monster->GetTarget() == this); Monster->UnsafeUnsetTarget(); i = m_TargetingMe.erase(i); } ASSERT(m_TargetingMe.size() == 0); } std::map cPawn::GetEntityEffects() const { std::map Effects; for (auto & Effect : m_EntityEffects) { Effects.insert({ Effect.first, Effect.second.get() }); } return Effects; } cEntityEffect * cPawn::GetEntityEffect(cEntityEffect::eType a_EffectType) const { auto itr = m_EntityEffects.find(a_EffectType); return (itr != m_EntityEffects.end()) ? itr->second.get() : nullptr; } void cPawn::ResetPosition(Vector3d a_NewPosition) { Super::ResetPosition(a_NewPosition); m_LastGroundHeight = GetPosY(); } bool cPawn::DeductTotem(const eDamageType a_DamageType) { if ((a_DamageType == dtAdmin) || (a_DamageType == dtInVoid)) { // Beyond saving: return false; } if (!IsPlayer()) { // TODO: implement when mobs will be able to pick up items based on CanPickUpLoot attribute: return false; } // If the player is holding a totem of undying in their off-hand or // main-hand slot and receives otherwise fatal damage, the totem saves the player from death. auto & inv = static_cast(this)->GetInventory(); if (inv.GetEquippedItem().m_ItemType == E_ITEM_TOTEM_OF_UNDYING) { inv.SetEquippedItem({}); return true; } if (inv.GetShieldSlot().m_ItemType == E_ITEM_TOTEM_OF_UNDYING) { inv.SetShieldSlot({}); return true; } return false; } bool cPawn::FindTeleportDestination(cWorld & a_World, const int a_HeightRequired, const unsigned int a_NumTries, Vector3d & a_Destination, const Vector3i a_MinBoxCorner, const Vector3i a_MaxBoxCorner) { /* Algorithm: Choose random destination. Seek downwards, regardless of distance until the block is made of movement-blocking material: https://minecraft.wiki/w/Materials Succeeds if no liquid or solid blocks prevents from standing at destination. */ auto & Random = GetRandomProvider(); for (unsigned int i = 0; i < a_NumTries; i++) { const int DestX = Random.RandInt(a_MinBoxCorner.x, a_MaxBoxCorner.x); int DestY = Random.RandInt(a_MinBoxCorner.y, a_MaxBoxCorner.y); const int DestZ = Random.RandInt(a_MinBoxCorner.z, a_MaxBoxCorner.z); // Seek downwards from initial destination until we find a solid block or go into the void BLOCKTYPE DestBlock = a_World.GetBlock({DestX, DestY, DestZ}); while ((DestY >= 0) && !cBlockInfo::IsSolid(DestBlock)) { DestBlock = a_World.GetBlock({DestX, DestY, DestZ}); DestY--; } // Couldn't find a solid block so move to next attempt if (DestY < 0) { continue; } // Succeed if blocks above destination are empty bool Success = true; for (int j = 1; j <= a_HeightRequired; j++) { BLOCKTYPE TestBlock = a_World.GetBlock({DestX, DestY + j, DestZ}); if (cBlockInfo::IsSolid(TestBlock) || IsBlockLiquid(TestBlock)) { Success = false; break; } } if (!Success) { continue; } // Offsets for entity to be centred and standing on solid block a_Destination = Vector3d(DestX + 0.5, DestY + 1, DestZ + 0.5); return true; } return false; } bool cPawn::FindTeleportDestination(cWorld & a_World, const int a_HeightRequired, const unsigned int a_NumTries, Vector3d & a_Destination, const cBoundingBox a_BoundingBox) { return FindTeleportDestination(a_World, a_HeightRequired, a_NumTries, a_Destination, a_BoundingBox.GetMin(), a_BoundingBox.GetMax()); } bool cPawn::FindTeleportDestination(cWorld & a_World, const int a_HeightRequired, const unsigned int a_NumTries, Vector3d & a_Destination, Vector3i a_Centre, const int a_HalfCubeWidth) { Vector3i MinCorner(a_Centre.x - a_HalfCubeWidth, a_Centre.y - a_HalfCubeWidth, a_Centre.z - a_HalfCubeWidth); Vector3i MaxCorner(a_Centre.x + a_HalfCubeWidth, a_Centre.y + a_HalfCubeWidth, a_Centre.z + a_HalfCubeWidth); return FindTeleportDestination(a_World, a_HeightRequired, a_NumTries, a_Destination, MinCorner, MaxCorner); } ================================================ FILE: src/Entities/Pawn.h ================================================ #pragma once #include "Entity.h" #include "EntityEffect.h" // fwd cMonster class cMonster; // tolua_begin class cPawn: public cEntity { // tolua_end using Super = cEntity; public: CLASS_PROTODEF(cPawn) cPawn(eEntityType a_EntityType, float a_Width, float a_Height); virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; virtual void KilledBy(TakeDamageInfo & a_TDI) override; virtual bool IsFireproof(void) const override; virtual bool IsInvisible() const override; virtual void HandleAir(void) override; virtual void HandleFalling(void); virtual void OnRemoveFromWorld(cWorld & a_World) override; /** Handles farmland trampling when hitting the ground. Algorithm: fall height <= 0.6875 blocks: no trampling fall height > 0.6875 and <= 1.0625: 25% chance of trampling fall height > 1.0625 and <= 1.5625: 66% chance of trampling fall height > 1.5625: always trample The values may differ from vanilla, they were determined experimentally. Additionaly, mobs smaller than 0.512 cubic blocks won't trample. */ void HandleFarmlandTrampling(double a_FallHeight, BLOCKTYPE a_BlockAtFoot, BLOCKTYPE a_BlockBelow); /** Tells all pawns which are targeting us to stop targeting us. */ void StopEveryoneFromTargetingMe(); // tolua_begin /** Applies an entity effect. Checks with plugins if they allow the addition. a_EffectIntensity is the level of the effect (0 = Potion I, 1 = Potion II, etc). a_DistanceModifier is the scalar multiplied to the potion duration (only applies to splash potions). */ void AddEntityEffect(cEntityEffect::eType a_EffectType, int a_EffectDurationTicks, short a_EffectIntensity, double a_DistanceModifier = 1); /** Removes a currently applied entity effect. */ void RemoveEntityEffect(cEntityEffect::eType a_EffectType); /** Returns true, if the entity effect is currently applied. */ bool HasEntityEffect(cEntityEffect::eType a_EffectType) const; /** Removes all currently applied entity effects (used when drinking milk) */ void ClearEntityEffects(void); // tolua_end /** Remove the monster from the list of monsters targeting this pawn. */ void NoLongerTargetingMe(cMonster * a_Monster); /** Add the monster to the list of monsters targeting this pawn. (Does not check if already in list!) */ void TargetingMe(cMonster * a_Monster); /** Returns all entity effects */ std::map GetEntityEffects() const; /** Returns the entity effect, if it is currently applied or nullptr if not. */ cEntityEffect * GetEntityEffect(cEntityEffect::eType a_EffectType) const; // tolua_begin static bool FindTeleportDestination(cWorld & a_World, const int a_HeightRequired, const unsigned int a_NumTries, Vector3d & a_Destination, const Vector3i a_MinBoxCorner, const Vector3i a_MaxBoxCorner); static bool FindTeleportDestination(cWorld & a_World, const int a_HeightRequired, const unsigned int a_NumTries, Vector3d & a_Destination, const cBoundingBox a_BoundingBox); /** Used by enderman and chorus fruit. Checks for valid destinations in a cube of length 2 * a_HalfCubeWidth centred at a_Centre. Returns true and places destination in a_Destination if successful. Returns false if destination could be found after a_NumTries attempts. Details at: https://minecraft.wiki/w/Enderman#Teleportation. */ static bool FindTeleportDestination(cWorld & a_World, const int a_HeightRequired, const unsigned int a_NumTries, Vector3d & a_Destination, Vector3i a_Centre, const int a_HalfCubeWidth); // tolua_end protected: typedef std::map> tEffectMap; tEffectMap m_EntityEffects; double m_LastGroundHeight; bool m_bTouchGround; virtual void ResetPosition(Vector3d a_NewPosition) override; private: /** A list of all monsters that are targeting this pawn. */ std::vector m_TargetingMe; /** Attempt to activate a Totem of Undying. If activation for the given type of damage was successful, consumes the totem and returns true. */ bool DeductTotem(eDamageType a_DamageType); } ; // tolua_export ================================================ FILE: src/Entities/Pickup.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #ifndef _WIN32 #include #endif #include "Pickup.h" #include "Player.h" #include "../Mobs/Villager.h" #include "../ClientHandle.h" #include "../World.h" #include "../Server.h" #include "../Bindings/PluginManager.h" #include "../Registries/Items.h" #include "../Root.h" #include "../Chunk.h" class cPickupCombiningCallback { public: cPickupCombiningCallback(Vector3d a_Position, cPickup * a_Pickup) : m_FoundMatchingPickup(false), m_Position(a_Position), m_Pickup(a_Pickup) { } bool operator () (cEntity & a_Entity) { ASSERT(a_Entity.IsTicking()); if (!a_Entity.IsPickup() || (a_Entity.GetUniqueID() <= m_Pickup->GetUniqueID()) || !a_Entity.IsOnGround()) { return false; } Vector3d EntityPos = a_Entity.GetPosition(); double Distance = (EntityPos - m_Position).Length(); auto & OtherPickup = static_cast(a_Entity); cItem & Item = OtherPickup.GetItem(); if ((Distance < 1.2) && Item.IsEqual(m_Pickup->GetItem()) && OtherPickup.CanCombine()) { short CombineCount = static_cast(Item.m_ItemCount); if ((CombineCount + static_cast(m_Pickup->GetItem().m_ItemCount)) > static_cast(Item.GetMaxStackSize())) { CombineCount = Item.GetMaxStackSize() - m_Pickup->GetItem().m_ItemCount; } if (CombineCount <= 0) { return false; } m_Pickup->GetItem().AddCount(static_cast(CombineCount)); Item.m_ItemCount -= static_cast(CombineCount); if (Item.m_ItemCount <= 0) { a_Entity.GetWorld()->BroadcastCollectEntity(a_Entity, *m_Pickup, static_cast(CombineCount)); a_Entity.Destroy(); // Reset the timer m_Pickup->SetAge(0); } else { a_Entity.GetWorld()->BroadcastEntityMetadata(a_Entity); } m_FoundMatchingPickup = true; } return false; } inline bool FoundMatchingPickup() { return m_FoundMatchingPickup; } protected: bool m_FoundMatchingPickup; Vector3d m_Position; cPickup * m_Pickup; }; //////////////////////////////////////////////////////////////////////////////// // cPickup: cPickup::cPickup(Vector3d a_Pos, const cItem & a_Item, bool IsPlayerCreated, Vector3f a_Speed, int a_LifetimeTicks, bool a_CanCombine): Super(etPickup, a_Pos, 0.25f, 0.25f), m_Timer(0), m_Item(a_Item), m_bCollected(false), m_bIsPlayerCreated(IsPlayerCreated), m_bCanCombine(a_CanCombine), m_Lifetime(cTickTime(a_LifetimeTicks)) { SetGravity(-16.0f); SetAirDrag(0.02f); SetMaxHealth(5); SetHealth(5); SetSpeed(a_Speed); } void cPickup::SpawnOn(cClientHandle & a_Client) { a_Client.SendSpawnEntity(*this); a_Client.SendEntityMetadata(*this); } void cPickup::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { Super::Tick(a_Dt, a_Chunk); if (!IsTicking()) { // The base class tick destroyed us return; } BroadcastMovementUpdate(); // Notify clients of position m_Timer += a_Dt; if (!m_bCollected) { int BlockY = POSY_TOINT; int BlockX = POSX_TOINT; int BlockZ = POSZ_TOINT; if ((BlockY >= 0) && (BlockY < cChunkDef::Height)) // Don't do anything except for falling when outside the world { // Position might have changed due to physics. So we have to make sure we have the correct chunk. GET_AND_VERIFY_CURRENT_CHUNK(CurrentChunk, BlockX, BlockZ); // Destroy the pickup if it is on fire: if (IsOnFire()) { m_bCollected = true; m_Timer = std::chrono::milliseconds(0); // We have to reset the timer. m_Timer += a_Dt; // In case we have to destroy the pickup in the same tick. if (m_Timer > std::chrono::milliseconds(500)) { Destroy(); return; } } // Try to combine the pickup with adjacent same-item pickups: if ((m_Item.m_ItemCount < m_Item.GetMaxStackSize()) && IsOnGround() && CanCombine()) // Don't combine if already full or not on ground { // By using a_Chunk's ForEachEntity() instead of cWorld's, pickups don't combine across chunk boundaries. // That is a small price to pay for not having to traverse the entire world for each entity. // The speedup in the tick thread is quite considerable. cPickupCombiningCallback PickupCombiningCallback(GetPosition(), this); a_Chunk.ForEachEntity(PickupCombiningCallback); if (PickupCombiningCallback.FoundMatchingPickup()) { m_World->BroadcastEntityMetadata(*this); } } } } else { if (m_Timer > std::chrono::milliseconds(500)) // 0.5 second { Destroy(); return; } } if (m_Timer > m_Lifetime) { Destroy(); return; } } bool cPickup::DoTakeDamage(TakeDamageInfo & a_TDI) { if (a_TDI.DamageType == dtCactusContact) { Destroy(); return true; } return Super::DoTakeDamage(a_TDI); } bool cPickup::CollectedBy(cEntity & a_Dest) { if (m_bCollected) { // LOG("Pickup %d cannot be collected by \"%s\", because it has already been collected.", m_UniqueID, a_Dest->GetName().c_str()); return false; // It's already collected! } // This type of entity can't pickup items if (!a_Dest.IsPawn()) { return false; } // Two seconds if player created the pickup (vomiting), half a second if anything else if (m_Timer < (m_bIsPlayerCreated ? std::chrono::seconds(2) : std::chrono::milliseconds(500))) { // LOG("Pickup %d cannot be collected by \"%s\", because it is not old enough.", m_UniqueID, a_Dest->GetName().c_str()); return false; // Not old enough } // Checking for villagers if (!a_Dest.IsPlayer() && a_Dest.IsMob()) { auto & Mob = static_cast(a_Dest); if (Mob.GetMobType() == mtVillager) { // Villagers only pickup food if (!ItemCategory::IsVillagerFood(m_Item.m_ItemType)) { return false; } auto & Villager = static_cast(Mob); char NumAdded = Villager.GetInventory().AddItem(m_Item); if (NumAdded > 0) { m_Item.m_ItemCount -= NumAdded; m_World->BroadcastCollectEntity(*this, a_Dest, static_cast(NumAdded)); // Also send the "pop" sound effect with a somewhat random pitch (fast-random using EntityID ;) m_World->BroadcastSoundEffect("entity.item.pickup", GetPosition(), 0.3f, (1.2f + (static_cast((GetUniqueID() * 23) % 32)) / 64)); if (m_Item.m_ItemCount <= 0) { // All of the pickup has been collected, schedule the pickup for destroying m_bCollected = true; } m_Timer = std::chrono::milliseconds(0); return true; } // Pickup cannot be collected because the entity has not enough space return false; } } else if (a_Dest.IsPlayer()) { auto & Player = static_cast(a_Dest); // If the player is a spectator, he cannot collect anything if (Player.IsGameModeSpectator()) { return false; } if (cRoot::Get()->GetPluginManager()->CallHookCollectingPickup(Player, *this)) { // LOG("Pickup %d cannot be collected by \"%s\", because a plugin has said no.", m_UniqueID, a_Dest->GetName().c_str()); return false; } char NumAdded = Player.GetInventory().AddItem(m_Item); if (NumAdded > 0) { // Check achievements switch (m_Item.m_ItemType) { case E_BLOCK_LOG: Player.AwardAchievement(CustomStatistic::AchMineWood); break; case E_ITEM_LEATHER: Player.AwardAchievement(CustomStatistic::AchKillCow); break; case E_ITEM_DIAMOND: Player.AwardAchievement(CustomStatistic::AchDiamonds); break; case E_ITEM_BLAZE_ROD: Player.AwardAchievement(CustomStatistic::AchBlazeRod); break; default: break; } m_Item.m_ItemCount -= NumAdded; m_World->BroadcastCollectEntity(*this, a_Dest, static_cast(NumAdded)); // Also send the "pop" sound effect with a somewhat random pitch (fast-random using EntityID ;) m_World->BroadcastSoundEffect("entity.item.pickup", GetPosition(), 0.3f, (1.2f + (static_cast((GetUniqueID() * 23) % 32)) / 64)); if (m_Item.m_ItemCount <= 0) { // All of the pickup has been collected, schedule the pickup for destroying m_bCollected = true; } m_Timer = std::chrono::milliseconds(0); return true; } } // LOG("Pickup %d cannot be collected by \"%s\", because there's no space in the inventory.", a_Dest->GetName().c_str(), m_UniqueID); return false; } ================================================ FILE: src/Entities/Pickup.h ================================================ #pragma once #include "Entity.h" #include "../Item.h" class cPlayer; // tolua_begin class cPickup : public cEntity { // tolua_end using Super = cEntity; public: // tolua_export CLASS_PROTODEF(cPickup) cPickup(Vector3d a_Pos, const cItem & a_Item, bool IsPlayerCreated, Vector3f a_Speed = Vector3f(), int a_LifetimeTicks = 6000, bool a_CanCombine = true); cItem & GetItem(void) {return m_Item; } // tolua_export const cItem & GetItem(void) const {return m_Item; } virtual void SpawnOn(cClientHandle & a_ClientHandle) override; bool CollectedBy(cEntity & a_Dest); // tolua_export virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; virtual bool DoTakeDamage(TakeDamageInfo & a_TDI) override; virtual bool DoesPreventBlockPlacement(void) const override { return false; } /** Returns whether this pickup is allowed to combine with other similar pickups */ bool CanCombine(void) const { return m_bCanCombine; } // tolua_export /** Sets whether this pickup is allowed to combine with other similar pickups */ void SetCanCombine(bool a_CanCombine) { m_bCanCombine = a_CanCombine; } // tolua_export /** Returns the number of ticks that this entity has existed */ int GetAge(void) const { return std::chrono::duration_cast(m_Timer).count(); } // tolua_export /** Set the number of ticks that this entity has existed */ void SetAge(int a_Age) { m_Timer = cTickTime(a_Age); } // tolua_export /** Returns the number of ticks that this pickup should live for */ int GetLifetime(void) const { return std::chrono::duration_cast(m_Lifetime).count(); } // tolua_export /** Set the number of ticks that this pickup should live for */ void SetLifetime(int a_Lifetime) { m_Lifetime = cTickTime(a_Lifetime); } // tolua_export /** Returns true if the pickup has already been collected */ bool IsCollected(void) const { return m_bCollected; } // tolua_export /** Returns true if created by player (i.e. vomiting), used for determining picking-up delay time */ bool IsPlayerCreated(void) const { return m_bIsPlayerCreated; } // tolua_export private: /** The number of ticks that the entity has existed / timer between collect and destroy; in msec */ std::chrono::milliseconds m_Timer; cItem m_Item; bool m_bCollected; bool m_bIsPlayerCreated; bool m_bCanCombine; std::chrono::milliseconds m_Lifetime; }; // tolua_export ================================================ FILE: src/Entities/Player.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "Player.h" #include "../Mobs/Wolf.h" #include "../Mobs/Horse.h" #include "../BoundingBox.h" #include "../ChatColor.h" #include "../Server.h" #include "../UI/InventoryWindow.h" #include "../UI/WindowOwner.h" #include "../Bindings/PluginManager.h" #include "../BlockEntities/BlockEntity.h" #include "../BlockEntities/EnderChestEntity.h" #include "../Root.h" #include "../Chunk.h" #include "../Items/ItemHandler.h" #include "../FastRandom.h" #include "../ClientHandle.h" #include "../WorldStorage/StatisticsSerializer.h" #include "../CompositeChat.h" #include "../Blocks/BlockHandler.h" #include "../Blocks/BlockSlab.h" #include "../Blocks/ChunkInterface.h" #include "../IniFile.h" #include "../JsonUtils.h" #include "json/json.h" #include "../CraftingRecipes.h" namespace { /** Returns the folder for the player data based on the UUID given. This can be used both for online and offline UUIDs. */ AString GetUUIDFolderName(const cUUID & a_Uuid) { AString UUID = a_Uuid.ToShortString(); AString res("players/"); res.append(UUID, 0, 2); res.push_back('/'); return res; } } // namespace (anonymous) const int cPlayer::MAX_HEALTH = 20; const int cPlayer::MAX_FOOD_LEVEL = 20; // Number of ticks it takes to eat an item. #define EATING_TICKS 30_tick // 6000 ticks or 5 minutes #define PLAYER_INVENTORY_SAVE_INTERVAL 6000 // Food saturation for newly-joined or just-respawned players. #define RESPAWN_FOOD_SATURATION 5 #define XP_TO_LEVEL15 255 #define XP_PER_LEVEL_TO15 17 #define XP_TO_LEVEL30 825 cPlayer::BodyStanceCrouching::BodyStanceCrouching(cPlayer & a_Player) { a_Player.SetSize(0.6f, 1.65f); } cPlayer::BodyStanceSleeping::BodyStanceSleeping(cPlayer & a_Player) { a_Player.SetSize(0.2f, 0.2f); } cPlayer::BodyStanceStanding::BodyStanceStanding(cPlayer & a_Player) { a_Player.SetSize(0.6f, 1.8f); } cPlayer::BodyStanceGliding::BodyStanceGliding(cPlayer & a_Player) : TicksElytraFlying(0) { a_Player.SetSize(0.6f, 0.6f); } cPlayer::cPlayer(const std::shared_ptr & a_Client) : Super(etPlayer, 0.6f, 1.8f), m_BodyStance(BodyStanceStanding(*this)), m_Inventory(*this), m_EnderChestContents(9, 3), m_DefaultWorldPath(cRoot::Get()->GetDefaultWorld()->GetDataPath()), m_ClientHandle(a_Client), m_NormalMaxSpeed(1.0), m_SprintingMaxSpeed(1.3), m_FlyingMaxSpeed(1.0), m_IsChargingBow(false), m_IsFishing(false), m_IsFrozen(false), m_IsLeftHanded(false), m_IsTeleporting(false), m_EatingFinishTick(-1), m_BowCharge(0), m_FloaterID(cEntity::INVALID_ID), m_Team(nullptr), m_Spectating(nullptr), m_TicksUntilNextSave(PLAYER_INVENTORY_SAVE_INTERVAL), m_SkinParts(0) { ASSERT(GetName().length() <= 16); // Otherwise this player could crash many clients... m_InventoryWindow = new cInventoryWindow(*this); m_CurrentWindow = m_InventoryWindow; m_InventoryWindow->OpenedByPlayer(*this); LoadFromDisk(); SetMaxHealth(MAX_HEALTH); UpdateCapabilities(); // Only required for plugins listening to HOOK_SPAWNING_ENTITY to not read uninitialised variables. } cPlayer::~cPlayer(void) { LOGD("Deleting cPlayer \"%s\" at %p, ID %d", GetName().c_str(), static_cast(this), GetUniqueID()); // "Times ragequit": m_Stats.Custom[CustomStatistic::LeaveGame]++; SaveToDisk(); delete m_InventoryWindow; LOGD("Player %p deleted", static_cast(this)); } void cPlayer::OnLoseSpectated() { m_ClientHandle->SendCameraSetTo(*this); m_ClientHandle->SendPlayerMoveLook(); m_Spectating = nullptr; } int cPlayer::CalcLevelFromXp(int a_XpTotal) { // level 0 to 15 if (a_XpTotal <= XP_TO_LEVEL15) { return a_XpTotal / XP_PER_LEVEL_TO15; } // level 30+ if (a_XpTotal > XP_TO_LEVEL30) { return static_cast((151.5 + sqrt( 22952.25 - (14 * (2220 - a_XpTotal)))) / 7); } // level 16 to 30 return static_cast((29.5 + sqrt( 870.25 - (6 * ( 360 - a_XpTotal)))) / 3); } const std::set & cPlayer::GetKnownRecipes() const { return m_KnownRecipes; } int cPlayer::XpForLevel(int a_Level) { // level 0 to 15 if (a_Level <= 15) { return a_Level * XP_PER_LEVEL_TO15; } // level 30+ if (a_Level >= 31) { return static_cast((3.5 * a_Level * a_Level) - (151.5 * a_Level) + 2220); } // level 16 to 30 return static_cast((1.5 * a_Level * a_Level) - (29.5 * a_Level) + 360); } int cPlayer::GetXpLevel() const { return CalcLevelFromXp(m_CurrentXp); } float cPlayer::GetXpPercentage() const { int currentLevel = CalcLevelFromXp(m_CurrentXp); int currentLevel_XpBase = XpForLevel(currentLevel); return static_cast(m_CurrentXp - currentLevel_XpBase) / static_cast(XpForLevel(1 + currentLevel) - currentLevel_XpBase); } bool cPlayer::SetCurrentExperience(int a_CurrentXp) { if (!(a_CurrentXp >= 0) || (a_CurrentXp > (std::numeric_limits::max() - m_LifetimeTotalXp))) { LOGWARNING("Tried to update experiece with an invalid Xp value: %d", a_CurrentXp); return false; // oops, they gave us a dodgey number } m_CurrentXp = a_CurrentXp; // Update experience: m_ClientHandle->SendExperience(); return true; } int cPlayer::DeltaExperience(int a_Xp_delta) { if (a_Xp_delta > (std::numeric_limits().max() - m_CurrentXp)) { // Value was bad, abort and report LOGWARNING("Attempt was made to increment Xp by %d, which overflowed the int datatype. Ignoring.", a_Xp_delta); return -1; // Should we instead just return the current Xp? } m_CurrentXp += a_Xp_delta; // Make sure they didn't subtract too much m_CurrentXp = std::max(m_CurrentXp, 0); // Update total for score calculation if (a_Xp_delta > 0) { m_LifetimeTotalXp += a_Xp_delta; } LOGD("Player \"%s\" gained / lost %d experience, total is now: %d", GetName().c_str(), a_Xp_delta, m_CurrentXp); // Set experience to be updated: m_ClientHandle->SendExperience(); return m_CurrentXp; } void cPlayer::StartChargingBow(void) { LOGD("Player \"%s\" started charging their bow", GetName().c_str()); m_IsChargingBow = true; m_BowCharge = 0; m_World->BroadcastEntityMetadata(*this, m_ClientHandle.get()); } int cPlayer::FinishChargingBow(void) { LOGD("Player \"%s\" finished charging their bow at a charge of %d", GetName().c_str(), m_BowCharge); int res = m_BowCharge; m_IsChargingBow = false; m_BowCharge = 0; m_World->BroadcastEntityMetadata(*this, m_ClientHandle.get()); return res; } void cPlayer::CancelChargingBow(void) { LOGD("Player \"%s\" cancelled charging their bow at a charge of %d", GetName().c_str(), m_BowCharge); m_IsChargingBow = false; m_BowCharge = 0; m_World->BroadcastEntityMetadata(*this, m_ClientHandle.get()); } void cPlayer::SetTouchGround(bool a_bTouchGround) { if (IsGameModeSpectator()) // You can fly through the ground in Spectator { return; } UNUSED(a_bTouchGround); /* Unfortunately whatever the reason, there are still desyncs in on-ground status between the client and server. For example: 1. Walking off a ledge (whatever height) 2. Initial login Thus, it is too risky to compare their value against ours and kick them for hacking */ } void cPlayer::Heal(int a_Health) { Super::Heal(a_Health); m_ClientHandle->SendHealth(); } void cPlayer::SetFoodLevel(int a_FoodLevel) { int FoodLevel = Clamp(a_FoodLevel, 0, MAX_FOOD_LEVEL); if (cRoot::Get()->GetPluginManager()->CallHookPlayerFoodLevelChange(*this, FoodLevel)) { return; } m_FoodLevel = FoodLevel; m_ClientHandle->SendHealth(); } void cPlayer::SetFoodSaturationLevel(double a_FoodSaturationLevel) { m_FoodSaturationLevel = Clamp(a_FoodSaturationLevel, 0.0, static_cast(m_FoodLevel)); } void cPlayer::SetFoodTickTimer(int a_FoodTickTimer) { m_FoodTickTimer = a_FoodTickTimer; } void cPlayer::SetFoodExhaustionLevel(double a_FoodExhaustionLevel) { m_FoodExhaustionLevel = Clamp(a_FoodExhaustionLevel, 0.0, 40.0); } bool cPlayer::Feed(int a_Food, double a_Saturation) { if (IsSatiated()) { return false; } SetFoodSaturationLevel(m_FoodSaturationLevel + a_Saturation); SetFoodLevel(m_FoodLevel + a_Food); return true; } void cPlayer::AddFoodExhaustion(double a_Exhaustion) { if (!(IsGameModeCreative() || IsGameModeSpectator())) { m_FoodExhaustionLevel = std::min(m_FoodExhaustionLevel + a_Exhaustion, 40.0); } } bool cPlayer::IsInBed(void) const { return std::holds_alternative(m_BodyStance); } bool cPlayer::IsLeftHanded() const { return m_IsLeftHanded; } bool cPlayer::IsStanding() const { return std::holds_alternative(m_BodyStance); } void cPlayer::TossItems(const cItems & a_Items) { if (IsGameModeSpectator()) // Players can't toss items in spectator { return; } m_Stats.Custom[CustomStatistic::Drop] += static_cast(a_Items.Size()); const auto Speed = (GetLookVector() + Vector3d(0, 0.2, 0)) * 6; // A dash of height and a dollop of speed const auto Position = GetEyePosition() - Vector3d(0, 0.2, 0); // Correct for eye-height weirdness m_World->SpawnItemPickups(a_Items, Position, Speed, true); // 'true' because created by player } void cPlayer::SetIsInBed(const bool a_GoToBed) { if (a_GoToBed && IsStanding()) { m_BodyStance = BodyStanceSleeping(*this); m_World->BroadcastEntityAnimation(*this, EntityAnimation::PlayerEntersBed); } else if (!a_GoToBed && IsInBed()) { m_BodyStance = BodyStanceStanding(*this); m_World->BroadcastEntityAnimation(*this, EntityAnimation::PlayerLeavesBed); } } void cPlayer::StartEating(void) { // Set the timer: m_EatingFinishTick = m_World->GetWorldAge() + EATING_TICKS; // Send the packet: m_World->BroadcastEntityMetadata(*this); } void cPlayer::FinishEating(void) { // Reset the timer: m_EatingFinishTick = -1_tick; // Send the packets: m_ClientHandle->SendEntityAnimation(*this, EntityAnimation::PlayerFinishesEating); m_World->BroadcastEntityMetadata(*this); // consume the item: cItem Item(GetEquippedItem()); Item.m_ItemCount = 1; auto & ItemHandler = Item.GetHandler(); if (!ItemHandler.EatItem(this, &Item)) { return; } ItemHandler.OnFoodEaten(m_World, this, &Item); } void cPlayer::AbortEating(void) { m_EatingFinishTick = -1_tick; m_World->BroadcastEntityMetadata(*this); } void cPlayer::ClearInventoryPaintSlots(void) { // Clear the list of slots that are being inventory-painted. Used by cWindow only m_InventoryPaintSlots.clear(); } void cPlayer::AddInventoryPaintSlot(int a_SlotNum) { // Add a slot to the list for inventory painting. Used by cWindow only m_InventoryPaintSlots.push_back(a_SlotNum); } const cSlotNums & cPlayer::GetInventoryPaintSlots(void) const { // Return the list of slots currently stored for inventory painting. Used by cWindow only return m_InventoryPaintSlots; } double cPlayer::GetMaxSpeed(void) const { if (IsFlying()) { return m_FlyingMaxSpeed; } else if (IsSprinting()) { return m_SprintingMaxSpeed; } else { return m_NormalMaxSpeed; } } void cPlayer::SetNormalMaxSpeed(double a_Speed) { m_NormalMaxSpeed = a_Speed; if (!m_IsFrozen) { // If we are frozen, we do not send this yet. We send when unfreeze() is called m_World->BroadcastEntityProperties(*this); } } void cPlayer::SetSprintingMaxSpeed(double a_Speed) { m_SprintingMaxSpeed = a_Speed; if (!m_IsFrozen) { // If we are frozen, we do not send this yet. We send when unfreeze() is called m_World->BroadcastEntityProperties(*this); } } void cPlayer::SetFlyingMaxSpeed(double a_Speed) { m_FlyingMaxSpeed = a_Speed; if (!m_IsFrozen) { // If we are frozen, we do not send this yet. We send when unfreeze() is called m_ClientHandle->SendPlayerAbilities(); } } void cPlayer::SetCrouch(const bool a_ShouldCrouch) { if (a_ShouldCrouch && IsStanding()) { m_BodyStance = BodyStanceCrouching(*this); // Handle spectator mode detach: if (IsGameModeSpectator()) { SpectateEntity(nullptr); } cRoot::Get()->GetPluginManager()->CallHookPlayerCrouched(*this); } else if (!a_ShouldCrouch && IsCrouched()) { m_BodyStance = BodyStanceStanding(*this); } m_World->BroadcastEntityMetadata(*this); } void cPlayer::SetElytraFlight(const bool a_ShouldElytraFly) { if (a_ShouldElytraFly && IsStanding() && !IsOnGround() && !IsInWater() && !IsRiding() && (GetEquippedChestplate().m_ItemType == E_ITEM_ELYTRA)) { m_BodyStance = BodyStanceGliding(*this); } else if (!a_ShouldElytraFly && IsElytraFlying()) { m_BodyStance = BodyStanceStanding(*this); } m_World->BroadcastEntityMetadata(*this); } void cPlayer::SetFlying(const bool a_ShouldFly) { if (a_ShouldFly == m_IsFlying) { return; } m_IsFlying = a_ShouldFly; if (!m_IsFrozen) { // If we are frozen, we do not send this yet. We send when unfreeze() is called m_ClientHandle->SendPlayerAbilities(); } } void cPlayer::SetLeftHanded(const bool a_IsLeftHanded) { m_IsLeftHanded = a_IsLeftHanded; m_World->BroadcastEntityMetadata(*this); } void cPlayer::SetSprint(const bool a_ShouldSprint) { if (a_ShouldSprint && IsStanding()) { m_BodyStance = BodyStanceSprinting(); } else if (!a_ShouldSprint && IsSprinting()) { m_BodyStance = BodyStanceStanding(*this); } m_World->BroadcastEntityMetadata(*this); m_World->BroadcastEntityProperties(*this); } void cPlayer::SetCanFly(bool a_CanFly) { if (a_CanFly == m_IsFlightCapable) { return; } m_IsFlightCapable = a_CanFly; m_ClientHandle->SendPlayerAbilities(); } void cPlayer::SetCustomName(const AString & a_CustomName) { if (m_CustomName == a_CustomName) { return; } m_World->BroadcastPlayerListRemovePlayer(*this); m_CustomName = a_CustomName; if (m_CustomName.length() > 16) { m_CustomName = m_CustomName.substr(0, 16); } m_World->BroadcastPlayerListAddPlayer(*this); m_World->BroadcastSpawnEntity(*this, m_ClientHandle.get()); } void cPlayer::SetBedPos(const Vector3i a_Position) { SetBedPos(a_Position, *m_World); } void cPlayer::SetBedPos(const Vector3i a_Position, const cWorld & a_World) { m_RespawnPosition = a_Position; m_IsRespawnPointForced = false; m_SpawnWorldName = a_World.GetName(); } void cPlayer::SetRespawnPosition(const Vector3i a_Position, const cWorld & a_World) { m_RespawnPosition = a_Position; m_IsRespawnPointForced = true; m_SpawnWorldName = a_World.GetName(); } cWorld * cPlayer::GetRespawnWorld() { if (const auto World = cRoot::Get()->GetWorld(m_SpawnWorldName); World != nullptr) { return World; } return cRoot::Get()->GetDefaultWorld(); } void cPlayer::NotifyNearbyWolves(cPawn * a_Opponent, bool a_IsPlayerInvolved) { ASSERT(a_Opponent != nullptr); m_World->ForEachEntityInBox(cBoundingBox(GetPosition(), 16), [&] (cEntity & a_Entity) { if (a_Entity.IsMob()) { auto & Mob = static_cast(a_Entity); if (Mob.GetMobType() == mtWolf) { auto & Wolf = static_cast(Mob); Wolf.ReceiveNearbyFightInfo(GetUUID(), a_Opponent, a_IsPlayerInvolved); } } return false; } ); } void cPlayer::KilledBy(TakeDamageInfo & a_TDI) { Super::KilledBy(a_TDI); if (m_Health > 0) { return; // not dead yet =] } m_IsVisible = false; // So new clients don't see the player // Detach player from object / entity. If the player dies, the server still says // that the player is attached to the entity / object Detach(); // Puke out all the items cItems Pickups; m_Inventory.CopyToItems(Pickups); m_Inventory.Clear(); if (GetName() == "Notch") { Pickups.Add(cItem(E_ITEM_RED_APPLE)); } m_Stats.Custom[CustomStatistic::Drop] += static_cast(Pickups.Size()); m_World->SpawnItemPickups(Pickups, GetPosX(), GetPosY(), GetPosZ(), 10); SaveToDisk(); // Save it, yeah the world is a tough place ! BroadcastDeathMessage(a_TDI); m_Stats.Custom[CustomStatistic::Deaths]++; m_Stats.Custom[CustomStatistic::TimeSinceDeath] = 0; m_World->GetScoreBoard().AddPlayerScore(GetName(), cObjective::otDeathCount, 1); } void cPlayer::Killed(const cEntity & a_Victim, eDamageType a_DamageType) { cScoreboard & ScoreBoard = m_World->GetScoreBoard(); if (a_Victim.IsPlayer()) { m_Stats.Custom[CustomStatistic::PlayerKills]++; ScoreBoard.AddPlayerScore(GetName(), cObjective::otPlayerKillCount, 1); } else if (a_Victim.IsMob()) { const auto & Monster = static_cast(a_Victim); if (Monster.GetMobFamily() == cMonster::mfHostile) { AwardAchievement(CustomStatistic::AchKillEnemy); } if ((Monster.GetMobType() == eMonsterType::mtSkeleton) && (a_DamageType == eDamageType::dtRangedAttack)) { const double DistX = GetPosX() - Monster.GetPosX(); const double DistZ = GetPosZ() - Monster.GetPosZ(); if ((DistX * DistX + DistZ * DistZ) >= 2500.0) { AwardAchievement(CustomStatistic::AchSnipeSkeleton); } } m_Stats.Custom[CustomStatistic::MobKills]++; } ScoreBoard.AddPlayerScore(GetName(), cObjective::otTotalKillCount, 1); } void cPlayer::Respawn(void) { ASSERT(m_World != nullptr); m_Health = GetMaxHealth(); SetInvulnerableTicks(20); // Reset food level: m_FoodLevel = MAX_FOOD_LEVEL; m_FoodSaturationLevel = RESPAWN_FOOD_SATURATION; m_FoodExhaustionLevel = 0; // Reset Experience m_CurrentXp = 0; m_LifetimeTotalXp = 0; // ToDo: send score to client? How? // Extinguish the fire: StopBurning(); // Disable flying: SetFlying(false); if (!m_IsRespawnPointForced) { // Check if the bed is still present: if (GetRespawnWorld()->GetBlock(m_RespawnPosition) != E_BLOCK_BED) { const auto & DefaultWorld = *cRoot::Get()->GetDefaultWorld(); // If not, reset spawn to default and inform: SetRespawnPosition(Vector3i(DefaultWorld.GetSpawnX(), DefaultWorld.GetSpawnY(), DefaultWorld.GetSpawnZ()), DefaultWorld); SendAboveActionBarMessage("Your home bed was missing or obstructed"); } // TODO: bed obstruction check here } if (const auto RespawnWorld = GetRespawnWorld(); m_World != RespawnWorld) { MoveToWorld(*RespawnWorld, m_RespawnPosition, false, false); } else { m_ClientHandle->SendRespawn(m_World->GetDimension(), true); TeleportToCoords(m_RespawnPosition.x, m_RespawnPosition.y, m_RespawnPosition.z); } // The Notchian client enters a weird glitched state when trying to "resurrect" dead players // To prevent that, destroy the existing client-side entity, and create a new one with the same ID // This does not make any difference to more modern clients m_World->BroadcastDestroyEntity(*this, &*m_ClientHandle); m_World->BroadcastSpawnEntity(*this, &*m_ClientHandle); SetVisible(true); } double cPlayer::GetEyeHeight(void) const { return GetEyePosition().y - GetPosY(); } Vector3d cPlayer::GetEyePosition(void) const { if (IsCrouched()) { return GetPosition().addedY(1.54); } if (IsElytraFlying()) { return GetPosition().addedY(0.4); } if (IsInBed()) { return GetPosition().addedY(0.2); } return GetPosition().addedY(1.6); } bool cPlayer::IsGameModeCreative(void) const { return (GetEffectiveGameMode() == gmCreative); } bool cPlayer::IsGameModeSurvival(void) const { return (GetEffectiveGameMode() == gmSurvival); } bool cPlayer::IsGameModeAdventure(void) const { return (GetEffectiveGameMode() == gmAdventure); } bool cPlayer::IsGameModeSpectator(void) const { return (GetEffectiveGameMode() == gmSpectator); } bool cPlayer::CanMobsTarget(void) const { return (IsGameModeSurvival() || IsGameModeAdventure()) && (m_Health > 0); } AString cPlayer::GetIP(void) const { return m_ClientHandle->GetIPString(); } void cPlayer::SetTeam(cTeam * a_Team) { if (m_Team == a_Team) { return; } if (m_Team) { m_Team->RemovePlayer(GetName()); } m_Team = a_Team; if (m_Team) { m_Team->AddPlayer(GetName()); } } cTeam * cPlayer::UpdateTeam(void) { if (m_World == nullptr) { SetTeam(nullptr); } else { cScoreboard & Scoreboard = m_World->GetScoreBoard(); SetTeam(Scoreboard.QueryPlayerTeam(GetName())); } return m_Team; } void cPlayer::OpenWindow(cWindow & a_Window) { if (cRoot::Get()->GetPluginManager()->CallHookPlayerOpeningWindow(*this, a_Window)) { return; } if (&a_Window != m_CurrentWindow) { CloseWindow(false); } a_Window.OpenedByPlayer(*this); m_CurrentWindow = &a_Window; a_Window.SendWholeWindow(*GetClientHandle()); } void cPlayer::CloseWindow(bool a_CanRefuse) { if (m_CurrentWindow == nullptr) { m_CurrentWindow = m_InventoryWindow; return; } if (m_CurrentWindow->ClosedByPlayer(*this, a_CanRefuse) || !a_CanRefuse) { // Close accepted, go back to inventory window (the default): m_CurrentWindow = m_InventoryWindow; } else { // Re-open the window m_CurrentWindow->OpenedByPlayer(*this); m_CurrentWindow->SendWholeWindow(*GetClientHandle()); } } void cPlayer::CloseWindowIfID(char a_WindowID, bool a_CanRefuse) { if ((m_CurrentWindow == nullptr) || (m_CurrentWindow->GetWindowID() != a_WindowID)) { return; } CloseWindow(); } void cPlayer::SendMessage(const AString & a_Message) { m_ClientHandle->SendChat(a_Message, mtCustom); } void cPlayer::SendMessageInfo(const AString & a_Message) { m_ClientHandle->SendChat(a_Message, mtInformation); } void cPlayer::SendMessageFailure(const AString & a_Message) { m_ClientHandle->SendChat(a_Message, mtFailure); } void cPlayer::SendMessageSuccess(const AString & a_Message) { m_ClientHandle->SendChat(a_Message, mtSuccess); } void cPlayer::SendMessageWarning(const AString & a_Message) { m_ClientHandle->SendChat(a_Message, mtWarning); } void cPlayer::SendMessageFatal(const AString & a_Message) { m_ClientHandle->SendChat(a_Message, mtFailure); } void cPlayer::SendMessagePrivateMsg(const AString & a_Message, const AString & a_Sender) { m_ClientHandle->SendChat(a_Message, mtPrivateMessage, a_Sender); } void cPlayer::SendMessage(const cCompositeChat & a_Message) { m_ClientHandle->SendChat(a_Message); } void cPlayer::SendMessageRaw(const AString & a_MessageRaw, eChatType a_Type) { m_ClientHandle->SendChatRaw(a_MessageRaw, a_Type); } void cPlayer::SendSystemMessage(const AString & a_Message) { m_ClientHandle->SendChatSystem(a_Message, mtCustom); } void cPlayer::SendAboveActionBarMessage(const AString & a_Message) { m_ClientHandle->SendChatAboveActionBar(a_Message, mtCustom); } void cPlayer::SendSystemMessage(const cCompositeChat & a_Message) { m_ClientHandle->SendChatSystem(a_Message); } void cPlayer::SendAboveActionBarMessage(const cCompositeChat & a_Message) { m_ClientHandle->SendChatAboveActionBar(a_Message); } const AString & cPlayer::GetName(void) const { return m_ClientHandle->GetUsername(); } void cPlayer::SetGameMode(eGameMode a_GameMode) { if ((a_GameMode < gmMin) || (a_GameMode >= gmMax)) { LOGWARNING("%s: Setting invalid gamemode: %d", GetName().c_str(), a_GameMode); return; } if (m_GameMode == a_GameMode) { // New gamemode unchanged, we're done: return; } m_GameMode = a_GameMode; UpdateCapabilities(); if (IsGameModeSpectator()) { // Spectators cannot ride entities: Detach(); } else { // Non-spectators may not spectate: SpectateEntity(nullptr); } m_ClientHandle->SendGameMode(a_GameMode); m_ClientHandle->SendInventorySlot(-1, -1, m_DraggingItem); m_World->BroadcastPlayerListUpdateGameMode(*this); m_World->BroadcastEntityMetadata(*this); } void cPlayer::UpdateCapabilities() { if (IsGameModeCreative()) { m_IsFlightCapable = true; m_IsVisible = true; } else if (IsGameModeSpectator()) { m_DraggingItem.Empty(); // Clear the current dragging item of spectators. m_IsFlightCapable = true; m_IsFlying = true; // Spectators are always in flight mode. m_IsVisible = false; // Spectators are invisible. } else { m_IsFlightCapable = false; m_IsFlying = false; m_IsVisible = true; } } void cPlayer::AwardAchievement(const CustomStatistic a_Ach) { // Check if the prerequisites are met: if (!m_Stats.SatisfiesPrerequisite(a_Ach)) { return; } // Increment the statistic and check if we already have it: if (m_Stats.Custom[a_Ach]++ != 1) { return; } if (m_World->ShouldBroadcastAchievementMessages()) { cCompositeChat Msg; Msg.SetMessageType(mtSuccess); // TODO: cCompositeChat should not use protocol-specific strings // Msg.AddShowAchievementPart(GetName(), nameNew); Msg.AddTextPart("Achievement get!"); m_World->BroadcastChat(Msg); } // Achievement Get! m_ClientHandle->SendStatistics(m_Stats); } void cPlayer::TeleportToCoords(double a_PosX, double a_PosY, double a_PosZ) { // ask plugins to allow teleport to the new position. if (!cRoot::Get()->GetPluginManager()->CallHookEntityTeleport(*this, m_LastPosition, Vector3d(a_PosX, a_PosY, a_PosZ))) { m_IsTeleporting = true; Detach(); SetPosition({a_PosX, a_PosY, a_PosZ}); FreezeInternal(GetPosition(), false); m_ClientHandle->SendPlayerMoveLook(); } } void cPlayer::Freeze(const Vector3d & a_Location) { FreezeInternal(a_Location, true); } bool cPlayer::IsFrozen() { return m_IsFrozen; } void cPlayer::Unfreeze() { if (IsElytraFlying()) { m_World->BroadcastEntityMetadata(*this); } m_ClientHandle->SendPlayerAbilities(); m_World->BroadcastEntityProperties(*this); m_IsFrozen = false; BroadcastMovementUpdate(m_ClientHandle.get()); GetClientHandle()->SendPlayerPosition(); } void cPlayer::SendRotation(double a_YawDegrees, double a_PitchDegrees) { SetYaw(a_YawDegrees); SetPitch(a_PitchDegrees); m_ClientHandle->SendPlayerMoveLook(); } void cPlayer::SpectateEntity(cEntity * a_Target) { if (a_Target == this) { // Canonicalise self-pointers: a_Target = nullptr; } if (m_Spectating == a_Target) { // Already spectating requested target: return; } if (a_Target == nullptr) { m_Spectating->OnLoseSpectator(*this); OnLoseSpectated(); return; } m_Spectating = a_Target; a_Target->OnAcquireSpectator(*this); m_ClientHandle->SendCameraSetTo(*a_Target); } Vector3d cPlayer::GetThrowStartPos(void) const { Vector3d res = GetEyePosition(); // Adjust the position to be just outside the player's bounding box: res.x += 0.16 * cos(GetPitch()); res.y += -0.1; res.z += 0.16 * sin(GetPitch()); return res; } Vector3d cPlayer::GetThrowSpeed(double a_SpeedCoeff) const { Vector3d res = GetLookVector(); res.Normalize(); // TODO: Add a slight random change (+-0.0075 in each direction) return res * a_SpeedCoeff; } eGameMode cPlayer::GetEffectiveGameMode(void) const { return (m_GameMode == gmNotSet) ? m_World->GetGameMode() : m_GameMode; } void cPlayer::ForceSetSpeed(const Vector3d & a_Speed) { SetSpeed(a_Speed); } void cPlayer::SetVisible(bool a_bVisible) { if (a_bVisible && !m_IsVisible) { m_IsVisible = true; } if (!a_bVisible && m_IsVisible) { m_IsVisible = false; } m_World->BroadcastEntityMetadata(*this); } MTRand cPlayer::GetEnchantmentRandomProvider() { return m_EnchantmentSeed; } void cPlayer::PermuteEnchantmentSeed() { // Get a new random integer and save that as the seed: m_EnchantmentSeed = GetRandomProvider().RandInt(); } bool cPlayer::HasPermission(const AString & a_Permission) const { if (a_Permission.empty()) { // Empty permission request is always granted return true; } AStringVector Split = StringSplit(a_Permission, "."); // Iterate over all restrictions; if any matches, then return failure: for (auto & Restriction: m_SplitRestrictions) { if (PermissionMatches(Split, Restriction)) { return false; } } // for Restriction - m_SplitRestrictions[] // Iterate over all granted permissions; if any matches, then return success: for (auto & Permission: m_SplitPermissions) { if (PermissionMatches(Split, Permission)) { return true; } } // for Permission - m_SplitPermissions[] // No granted permission matches return false; } bool cPlayer::PermissionMatches(const AStringVector & a_Permission, const AStringVector & a_Template) { // Check the sub-items if they are the same or there's a wildcard: size_t lenP = a_Permission.size(); size_t lenT = a_Template.size(); size_t minLen = std::min(lenP, lenT); for (size_t i = 0; i < minLen; i++) { if (a_Template[i] == "*") { // Has matched so far and now there's a wildcard in the template, so the permission matches: return true; } if (a_Permission[i] != a_Template[i]) { // Found a mismatch return false; } } // So far all the sub-items have matched // If the sub-item count is the same, then the permission matches return (lenP == lenT); } AString cPlayer::GetColor(void) const { if (m_MsgNameColorCode.empty() || (m_MsgNameColorCode == "-")) { // Color has not been assigned, return an empty string: return AString(); } // Return the color, including the delimiter: return cChatColor::Delimiter + m_MsgNameColorCode; } AString cPlayer::GetPrefix(void) const { return m_MsgPrefix; } AString cPlayer::GetSuffix(void) const { return m_MsgSuffix; } AString cPlayer::GetPlayerListName() const { const AString & Color = GetColor(); if (HasCustomName()) { return m_CustomName; } else if ((GetName().length() <= 14) && !Color.empty()) { return fmt::format(FMT_STRING("{}{}"), Color, GetName()); } else { return GetName(); } } void cPlayer::SetDraggingItem(const cItem & a_Item) { if (GetWindow() != nullptr) { m_DraggingItem = a_Item; GetClientHandle()->SendInventorySlot(-1, -1, m_DraggingItem); } } void cPlayer::TossEquippedItem(char a_Amount) { cItems Drops; cItem DroppedItem(GetInventory().GetEquippedItem()); if (!DroppedItem.IsEmpty()) { char NewAmount = a_Amount; if (NewAmount > GetInventory().GetEquippedItem().m_ItemCount) { NewAmount = GetInventory().GetEquippedItem().m_ItemCount; // Drop only what's there } GetInventory().GetHotbarGrid().ChangeSlotCount(GetInventory().GetEquippedSlotNum() /* Returns hotbar subslot, which HotbarGrid takes */, -a_Amount); DroppedItem.m_ItemCount = NewAmount; Drops.push_back(DroppedItem); } TossItems(Drops); } void cPlayer::ReplaceOneEquippedItemTossRest(const cItem & a_Item) { auto PlacedCount = GetInventory().ReplaceOneEquippedItem(a_Item); char ItemCountToToss = a_Item.m_ItemCount - static_cast(PlacedCount); if (ItemCountToToss == 0) { return; } cItem Pickup = a_Item; Pickup.m_ItemCount = ItemCountToToss; TossPickup(Pickup); } void cPlayer::TossHeldItem(char a_Amount) { cItems Drops; cItem & Item = GetDraggingItem(); if (!Item.IsEmpty()) { char OriginalItemAmount = Item.m_ItemCount; Item.m_ItemCount = std::min(OriginalItemAmount, a_Amount); Drops.push_back(Item); if (OriginalItemAmount > a_Amount) { Item.m_ItemCount = OriginalItemAmount - a_Amount; } else { Item.Empty(); } } TossItems(Drops); } void cPlayer::TossPickup(const cItem & a_Item) { cItems Drops; Drops.push_back(a_Item); TossItems(Drops); } void cPlayer::LoadFromDisk() { RefreshRank(); Json::Value Root; const auto & UUID = GetUUID(); const auto & FileName = GetUUIDFileName(UUID); try { // Load the data from the save file and parse: InputFileStream(FileName) >> Root; // Load the player stats. // We use the default world name (like bukkit) because stats are shared between dimensions / worlds. StatisticsSerializer::Load(m_Stats, m_DefaultWorldPath, UUID.ToLongString()); } catch (const InputFileStream::failure &) { if (errno != ENOENT) { // Save file exists but unreadable: throw; } // This is a new player whom we haven't seen yet with no save file, let them have the defaults: LOG("Player \"%s\" (%s) save or statistics file not found, resetting to defaults", GetName().c_str(), UUID.ToShortString().c_str()); } m_CurrentWorldName = Root.get("world", cRoot::Get()->GetDefaultWorld()->GetName()).asString(); m_World = cRoot::Get()->GetWorld(m_CurrentWorldName); if (const auto & PlayerPosition = Root["position"]; PlayerPosition.size() == 3) { SetPosition(PlayerPosition[0].asDouble(), PlayerPosition[1].asDouble(), PlayerPosition[2].asDouble()); } else { SetPosition(Vector3d(0.5, 0.5, 0.5) + Vector3i(m_World->GetSpawnX(), m_World->GetSpawnY(), m_World->GetSpawnZ())); } if (const auto & PlayerRotation = Root["rotation"]; PlayerRotation.size() == 3) { SetYaw (PlayerRotation[0].asDouble()); SetPitch(PlayerRotation[1].asDouble()); SetRoll (PlayerRotation[2].asDouble()); } m_Health = Root.get("health", MAX_HEALTH).asFloat(); m_AirLevel = Root.get("air", MAX_AIR_LEVEL).asInt(); m_FoodLevel = Root.get("food", MAX_FOOD_LEVEL).asInt(); m_FoodSaturationLevel = Root.get("foodSaturation", RESPAWN_FOOD_SATURATION).asDouble(); m_FoodTickTimer = Root.get("foodTickTimer", 0).asInt(); m_FoodExhaustionLevel = Root.get("foodExhaustion", 0).asDouble(); m_LifetimeTotalXp = Root.get("xpTotal", 0).asInt(); m_CurrentXp = Root.get("xpCurrent", 0).asInt(); m_IsFlying = Root.get("isflying", 0).asBool(); m_EnchantmentSeed = Root.get("enchantmentSeed", GetRandomProvider().RandInt()).asUInt(); Json::Value & JSON_KnownItems = Root["knownItems"]; for (UInt32 i = 0; i < JSON_KnownItems.size(); i++) { cItem Item; Item.FromJson(JSON_KnownItems[i]); m_KnownItems.insert(Item); } const auto & RecipeNameMap = cRoot::Get()->GetCraftingRecipes()->GetRecipeNameMap(); Json::Value & JSON_KnownRecipes = Root["knownRecipes"]; for (UInt32 i = 0; i < JSON_KnownRecipes.size(); i++) { auto RecipeId = RecipeNameMap.find(JSON_KnownRecipes[i].asString()); if (RecipeId != RecipeNameMap.end()) { m_KnownRecipes.insert(RecipeId->second); } } m_GameMode = static_cast(Root.get("gamemode", eGameMode_NotSet).asInt()); m_Inventory.LoadFromJson(Root["inventory"]); m_Inventory.SetEquippedSlotNum(Root.get("equippedItemSlot", 0).asInt()); cEnderChestEntity::LoadFromJson(Root["enderchestinventory"], m_EnderChestContents); m_RespawnPosition.x = Root.get("SpawnX", m_World->GetSpawnX()).asInt(); m_RespawnPosition.y = Root.get("SpawnY", m_World->GetSpawnY()).asInt(); m_RespawnPosition.z = Root.get("SpawnZ", m_World->GetSpawnZ()).asInt(); m_IsRespawnPointForced = Root.get("SpawnForced", true).asBool(); m_SpawnWorldName = Root.get("SpawnWorld", m_World->GetName()).asString(); FLOGD("Player \"{0}\" with save file \"{1}\" is spawning at {2:.2f} in world \"{3}\"", GetName(), FileName, GetPosition(), m_World->GetName() ); } void cPlayer::OpenHorseInventory() { if ( (m_AttachedTo == nullptr) || !m_AttachedTo->IsMob() ) { return; } auto & Mob = static_cast(*m_AttachedTo); if (Mob.GetMobType() != mtHorse) { return; } auto & Horse = static_cast(Mob); // The client sends requests for untame horses as well but shouldn't actually open if (Horse.IsTame()) { Horse.PlayerOpenWindow(*this); } } void cPlayer::SaveToDisk() { const auto & UUID = GetUUID(); cFile::CreateFolderRecursive(GetUUIDFolderName(UUID)); // create the JSON data Json::Value JSON_PlayerPosition; JSON_PlayerPosition.append(Json::Value(GetPosX())); JSON_PlayerPosition.append(Json::Value(GetPosY())); JSON_PlayerPosition.append(Json::Value(GetPosZ())); Json::Value JSON_PlayerRotation; JSON_PlayerRotation.append(Json::Value(GetYaw())); JSON_PlayerRotation.append(Json::Value(GetPitch())); JSON_PlayerRotation.append(Json::Value(GetRoll())); Json::Value JSON_Inventory; m_Inventory.SaveToJson(JSON_Inventory); Json::Value JSON_EnderChestInventory; cEnderChestEntity::SaveToJson(JSON_EnderChestInventory, m_EnderChestContents); Json::Value JSON_KnownItems; for (const auto & KnownItem : m_KnownItems) { Json::Value JSON_Item; KnownItem.GetJson(JSON_Item); JSON_KnownItems.append(JSON_Item); } Json::Value JSON_KnownRecipes; for (auto KnownRecipe : m_KnownRecipes) { auto Recipe = cRoot::Get()->GetCraftingRecipes()->GetRecipeById(KnownRecipe); JSON_KnownRecipes.append(Recipe->m_RecipeName); } Json::Value root; root["position"] = JSON_PlayerPosition; root["rotation"] = JSON_PlayerRotation; root["inventory"] = JSON_Inventory; root["knownItems"] = JSON_KnownItems; root["knownRecipes"] = JSON_KnownRecipes; root["equippedItemSlot"] = m_Inventory.GetEquippedSlotNum(); root["enderchestinventory"] = JSON_EnderChestInventory; root["health"] = m_Health; root["xpTotal"] = m_LifetimeTotalXp; root["xpCurrent"] = m_CurrentXp; root["air"] = m_AirLevel; root["food"] = m_FoodLevel; root["foodSaturation"] = m_FoodSaturationLevel; root["foodTickTimer"] = m_FoodTickTimer; root["foodExhaustion"] = m_FoodExhaustionLevel; root["isflying"] = IsFlying(); root["lastknownname"] = GetName(); root["SpawnX"] = GetLastBedPos().x; root["SpawnY"] = GetLastBedPos().y; root["SpawnZ"] = GetLastBedPos().z; root["SpawnForced"] = m_IsRespawnPointForced; root["SpawnWorld"] = m_SpawnWorldName; root["enchantmentSeed"] = m_EnchantmentSeed; root["world"] = m_CurrentWorldName; root["gamemode"] = static_cast(m_GameMode); auto JsonData = JsonUtils::WriteStyledString(root); AString SourceFile = GetUUIDFileName(UUID); cFile f; if (!f.Open(SourceFile, cFile::fmWrite)) { LOGWARNING("Error writing player \"%s\" to file \"%s\": cannot open file. Player will lose their progress", GetName().c_str(), SourceFile.c_str() ); return; } if (f.Write(JsonData.c_str(), JsonData.size()) != static_cast(JsonData.size())) { LOGWARNING("Error writing player \"%s\" to file \"%s\": cannot save data. Player will lose their progress", GetName().c_str(), SourceFile.c_str() ); return; } try { // Save the player stats. // We use the default world name (like bukkit) because stats are shared between dimensions / worlds. // TODO: save together with player.dat, not in some other place. StatisticsSerializer::Save(m_Stats, m_DefaultWorldPath, GetUUID().ToLongString()); } catch (...) { LOGWARNING("Error writing player \"%s\" statistics to file", GetName().c_str()); } } void cPlayer::UseEquippedItem(short a_Damage) { // No durability loss in creative or spectator modes: if (IsGameModeCreative() || IsGameModeSpectator()) { return; } UseItem(cInventory::invHotbarOffset + m_Inventory.GetEquippedSlotNum(), a_Damage); } void cPlayer::UseEquippedItem(cItemHandler::eDurabilityLostAction a_Action) { // Get item being used: cItem Item = GetEquippedItem(); // Get base damage for action type: short Dmg = Item.GetHandler().GetDurabilityLossByAction(a_Action); UseEquippedItem(Dmg); } void cPlayer::UseItem(int a_SlotNumber, short a_Damage) { const cItem & Item = m_Inventory.GetSlot(a_SlotNumber); if (Item.IsEmpty()) { return; } // Ref: https://minecraft.wiki/w/Enchanting#Unbreaking unsigned int UnbreakingLevel = Item.m_Enchantments.GetLevel(cEnchantments::enchUnbreaking); double chance = ItemCategory::IsArmor(Item.m_ItemType) ? (0.6 + (0.4 / (UnbreakingLevel + 1))) : (1.0 / (UnbreakingLevel + 1)); // When durability is reduced by multiple points // Unbreaking is applied for each point of reduction. std::binomial_distribution Dist(a_Damage, chance); short ReducedDamage = Dist(GetRandomProvider().Engine()); if (m_Inventory.DamageItem(a_SlotNumber, ReducedDamage)) { // The item broke. Broadcast the correct animation: if (Item.m_ItemType == E_ITEM_SHIELD) { m_World->BroadcastEntityAnimation(*this, EntityAnimation::PawnShieldBreaks); } else if (a_SlotNumber == (cInventory::invHotbarOffset + m_Inventory.GetEquippedSlotNum())) { m_World->BroadcastEntityAnimation(*this, EntityAnimation::PawnMainHandEquipmentBreaks); } else { switch (a_SlotNumber) { case cInventory::invArmorOffset: return m_World->BroadcastEntityAnimation(*this, EntityAnimation::PawnHeadEquipmentBreaks); case cInventory::invArmorOffset + 1: return m_World->BroadcastEntityAnimation(*this, EntityAnimation::PawnChestEquipmentBreaks); case cInventory::invArmorOffset + 2: return m_World->BroadcastEntityAnimation(*this, EntityAnimation::PawnLegsEquipmentBreaks); case cInventory::invArmorOffset + 3: return m_World->BroadcastEntityAnimation(*this, EntityAnimation::PawnFeetEquipmentBreaks); case cInventory::invShieldOffset: return m_World->BroadcastEntityAnimation(*this, EntityAnimation::PawnOffHandEquipmentBreaks); } } } else if (Item.m_ItemType == E_ITEM_SHIELD) { // The item survived. Special case for shield blocking: m_World->BroadcastEntityAnimation(*this, EntityAnimation::PawnShieldBlocks); } } void cPlayer::HandleFood(void) { // Ref.: https://minecraft.wiki/w/Hunger if (IsGameModeCreative() || IsGameModeSpectator()) { // Hunger is disabled for Creative and Spectator return; } // Apply food exhaustion that has accumulated: if (m_FoodExhaustionLevel > 4.0) { m_FoodExhaustionLevel -= 4.0; if (m_FoodSaturationLevel > 0.0) { m_FoodSaturationLevel = std::max(m_FoodSaturationLevel - 1.0, 0.0); } else { SetFoodLevel(m_FoodLevel - 1); } } // Heal or damage, based on the food level, using the m_FoodTickTimer: if ((m_FoodLevel >= 18) || (m_FoodLevel <= 0)) { m_FoodTickTimer++; if (m_FoodTickTimer >= 80) { m_FoodTickTimer = 0; if ((m_FoodLevel >= 18) && (GetHealth() < GetMaxHealth())) { // Regenerate health from food, incur 3 pts of food exhaustion: Heal(1); AddFoodExhaustion(3.0); } else if ((m_FoodLevel <= 0) && (m_Health > 1)) { // Damage from starving TakeDamage(dtStarving, nullptr, 1, 1, 0); } } } else { m_FoodTickTimer = 0; } } void cPlayer::HandleFloater() { if (GetEquippedItem().m_ItemType == E_ITEM_FISHING_ROD) { return; } m_World->DoWithEntityByID(m_FloaterID, [](cEntity & a_Entity) { a_Entity.Destroy(); return true; } ); SetIsFishing(false); } bool cPlayer::IsClimbing(void) const { const auto Position = GetPosition().Floor(); if (!cChunkDef::IsValidHeight(Position)) { return false; } BLOCKTYPE Block = m_World->GetBlock(Position); switch (Block) { case E_BLOCK_LADDER: case E_BLOCK_VINES: { return true; } default: return false; } } void cPlayer::UpdateMovementStats(const Vector3d & a_DeltaPos, bool a_PreviousIsOnGround) { if (m_IsTeleporting) { m_IsTeleporting = false; return; } const auto Value = FloorC(a_DeltaPos.Length() * 100 + 0.5); if (m_AttachedTo == nullptr) { if (IsFlying()) { m_Stats.Custom[CustomStatistic::FlyOneCm] += Value; // May be flying and doing any of the following: } if (IsClimbing()) { if (a_DeltaPos.y > 0.0) // Going up { m_Stats.Custom[CustomStatistic::ClimbOneCm] += FloorC(a_DeltaPos.y * 100 + 0.5); } } else if (IsInWater()) { if (m_IsHeadInWater) { m_Stats.Custom[CustomStatistic::WalkUnderWaterOneCm] += Value; } else { m_Stats.Custom[CustomStatistic::WalkOnWaterOneCm] += Value; } AddFoodExhaustion(0.00015 * static_cast(Value)); } else if (IsOnGround()) { if (IsCrouched()) { m_Stats.Custom[CustomStatistic::CrouchOneCm] += Value; AddFoodExhaustion(0.0001 * static_cast(Value)); } if (IsSprinting()) { m_Stats.Custom[CustomStatistic::SprintOneCm] += Value; AddFoodExhaustion(0.001 * static_cast(Value)); } else { m_Stats.Custom[CustomStatistic::WalkOneCm] += Value; AddFoodExhaustion(0.0001 * static_cast(Value)); } } else { // If a jump just started, process food exhaustion: if ((a_DeltaPos.y > 0.0) && a_PreviousIsOnGround) { m_Stats.Custom[CustomStatistic::Jump]++; AddFoodExhaustion((IsSprinting() ? 0.008 : 0.002) * static_cast(Value)); } else if (a_DeltaPos.y < 0.0) { // Increment statistic m_Stats.Custom[CustomStatistic::FallOneCm] += static_cast(-a_DeltaPos.y * 100 + 0.5); } // TODO: good opportunity to detect illegal flight (check for falling tho) } } else { switch (m_AttachedTo->GetEntityType()) { case cEntity::etMinecart: m_Stats.Custom[CustomStatistic::MinecartOneCm] += Value; break; case cEntity::etBoat: m_Stats.Custom[CustomStatistic::BoatOneCm] += Value; break; case cEntity::etMonster: { cMonster * Monster = static_cast(m_AttachedTo); switch (Monster->GetMobType()) { case mtPig: m_Stats.Custom[CustomStatistic::PigOneCm] += Value; break; case mtHorse: m_Stats.Custom[CustomStatistic::HorseOneCm] += Value; break; default: break; } break; } default: break; } } } void cPlayer::LoadRank(void) { // Update our permissions: RefreshRank(); // Send a permission level update: m_ClientHandle->SendPlayerPermissionLevel(); } void cPlayer::SendBlocksAround(Vector3i a_BlockPos, int a_Range) { // Collect the coords of all the blocks to send: sSetBlockVector blks; for (int y = a_BlockPos.y - a_Range + 1; y < a_BlockPos.y + a_Range; y++) { for (int z = a_BlockPos.z - a_Range + 1; z < a_BlockPos.z + a_Range; z++) { for (int x = a_BlockPos.x - a_Range + 1; x < a_BlockPos.x + a_Range; x++) { blks.emplace_back(x, y, z, E_BLOCK_AIR, static_cast(0)); // Use fake blocktype, it will get set later on. } } } // for y // Get the values of all the blocks: if (!m_World->GetBlocks(blks, false)) { LOGD("%s: Cannot query all blocks, not sending an update", __FUNCTION__); return; } // Divide the block changes by their respective chunks: std::unordered_map Changes; for (const auto & blk: blks) { Changes[cChunkCoords(blk.m_ChunkX, blk.m_ChunkZ)].push_back(blk); } // for blk - blks[] blks.clear(); // Send the blocks for each affected chunk: for (auto itr = Changes.cbegin(), end = Changes.cend(); itr != end; ++itr) { m_ClientHandle->SendBlockChanges(itr->first.m_ChunkX, itr->first.m_ChunkZ, itr->second); } } bool cPlayer::DoesPlacingBlocksIntersectEntity(const std::initializer_list a_Blocks) const { // Compute the bounding box for each block to be placed std::vector PlacementBoxes; cBoundingBox PlacingBounds(0, 0, 0, 0, 0, 0); bool HasInitializedBounds = false; for (auto blk: a_Blocks) { int x = blk.GetX(); int y = blk.GetY(); int z = blk.GetZ(); cBoundingBox BlockBox = cBlockHandler::For(blk.m_BlockType).GetPlacementCollisionBox( m_World->GetBlock({ x - 1, y, z }), m_World->GetBlock({ x + 1, y, z }), (y == 0) ? static_cast(E_BLOCK_AIR) : m_World->GetBlock({ x, y - 1, z }), (y == cChunkDef::Height - 1) ? static_cast(E_BLOCK_AIR) : m_World->GetBlock({ x, y + 1, z }), m_World->GetBlock({ x, y, z - 1 }), m_World->GetBlock({ x, y, z + 1 }) ); BlockBox.Move(x, y, z); PlacementBoxes.push_back(BlockBox); if (HasInitializedBounds) { PlacingBounds = PlacingBounds.Union(BlockBox); } else { PlacingBounds = BlockBox; HasInitializedBounds = true; } } cWorld * World = GetWorld(); // Check to see if any entity intersects any block being placed return !World->ForEachEntityInBox(PlacingBounds, [&](cEntity & a_Entity) { // The distance inside the block the entity can still be. const double EPSILON = 0.0005; if (!a_Entity.DoesPreventBlockPlacement()) { return false; } auto EntBox = a_Entity.GetBoundingBox(); for (auto BlockBox : PlacementBoxes) { // Put in a little bit of wiggle room BlockBox.Expand(-EPSILON, -EPSILON, -EPSILON); if (EntBox.DoesIntersect(BlockBox)) { return true; } } return false; } ); } const cUUID & cPlayer::GetUUID(void) const { return m_ClientHandle->GetUUID(); } bool cPlayer::PlaceBlock(const Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) { return PlaceBlocks({ { a_Position, a_BlockType, a_BlockMeta } }); } bool cPlayer::PlaceBlocks(const std::initializer_list a_Blocks) { if (DoesPlacingBlocksIntersectEntity(a_Blocks)) { // Abort - re-send all the current blocks in the a_Blocks' coords to the client: for (const auto & ResendBlock : a_Blocks) { m_World->SendBlockTo(ResendBlock.GetX(), ResendBlock.GetY(), ResendBlock.GetZ(), *this); } return false; } cPluginManager * pm = cPluginManager::Get(); // Check the blocks CanBeAt, and call the "placing" hooks; if any fail, abort: for (const auto & Block : a_Blocks) { if ( !m_World->DoWithChunkAt(Block.GetAbsolutePos(), [&Block](cChunk & a_Chunk) { return cBlockHandler::For(Block.m_BlockType).CanBeAt(a_Chunk, Block.GetRelativePos(), Block.m_BlockMeta); }) ) { return false; } if (pm->CallHookPlayerPlacingBlock(*this, Block)) { // Abort - re-send all the current blocks in the a_Blocks' coords to the client: for (const auto & ResendBlock : a_Blocks) { m_World->SendBlockTo(ResendBlock.GetX(), ResendBlock.GetY(), ResendBlock.GetZ(), *this); } return false; } } cChunkInterface ChunkInterface(m_World->GetChunkMap()); for (const auto & Block : a_Blocks) { // Set the blocks: m_World->PlaceBlock(Block.GetAbsolutePos(), Block.m_BlockType, Block.m_BlockMeta); // Call the "placed" hooks: pm->CallHookPlayerPlacedBlock(*this, Block); } return true; } void cPlayer::SetSkinParts(int a_Parts) { m_SkinParts = a_Parts & spMask; m_World->BroadcastEntityMetadata(*this, m_ClientHandle.get()); } AString cPlayer::GetUUIDFileName(const cUUID & a_UUID) { AString UUID = a_UUID.ToLongString(); AString res("players/"); res.append(UUID, 0, 2); res.push_back('/'); res.append(UUID, 2, AString::npos); res.append(".json"); return res; } void cPlayer::FreezeInternal(const Vector3d & a_Location, bool a_ManuallyFrozen) { SetSpeed(0, 0, 0); SetPosition(a_Location); m_IsFrozen = true; m_IsManuallyFrozen = a_ManuallyFrozen; double NormalMaxSpeed = GetNormalMaxSpeed(); double SprintMaxSpeed = GetSprintingMaxSpeed(); double FlyingMaxpeed = GetFlyingMaxSpeed(); bool IsFlying = m_IsFlying; // Set the client-side speed to 0 m_NormalMaxSpeed = 0; m_SprintingMaxSpeed = 0; m_FlyingMaxSpeed = 0; m_IsFlying = true; // Send the client its fake speed and max speed of 0 m_ClientHandle->SendPlayerMoveLook(); m_ClientHandle->SendPlayerAbilities(); m_ClientHandle->SendEntityVelocity(*this); m_World->BroadcastEntityProperties(*this); // Keep the server side speed variables as they were in the first place m_NormalMaxSpeed = NormalMaxSpeed; m_SprintingMaxSpeed = SprintMaxSpeed; m_FlyingMaxSpeed = FlyingMaxpeed; m_IsFlying = IsFlying; } float cPlayer::GetLiquidHeightPercent(NIBBLETYPE a_Meta) { if (a_Meta >= 8) { a_Meta = 0; } return static_cast(a_Meta + 1) / 9.0f; } bool cPlayer::IsInsideWater() { const auto EyePos = GetEyePosition().Floor(); if (!cChunkDef::IsValidHeight(EyePos)) { // Not in water if in void. return false; } BLOCKTYPE Block; NIBBLETYPE Meta; if ( !m_World->GetBlockTypeMeta(GetEyePosition().Floor(), Block, Meta) || ((Block != E_BLOCK_WATER) && (Block != E_BLOCK_STATIONARY_WATER)) ) { return false; } const auto EyeHeight = GetEyeHeight(); float f = GetLiquidHeightPercent(Meta) - 0.11111111f; float f1 = static_cast(EyeHeight + 1) - f; return EyeHeight < f1; } float cPlayer::GetDigSpeed(BLOCKTYPE a_Block) { // Based on: https://minecraft.wiki/w/Breaking#Speed // Get the base speed multiplier of the equipped tool for the mined block float MiningSpeed = GetEquippedItem().GetHandler().GetBlockBreakingStrength(a_Block); // If we can harvest the block then we can apply material and enchantment bonuses if (GetEquippedItem().GetHandler().CanHarvestBlock(a_Block)) { if (MiningSpeed > 1.0f) // If the base multiplier for this block is greater than 1, now we can check enchantments { unsigned int EfficiencyModifier = GetEquippedItem().m_Enchantments.GetLevel(cEnchantments::eEnchantment::enchEfficiency); if (EfficiencyModifier > 0) // If an efficiency enchantment is present, apply formula as on wiki { MiningSpeed += (EfficiencyModifier * EfficiencyModifier) + 1; } } } else // If we can't harvest the block then no bonuses: { MiningSpeed = 1; } // Haste increases speed by 20% per level auto Haste = GetEntityEffect(cEntityEffect::effHaste); if (Haste != nullptr) { int intensity = Haste->GetIntensity() + 1; MiningSpeed *= 1.0f + (intensity * 0.2f); } // Mining fatigue decreases speed a lot auto MiningFatigue = GetEntityEffect(cEntityEffect::effMiningFatigue); if (MiningFatigue != nullptr) { int intensity = MiningFatigue->GetIntensity(); switch (intensity) { case 0: MiningSpeed *= 0.3f; break; case 1: MiningSpeed *= 0.09f; break; case 2: MiningSpeed *= 0.0027f; break; default: MiningSpeed *= 0.00081f; break; } } // 5x speed loss for being in water if (IsInsideWater() && !(GetEquippedItem().m_Enchantments.GetLevel(cEnchantments::eEnchantment::enchAquaAffinity) > 0)) { MiningSpeed /= 5.0f; } // 5x speed loss for not touching ground if (!IsOnGround()) { MiningSpeed /= 5.0f; } return MiningSpeed; } float cPlayer::GetMiningProgressPerTick(BLOCKTYPE a_Block) { // Based on https://minecraft.wiki/w/Breaking#Calculation // If we know it's instantly breakable then quit here: if (cBlockInfo::IsOneHitDig(a_Block)) { return 1; } const bool CanHarvest = GetEquippedItem().GetHandler().CanHarvestBlock(a_Block); const float BlockHardness = cBlockInfo::GetHardness(a_Block) * (CanHarvest ? 1.5f : 5.0f); ASSERT(BlockHardness > 0); // Can't divide by 0 or less, IsOneHitDig should have returned true // LOGD("Time to mine block = %f", BlockHardness/DigSpeed); // Number of ticks to mine = (20 * BlockHardness)/DigSpeed; // Therefore take inverse to get fraction mined per tick: return GetDigSpeed(a_Block) / (20.0f * BlockHardness); } bool cPlayer::CanInstantlyMine(BLOCKTYPE a_Block) { // Based on: https://minecraft.wiki/w/Breaking#Calculation // If the dig speed is greater than 30 times the hardness, then the wiki says we can instantly mine: return GetDigSpeed(a_Block) > (30 * cBlockInfo::GetHardness(a_Block)); } void cPlayer::AddKnownItem(const cItem & a_Item) { if (a_Item.m_ItemType < 0) { return; } auto Response = m_KnownItems.insert(a_Item.CopyOne()); if (!Response.second) { // The item was already known, bail out: return; } // Process the recipes that got unlocked by this newly-known item: auto Recipes = cRoot::Get()->GetCraftingRecipes()->FindNewRecipesForItem(a_Item, m_KnownItems); for (const auto & RecipeId : Recipes) { AddKnownRecipe(RecipeId); } } void cPlayer::AddKnownRecipe(UInt32 a_RecipeId) { auto Response = m_KnownRecipes.insert(a_RecipeId); if (!Response.second) { // The recipe was already known, bail out: return; } m_ClientHandle->SendUnlockRecipe(a_RecipeId); } void cPlayer::TickFreezeCode() { if (m_IsFrozen) { if ((!m_IsManuallyFrozen) && (GetClientHandle()->IsPlayerChunkSent())) { // If the player was automatically frozen, unfreeze if the chunk the player is inside is loaded and sent Unfreeze(); // Pull the player out of any solids that might have loaded on them. PREPARE_REL_AND_CHUNK(GetPosition(), *(GetParentChunk())); if (RelSuccess) { int NewY = Rel.y; if (NewY < 0) { NewY = 0; } while (NewY < cChunkDef::Height - 2) { // If we find a position with enough space for the player if ( !cBlockInfo::IsSolid(Chunk->GetBlock(Rel.x, NewY, Rel.z)) && !cBlockInfo::IsSolid(Chunk->GetBlock(Rel.x, NewY + 1, Rel.z)) ) { // If the found position is not the same as the original if (NewY != Rel.y) { SetPosition(GetPosition().x, NewY, GetPosition().z); GetClientHandle()->SendPlayerPosition(); } break; } ++NewY; } } } else if ((GetWorld()->GetWorldTickAge() % 100_tick) == 0_tick) { // Despite the client side freeze, the player may be able to move a little by // Jumping or canceling flight. Re-freeze every now and then FreezeInternal(GetPosition(), m_IsManuallyFrozen); } } else { if (!GetClientHandle()->IsPlayerChunkSent() || (!GetParentChunk()->IsValid())) { FreezeInternal(GetPosition(), false); } } } void cPlayer::RefreshRank() { const auto & UUID = GetUUID(); cRankManager * RankMgr = cRoot::Get()->GetRankManager(); // Load the values from cRankManager: m_Rank = RankMgr->GetPlayerRankName(UUID); if (m_Rank.empty()) { m_Rank = RankMgr->GetDefaultRank(); } else { // Update the name: RankMgr->UpdatePlayerName(UUID, GetName()); } m_Permissions = RankMgr->GetPlayerPermissions(UUID); m_Restrictions = RankMgr->GetPlayerRestrictions(UUID); RankMgr->GetRankVisuals(m_Rank, m_MsgPrefix, m_MsgSuffix, m_MsgNameColorCode); // Break up the individual permissions on each dot, into m_SplitPermissions: m_SplitPermissions.clear(); m_SplitPermissions.reserve(m_Permissions.size()); for (auto & Permission : m_Permissions) { m_SplitPermissions.push_back(StringSplit(Permission, ".")); } // Break up the individual restrictions on each dot, into m_SplitRestrictions: m_SplitRestrictions.clear(); m_SplitRestrictions.reserve(m_Restrictions.size()); for (auto & Restriction : m_Restrictions) { m_SplitRestrictions.push_back(StringSplit(Restriction, ".")); } } void cPlayer::ApplyArmorDamage(int a_DamageBlocked) { short ArmorDamage = static_cast(std::max(a_DamageBlocked / 4, 1)); for (int i = 0; i < 4; i++) { UseItem(cInventory::invArmorOffset + i, ArmorDamage); } } void cPlayer::BroadcastMovementUpdate(const cClientHandle * a_Exclude) { if (!m_IsFrozen && m_Speed.SqrLength() > 0.001) { // If the player is not frozen, has a non-zero speed, // send the speed to the client so he is forced to move so: m_ClientHandle->SendEntityVelocity(*this); } // Since we do no physics processing for players, speed will otherwise never decrease: m_Speed.Set(0, 0, 0); Super::BroadcastMovementUpdate(a_Exclude); } bool cPlayer::DoTakeDamage(TakeDamageInfo & a_TDI) { // Filters out damage for creative mode / friendly fire. if ((a_TDI.DamageType != dtInVoid) && (a_TDI.DamageType != dtPlugin)) { if (IsGameModeCreative() || IsGameModeSpectator()) { // No damage / health in creative or spectator mode if not void or plugin damage return false; } } if ((a_TDI.Attacker != nullptr) && (a_TDI.Attacker->IsPlayer())) { cPlayer * Attacker = static_cast(a_TDI.Attacker); if ((m_Team != nullptr) && (m_Team == Attacker->m_Team)) { if (!m_Team->AllowsFriendlyFire()) { // Friendly fire is disabled return false; } } } if (Super::DoTakeDamage(a_TDI)) { // Any kind of damage adds food exhaustion AddFoodExhaustion(0.3f); m_ClientHandle->SendHealth(); // Tell the wolves if (a_TDI.Attacker != nullptr) { if (a_TDI.Attacker->IsPawn()) { NotifyNearbyWolves(static_cast(a_TDI.Attacker), true); } } m_Stats.Custom[CustomStatistic::DamageTaken] += FloorC(a_TDI.FinalDamage * 10 + 0.5); return true; } return false; } float cPlayer::GetEnchantmentBlastKnockbackReduction() { if ( IsGameModeSpectator() || (IsGameModeCreative() && !IsOnGround()) ) { return 1; // No impact from explosion } return Super::GetEnchantmentBlastKnockbackReduction(); } bool cPlayer::IsCrouched(void) const { return std::holds_alternative(m_BodyStance); } bool cPlayer::IsSprinting(void) const { return std::holds_alternative(m_BodyStance); } bool cPlayer::IsElytraFlying(void) const { return std::holds_alternative(m_BodyStance); } bool cPlayer::IsInvisible() const { return !m_IsVisible || Super::IsInvisible(); } void cPlayer::OnAddToWorld(cWorld & a_World) { // Sends player spawn: Super::OnAddToWorld(a_World); // Update world name tracking: m_CurrentWorldName = m_World->GetName(); // Fix to stop the player falling through the world, until we get serversided collision detection: FreezeInternal(GetPosition(), false); // UpdateCapabilities was called in the constructor, and in OnRemoveFromWorld, possibly changing our visibility. // If world is in spectator mode, invisibility will need updating. If we just connected, we might be on fire from a previous game. // Hence, tell the client by sending metadata: m_ClientHandle->SendEntityMetadata(*this); // Send contents of the inventory window: m_ClientHandle->SendWholeInventory(*m_CurrentWindow); // Send health (the respawn packet, which understandably resets health, is also used for world travel...): m_ClientHandle->SendHealth(); // Send experience, similar story with the respawn packet: m_ClientHandle->SendExperience(); // Send hotbar active slot (also reset by respawn): m_ClientHandle->SendHeldItemChange(m_Inventory.GetEquippedSlotNum()); // Update player team: UpdateTeam(); // Send scoreboard data: m_World->GetScoreBoard().SendTo(*m_ClientHandle); // Update the view distance: m_ClientHandle->SetViewDistance(m_ClientHandle->GetRequestedViewDistance()); // Send current weather of target world: m_ClientHandle->SendWeather(a_World.GetWeather()); // Send time: m_ClientHandle->SendTimeUpdate(a_World.GetWorldAge(), a_World.GetWorldDate(), a_World.IsDaylightCycleEnabled()); // Finally, deliver the notification hook: cRoot::Get()->GetPluginManager()->CallHookPlayerSpawned(*this); } void cPlayer::OnDetach() { if (m_IsTeleporting) { // If they are teleporting, no need to figure out position: return; } int PosX = POSX_TOINT; int PosY = POSY_TOINT; int PosZ = POSZ_TOINT; // Search for a position within an area to teleport player after detachment // Position must be solid land with two air blocks above. // If nothing found, player remains where they are. for (int x = PosX - 1; x <= (PosX + 1); ++x) { for (int y = PosY; y <= (PosY + 3); ++y) { for (int z = PosZ - 1; z <= (PosZ + 1); ++z) { if ( (m_World->GetBlock({ x, y, z }) == E_BLOCK_AIR) && (m_World->GetBlock({ x, y + 1, z }) == E_BLOCK_AIR) && cBlockInfo::IsSolid(m_World->GetBlock({ x, y - 1, z })) ) { TeleportToCoords(x + 0.5, y, z + 0.5); return; } } } } } void cPlayer::OnRemoveFromWorld(cWorld & a_World) { Super::OnRemoveFromWorld(a_World); // Remove any references to this player pointer by windows in the old world: CloseWindow(false); // Stop spectation and remove our reference from the spectated: SpectateEntity(nullptr); // Remove the client handle from the world: m_World->RemoveClientFromChunks(m_ClientHandle.get()); if (m_ClientHandle->IsDestroyed()) // Note: checking IsWorldChangeScheduled not appropriate here since we can disconnecting while having a scheduled warp { // Disconnecting, do the necessary cleanup. // This isn't in the destructor to avoid crashing accessing destroyed objects during shutdown. if (!cRoot::Get()->GetPluginManager()->CallHookPlayerDestroyed(*this)) { cRoot::Get()->BroadcastChatLeave(fmt::format(FMT_STRING("{} has left the game"), GetName())); LOGINFO("Player %s has left the game", GetName()); } // Remove ourself from everyone's lists: cRoot::Get()->BroadcastPlayerListsRemovePlayer(*this); // Atomically decrement player count (in world thread): cRoot::Get()->GetServer()->PlayerDestroyed(); // We're just disconnecting. The remaining code deals with going through portals, so bail: return; } const auto DestinationDimension = m_WorldChangeInfo.m_NewWorld->GetDimension(); // Award relevant achievements: if (DestinationDimension == dimEnd) { AwardAchievement(CustomStatistic::AchTheEnd); } else if (DestinationDimension == dimNether) { AwardAchievement(CustomStatistic::AchPortal); } // Set capabilities based on new world: UpdateCapabilities(); // Clientside warp start: m_ClientHandle->SendRespawn(DestinationDimension, false); m_ClientHandle->SendPlayerListUpdateGameMode(*this); m_World->BroadcastPlayerListUpdateGameMode(*this); // Clear sent chunk lists from the clienthandle: m_ClientHandle->RemoveFromWorld(); } void cPlayer::SpawnOn(cClientHandle & a_Client) { if (m_ClientHandle.get() == &a_Client) { return; } a_Client.SendPlayerSpawn(*this); a_Client.SendEntityHeadLook(*this); a_Client.SendEntityEquipment(*this, 0, m_Inventory.GetEquippedItem()); a_Client.SendEntityEquipment(*this, 1, m_Inventory.GetEquippedBoots()); a_Client.SendEntityEquipment(*this, 2, m_Inventory.GetEquippedLeggings()); a_Client.SendEntityEquipment(*this, 3, m_Inventory.GetEquippedChestplate()); a_Client.SendEntityEquipment(*this, 4, m_Inventory.GetEquippedHelmet()); } void cPlayer::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { if (m_ClientHandle->IsDestroyed()) { Destroy(); return; } if (!m_ClientHandle->IsPlaying()) { // We're not yet in the game, ignore everything: return; } { const auto TicksElapsed = static_cast(std::chrono::duration_cast(a_Dt).count()); m_Stats.Custom[CustomStatistic::PlayOneMinute] += TicksElapsed; m_Stats.Custom[CustomStatistic::TimeSinceDeath] += TicksElapsed; if (IsCrouched()) { m_Stats.Custom[CustomStatistic::SneakTime] += TicksElapsed; } } ASSERT((GetParentChunk() != nullptr) && (GetParentChunk()->IsValid())); ASSERT(a_Chunk.IsValid()); // Handle a frozen player: TickFreezeCode(); if ( m_IsFrozen || // Don't do Tick updates if frozen IsWorldChangeScheduled() // If we're about to change worlds (e.g. respawn), abort processing all world interactions (GH #3939) ) { return; } Super::Tick(a_Dt, a_Chunk); // Handle charging the bow: if (m_IsChargingBow) { m_BowCharge += 1; } // Handle syncing our position with the entity being spectated: if (IsGameModeSpectator() && (m_Spectating != nullptr)) { SetYaw(m_Spectating->GetYaw()); SetPitch(m_Spectating->GetPitch()); SetRoll(m_Spectating->GetRoll()); SetPosition(m_Spectating->GetPosition()); } if (IsElytraFlying()) { // Damage elytra, once per second: { using namespace std::chrono_literals; auto & TicksFlying = std::get(m_BodyStance).TicksElytraFlying; const auto TotalFlew = TicksFlying + a_Dt; const auto Periods = static_cast(TotalFlew / 1s); TicksFlying = std::chrono::duration_cast(TotalFlew - Periods * 1s); UseItem(cInventory::invArmorOffset + 1, Periods); } // Check if flight is still possible: if (IsOnGround() || IsInWater() || IsRiding() || (GetEquippedChestplate().m_ItemType != E_ITEM_ELYTRA)) { SetElytraFlight(false); } } else if (IsInBed()) { // Check if sleeping is still possible: if ((GetPosition().Floor() != m_RespawnPosition) || (m_World->GetBlock(m_RespawnPosition) != E_BLOCK_BED)) { m_ClientHandle->HandleLeaveBed(); } } BroadcastMovementUpdate(m_ClientHandle.get()); if (m_Health > 0) // make sure player is alive { if ((m_EatingFinishTick >= 0_tick) && (m_EatingFinishTick <= m_World->GetWorldAge())) { FinishEating(); } HandleFood(); } if (m_IsFishing) { HandleFloater(); } // Update items (e.g. Maps) m_Inventory.UpdateItems(); if (m_TicksUntilNextSave == 0) { SaveToDisk(); m_TicksUntilNextSave = PLAYER_INVENTORY_SAVE_INTERVAL; } else { m_TicksUntilNextSave--; } } ================================================ FILE: src/Entities/Player.h ================================================ #pragma once #include "Pawn.h" #include "../Inventory.h" #include "../Defines.h" #include "../World.h" #include "../Items/ItemHandler.h" #include "../StatisticsManager.h" #include "../UUID.h" class cWindow; class cClientHandle; class cTeam; // tolua_begin class cPlayer: public cPawn { // tolua_end using Super = cPawn; /** Tag representing a sneaking pose. */ struct BodyStanceCrouching { BodyStanceCrouching(cPlayer & a_Player); }; /** Tag representing a sleeping pose. Set by a right click on unoccupied bed, unset by a time fast forward or teleport. */ struct BodyStanceSleeping { BodyStanceSleeping(cPlayer & a_Player); }; /** Tag representing a sprinting pose. */ struct BodyStanceSprinting { }; /** Tag representing the neutral stance. */ struct BodyStanceStanding { BodyStanceStanding(cPlayer & a_Player); }; /** Tag representing a swimming or elytra flying pose. */ struct BodyStanceGliding { BodyStanceGliding(cPlayer & a_Player); cTickTime TicksElytraFlying; }; /* struct HandStanceNeutral { }; struct HandStandChargingBow { int m_BowCharge; }; struct HandStanceEating { }; */ // tolua_begin public: static const int MAX_HEALTH; static const int MAX_FOOD_LEVEL; // tolua_end CLASS_PROTODEF(cPlayer) cPlayer(const std::shared_ptr & a_Client); virtual ~cPlayer() override; /** Called when spectation stops, because the player crouched or when the entity we're spectating gets removed from the world. */ void OnLoseSpectated(); // tolua_begin /** Sets the experience total Returns true on success "should" really only be called at init or player death, plugins excepted */ bool SetCurrentExperience(int a_XpTotal); /* changes Xp by Xp_delta, you "shouldn't" inc more than MAX_EXPERIENCE_ORB_SIZE Wont't allow xp to go negative Returns the new current experience, -1 on error */ int DeltaExperience(int a_Xp_delta); /** Gets the experience total - XpTotal for score on death */ inline int GetXpLifetimeTotal(void) { return m_LifetimeTotalXp; } /** Gets the current experience */ inline int GetCurrentXp(void) { return m_CurrentXp; } /** Gets the current level - XpLevel */ int GetXpLevel(void) const; /** Gets the experience bar percentage - XpP */ float GetXpPercentage(void) const; /** Calculates the amount of XP needed for a given level Ref: https://minecraft.wiki/w/XP */ static int XpForLevel(int a_Level); /** Inverse of XpForLevel Ref: https://minecraft.wiki/w/XP values are as per this with pre-calculations */ static int CalcLevelFromXp(int a_CurrentXp); // tolua_end /** Gets the set of IDs for recipes this player has discovered. */ const std::set & GetKnownRecipes() const; /** Starts charging the equipped bow */ void StartChargingBow(void); /** Finishes charging the current bow. Returns the number of ticks for which the bow has been charged */ int FinishChargingBow(void); /** Cancels the current bow charging */ void CancelChargingBow(void); /** Gets If The Player Is Teleporting To Fix https://github.com/cuberite/cuberite/issues/5542 */ bool GetIsTeleporting() { return m_IsTeleporting; } /** Returns true if the player is currently charging the bow */ bool IsChargingBow(void) const { return m_IsChargingBow; } void SetTouchGround(bool a_bTouchGround); double GetEyeHeight(void) const; // tolua_export Vector3d GetEyePosition(void) const; // tolua_export inline cInventory & GetInventory(void) { return m_Inventory; } // tolua_export inline const cInventory & GetInventory(void) const { return m_Inventory; } /** Gets the contents of the player's associated enderchest */ cItemGrid & GetEnderChestContents(void) { return m_EnderChestContents; } inline const cItem & GetEquippedItem(void) const { return GetInventory().GetEquippedItem(); } // tolua_export /** Returns whether the player is climbing (ladders, vines etc.) */ bool IsClimbing(void) const; virtual void TeleportToCoords(double a_PosX, double a_PosY, double a_PosZ) override; /** Updates player's capabilities - flying, visibility, etc. from their gamemode. */ void UpdateCapabilities(); // tolua_begin /** Prevent the player from moving and lock him into a_Location. */ void Freeze(const Vector3d & a_Location); /** Is the player frozen? */ bool IsFrozen(); /** Cancels Freeze(...) and allows the player to move naturally. */ void Unfreeze(); /** Sends the "look" packet to the player, forcing them to set their rotation to the specified values. a_YawDegrees is clipped to range [-180, +180), a_PitchDegrees is clipped to range [-180, +180) but the client only uses [-90, +90] */ void SendRotation(double a_YawDegrees, double a_PitchDegrees); /** Spectates the target entity. If a_Target is nullptr or a pointer to self, end spectation. */ void SpectateEntity(cEntity * a_Target); /** Returns the position where projectiles thrown by this player should start, player eye position + adjustment */ Vector3d GetThrowStartPos(void) const; /** Returns the initial speed vector of a throw, with a 3D length of a_SpeedCoeff. */ Vector3d GetThrowSpeed(double a_SpeedCoeff) const; /** Returns the current gamemode. Partly OBSOLETE, you should use IsGameModeXXX() functions wherever applicable */ eGameMode GetGameMode(void) const { return m_GameMode; } /** Returns the current effective gamemode (inherited gamemode is resolved before returning) */ eGameMode GetEffectiveGameMode(void) const; /** Sets the gamemode for the player. The gamemode may be gmNotSet, in that case the player inherits the world's gamemode. Updates the gamemode on the client (sends the packet) */ void SetGameMode(eGameMode a_GameMode); /** Returns true if the player is in Creative mode, either explicitly, or by inheriting from current world */ bool IsGameModeCreative(void) const; /** Returns true if the player is in Survival mode, either explicitly, or by inheriting from current world */ bool IsGameModeSurvival(void) const; /** Returns true if the player is in Adventure mode, either explicitly, or by inheriting from current world */ bool IsGameModeAdventure(void) const; /** Returns true if the player is in Spectator mode, either explicitly, or by inheriting from current world */ bool IsGameModeSpectator(void) const; /** Returns true if the player is fireproof Stops players burning in creative or spectator modes. */ virtual bool IsFireproof() const override { return (m_IsFireproof || IsGameModeCreative() || IsGameModeSpectator()); } /** Returns true if the player can be targeted by Mobs */ bool CanMobsTarget(void) const; AString GetIP(void) const; // tolua_export /** Return the associated statistic and achievement manager. */ StatisticsManager & GetStatistics() { return m_Stats; } /** Returns the associated team, nullptr if none */ cTeam * GetTeam(void) { return m_Team; } // tolua_export /** Returns the associated team, nullptr if none */ const cTeam * GetTeam(void) const { return m_Team; } /** Sets the player team, nullptr if none */ void SetTeam(cTeam * a_Team); // tolua_end /** Forces the player to query the scoreboard for his team */ cTeam * UpdateTeam(void); /** Awards the player an achievement. If all prerequisites are met, this method will award the achievement and will broadcast a chat message. If the achievement has been already awarded to the player, this method will just increment the stat counter. */ void AwardAchievement(CustomStatistic a_Ach); /** Forces the player to move in the given direction. @deprecated Use SetSpeed instead. */ void ForceSetSpeed(const Vector3d & a_Speed); // tolua_export cWindow * GetWindow(void) { return m_CurrentWindow; } // tolua_export const cWindow * GetWindow(void) const { return m_CurrentWindow; } // tolua_begin /** Opens the specified window; closes the current one first using CloseWindow() */ void OpenWindow(cWindow & a_Window); /** Closes the current window, resets current window to m_InventoryWindow. A plugin may refuse the closing if a_CanRefuse is true */ void CloseWindow(bool a_CanRefuse = true); /** Closes the current window if it matches the specified ID, resets current window to m_InventoryWindow */ void CloseWindowIfID(char a_WindowID, bool a_CanRefuse = true); cClientHandle * GetClientHandle(void) const { return m_ClientHandle.get(); } // tolua_end /** Get a copy of the PRNG for enchanting related generation, don't use this for other purposes. The PRNG's state is initialised with an internal seed, such that until PermuteEnchantmentSeed is called, this function returns the same PRNG. */ MTRand GetEnchantmentRandomProvider(); /** Permute the seed for enchanting related PRNGs, don't use this for other purposes. */ void PermuteEnchantmentSeed(); // tolua_begin void SendMessage (const AString & a_Message); void SendMessageInfo (const AString & a_Message); void SendMessageFailure (const AString & a_Message); void SendMessageSuccess (const AString & a_Message); void SendMessageWarning (const AString & a_Message); void SendMessageFatal (const AString & a_Message); void SendMessagePrivateMsg (const AString & a_Message, const AString & a_Sender); void SendMessage (const cCompositeChat & a_Message); void SendMessageRaw (const AString & a_MessageRaw, eChatType a_Type = eChatType::ctChatBox); void SendSystemMessage (const AString & a_Message); void SendAboveActionBarMessage(const AString & a_Message); void SendSystemMessage (const cCompositeChat & a_Message); void SendAboveActionBarMessage(const cCompositeChat & a_Message); const AString & GetName(void) const; // tolua_end bool HasPermission(const AString & a_Permission) const; // tolua_export /** Returns true iff a_Permission matches the a_Template. A match is defined by either being exactly the same, or each sub-item matches until there's a wildcard in a_Template. Ie. {"a", "b", "c"} matches {"a", "b", "*"} but doesn't match {"a", "b"} */ static bool PermissionMatches(const AStringVector & a_Permission, const AStringVector & a_Template); // Exported in ManualBindings with AString params /** Returns all the permissions that the player has assigned to them. */ const AStringVector & GetPermissions(void) const { return m_Permissions; } // Exported in ManualBindings.cpp /** Returns all the restrictions that the player has assigned to them. */ const AStringVector & GetRestrictions(void) const { return m_Restrictions; } // Exported in ManualBindings.cpp // tolua_begin /** Returns the full color code to use for this player, based on their rank. The returned value either is empty, or includes the cChatColor::Delimiter. */ AString GetColor(void) const; /** Returns the player name prefix, may contain @ format directives */ AString GetPrefix(void) const; /** Returns the player name suffix, may contain @ format directives */ AString GetSuffix(void) const; /** Returns the name that is used in the playerlist. */ AString GetPlayerListName(void) const; /** tosses the item in the selected hotbar slot */ void TossEquippedItem(char a_Amount = 1); /** Removes one item from the the current equipped item stack, and attempts to add the specified item stack back to the same slot. If it is not possible to place the item in the same slot, tries to place the specified item elsewhere in the inventory. If this is not possible, then any remaining items are tossed. If the currently equipped slot is empty, its contents are simply set to the given Item. */ void ReplaceOneEquippedItemTossRest(const cItem &); /** tosses the item held in hand (when in UI windows) */ void TossHeldItem(char a_Amount = 1); /** tosses a pickup newly created from a_Item */ void TossPickup(const cItem & a_Item); /** Heals the player by the specified amount of HPs (positive only); sends health update */ virtual void Heal(int a_Health) override; int GetFoodLevel (void) const { return m_FoodLevel; } double GetFoodSaturationLevel (void) const { return m_FoodSaturationLevel; } int GetFoodTickTimer (void) const { return m_FoodTickTimer; } double GetFoodExhaustionLevel (void) const { return m_FoodExhaustionLevel; } /** Returns true if the player is satiated, i. e. their foodlevel is at the max and they cannot eat anymore */ bool IsSatiated(void) const { return (m_FoodLevel >= MAX_FOOD_LEVEL); } void SetFoodLevel (int a_FoodLevel); void SetFoodSaturationLevel (double a_FoodSaturationLevel); void SetFoodTickTimer (int a_FoodTickTimer); void SetFoodExhaustionLevel (double a_FoodExhaustionLevel); /** Adds to FoodLevel and FoodSaturationLevel, returns true if any food has been consumed, false if player "full" */ bool Feed(int a_Food, double a_Saturation); /** Adds the specified exhaustion to m_FoodExhaustion. Expects only positive values. */ void AddFoodExhaustion(double a_Exhaustion); /** Returns true if the player is currently in the process of eating the currently equipped item */ bool IsEating(void) const { return m_EatingFinishTick >= 0_tick; } /** Returns true if the player is currently flying */ bool IsFlying(void) const { return m_IsFlying; } /** Returns true if a player is sleeping in a bed. */ bool IsInBed(void) const; /** Returns true if the player's left hand is dominant. */ bool IsLeftHanded() const; /** Returns true if the player has thrown out a floater */ bool IsFishing(void) const { return m_IsFishing; } void SetIsFishing(bool a_IsFishing, UInt32 a_FloaterID = cEntity::INVALID_ID) { m_IsFishing = a_IsFishing; m_FloaterID = a_FloaterID; } UInt32 GetFloaterID(void) const { return m_FloaterID; } // tolua_end /** Returns true if a player is standing normally, that is, in a neutral pose. */ bool IsStanding() const; /** Tosses a list of items. */ void TossItems(const cItems & a_Items); /** Sets a player's in-bed state. We can't be sure plugins will keep this value updated, so no exporting. If value is false (not in bed), will update players of the fact that they have been ejected from the bed. */ void SetIsInBed(bool a_IsInBed); /** Starts eating the currently equipped item. Resets the eating timer and sends the proper animation packet */ void StartEating(void); /** Finishes eating the currently equipped item. Consumes the item, updates health and broadcasts the packets */ void FinishEating(void); /** Aborts the current eating operation */ void AbortEating(void); virtual void KilledBy(TakeDamageInfo & a_TDI) override; virtual void Killed(const cEntity & a_Victim, eDamageType a_DamageType) override; void Respawn(void); // tolua_export void SetVisible( bool a_bVisible); // tolua_export /** Saves all player data, such as inventory, to JSON. */ void SaveToDisk(void); /** Loads the player data from the save file. Sets m_World to the world where the player will spawn, based on the stored world name or the default world by calling LoadFromFile(). */ void LoadFromDisk(); const AString & GetLoadedWorldName() const { return m_CurrentWorldName; } /** Opens the inventory of any tame horse the player is riding. If the player is not riding a horse or if the horse is untamed, does nothing. */ void OpenHorseInventory(); /** Damage the player's equipped item by a_Damage, possibly less if the equipped item is enchanted. */ void UseEquippedItem(short a_Damage = 1); /** Damage the player's equipped item by the amount of damage such an item is damaged by when used for a_Action */ void UseEquippedItem(cItemHandler::eDurabilityLostAction a_Action); /** Damage the item in a_SlotNumber by a_Damage, possibly less if the equipped item is enchanted. */ void UseItem(int a_SlotNumber, short a_Damage = 1); /** In UI windows, get the item that the player is dragging */ cItem & GetDraggingItem(void) {return m_DraggingItem; } // tolua_export /** In UI windows, set the item that the player is dragging */ void SetDraggingItem(const cItem & a_Item); // tolua_export // In UI windows, when inventory-painting: /** Clears the list of slots that are being inventory-painted. To be used by cWindow only */ void ClearInventoryPaintSlots(void); /** Adds a slot to the list for inventory painting. To be used by cWindow only */ void AddInventoryPaintSlot(int a_SlotNum); /** Returns the list of slots currently stored for inventory painting. To be used by cWindow only */ const cSlotNums & GetInventoryPaintSlots(void) const; // tolua_begin /** Returns the current relative maximum speed (takes current sprinting / flying state into account) */ double GetMaxSpeed(void) const; /** Gets the normal relative maximum speed */ double GetNormalMaxSpeed(void) const { return m_NormalMaxSpeed; } /** Gets the sprinting relative maximum speed */ double GetSprintingMaxSpeed(void) const { return m_SprintingMaxSpeed; } /** Gets the flying relative maximum speed */ double GetFlyingMaxSpeed(void) const { return m_FlyingMaxSpeed; } /** Sets the normal relative maximum speed. Sends the update to player, if needed. */ void SetNormalMaxSpeed(double a_Speed); /** Sets the sprinting relative maximum speed. Sends the update to player, if needed. */ void SetSprintingMaxSpeed(double a_Speed); /** Sets the flying relative maximum speed. Sends the update to player, if needed. */ void SetFlyingMaxSpeed(double a_Speed); /** Starts or stops crouching, if our current body stance permits, broadcasting the state change. */ void SetCrouch(bool a_ShouldCrouch); /** Starts or stops elytra flight, if our current body stance permits, broadcasting the state change. */ void SetElytraFlight(bool a_ShouldElytraFly); /** Starts or stops flying, broadcasting the state change. */ void SetFlying(bool a_ShouldFly); /** Sets the dominant hand of the player. */ void SetLeftHanded(bool a_IsLeftHanded); /** Starts or stops sprinting, if our current body stance permits, broadcasting the state change. */ void SetSprint(bool a_ShouldSprint); /** If true the player can fly even when he's not in creative. */ void SetCanFly(bool a_CanFly); /** Returns true if the player has a custom name. */ bool HasCustomName(void) const { return !m_CustomName.empty(); } /** Returns the custom name of this player. If the player hasn't a custom name, it will return an empty string. */ const AString & GetCustomName(void) const { return m_CustomName; } /** Sets the custom name of this player. If you want to disable the custom name, simply set an empty string. The custom name will be used in the tab-list, in the player nametag and in the tab-completion. */ void SetCustomName(const AString & a_CustomName); /** Gets the player's potential respawn position (named LastBedPos for compatibility reasons). */ Vector3i GetLastBedPos(void) const { return m_RespawnPosition; } /** Returns if the respawn point is unconditionally used. */ bool IsRespawnPointForced(void) const { return m_IsRespawnPointForced; } /** Sets the player's bed position to the specified position. Sets the respawn world to the player's world and unforces the respawn point. The given position will be used subject to bed checks when respawning. */ void SetBedPos(Vector3i a_Position); /** Sets the player's bed position to the specified position. The spawn point is unforced. The given position will be used subject to bed checks when respawning. */ void SetBedPos(Vector3i a_Position, const cWorld & a_World); /** Sets the player's forced respawn position and world. */ void SetRespawnPosition(Vector3i a_Position, const cWorld & a_World); // tolua_end // TODO lua export GetRespawnWorld cWorld * GetRespawnWorld(); /** Update movement-related statistics. */ void UpdateMovementStats(const Vector3d & a_DeltaPos, bool a_PreviousIsOnGround); /** Whether placing the given blocks would intersect any entitiy */ bool DoesPlacingBlocksIntersectEntity(std::initializer_list a_Blocks) const; /** Returns the UUID that has been read from the client, or nil if not available. */ const cUUID & GetUUID(void) const; // Exported in ManualBindings.cpp // tolua_begin /** Returns wheter the player can fly or not. */ virtual bool CanFly(void) const { return m_IsFlightCapable; } /** (Re)loads the rank and permissions from the cRankManager and sends a permission level update to the client. */ void LoadRank(void); /** Sends the block in the specified range around the specified coord to the client as a block change packet. The blocks in range (a_BlockX - a_Range, a_BlockX + a_Range) are sent (NY-metric). */ void SendBlocksAround(Vector3i a_BlockPos, int a_Range = 1); bool HasSkinPart(eSkinPart a_Part) const { return (m_SkinParts & a_Part) != 0; } int GetSkinParts(void) const { return m_SkinParts; } void SetSkinParts(int a_Parts); // tolua_end /** Attempts to place the block in the world with a call to PlaceBlocks. */ bool PlaceBlock(Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta); /** Calls the block placement hooks and places the blocks in the world. First the "placing" hooks for all the blocks are called, then the blocks are placed, and finally the "placed" hooks are called. If the any of the "placing" hooks aborts, none of the blocks are placed and the function returns false. Returns true if all the blocks are placed. */ bool PlaceBlocks(std::initializer_list a_Blocks); /** Notify nearby wolves that the player or one of the player's wolves took damage or did damage to an entity @param a_Opponent the opponent we're fighting. @param a_IsPlayerInvolved Should be true if the player took or did damage, and false if one of the player's wolves took or did damage. */ void NotifyNearbyWolves(cPawn * a_Opponent, bool a_IsPlayerInvolved); /** Returns the progress mined per tick for the block a_Block as a fraction (1 would be completely mined) Depends on hardness values so check those are correct. Source: https://minecraft.wiki/w/Breaking#Calculation */ float GetMiningProgressPerTick(BLOCKTYPE a_Block); /** Given tool, enchantments, status effects, and world position returns whether a_Block would be instantly mined. Depends on hardness values so check those are correct. Source: https://minecraft.wiki/w/Breaking#Instant_breaking */ bool CanInstantlyMine(BLOCKTYPE a_Block); /** Adds an Item to the list of known items. If the item is already known, does nothing. */ void AddKnownItem(const cItem & a_Item); // cEntity overrides: virtual cItem GetEquippedWeapon(void) const override { return m_Inventory.GetEquippedItem(); } virtual cItem GetEquippedHelmet(void) const override { return m_Inventory.GetEquippedHelmet(); } virtual cItem GetEquippedChestplate(void) const override { return m_Inventory.GetEquippedChestplate(); } virtual cItem GetEquippedLeggings(void) const override { return m_Inventory.GetEquippedLeggings(); } virtual cItem GetEquippedBoots(void) const override { return m_Inventory.GetEquippedBoots(); } virtual cItem GetOffHandEquipedItem(void) const override { return m_Inventory.GetShieldSlot(); } virtual bool IsCrouched(void) const override; virtual bool IsOnGround(void) const override { return m_bTouchGround; } virtual bool IsSprinting(void) const override; private: typedef std::vector > AStringVectorVector; /** The current body stance the player has adopted. */ std::variant m_BodyStance; /** The name of the rank assigned to this player. */ AString m_Rank; /** All the permissions that this player has, based on their rank. */ AStringVector m_Permissions; /** All the restrictions that this player has, based on their rank. */ AStringVector m_Restrictions; /** All the permissions that this player has, based on their rank, split into individual dot-delimited parts. This is used mainly by the HasPermission() function to optimize the lookup. */ AStringVectorVector m_SplitPermissions; /** All the restrictions that this player has, based on their rank, split into individual dot-delimited parts. This is used mainly by the HasPermission() function to optimize the lookup. */ AStringVectorVector m_SplitRestrictions; // Message visuals: AString m_MsgPrefix, m_MsgSuffix; AString m_MsgNameColorCode; // Food-related variables: /** Represents the food bar, one point equals half a "drumstick" */ int m_FoodLevel; /** "Overcharge" for the m_FoodLevel; is depleted before m_FoodLevel */ double m_FoodSaturationLevel; /** Count-up to the healing or damaging action, based on m_FoodLevel */ int m_FoodTickTimer; /** A "buffer" which adds up hunger before it is substracted from m_FoodSaturationLevel or m_FoodLevel. Each action adds a little */ double m_FoodExhaustionLevel; /** Stores the player's inventory, consisting of crafting grid, hotbar, and main slots */ cInventory m_Inventory; /** An item grid that stores the player specific enderchest contents */ cItemGrid m_EnderChestContents; cWindow * m_CurrentWindow; cWindow * m_InventoryWindow; /** The player's potential respawn position, initialised to world spawn by default. During player respawn from death, if m_IsRespawnPointForced is false and no bed exists here, it will be reset to world spawn. */ Vector3i m_RespawnPosition; /** The name of the world which the player respawns in upon death. This is stored as a string to enable SaveToDisk to not touch cRoot, and thus can be safely called in the player's destructor. */ std::string m_SpawnWorldName; /** The name of the world which the player currently resides in. Stored in addition to m_World to allow SaveToDisk to be safely called in the player's destructor. */ std::string m_CurrentWorldName; /** The save path of the default world. */ std::string m_DefaultWorldPath; eGameMode m_GameMode; /** The item being dragged by the cursor while in a UI window */ cItem m_DraggingItem; std::shared_ptr m_ClientHandle; cSlotNums m_InventoryPaintSlots; /** Max speed, relative to the game default. 1 means regular speed, 2 means twice as fast, 0.5 means half-speed. Default value is 1. */ double m_NormalMaxSpeed; /** Max speed, relative to the game default max speed, when sprinting. 1 means regular speed, 2 means twice as fast, 0.5 means half-speed. Default value is 1.3. */ double m_SprintingMaxSpeed; /** Max speed, relative to the game default flying max speed, when flying. 1 means regular speed, 2 means twice as fast, 0.5 means half-speed. Default value is 1. */ double m_FlyingMaxSpeed; bool m_IsChargingBow; bool m_IsFishing; /** If this is true the player can fly. Even if he is not in creative. */ bool m_IsFlightCapable; bool m_IsFlying; /** If true, we are locking m_Position to m_FrozenPosition. */ bool m_IsFrozen; /** Whether the player is left-handed, or right-handed. */ bool m_IsLeftHanded; /** Was the player frozen manually by a plugin or automatically by the server? */ bool m_IsManuallyFrozen; /** Whether we unconditionally respawn to m_RespawnPosition, or check if a bed is unobstructed and available first. */ bool m_IsRespawnPointForced; /** Flag used by food handling system to determine whether a teleport has just happened. Will not apply food penalties if found to be true; will set to false after processing. */ bool m_IsTeleporting; bool m_IsVisible; /** The world tick in which eating will be finished. -1 if not eating */ cTickTimeLong m_EatingFinishTick; /** Player Xp level */ int m_LifetimeTotalXp; int m_CurrentXp; unsigned int m_EnchantmentSeed; int m_BowCharge; UInt32 m_FloaterID; cTeam * m_Team; /** The entity that this player is spectating, nullptr if none. */ cEntity * m_Spectating; StatisticsManager m_Stats; /** How long till the player's inventory will be saved Default save interval is #defined in PLAYER_INVENTORY_SAVE_INTERVAL */ unsigned int m_TicksUntilNextSave; AString m_CustomName; /** Displayed skin part bit mask */ int m_SkinParts; /** List on known recipes as Ids */ std::set m_KnownRecipes; /** List of known items as Ids */ std::set m_KnownItems; /** Called in each tick to handle food-related processing */ void HandleFood(void); /** Called in each tick if the player is fishing to make sure the floater dissapears when the player doesn't have a fishing rod as equipped item. */ void HandleFloater(void); /** Returns the filename for the player data based on the UUID given. This can be used both for online and offline UUIDs. */ AString GetUUIDFileName(const cUUID & a_UUID); /** Pins the player to a_Location until Unfreeze() is called. If ManuallyFrozen is false, the player will unfreeze when the chunk is loaded. */ void FreezeInternal(const Vector3d & a_Location, bool a_ManuallyFrozen); /** Returns how high the liquid is in percent. Used by IsInsideWater */ float GetLiquidHeightPercent(NIBBLETYPE a_Meta); /** Checks if the player is inside of water */ bool IsInsideWater(); /** Returns the dig speed using the current tool on the block a_Block. Returns one if using hand. If the player is using a tool that is good to break the block the value is higher. If he has an enchanted tool with efficiency or he has a haste or mining fatique effect it gets multiplied by a specific factor depending on the strength of the effect or enchantment. In he is in water it gets divided by 5 except if his tool is enchanted with aqua affinity. If he is not on ground it also gets divided by 5. Source: https://minecraft.wiki/w/Breaking#Calculation */ float GetDigSpeed(BLOCKTYPE a_Block); /** Add the recipe Id to the known recipes. If the recipe is already known, does nothing. */ void AddKnownRecipe(UInt32 RecipeId); void TickFreezeCode(); /** (Re)loads the rank and permissions from the cRankManager. Loads the m_Rank, m_Permissions, m_MsgPrefix, m_MsgSuffix and m_MsgNameColorCode members. */ void RefreshRank(); // cEntity overrides: virtual void ApplyArmorDamage(int DamageBlocked) override; virtual void BroadcastMovementUpdate(const cClientHandle * a_Exclude = nullptr) override; virtual bool DoTakeDamage(TakeDamageInfo & TDI) override; virtual float GetEnchantmentBlastKnockbackReduction() override; virtual void HandlePhysics(std::chrono::milliseconds a_Dt, cChunk &) override { UNUSED(a_Dt); } virtual bool IsElytraFlying(void) const override; virtual bool IsInvisible() const override; virtual bool IsRclking(void) const override { return IsEating() || IsChargingBow(); } virtual void OnAddToWorld(cWorld & a_World) override; virtual void OnDetach() override; virtual void OnRemoveFromWorld(cWorld & a_World) override; virtual void SpawnOn(cClientHandle & a_Client) override; virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; } ; // tolua_export ================================================ FILE: src/Entities/ProjectileEntity.cpp ================================================ // ProjectileEntity.cpp // Implements the cProjectileEntity class representing the common base class for projectiles, as well as individual projectile types #include "Globals.h" #include "../Bindings/PluginManager.h" #include "ProjectileEntity.h" #include "../BlockInfo.h" #include "../ClientHandle.h" #include "../LineBlockTracer.h" #include "../BoundingBox.h" #include "../ChunkMap.h" #include "../Chunk.h" #include "ArrowEntity.h" #include "ThrownEggEntity.h" #include "ThrownEnderPearlEntity.h" #include "ExpBottleEntity.h" #include "ThrownSnowballEntity.h" #include "FireChargeEntity.h" #include "FireworkEntity.h" #include "GhastFireballEntity.h" #include "WitherSkullEntity.h" #include "SplashPotionEntity.h" #include "Player.h" //////////////////////////////////////////////////////////////////////////////// // cProjectileTracerCallback: class cProjectileTracerCallback : public cBlockTracer::cCallbacks { public: cProjectileTracerCallback(cProjectileEntity * a_Projectile) : m_Projectile(a_Projectile), m_SlowdownCoeff(0.99) // Default slowdown when not in water { } double GetSlowdownCoeff(void) const { return m_SlowdownCoeff; } protected: cProjectileEntity * m_Projectile; double m_SlowdownCoeff; // cCallbacks overrides: virtual bool OnNextBlock(Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, eBlockFace a_EntryFace) override { /* // DEBUG: FLOGD("Hit block {0}:{1} at {2} face {3}, {4} ({5})", a_BlockType, a_BlockMeta, Vector3i{a_BlockX, a_BlockY, a_BlockZ}, a_EntryFace, cBlockInfo::IsSolid(a_BlockType) ? "solid" : "non-solid", ItemToString(cItem(a_BlockType, 1, a_BlockMeta)) ); */ if (cBlockInfo::IsSolid(a_BlockType)) { // The projectile hit a solid block, calculate the exact hit coords: cBoundingBox bb(a_BlockPos, a_BlockPos + Vector3i(1, 1, 1)); // Bounding box of the block hit const Vector3d LineStart = m_Projectile->GetPosition(); // Start point for the imaginary line that goes through the block hit const Vector3d LineEnd = LineStart + m_Projectile->GetSpeed(); // End point for the imaginary line that goes through the block hit double LineCoeff = 0; // Used to calculate where along the line an intersection with the bounding box occurs eBlockFace Face; // Face hit if (bb.CalcLineIntersection(LineStart, LineEnd, LineCoeff, Face)) { Vector3d Intersection = LineStart + m_Projectile->GetSpeed() * LineCoeff; // Point where projectile goes into the hit block if (cPluginManager::Get()->CallHookProjectileHitBlock(*m_Projectile, a_BlockPos, Face, Intersection)) { return false; } m_Projectile->OnHitSolidBlock(Intersection, Face); return true; } else { LOGD("WEIRD! block tracer reports a hit, but BBox tracer doesn't. Ignoring the hit."); } } // Convey some special effects from special blocks: switch (a_BlockType) { case E_BLOCK_LAVA: case E_BLOCK_STATIONARY_LAVA: { m_Projectile->StartBurning(30); m_SlowdownCoeff = std::min(m_SlowdownCoeff, 0.9); // Slow down to 0.9* the speed each tick when moving through lava break; } case E_BLOCK_WATER: case E_BLOCK_STATIONARY_WATER: { m_Projectile->StopBurning(); m_SlowdownCoeff = std::min(m_SlowdownCoeff, 0.8); // Slow down to 0.8* the speed each tick when moving through water break; } } // switch (a_BlockType) // Continue tracing return false; } } ; //////////////////////////////////////////////////////////////////////////////// // cProjectileEntityCollisionCallback: class cProjectileEntityCollisionCallback { public: cProjectileEntityCollisionCallback(cProjectileEntity * a_Projectile, const Vector3d & a_Pos, const Vector3d & a_NextPos) : m_Projectile(a_Projectile), m_Pos(a_Pos), m_NextPos(a_NextPos), m_MinCoeff(1), m_HitEntity(nullptr) { } bool operator () (cEntity & a_Entity) { if ( (&a_Entity == m_Projectile) || // Do not check collisions with self (a_Entity.GetUniqueID() == m_Projectile->GetCreatorUniqueID()) // Do not check whoever shot the projectile ) { // Don't check creator only for the first 5 ticks so that projectiles can collide with the creator if (m_Projectile->GetTicksAlive() <= 5) { return false; } } auto EntBox = a_Entity.GetBoundingBox(); // Instead of colliding the bounding box with another bounding box in motion, we collide an enlarged bounding box with a hairline. // The results should be good enough for our purposes double LineCoeff; eBlockFace Face; EntBox.Expand(m_Projectile->GetWidth() / 2, m_Projectile->GetHeight() / 2, m_Projectile->GetWidth() / 2); if (!EntBox.CalcLineIntersection(m_Pos, m_NextPos, LineCoeff, Face)) { // No intersection whatsoever return false; } if ( !a_Entity.IsMob() && !a_Entity.IsMinecart() && ( !a_Entity.IsPlayer() || static_cast(a_Entity).IsGameModeSpectator() ) && !a_Entity.IsBoat() && !a_Entity.IsEnderCrystal() ) { // Not an entity that interacts with a projectile return false; } if (cPluginManager::Get()->CallHookProjectileHitEntity(*m_Projectile, a_Entity)) { // A plugin disagreed. return false; } if (LineCoeff < m_MinCoeff) { // The entity is closer than anything we've stored so far, replace it as the potential victim m_MinCoeff = LineCoeff; m_HitEntity = &a_Entity; } // Don't break the enumeration, we want all the entities return false; } /** Returns the nearest entity that was hit, after the enumeration has been completed */ cEntity * GetHitEntity(void) const { return m_HitEntity; } /** Returns the line coeff where the hit was encountered, after the enumeration has been completed */ double GetMinCoeff(void) const { return m_MinCoeff; } /** Returns true if the callback has encountered a true hit */ bool HasHit(void) const { return (m_MinCoeff < 1); } protected: cProjectileEntity * m_Projectile; const Vector3d & m_Pos; const Vector3d & m_NextPos; double m_MinCoeff; // The coefficient of the nearest hit on the Pos line // Although it's bad(tm) to store entity ptrs from a callback, we can afford it here, because the entire callback // is processed inside the tick thread, so the entities won't be removed in between the calls and the final processing cEntity * m_HitEntity; // The nearest hit entity } ; //////////////////////////////////////////////////////////////////////////////// // cProjectileEntity: cProjectileEntity::cProjectileEntity(eKind a_Kind, cEntity * a_Creator, Vector3d a_Pos, float a_Width, float a_Height): Super(etProjectile, a_Pos, a_Width, a_Height), m_ProjectileKind(a_Kind), m_CreatorData( ((a_Creator != nullptr) ? a_Creator->GetUniqueID() : cEntity::INVALID_ID), ((a_Creator != nullptr) ? (a_Creator->IsPlayer() ? static_cast(a_Creator)->GetName() : "") : ""), ((a_Creator != nullptr) ? a_Creator->GetEquippedWeapon().m_Enchantments : cEnchantments()) ), m_IsInGround(false) { SetGravity(-12.0f); SetAirDrag(0.01f); } cProjectileEntity::cProjectileEntity(eKind a_Kind, cEntity * a_Creator, Vector3d a_Pos, Vector3d a_Speed, float a_Width, float a_Height): cProjectileEntity(a_Kind, a_Creator, a_Pos, a_Width, a_Height) { SetSpeed(a_Speed); SetYawFromSpeed(); SetPitchFromSpeed(); } std::unique_ptr cProjectileEntity::Create( eKind a_Kind, cEntity * a_Creator, Vector3d a_Pos, const cItem * a_Item, const Vector3d * a_Speed ) { Vector3d Speed; if (a_Speed != nullptr) { Speed = *a_Speed; } switch (a_Kind) { case pkArrow: return std::make_unique (a_Creator, a_Pos, Speed); case pkEgg: return std::make_unique (a_Creator, a_Pos, Speed); case pkEnderPearl: return std::make_unique(a_Creator, a_Pos, Speed); case pkSnowball: return std::make_unique (a_Creator, a_Pos, Speed); case pkGhastFireball: return std::make_unique (a_Creator, a_Pos, Speed); case pkFireCharge: return std::make_unique (a_Creator, a_Pos, Speed); case pkExpBottle: return std::make_unique (a_Creator, a_Pos, Speed); case pkSplashPotion: return std::make_unique (a_Creator, a_Pos, Speed, *a_Item); case pkWitherSkull: return std::make_unique (a_Creator, a_Pos, Speed); case pkFirework: { ASSERT(a_Item != nullptr); if (a_Item->m_FireworkItem.m_Colours.empty()) { return nullptr; } return std::make_unique(a_Creator, a_Pos, *a_Item); } } LOGWARNING("%s: Unknown projectile kind: %d", __FUNCTION__, a_Kind); return nullptr; } void cProjectileEntity::OnHitSolidBlock(Vector3d a_HitPos, eBlockFace a_HitFace) { // Set the position based on what face was hit: SetPosition(a_HitPos); SetSpeed(0, 0, 0); // DEBUG: FLOGD("Projectile {0}: pos {1:.02f}, hit solid block at face {2}", m_UniqueID, a_HitPos, a_HitFace ); m_IsInGround = true; } void cProjectileEntity::OnHitEntity(cEntity & a_EntityHit, Vector3d a_HitPos) { UNUSED(a_HitPos); // If we were created by a player and we hit a pawn, notify attacking player's wolves if (a_EntityHit.IsPawn() && (GetCreatorName() != "")) { auto EntityHit = static_cast(&a_EntityHit); m_World->DoWithEntityByID(GetCreatorUniqueID(), [=](cEntity & a_Hitter) { static_cast(a_Hitter).NotifyNearbyWolves(EntityHit, true); return true; } ); } } AString cProjectileEntity::GetMCAClassName(void) const { switch (m_ProjectileKind) { case pkArrow: return "Arrow"; case pkSnowball: return "Snowball"; case pkEgg: return "Egg"; case pkGhastFireball: return "Fireball"; case pkFireCharge: return "SmallFireball"; case pkEnderPearl: return "ThrownEnderpearl"; case pkExpBottle: return "ThrownExpBottle"; case pkSplashPotion: return "SplashPotion"; case pkWitherSkull: return "WitherSkull"; case pkFirework: return "Firework"; } UNREACHABLE("Unsupported projectile kind"); } void cProjectileEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { Super::Tick(a_Dt, a_Chunk); if (!IsTicking()) { // The base class tick destroyed us return; } BroadcastMovementUpdate(); } void cProjectileEntity::HandlePhysics(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { if (m_IsInGround) { // Already-grounded projectiles don't move at all return; } auto DtSec = std::chrono::duration_cast>(a_Dt); const Vector3d DeltaSpeed = GetSpeed() * DtSec.count(); const Vector3d Pos = GetPosition(); const Vector3d NextPos = Pos + DeltaSpeed; // Test for entity collisions: cProjectileEntityCollisionCallback EntityCollisionCallback(this, Pos, NextPos); a_Chunk.ForEachEntity(EntityCollisionCallback); if (EntityCollisionCallback.HasHit()) { // An entity was hit: Vector3d HitPos = Pos + (NextPos - Pos) * EntityCollisionCallback.GetMinCoeff(); // DEBUG: FLOGD("Projectile {0} has hit an entity {1} ({2}) at {3:.02f} (coeff {4:.03f})", m_UniqueID, EntityCollisionCallback.GetHitEntity()->GetUniqueID(), EntityCollisionCallback.GetHitEntity()->GetClass(), HitPos, EntityCollisionCallback.GetMinCoeff() ); OnHitEntity(*(EntityCollisionCallback.GetHitEntity()), HitPos); if (!IsTicking()) { return; // We were destroyed by an override of OnHitEntity } } // TODO: Test the entities in the neighboring chunks, too // Trace the tick's worth of movement as a line: cProjectileTracerCallback TracerCallback(this); if (!cLineBlockTracer::Trace(*m_World, TracerCallback, Pos, NextPos)) { // Something has been hit, abort all other processing return; } // The tracer also checks the blocks for slowdown blocks - water and lava - and stores it for later in its SlowdownCoeff // Update the position: SetPosition(NextPos); // Add slowdown and gravity effect to the speed: Vector3d NewSpeed(GetSpeed()); NewSpeed.y += m_Gravity * DtSec.count(); NewSpeed -= NewSpeed * (m_AirDrag * 20.0f) * DtSec.count(); SetSpeed(NewSpeed); SetYawFromSpeed(); SetPitchFromSpeed(); /* FLOGD("Projectile {0}: pos {1:.02f}, speed {2:.02f}, rot {{{3:.02f}, {4:.02f}}}", m_UniqueID, GetPos(), GetSpeed(), GetYaw(), GetPitch() ); */ } void cProjectileEntity::SpawnOn(cClientHandle & a_Client) { a_Client.SendSpawnEntity(*this); a_Client.SendEntityMetadata(*this); } void cProjectileEntity::CollectedBy(cPlayer & a_Dest) { // Overriden in arrow UNUSED(a_Dest); } ================================================ FILE: src/Entities/ProjectileEntity.h ================================================ // ProjectileEntity.h // Declares the cProjectileEntity class representing the common base class for projectiles #pragma once #include "Entity.h" // tolua_begin class cProjectileEntity : public cEntity { // tolua_end using Super = cEntity; // tolua_begin public: /** The kind of the projectile. */ enum eKind { pkArrow, pkSnowball, pkEgg, pkGhastFireball, pkFireCharge, pkEnderPearl, pkExpBottle, pkSplashPotion, pkFirework, pkWitherSkull, } ; // tolua_end CLASS_PROTODEF(cProjectileEntity) cProjectileEntity(eKind a_Kind, cEntity * a_Creator, Vector3d a_Pos, float a_Width, float a_Height); cProjectileEntity(eKind a_Kind, cEntity * a_Creator, Vector3d a_Pos, Vector3d a_Speed, float a_Width, float a_Height); /** Creates a new instance of the specified projectile entity. a_Item is the item from which the projectile originated (such as firework or arrow). */ static std::unique_ptr Create( eKind a_Kind, cEntity * a_Creator, Vector3d a_Pos, const cItem * a_Item, const Vector3d * a_Speed = nullptr ); /** OBSOLETE, use the Vector3d-based overload instead. Creates a new instance of the specified projectile entity. a_Item is the item from which the projectile originated (such as firework or arrow). */ static std::unique_ptr Create( eKind a_Kind, cEntity * a_Creator, double a_PosX, double a_PosY, double a_PosZ, const cItem * a_Item, const Vector3d * a_Speed = nullptr ) { return Create(a_Kind, a_Creator, {a_PosX, a_PosY, a_PosZ}, a_Item, a_Speed); } /** Called by the physics blocktracer when the entity hits a solid block, the hit position and the face hit (BLOCK_FACE_) is given */ virtual void OnHitSolidBlock(Vector3d a_HitPos, eBlockFace a_HitFace); /** Called by the physics blocktracer when the entity hits another entity */ virtual void OnHitEntity(cEntity & a_EntityHit, Vector3d a_HitPos); /** Called by Chunk when the projectile is eligible for player collection */ virtual void CollectedBy(cPlayer & a_Dest); // tolua_begin /** Returns the kind of the projectile (fast class identification) */ eKind GetProjectileKind(void) const { return m_ProjectileKind; } /** Returns the unique ID of the entity who created this projectile May return an ID <0 */ UInt32 GetCreatorUniqueID(void) const { return m_CreatorData.m_UniqueID; } /** Returns the name of the player that created the projectile Will be empty for non-player creators */ AString GetCreatorName(void) const { return m_CreatorData.m_Name; } /** Returns the string that is used as the entity type (class name) in MCA files */ AString GetMCAClassName(void) const; /** Returns true if the projectile has hit the ground and is stuck there */ bool IsInGround(void) const { return m_IsInGround; } // tolua_end /** Sets the internal InGround flag. To be used by MCA loader only! */ void SetIsInGround(bool a_IsInGround) { m_IsInGround = a_IsInGround; } protected: /** A structure that stores the Entity ID and Playername of the projectile's creator Used to migitate invalid pointers caused by the creator being destroyed. */ struct CreatorData { CreatorData(UInt32 a_UniqueID, const AString & a_Name, const cEnchantments & a_Enchantments) : m_UniqueID(a_UniqueID), m_Name(a_Name), m_Enchantments(a_Enchantments) { } const UInt32 m_UniqueID; AString m_Name; cEnchantments m_Enchantments; }; /** The type of projectile I am */ eKind m_ProjectileKind; /** The structure for containing the entity ID and name who has created this projectile The ID and / or name may be nullptr (e.g. for dispensers / mobs). */ CreatorData m_CreatorData; /** True if the projectile has hit the ground and is stuck there */ bool m_IsInGround; // cEntity overrides: virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; virtual void HandlePhysics(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; virtual void SpawnOn(cClientHandle & a_Client) final override; } ; // tolua_export ================================================ FILE: src/Entities/SplashPotionEntity.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "SplashPotionEntity.h" #include "Pawn.h" #include "../EffectID.h" //////////////////////////////////////////////////////////////////////////////// // cSplashPotionEntity: cSplashPotionEntity::cSplashPotionEntity( cEntity * a_Creator, Vector3d a_Pos, Vector3d a_Speed, const cItem & a_Item ): Super(pkSplashPotion, a_Creator, a_Pos, a_Speed, 0.25f, 0.25f), m_Item(a_Item) { m_EntityEffectType = cEntityEffect::GetPotionEffectType(a_Item.m_ItemDamage); m_EntityEffect = cEntityEffect( cEntityEffect::GetPotionEffectDuration(a_Item.m_ItemDamage), cEntityEffect::GetPotionEffectIntensity(a_Item.m_ItemDamage) ); m_PotionColor = cEntityEffect::GetPotionColor(a_Item.m_ItemDamage); } void cSplashPotionEntity::Splash(Vector3d a_HitPos) { // Look for entities in 8.25 (width) x 4.25 (height) cuboid _centred_ on hit position: m_World->ForEachEntityInBox({ a_HitPos.addedY(-4.25 / 2), 8.25 / 2, 4.25 }, [this, a_HitPos](cEntity & a_Entity) { if (!a_Entity.IsPawn()) { // Not an entity that can take effects return false; } double SplashDistance = (a_Entity.GetPosition() - a_HitPos).Length(); double Reduction = -0.25 * SplashDistance + 1.0; // y = -0.25x + 1, where x is the distance from the player. Approximation for potion splash. Reduction = std::max(Reduction, 0.0); static_cast(a_Entity).AddEntityEffect(m_EntityEffectType, m_EntityEffect.GetDuration(), m_EntityEffect.GetIntensity(), Reduction); return false; }); m_World->BroadcastSoundParticleEffect( EffectID::PARTICLE_SPLASH_POTION, a_HitPos.Floor(), m_PotionColor ); } void cSplashPotionEntity::OnHitEntity(cEntity & a_EntityHit, Vector3d a_HitPos) { Super::OnHitEntity(a_EntityHit, a_HitPos); a_EntityHit.TakeDamage(dtRangedAttack, this, 0, 1); Splash(a_HitPos); Destroy(); } void cSplashPotionEntity::OnHitSolidBlock(Vector3d a_HitPos, eBlockFace a_HitFace) { Super::OnHitSolidBlock(a_HitPos, a_HitFace); Splash(a_HitPos); Destroy(); } ================================================ FILE: src/Entities/SplashPotionEntity.h ================================================ // SplashPotionEntity.h // Declares the cSplashPotionEntity class representing a splash potion that has been thrown #pragma once #include "ProjectileEntity.h" #include "EntityEffect.h" #include "../World.h" class cEntity; // tolua_begin class cSplashPotionEntity : public cProjectileEntity { // tolua_end using Super = cProjectileEntity; public: // tolua_export CLASS_PROTODEF(cSplashPotionEntity) cSplashPotionEntity( cEntity * a_Creator, Vector3d a_Pos, Vector3d a_Speed, const cItem & a_Item ); // tolua_begin cEntityEffect::eType GetEntityEffectType(void) const { return m_EntityEffectType; } int GetPotionColor(void) const { return m_PotionColor; } const cItem & GetItem(void) const { return m_Item; } void SetEntityEffectType(cEntityEffect::eType a_EntityEffectType) { m_EntityEffectType = a_EntityEffectType; } void SetPotionColor(int a_PotionColor) { m_PotionColor = a_PotionColor; } // tolua_end cEntityEffect GetEntityEffect(void) const { return m_EntityEffect; } void SetEntityEffect(cEntityEffect a_EntityEffect) { m_EntityEffect = a_EntityEffect; } private: cEntityEffect::eType m_EntityEffectType; cEntityEffect m_EntityEffect; int m_PotionColor; cItem m_Item; /** Splashes the potion, fires its particle effects and sounds @param a_HitPos The position where the potion will splash */ void Splash(Vector3d a_HitPos); // cProjectileEntity overrides: virtual void OnHitEntity(cEntity & a_EntityHit, Vector3d a_HitPos) override; virtual void OnHitSolidBlock(Vector3d a_HitPos, eBlockFace a_HitFace) override; } ; // tolua_export ================================================ FILE: src/Entities/TNTEntity.cpp ================================================ #include "Globals.h" #include "TNTEntity.h" #include "../World.h" #include "../ClientHandle.h" cTNTEntity::cTNTEntity(Vector3d a_Pos, unsigned a_FuseTicks) : Super(etTNT, a_Pos, 0.98f, 0.98f), m_FuseTicks(a_FuseTicks) { SetGravity(-16.0f); SetAirDrag(0.02f); } void cTNTEntity::SpawnOn(cClientHandle & a_ClientHandle) { a_ClientHandle.SendSpawnEntity(*this); m_bDirtyOrientation = false; // TODO: why? m_bDirtyHead = false; } void cTNTEntity::Explode(void) { FLOGD("BOOM at {0}", GetPosition()); // Destroy first so the Explodinator doesn't find us (when iterating through entities): Destroy(); // TODO: provided centred coordinates to all calls to DoExplosionAt, from entities and blocks // This is to ensure maximum efficiency of explosions m_World->DoExplosionAt(4.0, GetPosX(), GetPosY() + GetHeight() / 2, GetPosZ(), true, esPrimedTNT, this); } void cTNTEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { Super::Tick(a_Dt, a_Chunk); if (!IsTicking()) { // The base class tick destroyed us return; } BroadcastMovementUpdate(); if (m_FuseTicks > 0) { --m_FuseTicks; } if (m_FuseTicks == 0) { Explode(); } } ================================================ FILE: src/Entities/TNTEntity.h ================================================ #pragma once #include "Entity.h" // tolua_begin class cTNTEntity: public cEntity { // tolua_end using Super = cEntity; public: // tolua_export CLASS_PROTODEF(cTNTEntity) cTNTEntity(Vector3d a_Pos, unsigned a_FuseTicks = 80); // cEntity overrides: virtual void SpawnOn(cClientHandle & a_ClientHandle) override; virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; // tolua_begin /** Explode the tnt */ void Explode(void); /** Returns the fuse ticks until the tnt will explode */ unsigned GetFuseTicks(void) const { return m_FuseTicks; } /** Set the fuse ticks until the tnt will explode */ void SetFuseTicks(unsigned a_FuseTicks) { m_FuseTicks = a_FuseTicks; } // tolua_end protected: unsigned m_FuseTicks; ///< How much ticks is left, while the tnt will explode }; // tolua_export ================================================ FILE: src/Entities/ThrownEggEntity.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "ThrownEggEntity.h" #include "../World.h" cThrownEggEntity::cThrownEggEntity(cEntity * a_Creator, Vector3d a_Pos, Vector3d a_Speed): Super(pkEgg, a_Creator, a_Pos, a_Speed, 0.25f, 0.25f) { } void cThrownEggEntity::OnHitEntity(cEntity & a_EntityHit, Vector3d a_HitPos) { Super::OnHitEntity(a_EntityHit, a_HitPos); int Damage = 0; if (a_EntityHit.IsMob() && (static_cast(a_EntityHit).GetMobType() == mtEnderDragon)) { // Enderdragons take 1 damage: Damage = 1; } else if (a_EntityHit.IsEnderCrystal()) { // Endercrystals are destroyed: Damage = CeilC(a_EntityHit.GetHealth()); } a_EntityHit.TakeDamage(dtRangedAttack, GetCreatorUniqueID(), Damage, 1); m_World->BroadcastEntityAnimation(*this, EntityAnimation::EggCracks); TrySpawnChicken(a_HitPos); Destroy(); } void cThrownEggEntity::OnHitSolidBlock(Vector3d a_HitPos, eBlockFace a_HitFace) { Super::OnHitSolidBlock(a_HitPos, a_HitFace); m_World->BroadcastEntityAnimation(*this, EntityAnimation::EggCracks); TrySpawnChicken(a_HitPos); Destroy(); } void cThrownEggEntity::TrySpawnChicken(Vector3d a_HitPos) { auto & Random = GetRandomProvider(); if (Random.RandBool(0.125)) { m_World->SpawnMob(a_HitPos.x, a_HitPos.y, a_HitPos.z, mtChicken, true); } else if (Random.RandBool(1.0 / 33.0)) { m_World->SpawnMob(a_HitPos.x, a_HitPos.y, a_HitPos.z, mtChicken, true); m_World->SpawnMob(a_HitPos.x, a_HitPos.y, a_HitPos.z, mtChicken, true); m_World->SpawnMob(a_HitPos.x, a_HitPos.y, a_HitPos.z, mtChicken, true); m_World->SpawnMob(a_HitPos.x, a_HitPos.y, a_HitPos.z, mtChicken, true); } } ================================================ FILE: src/Entities/ThrownEggEntity.h ================================================ // ThrownEggEntity.h // Declares the cThrownEggEntity class representing a regular thrown egg #pragma once #include "ProjectileEntity.h" // tolua_begin class cThrownEggEntity : public cProjectileEntity { // tolua_end using Super = cProjectileEntity; public: // tolua_export CLASS_PROTODEF(cThrownEggEntity) cThrownEggEntity(cEntity * a_Creator, Vector3d a_Pos, Vector3d a_Speed); private: /** Randomly decides whether to spawn a chicken where the egg lands. */ void TrySpawnChicken(Vector3d a_HitPos); // cProjectileEntity overrides: virtual void OnHitEntity(cEntity & a_EntityHit, Vector3d a_HitPos) override; virtual void OnHitSolidBlock(Vector3d a_HitPos, eBlockFace a_HitFace) override; } ; // tolua_export ================================================ FILE: src/Entities/ThrownEnderPearlEntity.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "FastRandom.h" #include "Mobs/MonsterTypes.h" #include "ThrownEnderPearlEntity.h" #include "Player.h" cThrownEnderPearlEntity::cThrownEnderPearlEntity(cEntity * a_Creator, Vector3d a_Pos, Vector3d a_Speed): Super(pkEnderPearl, a_Creator, a_Pos, a_Speed, 0.25f, 0.25f) { } void cThrownEnderPearlEntity::OnHitEntity(cEntity & a_EntityHit, Vector3d a_HitPos) { Super::OnHitEntity(a_EntityHit, a_HitPos); int Damage = 0; if (a_EntityHit.IsEnderCrystal()) { // Endercrystals are destroyed: Damage = CeilC(a_EntityHit.GetHealth()); } a_EntityHit.TakeDamage(dtRangedAttack, this, Damage, 1); TeleportCreator(a_HitPos); Destroy(); } void cThrownEnderPearlEntity::OnHitSolidBlock(Vector3d a_HitPos, eBlockFace a_HitFace) { Super::OnHitSolidBlock(a_HitPos, a_HitFace); TeleportCreator(a_HitPos); Destroy(); } void cThrownEnderPearlEntity::TeleportCreator(Vector3d a_HitPos) { if (m_CreatorData.m_Name.empty()) { return; } GetWorld()->FindAndDoWithPlayer(m_CreatorData.m_Name, [=](cPlayer & a_Entity) { auto & Random = GetRandomProvider(); // 5% chance to spawn an endermite if (Random.RandBool(0.05)) { Vector3d PlayerPosition = a_Entity.GetPosition(); m_World->SpawnMob(PlayerPosition.x, PlayerPosition.y, PlayerPosition.z, mtEndermite); } // Teleport the creator here, make them take 5 damage: a_Entity.TeleportToCoords(a_HitPos.x, a_HitPos.y + 0.2, a_HitPos.z); a_Entity.TakeDamage(dtEnderPearl, this, 5, 0); return false; }); } ================================================ FILE: src/Entities/ThrownEnderPearlEntity.h ================================================ // ThrownEnderPearlEntity.h // Declares the cThrownEnderPeralEntity class representing an ender pearl being thrown #pragma once #include "ProjectileEntity.h" // tolua_begin class cThrownEnderPearlEntity : public cProjectileEntity { // tolua_end using Super = cProjectileEntity; public: // tolua_export CLASS_PROTODEF(cThrownEnderPearlEntity) cThrownEnderPearlEntity(cEntity * a_Creator, Vector3d a_Pos, Vector3d a_Speed); private: /** Teleports the creator where the ender pearl lands */ void TeleportCreator(Vector3d a_HitPos); // cProjectileEntity overrides: virtual void OnHitEntity(cEntity & a_EntityHit, Vector3d a_HitPos) override; virtual void OnHitSolidBlock(Vector3d a_HitPos, eBlockFace a_HitFace) override; } ; // tolua_export ================================================ FILE: src/Entities/ThrownSnowballEntity.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "ThrownSnowballEntity.h" #include "../World.h" cThrownSnowballEntity::cThrownSnowballEntity(cEntity * a_Creator, Vector3d a_Pos, Vector3d a_Speed): Super(pkSnowball, a_Creator, a_Pos, a_Speed, 0.25f, 0.25f) { } void cThrownSnowballEntity::OnHitEntity(cEntity & a_EntityHit, Vector3d a_HitPos) { Super::OnHitEntity(a_EntityHit, a_HitPos); int Damage = 0; if (a_EntityHit.IsMob() && (static_cast(a_EntityHit).GetMobType() == mtBlaze)) { // Blazes take 3 damage: Damage = 3; } else if (a_EntityHit.IsEnderCrystal()) { // Endercrystals are destroyed: Damage = CeilC(a_EntityHit.GetHealth()); } a_EntityHit.TakeDamage(dtRangedAttack, GetCreatorUniqueID(), Damage, 1); m_World->BroadcastEntityAnimation(*this, EntityAnimation::SnowballPoofs); Destroy(); } void cThrownSnowballEntity::OnHitSolidBlock(Vector3d a_HitPos, eBlockFace a_HitFace) { Super::OnHitSolidBlock(a_HitPos, a_HitFace); m_World->BroadcastEntityAnimation(*this, EntityAnimation::SnowballPoofs); Destroy(); } ================================================ FILE: src/Entities/ThrownSnowballEntity.h ================================================ // ThrownSnowballEntity.h // Declares the cThrownSnowballEntity representing a snowball that has been thrown #pragma once #include "ProjectileEntity.h" // tolua_begin class cThrownSnowballEntity : public cProjectileEntity { // tolua_end using Super = cProjectileEntity; public: // tolua_export CLASS_PROTODEF(cThrownSnowballEntity) cThrownSnowballEntity(cEntity * a_Creator, Vector3d a_Pos, Vector3d a_Speed); private: // cProjectileEntity overrides: virtual void OnHitEntity(cEntity & a_EntityHit, Vector3d a_HitPos) override; virtual void OnHitSolidBlock(Vector3d a_HitPos, eBlockFace a_HitFace) override; } ; // tolua_export ================================================ FILE: src/Entities/WitherSkullEntity.cpp ================================================ // WitherSkullEntity.cpp // Implements the cWitherSkullEntity class representing the entity used by both blue and black wither skulls #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "WitherSkullEntity.h" #include "../World.h" cWitherSkullEntity::cWitherSkullEntity(cEntity * a_Creator, Vector3d a_Pos, Vector3d a_Speed): Super(pkWitherSkull, a_Creator, a_Pos, 0.3125f, 0.3125f) { SetSpeed(a_Speed); SetGravity(0); SetAirDrag(0); } void cWitherSkullEntity::OnHitSolidBlock(Vector3d a_HitPos, eBlockFace a_HitFace) { // TODO: Explode // TODO: Apply wither effect to entities nearby Destroy(); } void cWitherSkullEntity::OnHitEntity(cEntity & a_EntityHit, Vector3d a_HitPos) { // TODO: If entity is Ender Crystal, destroy it a_EntityHit.TakeDamage(dtRangedAttack, this, 0, 1); // TODO: Explode // TODO: Apply wither effect to entity and others nearby Destroy(); } ================================================ FILE: src/Entities/WitherSkullEntity.h ================================================ // WitherSkullEntity.h // Declares the cWitherSkullEntity class representing the entity used by both blue and black wither skulls #pragma once #include "ProjectileEntity.h" // tolua_begin class cWitherSkullEntity : public cProjectileEntity { // tolua_end using Super = cProjectileEntity; public: // tolua_export CLASS_PROTODEF(cWitherSkullEntity) cWitherSkullEntity(cEntity * a_Creator, Vector3d a_Pos, Vector3d a_Speed); protected: // cProjectileEntity overrides: virtual void OnHitSolidBlock(Vector3d a_HitPos, eBlockFace a_HitFace) override; virtual void OnHitEntity(cEntity & a_EntityHit, Vector3d a_HitPos) override; } ; // tolua_export ================================================ FILE: src/FastRandom.cpp ================================================ // FastRandom.cpp #include "Globals.h" #include "FastRandom.h" MTRand & GetRandomProvider() { thread_local MTRand Random = [] { cRandomDeviceSeeder Seeder; return MTRand(Seeder); }(); return Random; } UInt32 Detail::GetRandomSeed() { thread_local UInt32 SeedCounter = [] { std::random_device rd; std::uniform_int_distribution dist; return dist(rd); }(); return ++SeedCounter; } ================================================ FILE: src/FastRandom.h ================================================ // FastRandom.h // Declares the cFastRandom class representing a fast random number generator /* The cFastRandom alias should be avoided in favor of the result of a call to GetRandomProvider(). The MTRand generator used is faster, has a better range and provides higher quality randomness. Note that MTRand is relatively costly to construct and so instances should be long lived, prefer calls to GetRandomProvider over creating new instances. */ #pragma once namespace Detail { /** Returns a low quality seed. */ UInt32 GetRandomSeed(); /** Aliases true_type if Char is any variant of char ignoring signed-ness. */ template using IsChar = typename std::is_same::type, signed char>::type; template struct cUniformImpl : public std::conditional< IsChar::value, typename std::conditional< // Match signed-ness of IntType std::is_signed::value, std::uniform_int_distribution, std::uniform_int_distribution >::type, std::uniform_int_distribution > { }; /** uniform_int_distribution is undefined so this aliases a valid type. */ template using cUniform = typename cUniformImpl::type; } /** Class to wrap any random engine to provide a more convenient interface. */ template class cRandomWrapper { public: /** Initialize with a low quality seed. */ cRandomWrapper(): m_Engine(Detail::GetRandomSeed()) { } /** Initialize with a SeedSequence. */ template cRandomWrapper(SeedSeq & a_SeedSeq): m_Engine(a_SeedSeq) { } /** Return a random IntType in the range [a_Min, a_Max]. */ template IntType RandInt(IntType a_Min, IntType a_Max) { ASSERT( (a_Max >= a_Min) && (a_Max <= std::numeric_limits::max()) && (a_Min >= std::numeric_limits::min()) ); Detail::cUniform dist( static_cast(a_Min), static_cast(a_Max) ); return static_cast(dist(m_Engine)); } /** Return a random IntType in the range [0, a_Max]. */ template IntType RandInt(IntType a_Max) { ASSERT((a_Max >= 0) && (a_Max <= std::numeric_limits::max())); Detail::cUniform dist(IntType(0), static_cast(a_Max)); return static_cast(dist(m_Engine)); } /** Return a random IntType in the range [0, std::numeric_limits::max()]. */ template IntType RandInt() { Detail::cUniform dist(IntType(0), std::numeric_limits::max()); return static_cast(dist(m_Engine)); } /** Return a random RealType in the range [a_Min, a_Max). */ template RealType RandReal(RealType a_Min, RealType a_Max) { std::uniform_real_distribution dist(a_Min, a_Max); return dist(m_Engine); } /** Return a random RealType in the range [0, a_Max). */ template RealType RandReal(RealType a_Max) { std::uniform_real_distribution dist(RealType(0), a_Max); return dist(m_Engine); } /** Return a random RealType in the range [0, 1). */ template RealType RandReal() { std::uniform_real_distribution dist; return dist(m_Engine); } /** Return a random bool with the given probability of being true. */ bool RandBool(double a_TrueProbability = 0.5) { std::bernoulli_distribution dist(a_TrueProbability); return dist(m_Engine); } /** Returns a reference to the underlying random engine. */ RandomEngine & Engine() { return m_Engine; } private: RandomEngine m_Engine; }; /** Utility to seed a random engine with maximal entropy from random_device. */ struct cRandomDeviceSeeder { using result_type = std::random_device::result_type; template void generate(Itr first, Itr last) { std::random_device rd; std::uniform_int_distribution dist; for (; first != last; ++first) { *first = dist(rd); } } }; using cFastRandom = cRandomWrapper; using MTRand = cRandomWrapper; /** Returns the current thread's random number source. */ MTRand & GetRandomProvider(); ================================================ FILE: src/ForEachChunkProvider.h ================================================ // ForEachChunkProvider.h // Declares the cForEachChunkProvider class which acts as an interface for classes that provide a ForEachChunkInRect() function // Primarily serves as a decoupling between cBlockArea and cWorld #pragma once // fwd: class cChunkDataCallback; class cBlockArea; class cForEachChunkProvider { public: virtual ~cForEachChunkProvider() {} /** Calls the callback for each chunk in the specified range. */ virtual bool ForEachChunkInRect(int a_MinChunkX, int a_MaxChunkX, int a_MinChunkZ, int a_MaxChunkZ, cChunkDataCallback & a_Callback) = 0; /** Writes the block area into the specified coords. Returns true if all chunks have been processed. a_DataTypes is a bitmask of cBlockArea::baXXX constants ORed together. */ virtual bool WriteBlockArea(cBlockArea & a_Area, int a_MinBlockX, int a_MinBlockY, int a_MinBlockZ, int a_DataTypes) = 0; }; ================================================ FILE: src/FunctionRef.h ================================================ #pragma once // Declared only so it can be partially specialized template class cFunctionRef; /** A light-weight, type-erased reference to a function object. ### Usage `cFunctionRef` is used whenever you call a normal function with a lambda. e.g. one of the `cWorld::DoWith` functions, m_World->DoWithChunkAt(BlockPos, [](cChunk & a_Chunk) -> bool { ... } ); It looks like you're calling it with a lambda but that would require `DoWithChunkAt` to be a template. The function is really being called with `cFunctionRef` which is constructed from the lambda via a templated constructor. This gives you a generic pointer to the lambda which doesn't depend on the type of the function object it references. ### Notes - This is similar to a `std::function` but doesn't copy the function object. This means that mutable function objects will be modified for the caller but would not be if using a `std::function` (See #3990 for implications of this). - A `cFunctionRef` has no empty state but is non-owning and so is safe to call as long as the referred object is still alive. */ template class cFunctionRef { public: /** Construct from a function object. */ template ::type, cFunctionRef>::value, int>::type = 0 > cFunctionRef(FunctionObject && a_FunctionObject) { // Store an opaque reference to the object. m_CallableData = &a_FunctionObject; // Along with a function that knows how to call the object. m_CallFunction = &ObjectFunctionCaller; } /** Call the referenced function object */ Ret operator () (Args... a_Args) { return m_CallFunction(m_CallableData, std::forward(a_Args)...); } private: /** Function that performs the call. */ template static Ret ObjectFunctionCaller(void * a_Callable, Args... a_Args) { // Convert opaque reference to the concrete type. using ObjectPtr = typename std::add_pointer::type; auto & Object = *static_cast(a_Callable); // Forward the call down to the object. return Object(std::forward(a_Args)...); } using cCallFunction = Ret(*)(void *, Args...); /** Type erased reference to a callable. */ void * m_CallableData; /** Function that knows how to call the type erased reference. */ cCallFunction m_CallFunction; }; ================================================ FILE: src/FurnaceRecipe.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "FurnaceRecipe.h" #include "Item.h" #include #define FURNACE_RECIPE_FILE "furnace.txt" typedef std::list RecipeList; typedef std::list FuelList; struct cFurnaceRecipe::sFurnaceRecipeState { RecipeList Recipes; FuelList Fuel; }; cFurnaceRecipe::cFurnaceRecipe() : m_pState(new sFurnaceRecipeState) { ReloadRecipes(); } cFurnaceRecipe::~cFurnaceRecipe() { ClearRecipes(); delete m_pState; m_pState = nullptr; } void cFurnaceRecipe::ReloadRecipes(void) { ClearRecipes(); LOGD("Loading furnace recipes..."); std::ifstream f(FURNACE_RECIPE_FILE, std::ios::in); if (!f.good()) { LOG("Could not open the furnace recipes file \"%s\". No furnace recipes are available.", FURNACE_RECIPE_FILE); return; } unsigned int LineNum = 0; AString ParsingLine; while (std::getline(f, ParsingLine)) { LineNum++; // Remove comments from the line: size_t FirstCommentSymbol = ParsingLine.find('#'); if ((FirstCommentSymbol != AString::npos) && (FirstCommentSymbol != 0)) { ParsingLine.erase(ParsingLine.begin() + static_cast(FirstCommentSymbol), ParsingLine.end()); } if (IsOnlyWhitespace(ParsingLine)) { // Ignore empty and whitespace only lines continue; } switch (ParsingLine[0]) { case '#': { // Comment break; } case '!': { AddFuelFromLine(ParsingLine, LineNum); break; } default: { AddRecipeFromLine(ParsingLine, LineNum); break; } } // switch (ParsingLine[0]) } // while (getline(ParsingLine)) LOG("Loaded %zu furnace recipes and %zu fuels", m_pState->Recipes.size(), m_pState->Fuel.size()); } void cFurnaceRecipe::AddFuelFromLine(const AString & a_Line, unsigned int a_LineNum) { AString Line(a_Line); Line.erase(Line.begin()); // Remove the beginning "!" Line.erase(std::remove_if(Line.begin(), Line.end(), isspace), Line.end()); std::unique_ptr Item = std::make_unique(); int BurnTime; const AStringVector & Sides = StringSplit(Line, "="); if (Sides.size() != 2) { LOGWARNING("furnace.txt: line %d: A single '=' was expected, got %zu", a_LineNum, Sides.size() - 1); LOGINFO("Offending line: \"%s\"", a_Line.c_str()); return; } if (!ParseItem(Sides[0], *Item)) { LOGWARNING("furnace.txt: line %d: Cannot parse item \"%s\".", a_LineNum, Sides[0].c_str()); LOGINFO("Offending line: \"%s\"", a_Line.c_str()); return; } if (!StringToInteger(Sides[1], BurnTime)) { LOGWARNING("furnace.txt: line %d: Cannot parse burn time.", a_LineNum); LOGINFO("Offending line: \"%s\"", a_Line.c_str()); return; } // Add to fuel list: cFuel Fuel; Fuel.In = Item.release(); Fuel.BurnTime = BurnTime; m_pState->Fuel.push_back(Fuel); } void cFurnaceRecipe::AddRecipeFromLine(const AString & a_Line, unsigned int a_LineNum) { AString Line(a_Line); Line.erase(std::remove_if(Line.begin(), Line.end(), isspace), Line.end()); int CookTime = 200; float Reward = 0; std::unique_ptr InputItem = std::make_unique(); std::unique_ptr OutputItem = std::make_unique(); const AStringVector & Sides = StringSplit(Line, "="); if (Sides.size() != 2) { LOGWARNING("furnace.txt: line %d: A single '=' was expected, got %zu", a_LineNum, Sides.size() - 1); LOGINFO("Offending line: \"%s\"", a_Line.c_str()); return; } const AStringVector & InputSplit = StringSplit(Sides[0], "@"); if (!ParseItem(InputSplit[0], *InputItem)) { LOGWARNING("furnace.txt: line %d: Cannot parse input item \"%s\".", a_LineNum, InputSplit[0].c_str()); LOGINFO("Offending line: \"%s\"", a_Line.c_str()); return; } if (InputSplit.size() > 1) { if (!StringToInteger(InputSplit[1], CookTime)) { LOGWARNING("furnace.txt: line %d: Cannot parse cook time \"%s\".", a_LineNum, InputSplit[1].c_str()); LOGINFO("Offending line: \"%s\"", a_Line.c_str()); return; } } const AStringVector & OutputSplit = StringSplit(Sides[1], "$"); if (!ParseItem(OutputSplit[0], *OutputItem)) { LOGWARNING("furnace.txt: line %d: Cannot parse output item \"%s\".", a_LineNum, OutputSplit[0].c_str()); LOGINFO("Offending line: \"%s\"", a_Line.c_str()); return; } if (OutputSplit.size() > 1) { if (!StringToFloat(OutputSplit[1], Reward)) { LOGWARNING("furnace.txt: line %d: Cannot parse reward \"%s\".", a_LineNum, OutputSplit[1].c_str()); LOGINFO("Offending line: \"%s\"", a_Line.c_str()); return; } } cRecipe Recipe; Recipe.In = InputItem.release(); Recipe.Out = OutputItem.release(); Recipe.CookTime = CookTime; Recipe.Reward = Reward; m_pState->Recipes.push_back(Recipe); } bool cFurnaceRecipe::ParseItem(const AString & a_String, cItem & a_Item) { AString ItemString = a_String; const AStringVector & SplitAmount = StringSplit(ItemString, ","); ItemString = SplitAmount[0]; const AStringVector & SplitMeta = StringSplit(ItemString, ":"); ItemString = SplitMeta[0]; if (!StringToItem(ItemString, a_Item)) { return false; } if (SplitAmount.size() > 1) { if (!StringToInteger(SplitAmount[1], a_Item.m_ItemCount)) { return false; } } if (SplitMeta.size() > 1) { if (!StringToInteger(SplitMeta[1], a_Item.m_ItemDamage)) { return false; } } return true; } void cFurnaceRecipe::ClearRecipes(void) { for (RecipeList::iterator itr = m_pState->Recipes.begin(); itr != m_pState->Recipes.end(); ++itr) { cRecipe Recipe = *itr; delete Recipe.In; Recipe.In = nullptr; delete Recipe.Out; Recipe.Out = nullptr; } m_pState->Recipes.clear(); for (FuelList::iterator itr = m_pState->Fuel.begin(); itr != m_pState->Fuel.end(); ++itr) { cFuel Fuel = *itr; delete Fuel.In; Fuel.In = nullptr; } m_pState->Fuel.clear(); } const cFurnaceRecipe::cRecipe * cFurnaceRecipe::GetRecipeFrom(const cItem & a_Ingredient) const { const cRecipe * BestRecipe = nullptr; for (RecipeList::const_iterator itr = m_pState->Recipes.begin(); itr != m_pState->Recipes.end(); ++itr) { const cRecipe & Recipe = *itr; if ((Recipe.In->m_ItemType == a_Ingredient.m_ItemType) && (Recipe.In->m_ItemCount <= a_Ingredient.m_ItemCount)) { if (BestRecipe && (BestRecipe->In->m_ItemCount > Recipe.In->m_ItemCount)) { continue; } else if ((Recipe.In->m_ItemDamage == -1) || (Recipe.In->m_ItemDamage == a_Ingredient.m_ItemDamage)) { BestRecipe = &Recipe; } } } return BestRecipe; } bool cFurnaceRecipe::IsFuel(const cItem & a_Item) const { for (auto & Fuel : m_pState->Fuel) { if ((Fuel.In->m_ItemType == a_Item.m_ItemType) && (Fuel.In->m_ItemCount <= a_Item.m_ItemCount)) { return true; } } return false; } int cFurnaceRecipe::GetBurnTime(const cItem & a_Fuel) const { int BestFuel = 0; for (FuelList::const_iterator itr = m_pState->Fuel.begin(); itr != m_pState->Fuel.end(); ++itr) { const cFuel & Fuel = *itr; if ((Fuel.In->m_ItemType == a_Fuel.m_ItemType) && (Fuel.In->m_ItemCount <= a_Fuel.m_ItemCount)) { if (BestFuel > 0 && (BestFuel > Fuel.BurnTime)) { continue; } else { BestFuel = Fuel.BurnTime; } } } return BestFuel; } ================================================ FILE: src/FurnaceRecipe.h ================================================ #pragma once class cItem; class cFurnaceRecipe { public: cFurnaceRecipe(void); ~cFurnaceRecipe(); void ReloadRecipes(void); struct cFuel { cItem * In; int BurnTime; ///< How long this fuel burns, in ticks }; struct cRecipe { cItem * In; cItem * Out; int CookTime; ///< How long this recipe takes to smelt, in ticks float Reward; ///< Experience reward for creating 1 of this item }; /** Returns a recipe for the specified input, nullptr if no recipe found */ const cRecipe * GetRecipeFrom(const cItem & a_Ingredient) const; /** Returns true if the item is a fuel, false if not. */ bool IsFuel(const cItem & a_Item) const; /** Returns the amount of time that the specified fuel burns, in ticks */ int GetBurnTime(const cItem & a_Fuel) const; private: void ClearRecipes(void); /** Parses the fuel contained in the line, adds it to m_pState's fuels. Logs a warning to the console on input error. */ void AddFuelFromLine(const AString & a_Line, unsigned int a_LineNum); /** Parses the recipe contained in the line, adds it to m_pState's recipes. Logs a warning to the console on input error. */ void AddRecipeFromLine(const AString & a_Line, unsigned int a_LineNum); /** Parses an item string in the format "[: ][, ]", returns true if successful. */ bool ParseItem(const AString & a_String, cItem & a_Item); struct sFurnaceRecipeState; sFurnaceRecipeState * m_pState; }; ================================================ FILE: src/Generating/BioGen.cpp ================================================ // BioGen.cpp // Implements the various biome generators #include "Globals.h" #include "BioGen.h" #include "IntGen.h" #include "ProtIntGen.h" #include "../IniFile.h" #include "../LinearUpscale.h" //////////////////////////////////////////////////////////////////////////////// // cBioGenConstant: void cBioGenConstant::GenBiomes(cChunkCoords a_ChunkCoords, cChunkDef::BiomeMap & a_BiomeMap) { UNUSED(a_ChunkCoords); for (size_t i = 0; i < ARRAYCOUNT(a_BiomeMap); i++) { a_BiomeMap[i] = m_Biome; } } void cBioGenConstant::InitializeBiomeGen(cIniFile & a_IniFile) { AString defaultBiome; switch (StringToDimension(a_IniFile.GetValue("General", "Dimension", "Overworld"))) { case dimOverworld: defaultBiome = "Plains"; break; case dimNether: defaultBiome = "Nether"; break; case dimEnd: defaultBiome = "End"; break; case dimNotSet: defaultBiome = "Swampland"; break; } AString Biome = a_IniFile.GetValueSet("Generator", "ConstantBiome", defaultBiome); m_Biome = StringToBiome(Biome); if (m_Biome == biInvalidBiome) { LOGWARN("[Generator]::ConstantBiome value \"%s\" not recognized, using \"Plains\".", Biome.c_str()); m_Biome = biPlains; } } //////////////////////////////////////////////////////////////////////////////// // cBioGenCache: cBioGenCache::cBioGenCache(cBiomeGen & a_BioGenToCache, size_t a_CacheSize) : m_BioGenToCache(a_BioGenToCache), m_CacheSize(a_CacheSize), m_NumHits(0), m_NumMisses(0), m_TotalChain(0) { m_CacheData.resize(m_CacheSize); m_CacheOrder.resize(m_CacheSize); for (size_t i = 0; i < m_CacheSize; i++) { m_CacheOrder[i] = i; } } void cBioGenCache::GenBiomes(cChunkCoords a_ChunkCoords, cChunkDef::BiomeMap & a_BiomeMap) { if (((m_NumHits + m_NumMisses) % 1024) == 10) { // LOGD("BioGenCache: %u hits, %u misses, saved %.2f %%", static_cast(m_NumHits), static_cast(m_NumMisses), 100.0 * m_NumHits / (m_NumHits + m_NumMisses)); // LOGD("BioGenCache: Avg cache chain length: %.2f", static_cast(m_TotalChain) / m_NumHits); } for (size_t i = 0; i < m_CacheSize; i++) { if (m_CacheData[m_CacheOrder[i]].m_Coords != a_ChunkCoords) { continue; } // Found it in the cache size_t Idx = m_CacheOrder[i]; // Move to front: for (size_t j = i; j > 0; j--) { m_CacheOrder[j] = m_CacheOrder[j - 1]; } m_CacheOrder[0] = Idx; // Use the cached data: memcpy(a_BiomeMap, m_CacheData[Idx].m_BiomeMap, sizeof(a_BiomeMap)); m_NumHits++; m_TotalChain += i; return; } // for i - cache // Not in the cache: m_NumMisses++; m_BioGenToCache.GenBiomes(a_ChunkCoords, a_BiomeMap); // Insert it as the first item in the MRU order: size_t Idx = m_CacheOrder[m_CacheSize - 1]; for (size_t i = m_CacheSize - 1; i > 0; i--) { m_CacheOrder[i] = m_CacheOrder[i - 1]; } // for i - m_CacheOrder[] m_CacheOrder[0] = Idx; memcpy(m_CacheData[Idx].m_BiomeMap, a_BiomeMap, sizeof(a_BiomeMap)); m_CacheData[Idx].m_Coords = a_ChunkCoords; } void cBioGenCache::InitializeBiomeGen(cIniFile & a_IniFile) { Super::InitializeBiomeGen(a_IniFile); m_BioGenToCache.InitializeBiomeGen(a_IniFile); } //////////////////////////////////////////////////////////////////////////////// // cBioGenMulticache: cBioGenMulticache::cBioGenMulticache(std::unique_ptr a_BioGenToCache, size_t a_SubCacheSize, size_t a_NumSubCaches) : m_NumSubCaches(a_NumSubCaches), m_Underlying(std::move(a_BioGenToCache)) { m_Caches.reserve(a_NumSubCaches); for (size_t i = 0; i < a_NumSubCaches; i++) { m_Caches.push_back(std::make_unique(*m_Underlying, a_SubCacheSize)); } } void cBioGenMulticache::GenBiomes(cChunkCoords a_ChunkCoords, cChunkDef::BiomeMap & a_BiomeMap) { const size_t coefficient = 3; const size_t cacheIdx = (static_cast(a_ChunkCoords.m_ChunkX) + coefficient * static_cast(a_ChunkCoords.m_ChunkZ)) % m_NumSubCaches; m_Caches[cacheIdx]->GenBiomes(a_ChunkCoords, a_BiomeMap); } void cBioGenMulticache::InitializeBiomeGen(cIniFile & a_IniFile) { for (auto & itr : m_Caches) { itr->InitializeBiomeGen(a_IniFile); } } //////////////////////////////////////////////////////////////////////////////// // cBiomeGenList: void cBiomeGenList::InitializeBiomes(const AString & a_Biomes) { AStringVector Split = StringSplitAndTrim(a_Biomes, ","); // Convert each string in the list into biome: for (AStringVector::const_iterator itr = Split.begin(); itr != Split.end(); ++itr) { AStringVector Split2 = StringSplit(*itr, ":"); if (Split2.size() < 1) { continue; } int Count = 1; if (Split2.size() >= 2) { if (!StringToInteger(Split2[1], Count)) { LOGWARNING("Cannot decode biome count: \"%s\"; using 1.", Split2[1].c_str()); Count = 1; } } EMCSBiome Biome = StringToBiome(Split2[0]); if (Biome != biInvalidBiome) { for (int i = 0; i < Count; i++) { m_Biomes.push_back(Biome); } } else { LOGWARNING("Cannot decode biome name: \"%s\"; skipping", Split2[0].c_str()); } } // for itr - Split[] if (!m_Biomes.empty()) { m_BiomesCount = static_cast(m_Biomes.size()); return; } // There were no biomes, add default biomes: static EMCSBiome Biomes[] = { biOcean, biPlains, biDesert, biExtremeHills, biForest, biTaiga, biSwampland, biRiver, biFrozenOcean, biFrozenRiver, biIcePlains, biIceMountains, biMushroomIsland, biMushroomShore, biBeach, biDesertHills, biForestHills, biTaigaHills, biExtremeHillsEdge, biJungle, biJungleHills, } ; m_Biomes.reserve(ARRAYCOUNT(Biomes)); for (size_t i = 0; i < ARRAYCOUNT(Biomes); i++) { m_Biomes.push_back(Biomes[i]); } m_BiomesCount = static_cast(m_Biomes.size()); } //////////////////////////////////////////////////////////////////////////////// // cBioGenCheckerboard: void cBioGenCheckerboard::GenBiomes(cChunkCoords a_ChunkCoords, cChunkDef::BiomeMap & a_BiomeMap) { for (int z = 0; z < cChunkDef::Width; z++) { int Base = (cChunkDef::Width * a_ChunkCoords.m_ChunkZ + z) / m_BiomeSize; for (int x = 0; x < cChunkDef::Width; x++) { int Add = cChunkDef::Width * a_ChunkCoords.m_ChunkX + x; size_t BiomeIdx = static_cast((((Base + Add / m_BiomeSize) % m_BiomesCount) + m_BiomesCount) % m_BiomesCount); // Need to add and modulo twice because of negative numbers a_BiomeMap[x + cChunkDef::Width * z] = m_Biomes[BiomeIdx]; } } } void cBioGenCheckerboard::InitializeBiomeGen(cIniFile & a_IniFile) { Super::InitializeBiomeGen(a_IniFile); AString Biomes = a_IniFile.GetValueSet ("Generator", "CheckerBoardBiomes", ""); m_BiomeSize = a_IniFile.GetValueSetI("Generator", "CheckerboardBiomeSize", 64); m_BiomeSize = (m_BiomeSize < 8) ? 8 : m_BiomeSize; InitializeBiomes(Biomes); } //////////////////////////////////////////////////////////////////////////////// // cBioGenVoronoi : void cBioGenVoronoi::GenBiomes(cChunkCoords a_ChunkCoords, cChunkDef::BiomeMap & a_BiomeMap) { int BaseZ = cChunkDef::Width * a_ChunkCoords.m_ChunkZ; int BaseX = cChunkDef::Width * a_ChunkCoords.m_ChunkX; for (int z = 0; z < cChunkDef::Width; z++) { int AbsoluteZ = BaseZ + z; for (int x = 0; x < cChunkDef::Width; x++) { int VoronoiCellValue = m_Voronoi.GetValueAt(BaseX + x, AbsoluteZ) / 8; cChunkDef::SetBiome(a_BiomeMap, x, z, m_Biomes[static_cast(VoronoiCellValue % m_BiomesCount)]); } // for x } // for z } void cBioGenVoronoi::InitializeBiomeGen(cIniFile & a_IniFile) { Super::InitializeBiomeGen(a_IniFile); int CellSize = a_IniFile.GetValueSetI("Generator", "VoronoiCellSize", 128); int JitterSize = a_IniFile.GetValueSetI("Generator", "VoronoiJitterSize", CellSize); int OddRowOffset = a_IniFile.GetValueSetI("Generator", "VoronoiOddRowOffset", 0); m_Voronoi.SetCellSize(CellSize); m_Voronoi.SetJitterSize(JitterSize); m_Voronoi.SetOddRowOffset(OddRowOffset); InitializeBiomes(a_IniFile.GetValueSet ("Generator", "VoronoiBiomes", "")); } //////////////////////////////////////////////////////////////////////////////// // cBioGenDistortedVoronoi: void cBioGenDistortedVoronoi::GenBiomes(cChunkCoords a_ChunkCoords, cChunkDef::BiomeMap & a_BiomeMap) { int BaseZ = cChunkDef::Width * a_ChunkCoords.m_ChunkZ; int BaseX = cChunkDef::Width * a_ChunkCoords.m_ChunkX; // Distortions for linear interpolation: int DistortX[cChunkDef::Width + 1][cChunkDef::Width + 1]; int DistortZ[cChunkDef::Width + 1][cChunkDef::Width + 1]; for (int x = 0; x <= 4; x++) for (int z = 0; z <= 4; z++) { Distort(BaseX + x * 4, BaseZ + z * 4, DistortX[4 * x][4 * z], DistortZ[4 * x][4 * z]); } LinearUpscale2DArrayInPlace(&DistortX[0][0]); LinearUpscale2DArrayInPlace(&DistortZ[0][0]); for (int z = 0; z < cChunkDef::Width; z++) { for (int x = 0; x < cChunkDef::Width; x++) { int VoronoiCellValue = m_Voronoi.GetValueAt(DistortX[x][z], DistortZ[x][z]) / 8; cChunkDef::SetBiome(a_BiomeMap, x, z, m_Biomes[static_cast(VoronoiCellValue % m_BiomesCount)]); } // for x } // for z } void cBioGenDistortedVoronoi::InitializeBiomeGen(cIniFile & a_IniFile) { Super::InitializeBiomeGen(a_IniFile); m_CellSize = a_IniFile.GetValueSetI("Generator", "DistortedVoronoiCellSize", 96); m_Voronoi.SetCellSize(m_CellSize); InitializeBiomes(a_IniFile.GetValueSet("Generator", "DistortedVoronoiBiomes", "")); } void cBioGenDistortedVoronoi::Distort(int a_BlockX, int a_BlockZ, int & a_DistortedX, int & a_DistortedZ) { double NoiseX = m_Noise.CubicNoise3D(static_cast(a_BlockX / m_CellSize), static_cast(a_BlockZ / m_CellSize), 1000); NoiseX += 0.5 * m_Noise.CubicNoise3D(2 * static_cast(a_BlockX / m_CellSize), 2 * static_cast(a_BlockZ / m_CellSize), 2000); NoiseX += 0.08 * m_Noise.CubicNoise3D(16 * static_cast(a_BlockX / m_CellSize), 16 * static_cast(a_BlockZ / m_CellSize), 3000); double NoiseZ = m_Noise.CubicNoise3D(static_cast(a_BlockX / m_CellSize), static_cast(a_BlockZ / m_CellSize), 4000); NoiseZ += 0.5 * m_Noise.CubicNoise3D(2 * static_cast(a_BlockX / m_CellSize), 2 * static_cast(a_BlockZ / m_CellSize), 5000); NoiseZ += 0.08 * m_Noise.CubicNoise3D(16 * static_cast(a_BlockX / m_CellSize), 16 * static_cast(a_BlockZ / m_CellSize), 6000); a_DistortedX = a_BlockX + static_cast(m_CellSize * 0.5 * NoiseX); a_DistortedZ = a_BlockZ + static_cast(m_CellSize * 0.5 * NoiseZ); } //////////////////////////////////////////////////////////////////////////////// // cBioGenMultiStepMap : cBioGenMultiStepMap::cBioGenMultiStepMap(int a_Seed) : m_Noise1(a_Seed + 1000), m_Noise2(a_Seed + 2000), m_Noise3(a_Seed + 3000), m_Noise4(a_Seed + 4000), m_Noise5(a_Seed + 5000), m_Noise6(a_Seed + 6000), m_Seed(a_Seed), m_OceanCellSize(384), m_MushroomIslandSize(64), m_RiverCellSize(384), m_RiverWidthThreshold(0.125), m_LandBiomesSize(1024) { } void cBioGenMultiStepMap::InitializeBiomeGen(cIniFile & a_IniFile) { m_OceanCellSize = a_IniFile.GetValueSetI("Generator", "MultiStepMapOceanCellSize", m_OceanCellSize); m_MushroomIslandSize = a_IniFile.GetValueSetI("Generator", "MultiStepMapMushroomIslandSize", m_MushroomIslandSize); m_RiverCellSize = a_IniFile.GetValueSetI("Generator", "MultiStepMapRiverCellSize", m_RiverCellSize); m_RiverWidthThreshold = a_IniFile.GetValueSetF("Generator", "MultiStepMapRiverWidth", m_RiverWidthThreshold); m_LandBiomesSize = static_cast(a_IniFile.GetValueSetI("Generator", "MultiStepMapLandBiomeSize", static_cast(m_LandBiomesSize))); } void cBioGenMultiStepMap::GenBiomes(cChunkCoords a_ChunkCoords, cChunkDef::BiomeMap & a_BiomeMap) { DecideOceanLandMushroom(a_ChunkCoords, a_BiomeMap); AddRivers(a_ChunkCoords, a_BiomeMap); ApplyTemperatureHumidity(a_ChunkCoords, a_BiomeMap); } void cBioGenMultiStepMap::DecideOceanLandMushroom(cChunkCoords a_ChunkCoords, cChunkDef::BiomeMap & a_BiomeMap) { // Distorted Voronoi over 3 biomes, with mushroom having only a special occurence. // Prepare a distortion lookup table, by distorting a 5x5 area and using that as 1:4 zoom (linear interpolate): int BaseZ = cChunkDef::Width * a_ChunkCoords.m_ChunkZ; int BaseX = cChunkDef::Width * a_ChunkCoords.m_ChunkX; int DistortX[cChunkDef::Width + 1][cChunkDef::Width + 1]; int DistortZ[cChunkDef::Width + 1][cChunkDef::Width + 1]; int DistortSize = m_OceanCellSize / 2; for (int x = 0; x <= 4; x++) for (int z = 0; z <= 4; z++) { Distort(BaseX + x * 4, BaseZ + z * 4, DistortX[4 * x][4 * z], DistortZ[4 * x][4 * z], DistortSize); } LinearUpscale2DArrayInPlace(&DistortX[0][0]); LinearUpscale2DArrayInPlace(&DistortZ[0][0]); // Prepare a 9x9 area of neighboring cell seeds // (assuming that 7x7 cell area is larger than a chunk being generated) const int NEIGHBORHOOD_SIZE = 4; // How many seeds in each direction to check int CellX = BaseX / m_OceanCellSize; int CellZ = BaseZ / m_OceanCellSize; int SeedX[2 * NEIGHBORHOOD_SIZE + 1][2 * NEIGHBORHOOD_SIZE + 1]; int SeedZ[2 * NEIGHBORHOOD_SIZE + 1][2 * NEIGHBORHOOD_SIZE + 1]; EMCSBiome SeedV[2 * NEIGHBORHOOD_SIZE + 1][2 * NEIGHBORHOOD_SIZE + 1]; for (int xc = 0; xc < 2 * NEIGHBORHOOD_SIZE + 1; xc++) { int RealCellX = xc + CellX - NEIGHBORHOOD_SIZE; int CellBlockX = RealCellX * m_OceanCellSize; for (int zc = 0; zc < 2 * NEIGHBORHOOD_SIZE + 1; zc++) { int RealCellZ = zc + CellZ - NEIGHBORHOOD_SIZE; int CellBlockZ = RealCellZ * m_OceanCellSize; int OffsetX = (m_Noise2.IntNoise3DInt(RealCellX, 16 * RealCellX + 32 * RealCellZ, RealCellZ) / 8) % m_OceanCellSize; int OffsetZ = (m_Noise4.IntNoise3DInt(RealCellX, 32 * RealCellX - 16 * RealCellZ, RealCellZ) / 8) % m_OceanCellSize; SeedX[xc][zc] = CellBlockX + OffsetX; SeedZ[xc][zc] = CellBlockZ + OffsetZ; SeedV[xc][zc] = (((m_Noise6.IntNoise3DInt(RealCellX, RealCellX - RealCellZ + 1000, RealCellZ) / 11) % 256) > 90) ? biOcean : (biInvalidBiome); } // for z } // for x for (int xc = 1; xc < 2 * NEIGHBORHOOD_SIZE; xc++) for (int zc = 1; zc < 2 * NEIGHBORHOOD_SIZE; zc++) { if ( (SeedV[xc ][zc] == biOcean) && (SeedV[xc - 1][zc] == biOcean) && (SeedV[xc + 1][zc] == biOcean) && (SeedV[xc ][zc - 1] == biOcean) && (SeedV[xc ][zc + 1] == biOcean) && (SeedV[xc - 1][zc - 1] == biOcean) && (SeedV[xc + 1][zc - 1] == biOcean) && (SeedV[xc - 1][zc + 1] == biOcean) && (SeedV[xc + 1][zc + 1] == biOcean) ) { SeedV[xc][zc] = biMushroomIsland; } } // For each column find the nearest distorted cell and use its value as the biome: int MushroomOceanThreshold = m_OceanCellSize * m_OceanCellSize * m_MushroomIslandSize / 1024; int MushroomShoreThreshold = m_OceanCellSize * m_OceanCellSize * m_MushroomIslandSize / 2048; for (int z = 0; z < cChunkDef::Width; z++) { for (int x = 0; x < cChunkDef::Width; x++) { int AbsoluteZ = DistortZ[x][z]; int AbsoluteX = DistortX[x][z]; int MinDist = m_OceanCellSize * m_OceanCellSize * 16; // There has to be a cell closer than this EMCSBiome Biome = biPlains; // Find the nearest cell seed: for (int xs = 1; xs < 2 * NEIGHBORHOOD_SIZE; xs++) for (int zs = 1; zs < 2 * NEIGHBORHOOD_SIZE; zs++) { int Dist = (SeedX[xs][zs] - AbsoluteX) * (SeedX[xs][zs] - AbsoluteX) + (SeedZ[xs][zs] - AbsoluteZ) * (SeedZ[xs][zs] - AbsoluteZ); if (Dist >= MinDist) { continue; } MinDist = Dist; Biome = SeedV[xs][zs]; // Shrink mushroom biome and add a shore: if (Biome == biMushroomIsland) { if (Dist > MushroomOceanThreshold) { Biome = biOcean; } else if (Dist > MushroomShoreThreshold) { Biome = biMushroomShore; } } } // for zs, xs cChunkDef::SetBiome(a_BiomeMap, x, z, Biome); } // for x } // for z } void cBioGenMultiStepMap::AddRivers(cChunkCoords a_ChunkCoords, cChunkDef::BiomeMap & a_BiomeMap) { for (int z = 0; z < cChunkDef::Width; z++) { float NoiseCoordZ = static_cast(a_ChunkCoords.m_ChunkZ * cChunkDef::Width + z) / m_RiverCellSize; for (int x = 0; x < cChunkDef::Width; x++) { if (cChunkDef::GetBiome(a_BiomeMap, x, z) != biInvalidBiome) { // Biome already set, skip this column continue; } float NoiseCoordX = static_cast(a_ChunkCoords.m_ChunkX * cChunkDef::Width + x) / m_RiverCellSize; double Noise = m_Noise1.CubicNoise2D( NoiseCoordX, NoiseCoordZ); Noise += 0.5 * m_Noise3.CubicNoise2D(2 * NoiseCoordX, 2 * NoiseCoordZ); Noise += 0.1 * m_Noise5.CubicNoise2D(8 * NoiseCoordX, 8 * NoiseCoordZ); if ((Noise > 0) && (Noise < m_RiverWidthThreshold)) { cChunkDef::SetBiome(a_BiomeMap, x, z, biRiver); } } // for x } // for z } void cBioGenMultiStepMap::ApplyTemperatureHumidity(cChunkCoords a_ChunkCoords, cChunkDef::BiomeMap & a_BiomeMap) { IntMap TemperatureMap; IntMap HumidityMap; BuildTemperatureHumidityMaps(a_ChunkCoords, TemperatureMap, HumidityMap); FreezeWaterBiomes(a_BiomeMap, TemperatureMap); DecideLandBiomes(a_BiomeMap, TemperatureMap, HumidityMap); } void cBioGenMultiStepMap::Distort(int a_BlockX, int a_BlockZ, int & a_DistortedX, int & a_DistortedZ, int a_CellSize) { double NoiseX = m_Noise3.CubicNoise2D( static_cast(a_BlockX / a_CellSize), static_cast(a_BlockZ / a_CellSize)); NoiseX += 0.5 * m_Noise2.CubicNoise2D(2 * static_cast(a_BlockX / a_CellSize), 2 * static_cast(a_BlockZ / a_CellSize)); NoiseX += 0.1 * m_Noise1.CubicNoise2D(16 * static_cast(a_BlockX / a_CellSize), 16 * static_cast(a_BlockZ / a_CellSize)); double NoiseZ = m_Noise6.CubicNoise2D( static_cast(a_BlockX / a_CellSize), static_cast(a_BlockZ / a_CellSize)); NoiseZ += 0.5 * m_Noise5.CubicNoise2D(2 * static_cast(a_BlockX / a_CellSize), 2 * static_cast(a_BlockZ / a_CellSize)); NoiseZ += 0.1 * m_Noise4.CubicNoise2D(16 * static_cast(a_BlockX / a_CellSize), 16 * static_cast(a_BlockZ / a_CellSize)); a_DistortedX = a_BlockX + static_cast(a_CellSize * 0.5 * NoiseX); a_DistortedZ = a_BlockZ + static_cast(a_CellSize * 0.5 * NoiseZ); } void cBioGenMultiStepMap::BuildTemperatureHumidityMaps(cChunkCoords a_ChunkCoords, IntMap & a_TemperatureMap, IntMap & a_HumidityMap) { // Linear interpolation over 8x8 blocks; use double for better precision: DblMap TemperatureMap; DblMap HumidityMap; for (int z = 0; z < 17; z += 8) { float NoiseCoordZ = static_cast(a_ChunkCoords.m_ChunkZ * cChunkDef::Width + z) / m_LandBiomesSize; for (int x = 0; x < 17; x += 8) { float NoiseCoordX = static_cast(a_ChunkCoords.m_ChunkX * cChunkDef::Width + x) / m_LandBiomesSize; double NoiseT = m_Noise1.CubicNoise2D( NoiseCoordX, NoiseCoordZ); NoiseT += 0.5 * m_Noise2.CubicNoise2D(2 * NoiseCoordX, 2 * NoiseCoordZ); NoiseT += 0.1 * m_Noise3.CubicNoise2D(8 * NoiseCoordX, 8 * NoiseCoordZ); TemperatureMap[x + 17 * z] = NoiseT; double NoiseH = m_Noise4.CubicNoise2D( NoiseCoordX, NoiseCoordZ); NoiseH += 0.5 * m_Noise5.CubicNoise2D(2 * NoiseCoordX, 2 * NoiseCoordZ); NoiseH += 0.1 * m_Noise6.CubicNoise2D(8 * NoiseCoordX, 8 * NoiseCoordZ); HumidityMap[x + 17 * z] = NoiseH; } // for x } // for z LinearUpscale2DArrayInPlace<17, 17, 8, 8>(TemperatureMap); LinearUpscale2DArrayInPlace<17, 17, 8, 8>(HumidityMap); // Re-map into integral values in [0 .. 255] range: for (size_t idx = 0; idx < ARRAYCOUNT(a_TemperatureMap); idx++) { a_TemperatureMap[idx] = Clamp(static_cast(128 + TemperatureMap[idx] * 128), 0, 255); a_HumidityMap[idx] = Clamp(static_cast(128 + HumidityMap[idx] * 128), 0, 255); } } void cBioGenMultiStepMap::DecideLandBiomes(cChunkDef::BiomeMap & a_BiomeMap, const IntMap & a_TemperatureMap, const IntMap & a_HumidityMap) { static const EMCSBiome BiomeMap[] = { // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 /* 0 */ biTundra, biTundra, biTundra, biTundra, biPlains, biPlains, biPlains, biPlains, biPlains, biPlains, biDesert, biDesert, biDesert, biDesert, biDesert, biDesert, /* 1 */ biTundra, biTundra, biTundra, biTundra, biPlains, biPlains, biPlains, biPlains, biPlains, biPlains, biDesert, biDesert, biDesert, biDesert, biDesert, biDesert, /* 2 */ biTundra, biTundra, biTundra, biTundra, biPlains, biExtremeHills, biPlains, biPlains, biPlains, biPlains, biDesert, biDesert, biDesertHills, biDesertHills, biDesert, biDesert, /* 3 */ biTundra, biTundra, biTundra, biTundra, biExtremeHills, biExtremeHills, biPlains, biPlains, biPlains, biPlains, biDesert, biDesert, biDesertHills, biDesertHills, biDesert, biDesert, /* 4 */ biTundra, biTundra, biIceMountains, biIceMountains, biExtremeHills, biExtremeHills, biPlains, biPlains, biPlains, biPlains, biForestHills, biForestHills, biExtremeHills, biExtremeHills, biDesertHills, biDesert, /* 5 */ biTundra, biTundra, biIceMountains, biIceMountains, biExtremeHills, biExtremeHills, biPlains, biPlains, biPlains, biPlains, biForestHills, biForestHills, biExtremeHills, biExtremeHills, biDesertHills, biDesert, /* 6 */ biTundra, biTundra, biIceMountains, biIceMountains, biForestHills, biForestHills, biForest, biForest, biForest, biForest, biForest, biForestHills, biExtremeHills, biExtremeHills, biPlains, biPlains, /* 7 */ biTundra, biTundra, biIceMountains, biIceMountains, biForestHills, biForestHills, biForest, biForest, biForest, biForest, biForest, biForestHills, biExtremeHills, biExtremeHills, biPlains, biPlains, /* 8 */ biTundra, biTundra, biTaiga, biTaiga, biForest, biForest, biForest, biForest, biForest, biForest, biForest, biForestHills, biExtremeHills, biExtremeHills, biPlains, biPlains, /* 9 */ biTundra, biTundra, biTaiga, biTaiga, biForest, biForest, biForest, biForest, biForest, biForest, biForest, biForestHills, biExtremeHills, biExtremeHills, biPlains, biPlains, /* 10 */ biTaiga, biTaiga, biTaiga, biIceMountains, biForestHills, biForestHills, biForest, biForest, biForest, biForest, biJungle, biJungle, biSwampland, biSwampland, biSwampland, biSwampland, /* 11 */ biTaiga, biTaiga, biIceMountains, biIceMountains, biExtremeHills, biForestHills, biForest, biForest, biForest, biForest, biJungle, biJungle, biSwampland, biSwampland, biSwampland, biSwampland, /* 12 */ biTaiga, biTaiga, biIceMountains, biIceMountains, biExtremeHills, biJungleHills, biJungle, biJungle, biJungle, biJungle, biJungle, biJungle, biSwampland, biSwampland, biSwampland, biSwampland, /* 13 */ biTaiga, biTaiga, biTaiga, biIceMountains, biJungleHills, biJungleHills, biJungle, biJungle, biJungle, biJungle, biJungle, biJungle, biSwampland, biSwampland, biSwampland, biSwampland, /* 14 */ biTaiga, biTaiga, biTaiga, biTaiga, biJungle, biJungle, biJungle, biJungle, biJungle, biJungle, biJungle, biJungle, biSwampland, biSwampland, biSwampland, biSwampland, /* 15 */ biTaiga, biTaiga, biTaiga, biTaiga, biJungle, biJungle, biJungle, biJungle, biJungle, biJungle, biJungle, biJungle, biSwampland, biSwampland, biSwampland, biSwampland, } ; for (int z = 0; z < cChunkDef::Width; z++) { int idxZ = 17 * z; for (int x = 0; x < cChunkDef::Width; x++) { if (cChunkDef::GetBiome(a_BiomeMap, x, z) != biInvalidBiome) { // Already set before continue; } int idx = idxZ + x; int Temperature = a_TemperatureMap[idx] / 16; // -> [0..15] range int Humidity = a_HumidityMap[idx] / 16; // -> [0..15] range cChunkDef::SetBiome(a_BiomeMap, x, z, BiomeMap[Temperature + 16 * Humidity]); } // for x } // for z } void cBioGenMultiStepMap::FreezeWaterBiomes(cChunkDef::BiomeMap & a_BiomeMap, const IntMap & a_TemperatureMap) { int idx = 0; for (int z = 0; z < cChunkDef::Width; z++) { for (int x = 0; x < cChunkDef::Width; x++, idx++) { if (a_TemperatureMap[idx] > 4 * 16) { // Not frozen continue; } switch (cChunkDef::GetBiome(a_BiomeMap, x, z)) { case biRiver: cChunkDef::SetBiome(a_BiomeMap, x, z, biFrozenRiver); break; case biOcean: cChunkDef::SetBiome(a_BiomeMap, x, z, biFrozenOcean); break; default: break; } } // for x idx += 1; } // for z } //////////////////////////////////////////////////////////////////////////////// // cBioGenTwoLevel: cBioGenTwoLevel::cBioGenTwoLevel(int a_Seed) : m_VoronoiLarge(a_Seed + 1000), m_VoronoiSmall(a_Seed + 2000), m_Noise1(a_Seed + 5001), m_Noise2(a_Seed + 5002), m_Noise3(a_Seed + 5003), m_Noise4(a_Seed + 5004), m_Noise5(a_Seed + 5005), m_Noise6(a_Seed + 5006), m_FreqX1(0.0), m_AmpX1(0.0), m_FreqX2(0.0), m_AmpX2(0.0), m_FreqX3(0.0), m_AmpX3(0.0), m_FreqZ1(0.0), m_AmpZ1(0.0), m_FreqZ2(0.0), m_AmpZ2(0.0), m_FreqZ3(0.0), m_AmpZ3(0.0) { } void cBioGenTwoLevel::GenBiomes(cChunkCoords a_ChunkCoords, cChunkDef::BiomeMap & a_BiomeMap) { int BaseZ = cChunkDef::Width * a_ChunkCoords.m_ChunkZ; int BaseX = cChunkDef::Width * a_ChunkCoords.m_ChunkX; // Distortions for linear interpolation: int DistortX[cChunkDef::Width + 1][cChunkDef::Width + 1]; int DistortZ[cChunkDef::Width + 1][cChunkDef::Width + 1]; for (int x = 0; x <= 4; x++) for (int z = 0; z <= 4; z++) { float BlockX = static_cast(BaseX + x * 4); float BlockZ = static_cast(BaseZ + z * 4); double NoiseX = m_AmpX1 * m_Noise1.CubicNoise2D(BlockX * m_FreqX1, BlockZ * m_FreqX1); NoiseX += m_AmpX2 * m_Noise2.CubicNoise2D(BlockX * m_FreqX2, BlockZ * m_FreqX2); NoiseX += m_AmpX3 * m_Noise3.CubicNoise2D(BlockX * m_FreqX3, BlockZ * m_FreqX3); double NoiseZ = m_AmpZ1 * m_Noise4.CubicNoise2D(BlockX * m_FreqZ1, BlockZ * m_FreqZ1); NoiseZ += m_AmpZ2 * m_Noise5.CubicNoise2D(BlockX * m_FreqZ2, BlockZ * m_FreqZ2); NoiseZ += m_AmpZ3 * m_Noise6.CubicNoise2D(BlockX * m_FreqZ3, BlockZ * m_FreqZ3); DistortX[4 * x][4 * z] = static_cast(BlockX + NoiseX); DistortZ[4 * x][4 * z] = static_cast(BlockZ + NoiseZ); } LinearUpscale2DArrayInPlace(&DistortX[0][0]); LinearUpscale2DArrayInPlace(&DistortZ[0][0]); // Apply distortion to each block coord, then query the voronoi maps for biome group and biome index and choose biome based on that: for (int z = 0; z < cChunkDef::Width; z++) { for (int x = 0; x < cChunkDef::Width; x++) { int SeedX, SeedZ, MinDist2; int BiomeGroup = m_VoronoiLarge.GetValueAt(DistortX[x][z], DistortZ[x][z], SeedX, SeedZ, MinDist2) / 7; size_t BiomeIdx = static_cast(m_VoronoiSmall.GetValueAt(DistortX[x][z], DistortZ[x][z], SeedX, SeedZ, MinDist2) / 11); int MinDist1 = (DistortX[x][z] - SeedX) * (DistortX[x][z] - SeedX) + (DistortZ[x][z] - SeedZ) * (DistortZ[x][z] - SeedZ); cChunkDef::SetBiome(a_BiomeMap, x, z, SelectBiome(BiomeGroup, BiomeIdx, (MinDist1 < MinDist2 / 4) ? 1 : 0)); } } } EMCSBiome cBioGenTwoLevel::SelectBiome(int a_BiomeGroup, size_t a_BiomeIdx, int a_DistLevel) { // TODO: Move this into settings struct BiomeLevels { EMCSBiome InnerBiome; EMCSBiome OuterBiome; } ; static BiomeLevels bgOceanBlocks[] = { { biOcean, biOcean, }, { biOcean, biOcean, }, { biOcean, biOcean, }, { biOcean, biOcean, }, { biOcean, biDeepOcean, }, { biOcean, biDeepOcean, }, { biDeepOcean, biDeepOcean, }, { biDeepOcean, biDeepOcean, }, { biDeepOcean, biDeepOcean, }, { biDeepOcean, biDeepOcean, }, { biMushroomIsland, biMushroomShore, } } ; static BiomeLevels bgFrozenBlocks[] = { { biIcePlains, biIcePlains, }, { biIceMountains, biIceMountains, }, { biFrozenOcean, biFrozenRiver, }, { biColdTaiga, biColdTaiga, }, { biColdTaigaHills, biColdTaigaHills, }, { biColdTaigaM, biColdTaigaM, }, { biIcePlainsSpikes, biIcePlainsSpikes, }, { biExtremeHills, biExtremeHillsEdge, }, { biExtremeHillsPlus, biExtremeHillsEdge, }, { biExtremeHillsPlusM, biExtremeHillsPlusM, }, } ; static BiomeLevels bgTemperateBlocks[] = { { biBirchForestHills, biBirchForest, }, { biBirchForest, biBirchForest, }, { biBirchForestHillsM, biBirchForestM, }, { biBirchForestM, biBirchForestM, }, { biForest, biForestHills, }, { biFlowerForest, biFlowerForest, }, { biRoofedForest, biForest, }, { biRoofedForest, biRoofedForest, }, { biRoofedForestM, biForest, }, { biPlains, biPlains, }, { biSunflowerPlains, biSunflowerPlains, }, { biSwampland, biSwampland, }, { biSwamplandM, biSwamplandM, }, } ; static BiomeLevels bgWarmBlocks[] = { { biDesertHills, biDesert, }, { biDesert, biDesert, }, { biDesertM, biDesertM, }, { biSavannaPlateau, biSavanna, }, { biSavanna, biSavanna, }, { biSavannaM, biSavannaM, }, } ; static BiomeLevels bgMesaBlocks[] = { { biMesaPlateau, biMesa, }, { biMesaPlateauF, biMesa, }, { biMesaPlateauFM, biMesa, }, { biMesaPlateauM, biMesa, }, { biMesaBryce, biMesaBryce, }, { biSavanna, biSavanna, }, { biSavannaPlateau, biSavanna, }, } ; static BiomeLevels bgConifersBlocks[] = { { biTaiga, biTaiga, }, { biTaigaM, biTaigaM, }, { biMegaTaiga, biMegaTaiga, }, { biMegaSpruceTaiga, biMegaSpruceTaiga, }, { biMegaSpruceTaigaHills, biMegaSpruceTaiga, } } ; static BiomeLevels bgDenseTreesBlocks[] = { { biJungleHills, biJungle, }, { biJungle, biJungleEdge, }, { biJungleM, biJungleEdgeM, }, } ; static struct { BiomeLevels * Biomes; size_t Count; } BiomeGroups[] = { { bgOceanBlocks, ARRAYCOUNT(bgOceanBlocks), }, { bgOceanBlocks, ARRAYCOUNT(bgOceanBlocks), }, { bgFrozenBlocks, ARRAYCOUNT(bgFrozenBlocks), }, { bgFrozenBlocks, ARRAYCOUNT(bgFrozenBlocks), }, { bgTemperateBlocks, ARRAYCOUNT(bgTemperateBlocks), }, { bgTemperateBlocks, ARRAYCOUNT(bgTemperateBlocks), }, { bgConifersBlocks, ARRAYCOUNT(bgConifersBlocks), }, { bgConifersBlocks, ARRAYCOUNT(bgConifersBlocks), }, { bgWarmBlocks, ARRAYCOUNT(bgWarmBlocks), }, { bgWarmBlocks, ARRAYCOUNT(bgWarmBlocks), }, { bgMesaBlocks, ARRAYCOUNT(bgMesaBlocks), }, { bgDenseTreesBlocks, ARRAYCOUNT(bgDenseTreesBlocks), }, } ; size_t Group = static_cast(a_BiomeGroup) % ARRAYCOUNT(BiomeGroups); size_t Index = a_BiomeIdx % BiomeGroups[Group].Count; return (a_DistLevel > 0) ? BiomeGroups[Group].Biomes[Index].InnerBiome : BiomeGroups[Group].Biomes[Index].OuterBiome; } void cBioGenTwoLevel::InitializeBiomeGen(cIniFile & a_IniFile) { m_VoronoiLarge.SetCellSize(a_IniFile.GetValueSetI("Generator", "TwoLevelLargeCellSize", 1024)); m_VoronoiSmall.SetCellSize(a_IniFile.GetValueSetI("Generator", "TwoLevelSmallCellSize", 128)); m_FreqX1 = static_cast(a_IniFile.GetValueSetF("Generator", "TwoLevelDistortXOctave1Freq", 0.01)); m_AmpX1 = static_cast(a_IniFile.GetValueSetF("Generator", "TwoLevelDistortXOctave1Amp", 80)); m_FreqX2 = static_cast(a_IniFile.GetValueSetF("Generator", "TwoLevelDistortXOctave2Freq", 0.05)); m_AmpX2 = static_cast(a_IniFile.GetValueSetF("Generator", "TwoLevelDistortXOctave2Amp", 20)); m_FreqX3 = static_cast(a_IniFile.GetValueSetF("Generator", "TwoLevelDistortXOctave3Freq", 0.1)); m_AmpX3 = static_cast(a_IniFile.GetValueSetF("Generator", "TwoLevelDistortXOctave3Amp", 8)); m_FreqZ1 = static_cast(a_IniFile.GetValueSetF("Generator", "TwoLevelDistortZOctave1Freq", 0.01)); m_AmpZ1 = static_cast(a_IniFile.GetValueSetF("Generator", "TwoLevelDistortZOctave1Amp", 80)); m_FreqZ2 = static_cast(a_IniFile.GetValueSetF("Generator", "TwoLevelDistortZOctave2Freq", 0.05)); m_AmpZ2 = static_cast(a_IniFile.GetValueSetF("Generator", "TwoLevelDistortZOctave2Amp", 20)); m_FreqZ3 = static_cast(a_IniFile.GetValueSetF("Generator", "TwoLevelDistortZOctave3Freq", 0.1)); m_AmpZ3 = static_cast(a_IniFile.GetValueSetF("Generator", "TwoLevelDistortZOctave3Amp", 8)); } //////////////////////////////////////////////////////////////////////////////// // cBioGenGrown: class cBioGenGrown: public cBiomeGen { public: cBioGenGrown(int a_Seed) { auto FinalRivers = std::make_shared>(a_Seed + 12) | MakeIntGen>(a_Seed + 11) | MakeIntGen>(a_Seed + 6) | MakeIntGen>(a_Seed + 5) | MakeIntGen>(a_Seed + 10) | MakeIntGen>(a_Seed + 5) | MakeIntGen>(a_Seed + 9) | MakeIntGen>(a_Seed + 5) | MakeIntGen>(a_Seed + 8) | MakeIntGen>(a_Seed + 5) | MakeIntGen>(a_Seed + 4) | MakeIntGen>(a_Seed + 3) | MakeIntGen>(a_Seed + 2) | MakeIntGen>(a_Seed + 1); auto alteration = std::make_shared>(a_Seed, std::make_shared>(a_Seed, 20 )); auto alteration2 = std::make_shared>(a_Seed + 1, std::make_shared>(a_Seed + 2, std::make_shared>(a_Seed + 1, std::make_shared>(a_Seed + 2, std::make_shared>(a_Seed + 1, 10 ))))); auto FinalBiomes = std::make_shared> (a_Seed + 1, std::make_shared>(a_Seed + 15, std::make_shared> (a_Seed + 1, std::make_shared> (a_Seed + 16, std::make_shared> ( std::make_shared> (a_Seed + 1, std::make_shared> (a_Seed + 2004, 10, std::make_shared> (a_Seed + 10, 500, biDeepOcean, std::make_shared> (a_Seed + 1, biPlains, biSunflowerPlains, 20, std::make_shared> (a_Seed + 5, alteration2, std::make_shared> (a_Seed + 1, alteration, std::make_shared> (a_Seed + 3, std::make_shared>(a_Seed + 2, std::make_shared> (a_Seed + 4, std::make_shared> (a_Seed + 99, biIcePlains, biIcePlainsSpikes, 50, std::make_shared> (a_Seed + 8, std::make_shared> (a_Seed + 10, 300, biDeepOcean, std::make_shared> (a_Seed + 9, 8, biMushroomIsland, std::make_shared> (a_Seed + 3000, std::make_shared> (a_Seed + 2000, 200, std::make_shared> (a_Seed + 5, std::make_shared> (a_Seed + 5, 50, std::make_shared> ( std::make_shared> (a_Seed + 2000, 200, std::make_shared> (a_Seed + 7, std::make_shared> (a_Seed + 8, 50, bgOcean, std::make_shared> (a_Seed + 101, bgIce, bgTemperate, 150, std::make_shared> (a_Seed + 2000, 200, std::make_shared> (a_Seed + 9, 50, bgOcean, std::make_shared> (a_Seed + 100, 30) | MakeIntGen> (a_Seed + 10) ))))))))))))))))))))))))))))); m_Gen = std::make_shared>(a_Seed, std::make_shared>(a_Seed, std::make_shared>(a_Seed, std::make_shared>(a_Seed, std::make_shared> ( FinalBiomes, FinalRivers ))))); } virtual void GenBiomes(cChunkCoords a_ChunkCoords, cChunkDef::BiomeMap & a_Biomes) override { cIntGen<16, 16>::Values vals; m_Gen->GetInts(a_ChunkCoords.m_ChunkX * cChunkDef::Width, a_ChunkCoords.m_ChunkZ * cChunkDef::Width, vals); for (int z = 0; z < cChunkDef::Width; z++) { for (int x = 0; x < cChunkDef::Width; x++) { cChunkDef::SetBiome(a_Biomes, x, z, static_cast(vals[x + cChunkDef::Width * z])); } } } protected: std::shared_ptr> m_Gen; }; //////////////////////////////////////////////////////////////////////////////// // cBioGenProtGrown: class cBioGenProtGrown: public cBiomeGen { public: cBioGenProtGrown(int a_Seed) { auto FinalRivers = std::make_shared(a_Seed + 1, std::make_shared(a_Seed + 2, std::make_shared(a_Seed + 3, std::make_shared(a_Seed + 4, std::make_shared(a_Seed + 5, std::make_shared(a_Seed + 8, std::make_shared(a_Seed + 5, std::make_shared(a_Seed + 9, std::make_shared(a_Seed + 5, std::make_shared(a_Seed + 10, std::make_shared(a_Seed + 5, std::make_shared(a_Seed + 6, std::make_shared(a_Seed + 11, std::make_shared(a_Seed + 12, 2 )))))))))))))); auto alteration = std::make_shared(a_Seed, std::make_shared(a_Seed, 20 )); auto alteration2 = std::make_shared(a_Seed + 1, std::make_shared(a_Seed + 2, std::make_shared(a_Seed + 1, std::make_shared(a_Seed + 2, std::make_shared(a_Seed + 1, 10 ))))); auto FinalBiomes = std::make_shared(a_Seed + 1, std::make_shared(a_Seed + 15, std::make_shared(a_Seed + 1, std::make_shared(a_Seed + 16, std::make_shared( std::make_shared(a_Seed + 1, std::make_shared(a_Seed + 2004, 10, std::make_shared(a_Seed + 10, 500, biDeepOcean, std::make_shared(a_Seed + 1, biPlains, biSunflowerPlains, 20, std::make_shared(a_Seed + 5, alteration2, std::make_shared(a_Seed + 1, alteration, std::make_shared(a_Seed + 3, std::make_shared(a_Seed + 2, std::make_shared(a_Seed + 4, std::make_shared(a_Seed + 99, biIcePlains, biIcePlainsSpikes, 50, std::make_shared(a_Seed + 8, std::make_shared(a_Seed + 10, 300, biDeepOcean, std::make_shared(a_Seed + 9, 8, biMushroomIsland, std::make_shared(a_Seed + 3000, std::make_shared(a_Seed + 2000, 200, std::make_shared(a_Seed + 5, std::make_shared(a_Seed + 5, 50, std::make_shared( std::make_shared(a_Seed + 2000, 200, std::make_shared(a_Seed + 7, std::make_shared(a_Seed + 8, 50, bgOcean, std::make_shared(a_Seed + 101, bgIce, bgTemperate, 150, std::make_shared(a_Seed + 2000, 200, std::make_shared(a_Seed + 9, 50, bgOcean, std::make_shared(a_Seed + 10, std::make_shared(a_Seed + 100, 30 ))))))))))))))))))))))))))))))); m_Gen = std::make_shared(a_Seed, std::make_shared(a_Seed, std::make_shared(a_Seed, std::make_shared(a_Seed, std::make_shared( FinalBiomes, FinalRivers ))))); } virtual void GenBiomes(cChunkCoords a_ChunkCoords, cChunkDef::BiomeMap & a_Biomes) override { int vals[16 * 16]; m_Gen->GetInts(a_ChunkCoords.m_ChunkX * cChunkDef::Width, a_ChunkCoords.m_ChunkZ * cChunkDef::Width, 16, 16, vals); for (int z = 0; z < cChunkDef::Width; z++) { for (int x = 0; x < cChunkDef::Width; x++) { cChunkDef::SetBiome(a_Biomes, x, z, static_cast(vals[x + cChunkDef::Width * z])); } } } protected: std::shared_ptr m_Gen; }; //////////////////////////////////////////////////////////////////////////////// // cBiomeGen: std::unique_ptr cBiomeGen::CreateBiomeGen(cIniFile & a_IniFile, int a_Seed, bool & a_CacheOffByDefault) { AString BiomeGenName = a_IniFile.GetValue("Generator", "BiomeGen"); if (BiomeGenName.empty()) { LOGWARN("[Generator] BiomeGen value not set in world.ini, using \"Grown\"."); BiomeGenName = "Grown"; } std::unique_ptr res; a_CacheOffByDefault = false; if (NoCaseCompare(BiomeGenName, "constant") == 0) { res = std::make_unique(); a_CacheOffByDefault = true; // we're generating faster than a cache would retrieve data :) } else if (NoCaseCompare(BiomeGenName, "checkerboard") == 0) { res = std::make_unique(); a_CacheOffByDefault = true; // we're (probably) generating faster than a cache would retrieve data } else if (NoCaseCompare(BiomeGenName, "voronoi") == 0) { res = std::make_unique(a_Seed); } else if (NoCaseCompare(BiomeGenName, "distortedvoronoi") == 0) { res = std::make_unique(a_Seed); } else if (NoCaseCompare(BiomeGenName, "twolevel") == 0) { res = std::make_unique(a_Seed); } else if (NoCaseCompare(BiomeGenName, "multistepmap") == 0) { res = std::make_unique(a_Seed); } else if (NoCaseCompare(BiomeGenName, "grownprot") == 0) { res = std::make_unique(a_Seed); } else { if (NoCaseCompare(BiomeGenName, "grown") != 0) { LOGWARNING("Unknown BiomeGen \"%s\", using \"Grown\" instead.", BiomeGenName.c_str()); } res = std::make_unique(a_Seed); } res->InitializeBiomeGen(a_IniFile); return res; } //////////////////////////////////////////////////////////////////////////////// // Performance tests: // Change to 1 to enable the perf test: #if 0 #include class cBioGenPerfTest { public: cBioGenPerfTest() { std::cout << "BioGen performance tests commencing, please wait..." << std::endl; TestGen("MultiStepMap", std::make_unique(1).get()); TestGen("Grown", std::make_unique(1).get()); TestGen("GrownProt", std::make_unique(1).get()); std::cout << "BioGen performance tests complete." << std::endl; } protected: void TestGen(const AString && a_GenName, cBiomeGen * a_BioGen) { // Initialize the default settings for the generator: cIniFile iniFile; a_BioGen->InitializeBiomeGen(iniFile); // Generate the biomes: auto start = std::chrono::system_clock::now(); for (int z = 0; z < 100; z++) { for (int x = 0; x < 100; x++) { cChunkDef::BiomeMap biomes; a_BioGen->GenBiomes(x, z, biomes); } // for x } // for z auto dur = std::chrono::system_clock::now() - start; double milliseconds = static_cast((std::chrono::duration_cast(dur)).count()); std::cout << a_GenName << ": " << 1000.0 * 100.0 * 100.0 / milliseconds << " chunks per second" << std::endl; } } g_BioGenPerfTest; #endif ================================================ FILE: src/Generating/BioGen.h ================================================ // BioGen.h /* Interfaces to the various biome generators: - cBioGenConstant - cBioGenCheckerboard - cBioGenDistortedVoronoi */ #pragma once #include "ComposableGenerator.h" #include "../Noise/Noise.h" #include "../VoronoiMap.h" class cBioGenConstant : public cBiomeGen { public: cBioGenConstant(void) : m_Biome(biPlains) {} protected: EMCSBiome m_Biome; // cBiomeGen overrides: virtual void GenBiomes(cChunkCoords a_ChunkCoords, cChunkDef::BiomeMap & a_BiomeMap) override; virtual void InitializeBiomeGen(cIniFile & a_IniFile) override; } ; /** A simple cache that stores N most recently generated chunks' biomes; N being settable upon creation */ class cBioGenCache: public cBiomeGen { using Super = cBiomeGen; public: cBioGenCache(cBiomeGen & a_BioGenToCache, size_t a_CacheSize); protected: friend class cBioGenMulticache; cBiomeGen & m_BioGenToCache; struct sCacheData { cChunkCoords m_Coords; cChunkDef::BiomeMap m_BiomeMap; /** Default constructor: Fill in bogus coords so that the item is not used in the cache until properly calculated. */ sCacheData(): m_Coords(0x7fffffff, 0x7fffffff) { } } ; // To avoid moving large amounts of data for the MRU behavior, we MRU-ize indices to an array of the actual data size_t m_CacheSize; std::vector m_CacheOrder; // MRU-ized order, indices into m_CacheData array std::vector m_CacheData; // m_CacheData[m_CacheOrder[0]] is the most recently used // Cache statistics size_t m_NumHits; size_t m_NumMisses; size_t m_TotalChain; // Number of cache items walked to get to a hit (only added for hits) virtual void GenBiomes(cChunkCoords a_ChunkCoords, cChunkDef::BiomeMap & a_BiomeMap) override; virtual void InitializeBiomeGen(cIniFile & a_IniFile) override; } ; class cBioGenMulticache: public cBiomeGen { using Super = cBiomeGen; public: /* Creates a new multicache - a cache that divides the caching into several sub-caches based on the chunk coords. This allows us to use shorter cache depths with faster lookups for more covered area. (#381) a_SubCacheSize defines the size of each sub-cache a_NumSubCaches defines how many sub-caches are used for the multicache. */ cBioGenMulticache(std::unique_ptr a_BioGenToCache, size_t a_SubCacheSize, size_t a_NumSubCaches); protected: /** Number of sub-caches. Pulled out of m_Caches.size() for faster access. */ size_t m_NumSubCaches; /** Individual sub-caches. */ std::vector> m_Caches; /** The underlying biome generator. */ std::unique_ptr m_Underlying; virtual void GenBiomes(cChunkCoords a_ChunkCoords, cChunkDef::BiomeMap & a_BiomeMap) override; virtual void InitializeBiomeGen(cIniFile & a_IniFile) override; }; /** Base class for generators that use a list of available biomes. This class takes care of the list. */ class cBiomeGenList: public cBiomeGen { using Super = cBiomeGen; protected: // List of biomes that the generator is allowed to generate: typedef std::vector EMCSBiomes; EMCSBiomes m_Biomes; int m_BiomesCount; // Pulled out of m_Biomes for faster access /** Parses the INI file setting string into m_Biomes. */ void InitializeBiomes(const AString & a_Biomes); } ; class cBioGenCheckerboard: public cBiomeGenList { using Super = cBiomeGenList; protected: int m_BiomeSize; // cBiomeGen overrides: virtual void GenBiomes(cChunkCoords a_ChunkCoords, cChunkDef::BiomeMap & a_BiomeMap) override; virtual void InitializeBiomeGen(cIniFile & a_IniFile) override; } ; class cBioGenVoronoi: public cBiomeGenList { using Super = cBiomeGenList; public: cBioGenVoronoi(int a_Seed) : m_Voronoi(a_Seed) { } protected: cVoronoiMap m_Voronoi; // cBiomeGen overrides: virtual void GenBiomes(cChunkCoords a_ChunkCoords, cChunkDef::BiomeMap & a_BiomeMap) override; virtual void InitializeBiomeGen(cIniFile & a_IniFile) override; EMCSBiome VoronoiBiome(int a_BlockX, int a_BlockZ); } ; class cBioGenDistortedVoronoi: public cBiomeGenList { using Super = cBiomeGenList; public: cBioGenDistortedVoronoi(int a_Seed): m_Noise(a_Seed), m_Voronoi(a_Seed), m_CellSize(0) { } protected: /** Noise used for the distortion */ cNoise m_Noise; /** The underlying Voronoi map of the biomes */ cVoronoiMap m_Voronoi; /** Size of the Voronoi cells, also used for distortion amplitude */ int m_CellSize; // cBiomeGen overrides: virtual void GenBiomes(cChunkCoords a_ChunkCoords, cChunkDef::BiomeMap & a_BiomeMap) override; virtual void InitializeBiomeGen(cIniFile & a_IniFile) override; /** Distorts the coords using a Perlin-like noise */ void Distort(int a_BlockX, int a_BlockZ, int & a_DistortedX, int & a_DistortedZ); } ; class cBioGenMultiStepMap: public cBiomeGen { using Super = cBiomeGen; public: cBioGenMultiStepMap(int a_Seed); protected: // Noises used for composing the perlin-noise: cNoise m_Noise1; cNoise m_Noise2; cNoise m_Noise3; cNoise m_Noise4; cNoise m_Noise5; cNoise m_Noise6; int m_Seed; int m_OceanCellSize; int m_MushroomIslandSize; int m_RiverCellSize; double m_RiverWidthThreshold; float m_LandBiomesSize; typedef int IntMap[17 * 17]; // x + 17 * z, expected trimmed into [0..255] range typedef double DblMap[17 * 17]; // x + 17 * z, expected trimmed into [0..1] range // cBiomeGen overrides: virtual void GenBiomes(cChunkCoords a_ChunkCoords, cChunkDef::BiomeMap & a_BiomeMap) override; virtual void InitializeBiomeGen(cIniFile & a_IniFile) override; /** Step 1: Decides between ocean, land and mushroom, using a DistVoronoi with special conditions and post-processing for mushroom islands Sets biomes to biOcean, -1 (i.e. land), biMushroomIsland or biMushroomShore. */ void DecideOceanLandMushroom(cChunkCoords a_ChunkCoords, cChunkDef::BiomeMap & a_BiomeMap); /** Step 2: Add rivers to the land Flips some "-1" biomes into biRiver. */ void AddRivers(cChunkCoords a_ChunkCoords, cChunkDef::BiomeMap & a_BiomeMap); /** Step 3: Decide land biomes using a temperature / humidity map; freeze ocean / river in low temperatures. Flips all remaining "-1" biomes into land biomes. Also flips some biOcean and biRiver into biFrozenOcean, biFrozenRiver, based on temp map. */ void ApplyTemperatureHumidity(cChunkCoords a_ChunkCoords, cChunkDef::BiomeMap & a_BiomeMap); /** Distorts the coords using a Perlin-like noise, with a specified cell-size */ void Distort(int a_BlockX, int a_BlockZ, int & a_DistortedX, int & a_DistortedZ, int a_CellSize); /** Builds two Perlin-noise maps, one for temperature, the other for humidity. Trims both into [0..255] range */ void BuildTemperatureHumidityMaps(cChunkCoords a_ChunkCoords, IntMap & a_TemperatureMap, IntMap & a_HumidityMap); /** Flips all remaining "-1" biomes into land biomes using the two maps */ void DecideLandBiomes(cChunkDef::BiomeMap & a_BiomeMap, const IntMap & a_TemperatureMap, const IntMap & a_HumidityMap); /** Flips biOcean and biRiver into biFrozenOcean and biFrozenRiver if the temperature is too low */ void FreezeWaterBiomes(cChunkDef::BiomeMap & a_BiomeMap, const IntMap & a_TemperatureMap); } ; class cBioGenTwoLevel: public cBiomeGen { using Super = cBiomeGen; public: cBioGenTwoLevel(int a_Seed); protected: /** The Voronoi map that decides the groups of biomes */ cVoronoiMap m_VoronoiLarge; /** The Voronoi map that decides biomes inside individual biome groups */ cVoronoiMap m_VoronoiSmall; // The noises used for the distortion: cNoise m_Noise1; cNoise m_Noise2; cNoise m_Noise3; cNoise m_Noise4; cNoise m_Noise5; cNoise m_Noise6; // Frequencies and amplitudes for the distortion noises: float m_FreqX1, m_AmpX1; float m_FreqX2, m_AmpX2; float m_FreqX3, m_AmpX3; float m_FreqZ1, m_AmpZ1; float m_FreqZ2, m_AmpZ2; float m_FreqZ3, m_AmpZ3; // cBiomeGen overrides: virtual void GenBiomes(cChunkCoords a_ChunkCoords, cChunkDef::BiomeMap & a_BiomeMap) override; virtual void InitializeBiomeGen(cIniFile & a_IniFile) override; /** Selects biome from the specified biome group, based on the specified index. Note that both params may overflow a_DistLevel is either 0 or 1; zero when it is at the edge of the small Voronoi cell, 1 near the center */ EMCSBiome SelectBiome(int a_BiomeGroup, size_t a_BiomeIdx, int a_DistLevel); } ; ================================================ FILE: src/Generating/CMakeLists.txt ================================================ target_sources( ${CMAKE_PROJECT_NAME} PRIVATE BioGen.cpp Caves.cpp ChunkDesc.cpp ChunkGenerator.cpp CompoGen.cpp CompoGenBiomal.cpp ComposableGenerator.cpp DistortedHeightmap.cpp DungeonRoomsFinisher.cpp EndGen.cpp EnderDragonFightStructuresGen.cpp FinishGen.cpp GridStructGen.cpp HeiGen.cpp MineShafts.cpp Noise3DGenerator.cpp PieceGeneratorBFSTree.cpp PieceModifier.cpp PiecePool.cpp PieceStructuresGen.cpp Prefab.cpp PrefabPiecePool.cpp PrefabStructure.cpp Ravines.cpp RoughRavines.cpp SinglePieceStructuresGen.cpp StructGen.cpp Trees.cpp TwoHeights.cpp VerticalLimit.cpp VerticalStrategy.cpp VillageGen.cpp BioGen.h Caves.h ChunkDesc.h ChunkGenerator.h CompoGen.h CompoGenBiomal.h ComposableGenerator.h CompositedHeiGen.h DistortedHeightmap.h DungeonRoomsFinisher.h EndGen.h EnderDragonFightStructuresGen.h FinishGen.h GridStructGen.h HeiGen.h IntGen.h MineShafts.h Noise3DGenerator.h PieceGeneratorBFSTree.h PieceModifier.h PiecePool.h PieceStructuresGen.h Prefab.h PrefabPiecePool.h PrefabStructure.h ProtIntGen.h Ravines.h RoughRavines.h ShapeGen.cpp SinglePieceStructuresGen.h StructGen.h Trees.h TwoHeights.h VerticalLimit.h VerticalStrategy.h VillageGen.h ) ================================================ FILE: src/Generating/Caves.cpp ================================================ // Caves.cpp // Implements the various cave structure generators: // - cStructGenWormNestCaves // - cStructGenDualRidgeCaves // - cStructGenMarbleCaves // - cStructGenNetherCaves /* WormNestCave generator: Caves are generated in "nests" - groups of tunnels generated from a single point. For each chunk, all the nests that could intersect it are generated. For each nest, first the schematic structure is generated (tunnel from ... to ..., branch, tunnel2 from ... to ...) Then each tunnel is randomized by inserting points in between its ends. Finally each tunnel is smoothed and Bresenham-3D-ed so that it is a collection of spheres with their centers next to each other. When the tunnels are ready, they are simply carved into the chunk, one by one. To optimize, each tunnel keeps track of its bounding box, so that it can be skipped for chunks that don't intersect it. MarbleCaves generator: For each voxel a 3D noise function is evaluated, if the value crosses a boundary, the voxel is dug out, otherwise it is kept. Problem with this is the amount of CPU work needed for each chunk. Also the overall shape of the generated holes is unsatisfactory - there are whole "sheets" of holes in the ground. DualRidgeCaves generator: Instead of evaluating a single noise function, two different noise functions are multiplied. This produces regular tunnels instead of sheets. However due to the sheer amount of CPU work needed, the noise functions need to be reduced in complexity in order for this generator to be useful, so the caves' shapes are "bubbly" at best. */ #include "Globals.h" #include "Caves.h" #include "../BlockInfo.h" const int MIN_RADIUS = 3; const int MAX_RADIUS = 8; struct cCaveDefPoint { int m_BlockX; int m_BlockY; int m_BlockZ; int m_Radius; cCaveDefPoint(int a_BlockX, int a_BlockY, int a_BlockZ, int a_Radius) : m_BlockX(a_BlockX), m_BlockY(a_BlockY), m_BlockZ(a_BlockZ), m_Radius(a_Radius) { } } ; typedef std::vector cCaveDefPoints; /** A single non-branching tunnel of a WormNestCave */ class cCaveTunnel { // The bounding box, including the radii around defpoints: int m_MinBlockX, m_MaxBlockX; int m_MinBlockY, m_MaxBlockY; int m_MinBlockZ, m_MaxBlockZ; /** Generates the shaping defpoints for the cave, based on the cave block coords and noise */ void Randomize(cNoise & a_Noise); /** Refines (adds and smooths) defpoints from a_Src into a_Dst; returns false if no refinement possible (segments too short) */ bool RefineDefPoints(const cCaveDefPoints & a_Src, cCaveDefPoints & a_Dst); /** Does rounds of smoothing, two passes of RefineDefPoints(), as long as they return true */ void Smooth(void); /** Linearly interpolates the points so that the maximum distance between two neighbors is max 1 block */ void FinishLinear(void); /** Calculates the bounding box of the points present */ void CalcBoundingBox(void); public: cCaveDefPoints m_Points; cCaveTunnel( int a_BlockStartX, int a_BlockStartY, int a_BlockStartZ, int a_StartRadius, int a_BlockEndX, int a_BlockEndY, int a_BlockEndZ, int a_EndRadius, cNoise & a_Noise ); /** Carves the tunnel into the chunk specified */ void ProcessChunk( int a_ChunkX, int a_ChunkZ, cChunkDef::BlockTypes & a_BlockTypes, cChunkDesc::BlockNibbleBytes & a_BlockMetas, cChunkDef::HeightMap & a_HeightMap ); #ifndef NDEBUG AString ExportAsSVG(int a_Color, int a_OffsetX, int a_OffsetZ) const; #endif // !NDEBUG } ; typedef std::vector cCaveTunnels; /** A collection of connected tunnels, possibly branching. */ class cStructGenWormNestCaves::cCaveSystem: public cGridStructGen::cStructure { using Super = cGridStructGen::cStructure; public: // The generating block position; is read directly in cStructGenWormNestCaves::GetCavesForChunk() int m_BlockX; int m_BlockZ; cCaveSystem(int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ, int a_MaxOffset, int a_Size, cNoise & a_Noise); virtual ~cCaveSystem() override; protected: int m_Size; cCaveTunnels m_Tunnels; void Clear(void); /** Generates a_Segment successive tunnels, with possible branches. Generates the same output for the same [x, y, z, a_Segments] */ void GenerateTunnelsFromPoint( int a_OriginX, int a_OriginY, int a_OriginZ, cNoise & a_Noise, int a_Segments ); /** Returns a radius based on the location provided. */ int GetRadius(cNoise & a_Noise, int a_OriginX, int a_OriginY, int a_OriginZ); // cGridStructGen::cStructure overrides: virtual void DrawIntoChunk(cChunkDesc & a_ChunkDesc) override; } ; //////////////////////////////////////////////////////////////////////////////// // cCaveTunnel: cCaveTunnel::cCaveTunnel( int a_BlockStartX, int a_BlockStartY, int a_BlockStartZ, int a_StartRadius, int a_BlockEndX, int a_BlockEndY, int a_BlockEndZ, int a_EndRadius, cNoise & a_Noise ) { m_Points.emplace_back(a_BlockStartX, a_BlockStartY, a_BlockStartZ, a_StartRadius); m_Points.emplace_back(a_BlockEndX, a_BlockEndY, a_BlockEndZ, a_EndRadius); if ((a_BlockStartY <= 0) && (a_BlockEndY <= 0)) { // Don't bother detailing this cave, it's under the world anyway m_MinBlockX = m_MaxBlockX = 0; m_MinBlockY = m_MaxBlockY = -1; m_MinBlockZ = m_MaxBlockZ = 0; return; } Randomize(a_Noise); Smooth(); // We know that the linear finishing won't affect the bounding box, so let's calculate it now, as we have less data: CalcBoundingBox(); FinishLinear(); } void cCaveTunnel::Randomize(cNoise & a_Noise) { // Repeat 4 times: for (int i = 0; i < 4; i++) { // For each already present point, insert a point in between it and its predecessor, shifted randomly. cCaveDefPoint & Point = m_Points.front(); int PrevX = Point.m_BlockX; int PrevY = Point.m_BlockY; int PrevZ = Point.m_BlockZ; int PrevR = Point.m_Radius; cCaveDefPoints Pts; Pts.reserve(m_Points.size() * 2 + 1); Pts.push_back(Point); for (cCaveDefPoints::const_iterator itr = m_Points.begin() + 1, end = m_Points.end(); itr != end; ++itr) { int Random = a_Noise.IntNoise3DInt(PrevX, PrevY, PrevZ + i) / 11; int len = (PrevX - itr->m_BlockX) * (PrevX - itr->m_BlockX); len += (PrevY - itr->m_BlockY) * (PrevY - itr->m_BlockY); len += (PrevZ - itr->m_BlockZ) * (PrevZ - itr->m_BlockZ); len = 3 * static_cast(sqrt(static_cast(len))) / 4; int Rad = std::min(MAX_RADIUS, std::max(MIN_RADIUS, (PrevR + itr->m_Radius) / 2 + (Random % 3) - 1)); Random /= 4; int x = (itr->m_BlockX + PrevX) / 2 + (Random % (len + 1) - len / 2); Random /= 256; int y = (itr->m_BlockY + PrevY) / 2 + (Random % (len / 2 + 1) - len / 4); Random /= 256; int z = (itr->m_BlockZ + PrevZ) / 2 + (Random % (len + 1) - len / 2); Pts.emplace_back(x, y, z, Rad); Pts.push_back(*itr); PrevX = itr->m_BlockX; PrevY = itr->m_BlockY; PrevZ = itr->m_BlockZ; PrevR = itr->m_Radius; } std::swap(Pts, m_Points); } } bool cCaveTunnel::RefineDefPoints(const cCaveDefPoints & a_Src, cCaveDefPoints & a_Dst) { if (a_Src.size() < 2) { // There are no midpoints, nothing to smooth return true; } // Smoothing: for each line segment, add points on its 1 / 4 lengths bool res = false; size_t Num = a_Src.size() - 2; // this many intermediary points a_Dst.clear(); a_Dst.reserve(Num * 2 + 2); cCaveDefPoints::const_iterator itr = a_Src.begin() + 1; const cCaveDefPoint & Source = a_Src.front(); a_Dst.push_back(Source); int PrevX = Source.m_BlockX; int PrevY = Source.m_BlockY; int PrevZ = Source.m_BlockZ; int PrevR = Source.m_Radius; for (size_t i = 0; i <= Num; ++i, ++itr) { int dx = itr->m_BlockX - PrevX; int dy = itr->m_BlockY - PrevY; int dz = itr->m_BlockZ - PrevZ; if (abs(dx) + abs(dz) + abs(dy) < 6) { // Too short a segment to smooth-subdivide into quarters PrevX = itr->m_BlockX; PrevY = itr->m_BlockY; PrevZ = itr->m_BlockZ; PrevR = itr->m_Radius; continue; } int dr = itr->m_Radius - PrevR; int Rad1 = std::max(PrevR + 1 * dr / 4, 1); int Rad2 = std::max(PrevR + 3 * dr / 4, 1); a_Dst.emplace_back(PrevX + 1 * dx / 4, PrevY + 1 * dy / 4, PrevZ + 1 * dz / 4, Rad1); a_Dst.emplace_back(PrevX + 3 * dx / 4, PrevY + 3 * dy / 4, PrevZ + 3 * dz / 4, Rad2); PrevX = itr->m_BlockX; PrevY = itr->m_BlockY; PrevZ = itr->m_BlockZ; PrevR = itr->m_Radius; res = true; } a_Dst.push_back(a_Src.back()); return res && (a_Src.size() < a_Dst.size()); } void cCaveTunnel::Smooth(void) { cCaveDefPoints Pts; for (;;) { if (!RefineDefPoints(m_Points, Pts)) { std::swap(Pts, m_Points); return; } if (!RefineDefPoints(Pts, m_Points)) { return; } } } void cCaveTunnel::FinishLinear(void) { // For each segment, use Bresenham's 3D line algorithm to draw a "line" of defpoints cCaveDefPoints Pts; std::swap(Pts, m_Points); m_Points.reserve(Pts.size() * 3); cCaveDefPoint & PrevPoint = Pts.front(); int PrevX = PrevPoint.m_BlockX; int PrevY = PrevPoint.m_BlockY; int PrevZ = PrevPoint.m_BlockZ; for (cCaveDefPoints::const_iterator itr = Pts.begin() + 1, end = Pts.end(); itr != end; ++itr) { int x1 = itr->m_BlockX; int y1 = itr->m_BlockY; int z1 = itr->m_BlockZ; int dx = abs(x1 - PrevX); int dy = abs(y1 - PrevY); int dz = abs(z1 - PrevZ); int sx = (PrevX < x1) ? 1 : -1; int sy = (PrevY < y1) ? 1 : -1; int sz = (PrevZ < z1) ? 1 : -1; int R = itr->m_Radius; if (dx >= std::max(dy, dz)) // x dominant { int yd = dy - dx / 2; int zd = dz - dx / 2; for (;;) { m_Points.emplace_back(PrevX, PrevY, PrevZ, R); if (PrevX == x1) { break; } if (yd >= 0) // move along y { PrevY += sy; yd -= dx; } if (zd >= 0) // move along z { PrevZ += sz; zd -= dx; } // move along x PrevX += sx; yd += dy; zd += dz; } } else if (dy >= std::max(dx, dz)) // y dominant { int xd = dx - dy / 2; int zd = dz - dy / 2; for (;;) { m_Points.emplace_back(PrevX, PrevY, PrevZ, R); if (PrevY == y1) { break; } if (xd >= 0) // move along x { PrevX += sx; xd -= dy; } if (zd >= 0) // move along z { PrevZ += sz; zd -= dy; } // move along y PrevY += sy; xd += dx; zd += dz; } } else { // z dominant ASSERT(dz >= std::max(dx, dy)); int xd = dx - dz / 2; int yd = dy - dz / 2; for (;;) { m_Points.emplace_back(PrevX, PrevY, PrevZ, R); if (PrevZ == z1) { break; } if (xd >= 0) // move along x { PrevX += sx; xd -= dz; } if (yd >= 0) // move along y { PrevY += sy; yd -= dz; } // move along z PrevZ += sz; xd += dx; yd += dy; } } // if (which dimension is dominant) } // for itr } void cCaveTunnel::CalcBoundingBox(void) { cCaveDefPoint & Point = m_Points.front(); m_MinBlockX = m_MaxBlockX = Point.m_BlockX; m_MinBlockY = m_MaxBlockY = Point.m_BlockY; m_MinBlockZ = m_MaxBlockZ = Point.m_BlockZ; for (cCaveDefPoints::const_iterator itr = m_Points.begin() + 1, end = m_Points.end(); itr != end; ++itr) { m_MinBlockX = std::min(m_MinBlockX, itr->m_BlockX - itr->m_Radius); m_MaxBlockX = std::max(m_MaxBlockX, itr->m_BlockX + itr->m_Radius); m_MinBlockY = std::min(m_MinBlockY, itr->m_BlockY - itr->m_Radius); m_MaxBlockY = std::max(m_MaxBlockY, itr->m_BlockY + itr->m_Radius); m_MinBlockZ = std::min(m_MinBlockZ, itr->m_BlockZ - itr->m_Radius); m_MaxBlockZ = std::max(m_MaxBlockZ, itr->m_BlockZ + itr->m_Radius); } // for itr - m_Points[] } void cCaveTunnel::ProcessChunk( int a_ChunkX, int a_ChunkZ, cChunkDef::BlockTypes & a_BlockTypes, cChunkDesc::BlockNibbleBytes & a_BlockMetas, cChunkDef::HeightMap & a_HeightMap ) { int BaseX = a_ChunkX * cChunkDef::Width; int BaseZ = a_ChunkZ * cChunkDef::Width; if ( (BaseX > m_MaxBlockX) || (BaseX + cChunkDef::Width < m_MinBlockX) || (BaseZ > m_MaxBlockZ) || (BaseZ + cChunkDef::Width < m_MinBlockZ) ) { // Tunnel does not intersect the chunk at all, bail out return; } int BlockStartX = a_ChunkX * cChunkDef::Width; int BlockStartZ = a_ChunkZ * cChunkDef::Width; int BlockEndX = BlockStartX + cChunkDef::Width; int BlockEndZ = BlockStartZ + cChunkDef::Width; for (cCaveDefPoints::const_iterator itr = m_Points.begin(), end = m_Points.end(); itr != end; ++itr) { if ( (itr->m_BlockX + itr->m_Radius < BlockStartX) || (itr->m_BlockX - itr->m_Radius > BlockEndX) || (itr->m_BlockZ + itr->m_Radius < BlockStartZ) || (itr->m_BlockZ - itr->m_Radius > BlockEndZ) ) { // Cannot intersect, bail out early continue; } // Carve out a sphere around the xyz point, m_Radius in diameter; skip 3 / 7 off the top and bottom: int DifX = itr->m_BlockX - BlockStartX; // substitution for faster calc int DifY = itr->m_BlockY; int DifZ = itr->m_BlockZ - BlockStartZ; // substitution for faster calc int Bottom = std::max(itr->m_BlockY - 3 * itr->m_Radius / 7, 1); int Top = std::min(itr->m_BlockY + 3 * itr->m_Radius / 7, static_cast(cChunkDef::Height)); int SqRad = itr->m_Radius * itr->m_Radius; for (int z = 0; z < cChunkDef::Width; z++) for (int x = 0; x < cChunkDef::Width; x++) { for (int y = Bottom; y <= Top; y++) { int SqDist = (DifX - x) * (DifX - x) + (DifY - y) * (DifY - y) + (DifZ - z) * (DifZ - z); if (4 * SqDist <= SqRad) { if (cBlockInfo::CanBeTerraformed(cChunkDef::GetBlock(a_BlockTypes, x, y, z))) { cChunkDef::SetBlock(a_BlockTypes, x, y, z, E_BLOCK_AIR); } } else if (SqDist <= SqRad * 2) { if (cChunkDef::GetBlock(a_BlockTypes, x, y, z) == E_BLOCK_SAND) { const auto Index = cChunkDef::MakeIndex(x, y, z); if (a_BlockMetas[Index] == 1) { a_BlockMetas[Index] = 0; cChunkDef::SetBlock(a_BlockTypes, x, y, z, E_BLOCK_RED_SANDSTONE); } else { cChunkDef::SetBlock(a_BlockTypes, x, y, z, E_BLOCK_SANDSTONE); } } } } // for y } // for x, z } // for itr - m_Points[] /* #ifndef NDEBUG // For debugging purposes, outline the shape of the cave using glowstone, after carving the entire cave: for (cCaveDefPoints::const_iterator itr = m_Points.begin(), end = m_Points.end(); itr != end; ++itr) { int DifX = itr->m_BlockX - BlockStartX; // substitution for faster calc int DifZ = itr->m_BlockZ - BlockStartZ; // substitution for faster calc if ( (DifX >= 0) && (DifX < cChunkDef::Width) && (itr->m_BlockY > 0) && (itr->m_BlockY < cChunkDef::Height) && (DifZ >= 0) && (DifZ < cChunkDef::Width) ) { cChunkDef::SetBlock(a_BlockTypes, DifX, itr->m_BlockY, DifZ, E_BLOCK_GLOWSTONE); } } // for itr - m_Points[] #endif // !NDEBUG //*/ } #ifndef NDEBUG AString cCaveTunnel::ExportAsSVG(int a_Color, int a_OffsetX, int a_OffsetZ) const { AString SVG; SVG.reserve(m_Points.size() * 20 + 200); SVG.append(fmt::format(FMT_STRING("m_BlockX, a_OffsetZ + itr->m_BlockZ)); Prefix = 'L'; } SVG.append("\"/>\n"); return SVG; } #endif // !NDEBUG //////////////////////////////////////////////////////////////////////////////// // cStructGenWormNestCaves::cCaveSystem: cStructGenWormNestCaves::cCaveSystem::cCaveSystem(int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ, int a_MaxOffset, int a_Size, cNoise & a_Noise) : Super(a_GridX, a_GridZ, a_OriginX, a_OriginZ), m_Size(a_Size) { int Num = 1 + a_Noise.IntNoise2DInt(a_OriginX, a_OriginZ) % 3; for (int i = 0; i < Num; i++) { int OriginX = a_OriginX + (a_Noise.IntNoise3DInt(13 * a_OriginX, 17 * a_OriginZ, 11 * i) / 19) % a_MaxOffset; int OriginZ = a_OriginZ + (a_Noise.IntNoise3DInt(17 * a_OriginX, 13 * a_OriginZ, 11 * i) / 23) % a_MaxOffset; int OriginY = 20 + (a_Noise.IntNoise3DInt(19 * a_OriginX, 13 * a_OriginZ, 11 * i) / 17) % 20; // Generate three branches from the origin point: // The tunnels generated depend on X, Y, Z and Branches, // for the same set of numbers it generates the same offsets! // That's why we add a +1 to X in the third line GenerateTunnelsFromPoint(OriginX, OriginY, OriginZ, a_Noise, 3); GenerateTunnelsFromPoint(OriginX, OriginY, OriginZ, a_Noise, 2); GenerateTunnelsFromPoint(OriginX + 1, OriginY, OriginZ, a_Noise, 3); } } cStructGenWormNestCaves::cCaveSystem::~cCaveSystem() { Clear(); } void cStructGenWormNestCaves::cCaveSystem::DrawIntoChunk(cChunkDesc & a_ChunkDesc) { int ChunkX = a_ChunkDesc.GetChunkX(); int ChunkZ = a_ChunkDesc.GetChunkZ(); cChunkDef::BlockTypes & BlockTypes = a_ChunkDesc.GetBlockTypes(); cChunkDef::HeightMap & HeightMap = a_ChunkDesc.GetHeightMap(); cChunkDesc::BlockNibbleBytes & BlockMetas = a_ChunkDesc.GetBlockMetasUncompressed(); for (cCaveTunnels::const_iterator itr = m_Tunnels.begin(), end = m_Tunnels.end(); itr != end; ++itr) { (*itr)->ProcessChunk(ChunkX, ChunkZ, BlockTypes, BlockMetas, HeightMap); } // for itr - m_Tunnels[] } void cStructGenWormNestCaves::cCaveSystem::Clear(void) { for (cCaveTunnels::const_iterator itr = m_Tunnels.begin(), end = m_Tunnels.end(); itr != end; ++itr) { delete *itr; } m_Tunnels.clear(); } void cStructGenWormNestCaves::cCaveSystem::GenerateTunnelsFromPoint( int a_OriginX, int a_OriginY, int a_OriginZ, cNoise & a_Noise, int a_NumSegments ) { int DoubleSize = m_Size * 2; int Radius = GetRadius(a_Noise, a_OriginX + a_OriginY, a_OriginY + a_OriginZ, a_OriginZ + a_OriginX); for (int i = a_NumSegments - 1; i >= 0; --i) { int EndX = a_OriginX + (((a_Noise.IntNoise3DInt(a_OriginX, a_OriginY, a_OriginZ + 11 * a_NumSegments) / 7) % DoubleSize) - m_Size) / 2; int EndY = a_OriginY + (((a_Noise.IntNoise3DInt(a_OriginY, 13 * a_NumSegments, a_OriginZ + a_OriginX) / 7) % DoubleSize) - m_Size) / 4; int EndZ = a_OriginZ + (((a_Noise.IntNoise3DInt(a_OriginZ + 17 * a_NumSegments, a_OriginX, a_OriginY) / 7) % DoubleSize) - m_Size) / 2; int EndR = GetRadius(a_Noise, a_OriginX + 7 * i, a_OriginY + 11 * i, a_OriginZ + a_OriginX); m_Tunnels.push_back(new cCaveTunnel(a_OriginX, a_OriginY, a_OriginZ, Radius, EndX, EndY, EndZ, EndR, a_Noise)); GenerateTunnelsFromPoint(EndX, EndY, EndZ, a_Noise, i); a_OriginX = EndX; a_OriginY = EndY; a_OriginZ = EndZ; Radius = EndR; } // for i - a_NumSegments } int cStructGenWormNestCaves::cCaveSystem::GetRadius(cNoise & a_Noise, int a_OriginX, int a_OriginY, int a_OriginZ) { // Instead of a flat distribution noise function, we need to shape it, so that most caves are smallish and only a few select are large int rnd = a_Noise.IntNoise3DInt(a_OriginX, a_OriginY, a_OriginZ) / 11; /* // Not good enough: // The algorithm of choice: emulate gauss-distribution noise by adding 3 flat noises, then fold it in half using absolute value. // To save on processing, use one random value and extract 3 bytes to be separately added as the gaussian noise int sum = (rnd & 0xff) + ((rnd >> 8) & 0xff) + ((rnd >> 16) & 0xff); // sum is now a gaussian-distribution noise within [0 .. 767], with center at 384. // We want mapping 384 -> 3, 0 -> 19, 768 -> 19, so divide by 24 to get [0 .. 31] with center at 16, then use abs() to fold around the center int res = 3 + abs((sum / 24) - 16); */ // Algorithm of choice: random value in the range of zero to random value - heavily towards zero int res = MIN_RADIUS + (rnd >> 8) % ((rnd % (MAX_RADIUS - MIN_RADIUS)) + 1); return res; } //////////////////////////////////////////////////////////////////////////////// // cStructGenWormNestCaves: cGridStructGen::cStructurePtr cStructGenWormNestCaves::CreateStructure(int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ) { return cStructurePtr(new cCaveSystem(a_GridX, a_GridZ, a_OriginX, a_OriginZ, m_MaxOffset, m_Size, m_Noise)); } //////////////////////////////////////////////////////////////////////////////// // cStructGenMarbleCaves: static float GetMarbleNoise( float x, float y, float z, cNoise & a_Noise) { static const float PI_2 = 1.57079633f; float oct1 = (a_Noise.CubicNoise3D(x * 0.1f, y * 0.1f, z * 0.1f)) * 4; oct1 = oct1 * oct1 * oct1; if (oct1 < 0.f) { oct1 = PI_2; } if (oct1 > PI_2) { oct1 = PI_2; } return oct1; } void cStructGenMarbleCaves::GenFinish(cChunkDesc & a_ChunkDesc) { cNoise Noise(m_Seed); for (int z = 0; z < cChunkDef::Width; z++) { const float zz = static_cast(a_ChunkDesc.GetChunkZ() * cChunkDef::Width + z); for (int x = 0; x < cChunkDef::Width; x++) { const float xx = static_cast(a_ChunkDesc.GetChunkX() * cChunkDef::Width + x); int Top = a_ChunkDesc.GetHeight(x, z); for (int y = 1; y < Top; ++y) { if (a_ChunkDesc.GetBlockType(x, y, z) != E_BLOCK_STONE) { continue; } const float yy = static_cast(y); const float WaveNoise = 1; if (cosf(GetMarbleNoise(xx, yy * 0.5f, zz, Noise)) * fabs(cosf(yy * 0.2f + WaveNoise * 2) * 0.75f + WaveNoise) > 0.0005f) { a_ChunkDesc.SetBlockType(x, y, z, E_BLOCK_AIR); } } // for y } // for x } // for z } //////////////////////////////////////////////////////////////////////////////// // cStructGenDualRidgeCaves: void cStructGenDualRidgeCaves::GenFinish(cChunkDesc & a_ChunkDesc) { for (int z = 0; z < cChunkDef::Width; z++) { const float zz = static_cast(a_ChunkDesc.GetChunkZ() * cChunkDef::Width + z) / 10; for (int x = 0; x < cChunkDef::Width; x++) { const float xx = static_cast(a_ChunkDesc.GetChunkX() * cChunkDef::Width + x) / 10; int Top = a_ChunkDesc.GetHeight(x, z); for (int y = 1; y <= Top; ++y) { const float yy = static_cast(y / 10); float n1 = m_Noise1.CubicNoise3D(xx, yy, zz); float n2 = m_Noise2.CubicNoise3D(xx, yy, zz); float n3 = m_Noise1.CubicNoise3D(xx * 4, yy * 4, zz * 4) / 4; float n4 = m_Noise2.CubicNoise3D(xx * 4, yy * 4, zz * 4) / 4; if ((std::abs(n1 + n3) * std::abs(n2 + n4)) > m_Threshold) { a_ChunkDesc.SetBlockType(x, y, z, E_BLOCK_AIR); } } // for y } // for x } // for z } ================================================ FILE: src/Generating/Caves.h ================================================ // Caves.h // Interfaces to the various cave structure generators: // - cStructGenWormNestCaves // - cStructGenMarbleCaves // - cStructGenNetherCaves #pragma once #include "GridStructGen.h" class cStructGenMarbleCaves : public cFinishGen { public: cStructGenMarbleCaves(int a_Seed) : m_Seed(a_Seed) {} protected: int m_Seed; // cFinishGen override: virtual void GenFinish(cChunkDesc & a_ChunkDesc) override; } ; class cStructGenDualRidgeCaves : public cFinishGen { public: cStructGenDualRidgeCaves(int a_Seed, float a_Threshold) : m_Noise1(a_Seed), m_Noise2(2 * a_Seed + 19999), m_Seed(a_Seed), m_Threshold(a_Threshold) { } protected: cNoise m_Noise1; cNoise m_Noise2; int m_Seed; float m_Threshold; // cFinishGen override: virtual void GenFinish(cChunkDesc & a_ChunkDesc) override; } ; class cStructGenWormNestCaves: public cGridStructGen { using Super = cGridStructGen; public: cStructGenWormNestCaves(int a_Seed, int a_Size = 64, int a_Grid = 96, int a_MaxOffset = 128) : Super(a_Seed, a_Grid, a_Grid, a_MaxOffset, a_MaxOffset, a_Size, a_Size, 100), m_Size(a_Size), m_MaxOffset(a_MaxOffset), m_Grid(a_Grid) { } protected: class cCaveSystem; // fwd: Caves.cpp int m_Size; // relative size of the cave systems' caves. Average number of blocks of each initial tunnel int m_MaxOffset; // maximum offset of the cave nest origin from the grid cell the nest belongs to int m_Grid; // average spacing of the nests // cGridStructGen override: virtual cStructurePtr CreateStructure(int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ) override; } ; ================================================ FILE: src/Generating/ChunkDesc.cpp ================================================ // ChunkDesc.cpp // Implements the cChunkDesc class representing the chunk description used while generating a chunk. This class is also exported to Lua for HOOK_CHUNK_GENERATING. #include "Globals.h" #include "ChunkDesc.h" #include "../Noise/Noise.h" #include "../BlockEntities/BlockEntity.h" #include "../Entities/Entity.h" cChunkDesc::cChunkDesc(cChunkCoords a_Coords) : m_Coords(a_Coords), m_bUseDefaultBiomes(true), m_bUseDefaultHeight(true), m_bUseDefaultComposition(true), m_bUseDefaultFinish(true) { m_BlockArea.Create(cChunkDef::Width, cChunkDef::Height, cChunkDef::Width); /* memset(m_BlockTypes, 0, sizeof(cChunkDef::BlockTypes)); memset(m_BlockMeta, 0, sizeof(cChunkDef::BlockNibbles)); */ memset(m_BiomeMap, 0, sizeof(cChunkDef::BiomeMap)); memset(m_HeightMap, 0, sizeof(cChunkDef::HeightMap)); } cChunkDesc::~cChunkDesc() { // Nothing needed yet } void cChunkDesc::SetChunkCoords(cChunkCoords a_Coords) { m_Coords = a_Coords; } void cChunkDesc::FillBlocks(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) { m_BlockArea.Fill(cBlockArea::baTypes | cBlockArea::baMetas, a_BlockType, a_BlockMeta); } void cChunkDesc::SetBlockTypeMeta(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) { m_BlockArea.SetRelBlockTypeMeta(a_RelX, a_RelY, a_RelZ, a_BlockType, a_BlockMeta); } void cChunkDesc::GetBlockTypeMeta(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta) const { m_BlockArea.GetRelBlockTypeMeta(a_RelX, a_RelY, a_RelZ, a_BlockType, a_BlockMeta); } void cChunkDesc::SetBlockType(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType) { cChunkDef::SetBlock(m_BlockArea.GetBlockTypes(), a_RelX, a_RelY, a_RelZ, a_BlockType); } BLOCKTYPE cChunkDesc::GetBlockType(int a_RelX, int a_RelY, int a_RelZ) const { return cChunkDef::GetBlock(m_BlockArea.GetBlockTypes(), a_RelX, a_RelY, a_RelZ); } NIBBLETYPE cChunkDesc::GetBlockMeta(int a_RelX, int a_RelY, int a_RelZ) const { return m_BlockArea.GetRelBlockMeta(a_RelX, a_RelY, a_RelZ); } void cChunkDesc::SetBlockMeta(int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_BlockMeta) { m_BlockArea.SetRelBlockMeta(a_RelX, a_RelY, a_RelZ, a_BlockMeta); } void cChunkDesc::SetBiome(int a_RelX, int a_RelZ, EMCSBiome a_BiomeID) { cChunkDef::SetBiome(m_BiomeMap, a_RelX, a_RelZ, a_BiomeID); } EMCSBiome cChunkDesc::GetBiome(int a_RelX, int a_RelZ) const { return cChunkDef::GetBiome(m_BiomeMap, a_RelX, a_RelZ); } void cChunkDesc::SetHeight(int a_RelX, int a_RelZ, HEIGHTTYPE a_Height) { cChunkDef::SetHeight(m_HeightMap, a_RelX, a_RelZ, a_Height); } HEIGHTTYPE cChunkDesc::GetHeight(int a_RelX, int a_RelZ) const { return cChunkDef::GetHeight(m_HeightMap, a_RelX, a_RelZ); } void cChunkDesc::SetHeightFromShape(const Shape & a_Shape) { for (int z = 0; z < cChunkDef::Width; z++) { for (int x = 0; x < cChunkDef::Width; x++) { for (HEIGHTTYPE y = cChunkDef::Height - 1; y > 0; y--) { if (a_Shape[y + x * 256 + z * 16 * 256] != 0) { cChunkDef::SetHeight(m_HeightMap, x, z, y); break; } } // for y } // for x } // for z } void cChunkDesc::GetShapeFromHeight(Shape & a_Shape) const { for (int z = 0; z < cChunkDef::Width; z++) { for (int x = 0; x < cChunkDef::Width; x++) { int height = cChunkDef::GetHeight(m_HeightMap, x, z); for (int y = 0; y <= height; y++) { a_Shape[y + x * 256 + z * 16 * 256] = 1; } for (int y = height + 1; y < cChunkDef::Height; y++) { a_Shape[y + x * 256 + z * 16 * 256] = 0; } // for y } // for x } // for z } void cChunkDesc::SetUseDefaultBiomes(bool a_bUseDefaultBiomes) { m_bUseDefaultBiomes = a_bUseDefaultBiomes; } bool cChunkDesc::IsUsingDefaultBiomes(void) const { return m_bUseDefaultBiomes; } void cChunkDesc::SetUseDefaultHeight(bool a_bUseDefaultHeight) { m_bUseDefaultHeight = a_bUseDefaultHeight; } bool cChunkDesc::IsUsingDefaultHeight(void) const { return m_bUseDefaultHeight; } void cChunkDesc::SetUseDefaultComposition(bool a_bUseDefaultComposition) { m_bUseDefaultComposition = a_bUseDefaultComposition; } bool cChunkDesc::IsUsingDefaultComposition(void) const { return m_bUseDefaultComposition; } void cChunkDesc::SetUseDefaultFinish(bool a_bUseDefaultFinish) { m_bUseDefaultFinish = a_bUseDefaultFinish; } bool cChunkDesc::IsUsingDefaultFinish(void) const { return m_bUseDefaultFinish; } void cChunkDesc::WriteBlockArea(const cBlockArea & a_BlockArea, int a_RelX, int a_RelY, int a_RelZ, cBlockArea::eMergeStrategy a_MergeStrategy) { m_BlockArea.Merge(a_BlockArea, a_RelX, a_RelY, a_RelZ, a_MergeStrategy); } void cChunkDesc::ReadBlockArea(cBlockArea & a_Dest, int a_MinRelX, int a_MaxRelX, int a_MinRelY, int a_MaxRelY, int a_MinRelZ, int a_MaxRelZ) { // Normalize the coords: if (a_MinRelX > a_MaxRelX) { std::swap(a_MinRelX, a_MaxRelX); } if (a_MinRelY > a_MaxRelY) { std::swap(a_MinRelY, a_MaxRelY); } if (a_MinRelZ > a_MaxRelZ) { std::swap(a_MinRelZ, a_MaxRelZ); } // Include the Max coords: a_MaxRelX += 1; a_MaxRelY += 1; a_MaxRelZ += 1; // Check coords validity: if (a_MinRelX < 0) { LOGWARNING("%s: MinRelX less than zero, adjusting to zero", __FUNCTION__); a_MinRelX = 0; } else if (a_MinRelX >= cChunkDef::Width) { LOGWARNING("%s: MinRelX more than chunk width, adjusting to chunk width", __FUNCTION__); a_MinRelX = cChunkDef::Width - 1; } if (a_MaxRelX < 0) { LOGWARNING("%s: MaxRelX less than zero, adjusting to zero", __FUNCTION__); a_MaxRelX = 0; } else if (a_MaxRelX > cChunkDef::Width) { LOGWARNING("%s: MaxRelX more than chunk width, adjusting to chunk width", __FUNCTION__); a_MaxRelX = cChunkDef::Width; } if (a_MinRelY < 0) { LOGWARNING("%s: MinRelY less than zero, adjusting to zero", __FUNCTION__); a_MinRelY = 0; } else if (a_MinRelY >= cChunkDef::Height) { LOGWARNING("%s: MinRelY more than chunk height, adjusting to chunk height", __FUNCTION__); a_MinRelY = cChunkDef::Height - 1; } if (a_MaxRelY < 0) { LOGWARNING("%s: MaxRelY less than zero, adjusting to zero", __FUNCTION__); a_MaxRelY = 0; } else if (a_MaxRelY > cChunkDef::Height) { LOGWARNING("%s: MaxRelY more than chunk height, adjusting to chunk height", __FUNCTION__); a_MaxRelY = cChunkDef::Height; } if (a_MinRelZ < 0) { LOGWARNING("%s: MinRelZ less than zero, adjusting to zero", __FUNCTION__); a_MinRelZ = 0; } else if (a_MinRelZ >= cChunkDef::Width) { LOGWARNING("%s: MinRelZ more than chunk width, adjusting to chunk width", __FUNCTION__); a_MinRelZ = cChunkDef::Width - 1; } if (a_MaxRelZ < 0) { LOGWARNING("%s: MaxRelZ less than zero, adjusting to zero", __FUNCTION__); a_MaxRelZ = 0; } else if (a_MaxRelZ > cChunkDef::Width) { LOGWARNING("%s: MaxRelZ more than chunk width, adjusting to chunk width", __FUNCTION__); a_MaxRelZ = cChunkDef::Width; } // Prepare the block area: int SizeX = a_MaxRelX - a_MinRelX; int SizeY = a_MaxRelY - a_MinRelY; int SizeZ = a_MaxRelZ - a_MinRelZ; a_Dest.Clear(); a_Dest.m_Origin.x = m_Coords.m_ChunkX * cChunkDef::Width + a_MinRelX; a_Dest.m_Origin.y = a_MinRelY; a_Dest.m_Origin.z = m_Coords.m_ChunkZ * cChunkDef::Width + a_MinRelZ; a_Dest.SetSize(SizeX, SizeY, SizeZ, cBlockArea::baTypes | cBlockArea::baMetas); for (int y = 0; y < SizeY; y++) { int CDY = a_MinRelY + y; for (int z = 0; z < SizeZ; z++) { int CDZ = a_MinRelZ + z; for (int x = 0; x < SizeX; x++) { int CDX = a_MinRelX + x; BLOCKTYPE BlockType; NIBBLETYPE BlockMeta; GetBlockTypeMeta(CDX, CDY, CDZ, BlockType, BlockMeta); a_Dest.SetRelBlockTypeMeta(x, y, z, BlockType, BlockMeta); } // for x } // for z } // for y } HEIGHTTYPE cChunkDesc::GetMaxHeight(void) const { HEIGHTTYPE MaxHeight = m_HeightMap[0]; for (size_t i = 1; i < ARRAYCOUNT(m_HeightMap); i++) { if (m_HeightMap[i] > MaxHeight) { MaxHeight = m_HeightMap[i]; } } return MaxHeight; } HEIGHTTYPE cChunkDesc::GetMinHeight(void) const { HEIGHTTYPE MinHeight = m_HeightMap[0]; for (size_t i = 1; i < ARRAYCOUNT(m_HeightMap); i++) { if (m_HeightMap[i] < MinHeight) { MinHeight = m_HeightMap[i]; } } return MinHeight; } void cChunkDesc::FillRelCuboid( int a_MinX, int a_MaxX, int a_MinY, int a_MaxY, int a_MinZ, int a_MaxZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta ) { int MinX = std::max(a_MinX, 0); int MinY = std::max(a_MinY, 0); int MinZ = std::max(a_MinZ, 0); int MaxX = std::min(a_MaxX, cChunkDef::Width - 1); int MaxY = std::min(a_MaxY, cChunkDef::Height - 1); int MaxZ = std::min(a_MaxZ, cChunkDef::Width - 1); for (int y = MinY; y <= MaxY; y++) { for (int z = MinZ; z <= MaxZ; z++) { for (int x = MinX; x <= MaxX; x++) { SetBlockTypeMeta(x, y, z, a_BlockType, a_BlockMeta); } } // for z } // for y } void cChunkDesc::ReplaceRelCuboid( int a_MinX, int a_MaxX, int a_MinY, int a_MaxY, int a_MinZ, int a_MaxZ, BLOCKTYPE a_SrcType, NIBBLETYPE a_SrcMeta, BLOCKTYPE a_DstType, NIBBLETYPE a_DstMeta ) { int MinX = std::max(a_MinX, 0); int MinY = std::max(a_MinY, 0); int MinZ = std::max(a_MinZ, 0); int MaxX = std::min(a_MaxX, cChunkDef::Width - 1); int MaxY = std::min(a_MaxY, cChunkDef::Height - 1); int MaxZ = std::min(a_MaxZ, cChunkDef::Width - 1); for (int y = MinY; y <= MaxY; y++) { for (int z = MinZ; z <= MaxZ; z++) { for (int x = MinX; x <= MaxX; x++) { BLOCKTYPE BlockType; NIBBLETYPE BlockMeta; GetBlockTypeMeta(x, y, z, BlockType, BlockMeta); if ((BlockType == a_SrcType) && (BlockMeta == a_SrcMeta)) { SetBlockTypeMeta(x, y, z, a_DstType, a_DstMeta); } } } // for z } // for y } void cChunkDesc::FloorRelCuboid( int a_MinX, int a_MaxX, int a_MinY, int a_MaxY, int a_MinZ, int a_MaxZ, BLOCKTYPE a_DstType, NIBBLETYPE a_DstMeta ) { int MinX = std::max(a_MinX, 0); int MinY = std::max(a_MinY, 0); int MinZ = std::max(a_MinZ, 0); int MaxX = std::min(a_MaxX, cChunkDef::Width - 1); int MaxY = std::min(a_MaxY, cChunkDef::Height - 1); int MaxZ = std::min(a_MaxZ, cChunkDef::Width - 1); for (int y = MinY; y <= MaxY; y++) { for (int z = MinZ; z <= MaxZ; z++) { for (int x = MinX; x <= MaxX; x++) { switch (GetBlockType(x, y, z)) { case E_BLOCK_AIR: case E_BLOCK_WATER: case E_BLOCK_STATIONARY_WATER: { SetBlockTypeMeta(x, y, z, a_DstType, a_DstMeta); break; } } // switch (GetBlockType) } // for x } // for z } // for y } void cChunkDesc::RandomFillRelCuboid( int a_MinX, int a_MaxX, int a_MinY, int a_MaxY, int a_MinZ, int a_MaxZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_RandomSeed, int a_ChanceOutOf10k ) { cNoise Noise(a_RandomSeed); int MinX = std::max(a_MinX, 0); int MinY = std::max(a_MinY, 0); int MinZ = std::max(a_MinZ, 0); int MaxX = std::min(a_MaxX, cChunkDef::Width - 1); int MaxY = std::min(a_MaxY, cChunkDef::Height - 1); int MaxZ = std::min(a_MaxZ, cChunkDef::Width - 1); for (int y = MinY; y <= MaxY; y++) { for (int z = MinZ; z <= MaxZ; z++) { for (int x = MinX; x <= MaxX; x++) { int rnd = (Noise.IntNoise3DInt(x, y, z) / 7) % 10000; if (rnd <= a_ChanceOutOf10k) { SetBlockTypeMeta(x, y, z, a_BlockType, a_BlockMeta); } } } // for z } // for y } cBlockEntity * cChunkDesc::GetBlockEntity(int a_RelX, int a_RelY, int a_RelZ) { const auto Idx = cChunkDef::MakeIndex(a_RelX, a_RelY, a_RelZ); const auto Iterator = m_BlockArea.GetBlockEntities().find(Idx); if (Iterator != m_BlockArea.GetBlockEntities().end()) { // Already in the list: cBlockEntity * BlockEntity = Iterator->second.get(); if (BlockEntity->GetBlockType() == GetBlockType(a_RelX, a_RelY, a_RelZ)) { // Correct type, already present. Return it: return BlockEntity; } else { // Wrong type, the block type has been overwritten. Erase and create new: m_BlockArea.GetBlockEntities().erase(Iterator); } } int AbsX = a_RelX + m_Coords.m_ChunkX * cChunkDef::Width; int AbsZ = a_RelZ + m_Coords.m_ChunkZ * cChunkDef::Width; // The block entity is not created yet, try to create it and add to list: auto BlockEntity = cBlockEntity::CreateByBlockType(GetBlockType(a_RelX, a_RelY, a_RelZ), GetBlockMeta(a_RelX, a_RelY, a_RelZ), {AbsX, a_RelY, AbsZ}); if (BlockEntity == nullptr) { // No block entity for this block type return nullptr; } auto res = m_BlockArea.GetBlockEntities().emplace(Idx, std::move(BlockEntity)); return res.first->second.get(); } void cChunkDesc::UpdateHeightmap(void) { for (int x = 0; x < cChunkDef::Width; x++) { for (int z = 0; z < cChunkDef::Width; z++) { HEIGHTTYPE Height = 0; for (HEIGHTTYPE y = cChunkDef::Height - 1; y > 0; y--) { BLOCKTYPE BlockType = GetBlockType(x, y, z); if (BlockType != E_BLOCK_AIR) { Height = y; break; } } // for y SetHeight(x, z, Height); } // for z } // for x } void cChunkDesc::CompressBlockMetas(cChunkDef::BlockNibbles & a_DestMetas) { const NIBBLETYPE * AreaMetas = m_BlockArea.GetBlockMetas(); for (size_t i = 0; i < ARRAYCOUNT(a_DestMetas); i++) { a_DestMetas[i] = static_cast(AreaMetas[2 * i] | (AreaMetas[2 * i + 1] << 4)); } } #ifndef NDEBUG void cChunkDesc::VerifyHeightmap(void) { for (int x = 0; x < cChunkDef::Width; x++) { for (int z = 0; z < cChunkDef::Width; z++) { for (int y = cChunkDef::Height - 1; y > 0; y--) { BLOCKTYPE BlockType = GetBlockType(x, y, z); if (BlockType != E_BLOCK_AIR) { int Height = GetHeight(x, z); ASSERT(Height == y); break; } } // for y } // for z } // for x } #endif // !NDEBUG ================================================ FILE: src/Generating/ChunkDesc.h ================================================ // ChunkDesc.h // Declares the cChunkDesc class representing the chunk description used while generating a chunk. This class is also exported to Lua for HOOK_CHUNK_GENERATING. #pragma once #include "../BlockArea.h" #include "../Cuboid.h" // fwd: ../BlockArea.h class cBlockArea; // tolua_begin class cChunkDesc { public: // tolua_end /** The datatype used to represent the entire chunk worth of shape. 0 = air 1 = solid Indexed as [y + 256 * x + 256 * 16 * z]. */ typedef Byte Shape[256 * 16 * 16]; /** Uncompressed block metas, 1 meta per byte */ typedef NIBBLETYPE BlockNibbleBytes[cChunkDef::NumBlocks]; cChunkDesc(cChunkCoords a_Coords); ~cChunkDesc(); void SetChunkCoords(cChunkCoords a_Coords); // tolua_begin int GetChunkX() const { return m_Coords.m_ChunkX; } // Prefer GetChunkCoords() instead int GetChunkZ() const { return m_Coords.m_ChunkZ; } // Prefer GetChunkCoords() instead // tolua_end cChunkCoords GetChunkCoords() const { return m_Coords; } // tolua_begin void FillBlocks(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta); void SetBlockTypeMeta(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta); // tolua_end /** Returns the BlockType and BlockMeta at the specified coords. Exported to Lua manually to avoid extra parameters generated by ToLua++. */ void GetBlockTypeMeta(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta) const; // tolua_begin void SetBlockType(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType); BLOCKTYPE GetBlockType(int a_RelX, int a_RelY, int a_RelZ) const; void SetBlockMeta(int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_BlockMeta); NIBBLETYPE GetBlockMeta(int a_RelX, int a_RelY, int a_RelZ) const; void SetBiome(int a_RelX, int a_RelZ, EMCSBiome a_BiomeID); EMCSBiome GetBiome(int a_RelX, int a_RelZ) const; // These operate on the heightmap, so they could get out of sync with the data // Use UpdateHeightmap() to re-calculate heightmap from the block data void SetHeight(int a_RelX, int a_RelZ, HEIGHTTYPE a_Height); HEIGHTTYPE GetHeight(int a_RelX, int a_RelZ) const; // tolua_end /** Sets the heightmap to match the given shape data. Note that this ignores overhangs; the method is mostly used by old composition generators. */ void SetHeightFromShape(const Shape & a_Shape); /** Sets the shape in a_Shape to match the heightmap stored currently in m_HeightMap. */ void GetShapeFromHeight(Shape & a_Shape) const; /** Returns the index into the internal shape array for the specified coords */ inline static size_t MakeShapeIndex(int a_X, int a_Y, int a_Z) { return static_cast(a_Y + a_X * cChunkDef::Height + a_Z * cChunkDef::Height * cChunkDef::Width); } inline static void SetShapeIsSolidAt(Shape & a_Shape, int a_X, int a_Y, int a_Z, bool a_IsSolid) { auto index = MakeShapeIndex(a_X, a_Y, a_Z); a_Shape[index] = a_IsSolid ? 1 : 0; } inline static bool GetShapeIsSolidAt(const Shape & a_Shape, int a_X, int a_Y, int a_Z) { auto index = MakeShapeIndex(a_X, a_Y, a_Z); return a_Shape[index]; } // tolua_begin // Default generation: void SetUseDefaultBiomes(bool a_bUseDefaultBiomes); bool IsUsingDefaultBiomes(void) const; void SetUseDefaultHeight(bool a_bUseDefaultHeight); bool IsUsingDefaultHeight(void) const; void SetUseDefaultComposition(bool a_bUseDefaultComposition); bool IsUsingDefaultComposition(void) const; void SetUseDefaultFinish(bool a_bUseDefaultFinish); bool IsUsingDefaultFinish(void) const; /** Writes the block area into the chunk, with its origin set at the specified relative coords. Area's data overwrite everything in the chunk. */ void WriteBlockArea(const cBlockArea & a_BlockArea, int a_RelX, int a_RelY, int a_RelZ, cBlockArea::eMergeStrategy a_MergeStrategy = cBlockArea::msOverwrite); /** Reads an area from the chunk into a cBlockArea, blocktypes and blockmetas */ void ReadBlockArea(cBlockArea & a_Dest, int a_MinRelX, int a_MaxRelX, int a_MinRelY, int a_MaxRelY, int a_MinRelZ, int a_MaxRelZ); /** Returns the maximum height value in the heightmap. */ HEIGHTTYPE GetMaxHeight(void) const; /** Returns the minimum height value in the heightmap. */ HEIGHTTYPE GetMinHeight(void) const; /** Fills the relative cuboid with specified block; allows cuboid out of range of this chunk */ void FillRelCuboid( int a_MinX, int a_MaxX, int a_MinY, int a_MaxY, int a_MinZ, int a_MaxZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta ); /** Fills the relative cuboid with specified block; allows cuboid out of range of this chunk */ void FillRelCuboid(const cCuboid & a_RelCuboid, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) { FillRelCuboid( a_RelCuboid.p1.x, a_RelCuboid.p2.x, a_RelCuboid.p1.y, a_RelCuboid.p2.y, a_RelCuboid.p1.z, a_RelCuboid.p2.z, a_BlockType, a_BlockMeta ); } /** Replaces the specified src blocks in the cuboid by the dst blocks; allows cuboid out of range of this chunk */ void ReplaceRelCuboid( int a_MinX, int a_MaxX, int a_MinY, int a_MaxY, int a_MinZ, int a_MaxZ, BLOCKTYPE a_SrcType, NIBBLETYPE a_SrcMeta, BLOCKTYPE a_DstType, NIBBLETYPE a_DstMeta ); /** Replaces the specified src blocks in the cuboid by the dst blocks; allows cuboid out of range of this chunk */ void ReplaceRelCuboid( const cCuboid & a_RelCuboid, BLOCKTYPE a_SrcType, NIBBLETYPE a_SrcMeta, BLOCKTYPE a_DstType, NIBBLETYPE a_DstMeta ) { ReplaceRelCuboid( a_RelCuboid.p1.x, a_RelCuboid.p2.x, a_RelCuboid.p1.y, a_RelCuboid.p2.y, a_RelCuboid.p1.z, a_RelCuboid.p2.z, a_SrcType, a_SrcMeta, a_DstType, a_DstMeta ); } /** Replaces the blocks in the cuboid by the dst blocks if they are considered non-floor (air, water); allows cuboid out of range of this chunk */ void FloorRelCuboid( int a_MinX, int a_MaxX, int a_MinY, int a_MaxY, int a_MinZ, int a_MaxZ, BLOCKTYPE a_DstType, NIBBLETYPE a_DstMeta ); /** Replaces the blocks in the cuboid by the dst blocks if they are considered non-floor (air, water); allows cuboid out of range of this chunk */ void FloorRelCuboid( const cCuboid & a_RelCuboid, BLOCKTYPE a_DstType, NIBBLETYPE a_DstMeta ) { FloorRelCuboid( a_RelCuboid.p1.x, a_RelCuboid.p2.x, a_RelCuboid.p1.y, a_RelCuboid.p2.y, a_RelCuboid.p1.z, a_RelCuboid.p2.z, a_DstType, a_DstMeta ); } /** Fills the relative cuboid with specified block with a random chance; allows cuboid out of range of this chunk */ void RandomFillRelCuboid( int a_MinX, int a_MaxX, int a_MinY, int a_MaxY, int a_MinZ, int a_MaxZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_RandomSeed, int a_ChanceOutOf10k ); /** Fills the relative cuboid with specified block with a random chance; allows cuboid out of range of this chunk */ void RandomFillRelCuboid( const cCuboid & a_RelCuboid, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_RandomSeed, int a_ChanceOutOf10k ) { RandomFillRelCuboid( a_RelCuboid.p1.x, a_RelCuboid.p2.x, a_RelCuboid.p1.y, a_RelCuboid.p2.y, a_RelCuboid.p1.z, a_RelCuboid.p2.z, a_BlockType, a_BlockMeta, a_RandomSeed, a_ChanceOutOf10k ); } /** Returns the block entity at the specified coords. If there is no block entity at those coords, tries to create one, based on the block type If the blocktype doesn't support a block entity, returns nullptr. */ cBlockEntity * GetBlockEntity(int a_RelX, int a_RelY, int a_RelZ); /** Updates the heightmap to match the current contents. Useful for plugins when writing custom block areas into the chunk */ void UpdateHeightmap(void); // tolua_end // Accessors used by cChunkGenerator::Generator descendants: inline cChunkDef::BiomeMap & GetBiomeMap (void) { return m_BiomeMap; } inline cChunkDef::BlockTypes & GetBlockTypes (void) { return *(reinterpret_cast(m_BlockArea.GetBlockTypes())); } // CANNOT, different compression! // inline cChunkDef::BlockNibbles & GetBlockMetas (void) { return *((cChunkDef::BlockNibbles *)m_BlockArea.GetBlockMetas()); } inline BlockNibbleBytes & GetBlockMetasUncompressed(void) { return *(reinterpret_cast(m_BlockArea.GetBlockMetas())); } inline cChunkDef::HeightMap & GetHeightMap (void) { return m_HeightMap; } inline cEntityList & GetEntities (void) { return m_Entities; } inline const cBlockEntities & GetBlockEntities (void) const { return m_BlockArea.GetBlockEntities(); } inline cBlockEntities & GetBlockEntities (void) { return m_BlockArea.GetBlockEntities(); } inline const cChunkDef::BiomeMap & GetBiomeMap() const { return m_BiomeMap; } inline const cChunkDef::BlockTypes & GetBlockTypes() const { return *(reinterpret_cast(m_BlockArea.GetBlockTypes())); } inline const cChunkDef::HeightMap & GetHeightMap() const { return m_HeightMap; } /** Compresses the metas from the BlockArea format (1 meta per byte) into regular format (2 metas per byte) */ void CompressBlockMetas(cChunkDef::BlockNibbles & a_DestMetas); #ifndef NDEBUG /** Verifies that the heightmap corresponds to blocktype contents; if not, asserts on that column */ void VerifyHeightmap(void); #endif // !NDEBUG private: cChunkCoords m_Coords; cChunkDef::BiomeMap m_BiomeMap; cBlockArea m_BlockArea; cChunkDef::HeightMap m_HeightMap; cEntityList m_Entities; bool m_bUseDefaultBiomes; bool m_bUseDefaultHeight; bool m_bUseDefaultComposition; bool m_bUseDefaultFinish; } ; // tolua_export ================================================ FILE: src/Generating/ChunkGenerator.cpp ================================================ #include "Globals.h" #include "ChunkGenerator.h" #include "ChunkDesc.h" #include "ComposableGenerator.h" #include "Noise3DGenerator.h" #include "../IniFile.h" #include "../FastRandom.h" void cChunkGenerator::Initialize(cIniFile & a_IniFile) { // Get the seed; create a new one and log it if not found in the INI file: if (a_IniFile.HasValue("Seed", "Seed")) { m_Seed = a_IniFile.GetValueI("Seed", "Seed"); } else { m_Seed = GetRandomProvider().RandInt(); LOGINFO("Chosen a new random seed for world: %d", m_Seed); a_IniFile.SetValueI("Seed", "Seed", m_Seed); } m_Dimension = StringToDimension(a_IniFile.GetValue("General", "Dimension", "Overworld")); } std::unique_ptr cChunkGenerator::CreateFromIniFile(cIniFile & a_IniFile) { // Get the generator engine based on the INI file settings: std::unique_ptr res; AString GeneratorName = a_IniFile.GetValueSet("Generator", "Generator", "Composable"); if (NoCaseCompare(GeneratorName, "Noise3D") == 0) { res.reset(new cNoise3DGenerator()); } else { if (NoCaseCompare(GeneratorName, "composable") != 0) { LOGWARN("[Generator]::Generator value \"%s\" not recognized, using \"Composable\".", GeneratorName.c_str()); } res.reset(new cComposableGenerator()); } if (res == nullptr) { LOGERROR("Generator could not start, aborting the server"); return nullptr; } res->Initialize(a_IniFile); return res; } EMCSBiome cChunkGenerator::GetBiomeAt(int a_BlockX, int a_BlockZ) { cChunkDef::BiomeMap Biomes; int Y = 0; int ChunkX, ChunkZ; cChunkDef::AbsoluteToRelative(a_BlockX, Y, a_BlockZ, ChunkX, ChunkZ); GenerateBiomes({ChunkX, ChunkZ}, Biomes); return cChunkDef::GetBiome(Biomes, a_BlockX, a_BlockZ); } ================================================ FILE: src/Generating/ChunkGenerator.h ================================================ #pragma once #include "../Defines.h" #include "ChunkDef.h" // fwd: class cIniFile; class cChunkDesc; /** The interface that all chunk generators must implement to provide the generated chunks. Also a static factory that creates the descendants based on INI file settings. The cChunkGeneratorThread uses this interface to generate chunks for a single world. Ths calls to generate chunks are synchronous - they don't return until the chunk is fully generated. */ class cChunkGenerator { public: virtual ~cChunkGenerator() {} // Force a virtual destructor /** Called to initialize the generator on server startup. Descendants should call Super::Initialize() before initializing themselves. */ virtual void Initialize(cIniFile & a_IniFile); /** Generates the biomes for the specified chunk. Used by the world loader if biomes failed loading. */ virtual void GenerateBiomes(cChunkCoords a_ChunkCoords, cChunkDef::BiomeMap & a_BiomeMap) = 0; /** Returns the biome at the specified coords. Used by ChunkMap if an invalid chunk is queried for biome. The default implementation uses GenerateBiomes(). */ virtual EMCSBiome GetBiomeAt(int a_BlockX, int a_BlockZ); /** Does the actual chunk generation. Descendants need to override this and generate into a_ChunkDesc. */ virtual void Generate(cChunkDesc & a_ChunkDesc) = 0; /** Returns the seed that was read from the INI file. */ int GetSeed(void) const { return m_Seed; } /** Creates and initializes the entire generator based on the settings in the INI file. Initializes the generator, so that it can be used immediately after this call returns. */ static std::unique_ptr CreateFromIniFile(cIniFile & a_IniFile); protected: /** The main seed, read from the INI file, used for the entire generator. */ int m_Seed; /** The dimension, read from the INI file. */ eDimension m_Dimension; }; ================================================ FILE: src/Generating/CompoGen.cpp ================================================ // CompoGen.cpp /* Implements the various terrain composition generators: - cCompoGenSameBlock - cCompoGenDebugBiomes - cCompoGenClassic */ #include "Globals.h" #include "CompoGen.h" #include "../Item.h" #include "../LinearUpscale.h" #include "../IniFile.h" //////////////////////////////////////////////////////////////////////////////// // cCompoGenSameBlock: void cCompoGenSameBlock::ComposeTerrain(cChunkDesc & a_ChunkDesc, const cChunkDesc::Shape & a_Shape) { a_ChunkDesc.SetHeightFromShape(a_Shape); a_ChunkDesc.FillBlocks(E_BLOCK_AIR, 0); for (int z = 0; z < cChunkDef::Width; z++) { for (int x = 0; x < cChunkDef::Width; x++) { int Start; if (m_IsBedrocked) { a_ChunkDesc.SetBlockType(x, 0, z, E_BLOCK_BEDROCK); Start = 1; } else { Start = 0; } for (int y = a_ChunkDesc.GetHeight(x, z); y >= Start; y--) { a_ChunkDesc.SetBlockType(x, y, z, m_BlockType); } // for y } // for z } // for x } void cCompoGenSameBlock::InitializeCompoGen(cIniFile & a_IniFile) { m_BlockType = static_cast(GetIniItemSet(a_IniFile, "Generator", "SameBlockType", "stone").m_ItemType); m_IsBedrocked = (a_IniFile.GetValueSetI("Generator", "SameBlockBedrocked", 1) != 0); } //////////////////////////////////////////////////////////////////////////////// // cCompoGenDebugBiomes: void cCompoGenDebugBiomes::ComposeTerrain(cChunkDesc & a_ChunkDesc, const cChunkDesc::Shape & a_Shape) { static BLOCKTYPE Blocks[] = { E_BLOCK_STONE, E_BLOCK_COBBLESTONE, E_BLOCK_LOG, E_BLOCK_PLANKS, E_BLOCK_SANDSTONE, E_BLOCK_WOOL, E_BLOCK_COAL_ORE, E_BLOCK_IRON_ORE, E_BLOCK_GOLD_ORE, E_BLOCK_DIAMOND_ORE, E_BLOCK_LAPIS_ORE, E_BLOCK_REDSTONE_ORE, E_BLOCK_IRON_BLOCK, E_BLOCK_GOLD_BLOCK, E_BLOCK_DIAMOND_BLOCK, E_BLOCK_LAPIS_BLOCK, E_BLOCK_BRICK, E_BLOCK_MOSSY_COBBLESTONE, E_BLOCK_OBSIDIAN, E_BLOCK_NETHERRACK, E_BLOCK_SOULSAND, E_BLOCK_NETHER_BRICK, E_BLOCK_BEDROCK, } ; a_ChunkDesc.SetHeightFromShape(a_Shape); a_ChunkDesc.FillBlocks(E_BLOCK_AIR, 0); for (int z = 0; z < cChunkDef::Width; z++) { for (int x = 0; x < cChunkDef::Width; x++) { BLOCKTYPE BlockType = Blocks[a_ChunkDesc.GetBiome(x, z)]; for (int y = a_ChunkDesc.GetHeight(x, z); y >= 0; y--) { a_ChunkDesc.SetBlockType(x, y, z, BlockType); } // for y } // for z } // for x } //////////////////////////////////////////////////////////////////////////////// // cCompoGenClassic: cCompoGenClassic::cCompoGenClassic(void) : m_SeaLevel(60), m_BeachHeight(2), m_BeachDepth(4), m_BlockTop(E_BLOCK_GRASS), m_BlockMiddle(E_BLOCK_DIRT), m_BlockBottom(E_BLOCK_STONE), m_BlockBeach(E_BLOCK_SAND), m_BlockBeachBottom(E_BLOCK_SANDSTONE), m_BlockSea(E_BLOCK_STATIONARY_WATER) { } void cCompoGenClassic::ComposeTerrain(cChunkDesc & a_ChunkDesc, const cChunkDesc::Shape & a_Shape) { /* The classic composition means: - 1 layer of grass, 3 of dirt and the rest stone, if the height > sealevel + beachheight - 3 sand and a 1 sandstone, rest stone if between sealevel and sealevel + beachheight - water from waterlevel to height, then 3 sand, 1 sandstone, the rest stone, if water depth < beachdepth - water from waterlevel, then 3 dirt, the rest stone otherwise - bedrock at the bottom */ a_ChunkDesc.FillBlocks(E_BLOCK_AIR, 0); a_ChunkDesc.SetHeightFromShape(a_Shape); // The patterns to use for different situations, must be same length! const BLOCKTYPE PatternGround[] = {m_BlockTop, m_BlockMiddle, m_BlockMiddle, m_BlockMiddle} ; const BLOCKTYPE PatternBeach[] = {m_BlockBeach, m_BlockBeach, m_BlockBeach, m_BlockBeachBottom} ; const BLOCKTYPE PatternOcean[] = {m_BlockMiddle, m_BlockMiddle, m_BlockMiddle, m_BlockBottom} ; static int PatternLength = ARRAYCOUNT(PatternGround); ASSERT(ARRAYCOUNT(PatternGround) == ARRAYCOUNT(PatternBeach)); ASSERT(ARRAYCOUNT(PatternGround) == ARRAYCOUNT(PatternOcean)); for (int z = 0; z < cChunkDef::Width; z++) { for (int x = 0; x < cChunkDef::Width; x++) { int Height = a_ChunkDesc.GetHeight(x, z); const BLOCKTYPE * Pattern; if (Height > m_SeaLevel + m_BeachHeight) { Pattern = PatternGround; } else if (Height > m_SeaLevel - m_BeachDepth) { Pattern = PatternBeach; } else { Pattern = PatternOcean; } // Fill water from sealevel down to height (if any): for (int y = m_SeaLevel; y >= Height; --y) { a_ChunkDesc.SetBlockType(x, y, z, m_BlockSea); } // Fill from height till the bottom: for (int y = Height; y >= 1; y--) { a_ChunkDesc.SetBlockType(x, y, z, (Height - y < PatternLength) ? Pattern[Height - y] : m_BlockBottom); } // The last layer is always bedrock: a_ChunkDesc.SetBlockType(x, 0, z, E_BLOCK_BEDROCK); } // for x } // for z } void cCompoGenClassic::InitializeCompoGen(cIniFile & a_IniFile) { m_SeaLevel = a_IniFile.GetValueSetI("Generator", "SeaLevel", m_SeaLevel); m_BeachHeight = a_IniFile.GetValueSetI("Generator", "ClassicBeachHeight", m_BeachHeight); m_BeachDepth = a_IniFile.GetValueSetI("Generator", "ClassicBeachDepth", m_BeachDepth); m_BlockTop = static_cast(GetIniItemSet(a_IniFile, "Generator", "ClassicBlockTop", "grass").m_ItemType); m_BlockMiddle = static_cast(GetIniItemSet(a_IniFile, "Generator", "ClassicBlockMiddle", "dirt").m_ItemType); m_BlockBottom = static_cast(GetIniItemSet(a_IniFile, "Generator", "ClassicBlockBottom", "stone").m_ItemType); m_BlockBeach = static_cast(GetIniItemSet(a_IniFile, "Generator", "ClassicBlockBeach", "sand").m_ItemType); m_BlockBeachBottom = static_cast(GetIniItemSet(a_IniFile, "Generator", "ClassicBlockBeachBottom", "sandstone").m_ItemType); m_BlockSea = static_cast(GetIniItemSet(a_IniFile, "Generator", "ClassicBlockSea", "stationarywater").m_ItemType); } //////////////////////////////////////////////////////////////////////////////// // cCompoGenNether: cCompoGenNether::cCompoGenNether(int a_Seed) : m_Noise1(a_Seed + 10), m_Noise2(a_Seed * a_Seed * 10 + a_Seed * 1000 + 6000), m_MaxThreshold(25000) { } void cCompoGenNether::ComposeTerrain(cChunkDesc & a_ChunkDesc, const cChunkDesc::Shape & a_Shape) { HEIGHTTYPE MaxHeight = a_ChunkDesc.GetMaxHeight(); const int SEGMENT_HEIGHT = 8; const int INTERPOL_X = 16; // Must be a divisor of 16 const int INTERPOL_Z = 16; // Must be a divisor of 16 // Interpolate the chunk in 16 * SEGMENT_HEIGHT * 16 "segments", each SEGMENT_HEIGHT blocks high and each linearly interpolated separately. // Have two buffers, one for the lowest floor and one for the highest floor, so that Y-interpolation can be done between them // Then swap the buffers and use the previously-top one as the current-bottom, without recalculating it. int FloorBuf1[17 * 17]; int FloorBuf2[17 * 17]; int * FloorHi = FloorBuf1; int * FloorLo = FloorBuf2; int BaseX = a_ChunkDesc.GetChunkX() * cChunkDef::Width; int BaseZ = a_ChunkDesc.GetChunkZ() * cChunkDef::Width; // Interpolate the lowest floor: for (int z = 0; z <= 16 / INTERPOL_Z; z++) for (int x = 0; x <= 16 / INTERPOL_X; x++) { // We need to store the intermediate result in a volatile variable, otherwise gcc -O2 optimizes // through the undefined behavior in cNoise and produces different data than the other platforms / build types (#4384) volatile int intermediate = m_Noise1.IntNoise3DInt(BaseX + INTERPOL_X * x, 0, BaseZ + INTERPOL_Z * z) * m_Noise2.IntNoise3DInt(BaseX + INTERPOL_X * x, 0, BaseZ + INTERPOL_Z * z); FloorLo[INTERPOL_X * x + 17 * INTERPOL_Z * z] = intermediate / 256; } // for x, z - FloorLo[] LinearUpscale2DArrayInPlace<17, 17, INTERPOL_X, INTERPOL_Z>(FloorLo); // Interpolate segments: for (int Segment = 0; Segment < MaxHeight; Segment += SEGMENT_HEIGHT) { // First update the high floor: for (int z = 0; z <= 16 / INTERPOL_Z; z++) for (int x = 0; x <= 16 / INTERPOL_X; x++) { // We need to store the intermediate result in a volatile variable, otherwise gcc -O2 optimizes // through the undefined behavior in cNoise and produces different data than the other platforms / build types (#4384) volatile int intermediate = m_Noise1.IntNoise3DInt(BaseX + INTERPOL_X * x, Segment + SEGMENT_HEIGHT, BaseZ + INTERPOL_Z * z) * m_Noise2.IntNoise3DInt(BaseX + INTERPOL_Z * x, Segment + SEGMENT_HEIGHT, BaseZ + INTERPOL_Z * z); FloorHi[INTERPOL_X * x + 17 * INTERPOL_Z * z] = intermediate / 256; } // for x, z - FloorLo[] LinearUpscale2DArrayInPlace<17, 17, INTERPOL_X, INTERPOL_Z>(FloorHi); // Interpolate between FloorLo and FloorHi: for (int z = 0; z < 16; z++) for (int x = 0; x < 16; x++) { int Threshold = static_cast(m_Noise1.CubicNoise2D(static_cast(BaseX + x) / 75, static_cast(BaseZ + z) / 75) * m_MaxThreshold); int Lo = FloorLo[x + 17 * z] / 256; int Hi = FloorHi[x + 17 * z] / 256; for (int y = 0; y < SEGMENT_HEIGHT; y++) { int Val = Lo + (Hi - Lo) * y / SEGMENT_HEIGHT; if (Val < Threshold) { a_ChunkDesc.SetBlockType(x, y + Segment, z, E_BLOCK_NETHERRACK); } } } // Swap the floors: std::swap(FloorLo, FloorHi); } // Bedrock at the bottom and at the top, cover ceiling with netherrack: for (int z = 0; z < 16; z++) for (int x = 0; x < 16; x++) { a_ChunkDesc.SetBlockType(x, 0, z, E_BLOCK_BEDROCK); int Height = a_ChunkDesc.GetHeight(x, z); a_ChunkDesc.SetBlockType(x, Height, z, E_BLOCK_BEDROCK); NOISE_DATATYPE CeilingDisguise = (m_Noise1.CubicNoise2D(static_cast(a_ChunkDesc.GetChunkX() * cChunkDef::Width + x) / 10, static_cast(a_ChunkDesc.GetChunkZ() * cChunkDef::Width + z) / 10)); if (CeilingDisguise < 0) { CeilingDisguise = -CeilingDisguise; } int CeilingDisguiseHeight = Height - 2 - FloorC(CeilingDisguise * 3); for (int y = Height - 1; y > CeilingDisguiseHeight; y--) { a_ChunkDesc.SetBlockType(x, y, z, E_BLOCK_NETHERRACK); } } } void cCompoGenNether::InitializeCompoGen(cIniFile & a_IniFile) { m_MaxThreshold = a_IniFile.GetValueSetF("Generator", "NetherMaxThreshold", m_MaxThreshold); } //////////////////////////////////////////////////////////////////////////////// // cCompoGenCache: cCompoGenCache::cCompoGenCache(std::unique_ptr a_Underlying, int a_CacheSize) : m_Underlying(std::move(a_Underlying)), m_CacheSize(a_CacheSize), m_CacheOrder(new int[ToUnsigned(a_CacheSize)]), m_CacheData(new sCacheData[ToUnsigned(a_CacheSize)]), m_NumHits(0), m_NumMisses(0), m_TotalChain(0) { for (int i = 0; i < m_CacheSize; i++) { m_CacheOrder[i] = i; m_CacheData[i].m_ChunkX = 0x7fffffff; m_CacheData[i].m_ChunkZ = 0x7fffffff; } } cCompoGenCache::~cCompoGenCache() { delete[] m_CacheData; m_CacheData = nullptr; delete[] m_CacheOrder; m_CacheOrder = nullptr; } void cCompoGenCache::ComposeTerrain(cChunkDesc & a_ChunkDesc, const cChunkDesc::Shape & a_Shape) { #ifndef NDEBUG if (((m_NumHits + m_NumMisses) % 1024) == 10) { // LOGD("CompoGenCache: %d hits, %d misses, saved %.2f %%", m_NumHits, m_NumMisses, 100.0 * m_NumHits / (m_NumHits + m_NumMisses)); // LOGD("CompoGenCache: Avg cache chain length: %.2f", static_cast(m_TotalChain) / m_NumHits); } #endif // !NDEBUG int ChunkX = a_ChunkDesc.GetChunkX(); int ChunkZ = a_ChunkDesc.GetChunkZ(); for (int i = 0; i < m_CacheSize; i++) { if ( (m_CacheData[m_CacheOrder[i]].m_ChunkX != ChunkX) || (m_CacheData[m_CacheOrder[i]].m_ChunkZ != ChunkZ) ) { continue; } // Found it in the cache int Idx = m_CacheOrder[i]; // Move to front: for (int j = i; j > 0; j--) { m_CacheOrder[j] = m_CacheOrder[j - 1]; } m_CacheOrder[0] = Idx; // Use the cached data: memcpy(a_ChunkDesc.GetBlockTypes(), m_CacheData[Idx].m_BlockTypes, sizeof(a_ChunkDesc.GetBlockTypes())); memcpy(a_ChunkDesc.GetBlockMetasUncompressed(), m_CacheData[Idx].m_BlockMetas, sizeof(a_ChunkDesc.GetBlockMetasUncompressed())); memcpy(a_ChunkDesc.GetHeightMap(), m_CacheData[Idx].m_HeightMap, sizeof(a_ChunkDesc.GetHeightMap())); m_NumHits++; m_TotalChain += i; return; } // for i - cache // Not in the cache: m_NumMisses++; m_Underlying->ComposeTerrain(a_ChunkDesc, a_Shape); // Insert it as the first item in the MRU order: int Idx = m_CacheOrder[m_CacheSize - 1]; for (int i = m_CacheSize - 1; i > 0; i--) { m_CacheOrder[i] = m_CacheOrder[i - 1]; } // for i - m_CacheOrder[] m_CacheOrder[0] = Idx; memcpy(m_CacheData[Idx].m_BlockTypes, a_ChunkDesc.GetBlockTypes(), sizeof(a_ChunkDesc.GetBlockTypes())); memcpy(m_CacheData[Idx].m_BlockMetas, a_ChunkDesc.GetBlockMetasUncompressed(), sizeof(a_ChunkDesc.GetBlockMetasUncompressed())); memcpy(m_CacheData[Idx].m_HeightMap, a_ChunkDesc.GetHeightMap(), sizeof(a_ChunkDesc.GetHeightMap())); m_CacheData[Idx].m_ChunkX = ChunkX; m_CacheData[Idx].m_ChunkZ = ChunkZ; } void cCompoGenCache::InitializeCompoGen(cIniFile & a_IniFile) { m_Underlying->InitializeCompoGen(a_IniFile); } ================================================ FILE: src/Generating/CompoGen.h ================================================ // CompoGen.h /* Interfaces to the various terrain composition generators: - cCompoGenSameBlock - cCompoGenDebugBiomes - cCompoGenClassic - cCompoGenBiomal - cCompoGenNether - cCompoGenCache */ #pragma once #include "ComposableGenerator.h" #include "../Noise/Noise.h" class cCompoGenSameBlock : public cTerrainCompositionGen { public: cCompoGenSameBlock(void) : m_BlockType(E_BLOCK_STONE), m_IsBedrocked(true) {} protected: BLOCKTYPE m_BlockType; bool m_IsBedrocked; // cTerrainCompositionGen overrides: virtual void ComposeTerrain(cChunkDesc & a_ChunkDesc, const cChunkDesc::Shape & a_Shape) override; virtual void InitializeCompoGen(cIniFile & a_IniFile) override; } ; class cCompoGenDebugBiomes : public cTerrainCompositionGen { public: cCompoGenDebugBiomes(void) {} protected: // cTerrainCompositionGen overrides: virtual void ComposeTerrain(cChunkDesc & a_ChunkDesc, const cChunkDesc::Shape & a_Shape) override; } ; class cCompoGenClassic : public cTerrainCompositionGen { public: cCompoGenClassic(void); protected: int m_SeaLevel; int m_BeachHeight; int m_BeachDepth; BLOCKTYPE m_BlockTop; BLOCKTYPE m_BlockMiddle; BLOCKTYPE m_BlockBottom; BLOCKTYPE m_BlockBeach; BLOCKTYPE m_BlockBeachBottom; BLOCKTYPE m_BlockSea; // cTerrainCompositionGen overrides: virtual void ComposeTerrain(cChunkDesc & a_ChunkDesc, const cChunkDesc::Shape & a_Shape) override; virtual void InitializeCompoGen(cIniFile & a_IniFile) override; } ; class cCompoGenNether : public cTerrainCompositionGen { public: cCompoGenNether(int a_Seed); protected: cNoise m_Noise1; cNoise m_Noise2; double m_MaxThreshold; // cTerrainCompositionGen overrides: virtual void ComposeTerrain(cChunkDesc & a_ChunkDesc, const cChunkDesc::Shape & a_Shape) override; virtual void InitializeCompoGen(cIniFile & a_IniFile) override; } ; /** Caches most-recently-used chunk composition of another composition generator. Caches only the types and metas */ class cCompoGenCache : public cTerrainCompositionGen { public: cCompoGenCache(std::unique_ptr a_Underlying, int a_CacheSize); virtual ~cCompoGenCache() override; // cTerrainCompositionGen override: virtual void ComposeTerrain(cChunkDesc & a_ChunkDesc, const cChunkDesc::Shape & a_Shape) override; virtual void InitializeCompoGen(cIniFile & a_IniFile) override; protected: std::unique_ptr m_Underlying; struct sCacheData { int m_ChunkX; int m_ChunkZ; cChunkDef::BlockTypes m_BlockTypes; cChunkDesc::BlockNibbleBytes m_BlockMetas; // The metas are uncompressed, 1 meta per byte cChunkDef::HeightMap m_HeightMap; } ; // To avoid moving large amounts of data for the MRU behavior, we MRU-ize indices to an array of the actual data int m_CacheSize; int * m_CacheOrder; // MRU-ized order, indices into m_CacheData array sCacheData * m_CacheData; // m_CacheData[m_CacheOrder[0]] is the most recently used // Cache statistics int m_NumHits; int m_NumMisses; int m_TotalChain; // Number of cache items walked to get to a hit (only added for hits) } ; ================================================ FILE: src/Generating/CompoGenBiomal.cpp ================================================ // CompoGenBiomal.cpp // Implements the cCompoGenBiomal class representing the biome-aware composition generator #include "Globals.h" #include "CompoGenBiomal.h" #include "../IniFile.h" #include "../Noise/Noise.h" #include "../LinearUpscale.h" //////////////////////////////////////////////////////////////////////////////// // cPattern: /** This class is used to store a column pattern initialized at runtime, so that the program doesn't need to explicitly set 256 values for each pattern Each pattern has 256 blocks so that there's no need to check pattern bounds when assigning the pattern - there will always be enough pattern left, even for the whole-chunk-height columns. */ class cPattern { public: struct BlockInfo { BLOCKTYPE m_BlockType = E_BLOCK_STONE; NIBBLETYPE m_BlockMeta = 0; }; constexpr cPattern(std::initializer_list a_TopBlocks) { ASSERT(a_TopBlocks.size() <= cChunkDef::Height); // Copy the pattern into the top: size_t i = 0; for (const auto & Block : a_TopBlocks) { m_Pattern[i] = Block; ++i; } // The remaining blocks default to stone } const BlockInfo * Get(void) const { return m_Pattern; } protected: BlockInfo m_Pattern[cChunkDef::Height] = {}; } ; //////////////////////////////////////////////////////////////////////////////// // Land top block patterns: static constexpr cPattern patGrass = { {E_BLOCK_GRASS, 0}, {E_BLOCK_DIRT, E_META_DIRT_NORMAL}, {E_BLOCK_DIRT, E_META_DIRT_NORMAL}, {E_BLOCK_DIRT, E_META_DIRT_NORMAL}, } ; static constexpr cPattern patSand = { { E_BLOCK_SAND, 0}, { E_BLOCK_SAND, 0}, { E_BLOCK_SAND, 0}, { E_BLOCK_SANDSTONE, 0}, } ; static constexpr cPattern patDirt = { {E_BLOCK_DIRT, E_META_DIRT_NORMAL}, {E_BLOCK_DIRT, E_META_DIRT_NORMAL}, {E_BLOCK_DIRT, E_META_DIRT_NORMAL}, {E_BLOCK_DIRT, E_META_DIRT_NORMAL}, } ; static constexpr cPattern patPodzol = { {E_BLOCK_DIRT, E_META_DIRT_PODZOL}, {E_BLOCK_DIRT, E_META_DIRT_NORMAL}, {E_BLOCK_DIRT, E_META_DIRT_NORMAL}, {E_BLOCK_DIRT, E_META_DIRT_NORMAL}, } ; static constexpr cPattern patGrassLess = { {E_BLOCK_DIRT, E_META_DIRT_GRASSLESS}, {E_BLOCK_DIRT, E_META_DIRT_NORMAL}, {E_BLOCK_DIRT, E_META_DIRT_NORMAL}, {E_BLOCK_DIRT, E_META_DIRT_NORMAL}, } ; static constexpr cPattern patMycelium = { {E_BLOCK_MYCELIUM, 0}, {E_BLOCK_DIRT, 0}, {E_BLOCK_DIRT, 0}, {E_BLOCK_DIRT, 0}, } ; static constexpr cPattern patGravel = { {E_BLOCK_GRAVEL, 0}, {E_BLOCK_GRAVEL, 0}, {E_BLOCK_GRAVEL, 0}, {E_BLOCK_STONE, 0}, } ; static constexpr cPattern patStone = { {E_BLOCK_STONE, 0}, {E_BLOCK_STONE, 0}, {E_BLOCK_STONE, 0}, {E_BLOCK_STONE, 0}, } ; //////////////////////////////////////////////////////////////////////////////// // Ocean floor patterns: static constexpr cPattern patOFSand = { {E_BLOCK_SAND, 0}, {E_BLOCK_SAND, 0}, {E_BLOCK_SAND, 0}, {E_BLOCK_SANDSTONE, 0} } ; static constexpr cPattern patOFClay = { { E_BLOCK_CLAY, 0}, { E_BLOCK_CLAY, 0}, { E_BLOCK_SAND, 0}, { E_BLOCK_SAND, 0}, } ; static constexpr cPattern patOFOrangeClay = { { E_BLOCK_STAINED_CLAY, E_META_STAINED_GLASS_ORANGE}, { E_BLOCK_STAINED_CLAY, E_META_STAINED_GLASS_ORANGE}, { E_BLOCK_STAINED_CLAY, E_META_STAINED_GLASS_ORANGE}, } ; //////////////////////////////////////////////////////////////////////////////// // cCompoGenBiomal: class cCompoGenBiomal : public cTerrainCompositionGen { public: cCompoGenBiomal(int a_Seed) : m_SeaLevel(62), m_OceanFloorSelect(a_Seed + 1), m_MesaFloor(a_Seed + 2) { initMesaPattern(a_Seed); } protected: /** The block height at which water is generated instead of air. */ HEIGHTTYPE m_SeaLevel; /** The pattern used for mesa biomes. Initialized by seed on generator creation. */ cPattern::BlockInfo m_MesaPattern[2 * cChunkDef::Height]; /** Noise used for selecting between dirt and sand on the ocean floor. */ cNoise m_OceanFloorSelect; /** Noise used for the floor of the clay blocks in mesa biomes. */ cNoise m_MesaFloor; // cTerrainCompositionGen overrides: virtual void ComposeTerrain(cChunkDesc & a_ChunkDesc, const cChunkDesc::Shape & a_Shape) override { a_ChunkDesc.FillBlocks(E_BLOCK_AIR, 0); for (int z = 0; z < cChunkDef::Width; z++) { for (int x = 0; x < cChunkDef::Width; x++) { ComposeColumn(a_ChunkDesc, x, z, &(a_Shape[x * 256 + z * 16 * 256])); } // for x } // for z } virtual void InitializeCompoGen(cIniFile & a_IniFile) override { m_SeaLevel = static_cast(a_IniFile.GetValueSetI("Generator", "SeaLevel", m_SeaLevel)); } /** Initializes the m_MesaPattern with a pattern based on the generator's seed. */ void initMesaPattern(int a_Seed) { // In a loop, choose whether to use one, two or three layers of stained clay, then choose a color and width for each layer // Separate each group with another layer of hardened clay cNoise patternNoise(a_Seed); static NIBBLETYPE allowedColors[] = { E_META_STAINED_CLAY_YELLOW, E_META_STAINED_CLAY_YELLOW, E_META_STAINED_CLAY_RED, E_META_STAINED_CLAY_RED, E_META_STAINED_CLAY_WHITE, E_META_STAINED_CLAY_BROWN, E_META_STAINED_CLAY_BROWN, E_META_STAINED_CLAY_BROWN, E_META_STAINED_CLAY_ORANGE, E_META_STAINED_CLAY_ORANGE, E_META_STAINED_CLAY_ORANGE, E_META_STAINED_CLAY_ORANGE, E_META_STAINED_CLAY_ORANGE, E_META_STAINED_CLAY_ORANGE, E_META_STAINED_CLAY_LIGHTGRAY, } ; static int layerSizes[] = // Adjust the chance so that thinner layers occur more commonly { 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, } ; int idx = ARRAYCOUNT(m_MesaPattern) - 1; while (idx >= 0) { // A layer group of 1 - 2 color stained clay: int rnd = patternNoise.IntNoise1DInt(idx) / 7; int numLayers = (rnd % 2) + 1; rnd /= 2; for (int lay = 0; lay < numLayers; lay++) { int numBlocks = layerSizes[(static_cast(rnd) % ARRAYCOUNT(layerSizes))]; NIBBLETYPE Color = allowedColors[static_cast(rnd / 4) % ARRAYCOUNT(allowedColors)]; if ( ((numBlocks == 3) && (numLayers == 2)) || // In two-layer mode disallow the 3-high layers: (Color == E_META_STAINED_CLAY_WHITE)) // White stained clay can ever be only 1 block high { numBlocks = 1; } numBlocks = std::min(idx + 1, numBlocks); // Limit by idx so that we don't have to check inside the loop rnd /= 32; for (int block = 0; block < numBlocks; block++, idx--) { m_MesaPattern[idx].m_BlockMeta = Color; m_MesaPattern[idx].m_BlockType = E_BLOCK_STAINED_CLAY; } // for block } // for lay // A layer of hardened clay in between the layer group: int numBlocks = (rnd % 4) + 1; // All heights the same probability if ((numLayers == 2) && (numBlocks < 4)) { // For two layers of stained clay, add an extra block of hardened clay: numBlocks++; } numBlocks = std::min(idx + 1, numBlocks); // Limit by idx so that we don't have to check inside the loop for (int block = 0; block < numBlocks; block++, idx--) { m_MesaPattern[idx].m_BlockMeta = 0; m_MesaPattern[idx].m_BlockType = E_BLOCK_HARDENED_CLAY; } // for block } // while (idx >= 0) } /** Composes a single column in a_ChunkDesc. Chooses what to do based on the biome in that column. */ void ComposeColumn(cChunkDesc & a_ChunkDesc, int a_RelX, int a_RelZ, const Byte * a_ShapeColumn) { // Frequencies for the podzol floor selecting noise: const NOISE_DATATYPE FrequencyX = 8; const NOISE_DATATYPE FrequencyZ = 8; EMCSBiome Biome = a_ChunkDesc.GetBiome(a_RelX, a_RelZ); switch (Biome) { case biOcean: case biPlains: case biForest: case biTaiga: case biSwampland: case biRiver: case biFrozenOcean: case biFrozenRiver: case biIcePlains: case biIceMountains: case biForestHills: case biTaigaHills: case biExtremeHillsEdge: case biExtremeHillsPlus: case biExtremeHills: case biJungle: case biJungleHills: case biJungleEdge: case biDeepOcean: case biStoneBeach: case biColdBeach: case biBirchForest: case biBirchForestHills: case biRoofedForest: case biColdTaiga: case biColdTaigaHills: case biSavanna: case biSavannaPlateau: case biSunflowerPlains: case biFlowerForest: case biTaigaM: case biSwamplandM: case biIcePlainsSpikes: case biJungleM: case biJungleEdgeM: case biBirchForestM: case biBirchForestHillsM: case biRoofedForestM: case biColdTaigaM: case biSavannaM: case biSavannaPlateauM: { FillColumnPattern(a_ChunkDesc, a_RelX, a_RelZ, patGrass.Get(), a_ShapeColumn); return; } case biMegaTaiga: case biMegaTaigaHills: case biMegaSpruceTaiga: case biMegaSpruceTaigaHills: { // Select the pattern to use - podzol, grass or grassless dirt: NOISE_DATATYPE NoiseX = (static_cast(a_ChunkDesc.GetChunkX() * cChunkDef::Width + a_RelX)) / FrequencyX; NOISE_DATATYPE NoiseY = (static_cast(a_ChunkDesc.GetChunkZ() * cChunkDef::Width + a_RelZ)) / FrequencyZ; NOISE_DATATYPE Val = m_OceanFloorSelect.CubicNoise2D(NoiseX, NoiseY); const cPattern::BlockInfo * Pattern = (Val < -0.9) ? patGrassLess.Get() : ((Val > 0) ? patPodzol.Get() : patGrass.Get()); FillColumnPattern(a_ChunkDesc, a_RelX, a_RelZ, Pattern, a_ShapeColumn); return; } case biDesertHills: case biDesert: case biDesertM: case biBeach: { FillColumnPattern(a_ChunkDesc, a_RelX, a_RelZ, patSand.Get(), a_ShapeColumn); return; } case biMushroomIsland: case biMushroomShore: { FillColumnPattern(a_ChunkDesc, a_RelX, a_RelZ, patMycelium.Get(), a_ShapeColumn); return; } case biMesa: case biMesaPlateauF: case biMesaPlateau: case biMesaBryce: case biMesaPlateauFM: case biMesaPlateauM: { // Mesa biomes need special handling, because they don't follow the usual "4 blocks from top pattern", // instead, they provide a "from bottom" pattern with varying base height, // usually 4 blocks below the ocean level FillColumnMesa(a_ChunkDesc, a_RelX, a_RelZ, a_ShapeColumn); return; } case biExtremeHillsPlusM: case biExtremeHillsM: { // Select the pattern to use - gravel, stone or grass: NOISE_DATATYPE NoiseX = (static_cast(a_ChunkDesc.GetChunkX() * cChunkDef::Width + a_RelX)) / FrequencyX; NOISE_DATATYPE NoiseY = (static_cast(a_ChunkDesc.GetChunkZ() * cChunkDef::Width + a_RelZ)) / FrequencyZ; NOISE_DATATYPE Val = m_OceanFloorSelect.CubicNoise2D(NoiseX, NoiseY); const cPattern::BlockInfo * Pattern = (Val < 0.0) ? patStone.Get() : patGrass.Get(); FillColumnPattern(a_ChunkDesc, a_RelX, a_RelZ, Pattern, a_ShapeColumn); return; } case biInvalidBiome: case biNether: case biEnd: case biNumBiomes: case biVariant: case biNumVariantBiomes: { // This generator is not supposed to be used for these biomes, but it has to produce *something* // so let's produce stone: FillColumnPattern(a_ChunkDesc, a_RelX, a_RelZ, patStone.Get(), a_ShapeColumn); return; } } // switch (Biome) } /** Fills the specified column with the specified pattern; restarts the pattern when air is reached, switches to ocean floor pattern if ocean is reached. Always adds bedrock at the very bottom. */ void FillColumnPattern(cChunkDesc & a_ChunkDesc, int a_RelX, int a_RelZ, const cPattern::BlockInfo * a_Pattern, const Byte * a_ShapeColumn) { bool HasHadWater = false; int PatternIdx = 0; HEIGHTTYPE top = a_ChunkDesc.GetHeight(a_RelX, a_RelZ); if (top < m_SeaLevel) { top = m_SeaLevel; a_ChunkDesc.SetHeight(a_RelX, a_RelZ, top - 1); } for (int y = top; y > 0; y--) { if (a_ShapeColumn[y] > 0) { // "ground" part, use the pattern: a_ChunkDesc.SetBlockTypeMeta(a_RelX, y, a_RelZ, a_Pattern[PatternIdx].m_BlockType, a_Pattern[PatternIdx].m_BlockMeta); PatternIdx++; continue; } // "air" or "water" part: // Reset the pattern index to zero, so that the pattern is repeated from the top again: PatternIdx = 0; if (y >= m_SeaLevel) { // "air" part, do nothing continue; } a_ChunkDesc.SetBlockType(a_RelX, y, a_RelZ, E_BLOCK_STATIONARY_WATER); if (HasHadWater) { continue; } // Select the ocean-floor pattern to use: if (a_ChunkDesc.GetBiome(a_RelX, a_RelZ) == biDeepOcean) { a_Pattern = patGravel.Get(); } else { a_Pattern = ChooseOceanFloorPattern(a_ChunkDesc.GetChunkX(), a_ChunkDesc.GetChunkZ(), a_RelX, a_RelZ); } HasHadWater = true; } // for y if (a_ShapeColumn[0] > 0) { a_ChunkDesc.SetBlockType(a_RelX, 0, a_RelZ, E_BLOCK_BEDROCK); } } /** Fills the specified column with mesa pattern, based on the column height */ void FillColumnMesa(cChunkDesc & a_ChunkDesc, int a_RelX, int a_RelZ, const Byte * a_ShapeColumn) { // Frequencies for the clay floor noise: const NOISE_DATATYPE FrequencyX = 50; const NOISE_DATATYPE FrequencyZ = 50; int Top = a_ChunkDesc.GetHeight(a_RelX, a_RelZ); if (Top < m_SeaLevel) { // The terrain is below sealevel, handle as regular ocean with red sand floor: FillColumnPattern(a_ChunkDesc, a_RelX, a_RelZ, patOFOrangeClay.Get(), a_ShapeColumn); return; } NOISE_DATATYPE NoiseX = (static_cast(a_ChunkDesc.GetChunkX() * cChunkDef::Width + a_RelX)) / FrequencyX; NOISE_DATATYPE NoiseY = (static_cast(a_ChunkDesc.GetChunkZ() * cChunkDef::Width + a_RelZ)) / FrequencyZ; int ClayFloor = m_SeaLevel - 6 + static_cast(4.f * m_MesaFloor.CubicNoise2D(NoiseX, NoiseY)); if (ClayFloor >= Top) { ClayFloor = Top - 1; } if (Top - m_SeaLevel < 5) { // Simple case: top is red sand, then hardened clay down to ClayFloor, then stone: a_ChunkDesc.SetBlockTypeMeta(a_RelX, Top, a_RelZ, E_BLOCK_SAND, E_META_SAND_RED); for (int y = Top - 1; y >= ClayFloor; y--) { a_ChunkDesc.SetBlockType(a_RelX, y, a_RelZ, E_BLOCK_HARDENED_CLAY); } for (int y = ClayFloor - 1; y > 0; y--) { a_ChunkDesc.SetBlockType(a_RelX, y, a_RelZ, E_BLOCK_STONE); } a_ChunkDesc.SetBlockType(a_RelX, 0, a_RelZ, E_BLOCK_BEDROCK); return; } // Difficult case: use the mesa pattern and watch for overhangs: int PatternIdx = cChunkDef::Height - (Top - ClayFloor); // We want the block at index ClayFloor to be pattern's 256th block (first stone) const cPattern::BlockInfo * Pattern = m_MesaPattern; bool HasHadWater = false; for (int y = Top; y > 0; y--) { if (a_ShapeColumn[y] > 0) { // "ground" part, use the pattern: a_ChunkDesc.SetBlockTypeMeta(a_RelX, y, a_RelZ, Pattern[PatternIdx].m_BlockType, Pattern[PatternIdx].m_BlockMeta); PatternIdx++; continue; } if (y >= m_SeaLevel) { // "air" part, do nothing continue; } // "water" part, fill with water and choose new pattern for ocean floor, if not chosen already: PatternIdx = 0; a_ChunkDesc.SetBlockType(a_RelX, y, a_RelZ, E_BLOCK_STATIONARY_WATER); if (HasHadWater) { continue; } // Select the ocean-floor pattern to use: Pattern = ChooseOceanFloorPattern(a_ChunkDesc.GetChunkX(), a_ChunkDesc.GetChunkZ(), a_RelX, a_RelZ); HasHadWater = true; } // for y a_ChunkDesc.SetBlockType(a_RelX, 0, a_RelZ, E_BLOCK_BEDROCK); EMCSBiome MesaVersion = a_ChunkDesc.GetBiome(a_RelX, a_RelZ); if ((MesaVersion == biMesaPlateauF) || (MesaVersion == biMesaPlateauFM)) { if (Top < 95 + static_cast(m_MesaFloor.CubicNoise2D(NoiseY * 2, NoiseX * 2) * 6)) { return; } BLOCKTYPE Block = (m_MesaFloor.CubicNoise2D(NoiseX * 4, NoiseY * 4) < 0) ? E_BLOCK_DIRT : E_BLOCK_GRASS; NIBBLETYPE Meta = (Block == E_BLOCK_GRASS) ? 0 : 1; a_ChunkDesc.SetBlockTypeMeta(a_RelX, Top, a_RelZ, Block, Meta); } } /** Returns the pattern to use for an ocean floor in the specified column. The returned pattern is guaranteed to be 256 blocks long. */ const cPattern::BlockInfo * ChooseOceanFloorPattern(int a_ChunkX, int a_ChunkZ, int a_RelX, int a_RelZ) { // Frequencies for the ocean floor selecting noise: const NOISE_DATATYPE FrequencyX = 3; const NOISE_DATATYPE FrequencyZ = 3; // Select the ocean-floor pattern to use: NOISE_DATATYPE NoiseX = (static_cast(a_ChunkX * cChunkDef::Width + a_RelX)) / FrequencyX; NOISE_DATATYPE NoiseY = (static_cast(a_ChunkZ * cChunkDef::Width + a_RelZ)) / FrequencyZ; NOISE_DATATYPE Val = m_OceanFloorSelect.CubicNoise2D(NoiseX, NoiseY); if (Val < -0.95) { return patOFClay.Get(); } else if (Val < 0) { return patOFSand.Get(); } else { return patDirt.Get(); } } } ; std::unique_ptr CreateCompoGenBiomal(int a_Seed) { return std::make_unique(a_Seed); } ================================================ FILE: src/Generating/CompoGenBiomal.h ================================================ // CompoGenBiomal.h #pragma once #include "ComposableGenerator.h" /** Returns a new instance of the Biomal composition generator. */ std::unique_ptr CreateCompoGenBiomal(int a_Seed); ================================================ FILE: src/Generating/ComposableGenerator.cpp ================================================ // ComposableGenerator.cpp // Implements the cComposableGenerator class representing the chunk generator that takes the composition approach to generating chunks #include "Globals.h" #include "ComposableGenerator.h" #include "../IniFile.h" // Individual composed algorithms: #include "BioGen.h" #include "HeiGen.h" #include "CompoGen.h" #include "StructGen.h" #include "FinishGen.h" #include "CompoGenBiomal.h" #include "CompositedHeiGen.h" #include "Caves.h" #include "DistortedHeightmap.h" #include "DungeonRoomsFinisher.h" #include "EndGen.h" #include "EnderDragonFightStructuresGen.h" #include "MineShafts.h" #include "Noise3DGenerator.h" #include "Ravines.h" #include "RoughRavines.h" #include "SinglePieceStructuresGen.h" #include "VillageGen.h" #include "PieceStructuresGen.h" //////////////////////////////////////////////////////////////////////////////// // cTerrainCompositionGen: std::unique_ptr cTerrainCompositionGen::CreateCompositionGen( cIniFile & a_IniFile, cBiomeGen & a_BiomeGen, cTerrainShapeGen & a_ShapeGen, int a_Seed ) { AString CompoGenName = a_IniFile.GetValue("Generator", "CompositionGen"); if (CompoGenName.empty()) { LOGWARN("[Generator] CompositionGen value not set in world.ini, using \"Biomal\"."); CompoGenName = "Biomal"; } // Compositor list is alpha-sorted std::unique_ptr res; if (NoCaseCompare(CompoGenName, "Biomal") == 0) { res = CreateCompoGenBiomal(a_Seed); } else if (NoCaseCompare(CompoGenName, "BiomalNoise3D") == 0) { // The composition that used to be provided with BiomalNoise3D is now provided by the Biomal compositor: res = CreateCompoGenBiomal(a_Seed); } else if (NoCaseCompare(CompoGenName, "Classic") == 0) { res = std::make_unique(); } else if (NoCaseCompare(CompoGenName, "DebugBiomes") == 0) { res = std::make_unique(); } else if (NoCaseCompare(CompoGenName, "DistortedHeightmap") == 0) { // The composition that used to be provided with DistortedHeightmap is now provided by the Biomal compositor: res = CreateCompoGenBiomal(a_Seed); } else if (NoCaseCompare(CompoGenName, "End") == 0) { res = std::make_unique(a_Seed); } else if (NoCaseCompare(CompoGenName, "Nether") == 0) { res = std::make_unique(a_Seed); } else if (NoCaseCompare(CompoGenName, "Noise3D") == 0) { // The composition that used to be provided with Noise3D is now provided by the Biomal compositor: res = CreateCompoGenBiomal(a_Seed); } else if (NoCaseCompare(CompoGenName, "SameBlock") == 0) { res = std::make_unique(); } else { LOGWARN("Unknown CompositionGen \"%s\", using \"Biomal\" instead.", CompoGenName.c_str()); a_IniFile.SetValue("Generator", "CompositionGen", "Biomal"); return CreateCompositionGen(a_IniFile, a_BiomeGen, a_ShapeGen, a_Seed); } ASSERT(res != nullptr); // Read the settings from the ini file: res->InitializeCompoGen(a_IniFile); return res; } //////////////////////////////////////////////////////////////////////////////// // cComposableGenerator: cComposableGenerator::cComposableGenerator(): m_BiomeGen(), m_ShapeGen(), m_CompositionGen() { } void cComposableGenerator::Initialize(cIniFile & a_IniFile) { Super::Initialize(a_IniFile); // Add the defaults, if they're not overridden: InitializeGeneratorDefaults(a_IniFile, m_Dimension); InitBiomeGen(a_IniFile); InitShapeGen(a_IniFile); InitCompositionGen(a_IniFile); InitFinishGens(a_IniFile); } void cComposableGenerator::GenerateBiomes(cChunkCoords a_ChunkCoords, cChunkDef::BiomeMap & a_BiomeMap) { if (m_BiomeGen != nullptr) // Quick fix for generator deinitializing before the world storage finishes loading { m_BiomeGen->GenBiomes(a_ChunkCoords, a_BiomeMap); } } void cComposableGenerator::Generate(cChunkDesc & a_ChunkDesc) { if (a_ChunkDesc.IsUsingDefaultBiomes()) { m_BiomeGen->GenBiomes(a_ChunkDesc.GetChunkCoords(), a_ChunkDesc.GetBiomeMap()); } cChunkDesc::Shape shape; if (a_ChunkDesc.IsUsingDefaultHeight()) { m_ShapeGen->GenShape(a_ChunkDesc.GetChunkCoords(), shape); a_ChunkDesc.SetHeightFromShape(shape); } else { // Convert the heightmap in a_ChunkDesc into shape: a_ChunkDesc.GetShapeFromHeight(shape); } bool ShouldUpdateHeightmap = false; if (a_ChunkDesc.IsUsingDefaultComposition()) { m_CompositionGen->ComposeTerrain(a_ChunkDesc, shape); } if (a_ChunkDesc.IsUsingDefaultFinish()) { for (const auto & Finisher : m_FinishGens) { Finisher->GenFinish(a_ChunkDesc); } ShouldUpdateHeightmap = true; } if (ShouldUpdateHeightmap) { a_ChunkDesc.UpdateHeightmap(); } } void cComposableGenerator::InitializeGeneratorDefaults(cIniFile & a_IniFile, eDimension a_Dimension) { switch (a_Dimension) { case dimOverworld: { a_IniFile.GetValueSet("Generator", "BiomeGen", "Grown"); a_IniFile.GetValueSet("Generator", "ShapeGen", "BiomalNoise3D"); a_IniFile.GetValueSet("Generator", "CompositionGen", "Biomal"); a_IniFile.GetValueSet("Generator", "Finishers", "RoughRavines, " "WormNestCaves, " "WaterLakes, " "WaterSprings, " "LavaLakes, " "LavaSprings, " "OreNests, " "Mineshafts, " "Trees, " "Villages, " "SinglePieceStructures: JungleTemple|WitchHut|DesertPyramid|DesertWell, " "TallGrass, " "SprinkleFoliage, " "Ice, " "Snow, " "Lilypads, " "BottomLava, " "DeadBushes, " "NaturalPatches, " "PreSimulator, " "Animals, " "OverworldClumpFlowers, " "ForestRocks" ); break; } // dimOverworld case dimNether: { a_IniFile.GetValueSet("Generator", "Generator", "Composable"); a_IniFile.GetValueSet("Generator", "BiomeGen", "Constant"); a_IniFile.GetValueSet("Generator", "ConstantBiome", "Nether"); a_IniFile.GetValueSet("Generator", "ShapeGen", "HeightMap"); a_IniFile.GetValueSet("Generator", "HeightGen", "Flat"); a_IniFile.GetValueSet("Generator", "FlatHeight", "128"); a_IniFile.GetValueSet("Generator", "CompositionGen", "Nether"); a_IniFile.GetValueSet("Generator", "Finishers", "SoulsandRims, " "WormNestCaves, " "BottomLava, " "LavaSprings, " "NetherClumpFoliage, " "NetherOreNests, " "PieceStructures: NetherFort, " "GlowStone, " "PreSimulator"); break; } // dimNether case dimEnd: { a_IniFile.GetValueSet("Generator", "BiomeGen", "Constant"); a_IniFile.GetValueSet("Generator", "ConstantBiome", "End"); a_IniFile.GetValueSet("Generator", "ShapeGen", "End"); a_IniFile.GetValueSet("Generator", "CompositionGen", "End"); a_IniFile.GetValueSet("Generator", "Finishers", "EnderDragonFightStructures"); break; } // dimEnd default: { ASSERT(!"Unhandled dimension"); break; } } } void cComposableGenerator::InitBiomeGen(cIniFile & a_IniFile) { bool CacheOffByDefault = false; m_BiomeGen = cBiomeGen::CreateBiomeGen(a_IniFile, m_Seed, CacheOffByDefault); // Add a cache, if requested: // The default is 16 * 128 caches, which is 2 MiB of RAM. Reasonable, for the amount of work this is saving. int CacheSize = a_IniFile.GetValueSetI("Generator", "BiomeGenCacheSize", CacheOffByDefault ? 0 : 16); if (CacheSize <= 0) { return; } int MultiCacheLength = a_IniFile.GetValueSetI("Generator", "BiomeGenMultiCacheLength", 128); if (CacheSize < 4) { LOGWARNING("Biomegen cache size set too low, would hurt performance instead of helping. Increasing from %d to %d", CacheSize, 4 ); CacheSize = 4; } LOGD("Using a cache for biomegen of size %d.", CacheSize); if (MultiCacheLength > 0) { LOGD("Enabling multicache for biomegen of length %d.", MultiCacheLength); m_BiomeGen = std::make_unique(std::move(m_BiomeGen), static_cast(CacheSize), static_cast(MultiCacheLength)); } else { m_BiomeGen = std::make_unique(std::move(m_BiomeGen), static_cast(CacheSize), 1); } } void cComposableGenerator::InitShapeGen(cIniFile & a_IniFile) { bool CacheOffByDefault = false; m_ShapeGen = cTerrainShapeGen::CreateShapeGen( a_IniFile, *m_BiomeGen, m_Seed, CacheOffByDefault ); /* // TODO // Add a cache, if requested: int CacheSize = a_IniFile.GetValueSetI("Generator", "ShapeGenCacheSize", CacheOffByDefault ? 0 : 64); if (CacheSize > 0) { if (CacheSize < 4) { LOGWARNING("Heightgen cache size set too low, would hurt performance instead of helping. Increasing from %d to %d", CacheSize, 4 ); CacheSize = 4; } LOGD("Using a cache for Heightgen of size %d.", CacheSize); m_HeightGen = cTerrainHeightGenPtr(new cHeiGenCache(m_HeightGen, CacheSize)); } */ } void cComposableGenerator::InitCompositionGen(cIniFile & a_IniFile) { m_CompositionGen = cTerrainCompositionGen::CreateCompositionGen( a_IniFile, *m_BiomeGen, *m_ShapeGen, m_Seed ); // Add a cache over the composition generator: // Even a cache of size 1 is useful due to the CompositedHeiGen cache after us doing re-composition on its misses int CompoGenCacheSize = a_IniFile.GetValueSetI("Generator", "CompositionGenCacheSize", 64); if (CompoGenCacheSize > 0) { m_CompositionGen = std::make_unique(std::move(m_CompositionGen), CompoGenCacheSize); } // Create a cache of the composited heightmaps, so that finishers may use it: m_CompositedHeightCache = std::make_unique(std::make_unique(*m_BiomeGen, *m_ShapeGen, *m_CompositionGen), 16, 128); // 128 subcaches of depth 16 each = 0.5 MiB of RAM. Acceptable, for the amount of work this saves. } void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile) { auto seaLevel = a_IniFile.GetValueI("Generator", "SeaLevel"); AString Finishers = a_IniFile.GetValue("Generator", "Finishers"); // Create all requested finishers: AStringVector Str = StringSplitAndTrim(Finishers, ","); for (AStringVector::const_iterator itr = Str.begin(); itr != Str.end(); ++itr) { auto split = StringSplitAndTrim(*itr, ":"); if (split.empty()) { continue; } const auto & finisher = split[0]; // Finishers, alpha-sorted: if (NoCaseCompare(finisher, "Animals") == 0) { m_FinishGens.push_back(std::make_unique(m_Seed, a_IniFile, m_Dimension)); } else if (NoCaseCompare(finisher, "BottomLava") == 0) { int DefaultBottomLavaLevel = (m_Dimension == dimNether) ? 30 : 10; int BottomLavaLevel = a_IniFile.GetValueSetI("Generator", "BottomLavaLevel", DefaultBottomLavaLevel); m_FinishGens.push_back(std::make_unique(BottomLavaLevel)); } else if (NoCaseCompare(finisher, "DeadBushes") == 0) { // A list with all the allowed biomes. cFinishGenSingleTopBlock::BiomeList AllowedBiomes; AllowedBiomes.push_back(biDesert); AllowedBiomes.push_back(biDesertHills); AllowedBiomes.push_back(biDesertM); AllowedBiomes.push_back(biMesa); AllowedBiomes.push_back(biMesaBryce); AllowedBiomes.push_back(biMesaPlateau); AllowedBiomes.push_back(biMesaPlateauF); AllowedBiomes.push_back(biMesaPlateauFM); AllowedBiomes.push_back(biMesaPlateauM); AllowedBiomes.push_back(biMegaTaiga); // A list with all the allowed blocks that can be below the dead bush. cFinishGenSingleTopBlock::BlockList AllowedBlocks; AllowedBlocks.push_back(E_BLOCK_SAND); AllowedBlocks.push_back(E_BLOCK_HARDENED_CLAY); AllowedBlocks.push_back(E_BLOCK_STAINED_CLAY); m_FinishGens.push_back(std::make_unique(m_Seed, E_BLOCK_DEAD_BUSH, AllowedBiomes, 2, AllowedBlocks)); } else if (NoCaseCompare(finisher, "DirectOverhangs") == 0) { m_FinishGens.push_back(std::make_unique(m_Seed)); } else if (NoCaseCompare(finisher, "DirtPockets") == 0) { auto Gen = std::make_unique(m_Seed + 1, cFinishGenOrePockets::DefaultNaturalPatches()); Gen->Initialize(a_IniFile, "DirtPockets"); m_FinishGens.push_back(std::move(Gen)); } else if (NoCaseCompare(finisher, "DistortedMembraneOverhangs") == 0) { m_FinishGens.push_back(std::make_unique(m_Seed)); } else if (NoCaseCompare(finisher, "DualRidgeCaves") == 0) { float Threshold = static_cast(a_IniFile.GetValueSetF("Generator", "DualRidgeCavesThreshold", 0.3)); m_FinishGens.push_back(std::make_unique(m_Seed, Threshold)); } else if (NoCaseCompare(finisher, "DungeonRooms") == 0) { int GridSize = a_IniFile.GetValueSetI("Generator", "DungeonRoomsGridSize", 48); int MaxSize = a_IniFile.GetValueSetI("Generator", "DungeonRoomsMaxSize", 7); int MinSize = a_IniFile.GetValueSetI("Generator", "DungeonRoomsMinSize", 5); AString HeightDistrib = a_IniFile.GetValueSet ("Generator", "DungeonRoomsHeightDistrib", "0, 0; 10, 10; 11, 500; 40, 500; 60, 40; 90, 1"); m_FinishGens.push_back(std::make_unique(*m_ShapeGen, m_Seed, GridSize, MaxSize, MinSize, HeightDistrib)); } else if (NoCaseCompare(finisher, "EnderDragonFightStructures") == 0) { AString Pillars = a_IniFile.GetValueSet("Generator", "ObsidianPillars", "76|3|false; 79|3|true; 82|3|true; " "85|4|false; 88|4|false; 91|4|false; " "94|5|false; 97|5|false; 100|5|false; " "103|6|false"); int Radius = a_IniFile.GetValueSetI("Generator", "ObsidianPillarsRadius", 43); auto Gen = std::make_unique(m_Seed); Gen->Init(Pillars, Radius); m_FinishGens.push_back(std::move(Gen)); } else if (NoCaseCompare(finisher, "ForestRocks") == 0) { m_FinishGens.push_back(std::make_unique(m_Seed, a_IniFile)); } else if (NoCaseCompare(finisher, "GlowStone") == 0) { m_FinishGens.push_back(std::make_unique(m_Seed)); } else if (NoCaseCompare(finisher, "Ice") == 0) { m_FinishGens.push_back(std::make_unique()); } else if (NoCaseCompare(finisher, "LavaLakes") == 0) { int Probability = a_IniFile.GetValueSetI("Generator", "LavaLakesProbability", 10); m_FinishGens.push_back(std::make_unique(m_Seed * 5 + 16873, E_BLOCK_STATIONARY_LAVA, *m_ShapeGen, Probability)); } else if (NoCaseCompare(finisher, "LavaSprings") == 0) { m_FinishGens.push_back(std::make_unique(m_Seed, E_BLOCK_LAVA, a_IniFile, m_Dimension)); } else if (NoCaseCompare(finisher, "Lilypads") == 0) { // A list with all the allowed biomes. cFinishGenSingleTopBlock::BiomeList AllowedBiomes; AllowedBiomes.push_back(biSwampland); AllowedBiomes.push_back(biSwamplandM); // A list with all the allowed blocks that can be below the lilypad. cFinishGenSingleTopBlock::BlockList AllowedBlocks; AllowedBlocks.push_back(E_BLOCK_WATER); AllowedBlocks.push_back(E_BLOCK_STATIONARY_WATER); m_FinishGens.push_back(std::make_unique(m_Seed, E_BLOCK_LILY_PAD, AllowedBiomes, 4, AllowedBlocks)); } else if (NoCaseCompare(finisher, "MarbleCaves") == 0) { m_FinishGens.push_back(std::make_unique(m_Seed)); } else if (NoCaseCompare(finisher, "MineShafts") == 0) { int GridSize = a_IniFile.GetValueSetI("Generator", "MineShaftsGridSize", 512); int MaxOffset = a_IniFile.GetValueSetI("Generator", "MineShaftsMaxOffset", 256); int MaxSystemSize = a_IniFile.GetValueSetI("Generator", "MineShaftsMaxSystemSize", 160); int ChanceCorridor = a_IniFile.GetValueSetI("Generator", "MineShaftsChanceCorridor", 600); int ChanceCrossing = a_IniFile.GetValueSetI("Generator", "MineShaftsChanceCrossing", 200); int ChanceStaircase = a_IniFile.GetValueSetI("Generator", "MineShaftsChanceStaircase", 200); m_FinishGens.push_back(std::make_unique( m_Seed, GridSize, MaxOffset, MaxSystemSize, ChanceCorridor, ChanceCrossing, ChanceStaircase )); } else if (NoCaseCompare(finisher, "NaturalPatches") == 0) { m_FinishGens.push_back(std::make_unique(m_Seed + 1, cFinishGenOreNests::DefaultNaturalPatches())); } else if (NoCaseCompare(finisher, "NetherClumpFoliage") == 0) { m_FinishGens.push_back(std::make_unique(m_Seed)); } else if (NoCaseCompare(finisher, "NetherOreNests") == 0) { m_FinishGens.push_back(std::make_unique(m_Seed + 2, cFinishGenOreNests::DefaultNetherOres())); } else if (NoCaseCompare(finisher, "OreNests") == 0) { m_FinishGens.push_back(std::make_unique(m_Seed + 3, cFinishGenOreNests::DefaultOverworldOres())); } else if (NoCaseCompare(finisher, "OrePockets") == 0) { auto Gen = std::make_unique(m_Seed + 2, cFinishGenOrePockets::DefaultOverworldOres()); Gen->Initialize(a_IniFile, "OrePockets"); m_FinishGens.push_back(std::move(Gen)); } else if (NoCaseCompare(finisher, "OverworldClumpFlowers") == 0) { auto flowers = cFinishGenClumpTopBlock::ParseIniFile(a_IniFile, "OverworldClumpFlowers"); m_FinishGens.push_back(std::make_unique(m_Seed, flowers)); } else if (NoCaseCompare(finisher, "PieceStructures") == 0) { if (split.size() < 2) { LOGWARNING("The PieceStructures generator needs the structures to use. Example: \"PieceStructures: NetherFort\"."); continue; } auto Gen = std::make_unique(m_Seed); if (Gen->Initialize(split[1], seaLevel, *m_BiomeGen, *m_CompositedHeightCache)) { m_FinishGens.push_back(std::move(Gen)); } } else if (NoCaseCompare(finisher, "PreSimulator") == 0) { // Load the settings bool PreSimulateFallingBlocks = a_IniFile.GetValueSetB("Generator", "PreSimulatorFallingBlocks", true); bool PreSimulateWater = a_IniFile.GetValueSetB("Generator", "PreSimulatorWater", true); bool PreSimulateLava = a_IniFile.GetValueSetB("Generator", "PreSimulatorLava", true); m_FinishGens.push_back(std::make_unique(PreSimulateFallingBlocks, PreSimulateWater, PreSimulateLava)); } else if (NoCaseCompare(finisher, "Ravines") == 0) { m_FinishGens.push_back(std::make_unique(m_Seed, 128)); } else if (NoCaseCompare(finisher, "RoughRavines") == 0) { int GridSize = a_IniFile.GetValueSetI("Generator", "RoughRavinesGridSize", 256); int MaxOffset = a_IniFile.GetValueSetI("Generator", "RoughRavinesMaxOffset", 128); int MaxSize = a_IniFile.GetValueSetI("Generator", "RoughRavinesMaxSize", 128); int MinSize = a_IniFile.GetValueSetI("Generator", "RoughRavinesMinSize", 64); double MaxCenterWidth = a_IniFile.GetValueSetF("Generator", "RoughRavinesMaxCenterWidth", 8); double MinCenterWidth = a_IniFile.GetValueSetF("Generator", "RoughRavinesMinCenterWidth", 2); double MaxRoughness = a_IniFile.GetValueSetF("Generator", "RoughRavinesMaxRoughness", 0.2); double MinRoughness = a_IniFile.GetValueSetF("Generator", "RoughRavinesMinRoughness", 0.05); double MaxFloorHeightEdge = a_IniFile.GetValueSetF("Generator", "RoughRavinesMaxFloorHeightEdge", 8); double MinFloorHeightEdge = a_IniFile.GetValueSetF("Generator", "RoughRavinesMinFloorHeightEdge", 30); double MaxFloorHeightCenter = a_IniFile.GetValueSetF("Generator", "RoughRavinesMaxFloorHeightCenter", 20); double MinFloorHeightCenter = a_IniFile.GetValueSetF("Generator", "RoughRavinesMinFloorHeightCenter", 6); double MaxCeilingHeightEdge = a_IniFile.GetValueSetF("Generator", "RoughRavinesMaxCeilingHeightEdge", 56); double MinCeilingHeightEdge = a_IniFile.GetValueSetF("Generator", "RoughRavinesMinCeilingHeightEdge", 38); double MaxCeilingHeightCenter = a_IniFile.GetValueSetF("Generator", "RoughRavinesMaxCeilingHeightCenter", 58); double MinCeilingHeightCenter = a_IniFile.GetValueSetF("Generator", "RoughRavinesMinCeilingHeightCenter", 36); m_FinishGens.push_back(std::make_unique( m_Seed, MaxSize, MinSize, static_cast(MaxCenterWidth), static_cast(MinCenterWidth), static_cast(MaxRoughness), static_cast(MinRoughness), static_cast(MaxFloorHeightEdge), static_cast(MinFloorHeightEdge), static_cast(MaxFloorHeightCenter), static_cast(MinFloorHeightCenter), static_cast(MaxCeilingHeightEdge), static_cast(MinCeilingHeightEdge), static_cast(MaxCeilingHeightCenter), static_cast(MinCeilingHeightCenter), GridSize, MaxOffset )); } else if (NoCaseCompare(finisher, "SinglePieceStructures") == 0) { if (split.size() < 2) { LOGWARNING("The SinglePieceStructures generator needs the structures to use. Example: \"SinglePieceStructures: DesertPyramid\"."); continue; } auto Gen = std::make_unique(m_Seed); if (Gen->Initialize(split[1], seaLevel, *m_BiomeGen, *m_CompositedHeightCache)) { m_FinishGens.push_back(std::move(Gen)); } } else if (NoCaseCompare(finisher, "SoulsandRims") == 0) { m_FinishGens.push_back(std::make_unique(m_Seed)); } else if (NoCaseCompare(finisher, "Snow") == 0) { m_FinishGens.push_back(std::make_unique()); } else if (NoCaseCompare(finisher, "SprinkleFoliage") == 0) { int MaxCactusHeight = a_IniFile.GetValueI("Plants", "MaxCactusHeight", 3); int MaxSugarcaneHeight = a_IniFile.GetValueI("Plants", "MaxSugarcaneHeight", 3); m_FinishGens.push_back(std::make_unique(m_Seed, MaxCactusHeight, MaxSugarcaneHeight)); } else if (NoCaseCompare(finisher, "TallGrass") == 0) { m_FinishGens.push_back(std::make_unique(m_Seed)); } else if (NoCaseCompare(finisher, "Trees") == 0) { m_FinishGens.push_back(std::make_unique(m_Seed, *m_BiomeGen, *m_ShapeGen, *m_CompositionGen)); } else if (NoCaseCompare(finisher, "Villages") == 0) { int GridSize = a_IniFile.GetValueSetI("Generator", "VillageGridSize", 384); int MaxOffset = a_IniFile.GetValueSetI("Generator", "VillageMaxOffset", 128); int MaxDepth = a_IniFile.GetValueSetI("Generator", "VillageMaxDepth", 2); int MaxSize = a_IniFile.GetValueSetI("Generator", "VillageMaxSize", 128); int MinDensity = a_IniFile.GetValueSetI("Generator", "VillageMinDensity", 50); int MaxDensity = a_IniFile.GetValueSetI("Generator", "VillageMaxDensity", 80); AString PrefabList = a_IniFile.GetValueSet("Generator", "VillagePrefabs", "PlainsVillage, SandVillage"); auto Prefabs = StringSplitAndTrim(PrefabList, ","); m_FinishGens.push_back(std::make_unique(m_Seed, GridSize, MaxOffset, MaxDepth, MaxSize, MinDensity, MaxDensity, *m_BiomeGen, *m_CompositedHeightCache, seaLevel, Prefabs)); } else if (NoCaseCompare(finisher, "Vines") == 0) { int Level = a_IniFile.GetValueSetI("Generator", "VinesLevel", 40); m_FinishGens.push_back(std::make_unique(m_Seed, Level)); } else if (NoCaseCompare(finisher, "WaterLakes") == 0) { int Probability = a_IniFile.GetValueSetI("Generator", "WaterLakesProbability", 25); m_FinishGens.push_back(std::make_unique(m_Seed * 3 + 652, E_BLOCK_STATIONARY_WATER, *m_ShapeGen, Probability)); } else if (NoCaseCompare(finisher, "WaterSprings") == 0) { m_FinishGens.push_back(std::make_unique(m_Seed, E_BLOCK_WATER, a_IniFile, m_Dimension)); } else if (NoCaseCompare(finisher, "WormNestCaves") == 0) { int Size = a_IniFile.GetValueSetI("Generator", "WormNestCavesSize", 64); int Grid = a_IniFile.GetValueSetI("Generator", "WormNestCavesGrid", 96); int MaxOffset = a_IniFile.GetValueSetI("Generator", "WormNestMaxOffset", 32); m_FinishGens.push_back(std::make_unique(m_Seed, Size, Grid, MaxOffset)); } else { LOGWARNING("Unknown Finisher in the [Generator] section: \"%s\". Ignoring.", finisher.c_str()); } } // for itr - Str[] } ================================================ FILE: src/Generating/ComposableGenerator.h ================================================ // ComposableGenerator.h // Declares the cComposableGenerator class representing the chunk generator that takes the composition approach to generating chunks /* Generating works by composing several algorithms: Biome, TerrainHeight, TerrainComposition, Ores, Structures and SmallFoliage Each algorithm may be chosen from a pool of available algorithms in the same class and combined with others, based on user's preferences in the world.ini. See https://forum.cuberite.org/thread-409.html for details. */ #pragma once #include "ChunkGenerator.h" #include "ChunkDesc.h" // Forward-declare the shared pointers to subgenerator classes: class cBiomeGen; class cTerrainShapeGen; class cTerrainHeightGen; class cTerrainCompositionGen; class cFinishGen; /** The interface that a biome generator must implement A biome generator takes chunk coords on input and outputs an array of biome indices for that chunk on output. The output array is sequenced in the same way as the MapChunk packet's biome data. */ class cBiomeGen { public: virtual ~cBiomeGen() {} // Force a virtual destructor in descendants /** Generates biomes for the given chunk */ virtual void GenBiomes(cChunkCoords a_ChunkCoords, cChunkDef::BiomeMap & a_BiomeMap) = 0; /** Reads parameters from the ini file, prepares generator for use. */ virtual void InitializeBiomeGen(cIniFile & a_IniFile) {} /** Creates the correct BiomeGen descendant based on the ini file settings. a_Seed is the seed read from the INI file. a_CacheOffByDefault gets set to whether the cache should be disabled by default. Used in BiomeVisualiser, too. Implemented in BioGen.cpp! */ static std::unique_ptr CreateBiomeGen( cIniFile & a_IniFile, int a_Seed, bool & a_CacheOffByDefault ); } ; /** The interface that a terrain shape generator must implement A terrain shape generator takes chunk coords on input and outputs a 3D array of "shape" for that chunk. The shape here represents the distinction between air and solid; there's no representation of Water since that is added by the composition geenrator. The output array is indexed [y + 256 * z + 16 * 256 * x], so that it's fast to later compose a single column of the terrain, which is the dominant operation following the shape generation. The generator may request biome information from the underlying BiomeGen, it may even request information for other chunks than the one it's currently generating (neighbors - for averaging) */ class cTerrainShapeGen { public: virtual ~cTerrainShapeGen() {} // Force a virtual destructor in descendants /** Generates the shape for the given chunk */ virtual void GenShape(cChunkCoords a_ChunkCoords, cChunkDesc::Shape & a_Shape) = 0; /** Reads parameters from the ini file, prepares generator for use. */ virtual void InitializeShapeGen(cIniFile & a_IniFile) {} /** Creates the correct TerrainShapeGen descendant based on the ini file settings and the seed provided. a_BiomeGen is the underlying biome generator, some shape generators may depend on it providing additional biomes data around the chunk a_CacheOffByDefault gets set to whether the cache should be disabled by default Implemented in ShapeGen.cpp! */ static std::unique_ptr CreateShapeGen( cIniFile & a_IniFile, cBiomeGen & a_BiomeGen, int a_Seed, bool & a_CacheOffByDefault ); } ; /** The interface that is used to query terrain height from the shape generator. Usually the structure generators require only the final heightmap, and generating the whole shape only to consume the heightmap is wasteful, so this interface is used instead; it has a cache implemented over it so that data is retained. */ class cTerrainHeightGen { public: virtual ~cTerrainHeightGen() {} // Force a virtual destructor in descendants /** Retrieves the heightmap for the specified chunk. */ virtual void GenHeightMap(cChunkCoords a_ChunkCoords, cChunkDef::HeightMap & a_HeightMap) = 0; /** Initializes the generator, reading its parameters from the INI file. */ virtual void InitializeHeightGen(cIniFile & a_IniFile) {} /** Returns the height at the specified column. The default implementation calls GenHeightMap(), and then queries the heightmap. Descendants may provide a better-performing method. */ virtual HEIGHTTYPE GetHeightAt(int a_BlockX, int a_BlockZ) { auto chunkCoords = cChunkDef::BlockToChunk({a_BlockX, 0, a_BlockZ}); cChunkDef::HeightMap heightMap; GenHeightMap(chunkCoords, heightMap); return cChunkDef::GetHeight(heightMap, a_BlockX - chunkCoords.m_ChunkX * cChunkDef::Width, a_BlockZ - chunkCoords.m_ChunkZ * cChunkDef::Width); } /** Creates a cTerrainHeightGen descendant based on the INI file settings. */ static std::unique_ptr CreateHeightGen( cIniFile & a_IniFile, cBiomeGen & a_BiomeGen, int a_Seed, bool & a_CacheOffByDefault ); } ; /** The interface that a terrain composition generator must implement Terrain composition takes chunk coords on input and outputs the blockdata for that entire chunk, along with the list of entities. It is supposed to make use of the underlying TerrainHeightGen and BiomeGen for that purpose, but it may request information for other chunks than the one it's currently generating from them. */ class cTerrainCompositionGen { public: virtual ~cTerrainCompositionGen() {} // Force a virtual destructor in descendants /** Generates the chunk's composition into a_ChunkDesc, using the terrain shape provided in a_Shape. Is expected to fill a_ChunkDesc's heightmap with the data from a_Shape. */ virtual void ComposeTerrain(cChunkDesc & a_ChunkDesc, const cChunkDesc::Shape & a_Shape) = 0; /** Reads parameters from the ini file, prepares generator for use. */ virtual void InitializeCompoGen(cIniFile & a_IniFile) {} /** Creates the correct TerrainCompositionGen descendant based on the ini file settings and the seed provided. a_BiomeGen is the underlying biome generator, some composition generators may depend on it providing additional biomes around the chunk a_ShapeGen is the underlying shape generator, some composition generators may depend on it providing additional shape around the chunk. */ static std::unique_ptr CreateCompositionGen( cIniFile & a_IniFile, cBiomeGen & a_BiomeGen, cTerrainShapeGen & a_ShapeGen, int a_Seed ); } ; /** The interface that a finisher must implement Finisher implements changes to the chunk after the rough terrain has been generated. Examples of finishers are trees, snow, ore, lilypads and others. Note that a worldgenerator may contain multiple finishers, chained one after another. Also note that previously we used to distinguish between a structuregen and a finisher; this distinction is no longer relevant, all structure generators are considered finishers now (#398) */ class cFinishGen { public: virtual ~cFinishGen() {} // Force a virtual destructor in descendants virtual void GenFinish(cChunkDesc & a_ChunkDesc) = 0; } ; class cComposableGenerator: public cChunkGenerator { using Super = cChunkGenerator; public: cComposableGenerator(); // cChunkGenerator::cGenerator overrides: virtual void Initialize(cIniFile & a_IniFile) override; virtual void GenerateBiomes(cChunkCoords a_ChunkCoords, cChunkDef::BiomeMap & a_BiomeMap) override; virtual void Generate(cChunkDesc & a_ChunkDesc) override; /** If there's no particular sub-generator set in the INI file, adds the default one, based on the dimension. */ static void InitializeGeneratorDefaults(cIniFile & a_IniFile, eDimension a_Dimension); protected: // The generator's composition: /** The biome generator. */ std::unique_ptr m_BiomeGen; /** The terrain shape generator. */ std::unique_ptr m_ShapeGen; /** The terrain composition generator. */ std::unique_ptr m_CompositionGen; /** The cache for the heights of the composited terrain. */ std::unique_ptr m_CompositedHeightCache; /** The finisher generators, in the order in which they are applied. */ std::vector> m_FinishGens; /** Reads the BiomeGen settings from the ini and initializes m_BiomeGen accordingly */ void InitBiomeGen(cIniFile & a_IniFile); /** Reads the ShapeGen settings from the ini and initializes m_ShapeGen accordingly */ void InitShapeGen(cIniFile & a_IniFile); /** Reads the CompositionGen settings from the ini and initializes m_CompositionGen accordingly */ void InitCompositionGen(cIniFile & a_IniFile); /** Reads the finishers from the ini and initializes m_FinishGens accordingly */ void InitFinishGens(cIniFile & a_IniFile); } ; ================================================ FILE: src/Generating/CompositedHeiGen.h ================================================ // CompositedHeiGen.h // Declares the cCompositedHeiGen class representing a cTerrainHeightGen descendant that calculates heightmap of the composited terrain // This is used to further cache heightmaps for chunks already generated for finishers that require only heightmap information #pragma once #include "ComposableGenerator.h" class cCompositedHeiGen: public cTerrainHeightGen { public: cCompositedHeiGen(cBiomeGen & a_BiomeGen, cTerrainShapeGen & a_ShapeGen, cTerrainCompositionGen & a_CompositionGen): m_BiomeGen(a_BiomeGen), m_ShapeGen(a_ShapeGen), m_CompositionGen(a_CompositionGen) { } // cTerrainHeightGen overrides: virtual void GenHeightMap(cChunkCoords a_ChunkCoords, cChunkDef::HeightMap & a_HeightMap) override { cChunkDesc::Shape shape; m_ShapeGen.GenShape(a_ChunkCoords, shape); cChunkDesc desc(a_ChunkCoords); m_BiomeGen.GenBiomes(a_ChunkCoords, desc.GetBiomeMap()); // Need to initialize biomes for the composition gen desc.SetHeightFromShape(shape); m_CompositionGen.ComposeTerrain(desc, shape); memcpy(a_HeightMap, desc.GetHeightMap(), sizeof(a_HeightMap)); } protected: cBiomeGen & m_BiomeGen; cTerrainShapeGen & m_ShapeGen; cTerrainCompositionGen & m_CompositionGen; }; ================================================ FILE: src/Generating/DistortedHeightmap.cpp ================================================ // DistortedHeightmap.cpp // Implements the cDistortedHeightmap class representing the height and composition generator capable of overhangs #include "Globals.h" #include "DistortedHeightmap.h" #include "../IniFile.h" #include "../LinearUpscale.h" //////////////////////////////////////////////////////////////////////////////// // cDistortedHeightmap: /** This table assigns a relative maximum overhang size in each direction to biomes. Both numbers indicate a number which will multiply the noise value for each coord; this means that you can have different-sized overhangs in each direction. Usually you'd want to keep both numbers the same. The numbers are "relative", not absolute maximum; overhangs of a slightly larger size are possible due to the way that noise is calculated. */ const cDistortedHeightmap::sGenParam cDistortedHeightmap::m_GenParam[256] = { /* Biome | AmpX | AmpZ */ /* biOcean */ { 1.5f, 1.5f}, /* biPlains */ { 0.5f, 0.5f}, /* biDesert */ { 0.5f, 0.5f}, /* biExtremeHills */ {16.0f, 16.0f}, /* biForest */ { 3.0f, 3.0f}, /* biTaiga */ { 1.5f, 1.5f}, /* biSwampland */ { 0.0f, 0.0f}, /* biRiver */ { 0.0f, 0.0f}, /* biNether */ { 0.0f, 0.0f}, // Unused, but must be here due to indexing /* biSky */ { 0.0f, 0.0f}, // Unused, but must be here due to indexing /* biFrozenOcean */ { 0.0f, 0.0f}, /* biFrozenRiver */ { 0.0f, 0.0f}, /* biIcePlains */ { 0.0f, 0.0f}, /* biIceMountains */ { 8.0f, 8.0f}, /* biMushroomIsland */ { 4.0f, 4.0f}, /* biMushroomShore */ { 0.0f, 0.0f}, /* biBeach */ { 0.0f, 0.0f}, /* biDesertHills */ { 5.0f, 5.0f}, /* biForestHills */ { 6.0f, 6.0f}, /* biTaigaHills */ { 8.0f, 8.0f}, /* biExtremeHillsEdge */ { 7.0f, 7.0f}, /* biJungle */ { 4.0f, 4.0f}, /* biJungleHills */ { 8.0f, 8.0f}, /* biJungleEdge */ { 3.0f, 3.0f}, // 23 /* biDeepOcean */ { 1.0f, 1.0f}, // 24 /* biStoneBeach */ { 1.0f, 1.0f}, // 25 /* biColdBeach */ { 1.0f, 1.0f}, // 26 /* biBirchForest */ { 3.0f, 3.0f}, // 27 /* biBirchForestHills */ { 6.0f, 6.0f}, // 28 /* biRoofedForest */ { 3.0f, 3.0f}, // 29 /* biColdTaiga */ { 0.5f, 0.5f}, // 30 /* biColdTaigaHills */ { 4.0f, 4.0f}, // 31 /* biMegaTaiga */ { 1.0f, 1.0f}, // 32 /* biMegaTaigaHills */ { 4.0f, 4.0f}, // 33 /* biExtremeHillsPlus */ {32.0f, 32.0f}, // 34 - anyone say extreme plus? Make it extreme plus, then :) /* biSavanna */ { 2.0f, 2.0f}, // 35 /* biSavannaPlateau */ { 3.0f, 3.0f}, // 36 /* biMesa */ { 2.0f, 2.0f}, // 37 /* biMesaPlateauF */ { 2.0f, 2.0f}, // 38 /* biMesaPlateau */ { 2.0f, 2.0f}, // 39 // biomes 40 .. 128 are unused, 89 empty placeholders here: {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, // 40 .. 49 {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, // 50 .. 59 {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, // 60 .. 69 {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, // 70 .. 79 {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, // 80 .. 89 {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, // 90 .. 99 {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, // 100 .. 109 {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, // 110 .. 119 {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, // 120 .. 128 // Release 1.7 biome variants: /* biSunflowerPlains */ { 1.0f, 1.0f}, // 129 /* biDesertM */ { 1.0f, 1.0f}, // 130 /* biExtremeHillsM */ {16.0f, 16.0f}, // 131 /* biFlowerForest */ { 4.0f, 4.0f}, // 132 /* biTaigaM */ { 3.0f, 3.0f}, // 133 /* biSwamplandM */ { 0.0f, 0.0f}, // 134 // Biomes 135 .. 139 unused, 5 empty placeholders here: {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, // 135 .. 139 /* biIcePlainsSpikes */ { 1.0f, 1.0f}, // 140 // Biomes 141 .. 148 unused, 8 empty placeholders here: {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, // 141 .. 148 /* biJungleM */ { 4.0f, 4.0f}, // 149 {0.0f, 0.0f}, // 150 /* biJungleEdgeM */ { 3.0f, 3.0f}, // 151 {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, // 152 .. 154 /* biBirchForestM */ { 3.0f, 3.0f}, // 155 /* biBirchForestHillsM */ { 5.0f, 5.0f}, // 156 /* biRoofedForestM */ { 2.0f, 2.0f}, // 157 /* biColdTaigaM */ { 1.0f, 1.0f}, // 158 {0.0f, 0.0f}, // 159 /* biMegaSpruceTaiga */ { 3.0f, 3.0f}, // 160 /* biMegaSpruceTaigaHills */ { 3.0f, 3.0f}, // 161 /* biExtremeHillsPlusM */ {32.0f, 32.0f}, // 162 /* biSavannaM */ { 2.0f, 2.0f}, // 163 /* biSavannaPlateauM */ { 3.0f, 3.0f}, // 164 /* biMesaBryce */ { 0.5f, 0.5f}, // 165 /* biMesaPlateauFM */ { 2.0f, 2.0f}, // 166 /* biMesaPlateauM */ { 2.0f, 2.0f}, // 167 } ; cDistortedHeightmap::cDistortedHeightmap(int a_Seed, cBiomeGen & a_BiomeGen) : m_NoiseDistortX(a_Seed + 1000), m_NoiseDistortZ(a_Seed + 2000), m_CurChunkCoords(0x7fffffff, 0x7fffffff), // Set impossible coords for the chunk so that it's always considered stale m_BiomeGen(a_BiomeGen), m_UnderlyingHeiGen(a_Seed, a_BiomeGen), m_HeightGen(m_UnderlyingHeiGen, 64), m_IsInitialized(false) { m_NoiseDistortX.AddOctave(static_cast(1), static_cast(0.5)); m_NoiseDistortX.AddOctave(static_cast(0.5), static_cast(1)); m_NoiseDistortX.AddOctave(static_cast(0.25), static_cast(2)); m_NoiseDistortZ.AddOctave(static_cast(1), static_cast(0.5)); m_NoiseDistortZ.AddOctave(static_cast(0.5), static_cast(1)); m_NoiseDistortZ.AddOctave(static_cast(0.25), static_cast(2)); } void cDistortedHeightmap::Initialize(cIniFile & a_IniFile) { if (m_IsInitialized) { return; } // Read the params from the INI file: m_SeaLevel = a_IniFile.GetValueSetI("Generator", "SeaLevel", 62); m_FrequencyX = static_cast(a_IniFile.GetValueSetF("Generator", "DistortedHeightmapFrequencyX", 10)); m_FrequencyY = static_cast(a_IniFile.GetValueSetF("Generator", "DistortedHeightmapFrequencyY", 10)); m_FrequencyZ = static_cast(a_IniFile.GetValueSetF("Generator", "DistortedHeightmapFrequencyZ", 10)); m_IsInitialized = true; } void cDistortedHeightmap::PrepareState(cChunkCoords a_ChunkCoords) { if (m_CurChunkCoords == a_ChunkCoords) { return; } m_CurChunkCoords = a_ChunkCoords; m_HeightGen.GenHeightMap(a_ChunkCoords, m_CurChunkHeights); UpdateDistortAmps(); GenerateHeightArray(); } void cDistortedHeightmap::GenerateHeightArray(void) { // Generate distortion noise: NOISE_DATATYPE DistortNoiseX[DIM_X * DIM_Y * DIM_Z]; NOISE_DATATYPE DistortNoiseZ[DIM_X * DIM_Y * DIM_Z]; NOISE_DATATYPE Workspace[DIM_X * DIM_Y * DIM_Z]; NOISE_DATATYPE StartX = static_cast(m_CurChunkCoords.m_ChunkX * cChunkDef::Width) / m_FrequencyX; NOISE_DATATYPE EndX = static_cast((m_CurChunkCoords.m_ChunkX + 1) * cChunkDef::Width - 1) / m_FrequencyX; NOISE_DATATYPE StartY = 0; NOISE_DATATYPE EndY = static_cast(257) / m_FrequencyY; NOISE_DATATYPE StartZ = static_cast(m_CurChunkCoords.m_ChunkZ * cChunkDef::Width) / m_FrequencyZ; NOISE_DATATYPE EndZ = static_cast((m_CurChunkCoords.m_ChunkZ + 1) * cChunkDef::Width - 1) / m_FrequencyZ; m_NoiseDistortX.Generate3D(DistortNoiseX, DIM_X, DIM_Y, DIM_Z, StartX, EndX, StartY, EndY, StartZ, EndZ, Workspace); m_NoiseDistortZ.Generate3D(DistortNoiseZ, DIM_X, DIM_Y, DIM_Z, StartX, EndX, StartY, EndY, StartZ, EndZ, Workspace); // The distorted heightmap, before linear upscaling NOISE_DATATYPE DistHei[DIM_X * DIM_Y * DIM_Z]; // Distort the heightmap using the distortion: for (int z = 0; z < DIM_Z; z++) { int AmpIdx = z * DIM_X; for (int y = 0; y < DIM_Y; y++) { int NoiseArrayIdx = z * DIM_X * DIM_Y + y * DIM_X; for (int x = 0; x < DIM_X; x++) { NOISE_DATATYPE DistX = DistortNoiseX[NoiseArrayIdx + x] * m_DistortAmpX[AmpIdx + x]; NOISE_DATATYPE DistZ = DistortNoiseZ[NoiseArrayIdx + x] * m_DistortAmpZ[AmpIdx + x]; DistX += static_cast(m_CurChunkCoords.m_ChunkX * cChunkDef::Width + x * INTERPOL_X); DistZ += static_cast(m_CurChunkCoords.m_ChunkZ * cChunkDef::Width + z * INTERPOL_Z); // Adding 0.5 helps alleviate the interpolation artifacts DistHei[NoiseArrayIdx + x] = static_cast(GetHeightmapAt(DistX, DistZ)) + static_cast(0.5); } } } // Upscale the distorted heightmap into full dimensions: LinearUpscale3DArray( DistHei, DIM_X, DIM_Y, DIM_Z, m_DistortedHeightmap, INTERPOL_X, INTERPOL_Y, INTERPOL_Z ); // DEBUG: Debug3DNoise(m_DistortedHeightmap, 17, 257, 17, fmt::format(FMT_STRING("DistortedHeightmap_{}_{}"), m_CurChunkX, m_CurChunkZ)); } void cDistortedHeightmap::GenShape(cChunkCoords a_ChunkCoords, cChunkDesc::Shape & a_Shape) { PrepareState(a_ChunkCoords); for (int z = 0; z < cChunkDef::Width; z++) { for (int x = 0; x < cChunkDef::Width; x++) { int idx = x + 17 * 257 * z; for (int y = 0; y < cChunkDef::Height; y++) { a_Shape[y + x * 256 + z * 16 * 256] = (y < m_DistortedHeightmap[idx + y * 17]) ? 1 : 0; } // for y } // for x } // for z } void cDistortedHeightmap::InitializeShapeGen(cIniFile & a_IniFile) { Initialize(a_IniFile); } int cDistortedHeightmap::GetHeightmapAt(NOISE_DATATYPE a_X, NOISE_DATATYPE a_Z) { int RelX = FloorC(a_X); int RelY = 0; int RelZ = FloorC(a_Z); int ChunkX, ChunkZ; cChunkDef::AbsoluteToRelative(RelX, RelY, RelZ, ChunkX, ChunkZ); // If we're within the same chunk, return the pre-cached heightmap: if ((ChunkX == m_CurChunkCoords.m_ChunkX) && (ChunkZ == m_CurChunkCoords.m_ChunkZ)) { return cChunkDef::GetHeight(m_CurChunkHeights, RelX, RelZ); } // Ask the cache: HEIGHTTYPE res = 0; if (m_HeightGen.GetHeightAt(ChunkX, ChunkZ, RelX, RelZ, res)) { // The height was in the cache return res; } // The height is not in the cache, generate full heightmap and get it there: cChunkDef::HeightMap Heightmap; m_HeightGen.GenHeightMap({ChunkX, ChunkZ}, Heightmap); return cChunkDef::GetHeight(Heightmap, RelX, RelZ); } void cDistortedHeightmap::UpdateDistortAmps(void) { BiomeNeighbors Biomes; for (int z = -1; z <= 1; z++) { for (int x = -1; x <= 1; x++) { m_BiomeGen.GenBiomes({m_CurChunkCoords.m_ChunkX + x, m_CurChunkCoords.m_ChunkZ + z}, Biomes[x + 1][z + 1]); } // for x } // for z for (int z = 0; z < DIM_Z; z++) { for (int x = 0; x < DIM_Z; x++) { GetDistortAmpsAt(Biomes, x * INTERPOL_X, z * INTERPOL_Z, m_DistortAmpX[x + DIM_X * z], m_DistortAmpZ[x + DIM_X * z]); } } } void cDistortedHeightmap::GetDistortAmpsAt(BiomeNeighbors & a_Neighbors, int a_RelX, int a_RelZ, NOISE_DATATYPE & a_DistortAmpX, NOISE_DATATYPE & a_DistortAmpZ) { // Sum up how many biomes of each type there are in the neighborhood: int BiomeCounts[256]; memset(BiomeCounts, 0, sizeof(BiomeCounts)); int Sum = 0; for (int z = -8; z <= 8; z++) { int FinalZ = a_RelZ + z + cChunkDef::Width; int IdxZ = FinalZ / cChunkDef::Width; int ModZ = FinalZ % cChunkDef::Width; int WeightZ = 9 - abs(z); for (int x = -8; x <= 8; x++) { int FinalX = a_RelX + x + cChunkDef::Width; int IdxX = FinalX / cChunkDef::Width; int ModX = FinalX % cChunkDef::Width; EMCSBiome Biome = cChunkDef::GetBiome(a_Neighbors[IdxX][IdxZ], ModX, ModZ); int WeightX = 9 - abs(x); BiomeCounts[Biome] += WeightX + WeightZ; Sum += WeightX + WeightZ; } // for x } // for z if (Sum <= 0) { // No known biome around? Weird. Return a bogus value: ASSERT(!"cHeiGenBiomal: Biome sum failed, no known biome around"); a_DistortAmpX = 16; a_DistortAmpZ = 16; } // For each biome type that has a nonzero count, calc its amps and add it: NOISE_DATATYPE AmpX = 0; NOISE_DATATYPE AmpZ = 0; for (size_t i = 0; i < ARRAYCOUNT(BiomeCounts); i++) { if (BiomeCounts[i] <= 0) { continue; } /* // Sanity checks for biome parameters, enable them to check the biome param table in runtime (slow): ASSERT(m_GenParam[i].m_DistortAmpX >= 0); ASSERT(m_GenParam[i].m_DistortAmpX < 100); ASSERT(m_GenParam[i].m_DistortAmpX >= 0); ASSERT(m_GenParam[i].m_DistortAmpX < 100); */ AmpX += BiomeCounts[i] * m_GenParam[i].m_DistortAmpX; AmpZ += BiomeCounts[i] * m_GenParam[i].m_DistortAmpZ; } a_DistortAmpX = AmpX / Sum; a_DistortAmpZ = AmpZ / Sum; } ================================================ FILE: src/Generating/DistortedHeightmap.h ================================================ // DistortedHeightmap.h // Declares the cDistortedHeightmap class representing the height and composition generator capable of overhangs #pragma once #include "ComposableGenerator.h" #include "HeiGen.h" #define NOISE_SIZE_Y (257 + 32) class cDistortedHeightmap : public cTerrainShapeGen { public: cDistortedHeightmap(int a_Seed, cBiomeGen & a_BiomeGen); protected: typedef cChunkDef::BiomeMap BiomeNeighbors[3][3]; // Linear upscaling step sizes, must be divisors of cChunkDef::Width and cChunkDef::Height, respectively: static const int INTERPOL_X = 8; static const int INTERPOL_Y = 4; static const int INTERPOL_Z = 8; // Linear upscaling buffer dimensions, calculated from the step sizes: static const int DIM_X = 1 + (17 / INTERPOL_X); static const int DIM_Y = 1 + (257 / INTERPOL_Y); static const int DIM_Z = 1 + (17 / INTERPOL_Z); cPerlinNoise m_NoiseDistortX; cPerlinNoise m_NoiseDistortZ; int m_SeaLevel; NOISE_DATATYPE m_FrequencyX; NOISE_DATATYPE m_FrequencyY; NOISE_DATATYPE m_FrequencyZ; cChunkCoords m_CurChunkCoords; NOISE_DATATYPE m_DistortedHeightmap[17 * 257 * 17]; /** The bime generator to query for biomes. */ cBiomeGen & m_BiomeGen; /** The generator that provides the base heightmap (before distortion). */ cHeiGenBiomal m_UnderlyingHeiGen; /** Cache for m_UnderlyingHeiGen. */ cHeiGenCache m_HeightGen; /** Heightmap for the current chunk, before distortion (from m_HeightGen). Used for optimization. */ cChunkDef::HeightMap m_CurChunkHeights; // Per-biome terrain generator parameters: struct sGenParam { NOISE_DATATYPE m_DistortAmpX; NOISE_DATATYPE m_DistortAmpZ; } ; static const sGenParam m_GenParam[256]; // Distortion amplitudes for each direction, before linear upscaling NOISE_DATATYPE m_DistortAmpX[DIM_X * DIM_Z]; NOISE_DATATYPE m_DistortAmpZ[DIM_X * DIM_Z]; /** True if Initialize() has been called. Used to initialize-once even with multiple init entrypoints (HeiGen / CompoGen). */ bool m_IsInitialized; /** Unless the LastChunk coords are equal to coords given, prepares the internal state (noise arrays, heightmap). */ void PrepareState(cChunkCoords a_ChunkCoords); /** Generates the m_DistortedHeightmap array for the current chunk. */ void GenerateHeightArray(void); /** Calculates the heightmap value (before distortion) at the specified (floating-point) coords. */ int GetHeightmapAt(NOISE_DATATYPE a_X, NOISE_DATATYPE a_Z); /** Updates m_DistortAmpX/Z[] based on m_CurChunkX and m_CurChunkZ. */ void UpdateDistortAmps(void); /** Calculates the X and Z distortion amplitudes based on the neighbors' biomes. */ void GetDistortAmpsAt(BiomeNeighbors & a_Neighbors, int a_RelX, int a_RelZ, NOISE_DATATYPE & a_DistortAmpX, NOISE_DATATYPE & a_DistortAmpZ); /** Reads the settings from the ini file. Skips reading if already initialized. */ void Initialize(cIniFile & a_IniFile); // cTerrainShapeGen overrides: virtual void GenShape(cChunkCoords a_ChunkCoords, cChunkDesc::Shape & a_Shape) override; virtual void InitializeShapeGen(cIniFile & a_IniFile) override; } ; ================================================ FILE: src/Generating/DungeonRoomsFinisher.cpp ================================================ // DungeonRoomsFinisher.cpp // Declares the cDungeonRoomsFinisher class representing the finisher that generates dungeon rooms #include "Globals.h" #include "DungeonRoomsFinisher.h" #include "../BlockInfo.h" #include "../FastRandom.h" #include "../BlockEntities/ChestEntity.h" #include "../BlockEntities/MobSpawnerEntity.h" /** Height, in blocks, of the internal dungeon room open space. This many air blocks Y-wise. */ static const int ROOM_HEIGHT = 4; //////////////////////////////////////////////////////////////////////////////// // cDungeonRoom: class cDungeonRoom: public cGridStructGen::cStructure { using Super = cGridStructGen::cStructure; public: cDungeonRoom( int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ, int a_HalfSizeX, int a_HalfSizeZ, int a_FloorHeight, cNoise & a_Noise ): Super(a_GridX, a_GridZ, a_OriginX, a_OriginZ), m_StartX(a_OriginX - a_HalfSizeX), m_EndX(a_OriginX + a_HalfSizeX), m_StartZ(a_OriginZ - a_HalfSizeZ), m_EndZ(a_OriginZ + a_HalfSizeZ), m_FloorHeight(a_FloorHeight) { /* Pick coords next to the wall for the chests. This is done by indexing the possible coords, picking any one for the first chest and then picking another position for the second chest that is not adjacent to the first pos */ int rnd = a_Noise.IntNoise2DInt(a_OriginX, a_OriginZ) / 7; int SizeX = m_EndX - m_StartX - 1; int SizeZ = m_EndZ - m_StartZ - 1; int NumPositions = 2 * SizeX + 2 * SizeZ; int FirstChestPos = rnd % NumPositions; // The corner positions are a bit more likely, but we don't mind rnd = rnd / 512; int SecondChestPos = (FirstChestPos + 2 + (rnd % (NumPositions - 3))) % NumPositions; m_Chest1 = DecodeChestCoords(FirstChestPos, SizeX, SizeZ); m_Chest2 = DecodeChestCoords(SecondChestPos, SizeX, SizeZ); // Choose what the mobspawner will spawn. // 25% chance for a spider, 25% for a skeleton and 50% chance to get a zombie spawer. int MobType = (a_Noise.IntNoise3DInt(a_OriginX, m_FloorHeight, a_OriginZ) / 7) % 100; if (MobType <= 25) { m_MonsterType = mtSkeleton; } else if (MobType <= 50) { m_MonsterType = mtSpider; } else { m_MonsterType = mtZombie; } } protected: // The X range of the room, start inclusive, end exclusive: int m_StartX, m_EndX; // The Z range of the room, start inclusive, end exclusive: int m_StartZ, m_EndZ; /** The Y coord of the floor of the room */ int m_FloorHeight; /** The (absolute) coords of the first chest. The Y coord represents the chest's Meta value (facing). */ Vector3i m_Chest1; /** The (absolute) coords of the second chest. The Y coord represents the chest's Meta value (facing). */ Vector3i m_Chest2; /** The monster type for the mobspawner entity. */ eMonsterType m_MonsterType; /** Decodes the position index along the room walls into a proper 2D position for a chest. The Y coord of the returned vector specifies the chest's meta value. */ Vector3i DecodeChestCoords(int a_PosIdx, int a_SizeX, int a_SizeZ) { if (a_PosIdx < a_SizeX) { // Return a coord on the ZM side of the room: return Vector3i(m_StartX + a_PosIdx + 1, E_META_CHEST_FACING_ZP, m_StartZ + 1); } a_PosIdx -= a_SizeX; if (a_PosIdx < a_SizeZ) { // Return a coord on the XP side of the room: return Vector3i(m_EndX - 1, E_META_CHEST_FACING_XM, m_StartZ + a_PosIdx + 1); } a_PosIdx -= a_SizeZ; if (a_PosIdx < a_SizeX) { // Return a coord on the ZP side of the room: return Vector3i(m_StartX + a_PosIdx + 1, E_META_CHEST_FACING_ZM, m_StartZ + 1); } a_PosIdx -= a_SizeX; // Return a coord on the XM side of the room: return Vector3i(m_StartX + 1, E_META_CHEST_FACING_XP, m_StartZ + a_PosIdx + 1); } /** Fills the specified area of blocks in the chunk with the specified blocktype if they are one of the overwritten block types. The coords are absolute, start coords are inclusive, end coords are exclusive. */ void ReplaceCuboid(cChunkDesc & a_ChunkDesc, int a_StartX, int a_StartY, int a_StartZ, int a_EndX, int a_EndY, int a_EndZ, BLOCKTYPE a_DstBlockType) { int BlockX = a_ChunkDesc.GetChunkX() * cChunkDef::Width; int BlockZ = a_ChunkDesc.GetChunkZ() * cChunkDef::Width; int RelStartX = Clamp(a_StartX - BlockX, 0, cChunkDef::Width); int RelStartZ = Clamp(a_StartZ - BlockZ, 0, cChunkDef::Width); int RelEndX = Clamp(a_EndX - BlockX, 0, cChunkDef::Width); int RelEndZ = Clamp(a_EndZ - BlockZ, 0, cChunkDef::Width); for (int y = a_StartY; y < a_EndY; y++) { for (int z = RelStartZ; z < RelEndZ; z++) { for (int x = RelStartX; x < RelEndX; x++) { if (cBlockInfo::CanBeTerraformed(a_ChunkDesc.GetBlockType(x, y, z))) { a_ChunkDesc.SetBlockType(x, y, z, a_DstBlockType); } } // for x } // for z } // for z } /** Fills the specified area of blocks in the chunk with a random pattern of the specified blocktypes, if they are one of the overwritten block types. The coords are absolute, start coords are inclusive, end coords are exclusive. The first blocktype uses 75% chance, the second 25% chance. */ void ReplaceCuboidRandom(cChunkDesc & a_ChunkDesc, int a_StartX, int a_StartY, int a_StartZ, int a_EndX, int a_EndY, int a_EndZ, BLOCKTYPE a_DstBlockType1, BLOCKTYPE a_DstBlockType2) { int BlockX = a_ChunkDesc.GetChunkX() * cChunkDef::Width; int BlockZ = a_ChunkDesc.GetChunkZ() * cChunkDef::Width; int RelStartX = Clamp(a_StartX - BlockX, 0, cChunkDef::Width - 1); int RelStartZ = Clamp(a_StartZ - BlockZ, 0, cChunkDef::Width - 1); int RelEndX = Clamp(a_EndX - BlockX, 0, cChunkDef::Width); int RelEndZ = Clamp(a_EndZ - BlockZ, 0, cChunkDef::Width); auto & rnd = GetRandomProvider(); for (int y = a_StartY; y < a_EndY; y++) { for (int z = RelStartZ; z < RelEndZ; z++) { for (int x = RelStartX; x < RelEndX; x++) { if (cBlockInfo::CanBeTerraformed(a_ChunkDesc.GetBlockType(x, y, z))) { BLOCKTYPE BlockType = rnd.RandBool(0.75) ? a_DstBlockType1 : a_DstBlockType2; a_ChunkDesc.SetBlockType(x, y, z, BlockType); } } // for x } // for z } // for z } /** Tries to place a chest at the specified (absolute) coords. Does nothing if the coords are outside the chunk. */ void TryPlaceChest(cChunkDesc & a_ChunkDesc, const Vector3i & a_Chest) { int RelX = a_Chest.x - a_ChunkDesc.GetChunkX() * cChunkDef::Width; int RelZ = a_Chest.z - a_ChunkDesc.GetChunkZ() * cChunkDef::Width; if ( (RelX < 0) || (RelX >= cChunkDef::Width) || // The X coord is not in this chunk (RelZ < 0) || (RelZ >= cChunkDef::Width) // The Z coord is not in this chunk ) { return; } a_ChunkDesc.SetBlockTypeMeta(RelX, m_FloorHeight + 1, RelZ, E_BLOCK_CHEST, static_cast(a_Chest.y)); // Fill the chest with random loot static const cLootProbab LootProbab[] = { // Item, MinAmount, MaxAmount, Weight { cItem(E_ITEM_GOLDEN_APPLE), 1, 1, 1 }, { cItem(E_ITEM_DIAMOND_HORSE_ARMOR), 1, 1, 1 }, { cItem(E_ITEM_GOLD_HORSE_ARMOR), 1, 1, 2 }, { cItem(E_ITEM_GOLD), 1, 4, 2 }, { cItem(E_ITEM_13_DISC), 1, 1, 4 }, { cItem(E_ITEM_CAT_DISC), 1, 1, 4 }, { cItem(E_ITEM_IRON_HORSE_ARMOR), 1, 1, 5 }, { cItem(E_ITEM_IRON), 1, 4, 10 }, { cItem(E_ITEM_WHEAT), 1, 4, 10 }, { cItem(E_ITEM_GUNPOWDER), 1, 4, 10 }, { cItem(E_ITEM_STRING), 1, 4, 10 }, { cItem(E_ITEM_REDSTONE_DUST), 1, 4, 10 }, { cItem(E_ITEM_COAL), 1, 4, 10 }, { cItem(E_ITEM_BONE), 1, 4, 10 }, { cItem(E_ITEM_ROTTEN_FLESH), 1, 4, 10 }, { cItem(E_ITEM_SADDLE), 1, 1, 10 }, { cItem(E_ITEM_BUCKET), 1, 1, 10 }, { cItem(E_ITEM_BREAD), 1, 1, 10 }, { cItem(E_ITEM_NAME_TAG), 1, 1, 10 }, { cItem(E_ITEM_BEETROOT_SEEDS), 2, 4, 10 }, { cItem(E_ITEM_MELON_SEEDS), 2, 4, 10 }, { cItem(E_ITEM_PUMPKIN_SEEDS), 2, 4, 10 }, } ; cChestEntity * ChestEntity = static_cast(a_ChunkDesc.GetBlockEntity(RelX, m_FloorHeight + 1, RelZ)); ASSERT((ChestEntity != nullptr) && (ChestEntity->GetBlockType() == E_BLOCK_CHEST)); cNoise Noise(a_ChunkDesc.GetChunkX() ^ a_ChunkDesc.GetChunkZ()); int NumSlots = 3 + ((Noise.IntNoise3DInt(a_Chest.x, a_Chest.y, a_Chest.z) / 11) % 4); int Seed = Noise.IntNoise2DInt(RelX, RelZ); ChestEntity->GetContents().GenerateRandomLootWithBooks(LootProbab, ARRAYCOUNT(LootProbab), NumSlots, Seed); } // cGridStructGen::cStructure override: virtual void DrawIntoChunk(cChunkDesc & a_ChunkDesc) override { if ( (m_EndX < a_ChunkDesc.GetChunkX() * cChunkDef::Width) || (m_StartX >= a_ChunkDesc.GetChunkX() * cChunkDef::Width + cChunkDef::Width) || (m_EndZ < a_ChunkDesc.GetChunkZ() * cChunkDef::Width) || (m_StartZ >= a_ChunkDesc.GetChunkZ() * cChunkDef::Width + cChunkDef::Width) ) { // The chunk is not intersecting the room at all, bail out return; } int b = m_FloorHeight + 1; // Bottom int t = m_FloorHeight + 1 + ROOM_HEIGHT; // Top ReplaceCuboidRandom(a_ChunkDesc, m_StartX, m_FloorHeight, m_StartZ, m_EndX + 1, b, m_EndZ + 1, E_BLOCK_MOSSY_COBBLESTONE, E_BLOCK_COBBLESTONE); // Floor ReplaceCuboid(a_ChunkDesc, m_StartX + 1, b, m_StartZ + 1, m_EndX, t, m_EndZ, E_BLOCK_AIR); // Insides // Walls: ReplaceCuboid(a_ChunkDesc, m_StartX, b, m_StartZ, m_StartX + 1, t, m_EndZ, E_BLOCK_COBBLESTONE); // XM wall ReplaceCuboid(a_ChunkDesc, m_EndX, b, m_StartZ, m_EndX + 1, t, m_EndZ, E_BLOCK_COBBLESTONE); // XP wall ReplaceCuboid(a_ChunkDesc, m_StartX, b, m_StartZ, m_EndX + 1, t, m_StartZ + 1, E_BLOCK_COBBLESTONE); // ZM wall ReplaceCuboid(a_ChunkDesc, m_StartX, b, m_EndZ, m_EndX + 1, t, m_EndZ + 1, E_BLOCK_COBBLESTONE); // ZP wall // Place chests: TryPlaceChest(a_ChunkDesc, m_Chest1); TryPlaceChest(a_ChunkDesc, m_Chest2); // Place the spawner: int CenterX = (m_StartX + m_EndX) / 2 - a_ChunkDesc.GetChunkX() * cChunkDef::Width; int CenterZ = (m_StartZ + m_EndZ) / 2 - a_ChunkDesc.GetChunkZ() * cChunkDef::Width; if ( (CenterX >= 0) && (CenterX < cChunkDef::Width) && (CenterZ >= 0) && (CenterZ < cChunkDef::Width) ) { a_ChunkDesc.SetBlockTypeMeta(CenterX, b, CenterZ, E_BLOCK_MOB_SPAWNER, 0); cMobSpawnerEntity * MobSpawner = static_cast(a_ChunkDesc.GetBlockEntity(CenterX, b, CenterZ)); ASSERT((MobSpawner != nullptr) && (MobSpawner->GetBlockType() == E_BLOCK_MOB_SPAWNER)); MobSpawner->SetEntity(m_MonsterType); } } } ; //////////////////////////////////////////////////////////////////////////////// // cDungeonRoomsFinisher: cDungeonRoomsFinisher::cDungeonRoomsFinisher(cTerrainShapeGen & a_ShapeGen, int a_Seed, int a_GridSize, int a_MaxSize, int a_MinSize, const AString & a_HeightDistrib) : Super(a_Seed + 100, a_GridSize, a_GridSize, a_GridSize, a_GridSize, a_MaxSize, a_MaxSize, 1024), m_ShapeGen(a_ShapeGen), m_MaxHalfSize((a_MaxSize + 1) / 2), m_MinHalfSize((a_MinSize + 1) / 2), m_HeightProbability(cChunkDef::Height) { // Initialize the height probability distribution: m_HeightProbability.SetDefString(a_HeightDistrib); // Normalize the min and max size: if (m_MinHalfSize > m_MaxHalfSize) { std::swap(m_MinHalfSize, m_MaxHalfSize); } } cDungeonRoomsFinisher::cStructurePtr cDungeonRoomsFinisher::CreateStructure(int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ) { // Select a random room size in each direction: int rnd = m_Noise.IntNoise2DInt(a_OriginX, a_OriginZ) / 7; int HalfSizeX = m_MinHalfSize + (rnd % (m_MaxHalfSize - m_MinHalfSize + 1)); rnd = rnd / 32; int HalfSizeZ = m_MinHalfSize + (rnd % (m_MaxHalfSize - m_MinHalfSize + 1)); rnd = rnd / 32; // Select a random floor height for the room, based on the height generator: int ChunkX, ChunkZ; int RelX = a_OriginX, RelY = 0, RelZ = a_OriginZ; cChunkDef::AbsoluteToRelative(RelX, RelY, RelZ, ChunkX, ChunkZ); cChunkDesc::Shape shape; m_ShapeGen.GenShape({ChunkX, ChunkZ}, shape); int height = 0; int idx = RelX * 256 + RelZ * 16 * 256; for (int y = 6; y < cChunkDef::Height; y++) { if (shape[idx + y] != 0) { continue; } height = Clamp(m_HeightProbability.MapValue(rnd % m_HeightProbability.GetSum()), 10, y - 5); } // Create the dungeon room descriptor: return cStructurePtr(new cDungeonRoom(a_GridX, a_GridZ, a_OriginX, a_OriginZ, HalfSizeX, HalfSizeZ, height, m_Noise)); } ================================================ FILE: src/Generating/DungeonRoomsFinisher.h ================================================ // DungeonRoomsFinisher.h // Declares the cDungeonRoomsFinisher class representing the finisher that generates dungeon rooms #pragma once #include "GridStructGen.h" #include "../ProbabDistrib.h" class cDungeonRoomsFinisher: public cGridStructGen { using Super = cGridStructGen; public: /** Creates a new dungeon room finisher. a_ShapeGen is the underlying terrain shape generator, so that the rooms can always be placed under the terrain. a_MaxSize and a_MinSize are the maximum and minimum sizes of the room's internal (air) area, in blocks across. a_HeightDistrib is the string defining the height distribution for the rooms (cProbabDistrib format). */ cDungeonRoomsFinisher(cTerrainShapeGen & a_ShapeGen, int a_Seed, int a_GridSize, int a_MaxSize, int a_MinSize, const AString & a_HeightDistrib); protected: /** The shape gen that is used for limiting the rooms' Y coords */ cTerrainShapeGen & m_ShapeGen; /** Maximum half-size (from center to wall) of the dungeon room's inner (air) area. Default is 3 (vanilla). */ int m_MaxHalfSize; /** Minimum half-size (from center to wall) of the dungeon room's inner (air) area. Default is 2 (vanilla). */ int m_MinHalfSize; /** The height probability distribution to make the spawners more common in layers 10 - 40, less common outside this range. */ cProbabDistrib m_HeightProbability; // cGridStructGen overrides: virtual cStructurePtr CreateStructure(int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ) override; } ; ================================================ FILE: src/Generating/EndGen.cpp ================================================ // EndGen.cpp // Implements the cEndGen class representing the generator for the End, both as a HeightGen and CompositionGen #include "Globals.h" #include "EndGen.h" #include "../IniFile.h" #include "../LinearUpscale.h" enum { // Interpolation cell size: INTERPOL_X = 4, INTERPOL_Y = 4, INTERPOL_Z = 4, // Size of chunk data, downscaled before interpolation: DIM_X = 16 / INTERPOL_X + 1, DIM_Y = 256 / INTERPOL_Y + 1, DIM_Z = 16 / INTERPOL_Z + 1, }; //////////////////////////////////////////////////////////////////////////////// // cEndGen: cEndGen::cEndGen(int a_Seed) : m_Seed(a_Seed), m_Perlin(m_Seed), m_MainIslandSize(200), m_IslandThickness(32), m_IslandYOffset(30), m_MainIslandFrequencyX(100), m_MainIslandFrequencyY(80), m_MainIslandFrequencyZ(100), m_MainIslandMinThreshold(0.2f), m_SmallIslandFrequencyX(50), m_SmallIslandFrequencyY(80), m_SmallIslandFrequencyZ(50), m_SmallIslandMinThreshold(-0.5f), m_LastChunkCoords(0x7fffffff, 0x7fffffff) // Use dummy coords that won't ever be used by real chunks { m_Perlin.AddOctave(1, 1); m_Perlin.AddOctave(2, 0.5); m_Perlin.AddOctave(4, 0.25); } void cEndGen::InitializeShapeGen(cIniFile & a_IniFile) { m_MainIslandSize = a_IniFile.GetValueSetI("Generator", "EndGenMainIslandSize", m_MainIslandSize); m_IslandThickness = a_IniFile.GetValueSetI("Generator", "EndGenIslandThickness", m_IslandThickness); m_IslandYOffset = a_IniFile.GetValueSetI("Generator", "EndGenIslandYOffset", m_IslandYOffset); m_MainIslandFrequencyX = static_cast(a_IniFile.GetValueSetF("Generator", "EndGenMainFrequencyX", m_MainIslandFrequencyX)); m_MainIslandFrequencyY = static_cast(a_IniFile.GetValueSetF("Generator", "EndGenMainFrequencyY", m_MainIslandFrequencyY)); m_MainIslandFrequencyZ = static_cast(a_IniFile.GetValueSetF("Generator", "EndGenMainFrequencyZ", m_MainIslandFrequencyZ)); m_MainIslandMinThreshold = static_cast(a_IniFile.GetValueSetF("Generator", "EndGenMainMinThreshold", m_MainIslandMinThreshold)); m_SmallIslandFrequencyX = static_cast(a_IniFile.GetValueSetF("Generator", "EndGenSmallFrequencyX", m_SmallIslandFrequencyX)); m_SmallIslandFrequencyY = static_cast(a_IniFile.GetValueSetF("Generator", "EndGenSmallFrequencyY", m_SmallIslandFrequencyY)); m_SmallIslandFrequencyZ = static_cast(a_IniFile.GetValueSetF("Generator", "EndGenSmallFrequencyZ", m_SmallIslandFrequencyZ)); m_SmallIslandMinThreshold = static_cast(a_IniFile.GetValueSetF("Generator", "EndGenSmallMinThreshold", m_SmallIslandMinThreshold)); } void cEndGen::PrepareState(cChunkCoords a_ChunkCoords) { if (m_LastChunkCoords == a_ChunkCoords) { return; } m_LastChunkCoords = a_ChunkCoords; GenerateNoiseArray(); } void cEndGen::GenerateNoiseArray(void) { NOISE_DATATYPE NoiseData[DIM_X * DIM_Y * DIM_Z]; // [x + DIM_X * z + DIM_X * DIM_Z * y] NOISE_DATATYPE Workspace[DIM_X * DIM_Y * DIM_Z]; // [x + DIM_X * z + DIM_X * DIM_Z * y] // Choose the frequency to use depending on the distance from spawn. auto distanceFromSpawn = cChunkDef::RelativeToAbsolute({ cChunkDef::Width / 2, 0, cChunkDef::Width / 2 }, m_LastChunkCoords).Length(); auto frequencyX = distanceFromSpawn > m_MainIslandSize * 2 ? m_SmallIslandFrequencyX : m_MainIslandFrequencyX; auto frequencyY = distanceFromSpawn > m_MainIslandSize * 2 ? m_SmallIslandFrequencyY : m_MainIslandFrequencyY; auto frequencyZ = distanceFromSpawn > m_MainIslandSize * 2 ? m_SmallIslandFrequencyZ : m_MainIslandFrequencyZ; // Generate the downscaled noise: auto StartX = static_cast(m_LastChunkCoords.m_ChunkX * cChunkDef::Width) / frequencyX; auto EndX = static_cast((m_LastChunkCoords.m_ChunkX + 1) * cChunkDef::Width) / frequencyX; auto StartZ = static_cast(m_LastChunkCoords.m_ChunkZ * cChunkDef::Width) / frequencyZ; auto EndZ = static_cast((m_LastChunkCoords.m_ChunkZ + 1) * cChunkDef::Width) / frequencyZ; auto StartY = 0.0f; auto EndY = static_cast(cChunkDef::Height) / frequencyY; m_Perlin.Generate3D(NoiseData, DIM_X, DIM_Z, DIM_Y, StartX, EndX, StartZ, EndZ, StartY, EndY, Workspace); // Add distance: for (int y = 0; y < DIM_Y; y++) { auto ValY = static_cast(2 * INTERPOL_Y * y - m_IslandThickness) / m_IslandThickness; ValY = static_cast(std::pow(ValY, 6)); for (int z = 0; z < DIM_Z; z++) { for (int x = 0; x < DIM_X; x++) { NoiseData[x + DIM_X * z + DIM_X * DIM_Z * y] += ValY; } // for x } // for z } // for y // Upscale into real chunk size: LinearUpscale3DArray(NoiseData, DIM_X, DIM_Z, DIM_Y, m_NoiseArray, INTERPOL_X, INTERPOL_Z, INTERPOL_Y); } void cEndGen::GenShape(cChunkCoords a_ChunkCoords, cChunkDesc::Shape & a_Shape) { PrepareState(a_ChunkCoords); int MaxY = std::min(static_cast(1.75 * m_IslandThickness + m_IslandYOffset), cChunkDef::Height - 1); // Choose which threshold to use depending on the distance from spawn. double chunkDistanceFromSpawn = cChunkDef::RelativeToAbsolute({ cChunkDef::Width / 2, 0, cChunkDef::Width / 2 }, a_ChunkCoords).Length(); double minThreshold = chunkDistanceFromSpawn > m_MainIslandSize * 2 ? m_SmallIslandMinThreshold : m_MainIslandMinThreshold; for (int z = 0; z < cChunkDef::Width; z++) { for (int x = 0; x < cChunkDef::Width; x++) { // Calculate the required treshold based on the distance from spawn. // This way a void can be generated between the main island and the other islands. double distanceFromSpawn = cChunkDef::RelativeToAbsolute({ x, 0, z }, a_ChunkCoords).Length(); double pow = std::pow((distanceFromSpawn - m_MainIslandSize) / m_MainIslandSize / 2, 3); double mult = 3 * ((distanceFromSpawn - m_MainIslandSize) / m_MainIslandSize); double threshold = std::min(pow - mult, minThreshold); for (int y = 0; y < m_IslandYOffset; y++) { cChunkDesc::SetShapeIsSolidAt(a_Shape, x, y, z, false); } for (int y = m_IslandYOffset; y < MaxY; y++) { cChunkDesc::SetShapeIsSolidAt(a_Shape, x, y, z, m_NoiseArray[(y - m_IslandYOffset) * 17 * 17 + z * 17 + x] <= threshold); } for (int y = MaxY; y < cChunkDef::Height; y++) { cChunkDesc::SetShapeIsSolidAt(a_Shape, x, y, z, false); } } // for x } // for z } void cEndGen::ComposeTerrain(cChunkDesc & a_ChunkDesc, const cChunkDesc::Shape & a_Shape) { a_ChunkDesc.FillBlocks(E_BLOCK_AIR, 0); for (int z = 0; z < cChunkDef::Width; z++) { for (int x = 0; x < cChunkDef::Width; x++) { for (int y = 0; y < cChunkDef::Height; y++) { if (cChunkDesc::GetShapeIsSolidAt(a_Shape, x, y, z)) { a_ChunkDesc.SetBlockType(x, y, z, E_BLOCK_END_STONE); } } // for y } // for x } // for z } ================================================ FILE: src/Generating/EndGen.h ================================================ // EndGen.h // Declares the cEndGen class representing the generator for the End, both as a HeightGen and CompositionGen #pragma once #include "ComposableGenerator.h" #include "../Noise/Noise.h" class cEndGen : public cTerrainShapeGen, public cTerrainCompositionGen { public: cEndGen(int a_Seed); protected: /** Seed for the noise */ int m_Seed; /** The Perlin noise used for generating */ cPerlinNoise m_Perlin; // XYZ size of the "island", in blocks: int m_MainIslandSize; int m_IslandThickness; int m_IslandYOffset; // XYZ Frequencies of the noise functions: NOISE_DATATYPE m_MainIslandFrequencyX; NOISE_DATATYPE m_MainIslandFrequencyY; NOISE_DATATYPE m_MainIslandFrequencyZ; NOISE_DATATYPE m_MainIslandMinThreshold; // XYZ Frequencies of the noise functions on the smaller islands: NOISE_DATATYPE m_SmallIslandFrequencyX; NOISE_DATATYPE m_SmallIslandFrequencyY; NOISE_DATATYPE m_SmallIslandFrequencyZ; NOISE_DATATYPE m_SmallIslandMinThreshold; // Noise array for the last chunk (in the noise range) cChunkCoords m_LastChunkCoords; NOISE_DATATYPE m_NoiseArray[17 * 17 * 257]; // x + 17 * z + 17 * 17 * y /** Unless the LastChunk coords are equal to coords given, prepares the internal state (noise array) */ void PrepareState(cChunkCoords a_ChunkCoords); /** Generates the m_NoiseArray array for the current chunk */ void GenerateNoiseArray(void); // cTerrainShapeGen overrides: virtual void GenShape(cChunkCoords a_ChunkCoords, cChunkDesc::Shape & a_Shape) override; virtual void InitializeShapeGen(cIniFile & a_IniFile) override; // cTerrainCompositionGen overrides: virtual void ComposeTerrain(cChunkDesc & a_ChunkDesc, const cChunkDesc::Shape & a_Shape) override; } ; ================================================ FILE: src/Generating/EnderDragonFightStructuresGen.cpp ================================================ #include "Globals.h" #include "EnderDragonFightStructuresGen.h" #include "../Chunk.h" #include "../Entities/EnderCrystal.h" #include "../WorldStorage/SchematicFileSerializer.h" const std::array cEnderDragonFightStructuresGen::m_CagePos = { { // First layer {-2, -1, -2}, {-2, -1, -1}, {-2, -1, 0}, {-2, -1, 1}, {-2, -1, 2}, {2, -1, -2}, {2, -1, -1}, {2, -1, 0}, {2, -1, 1}, {2, -1, 2}, {-1, -1, -2}, {0, -1, -2}, {1, -1, -2}, {-1, -1, 2}, {0, -1, 2}, {1, -1, 2}, // Second layer {-2, 0, -2}, {-2, 0, -1}, {-2, 0, 0}, {-2, 0, 1}, {-2, 0, 2}, {2, 0, -2}, {2, 0, -1}, {2, 0, 0}, {2, 0, 1}, {2, 0, 2}, {-1, 0, -2}, {0, 0, -2}, {1, 0, -2}, {-1, 0, 2}, {0, 0, 2}, {1, 0, 2}, // Third layer {-2, 1, -2}, {-2, 1, -1}, {-2, 1, 0}, {-2, 1, 1}, {-2, 1, 2}, {2, 1, -2}, {2, 1, -1}, {2, 1, 0}, {2, 1, 1}, {2, 1, 2}, {-1, 1, -2}, {0, 1, -2}, {1, 1, -2}, {-1, 1, 2}, {0, 1, 2}, {1, 1, 2}, } }; const std::array cEnderDragonFightStructuresGen::m_CageAir = { { // First layer {-1, -1, -1}, {0, -1, -1}, {1, -1, -1}, {-1, -1, 1}, {0, -1, 1}, {1, -1, 1}, {-1, -1, 0}, {1, -1, 0}, // Second layer {-1, 0, -1}, {0, 0, -1}, {1, 0, -1}, {-1, 0, 1}, {0, 0, 1}, {1, 0, 1}, {-1, 0, 0}, {1, 0, 0}, {0, 0, 0}, // Third layer {-1, 1, -1}, {0, 1, -1}, {1, 1, -1}, {-1, 1, 1}, {0, 1, 1}, {1, 1, 1}, {-1, 1, 0}, {1, 1, 0}, {0, 1, 0}, } }; cEnderDragonFightStructuresGen::cEnderDragonFightStructuresGen(int a_Seed) : m_Noise(a_Seed) { } void cEnderDragonFightStructuresGen::Init(const AString & a_TowerProperties, int a_Radius) { const auto ChunkWidth = cChunkDef::Width; // Loads the fountain schematic if (!cFile::IsFile(AString("Prefabs") + cFile::GetPathSeparator() + "SinglePieceStructures" + cFile::GetPathSeparator() + "EndFountain.schematic")) { LOGWARNING("EnderDragonFightStructuresGen is missing its end fountain prefab, please update your Cuberite server files! There will be no end fountain!"); } else { cSchematicFileSerializer::LoadFromSchematicFile(m_Fountain, AString("Prefabs") + cFile::GetPathSeparator() + "SinglePieceStructures" + cFile::GetPathSeparator() + "EndFountain.schematic"); } // Reads the given tower properties const auto TowerPropertiesVector = StringSplitAndTrim(a_TowerProperties, ";"); std::vector TowerProperties; for (const auto & TowerProperty : TowerPropertiesVector) { const auto TowerPropertyVector = StringSplitAndTrim(TowerProperty, "|"); if (TowerPropertyVector.size() != 3) { LOGWARNING("Got unknown parameters on generating obsidian pillars: %s, Please use \"Height|Radius|HasCage\"; ...", TowerProperty); continue; } int Height = std::min(std::stoi(TowerPropertyVector[0]), cChunkDef::Height - 2); // The highest block placed is two blocks above the given height (the cage above some towers) int Radius = std::stoi(TowerPropertyVector[1]); bool HasCage; if (NoCaseCompare(TowerPropertyVector[2], "true") == 0) { HasCage = true; } else if (NoCaseCompare(TowerPropertyVector[2], "false") == 0) { HasCage = false; } else { LOGWARNING("Got unknown value for boolean of the tower: %s should have a cage! %s. Tower will not be generated!", TowerProperty, TowerPropertyVector[2]); continue; } TowerProperties.push_back({Vector3d(), Height, Radius, HasCage}); } // A random angle in radian double Angle = m_Noise.IntNoise1D(m_Noise.GetSeed()) * M_PI + M_PI; // Shuffles the order of the towers std::shuffle(TowerProperties.begin(), TowerProperties.end(), std::default_random_engine(static_cast(m_Noise.GetSeed()))); // Generate Positions in a circle for (size_t I = 0; I < TowerProperties.size(); I++) { auto TowerPos = Vector3i(FloorC(a_Radius * cos(Angle)), 0, FloorC(a_Radius * sin(Angle))); TowerProperties[I].m_Pos = TowerPos; // Check all crossed chunks for (int X = -TowerProperties[I].m_Radius - ChunkWidth; X <= TowerProperties[I].m_Radius + ChunkWidth; X+=std::min(TowerProperties[I].m_Radius, ChunkWidth)) { for (int Z = -TowerProperties[I].m_Radius - ChunkWidth; Z <= TowerProperties[I].m_Radius + ChunkWidth; Z+=std::min(TowerProperties[I].m_Radius, ChunkWidth)) { auto Chunk = cChunkDef::BlockToChunk({TowerPos.x + X, 0, TowerPos.z + Z}); // Update limits m_MinX = std::min(Chunk.m_ChunkX, m_MinX); m_MinZ = std::min(Chunk.m_ChunkZ, m_MinZ); m_MaxX = std::max(Chunk.m_ChunkX, m_MaxX); m_MaxZ = std::max(Chunk.m_ChunkZ, m_MaxZ); // If the tower is not in chunk put it in bool ShouldPlace = true; for (const auto & Property : m_TowerPos[Chunk]) { ShouldPlace &= !(TowerPos == Property.m_Pos); } if (ShouldPlace) { m_TowerPos[Chunk].emplace_back(TowerProperties[I]); } } } // Generate angle of next tower Angle = fmod(Angle + (2.0 * M_PI / static_cast(TowerProperties.size())), 2.0 * M_PI); } } void cEnderDragonFightStructuresGen::GenFinish(cChunkDesc &a_ChunkDesc) { auto Coords = a_ChunkDesc.GetChunkCoords(); // If not in the chunks to write if ((Coords.m_ChunkX > m_MaxX) || (Coords.m_ChunkX < m_MinX) || (Coords.m_ChunkZ > m_MaxZ) || (Coords.m_ChunkZ < m_MinZ)) { return; } // Places the exit portal if (Coords == cChunkCoords({0, 0})) { /* auto EnderDragon = std::make_unique(); EnderDragon->SetPosition({0.0, static_cast(a_ChunkDesc.GetHeight(0, 0) + 20), 0.0}); // Spawns the dragon 20 blocks above the terrain at (0, 0) a_ChunkDesc.GetEntities().emplace_back(std::move(EnderDragon)); */ // Todo: 25.10.20 - Add the ender dragon spawning when the dragon behaves properly - 12xx12 a_ChunkDesc.WriteBlockArea(m_Fountain, static_cast(FloorC(-m_Fountain.GetSizeX() / 2)), 62, static_cast(FloorC(-m_Fountain.GetSizeX() / 2)), cBlockArea::msSpongePrint ); } else if (Coords == cChunkCoords({-1, 0})) { a_ChunkDesc.WriteBlockArea(m_Fountain, cChunkDef::Width - static_cast(FloorC(m_Fountain.GetSizeX() / 2)), 62, static_cast(FloorC(-m_Fountain.GetSizeZ() / 2)), cBlockArea::msSpongePrint ); } else if (Coords == cChunkCoords({0, -1})) { a_ChunkDesc.WriteBlockArea(m_Fountain, static_cast(FloorC(-m_Fountain.GetSizeX() / 2)), 62, cChunkDef::Width - static_cast(FloorC(m_Fountain.GetSizeZ() / 2)), cBlockArea::msSpongePrint); } else if (Coords == cChunkCoords({-1, -1})) { a_ChunkDesc.WriteBlockArea(m_Fountain, cChunkDef::Width - static_cast(FloorC(m_Fountain.GetSizeX() / 2)), 62, cChunkDef::Width - static_cast(FloorC(m_Fountain.GetSizeZ() / 2)), cBlockArea::msSpongePrint); } auto It = m_TowerPos.find(Coords); if (It == m_TowerPos.end()) { return; } for (const auto & Property : It->second) { PlaceTower(a_ChunkDesc, Property); } } void cEnderDragonFightStructuresGen::PlaceTower(cChunkDesc &a_ChunkDesc, const sTowerProperties & a_Properties) { auto Pos = cChunkDef::AbsoluteToRelative(a_Properties.m_Pos, a_ChunkDesc.GetChunkCoords()); // Place obsidian pillar for (int X = -a_Properties.m_Radius; X < a_Properties.m_Radius; X++) { for (int Z = -a_Properties.m_Radius; Z < a_Properties.m_Radius; Z++) { Vector3i NewPos = {Pos.x + X, 1, Pos.z + Z}; if (cChunkDef::IsValidRelPos(NewPos)) { // The 3 was achieved by trial and error till the shape matched the notchian implementation if ((NewPos - Vector3i(Pos.x, 1, Pos.z)).SqrLength() < a_Properties.m_Radius * a_Properties.m_Radius - 3) { for (int Y = 0; Y <= a_Properties.m_Height - 2; Y++) { a_ChunkDesc.SetBlockType(NewPos.x, Y, NewPos.z, E_BLOCK_OBSIDIAN); } } } } } // Spawn the iron bars if there are some if (a_Properties.m_HasCage) { // Place walls for (const auto & Offset : m_CagePos) { if (cChunkDef::IsValidRelPos(Vector3d(Pos.x, a_Properties.m_Height, Pos.z) + Offset)) { a_ChunkDesc.SetBlockType(Pos.x + Offset.x, a_Properties.m_Height + Offset.y, Pos.z + Offset.z, E_BLOCK_IRON_BARS); } } // Remove any block that may generate inside the cage for (const auto & Offset : m_CageAir) { if (cChunkDef::IsValidRelPos(Pos + Offset)) { a_ChunkDesc.SetBlockType(Pos.x + Offset.x, a_Properties.m_Height + Offset.y, Pos.z + Offset.z, E_BLOCK_AIR); } } // Place roof for (int X = -2; X <= 2; ++X) { for (int Z = -2; Z <= 2; ++Z) { if (cChunkDef::IsValidRelPos({Pos.x + X, 1, Pos.z + Z})) { a_ChunkDesc.SetBlockType(Pos.x + X, a_Properties.m_Height + 2, Pos.z + Z, E_BLOCK_IRON_BARS); } } } } // Place the top decoration if the origin is in this chunk if (cChunkDef::IsValidRelPos(Pos)) { // Spawn the bedrock a_ChunkDesc.SetBlockType(Pos.x, a_Properties.m_Height - 1, Pos.z, E_BLOCK_BEDROCK); // Spawn the fire a_ChunkDesc.SetBlockType(Pos.x, a_Properties.m_Height, Pos.z, E_BLOCK_FIRE); // Spawn the ender crystal of the origin position is in this chunk auto EnderCrystal = std::make_unique(Vector3d(0.5, a_Properties.m_Height, 0.5) + a_Properties.m_Pos, true); a_ChunkDesc.GetEntities().emplace_back(std::move(EnderCrystal)); } } ================================================ FILE: src/Generating/EnderDragonFightStructuresGen.h ================================================ #pragma once /* https://minecraft.wiki/w/End_spike https://minecraft.wiki/w/End_Crystal https://minecraft.wiki/w/Ender_Dragon */ #include "FinishGen.h" class cEnderDragonFightStructuresGen : public cFinishGen { public: cEnderDragonFightStructuresGen(int a_Seed); void Init(const AString & a_TowerProperties, int a_Radius); protected: struct sTowerProperties { Vector3i m_Pos; int m_Height; int m_Radius; bool m_HasCage; }; cNoise m_Noise; std::map> m_TowerPos; static const std::array m_CagePos; static const std::array m_CageAir; cBlockArea m_Fountain; int m_MinX = -1, m_MaxX = 1, m_MinZ = -1, m_MaxZ = 1; void GenFinish(cChunkDesc &a_ChunkDesc) override; void PlaceTower(cChunkDesc & a_ChunkDesc, const sTowerProperties & a_TowerProperties); }; ================================================ FILE: src/Generating/FinishGen.cpp ================================================ // FinishGen.cpp /* Implements the various finishing generators: - cFinishGenSnow - cFinishGenIce - cFinishGenSprinkleFoliage */ #include "Globals.h" #include "FinishGen.h" #include "../Simulator/FluidSimulator.h" // for cFluidSimulator::CanWashAway() #include "../Simulator/FireSimulator.h" #include "../IniFile.h" #include "../MobSpawner.h" #include "../BlockInfo.h" #define DEF_NETHER_WATER_SPRINGS "0, 1; 255, 1" #define DEF_NETHER_LAVA_SPRINGS "0, 0; 30, 0; 31, 50; 120, 50; 127, 0" #define DEF_OVERWORLD_WATER_SPRINGS "0, 0; 10, 10; 11, 75; 16, 83; 20, 83; 24, 78; 32, 62; 40, 40; 44, 15; 48, 7; 56, 2; 64, 1; 255, 0" #define DEF_OVERWORLD_LAVA_SPRINGS "0, 0; 10, 5; 11, 45; 48, 2; 64, 1; 255, 0" #define DEF_END_WATER_SPRINGS "0, 1; 255, 1" #define DEF_END_LAVA_SPRINGS "0, 1; 255, 1" #define DEF_ANIMAL_SPAWN_PERCENT 10 #define DEF_NO_ANIMALS 0 static inline bool IsWater(BLOCKTYPE a_BlockType) { return (a_BlockType == E_BLOCK_STATIONARY_WATER) || (a_BlockType == E_BLOCK_WATER); } //////////////////////////////////////////////////////////////////////////////// // cFinishGenNetherClumpFoliage: void cFinishGenNetherClumpFoliage::GenFinish(cChunkDesc & a_ChunkDesc) { int ChunkX = a_ChunkDesc.GetChunkX(); int ChunkZ = a_ChunkDesc.GetChunkZ(); int Val1 = m_Noise.IntNoise2DInt(ChunkX ^ ChunkZ, ChunkZ + ChunkX); int Val2 = m_Noise.IntNoise2DInt(ChunkZ ^ ChunkX, ChunkZ - ChunkX); int PosX = Val1 % 16; int PosZ = Val2 % 16; for (int y = 1; y < cChunkDef::Height; y++) { if (a_ChunkDesc.GetBlockType(PosX, y, PosZ) != E_BLOCK_AIR) { continue; } if (!cBlockInfo::IsSolid(a_ChunkDesc.GetBlockType(PosX, y - 1, PosZ))) // Only place on solid blocks { continue; } // Choose what block to use. NOISE_DATATYPE BlockType = m_Noise.IntNoise3D(static_cast(ChunkX), y, static_cast(ChunkZ)); if (BlockType < -0.7) { TryPlaceClump(a_ChunkDesc, PosX, y, PosZ, E_BLOCK_BROWN_MUSHROOM); } else if (BlockType < 0) { TryPlaceClump(a_ChunkDesc, PosX, y, PosZ, E_BLOCK_RED_MUSHROOM); } else if (BlockType < 0.7) { TryPlaceClump(a_ChunkDesc, PosX, y, PosZ, E_BLOCK_FIRE); } } } void cFinishGenNetherClumpFoliage::TryPlaceClump(cChunkDesc & a_ChunkDesc, int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_Block) { bool IsFireBlock = a_Block == E_BLOCK_FIRE; int MinX = a_RelX - 4; if (MinX < 0) // Check if the coordinate is outside the chunk. If it it then adjust it. { MinX = 0; } int MaxX = a_RelX + 4; if (MaxX > cChunkDef::Width) // Check if the coordinate is outside the chunk. If it it then adjust it. { MaxX = cChunkDef::Width; } int MinZ = a_RelZ - 4; if (MinZ < 0) // Check if the coordinate is outside the chunk. If it it then adjust it. { MinZ = 0; } int MaxZ = a_RelZ + 4; if (MaxZ > cChunkDef::Width) // Check if the coordinate is outside the chunk. If it it then adjust it. { MaxZ = cChunkDef::Width; } int MinY = a_RelY - 2; if (MinY < 0) // Check if the coordinate is outside the chunk. If it it then adjust it. { MinY = 0; } int MaxY = a_RelY + 2; if (MaxY > cChunkDef::Height) // Check if the coordinate is outside the chunk. If it it then adjust it. { MaxY = cChunkDef::Height; } for (int x = MinX; x < MaxX; x++) { int xx = a_ChunkDesc.GetChunkX() * cChunkDef::Width + x; for (int z = MinZ; z < MaxZ; z++) { int zz = a_ChunkDesc.GetChunkZ() * cChunkDef::Width + z; for (int y = MinY; y < MaxY; y++) { if ( ((x < 0) || (x >= cChunkDef::Width)) || ((y < 0) || (y >= cChunkDef::Height)) || ((z < 0) || (z >= cChunkDef::Width)) ) { continue; } if (a_ChunkDesc.GetBlockType(x, y, z) != E_BLOCK_AIR) // Don't replace non air blocks. { continue; } BLOCKTYPE BlockBelow = a_ChunkDesc.GetBlockType(x, y - 1, z); if (!cBlockInfo::FullyOccupiesVoxel(BlockBelow)) // Only place on solid blocks { continue; } if (IsFireBlock) // don't place fire on non-forever burning blocks. { if (!cFireSimulator::DoesBurnForever(BlockBelow)) { continue; } } NOISE_DATATYPE Val = m_Noise.IntNoise2D(xx, zz); if (Val < -0.5) { a_ChunkDesc.SetBlockType(x, y, z, a_Block); } } } } } //////////////////////////////////////////////////////////////////////////////// // cFinishGenClumpTopBlock void cFinishGenClumpTopBlock::GenFinish(cChunkDesc & a_ChunkDesc) { int ChunkX = a_ChunkDesc.GetChunkX(); int ChunkZ = a_ChunkDesc.GetChunkZ(); int NoiseVal = m_Noise.IntNoise2DInt(ChunkX, ChunkZ); EMCSBiome Biome = a_ChunkDesc.GetBiome(cChunkDef::Width / 2, cChunkDef::Width / 2); BiomeInfo info = m_FlowersPerBiome[static_cast(Biome)]; const auto & PossibleBlocks = info.m_Blocks; if (PossibleBlocks.empty()) { // No need to go any further. This biome can't generate any blocks. return; } int NumClumps = info.m_MaxNumClumpsPerChunk - info.m_MinNumClumpsPerChunk; if (NumClumps == 0) { NumClumps = 1; } NumClumps = NoiseVal % NumClumps + info.m_MinNumClumpsPerChunk; for (int i = 0; i < NumClumps; i++) { int Val1 = m_Noise.IntNoise2DInt(ChunkX * ChunkZ * i, ChunkZ + ChunkX + i); int Val2 = m_Noise.IntNoise2DInt(ChunkZ * ChunkX + i, ChunkZ - ChunkX * i); int BlockVal = m_Noise.IntNoise2DInt(Val1, Val2); int PosX = Val1 % (cChunkDef::Width - RANGE_FROM_CENTER * 2) + RANGE_FROM_CENTER; int PosZ = Val2 % (cChunkDef::Width - RANGE_FROM_CENTER * 2) + RANGE_FROM_CENTER; int TotalWeight = 0; for (const auto & Block : PossibleBlocks) { TotalWeight += Block.m_Weight; } // Prevent division by 0 TotalWeight = (TotalWeight != 0) ? TotalWeight : 1; int Weight = BlockVal % TotalWeight; for (const auto & Block : PossibleBlocks) { Weight -= Block.m_Weight; if (Weight < 0) { TryPlaceFoliageClump(a_ChunkDesc, PosX, PosZ, Block.m_BlockType, Block.m_BlockMeta, Block.m_BlockType == E_BLOCK_BIG_FLOWER); break; } } } } void cFinishGenClumpTopBlock::TryPlaceFoliageClump(cChunkDesc & a_ChunkDesc, int a_CenterX, int a_CenterZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, bool a_IsDoubleTall) { int ChunkX = a_ChunkDesc.GetChunkX(); int ChunkZ = a_ChunkDesc.GetChunkZ(); int NumBlocks = m_Noise.IntNoise2DInt(a_CenterX + ChunkX * 16, a_CenterZ + ChunkZ * 16) % (MAX_NUM_FOLIAGE - MIN_NUM_FOLIAGE) + MIN_NUM_FOLIAGE + 1; for (int i = 1; i < NumBlocks; i++) { int Rnd = m_Noise.IntNoise2DInt(ChunkX + ChunkZ + i, ChunkX - ChunkZ - i) / 59; int x = a_CenterX + (((Rnd % 59) % RANGE_FROM_CENTER * 2) - RANGE_FROM_CENTER); int z = a_CenterZ + (((Rnd / 97) % RANGE_FROM_CENTER * 2) - RANGE_FROM_CENTER); int Top = a_ChunkDesc.GetHeight(x, z); // Doesn't place if the blocks can't be placed. Checked value also depends on a_IsDoubleTall if (Top + 1 + (a_IsDoubleTall ? 1 : 0) >= cChunkDef::Height) { continue; } auto GroundBlockType = a_ChunkDesc.GetBlockType(x, Top, z); if ( (GroundBlockType == E_BLOCK_GRASS) || ( (GroundBlockType == E_BLOCK_MYCELIUM) && ((a_BlockType == E_BLOCK_RED_MUSHROOM) || (a_BlockType == E_BLOCK_BROWN_MUSHROOM)) ) ) { a_ChunkDesc.SetBlockTypeMeta(x, Top + 1, z, a_BlockType, a_BlockMeta); if (a_IsDoubleTall) { a_ChunkDesc.SetBlockTypeMeta(x, Top + 2, z, E_BLOCK_BIG_FLOWER, E_META_BIG_FLOWER_TOP); a_ChunkDesc.SetHeight(x, z, static_cast(Top + 2)); } else { a_ChunkDesc.SetHeight(x, z, static_cast(Top + 1)); } } } } void cFinishGenClumpTopBlock::ParseConfigurationString(const AString & a_RawClumpInfo, std::vector & a_Output) { // Initialize the vector for all biomes. for (int i = static_cast(a_Output.size()); i <= static_cast(biMaxVariantBiome); i++) { // Push empty BiomeInfo structure to be later directly accessed by index: a_Output.emplace_back(); } AStringVector ClumpInfo = StringSplitAndTrim(a_RawClumpInfo, "="); // Information about a clump is divided in 2 parts. The biomes they can be in and the blocks that can be placed. if (ClumpInfo.size() != 2) { LOGWARNING("OverworldClumpFoliage: Data missing for \"%s\". Please divide biome and blocks with a semi colon", a_RawClumpInfo.c_str()); return; } AStringVector Biomes = StringSplitAndTrim(ClumpInfo[0], ";"); AStringVector Blocks = StringSplitAndTrim(ClumpInfo[1], ";"); for (const auto & RawBiomeInfo : Biomes) { const AStringVector BiomeInfo = StringSplitAndTrim(RawBiomeInfo, ","); const AString & BiomeName = BiomeInfo[0]; const EMCSBiome Biome = StringToBiome(BiomeName); if (Biome == biInvalidBiome) { LOGWARNING("Biome \"%s\" is invalid.", BiomeName.c_str()); continue; } // The index of Biome in the output vector. const size_t BiomeIndex = static_cast(Biome); if (BiomeInfo.size() == 2) { // Only the minimum amount of clumps per chunk is changed. int MinNumClump = 1; if (!StringToInteger(BiomeInfo[1], MinNumClump)) { LOGWARNING("OverworldClumpFoliage: Invalid data in \"%s\". Second parameter is either not existing or a number", RawBiomeInfo.c_str()); continue; } a_Output[BiomeIndex].m_MinNumClumpsPerChunk = MinNumClump; // In case the minimum number is higher than the current maximum value we change the max to the minimum value. a_Output[BiomeIndex].m_MaxNumClumpsPerChunk = std::max(MinNumClump, a_Output[BiomeIndex].m_MaxNumClumpsPerChunk); } else if (BiomeInfo.size() == 3) { // Both the minimum and maximum amount of clumps per chunk is changed. int MinNumClumps = 0, MaxNumClumps = 1; if (!StringToInteger(BiomeInfo[1], MinNumClumps) || !StringToInteger(BiomeInfo[2], MaxNumClumps)) { LOGWARNING("Invalid data in \"%s\". Second parameter is either not existing or a number", RawBiomeInfo.c_str()); continue; } a_Output[BiomeIndex].m_MaxNumClumpsPerChunk = MaxNumClumps + 1; a_Output[BiomeIndex].m_MinNumClumpsPerChunk = MinNumClumps; } // TODO: Make the weight configurable. for (const auto & BlockName : Blocks) { cItem Block; if (!StringToItem(BlockName, Block) || !IsValidBlock(Block.m_ItemType)) { LOGWARNING("Block \"%s\" is invalid", BlockName.c_str()); continue; } // Construct the FoliageInfo: a_Output[BiomeIndex].m_Blocks.emplace_back( static_cast(Block.m_ItemType), static_cast(Block.m_ItemDamage), 100 ); } } } std::vector cFinishGenClumpTopBlock::ParseIniFile(cIniFile & a_IniFile, const AString & a_ClumpPrefix) { std::vector Foliage; int NumGeneratorValues = a_IniFile.GetNumValues("Generator"); int GeneratorKeyId = a_IniFile.FindKey("Generator"); for (int i = 0; i < NumGeneratorValues; i++) { AString ValueName = a_IniFile.GetValueName("Generator", i); if (ValueName.substr(0, a_ClumpPrefix.size()) == a_ClumpPrefix) { AString RawClump = a_IniFile.GetValue(GeneratorKeyId, i); cFinishGenClumpTopBlock::ParseConfigurationString(RawClump, Foliage); } } if (Foliage.empty()) { cFinishGenClumpTopBlock::ParseConfigurationString(a_IniFile.GetValueSet("Generator", a_ClumpPrefix + "-1", "Forest, -2, 2; ForestHills, -3, 2; FlowerForest = yellowflower; redflower; lilac; rosebush"), Foliage); cFinishGenClumpTopBlock::ParseConfigurationString(a_IniFile.GetValueSet("Generator", a_ClumpPrefix + "-2", "Plains, -2, 1; SunflowerPlains = yellowflower; redflower; azurebluet; redtulip; orangetulip; whitetulip; pinktulip; oxeyedaisy"), Foliage); cFinishGenClumpTopBlock::ParseConfigurationString(a_IniFile.GetValueSet("Generator", a_ClumpPrefix + "-3", "SunflowerPlains, 1, 2 = sunflower"), Foliage); cFinishGenClumpTopBlock::ParseConfigurationString(a_IniFile.GetValueSet("Generator", a_ClumpPrefix + "-4", "FlowerForest, 2, 5 = allium; redtulip; orangetulip; whitetulip; pinktulip; oxeyedaisy"), Foliage); cFinishGenClumpTopBlock::ParseConfigurationString(a_IniFile.GetValueSet("Generator", a_ClumpPrefix + "-5", "Swampland; SwamplandM = brownmushroom; redmushroom; blueorchid"), Foliage); cFinishGenClumpTopBlock::ParseConfigurationString(a_IniFile.GetValueSet("Generator", a_ClumpPrefix + "-6", "MushroomIsland; MushroomShore; MegaTaiga; MegaTaigaHills; MegaSpruceTaiga; MegaSpruceTaigaHills = brownmushroom; redmushroom"), Foliage); cFinishGenClumpTopBlock::ParseConfigurationString(a_IniFile.GetValueSet("Generator", a_ClumpPrefix + "-7", "RoofedForest, 1, 5; RoofedForestM, 1, 5 = rosebush; peony; lilac; grass"), Foliage); cFinishGenClumpTopBlock::ParseConfigurationString(a_IniFile.GetValueSet("Generator", a_ClumpPrefix + "-8", "MegaTaiga; MegaTaigaHills = deadbush"), Foliage); } return Foliage; } //////////////////////////////////////////////////////////////////////////////// // cFinishGenGlowStone: void cFinishGenGlowStone::GenFinish(cChunkDesc & a_ChunkDesc) { int ChunkX = a_ChunkDesc.GetChunkX(); int ChunkZ = a_ChunkDesc.GetChunkZ(); // Change the number of attempts to create a vein depending on the maximum height of the chunk. A standard Nether could have 5 veins at most. int NumGlowStone = m_Noise.IntNoise2DInt(ChunkX, ChunkZ) % a_ChunkDesc.GetMaxHeight() / 23; for (int i = 1; i <= NumGlowStone; i++) { // The maximum size for a string of glowstone can get 3 - 5 blocks long int Size = 3 + m_Noise.IntNoise3DInt(ChunkX, i, ChunkZ) % 3; // Generate X / Z coordinates. int X = Size + (m_Noise.IntNoise2DInt(i, Size) % (cChunkDef::Width - Size * 2)); int Z = Size + (m_Noise.IntNoise2DInt(X, i) % (cChunkDef::Width - Size * 2)); int Height = a_ChunkDesc.GetHeight(X, Z); for (int y = Height; y > Size; y--) { if (!cBlockInfo::IsSolid(a_ChunkDesc.GetBlockType(X, y, Z))) { // Current block isn't solid, bail out continue; } if (a_ChunkDesc.GetBlockType(X, y - 1, Z) != E_BLOCK_AIR) { // The block below isn't air, bail out continue; } if ((m_Noise.IntNoise3DInt(X, y, Z) % 100) < 95) { // Have a 5% chance of creating the glowstone continue; } TryPlaceGlowstone(a_ChunkDesc, X, y, Z, Size, 5 + m_Noise.IntNoise3DInt(X, y, Z) % 7); break; } } } void cFinishGenGlowStone::TryPlaceGlowstone(cChunkDesc & a_ChunkDesc, int a_RelX, int a_RelY, int a_RelZ, int a_Size, int a_NumStrings) { // The starting point of every glowstone string Vector3i StartPoint = Vector3i(a_RelX, a_RelY, a_RelZ); // Array with possible directions for a string of glowstone to go to. const Vector3i AvailableDirections[] = { { -1, 0, 0 }, { 1, 0, 0 }, { 0, -1, 0 }, // Don't let the glowstone go up { 0, 0, -1 }, { 0, 0, 1 }, // Diagonal direction. Only X or Z with Y. // If all were changed the glowstone string looks awkward { 0, -1, 1 }, { 1, -1, 0 }, { 0, -1, -1 }, { -1, -1, 0 }, }; for (int i = 1; i <= a_NumStrings; i++) { // The current position of the string that is being generated Vector3i CurrentPos = Vector3i(StartPoint); // A vector where the previous direction of a glowstone string is stored. // This is used to make the strings change direction when going one block further Vector3i PreviousDirection = Vector3i(); for (int j = 0; j < a_Size; j++) { Vector3i Direction = AvailableDirections[static_cast(m_Noise.IntNoise3DInt(CurrentPos.x, CurrentPos.y * i, CurrentPos.z)) % ARRAYCOUNT(AvailableDirections)]; int Attempts = 2; // multiply by 1 would make no difference, so multiply by 2 instead while (Direction.Equals(PreviousDirection)) { // To make the glowstone branches look better we want to make the direction change every time. Direction = AvailableDirections[static_cast(m_Noise.IntNoise3DInt(CurrentPos.x, CurrentPos.y * i * Attempts, CurrentPos.z)) % ARRAYCOUNT(AvailableDirections)]; Attempts++; } // Update the previous direction variable PreviousDirection = Direction; // Update the position of the glowstone string CurrentPos += Direction; if (cBlockInfo::IsSolid(a_ChunkDesc.GetBlockType(CurrentPos.x, CurrentPos.y, CurrentPos.z)) && (a_ChunkDesc.GetBlockType(CurrentPos.x, CurrentPos.y, CurrentPos.z) != E_BLOCK_GLOWSTONE)) { // The glowstone hit something solid, and it wasn't glowstone. Stop the string. break; } // Place a glowstone block. a_ChunkDesc.SetBlockType(CurrentPos.x, CurrentPos.y, CurrentPos.z, E_BLOCK_GLOWSTONE); } } } //////////////////////////////////////////////////////////////////////////////// // cFinishGenTallGrass: void cFinishGenTallGrass::GenFinish(cChunkDesc & a_ChunkDesc) { for (int x = 0; x < cChunkDef::Width; x++) { int xx = x + a_ChunkDesc.GetChunkX() * cChunkDef::Width; for (int z = 0; z < cChunkDef::Width; z++) { int zz = z + a_ChunkDesc.GetChunkZ() * cChunkDef::Width; int BiomeDensity = GetBiomeDensity(a_ChunkDesc.GetBiome(x, z)); // Choose if we want to place long grass here. If not then bail out: if ((m_Noise.IntNoise2DInt(xx + m_Noise.IntNoise1DInt(xx), zz + m_Noise.IntNoise1DInt(zz)) / 7 % 100) > BiomeDensity) { continue; } // Get the top block + 1. This is the place where the grass would finaly be placed: int y = a_ChunkDesc.GetHeight(x, z) + 1; if (y >= cChunkDef::Height - 1) { continue; } // Walk below trees: auto BlockBelow = a_ChunkDesc.GetBlockType(x, y - 1, z); bool failed = false; // marker if the search for a valid position was successful while ( (BlockBelow == E_BLOCK_LEAVES) || (BlockBelow == E_BLOCK_NEW_LEAVES) || (BlockBelow == E_BLOCK_LOG) || (BlockBelow == E_BLOCK_NEW_LOG) || (BlockBelow == E_BLOCK_AIR) ) { y--; if (!cChunkDef::IsValidHeight({x, y - 1, z})) { failed = true; break; } BlockBelow = a_ChunkDesc.GetBlockType(x, y - 1, z); } if (failed) { continue; } // Check if long grass can be placed: if ( (a_ChunkDesc.GetBlockType(x, y, z) != E_BLOCK_AIR) || ((a_ChunkDesc.GetBlockType(x, y - 1, z) != E_BLOCK_GRASS) && (a_ChunkDesc.GetBlockType(x, y - 1, z) != E_BLOCK_DIRT)) ) { continue; } // Choose what long grass meta we should use: int GrassType = m_Noise.IntNoise2DInt(xx * 50, zz * 50) / 7 % 100; if ((GrassType < 60) && CanGrassGrow(a_ChunkDesc.GetBiome(x, z))) { a_ChunkDesc.SetBlockTypeMeta(x, y, z, E_BLOCK_TALL_GRASS, E_META_TALL_GRASS_GRASS); } else if ((GrassType < 90) && CanFernGrow(a_ChunkDesc.GetBiome(x, z))) { a_ChunkDesc.SetBlockTypeMeta(x, y, z, E_BLOCK_TALL_GRASS, E_META_TALL_GRASS_FERN); } else if (!IsBiomeVeryCold(a_ChunkDesc.GetBiome(x, z))) { // If double long grass we have to choose what type we should use: if (a_ChunkDesc.GetBlockType(x, y + 1, z) == E_BLOCK_AIR) { NIBBLETYPE Meta; if (CanGrassGrow(a_ChunkDesc.GetBiome(x, z))) { Meta = (m_Noise.IntNoise2DInt(xx * 100, zz * 100) / 7 % 100) > 25 ? E_META_BIG_FLOWER_DOUBLE_TALL_GRASS : E_META_BIG_FLOWER_LARGE_FERN; } else { Meta = E_META_BIG_FLOWER_LARGE_FERN; } if ((Meta != E_META_BIG_FLOWER_LARGE_FERN) || CanLargeFernGrow(a_ChunkDesc.GetBiome(x, z))) { a_ChunkDesc.SetBlockTypeMeta(x, y, z, E_BLOCK_BIG_FLOWER, Meta); a_ChunkDesc.SetBlockTypeMeta(x, y + 1, z, E_BLOCK_BIG_FLOWER, E_META_BIG_FLOWER_TOP); a_ChunkDesc.SetHeight(x, z, static_cast(y + 1)); } } } else { NIBBLETYPE meta = static_cast((m_Noise.IntNoise2DInt(xx * 50, zz * 50) / 7 % 2) + 1); a_ChunkDesc.SetBlockTypeMeta(x, y, z, E_BLOCK_TALL_GRASS, meta); a_ChunkDesc.SetHeight(x, z, static_cast(y)); } } } } bool cFinishGenTallGrass::CanFernGrow(EMCSBiome a_Biome) { switch (a_Biome) { case biJungle: case biJungleEdge: case biJungleEdgeM: case biJungleHills: case biJungleM: { return true; } default: { return CanLargeFernGrow(a_Biome); } } } bool cFinishGenTallGrass::CanLargeFernGrow(EMCSBiome a_Biome) { switch (a_Biome) { case biColdTaiga: case biColdTaigaHills: case biColdTaigaM: case biTaiga: case biTaigaHills: case biTaigaM: case biMegaSpruceTaiga: case biMegaSpruceTaigaHills: case biMegaTaiga: case biMegaTaigaHills: { return true; } default: { return false; } } } int cFinishGenTallGrass::GetBiomeDensity(EMCSBiome a_Biome) { switch (a_Biome) { case biSavanna: case biSavannaM: case biSavannaPlateau: case biSavannaPlateauM: case biPlains: { return 70; } case biExtremeHillsEdge: case biExtremeHillsPlus: case biExtremeHills: case biExtremeHillsPlusM: case biExtremeHillsM: case biIceMountains: { return 3; } default: { return 20; } } } bool cFinishGenTallGrass::CanGrassGrow(EMCSBiome a_Biome) { switch (a_Biome) { case biMegaTaiga: case biMegaTaigaHills: { return false; } default: { return true; } } } //////////////////////////////////////////////////////////////////////////////// // cFinishGenVines bool cFinishGenVines::IsJungleVariant(EMCSBiome a_Biome) { switch (a_Biome) { case biJungle: case biJungleEdge: case biJungleEdgeM: case biJungleHills: case biJungleM: { return true; } default: { return false; } } } void cFinishGenVines::GenFinish(cChunkDesc & a_ChunkDesc) { for (int x = 0; x < cChunkDef::Width; x++) { int xx = x + a_ChunkDesc.GetChunkX() * cChunkDef::Width; for (int z = 0; z < cChunkDef::Width; z++) { int zz = z + a_ChunkDesc.GetChunkZ() * cChunkDef::Width; if (!IsJungleVariant(a_ChunkDesc.GetBiome(x, z))) { // Current biome isn't a jungle continue; } if ((m_Noise.IntNoise2DInt(xx, zz) % 101) < 50) { continue; } int Height = a_ChunkDesc.GetHeight(x, z); for (int y = Height; y > m_Level; y--) { if (a_ChunkDesc.GetBlockType(x, y, z) != E_BLOCK_AIR) { // Can't place vines in non-air blocks continue; } if ((m_Noise.IntNoise3DInt(xx, y, zz) % 101) < 50) { continue; } std::vector Places; if ((x + 1 < cChunkDef::Width) && cBlockInfo::FullyOccupiesVoxel(a_ChunkDesc.GetBlockType(x + 1, y, z))) { Places.push_back(8); } if ((x - 1 > 0) && cBlockInfo::FullyOccupiesVoxel(a_ChunkDesc.GetBlockType(x - 1, y, z))) { Places.push_back(2); } if ((z + 1 < cChunkDef::Width) && cBlockInfo::FullyOccupiesVoxel(a_ChunkDesc.GetBlockType(x, y, z + 1))) { Places.push_back(1); } if ((z - 1 > 0) && cBlockInfo::FullyOccupiesVoxel(a_ChunkDesc.GetBlockType(x, y, z - 1))) { Places.push_back(4); } if (Places.size() == 0) { continue; } NIBBLETYPE Meta = Places[static_cast(m_Noise.IntNoise3DInt(xx, y, zz)) % Places.size()]; a_ChunkDesc.SetBlockTypeMeta(x, y, z, E_BLOCK_VINES, Meta); } } } } //////////////////////////////////////////////////////////////////////////////// // cFinishGenSprinkleFoliage: bool cFinishGenSprinkleFoliage::TryAddCactus(cChunkDesc & a_ChunkDesc, int a_RelX, HEIGHTTYPE & a_RelY, int a_RelZ) { if (!IsDesertVariant(a_ChunkDesc.GetBiome(a_RelX, a_RelZ))) { return false; } int CactusHeight = 1 + (m_Noise.IntNoise2DInt(a_RelX, a_RelZ) % m_MaxCactusHeight); // We'll be doing comparison with blocks above, so the coords should be 1 block away from chunk top if (a_RelY + CactusHeight >= cChunkDef::Height - 1) { CactusHeight = cChunkDef::Height - a_RelY - 1; } // We'll be doing comparison to neighbors, so require the coords to be 1 block away from the chunk edges: if ( (a_RelX < 1) || (a_RelX >= cChunkDef::Width - 1) || (a_RelZ < 1) || (a_RelZ >= cChunkDef::Width - 1) ) { return false; } for (int i = 0; i < CactusHeight; i++) { const bool cactusExists = i != 0; const int y = a_RelY + 1; if ( cBlockInfo::IsSolid(a_ChunkDesc.GetBlockType(a_RelX + 1, y, a_RelZ)) || cBlockInfo::IsSolid(a_ChunkDesc.GetBlockType(a_RelX - 1, y, a_RelZ)) || cBlockInfo::IsSolid(a_ChunkDesc.GetBlockType(a_RelX, y, a_RelZ + 1)) || cBlockInfo::IsSolid(a_ChunkDesc.GetBlockType(a_RelX, y, a_RelZ - 1)) ) { return cactusExists; } // All conditions are met, we can place a cactus here a_ChunkDesc.SetBlockType(a_RelX, ++a_RelY, a_RelZ, E_BLOCK_CACTUS); } return true; } //////////////////////////////////////////////////////////////////////////////// // cFinishGenSprinkleFoliage: bool cFinishGenSprinkleFoliage::TryAddSugarcane(cChunkDesc & a_ChunkDesc, int a_RelX, HEIGHTTYPE & a_RelY, int a_RelZ) { int SugarcaneHeight = 1 + (m_Noise.IntNoise2DInt(a_RelX, a_RelZ) % m_MaxSugarcaneHeight); // Only allow dirt, grass, sand and sugarcane below sugarcane: switch (a_ChunkDesc.GetBlockType(a_RelX, a_RelY, a_RelZ)) { case E_BLOCK_DIRT: case E_BLOCK_GRASS: case E_BLOCK_SAND: case E_BLOCK_SUGARCANE: { break; } default: { return false; } } // We'll be doing comparison with blocks above, so the coords should be 1 block away from chunk top if (a_RelY + SugarcaneHeight >= cChunkDef::Height - 1) { SugarcaneHeight = cChunkDef::Height - a_RelY - 1; } // We'll be doing comparison to neighbors, so require the coords to be 1 block away from the chunk edges: if ( (a_RelX < 1) || (a_RelX >= cChunkDef::Width - 1) || (a_RelZ < 1) || (a_RelZ >= cChunkDef::Width - 1) ) { return false; } // Water is required next to the block below the sugarcane (if the block below isn't sugarcane already) if ( !IsWater(a_ChunkDesc.GetBlockType(a_RelX - 1, a_RelY, a_RelZ)) && !IsWater(a_ChunkDesc.GetBlockType(a_RelX + 1, a_RelY, a_RelZ)) && !IsWater(a_ChunkDesc.GetBlockType(a_RelX, a_RelY, a_RelZ - 1)) && !IsWater(a_ChunkDesc.GetBlockType(a_RelX, a_RelY, a_RelZ + 1)) && a_ChunkDesc.GetBlockType(a_RelX, a_RelY, a_RelZ) != E_BLOCK_SUGARCANE ) { return false; } for (int i = 0; i < SugarcaneHeight; i++) { // All conditions met, place a sugarcane here a_ChunkDesc.SetBlockType(a_RelX, ++a_RelY, a_RelZ, E_BLOCK_SUGARCANE); } return true; } void cFinishGenSprinkleFoliage::GenFinish(cChunkDesc & a_ChunkDesc) { // Generate small foliage (1-block): // TODO: Update heightmap with 1-block-tall foliage for (int z = 0; z < cChunkDef::Width; z++) { int BlockZ = a_ChunkDesc.GetChunkZ() * cChunkDef::Width + z; const float zz = static_cast(BlockZ); for (int x = 0; x < cChunkDef::Width; x++) { int BlockX = a_ChunkDesc.GetChunkX() * cChunkDef::Width + x; if (((m_Noise.IntNoise2DInt(BlockX, BlockZ) / 8) % 128) < 124) { continue; } HEIGHTTYPE Top = a_ChunkDesc.GetHeight(x, z); if (Top > 250) { // Nothing grows above Y=250 continue; } if (a_ChunkDesc.GetBlockType(x, Top + 1, z) != E_BLOCK_AIR) { // Space already taken by something else, don't grow here // WEIRD, since we're using heightmap, so there should NOT be anything above it continue; } const float xx = static_cast(BlockX); float val1 = m_Noise.CubicNoise2D(xx * 0.1f, zz * 0.1f); float val2 = m_Noise.CubicNoise2D(xx * 0.01f, zz * 0.01f); switch (a_ChunkDesc.GetBlockType(x, Top, z)) { case E_BLOCK_GRASS: { if (TryAddSugarcane(a_ChunkDesc, x, Top, z)) { // Checks and block placing are handled in the TryAddSugarcane method } else if ((val1 > 0.5) && (val2 < -0.5)) { float val3 = m_Noise.CubicNoise2D(xx * 0.01f + 10, zz * 0.01f + 10); a_ChunkDesc.SetBlockTypeMeta(x, ++Top, z, E_BLOCK_PUMPKIN, static_cast(val3 * 8) % 4); } break; } // case E_BLOCK_GRASS case E_BLOCK_SAND: { if (val1 + val2 > 0.5f) { if (!TryAddCactus(a_ChunkDesc, x, Top, z)) { TryAddSugarcane(a_ChunkDesc, x, Top, z); } } else { TryAddSugarcane(a_ChunkDesc, x, Top, z); } break; } } // switch (TopBlock) a_ChunkDesc.SetHeight(x, z, Top); } // for x } // for z } bool cFinishGenSprinkleFoliage::IsDesertVariant(EMCSBiome a_Biome) { return ( (a_Biome == biDesertHills) || (a_Biome == biDesert) || (a_Biome == biDesertM) ); } //////////////////////////////////////////////////////////////////////////////// // cFinishGenSoulsandRims void cFinishGenSoulsandRims::GenFinish(cChunkDesc & a_ChunkDesc) { int ChunkX = a_ChunkDesc.GetChunkX() * cChunkDef::Width; int ChunkZ = a_ChunkDesc.GetChunkZ() * cChunkDef::Width; HEIGHTTYPE MaxHeight = a_ChunkDesc.GetMaxHeight(); for (int x = 0; x < 16; x++) { int xx = ChunkX + x; for (int z = 0; z < 16; z++) { int zz = ChunkZ + z; // Place soulsand rims when netherrack gets thin for (int y = 2; y < MaxHeight - 2; y++) { // The current block is air. Let's bail ut. BLOCKTYPE Block = a_ChunkDesc.GetBlockType(x, y, z); if (Block != E_BLOCK_NETHERRACK) { continue; } if ( ((a_ChunkDesc.GetBlockType(x, y + 1, z) != E_BLOCK_AIR) && ( a_ChunkDesc.GetBlockType(x, y + 2, z) != E_BLOCK_AIR)) || ((a_ChunkDesc.GetBlockType(x, y - 1, z) != E_BLOCK_AIR) && ( a_ChunkDesc.GetBlockType(x, y - 2, z) != E_BLOCK_AIR)) ) { continue; } NOISE_DATATYPE NoiseX = (static_cast(xx)) / 32; NOISE_DATATYPE NoiseY = (static_cast(zz)) / 32; NOISE_DATATYPE CompBlock = m_Noise.CubicNoise3D(NoiseX, static_cast(y) / 4, NoiseY); if (CompBlock < 0) { a_ChunkDesc.SetBlockType(x, y, z, E_BLOCK_SOULSAND); } } } } } //////////////////////////////////////////////////////////////////////////////// // cFinishGenSnow: void cFinishGenSnow::GenFinish(cChunkDesc & a_ChunkDesc) { // Add a snow block in snowy biomes onto blocks that can be snowed over for (int z = 0; z < cChunkDef::Width; z++) { for (int x = 0; x < cChunkDef::Width; x++) { HEIGHTTYPE Height = a_ChunkDesc.GetHeight(x, z); if (GetSnowStartHeight(a_ChunkDesc.GetBiome(x, z)) > Height) { // Height isn't high enough for snow to start forming. continue; } if (!cBlockInfo::IsSnowable(a_ChunkDesc.GetBlockType(x, Height, z)) || (Height >= cChunkDef::Height - 1)) { // The top block can't be snown over. continue; } a_ChunkDesc.SetBlockType(x, Height + 1, z, E_BLOCK_SNOW); a_ChunkDesc.SetHeight(x, z, Height + 1); } // for x } // for z } //////////////////////////////////////////////////////////////////////////////// // cFinishGenIce: void cFinishGenIce::GenFinish(cChunkDesc & a_ChunkDesc) { // Turn surface water into ice in icy biomes for (int z = 0; z < cChunkDef::Width; z++) { for (int x = 0; x < cChunkDef::Width; x++) { int Height = a_ChunkDesc.GetHeight(x, z); if (GetSnowStartHeight(a_ChunkDesc.GetBiome(x, z)) > Height) { // Height isn't high enough for snow to start forming. continue; } if (!IsBlockWater(a_ChunkDesc.GetBlockType(x, Height, z))) { // The block isn't a water block. continue; } if (a_ChunkDesc.GetBlockMeta(x, Height, z) != 0) { // The water block isn't a source block. continue; } a_ChunkDesc.SetBlockType(x, Height, z, E_BLOCK_ICE); } // for x } // for z } //////////////////////////////////////////////////////////////////////////////// // cFinishGenSingleTopBlock: int cFinishGenSingleTopBlock::GetNumToGen(const cChunkDef::BiomeMap & a_BiomeMap) { int res = 0; for (size_t i = 0; i < ARRAYCOUNT(a_BiomeMap); i++) { if (IsAllowedBiome(a_BiomeMap[i])) { res++; } } // for i - a_BiomeMap[] return m_Amount * res / 256; } void cFinishGenSingleTopBlock::GenFinish(cChunkDesc & a_ChunkDesc) { int NumToGen = GetNumToGen(a_ChunkDesc.GetBiomeMap()); int ChunkX = a_ChunkDesc.GetChunkX(); int ChunkZ = a_ChunkDesc.GetChunkZ(); for (int i = 0; i < NumToGen; i++) { int x = (m_Noise.IntNoise3DInt(ChunkX + ChunkZ, ChunkZ, i) / 13) % cChunkDef::Width; int z = (m_Noise.IntNoise3DInt(ChunkX - ChunkZ, i, ChunkZ) / 11) % cChunkDef::Width; // Place the block at {x, z} if possible: EMCSBiome Biome = a_ChunkDesc.GetBiome(x, z); if (!IsAllowedBiome(Biome)) { // Incorrect biome continue; } HEIGHTTYPE Height = a_ChunkDesc.GetHeight(x, z); if (Height >= cChunkDef::Height - 1) { // Too high up continue; } if (a_ChunkDesc.GetBlockType(x, Height + 1, z) != E_BLOCK_AIR) { // Not an empty block continue; } BLOCKTYPE BlockBelow = a_ChunkDesc.GetBlockType(x, Height, z); if (!IsAllowedBlockBelow(BlockBelow)) { continue; } a_ChunkDesc.SetBlockType(x, Height + 1, z, m_BlockType); a_ChunkDesc.SetHeight(x, z, Height + 1); } } //////////////////////////////////////////////////////////////////////////////// // cFinishGenBottomLava: void cFinishGenBottomLava::GenFinish(cChunkDesc & a_ChunkDesc) { cChunkDef::BlockTypes & BlockTypes = a_ChunkDesc.GetBlockTypes(); for (int y = m_Level; y > 0; y--) { for (int z = 0; z < cChunkDef::Width; z++) for (int x = 0; x < cChunkDef::Width; x++) { const auto Index = cChunkDef::MakeIndex(x, y, z); if (BlockTypes[Index] == E_BLOCK_AIR) { BlockTypes[Index] = E_BLOCK_STATIONARY_LAVA; } } // for x, for z } // for y } //////////////////////////////////////////////////////////////////////////////// // cFinishGenPreSimulator: cFinishGenPreSimulator::cFinishGenPreSimulator(bool a_PreSimulateFallingBlocks, bool a_PreSimulateWater, bool a_PreSimulateLava) : m_PreSimulateFallingBlocks(a_PreSimulateFallingBlocks), m_PreSimulateWater(a_PreSimulateWater), m_PreSimulateLava(a_PreSimulateLava) { // Nothing needed yet } void cFinishGenPreSimulator::GenFinish(cChunkDesc & a_ChunkDesc) { if (m_PreSimulateFallingBlocks) { CollapseSandGravel(a_ChunkDesc); } if (m_PreSimulateWater) { StationarizeFluid(a_ChunkDesc.GetBlockTypes(), a_ChunkDesc.GetHeightMap(), E_BLOCK_WATER, E_BLOCK_STATIONARY_WATER); } if (m_PreSimulateLava) { StationarizeFluid(a_ChunkDesc.GetBlockTypes(), a_ChunkDesc.GetHeightMap(), E_BLOCK_LAVA, E_BLOCK_STATIONARY_LAVA); } // TODO: other operations } void cFinishGenPreSimulator::CollapseSandGravel(cChunkDesc & a_ChunkDesc) { for (int z = 0; z < cChunkDef::Width; z++) { for (int x = 0; x < cChunkDef::Width; x++) { int LastY = -1; int HeightY = 0; for (int y = 0; y < cChunkDef::Height; y++) { BLOCKTYPE Block = a_ChunkDesc.GetBlockType(x, y, z); switch (Block) { default: { // Set the last block onto which stuff can fall to this height: LastY = y; HeightY = y; break; } case E_BLOCK_AIR: { // Do nothing break; } case E_BLOCK_FIRE: case E_BLOCK_WATER: case E_BLOCK_STATIONARY_WATER: case E_BLOCK_LAVA: case E_BLOCK_STATIONARY_LAVA: { // Do nothing, only remember this height as potentially highest HeightY = y; break; } case E_BLOCK_SAND: case E_BLOCK_GRAVEL: { if (LastY < y - 1) { auto BlockMeta = a_ChunkDesc.GetBlockMeta(x, y, z); a_ChunkDesc.SetBlockTypeMeta(x, LastY + 1, z, Block, BlockMeta); a_ChunkDesc.SetBlockTypeMeta(x, y, z, E_BLOCK_AIR, 0); } LastY++; if (LastY > HeightY) { HeightY = LastY; } break; } } // switch (GetBlock) } // for y a_ChunkDesc.SetHeight(x, z, static_cast(HeightY)); } // for x } // for z } void cFinishGenPreSimulator::StationarizeFluid( cChunkDef::BlockTypes & a_BlockTypes, // Block types to read and change cChunkDef::HeightMap & a_HeightMap, // Height map to read BLOCKTYPE a_Fluid, BLOCKTYPE a_StationaryFluid ) { // Turn fluid in the middle to stationary, unless it has air or washable block next to it: for (int z = 1; z < cChunkDef::Width - 1; z++) { for (int x = 1; x < cChunkDef::Width - 1; x++) { for (int y = cChunkDef::GetHeight(a_HeightMap, x, z); y >= 0; y--) { BLOCKTYPE Block = cChunkDef::GetBlock(a_BlockTypes, x, y, z); if ((Block != a_Fluid) && (Block != a_StationaryFluid)) { continue; } static const struct { int x, y, z; } Coords[] = { {1, 0, 0}, {-1, 0, 0}, {0, 0, 1}, {0, 0, -1}, {0, -1, 0} } ; BLOCKTYPE BlockToSet = a_StationaryFluid; // By default, don't simulate this block for (size_t i = 0; i < ARRAYCOUNT(Coords); i++) { if ((y == 0) && (Coords[i].y < 0)) { continue; } BLOCKTYPE Neighbor = cChunkDef::GetBlock(a_BlockTypes, x + Coords[i].x, y + Coords[i].y, z + Coords[i].z); if ((Neighbor == E_BLOCK_AIR) || cFluidSimulator::CanWashAway(Neighbor)) { // There is an air / washable neighbor, simulate this block BlockToSet = a_Fluid; break; } } // for i - Coords[] cChunkDef::SetBlock(a_BlockTypes, x, y, z, BlockToSet); } // for y } // for x } // for z // Turn fluid at the chunk edges into non-stationary fluid: for (int y = 0; y < cChunkDef::Height; y++) { for (int i = 0; i < cChunkDef::Width; i++) // i stands for both x and z here { if (cChunkDef::GetBlock(a_BlockTypes, 0, y, i) == a_StationaryFluid) { cChunkDef::SetBlock(a_BlockTypes, 0, y, i, a_Fluid); } if (cChunkDef::GetBlock(a_BlockTypes, i, y, 0) == a_StationaryFluid) { cChunkDef::SetBlock(a_BlockTypes, i, y, 0, a_Fluid); } if (cChunkDef::GetBlock(a_BlockTypes, cChunkDef::Width - 1, y, i) == a_StationaryFluid) { cChunkDef::SetBlock(a_BlockTypes, cChunkDef::Width - 1, y, i, a_Fluid); } if (cChunkDef::GetBlock(a_BlockTypes, i, y, cChunkDef::Width - 1) == a_StationaryFluid) { cChunkDef::SetBlock(a_BlockTypes, i, y, cChunkDef::Width - 1, a_Fluid); } } } } //////////////////////////////////////////////////////////////////////////////// // cFinishGenFluidSprings: cFinishGenFluidSprings::cFinishGenFluidSprings(int a_Seed, BLOCKTYPE a_Fluid, cIniFile & a_IniFile, eDimension a_Dimension) : m_Noise(a_Seed + a_Fluid * 100), // Need to take fluid into account, otherwise water and lava springs generate next to each other m_HeightDistribution(cChunkDef::Height - 1), m_Fluid(a_Fluid) { bool IsWater = (a_Fluid == E_BLOCK_WATER); AString SectionName = IsWater ? "WaterSprings" : "LavaSprings"; AString DefaultHeightDistribution; int DefaultChance = 0; switch (a_Dimension) { case dimNether: { DefaultHeightDistribution = IsWater ? DEF_NETHER_WATER_SPRINGS : DEF_NETHER_LAVA_SPRINGS; DefaultChance = IsWater ? 0 : 15; break; } case dimOverworld: { DefaultHeightDistribution = IsWater ? DEF_OVERWORLD_WATER_SPRINGS : DEF_OVERWORLD_LAVA_SPRINGS; DefaultChance = IsWater ? 24 : 9; break; } case dimEnd: { DefaultHeightDistribution = IsWater ? DEF_END_WATER_SPRINGS : DEF_END_LAVA_SPRINGS; DefaultChance = 0; break; } default: { ASSERT(!"Unhandled world dimension"); break; } } // switch (dimension) AString HeightDistribution = a_IniFile.GetValueSet(SectionName, "HeightDistribution", DefaultHeightDistribution); if (!m_HeightDistribution.SetDefString(HeightDistribution) || (m_HeightDistribution.GetSum() <= 0)) { LOGWARNING("[%sSprings]: HeightDistribution is invalid, using the default of \"%s\".", (a_Fluid == E_BLOCK_WATER) ? "Water" : "Lava", DefaultHeightDistribution.c_str() ); m_HeightDistribution.SetDefString(DefaultHeightDistribution); } m_Chance = a_IniFile.GetValueSetI(SectionName, "Chance", DefaultChance); } void cFinishGenFluidSprings::GenFinish(cChunkDesc & a_ChunkDesc) { int ChanceRnd = (m_Noise.IntNoise3DInt(128 * a_ChunkDesc.GetChunkX(), 512, 256 * a_ChunkDesc.GetChunkZ()) / 13) % 100; if (ChanceRnd > m_Chance) { // Not in this chunk return; } // Get the height at which to try: int Height = m_Noise.IntNoise3DInt(128 * a_ChunkDesc.GetChunkX(), 1024, 256 * a_ChunkDesc.GetChunkZ()) / 11; Height %= m_HeightDistribution.GetSum(); Height = m_HeightDistribution.MapValue(Height); // Try adding the spring at the height, if unsuccessful, move lower: for (int y = Height; y > 1; y--) { // TODO: randomize the order in which the coords are being checked for (int z = 1; z < cChunkDef::Width - 1; z++) { for (int x = 1; x < cChunkDef::Width - 1; x++) { switch (a_ChunkDesc.GetBlockType(x, y, z)) { case E_BLOCK_NETHERRACK: case E_BLOCK_STONE: { if (TryPlaceSpring(a_ChunkDesc, x, y, z)) { // Succeeded, bail out return; } } } // switch (BlockType) } // for x } // for y } // for y } bool cFinishGenFluidSprings::TryPlaceSpring(cChunkDesc & a_ChunkDesc, int x, int y, int z) { // In order to place a spring, it needs exactly one of the XZ neighbors or a below neighbor to be air // Also, its neighbor on top of it must be non-air if (a_ChunkDesc.GetBlockType(x, y + 1, z) == E_BLOCK_AIR) { return false; } static const struct { int x, y, z; } Coords[] = { {-1, 0, 0}, { 1, 0, 0}, { 0, -1, 0}, { 0, 0, -1}, { 0, 0, 1}, } ; int NumAirNeighbors = 0; for (size_t i = 0; i < ARRAYCOUNT(Coords); i++) { switch (a_ChunkDesc.GetBlockType(x + Coords[i].x, y + Coords[i].y, z + Coords[i].z)) { case E_BLOCK_AIR: { NumAirNeighbors += 1; if (NumAirNeighbors > 1) { return false; } } } } if (NumAirNeighbors == 0) { return false; } // Has exactly one air neighbor, place a spring: a_ChunkDesc.SetBlockTypeMeta(x, y, z, m_Fluid, 0); return true; } //////////////////////////////////////////////////////////////////////////////// // cFinishGenPassiveMobs: cFinishGenPassiveMobs::cFinishGenPassiveMobs(int a_Seed, cIniFile & a_IniFile, eDimension a_Dimension) : m_Noise(a_Seed) { AString SectionName = "Animals"; int DefaultAnimalSpawnChunkPercentage = DEF_ANIMAL_SPAWN_PERCENT; switch (a_Dimension) { case dimOverworld: { DefaultAnimalSpawnChunkPercentage = DEF_ANIMAL_SPAWN_PERCENT; break; } case dimNether: case dimEnd: // No nether or end animals (currently) { DefaultAnimalSpawnChunkPercentage = DEF_NO_ANIMALS; break; } default: { ASSERT(!"Unhandled world dimension"); DefaultAnimalSpawnChunkPercentage = DEF_NO_ANIMALS; break; } } // switch (dimension) m_AnimalProbability = a_IniFile.GetValueSetI(SectionName, "AnimalSpawnChunkPercentage", DefaultAnimalSpawnChunkPercentage); if ((m_AnimalProbability < 0) || (m_AnimalProbability > 100)) { LOGWARNING("[Animals]: AnimalSpawnChunkPercentage is invalid, using the default of \"%d\".", DefaultAnimalSpawnChunkPercentage); m_AnimalProbability = DefaultAnimalSpawnChunkPercentage; } } void cFinishGenPassiveMobs::GenFinish(cChunkDesc & a_ChunkDesc) { int chunkX = a_ChunkDesc.GetChunkX(); int chunkZ = a_ChunkDesc.GetChunkZ(); int ChanceRnd = (m_Noise.IntNoise2DInt(chunkX, chunkZ) / 7) % 100; if (ChanceRnd > m_AnimalProbability) { return; } eMonsterType RandomMob = GetRandomMob(a_ChunkDesc); if (RandomMob == mtInvalidType) { // No mobs here. Don't send an error, because if the biome was a desert it would return mtInvalidType as well. return; } // Try spawning a pack center 10 times, should get roughly the same probability for (int Tries = 0; Tries < 10; Tries++) { int PackCenterX = (m_Noise.IntNoise2DInt(chunkX + chunkZ, Tries) / 7) % cChunkDef::Width; int PackCenterZ = (m_Noise.IntNoise2DInt(chunkX, chunkZ + Tries) / 7) % cChunkDef::Width; if (TrySpawnAnimals(a_ChunkDesc, PackCenterX, a_ChunkDesc.GetHeight(PackCenterX, PackCenterZ), PackCenterZ, RandomMob)) { for (int i = 0; i < 3; i++) { int OffsetX = (m_Noise.IntNoise2DInt(chunkX + chunkZ + i, Tries) / 7) % cChunkDef::Width; int OffsetZ = (m_Noise.IntNoise2DInt(chunkX, chunkZ + Tries + i) / 7) % cChunkDef::Width; TrySpawnAnimals(a_ChunkDesc, OffsetX, a_ChunkDesc.GetHeight(OffsetX, OffsetZ), OffsetZ, RandomMob); } return; } // if pack center spawn successful } // for tries } bool cFinishGenPassiveMobs::TrySpawnAnimals(cChunkDesc & a_ChunkDesc, int a_RelX, int a_RelY, int a_RelZ, eMonsterType AnimalToSpawn) { if ((a_RelY >= cChunkDef::Height - 1) || (a_RelY <= 0)) { return false; } BLOCKTYPE BlockAtHead = a_ChunkDesc.GetBlockType(a_RelX, a_RelY + 1, a_RelZ); BLOCKTYPE BlockAtFeet = a_ChunkDesc.GetBlockType(a_RelX, a_RelY, a_RelZ); BLOCKTYPE BlockUnderFeet = a_ChunkDesc.GetBlockType(a_RelX, a_RelY - 1, a_RelZ); // Check block below (opaque, grass, water), and above (air) if ((AnimalToSpawn == mtSquid) && (BlockAtFeet != E_BLOCK_WATER)) { return false; } if ( (AnimalToSpawn != mtSquid) && (BlockAtHead != E_BLOCK_AIR) && (BlockAtFeet != E_BLOCK_AIR) && (!cBlockInfo::IsTransparent(BlockUnderFeet)) ) { return false; } if ( (BlockUnderFeet != E_BLOCK_GRASS) && ((AnimalToSpawn == mtWolf) || (AnimalToSpawn == mtRabbit) || (AnimalToSpawn == mtCow) || (AnimalToSpawn == mtSheep) || (AnimalToSpawn == mtChicken) || (AnimalToSpawn == mtPig)) ) { return false; } if ((AnimalToSpawn == mtMooshroom) && (BlockUnderFeet != E_BLOCK_MYCELIUM)) { return false; } double AnimalX = static_cast(a_ChunkDesc.GetChunkX() * cChunkDef::Width + a_RelX + 0.5); double AnimalY = a_RelY; double AnimalZ = static_cast(a_ChunkDesc.GetChunkZ() * cChunkDef::Width + a_RelZ + 0.5); auto NewMob = cMonster::NewMonsterFromType(AnimalToSpawn); NewMob->SetHealth(NewMob->GetMaxHealth()); NewMob->SetPosition(AnimalX, AnimalY, AnimalZ); FLOGD("Spawning {0} #{1} at {2:.02f}", NewMob->GetClass(), NewMob->GetUniqueID(), NewMob->GetPosition()); a_ChunkDesc.GetEntities().emplace_back(std::move(NewMob)); return true; } eMonsterType cFinishGenPassiveMobs::GetRandomMob(cChunkDesc & a_ChunkDesc) { std::vector ListOfSpawnables; int chunkX = a_ChunkDesc.GetChunkX(); int chunkZ = a_ChunkDesc.GetChunkZ(); int x = (m_Noise.IntNoise2DInt(chunkX, chunkZ + 10) / 7) % cChunkDef::Width; int z = (m_Noise.IntNoise2DInt(chunkX + chunkZ, chunkZ) / 7) % cChunkDef::Width; for (auto MobType : cMobSpawner::GetAllowedMobTypes(a_ChunkDesc.GetBiome(x, z))) { if (cMonster::FamilyFromType(MobType) == cMonster::eFamily::mfPassive) { ListOfSpawnables.push_back(MobType); } } if (ListOfSpawnables.empty()) { return mtInvalidType; } auto RandMob = (static_cast(m_Noise.IntNoise2DInt(chunkX - chunkZ + 2, chunkX + 5) / 7) % ListOfSpawnables.size()); return ListOfSpawnables[RandMob]; } //////////////////////////////////////////////////////////////////////////////// // cFinishGenOres: void cFinishGenOres::GenFinish(cChunkDesc & a_ChunkDesc) { int seq = 1; // Generate the ores from the ore list. for (const auto & ore: m_OreInfos) { GenerateOre( a_ChunkDesc, ore.m_BlockType, ore.m_BlockMeta, ore.m_MaxHeight, ore.m_NumNests, ore.m_NestSize, seq ); seq++; } } const cFinishGenOres::OreInfos & cFinishGenOres::DefaultOverworldOres(void) { static OreInfos res { // OreType, OreMeta, MaxHeight, NumNests, NestSize {E_BLOCK_COAL_ORE, 0, 127, 20, 16}, {E_BLOCK_IRON_ORE, 0, 64, 20, 8}, {E_BLOCK_GOLD_ORE, 0, 32, 2, 8}, {E_BLOCK_REDSTONE_ORE, 0, 16, 8, 7}, {E_BLOCK_DIAMOND_ORE, 0, 15, 1, 7}, {E_BLOCK_LAPIS_ORE, 0, 30, 1, 6}, {E_BLOCK_EMERALD_ORE, 0, 32, 11, 1}, {E_BLOCK_SILVERFISH_EGG, 0, 64, 7, 9}, }; return res; } const cFinishGenOres::OreInfos & cFinishGenOres::DefaultNetherOres(void) { static OreInfos res { // OreType, OreMeta, MaxHeight, NumNests, NestSize {E_BLOCK_NETHER_QUARTZ_ORE, 0, 127, 20, 8}, }; return res; } const cFinishGenOres::OreInfos & cFinishGenOres::DefaultNaturalPatches(void) { static OreInfos res { // OreType, OreMeta, MaxHeight, NumNests, NestSize {E_BLOCK_DIRT, 0, 127, 20, 32}, {E_BLOCK_GRAVEL, 0, 127, 10, 32}, {E_BLOCK_STONE, E_META_STONE_GRANITE, 127, 20, 32}, {E_BLOCK_STONE, E_META_STONE_DIORITE, 127, 20, 32}, {E_BLOCK_STONE, E_META_STONE_ANDESITE, 127, 20, 32}, }; return res; } cFinishGenOres::OreInfos cFinishGenOres::OreInfosFromString(const AString & a_OreInfosString) { // The string is expected to be formatted as " | | | ..." // Each OreInfo is expected to be formatted as " : : : : " OreInfos res; auto ores = StringSplitAndTrim(a_OreInfosString, "|"); for (const auto & ore: ores) { auto parts = StringSplitAndTrim(ore, ":"); if (parts.size() != 5) { LOGWARNING("Cannot parse ore information from string, not enough OreInfo members (exp 5, got %d). Offending item: \"%s\".", static_cast(parts.size()), ore.c_str() ); continue; } auto oreType = BlockStringToType(parts[0]); if (oreType < 0) { LOGWARNING("Cannot parse ore information from string, invalid OreType: \"%s\".", parts[0].c_str()); continue; } NIBBLETYPE oreMeta; int maxHeight, numNests, nestSize; if ( !StringToInteger(parts[1], oreMeta) || !StringToInteger(parts[2], maxHeight) || !StringToInteger(parts[3], numNests) || !StringToInteger(parts[4], nestSize) ) { LOGWARNING("Cannot parse ore information from string, invalid number in OreInfo \"%s\".", ore.c_str()); continue; } res.emplace_back(static_cast(oreType), oreMeta, maxHeight, numNests, nestSize); } // for i - split[] return res; } AString cFinishGenOres::OreInfosToString(const cFinishGenOres::OreInfos & a_OreInfos) { AString res; for (const auto & ore: a_OreInfos) { if (!res.empty()) { res.append(" | "); } res.append(fmt::format(FMT_STRING("{}:{}:{}:{}:{}"), ItemTypeToString(ore.m_BlockType), ore.m_BlockMeta, ore.m_MaxHeight, ore.m_NumNests, ore.m_NestSize )); } // for ore - a_OreInfos[] return res; } void cFinishGenOres::SetSeed(int a_Seed) { m_Noise.SetSeed(a_Seed); } //////////////////////////////////////////////////////////////////////////////// // cFinishGenOreNests: void cFinishGenOreNests::GenerateOre( cChunkDesc & a_ChunkDesc, BLOCKTYPE a_OreType, NIBBLETYPE a_OreMeta, int a_MaxHeight, int a_NumNests, int a_NestSize, int a_Seq ) { // This function generates several "nests" of ore, each nest consisting of number of ore blocks relatively adjacent to each other. // It does so by making a random XYZ walk and adding ore along the way in cuboids of different (random) sizes // Only "terraformable" blocks get replaced with ore, all other blocks stay (so the nest can actually be smaller than specified). // If there is an attempt to generate Emerald ores in a chunk with no mountains biome abort // There are just four points sampled to avoid searching all 16 * 16 blocks: if (a_OreType == E_BLOCK_EMERALD_ORE) { const auto BiomeSampleOne = a_ChunkDesc.GetBiome( 4, 4); const auto BiomeSampleTwo = a_ChunkDesc.GetBiome( 4, 12); const auto BiomeSampleThree = a_ChunkDesc.GetBiome(12, 4); const auto BiomeSampleFour = a_ChunkDesc.GetBiome(12, 12); if ( !IsBiomeMountain(BiomeSampleOne) && !IsBiomeMountain(BiomeSampleTwo) && !IsBiomeMountain(BiomeSampleThree) && !IsBiomeMountain(BiomeSampleFour) ) { return; } } // Gold ores are generated more often in Mesa-Type-Biomes: // https://minecraft.wiki/w/Gold_Ore if (a_OreType == E_BLOCK_GOLD_ORE) { const auto BiomeSampleOne = a_ChunkDesc.GetBiome( 4, 4); const auto BiomeSampleTwo = a_ChunkDesc.GetBiome( 4, 12); const auto BiomeSampleThree = a_ChunkDesc.GetBiome(12, 4); const auto BiomeSampleFour = a_ChunkDesc.GetBiome(12, 12); if ( IsBiomeMesa(BiomeSampleOne) || IsBiomeMesa(BiomeSampleTwo) || IsBiomeMesa(BiomeSampleThree) || IsBiomeMesa(BiomeSampleFour) ) { a_MaxHeight = 76; a_NumNests = 22; // 2 times default + 20 times mesa bonus } } if (a_OreType == E_BLOCK_SILVERFISH_EGG) { const auto BiomeSampleOne = a_ChunkDesc.GetBiome( 4, 4); const auto BiomeSampleTwo = a_ChunkDesc.GetBiome( 4, 12); const auto BiomeSampleThree = a_ChunkDesc.GetBiome(12, 4); const auto BiomeSampleFour = a_ChunkDesc.GetBiome(12, 12); if ( !IsBiomeMountain(BiomeSampleOne) && !IsBiomeMountain(BiomeSampleTwo) && !IsBiomeMountain(BiomeSampleThree) && !IsBiomeMountain(BiomeSampleFour) ) { return; } } auto chunkX = a_ChunkDesc.GetChunkX(); auto chunkZ = a_ChunkDesc.GetChunkZ(); auto & blockTypes = a_ChunkDesc.GetBlockTypes(); auto & blockMetas = a_ChunkDesc.GetBlockMetasUncompressed(); for (int i = 0; i < a_NumNests; i++) { int nestRnd = m_Noise.IntNoise3DInt(chunkX + i, a_Seq, chunkZ + 64 * i) / 8; int BaseX = nestRnd % cChunkDef::Width; nestRnd /= cChunkDef::Width; int BaseZ = nestRnd % cChunkDef::Width; nestRnd /= cChunkDef::Width; int BaseY = nestRnd % a_MaxHeight; nestRnd /= a_MaxHeight; int NestSize = a_NestSize + (nestRnd % (std::max(a_NestSize, 4) / 4)); // The actual nest size may be up to 1 / 4 larger int Num = 0; while (Num < NestSize) { // Put a cuboid around [BaseX, BaseY, BaseZ] int rnd = m_Noise.IntNoise3DInt(chunkX + 64 * i, 2 * a_Seq + Num, chunkZ + 32 * i) / 8; int xsize = rnd % 2; int ysize = (rnd / 4) % 2; int zsize = (rnd / 16) % 2; rnd >>= 8; for (int x = xsize; x >= 0; --x) { int BlockX = BaseX + x; if (!cChunkDef::IsValidWidth(BlockX)) { Num++; // So that the cycle finishes even if the base coords wander away from the chunk continue; } for (int y = ysize; y >= 0; --y) { int BlockY = BaseY + y; if (!cChunkDef::IsValidHeight({BlockX, BlockY, BaseZ})) { Num++; // So that the cycle finishes even if the base coords wander away from the chunk continue; } for (int z = zsize; z >= 0; --z) { int BlockZ = BaseZ + z; if (!cChunkDef::IsValidWidth(BlockZ)) { Num++; // So that the cycle finishes even if the base coords wander away from the chunk continue; } const auto Index = cChunkDef::MakeIndex(BlockX, BlockY, BlockZ); const auto blockType = blockTypes[Index]; if ((blockType == E_BLOCK_STONE) || (blockType == E_BLOCK_NETHERRACK)) { blockTypes[Index] = a_OreType; blockMetas[Index] = a_OreMeta; } Num++; } // for z } // for y } // for x // Move the base to a neighbor voxel switch (rnd % 4) { case 0: BaseX--; break; case 1: BaseX++; break; } switch ((rnd >> 3) % 4) { case 0: BaseY--; break; case 1: BaseY++; break; } switch ((rnd >> 6) % 4) { case 0: BaseZ--; break; case 1: BaseZ++; break; } } // while (Num < NumBlocks) } // for i - NumNests } //////////////////////////////////////////////////////////////////////////////// // cFinishGenOrePockets: void cFinishGenOrePockets::Initialize(cIniFile & a_IniFile, const AString & a_GenName) { // Read the OreInfos configuration: auto valueName = a_GenName + "Blocks"; auto pocketCfg = a_IniFile.GetValue("Generator", valueName, ""); if (pocketCfg.empty()) { // There's no config currently stored in the INI file. Store the defaults as the config: a_IniFile.SetValue("Generator", valueName, OreInfosToString(m_OreInfos)); } else { m_OreInfos = OreInfosFromString(pocketCfg); } // Read the optional seed configuration (but do not store the default): valueName = a_GenName + "Seed"; SetSeed(a_IniFile.GetValueI("Generator", valueName, m_Noise.GetSeed())); } void cFinishGenOrePockets::GenerateOre( cChunkDesc & a_ChunkDesc, BLOCKTYPE a_OreType, NIBBLETYPE a_OreMeta, int a_MaxHeight, int a_NumNests, int a_NestSize, int a_Seq ) { // This function generates several "pockets" of the specified ore // Each chunk can contain only pockets that are generated for that chunk, or for its XM / ZM neighbors. // Generate for the 3 neighbors in the XP / ZP direction as well, so that pockets crossing the boundaries are accounted for as well: int chunkZ = a_ChunkDesc.GetChunkZ(); int chunkX = a_ChunkDesc.GetChunkX(); imprintChunkOrePockets(chunkX - 1, chunkZ - 1, a_ChunkDesc, a_OreType, a_OreMeta, a_MaxHeight, a_NumNests, a_NestSize, a_Seq); imprintChunkOrePockets(chunkX - 1, chunkZ, a_ChunkDesc, a_OreType, a_OreMeta, a_MaxHeight, a_NumNests, a_NestSize, a_Seq); imprintChunkOrePockets(chunkX, chunkZ - 1, a_ChunkDesc, a_OreType, a_OreMeta, a_MaxHeight, a_NumNests, a_NestSize, a_Seq); imprintChunkOrePockets(chunkX, chunkZ, a_ChunkDesc, a_OreType, a_OreMeta, a_MaxHeight, a_NumNests, a_NestSize, a_Seq); } void cFinishGenOrePockets::imprintChunkOrePockets( int a_ChunkX, int a_ChunkZ, cChunkDesc & a_ChunkDesc, BLOCKTYPE a_OreType, NIBBLETYPE a_OreMeta, int a_MaxHeight, int a_NumNests, int a_NestSize, int a_Seq ) { // Pick a starting coord for each nest: int baseBlockX = a_ChunkX * cChunkDef::Width; int baseBlockZ = a_ChunkZ * cChunkDef::Width; for (int i = 0; i < a_NumNests; i++) { int nestRnd = m_Noise.IntNoise3DInt(a_ChunkX + i, a_Seq, a_ChunkZ + 64 * i) / 7; int baseX = (nestRnd % cChunkDef::Width) + baseBlockX; nestRnd /= cChunkDef::Width; int baseZ = (nestRnd % cChunkDef::Width) + baseBlockZ; nestRnd /= cChunkDef::Width; int baseY = nestRnd % a_MaxHeight; nestRnd /= a_MaxHeight; imprintPocket( a_ChunkDesc, baseX, baseY, baseZ, a_NestSize, i + 200 * a_Seq, a_OreType, a_OreMeta ); } // for i - NumNests } void cFinishGenOrePockets::imprintPocket( cChunkDesc & a_ChunkDesc, int a_MinPocketX, int a_PocketY, int a_MinPocketZ, int a_NestSize, int a_Seq, BLOCKTYPE a_OreType, NIBBLETYPE a_OreMeta ) { // A line segment in a random direction is chosen. Then, several spheres are formed along this line segment, // with their diameters diminishing towards the line ends (one half of a sinusoid) double x1 = static_cast(a_MinPocketX) + 0.5; double y1 = static_cast(a_PocketY) + 0.5; double z1 = static_cast(a_MinPocketZ) + 0.5; int rnd = m_Noise.IntNoise2DInt(a_MinPocketX + 7 * a_Seq, a_MinPocketZ + a_PocketY * 11) / 7; double angle = static_cast(rnd % 256) / (256.0 * M_PI / 2.0); // range [0 .. pi / 2] rnd /= 256; double length = static_cast(a_NestSize) / 4.0; double x2 = x1 + sin(angle) * length; // Always larger than x1 double z2 = z1 + cos(angle) * length; // Always larger than z1 double y2 = y1 + static_cast((rnd % 3) - 1); // Up to 1 block away from y1 // Iterate over the line segment in a total of a_NestSize steps: double stepX = (x2 - x1) / static_cast(a_NestSize); double stepY = (y2 - y1) / static_cast(a_NestSize); double stepZ = (z2 - z1) / static_cast(a_NestSize); double stepR = M_PI / static_cast(a_NestSize); double size = static_cast(a_NestSize) / 16.0; for (int i = 0; i < a_NestSize; ++i) { double iDbl = static_cast(i); double sphereX = x1 + stepX * iDbl; double sphereY = y1 + stepY * iDbl; double sphereZ = z1 + stepZ * iDbl; double radius = (sin(stepR * iDbl) + 1.0) * size + 1.0; imprintSphere(a_ChunkDesc, sphereX, sphereY, sphereZ, radius, a_OreType, a_OreMeta); } // for i } void cFinishGenOrePockets::imprintSphere( cChunkDesc & a_ChunkDesc, double a_SphereX, double a_SphereY, double a_SphereZ, double a_Radius, BLOCKTYPE a_OreType, NIBBLETYPE a_OreMeta ) { // Get the sphere's bounding box, unioned with the chunk's bounding box (possibly empty): int baseX = a_ChunkDesc.GetChunkX() * cChunkDef::Width; int baseZ = a_ChunkDesc.GetChunkZ() * cChunkDef::Width; int minX = std::max(FloorC(a_SphereX - a_Radius), baseX); int minY = std::max(FloorC(a_SphereY - a_Radius), 0); int minZ = std::max(FloorC(a_SphereZ - a_Radius), baseZ); int maxX = std::min(CeilC(a_SphereX + a_Radius), baseX + cChunkDef::Width - 1); int maxY = std::min(CeilC(a_SphereY + a_Radius), cChunkDef::Height - 1); int maxZ = std::min(CeilC(a_SphereZ + a_Radius), baseZ + cChunkDef::Width - 1); /* // DEBUG: int blockX = FloorC(a_SphereX); int blockY = FloorC(a_SphereY); int blockZ = FloorC(a_SphereZ); if ( (blockX >= baseX) && (blockX < baseX + cChunkDef::Width) && (blockY >= 0) && (blockY < cChunkDef::Height) && (blockZ >= baseZ) && (blockZ < baseZ + cChunkDef::Width) ) { // FLOGD("Imprinting a sphere center at {0}", Vector3i{blockX, blockY, blockZ}); a_ChunkDesc.SetBlockTypeMeta(blockX - baseX, blockY, blockZ - baseZ, a_OreType, a_OreMeta); } return; //*/ // Imprint the parts of the sphere intersecting the chunk: double radiusSq = a_Radius * a_Radius / 4.0; for (int y = minY; y <= maxY; y++) { double relY = static_cast(y) + 0.5 - a_SphereY; double relYSq = relY * relY; if (relYSq > radiusSq) { // outside the sphere, bail out continue; } for (int z = minZ; z <= maxZ; z++) { double relZ = static_cast(z) + 0.5 - a_SphereZ; double relZSq = relZ * relZ; if (relZSq + relYSq > radiusSq) { // outside the sphere, bail out continue; } for (int x = minX; x <= maxX; x++) { double relX = static_cast(x) + 0.5 - a_SphereX; double relXSq = relX * relX; if (relZSq + relYSq + relXSq > radiusSq) { // outside the sphere, bail out continue; } int bX = x - baseX; int bZ = z - baseZ; auto blockType = a_ChunkDesc.GetBlockType(bX, y, bZ); if ((blockType == E_BLOCK_STONE) || (blockType == E_BLOCK_NETHERRACK)) { a_ChunkDesc.SetBlockTypeMeta(bX, y, bZ, a_OreType, a_OreMeta); } } // for x } // for z } // for y } cFinishGenForestRocks::cFinishGenForestRocks(int a_Seed, cIniFile & a_IniFile) : m_Noise(a_Seed) { } void cFinishGenForestRocks::GenFinish(cChunkDesc & a_ChunkDesc) { // Choose random position in chunk and place boulder around it auto Pos = Vector3i( m_Noise.IntNoise2DInt(a_ChunkDesc.GetChunkX(), a_ChunkDesc.GetChunkZ()) % cChunkDef::Width, 0, m_Noise.IntNoise2DInt(a_ChunkDesc.GetChunkX(), a_ChunkDesc.GetChunkZ()) % cChunkDef::Width ); Pos.y = a_ChunkDesc.GetHeight(Pos.x, Pos.z) % cChunkDef::Height; auto Biome = a_ChunkDesc.GetBiome(Pos.x, Pos.z); if ((Biome != biMegaTaiga) && (Biome != biMegaTaigaHills)) { return; } // Determines the size of the boulder const int TwoLimit = 70; const int ThreeLimit = 90; auto RadiusChance = m_Noise.IntNoise2DInt(a_ChunkDesc.GetChunkX(), a_ChunkDesc.GetChunkZ()) % 100; int Radius = 1; if (RadiusChance > TwoLimit && RadiusChance <= ThreeLimit) { Radius = 2; } else if (RadiusChance > ThreeLimit) { Radius = 3; } Pos.x = Clamp(Pos.x, Radius, cChunkDef::Width - Radius - 1); Pos.z = Clamp(Pos.z, Radius, cChunkDef::Width - Radius - 1); auto StartBlock = a_ChunkDesc.GetBlockType(Pos.x, Pos.y, Pos.z); while (!((StartBlock == E_BLOCK_DIRT) || (StartBlock == E_BLOCK_GRASS))) { Pos.y -= 1; if (!cChunkDef::IsValidRelPos(Pos.addedY(-Radius))) { return; } StartBlock = a_ChunkDesc.GetBlockType(Pos.x, Pos.y, Pos.z); } Pos.y -= Radius - 1; // Pos.y = Clamp(Pos.y - m_Noise.IntNoise2DInt(a_ChunkDesc.GetChunkX(), a_ChunkDesc.GetChunkZ()) % Radius + 1, 0, cChunkDef::Height); for (int x = -Radius; x <= Radius; x++) { for (int y = -Radius; y <= Radius; y++) { for (int z = -Radius; z <= Radius; z++) { if (!cChunkDef::IsValidRelPos({ Pos.x + x, Pos.y + y, Pos.z + z })) { continue; } if (Vector3d(x, y, z).SqrLength() > Radius * Radius + 1) { continue; } a_ChunkDesc.SetBlockTypeMeta(Pos.x + x, Pos.y + y, Pos.z + z, E_BLOCK_MOSSY_COBBLESTONE, 0); } } } } ================================================ FILE: src/Generating/FinishGen.h ================================================ // FinishGen.h /* Interfaces to the various finishing generators: - cFinishGenSnow - cFinishGenIce - cFinishGenSprinkleFoliage - cFinishGenLilypads - cFinishGenBottomLava - cFinishGenPreSimulator - cFinishGenDeadBushes */ #pragma once #include "ComposableGenerator.h" #include "../Noise/Noise.h" #include "../ProbabDistrib.h" #include "../Mobs/Monster.h" class cFinishGenSnow : public cFinishGen { protected: // cFinishGen override: virtual void GenFinish(cChunkDesc & a_ChunkDesc) override; } ; class cFinishGenIce : public cFinishGen { protected: // cFinishGen override: virtual void GenFinish(cChunkDesc & a_ChunkDesc) override; } ; class cFinishGenNetherClumpFoliage : public cFinishGen { public: cFinishGenNetherClumpFoliage(int a_Seed) : m_Noise(a_Seed), m_Seed(a_Seed) { } protected: cNoise m_Noise; int m_Seed; void TryPlaceClump(cChunkDesc & a_ChunkDesc, int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_Block); virtual void GenFinish(cChunkDesc & a_ChunkDesc) override; } ; class cFinishGenClumpTopBlock : public cFinishGen { public: // Contains the meta, type and weight for a clump block struct FoliageInfo { BLOCKTYPE m_BlockType; NIBBLETYPE m_BlockMeta; int m_Weight; FoliageInfo(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_Weight) : m_BlockType(a_BlockType), m_BlockMeta(a_BlockMeta), m_Weight(a_Weight) {} }; // Contains the minimum and maximum amount of clumps for a biome and it's blocks. struct BiomeInfo { int m_MinNumClumpsPerChunk; int m_MaxNumClumpsPerChunk; std::vector m_Blocks; BiomeInfo() : m_MinNumClumpsPerChunk(0), m_MaxNumClumpsPerChunk(2), m_Blocks() {} BiomeInfo(int a_MinNumClumpsPerChunk, int a_MaxNumClumpsPerChunk, std::vector a_Blocks) : m_MinNumClumpsPerChunk(a_MinNumClumpsPerChunk), m_MaxNumClumpsPerChunk(a_MaxNumClumpsPerChunk), m_Blocks(std::move(a_Blocks)) {} }; cFinishGenClumpTopBlock(int a_Seed, std::vector a_BlockList) : m_Noise(a_Seed), m_FlowersPerBiome() { std::swap(a_BlockList, m_FlowersPerBiome); } /** Parses a string and puts a vector with a length of biMaxVariantBiome in a_Output. The format of the string is ";". This can also be repeated with a | */ static void ParseConfigurationString(const AString & a_String, std::vector & a_Output); /** Parses an inifile in search for all clumps */ static std::vector ParseIniFile(cIniFile & a_IniFile, const AString & a_ClumpPrefix); protected: cNoise m_Noise; std::vector m_FlowersPerBiome; /** The maximum number of foliage per clump */ const int MAX_NUM_FOLIAGE = 8; /** The minimum number of foliage per clump */ const int MIN_NUM_FOLIAGE = 4; /** The maximum range a foliage can be placed from the center of the clump */ const int RANGE_FROM_CENTER = 5; void TryPlaceFoliageClump(cChunkDesc & a_ChunkDesc, int a_RelX, int a_RelZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, bool a_IsDoubleTall); virtual void GenFinish(cChunkDesc & a_ChunkDesc) override; }; class cFinishGenGlowStone : public cFinishGen { public: cFinishGenGlowStone(int a_Seed) : m_Noise(a_Seed), m_Seed(a_Seed) { } protected: cNoise m_Noise; int m_Seed; void TryPlaceGlowstone(cChunkDesc & a_ChunkDesc, int a_RelX, int a_RelY, int a_RelZ, int a_Size, int a_NumStrings); virtual void GenFinish(cChunkDesc & a_ChunkDesc) override; } ; class cFinishGenTallGrass : public cFinishGen { public: cFinishGenTallGrass(int a_Seed) : m_Noise(a_Seed), m_Seed(a_Seed) {} protected: cNoise m_Noise; int m_Seed; // cFinishGen override: virtual void GenFinish(cChunkDesc & a_ChunkDesc) override; static bool CanFernGrow(EMCSBiome a_Biome); static bool CanLargeFernGrow(EMCSBiome a_Biome); static int GetBiomeDensity(EMCSBiome a_Biome); static bool CanGrassGrow(EMCSBiome a_Biome); }; class cFinishGenVines : public cFinishGen { public: cFinishGenVines(int a_Seed, int a_Level) : m_Noise(a_Seed), m_Level(a_Level) { } bool IsJungleVariant(EMCSBiome a_Biome); protected: cNoise m_Noise; int m_Level; virtual void GenFinish(cChunkDesc & a_ChunkDesc) override; }; class cFinishGenSoulsandRims : public cFinishGen { public: cFinishGenSoulsandRims(int a_Seed) : m_Noise(a_Seed) { } protected: cNoise m_Noise; virtual void GenFinish(cChunkDesc & a_ChunkDesc) override; } ; class cFinishGenSprinkleFoliage : public cFinishGen { public: cFinishGenSprinkleFoliage(int a_Seed, int a_MaxCactusHeight, int a_MaxSugarcaneHeight): m_Noise(a_Seed), m_Seed(a_Seed), m_MaxCactusHeight(a_MaxCactusHeight), m_MaxSugarcaneHeight(a_MaxSugarcaneHeight) { } protected: cNoise m_Noise; int m_Seed; int m_MaxCactusHeight; int m_MaxSugarcaneHeight; /** Tries to place sugarcane at the coords specified, returns true if successful, updates the top variable (hence the & a_RefY) */ bool TryAddSugarcane(cChunkDesc & a_ChunkDesc, int a_RelX, HEIGHTTYPE & a_RelY, int a_RelZ); /** Tries to place cactus at the coords specified, returns true if successful, updates the top variable (hence the & a_RefY) */ bool TryAddCactus(cChunkDesc & a_ChunkDesc, int a_RelX, HEIGHTTYPE & a_RelY, int a_RelZ); // Returns true is the specified biome is a desert or its variant static bool IsDesertVariant(EMCSBiome a_biome); // cFinishGen override: virtual void GenFinish(cChunkDesc & a_ChunkDesc) override; } ; /** This class adds a single top block in random positions in the specified biome on top of specified allowed blocks. Used for: - Lilypads finisher - DeadBushes finisher */ class cFinishGenSingleTopBlock : public cFinishGen { public: typedef std::vector BlockList; bool m_IsAllowedBelow[256]; typedef std::vector BiomeList; bool m_IsBiomeAllowed[256]; cFinishGenSingleTopBlock( int a_Seed, BLOCKTYPE a_BlockType, BiomeList a_Biomes, int a_Amount, BlockList a_AllowedBelow ) : m_Noise(a_Seed), m_BlockType(a_BlockType), m_Amount(a_Amount) { // Initialize all the block types. for (size_t idx = 0; idx < ARRAYCOUNT(m_IsAllowedBelow); ++idx) { m_IsAllowedBelow[idx] = false; } // Load the allowed blocks into m_IsAllowedBelow for (BlockList::iterator itr = a_AllowedBelow.begin(); itr != a_AllowedBelow.end(); ++itr) { m_IsAllowedBelow[*itr] = true; } // Initialize all the biome types. for (size_t idx = 0; idx < ARRAYCOUNT(m_IsBiomeAllowed); ++idx) { m_IsBiomeAllowed[idx] = false; } // Load the allowed biomes into m_IsBiomeAllowed for (BiomeList::iterator itr = a_Biomes.begin(); itr != a_Biomes.end(); ++itr) { m_IsBiomeAllowed[*itr] = true; } } protected: cNoise m_Noise; BLOCKTYPE m_BlockType; /** Relative amount of blocks to try adding. 1 = one block per 256 biome columns. */ int m_Amount; int GetNumToGen(const cChunkDef::BiomeMap & a_BiomeMap); /** Returns true if the given biome is a biome that is allowed. */ inline bool IsAllowedBiome(EMCSBiome a_Biome) { return m_IsBiomeAllowed[a_Biome]; } /** Returns true if the given blocktype may be below m_BlockType */ inline bool IsAllowedBlockBelow(BLOCKTYPE a_BlockBelow) { return m_IsAllowedBelow[a_BlockBelow]; } // cFinishGen override: virtual void GenFinish(cChunkDesc & a_ChunkDesc) override; } ; class cFinishGenBottomLava : public cFinishGen { public: cFinishGenBottomLava(int a_Level) : m_Level(a_Level) { } int GetLevel(void) const { return m_Level; } protected: int m_Level; // cFinishGen override: virtual void GenFinish(cChunkDesc & a_ChunkDesc) override; } ; class cFinishGenPreSimulator : public cFinishGen { public: cFinishGenPreSimulator(bool a_PreSimulateFallingBlocks, bool a_PreSimulateWater, bool a_PreSimulateLava); protected: bool m_PreSimulateFallingBlocks; bool m_PreSimulateWater; bool m_PreSimulateLava; /** Drops hanging sand and gravel down to the ground, recalculates heightmap */ void CollapseSandGravel(cChunkDesc & a_ChunkDesc); /** For each fluid block: - if all surroundings are of the same fluid, makes it stationary; otherwise makes it flowing (excl. top) - all fluid on the chunk's edge is made flowing */ void StationarizeFluid( cChunkDef::BlockTypes & a_BlockTypes, // Block types to read and change cChunkDef::HeightMap & a_HeightMap, // Height map to read BLOCKTYPE a_Fluid, BLOCKTYPE a_StationaryFluid ); // cFinishGen override: virtual void GenFinish(cChunkDesc & a_ChunkDesc) override; } ; class cFinishGenFluidSprings : public cFinishGen { public: cFinishGenFluidSprings(int a_Seed, BLOCKTYPE a_Fluid, cIniFile & a_IniFile, eDimension a_Dimension); protected: cNoise m_Noise; cProbabDistrib m_HeightDistribution; BLOCKTYPE m_Fluid; int m_Chance; ///< Chance, [0..100], that a spring will be generated in a chunk // cFinishGen override: virtual void GenFinish(cChunkDesc & a_ChunkDesc) override; /** Tries to place a spring at the specified coords, checks neighbors. Returns true if successful. */ bool TryPlaceSpring(cChunkDesc & a_ChunkDesc, int x, int y, int z); } ; /** This class populates generated chunks with packs of biome-dependant animals Animals: cows, sheep, pigs, mooshrooms, squid, horses, wolves, ocelots */ class cFinishGenPassiveMobs : public cFinishGen { public: cFinishGenPassiveMobs(int a_Seed, cIniFile & a_IniFile, eDimension a_Dimension); protected: /** The noise used as the source of randomness */ cNoise m_Noise; /** Chance, [0..100], that an animal pack will be generated in a chunk */ int m_AnimalProbability; // cFinishGen override: virtual void GenFinish(cChunkDesc & a_ChunkDesc) override; /** Returns false if an animal cannot spawn at given coords, else adds it to the chunk's entity list and returns true */ bool TrySpawnAnimals(cChunkDesc & a_ChunkDesc, int x, int y, int z, eMonsterType AnimalToSpawn); /** Picks a random animal from biome-dependant list for a random position in the chunk. Returns the chosen mob type, or mtInvalid if no mob chosen. */ eMonsterType GetRandomMob(cChunkDesc & a_ChunkDesc); } ; /** Base class for generators that have an ore list attached to them. Provides the storage and parsing for the ore list, as well as the generic plumbing for generating individual ores. Descendants should override GenerateOre() to provide the specific ore generation technique. Note that this class uses the "Nest" terminology for individual packs of ore, it doesn't imply any shape or algorithm. */ class cFinishGenOres: public cFinishGen { using Super = cFinishGen; public: struct OreInfo { BLOCKTYPE m_BlockType; // The type of the nest. NIBBLETYPE m_BlockMeta; // The block meta int m_MaxHeight; // The highest possible a nest can occur int m_NumNests; // How many nests per chunk int m_NestSize; // The amount of blocks a nest can have. OreInfo() : m_BlockType(0), m_BlockMeta(0), m_MaxHeight(0), m_NumNests(0), m_NestSize(0) { } OreInfo(BLOCKTYPE a_OreType, NIBBLETYPE a_OreMeta, int a_MaxHeight, int a_NumNests, int a_NestSize) : m_BlockType(a_OreType), m_BlockMeta(a_OreMeta), m_MaxHeight(a_MaxHeight), m_NumNests(a_NumNests), m_NestSize(a_NestSize) { } }; typedef std::vector OreInfos; cFinishGenOres(int a_Seed, const OreInfos & a_OreInfos): m_Noise(a_Seed), m_OreInfos(a_OreInfos) { } // cFinishGen overrides: virtual void GenFinish(cChunkDesc & a_ChunkDesc) override; /** Returns a vector of OreInfo structures describing the default Overworld ores, usable in the constructor. */ static const OreInfos & DefaultOverworldOres(void); /** Returns a vector of OreInfo structures describing the default Nether ores, usable in the constructor. */ static const OreInfos & DefaultNetherOres(void); /** Returns a vector of OreInfo structures describing the default Overworld non-ore pockets (dirt, diorite etc), usable in the constructor. */ static const OreInfos & DefaultNaturalPatches(void); /** Parses the parameter string into OreInfos array. See OreInfosToString() for the complementary function. Used for loading configuration from INI files. */ static OreInfos OreInfosFromString(const AString & a_OreInfosString); /** Returns a string that represents the OreInfos given as the parameter. See OreInfosFromString() for the complementary function. Used for storing defaults in the INI file. */ static AString OreInfosToString(const OreInfos & a_OreInfos); /** (Re-)sets the seed used by the internal generating mechanisms. */ void SetSeed(int a_Seed); protected: /** The noise used for generating. */ cNoise m_Noise; /** All the ores enabled in this generator. */ OreInfos m_OreInfos; /** Generates a single ore in the specified chunk image. a_Seq is the sequencing number (used as a complement to seed to make each ore in the same chunk have different nests) */ virtual void GenerateOre( cChunkDesc & a_ChunkDesc, BLOCKTYPE a_OreType, NIBBLETYPE a_OreMeta, int a_MaxHeight, int a_NumNests, int a_NestSize, int a_Seq ) = 0; // TODO: Helper function to parse a config string into m_OreInfos }; class cFinishGenOreNests: public cFinishGenOres { using Super = cFinishGenOres; public: cFinishGenOreNests(int a_Seed, const OreInfos & a_OreInfos): Super(a_Seed, a_OreInfos) {} protected: // cFinishGenOreClumps overrides: virtual void GenerateOre( cChunkDesc & a_ChunkDesc, BLOCKTYPE a_OreType, NIBBLETYPE a_OreMeta, int a_MaxHeight, int a_NumNests, int a_NestSize, int a_Seq ) override; } ; class cFinishGenOrePockets: public cFinishGenOres { using Super = cFinishGenOres; public: cFinishGenOrePockets(int a_Seed, const OreInfos & a_OreInfos): Super(a_Seed, a_OreInfos) {} /** Reads the configuration from the specified INI file. a_GenName is the name of the generator (this class may be used for OrePockets and DirtPockets, each has a different default). */ void Initialize(cIniFile & a_IniFile, const AString & a_GenName); protected: // cFinishGenOreClumps overrides: virtual void GenerateOre( cChunkDesc & a_ChunkDesc, BLOCKTYPE a_OreType, NIBBLETYPE a_OreMeta, int a_MaxNestHeight, int a_NumNests, int a_NestSize, int a_Seq ) override; /** Calculates the pockets for the specified chunk and imprints them into the specified ChunkDesc (not necessarily the same chunk). a_Seq is the sequence number of the ore, to provide another source of randomness. */ void imprintChunkOrePockets( int a_ChunkX, int a_ChunkZ, cChunkDesc & a_ChunkDesc, BLOCKTYPE a_OreType, NIBBLETYPE a_OreMeta, int a_MaxHeight, int a_NumNests, int a_NestSize, int a_Seq ); /** Imprints a single pocket of the specified ore at the specified coords into the chunk. The pocket shape has its minimum X and Z coords specified, Y can be anywhere around the specified Y coord. a_Seq is the sequence number of the ore, to provide another source of randomness. */ void imprintPocket( cChunkDesc & a_ChunkDesc, int a_MinPocketX, int a_PocketY, int a_MinPocketZ, int a_NestSize, int a_Seq, BLOCKTYPE a_OreType, NIBBLETYPE a_OreMeta ); /** Imprints a single sphere of the specified ore at the specified coords. */ void imprintSphere( cChunkDesc & a_ChunkDesc, double a_SphereX, double a_SphereY, double a_SphereZ, double a_Radius, BLOCKTYPE a_OreType, NIBBLETYPE a_OreMeta ); }; class cFinishGenForestRocks: public cFinishGen { public: cFinishGenForestRocks(int a_Seed, cIniFile & a_IniFile); virtual void GenFinish(cChunkDesc & a_ChunkDesc) override; private: cNoise m_Noise; }; ================================================ FILE: src/Generating/GridStructGen.cpp ================================================ // GridStructGen.cpp // Implements the cGridStructGen class representing a common base class for structure generators that place structures in a semi-random grid #include "Globals.h" #include "GridStructGen.h" //////////////////////////////////////////////////////////////////////////////// // cEmptyStructure: /** A cStructure descendant representing an empty structure. Used when the generator descended from cGridStructGen doesn't return any structure, to keep at least the Origin coords so that the structure isn't queried over and over again. */ class cEmptyStructure: public cGridStructGen::cStructure { using Super = cGridStructGen::cStructure; public: cEmptyStructure(int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ) : Super(a_GridX, a_GridZ, a_OriginX, a_OriginZ) { } protected: virtual void DrawIntoChunk(cChunkDesc & a_ChunkDesc) override { // Do nothing } } ; cGridStructGen::cGridStructGen( int a_Seed, int a_GridSizeX, int a_GridSizeZ, int a_MaxOffsetX, int a_MaxOffsetZ, int a_MaxStructureSizeX, int a_MaxStructureSizeZ, size_t a_MaxCacheSize ) : m_Seed(a_Seed), m_Noise(a_Seed), m_GridSizeX(a_GridSizeX), m_GridSizeZ(a_GridSizeZ), m_MaxOffsetX(a_MaxOffsetX), m_MaxOffsetZ(a_MaxOffsetZ), m_MaxStructureSizeX(a_MaxStructureSizeX), m_MaxStructureSizeZ(a_MaxStructureSizeZ), m_MaxCacheSize(a_MaxCacheSize) { if (m_GridSizeX == 0) { LOG("Grid Size cannot be zero, setting to 1"); m_GridSizeX = 1; } if (m_GridSizeZ == 0) { LOG("Grid Size cannot be zero, setting to 1"); m_GridSizeZ = 1; } size_t NumStructuresPerQuery = static_cast(((m_MaxStructureSizeX + m_MaxOffsetX) / m_GridSizeX + 1) * ((m_MaxStructureSizeZ + m_MaxOffsetZ) / m_GridSizeZ + 1)); if (NumStructuresPerQuery > m_MaxCacheSize) { m_MaxCacheSize = NumStructuresPerQuery * 4; LOGINFO( "cGridStructGen: The cache size is too small (%u), increasing the cache size to %u to avoid inefficiency.", static_cast(a_MaxCacheSize), static_cast(m_MaxCacheSize) ); } } cGridStructGen::cGridStructGen(int a_Seed): m_BaseSeed(a_Seed), m_Seed(a_Seed), m_Noise(a_Seed), m_GridSizeX(256), m_GridSizeZ(256), m_MaxOffsetX(128), m_MaxOffsetZ(128), m_MaxStructureSizeX(128), m_MaxStructureSizeZ(128), m_MaxCacheSize(256) { } void cGridStructGen::SetGeneratorParams(const AStringMap & a_GeneratorParams) { ASSERT(m_Cache.empty()); // No changing the params after chunks are generated m_GridSizeX = GetStringMapInteger (a_GeneratorParams, "GridSizeX", m_GridSizeX); m_GridSizeZ = GetStringMapInteger (a_GeneratorParams, "GridSizeZ", m_GridSizeZ); m_MaxOffsetX = GetStringMapInteger (a_GeneratorParams, "MaxOffsetX", m_MaxOffsetX); m_MaxOffsetZ = GetStringMapInteger (a_GeneratorParams, "MaxOffsetZ", m_MaxOffsetZ); m_MaxStructureSizeX = GetStringMapInteger (a_GeneratorParams, "MaxStructureSizeX", m_MaxStructureSizeX); m_MaxStructureSizeZ = GetStringMapInteger (a_GeneratorParams, "MaxStructureSizeZ", m_MaxStructureSizeZ); m_MaxCacheSize = GetStringMapInteger(a_GeneratorParams, "MaxCacheSize", m_MaxCacheSize); // Silently fix out-of-range parameters: if (m_MaxOffsetX < 1) { m_MaxOffsetX = 1; } if (m_MaxOffsetZ < 1) { m_MaxOffsetZ = 1; } // Set the seed based on the seed offset from the parameters: auto seedOffset = GetStringMapInteger(a_GeneratorParams, "SeedOffset", 0); m_Seed = m_BaseSeed + seedOffset; m_Noise.SetSeed(m_Seed); } void cGridStructGen::GetStructuresForChunk(int a_ChunkX, int a_ChunkZ, cStructurePtrs & a_Structures) { // Calculate the min and max grid coords of the structures to be returned: int MinBlockX = a_ChunkX * cChunkDef::Width - m_MaxStructureSizeX - m_MaxOffsetX; int MinBlockZ = a_ChunkZ * cChunkDef::Width - m_MaxStructureSizeZ - m_MaxOffsetZ; int MaxBlockX = a_ChunkX * cChunkDef::Width + m_MaxStructureSizeX + m_MaxOffsetX + cChunkDef::Width - 1; int MaxBlockZ = a_ChunkZ * cChunkDef::Width + m_MaxStructureSizeZ + m_MaxOffsetZ + cChunkDef::Width - 1; int MinGridX = MinBlockX / m_GridSizeX; int MinGridZ = MinBlockZ / m_GridSizeZ; int MaxGridX = (MaxBlockX + m_GridSizeX - 1) / m_GridSizeX; int MaxGridZ = (MaxBlockZ + m_GridSizeZ - 1) / m_GridSizeZ; int MinX = MinGridX * m_GridSizeX; int MaxX = MaxGridX * m_GridSizeX; int MinZ = MinGridZ * m_GridSizeZ; int MaxZ = MaxGridZ * m_GridSizeZ; // Walk the cache, move each structure that we want into a_Structures: for (cStructurePtrs::iterator itr = m_Cache.begin(), end = m_Cache.end(); itr != end;) { if ( ((*itr)->m_GridX >= MinX) && ((*itr)->m_GridX < MaxX) && ((*itr)->m_GridZ >= MinZ) && ((*itr)->m_GridZ < MaxZ) ) { // want a_Structures.push_back(*itr); itr = m_Cache.erase(itr); } else { // don't want ++itr; } } // for itr - m_Cache[] // Create those structures that haven't been in the cache: for (int x = MinGridX; x < MaxGridX; x++) { int GridX = x * m_GridSizeX; for (int z = MinGridZ; z < MaxGridZ; z++) { int GridZ = z * m_GridSizeZ; bool Found = false; for (cStructurePtrs::const_iterator itr = a_Structures.begin(), end = a_Structures.end(); itr != end; ++itr) { if (((*itr)->m_GridX == GridX) && ((*itr)->m_GridZ == GridZ)) { Found = true; break; } } // for itr - a_Structures[] if (!Found) { int OriginX = GridX + ((m_Noise.IntNoise2DInt(GridX + 3, GridZ + 5) / 7) % (m_MaxOffsetX * 2)) - m_MaxOffsetX; int OriginZ = GridZ + ((m_Noise.IntNoise2DInt(GridX + 5, GridZ + 3) / 7) % (m_MaxOffsetZ * 2)) - m_MaxOffsetZ; cStructurePtr Structure = CreateStructure(GridX, GridZ, OriginX, OriginZ); if (Structure.get() == nullptr) { Structure.reset(new cEmptyStructure(GridX, GridZ, OriginX, OriginZ)); } a_Structures.push_back(Structure); } } // for z } // for x // Copy a_Forts into m_Cache to the beginning: cStructurePtrs StructuresCopy (a_Structures); m_Cache.splice(m_Cache.begin(), StructuresCopy, StructuresCopy.begin(), StructuresCopy.end()); // Trim the cache if it's too long: size_t CacheSize = 0; for (cStructurePtrs::iterator itr = m_Cache.begin(), end = m_Cache.end(); itr != end; ++itr) { CacheSize += (*itr)->GetCacheCost(); if (CacheSize > m_MaxCacheSize) { // Erase all items from this one till the cache end m_Cache.erase(itr, m_Cache.end()); break; } } } void cGridStructGen::GenFinish(cChunkDesc & a_ChunkDesc) { int ChunkX = a_ChunkDesc.GetChunkX(); int ChunkZ = a_ChunkDesc.GetChunkZ(); cStructurePtrs Structures; GetStructuresForChunk(ChunkX, ChunkZ, Structures); for (cStructurePtrs::const_iterator itr = Structures.begin(); itr != Structures.end(); ++itr) { (*itr)->DrawIntoChunk(a_ChunkDesc); } // for itr - Structures[] } ================================================ FILE: src/Generating/GridStructGen.h ================================================ // GridStructGen.h // Declares the cGridStructGen class representing a common base class for structure generators that place structures in a semi-random grid #pragma once #include "ComposableGenerator.h" #include "../Noise/Noise.h" /** Generates structures in a semi-random grid. Defines a grid in the XZ space with predefined cell size in each direction. Each cell then receives exactly one structure (provided by the descendant class). The structure is placed within the cell, but doesn't need to be bounded by the cell, it can be well outside the cell; the generator uses the MaxStructureSize parameter to determine how far away from the cell the structure can be at most. Each structure has an offset from the grid's center point, the offset is generated randomly from a range given to this class as a parameter. Each structure thus contains the coords of its grid center (m_GridX, m_GridZ) and the actual origin from which it's built (m_OriginX, m_OriginZ). This class provides a cache for the structures generated for successive chunks and manages that cache. It also provides the cFinishGen override that uses the cache to actually generate the structure into chunk data. After generating each chunk the cache is checked for size, each item in the cache has a cost associated with it and the cache is trimmed (from its least-recently-used end) so that the sum of the cost in the cache is less than m_MaxCacheSize To use this class, declare a descendant class that implements the overridable methods, then create an instance of that class. The descendant must provide the CreateStructure() function that is called to generate a structure at the specific grid cell. The descendant must use a specific cStructure descendant to provide the actual structure that gets generated. The structure must provide the DrawIntoChunk() function that generates the structure into the chunk data, and can override the GetCacheCost() function that returns the cost of that structure in the cache. */ class cGridStructGen : public cFinishGen { public: /** Represents a single structure that occupies the grid point. Knows how to draw itself into a chunk. */ class cStructure { public: /** The grid point for which the structure is generated. */ int m_GridX, m_GridZ; /** The origin (the coords for which the structure is generated) */ int m_OriginX, m_OriginZ; /** Creates a structure that has its origin set at the specified coords. */ cStructure (int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ) : m_GridX(a_GridX), m_GridZ(a_GridZ), m_OriginX(a_OriginX), m_OriginZ(a_OriginZ) { } // Force a virtual destructor in descendants: virtual ~cStructure() {} /** Draws self into the specified chunk */ virtual void DrawIntoChunk(cChunkDesc & a_ChunkDesc) = 0; /** Returns the cost of keeping this structure in the cache */ virtual size_t GetCacheCost(void) const { return 1; } } ; typedef std::shared_ptr cStructurePtr; typedef std::list cStructurePtrs; cGridStructGen( int a_Seed, int a_GridSizeX, int a_GridSizeZ, int a_MaxOffsetX, int a_MaxOffsetZ, int a_MaxStructureSizeX, int a_MaxStructureSizeZ, size_t a_MaxCacheSize ); /** Creates a new instance that has the generation parameters set to defaults. This is used for instances that are later loaded from a file. */ cGridStructGen(int a_Seed); /** Sets the generator params based on the dictionary passed in. Note that this must not be called anymore after generating a chunk. */ void SetGeneratorParams(const AStringMap & a_GeneratorParams); // cFinishGen override: virtual void GenFinish(cChunkDesc & a_ChunkDesc) override; protected: /** Base seed of the world for which the generator generates chunk. */ int m_BaseSeed; /** Seed for generating grid offsets and also available for descendants. Calculated from m_BaseSeed by adding the SeedOffset parameter loaded from the cubeset file (if applicable); otherwise the same as m_BaseSeed. */ int m_Seed; /** The noise used for generating grid offsets. */ cNoise m_Noise; /** The size of each grid's cell in the X axis */ int m_GridSizeX; /** The size of each grid's cell in the Z axis */ int m_GridSizeZ; /** The maximum offset of the structure's origin from the grid midpoint, in X coord. */ int m_MaxOffsetX; /** The maximum offset of the structure's origin from the grid midpoint, in Z coord. */ int m_MaxOffsetZ; /** Maximum theoretical size of the structure in the X axis. This limits the structures considered for a single chunk, so the lesser the number, the better performance. Structures large than this may get cropped. */ int m_MaxStructureSizeX; /** Maximum theoretical size of the structure in the Z axis. This limits the structures considered for a single chunk, so the lesser the number, the better performance. Structures large than this may get cropped. */ int m_MaxStructureSizeZ; /** Maximum allowed sum of costs for items in the cache. Items that are over this cost are removed from the cache, oldest-first */ size_t m_MaxCacheSize; /** Cache for the most recently generated structures, ordered by the recentness. */ cStructurePtrs m_Cache; /** Clears everything from the cache */ void ClearCache(void); /** Returns all structures that may intersect the given chunk. The structures are considered as intersecting iff their bounding box (defined by m_MaxStructureSize) around their gridpoint intersects the chunk. */ void GetStructuresForChunk(int a_ChunkX, int a_ChunkZ, cStructurePtrs & a_Structures); // Functions for the descendants to override: /** Create a new structure at the specified gridpoint */ virtual cStructurePtr CreateStructure(int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ) = 0; } ; ================================================ FILE: src/Generating/HeiGen.cpp ================================================ // HeiGen.cpp // Implements the various terrain height generators #include "Globals.h" #include "HeiGen.h" #include "../LinearUpscale.h" #include "../IniFile.h" #include "DistortedHeightmap.h" #include "EndGen.h" #include "Noise3DGenerator.h" #include "ProtIntGen.h" //////////////////////////////////////////////////////////////////////////////// // cHeiGenSteppy: class cHeiGenSteppy: public cTerrainHeightGen { public: cHeiGenSteppy(int a_Seed) : m_Seed(a_Seed) { m_Gen = std::make_shared>( std::make_shared (a_Seed + 1, std::make_shared (a_Seed + 2, std::make_shared (a_Seed + 3, std::make_shared (a_Seed + 4, std::make_shared (a_Seed + 5, 1, std::make_shared (a_Seed + 6, std::make_shared (a_Seed + 7, std::make_shared (a_Seed + 8, 60, std::make_shared (a_Seed + 9, 1, std::make_shared (a_Seed + 1, std::make_shared (a_Seed + 2, std::make_shared (a_Seed + 3, 60, std::make_shared (a_Seed + 4, std::make_shared (a_Seed + 5, std::make_shared (a_Seed + 6, 60, std::make_shared (a_Seed + 7, 10, 50, 50, std::make_shared (a_Seed + 8, std::make_shared (a_Seed + 9, std::make_shared (a_Seed + 1, 10, 50, 50, std::make_shared (a_Seed + 2, 2, std::make_shared (a_Seed + 3, std::make_shared (a_Seed + 4, std::make_shared (a_Seed + 5, 10) ))))))))))))))))))))))); } // cTerrainHeightGen overrides: virtual void GenHeightMap(cChunkCoords a_ChunkCoords, cChunkDef::HeightMap & a_HeightMap) override { int heights[cChunkDef::Width * cChunkDef::Width]; m_Gen->GetInts( a_ChunkCoords.m_ChunkX * cChunkDef::Width, a_ChunkCoords.m_ChunkZ * cChunkDef::Width, static_cast(cChunkDef::Width), static_cast(cChunkDef::Width), heights ); for (size_t i = 0; i < ARRAYCOUNT(heights); i++) { a_HeightMap[i] = static_cast(std::max(std::min(60 + heights[i], cChunkDef::Height - 60), 40)); } } protected: int m_Seed; std::shared_ptr m_Gen; }; //////////////////////////////////////////////////////////////////////////////// // cHeiGenFlat: void cHeiGenFlat::GenHeightMap(cChunkCoords a_ChunkCoords, cChunkDef::HeightMap & a_HeightMap) { UNUSED(a_ChunkCoords); for (size_t i = 0; i < ARRAYCOUNT(a_HeightMap); i++) { a_HeightMap[i] = m_Height; } } void cHeiGenFlat::InitializeHeightGen(cIniFile & a_IniFile) { m_Height = static_cast(a_IniFile.GetValueSetI("Generator", "FlatHeight", m_Height)); } //////////////////////////////////////////////////////////////////////////////// // cHeiGenCache: cHeiGenCache::cHeiGenCache(cTerrainHeightGen & a_HeiGenToCache, size_t a_CacheSize) : m_HeiGenToCache(a_HeiGenToCache), m_CacheSize(a_CacheSize), m_NumHits(0), m_NumMisses(0), m_TotalChain(0) { m_CacheOrder.resize(a_CacheSize); m_CacheData.resize(a_CacheSize); for (size_t i = 0; i < m_CacheSize; i++) { m_CacheOrder[i] = i; } } void cHeiGenCache::GenHeightMap(cChunkCoords a_ChunkCoords, cChunkDef::HeightMap & a_HeightMap) { /* if (((m_NumHits + m_NumMisses) % 1024) == 10) { LOGD("HeiGenCache: %d hits, %d misses, saved %.2f %%", m_NumHits, m_NumMisses, 100.0 * m_NumHits / (m_NumHits + m_NumMisses)); LOGD("HeiGenCache: Avg cache chain length: %.2f", static_cast(m_TotalChain) / m_NumHits); } //*/ for (size_t i = 0; i < m_CacheSize; i++) { if (m_CacheData[m_CacheOrder[i]].m_Coords != a_ChunkCoords) { continue; } // Found it in the cache auto Idx = m_CacheOrder[i]; // Move to front: for (size_t j = i; j > 0; j--) { m_CacheOrder[j] = m_CacheOrder[j - 1]; } m_CacheOrder[0] = Idx; // Use the cached data: memcpy(a_HeightMap, m_CacheData[Idx].m_HeightMap, sizeof(a_HeightMap)); m_NumHits++; m_TotalChain += i; return; } // for i - cache // Not in the cache: m_NumMisses++; m_HeiGenToCache.GenHeightMap(a_ChunkCoords, a_HeightMap); // Insert it as the first item in the MRU order: auto Idx = m_CacheOrder[m_CacheSize - 1]; for (auto i = m_CacheSize - 1; i > 0; i--) { m_CacheOrder[i] = m_CacheOrder[i - 1]; } // for i - m_CacheOrder[] m_CacheOrder[0] = Idx; memcpy(m_CacheData[Idx].m_HeightMap, a_HeightMap, sizeof(a_HeightMap)); m_CacheData[Idx].m_Coords = a_ChunkCoords; } HEIGHTTYPE cHeiGenCache::GetHeightAt(int a_BlockX, int a_BlockZ) { // First try if the chunk is already in the cache: int chunkX, chunkZ; cChunkDef::BlockToChunk(a_BlockX, a_BlockZ, chunkX, chunkZ); HEIGHTTYPE res; if (GetHeightAt(chunkX, chunkZ, a_BlockX - chunkX * cChunkDef::Width, a_BlockZ - chunkZ * cChunkDef::Width, res)) { return res; } // Chunk not in cache, generate the chunk and ask again: cChunkDef::HeightMap heightMap; GenHeightMap({chunkX, chunkZ}, heightMap); return cChunkDef::GetHeight(heightMap, a_BlockX - chunkX * cChunkDef::Width, a_BlockZ - chunkZ * cChunkDef::Width); } bool cHeiGenCache::GetHeightAt(int a_ChunkX, int a_ChunkZ, int a_RelX, int a_RelZ, HEIGHTTYPE & a_Height) { for (size_t i = 0; i < m_CacheSize; i++) { if ((m_CacheData[i].m_Coords.m_ChunkX == a_ChunkX) && (m_CacheData[i].m_Coords.m_ChunkZ == a_ChunkZ)) { a_Height = cChunkDef::GetHeight(m_CacheData[i].m_HeightMap, a_RelX, a_RelZ); return true; } } // for i - m_CacheData[] return false; } //////////////////////////////////////////////////////////////////////////////// // cHeiGenMultiCache: cHeiGenMultiCache::cHeiGenMultiCache(std::unique_ptr a_HeiGenToCache, size_t a_SubCacheSize, size_t a_NumSubCaches): m_NumSubCaches(a_NumSubCaches), m_Underlying(std::move(a_HeiGenToCache)) { // Create the individual sub-caches: m_SubCaches.reserve(a_NumSubCaches); for (size_t i = 0; i < a_NumSubCaches; i++) { m_SubCaches.push_back(std::make_unique(*m_Underlying, a_SubCacheSize)); } } void cHeiGenMultiCache::GenHeightMap(cChunkCoords a_ChunkCoords, cChunkDef::HeightMap & a_HeightMap) { // Get the subcache responsible for this chunk: const size_t cacheIdx = (static_cast(a_ChunkCoords.m_ChunkX) + m_CoeffZ * static_cast(a_ChunkCoords.m_ChunkZ)) % m_NumSubCaches; // Ask the subcache: m_SubCaches[cacheIdx]->GenHeightMap(a_ChunkCoords, a_HeightMap); } HEIGHTTYPE cHeiGenMultiCache::GetHeightAt(int a_BlockX, int a_BlockZ) { // First try if the chunk is already in the cache: int chunkX, chunkZ; cChunkDef::BlockToChunk(a_BlockX, a_BlockZ, chunkX, chunkZ); HEIGHTTYPE res; if (GetHeightAt(chunkX, chunkZ, a_BlockX - chunkX * cChunkDef::Width, a_BlockZ - chunkZ * cChunkDef::Width, res)) { return res; } // Chunk not in cache, generate the chunk and ask again: cChunkDef::HeightMap heightMap; GenHeightMap({chunkX, chunkZ}, heightMap); return cChunkDef::GetHeight(heightMap, a_BlockX - chunkX * cChunkDef::Width, a_BlockZ - chunkZ * cChunkDef::Width); } bool cHeiGenMultiCache::GetHeightAt(int a_ChunkX, int a_ChunkZ, int a_RelX, int a_RelZ, HEIGHTTYPE & a_Height) { // Get the subcache responsible for this chunk: const size_t cacheIdx = (static_cast(a_ChunkX) + m_CoeffZ * static_cast(a_ChunkZ)) % m_NumSubCaches; // Ask the subcache: return m_SubCaches[cacheIdx]->GetHeightAt(a_ChunkX, a_ChunkZ, a_RelX, a_RelZ, a_Height); } //////////////////////////////////////////////////////////////////////////////// // cHeiGenClassic: cHeiGenClassic::cHeiGenClassic(int a_Seed) : m_Seed(a_Seed), m_Noise(a_Seed), m_HeightFreq1(1.0f), m_HeightAmp1(1.0f), m_HeightFreq2(0.5f), m_HeightAmp2(0.5f), m_HeightFreq3(0.1f), m_HeightAmp3(0.1f) { } float cHeiGenClassic::GetNoise(float x, float y) { float oct1 = m_Noise.CubicNoise2D(x * m_HeightFreq1, y * m_HeightFreq1) * m_HeightAmp1; float oct2 = m_Noise.CubicNoise2D(x * m_HeightFreq2, y * m_HeightFreq2) * m_HeightAmp2; float oct3 = m_Noise.CubicNoise2D(x * m_HeightFreq3, y * m_HeightFreq3) * m_HeightAmp3; float height = m_Noise.CubicNoise2D(x * 0.1f, y * 0.1f) * 2; float flatness = ((m_Noise.CubicNoise2D(x * 0.5f, y * 0.5f) + 1.f) * 0.5f) * 1.1f; // 0 ... 1.5 flatness *= flatness * flatness; return (oct1 + oct2 + oct3) * flatness + height; } void cHeiGenClassic::GenHeightMap(cChunkCoords a_ChunkCoords, cChunkDef::HeightMap & a_HeightMap) { for (int z = 0; z < cChunkDef::Width; z++) { const float zz = static_cast(a_ChunkCoords.m_ChunkZ * cChunkDef::Width + z); for (int x = 0; x < cChunkDef::Width; x++) { const float xx = static_cast(a_ChunkCoords.m_ChunkX * cChunkDef::Width + x); HEIGHTTYPE hei = static_cast(Clamp(static_cast(64 + (GetNoise(xx * 0.05f, zz * 0.05f) * 16)), 10, 250)); cChunkDef::SetHeight(a_HeightMap, x, z, hei); } // for x } // for z } void cHeiGenClassic::InitializeHeightGen(cIniFile & a_IniFile) { m_HeightFreq1 = static_cast(a_IniFile.GetValueSetF("Generator", "ClassicHeightFreq1", 0.1)); m_HeightFreq2 = static_cast(a_IniFile.GetValueSetF("Generator", "ClassicHeightFreq2", 1.0)); m_HeightFreq3 = static_cast(a_IniFile.GetValueSetF("Generator", "ClassicHeightFreq3", 2.0)); m_HeightAmp1 = static_cast(a_IniFile.GetValueSetF("Generator", "ClassicHeightAmp1", 1.0)); m_HeightAmp2 = static_cast(a_IniFile.GetValueSetF("Generator", "ClassicHeightAmp2", 0.5)); m_HeightAmp3 = static_cast(a_IniFile.GetValueSetF("Generator", "ClassicHeightAmp3", 0.5)); } //////////////////////////////////////////////////////////////////////////////// // cHeiGenMountains: cHeiGenMountains::cHeiGenMountains(int a_Seed) : m_Seed(a_Seed), m_MountainNoise(a_Seed + 100), m_DitchNoise(a_Seed + 200), m_Perlin(a_Seed + 300) { } void cHeiGenMountains::GenHeightMap(cChunkCoords a_ChunkCoords, cChunkDef::HeightMap & a_HeightMap) { NOISE_DATATYPE StartX = static_cast(a_ChunkCoords.m_ChunkX * cChunkDef::Width); NOISE_DATATYPE EndX = static_cast(a_ChunkCoords.m_ChunkX * cChunkDef::Width + cChunkDef::Width - 1); NOISE_DATATYPE StartZ = static_cast(a_ChunkCoords.m_ChunkZ * cChunkDef::Width); NOISE_DATATYPE EndZ = static_cast(a_ChunkCoords.m_ChunkZ * cChunkDef::Width + cChunkDef::Width - 1); NOISE_DATATYPE Workspace[16 * 16]; NOISE_DATATYPE MountainNoise[16 * 16]; NOISE_DATATYPE DitchNoise[16 * 16]; NOISE_DATATYPE PerlinNoise[16 * 16]; m_MountainNoise.Generate2D(MountainNoise, 16, 16, StartX, EndX, StartZ, EndZ, Workspace); m_DitchNoise.Generate2D(DitchNoise, 16, 16, StartX, EndX, StartZ, EndZ, Workspace); m_Perlin.Generate2D(PerlinNoise, 16, 16, StartX, EndX, StartZ, EndZ, Workspace); for (int z = 0; z < cChunkDef::Width; z++) { int IdxZ = z * cChunkDef::Width; for (int x = 0; x < cChunkDef::Width; x++) { int idx = IdxZ + x; HEIGHTTYPE hei = static_cast(Clamp(100 - static_cast((MountainNoise[idx] - DitchNoise[idx] + PerlinNoise[idx]) * 15), 10, 250)); cChunkDef::SetHeight(a_HeightMap, x, z, hei); } // for x } // for z } void cHeiGenMountains::InitializeHeightGen(cIniFile & a_IniFile) { // TODO: Read the params from an INI file m_MountainNoise.AddOctave(0.1f, 0.2f); m_MountainNoise.AddOctave(0.05f, 0.4f); m_MountainNoise.AddOctave(0.02f, 1.0f); m_DitchNoise.AddOctave(0.1f, 0.2f); m_DitchNoise.AddOctave(0.05f, 0.4f); m_DitchNoise.AddOctave(0.02f, 1.0f); m_Perlin.AddOctave(0.01f, 1.5f); } //////////////////////////////////////////////////////////////////////////////// // cHeiGenBiomal: const cHeiGenBiomal::sGenParam cHeiGenBiomal::m_GenParam[256] = { /* Fast-changing | Middle-changing | Slow-changing | */ /* Biome | Freq1 | Amp1 | Freq2 | Amp2 | Freq3 | Amp3 | BaseHeight */ /* biOcean */ { 0.1f, 2.0f, 0.05f, 10.0f, 0.01f, 8.0f, 50}, /* biPlains */ { 0.1f, 1.0f, 0.05f, 1.5f, 0.01f, 4.0f, 68}, /* biDesert */ { 0.1f, 1.0f, 0.05f, 1.5f, 0.01f, 4.0f, 68}, /* biExtremeHills */ { 0.2f, 4.0f, 0.05f, 20.0f, 0.01f, 16.0f, 100}, /* biForest */ { 0.1f, 1.0f, 0.05f, 2.0f, 0.01f, 4.0f, 70}, /* biTaiga */ { 0.1f, 1.0f, 0.05f, 2.0f, 0.01f, 4.0f, 70}, /* biSwampland */ { 0.1f, 1.1f, 0.05f, 1.5f, 0.02f, 2.5f, 61.5}, /* biRiver */ { 0.2f, 0.1f, 0.05f, 0.1f, 0.01f, 0.1f, 56}, /* biNether */ { 0.1f, 0.0f, 0.01f, 0.0f, 0.01f, 0.0f, 0}, // Unused, but must be here due to indexing /* biSky */ { 0.1f, 0.0f, 0.01f, 0.0f, 0.01f, 0.0f, 0}, // Unused, but must be here due to indexing /* biFrozenOcean */ { 0.1f, 2.0f, 0.05f, 12.0f, 0.01f, 10.0f, 40}, /* biFrozenRiver */ { 0.2f, 0.1f, 0.05f, 0.1f, 0.01f, 0.1f, 56}, /* biIcePlains */ { 0.1f, 1.0f, 0.05f, 1.5f, 0.01f, 4.0f, 68}, /* biIceMountains */ { 0.2f, 2.0f, 0.05f, 10.0f, 0.01f, 8.0f, 80}, /* biMushroomIsland */ { 0.1f, 2.0f, 0.05f, 8.0f, 0.01f, 6.0f, 80}, /* biMushroomShore */ { 0.1f, 1.0f, 0.05f, 2.0f, 0.01f, 4.0f, 64}, /* biBeach */ { 0.1f, 0.5f, 0.05f, 1.0f, 0.01f, 1.0f, 64}, /* biDesertHills */ { 0.2f, 2.0f, 0.05f, 5.0f, 0.01f, 4.0f, 75}, /* biForestHills */ { 0.2f, 2.0f, 0.05f, 12.0f, 0.01f, 10.0f, 80}, /* biTaigaHills */ { 0.2f, 2.0f, 0.05f, 12.0f, 0.01f, 10.0f, 80}, /* biExtremeHillsEdge */ { 0.2f, 3.0f, 0.05f, 16.0f, 0.01f, 12.0f, 80}, /* biJungle */ { 0.1f, 3.0f, 0.05f, 6.0f, 0.01f, 6.0f, 70}, /* biJungleHills */ { 0.2f, 3.0f, 0.05f, 12.0f, 0.01f, 10.0f, 80}, /* biJungleEdge */ { 0.1f, 3.0f, 0.05f, 6.0f, 0.01f, 6.0f, 70}, /* biDeepOcean */ { 0.1f, 2.0f, 0.05f, 12.0f, 0.01f, 10.0f, 40}, /* biStoneBeach */ { 0.1f, 2.0f, 0.05f, 12.0f, 0.01f, 10.0f, 40}, /* biColdBeach */ { 0.1f, 0.5f, 0.05f, 1.0f, 0.01f, 1.0f, 64}, /* biBirchForest */ { 0.1f, 1.0f, 0.05f, 2.0f, 0.01f, 4.0f, 70}, /* biBirchForestHills */ { 0.2f, 2.0f, 0.05f, 10.0f, 0.01f, 8.0f, 80}, /* biRoofedForest */ { 0.1f, 1.0f, 0.05f, 2.0f, 0.01f, 4.0f, 70}, /* biColdTaiga */ { 0.1f, 1.0f, 0.05f, 2.0f, 0.01f, 4.0f, 70}, /* biColdTaigaHills */ { 0.2f, 2.0f, 0.05f, 10.0f, 0.01f, 8.0f, 80}, /* biMegaTaiga */ { 0.1f, 1.0f, 0.05f, 2.0f, 0.01f, 4.0f, 70}, /* biMegaTaigaHills */ { 0.2f, 2.0f, 0.05f, 10.0f, 0.01f, 8.0f, 80}, /* biExtremeHillsPlus */ { 0.2f, 4.0f, 0.05f, 20.0f, 0.01f, 16.0f, 120}, /* biSavanna */ { 0.1f, 1.0f, 0.05f, 1.5f, 0.01f, 4.0f, 68}, /* biSavannaPlateau */ { 0.1f, 1.0f, 0.05f, 1.5f, 0.01f, 4.0f, 80}, /* biMesa */ { 0.2f, 2.0f, 0.05f, 10.0f, 0.01f, 8.0f, 70}, // 165 /* biMesaPlateauF */ { 0.1f, 1.0f, 0.05f, 1.5f, 0.01f, 4.0f, 80}, /* biMesaPlateau */ { 0.1f, 1.0f, 0.05f, 1.5f, 0.01f, 4.0f, 80}, // biomes 40 .. 128 are unused, 89 empty placeholders here: {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, // 40 .. 49 {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, // 50 .. 59 {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, // 60 .. 69 {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, // 70 .. 79 {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, // 80 .. 89 {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, // 90 .. 99 {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, // 100 .. 109 {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, // 110 .. 119 {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, // 120 .. 128 /* biSunflowerPlains */ { 0.1f, 2.0f, 0.05f, 12.0f, 0.01f, 10.0f, 40}, // 129 /* biDesertM */ { 0.1f, 2.0f, 0.05f, 12.0f, 0.01f, 10.0f, 40}, // 130 /* biExtremeHillsM */ { 0.1f, 2.0f, 0.05f, 12.0f, 0.01f, 10.0f, 40}, // 131 /* biFlowerForest */ { 0.1f, 2.0f, 0.05f, 12.0f, 0.01f, 10.0f, 40}, // 132 /* biTaigaM */ { 0.1f, 2.0f, 0.05f, 12.0f, 0.01f, 10.0f, 40}, // 133 /* biSwamplandM */ { 1.0f, 3.0f, 1.10f, 7.0f, 0.01f, 0.01f, 60}, // 134 // Biomes 135 .. 139 unused, 5 empty placeholders here: {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, // 135 .. 139 /* biIcePlainsSpikes */ { 0.1f, 2.0f, 0.05f, 12.0f, 0.01f, 10.0f, 40}, // 140 // Biomes 141 .. 148 unused, 8 empty placeholders here: {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, // 141 .. 148 /* biJungleM */ { 0.1f, 3.0f, 0.05f, 6.0f, 0.01f, 6.0f, 70}, // 149 {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, // 150 /* biJungleEdgeM */ { 0.1f, 3.0f, 0.05f, 6.0f, 0.01f, 6.0f, 70}, // 151 {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, // 152 .. 154 /* biBirchForestM */ { 0.1f, 1.0f, 0.05f, 2.0f, 0.01f, 4.0f, 70}, // 155 /* biBirchForestHillsM */ { 0.2f, 2.0f, 0.05f, 10.0f, 0.01f, 8.0f, 80}, // 156 /* biRoofedForestM */ { 0.1f, 1.0f, 0.05f, 2.0f, 0.01f, 4.0f, 70}, // 157 /* biColdTaigaM */ { 0.1f, 1.0f, 0.05f, 2.0f, 0.01f, 4.0f, 70}, // 158 {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, // 159 /* biMegaSpruceTaiga */ { 0.1f, 1.0f, 0.05f, 2.0f, 0.01f, 4.0f, 70}, // 160 /* biMegaSpruceTaigaHills */ { 0.2f, 2.0f, 0.05f, 10.0f, 0.01f, 8.0f, 80}, // 161 /* biExtremeHillsPlusM */ { 0.2f, 4.0f, 0.05f, 20.0f, 0.01f, 16.0f, 120}, // 162 /* biSavannaM */ { 0.1f, 1.0f, 0.05f, 1.5f, 0.01f, 4.0f, 68}, // 163 /* biSavannaPlateauM */ { 0.1f, 1.0f, 0.05f, 1.5f, 0.01f, 4.0f, 80}, // 164 /* biMesaBryce */ { 0.2f, 2.0f, 0.1f, 30.0f, 0.01f, 8.0f, 80}, /* biMesaPlateauFM */ { 0.1f, 1.0f, 0.05f, 1.5f, 0.01f, 4.0f, 80}, // 166 /* biMesaPlateauM */ { 0.1f, 1.0f, 0.05f, 1.5f, 0.01f, 4.0f, 80}, // 167 } ; void cHeiGenBiomal::GenHeightMap(cChunkCoords a_ChunkCoords, cChunkDef::HeightMap & a_HeightMap) { // Generate a 3x3 chunk area of biomes around this chunk: BiomeNeighbors Biomes; for (int z = -1; z <= 1; z++) { for (int x = -1; x <= 1; x++) { m_BiomeGen.GenBiomes({a_ChunkCoords.m_ChunkX + x, a_ChunkCoords.m_ChunkZ + z}, Biomes[x + 1][z + 1]); } // for x } // for z // Linearly interpolate 4x4 blocks of heightmap: // Must be done on a floating point datatype, otherwise the results are ugly! const int STEPZ = 4; // Must be a divisor of 16 const int STEPX = 4; // Must be a divisor of 16 NOISE_DATATYPE Height[17 * 17]; for (int z = 0; z < 17; z += STEPZ) { for (int x = 0; x < 17; x += STEPX) { Height[x + 17 * z] = GetHeightAt(x, z, a_ChunkCoords.m_ChunkX, a_ChunkCoords.m_ChunkZ, Biomes); } } LinearUpscale2DArrayInPlace<17, 17, STEPX, STEPZ>(Height); // Copy into the heightmap for (int z = 0; z < cChunkDef::Width; z++) { for (int x = 0; x < cChunkDef::Width; x++) { cChunkDef::SetHeight(a_HeightMap, x, z, static_cast(Height[x + 17 * z])); } } } void cHeiGenBiomal::InitializeHeightGen(cIniFile & a_IniFile) { // No user-settable params } NOISE_DATATYPE cHeiGenBiomal::GetHeightAt(int a_RelX, int a_RelZ, int a_ChunkX, int a_ChunkZ, const cHeiGenBiomal::BiomeNeighbors & a_BiomeNeighbors) { // Sum up how many biomes of each type there are in the neighborhood: int BiomeCounts[256]; memset(BiomeCounts, 0, sizeof(BiomeCounts)); int Sum = 0; for (int z = -8; z <= 8; z++) { int FinalZ = a_RelZ + z + cChunkDef::Width; int IdxZ = FinalZ / cChunkDef::Width; int ModZ = FinalZ % cChunkDef::Width; int WeightZ = 9 - abs(z); for (int x = -8; x <= 8; x++) { int FinalX = a_RelX + x + cChunkDef::Width; int IdxX = FinalX / cChunkDef::Width; int ModX = FinalX % cChunkDef::Width; EMCSBiome Biome = cChunkDef::GetBiome(a_BiomeNeighbors[IdxX][IdxZ], ModX, ModZ); int WeightX = 9 - abs(x); BiomeCounts[Biome] += WeightX + WeightZ; Sum += WeightX + WeightZ; } // for x } // for z // For each biome type that has a nonzero count, calc its height and add it: if (Sum > 0) { NOISE_DATATYPE Height = 0; int BlockX = a_ChunkX * cChunkDef::Width + a_RelX; int BlockZ = a_ChunkZ * cChunkDef::Width + a_RelZ; for (size_t i = 0; i < ARRAYCOUNT(BiomeCounts); i++) { if (BiomeCounts[i] == 0) { continue; } /* // Sanity checks for biome parameters, enable them to check the biome param table in runtime (slow): ASSERT(m_GenParam[i].m_HeightFreq1 >= 0); ASSERT(m_GenParam[i].m_HeightFreq1 < 1000); ASSERT(m_GenParam[i].m_HeightFreq2 >= 0); ASSERT(m_GenParam[i].m_HeightFreq2 < 1000); ASSERT(m_GenParam[i].m_HeightFreq3 >= 0); ASSERT(m_GenParam[i].m_HeightFreq3 < 1000); */ NOISE_DATATYPE oct1 = m_Noise.CubicNoise2D(BlockX * m_GenParam[i].m_HeightFreq1, BlockZ * m_GenParam[i].m_HeightFreq1) * m_GenParam[i].m_HeightAmp1; NOISE_DATATYPE oct2 = m_Noise.CubicNoise2D(BlockX * m_GenParam[i].m_HeightFreq2, BlockZ * m_GenParam[i].m_HeightFreq2) * m_GenParam[i].m_HeightAmp2; NOISE_DATATYPE oct3 = m_Noise.CubicNoise2D(BlockX * m_GenParam[i].m_HeightFreq3, BlockZ * m_GenParam[i].m_HeightFreq3) * m_GenParam[i].m_HeightAmp3; Height += BiomeCounts[i] * (m_GenParam[i].m_BaseHeight + oct1 + oct2 + oct3); } NOISE_DATATYPE res = Height / Sum; return std::min(static_cast(250), std::max(res, static_cast(5))); } // No known biome around? Weird. Return a bogus value: ASSERT(!"cHeiGenBiomal: Biome sum failed, no known biome around"); return 5; } //////////////////////////////////////////////////////////////////////////////// // cHeiGenMinMax: class cHeiGenMinMax: public cTerrainHeightGen { using Super = cTerrainHeightGen; /** Size of the averaging process, in columns (for each direction). Must be less than 16. */ static const int AVERAGING_SIZE = 4; public: cHeiGenMinMax(int a_Seed, cBiomeGen & a_BiomeGen): m_Noise(a_Seed), m_BiomeGen(a_BiomeGen), m_TotalWeight(0) { // Initialize the weights: for (int z = 0; z <= AVERAGING_SIZE * 2; z++) { for (int x = 0; x <= AVERAGING_SIZE * 2; x++) { m_Weights[z][x] = 1 + 2 * AVERAGING_SIZE - std::abs(x - AVERAGING_SIZE) - std::abs(z - AVERAGING_SIZE); m_TotalWeight += m_Weights[z][x]; } } // Initialize the Perlin generator: m_Perlin.AddOctave(0.04f, 0.2f); m_Perlin.AddOctave(0.02f, 0.1f); m_Perlin.AddOctave(0.01f, 0.05f); } virtual void GenHeightMap(cChunkCoords a_ChunkCoords, cChunkDef::HeightMap & a_HeightMap) override { // Generate the biomes for the 3 * 3 neighbors: cChunkDef::BiomeMap neighborBiomes[3][3]; for (int z = 0; z < 3; z++) for (int x = 0; x < 3; x++) { m_BiomeGen.GenBiomes({a_ChunkCoords.m_ChunkX + x - 1, a_ChunkCoords.m_ChunkZ + z - 1}, neighborBiomes[z][x]); } // Get the min and max heights based on the biomes: double minHeight[cChunkDef::Width * cChunkDef::Width]; double maxHeight[cChunkDef::Width * cChunkDef::Width]; for (int z = 0; z < cChunkDef::Width; z++) { for (int x = 0; x < cChunkDef::Width; x++) { // For each column, sum the min and max values of the neighborhood around it: double min = 0, max = 0; for (int relz = 0; relz <= AVERAGING_SIZE * 2; relz++) { int bz = z + 16 + relz - AVERAGING_SIZE; // Biome Z coord relative to the neighborBiomes start int cz = bz / 16; // Chunk Z coord relative to the neighborBiomes start bz = bz % 16; // Biome Z coord relative to cz in neighborBiomes for (int relx = 0; relx <= AVERAGING_SIZE * 2; relx++) { int bx = x + 16 + relx - AVERAGING_SIZE; // Biome X coord relative to the neighborBiomes start int cx = bx / 16; // Chunk X coord relative to the neighborBiomes start bx = bx % 16; // Biome X coord relative to cz in neighborBiomes // Get the biome's min and max heights: double bmin, bmax; getBiomeMinMax(cChunkDef::GetBiome(neighborBiomes[cz][cx], bx, bz), bmin, bmax); // Add them to the total, with the weight depending on their relative position to the column: min += bmin * m_Weights[relz][relx]; max += bmax * m_Weights[relz][relx]; } // for relx } // for relz minHeight[x + z * cChunkDef::Width] = min / m_TotalWeight; maxHeight[x + z * cChunkDef::Width] = max / m_TotalWeight; } // for x } // for z // Generate the base noise: NOISE_DATATYPE noise[cChunkDef::Width * cChunkDef::Width]; NOISE_DATATYPE workspace[cChunkDef::Width * cChunkDef::Width]; NOISE_DATATYPE startX = static_cast(a_ChunkCoords.m_ChunkX * cChunkDef::Width); NOISE_DATATYPE endX = startX + cChunkDef::Width - 1; NOISE_DATATYPE startZ = static_cast(a_ChunkCoords.m_ChunkZ * cChunkDef::Width); NOISE_DATATYPE endZ = startZ + cChunkDef::Width - 1; m_Perlin.Generate2D(noise, 16, 16, startX, endX, startZ, endZ, workspace); // Make the height by ranging the noise between min and max: for (int z = 0; z < cChunkDef::Width; z++) { for (int x = 0; x < cChunkDef::Width; x++) { double min = minHeight[x + z * cChunkDef::Width]; double max = maxHeight[x + z * cChunkDef::Width]; double h = (max + min) / 2 + noise[x + z * cChunkDef::Width] * (max - min); cChunkDef::SetHeight(a_HeightMap, x, z, static_cast(h)); } } } virtual void InitializeHeightGen(cIniFile & a_IniFile) override { // No settings available } protected: cNoise m_Noise; cPerlinNoise m_Perlin; /** The biome generator to query for the underlying biomes. */ cBiomeGen & m_BiomeGen; /** Weights applied to each of the min / max values in the neighborhood of the currently evaluated column. */ double m_Weights[AVERAGING_SIZE * 2 + 1][AVERAGING_SIZE * 2 + 1]; /** Sum of all the m_Weights items. */ double m_TotalWeight; /** Returns the minimum and maximum heights for the given biome. */ void getBiomeMinMax(EMCSBiome a_Biome, double & a_Min, double & a_Max) { switch (a_Biome) { case biBeach: a_Min = 61; a_Max = 64; break; case biBirchForest: a_Min = 63; a_Max = 75; break; case biBirchForestHills: a_Min = 63; a_Max = 90; break; case biBirchForestHillsM: a_Min = 63; a_Max = 90; break; case biBirchForestM: a_Min = 63; a_Max = 75; break; case biColdBeach: a_Min = 61; a_Max = 64; break; case biColdTaiga: a_Min = 63; a_Max = 75; break; case biColdTaigaHills: a_Min = 63; a_Max = 90; break; case biColdTaigaM: a_Min = 63; a_Max = 75; break; case biDeepOcean: a_Min = 30; a_Max = 60; break; case biDesert: a_Min = 63; a_Max = 70; break; case biDesertHills: a_Min = 63; a_Max = 85; break; case biDesertM: a_Min = 63; a_Max = 70; break; case biEnd: a_Min = 10; a_Max = 100; break; case biExtremeHills: a_Min = 60; a_Max = 120; break; case biExtremeHillsEdge: a_Min = 63; a_Max = 100; break; case biExtremeHillsM: a_Min = 60; a_Max = 120; break; case biExtremeHillsPlus: a_Min = 60; a_Max = 140; break; case biExtremeHillsPlusM: a_Min = 60; a_Max = 140; break; case biFlowerForest: a_Min = 63; a_Max = 75; break; case biForest: a_Min = 63; a_Max = 75; break; case biForestHills: a_Min = 63; a_Max = 90; break; case biFrozenOcean: a_Min = 45; a_Max = 64; break; case biFrozenRiver: a_Min = 60; a_Max = 62; break; case biIceMountains: a_Min = 63; a_Max = 90; break; case biIcePlains: a_Min = 63; a_Max = 70; break; case biIcePlainsSpikes: a_Min = 60; a_Max = 70; break; case biJungle: a_Min = 60; a_Max = 80; break; case biJungleEdge: a_Min = 62; a_Max = 75; break; case biJungleEdgeM: a_Min = 62; a_Max = 75; break; case biJungleHills: a_Min = 60; a_Max = 90; break; case biJungleM: a_Min = 60; a_Max = 75; break; case biMegaSpruceTaiga: a_Min = 63; a_Max = 75; break; case biMegaSpruceTaigaHills: a_Min = 63; a_Max = 90; break; case biMegaTaiga: a_Min = 63; a_Max = 75; break; case biMegaTaigaHills: a_Min = 63; a_Max = 90; break; case biMesa: a_Min = 63; a_Max = 90; break; case biMesaBryce: a_Min = 60; a_Max = 67; break; case biMesaPlateau: a_Min = 75; a_Max = 85; break; case biMesaPlateauF: a_Min = 80; a_Max = 90; break; case biMesaPlateauFM: a_Min = 80; a_Max = 90; break; case biMesaPlateauM: a_Min = 75; a_Max = 85; break; case biMushroomIsland: a_Min = 63; a_Max = 90; break; case biMushroomShore: a_Min = 60; a_Max = 75; break; case biNether: a_Min = 10; a_Max = 100; break; case biOcean: a_Min = 45; a_Max = 64; break; case biPlains: a_Min = 63; a_Max = 70; break; case biRiver: a_Min = 60; a_Max = 62; break; case biRoofedForest: a_Min = 63; a_Max = 75; break; case biRoofedForestM: a_Min = 63; a_Max = 75; break; case biSavanna: a_Min = 63; a_Max = 75; break; case biSavannaM: a_Min = 63; a_Max = 80; break; case biSavannaPlateau: a_Min = 75; a_Max = 100; break; case biSavannaPlateauM: a_Min = 80; a_Max = 160; break; case biStoneBeach: a_Min = 60; a_Max = 64; break; case biSunflowerPlains: a_Min = 63; a_Max = 70; break; case biSwampland: a_Min = 60; a_Max = 67; break; case biSwamplandM: a_Min = 61; a_Max = 67; break; case biTaiga: a_Min = 63; a_Max = 75; break; case biTaigaHills: a_Min = 63; a_Max = 90; break; case biTaigaM: a_Min = 63; a_Max = 80; break; case biInvalidBiome: case biNumBiomes: case biVariant: case biNumVariantBiomes: { ASSERT(!"Unknown biome"); a_Min = 10; a_Max = 10; break; } } } }; //////////////////////////////////////////////////////////////////////////////// // cTerrainHeightGen: std::unique_ptr cTerrainHeightGen::CreateHeightGen(cIniFile & a_IniFile, cBiomeGen & a_BiomeGen, int a_Seed, bool & a_CacheOffByDefault) { AString HeightGenName = a_IniFile.GetValueSet("Generator", "HeightGen", ""); if (HeightGenName.empty()) { LOGWARN("[Generator] HeightGen value not set in world.ini, using \"Biomal\"."); HeightGenName = "Biomal"; } a_CacheOffByDefault = false; std::unique_ptr res; if (NoCaseCompare(HeightGenName, "Flat") == 0) { res = std::make_unique(); a_CacheOffByDefault = true; // We're generating faster than a cache would retrieve data } else if (NoCaseCompare(HeightGenName, "classic") == 0) { res = std::make_unique(a_Seed); } else if (NoCaseCompare(HeightGenName, "DistortedHeightmap") == 0) { // Not a heightmap-based generator, but it used to be accessible via HeightGen, so we need to skip making the default out of it // Return an empty pointer, the caller will create the proper generator: return nullptr; } else if (NoCaseCompare(HeightGenName, "End") == 0) { // Not a heightmap-based generator, but it used to be accessible via HeightGen, so we need to skip making the default out of it // Return an empty pointer, the caller will create the proper generator: return nullptr; } else if (NoCaseCompare(HeightGenName, "MinMax") == 0) { res = std::make_unique(a_Seed, a_BiomeGen); } else if (NoCaseCompare(HeightGenName, "Mountains") == 0) { res = std::make_unique(a_Seed); } else if (NoCaseCompare(HeightGenName, "BiomalNoise3D") == 0) { // Not a heightmap-based generator, but it used to be accessible via HeightGen, so we need to skip making the default out of it // Return an empty pointer, the caller will create the proper generator: return nullptr; } else if (NoCaseCompare(HeightGenName, "Steppy") == 0) { res = std::make_unique(a_Seed); } else if (NoCaseCompare(HeightGenName, "Noise3D") == 0) { // Not a heightmap-based generator, but it used to be accessible via HeightGen, so we need to skip making the default out of it // Return an empty pointer, the caller will create the proper generator: return nullptr; } else if (NoCaseCompare(HeightGenName, "Biomal") == 0) { res = std::make_unique(a_Seed, a_BiomeGen); /* // Performance-testing: LOGINFO("Measuring performance of cHeiGenBiomal..."); clock_t BeginTick = clock(); for (int x = 0; x < 500; x++) { cChunkDef::HeightMap Heights; res->GenHeightMap(x * 5, x * 5, Heights); } clock_t Duration = clock() - BeginTick; LOGINFO("HeightGen for 500 chunks took %d ticks (%.02f sec)", Duration, (double)Duration / CLOCKS_PER_SEC); //*/ } else { // No match found, force-set the default and retry LOGWARN("Unknown HeightGen \"%s\", using \"Biomal\" instead.", HeightGenName.c_str()); a_IniFile.SetValue("Generator", "HeightGen", "Biomal"); return CreateHeightGen(a_IniFile, a_BiomeGen, a_Seed, a_CacheOffByDefault); } // Read the settings: res->InitializeHeightGen(a_IniFile); return res; } ================================================ FILE: src/Generating/HeiGen.h ================================================ // HeiGen.h /* Interfaces to the various height-based terrain shape generators: - cHeiGenFlat - cHeiGenClassic - cHeiGenBiomal Also implements the heightmap cache */ #pragma once #include "ComposableGenerator.h" #include "../Noise/Noise.h" /** A simple cache that stores N most recently generated chunks' heightmaps; N being settable upon creation */ class cHeiGenCache : public cTerrainHeightGen { public: cHeiGenCache(cTerrainHeightGen & a_HeiGenToCache, size_t a_CacheSize); // cTerrainHeightGen overrides: virtual void GenHeightMap(cChunkCoords a_ChunkCoords, cChunkDef::HeightMap & a_HeightMap) override; virtual HEIGHTTYPE GetHeightAt(int a_BlockX, int a_BlockZ) override; /** Retrieves height at the specified point in the cache, returns true if found, false if not found */ bool GetHeightAt(int a_ChunkX, int a_ChunkZ, int a_RelX, int a_RelZ, HEIGHTTYPE & a_Height); protected: struct sCacheData { cChunkCoords m_Coords; cChunkDef::HeightMap m_HeightMap; /** Default constructor: Fill in bogus coords, so that the item is not used until properly calculated. */ sCacheData(): m_Coords(0x7fffffff, 0x7fffffff) {} } ; /** The terrain height generator that is being cached. */ cTerrainHeightGen & m_HeiGenToCache; // To avoid moving large amounts of data for the MRU behavior, we MRU-ize indices to an array of the actual data size_t m_CacheSize; std::vector m_CacheOrder; // MRU-ized order, indices into m_CacheData array std::vector m_CacheData; // m_CacheData[m_CacheOrder[0]] is the most recently used // Cache statistics size_t m_NumHits; size_t m_NumMisses; size_t m_TotalChain; // Number of cache items walked to get to a hit (only added for hits) } ; /** Caches heightmaps in multiple underlying caches to improve the distribution and lower the chain length. */ class cHeiGenMultiCache: public cTerrainHeightGen { public: cHeiGenMultiCache(std::unique_ptr a_HeightGenToCache, size_t a_SubCacheSize, size_t a_NumSubCaches); // cTerrainHeightGen overrides: virtual void GenHeightMap(cChunkCoords a_ChunkCoords, cChunkDef::HeightMap & a_HeightMap) override; virtual HEIGHTTYPE GetHeightAt(int a_BlockX, int a_BlockZ) override; /** Retrieves height at the specified point in the cache, returns true if found, false if not found */ bool GetHeightAt(int a_ChunkX, int a_ChunkZ, int a_RelX, int a_RelZ, HEIGHTTYPE & a_Height); protected: /** The coefficient used to turn Z coords into index (x + Coeff * z). */ static const size_t m_CoeffZ = 5; /** Number of sub-caches, pulled out of m_SubCaches.size() for performance reasons. */ size_t m_NumSubCaches; /** The individual sub-caches. */ std::vector> m_SubCaches; /** The underlying height generator. */ std::unique_ptr m_Underlying; }; class cHeiGenFlat : public cTerrainHeightGen { public: cHeiGenFlat(void) : m_Height(5) {} protected: HEIGHTTYPE m_Height; // cTerrainHeightGen overrides: virtual void GenHeightMap(cChunkCoords a_ChunkCoords, cChunkDef::HeightMap & a_HeightMap) override; virtual void InitializeHeightGen(cIniFile & a_IniFile) override; } ; class cHeiGenClassic : public cTerrainHeightGen { public: cHeiGenClassic(int a_Seed); protected: int m_Seed; cNoise m_Noise; float m_HeightFreq1, m_HeightAmp1; float m_HeightFreq2, m_HeightAmp2; float m_HeightFreq3, m_HeightAmp3; float GetNoise(float x, float y); // cTerrainHeightGen overrides: virtual void GenHeightMap(cChunkCoords a_ChunkCoords, cChunkDef::HeightMap & a_HeightMap) override; virtual void InitializeHeightGen(cIniFile & a_IniFile) override; } ; class cHeiGenMountains : public cTerrainHeightGen { public: cHeiGenMountains(int a_Seed); protected: int m_Seed; cRidgedMultiNoise m_MountainNoise; cRidgedMultiNoise m_DitchNoise; cPerlinNoise m_Perlin; // cTerrainHeightGen overrides: virtual void GenHeightMap(cChunkCoords a_ChunkCoords, cChunkDef::HeightMap & a_HeightMap) override; virtual void InitializeHeightGen(cIniFile & a_IniFile) override; } ; class cHeiGenBiomal: public cTerrainHeightGen { using Super = cTerrainHeightGen; public: cHeiGenBiomal(int a_Seed, cBiomeGen & a_BiomeGen): m_Noise(a_Seed), m_BiomeGen(a_BiomeGen) { } // cTerrainHeightGen overrides: virtual void GenHeightMap(cChunkCoords a_ChunkCoords, cChunkDef::HeightMap & a_HeightMap) override; virtual HEIGHTTYPE GetHeightAt(int a_BlockX, int a_BlockZ) override // Need to provide this override due to clang's overzealous detection of overloaded virtuals { return Super::GetHeightAt(a_BlockX, a_BlockZ); } virtual void InitializeHeightGen(cIniFile & a_IniFile) override; protected: typedef cChunkDef::BiomeMap BiomeNeighbors[3][3]; cNoise m_Noise; cBiomeGen & m_BiomeGen; // Per-biome terrain generator parameters: struct sGenParam { float m_HeightFreq1, m_HeightAmp1; float m_HeightFreq2, m_HeightAmp2; float m_HeightFreq3, m_HeightAmp3; float m_BaseHeight; } ; static const sGenParam m_GenParam[256]; NOISE_DATATYPE GetHeightAt(int a_RelX, int a_RelZ, int a_ChunkX, int a_ChunkZ, const BiomeNeighbors & a_BiomeNeighbors); } ; ================================================ FILE: src/Generating/IntGen.h ================================================ // IntGen.h // Declares the cIntGen class and descendants for generating and filtering various 2D arrays of ints /* The integers generated may be interpreted in several ways: - land / sea designators - 0 = ocean - >0 = land - biome group - 0 = ocean - 1 = desert biomes - 2 = temperate biomes - 3 = mountains (hills and forests) - 4 = ice biomes - biome group with "bgfRare" flag (for generating rare biomes for the group) - biome IDs The interpretation depends on the generator used and on the position in the chain. The generators can be chained together - one produces data that another one consumes. Some of such chain connections require changing the data dimensions between the two, which is handled automatically by using templates. */ #pragma once #include #include "../Noise/Noise.h" #include "BiomeDef.h" /** Constants representing the biome group designators. */ const int bgOcean = 0; const int bgDesert = 1; const int bgTemperate = 2; const int bgMountains = 3; const int bgIce = 4; const int bgLandOceanMax = 4; // Maximum biome group value generated in the landOcean generator const int bgfRare = 1024; // Flag added to values to generate rare biomes for the group /** Interface that all the generator classes provide. */ template class cIntGen { public: using IntGenType = cIntGen; /** Force a virtual destructor in all descendants. Descendants contain virtual functions and are referred to via pointer-to-base, so they need a virtual destructor. */ virtual ~cIntGen() {} /** Holds the array of values generated by this class (descendant). */ using Values = int[SizeX * SizeZ]; /** Generates the array of templated size into a_Values, based on given min coords. */ virtual void GetInts(int a_MinX, int a_MinZ, Values & a_Values) = 0; }; // Code adapted from https://stackoverflow.com/questions/7858817/unpacking-a-tuple-to-call-a-matching-function-pointer template struct sSeq { }; template struct sGens : sGens { }; template struct sGens<0, S...> { using type = sSeq; }; template class cIntGenFactory { public: using Generator = Gen; cIntGenFactory(Args&&... a_args) : m_args(std::make_tuple(std::forward(a_args)...)) { } template std::shared_ptr construct(LhsGen&& a_Lhs) { return construct_impl(std::forward(a_Lhs), typename sGens::type()); } private: std::tuple m_args; template std::shared_ptr construct_impl(LhsGen&& a_Lhs, sSeq) { return std::make_shared(std::get(m_args)..., std::forward(a_Lhs)); } }; template std::shared_ptr operator| (std::shared_ptr a_Lhs, cIntGenFactory a_Rhs) { return a_Rhs.construct(static_cast>(a_Lhs)); } template cIntGenFactory MakeIntGen(Args&&... a_Args) { return cIntGenFactory(std::forward(a_Args)...); } /** Provides additional cNoise member and its helper functions. */ template class cIntGenWithNoise: public cIntGen { using Super = cIntGen; public: cIntGenWithNoise(int a_Seed): m_Noise(a_Seed) { } protected: cNoise m_Noise; /** Chooses one of a_Val1 or a_Val2, based on m_Noise and the coordinates for querying the noise. */ int ChooseRandomOne(int a_RndX, int a_RndZ, int a_Val1, int a_Val2) { int rnd = m_Noise.IntNoise2DInt(a_RndX, a_RndZ) / 7; return ((rnd & 1) == 0) ? a_Val1 : a_Val2; } /** Chooses one of a_ValN, based on m_Noise and the coordinates for querying the noise. */ int ChooseRandomOne(int a_RndX, int a_RndZ, int a_Val1, int a_Val2, int a_Val3, int a_Val4) { int rnd = m_Noise.IntNoise2DInt(a_RndX, a_RndZ) / 7; switch (rnd % 4) { case 0: return a_Val1; case 1: return a_Val2; case 2: return a_Val3; default: return a_Val4; } } }; /** Generates a 2D array of random integers in the specified range [0 .. Range). */ template class cIntGenChoice: public cIntGenWithNoise { using Super = cIntGenWithNoise; public: cIntGenChoice(int a_Seed): Super(a_Seed) { } virtual void GetInts(int a_MinX, int a_MinZ, typename Super::Values & a_Values) override { for (int z = 0; z < SizeZ; z++) { int BaseZ = a_MinZ + z; for (int x = 0; x < SizeX; x++) { a_Values[x + SizeX * z] = (Super::m_Noise.IntNoise2DInt(a_MinX + x, BaseZ) / 7) % Range; } } // for z } }; /** Decides between the ocean and landmass biomes. Has a threshold (in percent) of how much land, the larger the threshold, the more land. Generates 0 for ocean, biome group ID for landmass. */ template class cIntGenLandOcean: public cIntGenWithNoise { using Super = cIntGenWithNoise; public: cIntGenLandOcean(int a_Seed, int a_Threshold): Super(a_Seed), m_Threshold(a_Threshold) { } virtual void GetInts(int a_MinX, int a_MinZ, typename Super::Values & a_Values) override { for (int z = 0; z < SizeZ; z++) { int BaseZ = a_MinZ + z; for (int x = 0; x < SizeX; x++) { int rnd = (Super::m_Noise.IntNoise2DInt(a_MinX + x, BaseZ) / 7); a_Values[x + SizeX * z] = ((rnd % 100) < m_Threshold) ? ((rnd / 101) % bgLandOceanMax + 1) : 0; } } // If the centerpoint of the world is within the area, set it to bgTemperate, always: if ((a_MinX <= 0) && (a_MinZ <= 0) && (a_MinX + SizeX > 0) && (a_MinZ + SizeZ > 0)) { a_Values[-a_MinX - a_MinZ * SizeX] = bgTemperate; } } protected: int m_Threshold; }; /** Zooms the underlying value array to twice the size. Uses random-neighbor for the pixels in-between. This means that the zoome out image is randomly distorted. Applying zoom several times provides all the distortion that the generators need. */ template class cIntGenZoom: public cIntGenWithNoise { using Super = cIntGenWithNoise; protected: static const int m_LowerSizeX = (SizeX / 2) + 2; static const int m_LowerSizeZ = (SizeZ / 2) + 2; public: using Underlying = std::shared_ptr>; cIntGenZoom(int a_Seed, Underlying a_UnderlyingGen): Super(a_Seed), m_UnderlyingGen(a_UnderlyingGen) { } virtual void GetInts(int a_MinX, int a_MinZ, typename Super::Values & a_Values) override { // Generate the underlying data with half the resolution: int lowerMinX = a_MinX >> 1; int lowerMinZ = a_MinZ >> 1; int lowerData[m_LowerSizeX * m_LowerSizeZ]; m_UnderlyingGen->GetInts(lowerMinX, lowerMinZ, lowerData); const int lowStepX = (m_LowerSizeX - 1) * 2; const int lowStepZ = (m_LowerSizeZ - 1) * 2; int cache[lowStepX * lowStepZ]; // Discreet-interpolate the values into twice the size: for (int z = 0; z < m_LowerSizeZ - 1; ++z) { int idx = (z * 2) * lowStepX; int PrevZ0 = lowerData[z * m_LowerSizeX]; int PrevZ1 = lowerData[(z + 1) * m_LowerSizeX]; for (int x = 0; x < m_LowerSizeX - 1; ++x) { int ValX1Z0 = lowerData[x + 1 + z * m_LowerSizeX]; int ValX1Z1 = lowerData[x + 1 + (z + 1) * m_LowerSizeX]; int RndX = (x + lowerMinX) * 2; int RndZ = (z + lowerMinZ) * 2; cache[idx] = PrevZ0; cache[idx + lowStepX] = Super::ChooseRandomOne(RndX, RndZ + 1, PrevZ0, PrevZ1); cache[idx + 1] = Super::ChooseRandomOne(RndX, RndZ - 1, PrevZ0, ValX1Z0); cache[idx + 1 + lowStepX] = Super::ChooseRandomOne(RndX, RndZ, PrevZ0, ValX1Z0, PrevZ1, ValX1Z1); idx += 2; PrevZ0 = ValX1Z0; PrevZ1 = ValX1Z1; } } // Copy from Cache into a_Values; take into account the even / odd offsets in a_Min: for (int z = 0; z < SizeZ; ++z) { memcpy(a_Values + z * SizeX, cache + (z + (a_MinZ & 1)) * lowStepX + (a_MinX & 1), SizeX * sizeof(int)); } } protected: Underlying m_UnderlyingGen; }; /** Smoothes out some artifacts generated by the zooming - mostly single-pixel values. Compares each pixel to its neighbors and if the neighbors are equal, changes the pixel to their value. */ template class cIntGenSmooth: public cIntGenWithNoise { using Super = cIntGenWithNoise; static const int m_LowerSizeX = SizeX + 2; static const int m_LowerSizeZ = SizeZ + 2; public: using Underlying = std::shared_ptr>; cIntGenSmooth(int a_Seed, Underlying a_Underlying): Super(a_Seed), m_Underlying(a_Underlying) { } virtual void GetInts(int a_MinX, int a_MinZ, typename Super::Values & a_Values) override { // Generate the underlying values: int lowerData[m_LowerSizeX * m_LowerSizeZ]; m_Underlying->GetInts(a_MinX - 1, a_MinZ - 1, lowerData); // Smooth - for each square check if the surroundings are the same, if so, expand them diagonally. // Also get rid of single-pixel irregularities (A-B-A): for (int z = 0; z < SizeZ; z++) { int NoiseZ = a_MinZ + z; for (int x = 0; x < SizeX; x++) { int val = lowerData[x + 1 + (z + 1) * m_LowerSizeX]; int above = lowerData[x + 1 + z * m_LowerSizeX]; int below = lowerData[x + 1 + (z + 2) * m_LowerSizeX]; int left = lowerData[x + (z + 1) * m_LowerSizeX]; int right = lowerData[x + 2 + (z + 1) * m_LowerSizeX]; if ((left == right) && (above == below)) { if (((Super::m_Noise.IntNoise2DInt(a_MinX + x, NoiseZ) / 7) % 2) == 0) { val = left; } else { val = above; } } else { if (left == right) { val = left; } if (above == below) { val = above; } } a_Values[x + z * SizeX] = val; } } } protected: Underlying m_Underlying; }; /** Converts land biomes at the edge of an ocean into the respective beach biome. */ template class cIntGenBeaches: public cIntGen { using Super = cIntGen; static const int m_UnderlyingSizeX = SizeX + 2; static const int m_UnderlyingSizeZ = SizeZ + 2; public: using Underlying = std::shared_ptr>; cIntGenBeaches(Underlying a_Underlying): m_Underlying(a_Underlying) { } virtual void GetInts(int a_MinX, int a_MinZ, typename Super::Values & a_Values) override { // Map for biome -> its beach: static const int ToBeach[] = { /* biOcean */ biOcean, /* biPlains */ biBeach, /* biDesert */ biBeach, /* biExtremeHills */ biStoneBeach, /* biForest */ biBeach, /* biTaiga */ biColdBeach, /* biSwampland */ biSwampland, /* biRiver */ biRiver, /* biNether */ biNether, /* biEnd */ biEnd, /* biFrozenOcean */ biColdBeach, /* biFrozenRiver */ biColdBeach, /* biIcePlains */ biColdBeach, /* biIceMountains */ biColdBeach, /* biMushroomIsland */ biMushroomShore, /* biMushroomShore */ biMushroomShore, /* biBeach */ biBeach, /* biDesertHills */ biBeach, /* biForestHills */ biBeach, /* biTaigaHills */ biColdBeach, /* biExtremeHillsEdge */ biStoneBeach, /* biJungle */ biBeach, /* biJungleHills */ biBeach, /* biJungleEdge */ biBeach, /* biDeepOcean */ biOcean, /* biStoneBeach */ biStoneBeach, /* biColdBeach */ biColdBeach, /* biBirchForest */ biBeach, /* biBirchForestHills */ biBeach, /* biRoofedForest */ biBeach, /* biColdTaiga */ biColdBeach, /* biColdTaigaHills */ biColdBeach, /* biMegaTaiga */ biStoneBeach, /* biMegaTaigaHills */ biStoneBeach, /* biExtremeHillsPlus */ biStoneBeach, /* biSavanna */ biBeach, /* biSavannaPlateau */ biBeach, /* biMesa */ biMesa, /* biMesaPlateauF */ biMesa, /* biMesaPlateau */ biMesa, }; // Generate the underlying values: int lowerValues[m_UnderlyingSizeX * m_UnderlyingSizeZ]; m_Underlying->GetInts(a_MinX - 1, a_MinZ - 1, lowerValues); // Add beaches between ocean and biomes: for (int z = 0; z < SizeZ; z++) { for (int x = 0; x < SizeX; x++) { int val = lowerValues[x + 1 + (z + 1) * m_UnderlyingSizeX]; int above = lowerValues[x + 1 + z * m_UnderlyingSizeX]; int below = lowerValues[x + 1 + (z + 2) * m_UnderlyingSizeX]; int left = lowerValues[x + (z + 1) * m_UnderlyingSizeX]; int right = lowerValues[x + 2 + (z + 1) * m_UnderlyingSizeX]; if (!IsBiomeOcean(val)) { if (IsBiomeOcean(above) || IsBiomeOcean(below) || IsBiomeOcean(left) || IsBiomeOcean(right)) { // First convert the value to a regular biome (drop the M flag), then modulo by our biome count: val = ToBeach[static_cast((val % 128)) % ARRAYCOUNT(ToBeach)]; } } a_Values[x + z * SizeX] = val; } } } protected: Underlying m_Underlying; }; /** Generates the underlying numbers and then randomly changes some ocean group pixels into random land biome group pixels, based on the predefined chance. */ template class cIntGenAddIslands: public cIntGenWithNoise { using Super = cIntGenWithNoise; public: using Underlying = std::shared_ptr>; cIntGenAddIslands(int a_Seed, int a_Chance, Underlying a_Underlying): Super(a_Seed), m_Chance(a_Chance), m_Underlying(a_Underlying) { } virtual void GetInts(int a_MinX, int a_MinZ, typename Super::Values & a_Values) override { m_Underlying->GetInts(a_MinX, a_MinZ, a_Values); for (int z = 0; z < SizeZ; z++) { for (int x = 0; x < SizeX; x++) { if (a_Values[x + z * SizeX] == bgOcean) { int rnd = Super::m_Noise.IntNoise2DInt(a_MinX + x, a_MinZ + z) / 7; if (rnd % 1000 < m_Chance) { a_Values[x + z * SizeX] = (rnd / 1003) % bgLandOceanMax; } } } // for x } // for z } protected: /** Chance, in permille, of an island being generated in ocean. */ int m_Chance; Underlying m_Underlying; }; /** A filter that adds an edge biome group between two biome groups that need an edge between them. */ template class cIntGenBiomeGroupEdges: public cIntGen { using Super = cIntGen; static const int m_UnderlyingSizeX = SizeX + 2; static const int m_UnderlyingSizeZ = SizeZ + 2; public: using Underlying = std::shared_ptr>; cIntGenBiomeGroupEdges(Underlying a_Underlying): m_Underlying(a_Underlying) { } virtual void GetInts(int a_MinX, int a_MinZ, typename Super::Values & a_Values) override { // Generate the underlying biome groups: int lowerValues[m_UnderlyingSizeX * m_UnderlyingSizeZ]; m_Underlying->GetInts(a_MinX, a_MinZ, lowerValues); // Change the biomes on incompatible edges into an edge biome: for (int z = 0; z < SizeZ; z++) { for (int x = 0; x < SizeX; x++) { int val = lowerValues[x + 1 + (z + 1) * m_UnderlyingSizeX]; int above = lowerValues[x + 1 + z * m_UnderlyingSizeX]; int below = lowerValues[x + 1 + (z + 2) * m_UnderlyingSizeX]; int left = lowerValues[x + (z + 1) * m_UnderlyingSizeX]; int right = lowerValues[x + 2 + (z + 1) * m_UnderlyingSizeX]; switch (val) { // Desert should neighbor only oceans, desert and temperates; change to temperate when another: case bgDesert: { if ( !isDesertCompatible(above) || !isDesertCompatible(below) || !isDesertCompatible(left) || !isDesertCompatible(right) ) { val = bgTemperate; } break; } // case bgDesert // Ice should not neighbor deserts; change to temperate: case bgIce: { if ( (above == bgDesert) || (below == bgDesert) || (left == bgDesert) || (right == bgDesert) ) { val = bgTemperate; } break; } // case bgIce } a_Values[x + z * SizeX] = val; } // for x } // for z } protected: Underlying m_Underlying; inline bool isDesertCompatible(int a_BiomeGroup) { switch (a_BiomeGroup) { case bgOcean: case bgDesert: case bgTemperate: { return true; } default: { return false; } } } }; /** Turns biome group indices into real biomes. For each pixel, takes its biome group and chooses a random biome from that group; replaces the value with that biome. */ template class cIntGenBiomes: public cIntGenWithNoise { using Super = cIntGenWithNoise; public: using Underlying = std::shared_ptr>; cIntGenBiomes(int a_Seed, Underlying a_Underlying): Super(a_Seed), m_Underlying(a_Underlying) { } virtual void GetInts(int a_MinX, int a_MinZ, typename Super::Values & a_Values) override { // Define the per-biome-group biomes: static const int oceanBiomes[] = { biOcean, // biDeepOcean, }; // Same as oceanBiomes, there are no rare oceanic biomes (mushroom islands are handled separately) static const int rareOceanBiomes[] = { biOcean, }; static const int desertBiomes[] = { biDesert, biDesert, biDesert, biDesert, biDesert, biDesert, biSavanna, biSavanna, biPlains, }; static const int rareDesertBiomes[] = { biMesaPlateau, biMesaPlateauF, }; static const int temperateBiomes[] = { biForest, biForest, biRoofedForest, biExtremeHills, biPlains, biBirchForest, biSwampland, }; static const int rareTemperateBiomes[] = { biJungle, // Jungle is not strictly temperate, but let's piggyback it here }; static const int mountainBiomes[] = { biExtremeHills, biForest, biTaiga, biPlains, }; static const int rareMountainBiomes[] = { biMegaTaiga, }; static const int iceBiomes[] = { biIcePlains, biIcePlains, biIcePlains, biIcePlains, biColdTaiga, }; // Same as iceBiomes, there's no rare ice biome static const int rareIceBiomes[] = { biIcePlains, biIcePlains, biIcePlains, biIcePlains, biColdTaiga, }; static const cBiomesInGroups biomesInGroups[] = { /* bgOcean */ { static_cast(ARRAYCOUNT(oceanBiomes)), oceanBiomes}, /* bgDesert */ { static_cast(ARRAYCOUNT(desertBiomes)), desertBiomes}, /* bgTemperate */ { static_cast(ARRAYCOUNT(temperateBiomes)), temperateBiomes}, /* bgMountains */ { static_cast(ARRAYCOUNT(mountainBiomes)), mountainBiomes}, /* bgIce */ { static_cast(ARRAYCOUNT(iceBiomes)), iceBiomes}, }; static const cBiomesInGroups rareBiomesInGroups[] = { /* bgOcean */ { static_cast(ARRAYCOUNT(rareOceanBiomes)), rareOceanBiomes}, /* bgDesert */ { static_cast(ARRAYCOUNT(rareDesertBiomes)), rareDesertBiomes}, /* bgTemperate */ { static_cast(ARRAYCOUNT(rareTemperateBiomes)), rareTemperateBiomes}, /* bgMountains */ { static_cast(ARRAYCOUNT(rareMountainBiomes)), rareMountainBiomes}, /* bgIce */ { static_cast(ARRAYCOUNT(rareIceBiomes)), rareIceBiomes}, }; // Generate the underlying values, representing biome groups: m_Underlying->GetInts(a_MinX, a_MinZ, a_Values); // Overwrite each biome group with a random biome from that group: for (int z = 0; z < SizeZ; z++) { int IdxZ = z * SizeX; for (int x = 0; x < SizeX; x++) { size_t val = static_cast(a_Values[x + IdxZ]); const cBiomesInGroups & Biomes = (val > bgfRare) ? rareBiomesInGroups[(val & (bgfRare - 1)) % ARRAYCOUNT(rareBiomesInGroups)] : biomesInGroups[val % ARRAYCOUNT(biomesInGroups)]; int rnd = (Super::m_Noise.IntNoise2DInt(x + a_MinX, z + a_MinZ) / 7); a_Values[x + IdxZ] = Biomes.Biomes[rnd % Biomes.Count]; } } } protected: struct cBiomesInGroups { const int Count; const int * Biomes; }; /** The underlying int generator */ Underlying m_Underlying; }; /** Randomly replaces pixels of one value to another value, using the given chance. */ template class cIntGenReplaceRandomly: public cIntGenWithNoise { using Super = cIntGenWithNoise; public: using Underlying = std::shared_ptr>; cIntGenReplaceRandomly(int a_From, int a_To, int a_Chance, int a_Seed, Underlying a_Underlying): Super(a_Seed), m_From(a_From), m_To(a_To), m_Chance(a_Chance), m_Underlying(a_Underlying) { } virtual void GetInts(int a_MinX, int a_MinZ, typename Super::Values & a_Values) override { // Generate the underlying values: m_Underlying->GetInts(a_MinX, a_MinZ, a_Values); // Replace some of the values: for (int z = 0; z < SizeZ; z++) { int idxZ = z * SizeX; for (int x = 0; x < SizeX; x++) { int idx = x + idxZ; if (a_Values[idx] == m_From) { int rnd = Super::m_Noise.IntNoise2DInt(x + a_MinX, z + a_MinZ) / 7; if (rnd % 1000 < m_Chance) { a_Values[idx] = m_To; } } } } // for z } protected: /** The original value to be replaced. */ int m_From; /** The destination value to which to replace. */ int m_To; /** Chance, in permille, of replacing the value. */ int m_Chance; Underlying m_Underlying; }; /** Mixer that joins together finalized biomes and rivers. It first checks for oceans, if there is an ocean in the Biomes, it keeps the ocean. If there's no ocean, it checks Rivers for a river, if there is a river, it uses the Biomes to select either regular river or frozen river, based on the biome. */ template class cIntGenMixRivers: public cIntGen { using Super = cIntGen; public: using Underlying = std::shared_ptr>; cIntGenMixRivers(Underlying a_Biomes, Underlying a_Rivers): m_Biomes(a_Biomes), m_Rivers(a_Rivers) { } virtual void GetInts(int a_MinX, int a_MinZ, typename Super::Values & a_Values) override { // Generate the underlying data: m_Biomes->GetInts(a_MinX, a_MinZ, a_Values); typename Super::Values riverData; m_Rivers->GetInts(a_MinX, a_MinZ, riverData); // Mix the values: for (int z = 0; z < SizeZ; z++) { int idxZ = z * SizeX; for (int x = 0; x < SizeX; x++) { int idx = x + idxZ; if (IsBiomeOcean(a_Values[idx])) { // Oceans are kept without any changes continue; } if (riverData[idx] != biRiver) { // There's no river, keep the current value continue; } // There's a river, change the output to a river or a frozen river, based on the original biome: if (IsBiomeVeryCold(static_cast(a_Values[idx]))) { a_Values[idx] = biFrozenRiver; } else { a_Values[idx] = biRiver; } } // for x } // for z } protected: Underlying m_Biomes; Underlying m_Rivers; }; /** Generates a river based on the underlying data. This is basically an edge detector over the underlying data. The rivers are the edges where the underlying data changes from one pixel to its neighbor. */ template class cIntGenRiver: public cIntGenWithNoise { using Super = cIntGenWithNoise; static const int UnderlyingSizeX = SizeX + 2; static const int UnderlyingSizeZ = SizeZ + 2; public: using Underlying = std::shared_ptr>; cIntGenRiver(int a_Seed, Underlying a_Underlying): Super(a_Seed), m_Underlying(a_Underlying) { } virtual void GetInts(int a_MinX, int a_MinZ, typename Super::Values & a_Values) override { // Generate the underlying data: int Cache[UnderlyingSizeX * UnderlyingSizeZ]; m_Underlying->GetInts(a_MinX - 1, a_MinZ - 1, Cache); // Detect the edges: for (int z = 0; z < SizeZ; z++) { for (int x = 0; x < SizeX; x++) { int Above = Cache[x + 1 + z * UnderlyingSizeX]; int Below = Cache[x + 1 + (z + 2) * UnderlyingSizeX]; int Left = Cache[x + (z + 1) * UnderlyingSizeX]; int Right = Cache[x + 2 + (z + 1) * UnderlyingSizeX]; int val = Cache[x + 1 + (z + 1) * UnderlyingSizeX]; if ((val == Above) && (val == Below) && (val == Left) && (val == Right)) { val = 0; } else { val = biRiver; } a_Values[x + z * SizeX] = val; } // for x } // for z } protected: Underlying m_Underlying; }; /** Turns some of the oceans into the specified biome. Used for mushroom and deep ocean. The biome is only placed if at least 3 of its neighbors are ocean and only with the specified chance. */ template class cIntGenAddToOcean: public cIntGenWithNoise { using Super = cIntGenWithNoise; static const int UnderlyingSizeX = SizeX + 2; static const int UnderlyingSizeZ = SizeZ + 2; public: using Underlying = std::shared_ptr>; cIntGenAddToOcean(int a_Seed, int a_Chance, int a_ToValue, Underlying a_Underlying): Super(a_Seed), m_Chance(a_Chance), m_ToValue(a_ToValue), m_Underlying(a_Underlying) { } virtual void GetInts(int a_MinX, int a_MinZ, typename Super::Values & a_Values) override { // Generate the underlying data: int Cache[UnderlyingSizeX * UnderlyingSizeZ]; m_Underlying->GetInts(a_MinX - 1, a_MinZ - 1, Cache); // Add the mushroom islands: for (int z = 0; z < SizeZ; z++) { for (int x = 0; x < SizeX; x++) { int val = Cache[x + 1 + (z + 1) * UnderlyingSizeX]; if (!IsBiomeOcean(val)) { a_Values[x + z * SizeX] = val; continue; } // Count the ocean neighbors: int Above = Cache[x + 1 + z * UnderlyingSizeX]; int Below = Cache[x + 1 + (z + 2) * UnderlyingSizeX]; int Left = Cache[x + (z + 1) * UnderlyingSizeX]; int Right = Cache[x + 2 + (z + 1) * UnderlyingSizeX]; int NumOceanNeighbors = 0; if (IsBiomeOcean(Above)) { NumOceanNeighbors += 1; } if (IsBiomeOcean(Below)) { NumOceanNeighbors += 1; } if (IsBiomeOcean(Left)) { NumOceanNeighbors += 1; } if (IsBiomeOcean(Right)) { NumOceanNeighbors += 1; } // If at least 3 ocean neighbors and the chance is right, change: if ( (NumOceanNeighbors >= 3) && ((Super::m_Noise.IntNoise2DInt(x + a_MinX, z + a_MinZ) / 7) % 1000 < m_Chance) ) { a_Values[x + z * SizeX] = m_ToValue; } else { a_Values[x + z * SizeX] = val; } } // for x } // for z } protected: /** Chance, in permille, of changing the biome. */ int m_Chance; /** The value to change the ocean into. */ int m_ToValue; Underlying m_Underlying; }; /** Changes random pixels of the underlying data to the specified value. */ template class cIntGenSetRandomly: public cIntGenWithNoise { using Super = cIntGenWithNoise; public: using Underlying = std::shared_ptr>; cIntGenSetRandomly(int a_Seed, int a_Chance, int a_ToValue, Underlying a_Underlying): Super(a_Seed), m_Chance(a_Chance), m_ToValue(a_ToValue), m_Underlying(a_Underlying) { } virtual void GetInts(int a_MinX, int a_MinZ, typename Super::Values & a_Values) override { // Generate the underlying data: m_Underlying->GetInts(a_MinX, a_MinZ, a_Values); // Change random pixels to bgOcean: for (int z = 0; z < SizeZ; z++) { for (int x = 0; x < SizeX; x++) { int rnd = Super::m_Noise.IntNoise2DInt(x + a_MinX, z + a_MinZ) / 7; if (rnd % 1000 < m_Chance) { a_Values[x + z * SizeX] = m_ToValue; } } } } protected: /** Chance, in permille, of changing each pixel. */ int m_Chance; /** The value to which to set the pixel. */ int m_ToValue; Underlying m_Underlying; }; /** Adds a "rare" flag to random biome groups, based on the given chance. */ template class cIntGenRareBiomeGroups: public cIntGenWithNoise { using Super = cIntGenWithNoise; public: using Underlying = std::shared_ptr>; cIntGenRareBiomeGroups(int a_Seed, int a_Chance, Underlying a_Underlying): Super(a_Seed), m_Chance(a_Chance), m_Underlying(a_Underlying) { } virtual void GetInts(int a_MinX, int a_MinZ, typename Super::Values & a_Values) override { // Generate the underlying data: m_Underlying->GetInts(a_MinX, a_MinZ, a_Values); // Change some of the biome groups into rare biome groups: for (int z = 0; z < SizeZ; z++) { for (int x = 0; x < SizeX; x++) { int rnd = Super::m_Noise.IntNoise2DInt(x + a_MinX, z + a_MinZ) / 7; if (rnd % 1000 < m_Chance) { int idx = x + SizeX * z; a_Values[idx] = a_Values[idx] | bgfRare; } } } } protected: /** Chance, in permille, of changing each pixel into the rare biome group. */ int m_Chance; /** The underlying generator. */ Underlying m_Underlying; }; /** Changes biomes in the parent data into an alternate versions (usually "hill" variants), in such places that have their alterations set. */ template class cIntGenAlternateBiomes: public cIntGenWithNoise { using Super = cIntGenWithNoise; public: using Underlying = std::shared_ptr>; cIntGenAlternateBiomes(int a_Seed, Underlying a_Alterations, Underlying a_BaseBiomes): Super(a_Seed), m_Alterations(a_Alterations), m_BaseBiomes(a_BaseBiomes) { } virtual void GetInts(int a_MinX, int a_MinZ, typename Super::Values & a_Values) override { // Generate the base biomes and the alterations: m_BaseBiomes->GetInts(a_MinX, a_MinZ, a_Values); typename Super::Values alterations; m_Alterations->GetInts(a_MinX, a_MinZ, alterations); // Change the biomes into their alternate versions: for (int idx = 0; idx < SizeX * SizeZ; ++idx) { if (alterations[idx] == 0) { // No change continue; } // Change to alternate biomes: int val = a_Values[idx]; switch (val) { case biBirchForest: val = biBirchForestHills; break; case biDesert: val = biDesertHills; break; case biExtremeHills: val = biExtremeHillsPlus; break; case biForest: val = biForestHills; break; case biIcePlains: val = biIceMountains; break; case biJungle: val = biJungleHills; break; case biMegaTaiga: val = biMegaTaigaHills; break; case biMesaPlateau: val = biMesa; break; case biMesaPlateauF: val = biMesa; break; case biMesaPlateauM: val = biMesa; break; case biMesaPlateauFM: val = biMesa; break; case biPlains: val = biForest; break; case biRoofedForest: val = biPlains; break; case biSavanna: val = biSavannaPlateau; break; case biTaiga: val = biTaigaHills; break; } a_Values[idx] = val; } // for idx - a_Values[] } protected: Underlying m_Alterations; Underlying m_BaseBiomes; }; /** Adds an edge between two specifically incompatible biomes, such as mesa and forest. */ template class cIntGenBiomeEdges: public cIntGenWithNoise { using Super = cIntGenWithNoise; static const int m_LowerSizeX = SizeX + 2; static const int m_LowerSizeZ = SizeZ + 2; public: using Underlying = std::shared_ptr>; cIntGenBiomeEdges(int a_Seed, Underlying a_Underlying): Super(a_Seed), m_Underlying(a_Underlying) { } virtual void GetInts(int a_MinX, int a_MinZ, typename Super::Values & a_Values) override { // Generate the underlying biomes: typename Underlying::element_type::Values lowerValues; m_Underlying->GetInts(a_MinX - 1, a_MinZ - 1, lowerValues); // Convert incompatible edges into neutral biomes: for (int z = 0; z < SizeZ; z++) { for (int x = 0; x < SizeX; x++) { int biome = lowerValues[x + 1 + (z + 1) * m_LowerSizeX]; int above = lowerValues[x + 1 + z * m_LowerSizeX]; int below = lowerValues[x + 1 + (z + 2) * m_LowerSizeX]; int left = lowerValues[x + (z + 1) * m_LowerSizeX]; int right = lowerValues[x + 2 + (z + 1) * m_LowerSizeX]; switch (biome) { case biDesert: case biDesertM: case biDesertHills: { if ( IsBiomeVeryCold(static_cast(above)) || IsBiomeVeryCold(static_cast(below)) || IsBiomeVeryCold(static_cast(left)) || IsBiomeVeryCold(static_cast(right)) ) { biome = biPlains; } break; } // case biDesert case biMesaPlateau: case biMesaPlateauF: case biMesaPlateauFM: case biMesaPlateauM: { if ( !isMesaCompatible(above) || !isMesaCompatible(below) || !isMesaCompatible(left) || !isMesaCompatible(right) ) { biome = biDesert; } break; } // Mesa biomes case biJungle: case biJungleM: { if ( !isJungleCompatible(above) || !isJungleCompatible(below) || !isJungleCompatible(left) || !isJungleCompatible(right) ) { biome = (biome == biJungle) ? biJungleEdge : biJungleEdgeM; } break; } // Jungle biomes case biSwampland: case biSwamplandM: { if ( IsBiomeNoDownfall(static_cast(above)) || IsBiomeNoDownfall(static_cast(below)) || IsBiomeNoDownfall(static_cast(left)) || IsBiomeNoDownfall(static_cast(right)) ) { biome = biPlains; } break; } // Swampland biomes } // switch (biome) a_Values[x + z * SizeX] = biome; } // for x } // for z } protected: Underlying m_Underlying; bool isMesaCompatible(int a_Biome) { switch (a_Biome) { case biDesert: case biMesa: case biMesaBryce: case biMesaPlateau: case biMesaPlateauF: case biMesaPlateauFM: case biMesaPlateauM: case biOcean: case biDeepOcean: { return true; } default: { return false; } } } bool isJungleCompatible(int a_Biome) { switch (a_Biome) { case biJungle: case biJungleM: case biJungleEdge: case biJungleEdgeM: case biJungleHills: { return true; } default: { return false; } } } }; /** Changes biomes in the parent data into their alternate versions ("M" variants), in such places that have their alterations set. */ template class cIntGenMBiomes: public cIntGenWithNoise { using Super = cIntGenWithNoise; public: using Underlying = std::shared_ptr>; cIntGenMBiomes(int a_Seed, Underlying a_Alteration, Underlying a_Underlying): Super(a_Seed), m_Underlying(a_Underlying), m_Alteration(a_Alteration) { } virtual void GetInts(int a_MinX, int a_MinZ, typename Super::Values & a_Values) override { // Generate the underlying biomes and the alterations: m_Underlying->GetInts(a_MinX, a_MinZ, a_Values); typename Super::Values alterations; m_Alteration->GetInts(a_MinX, a_MinZ, alterations); // Wherever alterations are nonzero, change into alternate biome, if available: for (int idx = 0; idx < SizeX * SizeZ; ++idx) { if (alterations[idx] == 0) { continue; } // Ice spikes biome was removed from here, because it was generated way too often switch (a_Values[idx]) { case biPlains: a_Values[idx] = biSunflowerPlains; break; case biDesert: a_Values[idx] = biDesertM; break; case biExtremeHills: a_Values[idx] = biExtremeHillsM; break; case biForest: a_Values[idx] = biFlowerForest; break; case biTaiga: a_Values[idx] = biTaigaM; break; case biSwampland: a_Values[idx] = biSwamplandM; break; case biJungle: a_Values[idx] = biJungleM; break; case biJungleEdge: a_Values[idx] = biJungleEdgeM; break; case biBirchForest: a_Values[idx] = biBirchForestM; break; case biBirchForestHills: a_Values[idx] = biBirchForestHillsM; break; case biRoofedForest: a_Values[idx] = biRoofedForestM; break; case biColdTaiga: a_Values[idx] = biColdTaigaM; break; case biMegaSpruceTaiga: a_Values[idx] = biMegaSpruceTaiga; break; case biMegaSpruceTaigaHills: a_Values[idx] = biMegaSpruceTaigaHills; break; case biExtremeHillsPlus: a_Values[idx] = biExtremeHillsPlusM; break; case biSavanna: a_Values[idx] = biSavannaM; break; case biSavannaPlateau: a_Values[idx] = biSavannaPlateauM; break; case biMesa: a_Values[idx] = biMesaBryce; break; case biMesaPlateauF: a_Values[idx] = biMesaPlateauFM; break; case biMesaPlateau: a_Values[idx] = biMesaBryce; break; } } // for idx - a_Values[] / alterations[] } protected: Underlying m_Underlying; Underlying m_Alteration; }; ================================================ FILE: src/Generating/MineShafts.cpp ================================================ // MineShafts.cpp // Implements the cStructGenMineShafts class representing the structure generator for abandoned mineshafts /* Algorithm: The cStructGenMineShafts::cMineShaftSystem class is the main controller, which knows what mineshaft classes there are and their random weights. It gets asked to produce a new class everytime a connection is to be made. The cMineShaft class is a base class for each mineshaft structure. Each cMineShaft descendant knows how large it is, how to imprint itself into the chunk data and where to connect to other descendants. Its PivotPoint is always a walkable column. Its Direction determines in which direction the structure is facing. The generation starts with the central dirt room, from there corridors, crossings and staircases are added in a depth-first processing. Each of the descendants will branch randomly, if not beyond the allowed recursion level */ #include "Globals.h" #include "MineShafts.h" #include "../Cuboid.h" #include "../BlockEntities/ChestEntity.h" #include "../BlockEntities/MobSpawnerEntity.h" class cMineShaft { public: enum eKind { mskDirtRoom, mskCorridor, mskCrossing, mskStaircase, } ; enum eDirection { dirXP, dirZP, dirXM, dirZM, } ; cStructGenMineShafts::cMineShaftSystem & m_ParentSystem; eKind m_Kind; cCuboid m_BoundingBox; cMineShaft(cStructGenMineShafts::cMineShaftSystem & a_ParentSystem, eKind a_Kind) : m_ParentSystem(a_ParentSystem), m_Kind(a_Kind) { } cMineShaft(cStructGenMineShafts::cMineShaftSystem & a_ParentSystem, eKind a_Kind, const cCuboid & a_BoundingBox) : m_ParentSystem(a_ParentSystem), m_Kind(a_Kind), m_BoundingBox(a_BoundingBox) { } virtual ~cMineShaft() {} /** Returns true if this mineshaft intersects the specified cuboid */ bool DoesIntersect(const cCuboid & a_Other) { return m_BoundingBox.DoesIntersect(a_Other); } /** If recursion level is not too large, appends more branches to the parent system, using exit points specific to this class. */ virtual void AppendBranches(int a_RecursionLevel, cNoise & a_Noise) = 0; /** Imprints this shape into the specified chunk's data */ virtual void ProcessChunk(cChunkDesc & a_ChunkDesc) = 0; } ; using cMineShafts = std::vector; class cMineShaftDirtRoom: public cMineShaft { using Super = cMineShaft; public: cMineShaftDirtRoom(cStructGenMineShafts::cMineShaftSystem & a_Parent, cNoise & a_Noise); // cMineShaft overrides: virtual void AppendBranches(int a_RecursionLevel, cNoise & a_Noise) override; virtual void ProcessChunk(cChunkDesc & a_ChunkDesc) override; } ; class cMineShaftCorridor: public cMineShaft { using Super = cMineShaft; public: /** Creates a new Corridor attached to the specified pivot point and direction. Checks all ParentSystem's objects and disallows intersecting. Initializes the new object to fit. May return nullptr if cannot fit. */ static cMineShaft * CreateAndFit( cStructGenMineShafts::cMineShaftSystem & a_ParentSystem, int a_PivotX, int a_PivotY, int a_PivotZ, eDirection a_Direction, cNoise & a_Noise ); protected: static const int MAX_SEGMENTS = 5; int m_NumSegments; eDirection m_Direction; bool m_HasFullBeam[MAX_SEGMENTS]; ///< If true, segment at that index has a full beam support (planks in the top center block) int m_ChestPosition; ///< If <0, no chest; otherwise an offset from m_BoundingBox's p1.x or p1.z, depenging on m_Direction int m_SpawnerPosition; ///< If <0, no spawner; otherwise an offset from m_BoundingBox's p1.x or p1.z, depenging on m_Direction bool m_HasTracks; ///< If true, random tracks will be placed on the floor cMineShaftCorridor( cStructGenMineShafts::cMineShaftSystem & a_ParentSystem, const cCuboid & a_BoundingBox, int a_NumSegments, eDirection a_Direction, cNoise & a_Noise ); // cMineShaft overrides: virtual void AppendBranches(int a_RecursionLevel, cNoise & a_Noise) override; virtual void ProcessChunk(cChunkDesc & a_ChunkDesc) override; /** Places a chest, if the corridor has one */ void PlaceChest(cChunkDesc & a_ChunkDesc); /** If this corridor has tracks, places them randomly */ void PlaceTracks(cChunkDesc & a_ChunkDesc); /** If this corridor has a spawner, places the spawner */ void PlaceSpawner(cChunkDesc & a_ChunkDesc); /** Randomly places torches around the central beam block */ void PlaceTorches(cChunkDesc & a_ChunkDesc); } ; class cMineShaftCrossing: public cMineShaft { using Super = cMineShaft; public: /** Creates a new Crossing attached to the specified pivot point and direction. Checks all ParentSystem's objects and disallows intersecting. Initializes the new object to fit. May return nullptr if cannot fit. */ static cMineShaft * CreateAndFit( cStructGenMineShafts::cMineShaftSystem & a_ParentSystem, int a_PivotX, int a_PivotY, int a_PivotZ, eDirection a_Direction, cNoise & a_Noise ); protected: cMineShaftCrossing(cStructGenMineShafts::cMineShaftSystem & a_ParentSystem, const cCuboid & a_BoundingBox); // cMineShaft overrides: virtual void AppendBranches(int a_RecursionLevel, cNoise & a_Noise) override; virtual void ProcessChunk(cChunkDesc & a_ChunkDesc) override; } ; class cMineShaftStaircase: public cMineShaft { using Super = cMineShaft; public: enum eSlope { sUp, sDown, } ; /** Creates a new Staircase attached to the specified pivot point and direction. Checks all ParentSystem's objects and disallows intersecting. Initializes the new object to fit. May return nullptr if cannot fit. */ static cMineShaft * CreateAndFit( cStructGenMineShafts::cMineShaftSystem & a_ParentSystem, int a_PivotX, int a_PivotY, int a_PivotZ, eDirection a_Direction, cNoise & a_Noise ); protected: eDirection m_Direction; eSlope m_Slope; cMineShaftStaircase( cStructGenMineShafts::cMineShaftSystem & a_ParentSystem, const cCuboid & a_BoundingBox, eDirection a_Direction, eSlope a_Slope ); // cMineShaft overrides: virtual void AppendBranches(int a_RecursionLevel, cNoise & a_Noise) override; virtual void ProcessChunk(cChunkDesc & a_ChunkDesc) override; } ; class cStructGenMineShafts::cMineShaftSystem: public cGridStructGen::cStructure { using Super = cGridStructGen::cStructure; public: int m_GridSize; ///< Maximum offset of the dirtroom from grid center, * 2, in each direction int m_MaxRecursion; ///< Maximum recursion level (initialized from cStructGenMineShafts::m_MaxRecursion) int m_ProbLevelCorridor; ///< Probability level of a branch object being the corridor int m_ProbLevelCrossing; ///< Probability level of a branch object being the crossing, minus Corridor int m_ProbLevelStaircase; ///< Probability level of a branch object being the staircase, minus Crossing int m_ChanceChest; ///< Chance [0 .. 250] that a corridor has a chest in it int m_ChanceSpawner; ///< Chance [0 .. 250] that a corridor has a spawner in it int m_ChanceTorch; ///< Chance [0 .. 10k] for a torch appearing attached to a corridor's beam cMineShafts m_MineShafts; ///< List of cMineShaft descendants that comprise this system cCuboid m_BoundingBox; ///< Bounding box into which all of the components need to fit /** Creates and generates the entire system */ cMineShaftSystem( int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ, int a_GridSize, int a_MaxSystemSize, cNoise & a_Noise, int a_ProbLevelCorridor, int a_ProbLevelCrossing, int a_ProbLevelStaircase ); virtual ~cMineShaftSystem() override; /** Creates new cMineShaft descendant connected at the specified point, heading the specified direction, if it fits, appends it to the list and calls its AppendBranches() */ void AppendBranch( int a_BlockX, int a_BlockY, int a_BlockZ, cMineShaft::eDirection a_Direction, cNoise & a_Noise, int a_RecursionLevel ); /** Returns true if none of the objects in m_MineShafts intersect with the specified bounding box and the bounding box is valid */ bool CanAppend(const cCuboid & a_BoundingBox); // cGridStructGen::cStructure overrides: virtual void DrawIntoChunk(cChunkDesc & a_Chunk) override; } ; //////////////////////////////////////////////////////////////////////////////// // cStructGenMineShafts::cMineShaftSystem: cStructGenMineShafts::cMineShaftSystem::cMineShaftSystem( int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ, int a_GridSize, int a_MaxSystemSize, cNoise & a_Noise, int a_ProbLevelCorridor, int a_ProbLevelCrossing, int a_ProbLevelStaircase ) : Super(a_GridX, a_GridZ, a_OriginX, a_OriginZ), m_GridSize(a_GridSize), m_MaxRecursion(8), // TODO: settable m_ProbLevelCorridor(a_ProbLevelCorridor), m_ProbLevelCrossing(a_ProbLevelCrossing), m_ProbLevelStaircase(a_ProbLevelStaircase + 1), m_ChanceChest(12), // TODO: settable m_ChanceSpawner(12), // TODO: settable m_ChanceTorch(1000) // TODO: settable { m_MineShafts.reserve(100); cMineShaft * Start = new cMineShaftDirtRoom(*this, a_Noise); m_MineShafts.push_back(Start); m_BoundingBox.Assign( {Start->m_BoundingBox.p1.x - a_MaxSystemSize / 2, 2, Start->m_BoundingBox.p1.z - a_MaxSystemSize / 2}, {Start->m_BoundingBox.p2.x + a_MaxSystemSize / 2, 50, Start->m_BoundingBox.p2.z + a_MaxSystemSize / 2} ); Start->AppendBranches(0, a_Noise); for (cMineShafts::const_iterator itr = m_MineShafts.begin(), end = m_MineShafts.end(); itr != end; ++itr) { ASSERT((*itr)->m_BoundingBox.IsSorted()); } // for itr - m_MineShafts[] } cStructGenMineShafts::cMineShaftSystem::~cMineShaftSystem() { for (cMineShafts::iterator itr = m_MineShafts.begin(), end = m_MineShafts.end(); itr != end; ++itr) { delete *itr; } // for itr - m_MineShafts[] m_MineShafts.clear(); } void cStructGenMineShafts::cMineShaftSystem::DrawIntoChunk(cChunkDesc & a_Chunk) { for (cMineShafts::const_iterator itr = m_MineShafts.begin(), end = m_MineShafts.end(); itr != end; ++itr) { (*itr)->ProcessChunk(a_Chunk); } // for itr - m_MineShafts[] } void cStructGenMineShafts::cMineShaftSystem::AppendBranch( int a_PivotX, int a_PivotY, int a_PivotZ, cMineShaft::eDirection a_Direction, cNoise & a_Noise, int a_RecursionLevel ) { if (a_RecursionLevel > m_MaxRecursion) { return; } cMineShaft * Next = nullptr; int rnd = (a_Noise.IntNoise3DInt(a_PivotX, a_PivotY + a_RecursionLevel * 16, a_PivotZ) / 13) % m_ProbLevelStaircase; if (rnd < m_ProbLevelCorridor) { Next = cMineShaftCorridor::CreateAndFit(*this, a_PivotX, a_PivotY, a_PivotZ, a_Direction, a_Noise); } else if (rnd < m_ProbLevelCrossing) { Next = cMineShaftCrossing::CreateAndFit(*this, a_PivotX, a_PivotY, a_PivotZ, a_Direction, a_Noise); } else { Next = cMineShaftStaircase::CreateAndFit(*this, a_PivotX, a_PivotY, a_PivotZ, a_Direction, a_Noise); } if (Next == nullptr) { return; } m_MineShafts.push_back(Next); Next->AppendBranches(a_RecursionLevel + 1, a_Noise); } bool cStructGenMineShafts::cMineShaftSystem::CanAppend(const cCuboid & a_BoundingBox) { if (!a_BoundingBox.IsCompletelyInside(m_BoundingBox)) { // Too far away, or too low / too high return false; } // Check intersections: for (cMineShafts::const_iterator itr = m_MineShafts.begin(), end = m_MineShafts.end(); itr != end; ++itr) { if ((*itr)->DoesIntersect(a_BoundingBox)) { return false; } } // for itr - m_MineShafts[] return true; } //////////////////////////////////////////////////////////////////////////////// // cMineShaftDirtRoom: cMineShaftDirtRoom::cMineShaftDirtRoom(cStructGenMineShafts::cMineShaftSystem & a_Parent, cNoise & a_Noise) : Super(a_Parent, mskDirtRoom) { // Make the room of random size, min 10 x 4 x 10; max 18 x 12 x 18: int rnd = a_Noise.IntNoise3DInt(a_Parent.m_OriginX, 0, a_Parent.m_OriginZ) / 7; int OfsX = (rnd % a_Parent.m_GridSize) - a_Parent.m_GridSize / 2; rnd >>= 12; int OfsZ = (rnd % a_Parent.m_GridSize) - a_Parent.m_GridSize / 2; rnd = a_Noise.IntNoise3DInt(a_Parent.m_OriginX, 1000, a_Parent.m_OriginZ) / 11; m_BoundingBox.p1.x = a_Parent.m_OriginX + OfsX; m_BoundingBox.p2.x = m_BoundingBox.p1.x + 10 + (rnd % 8); rnd >>= 4; m_BoundingBox.p1.z = a_Parent.m_OriginZ + OfsZ; m_BoundingBox.p2.z = m_BoundingBox.p1.z + 10 + (rnd % 8); rnd >>= 4; m_BoundingBox.p1.y = 20; m_BoundingBox.p2.y = 24 + rnd % 8; } void cMineShaftDirtRoom::AppendBranches(int a_RecursionLevel, cNoise & a_Noise) { int Height = m_BoundingBox.DifY() - 3; for (int x = m_BoundingBox.p1.x + 1; x < m_BoundingBox.p2.x; x += 4) { int rnd = a_Noise.IntNoise3DInt(x, a_RecursionLevel, m_BoundingBox.p1.z) / 7; m_ParentSystem.AppendBranch(x, m_BoundingBox.p1.y + (rnd % Height), m_BoundingBox.p1.z - 1, dirZM, a_Noise, a_RecursionLevel); rnd >>= 4; m_ParentSystem.AppendBranch(x, m_BoundingBox.p1.y + (rnd % Height), m_BoundingBox.p2.z + 1, dirZP, a_Noise, a_RecursionLevel); } for (int z = m_BoundingBox.p1.z + 1; z < m_BoundingBox.p2.z; z += 4) { int rnd = a_Noise.IntNoise3DInt(m_BoundingBox.p1.x, a_RecursionLevel, z) / 13; m_ParentSystem.AppendBranch(m_BoundingBox.p1.x - 1, m_BoundingBox.p1.y + (rnd % Height), z, dirXM, a_Noise, a_RecursionLevel); rnd >>= 4; m_ParentSystem.AppendBranch(m_BoundingBox.p2.x + 1, m_BoundingBox.p1.y + (rnd % Height), z, dirXP, a_Noise, a_RecursionLevel); } } void cMineShaftDirtRoom::ProcessChunk(cChunkDesc & a_ChunkDesc) { int BlockX = a_ChunkDesc.GetChunkX() * cChunkDef::Width; int BlockZ = a_ChunkDesc.GetChunkZ() * cChunkDef::Width; if ( (m_BoundingBox.p1.x > BlockX + cChunkDef::Width) || (m_BoundingBox.p1.z > BlockZ + cChunkDef::Width) || (m_BoundingBox.p2.x < BlockX) || (m_BoundingBox.p2.z < BlockZ) ) { // Early bailout - cannot intersect this chunk return; } // Chunk-relative coords of the boundaries: int MinX = std::max(BlockX, m_BoundingBox.p1.x) - BlockX; int MaxX = std::min(BlockX + cChunkDef::Width, m_BoundingBox.p2.x + 1) - BlockX; int MinZ = std::max(BlockZ, m_BoundingBox.p1.z) - BlockZ; int MaxZ = std::min(BlockZ + cChunkDef::Width, m_BoundingBox.p2.z + 1) - BlockZ; // Carve the room out: for (int z = MinZ; z < MaxZ; z++) { for (int x = MinX; x < MaxX; x++) { for (int y = m_BoundingBox.p1.y + 1; y < m_BoundingBox.p2.y; y++) { a_ChunkDesc.SetBlockType(x, y, z, E_BLOCK_AIR); } if (a_ChunkDesc.GetBlockType(x, m_BoundingBox.p1.y, z) != E_BLOCK_AIR) { a_ChunkDesc.SetBlockType(x, m_BoundingBox.p1.y, z, E_BLOCK_DIRT); } } // for x } // for z } //////////////////////////////////////////////////////////////////////////////// // cMineShaftCorridor: cMineShaftCorridor::cMineShaftCorridor( cStructGenMineShafts::cMineShaftSystem & a_ParentSystem, const cCuboid & a_BoundingBox, int a_NumSegments, eDirection a_Direction, cNoise & a_Noise ) : Super(a_ParentSystem, mskCorridor, a_BoundingBox), m_NumSegments(a_NumSegments), m_Direction(a_Direction), m_ChestPosition(-1), m_SpawnerPosition(-1) { int rnd = a_Noise.IntNoise3DInt(a_BoundingBox.p1.x, a_BoundingBox.p1.y, a_BoundingBox.p1.z) / 7; for (int i = 0; i < a_NumSegments; i++) { m_HasFullBeam[i] = (rnd % 4) < 3; // 75 % chance of full beam rnd >>= 2; } m_HasTracks = ((rnd % 4) < 2); // 50 % chance of tracks rnd = a_Noise.IntNoise3DInt(a_BoundingBox.p1.z, a_BoundingBox.p1.x, a_BoundingBox.p1.y) / 7; int ChestCheck = rnd % 250; rnd >>= 8; int SpawnerCheck = rnd % 250; rnd >>= 8; if (ChestCheck < a_ParentSystem.m_ChanceChest) { m_ChestPosition = rnd % (a_NumSegments * 5); } if ((a_NumSegments < 4) && (SpawnerCheck < a_ParentSystem.m_ChanceSpawner)) { m_SpawnerPosition = rnd % (a_NumSegments * 5); } } cMineShaft * cMineShaftCorridor::CreateAndFit( cStructGenMineShafts::cMineShaftSystem & a_ParentSystem, int a_PivotX, int a_PivotY, int a_PivotZ, eDirection a_Direction, cNoise & a_Noise ) { cCuboid BoundingBox(a_PivotX, a_PivotY - 1, a_PivotZ); BoundingBox.p2.y += 3; int rnd = a_Noise.IntNoise3DInt(a_PivotX, a_PivotY + static_cast(a_ParentSystem.m_MineShafts.size()), a_PivotZ) / 7; int NumSegments = 2 + (rnd) % (MAX_SEGMENTS - 1); // 2 .. MAX_SEGMENTS switch (a_Direction) { case dirXP: BoundingBox.p2.x += NumSegments * 5 - 1; BoundingBox.p1.z -= 1; BoundingBox.p2.z += 1; break; case dirXM: BoundingBox.p1.x -= NumSegments * 5 - 1; BoundingBox.p1.z -= 1; BoundingBox.p2.z += 1; break; case dirZP: BoundingBox.p2.z += NumSegments * 5 - 1; BoundingBox.p1.x -= 1; BoundingBox.p2.x += 1; break; case dirZM: BoundingBox.p1.z -= NumSegments * 5 - 1; BoundingBox.p1.x -= 1; BoundingBox.p2.x += 1; break; } if (!a_ParentSystem.CanAppend(BoundingBox)) { return nullptr; } return new cMineShaftCorridor(a_ParentSystem, BoundingBox, NumSegments, a_Direction, a_Noise); } void cMineShaftCorridor::AppendBranches(int a_RecursionLevel, cNoise & a_Noise) { int Outerrnd = a_Noise.IntNoise3DInt(m_BoundingBox.p1.x, m_BoundingBox.p1.y + a_RecursionLevel, m_BoundingBox.p1.z) / 7; // Prefer the same height, but allow for up to one block height displacement: int OuterHeight = m_BoundingBox.p1.y + ((Outerrnd % 4) + ((Outerrnd >> 3) % 3)) / 2; switch (m_Direction) { case dirXM: { m_ParentSystem.AppendBranch(m_BoundingBox.p1.x - 1, OuterHeight, m_BoundingBox.p1.z + 1, dirXM, a_Noise, a_RecursionLevel); for (int i = m_NumSegments; i >= 0; i--) { int rnd = a_Noise.IntNoise3DInt(m_BoundingBox.p1.x + i + 10, m_BoundingBox.p1.y + a_RecursionLevel, m_BoundingBox.p1.z) / 11; int Height = m_BoundingBox.p1.y + ((rnd % 4) + ((rnd >> 3) % 3)) / 2; rnd >>= 6; int Ofs = 1 + rnd % (m_NumSegments * 5 - 2); m_ParentSystem.AppendBranch(m_BoundingBox.p1.x + Ofs, Height, m_BoundingBox.p1.z - 1, dirZM, a_Noise, a_RecursionLevel); m_ParentSystem.AppendBranch(m_BoundingBox.p1.x + Ofs, Height, m_BoundingBox.p2.z + 1, dirZP, a_Noise, a_RecursionLevel); } break; } case dirXP: { m_ParentSystem.AppendBranch(m_BoundingBox.p2.x + 1, OuterHeight, m_BoundingBox.p1.z + 1, dirXP, a_Noise, a_RecursionLevel); for (int i = m_NumSegments; i >= 0; i--) { int rnd = a_Noise.IntNoise3DInt(m_BoundingBox.p1.x + i + 10, m_BoundingBox.p1.y + a_RecursionLevel, m_BoundingBox.p1.z) / 11; int Height = m_BoundingBox.p1.y + ((rnd % 4) + ((rnd >> 3) % 3)) / 2; rnd >>= 6; int Ofs = 1 + rnd % (m_NumSegments * 5 - 2); m_ParentSystem.AppendBranch(m_BoundingBox.p1.x + Ofs, Height, m_BoundingBox.p1.z - 1, dirZM, a_Noise, a_RecursionLevel); m_ParentSystem.AppendBranch(m_BoundingBox.p1.x + Ofs, Height, m_BoundingBox.p2.z + 1, dirZP, a_Noise, a_RecursionLevel); } break; } case dirZM: { m_ParentSystem.AppendBranch(m_BoundingBox.p1.x + 1, OuterHeight, m_BoundingBox.p1.z - 1, dirZM, a_Noise, a_RecursionLevel); for (int i = m_NumSegments; i >= 0; i--) { int rnd = a_Noise.IntNoise3DInt(m_BoundingBox.p1.x + i + 10, m_BoundingBox.p1.y + a_RecursionLevel, m_BoundingBox.p1.z) / 11; int Height = m_BoundingBox.p1.y + ((rnd % 4) + ((rnd >> 3) % 3)) / 2; rnd >>= 6; int Ofs = 1 + rnd % (m_NumSegments * 5 - 2); m_ParentSystem.AppendBranch(m_BoundingBox.p1.x - 1, Height, m_BoundingBox.p1.z + Ofs, dirXM, a_Noise, a_RecursionLevel); m_ParentSystem.AppendBranch(m_BoundingBox.p2.x + 1, Height, m_BoundingBox.p1.z + Ofs, dirXP, a_Noise, a_RecursionLevel); } break; } case dirZP: { m_ParentSystem.AppendBranch(m_BoundingBox.p1.x + 1, OuterHeight, m_BoundingBox.p2.z + 1, dirZP, a_Noise, a_RecursionLevel); for (int i = m_NumSegments; i >= 0; i--) { int rnd = a_Noise.IntNoise3DInt(m_BoundingBox.p1.x + i + 10, m_BoundingBox.p1.y + a_RecursionLevel, m_BoundingBox.p1.z) / 11; int Height = m_BoundingBox.p1.y + ((rnd % 4) + ((rnd >> 3) % 3)) / 2; rnd >>= 6; int Ofs = 1 + rnd % (m_NumSegments * 5 - 2); m_ParentSystem.AppendBranch(m_BoundingBox.p1.x - 1, Height, m_BoundingBox.p1.z + Ofs, dirXM, a_Noise, a_RecursionLevel); m_ParentSystem.AppendBranch(m_BoundingBox.p2.x + 1, Height, m_BoundingBox.p1.z + Ofs, dirXP, a_Noise, a_RecursionLevel); } break; } } // switch (m_Direction) } void cMineShaftCorridor::ProcessChunk(cChunkDesc & a_ChunkDesc) { int BlockX = a_ChunkDesc.GetChunkX() * cChunkDef::Width; int BlockZ = a_ChunkDesc.GetChunkZ() * cChunkDef::Width; cCuboid RelBoundingBox(m_BoundingBox); RelBoundingBox.Move({-BlockX, 0, -BlockZ}); RelBoundingBox.p1.y += 1; RelBoundingBox.p2.y -= 1; cCuboid Top(RelBoundingBox); Top.p2.y += 1; Top.p1.y = Top.p2.y; a_ChunkDesc.FillRelCuboid(RelBoundingBox, E_BLOCK_AIR, 0); a_ChunkDesc.RandomFillRelCuboid(Top, E_BLOCK_AIR, 0, (BlockX ^ (BlockZ + BlockX)), 8000); if (m_SpawnerPosition >= 0) { // Cobwebs around the spider spawner a_ChunkDesc.RandomFillRelCuboid(RelBoundingBox, E_BLOCK_COBWEB, 0, (BlockX ^ (BlockZ + BlockZ)), 8000); a_ChunkDesc.RandomFillRelCuboid(Top, E_BLOCK_COBWEB, 0, (BlockX ^ (BlockZ + BlockX)), 5000); } a_ChunkDesc.RandomFillRelCuboid(Top, E_BLOCK_COBWEB, 0, (BlockX ^ (BlockZ + BlockX + 10)), 500); RelBoundingBox.p1.y = m_BoundingBox.p1.y; RelBoundingBox.p2.y = m_BoundingBox.p1.y; a_ChunkDesc.FloorRelCuboid(RelBoundingBox, E_BLOCK_PLANKS, 0); switch (m_Direction) { case dirXM: case dirXP: { int y1 = m_BoundingBox.p1.y + 1; int y2 = m_BoundingBox.p1.y + 2; int y3 = m_BoundingBox.p1.y + 3; int z1 = m_BoundingBox.p1.z - BlockZ; int z2 = m_BoundingBox.p2.z - BlockZ; for (int i = 0; i < m_NumSegments; i++) { int x = m_BoundingBox.p1.x + i * 5 + 2 - BlockX; if ((x < 0) || (x >= cChunkDef::Width)) { continue; } if ((z1 >= 0) && (z1 < cChunkDef::Width)) { a_ChunkDesc.SetBlockTypeMeta(x, y1, z1, E_BLOCK_FENCE, 0); a_ChunkDesc.SetBlockTypeMeta(x, y2, z1, E_BLOCK_FENCE, 0); a_ChunkDesc.SetBlockTypeMeta(x, y3, z1, E_BLOCK_PLANKS, 0); } if ((z2 >= 0) && (z2 < cChunkDef::Width)) { a_ChunkDesc.SetBlockTypeMeta(x, y1, z2, E_BLOCK_FENCE, 0); a_ChunkDesc.SetBlockTypeMeta(x, y2, z2, E_BLOCK_FENCE, 0); a_ChunkDesc.SetBlockTypeMeta(x, y3, z2, E_BLOCK_PLANKS, 0); } if ((z1 >= -1) && (z1 < cChunkDef::Width - 1) && m_HasFullBeam[i]) { a_ChunkDesc.SetBlockTypeMeta(x, y3, z1 + 1, E_BLOCK_PLANKS, 0); } } // for i - NumSegments break; } case dirZM: case dirZP: { int y1 = m_BoundingBox.p1.y + 1; int y2 = m_BoundingBox.p1.y + 2; int y3 = m_BoundingBox.p1.y + 3; int x1 = m_BoundingBox.p1.x - BlockX; int x2 = m_BoundingBox.p2.x - BlockX; for (int i = 0; i < m_NumSegments; i++) { int z = m_BoundingBox.p1.z + i * 5 + 2 - BlockZ; if ((z < 0) || (z >= cChunkDef::Width)) { continue; } if ((x1 >= 0) && (x1 < cChunkDef::Width)) { a_ChunkDesc.SetBlockTypeMeta(x1, y1, z, E_BLOCK_FENCE, 0); a_ChunkDesc.SetBlockTypeMeta(x1, y2, z, E_BLOCK_FENCE, 0); a_ChunkDesc.SetBlockTypeMeta(x1, y3, z, E_BLOCK_PLANKS, 0); } if ((x2 >= 0) && (x2 < cChunkDef::Width)) { a_ChunkDesc.SetBlockTypeMeta(x2, y1, z, E_BLOCK_FENCE, 0); a_ChunkDesc.SetBlockTypeMeta(x2, y2, z, E_BLOCK_FENCE, 0); a_ChunkDesc.SetBlockTypeMeta(x2, y3, z, E_BLOCK_PLANKS, 0); } if ((x1 >= -1) && (x1 < cChunkDef::Width - 1) && m_HasFullBeam[i]) { a_ChunkDesc.SetBlockTypeMeta(x1 + 1, y3, z, E_BLOCK_PLANKS, 0); } } // for i - NumSegments break; } // case dirZ? } // for i PlaceChest(a_ChunkDesc); PlaceTracks(a_ChunkDesc); PlaceSpawner(a_ChunkDesc); // (must be after Tracks!) PlaceTorches(a_ChunkDesc); } void cMineShaftCorridor::PlaceChest(cChunkDesc & a_ChunkDesc) { static const cLootProbab LootProbab[] = { // Item, MinAmount, MaxAmount, Weight { cItem(E_ITEM_IRON), 1, 5, 10 }, { cItem(E_ITEM_GOLD), 1, 3, 5 }, { cItem(E_ITEM_REDSTONE_DUST), 4, 9, 5 }, { cItem(E_ITEM_DIAMOND), 1, 2, 3 }, { cItem(E_ITEM_DYE, 1, 4), 4, 9, 5 }, // lapis lazuli dye { cItem(E_ITEM_COAL), 3, 8, 10 }, { cItem(E_ITEM_BREAD), 1, 3, 15 }, { cItem(E_ITEM_IRON_PICKAXE), 1, 1, 1 }, { cItem(E_BLOCK_MINECART_TRACKS), 4, 8, 1 }, { cItem(E_ITEM_MELON_SEEDS), 2, 4, 10 }, { cItem(E_ITEM_PUMPKIN_SEEDS), 2, 4, 10 }, } ; if (m_ChestPosition < 0) { return; } int BlockX = a_ChunkDesc.GetChunkX() * cChunkDef::Width; int BlockZ = a_ChunkDesc.GetChunkZ() * cChunkDef::Width; int x, z; NIBBLETYPE Meta = 0; [&] { switch (m_Direction) { case dirXM: case dirXP: { x = m_BoundingBox.p1.x + m_ChestPosition - BlockX; z = m_BoundingBox.p1.z - BlockZ; Meta = E_META_CHEST_FACING_ZP; return; } case dirZM: case dirZP: { x = m_BoundingBox.p1.x - BlockX; z = m_BoundingBox.p1.z + m_ChestPosition - BlockZ; Meta = E_META_CHEST_FACING_XP; return; } } // switch (Dir) UNREACHABLE("Unsupported corridor direction"); }(); if ( (x >= 0) && (x < cChunkDef::Width) && (z >= 0) && (z < cChunkDef::Width) ) { a_ChunkDesc.SetBlockTypeMeta(x, m_BoundingBox.p1.y + 1, z, E_BLOCK_CHEST, Meta); cChestEntity * ChestEntity = static_cast(a_ChunkDesc.GetBlockEntity(x, m_BoundingBox.p1.y + 1, z)); ASSERT((ChestEntity != nullptr) && (ChestEntity->GetBlockType() == E_BLOCK_CHEST)); cNoise Noise(a_ChunkDesc.GetChunkX() ^ a_ChunkDesc.GetChunkZ()); int NumSlots = 3 + ((Noise.IntNoise3DInt(x, m_BoundingBox.p1.y, z) / 11) % 4); int Seed = Noise.IntNoise2DInt(x, z); ChestEntity->GetContents().GenerateRandomLootWithBooks(LootProbab, ARRAYCOUNT(LootProbab), NumSlots, Seed); } } void cMineShaftCorridor::PlaceTracks(cChunkDesc & a_ChunkDesc) { if (!m_HasTracks) { return; } cCuboid Box(m_BoundingBox); Box.Move({-a_ChunkDesc.GetChunkX() * cChunkDef::Width, 1, -a_ChunkDesc.GetChunkZ() * cChunkDef::Width}); Box.p2.y = Box.p1.y; Box.p1.x += 1; Box.p2.x -= 1; Box.p1.z += 1; Box.p2.z -= 1; NIBBLETYPE Meta = 0; switch (m_Direction) { case dirXM: case dirXP: { Meta = E_META_TRACKS_X; break; } case dirZM: case dirZP: { Meta = E_META_TRACKS_Z; break; } } // switch (direction) a_ChunkDesc.RandomFillRelCuboid(Box, E_BLOCK_MINECART_TRACKS, Meta, a_ChunkDesc.GetChunkX() + a_ChunkDesc.GetChunkZ(), 6000); } void cMineShaftCorridor::PlaceSpawner(cChunkDesc & a_ChunkDesc) { if (m_SpawnerPosition < 0) { // No spawner in this corridor return; } int SpawnerRelX = m_BoundingBox.p1.x + 1 - a_ChunkDesc.GetChunkX() * cChunkDef::Width; int SpawnerRelZ = m_BoundingBox.p1.z + 1 - a_ChunkDesc.GetChunkZ() * cChunkDef::Width; switch (m_Direction) { case dirXM: case dirXP: { SpawnerRelX += m_SpawnerPosition - 1; break; } case dirZM: case dirZP: { SpawnerRelZ += m_SpawnerPosition - 1; break; } } if ( (SpawnerRelX >= 0) && (SpawnerRelX < cChunkDef::Width) && (SpawnerRelZ >= 0) && (SpawnerRelZ < cChunkDef::Width) ) { a_ChunkDesc.SetBlockTypeMeta(SpawnerRelX, m_BoundingBox.p1.y + 1, SpawnerRelZ, E_BLOCK_MOB_SPAWNER, 0); cMobSpawnerEntity * MobSpawner = static_cast(a_ChunkDesc.GetBlockEntity(SpawnerRelX, m_BoundingBox.p1.y + 1, SpawnerRelZ)); ASSERT((MobSpawner != nullptr) && (MobSpawner->GetBlockType() == E_BLOCK_MOB_SPAWNER)); MobSpawner->SetEntity(mtCaveSpider); } } void cMineShaftCorridor::PlaceTorches(cChunkDesc & a_ChunkDesc) { cNoise Noise(m_BoundingBox.p1.x); switch (m_Direction) { case dirXM: case dirXP: { int z = m_BoundingBox.p1.z + 1 - a_ChunkDesc.GetChunkZ() * cChunkDef::Width; if ((z < 0) || (z >= cChunkDef::Width)) { return; } int BlockX = a_ChunkDesc.GetChunkX() * cChunkDef::Width; for (int i = 0; i < m_NumSegments; i++) { if (!m_HasFullBeam[i]) { continue; } int x = m_BoundingBox.p1.x + i * 5 + 1 - BlockX; if ((x >= 0) && (x < cChunkDef::Width)) { if (((Noise.IntNoise2DInt(x, z) / 7) % 10000) < m_ParentSystem.m_ChanceTorch) { a_ChunkDesc.SetBlockTypeMeta(x, m_BoundingBox.p2.y, z, E_BLOCK_TORCH, E_META_TORCH_XP); } } x += 2; if ((x >= 0) && (x < cChunkDef::Width)) { if (((Noise.IntNoise2DInt(x, z) / 7) % 10000) < m_ParentSystem.m_ChanceTorch) { a_ChunkDesc.SetBlockTypeMeta(x, m_BoundingBox.p2.y, z, E_BLOCK_TORCH, E_META_TORCH_XM); } } } // for i break; } case dirZM: case dirZP: { int x = m_BoundingBox.p1.x + 1 - a_ChunkDesc.GetChunkX() * cChunkDef::Width; if ((x < 0) || (x >= cChunkDef::Width)) { return; } int BlockZ = a_ChunkDesc.GetChunkZ() * cChunkDef::Width; for (int i = 0; i < m_NumSegments; i++) { if (!m_HasFullBeam[i]) { continue; } int z = m_BoundingBox.p1.z + i * 5 + 1 - BlockZ; if ((z >= 0) && (z < cChunkDef::Width)) { if (((Noise.IntNoise2DInt(x, z) / 7) % 10000) < m_ParentSystem.m_ChanceTorch) { a_ChunkDesc.SetBlockTypeMeta(x, m_BoundingBox.p2.y, z, E_BLOCK_TORCH, E_META_TORCH_ZP); } } z += 2; if ((z >= 0) && (z < cChunkDef::Width)) { if (((Noise.IntNoise2DInt(x, z) / 7) % 10000) < m_ParentSystem.m_ChanceTorch) { a_ChunkDesc.SetBlockTypeMeta(x, m_BoundingBox.p2.y, z, E_BLOCK_TORCH, E_META_TORCH_ZM); } } } // for i break; } } // switch (direction) } //////////////////////////////////////////////////////////////////////////////// // cMineShaftCrossing: cMineShaftCrossing::cMineShaftCrossing(cStructGenMineShafts::cMineShaftSystem & a_ParentSystem, const cCuboid & a_BoundingBox) : Super(a_ParentSystem, mskCrossing, a_BoundingBox) { } cMineShaft * cMineShaftCrossing::CreateAndFit( cStructGenMineShafts::cMineShaftSystem & a_ParentSystem, int a_PivotX, int a_PivotY, int a_PivotZ, eDirection a_Direction, cNoise & a_Noise ) { cCuboid BoundingBox(a_PivotX, a_PivotY - 1, a_PivotZ); int rnd = a_Noise.IntNoise3DInt(a_PivotX, a_PivotY + static_cast(a_ParentSystem.m_MineShafts.size()), a_PivotZ) / 7; BoundingBox.p2.y += 3; if ((rnd % 4) < 2) { // 2-level crossing: BoundingBox.p2.y += 4; rnd >>= 2; if ((rnd % 4) < 2) { // This is the higher level: BoundingBox.p1.y -= 4; BoundingBox.p2.y -= 4; } } switch (a_Direction) { case dirXP: BoundingBox.p2.x += 4; BoundingBox.p1.z -= 2; BoundingBox.p2.z += 2; break; case dirXM: BoundingBox.p1.x -= 4; BoundingBox.p1.z -= 2; BoundingBox.p2.z += 2; break; case dirZP: BoundingBox.p2.z += 4; BoundingBox.p1.x -= 2; BoundingBox.p2.x += 2; break; case dirZM: BoundingBox.p1.z -= 4; BoundingBox.p1.x -= 2; BoundingBox.p2.x += 2; break; } if (!a_ParentSystem.CanAppend(BoundingBox)) { return nullptr; } return new cMineShaftCrossing(a_ParentSystem, BoundingBox); } void cMineShaftCrossing::AppendBranches(int a_RecursionLevel, cNoise & a_Noise) { struct { int x, y, z; eDirection dir; } Exits[] = { // Bottom level: {-1, 1, 2, dirXM}, { 2, 1, -1, dirZM}, { 5, 1, 2, dirXP}, { 2, 1, 5, dirZP}, // Top level: {-1, 5, 2, dirXM}, { 2, 5, -1, dirZM}, { 5, 5, 2, dirXP}, { 2, 5, 5, dirZP}, } ; for (size_t i = 0; i < ARRAYCOUNT(Exits); i++) { if (m_BoundingBox.p1.y + Exits[i].y >= m_BoundingBox.p2.y) { // This exit is not available (two-level exit on a one-level crossing) continue; } int Height = m_BoundingBox.p1.y + Exits[i].y; m_ParentSystem.AppendBranch(m_BoundingBox.p1.x + Exits[i].x, Height, m_BoundingBox.p1.z + Exits[i].z, Exits[i].dir, a_Noise, a_RecursionLevel); } // for i } void cMineShaftCrossing::ProcessChunk(cChunkDesc & a_ChunkDesc) { int BlockX = a_ChunkDesc.GetChunkX() * cChunkDef::Width; int BlockZ = a_ChunkDesc.GetChunkZ() * cChunkDef::Width; cCuboid box(m_BoundingBox); box.Move({-BlockX, 0, -BlockZ}); if ((box.p2.x < 0) || (box.p2.z < 0) || (box.p1.x >= cChunkDef::Width) || (box.p1.z > cChunkDef::Width)) { // Does not intersect this chunk return; } int Floor = box.p1.y + 1; int Ceil = box.p2.y; // The supports: a_ChunkDesc.FillRelCuboid(box.p1.x + 1, box.p1.x + 1, Floor, Ceil, box.p1.z + 1, box.p1.z + 1, E_BLOCK_PLANKS, 0); a_ChunkDesc.FillRelCuboid(box.p2.x - 1, box.p2.x - 1, Floor, Ceil, box.p1.z + 1, box.p1.z + 1, E_BLOCK_PLANKS, 0); a_ChunkDesc.FillRelCuboid(box.p1.x + 1, box.p1.x + 1, Floor, Ceil, box.p2.z - 1, box.p2.z - 1, E_BLOCK_PLANKS, 0); a_ChunkDesc.FillRelCuboid(box.p2.x - 1, box.p2.x - 1, Floor, Ceil, box.p2.z - 1, box.p2.z - 1, E_BLOCK_PLANKS, 0); // The air in between: a_ChunkDesc.FillRelCuboid(box.p1.x + 2, box.p1.x + 2, Floor, Ceil, box.p1.z + 1, box.p2.z - 1, E_BLOCK_AIR, 0); a_ChunkDesc.FillRelCuboid(box.p1.x + 1, box.p2.x - 1, Floor, Ceil, box.p1.z + 2, box.p1.z + 2, E_BLOCK_AIR, 0); // The air on the edges: int Mid = Floor + 2; a_ChunkDesc.FillRelCuboid(box.p1.x, box.p1.x, Floor, Mid, box.p1.z + 1, box.p2.z - 1, E_BLOCK_AIR, 0); a_ChunkDesc.FillRelCuboid(box.p2.x, box.p2.x, Floor, Mid, box.p1.z + 1, box.p2.z - 1, E_BLOCK_AIR, 0); a_ChunkDesc.FillRelCuboid(box.p1.x + 1, box.p2.x - 1, Floor, Mid, box.p1.z, box.p1.z, E_BLOCK_AIR, 0); a_ChunkDesc.FillRelCuboid(box.p1.x + 1, box.p2.x - 1, Floor, Mid, box.p2.z, box.p2.z, E_BLOCK_AIR, 0); Mid += 2; if (Mid < Ceil) { a_ChunkDesc.FillRelCuboid(box.p1.x, box.p1.x, Mid, Ceil, box.p1.z + 1, box.p2.z - 1, E_BLOCK_AIR, 0); a_ChunkDesc.FillRelCuboid(box.p2.x, box.p2.x, Mid, Ceil, box.p1.z + 1, box.p2.z - 1, E_BLOCK_AIR, 0); a_ChunkDesc.FillRelCuboid(box.p1.x + 1, box.p2.x - 1, Mid, Ceil, box.p1.z, box.p1.z, E_BLOCK_AIR, 0); a_ChunkDesc.FillRelCuboid(box.p1.x + 1, box.p2.x - 1, Mid, Ceil, box.p2.z, box.p2.z, E_BLOCK_AIR, 0); } // The floor, if needed: box.p2.y = box.p1.y; a_ChunkDesc.FloorRelCuboid(box, E_BLOCK_PLANKS, 0); } //////////////////////////////////////////////////////////////////////////////// // cMineShaftStaircase: cMineShaftStaircase::cMineShaftStaircase( cStructGenMineShafts::cMineShaftSystem & a_ParentSystem, const cCuboid & a_BoundingBox, eDirection a_Direction, eSlope a_Slope ) : Super(a_ParentSystem, mskStaircase, a_BoundingBox), m_Direction(a_Direction), m_Slope(a_Slope) { } cMineShaft * cMineShaftStaircase::CreateAndFit( cStructGenMineShafts::cMineShaftSystem & a_ParentSystem, int a_PivotX, int a_PivotY, int a_PivotZ, eDirection a_Direction, cNoise & a_Noise ) { int rnd = a_Noise.IntNoise3DInt(a_PivotX, a_PivotY + static_cast(a_ParentSystem.m_MineShafts.size()), a_PivotZ) / 7; cCuboid Box; switch (a_Direction) { case dirXM: { Box.Assign({a_PivotX - 7, a_PivotY - 1, a_PivotZ - 1}, {a_PivotX, a_PivotY + 6, a_PivotZ + 1}); break; } case dirXP: { Box.Assign({a_PivotX, a_PivotY - 1, a_PivotZ - 1}, {a_PivotX + 7, a_PivotY + 6, a_PivotZ + 1}); break; } case dirZM: { Box.Assign({a_PivotX - 1, a_PivotY - 1, a_PivotZ - 7}, {a_PivotX + 1, a_PivotY + 6, a_PivotZ}); break; } case dirZP: { Box.Assign({a_PivotX - 1, a_PivotY - 1, a_PivotZ}, {a_PivotX + 1, a_PivotY + 6, a_PivotZ + 7}); break; } } eSlope Slope = sUp; if ((rnd % 4) < 2) // 50 % { Slope = sDown; Box.Move({0, -4, 0}); } if (!a_ParentSystem.CanAppend(Box)) { return nullptr; } return new cMineShaftStaircase(a_ParentSystem, Box, a_Direction, Slope); } void cMineShaftStaircase::AppendBranches(int a_RecursionLevel, cNoise & a_Noise) { int Height = m_BoundingBox.p1.y + ((m_Slope == sDown) ? 1 : 5); switch (m_Direction) { case dirXM: m_ParentSystem.AppendBranch(m_BoundingBox.p1.x - 1, Height, m_BoundingBox.p1.z + 1, dirXM, a_Noise, a_RecursionLevel); break; case dirXP: m_ParentSystem.AppendBranch(m_BoundingBox.p2.x + 1, Height, m_BoundingBox.p1.z + 1, dirXP, a_Noise, a_RecursionLevel); break; case dirZM: m_ParentSystem.AppendBranch(m_BoundingBox.p1.x + 1, Height, m_BoundingBox.p1.z - 1, dirZM, a_Noise, a_RecursionLevel); break; case dirZP: m_ParentSystem.AppendBranch(m_BoundingBox.p1.x + 1, Height, m_BoundingBox.p2.z + 1, dirZP, a_Noise, a_RecursionLevel); break; } } void cMineShaftStaircase::ProcessChunk(cChunkDesc & a_ChunkDesc) { int BlockX = a_ChunkDesc.GetChunkX() * cChunkDef::Width; int BlockZ = a_ChunkDesc.GetChunkZ() * cChunkDef::Width; cCuboid RelB(m_BoundingBox); RelB.Move({-BlockX, 0, -BlockZ}); if ( (RelB.p1.x >= cChunkDef::Width) || (RelB.p1.z >= cChunkDef::Width) || (RelB.p2.x < 0) || (RelB.p2.z < 0) ) { // No intersection between this staircase and this chunk return; } int SFloor = RelB.p1.y + ((m_Slope == sDown) ? 5 : 1); int DFloor = RelB.p1.y + ((m_Slope == sDown) ? 1 : 5); int Add = (m_Slope == sDown) ? -1 : 1; int InitAdd = (m_Slope == sDown) ? -1 : 0; cCuboid Box; switch (m_Direction) { case dirXM: { a_ChunkDesc.FillRelCuboid (RelB.p2.x - 1, RelB.p2.x, SFloor, SFloor + 2, RelB.p1.z, RelB.p2.z, E_BLOCK_AIR, 0); a_ChunkDesc.FillRelCuboid (RelB.p1.x, RelB.p1.x + 1, DFloor, DFloor + 2, RelB.p1.z, RelB.p2.z, E_BLOCK_AIR, 0); a_ChunkDesc.FloorRelCuboid(RelB.p2.x - 1, RelB.p2.x, SFloor - 1, SFloor - 1, RelB.p1.z, RelB.p2.z, E_BLOCK_PLANKS, 0); a_ChunkDesc.FloorRelCuboid(RelB.p1.x, RelB.p1.x + 1, DFloor - 1, DFloor - 1, RelB.p1.z, RelB.p2.z, E_BLOCK_PLANKS, 0); Box.Assign({RelB.p2.x - 2, SFloor + InitAdd, RelB.p1.z}, {RelB.p2.x - 2, SFloor + 3 + InitAdd, RelB.p2.z}); for (int i = 0; i < 4; i++) { a_ChunkDesc.FillRelCuboid(Box, E_BLOCK_AIR, 0); a_ChunkDesc.FloorRelCuboid(Box.p1.x, Box.p2.x, Box.p1.y - 1, Box.p1.y - 1, Box.p1.z, Box.p2.z, E_BLOCK_PLANKS, 0); Box.Move({-1, Add, 0}); } break; } case dirXP: { a_ChunkDesc.FillRelCuboid (RelB.p1.x, RelB.p1.x + 1, SFloor, SFloor + 2, RelB.p1.z, RelB.p2.z, E_BLOCK_AIR, 0); a_ChunkDesc.FillRelCuboid (RelB.p2.x - 1, RelB.p2.x, DFloor, DFloor + 2, RelB.p1.z, RelB.p2.z, E_BLOCK_AIR, 0); a_ChunkDesc.FloorRelCuboid(RelB.p1.x, RelB.p1.x + 1, SFloor - 1, SFloor - 1, RelB.p1.z, RelB.p2.z, E_BLOCK_PLANKS, 0); a_ChunkDesc.FloorRelCuboid(RelB.p2.x - 1, RelB.p2.x, DFloor - 1, DFloor - 1, RelB.p1.z, RelB.p2.z, E_BLOCK_PLANKS, 0); Box.Assign({RelB.p1.x + 2, SFloor + InitAdd, RelB.p1.z}, {RelB.p1.x + 2, SFloor + 3 + InitAdd, RelB.p2.z}); for (int i = 0; i < 4; i++) { a_ChunkDesc.FillRelCuboid(Box, E_BLOCK_AIR, 0); a_ChunkDesc.FloorRelCuboid(Box.p1.x, Box.p2.x, Box.p1.y - 1, Box.p1.y - 1, Box.p1.z, Box.p2.z, E_BLOCK_PLANKS, 0); Box.Move({1, Add, 0}); } break; } case dirZM: { a_ChunkDesc.FillRelCuboid (RelB.p1.x, RelB.p2.x, SFloor, SFloor + 2, RelB.p2.z - 1, RelB.p2.z, E_BLOCK_AIR, 0); a_ChunkDesc.FillRelCuboid (RelB.p1.x, RelB.p2.x, DFloor, DFloor + 2, RelB.p1.z, RelB.p1.z + 1, E_BLOCK_AIR, 0); a_ChunkDesc.FloorRelCuboid(RelB.p1.x, RelB.p2.x, SFloor - 1, SFloor - 1, RelB.p2.z - 1, RelB.p2.z, E_BLOCK_PLANKS, 0); a_ChunkDesc.FloorRelCuboid(RelB.p1.x, RelB.p2.x, DFloor - 1, DFloor - 1, RelB.p1.z, RelB.p1.z + 1, E_BLOCK_PLANKS, 0); Box.Assign({RelB.p1.x, SFloor + InitAdd, RelB.p2.z - 2}, {RelB.p2.x, SFloor + 3 + InitAdd, RelB.p2.z - 2}); for (int i = 0; i < 4; i++) { a_ChunkDesc.FillRelCuboid(Box, E_BLOCK_AIR, 0); a_ChunkDesc.FloorRelCuboid(Box.p1.x, Box.p2.x, Box.p1.y - 1, Box.p1.y - 1, Box.p1.z, Box.p2.z, E_BLOCK_PLANKS, 0); Box.Move({0, Add, -1}); } break; } case dirZP: { a_ChunkDesc.FillRelCuboid (RelB.p1.x, RelB.p2.x, SFloor, SFloor + 2, RelB.p1.z, RelB.p1.z + 1, E_BLOCK_AIR, 0); a_ChunkDesc.FillRelCuboid (RelB.p1.x, RelB.p2.x, DFloor, DFloor + 2, RelB.p2.z - 1, RelB.p2.z, E_BLOCK_AIR, 0); a_ChunkDesc.FloorRelCuboid(RelB.p1.x, RelB.p2.x, SFloor - 1, SFloor - 1, RelB.p1.z, RelB.p1.z + 1, E_BLOCK_PLANKS, 0); a_ChunkDesc.FloorRelCuboid(RelB.p1.x, RelB.p2.x, DFloor - 1, DFloor - 1, RelB.p2.z - 1, RelB.p2.z, E_BLOCK_PLANKS, 0); Box.Assign({RelB.p1.x, SFloor + InitAdd, RelB.p1.z + 2}, {RelB.p2.x, SFloor + 3 + InitAdd, RelB.p1.z + 2}); for (int i = 0; i < 4; i++) { a_ChunkDesc.FillRelCuboid(Box, E_BLOCK_AIR, 0); a_ChunkDesc.FloorRelCuboid(Box.p1.x, Box.p2.x, Box.p1.y - 1, Box.p1.y - 1, Box.p1.z, Box.p2.z, E_BLOCK_PLANKS, 0); Box.Move({0, Add, 1}); } break; } } // switch (m_Direction) } //////////////////////////////////////////////////////////////////////////////// // cStructGenMineShafts: cStructGenMineShafts::cStructGenMineShafts( int a_Seed, int a_GridSize, int a_MaxOffset, int a_MaxSystemSize, int a_ChanceCorridor, int a_ChanceCrossing, int a_ChanceStaircase ) : Super(a_Seed, a_GridSize, a_GridSize, a_MaxOffset, a_MaxOffset, a_MaxSystemSize, a_MaxSystemSize, 100), m_GridSize(a_GridSize), m_MaxSystemSize(a_MaxSystemSize), m_ProbLevelCorridor(std::max(0, a_ChanceCorridor)), m_ProbLevelCrossing(std::max(0, a_ChanceCorridor + a_ChanceCrossing)), m_ProbLevelStaircase(std::max(0, a_ChanceCorridor + a_ChanceCrossing + a_ChanceStaircase)) { } cGridStructGen::cStructurePtr cStructGenMineShafts::CreateStructure(int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ) { return cStructurePtr(new cMineShaftSystem(a_GridX, a_GridZ, a_OriginX, a_OriginZ, m_GridSize, m_MaxSystemSize, m_Noise, m_ProbLevelCorridor, m_ProbLevelCrossing, m_ProbLevelStaircase)); } ================================================ FILE: src/Generating/MineShafts.h ================================================ // MineShafts.h // Declares the cStructGenMineShafts class representing the structure generator for abandoned mineshafts #pragma once #include "GridStructGen.h" class cStructGenMineShafts : public cGridStructGen { typedef cGridStructGen Super; public: cStructGenMineShafts( int a_Seed, int a_GridSize, int a_MaxOffset, int a_MaxSystemSize, int a_ChanceCorridor, int a_ChanceCrossing, int a_ChanceStaircase ); protected: friend class cMineShaft; friend class cMineShaftDirtRoom; friend class cMineShaftCorridor; friend class cMineShaftCrossing; friend class cMineShaftStaircase; class cMineShaftSystem; // fwd: MineShafts.cpp int m_GridSize; ///< Average spacing of the systems int m_MaxSystemSize; ///< Maximum block size of a mineshaft system int m_ProbLevelCorridor; ///< Probability level of a branch object being the corridor int m_ProbLevelCrossing; ///< Probability level of a branch object being the crossing, minus Corridor int m_ProbLevelStaircase; ///< Probability level of a branch object being the staircase, minus Crossing // cGridStructGen overrides: virtual cStructurePtr CreateStructure(int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ) override; } ; ================================================ FILE: src/Generating/Noise3DGenerator.cpp ================================================ // Nosie3DGenerator.cpp // Generates terrain using 3D noise, rather than composing. Is a test. #include "Globals.h" #include "Noise3DGenerator.h" #include "../IniFile.h" #include "../LinearInterpolation.h" #include "../LinearUpscale.h" /* // Perform an automatic test of upscaling upon program start (use breakpoints to debug): class Test { public: Test(void) { DoTest1(); DoTest2(); } void DoTest1(void) { float In[3 * 3 * 3]; for (size_t i = 0; i < ARRAYCOUNT(In); i++) { In[i] = (float)(i % 5); } Debug3DNoise(In, 3, 3, 3, "Upscale3D in"); float Out[17 * 33 * 35]; LinearUpscale3DArray(In, 3, 3, 3, Out, 8, 16, 17); Debug3DNoise(Out, 17, 33, 35, "Upscale3D test"); } void DoTest2(void) { float In[3 * 3]; for (size_t i = 0; i < ARRAYCOUNT(In); i++) { In[i] = (float)(i % 5); } Debug2DNoise(In, 3, 3, "Upscale2D in"); float Out[17 * 33]; LinearUpscale2DArray(In, 3, 3, Out, 8, 16); Debug2DNoise(Out, 17, 33, "Upscale2D test"); } } gTest; //*/ #if 0 // Perform speed test of the cInterpolNoise class static class cInterpolNoiseSpeedTest { public: cInterpolNoiseSpeedTest(void) { TestSpeed2D(); TestSpeed3D(); printf("InterpolNoise speed comparison finished.\n"); } /** Compare the speed of the 3D InterpolNoise vs 3D CubicNoise. */ void TestSpeed3D(void) { printf("Evaluating 3D noise performance...\n"); static const int SIZE_X = 128; static const int SIZE_Y = 128; static const int SIZE_Z = 128; static const NOISE_DATATYPE MUL = 80; std::unique_ptr arr(new NOISE_DATATYPE[SIZE_X * SIZE_Y * SIZE_Z]); cTimer timer; // Test the cInterpolNoise: cInterpolNoise interpNoise(1); long long start = timer.GetNowTime(); for (int i = 0; i < 30; i++) { interpNoise.Generate3D(arr.get(), SIZE_X, SIZE_Y, SIZE_Z, MUL * i, MUL * i + MUL, 0, MUL, 0, MUL); } long long end = timer.GetNowTime(); printf("InterpolNoise took %.02f sec\n", static_cast(end - start) / 1000); // Test the cCubicNoise: cCubicNoise cubicNoise(1); start = timer.GetNowTime(); for (int i = 0; i < 30; i++) { cubicNoise.Generate3D(arr.get(), SIZE_X, SIZE_Y, SIZE_Z, MUL * i, MUL * i + MUL, 0, MUL, 0, MUL); } end = timer.GetNowTime(); printf("CubicNoise took %.02f sec\n", static_cast(end - start) / 1000); printf("3D noise performance comparison finished.\n"); } /** Compare the speed of the 2D InterpolNoise vs 2D CubicNoise. */ void TestSpeed2D(void) { printf("Evaluating 2D noise performance...\n"); static const int SIZE_X = 128; static const int SIZE_Y = 128; static const NOISE_DATATYPE MUL = 80; std::unique_ptr arr(new NOISE_DATATYPE[SIZE_X * SIZE_Y]); cTimer timer; // Test the cInterpolNoise: cInterpolNoise interpNoise(1); long long start = timer.GetNowTime(); for (int i = 0; i < 500; i++) { interpNoise.Generate2D(arr.get(), SIZE_X, SIZE_Y, MUL * i, MUL * i + MUL, 0, MUL); } long long end = timer.GetNowTime(); printf("InterpolNoise took %.02f sec\n", static_cast(end - start) / 1000); // Test the cCubicNoise: cCubicNoise cubicNoise(1); start = timer.GetNowTime(); for (int i = 0; i < 500; i++) { cubicNoise.Generate2D(arr.get(), SIZE_X, SIZE_Y, MUL * i, MUL * i + MUL, 0, MUL); } end = timer.GetNowTime(); printf("CubicNoise took %.02f sec\n", static_cast(end - start) / 1000); printf("2D noise performance comparison finished.\n"); } } g_InterpolNoiseSpeedTest; #endif //////////////////////////////////////////////////////////////////////////////// // cNoise3DGenerator: cNoise3DGenerator::cNoise3DGenerator(): Super(), m_Perlin(1000), m_Cubic(1000) { m_Perlin.AddOctave(1, 1); m_Perlin.AddOctave(2, 0.5); m_Perlin.AddOctave(4, 0.25); m_Perlin.AddOctave(8, 0.125); m_Perlin.AddOctave(16, 0.0625); m_Cubic.AddOctave(1, 1); m_Cubic.AddOctave(2, 0.5); m_Cubic.AddOctave(4, 0.25); m_Cubic.AddOctave(8, 0.125); m_Cubic.AddOctave(16, 0.0625); } cNoise3DGenerator::~cNoise3DGenerator() { // Nothing needed yet } void cNoise3DGenerator::Initialize(cIniFile & a_IniFile) { // Params: m_SeaLevel = a_IniFile.GetValueSetI("Generator", "SeaLevel", 62); m_HeightAmplification = static_cast(a_IniFile.GetValueSetF("Generator", "Noise3DHeightAmplification", 0.1)); m_MidPoint = static_cast(a_IniFile.GetValueSetF("Generator", "Noise3DMidPoint", 68)); m_FrequencyX = static_cast(a_IniFile.GetValueSetF("Generator", "Noise3DFrequencyX", 8)); m_FrequencyY = static_cast(a_IniFile.GetValueSetF("Generator", "Noise3DFrequencyY", 8)); m_FrequencyZ = static_cast(a_IniFile.GetValueSetF("Generator", "Noise3DFrequencyZ", 8)); m_AirThreshold = static_cast(a_IniFile.GetValueSetF("Generator", "Noise3DAirThreshold", 0.5)); } void cNoise3DGenerator::GenerateBiomes(cChunkCoords a_ChunkCoords, cChunkDef::BiomeMap & a_BiomeMap) { UNUSED(a_ChunkCoords); for (size_t i = 0; i < ARRAYCOUNT(a_BiomeMap); i++) { a_BiomeMap[i] = biExtremeHills; } } void cNoise3DGenerator::Generate(cChunkDesc & a_ChunkDesc) { NOISE_DATATYPE Noise[17 * 257 * 17]; GenerateNoiseArray(a_ChunkDesc.GetChunkCoords(), Noise); // Output noise into chunk: for (int z = 0; z < cChunkDef::Width; z++) { for (int y = 0; y < cChunkDef::Height; y++) { int idx = z * 17 * 257 + y * 17; for (int x = 0; x < cChunkDef::Width; x++) { NOISE_DATATYPE n = Noise[idx++]; BLOCKTYPE BlockType; if (n > m_AirThreshold) { BlockType = (y > m_SeaLevel) ? E_BLOCK_AIR : E_BLOCK_STATIONARY_WATER; } else { BlockType = E_BLOCK_STONE; } a_ChunkDesc.SetBlockType(x, y, z, BlockType); } } } a_ChunkDesc.UpdateHeightmap(); ComposeTerrain (a_ChunkDesc); } void cNoise3DGenerator::GenerateNoiseArray(cChunkCoords a_ChunkCoords, NOISE_DATATYPE * a_OutNoise) { NOISE_DATATYPE NoiseO[DIM_X * DIM_Y * DIM_Z]; // Output for the Perlin noise NOISE_DATATYPE NoiseW[DIM_X * DIM_Y * DIM_Z]; // Workspace that the noise calculation can use and trash // Our noise array has different layout, XZY, instead of regular chunk's XYZ, that's why the coords are "renamed" NOISE_DATATYPE StartX = static_cast(a_ChunkCoords.m_ChunkX * cChunkDef::Width) / m_FrequencyX; NOISE_DATATYPE EndX = static_cast((a_ChunkCoords.m_ChunkX + 1) * cChunkDef::Width) / m_FrequencyX; NOISE_DATATYPE StartZ = static_cast(a_ChunkCoords.m_ChunkZ * cChunkDef::Width) / m_FrequencyZ; NOISE_DATATYPE EndZ = static_cast((a_ChunkCoords.m_ChunkZ + 1) * cChunkDef::Width) / m_FrequencyZ; NOISE_DATATYPE StartY = 0; NOISE_DATATYPE EndY = static_cast(256) / m_FrequencyY; m_Perlin.Generate3D(NoiseO, DIM_X, DIM_Y, DIM_Z, StartX, EndX, StartY, EndY, StartZ, EndZ, NoiseW); // Precalculate a "height" array: NOISE_DATATYPE Height[DIM_X * DIM_Z]; // Output for the cubic noise heightmap ("source") m_Cubic.Generate2D(Height, DIM_X, DIM_Z, StartX / 5, EndX / 5, StartZ / 5, EndZ / 5); for (size_t i = 0; i < ARRAYCOUNT(Height); i++) { Height[i] = Height[i] * m_HeightAmplification; } // Modify the noise by height data: for (int y = 0; y < DIM_Y; y++) { NOISE_DATATYPE AddHeight = (y * UPSCALE_Y - m_MidPoint) / 30; // AddHeight *= AddHeight * AddHeight; for (int z = 0; z < DIM_Z; z++) { NOISE_DATATYPE * CurRow = &(NoiseO[y * DIM_X + z * DIM_X * DIM_Y]); for (int x = 0; x < DIM_X; x++) { CurRow[x] += AddHeight + Height[x + DIM_X * z]; } } } // Upscale the Perlin noise into full-blown chunk dimensions: LinearUpscale3DArray( NoiseO, DIM_X, DIM_Y, DIM_Z, a_OutNoise, UPSCALE_X, UPSCALE_Y, UPSCALE_Z ); } void cNoise3DGenerator::ComposeTerrain(cChunkDesc & a_ChunkDesc) { // Make basic terrain composition: for (int z = 0; z < cChunkDef::Width; z++) { for (int x = 0; x < cChunkDef::Width; x++) { int LastAir = a_ChunkDesc.GetHeight(x, z) + 1; bool HasHadWater = false; for (int y = LastAir - 1; y > 0; y--) { switch (a_ChunkDesc.GetBlockType(x, y, z)) { case E_BLOCK_AIR: { LastAir = y; break; } case E_BLOCK_STONE: { if (LastAir - y > 3) { break; } if (HasHadWater) { a_ChunkDesc.SetBlockType(x, y, z, E_BLOCK_SAND); } else { a_ChunkDesc.SetBlockType(x, y, z, (LastAir == y + 1) ? E_BLOCK_GRASS : E_BLOCK_DIRT); } break; } case E_BLOCK_STATIONARY_WATER: { LastAir = y; HasHadWater = true; break; } } // switch (GetBlockType()) } // for y a_ChunkDesc.SetBlockType(x, 0, z, E_BLOCK_BEDROCK); } // for x } // for z } //////////////////////////////////////////////////////////////////////////////// // cNoise3DComposable: cNoise3DComposable::cNoise3DComposable(int a_Seed) : m_ChoiceNoise(a_Seed), m_DensityNoiseA(a_Seed + 1), m_DensityNoiseB(a_Seed + 2), m_BaseNoise(a_Seed + 3), m_HeightAmplification(0.0), m_MidPoint(0.0), m_FrequencyX(0.0), m_FrequencyY(0.0), m_FrequencyZ(0.0), m_BaseFrequencyX(0.0), m_BaseFrequencyZ(0.0), m_ChoiceFrequencyX(0.0), m_ChoiceFrequencyY(0.0), m_ChoiceFrequencyZ(0.0), m_AirThreshold(0.0), m_LastChunkCoords(0x7fffffff, 0x7fffffff) // Use dummy coords that won't ever be used by real chunks { } void cNoise3DComposable::Initialize(cIniFile & a_IniFile) { // Params: // The defaults generate extreme hills terrain m_HeightAmplification = static_cast(a_IniFile.GetValueSetF("Generator", "Noise3DHeightAmplification", 0.045)); m_MidPoint = static_cast(a_IniFile.GetValueSetF("Generator", "Noise3DMidPoint", 75)); m_FrequencyX = static_cast(a_IniFile.GetValueSetF("Generator", "Noise3DFrequencyX", 40)); m_FrequencyY = static_cast(a_IniFile.GetValueSetF("Generator", "Noise3DFrequencyY", 40)); m_FrequencyZ = static_cast(a_IniFile.GetValueSetF("Generator", "Noise3DFrequencyZ", 40)); m_BaseFrequencyX = static_cast(a_IniFile.GetValueSetF("Generator", "Noise3DBaseFrequencyX", 40)); m_BaseFrequencyZ = static_cast(a_IniFile.GetValueSetF("Generator", "Noise3DBaseFrequencyZ", 40)); m_ChoiceFrequencyX = static_cast(a_IniFile.GetValueSetF("Generator", "Noise3DChoiceFrequencyX", 40)); m_ChoiceFrequencyY = static_cast(a_IniFile.GetValueSetF("Generator", "Noise3DChoiceFrequencyY", 80)); m_ChoiceFrequencyZ = static_cast(a_IniFile.GetValueSetF("Generator", "Noise3DChoiceFrequencyZ", 40)); m_AirThreshold = static_cast(a_IniFile.GetValueSetF("Generator", "Noise3DAirThreshold", 0)); int NumChoiceOctaves = a_IniFile.GetValueSetI("Generator", "Noise3DNumChoiceOctaves", 4); int NumDensityOctaves = a_IniFile.GetValueSetI("Generator", "Noise3DNumDensityOctaves", 6); int NumBaseOctaves = a_IniFile.GetValueSetI("Generator", "Noise3DNumBaseOctaves", 6); NOISE_DATATYPE BaseNoiseAmplitude = static_cast(a_IniFile.GetValueSetF("Generator", "Noise3DBaseAmplitude", 1)); // Add octaves for the choice noise: NOISE_DATATYPE wavlen = 1, ampl = 0.5; for (int i = 0; i < NumChoiceOctaves; i++) { m_ChoiceNoise.AddOctave(wavlen, ampl); wavlen = wavlen * 2; ampl = ampl / 2; } // Add octaves for the density noises: wavlen = 1; ampl = 1; for (int i = 0; i < NumDensityOctaves; i++) { m_DensityNoiseA.AddOctave(wavlen, ampl); m_DensityNoiseB.AddOctave(wavlen, ampl); wavlen = wavlen * 2; ampl = ampl / 2; } // Add octaves for the base noise: wavlen = 1; ampl = BaseNoiseAmplitude; for (int i = 0; i < NumBaseOctaves; i++) { m_BaseNoise.AddOctave(wavlen, ampl); wavlen = wavlen * 2; ampl = ampl / 2; } } void cNoise3DComposable::GenerateNoiseArrayIfNeeded(cChunkCoords a_ChunkCoords) { if (a_ChunkCoords == m_LastChunkCoords) { // The noise for this chunk is already generated in m_NoiseArray return; } m_LastChunkCoords = a_ChunkCoords; // Generate all the noises: NOISE_DATATYPE ChoiceNoise[5 * 5 * 33]; NOISE_DATATYPE Workspace[5 * 5 * 33]; NOISE_DATATYPE DensityNoiseA[5 * 5 * 33]; NOISE_DATATYPE DensityNoiseB[5 * 5 * 33]; NOISE_DATATYPE BaseNoise[5 * 5]; NOISE_DATATYPE BlockX = static_cast(a_ChunkCoords.m_ChunkX * cChunkDef::Width); NOISE_DATATYPE BlockZ = static_cast(a_ChunkCoords.m_ChunkZ * cChunkDef::Width); // Note that we have to swap the X and Y coords, because noise generator uses [x + SizeX * y + SizeX * SizeY * z] ordering and we want "BlockY" to be "x": m_ChoiceNoise.Generate3D (ChoiceNoise, 33, 5, 5, 0, 257 / m_ChoiceFrequencyY, BlockX / m_ChoiceFrequencyX, (BlockX + 17) / m_ChoiceFrequencyX, BlockZ / m_ChoiceFrequencyZ, (BlockZ + 17) / m_ChoiceFrequencyZ, Workspace); m_DensityNoiseA.Generate3D(DensityNoiseA, 33, 5, 5, 0, 257 / m_FrequencyY, BlockX / m_FrequencyX, (BlockX + 17) / m_FrequencyX, BlockZ / m_FrequencyZ, (BlockZ + 17) / m_FrequencyZ, Workspace); m_DensityNoiseB.Generate3D(DensityNoiseB, 33, 5, 5, 0, 257 / m_FrequencyY, BlockX / m_FrequencyX, (BlockX + 17) / m_FrequencyX, BlockZ / m_FrequencyZ, (BlockZ + 17) / m_FrequencyZ, Workspace); m_BaseNoise.Generate2D (BaseNoise, 5, 5, BlockX / m_BaseFrequencyX, (BlockX + 17) / m_BaseFrequencyX, BlockZ / m_FrequencyZ, (BlockZ + 17) / m_FrequencyZ, Workspace); // Calculate the final noise based on the partial noises: for (int z = 0; z < 5; z++) { for (int x = 0; x < 5; x++) { NOISE_DATATYPE curBaseNoise = BaseNoise[x + 5 * z]; for (int y = 0; y < 33; y++) { NOISE_DATATYPE AddHeight = (static_cast(y * 8) - m_MidPoint) * m_HeightAmplification; // If "underground", make the terrain smoother by forcing the vertical linear gradient into steeper slope: if (AddHeight < 0) { AddHeight *= 4; } // If too high, cut off any terrain: if (y > 28) { AddHeight = AddHeight + static_cast(y - 28) / 4; } // Decide between the two density noises: int idx = 33 * x + 33 * 5 * z + y; Workspace[idx] = ClampedLerp(DensityNoiseA[idx], DensityNoiseB[idx], 8 * (ChoiceNoise[idx] + 0.5f)) + AddHeight + curBaseNoise; } } } LinearUpscale3DArray(Workspace, 33, 5, 5, m_NoiseArray, 8, 4, 4); } void cNoise3DComposable::GenShape(cChunkCoords a_ChunkCoords, cChunkDesc::Shape & a_Shape) { GenerateNoiseArrayIfNeeded(a_ChunkCoords); // Translate the noise array into Shape: for (int z = 0; z < cChunkDef::Width; z++) { for (int x = 0; x < cChunkDef::Width; x++) { for (int y = 0; y < cChunkDef::Height; y++) { a_Shape[y + x * 256 + z * 256 * 16] = (m_NoiseArray[y + 257 * x + 257 * 17 * z] > m_AirThreshold) ? 0 : 1; } } // for x } // for z } //////////////////////////////////////////////////////////////////////////////// // cBiomalNoise3DComposable: cBiomalNoise3DComposable::cBiomalNoise3DComposable(int a_Seed, cBiomeGen & a_BiomeGen) : m_ChoiceNoise(a_Seed), m_DensityNoiseA(a_Seed + 1), m_DensityNoiseB(a_Seed + 2), m_BaseNoise(a_Seed + 3), m_BiomeGen(a_BiomeGen), m_LastChunkCoords(0x7fffffff, 0x7fffffff) // Set impossible coords for the chunk so that it's always considered stale { // Generate the weight distribution for summing up neighboring biomes: m_WeightSum = 0; for (int z = 0; z <= AVERAGING_SIZE * 2; z++) { for (int x = 0; x <= AVERAGING_SIZE * 2; x++) { m_Weight[z][x] = static_cast((AVERAGING_SIZE - std::abs(AVERAGING_SIZE - x)) + (AVERAGING_SIZE - std::abs(AVERAGING_SIZE - z))); m_WeightSum += m_Weight[z][x]; } } } void cBiomalNoise3DComposable::Initialize(cIniFile & a_IniFile) { // Params: // The defaults generate extreme hills terrain m_SeaLevel = a_IniFile.GetValueSetI("Generator", "SeaLevel", 62); m_FrequencyX = static_cast(a_IniFile.GetValueSetF("Generator", "BiomalNoise3DFrequencyX", 40)); m_FrequencyY = static_cast(a_IniFile.GetValueSetF("Generator", "BiomalNoise3DFrequencyY", 40)); m_FrequencyZ = static_cast(a_IniFile.GetValueSetF("Generator", "BiomalNoise3DFrequencyZ", 40)); m_BaseFrequencyX = static_cast(a_IniFile.GetValueSetF("Generator", "BiomalNoise3DBaseFrequencyX", 40)); m_BaseFrequencyZ = static_cast(a_IniFile.GetValueSetF("Generator", "BiomalNoise3DBaseFrequencyZ", 40)); m_ChoiceFrequencyX = static_cast(a_IniFile.GetValueSetF("Generator", "BiomalNoise3DChoiceFrequencyX", 40)); m_ChoiceFrequencyY = static_cast(a_IniFile.GetValueSetF("Generator", "BiomalNoise3DChoiceFrequencyY", 80)); m_ChoiceFrequencyZ = static_cast(a_IniFile.GetValueSetF("Generator", "BiomalNoise3DChoiceFrequencyZ", 40)); m_AirThreshold = static_cast(a_IniFile.GetValueSetF("Generator", "BiomalNoise3DAirThreshold", 0)); int NumChoiceOctaves = a_IniFile.GetValueSetI("Generator", "BiomalNoise3DNumChoiceOctaves", 4); int NumDensityOctaves = a_IniFile.GetValueSetI("Generator", "BiomalNoise3DNumDensityOctaves", 6); int NumBaseOctaves = a_IniFile.GetValueSetI("Generator", "BiomalNoise3DNumBaseOctaves", 6); NOISE_DATATYPE BaseNoiseAmplitude = static_cast(a_IniFile.GetValueSetF("Generator", "BiomalNoise3DBaseAmplitude", 1)); // Add octaves for the choice noise: NOISE_DATATYPE wavlen = 1, ampl = 0.5; for (int i = 0; i < NumChoiceOctaves; i++) { m_ChoiceNoise.AddOctave(wavlen, ampl); wavlen = wavlen * 2; ampl = ampl / 2; } // Add octaves for the density noises: wavlen = 1; ampl = 1; for (int i = 0; i < NumDensityOctaves; i++) { m_DensityNoiseA.AddOctave(wavlen, ampl); m_DensityNoiseB.AddOctave(wavlen, ampl); wavlen = wavlen * 2; ampl = ampl / 2; } // Add octaves for the base noise: wavlen = 1; ampl = BaseNoiseAmplitude; for (int i = 0; i < NumBaseOctaves; i++) { m_BaseNoise.AddOctave(wavlen, ampl); wavlen = wavlen * 2; ampl = ampl / 2; } } void cBiomalNoise3DComposable::GenerateNoiseArrayIfNeeded(cChunkCoords a_ChunkCoords) { if (a_ChunkCoords == m_LastChunkCoords) { // The noise for this chunk is already generated in m_NoiseArray return; } m_LastChunkCoords = a_ChunkCoords; // Calculate the parameters for the biomes: ChunkParam MidPoint; ChunkParam HeightAmp; CalcBiomeParamArrays(a_ChunkCoords, HeightAmp, MidPoint); // Generate all the noises: NOISE_DATATYPE ChoiceNoise[5 * 5 * 33]; NOISE_DATATYPE Workspace[5 * 5 * 33]; NOISE_DATATYPE DensityNoiseA[5 * 5 * 33]; NOISE_DATATYPE DensityNoiseB[5 * 5 * 33]; NOISE_DATATYPE BaseNoise[5 * 5]; NOISE_DATATYPE BlockX = static_cast(a_ChunkCoords.m_ChunkX * cChunkDef::Width); NOISE_DATATYPE BlockZ = static_cast(a_ChunkCoords.m_ChunkZ * cChunkDef::Width); // Note that we have to swap the X and Y coords, because noise generator uses [x + SizeX * y + SizeX * SizeY * z] ordering and we want "BlockY" to be "x": m_ChoiceNoise.Generate3D (ChoiceNoise, 33, 5, 5, 0, 257 / m_ChoiceFrequencyY, BlockX / m_ChoiceFrequencyX, (BlockX + 17) / m_ChoiceFrequencyX, BlockZ / m_ChoiceFrequencyZ, (BlockZ + 17) / m_ChoiceFrequencyZ, Workspace); m_DensityNoiseA.Generate3D(DensityNoiseA, 33, 5, 5, 0, 257 / m_FrequencyY, BlockX / m_FrequencyX, (BlockX + 17) / m_FrequencyX, BlockZ / m_FrequencyZ, (BlockZ + 17) / m_FrequencyZ, Workspace); m_DensityNoiseB.Generate3D(DensityNoiseB, 33, 5, 5, 0, 257 / m_FrequencyY, BlockX / m_FrequencyX, (BlockX + 17) / m_FrequencyX, BlockZ / m_FrequencyZ, (BlockZ + 17) / m_FrequencyZ, Workspace); m_BaseNoise.Generate2D (BaseNoise, 5, 5, BlockX / m_BaseFrequencyX, (BlockX + 17) / m_BaseFrequencyX, BlockZ / m_FrequencyZ, (BlockZ + 17) / m_FrequencyZ, Workspace); // Calculate the final noise based on the partial noises: for (int z = 0; z < 5; z++) { for (int x = 0; x < 5; x++) { NOISE_DATATYPE curMidPoint = MidPoint[x + 5 * z]; NOISE_DATATYPE curHeightAmp = HeightAmp[x + 5 * z]; NOISE_DATATYPE curBaseNoise = BaseNoise[x + 5 * z]; for (int y = 0; y < 33; y++) { NOISE_DATATYPE AddHeight = (static_cast(y * 8) - curMidPoint) * curHeightAmp; // If "underground", make the terrain smoother by forcing the vertical linear gradient into steeper slope: if (AddHeight < 0) { AddHeight *= 4; } // If too high, cut off any terrain: if (y > 28) { AddHeight = AddHeight + static_cast(y - 28) / 4; } // Decide between the two density noises: int idx = 33 * x + y + 33 * 5 * z; Workspace[idx] = ClampedLerp(DensityNoiseA[idx], DensityNoiseB[idx], 8 * (ChoiceNoise[idx] + 0.5f)) + AddHeight + curBaseNoise; } } } LinearUpscale3DArray(Workspace, 33, 5, 5, m_NoiseArray, 8, 4, 4); } void cBiomalNoise3DComposable::CalcBiomeParamArrays(cChunkCoords a_ChunkCoords, ChunkParam & a_HeightAmp, ChunkParam & a_MidPoint) { // Generate the 3 * 3 chunks of biomes around this chunk: cChunkDef::BiomeMap neighborBiomes[3 * 3]; for (int z = 0; z < 3; z++) { for (int x = 0; x < 3; x++) { m_BiomeGen.GenBiomes({a_ChunkCoords.m_ChunkX + x - 1, a_ChunkCoords.m_ChunkZ + z - 1}, neighborBiomes[x + 3 * z]); } } // Sum up the biome values: for (int z = 0; z < 5; z++) { for (int x = 0; x < 5; x++) { NOISE_DATATYPE totalHeightAmp = 0; NOISE_DATATYPE totalMidPoint = 0; // Add up the biomes around this point: for (int relz = 0; relz <= AVERAGING_SIZE * 2; ++relz) { int colz = 16 + z * 4 + relz - AVERAGING_SIZE; // Biome Z coord relative to the neighborBiomes start int neicellz = colz / 16; // Chunk Z coord relative to the neighborBiomes start int neirelz = colz % 16; // Biome Z coord relative to cz in neighborBiomes for (int relx = 0; relx <= AVERAGING_SIZE * 2; ++relx) { int colx = 16 + x * 4 + relx - AVERAGING_SIZE; // Biome X coord relative to the neighborBiomes start int neicellx = colx / 16; // Chunk X coord relative to the neighborBiomes start int neirelx = colx % 16; // Biome X coord relative to cz in neighborBiomes EMCSBiome biome = cChunkDef::GetBiome(neighborBiomes[neicellx + neicellz * 3], neirelx, neirelz); NOISE_DATATYPE heightAmp, midPoint; GetBiomeParams(biome, heightAmp, midPoint); totalHeightAmp += heightAmp * m_Weight[relz][relx]; totalMidPoint += midPoint * m_Weight[relz][relx]; } // for relx } // for relz a_HeightAmp[x + 5 * z] = totalHeightAmp / m_WeightSum; a_MidPoint[x + 5 * z] = totalMidPoint / m_WeightSum; } // for x } // for z } void cBiomalNoise3DComposable::GetBiomeParams(EMCSBiome a_Biome, NOISE_DATATYPE & a_HeightAmp, NOISE_DATATYPE & a_MidPoint) { switch (a_Biome) { case biBeach: a_HeightAmp = 0.2f; a_MidPoint = 60; break; case biBirchForest: a_HeightAmp = 0.1f; a_MidPoint = 64; break; case biBirchForestHills: a_HeightAmp = 0.075f; a_MidPoint = 68; break; case biBirchForestHillsM: a_HeightAmp = 0.075f; a_MidPoint = 68; break; case biBirchForestM: a_HeightAmp = 0.1f; a_MidPoint = 64; break; case biColdBeach: a_HeightAmp = 0.3f; a_MidPoint = 62; break; case biColdTaiga: a_HeightAmp = 0.1f; a_MidPoint = 64; break; case biColdTaigaM: a_HeightAmp = 0.1f; a_MidPoint = 64; break; case biColdTaigaHills: a_HeightAmp = 0.075f; a_MidPoint = 68; break; case biDesertHills: a_HeightAmp = 0.075f; a_MidPoint = 68; break; case biDeepOcean: a_HeightAmp = 0.17f; a_MidPoint = 35; break; case biDesert: a_HeightAmp = 0.29f; a_MidPoint = 62; break; case biDesertM: a_HeightAmp = 0.29f; a_MidPoint = 62; break; case biEnd: a_HeightAmp = 0.15f; a_MidPoint = 64; break; case biExtremeHills: a_HeightAmp = 0.045f; a_MidPoint = 75; break; case biExtremeHillsEdge: a_HeightAmp = 0.1f; a_MidPoint = 70; break; case biExtremeHillsM: a_HeightAmp = 0.045f; a_MidPoint = 75; break; case biExtremeHillsPlus: a_HeightAmp = 0.04f; a_MidPoint = 80; break; case biExtremeHillsPlusM: a_HeightAmp = 0.04f; a_MidPoint = 80; break; case biFlowerForest: a_HeightAmp = 0.1f; a_MidPoint = 64; break; case biForest: a_HeightAmp = 0.1f; a_MidPoint = 64; break; case biForestHills: a_HeightAmp = 0.075f; a_MidPoint = 68; break; case biFrozenRiver: a_HeightAmp = 0.4f; a_MidPoint = 54; break; case biFrozenOcean: a_HeightAmp = 0.12f; a_MidPoint = 45; break; case biIceMountains: a_HeightAmp = 0.075f; a_MidPoint = 68; break; case biIcePlains: a_HeightAmp = 0.3f; a_MidPoint = 62; break; case biIcePlainsSpikes: a_HeightAmp = 0.3f; a_MidPoint = 62; break; case biJungle: a_HeightAmp = 0.1f; a_MidPoint = 63; break; case biJungleEdge: a_HeightAmp = 0.15f; a_MidPoint = 62; break; case biJungleEdgeM: a_HeightAmp = 0.15f; a_MidPoint = 62; break; case biJungleHills: a_HeightAmp = 0.075f; a_MidPoint = 68; break; case biJungleM: a_HeightAmp = 0.1f; a_MidPoint = 63; break; case biMegaSpruceTaiga: a_HeightAmp = 0.09f; a_MidPoint = 64; break; case biMegaSpruceTaigaHills: a_HeightAmp = 0.075f; a_MidPoint = 68; break; case biMegaTaiga: a_HeightAmp = 0.1f; a_MidPoint = 64; break; case biMegaTaigaHills: a_HeightAmp = 0.075f; a_MidPoint = 68; break; case biMesa: a_HeightAmp = 0.09f; a_MidPoint = 61; break; case biMesaBryce: a_HeightAmp = 0.15f; a_MidPoint = 61; break; case biMesaPlateau: a_HeightAmp = 0.25f; a_MidPoint = 86; break; case biMesaPlateauF: a_HeightAmp = 0.25f; a_MidPoint = 96; break; case biMesaPlateauFM: a_HeightAmp = 0.25f; a_MidPoint = 96; break; case biMesaPlateauM: a_HeightAmp = 0.25f; a_MidPoint = 86; break; case biMushroomShore: a_HeightAmp = 0.075f; a_MidPoint = 60; break; case biMushroomIsland: a_HeightAmp = 0.06f; a_MidPoint = 80; break; case biNether: a_HeightAmp = 0.01f; a_MidPoint = 64; break; case biOcean: a_HeightAmp = 0.12f; a_MidPoint = 45; break; case biPlains: a_HeightAmp = 0.3f; a_MidPoint = 62; break; case biRiver: a_HeightAmp = 0.4f; a_MidPoint = 54; break; case biRoofedForest: a_HeightAmp = 0.1f; a_MidPoint = 64; break; case biRoofedForestM: a_HeightAmp = 0.1f; a_MidPoint = 64; break; case biSavanna: a_HeightAmp = 0.3f; a_MidPoint = 62; break; case biSavannaM: a_HeightAmp = 0.3f; a_MidPoint = 62; break; case biSavannaPlateau: a_HeightAmp = 0.3f; a_MidPoint = 85; break; case biSavannaPlateauM: a_HeightAmp = 0.012f; a_MidPoint = 105; break; case biStoneBeach: a_HeightAmp = 0.075f; a_MidPoint = 60; break; case biSunflowerPlains: a_HeightAmp = 0.3f; a_MidPoint = 62; break; case biSwampland: a_HeightAmp = 0.25f; a_MidPoint = 59; break; case biSwamplandM: a_HeightAmp = 0.11f; a_MidPoint = 59; break; case biTaiga: a_HeightAmp = 0.1f; a_MidPoint = 64; break; case biTaigaM: a_HeightAmp = 0.1f; a_MidPoint = 70; break; case biTaigaHills: a_HeightAmp = 0.075f; a_MidPoint = 68; break; case biInvalidBiome: case biNumBiomes: case biVariant: case biNumVariantBiomes: { // Make a crazy terrain so that it stands out a_HeightAmp = 0.001f; a_MidPoint = 90; break; } } } void cBiomalNoise3DComposable::GenShape(cChunkCoords a_ChunkCoords, cChunkDesc::Shape & a_Shape) { GenerateNoiseArrayIfNeeded(a_ChunkCoords); // Translate the noise array into Shape: for (int z = 0; z < cChunkDef::Width; z++) { for (int x = 0; x < cChunkDef::Width; x++) { for (int y = 0; y < cChunkDef::Height; y++) { a_Shape[y + x * 256 + z * 256 * 16] = (m_NoiseArray[y + 257 * x + 257 * 17 * z] > m_AirThreshold) ? 0 : 1; } } // for x } // for z } ================================================ FILE: src/Generating/Noise3DGenerator.h ================================================ // Noise3DGenerator.h // Declares cNoise3DGenerator and cNoise3DComposable classes, representing 3D-noise-based generators. // They generate terrain shape by combining a lerp of two 3D noises with a vertical linear gradient // cNoise3DGenerator is obsolete and unmaintained. // cNoise3DComposable is used to test parameter combinations for single-biome worlds. #pragma once #include "ComposableGenerator.h" #include "../Noise/Noise.h" #include "../Noise/InterpolNoise.h" class cNoise3DGenerator: public cChunkGenerator { using Super = cChunkGenerator; public: cNoise3DGenerator(); virtual ~cNoise3DGenerator() override; virtual void Initialize(cIniFile & a_IniFile) override; virtual void GenerateBiomes(cChunkCoords a_ChunkCoords, cChunkDef::BiomeMap & a_BiomeMap) override; virtual void Generate(cChunkDesc & a_ChunkDesc) override; protected: // Linear interpolation step sizes, must be divisors of cChunkDef::Width and cChunkDef::Height, respectively: static const int UPSCALE_X = 4; static const int UPSCALE_Y = 8; static const int UPSCALE_Z = 4; // Linear interpolation buffer dimensions, calculated from the step sizes: static const int DIM_X = 1 + cChunkDef::Width / UPSCALE_X; static const int DIM_Y = 1 + cChunkDef::Height / UPSCALE_Y; static const int DIM_Z = 1 + cChunkDef::Width / UPSCALE_Z; /** The base 3D noise source for the actual composition */ cOctavedNoise m_Perlin; /** The noise used for heightmap directing. */ cOctavedNoise m_Cubic; int m_SeaLevel; NOISE_DATATYPE m_HeightAmplification; NOISE_DATATYPE m_MidPoint; // Where the vertical "center" of the noise should be NOISE_DATATYPE m_FrequencyX; NOISE_DATATYPE m_FrequencyY; NOISE_DATATYPE m_FrequencyZ; NOISE_DATATYPE m_AirThreshold; /** Generates the 3D noise array used for terrain generation into a_Noise; a_Noise is of ChunkData-size */ void GenerateNoiseArray(cChunkCoords a_ChunkCoords, NOISE_DATATYPE * a_Noise); /** Composes terrain - adds dirt, grass and sand */ void ComposeTerrain(cChunkDesc & a_ChunkDesc); } ; class cNoise3DComposable : public cTerrainShapeGen { public: cNoise3DComposable(int a_Seed); void Initialize(cIniFile & a_IniFile); protected: /** The 3D noise that is used to choose between density noise A and B. */ cOctavedNoise> m_ChoiceNoise; /** Density 3D noise, variant A. */ cOctavedNoise> m_DensityNoiseA; /** Density 3D noise, variant B. */ cOctavedNoise> m_DensityNoiseB; /** Heightmap-like noise used to provide variance for low-amplitude biomes. */ cOctavedNoise> m_BaseNoise; /** The main parameter of the generator, specifies the slope of the vertical linear gradient. A higher value means a steeper slope and a smaller total amplitude of the generated terrain. */ NOISE_DATATYPE m_HeightAmplification; /** Where the vertical "center" of the noise should be, as block height. */ NOISE_DATATYPE m_MidPoint; // Frequency of the 3D noise's first octave: NOISE_DATATYPE m_FrequencyX; NOISE_DATATYPE m_FrequencyY; NOISE_DATATYPE m_FrequencyZ; // Frequency of the base terrain noise: NOISE_DATATYPE m_BaseFrequencyX; NOISE_DATATYPE m_BaseFrequencyZ; // Frequency of the choice noise: NOISE_DATATYPE m_ChoiceFrequencyX; NOISE_DATATYPE m_ChoiceFrequencyY; NOISE_DATATYPE m_ChoiceFrequencyZ; // Threshold for when the values are considered air: NOISE_DATATYPE m_AirThreshold; // Cache for the last calculated chunk (reused between heightmap and composition queries): cChunkCoords m_LastChunkCoords; NOISE_DATATYPE m_NoiseArray[17 * 17 * 257]; // x + 17 * z + 17 * 17 * y /** Generates the 3D noise array used for terrain generation (m_NoiseArray), unless the LastChunk coords are equal to coords given */ void GenerateNoiseArrayIfNeeded(cChunkCoords a_ChunkCoords); // cTerrainHeightGen overrides: virtual void GenShape(cChunkCoords a_ChunkCoords, cChunkDesc::Shape & a_Shape) override; virtual void InitializeShapeGen(cIniFile & a_IniFile) override { Initialize(a_IniFile); } } ; class cBiomalNoise3DComposable : public cTerrainShapeGen { public: cBiomalNoise3DComposable(int a_Seed, cBiomeGen & a_BiomeGen); void Initialize(cIniFile & a_IniFile); protected: /** Number of columns around the pixel to query for biomes for averaging. Must be less than or equal to 16. */ static const int AVERAGING_SIZE = 9; /** Type used for a single parameter across the entire (downscaled) chunk. */ typedef NOISE_DATATYPE ChunkParam[5 * 5]; /** The noise that is used to choose between density noise A and B. */ cOctavedNoise> m_ChoiceNoise; /** Density 3D noise, variant A. */ cOctavedNoise> m_DensityNoiseA; /** Density 3D noise, variant B. */ cOctavedNoise> m_DensityNoiseB; /** Heightmap-like noise used to provide variance for low-amplitude biomes. */ cOctavedNoise> m_BaseNoise; /** The underlying biome generator. */ cBiomeGen & m_BiomeGen; /** Block height of the sealevel, used for composing the terrain. */ int m_SeaLevel; // Frequency of the 3D noise's first octave: NOISE_DATATYPE m_FrequencyX; NOISE_DATATYPE m_FrequencyY; NOISE_DATATYPE m_FrequencyZ; // Frequency of the base terrain noise: NOISE_DATATYPE m_BaseFrequencyX; NOISE_DATATYPE m_BaseFrequencyZ; // Frequency of the choice noise: NOISE_DATATYPE m_ChoiceFrequencyX; NOISE_DATATYPE m_ChoiceFrequencyY; NOISE_DATATYPE m_ChoiceFrequencyZ; // Threshold for when the values are considered air: NOISE_DATATYPE m_AirThreshold; // Cache for the last calculated chunk (reused between heightmap and composition queries): cChunkCoords m_LastChunkCoords; NOISE_DATATYPE m_NoiseArray[17 * 17 * 257]; // 257 * x + y + 257 * 17 * z /** Weights for summing up neighboring biomes. */ NOISE_DATATYPE m_Weight[AVERAGING_SIZE * 2 + 1][AVERAGING_SIZE * 2 + 1]; /** The sum of m_Weight[]. */ NOISE_DATATYPE m_WeightSum; /** Generates the 3D noise array used for terrain generation (m_NoiseArray), unless the LastChunk coords are equal to coords given */ void GenerateNoiseArrayIfNeeded(cChunkCoords a_ChunkCoords); /** Calculates the biome-related parameters for the chunk. */ void CalcBiomeParamArrays(cChunkCoords a_ChunkCoords, ChunkParam & a_HeightAmp, ChunkParam & a_MidPoint); /** Returns the parameters for the specified biome. */ void GetBiomeParams(EMCSBiome a_Biome, NOISE_DATATYPE & a_HeightAmp, NOISE_DATATYPE & a_MidPoint); // cTerrainShapeGen overrides: virtual void GenShape(cChunkCoords a_ChunkCoords, cChunkDesc::Shape & a_Shape) override; virtual void InitializeShapeGen(cIniFile & a_IniFile) override { Initialize(a_IniFile); } } ; ================================================ FILE: src/Generating/PieceGeneratorBFSTree.cpp ================================================ // PieceGeneratorBFSTree.cpp // Implements the cPieceGeneratorBFSTree class for generating structures composed of individual "pieces" in a simple tree /* The generator keeps a pool of currently-open connectors, chooses one at random and tries to place a piece on it, thus possibly extending the pool of open connectors with the new piece's ones (like breadth-first search). */ #include "Globals.h" #include "PieceGeneratorBFSTree.h" #include "VerticalStrategy.h" #include "VerticalLimit.h" //////////////////////////////////////////////////////////////////////////////// // cPieceGeneratorBFSTree: cPieceGeneratorBFSTree::cPieceGeneratorBFSTree(cPiecePool & a_PiecePool, int a_Seed): m_PiecePool(a_PiecePool), m_Noise(a_Seed), m_Seed(a_Seed) { } cPlacedPiecePtr cPieceGeneratorBFSTree::PlaceStartingPiece(int a_BlockX, int a_BlockZ, cFreeConnectors & a_OutConnectors) { m_PiecePool.Reset(); int rnd = m_Noise.IntNoise2DInt(a_BlockX, a_BlockZ) / 7; // Choose a random one of the starting pieces: cPieces StartingPieces = m_PiecePool.GetStartingPieces(); int Total = 0; for (cPieces::const_iterator itr = StartingPieces.begin(), end = StartingPieces.end(); itr != end; ++itr) { Total += m_PiecePool.GetStartingPieceWeight(**itr); } cPiece * StartingPiece; if (Total > 0) { int Chosen = rnd % Total; StartingPiece = StartingPieces.front(); for (cPieces::const_iterator itr = StartingPieces.begin(), end = StartingPieces.end(); itr != end; ++itr) { Chosen -= m_PiecePool.GetStartingPieceWeight(**itr); if (Chosen <= 0) { StartingPiece = *itr; break; } } } else { // All pieces returned zero weight, but we need one to start. Choose with equal chance: StartingPiece = StartingPieces[static_cast(rnd) % StartingPieces.size()]; } rnd = rnd >> 16; // Choose a random supported rotation: int Rotations[4] = {0}; int NumRotations = 1; for (size_t i = 1; i < ARRAYCOUNT(Rotations); i++) { if (StartingPiece->CanRotateCCW(static_cast(i))) { Rotations[NumRotations] = static_cast(i); NumRotations += 1; } } int Rotation = Rotations[rnd % NumRotations]; int BlockY = StartingPiece->GetStartingPieceHeight(a_BlockX, a_BlockZ); ASSERT(BlockY >= 0); // The vertical strategy should have been provided and should give valid coords cPlacedPiece * res = new cPlacedPiece(nullptr, *StartingPiece, Vector3i(a_BlockX, BlockY, a_BlockZ), Rotation); // Place the piece's connectors into a_OutConnectors: const cPiece::cConnectors & Conn = StartingPiece->GetConnectors(); for (cPiece::cConnectors::const_iterator itr = Conn.begin(), end = Conn.end(); itr != end; ++itr) { a_OutConnectors.push_back( cFreeConnector(res, StartingPiece->RotateMoveConnector(*itr, Rotation, a_BlockX, BlockY, a_BlockZ)) ); } return cPlacedPiecePtr(res); } bool cPieceGeneratorBFSTree::TryPlacePieceAtConnector( const cPlacedPiece & a_ParentPiece, const cPiece::cConnector & a_Connector, cPlacedPieces & a_OutPieces, cPieceGeneratorBFSTree::cFreeConnectors & a_OutConnectors ) { // Get a list of available connections: cConnections Connections; int WantedConnectorType = -a_Connector.m_Type; cPieces AvailablePieces = m_PiecePool.GetPiecesWithConnector(WantedConnectorType); Connections.reserve(AvailablePieces.size()); Vector3i ConnPos = cPiece::cConnector::AddDirection(a_Connector.m_Pos, a_Connector.m_Direction); // The position at which the new connector should be placed - 1 block away from the current connector int WeightTotal = 0; for (cPieces::iterator itrP = AvailablePieces.begin(), endP = AvailablePieces.end(); itrP != endP; ++itrP) { // Get the relative chance of this piece being generated in this path: int Weight = m_PiecePool.GetPieceWeight(a_ParentPiece, a_Connector, **itrP); if (Weight <= 0) { continue; } // Try fitting each of the piece's connector: cPiece::cConnectors Connectors = (*itrP)->GetConnectors(); auto verticalLimit = (*itrP)->GetVerticalLimit(); for (cPiece::cConnectors::iterator itrC = Connectors.begin(), endC = Connectors.end(); itrC != endC; ++itrC) { if (itrC->m_Type != WantedConnectorType) { continue; } // This is a same-type connector, find out how to rotate to it: int NumCCWRotations = cPiece::cConnector::GetNumCCWRotationsToFit(a_Connector.m_Direction, itrC->m_Direction); if ((NumCCWRotations < 0) || !(*itrP)->CanRotateCCW(NumCCWRotations)) { // Doesn't support this rotation continue; } // Check if the piece's VerticalLimit allows this connection: if ((verticalLimit != nullptr) && (!verticalLimit->CanBeAtHeight(ConnPos.x, ConnPos.z, ConnPos.y - itrC->m_Pos.y))) { continue; } if (!CheckConnection(a_Connector, ConnPos, **itrP, *itrC, NumCCWRotations, a_OutPieces)) { // Doesn't fit in this rotation continue; } // Fits, add it to list of possibile connections: Connections.emplace_back(**itrP, *itrC, NumCCWRotations, Weight); WeightTotal += Weight; } // for itrC - Connectors[] } // for itrP - AvailablePieces[] if (Connections.empty()) { // No available connections, bail out return false; } ASSERT(WeightTotal > 0); // Choose a random connection from the list, based on the weights: int rnd = (m_Noise.IntNoise3DInt(a_Connector.m_Pos.x, a_Connector.m_Pos.y, a_Connector.m_Pos.z) / 7) % WeightTotal; size_t ChosenIndex = 0; for (cConnections::const_iterator itr = Connections.begin(), end = Connections.end(); itr != end; ++itr, ++ChosenIndex) { rnd -= itr->m_Weight; if (rnd <= 0) { // This is the piece to choose break; } } cConnection & Conn = Connections[ChosenIndex]; // Place the piece: Vector3i NewPos = Conn.m_Piece->RotatePos(Conn.m_Connector.m_Pos, Conn.m_NumCCWRotations); ConnPos -= NewPos; auto PlacedPiece = std::make_unique(&a_ParentPiece, *(Conn.m_Piece), ConnPos, Conn.m_NumCCWRotations); // Add the new piece's connectors to the list of free connectors: cPiece::cConnectors Connectors = Conn.m_Piece->GetConnectors(); for (cPiece::cConnectors::const_iterator itr = Connectors.begin(), end = Connectors.end(); itr != end; ++itr) { if (itr->m_Pos.Equals(Conn.m_Connector.m_Pos)) { // This is the connector through which we have been connected to the parent, don't add continue; } a_OutConnectors.emplace_back(PlacedPiece.get(), Conn.m_Piece->RotateMoveConnector(*itr, Conn.m_NumCCWRotations, ConnPos.x, ConnPos.y, ConnPos.z)); } a_OutPieces.push_back(std::move(PlacedPiece)); return true; } bool cPieceGeneratorBFSTree::CheckConnection( const cPiece::cConnector & a_ExistingConnector, const Vector3i & a_ToPos, const cPiece & a_Piece, const cPiece::cConnector & a_NewConnector, int a_NumCCWRotations, const cPlacedPieces & a_OutPieces ) { // For each placed piece, test the hitbox against the new piece: cCuboid RotatedHitBox = a_Piece.RotateHitBoxToConnector(a_NewConnector, a_ToPos, a_NumCCWRotations); RotatedHitBox.Sort(); for (cPlacedPieces::const_iterator itr = a_OutPieces.begin(), end = a_OutPieces.end(); itr != end; ++itr) { if ((*itr)->GetHitBox().DoesIntersect(RotatedHitBox)) { return false; } } return true; } void cPieceGeneratorBFSTree::PlacePieces(int a_BlockX, int a_BlockZ, int a_MaxDepth, cPlacedPieces & a_OutPieces) { a_OutPieces.clear(); cFreeConnectors ConnectorPool; // Place the starting piece: a_OutPieces.push_back(PlaceStartingPiece(a_BlockX, a_BlockZ, ConnectorPool)); /* // DEBUG: FLOGD("Placed the starting piece at {0}", Vector3i{a_BlockX, a_BlockY, a_BlockZ}); cCuboid Hitbox = a_OutPieces[0]->GetHitBox(); Hitbox.Sort(); FLOGD(" Hitbox: {0} - {1} ({2} * {3} * {4})\n", Hitbox.p1, Hitbox.p2, Hitbox.DifX() + 1, Hitbox.DifY() + 1, Hitbox.DifZ() + 1 ); DebugConnectorPool(ConnectorPool, 0); //*/ // Place pieces at the available connectors: /* Instead of removing them one by one from the pool, we process them sequentially and take note of the last processed one. To save on memory, once the number of processed connectors reaches a big number, a chunk of the connectors is removed. */ size_t NumProcessed = 0; while (ConnectorPool.size() > NumProcessed) { cFreeConnector & Conn = ConnectorPool[NumProcessed]; if (Conn.m_Piece->GetDepth() < a_MaxDepth) { if (TryPlacePieceAtConnector(*Conn.m_Piece, Conn.m_Connector, a_OutPieces, ConnectorPool)) { /* // DEBUG: const cPlacedPiece * NewPiece = a_OutPieces.back(); const Vector3i & Coords = NewPiece->GetCoords(); FLOGD("Placed a new piece at {0}, rotation {1}\n", Coords, NewPiece->GetNumCCWRotations()); cCuboid Hitbox = NewPiece->GetHitBox(); Hitbox.Sort(); FLOGD(" Hitbox: {0} - {1} ({2} * {3} * {4})\n", Hitbox.p1, Hitbox.p2, Hitbox.DifX() + 1, Hitbox.DifY() + 1, Hitbox.DifZ() + 1 ); DebugConnectorPool(ConnectorPool, NumProcessed + 1); //*/ } } NumProcessed++; if (NumProcessed > 1000) { typedef cPieceGeneratorBFSTree::cFreeConnectors::difference_type difType; ConnectorPool.erase(ConnectorPool.begin(), ConnectorPool.begin() + static_cast(NumProcessed)); NumProcessed = 0; } } } //* // DEBUG: void cPieceGeneratorBFSTree::DebugConnectorPool(const cPieceGeneratorBFSTree::cFreeConnectors & a_ConnectorPool, size_t a_NumProcessed) { fmt::print(" Connector pool: {0} items\n", a_ConnectorPool.size() - a_NumProcessed); size_t idx = 0; typedef cPieceGeneratorBFSTree::cFreeConnectors::difference_type difType; for (auto itr = a_ConnectorPool.cbegin() + static_cast(a_NumProcessed), end = a_ConnectorPool.cend(); itr != end; ++itr, ++idx) { fmt::print(" {0}: {{{1}, {2}, {3}}}, type {4}, direction {5}, depth {6}\n", idx, itr->m_Connector.m_Pos.x, itr->m_Connector.m_Pos.y, itr->m_Connector.m_Pos.z, itr->m_Connector.m_Type, cPiece::cConnector::DirectionToString(itr->m_Connector.m_Direction), itr->m_Piece->GetDepth() ); } // for itr - a_ConnectorPool[] } //*/ //////////////////////////////////////////////////////////////////////////////// // cPieceGeneratorBFSTree::cConnection: cPieceGeneratorBFSTree::cConnection::cConnection(cPiece & a_Piece, cPiece::cConnector & a_Connector, int a_NumCCWRotations, int a_Weight) : m_Piece(&a_Piece), m_Connector(a_Connector), m_NumCCWRotations(a_NumCCWRotations), m_Weight(a_Weight) { } //////////////////////////////////////////////////////////////////////////////// // cPieceGeneratorBFSTree::cFreeConnector: cPieceGeneratorBFSTree::cFreeConnector::cFreeConnector(cPlacedPiece * a_Piece, const cPiece::cConnector & a_Connector) : m_Piece(a_Piece), m_Connector(a_Connector) { } ================================================ FILE: src/Generating/PieceGeneratorBFSTree.h ================================================ // PieceGeneratorBFSTree.h // Declares the cPieceGeneratorBFSTree class for generating structures composed of individual "pieces" in a simple tree #pragma once #include "PiecePool.h" #include "../Noise/Noise.h" class cPieceGeneratorBFSTree { public: /** Creates a new object tied to the specified PiecePool, using the specified seed. */ cPieceGeneratorBFSTree(cPiecePool & a_PiecePool, int a_Seed); /** Generates a placement for pieces at the specified coords. The Y coord is generated automatically based on the starting piece that is chosen. */ void PlacePieces(int a_BlockX, int a_BlockZ, int a_MaxDepth, cPlacedPieces & a_OutPieces); protected: /** The type used for storing a connection from one piece to another, while building the piece tree. */ struct cConnection { cPiece * m_Piece; // The piece being connected cPiece::cConnector m_Connector; // The piece's connector being used (relative non-rotated coords) int m_NumCCWRotations; // Number of rotations necessary to match the two connectors int m_Weight; // Relative chance that this connection will be chosen cConnection(cPiece & a_Piece, cPiece::cConnector & a_Connector, int a_NumCCWRotations, int a_Weight); }; typedef std::vector cConnections; /** The type used for storing a pool of connectors that will be attempted to expand by another piece. */ struct cFreeConnector { cPlacedPiece * m_Piece; cPiece::cConnector m_Connector; cFreeConnector(cPlacedPiece * a_Piece, const cPiece::cConnector & a_Connector); }; typedef std::vector cFreeConnectors; /** The pool from which pieces are taken. */ cPiecePool & m_PiecePool; /** The noise used for random number generation. */ cNoise m_Noise; /** The seed used by this generator. */ int m_Seed; /** Selects a starting piece and places it, including its height and rotation. Also puts the piece's connectors in a_OutConnectors. */ cPlacedPiecePtr PlaceStartingPiece(int a_BlockX, int a_BlockZ, cFreeConnectors & a_OutConnectors); /** Tries to place a new piece at the specified (placed) connector. Returns true if successful. */ bool TryPlacePieceAtConnector( const cPlacedPiece & a_ParentPiece, // The existing piece to a new piece should be placed const cPiece::cConnector & a_Connector, // The existing connector (world-coords) to which a new piece should be placed cPlacedPieces & a_OutPieces, // Already placed pieces, to be checked for intersections cFreeConnectors & a_OutConnectors // List of free connectors to which the new connectors will be placed ); /** Checks if the specified piece would fit with the already-placed pieces, using the specified connector and number of CCW rotations. a_ExistingConnector is in world-coords and is already rotated properly a_ToPos is the world-coords position on which the new connector should be placed (1 block away from a_ExistingConnector, in its Direction) a_NewConnector is in the original (non-rotated) coords. Returns true if the piece fits, false if not. */ bool CheckConnection( const cPiece::cConnector & a_ExistingConnector, // The existing connector const Vector3i & a_ToPos, // The position on which the new connector should be placed const cPiece & a_Piece, // The new piece const cPiece::cConnector & a_NewConnector, // The connector of the new piece int a_NumCCWRotations, // Number of rotations for the new piece to align the connector const cPlacedPieces & a_OutPieces // All the already-placed pieces to check ); /** DEBUG: Outputs all the connectors in the pool into stdout. a_NumProcessed signals the number of connectors from the pool that should be considered processed (not listed). */ void DebugConnectorPool(const cFreeConnectors & a_ConnectorPool, size_t a_NumProcessed); } ; ================================================ FILE: src/Generating/PieceModifier.cpp ================================================ // PieceModifier.cpp // Implements the various classes descending from cPiece::cPieceModifier #include "Globals.h" #include "PieceModifier.h" #include "../Noise/Noise.h" // Constant that is added to seed static const int SEED_OFFSET = 135 * 13; //////////////////////////////////////////////////////////////////////////////// /** A modifier which is pseudo-randomly replacing blocks to other types and metas. */ class cPieceModifierRandomizeBlocks: public cPiece::cPieceModifier { public: cPieceModifierRandomizeBlocks(void) : m_Seed() { } virtual bool InitializeFromString(const AString & a_Params, bool a_LogWarnings) override { m_AllWeights = 0; AString Params = a_Params; /** BlocksToReplace parsing */ auto idxPipe = Params.find('|'); if (idxPipe != AString::npos) { AString blocksToReplaceStr = Params.substr(0, idxPipe); auto blocksToReplace = StringSplitAndTrim(blocksToReplaceStr, ","); for (size_t i = 0; i < blocksToReplace.size(); i++) { BLOCKTYPE blockType = static_cast(BlockStringToType(blocksToReplace[i])); if ((blockType == E_BLOCK_AIR) && !NoCaseCompare(blocksToReplace[i], "Air")) { CONDWARNING(a_LogWarnings, "Cannot parse block type from string \"%s\"!", blocksToReplace[i].c_str()); return false; } m_BlocksToReplace[blockType] = 1; } Params = Params.substr(idxPipe + 1, Params.length() - 1); } if (m_BlocksToReplace.size() == 0) { CONDWARNING(a_LogWarnings, "You must specify at least one block to replace%s!", ""); return false; } /** Meta params parsing */ auto idxSqBracketStart = Params.find('['); auto idxSqBracketStartLast = Params.find_last_of('['); bool isMultiMeta = false; if ((idxSqBracketStart != idxSqBracketStartLast) && (idxSqBracketStartLast != Params.length() - 1)) { // Meta per block type isMultiMeta = true; } else { auto idxSqBracketEnd = Params.find(']'); if ((idxSqBracketEnd == Params.length() - 1) && (idxSqBracketStart != AString::npos)) { AString metaParamsStr = Params.substr(idxSqBracketStart + 1, Params.length() - idxSqBracketStart - 2); std::array metaParamsInt; if (!ParseMeta(metaParamsStr, metaParamsInt, a_LogWarnings)) { return false; } m_MinMeta = metaParamsInt[0]; m_MaxMeta = metaParamsInt[1]; m_MinNoiseMeta = metaParamsInt[2]; m_MaxNoiseMeta = metaParamsInt[3]; Params = Params.substr(0, idxSqBracketStart); } } // BlocksToRandomize parsing auto BlocksToRandomize = StringSplitAndTrim(Params, ";"); for (size_t i = 0; i < BlocksToRandomize.size(); i++) { AString block = BlocksToRandomize[i]; cRandomizedBlock Block{}; if (isMultiMeta) { auto sqBrStart = block.find('['); if (sqBrStart != AString::npos) { auto sqBrEnd = block.find(']'); if (sqBrEnd != block.size() - 1) { CONDWARNING(a_LogWarnings, "If present, block meta params must be at the end of block to randomize definition \"%s\"!", block.c_str()); return false; } AString metaParamsStr = block.substr(sqBrStart + 1, block.size() - sqBrStart - 2); std::array metaParamsInt; if (!ParseMeta(metaParamsStr, metaParamsInt, a_LogWarnings)) { return false; } Block.m_MinMeta = metaParamsInt[0]; Block.m_MaxMeta = metaParamsInt[1]; Block.m_MinNoiseMeta = metaParamsInt[2]; Block.m_MaxNoiseMeta = metaParamsInt[3]; block = block.substr(0, sqBrStart); } // No meta randomization for this block } auto BlockParams = StringSplitAndTrim(block, ","); if (BlockParams.size() < 2) { CONDWARNING(a_LogWarnings, "Block weight is required param \"%s\"!", BlockParams[0].c_str()); return false; } BLOCKTYPE BlockType = static_cast(BlockStringToType(BlockParams[0])); int BlockWeight = 0; if ((BlockType != E_BLOCK_AIR) && !NoCaseCompare(BlockParams[0], "Air")) { // Failed to parse block type CONDWARNING( a_LogWarnings, "Cannot parse block type from string \"%s\"!", BlockParams[0].c_str()); return false; } if (!StringToInteger(BlockParams[1], BlockWeight)) { // Failed to parse the crop weight: CONDWARNING( a_LogWarnings, "Cannot parse block weight from string \"%s\"!", BlockParams[1].c_str()); return false; } Block.m_Type = BlockType; Block.m_Weight = BlockWeight; m_AllWeights += BlockWeight; m_BlocksToRandomize.push_back(Block); } if (m_BlocksToRandomize.size() == 0) { CONDWARNING(a_LogWarnings, "You must specify at least one block to randomize%s!", ""); return false; } return true; } bool ParseMeta(const AString & a_Meta, std::array & a_ParsedMeta, bool a_LogWarnings) { auto MetaParams = StringSplitAndTrim(a_Meta, ","); for (size_t i = 0; i < MetaParams.size(); i++) { int Value; if (!StringToInteger(MetaParams[i], Value)) { // Failed to parse meta parameter from string: CONDWARNING(a_LogWarnings, "Cannot parse meta param from string \"%s\", meta: %s!", MetaParams[i].c_str(), a_Meta.c_str()); return false; } if (i > 3) { CONDWARNING(a_LogWarnings, "Unsupported meta param \"%d\"!", Value); return false; } a_ParsedMeta[i] = Value; } if (MetaParams.size() == 1) { // Noise is not used for meta a_ParsedMeta[1] = a_ParsedMeta[0]; } else if (MetaParams.size() == 2) { // Noise range is same as meta range a_ParsedMeta[2] = a_ParsedMeta[0]; a_ParsedMeta[3] = a_ParsedMeta[1]; } else if (MetaParams.size() == 3) { a_ParsedMeta[3] = a_ParsedMeta[1]; } return true; } virtual void Modify(cBlockArea & a_Image, const Vector3i a_PiecePos, const int a_PieceRot) override { cNoise Noise(m_Seed); cNoise PieceNoise(Noise.IntNoise3DInt(a_PiecePos)); size_t NumBlocks = a_Image.GetBlockCount(); BLOCKTYPE * BlockTypes = a_Image.GetBlockTypes(); BLOCKTYPE * BlockMetas = a_Image.GetBlockMetas(); for (size_t i = 0; i < NumBlocks; i++) { if (m_BlocksToReplace.count(BlockTypes[i])) { float BlockRnd = PieceNoise.IntNoise2DInRange(a_PieceRot, static_cast(i), 0.0F, static_cast(m_AllWeights)); int weightDelta = 0; for (auto & blockToRnd : m_BlocksToRandomize) { weightDelta += blockToRnd.m_Weight; if (BlockRnd <= weightDelta) { BlockTypes[i] = blockToRnd.m_Type; // Per block meta params if (blockToRnd.m_MinMeta < blockToRnd.m_MaxMeta) { int BlockMetaRnd = std::clamp(static_cast(PieceNoise.IntNoise2DInRange(a_PieceRot*2, static_cast(i), static_cast(blockToRnd.m_MinNoiseMeta), static_cast(blockToRnd.m_MaxNoiseMeta))), blockToRnd.m_MinMeta, blockToRnd.m_MaxMeta); BlockMetas[i] = static_cast(BlockMetaRnd); } else if ((blockToRnd.m_MaxMeta > -1) && (blockToRnd.m_MaxMeta == blockToRnd.m_MinMeta)) { // Change meta if at least minimum meta was specified BlockMetas[i] = static_cast(blockToRnd.m_MaxMeta); } break; } } // All blocks meta params if (m_MaxMeta > m_MinMeta) { int BlockMetaRnd = std::clamp(static_cast(PieceNoise.IntNoise2DInRange(a_PieceRot * 2, static_cast(i), static_cast(m_MinNoiseMeta), static_cast(m_MaxNoiseMeta))), m_MinMeta, m_MaxMeta); BlockMetas[i] = static_cast(BlockMetaRnd); } else if ((m_MaxMeta > -1) && (m_MaxMeta == m_MinMeta)) { // Change meta if at least minimum meta was specified BlockMetas[i] = static_cast(m_MaxMeta); } } } // for i - BlockTypes[] } virtual void AssignSeed(int a_Seed) override { m_Seed = a_Seed + SEED_OFFSET; } protected: int m_Seed; int m_AllWeights = 0; /** Block types of a blocks which are being replaced by this strategy */ std::map m_BlocksToReplace; /** Randomized blocks with their weights and meta params */ cRandomizedBlocks m_BlocksToRandomize; /** Minimum meta to randomize */ int m_MinMeta = 0; /** Maximum meta to randomize */ int m_MaxMeta = -1; /** Maximum meta in noise range */ int m_MaxNoiseMeta = 0; /** Minimum meta in noise range */ int m_MinNoiseMeta = 0; }; //////////////////////////////////////////////////////////////////////////////// // CreatePieceModifierFromString: bool CreatePieceModifierFromString(const AString & a_Definition, std::shared_ptr & a_Modifiers, bool a_LogWarnings) { auto idxCurlyStart = a_Definition.find('{'); auto idxCurlyFirstEnd = a_Definition.find('}'); if ((idxCurlyStart == AString::npos) && (idxCurlyFirstEnd == AString::npos)) { CONDWARNING(a_LogWarnings, "Piece metadata \"Modifiers\" needs at least one valid modifier definition \"%s\"!", a_Definition.c_str()); return false; } auto modifiersStr = StringSplitAndTrim(a_Definition, "{"); for (size_t i = 0; i < modifiersStr.size(); i++) { AString modifierStr = TrimString(modifiersStr[i]); if (modifierStr.size() == 0) { continue; } auto idxCurlyEnd = modifierStr.find('}'); if (idxCurlyEnd == AString::npos) { CONDWARNING(a_LogWarnings, "Modifier definition must end with curly bracket \"%s\"!!", modifierStr.c_str()); return false; } modifierStr = modifierStr.substr(0, idxCurlyEnd); // Break apart the modifier class, the first parameter before the first pipe char: auto idxPipe = modifierStr.find('|'); if (idxPipe == AString::npos) { idxPipe = modifierStr.length(); } AString ModifierClass = modifierStr.substr(0, idxPipe); // Create a modifier class based on the class string: cPiece::cPieceModifierPtr Modifier; if (NoCaseCompare(ModifierClass, "RandomizeBlocks") == 0) { Modifier = std::make_shared(); } if (Modifier == nullptr) { CONDWARNING(a_LogWarnings, "Unknown modifier class \"%s\" %s!", ModifierClass.c_str(), modifierStr.c_str()); return false; } // Initialize the modifier's parameters: AString Params; if (idxPipe < modifierStr.length()) { Params = modifierStr.substr(idxPipe + 1); } if (!Modifier->InitializeFromString(Params, a_LogWarnings)) { CONDWARNING(a_LogWarnings, "InitializeFromString error \"%s\" -- %!", Params.c_str(), modifierStr.c_str()); return false; } a_Modifiers->push_back(Modifier); } return true; } ================================================ FILE: src/Generating/PieceModifier.h ================================================ // PieceModifier.h // Declares the public interface for cPiece's cPieceModifier implementations #pragma once #include "PiecePool.h" bool CreatePieceModifierFromString(const AString & a_Definition, std::shared_ptr & a_Modifiers, bool a_LogWarnings); /** Used to store block type, meta, weight and some more params */ class cRandomizedBlock { public: BLOCKTYPE m_Type; int m_Weight; /** Minimum meta to randomize */ int m_MinMeta = 0; /** Maximum meta to randomize */ int m_MaxMeta = -1; /** Maximum meta in noise range */ int m_MaxNoiseMeta = 0; /** Minimum meta in noise range */ int m_MinNoiseMeta = 0; }; typedef std::vector cRandomizedBlocks; ================================================ FILE: src/Generating/PiecePool.cpp ================================================ // PiecePool.cpp // Implements the cPiecePool class representing a pool of cPieces - "parts" of a structure, used in piece-generators // A cPiece is a single static part of a structure that can rotate around the Y axis, has connectors to other pieces and knows how to draw itself into the world. // The pool manages the pieces and provides lists of its pieces matching criteria, and provides relative weights for the random distribution of pieces. #include "Globals.h" #include "PiecePool.h" #include "VerticalStrategy.h" #include "VerticalLimit.h" #include "PieceModifier.h" //////////////////////////////////////////////////////////////////////////////// // cPiece: bool cPiece::SetVerticalStrategyFromString(const AString & a_StrategyDesc, bool a_LogWarnings) { auto strategy = CreateVerticalStrategyFromString(a_StrategyDesc, a_LogWarnings); if (strategy == nullptr) { return false; } m_VerticalStrategy = strategy; return true; } bool cPiece::SetVerticalLimitFromString(const AString & a_LimitDesc, bool a_LogWarnings) { auto limit = CreateVerticalLimitFromString(a_LimitDesc, a_LogWarnings); if (limit == nullptr) { return false; } m_VerticalLimit = limit; return true; } bool cPiece::SetPieceModifiersFromString(const AString & a_Definition, bool a_LogWarnings) { auto modifiers = std::make_shared(); if (!CreatePieceModifierFromString(a_Definition, modifiers, a_LogWarnings)) { return false; } cPieceModifiers Modifiers; for (size_t i = 0; i < modifiers->size(); i++) { Modifiers.push_back(std::move(modifiers->at(i))); } m_Modifiers = Modifiers; return true; } Vector3i cPiece::RotatePos(const Vector3i & a_Pos, int a_NumCCWRotations) const { Vector3i Size = GetSize(); switch (a_NumCCWRotations) { case 0: { // No rotation needed return a_Pos; } case 1: { // 1 CCW rotation: return Vector3i(a_Pos.z, a_Pos.y, Size.x - a_Pos.x - 1); } case 2: { // 2 rotations ( = axis flip): return Vector3i(Size.x - a_Pos.x - 1, a_Pos.y, Size.z - a_Pos.z - 1); } case 3: { // 1 CW rotation: return Vector3i(Size.z - a_Pos.z - 1, a_Pos.y, a_Pos.x); } } ASSERT(!"Unhandled rotation"); return a_Pos; } cPiece::cConnector cPiece::RotateMoveConnector(const cConnector & a_Connector, int a_NumCCWRotations, int a_MoveX, int a_MoveY, int a_MoveZ) const { cPiece::cConnector res(a_Connector); // Rotate the res connector: switch (a_NumCCWRotations) { case 0: { // No rotation needed break; } case 1: { // 1 CCW rotation: res.m_Direction = cConnector::RotateDirectionCCW(res.m_Direction); break; } case 2: { // 2 rotations ( = axis flip): res.m_Direction = cConnector::RotateDirection(res.m_Direction); break; } case 3: { // 1 CW rotation: res.m_Direction = cConnector::RotateDirectionCW(res.m_Direction); break; } } res.m_Pos = RotatePos(a_Connector.m_Pos, a_NumCCWRotations); // Move the res connector: res.m_Pos.x += a_MoveX; res.m_Pos.y += a_MoveY; res.m_Pos.z += a_MoveZ; return res; } cCuboid cPiece::RotateHitBoxToConnector( const cPiece::cConnector & a_MyConnector, const Vector3i & a_ToConnectorPos, int a_NumCCWRotations ) const { ASSERT(a_NumCCWRotations == (a_NumCCWRotations % 4)); Vector3i ConnPos = RotatePos(a_MyConnector.m_Pos, a_NumCCWRotations); ConnPos = a_ToConnectorPos - ConnPos; return RotateMoveHitBox(a_NumCCWRotations, ConnPos.x, ConnPos.y, ConnPos.z); } cCuboid cPiece::RotateMoveHitBox(int a_NumCCWRotations, int a_MoveX, int a_MoveY, int a_MoveZ) const { ASSERT(a_NumCCWRotations == (a_NumCCWRotations % 4)); cCuboid res = GetHitBox(); res.p1 = RotatePos(res.p1, a_NumCCWRotations); res.p2 = RotatePos(res.p2, a_NumCCWRotations); res.p1.Move(a_MoveX, a_MoveY, a_MoveZ); res.p2.Move(a_MoveX, a_MoveY, a_MoveZ); return res; } //////////////////////////////////////////////////////////////////////////////// // cPiece::cConnector: cPiece::cConnector::cConnector(int a_X, int a_Y, int a_Z, int a_Type, eDirection a_Direction) : m_Pos(a_X, a_Y, a_Z), m_Type(a_Type), m_Direction(a_Direction) { } cPiece::cConnector::cConnector(const Vector3i & a_Pos, int a_Type, eDirection a_Direction) : m_Pos(a_Pos), m_Type(a_Type), m_Direction(a_Direction) { } Vector3i cPiece::cConnector::AddDirection(const Vector3i & a_Pos, eDirection a_Direction) { switch (a_Direction) { case dirXM: return Vector3i(a_Pos.x - 1, a_Pos.y, a_Pos.z); case dirXP: return Vector3i(a_Pos.x + 1, a_Pos.y, a_Pos.z); case dirYM: return Vector3i(a_Pos.x, a_Pos.y - 1, a_Pos.z); case dirYP: return Vector3i(a_Pos.x, a_Pos.y + 1, a_Pos.z); case dirZM: return Vector3i(a_Pos.x, a_Pos.y, a_Pos.z - 1); case dirZP: return Vector3i(a_Pos.x, a_Pos.y, a_Pos.z + 1); case dirYM_XM_ZM: return Vector3i(a_Pos.x, a_Pos.y - 1, a_Pos.z); case dirYM_XM_ZP: return Vector3i(a_Pos.x, a_Pos.y - 1, a_Pos.z); case dirYM_XP_ZM: return Vector3i(a_Pos.x, a_Pos.y - 1, a_Pos.z); case dirYM_XP_ZP: return Vector3i(a_Pos.x, a_Pos.y - 1, a_Pos.z); case dirYP_XM_ZM: return Vector3i(a_Pos.x, a_Pos.y + 1, a_Pos.z); case dirYP_XM_ZP: return Vector3i(a_Pos.x, a_Pos.y + 1, a_Pos.z); case dirYP_XP_ZM: return Vector3i(a_Pos.x, a_Pos.y + 1, a_Pos.z); case dirYP_XP_ZP: return Vector3i(a_Pos.x, a_Pos.y + 1, a_Pos.z); } UNREACHABLE("Unsupported connector direction"); } const char * cPiece::cConnector::DirectionToString(eDirection a_Direction) { switch (a_Direction) { case dirXM: return "x-"; case dirXP: return "x+"; case dirYM: return "y-"; case dirYP: return "y+"; case dirZM: return "z-"; case dirZP: return "z+"; case dirYM_XM_ZM: return "y-x-z-"; case dirYM_XM_ZP: return "y-x-z+"; case dirYM_XP_ZM: return "y-x+z-"; case dirYM_XP_ZP: return "y-x+z+"; case dirYP_XM_ZM: return "y+x-z-"; case dirYP_XM_ZP: return "y+x-z+"; case dirYP_XP_ZM: return "y+x+z-"; case dirYP_XP_ZP: return "y+x+z+"; } UNREACHABLE("Unsupported connector direction"); } bool cPiece::cConnector::IsValidDirection(int a_Direction) { switch (a_Direction) { case dirXM: case dirXP: case dirYM: case dirYP: case dirZM: case dirZP: case dirYM_XM_ZM: case dirYM_XM_ZP: case dirYM_XP_ZM: case dirYM_XP_ZP: case dirYP_XM_ZM: case dirYP_XM_ZP: case dirYP_XP_ZM: case dirYP_XP_ZP: { return true; } } return false; } cPiece::cConnector::eDirection cPiece::cConnector::RotateDirection(eDirection a_Direction) { // 180-degree rotation: switch (a_Direction) { case dirXM: return dirXP; case dirXP: return dirXM; case dirYM: return dirYM; case dirYP: return dirYP; case dirZM: return dirZM; case dirZP: return dirZP; case dirYM_XM_ZM: return dirYM_XP_ZP; case dirYM_XM_ZP: return dirYM_XP_ZM; case dirYM_XP_ZM: return dirYM_XM_ZP; case dirYM_XP_ZP: return dirYM_XM_ZM; case dirYP_XM_ZM: return dirYP_XP_ZP; case dirYP_XM_ZP: return dirYP_XP_ZM; case dirYP_XP_ZM: return dirYP_XM_ZP; case dirYP_XP_ZP: return dirYP_XM_ZM; } UNREACHABLE("Unsupported connector direction"); } cPiece::cConnector::eDirection cPiece::cConnector::RotateDirectionCCW(eDirection a_Direction) { // 90 degrees CCW rotation: switch (a_Direction) { case dirXM: return dirZP; case dirXP: return dirZM; case dirYM: return dirYM; case dirYP: return dirYP; case dirZM: return dirXM; case dirZP: return dirXP; case dirYM_XM_ZM: return dirYM_XM_ZP; case dirYM_XM_ZP: return dirYM_XP_ZP; case dirYM_XP_ZM: return dirYM_XM_ZM; case dirYM_XP_ZP: return dirYM_XP_ZM; case dirYP_XM_ZM: return dirYP_XM_ZP; case dirYP_XM_ZP: return dirYP_XP_ZP; case dirYP_XP_ZM: return dirYP_XM_ZM; case dirYP_XP_ZP: return dirYP_XP_ZM; } UNREACHABLE("Unsupported connector direction"); } cPiece::cConnector::eDirection cPiece::cConnector::RotateDirectionCW(eDirection a_Direction) { // 90 degrees CW rotation: switch (a_Direction) { case dirXM: return dirZM; case dirXP: return dirZP; case dirYM: return dirYM; case dirYP: return dirYP; case dirZM: return dirXP; case dirZP: return dirXM; case dirYM_XM_ZM: return dirYM_XP_ZM; case dirYM_XM_ZP: return dirYM_XM_ZM; case dirYM_XP_ZM: return dirYM_XP_ZP; case dirYM_XP_ZP: return dirYM_XM_ZP; case dirYP_XM_ZM: return dirYP_XP_ZM; case dirYP_XM_ZP: return dirYP_XM_ZM; case dirYP_XP_ZM: return dirYP_XP_ZP; case dirYP_XP_ZP: return dirYP_XM_ZP; } UNREACHABLE("Unsupported connector direction"); } int cPiece::cConnector::GetNumCCWRotationsToFit(eDirection a_FixedDir, eDirection a_RotatingDir) { // Translation of direction - direction -> number of CCW rotations needed: // You need DirectionRotationTable[fixed][rot] CCW turns to connect rot to fixed (they are opposite) // -1 if not possible static const int DirectionRotationTable[14][14] = { /* YM, YP, ZM, ZP, XM, XP, YM-XM-ZM, YM-XM-ZP, YM-XP-ZM, YM-XP-ZP, YP-XM-ZM, YP-XM-ZP, YP-XP-ZM, YP-XP-ZP */ /* YM */ { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* YP */ {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* ZM */ {-1, -1, 2, 0, 1, 3, -1, -1, -1, -1, -1, -1, -1, -1}, /* ZP */ {-1, -1, 0, 2, 3, 1, -1, -1, -1, -1, -1, -1, -1, -1}, /* XM */ {-1, -1, 3, 1, 2, 0, -1, -1, -1, -1, -1, -1, -1, -1}, /* XP */ {-1, -1, 1, 3, 0, 2, -1, -1, -1, -1, -1, -1, -1, -1}, /* YM-XM-ZM */ {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 3, 1, 2}, /* YM-XM-ZP */ {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 0, 2, 3}, /* YM-XP-ZM */ {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, 2, 0, 1}, /* YM-XP-ZP */ {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2, 1, 3, 0}, /* YP-XM-ZM */ {-1, -1, -1, -1, -1, -1, 0, 3, 1, 2, -1, -1, -1, -1}, /* YP-XM-ZP */ {-1, -1, -1, -1, -1, -1, 1, 0, 2, 3, -1, -1, -1, -1}, /* YP-XP-ZM */ {-1, -1, -1, -1, -1, -1, 3, 2, 0, 1, -1, -1, -1, -1}, /* YP-XP-ZP */ {-1, -1, -1, -1, -1, -1, 2, 1, 3, 0, -1, -1, -1, -1}, }; return DirectionRotationTable[a_FixedDir][a_RotatingDir]; } bool cPiece::cConnector::StringToDirection(const AString & a_Value, eDirection & a_Out) { // First try converting as a number: int dirInt; if (StringToInteger(a_Value, dirInt)) { if (!IsValidDirection(dirInt)) { return false; } a_Out = static_cast(dirInt); return true; } // Compare to string representation: static const struct { const char * m_String; eDirection m_Value; } StringDirections[] = { {"x-", dirXM}, {"x+", dirXP}, {"y-", dirYM}, {"y+", dirYP}, {"z-", dirZM}, {"z+", dirZP}, {"y-x-z-", dirYM_XM_ZM}, {"y-x-z+", dirYM_XM_ZP}, {"y-x+z-", dirYM_XP_ZM}, {"y-x+z+", dirYM_XP_ZP}, {"y+x-z-", dirYP_XM_ZM}, {"y+x-z+", dirYP_XM_ZP}, {"y+x+z-", dirYP_XP_ZM}, {"y+x+z+", dirYP_XP_ZP}, // Alternate names, with slashes: {"y-/x-/z-", dirYM_XM_ZM}, {"y-/x-/z+", dirYM_XM_ZP}, {"y-/x+/z-", dirYM_XP_ZM}, {"y-/x+/z+", dirYM_XP_ZP}, {"y+/x-/z-", dirYP_XM_ZM}, {"y+/x-/z+", dirYP_XM_ZP}, {"y+/x+/z-", dirYP_XP_ZM}, {"y+/x+/z+", dirYP_XP_ZP}, }; auto lcValue = StrToLower(a_Value); for (size_t i = 0; i < ARRAYCOUNT(StringDirections); i++) { if (strcmp(lcValue.c_str(), StringDirections[i].m_String) == 0) { a_Out = StringDirections[i].m_Value; return true; } } // Not understood, failure: return false; } //////////////////////////////////////////////////////////////////////////////// // cPlacedPiece: cPlacedPiece::cPlacedPiece(const cPlacedPiece * a_Parent, const cPiece & a_Piece, const Vector3i & a_Coords, int a_NumCCWRotations) : m_Parent(a_Parent), m_Piece(&a_Piece), m_Coords(a_Coords), m_NumCCWRotations(a_NumCCWRotations), m_HasBeenMovedToGround(false) { m_Depth = (m_Parent == nullptr) ? 0 : (m_Parent->GetDepth() + 1); m_HitBox = a_Piece.RotateMoveHitBox(a_NumCCWRotations, a_Coords.x, a_Coords.y, a_Coords.z); m_HitBox.Sort(); } cPiece::cConnector cPlacedPiece::GetRotatedConnector(size_t a_Index) const { cPiece::cConnectors Connectors = m_Piece->GetConnectors(); ASSERT(Connectors.size() >= a_Index); return m_Piece->RotateMoveConnector(Connectors[a_Index], m_NumCCWRotations, m_Coords.x, m_Coords.y, m_Coords.z); } cPiece::cConnector cPlacedPiece::GetRotatedConnector(const cPiece::cConnector & a_Connector) const { return m_Piece->RotateMoveConnector(a_Connector, m_NumCCWRotations, m_Coords.x, m_Coords.y, m_Coords.z); } void cPlacedPiece::MoveToGroundBy(int a_OffsetY) { m_Coords.y += a_OffsetY; m_HasBeenMovedToGround = true; } ================================================ FILE: src/Generating/PiecePool.h ================================================ // PiecePool.h // Declares the cPiecePool class representing a pool of cPieces - "parts" of a structure, used in piece-generators #pragma once #include "ComposableGenerator.h" #include "../Defines.h" #include "../Cuboid.h" /** Represents a single piece. Can have multiple connectors of different types where other pieces can connect. */ class cPiece { public: // Force a virtual destructor in all descendants virtual ~cPiece() {} struct cConnector { enum eDirection { // The following values correspond to equivalent eBlockFace values: dirXM = BLOCK_FACE_XM, // Pointing towards the X- side of the prefab dirXP = BLOCK_FACE_XP, // Pointing towards the X+ side of the prefab dirYM = BLOCK_FACE_YM, // Pointing towards the Y- side of the prefab, doesn't change with rotation around the Y axis dirYP = BLOCK_FACE_YP, // Pointing towards the Y+ side of the prefab, doesn't change with rotation around the Y axis dirZM = BLOCK_FACE_ZM, // Pointing towards the Z- side of the prefab dirZP = BLOCK_FACE_ZP, // Pointing towards the Z+ side of the prefab // Special kind of the vertical connectors (changes with rotation around the Y axis) dirYM_XM_ZM = BLOCK_FACE_MAX + 1, // Pointing towards the Y- side of the prefab, conceptually at the X- Z- corner of the block dirYM_XM_ZP, // Pointing towards the Y- side of the prefab, conceptually at the X- Z+ corner of the block dirYM_XP_ZM, // Pointing towards the Y- side of the prefab, conceptually at the X+ Z- corner of the block dirYM_XP_ZP, // Pointing towards the Y- side of the prefab, conceptually at the X+ Z+ corner of the block dirYP_XM_ZM, // Pointing towards the Y+ side of the prefab, conceptually at the X- Z- corner of the block dirYP_XM_ZP, // Pointing towards the Y+ side of the prefab, conceptually at the X- Z+ corner of the block dirYP_XP_ZM, // Pointing towards the Y+ side of the prefab, conceptually at the X+ Z- corner of the block dirYP_XP_ZP, // Pointing towards the Y+ side of the prefab, conceptually at the X+ Z+ corner of the block }; /** Position relative to the piece */ Vector3i m_Pos; /** Type of the connector. Any arbitrary number; the generator connects only connectors of opposite (negative) types. */ int m_Type; /** Direction in which the connector is facing. Will be matched by the opposite direction for the connecting connector. */ eDirection m_Direction; cConnector(int a_X, int a_Y, int a_Z, int a_Type, eDirection a_Direction); cConnector(const Vector3i & a_Pos, int a_Type, eDirection a_Direction); /** Returns the position of the block that has the specified direction from the specified position. Similar to ::AddFaceDirection() */ static Vector3i AddDirection(const Vector3i & a_Pos, eDirection a_Direction); /** Returns the string representation of the direction. For debugging purposes. */ static const char * DirectionToString(eDirection a_Direction); /** Returns true if the specified number corresponds to a valid eDirection. */ static bool IsValidDirection(int a_Direction); /** Returns the direction corresponding to the given direction rotated 180 degrees around the Y axis. */ static eDirection RotateDirection(eDirection a_Direction); /** Returns the direction corresponding to the given direction rotated 90 degrees CCW around the Y axis. */ static eDirection RotateDirectionCCW(eDirection a_Direction); /** Returns the direction corresponding to the given direction rotated 90 degrees CW around the Y axis. */ static eDirection RotateDirectionCW(eDirection a_Direction); /** Returns the number of CCW rotations that a_RotatingDir requires in order to be the counter-direction of a_FixedDir. Ie. if you have a connector with a_FixedDir and you're rotating a piece that has a connector with a_RotatingDir, how many CCW rotations it needs to make the connectors compatible. Returns -1 if it is impossible to fit the two directions. */ static int GetNumCCWRotationsToFit(eDirection a_FixedDir, eDirection a_RotatingDir); /** Converts the string representation of a direction into the eDirection enum value. Returns true if successful, false on failure. Accepts both numbers and string representations such as "x+" or "Y+X-Z+". */ static bool StringToDirection(const AString & a_Value, eDirection & a_Out); }; typedef std::vector cConnectors; /** Base class (interface) for strategies for placing the starting pieces vertically. Descendants can override the GetVerticalPlacement() method to provide custom placement decisions. */ class cVerticalStrategy { public: // Force a virtual destructor in descendants virtual ~cVerticalStrategy() {} /** Returns the Y coord of the piece */ virtual int GetVerticalPlacement(int a_BlockX, int a_BlockZ) = 0; /** Initializes the strategy's parameters from the string representation. a_Params is the string containing only the parameters (substring after the first pipe character in the strategy description string). If a_LogWarnings is true, logs any problems to the console. Returns true if successful, false if the string parsing failed. Used when loading the strategy from a file. */ virtual bool InitializeFromString(const AString & a_Params, bool a_LogWarnings) = 0; /** Called when the piece pool is assigned to a generator, so that the strategies may bind to the underlying subgenerators. */ virtual void AssignGens(int a_Seed, cBiomeGen & a_BiomeGen, cTerrainHeightGen & a_TerrainHeightGen, int a_SeaLevel) {} }; typedef std::shared_ptr cVerticalStrategyPtr; /** Base class (interface) for the vertical limit of piece placement. Each placed piece can have a limit, represented by this class, that gets queried for validity of the placement. */ class cVerticalLimit { public: virtual ~cVerticalLimit() {} /** Called to inquire whether the specified piece can be placed at the specified height. a_BlockX, a_BlockZ is the column of the connector that is being queried. a_Height is the requested height of the piece's lowest block. */ virtual bool CanBeAtHeight(int a_BlockX, int a_BlockZ, int a_Height) = 0; /** Initializes the limit's parameters from the string representation. a_Params is the string containing only the parameters (substring after the first pipe character in the limit description string). Returns true if successful, false if the string parsing failed. If a_LogWarnings is true, any error while parsing the string is output to the server console. Used when loading the limit from a file. */ virtual bool InitializeFromString(const AString & a_Params, bool a_LogWarnings) = 0; /** Called when the piece pool is assigned to a generator, so that the limits may bind to the underlying subgenerators. */ virtual void AssignGens(int a_Seed, cBiomeGen & a_BiomeGen, cTerrainHeightGen & a_TerrainHeightGen, int a_SeaLevel) {} }; typedef std::shared_ptr cVerticalLimitPtr; /** Base class (interface) for piece modifiers. */ class cPieceModifier { public: // Force a virtual destructor in descendants virtual ~cPieceModifier() {} /** Initializes the modifier's parameters from the string representation. a_Params is the string containing only the parameters If a_LogWarnings is true, logs any problems to the console. Returns true if successful, false if the string parsing failed. Used when loading the modifier from a file. */ virtual bool InitializeFromString(const AString & a_Params, bool a_LogWarnings) = 0; /** Called prior to writing piece to a chunk, so that modifiers can modify blocks in the blockarea */ virtual void Modify(cBlockArea & a_Image, const Vector3i a_PiecePos, const int a_PieceNumRotations) = 0; /** Called when the piece pool is assigned to a generator, so that the modifiers can access world seed. */ virtual void AssignSeed(int a_Seed) {} }; typedef std::shared_ptr cPieceModifierPtr; typedef std::vector cPieceModifiers; /** The strategy used for vertical placement of this piece when it is used as a starting piece. */ cVerticalStrategyPtr m_VerticalStrategy; /** The checker that verifies each placement's vertical position. */ cVerticalLimitPtr m_VerticalLimit; /** The modifiers which are modifying piece's blocks. */ cPieceModifiers m_Modifiers; /** Returns all of the available connectors that the piece has. Each connector has a (relative) position in the piece, and a type associated with it. */ virtual cConnectors GetConnectors(void) const = 0; /** Returns the dimensions of this piece. The dimensions cover the entire piece, there is no block that the piece generates outside of this size. */ virtual Vector3i GetSize(void) const = 0; /** Returns the "hitbox" of this piece. A hitbox is what is compared and must not intersect other pieces' hitboxes when generating. */ virtual cCuboid GetHitBox(void) const = 0; /** Returns true if the piece can be rotated CCW the specific number of 90-degree turns. */ virtual bool CanRotateCCW(int a_NumRotations) const = 0; /** Returns the height, based on m_VerticalStrategy, for this piece when used as the starting piece. If there's no strategy assigned to this piece, returns -1. */ int GetStartingPieceHeight(int a_BlockX, int a_BlockZ) { if (m_VerticalStrategy != nullptr) { return m_VerticalStrategy->GetVerticalPlacement(a_BlockX, a_BlockZ); } return -1; } void SetVerticalStrategy(cVerticalStrategyPtr a_VerticalStrategy) { m_VerticalStrategy = std::move(a_VerticalStrategy); } cVerticalStrategyPtr GetVerticalStrategy(void) const { return m_VerticalStrategy; } cVerticalLimitPtr GetVerticalLimit(void) const { return m_VerticalLimit; } cPieceModifiers GetModifiers(void) const { return m_Modifiers; } /** Sets the vertical strategy based on the description in the string. If a_LogWarnings is true, logs the parsing problems into the server console. Returns true if successful, false if strategy parsing failed (no strategy assigned). */ bool SetVerticalStrategyFromString(const AString & a_StrategyDesc, bool a_LogWarnings); /** Sets the vertical limit based on the description string. Returns true if successful, false if limit parsing failed (no limit assigned). If a_LogWarnings is true, any problem is reported into the server console. */ bool SetVerticalLimitFromString(const AString & a_LimitDesc, bool a_LogWarnings); /** Sets the modifiers with their params in the string. If a_LogWarnings is true, logs the parsing problems into the server console. Returns true if successful, false if strategy parsing failed (no strategy assigned). */ bool SetPieceModifiersFromString(const AString & a_Definition, bool a_LogWarnings); /** Returns a copy of the a_Pos after rotating the piece the specified number of CCW rotations. */ Vector3i RotatePos(const Vector3i & a_Pos, int a_NumCCWRotations) const; /** Returns a copy of the connector that is rotated and then moved by the specified amounts. */ cConnector RotateMoveConnector(const cConnector & a_Connector, int a_NumCCWRotations, int a_MoveX, int a_MoveY, int a_MoveZ) const; /** Returns the hitbox after the specified number of rotations and moved so that a_MyConnector is placed at a_ToConnectorPos. */ cCuboid RotateHitBoxToConnector(const cConnector & a_MyConnector, const Vector3i & a_ToConnectorPos, int a_NumCCWRotations) const; /** Returns the hitbox after the specified number of CCW rotations and moved by the specified amounts. */ cCuboid RotateMoveHitBox(int a_NumCCWRotations, int a_MoveX, int a_MoveY, int a_MoveZ) const; }; typedef std::vector cPieces; // fwd: class cPlacedPiece; /** This class is an interface that stores pieces for a generator. Provides lists of pieces based on criteria (IsStarting, HasConnector). Provides per-piece weights for random distribution of individual pieces. */ class cPiecePool { public: // Force a virtual destructor in all descendants: virtual ~cPiecePool() {} /** Returns a list of pieces that contain the specified connector type. The cPiece pointers returned are managed by the pool and the caller doesn't free them. */ virtual cPieces GetPiecesWithConnector(int a_ConnectorType) = 0; /** Returns the pieces that should be used as the starting point. Multiple starting points are supported, one of the returned piece will be chosen. */ virtual cPieces GetStartingPieces(void) = 0; /** Returns the relative weight with which the a_NewPiece is to be selected for placing under a_PlacedPiece through a_ExistingConnector. a_ExistingConnector is the original connector, before any movement or rotation is applied to it. This allows the pool to tweak the piece's chances, based on the previous pieces in the tree and the connector used. The higher the number returned, the higher the chance the piece will be chosen. 0 means the piece will never be chosen. */ virtual int GetPieceWeight( const cPlacedPiece & a_PlacedPiece, const cPiece::cConnector & a_ExistingConnector, const cPiece & a_NewPiece ) { return 1; } /** Returns the relative weight with which the a_NewPiece is to be selected for placing as the first piece. This allows the pool to tweak the piece's chances. The higher the number returned, the higher the chance the piece will be chosen. 0 means the piece will not be chosen. If all pieces return 0, a random piece is chosen, with all equal chances. */ virtual int GetStartingPieceWeight(const cPiece & a_NewPiece) { return 1; } /** Called after a piece is placed, to notify the pool that it has been used. The pool may adjust the pieces it will return the next time. */ virtual void PiecePlaced(const cPiece & a_Piece) = 0; /** Called when the pool has finished the current structure and should reset any piece-counters it has for a new structure. */ virtual void Reset(void) = 0; }; /** Represents a single piece that has been placed to specific coords in the world. */ class cPlacedPiece { public: cPlacedPiece(const cPlacedPiece * a_Parent, const cPiece & a_Piece, const Vector3i & a_Coords, int a_NumCCWRotations); const cPlacedPiece * GetParent (void) const { return m_Parent; } const cPiece & GetPiece (void) const { return *m_Piece; } const Vector3i & GetCoords (void) const { return m_Coords; } int GetNumCCWRotations (void) const { return m_NumCCWRotations; } const cCuboid & GetHitBox (void) const { return m_HitBox; } int GetDepth (void) const { return m_Depth; } bool HasBeenMovedToGround(void) const { return m_HasBeenMovedToGround; } /** Returns the coords as a modifiable object. */ Vector3i & GetCoords(void) { return m_Coords; } /** Returns the connector at the specified index, rotated in the actual placement. Undefined behavior if a_Index is out of range. */ cPiece::cConnector GetRotatedConnector(size_t a_Index) const; /** Returns a copy of the specified connector, modified to account for the translation and rotation for this placement. */ cPiece::cConnector GetRotatedConnector(const cPiece::cConnector & a_Connector) const; /** Moves the placed piece Y-wise by the specified offset. Sets m_HasBeenMovedToGround to true, too. Used eg. by village houses. */ void MoveToGroundBy(int a_OffsetY); protected: const cPlacedPiece * m_Parent; const cPiece * m_Piece; Vector3i m_Coords; int m_NumCCWRotations; cCuboid m_HitBox; // Hitbox of the placed piece, in world coords int m_Depth; // Depth in the generated piece tree /** Set to true once the piece has been moved Y-wise. Used eg. by village houses. */ bool m_HasBeenMovedToGround; }; typedef std::unique_ptr cPlacedPiecePtr; typedef std::vector cPlacedPieces; ================================================ FILE: src/Generating/PieceStructuresGen.cpp ================================================ // PieceStructuresGen.cpp // Declares the cPieceStructuresGen class representing the PieceStructures finisher generator #include "Globals.h" #include "PieceStructuresGen.h" #include "PrefabStructure.h" #include "PieceGeneratorBFSTree.h" #include "../IniFile.h" class cPieceStructuresGen::cGen: public cGridStructGen { using Super = cGridStructGen; public: cGen(int a_Seed, cBiomeGen & a_BiomeGen, cTerrainHeightGen & a_HeightGen, int a_SeaLevel, const AString & a_Name): Super(a_Seed), m_BiomeGen(a_BiomeGen), m_HeightGen(a_HeightGen), m_SeaLevel(a_SeaLevel), m_Name(a_Name), m_MaxDepth(5) { } /** Loads the piecepool from a file. Returns true on success, logs warning and returns false on failure. */ bool LoadFromFile(const AString & a_FileName) { // Load the piecepool from the file, log any warnings: if (!m_PiecePool.LoadFromFile(a_FileName, true)) { return false; } if (NoCaseCompare(m_PiecePool.GetIntendedUse(), "PieceStructures") != 0) { LOGWARNING("PieceStructures generator: File %s is intended for use in \"%s\", rather than piece structures. Loading the file, but the generator may behave unexpectedly.", a_FileName.c_str(), m_PiecePool.GetIntendedUse().c_str() ); } m_PiecePool.AssignGens(m_Seed, m_BiomeGen, m_HeightGen, m_SeaLevel); // Apply generator params from the piecepool (in the metadata) into the generator: auto & GeneratorParams = m_PiecePool.GetAllMetadata(); SetGeneratorParams(GeneratorParams); m_MaxDepth = GetStringMapInteger(GeneratorParams, "MaxDepth", m_MaxDepth); return true; } // cGridStructGen overrides: virtual cStructurePtr CreateStructure(int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ) override { cPlacedPieces OutPieces; cPieceGeneratorBFSTree PieceTree(m_PiecePool, m_Seed); PieceTree.PlacePieces(a_OriginX, a_OriginZ, m_MaxDepth, OutPieces); return std::make_shared(a_GridX, a_GridZ, a_OriginX, a_OriginZ, std::move(OutPieces), m_HeightGen); } protected: /** The type used for storing a connection from one piece to another, while building the piece tree. */ struct cConnection { cPiece * m_Piece; // The piece being connected cPiece::cConnector m_Connector; // The piece's connector being used (relative non-rotated coords) int m_NumCCWRotations; // Number of rotations necessary to match the two connectors int m_Weight; // Relative chance that this connection will be chosen cConnection(cPiece & a_Piece, cPiece::cConnector & a_Connector, int a_NumCCWRotations, int a_Weight); }; typedef std::vector cConnections; /** The type used for storing a pool of connectors that will be attempted to expand by another piece. */ struct cFreeConnector { cPlacedPiece * m_Piece; cPiece::cConnector m_Connector; cFreeConnector(cPlacedPiece * a_Piece, const cPiece::cConnector & a_Connector); }; typedef std::vector cFreeConnectors; /** The underlying biome generator that defines whether the structure is created or not */ cBiomeGen & m_BiomeGen; /** The underlying height generator, used to position the prefabs crossing chunk borders if they are set to FitGround. */ cTerrainHeightGen & m_HeightGen; /** The world's sea level, if available. Used for some cVerticalStrategy descendants. */ int m_SeaLevel; /** The name that is used for reporting. */ AString m_Name; /** All available prefabs. */ cPrefabPiecePool m_PiecePool; /** Maximum depth of the generated piece tree. */ int m_MaxDepth; }; //////////////////////////////////////////////////////////////////////////////// // cPieceStructuresGen: cPieceStructuresGen::cPieceStructuresGen(int a_Seed): m_Seed(a_Seed) { } bool cPieceStructuresGen::Initialize(const AString & a_Prefabs, int a_SeaLevel, cBiomeGen & a_BiomeGen, cTerrainHeightGen & a_HeightGen) { // Load each piecepool: auto Structures = StringSplitAndTrim(a_Prefabs, "|"); for (const auto & Structure : Structures) { auto FileName = fmt::format(FMT_STRING("Prefabs{0}PieceStructures{0}{1}.cubeset"), cFile::PathSeparator(), Structure); if (!cFile::IsFile(FileName)) { FileName.append(".gz"); if (!cFile::IsFile(FileName)) { LOGWARNING("Cannot load PieceStructures cubeset file %s", FileName); continue; } } auto Gen = std::make_shared(m_Seed, a_BiomeGen, a_HeightGen, a_SeaLevel, Structure); if (Gen->LoadFromFile(FileName)) { m_Gens.push_back(Gen); } } // Report a warning if no generators available: if (m_Gens.empty()) { LOGWARNING("The PieceStructures generator was asked to generate \"%s\", but none of the prefabs are valid.", a_Prefabs); return false; } return true; } void cPieceStructuresGen::GenFinish(cChunkDesc & a_Chunk) { for (auto & Gen : m_Gens) { Gen->GenFinish(a_Chunk); } } ================================================ FILE: src/Generating/PieceStructuresGen.h ================================================ // PieceStructuresGen.h // Declares the cPieceStructuresGen class representing the PieceStructures finisher generator /* This generator loads various pieces from "piecepool" files, and each such piecepool is then used in a separate cPieceGenerator instance. */ #pragma once #include "ComposableGenerator.h" #include "PrefabPiecePool.h" class cPieceStructuresGen: public cFinishGen { using Super = cFinishGen; public: cPieceStructuresGen(int a_Seed); /** Initializes the generator based on the specified prefab sets. a_Prefabs contains the list of prefab sets that should be activated, "|"-separated. All problems are logged to the console and the generator skips over them. Returns true if at least one prefab set is valid (the generator should be kept). */ bool Initialize(const AString & a_Prefabs, int a_SeaLevel, cBiomeGen & a_BiomeGen, cTerrainHeightGen & a_HeightGen); // cFinishGen override: virtual void GenFinish(cChunkDesc & a_ChunkDesc) override; protected: /** The generator doing the work for a single prefab set. Forward-declared so that its implementation changes don't affect the header. */ class cGen; typedef std::shared_ptr cGenPtr; typedef std::vector cGenPtrs; /** The individual structure generators, one per piecepool. */ cGenPtrs m_Gens; /** The seed for the random number generator */ int m_Seed; }; ================================================ FILE: src/Generating/Prefab.cpp ================================================ // Prefab.cpp /* Implements the cPrefab class, representing a cPiece descendant for the cPieceGenerator that uses a prefabricate in a cBlockArea for drawing itself. */ #include "Globals.h" #include "Prefab.h" #include "../WorldStorage/SchematicFileSerializer.h" #include "ChunkDesc.h" #include "../BlockInfo.h" cPrefab::cPrefab(const cPrefab::sDef & a_Def) : m_Size(a_Def.m_SizeX, a_Def.m_SizeY, a_Def.m_SizeZ), m_HitBox( {a_Def.m_HitboxMinX, a_Def.m_HitboxMinY, a_Def.m_HitboxMinZ}, {a_Def.m_HitboxMaxX, a_Def.m_HitboxMaxY, a_Def.m_HitboxMaxZ} ), m_AllowedRotations(a_Def.m_AllowedRotations), m_MergeStrategy(a_Def.m_MergeStrategy), m_ExtendFloorStrategy(a_Def.m_ExtendFloorStrategy), m_DefaultWeight(a_Def.m_DefaultWeight), m_AddWeightIfSame(a_Def.m_AddWeightIfSame), m_MoveToGround(a_Def.m_MoveToGround) { m_BlockArea[0].Create(m_Size); CharMap cm; ParseCharMap(cm, a_Def.m_CharMap); ParseBlockImage(cm, a_Def.m_Image); ParseConnectors(a_Def.m_Connectors); ParseDepthWeight(a_Def.m_DepthWeight); AddRotatedBlockAreas(); } cPrefab::cPrefab(const cBlockArea & a_Image, int a_AllowedRotations) : m_Size(a_Image.GetSize()), m_AllowedRotations(a_AllowedRotations), m_MergeStrategy(cBlockArea::msOverwrite), m_ExtendFloorStrategy(efsNone), m_DefaultWeight(1), m_AddWeightIfSame(0), m_MoveToGround(false) { m_HitBox.p1.Set(0, 0, 0); m_HitBox.p2.Set(m_Size.x - 1, m_Size.y - 1, m_Size.z - 1); m_BlockArea[0].CopyFrom(a_Image); AddRotatedBlockAreas(); } cPrefab::cPrefab(const cBlockArea & a_Image) : m_Size(a_Image.GetSize()), m_AllowedRotations(0), m_MergeStrategy(cBlockArea::msOverwrite), m_ExtendFloorStrategy(efsNone), m_DefaultWeight(1), m_AddWeightIfSame(0), m_MoveToGround(false) { m_HitBox.p1.Set(0, 0, 0); m_HitBox.p2.Set(m_Size.x - 1, m_Size.y - 1, m_Size.z - 1); m_BlockArea[0].CopyFrom(a_Image); } cPrefab::cPrefab(const AString & a_BlockDefinitions, const AString & a_BlockData, int a_SizeX, int a_SizeY, int a_SizeZ) : m_Size(a_SizeX, a_SizeY, a_SizeZ), m_AllowedRotations(0), m_MergeStrategy(cBlockArea::msOverwrite), m_ExtendFloorStrategy(efsNone), m_DefaultWeight(1), m_AddWeightIfSame(0), m_MoveToGround(false) { m_HitBox.p1.Set(0, 0, 0); m_HitBox.p2.Set(m_Size.x - 1, m_Size.y - 1, m_Size.z - 1); m_BlockArea[0].Create(m_Size); CharMap cm; ParseCharMap(cm, a_BlockDefinitions.c_str()); ParseBlockImage(cm, a_BlockData.c_str()); } void cPrefab::AddRotatedBlockAreas(void) { // 1 CCW rotation: if ((m_AllowedRotations & 0x01) != 0) { m_BlockArea[1].CopyFrom(m_BlockArea[0]); m_BlockArea[1].RotateCCW(); } // 2 rotations are the same as mirroring twice; mirroring is faster because it has no reallocations if ((m_AllowedRotations & 0x02) != 0) { m_BlockArea[2].CopyFrom(m_BlockArea[0]); m_BlockArea[2].MirrorXY(); m_BlockArea[2].MirrorYZ(); } // 3 CCW rotations = 1 CW rotation: if ((m_AllowedRotations & 0x04) != 0) { m_BlockArea[3].CopyFrom(m_BlockArea[0]); m_BlockArea[3].RotateCW(); } } void cPrefab::Draw(cChunkDesc & a_Dest, const cPlacedPiece * a_Placement) const { Draw(a_Dest, a_Placement->GetCoords(), a_Placement->GetNumCCWRotations()); } void cPrefab::Draw(cChunkDesc & a_Dest, const Vector3i & a_Placement, int a_NumRotations) const { // Draw the basic image: Vector3i Placement(a_Placement); int ChunkStartX = a_Dest.GetChunkX() * cChunkDef::Width; int ChunkStartZ = a_Dest.GetChunkZ() * cChunkDef::Width; Placement.Move(-ChunkStartX, 0, -ChunkStartZ); const cBlockArea & Image = m_BlockArea[a_NumRotations]; // If the placement is outside this chunk, bail out: if ( (Placement.x > cChunkDef::Width) || (Placement.x + Image.GetSizeX() < 0) || (Placement.z > cChunkDef::Width) || (Placement.z + Image.GetSizeZ() < 0) ) { return; } if (m_Modifiers.size() == 0) { // Write the image: a_Dest.WriteBlockArea(Image, Placement.x, Placement.y, Placement.z, m_MergeStrategy); } else { cBlockArea RandomizedImage; Image.CopyTo(RandomizedImage); for (size_t i = 0; i < m_Modifiers.size(); i++) { m_Modifiers[i]->Modify(RandomizedImage, a_Placement, a_NumRotations); } // Write the modified image: a_Dest.WriteBlockArea(RandomizedImage, Placement.x, Placement.y, Placement.z, m_MergeStrategy); } // If requested, draw the floor (from the bottom of the prefab down to the nearest non-air) switch (m_ExtendFloorStrategy) { case efsNone: break; // Nothing needed case efsRepeatBottomTillNonAir: { int MaxX = Image.GetSizeX(); int MaxZ = Image.GetSizeZ(); for (int z = 0; z < MaxZ; z++) { int RelZ = Placement.z + z; if ((RelZ < 0) || (RelZ >= cChunkDef::Width)) { // Z coord outside the chunk continue; } for (int x = 0; x < MaxX; x++) { int RelX = Placement.x + x; if ((RelX < 0) || (RelX >= cChunkDef::Width)) { // X coord outside the chunk continue; } BLOCKTYPE BlockType; NIBBLETYPE BlockMeta; Image.GetRelBlockTypeMeta(x, 0, z, BlockType, BlockMeta); if ((BlockType == E_BLOCK_AIR) || (BlockType == E_BLOCK_SPONGE)) { // Do not expand air nor sponge blocks continue; } for (int y = Placement.y - 1; y >= 0; y--) { BLOCKTYPE ExistingBlock = a_Dest.GetBlockType(RelX, y, RelZ); if (ExistingBlock != E_BLOCK_AIR) { // End the expansion for this column, reached the end break; } a_Dest.SetBlockTypeMeta(RelX, y, RelZ, BlockType, BlockMeta); } // for y } // for x } // for z break; } // efsRepeatBottomTillNonAir case efsRepeatBottomTillSolid: { int MaxX = Image.GetSizeX(); int MaxZ = Image.GetSizeZ(); for (int z = 0; z < MaxZ; z++) { int RelZ = Placement.z + z; if ((RelZ < 0) || (RelZ >= cChunkDef::Width)) { // Z coord outside the chunk continue; } for (int x = 0; x < MaxX; x++) { int RelX = Placement.x + x; if ((RelX < 0) || (RelX >= cChunkDef::Width)) { // X coord outside the chunk continue; } BLOCKTYPE BlockType; NIBBLETYPE BlockMeta; Image.GetRelBlockTypeMeta(x, 0, z, BlockType, BlockMeta); if ((BlockType == E_BLOCK_AIR) || (BlockType == E_BLOCK_SPONGE)) { // Do not expand air nor sponge blocks continue; } for (int y = Placement.y - 1; y >= 0; y--) { BLOCKTYPE ExistingBlock = a_Dest.GetBlockType(RelX, y, RelZ); if (cBlockInfo::IsSolid(ExistingBlock)) { // End the expansion for this column, reached the end break; } a_Dest.SetBlockTypeMeta(RelX, y, RelZ, BlockType, BlockMeta); } // for y } // for x } // for z break; } // efsRepeatBottomTillSolid } } bool cPrefab::HasConnectorType(int a_ConnectorType) const { for (cConnectors::const_iterator itr = m_Connectors.begin(), end = m_Connectors.end(); itr != end; ++itr) { if (itr->m_Type == a_ConnectorType) { return true; } } // for itr - m_Connectors[] return false; } int cPrefab::GetPieceWeight(const cPlacedPiece & a_PlacedPiece, const cPiece::cConnector & a_ExistingConnector) const { // Use the default or per-depth weight: cDepthWeight::const_iterator itr = m_DepthWeight.find(a_PlacedPiece.GetDepth() + 1); int res = (itr == m_DepthWeight.end()) ? m_DefaultWeight : itr->second; // If the piece is the same as the parent, apply the m_AddWeightIfSame modifier: const cPiece * ParentPiece = &a_PlacedPiece.GetPiece(); const cPiece * ThisPiece = this; if (ThisPiece == ParentPiece) { res += m_AddWeightIfSame; } return res; } void cPrefab::SetDefaultWeight(int a_DefaultWeight) { m_DefaultWeight = a_DefaultWeight; } void cPrefab::AddConnector(int a_RelX, int a_RelY, int a_RelZ, cPiece::cConnector::eDirection a_Direction, int a_Type) { m_Connectors.emplace_back(a_RelX, a_RelY, a_RelZ, a_Type, a_Direction); } void cPrefab::SetAllowedRotations(int a_AllowedRotations) { m_AllowedRotations = a_AllowedRotations; AddRotatedBlockAreas(); } void cPrefab::ParseCharMap(CharMap & a_CharMapOut, const char * a_CharMapDef) { ASSERT(a_CharMapDef != nullptr); // Initialize the charmap to all-invalid values: for (size_t i = 0; i < ARRAYCOUNT(a_CharMapOut); i++) { a_CharMapOut[i].m_BlockType = 0; a_CharMapOut[i].m_BlockMeta = 16; // Mark unassigned entries with a meta that is impossible otherwise } // Process the lines in the definition: AStringVector Lines = StringSplitAndTrim(a_CharMapDef, "\n"); for (AStringVector::const_iterator itr = Lines.begin(), end = Lines.end(); itr != end; ++itr) { AStringVector CharDef = StringSplitAndTrim(*itr, ":"); size_t NumElements = CharDef.size(); if ((NumElements < 2) || CharDef[0].empty() || CharDef[1].empty()) { LOGWARNING("Bad prefab CharMap definition line: \"%s\", skipping.", itr->c_str()); continue; } unsigned char Src = static_cast(CharDef[0][0]); ASSERT(a_CharMapOut[Src].m_BlockMeta == 16); // This letter has not been assigned yet? a_CharMapOut[Src].m_BlockType = static_cast(atoi(CharDef[1].c_str())); NIBBLETYPE BlockMeta = 0; if ((NumElements >= 3) && !CharDef[2].empty()) { BlockMeta = static_cast(atoi(CharDef[2].c_str())); ASSERT((BlockMeta <= 15)); } a_CharMapOut[Src].m_BlockMeta = BlockMeta; } // for itr - Lines[] } void cPrefab::ParseBlockImage(const CharMap & a_CharMap, const char * a_BlockImage) { // Map each letter in the a_BlockImage (from the in-source definition) to real blocktype / blockmeta: for (int y = 0; y < m_Size.y; y++) { for (int z = 0; z < m_Size.z; z++) { const unsigned char * BlockImage = reinterpret_cast(a_BlockImage + y * m_Size.x * m_Size.z + z * m_Size.x); for (int x = 0; x < m_Size.x; x++) { const sBlockTypeDef & MappedValue = a_CharMap[BlockImage[x]]; ASSERT(MappedValue.m_BlockMeta != 16); // Using a letter not defined in the CharMap? m_BlockArea[0].SetRelBlockTypeMeta(x, y, z, MappedValue.m_BlockType, MappedValue.m_BlockMeta); } } } } void cPrefab::ParseConnectors(const char * a_ConnectorsDef) { ASSERT(a_ConnectorsDef != nullptr); AStringVector Lines = StringSplitAndTrim(a_ConnectorsDef, "\n"); for (AStringVector::const_iterator itr = Lines.begin(), end = Lines.end(); itr != end; ++itr) { if (itr->empty()) { continue; } // Split into components: "Type: X, Y, Z: Direction": AStringVector Defs = StringSplitAndTrim(*itr, ":"); if (Defs.size() != 3) { LOGWARNING("Bad prefab Connector definition line: \"%s\", skipping.", itr->c_str()); continue; } AStringVector Coords = StringSplitAndTrim(Defs[1], ","); if (Coords.size() != 3) { LOGWARNING("Bad prefab Connector coords definition: \"%s\", skipping.", Defs[1].c_str()); continue; } // Check that the Direction is valid: cPiece::cConnector::eDirection Direction; if (!cPiece::cConnector::StringToDirection(Defs[2], Direction)) { LOGWARNING("Bad prefab Connector direction: \"%s\", skipping.", Defs[2].c_str()); continue; } // Add the connector: m_Connectors.push_back(cPiece::cConnector( atoi(Coords[0].c_str()), atoi(Coords[1].c_str()), atoi(Coords[2].c_str()), // Connector pos atoi(Defs[0].c_str()), // Connector type Direction )); } // for itr - Lines[] } void cPrefab::ParseDepthWeight(const char * a_DepthWeightDef) { // The member needn't be defined at all, if so, skip: if (a_DepthWeightDef == nullptr) { return; } // Split into individual records: "Record | Record | Record" AStringVector Defs = StringSplitAndTrim(a_DepthWeightDef, "|"); // Add each record's contents: for (AStringVector::const_iterator itr = Defs.begin(), end = Defs.end(); itr != end; ++itr) { // Split into components: "Depth : Weight" AStringVector Components = StringSplitAndTrim(*itr, ":"); if (Components.size() != 2) { LOGWARNING("Bad prefab DepthWeight record: \"%s\", skipping.", itr->c_str()); continue; } // Parse depth: int Depth = atoi(Components[0].c_str()); if ((Depth == 0) && (Components[0] != "0")) { LOGWARNING("Bad prefab DepthWeight record, cannot parse depth \"%s\", skipping.", Components[0].c_str()); continue; } // Parse weight: int Weight = atoi(Components[1].c_str()); if ((Weight == 0) && (Components[1] != "0")) { LOGWARNING("Bad prefab DepthWeight record, cannot parse weight \"%s\", skipping.", Components[1].c_str()); continue; } // Save to map: ASSERT(m_DepthWeight.find(Depth) == m_DepthWeight.end()); // Not a duplicate m_DepthWeight[Depth] = Weight; } // for itr - Defs[] } cPiece::cConnectors cPrefab::GetConnectors(void) const { return m_Connectors; } Vector3i cPrefab::GetSize(void) const { return m_Size; } cCuboid cPrefab::GetHitBox(void) const { return m_HitBox; } bool cPrefab::CanRotateCCW(int a_NumRotations) const { // Either zero rotations // Or the proper bit in m_AllowedRotations is set return (a_NumRotations == 0) || ((m_AllowedRotations & (1 << ((a_NumRotations + 3) % 4))) != 0); } ================================================ FILE: src/Generating/Prefab.h ================================================ // Prefab.h /* Declares the cPrefab class, representing a cPiece descendant for the cPieceGenerator that uses a prefabricate in a cBlockArea for drawing itself. The class can be constructed from data that is stored directly in the executable, in a sPrefabDef structure declared in this file as well; the Gallery server exports areas in this format. */ #pragma once #include "PiecePool.h" #include "../BlockArea.h" // fwd: class cChunkDesc; class cPrefab : public cPiece { public: /** How to handle the space between the prefab bottom and the terrain top. */ enum eExtendFloorStrategy { efsNone, ///< No processing, the prefab is left "floating in the air" efsRepeatBottomTillNonAir, ///< Repeat the bottom-most block down until the first non-air block efsRepeatBottomTillSolid, ///< Repeat the bottom-most block down until the first solid block; non-solids are overwritten }; struct sDef { int m_SizeX; int m_SizeY; int m_SizeZ; /** The hitbox used for collision-checking between prefabs. Relative to the bounds. */ int m_HitboxMinX, m_HitboxMinY, m_HitboxMinZ; int m_HitboxMaxX, m_HitboxMaxY, m_HitboxMaxZ; /** The mapping between characters in m_Image and the blocktype / blockmeta. Format: "Char: BlockType: BlockMeta \n Char: BlockType : BlockMeta \n ..." */ const char * m_CharMap; /** The actual image to be used for the prefab. Organized YZX (Y changes the least often). Each character represents a single block, the type is mapped through m_CharMap. */ const char * m_Image; /** List of connectors. Format: "Type: X, Y, Z : Direction \n Type : X, Y, Z : Direction \n ...". Type is an arbitrary number, Direction is the BlockFace constant value (0 .. 5). */ const char * m_Connectors; /** Bitmask specifying the allowed rotations. N rotations CCW are allowed if bit N is set. */ int m_AllowedRotations; /** The merge strategy to use while drawing the prefab. */ cBlockArea::eMergeStrategy m_MergeStrategy; /** How the prefab should handle not being on top of the ground. This is used for houses to be "on the ground", as well as nether fortresses not to float. */ eExtendFloorStrategy m_ExtendFloorStrategy; /** Chance of this piece being used, if no other modifier is active. */ int m_DefaultWeight; /** Chances of this piece being used, per depth of the generated piece tree. The starting piece has a depth of 0, the pieces connected to it are depth 1, etc. The specified depth stands for the depth of the new piece (not the existing already-placed piece), so valid depths start at 1. Format: "Depth : Weight | Depth : Weight | Depth : Weight ..." Depths that are not specified will use the m_DefaultWeight value. */ const char * m_DepthWeight; /** The weight to add to this piece's base per-depth chance if the previous piece is the same. Can be positive or negative. This is used e. g. to make nether bridges prefer spanning multiple segments or to penalize turrets next to each other. */ int m_AddWeightIfSame; /** If true, the piece will be moved Y-wise so that its first connector is sitting on the terrain. This is used e. g. for village houses. */ bool m_MoveToGround; }; /** Creates a prefab from the provided definition. */ cPrefab(const sDef & a_Def); /** Creates a prefab based on the given BlockArea and allowed rotations. */ cPrefab(const cBlockArea & a_Image, int a_AllowedRotations); /** Creates a prefab based on the given BlockArea. Allowed rotations can be added later on using SetAllowedRotations(). */ cPrefab(const cBlockArea & a_Image); /** Creates a prefab based on the specified block data, using the char-to-block map in a_BlockDefinitions. Allowed rotations can be added later on using SetAllowedRotations(). */ cPrefab(const AString & a_BlockDefinitions, const AString & a_BlockData, int a_SizeX, int a_SizeY, int a_SizeZ); /** Draws the prefab into the specified chunk, according to the placement stored in the PlacedPiece. */ void Draw(cChunkDesc & a_Dest, const cPlacedPiece * a_Placement) const; /** Draws the prefab into the specified chunks, according to the specified placement and rotations. */ void Draw(cChunkDesc & a_Dest, const Vector3i & a_Placement, int a_NumRotations) const; /** Returns true if the prefab has any connector of the specified type. */ bool HasConnectorType(int a_ConnectorType) const; /** Returns the weight (chance) of this prefab generating as the next piece after the specified placed piece. PiecePool implementations can use this for their GetPieceWeight() implementations. */ int GetPieceWeight(const cPlacedPiece & a_PlacedPiece, const cPiece::cConnector & a_ExistingConnector) const; /** Sets the (unmodified) DefaultWeight property for this piece. */ void SetDefaultWeight(int a_DefaultWeight); /** Returns the unmodified DefaultWeight property for the piece. */ int GetDefaultWeight(void) const { return m_DefaultWeight; } /** Sets the AddWeightIfSame member, that is used to modify the weight when the previous piece is the same prefab */ void SetAddWeightIfSame(int a_AddWeightIfSame) { m_AddWeightIfSame = a_AddWeightIfSame; } /** Adds the specified connector to the list of connectors this piece supports. */ void AddConnector(int a_RelX, int a_RelY, int a_RelZ, cPiece::cConnector::eDirection a_Direction, int a_Type); /** Returns whether the prefab should be moved Y-wise to ground before drawing, rather than staying at the coords governed by the connectors. */ bool ShouldMoveToGround(void) const { return m_MoveToGround; } /** Sets the m_AllowedRotations bitmask and fills the m_BlockArea[] with rotated versions of m_BlockArea[0]. */ void SetAllowedRotations(int a_AllowedRotations); /** Parses the per-depth weight into m_DepthWeight member. */ void ParseDepthWeight(const char * a_DepthWeightDef); /** Sets the merge strategy to be used when drawing the piece. */ void SetMergeStrategy(cBlockArea::eMergeStrategy a_MergeStrategy) { m_MergeStrategy = a_MergeStrategy; } /** Sets the flag whether the prefab should be moved to ground level before being drawn. */ void SetMoveToGround(bool a_MoveToGround) { m_MoveToGround = a_MoveToGround; } /** Sets the strategy to use between the bottom of the prefab and the terrain top. */ void SetExtendFloorStrategy(eExtendFloorStrategy a_Strategy) { m_ExtendFloorStrategy = a_Strategy; } /** Sets the internal hitbox to the specified value. */ void SetHitBox(const cCuboid & a_HitBox) { m_HitBox = a_HitBox; } protected: /** Packs complete definition of a single block, for per-letter assignment. */ struct sBlockTypeDef { BLOCKTYPE m_BlockType; NIBBLETYPE m_BlockMeta; }; /** Maps letters in the sDef::m_Image onto a sBlockTypeDef block type definition. */ typedef sBlockTypeDef CharMap[256]; /** Maps generator tree depth to weight. */ typedef std::map cDepthWeight; /** The cBlockArea that contains the block definitions for the prefab. The index identifies the number of CCW rotations applied (0 = no rotation, 1 = 1 CCW rotation, ...). */ cBlockArea m_BlockArea[4]; /** The size of the prefab */ Vector3i m_Size; /** The hitbox used for collision-checking between prefabs. */ cCuboid m_HitBox; /** The connectors through which the piece connects to other pieces */ cConnectors m_Connectors; /** Bitmask, bit N set -> N rotations CCW supported */ int m_AllowedRotations; /** The merge strategy to use when drawing the prefab into a block area */ cBlockArea::eMergeStrategy m_MergeStrategy; /** How the prefab should handle not being on top of the ground. This is used for houses to be "on the ground", as well as nether fortresses not to float. */ eExtendFloorStrategy m_ExtendFloorStrategy; /** Chance of this piece being used, if no other modifier is active. */ int m_DefaultWeight; /** Chances of this piece being used, per depth of the generated piece tree. The starting piece has a depth of 0, the pieces connected to it are depth 1, etc. The specified depth stands for the depth of the new piece (not the existing already-placed piece), so valid depths start at 1. Depths that are not specified will use the m_DefaultWeight value. */ cDepthWeight m_DepthWeight; /** The weight to add to this piece's base per-depth chance if the previous piece is the same. Can be positive or negative. This is used e. g. to make nether bridges prefer spanning multiple segments or to penalize turrets next to each other. */ int m_AddWeightIfSame; /** If true, the piece will be moved Y-wise so that its first connector is sitting on the terrain. This is used e. g. for village houses. */ bool m_MoveToGround; // cPiece overrides: virtual cConnectors GetConnectors(void) const override; virtual Vector3i GetSize(void) const override; virtual cCuboid GetHitBox(void) const override; virtual bool CanRotateCCW(int a_NumRotations) const override; /** Based on the m_AllowedRotations, adds rotated cBlockAreas to the m_BlockArea array. To be called only from this class's constructor! */ void AddRotatedBlockAreas(void); /** Parses the CharMap in the definition into a CharMap binary data used for translating the definition into BlockArea. */ void ParseCharMap(CharMap & a_CharMapOut, const char * a_CharMapDef); /** Parses the Image in the definition into m_BlockArea[0]'s block types and metas, using the specified CharMap. */ void ParseBlockImage(const CharMap & a_CharMap, const char * a_BlockImage); /** Parses the connectors definition text into m_Connectors member. */ void ParseConnectors(const char * a_ConnectorsDef); }; ================================================ FILE: src/Generating/PrefabPiecePool.cpp ================================================ // PrefabPiecePool.cpp // Implements the cPrefabPiecePool class that represents a cPiecePool descendant that uses cPrefab instances as the pieces #include "Globals.h" #include "PrefabPiecePool.h" #include "VerticalStrategy.h" #include "../Bindings/LuaState.h" #include "../WorldStorage/SchematicFileSerializer.h" #include "../StringCompression.h" /** Returns the map of string => eMergeStrategy used when translating cubeset file merge strategies. */ static std::map & GetMergeStrategyMap(void) { static std::map msmap; if (msmap.empty()) { // This is the first use, initialize the map: msmap["msOverwrite"] = cBlockArea::msOverwrite; msmap["msFillAir"] = cBlockArea::msFillAir; msmap["msImprint"] = cBlockArea::msImprint; msmap["msLake"] = cBlockArea::msLake; msmap["msSpongePrint"] = cBlockArea::msSpongePrint; msmap["msDifference"] = cBlockArea::msDifference; msmap["msSimpleCompare"] = cBlockArea::msSimpleCompare; msmap["msMask"] = cBlockArea::msMask; } return msmap; } //////////////////////////////////////////////////////////////////////////////// // cPrefabPiecePool: cPrefabPiecePool::cPrefabPiecePool(void) { } cPrefabPiecePool::cPrefabPiecePool( const cPrefab::sDef * a_PieceDefs, size_t a_NumPieceDefs, const cPrefab::sDef * a_StartingPieceDefs, size_t a_NumStartingPieceDefs, int a_DefaultStartingPieceHeight ) { AddPieceDefs(a_PieceDefs, a_NumPieceDefs); if (a_StartingPieceDefs != nullptr) { AddStartingPieceDefs(a_StartingPieceDefs, a_NumStartingPieceDefs, a_DefaultStartingPieceHeight); } } cPrefabPiecePool::~cPrefabPiecePool() { Clear(); } void cPrefabPiecePool::Clear(void) { m_PiecesByConnector.clear(); for (cPieces::iterator itr = m_AllPieces.begin(), end = m_AllPieces.end(); itr != end; ++itr) { delete *itr; } m_AllPieces.clear(); for (cPieces::iterator itr = m_StartingPieces.begin(), end = m_StartingPieces.end(); itr != end; ++itr) { delete *itr; } m_StartingPieces.clear(); } void cPrefabPiecePool::AddPieceDefs(const cPrefab::sDef * a_PieceDefs, size_t a_NumPieceDefs) { ASSERT(a_PieceDefs != nullptr); for (size_t i = 0; i < a_NumPieceDefs; i++) { cPrefab * Prefab = new cPrefab(a_PieceDefs[i]); m_AllPieces.push_back(Prefab); AddToPerConnectorMap(Prefab); } } void cPrefabPiecePool::AddStartingPieceDefs( const cPrefab::sDef * a_StartingPieceDefs, size_t a_NumStartingPieceDefs, int a_DefaultPieceHeight ) { ASSERT(a_StartingPieceDefs != nullptr); auto verticalStrategy = CreateVerticalStrategyFromString(fmt::format(FMT_STRING("Fixed|{}"), a_DefaultPieceHeight), false); for (size_t i = 0; i < a_NumStartingPieceDefs; i++) { cPrefab * Prefab = new cPrefab(a_StartingPieceDefs[i]); if (a_DefaultPieceHeight >= 0) { Prefab->SetVerticalStrategy(verticalStrategy); } m_StartingPieces.push_back(Prefab); } } bool cPrefabPiecePool::LoadFromFile(const AString & a_FileName, bool a_LogWarnings) { // Read the file into a string buffer, load from string: auto contents = cFile::ReadWholeFile(a_FileName); if (contents.empty()) { CONDWARNING(a_LogWarnings, "Cannot read data from file %s", a_FileName.c_str()); return false; } return LoadFromString(contents, a_FileName, a_LogWarnings); } bool cPrefabPiecePool::LoadFromString(const AString & a_Contents, const AString & a_FileName, bool a_LogWarnings) { // If the contents start with GZip signature, ungzip and retry: if (a_Contents.substr(0, 3) == "\x1f\x8b\x08") { try { const auto Extracted = Compression::Extractor().ExtractGZip( { reinterpret_cast(a_Contents.data()), a_Contents.size() }); // Here we do an extra std::string conversion, hardly efficient, but... // Better would be refactor into LoadFromByteView for the GZip decompression path, and getting cFile to support std::byte. // ...so it'll do for now. return LoadFromString(std::string(Extracted.GetStringView()), a_FileName, a_LogWarnings); } catch (const std::exception & Oops) { CONDWARNING(a_LogWarnings, "Failed to decompress Gzip data in file %s. %s", a_FileName.c_str(), Oops.what()); return false; } } // Search the first 8 KiB of the file for the format auto-detection string: const auto Header = a_Contents.substr(0, 8 KiB); if (Header.find("CubesetFormatVersion =") != AString::npos) { return LoadFromCubeset(a_Contents, a_FileName, a_LogWarnings); } CONDWARNING(a_LogWarnings, "Cannot load prefabs from file %s, unknown file format", a_FileName.c_str()); return false; } bool cPrefabPiecePool::LoadFromCubeset(const AString & a_Contents, const AString & a_FileName, bool a_LogWarnings) { // Load the file in the Lua interpreter: cLuaState Lua(fmt::format(FMT_STRING("LoadablePiecePool {}"), a_FileName)); Lua.Create(); cLuaState::cLock lock(Lua); if (!Lua.LoadString(a_Contents, a_FileName, a_LogWarnings)) { // Reason for failure has already been logged in LoadFile() return false; } // Check the version: int Version = 0; if (!Lua.GetNamedGlobal("Cubeset.Metadata.CubesetFormatVersion", Version)) { CONDWARNING(a_LogWarnings, "Cannot load cubeset %s, it doesn't contain version information.", a_FileName); return false; } // Load the data, using the correct version loader: if (Version == 1) { return LoadFromCubesetVer1(a_FileName, Lua, a_LogWarnings); } // Unknown version: CONDWARNING(a_LogWarnings, "Cannot load cubeset %s, version (%d) not supported.", a_FileName, Version); return false; } void cPrefabPiecePool::AddToPerConnectorMap(cPrefab * a_Prefab) { cPiece::cConnectors Connectors = (static_cast(a_Prefab))->GetConnectors(); for (cPiece::cConnectors::const_iterator itr = Connectors.begin(), end = Connectors.end(); itr != end; ++itr) { m_PiecesByConnector[itr->m_Type].push_back(a_Prefab); } } bool cPrefabPiecePool::LoadFromCubesetVer1(const AString & a_FileName, cLuaState & a_LuaState, bool a_LogWarnings) { // Load the metadata and apply the known ones: ReadPoolMetadataCubesetVer1(a_FileName, a_LuaState, a_LogWarnings); ApplyBaseMetadataCubesetVer1(a_FileName, a_LogWarnings); // Push the Cubeset.Pieces global value on the stack: auto pieces = a_LuaState.WalkToNamedGlobal("Cubeset.Pieces"); if (!pieces.IsValid() || !lua_istable(a_LuaState, -1)) { CONDWARNING(a_LogWarnings, "The cubeset file %s doesn't contain any pieces", a_FileName.c_str()); return false; } // Iterate over all items in the Cubeset.Pieces value: int idx = 1; bool res = true; while (true) { lua_pushinteger(a_LuaState, idx); // stk: [Pieces] [idx] lua_gettable(a_LuaState, -2); // stk: [Pieces] [PieceItem] if (!lua_istable(a_LuaState, -1)) { // The PieceItem is not present, we've iterated over all items lua_pop(a_LuaState, 1); // stk: [Pieces] break; } if (!LoadCubesetPieceVer1(a_FileName, a_LuaState, idx, a_LogWarnings)) { res = false; } lua_pop(a_LuaState, 1); // stk: [Pieces] idx += 1; } return res; } bool cPrefabPiecePool::LoadCubesetPieceVer1(const AString & a_FileName, cLuaState & a_LuaState, int a_PieceIndex, bool a_LogWarnings) { ASSERT(lua_istable(a_LuaState, -1)); // The piece name is optional, but useful for debugging messages: AString PieceName; if (!a_LuaState.GetNamedValue("OriginData.ExportName", PieceName)) { PieceName = fmt::format(FMT_STRING("Piece #{}"), a_PieceIndex); } // Read the hitbox dimensions: cCuboid Hitbox; if ( !a_LuaState.GetNamedValue("Hitbox.MinX", Hitbox.p1.x) || !a_LuaState.GetNamedValue("Hitbox.MinY", Hitbox.p1.y) || !a_LuaState.GetNamedValue("Hitbox.MinZ", Hitbox.p1.z) || !a_LuaState.GetNamedValue("Hitbox.MaxX", Hitbox.p2.x) || !a_LuaState.GetNamedValue("Hitbox.MaxY", Hitbox.p2.y) || !a_LuaState.GetNamedValue("Hitbox.MaxZ", Hitbox.p2.z) ) { CONDWARNING(a_LogWarnings, "Cannot load piece %s from file %s, it's missing hitbox information", PieceName, a_FileName); return false; } // Load the prefab data: auto prefab = LoadPrefabFromCubesetVer1(a_FileName, a_LuaState, PieceName, a_LogWarnings); if (prefab == nullptr) { return false; } prefab->SetHitBox(Hitbox); // Read the connectors if (!ReadConnectorsCubesetVer1(a_FileName, a_LuaState, PieceName, prefab.get(), a_LogWarnings)) { return false; } // Read the allowed rotations. It is an optional metadata value, default to 0: int AllowedRotations = 0; a_LuaState.GetNamedValue("Metadata.AllowedRotations", AllowedRotations); prefab->SetAllowedRotations(AllowedRotations); // Read the relevant metadata for the piece: if (!ReadPieceMetadataCubesetVer1(a_FileName, a_LuaState, PieceName, prefab.get(), a_LogWarnings)) { return false; } // If the piece is a starting piece, check that it has a vertical strategy: int IsStartingPiece = 0; a_LuaState.GetNamedValue("Metadata.IsStarting", IsStartingPiece); if (IsStartingPiece != 0) { if (prefab->GetVerticalStrategy() == nullptr) { CONDWARNING(a_LogWarnings, "Starting prefab %s in file %s doesn't have its VerticalStrategy set. Setting to Fixed|150.", PieceName, a_FileName ); VERIFY(prefab->SetVerticalStrategyFromString("Fixed|150", false)); } } // Add the prefab into the list of pieces: if (IsStartingPiece != 0) { m_StartingPieces.push_back(prefab.release()); } else { auto p = prefab.release(); m_AllPieces.push_back(p); AddToPerConnectorMap(p); } return true; } std::unique_ptr cPrefabPiecePool::LoadPrefabFromCubesetVer1( const AString & a_FileName, cLuaState & a_LuaState, const AString & a_PieceName, bool a_LogWarnings ) { // First try loading a referenced schematic file, if any: AString SchematicFileName; if (a_LuaState.GetNamedValue("SchematicFileName", SchematicFileName)) { auto PathEnd = a_FileName.find_last_of("/\\"); // Find the last path separator if (PathEnd != AString::npos) { SchematicFileName = a_FileName.substr(0, PathEnd) + SchematicFileName; } cBlockArea area; try { cSchematicFileSerializer::LoadFromSchematicFile(area, SchematicFileName); } catch (const std::exception & Oops) { CONDWARNING(a_LogWarnings, "Cannot load schematic file \"%s\" for piece %s in cubeset %s. %s", SchematicFileName.c_str(), a_PieceName.c_str(), a_FileName.c_str(), Oops.what() ); return nullptr; } return std::make_unique(area); } // if (SchematicFileName) // There's no referenced schematic file, load from BlockDefinitions / BlockData. // Get references to the data and the table.concat function: cLuaState::cRef TableConcat, BlockDefinitions, BlockData; if ( !a_LuaState.GetNamedGlobal("table.concat", TableConcat) || !a_LuaState.GetNamedValue("BlockDefinitions", BlockDefinitions) || !a_LuaState.GetNamedValue("BlockData", BlockData) ) { CONDWARNING(a_LogWarnings, "Cannot parse block data for piece %s in cubeset %s", a_PieceName.c_str(), a_FileName.c_str()); return nullptr; } // Call table.concat() on the BlockDefinitions: AString BlockDefStr; if (!a_LuaState.Call(TableConcat, BlockDefinitions, "\n", cLuaState::Return, BlockDefStr)) { CONDWARNING(a_LogWarnings, "Cannot concat block definitions for piece %s in cubeset %s", a_PieceName.c_str(), a_FileName.c_str()); return nullptr; } // Call table.concat() on the BlockData: AString BlockDataStr; if (!a_LuaState.Call(TableConcat, BlockData, "", cLuaState::Return, BlockDataStr)) { CONDWARNING(a_LogWarnings, "Cannot concat block data for piece %s in cubeset %s", a_PieceName.c_str(), a_FileName.c_str()); return nullptr; } // Read the size: int SizeX = 0, SizeY = 0, SizeZ = 0; if ( !a_LuaState.GetNamedValue("Size.x", SizeX) || !a_LuaState.GetNamedValue("Size.y", SizeY) || !a_LuaState.GetNamedValue("Size.z", SizeZ) ) { CONDWARNING(a_LogWarnings, "Cannot load piece %s from file %s, its size information is missing", a_PieceName.c_str(), a_FileName.c_str()); return nullptr; } // Check that the size matches the data length: if (static_cast(SizeX * SizeY * SizeZ) != BlockDataStr.size()) { CONDWARNING(a_LogWarnings, "Cannot create piece %s from file %s, its size (%d) doesn't match the blockdata length (%u)", a_PieceName.c_str(), a_FileName.c_str(), SizeX * SizeY * SizeZ, static_cast(BlockDataStr.size()) ); return nullptr; } return std::make_unique(BlockDefStr, BlockDataStr, SizeX, SizeY, SizeZ); } bool cPrefabPiecePool::ReadConnectorsCubesetVer1( const AString & a_FileName, cLuaState & a_LuaState, const AString & a_PieceName, cPrefab * a_Prefab, bool a_LogWarnings ) { // Get the Connectors subtable: auto conns = a_LuaState.WalkToValue("Connectors"); if (!conns.IsValid()) { CONDWARNING(a_LogWarnings, "Cannot load piece %s from file %s, it has no connectors definition.", a_PieceName.c_str(), a_FileName.c_str()); return false; } // Iterate over all items in the Connectors table: int idx = 1; bool res = true; while (true) { lua_pushinteger(a_LuaState, idx); // stk: [Connectors] [idx] lua_gettable(a_LuaState, -2); // stk: [Connectors] [conn] if (!lua_istable(a_LuaState, -1)) { // The connector is not present, we've iterated over all items lua_pop(a_LuaState, 1); // stk: [Connectors] break; } int Type = 0, RelX = 0, RelY = 0, RelZ = 0; AString DirectionStr; cPiece::cConnector::eDirection Direction = cPiece::cConnector::dirYM; if ( !a_LuaState.GetNamedValue("Type", Type) || !a_LuaState.GetNamedValue("RelX", RelX) || !a_LuaState.GetNamedValue("RelY", RelY) || !a_LuaState.GetNamedValue("RelZ", RelZ) || !a_LuaState.GetNamedValue("Direction", DirectionStr) || !cPiece::cConnector::StringToDirection(DirectionStr, Direction) ) { if (a_LogWarnings) { FLOGWARNING("Piece {0} in file {1} has a malformed Connector at index {2} ({3}, type {4}, direction {5}). Skipping the connector.", a_PieceName, a_FileName, idx, Vector3i{RelX, RelY, RelZ}, Type, DirectionStr ); } res = false; lua_pop(a_LuaState, 1); // stk: [Connectors] idx += 1; continue; } a_Prefab->AddConnector(RelX, RelY, RelZ, Direction, Type); lua_pop(a_LuaState, 1); // stk: [Connectors] idx += 1; } return res; } bool cPrefabPiecePool::ReadPieceMetadataCubesetVer1( const AString & a_FileName, cLuaState & a_LuaState, const AString & a_PieceName, cPrefab * a_Prefab, bool a_LogWarnings ) { // Push the Metadata table on top of the Lua stack: auto md = a_LuaState.WalkToValue("Metadata"); if (!md.IsValid()) { return false; } // Get the values: int AddWeightIfSame = 0, DefaultWeight = 100, MoveToGround = 0; AString DepthWeight, MergeStrategy, VerticalLimit, VerticalStrategy; a_LuaState.GetNamedValue("AddWeightIfSame", AddWeightIfSame); a_LuaState.GetNamedValue("DefaultWeight", DefaultWeight); a_LuaState.GetNamedValue("DepthWeight", DepthWeight); a_LuaState.GetNamedValue("MergeStrategy", MergeStrategy); a_LuaState.GetNamedValue("MoveToGround", MoveToGround); a_LuaState.GetNamedValue("VerticalLimit", VerticalLimit); a_LuaState.GetNamedValue("VerticalStrategy", VerticalStrategy); // Apply the values: a_Prefab->SetAddWeightIfSame(AddWeightIfSame); a_Prefab->SetDefaultWeight(DefaultWeight); a_Prefab->ParseDepthWeight(DepthWeight.c_str()); auto msmap = GetMergeStrategyMap(); auto strategy = msmap.find(MergeStrategy); if (strategy == msmap.end()) { CONDWARNING(a_LogWarnings, "Unknown merge strategy (\"%s\") specified for piece %s in file %s. Using msSpongePrint instead.", MergeStrategy.c_str(), a_PieceName.c_str(), a_FileName.c_str() ); a_Prefab->SetMergeStrategy(cBlockArea::msSpongePrint); } else { a_Prefab->SetMergeStrategy(strategy->second); } a_Prefab->SetMoveToGround(MoveToGround != 0); AString ExpandFloorStrategyStr; if (!a_LuaState.GetNamedValue("ExpandFloorStrategy", ExpandFloorStrategyStr)) { // Check the older variant for ExpandFloorStrategy, ShouldExpandFloor: int ShouldExpandFloor; if (a_LuaState.GetNamedValue("ShouldExpandFloor", ShouldExpandFloor)) { LOG("Piece \"%s\" in file \"%s\" is using the old \"ShouldExpandFloor\" attribute. Use the new \"ExpandFloorStrategy\" attribute instead for more options.", a_PieceName.c_str(), a_FileName.c_str() ); a_Prefab->SetExtendFloorStrategy((ShouldExpandFloor != 0) ? cPrefab::efsRepeatBottomTillNonAir : cPrefab::efsNone); } } else { auto lcExpandFloorStrategyStr = StrToLower(ExpandFloorStrategyStr); if (lcExpandFloorStrategyStr == "repeatbottomtillnonair") { a_Prefab->SetExtendFloorStrategy(cPrefab::efsRepeatBottomTillNonAir); } else if (lcExpandFloorStrategyStr == "repeatbottomtillsolid") { a_Prefab->SetExtendFloorStrategy(cPrefab::efsRepeatBottomTillSolid); } else { if (lcExpandFloorStrategyStr != "none") { LOGWARNING("Piece \"%s\" in file \"%s\" is using an unknown \"ExpandFloorStrategy\" attribute value: \"%s\"", a_PieceName.c_str(), a_FileName.c_str(), ExpandFloorStrategyStr.c_str() ); } a_Prefab->SetExtendFloorStrategy(cPrefab::efsNone); } } if (!VerticalLimit.empty()) { if (!a_Prefab->SetVerticalLimitFromString(VerticalLimit, a_LogWarnings)) { CONDWARNING(a_LogWarnings, "Unknown VerticalLimit (\"%s\") specified for piece %s in file %s. Using no limit instead.", VerticalLimit.c_str(), a_PieceName.c_str(), a_FileName.c_str() ); } } a_Prefab->SetVerticalStrategyFromString(VerticalStrategy, a_LogWarnings); AString ModifiersStr; if (a_LuaState.GetNamedValue("Modifiers", ModifiersStr)) { a_Prefab->SetPieceModifiersFromString(ModifiersStr, a_LogWarnings); } return true; } void cPrefabPiecePool::ApplyBaseMetadataCubesetVer1( const AString & a_FileName, bool a_LogWarnings ) { // Set the metadata values to defaults: m_MinDensity = 100; m_MaxDensity = 100; m_VillageRoadBlockType = E_BLOCK_GRAVEL; m_VillageRoadBlockMeta = 0; m_VillageWaterRoadBlockType = E_BLOCK_PLANKS; m_VillageWaterRoadBlockMeta = 0; // Read the metadata values: m_IntendedUse = GetMetadata("IntendedUse"); GetStringMapInteger(m_Metadata, "MaxDensity", m_MaxDensity); GetStringMapInteger(m_Metadata, "MinDensity", m_MinDensity); GetStringMapInteger(m_Metadata, "VillageRoadBlockType", m_VillageRoadBlockType); GetStringMapInteger(m_Metadata, "VillageRoadBlockMeta", m_VillageRoadBlockMeta); GetStringMapInteger(m_Metadata, "VillageWaterRoadBlockType", m_VillageWaterRoadBlockType); GetStringMapInteger(m_Metadata, "VillageWaterRoadBlockMeta", m_VillageWaterRoadBlockMeta); // Read the allowed biomes: AString allowedBiomes = GetMetadata("AllowedBiomes"); if (allowedBiomes.empty()) { // All biomes are allowed: for (int b = biFirstBiome; b <= biMaxBiome; b++) { m_AllowedBiomes.insert(static_cast(b)); } for (int b = biFirstVariantBiome; b <= biMaxVariantBiome; b++) { m_AllowedBiomes.insert(static_cast(b)); } } else { auto biomes = StringSplitAndTrim(allowedBiomes, ","); for (const auto & biome: biomes) { EMCSBiome b = StringToBiome(biome); if (b == biInvalidBiome) { CONDWARNING(a_LogWarnings, "Invalid biome (\"%s\") specified in AllowedBiomes in cubeset file %s. Skipping the biome.", biome.c_str(), a_FileName.c_str() ); continue; } m_AllowedBiomes.insert(b); } } } bool cPrefabPiecePool::ReadPoolMetadataCubesetVer1( const AString & a_FileName, cLuaState & a_LuaState, bool a_LogWarnings ) { // Push the Cubeset.Metadata table on top of the Lua stack: auto gp = a_LuaState.WalkToNamedGlobal("Cubeset.Metadata"); if (!gp.IsValid()) { return true; } // Iterate over elements in the table, put them into the m_GeneratorParams map: lua_pushnil(a_LuaState); // Table is at index -2, starting key (nil) at index -1 while (lua_next(a_LuaState, -2) != 0) { // Table at index -3, key at index -2, value at index -1 AString key, val; a_LuaState.GetStackValues(-2, key, val); m_Metadata[key] = val; lua_pop(a_LuaState, 1); // Table at index -2, key at index -1 } return true; } AString cPrefabPiecePool::GetMetadata(const AString & a_ParamName) const { auto itr = m_Metadata.find(a_ParamName); if (itr == m_Metadata.end()) { return AString(); } return itr->second; } void cPrefabPiecePool::AssignGens(int a_Seed, cBiomeGen & a_BiomeGen, cTerrainHeightGen & a_HeightGen, int a_SeaLevel) { // Assign the generator linkage to all starting pieces' VerticalStrategies: for (auto & piece: m_StartingPieces) { auto verticalStrategy = piece->GetVerticalStrategy(); if (verticalStrategy != nullptr) { verticalStrategy->AssignGens(a_Seed, a_BiomeGen, a_HeightGen, a_SeaLevel); } } // for piece - m_StartingPieces[] // Assign the generator linkage to all pieces' VerticalLimits: for (auto & piece: m_AllPieces) { auto verticalLimit = piece->GetVerticalLimit(); if (verticalLimit != nullptr) { verticalLimit->AssignGens(a_Seed, a_BiomeGen, a_HeightGen, a_SeaLevel); } auto modifiers = piece->GetModifiers(); if (modifiers.size() > 0) { for (size_t i = 0; i < modifiers.size(); i++) { modifiers[i]->AssignSeed(a_Seed); } } } // for piece - m_AllPieces[] } cPieces cPrefabPiecePool::GetPiecesWithConnector(int a_ConnectorType) { return m_PiecesByConnector[a_ConnectorType]; } cPieces cPrefabPiecePool::GetStartingPieces(void) { if (m_StartingPieces.empty()) { return m_AllPieces; } else { return m_StartingPieces; } } int cPrefabPiecePool::GetPieceWeight(const cPlacedPiece & a_PlacedPiece, const cPiece::cConnector & a_ExistingConnector, const cPiece & a_NewPiece) { return (static_cast(a_NewPiece)).GetPieceWeight(a_PlacedPiece, a_ExistingConnector); } int cPrefabPiecePool::GetStartingPieceWeight(const cPiece & a_NewPiece) { return (static_cast(a_NewPiece)).GetDefaultWeight(); } void cPrefabPiecePool::PiecePlaced(const cPiece & a_Piece) { // Do nothing UNUSED(a_Piece); } void cPrefabPiecePool::Reset(void) { // Do nothing } ================================================ FILE: src/Generating/PrefabPiecePool.h ================================================ // PrefabPiecePool.h // Declares the cPrefabPiecePool class that represents a cPiecePool descendant that uses cPrefab instances as the pieces #pragma once #include "PiecePool.h" #include "Prefab.h" // fwd: class cLuaState; class cPrefabPiecePool : public cPiecePool { public: /** Creates an empty instance. Prefabs can be added by calling AddPieceDefs() and AddStartingPieceDefs(). */ cPrefabPiecePool(void); /** Creates a piece pool with prefabs from the specified definitions. If both a_PieceDefs and a_StartingPieceDefs are given, only the a_StartingPieceDefs are used as starting pieces for the pool, and they do not participate in the generation any further. If only a_PieceDefs is given, any such piece can be chosen as a starting piece, and all the pieces are used for generating. More pieces can be added to the instance afterwards by calling AddPieceDefs() and AddStartingPieceDefs(). If a_DefaultStartingPieceHeight is non-negative, it is applied to each starting piece as its fixed height (for the GetStartingPieceHeight() call). */ cPrefabPiecePool( const cPrefab::sDef * a_PieceDefs, size_t a_NumPieceDefs, const cPrefab::sDef * a_StartingPieceDefs, size_t a_NumStartingPieceDefs, int a_DefaultStartingPieceHeight = -1 ); /** Destroys the pool, freeing all pieces. */ virtual ~cPrefabPiecePool() override; /** Removes and frees all pieces from this pool. */ void Clear(void); /** Adds pieces from the specified definitions into m_AllPieces. Also adds the pieces into the m_PiecesByConnector map. May be called multiple times with different PieceDefs, will add all such pieces. */ void AddPieceDefs(const cPrefab::sDef * a_PieceDefs, size_t a_NumPieceDefs); /** Adds pieces from the specified definitions into m_StartingPieces. Doesn't add them to the m_PiecesByConnector map. May be called multiple times with different PieceDefs, will add all such pieces. If a_DefaultPieceHeight is non-negative, it is applied to each piece as its fixed height (for the GetStartingPieceHeight() call). */ void AddStartingPieceDefs( const cPrefab::sDef * a_StartingPieceDefs, size_t a_NumStartingPieceDefs, int a_DefaultPieceHeight = -1 ); /** Loads the pieces from the specified file. Returns true if successful, false on error. If a_LogWarnings is true, logs a warning to console when loading fails. */ bool LoadFromFile(const AString & a_FileName, bool a_LogWarnings); /** Loads the pieces from the specified string. Returns true if successful, false on error. a_FileName is used only logging. If a_LogWarnings is true, logs a warning to console when loading fails. */ bool LoadFromString(const AString & a_Contents, const AString & a_FileName, bool a_LogWarnings); /** Loads the pieces from the specified string containing Cubeset file data. Returns true if successful, false on error. a_FileName is used only logging. If a_LogWarnings is true, logs a warning to console when loading fails. */ bool LoadFromCubeset(const AString & a_Contents, const AString & a_FileName, bool a_LogWarnings); /** Returns the number of regular (non-starting) pieces. */ size_t GetAllPiecesCount(void) const { return m_AllPieces.size(); } /** Returns the number of starting pieces. */ size_t GetStartingPiecesCount(void) const { return m_StartingPieces.size(); } // Metadata accessors: const AString & GetIntendedUse(void) const { return m_IntendedUse; } int GetMinDensity(void) const { return m_MinDensity; } int GetMaxDensity(void) const { return m_MaxDensity; } BLOCKTYPE GetVillageRoadBlockType (void) const { return m_VillageRoadBlockType; } NIBBLETYPE GetVillageRoadBlockMeta (void) const { return m_VillageRoadBlockMeta; } BLOCKTYPE GetVillageWaterRoadBlockType(void) const { return m_VillageWaterRoadBlockType; } NIBBLETYPE GetVillageWaterRoadBlockMeta(void) const { return m_VillageWaterRoadBlockMeta; } /** Returns true if a_Biome is among the accepted biomes in the m_AcceptedBiomes metadata member. */ bool IsBiomeAllowed(EMCSBiome a_Biome) const { return (m_AllowedBiomes.find(a_Biome) != m_AllowedBiomes.end()); } /** Returns the specified value from the metadata map. Returns an empty string if no such value had been read. */ AString GetMetadata(const AString & a_ParamName) const; const AStringMap & GetAllMetadata(void) const { return m_Metadata; } /** Called when the piece pool is assigned to a generator, so that the individual starting pieces' vertical strategies may bind to the underlying subgenerators. */ void AssignGens(int a_Seed, cBiomeGen & a_BiomeGen, cTerrainHeightGen & a_HeightGen, int a_SeaLevel); // cPiecePool overrides: virtual cPieces GetPiecesWithConnector(int a_ConnectorType) override; virtual cPieces GetStartingPieces(void) override; virtual int GetPieceWeight(const cPlacedPiece & a_PlacedPiece, const cPiece::cConnector & a_ExistingConnector, const cPiece & a_NewPiece) override; virtual int GetStartingPieceWeight(const cPiece & a_NewPiece) override; virtual void PiecePlaced(const cPiece & a_Piece) override; virtual void Reset(void) override; protected: /** The type used to map a connector type to the list of pieces with that connector */ typedef std::map cPiecesMap; /** All the pieces that are allowed for building. This is the list that's used for memory allocation and deallocation for the pieces. */ cPieces m_AllPieces; /** The pieces that are used as starting pieces. This list is not shared and the pieces need deallocation. */ cPieces m_StartingPieces; /** The map that has all pieces by their connector types The pieces are copies out of m_AllPieces and shouldn't be ever delete-d. */ cPiecesMap m_PiecesByConnector; /** The intended use of this piece pool, as specified by the pool's metadata. */ AString m_IntendedUse; /** The minimum density, as read from the metadata. */ int m_MinDensity; /** The maximum density, as read from the metadata. */ int m_MaxDensity; /** The block type to use for the village roads. */ BLOCKTYPE m_VillageRoadBlockType; /** The block meta to use for the village roads. */ NIBBLETYPE m_VillageRoadBlockMeta; /** The block type used for the village roads if the road is on water. */ BLOCKTYPE m_VillageWaterRoadBlockType; /** The block meta used for the village roads if the road is on water. */ NIBBLETYPE m_VillageWaterRoadBlockMeta; /** A set of allowed biomes for the pool. The pool will only be used within the specified biomes. */ std::unordered_set m_AllowedBiomes; /** A dictionary of pool-wide metadata, as read from the cubeset file. */ AStringMap m_Metadata; /** Adds the prefab to the m_PiecesByConnector map for all its connectors. */ void AddToPerConnectorMap(cPrefab * a_Prefab); /** Loads the pieces from the cubeset file parsed into the specified Lua state. Returns true on success, false on error. a_FileName is used only logging. If a_LogWarnings is true, logs a warning to console when loading fails. */ bool LoadFromCubesetVer1(const AString & a_FileName, cLuaState & a_LuaState, bool a_LogWarnings); /** Loads a single piece from the cubeset file parsed into the specified Lua state. The piece's definition table is expected to be at the top of the Lua stack. Returns true on success, false on error. a_PieceIndex is the index of the piece, in the Pieces table. It is used for logging only. If a_LogWarnings is true, logs a warning to console when loading fails. */ bool LoadCubesetPieceVer1(const AString & a_FileName, cLuaState & a_LuaState, int a_PieceIndex, bool a_LogWarnings); /** Loads a single piece's prefab from the cubeset file parsed into the specified Lua state. The piece's definition table is expected to be at the top of the Lua stack. Returns the prefab on success, nullptr on failure. a_PieceName is the identification of the piece, used for logging only. If a_LogWarnings is true, logs a warning to console when loading fails. */ std::unique_ptr LoadPrefabFromCubesetVer1( const AString & a_FileName, cLuaState & a_LuaState, const AString & a_PieceName, bool a_LogWarnings ); /** Reads a single piece's connectors from the cubeset file parsed into the specified Lua state. The piece's definition table is expected to be at the top of the Lua stack. Returns true on success, false on failure. The connectors are added into the a_Prefab object. No Connectors table is considered a failure, empty Connectors table is considered a success. If any of the connectors are malformed, it is considered a failure, although the rest of the connectors will still load. a_PieceName is the identification of the piece, used for logging only. If a_LogWarnings is true, logs a warning to console when loading fails. */ bool ReadConnectorsCubesetVer1( const AString & a_FileName, cLuaState & a_LuaState, const AString & a_PieceName, cPrefab * a_Prefab, bool a_LogWarnings ); /** Reads a single piece's metadata from the cubeset file parsed into the specified Lua state. The piece's definition table is expected to be at the top of the Lua stack. Returns true on success, false on failure. The metadata is applied into the a_Prefab object. a_PieceName is the identification of the piece, used for logging only. If a_LogWarnings is true, logs a warning to console when loading fails. */ bool ReadPieceMetadataCubesetVer1( const AString & a_FileName, cLuaState & a_LuaState, const AString & a_PieceName, cPrefab * a_Prefab, bool a_LogWarnings ); /** Reads the metadata for the entire pool from the cubeset file, stores it in the m_Metadata map. Returns true on success, false on failure. If a_LogWarnings is true, logs a warning to console when loading fails. */ bool ReadPoolMetadataCubesetVer1( const AString & a_FileName, cLuaState & a_LuaState, bool a_LogWarnings ); /** Applies the base known metadata from the m_Metadata map into this pool. If a_LogWarnings is true, logs a warning to console when loading fails. */ void ApplyBaseMetadataCubesetVer1( const AString & a_FileName, bool a_LogWarnings ); } ; ================================================ FILE: src/Generating/PrefabStructure.cpp ================================================ // PrefabStructure.cpp // Implements the cPrefabStructure class representing a cGridStructGen::cStructure descendant based on placed cPrefab instances #include "Globals.h" #include "PrefabStructure.h" #include "Prefab.h" cPrefabStructure::cPrefabStructure( int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ, cPlacedPieces && a_Pieces, cTerrainHeightGen & a_HeightGen ): Super(a_GridX, a_GridZ, a_OriginX, a_OriginZ), m_Pieces(std::move(a_Pieces)), m_HeightGen(a_HeightGen) { } void cPrefabStructure::DrawIntoChunk(cChunkDesc & a_Chunk) { // Iterate over all items // Each intersecting prefab is placed on ground, if requested, then drawn for (cPlacedPieces::iterator itr = m_Pieces.begin(), end = m_Pieces.end(); itr != end; ++itr) { const cPrefab & Prefab = static_cast((*itr)->GetPiece()); if (Prefab.ShouldMoveToGround() && !(*itr)->HasBeenMovedToGround()) { PlacePieceOnGround(**itr); } Prefab.Draw(a_Chunk, itr->get()); } // for itr - m_PlacedPieces[] } void cPrefabStructure::PlacePieceOnGround(cPlacedPiece & a_Piece) { cPiece::cConnector FirstConnector = a_Piece.GetRotatedConnector(0); int ChunkX, ChunkZ; int BlockX = FirstConnector.m_Pos.x; int BlockZ = FirstConnector.m_Pos.z; int BlockY; cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ); cChunkDef::HeightMap HeightMap; m_HeightGen.GenHeightMap({ChunkX, ChunkZ}, HeightMap); int TerrainHeight = cChunkDef::GetHeight(HeightMap, BlockX, BlockZ); a_Piece.MoveToGroundBy(TerrainHeight - FirstConnector.m_Pos.y + 1); } ================================================ FILE: src/Generating/PrefabStructure.h ================================================ // PrefabStructure.h // Declares the cPrefabStructure class representing a cGridStructGen::cStructure descendant based on placed cPrefab instances #pragma once #include "GridStructGen.h" #include "PiecePool.h" class cPrefabStructure: public cGridStructGen::cStructure { using Super = cGridStructGen::cStructure; public: cPrefabStructure( int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ, cPlacedPieces && a_Pieces, cTerrainHeightGen & a_HeightGen ); protected: /** The pieces placed by the generator. */ cPlacedPieces m_Pieces; /** The height generator used when adjusting pieces onto the ground. */ cTerrainHeightGen & m_HeightGen; // cGridStructGen::cStructure overrides: virtual void DrawIntoChunk(cChunkDesc & a_Chunk) override; /** Adjusts the Y coord of the given piece so that the piece is on the ground. Ground level is assumed to be represented by the first connector in the piece. */ void PlacePieceOnGround(cPlacedPiece & a_Piece); }; ================================================ FILE: src/Generating/ProtIntGen.h ================================================ // ProtIntGen.h // Declares the prototyping integer generators - cProtIntGen class and its descendants /* These classes generate 2D arrays of integers that have various interpretations. The main purpose of these classes is to provide fast prototyping for cIntGen classes - unlike cIntGen classes, these are not template-based and so they take care of the underlying sizes automatically. This makes them easier to chain and re-chain, since the size parameters don't need to be adjusted after each such case. Their performance is, however, slightly worse, which is why we use cIntGen classes in the final generator. Because there is no SizeX / SizeZ template param, the generators would have to either alloc memory for each underlying generator's values, or use a maximum-size buffer. We chose the latter, to avoid memory allocation overhead; this however means that there's (an arbitrary) limit to the size of the generated data. */ #pragma once // We need the biome group constants defined there: #include "IntGen.h" /** Maximum size of the generated area. This value is used only if there isn't an override in place. To adjust the actual buffer size, just do a "#define PROT_INT_BUFFER_SIZE 9000" before including this header. Note, however, that you should use a consistent value throughout a single project. */ #ifndef PROT_INT_BUFFER_SIZE #define PROT_INT_BUFFER_SIZE 900 #endif /** Interface that all the generator classes provide. */ class cProtIntGen { protected: /** Maximum size of the generated area. Adjust the constant if you need larger areas, these are just so that we can use fixed-size buffers. */ static const int m_BufferSize = PROT_INT_BUFFER_SIZE; public: /** Type of the generic interface used for storing links to the underlying generators. */ using Underlying = std::shared_ptr; /** Force a virtual destructor in all descendants. Descendants contain virtual functions and are referred to via pointer-to-base, so they need a virtual destructor. */ virtual ~cProtIntGen() {} /** Generates the array of specified size into a_Values, based on given min coords. */ virtual void GetInts(int a_MinX, int a_MinZ, size_t a_SizeX, size_t a_SizeZ, int *a_Values) = 0; }; /** Provides additional cNoise member and its helper functions. */ class cProtIntGenWithNoise: public cProtIntGen { using Super = cProtIntGen; public: cProtIntGenWithNoise(int a_Seed): m_Noise(a_Seed) { } protected: cNoise m_Noise; /** Chooses one of a_Val1 or a_Val2, based on m_Noise and the coordinates for querying the noise. */ int chooseRandomOne(int a_RndX, int a_RndZ, int a_Val1, int a_Val2) { int rnd = m_Noise.IntNoise2DInt(a_RndX, a_RndZ) / 7; return ((rnd & 1) == 0) ? a_Val1 : a_Val2; } /** Chooses one of a_ValN, based on m_Noise and the coordinates for querying the noise. */ int chooseRandomOne(int a_RndX, int a_RndZ, int a_Val1, int a_Val2, int a_Val3, int a_Val4) { int rnd = m_Noise.IntNoise2DInt(a_RndX, a_RndZ) / 7; switch (rnd % 4) { case 0: return a_Val1; case 1: return a_Val2; case 2: return a_Val3; default: return a_Val4; } } }; /** Generates a 2D array of random integers in the specified range [0 .. Range). */ class cProtIntGenChoice: public cProtIntGenWithNoise { using Super = cProtIntGenWithNoise; public: cProtIntGenChoice(int a_Seed, int a_Range): Super(a_Seed), m_Range(a_Range) { } virtual void GetInts(int a_MinX, int a_MinZ, size_t a_SizeX, size_t a_SizeZ, int *a_Values) override { for (size_t z = 0; z < a_SizeZ; z++) { int BaseZ = a_MinZ + static_cast(z); for (size_t x = 0; x < a_SizeX; x++) { a_Values[x + a_SizeX * z] = (Super::m_Noise.IntNoise2DInt(a_MinX + static_cast(x), BaseZ) / 7) % m_Range; } } // for z } protected: int m_Range; }; /** Decides between the ocean and landmass biomes. Has a threshold (in percent) of how much land, the larger the threshold, the more land. Generates 0 for ocean, biome group ID for landmass. */ class cProtIntGenLandOcean: public cProtIntGenWithNoise { using Super = cProtIntGenWithNoise; public: cProtIntGenLandOcean(int a_Seed, int a_Threshold): Super(a_Seed), m_Threshold(a_Threshold) { } virtual void GetInts(int a_MinX, int a_MinZ, size_t a_SizeX, size_t a_SizeZ, int *a_Values) override { for (size_t z = 0; z < a_SizeZ; z++) { int BaseZ = a_MinZ + static_cast(z); for (size_t x = 0; x < a_SizeX; x++) { int rnd = (Super::m_Noise.IntNoise2DInt(a_MinX + static_cast(x), BaseZ) / 7); a_Values[x + a_SizeX * z] = ((rnd % 100) < m_Threshold) ? ((rnd / 101) % bgLandOceanMax + 1) : 0; } } // If the centerpoint of the world is within the area, set it to bgTemperate, always: if ((a_MinX <= 0) && (a_MinZ <= 0) && (a_MinX + static_cast(a_SizeX) > 0) && (a_MinZ + static_cast(a_SizeZ) > 0)) { a_Values[static_cast(-a_MinX) - static_cast(a_MinZ) * a_SizeX] = bgTemperate; } } protected: int m_Threshold; }; /** Zooms the underlying value array to twice the size. Uses random-neighbor for the pixels in-between. This means that the zoome out image is randomly distorted. Applying zoom several times provides all the distortion that the generators need. */ class cProtIntGenZoom: public cProtIntGenWithNoise { using Super = cProtIntGenWithNoise; public: cProtIntGenZoom(int a_Seed, Underlying a_UnderlyingGen): Super(a_Seed), m_UnderlyingGen(std::move(a_UnderlyingGen)) { } virtual void GetInts(int a_MinX, int a_MinZ, size_t a_SizeX, size_t a_SizeZ, int *a_Values) override { // Get the coords for the lower generator: int lowerMinX = a_MinX >> 1; int lowerMinZ = a_MinZ >> 1; size_t lowerSizeX = a_SizeX / 2 + 2; size_t lowerSizeZ = a_SizeZ / 2 + 2; ASSERT(lowerSizeX * lowerSizeZ <= m_BufferSize); ASSERT(lowerSizeX > 0); ASSERT(lowerSizeZ > 0); // Generate the underlying data with half the resolution: int lowerData[m_BufferSize]; m_UnderlyingGen->GetInts(lowerMinX, lowerMinZ, lowerSizeX, lowerSizeZ, lowerData); const size_t lowStepX = (lowerSizeX - 1) * 2; int cache[m_BufferSize]; // Discreet-interpolate the values into twice the size: for (size_t z = 0; z < lowerSizeZ - 1; ++z) { size_t idx = (z * 2) * lowStepX; int PrevZ0 = lowerData[z * lowerSizeX]; int PrevZ1 = lowerData[(z + 1) * lowerSizeX]; for (size_t x = 0; x < lowerSizeX - 1; ++x) { int ValX1Z0 = lowerData[x + 1 + z * lowerSizeX]; int ValX1Z1 = lowerData[x + 1 + (z + 1) * lowerSizeX]; int RndX = (static_cast(x) + lowerMinX) * 2; int RndZ = (static_cast(z) + lowerMinZ) * 2; cache[idx] = PrevZ0; cache[idx + lowStepX] = Super::chooseRandomOne(RndX, RndZ + 1, PrevZ0, PrevZ1); cache[idx + 1] = Super::chooseRandomOne(RndX, RndZ - 1, PrevZ0, ValX1Z0); cache[idx + 1 + lowStepX] = Super::chooseRandomOne(RndX, RndZ, PrevZ0, ValX1Z0, PrevZ1, ValX1Z1); idx += 2; PrevZ0 = ValX1Z0; PrevZ1 = ValX1Z1; } } // Copy from Cache into a_Values; take into account the even / odd offsets in a_Min: for (size_t z = 0; z < a_SizeZ; ++z) { memcpy(a_Values + z * a_SizeX, cache + (z + (a_MinZ & 1)) * lowStepX + (a_MinX & 1), a_SizeX * sizeof(int)); } } protected: Underlying m_UnderlyingGen; }; /** Smoothes out some artifacts generated by the zooming - mostly single-pixel values. Compares each pixel to its neighbors and if the neighbors are equal, changes the pixel to their value. */ class cProtIntGenSmooth: public cProtIntGenWithNoise { using Super = cProtIntGenWithNoise; public: cProtIntGenSmooth(int a_Seed, Underlying a_Underlying): Super(a_Seed), m_Underlying(std::move(a_Underlying)) { } virtual void GetInts(int a_MinX, int a_MinZ, size_t a_SizeX, size_t a_SizeZ, int *a_Values) override { // Generate the underlying values: size_t lowerSizeX = a_SizeX + 2; size_t lowerSizeZ = a_SizeZ + 2; ASSERT(lowerSizeX * lowerSizeZ <= m_BufferSize); int lowerData[m_BufferSize]; m_Underlying->GetInts(a_MinX - 1, a_MinZ - 1, lowerSizeX, lowerSizeZ, lowerData); // Smooth - for each square check if the surroundings are the same, if so, expand them diagonally. // Also get rid of single-pixel irregularities (A-B-A): for (size_t z = 0; z < a_SizeZ; z++) { int NoiseZ = a_MinZ + static_cast(z); for (size_t x = 0; x < a_SizeX; x++) { int val = lowerData[x + 1 + (z + 1) * lowerSizeX]; int above = lowerData[x + 1 + z * lowerSizeX]; int below = lowerData[x + 1 + (z + 2) * lowerSizeX]; int left = lowerData[x + (z + 1) * lowerSizeX]; int right = lowerData[x + 2 + (z + 1) * lowerSizeX]; if ((left == right) && (above == below)) { if (((Super::m_Noise.IntNoise2DInt(a_MinX + static_cast(x), NoiseZ) / 7) % 2) == 0) { val = left; } else { val = above; } } else { if (left == right) { val = left; } if (above == below) { val = above; } } a_Values[x + z * a_SizeX] = val; } } } protected: Underlying m_Underlying; }; /** Averages the values of the underlying 2 * 2 neighbors. */ class cProtIntGenAvgValues: public cProtIntGen { using Super = cProtIntGen; public: cProtIntGenAvgValues(Underlying a_Underlying): m_Underlying(std::move(a_Underlying)) { } virtual void GetInts(int a_MinX, int a_MinZ, size_t a_SizeX, size_t a_SizeZ, int *a_Values) override { // Generate the underlying values: size_t lowerSizeX = a_SizeX + 1; size_t lowerSizeZ = a_SizeZ + 1; ASSERT(lowerSizeX * lowerSizeZ <= m_BufferSize); int lowerData[m_BufferSize]; m_Underlying->GetInts(a_MinX, a_MinZ, lowerSizeX, lowerSizeZ, lowerData); // Average - add all 4 "neighbors" and divide by 4: for (size_t z = 0; z < a_SizeZ; z++) { for (size_t x = 0; x < a_SizeX; x++) { size_t idxLower = x + lowerSizeX * z; a_Values[x + a_SizeX * z] = ( lowerData[idxLower] + lowerData[idxLower + 1] + lowerData[idxLower + lowerSizeX] + lowerData[idxLower + lowerSizeX + 1] ) / 4; } } } protected: Underlying m_Underlying; }; /** Averages the values of the underlying 4 * 4 neighbors. */ class cProtIntGenAvg4Values: public cProtIntGen { using Super = cProtIntGen; public: cProtIntGenAvg4Values(Underlying a_Underlying): m_Underlying(std::move(a_Underlying)) { } virtual void GetInts(int a_MinX, int a_MinZ, size_t a_SizeX, size_t a_SizeZ, int *a_Values) override { // Generate the underlying values: size_t lowerSizeX = a_SizeX + 4; size_t lowerSizeZ = a_SizeZ + 4; ASSERT(lowerSizeX * lowerSizeZ <= m_BufferSize); int lowerData[m_BufferSize]; m_Underlying->GetInts(a_MinX - 1, a_MinZ - 1, lowerSizeX, lowerSizeZ, lowerData); // Calculate the weighted average of all 16 "neighbors": for (size_t z = 0; z < a_SizeZ; z++) { for (size_t x = 0; x < a_SizeX; x++) { size_t idxLower1 = x + lowerSizeX * z; size_t idxLower2 = idxLower1 + lowerSizeX; size_t idxLower3 = idxLower1 + 2 * lowerSizeX; size_t idxLower4 = idxLower1 + 3 * lowerSizeX; a_Values[x + a_SizeX * z] = ( 1 * lowerData[idxLower1] + 2 * lowerData[idxLower1 + 1] + 2 * lowerData[idxLower1 + 2] + 1 * lowerData[idxLower1 + 3] + 2 * lowerData[idxLower2] + 32 * lowerData[idxLower2 + 1] + 32 * lowerData[idxLower2 + 2] + 2 * lowerData[idxLower2 + 3] + 2 * lowerData[idxLower3] + 32 * lowerData[idxLower3 + 1] + 32 * lowerData[idxLower3 + 2] + 2 * lowerData[idxLower3 + 3] + 1 * lowerData[idxLower4] + 2 * lowerData[idxLower4 + 1] + 2 * lowerData[idxLower4 + 2] + 1 * lowerData[idxLower4 + 3] ) / 148; } } } protected: Underlying m_Underlying; }; /** Averages the values of the underlying 3 * 3 neighbors with custom weight. */ template class cProtIntGenWeightAvg: public cProtIntGen { using Super = cProtIntGen; public: cProtIntGenWeightAvg(Underlying a_Underlying): m_Underlying(std::move(a_Underlying)) { } virtual void GetInts(int a_MinX, int a_MinZ, size_t a_SizeX, size_t a_SizeZ, int *a_Values) override { // Generate the underlying values: size_t lowerSizeX = a_SizeX + 3; size_t lowerSizeZ = a_SizeZ + 3; ASSERT(lowerSizeX * lowerSizeZ <= m_BufferSize); int lowerData[m_BufferSize]; m_Underlying->GetInts(a_MinX, a_MinZ, lowerSizeX, lowerSizeZ, lowerData); // Calculate the weighted average the neighbors: for (size_t z = 0; z < a_SizeZ; z++) { for (size_t x = 0; x < a_SizeX; x++) { size_t idxLower1 = x + lowerSizeX * z; size_t idxLower2 = idxLower1 + lowerSizeX; size_t idxLower3 = idxLower1 + 2 * lowerSizeX; a_Values[x + a_SizeX * z] = ( WeightDiagonal * lowerData[idxLower1] + WeightCardinal * lowerData[idxLower1 + 1] + WeightDiagonal * lowerData[idxLower1 + 2] + WeightCardinal * lowerData[idxLower2] + WeightCenter * lowerData[idxLower2 + 1] + WeightCardinal * lowerData[idxLower2 + 2] + WeightDiagonal * lowerData[idxLower3] + WeightCardinal * lowerData[idxLower3 + 1] + WeightDiagonal * lowerData[idxLower3 + 2] ) / (4 * WeightDiagonal + 4 * WeightCardinal + WeightCenter); } } } protected: Underlying m_Underlying; }; /** Replaces random values of the underlying data with random integers in the specified range [Min .. Min + Range). */ class cProtIntGenRndChoice: public cProtIntGenWithNoise { using Super = cProtIntGenWithNoise; public: cProtIntGenRndChoice(int a_Seed, int a_ChancePct, int a_Min, int a_Range, Underlying a_Underlying): Super(a_Seed), m_ChancePct(a_ChancePct), m_Min(a_Min), m_Range(a_Range), m_Underlying(std::move(a_Underlying)) { } virtual void GetInts(int a_MinX, int a_MinZ, size_t a_SizeX, size_t a_SizeZ, int *a_Values) override { // Generate the underlying values: m_Underlying->GetInts(a_MinX, a_MinZ, a_SizeX, a_SizeZ, a_Values); // Replace random values: for (size_t z = 0; z < a_SizeZ; z++) { int BaseZ = a_MinZ + static_cast(z); for (size_t x = 0; x < a_SizeX; x++) { if (((Super::m_Noise.IntNoise2DInt(BaseZ, a_MinX + static_cast(x)) / 13) % 101) < m_ChancePct) { a_Values[x + a_SizeX * z] = m_Min + (Super::m_Noise.IntNoise2DInt(a_MinX + static_cast(x), BaseZ) / 7) % m_Range; } } // for x } // for z } protected: int m_ChancePct; int m_Min; int m_Range; Underlying m_Underlying; }; /** Adds a random value in range [-a_HalfRange, +a_HalfRange] to each of the underlying values. */ class cProtIntGenAddRnd: public cProtIntGenWithNoise { using Super = cProtIntGenWithNoise; public: cProtIntGenAddRnd(int a_Seed, int a_HalfRange, Underlying a_Underlying): Super(a_Seed), m_Range(a_HalfRange * 2 + 1), m_HalfRange(a_HalfRange), m_Underlying(std::move(a_Underlying)) { } virtual void GetInts(int a_MinX, int a_MinZ, size_t a_SizeX, size_t a_SizeZ, int *a_Values) override { // Generate the underlying values: m_Underlying->GetInts(a_MinX, a_MinZ, a_SizeX, a_SizeZ, a_Values); // Add the random values: for (size_t z = 0; z < a_SizeZ; z++) { int NoiseZ = a_MinZ + static_cast(z); for (size_t x = 0; x < a_SizeX; x++) { int noiseVal = ((Super::m_Noise.IntNoise2DInt(a_MinX + static_cast(x), NoiseZ) / 7) % m_Range) - m_HalfRange; a_Values[x + z * a_SizeX] += noiseVal; } } } protected: int m_Range; int m_HalfRange; Underlying m_Underlying; }; /** Replaces random underlying values with the average of the neighbors. */ class cProtIntGenRndAvg: public cProtIntGenWithNoise { using Super = cProtIntGenWithNoise; public: cProtIntGenRndAvg(int a_Seed, int a_AvgChancePct, Underlying a_Underlying): Super(a_Seed), m_AvgChancePct(a_AvgChancePct), m_Underlying(std::move(a_Underlying)) { } virtual void GetInts(int a_MinX, int a_MinZ, size_t a_SizeX, size_t a_SizeZ, int *a_Values) override { // Generate the underlying values: size_t lowerSizeX = a_SizeX + 2; size_t lowerSizeZ = a_SizeZ + 2; ASSERT(lowerSizeX * lowerSizeZ <= m_BufferSize); int lowerData[m_BufferSize]; m_Underlying->GetInts(a_MinX - 1, a_MinZ - 1, lowerSizeX, lowerSizeZ, lowerData); // Average random values: for (size_t z = 0; z < a_SizeZ; z++) { int NoiseZ = a_MinZ + static_cast(z); for (size_t x = 0; x < a_SizeX; x++) { size_t idxLower = x + 1 + lowerSizeX * (z + 1); if (((Super::m_Noise.IntNoise2DInt(a_MinX + static_cast(x), NoiseZ) / 7) % 100) > m_AvgChancePct) { // Average the 4 neighbors: a_Values[x + z * a_SizeX] = ( lowerData[idxLower - 1] + lowerData[idxLower + 1] + lowerData[idxLower - lowerSizeX] + lowerData[idxLower + lowerSizeX] ) / 4; } else { // Keep the underlying value: a_Values[x + z * a_SizeX] = lowerData[idxLower]; } } } } protected: int m_AvgChancePct; Underlying m_Underlying; }; /** Replaces random underlying values with a random value in between the max and min of the neighbors. */ class cProtIntGenRndBetween: public cProtIntGenWithNoise { using Super = cProtIntGenWithNoise; public: cProtIntGenRndBetween(int a_Seed, int a_AvgChancePct, Underlying a_Underlying): Super(a_Seed), m_AvgChancePct(a_AvgChancePct), m_Underlying(std::move(a_Underlying)) { } virtual void GetInts(int a_MinX, int a_MinZ, size_t a_SizeX, size_t a_SizeZ, int *a_Values) override { // Generate the underlying values: size_t lowerSizeX = a_SizeX + 2; size_t lowerSizeZ = a_SizeZ + 2; ASSERT(lowerSizeX * lowerSizeZ <= m_BufferSize); int lowerData[m_BufferSize]; m_Underlying->GetInts(a_MinX - 1, a_MinZ - 1, lowerSizeX, lowerSizeZ, lowerData); // Average random values: for (size_t z = 0; z < a_SizeZ; z++) { int NoiseZ = a_MinZ + static_cast(z); for (size_t x = 0; x < a_SizeX; x++) { size_t idxLower = x + 1 + lowerSizeX * (z + 1); if (((Super::m_Noise.IntNoise2DInt(a_MinX + static_cast(x), NoiseZ) / 7) % 100) > m_AvgChancePct) { // Chose a value in between the min and max neighbor: int min = std::min(std::min(lowerData[idxLower - 1], lowerData[idxLower + 1]), std::min(lowerData[idxLower - lowerSizeX], lowerData[idxLower + lowerSizeX])); int max = std::max(std::max(lowerData[idxLower - 1], lowerData[idxLower + 1]), std::max(lowerData[idxLower - lowerSizeX], lowerData[idxLower + lowerSizeX])); a_Values[x + z * a_SizeX] = min + ((Super::m_Noise.IntNoise2DInt(a_MinX + static_cast(x), NoiseZ + 10) / 7) % (max - min + 1)); } else { // Keep the underlying value: a_Values[x + z * a_SizeX] = lowerData[idxLower]; } } } } protected: int m_AvgChancePct; Underlying m_Underlying; }; /** Converts land biomes at the edge of an ocean into the respective beach biome. */ class cProtIntGenBeaches: public cProtIntGen { using Super = cProtIntGen; public: cProtIntGenBeaches(Underlying a_Underlying): m_Underlying(std::move(a_Underlying)) { } virtual void GetInts(int a_MinX, int a_MinZ, size_t a_SizeX, size_t a_SizeZ, int *a_Values) override { // Map for biome -> its beach: static const int ToBeach[] = { /* biOcean */ biOcean, /* biPlains */ biBeach, /* biDesert */ biBeach, /* biExtremeHills */ biStoneBeach, /* biForest */ biBeach, /* biTaiga */ biColdBeach, /* biSwampland */ biSwampland, /* biRiver */ biRiver, /* biNether */ biNether, /* biEnd */ biEnd, /* biFrozenOcean */ biColdBeach, /* biFrozenRiver */ biColdBeach, /* biIcePlains */ biColdBeach, /* biIceMountains */ biColdBeach, /* biMushroomIsland */ biMushroomShore, /* biMushroomShore */ biMushroomShore, /* biBeach */ biBeach, /* biDesertHills */ biBeach, /* biForestHills */ biBeach, /* biTaigaHills */ biColdBeach, /* biExtremeHillsEdge */ biStoneBeach, /* biJungle */ biBeach, /* biJungleHills */ biBeach, /* biJungleEdge */ biBeach, /* biDeepOcean */ biOcean, /* biStoneBeach */ biStoneBeach, /* biColdBeach */ biColdBeach, /* biBirchForest */ biBeach, /* biBirchForestHills */ biBeach, /* biRoofedForest */ biBeach, /* biColdTaiga */ biColdBeach, /* biColdTaigaHills */ biColdBeach, /* biMegaTaiga */ biStoneBeach, /* biMegaTaigaHills */ biStoneBeach, /* biExtremeHillsPlus */ biStoneBeach, /* biSavanna */ biBeach, /* biSavannaPlateau */ biBeach, /* biMesa */ biMesa, /* biMesaPlateauF */ biMesa, /* biMesaPlateau */ biMesa, }; // Generate the underlying values: size_t lowerSizeX = a_SizeX + 2; size_t lowerSizeZ = a_SizeZ + 2; ASSERT(lowerSizeX * lowerSizeZ <= m_BufferSize); int lowerValues[m_BufferSize]; m_Underlying->GetInts(a_MinX - 1, a_MinZ - 1, lowerSizeX, lowerSizeZ, lowerValues); // Add beaches between ocean and biomes: for (size_t z = 0; z < a_SizeZ; z++) { for (size_t x = 0; x < a_SizeX; x++) { int val = lowerValues[x + 1 + (z + 1) * lowerSizeX]; int above = lowerValues[x + 1 + z * lowerSizeX]; int below = lowerValues[x + 1 + (z + 2) * lowerSizeX]; int left = lowerValues[x + (z + 1) * lowerSizeX]; int right = lowerValues[x + 2 + (z + 1) * lowerSizeX]; if (!IsBiomeOcean(val)) { if (IsBiomeOcean(above) || IsBiomeOcean(below) || IsBiomeOcean(left) || IsBiomeOcean(right)) { // First convert the value to a regular biome (drop the M flag), then modulo by our biome count: val = ToBeach[static_cast(val % 128) % ARRAYCOUNT(ToBeach)]; } } a_Values[x + z * a_SizeX] = val; } } } protected: Underlying m_Underlying; }; /** Generates the underlying numbers and then randomly changes some ocean group pixels into random land biome group pixels, based on the predefined chance. */ class cProtIntGenAddIslands: public cProtIntGenWithNoise { using Super = cProtIntGenWithNoise; public: using Underlying = std::shared_ptr; cProtIntGenAddIslands(int a_Seed, int a_Chance, Underlying a_Underlying): Super(a_Seed), m_Chance(a_Chance), m_Underlying(std::move(a_Underlying)) { } virtual void GetInts(int a_MinX, int a_MinZ, size_t a_SizeX, size_t a_SizeZ, int *a_Values) override { m_Underlying->GetInts(a_MinX, a_MinZ, a_SizeX, a_SizeZ, a_Values); for (size_t z = 0; z < a_SizeZ; z++) { for (size_t x = 0; x < a_SizeX; x++) { if (a_Values[x + z * a_SizeX] == bgOcean) { int rnd = Super::m_Noise.IntNoise2DInt(a_MinX + static_cast(x), a_MinZ + static_cast(z)) / 7; if (rnd % 1000 < m_Chance) { a_Values[x + z * a_SizeX] = (rnd / 1003) % bgLandOceanMax; } } } } } protected: /** Chance of each ocean pixel being converted, in permille. */ int m_Chance; Underlying m_Underlying; }; /** A filter that adds an edge biome group between two biome groups that need an edge between them. */ class cProtIntGenBiomeGroupEdges: public cProtIntGen { using Super = cProtIntGen; public: cProtIntGenBiomeGroupEdges(Underlying a_Underlying): m_Underlying(std::move(a_Underlying)) { } virtual void GetInts(int a_MinX, int a_MinZ, size_t a_SizeX, size_t a_SizeZ, int * a_Values) override { // Generate the underlying biome groups: size_t lowerSizeX = a_SizeX + 2; size_t lowerSizeZ = a_SizeZ + 2; ASSERT(lowerSizeX * lowerSizeZ <= m_BufferSize); int lowerValues[m_BufferSize]; m_Underlying->GetInts(a_MinX, a_MinZ, lowerSizeX, lowerSizeZ, lowerValues); // Change the biomes on incompatible edges into an edge biome: for (size_t z = 0; z < a_SizeZ; z++) { for (size_t x = 0; x < a_SizeX; x++) { int val = lowerValues[x + 1 + (z + 1) * lowerSizeX]; int Above = lowerValues[x + 1 + z * lowerSizeX]; int Below = lowerValues[x + 1 + (z + 2) * lowerSizeX]; int Left = lowerValues[x + (z + 1) * lowerSizeX]; int Right = lowerValues[x + 2 + (z + 1) * lowerSizeX]; switch (val) { // Desert should neighbor only oceans, desert and temperates; change to temperate when another: case bgDesert: { if ( !isDesertCompatible(Above) || !isDesertCompatible(Below) || !isDesertCompatible(Left) || !isDesertCompatible(Right) ) { val = bgTemperate; } break; } // case bgDesert // Ice should not neighbor deserts; change to temperate: case bgIce: { if ( (Above == bgDesert) || (Below == bgDesert) || (Left == bgDesert) || (Right == bgDesert) ) { val = bgTemperate; } break; } // case bgIce } a_Values[x + z * a_SizeX] = val; } // for x } // for z } protected: Underlying m_Underlying; inline bool isDesertCompatible(int a_BiomeGroup) { switch (a_BiomeGroup) { case bgOcean: case bgDesert: case bgTemperate: { return true; } default: { return false; } } } }; /** Turns biome group indices into real biomes. For each pixel, takes its biome group and chooses a random biome from that group; replaces the value with that biome. */ class cProtIntGenBiomes: public cProtIntGenWithNoise { using Super = cProtIntGenWithNoise; public: cProtIntGenBiomes(int a_Seed, Underlying a_Underlying): Super(a_Seed), m_Underlying(std::move(a_Underlying)) { } virtual void GetInts(int a_MinX, int a_MinZ, size_t a_SizeX, size_t a_SizeZ, int *a_Values) override { // Define the per-biome-group biomes: static const int oceanBiomes[] = { biOcean, // biDeepOcean, }; // Same as oceanBiomes, there are no rare oceanic biomes (mushroom islands are handled separately) static const int rareOceanBiomes[] = { biOcean, }; static const int desertBiomes[] = { biDesert, biDesert, biDesert, biDesert, biDesert, biDesert, biSavanna, biSavanna, biPlains, }; static const int rareDesertBiomes[] = { biMesaPlateau, biMesaPlateauF, }; static const int temperateBiomes[] = { biForest, biForest, biRoofedForest, biExtremeHills, biPlains, biBirchForest, biSwampland, }; static const int rareTemperateBiomes[] = { biJungle, // Jungle is not strictly temperate, but let's piggyback it here }; static const int mountainBiomes[] = { biExtremeHills, biForest, biTaiga, biPlains, }; static const int rareMountainBiomes[] = { biMegaTaiga, }; static const int iceBiomes[] = { biIcePlains, biIcePlains, biIcePlains, biIcePlains, biColdTaiga, }; // Same as iceBiomes, there's no rare ice biome static const int rareIceBiomes[] = { biIcePlains, biIcePlains, biIcePlains, biIcePlains, biColdTaiga, }; static const cBiomesInGroups biomesInGroups[] = { /* bgOcean */ { static_cast(ARRAYCOUNT(oceanBiomes)), oceanBiomes}, /* bgDesert */ { static_cast(ARRAYCOUNT(desertBiomes)), desertBiomes}, /* bgTemperate */ { static_cast(ARRAYCOUNT(temperateBiomes)), temperateBiomes}, /* bgMountains */ { static_cast(ARRAYCOUNT(mountainBiomes)), mountainBiomes}, /* bgIce */ { static_cast(ARRAYCOUNT(iceBiomes)), iceBiomes}, }; static const cBiomesInGroups rareBiomesInGroups[] = { /* bgOcean */ { static_cast(ARRAYCOUNT(rareOceanBiomes)), rareOceanBiomes}, /* bgDesert */ { static_cast(ARRAYCOUNT(rareDesertBiomes)), rareDesertBiomes}, /* bgTemperate */ { static_cast(ARRAYCOUNT(rareTemperateBiomes)), rareTemperateBiomes}, /* bgMountains */ { static_cast(ARRAYCOUNT(rareMountainBiomes)), rareMountainBiomes}, /* bgIce */ { static_cast(ARRAYCOUNT(rareIceBiomes)), rareIceBiomes}, }; // Generate the underlying values, representing biome groups: m_Underlying->GetInts(a_MinX, a_MinZ, a_SizeX, a_SizeZ, a_Values); // Overwrite each biome group with a random biome from that group: // Take care of the bgfRare flag for (size_t z = 0; z < a_SizeZ; z++) { size_t IdxZ = z * a_SizeX; for (size_t x = 0; x < a_SizeX; x++) { int val = a_Values[x + IdxZ]; const cBiomesInGroups & Biomes = (val > bgfRare) ? rareBiomesInGroups[(val & (bgfRare - 1)) % ARRAYCOUNT(rareBiomesInGroups)] : biomesInGroups[static_cast(val) % ARRAYCOUNT(biomesInGroups)]; int rnd = (Super::m_Noise.IntNoise2DInt(static_cast(x) + a_MinX, static_cast(z) + a_MinZ) / 7); a_Values[x + IdxZ] = Biomes.Biomes[rnd % Biomes.Count]; } } } protected: struct cBiomesInGroups { const int Count; const int * Biomes; }; /** The underlying int generator */ Underlying m_Underlying; }; /** Randomly replaces pixels of one value to another value, using the given chance. */ class cProtIntGenReplaceRandomly: public cProtIntGenWithNoise { using Super = cProtIntGenWithNoise; public: using Underlying = std::shared_ptr; cProtIntGenReplaceRandomly(int a_Seed, int a_From, int a_To, int a_Chance, Underlying a_Underlying): Super(a_Seed), m_From(a_From), m_To(a_To), m_Chance(a_Chance), m_Underlying(std::move(a_Underlying)) { } virtual void GetInts(int a_MinX, int a_MinZ, size_t a_SizeX, size_t a_SizeZ, int *a_Values) override { // Generate the underlying values: m_Underlying->GetInts(a_MinX, a_MinZ, a_SizeX, a_SizeZ, a_Values); // Replace some of the values: for (size_t z = 0; z < a_SizeZ; z++) { size_t idxZ = z * a_SizeX; for (size_t x = 0; x < a_SizeX; x++) { size_t idx = x + idxZ; if (a_Values[idx] == m_From) { int rnd = Super::m_Noise.IntNoise2DInt(static_cast(x) + a_MinX, static_cast(z) + a_MinZ) / 7; if (rnd % 1000 < m_Chance) { a_Values[idx] = m_To; } } } } // for z } protected: /** The original value to be replaced. */ int m_From; /** The destination value to which to replace. */ int m_To; /** Chance, in permille, of replacing the value. */ int m_Chance; Underlying m_Underlying; }; /** Mixer that joins together finalized biomes and rivers. It first checks for oceans, if there is an ocean in the Biomes, it keeps the ocean. If there's no ocean, it checks Rivers for a river, if there is a river, it uses the Biomes to select either regular river or frozen river, based on the biome. */ class cProtIntGenMixRivers: public cProtIntGen { using Super = cProtIntGen; public: cProtIntGenMixRivers(Underlying a_Biomes, Underlying a_Rivers): m_Biomes(std::move(a_Biomes)), m_Rivers(std::move(a_Rivers)) { } virtual void GetInts(int a_MinX, int a_MinZ, size_t a_SizeX, size_t a_SizeZ, int *a_Values) override { // Generate the underlying data: ASSERT(a_SizeX * a_SizeZ <= m_BufferSize); m_Biomes->GetInts(a_MinX, a_MinZ, a_SizeX, a_SizeZ, a_Values); int riverData[m_BufferSize]; m_Rivers->GetInts(a_MinX, a_MinZ, a_SizeX, a_SizeZ, riverData); // Mix the values: for (size_t z = 0; z < a_SizeZ; z++) { size_t idxZ = z * a_SizeX; for (size_t x = 0; x < a_SizeX; x++) { size_t idx = x + idxZ; if (IsBiomeOcean(a_Values[idx])) { // Oceans are kept without any changes continue; } if (riverData[idx] != biRiver) { // There's no river, keep the current value continue; } // There's a river, change the output to a river or a frozen river, based on the original biome: if (IsBiomeVeryCold(static_cast(a_Values[idx]))) { a_Values[idx] = biFrozenRiver; } else { a_Values[idx] = biRiver; } } // for x } // for z } protected: Underlying m_Biomes; Underlying m_Rivers; }; /** Generates a river based on the underlying data. This is basically an edge detector over the underlying data. The rivers are the edges where the underlying data changes from one pixel to its neighbor. */ class cProtIntGenRiver: public cProtIntGenWithNoise { using Super = cProtIntGenWithNoise; public: cProtIntGenRiver(int a_Seed, Underlying a_Underlying): Super(a_Seed), m_Underlying(std::move(a_Underlying)) { } virtual void GetInts(int a_MinX, int a_MinZ, size_t a_SizeX, size_t a_SizeZ, int *a_Values) override { // Generate the underlying data: size_t lowerSizeX = a_SizeX + 2; size_t lowerSizeZ = a_SizeZ + 2; ASSERT(lowerSizeX * lowerSizeZ <= m_BufferSize); int lowerValues[m_BufferSize]; m_Underlying->GetInts(a_MinX - 1, a_MinZ - 1, lowerSizeX, lowerSizeZ, lowerValues); // Detect the edges: for (size_t z = 0; z < a_SizeZ; z++) { for (size_t x = 0; x < a_SizeX; x++) { int Above = lowerValues[x + 1 + z * lowerSizeX]; int Below = lowerValues[x + 1 + (z + 2) * lowerSizeX]; int Left = lowerValues[x + (z + 1) * lowerSizeX]; int Right = lowerValues[x + 2 + (z + 1) * lowerSizeX]; int val = lowerValues[x + 1 + (z + 1) * lowerSizeX]; if ((val == Above) && (val == Below) && (val == Left) && (val == Right)) { val = 0; } else { val = biRiver; } a_Values[x + z * a_SizeX] = val; } // for x } // for z } protected: Underlying m_Underlying; }; /** Turns some of the oceans into the specified biome. Used for mushroom and deep ocean. The biome is only placed if at least 3 of its neighbors are ocean and only with the specified chance. */ class cProtIntGenAddToOcean: public cProtIntGenWithNoise { using Super = cProtIntGenWithNoise; public: cProtIntGenAddToOcean(int a_Seed, int a_Chance, int a_ToValue, Underlying a_Underlying): Super(a_Seed), m_Chance(a_Chance), m_ToValue(a_ToValue), m_Underlying(std::move(a_Underlying)) { } virtual void GetInts(int a_MinX, int a_MinZ, size_t a_SizeX, size_t a_SizeZ, int *a_Values) override { // Generate the underlying data: size_t lowerSizeX = a_SizeX + 2; size_t lowerSizeZ = a_SizeZ + 2; ASSERT(lowerSizeX * lowerSizeZ <= m_BufferSize); int lowerValues[m_BufferSize]; m_Underlying->GetInts(a_MinX - 1, a_MinZ - 1, lowerSizeX, lowerSizeZ, lowerValues); // Add the mushroom islands: for (size_t z = 0; z < a_SizeZ; z++) { for (size_t x = 0; x < a_SizeX; x++) { int val = lowerValues[x + 1 + (z + 1) * lowerSizeX]; if (!IsBiomeOcean(val)) { a_Values[x + z * a_SizeX] = val; continue; } // Count the ocean neighbors: int Above = lowerValues[x + 1 + z * lowerSizeX]; int Below = lowerValues[x + 1 + (z + 2) * lowerSizeX]; int Left = lowerValues[x + (z + 1) * lowerSizeX]; int Right = lowerValues[x + 2 + (z + 1) * lowerSizeX]; int NumOceanNeighbors = 0; if (IsBiomeOcean(Above)) { NumOceanNeighbors += 1; } if (IsBiomeOcean(Below)) { NumOceanNeighbors += 1; } if (IsBiomeOcean(Left)) { NumOceanNeighbors += 1; } if (IsBiomeOcean(Right)) { NumOceanNeighbors += 1; } // If at least 3 ocean neighbors and the chance is right, change: if ( (NumOceanNeighbors >= 3) && ((Super::m_Noise.IntNoise2DInt(static_cast(x) + a_MinX, static_cast(z) + a_MinZ) / 7) % 1000 < m_Chance) ) { a_Values[x + z * a_SizeX] = m_ToValue; } else { a_Values[x + z * a_SizeX] = val; } } // for x } // for z } protected: /** Chance, in permille, of changing the biome. */ int m_Chance; /** The value to change the ocean into. */ int m_ToValue; Underlying m_Underlying; }; /** Changes random pixels of the underlying data to the specified value. */ class cProtIntGenSetRandomly: public cProtIntGenWithNoise { using Super = cProtIntGenWithNoise; public: cProtIntGenSetRandomly(int a_Seed, int a_Chance, int a_ToValue, Underlying a_Underlying): Super(a_Seed), m_Chance(a_Chance), m_ToValue(a_ToValue), m_Underlying(std::move(a_Underlying)) { } virtual void GetInts(int a_MinX, int a_MinZ, size_t a_SizeX, size_t a_SizeZ, int *a_Values) override { // Generate the underlying data: m_Underlying->GetInts(a_MinX, a_MinZ, a_SizeX, a_SizeZ, a_Values); // Change random pixels to bgOcean: for (size_t z = 0; z < a_SizeZ; z++) { for (size_t x = 0; x < a_SizeX; x++) { int rnd = Super::m_Noise.IntNoise2DInt(static_cast(x) + a_MinX, static_cast(z) + a_MinZ) / 7; if (rnd % 1000 < m_Chance) { a_Values[x + z * a_SizeX] = m_ToValue; } } } } protected: /** Chance, in permille, of changing each pixel. */ int m_Chance; /** The value to which to set the pixel. */ int m_ToValue; Underlying m_Underlying; }; /** Adds a "rare" flag to random biome groups, based on the given chance. */ class cProtIntGenRareBiomeGroups: public cProtIntGenWithNoise { using Super = cProtIntGenWithNoise; public: cProtIntGenRareBiomeGroups(int a_Seed, int a_Chance, Underlying a_Underlying): Super(a_Seed), m_Chance(a_Chance), m_Underlying(std::move(a_Underlying)) { } virtual void GetInts(int a_MinX, int a_MinZ, size_t a_SizeX, size_t a_SizeZ, int *a_Values) override { // Generate the underlying data: m_Underlying->GetInts(a_MinX, a_MinZ, a_SizeX, a_SizeZ, a_Values); // Change some of the biome groups into rare biome groups: for (size_t z = 0; z < a_SizeZ; z++) { for (size_t x = 0; x < a_SizeX; x++) { int rnd = Super::m_Noise.IntNoise2DInt(static_cast(x) + a_MinX, static_cast(z) + a_MinZ) / 7; if (rnd % 1000 < m_Chance) { size_t idx = x + a_SizeX * z; a_Values[idx] = a_Values[idx] | bgfRare; } } } } protected: /** Chance, in permille, of changing each pixel into the rare biome group. */ int m_Chance; /** The underlying generator. */ Underlying m_Underlying; }; /** Changes biomes in the parent data into an alternate versions (usually "hill" variants), in such places that have their alterations set. */ class cProtIntGenAlternateBiomes: public cProtIntGenWithNoise { using Super = cProtIntGenWithNoise; public: cProtIntGenAlternateBiomes(int a_Seed, Underlying a_Alterations, Underlying a_BaseBiomes): Super(a_Seed), m_Alterations(std::move(a_Alterations)), m_BaseBiomes(std::move(a_BaseBiomes)) { } virtual void GetInts(int a_MinX, int a_MinZ, size_t a_SizeX, size_t a_SizeZ, int *a_Values) override { // Generate the base biomes and the alterations: m_BaseBiomes->GetInts(a_MinX, a_MinZ, a_SizeX, a_SizeZ, a_Values); int alterations[m_BufferSize]; m_Alterations->GetInts(a_MinX, a_MinZ, a_SizeX, a_SizeZ, alterations); // Change the biomes into their alternate versions: size_t len = a_SizeX * a_SizeZ; for (size_t idx = 0; idx < len; ++idx) { if (alterations[idx] == 0) { // No change continue; } // Change to alternate biomes: int val = a_Values[idx]; switch (val) { case biBirchForest: val = biBirchForestHills; break; case biDesert: val = biDesertHills; break; case biExtremeHills: val = biExtremeHillsPlus; break; case biForest: val = biForestHills; break; case biIcePlains: val = biIceMountains; break; case biJungle: val = biJungleHills; break; case biMegaTaiga: val = biMegaTaigaHills; break; case biMesaPlateau: val = biMesa; break; case biMesaPlateauF: val = biMesa; break; case biMesaPlateauM: val = biMesa; break; case biMesaPlateauFM: val = biMesa; break; case biPlains: val = biForest; break; case biRoofedForest: val = biPlains; break; case biSavanna: val = biSavannaPlateau; break; case biTaiga: val = biTaigaHills; break; } a_Values[idx] = val; } // for idx - a_Values[] } protected: Underlying m_Alterations; Underlying m_BaseBiomes; }; /** Adds an edge between two specifically incompatible biomes, such as mesa and forest. */ class cProtIntGenBiomeEdges: public cProtIntGenWithNoise { using Super = cProtIntGenWithNoise; public: cProtIntGenBiomeEdges(int a_Seed, Underlying a_Underlying): Super(a_Seed), m_Underlying(std::move(a_Underlying)) { } virtual void GetInts(int a_MinX, int a_MinZ, size_t a_SizeX, size_t a_SizeZ, int *a_Values) override { // Generate the underlying biomes: size_t lowerSizeX = a_SizeX + 2; size_t lowerSizeZ = a_SizeZ + 2; ASSERT(lowerSizeX * lowerSizeZ <= m_BufferSize); int lowerValues[m_BufferSize]; m_Underlying->GetInts(a_MinX - 1, a_MinZ - 1, lowerSizeX, lowerSizeZ, lowerValues); // Convert incompatible edges into neutral biomes: for (size_t z = 0; z < a_SizeZ; z++) { for (size_t x = 0; x < a_SizeX; x++) { int biome = lowerValues[x + 1 + (z + 1) * lowerSizeX]; int above = lowerValues[x + 1 + z * lowerSizeX]; int below = lowerValues[x + 1 + (z + 2) * lowerSizeX]; int left = lowerValues[x + (z + 1) * lowerSizeX]; int right = lowerValues[x + 2 + (z + 1) * lowerSizeX]; switch (biome) { case biDesert: case biDesertM: case biDesertHills: { if ( IsBiomeVeryCold(static_cast(above)) || IsBiomeVeryCold(static_cast(below)) || IsBiomeVeryCold(static_cast(left)) || IsBiomeVeryCold(static_cast(right)) ) { biome = biPlains; } break; } // case biDesert case biMesaPlateau: case biMesaPlateauF: case biMesaPlateauFM: case biMesaPlateauM: { if ( !isMesaCompatible(above) || !isMesaCompatible(below) || !isMesaCompatible(left) || !isMesaCompatible(right) ) { biome = biDesert; } break; } // Mesa biomes case biJungle: case biJungleM: { if ( !isJungleCompatible(above) || !isJungleCompatible(below) || !isJungleCompatible(left) || !isJungleCompatible(right) ) { biome = (biome == biJungle) ? biJungleEdge : biJungleEdgeM; } break; } // Jungle biomes case biSwampland: case biSwamplandM: { if ( IsBiomeNoDownfall(static_cast(above)) || IsBiomeNoDownfall(static_cast(below)) || IsBiomeNoDownfall(static_cast(left)) || IsBiomeNoDownfall(static_cast(right)) ) { biome = biPlains; } break; } // Swampland biomes } // switch (biome) a_Values[x + z * a_SizeX] = biome; } // for x } // for z } protected: Underlying m_Underlying; bool isMesaCompatible(int a_Biome) { switch (a_Biome) { case biDesert: case biMesa: case biMesaBryce: case biMesaPlateau: case biMesaPlateauF: case biMesaPlateauFM: case biMesaPlateauM: case biOcean: case biDeepOcean: { return true; } default: { return false; } } } bool isJungleCompatible(int a_Biome) { switch (a_Biome) { case biJungle: case biJungleM: case biJungleEdge: case biJungleEdgeM: case biJungleHills: { return true; } default: { return false; } } } }; /** Changes biomes in the parent data into their alternate versions ("M" variants), in such places that have their alterations set. */ class cProtIntGenMBiomes: public cProtIntGenWithNoise { using Super = cProtIntGenWithNoise; public: cProtIntGenMBiomes(int a_Seed, Underlying a_Alteration, Underlying a_Underlying): Super(a_Seed), m_Underlying(std::move(a_Underlying)), m_Alteration(std::move(a_Alteration)) { } virtual void GetInts(int a_MinX, int a_MinZ, size_t a_SizeX, size_t a_SizeZ, int *a_Values) override { // Generate the underlying biomes and the alterations: m_Underlying->GetInts(a_MinX, a_MinZ, a_SizeX, a_SizeZ, a_Values); int alterations[m_BufferSize]; m_Alteration->GetInts(a_MinX, a_MinZ, a_SizeX, a_SizeZ, alterations); // Wherever alterations are nonzero, change into alternate biome, if available: size_t len = a_SizeX * a_SizeZ; for (size_t idx = 0; idx < len; ++idx) { if (alterations[idx] == 0) { continue; } // Ice spikes biome was removed from here, because it was generated way too often switch (a_Values[idx]) { case biPlains: a_Values[idx] = biSunflowerPlains; break; case biDesert: a_Values[idx] = biDesertM; break; case biExtremeHills: a_Values[idx] = biExtremeHillsM; break; case biForest: a_Values[idx] = biFlowerForest; break; case biTaiga: a_Values[idx] = biTaigaM; break; case biSwampland: a_Values[idx] = biSwamplandM; break; case biJungle: a_Values[idx] = biJungleM; break; case biJungleEdge: a_Values[idx] = biJungleEdgeM; break; case biBirchForest: a_Values[idx] = biBirchForestM; break; case biBirchForestHills: a_Values[idx] = biBirchForestHillsM; break; case biRoofedForest: a_Values[idx] = biRoofedForestM; break; case biColdTaiga: a_Values[idx] = biColdTaigaM; break; case biMegaSpruceTaiga: a_Values[idx] = biMegaSpruceTaiga; break; case biMegaSpruceTaigaHills: a_Values[idx] = biMegaSpruceTaigaHills; break; case biExtremeHillsPlus: a_Values[idx] = biExtremeHillsPlusM; break; case biSavanna: a_Values[idx] = biSavannaM; break; case biSavannaPlateau: a_Values[idx] = biSavannaPlateauM; break; case biMesa: a_Values[idx] = biMesaBryce; break; case biMesaPlateauF: a_Values[idx] = biMesaPlateauFM; break; case biMesaPlateau: a_Values[idx] = biMesaBryce; break; } } // for idx - a_Values[] / alterations[] } protected: Underlying m_Underlying; Underlying m_Alteration; }; ================================================ FILE: src/Generating/Ravines.cpp ================================================ // Ravines.cpp // Implements the cStructGenRavines class representing the ravine structure generator #include "Globals.h" #include "Ravines.h" static const int NUM_RAVINE_POINTS = 4; struct cRavDefPoint { int m_BlockX; int m_BlockZ; int m_Radius; int m_Top; int m_Bottom; cRavDefPoint(int a_BlockX, int a_BlockZ, int a_Radius, int a_Top, int a_Bottom) : m_BlockX(a_BlockX), m_BlockZ(a_BlockZ), m_Radius(a_Radius), m_Top (a_Top), m_Bottom(a_Bottom) { } } ; using cRavDefPoints = std::vector; class cStructGenRavines::cRavine: public cGridStructGen::cStructure { using Super = cGridStructGen::cStructure; cRavDefPoints m_Points; /** Generates the shaping defpoints for the ravine, based on the ravine block coords and noise */ void GenerateBaseDefPoints(int a_BlockX, int a_BlockZ, int a_Size, cNoise & a_Noise); /** Refines (adds and smooths) defpoints from a_Src into a_Dst */ void RefineDefPoints(const cRavDefPoints & a_Src, cRavDefPoints & a_Dst); /** Does one round of smoothing, two passes of RefineDefPoints() */ void Smooth(void); /** Linearly interpolates the points so that the maximum distance between two neighbors is max 1 block */ void FinishLinear(void); public: cRavine(int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ, int a_Size, cNoise & a_Noise); #ifndef NDEBUG /** Exports itself as a SVG line definition */ AString ExportAsSVG(int a_Color, int a_OffsetX = 0, int a_OffsetZ = 0) const; #endif // !NDEBUG protected: // cGridStructGen::cStructure overrides: virtual void DrawIntoChunk(cChunkDesc & a_ChunkDesc) override; } ; //////////////////////////////////////////////////////////////////////////////// // cStructGenRavines: cStructGenRavines::cStructGenRavines(int a_Seed, int a_Size) : Super(a_Seed, a_Size, a_Size, a_Size, a_Size, a_Size * 2, a_Size * 2, 100), m_Size(a_Size) { } cGridStructGen::cStructurePtr cStructGenRavines::CreateStructure(int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ) { return cStructurePtr(new cRavine(a_GridX, a_GridZ, a_OriginX, a_OriginZ, m_Size, m_Noise)); } //////////////////////////////////////////////////////////////////////////////// // cStructGenRavines::cRavine cStructGenRavines::cRavine::cRavine(int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ, int a_Size, cNoise & a_Noise) : Super(a_GridX, a_GridZ, a_OriginX, a_OriginZ) { // Calculate the ravine shape-defining points: GenerateBaseDefPoints(a_OriginX, a_OriginZ, a_Size, a_Noise); // Smooth the ravine. Two passes are needed: Smooth(); Smooth(); // Linearly interpolate the neighbors so that they're close enough together: FinishLinear(); } void cStructGenRavines::cRavine::GenerateBaseDefPoints(int a_BlockX, int a_BlockZ, int a_Size, cNoise & a_Noise) { // Modify the size slightly to have different-sized ravines (1 / 2 to 1 / 1 of a_Size): a_Size = (512 + ((a_Noise.IntNoise3DInt(19 * a_BlockX, 11 * a_BlockZ, a_BlockX + a_BlockZ) / 17) % 512)) * a_Size / 1024; // The complete offset of the ravine from its cellpoint, up to 2 * a_Size in each direction int OffsetX = (((a_Noise.IntNoise3DInt(50 * a_BlockX, 30 * a_BlockZ, 0) / 9) % (2 * a_Size)) + ((a_Noise.IntNoise3DInt(30 * a_BlockX, 50 * a_BlockZ, 1000) / 7) % (2 * a_Size)) - 2 * a_Size) / 2; int OffsetZ = (((a_Noise.IntNoise3DInt(50 * a_BlockX, 30 * a_BlockZ, 2000) / 7) % (2 * a_Size)) + ((a_Noise.IntNoise3DInt(30 * a_BlockX, 50 * a_BlockZ, 3000) / 9) % (2 * a_Size)) - 2 * a_Size) / 2; int CenterX = a_BlockX + OffsetX; int CenterZ = a_BlockZ + OffsetZ; // Get the base angle in which the ravine "axis" goes: float Angle = static_cast((static_cast((a_Noise.IntNoise3DInt(20 * a_BlockX, 70 * a_BlockZ, 6000) / 9) % 16384)) / 16384.0 * M_PI); float xc = sinf(Angle); float zc = cosf(Angle); // Calculate the definition points and radii: int MaxRadius = static_cast(sqrt(12.0 + ((a_Noise.IntNoise2DInt(61 * a_BlockX, 97 * a_BlockZ) / 13) % a_Size) / 16)); int Top = 32 + ((a_Noise.IntNoise2DInt(13 * a_BlockX, 17 * a_BlockZ) / 23) % 32); int Bottom = 5 + ((a_Noise.IntNoise2DInt(17 * a_BlockX, 29 * a_BlockZ) / 13) % 32); int Mid = (Top + Bottom) / 2; int DefinitionPointX = CenterX - static_cast(xc * a_Size / 2); int DefinitionPointZ = CenterZ - static_cast(zc * a_Size / 2); m_Points.emplace_back(DefinitionPointX, DefinitionPointZ, 0, (Mid + Top) / 2, (Mid + Bottom) / 2); for (int i = 1; i < NUM_RAVINE_POINTS - 1; i++) { int LineX = CenterX + static_cast(xc * a_Size * (i - NUM_RAVINE_POINTS / 2) / NUM_RAVINE_POINTS); int LineZ = CenterZ + static_cast(zc * a_Size * (i - NUM_RAVINE_POINTS / 2) / NUM_RAVINE_POINTS); // Amplitude is the amount of blocks that this point is away from the ravine "axis" int Amplitude = (a_Noise.IntNoise3DInt(70 * a_BlockX, 20 * a_BlockZ + 31 * i, 10000 * i) / 9) % a_Size; Amplitude = Amplitude / 4 - a_Size / 8; // Amplitude is in interval [-a_Size / 4, a_Size / 4] int PointX = LineX + static_cast(zc * Amplitude); int PointZ = LineZ - static_cast(xc * Amplitude); int Radius = MaxRadius - abs(i - NUM_RAVINE_POINTS / 2); // TODO: better radius function int ThisTop = Top + ((a_Noise.IntNoise3DInt(7 * a_BlockX, 19 * a_BlockZ, i * 31) / 13) % 8) - 4; int ThisBottom = Bottom + ((a_Noise.IntNoise3DInt(19 * a_BlockX, 7 * a_BlockZ, i * 31) / 13) % 8) - 4; m_Points.emplace_back(PointX, PointZ, Radius, ThisTop, ThisBottom); } // for i - m_Points[] DefinitionPointX = CenterX + static_cast(xc * a_Size / 2); DefinitionPointZ = CenterZ + static_cast(zc * a_Size / 2); m_Points.emplace_back(DefinitionPointX, DefinitionPointZ, 0, Mid, Mid); } void cStructGenRavines::cRavine::RefineDefPoints(const cRavDefPoints & a_Src, cRavDefPoints & a_Dst) { if (a_Src.size() < 2) { // No midpoints, nothing to refine return; } // Smoothing: for each line segment, add points on its 1 / 4 lengths size_t Num = a_Src.size() - 2; // this many intermediary points a_Dst.clear(); a_Dst.reserve(Num * 2 + 2); cRavDefPoints::const_iterator itr = a_Src.begin() + 1; const cRavDefPoint & Source = a_Src.front(); a_Dst.push_back(Source); int PrevX = Source.m_BlockX; int PrevZ = Source.m_BlockZ; int PrevR = Source.m_Radius; int PrevT = Source.m_Top; int PrevB = Source.m_Bottom; for (size_t i = 0; i <= Num; ++i, ++itr) { int dx = itr->m_BlockX - PrevX; int dz = itr->m_BlockZ - PrevZ; if (abs(dx) + abs(dz) < 4) { // Too short a segment to smooth-subdivide into quarters continue; } int dr = itr->m_Radius - PrevR; int dt = itr->m_Top - PrevT; int db = itr->m_Bottom - PrevB; int Rad1 = std::max(PrevR + 1 * dr / 4, 1); int Rad2 = std::max(PrevR + 3 * dr / 4, 1); a_Dst.emplace_back(PrevX + 1 * dx / 4, PrevZ + 1 * dz / 4, Rad1, PrevT + 1 * dt / 4, PrevB + 1 * db / 4); a_Dst.emplace_back(PrevX + 3 * dx / 4, PrevZ + 3 * dz / 4, Rad2, PrevT + 3 * dt / 4, PrevB + 3 * db / 4); PrevX = itr->m_BlockX; PrevZ = itr->m_BlockZ; PrevR = itr->m_Radius; PrevT = itr->m_Top; PrevB = itr->m_Bottom; } a_Dst.push_back(a_Src.back()); } void cStructGenRavines::cRavine::Smooth(void) { cRavDefPoints Pts; RefineDefPoints(m_Points, Pts); // Refine m_Points -> Pts RefineDefPoints(Pts, m_Points); // Refine Pts -> m_Points } void cStructGenRavines::cRavine::FinishLinear(void) { // For each segment, use Bresenham's line algorithm to draw a "line" of defpoints // _X 2012_07_20: I tried modifying this algorithm to produce "thick" lines (only one coord change per point) // But the results were about the same as the original, so I disposed of it again - no need to use twice the count of points cRavDefPoints Pts; std::swap(Pts, m_Points); m_Points.reserve(Pts.size() * 3); int PrevX = Pts.front().m_BlockX; int PrevZ = Pts.front().m_BlockZ; for (cRavDefPoints::const_iterator itr = Pts.begin() + 1, end = Pts.end(); itr != end; ++itr) { int x1 = itr->m_BlockX; int z1 = itr->m_BlockZ; int dx = abs(x1 - PrevX); int dz = abs(z1 - PrevZ); int sx = (PrevX < x1) ? 1 : -1; int sz = (PrevZ < z1) ? 1 : -1; int err = dx - dz; int R = itr->m_Radius; int T = itr->m_Top; int B = itr->m_Bottom; for (;;) { m_Points.emplace_back(PrevX, PrevZ, R, T, B); if ((PrevX == x1) && (PrevZ == z1)) { break; } int e2 = 2 * err; if (e2 > -dz) { err -= dz; PrevX += sx; } if (e2 < dx) { err += dx; PrevZ += sz; } } // while (true) } // for itr } #ifndef NDEBUG AString cStructGenRavines::cRavine::ExportAsSVG(int a_Color, int a_OffsetX, int a_OffsetZ) const { auto SVG = fmt::format(FMT_STRING("m_BlockX, a_OffsetZ + itr->m_BlockZ)); Prefix = 'L'; } SVG.append("\"/>\n"); // Base point highlight: SVG.append(fmt::format(FMT_STRING("\n"), a_OffsetX + m_OriginX - 5, a_OffsetZ + m_OriginZ, a_OffsetX + m_OriginX + 5, a_OffsetZ + m_OriginZ )); SVG.append(fmt::format(FMT_STRING("\n"), a_OffsetX + m_OriginX, a_OffsetZ + m_OriginZ - 5, a_OffsetX + m_OriginX, a_OffsetZ + m_OriginZ + 5 )); // A gray line from the base point to the first point of the ravine, for identification: SVG.append(fmt::format(FMT_STRING("\n"), a_OffsetX + m_OriginX, a_OffsetZ + m_OriginZ, a_OffsetX + m_Points.front().m_BlockX, a_OffsetZ + m_Points.front().m_BlockZ )); // Offset guides: if (a_OffsetX > 0) { SVG.append(fmt::format(FMT_STRING("\n"), a_OffsetX, a_OffsetX )); } if (a_OffsetZ > 0) { SVG.append(fmt::format(FMT_STRING("\n"), a_OffsetZ, a_OffsetZ )); } return SVG; } #endif // !NDEBUG void cStructGenRavines::cRavine::DrawIntoChunk(cChunkDesc & a_ChunkDesc) { int BlockStartX = a_ChunkDesc.GetChunkX() * cChunkDef::Width; int BlockStartZ = a_ChunkDesc.GetChunkZ() * cChunkDef::Width; int BlockEndX = BlockStartX + cChunkDef::Width; int BlockEndZ = BlockStartZ + cChunkDef::Width; for (cRavDefPoints::const_iterator itr = m_Points.begin(), end = m_Points.end(); itr != end; ++itr) { if ( (itr->m_BlockX + itr->m_Radius < BlockStartX) || (itr->m_BlockX - itr->m_Radius > BlockEndX) || (itr->m_BlockZ + itr->m_Radius < BlockStartZ) || (itr->m_BlockZ - itr->m_Radius > BlockEndZ) ) { // Cannot intersect, bail out early continue; } // Carve out a cylinder around the xz point, m_Radius in diameter, from Bottom to Top: int RadiusSq = itr->m_Radius * itr->m_Radius; // instead of doing sqrt for each distance, we do sqr of the radius int DifX = BlockStartX - itr->m_BlockX; // substitution for faster calc int DifZ = BlockStartZ - itr->m_BlockZ; // substitution for faster calc for (int x = 0; x < cChunkDef::Width; x++) for (int z = 0; z < cChunkDef::Width; z++) { #ifndef NDEBUG // DEBUG: Make the ravine shapepoints visible on a single layer (so that we can see with Minutor what's going on) if ((DifX + x == 0) && (DifZ + z == 0)) { a_ChunkDesc.SetBlockType(x, 4, z, E_BLOCK_LAPIS_ORE); } #endif // !NDEBUG int DistSq = (DifX + x) * (DifX + x) + (DifZ + z) * (DifZ + z); if (DistSq <= RadiusSq) { int Top = std::min(itr->m_Top, static_cast(cChunkDef::Height)); // Stupid gcc needs int cast for (int y = std::max(itr->m_Bottom, 1); y <= Top; y++) { switch (a_ChunkDesc.GetBlockType(x, y, z)) { // Only carve out these specific block types case E_BLOCK_DIRT: case E_BLOCK_GRASS: case E_BLOCK_STONE: case E_BLOCK_COBBLESTONE: case E_BLOCK_GRAVEL: case E_BLOCK_SAND: case E_BLOCK_SANDSTONE: case E_BLOCK_NETHERRACK: case E_BLOCK_COAL_ORE: case E_BLOCK_IRON_ORE: case E_BLOCK_GOLD_ORE: case E_BLOCK_DIAMOND_ORE: case E_BLOCK_REDSTONE_ORE: case E_BLOCK_REDSTONE_ORE_GLOWING: { a_ChunkDesc.SetBlockType(x, y, z, E_BLOCK_AIR); break; } default: break; } } } } // for x, z - a_BlockTypes } // for itr - m_Points[] } ================================================ FILE: src/Generating/Ravines.h ================================================ // Ravines.h // Interfaces to the cStructGenRavines class representing the ravine structure generator #pragma once #include "GridStructGen.h" class cStructGenRavines: public cGridStructGen { using Super = cGridStructGen; public: cStructGenRavines(int a_Seed, int a_Size); protected: class cRavine; // fwd: Ravines.cpp int m_Size; // Max size, in blocks, of the ravines generated // cGridStructGen overrides: virtual cStructurePtr CreateStructure(int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ) override; } ; ================================================ FILE: src/Generating/RoughRavines.cpp ================================================ // RoughRavines.cpp // Implements the cRoughRavines class representing the rough ravine generator #include "Globals.h" #include "RoughRavines.h" #include "../BlockInfo.h" //////////////////////////////////////////////////////////////////////////////// // cRoughRavine: class cRoughRavine: public cGridStructGen::cStructure { using Super = cGridStructGen::cStructure; public: cRoughRavine( int a_Seed, size_t a_Size, float a_CenterWidth, float a_Roughness, float a_FloorHeightEdge1, float a_FloorHeightEdge2, float a_FloorHeightCenter, float a_CeilingHeightEdge1, float a_CeilingHeightEdge2, float a_CeilingHeightCenter, int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ ): Super(a_GridX, a_GridZ, a_OriginX, a_OriginZ), m_Seed(a_Seed + 100), m_Noise(a_Seed + 100), m_Roughness(a_Roughness) { // Create the basic structure - 2 lines meeting at the centerpoint: size_t Max = 2 * a_Size; size_t Half = a_Size; // m_DefPoints[Half] will be the centerpoint m_DefPoints.resize(Max + 1); int rnd = m_Noise.IntNoise2DInt(a_OriginX, a_OriginZ) / 7; float Len = static_cast(a_Size); float Angle = static_cast(rnd); // Angle is in radians, will be wrapped in the "sin" and "cos" operations float OfsX = sinf(Angle) * Len; float OfsZ = cosf(Angle) * Len; m_DefPoints[0].Set (a_OriginX - OfsX, a_OriginZ - OfsZ, 1, a_CeilingHeightEdge1, a_FloorHeightEdge1); m_DefPoints[Half].Set(static_cast(a_OriginX), static_cast(a_OriginZ), a_CenterWidth, a_CeilingHeightCenter, a_FloorHeightCenter); m_DefPoints[Max].Set (a_OriginX + OfsX, a_OriginZ + OfsZ, 1, a_CeilingHeightEdge2, a_FloorHeightEdge2); // Calculate the points in between, recursively: SubdivideLine(0, Half); SubdivideLine(Half, Max); // Initialize the per-height radius modifiers: InitPerHeightRadius(a_GridX, a_GridZ); } protected: struct sRavineDefPoint { float m_X; float m_Z; float m_Radius; float m_Top; float m_Bottom; void Set(float a_X, float a_Z, float a_Radius, float a_Top, float a_Bottom) { m_X = a_X; m_Z = a_Z; m_Radius = a_Radius; m_Top = a_Top; m_Bottom = a_Bottom; } }; using sRavineDefPoints = std::vector; int m_Seed; cNoise m_Noise; int m_MaxSize; sRavineDefPoints m_DefPoints; float m_Roughness; /** Number to add to the radius based on the height. This creates the "ledges" in the ravine walls. */ float m_PerHeightRadius[cChunkDef::Height]; /** Recursively subdivides the line between the points of the specified index. Sets the midpoint to the center of the line plus or minus a random offset, then calls itself for each half of the new line. */ void SubdivideLine(size_t a_Idx1, size_t a_Idx2) { // Calculate the midpoint: const sRavineDefPoint & p1 = m_DefPoints[a_Idx1]; const sRavineDefPoint & p2 = m_DefPoints[a_Idx2]; float MidX = (p1.m_X + p2.m_X) / 2; float MidZ = (p1.m_Z + p2.m_Z) / 2; float MidR = (p1.m_Radius + p2.m_Radius) / 2 + 0.1f; float MidT = (p1.m_Top + p2.m_Top) / 2; float MidB = (p1.m_Bottom + p2.m_Bottom) / 2; // Adjust the midpoint by a small amount of perpendicular vector in a random one of its two directions: float dx = p2.m_X - p1.m_X; float dz = p2.m_Z - p1.m_Z; if ((m_Noise.IntNoise2DInt(static_cast(MidX), static_cast(MidZ)) / 11) % 2 == 0) { MidX += dz * m_Roughness; MidZ -= dx * m_Roughness; } else { MidX -= dz * m_Roughness; MidZ += dx * m_Roughness; } size_t MidIdx = (a_Idx1 + a_Idx2) / 2; m_DefPoints[MidIdx].Set(MidX, MidZ, MidR, MidT, MidB); // Recurse the two halves, if they are worth recursing: if (MidIdx - a_Idx1 > 1) { SubdivideLine(a_Idx1, MidIdx); } if (a_Idx2 - MidIdx > 1) { SubdivideLine(MidIdx, a_Idx2); } } void InitPerHeightRadius(int a_GridX, int a_GridZ) { int h = 0; while (h < cChunkDef::Height) { m_Noise.SetSeed(m_Seed + h); int rnd = m_Noise.IntNoise2DInt(a_GridX, a_GridZ) / 13; int NumBlocks = (rnd % 3) + 2; rnd = rnd / 4; float Val = static_cast(rnd % 256) / 128.0f - 1.0f; // Random float in range [-1, +1] if (h + NumBlocks > cChunkDef::Height) { NumBlocks = cChunkDef::Height - h; } for (int i = 0; i < NumBlocks; i++) { m_PerHeightRadius[h + i] = Val; } h += NumBlocks; } } virtual void DrawIntoChunk(cChunkDesc & a_ChunkDesc) override { int BlockStartX = a_ChunkDesc.GetChunkX() * cChunkDef::Width; int BlockStartZ = a_ChunkDesc.GetChunkZ() * cChunkDef::Width; int BlockEndX = BlockStartX + cChunkDef::Width; int BlockEndZ = BlockStartZ + cChunkDef::Width; for (sRavineDefPoints::const_iterator itr = m_DefPoints.begin(), end = m_DefPoints.end(); itr != end; ++itr) { if ( (ceilf (itr->m_X + itr->m_Radius + 2) < BlockStartX) || (floorf(itr->m_X - itr->m_Radius - 2) > BlockEndX) || (ceilf (itr->m_Z + itr->m_Radius + 2) < BlockStartZ) || (floorf(itr->m_Z - itr->m_Radius - 2) > BlockEndZ) ) { // Cannot intersect, bail out early continue; } // Carve out a cylinder around the xz point, up to (m_Radius + 2) in diameter, from Bottom to Top: // On each height level, use m_PerHeightRadius[] to modify the actual radius used // EnlargedRadiusSq is the square of the radius enlarged by the maximum m_PerHeightRadius offset - anything outside it will never be touched. float RadiusSq = (itr->m_Radius + 2) * (itr->m_Radius + 2); float DifX = BlockStartX - itr->m_X; // substitution for faster calc float DifZ = BlockStartZ - itr->m_Z; // substitution for faster calc for (int x = 0; x < cChunkDef::Width; x++) for (int z = 0; z < cChunkDef::Width; z++) { #ifndef NDEBUG // DEBUG: Make the roughravine shapepoints visible on a single layer (so that we can see with Minutor what's going on) if ((FloorC(DifX + x) == 0) && (FloorC(DifZ + z) == 0)) { a_ChunkDesc.SetBlockType(x, 4, z, E_BLOCK_LAPIS_ORE); } #endif // !NDEBUG // If the column is outside the enlarged radius, bail out completely float DistSq = (DifX + x) * (DifX + x) + (DifZ + z) * (DifZ + z); if (DistSq > RadiusSq) { continue; } int Top = std::min(CeilC(itr->m_Top), +cChunkDef::Height); for (int y = std::max(FloorC(itr->m_Bottom), 1); y <= Top; y++) { if ((itr->m_Radius + m_PerHeightRadius[y]) * (itr->m_Radius + m_PerHeightRadius[y]) < DistSq) { continue; } if (cBlockInfo::CanBeTerraformed(a_ChunkDesc.GetBlockType(x, y, z))) { a_ChunkDesc.SetBlockType(x, y, z, E_BLOCK_AIR); } } // for y } // for x, z - a_BlockTypes } // for itr - m_Points[] } }; //////////////////////////////////////////////////////////////////////////////// // cRoughRavines: cRoughRavines::cRoughRavines( int a_Seed, int a_MaxSize, int a_MinSize, float a_MaxCenterWidth, float a_MinCenterWidth, float a_MaxRoughness, float a_MinRoughness, float a_MaxFloorHeightEdge, float a_MinFloorHeightEdge, float a_MaxFloorHeightCenter, float a_MinFloorHeightCenter, float a_MaxCeilingHeightEdge, float a_MinCeilingHeightEdge, float a_MaxCeilingHeightCenter, float a_MinCeilingHeightCenter, int a_GridSize, int a_MaxOffset ) : Super(a_Seed, a_GridSize, a_GridSize, a_MaxOffset, a_MaxOffset, a_MaxSize, a_MaxSize, 64), m_MaxSize(a_MaxSize), m_MinSize(a_MinSize), m_MaxCenterWidth(a_MaxCenterWidth), m_MinCenterWidth(a_MinCenterWidth), m_MaxRoughness(a_MaxRoughness), m_MinRoughness(a_MinRoughness), m_MaxFloorHeightEdge(a_MaxFloorHeightEdge), m_MinFloorHeightEdge(a_MinFloorHeightEdge), m_MaxFloorHeightCenter(a_MaxFloorHeightCenter), m_MinFloorHeightCenter(a_MinFloorHeightCenter), m_MaxCeilingHeightEdge(a_MaxCeilingHeightEdge), m_MinCeilingHeightEdge(a_MinCeilingHeightEdge), m_MaxCeilingHeightCenter(a_MaxCeilingHeightCenter), m_MinCeilingHeightCenter(a_MinCeilingHeightCenter) { if (m_MinSize > m_MaxSize) { std::swap(m_MinSize, m_MaxSize); std::swap(a_MinSize, a_MaxSize); } if (m_MaxSize < 16) { m_MaxSize = 16; LOGWARNING("RoughRavines: MaxSize too small, adjusting request from %d to %d", a_MaxSize, m_MaxSize); } if (m_MinSize < 16) { m_MinSize = 16; LOGWARNING("RoughRavines: MinSize too small, adjusting request from %d to %d", a_MinSize, m_MinSize); } if (m_MinSize == m_MaxSize) { m_MaxSize = m_MinSize + 1; } } cGridStructGen::cStructurePtr cRoughRavines::CreateStructure(int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ) { // Pick a random value for each of the ravine's parameters: size_t Size = static_cast(m_MinSize + (m_Noise.IntNoise2DInt(a_GridX, a_GridZ) / 7) % (m_MaxSize - m_MinSize)); // Random int from m_MinSize to m_MaxSize float CenterWidth = m_Noise.IntNoise2DInRange(a_GridX + 10, a_GridZ, m_MinCenterWidth, m_MaxCenterWidth); float Roughness = m_Noise.IntNoise2DInRange(a_GridX + 20, a_GridZ, m_MinRoughness, m_MaxRoughness); float FloorHeightEdge1 = m_Noise.IntNoise2DInRange(a_GridX + 30, a_GridZ, m_MinFloorHeightEdge, m_MaxFloorHeightEdge); float FloorHeightEdge2 = m_Noise.IntNoise2DInRange(a_GridX + 40, a_GridZ, m_MinFloorHeightEdge, m_MaxFloorHeightEdge); float FloorHeightCenter = m_Noise.IntNoise2DInRange(a_GridX + 50, a_GridZ, m_MinFloorHeightCenter, m_MaxFloorHeightCenter); float CeilingHeightEdge1 = m_Noise.IntNoise2DInRange(a_GridX + 60, a_GridZ, m_MinCeilingHeightEdge, m_MaxCeilingHeightEdge); float CeilingHeightEdge2 = m_Noise.IntNoise2DInRange(a_GridX + 70, a_GridZ, m_MinCeilingHeightEdge, m_MaxCeilingHeightEdge); float CeilingHeightCenter = m_Noise.IntNoise2DInRange(a_GridX + 80, a_GridZ, m_MinCeilingHeightCenter, m_MaxCeilingHeightCenter); // Create a ravine: return cStructurePtr(new cRoughRavine( m_Seed, Size, CenterWidth, Roughness, FloorHeightEdge1, FloorHeightEdge2, FloorHeightCenter, CeilingHeightEdge1, CeilingHeightEdge2, CeilingHeightCenter, a_GridX, a_GridZ, a_OriginX, a_OriginZ )); } ================================================ FILE: src/Generating/RoughRavines.h ================================================ // RoughRavines.h // Declares the cRoughRavines class representing the rough ravine generator #pragma once #include "GridStructGen.h" class cRoughRavines: public cGridStructGen { using Super = cGridStructGen; public: cRoughRavines( int a_Seed, int a_MaxSize, int a_MinSize, float a_MaxCenterWidth, float a_MinCenterWidth, float a_MaxRoughness, float a_MinRoughness, float a_MaxFloorHeightEdge, float a_MinFloorHeightEdge, float a_MaxFloorHeightCenter, float a_MinFloorHeightCenter, float a_MaxCeilingHeightEdge, float a_MinCeilingHeightEdge, float a_MaxCeilingHeightCenter, float a_MinCeilingHeightCenter, int a_GridSize, int a_MaxOffset ); protected: /** Maximum size of the ravine, in each of the X / Z axis */ int m_MaxSize; /** Minimum size of the ravine */ int m_MinSize; /** Maximum width of the ravine's center, in blocks */ float m_MaxCenterWidth; /** Minimum width of the ravine's center, in blocks */ float m_MinCenterWidth; /** Maximum roughness of the ravine */ float m_MaxRoughness; /** Minimum roughness of the ravine */ float m_MinRoughness; /** Maximum floor height at the ravine's edge */ float m_MaxFloorHeightEdge; /** Minimum floor height at the ravine's edge */ float m_MinFloorHeightEdge; /** Maximum floor height at the ravine's center */ float m_MaxFloorHeightCenter; /** Minimum floor height at the ravine's center */ float m_MinFloorHeightCenter; /** Maximum ceiling height at the ravine's edge */ float m_MaxCeilingHeightEdge; /** Minimum ceiling height at the ravine's edge */ float m_MinCeilingHeightEdge; /** Maximum ceiling height at the ravine's center */ float m_MaxCeilingHeightCenter; /** Minimum ceiling height at the ravine's center */ float m_MinCeilingHeightCenter; // cGridStructGen overrides: virtual cStructurePtr CreateStructure(int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ) override; }; ================================================ FILE: src/Generating/ShapeGen.cpp ================================================ // ShapeGen.cpp // Implements the function to create a cTerrainShapeGen descendant based on INI file settings #include "Globals.h" #include "HeiGen.h" #include "../IniFile.h" #include "DistortedHeightmap.h" #include "EndGen.h" #include "Noise3DGenerator.h" #include "TwoHeights.h" //////////////////////////////////////////////////////////////////////////////// // cTerrainHeightToShapeGen: /** Converts old-style height-generators into new-style shape-generators. */ class cTerrainHeightToShapeGen: public cTerrainShapeGen { public: cTerrainHeightToShapeGen(std::unique_ptr a_HeightGen): m_HeightGen(std::move(a_HeightGen)) { } // cTerrainShapeGen overrides: virtual void GenShape(cChunkCoords a_ChunkCoords, cChunkDesc::Shape & a_Shape) override { // Generate the heightmap: cChunkDef::HeightMap heightMap; m_HeightGen->GenHeightMap(a_ChunkCoords, heightMap); // Convert from heightmap to shape: for (int z = 0; z < cChunkDef::Width; z++) { for (int x = 0; x < cChunkDef::Width; x++) { int height = cChunkDef::GetHeight(heightMap, x, z) + 1; Byte * shapeColumn = &(a_Shape[(x + 16 * z) * 256]); for (int y = 0; y < height; y++) { shapeColumn[y] = 1; } for (int y = height; y < cChunkDef::Height; y++) { shapeColumn[y] = 0; } } // for x } // for z } virtual void InitializeShapeGen(cIniFile & a_IniFile) override { m_HeightGen->InitializeHeightGen(a_IniFile); } protected: /** The height generator being converted. */ std::unique_ptr m_HeightGen; }; typedef std::shared_ptr cTerrainHeightToShapeGenPtr; //////////////////////////////////////////////////////////////////////////////// // cTerrainShapeGen: std::unique_ptr cTerrainShapeGen::CreateShapeGen( cIniFile & a_IniFile, cBiomeGen & a_BiomeGen, int a_Seed, bool & a_CacheOffByDefault ) { AString shapeGenName = a_IniFile.GetValue("Generator", "ShapeGen"); if (shapeGenName.empty()) { LOGWARN("[Generator] ShapeGen value not set in world.ini, using \"BiomalNoise3D\"."); shapeGenName = "BiomalNoise3D"; } // If the shapegen is HeightMap, redirect to older HeightMap-based generators: if (NoCaseCompare(shapeGenName, "HeightMap") == 0) { auto heightGen = cTerrainHeightGen::CreateHeightGen(a_IniFile, a_BiomeGen, a_Seed, a_CacheOffByDefault); if (heightGen != nullptr) { return std::make_unique(std::move(heightGen)); } // The height gen was not recognized; several heightgens were promoted to shape gens, so let's try them instead: shapeGenName = a_IniFile.GetValue("Generator", "HeightGen", ""); if (shapeGenName.empty()) { LOGWARNING("[Generator] ShapeGen set to HeightMap, but HeightGen not set. Reverting to \"BiomalNoise3D\"."); shapeGenName = "BiomalNoise3D"; a_IniFile.SetValue("Generator", "ShapeGen", shapeGenName); } } // Choose the shape generator based on the name: a_CacheOffByDefault = false; std::unique_ptr res; if (NoCaseCompare(shapeGenName, "DistortedHeightmap") == 0) { res = std::make_unique(a_Seed, a_BiomeGen); } else if (NoCaseCompare(shapeGenName, "End") == 0) { res = std::make_unique(a_Seed); } else if (NoCaseCompare(shapeGenName, "BiomalNoise3D") == 0) { res = std::make_unique(a_Seed, a_BiomeGen); } else if (NoCaseCompare(shapeGenName, "Noise3D") == 0) { res = std::make_unique(a_Seed); } else if (NoCaseCompare(shapeGenName, "TwoHeights") == 0) { res = CreateShapeGenTwoHeights(a_Seed, a_BiomeGen); } else { // No match found, force-set the default and retry LOGWARN("Unknown ShapeGen \"%s\", using \"BiomalNoise3D\" instead.", shapeGenName.c_str()); a_IniFile.SetValue("Generator", "ShapeGen", "BiomalNoise3D"); return CreateShapeGen(a_IniFile, a_BiomeGen, a_Seed, a_CacheOffByDefault); } // Read the settings: res->InitializeShapeGen(a_IniFile); return res; } ================================================ FILE: src/Generating/SinglePieceStructuresGen.cpp ================================================ #include "SinglePieceStructuresGen.h" #include "PrefabStructure.h" #include "../IniFile.h" #include "../Item.h" //////////////////////////////////////////////////////////////////////////////// // cSinglePieceStructuresGen::cGen class cSinglePieceStructuresGen::cGen : public cGridStructGen { using Super = cGridStructGen; public: cGen(int a_Seed, cBiomeGen & a_BiomeGen, cTerrainHeightGen & a_HeightGen, int a_SeaLevel, const AString & a_Name): Super(a_Seed), m_BiomeGen(a_BiomeGen), m_HeightGen(a_HeightGen), m_SeaLevel(a_SeaLevel), m_Name(a_Name) { } /** Loads the piecepool from a file. Returns true on success, logs warning and returns false on failure. */ bool LoadFromFile(const AString & a_FileName) { m_PiecePool.Clear(); // Load the piecepool from the file, log any warnings: if (!m_PiecePool.LoadFromFile(a_FileName, true)) { return false; } if (NoCaseCompare(m_PiecePool.GetIntendedUse(), "SinglePieceStructures") != 0) { LOGWARNING("SinglePieceStructures generator: File %s is intended for use in \"%s\", rather than single piece structures. Loading the file, but the generator may behave unexpectedly.", a_FileName.c_str(), m_PiecePool.GetIntendedUse().c_str() ); } m_PiecePool.AssignGens(m_Seed, m_BiomeGen, m_HeightGen, m_SeaLevel); // Apply generator params from the piecepool (in the metadata) into the generator: auto & generatorParams = m_PiecePool.GetAllMetadata(); SetGeneratorParams(generatorParams); return true; } // cGridStructGen override virtual cStructurePtr CreateStructure(int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ) override { // Generate the biomes for the chunk surrounding the origin: int ChunkX, ChunkZ; cChunkDef::BlockToChunk(a_OriginX, a_OriginZ, ChunkX, ChunkZ); cChunkDef::BiomeMap Biomes; m_BiomeGen.GenBiomes({ChunkX, ChunkZ}, Biomes); // Checks if the biome at the origin position is allowed auto Relative = cChunkDef::AbsoluteToRelative(Vector3i(a_OriginX, 1, a_OriginZ), {ChunkX, ChunkZ}); if (!m_PiecePool.IsBiomeAllowed(Biomes[Relative.x + cChunkDef::Width * Relative.z])) { return cStructurePtr(); } cPlacedPieces OutPiece; OutPiece.push_back(GetPiece(a_OriginX, a_OriginZ)); return std::make_shared(a_GridX, a_GridZ, a_OriginX, a_OriginZ, std::move(OutPiece), m_HeightGen); } /** Determines which piece to place from the piece pool */ cPlacedPiecePtr GetPiece(int a_BlockX, int a_BlockZ) { int rnd = m_Noise.IntNoise2DInt(a_BlockX, a_BlockZ) / 7; // Choose a random one of the starting pieces: cPieces StartingPieces = m_PiecePool.GetStartingPieces(); int Total = 0; for (cPieces::const_iterator itr = StartingPieces.begin(), end = StartingPieces.end(); itr != end; ++itr) { Total += m_PiecePool.GetStartingPieceWeight(**itr); } cPiece * StartingPiece; if (Total > 0) { int Chosen = rnd % Total; StartingPiece = StartingPieces.front(); for (cPieces::const_iterator itr = StartingPieces.begin(), end = StartingPieces.end(); itr != end; ++itr) { Chosen -= m_PiecePool.GetStartingPieceWeight(**itr); if (Chosen <= 0) { StartingPiece = *itr; break; } } } else { // All pieces returned zero weight, but we need one to start. Choose with equal chance: StartingPiece = StartingPieces[static_cast(rnd) % StartingPieces.size()]; } rnd = rnd >> 16; // Choose a random supported rotation: int Rotations[4] = {0}; int NumRotations = 1; for (size_t i = 1; i < ARRAYCOUNT(Rotations); i++) { if (StartingPiece->CanRotateCCW(static_cast(i))) { Rotations[NumRotations] = static_cast(i); NumRotations += 1; } } int Rotation = Rotations[rnd % NumRotations]; int BlockY = StartingPiece->GetStartingPieceHeight(a_BlockX, a_BlockZ); ASSERT(BlockY >= 0); // The vertical strategy should have been provided and should give valid coords cPlacedPiece * Piece = new cPlacedPiece(nullptr, *StartingPiece, Vector3i(a_BlockX, BlockY, a_BlockZ), Rotation); return cPlacedPiecePtr(Piece); } protected: /** The underlying biome generator that defines whether the structure is created or not */ cBiomeGen & m_BiomeGen; /** The underlying height generator, used to position the prefabs crossing chunk borders if they are set to FitGround. */ cTerrainHeightGen & m_HeightGen; /** The world's sea level, if available. Used for some cVerticalStrategy descendants. */ int m_SeaLevel; /** The name that is used for reporting. */ AString m_Name; /** All available prefabs. */ cPrefabPiecePool m_PiecePool; }; //////////////////////////////////////////////////////////////////////////////// // cSinglePieceStructuresGen cSinglePieceStructuresGen::cSinglePieceStructuresGen(int a_Seed) : m_Seed(a_Seed) { } bool cSinglePieceStructuresGen::Initialize(const AString & a_Prefabs, int a_SeaLevel, cBiomeGen & a_BiomeGen, cTerrainHeightGen & a_HeightGen) { // Load each piecepool: auto Structures = StringSplitAndTrim(a_Prefabs, "|"); for (const auto & S: Structures) { auto FileName = fmt::format(FMT_STRING("Prefabs{0}SinglePieceStructures{0}{1}.cubeset"), cFile::PathSeparator(), S); if (!cFile::IsFile(FileName)) { FileName.append(".gz"); if (!cFile::IsFile(FileName)) { LOGWARNING("Cannot load SinglePieceStructure cubeset file %s", FileName); continue; } } auto Gen = std::make_shared(m_Seed, a_BiomeGen, a_HeightGen, a_SeaLevel, S); if (Gen->LoadFromFile(FileName)) { m_Gens.push_back(Gen); } } // Report a warning if no generators available: if (m_Gens.empty()) { LOGWARNING("The PieceStructures generator was asked to generate \"%s\", but none of the prefabs are valid.", a_Prefabs); return false; } return true; } void cSinglePieceStructuresGen::GenFinish(cChunkDesc & a_Chunk) { for (auto & Gen: m_Gens) { Gen->GenFinish(a_Chunk); } } ================================================ FILE: src/Generating/SinglePieceStructuresGen.h ================================================ // PrefabSingleStructureGen.h /* Classes to support the generation of single piece prefab structures */ #pragma once #include "Globals.h" #include "ComposableGenerator.h" #include "PrefabPiecePool.h" /** The Single Prefab Structure Generator: This uses the cGridStructGen to generate the structures on the map This is similar to the Piece Structure Generator but only placing one possible structure The Exported cubeset MUST have all possible structures as start structures or the server crashes on generation else it isn't accessible from the m_Piecepool. */ class cSinglePieceStructuresGen : public cFinishGen { using Super = cFinishGen; public: cSinglePieceStructuresGen(int a_Seed); /** Initializes the generator based on the specified prefab sets. a_Prefabs contains the list of prefab sets that should be activated, "|"-separated. All problems are logged to the console and the generator skips over them. Returns true if at least one prefab set is valid (the generator should be kept). */ bool Initialize(const AString & a_Prefabs, int a_SeaLevel, cBiomeGen & a_BiomeGen, cTerrainHeightGen & a_HeightGen); // cFinishGen override: virtual void GenFinish(cChunkDesc & a_ChunkDesc) override; protected: /** The generator doing the work for a single prefab set. Forward-declared so that its implementation changes don't affect the header. */ class cGen; typedef std::shared_ptr cGenPtr; typedef std::vector cGenPtrs; /** The individual structure generators, one per piecepool. */ cGenPtrs m_Gens; /** The seed for the random number generator */ int m_Seed; }; ================================================ FILE: src/Generating/StructGen.cpp ================================================ // StructGen.h #include "Globals.h" #include "StructGen.h" #include "Trees.h" #include "../BlockArea.h" #include "../LinearUpscale.h" #include "../BlockInfo.h" //////////////////////////////////////////////////////////////////////////////// // cStructGenTrees: void cStructGenTrees::GenFinish(cChunkDesc & a_ChunkDesc) { int ChunkX = a_ChunkDesc.GetChunkX(); int ChunkZ = a_ChunkDesc.GetChunkZ(); cChunkDesc WorkerDesc({ChunkX, ChunkZ}); // Generate trees: for (int x = 0; x <= 2; x++) { int BaseX = ChunkX + x - 1; for (int z = 0; z <= 2; z++) { int BaseZ = ChunkZ + z - 1; cChunkDesc * Dest; if ((x != 1) || (z != 1)) { Dest = &WorkerDesc; WorkerDesc.SetChunkCoords({BaseX, BaseZ}); // TODO: This may cause a lot of wasted calculations, instead of pulling data out of a single (cChunkDesc) cache cChunkDesc::Shape workerShape; m_BiomeGen.GenBiomes ({BaseX, BaseZ}, WorkerDesc.GetBiomeMap()); m_ShapeGen.GenShape ({BaseX, BaseZ}, workerShape); WorkerDesc.SetHeightFromShape (workerShape); m_CompositionGen.ComposeTerrain(WorkerDesc, workerShape); } else { Dest = &a_ChunkDesc; } double NumTrees = GetNumTrees(BaseX, BaseZ, Dest->GetBiomeMap()); sSetBlockVector OutsideLogs, OutsideOther; if (NumTrees < 1) { Vector3i Pos; Pos.x = (m_Noise.IntNoise3DInt(BaseX + BaseZ, BaseZ, 0) / 19) % cChunkDef::Width; Pos.z = (m_Noise.IntNoise3DInt(BaseX - BaseZ, 0, BaseZ) / 19) % cChunkDef::Width; Pos.y = Dest->GetHeight(Pos.x, Pos.z); if (std::abs(m_Noise.IntNoise3D(BaseX * cChunkDef::Width + Pos.x, Pos.y, BaseZ * cChunkDef::Width + Pos.z)) <= NumTrees) { GenerateSingleTree(BaseX, BaseZ, 0, Pos, *Dest, OutsideLogs, OutsideOther); } } else { for (int i = 0; i < NumTrees; i++) { Vector3i Pos; Pos.x = (m_Noise.IntNoise3DInt(BaseX + BaseZ, BaseZ, i) / 19) % cChunkDef::Width; Pos.z = (m_Noise.IntNoise3DInt(BaseX - BaseZ, i, BaseZ) / 19) % cChunkDef::Width; Pos.y = Dest->GetHeight(Pos.x, Pos.z); GenerateSingleTree(BaseX, BaseZ, i, Pos, *Dest, OutsideLogs, OutsideOther); } } sSetBlockVector IgnoredOverflow; IgnoredOverflow.reserve(OutsideOther.size()); ApplyTreeImage(ChunkX, ChunkZ, a_ChunkDesc, OutsideOther, IgnoredOverflow); IgnoredOverflow.clear(); IgnoredOverflow.reserve(OutsideLogs.size()); ApplyTreeImage(ChunkX, ChunkZ, a_ChunkDesc, OutsideLogs, IgnoredOverflow); } // for z } // for x a_ChunkDesc.UpdateHeightmap(); } void cStructGenTrees::GenerateSingleTree( int a_ChunkX, int a_ChunkZ, int a_Seq, Vector3i a_Pos, cChunkDesc & a_ChunkDesc, sSetBlockVector & a_OutsideLogs, sSetBlockVector & a_OutsideOther ) { if ((a_Pos.y <= 0) || (a_Pos.y >= 230)) { return; } // Check the block underneath the tree: BLOCKTYPE TopBlock = a_ChunkDesc.GetBlockType(a_Pos.x, a_Pos.y, a_Pos.z); if ((TopBlock != E_BLOCK_DIRT) && (TopBlock != E_BLOCK_GRASS) && (TopBlock != E_BLOCK_FARMLAND) && (TopBlock != E_BLOCK_MYCELIUM)) { return; } sSetBlockVector TreeLogs, TreeOther; GetTreeImageByBiome( { a_ChunkX * cChunkDef::Width + a_Pos.x, a_Pos.y + 1, a_ChunkZ * cChunkDef::Width + a_Pos.z }, m_Noise, a_Seq, a_ChunkDesc.GetBiome(a_Pos.x, a_Pos.z), TreeLogs, TreeOther ); // Check if the generated image fits the terrain. Only the logs are checked: for (sSetBlockVector::const_iterator itr = TreeLogs.begin(); itr != TreeLogs.end(); ++itr) { if ((itr->m_ChunkX != a_ChunkX) || (itr->m_ChunkZ != a_ChunkZ)) { // Outside the chunk continue; } if (itr->m_RelY >= cChunkDef::Height) { // Above the chunk, cut off (this shouldn't happen too often, we're limiting trees to y < 230) continue; } BLOCKTYPE Block = a_ChunkDesc.GetBlockType(itr->m_RelX, itr->m_RelY, itr->m_RelZ); switch (Block) { CASE_TREE_ALLOWED_BLOCKS: { break; } default: { // There's something in the way, abort this tree altogether return; } } } ApplyTreeImage(a_ChunkX, a_ChunkZ, a_ChunkDesc, TreeOther, a_OutsideOther); ApplyTreeImage(a_ChunkX, a_ChunkZ, a_ChunkDesc, TreeLogs, a_OutsideLogs); } void cStructGenTrees::ApplyTreeImage( int a_ChunkX, int a_ChunkZ, cChunkDesc & a_ChunkDesc, const sSetBlockVector & a_Image, sSetBlockVector & a_Overflow ) { // Put the generated image into a_BlockTypes, push things outside this chunk into a_Blocks for (sSetBlockVector::const_iterator itr = a_Image.begin(), end = a_Image.end(); itr != end; ++itr) { if ((itr->m_ChunkX == a_ChunkX) && (itr->m_ChunkZ == a_ChunkZ) && (itr->m_RelY < cChunkDef::Height)) { // Inside this chunk, integrate into a_ChunkDesc: switch (a_ChunkDesc.GetBlockType(itr->m_RelX, itr->m_RelY, itr->m_RelZ)) { case E_BLOCK_NEW_LEAVES: case E_BLOCK_LEAVES: case E_BLOCK_HUGE_BROWN_MUSHROOM: case E_BLOCK_HUGE_RED_MUSHROOM: { if ((itr->m_BlockType != E_BLOCK_LOG) && (itr->m_BlockType != E_BLOCK_NEW_LOG)) { break; } // fallthrough: } CASE_TREE_OVERWRITTEN_BLOCKS: { a_ChunkDesc.SetBlockTypeMeta(itr->m_RelX, itr->m_RelY, itr->m_RelZ, itr->m_BlockType, itr->m_BlockMeta); // If grass is below our tree, turn it to dirt if ( (cBlockInfo::IsSolid(itr->m_BlockType)) && (a_ChunkDesc.GetBlockType(itr->m_RelX, itr->m_RelY - 1, itr->m_RelZ) == E_BLOCK_GRASS) ) { a_ChunkDesc.SetBlockType(itr->m_RelX, itr->m_RelY - 1, itr->m_RelZ, E_BLOCK_DIRT); } break; } } // switch (GetBlock()) continue; } // Outside the chunk, push into a_Overflow. // Don't check if already present there, by separating logs and others we don't need the checks anymore: a_Overflow.push_back(*itr); } } double cStructGenTrees::GetNumTrees( int a_ChunkX, int a_ChunkZ, const cChunkDef::BiomeMap & a_Biomes ) { auto BiomeTrees = [](EMCSBiome a_Biome) { switch (a_Biome) { case biOcean: return 2.0; case biPlains: return 0.03125; case biDesert: return 0.0; case biExtremeHills: return 3.0; case biForest: return 30.0; case biTaiga: return 30.0; case biSwampland: return 8.0; case biRiver: return 0.0; case biNether: return 0.0; case biEnd: return 0.0; case biFrozenOcean: return 0.0; case biFrozenRiver: return 0.0; case biIcePlains: return 0.03125; case biIceMountains: return 0.125; case biMushroomIsland: return 3.0; case biMushroomShore: return 3.0; case biBeach: return 0.0; case biDesertHills: return 0.0; case biForestHills: return 20.0; case biTaigaHills: return 20.0; case biExtremeHillsEdge: return 5.0; case biJungle: return 120.0; case biJungleHills: return 90.0; case biJungleEdge: return 90.0; case biDeepOcean: return 0.0; case biStoneBeach: return 0.0; case biColdBeach: return 0.0; case biBirchForest: return 30.0; case biBirchForestHills: return 20.0; case biRoofedForest: return 50.0; case biColdTaiga: return 20.0; case biColdTaigaHills: return 15.0; case biMegaTaiga: return 15.0; case biMegaTaigaHills: return 15.0; case biExtremeHillsPlus: return 3.0; case biSavanna: return 8.0; case biSavannaPlateau: return 12.0; case biMesa: return 2.0; case biMesaPlateauF: return 8.0; case biMesaPlateau: return 8.0; // Biome variants case biSunflowerPlains: return 0.03125; case biDesertM: return 0.0; case biExtremeHillsM: return 4.0; case biFlowerForest: return 2.0; case biTaigaM: return 30.0; case biSwamplandM: return 8.0; case biIcePlainsSpikes: return 0.0078125; case biJungleM: return 120.0; case biJungleEdgeM: return 90.0; case biBirchForestM: return 30.0; case biBirchForestHillsM: return 20.0; case biRoofedForestM: return 40.0; case biColdTaigaM: return 30.0; case biMegaSpruceTaiga: return 15.0; case biMegaSpruceTaigaHills: return 15.0; case biExtremeHillsPlusM: return 4.0; case biSavannaM: return 8.0; case biSavannaPlateauM: return 12.0; case biMesaBryce: return 4.0; case biMesaPlateauFM: return 12.0; case biMesaPlateauM: return 12.0; // Non-biomes case biInvalidBiome: case biNumBiomes: case biVariant: case biNumVariantBiomes: { break; } } UNREACHABLE("Unsupported biome"); }; double NumTrees = 0.0; for (auto Biome : a_Biomes) { NumTrees += BiomeTrees(Biome); } return NumTrees / (cChunkDef::Width * cChunkDef::Width * 4); } //////////////////////////////////////////////////////////////////////////////// // cStructGenLakes: void cStructGenLakes::GenFinish(cChunkDesc & a_ChunkDesc) { int ChunkX = a_ChunkDesc.GetChunkX(); int ChunkZ = a_ChunkDesc.GetChunkZ(); for (int z = -1; z < 2; z++) for (int x = -1; x < 2; x++) { if (((m_Noise.IntNoise2DInt(ChunkX + x, ChunkZ + z) / 17) % 100) > m_Probability) { continue; } cBlockArea Lake; CreateLakeImage(ChunkX + x, ChunkZ + z, a_ChunkDesc.GetMinHeight(), Lake); int OfsX = Lake.GetOriginX() + x * cChunkDef::Width; int OfsZ = Lake.GetOriginZ() + z * cChunkDef::Width; // Merge the lake into the current data a_ChunkDesc.WriteBlockArea(Lake, OfsX, Lake.GetOriginY(), OfsZ, cBlockArea::msLake); } // for x, z - neighbor chunks } void cStructGenLakes::CreateLakeImage(int a_ChunkX, int a_ChunkZ, int a_MaxLakeHeight, cBlockArea & a_Lake) { a_Lake.Create(16, 8, 16); a_Lake.Fill(cBlockArea::baTypes, E_BLOCK_SPONGE); // Sponge is the NOP blocktype for lake merging strategy // Make a random position in the chunk by using a random 16 block XZ offset and random height up to chunk's max height minus 6 int MinHeight = std::max(a_MaxLakeHeight - 6, 2); int Rnd = m_Noise.IntNoise3DInt(a_ChunkX, 128, a_ChunkZ) / 11; // Random offset [-8 .. 8], with higher probability around 0; add up four three-bit-wide randoms [0 .. 28], divide and subtract to get range int OffsetX = 4 * ((Rnd & 0x07) + ((Rnd & 0x38) >> 3) + ((Rnd & 0x1c0) >> 6) + ((Rnd & 0xe00) >> 9)) / 7 - 8; Rnd >>= 12; // Random offset [-8 .. 8], with higher probability around 0; add up four three-bit-wide randoms [0 .. 28], divide and subtract to get range int OffsetZ = 4 * ((Rnd & 0x07) + ((Rnd & 0x38) >> 3) + ((Rnd & 0x1c0) >> 6) + ((Rnd & 0xe00) >> 9)) / 7 - 8; Rnd = m_Noise.IntNoise3DInt(a_ChunkX, 512, a_ChunkZ) / 13; // Random height [1 .. MinHeight] with preference to center heights int HeightY = 1 + (((Rnd & 0x1ff) % MinHeight) + (((Rnd >> 9) & 0x1ff) % MinHeight)) / 2; a_Lake.SetOrigin(OffsetX, HeightY, OffsetZ); // Hollow out a few bubbles inside the blockarea: int NumBubbles = 4 + ((Rnd >> 18) & 0x03); // 4 .. 7 bubbles BLOCKTYPE * BlockTypes = a_Lake.GetBlockTypes(); for (int i = 0; i < NumBubbles; i++) { int BubbleRnd = m_Noise.IntNoise3DInt(a_ChunkX, i, a_ChunkZ) / 13; const int BubbleR = 2 + (BubbleRnd & 0x03); // 2 .. 5 const int Range = 16 - 2 * BubbleR; const int BubbleX = BubbleR + (BubbleRnd % Range); BubbleRnd >>= 4; const int BubbleY = 4 + (BubbleRnd & 0x01); // 4 .. 5 BubbleRnd >>= 1; const int BubbleZ = BubbleR + (BubbleRnd % Range); const int HalfR = BubbleR / 2; // 1 .. 2 const int RSquared = BubbleR * BubbleR; for (int y = -HalfR; y <= HalfR; y++) { // BubbleY + y is in the [0, 7] bounds int DistY = 4 * y * y / 3; int IdxY = (BubbleY + y) * 16 * 16; for (int z = -BubbleR; z <= BubbleR; z++) { int DistYZ = DistY + z * z; if (DistYZ >= RSquared) { continue; } int IdxYZ = BubbleX + IdxY + (BubbleZ + z) * 16; for (int x = -BubbleR; x <= BubbleR; x++) { if (x * x + DistYZ < RSquared) { BlockTypes[x + IdxYZ] = E_BLOCK_AIR; } } // for x } // for z } // for y } // for i - bubbles // Turn air in the bottom half into liquid: for (int y = 0; y < 4; y++) { for (int z = 0; z < 16; z++) for (int x = 0; x < 16; x++) { if (BlockTypes[x + z * 16 + y * 16 * 16] == E_BLOCK_AIR) { BlockTypes[x + z * 16 + y * 16 * 16] = m_Fluid; } } // for z, x } // for y // TODO: Turn sponge next to lava into stone // a_Lake.SaveToSchematicFile(fmt::format(FMT_STRING("Lake_{}_{}.schematic"), a_ChunkX, a_ChunkZ)); } //////////////////////////////////////////////////////////////////////////////// // cStructGenDirectOverhangs: cStructGenDirectOverhangs::cStructGenDirectOverhangs(int a_Seed) : m_Noise1(a_Seed), m_Noise2(a_Seed + 1000) { } void cStructGenDirectOverhangs::GenFinish(cChunkDesc & a_ChunkDesc) { // If there is no column of the wanted biome, bail out: if (!HasWantedBiome(a_ChunkDesc)) { return; } HEIGHTTYPE MaxHeight = a_ChunkDesc.GetMaxHeight(); const int SEGMENT_HEIGHT = 8; const int INTERPOL_X = 16; // Must be a divisor of 16 const int INTERPOL_Z = 16; // Must be a divisor of 16 // Interpolate the chunk in 16 * SEGMENT_HEIGHT * 16 "segments", each SEGMENT_HEIGHT blocks high and each linearly interpolated separately. // Have two buffers, one for the lowest floor and one for the highest floor, so that Y-interpolation can be done between them // Then swap the buffers and use the previously-top one as the current-bottom, without recalculating it. int FloorBuf1[17 * 17]; int FloorBuf2[17 * 17]; int * FloorHi = FloorBuf1; int * FloorLo = FloorBuf2; int BaseX = a_ChunkDesc.GetChunkX() * cChunkDef::Width; int BaseZ = a_ChunkDesc.GetChunkZ() * cChunkDef::Width; int BaseY = 63; // Interpolate the lowest floor: for (int z = 0; z <= 16 / INTERPOL_Z; z++) for (int x = 0; x <= 16 / INTERPOL_X; x++) { FloorLo[INTERPOL_X * x + 17 * INTERPOL_Z * z] = m_Noise1.IntNoise3DInt(BaseX + INTERPOL_X * x, BaseY, BaseZ + INTERPOL_Z * z) * m_Noise2.IntNoise3DInt(BaseX + INTERPOL_X * x, BaseY, BaseZ + INTERPOL_Z * z) / 256; } // for x, z - FloorLo[] LinearUpscale2DArrayInPlace<17, 17, INTERPOL_X, INTERPOL_Z>(FloorLo); // Interpolate segments: for (int Segment = BaseY; Segment < MaxHeight; Segment += SEGMENT_HEIGHT) { // First update the high floor: for (int z = 0; z <= 16 / INTERPOL_Z; z++) for (int x = 0; x <= 16 / INTERPOL_X; x++) { FloorHi[INTERPOL_X * x + 17 * INTERPOL_Z * z] = ( m_Noise1.IntNoise3DInt(BaseX + INTERPOL_X * x, Segment + SEGMENT_HEIGHT, BaseZ + INTERPOL_Z * z) * m_Noise2.IntNoise3DInt(BaseX + INTERPOL_Z * x, Segment + SEGMENT_HEIGHT, BaseZ + INTERPOL_Z * z) / 256 ); } // for x, z - FloorLo[] LinearUpscale2DArrayInPlace<17, 17, INTERPOL_X, INTERPOL_Z>(FloorHi); // Interpolate between FloorLo and FloorHi: for (int z = 0; z < 16; z++) for (int x = 0; x < 16; x++) { EMCSBiome biome = a_ChunkDesc.GetBiome(x, z); if ((biome == biExtremeHills) || (biome == biExtremeHillsEdge)) { int Lo = FloorLo[x + 17 * z] / 256; int Hi = FloorHi[x + 17 * z] / 256; for (int y = 0; y < SEGMENT_HEIGHT; y++) { int Val = Lo + (Hi - Lo) * y / SEGMENT_HEIGHT; if (Val < 0) { a_ChunkDesc.SetBlockType(x, y + Segment, z, E_BLOCK_AIR); } } // for y break; } // if (biome) } // for z, x // Swap the floors: std::swap(FloorLo, FloorHi); } } bool cStructGenDirectOverhangs::HasWantedBiome(cChunkDesc & a_ChunkDesc) const { cChunkDef::BiomeMap & Biomes = a_ChunkDesc.GetBiomeMap(); for (size_t i = 0; i < ARRAYCOUNT(Biomes); i++) { switch (Biomes[i]) { case biExtremeHills: case biExtremeHillsEdge: { return true; } default: { break; } } } // for i return false; } //////////////////////////////////////////////////////////////////////////////// // cStructGenDistortedMembraneOverhangs: cStructGenDistortedMembraneOverhangs::cStructGenDistortedMembraneOverhangs(int a_Seed) : m_NoiseX(a_Seed + 1000), m_NoiseY(a_Seed + 2000), m_NoiseZ(a_Seed + 3000), m_NoiseH(a_Seed + 4000) { } void cStructGenDistortedMembraneOverhangs::GenFinish(cChunkDesc & a_ChunkDesc) { const NOISE_DATATYPE Frequency = static_cast(16); const NOISE_DATATYPE Amount = static_cast(1); for (int y = 50; y < 128; y++) { NOISE_DATATYPE NoiseY = static_cast(y) / 32; // TODO: proper water level - where to get? BLOCKTYPE ReplacementBlock = (y > 62) ? E_BLOCK_AIR : E_BLOCK_STATIONARY_WATER; for (int z = 0; z < cChunkDef::Width; z++) { NOISE_DATATYPE NoiseZ = static_cast(a_ChunkDesc.GetChunkZ() * cChunkDef::Width + z) / Frequency; for (int x = 0; x < cChunkDef::Width; x++) { NOISE_DATATYPE NoiseX = static_cast(a_ChunkDesc.GetChunkX() * cChunkDef::Width + x) / Frequency; NOISE_DATATYPE DistortX = m_NoiseX.CubicNoise3D(NoiseX, NoiseY, NoiseZ) * Amount; NOISE_DATATYPE DistortY = m_NoiseY.CubicNoise3D(NoiseX, NoiseY, NoiseZ) * Amount; NOISE_DATATYPE DistortZ = m_NoiseZ.CubicNoise3D(NoiseX, NoiseY, NoiseZ) * Amount; int MembraneHeight = 96 - static_cast((DistortY + m_NoiseH.CubicNoise2D(NoiseX + DistortX, NoiseZ + DistortZ)) * 30); if (MembraneHeight < y) { a_ChunkDesc.SetBlockType(x, y, z, ReplacementBlock); } } // for y } // for x } // for z } ================================================ FILE: src/Generating/StructGen.h ================================================ // StructGen.h /* Interfaces to the various structure generators: - cStructGenTrees - cStructGenMarbleCaves - cStructGenOres */ #pragma once #include "ComposableGenerator.h" #include "../Noise/Noise.h" class cStructGenTrees : public cFinishGen { public: cStructGenTrees(int a_Seed, cBiomeGen & a_BiomeGen, cTerrainShapeGen & a_ShapeGen, cTerrainCompositionGen & a_CompositionGen) : m_Seed(a_Seed), m_Noise(a_Seed), m_BiomeGen(a_BiomeGen), m_ShapeGen(a_ShapeGen), m_CompositionGen(a_CompositionGen) {} protected: int m_Seed; cNoise m_Noise; cBiomeGen & m_BiomeGen; cTerrainShapeGen & m_ShapeGen; cTerrainCompositionGen & m_CompositionGen; /** Generates and applies an image of a single tree. Parts of the tree inside the chunk are applied to a_ChunkDesc. Parts of the tree outside the chunk are stored in a_OutsideXYZ */ void GenerateSingleTree( int a_ChunkX, int a_ChunkZ, int a_Seq, Vector3i a_Pos, cChunkDesc & a_ChunkDesc, sSetBlockVector & a_OutsideLogs, sSetBlockVector & a_OutsideOther ) ; /** Applies an image into chunk blockdata; all blocks outside the chunk will be appended to a_Overflow. */ void ApplyTreeImage( int a_ChunkX, int a_ChunkZ, cChunkDesc & a_ChunkDesc, const sSetBlockVector & a_Image, sSetBlockVector & a_Overflow ); /** Get the the number of trees to generate in a_Chunk If the value is between 0 and 1, it should be interpreted as the probability that a tree should be generated. */ double GetNumTrees( int a_ChunkX, int a_ChunkZ, const cChunkDef::BiomeMap & a_Biomes ); // cFinishGen override: virtual void GenFinish(cChunkDesc & a_ChunkDesc) override; } ; class cStructGenLakes : public cFinishGen { public: cStructGenLakes(int a_Seed, BLOCKTYPE a_Fluid, cTerrainShapeGen & a_ShapeGen, int a_Probability) : m_Noise(a_Seed), m_Seed(a_Seed), m_Fluid(a_Fluid), m_ShapeGen(a_ShapeGen), m_Probability(a_Probability) { } protected: cNoise m_Noise; int m_Seed; BLOCKTYPE m_Fluid; cTerrainShapeGen & m_ShapeGen; /** Chance, [0 .. 100], of a chunk having the lake. */ int m_Probability; // cFinishGen override: virtual void GenFinish(cChunkDesc & a_ChunkDesc) override; /** Creates a lake image for the specified chunk into a_Lake. */ void CreateLakeImage(int a_ChunkX, int a_ChunkZ, int a_MaxLakeHeight, cBlockArea & a_Lake); } ; class cStructGenDirectOverhangs : public cFinishGen { public: cStructGenDirectOverhangs(int a_Seed); protected: cNoise m_Noise1; cNoise m_Noise2; // cFinishGen override: virtual void GenFinish(cChunkDesc & a_ChunkDesc) override; bool HasWantedBiome(cChunkDesc & a_ChunkDesc) const; } ; class cStructGenDistortedMembraneOverhangs : public cFinishGen { public: cStructGenDistortedMembraneOverhangs(int a_Seed); protected: cNoise m_NoiseX; cNoise m_NoiseY; cNoise m_NoiseZ; cNoise m_NoiseH; // cFinishGen override: virtual void GenFinish(cChunkDesc & a_ChunkDesc) override; } ; ================================================ FILE: src/Generating/Trees.cpp ================================================ // Trees.cpp // Implements helper functions used for generating trees #include "Globals.h" #include "Trees.h" #include "../BlockType.h" #include "../World.h" typedef struct { int x, z; } sCoords; typedef struct { int x, z; NIBBLETYPE Meta; } sMetaCoords; static const sCoords Corners[] = { {-1, -1}, {-1, 1}, {1, -1}, {1, 1}, } ; /** Chooses a direction for a branch to go to based on the start position (a_BlockPos) and a_Seq. */ static const Vector3d & pickBranchDirection(const cNoise a_Noise, Vector3i a_BlockPos, int a_Seq) { static const std::array directions = { { { -1, 0, 0 }, { 0, 0, -1 }, { -1, 0, 1 }, { -1, 0, -1 }, { 1, 0, 1 }, { 1, 0, -1 }, { 1, 0, 0 }, { 0, 0, 1 }, { -0.5, 0, 0 }, { 0, 0, -0.5 }, { -0.5, 0, 0.5 }, { -0.5, 0, -0.5 }, { 0.5, 0, 0.5 }, { 0.5, 0, -0.5 }, { 0.5, 0, 0 }, { 0, 0, 0.5 }, { -1, 0.5, 0 }, { 0, 0.5, -1 }, { -1, 0.5, 1 }, { -1, 0.5, -1 }, { 1, 0.5, 1 }, { 1, 0.5, -1 }, { 1, 0.5, 0 }, { 0, 0.5, 1 }, { -0.5, 0.5, 0 }, { 0, 0.5, -0.5 }, { -0.5, 0.5, 0.5 }, { -0.5, 0.5, -0.5 }, { 0.5, 0.5, 0.5 }, { 0.5, 0.5, -0.5 }, { 0.5, 0.5, 0 }, { 0, 0.5, 0.5 }, } }; size_t index = static_cast(a_Noise.IntNoise3DInt(a_BlockPos * a_Seq)) % directions.size(); return directions[index]; } // BigO = a big ring of blocks, used for generating horz slices of treetops, the number indicates the radius static const sCoords BigO1[] = { /* -1 */ {0, -1}, /* 0 */ {-1, 0}, {1, 0}, /* 1 */ {0, 1}, } ; static const sCoords BigO2[] = { /* -2 */ {-1, -2}, {0, -2}, {1, -2}, /* -1 */ {-2, -1}, {-1, -1}, {0, -1}, {1, -1}, {2, -1}, /* 0 */ {-2, 0}, {-1, 0}, {1, 0}, {2, 0}, /* 1 */ {-2, 1}, {-1, 1}, {0, 1}, {1, 1}, {2, 1}, /* 2 */ {-1, 2}, {0, 2}, {1, 2}, } ; static const sCoords BigO3[] = { /* -3 */ {-2, -3}, {-1, -3}, {0, -3}, {1, -3}, {2, -3}, /* -2 */ {-3, -2}, {-2, -2}, {-1, -2}, {0, -2}, {1, -2}, {2, -2}, {3, -2}, /* -1 */ {-3, -1}, {-2, -1}, {-1, -1}, {0, -1}, {1, -1}, {2, -1}, {3, -1}, /* 0 */ {-3, 0}, {-2, 0}, {-1, 0}, {1, 0}, {2, 0}, {3, 0}, /* 1 */ {-3, 1}, {-2, 1}, {-1, 1}, {0, 1}, {1, 1}, {2, 1}, {3, 1}, /* 2 */ {-3, 2}, {-2, 2}, {-1, 2}, {0, 2}, {1, 2}, {2, 2}, {3, 2}, /* 3 */ {-2, 3}, {-1, 3}, {0, 3}, {1, 3}, {2, 3}, } ; static const sCoords BigO4[] = // Part of dark oak tree { /* -4 */ {-2, -4}, {-1, -4}, {0, -4}, {1, -4}, {2, -4}, /* -3 */ {-3, -3}, {-2, -3}, {-1, -3}, {0, -3}, {1, -3}, {2, -3}, {3, -3}, /* -2 */ {-4, -2}, {-3, -2}, {-2, -2}, {-1, -2}, {0, -2}, {1, -2}, {2, -2}, {3, -2}, {4, -2}, /* -1 */ {-4, -1}, {-3, -1}, {-2, -1}, {-1, -1}, {0, -1}, {1, -1}, {2, -1}, {3, -1}, {4, -1}, /* 0 */ {-4, 0}, {-3, 0}, {-2, 0}, {-1, 0}, {1, 0}, {2, 0}, {3, 0}, {4, 0}, /* 1 */ {-4, 1}, {-3, 1}, {-2, 1}, {-1, 1}, {0, 1}, {1, 1}, {2, 1}, {3, 1}, {4, 1}, /* 2 */ {-4, 2}, {-3, 2}, {-2, 2}, {-1, 2}, {0, 2}, {1, 2}, {2, 2}, {3, 2}, {4, 2}, /* 3 */ {-3, 3}, {-2, 3}, {-1, 3}, {0, 3}, {1, 3}, {2, 3}, {3, 3}, /* 4 */ {-2, 4}, {-1, 4}, {0, 4}, {1, 4}, {2, 4}, }; static const sCoords BigO3Jungle[] = { /* -3 */ {0, -3}, {1, -3}, /* -2 */ {-1, -2}, {0, -2}, {1, -2}, {2, -2}, /* -1 */ {-2, -1}, {-1, -1}, {0, -1}, {1, -1}, {2, -1}, {3, -1}, /* 0 */ {-3, 0}, {-2, 0}, {-1, 0}, {0, 0}, {1, 0}, {2, 0}, {3, 0}, {4, 0}, /* 1 */ {-3, 1}, {-2, 1}, {-1, 1}, {0, 1}, {1, 1}, {2, 1}, {3, 1}, {4, 1}, /* 2 */ {-2, 2}, {-1, 2}, {0, 2}, {1, 2}, {2, 2}, {3, 2}, /* 3 */ {-1, 3}, {0, 3}, {1, 3}, {2, 3}, /* 4 */ {0, 4}, {1, 4}, }; static const sCoords BigO4Jungle[] = { /* -4 */ {0, -4}, {1, -4}, /* -3 */ {-2, -3}, {-1, -3}, {0, -3}, {1, -3}, {2, -3}, {3, -3}, /* -2 */ {-3, -2}, {-2, -2}, {-1, -2}, {0, -2}, {1, -2}, {2, -2}, {3, -2}, {4, -2}, /* -1 */ {-3, -1}, {-2, -1}, {-1, -1}, {0, -1}, {1, -1}, {2, -1}, {3, -1}, {4, -1}, /* 0 */ {-4, 0}, {-3, 0}, {-2, 0}, {-1, 0}, {2, 0}, {3, 0}, {4, 0}, {5, 0}, /* 1 */ {-4, 1}, {-3, 1}, {-2, 1}, {-1, 1}, {2, 1}, {3, 1}, {4, 1}, {5, 1}, /* 2 */ {-3, 2}, {-2, 2}, {-1, 2}, {0, 2}, {1, 2}, {2, 2}, {3, 2}, {4, 2}, /* 3 */ {-3, 3}, {-2, 3}, {-1, 3}, {0, 3}, {1, 3}, {2, 3}, {3, 3}, {4, 3}, /* 4 */ {-2, 4}, {-1, 4}, {0, 4}, {1, 4}, {2, 4}, {3, 4}, /* 5 */ {0, 5}, {1, 5}, }; static const sCoords BigO5Jungle[] = { /* -5 */ {0, -5}, {1, -5}, /* -4 */ {-2, -4}, {-1, -4}, {0, -4}, {1, -4}, {2, -4}, {3, -4}, /* -3 */ {-3, -3}, {-2, -3}, {-1, -3}, {0, -3}, {1, -3}, {2, -3}, {3, -3}, {4, -3}, /* -2 */ {-4, -2}, {-3, -2}, {-2, -2}, {-1, -2}, {0, -2}, {1, -2}, {2, -2}, {3, -2}, {4, -2}, {5, -2}, /* -1 */ {-4, -1}, {-3, -1}, {-2, -1}, {-1, -1}, {0, -1}, {1, -1}, {2, -1}, {3, -1}, {4, -1}, {5, -1}, /* 0 */ {-5, 0}, {-4, 0}, {-3, 0}, {-2, 0}, {-1, 0}, {2, 0}, {3, 0}, {4, 0}, {5, 0}, {6, 0}, /* 1 */ {-5, 1}, {-4, 1}, {-3, 1}, {-2, 1}, {-1, 1}, {2, 1}, {3, 1}, {4, 1}, {5, 1}, {6, 1}, /* 2 */ {-4, 2}, {-3, 2}, {-2, 2}, {-1, 2}, {0, 2}, {1, 2}, {2, 2}, {3, 2}, {4, 2}, {5, 2}, /* 3 */ {-4, 3}, {-3, 3}, {-2, 3}, {-1, 3}, {0, 3}, {1, 3}, {2, 3}, {3, 3}, {4, 3}, {5, 3}, /* 4 */ {-3, 4}, {-2, 4}, {-1, 4}, {0, 4}, {1, 4}, {2, 4}, {3, 4}, {4, 4}, /* 5 */ {-2, 5}, {-1, 5}, {0, 5}, {1, 5}, {2, 5}, {3, 5}, /* 6 */ {0, 6}, {1, 6}, } ; static const sCoords TopLargePine[] = { /* 0 */ {0, 0}, {1, 0}, /* 1 */ {0, 1}, {1, 1}, } ; static const sCoords BigOF2Pine[] = { /* -1 */ {0, -1}, {1, -1}, /* 0 */ {-1, 0}, {0, 0}, {1, 0}, {2, 0}, /* 1 */ {-1, 1}, {0, 1}, {1, 1}, {2, 1}, /* 2 */ {0, 2}, {1, 2}, } ; static const sCoords BigO2Pine[] = { /* -2 */ {0, -2}, {1, -2}, /* -1 */ {-1, -1}, {0, -1}, {1, -1}, {2, -1}, /* 0 */ {-2, 0}, {-1, 0}, {2, 0}, {3, 0}, /* 1 */ {-2, 1}, {-1, 1}, {2, 1}, {3, 1}, /* 2 */ {-1, 2}, {0, 2}, {1, 2}, {2, 2}, /* 3 */ {0, 3}, {1, 3}, } ; static const sCoords BigO3Pine[] = { /* -3 */ {0, -3}, {1, -3}, /* -2 */ {-1, -2}, {0, -2}, {1, -2}, {2, -2}, /* -1 */ {-2, -1}, {-1, -1}, {0, -1}, {1, -1}, {2, -1}, {3, -1}, /* 0 */ {-3, 0}, {-2, 0}, {-1, 0}, {2, 0}, {3, 0}, {4, 0}, /* 1 */ {-3, 1}, {-2, 1}, {-1, 1}, {2, 1}, {3, 1}, {4, 1}, /* 2 */ {-2, 2}, {-1, 2}, {0, 2}, {1, 2}, {2, 2}, {3, 2}, /* 3 */ {-1, 3}, {0, 3}, {1, 3}, {2, 3}, /* 4 */ {0, 4}, {1, 4}, }; static const sCoords BigO1Spruce[] = { /* -1 */ {0, -1}, {1, -1}, /* 0 */ {-1, 0}, {2, 0}, /* 1 */ {-1, 1}, {2, 1}, /* 2 */ {0, 2}, {1, 2}, } ; typedef struct { const sCoords * Coords; size_t Count; } sCoordsArr; static const sCoordsArr BigOLayers[] = { {BigO1, ARRAYCOUNT(BigO1)}, {BigO2, ARRAYCOUNT(BigO2)}, {BigO3, ARRAYCOUNT(BigO3)}, {BigO4, ARRAYCOUNT(BigO4)}, } ; static const sCoordsArr BigOJungleLayers[] = { {BigO5Jungle, ARRAYCOUNT(BigO5Jungle)}, {BigO4Jungle, ARRAYCOUNT(BigO4Jungle)}, {BigO3Jungle, ARRAYCOUNT(BigO3Jungle)}, }; static const sCoordsArr BigOPineLayers[] = { {BigO3Pine, ARRAYCOUNT(BigO3Pine)}, {BigO2Pine, ARRAYCOUNT(BigO2Pine)}, {BigOF2Pine, ARRAYCOUNT(BigOF2Pine)}, {TopLargePine, ARRAYCOUNT(TopLargePine)}, }; static const sCoordsArr BigOSpruceLayersV1[] = { {BigO1Spruce, ARRAYCOUNT(BigO1Spruce)}, {nullptr, 0}, }; static const sCoordsArr BigOSpruceLayersV2[] = { {BigO2Pine, ARRAYCOUNT(BigO2Pine)}, {BigO1Spruce, ARRAYCOUNT(BigO1Spruce)}, }; static const sCoordsArr BigOSpruceLayersV3[] = { {BigO3Pine, ARRAYCOUNT(BigO3Pine)}, {BigO2Pine, ARRAYCOUNT(BigO2Pine)}, }; static const sCoordsArr BigOSpruceLayersV4[] = { {BigO4Jungle, ARRAYCOUNT(BigO4Jungle)}, {BigO3Pine, ARRAYCOUNT(BigO3Pine)}, }; static const sCoordsArr BigOSpruceTop[] = { {BigO1Spruce, ARRAYCOUNT(BigO1Spruce)}, {TopLargePine, ARRAYCOUNT(TopLargePine)}, }; /** Pushes a specified layer of blocks of the same type around (x, h, z) into a_Blocks */ inline void PushCoordBlocks(int a_BlockX, int a_Height, int a_BlockZ, sSetBlockVector & a_Blocks, const sCoords * a_Coords, size_t a_NumCoords, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) { for (size_t i = 0; i < a_NumCoords; i++) { a_Blocks.emplace_back(a_BlockX + a_Coords[i].x, a_Height, a_BlockZ + a_Coords[i].z, a_BlockType, a_Meta); } } inline void PushCornerBlocks(int a_BlockX, int a_Height, int a_BlockZ, int a_Seq, cNoise & a_Noise, int a_Chance, sSetBlockVector & a_Blocks, int a_CornersDist, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) { for (size_t i = 0; i < ARRAYCOUNT(Corners); i++) { int x = a_BlockX + Corners[i].x; int z = a_BlockZ + Corners[i].z; if (a_Noise.IntNoise3DInt(x + 64 * a_Seq, a_Height, z + 64 * a_Seq) <= a_Chance) { a_Blocks.emplace_back(x, a_Height, z, a_BlockType, a_Meta); } } // for i - Corners[] } inline void PushSomeColumns(int a_BlockX, int a_Height, int a_BlockZ, int a_ColumnHeight, int a_Seq, cNoise & a_Noise, int a_Chance, sSetBlockVector & a_Blocks, const sMetaCoords * a_Coords, size_t a_NumCoords, BLOCKTYPE a_BlockType) { for (size_t i = 0; i < a_NumCoords; i++) { int x = a_BlockX + a_Coords[i].x; int z = a_BlockZ + a_Coords[i].z; if (a_Noise.IntNoise3DInt(x + 64 * a_Seq, a_Height + static_cast(i), z + 64 * a_Seq) <= a_Chance) { for (int j = 0; j < a_ColumnHeight; j++) { a_Blocks.emplace_back(x, a_Height - j, z, a_BlockType, a_Coords[i].Meta); } } } // for i - a_Coords[] } void GetTreeImageByBiome(Vector3i a_BlockPos, cNoise & a_Noise, int a_Seq, EMCSBiome a_Biome, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks) { switch (a_Biome) { case biPlains: case biForest: case biForestHills: case biSunflowerPlains: case biFlowerForest: case biDeepOcean: case biStoneBeach: case biColdBeach: { // Apple or birch trees: if (a_Noise.IntNoise3DInt(a_BlockPos.addedY(16 * a_Seq).addedZ(16 * a_Seq)) < 0x5fffffff) { GetAppleTreeImage(a_BlockPos, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks); } else { GetBirchTreeImage(a_BlockPos, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks); } return; } case biColdTaiga: case biColdTaigaM: case biColdTaigaHills: case biIcePlains: case biIceMountains: case biTaiga: case biTaigaHills: case biTaigaM: { // Conifers GetConiferTreeImage(a_BlockPos, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks, false); return; } case biSwamplandM: case biSwampland: { // Swamp trees: GetSwampTreeImage(a_BlockPos, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks); return; } case biJungle: case biJungleHills: case biJungleEdge: case biJungleM: case biJungleEdgeM: { // Apple bushes, large jungle trees, small jungle trees if (a_Noise.IntNoise3DInt(a_BlockPos.addedY(16 * a_Seq).addedZ(16 * a_Seq)) < 0x6fffffff) { GetAppleBushImage(a_BlockPos, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks); } else { bool IsLarge = a_Noise.IntNoise3DInt(a_BlockPos.addedX(32 * a_Seq).addedY(32 * a_Seq)) < 0x60000000; GetJungleTreeImage(a_BlockPos, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks, IsLarge); } return; } case biBirchForest: case biBirchForestHills: { GetBirchTreeImage(a_BlockPos, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks); return; } case biBirchForestM: case biBirchForestHillsM: { GetTallBirchTreeImage(a_BlockPos, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks); return; } case biMegaTaiga: case biMegaTaigaHills: { bool IsLarge = a_Noise.IntNoise3DInt(a_BlockPos.addedX(32 * a_Seq).addedY(32 * a_Seq)) < 0x30000000; GetConiferTreeImage(a_BlockPos, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks, IsLarge); return; } case biMegaSpruceTaiga: case biMegaSpruceTaigaHills: { bool IsLarge = a_Noise.IntNoise3DInt(a_BlockPos.addedX(32 * a_Seq).addedY(32 * a_Seq)) < 0x30000000; GetSpruceTreeImage(a_BlockPos, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks, IsLarge); return; } case biExtremeHills: case biExtremeHillsM: case biExtremeHillsEdge: case biExtremeHillsPlus: case biExtremeHillsPlusM: { if (a_Noise.IntNoise3DInt(a_BlockPos.addedY(16 * a_Seq).addedZ(16 * a_Seq)) < 0x6fffffff) { GetConiferTreeImage(a_BlockPos, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks); } else { GetAppleTreeImage(a_BlockPos, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks); } return; } case biSavanna: case biSavannaPlateau: case biSavannaM: case biSavannaPlateauM: { GetAcaciaTreeImage(a_BlockPos, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks); return; } case biRoofedForest: case biRoofedForestM: { // 53 % DarkOak // 23 % SmallAppleTree // 16 % RedMushroom // 4 % BrownMushroom // 4 % Birch const int DarkOakProb = 53; const int SmallAppleTreeProb = DarkOakProb + 23; const int RedMushroomProb = SmallAppleTreeProb + 16; const int BrownMushroomProb = RedMushroomProb + 4; static_assert(BrownMushroomProb + 4 == 100); auto RandomValue = a_Noise.IntNoise3DInt(a_BlockPos.addedY(16 * a_Seq).addedZ(16 * a_Seq)) % 100; if (RandomValue < DarkOakProb) { GetDarkoakTreeImage(a_BlockPos, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks); } else if ((RandomValue >= DarkOakProb) && (RandomValue < SmallAppleTreeProb)) { GetSmallAppleTreeImage(a_BlockPos, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks); } else if ((RandomValue >= SmallAppleTreeProb) && (RandomValue < RedMushroomProb)) { GetRedMushroomTreeImage(a_BlockPos, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks); } else if ((RandomValue >= RedMushroomProb) && (RandomValue < BrownMushroomProb)) { GetBrownMushroomTreeImage(a_BlockPos, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks); } else { GetBirchTreeImage(a_BlockPos, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks); } return; } case biMesa: case biMesaPlateauF: case biMesaPlateau: case biMesaBryce: case biMesaPlateauFM: case biMesaPlateauM: { GetSmallAppleTreeImage(a_BlockPos, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks); return; } case biMushroomIsland: case biMushroomShore: { if (a_Noise.IntNoise3DInt(a_BlockPos.addedY(16 * a_Seq).addedZ(16 * a_Seq)) < 0x6fffffff) { GetBrownMushroomTreeImage(a_BlockPos, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks); } else { GetRedMushroomTreeImage(a_BlockPos, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks); } return; } case biDesert: case biDesertHills: case biDesertM: case biRiver: case biBeach: case biHell: case biSky: case biOcean: case biFrozenOcean: case biFrozenRiver: case biIcePlainsSpikes: case biVariant: case biNumBiomes: case biNumVariantBiomes: case biInvalidBiome: { // These biomes have no trees, or are non-biome members of the enum. return; } } ASSERT(!"Invalid biome type!"); } void GetAppleTreeImage(Vector3i a_BlockPos, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks) { if (a_Noise.IntNoise3DInt(a_BlockPos.addedX(32 * a_Seq).addedY(32 * a_Seq)) < 0x73333333) { GetSmallAppleTreeImage(a_BlockPos, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks); } else { GetLargeAppleTreeImage(a_BlockPos, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks); } } void GetSmallAppleTreeImage(Vector3i a_BlockPos, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks) { /* Small apple tree has: - a top plus (no log) - optional BigO1 + random corners (log) - 2 layers of BigO2 + random corners (log) - 1 to 3 blocks of trunk */ int Random = a_Noise.IntNoise3DInt(a_BlockPos.addedX(64 * a_Seq)) >> 3; HEIGHTTYPE Heights[] = {1, 2, 2, 3} ; HEIGHTTYPE Height = 1 + Heights[Random & 3]; Random >>= 2; // Pre-alloc so that we don't realloc too often later: a_LogBlocks.reserve(static_cast(Height + 5)); a_OtherBlocks.reserve(ARRAYCOUNT(BigO2) * 2 + ARRAYCOUNT(BigO1) + ARRAYCOUNT(Corners) * 3 + 3 + 5); // Trunk: for (int i = 0; i < Height; i++) { a_LogBlocks.emplace_back(a_BlockPos.addedY(i), E_BLOCK_LOG, E_META_LOG_APPLE); } int Hei = a_BlockPos.y + Height; // 2 BigO2 + corners layers: for (int i = 0; i < 2; i++) { PushCoordBlocks (a_BlockPos.x, Hei, a_BlockPos.z, a_OtherBlocks, BigO2, ARRAYCOUNT(BigO2), E_BLOCK_LEAVES, E_META_LEAVES_APPLE); PushCornerBlocks(a_BlockPos.x, Hei, a_BlockPos.z, a_Seq, a_Noise, 0x5000000 - i * 0x10000000, a_OtherBlocks, 2, E_BLOCK_LEAVES, E_META_LEAVES_APPLE); a_LogBlocks.emplace_back(a_BlockPos.x, Hei, a_BlockPos.z, E_BLOCK_LOG, E_META_LOG_APPLE); Hei++; } // for i - 2* // Optional BigO1 + corners layer: if ((Random & 1) == 0) { PushCoordBlocks (a_BlockPos.x, Hei, a_BlockPos.z, a_OtherBlocks, BigO1, ARRAYCOUNT(BigO1), E_BLOCK_LEAVES, E_META_LEAVES_APPLE); PushCornerBlocks(a_BlockPos.x, Hei, a_BlockPos.z, a_Seq, a_Noise, 0x6000000, a_OtherBlocks, 1, E_BLOCK_LEAVES, E_META_LEAVES_APPLE); a_LogBlocks.emplace_back(a_BlockPos.x, Hei, a_BlockPos.z, E_BLOCK_LOG, E_META_LOG_APPLE); Hei++; } // Top plus: PushCoordBlocks(a_BlockPos.x, Hei, a_BlockPos.z, a_OtherBlocks, BigO1, ARRAYCOUNT(BigO1), E_BLOCK_LEAVES, E_META_LEAVES_APPLE); a_OtherBlocks.emplace_back(a_BlockPos.x, Hei, a_BlockPos.z, E_BLOCK_LEAVES, E_META_LEAVES_APPLE); } void GetLargeAppleTreeImage(Vector3i a_BlockPos, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks) { int Height = 7 + a_Noise.IntNoise3DInt(a_BlockPos) % 4; // Create branches for (int i = 4; i < Height; i++) { // Get a direction for the trunk to go to. Vector3d BranchStartDirection = pickBranchDirection(a_Noise, a_BlockPos.addedY(i), a_Seq); Vector3d BranchDirection = pickBranchDirection(a_Noise, a_BlockPos.addedY(i * a_Seq), a_Seq) / 3; int BranchLength = 2 + a_Noise.IntNoise3DInt(a_BlockPos * a_Seq) % 3; GetTreeBranch(E_BLOCK_LOG, E_META_LOG_APPLE, a_BlockPos.addedY(i), BranchLength, BranchStartDirection, BranchDirection, a_LogBlocks); } // Place leaves around each log block for (auto itr : a_LogBlocks) { // Get the log's X and Z coordinates int X = itr.GetX(); int Z = itr.GetZ(); a_OtherBlocks.emplace_back(X, itr.m_RelY - 2, Z, E_BLOCK_LEAVES, E_META_LEAVES_APPLE); PushCoordBlocks(X, itr.m_RelY - 2, Z, a_OtherBlocks, BigO1, ARRAYCOUNT(BigO1), E_BLOCK_LEAVES, E_META_LEAVES_APPLE); for (int y = -1; y <= 1; y++) { PushCoordBlocks (X, itr.m_RelY + y, Z, a_OtherBlocks, BigO2, ARRAYCOUNT(BigO2), E_BLOCK_LEAVES, E_META_LEAVES_APPLE); } PushCoordBlocks(X, itr.m_RelY + 2, Z, a_OtherBlocks, BigO1, ARRAYCOUNT(BigO1), E_BLOCK_LEAVES, E_META_LEAVES_APPLE); a_OtherBlocks.emplace_back(X, itr.m_RelY + 2, Z, E_BLOCK_LEAVES, E_META_LEAVES_APPLE); } // Trunk: for (int i = 0; i < Height; i++) { a_LogBlocks.emplace_back(a_BlockPos.addedY(i), E_BLOCK_LOG, E_META_LOG_APPLE); } } Vector3d GetTreeBranch(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_BlockPos, int a_BranchLength, Vector3d a_StartDirection, Vector3d a_Direction, sSetBlockVector & a_LogBlocks) { Vector3d CurrentPos = Vector3d(a_BlockPos); Vector3d Direction = a_StartDirection; for (int i = 0; i < a_BranchLength; i++) { CurrentPos += Direction; Direction += a_Direction; Direction.Clamp(-1.0, 1.0); a_LogBlocks.emplace_back(CurrentPos.Floor(), a_BlockType, GetLogMetaFromDirection(a_BlockMeta, Direction)); } return CurrentPos; } NIBBLETYPE GetLogMetaFromDirection(NIBBLETYPE a_BlockMeta, Vector3d a_Direction) { a_Direction.Abs(); if ((a_Direction.y > a_Direction.x) && (a_Direction.y > a_Direction.z)) { return a_BlockMeta; } else if (a_Direction.x > a_Direction.z) { return a_BlockMeta + 4; } else { return a_BlockMeta + 8; } } void GetBirchTreeImage(Vector3i a_BlockPos, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks) { HEIGHTTYPE Height = 5 + static_cast(a_Noise.IntNoise3DInt(a_BlockPos.addedX(64 * a_Seq)) % 3); // Prealloc, so that we don't realloc too often later: a_LogBlocks.reserve(static_cast(Height)); a_OtherBlocks.reserve(80); // The entire trunk, out of logs: for (int i = Height - 1; i >= 0; --i) { a_LogBlocks.emplace_back(a_BlockPos.addedY(i), E_BLOCK_LOG, E_META_LOG_BIRCH); } int h = a_BlockPos.y + Height; // Top layer - just the Plus: PushCoordBlocks(a_BlockPos.x, h, a_BlockPos.z, a_OtherBlocks, BigO1, ARRAYCOUNT(BigO1), E_BLOCK_LEAVES, E_META_LEAVES_BIRCH); a_OtherBlocks.emplace_back(a_BlockPos.x, h, a_BlockPos.z, E_BLOCK_LEAVES, E_META_LEAVES_BIRCH); // There's no log at this layer h--; // Second layer - log, Plus and maybe Corners: PushCoordBlocks (a_BlockPos.x, h, a_BlockPos.z, a_OtherBlocks, BigO1, ARRAYCOUNT(BigO1), E_BLOCK_LEAVES, E_META_LEAVES_BIRCH); PushCornerBlocks(a_BlockPos.x, h, a_BlockPos.z, a_Seq, a_Noise, 0x5fffffff, a_OtherBlocks, 1, E_BLOCK_LEAVES, E_META_LEAVES_BIRCH); h--; // Third and fourth layers - BigO2 and maybe 2 * Corners: for (int Row = 0; Row < 2; Row++) { PushCoordBlocks (a_BlockPos.x, h, a_BlockPos.z, a_OtherBlocks, BigO2, ARRAYCOUNT(BigO2), E_BLOCK_LEAVES, E_META_LEAVES_BIRCH); PushCornerBlocks(a_BlockPos.x, h, a_BlockPos.z, a_Seq, a_Noise, 0x3fffffff + Row * 0x10000000, a_OtherBlocks, 2, E_BLOCK_LEAVES, E_META_LEAVES_BIRCH); h--; } // for Row - 2* } void GetAcaciaTreeImage(Vector3i a_BlockPos, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks) { // Calculate a base height int Height = 2 + (a_Noise.IntNoise3DInt(a_BlockPos) / 11 % 3); // Create the trunk for (int i = 0; i < Height; i++) { a_LogBlocks.emplace_back(a_BlockPos.addedY(i), E_BLOCK_NEW_LOG, E_META_NEW_LOG_ACACIA_WOOD); } // Array with possible directions for a branch to go to. const Vector3i AvailableDirections[] = { { -1, 1, 0 }, { 0, 1, -1 }, { -1, 1, 1 }, { -1, 1, -1 }, { 1, 1, 1 }, { 1, 1, -1 }, { 1, 1, 0 }, { 0, 1, 1 }, }; // Get a direction for the trunk to go to. Vector3i BranchDirection = AvailableDirections[a_Noise.IntNoise3DInt(a_BlockPos) % 8]; // Calculate a height for the branch between 1 and 3 int BranchHeight = a_Noise.IntNoise3DInt(a_BlockPos) % 3 + 1; Vector3i BranchPos = GetTreeBranch(E_BLOCK_NEW_LOG, E_META_NEW_LOG_ACACIA_WOOD, a_BlockPos.addedY(Height - 1), BranchHeight, Vector3i(BranchDirection), Vector3i(BranchDirection), a_LogBlocks).Floor(); // Add the leaves to the top of the branch PushCoordBlocks(BranchPos.x, BranchPos.y, BranchPos.z, a_OtherBlocks, BigO3, ARRAYCOUNT(BigO3), E_BLOCK_NEW_LEAVES, E_META_NEWLEAVES_ACACIA); PushCoordBlocks(BranchPos.x, BranchPos.y + 1, BranchPos.z, a_OtherBlocks, BigO2, ARRAYCOUNT(BigO2), E_BLOCK_NEW_LEAVES, E_META_NEWLEAVES_ACACIA); a_OtherBlocks.emplace_back(BranchPos.x, BranchPos.y + 1, BranchPos.z, E_BLOCK_NEW_LEAVES, E_META_NEWLEAVES_ACACIA); // Choose if we have to add another branch bool TwoTop = (a_Noise.IntNoise3D(a_BlockPos) < 0); if (!TwoTop) { return; } // Invert the direction of the previous branch. BranchDirection = Vector3d(-BranchDirection.x, 1, -BranchDirection.z); // Calculate a new height for the second branch BranchHeight = a_Noise.IntNoise3DInt(a_BlockPos * a_Seq) % 3 + 1; BranchPos = GetTreeBranch(E_BLOCK_NEW_LOG, E_META_NEW_LOG_ACACIA_WOOD, a_BlockPos.addedY(Height - 1), BranchHeight, BranchDirection, BranchDirection, a_LogBlocks).Floor(); // And add the leaves ontop of the second branch PushCoordBlocks(BranchPos.x, BranchPos.y, BranchPos.z, a_OtherBlocks, BigO3, ARRAYCOUNT(BigO3), E_BLOCK_NEW_LEAVES, E_META_NEWLEAVES_ACACIA); PushCoordBlocks(BranchPos.x, BranchPos.y + 1, BranchPos.z, a_OtherBlocks, BigO2, ARRAYCOUNT(BigO2), E_BLOCK_NEW_LEAVES, E_META_NEWLEAVES_ACACIA); a_OtherBlocks.emplace_back(BranchPos.x, BranchPos.y + 1, BranchPos.z, E_BLOCK_NEW_LEAVES, E_META_NEWLEAVES_ACACIA); } void GetDarkoakTreeImage(Vector3i a_BlockPos, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks) { // Pick a height int Height = 5 + (a_Noise.IntNoise3DInt(a_BlockPos.addedX(32 * a_Seq).addedZ(32 * a_Seq)) / 11) % 4; // Create the trunk for (int i = 0; i < Height; i++) { a_LogBlocks.emplace_back(a_BlockPos.addedY(i), E_BLOCK_NEW_LOG, E_META_NEW_LOG_DARK_OAK_WOOD); a_LogBlocks.emplace_back(a_BlockPos.addedX(1).addedY(i), E_BLOCK_NEW_LOG, E_META_NEW_LOG_DARK_OAK_WOOD); a_LogBlocks.emplace_back(a_BlockPos.addedY(i).addedZ(1), E_BLOCK_NEW_LOG, E_META_NEW_LOG_DARK_OAK_WOOD); a_LogBlocks.emplace_back(a_BlockPos.addedX(1).addedY(i).addedZ(1), E_BLOCK_NEW_LOG, E_META_NEW_LOG_DARK_OAK_WOOD); } // Prevent floating trees by placing dirt under them for (int i = 1; i < 5; i++) { a_OtherBlocks.emplace_back(a_BlockPos.addedY(-i), E_BLOCK_DIRT, E_META_DIRT_NORMAL); a_OtherBlocks.emplace_back(a_BlockPos.addedX(1).addedY(-i), E_BLOCK_DIRT, E_META_DIRT_NORMAL); a_OtherBlocks.emplace_back(a_BlockPos.addedY(-i).addedZ(1), E_BLOCK_DIRT, E_META_DIRT_NORMAL); a_OtherBlocks.emplace_back(a_BlockPos.addedX(1).addedY(-i).addedZ(1), E_BLOCK_DIRT, E_META_DIRT_NORMAL); } // Create branches for (int i = 0; i < 3; i++) { int x = (a_Noise.IntNoise3DInt(a_BlockPos.addedX(32 * a_Seq).addedZ(32 * a_Seq).addedY(i * a_Seq)) % 3) - 1; int z = (a_Noise.IntNoise3DInt(a_BlockPos.addedX(-32 * a_Seq).addedZ(-32 * a_Seq).addedY(i * a_Seq)) % 3) - 1; // The branches would end up in the trunk. if ((x >= a_BlockPos.x) && (x <= a_BlockPos.x + 1) && (z >= a_BlockPos.z) && (z <= a_BlockPos.z + 1)) { NOISE_DATATYPE Val1 = a_Noise.IntNoise2D(x, z); if (Val1 < 0) { x = a_BlockPos.x + ((Val1 < -0.5) ? -1 : 3); } else { z = a_BlockPos.z + ((Val1 < 0.5) ? -1 : 3); } } int y = Height - (a_Noise.IntNoise3DInt(a_BlockPos.addedX(x).addedZ(z).addedY(i * a_Seq)) % (Height - (Height / 4))); for (int Y = y; Y < Height; Y++) { a_LogBlocks.emplace_back(a_BlockPos.addedX(x).addedY(Y).addedZ(z), E_BLOCK_NEW_LOG, E_META_NEW_LOG_DARK_OAK_WOOD); } } int hei = a_BlockPos.y + Height - 2; // The lower two leaves layers are BigO4 with log in the middle and possibly corners: for (int i = 0; i < 2; i++) { PushCoordBlocks(a_BlockPos.x, hei, a_BlockPos.z, a_OtherBlocks, BigO4, ARRAYCOUNT(BigO4), E_BLOCK_NEW_LEAVES, E_META_NEWLEAVES_DARK_OAK); PushCornerBlocks(a_BlockPos.x, hei, a_BlockPos.z, a_Seq, a_Noise, 0x5fffffff, a_OtherBlocks, 3, E_BLOCK_NEW_LEAVES, E_META_NEWLEAVES_DARK_OAK); hei++; } // for i < 2 // The top leaves layer is a BigO3 with leaves in the middle and possibly corners: PushCoordBlocks(a_BlockPos.x, hei, a_BlockPos.z, a_OtherBlocks, BigO3, ARRAYCOUNT(BigO3), E_BLOCK_NEW_LEAVES, E_META_NEWLEAVES_DARK_OAK); PushCornerBlocks(a_BlockPos.x, hei, a_BlockPos.z, a_Seq, a_Noise, 0x5fffffff, a_OtherBlocks, 3, E_BLOCK_NEW_LEAVES, E_META_NEWLEAVES_DARK_OAK); a_OtherBlocks.emplace_back(a_BlockPos.x, hei, a_BlockPos.z, E_BLOCK_NEW_LEAVES, E_META_NEWLEAVES_DARK_OAK); } void GetTallBirchTreeImage(Vector3i a_BlockPos, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks) { HEIGHTTYPE Height = 9 + static_cast(a_Noise.IntNoise3DInt(a_BlockPos.addedX(64 * a_Seq)) % 3); // Prealloc, so that we don't realloc too often later: a_LogBlocks.reserve(static_cast(Height)); a_OtherBlocks.reserve(80); // The entire trunk, out of logs: for (int i = Height - 1; i >= 0; --i) { a_LogBlocks.emplace_back(a_BlockPos.addedY(i), E_BLOCK_LOG, E_META_LOG_BIRCH); } int h = a_BlockPos.y + Height; // Top layer - just the Plus: PushCoordBlocks(a_BlockPos.x, h, a_BlockPos.z, a_OtherBlocks, BigO1, ARRAYCOUNT(BigO1), E_BLOCK_LEAVES, E_META_LEAVES_BIRCH); a_OtherBlocks.emplace_back(a_BlockPos.x, h, a_BlockPos.z, E_BLOCK_LEAVES, E_META_LEAVES_BIRCH); // There's no log at this layer h--; // Second layer - log, Plus and maybe Corners: PushCoordBlocks (a_BlockPos.x, h, a_BlockPos.z, a_OtherBlocks, BigO1, ARRAYCOUNT(BigO1), E_BLOCK_LEAVES, E_META_LEAVES_BIRCH); PushCornerBlocks(a_BlockPos.x, h, a_BlockPos.z, a_Seq, a_Noise, 0x5fffffff, a_OtherBlocks, 1, E_BLOCK_LEAVES, E_META_LEAVES_BIRCH); h--; // Third and fourth layers - BigO2 and maybe 2 * Corners: for (int Row = 0; Row < 2; Row++) { PushCoordBlocks (a_BlockPos.x, h, a_BlockPos.z, a_OtherBlocks, BigO2, ARRAYCOUNT(BigO2), E_BLOCK_LEAVES, E_META_LEAVES_BIRCH); PushCornerBlocks(a_BlockPos.x, h, a_BlockPos.z, a_Seq, a_Noise, 0x3fffffff + Row * 0x10000000, a_OtherBlocks, 2, E_BLOCK_LEAVES, E_META_LEAVES_BIRCH); h--; } // for Row - 2* } void GetConiferTreeImage(Vector3i a_BlockPos, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks, bool a_Large) { // Half chance for a spruce, half for a pine and for the large ones 3 chances for a pine and one for spruce: if (a_Noise.IntNoise3DInt(a_BlockPos.addedX(64 * a_Seq).addedZ(32 * a_Seq)) < (a_Large ? 0x20000000 : 0x40000000)) { GetSpruceTreeImage(a_BlockPos, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks, a_Large); } else { GetPineTreeImage(a_BlockPos, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks, a_Large); } } void GetSpruceTreeImage(Vector3i a_BlockPos, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks, bool a_Large) { if (a_Large) { GetLargeSpruceTreeImage(a_BlockPos, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks); } else { GetSmallSpruceTreeImage(a_BlockPos, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks); } } void GetPineTreeImage(Vector3i a_BlockPos, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks, bool a_Large) { if (a_Large) { GetLargePineTreeImage(a_BlockPos, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks); } else { GetSmallPineTreeImage(a_BlockPos, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks); } } void GetSmallSpruceTreeImage(Vector3i a_BlockPos, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks) { // Spruces have a top section with layer sizes of (0, 1, 0) or only (1, 0), // then 1 - 3 sections of ascending sizes (1, 2) [most often], (1, 3) or (1, 2, 3) // and an optional bottom section of size 1, followed by 1 - 3 clear trunk blocks // We'll use bits from this number as partial random numbers; but the noise function has mod8 irregularities // (each of the mod8 remainders has a very different chance of occurrence) - that's why we divide by 8 int MyRandom = a_Noise.IntNoise3DInt(a_BlockPos.addedX(32 * a_Seq).addedY(32 * a_Seq)) / 8; static const HEIGHTTYPE sHeights[] = {1, 2, 2, 3}; HEIGHTTYPE Height = sHeights[MyRandom & 3]; MyRandom >>= 2; // Prealloc, so that we don't realloc too often later: a_LogBlocks.reserve(static_cast(Height)); a_OtherBlocks.reserve(180); // Clear trunk blocks: for (int i = 0; i < Height; i++) { a_LogBlocks.emplace_back(a_BlockPos.addedY(i), E_BLOCK_LOG, E_META_LOG_CONIFER); } Height += static_cast(a_BlockPos.y); // Optional size-1 bottom leaves layer: if ((MyRandom & 1) == 0) { PushCoordBlocks(a_BlockPos.x, Height, a_BlockPos.z, a_OtherBlocks, BigO1, ARRAYCOUNT(BigO1), E_BLOCK_LEAVES, E_META_LEAVES_CONIFER); a_OtherBlocks.emplace_back(a_BlockPos.x, Height, a_BlockPos.z, E_BLOCK_LOG, E_META_LOG_CONIFER); Height++; } MyRandom >>= 1; // 1 to 3 sections of leaves layers: static const int sNumSections[] = {1, 2, 2, 3}; int NumSections = sNumSections[MyRandom & 3]; MyRandom >>= 2; for (int i = 0; i < NumSections; i++) { switch (MyRandom & 3) // SectionType; (1, 2) twice as often as the other two { case 0: case 1: { PushCoordBlocks(a_BlockPos.x, Height, a_BlockPos.z, a_OtherBlocks, BigO2, ARRAYCOUNT(BigO2), E_BLOCK_LEAVES, E_META_LEAVES_CONIFER); PushCoordBlocks(a_BlockPos.x, Height + 1, a_BlockPos.z, a_OtherBlocks, BigO1, ARRAYCOUNT(BigO1), E_BLOCK_LEAVES, E_META_LEAVES_CONIFER); a_LogBlocks.emplace_back(a_BlockPos.x, Height, a_BlockPos.z, E_BLOCK_LOG, E_META_LOG_CONIFER); a_LogBlocks.emplace_back(a_BlockPos.x, Height + 1, a_BlockPos.z, E_BLOCK_LOG, E_META_LOG_CONIFER); Height += 2; break; } case 2: { PushCoordBlocks(a_BlockPos.x, Height, a_BlockPos.z, a_OtherBlocks, BigO3, ARRAYCOUNT(BigO3), E_BLOCK_LEAVES, E_META_LEAVES_CONIFER); PushCoordBlocks(a_BlockPos.x, Height + 1, a_BlockPos.z, a_OtherBlocks, BigO1, ARRAYCOUNT(BigO1), E_BLOCK_LEAVES, E_META_LEAVES_CONIFER); a_LogBlocks.emplace_back(a_BlockPos.x, Height, a_BlockPos.z, E_BLOCK_LOG, E_META_LOG_CONIFER); a_LogBlocks.emplace_back(a_BlockPos.x, Height + 1, a_BlockPos.z, E_BLOCK_LOG, E_META_LOG_CONIFER); Height += 2; break; } case 3: { PushCoordBlocks(a_BlockPos.x, Height, a_BlockPos.z, a_OtherBlocks, BigO3, ARRAYCOUNT(BigO3), E_BLOCK_LEAVES, E_META_LEAVES_CONIFER); PushCoordBlocks(a_BlockPos.x, Height + 1, a_BlockPos.z, a_OtherBlocks, BigO2, ARRAYCOUNT(BigO2), E_BLOCK_LEAVES, E_META_LEAVES_CONIFER); PushCoordBlocks(a_BlockPos.x, Height + 2, a_BlockPos.z, a_OtherBlocks, BigO1, ARRAYCOUNT(BigO1), E_BLOCK_LEAVES, E_META_LEAVES_CONIFER); a_LogBlocks.emplace_back(a_BlockPos.x, Height, a_BlockPos.z, E_BLOCK_LOG, E_META_LOG_CONIFER); a_LogBlocks.emplace_back(a_BlockPos.x, Height + 1, a_BlockPos.z, E_BLOCK_LOG, E_META_LOG_CONIFER); a_LogBlocks.emplace_back(a_BlockPos.x, Height + 2, a_BlockPos.z, E_BLOCK_LOG, E_META_LOG_CONIFER); Height += 3; break; } } // switch (SectionType) MyRandom >>= 2; } // for i - Sections if ((MyRandom & 1) == 0) { // (0, 1, 0) top: a_LogBlocks.emplace_back (a_BlockPos.x, Height, a_BlockPos.z, E_BLOCK_LOG, E_META_LOG_CONIFER); PushCoordBlocks (a_BlockPos.x, Height + 1, a_BlockPos.z, a_OtherBlocks, BigO1, ARRAYCOUNT(BigO1), E_BLOCK_LEAVES, E_META_LEAVES_CONIFER); a_OtherBlocks.emplace_back(a_BlockPos.x, Height + 1, a_BlockPos.z, E_BLOCK_LEAVES, E_META_LEAVES_CONIFER); a_OtherBlocks.emplace_back(a_BlockPos.x, Height + 2, a_BlockPos.z, E_BLOCK_LEAVES, E_META_LEAVES_CONIFER); } else { // (1, 0) top: a_OtherBlocks.emplace_back(a_BlockPos.x, Height, a_BlockPos.z, E_BLOCK_LEAVES, E_META_LEAVES_CONIFER); PushCoordBlocks (a_BlockPos.x, Height + 1, a_BlockPos.z, a_OtherBlocks, BigO1, ARRAYCOUNT(BigO1), E_BLOCK_LEAVES, E_META_LEAVES_CONIFER); a_OtherBlocks.emplace_back(a_BlockPos.x, Height + 1, a_BlockPos.z, E_BLOCK_LEAVES, E_META_LEAVES_CONIFER); } } static void LargeSpruceAddRing(Vector3i a_BlockPos, int & a_Height, const sCoordsArr* const a_Ring, size_t a_RingCount, sSetBlockVector & a_OtherBlocks) { for (size_t i = 0; i < a_RingCount ; i++) { PushCoordBlocks(a_BlockPos.x, a_Height--, a_BlockPos.z, a_OtherBlocks, a_Ring[a_RingCount - 1 - i].Coords, a_Ring[a_RingCount - 1 - i].Count, E_BLOCK_LEAVES, E_META_LEAVES_CONIFER); } } const int MIN_LARGE_SPRUCE_TREE_RINGS = 3; const int MAX_LARGE_SPRUCE_TREE_RINGS = 11; void GetLargeSpruceTreeImage(Vector3i a_BlockPos, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks) { int Height = 20 + (a_Noise.IntNoise3DInt(a_BlockPos.addedXZ(32 * a_Seq, 32 * a_Seq)) / 11) % 12; int LeavesRingCount = MIN_LARGE_SPRUCE_TREE_RINGS + (a_Noise.IntNoise3DInt(a_BlockPos.addedXZ(32 * a_Seq, 32 * a_Seq)) / 13) % (1 + MAX_LARGE_SPRUCE_TREE_RINGS - MIN_LARGE_SPRUCE_TREE_RINGS); int RingRadius = 0; a_LogBlocks.reserve(static_cast(Height) * 4); a_OtherBlocks.reserve(ARRAYCOUNT(BigO1Spruce) + ARRAYCOUNT(TopLargePine) + MAX_LARGE_SPRUCE_TREE_RINGS * (ARRAYCOUNT(BigO4Jungle) + ARRAYCOUNT(BigO3Pine) + ARRAYCOUNT(BigO2Pine))); for (int i = 0; i < Height; i++) { a_LogBlocks.emplace_back(a_BlockPos.addedY(i), E_BLOCK_LOG, E_META_LOG_CONIFER); a_LogBlocks.emplace_back(a_BlockPos.addedY(i).addedX(1), E_BLOCK_LOG, E_META_LOG_CONIFER); a_LogBlocks.emplace_back(a_BlockPos.addedY(i).addedZ(1), E_BLOCK_LOG, E_META_LOG_CONIFER); a_LogBlocks.emplace_back(a_BlockPos.addedY(i).addedXZ(1, 1), E_BLOCK_LOG, E_META_LOG_CONIFER); } int hei = a_BlockPos.y + Height - 1; // Prevent floating trees by placing dirt under them for (int i = 1; i < 5; i++) { a_OtherBlocks.emplace_back(a_BlockPos.addedY(-i), E_BLOCK_DIRT, E_META_DIRT_NORMAL); a_OtherBlocks.emplace_back(a_BlockPos.addedY(-i).addedX(1), E_BLOCK_DIRT, E_META_DIRT_NORMAL); a_OtherBlocks.emplace_back(a_BlockPos.addedY(-i).addedZ(1), E_BLOCK_DIRT, E_META_DIRT_NORMAL); a_OtherBlocks.emplace_back(a_BlockPos.addedY(-i).addedXZ(1, 1), E_BLOCK_DIRT, E_META_DIRT_NORMAL); } // Place the top. for (size_t i = 0; i < ARRAYCOUNT(BigOSpruceTop); i++) { PushCoordBlocks(a_BlockPos.x, hei++, a_BlockPos.z, a_OtherBlocks, BigOSpruceTop[i].Coords, BigOSpruceTop[i].Count, E_BLOCK_LEAVES, E_META_LEAVES_CONIFER); } hei = a_BlockPos.y + Height - 2; for (int i = 0; i < LeavesRingCount; i++) { unsigned int Val = static_cast(a_Noise.IntNoise3DInt(a_BlockPos.addedXZ(32 * a_Seq, 32 * i)) / 23) % 8; if ((Val < 4) && RingRadius < 3) { RingRadius++; } else if ((Val == 7) && (RingRadius > 0)) { RingRadius--; } switch (RingRadius) { case 0: { LargeSpruceAddRing(a_BlockPos, hei, BigOSpruceLayersV1, ARRAYCOUNT(BigOSpruceLayersV1), a_OtherBlocks); break; } case 1: { LargeSpruceAddRing(a_BlockPos, hei, BigOSpruceLayersV2, ARRAYCOUNT(BigOSpruceLayersV2), a_OtherBlocks); break; } case 2: { LargeSpruceAddRing(a_BlockPos, hei, BigOSpruceLayersV3, ARRAYCOUNT(BigOSpruceLayersV3), a_OtherBlocks); break; } case 3: { LargeSpruceAddRing(a_BlockPos, hei, BigOSpruceLayersV4, ARRAYCOUNT(BigOSpruceLayersV4), a_OtherBlocks); break; } default: { break; } } if (hei - a_BlockPos.y <= 2) { break; } } } void GetSmallPineTreeImage(Vector3i a_BlockPos, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks) { // Tall, little leaves on top. The top leaves are arranged in a shape of two cones joined by their bases. // There can be one or two layers representing the cone bases (SameSizeMax) int MyRandom = a_Noise.IntNoise3DInt(a_BlockPos.addedXZ(32 * a_Seq, 32 * a_Seq)) / 8; int TrunkHeight = 8 + (MyRandom % 3); int SameSizeMax = ((MyRandom & 8) == 0) ? 1 : 0; MyRandom >>= 3; int NumLeavesLayers = 2 + (MyRandom % 3); // Number of layers that have leaves in them if (NumLeavesLayers == 2) { SameSizeMax = 0; } // Pre-allocate the vector: a_LogBlocks.reserve(static_cast(TrunkHeight)); a_OtherBlocks.reserve(static_cast(NumLeavesLayers * 25)); // The entire trunk, out of logs: for (int i = TrunkHeight; i >= 0; --i) { a_LogBlocks.emplace_back(a_BlockPos.addedY(i), E_BLOCK_LOG, E_META_LOG_CONIFER); } int h = a_BlockPos.y + TrunkHeight + 2; // Top layer - just a single leaves block: a_OtherBlocks.emplace_back(a_BlockPos.x, h, a_BlockPos.z, E_BLOCK_LEAVES, E_META_LEAVES_CONIFER); h--; // One more layer is above the trunk, push the central leaves: a_OtherBlocks.emplace_back(a_BlockPos.x, h, a_BlockPos.z, E_BLOCK_LEAVES, E_META_LEAVES_CONIFER); // Layers expanding in size, then collapsing again: // LOGD("Generating %d layers of pine leaves, SameSizeMax = %d", NumLeavesLayers, SameSizeMax); for (int i = 0; i < NumLeavesLayers; ++i) { int LayerSize = std::min(i, NumLeavesLayers - i + SameSizeMax - 1); // LOGD("LayerSize %d: %d", i, LayerSize); if (LayerSize < 0) { break; } ASSERT(static_cast(LayerSize) < ARRAYCOUNT(BigOLayers)); PushCoordBlocks(a_BlockPos.x, h, a_BlockPos.z, a_OtherBlocks, BigOLayers[LayerSize].Coords, BigOLayers[LayerSize].Count, E_BLOCK_LEAVES, E_META_LEAVES_CONIFER); h--; } } void GetLargePineTreeImage(Vector3i a_BlockPos, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks) { int Height = 20 + (a_Noise.IntNoise3DInt(a_BlockPos.addedXZ(32 * a_Seq, 32 * a_Seq)) / 11) % 12; a_LogBlocks.reserve(static_cast(Height) * 4); a_OtherBlocks.reserve(ARRAYCOUNT(BigO3Pine) + ARRAYCOUNT(BigO2Pine) + ARRAYCOUNT(BigOF2Pine) + ARRAYCOUNT(TopLargePine)); for (int i = 0; i < Height; i++) { a_LogBlocks.emplace_back(a_BlockPos.addedY(i), E_BLOCK_LOG, E_META_LOG_CONIFER); a_LogBlocks.emplace_back(a_BlockPos.addedY(i).addedX(1), E_BLOCK_LOG, E_META_LOG_CONIFER); a_LogBlocks.emplace_back(a_BlockPos.addedY(i).addedZ(1), E_BLOCK_LOG, E_META_LOG_CONIFER); a_LogBlocks.emplace_back(a_BlockPos.addedY(i).addedXZ(1, 1), E_BLOCK_LOG, E_META_LOG_CONIFER); } int hei = a_BlockPos.y + Height - 2; // Prevent floating trees by placing dirt under them for (int i = 1; i < 5; i++) { a_OtherBlocks.emplace_back(a_BlockPos.addedY(-i), E_BLOCK_DIRT, E_META_DIRT_NORMAL); a_OtherBlocks.emplace_back(a_BlockPos.addedY(-i).addedX(1), E_BLOCK_DIRT, E_META_DIRT_NORMAL); a_OtherBlocks.emplace_back(a_BlockPos.addedY(-i).addedZ(1), E_BLOCK_DIRT, E_META_DIRT_NORMAL); a_OtherBlocks.emplace_back(a_BlockPos.addedY(-i).addedXZ(1, 1), E_BLOCK_DIRT, E_META_DIRT_NORMAL); } // Place the canopy. for (size_t i = 0; i < ARRAYCOUNT(BigOPineLayers); i++) { PushCoordBlocks(a_BlockPos.x, hei++, a_BlockPos.z, a_OtherBlocks, BigOPineLayers[i].Coords, BigOPineLayers[i].Count, E_BLOCK_LEAVES, E_META_LEAVES_CONIFER); } } void GetSwampTreeImage(Vector3i a_BlockPos, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks) { // Vines are around the BigO3, but not in the corners; need proper meta for direction static const sMetaCoords Vines[] = { {-2, -4, 1}, {-1, -4, 1}, {0, -4, 1}, {1, -4, 1}, {2, -4, 1}, // North face {-2, 4, 4}, {-1, 4, 4}, {0, 4, 4}, {1, 4, 4}, {2, 4, 4}, // South face {4, -2, 2}, {4, -1, 2}, {4, 0, 2}, {4, 1, 2}, {4, 2, 2}, // East face {-4, -2, 8}, {-4, -1, 8}, {-4, 0, 8}, {-4, 1, 8}, {-4, 2, 8}, // West face } ; int Height = 3 + (a_Noise.IntNoise3DInt(a_BlockPos.addedXZ(32 * a_Seq, 32 * a_Seq)) / 8) % 3; a_LogBlocks.reserve(static_cast(Height)); a_OtherBlocks.reserve(2 * ARRAYCOUNT(BigO2) + 2 * ARRAYCOUNT(BigO3) + static_cast(Height) * ARRAYCOUNT(Vines) + 20); for (int i = 0; i < Height; i++) { a_LogBlocks.emplace_back(a_BlockPos.addedY(i), E_BLOCK_LOG, E_META_LOG_APPLE); } int hei = a_BlockPos.y + Height - 2; // Put vines around the lowermost leaves layer: PushSomeColumns(a_BlockPos.x, hei, a_BlockPos.z, Height, a_Seq, a_Noise, 0x3fffffff, a_OtherBlocks, Vines, ARRAYCOUNT(Vines), E_BLOCK_VINES); // The lower two leaves layers are BigO3 with log in the middle and possibly corners: for (int i = 0; i < 2; i++) { PushCoordBlocks(a_BlockPos.x, hei, a_BlockPos.z, a_OtherBlocks, BigO3, ARRAYCOUNT(BigO3), E_BLOCK_LEAVES, E_META_LEAVES_APPLE); PushCornerBlocks(a_BlockPos.x, hei, a_BlockPos.z, a_Seq, a_Noise, 0x5fffffff, a_OtherBlocks, 3, E_BLOCK_LEAVES, E_META_LEAVES_APPLE); hei++; } // for i - 2* // The upper two leaves layers are BigO2 with leaves in the middle and possibly corners: for (int i = 0; i < 2; i++) { PushCoordBlocks(a_BlockPos.x, hei, a_BlockPos.z, a_OtherBlocks, BigO2, ARRAYCOUNT(BigO2), E_BLOCK_LEAVES, E_META_LEAVES_APPLE); PushCornerBlocks(a_BlockPos.x, hei, a_BlockPos.z, a_Seq, a_Noise, 0x5fffffff, a_OtherBlocks, 3, E_BLOCK_LEAVES, E_META_LEAVES_APPLE); a_OtherBlocks.emplace_back(a_BlockPos.x, hei, a_BlockPos.z, E_BLOCK_LEAVES, E_META_LEAVES_APPLE); hei++; } // for i - 2* } void GetAppleBushImage(Vector3i a_BlockPos, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks) { a_OtherBlocks.reserve(3 + ARRAYCOUNT(BigO2) + ARRAYCOUNT(BigO1)); int hei = a_BlockPos.y; a_LogBlocks.emplace_back(a_BlockPos.x, hei, a_BlockPos.z, E_BLOCK_LOG, E_META_LOG_JUNGLE); PushCoordBlocks(a_BlockPos.x, hei, a_BlockPos.z, a_OtherBlocks, BigO2, ARRAYCOUNT(BigO2), E_BLOCK_LEAVES, E_META_LEAVES_APPLE); hei++; a_OtherBlocks.emplace_back(a_BlockPos.x, hei, a_BlockPos.z, E_BLOCK_LEAVES, E_META_LEAVES_APPLE); PushCoordBlocks(a_BlockPos.x, hei, a_BlockPos.z, a_OtherBlocks, BigO1, ARRAYCOUNT(BigO1), E_BLOCK_LEAVES, E_META_LEAVES_APPLE); hei++; a_OtherBlocks.emplace_back(a_BlockPos.x, hei, a_BlockPos.z, E_BLOCK_LEAVES, E_META_LEAVES_APPLE); } void GetJungleTreeImage(Vector3i a_BlockPos, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks, bool a_Large) { if (!a_Large) { GetSmallJungleTreeImage(a_BlockPos, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks); } else { GetLargeJungleTreeImage(a_BlockPos, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks); } } void GetLargeJungleTreeImage(Vector3i a_BlockPos, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks) { static const sMetaCoords VinesTrunk[] = { {0, -1, 1}, {1, -1, 1}, // North face {0, 2, 4}, {1, 2, 4}, // South face {-1, 1, 8}, {-1, 0, 8}, // West face {2, 1, 2}, {2, 0, 2}, // East face }; int Height = 10 + ((a_Noise.IntNoise3DInt(a_BlockPos.addedXZ(32 * a_Seq, 32 * a_Seq)) / 11) % 20); // 10 < Height < 29 a_LogBlocks.reserve(static_cast(Height) * 4); a_OtherBlocks.reserve(2 * ARRAYCOUNT(BigO5Jungle) + ARRAYCOUNT(BigO4Jungle) + ARRAYCOUNT(BigO3Jungle) + static_cast(Height) * 4 + 50); // Generates the main trunk for (int i = 0; i < Height; i++) { a_LogBlocks.emplace_back(a_BlockPos.addedY(i), E_BLOCK_LOG, E_META_LOG_JUNGLE); a_LogBlocks.emplace_back(a_BlockPos.addedY(i).addedX(1), E_BLOCK_LOG, E_META_LOG_JUNGLE); a_LogBlocks.emplace_back(a_BlockPos.addedY(i).addedZ(1), E_BLOCK_LOG, E_META_LOG_JUNGLE); a_LogBlocks.emplace_back(a_BlockPos.addedY(i).addedXZ(1, 1), E_BLOCK_LOG, E_META_LOG_JUNGLE); // Randomly place vines around the trunk for (size_t j = 0; j < ARRAYCOUNT(VinesTrunk); j++) { if (a_Noise.IntNoise3DInt(a_BlockPos.addedXZ(VinesTrunk[j].x, VinesTrunk[j].z).addedY(i)) % 3 != 0) { continue; } a_OtherBlocks.emplace_back(a_BlockPos.addedXZ(VinesTrunk[j].x, VinesTrunk[j].z).addedY(i), E_BLOCK_VINES, VinesTrunk[j].Meta); } } // Prevent floating trees by placing dirt under them for (int i = 1; i < 5; i++) { a_OtherBlocks.emplace_back(a_BlockPos.addedY(-i), E_BLOCK_DIRT, E_META_DIRT_NORMAL); a_OtherBlocks.emplace_back(a_BlockPos.addedY(-i).addedX(1), E_BLOCK_DIRT, E_META_DIRT_NORMAL); a_OtherBlocks.emplace_back(a_BlockPos.addedY(-i).addedZ(1), E_BLOCK_DIRT, E_META_DIRT_NORMAL); a_OtherBlocks.emplace_back(a_BlockPos.addedY(-i).addedXZ(1, 1), E_BLOCK_DIRT, E_META_DIRT_NORMAL); } int NumBranches = std::max( (a_Noise.IntNoise2DInt(a_BlockPos.x * a_Seq, a_BlockPos.z * a_Seq) / 10) % 4, // The Original Calculation FloorC(Height / 10.0f) // Just to assure that no massive trees spawn with just one branch ); int BranchStartHeight = 6 + Height % 5; // 6 < BranchStartHeight < 10 int BranchInterval = (Height - 6 - BranchStartHeight) / NumBranches; for (int i = BranchStartHeight; i < (Height - 6); i += BranchInterval) // Stop 6 blocks before reaching the top { // Get a direction for the trunk to go to. Vector3d BranchStartDirection = pickBranchDirection(a_Noise, a_BlockPos.addedY(i), a_Seq); Vector3d BranchDirection = pickBranchDirection(a_Noise, a_BlockPos.addedY(i * a_Seq), a_Seq) / 3; int BranchLength = 2 + a_Noise.IntNoise3DInt(a_BlockPos * a_Seq) % 2; Vector3i BranchEndPosition = GetTreeBranch(E_BLOCK_LOG, E_META_LOG_JUNGLE, a_BlockPos.addedY(i), BranchLength, BranchStartDirection, BranchDirection, a_LogBlocks).Floor(); // There's a chance that there is a third leaf level on a branch if ((a_Noise.IntNoise3DInt(a_BlockPos.x * a_Seq, a_BlockPos.y * a_Seq, a_BlockPos.z * a_Seq) % 4) == 0) // A quarter chance { PushCoordBlocks(BranchEndPosition.x, BranchEndPosition.y, BranchEndPosition.z, a_OtherBlocks, BigO3, ARRAYCOUNT(BigO3), E_BLOCK_LEAVES, E_META_LEAVES_JUNGLE); PushCoordBlocks(BranchEndPosition.x, BranchEndPosition.y + 1, BranchEndPosition.z, a_OtherBlocks, BigO2, ARRAYCOUNT(BigO2), E_BLOCK_LEAVES, E_META_LEAVES_JUNGLE); PushCoordBlocks(BranchEndPosition.x, BranchEndPosition.y + 2, BranchEndPosition.z, a_OtherBlocks, BigO1, ARRAYCOUNT(BigO1), E_BLOCK_LEAVES, E_META_LEAVES_JUNGLE); a_OtherBlocks.emplace_back(BranchEndPosition.x, BranchEndPosition.y + 2, BranchEndPosition.z, E_BLOCK_LEAVES, E_META_LEAVES_JUNGLE); } else { PushCoordBlocks(BranchEndPosition.x, BranchEndPosition.y, BranchEndPosition.z, a_OtherBlocks, BigO2, ARRAYCOUNT(BigO2), E_BLOCK_LEAVES, E_META_LEAVES_JUNGLE); PushCoordBlocks(BranchEndPosition.x, BranchEndPosition.y + 1, BranchEndPosition.z, a_OtherBlocks, BigO1, ARRAYCOUNT(BigO1), E_BLOCK_LEAVES, E_META_LEAVES_JUNGLE); a_OtherBlocks.emplace_back(BranchEndPosition.x, BranchEndPosition.y + 1, BranchEndPosition.z, E_BLOCK_LEAVES, E_META_LEAVES_JUNGLE); } } // Place the canopy. int CanopyHeight = a_BlockPos.y + Height - 2; for (size_t i = 0; i < ARRAYCOUNT(BigOJungleLayers); i++) { PushCoordBlocks(a_BlockPos.x, CanopyHeight++, a_BlockPos.z, a_OtherBlocks, BigOJungleLayers[i].Coords, BigOJungleLayers[i].Count, E_BLOCK_LEAVES, E_META_LEAVES_JUNGLE); } } void GetSmallJungleTreeImage(Vector3i a_BlockPos, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks) { // Vines are around the BigO3, but not in the corners; need proper meta for direction static const sMetaCoords Vines[] = { {-2, -4, 1}, {-1, -4, 1}, {0, -4, 1}, {1, -4, 1}, {2, -4, 1}, // North face {-2, 4, 4}, {-1, 4, 4}, {0, 4, 4}, {1, 4, 4}, {2, 4, 4}, // South face {4, -2, 2}, {4, -1, 2}, {4, 0, 2}, {4, 1, 2}, {4, 2, 2}, // East face {-4, -2, 8}, {-4, -1, 8}, {-4, 0, 8}, {-4, 1, 8}, // West face // TODO: proper metas and height: {0, 1, 1}, {0, -1, 4}, {-1, 0, 2}, {1, 1, 8}, // Around the tunk } ; int Height = 7 + (a_Noise.IntNoise3DInt(a_BlockPos.addedXZ(5 * a_Seq, 5 * a_Seq)) / 5) % 3; a_LogBlocks.reserve(static_cast(Height)); a_OtherBlocks.reserve( 2 * ARRAYCOUNT(BigO3) + // O3 layer, 2x 2 * ARRAYCOUNT(BigO2) + // O2 layer, 2x ARRAYCOUNT(BigO1) + 1 + // Plus on the top static_cast(Height) * ARRAYCOUNT(Vines) + // Vines 50 // some safety ); for (int i = 0; i < Height; i++) { a_LogBlocks.emplace_back(a_BlockPos.addedY(i), E_BLOCK_LOG, E_META_LOG_JUNGLE); } int hei = a_BlockPos.y + Height - 3; // Put vines around the lowermost leaves layer: PushSomeColumns(a_BlockPos.x, hei, a_BlockPos.z, Height, a_Seq, a_Noise, 0x3fffffff, a_OtherBlocks, Vines, ARRAYCOUNT(Vines), E_BLOCK_VINES); // The lower two leaves layers are BigO3 with log in the middle and possibly corners: for (int i = 0; i < 2; i++) { PushCoordBlocks(a_BlockPos.x, hei, a_BlockPos.z, a_OtherBlocks, BigO3, ARRAYCOUNT(BigO3), E_BLOCK_LEAVES, E_META_LEAVES_JUNGLE); PushCornerBlocks(a_BlockPos.x, hei, a_BlockPos.z, a_Seq, a_Noise, 0x5fffffff, a_OtherBlocks, 3, E_BLOCK_LEAVES, E_META_LEAVES_JUNGLE); hei++; } // for i - 2* // Two layers of BigO2 leaves, possibly with corners: for (int i = 0; i < 1; i++) { PushCoordBlocks(a_BlockPos.x, hei, a_BlockPos.z, a_OtherBlocks, BigO2, ARRAYCOUNT(BigO2), E_BLOCK_LEAVES, E_META_LEAVES_JUNGLE); PushCornerBlocks(a_BlockPos.x, hei, a_BlockPos.z, a_Seq, a_Noise, 0x5fffffff, a_OtherBlocks, 2, E_BLOCK_LEAVES, E_META_LEAVES_JUNGLE); hei++; } // for i - 2* // Top plus, all leaves: PushCoordBlocks(a_BlockPos.x, hei, a_BlockPos.z, a_OtherBlocks, BigO1, ARRAYCOUNT(BigO1), E_BLOCK_LEAVES, E_META_LEAVES_JUNGLE); a_OtherBlocks.emplace_back(a_BlockPos.x, hei, a_BlockPos.z, E_BLOCK_LEAVES, E_META_LEAVES_JUNGLE); } void GetRedMushroomTreeImage(Vector3i a_BlockPos, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks) { static constexpr int Height = 4; for (int i = 0; i < Height; i++) { a_LogBlocks.emplace_back(a_BlockPos.addedY(i), E_BLOCK_HUGE_RED_MUSHROOM, E_META_MUSHROOM_STEM); if (i != 0) { // NORTH SIDE a_LogBlocks.emplace_back(a_BlockPos.addedY(i).addedXZ(-1, -2), E_BLOCK_HUGE_RED_MUSHROOM, E_META_MUSHROOM_NORTH_WEST); a_LogBlocks.emplace_back(a_BlockPos.addedY(i).addedXZ(0, -2), E_BLOCK_HUGE_RED_MUSHROOM, E_META_MUSHROOM_NORTH); a_LogBlocks.emplace_back(a_BlockPos.addedY(i).addedXZ(1, -2), E_BLOCK_HUGE_RED_MUSHROOM, E_META_MUSHROOM_NORTH_EAST); // WEST SIDE a_LogBlocks.emplace_back(a_BlockPos.addedY(i).addedXZ(-2, -1), E_BLOCK_HUGE_RED_MUSHROOM, E_META_MUSHROOM_NORTH_WEST); a_LogBlocks.emplace_back(a_BlockPos.addedY(i).addedXZ(-2, 0), E_BLOCK_HUGE_RED_MUSHROOM, E_META_MUSHROOM_WEST); a_LogBlocks.emplace_back(a_BlockPos.addedY(i).addedXZ(-2, 1), E_BLOCK_HUGE_RED_MUSHROOM, E_META_MUSHROOM_SOUTH_WEST); // SOUTH SIDE a_LogBlocks.emplace_back(a_BlockPos.addedY(i).addedXZ(-1, 2), E_BLOCK_HUGE_RED_MUSHROOM, E_META_MUSHROOM_SOUTH_WEST); a_LogBlocks.emplace_back(a_BlockPos.addedY(i).addedXZ(0, 2), E_BLOCK_HUGE_RED_MUSHROOM, E_META_MUSHROOM_SOUTH); a_LogBlocks.emplace_back(a_BlockPos.addedY(i).addedXZ(1, 2), E_BLOCK_HUGE_RED_MUSHROOM, E_META_MUSHROOM_SOUTH_EAST); // EAST SIDE a_LogBlocks.emplace_back(a_BlockPos.addedY(i).addedXZ(2, -1), E_BLOCK_HUGE_RED_MUSHROOM, E_META_MUSHROOM_NORTH_EAST); a_LogBlocks.emplace_back(a_BlockPos.addedY(i).addedXZ(2, 0), E_BLOCK_HUGE_RED_MUSHROOM, E_META_MUSHROOM_EAST); a_LogBlocks.emplace_back(a_BlockPos.addedY(i).addedXZ(2, 1), E_BLOCK_HUGE_RED_MUSHROOM, E_META_MUSHROOM_SOUTH_EAST); } } // Top Layer a_LogBlocks.emplace_back(a_BlockPos.addedY(Height).addedXZ(-1, -1), E_BLOCK_HUGE_RED_MUSHROOM, E_META_MUSHROOM_NORTH_WEST); a_LogBlocks.emplace_back(a_BlockPos.addedY(Height).addedX(-1), E_BLOCK_HUGE_RED_MUSHROOM, E_META_MUSHROOM_WEST); a_LogBlocks.emplace_back(a_BlockPos.addedY(Height).addedXZ(-1, 1), E_BLOCK_HUGE_RED_MUSHROOM, E_META_MUSHROOM_SOUTH_WEST); a_LogBlocks.emplace_back(a_BlockPos.addedY(Height).addedZ(-1), E_BLOCK_HUGE_RED_MUSHROOM, E_META_MUSHROOM_NORTH); a_LogBlocks.emplace_back(a_BlockPos.addedY(Height), E_BLOCK_HUGE_RED_MUSHROOM, E_META_MUSHROOM_CENTER); a_LogBlocks.emplace_back(a_BlockPos.addedY(Height).addedZ(1), E_BLOCK_HUGE_RED_MUSHROOM, E_META_MUSHROOM_SOUTH); a_LogBlocks.emplace_back(a_BlockPos.addedY(Height).addedXZ(1, -1), E_BLOCK_HUGE_RED_MUSHROOM, E_META_MUSHROOM_NORTH_EAST); a_LogBlocks.emplace_back(a_BlockPos.addedY(Height).addedX(1), E_BLOCK_HUGE_RED_MUSHROOM, E_META_MUSHROOM_EAST); a_LogBlocks.emplace_back(a_BlockPos.addedY(Height).addedXZ(1, 1), E_BLOCK_HUGE_RED_MUSHROOM, E_META_MUSHROOM_SOUTH_EAST); } void GetBrownMushroomTreeImage(Vector3i a_BlockPos, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks) { static constexpr int Height = 4; static constexpr int Radius = 2; static constexpr int Border = 3; for (int i = 0; i < Height; i++) { a_LogBlocks.emplace_back(a_BlockPos.addedY(i), E_BLOCK_HUGE_BROWN_MUSHROOM, E_META_MUSHROOM_STEM); } for (int x = -Radius; x <= Radius; x++) { for (int z = -Radius; z <= Radius; z++) { a_LogBlocks.emplace_back(a_BlockPos.addedY(Height).addedXZ(x, z), E_BLOCK_HUGE_BROWN_MUSHROOM, E_META_MUSHROOM_CENTER); } } for (int i = 0; i < Border; i++) { // NORTH SIDE a_LogBlocks.emplace_back(a_BlockPos.addedY(Height).addedXZ(-1, -3).addedX(i), E_BLOCK_HUGE_BROWN_MUSHROOM, E_META_MUSHROOM_NORTH); // WEST SIDE a_LogBlocks.emplace_back(a_BlockPos.addedY(Height).addedXZ(-3, -1).addedZ(i), E_BLOCK_HUGE_BROWN_MUSHROOM, E_META_MUSHROOM_WEST); // SOUTH SIDE a_LogBlocks.emplace_back(a_BlockPos.addedY(Height).addedXZ(-1, 3).addedX(i), E_BLOCK_HUGE_BROWN_MUSHROOM, E_META_MUSHROOM_SOUTH); // EAST SIDE a_LogBlocks.emplace_back(a_BlockPos.addedY(Height).addedXZ(3, -1).addedZ(i), E_BLOCK_HUGE_BROWN_MUSHROOM, E_META_MUSHROOM_EAST); } // Corners a_LogBlocks.emplace_back(a_BlockPos.addedY(Height).addedXZ(3, 2), E_BLOCK_HUGE_BROWN_MUSHROOM, E_META_MUSHROOM_SOUTH_EAST); a_LogBlocks.emplace_back(a_BlockPos.addedY(Height).addedXZ(2, 3), E_BLOCK_HUGE_BROWN_MUSHROOM, E_META_MUSHROOM_SOUTH_EAST); a_LogBlocks.emplace_back(a_BlockPos.addedY(Height).addedXZ(-2, 3), E_BLOCK_HUGE_BROWN_MUSHROOM, E_META_MUSHROOM_SOUTH_WEST); a_LogBlocks.emplace_back(a_BlockPos.addedY(Height).addedXZ(-3, 2), E_BLOCK_HUGE_BROWN_MUSHROOM, E_META_MUSHROOM_SOUTH_WEST); a_LogBlocks.emplace_back(a_BlockPos.addedY(Height).addedXZ(-2, -3), E_BLOCK_HUGE_BROWN_MUSHROOM, E_META_MUSHROOM_NORTH_WEST); a_LogBlocks.emplace_back(a_BlockPos.addedY(Height).addedXZ(-3, -2), E_BLOCK_HUGE_BROWN_MUSHROOM, E_META_MUSHROOM_NORTH_WEST); a_LogBlocks.emplace_back(a_BlockPos.addedY(Height).addedXZ(2, -3), E_BLOCK_HUGE_BROWN_MUSHROOM, E_META_MUSHROOM_NORTH_EAST); a_LogBlocks.emplace_back(a_BlockPos.addedY(Height).addedXZ(3, -2), E_BLOCK_HUGE_BROWN_MUSHROOM, E_META_MUSHROOM_NORTH_EAST); } ================================================ FILE: src/Generating/Trees.h ================================================ // Trees.h // Interfaces to helper functions used for generating trees /* Note that all of these functions must generate the same tree image for the same input (x, y, z, seq) - cStructGenTrees depends on this To generate a random image for the (x, y, z) coords, pass an arbitrary value as (seq). Each function returns two arrays of blocks, "logs" and "other". The point is that logs are of higher priority, logs can overwrite others(leaves), but others shouldn't overwrite logs. This is an optimization for the generator. */ #pragma once #include "../Noise/Noise.h" #include "../ChunkDef.h" // For sSetBlockVector // Blocks that don't block tree growth: #define CASE_TREE_ALLOWED_BLOCKS \ case E_BLOCK_AIR: \ case E_BLOCK_LEAVES: \ case E_BLOCK_NEW_LEAVES: \ case E_BLOCK_SNOW: \ case E_BLOCK_TALL_GRASS: \ case E_BLOCK_DEAD_BUSH: \ case E_BLOCK_SAPLING: \ case E_BLOCK_VINES // Blocks that a tree may overwrite when growing: #define CASE_TREE_OVERWRITTEN_BLOCKS \ case E_BLOCK_AIR: \ /* case E_BLOCK_LEAVES: LEAVES are a special case, they can be overwritten only by log. Handled in cChunkMap::ReplaceTreeBlocks(). */ \ case E_BLOCK_SNOW: \ case E_BLOCK_TALL_GRASS: \ case E_BLOCK_BIG_FLOWER: \ case E_BLOCK_DEAD_BUSH: \ case E_BLOCK_SAPLING: \ case E_BLOCK_VINES /** Fills a_LogBlocks and a_OtherBlocks (dirt & leaves) with the blocks required to form a tree at the specified coords (lowest trunk block) in the specified biome */ void GetTreeImageByBiome(Vector3i a_BlockPos, cNoise & a_Noise, int a_Seq, EMCSBiome a_Biome, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks); /** Fills a_LogBlocks and a_OtherBlocks (dirt & leaves) with the blocks required to form a random apple tree */ void GetAppleTreeImage(Vector3i a_BlockPos, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks); /** Fills a_LogBlocks and a_OtherBlocks (dirt & leaves) with the blocks required to form a small (nonbranching) apple tree */ void GetSmallAppleTreeImage(Vector3i a_BlockPos, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks); /** Fills a_LogBlocks and a_OtherBlocks (dirt & leaves) with the blocks required to form a large (branching) apple tree */ void GetLargeAppleTreeImage(Vector3i a_BlockPos, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks); /** Fills a_LogBlocks with the logs of a tree branch of the provided log type. The length of the branch can be changed with the a_BranchLength. The initial direction is a_StartDirection. The direction can be manipulated with a_Direction to create a curve. Returns the position of the last log block placed. */ Vector3d GetTreeBranch(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_BlockPos, int a_BranchLength, Vector3d a_StartDirection, Vector3d a_Direction, sSetBlockVector & a_LogBlocks); /** Returns the meta for a log from the given direction */ NIBBLETYPE GetLogMetaFromDirection(NIBBLETYPE a_BlockMeta, Vector3d a_Direction); /** Fills a_LogBlocks and a_OtherBlocks (dirt & leaves) with the blocks required to form a random birch tree */ void GetBirchTreeImage(Vector3i a_BlockPos, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks); /** Fills a_LogBlocks and a_OtherBlocks (dirt & leaves) with the blocks required to form a random acacia tree */ void GetAcaciaTreeImage(Vector3i a_BlockPos, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks); /** Fills a_LogBlocks and a_OtherBlocks (dirt & leaves) with the blocks required to form a random darkoak tree */ void GetDarkoakTreeImage(Vector3i a_BlockPos, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks); /** Fills a_LogBlocks and a_OtherBlocks (dirt & leaves) with the blocks required to form a random large birch tree */ void GetTallBirchTreeImage(Vector3i a_BlockPos, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks); /** Fills a_LogBlocks and a_OtherBlocks (dirt & leaves) with the blocks required to form a random conifer tree. The probability to get a large pine is higher than a spruce tree */ void GetConiferTreeImage(Vector3i a_BlockPos, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks, bool a_Large = false); /** Fills a_LogBlocks and a_OtherBlocks (dirt & leaves) with the blocks required to form a random spruce */ void GetSpruceTreeImage(Vector3i a_BlockPos, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks, bool a_Large = false); /** Fills a_LogBlocks and a_OtherBlocks (dirt & leaves) with the blocks required to form a random pine */ void GetPineTreeImage(Vector3i a_BlockPos, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks, bool a_Large = false); /** Fills a_LogBlocks and a_OtherBlocks (dirt & leaves) with the blocks required to form a random small spruce (short conifer, two layers of leaves) */ void GetSmallSpruceTreeImage(Vector3i a_BlockPos, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks); /** Fills a_LogBlocks and a_OtherBlocks (dirt & leaves) with the blocks required to form a random small pine (tall conifer, little leaves at top) */ void GetSmallPineTreeImage(Vector3i a_BlockPos, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks); /** Fills a_LogBlocks and a_OtherBlocks (dirt & leaves) with the blocks required to form a random large spruce (short conifer, multiple layers of leaves) */ void GetLargeSpruceTreeImage(Vector3i a_BlockPos, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks); /** Fills a_LogBlocks and a_OtherBlocks (dirt & leaves) with the blocks required to form a random large pine (tall conifer, little leaves at top) */ void GetLargePineTreeImage(Vector3i a_BlockPos, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks); /** Fills a_LogBlocks and a_OtherBlocks (dirt & leaves) with the blocks required to form a random swampland tree */ void GetSwampTreeImage(Vector3i a_BlockPos, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks); /** Fills a_LogBlocks and a_OtherBlocks (dirt & leaves) with the blocks required to form a random apple bush (for jungles) */ void GetAppleBushImage(Vector3i a_BlockPos, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks); /** Fills a_LogBlocks and a_OtherBlocks (dirt & leaves) with the blocks required to form a random jungle tree */ void GetJungleTreeImage(Vector3i a_BlockPos, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks, bool a_Large); /** Fills a_LogBlocks and a_OtherBlocks (dirt & leaves) with the blocks required to form a large jungle tree (2x2 trunk) */ void GetLargeJungleTreeImage(Vector3i a_BlockPos, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks); /** Fills a_LogBlocks and a_OtherBlocks (dirt & leaves) with the blocks required to form a small jungle tree (1x1 trunk) */ void GetSmallJungleTreeImage(Vector3i a_BlockPos, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks); /** Fills a_LogBlocks and a_OtherBlocks with the blocks required to form the red mushroom */ void GetRedMushroomTreeImage(Vector3i vector3, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks); /** Fills a_LogBlocks and a_OtherBlocks with the blocks required to form the brown mushroom */ void GetBrownMushroomTreeImage(Vector3i a_BlockPos, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks); ================================================ FILE: src/Generating/TwoHeights.cpp ================================================ // TwoHeights.cpp // Implements the cTwoHeights class representing the terrain shape generator using two switched heightmaps #include "Globals.h" #include "TwoHeights.h" #include "../Noise/InterpolNoise.h" #include "HeiGen.h" #include "../LinearUpscale.h" #include "../IniFile.h" class cTwoHeights: public cTerrainShapeGen { using Super = cTerrainShapeGen; public: cTwoHeights(int a_Seed, cBiomeGen & a_BiomeGen): m_Seed(a_Seed), m_Choice(a_Seed), m_HeightA(a_Seed + 1, a_BiomeGen), m_HeightB(a_Seed + 2, a_BiomeGen) { } // cTerrainShapeGen override: virtual void GenShape(cChunkCoords a_ChunkCoords, cChunkDesc::Shape & a_Shape) override { // Generate the two heightmaps: cChunkDef::HeightMap heightsA; cChunkDef::HeightMap heightsB; m_HeightA.GenHeightMap(a_ChunkCoords, heightsA); m_HeightB.GenHeightMap(a_ChunkCoords, heightsB); // Generate the choice noise: NOISE_DATATYPE smallChoice[33 * 5 * 5]; NOISE_DATATYPE workspace[33 * 5 * 5]; NOISE_DATATYPE startX = 0; NOISE_DATATYPE endX = 256 * m_FrequencyY; NOISE_DATATYPE startY = a_ChunkCoords.m_ChunkX * cChunkDef::Width * m_FrequencyX; NOISE_DATATYPE endY = (a_ChunkCoords.m_ChunkX * cChunkDef::Width + cChunkDef::Width + 1) * m_FrequencyX; NOISE_DATATYPE startZ = a_ChunkCoords.m_ChunkZ * cChunkDef::Width * m_FrequencyZ; NOISE_DATATYPE endZ = (a_ChunkCoords.m_ChunkZ * cChunkDef::Width + cChunkDef::Width + 1) * m_FrequencyZ; m_Choice.Generate3D(smallChoice, 33, 5, 5, startX, endX, startY, endY, startZ, endZ, workspace); NOISE_DATATYPE choice[257 * 17 * 17]; LinearUpscale3DArray(smallChoice, 33, 5, 5, choice, 8, 4, 4); // Generate the shape: int idxShape = 0; for (int z = 0; z < cChunkDef::Width; z++) { for (int x = 0; x < cChunkDef::Width; x++) { int idxChoice = 257 * 17 * z + 257 * x; NOISE_DATATYPE heightA = static_cast(cChunkDef::GetHeight(heightsA, x, z)); NOISE_DATATYPE heightB = static_cast(cChunkDef::GetHeight(heightsB, x, z)); for (int y = 0; y < cChunkDef::Height; y++) { int height = static_cast(ClampedLerp(heightA, heightB, choice[idxChoice++])); a_Shape[idxShape++] = (y < height) ? 1 : 0; } } // for x } // for z } virtual void InitializeShapeGen(cIniFile & a_IniFile) override { m_FrequencyX = static_cast(a_IniFile.GetValueSetF("Generator", "TwoHeightsFrequencyX", 40)); m_FrequencyY = static_cast(a_IniFile.GetValueSetF("Generator", "TwoHeightsFrequencyY", 40)); m_FrequencyZ = static_cast(a_IniFile.GetValueSetF("Generator", "TwoHeightsFrequencyZ", 40)); // Initialize the two underlying height generators from an empty INI file: cIniFile empty; m_HeightA.InitializeHeightGen(empty); m_HeightB.InitializeHeightGen(empty); // Add the choice octaves: NOISE_DATATYPE freq = 0.001f; NOISE_DATATYPE ampl = 1; for (int i = 0; i < 4; i++) { m_Choice.AddOctave(freq, ampl); freq = freq * 2; ampl = ampl / 2; } } protected: int m_Seed; /** The noise used to decide between the two heightmaps. */ cOctavedNoise> m_Choice; /** The first height generator. */ cHeiGenBiomal m_HeightA; /** The second height generator. */ cHeiGenBiomal m_HeightB; /** The base frequencies for m_Choice in each of the world axis directions. */ NOISE_DATATYPE m_FrequencyX, m_FrequencyY, m_FrequencyZ; }; std::unique_ptr CreateShapeGenTwoHeights(int a_Seed, cBiomeGen & a_BiomeGen) { return std::make_unique(a_Seed, a_BiomeGen); } ================================================ FILE: src/Generating/TwoHeights.h ================================================ // TwoHeights.h // Declares the function to create a new instance of the cTwoHeights terrain shape generator #pragma once #include "ComposableGenerator.h" /** Creates and returns a new instance of the cTwoHeights terrain shape generator. The instance must be Initialize()-d before it is used. */ extern std::unique_ptr CreateShapeGenTwoHeights(int a_Seed, cBiomeGen & a_BiomeGen); ================================================ FILE: src/Generating/VerticalLimit.cpp ================================================ // VerticalLimit.cpp #include "Globals.h" #include "VerticalLimit.h" //////////////////////////////////////////////////////////////////////////////// // Globals: /** Parses a string containing a range in which both values are optional ("|") into Min, Max. Returns true if successful, false on failure. If a_LogWarnings is true, outputs failure reasons to console. The range is returned in a_Min and a_Max. If no value is in the string, both values are left unchanged. If only the minimum is in the string, it is assigned to both a_Min and a_Max. */ namespace VerticalLimit { static bool ParseRange(const AString & a_Params, int & a_Min, int & a_Max, bool a_LogWarnings) { auto params = StringSplitAndTrim(a_Params, "|"); if (params.size() == 0) { // No params, generate directly on top: return true; } if (!StringToInteger(params[0], a_Min)) { // Failed to parse the min rel height: CONDWARNING(a_LogWarnings, "Cannot parse minimum height from string \"%s\"!", params[0].c_str()); return false; } if (params.size() == 1) { // Only one param was given, there's no range a_Max = a_Min; return true; } if (!StringToInteger(params[1], a_Max)) { CONDWARNING(a_LogWarnings, "Cannot parse maximum height from string \"%s\"!", params[1].c_str()); return false; } if (a_Max < a_Min) { std::swap(a_Max, a_Min); } return true; } } //////////////////////////////////////////////////////////////////////////////// /** Limit that accepts any height. The default for all pieces. */ class cVerticalLimitNone: public cPiece::cVerticalLimit { public: virtual bool CanBeAtHeight(int a_BlockX, int a_BlockZ, int a_Height) override { // Any height is okay return true; } virtual bool InitializeFromString(const AString & a_Params, bool a_LogWarnings) override { // No parameters to read, no checks being done return true; } }; //////////////////////////////////////////////////////////////////////////////// /** Limit that accepts heights above the specified minimum fixed height. */ class cVerticalLimitAbove: public cPiece::cVerticalLimit { public: virtual bool CanBeAtHeight(int a_BlockX, int a_BlockZ, int a_Height) override { return (a_Height >= m_MinHeight); } virtual bool InitializeFromString(const AString & a_Params, bool a_LogWarnings) override { // Parameters: "", compulsory if (!StringToInteger(a_Params, m_MinHeight)) { CONDWARNING(a_LogWarnings, "Cannot parse the minimum height from string \"%s\"!", a_Params.c_str()); return false; } return true; } protected: /** The minimum accepted height. */ int m_MinHeight; }; //////////////////////////////////////////////////////////////////////////////// /** Limit that accepts heights that are a specified number of blocks above terrain. */ class cVerticalLimitAboveTerrain: public cPiece::cVerticalLimit { public: virtual bool CanBeAtHeight(int a_BlockX, int a_BlockZ, int a_Height) override { ASSERT(m_TerrainHeightGen != nullptr); auto terrainHeight = m_TerrainHeightGen->GetHeightAt(a_BlockX, a_BlockZ); int compareHeight = a_Height - terrainHeight; return ( (compareHeight >= m_MinBlocksAbove) && // Above the minimum (compareHeight <= m_MaxBlocksAbove) // and below the maximum ); } virtual bool InitializeFromString(const AString & a_Params, bool a_LogWarnings) override { // Parameters: "|", both optional m_MinBlocksAbove = 0; m_MaxBlocksAbove = 0; return VerticalLimit::ParseRange(a_Params, m_MinBlocksAbove, m_MaxBlocksAbove, a_LogWarnings); } virtual void AssignGens(int a_Seed, cBiomeGen & a_BiomeGen, cTerrainHeightGen & a_TerrainHeightGen, int a_SeaLevel) override { m_TerrainHeightGen = &a_TerrainHeightGen; } protected: /** The underlying height generator. */ cTerrainHeightGen * m_TerrainHeightGen; /** How many blocks above the terrain level do we accept on minimum. */ int m_MinBlocksAbove; /** How many blocks above the terrain level do we accept on maximum. */ int m_MaxBlocksAbove; }; //////////////////////////////////////////////////////////////////////////////// /** Limit that accepts heights that are a specified number of blocks above terrain and sealevel, whichever is higher. */ class cVerticalLimitAboveTerrainAndOcean: public cPiece::cVerticalLimit { public: virtual bool CanBeAtHeight(int a_BlockX, int a_BlockZ, int a_Height) override { ASSERT(m_TerrainHeightGen != nullptr); int terrainHeight = m_TerrainHeightGen->GetHeightAt(a_BlockX, a_BlockZ); int compareHeight = a_Height - std::max(terrainHeight, m_SeaLevel); return ( (compareHeight >= m_MinBlocksAbove) && // Above the minimum (compareHeight <= m_MaxBlocksAbove) // and below the maximum ); } virtual bool InitializeFromString(const AString & a_Params, bool a_LogWarnings) override { // Parameters: "|", both optional m_MinBlocksAbove = 0; m_MaxBlocksAbove = 0; return VerticalLimit::ParseRange(a_Params, m_MinBlocksAbove, m_MaxBlocksAbove, a_LogWarnings); } virtual void AssignGens(int a_Seed, cBiomeGen & a_BiomeGen, cTerrainHeightGen & a_TerrainHeightGen, int a_SeaLevel) override { m_TerrainHeightGen = &a_TerrainHeightGen; m_SeaLevel = a_SeaLevel; } protected: /** The underlying height generator. */ cTerrainHeightGen * m_TerrainHeightGen; /** The sealevel for the current world. */ int m_SeaLevel; /** How many blocks above the terrain level / ocean do we accept on minimum. */ int m_MinBlocksAbove; /** How many blocks above the terrain level / ocean do we accept on maximum. */ int m_MaxBlocksAbove; }; //////////////////////////////////////////////////////////////////////////////// /** Limit that accepts heights below the specified fixed height. NOTE that the query height is the BOTTOM of the piece. */ class cVerticalLimitBelow: public cPiece::cVerticalLimit { public: virtual bool CanBeAtHeight(int a_BlockX, int a_BlockZ, int a_Height) override { return (a_Height <= m_MaxHeight); } virtual bool InitializeFromString(const AString & a_Params, bool a_LogWarnings) override { // Parameters: "" if (!StringToInteger(a_Params, m_MaxHeight)) { CONDWARNING(a_LogWarnings, "Cannot parse the maximum height from string \"%s\"!", a_Params.c_str()); return false; } return true; } protected: /** The maximum accepted height. */ int m_MaxHeight; }; //////////////////////////////////////////////////////////////////////////////// /** Limit that accepts heights that are within a specified range below terrain. NOTE that the query height is the BOTTOM of the piece. */ class cVerticalLimitBelowTerrain: public cPiece::cVerticalLimit { public: virtual bool CanBeAtHeight(int a_BlockX, int a_BlockZ, int a_Height) override { auto terrainHeight = m_TerrainHeightGen->GetHeightAt(a_BlockX, a_BlockZ); auto compareHeight = terrainHeight - a_Height; return ( (compareHeight >= m_MinBlocksBelow) && (compareHeight <= m_MaxBlocksBelow) ); } virtual bool InitializeFromString(const AString & a_Params, bool a_LogWarnings) override { // Parameters: "|", both optional m_MinBlocksBelow = 0; m_MaxBlocksBelow = 0; return VerticalLimit::ParseRange(a_Params, m_MinBlocksBelow, m_MaxBlocksBelow, a_LogWarnings); } virtual void AssignGens(int a_Seed, cBiomeGen & a_BiomeGen, cTerrainHeightGen & a_TerrainHeightGen, int a_SeaLevel) override { m_TerrainHeightGen = &a_TerrainHeightGen; } protected: /** The underlying height generator. */ cTerrainHeightGen * m_TerrainHeightGen; /** How many blocks below the terrain level do we accept on minimum. */ int m_MinBlocksBelow; /** How many blocks below the terrain level do we accept on maximum. */ int m_MaxBlocksBelow; }; //////////////////////////////////////////////////////////////////////////////// /** Limit that accepts heights that are a specified number of blocks below terrain or sealevel, whichever is higher. */ class cVerticalLimitBelowTerrainOrOcean: public cPiece::cVerticalLimit { public: virtual bool CanBeAtHeight(int a_BlockX, int a_BlockZ, int a_Height) override { int terrainHeight = m_TerrainHeightGen->GetHeightAt(a_BlockX, a_BlockZ); auto compareHeight = std::max(terrainHeight, m_SeaLevel) - a_Height; return ( (compareHeight >= m_MinBlocksBelow) && (compareHeight <= m_MaxBlocksBelow) ); } virtual bool InitializeFromString(const AString & a_Params, bool a_LogWarnings) override { // Parameters: "|", both optional m_MinBlocksBelow = 0; m_MaxBlocksBelow = 0; return VerticalLimit::ParseRange(a_Params, m_MinBlocksBelow, m_MaxBlocksBelow, a_LogWarnings); } virtual void AssignGens(int a_Seed, cBiomeGen & a_BiomeGen, cTerrainHeightGen & a_TerrainHeightGen, int a_SeaLevel) override { m_TerrainHeightGen = &a_TerrainHeightGen; m_SeaLevel = a_SeaLevel; } protected: /** The underlying height generator. */ cTerrainHeightGen * m_TerrainHeightGen; /** The sealevel for the current world. */ int m_SeaLevel; /** How many blocks below the terrain level do we accept on minimum. */ int m_MinBlocksBelow; /** How many blocks below the terrain level do we accept on maximum. */ int m_MaxBlocksBelow; }; //////////////////////////////////////////////////////////////////////////////// // CreateVerticalLimitFromString: cPiece::cVerticalLimitPtr CreateVerticalLimitFromString(const AString & a_LimitDesc, bool a_LogWarnings) { // Break apart the limit class, the first parameter before the first pipe char: auto idxPipe = a_LimitDesc.find('|'); if (idxPipe == AString::npos) { idxPipe = a_LimitDesc.length(); } AString LimitClass = a_LimitDesc.substr(0, idxPipe); // Create a strategy class based on the class string: cPiece::cVerticalLimitPtr Limit; if ((LimitClass == "") || (NoCaseCompare(LimitClass, "None") == 0)) { Limit = std::make_shared(); } else if (NoCaseCompare(LimitClass, "Above") == 0) { Limit = std::make_shared(); } else if (NoCaseCompare(LimitClass, "AboveTerrain") == 0) { Limit = std::make_shared(); } else if (NoCaseCompare(LimitClass, "AboveTerrainAndOcean") == 0) { Limit = std::make_shared(); } else if (NoCaseCompare(LimitClass, "Below") == 0) { Limit = std::make_shared(); } else if (NoCaseCompare(LimitClass, "BelowTerrain") == 0) { Limit = std::make_shared(); } else if (NoCaseCompare(LimitClass, "BelowTerrainOrOcean") == 0) { Limit = std::make_shared(); } else { return nullptr; } // Initialize the limit's parameters: AString Params; if (idxPipe < a_LimitDesc.length()) { Params = a_LimitDesc.substr(idxPipe + 1); } if (!Limit->InitializeFromString(Params, a_LogWarnings)) { return nullptr; } return Limit; } ================================================ FILE: src/Generating/VerticalLimit.h ================================================ // VerticalLimit.h // Declares the public interface for cPiece's cVerticalLimit implementations #pragma once #include "PiecePool.h" /** Returns a new cPiece::cVerticalLimit descendant based on the specified description. a_LimitDesc is in the format "|". The params and the pipe may be omitted. If an unknown class is requested or the param parsing fails, nullptr is returned. If a_LogWarnings is true, any problem is reported into the server console. */ cPiece::cVerticalLimitPtr CreateVerticalLimitFromString(const AString & a_LimitDesc, bool a_LogWarnings); ================================================ FILE: src/Generating/VerticalStrategy.cpp ================================================ // VerticalStrategy.cpp // Implements the various classes descending from cPiece::cVerticalStrategy #include "Globals.h" #include "VerticalStrategy.h" #include "../Noise/Noise.h" // Constant that is added to random seed static const int SEED_OFFSET = 135; //////////////////////////////////////////////////////////////////////////////// // Globals: /** Parses a string containing a range in which both values are optional ("|") into Min, Range. Returns true if successful, false on failure. If a_LogWarnings is true, outputs failure reasons to console. The range is returned in a_Min and a_Range, they are left unchanged if the range value is not present in the string. */ namespace VerticalStrategy { static bool ParseRange(const AString & a_Params, int & a_Min, int & a_Range, bool a_LogWarnings) { auto params = StringSplitAndTrim(a_Params, "|"); if (params.size() == 0) { // No params, generate directly on top: return true; } if (!StringToInteger(params[0], a_Min)) { // Failed to parse the min rel height: CONDWARNING(a_LogWarnings, "Cannot parse minimum height from string \"%s\"!", params[0].c_str()); return false; } if (params.size() == 1) { // Only one param was given, there's no range return true; } int maxHeight = a_Min; if (!StringToInteger(params[1], maxHeight)) { CONDWARNING(a_LogWarnings, "Cannot parse maximum height from string \"%s\"!", params[1].c_str()); return false; } if (maxHeight < a_Min) { std::swap(maxHeight, a_Min); } a_Range = maxHeight - a_Min + 1; return true; } } //////////////////////////////////////////////////////////////////////////////// /** A vertical strategy that places the piece at a predefined height. */ class cVerticalStrategyFixed: public cPiece::cVerticalStrategy { public: cVerticalStrategyFixed(void): m_Height(-1000) // Default to "unassigned" height { } virtual int GetVerticalPlacement(int a_BlockX, int a_BlockZ) override { return m_Height; } virtual bool InitializeFromString(const AString & a_Params, bool a_LogWarnings) override { // Params: "", compulsory if (!StringToInteger(a_Params, m_Height)) { CONDWARNING(a_LogWarnings, "Cannot parse the fixed height from string \"%s\"!", a_Params.c_str()); return false; } return true; } protected: /** Height at which the pieces are placed. Note that this height may be outside the world, so that only a part of the piece is generated. */ int m_Height; }; //////////////////////////////////////////////////////////////////////////////// /** A vertical strategy that places the piece in a random height between two heights. */ class cVerticalStrategyRange: public cPiece::cVerticalStrategy { public: cVerticalStrategyRange(void): m_Seed(0), m_Min(-1), // Default to "unassigned" height m_Range(1) { } virtual int GetVerticalPlacement(int a_BlockX, int a_BlockZ) override { cNoise Noise(m_Seed); return m_Min + (Noise.IntNoise2DInt(a_BlockX, a_BlockZ) / 7) % m_Range; } virtual bool InitializeFromString(const AString & a_Params, bool a_LogWarnings) override { // Params: "|", all compulsory auto params = StringSplitAndTrim(a_Params, "|"); if (params.size() != 2) { CONDWARNING(a_LogWarnings, "Cannot parse the range parameters from string \"%s\"!", a_Params.c_str()); return false; } int Max = 0; if (!StringToInteger(params[0], m_Min) || !StringToInteger(params[1], Max)) { CONDWARNING(a_LogWarnings, "Cannot parse the minimum or maximum height from string \"%s\"!", a_Params.c_str()); return false; } if (m_Min > Max) { std::swap(m_Min, Max); } m_Range = Max - m_Min + 1; return true; } virtual void AssignGens(int a_Seed, cBiomeGen & a_BiomeGen, cTerrainHeightGen & a_TerrainHeightGen, int a_SeaLevel) override { m_Seed = a_Seed + SEED_OFFSET; } protected: /** Seed for the random generator. Received in AssignGens(). */ int m_Seed; /** Range for the random generator. Received in InitializeFromString(). */ int m_Min, m_Range; }; //////////////////////////////////////////////////////////////////////////////// /** A vertical strategy that places the piece in a specified range relative to the top of the terrain. */ class cVerticalStrategyTerrainTop: public cPiece::cVerticalStrategy { public: virtual int GetVerticalPlacement(int a_BlockX, int a_BlockZ) override { ASSERT(m_HeightGen != nullptr); int ChunkX, ChunkZ; cChunkDef::BlockToChunk(a_BlockX, a_BlockZ, ChunkX, ChunkZ); cChunkDef::HeightMap HeightMap; m_HeightGen->GenHeightMap({ChunkX, ChunkZ}, HeightMap); cNoise noise(m_Seed); int rel = m_MinRelHeight + (noise.IntNoise2DInt(a_BlockX, a_BlockZ) / 7) % m_RelHeightRange + 1; return cChunkDef::GetHeight(HeightMap, a_BlockX - ChunkX * cChunkDef::Width, a_BlockZ - ChunkZ * cChunkDef::Width) + rel; } virtual bool InitializeFromString(const AString & a_Params, bool a_LogWarnings) override { // Params: "|", all optional m_MinRelHeight = 0; m_RelHeightRange = 1; return VerticalStrategy::ParseRange(a_Params, m_MinRelHeight, m_RelHeightRange, a_LogWarnings); } virtual void AssignGens(int a_Seed, cBiomeGen & a_BiomeGen, cTerrainHeightGen & a_HeightGen, int a_SeaLevel) override { m_Seed = a_Seed + SEED_OFFSET; m_HeightGen = &a_HeightGen; } protected: /** Seed for the random generator. */ int m_Seed; /** Height generator from which the top of the terrain is read. */ cTerrainHeightGen * m_HeightGen; /** Minimum relative height at which the prefab is placed. */ int m_MinRelHeight; /** Range of the relative heights at which the prefab can be placed above the minimum. */ int m_RelHeightRange; }; //////////////////////////////////////////////////////////////////////////////// /** A vertical strategy that places the piece within a range on top of the terrain or ocean, whichever's higher. */ class cVerticalStrategyTerrainOrOceanTop: public cPiece::cVerticalStrategy { public: virtual int GetVerticalPlacement(int a_BlockX, int a_BlockZ) override { ASSERT(m_HeightGen != nullptr); int ChunkX, ChunkZ; cChunkDef::BlockToChunk(a_BlockX, a_BlockZ, ChunkX, ChunkZ); cChunkDef::HeightMap HeightMap; m_HeightGen->GenHeightMap({ChunkX, ChunkZ}, HeightMap); int terrainHeight = static_cast(cChunkDef::GetHeight(HeightMap, a_BlockX - ChunkX * cChunkDef::Width, a_BlockZ - ChunkZ * cChunkDef::Width)); terrainHeight = std::max(1 + terrainHeight, m_SeaLevel); cNoise noise(m_Seed); int rel = m_MinRelHeight + (noise.IntNoise2DInt(a_BlockX, a_BlockZ) / 7) % m_RelHeightRange + 1; return terrainHeight + rel; } virtual bool InitializeFromString(const AString & a_Params, bool a_LogWarnings) override { // Params: "|", all optional m_MinRelHeight = 0; m_RelHeightRange = 1; return VerticalStrategy::ParseRange(a_Params, m_MinRelHeight, m_RelHeightRange, a_LogWarnings); } virtual void AssignGens(int a_Seed, cBiomeGen & a_BiomeGen, cTerrainHeightGen & a_HeightGen, int a_SeaLevel) override { m_Seed = a_Seed + SEED_OFFSET; m_HeightGen = &a_HeightGen; m_SeaLevel = a_SeaLevel; } protected: /** Seed for the random generator. */ int m_Seed; /** Height generator from which the top of the terrain is read. */ cTerrainHeightGen * m_HeightGen; /** The sea level used by the world. */ int m_SeaLevel; /** Minimum relative height at which the prefab is placed. */ int m_MinRelHeight; /** Range of the relative heights at which the prefab can be placed above the minimum. */ int m_RelHeightRange; }; //////////////////////////////////////////////////////////////////////////////// // CreateVerticalStrategyFromString: cPiece::cVerticalStrategyPtr CreateVerticalStrategyFromString(const AString & a_StrategyDesc, bool a_LogWarnings) { // Break apart the strategy class, the first parameter before the first pipe char: auto idxPipe = a_StrategyDesc.find('|'); if (idxPipe == AString::npos) { idxPipe = a_StrategyDesc.length(); } AString StrategyClass = a_StrategyDesc.substr(0, idxPipe); // Create a strategy class based on the class string: cPiece::cVerticalStrategyPtr Strategy; if (NoCaseCompare(StrategyClass, "Fixed") == 0) { Strategy = std::make_shared(); } else if (NoCaseCompare(StrategyClass, "Range") == 0) { Strategy = std::make_shared(); } else if (NoCaseCompare(StrategyClass, "TerrainTop") == 0) { Strategy = std::make_shared(); } else if (NoCaseCompare(StrategyClass, "TerrainOrOceanTop") == 0) { Strategy = std::make_shared(); } else { return nullptr; } // Initialize the strategy's parameters: AString Params; if (idxPipe < a_StrategyDesc.length()) { Params = a_StrategyDesc.substr(idxPipe + 1); } if (!Strategy->InitializeFromString(Params, a_LogWarnings)) { return nullptr; } return Strategy; } ================================================ FILE: src/Generating/VerticalStrategy.h ================================================ // VerticalStrategy.h // Declares the public interface for cPiece's cVerticalStrategy implementations #pragma once #include "PiecePool.h" /** Returns a new cPiece::cVerticalStrategy descendant based on the specified description. a_StrategyDesc is in the format "|". The params and the pipe may be omitted. If an unknown class is requested or the param parsing fails, nullptr is returned. */ cPiece::cVerticalStrategyPtr CreateVerticalStrategyFromString(const AString & a_StrategyDesc, bool a_LogWarnings); ================================================ FILE: src/Generating/VillageGen.cpp ================================================ // VillageGen.cpp // Implements the cVillageGen class representing the village generator #include "Globals.h" #include "VillageGen.h" #include "PieceGeneratorBFSTree.h" #include "../BlockInfo.h" /* How village generating works: By descending from a cGridStructGen, a semi-random (jitter) grid is generated. A village may be generated for each of the grid's cells. Each cell checks the biomes in an entire chunk around its center, only generating a village if all biomes are village-friendly. If yes, the entire village structure is built for that cell. If not, the cell is left village-less. A village is generated using the regular BFS piece generator. The well piece is used as the starting piece, the roads and houses are then used as the following pieces. Only the houses are read from the prefabs, though, the roads are generated by code and their content is ignored. A special subclass of the cPiecePool class is used, so that the roads connect to each other and to the well only in predefined manners. The well has connectors of type "2". The houses have connectors of type "-1". The roads have connectors of both types' opposites, type "-2" at the far ends and type "1" on the long edges. Additionally, there are type "2" connectors along the long edges of the roads as well, so that the roads create T junctions. When the village is about to be drawn into a chunk, it queries the heights for each piece intersecting the chunk. The pieces are shifted so that their first connector lies on the surface, and the roads are drawn directly by turning the surface blocks into gravel / sandstone. The village prefabs are stored in global piecepools (one pool per village type). In order to support per-village density setting, the cVillage class itself implements the cPiecePool interface, relaying the calls to the underlying cVillagePiecePool, after processing the density check. */ class cVillagePiecePool: public cPrefabPiecePool { using Super = cPrefabPiecePool; public: cVillagePiecePool( const cPrefab::sDef * a_PieceDefs, size_t a_NumPieceDefs, const cPrefab::sDef * a_StartingPieceDefs, size_t a_NumStartingPieceDefs ): Super(a_PieceDefs, a_NumPieceDefs, a_StartingPieceDefs, a_NumStartingPieceDefs) { AddRoadPieces(); } cVillagePiecePool(void) { AddRoadPieces(); } void AddRoadPieces(void) { // Add the road pieces: for (int len = 27; len < 60; len += 12) { cBlockArea BA; BA.Create(len, 1, 3, cBlockArea::baTypes | cBlockArea::baMetas); BA.Fill(cBlockArea::baTypes | cBlockArea::baMetas, E_BLOCK_GRAVEL, 0); cPrefab * RoadPiece = new cPrefab(BA, 1); RoadPiece->AddConnector(0, 0, 1, cPiece::cConnector::dirXM, -2); RoadPiece->AddConnector(len - 1, 0, 1, cPiece::cConnector::dirXP, -2); RoadPiece->SetDefaultWeight(100); // Add the road connectors: for (int x = 1; x < len; x += 12) { RoadPiece->AddConnector(x, 0, 0, cPiece::cConnector::dirZM, 2); RoadPiece->AddConnector(x, 0, 2, cPiece::cConnector::dirZP, 2); } // Add the buildings connectors: for (int x = 7; x < len; x += 12) { RoadPiece->AddConnector(x, 0, 0, cPiece::cConnector::dirZM, 1); RoadPiece->AddConnector(x, 0, 2, cPiece::cConnector::dirZP, 1); } m_AllPieces.push_back(RoadPiece); m_PiecesByConnector[-2].push_back(RoadPiece); m_PiecesByConnector[1].push_back(RoadPiece); m_PiecesByConnector[2].push_back(RoadPiece); } // for len - roads of varying length } // cPrefabPiecePool overrides: virtual int GetPieceWeight(const cPlacedPiece & a_PlacedPiece, const cPiece::cConnector & a_ExistingConnector, const cPiece & a_NewPiece) override { // Roads cannot branch T-wise (appending -2 connector to a +2 connector on a 1-high piece): if ((a_ExistingConnector.m_Type == 2) && (a_PlacedPiece.GetDepth() > 0) && (a_PlacedPiece.GetPiece().GetSize().y == 1)) { return 0; } return static_cast(a_NewPiece).GetPieceWeight(a_PlacedPiece, a_ExistingConnector); } }; class cVillageGen::cVillage: public cGridStructGen::cStructure, protected cPiecePool { using Super = cGridStructGen::cStructure; public: cVillage( int a_Seed, int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ, int a_MaxRoadDepth, int a_MaxSize, int a_Density, cVillagePiecePool & a_Prefabs, cTerrainHeightGen & a_HeightGen ): Super(a_GridX, a_GridZ, a_OriginX, a_OriginZ), m_Seed(a_Seed), m_Noise(a_Seed), m_MaxSize(a_MaxSize), m_Density(a_Density), m_Borders( {a_OriginX - a_MaxSize, 0, a_OriginZ - a_MaxSize}, {a_OriginX + a_MaxSize, cChunkDef::Height - 1, a_OriginZ + a_MaxSize} ), m_Prefabs(a_Prefabs), m_HeightGen(a_HeightGen) { // Generate the pieces for this village; don't care about the Y coord: cPieceGeneratorBFSTree pg(*this, a_Seed); pg.PlacePieces(a_OriginX, a_OriginZ, a_MaxRoadDepth + 1, m_Pieces); if (m_Pieces.empty()) { return; } } protected: /** Seed for the random functions */ int m_Seed; /** The noise used as a pseudo-random generator */ cNoise m_Noise; /** Maximum size, in X / Z blocks, of the village (radius from the origin) */ int m_MaxSize; /** The density for this village. Used to refrain from populating all house connectors. Range [0, 100] */ int m_Density; /** Borders of the village - no item may reach out of this cuboid. */ cCuboid m_Borders; /** Prefabs to use for buildings */ cVillagePiecePool & m_Prefabs; /** The underlying height generator, used for placing the structures on top of the terrain. */ cTerrainHeightGen & m_HeightGen; /** The village pieces, placed by the generator. */ cPlacedPieces m_Pieces; // cGridStructGen::cStructure overrides: virtual void DrawIntoChunk(cChunkDesc & a_Chunk) override { // Iterate over all items // Each intersecting prefab is placed on ground, then drawn // Each intersecting road is drawn by replacing top soil blocks with gravel / sandstone blocks cChunkDef::HeightMap HeightMap; // Heightmap for this chunk, used by roads m_HeightGen.GenHeightMap(a_Chunk.GetChunkCoords(), HeightMap); for (cPlacedPieces::iterator itr = m_Pieces.begin(), end = m_Pieces.end(); itr != end; ++itr) { const cPrefab & Prefab = static_cast((*itr)->GetPiece()); if ((*itr)->GetPiece().GetSize().y == 1) { // It's a road, special handling (change top terrain blocks to m_RoadBlock) DrawRoad(a_Chunk, **itr, HeightMap); continue; } if (Prefab.ShouldMoveToGround() && !(*itr)->HasBeenMovedToGround()) { PlacePieceOnGround(**itr); } Prefab.Draw(a_Chunk, itr->get()); } // for itr - m_PlacedPieces[] } /** Adjusts the Y coord of the given piece so that the piece is on the ground. Ground level is assumed to be represented by the first connector in the piece. */ void PlacePieceOnGround(cPlacedPiece & a_Piece) { cPiece::cConnector FirstConnector = a_Piece.GetRotatedConnector(0); int ChunkX, ChunkZ; int BlockX = FirstConnector.m_Pos.x; int BlockZ = FirstConnector.m_Pos.z; int BlockY; cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ); cChunkDef::HeightMap HeightMap; m_HeightGen.GenHeightMap({ChunkX, ChunkZ}, HeightMap); int TerrainHeight = cChunkDef::GetHeight(HeightMap, BlockX, BlockZ); a_Piece.MoveToGroundBy(TerrainHeight - FirstConnector.m_Pos.y + 1); } /** Draws the road into the chunk. The heightmap is not queried from the heightgen, but is given via parameter, so that it may be queried just once for all roads in a chunk. */ void DrawRoad(cChunkDesc & a_Chunk, cPlacedPiece & a_Road, cChunkDef::HeightMap & a_HeightMap) { cCuboid RoadCoords = a_Road.GetHitBox(); RoadCoords.Sort(); int MinX = std::max(RoadCoords.p1.x - a_Chunk.GetChunkX() * cChunkDef::Width, 0); int MaxX = std::min(RoadCoords.p2.x - a_Chunk.GetChunkX() * cChunkDef::Width, cChunkDef::Width - 1); int MinZ = std::max(RoadCoords.p1.z - a_Chunk.GetChunkZ() * cChunkDef::Width, 0); int MaxZ = std::min(RoadCoords.p2.z - a_Chunk.GetChunkZ() * cChunkDef::Width, cChunkDef::Width - 1); auto WaterRoadBlockType = m_Prefabs.GetVillageWaterRoadBlockType(); auto WaterRoadBlockMeta = m_Prefabs.GetVillageWaterRoadBlockMeta(); auto RoadBlockType = m_Prefabs.GetVillageRoadBlockType(); auto RoadBlockMeta = m_Prefabs.GetVillageRoadBlockMeta(); for (int z = MinZ; z <= MaxZ; z++) { for (int x = MinX; x <= MaxX; x++) { auto height = cChunkDef::GetHeight(a_HeightMap, x, z); if (IsBlockWater(a_Chunk.GetBlockType(x, height, z))) { a_Chunk.SetBlockTypeMeta(x, height, z, WaterRoadBlockType, WaterRoadBlockMeta); } else { a_Chunk.SetBlockTypeMeta(x, height, z, RoadBlockType, RoadBlockMeta); } } } } // cPiecePool overrides: virtual cPieces GetPiecesWithConnector(int a_ConnectorType) override { return m_Prefabs.GetPiecesWithConnector(a_ConnectorType); } virtual cPieces GetStartingPieces(void) override { return m_Prefabs.GetStartingPieces(); } virtual int GetPieceWeight( const cPlacedPiece & a_PlacedPiece, const cPiece::cConnector & a_ExistingConnector, const cPiece & a_NewPiece ) override { // Check against the density: if (a_ExistingConnector.m_Type == 1) { const Vector3i & Coords = a_PlacedPiece.GetRotatedConnector(a_ExistingConnector).m_Pos; int rnd = (m_Noise.IntNoise3DInt(Coords.x, Coords.y, Coords.z) / 7) % 100; if (rnd > m_Density) { return 0; } } // Density check passed, relay to m_Prefabs: return m_Prefabs.GetPieceWeight(a_PlacedPiece, a_ExistingConnector, a_NewPiece); } virtual int GetStartingPieceWeight(const cPiece & a_NewPiece) override { return m_Prefabs.GetStartingPieceWeight(a_NewPiece); } virtual void PiecePlaced(const cPiece & a_Piece) override { m_Prefabs.PiecePlaced(a_Piece); } virtual void Reset(void) override { m_Prefabs.Reset(); } void MoveAllDescendants(cPlacedPieces & a_PlacedPieces, size_t a_Pivot, int a_HeightDifference) { size_t num = a_PlacedPieces.size(); auto & Pivot = a_PlacedPieces[a_Pivot]; for (size_t i = a_Pivot + 1; i < num; i++) { if ( (a_PlacedPieces[i]->GetParent() == Pivot.get()) && // It is a direct dependant of the pivot !(static_cast(a_PlacedPieces[i]->GetPiece())).ShouldMoveToGround() // It attaches strictly by connectors ) { a_PlacedPieces[i]->MoveToGroundBy(a_HeightDifference); MoveAllDescendants(a_PlacedPieces, i, a_HeightDifference); } } // for i - a_PlacedPieces[] } } ; //////////////////////////////////////////////////////////////////////////////// // cVillageGen: cVillageGen::cVillageGen( int a_Seed, int a_GridSize, int a_MaxOffset, int a_MaxDepth, int a_MaxSize, int a_MinDensity, int a_MaxDensity, cBiomeGen & a_BiomeGen, cTerrainHeightGen & a_HeightGen, int a_SeaLevel, const AStringVector & a_PrefabsToLoad ) : Super(a_Seed, a_GridSize, a_GridSize, a_MaxOffset, a_MaxOffset, a_MaxSize, a_MaxSize, 100), m_RandNoise(a_Seed + 1000), m_MaxDepth(a_MaxDepth), m_MaxSize(a_MaxSize), m_MinDensity(a_MinDensity), m_MaxDensity(a_MaxDensity), m_BiomeGen(a_BiomeGen), m_HeightGen(a_HeightGen) { for (const auto & toLoad: a_PrefabsToLoad) { auto prefabs = std::make_shared(); auto fileName = fmt::format(FMT_STRING("Prefabs{0}Villages{0}{1}.cubeset"), cFile::GetPathSeparator(), toLoad); if (prefabs->LoadFromFile(fileName, true)) { if (NoCaseCompare(prefabs->GetIntendedUse(), "village") != 0) { LOGWARNING("Village generator: File %s is intended for use in \"%s\", rather than villages. Loading the file, but the generator may behave unexpectedly.", fileName, prefabs->GetIntendedUse() ); } prefabs->AssignGens(a_Seed, m_BiomeGen, m_HeightGen, a_SeaLevel); m_Pools.push_back(std::move(prefabs)); } } } cGridStructGen::cStructurePtr cVillageGen::CreateStructure(int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ) { // Generate the biomes for the chunk surrounding the origin: int ChunkX, ChunkZ; cChunkDef::BlockToChunk(a_OriginX, a_OriginZ, ChunkX, ChunkZ); cChunkDef::BiomeMap Biomes; m_BiomeGen.GenBiomes({ChunkX, ChunkZ}, Biomes); // Get a list of pools that support each biome within the chunk: // If just one column's biome is not allowed, the pool is not used because it's likely that an unfriendly biome is too close auto availablePools = m_Pools; for (size_t i = 0; i < ARRAYCOUNT(Biomes); i++) { auto biome = Biomes[i]; availablePools.erase(std::remove_if(availablePools.begin(), availablePools.end(), [biome](std::shared_ptr & a_Pool) { return !a_Pool->IsBiomeAllowed(biome); }), availablePools.end() ); // Bail out if no compatible pools left: if (availablePools.empty()) { return cStructurePtr(); } } // Pick one pool from the available pools: if (availablePools.empty()) { return cStructurePtr(); } auto rnd = m_RandNoise.IntNoise2DInt(a_OriginX, a_OriginZ) / 11; auto pool = availablePools[static_cast(rnd) % availablePools.size()]; rnd /= 137; // Choose density for the village, random between m_MinDensity and m_MaxDensity: int Density; if (pool->GetMaxDensity() > pool->GetMinDensity()) { Density = pool->GetMinDensity() + rnd % (pool->GetMaxDensity() - pool->GetMinDensity()); } else { Density = pool->GetMinDensity(); } // Create a village based on the chosen prefabs: return cStructurePtr(new cVillage(m_Seed, a_GridX, a_GridZ, a_OriginX, a_OriginZ, m_MaxDepth, m_MaxSize, Density, *pool.get(), m_HeightGen)); } ================================================ FILE: src/Generating/VillageGen.h ================================================ // VillageGen.h // Declares the cVillageGen class representing the village generator #pragma once #include "GridStructGen.h" #include "PrefabPiecePool.h" // fwd: class cVillagePiecePool; class cVillageGen: public cGridStructGen { using Super = cGridStructGen; public: /** Creates a new instance of the generator with the specified parameters. */ cVillageGen( int a_Seed, int a_GridSize, int a_MaxOffset, int a_MaxDepth, int a_MaxSize, int a_MinDensity, int a_MaxDensity, cBiomeGen & a_BiomeGen, cTerrainHeightGen & a_HeightGen, int a_SeaLevel, const AStringVector & a_PrefabsToLoad ); protected: class cVillage; // fwd: VillageGen.cpp typedef std::vector> cVillagePiecePools; /** The noise used for generating random numbers */ cNoise m_RandNoise; /** Maximum depth of the generator tree */ int m_MaxDepth; /** Maximum size, in X / Z blocks, of the village (radius from the origin) */ int m_MaxSize; /** Minimum density - percentage of allowed house connections. Range [0, 100] */ int m_MinDensity; /** Maximum density - percentage of allowed house connections. Range [0, 100] */ int m_MaxDensity; /** The underlying biome generator that defines whether the village is created or not */ cBiomeGen & m_BiomeGen; /** The underlying height generator, used to position the prefabs crossing chunk borders */ cTerrainHeightGen & m_HeightGen; /** All available prefab sets. Each village gets one of these chosen randomly. */ cVillagePiecePools m_Pools; // cGridStructGen overrides: virtual cStructurePtr CreateStructure(int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ) override; } ; ================================================ FILE: src/Globals.cpp ================================================ // Globals.cpp // This file is used for precompiled header generation in MSVC environments #include "Globals.h" ================================================ FILE: src/Globals.h ================================================ // Globals.h // This file gets included from every module in the project, so that global symbols may be introduced easily // Also used for precompiled header generation in MSVC environments #pragma once // Compiler-dependent stuff: #if defined(_MSC_VER) // Use non-standard defines in #define _USE_MATH_DEFINES #ifndef NDEBUG // Override the "new" operator to include file and line specification for debugging memory leaks // Ref.: https://social.msdn.microsoft.com/Forums/en-US/ebc7dd7a-f3c6-49f1-8a60-e381052f21b6/debugging-memory-leaks?forum=vcgeneral#53f0cc89-62fe-45e8-bbf0-56b89f2a1901 // This causes MSVC Debug runs to produce a report upon program exit, that contains memory-leaks // together with the file:line information about where the memory was allocated. // Note that this doesn't work with placement-new, which needs to temporarily #undef the macro // (See AllocationPool.h for an example). #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_CLIENTBLOCK new(_CLIENT_BLOCK, __FILE__, __LINE__) #define new DEBUG_CLIENTBLOCK // For some reason this works magically - each "new X" gets replaced as "new(_CLIENT_BLOCK, "file", line) X" // The CRT has a definition for this operator new that stores the debugging info for leak-finding later. #endif #define UNREACHABLE_INTRINSIC __assume(false) #elif defined(__GNUC__) // TODO: Can GCC explicitly mark classes as abstract (no instances can be created)? #define abstract #define UNREACHABLE_INTRINSIC __builtin_unreachable() #else #error "You are using an unsupported compiler, you might need to #define some stuff here for your compiler" #endif // A macro to disallow the copy constructor and operator = functions // This should be used in the declarations for any class that shouldn't allow copying itself #define DISALLOW_COPY_AND_ASSIGN(TypeName) \ TypeName(const TypeName &) = delete; \ TypeName & operator =(const TypeName &) = delete // A macro that is used to mark unused local variables, to avoid pedantic warnings in gcc / clang / MSVC // Note that in MSVC it requires the full type of X to be known #define UNUSED_VAR(X) (void)(X) // A macro that is used to mark unused function parameters, to avoid pedantic warnings in gcc // Written so that the full type of param needn't be known #ifdef _MSC_VER #define UNUSED(X) #else #define UNUSED UNUSED_VAR #endif // OS-dependent stuff: #ifdef _WIN32 #define NOMINMAX // Windows SDK defines min and max macros, messing up with our std::min and std::max usage. #define WIN32_LEAN_AND_MEAN #define _WIN32_WINNT 0x0501 // We want to target Windows XP with Service Pack 2 & Windows Server 2003 with Service Pack 1 and higher. // Use CryptoAPI primitives when targeting a version that supports encrypting with AES-CFB8 smaller than a full block at a time. #define PLATFORM_CRYPTOGRAPHY (_WIN32_WINNT >= 0x0602) #include #include #include // IPv6 stuff // Windows SDK defines GetFreeSpace as a constant, probably a Win16 API remnant: #ifdef GetFreeSpace #undef GetFreeSpace #endif // GetFreeSpace #else #define PLATFORM_CRYPTOGRAPHY 0 #include #include #include #include #include #endif // CRT stuff: #include #include #include #include #include // STL stuff: #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // Integral types with predefined sizes: typedef signed long long Int64; typedef signed int Int32; typedef signed short Int16; typedef signed char Int8; typedef unsigned long long UInt64; typedef unsigned int UInt32; typedef unsigned short UInt16; typedef unsigned char UInt8; typedef unsigned char Byte; typedef Byte ColourID; template class SizeChecker { static_assert(sizeof(T) == Size, "Check the size of integral types"); }; template class SizeChecker; template class SizeChecker; template class SizeChecker; template class SizeChecker; template class SizeChecker; template class SizeChecker; template class SizeChecker; template class SizeChecker; // Common headers (part 1, without macros): #include "fmt.h" #include "StringUtils.h" #include "LoggerSimple.h" #include "OSSupport/CriticalSection.h" #include "OSSupport/Event.h" #include "OSSupport/File.h" #include "OSSupport/StackTrace.h" #ifdef TEST_GLOBALS // Basic logging function implementations namespace Logger { inline void LogFormat( std::string_view a_Format, eLogLevel, fmt::format_args a_ArgList ) { fmt::vprint(a_Format, a_ArgList); putchar('\n'); fflush(stdout); } inline void LogPrintf( std::string_view a_Format, eLogLevel, fmt::printf_args a_ArgList ) { fmt::vprintf(a_Format, a_ArgList); putchar('\n'); fflush(stdout); } inline void LogSimple(std::string_view a_Message, eLogLevel) { fmt::print("{}\n", a_Message); fflush(stdout); } } // namespace Logger #endif // Common definitions: /** Evaluates to the number of elements in an array (compile-time!) */ #define ARRAYCOUNT(X) (sizeof(X) / sizeof(*(X))) /** Allows arithmetic expressions like "32 KiB" (but consider using parenthesis around it, "(32 KiB)") */ #define KiB * 1024 #define MiB * 1024 * 1024 /** Faster than (int)floorf((float)x / (float)div) */ #define FAST_FLOOR_DIV(x, div) (((x) - (((x) < 0) ? ((div) - 1) : 0)) / (div)) // Own version of ASSERT() that plays nicely with the testing framework #ifdef TEST_GLOBALS class cAssertFailure { AString mExpression; AString mFileName; int mLineNumber; public: cAssertFailure(const AString & aExpression, const AString & aFileName, int aLineNumber): mExpression(aExpression), mFileName(aFileName), mLineNumber(aLineNumber) { } const AString & expression() const { return mExpression; } const AString & fileName() const { return mFileName; } int lineNumber() const { return mLineNumber; } }; #ifdef NDEBUG #define ASSERT(x) #else #define ASSERT(x) do { if (!(x)) { throw cAssertFailure(#x, __FILE__, __LINE__);} } while (0) #endif // Pretty much the same as ASSERT() but stays in Release builds #define VERIFY(x) (!!(x) || ( LOGERROR("Verification failed: %s, file %s, line %i", #x, __FILE__, __LINE__), std::abort(), 0)) #else // TEST_GLOBALS #ifdef NDEBUG #define ASSERT(x) #else #define ASSERT(x) ( !!(x) || ( LOGERROR("Assertion failed: %s, file %s, line %i", #x, __FILE__, __LINE__), std::abort(), 0)) #endif // Pretty much the same as ASSERT() but stays in Release builds #define VERIFY(x) (!!(x) || ( LOGERROR("Verification failed: %s, file %s, line %i", #x, __FILE__, __LINE__), std::abort(), 0)) #endif // else TEST_GLOBALS // Use to mark code that should be impossible to reach. #ifdef NDEBUG #define UNREACHABLE(x) UNREACHABLE_INTRINSIC #else #define UNREACHABLE(x) ( FLOGERROR("Hit unreachable code: {0}, file {1}, line {2}", #x, __FILE__, __LINE__), std::abort(), 0) #endif namespace cpp20 { template std::enable_if_t && (std::extent_v == 0), std::unique_ptr> make_unique_for_overwrite(std::size_t a_Size) { return std::unique_ptr(new std::remove_extent_t[a_Size]); } template std::enable_if_t, std::unique_ptr> make_unique_for_overwrite() { return std::unique_ptr(new T); } } /** You can use this struct to use in std::visit example: std::visit( OverloadedVariantAccess { [&] (cFirstType & a_FirstTypeObject) { // Your code to handle cFirstType }, [&] (cSecondType & a_SecondTypeObject) { // YourCode to handle cSecondType }, ... } , YourVariant); You can use constant references if you want to. */ template struct OverloadedVariantAccess : Ts... { using Ts::operator()...; }; template OverloadedVariantAccess(Ts...)->OverloadedVariantAccess; /** Clamp X to the specified range. */ template T Clamp(T a_Value, T a_Min, T a_Max) { return (a_Value < a_Min) ? a_Min : ((a_Value > a_Max) ? a_Max : a_Value); } /** Floors a value, then casts it to C (an int by default). */ template typename std::enable_if::value, C>::type FloorC(T a_Value) { return static_cast(std::floor(a_Value)); } /** Ceils a value, then casts it to C (an int by default). */ template typename std::enable_if::value, C>::type CeilC(T a_Value) { return static_cast(std::ceil(a_Value)); } // A time duration representing a Minecraft tick (50 ms), capable of storing at least 32'767 ticks. using cTickTime = std::chrono::duration>>; // A time duration representing a Minecraft tick (50 ms), capable of storing at least a 64 bit signed duration. using cTickTimeLong = std::chrono::duration; /** Converts a literal to a tick time. */ constexpr cTickTimeLong operator ""_tick(const unsigned long long a_Ticks) { return cTickTimeLong(a_Ticks); } using ContiguousByteBuffer = std::basic_string; using ContiguousByteBufferView = std::basic_string_view; #ifndef TOLUA_TEMPLATE_BIND #define TOLUA_TEMPLATE_BIND(x) #endif #ifdef TOLUA_EXPOSITION #error TOLUA_EXPOSITION should never actually be defined #endif template auto ToUnsigned(T a_Val) { ASSERT(a_Val >= 0); return static_cast>(a_Val); } // https://stackoverflow.com/questions/1666802/is-there-a-class-macro-in-c constexpr std::string_view methodName(std::string_view a_PrettyFunction) { size_t Bracket = a_PrettyFunction.rfind("("); size_t Space = a_PrettyFunction.rfind(" ", Bracket) + 1; return a_PrettyFunction.substr(Space, Bracket - Space); } // https://stackoverflow.com/questions/48857887/pretty-function-in-visual-c #if !defined(__PRETTY_FUNCTION__) && !defined(__GNUC__) #define __PRETTY_FUNCTION__ __FUNCSIG__ #endif #define __METHOD_NAME__ methodName(__PRETTY_FUNCTION__) // Common headers (part 2, with macros): #include "Vector3.h" ================================================ FILE: src/HTTP/CMakeLists.txt ================================================ target_sources( ${CMAKE_PROJECT_NAME} PRIVATE EnvelopeParser.cpp HTTPFormParser.cpp HTTPMessage.cpp HTTPMessageParser.cpp HTTPServer.cpp HTTPServerConnection.cpp MultipartParser.cpp NameValueParser.cpp SslHTTPServerConnection.cpp TransferEncodingParser.cpp UrlClient.cpp UrlParser.cpp EnvelopeParser.h HTTPFormParser.h HTTPMessage.h HTTPMessageParser.h HTTPServer.h HTTPServerConnection.h MultipartParser.h NameValueParser.h SslHTTPServerConnection.h TransferEncodingParser.h UrlClient.h UrlParser.h ) ================================================ FILE: src/HTTP/EnvelopeParser.cpp ================================================ // EnvelopeParser.cpp // Implements the cEnvelopeParser class representing a parser for RFC-822 envelope headers, used both in HTTP and in MIME #include "Globals.h" #include "EnvelopeParser.h" cEnvelopeParser::cEnvelopeParser(cCallbacks & a_Callbacks) : m_Callbacks(a_Callbacks), m_IsInHeaders(true) { } size_t cEnvelopeParser::Parse(const char * a_Data, size_t a_Size) { if (!m_IsInHeaders) { return 0; } // Start searching 1 char from the end of the already received data, if available: auto searchStart = m_IncomingData.size(); searchStart = (searchStart > 1) ? searchStart - 1 : 0; m_IncomingData.append(a_Data, a_Size); size_t idxCRLF = m_IncomingData.find("\r\n", searchStart); if (idxCRLF == AString::npos) { // Not a complete line yet, all input consumed: return a_Size; } // Parse as many lines as found: size_t Last = 0; do { if (idxCRLF == Last) { // This was the last line of the data. Finish whatever value has been cached and return: NotifyLast(); m_IsInHeaders = false; return a_Size - (m_IncomingData.size() - idxCRLF) + 2; } if (!ParseLine(m_IncomingData.c_str() + Last, idxCRLF - Last)) { // An error has occurred m_IsInHeaders = false; return AString::npos; } Last = idxCRLF + 2; idxCRLF = m_IncomingData.find("\r\n", idxCRLF + 2); } while (idxCRLF != AString::npos); m_IncomingData.erase(0, Last); // Parsed all lines and still expecting more return a_Size; } void cEnvelopeParser::Reset(void) { m_IsInHeaders = true; m_IncomingData.clear(); m_LastKey.clear(); m_LastValue.clear(); } void cEnvelopeParser::NotifyLast(void) { if (!m_LastKey.empty()) { m_Callbacks.OnHeaderLine(m_LastKey, m_LastValue); m_LastKey.clear(); } m_LastValue.clear(); } bool cEnvelopeParser::ParseLine(const char * a_Data, size_t a_Size) { ASSERT(a_Size > 0); if (a_Data[0] <= ' ') { // This line is a continuation for the previous line if (m_LastKey.empty()) { return false; } // Append, including the whitespace in a_Data[0] m_LastValue.append(a_Data, a_Size); return true; } // This is a line with a new key: NotifyLast(); for (size_t i = 0; i < a_Size; i++) { if (a_Data[i] == ':') { m_LastKey.assign(a_Data, i); if (a_Size > i + 1) { m_LastValue.assign(a_Data + i + 2, a_Size - i - 2); } else { m_LastValue.clear(); } return true; } } // for i - a_Data[] // No colon was found, key-less header?? return false; } ================================================ FILE: src/HTTP/EnvelopeParser.h ================================================ // EnvelopeParser.h // Declares the cEnvelopeParser class representing a parser for RFC-822 envelope headers, used both in HTTP and in MIME #pragma once class cEnvelopeParser { public: class cCallbacks { public: // Force a virtual destructor in descendants: virtual ~cCallbacks() {} /** Called when a full header line is parsed */ virtual void OnHeaderLine(const AString & a_Key, const AString & a_Value) = 0; } ; cEnvelopeParser(cCallbacks & a_Callbacks); /** Parses the incoming data. Returns the number of bytes consumed from the input. The bytes not consumed are not part of the envelope header. Returns AString::npos on error */ size_t Parse(const char * a_Data, size_t a_Size); /** Makes the parser forget everything parsed so far, so that it can be reused for parsing another datastream */ void Reset(void); /** Returns true if more input is expected for the envelope header */ bool IsInHeaders(void) const { return m_IsInHeaders; } /** Sets the IsInHeaders flag; used by cMultipartParser to simplify the parser initial conditions */ void SetIsInHeaders(bool a_IsInHeaders) { m_IsInHeaders = a_IsInHeaders; } public: /** Callbacks to call for the various events */ cCallbacks & m_Callbacks; /** Set to true while the parser is still parsing the envelope headers. Once set to true, the parser will not consume any more data. */ bool m_IsInHeaders; /** Buffer for the incoming data until it is parsed */ AString m_IncomingData; /** Holds the last parsed key; used for line-wrapped values */ AString m_LastKey; /** Holds the last parsed value; used for line-wrapped values */ AString m_LastValue; /** Notifies the callback of the key / value stored in m_LastKey / m_LastValue, then erases them */ void NotifyLast(void); /** Parses one line of header data. Returns true if successful */ bool ParseLine(const char * a_Data, size_t a_Size); } ; ================================================ FILE: src/HTTP/HTTPFormParser.cpp ================================================ // HTTPFormParser.cpp // Implements the cHTTPFormParser class representing a parser for forms sent over HTTP #include "Globals.h" #include "HTTPFormParser.h" #include "HTTPMessage.h" #include "NameValueParser.h" cHTTPFormParser::cHTTPFormParser(const cHTTPIncomingRequest & a_Request, cCallbacks & a_Callbacks) : m_Callbacks(a_Callbacks), m_IsValid(true), m_IsCurrentPartFile(false), m_FileHasBeenAnnounced(false) { if (a_Request.GetMethod() == "GET") { m_Kind = fpkURL; // Directly parse the URL in the request: const AString & URL = a_Request.GetURL(); size_t idxQM = URL.find('?'); if (idxQM != AString::npos) { Parse(URL.c_str() + idxQM + 1, URL.size() - idxQM - 1); } return; } if ((a_Request.GetMethod() == "POST") || (a_Request.GetMethod() == "PUT")) { if (strncmp(a_Request.GetContentType().c_str(), "application/x-www-form-urlencoded", 33) == 0) { m_Kind = fpkFormUrlEncoded; return; } if (strncmp(a_Request.GetContentType().c_str(), "multipart/form-data", 19) == 0) { m_Kind = fpkMultipart; BeginMultipart(a_Request); return; } } // Invalid method / content type combination, this is not a HTTP form m_IsValid = false; } cHTTPFormParser::cHTTPFormParser(eKind a_Kind, const char * a_Data, size_t a_Size, cCallbacks & a_Callbacks) : m_Callbacks(a_Callbacks), m_Kind(a_Kind), m_IsValid(true), m_IsCurrentPartFile(false), m_FileHasBeenAnnounced(false) { Parse(a_Data, a_Size); } void cHTTPFormParser::Parse(const char * a_Data, size_t a_Size) { if (!m_IsValid) { return; } switch (m_Kind) { case fpkURL: case fpkFormUrlEncoded: { // This format is used for smaller forms (not file uploads), so we can delay parsing it until Finish() m_IncomingData.append(a_Data, a_Size); break; } case fpkMultipart: { ASSERT(m_MultipartParser.get() != nullptr); m_MultipartParser->Parse(a_Data, a_Size); break; } } } bool cHTTPFormParser::Finish(void) { switch (m_Kind) { case fpkURL: case fpkFormUrlEncoded: { // m_IncomingData has all the form data, parse it now: ParseFormUrlEncoded(); break; } case fpkMultipart: { // Nothing needed for other formats break; } } return (m_IsValid && m_IncomingData.empty()); } bool cHTTPFormParser::HasFormData(const cHTTPIncomingRequest & a_Request) { const AString & ContentType = a_Request.GetContentType(); return ( (ContentType == "application/x-www-form-urlencoded") || (strncmp(ContentType.c_str(), "multipart/form-data", 19) == 0) || ( (a_Request.GetMethod() == "GET") && (a_Request.GetURL().find('?') != AString::npos) ) ); } void cHTTPFormParser::BeginMultipart(const cHTTPIncomingRequest & a_Request) { ASSERT(m_MultipartParser.get() == nullptr); m_MultipartParser.reset(new cMultipartParser(a_Request.GetContentType(), *this)); } void cHTTPFormParser::ParseFormUrlEncoded(void) { // Parse m_IncomingData for all the variables; no more data is incoming, since this is called from Finish() // This may not be the most performant version, but we don't care, the form data is small enough and we're not a full-fledged web server anyway AStringVector Lines = StringSplit(m_IncomingData, "&"); for (AStringVector::iterator itr = Lines.begin(), end = Lines.end(); itr != end; ++itr) { AStringVector Components = StringSplit(*itr, "="); switch (Components.size()) { default: { // Neither name nor value, or too many "="s, mark this as invalid form: m_IsValid = false; return; } case 1: { // Only name present auto name = URLDecode(ReplaceAllCharOccurrences(Components[0], '+', ' ')); if (name.first) { (*this)[name.second] = ""; } break; } case 2: { // name=value format: auto name = URLDecode(Components[0]); auto value = URLDecode(Components[1]); if (name.first && value.first) { (*this)[name.second] = value.second; } break; } } } // for itr - Lines[] m_IncomingData.clear(); } void cHTTPFormParser::OnPartStart(void) { m_CurrentPartFileName.clear(); m_CurrentPartName.clear(); m_IsCurrentPartFile = false; m_FileHasBeenAnnounced = false; } void cHTTPFormParser::OnPartHeader(const AString & a_Key, const AString & a_Value) { if (NoCaseCompare(a_Key, "Content-Disposition") == 0) { size_t len = a_Value.size(); size_t ParamsStart = AString::npos; for (size_t i = 0; i < len; ++i) { if (a_Value[i] > ' ') { if (strncmp(a_Value.c_str() + i, "form-data", 9) != 0) { // Content disposition is not "form-data", mark the whole form invalid m_IsValid = false; return; } ParamsStart = a_Value.find(';', i + 9); break; } } if (ParamsStart == AString::npos) { // There is data missing in the Content-Disposition field, mark the whole form invalid: m_IsValid = false; return; } // Parse the field name and optional filename from this header: cNameValueParser Parser(a_Value.data() + ParamsStart, a_Value.size() - ParamsStart); Parser.Finish(); m_CurrentPartName = Parser["name"]; if (!Parser.IsValid() || m_CurrentPartName.empty()) { // The required parameter "name" is missing, mark the whole form invalid: m_IsValid = false; return; } m_CurrentPartFileName = Parser["filename"]; } } void cHTTPFormParser::OnPartData(const char * a_Data, size_t a_Size) { if (m_CurrentPartName.empty()) { // Prologue, epilogue or invalid part return; } if (m_CurrentPartFileName.empty()) { // This is a variable, store it in the map iterator itr = find(m_CurrentPartName); if (itr == end()) { (*this)[m_CurrentPartName] = AString(a_Data, a_Size); } else { itr->second.append(a_Data, a_Size); } } else { // This is a file, pass it on through the callbacks if (!m_FileHasBeenAnnounced) { m_Callbacks.OnFileStart(*this, m_CurrentPartFileName); m_FileHasBeenAnnounced = true; } m_Callbacks.OnFileData(*this, a_Data, a_Size); } } void cHTTPFormParser::OnPartEnd(void) { if (m_FileHasBeenAnnounced) { m_Callbacks.OnFileEnd(*this); } m_CurrentPartName.clear(); m_CurrentPartFileName.clear(); } ================================================ FILE: src/HTTP/HTTPFormParser.h ================================================ // HTTPFormParser.h // Declares the cHTTPFormParser class representing a parser for forms sent over HTTP #pragma once #include "MultipartParser.h" // fwd: class cHTTPIncomingRequest; class cHTTPFormParser : public std::map, public cMultipartParser::cCallbacks { public: enum eKind { fpkURL, ///< The form has been transmitted as parameters to a GET request fpkFormUrlEncoded, ///< The form has been POSTed or PUT, with Content-Type of "application/x-www-form-urlencoded" fpkMultipart, ///< The form has been POSTed or PUT, with Content-Type of "multipart/form-data" } ; class cCallbacks { public: // Force a virtual destructor in descendants: virtual ~cCallbacks() {} /** Called when a new file part is encountered in the form data */ virtual void OnFileStart(cHTTPFormParser & a_Parser, const AString & a_FileName) = 0; /** Called when more file data has come for the current file in the form data */ virtual void OnFileData(cHTTPFormParser & a_Parser, const char * a_Data, size_t a_Size) = 0; /** Called when the current file part has ended in the form data */ virtual void OnFileEnd(cHTTPFormParser & a_Parser) = 0; } ; /** Creates a parser that is tied to a request and notifies of various events using a callback mechanism */ cHTTPFormParser(const cHTTPIncomingRequest & a_Request, cCallbacks & a_Callbacks); /** Creates a parser with the specified content type that reads data from a string */ cHTTPFormParser(eKind a_Kind, const char * a_Data, size_t a_Size, cCallbacks & a_Callbacks); /** Adds more data into the parser, as the request body is received */ void Parse(const char * a_Data, size_t a_Size); /** Notifies that there's no more data incoming and the parser should finish its parsing. Returns true if parsing successful. */ bool Finish(void); /** Returns true if the headers suggest the request has form data parseable by this class */ static bool HasFormData(const cHTTPIncomingRequest & a_Request); protected: /** The callbacks to call for incoming file data */ cCallbacks & m_Callbacks; /** The kind of the parser (decided in the constructor, used in Parse() */ eKind m_Kind; /** Buffer for the incoming data until it's parsed */ AString m_IncomingData; /** True if the information received so far is a valid form; set to false on first problem. Further parsing is skipped when false. */ bool m_IsValid; /** The parser for the multipart data, if used */ std::unique_ptr m_MultipartParser; /** Name of the currently parsed part in multipart data */ AString m_CurrentPartName; /** True if the currently parsed part in multipart data is a file */ bool m_IsCurrentPartFile; /** Filename of the current parsed part in multipart data (for file uploads) */ AString m_CurrentPartFileName; /** Set to true after m_Callbacks.OnFileStart() has been called, reset to false on PartEnd */ bool m_FileHasBeenAnnounced; /** Sets up the object for parsing a fpkMultipart request */ void BeginMultipart(const cHTTPIncomingRequest & a_Request); /** Parses m_IncomingData as form-urlencoded data (fpkURL or fpkFormUrlEncoded kinds) */ void ParseFormUrlEncoded(void); // cMultipartParser::cCallbacks overrides: virtual void OnPartStart (void) override; virtual void OnPartHeader(const AString & a_Key, const AString & a_Value) override; virtual void OnPartData (const char * a_Data, size_t a_Size) override; virtual void OnPartEnd (void) override; } ; ================================================ FILE: src/HTTP/HTTPMessage.cpp ================================================ // HTTPMessage.cpp // Declares the cHTTPMessage class representing the common ancestor for HTTP request and response classes #include "Globals.h" #include "HTTPMessage.h" // Disable MSVC warnings: #if defined(_MSC_VER) #pragma warning(push) #pragma warning(disable:4355) // 'this' : used in base member initializer list #endif //////////////////////////////////////////////////////////////////////////////// // cHTTPMessage: cHTTPMessage::cHTTPMessage(eKind a_Kind) : m_Kind(a_Kind), m_ContentLength(AString::npos) { } void cHTTPMessage::AddHeader(const AString & a_Key, const AString & a_Value) { auto Key = StrToLower(a_Key); auto itr = m_Headers.find(Key); if (itr == m_Headers.end()) { m_Headers[Key] = a_Value; } else { // The header-field key is specified multiple times, combine into comma-separated list (RFC 2616 @ 4.2) itr->second.append(", "); itr->second.append(a_Value); } // Special processing for well-known headers: if (Key == "content-type") { m_ContentType = m_Headers[Key]; } else if (Key == "content-length") { if (!StringToInteger(m_Headers[Key], m_ContentLength)) { m_ContentLength = 0; } } } //////////////////////////////////////////////////////////////////////////////// // cHTTPOutgoingResponse: cHTTPOutgoingResponse::cHTTPOutgoingResponse(void) : Super(mkResponse) { } void cHTTPOutgoingResponse::AppendToData(AString & a_DataStream) const { a_DataStream.append("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\nContent-Type: "); a_DataStream.append(m_ContentType); a_DataStream.append("\r\n"); for (auto itr = m_Headers.cbegin(), end = m_Headers.cend(); itr != end; ++itr) { if ((itr->first == "Content-Type") || (itr->first == "Content-Length")) { continue; } a_DataStream.append(itr->first); a_DataStream.append(": "); a_DataStream.append(itr->second); a_DataStream.append("\r\n"); } // for itr - m_Headers[] a_DataStream.append("\r\n"); } //////////////////////////////////////////////////////////////////////////////// // cHTTPIncomingRequest: cHTTPIncomingRequest::cHTTPIncomingRequest(const AString & a_Method, const AString & a_URL): Super(mkRequest), m_Method(a_Method), m_URL(a_URL), m_HasAuth(false) { } AString cHTTPIncomingRequest::GetURLPath(void) const { auto idxQuestionMark = m_URL.find('?'); if (idxQuestionMark == AString::npos) { return m_URL; } else { return m_URL.substr(0, idxQuestionMark); } } void cHTTPIncomingRequest::AddHeader(const AString & a_Key, const AString & a_Value) { if ( (NoCaseCompare(a_Key, "Authorization") == 0) && (strncmp(a_Value.c_str(), "Basic ", 6) == 0) ) { AString UserPass = Base64Decode(a_Value.substr(6)); size_t idxCol = UserPass.find(':'); if (idxCol != AString::npos) { m_AuthUsername = UserPass.substr(0, idxCol); m_AuthPassword = UserPass.substr(idxCol + 1); m_HasAuth = true; } } if ((a_Key == "Connection") && (NoCaseCompare(a_Value, "keep-alive") == 0)) { m_AllowKeepAlive = true; } Super::AddHeader(a_Key, a_Value); } ================================================ FILE: src/HTTP/HTTPMessage.h ================================================ // HTTPMessage.h // Declares the cHTTPMessage class representing the common ancestor for HTTP request and response classes #pragma once class cHTTPMessage { public: enum eStatus { HTTP_OK = 200, HTTP_BAD_REQUEST = 400, } ; enum eKind { mkRequest, mkResponse, } ; cHTTPMessage(eKind a_Kind); // Force a virtual destructor in all descendants virtual ~cHTTPMessage() {} /** Adds a header into the internal map of headers. Recognizes special headers: Content-Type and Content-Length */ virtual void AddHeader(const AString & a_Key, const AString & a_Value); void SetContentType (const AString & a_ContentType) { m_ContentType = a_ContentType; } void SetContentLength(size_t a_ContentLength) { m_ContentLength = a_ContentLength; } const AString & GetContentType (void) const { return m_ContentType; } size_t GetContentLength(void) const { return m_ContentLength; } protected: using cNameValueMap = std::map; eKind m_Kind; /** Map of headers, with their keys lowercased. */ AStringMap m_Headers; /** Type of the content; parsed by AddHeader(), set directly by SetContentLength() */ AString m_ContentType; /** Length of the content that is to be received. AString::npos when the object is created. Parsed by AddHeader() or set directly by SetContentLength() */ size_t m_ContentLength; } ; /** Stores outgoing response headers and serializes them to an HTTP data stream. */ class cHTTPOutgoingResponse: public cHTTPMessage { using Super = cHTTPMessage; public: cHTTPOutgoingResponse(void); /** Appends the response to the specified datastream - response line and headers. The body will be sent later directly through cConnection::Send() */ void AppendToData(AString & a_DataStream) const; } ; /** Provides storage for an incoming HTTP request. */ class cHTTPIncomingRequest: public cHTTPMessage { using Super = cHTTPMessage; public: /** Base class for anything that can be used as the UserData for the request. */ class cUserData { public: // Force a virtual destructor in descendants: virtual ~cUserData() {} }; using cUserDataPtr = std::shared_ptr; /** Creates a new instance of the class, containing the method and URL provided by the client. */ cHTTPIncomingRequest(const AString & a_Method, const AString & a_URL); /** Returns the method used in the request */ const AString & GetMethod(void) const { return m_Method; } /** Returns the URL used in the request */ const AString & GetURL(void) const { return m_URL; } /** Returns the path part of the URL. */ AString GetURLPath(void) const; /** Returns true if the request has had the Auth header present. */ bool HasAuth(void) const { return m_HasAuth; } /** Returns the username that the request presented. Only valid if HasAuth() is true */ const AString & GetAuthUsername(void) const { return m_AuthUsername; } /** Returns the password that the request presented. Only valid if HasAuth() is true */ const AString & GetAuthPassword(void) const { return m_AuthPassword; } bool DoesAllowKeepAlive(void) const { return m_AllowKeepAlive; } /** Attaches any kind of data to this request, to be later retrieved by GetUserData(). */ void SetUserData(cUserDataPtr a_UserData) { m_UserData = std::move(a_UserData); } /** Returns the data attached to this request by the class client. */ cUserDataPtr GetUserData(void) { return m_UserData; } /** Adds the specified header into the internal list of headers. Overrides the parent to add recognizing additional headers: auth and keepalive. */ virtual void AddHeader(const AString & a_Key, const AString & a_Value) override; protected: /** Method of the request (GET / PUT / POST / ...) */ AString m_Method; /** Full URL of the request */ AString m_URL; /** Set to true if the request contains auth data that was understood by the parser */ bool m_HasAuth; /** The username used for auth */ AString m_AuthUsername; /** The password used for auth */ AString m_AuthPassword; /** Set to true if the request indicated that it supports keepalives. If false, the server will close the connection once the request is finished */ bool m_AllowKeepAlive; /** Any data attached to the request by the class client. */ cUserDataPtr m_UserData; }; ================================================ FILE: src/HTTP/HTTPMessageParser.cpp ================================================ // HTTPMessageParser.cpp // Implements the cHTTPMessageParser class that parses HTTP messages (request or response) being pushed into the parser, // and reports the individual parts via callbacks #include "Globals.h" #include "HTTPMessageParser.h" cHTTPMessageParser::cHTTPMessageParser(cHTTPMessageParser::cCallbacks & a_Callbacks): m_Callbacks(a_Callbacks), m_EnvelopeParser(*this) { Reset(); } size_t cHTTPMessageParser::Parse(const char * a_Data, size_t a_Size) { // If parsing already finished or errorred, let the caller keep all the data: if (m_IsFinished || m_HasHadError) { return 0; } // If still waiting for the status line, add to buffer and try parsing it: auto inBufferSoFar = m_Buffer.size(); if (m_FirstLine.empty()) { m_Buffer.append(a_Data, a_Size); auto bytesConsumedFirstLine = ParseFirstLine(); ASSERT(bytesConsumedFirstLine <= inBufferSoFar + a_Size); // Haven't consumed more data than there is in the buffer ASSERT(bytesConsumedFirstLine > inBufferSoFar); // Have consumed at least the previous buffer contents if (m_FirstLine.empty()) { // All data used, but not a complete status line yet. return a_Size; } if (m_HasHadError) { return AString::npos; } // Status line completed, feed the rest of the buffer into the envelope parser: auto bytesConsumedEnvelope = m_EnvelopeParser.Parse(m_Buffer.data(), m_Buffer.size()); if (bytesConsumedEnvelope == AString::npos) { m_HasHadError = true; m_Callbacks.OnError("Failed to parse the envelope"); return AString::npos; } ASSERT(bytesConsumedEnvelope <= bytesConsumedFirstLine + a_Size); // Haven't consumed more data than there was in the buffer m_Buffer.erase(0, bytesConsumedEnvelope); if (!m_EnvelopeParser.IsInHeaders()) { HeadersFinished(); // Process any data still left in the buffer as message body: auto bytesConsumedBody = ParseBody(m_Buffer.data(), m_Buffer.size()); if (bytesConsumedBody == AString::npos) { // Error has already been reported by ParseBody, just bail out: return AString::npos; } return bytesConsumedBody + bytesConsumedEnvelope + bytesConsumedFirstLine - inBufferSoFar; } return a_Size; } // if (m_FirstLine.empty()) // If still parsing headers, send them to the envelope parser: if (m_EnvelopeParser.IsInHeaders()) { auto bytesConsumed = m_EnvelopeParser.Parse(a_Data, a_Size); if (bytesConsumed == AString::npos) { m_HasHadError = true; m_Callbacks.OnError("Failed to parse the envelope"); return AString::npos; } if (!m_EnvelopeParser.IsInHeaders()) { HeadersFinished(); // Process any data still left as message body: auto bytesConsumedBody = ParseBody(a_Data + bytesConsumed, a_Size - bytesConsumed); if (bytesConsumedBody == AString::npos) { // Error has already been reported by ParseBody, just bail out: return AString::npos; } } return a_Size; } // Already parsing the body return ParseBody(a_Data, a_Size); } void cHTTPMessageParser::Reset(void) { m_HasHadError = false; m_IsFinished = false; m_FirstLine.clear(); m_Buffer.clear(); m_EnvelopeParser.Reset(); m_TransferEncodingParser.reset(); m_TransferEncoding.clear(); m_ContentLength = 0; } size_t cHTTPMessageParser::ParseFirstLine(void) { auto idxLineEnd = m_Buffer.find("\r\n"); if (idxLineEnd == AString::npos) { // Not a complete line yet return m_Buffer.size(); } m_FirstLine = m_Buffer.substr(0, idxLineEnd); m_Buffer.erase(0, idxLineEnd + 2); m_Callbacks.OnFirstLine(m_FirstLine); return idxLineEnd + 2; } size_t cHTTPMessageParser::ParseBody(const char * a_Data, size_t a_Size) { if (m_TransferEncodingParser == nullptr) { // We have no Transfer-encoding parser assigned. This should have happened when finishing the envelope OnError("No transfer encoding parser"); return AString::npos; } // Parse the body using the transfer encoding parser: // (Note that TE parser returns the number of bytes left, while we return the number of bytes consumed) return a_Size - m_TransferEncodingParser->Parse(a_Data, a_Size); } void cHTTPMessageParser::HeadersFinished(void) { m_Callbacks.OnHeadersFinished(); m_TransferEncodingParser = cTransferEncodingParser::Create(*this, m_TransferEncoding, m_ContentLength); if (m_TransferEncodingParser == nullptr) { OnError(fmt::format(FMT_STRING("Unknown transfer encoding: {}"), m_TransferEncoding)); return; } } void cHTTPMessageParser::OnHeaderLine(const AString & a_Key, const AString & a_Value) { m_Callbacks.OnHeaderLine(a_Key, a_Value); auto Key = StrToLower(a_Key); if (Key == "content-length") { if (!StringToInteger(a_Value, m_ContentLength)) { OnError(fmt::format(FMT_STRING("Invalid content length header value: \"{}\""), a_Value)); } return; } if (Key == "transfer-encoding") { m_TransferEncoding = a_Value; return; } } void cHTTPMessageParser::OnError(const AString & a_ErrorDescription) { m_HasHadError = true; m_Callbacks.OnError(a_ErrorDescription); } void cHTTPMessageParser::OnBodyData(const void * a_Data, size_t a_Size) { m_Callbacks.OnBodyData(a_Data, a_Size); } void cHTTPMessageParser::OnBodyFinished(void) { m_IsFinished = true; m_Callbacks.OnBodyFinished(); } ================================================ FILE: src/HTTP/HTTPMessageParser.h ================================================ // HTTPMessageParser.h // Declares the cHTTPMessageParser class that parses HTTP messages (request or response) being pushed into the parser, // and reports the individual parts via callbacks #pragma once #include "EnvelopeParser.h" #include "TransferEncodingParser.h" class cHTTPMessageParser: protected cEnvelopeParser::cCallbacks, protected cTransferEncodingParser::cCallbacks { public: class cCallbacks { public: // Force a virtual destructor in descendants: virtual ~cCallbacks() {} /** Called when an error has occured while parsing. */ virtual void OnError(const AString & a_ErrorDescription) = 0; /** Called when the first line of the request or response is fully parsed. Doesn't check the validity of the line, only extracts the first complete line. */ virtual void OnFirstLine(const AString & a_FirstLine) = 0; /** Called when a single header line is parsed. */ virtual void OnHeaderLine(const AString & a_Key, const AString & a_Value) = 0; /** Called when all the headers have been parsed. */ virtual void OnHeadersFinished(void) = 0; /** Called for each chunk of the incoming body data. */ virtual void OnBodyData(const void * a_Data, size_t a_Size) = 0; /** Called when the entire body has been reported by OnBodyData(). */ virtual void OnBodyFinished(void) = 0; }; /** Creates a new parser instance that will use the specified callbacks for reporting. */ cHTTPMessageParser(cCallbacks & a_Callbacks); /** Parses the incoming data and calls the appropriate callbacks. Returns the number of bytes consumed or AString::npos number for error. */ size_t Parse(const char * a_Data, size_t a_Size); /** Called when the server indicates no more data will be sent (HTTP 1.0 socket closed). Finishes all parsing and calls apropriate callbacks (error if incomplete response). */ void Finish(void); /** Returns true if the entire response has been already parsed. */ bool IsFinished(void) const { return m_IsFinished; } /** Resets the parser to the initial state, so that a new request can be parsed. */ void Reset(void); protected: /** The callbacks used for reporting. */ cCallbacks & m_Callbacks; /** Set to true if an error has been encountered by the parser. */ bool m_HasHadError; /** True if the response has been fully parsed. */ bool m_IsFinished; /** The complete first line of the response. Empty if not parsed yet. */ AString m_FirstLine; /** Buffer for the incoming data until the status line is parsed. */ AString m_Buffer; /** Parser for the envelope data (headers) */ cEnvelopeParser m_EnvelopeParser; /** The specific parser for the transfer encoding used by this response. */ cTransferEncodingParserPtr m_TransferEncodingParser; /** The transfer encoding to be used by the parser. Filled while parsing headers, used when headers are finished. */ AString m_TransferEncoding; /** The content length, parsed from the headers, if available. Unused for chunked encoding. Filled while parsing headers, used when headers are finished. */ size_t m_ContentLength; /** Parses the first line out of m_Buffer. Removes the first line from m_Buffer, if appropriate. Returns the number of bytes consumed out of m_Buffer, or AString::npos number for error. */ size_t ParseFirstLine(void); /** Parses the message body. Processes transfer encoding and calls the callbacks for body data. Returns the number of bytes consumed or AString::npos number for error. */ size_t ParseBody(const char * a_Data, size_t a_Size); /** Called internally when the headers-parsing has just finished. */ void HeadersFinished(void); // cEnvelopeParser::cCallbacks overrides: virtual void OnHeaderLine(const AString & a_Key, const AString & a_Value) override; // cTransferEncodingParser::cCallbacks overrides: virtual void OnError(const AString & a_ErrorDescription) override; virtual void OnBodyData(const void * a_Data, size_t a_Size) override; virtual void OnBodyFinished(void) override; }; ================================================ FILE: src/HTTP/HTTPServer.cpp ================================================ // HTTPServer.cpp // Implements the cHTTPServer class representing a HTTP webserver that uses cListenThread and cSocketThreads for processing #include "Globals.h" #include "HTTPServer.h" #include "HTTPMessageParser.h" #include "HTTPServerConnection.h" #include "HTTPFormParser.h" #include "SslHTTPServerConnection.h" #include "../mbedTLS++/SslConfig.h" // Disable MSVC warnings: #if defined(_MSC_VER) #pragma warning(push) #pragma warning(disable:4355) // 'this' : used in base member initializer list #endif //////////////////////////////////////////////////////////////////////////////// // cHTTPServerListenCallbacks: class cHTTPServerListenCallbacks: public cNetwork::cListenCallbacks { public: cHTTPServerListenCallbacks(cHTTPServer & a_HTTPServer, UInt16 a_Port): m_HTTPServer(a_HTTPServer), m_Port(a_Port) { } protected: /** The HTTP server instance that we're attached to. */ cHTTPServer & m_HTTPServer; /** The port for which this instance is responsible. */ UInt16 m_Port; // cNetwork::cListenCallbacks overrides: virtual cTCPLink::cCallbacksPtr OnIncomingConnection(const AString & a_RemoteIPAddress, UInt16 a_RemotePort) override { return m_HTTPServer.OnIncomingConnection(a_RemoteIPAddress, a_RemotePort); } virtual void OnAccepted(cTCPLink & a_Link) override {} virtual void OnError(int a_ErrorCode, const AString & a_ErrorMsg) override { LOGWARNING("HTTP server error on port %d: %d (%s)", m_Port, a_ErrorCode, a_ErrorMsg.c_str()); } }; //////////////////////////////////////////////////////////////////////////////// // cHTTPServer: cHTTPServer::cHTTPServer(void) : m_Callbacks(nullptr) { } cHTTPServer::~cHTTPServer() { Stop(); } bool cHTTPServer::Initialize(void) { // Read the HTTPS cert + key: AString CertFile = cFile::ReadWholeFile("webadmin/httpscert.crt"); AString KeyFile = cFile::ReadWholeFile("webadmin/httpskey.pem"); if (!CertFile.empty() && !KeyFile.empty()) { auto Cert = std::make_shared(); int res = Cert->Parse(CertFile.data(), CertFile.size()); if (res == 0) { auto CertPrivKey = std::make_shared(); res = CertPrivKey->ParsePrivate(KeyFile.data(), KeyFile.size(), ""); if (res == 0) { // Modifyable locally but otherwise must be const auto Config = cSslConfig::MakeDefaultConfig(false); Config->SetOwnCert(Cert, CertPrivKey); m_SslConfig = std::move(Config); } else { // Reading the private key failed, reset the cert: LOGWARNING("WebServer: Cannot read HTTPS certificate private key: -0x%x", -res); } } else { LOGWARNING("WebServer: Cannot read HTTPS certificate: -0x%x", -res); } } // Notify the admin about the HTTPS / HTTP status if (m_SslConfig == nullptr) { LOGWARNING("WebServer: The server will run in unsecured HTTP mode."); LOGINFO("Put a valid HTTPS certificate in file 'webadmin/httpscert.crt' and its corresponding private key to 'webadmin/httpskey.pem' (without any password) to enable HTTPS support"); } else { LOGINFO("WebServer: The server will run in secure HTTPS mode."); } return true; } bool cHTTPServer::Start(cCallbacks & a_Callbacks, const AStringVector & a_Ports) { m_Callbacks = &a_Callbacks; // Open up requested ports: AStringVector ports; for (const auto & port : a_Ports) { UInt16 PortNum; if (!StringToInteger(port, PortNum)) { LOGWARNING("WebServer: Invalid port value: \"%s\". Ignoring.", port.c_str()); continue; } auto Handle = cNetwork::Listen(PortNum, std::make_shared(*this, PortNum)); if (Handle->IsListening()) { m_ServerHandles.push_back(Handle); ports.push_back(port); } } // for port - a_Ports[] // Inform the admin about the ports opened: AString reportPorts; for (const auto & port: ports) { if (!reportPorts.empty()) { reportPorts.append(", "); } reportPorts.append(port); } LOGINFO("WebAdmin is running on port(s) %s", reportPorts.c_str()); // Report success if at least one port opened successfully: return !m_ServerHandles.empty(); } void cHTTPServer::Stop(void) { for (const auto & handle : m_ServerHandles) { handle->Close(); } m_ServerHandles.clear(); } cTCPLink::cCallbacksPtr cHTTPServer::OnIncomingConnection(const AString & a_RemoteIPAddress, UInt16 a_RemotePort) { UNUSED(a_RemoteIPAddress); UNUSED(a_RemotePort); if (m_SslConfig != nullptr) { return std::make_shared(*this, m_SslConfig); } else { return std::make_shared(*this); } } void cHTTPServer::NewRequest(cHTTPServerConnection & a_Connection, cHTTPIncomingRequest & a_Request) { m_Callbacks->OnRequestBegun(a_Connection, a_Request); } void cHTTPServer::RequestBody(cHTTPServerConnection & a_Connection, cHTTPIncomingRequest & a_Request, const void * a_Data, size_t a_Size) { m_Callbacks->OnRequestBody(a_Connection, a_Request, static_cast(a_Data), a_Size); } void cHTTPServer::RequestFinished(cHTTPServerConnection & a_Connection, cHTTPIncomingRequest & a_Request) { m_Callbacks->OnRequestFinished(a_Connection, a_Request); } ================================================ FILE: src/HTTP/HTTPServer.h ================================================ // HTTPServer.h // Declares the cHTTPServer class representing a HTTP webserver that uses cListenThread and cSocketThreads for processing #pragma once #include "../OSSupport/Network.h" #include "../IniFile.h" #include "../mbedTLS++/CryptoKey.h" #include "../mbedTLS++/X509Cert.h" // fwd: class cHTTPIncomingRequest; class cHTTPServerConnection; class cSslConfig; class cHTTPServer { public: class cCallbacks { public: virtual ~cCallbacks() {} /** Called when a new request arrives over a connection and all its headers have been parsed. The request body needn't have arrived yet. */ virtual void OnRequestBegun(cHTTPServerConnection & a_Connection, cHTTPIncomingRequest & a_Request) = 0; /** Called when another part of request body has arrived. May be called multiple times for a single request. */ virtual void OnRequestBody(cHTTPServerConnection & a_Connection, cHTTPIncomingRequest & a_Request, const char * a_Data, size_t a_Size) = 0; /** Called when the request body has been fully received in previous calls to OnRequestBody() */ virtual void OnRequestFinished(cHTTPServerConnection & a_Connection, cHTTPIncomingRequest & a_Request) = 0; } ; cHTTPServer(void); virtual ~cHTTPServer(); /** Initializes the server - reads the cert files etc. */ bool Initialize(void); /** Starts the server and assigns the callbacks to use for incoming requests */ bool Start(cCallbacks & a_Callbacks, const AStringVector & a_Ports); /** Stops the server, drops all current connections */ void Stop(void); protected: friend class cHTTPServerConnection; friend class cSslHTTPServerConnection; friend class cHTTPServerListenCallbacks; /** The cNetwork API handle for the listening socket. */ cServerHandlePtrs m_ServerHandles; /** The callbacks to call for various events */ cCallbacks * m_Callbacks; /** Configuration for server ssl connections. */ std::shared_ptr m_SslConfig; /** Called by cHTTPServerListenCallbacks when there's a new incoming connection. Returns the connection instance to be used as the cTCPLink callbacks. */ cTCPLink::cCallbacksPtr OnIncomingConnection(const AString & a_RemoteIPAddress, UInt16 a_RemotePort); /** Called by cHTTPServerConnection when it finishes parsing the request header */ void NewRequest(cHTTPServerConnection & a_Connection, cHTTPIncomingRequest & a_Request); /** Called by cHTTPConenction when it receives more data for the request body. May be called multiple times for a single request. */ void RequestBody(cHTTPServerConnection & a_Connection, cHTTPIncomingRequest & a_Request, const void * a_Data, size_t a_Size); /** Called by cHTTPServerConnection when it detects that the request has finished (all of its body has been received) */ void RequestFinished(cHTTPServerConnection & a_Connection, cHTTPIncomingRequest & a_Request); } ; ================================================ FILE: src/HTTP/HTTPServerConnection.cpp ================================================ // HTTPConnection.cpp // Implements the cHTTPServerConnection class representing a single persistent connection in the HTTP server. #include "Globals.h" #include "HTTPServerConnection.h" #include "HTTPMessage.h" #include "HTTPServer.h" cHTTPServerConnection::cHTTPServerConnection(cHTTPServer & a_HTTPServer) : m_HTTPServer(a_HTTPServer), m_Parser(*this) { } cHTTPServerConnection::~cHTTPServerConnection() = default; void cHTTPServerConnection::SendStatusAndReason(int a_StatusCode, const AString & a_Response) { SendData(fmt::format(FMT_STRING("HTTP/1.1 {} {}\r\n"), a_StatusCode, a_Response)); SendData(fmt::format(FMT_STRING("Content-Length: {}\r\n\r\n"), a_Response)); SendData(a_Response.data(), a_Response.size()); m_CurrentRequest.reset(); m_Parser.Reset(); } void cHTTPServerConnection::SendNeedAuth(const AString & a_Realm) { SendData(fmt::format(FMT_STRING("HTTP/1.1 401 Unauthorized\r\nWWW-Authenticate: Basic realm=\"{}\"\r\nContent-Length: 0\r\n\r\n"), a_Realm)); m_CurrentRequest.reset(); m_Parser.Reset(); } void cHTTPServerConnection::Send(const cHTTPOutgoingResponse & a_Response) { ASSERT(m_CurrentRequest != nullptr); AString toSend; a_Response.AppendToData(toSend); SendData(toSend); } void cHTTPServerConnection::Send(const void * a_Data, size_t a_Size) { ASSERT(m_CurrentRequest != nullptr); // We're sending in Chunked transfer encoding SendData(fmt::format("{0:x}\r\n", a_Size)); SendData(a_Data, a_Size); SendData("\r\n"); } void cHTTPServerConnection::FinishResponse(void) { ASSERT(m_CurrentRequest != nullptr); SendData("0\r\n\r\n"); m_CurrentRequest.reset(); m_Parser.Reset(); } void cHTTPServerConnection::Terminate(void) { if (m_CurrentRequest != nullptr) { m_HTTPServer.RequestFinished(*this, *m_CurrentRequest); } m_Link->Close(); // Terminate the connection m_Link.reset(); } void cHTTPServerConnection::OnLinkCreated(cTCPLinkPtr a_Link) { ASSERT(m_Link == nullptr); m_Link = a_Link; } void cHTTPServerConnection::OnReceivedData(const char * a_Data, size_t a_Size) { ASSERT(m_Link != nullptr); m_Parser.Parse(a_Data, a_Size); } void cHTTPServerConnection::OnRemoteClosed(void) { if (m_CurrentRequest != nullptr) { m_HTTPServer.RequestFinished(*this, *m_CurrentRequest); } m_Link.reset(); } void cHTTPServerConnection::OnError(int a_ErrorCode, const AString & a_ErrorMsg) { OnRemoteClosed(); } void cHTTPServerConnection::OnError(const AString & a_ErrorDescription) { Terminate(); // HTTP data malformed, disconnect } void cHTTPServerConnection::OnFirstLine(const AString & a_FirstLine) { const auto Split = StringSplit(a_FirstLine, " "); if (Split.size() < 2) { // Invalid request line. We need at least the Method and URL: Terminate(); return; } // Create a new request object for this request: m_CurrentRequest = std::make_unique(Split[0], Split[1]); } void cHTTPServerConnection::OnHeaderLine(const AString & a_Key, const AString & a_Value) { if (m_CurrentRequest == nullptr) { return; } m_CurrentRequest->AddHeader(a_Key, a_Value); } void cHTTPServerConnection::OnHeadersFinished(void) { if (m_CurrentRequest == nullptr) { return; } m_HTTPServer.NewRequest(*this, *m_CurrentRequest); } void cHTTPServerConnection::OnBodyData(const void * a_Data, size_t a_Size) { if (m_CurrentRequest == nullptr) { return; } m_HTTPServer.RequestBody(*this, *m_CurrentRequest, a_Data, a_Size); } void cHTTPServerConnection::OnBodyFinished(void) { // Process the request: if (m_CurrentRequest != nullptr) { m_HTTPServer.RequestFinished(*this, *m_CurrentRequest); } // ...and reset: m_CurrentRequest.reset(); m_Parser.Reset(); } void cHTTPServerConnection::SendData(const void * a_Data, size_t a_Size) { m_Link->Send(a_Data, a_Size); } ================================================ FILE: src/HTTP/HTTPServerConnection.h ================================================ // HTTPConnection.h // Declares the cHTTPConnection class representing a single persistent connection in the HTTP server. #pragma once #include "../OSSupport/Network.h" #include "HTTPMessageParser.h" // fwd: class cHTTPServer; class cHTTPOutgoingResponse; class cHTTPIncomingRequest; class cHTTPServerConnection : public cTCPLink::cCallbacks, public cHTTPMessageParser::cCallbacks { public: /** Creates a new instance, connected to the specified HTTP server instance */ cHTTPServerConnection(cHTTPServer & a_HTTPServer); // Force a virtual destructor in all descendants virtual ~cHTTPServerConnection() override; /** Sends HTTP status code together with a_Reason (used for HTTP errors). Sends the a_Reason as the body as well, so that browsers display it. Clears the current request (since it's finished by this call). */ void SendStatusAndReason(int a_StatusCode, const AString & a_Reason); /** Sends the "401 unauthorized" reply together with instructions on authorizing, using the specified realm. Clears the current request (since it's finished by this call). */ void SendNeedAuth(const AString & a_Realm); /** Sends the headers contained in a_Response */ void Send(const cHTTPOutgoingResponse & a_Response); /** Sends the data as the response (may be called multiple times) */ void Send(const void * a_Data, size_t a_Size); /** Sends the data as the response (may be called multiple times) */ void Send(const AString & a_Data) { Send(a_Data.data(), a_Data.size()); } /** Indicates that the current response is finished, gets ready for receiving another request (HTTP 1.1 keepalive). Clears the current request (since it's finished by this call). */ void FinishResponse(void); /** Terminates the connection; finishes any request being currently processed */ void Terminate(void); protected: typedef std::map cNameValueMap; /** The parent webserver that is to be notified of events on this connection */ cHTTPServer & m_HTTPServer; /** The parser responsible for reading the requests. */ cHTTPMessageParser m_Parser; /** The request being currently received Valid only between having parsed the headers and finishing receiving the body. */ std::unique_ptr m_CurrentRequest; /** The network link attached to this connection. */ cTCPLinkPtr m_Link; // cTCPLink::cCallbacks overrides: /** The link instance has been created, remember it. */ virtual void OnLinkCreated(cTCPLinkPtr a_Link) override; /** Data is received from the client. */ virtual void OnReceivedData(const char * a_Data, size_t a_Size) override; /** The socket has been closed for any reason. */ virtual void OnRemoteClosed(void) override; /** An error has occurred on the socket. */ virtual void OnError(int a_ErrorCode, const AString & a_ErrorMsg) override; // cHTTPMessageParser::cCallbacks overrides: virtual void OnError(const AString & a_ErrorDescription) override; virtual void OnFirstLine(const AString & a_FirstLine) override; virtual void OnHeaderLine(const AString & a_Key, const AString & a_Value) override; virtual void OnHeadersFinished(void) override; virtual void OnBodyData(const void * a_Data, size_t a_Size) override; virtual void OnBodyFinished(void) override; // Overridable: /** Called to send raw data over the link. Descendants may provide data transformations (SSL etc.) */ virtual void SendData(const void * a_Data, size_t a_Size); /** Sends the raw data over the link. Descendants may provide data transformations (SSL etc.) via the overridable SendData() function. */ void SendData(const AString & a_Data) { SendData(a_Data.data(), a_Data.size()); } } ; typedef std::vector cHTTPServerConnections; ================================================ FILE: src/HTTP/MultipartParser.cpp ================================================ // MultipartParser.cpp // Implements the cMultipartParser class that parses messages in "multipart/*" encoding into the separate parts #include "Globals.h" #include "MultipartParser.h" #include "NameValueParser.h" // Disable MSVC warnings: #if defined(_MSC_VER) #pragma warning(push) #pragma warning(disable:4355) // 'this' : used in base member initializer list #endif //////////////////////////////////////////////////////////////////////////////// // self-test: #if 0 class cMultipartParserTest : public cMultipartParser::cCallbacks { public: cMultipartParserTest(void) { cMultipartParser Parser("multipart/mixed; boundary=\"MyBoundaryString\"; foo=bar", *this); const char Data[] = "ThisIsIgnoredPrologue\r\n\ --MyBoundaryString\r\n\ \r\n\ Body with confusing strings\r\n\ --NotABoundary\r\n\ --MyBoundaryStringWithPostfix\r\n\ --\r\n\ --MyBoundaryString\r\n\ content-disposition: inline\r\n\ \r\n\ This is body\r\n\ --MyBoundaryString\r\n\ \r\n\ Headerless body with trailing CRLF\r\n\ \r\n\ --MyBoundaryString--\r\n\ ThisIsIgnoredEpilogue"; printf("Multipart parsing test commencing.\n"); Parser.Parse(Data, sizeof(Data) - 1); // DEBUG: Check if the onscreen output corresponds with the data above printf("Multipart parsing test finished\n"); } virtual void OnPartStart(void) override { printf("Starting a new part\n"); } virtual void OnPartHeader(const AString & a_Key, const AString & a_Value) override { printf(" Hdr: \"%s\"=\"%s\"\n", a_Key.c_str(), a_Value.c_str()); } virtual void OnPartData(const char * a_Data, int a_Size) override { printf(" Data: %d bytes, \"%.*s\"\n", a_Size, a_Size, a_Data); } virtual void OnPartEnd(void) override { printf("Part end\n"); } } g_Test; #endif //////////////////////////////////////////////////////////////////////////////// // cMultipartParser: cMultipartParser::cMultipartParser(const AString & a_ContentType, cCallbacks & a_Callbacks) : m_Callbacks(a_Callbacks), m_IsValid(true), m_EnvelopeParser(*this), m_HasHadData(false) { // Check that the content type is multipart: AString ContentType(a_ContentType); if (strncmp(ContentType.c_str(), "multipart/", 10) != 0) { m_IsValid = false; return; } size_t idxSC = ContentType.find(';', 10); if (idxSC == AString::npos) { m_IsValid = false; return; } // Find the multipart boundary: ContentType.erase(0, idxSC + 1); cNameValueParser CTParser(ContentType.c_str(), ContentType.size()); CTParser.Finish(); if (!CTParser.IsValid()) { m_IsValid = false; return; } m_Boundary = CTParser["boundary"]; m_IsValid = !m_Boundary.empty(); if (!m_IsValid) { return; } // Set the envelope parser for parsing the body, so that our Parse() function parses the ignored prefix data as a body m_EnvelopeParser.SetIsInHeaders(false); // Append an initial CRLF to the incoming data, so that a body starting with the boundary line will get caught m_IncomingData.assign("\r\n"); /* m_Boundary = AString("\r\n--") + m_Boundary m_BoundaryEnd = m_Boundary + "--\r\n"; m_Boundary = m_Boundary + "\r\n"; */ } void cMultipartParser::Parse(const char * a_Data, size_t a_Size) { // Skip parsing if invalid if (!m_IsValid) { return; } // Append to buffer, then parse it: m_IncomingData.append(a_Data, a_Size); for (;;) { if (m_EnvelopeParser.IsInHeaders()) { size_t BytesConsumed = m_EnvelopeParser.Parse(m_IncomingData.data(), m_IncomingData.size()); if (BytesConsumed == AString::npos) { m_IsValid = false; return; } if ((BytesConsumed == a_Size) && m_EnvelopeParser.IsInHeaders()) { // All the incoming data has been consumed and still waiting for more return; } m_IncomingData.erase(0, BytesConsumed); } // Search for boundary / boundary end: size_t idxBoundary = m_IncomingData.find("\r\n--"); if (idxBoundary == AString::npos) { // Boundary string start not present, present as much data to the part callback as possible if (m_IncomingData.size() > m_Boundary.size() + 8) { size_t BytesToReport = m_IncomingData.size() - m_Boundary.size() - 8; m_Callbacks.OnPartData(m_IncomingData.data(), BytesToReport); m_IncomingData.erase(0, BytesToReport); } return; } if (idxBoundary > 0) { m_Callbacks.OnPartData(m_IncomingData.data(), idxBoundary); m_IncomingData.erase(0, idxBoundary); } idxBoundary = 4; size_t LineEnd = m_IncomingData.find("\r\n", idxBoundary); if (LineEnd == AString::npos) { // Not a complete line yet, present as much data to the part callback as possible if (m_IncomingData.size() > m_Boundary.size() + 8) { size_t BytesToReport = m_IncomingData.size() - m_Boundary.size() - 8; m_Callbacks.OnPartData(m_IncomingData.data(), BytesToReport); m_IncomingData.erase(0, BytesToReport); } return; } if ( (LineEnd - idxBoundary != m_Boundary.size()) && // Line length not equal to boundary (LineEnd - idxBoundary != m_Boundary.size() + 2) // Line length not equal to boundary end ) { // Got a line, but it's not a boundary, report it as data: m_Callbacks.OnPartData(m_IncomingData.data(), LineEnd); m_IncomingData.erase(0, LineEnd); continue; } if (strncmp(m_IncomingData.c_str() + idxBoundary, m_Boundary.c_str(), m_Boundary.size()) == 0) { // Boundary or BoundaryEnd found: m_Callbacks.OnPartEnd(); size_t idxSlash = idxBoundary + m_Boundary.size(); if ((m_IncomingData[idxSlash] == '-') && (m_IncomingData[idxSlash + 1] == '-')) { // This was the last part m_Callbacks.OnPartData(m_IncomingData.data() + idxSlash + 4, m_IncomingData.size() - idxSlash - 4); m_IncomingData.clear(); return; } m_Callbacks.OnPartStart(); m_IncomingData.erase(0, LineEnd + 2); // Keep parsing for the headers that may have come with this data: m_EnvelopeParser.Reset(); continue; } // It's a line, but not a boundary. It can be fully sent to the data receiver, since a boundary cannot cross lines m_Callbacks.OnPartData(m_IncomingData.c_str(), LineEnd); m_IncomingData.erase(0, LineEnd); } // while (true) } void cMultipartParser::OnHeaderLine(const AString & a_Key, const AString & a_Value) { m_Callbacks.OnPartHeader(a_Key, a_Value); } ================================================ FILE: src/HTTP/MultipartParser.h ================================================ // MultipartParser.h // Declares the cMultipartParser class that parses messages in "multipart/*" encoding into the separate parts #pragma once #include "EnvelopeParser.h" class cMultipartParser : protected cEnvelopeParser::cCallbacks { public: class cCallbacks { public: // Force a virtual destructor in descendants: virtual ~cCallbacks() {} /** Called when a new part starts */ virtual void OnPartStart(void) = 0; /** Called when a complete header line is received for a part */ virtual void OnPartHeader(const AString & a_Key, const AString & a_Value) = 0; /** Called when body for a part is received */ virtual void OnPartData(const char * a_Data, size_t a_Size) = 0; /** Called when the current part ends */ virtual void OnPartEnd(void) = 0; } ; /** Creates the parser, expects to find the boundary in a_ContentType */ cMultipartParser(const AString & a_ContentType, cCallbacks & a_Callbacks); /** Parses more incoming data */ void Parse(const char * a_Data, size_t a_Size); protected: /** The callbacks to call for various parsing events */ cCallbacks & m_Callbacks; /** True if the data parsed so far is valid; if false, further parsing is skipped */ bool m_IsValid; /** Parser for each part's envelope */ cEnvelopeParser m_EnvelopeParser; /** Buffer for the incoming data until it is parsed */ AString m_IncomingData; /** The boundary, excluding both the initial "--" and the terminating CRLF */ AString m_Boundary; /** Set to true if some data for the current part has already been signalized to m_Callbacks. Used for proper CRLF inserting. */ bool m_HasHadData; /** Parse one line of incoming data. The CRLF has already been stripped from a_Data / a_Size */ void ParseLine(const char * a_Data, size_t a_Size); /** Parse one line of incoming data in the headers section of a part. The CRLF has already been stripped from a_Data / a_Size */ void ParseHeaderLine(const char * a_Data, size_t a_Size); // cEnvelopeParser overrides: virtual void OnHeaderLine(const AString & a_Key, const AString & a_Value) override; } ; ================================================ FILE: src/HTTP/NameValueParser.cpp ================================================ // NameValueParser.cpp // Implements the cNameValueParser class that parses strings in the "name=value;name2=value2" format into a stringmap #include "Globals.h" #include "NameValueParser.h" // DEBUG: Self-test #if 0 class cNameValueParserTest { public: cNameValueParserTest(void) { const char Data[] = " Name1=Value1;Name2 = Value 2; Name3 =\"Value 3\"; Name4 =\'Value 4\'; Name5=\"Confusing; isn\'t it?\""; // Now try parsing char-by-char, to debug transitions across datachunk boundaries: cNameValueParser Parser2; for (size_t i = 0; i < sizeof(Data) - 1; i++) { Parser2.Parse(Data + i, 1); } Parser2.Finish(); // Parse as a single chunk of data: cNameValueParser Parser(Data, sizeof(Data) - 1); // Use the debugger to inspect the Parser variable // Check that the two parsers have the same content: for (cNameValueParser::const_iterator itr = Parser.begin(), end = Parser.end(); itr != end; ++itr) { ASSERT(Parser2[itr->first] == itr->second); } // for itr - Parser[] // Try parsing in 2-char chunks: cNameValueParser Parser3; for (int i = 0; i < sizeof(Data) - 2; i += 2) { Parser3.Parse(Data + i, 2); } if ((sizeof(Data) % 2) == 0) // There are even number of chars, including the NUL, so the data has an odd length. Parse one more char { Parser3.Parse(Data + sizeof(Data) - 2, 1); } Parser3.Finish(); // Check that the third parser has the same content: for (cNameValueParser::const_iterator itr = Parser.begin(), end = Parser.end(); itr != end; ++itr) { ASSERT(Parser3[itr->first] == itr->second); } // for itr - Parser[] printf("cNameValueParserTest done"); } } g_Test; #endif //////////////////////////////////////////////////////////////////////////////// // cNameValueParser: cNameValueParser::cNameValueParser(bool a_AllowsKeyOnly) : m_State(psKeySpace), m_AllowsKeyOnly(a_AllowsKeyOnly) { } cNameValueParser::cNameValueParser(const char * a_Data, size_t a_Size, bool a_AllowsKeyOnly) : m_State(psKeySpace), m_AllowsKeyOnly(a_AllowsKeyOnly) { Parse(a_Data, a_Size); } void cNameValueParser::Parse(const char * a_Data, size_t a_Size) { ASSERT(m_State != psFinished); // Calling Parse() after Finish() is wrong! size_t Last = 0; for (size_t i = 0; i < a_Size;) { switch (m_State) { case psInvalid: case psFinished: { return; } case psKeySpace: { // Skip whitespace until a non-whitespace is found, then start the key: while ((i < a_Size) && (a_Data[i] <= ' ')) { i++; } if ((i < a_Size) && (a_Data[i] > ' ')) { m_State = psKey; Last = i; } break; } case psKey: { // Read the key until whitespace or an equal sign: while (i < a_Size) { if (a_Data[i] == '=') { m_CurrentKey.append(a_Data + Last, i - Last); i++; Last = i; m_State = psEqual; break; } else if (a_Data[i] <= ' ') { m_CurrentKey.append(a_Data + Last, i - Last); i++; Last = i; m_State = psEqualSpace; break; } else if (a_Data[i] == ';') { if (!m_AllowsKeyOnly) { m_State = psInvalid; return; } m_CurrentKey.append(a_Data + Last, i - Last); i++; Last = i; (*this)[m_CurrentKey] = ""; m_CurrentKey.clear(); m_State = psKeySpace; break; } else if ((a_Data[i] == '\"') || (a_Data[i] == '\'')) { m_State = psInvalid; return; } i++; } // while (i < a_Size) if (i == a_Size) { // Still the key, ran out of data to parse, store the part of the key parsed so far: m_CurrentKey.append(a_Data + Last, a_Size - Last); return; } break; } case psEqualSpace: { // The space before the expected equal sign; the current key is already assigned while (i < a_Size) { if (a_Data[i] == '=') { m_State = psEqual; i++; Last = i; break; } else if (a_Data[i] == ';') { // Key-only if (!m_AllowsKeyOnly) { m_State = psInvalid; return; } i++; Last = i; (*this)[m_CurrentKey] = ""; m_CurrentKey.clear(); m_State = psKeySpace; break; } else if (a_Data[i] > ' ') { m_State = psInvalid; return; } i++; } // while (i < a_Size) break; } // case psEqualSpace case psEqual: { // just parsed the equal-sign while (i < a_Size) { if (a_Data[i] == ';') { if (!m_AllowsKeyOnly) { m_State = psInvalid; return; } i++; Last = i; (*this)[m_CurrentKey] = ""; m_CurrentKey.clear(); m_State = psKeySpace; break; } else if (a_Data[i] == '\"') { i++; Last = i; m_State = psValueInDQuotes; break; } else if (a_Data[i] == '\'') { i++; Last = i; m_State = psValueInSQuotes; break; } else { m_CurrentValue.push_back(a_Data[i]); i++; Last = i; m_State = psValueRaw; break; } } // while (i < a_Size) break; } // case psEqual case psValueInDQuotes: { while (i < a_Size) { if (a_Data[i] == '\"') { m_CurrentValue.append(a_Data + Last, i - Last); (*this)[m_CurrentKey] = m_CurrentValue; m_CurrentKey.clear(); m_CurrentValue.clear(); m_State = psAfterValue; i++; Last = i; break; } i++; } // while (i < a_Size) if (i == a_Size) { m_CurrentValue.append(a_Data + Last, a_Size - Last); } break; } // case psValueInDQuotes case psValueInSQuotes: { while (i < a_Size) { if (a_Data[i] == '\'') { m_CurrentValue.append(a_Data + Last, i - Last); (*this)[m_CurrentKey] = m_CurrentValue; m_CurrentKey.clear(); m_CurrentValue.clear(); m_State = psAfterValue; i++; Last = i; break; } i++; } // while (i < a_Size) if (i == a_Size) { m_CurrentValue.append(a_Data + Last, a_Size - Last); } break; } // case psValueInSQuotes case psValueRaw: { while (i < a_Size) { if (a_Data[i] == ';') { m_CurrentValue.append(a_Data + Last, i - Last); (*this)[m_CurrentKey] = m_CurrentValue; m_CurrentKey.clear(); m_CurrentValue.clear(); m_State = psKeySpace; i++; Last = i; break; } i++; } if (i == a_Size) { m_CurrentValue.append(a_Data + Last, a_Size - Last); } break; } // case psValueRaw case psAfterValue: { // Between the closing DQuote or SQuote and the terminating semicolon while (i < a_Size) { if (a_Data[i] == ';') { m_State = psKeySpace; i++; Last = i; break; } else if (a_Data[i] < ' ') { i++; continue; } m_State = psInvalid; return; } // while (i < a_Size) break; } } // switch (m_State) } // for i - a_Data[] } bool cNameValueParser::Finish(void) { switch (m_State) { case psInvalid: { return false; } case psFinished: { return true; } case psKey: case psEqualSpace: case psEqual: { if ((m_AllowsKeyOnly) && !m_CurrentKey.empty()) { (*this)[m_CurrentKey] = ""; m_State = psFinished; return true; } m_State = psInvalid; return false; } case psValueRaw: { (*this)[m_CurrentKey] = m_CurrentValue; m_State = psFinished; return true; } case psValueInDQuotes: case psValueInSQuotes: { // Missing the terminating quotes, this is an error m_State = psInvalid; return false; } case psKeySpace: case psAfterValue: { m_State = psFinished; return true; } } UNREACHABLE("Unsupported name value parser state"); } ================================================ FILE: src/HTTP/NameValueParser.h ================================================ // NameValueParser.h // Declares the cNameValueParser class that parses strings in the "name=value;name2=value2" format into a stringmap #pragma once class cNameValueParser : public std::map { public: /** Creates an empty parser */ cNameValueParser(bool a_AllowsKeyOnly = true); /** Creates an empty parser, then parses the data given. Doesn't call Finish(), so more data can be parsed later */ cNameValueParser(const char * a_Data, size_t a_Size, bool a_AllowsKeyOnly = true); /** Parses the data given */ void Parse(const char * a_Data, size_t a_Size); /** Notifies the parser that no more data will be coming. Returns true if the parser state is valid */ bool Finish(void); /** Returns true if the data parsed so far was valid */ bool IsValid(void) const { return (m_State != psInvalid); } /** Returns true if the parser expects no more data */ bool IsFinished(void) const { return ((m_State == psInvalid) || (m_State == psFinished)); } protected: enum eState { psKeySpace, ///< Parsing the space in front of the next key psKey, ///< Currently adding more chars to the key in m_CurrentKey psEqualSpace, ///< Space after m_CurrentKey psEqual, ///< Just parsed the = sign after a name psValueInSQuotes, ///< Just parsed a Single-quote sign after the Equal sign psValueInDQuotes, ///< Just parsed a Double-quote sign after the Equal sign psValueRaw, ///< Just parsed a raw value without a quote psAfterValue, ///< Just finished parsing the value, waiting for semicolon or data end psInvalid, ///< The parser has encountered an invalid input; further parsing is skipped psFinished, ///< The parser has already been instructed to finish and doesn't expect any more data } ; /** The current state of the parser */ eState m_State; /** If true, the parser will accept keys without an equal sign and the value */ bool m_AllowsKeyOnly; /** Buffer for the current Key */ AString m_CurrentKey; /** Buffer for the current Value; */ AString m_CurrentValue; } ; ================================================ FILE: src/HTTP/SslHTTPServerConnection.cpp ================================================ // SslHTTPConnection.cpp // Implements the cSslHTTPServerConnection class representing a HTTP connection made over a SSL link #include "Globals.h" #include "SslHTTPServerConnection.h" #include "HTTPServer.h" cSslHTTPServerConnection::cSslHTTPServerConnection( cHTTPServer & a_HTTPServer, const std::shared_ptr & a_Config ): Super(a_HTTPServer), m_Ssl(64000) { if (a_Config != nullptr) { m_Ssl.Initialize(a_Config); } else { m_Ssl.Initialize(false); } } cSslHTTPServerConnection::~cSslHTTPServerConnection() { m_Ssl.NotifyClose(); } void cSslHTTPServerConnection::OnReceivedData(const char * a_Data, size_t a_Size) { // Process the received data: const char * Data = a_Data; size_t Size = a_Size; for (;;) { // Try to write as many bytes into Ssl's "incoming" buffer as possible: size_t BytesWritten = 0; if (Size > 0) { BytesWritten = m_Ssl.WriteIncoming(Data, Size); Data += BytesWritten; Size -= BytesWritten; } // Try to read as many bytes from SSL's decryption as possible: char Buffer[32000]; int NumRead = m_Ssl.ReadPlain(Buffer, sizeof(Buffer)); if (NumRead > 0) { Super::OnReceivedData(Buffer, static_cast(NumRead)); // The link may have closed while processing the data, bail out: return; } else if (NumRead == MBEDTLS_ERR_SSL_WANT_READ) { // SSL requires us to send data to peer first, do so by "sending" empty data: SendData(nullptr, 0); } // If both failed, bail out: if ((BytesWritten == 0) && (NumRead <= 0)) { return; } } } void cSslHTTPServerConnection::SendData(const void * a_Data, size_t a_Size) { const char * OutgoingData = static_cast(a_Data); size_t pos = 0; for (;;) { // Write as many bytes from our buffer to SSL's encryption as possible: int NumWritten = 0; if (pos < a_Size) { NumWritten = m_Ssl.WritePlain(OutgoingData + pos, a_Size - pos); if (NumWritten > 0) { pos += static_cast(NumWritten); } } // Read as many bytes from SSL's "outgoing" buffer as possible: char Buffer[32000]; size_t NumBytes = m_Ssl.ReadOutgoing(Buffer, sizeof(Buffer)); if (NumBytes > 0) { m_Link->Send(Buffer, NumBytes); } // If both failed, bail out: if ((NumWritten <= 0) && (NumBytes == 0)) { return; } } } ================================================ FILE: src/HTTP/SslHTTPServerConnection.h ================================================ // SslHTTPServerConnection.h // Declares the cSslHTTPServerConnection class representing a HTTP connection made over an SSL link #pragma once #include "HTTPServerConnection.h" #include "../mbedTLS++/BufferedSslContext.h" class cSslHTTPServerConnection: public cHTTPServerConnection { using Super = cHTTPServerConnection; public: /** Creates a new connection on the specified server. Sends the specified cert as the server certificate, uses the private key for decryption. */ cSslHTTPServerConnection(cHTTPServer & a_HTTPServer, const std::shared_ptr & a_Config); virtual ~cSslHTTPServerConnection() override; protected: cBufferedSslContext m_Ssl; // cHTTPConnection overrides: virtual void OnReceivedData(const char * a_Data, size_t a_Size) override; // Data is received from the client virtual void SendData(const void * a_Data, size_t a_Size) override; // Data is to be sent to client } ; ================================================ FILE: src/HTTP/TransferEncodingParser.cpp ================================================ // TransferEncodingParser.cpp // Implements the cTransferEncodingParser class and its descendants representing the parsers for the various transfer encodings (chunked etc.) #include "Globals.h" #include "TransferEncodingParser.h" #include "EnvelopeParser.h" //////////////////////////////////////////////////////////////////////////////// // cChunkedTEParser: class cChunkedTEParser: public cTransferEncodingParser, public cEnvelopeParser::cCallbacks { using Super = cTransferEncodingParser; public: cChunkedTEParser(Super::cCallbacks & a_Callbacks): Super(a_Callbacks), m_State(psChunkLength), m_ChunkDataLengthLeft(0), m_TrailerParser(*this) { } protected: enum eState { psChunkLength, ///< Parsing the chunk length hex number psChunkLengthTrailer, ///< Any trailer (chunk extension) specified after the chunk length psChunkLengthLF, ///< The LF character after the CR character terminating the chunk length psChunkData, ///< Relaying chunk data psChunkDataCR, ///< Skipping the extra CR character after chunk data psChunkDataLF, ///< Skipping the extra LF character after chunk data psTrailer, ///< Received an empty chunk, parsing the trailer (through the envelope parser) psFinished, ///< The parser has finished parsing, either successfully or with an error }; /** The current state of the parser (parsing chunk length / chunk data). */ eState m_State; /** Number of bytes that still belong to the chunk currently being parsed. When in psChunkLength, the value is the currently parsed length digits. */ size_t m_ChunkDataLengthLeft; /** The parser used for the last (empty) chunk's trailer data */ cEnvelopeParser m_TrailerParser; /** Calls the OnError callback and sets parser state to finished. */ void Error(const AString & a_ErrorMsg) { m_State = psFinished; m_Callbacks.OnError(a_ErrorMsg); } /** Parses the incoming data, the current state is psChunkLength. Stops parsing when either the chunk length has been read, or there is no more data in the input. Returns the number of bytes consumed from the input, or AString::npos on error (calls the Error handler). */ size_t ParseChunkLength(const char * a_Data, size_t a_Size) { // Expected input: [;] // Only the hexnumber is parsed into m_ChunkDataLengthLeft, the rest is postponed into psChunkLengthTrailer or psChunkLengthLF for (size_t i = 0; i < a_Size; i++) { switch (a_Data[i]) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { m_ChunkDataLengthLeft = m_ChunkDataLengthLeft * 16 + static_cast(a_Data[i] - '0'); break; } case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': { m_ChunkDataLengthLeft = m_ChunkDataLengthLeft * 16 + static_cast(a_Data[i] - 'a' + 10); break; } case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': { m_ChunkDataLengthLeft = m_ChunkDataLengthLeft * 16 + static_cast(a_Data[i] - 'A' + 10); break; } case '\r': { m_State = psChunkLengthLF; return i + 1; } case ';': { m_State = psChunkLengthTrailer; return i + 1; } default: { Error(fmt::format(FMT_STRING("Invalid character in chunk length line: 0x{:02x}"), a_Data[i])); return AString::npos; } } // switch (a_Data[i]) } // for i - a_Data[] return a_Size; } /** Parses the incoming data, the current state is psChunkLengthTrailer. Stops parsing when either the chunk length trailer has been read, or there is no more data in the input. Returns the number of bytes consumed from the input, or AString::npos on error (calls the Error handler). */ size_t ParseChunkLengthTrailer(const char * a_Data, size_t a_Size) { // Expected input: // The LF itself is not parsed, it is instead postponed into psChunkLengthLF for (size_t i = 0; i < a_Size; i++) { switch (a_Data[i]) { case '\r': { m_State = psChunkLengthLF; return i; } default: { if (a_Data[i] < 32) { // Only printable characters are allowed in the trailer Error(fmt::format(FMT_STRING("Invalid character in chunk length line: 0x{:02x}"), a_Data[i])); return AString::npos; } } } // switch (a_Data[i]) } // for i - a_Data[] return a_Size; } /** Parses the incoming data, the current state is psChunkLengthLF. Only the LF character is expected, if found, moves to psChunkData, otherwise issues an error. If the chunk length that just finished reading is equal to 0, signals the end of stream (via psTrailer). Returns the number of bytes consumed from the input, or AString::npos on error (calls the Error handler). */ size_t ParseChunkLengthLF(const char * a_Data, size_t a_Size) { // Expected input: if (a_Size == 0) { return 0; } if (a_Data[0] == '\n') { if (m_ChunkDataLengthLeft == 0) { m_State = psTrailer; } else { m_State = psChunkData; } return 1; } Error(fmt::format(FMT_STRING("Invalid character past chunk length's CR: 0x{:02x}"), a_Data[0])); return AString::npos; } /** Consumes as much chunk data from the input as possible. Returns the number of bytes consumed from the input, or AString::npos on error (calls the Error() handler). */ size_t ParseChunkData(const char * a_Data, size_t a_Size) { ASSERT(m_ChunkDataLengthLeft > 0); auto bytes = std::min(a_Size, m_ChunkDataLengthLeft); m_ChunkDataLengthLeft -= bytes; m_Callbacks.OnBodyData(a_Data, bytes); if (m_ChunkDataLengthLeft == 0) { m_State = psChunkDataCR; } return bytes; } /** Parses the incoming data, the current state is psChunkDataCR. Only the CR character is expected, if found, moves to psChunkDataLF, otherwise issues an error. Returns the number of bytes consumed from the input, or AString::npos on error (calls the Error handler). */ size_t ParseChunkDataCR(const char * a_Data, size_t a_Size) { // Expected input: if (a_Size == 0) { return 0; } if (a_Data[0] == '\r') { m_State = psChunkDataLF; return 1; } Error(fmt::format(FMT_STRING("Invalid character past chunk data: 0x{:02x}"), a_Data[0])); return AString::npos; } /** Parses the incoming data, the current state is psChunkDataCR. Only the CR character is expected, if found, moves to psChunkDataLF, otherwise issues an error. Returns the number of bytes consumed from the input, or AString::npos on error (calls the Error handler). */ size_t ParseChunkDataLF(const char * a_Data, size_t a_Size) { // Expected input: if (a_Size == 0) { return 0; } if (a_Data[0] == '\n') { m_State = psChunkLength; return 1; } Error(fmt::format(FMT_STRING("Invalid character past chunk data's CR: 0x{:02x}"), a_Data[0])); return AString::npos; } /** Parses the incoming data, the current state is psChunkDataCR. The trailer is normally a set of "Header: Value" lines, terminated by an empty line. Use the m_TrailerParser for that. Returns the number of bytes consumed from the input, or AString::npos on error (calls the Error handler). */ size_t ParseTrailer(const char * a_Data, size_t a_Size) { auto res = m_TrailerParser.Parse(a_Data, a_Size); if (res == AString::npos) { Error("Error while parsing the trailer"); } if ((res < a_Size) || !m_TrailerParser.IsInHeaders()) { m_Callbacks.OnBodyFinished(); m_State = psFinished; } return res; } // cTransferEncodingParser overrides: virtual size_t Parse(const char * a_Data, size_t a_Size) override { while ((a_Size > 0) && (m_State != psFinished)) { size_t consumed = 0; switch (m_State) { case psChunkLength: consumed = ParseChunkLength (a_Data, a_Size); break; case psChunkLengthTrailer: consumed = ParseChunkLengthTrailer(a_Data, a_Size); break; case psChunkLengthLF: consumed = ParseChunkLengthLF (a_Data, a_Size); break; case psChunkData: consumed = ParseChunkData (a_Data, a_Size); break; case psChunkDataCR: consumed = ParseChunkDataCR (a_Data, a_Size); break; case psChunkDataLF: consumed = ParseChunkDataLF (a_Data, a_Size); break; case psTrailer: consumed = ParseTrailer (a_Data, a_Size); break; case psFinished: consumed = 0; break; // Not supposed to happen, but Clang complains without it } if (consumed == AString::npos) { return AString::npos; } a_Data += consumed; a_Size -= consumed; } return a_Size; } virtual void Finish() override { if (m_State != psFinished) { Error(fmt::format(FMT_STRING("ChunkedTransferEncoding: Finish signal received before the data stream ended (state: {})"), m_State)); } m_State = psFinished; } // cEnvelopeParser::cCallbacks overrides: virtual void OnHeaderLine(const AString & a_Key, const AString & a_Value) override { // Ignored } }; //////////////////////////////////////////////////////////////////////////////// // cIdentityTEParser: class cIdentityTEParser: public cTransferEncodingParser { using Super = cTransferEncodingParser; public: cIdentityTEParser(cCallbacks & a_Callbacks, size_t a_ContentLength): Super(a_Callbacks), m_BytesLeft(a_ContentLength) { } protected: /** How many bytes of content are left before the message ends. */ size_t m_BytesLeft; // cTransferEncodingParser overrides: virtual size_t Parse(const char * a_Data, size_t a_Size) override { auto size = std::min(a_Size, m_BytesLeft); if (size > 0) { m_Callbacks.OnBodyData(a_Data, size); } m_BytesLeft -= size; if (m_BytesLeft == 0) { m_Callbacks.OnBodyFinished(); } return a_Size - size; } virtual void Finish(void) override { if (m_BytesLeft > 0) { m_Callbacks.OnError("IdentityTransferEncoding: body was truncated"); } else { // BodyFinished has already been called, just bail out } } }; //////////////////////////////////////////////////////////////////////////////// // cTransferEncodingParser: cTransferEncodingParserPtr cTransferEncodingParser::Create( cCallbacks & a_Callbacks, const AString & a_TransferEncoding, size_t a_ContentLength ) { if (a_TransferEncoding == "chunked") { return std::make_shared(a_Callbacks); } if (a_TransferEncoding == "identity") { return std::make_shared(a_Callbacks, a_ContentLength); } if (a_TransferEncoding.empty()) { return std::make_shared(a_Callbacks, a_ContentLength); } return nullptr; } ================================================ FILE: src/HTTP/TransferEncodingParser.h ================================================ // TransferEncodingParser.h // Declares the cTransferEncodingParser class representing the parser for the various transfer encodings (chunked etc.) #pragma once // fwd: class cTransferEncodingParser; typedef std::shared_ptr cTransferEncodingParserPtr; /** Used as both the interface that all the parsers share and the (static) factory creating such parsers. */ class cTransferEncodingParser { public: class cCallbacks { public: // Force a virtual destructor in descendants virtual ~cCallbacks() {} /** Called when an error has occured while parsing. */ virtual void OnError(const AString & a_ErrorDescription) = 0; /** Called for each chunk of the incoming body data. */ virtual void OnBodyData(const void * a_Data, size_t a_Size) = 0; /** Called when the entire body has been reported by OnBodyData(). */ virtual void OnBodyFinished(void) = 0; }; // Force a virtual destructor in all descendants virtual ~cTransferEncodingParser() {} /** Parses the incoming data and calls the appropriate callbacks. Returns the number of bytes from the end of a_Data that is already not part of this message (if the parser can detect it). Returns AString::npos on an error. */ virtual size_t Parse(const char * a_Data, size_t a_Size) = 0; /** To be called when the stream is terminated from the source (connection closed). Flushes any buffers and calls appropriate callbacks. */ virtual void Finish(void) = 0; /** Creates a new parser for the specified encoding. If the encoding is not known, returns a nullptr. a_ContentLength is the length of the content, received in a Content-Length header. It is used for the Identity encoding, it is ignored for the Chunked encoding. */ static cTransferEncodingParserPtr Create( cCallbacks & a_Callbacks, const AString & a_TransferEncoding, size_t a_ContentLength ); protected: /** The callbacks used to report progress. */ cCallbacks & m_Callbacks; cTransferEncodingParser(cCallbacks & a_Callbacks): m_Callbacks(a_Callbacks) { } }; ================================================ FILE: src/HTTP/UrlClient.cpp ================================================ // UrlClient.cpp // Implements the cUrlClient class for high-level URL interaction #include "Globals.h" #include "HTTP/UrlClient.h" #include "HTTP/UrlParser.h" #include "HTTP/HTTPMessageParser.h" #include "mbedTLS++/X509Cert.h" #include "mbedTLS++/CryptoKey.h" // fwd: class cSchemeHandler; using cSchemeHandlerPtr = std::shared_ptr; namespace { /** Callbacks implementing the blocking UrlClient behavior. */ class cBlockingHTTPCallbacks : public cUrlClient::cCallbacks { public: explicit cBlockingHTTPCallbacks(std::shared_ptr a_Event, AString & a_ResponseBody) : m_Event(std::move(a_Event)), m_ResponseBody(a_ResponseBody), m_IsError(false) { } void OnBodyFinished() override { m_Event->Set(); } void OnError(const AString & a_ErrorMsg) override { LOGERROR("%s %d: HTTP Error: %s", __FILE__, __LINE__, a_ErrorMsg.c_str()); m_IsError = true; m_Event->Set(); } void OnBodyData(const void * a_Data, size_t a_Size) override { m_ResponseBody.append(static_cast(a_Data), a_Size); } std::shared_ptr m_Event; /** The accumulator for the partial body data, so that OnBodyFinished() can send the entire thing at once. */ AString & m_ResponseBody; /** Indicates whether an error was encountered while processing the request. */ bool m_IsError; }; } class cUrlClientRequest: public cNetwork::cConnectCallbacks, public cTCPLink::cCallbacks { friend class cHttpSchemeHandler; public: static std::pair Request( const AString & a_Method, const AString & a_URL, cUrlClient::cCallbacksPtr && a_Callbacks, AStringMap && a_Headers, const AString & a_Body, const AStringMap & a_Options ) { // Create a new instance of cUrlClientRequest, wrapped in a SharedPtr, so that it has a controlled lifetime. // Cannot use std::make_shared, because the constructor is not public std::shared_ptr ptr (new cUrlClientRequest( a_Method, a_URL, std::move(a_Callbacks), std::move(a_Headers), a_Body, a_Options )); return ptr->DoRequest(ptr); } /** Calls the error callback with the specified message, if it exists, and terminates the request. */ void CallErrorCallback(const AString & a_ErrorMessage) { // Call the error callback: m_Callbacks->OnError(a_ErrorMessage); // Terminate the request's TCP link: if (auto link = m_Link.lock()) { link->Close(); } } cUrlClient::cCallbacks & GetCallbacks() { return *m_Callbacks; } void RedirectTo(const AString & a_RedirectUrl); bool ShouldAllowRedirects() const; cX509CertPtr GetOwnCert() const { auto itr = m_Options.find("OwnCert"); if (itr == m_Options.end()) { return nullptr; } cX509CertPtr cert = std::make_shared(); if (!cert->Parse(itr->second.data(), itr->second.size())) { LOGD("OwnCert failed to parse"); return nullptr; } return cert; } cCryptoKeyPtr GetOwnPrivKey() const { auto itr = m_Options.find("OwnPrivKey"); if (itr == m_Options.end()) { return nullptr; } cCryptoKeyPtr key = std::make_shared(); auto passItr = m_Options.find("OwnPrivKeyPassword"); auto pass = (passItr == m_Options.end()) ? AString() : passItr->second; if (!key->ParsePrivate(itr->second.data(), itr->second.size(), pass)) { return nullptr; } return key; } /** Returns the parsed TrustedRootCAs from the options, or an empty pointer if the option is not set. Throws a std::runtime_error if CAs are provided, but parsing them fails. */ cX509CertPtr GetTrustedRootCAs() const { auto itr = m_Options.find("TrustedRootCAs"); if (itr == m_Options.end()) { return nullptr; } auto Cert = std::make_shared(); auto Res = Cert->Parse(itr->second.data(), itr->second.size()); if (Res != 0) { throw std::runtime_error(fmt::format("Failed to parse the TrustedRootCAs certificate: {}", Res)); } return Cert; } protected: /** Method to be used for the request */ AString m_Method; /** URL that will be requested. */ AString m_Url; /** Individual components of the URL that will be requested. */ AString m_UrlScheme, m_UrlUsername, m_UrlPassword, m_UrlHost, m_UrlPath, m_UrlQuery, m_UrlFragment; UInt16 m_UrlPort; /** Callbacks that report progress and results of the request. */ cUrlClient::cCallbacksPtr m_Callbacks; /** Extra headers to be sent with the request (besides the normal ones). */ AStringMap m_Headers; /** Body to be sent with the request, if any. */ AString m_Body; /** Extra options to be used for the request. */ AStringMap m_Options; /** weak_ptr to self, so that this object can keep itself alive as needed by calling lock(), and pass self as callbacks to cNetwork functions. */ std::weak_ptr m_Self; /** The handler that "talks" the protocol specified in m_UrlScheme, handles all the sending and receiving. */ std::shared_ptr m_SchemeHandler; /** The link handling the request. */ std::weak_ptr m_Link; /** The number of redirect attempts that will still be followed. If the response specifies a redirect and this is nonzero, the redirect is followed. If the response specifies a redirect and this is zero, a redirect loop is reported as an error. */ int m_NumRemainingRedirects; cUrlClientRequest( const AString & a_Method, const AString & a_Url, cUrlClient::cCallbacksPtr && a_Callbacks, AStringMap && a_Headers, const AString & a_Body, const AStringMap & a_Options ): m_Method(a_Method), m_Url(a_Url), m_Callbacks(std::move(a_Callbacks)), m_Headers(std::move(a_Headers)), m_Body(a_Body), m_Options(a_Options) { m_NumRemainingRedirects = GetStringMapInteger(m_Options, "MaxRedirects", 30); } std::pair DoRequest(const std::shared_ptr & a_Self); // cNetwork::cConnectCallbacks override: TCP link connected: virtual void OnConnected(cTCPLink & a_Link) override; // cNetwork::cConnectCallbacks override: An error has occurred: virtual void OnError(int a_ErrorCode, const AString & a_ErrorMsg) override { m_Callbacks->OnError(fmt::format(FMT_STRING("Network error {} ({})"), a_ErrorCode, a_ErrorMsg)); } // cTCPLink::cCallbacks override: TCP link created virtual void OnLinkCreated(cTCPLinkPtr a_Link) override { m_Link = a_Link; } // cTCPLink::cCallbacks override: TLS handshake completed on the link: virtual void OnTlsHandshakeCompleted(void) override; /** Called when there's data incoming from the remote peer. */ virtual void OnReceivedData(const char * a_Data, size_t a_Length) override; /** Called when the remote end closes the connection. The link is still available for connection information query (IP / port). Sending data on the link is not an error, but the data won't be delivered. */ virtual void OnRemoteClosed(void) override; }; /** Represents a base class for an object that "talks" a specified URL protocol, such as HTTP or FTP. Also provides a static factory method for creating an instance based on the scheme. A descendant of this class is created for each request and handles all of the request's aspects, from right after connecting to the TCP link till the link is closed. For an example of a specific handler, see the cHttpSchemeHandler class. */ class cSchemeHandler abstract { public: cSchemeHandler(cUrlClientRequest & a_ParentRequest): m_ParentRequest(a_ParentRequest) { } // Force a virtual destructor in all descendants virtual ~cSchemeHandler() {} /** Creates and returns a new handler for the specified scheme. a_ParentRequest is the request which is to be handled by the handler. */ static cSchemeHandlerPtr Create(const AString & a_Scheme, cUrlClientRequest & a_ParentRequest); /** Called when the link gets established. */ virtual void OnConnected(cTCPLink & a_Link) = 0; /** Called when there's data incoming from the remote peer. */ virtual void OnReceivedData(const char * a_Data, size_t a_Length) = 0; /** Called when the TLS handshake has completed on the underlying link. */ virtual void OnTlsHandshakeCompleted(void) = 0; /** Called when the remote end closes the connection. The link is still available for connection information query (IP / port). Sending data on the link is not an error, but the data won't be delivered. */ virtual void OnRemoteClosed(void) = 0; protected: cUrlClientRequest & m_ParentRequest; }; /** cSchemeHandler descendant that handles HTTP (and HTTPS) requests. */ class cHttpSchemeHandler: public cSchemeHandler, protected cHTTPMessageParser::cCallbacks { using Super = cSchemeHandler; public: cHttpSchemeHandler(cUrlClientRequest & a_ParentRequest, bool a_IsTls): Super(a_ParentRequest), m_Parser(*this), m_IsTls(a_IsTls), m_IsRedirect(false) { } virtual void OnConnected(cTCPLink & a_Link) override { m_Link = &a_Link; if (m_IsTls) { m_Link->StartTLSClient(m_ParentRequest.GetOwnCert(), m_ParentRequest.GetOwnPrivKey(), m_ParentRequest.GetTrustedRootCAs()); } else { SendRequest(); } } /** Sends the HTTP request over the link. Common code for both HTTP and HTTPS. */ void SendRequest() { // Compose the request line: auto requestLine = m_ParentRequest.m_UrlPath; if (requestLine.empty()) { requestLine = "/"; } if (!m_ParentRequest.m_UrlQuery.empty()) { requestLine.push_back('?'); requestLine.append(m_ParentRequest.m_UrlQuery); } m_Link->Send(fmt::format(FMT_STRING("{} {} HTTP/1.1\r\n"), m_ParentRequest.m_Method, requestLine)); // Send the headers: m_Link->Send(fmt::format(FMT_STRING("Host: {}\r\n"), m_ParentRequest.m_UrlHost)); m_Link->Send(fmt::format(FMT_STRING("Content-Length: {}\r\n"), m_ParentRequest.m_Body.size())); for (const auto & hdr: m_ParentRequest.m_Headers) { m_Link->Send(fmt::format(FMT_STRING("{}: {}\r\n"), hdr.first, hdr.second)); } // for itr - m_Headers[] m_Link->Send("\r\n", 2); // Send the body: m_Link->Send(m_ParentRequest.m_Body); // Notify the callbacks that the request has been sent: m_ParentRequest.GetCallbacks().OnRequestSent(); } virtual void OnReceivedData(const char * a_Data, size_t a_Length) override { auto res = m_Parser.Parse(a_Data, a_Length); if (res == AString::npos) { m_ParentRequest.CallErrorCallback("Failed to parse HTTP response"); return; } } virtual void OnTlsHandshakeCompleted(void) override { SendRequest(); } virtual void OnRemoteClosed(void) override { m_Link = nullptr; } // cHTTPResponseParser::cCallbacks overrides: virtual void OnError(const AString & a_ErrorDescription) override { m_Link = nullptr; m_ParentRequest.CallErrorCallback(a_ErrorDescription); } virtual void OnFirstLine(const AString & a_FirstLine) override { // Find the first space, parse the result code between it and the second space: auto idxFirstSpace = a_FirstLine.find(' '); if (idxFirstSpace == AString::npos) { m_ParentRequest.CallErrorCallback(fmt::format(FMT_STRING("Failed to parse HTTP status line \"{}\", no space delimiter."), a_FirstLine)); return; } auto idxSecondSpace = a_FirstLine.find(' ', idxFirstSpace + 1); if (idxSecondSpace == AString::npos) { m_ParentRequest.CallErrorCallback(fmt::format(FMT_STRING("Failed to parse HTTP status line \"{}\", missing second space delimiter."), a_FirstLine)); return; } int resultCode; auto resultCodeStr = a_FirstLine.substr(idxFirstSpace + 1, idxSecondSpace - idxFirstSpace - 1); if (!StringToInteger(resultCodeStr, resultCode)) { m_ParentRequest.CallErrorCallback(fmt::format(FMT_STRING("Failed to parse HTTP result code from response \"{}\""), resultCodeStr)); return; } // Check for redirects, follow if allowed by the options: switch (resultCode) { case cUrlClient::HTTP_STATUS_MULTIPLE_CHOICES: case cUrlClient::HTTP_STATUS_MOVED_PERMANENTLY: case cUrlClient::HTTP_STATUS_FOUND: case cUrlClient::HTTP_STATUS_SEE_OTHER: case cUrlClient::HTTP_STATUS_TEMPORARY_REDIRECT: { m_IsRedirect = true; return; } } m_ParentRequest.GetCallbacks().OnStatusLine(a_FirstLine.substr(0, idxFirstSpace), resultCode, a_FirstLine.substr(idxSecondSpace + 1)); } virtual void OnHeaderLine(const AString & a_Key, const AString & a_Value) override { if (m_IsRedirect) { if (a_Key == "Location") { m_RedirectLocation = a_Value; } } else { m_ParentRequest.GetCallbacks().OnHeader(a_Key, a_Value); } } /** Called when all the headers have been parsed. */ virtual void OnHeadersFinished(void) override { if (!m_IsRedirect) { m_ParentRequest.GetCallbacks().OnHeadersFinished(); } } /** Called for each chunk of the incoming body data. */ virtual void OnBodyData(const void * a_Data, size_t a_Size) override { if (!m_IsRedirect) { m_ParentRequest.GetCallbacks().OnBodyData(a_Data, a_Size); } } /** Called when the entire body has been reported by OnBodyData(). */ virtual void OnBodyFinished(void) override { if (m_IsRedirect) { if (m_RedirectLocation.empty()) { m_ParentRequest.CallErrorCallback("Invalid redirect, there's no location to redirect to"); } else { m_ParentRequest.RedirectTo(m_RedirectLocation); } } else { m_ParentRequest.GetCallbacks().OnBodyFinished(); // Finished recieving data, shutdown the link m_Link->Shutdown(); } } protected: /** The network link. */ cTCPLink * m_Link; /** Parser of the HTTP response message. */ cHTTPMessageParser m_Parser; /** If true, the TLS should be started on the link before sending the request (used for https). */ bool m_IsTls; /** Set to true if the first line contains a redirecting HTTP status code and the options specify to follow redirects. If true, and the parent request allows redirects, neither headers not the body contents are reported through the callbacks, and after the entire request is parsed, the redirect is attempted. */ bool m_IsRedirect; /** The Location where the request should be redirected. Only used when m_IsRedirect is true. */ AString m_RedirectLocation; }; //////////////////////////////////////////////////////////////////////////////// // cSchemeHandler: cSchemeHandlerPtr cSchemeHandler::Create(const AString & a_Scheme, cUrlClientRequest & a_ParentRequest) { auto lowerScheme = StrToLower(a_Scheme); if (lowerScheme == "http") { return std::make_shared(a_ParentRequest, false); } else if (lowerScheme == "https") { return std::make_shared(a_ParentRequest, true); } return nullptr; } //////////////////////////////////////////////////////////////////////////////// // cUrlClientRequest: void cUrlClientRequest::RedirectTo(const AString & a_RedirectUrl) { // Check that redirection is allowed: m_Callbacks->OnRedirecting(a_RedirectUrl); if (!ShouldAllowRedirects()) { CallErrorCallback(fmt::format(FMT_STRING("Redirect to \"{}\" not allowed"), a_RedirectUrl)); return; } // Keep ourself alive while the link drops ownership auto Self = m_Self.lock(); // Do the actual redirect: if (auto Link = m_Link.lock()) { Link->Close(); } m_Url = a_RedirectUrl; m_NumRemainingRedirects = m_NumRemainingRedirects - 1; auto res = DoRequest(Self); if (!res.first) { m_Callbacks->OnError(fmt::format(FMT_STRING("Redirection failed: {}"), res.second)); } } bool cUrlClientRequest::ShouldAllowRedirects() const { return (m_NumRemainingRedirects > 0); } void cUrlClientRequest::OnConnected(cTCPLink & a_Link) { m_Callbacks->OnConnected(a_Link); m_SchemeHandler->OnConnected(a_Link); } void cUrlClientRequest::OnTlsHandshakeCompleted(void) { // Notify the scheme handler and the callbacks: m_SchemeHandler->OnTlsHandshakeCompleted(); m_Callbacks->OnTlsHandshakeCompleted(); } void cUrlClientRequest::OnReceivedData(const char * a_Data, size_t a_Length) { auto handler = m_SchemeHandler; if (handler != nullptr) { handler->OnReceivedData(a_Data, a_Length); } } void cUrlClientRequest::OnRemoteClosed() { // Notify the callback: auto handler = m_SchemeHandler; if (handler != nullptr) { handler->OnRemoteClosed(); } } std::pair cUrlClientRequest::DoRequest(const std::shared_ptr & a_Self) { // We need a shared pointer to self, care must be taken not to pass any other ptr: ASSERT(a_Self.get() == this); m_Self = a_Self; // Parse the URL: auto res = cUrlParser::Parse(m_Url, m_UrlScheme, m_UrlUsername, m_UrlPassword, m_UrlHost, m_UrlPort, m_UrlPath, m_UrlQuery, m_UrlFragment); if (!res.first) { return res; } // Get a handler that will work with the specified scheme: m_SchemeHandler = cSchemeHandler::Create(m_UrlScheme, *this); if (m_SchemeHandler == nullptr) { return std::make_pair(false, fmt::format(FMT_STRING("Unknown URL scheme: {}"), m_UrlScheme)); } // Connect and transfer ownership to the link if (!cNetwork::Connect(m_UrlHost, m_UrlPort, a_Self, a_Self)) { return std::make_pair(false, "Network connection failed"); } return std::make_pair(true, AString()); } //////////////////////////////////////////////////////////////////////////////// // cUrlClient: std::pair cUrlClient::Request( const AString & a_Method, const AString & a_URL, cCallbacksPtr && a_Callbacks, AStringMap && a_Headers, const AString & a_Body, const AStringMap & a_Options ) { return cUrlClientRequest::Request( a_Method, a_URL, std::move(a_Callbacks), std::move(a_Headers), a_Body, a_Options ); } std::pair cUrlClient::Get( const AString & a_URL, cCallbacksPtr && a_Callbacks, AStringMap && a_Headers, const AString & a_Body, const AStringMap & a_Options ) { return cUrlClientRequest::Request( "GET", a_URL, std::move(a_Callbacks), std::move(a_Headers), a_Body, a_Options ); } std::pair cUrlClient::Post( const AString & a_URL, cCallbacksPtr && a_Callbacks, AStringMap && a_Headers, const AString & a_Body, const AStringMap & a_Options ) { return cUrlClientRequest::Request( "POST", a_URL, std::move(a_Callbacks), std::move(a_Headers), a_Body, a_Options ); } std::pair cUrlClient::Put( const AString & a_URL, cCallbacksPtr && a_Callbacks, AStringMap && a_Headers, const AString & a_Body, const AStringMap & a_Options ) { return cUrlClientRequest::Request( "PUT", a_URL, std::move(a_Callbacks), std::move(a_Headers), a_Body, a_Options ); } std::pair cUrlClient::BlockingRequest( const AString & a_Method, const AString & a_URL, AStringMap && a_Headers, const AString & a_Body, const AStringMap & a_Options ) { auto EvtFinished = std::make_shared(); AString Response; auto Callbacks = std::make_shared(EvtFinished, Response); auto [Success, ErrorMessage] = cUrlClient::Request(a_Method, a_URL, Callbacks, std::move(a_Headers), a_Body, a_Options); if (Success) { if (!EvtFinished->Wait(10000)) { return std::make_pair(false, "Timeout"); } if (Callbacks->m_IsError) { return std::make_pair(false, AString()); } } else { LOGWARNING("%s: HTTP error: %s", __FUNCTION__, ErrorMessage.c_str()); return std::make_pair(false, AString()); } return std::make_pair(true, Response); } std::pair cUrlClient::BlockingGet( const AString & a_URL, AStringMap a_Headers, const AString & a_Body, const AStringMap & a_Options ) { return BlockingRequest("GET", a_URL, std::move(a_Headers), a_Body, a_Options); } std::pair cUrlClient::BlockingPost( const AString & a_URL, AStringMap && a_Headers, const AString & a_Body, const AStringMap & a_Options ) { return BlockingRequest("POST", a_URL, std::move(a_Headers), a_Body, a_Options); } std::pair cUrlClient::BlockingPut( const AString & a_URL, AStringMap && a_Headers, const AString & a_Body, const AStringMap & a_Options ) { return BlockingRequest("PUT", a_URL, std::move(a_Headers), a_Body, a_Options); } ================================================ FILE: src/HTTP/UrlClient.h ================================================ // UrlClient.h // Declares the cUrlClient class for high-level URL interaction /* Options that can be set via the Options parameter to the cUrlClient calls: "MaxRedirects": The maximum number of allowed redirects before the client refuses a redirect with an error "OwnCert": The client certificate to use, if requested by the server. Any string that can be parsed by cX509Cert. "OwnPrivKey": The private key appropriate for OwnCert. Any string that can be parsed by cCryptoKey. "OwnPrivKeyPassword": The password for OwnPrivKey. If not present or empty, no password is assumed. "TrustedRootCAs": The trusted root CA certificates (\n-delimited concatenated PEM format) to be used for peer cert verification. If not present, peer cert is not verified. Behavior: - If a redirect is received, and redirection is allowed, the redirection is reported via OnRedirecting() callback and the request is restarted at the redirect URL, without reporting any of the redirect's headers nor body - If a redirect is received and redirection is not allowed (maximum redirection attempts have been reached), the OnRedirecting() callback is called with the redirect URL and then the request terminates with an OnError() callback, without reporting the redirect's headers nor body. */ #pragma once #include "../OSSupport/Network.h" class cUrlClient { public: /** Callbacks that are used for progress and result reporting. */ class cCallbacks { public: // Force a virtual destructor in descendants: virtual ~cCallbacks() {} /** Called when the TCP connection is established. */ virtual void OnConnected(cTCPLink & a_Link) {} /** Called for TLS connections, when the server certificate is received. Return true to continue with the request, false to abort. The default implementation does nothing and continues with the request. TODO: The certificate parameter needs a representation! */ virtual bool OnCertificateReceived() { return true; } /** Called for TLS connections, when the TLS handshake has been completed. An empty default implementation is provided so that clients don't need to reimplement it unless they are interested in the event. */ virtual void OnTlsHandshakeCompleted() { } /** Called after the entire request has been sent to the remote peer. */ virtual void OnRequestSent() {} /** Called after the first line of the response is parsed, unless the response is an allowed redirect. */ virtual void OnStatusLine(const AString & a_HttpVersion, int a_StatusCode, const AString & a_Rest) {} /** Called when a single HTTP header is received and parsed, unless the response is an allowed redirect Called once for each incoming header. */ virtual void OnHeader(const AString & a_Key, const AString & a_Value) {} /** Called when the HTTP headers have been fully parsed, unless the response is an allowed redirect. There will be no more OnHeader() calls. */ virtual void OnHeadersFinished() {} /** Called when the next fragment of the response body is received, unless the response is an allowed redirect. This can be called multiple times, as data arrives over the network. */ virtual void OnBodyData(const void * a_Data, size_t a_Size) {} /** Called after the response body has been fully reported by OnBody() calls, unless the response is an allowed redirect. There will be no more OnBody() calls. */ virtual void OnBodyFinished() {} /** Called when an asynchronous error is encountered. */ virtual void OnError(const AString & a_ErrorMsg) {} /** Called when a redirect is to be followed. This is called even if the redirecting is prohibited by the options; in such an event, this call will be followed by OnError(). If a response indicates a redirect (and the request allows redirecting), the regular callbacks OnStatusLine(), OnHeader(), OnHeadersFinished(), OnBodyData() and OnBodyFinished() are not called for such a response; instead, the redirect is silently attempted. */ virtual void OnRedirecting(const AString & a_NewLocation) {} }; using cCallbacksPtr = std::shared_ptr; /** Used for HTTP status codes. */ enum eHTTPStatus { HTTP_STATUS_OK = 200, HTTP_STATUS_MULTIPLE_CHOICES = 300, // MAY have a redirect using the "Location" header HTTP_STATUS_MOVED_PERMANENTLY = 301, // redirect using the "Location" header HTTP_STATUS_FOUND = 302, // redirect using the "Location" header HTTP_STATUS_SEE_OTHER = 303, // redirect using the "Location" header HTTP_STATUS_TEMPORARY_REDIRECT = 307, // redirect using the "Location" header }; /** Makes a network request to the specified URL, using the specified method (if applicable). The response is reported via the a_ResponseCallback callback, in a single call. The metadata about the response (HTTP headers) are reported via a_InfoCallback before the a_ResponseCallback call. If there is an asynchronous error, it is reported in via the a_ErrorCallback. If there is an immediate error (misformatted URL etc.), the function returns false and an error message. a_Headers contains additional headers to use for the request. a_Body specifies optional body to include with the request, if applicable. a_Options contains various options for the request that govern the request behavior, but aren't sent to the server, such as the proxy server, whether to follow redirects, and client certificate for TLS. */ static std::pair Request( const AString & a_Method, const AString & a_URL, cCallbacksPtr && a_Callbacks, AStringMap && a_Headers, const AString & a_Body, const AStringMap & a_Options ); /** Alias for Request("GET", ...) */ static std::pair Get( const AString & a_URL, cCallbacksPtr && a_Callbacks, AStringMap && a_Headers = {}, const AString & a_Body = {}, const AStringMap & a_Options = {} ); /** Alias for Request("POST", ...) */ static std::pair Post( const AString & a_URL, cCallbacksPtr && a_Callbacks, AStringMap && a_Headers, const AString & a_Body, const AStringMap & a_Options = {} ); /** Alias for Request("PUT", ...) */ static std::pair Put( const AString & a_URL, cCallbacksPtr && a_Callbacks, AStringMap && a_Headers, const AString & a_Body, const AStringMap & a_Options = {} ); /** Sends a generic request and block until a response is received or an error occurs. The first returned value specifies whether the response was received successfully. If successful, the second value provides the actual response data. */ static std::pair BlockingRequest( const AString & a_Method, const AString & a_URL, AStringMap && a_Headers = {}, const AString & a_Body = {}, const AStringMap & a_Options = {} ); /** Alias for BlockingRequest("GET", ...) */ static std::pair BlockingGet( const AString & a_URL, AStringMap a_Headers = {}, const AString & a_Body = {}, const AStringMap & a_Options = {} ); /** Alias for BlockingRequest("POST", ...) */ static std::pair BlockingPost( const AString & a_URL, AStringMap && a_Headers, const AString & a_Body, const AStringMap & a_Options = {} ); /** Alias for BlockingRequest("PUT", ...) */ static std::pair BlockingPut( const AString & a_URL, AStringMap && a_Headers, const AString & a_Body, const AStringMap & a_Options = {} ); }; ================================================ FILE: src/HTTP/UrlParser.cpp ================================================ // UrlParser.cpp // Implements the cUrlParser class that parses string URL into individual parts #include "Globals.h" #include "UrlParser.h" UInt16 cUrlParser::GetDefaultPort(const AString & a_Scheme) { if (a_Scheme == "http") { return 80; } else if (a_Scheme == "https") { return 443; } else if (a_Scheme == "ftp") { return 21; } else if (a_Scheme == "mailto") { return 25; } return 0; } std::pair cUrlParser::ParseAuthorityPart( const AString & a_AuthorityPart, AString & a_Username, AString & a_Password, AString & a_Host, UInt16 & a_Port ) { /* a_AuthorityPart format: [user:password@]host[:port] host can be an IPv4, hostname, or an IPv6 enclosed in brackets Assume only the password can contain an additional at-sign */ // Split the authority on the last at-sign, if present: auto idxLastAtSign = a_AuthorityPart.find_last_of('@'); auto credPart = (idxLastAtSign == AString::npos) ? AString() : a_AuthorityPart.substr(0, idxLastAtSign); auto srvrPart = (idxLastAtSign == AString::npos) ? a_AuthorityPart : a_AuthorityPart.substr(idxLastAtSign + 1); // User credentials are completely optional: auto idxCredColon = credPart.find(':'); a_Username = credPart.substr(0, idxCredColon); a_Password = (idxCredColon == AString::npos) ? AString() : credPart.substr(idxCredColon + 1); // Host can be a hostname, IPv4 or [IPv6]. If in brackets, search for the closing bracket first if (srvrPart.empty()) { // No host information at all. Bail out with success a_Host.clear(); return std::make_pair(true, AString()); } if (srvrPart[0] == '[') { // [IPv6] host, search for the closing bracket auto idxClosingBracket = srvrPart.find(']'); if (idxClosingBracket == AString::npos) { return std::make_pair(false, "Invalid IPv6-like address, missing closing bracket"); } a_Host = srvrPart.substr(0, idxClosingBracket); auto portPart = srvrPart.substr(idxClosingBracket + 1); if (portPart.empty()) { // No port was specified, return success return std::make_pair(true, AString()); } if (portPart[0] != ':') { return std::make_pair(false, "Invalid port format after IPv6 address, mising colon"); } if (!StringToInteger(portPart.substr(2), a_Port)) { return std::make_pair(false, "Failed to parse port number after IPv6 address"); } return std::make_pair(true, AString()); } // Not an [IPv6] address, split on the last colon: auto idxLastColon = srvrPart.find_last_of(':'); a_Host = srvrPart.substr(0, idxLastColon); if (idxLastColon == AString::npos) { // No port was specified, return success return std::make_pair(true, AString()); } auto portPart = srvrPart.substr(idxLastColon + 1); if (!StringToInteger(portPart, a_Port)) { return std::make_pair(false, "Failed to parse port number after hostname"); } return std::make_pair(true, AString()); } std::pair cUrlParser::Parse( const AString & a_Url, AString & a_Scheme, AString & a_Username, AString & a_Password, AString & a_Host, UInt16 & a_Port, AString & a_Path, AString & a_Query, AString & a_Fragment ) { // Find the scheme - the text before the first colon: auto idxColon = a_Url.find(':'); if (idxColon == AString::npos) { return std::make_pair(false, "Cannot parse the Scheme part of the URL"); } a_Scheme = StrToLower(a_Url.substr(0, idxColon)); a_Port = GetDefaultPort(a_Scheme); if (a_Port == 0) { return std::make_pair(false, fmt::format(FMT_STRING("Unknown URL scheme: \"{}\""), a_Scheme)); } // If the next two chars are a double-slash, skip them: auto authStart = idxColon + 1; if (a_Url.substr(authStart, 2) == "//") { authStart += 2; } // The Authority part follows the Scheme, until the first slash: auto idxFirstSlash = a_Url.find('/', authStart + 1); if (idxFirstSlash == AString::npos) { // No slash, the whole end of the Url is the authority part idxFirstSlash = a_Url.size(); } // Parse the Authority part into individual components: auto res = ParseAuthorityPart( a_Url.substr(authStart, idxFirstSlash - authStart), a_Username, a_Password, a_Host, a_Port ); if (!res.first) { return res; } // Parse the rest into a path, query and fragment: a_Path.clear(); a_Query.clear(); a_Fragment.clear(); if (idxFirstSlash == a_Url.size()) { // No additional data, bail out with success return std::make_pair(true, AString()); } auto idxPathEnd = a_Url.find_first_of("?#", idxFirstSlash + 1); if (idxPathEnd == AString::npos) { a_Path = a_Url.substr(idxFirstSlash); return std::make_pair(true, AString()); } a_Path = a_Url.substr(idxFirstSlash, idxPathEnd - idxFirstSlash); auto idxHash = a_Url.find('#', idxPathEnd); if (idxHash == AString::npos) { a_Query = a_Url.substr(idxPathEnd + 1); return std::make_pair(true, AString()); } if (idxHash > idxPathEnd) { a_Query = a_Url.substr(idxPathEnd + 1, idxHash - idxPathEnd - 1); } a_Fragment = a_Url.substr(idxHash + 1); return std::make_pair(true, AString()); } std::pair cUrlParser::Validate(const AString & a_Url) { AString UrlScheme, UrlUsername, UrlPassword, UrlHost, UrlPath, UrlQuery, UrlFragment; UInt16 Port; return Parse(a_Url, UrlScheme, UrlUsername, UrlPassword, UrlHost, Port, UrlPath, UrlQuery, UrlFragment); } ================================================ FILE: src/HTTP/UrlParser.h ================================================ // UrlParser.h // Declares the cUrlParser class that parses string URL into individual parts #pragma once class cUrlParser { public: /** Returns true if the specified scheme (http, ftp, mailto, ...) is recognized by the URL parser. Is case sensitive, known schemes are always lowercase. */ static bool IsKnownScheme(const AString & a_Scheme) { return (GetDefaultPort(a_Scheme) > 0); } /** Returns the default port used by the specified scheme / protocol. If the scheme is not known, 0 is returned. */ static UInt16 GetDefaultPort(const AString & a_Scheme); /** Parses the given Authority part of an URL into individual components. Returns true on success, returns false and error message on failure. */ static std::pair ParseAuthorityPart( const AString & a_AuthorityPart, AString & a_Username, AString & a_Password, AString & a_Host, UInt16 & a_Port ); /** Parses the given URL into individual components. Returns true on success, returns false and error message on failure. Fails if the scheme (protocol) is not known. If port is missing, the default port for the specific scheme is applied. */ static std::pair Parse( const AString & a_Url, AString & a_Scheme, AString & a_Username, AString & a_Password, AString & a_Host, UInt16 & a_Port, AString & a_Path, AString & a_Query, AString & a_Fragment ); /** Checks if the supplied URL is valid */ static std::pair Validate(const AString & a_Url); }; ================================================ FILE: src/IniFile.cpp ================================================ // IniFile.cpp: Implementation of the CIniFile class. // Written by: Adam Clauss // Email: cabadam@houston.rr.com // You may use this class / code as you wish in your programs. Feel free to distribute it, and // email suggested changes to me. // // Rewritten by: Shane Hill // Date: 2001-08-21 // Email: Shane.Hill@dsto.defence.gov.au // Reason: Remove dependancy on MFC. Code should compile on any // platform. //////////////////////////////////////////////////////////////////////////////// /* !! MODIFIED BY FAKETRUTH and xoft !! */ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules // C++ Includes #include // C Includes #include // Local Includes #include "IniFile.h" #if defined(WIN32) #define iniEOL endl #else #define iniEOL '\r' << endl #endif using namespace std; cIniFile::cIniFile(void) : m_IsCaseInsensitive(true) { } bool cIniFile::ReadFile(const AString & a_FileName, bool a_AllowExampleRedirect) { m_Filename = a_FileName; // Normally you would use ifstream, but the SGI CC compiler has // a few bugs with ifstream. So ... fstream used. fstream f; AString line; AString keyname, valuename, value; AString::size_type pLeft, pRight; bool IsFromExampleRedirect = false; f.open((a_FileName).c_str(), ios::in); if (f.fail()) { f.clear(); if (a_AllowExampleRedirect) { // Retry with the .example.ini file instead of .ini: AString ExPath(a_FileName.substr(0, a_FileName.length() - 4)); ExPath.append(".example.ini"); f.open((ExPath).c_str(), ios::in); if (f.fail()) { return false; } IsFromExampleRedirect = true; } else { return false; } } bool IsFirstLine = true; while (getline(f, line)) { // To be compatible with Win32, check for existence of '\r'. // Win32 files have the '\r' and Unix files don't at the end of a line. // Note that the '\r' will be written to INI files from // Unix so that the created INI file can be read under Win32 // without change. // Removes UTF-8 Byte Order Markers (BOM) if, present. if (IsFirstLine) { RemoveBom(line); IsFirstLine = false; } size_t lineLength = line.length(); if (lineLength == 0) { continue; } if (line[lineLength - 1] == '\r') { line = line.substr(0, lineLength - 1); } if (line.length() == 0) { continue; } // Check that the user hasn't opened a binary file by checking the first // character of each line! if (!isprint(line[0])) { printf("%s: Binary-check failed on char %d\n", __FUNCTION__, line[0]); f.close(); return false; } if ((pLeft = line.find_first_of(";#[=")) == AString::npos) { continue; } switch (line[pLeft]) { case '[': { if ( ((pRight = line.find_last_of("]")) != AString::npos) && (pRight > pLeft) ) { keyname = line.substr(pLeft + 1, pRight - pLeft - 1); AddKeyName(keyname); } break; } case '=': { valuename = line.substr(0, pLeft); value = TrimString(line.substr(pLeft + 1)); ReplaceString(value, "\\n", "\n"); AddValue(keyname, valuename, value); break; } case ';': case '#': { if (m_Names.empty()) { AddHeaderComment(line.substr(pLeft + 1)); } else { AddKeyComment(keyname, line.substr(pLeft + 1)); } break; } } // switch (line[pLeft]) } // while (getline()) f.close(); if (m_Keys.empty() && m_Names.empty() && m_Comments.empty()) { // File be empty or unreadable, equivalent to nonexistant return false; } if (IsFromExampleRedirect) { WriteFile(a_FileName); } return true; } bool cIniFile::WriteFile(const AString & a_FileName) const { // Normally you would use ofstream, but the SGI CC compiler has // a few bugs with ofstream. So ... fstream used. fstream f; AString writevalue; f.open((a_FileName).c_str(), ios::out); if (f.fail()) { return false; } // Write header comments. size_t NumComments = m_Comments.size(); for (size_t commentID = 0; commentID < NumComments; ++commentID) { f << ';' << m_Comments[commentID] << iniEOL; } if (NumComments > 0) { f << iniEOL; } // Write keys and values. for (size_t keyID = 0; keyID < m_Keys.size(); ++keyID) { f << '[' << m_Names[keyID] << ']' << iniEOL; // Comments. for (size_t commentID = 0; commentID < m_Keys[keyID].m_Comments.size(); ++commentID) { f << ';' << m_Keys[keyID].m_Comments[commentID] << iniEOL; } // Values. for (size_t valueID = 0; valueID < m_Keys[keyID].m_Names.size(); ++valueID) { writevalue = m_Keys[keyID].m_Values[valueID]; ReplaceString(writevalue, "\n", "\\n"); f << m_Keys[keyID].m_Names[valueID] << '=' << writevalue << iniEOL; } f << iniEOL; } f.close(); return true; } int cIniFile::FindKey(const AString & a_KeyName) const { AString CaseKeyName = CheckCase(a_KeyName); for (size_t keyID = 0; keyID < m_Names.size(); ++keyID) { if (CheckCase(m_Names[keyID]) == CaseKeyName) { return static_cast(keyID); } } return noID; } int cIniFile::FindValue(const int keyID, const AString & a_ValueName) const { if (!m_Keys.size() || (keyID >= static_cast(m_Keys.size()))) { return noID; } AString CaseValueName = CheckCase(a_ValueName); for (size_t valueID = 0; valueID < m_Keys[static_cast(keyID)].m_Names.size(); ++valueID) { if (CheckCase(m_Keys[static_cast(keyID)].m_Names[valueID]) == CaseValueName) { return int(valueID); } } return noID; } int cIniFile::AddKeyName(const AString & keyname) { m_Names.resize(m_Names.size() + 1, keyname); m_Keys.resize(m_Keys.size() + 1); return static_cast(m_Names.size()) - 1; } AString cIniFile::GetKeyName(const int keyID) const { if (keyID < static_cast(m_Names.size())) { return m_Names[static_cast(keyID)]; } else { return ""; } } int cIniFile::GetNumValues(const int keyID) const { if (keyID < static_cast(m_Keys.size())) { return static_cast(m_Keys[static_cast(keyID)].m_Names.size()); } return 0; } int cIniFile::GetNumValues(const AString & keyname) const { int keyID = FindKey(keyname); if (keyID == noID) { return 0; } return static_cast(m_Keys[static_cast(keyID)].m_Names.size()); } AString cIniFile::GetValueName(const int keyID, const int valueID) const { if ((keyID < static_cast(m_Keys.size())) && (valueID < static_cast(m_Keys[static_cast(keyID)].m_Names.size()))) { return m_Keys[static_cast(keyID)].m_Names[static_cast(valueID)]; } return ""; } AString cIniFile::GetValueName(const AString & keyname, const int valueID) const { int keyID = FindKey(keyname); if (keyID == noID) { return ""; } return GetValueName(keyID, valueID); } void cIniFile::AddValue(const AString & a_KeyName, const AString & a_ValueName, const AString & a_Value) { int keyID = FindKey(a_KeyName); if (keyID == noID) { keyID = int(AddKeyName(a_KeyName)); } m_Keys[static_cast(keyID)].m_Names.push_back(a_ValueName); m_Keys[static_cast(keyID)].m_Values.push_back(a_Value); } void cIniFile::AddValueI(const AString & a_KeyName, const AString & a_ValueName, const int a_Value) { AddValue(a_KeyName, a_ValueName, fmt::format(FMT_STRING("{}"), a_Value)); } void cIniFile::AddValueF(const AString & a_KeyName, const AString & a_ValueName, const double a_Value) { AddValue(a_KeyName, a_ValueName, fmt::format(FMT_STRING("{}"), a_Value)); } bool cIniFile::SetValue(const int keyID, const int valueID, const AString & value) { if ((static_cast(keyID) >= m_Keys.size()) || (static_cast(valueID) >= m_Keys[static_cast(keyID)].m_Names.size())) { return false; } m_Keys[static_cast(keyID)].m_Values[static_cast(valueID)] = value; return true; } bool cIniFile::SetValue(const AString & a_KeyName, const AString & a_ValueName, const AString & a_Value, const bool a_CreateIfNotExists) { int keyID = FindKey(a_KeyName); if (keyID == noID) { if (!a_CreateIfNotExists) { return false; } keyID = AddKeyName(a_KeyName); } int valueID = FindValue(keyID, a_ValueName); if (valueID == noID) { if (!a_CreateIfNotExists) { return false; } m_Keys[static_cast(keyID)].m_Names.push_back(a_ValueName); m_Keys[static_cast(keyID)].m_Values.push_back(a_Value); } else { m_Keys[static_cast(keyID)].m_Values[static_cast(valueID)] = a_Value; } return true; } bool cIniFile::SetValueI(const AString & a_KeyName, const AString & a_ValueName, const int a_Value, const bool a_CreateIfNotExists) { return SetValue(a_KeyName, a_ValueName, fmt::format(FMT_STRING("{}"), a_Value), a_CreateIfNotExists); } bool cIniFile::SetValueI(const AString & a_Keyname, const AString & a_ValueName, const Int64 a_Value, const bool a_CreateIfNotExists) { return SetValue(a_Keyname, a_ValueName, fmt::format(FMT_STRING("{}"), a_Value), a_CreateIfNotExists); } bool cIniFile::SetValueF(const AString & a_KeyName, const AString & a_ValueName, double const a_Value, const bool a_CreateIfNotExists) { return SetValue(a_KeyName, a_ValueName, fmt::format(FMT_STRING("{}"), a_Value), a_CreateIfNotExists); } AString cIniFile::GetValue(const int keyID, const int valueID, const AString & defValue) const { if ((keyID < static_cast(m_Keys.size())) && (valueID < static_cast(m_Keys[static_cast(keyID)].m_Names.size()))) { return m_Keys[static_cast(keyID)].m_Values[static_cast(valueID)]; } return defValue; } AString cIniFile::GetValue(const AString & keyname, const AString & valuename, const AString & defValue) const { int keyID = FindKey(keyname); if (keyID == noID) { return defValue; } int valueID = FindValue(int(keyID), valuename); if (valueID == noID) { return defValue; } return m_Keys[static_cast(keyID)].m_Values[static_cast(valueID)]; } int cIniFile::GetValueI(const AString & keyname, const AString & valuename, const int defValue) const { auto Data = fmt::format(FMT_STRING("{}"), defValue); return atoi(GetValue(keyname, valuename, Data).c_str()); } double cIniFile::GetValueF(const AString & keyname, const AString & valuename, double const defValue) const { auto Data = fmt::format(FMT_STRING("{}"), defValue); return atof(GetValue(keyname, valuename, Data).c_str()); } AString cIniFile::GetValueSet(const AString & keyname, const AString & valuename, const AString & defValue) { int keyID = FindKey(keyname); if (keyID == noID) { SetValue(keyname, valuename, defValue); return defValue; } int valueID = FindValue(int(keyID), valuename); if (valueID == noID) { SetValue(keyname, valuename, defValue); return defValue; } return m_Keys[static_cast(keyID)].m_Values[static_cast(valueID)]; } double cIniFile::GetValueSetF(const AString & keyname, const AString & valuename, const double defValue) { auto Data = fmt::format(FMT_STRING("{}"), defValue); return atof(GetValueSet(keyname, valuename, Data).c_str()); } int cIniFile::GetValueSetI(const AString & keyname, const AString & valuename, const int defValue) { auto Data = fmt::format(FMT_STRING("{}"), defValue); return atoi(GetValueSet(keyname, valuename, Data).c_str()); } Int64 cIniFile::GetValueSetI(const AString & keyname, const AString & valuename, const Int64 defValue) { auto Data = fmt::format(FMT_STRING("{}"), defValue); AString resultstring = GetValueSet(keyname, valuename, Data); Int64 result = defValue; #ifdef _WIN32 sscanf_s(resultstring.c_str(), "%lld", &result); #else sscanf(resultstring.c_str(), "%lld", &result); #endif return result; } bool cIniFile::DeleteValueByID(const int keyID, const int valueID) { if ((keyID < static_cast(m_Keys.size())) && (valueID < static_cast(m_Keys[static_cast(keyID)].m_Names.size()))) { // This looks strange, but is neccessary. vector::iterator npos = m_Keys[static_cast(keyID)].m_Names.begin() + valueID; vector::iterator vpos = m_Keys[static_cast(keyID)].m_Values.begin() + valueID; m_Keys[static_cast(keyID)].m_Names.erase(npos, npos + 1); m_Keys[static_cast(keyID)].m_Values.erase(vpos, vpos + 1); return true; } return false; } bool cIniFile::DeleteValue(const AString & keyname, const AString & valuename) { int keyID = FindKey(keyname); if (keyID == noID) { return false; } int valueID = FindValue(int(keyID), valuename); if (valueID == noID) { return false; } return DeleteValueByID(keyID, valueID); } bool cIniFile::DeleteKey(const AString & keyname) { int keyID = FindKey(keyname); if (keyID == noID) { return false; } vector::iterator npos = m_Names.begin() + keyID; vector::iterator kpos = m_Keys.begin() + keyID; m_Names.erase(npos, npos + 1); m_Keys.erase(kpos, kpos + 1); return true; } void cIniFile::Clear(void) { m_Names.clear(); m_Keys.clear(); m_Comments.clear(); } bool cIniFile::HasValue(const AString & a_KeyName, const AString & a_ValueName) const { // Find the key: int keyID = FindKey(a_KeyName); if (keyID == noID) { return false; } // Find the value: int valueID = FindValue(keyID, a_ValueName); return (valueID != noID); } void cIniFile::AddHeaderComment(const AString & comment) { m_Comments.push_back(comment); // comments.resize(comments.size() + 1, comment); } AString cIniFile::GetHeaderComment(const int commentID) const { if (commentID < static_cast(m_Comments.size())) { return m_Comments[static_cast(commentID)]; } return ""; } bool cIniFile::DeleteHeaderComment(int commentID) { if (commentID < static_cast(m_Comments.size())) { vector::iterator cpos = m_Comments.begin() + commentID; m_Comments.erase(cpos, cpos + 1); return true; } return false; } int cIniFile::GetNumKeyComments(const int keyID) const { if (keyID < static_cast(m_Keys.size())) { return static_cast(m_Keys[static_cast(keyID)].m_Comments.size()); } return 0; } int cIniFile::GetNumKeyComments(const AString & keyname) const { int keyID = FindKey(keyname); if (keyID == noID) { return 0; } return static_cast(m_Keys[static_cast(keyID)].m_Comments.size()); } bool cIniFile::AddKeyComment(const int keyID, const AString & comment) { if (keyID < static_cast(m_Keys.size())) { m_Keys[static_cast(keyID)].m_Comments.resize(m_Keys[static_cast(keyID)].m_Comments.size() + 1, comment); return true; } return false; } bool cIniFile::AddKeyComment(const AString & keyname, const AString & comment) { int keyID = FindKey(keyname); if (keyID == noID) { return false; } return AddKeyComment(keyID, comment); } AString cIniFile::GetKeyComment(const int keyID, const int commentID) const { if ((keyID < static_cast(m_Keys.size())) && (commentID < static_cast(m_Keys[static_cast(keyID)].m_Comments.size()))) { return m_Keys[static_cast(keyID)].m_Comments[static_cast(commentID)]; } return ""; } AString cIniFile::GetKeyComment(const AString & keyname, const int commentID) const { int keyID = FindKey(keyname); if (keyID == noID) { return ""; } return GetKeyComment(int(keyID), commentID); } bool cIniFile::DeleteKeyComment(const int keyID, const int commentID) { if ((keyID < static_cast(m_Keys.size())) && (commentID < static_cast(m_Keys[static_cast(keyID)].m_Comments.size()))) { vector::iterator cpos = m_Keys[static_cast(keyID)].m_Comments.begin() + commentID; m_Keys[static_cast(keyID)].m_Comments.erase(cpos, cpos + 1); return true; } return false; } bool cIniFile::DeleteKeyComment(const AString & keyname, const int commentID) { int keyID = FindKey(keyname); if (keyID == noID) { return false; } return DeleteKeyComment(int(keyID), commentID); } bool cIniFile::DeleteKeyComments(const int keyID) { if (keyID < static_cast(m_Keys.size())) { m_Keys[static_cast(keyID)].m_Comments.clear(); return true; } return false; } bool cIniFile::DeleteKeyComments(const AString & keyname) { int keyID = FindKey(keyname); if (keyID == noID) { return false; } return DeleteKeyComments(static_cast(keyID)); } AString cIniFile::CheckCase(const AString & s) const { if (!m_IsCaseInsensitive) { return s; } AString res(s); size_t len = res.length(); for (size_t i = 0; i < len; i++) { res[i] = static_cast(tolower(res[i])); } return res; } void cIniFile::RemoveBom(AString & a_line) const { // The BOM sequence for UTF-8 is 0xEF, 0xBB, 0xBF static unsigned const char BOM[] = { 0xEF, 0xBB, 0xBF }; // The BOM sequence, if present, is always th e first three characters of the input. const AString ref = a_line.substr(0, 3); // If any of the first three chars do not match, return and do nothing. for (size_t i = 0; i < 3; ++i) { if (static_cast(ref[i]) != BOM[i]) { return; } } // First three characters match; erase them. a_line.erase(0, 3); } bool cIniFile::KeyExists(AString a_keyname) const { return FindKey(a_keyname) != noID; } std::vector> cIniFile::GetValues(AString a_keyName) { std::vector> ret; int keyID = FindKey(a_keyName); if (keyID == noID) { return ret; } for (size_t valueID = 0; valueID < m_Keys[static_cast(keyID)].m_Names.size(); ++valueID) { ret.emplace_back(m_Keys[static_cast(keyID)].m_Names[valueID], m_Keys[static_cast(keyID)].m_Values[valueID]); } return ret; } AStringVector ReadUpgradeIniPorts( cSettingsRepositoryInterface & a_Settings, const AString & a_KeyName, const AString & a_PortsValueName, const AString & a_OldIPv4ValueName, const AString & a_OldIPv6ValueName, const AString & a_DefaultValue ) { // Read the regular value, but don't use the default (in order to detect missing value for upgrade): AStringVector Ports; for (const auto & pair : a_Settings.GetValues(a_KeyName)) { if (pair.first != a_PortsValueName) { continue; } AStringVector temp = StringSplitAndTrim(pair.second, ";,"); Ports.insert(Ports.end(), temp.begin(), temp.end()); } if (Ports.empty()) { // Historically there were two separate entries for IPv4 and IPv6, merge them and migrate: AString Ports4 = a_Settings.GetValue(a_KeyName, a_OldIPv4ValueName, a_DefaultValue); AString Ports6 = a_Settings.GetValue(a_KeyName, a_OldIPv6ValueName); Ports = MergeStringVectors(StringSplitAndTrim(Ports4, ";,"), StringSplitAndTrim(Ports6, ";,")); a_Settings.DeleteValue(a_KeyName, a_OldIPv4ValueName); a_Settings.DeleteValue(a_KeyName, a_OldIPv6ValueName); // If those weren't present or were empty, use the default:" if (Ports.empty()) { Ports = StringSplitAndTrim(a_DefaultValue, ";,"); } a_Settings.SetValue(a_KeyName, a_PortsValueName, StringsConcat(Ports, ',')); } return Ports; } ================================================ FILE: src/IniFile.h ================================================ // IniFile.cpp: Implementation of the CIniFile class. // Written by: Adam Clauss // Email: cabadam@tamu.edu // You may use this class / code as you wish in your programs. Feel free to distribute it, and // email suggested changes to me. // // Rewritten by: Shane Hill // Date: 2001-08-21 // Email: Shane.Hill@dsto.defence.gov.au // Reason: Remove dependancy on MFC. Code should compile on any // platform. Tested on Windows / Linux / Irix //////////////////////////////////////////////////////////////////////////////// /* !! MODIFIED BY FAKETRUTH and madmaxoft!! */ #pragma once #include "SettingsRepositoryInterface.h" #define MAX_KEYNAME 128 #define MAX_VALUENAME 128 #define MAX_VALUEDATA 2048 // tolua_begin class cIniFile: public cSettingsRepositoryInterface { private: // tolua_end using Super = cSettingsRepositoryInterface; bool m_IsCaseInsensitive; AString m_Filename; struct key { std::vector m_Names; std::vector m_Values; std::vector m_Comments; } ; std::vector m_Keys; std::vector m_Names; std::vector m_Comments; /** If the object is case-insensitive, returns s as lowercase; otherwise returns s as-is */ AString CheckCase(const AString & s) const; /** Removes the UTF-8 BOMs (Byte order makers), if present. */ void RemoveBom(AString & a_line) const; // tolua_begin public: // NOTE: This has to be present for ToLua++'s parser to output the noID constant into the API // We don't want to export the entire base class, so the constant needs to get pulled into this descendant enum { noID = Super::noID, }; /** Creates a new instance with no data */ cIniFile(void); // tolua_end virtual std::vector> GetValues(AString a_keyName) override; virtual bool KeyExists(const AString a_keyName) const override; // tolua_begin // Sets whether or not keynames and valuenames should be case sensitive. // The default is case insensitive. void CaseSensitive (void) { m_IsCaseInsensitive = false; } void CaseInsensitive(void) { m_IsCaseInsensitive = true; } /** Reads the contents of the specified ini file If the file doesn't exist and a_AllowExampleRedirect is true, tries to read .example.ini, and writes its contents as .ini, if successful. Returns true if successful, false otherwise. */ bool ReadFile(const AString & a_FileName, bool a_AllowExampleRedirect = true); /** Writes data stored in class to the specified ini file. Returns true on success, false on failure. */ bool WriteFile(const AString & a_FileName) const; virtual bool Flush() override { return WriteFile(m_Filename); } /** Deletes all stored ini data (but doesn't touch the file) */ void Clear(void); /** Returns true iff the specified value exists. */ bool HasValue(const AString & a_KeyName, const AString & a_ValueName) const override; /** Returns index of specified key, or noID if not found */ int FindKey(const AString & keyname) const; /** Returns index of specified value, in the specified key, or noID if not found */ int FindValue(const int keyID, const AString & valuename) const; /** Returns number of keys currently in the ini */ int GetNumKeys(void) const { return static_cast(m_Keys.size()); } /** Add a key name */ int AddKeyName(const AString & keyname) override; // Returns key names by index. AString GetKeyName(const int keyID) const; // Returns number of values stored for specified key. int GetNumValues(const AString & keyname) const; int GetNumValues(const int keyID) const; // Returns value name by index for a given keyname or keyID. AString GetValueName(const AString & keyname, const int valueID) const; AString GetValueName(const int keyID, const int valueID) const; // Gets value of [keyname] valuename =. // Overloaded to return string, int, and double. // Returns defValue if key / value not found. AString GetValue (const AString & keyname, const AString & valuename, const AString & defValue = "") const override; AString GetValue (const int keyID, const int valueID, const AString & defValue = "") const; double GetValueF(const AString & keyname, const AString & valuename, const double defValue = 0) const; int GetValueI(const AString & keyname, const AString & valuename, const int defValue = 0) const; bool GetValueB(const AString & keyname, const AString & valuename, const bool defValue = false) const { return (GetValueI(keyname, valuename, defValue ? 1 : 0) != 0); } // Gets the value; if not found, write the default to the INI file AString GetValueSet (const AString & keyname, const AString & valuename, const AString & defValue = "") override; double GetValueSetF(const AString & keyname, const AString & valuename, const double defValue = 0.0); int GetValueSetI(const AString & keyname, const AString & valuename, const int defValue = 0) override; Int64 GetValueSetI(const AString & keyname, const AString & valuename, const Int64 defValue = 0) override; bool GetValueSetB(const AString & keyname, const AString & valuename, const bool defValue = false) override { return (GetValueSetI(keyname, valuename, defValue ? 1 : 0) != 0); } // Adds a new value to the specified key. // If a value of the same name already exists, creates another one (non-standard INI file) void AddValue (const AString & a_KeyName, const AString & a_ValueName, const AString & a_Value) override; void AddValueI(const AString & a_KeyName, const AString & a_ValueName, const int a_Value); void AddValueB(const AString & a_KeyName, const AString & a_ValueName, const bool a_Value) { return AddValueI(a_KeyName, a_ValueName, a_Value ? 1 : 0); } void AddValueF(const AString & a_KeyName, const AString & a_ValueName, const double a_Value); // Overwrites the value of [keyname].valuename // Specify the optional parameter as false (0) if you do not want the value created if it doesn't exist. // Returns true if value set, false otherwise. // Overloaded to accept string, int, and double. bool SetValue (const int keyID, const int valueID, const AString & value); bool SetValue (const AString & a_KeyName, const AString & a_ValueName, const AString & a_Value, const bool a_CreateIfNotExists = true) override; bool SetValueI(const AString & a_KeyName, const AString & a_ValueName, const int a_Value, const bool a_CreateIfNotExists = true) override; bool SetValueI(const AString & a_Keyname, const AString & a_ValueName, const Int64 a_Value, const bool a_CreateIfNotExists = true); bool SetValueB(const AString & a_KeyName, const AString & a_ValueName, const bool a_Value, const bool a_CreateIfNotExists = true) { return SetValueI(a_KeyName, a_ValueName, int(a_Value), a_CreateIfNotExists); } bool SetValueF(const AString & a_KeyName, const AString & a_ValueName, const double a_Value, const bool a_CreateIfNotExists = true); // Deletes specified value. // Returns true if value existed and deleted, false otherwise. bool DeleteValueByID(const int keyID, const int valueID); bool DeleteValue(const AString & keyname, const AString & valuename) override; // Deletes specified key and all values contained within. // Returns true if key existed and deleted, false otherwise. bool DeleteKey(const AString & keyname); // Header comment functions. // Header comments are those comments before the first key. /** Returns the number of header comments */ int GetNumHeaderComments(void) {return static_cast(m_Comments.size());} /** Adds a header comment */ void AddHeaderComment(const AString & comment); /** Returns a header comment, or empty string if out of range */ AString GetHeaderComment(const int commentID) const; /** Deletes a header comment. Returns true if successful */ bool DeleteHeaderComment(int commentID); /** Deletes all header comments */ void DeleteHeaderComments(void) {m_Comments.clear();} // Key comment functions. // Key comments are those comments within a key. Any comments // defined within value names will be added to this list. Therefore, // these comments will be moved to the top of the key definition when // the CIniFile::WriteFile() is called. /** Get number of key comments */ int GetNumKeyComments(const int keyID) const; /** Get number of key comments */ int GetNumKeyComments(const AString & keyname) const; /** Add a key comment */ bool AddKeyComment(const int keyID, const AString & comment); /** Add a key comment */ bool AddKeyComment(const AString & keyname, const AString & comment) override; /** Return a key comment */ AString GetKeyComment(const int keyID, const int commentID) const; AString GetKeyComment(const AString & keyname, const int commentID) const override; // Delete a key comment. bool DeleteKeyComment(const int keyID, const int commentID); bool DeleteKeyComment(const AString & keyname, const int commentID) override; // Delete all comments for a key. bool DeleteKeyComments(const int keyID); bool DeleteKeyComments(const AString & keyname); }; // tolua_end /** Reads the list of ports from the INI file, possibly upgrading from IPv4 / IPv6-specific values into new version-agnostic value. Reads the list of ports from a_PortsValueName. If that value doesn't exist or is empty, the list is combined from values in a_OldIPv4ValueName and a_OldIPv6ValueName; in this case the old values are removed from the INI file. If there is none of the three values or they are all empty, the default is used and stored in the Ports value. */ AStringVector ReadUpgradeIniPorts( cSettingsRepositoryInterface & a_Settings, const AString & a_KeyName, const AString & a_PortsValueName, const AString & a_OldIPv4ValueName, const AString & a_OldIPv6ValueName, const AString & a_DefaultValue ); ================================================ FILE: src/Inventory.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "Inventory.h" #include "Entities/Player.h" #include "ClientHandle.h" #include "UI/Window.h" #include "Item.h" #include "Root.h" #include "World.h" #include "json/json.h" #include "Items/ItemHandler.h" cInventory::cInventory(cPlayer & a_Owner) : m_ArmorSlots (1, 4), // 1 x 4 slots m_InventorySlots(9, 3), // 9 x 3 slots m_HotbarSlots (9, 1), // 9 x 1 slots m_ShieldSlots (1, 1), // 1 x 1 slots m_Owner(a_Owner) { // Ask each ItemGrid to report changes to us: m_ArmorSlots.AddListener(*this); m_InventorySlots.AddListener(*this); m_HotbarSlots.AddListener(*this); m_ShieldSlots.AddListener(*this); SetEquippedSlotNum(0); } void cInventory::Clear(void) { m_ArmorSlots.Clear(); m_InventorySlots.Clear(); m_HotbarSlots.Clear(); m_ShieldSlots.Clear(); } int cInventory::HowManyCanFit(const cItem & a_ItemStack, bool a_ConsiderEmptySlots) { return HowManyCanFit(a_ItemStack, 0, invNumSlots - 1, a_ConsiderEmptySlots); } int cInventory::HowManyCanFit(const cItem & a_ItemStack, int a_BeginSlotNum, int a_EndSlotNum, bool a_ConsiderEmptySlots) { UNUSED(a_ConsiderEmptySlots); if ((a_BeginSlotNum < 0) || (a_BeginSlotNum >= invNumSlots)) { LOGWARNING("%s: Bad BeginSlotNum, got %d, there are %d slots; correcting to 0.", __FUNCTION__, a_BeginSlotNum, invNumSlots - 1); a_BeginSlotNum = 0; } if ((a_EndSlotNum < 0) || (a_EndSlotNum >= invNumSlots)) { LOGWARNING("%s: Bad EndSlotNum, got %d, there are %d slots; correcting to %d.", __FUNCTION__, a_BeginSlotNum, invNumSlots, invNumSlots - 1); a_EndSlotNum = invNumSlots - 1; } if (a_BeginSlotNum > a_EndSlotNum) { std::swap(a_BeginSlotNum, a_EndSlotNum); } char NumLeft = a_ItemStack.m_ItemCount; char MaxStack = a_ItemStack.GetMaxStackSize(); for (int i = a_BeginSlotNum; i <= a_EndSlotNum; i++) { const cItem & Slot = GetSlot(i); if (Slot.IsEmpty()) { NumLeft -= MaxStack; } else if (Slot.IsEqual(a_ItemStack)) { NumLeft -= MaxStack - Slot.m_ItemCount; } if (NumLeft <= 0) { // All items fit return a_ItemStack.m_ItemCount; } } // for i - m_Slots[] return a_ItemStack.m_ItemCount - NumLeft; } char cInventory::AddItem(const cItem & a_Item, bool a_AllowNewStacks) { m_Owner.AddKnownItem(a_Item); cItem ToAdd(a_Item); char res = 0; // When the item is a armor, try to set it directly to the armor slot. if (ItemCategory::IsArmor(a_Item.m_ItemType)) { for (int i = 0; i < m_ArmorSlots.GetNumSlots(); i++) { if (m_ArmorSlots.GetSlot(i).IsEmpty() && cSlotAreaArmor::CanPlaceArmorInSlot(i, a_Item)) { m_ArmorSlots.SetSlot(i, a_Item); return a_Item.m_ItemCount; } } } // Add to existing stacks in the hotbar. res += m_HotbarSlots.AddItem(ToAdd, false); ToAdd.m_ItemCount = static_cast(a_Item.m_ItemCount - res); if (ToAdd.m_ItemCount == 0) { return res; } // Add to existing stacks in main inventory. res += m_InventorySlots.AddItem(ToAdd, false); ToAdd.m_ItemCount = static_cast(a_Item.m_ItemCount - res); if (ToAdd.m_ItemCount == 0) { return res; } // All existing stacks are now filled. if (!a_AllowNewStacks) { return res; } // Try adding new stacks to the hotbar. res += m_HotbarSlots.AddItem(ToAdd, true); ToAdd.m_ItemCount = static_cast(a_Item.m_ItemCount - res); if (ToAdd.m_ItemCount == 0) { return res; } // Try adding new stacks to the main inventory. res += m_InventorySlots.AddItem(ToAdd, true); return res; } char cInventory::AddItems(cItems & a_ItemStackList, bool a_AllowNewStacks) { char TotalAdded = 0; for (cItems::iterator itr = a_ItemStackList.begin(); itr != a_ItemStackList.end();) { char NumAdded = AddItem(*itr, a_AllowNewStacks); if (itr->m_ItemCount == NumAdded) { itr = a_ItemStackList.erase(itr); } else { itr->m_ItemCount -= NumAdded; ++itr; } TotalAdded += NumAdded; } return TotalAdded; } int cInventory::RemoveItem(const cItem & a_ItemStack) { char RemovedItems = m_ShieldSlots.RemoveItem(a_ItemStack); if (RemovedItems < a_ItemStack.m_ItemCount) { RemovedItems += m_HotbarSlots.RemoveItem(a_ItemStack); } if (RemovedItems < a_ItemStack.m_ItemCount) { cItem Temp(a_ItemStack); Temp.m_ItemCount -= RemovedItems; RemovedItems += m_InventorySlots.RemoveItem(Temp); } return RemovedItems; } cItem * cInventory::FindItem(const cItem & a_RecipeItem) { cItem * Item = m_ShieldSlots.FindItem(a_RecipeItem); if (Item != nullptr) { return Item; } Item = m_HotbarSlots.FindItem(a_RecipeItem); if (Item != nullptr) { return Item; } return m_InventorySlots.FindItem(a_RecipeItem); } bool cInventory::RemoveOneEquippedItem(void) { if (m_HotbarSlots.GetSlot(m_EquippedSlotNum).IsEmpty()) { return false; } m_HotbarSlots.ChangeSlotCount(m_EquippedSlotNum, -1); return true; } int cInventory::ReplaceOneEquippedItem(const cItem & a_Item, bool a_TryOtherSlots) { // Ignore whether there was an item in the slot to remove. RemoveOneEquippedItem(); auto EquippedItem = GetEquippedItem(); if (EquippedItem.IsEmpty()) { SetEquippedItem(a_Item); return a_Item.m_ItemCount; } // Handle case when equipped item is the same as the replacement item. cItem ItemsToAdd = a_Item; if (EquippedItem.IsEqual(ItemsToAdd)) { auto AmountToAdd = std::min(static_cast(ItemsToAdd.GetMaxStackSize() - EquippedItem.m_ItemCount), ItemsToAdd.m_ItemCount); EquippedItem.m_ItemCount += AmountToAdd; SetEquippedItem(EquippedItem); ItemsToAdd.m_ItemCount -= AmountToAdd; } auto ItemsAdded = a_Item.m_ItemCount - ItemsToAdd.m_ItemCount; if (ItemsToAdd.m_ItemCount == 0) { return ItemsAdded; } if (!a_TryOtherSlots) { return ItemsAdded; } // Try the rest of the inventory. return AddItem(ItemsToAdd) + ItemsAdded; } int cInventory::HowManyItems(const cItem & a_Item) { return m_ArmorSlots.HowManyItems(a_Item) + m_InventorySlots.HowManyItems(a_Item) + m_HotbarSlots.HowManyItems(a_Item) + m_ShieldSlots.HowManyItems(a_Item); } bool cInventory::HasItems(const cItem & a_ItemStack) { int CurrentlyHave = HowManyItems(a_ItemStack); return (CurrentlyHave >= a_ItemStack.m_ItemCount); } void cInventory::SetSlot(int a_SlotNum, const cItem & a_Item) { if ((a_SlotNum < 0) || (a_SlotNum >= invNumSlots)) { LOGWARNING("%s: requesting an invalid slot index: %d out of %d. Ignoring.", __FUNCTION__, a_SlotNum, invNumSlots - 1); return; } int GridSlotNum = 0; cItemGrid * Grid = GetGridForSlotNum(a_SlotNum, GridSlotNum); if (Grid == nullptr) { LOGWARNING("%s(%d): requesting an invalid itemgrid. Ignoring.", __FUNCTION__, a_SlotNum); return; } Grid->SetSlot(GridSlotNum, a_Item); } void cInventory::SetArmorSlot(int a_ArmorSlotNum, const cItem & a_Item) { m_ArmorSlots.SetSlot(a_ArmorSlotNum, a_Item); } void cInventory::SetInventorySlot(int a_InventorySlotNum, const cItem & a_Item) { m_InventorySlots.SetSlot(a_InventorySlotNum, a_Item); } void cInventory::SetHotbarSlot(int a_HotBarSlotNum, const cItem & a_Item) { m_HotbarSlots.SetSlot(a_HotBarSlotNum, a_Item); } void cInventory::SetShieldSlot(const cItem & a_Item) { m_ShieldSlots.SetSlot(0, a_Item); } void cInventory::SetEquippedItem(const cItem & a_Item) { SetHotbarSlot(GetEquippedSlotNum(), a_Item); } void cInventory::SendEquippedSlot() { int EquippedSlotNum = cInventory::invArmorCount + cInventory::invInventoryCount + GetEquippedSlotNum(); SendSlot(EquippedSlotNum); } const cItem & cInventory::GetSlot(int a_SlotNum) const { if ((a_SlotNum < 0) || (a_SlotNum >= invNumSlots)) { LOGWARNING("%s: requesting an invalid slot index: %d out of %d. Returning the first inventory slot instead.", __FUNCTION__, a_SlotNum, invNumSlots - 1); return m_InventorySlots.GetSlot(0); } int GridSlotNum = 0; const cItemGrid * Grid = GetGridForSlotNum(a_SlotNum, GridSlotNum); if (Grid == nullptr) { // Something went wrong, but we don't know what. We must return a value, so return the first inventory slot LOGWARNING("%s(%d): requesting an invalid ItemGrid, returning the first inventory slot instead.", __FUNCTION__, a_SlotNum); return m_InventorySlots.GetSlot(0); } return Grid->GetSlot(GridSlotNum); } const cItem & cInventory::GetArmorSlot(int a_ArmorSlotNum) const { if ((a_ArmorSlotNum < 0) || (a_ArmorSlotNum >= invArmorCount)) { LOGWARNING("%s: requesting an invalid slot index: %d out of %d. Returning the first one instead", __FUNCTION__, a_ArmorSlotNum, invArmorCount - 1); return m_ArmorSlots.GetSlot(0); } return m_ArmorSlots.GetSlot(a_ArmorSlotNum); } const cItem & cInventory::GetInventorySlot(int a_InventorySlotNum) const { if ((a_InventorySlotNum < 0) || (a_InventorySlotNum >= invInventoryCount)) { LOGWARNING("%s: requesting an invalid slot index: %d out of %d. Returning the first one instead", __FUNCTION__, a_InventorySlotNum, invInventoryCount - 1); return m_InventorySlots.GetSlot(0); } return m_InventorySlots.GetSlot(a_InventorySlotNum); } const cItem & cInventory::GetHotbarSlot(int a_SlotNum) const { if ((a_SlotNum < 0) || (a_SlotNum >= invHotbarCount)) { LOGWARNING("%s: requesting an invalid slot index: %d out of %d. Returning the first one instead", __FUNCTION__, a_SlotNum, invHotbarCount - 1); return m_HotbarSlots.GetSlot(0); } return m_HotbarSlots.GetSlot(a_SlotNum); } const cItem & cInventory::GetShieldSlot() const { return m_ShieldSlots.GetSlot(0); } const cItem & cInventory::GetEquippedItem(void) const { return GetHotbarSlot(m_EquippedSlotNum); } void cInventory::SetEquippedSlotNum(int a_SlotNum) { if ((a_SlotNum < 0) || (a_SlotNum >= invHotbarCount)) { LOGWARNING("%s: requesting invalid slot index: %d out of %d. Setting 0 instead.", __FUNCTION__, a_SlotNum, invHotbarCount - 1); m_EquippedSlotNum = 0; } else { m_EquippedSlotNum = a_SlotNum; } } bool cInventory::DamageEquippedItem(short a_Amount) { return DamageItem(invHotbarOffset + m_EquippedSlotNum, a_Amount); } char cInventory::ChangeSlotCount(int a_SlotNum, char a_AddToCount) { int GridSlotNum = 0; cItemGrid * Grid = GetGridForSlotNum(a_SlotNum, GridSlotNum); if (Grid == nullptr) { LOGWARNING("%s: invalid slot number, expected 0 .. %d, got %d; ignoring", __FUNCTION__, invNumSlots, a_SlotNum); return -1; } return Grid->ChangeSlotCount(GridSlotNum, a_AddToCount); } bool cInventory::DamageItem(int a_SlotNum, short a_Amount) { if ((a_SlotNum < 0) || (a_SlotNum >= invNumSlots)) { LOGWARNING("%s: requesting an invalid slot index: %d out of %d", __FUNCTION__, a_SlotNum, invNumSlots - 1); return false; } if (a_Amount <= 0) { return false; } int GridSlotNum = 0; cItemGrid * Grid = GetGridForSlotNum(a_SlotNum, GridSlotNum); if (Grid == nullptr) { LOGWARNING("%s(%d, %d): requesting an invalid grid, ignoring.", __FUNCTION__, a_SlotNum, a_Amount); return false; } if (!Grid->DamageItem(GridSlotNum, a_Amount)) { // The item has been damaged, but did not break yet SendSlot(a_SlotNum); return false; } // The item has broken, remove it: Grid->EmptySlot(GridSlotNum); return true; } void cInventory::CopyToItems(cItems & a_Items) { m_ArmorSlots.CopyToItems(a_Items); m_InventorySlots.CopyToItems(a_Items); m_HotbarSlots.CopyToItems(a_Items); } void cInventory::SendSlot(int a_SlotNum) { cItem Item(GetSlot(a_SlotNum)); if (Item.IsEmpty()) { // Sanitize items that are not completely empty (ie. count == 0, but type != empty) Item.Empty(); } m_Owner.GetClientHandle()->SendInventorySlot(0, static_cast(a_SlotNum + 5), Item); // Slots in the client are numbered "+ 5" because of crafting grid and result } /* int cInventory::MoveItem(short a_ItemType, short a_ItemDamage, int a_Count, int a_BeginSlot, int a_EndSlot) { int res = 0; for (int i = a_BeginSlot; i <= a_EndSlot; i++) { if ( m_Slots[i].IsEmpty() || ((m_Slots[i].m_ItemType == a_ItemType) && (m_Slots[i].m_ItemDamage == a_ItemDamage)) ) { int MaxCount = ItemHandler(a_ItemType)->GetMaxStackSize(); ASSERT(m_Slots[i].m_ItemCount <= MaxCount); int NumToMove = std::min(a_Count, MaxCount - m_Slots[i].m_ItemCount); m_Slots[i].m_ItemCount += NumToMove; m_Slots[i].m_ItemDamage = a_ItemDamage; m_Slots[i].m_ItemType = a_ItemType; SendSlot(i); res += NumToMove; a_Count -= NumToMove; if (a_Count <= 0) { // No more items to distribute return res; } } } // for i - m_Slots[] // No more space to distribute to return res; } */ int cInventory::ArmorSlotNumToEntityEquipmentID(short a_ArmorSlotNum) { switch (a_ArmorSlotNum) { case 0: return 4; // Helmet case 1: return 3; // Chestplate case 2: return 2; // Leggings case 3: return 1; // Boots } LOGWARN("%s: invalid armor slot number: %d", __FUNCTION__, a_ArmorSlotNum); return 0; } #if 0 bool cInventory::AddToBar(cItem & a_Item, const int a_Offset, const int a_Size, bool * a_bChangedSlots, int a_Mode /* = 0 */) { // Fill already present stacks if (a_Mode < 2) { int MaxStackSize = cItemHandler::GetItemHandler(a_Item.m_ItemType)->GetMaxStackSize(); for (int i = 0; i < a_Size; i++) { if ( (m_Slots[i + a_Offset].m_ItemType == a_Item.m_ItemType) && (m_Slots[i + a_Offset].m_ItemCount < MaxStackSize) && (m_Slots[i + a_Offset].m_ItemDamage == a_Item.m_ItemDamage) ) { int NumFree = MaxStackSize - m_Slots[i + a_Offset].m_ItemCount; if (NumFree >= a_Item.m_ItemCount) { // printf("1. Adding %i items ( free: %i)\n", a_Item.m_ItemCount, NumFree); m_Slots[i + a_Offset].m_ItemCount += a_Item.m_ItemCount; a_Item.m_ItemCount = 0; a_bChangedSlots[i + a_Offset] = true; break; } else { // printf("2. Adding %i items\n", NumFree); m_Slots[i + a_Offset].m_ItemCount += (char)NumFree; a_Item.m_ItemCount -= (char)NumFree; a_bChangedSlots[i + a_Offset] = true; } } } } if (a_Mode > 0) { // If we got more left, find first empty slot for (int i = 0; (i < a_Size) && (a_Item.m_ItemCount > 0); i++) { if (m_Slots[i + a_Offset].m_ItemType == -1) { m_Slots[i + a_Offset] = a_Item; a_Item.m_ItemCount = 0; a_bChangedSlots[i + a_Offset] = true; } } } return true; } #endif void cInventory::UpdateItems(void) { const cItem & Slot = GetEquippedItem(); if (!Slot.IsEmpty()) { Slot.GetHandler().OnUpdate(m_Owner.GetWorld(), &m_Owner, Slot); } } void cInventory::SaveToJson(Json::Value & a_Value) { // The JSON originally included the 4 crafting slots and the result, so we have to put empty items there, too: cItem EmptyItem; Json::Value EmptyItemJson; EmptyItem.GetJson(EmptyItemJson); for (int i = 0; i < 5; i++) { a_Value.append(EmptyItemJson); } // The 4 armor slots follow: for (int i = 0; i < invArmorCount; i++) { Json::Value JSON_Item; m_ArmorSlots.GetSlot(i).GetJson(JSON_Item); a_Value.append(JSON_Item); } // Next comes the main inventory: for (int i = 0; i < invInventoryCount; i++) { Json::Value JSON_Item; m_InventorySlots.GetSlot(i).GetJson(JSON_Item); a_Value.append(JSON_Item); } // The hotbar: for (int i = 0; i < invHotbarCount; i++) { Json::Value JSON_Item; m_HotbarSlots.GetSlot(i).GetJson(JSON_Item); a_Value.append(JSON_Item); } // Shield slot is the last Json::Value JSON_Item; m_ShieldSlots.GetSlot(0).GetJson(JSON_Item); a_Value.append(JSON_Item); } bool cInventory::LoadFromJson(Json::Value & a_Value) { int SlotIdx = 0; for (Json::Value::iterator itr = a_Value.begin(); itr != a_Value.end(); ++itr, SlotIdx++) { cItem Item; Item.FromJson(*itr); // The JSON originally included the 4 crafting slots and the result slot, so we need to skip the first 5 items: if (SlotIdx < 5) { continue; } // If we loaded all the slots, stop now, even if the JSON has more: if (SlotIdx - 5 >= invNumSlots) { break; } int GridSlotNum = 0; cItemGrid * Grid = GetGridForSlotNum(SlotIdx - 5, GridSlotNum); ASSERT(Grid != nullptr); Grid->SetSlot(GridSlotNum, Item); } // for itr - a_Value[] return true; } const cItemGrid * cInventory::GetGridForSlotNum(int a_SlotNum, int & a_GridSlotNum) const { ASSERT(a_SlotNum >= 0); if (a_SlotNum < invArmorCount) { a_GridSlotNum = a_SlotNum; return &m_ArmorSlots; } a_SlotNum -= invArmorCount; if (a_SlotNum < invInventoryCount) { a_GridSlotNum = a_SlotNum; return &m_InventorySlots; } a_SlotNum -= invInventoryCount; if (a_SlotNum < invHotbarCount) { a_GridSlotNum = a_SlotNum; return &m_HotbarSlots; } a_GridSlotNum = a_SlotNum - invHotbarCount; return &m_ShieldSlots; } cItemGrid * cInventory::GetGridForSlotNum(int a_SlotNum, int & a_GridSlotNum) { ASSERT(a_SlotNum >= 0); if (a_SlotNum < invArmorCount) { a_GridSlotNum = a_SlotNum; return &m_ArmorSlots; } a_SlotNum -= invArmorCount; if (a_SlotNum < invInventoryCount) { a_GridSlotNum = a_SlotNum; return &m_InventorySlots; } a_SlotNum -= invInventoryCount; if (a_SlotNum < invHotbarCount) { a_GridSlotNum = a_SlotNum; return &m_HotbarSlots; } a_GridSlotNum = a_SlotNum - invHotbarCount; return &m_ShieldSlots; } void cInventory::OnSlotChanged(cItemGrid * a_ItemGrid, int a_SlotNum) { // Send the neccessary updates to whoever needs them if (!m_Owner.IsTicking()) { // Owner is not (yet) valid, skip for now return; } // Armor update needs broadcast to other players: cWorld * World = m_Owner.GetWorld(); if ((a_ItemGrid == &m_ArmorSlots) && (World != nullptr)) { World->BroadcastEntityEquipment( m_Owner, static_cast(ArmorSlotNumToEntityEquipmentID(static_cast(a_SlotNum))), m_ArmorSlots.GetSlot(a_SlotNum), m_Owner.GetClientHandle() ); } // Broadcast the Equipped Item, if the Slot is changed. if ((a_ItemGrid == &m_HotbarSlots) && (m_EquippedSlotNum == a_SlotNum)) { m_Owner.GetWorld()->BroadcastEntityEquipment(m_Owner, 0, GetEquippedItem(), m_Owner.GetClientHandle()); } // Convert the grid-local a_SlotNum to our global SlotNum: int Base = 0; if (a_ItemGrid == &m_ArmorSlots) { Base = invArmorOffset; } else if (a_ItemGrid == &m_InventorySlots) { Base = invInventoryOffset; } else if (a_ItemGrid == &m_HotbarSlots) { Base = invHotbarOffset; } else if (a_ItemGrid == &m_ShieldSlots) { Base = invShieldOffset; } else { ASSERT(!"Unknown ItemGrid calling OnSlotChanged()"); return; } SendSlot(Base + a_SlotNum); } ================================================ FILE: src/Inventory.h ================================================ #pragma once #include "ItemGrid.h" namespace Json { class Value; }; class cPlayer; // tolua_begin /** This class represents the player's inventory The slots are divided into three areas: - armor slots (1 x 4) - inventory slots (9 x 3) - hotbar slots (9 x 1) The generic GetSlot(), SetSlot() and HowManyCanFit() functions take the index of the slots, as if armor slots, inventory slots and then hotbar slots were put one after another. You can use the invArmorOffset, invInventoryOffset and invHotbarOffset constants. */ class cInventory : // tolua_end public cItemGrid::cListener // tolua_begin { public: // Counts and offsets to individual parts of the inventory, as used by GetSlot() / SetSlot() / HowManyCanFit(): enum { invArmorCount = 4, invInventoryCount = 9 * 3, invHotbarCount = 9, invShieldCount = 1, // Number of slots in shield slots grid invArmorOffset = 0, invInventoryOffset = invArmorOffset + invArmorCount, invHotbarOffset = invInventoryOffset + invInventoryCount, invShieldOffset = invHotbarOffset + invHotbarCount, // Offset where shield slots start invNumSlots = invShieldOffset + invShieldCount } ; // tolua_end cInventory(cPlayer & a_Owner); virtual ~cInventory() override {} // tolua_begin /** Removes all items from the entire inventory */ void Clear(void); /** Returns number of items out of a_ItemStack that can fit in the storage */ int HowManyCanFit(const cItem & a_ItemStack, bool a_ConsiderEmptySlots = true); /** Returns how many items of the specified type would fit into the slot range specified */ int HowManyCanFit(const cItem & a_ItemStack, int a_BeginSlotNum, int a_EndSlotNum, bool a_ConsiderEmptySlots = true); /** Adds as many items out of a_ItemStack as can fit. If a_AllowNewStacks is set to false, only existing stacks can be topped up; if a_AllowNewStacks is set to true, empty slots can be used for the rest. Fills existing stacks first and fills the hotbar before the main inventory. Returns the number of items that fit. */ char AddItem(const cItem & a_ItemStack, bool a_AllowNewStacks = true); /** Same as AddItem, but works on an entire list of item stacks. The a_ItemStackList is modified to reflect the leftover items. If a_AllowNewStacks is set to false, only existing stacks can be topped up; if a_AllowNewStacks is set to true, empty slots can be used for the rest. Returns the total number of items that fit. */ char AddItems(cItems & a_ItemStackList, bool a_AllowNewStacks); /** Removes the specified item from the inventory, as many as possible, up to a_ItemStack.m_ItemCount. Returns the number of items that were removed. */ int RemoveItem(const cItem & a_ItemStack); /** Finds an item based on ItemType and ItemDamage (<- defines the itemType, too) */ cItem * FindItem(const cItem & a_RecipeItem); /** Removes one item out of the currently equipped item stack, returns true if successful, false if empty-handed */ bool RemoveOneEquippedItem(void); /** Removes one item from the the current equipped item stack, and attempts to add the specified item stack back to the same slot. If it is not possible to place the item in the same slot, optionally (default true) tries to place the specified item elsewhere in the inventory. Returns the number of items successfully added. If the currently equipped slot is empty, its contents are simply set to the given Item. */ int ReplaceOneEquippedItem(const cItem & a_Item, bool a_TryOtherSlots = true); /** Returns the number of items of type a_Item that are stored */ int HowManyItems(const cItem & a_Item); /** Returns true if there are at least as many items of type a_ItemStack as in a_ItemStack */ bool HasItems(const cItem & a_ItemStack); /** Sends the equipped item slot to the client */ void SendEquippedSlot(); /** Returns the cItemGrid object representing the armor slots */ cItemGrid & GetArmorGrid(void) { return m_ArmorSlots; } /** Returns the cItemGrid object representing the main inventory slots */ cItemGrid & GetInventoryGrid(void) { return m_InventorySlots; } /** Returns the cItemGrid object representing the hotbar slots */ cItemGrid & GetHotbarGrid(void) { return m_HotbarSlots; } /** Returns the player associated with this inventory */ cPlayer & GetOwner(void) { return m_Owner; } /** Copies the non-empty slots into a_ItemStacks; preserves the original a_Items contents */ void CopyToItems(cItems & a_Items); // tolua_end /** Returns the player associated with this inventory (const version) */ const cPlayer & GetOwner(void) const { return m_Owner; } // tolua_begin /** Returns current item in a_SlotNum slot */ const cItem & GetSlot(int a_SlotNum) const; /** Returns current item in a_ArmorSlotNum in armor slots */ const cItem & GetArmorSlot(int a_ArmorSlotNum) const; /** Returns current item in a_ArmorSlotNum in inventory slots */ const cItem & GetInventorySlot(int a_InventorySlotNum) const; /** Returns current item in a_ArmorSlotNum in hotbar slots */ const cItem & GetHotbarSlot(int a_HotBarSlotNum) const; /** Returns current item in shield slot */ const cItem & GetShieldSlot() const; /** Returns current equiped item */ const cItem & GetEquippedItem(void) const; /** Puts a_Item item in a_SlotNum slot number */ void SetSlot(int a_SlotNum, const cItem & a_Item); /** Puts a_Item item in a_ArmorSlotNum slot number in armor slots */ void SetArmorSlot(int a_ArmorSlotNum, const cItem & a_Item); /** Puts a_Item item in a_InventorySlotNum slot number in inventory slots */ void SetInventorySlot(int a_InventorySlotNum, const cItem & a_Item); /** Puts a_Item item in a_HotBarSlotNum slot number in hotbar slots */ void SetHotbarSlot(int a_HotBarSlotNum, const cItem & a_Item); /** Sets current item in shield slot */ void SetShieldSlot(const cItem & a_Item); /** Sets current item in the equipped hotbar slot */ void SetEquippedItem(const cItem & a_Item); /** Sets equiped item to the a_SlotNum slot number */ void SetEquippedSlotNum(int a_SlotNum); /** Returns slot number of equiped item */ int GetEquippedSlotNum(void) { return m_EquippedSlotNum; } /** Adds (or subtracts, if a_AddToCount is negative) to the count of items in the specified slot. If the slot is empty, ignores the call. Returns the new count, or -1 if the slot number is invalid. */ char ChangeSlotCount(int a_SlotNum, char a_AddToCount); /** Adds the specified damage to the specified item; deletes the item and returns true if the item broke. */ bool DamageItem(int a_SlotNum, short a_Amount); /** Adds the specified damage to the currently held item; deletes the item and returns true if the item broke. */ bool DamageEquippedItem(short a_Amount = 1); const cItem & GetEquippedHelmet (void) const { return m_ArmorSlots.GetSlot(0); } const cItem & GetEquippedChestplate(void) const { return m_ArmorSlots.GetSlot(1); } const cItem & GetEquippedLeggings (void) const { return m_ArmorSlots.GetSlot(2); } const cItem & GetEquippedBoots (void) const { return m_ArmorSlots.GetSlot(3); } // tolua_end /** Sends the slot contents to the owner */ void SendSlot(int a_SlotNum); /** Update items (e.g. Maps) */ void UpdateItems(void); /** Converts an armor slot number into the ID for the EntityEquipment packet */ static int ArmorSlotNumToEntityEquipmentID(short a_ArmorSlotNum); void SaveToJson(Json::Value & a_Value); bool LoadFromJson(Json::Value & a_Value); protected: bool AddToBar(cItem & a_Item, const int a_Offset, const int a_Size, bool * a_bChangedSlots, int a_Mode = 0); cItemGrid m_ArmorSlots; cItemGrid m_InventorySlots; cItemGrid m_HotbarSlots; cItemGrid m_ShieldSlots; int m_EquippedSlotNum; cPlayer & m_Owner; /** Returns the ItemGrid and the (grid-local) slot number for a (global) slot number; return nullptr for invalid SlotNum */ const cItemGrid * GetGridForSlotNum(int a_SlotNum, int & a_GridSlotNum) const; /** Returns the ItemGrid and the (grid-local) slot number for a (global) slot number; return nullptr for invalid SlotNum */ cItemGrid * GetGridForSlotNum(int a_SlotNum, int & a_GridSlotNum); // cItemGrid::cListener override: virtual void OnSlotChanged(cItemGrid * a_ItemGrid, int a_SlotNum) override; }; // tolua_export ================================================ FILE: src/Item.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "Item.h" #include "BlockType.h" #include "ItemGrid.h" #include "json/json.h" #include "Items/ItemHandler.h" #include "FastRandom.h" cItem::cItem(): m_ItemType(E_ITEM_EMPTY), m_ItemCount(0), m_ItemDamage(0), m_CustomName(), m_RepairCost(0), m_FireworkItem(), m_ItemColor() { } cItem::cItem( short a_ItemType, char a_ItemCount, short a_ItemDamage, const AString & a_Enchantments, const AString & a_CustomName, const AStringVector & a_LoreTable ): m_ItemType (a_ItemType), m_ItemCount (a_ItemCount), m_ItemDamage (a_ItemDamage), m_Enchantments(a_Enchantments), m_CustomName (a_CustomName), m_LoreTable (a_LoreTable), m_RepairCost (0), m_FireworkItem(), m_ItemColor() { if (!IsValidItem(m_ItemType)) { if ((m_ItemType != E_BLOCK_AIR) && (m_ItemType != E_ITEM_EMPTY)) { LOGWARNING("%s: creating an invalid item type (%d), resetting to empty.", __FUNCTION__, a_ItemType); } Empty(); } } void cItem::Empty() { m_ItemType = E_ITEM_EMPTY; m_ItemCount = 0; m_ItemDamage = 0; m_Enchantments.Clear(); m_CustomName = ""; m_LoreTable.clear(); m_RepairCost = 0; m_FireworkItem.EmptyData(); m_ItemColor.Clear(); } void cItem::Clear() { m_ItemType = E_ITEM_EMPTY; m_ItemCount = 0; m_ItemDamage = 0; m_RepairCost = 0; m_ItemColor.Clear(); } cItem cItem::CopyOne(void) const { cItem res(*this); res.m_ItemCount = 1; return res; } cItem & cItem::AddCount(char a_AmountToAdd) { m_ItemCount += a_AmountToAdd; if (m_ItemCount <= 0) { Empty(); } return *this; } short cItem::GetMaxDamage(void) const { switch (m_ItemType) { case E_ITEM_BOW: return 384; case E_ITEM_CHAIN_BOOTS: return 196; case E_ITEM_CHAIN_CHESTPLATE:return 241; case E_ITEM_CHAIN_HELMET: return 166; case E_ITEM_CHAIN_LEGGINGS: return 226; case E_ITEM_DIAMOND_AXE: return 1561; case E_ITEM_DIAMOND_BOOTS: return 430; case E_ITEM_DIAMOND_CHESTPLATE: return 529; case E_ITEM_DIAMOND_HELMET: return 364; case E_ITEM_DIAMOND_HOE: return 1561; case E_ITEM_DIAMOND_LEGGINGS:return 496; case E_ITEM_DIAMOND_PICKAXE: return 1561; case E_ITEM_DIAMOND_SHOVEL: return 1561; case E_ITEM_DIAMOND_SWORD: return 1561; case E_ITEM_ELYTRA: return 432; case E_ITEM_FLINT_AND_STEEL: return 64; case E_ITEM_FISHING_ROD: return 65; case E_ITEM_GOLD_AXE: return 32; case E_ITEM_GOLD_BOOTS: return 92; case E_ITEM_GOLD_CHESTPLATE: return 113; case E_ITEM_GOLD_HELMET: return 78; case E_ITEM_GOLD_HOE: return 32; case E_ITEM_GOLD_LEGGINGS: return 106; case E_ITEM_GOLD_PICKAXE: return 32; case E_ITEM_GOLD_SHOVEL: return 32; case E_ITEM_GOLD_SWORD: return 32; case E_ITEM_IRON_AXE: return 250; case E_ITEM_IRON_BOOTS: return 196; case E_ITEM_IRON_CHESTPLATE: return 241; case E_ITEM_IRON_HELMET: return 166; case E_ITEM_IRON_HOE: return 250; case E_ITEM_IRON_LEGGINGS: return 226; case E_ITEM_IRON_PICKAXE: return 250; case E_ITEM_IRON_SHOVEL: return 250; case E_ITEM_IRON_SWORD: return 250; case E_ITEM_LEATHER_BOOTS: return 66; case E_ITEM_LEATHER_CAP: return 55; case E_ITEM_LEATHER_PANTS: return 76; case E_ITEM_LEATHER_TUNIC: return 81; case E_ITEM_SHEARS: return 250; case E_ITEM_STONE_AXE: return 131; case E_ITEM_STONE_HOE: return 131; case E_ITEM_STONE_PICKAXE: return 131; case E_ITEM_STONE_SHOVEL: return 131; case E_ITEM_STONE_SWORD: return 131; case E_ITEM_WOODEN_AXE: return 59; case E_ITEM_WOODEN_HOE: return 59; case E_ITEM_WOODEN_PICKAXE: return 59; case E_ITEM_WOODEN_SHOVEL: return 59; case E_ITEM_WOODEN_SWORD: return 59; default: return 0; } } bool cItem::DamageItem(short a_Amount) { short MaxDamage = GetMaxDamage(); if (MaxDamage == 0) { // Item doesn't have damage return false; } m_ItemDamage += a_Amount; return (m_ItemDamage > MaxDamage); } bool cItem::IsFullStack(void) const { return (m_ItemCount >= GetMaxStackSize()); } char cItem::GetMaxStackSize(void) const { return cItemHandler::For(m_ItemType).GetMaxStackSize(); } const cItemHandler & cItem::GetHandler(void) const { return cItemHandler::For(m_ItemType); } void cItem::GetJson(Json::Value & a_OutValue) const { a_OutValue["ID"] = m_ItemType; if (m_ItemType > 0) { a_OutValue["Count"] = m_ItemCount; a_OutValue["Health"] = m_ItemDamage; AString Enchantments(m_Enchantments.ToString()); if (!Enchantments.empty()) { a_OutValue["ench"] = Enchantments; } if (!IsCustomNameEmpty()) { a_OutValue["Name"] = m_CustomName; } if (!IsLoreEmpty()) { auto & LoreArray = (a_OutValue["Lore"] = Json::Value(Json::arrayValue)); for (const auto & Line : m_LoreTable) { LoreArray.append(Line); } } if (m_ItemColor.IsValid()) { a_OutValue["Color_Red"] = m_ItemColor.GetRed(); a_OutValue["Color_Green"] = m_ItemColor.GetGreen(); a_OutValue["Color_Blue"] = m_ItemColor.GetBlue(); } if ((m_ItemType == E_ITEM_FIREWORK_ROCKET) || (m_ItemType == E_ITEM_FIREWORK_STAR)) { a_OutValue["Flicker"] = m_FireworkItem.m_HasFlicker; a_OutValue["Trail"] = m_FireworkItem.m_HasTrail; a_OutValue["Type"] = m_FireworkItem.m_Type; a_OutValue["FlightTimeInTicks"] = m_FireworkItem.m_FlightTimeInTicks; a_OutValue["Colours"] = m_FireworkItem.ColoursToString(m_FireworkItem); a_OutValue["FadeColours"] = m_FireworkItem.FadeColoursToString(m_FireworkItem); } a_OutValue["RepairCost"] = m_RepairCost; } } void cItem::FromJson(const Json::Value & a_Value) { m_ItemType = static_cast(a_Value.get("ID", -1).asInt()); if (m_ItemType > 0) { m_ItemCount = static_cast(a_Value.get("Count", -1).asInt()); m_ItemDamage = static_cast(a_Value.get("Health", -1).asInt()); m_Enchantments.Clear(); m_Enchantments.AddFromString(a_Value.get("ench", "").asString()); m_CustomName = a_Value.get("Name", "").asString(); auto Lore = a_Value.get("Lore", Json::arrayValue); for (auto & Line : Lore) { m_LoreTable.push_back(Line.asString()); } int red = a_Value.get("Color_Red", -1).asInt(); int green = a_Value.get("Color_Green", -1).asInt(); int blue = a_Value.get("Color_Blue", -1).asInt(); if ((red > -1) && (red < static_cast(cColor::COLOR_LIMIT)) && (green > -1) && (green < static_cast(cColor::COLOR_LIMIT)) && (blue > -1) && (blue < static_cast(cColor::COLOR_LIMIT))) { m_ItemColor.SetColor(static_cast(red), static_cast(green), static_cast(blue)); } else if ((red != -1) || (blue != -1) || (green != -1)) { LOGWARNING("Item with invalid red, green, and blue values read in from json file."); } if ((m_ItemType == E_ITEM_FIREWORK_ROCKET) || (m_ItemType == E_ITEM_FIREWORK_STAR)) { m_FireworkItem.m_HasFlicker = a_Value.get("Flicker", false).asBool(); m_FireworkItem.m_HasTrail = a_Value.get("Trail", false).asBool(); m_FireworkItem.m_Type = static_cast(a_Value.get("Type", 0).asInt()); m_FireworkItem.m_FlightTimeInTicks = static_cast(a_Value.get("FlightTimeInTicks", 0).asInt()); m_FireworkItem.ColoursFromString(a_Value.get("Colours", "").asString(), m_FireworkItem); m_FireworkItem.FadeColoursFromString(a_Value.get("FadeColours", "").asString(), m_FireworkItem); } m_RepairCost = a_Value.get("RepairCost", 0).asInt(); } } bool cItem::IsEnchantable(short a_ItemType, bool a_FromBook) { if ( ItemCategory::IsAxe(a_ItemType) || ItemCategory::IsSword(a_ItemType) || ItemCategory::IsShovel(a_ItemType) || ItemCategory::IsPickaxe(a_ItemType) || (a_FromBook && ItemCategory::IsHoe(a_ItemType)) || ItemCategory::IsArmor(a_ItemType) ) { return true; } switch (a_ItemType) { case E_ITEM_BOOK: case E_ITEM_BOW: case E_ITEM_FISHING_ROD: { return true; } case E_ITEM_CARROT_ON_STICK: case E_ITEM_SHEARS: case E_ITEM_FLINT_AND_STEEL: { return a_FromBook; } } return false; } unsigned cItem::GetEnchantability() { switch (m_ItemType) { case E_ITEM_WOODEN_SWORD: case E_ITEM_WOODEN_PICKAXE: case E_ITEM_WOODEN_SHOVEL: case E_ITEM_WOODEN_AXE: case E_ITEM_WOODEN_HOE: return 15; case E_ITEM_LEATHER_CAP: case E_ITEM_LEATHER_TUNIC: case E_ITEM_LEATHER_PANTS: case E_ITEM_LEATHER_BOOTS: return 15; case E_ITEM_STONE_SWORD: case E_ITEM_STONE_PICKAXE: case E_ITEM_STONE_SHOVEL: case E_ITEM_STONE_AXE: case E_ITEM_STONE_HOE: return 5; case E_ITEM_IRON_HELMET: case E_ITEM_IRON_CHESTPLATE: case E_ITEM_IRON_LEGGINGS: case E_ITEM_IRON_BOOTS: return 9; case E_ITEM_IRON_SWORD: case E_ITEM_IRON_PICKAXE: case E_ITEM_IRON_SHOVEL: case E_ITEM_IRON_AXE: case E_ITEM_IRON_HOE: return 14; case E_ITEM_CHAIN_HELMET: case E_ITEM_CHAIN_CHESTPLATE: case E_ITEM_CHAIN_LEGGINGS: case E_ITEM_CHAIN_BOOTS: return 12; case E_ITEM_DIAMOND_HELMET: case E_ITEM_DIAMOND_CHESTPLATE: case E_ITEM_DIAMOND_LEGGINGS: case E_ITEM_DIAMOND_BOOTS: return 10; case E_ITEM_DIAMOND_SWORD: case E_ITEM_DIAMOND_PICKAXE: case E_ITEM_DIAMOND_SHOVEL: case E_ITEM_DIAMOND_AXE: case E_ITEM_DIAMOND_HOE: return 10; case E_ITEM_GOLD_HELMET: case E_ITEM_GOLD_CHESTPLATE: case E_ITEM_GOLD_LEGGINGS: case E_ITEM_GOLD_BOOTS: return 25; case E_ITEM_GOLD_SWORD: case E_ITEM_GOLD_PICKAXE: case E_ITEM_GOLD_SHOVEL: case E_ITEM_GOLD_AXE: case E_ITEM_GOLD_HOE: return 22; case E_ITEM_FISHING_ROD: case E_ITEM_BOW: case E_ITEM_BOOK: return 1; } return 0; } bool cItem::EnchantByXPLevels(unsigned a_NumXPLevels, MTRand & a_Random) { if (!cItem::IsEnchantable(m_ItemType)) { return false; } const auto Enchantability = GetEnchantability(); if (Enchantability == 0) { return false; } const auto ModifiedEnchantmentLevel = a_NumXPLevels + a_Random.RandInt(Enchantability / 4) + a_Random.RandInt(Enchantability / 4) + 1; const auto RandomBonus = 1.0F + (a_Random.RandReal() + a_Random.RandReal() - 1.0F) * 0.15F; const auto FinalEnchantmentLevel = static_cast(ModifiedEnchantmentLevel * RandomBonus + 0.5F); cWeightedEnchantments Enchantments; cEnchantments::AddItemEnchantmentWeights(Enchantments, m_ItemType, FinalEnchantmentLevel); if (m_ItemType == E_ITEM_BOOK) { m_ItemType = E_ITEM_ENCHANTED_BOOK; } cEnchantments Enchantment1 = cEnchantments::GetRandomEnchantmentFromVector(Enchantments, a_Random); m_Enchantments.AddFromString(Enchantment1.ToString()); cEnchantments::RemoveEnchantmentWeightFromVector(Enchantments, Enchantment1); // Checking for conflicting enchantments cEnchantments::CheckEnchantmentConflictsFromVector(Enchantments, Enchantment1); // Next Enchantment (Second) float NewEnchantmentLevel = a_NumXPLevels / 2.0f; float SecondEnchantmentChance = (NewEnchantmentLevel + 1) / 50.0f; if (Enchantments.empty() || !a_Random.RandBool(SecondEnchantmentChance)) { return true; } cEnchantments Enchantment2 = cEnchantments::GetRandomEnchantmentFromVector(Enchantments, a_Random); m_Enchantments.AddFromString(Enchantment2.ToString()); cEnchantments::RemoveEnchantmentWeightFromVector(Enchantments, Enchantment2); // Checking for conflicting enchantments cEnchantments::CheckEnchantmentConflictsFromVector(Enchantments, Enchantment2); // Next Enchantment (Third) NewEnchantmentLevel = NewEnchantmentLevel / 2.0f; float ThirdEnchantmentChance = (NewEnchantmentLevel + 1) / 50.0f; if (Enchantments.empty() || !a_Random.RandBool(ThirdEnchantmentChance)) { return true; } cEnchantments Enchantment3 = cEnchantments::GetRandomEnchantmentFromVector(Enchantments, a_Random); m_Enchantments.AddFromString(Enchantment3.ToString()); cEnchantments::RemoveEnchantmentWeightFromVector(Enchantments, Enchantment3); // Checking for conflicting enchantments cEnchantments::CheckEnchantmentConflictsFromVector(Enchantments, Enchantment3); // Next Enchantment (Fourth) NewEnchantmentLevel = NewEnchantmentLevel / 2.0f; float FourthEnchantmentChance = (NewEnchantmentLevel + 1) / 50.0f; if (Enchantments.empty() || !a_Random.RandBool(FourthEnchantmentChance)) { return true; } cEnchantments Enchantment4 = cEnchantments::GetRandomEnchantmentFromVector(Enchantments, a_Random); m_Enchantments.AddFromString(Enchantment4.ToString()); return true; } int cItem::AddEnchantment(int a_EnchantmentID, unsigned int a_Level, bool a_FromBook) { unsigned int OurLevel = m_Enchantments.GetLevel(a_EnchantmentID); int Multiplier = cEnchantments::GetXPCostMultiplier(a_EnchantmentID, a_FromBook); unsigned int NewLevel = 0; if (OurLevel > a_Level) { // They don't add anything to us NewLevel = OurLevel; } else if (OurLevel == a_Level) { // Bump it by 1 NewLevel = OurLevel + 1; } else { // Take the sacrifice's level NewLevel = a_Level; } unsigned int LevelCap = cEnchantments::GetLevelCap(a_EnchantmentID); if (NewLevel > LevelCap) { NewLevel = LevelCap; } m_Enchantments.SetLevel(a_EnchantmentID, NewLevel); return static_cast(NewLevel) * Multiplier; } bool cItem::CanHaveEnchantment(int a_EnchantmentID) { if (m_ItemType == E_ITEM_ENCHANTED_BOOK) { // Enchanted books can take anything return true; } // The organization here is based on the summary at: // https://minecraft.wiki/w/Enchanting // as of July 2017 (Minecraft 1.12). // Hand tool enchantments static const std::set SwordEnchantments = { cEnchantments::enchBaneOfArthropods, cEnchantments::enchFireAspect, cEnchantments::enchKnockback, cEnchantments::enchLooting, cEnchantments::enchSharpness, cEnchantments::enchSmite, cEnchantments::enchUnbreaking }; static const std::set AxeEnchantments = { cEnchantments::enchBaneOfArthropods, cEnchantments::enchEfficiency, cEnchantments::enchFortune, cEnchantments::enchSharpness, cEnchantments::enchSilkTouch, cEnchantments::enchSmite, cEnchantments::enchUnbreaking }; static const std::set ToolEnchantments = { cEnchantments::enchEfficiency, cEnchantments::enchFortune, cEnchantments::enchSilkTouch, cEnchantments::enchUnbreaking }; static const std::set ShearEnchantments = { cEnchantments::enchEfficiency, cEnchantments::enchUnbreaking }; static const std::set BowEnchantments = { cEnchantments::enchFlame, cEnchantments::enchInfinity, cEnchantments::enchPower, cEnchantments::enchPunch }; static const std::set FishingEnchantments = { cEnchantments::enchLuckOfTheSea, cEnchantments::enchLure }; static const std::set MiscEnchantments = { cEnchantments::enchUnbreaking }; if (ItemCategory::IsSword(m_ItemType)) { return SwordEnchantments.count(a_EnchantmentID) > 0; } if (ItemCategory::IsAxe(m_ItemType)) { return AxeEnchantments.count(a_EnchantmentID) > 0; } if (ItemCategory::IsPickaxe(m_ItemType) || ItemCategory::IsShovel(m_ItemType)) { return ToolEnchantments.count(a_EnchantmentID) > 0; } if (m_ItemType == E_ITEM_SHEARS) { return ShearEnchantments.count(a_EnchantmentID) > 0; } if (m_ItemType == E_ITEM_BOW) { return BowEnchantments.count(a_EnchantmentID) > 0; } if (m_ItemType == E_ITEM_FISHING_ROD) { return FishingEnchantments.count(a_EnchantmentID) > 0; } if (ItemCategory::IsHoe(m_ItemType) || (m_ItemType == E_ITEM_FLINT_AND_STEEL) || (m_ItemType == E_ITEM_CARROT_ON_STICK) || (m_ItemType == E_ITEM_SHIELD)) { return MiscEnchantments.count(a_EnchantmentID) > 0; } // Armor enchantments static const std::set ArmorEnchantments = { cEnchantments::enchBlastProtection, cEnchantments::enchFireProtection, cEnchantments::enchProjectileProtection, cEnchantments::enchProtection, cEnchantments::enchThorns, cEnchantments::enchUnbreaking }; static const std::set HatOnlyEnchantments = { cEnchantments::enchAquaAffinity, cEnchantments::enchRespiration }; static const std::set BootOnlyEnchantments = { cEnchantments::enchDepthStrider, cEnchantments::enchFeatherFalling }; if (ItemCategory::IsBoots(m_ItemType)) { return (BootOnlyEnchantments.count(a_EnchantmentID) > 0) || (ArmorEnchantments.count(a_EnchantmentID) > 0); } if (ItemCategory::IsHelmet(m_ItemType)) { return (HatOnlyEnchantments.count(a_EnchantmentID) > 0) || (ArmorEnchantments.count(a_EnchantmentID) > 0); } if (ItemCategory::IsArmor(m_ItemType)) { return ArmorEnchantments.count(a_EnchantmentID) > 0; } return false; } int cItem::AddEnchantmentsFromItem(const cItem & a_Other) { bool FromBook = (a_Other.m_ItemType == E_ITEM_ENCHANTED_BOOK); // Consider each enchantment seperately int EnchantingCost = 0; for (auto & Enchantment : a_Other.m_Enchantments) { if (CanHaveEnchantment(Enchantment.first)) { if (!m_Enchantments.CanAddEnchantment(Enchantment.first)) { // Cost of incompatible enchantments EnchantingCost += 1; } else { EnchantingCost += AddEnchantment(Enchantment.first, Enchantment.second, FromBook); } } } return EnchantingCost; } //////////////////////////////////////////////////////////////////////////////// // cItems: cItems::cItems(cItem && a_InitialItem) { push_back(std::move(a_InitialItem)); } cItem * cItems::Get(int a_Idx) { if ((a_Idx < 0) || (a_Idx >= static_cast(size()))) { LOGWARNING("cItems: Attempt to get an out-of-bounds item at index %d; there are currently %zu items. Returning a nil.", a_Idx, size()); return nullptr; } return &at(static_cast(a_Idx)); } void cItems::Set(int a_Idx, const cItem & a_Item) { if ((a_Idx < 0) || (a_Idx >= static_cast(size()))) { LOGWARNING("cItems: Attempt to set an item at an out-of-bounds index %d; there are currently %zu items. Not setting.", a_Idx, size()); return; } at(static_cast(a_Idx)) = a_Item; } void cItems::Delete(int a_Idx) { if ((a_Idx < 0) || (a_Idx >= static_cast(size()))) { LOGWARNING("cItems: Attempt to delete an item at an out-of-bounds index %d; there are currently %zu items. Ignoring.", a_Idx, size()); return; } erase(begin() + a_Idx); } void cItems::Set(int a_Idx, short a_ItemType, char a_ItemCount, short a_ItemDamage) { if ((a_Idx < 0) || (a_Idx >= static_cast(size()))) { LOGWARNING("cItems: Attempt to set an item at an out-of-bounds index %d; there are currently %zu items. Not setting.", a_Idx, size()); return; } at(static_cast(a_Idx)) = cItem(a_ItemType, a_ItemCount, a_ItemDamage); } bool cItems::Contains(const cItem & a_Item) { for (const auto & itr : *this) { if (a_Item.IsEqual(itr)) { return true; } } return false; } bool cItems::ContainsType(const cItem & a_Item) { for (const auto & itr : *this) { if (a_Item.IsSameType(itr)) { return true; } } return false; } void cItems::AddItemGrid(const cItemGrid & a_ItemGrid) { for (int i = 0; i < a_ItemGrid.GetNumSlots(); ++i) { const auto & Slot = a_ItemGrid.GetSlot(i); if (!Slot.IsEmpty()) { Add(Slot); } } } ================================================ FILE: src/Item.h ================================================ // Item.h // Declares the cItem class representing an item (in the inventory sense) #pragma once #include "Defines.h" #include "Enchantments.h" #include "WorldStorage/FireworksSerializer.h" #include "Color.h" // fwd: class cItemHandler; class cItemGrid; class cColor; namespace Json { class Value; } // tolua_begin class cItem { public: /** Creates an empty item */ cItem(void); /** Creates an item of the specified type, by default 1 piece with no damage and no enchantments */ cItem( short a_ItemType, char a_ItemCount = 1, short a_ItemDamage = 0, const AString & a_Enchantments = "", const AString & a_CustomName = "", const AStringVector & a_LoreTable = {} ); // The constructor is disabled in code, because the compiler generates it anyway, // but it needs to stay because ToLua needs to generate the binding for it #ifdef TOLUA_EXPOSITION /** Creates an exact copy of the item */ cItem(const cItem & a_CopyFrom); #endif /** Empties the item and frees up any dynamic storage used by the internals. */ void Empty(void); /** Empties the item and frees up any dynamic storage used by the internals. TODO: What is the usage difference? Merge with Empty()? */ void Clear(void); /** Returns true if the item represents an empty stack - either the type is invalid, or count is zero. */ bool IsEmpty(void) const { return ((m_ItemType <= 0) || (m_ItemCount <= 0)); } /* Returns true if this itemstack can stack with the specified stack (types match, enchantments etc.) ItemCounts are ignored. */ bool IsEqual(const cItem & a_Item) const { return ( IsSameType(a_Item) && (m_ItemDamage == a_Item.m_ItemDamage) && (m_Enchantments == a_Item.m_Enchantments) && (m_CustomName == a_Item.m_CustomName) && (m_LoreTable == a_Item.m_LoreTable) && m_FireworkItem.IsEqualTo(a_Item.m_FireworkItem) ); } bool IsSameType(const cItem & a_Item) const { return (m_ItemType == a_Item.m_ItemType) || (IsEmpty() && a_Item.IsEmpty()); } bool IsBothNameAndLoreEmpty(void) const { return (m_CustomName.empty() && m_LoreTable.empty()); } bool IsCustomNameEmpty(void) const { return (m_CustomName.empty()); } bool IsLoreEmpty(void) const { return (m_LoreTable.empty()); } /** Returns a copy of this item with m_ItemCount set to 1. Useful to preserve enchantments etc. on stacked items */ cItem CopyOne(void) const; /** Adds the specified count to this object and returns the reference to self (useful for chaining) */ cItem & AddCount(char a_AmountToAdd); /** Returns the maximum damage value that this item can have; zero if damage is not applied */ short GetMaxDamage(void) const; /** Damages a weapon / tool. Returns true when damage reaches max value and the item should be destroyed */ bool DamageItem(short a_Amount = 1); inline bool IsDamageable(void) const { return (GetMaxDamage() > 0); } /** Returns true if the item is stacked up to its maximum stacking. */ bool IsFullStack(void) const; /** Returns the maximum amount of stacked items of this type. */ char GetMaxStackSize(void) const; // tolua_end /** Returns the cItemHandler responsible for this item type */ const cItemHandler & GetHandler(void) const; /** Saves the item data into JSON representation */ void GetJson(Json::Value & a_OutValue) const; /** Loads the item data from JSON representation */ void FromJson(const Json::Value & a_Value); /** Returns true if the specified item type is enchantable. If FromBook is true, the function is used in the anvil inventory with book enchantments. So it checks the "only book enchantments" too. Example: You can only enchant a hoe with a book. */ static bool IsEnchantable(short a_ItemType, bool a_FromBook = false); // tolua_export /** Returns the enchantability of the item. When the item hasn't a enchantability, it will returns 0 */ unsigned GetEnchantability(); // tolua_export /** Randomly enchants the item using the specified number of XP levels. Returns true if the item was enchanted, false if not (not enchantable / too many enchantments already). Randomness is derived from the provided PRNG. */ bool EnchantByXPLevels(unsigned a_NumXPLevels, MTRand & a_Random); // Exported in ManualBindings.cpp /** Adds this specific enchantment to this item, returning the cost. FromBook specifies whether the enchantment should be treated as coming from a book. If true, then the cost returned uses the book values, if false it uses the normal item multipliers. */ int AddEnchantment(int a_EnchantmentID, unsigned int a_Level, bool a_FromBook); // tolua_export /** Adds the enchantments on a_Other to this item, returning the XP cost of the transfer. */ int AddEnchantmentsFromItem(const cItem & a_Other); // tolua_export /** Returns whether or not this item is allowed to have the given enchantment. Note: Does not check whether the enchantment is exclusive with the current enchantments on the item. */ bool CanHaveEnchantment(int a_EnchantmentID); // tolua_begin short m_ItemType; char m_ItemCount; short m_ItemDamage; cEnchantments m_Enchantments; AString m_CustomName; // tolua_end AStringVector m_LoreTable; // Exported in ManualBindings.cpp /** Compares two items for the same type or category. Type of item is defined via `m_ItemType` and `m_ItemDamage`. Some items (e.g. planks) have the same `m_ItemType` and the wood kind is defined via `m_ItemDamage`. `-1` is used as placeholder for all kinds (e.g. all kind of planks). Items are different when the `ItemType` is different or the `ItemDamage` is different and unequal -1. */ struct sItemCompare { bool operator() (const cItem & a_Lhs, const cItem & a_Rhs) const { if (a_Lhs.m_ItemType != a_Rhs.m_ItemType) { return (a_Lhs.m_ItemType < a_Rhs.m_ItemType); } if ((a_Lhs.m_ItemDamage == -1) || (a_Rhs.m_ItemDamage == -1)) { return false; // -1 is a wildcard, damage of -1 alway compares equal } return (a_Lhs.m_ItemDamage < a_Rhs.m_ItemDamage); } }; // tolua_begin int m_RepairCost; cFireworkItem m_FireworkItem; cColor m_ItemColor; }; // tolua_end /** This class bridges a vector of cItem for safe access via Lua. It checks boundaries for all accesses Note that this class is zero-indexed! */ class cItems // tolua_export : public std::vector { // tolua_export public: cItems(const cItems &) = default; cItems(cItems &&) = default; cItems & operator = (const cItems &) = default; cItems & operator = (cItems &&) = default; /** Constructs a new instance containing the specified item. */ cItems(cItem && a_InitialItem); // tolua_begin /** Need a Lua-accessible constructor */ cItems(void) {} cItem * Get (int a_Idx); void Set (int a_Idx, const cItem & a_Item); void Add (const cItem & a_Item) {push_back(a_Item); } void Add (short a_ItemType) { emplace_back(a_ItemType); } void Add (short a_ItemType, char a_ItemCount) { emplace_back(a_ItemType, a_ItemCount); } void Delete(int a_Idx); void Clear (void) {clear(); } size_t Size (void) const { return size(); } void Set (int a_Idx, short a_ItemType, char a_ItemCount, short a_ItemDamage); bool Contains(const cItem & a_Item); bool ContainsType(const cItem & a_Item); void Add (short a_ItemType, char a_ItemCount, short a_ItemDamage) { emplace_back(a_ItemType, a_ItemCount, a_ItemDamage); } /** Adds a copy of all items in a_ItemGrid. */ void AddItemGrid(const cItemGrid & a_ItemGrid); // tolua_end } ; // tolua_export /** Used to store loot probability tables */ class cLootProbab { public: cItem m_Item; int m_MinAmount; int m_MaxAmount; int m_Weight; } ; ================================================ FILE: src/ItemGrid.cpp ================================================ // ItemGrid.cpp // Implements the cItemGrid class representing a storage for items in a XY grid (chests, dispensers, inventory etc.) #include "Globals.h" #include "ItemGrid.h" #include "Items/ItemHandler.h" #include "Noise/Noise.h" cItemGrid::cItemGrid(int a_Width, int a_Height): m_Width(a_Width), m_Height(a_Height), m_Slots(a_Width * a_Height), m_IsInTriggerListeners(false) { } bool cItemGrid::IsValidSlotNum(int a_SlotNum) const { return ((a_SlotNum >= 0) && (a_SlotNum < m_Slots.size())); } bool cItemGrid::IsValidSlotCoords(int a_X, int a_Y) const { return ( (a_X >= 0) && (a_X < m_Width) && (a_Y >= 0) && (a_Y < m_Height) ); } int cItemGrid::GetSlotNum(int a_X, int a_Y) const { if (!IsValidSlotCoords(a_X, a_Y)) { LOGWARNING("%s: coords out of range: (%d, %d) in grid of size (%d, %d)", __FUNCTION__, a_X, a_Y, m_Width, m_Height ); return -1; } return a_X + m_Width * a_Y; } void cItemGrid::GetSlotCoords(int a_SlotNum, int & a_X, int & a_Y) const { if (!IsValidSlotNum(a_SlotNum)) { LOGWARNING("%s: SlotNum out of range: %d in grid of range %d", __FUNCTION__, a_SlotNum, m_Slots.size() ); a_X = -1; a_Y = -1; return; } a_X = a_SlotNum % m_Width; a_Y = a_SlotNum / m_Width; } void cItemGrid::CopyFrom(const cItemGrid & a_Src) { m_Width = a_Src.m_Width; m_Height = a_Src.m_Height; m_Slots = a_Src.m_Slots; // The listeners are not copied } const cItem & cItemGrid::GetSlot(int a_X, int a_Y) const { return GetSlot(GetSlotNum(a_X, a_Y)); } const cItem & cItemGrid::GetSlot(int a_SlotNum) const { if (!IsValidSlotNum(a_SlotNum)) { LOGWARNING("%s: Invalid slot number, %d out of %d slots", __FUNCTION__, a_SlotNum, m_Slots.size() ); a_SlotNum = 0; } return m_Slots.GetAt(a_SlotNum); } void cItemGrid::SetSlot(int a_X, int a_Y, const cItem & a_Item) { SetSlot(GetSlotNum(a_X, a_Y), a_Item); } void cItemGrid::SetSlot(int a_X, int a_Y, short a_ItemType, char a_ItemCount, short a_ItemDamage) { SetSlot(GetSlotNum(a_X, a_Y), cItem(a_ItemType, a_ItemCount, a_ItemDamage)); } void cItemGrid::SetSlot(int a_SlotNum, const cItem & a_Item) { if (!IsValidSlotNum(a_SlotNum)) { LOGWARNING("%s: Invalid slot number %d out of %d slots", __FUNCTION__, a_SlotNum, m_Slots.size() ); return; } if (!a_Item.IsEmpty() || m_Slots.IsStorageAllocated()) { m_Slots[a_SlotNum] = a_Item; } TriggerListeners(a_SlotNum); } void cItemGrid::SetSlot(int a_SlotNum, short a_ItemType, char a_ItemCount, short a_ItemDamage) { SetSlot(a_SlotNum, cItem(a_ItemType, a_ItemCount, a_ItemDamage)); } void cItemGrid::EmptySlot(int a_X, int a_Y) { EmptySlot(GetSlotNum(a_X, a_Y)); } void cItemGrid::EmptySlot(int a_SlotNum) { if (!IsValidSlotNum(a_SlotNum)) { LOGWARNING("%s: Invalid slot number %d out of %d slots", __FUNCTION__, a_SlotNum, m_Slots.size() ); return; } // Check if already empty: if (m_Slots.GetAt(a_SlotNum).IsEmpty()) { return; } // Empty and notify m_Slots[a_SlotNum].Empty(); TriggerListeners(a_SlotNum); } bool cItemGrid::IsSlotEmpty(int a_SlotNum) const { if (!IsValidSlotNum(a_SlotNum)) { LOGWARNING("%s: Invalid slot number %d out of %d slots", __FUNCTION__, a_SlotNum, m_Slots.size() ); return true; } return m_Slots.GetAt(a_SlotNum).IsEmpty(); } bool cItemGrid::IsSlotEmpty(int a_X, int a_Y) const { return IsSlotEmpty(GetSlotNum(a_X, a_Y)); } void cItemGrid::Clear(void) { if (!m_Slots.IsStorageAllocated()) { return; // Already clear } for (int i = 0; i < m_Slots.size(); i++) { m_Slots[i].Empty(); TriggerListeners(i); } } int cItemGrid::HowManyCanFit(const cItem & a_ItemStack, bool a_AllowNewStacks) { int NumLeft = a_ItemStack.m_ItemCount; int MaxStack = a_ItemStack.GetMaxStackSize(); if (!m_Slots.IsStorageAllocated()) { // Grid is empty, all slots are available return a_AllowNewStacks ? std::min(NumLeft, m_Slots.size() * MaxStack) : 0; } for (const auto & Slot : m_Slots) { if (Slot.IsEmpty()) { if (a_AllowNewStacks) { NumLeft -= MaxStack; } } else if (Slot.IsEqual(a_ItemStack)) { NumLeft -= MaxStack - Slot.m_ItemCount; } if (NumLeft <= 0) { // All items fit return a_ItemStack.m_ItemCount; } } // for Slot - m_Slots[] return a_ItemStack.m_ItemCount - NumLeft; } char cItemGrid::AddItemToSlot(const cItem & a_ItemStack, int a_Slot, int a_Num, int a_MaxStack) { if (!IsValidSlotNum(a_Slot)) { LOGWARNING("%s: Invalid slot number %d out of %d slots", __FUNCTION__, a_Slot, m_Slots.size() ); return 0; } char PrevCount = 0; if (m_Slots[a_Slot].IsEmpty()) { m_Slots[a_Slot] = a_ItemStack; PrevCount = 0; } else { PrevCount = m_Slots[a_Slot].m_ItemCount; } m_Slots[a_Slot].m_ItemCount = static_cast(std::min(a_MaxStack, PrevCount + a_Num)); char toReturn = m_Slots[a_Slot].m_ItemCount - PrevCount; TriggerListeners(a_Slot); return toReturn; } char cItemGrid::AddItem(cItem & a_ItemStack, bool a_AllowNewStacks, int a_PrioritySlot) { char NumLeft = a_ItemStack.m_ItemCount; char MaxStack = a_ItemStack.GetMaxStackSize(); if ((a_PrioritySlot != -1) && !IsValidSlotNum(a_PrioritySlot)) { LOGWARNING("%s: Invalid slot number %d out of %d slots", __FUNCTION__, a_PrioritySlot, m_Slots.size() ); a_PrioritySlot = -1; } if (!a_AllowNewStacks && !m_Slots.IsStorageAllocated()) { return 0; // No existing stacks to add to } // Try prioritySlot first: if ( (a_PrioritySlot != -1) && ( m_Slots[a_PrioritySlot].IsEmpty() || m_Slots[a_PrioritySlot].IsEqual(a_ItemStack) ) ) { NumLeft -= AddItemToSlot(a_ItemStack, a_PrioritySlot, NumLeft, MaxStack); } // Scan existing stacks: for (int i = 0; i < m_Slots.size(); i++) { if (m_Slots[i].IsEqual(a_ItemStack)) { NumLeft -= AddItemToSlot(a_ItemStack, i, NumLeft, MaxStack); } if (NumLeft <= 0) { // All items fit return a_ItemStack.m_ItemCount; } } // for i - m_Slots[] if (!a_AllowNewStacks) { return (a_ItemStack.m_ItemCount - NumLeft); } for (int i = 0; i < m_Slots.size(); i++) { if (m_Slots[i].IsEmpty()) { NumLeft -= AddItemToSlot(a_ItemStack, i, NumLeft, MaxStack); } if (NumLeft <= 0) { // All items fit return a_ItemStack.m_ItemCount; } } // for i - m_Slots[] return (a_ItemStack.m_ItemCount - NumLeft); } char cItemGrid::AddItems(cItems & a_ItemStackList, bool a_AllowNewStacks, int a_PrioritySlot) { char TotalAdded = 0; for (cItems::iterator itr = a_ItemStackList.begin(); itr != a_ItemStackList.end();) { char NumAdded = AddItem(*itr, a_AllowNewStacks, a_PrioritySlot); if (itr->m_ItemCount == NumAdded) { itr = a_ItemStackList.erase(itr); } else { itr->m_ItemCount -= NumAdded; ++itr; } TotalAdded += NumAdded; } return TotalAdded; } char cItemGrid::RemoveItem(const cItem & a_ItemStack) { char NumLeft = a_ItemStack.m_ItemCount; if (!m_Slots.IsStorageAllocated()) { return 0; // No items to remove } for (int i = 0; i < m_Slots.size(); i++) { if (NumLeft <= 0) { break; } if (m_Slots[i].IsEqual(a_ItemStack)) { char NumToRemove = std::min(NumLeft, m_Slots[i].m_ItemCount); NumLeft -= NumToRemove; m_Slots[i].m_ItemCount -= NumToRemove; if (m_Slots[i].m_ItemCount <= 0) { m_Slots[i].Empty(); } TriggerListeners(i); } } return (a_ItemStack.m_ItemCount - NumLeft); } cItem * cItemGrid::FindItem(const cItem & a_RecipeItem) { if (!m_Slots.IsStorageAllocated()) { return nullptr; } for (int i = 0; i < m_Slots.size(); i++) { // Items are equal if none is greater the other auto compare = cItem::sItemCompare{}; if (!compare(a_RecipeItem, m_Slots[i]) && !compare(m_Slots[i], a_RecipeItem)) { return &m_Slots[i]; } } return nullptr; } char cItemGrid::ChangeSlotCount(int a_SlotNum, char a_AddToCount) { if (!IsValidSlotNum(a_SlotNum)) { LOGWARNING("%s: Invalid slot number %d out of %d slots, ignoring the call, returning -1", __FUNCTION__, a_SlotNum, m_Slots.size() ); return -1; } if (m_Slots.GetAt(a_SlotNum).IsEmpty()) { // The item is empty, it's not gonna change return 0; } if (m_Slots[a_SlotNum].m_ItemCount <= -a_AddToCount) { // Trying to remove more items than there already are, make the item empty m_Slots[a_SlotNum].Empty(); TriggerListeners(a_SlotNum); return 0; } m_Slots[a_SlotNum].m_ItemCount += a_AddToCount; if (m_Slots[a_SlotNum].m_ItemCount > m_Slots[a_SlotNum].GetMaxStackSize()) { m_Slots[a_SlotNum].m_ItemCount = m_Slots[a_SlotNum].GetMaxStackSize(); } TriggerListeners(a_SlotNum); return m_Slots[a_SlotNum].m_ItemCount; } char cItemGrid::ChangeSlotCount(int a_X, int a_Y, char a_AddToCount) { return ChangeSlotCount(GetSlotNum(a_X, a_Y), a_AddToCount); } cItem cItemGrid::RemoveOneItem(int a_SlotNum) { if (!IsValidSlotNum(a_SlotNum)) { LOGWARNING("%s: Invalid slot number %d out of %d slots, ignoring the call, returning empty item", __FUNCTION__, a_SlotNum, m_Slots.size() ); return cItem(); } // If the slot is empty, return an empty item if (m_Slots.GetAt(a_SlotNum).IsEmpty()) { return cItem(); } // Make a copy of the item in slot, set count to 1 and remove one from the slot cItem res = m_Slots[a_SlotNum]; res.m_ItemCount = 1; m_Slots[a_SlotNum].m_ItemCount -= 1; // Emptying the slot correctly if appropriate if (m_Slots[a_SlotNum].m_ItemCount == 0) { m_Slots[a_SlotNum].Empty(); } // Notify everyone of the change TriggerListeners(a_SlotNum); // Return the stored one item return res; } cItem cItemGrid::RemoveOneItem(int a_X, int a_Y) { return RemoveOneItem(GetSlotNum(a_X, a_Y)); } int cItemGrid::HowManyItems(const cItem & a_Item) { if (!m_Slots.IsStorageAllocated()) { return 0; } int res = 0; for (auto & Slot : m_Slots) { if (Slot.IsEqual(a_Item)) { res += Slot.m_ItemCount; } } return res; } bool cItemGrid::HasItems(const cItem & a_ItemStack) { int CurrentlyHave = HowManyItems(a_ItemStack); return (CurrentlyHave >= a_ItemStack.m_ItemCount); } int cItemGrid::GetFirstEmptySlot(void) const { return GetNextEmptySlot(-1); } int cItemGrid::GetFirstUsedSlot(void) const { return GetNextUsedSlot(-1); } int cItemGrid::GetLastEmptySlot(void) const { for (int i = m_Slots.size() - 1; i >= 0; i--) { if (m_Slots.GetAt(i).IsEmpty()) { return i; } } return -1; } int cItemGrid::GetLastUsedSlot(void) const { if (!m_Slots.IsStorageAllocated()) { return -1; // No slots are used } for (int i = m_Slots.size() - 1; i >= 0; i--) { if (!m_Slots.GetAt(i).IsEmpty()) { return i; } } return -1; } int cItemGrid::GetNextEmptySlot(int a_StartFrom) const { if ((a_StartFrom != -1) && !IsValidSlotNum(a_StartFrom)) { LOGWARNING("%s: Invalid slot number %d out of %d slots", __FUNCTION__, a_StartFrom, m_Slots.size() ); a_StartFrom = -1; } for (int i = a_StartFrom + 1; i < m_Slots.size(); i++) { if (m_Slots.GetAt(i).IsEmpty()) { return i; } } return -1; } int cItemGrid::GetNextUsedSlot(int a_StartFrom) const { if ((a_StartFrom != -1) && !IsValidSlotNum(a_StartFrom)) { LOGWARNING("%s: Invalid slot number %d out of %d slots", __FUNCTION__, a_StartFrom, m_Slots.size() ); a_StartFrom = -1; } if (!m_Slots.IsStorageAllocated()) { return -1; // No slots are used } for (int i = a_StartFrom + 1; i < m_Slots.size(); i++) { if (!m_Slots.GetAt(i).IsEmpty()) { return i; } } return -1; } void cItemGrid::CopyToItems(cItems & a_Items) const { if (!m_Slots.IsStorageAllocated()) { return; // Nothing to copy } for (const auto & Slot : m_Slots) { if (!Slot.IsEmpty()) { a_Items.push_back(Slot); } } // for Slot - m_Slots[] } bool cItemGrid::DamageItem(int a_SlotNum, short a_Amount) { if (!IsValidSlotNum(a_SlotNum)) { LOGWARNING("%s: invalid slot number %d out of %d slots, ignoring.", __FUNCTION__, a_SlotNum, m_Slots.size()); return false; } if (!m_Slots.IsStorageAllocated()) { return false; // Nothing to damage } return m_Slots[a_SlotNum].DamageItem(a_Amount); } bool cItemGrid::DamageItem(int a_X, int a_Y, short a_Amount) { return DamageItem(GetSlotNum(a_X, a_Y), a_Amount); } void cItemGrid::GenerateRandomLootWithBooks(const cLootProbab * a_LootProbabs, size_t a_CountLootProbabs, int a_NumSlots, int a_Seed) { // Calculate the total weight: int TotalProbab = 1; for (size_t i = 0; i < a_CountLootProbabs; i++) { TotalProbab += a_LootProbabs[i].m_Weight; } // Pick the loot items: cNoise Noise(a_Seed); for (int i = 0; i < a_NumSlots; i++) { int Rnd = (Noise.IntNoise1DInt(i) / 7); int LootRnd = Rnd % TotalProbab; Rnd >>= 8; cItem CurrentLoot = cItem(E_ITEM_ENCHANTED_BOOK, 1, 0); // Choose the enchantments cWeightedEnchantments Enchantments; cEnchantments::AddItemEnchantmentWeights(Enchantments, E_ITEM_BOOK, static_cast(24 + Noise.IntNoise2DInt(a_Seed, TotalProbab) % 7)); int NumEnchantments = Noise.IntNoise3DInt(TotalProbab, Rnd, a_Seed) % 5; // The number of enchantments this book wil get. for (int j = 0; j <= NumEnchantments; j++) { cEnchantments Enchantment = cEnchantments::SelectEnchantmentFromVector(Enchantments, Noise.IntNoise2DInt(NumEnchantments, i)); CurrentLoot.m_Enchantments.Add(Enchantment); cEnchantments::RemoveEnchantmentWeightFromVector(Enchantments, Enchantment); cEnchantments::CheckEnchantmentConflictsFromVector(Enchantments, Enchantment); } for (size_t j = 0; j < a_CountLootProbabs; j++) { LootRnd -= a_LootProbabs[j].m_Weight; if (LootRnd < 0) { CurrentLoot = a_LootProbabs[j].m_Item; if ((a_LootProbabs[j].m_MaxAmount - a_LootProbabs[j].m_MinAmount) > 0) { CurrentLoot.m_ItemCount = static_cast(a_LootProbabs[j].m_MinAmount + (Rnd % (a_LootProbabs[j].m_MaxAmount - a_LootProbabs[j].m_MinAmount))); } else { CurrentLoot.m_ItemCount = static_cast(a_LootProbabs[j].m_MinAmount); } Rnd >>= 8; break; } } // for j - a_LootProbabs[] SetSlot(Rnd % m_Slots.size(), CurrentLoot); } // for i - NumSlots } void cItemGrid::AddListener(cListener & a_Listener) { cCSLock Lock(m_CSListeners); ASSERT(!m_IsInTriggerListeners); // Must not call this while in TriggerListeners() m_Listeners.push_back(&a_Listener); } void cItemGrid::RemoveListener(cListener & a_Listener) { cCSLock Lock(m_CSListeners); ASSERT(!m_IsInTriggerListeners); // Must not call this while in TriggerListeners() for (cListeners::iterator itr = m_Listeners.begin(), end = m_Listeners.end(); itr != end; ++itr) { if (*itr == &a_Listener) { m_Listeners.erase(itr); return; } } // for itr - m_Listeners[] } void cItemGrid::TriggerListeners(int a_SlotNum) { cListeners Listeners; { cCSLock Lock(m_CSListeners); m_IsInTriggerListeners = true; Listeners = m_Listeners; } for (cListeners::iterator itr = Listeners.begin(), end = Listeners.end(); itr != end; ++itr) { (*itr)->OnSlotChanged(this, a_SlotNum); } // for itr - m_Listeners[] m_IsInTriggerListeners = false; } ================================================ FILE: src/ItemGrid.h ================================================ // ItemGrid.h // Declares the cItemGrid class representing a storage for items in a XY grid (chests, dispensers, inventory etc.) #pragma once #include "Item.h" #include "LazyArray.h" // tolua_begin class cItemGrid { public: // tolua_end /** This class is used as a callback for when a slot changes */ class cListener { public: virtual ~cListener() {} /** Called whenever a slot changes */ virtual void OnSlotChanged(cItemGrid * a_ItemGrid, int a_SlotNum) = 0; } ; typedef std::vector cListeners; cItemGrid(int a_Width, int a_Height); // tolua_begin int GetWidth (void) const { return m_Width; } int GetHeight (void) const { return m_Height; } int GetNumSlots(void) const { return m_Slots.size(); } /** Converts XY coords into slot number; returns -1 on invalid coords */ int GetSlotNum(int a_X, int a_Y) const; // tolua_end /** Converts slot number into XY coords; sets coords to -1 on invalid slot number. Exported in ManualBindings.cpp */ void GetSlotCoords(int a_SlotNum, int & a_X, int & a_Y) const; /** Copies all items from a_Src to this grid. Doesn't copy the listeners. */ void CopyFrom(const cItemGrid & a_Src); // tolua_begin // Retrieve slots by coords or slot number; Logs warning and returns the first slot on invalid coords / slotnum const cItem & GetSlot(int a_X, int a_Y) const; const cItem & GetSlot(int a_SlotNum) const; // Set slot by coords or slot number; Logs warning and doesn't set on invalid coords / slotnum void SetSlot(int a_X, int a_Y, const cItem & a_Item); void SetSlot(int a_X, int a_Y, short a_ItemType, char a_ItemCount, short a_ItemDamage); void SetSlot(int a_SlotNum, const cItem & a_Item); void SetSlot(int a_SlotNum, short a_ItemType, char a_ItemCount, short a_ItemDamage); // Empty the specified slot; Logs warning and doesn't set on invalid coords / slotnum void EmptySlot(int a_X, int a_Y); void EmptySlot(int a_SlotNum); /** Returns true if the specified slot is empty or the slot doesn't exist */ bool IsSlotEmpty(int a_SlotNum) const; /** Returns true if the specified slot is empty or the slot doesn't exist */ bool IsSlotEmpty(int a_X, int a_Y) const; /** Sets all items as empty */ void Clear(void); /** Returns number of items out of a_ItemStack that can fit in the storage */ int HowManyCanFit(const cItem & a_ItemStack, bool a_AllowNewStacks = true); /** Adds as many items out of a_ItemStack as can fit. If a_AllowNewStacks is set to false, only existing stacks can be topped up; If a_AllowNewStacks is set to true, empty slots can be used for the rest. If a_PrioritySlot is set to a positive value, then the corresponding slot will be used first (if empty or compatible with added items). If a_PrioritySlot is set to -1, regular order applies. Returns the number of items that fit. */ char AddItem(cItem & a_ItemStack, bool a_AllowNewStacks = true, int a_PrioritySlot = -1); /** Same as AddItem, but works on an entire list of item stacks. The a_ItemStackList is modified to reflect the leftover items. If a_AllowNewStacks is set to false, only existing stacks can be topped up; If a_AllowNewStacks is set to true, empty slots can be used for the rest. If a_PrioritySlot is set to a positive value, then the corresponding slot will be used first (if empty or compatible with added items). If a_PrioritySlot is set to -1, regular order applies. Returns the total number of items that fit. */ char AddItems(cItems & a_ItemStackList, bool a_AllowNewStacks = true, int a_PrioritySlot = -1); /** Removes the specified item from the grid, as many as possible, up to a_ItemStack.m_ItemCount. Returns the number of items that were removed. */ char RemoveItem(const cItem & a_ItemStack); /** Finds an item based on ItemType and ItemDamage (<- defines the itemType, too) */ cItem * FindItem(const cItem & a_RecipeItem); /** Adds (or subtracts, if a_AddToCount is negative) to the count of items in the specified slot. If the slot is empty, ignores the call. Returns the new count. */ char ChangeSlotCount(int a_SlotNum, char a_AddToCount); /** Adds (or subtracts, if a_AddToCount is negative) to the count of items in the specified slot. If the slot is empty, ignores the call. Returns the new count. */ char ChangeSlotCount(int a_X, int a_Y, char a_AddToCount); /** Removes one item from the stack in the specified slot, and returns it. If the slot was empty, returns an empty item */ cItem RemoveOneItem(int a_SlotNum); /** Removes one item from the stack in the specified slot, and returns it. If the slot was empty, returns an empty item */ cItem RemoveOneItem(int a_X, int a_Y); /** Returns the number of items of type a_Item that are stored */ int HowManyItems(const cItem & a_Item); /** Returns true if there are at least as many items of type a_ItemStack as in a_ItemStack */ bool HasItems(const cItem & a_ItemStack); /** Returns the index of the first empty slot; -1 if all full */ int GetFirstEmptySlot(void) const; /** Returns the index of the first non-empty slot; -1 if all empty */ int GetFirstUsedSlot(void) const; /** Returns the index of the last empty slot; -1 if all full */ int GetLastEmptySlot(void) const; /** Returns the index of the last used slot; -1 if all empty */ int GetLastUsedSlot(void) const; /** Returns the index of the first empty slot following a_StartFrom (a_StartFrom is not checked) */ int GetNextEmptySlot(int a_StartFrom) const; /** Returns the index of the first used slot following a_StartFrom (a_StartFrom is not checked) */ int GetNextUsedSlot(int a_StartFrom) const; /** Copies the contents into a cItems object; preserves the original a_Items contents */ void CopyToItems(cItems & a_Items) const; /** Adds the specified damage to the specified item; returns true if the item broke (but the item is left intact) */ bool DamageItem(int a_SlotNum, short a_Amount); /** Adds the specified damage to the specified item; returns true if the item broke (but the item is left intact) */ bool DamageItem(int a_X, int a_Y, short a_Amount); // tolua_end /** Returns true if slot coordinates lie within the grid. */ bool IsValidSlotCoords(int a_X, int a_Y) const; /** Returns true if slot number is within the grid. */ bool IsValidSlotNum(int a_SlotNum) const; /** Generates random loot from the specified loot probability table, with a chance of enchanted books added. A total of a_NumSlots are taken by the loot. Cannot export to Lua due to raw array a_LootProbabs. TODO: Make this exportable / export through ManualBindings.cpp with a Lua table as LootProbabs */ void GenerateRandomLootWithBooks(const cLootProbab * a_LootProbabs, size_t a_CountLootProbabs, int a_NumSlots, int a_Seed); /** Adds a callback that gets called whenever a slot changes. Must not be called from within the listener callback! */ void AddListener(cListener & a_Listener); /** Removes a slot-change-callback. Must not be called from within the listener callback! */ void RemoveListener(cListener & a_Listener); // tolua_begin protected: int m_Width; int m_Height; cLazyArray m_Slots; cListeners m_Listeners; ///< Listeners which should be notified on slot changes; the pointers are not owned by this object cCriticalSection m_CSListeners; ///< CS that guards the m_Listeners against multi-thread access bool m_IsInTriggerListeners; ///< Set to true while TriggerListeners is running, to detect attempts to manipulate listener list while triggerring /** Calls all m_Listeners for the specified slot number */ void TriggerListeners(int a_SlotNum); /** Adds up to a_Num items out of a_ItemStack, as many as can fit, in specified slot Returns the number of items that did fit. */ char AddItemToSlot(const cItem & a_ItemStack, int a_Slot, int a_Num, int a_MaxStack); } ; // tolua_end ================================================ FILE: src/Items/CMakeLists.txt ================================================ target_sources( ${CMAKE_PROJECT_NAME} PRIVATE ItemHandler.cpp ItemAnvil.h ItemArmor.h ItemAxe.h ItemBanner.h ItemBed.h ItemBigFlower.h ItemBoat.h ItemBottle.h ItemBow.h ItemBucket.h ItemButton.h ItemChest.h ItemChorusFruit.h ItemCloth.h ItemComparator.h ItemCookedFish.h ItemDefaultItem.h ItemDoor.h ItemDropSpenser.h ItemDye.h ItemEmptyMap.h ItemEnchantingTable.h ItemEndCrystal.h ItemEndPortalFrame.h ItemEnderChest.h ItemEyeOfEnder.h ItemFenceGate.h ItemFishingRod.h ItemFood.h ItemFoodSeeds.h ItemFurnace.h ItemGlazedTerracotta.h ItemGoldenApple.h ItemHandler.h ItemHoe.h ItemHopper.h ItemItemFrame.h ItemJackOLantern.h ItemLadder.h ItemLeaves.h ItemLever.h ItemLighter.h ItemLilypad.h ItemMap.h ItemMilk.h ItemMinecart.h ItemMobHead.h ItemNetherWart.h ItemObserver.h ItemPainting.h ItemPickaxe.h ItemPiston.h ItemPlanks.h ItemPoisonousPotato.h ItemPotion.h ItemPumpkin.h ItemQuartz.h ItemRail.h ItemRawChicken.h ItemRawFish.h ItemRedstoneDust.h ItemRedstoneRepeater.h ItemRottenFlesh.h ItemSapling.h ItemSeeds.h ItemShears.h ItemShovel.h ItemSideways.h ItemSign.h ItemSlab.h ItemSnow.h ItemSoup.h ItemSpawnEgg.h ItemSpiderEye.h ItemStairs.h ItemSword.h ItemThrowable.h ItemTorch.h ItemTrapdoor.h ItemTripwireHook.h ItemVines.h SimplePlaceableItemHandler.h ) ================================================ FILE: src/Items/ItemAnvil.h ================================================ #pragma once #include "ItemHandler.h" #include "Blocks/BlockAnvil.h" class cItemAnvilHandler final : public cItemHandler { using Super = cItemHandler; public: using Super::Super; private: virtual bool CommitPlacement(cPlayer & a_Player, const cItem & a_HeldItem, const Vector3i a_PlacePosition, const eBlockFace a_ClickedBlockFace, const Vector3i a_CursorPosition) const override { return a_Player.PlaceBlock( a_PlacePosition, static_cast(a_HeldItem.m_ItemType), cBlockAnvilHandler::YawToMetaData(a_Player.GetYaw()) | static_cast(a_HeldItem.m_ItemDamage << 2) ); } }; ================================================ FILE: src/Items/ItemArmor.h ================================================ #pragma once #include "ItemHandler.h" #include "../World.h" class cItemArmorHandler final : public cItemHandler { using Super = cItemHandler; public: using Super::Super; /** Move the armor to the armor slot of the player's inventory */ virtual bool OnItemUse( cWorld * a_World, cPlayer * a_Player, cBlockPluginInterface & a_PluginInterface, const cItem & a_HeldItem, const Vector3i a_ClickedBlockPos, eBlockFace a_ClickedBlockFace ) const override { int SlotNum; if (ItemCategory::IsHelmet(a_HeldItem.m_ItemType)) { SlotNum = 0; } else if (ItemCategory::IsChestPlate(a_HeldItem.m_ItemType)) { SlotNum = 1; } else if (ItemCategory::IsLeggings(a_HeldItem.m_ItemType)) { SlotNum = 2; } else if (ItemCategory::IsBoots(a_HeldItem.m_ItemType)) { SlotNum = 3; } else { LOGWARNING("Used unknown armor: %i", a_HeldItem.m_ItemType); return false; } if (!a_Player->GetInventory().GetArmorSlot(SlotNum).IsEmpty()) { return false; } a_Player->GetInventory().SetArmorSlot(SlotNum, a_HeldItem.CopyOne()); a_Player->GetInventory().RemoveOneEquippedItem(); return true; } virtual bool CanRepairWithRawMaterial(short a_ItemType) const override { switch (m_ItemType) { case E_ITEM_CHAIN_BOOTS: case E_ITEM_CHAIN_CHESTPLATE: case E_ITEM_CHAIN_HELMET: case E_ITEM_CHAIN_LEGGINGS: { return (a_ItemType == E_ITEM_IRON); } case E_ITEM_DIAMOND_BOOTS: case E_ITEM_DIAMOND_CHESTPLATE: case E_ITEM_DIAMOND_HELMET: case E_ITEM_DIAMOND_LEGGINGS: { return (a_ItemType == E_ITEM_DIAMOND); } case E_ITEM_IRON_BOOTS: case E_ITEM_IRON_CHESTPLATE: case E_ITEM_IRON_HELMET: case E_ITEM_IRON_LEGGINGS: { return (a_ItemType == E_ITEM_IRON); } case E_ITEM_GOLD_BOOTS: case E_ITEM_GOLD_CHESTPLATE: case E_ITEM_GOLD_HELMET: case E_ITEM_GOLD_LEGGINGS: { return (a_ItemType == E_ITEM_GOLD); } case E_ITEM_ELYTRA: // TODO: require Phantom Membrane instead of leather starting from protocol version 369 or 1.13 release case E_ITEM_LEATHER_BOOTS: case E_ITEM_LEATHER_CAP: case E_ITEM_LEATHER_PANTS: case E_ITEM_LEATHER_TUNIC: { return (a_ItemType == E_ITEM_LEATHER); } } return false; } } ; ================================================ FILE: src/Items/ItemAxe.h ================================================ #pragma once #include "ItemHandler.h" #include "../BlockInfo.h" class cItemAxeHandler final : public cItemHandler { using Super = cItemHandler; public: using Super::Super; virtual short GetDurabilityLossByAction(eDurabilityLostAction a_Action) const override { switch (a_Action) { case dlaAttackEntity: return 2; case dlaBreakBlock: return 1; case dlaBreakBlockInstant: return 0; } UNREACHABLE("Unsupported durability loss action"); } virtual float GetBlockBreakingStrength(BLOCKTYPE a_Block) const override { if (!IsBlockMaterialWood(a_Block) && !IsBlockMaterialPlants(a_Block) && !IsBlockMaterialVine(a_Block)) { return Super::GetBlockBreakingStrength(a_Block); } else { switch (m_ItemType) { case E_ITEM_WOODEN_AXE: return 2.0f; case E_ITEM_STONE_AXE: return 4.0f; case E_ITEM_IRON_AXE: return 6.0f; case E_ITEM_GOLD_AXE: return 12.0f; case E_ITEM_DIAMOND_AXE: return 8.0f; } } ASSERT(!"Something is wrong here... Maybe they are axes out of a new material?"); return 1.0f; } } ; ================================================ FILE: src/Items/ItemBanner.h ================================================ #pragma once #include "ItemHandler.h" #include "../World.h" #include "../Blocks/BlockHandler.h" #include "../BlockEntities/BannerEntity.h" #include "../Blocks/ChunkInterface.h" class cItemBannerHandler final: public cItemHandler { using Super = cItemHandler; public: using Super::Super; private: virtual bool CommitPlacement(cPlayer & a_Player, const cItem & a_HeldItem, const Vector3i a_PlacePosition, const eBlockFace a_ClickedBlockFace, const Vector3i a_CursorPosition) const override { // Cannot place a banner at "no face" and from the bottom: if ((a_ClickedBlockFace == BLOCK_FACE_NONE) || (a_ClickedBlockFace == BLOCK_FACE_BOTTOM)) { return false; } if (!TryPlaceBanner(a_Player, a_PlacePosition, a_ClickedBlockFace)) { return false; } a_Player.GetWorld()->DoWithBlockEntityAt(a_PlacePosition, [&a_HeldItem](cBlockEntity & a_BlockEntity) { ASSERT((a_BlockEntity.GetBlockType() == E_BLOCK_STANDING_BANNER) || (a_BlockEntity.GetBlockType() == E_BLOCK_WALL_BANNER)); cBannerEntity & BannerEntity = static_cast(a_BlockEntity); BannerEntity.SetBaseColor(static_cast(a_HeldItem.m_ItemDamage)); BannerEntity.SetCustomName(a_HeldItem.m_CustomName); return false; }); return true; } virtual bool IsPlaceable(void) const override { return true; } static bool TryPlaceBanner(cPlayer & a_Player, const Vector3i a_PlacePosition, const eBlockFace a_ClickedBlockFace) { const auto Rotation = a_Player.GetYaw(); // Placing on the floor: if (a_ClickedBlockFace == BLOCK_FACE_TOP) { NIBBLETYPE Meta; if ((Rotation >= -11.25f) && (Rotation < 11.25f)) { // South Meta = 0x08; } else if ((Rotation >= 11.25f) && (Rotation < 33.75f)) { // SouthSouthWest Meta = 0x09; } else if ((Rotation >= 23.75f) && (Rotation < 56.25f)) { // SouthWest Meta = 0x0a; } else if ((Rotation >= 56.25f) && (Rotation < 78.75f)) { // WestSouthWest Meta = 0x0b; } else if ((Rotation >= 78.75f) && (Rotation < 101.25f)) { // West Meta = 0x0c; } else if ((Rotation >= 101.25f) && (Rotation < 123.75f)) { // WestNorthWest Meta = 0x0d; } else if ((Rotation >= 123.75f) && (Rotation < 146.25f)) { // NorthWest Meta = 0x0e; } else if ((Rotation >= 146.25f) && (Rotation < 168.75f)) { // NorthNorthWest Meta = 0x0f; } else if ((Rotation >= -168.75f) && (Rotation < -146.25f)) { // NorthNorthEast Meta = 0x01; } else if ((Rotation >= -146.25f) && (Rotation < -123.75f)) { // NorthEast Meta = 0x02; } else if ((Rotation >= -123.75f) && (Rotation < -101.25f)) { // EastNorthEast Meta = 0x03; } else if ((Rotation >= -101.25) && (Rotation < -78.75f)) { // East Meta = 0x04; } else if ((Rotation >= -78.75) && (Rotation < -56.25f)) { // EastSouthEast Meta = 0x05; } else if ((Rotation >= -56.25f) && (Rotation < -33.75f)) { // SouthEast Meta = 0x06; } else if ((Rotation >= -33.75f) && (Rotation < -11.25f)) { // SouthSouthEast Meta = 0x07; } else // degrees jumping from 180 to -180 { // North Meta = 0x00; } return a_Player.PlaceBlock(a_PlacePosition, E_BLOCK_STANDING_BANNER, Meta); } // We must be placing on the side of a block. NIBBLETYPE Meta; if (a_ClickedBlockFace == BLOCK_FACE_EAST) { Meta = 0x05; } else if (a_ClickedBlockFace == BLOCK_FACE_WEST) { Meta = 0x04; } else if (a_ClickedBlockFace == BLOCK_FACE_NORTH) { Meta = 0x02; } else // degrees jumping from 180 to -180 { Meta = 0x03; } return a_Player.PlaceBlock(a_PlacePosition, E_BLOCK_WALL_BANNER, Meta); } }; ================================================ FILE: src/Items/ItemBed.h ================================================ #pragma once #include "ItemHandler.h" #include "Blocks/BlockBed.h" #include "BlockEntities/BedEntity.h" class cItemBedHandler final : public cItemHandler { using Super = cItemHandler; public: using Super::Super; virtual bool CommitPlacement(cPlayer & a_Player, const cItem & a_HeldItem, const Vector3i a_PlacePosition, const eBlockFace a_ClickedBlockFace, const Vector3i a_CursorPosition) const override { const auto BlockMeta = cBlockBedHandler::YawToMetaData(a_Player.GetYaw()); const auto HeadPosition = a_PlacePosition + cBlockBedHandler::MetaDataToDirection(BlockMeta); auto & World = *a_Player.GetWorld(); BLOCKTYPE HeadType; NIBBLETYPE HeadMeta; if (!World.GetBlockTypeMeta(HeadPosition, HeadType, HeadMeta)) { return false; } // Vanilla only allows beds to be placed into air. // Check if there is empty space for the "head" block: if (!cBlockHandler::For(HeadType).DoesIgnoreBuildCollision(World, a_HeldItem, HeadPosition, HeadMeta, a_ClickedBlockFace, false)) { return false; } // The "foot", and the "head" block: if ( !a_Player.PlaceBlocks( { { a_PlacePosition, E_BLOCK_BED, BlockMeta }, { HeadPosition, E_BLOCK_BED, static_cast(BlockMeta | 0x08) } }) ) { return false; } auto SetColor = [&a_HeldItem](cBlockEntity & a_BlockEntity) { ASSERT(a_BlockEntity.GetBlockType() == E_BLOCK_BED); static_cast(a_BlockEntity).SetColor(a_HeldItem.m_ItemDamage); return false; }; World.DoWithBlockEntityAt(a_PlacePosition, SetColor); World.DoWithBlockEntityAt(HeadPosition, SetColor); return true; } virtual bool IsPlaceable(void) const override { return true; } }; ================================================ FILE: src/Items/ItemBigFlower.h ================================================ #pragma once #include "ItemHandler.h" #include "../BlockInfo.h" class cItemBigFlowerHandler final: public cItemHandler { using Super = cItemHandler; public: using Super::Super; virtual bool CommitPlacement(cPlayer & a_Player, const cItem & a_HeldItem, const Vector3i a_PlacePosition, const eBlockFace a_ClickedBlockFace, const Vector3i a_CursorPosition) const override { // Needs at least two free blocks to build in: if (a_PlacePosition.y >= (cChunkDef::Height - 1)) { return false; } const auto & World = *a_Player.GetWorld(); const auto TopPos = a_PlacePosition.addedY(1); BLOCKTYPE TopType; NIBBLETYPE TopMeta; if (!World.GetBlockTypeMeta(TopPos, TopType, TopMeta)) { return false; } if (!cBlockHandler::For(TopType).DoesIgnoreBuildCollision(World, a_HeldItem, TopPos, TopMeta, a_ClickedBlockFace, false)) { return false; } return a_Player.PlaceBlocks( { { a_PlacePosition, E_BLOCK_BIG_FLOWER, static_cast(a_HeldItem.m_ItemDamage & 0x07) }, { TopPos, E_BLOCK_BIG_FLOWER, E_META_BIG_FLOWER_TOP } }); } }; ================================================ FILE: src/Items/ItemBoat.h ================================================ #pragma once #include "../Entities/Boat.h" #include "../LineBlockTracer.h" class cItemBoatHandler final: public cItemHandler { using Super = cItemHandler; public: using Super::Super; virtual bool OnItemUse( cWorld * a_World, cPlayer * a_Player, cBlockPluginInterface & a_PluginInterface, const cItem & a_HeldItem, const Vector3i a_ClickedBlockPos, eBlockFace a_ClickedBlockFace ) const override { // Only allow placing blocks on top of blocks, or when not in range of dest block: if ((a_ClickedBlockFace != BLOCK_FACE_YM) && (a_ClickedBlockFace != BLOCK_FACE_NONE)) { return false; } // Find the actual placement position by tracing line of sight until non-air block: class cCallbacks: public cBlockTracer::cCallbacks { public: Vector3d m_Pos; bool m_HasFound; cCallbacks(): m_HasFound(false) { } virtual bool OnNextBlock(Vector3i a_CBBlockPos, BLOCKTYPE a_CBBlockType, NIBBLETYPE a_CBBlockMeta, eBlockFace a_CBEntryFace) override { if (a_CBBlockType != E_BLOCK_AIR) { m_Pos = a_CBBlockPos; m_HasFound = true; return true; } return false; } } Callbacks; auto Start = a_Player->GetEyePosition() + a_Player->GetLookVector(); auto End = a_Player->GetEyePosition() + a_Player->GetLookVector() * 5; cLineBlockTracer::Trace(*a_World, Callbacks, Start, End); if (!Callbacks.m_HasFound) { return false; } // Block above must be air to spawn a boat (prevents spawning a boat underwater) auto PosAbove = Callbacks.m_Pos.Floor().addedY(1); if (!cChunkDef::IsValidHeight(PosAbove)) { return false; } BLOCKTYPE BlockAbove = a_World->GetBlock(PosAbove); if (BlockAbove != E_BLOCK_AIR) { return false; } // Spawn block at water level if (a_World->SpawnBoat(Callbacks.m_Pos + Vector3d(0.5, 1, 0.5), cBoat::ItemToMaterial(a_Player->GetEquippedItem())) == cEntity::INVALID_ID) { return false; } // Remove boat from players hand if (!a_Player->IsGameModeCreative()) { a_Player->GetInventory().RemoveOneEquippedItem(); } return true; } } ; ================================================ FILE: src/Items/ItemBottle.h ================================================ #pragma once #include "ItemHandler.h" #include "../BlockInfo.h" #include "../World.h" class cItemBottleHandler final: public cItemHandler { using Super = cItemHandler; public: using Super::Super; /** Searches for a water source block in the line of sight. Returns true and sets a_BlockPos if a water source block is found within line-of-sight. Returns false if not. */ bool GetBlockFromTrace(cWorld * a_World, cPlayer * a_Player, Vector3i & a_BlockPos) const { class cCallbacks: public cBlockTracer::cCallbacks { public: Vector3i m_Pos; bool m_HasHitFluid; cCallbacks(): m_HasHitFluid(false) { } virtual bool OnNextBlock(Vector3i a_BlockPosition, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, eBlockFace a_EntryFace) override { if (IsBlockWater(a_BlockType)) { if (a_BlockMeta != 0) // we're only looking for source blocks { return false; } m_HasHitFluid = true; m_Pos = a_BlockPosition; return true; } return false; } } Callbacks; auto Start = a_Player->GetEyePosition() + a_Player->GetLookVector(); auto End = a_Player->GetEyePosition() + a_Player->GetLookVector() * 5; cLineBlockTracer::Trace(*a_World, Callbacks, Start, End); if (!Callbacks.m_HasHitFluid) { return false; } a_BlockPos = Callbacks.m_Pos; return true; } virtual bool OnItemUse( cWorld * a_World, cPlayer * a_Player, cBlockPluginInterface & a_PluginInterface, const cItem & a_HeldItem, const Vector3i a_ClickedBlockPos, eBlockFace a_ClickedBlockFace ) const override { if (a_ClickedBlockFace != BLOCK_FACE_NONE) { return false; } Vector3i BlockPos; if (!GetBlockFromTrace(a_World, a_Player, BlockPos)) { return false; // Nothing in range. } // Give back a filled water bottle if gamemode is not creative: if (!a_Player->IsGameModeCreative()) { a_Player->ReplaceOneEquippedItemTossRest(cItem(E_ITEM_POTION)); } return true; } } ; ================================================ FILE: src/Items/ItemBow.h ================================================ #pragma once #include "../Entities/ArrowEntity.h" #include "ItemHandler.h" class cItemBowHandler final: public cItemHandler { using Super = cItemHandler; public: using Super::Super; virtual bool OnItemUse( cWorld * a_World, cPlayer * a_Player, cBlockPluginInterface & a_PluginInterface, const cItem & a_HeldItem, const Vector3i a_ClickedBlockPos, eBlockFace a_ClickedBlockFace ) const override { ASSERT(a_Player != nullptr); // Check if the player has an arrow in the inventory, or is in Creative: if (!(a_Player->IsGameModeCreative() || a_Player->GetInventory().HasItems(cItem(E_ITEM_ARROW)))) { return false; } a_Player->StartChargingBow(); return true; } virtual void OnItemShoot(cPlayer * a_Player, const Vector3i a_BlockPos, eBlockFace a_BlockFace) const override { // Actual shot - produce the arrow with speed based on the number of ticks that the bow was charged UNUSED(a_BlockPos); ASSERT(a_Player != nullptr); int BowCharge = a_Player->FinishChargingBow(); double Force = static_cast(BowCharge) / 20.0; Force = (Force * Force + 2.0 * Force) / 3.0; // This formula is used by the 1.6.2 client if (Force < 0.1) { // Too little force, ignore the shot return; } Force = std::min(Force, 1.0); // Does the player have an arrow? if (!a_Player->IsGameModeCreative() && !a_Player->GetInventory().HasItems(cItem(E_ITEM_ARROW))) { return; } // Create the arrow entity: auto Arrow = std::make_unique(*a_Player, Force * 2); auto ArrowPtr = Arrow.get(); if (!ArrowPtr->Initialize(std::move(Arrow), *a_Player->GetWorld())) { return; } a_Player->GetWorld()->BroadcastSoundEffect( "entity.arrow.shoot", a_Player->GetPosition(), 0.5, static_cast(Force) ); if (!a_Player->IsGameModeCreative()) { if (a_Player->GetEquippedItem().m_Enchantments.GetLevel(cEnchantments::enchInfinity) == 0) { a_Player->GetInventory().RemoveItem(cItem(E_ITEM_ARROW)); } else { ArrowPtr->SetPickupState(cArrowEntity::psNoPickup); } a_Player->UseEquippedItem(); } if (a_Player->GetEquippedItem().m_Enchantments.GetLevel(cEnchantments::enchFlame) > 0) { ArrowPtr->StartBurning(100); } } } ; ================================================ FILE: src/Items/ItemBucket.h ================================================ #pragma once #include "ItemHandler.h" #include "../BlockInfo.h" #include "../World.h" #include "../Simulator/FluidSimulator.h" #include "../Blocks/BlockHandler.h" #include "../LineBlockTracer.h" #include "../Blocks/ChunkInterface.h" class cItemBucketHandler final : public cItemHandler { using Super = cItemHandler; public: constexpr cItemBucketHandler(int a_ItemType): Super(a_ItemType) { } virtual bool OnItemUse( cWorld * a_World, cPlayer * a_Player, cBlockPluginInterface & a_PluginInterface, const cItem & a_HeldItem, const Vector3i a_ClickedBlockPos, eBlockFace a_ClickedBlockFace ) const override { switch (m_ItemType) { case E_ITEM_BUCKET: return ScoopUpFluid(a_World, a_Player, a_HeldItem, a_ClickedBlockPos, a_ClickedBlockFace); case E_ITEM_LAVA_BUCKET: return PlaceFluid (a_World, a_Player, a_PluginInterface, a_HeldItem, a_ClickedBlockPos, a_ClickedBlockFace, E_BLOCK_LAVA); case E_ITEM_WATER_BUCKET: return PlaceFluid (a_World, a_Player, a_PluginInterface, a_HeldItem, a_ClickedBlockPos, a_ClickedBlockFace, E_BLOCK_WATER); default: { ASSERT(!"Unhandled ItemType"); return false; } } } bool ScoopUpFluid(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, const Vector3i a_ClickedBlockPos, eBlockFace a_ClickedBlockFace) const { // Players can't pick up fluid while in adventure mode. if (a_Player->IsGameModeAdventure()) { return false; } // Needs a valid clicked block: if (a_ClickedBlockFace != BLOCK_FACE_NONE) { return false; } Vector3i BlockPos; if (!GetBlockFromTrace(a_World, a_Player, BlockPos)) { return false; // Nothing in range. } if (a_World->GetBlockMeta(BlockPos) != 0) { // Not a source block return false; } BLOCKTYPE Block = a_World->GetBlock(BlockPos); ENUM_ITEM_TYPE NewItemType; if (IsBlockWater(Block)) { NewItemType = E_ITEM_WATER_BUCKET; } else if (IsBlockLava(Block)) { NewItemType = E_ITEM_LAVA_BUCKET; } else { return false; } // Check to see if destination block is too far away // Reach Distance Multiplayer = 5 Blocks if ((BlockPos.x - a_Player->GetPosX() > 5) || (BlockPos.z - a_Player->GetPosZ() > 5)) { return false; } // Remove water / lava block (unless plugins disagree): if (!a_Player->PlaceBlock(BlockPos, E_BLOCK_AIR, 0)) { return false; } // Give new bucket, filled with fluid when the gamemode is not creative: if (!a_Player->IsGameModeCreative()) { a_Player->ReplaceOneEquippedItemTossRest(cItem(NewItemType)); } return true; } bool PlaceFluid( cWorld * a_World, cPlayer * a_Player, cBlockPluginInterface & a_PluginInterface, const cItem & a_Item, const Vector3i a_BlockPos, eBlockFace a_BlockFace, BLOCKTYPE a_FluidBlock ) const { // Players can't place fluid while in adventure mode. if (a_Player->IsGameModeAdventure()) { return false; } if (a_BlockFace != BLOCK_FACE_NONE) { return false; } BLOCKTYPE CurrentBlockType; NIBBLETYPE CurrentBlockMeta; eBlockFace EntryFace; Vector3i BlockPos; if (!GetPlacementCoordsFromTrace(a_World, a_Player, BlockPos, CurrentBlockType, CurrentBlockMeta, EntryFace)) { return false; } // Check to see if destination block is too far away // Reach Distance Multiplayer = 5 Blocks if ((BlockPos.x - a_Player->GetPosX() > 5) || (BlockPos.z - a_Player->GetPosZ() > 5)) { return false; } // Give back an empty bucket if the gamemode is not creative: if (!a_Player->IsGameModeCreative()) { a_Player->ReplaceOneEquippedItemTossRest(cItem(E_ITEM_BUCKET)); } // Wash away anything that was there prior to placing: if (cFluidSimulator::CanWashAway(CurrentBlockType)) { if (a_PluginInterface.CallHookPlayerBreakingBlock(*a_Player, BlockPos, EntryFace, CurrentBlockType, CurrentBlockMeta)) { // Plugin disagrees with the washing-away return false; } a_World->DropBlockAsPickups(BlockPos, a_Player, nullptr); a_PluginInterface.CallHookPlayerBrokenBlock(*a_Player, BlockPos, EntryFace, CurrentBlockType, CurrentBlockMeta); } // Place the actual fluid block: return a_Player->PlaceBlock(BlockPos, a_FluidBlock, 0); } bool GetBlockFromTrace(cWorld * a_World, cPlayer * a_Player, Vector3i & a_BlockPos) const { class cCallbacks : public cBlockTracer::cCallbacks { public: Vector3i m_Pos; bool m_HasHitFluid; cCallbacks(void) : m_HasHitFluid(false) { } virtual bool OnNextBlock(Vector3i a_BlockPosition, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, eBlockFace a_EntryFace) override { if (IsBlockWater(a_BlockType) || IsBlockLava(a_BlockType)) { if (a_BlockMeta != 0) // GetBlockFromTrace is called for scooping up fluids; the hit block should be a source { return false; } m_HasHitFluid = true; m_Pos = a_BlockPosition; return true; } return false; } } Callbacks; cLineBlockTracer Tracer(*a_World, Callbacks); Vector3d Start(a_Player->GetEyePosition() + a_Player->GetLookVector()); Vector3d End(a_Player->GetEyePosition() + a_Player->GetLookVector() * 5); Tracer.Trace(Start, End); if (!Callbacks.m_HasHitFluid) { return false; } a_BlockPos = Callbacks.m_Pos; return true; } bool GetPlacementCoordsFromTrace(cWorld * a_World, cPlayer * a_Player, Vector3i & a_BlockPos, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta, eBlockFace & a_BlockFace) const { class cCallbacks : public cBlockTracer::cCallbacks { public: Vector3i m_Pos; BLOCKTYPE m_ReplacedBlockType; NIBBLETYPE m_ReplacedBlockMeta; eBlockFace m_EntryFace; virtual bool OnNextBlock(Vector3i a_CBBlockPos, BLOCKTYPE a_CBBlockType, NIBBLETYPE a_CBBlockMeta, eBlockFace a_CBEntryFace) override { if ((a_CBBlockType != E_BLOCK_AIR) && !IsBlockLiquid(a_CBBlockType)) { m_ReplacedBlockType = a_CBBlockType; m_ReplacedBlockMeta = a_CBBlockMeta; m_EntryFace = static_cast(a_CBEntryFace); if (!cFluidSimulator::CanWashAway(a_CBBlockType)) { a_CBBlockPos = AddFaceDirection(a_CBBlockPos, a_CBEntryFace); // Was an unwashawayable block, can't overwrite it! } m_Pos = a_CBBlockPos; // (Block could be washed away, replace it) return true; // Abort tracing } return false; } } Callbacks; cLineBlockTracer Tracer(*a_World, Callbacks); Vector3d Start(a_Player->GetEyePosition()); Vector3d End(a_Player->GetEyePosition() + a_Player->GetLookVector() * 5); // cLineBlockTracer::Trace() returns true when whole line was traversed. By returning true from the callback when we hit something, // we ensure that this never happens if liquid could be placed // Use this to judge whether the position is valid if (!Tracer.Trace(Start, End)) { a_BlockPos = Callbacks.m_Pos; a_BlockType = Callbacks.m_ReplacedBlockType; a_BlockMeta = Callbacks.m_ReplacedBlockMeta; a_BlockFace = Callbacks.m_EntryFace; return true; } return false; } }; ================================================ FILE: src/Items/ItemButton.h ================================================ #pragma once #include "ItemHandler.h" class cItemButtonHandler final : public cItemHandler { using Super = cItemHandler; public: using Super::Super; private: /** Converts the block face of the neighbor to which the button is attached, to the block meta for this button. */ static NIBBLETYPE BlockFaceToMetaData(eBlockFace a_BlockFace) { switch (a_BlockFace) { case BLOCK_FACE_YP: return 0x5; case BLOCK_FACE_ZM: return 0x4; case BLOCK_FACE_ZP: return 0x3; case BLOCK_FACE_XM: return 0x2; case BLOCK_FACE_XP: return 0x1; case BLOCK_FACE_YM: return 0x0; case BLOCK_FACE_NONE: { break; } } UNREACHABLE("Unsupported block face"); } virtual bool CommitPlacement(cPlayer & a_Player, const cItem & a_HeldItem, const Vector3i a_PlacePosition, const eBlockFace a_ClickedBlockFace, const Vector3i a_CursorPosition) const override { return a_Player.PlaceBlock(a_PlacePosition, static_cast(a_HeldItem.m_ItemType), BlockFaceToMetaData(a_ClickedBlockFace)); } }; ================================================ FILE: src/Items/ItemChest.h ================================================ #pragma once #include "ItemHandler.h" #include "Blocks/BlockChest.h" class cItemChestHandler final : public cItemHandler { using Super = cItemHandler; public: using Super::Super; cItemChestHandler(const cItemChestHandler &) = delete; private: virtual bool CommitPlacement(cPlayer & a_Player, const cItem & a_HeldItem, const Vector3i a_PlacePosition, const eBlockFace a_ClickedBlockFace, const Vector3i a_CursorPosition) const override { // Check that there is at most one single neighbor of the same chest type: static const Vector3i CrossCoords[] = { {-1, 0, 0}, { 0, 0, -1}, { 1, 0, 0}, { 0, 0, 1}, }; auto & World = *a_Player.GetWorld(); int NeighborIdx = -1; for (size_t i = 0; i < ARRAYCOUNT(CrossCoords); i++) { const auto NeighborPos = a_PlacePosition + CrossCoords[i]; if (World.GetBlock(NeighborPos) != m_ItemType) { continue; } if (NeighborIdx >= 0) { // Can't place here, there are already two neighbors, this would form a 3-block chest return false; } NeighborIdx = static_cast(i); // Check that this neighbor is a single chest: for (size_t j = 0; j < ARRAYCOUNT(CrossCoords); j++) { if (World.GetBlock(NeighborPos + CrossCoords[j]) == m_ItemType) { // Trying to place next to a dblchest return false; } } // for j } // for i // Get the meta of the placed chest; take existing neighbors into account: BLOCKTYPE ChestBlockType = static_cast(m_ItemType); NIBBLETYPE Meta; const auto yaw = a_Player.GetYaw(); switch (NeighborIdx) { case 0: case 2: { // The neighbor is in the X axis, form a X-axis-aligned dblchest: Meta = ((yaw >= -90) && (yaw < 90)) ? E_META_CHEST_FACING_ZM : E_META_CHEST_FACING_ZP; break; } case 1: case 3: { // The neighbor is in the Z axis, form a Z-axis-aligned dblchest: Meta = (yaw < 0) ? E_META_CHEST_FACING_XM : E_META_CHEST_FACING_XP; break; } default: { // No neighbor, place based on yaw: Meta = cBlockChestHandler::YawToMetaData(yaw); break; } } // switch (NeighborIdx) // Place the new chest: if (!a_Player.PlaceBlock(a_PlacePosition, ChestBlockType, Meta)) { return false; } // Adjust the existing chest, if any: if (NeighborIdx != -1) { World.FastSetBlock(a_PlacePosition + CrossCoords[NeighborIdx], ChestBlockType, Meta); } return true; } }; ================================================ FILE: src/Items/ItemChorusFruit.h ================================================ #pragma once #include "ItemFood.h" #include "../Entities/Pawn.h" class cItemChorusFruitHandler final: public cItemFoodHandler { using Super = cItemFoodHandler; public: constexpr cItemChorusFruitHandler(int a_ItemType) : Super(a_ItemType, FoodInfo(4, 2.4)) { } virtual bool EatItem(cPlayer * a_Player, cItem * a_Item) const override { cItemHandler::EatItem(a_Player, a_Item); if (!a_Player->IsGameModeCreative()) { a_Player->GetInventory().RemoveOneEquippedItem(); } // Attempt to find a teleport destination Vector3d Destination; cWorld * World = a_Player->GetWorld(); if (cPawn::FindTeleportDestination(*World, 2, 16, Destination, a_Player->GetPosition(), 8)) { // Broadcast sound effect to _pre-teleport_ location, then teleport player. World->BroadcastSoundEffect("item.chorus_fruit.teleport", a_Player->GetPosition(), 1, 1); a_Player->TeleportToCoords(Destination.x, Destination.y, Destination.z); } return true; } }; ================================================ FILE: src/Items/ItemCloth.h ================================================ #pragma once #include "ItemHandler.h" class cItemClothHandler final : public cItemHandler { public: constexpr cItemClothHandler(int a_ItemType) : cItemHandler(a_ItemType) { } } ; ================================================ FILE: src/Items/ItemComparator.h ================================================ #pragma once #include "ItemHandler.h" #include "../Blocks/BlockComparator.h" class cItemComparatorHandler final: public cItemHandler { using Super = cItemHandler; public: using Super::Super; virtual bool CommitPlacement(cPlayer & a_Player, const cItem & a_HeldItem, const Vector3i a_PlacePosition, const eBlockFace a_ClickedBlockFace, const Vector3i a_CursorPosition) const override { return a_Player.PlaceBlock(a_PlacePosition, E_BLOCK_INACTIVE_COMPARATOR, cBlockComparatorHandler::YawToMetaData(a_Player.GetYaw())); } virtual bool IsPlaceable(void) const override { return true; } } ; ================================================ FILE: src/Items/ItemCookedFish.h ================================================ #pragma once #include "ItemFood.h" class cItemCookedFishHandler final: public cItemFoodHandler { using Super = cItemFoodHandler; public: constexpr cItemCookedFishHandler(int a_ItemType): Super(a_ItemType, FoodInfo(0, 0)) { } virtual FoodInfo GetFoodInfo(const cItem * a_Item) const override { static const FoodInfo CookedFishInfos[] = { FoodInfo(5, 6.0), // Cooked fish FoodInfo(6, 9.6), // Cooked salmon }; if (a_Item->m_ItemDamage >= static_cast(ARRAYCOUNT(CookedFishInfos))) { LOGWARNING("Unknown cooked fish type '%d'", a_Item->m_ItemDamage); return FoodInfo(0, 0); } return CookedFishInfos[a_Item->m_ItemDamage]; } }; ================================================ FILE: src/Items/ItemDefaultItem.h ================================================ #pragma once #include "ItemHandler.h" class cDefaultItemHandler final : public cItemHandler { public: using cItemHandler::cItemHandler; }; ================================================ FILE: src/Items/ItemDoor.h ================================================ #pragma once #include "ItemHandler.h" #include "../World.h" #include "../Blocks/BlockDoor.h" class cItemDoorHandler final: public cItemHandler { using Super = cItemHandler; public: constexpr cItemDoorHandler(int a_ItemType): Super(a_ItemType) { } virtual bool CommitPlacement(cPlayer & a_Player, const cItem & a_HeldItem, const Vector3i a_PlacePosition, const eBlockFace a_ClickedBlockFace, const Vector3i a_CursorPosition) const override { // Vanilla only allows door placement while clicking on the top face of the block below the door: if (a_ClickedBlockFace != BLOCK_FACE_TOP) { return false; } // Get the block type of the door to place: BLOCKTYPE BlockType; switch (m_ItemType) { case E_ITEM_WOODEN_DOOR: BlockType = E_BLOCK_OAK_DOOR; break; case E_ITEM_IRON_DOOR: BlockType = E_BLOCK_IRON_DOOR; break; case E_ITEM_SPRUCE_DOOR: BlockType = E_BLOCK_SPRUCE_DOOR; break; case E_ITEM_BIRCH_DOOR: BlockType = E_BLOCK_BIRCH_DOOR; break; case E_ITEM_JUNGLE_DOOR: BlockType = E_BLOCK_JUNGLE_DOOR; break; case E_ITEM_DARK_OAK_DOOR: BlockType = E_BLOCK_DARK_OAK_DOOR; break; case E_ITEM_ACACIA_DOOR: BlockType = E_BLOCK_ACACIA_DOOR; break; default: UNREACHABLE("Unhandled door type"); } const auto & World = *a_Player.GetWorld(); const auto UpperBlockPosition = a_PlacePosition.addedY(1); // Check the block that will get replaced by the door: { BLOCKTYPE TopType; NIBBLETYPE TopMeta; if (!World.GetBlockTypeMeta(UpperBlockPosition, TopType, TopMeta)) { return false; } if (!cBlockHandler::For(TopType).DoesIgnoreBuildCollision(World, a_HeldItem, UpperBlockPosition, TopMeta, a_ClickedBlockFace, false)) { return false; } } // Get the coords of the neighboring blocks: NIBBLETYPE LowerBlockMeta = cBlockDoorHandler::YawToMetaData(a_Player.GetYaw()); Vector3i RelDirToOutside = cBlockDoorHandler::GetRelativeDirectionToOutside(LowerBlockMeta); Vector3i LeftNeighborPos = RelDirToOutside; LeftNeighborPos.TurnCW(); LeftNeighborPos.Move(a_PlacePosition); Vector3i RightNeighborPos = RelDirToOutside; RightNeighborPos.TurnCCW(); RightNeighborPos.Move(a_PlacePosition); // Decide whether the hinge is on the left (default) or on the right: NIBBLETYPE UpperBlockMeta = 0x08; BLOCKTYPE LeftNeighborBlock = World.GetBlock(LeftNeighborPos); BLOCKTYPE RightNeighborBlock = World.GetBlock(RightNeighborPos); /* // DEBUG: FLOGD("Door being placed at {0}", a_PlacePosition); FLOGD("RelDirToOutside: {0}", RelDirToOutside); FLOGD("Left neighbor at {0}: {1} ({2})", LeftNeighborPos, LeftNeighborBlock, ItemTypeToString(LeftNeighborBlock)); FLOGD("Right neighbor at {0}: {1} ({2})", RightNeighborPos, RightNeighborBlock, ItemTypeToString(RightNeighborBlock)); */ if ( cBlockDoorHandler::IsDoorBlockType(LeftNeighborBlock) || // The block to the left is a door block ( !cBlockInfo::IsSolid(LeftNeighborBlock) && // Prioritize hinge on the left side cBlockInfo::IsSolid(RightNeighborBlock) && // The block to the right is solid... !cBlockDoorHandler::IsDoorBlockType(RightNeighborBlock) // ... but not a door ) ) { // DEBUG: LOGD("Setting hinge to right side"); UpperBlockMeta = 0x09; // Upper block | hinge on right } // Set the blocks: return a_Player.PlaceBlocks( { { a_PlacePosition, BlockType, LowerBlockMeta }, { UpperBlockPosition, BlockType, UpperBlockMeta } }); } virtual bool IsPlaceable(void) const override { return true; } } ; ================================================ FILE: src/Items/ItemDropSpenser.h ================================================ #pragma once #include "ItemHandler.h" #include "Blocks/BlockDropSpenser.h" class cItemDropSpenserHandler final : public cItemHandler { using Super = cItemHandler; public: using Super::Super; private: virtual bool CommitPlacement(cPlayer & a_Player, const cItem & a_HeldItem, const Vector3i a_PlacePosition, const eBlockFace a_ClickedBlockFace, const Vector3i a_CursorPosition) const override { return a_Player.PlaceBlock(a_PlacePosition, static_cast(a_HeldItem.m_ItemType), cBlockDropSpenserHandler::DisplacementYawToMetaData(a_PlacePosition, a_Player.GetEyePosition(), a_Player.GetYaw())); } }; ================================================ FILE: src/Items/ItemDye.h ================================================ #pragma once #include "ItemHandler.h" #include "../World.h" #include "../Entities/Player.h" #include "../Blocks/BlockCocoaPod.h" class cItemDyeHandler final : public cItemHandler { using Super = cItemHandler; public: using Super::Super; virtual bool OnItemUse( cWorld * a_World, cPlayer * a_Player, cBlockPluginInterface & a_PluginInterface, const cItem & a_HeldItem, const Vector3i a_ClickedBlockPos, eBlockFace a_ClickedBlockFace ) const override { if ((a_HeldItem.m_ItemDamage == E_META_DYE_WHITE) && (a_ClickedBlockFace != BLOCK_FACE_NONE)) { // Bonemeal (white dye) is used to fertilize plants: if (FertilizePlant(*a_World, a_ClickedBlockPos)) { if (a_Player->IsGameModeSurvival()) { a_Player->GetInventory().RemoveOneEquippedItem(); return true; } } } else if ((a_HeldItem.m_ItemDamage == E_META_DYE_BROWN) && (a_ClickedBlockFace >= BLOCK_FACE_ZM) && (a_ClickedBlockFace <= BLOCK_FACE_XP)) { // Players can't place blocks while in adventure mode. if (a_Player->IsGameModeAdventure()) { return false; } // Cocoa (brown dye) can be planted on jungle logs: BLOCKTYPE BlockType; NIBBLETYPE BlockMeta; // Check if the block that the player clicked is a jungle log. if ( !a_World->GetBlockTypeMeta(a_ClickedBlockPos, BlockType, BlockMeta) || ((BlockType != E_BLOCK_LOG) || ((BlockMeta & 0x03) != E_META_LOG_JUNGLE)) ) { return false; } // Get the location from the new cocoa pod. auto CocoaPos = AddFaceDirection(a_ClickedBlockPos, a_ClickedBlockFace, false); BlockMeta = cBlockCocoaPodHandler::BlockFaceToMeta(a_ClickedBlockFace); // Place the cocoa pod: if (a_World->GetBlock(CocoaPos) != E_BLOCK_AIR) { return false; } if (a_Player->PlaceBlock(CocoaPos, E_BLOCK_COCOA_POD, BlockMeta)) { if (a_Player->IsGameModeSurvival()) { a_Player->GetInventory().RemoveOneEquippedItem(); } return true; } } return false; } /** Attempts to use the bonemeal on the plant at the specified (absolute) position. The effect of fertilization depends on the plant: https://minecraft.wiki/w/Bone_Meal#Fertilizer - grow a few stages - grow 1 stage with a chance - drop pickups without destroying the plant - grow more plants in the vicinity If fertilized succesfully, spawn appropriate particle effects, too. Returns true if the plant was fertilized successfully, false if not / not a plant. Note that successful fertilization doesn't mean successful growth - for blocks that have only a chance to grow, fertilization success is reported even in the case when the chance fails (bonemeal still needs to be consumed). */ static bool FertilizePlant(cWorld & a_World, Vector3i a_BlockPos) { BLOCKTYPE BlockType; NIBBLETYPE BlockMeta; if (!a_World.GetBlockTypeMeta(a_BlockPos, BlockType, BlockMeta)) { return false; } switch (BlockType) { case E_BLOCK_WHEAT: case E_BLOCK_CARROTS: case E_BLOCK_POTATOES: case E_BLOCK_MELON_STEM: case E_BLOCK_PUMPKIN_STEM: { // Grow by 2 - 5 stages: auto NumStages = GetRandomProvider().RandInt(2, 5); if (a_World.GrowPlantAt(a_BlockPos, NumStages) <= 0) { return false; } a_World.BroadcastSoundParticleEffect(EffectID::PARTICLE_HAPPY_VILLAGER, a_BlockPos, 0); return true; } // case wheat, carrots, potatoes, melon stem, pumpkin stem case E_BLOCK_BEETROOTS: { // Fix GH #4805. // Bonemeal should only advance growth, not spawn produce, and should not be consumed if plant at maturity: if (a_World.GrowPlantAt(a_BlockPos, 1) <= 0) { return false; } a_World.BroadcastSoundParticleEffect(EffectID::PARTICLE_HAPPY_VILLAGER, a_BlockPos, 0); if (GetRandomProvider().RandBool(0.25)) { // 75% chance of 1-stage growth, but we hit the 25%, rollback: a_World.GrowPlantAt(a_BlockPos, -1); } return true; } // case beetroots case E_BLOCK_SAPLING: { // 45% chance of growing to the next stage / full tree: if (GetRandomProvider().RandBool(0.45)) { a_World.GrowPlantAt(a_BlockPos, 1); } a_World.BroadcastSoundParticleEffect(EffectID::PARTICLE_HAPPY_VILLAGER, a_BlockPos, 0); return true; } // case sapling case E_BLOCK_BIG_FLOWER: { // Drop the corresponding flower item without destroying the block: cItems Pickups; switch (BlockMeta) { case E_META_BIG_FLOWER_SUNFLOWER: Pickups.Add(E_BLOCK_BIG_FLOWER, 1, E_META_BIG_FLOWER_SUNFLOWER); break; case E_META_BIG_FLOWER_LILAC: Pickups.Add(E_BLOCK_BIG_FLOWER, 1, E_META_BIG_FLOWER_LILAC); break; case E_META_BIG_FLOWER_ROSE_BUSH: Pickups.Add(E_BLOCK_BIG_FLOWER, 1, E_META_BIG_FLOWER_ROSE_BUSH); break; case E_META_BIG_FLOWER_PEONY: Pickups.Add(E_BLOCK_BIG_FLOWER, 1, E_META_BIG_FLOWER_PEONY); break; } // TODO: Should we call any hook for this? a_World.SpawnItemPickups(Pickups, a_BlockPos); return true; } // big flower case E_BLOCK_TALL_GRASS: case E_BLOCK_COCOA_POD: { // Always try to grow 1 stage: if (a_World.GrowPlantAt(a_BlockPos, 1) <= 0) { return false; } a_World.BroadcastSoundParticleEffect(EffectID::PARTICLE_HAPPY_VILLAGER, a_BlockPos, 0); return true; } // case tall grass case E_BLOCK_RED_MUSHROOM: case E_BLOCK_BROWN_MUSHROOM: { // 40% chance of growing into a large mushroom: if (GetRandomProvider().RandBool(0.6)) { return false; } if (a_World.GrowPlantAt(a_BlockPos, 1) <= 0) { return false; } a_World.BroadcastSoundParticleEffect(EffectID::PARTICLE_HAPPY_VILLAGER, a_BlockPos, 0); return true; } // case red or brown mushroom case E_BLOCK_GRASS: { GrowPlantsAround(a_World, a_BlockPos); return true; } // TODO: case E_BLOCK_SWEET_BERRY_BUSH: // TODO: case E_BLOCK_SEA_PICKLE: // TODO: case E_BLOCK_KELP: // TODO: case E_BLOCK_BAMBOO: } // switch (blockType) return false; } /** Grows new plants around the specified block. Places up to 40 new plants, with the following probability: - 0 up to 8 big grass (2-block tall grass) - 8 up tp 24 tall grass (1-block tall grass) - 0 up to 8 flowers (biome dependent variants) The new plants are spawned within 7 taxicab distance of a_Position, on a grass block. Broadcasts a particle for each new spawned plant. */ static void GrowPlantsAround(cWorld & a_World, const Vector3i a_Position) { auto & Random = GetRandomProvider(); auto DoubleGrassCount = Random.RandInt(8U); auto GrassCount = Random.RandInt(8U, 24U); auto FlowerCount = Random.RandInt(8U); // Do a round-robin placement: while ((DoubleGrassCount > 0) || (GrassCount > 0) || (FlowerCount > 0)) { // place the big grass: if (DoubleGrassCount != 0) { FindAdjacentGrassAnd<&GrowDoubleTallGrass>(a_World, a_Position); DoubleGrassCount--; } // place the tall grass: if (GrassCount != 0) { FindAdjacentGrassAnd<&GrowTallGrass>(a_World, a_Position); GrassCount--; } // place the flowers if (FlowerCount != 0) { FindAdjacentGrassAnd<&GrowFlower>(a_World, a_Position); FlowerCount--; } } } static void GrowDoubleTallGrass(cWorld & a_World, const Vector3i a_Position) { a_World.SetBlock(a_Position, E_BLOCK_BIG_FLOWER, E_META_BIG_FLOWER_DOUBLE_TALL_GRASS); a_World.BroadcastSoundParticleEffect(EffectID::PARTICLE_HAPPY_VILLAGER, a_Position, 0); const auto Above = a_Position.addedY(1); a_World.SetBlock(Above, E_BLOCK_BIG_FLOWER, E_META_BIG_FLOWER_DOUBLE_TALL_GRASS | E_META_BIG_FLOWER_TOP); a_World.BroadcastSoundParticleEffect(EffectID::PARTICLE_HAPPY_VILLAGER, Above, 0); } static void GrowTallGrass(cWorld & a_World, const Vector3i a_Position) { a_World.SetBlock(a_Position, E_BLOCK_TALL_GRASS, E_META_TALL_GRASS_GRASS); a_World.BroadcastSoundParticleEffect(EffectID::PARTICLE_HAPPY_VILLAGER, a_Position, 0); } /** Grows a biome-dependent flower according to https://minecraft.wiki/w/Flower#Flower_biomes */ static void GrowFlower(cWorld & a_World, const Vector3i a_Position) { auto & Random = GetRandomProvider(); switch (a_World.GetBiomeAt(a_Position.x, a_Position.z)) { case biPlains: case biSunflowerPlains: { switch (Random.RandInt(8)) { case 0: a_World.SetBlock(a_Position, E_BLOCK_DANDELION, 0); break; case 1: a_World.SetBlock(a_Position, E_BLOCK_FLOWER, E_META_FLOWER_POPPY); break; case 2: a_World.SetBlock(a_Position, E_BLOCK_FLOWER, E_META_FLOWER_ALLIUM); break; case 3: a_World.SetBlock(a_Position, E_BLOCK_RED_ROSE, 0); break; // was renamed to Azure Bluet later case 4: a_World.SetBlock(a_Position, E_BLOCK_FLOWER, E_META_FLOWER_RED_TULIP); break; case 5: a_World.SetBlock(a_Position, E_BLOCK_FLOWER, E_META_FLOWER_PINK_TULIP); break; case 6: a_World.SetBlock(a_Position, E_BLOCK_FLOWER, E_META_FLOWER_WHITE_TULIP); break; case 7: a_World.SetBlock(a_Position, E_BLOCK_FLOWER, E_META_FLOWER_ORANGE_TULIP); break; case 8: a_World.SetBlock(a_Position, E_BLOCK_FLOWER, E_META_FLOWER_OXEYE_DAISY); break; // TODO: Add cornflower } break; } case biSwampland: case biSwamplandM: { a_World.SetBlock(a_Position, E_BLOCK_FLOWER, E_META_FLOWER_BLUE_ORCHID); break; } case biFlowerForest: { switch (Random.RandInt(8)) { case 0: a_World.SetBlock(a_Position, E_BLOCK_DANDELION, 0); break; case 1: a_World.SetBlock(a_Position, E_BLOCK_FLOWER, E_META_FLOWER_POPPY); break; case 2: a_World.SetBlock(a_Position, E_BLOCK_FLOWER, E_META_FLOWER_ALLIUM); break; case 3: a_World.SetBlock(a_Position, E_BLOCK_RED_ROSE, 0); break; // was renamed to Azure Bluet later case 4: a_World.SetBlock(a_Position, E_BLOCK_FLOWER, E_META_FLOWER_RED_TULIP); break; case 5: a_World.SetBlock(a_Position, E_BLOCK_FLOWER, E_META_FLOWER_PINK_TULIP); break; case 6: a_World.SetBlock(a_Position, E_BLOCK_FLOWER, E_META_FLOWER_WHITE_TULIP); break; case 7: a_World.SetBlock(a_Position, E_BLOCK_FLOWER, E_META_FLOWER_ORANGE_TULIP); break; case 8: a_World.SetBlock(a_Position, E_BLOCK_FLOWER, E_META_FLOWER_OXEYE_DAISY); break; // TODO: Add cornflower, lily of the valley } break; } case biMesa: case biMesaBryce: case biMesaPlateau: case biMesaPlateauF: case biMesaPlateauM: case biMesaPlateauFM: case biMushroomIsland: case biMushroomShore: case biNether: case biEnd: { break; } default: { switch (Random.RandInt(1)) { case 0: a_World.SetBlock(a_Position, E_BLOCK_DANDELION, 0); break; case 1: a_World.SetBlock(a_Position, E_BLOCK_RED_ROSE, 0); break; } break; } } } /** Walks adjacent grass blocks up to 7 taxicab distance away from a_Position and calls the Planter function on the first suitable one found. Does nothing if no position suitable for growing was found. */ template static void FindAdjacentGrassAnd(cWorld & a_World, const Vector3i a_Position) { auto & Random = GetRandomProvider(); auto Position = a_Position; // Maximum 7 taxicab distance away from centre: for ( int Tries = 0; Tries != 8; Tries++, // Get the adjacent block to visit this iteration: Position += Vector3i( Random.RandInt(-1, 1), Random.RandInt(-1, 1) * (Random.RandInt(2) / 2), // Y offset, with discouragement to values that aren't zero Random.RandInt(-1, 1) ) ) { if ( !cChunkDef::IsValidHeight(Position) || (a_World.GetBlock(Position) != E_BLOCK_GRASS) // Are we looking at grass? ) { // Not grass or invalid height, restart random walk and bail: Position = a_Position; continue; } if (Planter == GrowDoubleTallGrass) { const auto TwoAbove = Position.addedY(2); if ((TwoAbove.y >= cChunkDef::Height) || (a_World.GetBlock(TwoAbove) != E_BLOCK_AIR)) { // Insufficient space for tall grass: continue; } } const auto PlantBase = Position.addedY(1); if ((PlantBase.y >= cChunkDef::Height) || (a_World.GetBlock(PlantBase) != E_BLOCK_AIR)) { // Insufficient space: continue; } Planter(a_World, PlantBase); return; } } } ; ================================================ FILE: src/Items/ItemEmptyMap.h ================================================ #pragma once #include "../Item.h" class cItemEmptyMapHandler final: public cItemHandler { using Super = cItemHandler; static const unsigned int DEFAULT_SCALE = 0; public: using Super::Super; virtual bool OnItemUse( cWorld * a_World, cPlayer * a_Player, cBlockPluginInterface & a_PluginInterface, const cItem & a_HeldItem, const Vector3i a_ClickedBlockPos, eBlockFace a_ClickedBlockFace ) const override { UNUSED(a_HeldItem); UNUSED(a_ClickedBlockFace); // The map center is fixed at the central point of the 8x8 block of chunks you are standing in when you right-click it. const int RegionWidth = cChunkDef::Width * 8; int CenterX = FloorC(a_Player->GetPosX() / RegionWidth) * RegionWidth + (RegionWidth / 2); int CenterZ = FloorC(a_Player->GetPosZ() / RegionWidth) * RegionWidth + (RegionWidth / 2); auto NewMap = a_World->GetMapManager().CreateMap(CenterX, CenterZ, DEFAULT_SCALE); if (NewMap == nullptr) { return true; } // Replace map in the inventory: a_Player->ReplaceOneEquippedItemTossRest(cItem(E_ITEM_MAP, 1, static_cast(NewMap->GetID() & 0x7fff))); return true; } } ; ================================================ FILE: src/Items/ItemEnchantingTable.h ================================================ #pragma once #include "ItemHandler.h" #include "../BlockEntities/EnchantingTableEntity.h" #include "../World.h" class cItemEnchantingTableHandler final: public cItemHandler { using Super = cItemHandler; public: using Super::Super; private: virtual bool CommitPlacement(cPlayer & a_Player, const cItem & a_HeldItem, const Vector3i a_PlacePosition, const eBlockFace a_ClickedBlockFace, const Vector3i a_CursorPosition) const override { if (!Super::CommitPlacement(a_Player, a_HeldItem, a_PlacePosition, a_ClickedBlockFace, a_CursorPosition)) { return false; } if (a_HeldItem.IsCustomNameEmpty()) { return true; } a_Player.GetWorld()->DoWithBlockEntityAt(a_PlacePosition, [&a_HeldItem](cBlockEntity & a_BlockEntity) { ASSERT(a_BlockEntity.GetBlockType() == E_BLOCK_ENCHANTMENT_TABLE); static_cast(a_BlockEntity).SetCustomName(a_HeldItem.m_CustomName); return false; }); return true; } virtual bool IsPlaceable(void) const override { return true; } } ; ================================================ FILE: src/Items/ItemEndCrystal.h ================================================ #pragma once #include "ItemHandler.h" #include "../World.h" #include "../Entities/Player.h" class cItemEndCrystalHandler final : public cItemHandler { using Super = cItemHandler; public: constexpr cItemEndCrystalHandler(int a_ItemType) : Super(a_ItemType) { } virtual bool OnItemUse( cWorld * a_World, cPlayer * a_Player, cBlockPluginInterface & a_PluginInterface, const cItem & a_HeldItem, const Vector3i a_BlockPos, eBlockFace a_ClickedBlockFace) const override { // Must click a valid block: if (a_ClickedBlockFace < 0) { return false; } if ( const auto BlockType = a_World->GetBlock(a_BlockPos); // Don't place if placement block is not obsidian or bedrock: (BlockType != E_BLOCK_OBSIDIAN) && (BlockType != E_BLOCK_BEDROCK) ) { return false; } // The position of the block above the placement block. const auto Above = a_BlockPos.addedY(1); if ( // Don't place if two blocks above placement block aren't air: ((Above.y != cChunkDef::Height) && (a_World->GetBlock(Above) != E_BLOCK_AIR)) || ((Above.y < (cChunkDef::Height - 1)) && (a_World->GetBlock(Above.addedY(1)) != E_BLOCK_AIR)) || // Refuse placement if there are any entities in a (1 by 2 by 1) bounding box with base at the block above: !a_World->ForEachEntityInBox( { Above, Above + Vector3i(1, 2, 1) }, [](cEntity & a_Entity) { return true; } ) ) { return false; } // Spawns ender crystal entity, aborts if plugin cancelled: if (a_World->SpawnEnderCrystal(Vector3d(0.5, 0, 0.5) + Above, false) == cEntity::INVALID_ID) { return false; } if (!a_Player->IsGameModeCreative()) { a_Player->GetInventory().RemoveOneEquippedItem(); } return true; } }; ================================================ FILE: src/Items/ItemEndPortalFrame.h ================================================ #pragma once #include "ItemHandler.h" #include "Blocks/BlockEndPortalFrame.h" class cItemEndPortalFrameHandler final : public cItemHandler { using Super = cItemHandler; public: using Super::Super; private: virtual bool CommitPlacement(cPlayer & a_Player, const cItem & a_HeldItem, const Vector3i a_PlacePosition, const eBlockFace a_ClickedBlockFace, const Vector3i a_CursorPosition) const override { return a_Player.PlaceBlock(a_PlacePosition, E_BLOCK_END_PORTAL_FRAME, cBlockEndPortalFrameHandler::YawToMetaData(a_Player.GetYaw())); } }; ================================================ FILE: src/Items/ItemEnderChest.h ================================================ #pragma once #include "ItemHandler.h" #include "Blocks/BlockEnderChest.h" class cItemEnderChestHandler final : public cItemHandler { using Super = cItemHandler; public: using Super::Super; private: virtual bool CommitPlacement(cPlayer & a_Player, const cItem & a_HeldItem, const Vector3i a_PlacePosition, const eBlockFace a_ClickedBlockFace, const Vector3i a_CursorPosition) const override { return a_Player.PlaceBlock(a_PlacePosition, E_BLOCK_ENDER_CHEST, cBlockEnderChestHandler::YawToMetaData(a_Player.GetYaw())); } }; ================================================ FILE: src/Items/ItemEyeOfEnder.h ================================================ #pragma once #include "ItemHandler.h" #include "ItemThrowable.h" class cItemEyeOfEnderHandler final: public cItemThrowableHandler { using Super = cItemThrowableHandler; public: constexpr cItemEyeOfEnderHandler(int a_ItemType): Super(a_ItemType, cProjectileEntity::pkSnowball, 30) { } virtual bool OnItemUse( cWorld * a_World, cPlayer * a_Player, cBlockPluginInterface & a_PluginInterface, const cItem & a_Item, const Vector3i a_ClickedBlockPos, eBlockFace a_ClickedBlockFace ) const override { // Try to fill an End Portal Frame block: if (a_ClickedBlockFace != BLOCK_FACE_NONE) { BLOCKTYPE FacingBlock; NIBBLETYPE FacingMeta; if (a_World->GetBlockTypeMeta(a_ClickedBlockPos, FacingBlock, FacingMeta) && (FacingBlock == E_BLOCK_END_PORTAL_FRAME)) { // Fill the portal frame. E_META_END_PORTAL_EYE is the bit for holding the eye of ender. if ((FacingMeta & E_META_END_PORTAL_FRAME_EYE) != E_META_END_PORTAL_FRAME_EYE) { a_World->SetBlock(a_ClickedBlockPos, E_BLOCK_END_PORTAL_FRAME, FacingMeta | E_META_END_PORTAL_FRAME_EYE); if (!a_Player->IsGameModeCreative()) { a_Player->GetInventory().RemoveOneEquippedItem(); } cChunkInterface ChunkInterface(a_World->GetChunkMap()); // Try to spawn portal: FindAndSetPortal(a_ClickedBlockPos, FacingMeta & 3, ChunkInterface, *a_World); return true; } } return false; } // TODO: Create projectile for Eye Of Ender // return Super::OnItemUse(a_World, a_Player, a_PluginInterface, a_Item, a_ClickedBlockPos, a_ClickedBlockFace); return false; } /** Returns false if portal cannot be made, true if portal was made. */ static bool FindAndSetPortal(Vector3i a_FirstFrame, NIBBLETYPE a_Direction, cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface) { /* PORTAL FINDING ALGORITH ======================= - Get clicked base block - Check diagonally (clockwise) for another portal block - if exists, and has eye, Continue. Abort if any are facing the wrong direction. - if doesn't exist, check horizontally (the block to the left of this block). Abort if there is no horizontal block. - After a corner has been met, traverse the portal clockwise, ensuring valid portal frames connect the rectangle. - Track the NorthWest Corner, and the dimensions. - If dimensions are valid, create the portal. */ static_assert((E_META_END_PORTAL_FRAME_ZM - E_META_END_PORTAL_FRAME_XM) == 1, "Should be going clockwise"); const int MIN_PORTAL_WIDTH = 3; const int MAX_PORTAL_WIDTH = 4; // Directions to use for the clockwise traversal. static const Vector3i Left[] = { { 1, 0, 0}, // 0, South, left block is East / XP { 0, 0, 1}, // 1, West, left block is South / ZP {-1, 0, 0}, // 2, North, left block is West / XM { 0, 0, -1}, // 3, East, left block is North / ZM }; static const Vector3i LeftForward[] = { { 1, 0, 1}, // 0, South, left block is SouthEast / XP ZP {-1, 0, 1}, // 1, West, left block is SouthWest / XM ZP {-1, 0, -1}, // 2, North, left block is NorthWest / XM ZM { 1, 0, -1}, // 3, East, left block is NorthEast / XP ZM }; int EdgesComplete = -1; // We start search _before_ finding the first edge Vector3i NorthWestCorner; int EdgeWidth[4] = { 1, 1, 1, 1 }; NIBBLETYPE CurrentDirection = a_Direction; Vector3i CurrentPos = a_FirstFrame; // Scan clockwise until we have seen all 4 edges while (EdgesComplete < 4) { // Check if we are at a corner Vector3i NextPos = CurrentPos + LeftForward[CurrentDirection]; if (IsPortalFrame(a_ChunkInterface.GetBlock(NextPos))) { // We have found the corner, move clockwise to next edge if (CurrentDirection == E_META_END_PORTAL_FRAME_XP) { // We are on the NW (XM, ZM) Corner // Relative to the previous frame, the portal should appear to the right of this portal frame. NorthWestCorner = NextPos - Left[CurrentDirection]; } if (EdgesComplete == -1) { // Reset current width, we will revisit it last EdgeWidth[CurrentDirection] = 1; } // Rotate 90 degrees clockwise CurrentDirection = (CurrentDirection + 1) % 4; EdgesComplete++; } else { // We are not at a corner, keep walking the edge NextPos = CurrentPos + Left[CurrentDirection]; EdgeWidth[CurrentDirection]++; if (EdgeWidth[CurrentDirection] > MAX_PORTAL_WIDTH) { // Don't build a portal that is too long. return false; } } if (!IsValidFrameAtPos(a_ChunkInterface, NextPos, CurrentDirection)) { // Neither the edge nor the corner are valid portal blocks. return false; } CurrentPos = NextPos; } if ((EdgeWidth[0] != EdgeWidth[2]) || (EdgeWidth[1] != EdgeWidth[3])) { // Mismatched Portal Dimensions. return false; } if ((EdgeWidth[0] < MIN_PORTAL_WIDTH) || (EdgeWidth[1] < MIN_PORTAL_WIDTH)) { // Portal too small. return false; } for (int i = 0; i < EdgeWidth[0]; i++) { for (int j = 0; j < EdgeWidth[1]; j++) { a_ChunkInterface.SetBlock(NorthWestCorner.x + i, NorthWestCorner.y, NorthWestCorner.z + j, E_BLOCK_END_PORTAL, 0); } } return true; } /** Return true if this block is a portal frame, has an eye, and is facing the correct direction. */ static bool IsValidFrameAtPos(cChunkInterface & a_ChunkInterface, Vector3i a_BlockPos, NIBBLETYPE a_ShouldFace) { BLOCKTYPE BlockType; NIBBLETYPE BlockMeta; return ( a_ChunkInterface.GetBlockTypeMeta(a_BlockPos, BlockType, BlockMeta) && (BlockType == E_BLOCK_END_PORTAL_FRAME) && (BlockMeta == (a_ShouldFace | E_META_END_PORTAL_FRAME_EYE)) ); } /** Return true if this block is a portal frame. */ static bool IsPortalFrame(BLOCKTYPE BlockType) { return (BlockType == E_BLOCK_END_PORTAL_FRAME); } } ; ================================================ FILE: src/Items/ItemFenceGate.h ================================================ #pragma once #include "ItemHandler.h" #include "Blocks/BlockFenceGate.h" class cItemFenceGateHandler final : public cItemHandler { using Super = cItemHandler; public: using Super::Super; private: virtual bool CommitPlacement(cPlayer & a_Player, const cItem & a_HeldItem, const Vector3i a_PlacePosition, const eBlockFace a_ClickedBlockFace, const Vector3i a_CursorPosition) const override { return a_Player.PlaceBlock(a_PlacePosition, static_cast(a_HeldItem.m_ItemType), cBlockFenceGateHandler::YawToMetaData(a_Player.GetYaw())); } }; ================================================ FILE: src/Items/ItemFishingRod.h ================================================ #pragma once #include "../Entities/Floater.h" #include "../Entities/Entity.h" #include "../Item.h" #include "../Root.h" //////////////////////////////////////////////////////////////////////////////// // cFloaterCallback class cFloaterCallback { public: cFloaterCallback(void) : m_CanPickup(false), m_AttachedMobID(cEntity::INVALID_ID) { } bool operator () (cEntity & a_Entity) { auto & Floater = static_cast(a_Entity); m_CanPickup = Floater.CanPickup(); m_Pos = Floater.GetPosition(); m_BitePos = Floater.GetBitePos(); m_AttachedMobID = Floater.GetAttachedMobID(); Floater.Destroy(); return true; } bool CanPickup(void) const { return m_CanPickup; } bool IsAttached(void) const { return (m_AttachedMobID != cEntity::INVALID_ID); } UInt32 GetAttachedMobID(void) const { return m_AttachedMobID; } Vector3d GetPos(void) const { return m_Pos; } Vector3d GetBitePos(void) const { return m_BitePos; } protected: bool m_CanPickup; UInt32 m_AttachedMobID; Vector3d m_Pos; Vector3d m_BitePos; } ; class cItemFishingRodHandler final: public cItemHandler { using Super = cItemHandler; public: using Super::Super; virtual bool OnItemUse( cWorld * a_World, cPlayer * a_Player, cBlockPluginInterface & a_PluginInterface, const cItem & a_HeldItem, const Vector3i a_ClickedBlockPos, eBlockFace a_ClickedBlockFace ) const override { if (a_ClickedBlockFace != BLOCK_FACE_NONE) { return false; } if (a_Player->IsFishing()) { ReelIn(*a_World, *a_Player); } else { // Cast a hook: auto & Random = GetRandomProvider(); auto CountDownTime = Random.RandInt(100, 900) - static_cast(a_Player->GetEquippedItem().m_Enchantments.GetLevel(cEnchantments::enchLure) * 100); auto Floater = std::make_unique( a_Player->GetEyePosition(), a_Player->GetLookVector() * 15, a_Player->GetUniqueID(), CountDownTime ); auto FloaterPtr = Floater.get(); if (!FloaterPtr->Initialize(std::move(Floater), *a_World)) { return false; } a_Player->SetIsFishing(true, FloaterPtr->GetUniqueID()); } return true; } /** Reels back the fishing line, reeling any attached mob, or creating fished loot, or just breaking the fishing rod. */ void ReelIn(cWorld & a_World, cPlayer & a_Player) const { cFloaterCallback FloaterInfo; a_World.DoWithEntityByID(a_Player.GetFloaterID(), FloaterInfo); a_Player.SetIsFishing(false); // If attached to an entity, reel it in: if (FloaterInfo.IsAttached()) { ReelInEntity(a_World, a_Player, FloaterInfo.GetAttachedMobID()); return; } // If loot can be caught, get it: if (FloaterInfo.CanPickup()) { ReelInLoot(a_World, a_Player, FloaterInfo.GetBitePos()); return; } // Empty fishing rod, just damage it: auto BlockType = a_World.GetBlock(FloaterInfo.GetPos() - Vector3d(0, 0.1, 0)); if ((BlockType != E_BLOCK_AIR) && !IsBlockWater(BlockType)) { a_Player.UseEquippedItem(2); } } /** Reels back the entity, specified by the ID, and damages the fishing rod accordingly. */ void ReelInEntity(cWorld & a_World, cPlayer & a_Player, UInt32 a_EntityID) const { auto PlayerPos = a_Player.GetPosition(); a_World.DoWithEntityByID(a_EntityID, [=](cEntity & a_Entity) { auto Speed = PlayerPos - a_Entity.GetPosition(); a_Entity.AddSpeed(Speed); return true; } ); a_Player.UseEquippedItem(5); } void ReelInLoot(cWorld & a_World, cPlayer & a_Player, const Vector3d a_FloaterBitePos) const { auto LotSLevel = std::min(a_Player.GetEquippedItem().m_Enchantments.GetLevel(cEnchantments::enchLuckOfTheSea), 3u); // Chances for getting an item from the category for each level of Luck of the Sea (0 - 3) const int TreasureChances[] = {50, 71, 92, 113}; // 5% | 7.1% | 9.2% | 11.3% const int JunkChances[] = {100, 81, 61, 42}; // 10% | 8.1% | 6.1% | 4.2% cItems Drops; auto & Random = GetRandomProvider(); int ItemCategory = Random.RandInt(999); if (ItemCategory < TreasureChances[LotSLevel]) { switch (Random.RandInt(5)) // Each piece of treasure has an equal chance of 1 / 6 { case 0: { cItem Bow(E_ITEM_BOW, 1, Random.RandInt(50)); Bow.EnchantByXPLevels(Random.RandInt(22U, 30U), GetRandomProvider()); Drops.Add(Bow); break; } case 1: { cItem Book(E_ITEM_BOOK); Book.EnchantByXPLevels(30, GetRandomProvider()); Drops.Add(Book); break; } case 2: { cItem Rod(E_ITEM_FISHING_ROD, 1, Random.RandInt(50)); Rod.EnchantByXPLevels(Random.RandInt(22U, 30U), GetRandomProvider()); Drops.Add(Rod); break; } case 3: { Drops.Add(cItem(E_ITEM_NAME_TAG)); break; } case 4: { Drops.Add(cItem(E_ITEM_SADDLE)); break; } case 5: { Drops.Add(cItem(E_BLOCK_LILY_PAD)); break; } } a_Player.GetStatistics().Custom[CustomStatistic::TreasureFished]++; } else if (ItemCategory < JunkChances[LotSLevel]) { int Junk = Random.RandInt(82); if (Junk < 10) // 10 / 83 chance of spawning a bowl { Drops.Add(cItem(E_ITEM_BOWL)); } else if (Junk < 12) // 2 / 83 chance of spawning a fishing rod { // Fishing Rods caught from the Junk category will be 10% .. 100% damaged, and always unenchanted. Drops.Add(cItem(E_ITEM_FISHING_ROD, 1, Random.RandInt(7, 65))); } else if (Junk < 22) // 10 / 83 chance of spawning leather { Drops.Add(cItem(E_ITEM_LEATHER)); } else if (Junk < 32) // 10 / 83 chance of spawning leather boots { // Leather boots caught from the Junk category will be 10% .. 100% damaged, and always unenchanted. Drops.Add(cItem(E_ITEM_LEATHER_BOOTS, 1, Random.RandInt(7, 66))); } else if (Junk < 42) // 10 / 83 chance of spawning rotten flesh { Drops.Add(cItem(E_ITEM_ROTTEN_FLESH)); } else if (Junk < 47) // 5 / 83 chance of spawning a stick { Drops.Add(cItem(E_ITEM_STICK)); } else if (Junk < 52) // 5 / 83 chance of spawning string { Drops.Add(cItem(E_ITEM_STRING)); } else if (Junk < 62) // 10 / 83 chance of spawning a water bottle { Drops.Add(cItem(E_ITEM_POTION)); } else if (Junk < 72) // 10 / 83 chance of spawning a bone { Drops.Add(cItem(E_ITEM_BONE)); } else if (Junk < 73) // 1 / 83 chance of spawning an ink sac { Drops.Add(cItem(E_ITEM_DYE)); } else // 10 / 83 chance of spawning a tripwire hook { Drops.Add(cItem(E_BLOCK_TRIPWIRE_HOOK)); } a_Player.GetStatistics().Custom[CustomStatistic::JunkFished]++; } else { int FishType = Random.RandInt(99); if (FishType <= 1) // Clownfish has a 2% chance of spawning { Drops.Add(cItem(E_ITEM_RAW_FISH, 1, E_META_RAW_FISH_CLOWNFISH)); } else if (FishType <= 12) // Pufferfish has a 13% chance of spawning { Drops.Add(cItem(E_ITEM_RAW_FISH, 1, E_META_RAW_FISH_PUFFERFISH)); } else if (FishType <= 24) // Raw salmon has a 25% chance of spawning { Drops.Add(cItem(E_ITEM_RAW_FISH, 1, E_META_RAW_FISH_SALMON)); } else // Raw fish has a 60% chance of spawning { Drops.Add(cItem(E_ITEM_RAW_FISH, 1, E_META_RAW_FISH_FISH)); } a_Player.GetStatistics().Custom[CustomStatistic::FishCaught]++; } auto Experience = Random.RandInt(1, 6); // Check with plugins if this loot is acceptable: if (cRoot::Get()->GetPluginManager()->CallHookPlayerFishing(a_Player, Drops, Experience)) { return; } // Spawn the loot and the experience orb: auto FloaterPos = a_FloaterBitePos.addedY(0.5); const float FISH_SPEED_MULT = 2.25f; Vector3d FlyDirection = (a_Player.GetEyePosition() - FloaterPos).addedY(1.0f) * FISH_SPEED_MULT; a_World.SpawnItemPickups(Drops, FloaterPos, FlyDirection); a_World.SpawnExperienceOrb(a_Player.GetPosition(), Experience); a_Player.UseEquippedItem(1); // Notify plugins cRoot::Get()->GetPluginManager()->CallHookPlayerFished(a_Player, Drops, Experience); } } ; ================================================ FILE: src/Items/ItemFood.h ================================================ #pragma once #include "ItemHandler.h" class cItemFoodHandler: public cItemHandler { using Super = cItemHandler; public: constexpr cItemFoodHandler(int a_ItemType, FoodInfo a_FoodInfo): Super(a_ItemType), m_FoodInfo(a_FoodInfo) { } virtual bool IsFood(void) const override { return true; } virtual FoodInfo GetFoodInfo(const cItem * a_Item) const override { UNUSED(a_Item); return m_FoodInfo; } virtual bool EatItem(cPlayer * a_Player, cItem * a_Item) const override { if (!Super::EatItem(a_Player, a_Item)) { return false; } if (!a_Player->IsGameModeCreative()) { a_Player->GetInventory().RemoveOneEquippedItem(); } return true; } protected: FoodInfo m_FoodInfo; ~cItemFoodHandler() = default; }; class cItemSimpleFoodHandler final: public cItemFoodHandler { using cItemFoodHandler::cItemFoodHandler; }; ================================================ FILE: src/Items/ItemFoodSeeds.h ================================================ #pragma once #include "ItemSeeds.h" #include "../World.h" class cItemFoodSeedsHandler final: public cItemSeedsHandler { using Super = cItemSeedsHandler; public: constexpr cItemFoodSeedsHandler(int a_ItemType, FoodInfo a_FoodInfo): Super(a_ItemType), m_FoodInfo(a_FoodInfo) { } virtual bool IsFood(void) const override { return true; } virtual FoodInfo GetFoodInfo(const cItem * a_Item) const override { UNUSED(a_Item); return m_FoodInfo; } virtual bool EatItem(cPlayer * a_Player, cItem * a_Item) const override { if (!Super::EatItem(a_Player, a_Item)) { return false; } if (!a_Player->IsGameModeCreative()) { a_Player->GetInventory().RemoveOneEquippedItem(); } return true; } protected: FoodInfo m_FoodInfo; }; ================================================ FILE: src/Items/ItemFurnace.h ================================================ #pragma once #include "ItemHandler.h" #include "Blocks/BlockFurnace.h" class cItemFurnaceHandler final : public cItemHandler { using Super = cItemHandler; public: using Super::Super; private: virtual bool CommitPlacement(cPlayer & a_Player, const cItem & a_HeldItem, const Vector3i a_PlacePosition, const eBlockFace a_ClickedBlockFace, const Vector3i a_CursorPosition) const override { return a_Player.PlaceBlock(a_PlacePosition, E_BLOCK_FURNACE, cBlockFurnaceHandler::YawToMetaData(a_Player.GetYaw())); } }; ================================================ FILE: src/Items/ItemGlazedTerracotta.h ================================================ #pragma once #include "ItemHandler.h" #include "Blocks/BlockGlazedTerracotta.h" class cItemGlazedTerracottaHandler final : public cItemHandler { using Super = cItemHandler; public: using Super::Super; private: virtual bool CommitPlacement(cPlayer & a_Player, const cItem & a_HeldItem, const Vector3i a_PlacePosition, const eBlockFace a_ClickedBlockFace, const Vector3i a_CursorPosition) const override { return a_Player.PlaceBlock(a_PlacePosition, static_cast(a_HeldItem.m_ItemType), cBlockGlazedTerracottaHandler::YawToMetaData(a_Player.GetYaw())); } }; ================================================ FILE: src/Items/ItemGoldenApple.h ================================================ #pragma once #include "ItemFood.h" class cItemGoldenAppleHandler final: public cItemFoodHandler { using Super = cItemFoodHandler; public: constexpr cItemGoldenAppleHandler(int a_ItemType): Super(a_ItemType, FoodInfo(4, 9.6)) { } virtual bool EatItem(cPlayer * a_Player, cItem * a_Item) const override { cItemHandler::EatItem(a_Player, a_Item); if (!a_Player->IsGameModeCreative()) { a_Player->GetInventory().RemoveOneEquippedItem(); } // Enchanted golden apples have stronger effects: if (a_Item->m_ItemDamage >= E_META_GOLDEN_APPLE_ENCHANTED) { a_Player->AddEntityEffect(cEntityEffect::effAbsorption, 2400, 3); a_Player->AddEntityEffect(cEntityEffect::effRegeneration, 400, 1); a_Player->AddEntityEffect(cEntityEffect::effResistance, 6000, 0); a_Player->AddEntityEffect(cEntityEffect::effFireResistance, 6000, 0); return true; } a_Player->AddEntityEffect(cEntityEffect::effAbsorption, 2400, 0); a_Player->AddEntityEffect(cEntityEffect::effRegeneration, 100, 1); return true; } }; ================================================ FILE: src/Items/ItemHandler.cpp ================================================ #include "Globals.h" #include "ItemHandler.h" #include "../World.h" #include "../Entities/Player.h" #include "../FastRandom.h" #include "../BlockInServerPluginInterface.h" #include "../Chunk.h" // Handlers: #include "ItemAnvil.h" #include "ItemArmor.h" #include "ItemAxe.h" #include "ItemBanner.h" #include "ItemBed.h" #include "ItemBigFlower.h" #include "ItemBoat.h" #include "ItemBottle.h" #include "ItemBow.h" #include "ItemBucket.h" #include "ItemButton.h" #include "ItemChest.h" #include "ItemChorusFruit.h" #include "ItemCloth.h" #include "ItemComparator.h" #include "ItemCookedFish.h" #include "ItemDefaultItem.h" #include "ItemDoor.h" #include "ItemDropSpenser.h" #include "ItemDye.h" #include "ItemEmptyMap.h" #include "ItemEnchantingTable.h" #include "ItemEndCrystal.h" #include "ItemEnderChest.h" #include "ItemEndPortalFrame.h" #include "ItemEyeOfEnder.h" #include "ItemFenceGate.h" #include "ItemFishingRod.h" #include "ItemFood.h" #include "ItemFoodSeeds.h" #include "ItemFurnace.h" #include "ItemGlazedTerracotta.h" #include "ItemGoldenApple.h" #include "ItemHoe.h" #include "ItemHopper.h" #include "ItemItemFrame.h" #include "ItemJackOLantern.h" #include "ItemLadder.h" #include "ItemLeaves.h" #include "ItemLever.h" #include "ItemLighter.h" #include "ItemLilypad.h" #include "ItemMap.h" #include "ItemMilk.h" #include "ItemMinecart.h" #include "ItemMobHead.h" #include "ItemNetherWart.h" #include "ItemObserver.h" #include "ItemPainting.h" #include "ItemPickaxe.h" #include "ItemPiston.h" #include "ItemPlanks.h" #include "ItemPoisonousPotato.h" #include "ItemPotion.h" #include "ItemPumpkin.h" #include "ItemQuartz.h" #include "ItemRail.h" #include "ItemRawChicken.h" #include "ItemRawFish.h" #include "ItemRedstoneDust.h" #include "ItemRedstoneRepeater.h" #include "ItemRottenFlesh.h" #include "ItemSapling.h" #include "ItemSeeds.h" #include "ItemShears.h" #include "ItemShovel.h" #include "ItemSideways.h" #include "ItemSign.h" #include "ItemSlab.h" #include "ItemSnow.h" #include "ItemSoup.h" #include "ItemSpawnEgg.h" #include "ItemSpiderEye.h" #include "ItemStairs.h" #include "ItemSword.h" #include "ItemThrowable.h" #include "ItemTorch.h" #include "ItemTrapdoor.h" #include "ItemTripwireHook.h" #include "ItemVines.h" #include "../Blocks/BlockHandler.h" #include "SimplePlaceableItemHandler.h" namespace { constexpr cDefaultItemHandler Item11DiscHandler (E_ITEM_11_DISC); constexpr cDefaultItemHandler Item13DiscHandler (E_ITEM_13_DISC); constexpr cItemBoatHandler ItemAcaciaBoatHandler (E_ITEM_ACACIA_BOAT); constexpr cDefaultItemHandler ItemAcaciaDoorBlockHandler (E_BLOCK_ACACIA_DOOR); constexpr cItemDoorHandler ItemAcaciaDoorHandler (E_ITEM_ACACIA_DOOR); constexpr cItemFenceGateHandler ItemAcaciaFenceGateHandler (E_BLOCK_ACACIA_FENCE_GATE); constexpr cDefaultItemHandler ItemAcaciaFenceHandler (E_BLOCK_ACACIA_FENCE); constexpr cItemStairsHandler ItemAcaciaStairsHandler (E_BLOCK_ACACIA_WOOD_STAIRS); constexpr cItemRailHandler ItemActivatorRailHandler (E_BLOCK_ACTIVATOR_RAIL); constexpr cDefaultItemHandler ItemActiveComparatorHandler (E_BLOCK_ACTIVE_COMPARATOR); constexpr cDefaultItemHandler ItemAirHandler (E_BLOCK_AIR); constexpr cItemAnvilHandler ItemAnvilHandler (E_BLOCK_ANVIL); constexpr cItemSimpleFoodHandler ItemAppleHandler (E_ITEM_RED_APPLE, cItemHandler::FoodInfo(4, 2.4)); constexpr cDefaultItemHandler ItemArmorStandHandler (E_ITEM_ARMOR_STAND); constexpr cDefaultItemHandler ItemArrowHandler (E_ITEM_ARROW); constexpr cItemSimpleFoodHandler ItemBakedPotatoHandler (E_ITEM_BAKED_POTATO, cItemHandler::FoodInfo(5, 6)); constexpr cItemBannerHandler ItemBannerHandler (E_ITEM_BANNER); constexpr cDefaultItemHandler ItemBarrierHandler (E_BLOCK_BARRIER); constexpr cDefaultItemHandler ItemBeaconHandler (E_BLOCK_BEACON); constexpr cDefaultItemHandler ItemBedBlockHandler (E_BLOCK_BED); constexpr cItemBedHandler ItemBedHandler (E_ITEM_BED); constexpr cDefaultItemHandler ItemBedrockHandler (E_BLOCK_BEDROCK); constexpr cItemSimpleFoodHandler ItemBeetrootHandler (E_ITEM_BEETROOT, cItemHandler::FoodInfo(1, 1.2)); constexpr cDefaultItemHandler ItemBeetrootsBlockHandler (E_BLOCK_BEETROOTS); constexpr cItemSimpleSeedsHandler ItemBeetrootSeedsHandler (E_ITEM_BEETROOT_SEEDS); constexpr cItemSoupHandler ItemBeetrootSoupHandler (E_ITEM_BEETROOT_SOUP, cItemHandler::FoodInfo(6, 7.2)); constexpr cItemBigFlowerHandler ItemBigFlowerHandler (E_BLOCK_BIG_FLOWER); constexpr cItemBoatHandler ItemBirchBoatHandler (E_ITEM_BIRCH_BOAT); constexpr cDefaultItemHandler ItemBirchDoorBlockHandler (E_BLOCK_BIRCH_DOOR); constexpr cItemDoorHandler ItemBirchDoorHandler (E_ITEM_BIRCH_DOOR); constexpr cItemFenceGateHandler ItemBirchFenceGateHandler (E_BLOCK_BIRCH_FENCE_GATE); constexpr cDefaultItemHandler ItemBirchFenceHandler (E_BLOCK_BIRCH_FENCE); constexpr cItemStairsHandler ItemBirchStairsHandler (E_BLOCK_BIRCH_WOOD_STAIRS); constexpr cItemGlazedTerracottaHandler ItemBlackGlazedTerracottaHandler (E_BLOCK_BLACK_GLAZED_TERRACOTTA); constexpr cDefaultItemHandler ItemBlackShulkerBoxHandler (E_BLOCK_BLACK_SHULKER_BOX); constexpr cDefaultItemHandler ItemBlazePowderHandler (E_ITEM_BLAZE_POWDER); constexpr cDefaultItemHandler ItemBlazeRodHandler (E_ITEM_BLAZE_ROD); constexpr cDefaultItemHandler ItemBlocksDiscHandler (E_ITEM_BLOCKS_DISC); constexpr cItemGlazedTerracottaHandler ItemBlueGlazedTerracottaHandler (E_BLOCK_BLUE_GLAZED_TERRACOTTA); constexpr cDefaultItemHandler ItemBlueShulkerBoxHandler (E_BLOCK_BLUE_SHULKER_BOX); constexpr cDefaultItemHandler ItemBoneBlockHandler (E_BLOCK_BONE_BLOCK); constexpr cDefaultItemHandler ItemBoneHandler (E_ITEM_BONE); constexpr cDefaultItemHandler ItemBookAndQuillHandler (E_ITEM_BOOK_AND_QUILL); constexpr cDefaultItemHandler ItemBookHandler (E_ITEM_BOOK); constexpr cDefaultItemHandler ItemBookshelfHandler (E_BLOCK_BOOKCASE); constexpr cItemBottleOEnchantingHandler ItemBottleOEnchantingHandler (E_ITEM_BOTTLE_O_ENCHANTING); constexpr cItemBowHandler ItemBowHandler (E_ITEM_BOW); constexpr cDefaultItemHandler ItemBowlHandler (E_ITEM_BOWL); constexpr cItemSimpleFoodHandler ItemBreadHandler (E_ITEM_BREAD, cItemHandler::FoodInfo(5, 6)); constexpr cDefaultItemHandler ItemBrewingStandBlockHandler (E_BLOCK_BREWING_STAND); constexpr cSimplePlaceableItemHandler ItemBrewingStandHandler (E_ITEM_BREWING_STAND, E_BLOCK_BREWING_STAND); constexpr cDefaultItemHandler ItemBrickHandler (E_ITEM_CLAY_BRICK); constexpr cDefaultItemHandler ItemBricksHandler (E_BLOCK_BRICK); constexpr cItemStairsHandler ItemBricksStairsHandler (E_BLOCK_BRICK_STAIRS); constexpr cItemGlazedTerracottaHandler ItemBrownGlazedTerracottaHandler (E_BLOCK_BROWN_GLAZED_TERRACOTTA); constexpr cDefaultItemHandler ItemBrownMushroomBlockHandler (E_BLOCK_BROWN_MUSHROOM); constexpr cDefaultItemHandler ItemBrownShulkerBoxHandler (E_BLOCK_BROWN_SHULKER_BOX); constexpr cItemBucketHandler ItemBucketHandler (E_ITEM_BUCKET); constexpr cDefaultItemHandler ItemCactusHandler (E_BLOCK_CACTUS); constexpr cDefaultItemHandler ItemCakeBlockHandler (E_BLOCK_CAKE); constexpr cSimplePlaceableItemHandler ItemCakeHandler (E_ITEM_CAKE, E_BLOCK_CAKE); constexpr cDefaultItemHandler ItemCarpetHandler (E_BLOCK_CARPET); constexpr cItemFoodSeedsHandler ItemCarrotHandler (E_ITEM_CARROT, cItemHandler::FoodInfo(3, 6.6)); constexpr cDefaultItemHandler ItemCarrotOnStickHandler (E_ITEM_CARROT_ON_STICK); constexpr cDefaultItemHandler ItemCarrotsBlockHandler (E_BLOCK_CARROTS); constexpr cDefaultItemHandler ItemCatDiscHandler (E_ITEM_CAT_DISC); constexpr cDefaultItemHandler ItemCauldronBlockHandler (E_BLOCK_CAULDRON); constexpr cSimplePlaceableItemHandler ItemCauldronHandler (E_ITEM_CAULDRON, E_BLOCK_CAULDRON);; constexpr cItemArmorHandler ItemChainBootsHandler (E_ITEM_CHAIN_BOOTS); constexpr cItemArmorHandler ItemChainChestplateHandler (E_ITEM_CHAIN_CHESTPLATE); constexpr cDefaultItemHandler ItemChainCommandBlockHandler (E_BLOCK_CHAIN_COMMAND_BLOCK); constexpr cItemArmorHandler ItemChainHelmetHandler (E_ITEM_CHAIN_HELMET); constexpr cItemArmorHandler ItemChainLeggingsHandler (E_ITEM_CHAIN_LEGGINGS); constexpr cItemChestHandler ItemChestHandler (E_BLOCK_CHEST); constexpr cItemMinecartHandler ItemChestMinecartHandler (E_ITEM_CHEST_MINECART); constexpr cDefaultItemHandler ItemChirpDiscHandler (E_ITEM_CHIRP_DISC); constexpr cDefaultItemHandler ItemChorusFlowerHandler (E_BLOCK_CHORUS_FLOWER); constexpr cItemChorusFruitHandler ItemChorusFruitHandler (E_ITEM_CHORUS_FRUIT); constexpr cDefaultItemHandler ItemChorusPlantHandler (E_BLOCK_CHORUS_PLANT); constexpr cDefaultItemHandler ItemClayBlockHandler (E_BLOCK_CLAY); constexpr cDefaultItemHandler ItemClayHandler (E_ITEM_CLAY); constexpr cDefaultItemHandler ItemClockHandler (E_ITEM_CLOCK); constexpr cDefaultItemHandler ItemCoalBlockHandler (E_BLOCK_BLOCK_OF_COAL); constexpr cDefaultItemHandler ItemCoalHandler (E_ITEM_COAL); constexpr cDefaultItemHandler ItemCoalOreHandler (E_BLOCK_COAL_ORE); constexpr cDefaultItemHandler ItemCobblestoneHandler (E_BLOCK_COBBLESTONE); constexpr cItemStairsHandler ItemCobblestoneStairsHandler (E_BLOCK_COBBLESTONE_STAIRS); constexpr cDefaultItemHandler ItemCobblestoneWallHandler (E_BLOCK_COBBLESTONE_WALL); constexpr cDefaultItemHandler ItemCobwebHandler (E_BLOCK_COBWEB); constexpr cDefaultItemHandler ItemCocoaPodHandler (E_BLOCK_COCOA_POD); constexpr cDefaultItemHandler ItemCommandBlockHandler (E_BLOCK_COMMAND_BLOCK); constexpr cItemComparatorHandler ItemComparatorHandler (E_ITEM_COMPARATOR); constexpr cDefaultItemHandler ItemCompassHandler (E_ITEM_COMPASS); constexpr cDefaultItemHandler ItemConcreteBlockHandler (E_BLOCK_CONCRETE); constexpr cDefaultItemHandler ItemConcretePowderHandler (E_BLOCK_CONCRETE_POWDER); constexpr cItemSimpleFoodHandler ItemCookedBeefHandler (E_ITEM_STEAK, cItemHandler::FoodInfo(8, 12.8)); constexpr cItemSimpleFoodHandler ItemCookedChickenHandler (E_ITEM_COOKED_CHICKEN, cItemHandler::FoodInfo(6, 7.2)); constexpr cItemCookedFishHandler ItemCookedFishHandler (E_ITEM_COOKED_FISH); constexpr cItemSimpleFoodHandler ItemCookedMuttonHandler (E_ITEM_COOKED_MUTTON, cItemHandler::FoodInfo(6, 9.6)); constexpr cItemSimpleFoodHandler ItemCookedPorkchopHandler (E_ITEM_COOKED_PORKCHOP, cItemHandler::FoodInfo(8, 12.8)); constexpr cItemSimpleFoodHandler ItemCookedRabbitHandler (E_ITEM_COOKED_RABBIT, cItemHandler::FoodInfo(5, 6)); constexpr cItemSimpleFoodHandler ItemCookieHandler (E_ITEM_COOKIE, cItemHandler::FoodInfo(2, 0.5)); constexpr cItemGlazedTerracottaHandler ItemCyanGlazedTerracottaHandler (E_BLOCK_CYAN_GLAZED_TERRACOTTA); constexpr cDefaultItemHandler ItemCyanShulkerBoxHandler (E_BLOCK_CYAN_SHULKER_BOX); constexpr cDefaultItemHandler ItemDandelionHandler (E_BLOCK_DANDELION); constexpr cItemBoatHandler ItemDarkOakBoatHandler (E_ITEM_DARK_OAK_BOAT); constexpr cDefaultItemHandler ItemDarkOakDoorBlockHandler (E_BLOCK_DARK_OAK_DOOR); constexpr cItemDoorHandler ItemDarkOakDoorHandler (E_ITEM_DARK_OAK_DOOR); constexpr cItemFenceGateHandler ItemDarkOakFenceGateHandler (E_BLOCK_DARK_OAK_FENCE_GATE); constexpr cDefaultItemHandler ItemDarkOakFenceHandler (E_BLOCK_DARK_OAK_FENCE); constexpr cItemStairsHandler ItemDarkOakStairsHandler (E_BLOCK_DARK_OAK_WOOD_STAIRS); constexpr cDefaultItemHandler ItemDaylightSensorBlockHandler (E_BLOCK_DAYLIGHT_SENSOR); constexpr cDefaultItemHandler ItemDeadBushHandler (E_BLOCK_DEAD_BUSH); constexpr cItemRailHandler ItemDetectorRailHandler (E_BLOCK_DETECTOR_RAIL); constexpr cItemAxeHandler ItemDiamondAxeHandler (E_ITEM_DIAMOND_AXE); constexpr cDefaultItemHandler ItemDiamondBlockHandler (E_BLOCK_DIAMOND_BLOCK); constexpr cItemArmorHandler ItemDiamondBootsHandler (E_ITEM_DIAMOND_BOOTS); constexpr cItemArmorHandler ItemDiamondChestplateHandler (E_ITEM_DIAMOND_CHESTPLATE); constexpr cDefaultItemHandler ItemDiamondHandler (E_ITEM_DIAMOND); constexpr cItemArmorHandler ItemDiamondHelmetHandler (E_ITEM_DIAMOND_HELMET); constexpr cItemHoeHandler ItemDiamondHoeHandler (E_ITEM_DIAMOND_HOE); constexpr cDefaultItemHandler ItemDiamondHorseArmorHandler (E_ITEM_DIAMOND_HORSE_ARMOR); constexpr cItemArmorHandler ItemDiamondLeggingsHandler (E_ITEM_DIAMOND_LEGGINGS); constexpr cDefaultItemHandler ItemDiamondOreHandler (E_BLOCK_DIAMOND_ORE); constexpr cItemPickaxeHandler ItemDiamondPickaxeHandler (E_ITEM_DIAMOND_PICKAXE); constexpr cItemShovelHandler ItemDiamondShovelHandler (E_ITEM_DIAMOND_SHOVEL); constexpr cItemSwordHandler ItemDiamondSwordHandler (E_ITEM_DIAMOND_SWORD); constexpr cDefaultItemHandler ItemDirtHandler (E_BLOCK_DIRT); constexpr cItemDropSpenserHandler ItemDispenserHandler (E_BLOCK_DISPENSER); constexpr cDefaultItemHandler ItemDoubleOakSlabHandler (E_BLOCK_DOUBLE_WOODEN_SLAB); constexpr cDefaultItemHandler ItemDoubleRedSandstoneSlabHandler (E_BLOCK_DOUBLE_RED_SANDSTONE_SLAB); constexpr cDefaultItemHandler ItemDoubleStoneSlabHandler (E_BLOCK_DOUBLE_STONE_SLAB); constexpr cDefaultItemHandler ItemDragonBreathHandler (E_ITEM_DRAGON_BREATH); constexpr cDefaultItemHandler ItemDragonEggBlockHandler (E_BLOCK_DRAGON_EGG); constexpr cItemDropSpenserHandler ItemDropperHandler (E_BLOCK_DROPPER); constexpr cItemDyeHandler ItemDyeHandler (E_ITEM_DYE); constexpr cItemEggHandler ItemEggHandler (E_ITEM_EGG); constexpr cItemArmorHandler ItemElytraHandler (E_ITEM_ELYTRA); constexpr cDefaultItemHandler ItemEmeraldBlockHandler (E_BLOCK_EMERALD_BLOCK); constexpr cDefaultItemHandler ItemEmeraldHandler (E_ITEM_EMERALD); constexpr cDefaultItemHandler ItemEmeraldOreHandler (E_BLOCK_EMERALD_ORE); constexpr cItemEmptyMapHandler ItemEmptyMapHandler (E_ITEM_EMPTY_MAP); constexpr cDefaultItemHandler ItemEnchantedBookHandler (E_ITEM_ENCHANTED_BOOK); constexpr cItemEnchantingTableHandler ItemEnchantingTableHandler (E_BLOCK_ENCHANTMENT_TABLE); constexpr cDefaultItemHandler ItemEndBricksHandler (E_BLOCK_END_BRICKS); constexpr cItemEndCrystalHandler ItemEndCrystalHandler (E_ITEM_END_CRYSTAL); constexpr cItemEnderChestHandler ItemEnderChestHandler (E_BLOCK_ENDER_CHEST); constexpr cItemEnderPearlHandler ItemEnderPearlHandler (E_ITEM_ENDER_PEARL); constexpr cDefaultItemHandler ItemEndGatewayHandler (E_BLOCK_END_GATEWAY); constexpr cDefaultItemHandler ItemEndPortalBlockHandler (E_BLOCK_END_PORTAL); constexpr cItemEndPortalFrameHandler ItemEndPortalFrameHandler (E_BLOCK_END_PORTAL_FRAME); constexpr cDefaultItemHandler ItemEndRodHandler (E_BLOCK_END_ROD); constexpr cDefaultItemHandler ItemEndStoneBlockHandler (E_BLOCK_END_STONE); constexpr cItemEyeOfEnderHandler ItemEyeOfEnderHandler (E_ITEM_EYE_OF_ENDER); constexpr cDefaultItemHandler ItemFarDiscHandler (E_ITEM_FAR_DISC); constexpr cDefaultItemHandler ItemFarmlandHandler (E_BLOCK_FARMLAND); constexpr cDefaultItemHandler ItemFeatherHandler (E_ITEM_FEATHER); constexpr cDefaultItemHandler ItemFermentedSpiderEyeHandler (E_ITEM_FERMENTED_SPIDER_EYE); constexpr cDefaultItemHandler ItemFireBlockHandler (E_BLOCK_FIRE); constexpr cItemLighterHandler ItemFireChargeHandler (E_ITEM_FIRE_CHARGE); constexpr cItemFireworkHandler ItemFireworkRocketHandler (E_ITEM_FIREWORK_ROCKET); constexpr cDefaultItemHandler ItemFireworkStarHandler (E_ITEM_FIREWORK_STAR); constexpr cItemFishingRodHandler ItemFishingRodHandler (E_ITEM_FISHING_ROD); constexpr cItemLighterHandler ItemFlintAndSteelHandler (E_ITEM_FLINT_AND_STEEL); constexpr cDefaultItemHandler ItemFlintHandler (E_ITEM_FLINT); constexpr cDefaultItemHandler ItemFlowerPotBlockHandler (E_BLOCK_FLOWER_POT); constexpr cSimplePlaceableItemHandler ItemFlowerPotHandler (E_ITEM_FLOWER_POT, E_BLOCK_FLOWER_POT); constexpr cDefaultItemHandler ItemFrostedIceHandler (E_BLOCK_FROSTED_ICE); constexpr cItemFurnaceHandler ItemFurnaceHandler (E_BLOCK_FURNACE); constexpr cItemMinecartHandler ItemFurnaceMinecartHandler (E_ITEM_FURNACE_MINECART); constexpr cDefaultItemHandler ItemGhastTearHandler (E_ITEM_GHAST_TEAR); constexpr cItemBottleHandler ItemGlassBottleHandler (E_ITEM_GLASS_BOTTLE); constexpr cDefaultItemHandler ItemGlassHandler (E_BLOCK_GLASS); constexpr cDefaultItemHandler ItemGlassPaneHandler (E_BLOCK_GLASS_PANE); constexpr cDefaultItemHandler ItemGlisteringMelonHandler (E_ITEM_GLISTERING_MELON); constexpr cDefaultItemHandler ItemGlowstoneBlockHandler (E_BLOCK_GLOWSTONE); constexpr cDefaultItemHandler ItemGlowstoneDustHandler (E_ITEM_GLOWSTONE_DUST); constexpr cDefaultItemHandler ItemGoldBlockHandler (E_BLOCK_GOLD_BLOCK); constexpr cItemGoldenAppleHandler ItemGoldenAppleHandler (E_ITEM_GOLDEN_APPLE); constexpr cItemAxeHandler ItemGoldenAxeHandler (E_ITEM_GOLD_AXE); constexpr cItemArmorHandler ItemGoldenBootsHandler (E_ITEM_GOLD_BOOTS); constexpr cItemSimpleFoodHandler ItemGoldenCarrotHandler (E_ITEM_GOLDEN_CARROT, cItemHandler::FoodInfo(6, 14.4)); constexpr cItemArmorHandler ItemGoldenChestplateHandler (E_ITEM_GOLD_CHESTPLATE); constexpr cItemArmorHandler ItemGoldenHelmetHandler (E_ITEM_GOLD_HELMET); constexpr cItemHoeHandler ItemGoldenHoeHandler (E_ITEM_GOLD_HOE); constexpr cDefaultItemHandler ItemGoldenHorseArmorHandler (E_ITEM_GOLD_HORSE_ARMOR); constexpr cItemArmorHandler ItemGoldenLeggingsHandler (E_ITEM_GOLD_LEGGINGS); constexpr cItemPickaxeHandler ItemGoldenPickaxeHandler (E_ITEM_GOLD_PICKAXE); constexpr cItemShovelHandler ItemGoldenShovelHandler (E_ITEM_GOLD_SHOVEL); constexpr cItemSwordHandler ItemGoldenSwordHandler (E_ITEM_GOLD_SWORD); constexpr cDefaultItemHandler ItemGoldHandler (E_ITEM_GOLD); constexpr cDefaultItemHandler ItemGoldNuggetHandler (E_ITEM_GOLD_NUGGET); constexpr cDefaultItemHandler ItemGoldOreHandler (E_BLOCK_GOLD_ORE); constexpr cDefaultItemHandler ItemGrassBlockHandler (E_BLOCK_GRASS); constexpr cDefaultItemHandler ItemGrassPathHandler (E_BLOCK_GRASS_PATH); constexpr cDefaultItemHandler ItemGravelHandler (E_BLOCK_GRAVEL); constexpr cItemGlazedTerracottaHandler ItemGrayGlazedTerracottaHandler (E_BLOCK_GRAY_GLAZED_TERRACOTTA); constexpr cDefaultItemHandler ItemGrayShulkerBoxHandler (E_BLOCK_GRAY_SHULKER_BOX); constexpr cItemGlazedTerracottaHandler ItemGreenGlazedTerracottaHandler (E_BLOCK_GREEN_GLAZED_TERRACOTTA); constexpr cDefaultItemHandler ItemGreenShulkerBoxHandler (E_BLOCK_GREEN_SHULKER_BOX); constexpr cDefaultItemHandler ItemGunpowderHandler (E_ITEM_GUNPOWDER); constexpr cDefaultItemHandler ItemHardenedClayHandler (E_BLOCK_HARDENED_CLAY); constexpr cItemSidewaysHandler ItemHayBaleHandler (E_BLOCK_HAY_BALE); constexpr cDefaultItemHandler ItemHeadBlockHandler (E_BLOCK_HEAD); constexpr cItemMobHeadHandler ItemHeadHandler (E_ITEM_HEAD); constexpr cDefaultItemHandler ItemHeavyWeightedPressurePlateHandler (E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE); constexpr cItemHopperHandler ItemHopperHandler (E_BLOCK_HOPPER); constexpr cDefaultItemHandler ItemHugeBrownMushroomBlockHandler (E_BLOCK_HUGE_BROWN_MUSHROOM); constexpr cDefaultItemHandler ItemHugeRedMushroomBlockHandler (E_BLOCK_HUGE_RED_MUSHROOM); constexpr cDefaultItemHandler ItemIceHandler (E_BLOCK_ICE); constexpr cDefaultItemHandler ItemInactiveComparatorHandler (E_BLOCK_INACTIVE_COMPARATOR); constexpr cDefaultItemHandler ItemInvertedDaylightSensorHandler (E_BLOCK_INVERTED_DAYLIGHT_SENSOR); constexpr cItemAxeHandler ItemIronAxeHandler (E_ITEM_IRON_AXE); constexpr cDefaultItemHandler ItemIronBarsBlockHandler (E_BLOCK_IRON_BARS); constexpr cDefaultItemHandler ItemIronBlockHandler (E_BLOCK_IRON_BLOCK); constexpr cItemArmorHandler ItemIronBootsHandler (E_ITEM_IRON_BOOTS); constexpr cItemArmorHandler ItemIronChestplateHandler (E_ITEM_IRON_CHESTPLATE); constexpr cDefaultItemHandler ItemIronDoorBlockHandler (E_BLOCK_IRON_DOOR); constexpr cItemDoorHandler ItemIronDoorHandler (E_ITEM_IRON_DOOR); constexpr cDefaultItemHandler ItemIronHandler (E_ITEM_IRON); constexpr cItemArmorHandler ItemIronHelmetHandler (E_ITEM_IRON_HELMET); constexpr cItemHoeHandler ItemIronHoeHandler (E_ITEM_IRON_HOE); constexpr cDefaultItemHandler ItemIronHorseArmorHandler (E_ITEM_IRON_HORSE_ARMOR); constexpr cItemArmorHandler ItemIronLeggingsHandler (E_ITEM_IRON_LEGGINGS); constexpr cDefaultItemHandler ItemIronNuggetHandler (E_ITEM_IRON_NUGGET); constexpr cDefaultItemHandler ItemIronOreHandler (E_BLOCK_IRON_ORE); constexpr cItemPickaxeHandler ItemIronPickaxeHandler (E_ITEM_IRON_PICKAXE); constexpr cItemShovelHandler ItemIronShovelHandler (E_ITEM_IRON_SHOVEL); constexpr cItemSwordHandler ItemIronSwordHandler (E_ITEM_IRON_SWORD); constexpr cItemTrapdoorHandler ItemIronTrapdoorHandler (E_BLOCK_IRON_TRAPDOOR); constexpr cItemItemFrameHandler ItemItemFrameHandler (E_ITEM_ITEM_FRAME); constexpr cItemJackOLanternHandler ItemJackOLanternHandler (E_BLOCK_JACK_O_LANTERN); constexpr cDefaultItemHandler ItemJukeboxHandler (E_BLOCK_JUKEBOX); constexpr cItemBoatHandler ItemJungleBoatHandler (E_ITEM_JUNGLE_BOAT); constexpr cDefaultItemHandler ItemJungleDoorBlockHandler (E_BLOCK_JUNGLE_DOOR); constexpr cItemDoorHandler ItemJungleDoorHandler (E_ITEM_JUNGLE_DOOR); constexpr cItemFenceGateHandler ItemJungleFenceGateHandler (E_BLOCK_JUNGLE_FENCE_GATE); constexpr cDefaultItemHandler ItemJungleFenceHandler (E_BLOCK_JUNGLE_FENCE); constexpr cItemStairsHandler ItemJungleStairsHandler (E_BLOCK_JUNGLE_WOOD_STAIRS); constexpr cItemLadderHandler ItemLadderHandler (E_BLOCK_LADDER); constexpr cDefaultItemHandler ItemLapisBlockHandler (E_BLOCK_LAPIS_BLOCK); constexpr cDefaultItemHandler ItemLapisOreHandler (E_BLOCK_LAPIS_ORE); constexpr cItemBucketHandler ItemLavaBucketHandler (E_ITEM_LAVA_BUCKET); constexpr cDefaultItemHandler ItemLavaHandler (E_BLOCK_LAVA); constexpr cDefaultItemHandler ItemLeashHandler (E_ITEM_LEAD); constexpr cItemArmorHandler ItemLeatherBootsHandler (E_ITEM_LEATHER_BOOTS); constexpr cItemArmorHandler ItemLeatherCapHandler (E_ITEM_LEATHER_CAP); constexpr cDefaultItemHandler ItemLeatherHandler (E_ITEM_LEATHER); constexpr cItemArmorHandler ItemLeatherPantsHandler (E_ITEM_LEATHER_PANTS); constexpr cItemArmorHandler ItemLeatherTunicHandler (E_ITEM_LEATHER_TUNIC); constexpr cItemLeavesHandler ItemLeavesHandler (E_BLOCK_LEAVES); constexpr cItemLeverHandler ItemLeverHandler (E_BLOCK_LEVER); constexpr cItemGlazedTerracottaHandler ItemLightBlueGlazedTerracottaHandler (E_BLOCK_LIGHT_BLUE_GLAZED_TERRACOTTA); constexpr cDefaultItemHandler ItemLightBlueShulkerBoxHandler (E_BLOCK_LIGHT_BLUE_SHULKER_BOX); constexpr cItemGlazedTerracottaHandler ItemLightGrayGlazedTerracottaHandler (E_BLOCK_LIGHT_GRAY_GLAZED_TERRACOTTA); constexpr cDefaultItemHandler ItemLightGrayShulkerBoxHandler (E_BLOCK_LIGHT_GRAY_SHULKER_BOX); constexpr cDefaultItemHandler ItemLightWeightedPressurePlateHandler (E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE); constexpr cItemLilypadHandler ItemLilypadHandler (E_BLOCK_LILY_PAD); constexpr cItemGlazedTerracottaHandler ItemLimeGlazedTerracottaHandler (E_BLOCK_LIME_GLAZED_TERRACOTTA); constexpr cDefaultItemHandler ItemLimeShulkerBoxHandler (E_BLOCK_LIME_SHULKER_BOX); constexpr cItemPotionHandler ItemLingeringPotionHandler (E_ITEM_LINGERING_POTION); constexpr cDefaultItemHandler ItemLitFurnaceHandler (E_BLOCK_LIT_FURNACE); constexpr cItemSidewaysHandler ItemLogHandler (E_BLOCK_LOG); constexpr cItemGlazedTerracottaHandler ItemMagentaGlazedTerracottaHandler (E_BLOCK_MAGENTA_GLAZED_TERRACOTTA); constexpr cDefaultItemHandler ItemMagentaShulkerBoxHandler (E_BLOCK_MAGENTA_SHULKER_BOX); constexpr cDefaultItemHandler ItemMagmaBlockHandler (E_BLOCK_MAGMA); constexpr cDefaultItemHandler ItemMagmaCreamHandler (E_ITEM_MAGMA_CREAM); constexpr cDefaultItemHandler ItemMallDiscHandler (E_ITEM_MALL_DISC); constexpr cItemMapHandler ItemMapHandler (E_ITEM_MAP); constexpr cDefaultItemHandler ItemMellohiDiscHandler (E_ITEM_MELLOHI_DISC); constexpr cDefaultItemHandler ItemMelonBlockHandler (E_BLOCK_MELON); constexpr cItemSimpleSeedsHandler ItemMelonSeedsHandler (E_ITEM_MELON_SEEDS); constexpr cItemSimpleFoodHandler ItemMelonSliceHandler (E_ITEM_MELON_SLICE, cItemHandler::FoodInfo(2, 1.2)); constexpr cDefaultItemHandler ItemMelonStemHandler (E_BLOCK_MELON_STEM); constexpr cItemMilkHandler ItemMilkHandler (E_ITEM_MILK); constexpr cItemMinecartHandler ItemMinecartHandler (E_ITEM_MINECART); constexpr cItemMinecartHandler ItemMinecartWithCommandBlockHandler (E_ITEM_MINECART_WITH_COMMAND_BLOCK); constexpr cItemMinecartHandler ItemMinecartWithHopperHandler (E_ITEM_MINECART_WITH_HOPPER); constexpr cItemMinecartHandler ItemMinecartWithTNTHandler (E_ITEM_MINECART_WITH_TNT); constexpr cDefaultItemHandler ItemMobSpawnerBlockHandler (E_BLOCK_MOB_SPAWNER); constexpr cDefaultItemHandler ItemMossyCobblestoneHandler (E_BLOCK_MOSSY_COBBLESTONE); constexpr cItemSoupHandler ItemMushroomSoupHandler (E_ITEM_MUSHROOM_SOUP, cItemHandler::FoodInfo(6, 7.2)); constexpr cDefaultItemHandler ItemMyceliumHandler (E_BLOCK_MYCELIUM); constexpr cDefaultItemHandler ItemNameTagHandler (E_ITEM_NAME_TAG); constexpr cDefaultItemHandler ItemNetherBrickFenceHandler (E_BLOCK_NETHER_BRICK_FENCE); constexpr cDefaultItemHandler ItemNetherBrickHandler (E_ITEM_NETHER_BRICK); constexpr cDefaultItemHandler ItemNetherBricksHandler (E_BLOCK_NETHER_BRICK); constexpr cItemStairsHandler ItemNetherBrickStairsHandler (E_BLOCK_NETHER_BRICK_STAIRS); constexpr cDefaultItemHandler ItemNetherPortalBlockHandler (E_BLOCK_NETHER_PORTAL); constexpr cDefaultItemHandler ItemNetherQuartzHandler (E_ITEM_NETHER_QUARTZ); constexpr cDefaultItemHandler ItemNetherQuartzOreHandler (E_BLOCK_NETHER_QUARTZ_ORE); constexpr cDefaultItemHandler ItemNetherrackHandler (E_BLOCK_NETHERRACK); constexpr cDefaultItemHandler ItemNetherStarHandler (E_ITEM_NETHER_STAR); constexpr cDefaultItemHandler ItemNetherWartBlockHandler (E_BLOCK_NETHER_WART_BLOCK); constexpr cItemNetherWartHandler ItemNetherWartHandler (E_ITEM_NETHER_WART); constexpr cDefaultItemHandler ItemNetherWartTechnicalBlockHandler (E_BLOCK_NETHER_WART); constexpr cItemLeavesHandler ItemNewLeavesHandler (E_BLOCK_NEW_LEAVES); constexpr cItemSidewaysHandler ItemNewLogHandler (E_BLOCK_NEW_LOG); constexpr cDefaultItemHandler ItemNoteBlockHandler (E_BLOCK_NOTE_BLOCK); constexpr cItemBoatHandler ItemOakBoatHandler (E_ITEM_BOAT); constexpr cItemButtonHandler ItemOakButtonHandler (E_BLOCK_WOODEN_BUTTON); constexpr cDefaultItemHandler ItemOakDoorBlockHandler (E_BLOCK_OAK_DOOR); constexpr cItemDoorHandler ItemOakDoorHandler (E_ITEM_WOODEN_DOOR); constexpr cItemFenceGateHandler ItemOakFenceGateHandler (E_BLOCK_OAK_FENCE_GATE); constexpr cDefaultItemHandler ItemOakFenceHandler (E_BLOCK_FENCE); constexpr cItemSlabHandler ItemOakSlabHandler (E_BLOCK_WOODEN_SLAB); constexpr cItemStairsHandler ItemOakStairsHandler (E_BLOCK_OAK_WOOD_STAIRS); constexpr cItemTrapdoorHandler ItemOakTrapdoorHandler (E_BLOCK_TRAPDOOR); constexpr cItemObserverHandler ItemObserverHandler (E_BLOCK_OBSERVER); constexpr cDefaultItemHandler ItemObsidianHandler (E_BLOCK_OBSIDIAN); constexpr cItemGlazedTerracottaHandler ItemOrangeGlazedTerracottaHandler (E_BLOCK_ORANGE_GLAZED_TERRACOTTA); constexpr cDefaultItemHandler ItemOrangeShulkerBoxHandler (E_BLOCK_ORANGE_SHULKER_BOX); constexpr cDefaultItemHandler ItemPackedIceHandler (E_BLOCK_PACKED_ICE); constexpr cItemPaintingHandler ItemPaintingHandler (E_ITEM_PAINTING); constexpr cDefaultItemHandler ItemPaperHandler (E_ITEM_PAPER); constexpr cItemGlazedTerracottaHandler ItemPinkGlazedTerracottaHandler (E_BLOCK_PINK_GLAZED_TERRACOTTA); constexpr cDefaultItemHandler ItemPinkShulkerBoxHandler (E_BLOCK_PINK_SHULKER_BOX); constexpr cDefaultItemHandler ItemPistonExtensionHandler (E_BLOCK_PISTON_EXTENSION); constexpr cItemPistonHandler ItemPistonHandler (E_BLOCK_PISTON); constexpr cDefaultItemHandler ItemPistonMovedBlockHandler (E_BLOCK_PISTON_MOVED_BLOCK); constexpr cItemPlanksHandler ItemPlanksHandler (E_BLOCK_PLANKS); constexpr cItemPoisonousPotatoHandler ItemPoisonousPotatoHandler (E_ITEM_POISONOUS_POTATO); constexpr cDefaultItemHandler ItemPoppedChorusFruitHandler (E_ITEM_POPPED_CHORUS_FRUIT); constexpr cDefaultItemHandler ItemPoppyHandler (E_BLOCK_FLOWER); constexpr cDefaultItemHandler ItemPotatoesBlockHandler (E_BLOCK_POTATOES); constexpr cItemFoodSeedsHandler ItemPotatoHandler (E_ITEM_POTATO, cItemHandler::FoodInfo(1, 0.6)); constexpr cItemPotionHandler ItemPotionHandler (E_ITEM_POTION); constexpr cItemRailHandler ItemPoweredRailHandler (E_BLOCK_POWERED_RAIL); constexpr cDefaultItemHandler ItemPrismarineBlockHandler (E_BLOCK_PRISMARINE_BLOCK); constexpr cDefaultItemHandler ItemPrismarineCrystalsHandler (E_ITEM_PRISMARINE_CRYSTALS); constexpr cDefaultItemHandler ItemPrismarineShardHandler (E_ITEM_PRISMARINE_SHARD); constexpr cItemPumpkinHandler ItemPumpkinHandler (E_BLOCK_PUMPKIN); constexpr cItemSimpleFoodHandler ItemPumpkinPieHandler (E_ITEM_PUMPKIN_PIE, cItemHandler::FoodInfo(8, 4.8)); constexpr cItemSimpleSeedsHandler ItemPumpkinSeedsHandler (E_ITEM_PUMPKIN_SEEDS); constexpr cDefaultItemHandler ItemPumpkinStemHandler (E_BLOCK_PUMPKIN_STEM); constexpr cItemGlazedTerracottaHandler ItemPurpleGlazedTerracottaHandler (E_BLOCK_PURPLE_GLAZED_TERRACOTTA); constexpr cDefaultItemHandler ItemPurpleShulkerBoxHandler (E_BLOCK_PURPLE_SHULKER_BOX); constexpr cDefaultItemHandler ItemPurpurBlockHandler (E_BLOCK_PURPUR_BLOCK); constexpr cDefaultItemHandler ItemPurpurDoubleSlabHandler (E_BLOCK_PURPUR_DOUBLE_SLAB); constexpr cDefaultItemHandler ItemPurpurPillarHandler (E_BLOCK_PURPUR_PILLAR); constexpr cItemSlabHandler ItemPurpurSlabHandler (E_BLOCK_PURPUR_SLAB); constexpr cItemStairsHandler ItemPurpurStairsHandler (E_BLOCK_PURPUR_STAIRS); constexpr cItemQuartzHandler ItemQuartzBlockHandler (E_BLOCK_QUARTZ_BLOCK); constexpr cItemStairsHandler ItemQuartzStairsHandler (E_BLOCK_QUARTZ_STAIRS); constexpr cDefaultItemHandler ItemRabbitHideHandler (E_ITEM_RABBIT_HIDE); constexpr cDefaultItemHandler ItemRabbitsFootHandler (E_ITEM_RABBITS_FOOT); constexpr cItemSoupHandler ItemRabbitStewHandler (E_ITEM_RABBIT_STEW, cItemHandler::FoodInfo(10, 12)); constexpr cItemRailHandler ItemRailHandler (E_BLOCK_RAIL); constexpr cItemSimpleFoodHandler ItemRawBeefHandler (E_ITEM_RAW_BEEF, cItemHandler::FoodInfo(3, 1.8)); constexpr cItemRawChickenHandler ItemRawChickenHandler (E_ITEM_RAW_CHICKEN); constexpr cItemRawFishHandler ItemRawFishHandler (E_ITEM_RAW_FISH); constexpr cItemSimpleFoodHandler ItemRawMuttonHandler (E_ITEM_RAW_MUTTON, cItemHandler::FoodInfo(2, 1.2)); constexpr cItemSimpleFoodHandler ItemRawPorkchopHandler (E_ITEM_RAW_PORKCHOP, cItemHandler::FoodInfo(3, 1.8)); constexpr cItemSimpleFoodHandler ItemRawRabbitHandler (E_ITEM_RAW_RABBIT, cItemHandler::FoodInfo(3, 1.8)); constexpr cItemGlazedTerracottaHandler ItemRedGlazedTerracottaHandler (E_BLOCK_RED_GLAZED_TERRACOTTA); constexpr cDefaultItemHandler ItemRedMushroomBlockHandler (E_BLOCK_RED_MUSHROOM); constexpr cDefaultItemHandler ItemRedNetherBricksHandler (E_BLOCK_RED_NETHER_BRICK); constexpr cDefaultItemHandler ItemRedSandstoneHandler (E_BLOCK_RED_SANDSTONE); constexpr cItemSlabHandler ItemRedSandstoneSlabHandler (E_BLOCK_RED_SANDSTONE_SLAB); constexpr cItemStairsHandler ItemRedSandstoneStairsHandler (E_BLOCK_RED_SANDSTONE_STAIRS); constexpr cDefaultItemHandler ItemRedShulkerBoxHandler (E_BLOCK_RED_SHULKER_BOX); constexpr cDefaultItemHandler ItemRedstoneBlockHandler (E_BLOCK_BLOCK_OF_REDSTONE); constexpr cItemRedstoneDustHandler ItemRedstoneDustHandler (E_ITEM_REDSTONE_DUST); constexpr cDefaultItemHandler ItemRedstoneLampOffHandler (E_BLOCK_REDSTONE_LAMP_OFF); constexpr cDefaultItemHandler ItemRedstoneLampOnHandler (E_BLOCK_REDSTONE_LAMP_ON); constexpr cDefaultItemHandler ItemRedstoneOreGlowingHandler (E_BLOCK_REDSTONE_ORE_GLOWING); constexpr cDefaultItemHandler ItemRedstoneOreHandler (E_BLOCK_REDSTONE_ORE); constexpr cItemRedstoneRepeaterHandler ItemRedstoneRepeaterHandler (E_ITEM_REDSTONE_REPEATER); constexpr cDefaultItemHandler ItemRedstoneRepeaterOffHandler (E_BLOCK_REDSTONE_REPEATER_OFF); constexpr cDefaultItemHandler ItemRedstoneRepeaterOnHandler (E_BLOCK_REDSTONE_REPEATER_ON); constexpr cItemTorchHandler ItemRedstoneTorchHandler (E_BLOCK_REDSTONE_TORCH_ON); constexpr cDefaultItemHandler ItemRedstoneTorchOffBlockHandler (E_BLOCK_REDSTONE_TORCH_OFF); constexpr cDefaultItemHandler ItemRedstoneWireHandler (E_BLOCK_REDSTONE_WIRE); constexpr cDefaultItemHandler ItemRepeatingCommandBlockHandler (E_BLOCK_REPEATING_COMMAND_BLOCK); constexpr cItemRottenFleshHandler ItemRottenFleshHandler (E_ITEM_ROTTEN_FLESH); constexpr cDefaultItemHandler ItemSaddleHandler (E_ITEM_SADDLE); constexpr cDefaultItemHandler ItemSandHandler (E_BLOCK_SAND); constexpr cDefaultItemHandler ItemSandstoneHandler (E_BLOCK_SANDSTONE); constexpr cItemStairsHandler ItemSandstoneStairsHandler (E_BLOCK_SANDSTONE_STAIRS); constexpr cItemSaplingHandler ItemSaplingHandler (E_BLOCK_SAPLING); constexpr cDefaultItemHandler ItemSeaLanternHandler (E_BLOCK_SEA_LANTERN); constexpr cItemSimpleSeedsHandler ItemSeedsHandler (E_ITEM_SEEDS); constexpr cItemShearsHandler ItemShearsHandler (E_ITEM_SHEARS); constexpr cDefaultItemHandler ItemShieldHandler (E_ITEM_SHIELD); constexpr cDefaultItemHandler ItemShulkerShellHandler (E_ITEM_SHULKER_SHELL); constexpr cItemSignHandler ItemSignHandler (E_ITEM_SIGN); constexpr cDefaultItemHandler ItemSignPostHandler (E_BLOCK_SIGN_POST); constexpr cDefaultItemHandler ItemSilverfishEggBlockHandler (E_BLOCK_SILVERFISH_EGG); constexpr cDefaultItemHandler ItemSlimeballHandler (E_ITEM_SLIMEBALL); constexpr cDefaultItemHandler ItemSlimeBlockHandler (E_BLOCK_SLIME_BLOCK); constexpr cItemSnowballHandler ItemSnowballHandler (E_ITEM_SNOWBALL); constexpr cDefaultItemHandler ItemSnowBlockHandler (E_BLOCK_SNOW_BLOCK); constexpr cItemSnowHandler ItemSnowHandler (E_BLOCK_SNOW); constexpr cDefaultItemHandler ItemSoulsandHandler (E_BLOCK_SOULSAND); constexpr cItemSpawnEggHandler ItemSpawnEggHandler (E_ITEM_SPAWN_EGG); constexpr cDefaultItemHandler ItemSpectralArrowHandler (E_ITEM_SPECTRAL_ARROW); constexpr cItemSpiderEyeHandler ItemSpiderEyeHandler (E_ITEM_SPIDER_EYE); constexpr cItemPotionHandler ItemSplashPotionHandler (E_ITEM_SPLASH_POTION); constexpr cDefaultItemHandler ItemSpongeHandler (E_BLOCK_SPONGE); constexpr cItemBoatHandler ItemSpruceBoatHandler (E_ITEM_SPRUCE_BOAT); constexpr cDefaultItemHandler ItemSpruceDoorBlockHandler (E_BLOCK_SPRUCE_DOOR); constexpr cItemDoorHandler ItemSpruceDoorHandler (E_ITEM_SPRUCE_DOOR); constexpr cItemFenceGateHandler ItemSpruceFenceGateHandler (E_BLOCK_SPRUCE_FENCE_GATE); constexpr cDefaultItemHandler ItemSpruceFenceHandler (E_BLOCK_SPRUCE_FENCE); constexpr cItemStairsHandler ItemSpruceStairsHandler (E_BLOCK_SPRUCE_WOOD_STAIRS); constexpr cDefaultItemHandler ItemStainedGlassHandler (E_BLOCK_STAINED_GLASS); constexpr cDefaultItemHandler ItemStainedGlassPaneHandler (E_BLOCK_STAINED_GLASS_PANE); constexpr cDefaultItemHandler ItemStalDiscHandler (E_ITEM_STAL_DISC); constexpr cDefaultItemHandler ItemStandingBannerHandler (E_BLOCK_STANDING_BANNER); constexpr cDefaultItemHandler ItemStationaryLavaHandler (E_BLOCK_STATIONARY_LAVA); constexpr cDefaultItemHandler ItemStationaryWaterHandler (E_BLOCK_STATIONARY_WATER); constexpr cDefaultItemHandler ItemStickHandler (E_ITEM_STICK); constexpr cItemPistonHandler ItemStickyPistonHandler (E_BLOCK_STICKY_PISTON); constexpr cItemAxeHandler ItemStoneAxeHandler (E_ITEM_STONE_AXE); constexpr cDefaultItemHandler ItemStoneBricksHandler (E_BLOCK_STONE_BRICKS); constexpr cItemStairsHandler ItemStoneBrickStairsHandler (E_BLOCK_STONE_BRICK_STAIRS); constexpr cItemButtonHandler ItemStoneButtonHandler (E_BLOCK_STONE_BUTTON); constexpr cDefaultItemHandler ItemStoneHandler (E_BLOCK_STONE); constexpr cItemHoeHandler ItemStoneHoeHandler (E_ITEM_STONE_HOE); constexpr cItemPickaxeHandler ItemStonePickaxeHandler (E_ITEM_STONE_PICKAXE); constexpr cDefaultItemHandler ItemStonePressurePlateHandler (E_BLOCK_STONE_PRESSURE_PLATE); constexpr cItemShovelHandler ItemStoneShovelHandler (E_ITEM_STONE_SHOVEL); constexpr cItemSlabHandler ItemStoneSlabHandler (E_BLOCK_STONE_SLAB); constexpr cItemSwordHandler ItemStoneSwordHandler (E_ITEM_STONE_SWORD); constexpr cDefaultItemHandler ItemStradDiscHandler (E_ITEM_STRAD_DISC); constexpr cSimplePlaceableItemHandler ItemStringHandler (E_ITEM_STRING, E_BLOCK_TRIPWIRE); constexpr cDefaultItemHandler ItemStructureBlockHandler (E_BLOCK_STRUCTURE_BLOCK); constexpr cDefaultItemHandler ItemStructureVoidHandler (E_BLOCK_STRUCTURE_VOID); constexpr cDefaultItemHandler ItemSugarCaneBlockHandler (E_BLOCK_SUGARCANE); constexpr cSimplePlaceableItemHandler ItemSugarCaneHandler (E_ITEM_SUGARCANE, E_BLOCK_SUGARCANE); constexpr cDefaultItemHandler ItemSugarHandler (E_ITEM_SUGAR); constexpr cDefaultItemHandler ItemTallGrassHandler (E_BLOCK_TALL_GRASS); constexpr cDefaultItemHandler ItemTerracottaHandler (E_BLOCK_TERRACOTTA); constexpr cDefaultItemHandler ItemTippedArrowHandler (E_ITEM_TIPPED_ARROW); constexpr cDefaultItemHandler ItemTNTHandler (E_BLOCK_TNT); constexpr cItemTorchHandler ItemTorchHandler (E_BLOCK_TORCH); constexpr cDefaultItemHandler ItemTotemOfUndyingHandler (E_ITEM_TOTEM_OF_UNDYING); constexpr cItemChestHandler ItemTrappedChestHandler (E_BLOCK_TRAPPED_CHEST); constexpr cDefaultItemHandler ItemTripwireHandler (E_BLOCK_TRIPWIRE); constexpr cItemTripwireHookHandler ItemTripwireHookHandler (E_BLOCK_TRIPWIRE_HOOK); constexpr cItemVinesHandler ItemVinesHandler (E_BLOCK_VINES); constexpr cDefaultItemHandler ItemWaitDiscHandler (E_ITEM_WAIT_DISC); constexpr cDefaultItemHandler ItemWallBannerHandler (E_BLOCK_WALL_BANNER); constexpr cDefaultItemHandler ItemWallsignHandler (E_BLOCK_WALLSIGN); constexpr cDefaultItemHandler ItemWardDiscHandler (E_ITEM_WARD_DISC); constexpr cItemBucketHandler ItemWaterBucketHandler (E_ITEM_WATER_BUCKET); constexpr cDefaultItemHandler ItemWaterHandler (E_BLOCK_WATER); constexpr cDefaultItemHandler ItemWheatBlockHandler (E_BLOCK_WHEAT); constexpr cDefaultItemHandler ItemWheatHandler (E_ITEM_WHEAT); constexpr cItemGlazedTerracottaHandler ItemWhiteGlazedTerracottaHandler (E_BLOCK_WHITE_GLAZED_TERRACOTTA); constexpr cDefaultItemHandler ItemWhiteShulkerBoxHandler (E_BLOCK_WHITE_SHULKER_BOX); constexpr cItemAxeHandler ItemWoodenAxeHandler (E_ITEM_WOODEN_AXE); constexpr cItemHoeHandler ItemWoodenHoeHandler (E_ITEM_WOODEN_HOE); constexpr cItemPickaxeHandler ItemWoodenPickaxeHandler (E_ITEM_WOODEN_PICKAXE); constexpr cDefaultItemHandler ItemWoodenPressurePlateHandler (E_BLOCK_WOODEN_PRESSURE_PLATE); constexpr cItemShovelHandler ItemWoodenShovelHandler (E_ITEM_WOODEN_SHOVEL); constexpr cItemSwordHandler ItemWoodenSwordHandler (E_ITEM_WOODEN_SWORD); constexpr cItemClothHandler ItemWoolHandler (E_BLOCK_WOOL); constexpr cDefaultItemHandler ItemWorkbenchHandler (E_BLOCK_WORKBENCH); constexpr cDefaultItemHandler ItemWrittenBookHandler (E_ITEM_WRITTEN_BOOK); constexpr cItemGlazedTerracottaHandler ItemYellowGlazedTerracottaHandler (E_BLOCK_YELLOW_GLAZED_TERRACOTTA); constexpr cDefaultItemHandler ItemYellowShulkerBoxHandler (E_BLOCK_YELLOW_SHULKER_BOX); } const cItemHandler & cItemHandler::For(int a_ItemType) { switch (a_ItemType) { case E_BLOCK_ACACIA_DOOR: return ItemAcaciaDoorBlockHandler; case E_BLOCK_ACACIA_FENCE: return ItemAcaciaFenceHandler; case E_BLOCK_ACACIA_FENCE_GATE: return ItemAcaciaFenceGateHandler; case E_BLOCK_ACACIA_WOOD_STAIRS: return ItemAcaciaStairsHandler; case E_BLOCK_ACTIVATOR_RAIL: return ItemActivatorRailHandler; case E_BLOCK_ACTIVE_COMPARATOR: return ItemActiveComparatorHandler; case E_BLOCK_AIR: return ItemAirHandler; case E_BLOCK_ANVIL: return ItemAnvilHandler; case E_BLOCK_BARRIER: return ItemBarrierHandler; case E_BLOCK_BEACON: return ItemBeaconHandler; case E_BLOCK_BED: return ItemBedBlockHandler; case E_BLOCK_BEDROCK: return ItemBedrockHandler; case E_BLOCK_BEETROOTS: return ItemBeetrootsBlockHandler; case E_BLOCK_BIG_FLOWER: return ItemBigFlowerHandler; case E_BLOCK_BIRCH_DOOR: return ItemBirchDoorBlockHandler; case E_BLOCK_BIRCH_FENCE: return ItemBirchFenceHandler; case E_BLOCK_BIRCH_FENCE_GATE: return ItemBirchFenceGateHandler; case E_BLOCK_BIRCH_WOOD_STAIRS: return ItemBirchStairsHandler; case E_BLOCK_BLACK_GLAZED_TERRACOTTA: return ItemBlackGlazedTerracottaHandler; case E_BLOCK_BLACK_SHULKER_BOX: return ItemBlackShulkerBoxHandler; case E_BLOCK_BLOCK_OF_COAL: return ItemCoalBlockHandler; case E_BLOCK_BLOCK_OF_REDSTONE: return ItemRedstoneBlockHandler; case E_BLOCK_BLUE_GLAZED_TERRACOTTA: return ItemBlueGlazedTerracottaHandler; case E_BLOCK_BLUE_SHULKER_BOX: return ItemBlueShulkerBoxHandler; case E_BLOCK_BONE_BLOCK: return ItemBoneBlockHandler; case E_BLOCK_BOOKCASE: return ItemBookshelfHandler; case E_BLOCK_BREWING_STAND: return ItemBrewingStandBlockHandler; case E_BLOCK_BRICK: return ItemBrickHandler; case E_BLOCK_BRICK_STAIRS: return ItemBricksStairsHandler; case E_BLOCK_BROWN_GLAZED_TERRACOTTA: return ItemBrownGlazedTerracottaHandler; case E_BLOCK_BROWN_MUSHROOM: return ItemBrownMushroomBlockHandler; case E_BLOCK_BROWN_SHULKER_BOX: return ItemBrownShulkerBoxHandler; case E_BLOCK_CACTUS: return ItemCactusHandler; case E_BLOCK_CAKE: return ItemCakeBlockHandler; case E_BLOCK_CARPET: return ItemCarpetHandler; case E_BLOCK_CARROTS: return ItemCarrotsBlockHandler; case E_BLOCK_CAULDRON: return ItemCauldronBlockHandler; case E_BLOCK_CHAIN_COMMAND_BLOCK: return ItemChainCommandBlockHandler; case E_BLOCK_CHEST: return ItemChestHandler; case E_BLOCK_CHORUS_FLOWER: return ItemChorusFlowerHandler; case E_BLOCK_CHORUS_PLANT: return ItemChorusPlantHandler; case E_BLOCK_CLAY: return ItemClayBlockHandler; case E_BLOCK_COAL_ORE: return ItemCoalOreHandler; case E_BLOCK_COBBLESTONE: return ItemCobblestoneHandler; case E_BLOCK_COBBLESTONE_STAIRS: return ItemCobblestoneStairsHandler; case E_BLOCK_COBBLESTONE_WALL: return ItemCobblestoneWallHandler; case E_BLOCK_COBWEB: return ItemCobwebHandler; case E_BLOCK_COCOA_POD: return ItemCocoaPodHandler; case E_BLOCK_COMMAND_BLOCK: return ItemCommandBlockHandler; case E_BLOCK_CONCRETE: return ItemConcreteBlockHandler; case E_BLOCK_CONCRETE_POWDER: return ItemConcretePowderHandler; case E_BLOCK_CRAFTING_TABLE: return ItemWorkbenchHandler; case E_BLOCK_CYAN_GLAZED_TERRACOTTA: return ItemCyanGlazedTerracottaHandler; case E_BLOCK_CYAN_SHULKER_BOX: return ItemCyanShulkerBoxHandler; case E_BLOCK_DANDELION: return ItemDandelionHandler; case E_BLOCK_DARK_OAK_DOOR: return ItemDarkOakDoorBlockHandler; case E_BLOCK_DARK_OAK_FENCE: return ItemDarkOakFenceHandler; case E_BLOCK_DARK_OAK_FENCE_GATE: return ItemDarkOakFenceGateHandler; case E_BLOCK_DARK_OAK_WOOD_STAIRS: return ItemDarkOakStairsHandler; case E_BLOCK_DAYLIGHT_SENSOR: return ItemDaylightSensorBlockHandler; case E_BLOCK_DEAD_BUSH: return ItemDeadBushHandler; case E_BLOCK_DETECTOR_RAIL: return ItemDetectorRailHandler; case E_BLOCK_DIAMOND_BLOCK: return ItemDiamondBlockHandler; case E_BLOCK_DIAMOND_ORE: return ItemDiamondOreHandler; case E_BLOCK_DIRT: return ItemDirtHandler; case E_BLOCK_DISPENSER: return ItemDispenserHandler; case E_BLOCK_DOUBLE_RED_SANDSTONE_SLAB: return ItemDoubleRedSandstoneSlabHandler; case E_BLOCK_DOUBLE_STONE_SLAB: return ItemDoubleStoneSlabHandler; case E_BLOCK_DOUBLE_WOODEN_SLAB: return ItemDoubleOakSlabHandler; case E_BLOCK_DRAGON_EGG: return ItemDragonEggBlockHandler; case E_BLOCK_DROPPER: return ItemDropperHandler; case E_BLOCK_EMERALD_BLOCK: return ItemEmeraldBlockHandler; case E_BLOCK_EMERALD_ORE: return ItemEmeraldOreHandler; case E_BLOCK_ENCHANTMENT_TABLE: return ItemEnchantingTableHandler; case E_BLOCK_ENDER_CHEST: return ItemEnderChestHandler; case E_BLOCK_END_BRICKS: return ItemEndBricksHandler; case E_BLOCK_END_GATEWAY: return ItemEndGatewayHandler; case E_BLOCK_END_PORTAL: return ItemEndPortalBlockHandler; case E_BLOCK_END_PORTAL_FRAME: return ItemEndPortalFrameHandler; case E_BLOCK_END_ROD: return ItemEndRodHandler; case E_BLOCK_END_STONE: return ItemEndStoneBlockHandler; case E_BLOCK_FARMLAND: return ItemFarmlandHandler; case E_BLOCK_FENCE: return ItemOakFenceHandler; case E_BLOCK_FIRE: return ItemFireBlockHandler; case E_BLOCK_FLOWER: return ItemPoppyHandler; case E_BLOCK_FLOWER_POT: return ItemFlowerPotBlockHandler; case E_BLOCK_FROSTED_ICE: return ItemFrostedIceHandler; case E_BLOCK_FURNACE: return ItemFurnaceHandler; case E_BLOCK_GLASS: return ItemGlassHandler; case E_BLOCK_GLASS_PANE: return ItemGlassPaneHandler; case E_BLOCK_GLOWSTONE: return ItemGlowstoneBlockHandler; case E_BLOCK_GOLD_BLOCK: return ItemGoldBlockHandler; case E_BLOCK_GOLD_ORE: return ItemGoldOreHandler; case E_BLOCK_GRASS: return ItemGrassBlockHandler; case E_BLOCK_GRASS_PATH: return ItemGrassPathHandler; case E_BLOCK_GRAVEL: return ItemGravelHandler; case E_BLOCK_GRAY_GLAZED_TERRACOTTA: return ItemGrayGlazedTerracottaHandler; case E_BLOCK_GRAY_SHULKER_BOX: return ItemGrayShulkerBoxHandler; case E_BLOCK_GREEN_GLAZED_TERRACOTTA: return ItemGreenGlazedTerracottaHandler; case E_BLOCK_GREEN_SHULKER_BOX: return ItemGreenShulkerBoxHandler; case E_BLOCK_HARDENED_CLAY: return ItemHardenedClayHandler; case E_BLOCK_HAY_BALE: return ItemHayBaleHandler; case E_BLOCK_HEAD: return ItemHeadBlockHandler; case E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE: return ItemHeavyWeightedPressurePlateHandler; case E_BLOCK_HOPPER: return ItemHopperHandler; case E_BLOCK_HUGE_BROWN_MUSHROOM: return ItemHugeBrownMushroomBlockHandler; case E_BLOCK_HUGE_RED_MUSHROOM: return ItemHugeRedMushroomBlockHandler; case E_BLOCK_ICE: return ItemIceHandler; case E_BLOCK_INACTIVE_COMPARATOR: return ItemInactiveComparatorHandler; case E_BLOCK_INVERTED_DAYLIGHT_SENSOR: return ItemInvertedDaylightSensorHandler; case E_BLOCK_IRON_BARS: return ItemIronBarsBlockHandler; case E_BLOCK_IRON_BLOCK: return ItemIronBlockHandler; case E_BLOCK_IRON_DOOR: return ItemIronDoorBlockHandler; case E_BLOCK_IRON_ORE: return ItemIronOreHandler; case E_BLOCK_IRON_TRAPDOOR: return ItemIronTrapdoorHandler; case E_BLOCK_JACK_O_LANTERN: return ItemJackOLanternHandler; case E_BLOCK_JUKEBOX: return ItemJukeboxHandler; case E_BLOCK_JUNGLE_DOOR: return ItemJungleDoorBlockHandler; case E_BLOCK_JUNGLE_FENCE: return ItemJungleFenceHandler; case E_BLOCK_JUNGLE_FENCE_GATE: return ItemJungleFenceGateHandler; case E_BLOCK_JUNGLE_WOOD_STAIRS: return ItemJungleStairsHandler; case E_BLOCK_LADDER: return ItemLadderHandler; case E_BLOCK_LAPIS_BLOCK: return ItemLapisBlockHandler; case E_BLOCK_LAPIS_ORE: return ItemLapisOreHandler; case E_BLOCK_LAVA: return ItemLavaHandler; case E_BLOCK_LEAVES: return ItemLeavesHandler; case E_BLOCK_LEVER: return ItemLeverHandler; case E_BLOCK_LIGHT_BLUE_GLAZED_TERRACOTTA: return ItemLightBlueGlazedTerracottaHandler; case E_BLOCK_LIGHT_BLUE_SHULKER_BOX: return ItemLightBlueShulkerBoxHandler; case E_BLOCK_LIGHT_GRAY_GLAZED_TERRACOTTA: return ItemLightGrayGlazedTerracottaHandler; case E_BLOCK_LIGHT_GRAY_SHULKER_BOX: return ItemLightGrayShulkerBoxHandler; case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE: return ItemLightWeightedPressurePlateHandler; case E_BLOCK_LILY_PAD: return ItemLilypadHandler; case E_BLOCK_LIME_GLAZED_TERRACOTTA: return ItemLimeGlazedTerracottaHandler; case E_BLOCK_LIME_SHULKER_BOX: return ItemLimeShulkerBoxHandler; case E_BLOCK_LIT_FURNACE: return ItemLitFurnaceHandler; case E_BLOCK_LOG: return ItemLogHandler; case E_BLOCK_MAGENTA_GLAZED_TERRACOTTA: return ItemMagentaGlazedTerracottaHandler; case E_BLOCK_MAGENTA_SHULKER_BOX: return ItemMagentaShulkerBoxHandler; case E_BLOCK_MAGMA: return ItemMagmaBlockHandler; case E_BLOCK_MELON: return ItemMelonBlockHandler; case E_BLOCK_MELON_STEM: return ItemMelonStemHandler; case E_BLOCK_MOB_SPAWNER: return ItemMobSpawnerBlockHandler; case E_BLOCK_MOSSY_COBBLESTONE: return ItemMossyCobblestoneHandler; case E_BLOCK_MYCELIUM: return ItemMyceliumHandler; case E_BLOCK_NETHERRACK: return ItemNetherrackHandler; case E_BLOCK_NETHER_BRICK: return ItemNetherBricksHandler; case E_BLOCK_NETHER_BRICK_FENCE: return ItemNetherBrickFenceHandler; case E_BLOCK_NETHER_BRICK_STAIRS: return ItemNetherBrickStairsHandler; case E_BLOCK_NETHER_PORTAL: return ItemNetherPortalBlockHandler; case E_BLOCK_NETHER_QUARTZ_ORE: return ItemNetherQuartzOreHandler; case E_BLOCK_NETHER_WART: return ItemNetherWartTechnicalBlockHandler; case E_BLOCK_NETHER_WART_BLOCK: return ItemNetherWartBlockHandler; case E_BLOCK_NEW_LEAVES: return ItemNewLeavesHandler; case E_BLOCK_NEW_LOG: return ItemNewLogHandler; case E_BLOCK_NOTE_BLOCK: return ItemNoteBlockHandler; case E_BLOCK_OAK_DOOR: return ItemOakDoorBlockHandler; case E_BLOCK_OAK_FENCE_GATE: return ItemOakFenceGateHandler; case E_BLOCK_OAK_WOOD_STAIRS: return ItemOakStairsHandler; case E_BLOCK_OBSERVER: return ItemObserverHandler; case E_BLOCK_OBSIDIAN: return ItemObsidianHandler; case E_BLOCK_ORANGE_GLAZED_TERRACOTTA: return ItemOrangeGlazedTerracottaHandler; case E_BLOCK_ORANGE_SHULKER_BOX: return ItemOrangeShulkerBoxHandler; case E_BLOCK_PACKED_ICE: return ItemPackedIceHandler; case E_BLOCK_PINK_GLAZED_TERRACOTTA: return ItemPinkGlazedTerracottaHandler; case E_BLOCK_PINK_SHULKER_BOX: return ItemPinkShulkerBoxHandler; case E_BLOCK_PISTON: return ItemPistonHandler; case E_BLOCK_PISTON_EXTENSION: return ItemPistonExtensionHandler; case E_BLOCK_PISTON_MOVED_BLOCK: return ItemPistonMovedBlockHandler; case E_BLOCK_PLANKS: return ItemPlanksHandler; case E_BLOCK_POTATOES: return ItemPotatoesBlockHandler; case E_BLOCK_POWERED_RAIL: return ItemPoweredRailHandler; case E_BLOCK_PRISMARINE_BLOCK: return ItemPrismarineBlockHandler; case E_BLOCK_PUMPKIN: return ItemPumpkinHandler; case E_BLOCK_PUMPKIN_STEM: return ItemPumpkinStemHandler; case E_BLOCK_PURPLE_GLAZED_TERRACOTTA: return ItemPurpleGlazedTerracottaHandler; case E_BLOCK_PURPLE_SHULKER_BOX: return ItemPurpleShulkerBoxHandler; case E_BLOCK_PURPUR_BLOCK: return ItemPurpurBlockHandler; case E_BLOCK_PURPUR_DOUBLE_SLAB: return ItemPurpurDoubleSlabHandler; case E_BLOCK_PURPUR_PILLAR: return ItemPurpurPillarHandler; case E_BLOCK_PURPUR_SLAB: return ItemPurpurSlabHandler; case E_BLOCK_PURPUR_STAIRS: return ItemPurpurStairsHandler; case E_BLOCK_QUARTZ_BLOCK: return ItemQuartzBlockHandler; case E_BLOCK_QUARTZ_STAIRS: return ItemQuartzStairsHandler; case E_BLOCK_RAIL: return ItemRailHandler; case E_BLOCK_REDSTONE_LAMP_OFF: return ItemRedstoneLampOffHandler; case E_BLOCK_REDSTONE_LAMP_ON: return ItemRedstoneLampOnHandler; case E_BLOCK_REDSTONE_ORE: return ItemRedstoneOreHandler; case E_BLOCK_REDSTONE_ORE_GLOWING: return ItemRedstoneOreGlowingHandler; case E_BLOCK_REDSTONE_REPEATER_OFF: return ItemRedstoneRepeaterOffHandler; case E_BLOCK_REDSTONE_REPEATER_ON: return ItemRedstoneRepeaterOnHandler; case E_BLOCK_REDSTONE_TORCH_OFF: return ItemRedstoneTorchOffBlockHandler; case E_BLOCK_REDSTONE_TORCH_ON: return ItemRedstoneTorchHandler; case E_BLOCK_REDSTONE_WIRE: return ItemRedstoneWireHandler; case E_BLOCK_RED_GLAZED_TERRACOTTA: return ItemRedGlazedTerracottaHandler; case E_BLOCK_RED_MUSHROOM: return ItemRedMushroomBlockHandler; case E_BLOCK_RED_NETHER_BRICK: return ItemRedNetherBricksHandler; case E_BLOCK_RED_SANDSTONE: return ItemRedSandstoneHandler; case E_BLOCK_RED_SANDSTONE_SLAB: return ItemRedSandstoneSlabHandler; case E_BLOCK_RED_SANDSTONE_STAIRS: return ItemRedSandstoneStairsHandler; case E_BLOCK_RED_SHULKER_BOX: return ItemRedShulkerBoxHandler; case E_BLOCK_REPEATING_COMMAND_BLOCK: return ItemRepeatingCommandBlockHandler; case E_BLOCK_SAND: return ItemSandHandler; case E_BLOCK_SANDSTONE: return ItemSandstoneHandler; case E_BLOCK_SANDSTONE_STAIRS: return ItemSandstoneStairsHandler; case E_BLOCK_SAPLING: return ItemSaplingHandler; case E_BLOCK_SEA_LANTERN: return ItemSeaLanternHandler; case E_BLOCK_SIGN_POST: return ItemSignPostHandler; case E_BLOCK_SILVERFISH_EGG: return ItemSilverfishEggBlockHandler; case E_BLOCK_SLIME_BLOCK: return ItemSlimeBlockHandler; case E_BLOCK_SNOW: return ItemSnowHandler; case E_BLOCK_SNOW_BLOCK: return ItemSnowBlockHandler; case E_BLOCK_SOULSAND: return ItemSoulsandHandler; case E_BLOCK_SPONGE: return ItemSpongeHandler; case E_BLOCK_SPRUCE_DOOR: return ItemSpruceDoorBlockHandler; case E_BLOCK_SPRUCE_FENCE: return ItemSpruceFenceHandler; case E_BLOCK_SPRUCE_FENCE_GATE: return ItemSpruceFenceGateHandler; case E_BLOCK_SPRUCE_WOOD_STAIRS: return ItemSpruceStairsHandler; case E_BLOCK_STAINED_GLASS: return ItemStainedGlassHandler; case E_BLOCK_STAINED_GLASS_PANE: return ItemStainedGlassPaneHandler; case E_BLOCK_STANDING_BANNER: return ItemStandingBannerHandler; case E_BLOCK_STATIONARY_LAVA : return ItemStationaryLavaHandler; case E_BLOCK_STATIONARY_WATER: return ItemStationaryWaterHandler; case E_BLOCK_STICKY_PISTON: return ItemStickyPistonHandler; case E_BLOCK_STONE: return ItemStoneHandler; case E_BLOCK_STONE_BRICKS: return ItemStoneBricksHandler; case E_BLOCK_STONE_BRICK_STAIRS: return ItemStoneBrickStairsHandler; case E_BLOCK_STONE_BUTTON: return ItemStoneButtonHandler; case E_BLOCK_STONE_PRESSURE_PLATE: return ItemStonePressurePlateHandler; case E_BLOCK_STONE_SLAB: return ItemStoneSlabHandler; case E_BLOCK_STRUCTURE_BLOCK: return ItemStructureBlockHandler; case E_BLOCK_STRUCTURE_VOID: return ItemStructureVoidHandler; case E_BLOCK_SUGARCANE: return ItemSugarCaneBlockHandler; case E_BLOCK_TALL_GRASS: return ItemTallGrassHandler; case E_BLOCK_TERRACOTTA: return ItemTerracottaHandler; case E_BLOCK_TNT: return ItemTNTHandler; case E_BLOCK_TORCH: return ItemTorchHandler; case E_BLOCK_TRAPDOOR: return ItemOakTrapdoorHandler; case E_BLOCK_TRAPPED_CHEST: return ItemTrappedChestHandler; case E_BLOCK_TRIPWIRE: return ItemTripwireHandler; case E_BLOCK_TRIPWIRE_HOOK: return ItemTripwireHookHandler; case E_BLOCK_VINES: return ItemVinesHandler; case E_BLOCK_WALLSIGN: return ItemWallsignHandler; case E_BLOCK_WALL_BANNER: return ItemWallBannerHandler; case E_BLOCK_WATER: return ItemWaterHandler; case E_BLOCK_WHEAT: return ItemWheatBlockHandler; case E_BLOCK_WHITE_GLAZED_TERRACOTTA: return ItemWhiteGlazedTerracottaHandler; case E_BLOCK_WHITE_SHULKER_BOX: return ItemWhiteShulkerBoxHandler; case E_BLOCK_WOODEN_BUTTON: return ItemOakButtonHandler; case E_BLOCK_WOODEN_PRESSURE_PLATE: return ItemWoodenPressurePlateHandler; case E_BLOCK_WOODEN_SLAB: return ItemOakSlabHandler; case E_BLOCK_WOOL: return ItemWoolHandler; case E_BLOCK_YELLOW_GLAZED_TERRACOTTA: return ItemYellowGlazedTerracottaHandler; case E_BLOCK_YELLOW_SHULKER_BOX: return ItemYellowShulkerBoxHandler; case E_ITEM_11_DISC: return Item11DiscHandler; case E_ITEM_13_DISC: return Item13DiscHandler; case E_ITEM_ACACIA_BOAT: return ItemAcaciaBoatHandler; case E_ITEM_ACACIA_DOOR: return ItemAcaciaDoorHandler; case E_ITEM_ARMOR_STAND: return ItemArmorStandHandler; case E_ITEM_ARROW: return ItemArrowHandler; case E_ITEM_BAKED_POTATO: return ItemBakedPotatoHandler; case E_ITEM_BANNER: return ItemBannerHandler; case E_ITEM_BED: return ItemBedHandler; case E_ITEM_BEETROOT: return ItemBeetrootHandler; case E_ITEM_BEETROOT_SEEDS: return ItemBeetrootSeedsHandler; case E_ITEM_BEETROOT_SOUP: return ItemBeetrootSoupHandler; case E_ITEM_BIRCH_BOAT: return ItemBirchBoatHandler; case E_ITEM_BIRCH_DOOR: return ItemBirchDoorHandler; case E_ITEM_BLAZE_POWDER: return ItemBlazePowderHandler; case E_ITEM_BLAZE_ROD: return ItemBlazeRodHandler; case E_ITEM_BLOCKS_DISC: return ItemBlocksDiscHandler; case E_ITEM_BOAT: return ItemOakBoatHandler; case E_ITEM_BONE: return ItemBoneHandler; case E_ITEM_BOOK: return ItemBookHandler; case E_ITEM_BOOK_AND_QUILL: return ItemBookAndQuillHandler; case E_ITEM_BOTTLE_O_ENCHANTING: return ItemBottleOEnchantingHandler; case E_ITEM_BOW: return ItemBowHandler; case E_ITEM_BOWL: return ItemBowlHandler; case E_ITEM_BREAD: return ItemBreadHandler; case E_ITEM_BREWING_STAND: return ItemBrewingStandHandler; case E_ITEM_BUCKET: return ItemBucketHandler; case E_ITEM_CAKE: return ItemCakeHandler; case E_ITEM_CARROT: return ItemCarrotHandler; case E_ITEM_CARROT_ON_STICK: return ItemCarrotOnStickHandler; case E_ITEM_CAT_DISC: return ItemCatDiscHandler; case E_ITEM_CAULDRON: return ItemCauldronHandler; case E_ITEM_CHAIN_BOOTS: return ItemChainBootsHandler; case E_ITEM_CHAIN_CHESTPLATE: return ItemChainChestplateHandler; case E_ITEM_CHAIN_HELMET: return ItemChainHelmetHandler; case E_ITEM_CHAIN_LEGGINGS: return ItemChainLeggingsHandler; case E_ITEM_CHEST_MINECART: return ItemChestMinecartHandler; case E_ITEM_CHIRP_DISC: return ItemChirpDiscHandler; case E_ITEM_CHORUS_FRUIT: return ItemChorusFruitHandler; case E_ITEM_CLAY: return ItemClayHandler; case E_ITEM_CLAY_BRICK: return ItemBricksHandler; case E_ITEM_CLOCK: return ItemClockHandler; case E_ITEM_COAL: return ItemCoalHandler; case E_ITEM_COMPARATOR: return ItemComparatorHandler; case E_ITEM_COMPASS: return ItemCompassHandler; case E_ITEM_COOKED_CHICKEN: return ItemCookedChickenHandler; case E_ITEM_COOKED_FISH: return ItemCookedFishHandler; case E_ITEM_COOKED_MUTTON: return ItemCookedMuttonHandler; case E_ITEM_COOKED_PORKCHOP: return ItemCookedPorkchopHandler; case E_ITEM_COOKED_RABBIT: return ItemCookedRabbitHandler; case E_ITEM_COOKIE: return ItemCookieHandler; case E_ITEM_DARK_OAK_BOAT: return ItemDarkOakBoatHandler; case E_ITEM_DARK_OAK_DOOR: return ItemDarkOakDoorHandler; case E_ITEM_DIAMOND: return ItemDiamondHandler; case E_ITEM_DIAMOND_AXE: return ItemDiamondAxeHandler; case E_ITEM_DIAMOND_BOOTS: return ItemDiamondBootsHandler; case E_ITEM_DIAMOND_CHESTPLATE: return ItemDiamondChestplateHandler; case E_ITEM_DIAMOND_HELMET: return ItemDiamondHelmetHandler; case E_ITEM_DIAMOND_HOE: return ItemDiamondHoeHandler; case E_ITEM_DIAMOND_HORSE_ARMOR: return ItemDiamondHorseArmorHandler; case E_ITEM_DIAMOND_LEGGINGS: return ItemDiamondLeggingsHandler; case E_ITEM_DIAMOND_PICKAXE: return ItemDiamondPickaxeHandler; case E_ITEM_DIAMOND_SHOVEL: return ItemDiamondShovelHandler; case E_ITEM_DIAMOND_SWORD: return ItemDiamondSwordHandler; case E_ITEM_DRAGON_BREATH: return ItemDragonBreathHandler; case E_ITEM_DYE: return ItemDyeHandler; case E_ITEM_EGG: return ItemEggHandler; case E_ITEM_ELYTRA: return ItemElytraHandler; case E_ITEM_EMERALD: return ItemEmeraldHandler; case E_ITEM_EMPTY_MAP: return ItemEmptyMapHandler; case E_ITEM_ENCHANTED_BOOK: return ItemEnchantedBookHandler; case E_ITEM_ENDER_PEARL: return ItemEnderPearlHandler; case E_ITEM_END_CRYSTAL: return ItemEndCrystalHandler; case E_ITEM_EYE_OF_ENDER: return ItemEyeOfEnderHandler; case E_ITEM_FAR_DISC: return ItemFarDiscHandler; case E_ITEM_FEATHER: return ItemFeatherHandler; case E_ITEM_FERMENTED_SPIDER_EYE: return ItemFermentedSpiderEyeHandler; case E_ITEM_FIREWORK_ROCKET: return ItemFireworkRocketHandler; case E_ITEM_FIREWORK_STAR: return ItemFireworkStarHandler; case E_ITEM_FIRE_CHARGE: return ItemFireChargeHandler; case E_ITEM_FISHING_ROD: return ItemFishingRodHandler; case E_ITEM_FLINT: return ItemFlintHandler; case E_ITEM_FLINT_AND_STEEL: return ItemFlintAndSteelHandler; case E_ITEM_FLOWER_POT: return ItemFlowerPotHandler; case E_ITEM_FURNACE_MINECART: return ItemFurnaceMinecartHandler; case E_ITEM_GHAST_TEAR: return ItemGhastTearHandler; case E_ITEM_GLASS_BOTTLE: return ItemGlassBottleHandler; case E_ITEM_GLISTERING_MELON: return ItemGlisteringMelonHandler; case E_ITEM_GLOWSTONE_DUST: return ItemGlowstoneDustHandler; case E_ITEM_GOLD: return ItemGoldHandler; case E_ITEM_GOLDEN_APPLE: return ItemGoldenAppleHandler; case E_ITEM_GOLDEN_CARROT: return ItemGoldenCarrotHandler; case E_ITEM_GOLD_AXE: return ItemGoldenAxeHandler; case E_ITEM_GOLD_BOOTS: return ItemGoldenBootsHandler; case E_ITEM_GOLD_CHESTPLATE: return ItemGoldenChestplateHandler; case E_ITEM_GOLD_HELMET: return ItemGoldenHelmetHandler; case E_ITEM_GOLD_HOE: return ItemGoldenHoeHandler; case E_ITEM_GOLD_HORSE_ARMOR: return ItemGoldenHorseArmorHandler; case E_ITEM_GOLD_LEGGINGS: return ItemGoldenLeggingsHandler; case E_ITEM_GOLD_NUGGET: return ItemGoldNuggetHandler; case E_ITEM_GOLD_PICKAXE: return ItemGoldenPickaxeHandler; case E_ITEM_GOLD_SHOVEL: return ItemGoldenShovelHandler; case E_ITEM_GOLD_SWORD: return ItemGoldenSwordHandler; case E_ITEM_GUNPOWDER: return ItemGunpowderHandler; case E_ITEM_HEAD: return ItemHeadHandler; case E_ITEM_IRON: return ItemIronHandler; case E_ITEM_IRON_AXE: return ItemIronAxeHandler; case E_ITEM_IRON_BOOTS: return ItemIronBootsHandler; case E_ITEM_IRON_CHESTPLATE: return ItemIronChestplateHandler; case E_ITEM_IRON_DOOR: return ItemIronDoorHandler; case E_ITEM_IRON_HELMET: return ItemIronHelmetHandler; case E_ITEM_IRON_HOE: return ItemIronHoeHandler; case E_ITEM_IRON_HORSE_ARMOR: return ItemIronHorseArmorHandler; case E_ITEM_IRON_LEGGINGS: return ItemIronLeggingsHandler; case E_ITEM_IRON_NUGGET: return ItemIronNuggetHandler; case E_ITEM_IRON_PICKAXE: return ItemIronPickaxeHandler; case E_ITEM_IRON_SHOVEL: return ItemIronShovelHandler; case E_ITEM_IRON_SWORD: return ItemIronSwordHandler; case E_ITEM_ITEM_FRAME: return ItemItemFrameHandler; case E_ITEM_JUNGLE_BOAT: return ItemJungleBoatHandler; case E_ITEM_JUNGLE_DOOR: return ItemJungleDoorHandler; case E_ITEM_LAVA_BUCKET: return ItemLavaBucketHandler; case E_ITEM_LEASH: return ItemLeashHandler; case E_ITEM_LEATHER: return ItemLeatherHandler; case E_ITEM_LEATHER_BOOTS: return ItemLeatherBootsHandler; case E_ITEM_LEATHER_CAP: return ItemLeatherCapHandler; case E_ITEM_LEATHER_PANTS: return ItemLeatherPantsHandler; case E_ITEM_LEATHER_TUNIC: return ItemLeatherTunicHandler; case E_ITEM_LINGERING_POTION: return ItemLingeringPotionHandler; case E_ITEM_MAGMA_CREAM: return ItemMagmaCreamHandler; case E_ITEM_MALL_DISC: return ItemMallDiscHandler; case E_ITEM_MAP: return ItemMapHandler; case E_ITEM_MELLOHI_DISC: return ItemMellohiDiscHandler; case E_ITEM_MELON_SEEDS: return ItemMelonSeedsHandler; case E_ITEM_MELON_SLICE: return ItemMelonSliceHandler; case E_ITEM_MILK: return ItemMilkHandler; case E_ITEM_MINECART: return ItemMinecartHandler; case E_ITEM_MINECART_WITH_COMMAND_BLOCK: return ItemMinecartWithCommandBlockHandler; case E_ITEM_MINECART_WITH_HOPPER: return ItemMinecartWithHopperHandler; case E_ITEM_MINECART_WITH_TNT: return ItemMinecartWithTNTHandler; case E_ITEM_MUSHROOM_SOUP: return ItemMushroomSoupHandler; case E_ITEM_NAME_TAG: return ItemNameTagHandler; case E_ITEM_NETHER_BRICK: return ItemNetherBrickHandler; case E_ITEM_NETHER_QUARTZ: return ItemNetherQuartzHandler; case E_ITEM_NETHER_STAR: return ItemNetherStarHandler; case E_ITEM_NETHER_WART: return ItemNetherWartHandler; case E_ITEM_PAINTING: return ItemPaintingHandler; case E_ITEM_PAPER: return ItemPaperHandler; case E_ITEM_POISONOUS_POTATO: return ItemPoisonousPotatoHandler; case E_ITEM_POPPED_CHORUS_FRUIT: return ItemPoppedChorusFruitHandler; case E_ITEM_POTATO: return ItemPotatoHandler; case E_ITEM_POTION: return ItemPotionHandler; case E_ITEM_PRISMARINE_CRYSTALS: return ItemPrismarineCrystalsHandler; case E_ITEM_PRISMARINE_SHARD: return ItemPrismarineShardHandler; case E_ITEM_PUMPKIN_PIE: return ItemPumpkinPieHandler; case E_ITEM_PUMPKIN_SEEDS: return ItemPumpkinSeedsHandler; case E_ITEM_RABBITS_FOOT: return ItemRabbitsFootHandler; case E_ITEM_RABBIT_HIDE: return ItemRabbitHideHandler; case E_ITEM_RABBIT_STEW: return ItemRabbitStewHandler; case E_ITEM_RAW_BEEF: return ItemRawBeefHandler; case E_ITEM_RAW_CHICKEN: return ItemRawChickenHandler; case E_ITEM_RAW_FISH: return ItemRawFishHandler; case E_ITEM_RAW_MUTTON: return ItemRawMuttonHandler; case E_ITEM_RAW_PORKCHOP: return ItemRawPorkchopHandler; case E_ITEM_RAW_RABBIT: return ItemRawRabbitHandler; case E_ITEM_REDSTONE_DUST: return ItemRedstoneDustHandler; case E_ITEM_REDSTONE_REPEATER: return ItemRedstoneRepeaterHandler; case E_ITEM_RED_APPLE: return ItemAppleHandler; case E_ITEM_ROTTEN_FLESH: return ItemRottenFleshHandler; case E_ITEM_SADDLE: return ItemSaddleHandler; case E_ITEM_SEEDS: return ItemSeedsHandler; case E_ITEM_SHEARS: return ItemShearsHandler; case E_ITEM_SHIELD: return ItemShieldHandler; case E_ITEM_SHULKER_SHELL: return ItemShulkerShellHandler; case E_ITEM_SIGN: return ItemSignHandler; case E_ITEM_SLIMEBALL: return ItemSlimeballHandler; case E_ITEM_SNOWBALL: return ItemSnowballHandler; case E_ITEM_SPAWN_EGG: return ItemSpawnEggHandler; case E_ITEM_SPECTRAL_ARROW: return ItemSpectralArrowHandler; case E_ITEM_SPIDER_EYE: return ItemSpiderEyeHandler; case E_ITEM_SPLASH_POTION: return ItemSplashPotionHandler; case E_ITEM_SPRUCE_BOAT: return ItemSpruceBoatHandler; case E_ITEM_SPRUCE_DOOR: return ItemSpruceDoorHandler; case E_ITEM_STAL_DISC: return ItemStalDiscHandler; case E_ITEM_STEAK: return ItemCookedBeefHandler; case E_ITEM_STICK: return ItemStickHandler; case E_ITEM_STONE_AXE: return ItemStoneAxeHandler; case E_ITEM_STONE_HOE: return ItemStoneHoeHandler; case E_ITEM_STONE_PICKAXE: return ItemStonePickaxeHandler; case E_ITEM_STONE_SHOVEL: return ItemStoneShovelHandler; case E_ITEM_STONE_SWORD: return ItemStoneSwordHandler; case E_ITEM_STRAD_DISC: return ItemStradDiscHandler; case E_ITEM_STRING: return ItemStringHandler; case E_ITEM_SUGAR: return ItemSugarHandler; case E_ITEM_SUGAR_CANE: return ItemSugarCaneHandler; case E_ITEM_TIPPED_ARROW: return ItemTippedArrowHandler; case E_ITEM_TOTEM_OF_UNDYING: return ItemTotemOfUndyingHandler; case E_ITEM_WAIT_DISC: return ItemWaitDiscHandler; case E_ITEM_WARD_DISC: return ItemWardDiscHandler; case E_ITEM_WATER_BUCKET: return ItemWaterBucketHandler; case E_ITEM_WHEAT: return ItemWheatHandler; case E_ITEM_WOODEN_AXE: return ItemWoodenAxeHandler; case E_ITEM_WOODEN_DOOR: return ItemOakDoorHandler; case E_ITEM_WOODEN_HOE: return ItemWoodenHoeHandler; case E_ITEM_WOODEN_PICKAXE: return ItemWoodenPickaxeHandler; case E_ITEM_WOODEN_SHOVEL: return ItemWoodenShovelHandler; case E_ITEM_WOODEN_SWORD: return ItemWoodenSwordHandler; case E_ITEM_WRITTEN_BOOK: return ItemWrittenBookHandler; } ASSERT("Unknown item type!"); return ItemAirHandler; } void cItemHandler::OnPlayerPlace(cPlayer & a_Player, const cItem & a_HeldItem, const Vector3i a_ClickedPosition, const BLOCKTYPE a_ClickedBlockType, const NIBBLETYPE a_ClickedBlockMeta, const eBlockFace a_ClickedBlockFace, const Vector3i a_CursorPosition) const { const auto & World = *a_Player.GetWorld(); // Check if the block ignores build collision (water, grass etc.): if (cBlockHandler::For(a_ClickedBlockType).DoesIgnoreBuildCollision(World, a_HeldItem, a_ClickedPosition, a_ClickedBlockMeta, a_ClickedBlockFace, true)) { // Try to place the block at the clicked position: if (!CommitPlacement(a_Player, a_HeldItem, a_ClickedPosition, a_ClickedBlockFace, a_CursorPosition)) { // The placement failed, the blocks have already been re-sent, re-send inventory: a_Player.GetInventory().SendEquippedSlot(); return; } } else { BLOCKTYPE PlaceBlock; NIBBLETYPE PlaceMeta; const auto PlacePosition = AddFaceDirection(a_ClickedPosition, a_ClickedBlockFace); if (!cChunkDef::IsValidHeight(PlacePosition) || !World.GetBlockTypeMeta(PlacePosition, PlaceBlock, PlaceMeta)) { // The block is being placed outside the world, ignore this packet altogether (GH #128): return; } // Clicked on side of block, make sure that placement won't be cancelled if there is a slab able to be double slabbed. // No need to do combinability (dblslab) checks, client will do that here. if (!cBlockHandler::For(PlaceBlock).DoesIgnoreBuildCollision(World, a_HeldItem, PlacePosition, PlaceMeta, a_ClickedBlockFace, false)) { // Tried to place a block into another? // Happens when you place a block aiming at side of block with a torch on it or stem beside it. a_Player.SendBlocksAround(PlacePosition, 2); a_Player.GetInventory().SendEquippedSlot(); return; } // Try to place the block: if (!CommitPlacement(a_Player, a_HeldItem, PlacePosition, a_ClickedBlockFace, a_CursorPosition)) { // The placement failed, the blocks have already been re-sent, re-send inventory: a_Player.GetInventory().SendEquippedSlot(); return; } } // Remove the "placed" item: if (a_Player.IsGameModeSurvival()) { a_Player.GetInventory().RemoveOneEquippedItem(); } } bool cItemHandler::OnItemUse( cWorld * a_World, cPlayer * a_Player, cBlockPluginInterface & a_PluginInterface, const cItem & a_Item, const Vector3i a_ClickedBlockPos, eBlockFace a_ClickedBlockFace ) const { UNUSED(a_World); UNUSED(a_Player); UNUSED(a_PluginInterface); UNUSED(a_Item); UNUSED(a_ClickedBlockPos); UNUSED(a_ClickedBlockFace); return false; } bool cItemHandler::OnDiggingBlock( cWorld * a_World, cPlayer * a_Player, const cItem & a_HeldItem, const Vector3i a_ClickedBlockPos, eBlockFace a_ClickedBlockFace ) const { UNUSED(a_World); UNUSED(a_Player); UNUSED(a_HeldItem); UNUSED(a_ClickedBlockPos); UNUSED(a_ClickedBlockFace); return false; } void cItemHandler::OnEntityAttack(cPlayer * a_Attacker, cEntity * a_AttackedEntity) const { UNUSED(a_AttackedEntity); a_Attacker->UseEquippedItem(dlaAttackEntity); } void cItemHandler::OnFoodEaten(cWorld * a_World, cPlayer * a_Player, cItem * a_Item) const { UNUSED(a_World); UNUSED(a_Player); UNUSED(a_Item); } short cItemHandler::GetDurabilityLossByAction(eDurabilityLostAction a_Action) const { UNUSED(a_Action); return 0; } char cItemHandler::GetMaxStackSize(void) const { if (m_ItemType < 256) { // All blocks can stack up to 64 return 64; } switch (m_ItemType) { case E_ITEM_ACACIA_DOOR: return 64; case E_ITEM_ARMOR_STAND: return 16; case E_ITEM_ARROW: return 64; case E_ITEM_BAKED_POTATO: return 64; case E_ITEM_BANNER: return 16; case E_ITEM_BEETROOT: return 64; case E_ITEM_BEETROOT_SEEDS: return 64; case E_ITEM_BIRCH_DOOR: return 64; case E_ITEM_BLAZE_POWDER: return 64; case E_ITEM_BLAZE_ROD: return 64; case E_ITEM_BONE: return 64; case E_ITEM_BOOK: return 64; case E_ITEM_BOTTLE_O_ENCHANTING: return 64; case E_ITEM_BOWL: return 64; case E_ITEM_BREAD: return 64; case E_ITEM_BREWING_STAND: return 64; case E_ITEM_BUCKET: return 16; case E_ITEM_CARROT: return 64; case E_ITEM_CAULDRON: return 64; case E_ITEM_CHORUS_FRUIT: return 64; case E_ITEM_CLAY: return 64; case E_ITEM_CLAY_BRICK: return 64; case E_ITEM_CLOCK: return 64; case E_ITEM_COAL: return 64; case E_ITEM_COMPARATOR: return 64; case E_ITEM_COMPASS: return 64; case E_ITEM_COOKED_CHICKEN: return 64; case E_ITEM_COOKED_FISH: return 64; case E_ITEM_COOKED_MUTTON: return 64; case E_ITEM_COOKED_PORKCHOP: return 64; case E_ITEM_COOKED_RABBIT: return 64; case E_ITEM_COOKIE: return 64; case E_ITEM_DARK_OAK_DOOR: return 64; case E_ITEM_DIAMOND: return 64; case E_ITEM_DRAGON_BREATH: return 64; case E_ITEM_DYE: return 64; case E_ITEM_EGG: return 16; case E_ITEM_EMERALD: return 64; case E_ITEM_EMPTY_MAP: return 64; case E_ITEM_ENDER_PEARL: return 16; case E_ITEM_EYE_OF_ENDER: return 64; case E_ITEM_FEATHER: return 64; case E_ITEM_FERMENTED_SPIDER_EYE: return 64; case E_ITEM_FIRE_CHARGE: return 64; case E_ITEM_FIREWORK_ROCKET: return 64; case E_ITEM_FIREWORK_STAR: return 64; case E_ITEM_FLINT: return 64; case E_ITEM_FLOWER_POT: return 64; case E_ITEM_GHAST_TEAR: return 64; case E_ITEM_GLASS_BOTTLE: return 64; case E_ITEM_GLISTERING_MELON: return 64; case E_ITEM_GLOWSTONE_DUST: return 64; case E_ITEM_GOLD: return 64; case E_ITEM_GOLDEN_APPLE: return 64; case E_ITEM_GOLDEN_CARROT: return 64; case E_ITEM_GOLD_NUGGET: return 64; case E_ITEM_GUNPOWDER: return 64; case E_ITEM_HEAD: return 64; case E_ITEM_JUNGLE_DOOR: return 64; case E_ITEM_IRON: return 64; case E_ITEM_IRON_DOOR: return 64; case E_ITEM_IRON_NUGGET: return 64; case E_ITEM_ITEM_FRAME: return 64; case E_ITEM_LEAD: return 64; case E_ITEM_LEATHER: return 64; case E_ITEM_MAGMA_CREAM: return 64; case E_ITEM_MAP: return 64; case E_ITEM_MELON_SEEDS: return 64; case E_ITEM_MELON_SLICE: return 64; case E_ITEM_NETHER_BRICK: return 64; case E_ITEM_NETHER_QUARTZ: return 64; case E_ITEM_NETHER_WART: return 64; case E_ITEM_PAINTING: return 64; case E_ITEM_PAPER: return 64; case E_ITEM_POISONOUS_POTATO: return 64; case E_ITEM_POPPED_CHORUS_FRUIT: return 64; case E_ITEM_POTATO: return 64; case E_ITEM_PRISMARINE_CRYSTALS: return 64; case E_ITEM_PRISMARINE_SHARD: return 64; case E_ITEM_PUMPKIN_PIE: return 64; case E_ITEM_PUMPKIN_SEEDS: return 64; case E_ITEM_RABBITS_FOOT: return 64; case E_ITEM_RABBIT_HIDE: return 64; case E_ITEM_RAW_BEEF: return 64; case E_ITEM_RAW_CHICKEN: return 64; case E_ITEM_RAW_FISH: return 64; case E_ITEM_RAW_MUTTON: return 64; case E_ITEM_RAW_PORKCHOP: return 64; case E_ITEM_RAW_RABBIT: return 64; case E_ITEM_RED_APPLE: return 64; case E_ITEM_REDSTONE_DUST: return 64; case E_ITEM_REDSTONE_REPEATER: return 64; case E_ITEM_ROTTEN_FLESH: return 64; case E_ITEM_SEEDS: return 64; case E_ITEM_SIGN: return 16; case E_ITEM_SLIMEBALL: return 64; case E_ITEM_SNOWBALL: return 16; case E_ITEM_SPAWN_EGG: return 64; case E_ITEM_SPECTRAL_ARROW: return 64; case E_ITEM_SPIDER_EYE: return 64; case E_ITEM_SPRUCE_DOOR: return 64; case E_ITEM_STEAK: return 64; case E_ITEM_STICK: return 64; case E_ITEM_STRING: return 64; case E_ITEM_SUGAR: return 64; case E_ITEM_SUGAR_CANE: return 64; case E_ITEM_TIPPED_ARROW: return 64; case E_ITEM_WHEAT: return 64; case E_ITEM_WOODEN_DOOR: return 64; // By default items don't stack: default: return 1; } } bool cItemHandler::IsFood(void) const { return false; } bool cItemHandler::IsDrinkable(short a_ItemDamage) const { UNUSED(a_ItemDamage); return false; } bool cItemHandler::IsPlaceable(void) const { // We can place any block that has a corresponding E_BLOCK_TYPE: return (m_ItemType >= 1) && (m_ItemType <= E_BLOCK_MAX_TYPE_ID); } bool cItemHandler::CanRepairWithRawMaterial(short a_ItemType) const { UNUSED(a_ItemType); return false; } bool cItemHandler::CanHarvestBlock(BLOCKTYPE a_BlockType) const { switch (a_BlockType) { case E_BLOCK_ANVIL: case E_BLOCK_BLACK_GLAZED_TERRACOTTA: case E_BLOCK_BLOCK_OF_COAL: case E_BLOCK_BLOCK_OF_REDSTONE: case E_BLOCK_BLUE_GLAZED_TERRACOTTA: case E_BLOCK_BONE_BLOCK: case E_BLOCK_BREWING_STAND: case E_BLOCK_BRICK: case E_BLOCK_BRICK_STAIRS: case E_BLOCK_BROWN_GLAZED_TERRACOTTA: case E_BLOCK_CAULDRON: case E_BLOCK_COAL_ORE: case E_BLOCK_COBBLESTONE: case E_BLOCK_COBBLESTONE_STAIRS: case E_BLOCK_COBBLESTONE_WALL: case E_BLOCK_COBWEB: case E_BLOCK_CONCRETE: case E_BLOCK_CYAN_GLAZED_TERRACOTTA: case E_BLOCK_DIAMOND_BLOCK: case E_BLOCK_DIAMOND_ORE: case E_BLOCK_DISPENSER: case E_BLOCK_DOUBLE_RED_SANDSTONE_SLAB: case E_BLOCK_DOUBLE_STONE_SLAB: case E_BLOCK_DROPPER: case E_BLOCK_EMERALD_ORE: case E_BLOCK_ENCHANTMENT_TABLE: case E_BLOCK_END_BRICKS: case E_BLOCK_END_STONE: case E_BLOCK_FURNACE: case E_BLOCK_GOLD_BLOCK: case E_BLOCK_GOLD_ORE: case E_BLOCK_GRAY_GLAZED_TERRACOTTA: case E_BLOCK_GREEN_GLAZED_TERRACOTTA: case E_BLOCK_HARDENED_CLAY: case E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE: case E_BLOCK_HOPPER: case E_BLOCK_IRON_BARS: case E_BLOCK_IRON_BLOCK: case E_BLOCK_IRON_DOOR: case E_BLOCK_IRON_ORE: case E_BLOCK_IRON_TRAPDOOR: case E_BLOCK_LAPIS_BLOCK: case E_BLOCK_LAPIS_ORE: case E_BLOCK_LIGHT_BLUE_GLAZED_TERRACOTTA: case E_BLOCK_LIGHT_GRAY_GLAZED_TERRACOTTA: case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE: case E_BLOCK_LIME_GLAZED_TERRACOTTA: case E_BLOCK_LIT_FURNACE: case E_BLOCK_MAGENTA_GLAZED_TERRACOTTA: case E_BLOCK_MAGMA: case E_BLOCK_MOB_SPAWNER: case E_BLOCK_MOSSY_COBBLESTONE: case E_BLOCK_NETHERRACK: case E_BLOCK_NETHER_BRICK: case E_BLOCK_NETHER_BRICK_FENCE: case E_BLOCK_NETHER_BRICK_STAIRS: case E_BLOCK_NETHER_QUARTZ_ORE: case E_BLOCK_OBSERVER: case E_BLOCK_OBSIDIAN: case E_BLOCK_ORANGE_GLAZED_TERRACOTTA: case E_BLOCK_PINK_GLAZED_TERRACOTTA: case E_BLOCK_PRISMARINE_BLOCK: case E_BLOCK_PURPLE_GLAZED_TERRACOTTA: case E_BLOCK_PURPUR_BLOCK: case E_BLOCK_PURPUR_DOUBLE_SLAB: case E_BLOCK_PURPUR_PILLAR: case E_BLOCK_PURPUR_SLAB: case E_BLOCK_PURPUR_STAIRS: case E_BLOCK_QUARTZ_BLOCK: case E_BLOCK_QUARTZ_STAIRS: case E_BLOCK_REDSTONE_ORE: case E_BLOCK_REDSTONE_ORE_GLOWING: case E_BLOCK_RED_GLAZED_TERRACOTTA: case E_BLOCK_RED_NETHER_BRICK: case E_BLOCK_RED_SANDSTONE: case E_BLOCK_RED_SANDSTONE_SLAB: case E_BLOCK_RED_SANDSTONE_STAIRS: case E_BLOCK_SANDSTONE: case E_BLOCK_SANDSTONE_STAIRS: case E_BLOCK_SNOW: case E_BLOCK_STONE: case E_BLOCK_STONE_BRICKS: case E_BLOCK_STONE_BRICK_STAIRS: case E_BLOCK_STONE_PRESSURE_PLATE: case E_BLOCK_STONE_SLAB: case E_BLOCK_VINES: case E_BLOCK_WHITE_GLAZED_TERRACOTTA: case E_BLOCK_YELLOW_GLAZED_TERRACOTTA: { return false; } default: return true; } } bool cItemHandler::EatItem(cPlayer * a_Player, cItem * a_Item) const { auto FoodInfo = GetFoodInfo(a_Item); return a_Player->Feed(FoodInfo.FoodLevel, FoodInfo.Saturation); } cItemHandler::FoodInfo cItemHandler::GetFoodInfo(const cItem * a_Item) const { UNUSED(a_Item); return FoodInfo(0, 0); } float cItemHandler::GetBlockBreakingStrength(BLOCKTYPE a_Block) const { return 1.0f; } bool cItemHandler::CommitPlacement(cPlayer & a_Player, const cItem & a_HeldItem, const Vector3i a_PlacePosition, const eBlockFace a_ClickedBlockFace, const Vector3i a_CursorPosition) const { ASSERT(m_ItemType < 256); // Items with IDs above 255 should all be handled by specific handlers. // By default, all blocks can be placed and the meta is copied over from the item's damage value: return a_Player.PlaceBlock( a_PlacePosition, static_cast(m_ItemType), static_cast(a_HeldItem.m_ItemDamage & 0x0f) ); } ================================================ FILE: src/Items/ItemHandler.h ================================================ #pragma once #include "../Defines.h" #include "../Item.h" // fwd: class cChunk; class cWorld; class cPlayer; class cBlockPluginInterface; class cItemHandler { public: friend class cItem; /** Actions that may cause durability of an item may be lost, where the magnitude of the loss depends on the specific item used to perform the action */ enum eDurabilityLostAction { dlaAttackEntity, dlaBreakBlock, dlaBreakBlockInstant, }; constexpr cItemHandler(int a_ItemType) : m_ItemType(a_ItemType) { } /** Called when the player tries to place the item (right mouse button, IsPlaceable() == true). a_ClickedPosition is the block that has been clicked to place this item. a_ClickedBlockFace is the face has been clicked to place this item. a_CursorPosition is the position of the player's cursor within a_ClickedBlockFace. If the block placement is refused inside this call, it will automatically revert the client-side changes. */ void OnPlayerPlace(cPlayer & a_Player, const cItem & a_HeldItem, Vector3i a_ClickedPosition, BLOCKTYPE a_ClickedBlockType, NIBBLETYPE a_ClickedBlockMeta, eBlockFace a_ClickedBlockFace, Vector3i a_CursorPosition) const; /** Called when the player tries to use the item (right mouse button). Descendants can return false to abort the usage (default behavior). */ virtual bool OnItemUse( cWorld * a_World, cPlayer * a_Player, cBlockPluginInterface & a_PluginInterface, const cItem & a_HeldItem, const Vector3i a_ClickedBlockPos, eBlockFace a_ClickedBlockFace ) const; /** Called when the client sends the SHOOT status in the lclk packet (releasing the bow). */ virtual void OnItemShoot(cPlayer *, const Vector3i a_BlockPos, eBlockFace a_BlockFace) const { UNUSED(a_BlockPos); UNUSED(a_BlockFace); } /** Called every tick while the item is on the player's inventory (used by maps, for example) - For now, called only for equipped items */ virtual void OnUpdate(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item) const { UNUSED(a_World); UNUSED(a_Player); UNUSED(a_Item); } /** Called while the player digs a block using this item */ virtual bool OnDiggingBlock( cWorld * a_World, cPlayer * a_Player, const cItem & a_HeldItem, const Vector3i a_ClickedBlockPos, eBlockFace a_ClickedBlockFace ) const; /** Called when a player attacks an entity with this item in hand. */ virtual void OnEntityAttack(cPlayer * a_Attacker, cEntity * a_AttackedEntity) const; /** Called after the player has eaten this item. */ virtual void OnFoodEaten(cWorld *a_World, cPlayer *a_Player, cItem *a_Item) const; /** Get the durability lost which the item will get, when a specified action was performed. This is only relevant for uses where the damage taken may depend on the item used. */ virtual short GetDurabilityLossByAction(eDurabilityLostAction a_Action) const; /** Returns the maximum stack size for a given item */ virtual char GetMaxStackSize(void) const; struct FoodInfo { int FoodLevel; double Saturation; constexpr FoodInfo(int a_FoodLevel, double a_Saturation) : FoodLevel(a_FoodLevel), Saturation(a_Saturation) { } } ; /** Returns the FoodInfo for this item. (FoodRecovery and Saturation) */ virtual FoodInfo GetFoodInfo(const cItem * a_Item) const; /** Lets the player eat a selected item. Returns true if the player ate the item */ virtual bool EatItem(cPlayer * a_Player, cItem * a_Item) const; /** Indicates if this item is food */ virtual bool IsFood(void) const; /** Indicates if this item is drinkable */ virtual bool IsDrinkable(short a_ItemDamage) const; /** Blocks simply get placed */ virtual bool IsPlaceable(void) const; /** Can the anvil repair this item, when a_Item is the second input? */ virtual bool CanRepairWithRawMaterial(short a_ItemType) const; /** Returns whether this tool / item can harvest a specific block (e.g. iron pickaxe can harvest diamond ore, but wooden one can't). Defaults to false unless overridden. */ virtual bool CanHarvestBlock(BLOCKTYPE a_BlockType) const; /** Returns the strength to break a specific block. Defaults to 1 unless overriden. */ virtual float GetBlockBreakingStrength(BLOCKTYPE a_Block) const; protected: static const cItemHandler & For(int a_ItemType); ~cItemHandler() = default; const int m_ItemType; /** Performs the actual placement of this placeable item. The descendant handler should call a_Player.PlaceBlock(s) supplying correct values for the newly placed block. The default handler uses the stored block type and meta copied from the lowest 4 bits of the player's equipped item's damage value. Handlers return what a_Player.PlaceBlock(s) returns, indicating whether the placement was successful. */ virtual bool CommitPlacement(cPlayer & a_Player, const cItem & a_HeldItem, Vector3i a_PlacePosition, eBlockFace a_ClickedBlockFace, Vector3i a_CursorPosition) const; }; ================================================ FILE: src/Items/ItemHoe.h ================================================ #pragma once #include "ItemHandler.h" #include "../World.h" #include "../Entities/Player.h" class cItemHoeHandler final: public cItemHandler { using Super = cItemHandler; public: using Super::Super; virtual bool OnItemUse( cWorld * a_World, cPlayer * a_Player, cBlockPluginInterface & a_PluginInterface, const cItem & a_HeldItem, const Vector3i a_ClickedBlockPos, eBlockFace a_ClickedBlockFace ) const override { if ((a_ClickedBlockFace == BLOCK_FACE_NONE) || (a_ClickedBlockPos.y >= cChunkDef::Height)) { return false; } // Need air above the hoe-d block to transform it: BLOCKTYPE UpperBlockType = a_World->GetBlock(a_ClickedBlockPos.addedY(1)); if (UpperBlockType != E_BLOCK_AIR) { return false; } // Can only transform dirt or grass blocks: BLOCKTYPE BlockType; NIBBLETYPE BlockMeta; if (!a_World->GetBlockTypeMeta(a_ClickedBlockPos, BlockType, BlockMeta)) { return false; } if ((BlockType != E_BLOCK_DIRT) && (BlockType != E_BLOCK_GRASS)) { return false; } if ((BlockType == E_BLOCK_DIRT) && (BlockMeta == E_META_DIRT_PODZOL)) { return false; } // Transform: auto NewBlockType = ((BlockType == E_BLOCK_DIRT) && (BlockMeta == E_META_DIRT_COARSE)) ? E_BLOCK_DIRT : E_BLOCK_FARMLAND; a_World->SetBlock(a_ClickedBlockPos, NewBlockType, 0); a_World->BroadcastSoundEffect("item.hoe.till", a_ClickedBlockPos + Vector3d(0.5, 0.5, 0.5), 1.0f, 0.8f); a_Player->UseEquippedItem(); return true; } virtual short GetDurabilityLossByAction(eDurabilityLostAction a_Action) const override { switch (a_Action) { case dlaAttackEntity: return 1; case dlaBreakBlock: return 0; case dlaBreakBlockInstant: return 0; } UNREACHABLE("Unsupported durability loss action"); } } ; ================================================ FILE: src/Items/ItemHopper.h ================================================ #pragma once #include "ItemHandler.h" class cItemHopperHandler final : public cItemHandler { using Super = cItemHandler; public: using Super::Super; private: inline static NIBBLETYPE BlockFaceToMetaData(eBlockFace a_BlockFace) { switch (a_BlockFace) { case BLOCK_FACE_BOTTOM: return E_META_HOPPER_FACING_YM; case BLOCK_FACE_TOP: return E_META_HOPPER_FACING_YM; case BLOCK_FACE_EAST: return E_META_HOPPER_FACING_XM; case BLOCK_FACE_NORTH: return E_META_HOPPER_FACING_ZP; case BLOCK_FACE_SOUTH: return E_META_HOPPER_FACING_ZM; case BLOCK_FACE_WEST: return E_META_HOPPER_FACING_XP; default: UNREACHABLE("Unsupported block face"); } } virtual bool CommitPlacement(cPlayer & a_Player, const cItem & a_HeldItem, const Vector3i a_PlacePosition, const eBlockFace a_ClickedBlockFace, const Vector3i a_CursorPosition) const override { return a_Player.PlaceBlock(a_PlacePosition, E_BLOCK_HOPPER, BlockFaceToMetaData(a_ClickedBlockFace)); } }; ================================================ FILE: src/Items/ItemItemFrame.h ================================================ #pragma once #include "ItemHandler.h" #include "../Entities/ItemFrame.h" #include "../Entities/Player.h" class cItemItemFrameHandler final: public cItemHandler { using Super = cItemHandler; public: using Super::Super; virtual bool OnItemUse( cWorld * a_World, cPlayer * a_Player, cBlockPluginInterface & a_PluginInterface, const cItem & a_HeldItem, const Vector3i a_ClickedBlockPos, eBlockFace a_ClickedBlockFace ) const override { // Can only place on a side face: if ((a_ClickedBlockFace == BLOCK_FACE_NONE) || (a_ClickedBlockFace == BLOCK_FACE_YP) || (a_ClickedBlockFace == BLOCK_FACE_YM)) { return false; } // Make sure the support block is a valid block to place an item frame on: if (!cHangingEntity::IsValidSupportBlock(a_World->GetBlock(a_ClickedBlockPos))) { return false; } // Make sure block that will be occupied by the item frame is free now: const auto PlacePos = AddFaceDirection(a_ClickedBlockPos, a_ClickedBlockFace); BLOCKTYPE Block = a_World->GetBlock(PlacePos); if (Block != E_BLOCK_AIR) { return false; } // An item frame, centred so pickups spawn nicely. auto ItemFrame = std::make_unique(a_ClickedBlockFace, Vector3d(0.5, 0.5, 0.5) + PlacePos); auto ItemFramePtr = ItemFrame.get(); if (!ItemFramePtr->Initialize(std::move(ItemFrame), *a_World)) { return false; } if (!a_Player->IsGameModeCreative()) { a_Player->GetInventory().RemoveOneEquippedItem(); } return true; } }; ================================================ FILE: src/Items/ItemJackOLantern.h ================================================ #pragma once #include "ItemHandler.h" #include "Blocks/BlockPumpkin.h" class cItemJackOLanternHandler final : public cItemHandler { using Super = cItemHandler; public: using Super::Super; private: virtual bool CommitPlacement(cPlayer & a_Player, const cItem & a_HeldItem, const Vector3i a_PlacePosition, const eBlockFace a_ClickedBlockFace, const Vector3i a_CursorPosition) const override { // Re-use the pumpkin converter for lanterns: return a_Player.PlaceBlock(a_PlacePosition, E_BLOCK_JACK_O_LANTERN, cBlockPumpkinHandler::YawToMetaData(a_Player.GetYaw())); } }; ================================================ FILE: src/Items/ItemLadder.h ================================================ #pragma once #include "ItemHandler.h" #include "Blocks/BlockLadder.h" class cItemLadderHandler final : public cItemHandler { using Super = cItemHandler; public: using Super::Super; private: /** Converts the block face of the neighbor to which the ladder is attached to the ladder block's meta. */ static NIBBLETYPE BlockFaceToMetaData(eBlockFace a_NeighborBlockFace) { switch (a_NeighborBlockFace) { case BLOCK_FACE_ZM: return 0x2; case BLOCK_FACE_ZP: return 0x3; case BLOCK_FACE_XM: return 0x4; case BLOCK_FACE_XP: return 0x5; case BLOCK_FACE_YM: case BLOCK_FACE_YP: return 0x2; default: UNREACHABLE("Unsupported neighbor block face"); } } virtual bool CommitPlacement(cPlayer & a_Player, const cItem & a_HeldItem, const Vector3i a_PlacePosition, eBlockFace a_ClickedBlockFace, const Vector3i a_CursorPosition) const override { const auto & World = *a_Player.GetWorld(); const auto ClickedBlockType = World.GetBlock(AddFaceDirection(a_PlacePosition, a_ClickedBlockFace, true)); // Try finding a suitable neighbor block face for the ladder; start with the given one: if (!cBlockLadderHandler::CanBePlacedOn(ClickedBlockType, a_ClickedBlockFace)) { // Couldn't be placed on whatever face was clicked, last ditch resort - find another face: a_ClickedBlockFace = FindSuitableFace(World, a_PlacePosition); if (a_ClickedBlockFace == BLOCK_FACE_NONE) { // No attachable face found - don't place the ladder: return false; } } return a_Player.PlaceBlock(a_PlacePosition, E_BLOCK_LADDER, BlockFaceToMetaData(a_ClickedBlockFace)); } /** Returns a suitable neighbor's blockface to place the ladder at the specified position. Returns BLOCK_FACE_NONE on failure. */ static eBlockFace FindSuitableFace(const cWorld & a_World, const Vector3i a_Position) { for (const auto Face : { BLOCK_FACE_ZM, BLOCK_FACE_XP, BLOCK_FACE_ZP, BLOCK_FACE_XM }) // Loop through all faces in specific order. { // The direction of Face is relative to the direction the ladder faces. // This is the position, computed inverted, that such a ladder would attach to. const auto NeighborPosition = AddFaceDirection(a_Position, Face, true); if (cBlockLadderHandler::CanBePlacedOn(a_World.GetBlock(NeighborPosition), Face)) { return Face; } } return BLOCK_FACE_NONE; } }; ================================================ FILE: src/Items/ItemLeaves.h ================================================ #pragma once #include "ItemHandler.h" class cItemLeavesHandler final : public cItemHandler { using Super = cItemHandler; public: using Super::Super; virtual bool CommitPlacement(cPlayer & a_Player, const cItem & a_HeldItem, const Vector3i a_PlacePosition, const eBlockFace a_ClickedBlockFace, const Vector3i a_CursorPosition) const override { return a_Player.PlaceBlock( a_PlacePosition, static_cast(m_ItemType), static_cast(a_HeldItem.m_ItemDamage | 0x4) // 0x4 bit set means this is a player-placed leaves block, not to be decayed. ); } } ; ================================================ FILE: src/Items/ItemLever.h ================================================ #pragma once #include "ItemHandler.h" class cItemLeverHandler final : public cItemHandler { using Super = cItemHandler; public: using Super::Super; private: /** Converts the block face of the neighbor to which the lever is attached to the lever block's meta. */ static NIBBLETYPE BlockFaceToMetaData(eBlockFace a_BlockFace) { // Determine lever direction: switch (a_BlockFace) { case BLOCK_FACE_YP: return 0x6; case BLOCK_FACE_XP: return 0x1; case BLOCK_FACE_XM: return 0x2; case BLOCK_FACE_ZP: return 0x3; case BLOCK_FACE_ZM: return 0x4; case BLOCK_FACE_YM: return 0x0; case BLOCK_FACE_NONE: break; } UNREACHABLE("Unsupported block face"); } virtual bool CommitPlacement(cPlayer & a_Player, const cItem & a_HeldItem, const Vector3i a_PlacePosition, const eBlockFace a_ClickedBlockFace, const Vector3i a_CursorPosition) const override { return a_Player.PlaceBlock(a_PlacePosition, static_cast(a_HeldItem.m_ItemType), BlockFaceToMetaData(a_ClickedBlockFace)); } }; ================================================ FILE: src/Items/ItemLighter.h ================================================ #pragma once #include "ItemHandler.h" #include "../World.h" #include "../Entities/Player.h" class cItemLighterHandler final: public cItemHandler { using Super = cItemHandler; public: using Super::Super; virtual bool OnItemUse( cWorld * a_World, cPlayer * a_Player, cBlockPluginInterface & a_PluginInterface, const cItem & a_HeldItem, const Vector3i a_ClickedBlockPos, eBlockFace a_ClickedBlockFace ) const override { if (a_ClickedBlockFace < 0) { return false; } if (!a_Player->IsGameModeCreative()) { if (m_ItemType == E_ITEM_FLINT_AND_STEEL) { a_Player->UseEquippedItem(); } else // Fire charge. { a_Player->GetInventory().RemoveOneEquippedItem(); } } // Activate TNT if we clicked on it while not crouched: if ((a_World->GetBlock(a_ClickedBlockPos) == E_BLOCK_TNT) && !a_Player->IsCrouched()) { a_World->DigBlock(a_ClickedBlockPos, a_Player); a_World->SpawnPrimedTNT(Vector3d(a_ClickedBlockPos) + Vector3d(0.5, 0.5, 0.5)); // 80 ticks to boom return false; } const auto FirePos = AddFaceDirection(a_ClickedBlockPos, a_ClickedBlockFace); if (!cChunkDef::IsValidHeight(FirePos)) { return false; } // Light a fire next to / on top of the block if air: if (a_World->GetBlock(FirePos) == E_BLOCK_AIR) { a_World->PlaceBlock(FirePos, E_BLOCK_FIRE, 0); // The client plays flint and steel sounds, only need to handle fire charges: if (m_ItemType == E_ITEM_FIRE_CHARGE) { a_World->BroadcastSoundEffect("item.firecharge.use", FirePos, 1.0f, 1.04f); } } return false; } } ; ================================================ FILE: src/Items/ItemLilypad.h ================================================ #pragma once #include "ItemHandler.h" #include "../Entities/Player.h" #include "../LineBlockTracer.h" class cItemLilypadHandler final: public cItemHandler { using Super = cItemHandler; public: constexpr cItemLilypadHandler(int a_ItemType): Super(a_ItemType) { } virtual bool IsPlaceable(void) const override { return false; // Set as not placeable so OnItemUse is called } virtual bool OnItemUse( cWorld * a_World, cPlayer * a_Player, cBlockPluginInterface & a_PluginInterface, const cItem & a_HeldItem, const Vector3i a_ClickedBlockPos, eBlockFace a_ClickedBlockFace ) const override { // The client sends BLOCK_FACE_NONE when it determines it should do a tracing-based placement. // Otherwise, a normal block face is sent. if (a_ClickedBlockFace != BLOCK_FACE_NONE) { // The position the client wants the lilypad placed. const auto PlacePos = AddFaceDirection(a_ClickedBlockPos, a_ClickedBlockFace); // Lilypad should not replace non air and non water blocks: if ( const auto BlockToReplace = a_World->GetBlock(PlacePos); (BlockToReplace != E_BLOCK_AIR) && (BlockToReplace != E_BLOCK_WATER) && (BlockToReplace != E_BLOCK_STATIONARY_WATER) ) { return false; } const auto Below = PlacePos.addedY(-1); if (Below.y < 0) { return false; } // Lilypad should be placed only if there is a water block below: if ( const auto BlockBelow = a_World->GetBlock(Below); (BlockBelow != E_BLOCK_WATER) && (BlockBelow != E_BLOCK_STATIONARY_WATER) ) { return false; } a_World->SetBlock(PlacePos, E_BLOCK_LILY_PAD, 0); if (!a_Player->IsGameModeCreative()) { a_Player->GetInventory().RemoveOneEquippedItem(); } return true; } class cCallbacks: public cBlockTracer::cCallbacks { public: virtual bool OnNextBlock(Vector3i a_CBBlockPos, BLOCKTYPE a_CBBlockType, NIBBLETYPE a_CBBlockMeta, eBlockFace a_CBEntryFace) override { if ( !IsBlockWater(a_CBBlockType) || (a_CBBlockMeta != 0) // The hit block should be a source ) { // TODO: Vanilla stops the trace. However, we need to continue the trace, to work around our lack of block bounding box support // which would otherwise mean we misbehave when clicking through the voxel a (e.g.) button occupies. Now, however, we misbehave // when clicking on a block near water... Nonetheless, the former would cause ghost blocks, so continue for now. // Ignore and continue trace: return false; } Position = AddFaceDirection(a_CBBlockPos, BLOCK_FACE_YP); // Always place pad at top of water block return true; } Vector3i Position; } Callbacks; const auto EyePosition = a_Player->GetEyePosition(); const auto End = EyePosition + a_Player->GetLookVector() * 5; if (cLineBlockTracer::Trace(*a_Player->GetWorld(), Callbacks, EyePosition, End)) { // The line traced to completion; no suitable water was found: return false; } const auto BlockToReplace = a_World->GetBlock(Callbacks.Position); if (BlockToReplace != E_BLOCK_AIR) { // Lilypad should not replace non air blocks: return false; } a_World->SetBlock(Callbacks.Position, E_BLOCK_LILY_PAD, 0); if (!a_Player->IsGameModeCreative()) { a_Player->GetInventory().RemoveOneEquippedItem(); } return true; } }; ================================================ FILE: src/Items/ItemMap.h ================================================ #pragma once #include "../Item.h" class cItemMapHandler final: public cItemHandler { using Super = cItemHandler; static const unsigned int DEFAULT_RADIUS = 128; public: using Super::Super; virtual void OnUpdate(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item) const override { cMap * Map = a_World->GetMapManager().GetMapData(static_cast(a_Item.m_ItemDamage)); if (Map == nullptr) { return; } Map->UpdateRadius(*a_Player, DEFAULT_RADIUS); Map->UpdateClient(a_Player); } } ; ================================================ FILE: src/Items/ItemMilk.h ================================================ #pragma once class cItemMilkHandler final: public cItemHandler { using Super = cItemHandler; public: using Super::Super; virtual bool IsDrinkable(short a_ItemDamage) const override { UNUSED(a_ItemDamage); return true; } virtual bool EatItem(cPlayer * a_Player, cItem * a_Item) const override { UNUSED(a_Item); a_Player->ClearEntityEffects(); if (!a_Player->IsGameModeCreative()) { a_Player->ReplaceOneEquippedItemTossRest(cItem(E_ITEM_BUCKET)); } return true; } }; ================================================ FILE: src/Items/ItemMinecart.h ================================================ #pragma once class cItemMinecartHandler final: public cItemHandler { using Super = cItemHandler; public: using Super::Super; virtual bool OnItemUse( cWorld * a_World, cPlayer * a_Player, cBlockPluginInterface & a_PluginInterface, const cItem & a_HeldItem, const Vector3i a_ClickedBlockPos, eBlockFace a_ClickedBlockFace ) const override { // Must be used on a block if (a_ClickedBlockFace < 0) { return false; } // Check that there's rail in there: BLOCKTYPE Block = a_World->GetBlock(a_ClickedBlockPos); switch (Block) { case E_BLOCK_MINECART_TRACKS: case E_BLOCK_POWERED_RAIL: case E_BLOCK_DETECTOR_RAIL: case E_BLOCK_ACTIVATOR_RAIL: { // These are allowed break; } default: { LOGD("Used minecart on an unsuitable block %d (%s)", Block, ItemTypeToString(Block).c_str()); return false; } } // Spawn the minecart: auto SpawnPos = Vector3d(a_ClickedBlockPos) + Vector3d(0.5, 0.5, 0.5); if (a_World->SpawnMinecart(SpawnPos, m_ItemType) == cEntity::INVALID_ID) { return false; } // Remove the item from inventory: if (!a_Player->IsGameModeCreative()) { a_Player->GetInventory().RemoveOneEquippedItem(); } return true; } } ; ================================================ FILE: src/Items/ItemMobHead.h ================================================ #pragma once #include "ItemHandler.h" #include "../World.h" #include "../BlockEntities/MobHeadEntity.h" class cItemMobHeadHandler final : public cItemHandler { using Super = cItemHandler; public: using Super::Super; virtual bool CommitPlacement(cPlayer & a_Player, const cItem & a_HeldItem, const Vector3i a_PlacePosition, const eBlockFace a_ClickedBlockFace, const Vector3i a_CursorPosition) const override { // Cannot place a head at "no face" and from the bottom: if ((a_ClickedBlockFace == BLOCK_FACE_NONE) || (a_ClickedBlockFace == BLOCK_FACE_BOTTOM)) { return false; } // If the placed head is a wither, try to spawn the wither first: if (a_HeldItem.m_ItemDamage == E_META_HEAD_WITHER) { if (TrySpawnWitherAround(a_Player, a_PlacePosition)) { return true; } // Wither not created, proceed with regular head placement } if (!a_Player.PlaceBlock(a_PlacePosition, E_BLOCK_HEAD, BlockFaceToBlockMeta(a_ClickedBlockFace))) { return false; } RegularHeadPlaced(a_Player, a_HeldItem, a_PlacePosition, a_ClickedBlockFace); return true; } /** Called after placing a regular head block with no mob spawning. Adjusts the mob head entity based on the equipped item's data. */ void RegularHeadPlaced(const cPlayer & a_Player, const cItem & a_HeldItem, const Vector3i a_PlacePosition, const eBlockFace a_ClickedBlockFace) const { const auto HeadType = static_cast(a_HeldItem.m_ItemDamage); const auto BlockMeta = static_cast(a_ClickedBlockFace); // Use a callback to set the properties of the mob head block entity: a_Player.GetWorld()->DoWithBlockEntityAt(a_PlacePosition, [&a_Player, HeadType, BlockMeta](cBlockEntity & a_BlockEntity) { ASSERT(a_BlockEntity.GetBlockType() == E_BLOCK_HEAD); auto & MobHeadEntity = static_cast(a_BlockEntity); int Rotation = 0; if (BlockMeta == 1) { Rotation = FloorC(a_Player.GetYaw() * 16.0f / 360.0f + 0.5f) & 0x0f; } MobHeadEntity.SetType(HeadType); MobHeadEntity.SetRotation(static_cast(Rotation)); return false; }); } /** Spawns a wither if the wither skull placed at the specified coords completes wither's spawning formula. Returns true if the wither was created. */ bool TrySpawnWitherAround(cPlayer & a_Player, const Vector3i a_BlockPos) const { // No wither can be created at Y < 2 - not enough space for the formula: if (a_BlockPos.y < 2) { return false; } // Check for all relevant wither locations: static const Vector3i RelCoords[] = { { 0, 0, 0}, { 1, 0, 0}, {-1, 0, 0}, { 0, 0, 1}, { 0, 0, -1}, }; for (auto & RelCoord : RelCoords) { if (TrySpawnWitherAt( *a_Player.GetWorld(), a_Player, a_BlockPos, RelCoord.x, RelCoord.z )) { return true; } } // for i - RelCoords[] return false; } /** Tries to spawn a wither at the specified offset from the placed head block. PlacedHead coords are used to override the block query - at those coords the block is not queried from the world, but assumed to be a head instead. Offset is used to shift the image around the X and Z axis. Returns true iff the wither was created successfully. */ bool TrySpawnWitherAt( cWorld & a_World, cPlayer & a_Player, Vector3i a_PlacedHeadPos, int a_OffsetX, int a_OffsetZ ) const { // Image for the wither at the X axis: static const sSetBlock ImageWitherX[] = { {-1, 0, 0, E_BLOCK_HEAD, 0}, { 0, 0, 0, E_BLOCK_HEAD, 0}, { 1, 0, 0, E_BLOCK_HEAD, 0}, {-1, -1, 0, E_BLOCK_SOULSAND, 0}, { 0, -1, 0, E_BLOCK_SOULSAND, 0}, { 1, -1, 0, E_BLOCK_SOULSAND, 0}, {-1, -2, 0, E_BLOCK_AIR, 0}, { 0, -2, 0, E_BLOCK_SOULSAND, 0}, { 1, -2, 0, E_BLOCK_AIR, 0}, }; // Image for the wither at the Z axis: static const sSetBlock ImageWitherZ[] = { { 0, 0, -1, E_BLOCK_HEAD, 0}, { 0, 0, 0, E_BLOCK_HEAD, 0}, { 0, 0, 1, E_BLOCK_HEAD, 0}, { 0, -1, -1, E_BLOCK_SOULSAND, 0}, { 0, -1, 0, E_BLOCK_SOULSAND, 0}, { 0, -1, 1, E_BLOCK_SOULSAND, 0}, { 0, -2, -1, E_BLOCK_AIR, 0}, { 0, -2, 0, E_BLOCK_SOULSAND, 0}, { 0, -2, 1, E_BLOCK_AIR, 0}, }; // Try to spawn the wither from each image: return ( TrySpawnWitherFromImage( a_World, a_Player, ImageWitherX, a_PlacedHeadPos, a_OffsetX, a_OffsetZ ) || TrySpawnWitherFromImage( a_World, a_Player, ImageWitherZ, a_PlacedHeadPos, a_OffsetX, a_OffsetZ ) ); } /** Tries to spawn a wither from the specified image at the specified offset from the placed head block. PlacedHead coords are used to override the block query - at those coords the block is not queried from the world, but assumed to be a head instead. Offset is used to shift the image around the X and Z axis. Returns true iff the wither was created successfully. */ bool TrySpawnWitherFromImage( cWorld & a_World, cPlayer & a_Player, const sSetBlock (& a_Image)[9], Vector3i a_PlacedHeadPos, int a_OffsetX, int a_OffsetZ ) const { std::array PositionsToClear; // Check each block individually: for (size_t i = 0; i != std::size(a_Image); i++) { // The absolute coords of the block in the image to check. const Vector3i Block( a_PlacedHeadPos.x + a_OffsetX + a_Image[i].GetX(), a_PlacedHeadPos.y + a_Image[i].GetY(), a_PlacedHeadPos.z + a_OffsetZ + a_Image[i].GetZ() ); // If the query is for the head the player is about to place (remember, it hasn't been set into the world yet), short-circuit-evaluate it: if (Block == a_PlacedHeadPos) { if (a_Image[i].m_BlockType != E_BLOCK_HEAD) { return false; // Didn't match. } PositionsToClear[i] = Block; continue; // Matched, continue checking the rest of the image. } // Query the world block: BLOCKTYPE BlockType; NIBBLETYPE BlockMeta; if (!a_World.GetBlockTypeMeta(Block, BlockType, BlockMeta)) { // Cannot query block, assume unloaded chunk, fail to spawn the wither return false; } // Compare the world block: if (BlockType != a_Image[i].m_BlockType) { return false; } // If it is a mob head, check it's a wither skull using the block entity: if ( (BlockType == E_BLOCK_HEAD) && !a_World.DoWithBlockEntityAt(Block, [&](cBlockEntity & a_BlockEntity) { ASSERT(a_BlockEntity.GetBlockType() == E_BLOCK_HEAD); return static_cast(a_BlockEntity).GetType() == SKULL_TYPE_WITHER; }) ) { return false; } // Matched, continue checking: PositionsToClear[i] = Block; } // for i - a_Image // All image blocks matched, try replace the image with air blocks: if ( !a_Player.PlaceBlocks( { { PositionsToClear[0], E_BLOCK_AIR, 0 }, { PositionsToClear[1], E_BLOCK_AIR, 0 }, { PositionsToClear[2], E_BLOCK_AIR, 0 }, { PositionsToClear[3], E_BLOCK_AIR, 0 }, { PositionsToClear[4], E_BLOCK_AIR, 0 }, { PositionsToClear[5], E_BLOCK_AIR, 0 }, { PositionsToClear[6], E_BLOCK_AIR, 0 }, { PositionsToClear[7], E_BLOCK_AIR, 0 }, { PositionsToClear[8], E_BLOCK_AIR, 0 }, }) ) { return false; } // Spawn the wither: int BlockX = a_PlacedHeadPos.x + a_OffsetX; int BlockZ = a_PlacedHeadPos.z + a_OffsetZ; a_World.SpawnMob(static_cast(BlockX) + 0.5, a_PlacedHeadPos.y - 2, static_cast(BlockZ) + 0.5, mtWither, false); AwardSpawnWitherAchievement(a_World, {BlockX, a_PlacedHeadPos.y - 2, BlockZ}); return true; } /** Awards the achievement to all players close to the specified point. */ void AwardSpawnWitherAchievement(cWorld & a_World, Vector3i a_BlockPos) const { Vector3f Pos(a_BlockPos); a_World.ForEachPlayer([=](cPlayer & a_Player) { // If player is close, award achievement: double Dist = (a_Player.GetPosition() - Pos).Length(); if (Dist < 50.0) { a_Player.AwardAchievement(CustomStatistic::AchSpawnWither); } return false; } ); } /** Converts the block face of the placement (which face of the block was clicked to place the head) into the block's metadata value. */ static NIBBLETYPE BlockFaceToBlockMeta(int a_BlockFace) { switch (a_BlockFace) { case BLOCK_FACE_TOP: return 0x01; // On ground (rotation provided in block entity) case BLOCK_FACE_XM: return 0x04; // west wall, facing east case BLOCK_FACE_XP: return 0x05; // east wall, facing west case BLOCK_FACE_ZM: return 0x02; // north wall, facing south case BLOCK_FACE_ZP: return 0x03; // south wall, facing north default: { ASSERT(!"Unhandled block face"); return 0; } } } virtual bool IsPlaceable(void) const override { return true; } } ; ================================================ FILE: src/Items/ItemNetherWart.h ================================================ #pragma once #include "ItemHandler.h" #include "../World.h" class cItemNetherWartHandler final: public cItemHandler { using Super = cItemHandler; public: using Super::Super; virtual bool CommitPlacement(cPlayer & a_Player, const cItem & a_HeldItem, const Vector3i a_PlacePosition, const eBlockFace a_ClickedBlockFace, const Vector3i a_CursorPosition) const override { // Only allow planting nether wart onto the top side of the block: if (a_ClickedBlockFace != BLOCK_FACE_TOP) { return true; } return a_Player.PlaceBlock(a_PlacePosition, E_BLOCK_NETHER_WART, 0); } virtual bool IsPlaceable(void) const override { return true; } } ; ================================================ FILE: src/Items/ItemObserver.h ================================================ #pragma once #include "ItemHandler.h" #include "Blocks/BlockObserver.h" class cItemObserverHandler final : public cItemHandler { using Super = cItemHandler; public: using Super::Super; private: virtual bool CommitPlacement(cPlayer & a_Player, const cItem & a_HeldItem, const Vector3i a_PlacePosition, const eBlockFace a_ClickedBlockFace, const Vector3i a_CursorPosition) const override { return a_Player.PlaceBlock(a_PlacePosition, E_BLOCK_OBSERVER, cBlockObserverHandler::DisplacementYawToMetaData(a_PlacePosition, a_Player.GetEyePosition(), a_Player.GetYaw())); } }; ================================================ FILE: src/Items/ItemPainting.h ================================================ #pragma once #include "ItemHandler.h" #include "../World.h" #include "../Entities/Player.h" #include "../Entities/Painting.h" class cItemPaintingHandler final: public cItemHandler { using Super = cItemHandler; public: using Super::Super; virtual bool OnItemUse( cWorld * a_World, cPlayer * a_Player, cBlockPluginInterface & a_PluginInterface, const cItem & a_HeldItem, const Vector3i a_ClickedBlockPos, eBlockFace a_ClickedBlockFace ) const override { // Paintings can't be flatly placed: if ( (a_ClickedBlockFace == BLOCK_FACE_NONE) || (a_ClickedBlockFace == BLOCK_FACE_YM) || (a_ClickedBlockFace == BLOCK_FACE_YP) ) { return false; } // Make sure the support block is a valid block to place a painting on: if (!cHangingEntity::IsValidSupportBlock(a_World->GetBlock(a_ClickedBlockPos))) { return false; } // Make sure block that will be occupied is free: auto PlacePos = AddFaceDirection(a_ClickedBlockPos, a_ClickedBlockFace); BLOCKTYPE PlaceBlockType = a_World->GetBlock(PlacePos); if (PlaceBlockType != E_BLOCK_AIR) { return false; } // Define all the possible painting titles static const AString gPaintingTitlesList[] = { { "Kebab" }, { "Aztec" }, { "Alban" }, { "Aztec2" }, { "Bomb" }, { "Plant" }, { "Wasteland" }, { "Wanderer" }, { "Graham" }, { "Pool" }, { "Courbet" }, { "Sunset" }, { "Sea" }, { "Creebet" }, { "Match" }, { "Bust" }, { "Stage" }, { "Void" }, { "SkullAndRoses" }, { "Wither" }, { "Fighters" }, { "Skeleton" }, { "DonkeyKong" }, { "Pointer" }, { "Pigscene" }, { "BurningSkull" } }; auto PaintingTitle = gPaintingTitlesList[a_World->GetTickRandomNumber(ARRAYCOUNT(gPaintingTitlesList) - 1)]; // A painting, centred so pickups spawn nicely. auto Painting = std::make_unique(PaintingTitle, a_ClickedBlockFace, Vector3d(0.5, 0.5, 0.5) + PlacePos); auto PaintingPtr = Painting.get(); if (!PaintingPtr->Initialize(std::move(Painting), *a_World)) { return false; } if (!a_Player->IsGameModeCreative()) { a_Player->GetInventory().RemoveOneEquippedItem(); } return true; } }; ================================================ FILE: src/Items/ItemPickaxe.h ================================================ #pragma once #include "ItemHandler.h" class cItemPickaxeHandler final: public cItemHandler { using Super = cItemHandler; public: constexpr cItemPickaxeHandler(int a_ItemType): Super(a_ItemType) { } virtual short GetDurabilityLossByAction(eDurabilityLostAction a_Action) const override { switch (a_Action) { case dlaAttackEntity: return 2; case dlaBreakBlock: return 1; case dlaBreakBlockInstant: return 0; } UNREACHABLE("Unsupported durability loss action"); } char PickaxeLevel() const { switch (m_ItemType) { case E_ITEM_WOODEN_PICKAXE: return 1; case E_ITEM_GOLD_PICKAXE: return 1; case E_ITEM_STONE_PICKAXE: return 2; case E_ITEM_IRON_PICKAXE: return 3; case E_ITEM_DIAMOND_PICKAXE: return 4; default: return 0; } } virtual bool CanHarvestBlock(BLOCKTYPE a_BlockType) const override { // NOTICE: Make sure to update cItemHandler::CanHarvestBlock() if adding new blocks here! switch (a_BlockType) { case E_BLOCK_OBSIDIAN: { return PickaxeLevel() >= 4; } case E_BLOCK_DIAMOND_BLOCK: case E_BLOCK_DIAMOND_ORE: case E_BLOCK_EMERALD_ORE: case E_BLOCK_GOLD_BLOCK: case E_BLOCK_GOLD_ORE: case E_BLOCK_REDSTONE_ORE: case E_BLOCK_REDSTONE_ORE_GLOWING: { return PickaxeLevel() >= 3; } case E_BLOCK_IRON_BLOCK: case E_BLOCK_IRON_ORE: case E_BLOCK_LAPIS_ORE: case E_BLOCK_LAPIS_BLOCK: { return PickaxeLevel() >= 2; } case E_BLOCK_ANVIL: case E_BLOCK_BLACK_GLAZED_TERRACOTTA: case E_BLOCK_BLOCK_OF_COAL: case E_BLOCK_BLOCK_OF_REDSTONE: case E_BLOCK_BLUE_GLAZED_TERRACOTTA: case E_BLOCK_BONE_BLOCK: case E_BLOCK_BREWING_STAND: case E_BLOCK_BRICK: case E_BLOCK_BRICK_STAIRS: case E_BLOCK_BROWN_GLAZED_TERRACOTTA: case E_BLOCK_CAULDRON: case E_BLOCK_COAL_ORE: case E_BLOCK_COBBLESTONE: case E_BLOCK_COBBLESTONE_STAIRS: case E_BLOCK_COBBLESTONE_WALL: case E_BLOCK_CONCRETE: case E_BLOCK_CYAN_GLAZED_TERRACOTTA: case E_BLOCK_DISPENSER: case E_BLOCK_DROPPER: case E_BLOCK_DOUBLE_RED_SANDSTONE_SLAB: case E_BLOCK_DOUBLE_STONE_SLAB: case E_BLOCK_ENCHANTMENT_TABLE: case E_BLOCK_END_BRICKS: case E_BLOCK_END_STONE: case E_BLOCK_FURNACE: case E_BLOCK_GRAY_GLAZED_TERRACOTTA: case E_BLOCK_GREEN_GLAZED_TERRACOTTA: case E_BLOCK_HARDENED_CLAY: case E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE: case E_BLOCK_HOPPER: case E_BLOCK_IRON_BARS: case E_BLOCK_IRON_DOOR: case E_BLOCK_IRON_TRAPDOOR: case E_BLOCK_LIGHT_BLUE_GLAZED_TERRACOTTA: case E_BLOCK_LIGHT_GRAY_GLAZED_TERRACOTTA: case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE: case E_BLOCK_LIT_FURNACE: case E_BLOCK_LIME_GLAZED_TERRACOTTA: case E_BLOCK_MAGENTA_GLAZED_TERRACOTTA: case E_BLOCK_MOB_SPAWNER: case E_BLOCK_MOSSY_COBBLESTONE: case E_BLOCK_MAGMA: case E_BLOCK_NETHER_BRICK: case E_BLOCK_NETHER_BRICK_STAIRS: case E_BLOCK_NETHER_BRICK_FENCE: case E_BLOCK_NETHER_QUARTZ_ORE: case E_BLOCK_NETHERRACK: case E_BLOCK_OBSERVER: case E_BLOCK_ORANGE_GLAZED_TERRACOTTA: case E_BLOCK_PRISMARINE_BLOCK: case E_BLOCK_PINK_GLAZED_TERRACOTTA: case E_BLOCK_PURPLE_GLAZED_TERRACOTTA: case E_BLOCK_PURPUR_BLOCK: case E_BLOCK_PURPUR_DOUBLE_SLAB: case E_BLOCK_PURPUR_PILLAR: case E_BLOCK_PURPUR_SLAB: case E_BLOCK_PURPUR_STAIRS: case E_BLOCK_QUARTZ_BLOCK: case E_BLOCK_QUARTZ_STAIRS: case E_BLOCK_RED_GLAZED_TERRACOTTA: case E_BLOCK_RED_NETHER_BRICK: case E_BLOCK_RED_SANDSTONE: case E_BLOCK_RED_SANDSTONE_STAIRS: case E_BLOCK_SANDSTONE: case E_BLOCK_SANDSTONE_STAIRS: case E_BLOCK_STONE: case E_BLOCK_STONE_BRICKS: case E_BLOCK_STONE_BRICK_STAIRS: case E_BLOCK_STONE_PRESSURE_PLATE: case E_BLOCK_STONE_SLAB: case E_BLOCK_WHITE_GLAZED_TERRACOTTA: case E_BLOCK_YELLOW_GLAZED_TERRACOTTA: { return PickaxeLevel() >= 1; } } return Super::CanHarvestBlock(a_BlockType); } virtual bool CanRepairWithRawMaterial(short a_ItemType) const override { switch (m_ItemType) { case E_ITEM_WOODEN_PICKAXE: return (a_ItemType == E_BLOCK_PLANKS); case E_ITEM_STONE_PICKAXE: return (a_ItemType == E_BLOCK_COBBLESTONE); case E_ITEM_IRON_PICKAXE: return (a_ItemType == E_ITEM_IRON); case E_ITEM_GOLD_PICKAXE: return (a_ItemType == E_ITEM_GOLD); case E_ITEM_DIAMOND_PICKAXE: return (a_ItemType == E_ITEM_DIAMOND); } return false; } virtual float GetBlockBreakingStrength(BLOCKTYPE a_Block) const override { if (!IsBlockMaterialIron(a_Block) && (a_Block != E_BLOCK_ANVIL) && !IsBlockMaterialRock(a_Block)) { return Super::GetBlockBreakingStrength(a_Block); } else { switch (m_ItemType) { case E_ITEM_WOODEN_PICKAXE: return 2.0f; case E_ITEM_STONE_PICKAXE: return 4.0f; case E_ITEM_IRON_PICKAXE: return 6.0f; case E_ITEM_GOLD_PICKAXE: return 12.0f; case E_ITEM_DIAMOND_PICKAXE: return 8.0f; } } ASSERT(!"Something is wrong here... Maybe they are pickaxes out of a new material?"); return 1.0f; } } ; ================================================ FILE: src/Items/ItemPiston.h ================================================ #pragma once #include "ItemHandler.h" #include "Blocks/BlockPiston.h" class cItemPistonHandler final: public cItemHandler { using Super = cItemHandler; public: using Super::Super; private: virtual bool CommitPlacement(cPlayer & a_Player, const cItem & a_HeldItem, const Vector3i a_PlacePosition, const eBlockFace a_ClickedBlockFace, const Vector3i a_CursorPosition) const override { return a_Player.PlaceBlock(a_PlacePosition, static_cast(a_HeldItem.m_ItemType), cBlockPistonHandler::DisplacementYawToMetaData(a_PlacePosition, a_Player.GetEyePosition(), a_Player.GetYaw())); } }; ================================================ FILE: src/Items/ItemPlanks.h ================================================ #pragma once #include "ItemHandler.h" class cItemPlanksHandler final : public cItemHandler { using Super = cItemHandler; public: using Super::Super; private: virtual bool CommitPlacement(cPlayer & a_Player, const cItem & a_HeldItem, const Vector3i a_PlacePosition, const eBlockFace a_ClickedBlockFace, const Vector3i a_CursorPosition) const override { return a_Player.PlaceBlock(a_PlacePosition, static_cast(a_HeldItem.m_ItemType), static_cast(a_HeldItem.m_ItemDamage)); } }; ================================================ FILE: src/Items/ItemPoisonousPotato.h ================================================ #pragma once #include "ItemFood.h" class cItemPoisonousPotatoHandler final: public cItemFoodHandler { using Super = cItemFoodHandler; public: constexpr cItemPoisonousPotatoHandler(int a_ItemType): Super(a_ItemType, FoodInfo(2, 1.2)) { } virtual bool EatItem(cPlayer * a_Player, cItem * a_Item) const override { if (!Super::EatItem(a_Player, a_Item)) { return false; } if (GetRandomProvider().RandBool(0.6)) { a_Player->AddEntityEffect(cEntityEffect::effPoison, 100, 0); } return true; } }; ================================================ FILE: src/Items/ItemPotion.h ================================================ #pragma once #include "../Entities/EntityEffect.h" class cItemPotionHandler final: public cItemHandler { using Super = cItemHandler; public: using Super::Super; // cItemHandler overrides: virtual bool IsDrinkable(short a_ItemDamage) const override { // Drinkable potion if 13th lowest bit is set // Ref.: https://minecraft.wiki/w/Potions#Data_value_table return cEntityEffect::IsPotionDrinkable(a_ItemDamage); } virtual bool OnItemUse( cWorld * a_World, cPlayer * a_Player, cBlockPluginInterface & a_PluginInterface, const cItem & a_HeldItem, const Vector3i a_ClickedBlockPos, eBlockFace a_ClickedBlockFace ) const override { short PotionDamage = a_HeldItem.m_ItemDamage; // Do not throw non-splash potions: if (cEntityEffect::IsPotionDrinkable(PotionDamage)) { return false; } Vector3d Pos = a_Player->GetThrowStartPos(); Vector3d Speed = a_Player->GetLookVector() * 14; // Play sound a_World->BroadcastSoundEffect("entity.arrow.shoot", a_Player->GetPosition() - Vector3d(0, a_Player->GetHeight(), 0), 0.5f, 0.4f / GetRandomProvider().RandReal(0.8f, 1.2f)); if (a_World->CreateProjectile(Pos.x, Pos.y, Pos.z, cProjectileEntity::pkSplashPotion, a_Player, &a_Player->GetEquippedItem(), &Speed) == cEntity::INVALID_ID) { return false; } if (!a_Player->IsGameModeCreative()) { a_Player->GetInventory().RemoveOneEquippedItem(); } return true; } virtual bool EatItem(cPlayer * a_Player, cItem * a_Item) const override { short PotionDamage = a_Item->m_ItemDamage; // Do not drink undrinkable potions: if (!cEntityEffect::IsPotionDrinkable(a_Item->m_ItemDamage)) { return false; } a_Player->AddEntityEffect( cEntityEffect::GetPotionEffectType(PotionDamage), cEntityEffect::GetPotionEffectDuration(PotionDamage), cEntityEffect::GetPotionEffectIntensity(PotionDamage) ); if (!a_Player->IsGameModeCreative()) { a_Player->ReplaceOneEquippedItemTossRest(cItem(E_ITEM_GLASS_BOTTLE)); } return true; } }; ================================================ FILE: src/Items/ItemPumpkin.h ================================================ #pragma once #include "ItemHandler.h" #include "Blocks/BlockPumpkin.h" class cItemPumpkinHandler final: public cItemHandler { using Super = cItemHandler; public: using Super::Super; private: virtual bool CommitPlacement(cPlayer & a_Player, const cItem & a_HeldItem, const Vector3i a_PlacePosition, const eBlockFace a_ClickedBlockFace, const Vector3i a_CursorPosition) const override { // First try spawning a snow golem or an iron golem: if (TrySpawnGolem(a_Player, a_PlacePosition)) { // The client thinks that they placed the pumpkin, let them know it's been replaced: a_Player.SendBlocksAround(a_PlacePosition); return true; } // No golem at these coords, place the block normally: return a_Player.PlaceBlock(a_PlacePosition, E_BLOCK_PUMPKIN, cBlockPumpkinHandler::YawToMetaData(a_Player.GetYaw())); } /** Spawns a snow / iron golem if the shape matches the recipe, supposing that the block placed at the specified coords is a pumpkin. Returns true if the golem blocks are removed (for spawning), false if the recipe is not matched. */ bool TrySpawnGolem(cPlayer & a_Player, const Vector3i a_PumpkinPos) const { // A golem can't form with a pumpkin below level 2 or above level 255: if ((a_PumpkinPos.y < 2) || (a_PumpkinPos.y >= cChunkDef::Height)) { return false; } auto & World = *a_Player.GetWorld(); // Decide which golem to try spawning based on the block below the placed pumpkin: switch (World.GetBlock(a_PumpkinPos.addedY(-1))) { case E_BLOCK_SNOW_BLOCK: return TrySpawnSnowGolem(World, a_Player, a_PumpkinPos); case E_BLOCK_IRON_BLOCK: return TrySpawnIronGolem(World, a_Player, a_PumpkinPos); default: { // No golem here: return false; } } } /** Spawns a snow golem if the shape matches the recipe, supposing that the block placed at the specified coords is a pumpkin. Returns true if the golem blocks are removed (for spawning), false if the recipe is not matched. Assumes that the block below the specified block has already been checked and is a snow block. */ bool TrySpawnSnowGolem(cWorld & a_World, cPlayer & a_Player, const Vector3i a_PumpkinPos) const { ASSERT(a_PumpkinPos.y > 1); ASSERT(a_World.GetBlock(a_PumpkinPos.addedY(-1)) == E_BLOCK_SNOW_BLOCK); // Need one more snow block 2 blocks below the pumpkin: if (a_World.GetBlock(a_PumpkinPos.addedY(-2)) != E_BLOCK_SNOW_BLOCK) { return false; } // Try to place air blocks where the original recipe blocks were: if ( !a_Player.PlaceBlocks( { { a_PumpkinPos, E_BLOCK_AIR, 0 }, // Head { a_PumpkinPos.addedY(-1), E_BLOCK_AIR, 0 }, // Torso { a_PumpkinPos.addedY(-2), E_BLOCK_AIR, 0 } // Legs }) ) { return false; } // Spawn the golem: auto GolemPos = Vector3d(a_PumpkinPos) + Vector3d(0.5, -2, 0.5); a_World.SpawnMob(GolemPos.x, GolemPos.y, GolemPos.z, mtSnowGolem, false); return true; } /** Spawns an iron golem if the shape matches the recipe, supposing that the block placed at the specified coords is a pumpkin. Returns true if the golem blocks are removed (for spawning), false if the recipe is not matched. Assumes that the block below the specified block has already been checked and is an iron block. */ bool TrySpawnIronGolem(cWorld & a_World, cPlayer & a_Player, const Vector3i a_PumpkinPos) const { ASSERT(a_PumpkinPos.y > 1); ASSERT(a_World.GetBlock(a_PumpkinPos.addedY(-1)) == E_BLOCK_IRON_BLOCK); // Need one more iron block 2 blocks below the pumpkin: if (a_World.GetBlock(a_PumpkinPos.addedY(-2)) != E_BLOCK_IRON_BLOCK) { return false; } // Check the two arm directions (X, Z) using a loop over two sets of offset vectors: auto BodyPos = a_PumpkinPos.addedY(-1); static const Vector3i ArmOffsets[] = { {1, 0, 0}, {0, 0, 1}, }; for (size_t i = 0; i < ARRAYCOUNT(ArmOffsets); i++) { // If the arm blocks don't match, bail out of this loop repetition: if ( (a_World.GetBlock(BodyPos + ArmOffsets[i]) != E_BLOCK_IRON_BLOCK) || (a_World.GetBlock(BodyPos - ArmOffsets[i]) != E_BLOCK_IRON_BLOCK) ) { continue; } // Try to place air blocks where the original recipe blocks were: if ( !a_Player.PlaceBlocks( { { a_PumpkinPos, E_BLOCK_AIR, 0 }, // Head { BodyPos, E_BLOCK_AIR, 0 }, // Torso { BodyPos.addedY(-1), E_BLOCK_AIR, 0 }, // Legs { BodyPos + ArmOffsets[i], E_BLOCK_AIR, 0 }, // Arm { BodyPos - ArmOffsets[i], E_BLOCK_AIR, 0 } // Arm }) ) { return false; } // Spawn the golem: auto GolemPos = Vector3d(a_PumpkinPos) + Vector3d(0.5, -2, 0.5); a_World.SpawnMob(GolemPos.x, GolemPos.y, GolemPos.z, mtIronGolem, false); return true; } // for i - ArmOffsets[] // Neither arm offset matched, this thing is not a complete golem return false; } }; ================================================ FILE: src/Items/ItemQuartz.h ================================================ #pragma once #include "ItemHandler.h" class cItemQuartzHandler final: public cItemHandler { using Super = cItemHandler; public: using Super::Super; private: /** Converts the block face of the pillar block's "base" to the block's metadata. */ static NIBBLETYPE BlockFaceToMetaData(eBlockFace a_BlockFace) { switch (a_BlockFace) { case BLOCK_FACE_YM: case BLOCK_FACE_YP: { return E_META_QUARTZ_PILLAR; // Top or bottom. } case BLOCK_FACE_ZP: case BLOCK_FACE_ZM: { return 0x4; // North or south. } case BLOCK_FACE_XP: case BLOCK_FACE_XM: { return 0x3; // East or west. } default: UNREACHABLE("Unsupported block face"); } } virtual bool CommitPlacement(cPlayer & a_Player, const cItem & a_HeldItem, const Vector3i a_PlacePosition, const eBlockFace a_ClickedBlockFace, const Vector3i a_CursorPosition) const override { const auto Meta = static_cast(a_Player.GetEquippedItem().m_ItemDamage); // Pillar block needs additional direction in the metadata: if (Meta == E_META_QUARTZ_PILLAR) { return a_Player.PlaceBlock(a_PlacePosition, E_BLOCK_QUARTZ_BLOCK, BlockFaceToMetaData(a_ClickedBlockFace)); } return a_Player.PlaceBlock(a_PlacePosition, E_BLOCK_QUARTZ_BLOCK, Meta); } }; ================================================ FILE: src/Items/ItemRail.h ================================================ #pragma once #include "ItemHandler.h" #include "Blocks/BlockRail.h" class cItemRailHandler final : public cItemHandler { using Super = cItemHandler; public: using Super::Super; private: virtual bool CommitPlacement(cPlayer & a_Player, const cItem & a_HeldItem, const Vector3i a_PlacePosition, const eBlockFace a_ClickedBlockFace, const Vector3i a_CursorPosition) const override { cChunkInterface ChunkInterface(a_Player.GetWorld()->GetChunkMap()); const auto RailType = static_cast(a_HeldItem.m_ItemType); return a_Player.PlaceBlock(a_PlacePosition, RailType, cBlockRailHandler::FindMeta(ChunkInterface, a_PlacePosition, RailType)); } }; ================================================ FILE: src/Items/ItemRawChicken.h ================================================ #pragma once #include "ItemFood.h" class cItemRawChickenHandler final: public cItemFoodHandler { using Super = cItemFoodHandler; public: constexpr cItemRawChickenHandler(int a_ItemType): Super(a_ItemType, FoodInfo(2, 1.2)) { } virtual bool EatItem(cPlayer * a_Player, cItem * a_Item) const override { if (!Super::EatItem(a_Player, a_Item)) { return false; } if (GetRandomProvider().RandBool(0.3)) { a_Player->AddEntityEffect(cEntityEffect::effHunger, 600, 0); } return true; } }; ================================================ FILE: src/Items/ItemRawFish.h ================================================ #pragma once #include "ItemFood.h" class cItemRawFishHandler final: public cItemFoodHandler { using Super = cItemFoodHandler; public: constexpr cItemRawFishHandler(int a_ItemType): Super(a_ItemType, FoodInfo(0, 0)) { } virtual FoodInfo GetFoodInfo(const cItem * a_Item) const override { static const FoodInfo RawFishInfos[] = { FoodInfo(2, 0.4), // Raw fish FoodInfo(2, 0.2), // Raw salmon FoodInfo(1, 0.2), // Clownfish FoodInfo(1, 0.2), // Pufferfish }; if (a_Item->m_ItemDamage >= static_cast(ARRAYCOUNT(RawFishInfos))) { LOGWARNING("Unknown raw fish type '%d'", a_Item->m_ItemDamage); return FoodInfo(0, 0); } return RawFishInfos[a_Item->m_ItemDamage]; } virtual bool EatItem(cPlayer * a_Player, cItem * a_Item) const override { if (!Super::EatItem(a_Player, a_Item)) { return false; } if (a_Item->m_ItemDamage == E_META_RAW_FISH_PUFFERFISH) { a_Player->AddEntityEffect(cEntityEffect::effHunger, 20 * 15, 2); a_Player->AddEntityEffect(cEntityEffect::effNausea, 20 * 15, 1); a_Player->AddEntityEffect(cEntityEffect::effPoison, 20 * 60, 3); } return true; } }; ================================================ FILE: src/Items/ItemRedstoneDust.h ================================================ #pragma once #include "ItemHandler.h" class cItemRedstoneDustHandler final: public cItemHandler { using Super = cItemHandler; public: using Super::Super; virtual bool CommitPlacement(cPlayer & a_Player, const cItem & a_HeldItem, const Vector3i a_PlacePosition, const eBlockFace a_ClickedBlockFace, const Vector3i a_CursorPosition) const override { return a_Player.PlaceBlock(a_PlacePosition, E_BLOCK_REDSTONE_WIRE, 0); } virtual bool IsPlaceable(void) const override { return true; } } ; ================================================ FILE: src/Items/ItemRedstoneRepeater.h ================================================ #pragma once #include "ItemHandler.h" #include "../Blocks/BlockRedstoneRepeater.h" class cItemRedstoneRepeaterHandler final : public cItemHandler { using Super = cItemHandler; public: using Super::Super; virtual bool CommitPlacement(cPlayer & a_Player, const cItem & a_HeldItem, const Vector3i a_PlacePosition, const eBlockFace a_ClickedBlockFace, const Vector3i a_CursorPosition) const override { return a_Player.PlaceBlock(a_PlacePosition, E_BLOCK_REDSTONE_REPEATER_OFF, cBlockRedstoneRepeaterHandler::YawToMetaData(a_Player.GetYaw())); } virtual bool IsPlaceable() const override { return true; } } ; ================================================ FILE: src/Items/ItemRottenFlesh.h ================================================ #pragma once #include "ItemFood.h" class cItemRottenFleshHandler final: public cItemFoodHandler { using Super = cItemFoodHandler; public: constexpr cItemRottenFleshHandler(int a_ItemType): Super(a_ItemType, FoodInfo(4, 0.8)) { } virtual bool EatItem(cPlayer * a_Player, cItem * a_Item) const override { if (!Super::EatItem(a_Player, a_Item)) { return false; } if (GetRandomProvider().RandBool(0.8)) { a_Player->AddEntityEffect(cEntityEffect::effHunger, 600, 0); } return true; } }; ================================================ FILE: src/Items/ItemSapling.h ================================================ #pragma once #include "ItemHandler.h" class cItemSaplingHandler final : public cItemHandler { using Super = cItemHandler; public: using Super::Super; virtual bool CommitPlacement(cPlayer & a_Player, const cItem & a_HeldItem, const Vector3i a_PlacePosition, const eBlockFace a_ClickedBlockFace, const Vector3i a_CursorPosition) const override { return a_Player.PlaceBlock( a_PlacePosition, static_cast(m_ItemType), static_cast(a_HeldItem.m_ItemDamage & 0x07) // Allow only the lowest 3 bits (top bit is for growth). ); } } ; ================================================ FILE: src/Items/ItemSeeds.h ================================================ #pragma once #include "ItemHandler.h" #include "../World.h" class cItemSeedsHandler: public cItemHandler { using Super = cItemHandler; public: constexpr cItemSeedsHandler(int a_ItemType): Super(a_ItemType) { } virtual bool CommitPlacement(cPlayer & a_Player, const cItem & a_HeldItem, const Vector3i a_PlacePosition, const eBlockFace a_ClickedBlockFace, const Vector3i a_CursorPosition) const override { // Only allow planting seeds from the top side of the block: if (a_ClickedBlockFace != BLOCK_FACE_TOP) { return false; } BLOCKTYPE BlockType; // Get the produce block based on the seed item: switch (m_ItemType) { case E_ITEM_BEETROOT_SEEDS: BlockType = E_BLOCK_BEETROOTS; break; case E_ITEM_CARROT: BlockType = E_BLOCK_CARROTS; break; case E_ITEM_MELON_SEEDS: BlockType = E_BLOCK_MELON_STEM; break; case E_ITEM_POTATO: BlockType = E_BLOCK_POTATOES; break; case E_ITEM_PUMPKIN_SEEDS: BlockType = E_BLOCK_PUMPKIN_STEM; break; case E_ITEM_SEEDS: BlockType = E_BLOCK_CROPS; break; default: UNREACHABLE("Unsupported seed type"); } return a_Player.PlaceBlock(a_PlacePosition, BlockType, 0); } virtual bool IsPlaceable(void) const override { return true; } protected: ~cItemSeedsHandler() = default; } ; class cItemSimpleSeedsHandler final: public cItemSeedsHandler { using cItemSeedsHandler::cItemSeedsHandler; }; ================================================ FILE: src/Items/ItemShears.h ================================================ #pragma once #include "ItemHandler.h" #include "../World.h" #include "../Entities/Player.h" class cItemShearsHandler final: public cItemHandler { using Super = cItemHandler; public: using Super::Super; virtual bool OnDiggingBlock( cWorld * a_World, cPlayer * a_Player, const cItem & a_HeldItem, const Vector3i a_ClickedBlockPos, eBlockFace a_ClickedBlockFace ) const override { BLOCKTYPE Block; NIBBLETYPE BlockMeta; if (!a_World->GetBlockTypeMeta(a_ClickedBlockPos, Block, BlockMeta)) { return false; } if ((Block == E_BLOCK_LEAVES) || (Block == E_BLOCK_NEW_LEAVES)) { a_World->DropBlockAsPickups(a_ClickedBlockPos, a_Player, &a_HeldItem); return true; } return false; } virtual bool CanHarvestBlock(BLOCKTYPE a_BlockType) const override { switch (a_BlockType) { case E_BLOCK_COBWEB: case E_BLOCK_DEAD_BUSH: case E_BLOCK_VINES: { return true; } } return Super::CanHarvestBlock(a_BlockType); } virtual short GetDurabilityLossByAction(eDurabilityLostAction a_Action) const override { switch (a_Action) { case dlaAttackEntity: return 0; case dlaBreakBlock: return 0; case dlaBreakBlockInstant: return 1; } UNREACHABLE("Unsupported durability loss action"); } virtual float GetBlockBreakingStrength(BLOCKTYPE a_Block) const override { if ((a_Block == E_BLOCK_COBWEB) || IsBlockMaterialLeaves(a_Block)) { return 15.0f; } else if (a_Block == E_BLOCK_WOOL) { return 5.0f; } else { return Super::GetBlockBreakingStrength(a_Block); } } } ; ================================================ FILE: src/Items/ItemShovel.h ================================================ #pragma once #include "ItemHandler.h" #include "../World.h" #include "../Entities/Player.h" #include "../BlockInServerPluginInterface.h" class cItemShovelHandler final: public cItemHandler { using Super = cItemHandler; public: using Super::Super; virtual short GetDurabilityLossByAction(eDurabilityLostAction a_Action) const override { switch (a_Action) { case dlaAttackEntity: return 2; case dlaBreakBlock: return 1; case dlaBreakBlockInstant: return 0; } UNREACHABLE("Unsupported durability loss action"); } virtual bool CanHarvestBlock(BLOCKTYPE a_BlockType) const override { if (a_BlockType == E_BLOCK_SNOW) { return true; } return Super::CanHarvestBlock(a_BlockType); } virtual bool CanRepairWithRawMaterial(short a_ItemType) const override { switch (m_ItemType) { case E_ITEM_WOODEN_SHOVEL: return (a_ItemType == E_BLOCK_PLANKS); case E_ITEM_STONE_SHOVEL: return (a_ItemType == E_BLOCK_COBBLESTONE); case E_ITEM_IRON_SHOVEL: return (a_ItemType == E_ITEM_IRON); case E_ITEM_GOLD_SHOVEL: return (a_ItemType == E_ITEM_GOLD); case E_ITEM_DIAMOND_SHOVEL: return (a_ItemType == E_ITEM_DIAMOND); } return false; } virtual float GetBlockBreakingStrength(BLOCKTYPE a_Block) const override { switch (a_Block) { case E_BLOCK_CLAY: case E_BLOCK_CONCRETE_POWDER: case E_BLOCK_DIRT: case E_BLOCK_FARMLAND: case E_BLOCK_GRASS: case E_BLOCK_GRASS_PATH: case E_BLOCK_GRAVEL: case E_BLOCK_MYCELIUM: case E_BLOCK_SAND: case E_BLOCK_SNOW: case E_BLOCK_SNOW_BLOCK: case E_BLOCK_SOULSAND: { switch (m_ItemType) { case E_ITEM_WOODEN_SHOVEL: return 2.0f; case E_ITEM_STONE_SHOVEL: return 4.0f; case E_ITEM_IRON_SHOVEL: return 6.0f; case E_ITEM_GOLD_SHOVEL: return 12.0f; case E_ITEM_DIAMOND_SHOVEL: return 8.0f; } break; } } return Super::GetBlockBreakingStrength(a_Block); } }; ================================================ FILE: src/Items/ItemSideways.h ================================================ #pragma once #include "ItemHandler.h" #include "Blocks/BlockSideways.h" /** Handler for blocks that have 3 orientations (hay bale, log), specified by the upper 2 bits in meta. Handles setting the correct orientation on placement. Additionally supports the metadata specifying block sub-type in its lower 2 bits. */ class cItemSidewaysHandler final : public cItemHandler { using Super = cItemHandler; public: using Super::Super; private: static NIBBLETYPE BlockFaceToMetaData(eBlockFace a_BlockFace, NIBBLETYPE a_Meta) { switch (a_BlockFace) { case BLOCK_FACE_YM: case BLOCK_FACE_YP: { return a_Meta; // Top or bottom, just return original. } case BLOCK_FACE_ZP: case BLOCK_FACE_ZM: { return a_Meta | 0x8; // North or south. } case BLOCK_FACE_XP: case BLOCK_FACE_XM: { return a_Meta | 0x4; // East or west. } default: UNREACHABLE("Unsupported block face"); } } virtual bool CommitPlacement(cPlayer & a_Player, const cItem & a_HeldItem, const Vector3i a_PlacePosition, const eBlockFace a_ClickedBlockFace, const Vector3i a_CursorPosition) const override { return a_Player.PlaceBlock(a_PlacePosition, static_cast(a_HeldItem.m_ItemType), BlockFaceToMetaData(a_ClickedBlockFace, static_cast(a_HeldItem.m_ItemDamage))); } }; ================================================ FILE: src/Items/ItemSign.h ================================================ #pragma once #include "ItemHandler.h" #include "../World.h" #include "../ClientHandle.h" class cItemSignHandler final: public cItemHandler { using Super = cItemHandler; public: using Super::Super; private: /** Converts the block face of the neighbor to which the wallsign is attached to the wallsign block's meta. */ static NIBBLETYPE BlockFaceToMetaData(eBlockFace a_NeighborBlockFace) { switch (a_NeighborBlockFace) { case BLOCK_FACE_ZM: return 0x02; case BLOCK_FACE_ZP: return 0x03; case BLOCK_FACE_XM: return 0x04; case BLOCK_FACE_XP: return 0x05; case BLOCK_FACE_NONE: case BLOCK_FACE_YP: case BLOCK_FACE_YM: { break; } } return 0x02; } virtual bool CommitPlacement(cPlayer & a_Player, const cItem & a_HeldItem, const Vector3i a_PlacePosition, const eBlockFace a_ClickedBlockFace, const Vector3i a_CursorPosition) const override { if (a_ClickedBlockFace == BLOCK_FACE_TOP) { if (!a_Player.PlaceBlock(a_PlacePosition, E_BLOCK_SIGN_POST, RotationToMetaData(a_Player.GetYaw()))) { return false; } } else if (!a_Player.PlaceBlock(a_PlacePosition, E_BLOCK_WALLSIGN, BlockFaceToMetaData(a_ClickedBlockFace))) { return false; } // After successfully placing the sign, open the sign editor for the player: a_Player.GetClientHandle()->SendEditSign(a_PlacePosition); return true; } virtual bool IsPlaceable(void) const override { return true; } /** Converts the (player) rotation to placed-signpost block meta. */ static NIBBLETYPE RotationToMetaData(double a_Rotation) { a_Rotation += 180 + (180.f / 16); // So it's not aligned with axis. if (a_Rotation > 360) { a_Rotation -= 360; } a_Rotation = (a_Rotation / 360) * 16; return static_cast(a_Rotation) % 16; } } ; ================================================ FILE: src/Items/ItemSlab.h ================================================ #pragma once #include "ItemHandler.h" class cItemSlabHandler final: public cItemHandler { using Super = cItemHandler; public: using Super::Super; private: virtual bool CommitPlacement(cPlayer & a_Player, const cItem & a_HeldItem, const Vector3i a_PlacePosition, const eBlockFace a_ClickedBlockFace, const Vector3i a_CursorPosition) const override { // Confer BlockSlab.h, which we're in cahoots with to make the below logic work. // If clicking a slab, combine it into a double-slab: if (cBlockSlabHandler::IsAnySlabType(a_Player.GetWorld()->GetBlock(a_PlacePosition))) { if (!a_Player.PlaceBlock(a_PlacePosition, GetDoubleSlabType(static_cast(a_HeldItem.m_ItemType)), static_cast(a_HeldItem.m_ItemDamage))) { return false; } a_Player.SendBlocksAround(a_PlacePosition, 2); // (see below) return true; } // Set the correct metadata based on player equipped item: if (!a_Player.PlaceBlock(a_PlacePosition, static_cast(a_HeldItem.m_ItemType), FaceToMetaData(static_cast(a_HeldItem.m_ItemDamage), a_ClickedBlockFace, a_CursorPosition))) { return false; } /* This is a workaround for versions < 1.13, where the client combines a slab in the direction of the clicked block face of a block ignoring build collision, rather than replacing said block. Resend blocks to the client to fix the bug. Ref.: https://forum.cuberite.org/thread-434-post-17388.html#pid17388 */ a_Player.SendBlocksAround(a_PlacePosition, 2); return true; } static NIBBLETYPE FaceToMetaData(const NIBBLETYPE a_BaseMeta, const eBlockFace a_ClickedBlockFace, const Vector3i a_CursorPosition) { switch (a_ClickedBlockFace) { case BLOCK_FACE_TOP: { // Bottom half slab block: return a_BaseMeta & 0x07; } case BLOCK_FACE_BOTTOM: { // Top half slab block: return a_BaseMeta | 0x08; } case BLOCK_FACE_EAST: case BLOCK_FACE_NORTH: case BLOCK_FACE_SOUTH: case BLOCK_FACE_WEST: { if (a_CursorPosition.y > 7) { // Cursor at top half of block, place top slab: return a_BaseMeta | 0x08; } else { // Cursor at bottom half of block, place bottom slab: return a_BaseMeta & 0x07; } } default: UNREACHABLE("Unhandled block face"); } } /** Converts the single-slab blocktype to its equivalent double-slab blocktype. */ static BLOCKTYPE GetDoubleSlabType(BLOCKTYPE a_SingleSlabBlockType) { switch (a_SingleSlabBlockType) { case E_BLOCK_STONE_SLAB: return E_BLOCK_DOUBLE_STONE_SLAB; case E_BLOCK_WOODEN_SLAB: return E_BLOCK_DOUBLE_WOODEN_SLAB; case E_BLOCK_RED_SANDSTONE_SLAB: return E_BLOCK_DOUBLE_RED_SANDSTONE_SLAB; case E_BLOCK_PURPUR_SLAB: return E_BLOCK_PURPUR_DOUBLE_SLAB; } UNREACHABLE("Unhandled slab type"); } }; ================================================ FILE: src/Items/ItemSnow.h ================================================ #pragma once #include "ItemHandler.h" class cItemSnowHandler final : public cItemHandler { using Super = cItemHandler; public: using Super::Super; private: virtual bool CommitPlacement(cPlayer & a_Player, const cItem & a_HeldItem, const Vector3i a_PlacePosition, const eBlockFace a_ClickedBlockFace, const Vector3i a_CursorPosition) const override { BLOCKTYPE Block; NIBBLETYPE Meta; a_Player.GetWorld()->GetBlockTypeMeta(a_PlacePosition, Block, Meta); // Check if incrementing existing snow height: if (Block == E_BLOCK_SNOW) { ASSERT(Meta < 7); // BlockSnow.h ensures that if we replace a snow layer, it won't be at max height. Meta++; } else { // First time placement: Meta = 0; } return a_Player.PlaceBlock(a_PlacePosition, E_BLOCK_SNOW, Meta); } }; ================================================ FILE: src/Items/ItemSoup.h ================================================ #pragma once #include "ItemFood.h" #include "../World.h" class cItemSoupHandler final: public cItemFoodHandler { using Super = cItemFoodHandler; public: constexpr cItemSoupHandler(int a_ItemType, FoodInfo a_FoodInfo): Super(a_ItemType, a_FoodInfo) { } virtual bool EatItem(cPlayer * a_Player, cItem * a_Item) const override { // Skip over food handler, which does removal for us. if (!cItemHandler::EatItem(a_Player, a_Item)) { return false; } if (!a_Player->IsGameModeCreative()) { a_Player->ReplaceOneEquippedItemTossRest(cItem(E_ITEM_BOWL)); } return true; } }; ================================================ FILE: src/Items/ItemSpawnEgg.h ================================================ #pragma once #include "ItemHandler.h" #include "../World.h" #include "../Entities/Player.h" class cItemSpawnEggHandler final: public cItemHandler { using Super = cItemHandler; public: using Super::Super; virtual bool OnItemUse( cWorld * a_World, cPlayer * a_Player, cBlockPluginInterface & a_PluginInterface, const cItem & a_HeldItem, const Vector3i a_ClickedBlockPos, eBlockFace a_ClickedBlockFace ) const override { // Must click a valid block: if (a_ClickedBlockFace < 0) { return false; } auto PlacementPos = AddFaceDirection(a_ClickedBlockPos, a_ClickedBlockFace); if (a_ClickedBlockFace == BLOCK_FACE_YM) { PlacementPos.y--; } auto MonsterType = ItemDamageToMonsterType(a_HeldItem.m_ItemDamage); if ( (MonsterType != mtInvalidType) && // Valid monster type (a_World->SpawnMob(PlacementPos.x + 0.5, PlacementPos.y, PlacementPos.z + 0.5, MonsterType, false) != cEntity::INVALID_ID)) // Spawning succeeded { if (!a_Player->IsGameModeCreative()) { // The mob was spawned, "use" the item: a_Player->GetInventory().RemoveOneEquippedItem(); } return true; } return false; } /** Converts the Spawn egg item damage to the monster type to spawn. Returns mtInvalidType for invalid damage values. */ static eMonsterType ItemDamageToMonsterType(short a_ItemDamage) { switch (a_ItemDamage) { case E_META_SPAWN_EGG_BAT: return mtBat; case E_META_SPAWN_EGG_BLAZE: return mtBlaze; case E_META_SPAWN_EGG_CAVE_SPIDER: return mtCaveSpider; case E_META_SPAWN_EGG_CHICKEN: return mtChicken; case E_META_SPAWN_EGG_COW: return mtCow; case E_META_SPAWN_EGG_CREEPER: return mtCreeper; case E_META_SPAWN_EGG_ENDERMAN: return mtEnderman; case E_META_SPAWN_EGG_ENDERMITE: return mtEndermite; case E_META_SPAWN_EGG_GHAST: return mtGhast; case E_META_SPAWN_EGG_GUARDIAN: return mtGuardian; case E_META_SPAWN_EGG_HORSE: return mtHorse; case E_META_SPAWN_EGG_MAGMA_CUBE: return mtMagmaCube; case E_META_SPAWN_EGG_MOOSHROOM: return mtMooshroom; case E_META_SPAWN_EGG_OCELOT: return mtOcelot; case E_META_SPAWN_EGG_PIG: return mtPig; case E_META_SPAWN_EGG_RABBIT: return mtRabbit; case E_META_SPAWN_EGG_SHEEP: return mtSheep; case E_META_SPAWN_EGG_SILVERFISH: return mtSilverfish; case E_META_SPAWN_EGG_SKELETON: return mtSkeleton; case E_META_SPAWN_EGG_SLIME: return mtSlime; case E_META_SPAWN_EGG_SPIDER: return mtSpider; case E_META_SPAWN_EGG_SQUID: return mtSquid; case E_META_SPAWN_EGG_VILLAGER: return mtVillager; case E_META_SPAWN_EGG_WITCH: return mtWitch; case E_META_SPAWN_EGG_WITHER_SKELETON: return mtWitherSkeleton; case E_META_SPAWN_EGG_WOLF: return mtWolf; case E_META_SPAWN_EGG_ZOMBIE: return mtZombie; case E_META_SPAWN_EGG_ZOMBIE_PIGMAN: return mtZombiePigman; case E_META_SPAWN_EGG_ZOMBIE_VILLAGER: return mtZombieVillager; default: return mtInvalidType; } } } ; ================================================ FILE: src/Items/ItemSpiderEye.h ================================================ #pragma once #include "ItemFood.h" class cItemSpiderEyeHandler final: public cItemFoodHandler { using Super = cItemFoodHandler; public: constexpr cItemSpiderEyeHandler(int a_ItemType): Super(a_ItemType, FoodInfo(2, 3.2)) { } virtual bool EatItem(cPlayer * a_Player, cItem * a_Item) const override { if (!Super::EatItem(a_Player, a_Item)) { return false; } a_Player->AddEntityEffect(cEntityEffect::effPoison, 100, 0); return true; } }; ================================================ FILE: src/Items/ItemStairs.h ================================================ #pragma once #include "ItemHandler.h" #include "Blocks/BlockStairs.h" class cItemStairsHandler final : public cItemHandler { using Super = cItemHandler; public: using Super::Super; private: virtual bool CommitPlacement(cPlayer & a_Player, const cItem & a_HeldItem, const Vector3i a_PlacePosition, const eBlockFace a_ClickedBlockFace, const Vector3i a_CursorPosition) const override { NIBBLETYPE Meta = cBlockStairsHandler::YawToMetaData(a_Player.GetYaw()); switch (a_ClickedBlockFace) { case BLOCK_FACE_TOP: break; case BLOCK_FACE_BOTTOM: Meta |= 0x4; break; // When placing onto a bottom face, always place an upside-down stairs block. case BLOCK_FACE_EAST: case BLOCK_FACE_NORTH: case BLOCK_FACE_SOUTH: case BLOCK_FACE_WEST: { // When placing onto a sideways face, check cursor, if in top half, make it an upside-down stairs block: if (a_CursorPosition.y > 8) { Meta |= 0x4; } break; } default: UNREACHABLE("Unhandled block face"); } return a_Player.PlaceBlock(a_PlacePosition, static_cast(a_HeldItem.m_ItemType), Meta); } }; ================================================ FILE: src/Items/ItemSword.h ================================================ #pragma once #include "ItemHandler.h" #include "../BlockInfo.h" class cItemSwordHandler final : public cItemHandler { using Super = cItemHandler; public: using Super::Super; virtual bool CanHarvestBlock(BLOCKTYPE a_BlockType) const override { if (a_BlockType == E_BLOCK_COBWEB) { return true; } return Super::CanHarvestBlock(a_BlockType); } virtual bool CanRepairWithRawMaterial(short a_ItemType) const override { switch (m_ItemType) { case E_ITEM_WOODEN_SWORD: return (a_ItemType == E_BLOCK_PLANKS); case E_ITEM_STONE_SWORD: return (a_ItemType == E_BLOCK_COBBLESTONE); case E_ITEM_IRON_SWORD: return (a_ItemType == E_ITEM_IRON); case E_ITEM_GOLD_SWORD: return (a_ItemType == E_ITEM_GOLD); case E_ITEM_DIAMOND_SWORD: return (a_ItemType == E_ITEM_DIAMOND); } return false; } virtual short GetDurabilityLossByAction(eDurabilityLostAction a_Action) const override { switch (a_Action) { case dlaAttackEntity: return 1; case dlaBreakBlock: return 2; case dlaBreakBlockInstant: return 0; } UNREACHABLE("Unsupported durability loss action"); } virtual float GetBlockBreakingStrength(BLOCKTYPE a_Block) const override { if (a_Block == E_BLOCK_COBWEB) { return 15.0f; } else { if ( IsBlockMaterialPlants(a_Block) || IsBlockMaterialVine(a_Block) || IsBlockMaterialLeaves(a_Block) || IsBlockMaterialGourd(a_Block) ) { return 1.5f; } else { return 1.0f; } } } } ; ================================================ FILE: src/Items/ItemThrowable.h ================================================ // Declares the itemhandlers for throwable items: eggs, snowballs, ender pearls, and eyes of ender. #pragma once #include "ItemHandler.h" #include "Entities/ProjectileEntity.h" class cItemThrowableHandler: public cItemHandler { using Super = cItemHandler; public: constexpr cItemThrowableHandler(int a_ItemType, cProjectileEntity::eKind a_ProjectileKind, double a_SpeedCoeff): Super(a_ItemType), m_ProjectileKind(a_ProjectileKind), m_SpeedCoeff(a_SpeedCoeff) { } virtual bool OnItemUse( cWorld * a_World, cPlayer * a_Player, cBlockPluginInterface & a_PluginInterface, const cItem & a_HeldItem, const Vector3i a_ClickedBlockPos, eBlockFace a_ClickedBlockFace ) const override { auto Pos = a_Player->GetThrowStartPos(); auto Speed = a_Player->GetLookVector() * m_SpeedCoeff; // Create the projectile: if (a_World->CreateProjectile(Pos.x, Pos.y, Pos.z, m_ProjectileKind, a_Player, &a_Player->GetEquippedItem(), &Speed) == cEntity::INVALID_ID) { return false; } // Play sound: a_World->BroadcastSoundEffect("entity.arrow.shoot", a_Player->GetPosition() - Vector3d(0, a_Player->GetHeight(), 0), 0.5f, 0.4f / GetRandomProvider().RandReal(0.8f, 1.2f)); // Remove from inventory if (!a_Player->IsGameModeCreative()) { a_Player->GetInventory().RemoveOneEquippedItem(); } return true; } protected: /** The kind of projectile to create when shooting */ cProjectileEntity::eKind m_ProjectileKind; /** The speed multiplier (to the player's normalized look vector) to set for the new projectile. */ double m_SpeedCoeff; ~cItemThrowableHandler() = default; } ; class cItemEggHandler final: public cItemThrowableHandler { using Super = cItemThrowableHandler; public: constexpr cItemEggHandler(int a_ItemType): Super(a_ItemType, cProjectileEntity::pkEgg, 30) { } } ; class cItemSnowballHandler final: public cItemThrowableHandler { using Super = cItemThrowableHandler; public: constexpr cItemSnowballHandler(int a_ItemType): Super(a_ItemType, cProjectileEntity::pkSnowball, 30) { } } ; class cItemEnderPearlHandler final: public cItemThrowableHandler { using Super = cItemThrowableHandler; public: constexpr cItemEnderPearlHandler(int a_ItemType): Super(a_ItemType, cProjectileEntity::pkEnderPearl, 30) { } } ; class cItemBottleOEnchantingHandler final : public cItemThrowableHandler { using Super = cItemThrowableHandler; public: constexpr cItemBottleOEnchantingHandler(int a_ItemType): Super(a_ItemType, cProjectileEntity::pkExpBottle, 14) { } }; class cItemFireworkHandler final: public cItemThrowableHandler { using Super = cItemThrowableHandler; public: constexpr cItemFireworkHandler(int a_ItemType): Super(a_ItemType, cProjectileEntity::pkFirework, 0) { } virtual bool OnItemUse( cWorld * a_World, cPlayer * a_Player, cBlockPluginInterface & a_PluginInterface, const cItem & a_HeldItem, const Vector3i a_ClickedBlockPos, eBlockFace a_ClickedBlockFace ) const override { if (a_World->GetBlock(a_ClickedBlockPos) == E_BLOCK_AIR) { return false; } if (a_World->CreateProjectile(Vector3d(a_ClickedBlockPos) + Vector3d(0.5, 1, 0.5), m_ProjectileKind, a_Player, &a_Player->GetEquippedItem()) == 0) { return false; } if (!a_Player->IsGameModeCreative()) { a_Player->GetInventory().RemoveOneEquippedItem(); } return true; } }; ================================================ FILE: src/Items/ItemTorch.h ================================================ #pragma once #include "ItemHandler.h" #include "Blocks/BlockTorch.h" class cItemTorchHandler final : public cItemHandler { using Super = cItemHandler; public: using Super::Super; private: /** Converts the block face of the neighbor to which the torch is attached, to the torch block's meta. */ static NIBBLETYPE BlockFaceToMetaData(eBlockFace a_BlockFace) { switch (a_BlockFace) { case BLOCK_FACE_TOP: return E_META_TORCH_FLOOR; case BLOCK_FACE_EAST: return E_META_TORCH_EAST; case BLOCK_FACE_WEST: return E_META_TORCH_WEST; case BLOCK_FACE_NORTH: return E_META_TORCH_NORTH; case BLOCK_FACE_SOUTH: return E_META_TORCH_SOUTH; default: UNREACHABLE("Unsupported block face"); } } virtual bool CommitPlacement(cPlayer & a_Player, const cItem & a_HeldItem, const Vector3i a_PlacePosition, eBlockFace a_ClickedBlockFace, const Vector3i a_CursorPosition) const override { const auto & World = *a_Player.GetWorld(); BLOCKTYPE ClickedBlockType; NIBBLETYPE ClickedBlockMeta; World.GetBlockTypeMeta(AddFaceDirection(a_PlacePosition, a_ClickedBlockFace, true), ClickedBlockType, ClickedBlockMeta); // Try finding a suitable neighbor block face for the torch; start with the given one: if (!cBlockTorchHandler::CanBePlacedOn(ClickedBlockType, ClickedBlockMeta, a_ClickedBlockFace)) { // Couldn't be placed on whatever face was clicked, last ditch resort - find another face: a_ClickedBlockFace = FindSuitableFace(World, a_PlacePosition); if (a_ClickedBlockFace == BLOCK_FACE_NONE) { // No attachable face found - don't place the torch: return false; } } return a_Player.PlaceBlock(a_PlacePosition, static_cast(a_HeldItem.m_ItemType), BlockFaceToMetaData(a_ClickedBlockFace)); } /** Returns a suitable neighbor's blockface to place the torch at the specified position. Returns BLOCK_FACE_NONE on failure. */ static eBlockFace FindSuitableFace(const cWorld & a_World, const Vector3i a_Position) { for (const auto Face : { BLOCK_FACE_ZM, BLOCK_FACE_XP, BLOCK_FACE_ZP, BLOCK_FACE_XM, BLOCK_FACE_YP }) // Loop through all faces in specific order. { // The direction of Face is relative to the direction the torch faces. // This is the position, computed inverted, that such a torch would attach to. const auto NeighborPosition = AddFaceDirection(a_Position, Face, true); BLOCKTYPE NeighborBlockType; NIBBLETYPE NeighborBlockMeta; a_World.GetBlockTypeMeta(NeighborPosition, NeighborBlockType, NeighborBlockMeta); if (cBlockTorchHandler::CanBePlacedOn(NeighborBlockType, NeighborBlockMeta, Face)) { return Face; } } return BLOCK_FACE_NONE; } }; ================================================ FILE: src/Items/ItemTrapdoor.h ================================================ #pragma once #include "ItemHandler.h" #include "Blocks/BlockTrapdoor.h" class cItemTrapdoorHandler final : public cItemHandler { using Super = cItemHandler; public: using Super::Super; private: inline static NIBBLETYPE BlockFaceToMetaData(eBlockFace a_BlockFace) { switch (a_BlockFace) { case BLOCK_FACE_ZP: return 0x1; case BLOCK_FACE_ZM: return 0x0; case BLOCK_FACE_XP: return 0x3; case BLOCK_FACE_XM: return 0x2; default: UNREACHABLE("Unsupported block face"); } } virtual bool CommitPlacement(cPlayer & a_Player, const cItem & a_HeldItem, const Vector3i a_PlacePosition, const eBlockFace a_ClickedBlockFace, const Vector3i a_CursorPosition) const override { NIBBLETYPE Meta; if (a_ClickedBlockFace == BLOCK_FACE_YP) { // Trapdoor is placed on top of a block. // Engage yaw rotation to determine hinge direction: Meta = cBlockTrapdoorHandler::YawToMetaData(a_Player.GetYaw()); } else if (a_ClickedBlockFace == BLOCK_FACE_YM) { // Trapdoor is placed on bottom of a block. // Engage yaw rotation to determine hinge direction, and toggle 'Move up half-block' bit on: Meta = cBlockTrapdoorHandler::YawToMetaData(a_Player.GetYaw()) | 0x8; } else { // Placement on block sides; hinge direction is determined by which side was clicked: Meta = BlockFaceToMetaData(a_ClickedBlockFace); if (a_CursorPosition.y > 7) { // Trapdoor is placed on a higher half of a vertical block. // Toggle 'Move up half-block' bit on: Meta |= 0x8; } } return a_Player.PlaceBlock(a_PlacePosition, static_cast(a_HeldItem.m_ItemType), Meta); } }; ================================================ FILE: src/Items/ItemTripwireHook.h ================================================ #pragma once #include "ItemHandler.h" class cItemTripwireHookHandler final : public cItemHandler { using Super = cItemHandler; public: using Super::Super; private: static NIBBLETYPE BlockFaceToMetaData(eBlockFace a_BlockFace) { switch (a_BlockFace) { case BLOCK_FACE_XM: return 0x1; case BLOCK_FACE_XP: return 0x3; case BLOCK_FACE_ZM: return 0x2; case BLOCK_FACE_ZP: return 0x0; default: UNREACHABLE("Unsupported block face"); } } virtual bool CommitPlacement(cPlayer & a_Player, const cItem & a_HeldItem, const Vector3i a_PlacePosition, const eBlockFace a_ClickedBlockFace, const Vector3i a_CursorPosition) const override { if ((a_ClickedBlockFace == BLOCK_FACE_YP) || (a_ClickedBlockFace == BLOCK_FACE_YM)) { return false; } return a_Player.PlaceBlock(a_PlacePosition, E_BLOCK_TRIPWIRE_HOOK, BlockFaceToMetaData(a_ClickedBlockFace)); } }; ================================================ FILE: src/Items/ItemVines.h ================================================ #pragma once #include "ItemHandler.h" class cItemVinesHandler final : public cItemHandler { using Super = cItemHandler; public: using Super::Super; private: virtual bool CommitPlacement(cPlayer & a_Player, const cItem & a_HeldItem, const Vector3i a_PlacePosition, const eBlockFace a_ClickedBlockFace, const Vector3i a_CursorPosition) const override { BLOCKTYPE Block; NIBBLETYPE Meta; a_Player.GetWorld()->GetBlockTypeMeta(a_PlacePosition, Block, Meta); NIBBLETYPE PlaceMeta; switch (a_ClickedBlockFace) { case BLOCK_FACE_NORTH: PlaceMeta = 0x1; break; case BLOCK_FACE_SOUTH: PlaceMeta = 0x4; break; case BLOCK_FACE_WEST: PlaceMeta = 0x8; break; case BLOCK_FACE_EAST: PlaceMeta = 0x2; break; default: return false; } if (Block == E_BLOCK_VINES) { PlaceMeta |= Meta; } return a_Player.PlaceBlock(a_PlacePosition, E_BLOCK_VINES, PlaceMeta); } }; ================================================ FILE: src/Items/SimplePlaceableItemHandler.h ================================================ #pragma once #include "ItemHandler.h" class cSimplePlaceableItemHandler final: public cItemHandler { using Super = cItemHandler; public: constexpr cSimplePlaceableItemHandler(int a_ItemType, BLOCKTYPE a_BlockType) : Super(a_ItemType), m_BlockType(a_BlockType) { } virtual bool IsPlaceable(void) const override { return true; } virtual bool CommitPlacement(cPlayer & a_Player, const cItem & a_HeldItem, const Vector3i a_PlacePosition, const eBlockFace a_ClickedBlockFace, const Vector3i a_CursorPosition) const override { return a_Player.PlaceBlock(a_PlacePosition, m_BlockType, 0); } private: BLOCKTYPE m_BlockType; }; ================================================ FILE: src/JsonUtils.cpp ================================================ #include "Globals.h" #include "JsonUtils.h" #include "json/json.h" #include namespace JsonUtils { AString WriteFastString(const Json::Value & a_Root) { Json::StreamWriterBuilder Builder; Builder["commentStyle"] = "None"; Builder["indentation"] = ""; return Json::writeString(Builder, a_Root); } AString WriteStyledString(const Json::Value & a_Root) { Json::StreamWriterBuilder Builder; return Json::writeString(Builder, a_Root); } bool ParseString(const AString & a_JsonStr, Json::Value & a_Root, AString * a_ErrorMsg) { Json::CharReaderBuilder Builder; std::unique_ptr Reader(Builder.newCharReader()); const char * Doc = a_JsonStr.data(); return Reader->parse(Doc, Doc + a_JsonStr.size(), &a_Root, a_ErrorMsg); } AString SerializeSingleValueJsonObject( const AString & a_Key, const AString & a_Value) { Json::Value root; root[a_Key] = a_Value; return JsonUtils::WriteFastString(root); } } // namespace JsonUtils ================================================ FILE: src/JsonUtils.h ================================================ #pragma once // fwd: namespace Json { class Value; } namespace JsonUtils { AString WriteFastString(const Json::Value & a_Root); AString WriteStyledString(const Json::Value & a_Root); bool ParseString(const AString & a_JsonStr, Json::Value & a_Root, AString * a_ErrorMsg = nullptr); /** Creates a Json string representing an object with the specified single value. */ extern AString SerializeSingleValueJsonObject(const AString & a_Key, const AString & a_Value); } ================================================ FILE: src/LazyArray.h ================================================ #pragma once /** A dynamic array that defers allocation to the first modifying access. Const references from the array before allocation will all be to the same default constructed value. It is therefore important that default constructed values are indistinguishable from each other. */ template class cLazyArray { static_assert((!std::is_reference::value && !std::is_array::value), "cLazyArray: T must be a value type"); static_assert(std::is_default_constructible::value, "cLazyArray: T must be default constructible"); public: using value_type = T; using pointer = T *; using const_pointer = const T *; using reference = T &; using const_reference = const T &; using size_type = int; using iterator = pointer; using const_iterator = const_pointer; cLazyArray(size_type a_Size) noexcept: m_Size{ a_Size } { ASSERT(a_Size > 0); } cLazyArray(const cLazyArray & a_Other): m_Size{ a_Other.m_Size } { if (a_Other.IsStorageAllocated()) { // Note that begin() will allocate the array to copy into std::copy(a_Other.begin(), a_Other.end(), begin()); } } cLazyArray(cLazyArray && a_Other) noexcept: m_Array{ std::move(a_Other.m_Array) }, m_Size{ a_Other.m_Size } { } cLazyArray & operator = (const cLazyArray & a_Other) { cLazyArray(a_Other).swap(*this); return *this; } cLazyArray & operator = (cLazyArray && a_Other) noexcept { m_Array = std::move(a_Other.m_Array); m_Size = a_Other.m_Size; return *this; } T & operator [] (size_type a_Idx) { ASSERT((0 <= a_Idx) && (a_Idx < m_Size)); return data()[a_Idx]; } const T & operator [] (size_type a_Idx) const { return GetAt(a_Idx); } // STL style interface const_iterator cbegin() const { return data(); } iterator begin() { return data(); } const_iterator begin() const { return cbegin(); } const_iterator cend() const { return data() + m_Size; } iterator end() { return data() + m_Size; } const_iterator end() const { return cend(); } size_type size() const noexcept { return m_Size; } const T * data() const { if (m_Array == nullptr) { m_Array.reset(new T[ToUnsigned(m_Size)]); } return m_Array.get(); } T * data() { static_assert(!std::is_const::value, ""); const cLazyArray * const_this = this; return const_cast(const_this->data()); } void swap(cLazyArray & a_Other) noexcept { std::swap(m_Array, a_Other.m_Array); std::swap(m_Size, a_Other.m_Size); } friend void swap(cLazyArray & a_Lhs, cLazyArray & a_Rhs) noexcept { a_Lhs.swap(a_Rhs); } // Extra functions to help avoid allocation /** A const view of an element of the array. Never causes the array to allocate. */ const T & GetAt(size_type a_Idx) const { ASSERT((0 <= a_Idx) && (a_Idx < m_Size)); if (IsStorageAllocated()) { return data()[a_Idx]; } else { static const T DefaultValue; return DefaultValue; } } /** Returns true if the array has already been allocated. */ bool IsStorageAllocated() const noexcept { return (m_Array != nullptr); } private: // Mutable so const data() can allocate the array mutable std::unique_ptr m_Array; size_type m_Size; }; ================================================ FILE: src/LightingThread.cpp ================================================ // LightingThread.cpp // Implements the cLightingThread class representing the thread that processes requests for lighting #include "Globals.h" #include "LightingThread.h" #include "ChunkMap.h" #include "World.h" #include "BlockInfo.h" /** Chunk data callback that takes the chunk data and puts them into cLightingThread's m_BlockTypes[] / m_HeightMap[]: */ class cReader : public cChunkDataCallback { virtual void ChunkData(const ChunkBlockData & a_BlockData, const ChunkLightData &) override { BLOCKTYPE * OutputRows = m_BlockTypes; int OutputIdx = m_ReadingChunkX + m_ReadingChunkZ * cChunkDef::Width * 3; for (size_t i = 0; i != cChunkDef::NumSections; ++i) { const auto Section = a_BlockData.GetSection(i); if (Section == nullptr) { // Skip to the next section OutputIdx += 9 * cChunkDef::SectionHeight * cChunkDef::Width; continue; } for (size_t OffsetY = 0; OffsetY != cChunkDef::SectionHeight; ++OffsetY) { for (size_t Z = 0; Z != cChunkDef::Width; ++Z) { auto InPtr = Section->data() + Z * cChunkDef::Width + OffsetY * cChunkDef::Width * cChunkDef::Width; std::copy_n(InPtr, cChunkDef::Width, OutputRows + OutputIdx * cChunkDef::Width); OutputIdx += 3; } // Skip into the next y-level in the 3x3 chunk blob; each level has cChunkDef::Width * 9 rows // We've already walked cChunkDef::Width * 3 in the "for z" cycle, that makes cChunkDef::Width * 6 rows left to skip OutputIdx += cChunkDef::Width * 6; } } } // BlockTypes() virtual void HeightMap(const cChunkDef::HeightMap & a_Heightmap) override { // Copy the entire heightmap, distribute it into the 3x3 chunk blob: typedef struct {HEIGHTTYPE m_Row[16]; } ROW; const ROW * InputRows = reinterpret_cast(a_Heightmap); ROW * OutputRows = reinterpret_cast(m_HeightMap); int InputIdx = 0; int OutputIdx = m_ReadingChunkX + m_ReadingChunkZ * cChunkDef::Width * 3; for (int z = 0; z < cChunkDef::Width; z++) { OutputRows[OutputIdx] = InputRows[InputIdx++]; OutputIdx += 3; } // for z // Find the highest block in the entire chunk, use it as a base for m_MaxHeight: HEIGHTTYPE MaxHeight = m_MaxHeight; for (size_t i = 0; i < ARRAYCOUNT(a_Heightmap); i++) { if (a_Heightmap[i] > MaxHeight) { MaxHeight = a_Heightmap[i]; } } m_MaxHeight = MaxHeight; } public: int m_ReadingChunkX; // 0, 1 or 2; x-offset of the chunk we're reading from the BlockTypes start int m_ReadingChunkZ; // 0, 1 or 2; z-offset of the chunk we're reading from the BlockTypes start HEIGHTTYPE m_MaxHeight; // Maximum value in this chunk's heightmap BLOCKTYPE * m_BlockTypes; // 3x3 chunks of block types, organized as a single XZY blob of data (instead of 3x3 XZY blobs) HEIGHTTYPE * m_HeightMap; // 3x3 chunks of height map, organized as a single XZY blob of data (instead of 3x3 XZY blobs) cReader(BLOCKTYPE * a_BlockTypes, HEIGHTTYPE * a_HeightMap) : m_ReadingChunkX(0), m_ReadingChunkZ(0), m_MaxHeight(0), m_BlockTypes(a_BlockTypes), m_HeightMap(a_HeightMap) { std::fill_n(m_BlockTypes, cChunkDef::NumBlocks * 9, E_BLOCK_AIR); } } ; //////////////////////////////////////////////////////////////////////////////// // cLightingThread: cLightingThread::cLightingThread(cWorld & a_World): Super("Lighting Executor"), m_World(a_World), m_MaxHeight(0), m_NumSeeds(0) { } cLightingThread::~cLightingThread() { Stop(); } void cLightingThread::Stop(void) { { cCSLock Lock(m_CS); for (cChunkStays::iterator itr = m_PendingQueue.begin(), end = m_PendingQueue.end(); itr != end; ++itr) { (*itr)->Disable(); delete *itr; } m_PendingQueue.clear(); for (cChunkStays::iterator itr = m_Queue.begin(), end = m_Queue.end(); itr != end; ++itr) { (*itr)->Disable(); delete *itr; } m_Queue.clear(); } m_ShouldTerminate = true; m_evtItemAdded.Set(); Super::Stop(); } void cLightingThread::QueueChunk(int a_ChunkX, int a_ChunkZ, std::unique_ptr a_CallbackAfter) { cChunkStay * ChunkStay = new cLightingChunkStay(*this, a_ChunkX, a_ChunkZ, std::move(a_CallbackAfter)); { // The ChunkStay will enqueue itself using the QueueChunkStay() once it is fully loaded // In the meantime, put it into the PendingQueue so that it can be removed when stopping the thread cCSLock Lock(m_CS); m_PendingQueue.push_back(ChunkStay); } ChunkStay->Enable(*m_World.GetChunkMap()); } void cLightingThread::WaitForQueueEmpty(void) { cCSLock Lock(m_CS); while (!m_ShouldTerminate && (!m_Queue.empty() || !m_PendingQueue.empty())) { cCSUnlock Unlock(Lock); m_evtQueueEmpty.Wait(); } } size_t cLightingThread::GetQueueLength(void) { cCSLock Lock(m_CS); return m_Queue.size() + m_PendingQueue.size(); } void cLightingThread::Execute(void) { for (;;) { { cCSLock Lock(m_CS); if (m_Queue.empty()) { cCSUnlock Unlock(Lock); m_evtItemAdded.Wait(); } } if (m_ShouldTerminate) { return; } // Process one items from the queue: cLightingChunkStay * Item; { cCSLock Lock(m_CS); if (m_Queue.empty()) { continue; } Item = static_cast(m_Queue.front()); m_Queue.pop_front(); if (m_Queue.empty()) { m_evtQueueEmpty.Set(); } } // CSLock(m_CS) LightChunk(*Item); Item->Disable(); delete Item; } } void cLightingThread::LightChunk(cLightingChunkStay & a_Item) { // If the chunk is already lit, skip it (report as success): if (m_World.IsChunkLighted(a_Item.m_ChunkX, a_Item.m_ChunkZ)) { if (a_Item.m_CallbackAfter != nullptr) { a_Item.m_CallbackAfter->Call({a_Item.m_ChunkX, a_Item.m_ChunkZ}, true); } return; } cChunkDef::BlockNibbles BlockLight, SkyLight; ReadChunks(a_Item.m_ChunkX, a_Item.m_ChunkZ); PrepareBlockLight(); CalcLight(m_BlockLight); PrepareSkyLight(); /* // DEBUG: Save chunk data with highlighted seeds for visual inspection: cFile f4; if ( f4.Open(fmt::format(FMT_STRING("Chunk_{}_{}_seeds.grab"), a_Item.m_ChunkX, a_Item.m_ChunkZ), cFile::fmWrite) ) { for (int z = 0; z < cChunkDef::Width * 3; z++) { for (int y = cChunkDef::Height / 2; y >= 0; y--) { unsigned char Seeds [cChunkDef::Width * 3]; memcpy(Seeds, m_BlockTypes + y * BlocksPerYLayer + z * cChunkDef::Width * 3, cChunkDef::Width * 3); for (int x = 0; x < cChunkDef::Width * 3; x++) { if (m_IsSeed1[y * BlocksPerYLayer + z * cChunkDef::Width * 3 + x]) { Seeds[x] = E_BLOCK_DIAMOND_BLOCK; } } f4.Write(Seeds, cChunkDef::Width * 3); } } f4.Close(); } //*/ CalcLight(m_SkyLight); /* // DEBUG: Save XY slices of the chunk data and lighting for visual inspection: cFile f1, f2, f3; if ( f1.Open(fmt::format(FMT_STRING("Chunk_{}_{}_data.grab"), a_Item.m_ChunkX, a_Item.m_ChunkZ), cFile::fmWrite) && f2.Open(fmt::format(FMT_STRING("Chunk_{}_{}_sky.grab"), a_Item.m_ChunkX, a_Item.m_ChunkZ), cFile::fmWrite) && f3.Open(fmt::format(FMT_STRING("Chunk_{}_{}_glow.grab"), a_Item.m_ChunkX, a_Item.m_ChunkZ), cFile::fmWrite) ) { for (int z = 0; z < cChunkDef::Width * 3; z++) { for (int y = cChunkDef::Height / 2; y >= 0; y--) { f1.Write(m_BlockTypes + y * BlocksPerYLayer + z * cChunkDef::Width * 3, cChunkDef::Width * 3); unsigned char SkyLight [cChunkDef::Width * 3]; unsigned char BlockLight[cChunkDef::Width * 3]; for (int x = 0; x < cChunkDef::Width * 3; x++) { SkyLight[x] = m_SkyLight [y * BlocksPerYLayer + z * cChunkDef::Width * 3 + x] << 4; BlockLight[x] = m_BlockLight[y * BlocksPerYLayer + z * cChunkDef::Width * 3 + x] << 4; } f2.Write(SkyLight, cChunkDef::Width * 3); f3.Write(BlockLight, cChunkDef::Width * 3); } } f1.Close(); f2.Close(); f3.Close(); } //*/ CompressLight(m_BlockLight, BlockLight); CompressLight(m_SkyLight, SkyLight); m_World.ChunkLighted(a_Item.m_ChunkX, a_Item.m_ChunkZ, BlockLight, SkyLight); if (a_Item.m_CallbackAfter != nullptr) { a_Item.m_CallbackAfter->Call({a_Item.m_ChunkX, a_Item.m_ChunkZ}, true); } } void cLightingThread::ReadChunks(int a_ChunkX, int a_ChunkZ) { cReader Reader(m_BlockTypes, m_HeightMap); for (int z = 0; z < 3; z++) { Reader.m_ReadingChunkZ = z; for (int x = 0; x < 3; x++) { Reader.m_ReadingChunkX = x; VERIFY(m_World.GetChunkData({a_ChunkX + x - 1, a_ChunkZ + z - 1}, Reader)); } // for z } // for x memset(m_BlockLight, 0, sizeof(m_BlockLight)); memset(m_SkyLight, 0, sizeof(m_SkyLight)); m_MaxHeight = Reader.m_MaxHeight; } void cLightingThread::PrepareSkyLight(void) { // Clear seeds: memset(m_IsSeed1, 0, sizeof(m_IsSeed1)); m_NumSeeds = 0; // Fill the top of the chunk with all-light: if (m_MaxHeight < cChunkDef::Height - 1) { std::fill(m_SkyLight + (m_MaxHeight + 1) * BlocksPerYLayer, m_SkyLight + ARRAYCOUNT(m_SkyLight), static_cast(15)); } // Walk every column that has all XZ neighbors for (int z = 1; z < cChunkDef::Width * 3 - 1; z++) { int BaseZ = z * cChunkDef::Width * 3; for (int x = 1; x < cChunkDef::Width * 3 - 1; x++) { int idx = BaseZ + x; // Find the lowest block in this column that receives full sunlight (go through transparent blocks): int Current = m_HeightMap[idx]; ASSERT(Current < cChunkDef::Height); while ( (Current >= 0) && cBlockInfo::IsTransparent(m_BlockTypes[idx + Current * BlocksPerYLayer]) && !cBlockInfo::IsSkylightDispersant(m_BlockTypes[idx + Current * BlocksPerYLayer]) ) { Current -= 1; // Sunlight goes down unchanged through this block } Current += 1; // Point to the last sunlit block, rather than the first non-transparent one // The other neighbors don't need transparent-block-checking. At worst we'll have a few dud seeds above the ground. int Neighbor1 = m_HeightMap[idx + 1] + 1; // X + 1 int Neighbor2 = m_HeightMap[idx - 1] + 1; // X - 1 int Neighbor3 = m_HeightMap[idx + cChunkDef::Width * 3] + 1; // Z + 1 int Neighbor4 = m_HeightMap[idx - cChunkDef::Width * 3] + 1; // Z - 1 int MaxNeighbor = std::max(std::max(Neighbor1, Neighbor2), std::max(Neighbor3, Neighbor4)); // Maximum of the four neighbors // Fill the column from m_MaxHeight to Current with all-light: for (int y = m_MaxHeight, Index = idx + y * BlocksPerYLayer; y >= Current; y--, Index -= BlocksPerYLayer) { m_SkyLight[Index] = 15; } // Add Current as a seed: if (Current < cChunkDef::Height) { int CurrentIdx = idx + Current * BlocksPerYLayer; m_IsSeed1[CurrentIdx] = true; m_SeedIdx1[m_NumSeeds++] = static_cast(CurrentIdx); } // Add seed from Current up to the highest neighbor: for (int y = Current + 1, Index = idx + y * BlocksPerYLayer; y < MaxNeighbor; y++, Index += BlocksPerYLayer) { m_IsSeed1[Index] = true; m_SeedIdx1[m_NumSeeds++] = static_cast(Index); } } } } void cLightingThread::PrepareBlockLight() { // Clear seeds: memset(m_IsSeed1, 0, sizeof(m_IsSeed1)); memset(m_IsSeed2, 0, sizeof(m_IsSeed2)); m_NumSeeds = 0; // Add each emissive block into the seeds: for (int Idx = 0; Idx < (m_MaxHeight * BlocksPerYLayer); ++Idx) { if (cBlockInfo::GetLightValue(m_BlockTypes[Idx]) == 0) { // Not a light-emissive block continue; } // Add current block as a seed: m_IsSeed1[Idx] = true; m_SeedIdx1[m_NumSeeds++] = static_cast(Idx); // Light it up: m_BlockLight[Idx] = cBlockInfo::GetLightValue(m_BlockTypes[Idx]); } } void cLightingThread::CalcLight(NIBBLETYPE * a_Light) { size_t NumSeeds2 = 0; while (m_NumSeeds > 0) { // Buffer 1 -> buffer 2 memset(m_IsSeed2, 0, sizeof(m_IsSeed2)); NumSeeds2 = 0; CalcLightStep(a_Light, m_NumSeeds, m_IsSeed1, m_SeedIdx1, NumSeeds2, m_IsSeed2, m_SeedIdx2); if (NumSeeds2 == 0) { return; } // Buffer 2 -> buffer 1 memset(m_IsSeed1, 0, sizeof(m_IsSeed1)); m_NumSeeds = 0; CalcLightStep(a_Light, NumSeeds2, m_IsSeed2, m_SeedIdx2, m_NumSeeds, m_IsSeed1, m_SeedIdx1); } } void cLightingThread::CalcLightStep( NIBBLETYPE * a_Light, size_t a_NumSeedsIn, unsigned char * a_IsSeedIn, unsigned int * a_SeedIdxIn, size_t & a_NumSeedsOut, unsigned char * a_IsSeedOut, unsigned int * a_SeedIdxOut ) { UNUSED(a_IsSeedIn); size_t NumSeedsOut = 0; for (size_t i = 0; i < a_NumSeedsIn; i++) { UInt32 SeedIdx = static_cast(a_SeedIdxIn[i]); int SeedX = SeedIdx % (cChunkDef::Width * 3); int SeedZ = (SeedIdx / (cChunkDef::Width * 3)) % (cChunkDef::Width * 3); // Propagate seed: if (SeedX < cChunkDef::Width * 3 - 1) { PropagateLight(a_Light, SeedIdx, SeedIdx + 1, NumSeedsOut, a_IsSeedOut, a_SeedIdxOut); } if (SeedX > 0) { PropagateLight(a_Light, SeedIdx, SeedIdx - 1, NumSeedsOut, a_IsSeedOut, a_SeedIdxOut); } if (SeedZ < cChunkDef::Width * 3 - 1) { PropagateLight(a_Light, SeedIdx, SeedIdx + cChunkDef::Width * 3, NumSeedsOut, a_IsSeedOut, a_SeedIdxOut); } if (SeedZ > 0) { PropagateLight(a_Light, SeedIdx, SeedIdx - cChunkDef::Width * 3, NumSeedsOut, a_IsSeedOut, a_SeedIdxOut); } if (SeedIdx < (cChunkDef::Height - 1) * BlocksPerYLayer) { PropagateLight(a_Light, SeedIdx, SeedIdx + BlocksPerYLayer, NumSeedsOut, a_IsSeedOut, a_SeedIdxOut); } if (SeedIdx >= BlocksPerYLayer) { PropagateLight(a_Light, SeedIdx, SeedIdx - BlocksPerYLayer, NumSeedsOut, a_IsSeedOut, a_SeedIdxOut); } } // for i - a_SeedIdxIn[] a_NumSeedsOut = NumSeedsOut; } void cLightingThread::CompressLight(NIBBLETYPE * a_LightArray, NIBBLETYPE * a_ChunkLight) { int InIdx = cChunkDef::Width * 49; // Index to the first nibble of the middle chunk in the a_LightArray int OutIdx = 0; for (int y = 0; y < cChunkDef::Height; y++) { for (int z = 0; z < cChunkDef::Width; z++) { for (int x = 0; x < cChunkDef::Width; x += 2) { a_ChunkLight[OutIdx++] = static_cast(a_LightArray[InIdx + 1] << 4) | a_LightArray[InIdx]; InIdx += 2; } InIdx += cChunkDef::Width * 2; } // Skip into the next y-level in the 3x3 chunk blob; each level has cChunkDef::Width * 9 rows // We've already walked cChunkDef::Width * 3 in the "for z" cycle, that makes cChunkDef::Width * 6 rows left to skip InIdx += cChunkDef::Width * cChunkDef::Width * 6; } } void cLightingThread::PropagateLight( NIBBLETYPE * a_Light, unsigned int a_SrcIdx, unsigned int a_DstIdx, size_t & a_NumSeedsOut, unsigned char * a_IsSeedOut, unsigned int * a_SeedIdxOut ) { ASSERT(a_SrcIdx < ARRAYCOUNT(m_SkyLight)); ASSERT(a_DstIdx < ARRAYCOUNT(m_BlockTypes)); if (a_Light[a_SrcIdx] <= a_Light[a_DstIdx] + cBlockInfo::GetSpreadLightFalloff(m_BlockTypes[a_DstIdx])) { // We're not offering more light than the dest block already has return; } a_Light[a_DstIdx] = a_Light[a_SrcIdx] - cBlockInfo::GetSpreadLightFalloff(m_BlockTypes[a_DstIdx]); if (!a_IsSeedOut[a_DstIdx]) { a_IsSeedOut[a_DstIdx] = true; a_SeedIdxOut[a_NumSeedsOut++] = a_DstIdx; } } void cLightingThread::QueueChunkStay(cLightingChunkStay & a_ChunkStay) { // Move the ChunkStay from the Pending queue to the lighting queue. { cCSLock Lock(m_CS); m_PendingQueue.remove(&a_ChunkStay); m_Queue.push_back(&a_ChunkStay); } m_evtItemAdded.Set(); } //////////////////////////////////////////////////////////////////////////////// // cLightingThread::cLightingChunkStay: cLightingThread::cLightingChunkStay::cLightingChunkStay(cLightingThread & a_LightingThread, int a_ChunkX, int a_ChunkZ, std::unique_ptr a_CallbackAfter) : m_LightingThread(a_LightingThread), m_ChunkX(a_ChunkX), m_ChunkZ(a_ChunkZ), m_CallbackAfter(std::move(a_CallbackAfter)) { Add(a_ChunkX + 1, a_ChunkZ + 1); Add(a_ChunkX + 1, a_ChunkZ); Add(a_ChunkX + 1, a_ChunkZ - 1); Add(a_ChunkX, a_ChunkZ + 1); Add(a_ChunkX, a_ChunkZ); Add(a_ChunkX, a_ChunkZ - 1); Add(a_ChunkX - 1, a_ChunkZ + 1); Add(a_ChunkX - 1, a_ChunkZ); Add(a_ChunkX - 1, a_ChunkZ - 1); } bool cLightingThread::cLightingChunkStay::OnAllChunksAvailable(void) { m_LightingThread.QueueChunkStay(*this); // Keep the ChunkStay alive: return false; } void cLightingThread::cLightingChunkStay::OnDisabled(void) { // Nothing needed in this callback } ================================================ FILE: src/LightingThread.h ================================================ // LightingThread.h // Interfaces to the cLightingThread class representing the thread that processes requests for lighting /* Lighting is done on whole chunks. For each chunk to be lighted, the whole 3x3 chunk area around it is read, then it is processed, so that the middle chunk area has valid lighting, and the lighting is copied into the ChunkMap. Lighting is calculated in full char arrays instead of nibbles, so that accessing the arrays is fast. Lighting is calculated in a flood-fill fashion: 1. Generate seeds from where the light spreads (full skylight / light-emitting blocks) 2. For each seed: - Spread the light 1 block in each of the 6 cardinal directions, if the blocktype allows - If the recipient block has had lower lighting value than that being spread, make it a new seed 3. Repeat step 2, until there are no more seeds The seeds need two fast operations: - Check if a block at [x, y, z] is already a seed - Get the next seed in the row For that reason it is stored in two arrays, one stores a bool saying a seed is in that position, the other is an array of seed coords, encoded as a single int. Step 2 needs two separate storages for old seeds and new seeds, so there are two actual storages for that purpose, their content is swapped after each full step-2-cycle. The thread has two queues of chunks that are to be lighted. The first queue, m_Queue, is the only one that is publicly visible, chunks get queued there by external requests. The second one, m_PostponedQueue, is for chunks that have been taken out of m_Queue and didn't have neighbors ready. Chunks from m_PostponedQueue are moved back into m_Queue when their neighbors get valid, using the ChunkReady callback. */ #pragma once #include "OSSupport/IsThread.h" #include "ChunkStay.h" // fwd: "cWorld.h" class cWorld; class cLightingThread: public cIsThread { using Super = cIsThread; public: cLightingThread(cWorld & a_World); virtual ~cLightingThread() override; void Stop(void); /** Queues the entire chunk for lighting. The callback, if specified, is called after the lighting has been processed. */ void QueueChunk(int a_ChunkX, int a_ChunkZ, std::unique_ptr a_CallbackAfter); /** Blocks until the queue is empty or the thread is terminated */ void WaitForQueueEmpty(void); size_t GetQueueLength(void); protected: class cLightingChunkStay : public cChunkStay { public: cLightingThread & m_LightingThread; int m_ChunkX; int m_ChunkZ; std::unique_ptr m_CallbackAfter; cLightingChunkStay(cLightingThread & a_LightingThread, int a_ChunkX, int a_ChunkZ, std::unique_ptr a_CallbackAfter); protected: virtual void OnChunkAvailable(int a_ChunkX, int a_ChunkZ) override { UNUSED(a_ChunkX); UNUSED(a_ChunkZ); } virtual bool OnAllChunksAvailable(void) override; virtual void OnDisabled(void) override; } ; typedef std::list cChunkStays; cWorld & m_World; /** The mutex to protect m_Queue and m_PendingQueue */ cCriticalSection m_CS; /** The ChunkStays that are loaded and are waiting to be lit. */ cChunkStays m_Queue; /** The ChunkStays that are waiting for load. Used for stopping the thread. */ cChunkStays m_PendingQueue; cEvent m_evtItemAdded; // Set when queue is appended, or to stop the thread cEvent m_evtQueueEmpty; // Set when the queue gets empty /** The highest block in the current 3x3 chunk data */ HEIGHTTYPE m_MaxHeight; // Buffers for the 3x3 chunk data // These buffers alone are 1.7 MiB in size, therefore they cannot be located on the stack safely - some architectures may have only 1 MiB for stack, or even less // Placing the buffers into the object means that this object can light chunks only in one thread! // The blobs are XZY organized as a whole, instead of 3x3 XZY-organized subarrays -> // -> This means data has to be scatterred when reading and gathered when writing! static const int BlocksPerYLayer = cChunkDef::Width * cChunkDef::Width * 3 * 3; BLOCKTYPE m_BlockTypes[BlocksPerYLayer * cChunkDef::Height]; NIBBLETYPE m_BlockLight[BlocksPerYLayer * cChunkDef::Height]; NIBBLETYPE m_SkyLight [BlocksPerYLayer * cChunkDef::Height]; HEIGHTTYPE m_HeightMap [BlocksPerYLayer]; // Seed management (5.7 MiB) // Two buffers, in each calc step one is set as input and the other as output, then in the next step they're swapped // Each seed is represented twice in this structure - both as a "list" and as a "position". // "list" allows fast traversal from seed to seed // "position" allows fast checking if a coord is already a seed unsigned char m_IsSeed1 [BlocksPerYLayer * cChunkDef::Height]; unsigned int m_SeedIdx1[BlocksPerYLayer * cChunkDef::Height]; unsigned char m_IsSeed2 [BlocksPerYLayer * cChunkDef::Height]; unsigned int m_SeedIdx2[BlocksPerYLayer * cChunkDef::Height]; size_t m_NumSeeds; virtual void Execute(void) override; /** Lights the entire chunk. If neighbor chunks don't exist, touches them and re-queues the chunk */ void LightChunk(cLightingChunkStay & a_Item); /** Prepares m_BlockTypes and m_HeightMap data; zeroes out the light arrays */ void ReadChunks(int a_ChunkX, int a_ChunkZ); /** Uses m_HeightMap to initialize the m_SkyLight[] data; fills in seeds for the skylight */ void PrepareSkyLight(void); /** Uses m_BlockTypes to initialize the m_BlockLight[] data; fills in seeds for the blocklight */ void PrepareBlockLight(void); /** Calculates light in the light array specified, using stored seeds */ void CalcLight(NIBBLETYPE * a_Light); /** Does one step in the light calculation - one seed propagation and seed recalculation */ void CalcLightStep( NIBBLETYPE * a_Light, size_t a_NumSeedsIn, unsigned char * a_IsSeedIn, unsigned int * a_SeedIdxIn, size_t & a_NumSeedsOut, unsigned char * a_IsSeedOut, unsigned int * a_SeedIdxOut ); /** Compresses from 1-block-per-byte (faster calc) into 2-blocks-per-byte (MC storage): */ void CompressLight(NIBBLETYPE * a_LightArray, NIBBLETYPE * a_ChunkLight); void PropagateLight( NIBBLETYPE * a_Light, unsigned int a_SrcIdx, unsigned int a_DstIdx, size_t & a_NumSeedsOut, unsigned char * a_IsSeedOut, unsigned int * a_SeedIdxOut ); /** Queues a chunkstay that has all of its chunks loaded. Called by cLightingChunkStay when all of its chunks are loaded. */ void QueueChunkStay(cLightingChunkStay & a_ChunkStay); } ; ================================================ FILE: src/LineBlockTracer.cpp ================================================ // LineBlockTracer.cpp // Implements the cLineBlockTracer class representing a cBlockTracer that traces along a straight line between two points #include "Globals.h" #include "LineBlockTracer.h" #include "BlockInfo.h" #include "World.h" #include "Chunk.h" #include "BoundingBox.h" cLineBlockTracer::cLineBlockTracer(cWorld & a_World, cCallbacks & a_Callbacks) : Super(a_World, a_Callbacks), m_Start(), m_End(), m_Diff(), m_Dir(), m_Current(), m_CurrentFace(BLOCK_FACE_NONE) { } bool cLineBlockTracer::Trace(cWorld & a_World, cBlockTracer::cCallbacks & a_Callbacks, const Vector3d a_Start, const Vector3d a_End) { cLineBlockTracer Tracer(a_World, a_Callbacks); return Tracer.Trace(a_Start, a_End); } bool cLineBlockTracer::LineOfSightTrace(cWorld & a_World, const Vector3d & a_Start, const Vector3d & a_End, int a_Sight) { static class LineOfSightCallbacks: public cLineBlockTracer::cCallbacks { bool m_IsAirOpaque; bool m_IsWaterOpaque; bool m_IsLavaOpaque; public: LineOfSightCallbacks(bool a_IsAirOpaque, bool a_IsWaterOpaque, bool a_IsLavaOpaque): m_IsAirOpaque(a_IsAirOpaque), m_IsWaterOpaque(a_IsWaterOpaque), m_IsLavaOpaque(a_IsLavaOpaque) {} virtual bool OnNextBlock(Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, eBlockFace a_EntryFace) override { switch (a_BlockType) { case E_BLOCK_AIR: return m_IsAirOpaque; case E_BLOCK_LAVA: return m_IsLavaOpaque; case E_BLOCK_STATIONARY_LAVA: return m_IsLavaOpaque; case E_BLOCK_STATIONARY_WATER: return m_IsWaterOpaque; case E_BLOCK_WATER: return m_IsWaterOpaque; default: return true; } } } callbacks( (a_Sight & losAir) == 0, (a_Sight & losWater) == 0, (a_Sight & losLava) == 0 ); return Trace(a_World, callbacks, a_Start, a_End); } bool cLineBlockTracer::FirstSolidHitTrace( cWorld & a_World, const Vector3d & a_Start, const Vector3d & a_End, Vector3d & a_HitCoords, Vector3i & a_HitBlockCoords, eBlockFace & a_HitBlockFace ) { class cSolidHitCallbacks: public cCallbacks { public: cSolidHitCallbacks(const Vector3d & a_CBStart, const Vector3d & a_CBEnd, Vector3d & a_CBHitCoords, Vector3i & a_CBHitBlockCoords, eBlockFace & a_CBHitBlockFace): m_Start(a_CBStart), m_End(a_CBEnd), m_HitCoords(a_CBHitCoords), m_HitBlockCoords(a_CBHitBlockCoords), m_HitBlockFace(a_CBHitBlockFace) { } virtual bool OnNextBlock(Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, eBlockFace a_EntryFace) override { if (!cBlockInfo::IsSolid(a_BlockType)) { return false; } // We hit a solid block, calculate the exact hit coords and abort trace: m_HitBlockCoords = a_BlockPos; m_HitBlockFace = a_EntryFace; cBoundingBox bb(a_BlockPos, a_BlockPos + Vector3i(1, 1, 1)); // Bounding box of the block hit double LineCoeff = 0; // Used to calculate where along the line an intersection with the bounding box occurs eBlockFace Face; // Face hit if (!bb.CalcLineIntersection(m_Start, m_End, LineCoeff, Face)) { // Math rounding errors have caused the calculation to miss the block completely, assume immediate hit LineCoeff = 0; } m_HitCoords = m_Start + (m_End - m_Start) * LineCoeff; // Point where projectile goes into the hit block return true; } protected: const Vector3d & m_Start; const Vector3d & m_End; Vector3d & m_HitCoords; Vector3i & m_HitBlockCoords; eBlockFace & m_HitBlockFace; } callbacks(a_Start, a_End, a_HitCoords, a_HitBlockCoords, a_HitBlockFace); return !Trace(a_World, callbacks, a_Start, a_End); } bool cLineBlockTracer::Trace(const Vector3d a_Start, const Vector3d a_End) { // Initialize the member veriables: m_Start = a_Start; m_End = a_End; m_Dir.x = (m_Start.x < m_End.x) ? 1 : -1; m_Dir.y = (m_Start.y < m_End.y) ? 1 : -1; m_Dir.z = (m_Start.z < m_End.z) ? 1 : -1; m_CurrentFace = BLOCK_FACE_NONE; // Check the start coords, adjust into the world: if (m_Start.y < 0) { if (m_End.y < 0) { // Nothing to trace m_Callbacks->OnNoMoreHits(); return true; } FixStartBelowWorld(); m_Callbacks->OnIntoWorld(m_Start); } else if (m_Start.y >= cChunkDef::Height) { if (m_End.y >= cChunkDef::Height) { m_Callbacks->OnNoMoreHits(); return true; } FixStartAboveWorld(); m_Callbacks->OnIntoWorld(m_Start); } m_Current = m_Start.Floor(); m_Diff = m_End - m_Start; // The actual trace is handled with ChunkMapCS locked by calling our ChunkCallback for the specified chunk int BlockX = FloorC(m_Start.x); int BlockZ = FloorC(m_Start.z); int ChunkX, ChunkZ; cChunkDef::BlockToChunk(BlockX, BlockZ, ChunkX, ChunkZ); return m_World->DoWithChunk(ChunkX, ChunkZ, [this](cChunk & a_Chunk) { return ChunkCallback(&a_Chunk); }); } void cLineBlockTracer::FixStartAboveWorld(void) { // We must set the start Y to less than cChunkDef::Height so that it is considered inside the world later on // Therefore we use an EPS-offset from the height, as small as reasonably possible. const double Height = static_cast(cChunkDef::Height) - 0.00001; CalcXZIntersection(Height, m_Start.x, m_Start.z); m_Start.y = Height; } void cLineBlockTracer::FixStartBelowWorld(void) { CalcXZIntersection(0, m_Start.x, m_Start.z); m_Start.y = 0; } void cLineBlockTracer::CalcXZIntersection(double a_Y, double & a_IntersectX, double & a_IntersectZ) { double Ratio = (m_Start.y - a_Y) / (m_Start.y - m_End.y); a_IntersectX = m_Start.x + (m_End.x - m_Start.x) * Ratio; a_IntersectZ = m_Start.z + (m_End.z - m_Start.z) * Ratio; } bool cLineBlockTracer::MoveToNextBlock(void) { // Find out which of the current block's walls gets hit by the path: static const double EPS = 0.00001; enum { dirNONE, dirX, dirY, dirZ, } Direction = dirNONE; // Calculate the next YZ wall hit: double Coeff = 1; if (std::abs(m_Diff.x) > EPS) { double DestX = (m_Dir.x > 0) ? (m_Current.x + 1) : m_Current.x; double CoeffX = (DestX - m_Start.x) / m_Diff.x; if (CoeffX <= 1) // We need to include equality for the last block in the trace { Coeff = CoeffX; Direction = dirX; } } // If the next XZ wall hit is closer, use it instead: if (std::abs(m_Diff.y) > EPS) { double DestY = (m_Dir.y > 0) ? (m_Current.y + 1) : m_Current.y; double CoeffY = (DestY - m_Start.y) / m_Diff.y; if (CoeffY <= Coeff) // We need to include equality for the last block in the trace { Coeff = CoeffY; Direction = dirY; } } // If the next XY wall hit is closer, use it instead: if (std::abs(m_Diff.z) > EPS) { double DestZ = (m_Dir.z > 0) ? (m_Current.z + 1) : m_Current.z; double CoeffZ = (DestZ - m_Start.z) / m_Diff.z; if (CoeffZ <= Coeff) // We need to include equality for the last block in the trace { Direction = dirZ; } } // Based on the wall hit, adjust the current coords switch (Direction) { case dirX: m_Current.x += m_Dir.x; m_CurrentFace = (m_Dir.x > 0) ? BLOCK_FACE_XM : BLOCK_FACE_XP; break; case dirY: m_Current.y += m_Dir.y; m_CurrentFace = (m_Dir.y > 0) ? BLOCK_FACE_YM : BLOCK_FACE_YP; break; case dirZ: m_Current.z += m_Dir.z; m_CurrentFace = (m_Dir.z > 0) ? BLOCK_FACE_ZM : BLOCK_FACE_ZP; break; case dirNONE: return false; } return true; } bool cLineBlockTracer::ChunkCallback(cChunk * a_Chunk) { ASSERT((m_Current.y >= 0) && (m_Current.y < cChunkDef::Height)); // This should be provided by FixStartAboveWorld() / FixStartBelowWorld() // This is the actual line tracing loop. for (;;) { // Our caller (DoWithChunk callback) should never give nothing: ASSERT(a_Chunk != nullptr); // Move to next block if (!MoveToNextBlock()) { // We've reached the end m_Callbacks->OnNoMoreHits(); return true; } if ((m_Current.y < 0) || (m_Current.y >= cChunkDef::Height)) { // We've gone out of the world, that's the end of this trace double IntersectX, IntersectZ; CalcXZIntersection(m_Current.y, IntersectX, IntersectZ); if (m_Callbacks->OnOutOfWorld({IntersectX, double(m_Current.y), IntersectZ})) { // The callback terminated the trace return false; } m_Callbacks->OnNoMoreHits(); return true; } // Update the current chunk a_Chunk = a_Chunk->GetNeighborChunk(m_Current.x, m_Current.z); if (a_Chunk == nullptr) { m_Callbacks->OnNoChunk(); return false; } // Report the current block through the callbacks: if (a_Chunk->IsValid()) { BLOCKTYPE BlockType; NIBBLETYPE BlockMeta; int RelX = m_Current.x - a_Chunk->GetPosX() * cChunkDef::Width; int RelZ = m_Current.z - a_Chunk->GetPosZ() * cChunkDef::Width; a_Chunk->GetBlockTypeMeta(RelX, m_Current.y, RelZ, BlockType, BlockMeta); if (m_Callbacks->OnNextBlock(m_Current, BlockType, BlockMeta, m_CurrentFace)) { // The callback terminated the trace return false; } } else if (m_Callbacks->OnNextBlockNoData(m_Current, m_CurrentFace)) { // The callback terminated the trace return false; } } } ================================================ FILE: src/LineBlockTracer.h ================================================ // LineBlockTracer.h // Declares the cLineBlockTracer class representing a cBlockTracer that traces along a straight line between two points #pragma once #include "BlockTracer.h" // fwd: Chunk.h class cChunk; class cLineBlockTracer: public cBlockTracer { using Super = cBlockTracer; public: enum eLineOfSight { // Bit flags used for LineOfSightTrace's Sight parameter: losAir = 1, // Can see through air losWater = 2, // Can see through water losLava = 4, // Can see through lava // Common combinations: losAirWaterLava = losAir | losWater | losLava, losAirWater = losAir | losWater, }; cLineBlockTracer(cWorld & a_World, cCallbacks & a_Callbacks); /** Traces one line between Start and End; returns true if the entire line was traced (until OnNoMoreHits()) */ bool Trace(Vector3d a_Start, Vector3d a_End); // Utility functions for simple one-line usage: /** Traces one line between Start and End; returns true if the entire line was traced (until OnNoMoreHits()) */ static bool Trace(cWorld & a_World, cCallbacks & a_Callbacks, const Vector3d a_Start, const Vector3d a_End); /** Returns true if the two positions are within line of sight (not obscured by blocks). a_Sight specifies which blocks are considered transparent for the trace, is an OR-combination of eLineOfSight constants. */ static bool LineOfSightTrace(cWorld & a_World, const Vector3d & a_Start, const Vector3d & a_End, int a_Sight); /** Traces until the first solid block is hit (or until end, whichever comes first. If a solid block was hit, returns true and fills a_HitCoords, a_HitBlockCoords and a_HitBlockFace. If a_End is encountered without hitting any solid block, returns false and doesn't touch a_HitCoords, a_HitBlockCoords nor a_HitBlockFace. a_HitCoords is the exact coords of the hit, a_HitBlockCoords are the coords of the solid block that was hit, a_HitBlockFace is the face of the solid block that was hit. */ static bool FirstSolidHitTrace( cWorld & a_World, const Vector3d & a_Start, const Vector3d & a_End, Vector3d & a_HitCoords, Vector3i & a_HitBlockCoords, eBlockFace & a_HitBlockFace ); protected: /** The start point of the trace */ Vector3d m_Start; /** The end point of the trace */ Vector3d m_End; /** The difference in coords, End - Start */ Vector3d m_Diff; /** The increment at which the block coords are going from Start to End; either +1 or -1 */ Vector3i m_Dir; /** The current block */ Vector3i m_Current; /** The face through which the current block has been entered */ eBlockFace m_CurrentFace; /** Adjusts the start point above the world to just at the world's top */ void FixStartAboveWorld(void); /** Adjusts the start point below the world to just at the world's bottom */ void FixStartBelowWorld(void); /** Calculates the XZ coords of an intersection with the specified Yconst plane; assumes that such an intersection exists */ void CalcXZIntersection(double a_Y, double & a_IntersectX, double & a_IntersectZ); /** Moves m_Current to the next block on the line; returns false if no move is possible (reached the end) */ bool MoveToNextBlock(void); bool ChunkCallback(cChunk * a_Chunk); } ; ================================================ FILE: src/LinearInterpolation.cpp ================================================ // LinearInterpolation.cpp // Implements methods for linear interpolation over 1D, 2D and 3D arrays #include "Globals.h" #include "LinearInterpolation.h" /* // Perform an automatic test upon program start (use breakpoints to debug): extern void Debug3DNoise(float * a_Noise, int a_SizeX, int a_SizeY, int a_SizeZ, const AString & a_FileNameBase); class Test { public: Test(void) { // DoTest1(); DoTest2(); } void DoTest1(void) { float In[8] = {0, 1, 2, 3, 1, 2, 2, 2}; float Out[3 * 3 * 3]; LinearInterpolate1DArray(In, 4, Out, 9); LinearInterpolate2DArray(In, 2, 2, Out, 3, 3); LinearInterpolate3DArray(In, 2, 2, 2, Out, 3, 3, 3); LOGD("Out[0]: %f", Out[0]); } void DoTest2(void) { float In[3 * 3 * 3]; for (size_t i = 0; i < ARRAYCOUNT(In); i++) { In[i] = (float)(i % 5); } float Out[15 * 16 * 17]; LinearInterpolate3DArray(In, 3, 3, 3, Out, 15, 16, 17); Debug3DNoise(Out, 15, 16, 17, "LERP test"); } } gTest; //*/ // Puts linearly interpolated values from one array into another array. 1D version void LinearInterpolate1DArray( float * a_Src, int a_SrcSizeX, float * a_Dst, int a_DstSizeX ) { a_Dst[0] = a_Src[0]; int DstSizeXm1 = a_DstSizeX - 1; int SrcSizeXm1 = a_SrcSizeX - 1; float fDstSizeXm1 = static_cast(DstSizeXm1); float fSrcSizeXm1 = static_cast(SrcSizeXm1); for (int x = 1; x < DstSizeXm1; x++) { int SrcIdx = x * SrcSizeXm1 / DstSizeXm1; float ValLo = a_Src[SrcIdx]; float ValHi = a_Src[SrcIdx + 1]; float Ratio = static_cast(x) * fSrcSizeXm1 / fDstSizeXm1 - SrcIdx; a_Dst[x] = ValLo + (ValHi - ValLo) * Ratio; } a_Dst[a_DstSizeX - 1] = a_Src[a_SrcSizeX - 1]; } // Puts linearly interpolated values from one array into another array. 2D version void LinearInterpolate2DArray( float * a_Src, int a_SrcSizeX, int a_SrcSizeY, float * a_Dst, int a_DstSizeX, int a_DstSizeY ) { ASSERT(a_DstSizeX > 0); ASSERT(a_DstSizeX < MAX_INTERPOL_SIZEX); ASSERT(a_DstSizeY > 0); ASSERT(a_DstSizeY < MAX_INTERPOL_SIZEY); // Calculate interpolation ratios and src indices along each axis: float RatioX[MAX_INTERPOL_SIZEX]; float RatioY[MAX_INTERPOL_SIZEY]; int SrcIdxX[MAX_INTERPOL_SIZEX]; int SrcIdxY[MAX_INTERPOL_SIZEY]; for (int x = 1; x < a_DstSizeX; x++) { SrcIdxX[x] = x * (a_SrcSizeX - 1) / (a_DstSizeX - 1); RatioX[x] = (static_cast(x * (a_SrcSizeX - 1)) / (a_DstSizeX - 1)) - SrcIdxX[x]; } for (int y = 1; y < a_DstSizeY; y++) { SrcIdxY[y] = y * (a_SrcSizeY - 1) / (a_DstSizeY - 1); RatioY[y] = (static_cast(y * (a_SrcSizeY - 1)) / (a_DstSizeY - 1)) - SrcIdxY[y]; } // Special values at the ends. Notice especially the last indices being (size - 2) with ratio set to 1, to avoid index overflow: SrcIdxX[0] = 0; RatioX[0] = 0; SrcIdxY[0] = 0; RatioY[0] = 0; SrcIdxX[a_DstSizeX - 1] = a_SrcSizeX - 2; RatioX[a_DstSizeX - 1] = 1; SrcIdxY[a_DstSizeY - 1] = a_SrcSizeY - 2; RatioY[a_DstSizeY - 1] = 1; // Output all the dst array values using the indices and ratios: int idx = 0; for (int y = 0; y < a_DstSizeY; y++) { int idxLoY = a_SrcSizeX * SrcIdxY[y]; int idxHiY = a_SrcSizeX * (SrcIdxY[y] + 1); float ry = RatioY[y]; for (int x = 0; x < a_DstSizeX; x++) { // The four src corners of the current "cell": float LoXLoY = a_Src[SrcIdxX[x] + idxLoY]; float HiXLoY = a_Src[SrcIdxX[x] + 1 + idxLoY]; float LoXHiY = a_Src[SrcIdxX[x] + idxHiY]; float HiXHiY = a_Src[SrcIdxX[x] + 1 + idxHiY]; // Linear interpolation along the X axis: float InterpXLoY = LoXLoY + (HiXLoY - LoXLoY) * RatioX[x]; float InterpXHiY = LoXHiY + (HiXHiY - LoXHiY) * RatioX[x]; // Linear interpolation along the Y axis: a_Dst[idx] = InterpXLoY + (InterpXHiY - InterpXLoY) * ry; idx += 1; } } } void LinearInterpolate3DArray( float * a_Src, int a_SrcSizeX, int a_SrcSizeY, int a_SrcSizeZ, float * a_Dst, int a_DstSizeX, int a_DstSizeY, int a_DstSizeZ ) { ASSERT(a_DstSizeX > 0); ASSERT(a_DstSizeX < MAX_INTERPOL_SIZEX); ASSERT(a_DstSizeY > 0); ASSERT(a_DstSizeY < MAX_INTERPOL_SIZEY); ASSERT(a_DstSizeZ > 0); ASSERT(a_DstSizeZ < MAX_INTERPOL_SIZEZ); // Calculate interpolation ratios and src indices along each axis: float RatioX[MAX_INTERPOL_SIZEX]; float RatioY[MAX_INTERPOL_SIZEY]; float RatioZ[MAX_INTERPOL_SIZEZ]; int SrcIdxX[MAX_INTERPOL_SIZEX]; int SrcIdxY[MAX_INTERPOL_SIZEY]; int SrcIdxZ[MAX_INTERPOL_SIZEZ]; for (int x = 1; x < a_DstSizeX; x++) { SrcIdxX[x] = x * (a_SrcSizeX - 1) / (a_DstSizeX - 1); RatioX[x] = (static_cast(x * (a_SrcSizeX - 1)) / (a_DstSizeX - 1)) - SrcIdxX[x]; } for (int y = 1; y < a_DstSizeY; y++) { SrcIdxY[y] = y * (a_SrcSizeY - 1) / (a_DstSizeY - 1); RatioY[y] = (static_cast(y * (a_SrcSizeY - 1)) / (a_DstSizeY - 1)) - SrcIdxY[y]; } for (int z = 1; z < a_DstSizeZ; z++) { SrcIdxZ[z] = z * (a_SrcSizeZ - 1) / (a_DstSizeZ - 1); RatioZ[z] = (static_cast(z * (a_SrcSizeZ - 1)) / (a_DstSizeZ - 1)) - SrcIdxZ[z]; } // Special values at the ends. Notice especially the last indices being (size - 2) with ratio set to 1, to avoid index overflow: SrcIdxX[0] = 0; RatioX[0] = 0; SrcIdxY[0] = 0; RatioY[0] = 0; SrcIdxZ[0] = 0; RatioZ[0] = 0; SrcIdxX[a_DstSizeX - 1] = a_SrcSizeX - 2; RatioX[a_DstSizeX - 1] = 1; SrcIdxY[a_DstSizeY - 1] = a_SrcSizeY - 2; RatioY[a_DstSizeY - 1] = 1; SrcIdxZ[a_DstSizeZ - 1] = a_SrcSizeZ - 2; RatioZ[a_DstSizeZ - 1] = 1; // Output all the dst array values using the indices and ratios: int idx = 0; for (int z = 0; z < a_DstSizeZ; z++) { int idxLoZ = a_SrcSizeX * a_SrcSizeY * SrcIdxZ[z]; int idxHiZ = a_SrcSizeX * a_SrcSizeY * (SrcIdxZ[z] + 1); float rz = RatioZ[z]; for (int y = 0; y < a_DstSizeY; y++) { int idxLoY = a_SrcSizeX * SrcIdxY[y]; int idxHiY = a_SrcSizeX * (SrcIdxY[y] + 1); float ry = RatioY[y]; for (int x = 0; x < a_DstSizeX; x++) { // The eight src corners of the current "cell": float LoXLoYLoZ = a_Src[SrcIdxX[x] + idxLoY + idxLoZ]; float HiXLoYLoZ = a_Src[SrcIdxX[x] + 1 + idxLoY + idxLoZ]; float LoXHiYLoZ = a_Src[SrcIdxX[x] + idxHiY + idxLoZ]; float HiXHiYLoZ = a_Src[SrcIdxX[x] + 1 + idxHiY + idxLoZ]; float LoXLoYHiZ = a_Src[SrcIdxX[x] + idxLoY + idxHiZ]; float HiXLoYHiZ = a_Src[SrcIdxX[x] + 1 + idxLoY + idxHiZ]; float LoXHiYHiZ = a_Src[SrcIdxX[x] + idxHiY + idxHiZ]; float HiXHiYHiZ = a_Src[SrcIdxX[x] + 1 + idxHiY + idxHiZ]; // Linear interpolation along the Z axis: float LoXLoYInZ = LoXLoYLoZ + (LoXLoYHiZ - LoXLoYLoZ) * rz; float HiXLoYInZ = HiXLoYLoZ + (HiXLoYHiZ - HiXLoYLoZ) * rz; float LoXHiYInZ = LoXHiYLoZ + (LoXHiYHiZ - LoXHiYLoZ) * rz; float HiXHiYInZ = HiXHiYLoZ + (HiXHiYHiZ - HiXHiYLoZ) * rz; // Linear interpolation along the Y axis: float LoXInYInZ = LoXLoYInZ + (LoXHiYInZ - LoXLoYInZ) * ry; float HiXInYInZ = HiXLoYInZ + (HiXHiYInZ - HiXLoYInZ) * ry; // Linear interpolation along the X axis: a_Dst[idx] = LoXInYInZ + (HiXInYInZ - LoXInYInZ) * RatioX[x]; idx += 1; } // for x } // for y } // for z } ================================================ FILE: src/LinearInterpolation.h ================================================ // LinearInterpolation.h // Declares methods for linear interpolation over 1D, 2D and 3D arrays #pragma once // 2D and 3D Interpolation is optimized by precalculating the ratios into static-sized arrays // These arrays enforce a max size of the dest array, but the limits are settable here: const int MAX_INTERPOL_SIZEX = 256; ///< Maximum X-size of the interpolated array const int MAX_INTERPOL_SIZEY = 512; ///< Maximum Y-size of the interpolated array const int MAX_INTERPOL_SIZEZ = 256; ///< Maximum Z-size of the interpolated array /** Puts linearly interpolated values from one array into another array. 1D version */ void LinearInterpolate1DArray( float * a_Src, ///< Src array int a_SrcSizeX, ///< Count of the src array float * a_Dst, ///< Src array int a_DstSizeX ///< Count of the dst array ); /** Puts linearly interpolated values from one array into another array. 2D version */ void LinearInterpolate2DArray( float * a_Src, ///< Src array, [x + a_SrcSizeX * y] int a_SrcSizeX, int a_SrcSizeY, ///< Count of the src array, in each direction float * a_Dst, ///< Dst array, [x + a_DstSizeX * y] int a_DstSizeX, int a_DstSizeY ///< Count of the dst array, in each direction ); /** Puts linearly interpolated values from one array into another array. 3D version */ void LinearInterpolate3DArray( float * a_Src, ///< Src array, [x + a_SrcSizeX * y + a_SrcSizeX * a_SrcSizeY * z] int a_SrcSizeX, int a_SrcSizeY, int a_SrcSizeZ, ///< Count of the src array, in each direction float * a_Dst, ///< Dst array, [x + a_DstSizeX * y + a_DstSizeX * a_DstSizeY * z] int a_DstSizeX, int a_DstSizeY, int a_DstSizeZ ///< Count of the dst array, in each direction ); ================================================ FILE: src/LinearUpscale.h ================================================ // LinearUpscale.h // Declares the functions for linearly upscaling arrays /* Upscaling means that the array is divided into same-size "cells", and each cell is linearly interpolated between its corners. The array's dimensions are therefore 1 + CellSize * NumCells, for each direction. Upscaling is more efficient than linear interpolation, because the cell sizes are integral and therefore the cells' boundaries are on the array points. However, upscaling usually requires generating the "1 +" in each direction. Upscaling is implemented in templates, so that it's compatible with multiple datatypes. Therefore, there is no cpp file. InPlace upscaling works on a single array and assumes that the values to work on have already been interspersed into the array to the cell boundaries. Specifically, a_Array[x * AnchorStepX + y * AnchorStepY] contains the anchor value. Regular upscaling takes two arrays and "moves" the input from src to dst; src is expected packed. */ #pragma once /** Linearly interpolates values in the array between the equidistant anchor points (upscales). Works in-place (input is already present at the correct output coords) Uses templates to make it possible for the compiler to further optimizer the loops */ template < int SizeX, int SizeY, // Dimensions of the array int AnchorStepX, int AnchorStepY, typename TYPE > void LinearUpscale2DArrayInPlace(TYPE * a_Array) { // First interpolate columns where the anchor points are: int LastYCell = SizeY - AnchorStepY; for (int y = 0; y < LastYCell; y += AnchorStepY) { int Idx = SizeX * y; for (int x = 0; x < SizeX; x += AnchorStepX) { TYPE StartValue = a_Array[Idx]; TYPE EndValue = a_Array[Idx + SizeX * AnchorStepY]; TYPE Diff = EndValue - StartValue; for (int CellY = 1; CellY < AnchorStepY; CellY++) { a_Array[Idx + SizeX * CellY] = StartValue + Diff * CellY / AnchorStepY; } // for CellY Idx += AnchorStepX; } // for x } // for y // Now interpolate in rows, each row has values in the anchor columns int LastXCell = SizeX - AnchorStepX; for (int y = 0; y < SizeY; y++) { int Idx = SizeX * y; for (int x = 0; x < LastXCell; x += AnchorStepX) { TYPE StartValue = a_Array[Idx]; TYPE EndValue = a_Array[Idx + AnchorStepX]; TYPE Diff = EndValue - StartValue; for (int CellX = 1; CellX < AnchorStepX; CellX++) { a_Array[Idx + CellX] = StartValue + CellX * Diff / AnchorStepX; } // for CellY Idx += AnchorStepX; } } } /** Linearly interpolates values in the array between the equidistant anchor points (upscales). Works on two arrays, input is packed and output is to be completely constructed. */ template void LinearUpscale2DArray( TYPE * a_Src, ///< Source array of size a_SrcSizeX x a_SrcSizeY int a_SrcSizeX, int a_SrcSizeY, ///< Dimensions of the src array TYPE * a_Dst, ///< Dest array, of size (a_SrcSizeX * a_UpscaleX + 1) x (a_SrcSizeY * a_UpscaleY + 1) int a_UpscaleX, int a_UpscaleY ///< Upscale factor for each direction ) { // For optimization reasons, we're storing the upscaling ratios in a fixed-size arrays of these sizes // Feel free to enlarge them if needed, but keep in mind that they're on the stack const int MAX_UPSCALE_X = 129; const int MAX_UPSCALE_Y = 129; ASSERT(a_Src != nullptr); ASSERT(a_Dst != nullptr); ASSERT(a_SrcSizeX > 0); ASSERT(a_SrcSizeY > 0); ASSERT(a_UpscaleX > 0); ASSERT(a_UpscaleY > 0); ASSERT(a_UpscaleX < MAX_UPSCALE_X); ASSERT(a_UpscaleY < MAX_UPSCALE_Y); // Pre-calculate the upscaling ratios: TYPE RatioX[MAX_UPSCALE_X]; TYPE RatioY[MAX_UPSCALE_Y]; for (int x = 0; x <= a_UpscaleX; x++) { RatioX[x] = static_cast(x) / a_UpscaleX; } for (int y = 0; y <= a_UpscaleY; y++) { RatioY[y] = static_cast(y) / a_UpscaleY; } const int DstSizeX = (a_SrcSizeX - 1) * a_UpscaleX + 1; [[maybe_unused]] const int DstSizeY = (a_SrcSizeY - 1) * a_UpscaleY + 1; // Interpolate each XY cell: for (int y = 0; y < (a_SrcSizeY - 1); y++) { int DstY = y * a_UpscaleY; int idx = y * a_SrcSizeX; for (int x = 0; x < (a_SrcSizeX - 1); x++, idx++) { int DstX = x * a_UpscaleX; TYPE LoXLoY = a_Src[idx]; TYPE LoXHiY = a_Src[idx + a_SrcSizeX]; TYPE HiXLoY = a_Src[idx + 1]; TYPE HiXHiY = a_Src[idx + 1 + a_SrcSizeX]; for (int CellY = 0; CellY <= a_UpscaleY; CellY++) { int DestIdx = (DstY + CellY) * DstSizeX + DstX; ASSERT(DestIdx + a_UpscaleX < DstSizeX * DstSizeY); TYPE LoXInY = LoXLoY + (LoXHiY - LoXLoY) * RatioY[CellY]; TYPE HiXInY = HiXLoY + (HiXHiY - HiXLoY) * RatioY[CellY]; for (int CellX = 0; CellX <= a_UpscaleX; CellX++, DestIdx++) { a_Dst[DestIdx] = LoXInY + (HiXInY - LoXInY) * RatioX[CellX]; } } // for CellY } // for x } // for y } /** Linearly interpolates values in the array between the equidistant anchor points (upscales). Works on two arrays, input is packed and output is to be completely constructed. */ template void LinearUpscale3DArray( TYPE * a_Src, ///< Source array of size a_SrcSizeX x a_SrcSizeY x a_SrcSizeZ int a_SrcSizeX, int a_SrcSizeY, int a_SrcSizeZ, ///< Dimensions of the src array TYPE * a_Dst, ///< Dest array, of size (a_SrcSizeX * a_UpscaleX + 1) x (a_SrcSizeY * a_UpscaleY + 1) x (a_SrcSizeZ * a_UpscaleZ + 1) int a_UpscaleX, int a_UpscaleY, int a_UpscaleZ ///< Upscale factor for each direction ) { // For optimization reasons, we're storing the upscaling ratios in a fixed-size arrays of these sizes // Feel free to enlarge them if needed, but keep in mind that they're on the stack const int MAX_UPSCALE_X = 128; const int MAX_UPSCALE_Y = 128; const int MAX_UPSCALE_Z = 128; ASSERT(a_Src != nullptr); ASSERT(a_Dst != nullptr); ASSERT(a_SrcSizeX > 0); ASSERT(a_SrcSizeY > 0); ASSERT(a_SrcSizeZ > 0); ASSERT(a_UpscaleX > 0); ASSERT(a_UpscaleY > 0); ASSERT(a_UpscaleZ > 0); ASSERT(a_UpscaleX <= MAX_UPSCALE_X); ASSERT(a_UpscaleY <= MAX_UPSCALE_Y); ASSERT(a_UpscaleZ <= MAX_UPSCALE_Z); // Pre-calculate the upscaling ratios: TYPE RatioX[MAX_UPSCALE_X]; TYPE RatioY[MAX_UPSCALE_Y]; TYPE RatioZ[MAX_UPSCALE_Z]; for (int x = 0; x <= a_UpscaleX; x++) { RatioX[x] = static_cast(x) / a_UpscaleX; } for (int y = 0; y <= a_UpscaleY; y++) { RatioY[y] = static_cast(y) / a_UpscaleY; } for (int z = 0; z <= a_UpscaleZ; z++) { RatioZ[z] = static_cast(z) / a_UpscaleZ; } const int DstSizeX = (a_SrcSizeX - 1) * a_UpscaleX + 1; const int DstSizeY = (a_SrcSizeY - 1) * a_UpscaleY + 1; [[maybe_unused]] const int DstSizeZ = (a_SrcSizeZ - 1) * a_UpscaleZ + 1; // Interpolate each XYZ cell: for (int z = 0; z < (a_SrcSizeZ - 1); z++) { int DstZ = z * a_UpscaleZ; for (int y = 0; y < (a_SrcSizeY - 1); y++) { int DstY = y * a_UpscaleY; int idx = y * a_SrcSizeX + z * a_SrcSizeX * a_SrcSizeY; for (int x = 0; x < (a_SrcSizeX - 1); x++, idx++) { int DstX = x * a_UpscaleX; TYPE LoXLoYLoZ = a_Src[idx]; TYPE LoXLoYHiZ = a_Src[idx + a_SrcSizeX * a_SrcSizeY]; TYPE LoXHiYLoZ = a_Src[idx + a_SrcSizeX]; TYPE LoXHiYHiZ = a_Src[idx + a_SrcSizeX + a_SrcSizeX * a_SrcSizeY]; TYPE HiXLoYLoZ = a_Src[idx + 1]; TYPE HiXLoYHiZ = a_Src[idx + 1 + a_SrcSizeX * a_SrcSizeY]; TYPE HiXHiYLoZ = a_Src[idx + 1 + a_SrcSizeX]; TYPE HiXHiYHiZ = a_Src[idx + 1 + a_SrcSizeX + a_SrcSizeX * a_SrcSizeY]; for (int CellZ = 0; CellZ <= a_UpscaleZ; CellZ++) { TYPE LoXLoYInZ = LoXLoYLoZ + (LoXLoYHiZ - LoXLoYLoZ) * RatioZ[CellZ]; TYPE LoXHiYInZ = LoXHiYLoZ + (LoXHiYHiZ - LoXHiYLoZ) * RatioZ[CellZ]; TYPE HiXLoYInZ = HiXLoYLoZ + (HiXLoYHiZ - HiXLoYLoZ) * RatioZ[CellZ]; TYPE HiXHiYInZ = HiXHiYLoZ + (HiXHiYHiZ - HiXHiYLoZ) * RatioZ[CellZ]; for (int CellY = 0; CellY <= a_UpscaleY; CellY++) { int DestIdx = (DstZ + CellZ) * DstSizeX * DstSizeY + (DstY + CellY) * DstSizeX + DstX; ASSERT(DestIdx + a_UpscaleX < DstSizeX * DstSizeY * DstSizeZ); TYPE LoXInY = LoXLoYInZ + (LoXHiYInZ - LoXLoYInZ) * RatioY[CellY]; TYPE HiXInY = HiXLoYInZ + (HiXHiYInZ - HiXLoYInZ) * RatioY[CellY]; for (int CellX = 0; CellX <= a_UpscaleX; CellX++, DestIdx++) { a_Dst[DestIdx] = LoXInY + (HiXInY - LoXInY) * RatioX[CellX]; } } // for CellY } // for CellZ } // for x } // for y } // for z } ================================================ FILE: src/Logger.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "Logger.h" #include "OSSupport/IsThread.h" #ifdef _WIN32 #include #endif static void WriteLogOpener(fmt::memory_buffer & Buffer) { const time_t rawtime = time(nullptr); struct tm timeinfo; #ifdef _MSC_VER localtime_s(&timeinfo, &rawtime); #else localtime_r(&rawtime, &timeinfo); #endif #ifndef NDEBUG const auto ThreadID = std::hash()(std::this_thread::get_id()); fmt::format_to( Buffer, "[{0:04x}|{1:02d}:{2:02d}:{3:02d}] ", ThreadID, timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec ); #else fmt::format_to( Buffer, "[{0:02d}:{1:02d}:{2:02d}] ", timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec ); #endif } cLogger & cLogger::GetInstance(void) { static cLogger Instance; return Instance; } void cLogger::InitiateMultithreading() { GetInstance(); } void cLogger::LogSimple(std::string_view a_Message, eLogLevel a_LogLevel) { fmt::memory_buffer Buffer; WriteLogOpener(Buffer); fmt::format_to(Buffer, "{0}\n", a_Message); LogLine(std::string_view(Buffer.data(), Buffer.size()), a_LogLevel); } void cLogger::LogLine(std::string_view a_Line, eLogLevel a_LogLevel) { cCSLock Lock(m_CriticalSection); for (size_t i = 0; i < m_LogListeners.size(); i++) { m_LogListeners[i]->Log(a_Line, a_LogLevel); } } void cLogger::LogPrintf(std::string_view a_Format, eLogLevel a_LogLevel, fmt::printf_args a_ArgList) { fmt::memory_buffer Buffer; WriteLogOpener(Buffer); fmt::vprintf(Buffer, fmt::to_string_view(a_Format), a_ArgList); fmt::format_to(Buffer, "\n"); LogLine(std::string_view(Buffer.data(), Buffer.size()), a_LogLevel); } void cLogger::LogFormat(std::string_view a_Format, eLogLevel a_LogLevel, fmt::format_args a_ArgList) { fmt::memory_buffer Buffer; WriteLogOpener(Buffer); fmt::vformat_to(Buffer, a_Format, a_ArgList); fmt::format_to(Buffer, "\n"); LogLine(std::string_view(Buffer.data(), Buffer.size()), a_LogLevel); } cLogger::cAttachment cLogger::AttachListener(std::unique_ptr a_Listener) { auto nonOwning = a_Listener.get(); { cCSLock Lock(m_CriticalSection); m_LogListeners.push_back(std::move(a_Listener)); } return cAttachment{nonOwning}; } void cLogger::DetachListener(cListener * a_Listener) { cCSLock Lock(m_CriticalSection); m_LogListeners.erase( std::remove_if( m_LogListeners.begin(), m_LogListeners.end(), [=](std::unique_ptr & a_OtherListener) -> bool { return a_OtherListener.get() == a_Listener; } ) ); } //////////////////////////////////////////////////////////////////////////////// // Global functions void Logger::LogFormat(std::string_view a_Format, eLogLevel a_LogLevel, fmt::format_args a_ArgList) { cLogger::GetInstance().LogFormat(a_Format, a_LogLevel, a_ArgList); } void Logger::LogPrintf(std::string_view a_Format, eLogLevel a_LogLevel, fmt::printf_args a_ArgList) { cLogger::GetInstance().LogPrintf(a_Format, a_LogLevel, a_ArgList); } void Logger::LogSimple(std::string_view a_Message, eLogLevel a_LogLevel) { cLogger::GetInstance().LogSimple(a_Message, a_LogLevel); } ================================================ FILE: src/Logger.h ================================================ #pragma once class cLogger { public: class cListener { public: virtual void Log(std::string_view a_Message, eLogLevel a_LogLevel) = 0; virtual ~cListener(){} }; class cAttachment { public: cAttachment() : m_listener(nullptr) {} cAttachment(cAttachment && a_other) : m_listener(a_other.m_listener) { a_other.m_listener = nullptr; } ~cAttachment() { if (m_listener != nullptr) { cLogger::GetInstance().DetachListener(m_listener); } } cAttachment & operator=(cAttachment && a_other) { m_listener = a_other.m_listener; a_other.m_listener = nullptr; return *this; } private: cListener * m_listener; friend class cLogger; cAttachment(cListener * a_listener) : m_listener(a_listener) {} }; /** Log a message formatted with a printf style formatting string. */ void LogPrintf(std::string_view a_Format, eLogLevel a_LogLevel, fmt::printf_args a_ArgList); /** Log a message formatted with a python style formatting string. */ void LogFormat(std::string_view a_Format, eLogLevel a_LogLevel, fmt::format_args a_ArgList); /** Logs the simple text message at the specified log level. */ void LogSimple(std::string_view a_Message, eLogLevel a_LogLevel = eLogLevel::Regular); cAttachment AttachListener(std::unique_ptr a_Listener); static cLogger & GetInstance(void); // Must be called before calling GetInstance in a multithreaded context static void InitiateMultithreading(); private: cCriticalSection m_CriticalSection; std::vector> m_LogListeners; void DetachListener(cListener * a_Listener); void LogLine(std::string_view a_Line, eLogLevel a_LogLevel); }; ================================================ FILE: src/LoggerListeners.cpp ================================================ #include "Globals.h" #include "LoggerListeners.h" #if defined(_WIN32) #include // Needed for _isatty(), not available on Linux #include #endif #if defined(_WIN32) || defined (__linux) || defined (__APPLE__) class cColouredConsoleListener : public cLogger::cListener { protected: virtual void SetLogColour(eLogLevel a_LogLevel) = 0; virtual void SetDefaultLogColour() = 0; virtual void Log(std::string_view a_Message, eLogLevel a_LogLevel) override { SetLogColour(a_LogLevel); fwrite(a_Message.data(), sizeof(char), a_Message.size(), stdout); SetDefaultLogColour(); } }; #endif #ifdef _WIN32 class cWindowsConsoleListener: public cColouredConsoleListener { using Super = cColouredConsoleListener; public: cWindowsConsoleListener(HANDLE a_Console, WORD a_DefaultConsoleAttrib): m_Console(a_Console), m_DefaultConsoleAttrib(a_DefaultConsoleAttrib) { } #ifndef NDEBUG virtual void Log(std::string_view a_Message, eLogLevel a_LogLevel) override { Super::Log(a_Message, a_LogLevel); // In a Windows Debug build, output the log to debug console as well: OutputDebugStringA(AString(a_Message).c_str()); } #endif virtual void SetLogColour(eLogLevel a_LogLevel) override { // by default, gray on black WORD Attrib = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED; switch (a_LogLevel) { case eLogLevel::Regular: { // Gray on black Attrib = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED; break; } case eLogLevel::Info: { // Yellow on black Attrib = FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY; break; } case eLogLevel::Warning: { // Red on black Attrib = FOREGROUND_RED | FOREGROUND_INTENSITY; break; } case eLogLevel::Error: { // Black on red Attrib = BACKGROUND_RED | BACKGROUND_INTENSITY; break; } } SetConsoleTextAttribute(m_Console, Attrib); } virtual void SetDefaultLogColour() override { SetConsoleTextAttribute(m_Console, m_DefaultConsoleAttrib); } private: HANDLE m_Console; WORD m_DefaultConsoleAttrib; }; #elif defined (__linux) || defined (__APPLE__) class cANSIConsoleListener : public cColouredConsoleListener { public: virtual void SetLogColour(eLogLevel a_LogLevel) override { switch (a_LogLevel) { case eLogLevel::Regular: { // Whatever the console default is printf("\x1b[0m"); break; } case eLogLevel::Info: { // Yellow on black printf("\x1b[33;1m"); break; } case eLogLevel::Warning: { // Red on black printf("\x1b[31;1m"); break; } case eLogLevel::Error: { // Yellow on red printf("\x1b[1;33;41;1m"); break; } } } virtual void SetDefaultLogColour() override { // Whatever the console default is printf("\x1b[0m"); fflush(stdout); } }; #endif class cVanillaCPPConsoleListener : public cLogger::cListener { public: virtual void Log(std::string_view a_Message, eLogLevel a_LogLevel) override { switch (a_LogLevel) { case eLogLevel::Regular: { fputs("Log: ", stdout); break; } case eLogLevel::Info: { fputs("Info: ", stdout); break; } case eLogLevel::Warning: { fputs("Warning: ", stdout); break; } case eLogLevel::Error: { fputs("Error: ", stdout); break; } } fwrite(a_Message.data(), sizeof(char), a_Message.size(), stdout); } }; // Listener for when stdout is closed, i.e. When running as a daemon. class cNullConsoleListener : public cLogger::cListener { virtual void Log(std::string_view a_Message, eLogLevel a_LogLevel) override { } }; std::unique_ptr MakeConsoleListener(bool a_IsService) { if (a_IsService) { return std::make_unique(); } #ifdef _WIN32 // See whether we are writing to a console the default console attrib: bool ShouldColorOutput = (_isatty(_fileno(stdin)) != 0); if (ShouldColorOutput) { CONSOLE_SCREEN_BUFFER_INFO sbi; HANDLE Console = GetStdHandle(STD_OUTPUT_HANDLE); GetConsoleScreenBufferInfo(Console, &sbi); WORD DefaultConsoleAttrib = sbi.wAttributes; return std::make_unique(Console, DefaultConsoleAttrib); } else { return std::make_unique(); } #elif defined (__linux) || defined (__APPLE__) // TODO: lookup terminal in terminfo if (isatty(fileno(stdout))) { return std::make_unique(); } else { return std::make_unique(); } #else return std::make_unique(); #endif } //////////////////////////////////////////////////////////////////////////////// // cFileListener: class cFileListener : public cLogger::cListener { public: cFileListener() {} bool Open() { // Assume creation succeeds, as the API does not provide a way to tell if the folder exists. cFile::CreateFolder("logs"); bool success = m_File.Open( fmt::format( FMT_STRING("logs/LOG_{}.txt"), std::chrono::duration_cast>>( std::chrono::system_clock::now().time_since_epoch() ).count() ), cFile::fmAppend ); return success; } virtual void Log(std::string_view a_Message, eLogLevel a_LogLevel) override { std::string_view LogLevelPrefix = "Unkn "; bool ShouldFlush = false; switch (a_LogLevel) { case eLogLevel::Regular: { LogLevelPrefix = " "; break; } case eLogLevel::Info: { LogLevelPrefix = "Info "; break; } case eLogLevel::Warning: { LogLevelPrefix = "Warn "; ShouldFlush = true; break; } case eLogLevel::Error: { LogLevelPrefix = "Err "; ShouldFlush = true; break; } } m_File.Write(LogLevelPrefix); m_File.Write(a_Message); if (ShouldFlush) { m_File.Flush(); } } private: cFile m_File; }; std::pair> MakeFileListener() { auto listener = std::make_unique(); if (!listener->Open()) { return {false, nullptr}; } return {true, std::move(listener)}; } ================================================ FILE: src/LoggerListeners.h ================================================ #include "Logger.h" std::unique_ptr MakeConsoleListener(bool a_IsService); std::pair> MakeFileListener(); ================================================ FILE: src/LoggerSimple.h ================================================ // Logging free functions defined in Logger.cpp #pragma once enum class eLogLevel { Regular, Info, Warning, Error, }; namespace Logger { extern void LogFormat( std::string_view a_Format, eLogLevel a_LogLevel, fmt::format_args a_ArgList ); extern void LogPrintf( std::string_view a_Format, eLogLevel a_LogLevel, fmt::printf_args a_ArgList ); extern void LogSimple(std::string_view a_Message, eLogLevel a_LogLevel); } // namespace Logger // python style format specified logging template void FLOG(std::string_view a_Format, const Args & ... args) { Logger::LogFormat(a_Format, eLogLevel::Regular, fmt::make_format_args(args...)); } template void FLOGINFO(std::string_view a_Format, const Args & ... args) { Logger::LogFormat(a_Format, eLogLevel::Info, fmt::make_format_args(args...)); } template void FLOGWARNING(std::string_view a_Format, const Args & ... args) { Logger::LogFormat(a_Format, eLogLevel::Warning, fmt::make_format_args(args...)); } template void FLOGERROR(std::string_view a_Format, const Args & ... args) { Logger::LogFormat(a_Format, eLogLevel::Error, fmt::make_format_args(args...)); } // printf style format specified logging (DEPRECATED) template void LOG(std::string_view a_Format, const Args & ... args) { Logger::LogPrintf(a_Format, eLogLevel::Regular, fmt::make_printf_args(args...)); } template void LOGINFO(std::string_view a_Format, const Args & ... args) { Logger::LogPrintf(a_Format, eLogLevel::Info, fmt::make_printf_args(args...)); } template void LOGWARNING(std::string_view a_Format, const Args & ... args) { Logger::LogPrintf(a_Format, eLogLevel::Warning, fmt::make_printf_args(args...)); } template void LOGERROR(std::string_view a_Format, const Args & ... args) { Logger::LogPrintf(a_Format, eLogLevel::Error, fmt::make_printf_args(args...)); } // Macro variants // In debug builds, translate LOGD to LOG, otherwise leave it out altogether: #if !defined(NDEBUG) || defined(TEST_GLOBALS) #define LOGD LOG #else #define LOGD(...) #endif // !NDEBUG #define LOGWARN LOGWARNING #if !defined(NDEBUG) || defined(TEST_GLOBALS) #define FLOGD FLOG #else #define FLOGD(...) #endif // !NDEBUG #define FLOGWARN FLOGWARNING // Conditionally log a warning #define CONDWARNING(ShouldLog, ...) \ do { \ if (ShouldLog) \ { \ LOGWARNING(__VA_ARGS__); \ } \ } while (false) ================================================ FILE: src/Map.cpp ================================================ // Map.cpp #include "Globals.h" #include "BlockInfo.h" #include "Blocks/BlockHandler.h" #include "Chunk.h" #include "ClientHandle.h" #include "Entities/Player.h" #include "FastRandom.h" #include "Map.h" #include "World.h" cMap::cMap(unsigned int a_ID, cWorld * a_World): m_ID(a_ID), m_Width(cChunkDef::Width * 8), m_Height(cChunkDef::Width * 8), m_Scale(3), m_CenterX(0), m_CenterZ(0), m_Dirty(false), // This constructor is for an empty map object which will be filled by the caller with the correct values - it does not need saving. m_World(a_World), m_Name(fmt::format(FMT_STRING("map_{}"), m_ID)) { m_Data.assign(m_Width * m_Height, E_BASE_COLOR_TRANSPARENT); } cMap::cMap(unsigned int a_ID, int a_CenterX, int a_CenterZ, cWorld * a_World, unsigned int a_Scale): m_ID(a_ID), m_Width(cChunkDef::Width * 8), m_Height(cChunkDef::Width * 8), m_Scale(a_Scale), m_CenterX(a_CenterX), m_CenterZ(a_CenterZ), m_Dirty(true), // This constructor is for creating a brand new map in game, it will always need saving. m_World(a_World), m_Name(fmt::format(FMT_STRING("map_{}"), m_ID)) { m_Data.assign(m_Width * m_Height, E_BASE_COLOR_TRANSPARENT); } void cMap::Tick() { for (const auto & Client : m_ClientsInCurrentTick) { Client->SendMapData(*this, 0, 0); } m_ClientsInCurrentTick.clear(); m_Decorators.clear(); } void cMap::UpdateRadius(int a_PixelX, int a_PixelZ, unsigned int a_Radius) { int PixelRadius = static_cast(a_Radius / GetPixelWidth()); unsigned int StartX = static_cast(Clamp(a_PixelX - PixelRadius, 0, static_cast(m_Width))); unsigned int StartZ = static_cast(Clamp(a_PixelZ - PixelRadius, 0, static_cast(m_Height))); unsigned int EndX = static_cast(Clamp(a_PixelX + PixelRadius, 0, static_cast(m_Width))); unsigned int EndZ = static_cast(Clamp(a_PixelZ + PixelRadius, 0, static_cast(m_Height))); for (unsigned int X = StartX; X < EndX; ++X) { for (unsigned int Z = StartZ; Z < EndZ; ++Z) { int dX = static_cast(X) - a_PixelX; int dZ = static_cast(Z) - a_PixelZ; if ((dX * dX) + (dZ * dZ) < (PixelRadius * PixelRadius)) { UpdatePixel(X, Z); } } } } void cMap::UpdateRadius(cPlayer & a_Player, unsigned int a_Radius) { int PixelWidth = static_cast(GetPixelWidth()); int PixelX = static_cast(a_Player.GetPosX() - m_CenterX) / PixelWidth + static_cast(m_Width / 2); int PixelZ = static_cast(a_Player.GetPosZ() - m_CenterZ) / PixelWidth + static_cast(m_Height / 2); UpdateRadius(PixelX, PixelZ, a_Radius); } bool cMap::UpdatePixel(unsigned int a_X, unsigned int a_Z) { int BlockX = m_CenterX + static_cast((a_X - m_Width / 2) * GetPixelWidth()); int BlockZ = m_CenterZ + static_cast((a_Z - m_Height / 2) * GetPixelWidth()); int ChunkX, ChunkZ; cChunkDef::BlockToChunk(BlockX, BlockZ, ChunkX, ChunkZ); int RelX = BlockX - (ChunkX * cChunkDef::Width); int RelZ = BlockZ - (ChunkZ * cChunkDef::Width); ASSERT(m_World != nullptr); ColorID PixelData; m_World->DoWithChunk(ChunkX, ChunkZ, [&](cChunk & a_Chunk) { if (GetDimension() == dimNether) { // TODO 2014-02-22 xdot: Nether maps return false; } static const std::array BrightnessID = { { 3, 0, 1, 2 } }; // Darkest to lightest BLOCKTYPE TargetBlock; NIBBLETYPE TargetMeta; auto Height = a_Chunk.GetHeight(RelX, RelZ); auto ChunkHeight = cChunkDef::Height; a_Chunk.GetBlockTypeMeta(RelX, Height, RelZ, TargetBlock, TargetMeta); auto ColourID = cBlockHandler::For(TargetBlock).GetMapBaseColourID(TargetMeta); if (IsBlockWater(TargetBlock)) { ChunkHeight /= 4; while (((--Height) != -1) && IsBlockWater(a_Chunk.GetBlock(RelX, Height, RelZ))) { continue; } } else if (ColourID == 0) { while (((--Height) != -1) && ((ColourID = cBlockHandler::For(a_Chunk.GetBlock(RelX, Height, RelZ)).GetMapBaseColourID(a_Chunk.GetMeta(RelX, Height, RelZ))) == 0)) { continue; } } // Multiply base color ID by 4 and add brightness ID const int BrightnessIDSize = static_cast(BrightnessID.size()); PixelData = ColourID * 4 + BrightnessID[static_cast(Clamp((BrightnessIDSize * Height) / ChunkHeight, 0, BrightnessIDSize - 1))]; return false; } ); SetPixel(a_X, a_Z, PixelData); return true; } void cMap::UpdateClient(cPlayer * a_Player) { ASSERT(a_Player != nullptr); m_Decorators.emplace_back(CreateDecorator(a_Player)); m_ClientsInCurrentTick.push_back(a_Player->GetClientHandle()); } eDimension cMap::GetDimension(void) const { ASSERT(m_World != nullptr); return m_World->GetDimension(); } void cMap::Resize(unsigned int a_Width, unsigned int a_Height) { if ((m_Width == a_Width) && (m_Height == a_Height)) { return; } m_Width = a_Width; m_Height = a_Height; m_Data.assign(m_Width * m_Height, 0); } void cMap::SetPosition(int a_CenterX, int a_CenterZ) { m_CenterX = a_CenterX; m_CenterZ = a_CenterZ; } bool cMap::SetPixel(unsigned int a_X, unsigned int a_Z, cMap::ColorID a_Data) { if ((a_X < m_Width) && (a_Z < m_Height)) { auto index = a_Z * m_Width + a_X; if (m_Data[index] != a_Data) { m_Data[index] = a_Data; m_Dirty = true; } return true; } else { return false; } } cMap::ColorID cMap::GetPixel(unsigned int a_X, unsigned int a_Z) { if ((a_X < m_Width) && (a_Z < m_Height)) { return m_Data[a_Z * m_Width + a_X]; } else { return E_BASE_COLOR_TRANSPARENT; } } unsigned int cMap::GetNumPixels(void) const { return m_Width * m_Height; } const cMapDecorator cMap::CreateDecorator(const cEntity * a_TrackedEntity) { int InsideWidth = (GetWidth() / 2) - 1; int InsideHeight = (GetHeight() / 2) - 1; // Center of pixel int PixelX = static_cast(a_TrackedEntity->GetPosX() - GetCenterX()) / static_cast(GetPixelWidth()); int PixelZ = static_cast(a_TrackedEntity->GetPosZ() - GetCenterZ()) / static_cast(GetPixelWidth()); cMapDecorator::eType Type; int Rot; if ((PixelX > -InsideWidth) && (PixelX <= InsideWidth) && (PixelZ > -InsideHeight) && (PixelZ <= InsideHeight)) { double Yaw = a_TrackedEntity->GetYaw(); if (GetDimension() == dimNether) { // TODO 2014-02-19 xdot: Refine Rot = GetRandomProvider().RandInt(15); } else { Rot = CeilC(((Yaw - 11.25) * 16) / 360); } Type = cMapDecorator::eType::E_TYPE_PLAYER; } else { Rot = 0; Type = cMapDecorator::eType::E_TYPE_PLAYER_OUTSIDE; // Move to border if (PixelX <= -InsideWidth) { PixelX = -InsideWidth; } if (PixelZ <= -InsideHeight) { PixelZ = -InsideHeight; } if (PixelX > InsideWidth) { PixelX = InsideWidth; } if (PixelZ > InsideHeight) { PixelZ = InsideHeight; } } return {Type, static_cast(2 * PixelX + 1), static_cast(2 * PixelZ + 1), Rot}; } unsigned int cMap::GetPixelWidth(void) const { return static_cast(pow(2.0, static_cast(m_Scale))); } ================================================ FILE: src/Map.h ================================================ // Map.h // Implementation of in-game coloured maps #pragma once #include "Defines.h" #include "ChunkDef.h" class cClientHandle; class cWorld; class cPlayer; class cMap; /** Encapsulates a map decorator. A map decorator represents an object drawn on the map that can move freely. (e.g. player trackers and item frame pointers) Excluding manually placed decorators, decorators are automatically managed (allocated and freed) by their parent cMap instance. */ struct cMapDecorator { public: enum class eType { E_TYPE_PLAYER = 0x00, E_TYPE_ITEM_FRAME = 0x01, /** Player outside of the boundaries of the map. */ E_TYPE_PLAYER_OUTSIDE = 0x06 }; cMapDecorator(eType a_Type, unsigned int a_X, unsigned int a_Z, int a_Rot) : m_Type(a_Type), m_PixelX(a_X), m_PixelZ(a_Z), m_Rot(a_Rot) { } public: unsigned int GetPixelX(void) const { return m_PixelX; } unsigned int GetPixelZ(void) const { return m_PixelZ; } int GetRot(void) const { return m_Rot; } eType GetType(void) const { return m_Type; } private: eType m_Type; unsigned int m_PixelX; unsigned int m_PixelZ; int m_Rot; }; // tolua_begin /** Encapsulates an in-game world map. */ class cMap { public: enum eBaseColor { E_BASE_COLOR_TRANSPARENT = 0, /* Air */ E_BASE_COLOR_LIGHT_GREEN = 4, /* Grass */ E_BASE_COLOR_LIGHT_BLUE = 5, E_BASE_COLOR_LIGHT_BROWN = 8, /* Sand */ E_BASE_COLOR_GRAY_1 = 12, /* Cloth */ E_BASE_COLOR_RED = 16, /* TNT */ E_BASE_COLOR_PALE_BLUE = 20, /* Ice */ E_BASE_COLOR_GRAY_2 = 24, /* Iron */ E_BASE_COLOR_DARK_GREEN = 28, /* Foliage */ E_BASE_COLOR_WHITE = 32, /* Snow */ E_BASE_COLOR_LIGHT_GRAY = 36, /* Clay */ E_BASE_COLOR_BROWN = 40, /* Dirt */ E_BASE_COLOR_DARK_GRAY = 44, /* Stone */ E_BASE_COLOR_BLUE = 48, /* Water */ E_BASE_COLOR_DARK_BROWN = 52 /* Wood */ }; typedef Byte ColorID; // tolua_end typedef std::vector cColorList; typedef std::vector cMapClientList; typedef std::vector cMapDecoratorList; /** Construct an empty map. */ cMap(unsigned int a_ID, cWorld * a_World); /** Construct an empty map at the specified coordinates. */ cMap(unsigned int a_ID, int a_CenterX, int a_CenterZ, cWorld * a_World, unsigned int a_Scale = 3); /** Sends a map update to all registered clients Clears the list holding registered clients and decorators */ void Tick(); /** Update a circular region with the specified radius and center (in pixels). */ void UpdateRadius(int a_PixelX, int a_PixelZ, unsigned int a_Radius); /** Update a circular region around the specified player. */ void UpdateRadius(cPlayer & a_Player, unsigned int a_Radius); /** Send next update packet to the specified player and remove invalid decorators / clients. */ void UpdateClient(cPlayer * a_Player); // tolua_begin void Resize(unsigned int a_Width, unsigned int a_Height); void SetPosition(int a_CenterX, int a_CenterZ); void SetScale(unsigned int a_Scale) { m_Scale = a_Scale; } bool SetPixel(unsigned int a_X, unsigned int a_Z, ColorID a_Data); ColorID GetPixel(unsigned int a_X, unsigned int a_Z); unsigned int GetWidth (void) const { return m_Width; } unsigned int GetHeight(void) const { return m_Height; } unsigned int GetScale(void) const { return m_Scale; } int GetCenterX(void) const { return m_CenterX; } int GetCenterZ(void) const { return m_CenterZ; } unsigned int GetID(void) const { return m_ID; } cWorld * GetWorld(void) { return m_World; } AString GetName(void) { return m_Name; } eDimension GetDimension(void) const; unsigned int GetNumPixels(void) const; unsigned int GetPixelWidth(void) const; // tolua_end const cMapDecorator CreateDecorator(const cEntity * a_TrackedEntity); const cMapDecoratorList GetDecorators(void) const { return m_Decorators; } const cColorList & GetData(void) const { return m_Data; } private: /** Update the specified pixel. */ bool UpdatePixel(unsigned int a_X, unsigned int a_Z); unsigned int m_ID; unsigned int m_Width; unsigned int m_Height; /** The zoom level, 2^scale square blocks per pixel */ unsigned int m_Scale; int m_CenterX; int m_CenterZ; bool m_Dirty; /** Column-major array of colours */ cColorList m_Data; cWorld * m_World; cMapClientList m_ClientsInCurrentTick; cMapDecoratorList m_Decorators; AString m_Name; friend class cMapManager; friend class cMapSerializer; }; // tolua_export ================================================ FILE: src/MapManager.cpp ================================================ // MapManager.cpp #include "Globals.h" #include "MapManager.h" #include "World.h" #include "WorldStorage/MapSerializer.h" // 6000 ticks or 5 minutes #define MAP_DATA_SAVE_INTERVAL 6000 cMapManager::cMapManager(cWorld * a_World) : m_World(a_World), m_TicksUntilNextSave(MAP_DATA_SAVE_INTERVAL) { ASSERT(m_World != nullptr); } bool cMapManager::DoWithMap(UInt32 a_ID, cMapCallback a_Callback) { cCSLock Lock(m_CS); cMap * Map = GetMapData(a_ID); if (Map == nullptr) { return false; } else { a_Callback(*Map); return true; } } void cMapManager::TickMaps() { cCSLock Lock(m_CS); for (auto & Map : m_MapData) { Map.Tick(); } if (m_TicksUntilNextSave == 0) { m_TicksUntilNextSave = MAP_DATA_SAVE_INTERVAL; SaveMapData(); } else { m_TicksUntilNextSave--; } } cMap * cMapManager::GetMapData(unsigned int a_ID) { if (a_ID < m_MapData.size()) { return &m_MapData[a_ID]; } else { return nullptr; } } cMap * cMapManager::CreateMap(int a_CenterX, int a_CenterY, unsigned int a_Scale) { cCSLock Lock(m_CS); if (m_MapData.size() >= 65536) { LOGWARN("Could not craft map - Too many maps in use"); return nullptr; } cMap Map(static_cast(m_MapData.size()), a_CenterX, a_CenterY, m_World, a_Scale); m_MapData.push_back(Map); return &m_MapData[Map.GetID()]; } void cMapManager::LoadMapData(void) { cCSLock Lock(m_CS); cIDCountSerializer IDSerializer(m_World->GetDataPath()); if (!IDSerializer.Load()) { return; } unsigned int MapCount = IDSerializer.GetMapCount(); m_MapData.clear(); for (unsigned int i = 0; i < MapCount; ++i) { cMap Map(i, m_World); cMapSerializer Serializer(m_World->GetDataPath(), &Map); if (!Serializer.Load()) { LOGWARN("Could not load map #%i", Map.GetID()); } m_MapData.push_back(Map); } } void cMapManager::SaveMapData(void) { cCSLock Lock(m_CS); if (m_MapData.empty()) { return; } cIDCountSerializer IDSerializer(m_World->GetDataPath()); IDSerializer.SetMapCount(static_cast(m_MapData.size())); if (!IDSerializer.Save()) { LOGERROR("Could not save idcounts.dat"); return; } for (cMapList::iterator it = m_MapData.begin(); it != m_MapData.end(); ++it) { cMap & Map = *it; if (Map.m_Dirty) { cMapSerializer Serializer(m_World->GetDataPath(), &Map); if (Serializer.Save()) { Map.m_Dirty = false; } else { LOGWARN("Could not save map #%i", Map.GetID()); } } } } ================================================ FILE: src/MapManager.h ================================================ // MapManager.h #pragma once #include "FunctionRef.h" #include "Map.h" using cMapCallback = cFunctionRef; // tolua_begin /** Manages the in-game maps of a single world - Thread safe. */ class cMapManager { public: // tolua_end cMapManager(cWorld * a_World); /** Returns the map with the specified ID, nullptr if out of range. WARNING: The returned map object is not thread safe. */ cMap * GetMapData(unsigned int a_ID); /** Creates a new map. Returns nullptr on error */ cMap * CreateMap(int a_CenterX, int a_CenterY, unsigned int a_Scale = 3); /** Calls the callback for the map with the specified ID. Returns true if the map was found and the callback called, false if map not found. Callback return value is ignored. */ bool DoWithMap(UInt32 a_ID, cMapCallback a_Callback); // Exported in ManualBindings.cpp /** Ticks each registered map */ void TickMaps(void); /** Loads the map data from the disk */ void LoadMapData(void); /** Saves the map data to the disk */ void SaveMapData(void); private: typedef std::vector cMapList; cCriticalSection m_CS; cMapList m_MapData; cWorld * m_World; /** How long till the map data will be saved Default save interval is #defined in MAP_DATA_SAVE_INTERVAL */ unsigned int m_TicksUntilNextSave; }; // tolua_export ================================================ FILE: src/Matrix4.h ================================================ #pragma once #define _USE_MATH_DEFINES // Enable non-standard math defines (MSVC) #include template // tolua_begin class Matrix4 { TOLUA_TEMPLATE_BIND((T, float, double)) // tolua_end public: T cell[16]; // tolua_begin inline Matrix4(void) { Identity(); } inline Matrix4(const Matrix4 & a_Rhs) { *this = a_Rhs; } // tolua_end inline Matrix4 & operator = (const Matrix4 & a_Rhs) { for (unsigned int i = 0; i < 16; ++i) { cell[i] = a_Rhs.cell[i]; } return *this; } // tolua_begin inline T & operator [] (int a_N) { ASSERT(a_N < 16); return cell[a_N]; } inline void Identity() { cell[1] = cell[2] = cell[3] = cell[4] = 0; cell[6] = cell[7] = cell[8] = cell[9] = 0; cell[11] = cell[12] = cell[13] = cell[14] = 0; cell[0] = cell[5] = cell[10] = cell[15] = 1; } inline void Init(const Vector3 & a_Pos, T a_RX, T a_RY, T a_RZ) { Matrix4 t; t.RotateX(a_RZ); RotateY(a_RY); Concatenate(t); t.RotateZ(a_RX); Concatenate(t); Translate(a_Pos); } inline void RotateX(T a_RX) { T sx = static_cast(sin(a_RX * M_PI / 180)); T cx = static_cast(cos(a_RX * M_PI / 180)); Identity(); cell[5] = cx; cell[6] = sx; cell[9] = -sx; cell[10] = cx; } inline void RotateY(T a_RY) { T sy = static_cast(sin(a_RY * M_PI / 180)); T cy = static_cast(cos(a_RY * M_PI / 180)); Identity(); cell[0] = cy; cell[2] = -sy; cell[8] = sy; cell[10] = cy; } inline void RotateZ(T a_RZ) { T sz = static_cast(sin(a_RZ * M_PI / 180)); T cz = static_cast(cos(a_RZ * M_PI / 180)); Identity(); cell[0] = cz; cell[1] = sz; cell[4] = -sz; cell[5] = cz; } inline void Translate(const Vector3 & a_Pos) { cell[3] += a_Pos.x; cell[7] += a_Pos.y; cell[11] += a_Pos.z; } inline void SetTranslation(const Vector3 & a_Pos) { cell[3] = a_Pos.x; cell[7] = a_Pos.y; cell[11] = a_Pos.z; } inline void Concatenate(const Matrix4 & m2) { Matrix4 res; for (unsigned int c = 0; c < 4; ++c) { for (unsigned int r = 0; r < 4; ++r) { res.cell[r * 4 + c] = ( cell[r * 4 + 0] * m2.cell[c + 0] + cell[r * 4 + 1] * m2.cell[c + 4] + cell[r * 4 + 2] * m2.cell[c + 8] + cell[r * 4 + 3] * m2.cell[c + 12] ); } } *this = res; } inline Vector3 Transform(const Vector3 & v) const { T x = cell[0] * v.x + cell[1] * v.y + cell[2] * v.z + cell[3]; T y = cell[4] * v.x + cell[5] * v.y + cell[6] * v.z + cell[7]; T z = cell[8] * v.x + cell[9] * v.y + cell[10] * v.z + cell[11]; return Vector3(x, y, z); } inline void Invert(void) { Matrix4 t; T tx = -cell[3]; T ty = -cell[7]; T tz = -cell[11]; for (unsigned int h = 0; h < 3; ++h) { for (unsigned int v = 0; v < 3; ++v) { t.cell[h + v * 4] = cell[v + h * 4]; } } for (unsigned int i = 0; i < 11; ++i) { cell[i] = t.cell[i]; } cell[3] = tx * cell[0] + ty * cell[1] + tz * cell[2]; cell[7] = tx * cell[4] + ty * cell[5] + tz * cell[6]; cell[11] = tx * cell[8] + ty * cell[9] + tz * cell[10]; } inline Vector3 GetXColumn(void) const { return Vector3(cell[0], cell[1], cell[2]); } inline Vector3 GetYColumn(void) const { return Vector3(cell[4], cell[5], cell[6]); } inline Vector3 GetZColumn(void) const { return Vector3(cell[8], cell[9], cell[10]); } inline void SetXColumn(const Vector3 & a_X) { cell[0] = a_X.x; cell[1] = a_X.y; cell[2] = a_X.z; } inline void SetYColumn(const Vector3 & a_Y) { cell[4] = a_Y.x; cell[5] = a_Y.y; cell[6] = a_Y.z; } inline void SetZColumn(const Vector3 & a_Z) { cell[8] = a_Z.x; cell[9] = a_Z.y; cell[10] = a_Z.z; } }; // tolua_end // tolua_begin typedef Matrix4 Matrix4d; typedef Matrix4 Matrix4f; // tolua_end ================================================ FILE: src/MemorySettingsRepository.cpp ================================================ #include "Globals.h" #include "MemorySettingsRepository.h" bool cMemorySettingsRepository::KeyExists(const AString keyname) const { return m_Map.count(keyname) != 0; } bool cMemorySettingsRepository::HasValue(const AString & a_KeyName, const AString & a_ValueName) const { auto outerIter = m_Map.find(a_KeyName); if (outerIter == m_Map.end()) { return false; } auto iter = outerIter->second.find(a_ValueName); return (iter != outerIter->second.end()); } int cMemorySettingsRepository::AddKeyName(const AString & a_keyname) { m_Map.emplace(a_keyname, std::unordered_multimap{}); return 0; } bool cMemorySettingsRepository::AddKeyComment(const AString & keyname, const AString & comment) { return false; } AString cMemorySettingsRepository::GetKeyComment(const AString & keyname, const int commentID) const { return ""; } bool cMemorySettingsRepository::DeleteKeyComment(const AString & keyname, const int commentID) { return false; } void cMemorySettingsRepository::AddValue (const AString & a_KeyName, const AString & a_ValueName, const AString & a_Value) { if (m_Writable) { m_Map[a_KeyName].emplace(a_ValueName, sValue(a_Value)); } } void cMemorySettingsRepository::AddValue (const AString & a_KeyName, const AString & a_ValueName, Int64 a_Value) { if (m_Writable) { m_Map[a_KeyName].emplace(a_ValueName, sValue(a_Value)); } } void cMemorySettingsRepository::AddValue (const AString & a_KeyName, const AString & a_ValueName, bool a_Value) { if (m_Writable) { m_Map[a_KeyName].emplace(a_ValueName, sValue(a_Value)); } } std::vector> cMemorySettingsRepository::GetValues(AString a_keyName) { std::vector> ret; for (const auto & pair : m_Map[a_keyName]) { ret.emplace_back(pair.first, pair.second.getStringValue()); } return ret; } AString cMemorySettingsRepository::GetValue (const AString & a_KeyName, const AString & a_ValueName, const AString & defValue) const { auto outerIter = m_Map.find(a_KeyName); if (outerIter == m_Map.end()) { return defValue; } auto iter = outerIter->second.find(a_ValueName); if (iter == outerIter->second.end()) { return defValue; } return iter->second.getStringValue(); } AString cMemorySettingsRepository::GetValueSet (const AString & a_KeyName, const AString & a_ValueName, const AString & defValue) { auto outerIter = m_Map.find(a_KeyName); if (outerIter == m_Map.end()) { AddValue(a_KeyName, a_ValueName, defValue); return defValue; } auto iter = outerIter->second.find(a_ValueName); if (iter == outerIter->second.end()) { AddValue(a_KeyName, a_ValueName, defValue); return defValue; } return iter->second.getStringValue(); } int cMemorySettingsRepository::GetValueSetI(const AString & a_KeyName, const AString & a_ValueName, const int defValue) { auto outerIter = m_Map.find(a_KeyName); if (outerIter == m_Map.end()) { AddValue(a_KeyName, a_ValueName, static_cast(defValue)); return defValue; } auto iter = outerIter->second.find(a_ValueName); if (iter == outerIter->second.end()) { AddValue(a_KeyName, a_ValueName, static_cast(defValue)); return defValue; } return static_cast(iter->second.getIntValue()); } Int64 cMemorySettingsRepository::GetValueSetI(const AString & a_KeyName, const AString & a_ValueName, const Int64 defValue) { auto outerIter = m_Map.find(a_KeyName); if (outerIter == m_Map.end()) { AddValue(a_KeyName, a_ValueName, defValue); return defValue; } auto iter = outerIter->second.find(a_ValueName); if (iter == outerIter->second.end()) { AddValue(a_KeyName, a_ValueName, defValue); return defValue; } return iter->second.getIntValue(); } bool cMemorySettingsRepository::GetValueSetB(const AString & a_KeyName, const AString & a_ValueName, const bool defValue) { auto outerIter = m_Map.find(a_KeyName); if (outerIter == m_Map.end()) { AddValue(a_KeyName, a_ValueName, defValue); return defValue; } auto iter = outerIter->second.find(a_ValueName); if (iter == outerIter->second.end()) { AddValue(a_KeyName, a_ValueName, defValue); return defValue; } return iter->second.getBoolValue(); } bool cMemorySettingsRepository::SetValue (const AString & a_KeyName, const AString & a_ValueName, const AString & a_Value, const bool a_CreateIfNotExists) { if (!m_Writable) { return false; } auto outerIter = m_Map.find(a_KeyName); if (outerIter == m_Map.end()) { if (a_CreateIfNotExists) { AddValue(a_KeyName, a_ValueName, a_Value); } return a_CreateIfNotExists; } auto iter = outerIter->second.find(a_ValueName); if (iter == outerIter->second.end()) { if (a_CreateIfNotExists) { AddValue(a_KeyName, a_ValueName, a_Value); } return a_CreateIfNotExists; } iter->second = sValue(a_Value); return true; } bool cMemorySettingsRepository::SetValueI(const AString & a_KeyName, const AString & a_ValueName, const int a_Value, const bool a_CreateIfNotExists) { if (!m_Writable) { return false; } auto outerIter = m_Map.find(a_KeyName); if (outerIter == m_Map.end()) { if (a_CreateIfNotExists) { AddValue(a_KeyName, a_ValueName, static_cast(a_Value)); } return a_CreateIfNotExists; } auto iter = outerIter->second.find(a_ValueName); if (iter == outerIter->second.end()) { if (a_CreateIfNotExists) { AddValue(a_KeyName, a_ValueName, static_cast(a_Value)); } return a_CreateIfNotExists; } iter->second = sValue(static_cast(a_Value)); return true; } bool cMemorySettingsRepository::DeleteValue(const AString & a_KeyName, const AString & a_ValueName) { if (!m_Writable) { return false; } auto outerIter = m_Map.find(a_KeyName); if (outerIter == m_Map.end()) { return false; } auto iter = outerIter->second.find(a_ValueName); if (iter == outerIter->second.end()) { return false; } outerIter->second.erase(iter); return true; } bool cMemorySettingsRepository::Flush() { return true; } ================================================ FILE: src/MemorySettingsRepository.h ================================================ #pragma once #include "SettingsRepositoryInterface.h" class cMemorySettingsRepository : public cSettingsRepositoryInterface { public: virtual bool KeyExists(const AString keyname) const override; virtual bool HasValue(const AString & a_KeyName, const AString & a_ValueName) const override; virtual int AddKeyName(const AString & keyname) override; virtual bool AddKeyComment(const AString & keyname, const AString & comment) override; virtual AString GetKeyComment(const AString & keyname, const int commentID) const override; virtual bool DeleteKeyComment(const AString & keyname, const int commentID) override; virtual void AddValue (const AString & a_KeyName, const AString & a_ValueName, const AString & a_Value) override; void AddValue (const AString & a_KeyName, const AString & a_ValueName, const Int64 a_Value); void AddValue (const AString & a_KeyName, const AString & a_ValueName, const bool a_Value); virtual std::vector> GetValues(AString a_keyName) override; virtual AString GetValue (const AString & keyname, const AString & valuename, const AString & defValue = "") const override; virtual AString GetValueSet (const AString & keyname, const AString & valuename, const AString & defValue = "") override; virtual int GetValueSetI(const AString & keyname, const AString & valuename, const int defValue = 0) override; virtual Int64 GetValueSetI(const AString & keyname, const AString & valuename, const Int64 defValue = 0) override; virtual bool GetValueSetB(const AString & keyname, const AString & valuename, const bool defValue = false) override; virtual bool SetValue (const AString & a_KeyName, const AString & a_ValueName, const AString & a_Value, const bool a_CreateIfNotExists = true) override; virtual bool SetValueI(const AString & a_KeyName, const AString & a_ValueName, const int a_Value, const bool a_CreateIfNotExists = true) override; virtual bool DeleteValue(const AString & keyname, const AString & valuename) override; virtual bool Flush() override; void SetReadOnly() { m_Writable = false; } private: bool m_Writable = true; struct sValue { sValue(AString value): #ifndef NDEBUG m_Type(eType::String), #endif m_stringValue (std::move(value)) { } sValue(Int64 value): #ifndef NDEBUG m_Type(eType::Int64), #endif m_intValue(value) { } sValue(bool value): #ifndef NDEBUG m_Type(eType::Bool), #endif m_boolValue(value) { } AString getStringValue() const { ASSERT(m_Type == eType::String); return m_stringValue; } Int64 getIntValue() const { ASSERT(m_Type == eType::Int64); return m_intValue; } bool getBoolValue() const { ASSERT(m_Type == eType::Bool); return m_boolValue; } private: #ifndef NDEBUG enum class eType { String, Int64, Bool } m_Type; #endif AString m_stringValue; union { Int64 m_intValue; bool m_boolValue; }; }; std::unordered_map> m_Map{}; }; ================================================ FILE: src/MobCensus.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "MobCensus.h" void cMobCensus::CollectMob(cMonster & a_Monster, cChunk & a_Chunk, double a_Distance) { m_ProximityCounter.CollectMob(a_Monster, a_Chunk, a_Distance); m_MobFamilyCollecter.CollectMob(a_Monster); } bool cMobCensus::IsCapped(cMonster::eFamily a_MobFamily) { const int ratio = 319; // This should be 256 as we are only supposed to take account from chunks that are in 17 x 17 from a player // but for now, we use all chunks loaded by players. that means 19 x 19 chunks. That's why we use 256 * (19 * 19) / (17 * 17) = 319 // MG TODO : code the correct count const auto MobCap = ((GetCapMultiplier(a_MobFamily) * GetNumChunks()) / ratio); return (MobCap < m_MobFamilyCollecter.GetNumberOfCollectedMobs(a_MobFamily)); } int cMobCensus::GetCapMultiplier(cMonster::eFamily a_MobFamily) { switch (a_MobFamily) { case cMonster::mfHostile: return 79; case cMonster::mfPassive: return 11; case cMonster::mfAmbient: return 16; case cMonster::mfWater: return 5; case cMonster::mfNoSpawn: { break; } } UNREACHABLE("Unsupported mob family"); } void cMobCensus::CollectSpawnableChunk(cChunk & a_Chunk) { m_EligibleForSpawnChunks.insert(&a_Chunk); } int cMobCensus::GetNumChunks(void) { return static_cast(m_EligibleForSpawnChunks.size()); } cMobProximityCounter & cMobCensus::GetProximityCounter(void) { return m_ProximityCounter; } void cMobCensus::Logd() { LOGD("Hostile mobs : %d %s", m_MobFamilyCollecter.GetNumberOfCollectedMobs(cMonster::mfHostile), IsCapped(cMonster::mfHostile) ? "(capped)" : ""); LOGD("Ambient mobs : %d %s", m_MobFamilyCollecter.GetNumberOfCollectedMobs(cMonster::mfAmbient), IsCapped(cMonster::mfAmbient) ? "(capped)" : ""); LOGD("Water mobs : %d %s", m_MobFamilyCollecter.GetNumberOfCollectedMobs(cMonster::mfWater), IsCapped(cMonster::mfWater) ? "(capped)" : ""); LOGD("Passive mobs : %d %s", m_MobFamilyCollecter.GetNumberOfCollectedMobs(cMonster::mfPassive), IsCapped(cMonster::mfPassive) ? "(capped)" : ""); } ================================================ FILE: src/MobCensus.h ================================================ #pragma once #include "MobProximityCounter.h" #include "MobFamilyCollecter.h" // fwd: class cChunk; class cMonster; /** This class is used to collect information, for each Mob, what is the distance of the closest player it was first being designed in order to make mobs spawn / despawn / act as the behaviour and even life of mobs depends on the distance to closest player as side effect : it also collect the chunks that are elligible for spawning as side effect 2 : it also know the caps for mobs number and can compare census to this numbers */ class cMobCensus { public: /** Returns the nested proximity counter */ cMobProximityCounter & GetProximityCounter(void); // collect an elligible Chunk for Mob Spawning // MG TODO : code the correct rule (not loaded chunk but short distant from players) void CollectSpawnableChunk(cChunk & a_Chunk); /** Collect a mob - its distance to player, its family ... */ void CollectMob(cMonster & a_Monster, cChunk & a_Chunk, double a_Distance); /** Returns true if the family is capped (i.e. there are more mobs of this family than max) */ bool IsCapped(cMonster::eFamily a_MobFamily); /** log the results of census to server console */ void Logd(void); protected : cMobProximityCounter m_ProximityCounter; cMobFamilyCollecter m_MobFamilyCollecter; std::set m_EligibleForSpawnChunks; /** Returns the number of chunks that are elligible for spawning (for now, the loaded, valid chunks) */ int GetNumChunks(); /** Returns the cap multiplier value of the given monster family */ static int GetCapMultiplier(cMonster::eFamily a_MobFamily); } ; ================================================ FILE: src/MobFamilyCollecter.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "MobFamilyCollecter.h" void cMobFamilyCollecter::CollectMob(cMonster & a_Monster) { cMonster::eFamily MobFamily = a_Monster.GetMobFamily(); m_Mobs[MobFamily].insert(&a_Monster); } int cMobFamilyCollecter::GetNumberOfCollectedMobs(cMonster::eFamily a_Family) { return static_cast(m_Mobs[a_Family].size()); } ================================================ FILE: src/MobFamilyCollecter.h ================================================ #pragma once #include "Mobs/Monster.h" // This is a side-effect of keeping Mobfamily inside Monster class. I'd prefer to keep both (Mobfamily and Monster) inside a "Monster" namespace MG TODO : do it /** This class is used to collect the list of mobs for each family */ class cMobFamilyCollecter { public : typedef const std::set tMobFamilyList; // collect a mob void CollectMob(cMonster & a_Monster); // return the number of mobs for this family int GetNumberOfCollectedMobs(cMonster::eFamily a_Family); protected : std::map > m_Mobs; } ; ================================================ FILE: src/MobProximityCounter.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "MobProximityCounter.h" #include "Entities/Entity.h" #include "Chunk.h" void cMobProximityCounter::CollectMob(cEntity & a_Monster, cChunk & a_Chunk, double a_Distance) { // LOGD("Collecting monster %s, with distance %f", a_Monster->GetClass(), a_Distance); tMonsterToDistance::iterator it = m_MonsterToDistance.find(&a_Monster); if (it == m_MonsterToDistance.end()) { sDistanceAndChunk newDistanceAndChunk(a_Distance, a_Chunk); std::pair result = m_MonsterToDistance.insert(tMonsterToDistance::value_type(&a_Monster, newDistanceAndChunk)); if (!result.second) { ASSERT(!"A collected Monster was not found inside distance map using find(), but insert() said there already is a key for it"); } } else { if (a_Distance < it->second.m_Distance) { it->second.m_Distance = a_Distance; it->second.m_Chunk = &a_Chunk; } } m_EligibleForSpawnChunks.insert(&a_Chunk); } 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))); } } cMobProximityCounter::sIterablePair cMobProximityCounter::getMobWithinThosesDistances(double a_DistanceMin, double a_DistanceMax) { sIterablePair toReturn; toReturn.m_Count = 0; toReturn.m_Begin = m_DistanceToMonster.end(); toReturn.m_End = m_DistanceToMonster.end(); a_DistanceMin *= a_DistanceMin;// this is because is use square distance a_DistanceMax *= a_DistanceMax; if (m_DistanceToMonster.empty()) { convertMaps(); } for (tDistanceToMonster::const_iterator itr = m_DistanceToMonster.begin(); itr != m_DistanceToMonster.end(); ++itr) { if (toReturn.m_Begin == m_DistanceToMonster.end()) { if ((a_DistanceMin == 1.0) || (itr->first > a_DistanceMin)) { toReturn.m_Begin = itr; // This is the first one with distance > a_DistanceMin; } } if (toReturn.m_Begin != m_DistanceToMonster.end()) { if ((a_DistanceMax != 1.0) && (itr->first > a_DistanceMax)) { toReturn.m_End = itr; // This is just after the last one with distance < a_DistanceMax // Note : if we are not going through this, it's ok, toReturn.m_End will be end(); break; } else { toReturn.m_Count ++; } } } return toReturn; } ================================================ FILE: src/MobProximityCounter.h ================================================ #pragma once class cChunk; class cEntity; // This class is used to collect, for each Mob, what is the distance of the closest player // it was first being designed in order to make mobs spawn / despawn / act // as the behaviour and even life of mobs depends on the distance to closest player class cMobProximityCounter { 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) {} double m_Distance; cChunk * m_Chunk; }; struct sMonsterAndChunk { sMonsterAndChunk(cEntity & a_Monster, cChunk & a_Chunk) : m_Monster(a_Monster), m_Chunk(a_Chunk) {} cEntity & m_Monster; cChunk & m_Chunk; }; public : typedef std::map tMonsterToDistance; typedef std::multimap tDistanceToMonster; protected : // this map is filled during collection phase, it will be later transformed into DistanceToMonster tMonsterToDistance m_MonsterToDistance; // this map is generated after collection phase, in order to access monster by distance to player tDistanceToMonster m_DistanceToMonster; // this are the collected chunks. Used to determinate the number of elligible chunk for spawning. std::set m_EligibleForSpawnChunks; protected : // transform monsterToDistance map (that was usefull for collecting) into distanceToMonster // that will be usefull for picking up. void convertMaps(); public : // count a mob on a specified chunk with specified distance to an unkown player // if the distance is shortest than the one collected, this become the new closest // distance and the chunk become the "hosting" chunk (that is the one that will perform the action) void CollectMob(cEntity & a_Monster, cChunk & a_Chunk, double a_Distance); // return the mobs that are within the range of distance of the closest player they are // that means that if a mob is 30 m from a player and 150 m from another one. It will be // in the range [0..50] but not in [100..200] struct sIterablePair { tDistanceToMonster::const_iterator m_Begin; tDistanceToMonster::const_iterator m_End; int m_Count; }; sIterablePair getMobWithinThosesDistances(double a_DistanceMin, double a_DistanceMax); }; ================================================ FILE: src/MobSpawner.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "MobSpawner.h" #include "BlockInfo.h" #include "Mobs/IncludeAllMonsters.h" #include "World.h" cMobSpawner::cMobSpawner(cMonster::eFamily a_MonsterFamily, const std::set& a_AllowedTypes) : m_MonsterFamily(a_MonsterFamily), m_NewPack(true), m_MobType(mtInvalidType) { for (std::set::const_iterator itr = a_AllowedTypes.begin(); itr != a_AllowedTypes.end(); ++itr) { if (cMonster::FamilyFromType(*itr) == a_MonsterFamily) { m_AllowedTypes.insert(*itr); } } } bool cMobSpawner::CheckPackCenter(BLOCKTYPE a_BlockType) { // Packs of non-water mobs can only be centered on an air block // Packs of water mobs can only be centered on a water block if (m_MonsterFamily == cMonster::mfWater) { return IsBlockWater(a_BlockType); } else { return a_BlockType == E_BLOCK_AIR; } } eMonsterType cMobSpawner::ChooseMobType(EMCSBiome a_Biome) { std::vector AllowedMobs; for (eMonsterType MobType : GetAllowedMobTypes(a_Biome)) { auto itr = m_AllowedTypes.find(MobType); if (itr != m_AllowedTypes.end()) { AllowedMobs.push_back(MobType); } } // Pick a random mob from the options: if (AllowedMobs.empty()) { return mtInvalidType; } return AllowedMobs[GetRandomProvider().RandInt(AllowedMobs.size() - 1)]; } bool cMobSpawner::CanSpawnHere(cChunk * a_Chunk, Vector3i a_RelPos, eMonsterType a_MobType, EMCSBiome a_Biome, bool a_DisableSolidBelowCheck) { if ((a_RelPos.y >= cChunkDef::Height - 1) || (a_RelPos.y <= 0)) { return false; } if (cChunkDef::IsValidHeight(a_RelPos.addedY(-1)) && (a_Chunk->GetBlock(a_RelPos.addedY(-1)) == E_BLOCK_BEDROCK)) { return false; // Make sure mobs do not spawn on bedrock. } auto & Random = GetRandomProvider(); auto TargetBlock = a_Chunk->GetBlock(a_RelPos); auto BlockLight = a_Chunk->GetBlockLight(a_RelPos); auto SkyLight = a_Chunk->GetSkyLight(a_RelPos); auto BlockAbove = a_Chunk->GetBlock(a_RelPos.addedY(1)); auto BlockBelow = a_Chunk->GetBlock(a_RelPos.addedY(-1)); SkyLight = a_Chunk->GetTimeAlteredLight(SkyLight); switch (a_MobType) { case mtBat: { return ( (a_RelPos.y <= 63) && (BlockLight <= 4) && (SkyLight <= 4) && (TargetBlock == E_BLOCK_AIR) && (!cBlockInfo::IsTransparent(BlockAbove)) ); } case mtBlaze: { return ( (TargetBlock == E_BLOCK_AIR) && (BlockAbove == E_BLOCK_AIR) && ((!cBlockInfo::IsTransparent(BlockBelow)) || (a_DisableSolidBelowCheck)) && (Random.RandBool()) ); } case mtCaveSpider: { return ( (TargetBlock == E_BLOCK_AIR) && ((!cBlockInfo::IsTransparent(BlockBelow)) || (a_DisableSolidBelowCheck)) && (SkyLight <= 7) && (BlockLight <= 7) && (Random.RandBool()) ); } case mtChicken: case mtCow: case mtPig: case mtHorse: case mtRabbit: case mtSheep: { return ( (TargetBlock == E_BLOCK_AIR) && (BlockAbove == E_BLOCK_AIR) && (BlockBelow == E_BLOCK_GRASS) && (SkyLight >= 9) ); } case mtCreeper: case mtSkeleton: case mtZombie: { return ( (TargetBlock == E_BLOCK_AIR) && (BlockAbove == E_BLOCK_AIR) && ((!cBlockInfo::IsTransparent(BlockBelow)) || (a_DisableSolidBelowCheck)) && (SkyLight <= 7) && (BlockLight <= 7) && (Random.RandBool()) ); } case mtEnderman: { if (a_RelPos.y < 250) { auto blockTop = a_Chunk->GetBlock(a_RelPos.addedY(2)); if (blockTop == E_BLOCK_AIR) { blockTop = a_Chunk->GetBlock(a_RelPos.addedY(3)); return ( (TargetBlock == E_BLOCK_AIR) && (BlockAbove == E_BLOCK_AIR) && (blockTop == E_BLOCK_AIR) && ((!cBlockInfo::IsTransparent(BlockBelow)) || (a_DisableSolidBelowCheck)) && (SkyLight <= 7) && (BlockLight <= 7) ); } } break; } case mtGhast: { return ( (TargetBlock == E_BLOCK_AIR) && (BlockAbove == E_BLOCK_AIR) && (Random.RandBool(0.01)) ); } case mtGuardian: { return ( IsBlockWater(TargetBlock) && IsBlockWater(BlockBelow) && (a_RelPos.y >= 45) && (a_RelPos.y <= 62) ); } case mtMagmaCube: case mtSlime: { const int AMOUNT_MOON_PHASES = 8; auto maxLight = Random.RandInt(0, 7); auto moonPhaseNumber = static_cast(std::floor(a_Chunk->GetWorld()->GetWorldAge().count() / 24000)) % AMOUNT_MOON_PHASES; auto moonThreshold = static_cast(std::abs(moonPhaseNumber - (AMOUNT_MOON_PHASES / 2)) / (AMOUNT_MOON_PHASES / 2)); return ( (TargetBlock == E_BLOCK_AIR) && (BlockAbove == E_BLOCK_AIR) && ( (!cBlockInfo::IsTransparent(BlockBelow)) || (a_DisableSolidBelowCheck)) && ( ( (a_RelPos.y <= 40) && a_Chunk->IsSlimeChunk() ) || ( (a_Biome == biSwampland) && (a_RelPos.y >= 50) && (a_RelPos.y <= 70) && (SkyLight <= maxLight) && (BlockLight <= maxLight) && (Random.RandBool(moonThreshold)) && (Random.RandBool(0.5)) ) ) ); } case mtMooshroom: { return ( (TargetBlock == E_BLOCK_AIR) && (BlockAbove == E_BLOCK_AIR) && (BlockBelow == E_BLOCK_MYCELIUM) && ( (a_Biome == biMushroomShore) || (a_Biome == biMushroomIsland) ) ); } case mtOcelot: { return ( (TargetBlock == E_BLOCK_AIR) && (BlockAbove == E_BLOCK_AIR) && ( (BlockBelow == E_BLOCK_GRASS) || (BlockBelow == E_BLOCK_LEAVES) || (BlockBelow == E_BLOCK_NEW_LEAVES) ) && (a_RelPos.y >= 62) && (Random.RandBool(2.0 / 3.0)) ); } case mtSpider: { bool CanSpawn = true; bool HasFloor = false; for (int x = 0; x < 2; ++x) { for (int z = 0; z < 2; ++z) { CanSpawn = a_Chunk->UnboundedRelGetBlockType(a_RelPos.addedXZ(x, z), TargetBlock); CanSpawn = CanSpawn && (TargetBlock == E_BLOCK_AIR); if (!CanSpawn) { return false; } HasFloor = ( HasFloor || ( a_Chunk->UnboundedRelGetBlockType(a_RelPos + Vector3i(x, -1, z), TargetBlock) && !cBlockInfo::IsTransparent(TargetBlock) ) ); } } return CanSpawn && HasFloor && (SkyLight <= 7) && (BlockLight <= 7); } case mtSquid: { return ( IsBlockWater(TargetBlock) && (a_RelPos.y >= 45) && (a_RelPos.y <= 62) ); } case mtWitherSkeleton: { return ( (TargetBlock == E_BLOCK_AIR) && (BlockAbove == E_BLOCK_AIR) && ((!cBlockInfo::IsTransparent(BlockBelow)) || (a_DisableSolidBelowCheck)) && (SkyLight <= 7) && (BlockLight <= 7) && (Random.RandBool(0.6)) ); } case mtWolf: { return ( (TargetBlock == E_BLOCK_GRASS) && (BlockAbove == E_BLOCK_AIR) && ( (a_Biome == biColdTaiga) || (a_Biome == biColdTaigaHills) || (a_Biome == biColdTaigaM) || (a_Biome == biForest) || (a_Biome == biTaiga) || (a_Biome == biTaigaHills) || (a_Biome == biTaigaM) || (a_Biome == biMegaTaiga) || (a_Biome == biMegaTaigaHills) ) ); } case mtZombiePigman: { return ( (TargetBlock == E_BLOCK_AIR) && (BlockAbove == E_BLOCK_AIR) && ((!cBlockInfo::IsTransparent(BlockBelow)) || (a_DisableSolidBelowCheck)) ); } default: { LOGD("MG TODO: Write spawning rule for mob type %d", a_MobType); return false; } } return false; } std::set cMobSpawner::GetAllowedMobTypes(EMCSBiome a_Biome) { std::set ListOfSpawnables; // Check biomes first to get a list of animals switch (a_Biome) { // Mooshroom only - no other mobs on mushroom islands case biMushroomIsland: case biMushroomShore: { ListOfSpawnables.insert(mtMooshroom); return ListOfSpawnables; } // Add Squid in ocean and river biomes case biOcean: case biFrozenOcean: case biFrozenRiver: case biRiver: case biDeepOcean: { ListOfSpawnables.insert(mtGuardian); break; } // Add ocelots in jungle biomes case biJungle: case biJungleHills: case biJungleEdge: case biJungleM: case biJungleEdgeM: { ListOfSpawnables.insert(mtOcelot); break; } // Add horses in plains-like biomes case biPlains: case biSunflowerPlains: case biSavanna: case biSavannaPlateau: case biSavannaM: case biSavannaPlateauM: { ListOfSpawnables.insert(mtHorse); break; } // Add wolves in forest biomes case biForest: { ListOfSpawnables.insert(mtWolf); break; } // Add wolves and rabbits in all taiga biomes case biColdTaiga: case biColdTaigaM: case biColdTaigaHills: case biTaiga: case biTaigaHills: case biTaigaM: case biMegaTaiga: case biMegaTaigaHills: { ListOfSpawnables.insert(mtWolf); ListOfSpawnables.insert(mtRabbit); break; } // Add rabbits in desert and flower forest biomes case biDesert: case biDesertHills: case biDesertM: case biFlowerForest: { ListOfSpawnables.insert(mtRabbit); break; } // Nothing special about this biome default: { break; } } // Overworld if ( (a_Biome != biDesertHills) && (a_Biome != biDesert) && (a_Biome != biDesertM) && (a_Biome != biBeach) && (a_Biome != biOcean) && (a_Biome != biDeepOcean)) { ListOfSpawnables.insert(mtSheep); ListOfSpawnables.insert(mtPig); ListOfSpawnables.insert(mtCow); ListOfSpawnables.insert(mtChicken); ListOfSpawnables.insert(mtEnderman); ListOfSpawnables.insert(mtSlime); } ListOfSpawnables.insert(mtBat); ListOfSpawnables.insert(mtSpider); ListOfSpawnables.insert(mtZombie); ListOfSpawnables.insert(mtSkeleton); ListOfSpawnables.insert(mtCreeper); ListOfSpawnables.insert(mtSquid); // Nether ListOfSpawnables.insert(mtBlaze); ListOfSpawnables.insert(mtGhast); ListOfSpawnables.insert(mtMagmaCube); ListOfSpawnables.insert(mtWitherSkeleton); ListOfSpawnables.insert(mtZombiePigman); return ListOfSpawnables; } cMonster * cMobSpawner::TryToSpawnHere(cChunk * a_Chunk, Vector3i a_RelPos, EMCSBiome a_Biome, int & a_MaxPackSize) { // If too close to any player, don't spawn anything auto AbsPos = a_Chunk->RelativeToAbsolute(a_RelPos); static const double RangeLimit = 24; if ( a_Chunk->GetWorld()->DoWithNearestPlayer( AbsPos, RangeLimit, [](cPlayer & a_Player) { return true; } ) ) { return nullptr; } if (m_NewPack) { m_MobType = ChooseMobType(a_Biome); if (m_MobType == mtInvalidType) { return nullptr; } if (m_MobType == mtWitherSkeleton) { a_MaxPackSize = 5; } else if (m_MobType == mtWolf) { a_MaxPackSize = 8; } else if (m_MobType == mtGhast) { a_MaxPackSize = 1; } m_NewPack = false; } if ((m_AllowedTypes.find(m_MobType) != m_AllowedTypes.end()) && CanSpawnHere(a_Chunk, a_RelPos, m_MobType, a_Biome)) { auto NewMob = cMonster::NewMonsterFromType(m_MobType); auto NewMobPtr = NewMob.get(); if (NewMob) { m_Spawned.push_back(std::move(NewMob)); } return NewMobPtr; } return nullptr; } void cMobSpawner::NewPack() { m_NewPack = true; } bool cMobSpawner::CanSpawnAnything(void) { return !m_AllowedTypes.empty(); } ================================================ FILE: src/MobSpawner.h ================================================ #pragma once #include "Chunk.h" #include "Mobs/Monster.h" // This is a side-effect of keeping Mobfamily inside Monster class. I'd prefer to keep both (Mobfamily and Monster) inside a "Monster" namespace MG TODO : do it /** This class is used to determine which monster can be spawned in which place it is essentially static (eg. Squids spawn in water, Zombies spawn in dark places) but it also has dynamic part depending on the world.ini settings. */ class cMobSpawner { public : /** Constructor a_MobFamily is the Family of mobs that this spawner will spawn a_AllowedTypes is the set of types allowed for mobs it will spawn. Empty set would result in no spawn at all Allowed mobs thah are not of the right Family will not be include (no warning). */ cMobSpawner(cMonster::eFamily MobFamily, const std::set & a_AllowedTypes); /** Check if specified block can be a Pack center for this spawner */ bool CheckPackCenter(BLOCKTYPE a_BlockType); /** Try to create a monster here If this is the first of a Pack, determine the type of monster a_Biome, BlockType & BlockMeta are used to decide what kind of Mob can Spawn here a_MaxPackSize is set to the maximum size for a pack this type of mob */ cMonster * TryToSpawnHere(cChunk * a_Chunk, Vector3i a_RelPos, EMCSBiome a_Biome, int & a_MaxPackSize); /** Mark the beginning of a new Pack. All mobs of the same Pack are the same type */ void NewPack(void); // return true if there is at least one allowed type bool CanSpawnAnything(void); std::vector> & getSpawned(void) { return m_Spawned; } /** Returns true if specified type of mob can spawn on specified block */ static bool CanSpawnHere(cChunk * a_Chunk, Vector3i a_RelPos, eMonsterType a_MobType, EMCSBiome a_Biome, bool a_DisableSolidBelowCheck = false); /** Returns all mob types that can spawn that biome */ static std::set GetAllowedMobTypes(EMCSBiome a_Biome); protected : /** Returns a random type that can spawn in the specified biome. Returns mtInvalidType if none is possible. */ eMonsterType ChooseMobType(EMCSBiome a_Biome); cMonster::eFamily m_MonsterFamily; std::set m_AllowedTypes; bool m_NewPack; eMonsterType m_MobType; std::vector> m_Spawned; } ; ================================================ FILE: src/Mobs/AggressiveMonster.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "AggressiveMonster.h" #include "LineBlockTracer.h" #include "World.h" #include "Entities/Player.h" cAggressiveMonster::cAggressiveMonster(const AString & a_ConfigName, eMonsterType a_MobType, const AString & a_SoundHurt, const AString & a_SoundDeath, const AString & a_SoundAmbient, float a_Width, float a_Height) : Super(a_ConfigName, a_MobType, a_SoundHurt, a_SoundDeath, a_SoundAmbient, a_Width, a_Height) { m_EMPersonality = AGGRESSIVE; } // What to do if in Chasing State void cAggressiveMonster::InStateChasing(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { Super::InStateChasing(a_Dt, a_Chunk); if (GetTarget() != nullptr) { MoveToPosition(GetTarget()->GetPosition()); } } void cAggressiveMonster::EventSeePlayer(cPlayer * a_Player, cChunk & a_Chunk) { Super::EventSeePlayer(a_Player, a_Chunk); m_EMState = CHASING; } cMonster * cAggressiveMonster::GetMonsterOfTypeInSight(eMonsterType a_MobType, unsigned int a_SightDistance) { cMonster * FoundTarget = nullptr; auto MinimumDistance = static_cast(a_SightDistance * a_SightDistance); class cCallback : public cBlockTracer::cCallbacks { public: bool OnNextBlock(Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, eBlockFace a_EntryFace) override { return a_BlockType != E_BLOCK_AIR; } }; auto Callbacks = cCallback(); auto Tracer = cLineBlockTracer(*GetWorld(), Callbacks); cEntityCallback Callback = [&](cEntity & a_Entity) { if (!a_Entity.IsMob()) { return false; } auto & Other = dynamic_cast(a_Entity); if (Other.GetMobType() != a_MobType) { return false; } Vector3d MyHeadPosition = GetPosition().addedY(GetHeight()); Vector3d TargetPosition = Other.GetPosition().addedY(Other.GetHeight()); double TargetDistance = (MyHeadPosition - TargetPosition).SqrLength(); if ( (MinimumDistance > TargetDistance) && (TargetDistance < (a_SightDistance * a_SightDistance)) ) { FoundTarget = & Other; return true; } return false; }; cBoundingBox CheckZone(GetPosition().addedXZ(-a_SightDistance, -a_SightDistance), GetPosition().addedXZ(a_SightDistance, a_SightDistance)); m_World->ForEachEntityInBox(CheckZone, Callback); return FoundTarget; } void cAggressiveMonster::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { Super::Tick(a_Dt, a_Chunk); if (!IsTicking()) { // The base class tick destroyed us return; } // Set or clear m_Target depending on rules for this Monster: if (m_EMState == CHASING) { CheckEventLostPlayer(a_Dt); } else { CheckEventSeePlayer(a_Chunk); } if ( (GetTarget() != nullptr) && TargetIsInRange() && cLineBlockTracer::LineOfSightTrace( *GetWorld(), GetPosition().addedY(GetHeight()), GetTarget()->GetPosition().addedY(GetTarget()->GetHeight()), (IsNetherNative() ? cLineBlockTracer::losAirWaterLava : cLineBlockTracer::losAirWater) ) && (GetHealth() > 0.0) ) { // Attack if reached destination, target isn't null, and have a clear line of sight to target (so won't attack through walls) Attack(a_Dt); } } bool cAggressiveMonster::Attack(std::chrono::milliseconds a_Dt) { if ((GetTarget() == nullptr) || (m_AttackCoolDownTicksLeft != 0)) { return false; } // Setting this higher gives us more wiggle room for attackrate ResetAttackCooldown(); double KnockbackAmount = 9; GetTarget()->TakeDamage(dtMobAttack, this, m_AttackDamage, KnockbackAmount); return true; } ================================================ FILE: src/Mobs/AggressiveMonster.h ================================================ #pragma once #include "Monster.h" class cAggressiveMonster: public cMonster { using Super = cMonster; public: cAggressiveMonster( const AString & a_ConfigName, eMonsterType a_MobType, const AString & a_SoundHurt, const AString & a_SoundDeath, const AString & a_SoundAmbient, float a_Width, float a_Height ); virtual void Tick (std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; virtual void InStateChasing(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; virtual void EventSeePlayer(cPlayer * a_Player, cChunk & a_Chunk) override; /** * Check if a monster of certain type is in sight * * @param a_mobtype the mob type to find * @param SightDistance max distance to check * * @return pointer to the mob found */ cMonster * GetMonsterOfTypeInSight(eMonsterType a_mobtype, unsigned int SightDistance=16); /** Try to perform attack returns true if attack was deemed successful (hit player, fired projectile, creeper exploded, etc.) even if it didn't actually do damage return false if e.g. the mob is still in cooldown from a previous attack */ virtual bool Attack(std::chrono::milliseconds a_Dt); } ; ================================================ FILE: src/Mobs/Bat.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "Bat.h" #include "../Chunk.h" cBat::cBat(void) : Super("Bat", mtBat, "entity.bat.hurt", "entity.bat.death", "entity.bat.ambient", 0.5f, 0.9f) { SetGravity(-2.0f); SetAirDrag(0.05f); } ================================================ FILE: src/Mobs/Bat.h ================================================ #pragma once #include "PassiveMonster.h" class cBat: public cPassiveMonster { using Super = cPassiveMonster; public: cBat(); CLASS_PROTODEF(cBat) bool IsHanging(void) const {return false; } } ; ================================================ FILE: src/Mobs/Blaze.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "Blaze.h" #include "../World.h" #include "../Entities/FireChargeEntity.h" cBlaze::cBlaze(void) : Super("Blaze", mtBlaze, "entity.blaze.hurt", "entity.blaze.death", "entity.blaze.ambient", 0.6f, 1.8f), m_IsCharging(false), m_ChargeTimer(0) { SetGravity(-8.0f); SetAirDrag(0.05f); } bool cBlaze::Attack(std::chrono::milliseconds a_Dt) { if ((GetTarget() != nullptr) && (m_AttackCoolDownTicksLeft == 0) && (!m_IsCharging)) { m_IsCharging = true; return true; } return false; } void cBlaze::GetDrops(cItems & a_Drops, cEntity * a_Killer) { if ((a_Killer != nullptr) && (a_Killer->IsPlayer() || a_Killer->IsA("cWolf"))) { unsigned int LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting); AddRandomDropItem(a_Drops, 0, 1 + LootingLevel, E_ITEM_BLAZE_ROD); } } void cBlaze::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { Super::Tick(a_Dt, a_Chunk); if (!IsTicking()) { // The base class tick destroyed us return; } if (m_IsCharging) { m_ChargeTimer++; if ( (m_ChargeTimer == 5) || (m_ChargeTimer == 10) || (m_ChargeTimer == 15) ) { Vector3d Speed = GetLookVector() * 20; Speed.y = Speed.y + 1; auto FireCharge = std::make_unique(this, GetPosition().addedY(1), Speed); auto FireChargePtr = FireCharge.get(); FireChargePtr->Initialize(std::move(FireCharge), *m_World); m_World->BroadcastSoundEffect("entity.blaze.shoot", GetPosition(), 4.0f, 1.0f); } } if ((m_IsCharging) && (m_ChargeTimer > 15)) { m_ChargeTimer = 0; m_IsCharging = false; ResetAttackCooldown(); } } ================================================ FILE: src/Mobs/Blaze.h ================================================ #pragma once #include "AggressiveMonster.h" class cBlaze: public cAggressiveMonster { using Super = cAggressiveMonster; public: cBlaze(); CLASS_PROTODEF(cBlaze) private: virtual bool Attack(std::chrono::milliseconds a_Dt) override; virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override; virtual bool IsNetherNative(void) override { return true; } virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; /** Specifies whether or not the blaze has started shooting fireballs. */ bool m_IsCharging; /** Number of ticks since the blaze started charging. Used to create 3 successive projectiles. */ int m_ChargeTimer; } ; ================================================ FILE: src/Mobs/CMakeLists.txt ================================================ target_sources( ${CMAKE_PROJECT_NAME} PRIVATE AggressiveMonster.cpp Bat.cpp Blaze.cpp CaveSpider.cpp Chicken.cpp Cow.cpp Creeper.cpp EnderDragon.cpp Endermite.cpp Enderman.cpp Ghast.cpp Giant.cpp Guardian.cpp Horse.cpp IronGolem.cpp MagmaCube.cpp Monster.cpp Mooshroom.cpp Ocelot.cpp PassiveAggressiveMonster.cpp PassiveMonster.cpp Path.cpp PathFinder.cpp Pig.cpp Rabbit.cpp Sheep.cpp Silverfish.cpp Skeleton.cpp Slime.cpp SnowGolem.cpp Spider.cpp Squid.cpp Villager.cpp Witch.cpp Wither.cpp WitherSkeleton.cpp Wolf.cpp Zombie.cpp ZombiePigman.cpp ZombieVillager.cpp AggressiveMonster.h Bat.h Blaze.h CaveSpider.h Chicken.h Cow.h Creeper.h EnderDragon.h Endermite.h Enderman.h Ghast.h Giant.h Guardian.h Horse.h IncludeAllMonsters.h IronGolem.h MagmaCube.h Monster.h MonsterTypes.h Mooshroom.h Ocelot.h PassiveAggressiveMonster.h PassiveMonster.h Path.h PathFinder.h Pig.h Rabbit.h Sheep.h Silverfish.h Skeleton.h Slime.h SnowGolem.h Spider.h Squid.h Villager.h Witch.h Wither.h WitherSkeleton.h Wolf.h Zombie.h ZombiePigman.h ZombieVillager.h ) ================================================ FILE: src/Mobs/CaveSpider.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "CaveSpider.h" #include "../World.h" cCaveSpider::cCaveSpider(void) : Super("CaveSpider", mtCaveSpider, "entity.spider.hurt", "entity.spider.death", "entity.spider.ambient", 0.7f, 0.5f) { } void cCaveSpider::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { Super::Tick(a_Dt, a_Chunk); if (!IsTicking()) { // The base class tick destroyed us return; } m_EMPersonality = (GetWorld()->GetTimeOfDay() < 13000_tick) ? PASSIVE : AGGRESSIVE; } bool cCaveSpider::Attack(std::chrono::milliseconds a_Dt) { if (!Super::Attack(a_Dt)) { return false; } if (GetTarget()->IsPawn()) { // TODO: Easy = no poison, Medium = 7 seconds, Hard = 15 seconds static_cast(GetTarget())->AddEntityEffect(cEntityEffect::effPoison, 7 * 20, 0); } return true; } void cCaveSpider::GetDrops(cItems & a_Drops, cEntity * a_Killer) { unsigned int LootingLevel = 0; if (a_Killer != nullptr) { LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting); } AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_STRING); if ((a_Killer != nullptr) && (a_Killer->IsPlayer() || a_Killer->IsA("cWolf"))) { AddRandomUncommonDropItem(a_Drops, 33.0f, E_ITEM_SPIDER_EYE); } } ================================================ FILE: src/Mobs/CaveSpider.h ================================================ #pragma once #include "AggressiveMonster.h" class cCaveSpider: public cAggressiveMonster { using Super = cAggressiveMonster; public: cCaveSpider(); CLASS_PROTODEF(cCaveSpider) virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; virtual bool Attack(std::chrono::milliseconds a_Dt) override; virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override; } ; ================================================ FILE: src/Mobs/Chicken.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "Chicken.h" #include "../World.h" cChicken::cChicken(void) : Super("Chicken", mtChicken, "entity.chicken.hurt", "entity.chicken.death", "entity.chicken.ambient", 0.4f, 0.7f), m_EggDropTimer(0) { SetGravity(-2.0f); SetAirDrag(0.0f); } void cChicken::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { Super::Tick(a_Dt, a_Chunk); if (!IsTicking()) { // The base class tick destroyed us return; } if (IsBaby()) { return; // Babies don't lay eggs } if ( ((m_EggDropTimer == 6000) && GetRandomProvider().RandBool()) || m_EggDropTimer == 12000 ) { cItems Drops; m_EggDropTimer = 0; Drops.emplace_back(E_ITEM_EGG, static_cast(1)); m_World->SpawnItemPickups(Drops, GetPosX(), GetPosY(), GetPosZ(), 10); } else { m_EggDropTimer++; } } void cChicken::GetDrops(cItems & a_Drops, cEntity * a_Killer) { if (IsBaby()) { return; // Babies don't drop items } unsigned int LootingLevel = 0; if (a_Killer != nullptr) { LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting); } AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_FEATHER); AddRandomDropItem(a_Drops, 1, 1, IsOnFire() ? E_ITEM_COOKED_CHICKEN : E_ITEM_RAW_CHICKEN); } bool cChicken::DoTakeDamage(TakeDamageInfo & a_TDI) { if (a_TDI.DamageType == dtFalling) { return false; } return Super::DoTakeDamage(a_TDI); } ================================================ FILE: src/Mobs/Chicken.h ================================================ #pragma once #include "PassiveMonster.h" class cChicken: public cPassiveMonster { using Super = cPassiveMonster; public: cChicken(); CLASS_PROTODEF(cChicken) virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override; virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; virtual void GetFollowedItems(cItems & a_Items) override { a_Items.Add(E_ITEM_BEETROOT_SEEDS); a_Items.Add(E_ITEM_MELON_SEEDS); a_Items.Add(E_ITEM_PUMPKIN_SEEDS); a_Items.Add(E_ITEM_SEEDS); } virtual bool DoTakeDamage(TakeDamageInfo & a_TDI) override; private: int m_EggDropTimer; } ; ================================================ FILE: src/Mobs/Cow.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "Cow.h" #include "../Entities/Player.h" cCow::cCow(void) : Super("Cow", mtCow, "entity.cow.hurt", "entity.cow.death", "entity.cow.ambient", 0.9f, 1.4f) { } void cCow::GetDrops(cItems & a_Drops, cEntity * a_Killer) { if (IsBaby()) { return; // Babies don't drop items } unsigned int LootingLevel = 0; if (a_Killer != nullptr) { LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting); } AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_LEATHER); AddRandomDropItem(a_Drops, 1, 3 + LootingLevel, IsOnFire() ? E_ITEM_STEAK : E_ITEM_RAW_BEEF); } void cCow::OnRightClicked(cPlayer & a_Player) { Super::OnRightClicked(a_Player); short HeldItem = a_Player.GetEquippedItem().m_ItemType; if (HeldItem == E_ITEM_BUCKET) { // Milk the cow. if (!a_Player.IsGameModeCreative()) { a_Player.ReplaceOneEquippedItemTossRest(cItem(E_ITEM_MILK)); } } } ================================================ FILE: src/Mobs/Cow.h ================================================ #pragma once #include "PassiveMonster.h" class cCow: public cPassiveMonster { using Super = cPassiveMonster; public: cCow(); CLASS_PROTODEF(cCow) virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override; virtual void OnRightClicked(cPlayer & a_Player) override; virtual void GetFollowedItems(cItems & a_Items) override { a_Items.Add(E_ITEM_WHEAT); } } ; ================================================ FILE: src/Mobs/Creeper.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "Creeper.h" #include "../World.h" #include "../Entities/ProjectileEntity.h" #include "../Entities/Player.h" cCreeper::cCreeper(void) : Super("Creeper", mtCreeper, "entity.creeper.hurt", "entity.creeper.death", "entity.creeper.ambient", 0.6f, 1.7f), m_bIsBlowing(false), m_bIsCharged(false), m_BurnedWithFlintAndSteel(false), m_ExplodingTimer(0) { } void cCreeper::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { Super::Tick(a_Dt, a_Chunk); if (!IsTicking()) { // The base class tick destroyed us return; } if (((GetTarget() == nullptr) || !TargetIsInRange()) && !m_BurnedWithFlintAndSteel) { if (m_bIsBlowing) { m_ExplodingTimer = 0; m_bIsBlowing = false; m_World->BroadcastEntityMetadata(*this); } } else { if (m_bIsBlowing) { m_ExplodingTimer += 1; } if ((m_ExplodingTimer == 30) && (GetHealth() > 0.0)) // only explode when not already dead { m_World->DoExplosionAt((m_bIsCharged ? 5 : 3), GetPosX(), GetPosY(), GetPosZ(), false, esMonster, this); Destroy(); // Just in case we aren't killed by the explosion } } } void cCreeper::GetDrops(cItems & a_Drops, cEntity * a_Killer) { if (m_ExplodingTimer == 30) { // Exploded creepers drop naught but charred flesh, which Minecraft doesn't have return; } unsigned int LootingLevel = 0; if (a_Killer != nullptr) { LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting); } AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_GUNPOWDER); // If the creeper was killed by a skeleton, add a random music disc drop: if ( (a_Killer != nullptr) && a_Killer->IsProjectile() && ((static_cast(a_Killer))->GetCreatorUniqueID() != cEntity::INVALID_ID)) { auto ProjectileCreatorCallback = [](cEntity & a_Entity) { return ( a_Entity.IsMob() && ((static_cast(a_Entity)).GetMobType() == mtSkeleton) ); }; if (GetWorld()->DoWithEntityByID(static_cast(a_Killer)->GetCreatorUniqueID(), ProjectileCreatorCallback)) { AddRandomDropItem(a_Drops, 1, 1, static_cast(m_World->GetTickRandomNumber(11) + E_ITEM_FIRST_DISC)); } } } bool cCreeper::DoTakeDamage(TakeDamageInfo & a_TDI) { if (!Super::DoTakeDamage(a_TDI)) { return false; } if (a_TDI.DamageType == dtLightning) { m_bIsCharged = true; } m_World->BroadcastEntityMetadata(*this); return true; } bool cCreeper::Attack(std::chrono::milliseconds a_Dt) { UNUSED(a_Dt); if (!m_bIsBlowing) { m_World->BroadcastSoundEffect("entity.creeper.primed", GetPosition(), 1.f, (0.75f + (static_cast((GetUniqueID() * 23) % 32)) / 64)); m_bIsBlowing = true; m_World->BroadcastEntityMetadata(*this); return true; } return false; } void cCreeper::OnRightClicked(cPlayer & a_Player) { Super::OnRightClicked(a_Player); if ((a_Player.GetEquippedItem().m_ItemType == E_ITEM_FLINT_AND_STEEL)) { if (!a_Player.IsGameModeCreative()) { a_Player.UseEquippedItem(); } m_World->BroadcastSoundEffect("entity.creeper.primed", GetPosition(), 1.f, (0.75f + (static_cast((GetUniqueID() * 23) % 32)) / 64)); m_bIsBlowing = true; m_World->BroadcastEntityMetadata(*this); m_BurnedWithFlintAndSteel = true; } } ================================================ FILE: src/Mobs/Creeper.h ================================================ #pragma once #include "AggressiveMonster.h" class cCreeper: public cAggressiveMonster { using Super = cAggressiveMonster; public: cCreeper(); CLASS_PROTODEF(cCreeper) virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override; virtual bool DoTakeDamage(TakeDamageInfo & a_TDI) override; virtual bool Attack(std::chrono::milliseconds a_Dt) override; virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; virtual void OnRightClicked(cPlayer & a_Player) override; bool IsBlowing(void) const {return m_bIsBlowing; } bool IsCharged(void) const {return m_bIsCharged; } bool IsBurnedWithFlintAndSteel(void) const {return m_BurnedWithFlintAndSteel; } private: bool m_bIsBlowing, m_bIsCharged, m_BurnedWithFlintAndSteel; int m_ExplodingTimer; } ; ================================================ FILE: src/Mobs/EnderDragon.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "EnderDragon.h" #include "../ClientHandle.h" #include "../CompositeChat.h" cEnderDragon::cEnderDragon(void) : Super("EnderDragon", mtEnderDragon, "entity.enderdragon.hurt", "entity.enderdragon.death", "entity.enderdragon.ambient", 16, 8) { } bool cEnderDragon::DoTakeDamage(TakeDamageInfo & a_TDI) { if (!Super::DoTakeDamage(a_TDI)) { return false; } m_World->BroadcastBossBarUpdateHealth(*this, GetUniqueID(), GetHealth() / GetMaxHealth()); return true; } void cEnderDragon::GetDrops(cItems & a_Drops, cEntity * a_Killer) { // No drops } void cEnderDragon::SpawnOn(cClientHandle & a_Client) { Super::SpawnOn(a_Client); // Red boss bar with no divisions that plays boss music and creates fog: a_Client.SendBossBarAdd(GetUniqueID(), cCompositeChat("Ender Dragon"), GetHealth() / GetMaxHealth(), BossBarColor::Red, BossBarDivisionType::None, false, true, true); } ================================================ FILE: src/Mobs/EnderDragon.h ================================================ #pragma once #include "AggressiveMonster.h" class cEnderDragon: public cAggressiveMonster { using Super = cAggressiveMonster; public: cEnderDragon(); CLASS_PROTODEF(cEnderDragon) virtual bool DoTakeDamage(TakeDamageInfo & a_TDI) override; virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override; virtual void SpawnOn(cClientHandle & a_Client) override; } ; ================================================ FILE: src/Mobs/Enderman.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "Chunk.h" #include "Enderman.h" #include "../Entities/Player.h" #include "../LineBlockTracer.h" //////////////////////////////////////////////////////////////////////////////// // cPlayerLookCheck class cPlayerLookCheck { public: cPlayerLookCheck(Vector3d a_EndermanHeadPosition, int a_SightDistance) : m_Player(nullptr), m_EndermanHeadPosition(a_EndermanHeadPosition), m_SightDistance(a_SightDistance) { } bool operator () (cPlayer & a_Player) { // Don't check players who cannot be targeted if (!a_Player.CanMobsTarget()) { return false; } const auto PlayerHeadPosition = a_Player.GetPosition().addedY(a_Player.GetHeight()); const auto Direction = m_EndermanHeadPosition - PlayerHeadPosition; // Don't check players who are more than SightDistance (64) blocks away: if (Direction.Length() > m_SightDistance) { return false; } // Don't check if the player has a pumpkin on his head: if (a_Player.GetEquippedHelmet().m_ItemType == E_BLOCK_PUMPKIN) { return false; } const auto LookVector = a_Player.GetLookVector(); // Note: ||LookVector|| is always 1. const auto Cosine = Direction.Dot(LookVector) / Direction.Length(); // a.b / (||a|| * ||b||) // If the player's crosshair is within 5 degrees of the enderman, it counts as looking: if ((Cosine < std::cos(0.09)) || (Cosine > std::cos(0))) // 0.09 rad ~ 5 degrees { return false; } // TODO: Check if endermen are angered through water in Vanilla if (!cLineBlockTracer::LineOfSightTrace(*a_Player.GetWorld(), m_EndermanHeadPosition, PlayerHeadPosition, cLineBlockTracer::losAirWater)) { // No direct line of sight return false; } m_Player = &a_Player; return true; } cPlayer * GetPlayer(void) const { return m_Player; } protected: cPlayer * m_Player; Vector3d m_EndermanHeadPosition; int m_SightDistance; } ; cEnderman::cEnderman(void) : Super("Enderman", mtEnderman, "entity.endermen.hurt", "entity.endermen.death", "entity.endermen.ambient", 0.6f, 2.9f), m_bIsScreaming(false), m_CarriedBlock(E_BLOCK_AIR), m_CarriedMeta(0) { } void cEnderman::GetDrops(cItems & a_Drops, cEntity * a_Killer) { unsigned int LootingLevel = 0; if (a_Killer != nullptr) { LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting); } AddRandomDropItem(a_Drops, 0, 1 + LootingLevel, E_ITEM_ENDER_PEARL); } void cEnderman::CheckEventSeePlayer(cChunk & a_Chunk) { if (GetTarget() != nullptr) { return; } cPlayerLookCheck Callback(GetPosition().addedY(GetHeight()), m_SightDistance); if (m_World->ForEachPlayer(Callback)) { return; } ASSERT(Callback.GetPlayer() != nullptr); // Target the player: cAggressiveMonster::EventSeePlayer(Callback.GetPlayer(), a_Chunk); m_bIsScreaming = true; GetWorld()->BroadcastEntityMetadata(*this); } void cEnderman::EventLosePlayer() { Super::EventLosePlayer(); m_bIsScreaming = false; GetWorld()->BroadcastEntityMetadata(*this); } void cEnderman::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { Super::Tick(a_Dt, a_Chunk); if (!IsTicking()) { // The base class tick destroyed us return; } if (m_EMState != CHASING) { cMonster * EndermiteFound = GetMonsterOfTypeInSight(mtEndermite, 64); if (EndermiteFound != nullptr) { SetTarget(EndermiteFound); m_EMState = CHASING; m_bIsScreaming = true; } } else { const auto Target = GetTarget(); if (Target != nullptr) { if (!Target->IsTicking()) { m_EMState = IDLE; m_bIsScreaming = false; } } } PREPARE_REL_AND_CHUNK(GetPosition().Floor(), a_Chunk); if (!RelSuccess) { return; } // Take damage when wet: if (IsInWater() || Chunk->IsWeatherWetAt(Rel)) { EventLosePlayer(); TakeDamage(dtEnvironment, nullptr, 1, 0); // TODO teleport to a safe location } } ================================================ FILE: src/Mobs/Enderman.h ================================================ #pragma once #include "PassiveAggressiveMonster.h" class cEnderman: public cPassiveAggressiveMonster { using Super = cPassiveAggressiveMonster; public: cEnderman(); CLASS_PROTODEF(cEnderman) virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override; virtual void CheckEventSeePlayer(cChunk & a_Chunk) override; virtual void EventLosePlayer(void) override; virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; bool IsScreaming(void) const {return m_bIsScreaming; } BLOCKTYPE GetCarriedBlock(void) const {return m_CarriedBlock; } NIBBLETYPE GetCarriedMeta(void) const {return m_CarriedMeta; } private: bool m_bIsScreaming; BLOCKTYPE m_CarriedBlock; NIBBLETYPE m_CarriedMeta; } ; ================================================ FILE: src/Mobs/Endermite.cpp ================================================ #include "Globals.h" #include "Endermite.h" #include "../World.h" #include "../Chunk.h" #include "../Blocks/BlockHandler.h" #include "../Blocks/BlockInfested.h" cEndermite::cEndermite() : Super("Endermite", mtEndermite, "entity.endermite.hurt", "entity.endermite.death", "entity.endermite.ambient", 0.4f, 0.3f), m_Timer(0), m_Lifetime(2 * 1000 * 60) // 2 minutes (2 * 1000 (mili to sec) * 60 (sec to min) * 2 because tick = 0.5 sec) { } void cEndermite::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { Super::Tick(a_Dt, a_Chunk); // Not destroying the endermite if a name is set if (m_CustomName.empty()) { m_Timer += a_Dt; // Destroy the endermite after 2 minutes if (m_Timer > m_Lifetime) { Destroy(); } } } ================================================ FILE: src/Mobs/Endermite.h ================================================ #pragma once #include "AggressiveMonster.h" class cEndermite: public cAggressiveMonster { using Super = cAggressiveMonster; // Endermite should despawn in two minutes std::chrono::milliseconds m_Timer; std::chrono::milliseconds m_Lifetime; public: cEndermite(); CLASS_PROTODEF(cEndermite) void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; } ; ================================================ FILE: src/Mobs/Ghast.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "Ghast.h" #include "../World.h" #include "../Entities/GhastFireballEntity.h" cGhast::cGhast(void) : Super("Ghast", mtGhast, "entity.ghast.hurt", "entity.ghast.death", "entity.ghast.ambient", 4, 4), m_IsCharging(false), m_FlightCooldown(5), m_TicksUntilShot(10) { SetGravity(0); SetAirDrag(0); } bool cGhast::Attack(std::chrono::milliseconds a_Dt) { if ((GetTarget() != nullptr) && (m_AttackCoolDownTicksLeft == 0) && (!m_IsCharging)) { auto & Random = GetRandomProvider(); auto SoundPitchMultiplier = 1.0f + (Random.RandReal(1.0f) - Random.RandReal(1.0f)) * 0.2f; m_World->BroadcastSoundEffect("entity.ghast.warn", GetPosition(), 4.0f, SoundPitchMultiplier * 0.9f); m_IsCharging = true; m_World->BroadcastEntityMetadata(*this); return true; } return false; } bool cGhast::DoTakeDamage(TakeDamageInfo & a_TDI) { // No fall damage if (a_TDI.DamageType == dtFalling) { return false; } return Super::DoTakeDamage(a_TDI); } void cGhast::GetDrops(cItems & a_Drops, cEntity * a_Killer) { unsigned int LootingLevel = 0; if (a_Killer != nullptr) { LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting); } AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_GUNPOWDER); AddRandomDropItem(a_Drops, 0, 1 + LootingLevel, E_ITEM_GHAST_TEAR); } void cGhast::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { Super::Tick(a_Dt, a_Chunk); if (!IsTicking()) { // The base class tick destroyed us return; } if ((m_IsCharging) && (m_TicksUntilShot-- == 0)) { m_TicksUntilShot = 10; m_IsCharging = false; m_World->BroadcastEntityMetadata(*this); Vector3d Speed = GetLookVector() * 20; Speed.y = Speed.y + 1; auto GhastBall = std::make_unique(this, GetPosition(), Speed); auto GhastBallPtr = GhastBall.get(); GhastBallPtr->Initialize(std::move(GhastBall), *m_World); m_World->BroadcastSoundEffect("entity.ghast.shoot", GetPosition(), 4.0f, 1.0f); ResetAttackCooldown(); } // TODO: Better flying if (m_FlightCooldown-- == 0) { m_FlightCooldown = 5; auto & Random = GetRandomProvider(); auto SpeedVector = Vector3d(Random.RandReal(-0.3, 0.3), Random.RandReal(-0.4, 0.4), Random.RandReal(-0.3, 0.3)); if (GetPosY() > 120) { SpeedVector = Vector3d(Random.RandReal(-0.4, 0.4), Random.RandReal(-0.45, 0.4), Random.RandReal(-0.4, 0.4)); } AddSpeed(SpeedVector); } } ================================================ FILE: src/Mobs/Ghast.h ================================================ #pragma once #include "AggressiveMonster.h" class cGhast: public cAggressiveMonster { using Super = cAggressiveMonster; public: cGhast(); CLASS_PROTODEF(cGhast) bool IsCharging(void) const { return m_IsCharging; } private: virtual bool Attack(std::chrono::milliseconds a_Dt) override; virtual bool DoTakeDamage(TakeDamageInfo & a_TDI) override; virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override; virtual bool IsNetherNative(void) override { return true; } virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; /** Specifies whether or not the ghast has started shooting a fireball. */ bool m_IsCharging; /** Number of ticks until the ghast tries to fly to another position. */ int m_FlightCooldown; /** Number of ticks until a projectile is created. Only used while m_IsCharging is true. */ int m_TicksUntilShot; } ; ================================================ FILE: src/Mobs/Giant.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "Giant.h" cGiant::cGiant(void) : Super("Giant", mtGiant, "entity.zombie.hurt", "entity.zombie.death", "entity.zombie.ambient", 3.6f, 12) { } void cGiant::GetDrops(cItems & a_Drops, cEntity * a_Killer) { AddRandomDropItem(a_Drops, 10, 50, E_ITEM_ROTTEN_FLESH); } ================================================ FILE: src/Mobs/Giant.h ================================================ #pragma once #include "AggressiveMonster.h" class cGiant: public cAggressiveMonster { using Super = cAggressiveMonster; public: cGiant(void); CLASS_PROTODEF(cGiant) virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override; } ; ================================================ FILE: src/Mobs/Guardian.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "Guardian.h" #include "../Chunk.h" cGuardian::cGuardian(void) : Super("Guardian", mtGuardian, "entity.guardian.hurt", "entity.guardian.death", "entity.guardian.ambient", 0.85f, 0.85f) { } void cGuardian::GetDrops(cItems & a_Drops, cEntity * a_Killer) { // Drops 0-3 Ink Sacs unsigned int LootingLevel = 0; if (a_Killer != nullptr) { LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting); } AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_PRISMARINE_SHARD); AddRandomDropItem(a_Drops, 0, 1 + LootingLevel, E_ITEM_RAW_FISH); AddRandomDropItem(a_Drops, 0, 1 + LootingLevel, E_ITEM_PRISMARINE_CRYSTALS); // TODO: Prismarine Crystals only drop if the raw fish drop is 0 } void cGuardian::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { m_PathfinderActivated = false; // Disable Pathfinding until it's fixed. TODO // We must first process current location, and only then tick, otherwise we risk processing a location in a chunk // that is not where the entity currently resides (FS #411) Vector3d Pos = GetPosition(); int RelY = FloorC(Pos.y); if ((RelY < 0) || (RelY >= cChunkDef::Height)) { return; } Super::Tick(a_Dt, a_Chunk); } ================================================ FILE: src/Mobs/Guardian.h ================================================ #pragma once #include "AggressiveMonster.h" class cGuardian: public cAggressiveMonster { using Super = cAggressiveMonster; public: cGuardian(); virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; CLASS_PROTODEF(cGuardian) virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override; // Guardians do not drown (or float) virtual void HandleAir(void) override {} virtual void SetSwimState(cChunk & a_Chunk) override {} } ; ================================================ FILE: src/Mobs/Horse.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "Horse.h" #include "../World.h" #include "../EffectID.h" #include "../Entities/Player.h" #include "../UI/HorseWindow.h" cHorse::cHorse(int Type, int Color, int Style, int TameTimes) : Super("Horse", mtHorse, "entity.horse.hurt", "entity.horse.death", "entity.horse.ambient", 1.4f, 1.6f), cEntityWindowOwner(this), m_bHasChest(false), m_bIsEating(false), m_bIsRearing(false), m_bIsMouthOpen(false), m_bIsTame(false), m_Type(Type), m_Color(Color), m_Style(Style), m_TimesToTame(TameTimes), m_TameAttemptTimes(0), m_RearTickCount(0), m_MaxSpeed(14.0) { } void cHorse::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { Super::Tick(a_Dt, a_Chunk); if (!IsTicking()) { // The base class tick destroyed us return; } bool MetadataDirty = false; auto & Random = GetRandomProvider(); if (!m_bIsMouthOpen) { if (Random.RandBool(0.02)) { MetadataDirty = true; m_bIsMouthOpen = true; } } else { if (Random.RandBool(0.10)) { MetadataDirty = true; m_bIsMouthOpen = false; } } if ((m_Attachee != nullptr) && (!m_bIsTame)) { if (m_TameAttemptTimes < m_TimesToTame) { if (Random.RandBool(0.02)) { m_World->BroadcastSoundParticleEffect(EffectID::PARTICLE_SMOKE, GetPosition().Floor(), int(SmokeDirection::SOUTH_EAST)); m_World->BroadcastSoundParticleEffect(EffectID::PARTICLE_SMOKE, GetPosition().Floor(), int(SmokeDirection::SOUTH_WEST)); m_World->BroadcastSoundParticleEffect(EffectID::PARTICLE_SMOKE, GetPosition().Floor(), int(SmokeDirection::NORTH_EAST)); m_World->BroadcastSoundParticleEffect(EffectID::PARTICLE_SMOKE, GetPosition().Floor(), int(SmokeDirection::NORTH_WEST)); m_World->BroadcastSoundEffect("entity.horse.angry", GetPosition(), 1.0f, 1.0f); m_Attachee->Detach(); MetadataDirty = true; m_bIsRearing = true; } } else { m_World->BroadcastParticleEffect("heart", static_cast(GetPosition()), Vector3f{}, 0, 5); MetadataDirty = true; m_bIsTame = true; } } if (m_bIsRearing) { if (m_RearTickCount == 20) { MetadataDirty = true; m_bIsRearing = false; m_RearTickCount = 0; } else { m_RearTickCount++; } } if (MetadataDirty) { m_World->BroadcastEntityMetadata(*this); } } void cHorse::OnRemoveFromWorld(cWorld & a_World) { const auto Window = GetWindow(); if (Window != nullptr) { Window->OwnerDestroyed(); } Super::OnRemoveFromWorld(a_World); } void cHorse::OnRightClicked(cPlayer & a_Player) { Super::OnRightClicked(a_Player); if (m_bIsTame) { if (a_Player.IsCrouched()) { PlayerOpenWindow(a_Player); return; } auto EquipedItemType = a_Player.GetEquippedItem().m_ItemType; if ( !IsSaddled() && ( (EquipedItemType == E_ITEM_SADDLE) || ItemCategory::IsHorseArmor(EquipedItemType) ) ) { // Player is holding a horse inventory item, open the window: PlayerOpenWindow(a_Player); } else { a_Player.AttachTo(*this); } } else if (a_Player.GetEquippedItem().IsEmpty()) { // Check if leashed / unleashed to player before try to ride if (!m_IsLeashActionJustDone) { if (m_Attachee != nullptr) { if (m_Attachee->GetUniqueID() == a_Player.GetUniqueID()) { a_Player.Detach(); return; } if (m_Attachee->IsPlayer()) { return; } m_Attachee->Detach(); } m_TameAttemptTimes++; a_Player.AttachTo(*this); } } else { m_bIsRearing = true; m_RearTickCount = 0; m_World->BroadcastSoundEffect("entity.horse.angry", GetPosition(), 1.0f, 0.8f); } } void cHorse::SetHorseSaddle(cItem a_Saddle) { if (a_Saddle.m_ItemType == E_ITEM_SADDLE) { m_World->BroadcastSoundEffect("entity.horse.saddle", GetPosition(), 1.0f, 0.8f); } else if (!a_Saddle.IsEmpty()) { return; // Invalid item } m_Saddle = std::move(a_Saddle); m_World->BroadcastEntityMetadata(*this); } void cHorse::SetHorseArmor(cItem a_Armor) { if (ItemCategory::IsHorseArmor(a_Armor.m_ItemType)) { m_World->BroadcastSoundEffect("entity.horse.armor", GetPosition(), 1.0f, 0.8f); } else if (!a_Armor.IsEmpty()) { return; // Invalid item } m_Armor = std::move(a_Armor); m_World->BroadcastEntityMetadata(*this); } int cHorse::GetHorseArmour(void) const { switch (m_Armor.m_ItemType) { case E_ITEM_EMPTY: return 0; case E_ITEM_IRON_HORSE_ARMOR: return 1; case E_ITEM_GOLD_HORSE_ARMOR: return 2; case E_ITEM_DIAMOND_HORSE_ARMOR: return 3; default: { LOGWARN("cHorse::GetHorseArmour: Invalid armour item (%d)", m_Armor.m_ItemType); return 0; } } } void cHorse::GetDrops(cItems & a_Drops, cEntity * a_Killer) { if (IsBaby()) { return; // Babies don't drop items } unsigned int LootingLevel = 0; if (a_Killer != nullptr) { LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting); } AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_LEATHER); if (IsSaddled()) { a_Drops.push_back(m_Saddle); } if (!m_Armor.IsEmpty()) { a_Drops.push_back(m_Armor); } } void cHorse::InStateIdle(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { // If horse is tame and someone is sitting on it, don't walk around if ((!m_bIsTame) || (m_Attachee == nullptr)) { Super::InStateIdle(a_Dt, a_Chunk); } } void cHorse::HandleSpeedFromAttachee(float a_Forward, float a_Sideways) { if ((m_bIsTame) && IsSaddled()) { Super::HandleSpeedFromAttachee(a_Forward * m_MaxSpeed, a_Sideways * m_MaxSpeed); } } void cHorse::PlayerOpenWindow(cPlayer & a_Player) { auto Window = GetWindow(); if (Window == nullptr) { Window = new cHorseWindow(*this); OpenWindow(Window); } a_Player.OpenWindow(*Window); } ================================================ FILE: src/Mobs/Horse.h ================================================ #pragma once #include "PassiveMonster.h" #include "../UI/WindowOwner.h" class cHorse: public cPassiveMonster, public cEntityWindowOwner { using Super = cPassiveMonster; public: cHorse(int Type, int Color, int Style, int TameTimes); CLASS_PROTODEF(cHorse) virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override; virtual void InStateIdle(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; virtual void HandleSpeedFromAttachee(float a_Forward, float a_Sideways) override; virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; virtual void OnRemoveFromWorld(cWorld & a_World) override; virtual void OnRightClicked(cPlayer & a_Player) override; bool IsSaddled (void) const {return !m_Saddle.IsEmpty(); } bool IsChested (void) const {return m_bHasChest; } bool IsEating (void) const {return m_bIsEating; } bool IsRearing (void) const {return m_bIsRearing; } bool IsMthOpen (void) const {return m_bIsMouthOpen; } bool IsTame (void) const override {return m_bIsTame; } int GetHorseType (void) const {return m_Type; } int GetHorseColor (void) const {return m_Color; } int GetHorseStyle (void) const {return m_Style; } int GetHorseArmour (void) const; /** Set the horse's saddle to the given item. @param a_SaddleItem should be either a saddle or empty. */ void SetHorseSaddle(cItem a_SaddleItem); /** Set the horse's armor slot to the given item. @param a_SaddleItem should be either a type of horse armor or empty. */ void SetHorseArmor(cItem a_ArmorItem); const cItem & GetHorseSaddle() const { return m_Saddle; } const cItem & GetHorseArmorItem() const { return m_Armor; } virtual void GetBreedingItems(cItems & a_Items) override { a_Items.Add(E_ITEM_GOLDEN_CARROT); a_Items.Add(E_ITEM_GOLDEN_APPLE); } void PlayerOpenWindow(cPlayer & a_Player); private: bool m_bHasChest, m_bIsEating, m_bIsRearing, m_bIsMouthOpen, m_bIsTame; int m_Type, m_Color, m_Style, m_TimesToTame, m_TameAttemptTimes, m_RearTickCount; float m_MaxSpeed; cItem m_Saddle; cItem m_Armor; } ; ================================================ FILE: src/Mobs/IncludeAllMonsters.h ================================================ #include "Bat.h" #include "Blaze.h" #include "CaveSpider.h" #include "Chicken.h" #include "Cow.h" #include "Creeper.h" #include "Enderman.h" #include "Endermite.h" #include "EnderDragon.h" #include "Ghast.h" #include "Giant.h" #include "Guardian.h" #include "Horse.h" #include "IronGolem.h" #include "MagmaCube.h" #include "Mooshroom.h" #include "Ocelot.h" #include "Pig.h" #include "Rabbit.h" #include "Sheep.h" #include "Silverfish.h" #include "Skeleton.h" #include "Slime.h" #include "SnowGolem.h" #include "Spider.h" #include "Squid.h" #include "Villager.h" #include "Witch.h" #include "Wither.h" #include "WitherSkeleton.h" #include "Wolf.h" #include "Zombie.h" #include "ZombiePigman.h" #include "ZombieVillager.h" ================================================ FILE: src/Mobs/IronGolem.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "IronGolem.h" cIronGolem::cIronGolem(void) : Super("IronGolem", mtIronGolem, "entity.irongolem.hurt", "entity.irongolem.death", "entity.irongolem.ambient", 1.4f, 2.7f) { } void cIronGolem::GetDrops(cItems & a_Drops, cEntity * a_Killer) { UNUSED(a_Killer); AddRandomDropItem(a_Drops, 0, 5, E_ITEM_IRON); AddRandomDropItem(a_Drops, 0, 2, E_BLOCK_FLOWER); } ================================================ FILE: src/Mobs/IronGolem.h ================================================ #pragma once #include "PassiveAggressiveMonster.h" class cIronGolem: public cPassiveAggressiveMonster { using Super = cPassiveAggressiveMonster; public: cIronGolem(); CLASS_PROTODEF(cIronGolem) virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override; // Iron golems do not drown nor float virtual void HandleAir(void) override {} virtual void SetSwimState(cChunk & a_Chunk) override {} } ; ================================================ FILE: src/Mobs/MagmaCube.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "MagmaCube.h" cMagmaCube::cMagmaCube(int a_Size) : Super( "MagmaCube", mtMagmaCube, fmt::format(FMT_STRING("entity.{}magmacube.hurt"), GetSizeName(a_Size)), fmt::format(FMT_STRING("entity.{}magmacube.death"), GetSizeName(a_Size)), "", 0.51f * a_Size, 0.51f * a_Size ), m_Size(a_Size) { } AString cMagmaCube::GetSizeName(int a_Size) { if (a_Size == 1) { return "small_"; } return ""; } void cMagmaCube::GetDrops(cItems & a_Drops, cEntity * a_Killer) { UNUSED(a_Killer); if (GetSize() > 1) { AddRandomUncommonDropItem(a_Drops, 25.0f, E_ITEM_MAGMA_CREAM); } } ================================================ FILE: src/Mobs/MagmaCube.h ================================================ #pragma once #include "AggressiveMonster.h" class cMagmaCube: public cAggressiveMonster { using Super = cAggressiveMonster; public: /** Creates a MagmaCube of the specified size; with 1 being the smallest */ cMagmaCube(int a_Size); CLASS_PROTODEF(cMagmaCube) int GetSize(void) const { return m_Size; } /** Returns the text describing the slime's size, as used by the client's resource subsystem for sounds. Returns either "big" or "small". */ static AString GetSizeName(int a_Size); private: virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override; virtual bool IsNetherNative(void) override { return true; } /** Size of the MagmaCube, with 1 being the smallest */ int m_Size; } ; ================================================ FILE: src/Mobs/Monster.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "IncludeAllMonsters.h" #include "LineBlockTracer.h" #include "../BlockInfo.h" #include "../Root.h" #include "../Server.h" #include "../ClientHandle.h" #include "../Items/ItemHandler.h" #include "../World.h" #include "../EffectID.h" #include "../Entities/Player.h" #include "../Entities/ExpOrb.h" #include "../MonsterConfig.h" #include "../BoundingBox.h" #include "Items/ItemSpawnEgg.h" #include "../Chunk.h" #include "../FastRandom.h" #include "PathFinder.h" #include "../Entities/LeashKnot.h" /** Map for eType <-> string Needs to be alpha-sorted by the strings, because binary search is used in StringToMobType() The strings need to be lowercase (for more efficient comparisons in StringToMobType()) m_VanillaName is the name that vanilla use for this mob. */ static const struct { eMonsterType m_Type; const char * m_lcName; const char * m_VanillaName; const char * m_VanillaNameNBT; } g_MobTypeNames[] = { {mtBat, "bat", "Bat", "bat"}, {mtBlaze, "blaze", "Blaze", "blaze"}, {mtCaveSpider, "cavespider", "CaveSpider", "cave_spider"}, {mtChicken, "chicken", "Chicken", "chicken"}, {mtCow, "cow", "Cow", "cow"}, {mtCreeper, "creeper", "Creeper", "creeper"}, {mtEnderman, "enderman", "Enderman", "enderman"}, {mtEndermite, "endermite", "Endermite", "endermite"}, {mtEnderDragon, "enderdragon", "EnderDragon", "ender_dragon"}, {mtGhast, "ghast", "Ghast", "ghast"}, {mtGiant, "giant", "Giant", "giant"}, {mtGuardian, "guardian", "Guardian", "guardian"}, {mtHorse, "horse", "EntityHorse", "horse"}, {mtIronGolem, "irongolem", "VillagerGolem", "iron_golem"}, {mtMagmaCube, "magmacube", "LavaSlime", "magma_cube"}, {mtMooshroom, "mooshroom", "MushroomCow", "mooshroom"}, {mtOcelot, "ocelot", "Ozelot", "ocelot"}, {mtPig, "pig", "Pig", "pig"}, {mtRabbit, "rabbit", "Rabbit", "rabbit"}, {mtSheep, "sheep", "Sheep", "sheep"}, {mtSilverfish, "silverfish", "Silverfish", "silverfish"}, {mtSkeleton, "skeleton", "Skeleton", "skeleton"}, {mtSlime, "slime", "Slime", "slime"}, {mtSnowGolem, "snowgolem", "SnowMan", "snow_golem"}, {mtSpider, "spider", "Spider", "spider"}, {mtSquid, "squid", "Squid", "squid"}, {mtVillager, "villager", "Villager", "villager"}, {mtWitch, "witch", "Witch", "witch"}, {mtWither, "wither", "WitherBoss", "wither"}, {mtWitherSkeleton, "witherskeleton", "WitherSkeleton", "wither_skeleton"}, {mtWolf, "wolf", "Wolf", "wolf"}, {mtZombie, "zombie", "Zombie", "zombie"}, {mtZombiePigman, "zombiepigman", "PigZombie", "zombie_pigman"}, {mtZombieVillager, "zombievillager", "ZombieVillager", "zombie_villager"}, } ; //////////////////////////////////////////////////////////////////////////////// // cMonster: cMonster::cMonster(const AString & a_ConfigName, eMonsterType a_MobType, const AString & a_SoundHurt, const AString & a_SoundDeath, const AString & a_SoundAmbient, float a_Width, float a_Height) : Super(etMonster, a_Width, a_Height) , m_EMState(IDLE) , m_EMPersonality(AGGRESSIVE) , m_PathFinder(a_Width, a_Height) , m_PathfinderActivated(false) , m_JumpCoolDown(0) , m_IdleInterval(0) , m_DestroyTimer(0) , m_MobType(a_MobType) , m_CustomName() , m_CustomNameAlwaysVisible(false) , m_SoundHurt(a_SoundHurt) , m_SoundDeath(a_SoundDeath) , m_SoundAmbient(a_SoundAmbient) , m_AttackRate(3) , m_AttackDamage(1) , m_AttackRange(1) , m_AttackCoolDownTicksLeft(0) , m_SightDistance(25) , m_DropChanceWeapon(0.085f) , m_DropChanceHelmet(0.085f) , m_DropChanceChestplate(0.085f) , m_DropChanceLeggings(0.085f) , m_DropChanceBoots(0.085f) , m_CanPickUpLoot(true) , m_TicksSinceLastDamaged(100) , m_BurnsInDaylight(false) , m_RelativeWalkSpeed(1) , m_Age(1) , m_AgingTimer(TPS * 60 * 20) // about 20 minutes , m_WasLastTargetAPlayer(false) , m_LeashedTo(nullptr) , m_LeashToPos(nullptr) , m_IsLeashActionJustDone(false) , m_CanBeLeashed(GetMobFamily() == eFamily::mfPassive) , m_LovePartner(nullptr) , m_LoveTimer(0) , m_LoveCooldown(0) , m_MatingTimer(0) , m_Target(nullptr) { if (!a_ConfigName.empty()) { GetMonsterConfig(a_ConfigName); } // Prevent mobs spawning at the same time from making sounds simultaneously m_AmbientSoundTimer = GetRandomProvider().RandInt(0, 100); } void cMonster::OnRemoveFromWorld(cWorld & a_World) { SetTarget(nullptr); // Tell them we're no longer targeting them. if (m_LovePartner != nullptr) { m_LovePartner->ResetLoveMode(); } if (IsLeashed()) { cEntity * LeashedTo = GetLeashedTo(); Unleash(false, true); // Remove leash knot if there are no more mobs leashed to if (!LeashedTo->HasAnyMobLeashed() && LeashedTo->IsLeashKnot()) { LeashedTo->Destroy(); } } Super::OnRemoveFromWorld(a_World); } void cMonster::SpawnOn(cClientHandle & a_Client) { a_Client.SendSpawnMob(*this); if (IsLeashed()) { a_Client.SendLeashEntity(*this, *this->GetLeashedTo()); } } void cMonster::MoveToWayPoint(cChunk & a_Chunk) { if ((m_NextWayPointPosition - GetPosition()).SqrLength() < WAYPOINT_RADIUS * WAYPOINT_RADIUS) { return; } if (m_JumpCoolDown <= 0) { if (DoesPosYRequireJump(FloorC(m_NextWayPointPosition.y))) { if ( (IsOnGround() && (GetSpeed().SqrLength() <= 0.5)) || // If walking on the ground, we need to slow down first, otherwise we miss the jump IsInWater() ) { m_bOnGround = false; m_JumpCoolDown = 20; AddPosY(1.6); // Jump!! SetSpeedY(1); SetSpeedX(3.2 * (m_NextWayPointPosition.x - GetPosition().x)); // Move forward in a preset speed. SetSpeedZ(3.2 * (m_NextWayPointPosition.z - GetPosition().z)); // The numbers were picked based on trial and error } } } else { --m_JumpCoolDown; } Vector3d Distance = m_NextWayPointPosition - GetPosition(); if ((std::abs(Distance.x) > 0.05) || (std::abs(Distance.z) > 0.05)) { Distance.y = 0; Distance.Normalize(); if (m_bOnGround) { Distance *= 2.5f; } else if (IsInWater()) { Distance *= 1.3f; } else { // Don't let the mob move too much if he's falling. Distance *= 0.25f; } if ((m_EMState == CHASING) || (m_EMState == ESCAPING)) { // Apply run speed: Distance *= m_BaseRunSpeed * m_RelativeWalkSpeed; } else { // Apply walk speed: Distance *= m_BaseWalkSpeed * m_RelativeWalkSpeed; } /* Reduced default speed. Close to Vanilla, easier for mobs to follow m_NextWayPointPositions, hence better pathfinding. */ Distance *= 0.5; AddSpeedX(Distance.x); AddSpeedZ(Distance.z); } } void cMonster::MoveToPosition(const Vector3d & a_Position) { m_FinalDestination = a_Position; m_PathfinderActivated = true; } void cMonster::StopMovingToPosition() { m_PathfinderActivated = false; } void cMonster::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { Super::Tick(a_Dt, a_Chunk); if (!IsTicking()) { // The base class tick destroyed us return; } GET_AND_VERIFY_CURRENT_CHUNK(Chunk, POSX_TOINT, POSZ_TOINT); ASSERT((GetTarget() == nullptr) || (GetTarget()->IsPawn() && (GetTarget()->GetWorld() == GetWorld()))); if (m_AttackCoolDownTicksLeft > 0) { m_AttackCoolDownTicksLeft -= 1; } if (m_Health <= 0) { // The mob is dead, but we're still animating the "puff" they leave when they die m_DestroyTimer += a_Dt; if (m_DestroyTimer > std::chrono::seconds(1)) { Destroy(); } return; } if (m_TicksSinceLastDamaged < 100) { ++m_TicksSinceLastDamaged; } // Process the undead burning in daylight. HandleDaylightBurning(*Chunk, WouldBurnAt(GetPosition(), *Chunk)); bool a_IsFollowingPath = false; if (m_PathfinderActivated && (GetMobType() != mtGhast)) // Pathfinder is currently disabled for ghasts, which have their own flying mechanism { if (ReachedFinalDestination() || (m_LeashToPos != nullptr)) { StopMovingToPosition(); // Simply sets m_PathfinderActivated to false. } else { // Note that m_NextWayPointPosition is actually returned by GetNextWayPoint) switch (m_PathFinder.GetNextWayPoint(*Chunk, GetPosition(), &m_FinalDestination, &m_NextWayPointPosition, m_EMState == IDLE)) { case ePathFinderStatus::PATH_FOUND: { /* If I burn in daylight, and I won't burn where I'm standing, and I'll burn in my next position, and at least one of those is true: 1. I am idle 2. I was not hurt by a player recently. Then STOP. */ if ( m_BurnsInDaylight && ((m_TicksSinceLastDamaged >= 100) || (m_EMState == IDLE)) && WouldBurnAt(m_NextWayPointPosition, *Chunk) && !WouldBurnAt(GetPosition(), *Chunk) ) { // If we burn in daylight, and we would burn at the next step, and we won't burn where we are right now, and we weren't provoked recently: StopMovingToPosition(); } else { a_IsFollowingPath = true; // Used for proper body / head orientation only. MoveToWayPoint(*Chunk); } break; } case ePathFinderStatus::PATH_NOT_FOUND: { StopMovingToPosition(); break; } default: { } } } } SetPitchAndYawFromDestination(a_IsFollowingPath); switch (m_EMState) { case IDLE: { // If enemy passive we ignore checks for player visibility. InStateIdle(a_Dt, a_Chunk); break; } case CHASING: { // If we do not see a player anymore skip chasing action. InStateChasing(a_Dt, a_Chunk); break; } case ESCAPING: { InStateEscaping(a_Dt, a_Chunk); break; } case ATTACKING: break; } // switch (m_EMState) // Leash calculations CalcLeashActions(a_Dt); BroadcastMovementUpdate(); // Ambient mob sounds if (!m_SoundAmbient.empty() && (--m_AmbientSoundTimer <= 0)) { auto & Random = GetRandomProvider(); auto ShouldPlaySound = Random.RandBool(); if (ShouldPlaySound) { auto SoundPitchMultiplier = 1.0f + (Random.RandReal(1.0f) - Random.RandReal(1.0f)) * 0.2f; m_World->BroadcastSoundEffect(m_SoundAmbient, GetPosition(), 1.0f, SoundPitchMultiplier * 1.0f); } m_AmbientSoundTimer = 100; } if (m_AgingTimer > 0) { m_AgingTimer--; if ((m_AgingTimer <= 0) && IsBaby()) { SetAge(1); m_World->BroadcastEntityMetadata(*this); } } } void cMonster::CalcLeashActions(std::chrono::milliseconds a_Dt) { // This mob just spotted in the world and [m_LeashToPos not null] shows that should be leashed to a leash knot at m_LeashToPos. // This keeps trying until knot is found. Leash knot may be in a different chunk that needn't or can't be loaded yet. if (!IsLeashed() && (m_LeashToPos != nullptr)) { auto LeashKnot = cLeashKnot::FindKnotAtPos(*m_World, { FloorC(m_LeashToPos->x), FloorC(m_LeashToPos->y), FloorC(m_LeashToPos->z) }); if (LeashKnot != nullptr) { LeashTo(*LeashKnot); SetLeashToPos(nullptr); } } if (!IsLeashed()) { return; } static const double CloseFollowDistance = 1.8; // The closest the mob will path towards the leashed to entity static const double LeashNaturalLength = 5.0; // The closest the mob is actively pulled towards the entity static const double LeashMaximumLength = 10.0; // Length where the leash breaks static const double LeashSpringConstant = 20.0; // How stiff the leash is const auto LeashedToPos = m_LeashedTo->GetPosition(); const auto Displacement = LeashedToPos - GetPosition(); const auto Distance = Displacement.Length(); const auto Direction = Displacement.NormalizeCopy(); // If the leash is over-extended, break the leash: if (Distance > LeashMaximumLength) { LOGD("Leash broken (distance)"); Unleash(false); return; } // If the mob isn't following close enough, pull the mob towards the leashed to entity: if (Distance > LeashNaturalLength) { // Accelerate monster towards the leashed to entity: const auto Extension = Distance - LeashNaturalLength; auto Acceleration = Direction * (Extension * LeashSpringConstant); // Stop mobs from floating up when on the ground if (IsOnGround() && (Acceleration.y < std::abs(GetGravity()))) { Acceleration.y = 0.0; } // Apply the acceleration using namespace std::chrono; AddSpeed(Acceleration * duration_cast>(a_Dt).count()); } // Passively follow the leashed to entity: if (Distance > CloseFollowDistance) { const Vector3d TargetBlock((LeashedToPos - Direction * CloseFollowDistance).Floor()); // Move to centre of target block face MoveToPosition(TargetBlock + Vector3d{ 0.5, 0.0, 0.5 }); } } void cMonster::SetPitchAndYawFromDestination(bool a_IsFollowingPath) { Vector3d BodyDistance; if (!a_IsFollowingPath) { if (GetTarget() == nullptr) { // Avoid dirtying head position when nothing will change // Thus avoids creating unnecessary network traffic return; } BodyDistance = GetTarget()->GetPosition() - GetPosition(); } else { BodyDistance = m_NextWayPointPosition - GetPosition(); } double BodyRotation, BodyPitch; BodyDistance.Normalize(); VectorToEuler(BodyDistance.x, BodyDistance.y, BodyDistance.z, BodyRotation, BodyPitch); SetYaw(BodyRotation); Vector3d HeadDistance; if (GetTarget() != nullptr) { if (GetTarget()->IsPlayer()) // Look at a player { HeadDistance = GetTarget()->GetPosition() - GetPosition(); } else // Look at some other entity { HeadDistance = GetTarget()->GetPosition() - GetPosition(); // HeadDistance.y = GetTarget()->GetPosY() + GetHeight(); } } else // Look straight { HeadDistance = BodyDistance; HeadDistance.y = 0; } double HeadRotation, HeadPitch; HeadDistance.Normalize(); VectorToEuler(HeadDistance.x, HeadDistance.y, HeadDistance.z, HeadRotation, HeadPitch); if ((std::abs(BodyRotation - HeadRotation) < 70) && (std::abs(HeadPitch) < 60)) { SetHeadYaw(HeadRotation); SetPitch(-HeadPitch); } else { SetHeadYaw(BodyRotation); SetPitch(0); } } void cMonster::HandleFalling() { m_bTouchGround = IsOnGround(); Super::HandleFalling(); } int cMonster::FindFirstNonAirBlockPosition(double a_PosX, double a_PosZ) { auto Position = GetPosition().Floor(); Position.y = Clamp(Position.y, 0, cChunkDef::Height); if (!cBlockInfo::IsSolid(m_World->GetBlock(Position))) { while (!cBlockInfo::IsSolid(m_World->GetBlock(Position)) && (Position.y > 0)) { Position.y--; } return Position.y + 1; } else { while ((Position.y < cChunkDef::Height) && cBlockInfo::IsSolid(m_World->GetBlock(Position))) { Position.y++; } return Position.y; } } bool cMonster::DoTakeDamage(TakeDamageInfo & a_TDI) { if (!Super::DoTakeDamage(a_TDI)) { return false; } if (!m_SoundHurt.empty() && (m_Health > 0)) { m_World->BroadcastSoundEffect(m_SoundHurt, GetPosition(), 1.0f, 0.8f); } if ((a_TDI.Attacker != nullptr) && a_TDI.Attacker->IsPawn()) { if ( (!a_TDI.Attacker->IsPlayer()) || (static_cast(a_TDI.Attacker)->CanMobsTarget()) ) { SetTarget(static_cast(a_TDI.Attacker)); } m_TicksSinceLastDamaged = 0; } return true; } void cMonster::KilledBy(TakeDamageInfo & a_TDI) { Super::KilledBy(a_TDI); if (m_SoundHurt != "") { m_World->BroadcastSoundEffect(m_SoundDeath, GetPosition(), 1.0f, 0.8f); } if (IsTame()) { if ((m_MobType == mtWolf) || (m_MobType == mtOcelot) || (m_MobType == mtCat) || (m_MobType == mtParrot)) { BroadcastDeathMessage(a_TDI); } } int Reward; switch (m_MobType) { // Animals case mtChicken: case mtCow: case mtHorse: case mtPig: case mtRabbit: case mtSheep: case mtSquid: case mtMooshroom: case mtOcelot: case mtWolf: { Reward = GetRandomProvider().RandInt(1, 3); break; } // Monsters case mtCaveSpider: case mtCreeper: case mtEnderman: case mtGhast: case mtGuardian: case mtSilverfish: case mtSkeleton: case mtSpider: case mtWitch: case mtWitherSkeleton: case mtZombie: case mtZombiePigman: case mtZombieVillager: case mtSlime: case mtMagmaCube: { Reward = GetRandomProvider().RandInt(6, 8); break; } case mtEndermite: { Reward = 3; break; } case mtBlaze: { Reward = 10; break; } // Bosses case mtEnderDragon: { Reward = 12000; break; } case mtWither: { Reward = 50; break; } default: { Reward = 0; break; } } if ((a_TDI.Attacker != nullptr) && (!IsBaby())) { m_World->SpawnSplitExperienceOrbs(GetPosX(), GetPosY(), GetPosZ(), Reward); } m_DestroyTimer = std::chrono::milliseconds(0); } void cMonster::OnRightClicked(cPlayer & a_Player) { Super::OnRightClicked(a_Player); const cItem & EquippedItem = a_Player.GetEquippedItem(); if ((EquippedItem.m_ItemType == E_ITEM_NAME_TAG) && !EquippedItem.m_CustomName.empty()) { SetCustomName(EquippedItem.m_CustomName); if (!a_Player.IsGameModeCreative()) { a_Player.GetInventory().RemoveOneEquippedItem(); } } // Using leashes m_IsLeashActionJustDone = false; if (IsLeashed() && (GetLeashedTo() == &a_Player)) // a player can only unleash a mob leashed to him { Unleash(!a_Player.IsGameModeCreative()); } else if (IsLeashed()) { // Mob is already leashed but client anticipates the server action and draws a leash link, so we need to send current leash to cancel it m_World->BroadcastLeashEntity(*this, *this->GetLeashedTo()); } else if (CanBeLeashed() && (EquippedItem.m_ItemType == E_ITEM_LEASH)) { if (!a_Player.IsGameModeCreative()) { a_Player.GetInventory().RemoveOneEquippedItem(); } LeashTo(a_Player); } } // Checks to see if EventSeePlayer should be fired // monster sez: Do I see the player void cMonster::CheckEventSeePlayer(cChunk & a_Chunk) { if (GetTarget() != nullptr) { return; } cPlayer * TargetPlayer = nullptr; double ClosestDistance = m_SightDistance * m_SightDistance; const auto MyHeadPosition = GetPosition().addedY(GetHeight()); // Enumerate all players within sight: m_World->ForEachPlayer([this, &TargetPlayer, &ClosestDistance, MyHeadPosition](cPlayer & a_Player) { if (!a_Player.CanMobsTarget()) { return false; } const auto TargetHeadPosition = a_Player.GetPosition().addedY(a_Player.GetHeight()); const auto TargetDistance = (TargetHeadPosition - MyHeadPosition).SqrLength(); // TODO: Currently all mobs see through lava, but only Nether-native mobs should be able to. if ( (TargetDistance < ClosestDistance) && cLineBlockTracer::LineOfSightTrace(*GetWorld(), MyHeadPosition, TargetHeadPosition, cLineBlockTracer::losAirWaterLava) ) { TargetPlayer = &a_Player; ClosestDistance = TargetDistance; } return false; }); // Target him if suitable player found: if (TargetPlayer != nullptr) { EventSeePlayer(TargetPlayer, a_Chunk); } } void cMonster::CheckEventLostPlayer(const std::chrono::milliseconds a_Dt) { const auto Target = GetTarget(); if (Target == nullptr) { return; } // Check if the player died, is in creative mode, etc: if (Target->IsPlayer() && !static_cast(Target)->CanMobsTarget()) { EventLosePlayer(); return; } // Check if the target is too far away: if (!Target->GetBoundingBox().DoesIntersect({ GetPosition(), m_SightDistance * 2.0 })) { EventLosePlayer(); return; } const auto MyHeadPosition = GetPosition().addedY(GetHeight()); const auto TargetHeadPosition = Target->GetPosition().addedY(Target->GetHeight()); if (!cLineBlockTracer::LineOfSightTrace(*GetWorld(), MyHeadPosition, TargetHeadPosition, cLineBlockTracer::losAirWaterLava)) { if ((m_LoseSightAbandonTargetTimer += a_Dt) > std::chrono::seconds(4)) { EventLosePlayer(); } } else { // Subtract the amount of time we "handled" instead of setting to zero, so we don't ignore a large a_Dt of say, 8s: m_LoseSightAbandonTargetTimer -= std::min(std::chrono::milliseconds(4000), m_LoseSightAbandonTargetTimer); } } // What to do if player is seen // default to change state to chasing void cMonster::EventSeePlayer(cPlayer * a_SeenPlayer, cChunk & a_Chunk) { UNUSED(a_Chunk); SetTarget(a_SeenPlayer); } void cMonster::EventLosePlayer(void) { SetTarget(nullptr); m_EMState = IDLE; m_LoseSightAbandonTargetTimer = std::chrono::seconds::zero(); } void cMonster::InStateIdle(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { if (m_PathfinderActivated) { return; // Still getting there } m_IdleInterval += a_Dt; if (m_IdleInterval > std::chrono::seconds(1)) { auto & Random = GetRandomProvider(); // At this interval the results are predictable int rem = Random.RandInt(1, 7); m_IdleInterval -= std::chrono::seconds(1); // So nothing gets dropped when the server hangs for a few seconds Vector3d Dist; Dist.x = static_cast(Random.RandInt(-5, 5)); Dist.z = static_cast(Random.RandInt(-5, 5)); if ((Dist.SqrLength() > 2) && (rem >= 3)) { Vector3d Destination(GetPosX() + Dist.x, GetPosition().y, GetPosZ() + Dist.z); cChunk * Chunk = a_Chunk.GetNeighborChunk(static_cast(Destination.x), static_cast(Destination.z)); if ((Chunk == nullptr) || !Chunk->IsValid()) { return; } BLOCKTYPE BlockType; NIBBLETYPE BlockMeta; int RelX = static_cast(Destination.x) - Chunk->GetPosX() * cChunkDef::Width; int RelZ = static_cast(Destination.z) - Chunk->GetPosZ() * cChunkDef::Width; int YBelowUs = static_cast(Destination.y) - 1; if (YBelowUs >= 0) { Chunk->GetBlockTypeMeta(RelX, YBelowUs, RelZ, BlockType, BlockMeta); if (BlockType != E_BLOCK_STATIONARY_WATER) // Idle mobs shouldn't enter water on purpose { MoveToPosition(Destination); } } } } } // What to do if in Chasing State // This state should always be defined in each child class void cMonster::InStateChasing(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { UNUSED(a_Dt); } // What to do if in Escaping State void cMonster::InStateEscaping(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { UNUSED(a_Dt); if (GetTarget() != nullptr) { Vector3d newloc = GetPosition(); newloc.x = (GetTarget()->GetPosition().x < newloc.x)? (newloc.x + m_SightDistance): (newloc.x - m_SightDistance); newloc.z = (GetTarget()->GetPosition().z < newloc.z)? (newloc.z + m_SightDistance): (newloc.z - m_SightDistance); MoveToPosition(newloc); } else { m_EMState = IDLE; // This shouldnt be required but just to be safe } } void cMonster::ResetAttackCooldown() { m_AttackCoolDownTicksLeft = static_cast(TPS * m_AttackRate); // A second has 20 ticks, an attack rate of 1 means 1 hit every second } void cMonster::SetCustomName(const AString & a_CustomName) { m_CustomName = a_CustomName; // The maximal length is 64 if (a_CustomName.length() > 64) { m_CustomName = a_CustomName.substr(0, 64); } if (m_World != nullptr) { m_World->BroadcastEntityMetadata(*this); } } void cMonster::SetCustomNameAlwaysVisible(bool a_CustomNameAlwaysVisible) { m_CustomNameAlwaysVisible = a_CustomNameAlwaysVisible; if (m_World != nullptr) { m_World->BroadcastEntityMetadata(*this); } } void cMonster::GetMonsterConfig(const AString & a_Name) { cRoot::Get()->GetMonsterConfig()->AssignAttributes(this, a_Name); } bool cMonster::IsNetherNative(void) { return false; } bool cMonster::IsUndead(void) { return false; } AString cMonster::MobTypeToString(eMonsterType a_MobType) { // Mob types aren't sorted, so we need to search linearly: for (size_t i = 0; i < ARRAYCOUNT(g_MobTypeNames); i++) { if (g_MobTypeNames[i].m_Type == a_MobType) { return g_MobTypeNames[i].m_lcName; } } // Not found: return ""; } AString cMonster::MobTypeToVanillaName(eMonsterType a_MobType) { // Mob types aren't sorted, so we need to search linearly: for (size_t i = 0; i < ARRAYCOUNT(g_MobTypeNames); i++) { if (g_MobTypeNames[i].m_Type == a_MobType) { return g_MobTypeNames[i].m_VanillaName; } } // Not found: return ""; } AString cMonster::MobTypeToVanillaNBT(eMonsterType a_MobType) { // Mob types aren't sorted, so we need to search linearly: for (size_t i = 0; i < ARRAYCOUNT(g_MobTypeNames); i++) { if (g_MobTypeNames[i].m_Type == a_MobType) { return g_MobTypeNames[i].m_VanillaNameNBT; } } // Not found: return ""; } eMonsterType cMonster::StringToMobType(const AString & a_Name) { AString lcName = StrToLower(a_Name); // Search Cuberite name: for (size_t i = 0; i < ARRAYCOUNT(g_MobTypeNames); i++) { if (strcmp(g_MobTypeNames[i].m_lcName, lcName.c_str()) == 0) { return g_MobTypeNames[i].m_Type; } } // Not found. Search Vanilla name: for (size_t i = 0; i < ARRAYCOUNT(g_MobTypeNames); i++) { if (strcmp(StrToLower(g_MobTypeNames[i].m_VanillaName).c_str(), lcName.c_str()) == 0) { return g_MobTypeNames[i].m_Type; } } // Search in NBT name for (size_t i = 0; i < ARRAYCOUNT(g_MobTypeNames); i++) { if (strcmp(StrToLower(g_MobTypeNames[i].m_VanillaNameNBT).c_str(), lcName.c_str()) == 0) { return g_MobTypeNames[i].m_Type; } } // Not found: return mtInvalidType; } cMonster::eFamily cMonster::FamilyFromType(eMonsterType a_Type) { // Passive-agressive mobs are counted in mob spawning code as passive switch (a_Type) { case mtBat: return mfAmbient; case mtBlaze: return mfHostile; case mtCat: return mfPassive; case mtCaveSpider: return mfHostile; case mtChicken: return mfPassive; case mtCod: return mfWater; case mtCow: return mfPassive; case mtCreeper: return mfHostile; case mtDolphin: return mfWater; case mtDonkey: return mfPassive; case mtDrowned: return mfHostile; case mtElderGuardian: return mfHostile; case mtEnderDragon: return mfNoSpawn; case mtEnderman: return mfHostile; case mtEndermite: return mfHostile; case mtEvoker: return mfHostile; case mtFox: return mfPassive; case mtGhast: return mfHostile; case mtGiant: return mfNoSpawn; case mtGuardian: return mfWater; // Just because they have special spawning conditions. TODO: If Watertemples have been added, this needs to be edited! case mtHoglin: return mfHostile; case mtHorse: return mfPassive; case mtHusk: return mfHostile; case mtIllusioner: return mfHostile; case mtIronGolem: return mfPassive; case mtLlama: return mfPassive; case mtMagmaCube: return mfHostile; case mtMooshroom: return mfPassive; case mtMule: return mfPassive; case mtOcelot: return mfPassive; case mtPanda: return mfPassive; case mtParrot: return mfPassive; case mtPhantom: return mfHostile; case mtPig: return mfPassive; case mtPiglin: return mfHostile; case mtPiglinBrute: return mfHostile; case mtPillager: return mfHostile; case mtPolarBear: return mfPassive; case mtPufferfish: return mfWater; case mtRabbit: return mfPassive; case mtRavager: return mfHostile; case mtSalmon: return mfWater; case mtSheep: return mfPassive; case mtShulker: return mfHostile; case mtSilverfish: return mfHostile; case mtSkeleton: return mfHostile; case mtSkeletonHorse: return mfPassive; case mtSlime: return mfHostile; case mtSnowGolem: return mfNoSpawn; case mtSpider: return mfHostile; case mtSquid: return mfWater; case mtStray: return mfHostile; case mtStrider: return mfHostile; case mtTraderLlama: return mfPassive; case mtTropicalFish: return mfWater; case mtTurtle: return mfWater; // I'm not quite sure case mtVex: return mfHostile; case mtVindicator: return mfHostile; case mtVillager: return mfPassive; case mtWanderingTrader: return mfPassive; case mtWitch: return mfHostile; case mtWither: return mfNoSpawn; case mtWitherSkeleton: return mfHostile; case mtWolf: return mfPassive; case mtZoglin: return mfHostile; case mtZombie: return mfHostile; case mtZombieHorse: return mfPassive; case mtZombiePigman: return mfHostile; case mtZombieVillager: return mfHostile; case mtInvalidType: break; } UNREACHABLE("Unhandled mob type"); } cTickTime cMonster::GetSpawnDelay(cMonster::eFamily a_MobFamily) { switch (a_MobFamily) { case mfHostile: return 40_tick; case mfPassive: return 40_tick; case mfAmbient: return 40_tick; case mfWater: return 400_tick; case mfNoSpawn: return -1_tick; } UNREACHABLE("Unhandled mob family"); } /** Sets the target. */ void cMonster::SetTarget (cPawn * a_NewTarget) { ASSERT((a_NewTarget == nullptr) || (IsTicking())); if (m_Target == a_NewTarget) { return; } cPawn * OldTarget = m_Target; m_Target = a_NewTarget; if (OldTarget != nullptr) { // Notify the old target that we are no longer targeting it. OldTarget->NoLongerTargetingMe(this); } if (a_NewTarget != nullptr) { ASSERT(a_NewTarget->IsTicking()); // Notify the new target that we are now targeting it. m_Target->TargetingMe(this); m_WasLastTargetAPlayer = m_Target->IsPlayer(); } } void cMonster::UnsafeUnsetTarget() { m_Target = nullptr; } cPawn * cMonster::GetTarget() { return m_Target; } std::unique_ptr cMonster::NewMonsterFromType(eMonsterType a_MobType) { auto & Random = GetRandomProvider(); // Create the mob entity switch (a_MobType) { case mtMagmaCube: { return std::make_unique(1 << Random.RandInt(2)); // Size 1, 2 or 4 } case mtSlime: { return std::make_unique(1 << Random.RandInt(2)); // Size 1, 2 or 4 } case mtVillager: return std::make_unique(cVillager::GetRandomProfession()); case mtHorse: { // Horses take a type (species), a colour, and a style (dots, stripes, etc.) int HorseType = Random.RandInt(7); int HorseColor = Random.RandInt(6); int HorseStyle = Random.RandInt(4); int HorseTameTimes = Random.RandInt(1, 6); if ((HorseType == 5) || (HorseType == 6) || (HorseType == 7)) { // Increase chances of normal horse (zero) HorseType = 0; } return std::make_unique(HorseType, HorseColor, HorseStyle, HorseTameTimes); } case mtZombieVillager: { return std::make_unique(cVillager::GetRandomProfession()); } case mtBat: return std::make_unique(); case mtBlaze: return std::make_unique(); case mtCaveSpider: return std::make_unique(); case mtChicken: return std::make_unique(); case mtCow: return std::make_unique(); case mtCreeper: return std::make_unique(); case mtEnderDragon: return std::make_unique(); case mtEndermite: return std::make_unique(); case mtEnderman: return std::make_unique(); case mtGhast: return std::make_unique(); case mtGiant: return std::make_unique(); case mtGuardian: return std::make_unique(); case mtIronGolem: return std::make_unique(); case mtMooshroom: return std::make_unique(); case mtOcelot: return std::make_unique(); case mtPig: return std::make_unique(); case mtRabbit: return std::make_unique(); case mtSheep: return std::make_unique(); case mtSilverfish: return std::make_unique(); case mtSkeleton: return std::make_unique(); case mtSnowGolem: return std::make_unique(); case mtSpider: return std::make_unique(); case mtSquid: return std::make_unique(); case mtWitch: return std::make_unique(); case mtWither: return std::make_unique(); case mtWitherSkeleton: return std::make_unique(); case mtWolf: return std::make_unique(); case mtZombie: return std::make_unique(); case mtZombiePigman: return std::make_unique(); default: { ASSERT(!"Unhandled mob type whilst trying to spawn mob!"); return nullptr; } } } void cMonster::EngageLoveMode(cMonster *a_Partner) { m_LovePartner = a_Partner; m_MatingTimer = 50; // about 3 seconds of mating } void cMonster::ResetLoveMode() { m_LovePartner = nullptr; m_LoveTimer = 0; m_MatingTimer = 0; m_LoveCooldown = TPS * 60 * 5; // 5 minutes // when an animal is in love mode, the client only stops sending the hearts if we let them know it's in cooldown, which is done with the "age" metadata m_World->BroadcastEntityMetadata(*this); } void cMonster::LoveTick(void) { // if we have a partner, mate if (m_LovePartner != nullptr) { if (m_MatingTimer > 0) { // If we should still mate, keep bumping into them until baby is made Vector3d Pos = m_LovePartner->GetPosition(); MoveToPosition(Pos); } else { // Mating finished. Spawn baby Vector3f Pos = (GetPosition() + m_LovePartner->GetPosition()) * 0.5; UInt32 BabyID = m_World->SpawnMob(Pos.x, Pos.y, Pos.z, GetMobType(), true); cMonster * Baby = nullptr; m_World->DoWithEntityByID(BabyID, [&](cEntity & a_Entity) { Baby = static_cast(&a_Entity); return true; }); if (Baby != nullptr) { Baby->InheritFromParents(this, m_LovePartner); } m_World->SpawnExperienceOrb(Pos.x, Pos.y, Pos.z, GetRandomProvider().RandInt(1, 6)); m_World->DoWithPlayerByUUID(m_Feeder, [&] (cPlayer & a_Player) { a_Player.GetStatistics().Custom[CustomStatistic::AnimalsBred]++; if (GetMobType() == eMonsterType::mtCow) { a_Player.AwardAchievement(CustomStatistic::AchBreedCow); } return true; }); m_LovePartner->ResetLoveMode(); ResetLoveMode(); } } else { // We have no partner, so we just chase the player if they have our breeding item cItems FollowedItems; GetFollowedItems(FollowedItems); if (FollowedItems.Size() > 0) { m_World->DoWithNearestPlayer(GetPosition(), static_cast(m_SightDistance), [&](cPlayer & a_Player) -> bool { const cItem & EquippedItem = a_Player.GetEquippedItem(); if (FollowedItems.ContainsType(EquippedItem)) { Vector3d PlayerPos = a_Player.GetPosition(); MoveToPosition(PlayerPos); } return true; }); } } // If we are in love mode but we have no partner, search for a partner neabry if (m_LoveTimer > 0) { if (m_LovePartner == nullptr) { m_World->ForEachEntityInBox(cBoundingBox(GetPosition(), 8, 8), [=](cEntity & a_Entity) { // If the entity is not a monster, don't breed with it // Also, do not self-breed if ((a_Entity.GetEntityType() != etMonster) || (&a_Entity == this)) { return false; } auto & Me = static_cast(*this); auto & PotentialPartner = static_cast(a_Entity); // If the potential partner is not of the same species, don't breed with it if (PotentialPartner.GetMobType() != Me.GetMobType()) { return false; } // If the potential partner is not in love // Or they already have a mate, do not breed with them if ((!PotentialPartner.IsInLove()) || (PotentialPartner.GetPartner() != nullptr)) { return false; } // All conditions met, let's breed! PotentialPartner.EngageLoveMode(&Me); Me.EngageLoveMode(&PotentialPartner); return true; }); } m_LoveTimer--; } if (m_MatingTimer > 0) { m_MatingTimer--; } if (m_LoveCooldown > 0) { m_LoveCooldown--; } } void cMonster::RightClickFeed(cPlayer & a_Player) { const cItem & EquippedItem = a_Player.GetEquippedItem(); // If a player holding breeding items right-clicked me, go into love mode if ((m_LoveCooldown == 0) && !IsInLove() && !IsBaby()) { cItems Items; GetBreedingItems(Items); if (Items.ContainsType(EquippedItem.m_ItemType)) { if (!a_Player.IsGameModeCreative()) { a_Player.GetInventory().RemoveOneEquippedItem(); } m_LoveTimer = TPS * 30; // half a minute m_World->BroadcastEntityAnimation(*this, EntityAnimation::AnimalFallsInLove); } } // If a player holding my spawn egg right-clicked me, spawn a new baby if (EquippedItem.m_ItemType == E_ITEM_SPAWN_EGG) { eMonsterType MonsterType = cItemSpawnEggHandler::ItemDamageToMonsterType(EquippedItem.m_ItemDamage); if ( (MonsterType == m_MobType) && (m_World->SpawnMob(GetPosX(), GetPosY(), GetPosZ(), m_MobType, true) != cEntity::INVALID_ID) // Spawning succeeded ) { if (!a_Player.IsGameModeCreative()) { // The mob was spawned, "use" the item: a_Player.GetInventory().RemoveOneEquippedItem(); } } } // Stores feeder UUID for statistic tracking m_Feeder = a_Player.GetUUID(); } void cMonster::AddRandomDropItem(cItems & a_Drops, unsigned int a_Min, unsigned int a_Max, short a_Item, short a_ItemHealth) { auto Count = GetRandomProvider().RandInt(a_Min, a_Max); auto MaxStackSize = static_cast(cItem(a_Item).GetMaxStackSize()); while (Count > MaxStackSize) { a_Drops.emplace_back(a_Item, MaxStackSize, a_ItemHealth); Count -= MaxStackSize; } if (Count > 0) { a_Drops.emplace_back(a_Item, Count, a_ItemHealth); } } void cMonster::AddRandomUncommonDropItem(cItems & a_Drops, float a_Chance, short a_Item, short a_ItemHealth) { if (GetRandomProvider().RandBool(a_Chance / 100.0)) { a_Drops.emplace_back(a_Item, static_cast(1), a_ItemHealth); } } void cMonster::AddRandomRareDropItem(cItems & a_Drops, cItems & a_Items, unsigned int a_LootingLevel) { auto & r1 = GetRandomProvider(); if (r1.RandBool((5 + a_LootingLevel) / 200.0)) { size_t Rare = r1.RandInt(a_Items.Size() - 1); a_Drops.push_back(a_Items.at(Rare)); } } void cMonster::AddRandomArmorDropItem(cItems & a_Drops, unsigned int a_LootingLevel) { auto & r1 = GetRandomProvider(); double LootingBonus = a_LootingLevel / 100.0; if (r1.RandBool(m_DropChanceHelmet + LootingBonus)) { if (!GetEquippedHelmet().IsEmpty()) { a_Drops.push_back(GetEquippedHelmet()); } } if (r1.RandBool(m_DropChanceChestplate + LootingBonus)) { if (!GetEquippedChestplate().IsEmpty()) { a_Drops.push_back(GetEquippedChestplate()); } } if (r1.RandBool(m_DropChanceLeggings + LootingBonus)) { if (!GetEquippedLeggings().IsEmpty()) { a_Drops.push_back(GetEquippedLeggings()); } } if (r1.RandBool(m_DropChanceBoots + LootingBonus)) { if (!GetEquippedBoots().IsEmpty()) { a_Drops.push_back(GetEquippedBoots()); } } } void cMonster::AddRandomWeaponDropItem(cItems & a_Drops, unsigned int a_LootingLevel) { if (GetRandomProvider().RandBool(m_DropChanceWeapon + (a_LootingLevel / 100.0))) { if (!GetEquippedWeapon().IsEmpty()) { a_Drops.push_back(GetEquippedWeapon()); } } } void cMonster::HandleDaylightBurning(cChunk & a_Chunk, bool WouldBurn) { if (!m_BurnsInDaylight) { return; } int RelY = POSY_TOINT; if ((RelY < 0) || (RelY >= cChunkDef::Height)) { // Outside the world return; } if (!a_Chunk.IsLightValid()) { m_World->QueueLightChunk(GetChunkX(), GetChunkZ()); return; } if (!IsOnFire() && WouldBurn) { // Burn for 100 ticks, then decide again StartBurning(100); } } bool cMonster::WouldBurnAt(Vector3d a_Location, cChunk & a_Chunk) { // If the Y coord is out of range, return the most logical result without considering anything else: int RelY = FloorC(a_Location.y); if (RelY >= cChunkDef::Height) { // Always burn above the world return true; } if (RelY <= 0) { // The mob is about to die, no point in burning return false; } PREPARE_REL_AND_CHUNK(a_Location, a_Chunk); if (!RelSuccess) { return false; } if ( (Chunk->GetBlock(Rel) != E_BLOCK_SOULSAND) && // Not on soulsand (GetWorld()->GetTimeOfDay() < 13000_tick) && // Daytime Chunk->IsWeatherSunnyAt(Rel.x, Rel.z) && // Not raining !IsInWater() // Isn't swimming ) { int MobHeight = CeilC(a_Location.y + GetHeight()) - 1; // The block Y coord of the mob's head if (MobHeight >= cChunkDef::Height) { return true; } // Start with the highest block and scan down to just above the mob's head. // If a non transparent is found, return false (do not burn). Otherwise return true. // Note that this loop is not a performance concern as transparent blocks are rare and the loop almost always bailes out // instantly.(An exception is e.g. standing under a long column of glass). int CurrentBlock = Chunk->GetHeight(Rel.x, Rel.z); while (CurrentBlock > MobHeight) { BLOCKTYPE Block = Chunk->GetBlock(Rel.x, CurrentBlock, Rel.z); if ( // Do not burn if a block above us meets one of the following conditions: (!cBlockInfo::IsTransparent(Block)) || (Block == E_BLOCK_LEAVES) || (Block == E_BLOCK_NEW_LEAVES) || (IsBlockWater(Block)) ) { return false; } --CurrentBlock; } return true; } return false; } cMonster::eFamily cMonster::GetMobFamily(void) const { return FamilyFromType(m_MobType); } void cMonster::LeashTo(cEntity & a_Entity, bool a_ShouldBroadcast) { // Do nothing if already leashed if (m_LeashedTo != nullptr) { return; } m_LeashedTo = &a_Entity; a_Entity.AddLeashedMob(this); if (a_ShouldBroadcast) { m_World->BroadcastLeashEntity(*this, a_Entity); } m_IsLeashActionJustDone = true; } void cMonster::Unleash(bool a_ShouldDropLeashPickup, bool a_ShouldBroadcast) { // Do nothing if not leashed if (m_LeashedTo == nullptr) { return; } m_LeashedTo->RemoveLeashedMob(this); m_LeashedTo = nullptr; if (a_ShouldDropLeashPickup) { cItems Pickups; Pickups.Add(cItem(E_ITEM_LEASH, 1, 0)); GetWorld()->SpawnItemPickups(Pickups, GetPosX() + 0.5, GetPosY() + 0.5, GetPosZ() + 0.5); } if (a_ShouldBroadcast) { m_World->BroadcastUnleashEntity(*this); } m_IsLeashActionJustDone = true; } void cMonster::Unleash(bool a_ShouldDropLeashPickup) { Unleash(a_ShouldDropLeashPickup, true); } ================================================ FILE: src/Mobs/Monster.h ================================================ #pragma once #include "../Entities/Pawn.h" #include "../UUID.h" #include "MonsterTypes.h" #include "PathFinder.h" class cItem; class cClientHandle; // tolua_begin class cMonster: public cPawn { // tolua_end using Super = cPawn; // tolua_begin public: enum eFamily { mfHostile = 0, // Spider, Zombies ... mfPassive = 1, // Cows, Pigs mfAmbient = 2, // Bats mfWater = 3, // Squid, Guardian mfNoSpawn } ; // tolua_end enum MState{ATTACKING, IDLE, CHASING, ESCAPING} m_EMState; enum MPersonality{PASSIVE, AGGRESSIVE, COWARDLY} m_EMPersonality; /** Creates the mob object. If a_ConfigName is not empty, the configuration is loaded using GetMonsterConfig() a_MobType is the type of the mob (also used in the protocol ( http://wiki.vg/Entities#Mobs 2012_12_22)) a_SoundHurt and a_SoundDeath are assigned into m_SoundHurt and m_SoundDeath, respectively */ cMonster(const AString & a_ConfigName, eMonsterType a_MobType, const AString & a_SoundHurt, const AString & a_SoundDeath, const AString & a_SoundAmbient, float a_Width, float a_Height); CLASS_PROTODEF(cMonster) virtual void OnRemoveFromWorld(cWorld & a_World) override; virtual void SpawnOn(cClientHandle & a_ClientHandle) override; virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; virtual bool DoTakeDamage(TakeDamageInfo & a_TDI) override; virtual void KilledBy(TakeDamageInfo & a_TDI) override; virtual void OnRightClicked(cPlayer & a_Player) override; virtual void HandleFalling(void) override; /** Engage pathfinder and tell it to calculate a path to a given position, and move the mob accordingly. */ virtual void MoveToPosition(const Vector3d & a_Position); // tolua_export // tolua_begin eMonsterType GetMobType(void) const { return m_MobType; } eFamily GetMobFamily(void) const; // tolua_end virtual void CheckEventSeePlayer(cChunk & a_Chunk); virtual void EventSeePlayer(cPlayer * a_Player, cChunk & a_Chunk); // tolua_begin /** Returns whether the mob can be leashed. */ bool CanBeLeashed() const { return m_CanBeLeashed; } /** Sets whether the mob can be leashed, for extensibility in plugins */ void SetCanBeLeashed(bool a_CanBeLeashed) { m_CanBeLeashed = a_CanBeLeashed; } /** Returns whether the monster is leashed to an entity. */ bool IsLeashed() const { return (m_LeashedTo != nullptr); } /** Leash the monster to an entity. */ void LeashTo(cEntity & a_Entity, bool a_ShouldBroadcast = true); /** Unleash the monster. Overload for the Unleash(bool, bool) function for plugins */ void Unleash(bool a_ShouldDropLeashPickup); /** Returns the entity to where this mob is leashed, returns nullptr if it's not leashed */ cEntity * GetLeashedTo() const { return m_LeashedTo; } // tolua_end /** Unleash the monster. */ void Unleash(bool a_ShouldDropLeashPickup, bool a_ShouldBroadcast); /** Sets entity position to where is leashed this mob */ void SetLeashToPos(Vector3d * pos) { m_LeashToPos = std::unique_ptr(pos); } /** Gets entity position to where mob should be leashed */ Vector3d * GetLeashToPos() const { return m_LeashToPos.get(); } /** Reads the monster configuration for the specified monster name and assigns it to this object. */ void GetMonsterConfig(const AString & a_Name); /** Returns whether this mob spawns in the Nether in Vanilla. This is a fixed value and is not affected by custom mob spawning settings. */ virtual bool IsNetherNative(void); /** Returns whether this mob is undead (skeleton, zombie, etc.) */ virtual bool IsUndead(void); virtual void EventLosePlayer(void); virtual void CheckEventLostPlayer(std::chrono::milliseconds a_Dt); virtual void InStateIdle (std::chrono::milliseconds a_Dt, cChunk & a_Chunk); virtual void InStateChasing (std::chrono::milliseconds a_Dt, cChunk & a_Chunk); virtual void InStateEscaping(std::chrono::milliseconds a_Dt, cChunk & a_Chunk); double GetAttackRate() { return m_AttackRate; } void SetAttackRate(double a_AttackRate) { m_AttackRate = a_AttackRate; } void SetAttackRange(double a_AttackRange) { m_AttackRange = a_AttackRange; } void SetAttackDamage(int a_AttackDamage) { m_AttackDamage = a_AttackDamage; } void SetSightDistance(int a_SightDistance) { m_SightDistance = a_SightDistance; } float GetDropChanceWeapon() { return m_DropChanceWeapon; } float GetDropChanceHelmet() { return m_DropChanceHelmet; } float GetDropChanceChestplate() { return m_DropChanceChestplate; } float GetDropChanceLeggings() { return m_DropChanceLeggings; } float GetDropChanceBoots() { return m_DropChanceBoots; } bool CanPickUpLoot() { return m_CanPickUpLoot; } void SetDropChanceWeapon(float a_DropChanceWeapon) { m_DropChanceWeapon = a_DropChanceWeapon; } void SetDropChanceHelmet(float a_DropChanceHelmet) { m_DropChanceHelmet = a_DropChanceHelmet; } void SetDropChanceChestplate(float a_DropChanceChestplate) { m_DropChanceChestplate = a_DropChanceChestplate; } void SetDropChanceLeggings(float a_DropChanceLeggings) { m_DropChanceLeggings = a_DropChanceLeggings; } void SetDropChanceBoots(float a_DropChanceBoots) { m_DropChanceBoots = a_DropChanceBoots; } void SetCanPickUpLoot(bool a_CanPickUpLoot) { m_CanPickUpLoot = a_CanPickUpLoot; } void ResetAttackCooldown(); void SetBurnsInDaylight(bool a_BurnsInDaylight) { m_BurnsInDaylight = a_BurnsInDaylight; } // tolua_export bool BurnsInDaylight() const { return m_BurnsInDaylight; } // tolua_export double GetRelativeWalkSpeed(void) const { return m_RelativeWalkSpeed; } // tolua_export void SetRelativeWalkSpeed(double a_Speed) { m_RelativeWalkSpeed = a_Speed; } // tolua_export void SetBaseWalkSpeed(double a_Speed) { m_BaseWalkSpeed = a_Speed; } void SetBaseRunSpeed(double a_Speed) { m_BaseRunSpeed = a_Speed; } // Overridables to handle ageable mobs virtual bool IsTame (void) const { return false; } virtual bool IsSitting (void) const { return false; } // tolua_begin bool IsBaby (void) const { return m_Age < 0; } int GetAge (void) const { return m_Age; } void SetAge(int a_Age) { m_Age = a_Age; } // tolua_end // tolua_begin /** Returns true if the monster has a custom name. */ bool HasCustomName(void) const { return !m_CustomName.empty(); } /** Gets the custom name of the monster. If no custom name is set, the function returns an empty string. */ const AString & GetCustomName(void) const { return m_CustomName; } /** Sets the custom name of the monster. You see the name over the monster. If you want to disable the custom name, simply set an empty string. */ void SetCustomName(const AString & a_CustomName); /** Is the custom name of this monster always visible? If not, you only see the name when you sight the mob. */ bool IsCustomNameAlwaysVisible(void) const { return m_CustomNameAlwaysVisible; } /** Sets the custom name visiblity of this monster. If it's false, you only see the name when you sight the mob. If it's true, you always see the custom name. */ void SetCustomNameAlwaysVisible(bool a_CustomNameAlwaysVisible); /** Translates MobType enum to a string, empty string if unknown */ static AString MobTypeToString(eMonsterType a_MobType); /** Translates MobType enum to the vanilla name of the mob, empty string if unknown. */ static AString MobTypeToVanillaName(eMonsterType a_MobType); /** Translates MobType string to the enum, mtInvalidType if not recognized */ static eMonsterType StringToMobType(const AString & a_MobTypeName); /** Returns the mob family based on the type */ static eFamily FamilyFromType(eMonsterType a_MobType); // tolua_end /** Returns the spawn delay (number of game ticks between spawn attempts) for the given mob family */ static cTickTime GetSpawnDelay(cMonster::eFamily a_MobFamily); /** Translates the MobType enum to the vanilla nbt name */ static AString MobTypeToVanillaNBT(eMonsterType a_MobType); /** Sets the target that this mob will chase. Pass a nullptr to unset. */ void SetTarget (cPawn * a_NewTarget); /** Unset the target without notifying the target entity. Do not use this, use SetTarget(nullptr) instead. This is only used by cPawn internally. */ void UnsafeUnsetTarget(); /** Returns the current target. */ cPawn * GetTarget(); /** Creates a new object of the specified mob. a_MobType is the type of the mob to be created Asserts and returns null if mob type is not specified */ static std::unique_ptr NewMonsterFromType(eMonsterType a_MobType); /** Returns if this mob last target was a player to avoid destruction on player quit */ bool WasLastTargetAPlayer() const { return m_WasLastTargetAPlayer; } /* the breeding processing */ /** Returns the items that the animal of this class follows when a player holds it in hand. */ virtual void GetFollowedItems(cItems & a_Items) { } /** Returns the items that make the animal breed - this is usually the same as the ones that make the animal follow, but not necessarily. */ virtual void GetBreedingItems(cItems & a_Items) { GetFollowedItems(a_Items); } /** Called after the baby is born, allows the baby to inherit the parents' properties (color, etc.) */ virtual void InheritFromParents(cMonster * a_Parent1, cMonster * a_Parent2) { } /** Returns the partner which the monster is currently mating with. */ cMonster * GetPartner(void) const { return m_LovePartner; } /** Start the mating process. Causes the monster to keep bumping into the partner until m_MatingTimer reaches zero. */ void EngageLoveMode(cMonster * a_Partner); /** Finish the mating process. Called after a baby is born. Resets all breeding related timers and sets m_LoveCooldown to 20 minutes. */ void ResetLoveMode(); /** Returns whether the monster has just been fed and is ready to mate. If this is "true" and GetPartner isn't "nullptr", then the monster is mating. */ bool IsInLove() const { return (m_LoveTimer > 0); } /** Returns whether the monster is tired of breeding and is in the cooldown state. */ bool IsInLoveCooldown() const { return (m_LoveCooldown > 0); } /** Does the whole love and breeding processing */ void LoveTick(void); /** Right click call to process feeding */ void RightClickFeed(cPlayer & a_Player); protected: /** The pathfinder instance handles pathfinding for this monster. */ cPathFinder m_PathFinder; /** Stores if pathfinder is being used - set when final destination is set, and unset when stopped moving to final destination */ bool m_PathfinderActivated; /** Coordinates of the next position that should be reached */ Vector3d m_NextWayPointPosition; /** Coordinates for the ultimate, final destination. */ Vector3d m_FinalDestination; /** Finds the lowest non-air block position (not the highest, as cWorld::GetHeight does) If current Y is nonsolid, goes down to try to find a solid block, then returns that + 1 If current Y is solid, goes up to find first nonsolid block, and returns that. If no suitable position is found, returns cChunkDef::Height. */ int FindFirstNonAirBlockPosition(double a_PosX, double a_PosZ); /** Returns if the ultimate, final destination has been reached. */ bool ReachedFinalDestination(void) { return ((m_FinalDestination - GetPosition()).SqrLength() < WAYPOINT_RADIUS * WAYPOINT_RADIUS); } /** Returns whether or not the target is close enough for attack. */ bool TargetIsInRange(void) { ASSERT(GetTarget() != nullptr); return ((GetTarget()->GetPosition() - GetPosition()).SqrLength() < (m_AttackRange * m_AttackRange)); } /** Returns whether the monster needs to jump to reach a given height. */ inline bool DoesPosYRequireJump(double a_PosY) { return (a_PosY > GetPosY() + 0.8); // Assume that differences up to 0.8 blocks can be walked instead of jumped } /** Move in a straight line to the next waypoint in the path, will jump if needed. */ void MoveToWayPoint(cChunk & a_Chunk); /** Stops pathfinding. Calls ResetPathFinding and sets m_IsFollowingPath to false */ void StopMovingToPosition(); /** Sets the body yaw and head yaw */ void SetPitchAndYawFromDestination(bool a_IsFollowingPath); int m_JumpCoolDown; std::chrono::milliseconds m_IdleInterval; std::chrono::milliseconds m_DestroyTimer; eMonsterType m_MobType; AString m_CustomName; bool m_CustomNameAlwaysVisible; AString m_SoundHurt; AString m_SoundDeath; AString m_SoundAmbient; double m_AttackRate; int m_AttackDamage; double m_AttackRange; int m_AttackCoolDownTicksLeft; int m_SightDistance; std::chrono::milliseconds m_LoseSightAbandonTargetTimer; float m_DropChanceWeapon; float m_DropChanceHelmet; float m_DropChanceChestplate; float m_DropChanceLeggings; float m_DropChanceBoots; bool m_CanPickUpLoot; int m_TicksSinceLastDamaged; // How many ticks ago we were last damaged by a player? void HandleDaylightBurning(cChunk & a_Chunk, bool WouldBurn); bool WouldBurnAt(Vector3d a_Location, cChunk & a_Chunk); bool m_BurnsInDaylight; double m_RelativeWalkSpeed; double m_BaseWalkSpeed; double m_BaseRunSpeed; int m_AmbientSoundTimer; int m_Age; int m_AgingTimer; bool m_WasLastTargetAPlayer; /** Entity leashed to */ cEntity * m_LeashedTo; /** Entity pos where this mob was leashed to. Used when deserializing the chunk in order to make the mob find the leash knot. */ std::unique_ptr m_LeashToPos; /** Mob has ben leashed or unleashed in current player action. Avoids double actions on horses. */ bool m_IsLeashActionJustDone; /** Determines whether a monster can be leashed */ bool m_CanBeLeashed; /** Adds a random number of a_Item between a_Min and a_Max to itemdrops a_Drops */ void AddRandomDropItem(cItems & a_Drops, unsigned int a_Min, unsigned int a_Max, short a_Item, short a_ItemHealth = 0); /** Adds a item a_Item with the chance of a_Chance (in percent) to itemdrops a_Drops */ void AddRandomUncommonDropItem(cItems & a_Drops, float a_Chance, short a_Item, short a_ItemHealth = 0); /** Adds one rare item out of the list of rare items a_Items modified by the looting level a_LootingLevel(I-III or custom) to the itemdrop a_Drops */ void AddRandomRareDropItem(cItems & a_Drops, cItems & a_Items, unsigned int a_LootingLevel); /** Adds armor that is equipped with the chance saved in m_DropChance[...] (this will be greter than 1 if picked up or 0.085 + (0.01 per LootingLevel) if born with) to the drop */ void AddRandomArmorDropItem(cItems & a_Drops, unsigned int a_LootingLevel); /** Adds weapon that is equipped with the chance saved in m_DropChance[...] (this will be greter than 1 if picked up or 0.085 + (0.01 per LootingLevel) if born with) to the drop */ void AddRandomWeaponDropItem(cItems & a_Drops, unsigned int a_LootingLevel); /* The breeding processing */ /** The monster's breeding partner. */ cMonster * m_LovePartner; /** Remembers the player is was last fed by for statistics tracking */ cUUID m_Feeder; /** If above 0, the monster is in love mode, and will breed if a nearby monster is also in love mode. Decrements by 1 per tick till reaching zero. */ int m_LoveTimer; /** If above 0, the monster is in cooldown mode and will refuse to breed. Decrements by 1 per tick till reaching zero. */ int m_LoveCooldown; /** The monster is engaged in mating, once this reaches zero, a baby will be born. Decrements by 1 per tick till reaching zero, then a baby is made and ResetLoveMode() is called. */ int m_MatingTimer; private: /** A pointer to the entity this mobile is aiming to reach. The validity of this pointer SHALL be guaranteed by the pointee; it MUST be reset when the pointee changes worlds or is destroyed. */ cPawn * m_Target; /** Leash calculations inside Tick function */ void CalcLeashActions(std::chrono::milliseconds a_Dt); } ; // tolua_export ================================================ FILE: src/Mobs/MonsterTypes.h ================================================ #pragma once // tolua_begin /** Identifies individual monster type. */ enum eMonsterType { mtInvalidType = -1, mtBat, mtBlaze, mtCat, // Added in 1.14 mtCaveSpider, mtChicken, mtCod, // Added in 1.13 mtCow, mtCreeper, mtDolphin, // Added in 1.13 mtDonkey, // Added in 1.6 mtDrowned, // Added in 1.13 mtElderGuardian, // Added in 1.13 mtEnderDragon, mtEnderman, mtEndermite, // Added in 1.8 mtEvoker, // Added in 1.11 mtFox, // Added in 1.14 mtGhast, mtGiant, mtGuardian, mtHorse, mtHoglin, // Added in 1.16 mtHusk, // Added in 1.10 mtIllusioner, // Added in 1.12 mtIronGolem, mtLlama, // Added in 1.11 mtMagmaCube, mtMooshroom, mtMule, // Added in 1.6 mtOcelot, mtPanda, // Added in 1.14 mtParrot, // Added in 1.12 mtPhantom, // Added in 1.13 mtPig, mtPiglin, // Added in 1.16 mtPiglinBrute, // Added in 1.16 mtPillager, // Added in 1.14 mtPolarBear, // Added in 1.10 mtPufferfish, // Added in 1.13 mtRabbit, mtRavager, // Added in 1.14 mtSalmon, // Added in 1.13 mtSheep, mtShulker, // Added in 1.9 mtSilverfish, mtSkeleton, mtSkeletonHorse, mtSlime, mtSnowGolem, mtSpider, mtSquid, mtStray, // Added in 1.10 mtStrider, // Added in 1.16 mtTraderLlama, // Added in 1.11 mtTropicalFish, // Added in 1.13 mtTurtle, // Added in 1.13 mtVex, // Added in 1.11 mtVillager, mtVindicator, // Added in 1.11 mtWanderingTrader, // Added in 1.14 mtWitch, mtWither, mtWitherSkeleton, mtWolf, mtZoglin, // Added in 1.16 mtZombie, mtZombieHorse, // Added in 1.6 mtZombifiedPiglin, mtZombieVillager, // Synonyms: mtZombiePigman = mtZombifiedPiglin, } ; // tolua_end ================================================ FILE: src/Mobs/Mooshroom.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "Mooshroom.h" #include "../Entities/Player.h" cMooshroom::cMooshroom(void) : Super("Mooshroom", mtMooshroom, "entity.cow.hurt", "entity.cow.death", "entity.cow.ambient", 0.9f, 1.4f) { } void cMooshroom::GetDrops(cItems & a_Drops, cEntity * a_Killer) { if (IsBaby()) { return; // Babies don't drop items } unsigned int LootingLevel = 0; if (a_Killer != nullptr) { LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting); } AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_LEATHER); AddRandomDropItem(a_Drops, 1, 3 + LootingLevel, IsOnFire() ? E_ITEM_STEAK : E_ITEM_RAW_BEEF); } void cMooshroom::OnRightClicked(cPlayer & a_Player) { switch (a_Player.GetEquippedItem().m_ItemType) { case E_ITEM_BUCKET: { // Milk the cow. if (!a_Player.IsGameModeCreative()) { a_Player.ReplaceOneEquippedItemTossRest(cItem(E_ITEM_MILK)); } } break; case E_ITEM_BOWL: { // Soup the cow. if (!a_Player.IsGameModeCreative()) { a_Player.ReplaceOneEquippedItemTossRest(cItem(E_ITEM_MUSHROOM_SOUP)); } } break; case E_ITEM_SHEARS: { if (!a_Player.IsGameModeCreative()) { a_Player.UseEquippedItem(); } cItems Drops; Drops.emplace_back(E_BLOCK_RED_MUSHROOM, static_cast(5), static_cast(0)); m_World->SpawnItemPickups(Drops, GetPosX(), GetPosY(), GetPosZ(), 10); m_World->SpawnMob(GetPosX(), GetPosY(), GetPosZ(), mtCow, false); Destroy(); } break; } } ================================================ FILE: src/Mobs/Mooshroom.h ================================================ #pragma once #include "PassiveMonster.h" class cMooshroom: public cPassiveMonster { using Super = cPassiveMonster; public: cMooshroom(); CLASS_PROTODEF(cMooshroom) virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override; virtual void OnRightClicked(cPlayer & a_Player) override; virtual void GetFollowedItems(cItems & a_Items) override { a_Items.Add(E_ITEM_WHEAT); } } ; ================================================ FILE: src/Mobs/Ocelot.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "Ocelot.h" #include "../World.h" #include "../Entities/Player.h" #include "../Items/ItemHandler.h" #include "../BoundingBox.h" // TODO: Ocelots should have a chance of spawning with two kittens /* if (!IsBaby() && GetRandomProvider().RandBool(1.0 / 7.0)) { m_World->SpawnMob(GetPosX(), GetPosY(), GetPosZ(), m_MobType, true); m_World->SpawnMob(GetPosX(), GetPosY(), GetPosZ(), m_MobType, true); } */ cOcelot::cOcelot(void) : Super("Ocelot", mtOcelot, "entity.cat.hurt", "entity.cat.death", "entity.cat.ambient", 0.6f, 0.7f), m_IsSitting(false), m_IsTame(false), m_IsBegging(false), m_CatType(ctWildOcelot), m_CheckPlayerTickCount(), m_OwnerName() { } void cOcelot::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { Super::Tick(a_Dt, a_Chunk); if (!IsTicking()) { // The base class tick destroyed us return; } if (!IsTame() && !IsBaby()) { if (m_CheckPlayerTickCount == 23) { m_World->DoWithNearestPlayer(GetPosition(), 10, [&](cPlayer & a_Player) -> bool { cItems Items; GetBreedingItems(Items); if (Items.ContainsType(a_Player.GetEquippedItem().m_ItemType)) { if (!IsBegging()) { SetIsBegging(true); m_World->BroadcastEntityMetadata(*this); } MoveToPosition(a_Player.GetPosition()); } else { if (IsBegging()) { SetIsBegging(false); m_World->BroadcastEntityMetadata(*this); } } return true; }, true); m_CheckPlayerTickCount = 0; } else { m_CheckPlayerTickCount++; } } if (IsTame() && !IsSitting()) { TickFollowPlayer(); } else if (IsSitting()) { StopMovingToPosition(); } m_World->BroadcastEntityMetadata(*this); } void cOcelot::TickFollowPlayer() { Vector3d OwnerPos; bool OwnerFlying = false; auto Callback = [&](cPlayer & a_Player) { OwnerPos = a_Player.GetPosition(); OwnerFlying = a_Player.IsFlying(); return true; }; if (m_World->DoWithPlayerByUUID(m_OwnerUUID, Callback)) { // The player is present in the world, follow him: double Distance = (OwnerPos - GetPosition()).Length(); if (Distance > 12) { if (!OwnerFlying) { OwnerPos.y = FindFirstNonAirBlockPosition(OwnerPos.x, OwnerPos.z); TeleportToCoords(OwnerPos.x, OwnerPos.y, OwnerPos.z); } } if (Distance < 2) { StopMovingToPosition(); } else { if (!OwnerFlying) { MoveToPosition(OwnerPos); } } } } void cOcelot::OnRightClicked(cPlayer & a_Player) { if (!IsTame()) { if ( IsBegging() && ((a_Player.GetPosition() - GetPosition()).Length() <= 3) ) { cItems Items; GetBreedingItems(Items); if (Items.ContainsType(a_Player.GetEquippedItem().m_ItemType)) { if (!a_Player.IsGameModeCreative()) { a_Player.GetInventory().RemoveOneEquippedItem(); } auto & Random = GetRandomProvider(); if (Random.RandBool(1.0 / 3.0)) { // Taming succeeded SetIsBegging(false); SetMaxHealth(20); SetIsTame(true); SetOwner(a_Player.GetName(), a_Player.GetUUID()); SetCatType(static_cast(Random.RandInt(1, 3))); m_World->BroadcastEntityAnimation(*this, EntityAnimation::OcelotTrusts); } else { // Taming failed m_World->BroadcastEntityAnimation(*this, EntityAnimation::OcelotDistrusts); } } } else { Super::OnRightClicked(a_Player); } } else if (a_Player.GetUUID() == m_OwnerUUID) { Super::OnRightClicked(a_Player); SetIsSitting(!IsSitting()); } m_World->BroadcastEntityMetadata(*this); } bool cOcelot::IsCatSittingOnBlock(cWorld * a_World, Vector3d a_BlockPosition) { return a_World->ForEachEntityInBox( cBoundingBox(Vector3d(a_BlockPosition.x, a_BlockPosition.y + 1, a_BlockPosition.z), 1), [=](cEntity & a_Entity) { return ( (a_Entity.GetEntityType() == cEntity::etMonster) && (static_cast(a_Entity).GetMobType() == eMonsterType::mtOcelot) && (static_cast(a_Entity).IsSitting()) ); } ); } bool cOcelot::DoTakeDamage(TakeDamageInfo & a_TDI) { if (a_TDI.DamageType == dtFalling) { return false; } return Super::DoTakeDamage(a_TDI); } ================================================ FILE: src/Mobs/Ocelot.h ================================================ #pragma once #include "PassiveMonster.h" #include "../UUID.h" class cOcelot: public cPassiveMonster { using Super = cPassiveMonster; public: enum eCatType { ctWildOcelot, ctTuxedo, ctTabby, ctSiamese, } ; cOcelot(void); CLASS_PROTODEF(cOcelot) virtual void OnRightClicked(cPlayer & a_Player) override; virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; virtual void TickFollowPlayer(); virtual void GetBreedingItems(cItems & a_Items) override { a_Items.Add(E_ITEM_RAW_FISH); } virtual bool DoTakeDamage(TakeDamageInfo & a_TDI) override; // Get functions bool IsSitting (void) const override { return m_IsSitting; } bool IsTame (void) const override { return m_IsTame; } bool IsBegging (void) const { return m_IsBegging; } AString GetOwnerName (void) const { return m_OwnerName; } cUUID GetOwnerUUID (void) const { return m_OwnerUUID; } eCatType GetOcelotType (void) const { return m_CatType; } // Set functions void SetIsSitting (bool a_IsSitting) { m_IsSitting = a_IsSitting; } void SetIsTame (bool a_IsTame) { m_IsTame = a_IsTame; } void SetIsBegging (bool a_IsBegging) { m_IsBegging = a_IsBegging; } void SetOwner (const AString & a_NewOwnerName, const cUUID & a_NewOwnerUUID) { m_OwnerName = a_NewOwnerName; m_OwnerUUID = a_NewOwnerUUID; } void SetCatType (eCatType a_CatType) { m_CatType = a_CatType; } /** Returns true if there's a cat sitting above the given position */ static bool IsCatSittingOnBlock(cWorld * a_World, Vector3d a_BlockPosition); protected: bool m_IsSitting; bool m_IsTame; bool m_IsBegging; eCatType m_CatType; /** Only check for a nearby player holding the breeding items every 23 ticks. */ int m_CheckPlayerTickCount; AString m_OwnerName; cUUID m_OwnerUUID; } ; ================================================ FILE: src/Mobs/PassiveAggressiveMonster.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "PassiveAggressiveMonster.h" #include "../Entities/Player.h" cPassiveAggressiveMonster::cPassiveAggressiveMonster(const AString & a_ConfigName, eMonsterType a_MobType, const AString & a_SoundHurt, const AString & a_SoundDeath, const AString & a_SoundAmbient, float a_Width, float a_Height) : Super(a_ConfigName, a_MobType, a_SoundHurt, a_SoundDeath, a_SoundAmbient, a_Width, a_Height) { m_EMPersonality = PASSIVE; } bool cPassiveAggressiveMonster::DoTakeDamage(TakeDamageInfo & a_TDI) { if (!Super::DoTakeDamage(a_TDI)) { return false; } if ((GetTarget() != nullptr) && GetTarget()->IsPlayer()) { if (static_cast(GetTarget())->CanMobsTarget()) { m_EMState = CHASING; } } return true; } void cPassiveAggressiveMonster::EventSeePlayer(cPlayer *, cChunk & a_Chunk) { // don't do anything, neutral mobs don't react to just seeing the player } ================================================ FILE: src/Mobs/PassiveAggressiveMonster.h ================================================ #pragma once #include "AggressiveMonster.h" class cPassiveAggressiveMonster: public cAggressiveMonster { using Super = cAggressiveMonster; public: cPassiveAggressiveMonster( const AString & a_ConfigName, eMonsterType a_MobType, const AString & a_SoundHurt, const AString & a_SoundDeath, const AString & a_SoundAmbient, float a_Width, float a_Height ); virtual bool DoTakeDamage(TakeDamageInfo & a_TDI) override; virtual void EventSeePlayer(cPlayer *, cChunk & a_Chunk) override; } ; ================================================ FILE: src/Mobs/PassiveMonster.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "PassiveMonster.h" #include "../World.h" #include "../Entities/Player.h" #include "../BoundingBox.h" #include "../Items/ItemSpawnEgg.h" cPassiveMonster::cPassiveMonster(const AString & a_ConfigName, eMonsterType a_MobType, const AString & a_SoundHurt, const AString & a_SoundDeath, const AString & a_SoundAmbient, float a_Width, float a_Height) : Super(a_ConfigName, a_MobType, a_SoundHurt, a_SoundDeath, a_SoundAmbient, a_Width, a_Height) { m_EMPersonality = PASSIVE; } bool cPassiveMonster::DoTakeDamage(TakeDamageInfo & a_TDI) { if (!Super::DoTakeDamage(a_TDI)) { return false; } if ((a_TDI.Attacker != this) && (a_TDI.Attacker != nullptr)) { m_EMState = ESCAPING; } return true; } void cPassiveMonster::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { Super::Tick(a_Dt, a_Chunk); if (!IsTicking()) { // The base class tick destroyed us return; } if (m_EMState == ESCAPING) { CheckEventLostPlayer(a_Dt); } cMonster::LoveTick(); } void cPassiveMonster::OnRightClicked(cPlayer & a_Player) { Super::OnRightClicked(a_Player); Super::RightClickFeed(a_Player); } ================================================ FILE: src/Mobs/PassiveMonster.h ================================================ #pragma once #include "Monster.h" #include "../UUID.h" class cPassiveMonster: public cMonster { using Super = cMonster; public: cPassiveMonster( const AString & a_ConfigName, eMonsterType a_MobType, const AString & a_SoundHurt, const AString & a_SoundDeath, const AString & a_SoundAmbient, float a_Width, float a_Height ); virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; virtual void OnRightClicked(cPlayer & a_Player) override; /** When hit by someone, run away */ virtual bool DoTakeDamage(TakeDamageInfo & a_TDI) override; }; ================================================ FILE: src/Mobs/Path.cpp ================================================ #include "Globals.h" #include "Path.h" #include "BlockType.h" #include "../BlockInfo.h" #include "../Chunk.h" #define JUMP_G_COST 20 #define NORMAL_G_COST 10 #define DIAGONAL_G_COST 14 #define DISTANCE_MANHATTAN 0 // 1: More speed, a bit less accuracy 0: Max accuracy, less speed. #define HEURISTICS_ONLY 0 // 1: Much more speed, much less accurate. #define CALCULATIONS_PER_STEP 10 // Higher means more CPU load but faster path calculations. // The only version which guarantees the shortest path is 0, 0. bool compareHeuristics::operator()(cPathCell * & a_Cell1, cPathCell * & a_Cell2) { return a_Cell1->m_F > a_Cell2->m_F; } /* cPath implementation */ cPath::cPath( cChunk & a_Chunk, const Vector3d & a_StartingPoint, const Vector3d & a_EndingPoint, int a_MaxSteps, double a_BoundingBoxWidth, double a_BoundingBoxHeight ) : m_StepsLeft(a_MaxSteps), m_IsValid(true), m_CurrentPoint(0), // GetNextPoint increments this to 1, but that's fine, since the first cell is always a_StartingPoint m_Chunk(&a_Chunk), m_BadChunkFound(false) { a_BoundingBoxWidth = 1; // Treat all mobs width as 1 until physics is improved. m_BoundingBoxWidth = CeilC(a_BoundingBoxWidth); m_BoundingBoxHeight = CeilC(a_BoundingBoxHeight); m_HalfWidth = a_BoundingBoxWidth / 2; int HalfWidthInt = FloorC(a_BoundingBoxWidth / 2); m_Source.x = FloorC(a_StartingPoint.x - HalfWidthInt); m_Source.y = FloorC(a_StartingPoint.y); m_Source.z = FloorC(a_StartingPoint.z - HalfWidthInt); m_Destination.x = FloorC(a_EndingPoint.x - HalfWidthInt); m_Destination.y = FloorC(a_EndingPoint.y); m_Destination.z = FloorC(a_EndingPoint.z - HalfWidthInt); if (!IsWalkable(m_Source, m_Source)) { m_Status = ePathFinderStatus::PATH_NOT_FOUND; return; } m_NearestPointToTarget = GetCell(m_Source); m_Status = ePathFinderStatus::CALCULATING; ProcessCell(GetCell(m_Source), nullptr, 0); } cPath::cPath() : m_IsValid(false) { } ePathFinderStatus cPath::CalculationStep(cChunk & a_Chunk) { m_Chunk = &a_Chunk; if (m_Status != ePathFinderStatus::CALCULATING) { return m_Status; } if (m_BadChunkFound) { FinishCalculation(ePathFinderStatus::PATH_NOT_FOUND); return m_Status; } if (m_StepsLeft == 0) { AttemptToFindAlternative(); } else { --m_StepsLeft; int i; for (i = 0; i < CALCULATIONS_PER_STEP; ++i) { if (StepOnce()) // StepOnce returns true when no more calculation is needed. { break; // if we're here, m_Status must have changed either to PATH_FOUND or PATH_NOT_FOUND. } } m_Chunk = nullptr; } return m_Status; } Vector3i cPath::AcceptNearbyPath() { ASSERT(m_Status == ePathFinderStatus::NEARBY_FOUND); m_Status = ePathFinderStatus::PATH_FOUND; return m_Destination; } bool cPath::StepOnce() { cPathCell * CurrentCell = OpenListPop(); // Path not reachable. if (CurrentCell == nullptr) { AttemptToFindAlternative(); return true; } // Path found. if (CurrentCell->m_Location == m_Destination) { BuildPath(); FinishCalculation(ePathFinderStatus::PATH_FOUND); return true; } // Calculation not finished yet // Check if we have a new NearestPoint. if ((m_Destination - CurrentCell->m_Location).Length() < 5) { if (GetRandomProvider().RandBool(0.25)) { m_NearestPointToTarget = CurrentCell; } } else if (CurrentCell->m_H < m_NearestPointToTarget->m_H) { m_NearestPointToTarget = CurrentCell; } // process a currentCell by inspecting all neighbors. // Now we start checking adjacent cells. // If true, no need to do more checks in that direction bool DoneEast = false, DoneWest = false, DoneNorth = false, DoneSouth = false; // If true, we can walk in that direction without changing height // This is used for deciding if to calculate diagonals bool WalkableEast = false, WalkableWest = false, WalkableNorth = false, WalkableSouth = false; // If we can jump without hitting the ceiling if (BodyFitsIn(CurrentCell->m_Location + Vector3i(0, 1, 0), CurrentCell->m_Location)) { // For ladder climbing ProcessIfWalkable(CurrentCell->m_Location + Vector3i(0, 1, 0), CurrentCell, JUMP_G_COST); // Check east-up if (ProcessIfWalkable(CurrentCell->m_Location + Vector3i(1, 1, 0), CurrentCell, JUMP_G_COST)) { DoneEast = true; } // Check west-up if (ProcessIfWalkable(CurrentCell->m_Location + Vector3i(-1, 1, 0), CurrentCell, JUMP_G_COST)) { DoneWest = true; } // Check north-up if (ProcessIfWalkable(CurrentCell->m_Location + Vector3i(0, 1, -1), CurrentCell, JUMP_G_COST)) { DoneNorth = true; } // Check south-up if (ProcessIfWalkable(CurrentCell->m_Location + Vector3i(0, 1, 1), CurrentCell, JUMP_G_COST)) { DoneSouth = true; } } // Check North, South, East, West at our own height or below. We are willing to jump up to 3 blocks down. if (!DoneEast) { for (int y = 0; y >= -3; --y) { if (ProcessIfWalkable(CurrentCell->m_Location + Vector3i(1, y, 0), CurrentCell, NORMAL_G_COST)) { DoneEast = true; if (y == 0) { WalkableEast = true; } break; } } } if (!DoneWest) { for (int y = 0; y >= -3; --y) { if (ProcessIfWalkable(CurrentCell->m_Location + Vector3i(-1, y, 0), CurrentCell, NORMAL_G_COST)) { DoneWest = true; if (y == 0) { WalkableWest = true; } break; } } } if (!DoneSouth) { for (int y = 0; y >= -3; --y) { if (ProcessIfWalkable(CurrentCell->m_Location + Vector3i(0, y, 1), CurrentCell, NORMAL_G_COST)) { DoneSouth = true; if (y == 0) { WalkableSouth = true; } break; } } } if (!DoneNorth) { for (int y = 0; y >= -3; --y) { if (ProcessIfWalkable(CurrentCell->m_Location + Vector3i(0, y, -1), CurrentCell, NORMAL_G_COST)) { DoneNorth = true; if (y == 0) { WalkableNorth = true; } break; } } } // Check diagonals if (WalkableNorth && WalkableEast) { ProcessIfWalkable(CurrentCell->m_Location + Vector3i(1, 0, -1), CurrentCell, DIAGONAL_G_COST); } if (WalkableNorth && WalkableWest) { ProcessIfWalkable(CurrentCell->m_Location + Vector3i(-1, 0, -1), CurrentCell, DIAGONAL_G_COST); } if (WalkableSouth && WalkableEast) { ProcessIfWalkable(CurrentCell->m_Location + Vector3i(1, 0, 1), CurrentCell, DIAGONAL_G_COST); } if (WalkableSouth && WalkableWest) { ProcessIfWalkable(CurrentCell->m_Location + Vector3i(-1, 0, 1), CurrentCell, DIAGONAL_G_COST); } return false; } void cPath::AttemptToFindAlternative() { if (m_NearestPointToTarget == GetCell(m_Source)) { FinishCalculation(ePathFinderStatus::PATH_NOT_FOUND); } else { m_Destination = m_NearestPointToTarget->m_Location; BuildPath(); FinishCalculation(ePathFinderStatus::NEARBY_FOUND); } } void cPath::BuildPath() { cPathCell * CurrentCell = GetCell(m_Destination); while (CurrentCell->m_Parent != nullptr) { // Waypoints are cylinders that start at some particular x, y, z and have infinite height. // Submerging water waypoints allows swimming mobs to be able to touch them. if (IsBlockWater(GetCell(CurrentCell->m_Location + Vector3i(0, -1, 0))->m_BlockType)) { CurrentCell->m_Location.y -= 30; } m_PathPoints.push_back(CurrentCell->m_Location); // Populate the cPath with points. All midpoints are added. Destination is added. Source is excluded. CurrentCell = CurrentCell->m_Parent; } } void cPath::FinishCalculation() { m_Map.clear(); m_OpenList = std::priority_queue, compareHeuristics>{}; } void cPath::FinishCalculation(ePathFinderStatus a_NewStatus) { if (m_BadChunkFound) { a_NewStatus = ePathFinderStatus::PATH_NOT_FOUND; } m_Status = a_NewStatus; FinishCalculation(); } void cPath::OpenListAdd(cPathCell * a_Cell) { a_Cell->m_Status = eCellStatus::OPENLIST; m_OpenList.push(a_Cell); #ifdef COMPILING_PATHFIND_DEBUGGER si::setBlock(a_Cell->m_Location.x, a_Cell->m_Location.y, a_Cell->m_Location.z, debug_open, SetMini(a_Cell)); #endif } cPathCell * cPath::OpenListPop() // Popping from the open list also means adding to the closed list. { if (m_OpenList.size() == 0) { return nullptr; // We've exhausted the search space and nothing was found, this will trigger a PATH_NOT_FOUND or NEARBY_FOUND status. } cPathCell * Ret = m_OpenList.top(); m_OpenList.pop(); Ret->m_Status = eCellStatus::CLOSEDLIST; #ifdef COMPILING_PATHFIND_DEBUGGER si::setBlock((Ret)->m_Location.x, (Ret)->m_Location.y, (Ret)->m_Location.z, debug_closed, SetMini(Ret)); #endif return Ret; } bool cPath::ProcessIfWalkable(const Vector3i & a_Location, cPathCell * a_Parent, int a_Cost) { if (IsWalkable(a_Location, a_Parent->m_Location)) { ProcessCell(GetCell(a_Location), a_Parent, a_Cost); return true; } return false; } void cPath::ProcessCell(cPathCell * a_Cell, cPathCell * a_Caller, int a_GDelta) { // Case 1: Cell is in the closed list, ignore it. if (a_Cell->m_Status == eCellStatus::CLOSEDLIST) { return; } if (a_Cell->m_Status == eCellStatus::NOLIST) // Case 2: The cell is not in any list. { // Cell is walkable, add it to the open list. // Note that non-walkable cells are filtered out in Step_internal(); // Special case: Start cell goes here, gDelta is 0, caller is NULL. a_Cell->m_Parent = a_Caller; if (a_Caller != nullptr) { a_Cell->m_G = a_Caller->m_G + a_GDelta; } else { a_Cell->m_G = 0; } // Calculate H. This is A*'s Heuristics value. #if DISTANCE_MANHATTAN == 1 // Manhattan distance. DeltaX + DeltaY + DeltaZ. a_Cell->m_H = 10 * (abs(a_Cell->m_Location.x-m_Destination.x) + abs(a_Cell->m_Location.y-m_Destination.y) + abs(a_Cell->m_Location.z-m_Destination.z)); #else // Euclidian distance. sqrt(DeltaX^2 + DeltaY^2 + DeltaZ^2), more precise. a_Cell->m_H = static_castm_H)>((a_Cell->m_Location - m_Destination).Length() * 10); #endif #if HEURISTICS_ONLY == 1 a_Cell->m_F = a_Cell->m_H; // Greedy search. https://en.wikipedia.org/wiki/Greedy_search #else a_Cell->m_F = a_Cell->m_H + a_Cell->m_G; // Regular A*. #endif OpenListAdd(a_Cell); return; } // Case 3: Cell is in the open list, check if G and H need an update. int NewG = a_Caller->m_G + a_GDelta; if (NewG < a_Cell->m_G) { a_Cell->m_G = NewG; a_Cell->m_H = a_Cell->m_F + a_Cell->m_G; a_Cell->m_Parent = a_Caller; } } void cPath::FillCellAttributes(cPathCell & a_Cell) { const Vector3i & Location = a_Cell.m_Location; ASSERT(m_Chunk != nullptr); if (!cChunkDef::IsValidHeight(Location)) { // Players can't build outside the game height, so it must be air a_Cell.m_IsSolid = false; a_Cell.m_IsSpecial = false; a_Cell.m_BlockType = E_BLOCK_AIR; return; } auto Chunk = m_Chunk->GetNeighborChunk(Location.x, Location.z); if ((Chunk == nullptr) || !Chunk->IsValid()) { m_BadChunkFound = true; a_Cell.m_IsSolid = true; a_Cell.m_IsSpecial = false; a_Cell.m_BlockType = E_BLOCK_AIR; // m_BlockType is never used when m_IsSpecial is false, but it may be used if we implement dijkstra return; } m_Chunk = Chunk; BLOCKTYPE BlockType; NIBBLETYPE BlockMeta; int RelX = Location.x - m_Chunk->GetPosX() * cChunkDef::Width; int RelZ = Location.z - m_Chunk->GetPosZ() * cChunkDef::Width; m_Chunk->GetBlockTypeMeta(RelX, Location.y, RelZ, BlockType, BlockMeta); a_Cell.m_BlockType = BlockType; a_Cell.m_BlockMeta = BlockMeta; if (BlockTypeIsSpecial(BlockType)) { a_Cell.m_IsSpecial = true; a_Cell.m_IsSolid = true; // Specials are solids only from a certain direction. But their m_IsSolid is always true } else if ((!cBlockInfo::IsSolid(a_Cell.m_BlockType)) && IsBlockFence(GetCell(Location + Vector3i(0, -1, 0))->m_BlockType)) { // Nonsolid blocks with fences below them are consider Special Solids. That is, they sometimes behave as solids. a_Cell.m_IsSpecial = true; a_Cell.m_IsSolid = true; } else { a_Cell.m_IsSpecial = false; a_Cell.m_IsSolid = cBlockInfo::IsSolid(BlockType); } } cPathCell * cPath::GetCell(const Vector3i & a_Location) { // Create the cell in the hash table if it's not already there. if (m_Map.count(a_Location) == 0) // Case 1: Cell is not on any list. We've never checked this cell before. { m_Map[a_Location].m_Location = a_Location; FillCellAttributes(m_Map[a_Location]); m_Map[a_Location].m_Status = eCellStatus::NOLIST; #ifdef COMPILING_PATHFIND_DEBUGGER #ifdef COMPILING_PATHFIND_DEBUGGER_MARK_UNCHECKED si::setBlock(a_Location.x, a_Location.y, a_Location.z, debug_unchecked, Cell->m_IsSolid ? NORMAL : MINI); #endif #endif return &m_Map[a_Location]; } else { return &m_Map[a_Location]; } } bool cPath::IsWalkable(const Vector3i & a_Location, const Vector3i & a_Source) { return (HasSolidBelow(a_Location) && BodyFitsIn(a_Location, a_Source)); } // We need the source because some special blocks are solid only from a certain direction e.g. doors bool cPath::BodyFitsIn(const Vector3i & a_Location, const Vector3i & a_Source) { int x, y, z; for (y = 0; y < m_BoundingBoxHeight; ++y) { for (x = 0; x < m_BoundingBoxWidth; ++x) { for (z = 0; z < m_BoundingBoxWidth; ++z) { cPathCell * CurrentCell = GetCell(a_Location + Vector3i(x, y, z)); if (CurrentCell->m_IsSolid) { if (CurrentCell->m_IsSpecial) { if (SpecialIsSolidFromThisDirection(CurrentCell->m_BlockType, CurrentCell->m_BlockMeta, a_Location - a_Source)) { return false; } } else { return false; } } } } } return true; } bool cPath::BlockTypeIsSpecial(BLOCKTYPE a_Type) { if (IsBlockFence(a_Type)) { return true; } switch (a_Type) { case E_BLOCK_OAK_DOOR: case E_BLOCK_DARK_OAK_DOOR: case E_BLOCK_TRAPDOOR: case E_BLOCK_WATER: case E_BLOCK_STATIONARY_WATER: { return true; } default: { return false; } } } bool cPath::SpecialIsSolidFromThisDirection(BLOCKTYPE a_Type, NIBBLETYPE a_Meta, const Vector3i & a_Direction) { if (a_Direction == Vector3i(0, 0, 0)) { return false; } // If there is a nonsolid above a fence if (!cBlockInfo::IsSolid(a_Type)) { // Only treat as solid when we're coming from below return (a_Direction.y > 0); } /* switch (a_Type) { case E_BLOCK_ETC: { Decide if solid from this direction and return either true or false. } // TODO Fill this with the other specials after physics is fixed } */ return true; } bool cPath::HasSolidBelow(const Vector3i & a_Location) { int x, z; for (x = 0; x < m_BoundingBoxWidth; ++x) { for (z = 0; z < m_BoundingBoxWidth; ++z) { if (GetCell(a_Location + Vector3i(x, -1, z))->m_IsSolid) { return true; } } } return false; } ================================================ FILE: src/Mobs/Path.h ================================================ #pragma once #include "ChunkDef.h" /* // Needed Fwds: cPath enum class ePathFinderStatus; class cPath; */ #include "../FastRandom.h" #ifdef COMPILING_PATHFIND_DEBUGGER /* Note: the COMPILING_PATHFIND_DEBUGGER flag is used by Native / WiseOldMan95 to debug this class outside of Cuberite. This preprocessor flag is never set when compiling Cuberite. */ #include "PathFinderIrrlicht_Head.h" #endif //fwd: ../Chunk.h class cChunk; /* Various little structs and classes */ enum class ePathFinderStatus {CALCULATING, PATH_FOUND, PATH_NOT_FOUND, NEARBY_FOUND}; enum class eCellStatus {OPENLIST, CLOSEDLIST, NOLIST}; /** The pathfinder has 3 types of cells (cPathCell). 1 - empty. m_IsSolid is false, m_IsSpecial is false. Air cells are always traversable by A*. 2 - occupied / solid. m_IsSolid is true, m_IsSpecial is false. Air cells are never traversable by A*. 3 - Special. m_IsSolid is true, m_IsSpecial is true. These cells are special: They may either behave as empty or as occupied / solid, depending on the mob's direction of movement. For instance, an airblock above a fence is a special cell, because when mobs attempt to travel to it by jumping, it acts as a solid. But when mobs fall and land on top of a fence, it acts as air. Special cells include: Doors, ladders, trapdoors, water, gates. The main function which handles special blocks is SpecialIsSolidFromThisDirection. This function receives a BlockType, a meta, and a direction of travel, then it uses those 3 parameters to decide whether the special block should behave as a solid or as air in this particular direction of travel. Currently, only fences and water are handled properly. The function always returns "true" (meaning: treat as occuiped/solid) for the rest of the blocks. This will be fixed once the physics engine issues are fixed. */ struct cPathCell { Vector3i m_Location; // Location of the cell in the world. int m_F, m_G, m_H; // F, G, H as defined in regular A*. eCellStatus m_Status; // Which list is the cell in? Either non, open, or closed. cPathCell * m_Parent; // Cell's parent, as defined in regular A*. bool m_IsSolid; // Is the cell an air or a solid? Partial solids are considered solids. If m_IsSpecial is true, this is always true. bool m_IsSpecial; // The cell is special - it acts as "solid" or "air" depending on direction, e.g. door or top of fence. BLOCKTYPE m_BlockType; NIBBLETYPE m_BlockMeta; }; class compareHeuristics { public: bool operator()(cPathCell * & a_V1, cPathCell * & a_V2); }; class cPath { public: /** Creates a pathfinder instance. After calling this, you are expected to call CalculationStep() once per tick or once per several ticks until it returns something other than CALCULATING. @param a_StartingPoint The function expects this position to be the lowest block the mob is in, a rule of thumb: "The block where the Zombie's knees are at". @param a_EndingPoint "The block where the Zombie's knees want to be". @param a_MaxSteps The maximum steps before giving up. @param a_BoundingBoxWidth the character's boundingbox width in blocks. Currently the parameter is ignored and 1 is assumed. @param a_BoundingBoxHeight the character's boundingbox width in blocks. Currently the parameter is ignored and 2 is assumed. */ cPath( cChunk & a_Chunk, const Vector3d & a_StartingPoint, const Vector3d & a_EndingPoint, int a_MaxSteps, double a_BoundingBoxWidth, double a_BoundingBoxHeight ); /** Creates an invalid path which is not usable. You shouldn't call any method other than isValid on such a path. */ cPath(); /** delete default constructors */ cPath(const cPath & a_other) = delete; cPath(cPath && a_other) = delete; cPath & operator=(const cPath & a_other) = delete; cPath & operator=(cPath && a_other) = delete; /** Performs part of the path calculation and returns the appropriate status. If PATH_FOUND is returned, the path was found, and you can call query the instance for waypoints via GetNextWayPoint, etc. If NEARBY_FOUND is returned, it means that the destination is not reachable, but a nearby destination is reachable. If the user likes the alternative destination, they can call AcceptNearbyPath to treat the path as found, and to make consequent calls to step return PATH_FOUND If PATH_NOT_FOUND is returned, then no path was found. */ ePathFinderStatus CalculationStep(cChunk & a_Chunk); /** Called after the PathFinder's step returns NEARBY_FOUND. Changes the PathFinder status from NEARBY_FOUND to PATH_FOUND, returns the nearby destination that the PathFinder found a path to. */ Vector3i AcceptNearbyPath(); // Point retrieval functions, inlined for performance: /** Returns the next point in the path. */ inline Vector3d GetNextPoint() { ASSERT(m_Status == ePathFinderStatus::PATH_FOUND); ASSERT(m_CurrentPoint < m_PathPoints.size()); Vector3i Point = m_PathPoints[m_PathPoints.size() - 1 - m_CurrentPoint]; ++m_CurrentPoint; return Vector3d(Point.x + m_HalfWidth, Point.y, Point.z + m_HalfWidth); } /** Checks if we have no more waypoints to return. Never call getnextPoint when this is true. */ inline bool NoMoreWayPoints() const { ASSERT(m_Status == ePathFinderStatus::PATH_FOUND); return (m_CurrentPoint == m_PathPoints.size()); } /** Returns true if GetNextPoint() was never called for this Path. */ inline bool IsFirstPoint() const { ASSERT(m_Status == ePathFinderStatus::PATH_FOUND); return (m_CurrentPoint == 0); } /** Returns true if this path is properly initialized. Returns false if this path was initialized with an empty constructor. If false, the path is unusable and you should not call any methods. */ inline bool IsValid() const { return m_IsValid; } /** The amount of waypoints left to return. */ inline size_t WayPointsLeft() const { ASSERT(m_Status == ePathFinderStatus::PATH_FOUND); return m_PathPoints.size() - m_CurrentPoint; } private: /* General */ bool StepOnce(); // The public version just calls this version * CALCULATIONS_PER_CALL times. void FinishCalculation(); // Clears the memory used for calculating the path. void FinishCalculation(ePathFinderStatus a_NewStatus); // Clears the memory used for calculating the path and changes the status. void AttemptToFindAlternative(); void BuildPath(); /* Openlist and closedlist management */ void OpenListAdd(cPathCell * a_Cell); cPathCell * OpenListPop(); bool ProcessIfWalkable(const Vector3i & a_Location, cPathCell * a_Source, int a_Cost); /* Map management */ void ProcessCell(cPathCell * a_Cell, cPathCell * a_Caller, int a_GDelta); cPathCell * GetCell(const Vector3i & a_location); /* Pathfinding fields */ std::priority_queue, compareHeuristics> m_OpenList; std::unordered_map> m_Map; Vector3i m_Destination; Vector3i m_Source; int m_BoundingBoxWidth; int m_BoundingBoxHeight; double m_HalfWidth; int m_StepsLeft; cPathCell * m_NearestPointToTarget; /* Control fields */ ePathFinderStatus m_Status; bool m_IsValid; /* Final path fields */ size_t m_CurrentPoint; std::vector m_PathPoints; /* Interfacing with the world */ void FillCellAttributes(cPathCell & a_Cell); // Query our hosting world and fill the cell with info cChunk * m_Chunk; // Only valid inside Step()! bool m_BadChunkFound; /* High level world queries */ bool IsWalkable(const Vector3i & a_Location, const Vector3i & a_Source); bool BodyFitsIn(const Vector3i & a_Location, const Vector3i & a_Source); bool BlockTypeIsSpecial(BLOCKTYPE a_Type); bool SpecialIsSolidFromThisDirection(BLOCKTYPE a_Type, NIBBLETYPE a_Meta, const Vector3i & a_Direction); bool HasSolidBelow(const Vector3i & a_Location); #ifdef COMPILING_PATHFIND_DEBUGGER #include "../path_irrlicht.cpp" #endif }; ================================================ FILE: src/Mobs/PathFinder.cpp ================================================ #include "Globals.h" #include "PathFinder.h" #include "BlockType.h" #include "../BlockInfo.h" #include "../Chunk.h" cPathFinder::cPathFinder(float a_MobWidth, float a_MobHeight) : m_Width(a_MobWidth), m_Height(a_MobHeight), m_GiveUpCounter(0), m_NotFoundCooldown(0) { } ePathFinderStatus cPathFinder::GetNextWayPoint(cChunk & a_Chunk, const Vector3d & a_Source, Vector3d * a_Destination, Vector3d * a_OutputWaypoint, bool a_DontCare) { m_FinalDestination = *a_Destination; m_Source = a_Source; // If a recent PATH_NOT_FOUND was returned, we rest for a few ticks. if (m_NotFoundCooldown > 0) { m_NotFoundCooldown -= 1; return ePathFinderStatus::CALCULATING; } // Tweak the destination. If something is wrong with the destination or the chunk, rest for a while. if (!(EnsureProperPoint(m_FinalDestination, a_Chunk) && EnsureProperPoint(m_Source, a_Chunk))) { m_NotFoundCooldown = 20; return ePathFinderStatus::PATH_NOT_FOUND; } /* printf("%d %d %d -> %d %d %d\n", static_cast(m_Source.x), static_cast(m_Source.y), static_cast(m_Source.z), static_cast(m_FinalDestination.x), static_cast(m_FinalDestination.y), static_cast(m_FinalDestination.z)); */ // Rest is over. Prepare m_Path by calling ResetPathFinding. if (m_NotFoundCooldown == 0) { m_NotFoundCooldown = -1; ResetPathFinding(a_Chunk); } // If m_Path has not been initialized yet, initialize it. if (!m_Path->IsValid()) { ResetPathFinding(a_Chunk); } switch (m_Path->CalculationStep(a_Chunk)) { case ePathFinderStatus::NEARBY_FOUND: { m_NoPathToTarget = true; m_PathDestination = m_Path->AcceptNearbyPath(); if (a_DontCare) { m_FinalDestination = m_PathDestination; *a_Destination = m_FinalDestination; // Modify the mob's final destination because it doesn't care about reaching an exact spot } else { m_DeviationOrigin = m_FinalDestination; // This is the only case in which m_DeviationOrigin != m_PathDestination } return ePathFinderStatus::CALCULATING; // The next call will trigger the PATH_FOUND case } case ePathFinderStatus::PATH_NOT_FOUND: { m_NotFoundCooldown = 20; return ePathFinderStatus::PATH_NOT_FOUND; } case ePathFinderStatus::CALCULATING: { return ePathFinderStatus::CALCULATING; } case ePathFinderStatus::PATH_FOUND: { m_GiveUpCounter -= 1; if (m_GiveUpCounter == 0) { if (a_DontCare) { // We're having trouble reaching the next waypoint but the mob // Doesn't care where to go, just tell him we got there ;) m_FinalDestination = m_Source; *a_Destination = m_FinalDestination; ResetPathFinding(a_Chunk); return ePathFinderStatus::CALCULATING; } else { ResetPathFinding(a_Chunk); return ePathFinderStatus::CALCULATING; } } if (PathIsTooOld()) { ResetPathFinding(a_Chunk); return ePathFinderStatus::CALCULATING; } if (m_Path->NoMoreWayPoints()) { // We're always heading towards m_PathDestination. // If m_PathDestination is exactly m_FinalDestination, then we're about to reach the destination. if (m_PathDestination == m_FinalDestination) { *a_OutputWaypoint = m_FinalDestination; return ePathFinderStatus::PATH_FOUND; } else { // Otherwise, we've finished our approximate path and time to recalc. ResetPathFinding(a_Chunk); return ePathFinderStatus::CALCULATING; } } Vector3d Waypoint(m_WayPoint); Vector3d Source(m_Source); Waypoint.y = 0; Source.y = 0; if (m_Path->IsFirstPoint() || (((Waypoint - Source).SqrLength() < WAYPOINT_RADIUS) && (m_Source.y >= m_WayPoint.y))) { // if the mob has just started or if the mob reached a waypoint, give them a new waypoint. m_WayPoint = m_Path->GetNextPoint(); m_GiveUpCounter = 40; return ePathFinderStatus::PATH_FOUND; } else { // Otherwise, the mob is still walking towards its waypoint, we'll patiently wait. We won't update m_WayPoint. *a_OutputWaypoint = m_WayPoint; return ePathFinderStatus::PATH_FOUND; } } } UNREACHABLE("Unsupported path finder status"); } void cPathFinder::ResetPathFinding(cChunk &a_Chunk) { m_GiveUpCounter = 40; m_NoPathToTarget = false; m_PathDestination = m_FinalDestination; m_DeviationOrigin = m_PathDestination; m_Path.reset(new cPath(a_Chunk, m_Source, m_PathDestination, 20, m_Width, m_Height)); } bool cPathFinder::EnsureProperPoint(Vector3d & a_Vector, cChunk & a_Chunk) { cChunk * Chunk = a_Chunk.GetNeighborChunk(FloorC(a_Vector.x), FloorC(a_Vector.z)); BLOCKTYPE BlockType; NIBBLETYPE BlockMeta; if ((Chunk == nullptr) || !Chunk->IsValid()) { return false; } // If destination in the air, first try to go 1 block north, or east, or west. // This fixes the player leaning issue. // If that failed, we instead go down to the lowest air block. auto Below = a_Vector.Floor().addedY(-1); if (!cChunkDef::IsValidHeight(Below)) { return false; } auto BelowRel = cChunkDef::AbsoluteToRelative(Below); Chunk->GetBlockTypeMeta(BelowRel, BlockType, BlockMeta); if (!(IsWaterOrSolid(BlockType))) { constexpr std::array Offsets = { { {-1, 0, 0}, {1, 0, 0}, {0, 0, -1}, {0, 0, 1}, {-1, 0, -1}, {-1, 0, 1}, {1, 0, -1}, {1, 0, 1}, } }; // Looks for a neighbouring block one block in x or z direction that is water or solid. bool InTheAir = true; for (const auto & Offset : Offsets) { auto InspectPos = Below + Offset; Chunk = a_Chunk.GetNeighborChunk(InspectPos.x, InspectPos.z); if ((Chunk == nullptr) || !Chunk->IsValid()) { return false; } auto InspectRel = cChunkDef::AbsoluteToRelative(InspectPos); Chunk->GetBlockTypeMeta(InspectRel, BlockType, BlockMeta); if (IsWaterOrSolid((BlockType))) { BelowRel = InspectRel; InTheAir = false; break; } } // Go down to the lowest air block. if (InTheAir) { while (cChunkDef::IsValidHeight(BelowRel.addedY(-1))) { Chunk->GetBlockTypeMeta(BelowRel.addedY(-1), BlockType, BlockMeta); if (IsWaterOrSolid(BlockType)) { break; } BelowRel.y -= 1; } } } // If destination in water or solid, go up to the first air block. while (BelowRel.y < cChunkDef::Height) { Chunk->GetBlockTypeMeta(BelowRel, BlockType, BlockMeta); if (!IsWaterOrSolid(BlockType)) { break; } BelowRel.y += 1; } return true; } bool cPathFinder::IsWaterOrSolid(BLOCKTYPE a_BlockType) { return ((a_BlockType == E_BLOCK_STATIONARY_WATER) || cBlockInfo::IsSolid(a_BlockType)); } bool cPathFinder::PathIsTooOld() const { size_t acceptableDeviation = m_Path->WayPointsLeft() / 2; if (acceptableDeviation == 0) { acceptableDeviation = 1; } const auto DeviationSqr = (m_FinalDestination - m_DeviationOrigin).SqrLength(); return (DeviationSqr > (acceptableDeviation * acceptableDeviation)); } ================================================ FILE: src/Mobs/PathFinder.h ================================================ #pragma once #include "Path.h" #define WAYPOINT_RADIUS 0.5 /** This class wraps cPath. cPath is a "dumb device" - You give it point A and point B, and it returns a full path path. cPathFinder - You give it a constant stream of point A (where you are) and point B (where you want to go), and it tells you where to go next. It manages path recalculation internally, and is much more efficient that calling cPath every step. */ class cPathFinder { public: /** Creates a cPathFinder instance. Each mob should have one cPathFinder throughout its lifetime. @param a_MobWidth The mob width. @param a_MobHeight The mob height. */ cPathFinder(float a_MobWidth, float a_MobHeight); /** Updates the PathFinder's internal state and returns a waypoint. A waypoint is a coordinate which the mob can safely move to from its current position in a straight line. The mob is expected to call this function tick as long as it is following a path. @param a_Chunk The chunk in which the mob is currently at. @param a_Source The mob's position. a_Source's coordinates are expected to be within the chunk given in a_Chunk. @param a_Destination The position the mob would like to reach. If a_ExactPath is true, the PathFinder may modify this. @param a_OutputWaypoint An output parameter: The next waypoint to go to. @param a_DontCare If true, the mob doesn't care where to go, and the Pathfinder may modify a_Destination. This should usually be false. An exception is a wandering idle mob which doesn't care about its final destination. In the future, idle mobs shouldn't use A* at all. Returns an ePathFinderStatus. ePathFinderStatus:CALCULATING - The PathFinder is still processing a path. Nothing was written to a_OutputWaypoint. The mob should probably not move. ePathFinderStatus:PATH_FOUND - The PathFinder has found a path to the target. The next waypoint was written a_OutputWaypoint. The mob should probably move to a_OutputWaypoint. ePathFinderStatus:NEARBY_FOUND - The PathFinder did not find a destination to the target but did find a nearby spot. The next waypoint was written a_OutputWaypoint. The mob should probably move to a_OutputWaypoint. ePathFinderStatus:PATH_NOT_FOUND - The PathFinder did not find a destination to the target. Nothing was written to a_OutputWaypoint. The mob should probably not move. Note: Once NEARBY_FOUND is returned once, subsequent calls return PATH_FOUND. */ ePathFinderStatus GetNextWayPoint(cChunk & a_Chunk, const Vector3d & a_Source, Vector3d * a_Destination, Vector3d * a_OutputWaypoint, bool a_DontCare = false); private: /** The width of the Mob which owns this PathFinder. */ float m_Width; /** The height of the Mob which owns this PathFinder. */ float m_Height; /** The current cPath instance we have. This is discarded and recreated when a path recalculation is needed. */ std::unique_ptr m_Path; /** If 0, will give up reaching the next m_WayPoint and will recalculate path. */ int m_GiveUpCounter; /** Coordinates of the next position that should be reached. */ Vector3d m_WayPoint; /** Coordinates for where we should go. This is out ultimate, final destination. */ Vector3d m_FinalDestination; /** Coordinates for where we are practically going. */ Vector3d m_PathDestination; /** When FinalDestination is too far from this, we recalculate. This usually equals PathDestination. Except when m_NoPathToTarget is true. */ Vector3d m_DeviationOrigin; /** Coordinates for where the mob is currently at. */ Vector3d m_Source; /** True if there's no path to target and we're walking to a nearby location instead. */ bool m_NoPathToTarget; /** When a path is not found, this cooldown prevents any recalculations for several ticks. */ int m_NotFoundCooldown; /** Ensures the location is not in the air or under water. May change the Y coordinate of the given vector. 1. If a_Vector is the position of water, a_Vector's Y will be modified to point to the first air block above it. 2. If a_Vector is the position of air, a_Vector's Y will be modified to point to the first airblock below it which has solid or water beneath. */ bool EnsureProperPoint(Vector3d & a_Vector, cChunk & a_Chunk); /** Resets a pathfinding task, typically because m_FinalDestination has deviated too much from m_DeviationOrigin. */ void ResetPathFinding(cChunk &a_Chunk); /** Return true the the blocktype is either water or solid */ bool IsWaterOrSolid(BLOCKTYPE a_BlockType); /** Is the path too old and should be recalculated? When this is true ResetPathFinding() is called. */ bool PathIsTooOld() const; }; ================================================ FILE: src/Mobs/Pig.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "Pig.h" #include "../Entities/Player.h" #include "../World.h" cPig::cPig(void) : Super("Pig", mtPig, "entity.pig.hurt", "entity.pig.death", "entity.pig.ambient", 0.9f, 0.9f), m_bIsSaddled(false) { } void cPig::GetDrops(cItems & a_Drops, cEntity * a_Killer) { if (IsBaby()) { return; // Babies don't drop items } unsigned int LootingLevel = 0; if (a_Killer != nullptr) { LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting); } AddRandomDropItem(a_Drops, 1, 3 + LootingLevel, IsOnFire() ? E_ITEM_COOKED_PORKCHOP : E_ITEM_RAW_PORKCHOP); if (m_bIsSaddled) { a_Drops.emplace_back(E_ITEM_SADDLE, static_cast(1)); } } void cPig::OnRightClicked(cPlayer & a_Player) { Super::OnRightClicked(a_Player); if (m_bIsSaddled) { if (m_Attachee != nullptr) { if (m_Attachee->GetUniqueID() == a_Player.GetUniqueID()) { // This player is already sitting in, they want out. a_Player.Detach(); return; } if (m_Attachee->IsPlayer()) { // Another player is already sitting in here, cannot attach return; } // Detach whatever is sitting in this pig now: m_Attachee->Detach(); } // Attach the player to this pig: a_Player.AttachTo(*this); } else if (a_Player.GetEquippedItem().m_ItemType == E_ITEM_SADDLE) { if (!a_Player.IsGameModeCreative()) { a_Player.GetInventory().RemoveOneEquippedItem(); } // Set saddle state & broadcast metadata m_bIsSaddled = true; m_World->BroadcastEntityMetadata(*this); } } void cPig::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { Super::Tick(a_Dt, a_Chunk); if (!IsTicking()) { // The base class tick destroyed us return; } // If the attachee player is holding a carrot-on-stick, let them drive this pig: if (m_bIsSaddled && (m_Attachee != nullptr)) { if (m_Attachee->IsPlayer() && (m_Attachee->GetEquippedWeapon().m_ItemType == E_ITEM_CARROT_ON_STICK)) { MoveToPosition((m_Attachee->GetPosition()) + (m_Attachee->GetLookVector()*10)); } } } bool cPig::DoTakeDamage(TakeDamageInfo & a_TDI) { if (!Super::DoTakeDamage(a_TDI)) { return false; } if (a_TDI.DamageType == dtLightning) { Destroy(); m_World->SpawnMob(GetPosX(), GetPosY(), GetPosZ(), mtZombiePigman, false); return true; } return true; } ================================================ FILE: src/Mobs/Pig.h ================================================ #pragma once #include "PassiveMonster.h" class cPig: public cPassiveMonster { using Super = cPassiveMonster; public: cPig(); CLASS_PROTODEF(cPig) // cEntity overrides virtual bool DoTakeDamage(TakeDamageInfo & a_TDI) override; virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override; virtual void OnRightClicked(cPlayer & a_Player) override; virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; virtual void GetFollowedItems(cItems & a_Items) override { a_Items.Add(E_ITEM_CARROT); } bool IsSaddled(void) const { return m_bIsSaddled; } private: bool m_bIsSaddled; } ; ================================================ FILE: src/Mobs/Rabbit.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "Rabbit.h" #include "../Entities/Player.h" #include "../World.h" cRabbit::cRabbit(void) : cRabbit(static_cast(GetRandomProvider().RandInt( static_cast(eRabbitType::SaltAndPepper) // Max possible Rabbit-Type )), 0) { } cRabbit::cRabbit(eRabbitType Type, int MoreCarrotTicks) : Super("Rabbit", mtRabbit, "entity.rabbit.hurt", "entity.rabbit.death", "entity.rabbit.ambient", 0.4f, 0.5f), m_Type(Type), m_MoreCarrotTicks(MoreCarrotTicks) { } void cRabbit::GetDrops(cItems & a_Drops, cEntity * a_Killer) { if (IsBaby()) { return; // Babies don't drop items } unsigned int LootingLevel = 0; if (a_Killer != nullptr) { LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting); } AddRandomDropItem(a_Drops, 0, 1 + LootingLevel, IsOnFire() ? E_ITEM_COOKED_RABBIT : E_ITEM_RAW_RABBIT); AddRandomDropItem(a_Drops, 0, 1 + LootingLevel, E_ITEM_RABBIT_HIDE); cItems RareDrops; RareDrops.Add(cItem(E_ITEM_RABBITS_FOOT)); AddRandomRareDropItem(a_Drops, RareDrops, LootingLevel); } ================================================ FILE: src/Mobs/Rabbit.h ================================================ #pragma once #include "PassiveMonster.h" enum class eRabbitType : UInt8 { Brown = 0, White = 1, Black = 2, BlackAndWhite = 3, Gold = 4, SaltAndPepper = 5, TheKillerBunny = 99 }; class cRabbit: public cPassiveMonster { using Super = cPassiveMonster; public: cRabbit(); cRabbit(eRabbitType Type, int MoreCarrotTicks = 0); CLASS_PROTODEF(cRabbit) virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override; virtual void GetFollowedItems(cItems & a_Items) override { a_Items.Add(E_ITEM_CARROT); a_Items.Add(E_ITEM_GOLDEN_CARROT); a_Items.Add(E_BLOCK_DANDELION); } eRabbitType GetRabbitType() const { return m_Type; } int GetMoreCarrotTicks() const { return m_MoreCarrotTicks; } private: eRabbitType m_Type; int m_MoreCarrotTicks; // Ticks until the Rabbit eat planted Carrots } ; ================================================ FILE: src/Mobs/Sheep.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "Sheep.h" #include "../Entities/Player.h" #include "../World.h" #include "../EffectID.h" #include "../FastRandom.h" cSheep::cSheep(int a_Color) : Super("Sheep", mtSheep, "entity.sheep.hurt", "entity.sheep.death", "entity.sheep.ambient", 0.9f, 1.3f), m_IsSheared(false), m_WoolColor(a_Color), m_TimeToStopEating(-1) { // Generate random wool color. if (m_WoolColor == -1) { m_WoolColor = GenerateNaturalRandomColor(); } if ((m_WoolColor < 0) || (m_WoolColor > 15)) { m_WoolColor = 0; } } void cSheep::GetDrops(cItems & a_Drops, cEntity * a_Killer) { if (IsBaby()) { return; // Babies don't drop items } if (!m_IsSheared) { a_Drops.emplace_back(E_BLOCK_WOOL, static_cast(1), static_cast(m_WoolColor)); } unsigned int LootingLevel = 0; if (a_Killer != nullptr) { LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting); } AddRandomDropItem(a_Drops, 1, 3 + LootingLevel, IsOnFire() ? E_ITEM_COOKED_MUTTON : E_ITEM_RAW_MUTTON); } void cSheep::OnRightClicked(cPlayer & a_Player) { Super::OnRightClicked(a_Player); const cItem & EquippedItem = a_Player.GetEquippedItem(); if ((EquippedItem.m_ItemType == E_ITEM_SHEARS) && !IsSheared() && !IsBaby()) { m_IsSheared = true; m_World->BroadcastEntityMetadata(*this); a_Player.UseEquippedItem(); cItems Drops; char NumDrops = GetRandomProvider().RandInt(1, 3); Drops.emplace_back(E_BLOCK_WOOL, NumDrops, static_cast(m_WoolColor)); m_World->SpawnItemPickups(Drops, GetPosX(), GetPosY(), GetPosZ(), 10); m_World->BroadcastSoundEffect("entity.sheep.shear", GetPosition(), 1.0f, 1.0f); } else if ((EquippedItem.m_ItemType == E_ITEM_DYE) && (m_WoolColor != 15 - EquippedItem.m_ItemDamage)) { m_WoolColor = 15 - EquippedItem.m_ItemDamage; if (!a_Player.IsGameModeCreative()) { a_Player.GetInventory().RemoveOneEquippedItem(); } m_World->BroadcastEntityMetadata(*this); } } void cSheep::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { Super::Tick(a_Dt, a_Chunk); if (!IsTicking()) { // The base class tick destroyed us return; } int PosX = POSX_TOINT; int PosY = POSY_TOINT - 1; int PosZ = POSZ_TOINT; if ((PosY <= 0) || (PosY >= cChunkDef::Height)) { return; } if (m_TimeToStopEating > 0) { StopMovingToPosition(); m_TimeToStopEating--; if (m_TimeToStopEating == 0) { if (m_World->GetBlock({ PosX, PosY, PosZ }) == E_BLOCK_GRASS) // Make sure grass hasn't been destroyed in the meantime { // The sheep ate the grass so we change it to dirt m_World->SetBlock({ PosX, PosY, PosZ }, E_BLOCK_DIRT, 0); GetWorld()->BroadcastSoundParticleEffect(EffectID::PARTICLE_BLOCK_BREAK, { PosX, PosY, PosZ }, E_BLOCK_GRASS); m_IsSheared = false; m_World->BroadcastEntityMetadata(*this); } } } else { if (GetRandomProvider().RandBool(1.0 / 600.0)) { if (m_World->GetBlock({ PosX, PosY, PosZ }) == E_BLOCK_GRASS) { m_World->BroadcastEntityAnimation(*this, EntityAnimation::SheepEatsGrass); m_TimeToStopEating = 40; } } } } void cSheep::InheritFromParents(cMonster * a_Parent1, cMonster * a_Parent2) { static const struct { short Parent1, Parent2, Child; } ColorInheritance[] = { { E_META_WOOL_BLUE, E_META_WOOL_RED, E_META_WOOL_PURPLE }, { E_META_WOOL_BLUE, E_META_WOOL_GREEN, E_META_WOOL_CYAN }, { E_META_WOOL_YELLOW, E_META_WOOL_RED, E_META_WOOL_ORANGE }, { E_META_WOOL_GREEN, E_META_WOOL_WHITE, E_META_WOOL_LIGHTGREEN }, { E_META_WOOL_RED, E_META_WOOL_WHITE, E_META_WOOL_PINK }, { E_META_WOOL_WHITE, E_META_WOOL_BLACK, E_META_WOOL_GRAY }, { E_META_WOOL_PURPLE, E_META_WOOL_PINK, E_META_WOOL_MAGENTA }, { E_META_WOOL_WHITE, E_META_WOOL_GRAY, E_META_WOOL_LIGHTGRAY }, { E_META_WOOL_BLUE, E_META_WOOL_WHITE, E_META_WOOL_LIGHTBLUE }, }; cSheep * Parent1 = static_cast(a_Parent1); cSheep * Parent2 = static_cast(a_Parent2); for (size_t i = 0; i < ARRAYCOUNT(ColorInheritance); i++) { if ( ((Parent1->GetFurColor() == ColorInheritance[i].Parent1) && (Parent2->GetFurColor() == ColorInheritance[i].Parent2)) || ((Parent1->GetFurColor() == ColorInheritance[i].Parent2) && (Parent2->GetFurColor() == ColorInheritance[i].Parent1)) ) { SetFurColor(ColorInheritance[i].Child); return; } } SetFurColor(GetRandomProvider().RandBool() ? Parent1->GetFurColor() : Parent2->GetFurColor()); } NIBBLETYPE cSheep::GenerateNaturalRandomColor(void) { int Chance = GetRandomProvider().RandInt(100); if (Chance <= 81) { return E_META_WOOL_WHITE; } else if (Chance <= 86) { return E_META_WOOL_BLACK; } else if (Chance <= 91) { return E_META_WOOL_GRAY; } else if (Chance <= 96) { return E_META_WOOL_LIGHTGRAY; } else if (Chance <= 99) { return E_META_WOOL_BROWN; } else { return E_META_WOOL_PINK; } } ================================================ FILE: src/Mobs/Sheep.h ================================================ #pragma once #include "PassiveMonster.h" class cSheep: public cPassiveMonster { using Super = cPassiveMonster; public: /** The number is the color of the sheep. Use E_META_WOOL_* constants for the wool color. If you type -1, the server will generate a random color with the GenerateNaturalRandomColor() function. */ cSheep(int a_Color = -1); CLASS_PROTODEF(cSheep) virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override; virtual void OnRightClicked(cPlayer & a_Player) override; virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; virtual void InheritFromParents(cMonster * a_Parent1, cMonster * a_Parent2) override; virtual void GetFollowedItems(cItems & a_Items) override { a_Items.Add(E_ITEM_WHEAT); } /** Generates a random color for the sheep like the vanilla server. The percent's where used are from the wiki: https://minecraft.wiki/w/Sheep#Breeding */ static NIBBLETYPE GenerateNaturalRandomColor(void); bool IsSheared(void) const { return m_IsSheared; } void SetSheared(bool a_IsSheared) { m_IsSheared = a_IsSheared; } int GetFurColor(void) const { return m_WoolColor; } void SetFurColor(int a_WoolColor) { m_WoolColor = a_WoolColor; } private: bool m_IsSheared; int m_WoolColor; int m_TimeToStopEating; } ; ================================================ FILE: src/Mobs/Silverfish.cpp ================================================ #include "Globals.h" #include "Silverfish.h" #include "../World.h" #include "../Chunk.h" #include "../Blocks/BlockHandler.h" #include "../Blocks/BlockInfested.h" cSilverfish::cSilverfish() : Super("Silverfish", mtSilverfish, "entity.silverfish.hurt", "entity.silverfish.death", "entity.silverfish.ambient", 0.4f, 0.3f) { } bool cSilverfish::DoTakeDamage(TakeDamageInfo &a_TDI) { // Call on our brethren to attack! // TODO: stop this if /gamerule mobGriefing is set to false // If the entity didn't take any damage, bail: if (!Super::DoTakeDamage(a_TDI)) { return false; } // Or, conversely took lethal damage, bail: if (m_Health <= 0) { return true; } if (a_TDI.Attacker == nullptr) { if ((a_TDI.DamageType != dtPoison) && (a_TDI.DamageType != dtPotionOfHarming)) { // Bail if attacker doesn't exist and it wasn't a splash potion: return true; } } else if (!a_TDI.Attacker->IsPlayer()) { // Bail if it wasn't a player attack: return true; } auto & Random = GetRandomProvider(); // Tries to spawn another Silverfish, returning if the search should continue. auto CheckInfested = [this, &Random, Position = GetPosition().Floor()](const Vector3i Offset) mutable { const auto Block = Position + Offset; if (m_World->GetBlock(Block) == E_BLOCK_SILVERFISH_EGG) { m_World->DigBlock(Block); return Random.RandBool(); } return false; }; // Search the faces of an increasingly large cube (so the positions closest get looked at first) // of min 3, max 10, for infested blocks and spawn additional reinforcements: for (int CubeSideLength = 3; CubeSideLength <= 10; CubeSideLength += 2) { const int HalfSide = CubeSideLength / 2; for (int OffsetX = -HalfSide; OffsetX <= HalfSide; OffsetX++) { for (int OffsetZ = -HalfSide; OffsetZ <= HalfSide; OffsetZ++) { if (CheckInfested({ OffsetX, +HalfSide, OffsetZ }) || CheckInfested({ OffsetX, -HalfSide, OffsetZ })) { return true; } } } for (int OffsetX = -HalfSide; OffsetX <= HalfSide; OffsetX++) { for (int OffsetY = -HalfSide + 1; OffsetY <= HalfSide - 1; OffsetY++) { if (CheckInfested({ OffsetX, OffsetY, +HalfSide }) || CheckInfested({ OffsetX, OffsetY, -HalfSide })) { return true; } } } for (int OffsetZ = -HalfSide + 1; OffsetZ <= HalfSide - 1; OffsetZ++) { for (int OffsetY = -HalfSide + 1; OffsetY <= HalfSide - 1; OffsetY++) { if (CheckInfested({ +HalfSide, OffsetY, OffsetZ }) || CheckInfested({ -HalfSide, OffsetY, OffsetZ })) { return true; } } } } return true; } ================================================ FILE: src/Mobs/Silverfish.h ================================================ #pragma once #include "AggressiveMonster.h" class cSilverfish: public cAggressiveMonster { using Super = cAggressiveMonster; public: cSilverfish(); CLASS_PROTODEF(cSilverfish) virtual bool DoTakeDamage(TakeDamageInfo & a_TDI) override; } ; ================================================ FILE: src/Mobs/Skeleton.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "Skeleton.h" #include "../World.h" #include "../Entities/ArrowEntity.h" #include "../ClientHandle.h" cSkeleton::cSkeleton(void) : Super("Skeleton", mtSkeleton, "entity.skeleton.hurt", "entity.skeleton.death", "entity.skeleton.ambient", 0.6f, 1.99f), m_ChargingBow(false) { } void cSkeleton::GetDrops(cItems & a_Drops, cEntity * a_Killer) { unsigned int LootingLevel = 0; if (a_Killer != nullptr) { LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting); } AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_ARROW); AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_BONE); AddRandomArmorDropItem(a_Drops, LootingLevel); AddRandomWeaponDropItem(a_Drops, LootingLevel); } void cSkeleton::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { Super::Tick(a_Dt, a_Chunk); if (!IsTicking()) { // The base class tick destroyed us return; } if (m_ChargingBow && (m_EMState == IDLE)) { // releasing bow if no more target is found m_ChargingBow = false; m_World->BroadcastEntityMetadata(*this); } } bool cSkeleton::Attack(std::chrono::milliseconds a_Dt) { StopMovingToPosition(); // Todo handle this in a better way, the skeleton does some uneeded recalcs due to inStateChasing auto & Random = GetRandomProvider(); if (!m_ChargingBow) { // updating pulling animation m_ChargingBow = true; m_World->BroadcastEntityMetadata(*this); } if ((GetTarget() != nullptr) && (m_AttackCoolDownTicksLeft == 0)) { Vector3d Inaccuracy = Vector3d(Random.RandReal(-0.25, 0.25), Random.RandReal(-0.25, 0.25), Random.RandReal(-0.25, 0.25)); Vector3d Speed = (GetTarget()->GetPosition() + Inaccuracy - GetPosition()) * 5; Speed.y += Random.RandInt(-1, 1); auto Arrow = std::make_unique(this, GetPosition().addedY(1), Speed); auto ArrowPtr = Arrow.get(); if (!ArrowPtr->Initialize(std::move(Arrow), *m_World)) { return false; } // releasing bow after arrow was shot m_ChargingBow = false; m_World->BroadcastEntityMetadata(*this); ResetAttackCooldown(); return true; } return false; } void cSkeleton::SpawnOn(cClientHandle & a_ClientHandle) { Super::SpawnOn(a_ClientHandle); a_ClientHandle.SendEntityEquipment(*this, 0, cItem(E_ITEM_BOW)); } ================================================ FILE: src/Mobs/Skeleton.h ================================================ #pragma once #include "AggressiveMonster.h" class cSkeleton: public cAggressiveMonster { using Super = cAggressiveMonster; public: cSkeleton(); CLASS_PROTODEF(cSkeleton) virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override; virtual bool Attack(std::chrono::milliseconds a_Dt) override; virtual void SpawnOn(cClientHandle & a_ClientHandle) override; virtual bool IsUndead(void) override { return true; } bool IsChargingBow() const { return m_ChargingBow; } private: bool m_ChargingBow; } ; ================================================ FILE: src/Mobs/Slime.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "Slime.h" #include "../FastRandom.h" #include "../World.h" cSlime::cSlime(int a_Size) : Super("Slime", mtSlime, fmt::format(FMT_STRING("entity.{}slime.hurt"), GetSizeName(a_Size)), fmt::format(FMT_STRING("entity.{}slime.death"), GetSizeName(a_Size)), "", 0.51f * a_Size, 0.51f * a_Size ), m_Size(a_Size) { SetMaxHealth(static_cast(a_Size * a_Size)); SetAttackDamage(a_Size); } void cSlime::GetDrops(cItems & a_Drops, cEntity * a_Killer) { unsigned int LootingLevel = 0; if (a_Killer != nullptr) { LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting); } // Only slimes with the size 1 can drop slimeballs. if (m_Size == 1) { AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_SLIMEBALL); } } bool cSlime::Attack(std::chrono::milliseconds a_Dt) { if (m_Size > 1) { // Only slimes larger than size 1 attack a player. return Super::Attack(a_Dt); } return false; } void cSlime::KilledBy(TakeDamageInfo & a_TDI) { if (GetHealth() > 0) { return; } if (m_Size != 1) { auto & Random = GetRandomProvider(); int SpawnAmount = Random.RandInt(2, 4); for (int i = 0; i < SpawnAmount; ++i) { double AddX = (i % 2 - 0.5) * m_Size / 4.0; double AddZ = (i / 2 - 0.5) * m_Size / 4.0; // Queue slimes to be spawned after the 1 second death animation has finished playing: m_World->ScheduleTask(cTickTime(20), [ Position = GetPosition() + Vector3d(AddX, 0.5, AddZ), Yaw = Random.RandReal(360.0f), Size = m_Size / 2 ](cWorld & a_World) { auto NewSlime = std::make_unique(Size); NewSlime->SetPosition(Position); NewSlime->SetYaw(Yaw); a_World.SpawnMobFinalize(std::move(NewSlime)); }); } } Super::KilledBy(a_TDI); } AString cSlime::GetSizeName(int a_Size) { if (a_Size == 1) { return "small_"; } return ""; } ================================================ FILE: src/Mobs/Slime.h ================================================ #pragma once #include "AggressiveMonster.h" class cSlime: public cAggressiveMonster { using Super = cAggressiveMonster; public: /** Creates a slime of the specified size; size can be 1, 2 or 4, with 1 is the smallest and 4 is the tallest. */ cSlime(int a_Size); CLASS_PROTODEF(cSlime) // cAggressiveMonster overrides: virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override; virtual bool Attack(std::chrono::milliseconds a_Dt) override; virtual void KilledBy(TakeDamageInfo & a_TDI) override; int GetSize(void) const { return m_Size; } /** Returns the text describing the slime's size, as used by the client's resource subsystem for sounds. Returns either "big" or "small". */ static AString GetSizeName(int a_Size); protected: /** Size of the slime, with 1 being the smallest. Vanilla uses sizes 1, 2 and 4 only. */ int m_Size; } ; ================================================ FILE: src/Mobs/SnowGolem.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "Chunk.h" #include "SnowGolem.h" #include "../BlockInfo.h" #include "../World.h" #include "../Entities/ThrownSnowballEntity.h" cSnowGolem::cSnowGolem(void) : Super("SnowGolem", mtSnowGolem, "entity.snowman.hurt", "entity.snowman.death", "entity.snowman.ambient", 0.7f, 1.9f) { } void cSnowGolem::GetDrops(cItems & a_Drops, cEntity * a_Killer) { UNUSED(a_Killer); AddRandomDropItem(a_Drops, 0, 15, E_ITEM_SNOWBALL); } void cSnowGolem::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { Super::Tick(a_Dt, a_Chunk); if (!IsTicking()) { // The base class tick destroyed us return; } PREPARE_REL_AND_CHUNK(GetPosition().Floor(), a_Chunk); if (!RelSuccess) { return; } if (IsBiomeNoDownfall(Chunk->GetBiomeAt(Rel.x, Rel.z))) { TakeDamage(dtEnvironment, nullptr, GetRawDamageAgainst(*this), GetKnockbackAmountAgainst(*this)); } else if (const auto Below = Rel.addedY(-1); Below.y >= 0) { if ((Chunk->GetBlock(Rel) == E_BLOCK_AIR) && cBlockInfo::IsSolid(Chunk->GetBlock(Below))) { Chunk->SetBlock(Rel, E_BLOCK_SNOW, 0); } } } bool cSnowGolem::Attack(std::chrono::milliseconds a_Dt) { UNUSED(a_Dt); // Comment inherited from skeletons StopMovingToPosition(); // Todo handle this in a better way, the snowman does some uneeded recalcs due to inStateChasing if ((GetTarget() != nullptr) && (m_AttackCoolDownTicksLeft == 0)) { auto & Random = GetRandomProvider(); Vector3d Inaccuracy = Vector3d(Random.RandReal(-0.75, 0.75), Random.RandReal(-0.75, 0.75), Random.RandReal(-0.75, 0.75)); // The projectile is launched from the head const auto HeadPos = GetPosition().addedY(1.5); // It aims around the head / chest const auto TargetPos = GetTarget()->GetPosition().addedY(GetTarget()->GetHeight() * 0.75); // With this data, we can calculate the speed const auto Speed = (TargetPos + Inaccuracy - HeadPos) * 5; auto Snowball = std::make_unique(this, HeadPos, Speed); auto SnowballPtr = Snowball.get(); if (!SnowballPtr->Initialize(std::move(Snowball), *GetWorld())) { return false; } ResetAttackCooldown(); return true; } return false; } ================================================ FILE: src/Mobs/SnowGolem.h ================================================ #pragma once #include "PassiveAggressiveMonster.h" class cSnowGolem: public cPassiveAggressiveMonster { using Super = cPassiveAggressiveMonster; public: cSnowGolem(); CLASS_PROTODEF(cSnowGolem) virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override; virtual bool Attack(std::chrono::milliseconds a_Dt) override; } ; ================================================ FILE: src/Mobs/Spider.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "Spider.h" #include "../World.h" #include "../Entities/Player.h" #include "../Chunk.h" cSpider::cSpider(void) : Super("Spider", mtSpider, "entity.spider.hurt", "entity.spider.death", "entity.spider.ambient", 1.4f, 0.9f) { } void cSpider::GetDrops(cItems & a_Drops, cEntity * a_Killer) { unsigned int LootingLevel = 0; if (a_Killer != nullptr) { LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting); } AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_STRING); if ((a_Killer != nullptr) && (a_Killer->IsPlayer() || a_Killer->IsA("cWolf"))) { AddRandomUncommonDropItem(a_Drops, 33.0f, E_ITEM_SPIDER_EYE); } } void cSpider::EventSeePlayer(cPlayer * a_Player, cChunk & a_Chunk) { if (!GetWorld()->IsChunkLighted(GetChunkX(), GetChunkZ())) { return; } PREPARE_REL_AND_CHUNK(GetPosition(), a_Chunk); if (!RelSuccess) { return; } if ((Chunk->GetSkyLightAltered(Rel.x, Rel.y, Rel.z) <= 11) && (Chunk->GetBlockLight(Rel.x, Rel.y, Rel.z) <= 11)) { Super::EventSeePlayer(a_Player, a_Chunk); } } bool cSpider::DoTakeDamage(TakeDamageInfo & a_TDI) { if (!Super::DoTakeDamage(a_TDI)) { return false; } // If the source of the damage is not from an pawn entity, switch to idle if ((a_TDI.Attacker == nullptr) || !a_TDI.Attacker->IsPawn()) { m_EMState = IDLE; } else { // If the source of the damage is from a pawn entity, chase that entity m_EMState = CHASING; } return true; } ================================================ FILE: src/Mobs/Spider.h ================================================ #pragma once #include "AggressiveMonster.h" class cSpider: public cAggressiveMonster { using Super = cAggressiveMonster; public: cSpider(); CLASS_PROTODEF(cSpider) virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override; virtual void EventSeePlayer(cPlayer *, cChunk & a_Chunk) override; virtual bool DoTakeDamage(TakeDamageInfo & a_TDI) override; } ; ================================================ FILE: src/Mobs/Squid.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "Squid.h" #include "../Chunk.h" cSquid::cSquid(void) : Super("Squid", mtSquid, "entity.squid.hurt", "entity.squid.death", "entity.squid.ambient", 0.8f, 0.8f) { } void cSquid::GetDrops(cItems & a_Drops, cEntity * a_Killer) { // Drops 0-3 Ink Sacs unsigned int LootingLevel = 0; if (a_Killer != nullptr) { LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting); } AddRandomDropItem(a_Drops, 0, 3 + LootingLevel, E_ITEM_DYE, E_META_DYE_BLACK); } void cSquid::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { m_PathfinderActivated = false; // Disable Pathfinding until it's fixed. TODO // We must first process current location, and only then tick, otherwise we risk processing a location in a chunk // that is not where the entity currently resides (FS #411) Vector3d Pos = GetPosition(); // TODO: Not a real behavior, but cool :D int RelY = FloorC(Pos.y); if ((RelY < 0) || (RelY >= cChunkDef::Height)) { return; } if (!IsHeadInWater()) { if (m_AirLevel <= 0) { // Runs the air tick timer to check whether the squid should be damaged if (m_AirTickTimer <= 0) { // Damage squid TakeDamage(dtSuffocating, nullptr, 1, 1, 0); // Reset timer m_AirTickTimer = DROWNING_TICKS; } else { m_AirTickTimer--; } } else { // Reduce air supply m_AirLevel--; } } else { // Set the air back to maximum m_AirLevel = MAX_AIR_LEVEL; m_AirTickTimer = DROWNING_TICKS; } Super::Tick(a_Dt, a_Chunk); } ================================================ FILE: src/Mobs/Squid.h ================================================ #pragma once #include "PassiveMonster.h" class cSquid: public cPassiveMonster { using Super = cPassiveMonster; public: cSquid(); virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; CLASS_PROTODEF(cSquid) virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override; // Squids do not drown (or float) virtual void HandleAir(void) override {} } ; ================================================ FILE: src/Mobs/Villager.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "Villager.h" #include "../World.h" #include "../BlockArea.h" #include "../Blocks/BlockHandler.h" #include "../BlockInServerPluginInterface.h" cVillager::cVillager(eVillagerType VillagerType) : Super("Villager", mtVillager, "entity.villager.hurt", "entity.villager.death", "entity.villager.ambient", 0.6f, 1.95f), m_ActionCountDown(-1), m_Type(VillagerType), m_FarmerAction(faIdling), m_Inventory(8, 1) { } bool cVillager::DoTakeDamage(TakeDamageInfo & a_TDI) { if (!Super::DoTakeDamage(a_TDI)) { return false; } if ((a_TDI.Attacker != nullptr) && a_TDI.Attacker->IsPlayer()) { if (GetRandomProvider().RandBool(1.0 / 6.0)) { m_World->BroadcastEntityAnimation(*this, EntityAnimation::VillagerShowsAnger); } } if (a_TDI.DamageType == dtLightning) { Destroy(); m_World->SpawnMob(GetPosX(), GetPosY(), GetPosZ(), mtWitch, false); return true; } return true; } void cVillager::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { Super::Tick(a_Dt, a_Chunk); if (!IsTicking()) { // The base class tick destroyed us return; } switch (m_Type) { case vtFarmer: { TickFarmer(); break; } } } void cVillager::KilledBy(TakeDamageInfo & a_TDI) { Super::KilledBy(a_TDI); // TODO: 0% chance on Easy, 50% chance on Normal and 100% chance on Hard if (GetRandomProvider().RandBool(0.5) && (a_TDI.Attacker != nullptr) && (a_TDI.Attacker->IsMob())) { eMonsterType MonsterType = (static_cast(a_TDI.Attacker)->GetMobType()); if ((MonsterType == mtZombie) || (MonsterType == mtZombieVillager)) { m_World->SpawnMob(GetPosX(), GetPosY(), GetPosZ(), mtZombieVillager, false); } } } //////////////////////////////////////////////////////////////////////////////// // Farmer functions: void cVillager::TickFarmer() { // Don't harvest crops if you must not if (!m_World->VillagersShouldHarvestCrops()) { return; } // This is to prevent undefined behaviors if (m_FinalDestination.y <= 0) { return; } if (!IsIdling()) { // Forcing the farmer to go to work spots. MoveToPosition(static_cast(m_CropsPos) + Vector3d(0.5, 0, 0.5)); // Forcing the farmer to look at the work spots. Vector3d Direction = (m_FinalDestination - (GetPosition() + Vector3d(0, 1.6, 0))); // We get the direction from the eyes of the farmer to the work spot. Direction.Normalize(); SetPitch(std::asin(-Direction.y) / M_PI * 180); } // Updating the timer if (m_ActionCountDown > -1) { m_ActionCountDown--; } // Searching for work in blocks where the farmer goes. if (IsHarvestable(m_FinalDestination.Floor())) { m_CropsPos = m_FinalDestination.Floor(); m_FarmerAction = faHarvesting; HandleFarmerTryHarvestCrops(); return; } else if (IsPlantable(m_FinalDestination.Floor()) && CanPlantCrops()) { m_CropsPos = m_FinalDestination.Floor(); m_FarmerAction = faPlanting; HandleFarmerTryPlaceCrops(); return; } else { m_FarmerAction = faIdling; // Returning to idling. } // Don't always try to do a special action. Each tick has 10% to do a special action. if (GetRandomProvider().RandBool(FARMER_SPECIAL_ACTION_CHANCE)) { ScanAreaForWork(); } } void cVillager::ScanAreaForWork() { auto Pos = GetPosition().Floor(); auto MinPos = Pos - FARMER_SCAN_CROPS_DIST; auto MaxPos = Pos + FARMER_SCAN_CROPS_DIST; // Read area to be checked for crops. cBlockArea Surrounding; Surrounding.Read( *m_World, MinPos, MaxPos ); for (int I = 0; I < FARMER_RANDOM_TICK_SPEED; I++) { for (int Y = MinPos.y; Y <= MaxPos.y; Y++) { // Pick random coordinates and check for crops. Vector3i CandidatePos(MinPos.x + m_World->GetTickRandomNumber(MaxPos.x - MinPos.x - 1), Y, MinPos.z + m_World->GetTickRandomNumber(MaxPos.z - MinPos.z - 1)); // A villager can harvest this. if (IsHarvestable(CandidatePos)) { m_CropsPos = CandidatePos; m_FarmerAction = faHarvesting; MoveToPosition(static_cast(m_CropsPos) + Vector3d(0.5, 0, 0.5)); return; } // A villager can plant this. else if (IsPlantable(CandidatePos) && CanPlantCrops()) { m_CropsPos = CandidatePos; m_FarmerAction = faHarvesting; MoveToPosition(static_cast(m_CropsPos) + Vector3d(0.5, 0, 0.5)); return; } } // for Y } // Repeat the proccess according to the random tick speed. } void cVillager::HandleFarmerTryHarvestCrops() { if (m_ActionCountDown > 0) { // The farmer is still on cooldown return; } // Harvest the crops if it is closer than 1 block. if ((GetPosition() - m_CropsPos).Length() < 1) { // Check if the blocks didn't change while the villager was walking to the coordinates. if (IsHarvestable(m_CropsPos)) { m_World->BroadcastSoundParticleEffect(EffectID::PARTICLE_BLOCK_BREAK, m_CropsPos, m_World->GetBlock(m_CropsPos)); m_World->DropBlockAsPickups(m_CropsPos, this, nullptr); // Applying 0.5 second cooldown. m_ActionCountDown = 10; } } } void cVillager::CheckForNearbyCrops() { // Search for adjacent crops constexpr std::array Directions = { Vector3i{0, 0, -1}, {0, 0, 1}, {1, 0, 0}, {-1, 0, 0} }; for (Vector3i Direction : Directions) { if (IsHarvestable(m_CropsPos + Direction)) { m_CropsPos += Direction; m_FarmerAction = faHarvesting; MoveToPosition(static_cast(m_CropsPos) + Vector3d(0.5, 0, 0.5)); return; } else if (IsPlantable(m_CropsPos + Direction) && CanPlantCrops()) { m_CropsPos += Direction; m_FarmerAction = faPlanting; MoveToPosition(static_cast(m_CropsPos) + Vector3d(0.5, 0, 0.5)); return; } } // There is no more work to do around the previous crops. m_FarmerAction = faIdling; } void cVillager::HandleFarmerTryPlaceCrops() { if ((GetPosition() - m_CropsPos).Length() > 1) { // The farmer is still to far from the final destination return; } if (m_ActionCountDown > 0) { // The farmer is still on cooldown return; } // Check if there is still farmland at the spot where the crops were. if (IsPlantable(m_CropsPos)) { // Finding the item to use to plant a crop int TargetSlot = -1; BLOCKTYPE CropBlockType = E_BLOCK_AIR; for (int I = 0; I < m_Inventory.GetWidth() && TargetSlot < 0; I++) { const cItem & Slot = m_Inventory.GetSlot(I); switch (Slot.m_ItemType) { case E_ITEM_SEEDS: { TargetSlot = I; CropBlockType = E_BLOCK_CROPS; break; } case E_ITEM_BEETROOT_SEEDS: { TargetSlot = I; CropBlockType = E_BLOCK_BEETROOTS; break; } case E_ITEM_POTATO: { TargetSlot = I; CropBlockType = E_BLOCK_POTATOES; break; } case E_ITEM_CARROT: { TargetSlot = I; CropBlockType = E_BLOCK_CARROTS; break; } default: { break; } } } // Removing item from villager inventory m_Inventory.RemoveOneItem(TargetSlot); // Placing crop block m_World->SetBlock(m_CropsPos, CropBlockType, 0); // Applying 1 second cooldown m_ActionCountDown = 20; // Try to do the same with adjacent crops. CheckForNearbyCrops(); } } bool cVillager::CanPlantCrops() { return m_Inventory.HasItems(cItem(E_ITEM_SEEDS)) || m_Inventory.HasItems(cItem(E_ITEM_BEETROOT_SEEDS)) || m_Inventory.HasItems(cItem(E_ITEM_POTATO)) || m_Inventory.HasItems(cItem(E_ITEM_CARROT)); } bool cVillager::IsBlockFarmable(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) { switch (a_BlockType) { case E_BLOCK_BEETROOTS: { // The crop must have fully grown up. return a_BlockMeta == 0x03; } case E_BLOCK_CROPS: case E_BLOCK_POTATOES: case E_BLOCK_CARROTS: { // The crop must have fully grown up. return a_BlockMeta == 0x07; } default: return false; } } bool cVillager::IsHarvestable(Vector3i a_CropsPos) { return IsBlockFarmable(m_World->GetBlock(a_CropsPos), m_World->GetBlockMeta(a_CropsPos)); } bool cVillager::IsPlantable(Vector3i a_CropsPos) { return (m_World->GetBlock(a_CropsPos.addedY(-1)) == E_BLOCK_FARMLAND) && (m_World->GetBlock(a_CropsPos) == E_BLOCK_AIR); } cVillager::eVillagerType cVillager::GetRandomProfession() { int Profession = GetRandomProvider().RandInt(cVillager::eVillagerType::vtMax - 1); return static_cast(Profession); } ================================================ FILE: src/Mobs/Villager.h ================================================ #pragma once #include "PassiveMonster.h" #include "../Blocks/ChunkInterface.h" #include "../Inventory.h" class cVillager: public cPassiveMonster { using Super = cPassiveMonster; public: enum eVillagerType { vtFarmer = 0, vtLibrarian = 1, vtPriest = 2, vtBlacksmith = 3, vtButcher = 4, vtGeneric = 5, vtMax } ; cVillager(eVillagerType VillagerType); CLASS_PROTODEF(cVillager) /** Returns a random Profession. */ static eVillagerType GetRandomProfession(); // cEntity overrides virtual bool DoTakeDamage(TakeDamageInfo & a_TDI) override; virtual void Tick (std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; virtual void KilledBy (TakeDamageInfo & a_TDI) override; // cVillager functions /** Returns the villager hidden inventory (8 slots). */ cItemGrid & GetInventory(void) { return m_Inventory; } const cItemGrid & GetInventory(void) const { return m_Inventory; } /** Returns true if the given blocktype are: crops, potatoes or carrots and they have full grown up. */ bool IsBlockFarmable(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta); /** Returns true if the block at the given location is a fully grown up crop. */ bool IsHarvestable(Vector3i a_CropsPos); /** Returns true if seeds can be planted at a given location. */ bool IsPlantable(Vector3i a_CropsPos); // Farmer functions enum eFarmerAction { faIdling, faPlanting, faHarvesting, } ; static const int FARMER_RANDOM_TICK_SPEED = 5; /** With 10% chance, it takes about 20 seconds to find a spot. */ static constexpr double FARMER_SPECIAL_ACTION_CHANCE = 0.1; /** This distance from the Villager makes for a 31x3x31 area. */ static constexpr Vector3i FARMER_SCAN_CROPS_DIST {15, 1, 15}; /** Tick function for farmers. */ void TickFarmer(); /** Searches in a 31x3x31 area to harvest crops or spaces to plant crops. If it found some it will navigate to them. */ void ScanAreaForWork(); /** Looks if the farmer has reached it's destination, and if it's still crops and the destination is closer then 1 block it will harvest them. */ void HandleFarmerTryHarvestCrops(); /** Looks if the farmer has reached it's destination, and if it's still non obstructed farmland and the destination is closer then 1 block it will plant crops. */ void HandleFarmerTryPlaceCrops(); /** Checking for harvesting or planting nearby crops */ void CheckForNearbyCrops(); /** Returns whether the farmer has crops in his inventory to plant. */ bool CanPlantCrops(); /** Returns whether the farmer is not working. */ bool IsIdling() { return m_FarmerAction == faIdling; } // Get and set functions. int GetVilType(void) const { return m_Type; } eFarmerAction GetFarmerAction(void) const { return m_FarmerAction; } private: int m_ActionCountDown; int m_Type; eFarmerAction m_FarmerAction; Vector3i m_CropsPos; cItemGrid m_Inventory; } ; ================================================ FILE: src/Mobs/Witch.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "Witch.h" #include "../FastRandom.h" cWitch::cWitch(void) : Super("Witch", mtWitch, "entity.witch.hurt", "entity.witch.death", "entity.witch.ambient", 0.6f, 1.95f) { } void cWitch::GetDrops(cItems & a_Drops, cEntity * a_Killer) { unsigned int LootingLevel = 0; if (a_Killer != nullptr) { LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting); } auto & r1 = GetRandomProvider(); int DropTypeCount = r1.RandInt(1, 3); for (int i = 0; i < DropTypeCount; i++) { int DropType = r1.RandInt(6); switch (DropType) { case 0: AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_GLASS_BOTTLE); break; case 1: AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_GLOWSTONE_DUST); break; case 2: AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_GUNPOWDER); break; case 3: AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_REDSTONE_DUST); break; case 4: AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_SPIDER_EYE); break; case 5: AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_STICK); break; case 6: AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_SUGAR); break; } } AddRandomWeaponDropItem(a_Drops, LootingLevel); } ================================================ FILE: src/Mobs/Witch.h ================================================ #pragma once #include "AggressiveMonster.h" class cWitch: public cAggressiveMonster { using Super = cAggressiveMonster; public: cWitch(); CLASS_PROTODEF(cWitch) virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override; bool IsAngry(void) const {return ((m_EMState == ATTACKING) || (m_EMState == CHASING)); } } ; ================================================ FILE: src/Mobs/Wither.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "Wither.h" #include "../World.h" #include "../Entities/Player.h" #include "../ClientHandle.h" #include "../CompositeChat.h" cWither::cWither(void) : Super("Wither", mtWither, "entity.wither.hurt", "entity.wither.death", "entity.wither.ambient", 0.9f, 3.5f), m_WitherInvulnerableTicks(220) { SetMaxHealth(300); SetHealth(GetMaxHealth() / 3); } bool cWither::IsArmored(void) const { return GetHealth() <= (GetMaxHealth() / 2); } bool cWither::DoTakeDamage(TakeDamageInfo & a_TDI) { if (a_TDI.DamageType == dtDrowning) { return false; } if (m_WitherInvulnerableTicks > 0) { return false; } if (IsArmored() && (a_TDI.DamageType == dtRangedAttack)) { return false; } if (!Super::DoTakeDamage(a_TDI)) { return false; } m_World->BroadcastBossBarUpdateHealth(*this, GetUniqueID(), GetHealth() / GetMaxHealth()); return true; } void cWither::GetDrops(cItems & a_Drops, cEntity * a_Killer) { AddRandomDropItem(a_Drops, 1, 1, E_ITEM_NETHER_STAR); } void cWither::KilledBy(TakeDamageInfo & a_TDI) { Super::KilledBy(a_TDI); Vector3d Pos = GetPosition(); m_World->ForEachPlayer([=](cPlayer & a_Player) { // TODO 2014-05-21 xdot: Vanilla minecraft uses an AABB check instead of a radius one double Dist = (a_Player.GetPosition() - Pos).Length(); if (Dist < 50.0) { // If player is close, award achievement a_Player.AwardAchievement(CustomStatistic::AchKillWither); } return false; } ); } void cWither::SpawnOn(cClientHandle & a_Client) { Super::SpawnOn(a_Client); // Purple boss bar with no divisions that darkens the sky: a_Client.SendBossBarAdd(GetUniqueID(), cCompositeChat("Wither"), GetHealth() / GetMaxHealth(), BossBarColor::Purple, BossBarDivisionType::None, true, false, false); } void cWither::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { Super::Tick(a_Dt, a_Chunk); if (!IsTicking()) { // The base class tick destroyed us return; } if (m_WitherInvulnerableTicks > 0) { unsigned int NewTicks = m_WitherInvulnerableTicks - 1; if (NewTicks == 0) { m_World->DoExplosionAt(7.0, GetPosX(), GetPosY(), GetPosZ(), false, esWitherBirth, this); } m_WitherInvulnerableTicks = NewTicks; if ((NewTicks % 10) == 0) { Heal(10); } } m_World->BroadcastEntityMetadata(*this); } ================================================ FILE: src/Mobs/Wither.h ================================================ #pragma once #include "AggressiveMonster.h" class cWither: public cAggressiveMonster { using Super = cAggressiveMonster; public: cWither(); CLASS_PROTODEF(cWither) unsigned int GetWitherInvulnerableTicks(void) const { return m_WitherInvulnerableTicks; } void SetWitherInvulnerableTicks(unsigned int a_Ticks) { m_WitherInvulnerableTicks = a_Ticks; } /** Returns whether the wither is invulnerable to arrows. */ bool IsArmored(void) const; // cEntity overrides virtual bool DoTakeDamage(TakeDamageInfo & a_TDI) override; virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override; virtual bool IsUndead(void) override { return true; } virtual void KilledBy(TakeDamageInfo & a_TDI) override; virtual void SpawnOn(cClientHandle & a_Client) override; virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; private: /** The number of ticks of invulnerability left after being initially created. Zero once invulnerability has expired. */ unsigned int m_WitherInvulnerableTicks; } ; ================================================ FILE: src/Mobs/WitherSkeleton.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "WitherSkeleton.h" #include "../World.h" #include "../ClientHandle.h" cWitherSkeleton::cWitherSkeleton(void) : Super("WitherSkeleton", mtWitherSkeleton, "entity.wither_skeleton.hurt", "entity.wither_skeleton.death", "entity.wither_skeleton.ambient", 0.7f, 2.4f) { } bool cWitherSkeleton::Attack(std::chrono::milliseconds a_Dt) { if (GetTarget() == nullptr) { return false; } GetTarget()->AddEntityEffect(cEntityEffect::effWither, 200, 0); return Super::Attack(a_Dt); } void cWitherSkeleton::GetDrops(cItems & a_Drops, cEntity * a_Killer) { unsigned int LootingLevel = 0; if (a_Killer != nullptr) { LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting); } AddRandomUncommonDropItem(a_Drops, 33.0f, E_ITEM_COAL); AddRandomUncommonDropItem(a_Drops, 8.5f, E_ITEM_STONE_SWORD, GetRandomProvider().RandInt(50)); cItems RareDrops; RareDrops.Add(cItem(E_ITEM_HEAD, 1, 1)); AddRandomRareDropItem(a_Drops, RareDrops, LootingLevel); AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_BONE); AddRandomArmorDropItem(a_Drops, LootingLevel); AddRandomWeaponDropItem(a_Drops, LootingLevel); } void cWitherSkeleton::SpawnOn(cClientHandle & a_ClientHandle) { Super::SpawnOn(a_ClientHandle); a_ClientHandle.SendEntityEquipment(*this, 0, cItem(E_ITEM_STONE_SWORD)); } ================================================ FILE: src/Mobs/WitherSkeleton.h ================================================ #pragma once #include "AggressiveMonster.h" class cWitherSkeleton: public cAggressiveMonster { using Super = cAggressiveMonster; public: cWitherSkeleton(); CLASS_PROTODEF(cWitherSkeleton) private: virtual bool Attack(std::chrono::milliseconds a_Dt) override; virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override; virtual bool IsNetherNative(void) override { return true; } virtual void SpawnOn(cClientHandle & a_ClientHandle) override; } ; ================================================ FILE: src/Mobs/Wolf.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "Wolf.h" #include "../World.h" #include "../Entities/Player.h" #include "../Items/ItemHandler.h" #include "../Items/ItemSpawnEgg.h" cWolf::cWolf(void) : Super("Wolf", mtWolf, "entity.wolf.hurt", "entity.wolf.death", "entity.wolf.ambient", 0.6f, 0.85f), m_IsSitting(false), m_IsTame(false), m_IsBegging(false), m_IsAngry(false), m_CollarColor(E_META_DYE_ORANGE), m_NotificationCooldown(0) { } bool cWolf::DoTakeDamage(TakeDamageInfo & a_TDI) { cPawn * PreviousTarget = GetTarget(); if (!Super::DoTakeDamage(a_TDI)) { return false; } if ((a_TDI.Attacker != nullptr) && a_TDI.Attacker->IsPawn()) { auto currTarget = GetTarget(); if ((currTarget != nullptr) && currTarget->IsPlayer()) { if (m_IsTame) { if ((static_cast(currTarget)->GetUUID() == m_OwnerUUID)) { SetTarget(PreviousTarget); // Do not attack owner } else { SetIsSitting(false); NotifyAlliesOfFight(static_cast(a_TDI.Attacker)); } } else { m_IsAngry = true; } } else if (m_IsTame) { SetIsSitting(false); NotifyAlliesOfFight(static_cast(a_TDI.Attacker)); } } m_World->BroadcastEntityMetadata(*this); // Broadcast health and possibly angry face return true; } void cWolf::NotifyAlliesOfFight(cPawn * a_Opponent) { if (GetOwnerName() == "") { return; } m_NotificationCooldown = 15; m_World->DoWithPlayerByUUID(m_OwnerUUID, [=](cPlayer & a_Player) { a_Player.NotifyNearbyWolves(a_Opponent, false); return false; } ); } bool cWolf::Attack(std::chrono::milliseconds a_Dt) { UNUSED(a_Dt); if ((GetTarget() != nullptr) && (GetTarget()->IsPlayer())) { if (static_cast(GetTarget())->GetUUID() == m_OwnerUUID) { SetTarget(nullptr); return false; } } NotifyAlliesOfFight(static_cast(GetTarget())); return Super::Attack(a_Dt); } void cWolf::ReceiveNearbyFightInfo(const cUUID & a_PlayerID, cPawn * a_Opponent, bool a_IsPlayerInvolved) { if ( (a_Opponent == nullptr) || IsSitting() || (!IsTame()) || (!a_Opponent->IsPawn()) || (a_PlayerID != m_OwnerUUID) ) { return; } // If we already have a target if (GetTarget() != nullptr) { // If a wolf is asking for help and we already have a target, do nothing if (!a_IsPlayerInvolved) { return; } // If a player is asking for help and we already have a target, // there's a 50% chance of helping and a 50% chance of doing nothing // This helps spread a wolf pack's targets over several mobs else if (GetRandomProvider().RandBool()) { return; } } if (a_Opponent->IsPlayer() && static_cast(a_Opponent)->GetUUID() == m_OwnerUUID) { return; // Our owner has hurt himself, avoid attacking them. } if (a_Opponent->IsMob() && static_cast(a_Opponent)->GetMobType() == mtWolf) { cWolf * Wolf = static_cast(a_Opponent); if (Wolf->GetOwnerUUID() == GetOwnerUUID()) { return; // Our owner attacked one of their wolves. Abort attacking wolf. } } SetTarget(a_Opponent); } void cWolf::OnRightClicked(cPlayer & a_Player) { cMonster::OnRightClicked(a_Player); const cItem & EquippedItem = a_Player.GetEquippedItem(); const int EquippedItemType = EquippedItem.m_ItemType; if (!IsTame() && !IsAngry()) { // If the player is holding a bone, try to tame the wolf: if (EquippedItemType == E_ITEM_BONE) { if (!a_Player.IsGameModeCreative()) { a_Player.GetInventory().RemoveOneEquippedItem(); } if (GetRandomProvider().RandBool(0.125)) { // Taming succeeded SetMaxHealth(20); SetIsTame(true); SetOwner(a_Player.GetName(), a_Player.GetUUID()); m_World->BroadcastEntityAnimation(*this, EntityAnimation::WolfTamingSucceeds); } else { // Taming failed m_World->BroadcastEntityAnimation(*this, EntityAnimation::WolfTamingFails); } } } else if (IsTame()) { if (a_Player.GetUUID() == m_OwnerUUID) { cMonster::RightClickFeed(a_Player); } // Feed the wolf, restoring its health, or dye its collar: switch (EquippedItemType) { case E_ITEM_RAW_BEEF: case E_ITEM_STEAK: case E_ITEM_RAW_PORKCHOP: case E_ITEM_COOKED_PORKCHOP: case E_ITEM_RAW_CHICKEN: case E_ITEM_COOKED_CHICKEN: case E_ITEM_ROTTEN_FLESH: case E_ITEM_RAW_MUTTON: case E_ITEM_RAW_RABBIT: case E_ITEM_COOKED_RABBIT: case E_ITEM_COOKED_MUTTON: { if (m_Health < m_MaxHealth) { Heal(EquippedItem.GetHandler().GetFoodInfo(&EquippedItem).FoodLevel); if (!a_Player.IsGameModeCreative()) { a_Player.GetInventory().RemoveOneEquippedItem(); } } else if (a_Player.GetUUID() == m_OwnerUUID) // Is the player the owner of the dog? { if (IsBaby()) { m_AgingTimer = FloorC(m_AgingTimer * 0.9); } } break; } case E_ITEM_DYE: { if (a_Player.GetUUID() == m_OwnerUUID) // Is the player the owner of the dog? { SetCollarColor(EquippedItem.m_ItemDamage); if (!a_Player.IsGameModeCreative()) { a_Player.GetInventory().RemoveOneEquippedItem(); } } break; } // Multiplication is handled in cMonster. Just prevents from sitting down. case E_ITEM_SPAWN_EGG: { break; } default: { if (a_Player.GetUUID() == m_OwnerUUID) // Is the player the owner of the dog? { SetIsSitting(!IsSitting()); } } } } if ((EquippedItemType == E_ITEM_SPAWN_EGG) && (!IsTame())) { eMonsterType MonsterType = cItemSpawnEggHandler::ItemDamageToMonsterType(EquippedItem.m_ItemDamage); if ( (MonsterType == m_MobType) && (m_World->SpawnMob(GetPosX(), GetPosY(), GetPosZ(), m_MobType, true) != cEntity::INVALID_ID)) // Spawning succeeded { if (!a_Player.IsGameModeCreative()) { // The mob was spawned, "use" the item: a_Player.GetInventory().RemoveOneEquippedItem(); } } } m_World->BroadcastEntityMetadata(*this); } void cWolf::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { if (!IsAngry()) { cMonster::Tick(a_Dt, a_Chunk); if (m_NotificationCooldown > 0) { m_NotificationCooldown -= 1; } } else { Super::Tick(a_Dt, a_Chunk); } if (!IsTicking()) { // The base class tick destroyed us return; } if (GetTarget() == nullptr) { m_World->DoWithNearestPlayer(GetPosition(), static_cast(m_SightDistance), [&](cPlayer & a_Player) -> bool { switch (a_Player.GetEquippedItem().m_ItemType) { case E_ITEM_BONE: case E_ITEM_RAW_BEEF: case E_ITEM_STEAK: case E_ITEM_RAW_CHICKEN: case E_ITEM_COOKED_CHICKEN: case E_ITEM_ROTTEN_FLESH: case E_ITEM_RAW_PORKCHOP: case E_ITEM_COOKED_PORKCHOP: { if (!IsBegging()) { SetIsBegging(true); m_World->BroadcastEntityMetadata(*this); } m_FinalDestination = a_Player.GetPosition(); // So that we will look at a player holding food // Don't move to the player if the wolf is sitting. if (!IsSitting()) { MoveToPosition(a_Player.GetPosition()); } break; } default: { if (IsBegging()) { SetIsBegging(false); m_World->BroadcastEntityMetadata(*this); } } } return true; }); } else { if (IsSitting()) { SetTarget(nullptr); } else { MoveToPosition(GetTarget()->GetPosition()); if (TargetIsInRange()) { Attack(a_Dt); } } } if (IsTame() && !IsSitting()) { TickFollowPlayer(); } else if (IsSitting()) { StopMovingToPosition(); } cMonster::LoveTick(); } void cWolf::TickFollowPlayer() { Vector3d OwnerPos; bool OwnerFlying; auto Callback = [&](cPlayer & a_Player) { OwnerPos = a_Player.GetPosition(); OwnerFlying = a_Player.IsFlying(); return true; }; if (m_World->DoWithPlayerByUUID(m_OwnerUUID, Callback)) { // The player is present in the world, follow him: double Distance = (OwnerPos - GetPosition()).Length(); if (Distance > 20) { if (!OwnerFlying) { OwnerPos.y = FindFirstNonAirBlockPosition(OwnerPos.x, OwnerPos.z); TeleportToCoords(OwnerPos.x, OwnerPos.y, OwnerPos.z); SetTarget(nullptr); } } if (Distance < 2) { if (GetTarget() == nullptr) { StopMovingToPosition(); } } else { if (GetTarget() == nullptr) { if (!OwnerFlying) { MoveToPosition(OwnerPos); } } } } } void cWolf::InStateIdle(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { if (!IsTame()) { cMonster::InStateIdle(a_Dt, a_Chunk); } } void cWolf::InheritFromParents(cMonster * a_Parent1, cMonster * a_Parent2) { const auto Parent1 = static_cast(a_Parent1); const auto Parent2 = static_cast(a_Parent2); if (Parent1->GetOwnerUUID() == Parent2->GetOwnerUUID()) { SetOwner(Parent1->GetOwnerName(), Parent2->GetOwnerUUID()); } else { auto Parent1Age = Parent1->GetAge(); auto Parent2Age = Parent2->GetAge(); if (Parent1Age > Parent2Age) { SetOwner(Parent2->GetOwnerName(), Parent2->GetOwnerUUID()); } else { SetOwner(Parent1->GetOwnerName(), Parent1->GetOwnerUUID()); } } } ================================================ FILE: src/Mobs/Wolf.h ================================================ #pragma once #include "PassiveAggressiveMonster.h" #include "../UUID.h" class cEntity; class cWolf: public cPassiveAggressiveMonster { using Super = cPassiveAggressiveMonster; public: cWolf(); CLASS_PROTODEF(cWolf) void NotifyAlliesOfFight(cPawn * a_Opponent); virtual bool DoTakeDamage(TakeDamageInfo & a_TDI) override; virtual void OnRightClicked(cPlayer & a_Player) override; virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; virtual void TickFollowPlayer(); virtual bool Attack(std::chrono::milliseconds a_Dt) override; // Get functions bool IsSitting (void) const override { return m_IsSitting; } bool IsTame (void) const override { return m_IsTame; } bool IsBegging (void) const { return m_IsBegging; } bool IsAngry (void) const { return m_IsAngry; } AString GetOwnerName (void) const { return m_OwnerName; } cUUID GetOwnerUUID (void) const { return m_OwnerUUID; } int GetCollarColor(void) const { return m_CollarColor; } // Set functions void SetIsSitting (bool a_IsSitting) { m_IsSitting = a_IsSitting; } void SetIsTame (bool a_IsTame) { m_IsTame = a_IsTame; } void SetIsBegging (bool a_IsBegging) { m_IsBegging = a_IsBegging; } void SetIsAngry (bool a_IsAngry) { m_IsAngry = a_IsAngry; } void SetCollarColor(int a_CollarColor) { m_CollarColor = a_CollarColor; } void SetOwner (const AString & a_NewOwnerName, const cUUID & a_NewOwnerUUID) { m_OwnerName = a_NewOwnerName; m_OwnerUUID = a_NewOwnerUUID; } /** Notfies the wolf of a nearby fight. The wolf may then decide to attack a_Opponent. If a_IsPlayerInvolved is true, then the player whose UUID is a_PlayerUUID is fighting a_Opponent If false, then a wolf owned by the player whose UUID is a_PlayerUUID is fighting a_Opponent @param a_PlayerUUID The UUID of the fighting player, or the UUID of the owner whose wolf is fighting. @param a_Opponent The opponent who is being faught. @param a_IsPlayerInvolved Whether the fighter a player or a wolf. */ void ReceiveNearbyFightInfo(const cUUID & a_PlayerUUID, cPawn * a_Opponent, bool a_IsPlayerInvolved); virtual void InStateIdle(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; virtual void InheritFromParents(cMonster * a_Parent1, cMonster * a_Parent2) override; virtual void GetBreedingItems(cItems & a_Items) override { a_Items.Add(E_ITEM_RAW_BEEF); a_Items.Add(E_ITEM_STEAK); a_Items.Add(E_ITEM_RAW_PORKCHOP); a_Items.Add(E_ITEM_COOKED_PORKCHOP); a_Items.Add(E_ITEM_RAW_CHICKEN); a_Items.Add(E_ITEM_COOKED_CHICKEN); a_Items.Add(E_ITEM_RAW_MUTTON); a_Items.Add(E_ITEM_COOKED_MUTTON); a_Items.Add(E_ITEM_RAW_RABBIT); a_Items.Add(E_ITEM_COOKED_RABBIT); a_Items.Add(E_ITEM_ROTTEN_FLESH); } protected: bool m_IsSitting; bool m_IsTame; bool m_IsBegging; bool m_IsAngry; AString m_OwnerName; cUUID m_OwnerUUID; int m_CollarColor; int m_NotificationCooldown; } ; ================================================ FILE: src/Mobs/Zombie.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "Zombie.h" #include "../World.h" #include "../LineBlockTracer.h" cZombie::cZombie() : Super("Zombie", mtZombie, "entity.zombie.hurt", "entity.zombie.death", "entity.zombie.ambient", 0.6f, 1.95f) { } void cZombie::GetDrops(cItems & a_Drops, cEntity * a_Killer) { unsigned int LootingLevel = 0; if (a_Killer != nullptr) { LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting); } AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_ROTTEN_FLESH); cItems RareDrops; RareDrops.Add(cItem(E_ITEM_IRON)); RareDrops.Add(cItem(E_ITEM_CARROT)); RareDrops.Add(cItem(E_ITEM_POTATO)); AddRandomRareDropItem(a_Drops, RareDrops, LootingLevel); AddRandomArmorDropItem(a_Drops, LootingLevel); AddRandomWeaponDropItem(a_Drops, LootingLevel); } ================================================ FILE: src/Mobs/Zombie.h ================================================ #pragma once #include "AggressiveMonster.h" class cZombie: public cAggressiveMonster { using Super = cAggressiveMonster; public: cZombie(); CLASS_PROTODEF(cZombie) virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override; virtual bool IsUndead(void) override { return true; } } ; ================================================ FILE: src/Mobs/ZombiePigman.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "ZombiePigman.h" #include "../World.h" #include "../ClientHandle.h" cZombiePigman::cZombiePigman(void) : Super("ZombiePigman", mtZombiePigman, "entity.zombie_pig.hurt", "entity.zombie_pig.death", "entity.zombie_pig.ambient", 0.6f, 1.95f) { } void cZombiePigman::GetDrops(cItems & a_Drops, cEntity * a_Killer) { unsigned int LootingLevel = 0; if (a_Killer != nullptr) { LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting); } AddRandomDropItem(a_Drops, 0, 1 + LootingLevel, E_ITEM_ROTTEN_FLESH); AddRandomDropItem(a_Drops, 0, 1 + LootingLevel, E_ITEM_GOLD_NUGGET); cItems RareDrops; RareDrops.Add(cItem(E_ITEM_GOLD)); AddRandomRareDropItem(a_Drops, RareDrops, LootingLevel); AddRandomArmorDropItem(a_Drops, LootingLevel); AddRandomWeaponDropItem(a_Drops, LootingLevel); } void cZombiePigman::KilledBy(TakeDamageInfo & a_TDI) { Super::KilledBy(a_TDI); if ((a_TDI.Attacker != nullptr) && (a_TDI.Attacker->IsPlayer())) { // TODO: Anger all nearby zombie pigmen // TODO: In vanilla, if one player angers ZPs, do they attack any nearby player, or only that one attacker? } } void cZombiePigman::SpawnOn(cClientHandle & a_ClientHandle) { Super::SpawnOn(a_ClientHandle); a_ClientHandle.SendEntityEquipment(*this, 0, cItem(E_ITEM_GOLD_SWORD)); } ================================================ FILE: src/Mobs/ZombiePigman.h ================================================ #pragma once #include "PassiveAggressiveMonster.h" class cZombiePigman: public cPassiveAggressiveMonster { using Super = cPassiveAggressiveMonster; public: cZombiePigman(); CLASS_PROTODEF(cZombiePigman) private: virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override; virtual bool IsUndead(void) override { return true; } virtual bool IsNetherNative(void) override { return true; } virtual void KilledBy(TakeDamageInfo & a_TDI) override; virtual void SpawnOn(cClientHandle & a_ClientHandle) override; } ; ================================================ FILE: src/Mobs/ZombieVillager.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "ZombieVillager.h" #include "../World.h" #include "../LineBlockTracer.h" #include "../Entities/Player.h" cZombieVillager::cZombieVillager(cVillager::eVillagerType a_Profession) : Super("ZombieVillager", mtZombieVillager, "entity.zombie_villager.hurt", "entity.zombie_villager.death", "entity.ambient", 0.6f, 1.95f), m_ConversionTime(-1), m_Profession(a_Profession) { SetBurnsInDaylight(true); } void cZombieVillager::GetDrops(cItems & a_Drops, cEntity * a_Killer) { unsigned int LootingLevel = 0; if (a_Killer != nullptr) { LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting); } AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_ROTTEN_FLESH); cItems RareDrops; RareDrops.Add(cItem(E_ITEM_IRON)); RareDrops.Add(cItem(E_ITEM_CARROT)); RareDrops.Add(cItem(E_ITEM_POTATO)); AddRandomRareDropItem(a_Drops, RareDrops, LootingLevel); AddRandomArmorDropItem(a_Drops, LootingLevel); AddRandomWeaponDropItem(a_Drops, LootingLevel); } void cZombieVillager::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { Super::Tick(a_Dt, a_Chunk); if (!IsTicking()) { // The base class tick destroyed us return; } LOGD("Conversion time: %d", m_ConversionTime); if (m_ConversionTime == 0) { m_World->BroadcastSoundEffect("entity.zombie_villager.cure", GetPosition(), 1.0f, 1.0f); Destroy(); m_World->SpawnMob(GetPosX(), GetPosY(), GetPosZ(), mtVillager, false); } else if (m_ConversionTime > 0) { m_ConversionTime--; } } void cZombieVillager::OnRightClicked(cPlayer & a_Player) { Super::OnRightClicked(a_Player); const cItem & EquippedItem = a_Player.GetEquippedItem(); if ((EquippedItem.m_ItemType == E_ITEM_GOLDEN_APPLE) && GetEntityEffect(cEntityEffect::effWeakness) != nullptr) { if (!a_Player.IsGameModeCreative()) { a_Player.GetInventory().RemoveOneEquippedItem(); } m_ConversionTime = 6000; } } ================================================ FILE: src/Mobs/ZombieVillager.h ================================================ #pragma once #include "AggressiveMonster.h" #include "Villager.h" class cZombieVillager: public cAggressiveMonster { using Super = cAggressiveMonster; public: cZombieVillager(cVillager::eVillagerType a_Profession); CLASS_PROTODEF(cZombieVillager) virtual void GetDrops (cItems & a_Drops, cEntity * a_Killer = nullptr) override; virtual void Tick (std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; virtual void OnRightClicked (cPlayer & a_Player) override; virtual bool IsUndead (void) override { return true; } int ConversionTime (void) const { return m_ConversionTime; } cVillager::eVillagerType GetProfession (void) const { return m_Profession; } private: int m_ConversionTime; cVillager::eVillagerType m_Profession; } ; ================================================ FILE: src/MonsterConfig.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "MonsterConfig.h" #include "Mobs/Monster.h" #include "IniFile.h" struct cMonsterConfig::sAttributesStruct { AString m_Name; int m_SightDistance; int m_AttackDamage; double m_AttackRange; double m_AttackRate; double m_MaxHealth; double m_BaseWalkSpeed; double m_BaseRunSpeed; bool m_IsFireproof; bool m_BurnsInDaylight; }; struct cMonsterConfig::sMonsterConfigState { AString MonsterTypes; std::list< sAttributesStruct > AttributesList; }; cMonsterConfig::cMonsterConfig(void) : m_pState( new sMonsterConfigState) { Initialize(); } cMonsterConfig::~cMonsterConfig() { delete m_pState; m_pState = nullptr; } void cMonsterConfig::Initialize() { cIniFile MonstersIniFile; if (!MonstersIniFile.ReadFile("monsters.ini")) { LOGWARNING("%s: Cannot read monsters.ini file, monster attributes not available", __FUNCTION__); return; } for (int i = static_cast(MonstersIniFile.GetNumKeys()); i >= 0; i--) { sAttributesStruct Attributes; AString Name = MonstersIniFile.GetKeyName(i); Attributes.m_Name = Name; Attributes.m_AttackDamage = MonstersIniFile.GetValueI(Name, "AttackDamage", 0); Attributes.m_AttackRange = MonstersIniFile.GetValueI(Name, "AttackRange", 0); Attributes.m_SightDistance = MonstersIniFile.GetValueI(Name, "SightDistance", 0); Attributes.m_AttackRate = MonstersIniFile.GetValueF(Name, "AttackRate", 0); Attributes.m_MaxHealth = MonstersIniFile.GetValueF(Name, "MaxHealth", 1); Attributes.m_BaseWalkSpeed = MonstersIniFile.GetValueF(Name, "WalkSpeed", 1); Attributes.m_BaseRunSpeed = MonstersIniFile.GetValueF(Name, "RunSpeed", Attributes.m_BaseWalkSpeed); Attributes.m_IsFireproof = MonstersIniFile.GetValueB(Name, "IsFireproof", false); Attributes.m_BurnsInDaylight = MonstersIniFile.GetValueB(Name, "BurnsInDaylight", false); m_pState->AttributesList.push_front(Attributes); } // for i - SplitList[] } void cMonsterConfig::AssignAttributes(cMonster * a_Monster, const AString & a_Name) { std::list::const_iterator itr; for (itr = m_pState->AttributesList.begin(); itr != m_pState->AttributesList.end(); ++itr) { if (itr->m_Name.compare(a_Name) == 0) { a_Monster->SetAttackDamage (itr->m_AttackDamage); a_Monster->SetAttackRange (itr->m_AttackRange); a_Monster->SetSightDistance (itr->m_SightDistance); a_Monster->SetAttackRate (static_cast(itr->m_AttackRate)); a_Monster->SetMaxHealth (static_cast(itr->m_MaxHealth)); a_Monster->SetBaseWalkSpeed (itr->m_BaseWalkSpeed); a_Monster->SetBaseRunSpeed (itr->m_BaseRunSpeed); a_Monster->SetIsFireproof (itr->m_IsFireproof); a_Monster->SetBurnsInDaylight(itr->m_BurnsInDaylight); return; } } // for itr - m_pState->AttributesList[] } ================================================ FILE: src/MonsterConfig.h ================================================ #pragma once // fwd: class cMonster; class cMonsterConfig { public: cMonsterConfig(void); ~cMonsterConfig(); void AssignAttributes(cMonster * a_Monster, const AString & a_Name); private: struct sAttributesStruct; struct sMonsterConfigState; sMonsterConfigState * m_pState; void Initialize(); } ; ================================================ FILE: src/NetherPortalScanner.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "NetherPortalScanner.h" #include "BlockInfo.h" #include "Entities/Entity.h" #include "World.h" const double cNetherPortalScanner::OutOffset = 0.5; const double cNetherPortalScanner::AcrossOffset = 0.5; cNetherPortalScanner::cNetherPortalScanner(cEntity & a_MovingEntity, cWorld & a_DestinationWorld, Vector3d a_DestPosition, int a_MaxY) : m_EntityID(a_MovingEntity.GetUniqueID()), m_SourceWorld(*a_MovingEntity.GetWorld()), m_World(a_DestinationWorld), m_FoundPortal(false), m_BuildPlatform(true), m_Dir(Direction::X), m_PortalLoc(a_DestPosition.Floor()), m_Position(a_DestPosition), m_MaxY(a_MaxY) { int MinX = FloorC((m_Position.x - SearchRadius) / cChunkDef::Width); int MinZ = FloorC((m_Position.z - SearchRadius) / cChunkDef::Width); int MaxX = CeilC((m_Position.x + SearchRadius) / cChunkDef::Width); int MaxZ = CeilC((m_Position.z + SearchRadius) / cChunkDef::Width); for (int x = MinX; x < MaxX; x++) { for (int z = MinZ; z < MaxZ; z++) { Add(x, z); } } Enable(*a_DestinationWorld.GetChunkMap()); } void cNetherPortalScanner::OnChunkAvailable(int a_ChunkX, int a_ChunkZ) { class PortalSearchCallback : public cChunkDataCallback { public: PortalSearchCallback(const int a_ChunkX, const int a_ChunkZ, bool & a_FoundPortal, Vector3i & a_PortalLoc, const Vector3d a_Position, const int a_MaxY) : m_ChunkX(a_ChunkX), m_ChunkZ(a_ChunkZ), m_FoundPortal(a_FoundPortal), m_PortalLoc(a_PortalLoc), m_Position(a_Position), m_MaxY(a_MaxY) { } private: virtual void ChunkData(const ChunkBlockData & a_BlockData, const ChunkLightData &) override { for (size_t Y = 0; Y < cChunkDef::NumSections; ++Y) { const auto Blocks = a_BlockData.GetSection(Y); if (Blocks == nullptr) { continue; } // Iterate through all of the blocks in the chunk: for (size_t i = 0; i < ChunkBlockData::SectionBlockCount; i++) { if ((*Blocks)[i] != E_BLOCK_NETHER_PORTAL) { continue; } Vector3i Coordinate = cChunkDef::IndexToCoordinate(i + Y * ChunkBlockData::SectionBlockCount); if (Coordinate.y >= m_MaxY) { // This is above the map, don't consider it: continue; } Vector3d PortalLoc = Vector3d(Coordinate.x + m_ChunkX * cChunkDef::Width, Coordinate.y, Coordinate.z + m_ChunkZ * cChunkDef::Width); if (!m_FoundPortal) { m_FoundPortal = true; m_PortalLoc = PortalLoc; } else if ((PortalLoc - m_Position).SqrLength() < (m_PortalLoc - m_Position).SqrLength()) { // Found a closer portal, use that instead: m_PortalLoc = PortalLoc; } } } } int m_ChunkX, m_ChunkZ; bool & m_FoundPortal; Vector3i & m_PortalLoc; const Vector3d m_Position; const int m_MaxY; } Callback(a_ChunkX, a_ChunkZ, m_FoundPortal, m_PortalLoc, m_Position, m_MaxY); [[maybe_unused]] const bool Result = m_World.GetChunkData({ a_ChunkX, a_ChunkZ }, Callback); ASSERT(Result); } bool cNetherPortalScanner::IsValidBuildLocation(Vector3i a_BlockPos) { // Check the base for (int i = 0; i < SearchSolidBaseWidth; i++) { for (int j = 0; j < PortalLength; j++) { BLOCKTYPE blocktype = m_World.GetBlock(a_BlockPos.addedXZ(i, j)); if (!cBlockInfo::IsSolid(blocktype)) { return false; } // Check the airspace for (int k = 1; k < PortalHeight; k++) { blocktype = m_World.GetBlock(a_BlockPos + Vector3i(i, k, j)); if (blocktype != E_BLOCK_AIR) { return false; } } } } return true; } bool cNetherPortalScanner::OnAllChunksAvailable(void) { if (m_FoundPortal) { // Find the bottom of this portal while (m_World.GetBlock(m_PortalLoc) == E_BLOCK_NETHER_PORTAL) { m_PortalLoc.y -= 1; } m_PortalLoc.y += 1; // Figure out which way the portal is facing int BXP = m_World.GetBlock(m_PortalLoc.addedX(1)); int BXM = m_World.GetBlock(m_PortalLoc.addedX(-1)); if ((BXP == E_BLOCK_NETHER_PORTAL) || (BXM == E_BLOCK_NETHER_PORTAL)) { // The long axis is along X m_Dir = Direction::X; } else { // The long axis is along Z m_Dir = Direction::Y; } } else { // Scan the area for a suitable location int minx = FloorC(m_Position.x) - BuildSearchRadius; int minz = FloorC(m_Position.z) - BuildSearchRadius; int maxx = FloorC(m_Position.x) + BuildSearchRadius; int maxz = FloorC(m_Position.z) + BuildSearchRadius; int maxy = m_MaxY; std::vector Possibilities; int x, y, z; for (y = 0; y < maxy - PortalHeight; y++) { for (x = minx; x < maxx - PortalLength; x++) { for (z = minz; z < maxz - SearchSolidBaseWidth; z++) { Vector3i Location = Vector3i(x, y, z); if (IsValidBuildLocation(Location)) { Possibilities.emplace_back(x, y, z); } } } } if (Possibilities.size() > 0) { m_BuildPlatform = false; // Find the nearest double DistanceToClosest = (Possibilities[0] - m_Position).SqrLength(); Vector3i Closest = Possibilities[0]; for (const auto & itr : Possibilities) { double Distance = (itr - m_Position).SqrLength(); if (Distance < DistanceToClosest) { DistanceToClosest = Distance; Closest = itr; } } m_PortalLoc = Closest; } } return true; } void cNetherPortalScanner::BuildNetherPortal(Vector3i a_Location, Direction a_Direction, bool a_IncludePlatform) { int x = a_Location.x; int y = a_Location.y; int z = a_Location.z; // Clear a 3x4x4 area starting right above the base for (int i = 0; i < SearchSolidBaseWidth; i++) { for (int j = 0; j < PortalLength; j++) { for (int k = 1; k < PortalHeight; k++) { if (a_Direction == Direction::Y) { m_World.SetBlock({ x + i, y + k, z + j }, E_BLOCK_AIR, 0); } else if (a_Direction == Direction::X) { m_World.SetBlock({ x + j, y + k, z + i }, E_BLOCK_AIR, 0); } } } } // Put in an obsidian base if (a_IncludePlatform) { for (int j = 0; j < PortalLength; j++) { // +2 on the short axis because that's where we deposit the entity if (a_Direction == Direction::Y) { m_World.SetBlock({ x + 2, y, z + j }, E_BLOCK_OBSIDIAN, 0); } else if (a_Direction == Direction::X) { m_World.SetBlock({ x + j, y, z + 2 }, E_BLOCK_OBSIDIAN, 0); } } } // Build an obsidian frame for (int i = 0; i < PortalHeight; i++) { if (a_Direction == Direction::Y) { m_World.SetBlock({ x + 1, y + i, z }, E_BLOCK_OBSIDIAN, 0); m_World.SetBlock({ x + 1, y + i, z + 3 }, E_BLOCK_OBSIDIAN, 0); } else if (a_Direction == Direction::X) { m_World.SetBlock({ x, y + i, z + 1 }, E_BLOCK_OBSIDIAN, 0); m_World.SetBlock({ x + 3, y + i, z + 1 }, E_BLOCK_OBSIDIAN, 0); } } for (int i = 0; i < PortalLength; i++) { if (a_Direction == Direction::Y) { m_World.SetBlock({ x + 1, y + 4, z + i }, E_BLOCK_OBSIDIAN, 0); m_World.SetBlock({ x + 1, y, z + i }, E_BLOCK_OBSIDIAN, 0); } else if (a_Direction == Direction::X) { m_World.SetBlock({ x + i, y + 4, z + 1 }, E_BLOCK_OBSIDIAN, 0); m_World.SetBlock({ x + i, y, z + 1 }, E_BLOCK_OBSIDIAN, 0); } } // Fill the frame (place a fire in the bottom) m_World.PlaceBlock(Vector3(x + 1, y + 1, z + 1), E_BLOCK_FIRE, 0); } void cNetherPortalScanner::OnDisabled(void) { // Now we actually move the player if (!m_FoundPortal) { // Build a new nether portal. FLOGD("Building nether portal at {0}", m_PortalLoc); BuildNetherPortal(m_PortalLoc, m_Dir, m_BuildPlatform); m_PortalLoc.x += 1; m_PortalLoc.y += 1; m_PortalLoc.z += 1; } // Put the entity near the opening Vector3d Position = m_PortalLoc; if (m_Dir == Direction::Y) { Position.x += OutOffset; Position.z += AcrossOffset; } else if (m_Dir == Direction::X) { Position.x += AcrossOffset; Position.z += OutOffset; } auto EntityID = m_EntityID; auto & DestinationWorld = m_World; auto DestinationPosition = Position; // Lookup our warping entity by ID // Necessary as they may have been destroyed in the meantime (#4582) // And since this is called from the destination world's thread queue a task on the source world m_SourceWorld.QueueTask( [EntityID, &DestinationWorld, DestinationPosition](cWorld & a_World) { a_World.DoWithEntityByID( EntityID, [&DestinationWorld, &DestinationPosition](cEntity & a_Entity) { FLOGD("Placing player at {0}", DestinationPosition); a_Entity.MoveToWorld(DestinationWorld, DestinationPosition, true, false); return true; } ); } ); delete this; } ================================================ FILE: src/NetherPortalScanner.h ================================================ #pragma once #include "ChunkStay.h" class cEntity; class cWorld; // This is the chunk stay which finds nearby nether portals class cNetherPortalScanner : public cChunkStay { public: cNetherPortalScanner(cEntity & a_MovingEntity, cWorld & a_DestinationWorld, Vector3d a_DestPosition, int a_MaxY); virtual void OnChunkAvailable(int a_ChunkX, int a_ChunkY) override; virtual bool OnAllChunksAvailable(void) override; virtual void OnDisabled(void) override; enum class Direction { X, Y }; private: /** Length and height, including the obsidian. */ static const int PortalLength = 4; static const int PortalHeight = 5; static const int SearchRadius = 128; static const int BuildSearchRadius = 16; /** The width of a solid base to search for when building. */ static const int SearchSolidBaseWidth = 3; /** Where to place the player out from the face and across the face */ static const double OutOffset; static const double AcrossOffset; /** Builds a portal. */ void BuildNetherPortal(Vector3i a_Location, Direction a_Direction, bool a_IncludePlatform); /** Whether the given location is a valid location to build a portal. */ bool IsValidBuildLocation(Vector3i a_BlockPosition); /** The ID of the entity that's being moved. */ UInt32 m_EntityID; /** The world we're moving the entity from, used to query the entity ID. */ cWorld & m_SourceWorld; /** The world we're moving the entity to. */ cWorld & m_World; /** Whether we found a portal during the loading of the chunks. */ bool m_FoundPortal; /** Whether to build a platform. True if we couldn't build the portal on solid ground */ bool m_BuildPlatform; /** The direction of the portal. */ Direction m_Dir; /** The position of the pre-existing portal. */ Vector3i m_PortalLoc; /** The center of the search area */ Vector3d m_Position; /** The maximum Y to scan to */ int m_MaxY; }; ================================================ FILE: src/Noise/CMakeLists.txt ================================================ target_sources( ${CMAKE_PROJECT_NAME} PRIVATE Noise.cpp InterpolNoise.h Noise.h OctavedNoise.h RidgedNoise.h ) ================================================ FILE: src/Noise/InterpolNoise.h ================================================ // InterpolNoise.h // Implements the cInterpolNoise class template representing a noise that interpolates the values between integer coords from a single set of neighbors #pragma once #include "Noise.h" #define FAST_FLOOR(x) (((x) < 0) ? ((static_cast(x)) - 1) : (static_cast(x))) //////////////////////////////////////////////////////////////////////////////// // cInterpolCell2D: template class cInterpolCell2D { public: cInterpolCell2D( const cNoise & a_Noise, ///< Noise to use for generating the random values NOISE_DATATYPE * a_Array, ///< Array to generate into [x + a_SizeX * y] int a_SizeX, int a_SizeY, ///< Count of the array, in each direction const NOISE_DATATYPE * a_FracX, ///< Pointer to the array that stores the X fractional values const NOISE_DATATYPE * a_FracY ///< Pointer to the attay that stores the Y fractional values ): m_Noise(a_Noise), m_WorkRnds(&m_Workspace1), m_CurFloorX(0), m_CurFloorY(0), m_Array(a_Array), m_SizeX(a_SizeX), m_SizeY(a_SizeY), m_FracX(a_FracX), m_FracY(a_FracY) { } /** Generates part of the output noise array using the current m_WorkRnds[] values */ void Generate( int a_FromX, int a_ToX, int a_FromY, int a_ToY ) { for (int y = a_FromY; y < a_ToY; y++) { NOISE_DATATYPE Interp[2]; NOISE_DATATYPE FracY = T::coeff(m_FracY[y]); Interp[0] = Lerp((*m_WorkRnds)[0][0], (*m_WorkRnds)[0][1], FracY); Interp[1] = Lerp((*m_WorkRnds)[1][0], (*m_WorkRnds)[1][1], FracY); int idx = y * m_SizeX + a_FromX; for (int x = a_FromX; x < a_ToX; x++) { m_Array[idx++] = Lerp(Interp[0], Interp[1], T::coeff(m_FracX[x])); } // for x } // for y } /** Initializes m_WorkRnds[] with the specified values of the noise at the specified integral coords. */ void InitWorkRnds(int a_FloorX, int a_FloorY) { m_CurFloorX = a_FloorX; m_CurFloorY = a_FloorY; (*m_WorkRnds)[0][0] = m_Noise.IntNoise2D(m_CurFloorX, m_CurFloorY); (*m_WorkRnds)[0][1] = m_Noise.IntNoise2D(m_CurFloorX, m_CurFloorY + 1); (*m_WorkRnds)[1][0] = m_Noise.IntNoise2D(m_CurFloorX + 1, m_CurFloorY); (*m_WorkRnds)[1][1] = m_Noise.IntNoise2D(m_CurFloorX + 1, m_CurFloorY + 1); } /** Updates m_WorkRnds[] for the new integral coords */ void Move(int a_NewFloorX, int a_NewFloorY) { // Swap the doublebuffer: int OldFloorX = m_CurFloorX; int OldFloorY = m_CurFloorY; Workspace * OldWorkRnds = m_WorkRnds; m_WorkRnds = (m_WorkRnds == &m_Workspace1) ? &m_Workspace2 : &m_Workspace1; // Reuse as much of the old workspace as possible: // TODO: Try out if simply calculating all 4 elements each time is faster than this monster loop int DiffX = OldFloorX - a_NewFloorX; int DiffY = OldFloorY - a_NewFloorY; for (int x = 0; x < 2; x++) { int cx = a_NewFloorX + x; int OldX = x - DiffX; // Where would this X be in the old grid? for (int y = 0; y < 2; y++) { int cy = a_NewFloorY + y; int OldY = y - DiffY; // Where would this Y be in the old grid? if ((OldX >= 0) && (OldX < 2) && (OldY >= 0) && (OldY < 2)) { (*m_WorkRnds)[x][y] = (*OldWorkRnds)[OldX][OldY]; } else { (*m_WorkRnds)[x][y] = static_cast(m_Noise.IntNoise2D(cx, cy)); } } } m_CurFloorX = a_NewFloorX; m_CurFloorY = a_NewFloorY; } protected: typedef NOISE_DATATYPE Workspace[2][2]; /** The noise used for generating the values at integral coords. */ const cNoise & m_Noise; /** The current random values; points to either m_Workspace1 or m_Workspace2 (doublebuffering) */ Workspace * m_WorkRnds; /** Buffer 1 for workspace doublebuffering, used in Move() */ Workspace m_Workspace1; /** Buffer 2 for workspace doublebuffering, used in Move() */ Workspace m_Workspace2; /** Coords of the currently calculated m_WorkRnds[]. */ int m_CurFloorX, m_CurFloorY; /** The output array to generate into. */ NOISE_DATATYPE * m_Array; /** Dimensions of the output array. */ int m_SizeX, m_SizeY; /** Arrays holding the fractional values of the coords in each direction. */ const NOISE_DATATYPE * m_FracX; const NOISE_DATATYPE * m_FracY; } ; //////////////////////////////////////////////////////////////////////////////// // cInterpolCell3D: /** Holds a cache of the last calculated integral noise values and interpolates between them en masse. Provides a massive optimization for cInterpolNoise. Works by calculating multiple noise values (that have the same integral noise coords) at once. The underlying noise values needn't be recalculated for these values, only the interpolation is done within the unit cube. */ template class cInterpolCell3D { public: cInterpolCell3D( const cNoise & a_Noise, ///< Noise to use for generating the random values NOISE_DATATYPE * a_Array, ///< Array to generate into [x + a_SizeX * y] int a_SizeX, int a_SizeY, int a_SizeZ, ///< Count of the array, in each direction const NOISE_DATATYPE * a_FracX, ///< Pointer to the array that stores the X fractional values const NOISE_DATATYPE * a_FracY, ///< Pointer to the attay that stores the Y fractional values const NOISE_DATATYPE * a_FracZ ///< Pointer to the array that stores the Z fractional values ): m_Noise(a_Noise), m_WorkRnds(&m_Workspace1), m_CurFloorX(0), m_CurFloorY(0), m_CurFloorZ(0), m_Array(a_Array), m_SizeX(a_SizeX), m_SizeY(a_SizeY), m_SizeZ(a_SizeZ), m_FracX(a_FracX), m_FracY(a_FracY), m_FracZ(a_FracZ) { } /** Generates part of the output array using current m_WorkRnds[]. */ void Generate( int a_FromX, int a_ToX, int a_FromY, int a_ToY, int a_FromZ, int a_ToZ ) { for (int z = a_FromZ; z < a_ToZ; z++) { int idxZ = z * m_SizeX * m_SizeY; NOISE_DATATYPE Interp2[2][2]; NOISE_DATATYPE FracZ = T::coeff(m_FracZ[z]); for (int x = 0; x < 2; x++) { for (int y = 0; y < 2; y++) { Interp2[x][y] = Lerp((*m_WorkRnds)[x][y][0], (*m_WorkRnds)[x][y][1], FracZ); } } for (int y = a_FromY; y < a_ToY; y++) { NOISE_DATATYPE Interp[2]; NOISE_DATATYPE FracY = T::coeff(m_FracY[y]); Interp[0] = Lerp(Interp2[0][0], Interp2[0][1], FracY); Interp[1] = Lerp(Interp2[1][0], Interp2[1][1], FracY); int idx = idxZ + y * m_SizeX + a_FromX; for (int x = a_FromX; x < a_ToX; x++) { m_Array[idx++] = Lerp(Interp[0], Interp[1], T::coeff(m_FracX[x])); } // for x } // for y } // for z } /** Initializes m_WorkRnds[] with the specified Floor values. */ void InitWorkRnds(int a_FloorX, int a_FloorY, int a_FloorZ) { m_CurFloorX = a_FloorX; m_CurFloorY = a_FloorY; m_CurFloorZ = a_FloorZ; (*m_WorkRnds)[0][0][0] = static_cast(m_Noise.IntNoise3D(m_CurFloorX, m_CurFloorY, m_CurFloorZ)); (*m_WorkRnds)[0][0][1] = static_cast(m_Noise.IntNoise3D(m_CurFloorX, m_CurFloorY, m_CurFloorZ + 1)); (*m_WorkRnds)[0][1][0] = static_cast(m_Noise.IntNoise3D(m_CurFloorX, m_CurFloorY + 1, m_CurFloorZ)); (*m_WorkRnds)[0][1][1] = static_cast(m_Noise.IntNoise3D(m_CurFloorX, m_CurFloorY + 1, m_CurFloorZ + 1)); (*m_WorkRnds)[1][0][0] = static_cast(m_Noise.IntNoise3D(m_CurFloorX + 1, m_CurFloorY, m_CurFloorZ)); (*m_WorkRnds)[1][0][1] = static_cast(m_Noise.IntNoise3D(m_CurFloorX + 1, m_CurFloorY, m_CurFloorZ + 1)); (*m_WorkRnds)[1][1][0] = static_cast(m_Noise.IntNoise3D(m_CurFloorX + 1, m_CurFloorY + 1, m_CurFloorZ)); (*m_WorkRnds)[1][1][1] = static_cast(m_Noise.IntNoise3D(m_CurFloorX + 1, m_CurFloorY + 1, m_CurFloorZ + 1)); } /** Updates m_WorkRnds[] for the new Floor values. */ void Move(int a_NewFloorX, int a_NewFloorY, int a_NewFloorZ) { // Swap the doublebuffer: int OldFloorX = m_CurFloorX; int OldFloorY = m_CurFloorY; int OldFloorZ = m_CurFloorZ; Workspace * OldWorkRnds = m_WorkRnds; m_WorkRnds = (m_WorkRnds == &m_Workspace1) ? &m_Workspace2 : &m_Workspace1; // Reuse as much of the old workspace as possible: // TODO: Try out if simply calculating all 8 elements each time is faster than this monster loop int DiffX = OldFloorX - a_NewFloorX; int DiffY = OldFloorY - a_NewFloorY; int DiffZ = OldFloorZ - a_NewFloorZ; for (int x = 0; x < 2; x++) { int cx = a_NewFloorX + x; int OldX = x - DiffX; // Where would this X be in the old grid? for (int y = 0; y < 2; y++) { int cy = a_NewFloorY + y; int OldY = y - DiffY; // Where would this Y be in the old grid? for (int z = 0; z < 2; z++) { int cz = a_NewFloorZ + z; int OldZ = z - DiffZ; if ((OldX >= 0) && (OldX < 2) && (OldY >= 0) && (OldY < 2) && (OldZ >= 0) && (OldZ < 2)) { (*m_WorkRnds)[x][y][z] = (*OldWorkRnds)[OldX][OldY][OldZ]; } else { (*m_WorkRnds)[x][y][z] = static_cast(m_Noise.IntNoise3D(cx, cy, cz)); } } // for z } // for y } // for x m_CurFloorX = a_NewFloorX; m_CurFloorY = a_NewFloorY; m_CurFloorZ = a_NewFloorZ; } protected: typedef NOISE_DATATYPE Workspace[2][2][2]; /** The noise used for generating the values at integral coords. */ const cNoise & m_Noise; /** The current random values; points to either m_Workspace1 or m_Workspace2 (doublebuffering) */ Workspace * m_WorkRnds; /** Buffer 1 for workspace doublebuffering, used in Move() */ Workspace m_Workspace1; /** Buffer 2 for workspace doublebuffering, used in Move() */ Workspace m_Workspace2; /** The integral coords of the currently calculated WorkRnds[] */ int m_CurFloorX, m_CurFloorY, m_CurFloorZ; /** The output array where the noise is calculated. */ NOISE_DATATYPE * m_Array; /** Dimensions of the output array. */ int m_SizeX, m_SizeY, m_SizeZ; /** Arrays holding the fractional values of the coords in each direction. */ const NOISE_DATATYPE * m_FracX; const NOISE_DATATYPE * m_FracY; const NOISE_DATATYPE * m_FracZ; } ; //////////////////////////////////////////////////////////////////////////////// // cInterpolNoise: template class cInterpolNoise { /** Maximum size, for each direction, of the generated array. */ static const int MAX_SIZE = 256; public: cInterpolNoise(int a_Seed): m_Noise(a_Seed) { } /** Sets a new seed for the generators. Relays the seed to the underlying noise. */ void SetSeed(int a_Seed) { m_Noise.SetSeed(a_Seed); } /** Fills a 2D array with the values of the noise. */ void Generate2D( NOISE_DATATYPE * a_Array, ///< Array to generate into [x + a_SizeX * y] int a_SizeX, int a_SizeY, ///< Count of the array, in each direction NOISE_DATATYPE a_StartX, NOISE_DATATYPE a_EndX, ///< Noise-space coords of the array in the X direction NOISE_DATATYPE a_StartY, NOISE_DATATYPE a_EndY ///< Noise-space coords of the array in the Y direction ) const { ASSERT(a_SizeX > 0); ASSERT(a_SizeY > 0); ASSERT(a_SizeX < MAX_SIZE); ASSERT(a_SizeY < MAX_SIZE); ASSERT(a_StartX < a_EndX); ASSERT(a_StartY < a_EndY); // Calculate the integral and fractional parts of each coord: int FloorX[MAX_SIZE]; int FloorY[MAX_SIZE]; NOISE_DATATYPE FracX[MAX_SIZE]; NOISE_DATATYPE FracY[MAX_SIZE]; int SameX[MAX_SIZE]; int SameY[MAX_SIZE]; int NumSameX, NumSameY; CalcFloorFrac(a_SizeX, a_StartX, a_EndX, FloorX, FracX, SameX, NumSameX); CalcFloorFrac(a_SizeY, a_StartY, a_EndY, FloorY, FracY, SameY, NumSameY); cInterpolCell2D Cell(m_Noise, a_Array, a_SizeX, a_SizeY, FracX, FracY); Cell.InitWorkRnds(FloorX[0], FloorY[0]); // Calculate query values using Cell: int FromY = 0; for (int y = 0; y < NumSameY; y++) { int ToY = FromY + SameY[y]; int FromX = 0; int CurFloorY = FloorY[FromY]; for (int x = 0; x < NumSameX; x++) { int ToX = FromX + SameX[x]; Cell.Generate(FromX, ToX, FromY, ToY); Cell.Move(FloorX[ToX], CurFloorY); FromX = ToX; } // for x Cell.Move(FloorX[0], FloorY[ToY]); FromY = ToY; } // for y } /** Fills a 3D array with the values of the noise. */ void Generate3D( NOISE_DATATYPE * a_Array, ///< Array to generate into [x + a_SizeX * y + a_SizeX * a_SizeY * z] int a_SizeX, int a_SizeY, int a_SizeZ, ///< Count of the array, in each direction NOISE_DATATYPE a_StartX, NOISE_DATATYPE a_EndX, ///< Noise-space coords of the array in the X direction NOISE_DATATYPE a_StartY, NOISE_DATATYPE a_EndY, ///< Noise-space coords of the array in the Y direction NOISE_DATATYPE a_StartZ, NOISE_DATATYPE a_EndZ ///< Noise-space coords of the array in the Z direction ) const { // Check params: ASSERT(a_SizeX > 1); ASSERT(a_SizeY > 1); ASSERT(a_SizeX < MAX_SIZE); ASSERT(a_SizeY < MAX_SIZE); ASSERT(a_SizeZ < MAX_SIZE); ASSERT(a_StartX < a_EndX); ASSERT(a_StartY < a_EndY); ASSERT(a_StartZ < a_EndZ); // Calculate the integral and fractional parts of each coord: int FloorX[MAX_SIZE]; int FloorY[MAX_SIZE]; int FloorZ[MAX_SIZE]; NOISE_DATATYPE FracX[MAX_SIZE]; NOISE_DATATYPE FracY[MAX_SIZE]; NOISE_DATATYPE FracZ[MAX_SIZE]; int SameX[MAX_SIZE]; int SameY[MAX_SIZE]; int SameZ[MAX_SIZE]; int NumSameX, NumSameY, NumSameZ; CalcFloorFrac(a_SizeX, a_StartX, a_EndX, FloorX, FracX, SameX, NumSameX); CalcFloorFrac(a_SizeY, a_StartY, a_EndY, FloorY, FracY, SameY, NumSameY); CalcFloorFrac(a_SizeZ, a_StartZ, a_EndZ, FloorZ, FracZ, SameZ, NumSameZ); cInterpolCell3D Cell( m_Noise, a_Array, a_SizeX, a_SizeY, a_SizeZ, FracX, FracY, FracZ ); Cell.InitWorkRnds(FloorX[0], FloorY[0], FloorZ[0]); // Calculate query values using Cell: int FromZ = 0; for (int z = 0; z < NumSameZ;) { int ToZ = FromZ + SameZ[z]; int CurFloorZ = FloorZ[FromZ]; int FromY = 0; for (int y = 0; y < NumSameY;) { int ToY = FromY + SameY[y]; int CurFloorY = FloorY[FromY]; int FromX = 0; for (int x = 0; x < NumSameX;) { int ToX = FromX + SameX[x]; Cell.Generate(FromX, ToX, FromY, ToY, FromZ, ToZ); if (++x < NumSameX) // Call Move() every time except for the last loop iteration { Cell.Move(FloorX[ToX], CurFloorY, CurFloorZ); FromX = ToX; } } if (++y < NumSameY) // Call Move() every time except for the last loop iteration { Cell.Move(FloorX[0], FloorY[ToY], CurFloorZ); FromY = ToY; } } // for y if (++z < NumSameZ) // Call Move() every time except for the last loop iteration { Cell.Move(FloorX[0], FloorY[0], FloorZ[ToZ]); FromZ = ToZ; } } // for z } protected: /** The noise used for the underlying value generation. */ cNoise m_Noise; /** Calculates the integral and fractional parts along one axis. a_Floor will receive the integral parts (array of a_Size ints). a_Frac will receive the fractional parts (array of a_Size floats). a_Same will receive the counts of items that have the same integral parts (array of up to a_Size ints). a_NumSame will receive the count of a_Same elements (total count of different integral parts). */ void CalcFloorFrac( int a_Size, NOISE_DATATYPE a_Start, NOISE_DATATYPE a_End, int * a_Floor, NOISE_DATATYPE * a_Frac, int * a_Same, int & a_NumSame ) const { ASSERT(a_Size > 0); // Calculate the floor and frac values: NOISE_DATATYPE val = a_Start; NOISE_DATATYPE dif = (a_End - a_Start) / (a_Size - 1); for (int i = 0; i < a_Size; i++) { a_Floor[i] = FAST_FLOOR(val); a_Frac[i] = val - a_Floor[i]; val += dif; } // Mark up the same floor values into a_Same / a_NumSame: int CurFloor = a_Floor[0]; int LastSame = 0; a_NumSame = 0; for (int i = 1; i < a_Size; i++) { if (a_Floor[i] != CurFloor) { a_Same[a_NumSame] = i - LastSame; LastSame = i; a_NumSame += 1; CurFloor = a_Floor[i]; } } // for i - a_Floor[] if (LastSame < a_Size) { a_Same[a_NumSame] = a_Size - LastSame; a_NumSame += 1; } } }; /** A fifth-degree curve for interpolating. Implemented as a functor for better chance of inlining. */ struct Interp5Deg { static NOISE_DATATYPE coeff(NOISE_DATATYPE a_Val) { return a_Val * a_Val * a_Val * (a_Val * (a_Val * 6 - 15) + 10); } }; typedef cInterpolNoise cInterp5DegNoise; ================================================ FILE: src/Noise/Noise.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "Noise.h" #define FAST_FLOOR(x) (((x) < 0) ? ((static_cast(x)) - 1) : (static_cast(x))) #if 0 /** cImprovedPerlin noise test suite: - Generate a rather large 2D and 3D noise array and output it to a file - Compare performance of cCubicNoise and cImprovedNoise, both in single-value and 3D-array usages */ static class cImprovedPerlinNoiseTest { public: cImprovedPerlinNoiseTest(void) { printf("Performing Improved Perlin Noise tests...\n"); TestImage(); TestSpeed(); TestSpeedArr(); printf("Improved Perlin Noise tests complete.\n"); } /** Tests the noise by generating 2D and 3D images and dumping them to files. */ void TestImage(void) { static const int SIZE_X = 256; static const int SIZE_Y = 256; static const int SIZE_Z = 16; cImprovedNoise noise(1); std::unique_ptr arr(new NOISE_DATATYPE[SIZE_X * SIZE_Y * SIZE_Z]); noise.Generate3D(arr.get(), SIZE_X, SIZE_Y, SIZE_Z, 0, 14, 0, 14, 0, 14); Debug3DNoise(arr.get(), SIZE_X, SIZE_Y, SIZE_Z, "ImprovedPerlinNoiseTest3D", 128); noise.Generate2D(arr.get(), SIZE_X, SIZE_Y, 0, 14, 15, 28); Debug2DNoise(arr.get(), SIZE_X, SIZE_Y, "ImprovedPerlinNoiseTest2D", 128); } /** Tests the speeds of cImprovedPerlin and cCubicNoise when generating individual values. */ void TestSpeed(void) { cImprovedNoise improvedNoise(1); cNoise noise(1); cTimer timer; // Measure the improvedNoise: NOISE_DATATYPE sum = 0; long long start = timer.GetNowTime(); for (int i = 0; i < 100000000; i++) { sum += improvedNoise.GetValueAt(i, 0, -i); } long long finish = timer.GetNowTime(); printf("cImprovedNoise took %.2f seconds; total is %f.\n", static_cast(finish - start) / 1000.0f, sum); // Measure the cubicNoise: sum = 0; start = timer.GetNowTime(); for (int i = 0; i < 100000000; i++) { sum += noise.IntNoise3D(i, 0, -i); } finish = timer.GetNowTime(); printf("cCubicNoise took %.2f seconds; total is %f.\n", static_cast(finish - start) / 1000.0f, sum); } /** Tests the speeds of cImprovedPerlin and cCubicNoise when generating arrays. */ void TestSpeedArr(void) { static const int SIZE_X = 256; static const int SIZE_Y = 256; static const int SIZE_Z = 16; std::unique_ptr arr(new NOISE_DATATYPE[SIZE_X * SIZE_Y * SIZE_Z]); cTimer timer; cImprovedNoise improvedNoise(1); cCubicNoise cubicNoise(1); // Measure the improvedNoise: long long start = timer.GetNowTime(); for (int i = 0; i < 40; i++) { improvedNoise.Generate3D(arr.get(), SIZE_X, SIZE_Y, SIZE_Z, 0, 14, 0, 14, 0, 14); } long long finish = timer.GetNowTime(); printf("cImprovedNoise(arr) took %.2f seconds.\n", static_cast(finish - start) / 1000.0f); // Measure the cubicNoise: start = timer.GetNowTime(); for (int i = 0; i < 40; i++) { cubicNoise.Generate3D(arr.get(), SIZE_X, SIZE_Y, SIZE_Z, 0, 14, 0, 14, 0, 14); } finish = timer.GetNowTime(); printf("cCubicNoise(arr) took %.2f seconds.\n", static_cast(finish - start) / 1000.0f); } } g_Test; #endif //////////////////////////////////////////////////////////////////////////////// // Globals: void Debug3DNoise(const NOISE_DATATYPE * a_Noise, size_t a_SizeX, size_t a_SizeY, size_t a_SizeZ, const AString & a_FileNameBase, NOISE_DATATYPE a_Coeff) { const int BUF_SIZE = 512; ASSERT(a_SizeX <= BUF_SIZE); // Just stretch it, if needed // Save in XY cuts: cFile f1; if (f1.Open(fmt::format(FMT_STRING("{}_XY ({}).grab"), a_FileNameBase, a_SizeX), cFile::fmWrite)) { for (size_t z = 0; z < a_SizeZ; z++) { for (size_t y = 0; y < a_SizeY; y++) { size_t idx = y * a_SizeX + z * a_SizeX * a_SizeY; unsigned char buf[BUF_SIZE]; for (size_t x = 0; x < a_SizeX; x++) { buf[x] = static_cast(Clamp(static_cast(128 + a_Coeff * a_Noise[idx++]), 0, 255)); } f1.Write(buf, a_SizeX); } // for y unsigned char buf[BUF_SIZE]; memset(buf, 0, a_SizeX); f1.Write(buf, a_SizeX); } // for z } // if (XY file open) cFile f2; if (f2.Open(fmt::format(FMT_STRING("{}_XZ ({}).grab"), a_FileNameBase, a_SizeX), cFile::fmWrite)) { for (size_t y = 0; y < a_SizeY; y++) { for (size_t z = 0; z < a_SizeZ; z++) { size_t idx = y * a_SizeX + z * a_SizeX * a_SizeY; unsigned char buf[BUF_SIZE]; for (size_t x = 0; x < a_SizeX; x++) { buf[x] = static_cast(Clamp(static_cast(128 + a_Coeff * a_Noise[idx++]), 0, 255)); } f2.Write(buf, a_SizeX); } // for z unsigned char buf[BUF_SIZE]; memset(buf, 0, a_SizeX); f2.Write(buf, a_SizeX); } // for y } // if (XZ file open) } void Debug2DNoise(const NOISE_DATATYPE * a_Noise, size_t a_SizeX, size_t a_SizeY, const AString & a_FileNameBase, NOISE_DATATYPE a_Coeff) { const int BUF_SIZE = 512; ASSERT(a_SizeX <= BUF_SIZE); // Just stretch it, if needed cFile f1; if (f1.Open(fmt::format(FMT_STRING("{} ({}).grab"), a_FileNameBase, a_SizeX), cFile::fmWrite)) { for (size_t y = 0; y < a_SizeY; y++) { size_t idx = y * a_SizeX; unsigned char buf[BUF_SIZE]; for (size_t x = 0; x < a_SizeX; x++) { buf[x] = static_cast(Clamp(static_cast(128 + a_Coeff * a_Noise[idx++]), 0, 255)); } f1.Write(buf, a_SizeX); } // for y } // if (file open) } //////////////////////////////////////////////////////////////////////////////// // cCubicCell2D: class cCubicCell2D { public: cCubicCell2D( const cNoise & a_Noise, ///< Noise to use for generating the random values NOISE_DATATYPE * a_Array, ///< Array to generate into [x + a_SizeX * y] int a_SizeX, int a_SizeY, ///< Count of the array, in each direction const NOISE_DATATYPE * a_FracX, ///< Pointer to the array that stores the X fractional values const NOISE_DATATYPE * a_FracY ///< Pointer to the attay that stores the Y fractional values ); /** Uses current m_WorkRnds[] to generate part of the array */ void Generate( int a_FromX, int a_ToX, int a_FromY, int a_ToY ); /** Initializes m_WorkRnds[] with the specified Floor values */ void InitWorkRnds(int a_FloorX, int a_FloorY); /** Updates m_WorkRnds[] for the new Floor values. */ void Move(int a_NewFloorX, int a_NewFloorY); protected: typedef NOISE_DATATYPE Workspace[4][4]; const cNoise & m_Noise; Workspace * m_WorkRnds; ///< The current random values; points to either m_Workspace1 or m_Workspace2 (doublebuffering) Workspace m_Workspace1; ///< Buffer 1 for workspace doublebuffering, used in Move() Workspace m_Workspace2; ///< Buffer 2 for workspace doublebuffering, used in Move() int m_CurFloorX; int m_CurFloorY; NOISE_DATATYPE * m_Array; int m_SizeX, m_SizeY; const NOISE_DATATYPE * m_FracX; const NOISE_DATATYPE * m_FracY; } ; cCubicCell2D::cCubicCell2D( const cNoise & a_Noise, ///< Noise to use for generating the random values NOISE_DATATYPE * a_Array, ///< Array to generate into [x + a_SizeX * y] int a_SizeX, int a_SizeY, ///< Count of the array, in each direction const NOISE_DATATYPE * a_FracX, ///< Pointer to the array that stores the X fractional values const NOISE_DATATYPE * a_FracY ///< Pointer to the attay that stores the Y fractional values ) : m_Noise(a_Noise), m_WorkRnds(&m_Workspace1), m_CurFloorX(0), m_CurFloorY(0), m_Array(a_Array), m_SizeX(a_SizeX), m_SizeY(a_SizeY), m_FracX(a_FracX), m_FracY(a_FracY) { } void cCubicCell2D::Generate( int a_FromX, int a_ToX, int a_FromY, int a_ToY ) { for (int y = a_FromY; y < a_ToY; y++) { NOISE_DATATYPE Interp[4]; NOISE_DATATYPE FracY = m_FracY[y]; Interp[0] = cNoise::CubicInterpolate((*m_WorkRnds)[0][0], (*m_WorkRnds)[0][1], (*m_WorkRnds)[0][2], (*m_WorkRnds)[0][3], FracY); Interp[1] = cNoise::CubicInterpolate((*m_WorkRnds)[1][0], (*m_WorkRnds)[1][1], (*m_WorkRnds)[1][2], (*m_WorkRnds)[1][3], FracY); Interp[2] = cNoise::CubicInterpolate((*m_WorkRnds)[2][0], (*m_WorkRnds)[2][1], (*m_WorkRnds)[2][2], (*m_WorkRnds)[2][3], FracY); Interp[3] = cNoise::CubicInterpolate((*m_WorkRnds)[3][0], (*m_WorkRnds)[3][1], (*m_WorkRnds)[3][2], (*m_WorkRnds)[3][3], FracY); int idx = y * m_SizeX + a_FromX; for (int x = a_FromX; x < a_ToX; x++) { m_Array[idx++] = cNoise::CubicInterpolate(Interp[0], Interp[1], Interp[2], Interp[3], m_FracX[x]); } // for x } // for y } void cCubicCell2D::InitWorkRnds(int a_FloorX, int a_FloorY) { m_CurFloorX = a_FloorX; m_CurFloorY = a_FloorY; for (int x = 0; x < 4; x++) { int cx = a_FloorX + x - 1; for (int y = 0; y < 4; y++) { int cy = a_FloorY + y - 1; (*m_WorkRnds)[x][y] = static_cast(m_Noise.IntNoise2D(cx, cy)); } } } void cCubicCell2D::Move(int a_NewFloorX, int a_NewFloorY) { // Swap the doublebuffer: int OldFloorX = m_CurFloorX; int OldFloorY = m_CurFloorY; Workspace * OldWorkRnds = m_WorkRnds; m_WorkRnds = (m_WorkRnds == &m_Workspace1) ? &m_Workspace2 : &m_Workspace1; // Reuse as much of the old workspace as possible: int DiffX = OldFloorX - a_NewFloorX; int DiffY = OldFloorY - a_NewFloorY; for (int x = 0; x < 4; x++) { int cx = a_NewFloorX + x - 1; int OldX = x - DiffX; // Where would this X be in the old grid? for (int y = 0; y < 4; y++) { int cy = a_NewFloorY + y - 1; int OldY = y - DiffY; // Where would this Y be in the old grid? if ((OldX >= 0) && (OldX < 4) && (OldY >= 0) && (OldY < 4)) { (*m_WorkRnds)[x][y] = (*OldWorkRnds)[OldX][OldY]; } else { (*m_WorkRnds)[x][y] = static_cast(m_Noise.IntNoise2D(cx, cy)); } } } m_CurFloorX = a_NewFloorX; m_CurFloorY = a_NewFloorY; } //////////////////////////////////////////////////////////////////////////////// // cCubicCell3D: class cCubicCell3D { public: cCubicCell3D( const cNoise & a_Noise, ///< Noise to use for generating the random values NOISE_DATATYPE * a_Array, ///< Array to generate into [x + a_SizeX * y] int a_SizeX, int a_SizeY, int a_SizeZ, ///< Count of the array, in each direction const NOISE_DATATYPE * a_FracX, ///< Pointer to the array that stores the X fractional values const NOISE_DATATYPE * a_FracY, ///< Pointer to the attay that stores the Y fractional values const NOISE_DATATYPE * a_FracZ ///< Pointer to the array that stores the Z fractional values ); /** Uses current m_WorkRnds[] to generate part of the array */ void Generate( int a_FromX, int a_ToX, int a_FromY, int a_ToY, int a_FromZ, int a_ToZ ); /** Initializes m_WorkRnds[] with the specified Floor values */ void InitWorkRnds(int a_FloorX, int a_FloorY, int a_FloorZ); /** Updates m_WorkRnds[] for the new Floor values. */ void Move(int a_NewFloorX, int a_NewFloorY, int a_NewFloorZ); protected: typedef NOISE_DATATYPE Workspace[4][4][4]; const cNoise & m_Noise; Workspace * m_WorkRnds; ///< The current random values; points to either m_Workspace1 or m_Workspace2 (doublebuffering) Workspace m_Workspace1; ///< Buffer 1 for workspace doublebuffering, used in Move() Workspace m_Workspace2; ///< Buffer 2 for workspace doublebuffering, used in Move() int m_CurFloorX; int m_CurFloorY; int m_CurFloorZ; NOISE_DATATYPE * m_Array; int m_SizeX, m_SizeY, m_SizeZ; const NOISE_DATATYPE * m_FracX; const NOISE_DATATYPE * m_FracY; const NOISE_DATATYPE * m_FracZ; } ; cCubicCell3D::cCubicCell3D( const cNoise & a_Noise, ///< Noise to use for generating the random values NOISE_DATATYPE * a_Array, ///< Array to generate into [x + a_SizeX * y] int a_SizeX, int a_SizeY, int a_SizeZ, ///< Count of the array, in each direction const NOISE_DATATYPE * a_FracX, ///< Pointer to the array that stores the X fractional values const NOISE_DATATYPE * a_FracY, ///< Pointer to the attay that stores the Y fractional values const NOISE_DATATYPE * a_FracZ ///< Pointer to the array that stores the Z fractional values ) : m_Noise(a_Noise), m_WorkRnds(&m_Workspace1), m_CurFloorX(0), m_CurFloorY(0), m_CurFloorZ(0), m_Array(a_Array), m_SizeX(a_SizeX), m_SizeY(a_SizeY), m_SizeZ(a_SizeZ), m_FracX(a_FracX), m_FracY(a_FracY), m_FracZ(a_FracZ) { } void cCubicCell3D::Generate( int a_FromX, int a_ToX, int a_FromY, int a_ToY, int a_FromZ, int a_ToZ ) { for (int z = a_FromZ; z < a_ToZ; z++) { int idxZ = z * m_SizeX * m_SizeY; NOISE_DATATYPE Interp2[4][4]; NOISE_DATATYPE FracZ = m_FracZ[z]; for (int x = 0; x < 4; x++) { for (int y = 0; y < 4; y++) { Interp2[x][y] = cNoise::CubicInterpolate((*m_WorkRnds)[x][y][0], (*m_WorkRnds)[x][y][1], (*m_WorkRnds)[x][y][2], (*m_WorkRnds)[x][y][3], FracZ); } } for (int y = a_FromY; y < a_ToY; y++) { NOISE_DATATYPE Interp[4]; NOISE_DATATYPE FracY = m_FracY[y]; Interp[0] = cNoise::CubicInterpolate(Interp2[0][0], Interp2[0][1], Interp2[0][2], Interp2[0][3], FracY); Interp[1] = cNoise::CubicInterpolate(Interp2[1][0], Interp2[1][1], Interp2[1][2], Interp2[1][3], FracY); Interp[2] = cNoise::CubicInterpolate(Interp2[2][0], Interp2[2][1], Interp2[2][2], Interp2[2][3], FracY); Interp[3] = cNoise::CubicInterpolate(Interp2[3][0], Interp2[3][1], Interp2[3][2], Interp2[3][3], FracY); int idx = idxZ + y * m_SizeX + a_FromX; for (int x = a_FromX; x < a_ToX; x++) { m_Array[idx++] = cNoise::CubicInterpolate(Interp[0], Interp[1], Interp[2], Interp[3], m_FracX[x]); } // for x } // for y } // for z } void cCubicCell3D::InitWorkRnds(int a_FloorX, int a_FloorY, int a_FloorZ) { m_CurFloorX = a_FloorX; m_CurFloorY = a_FloorY; m_CurFloorZ = a_FloorZ; for (int x = 0; x < 4; x++) { int cx = a_FloorX + x - 1; for (int y = 0; y < 4; y++) { int cy = a_FloorY + y - 1; for (int z = 0; z < 4; z++) { int cz = a_FloorZ + z - 1; (*m_WorkRnds)[x][y][z] = static_cast(m_Noise.IntNoise3D(cx, cy, cz)); } } } } void cCubicCell3D::Move(int a_NewFloorX, int a_NewFloorY, int a_NewFloorZ) { // Swap the doublebuffer: int OldFloorX = m_CurFloorX; int OldFloorY = m_CurFloorY; int OldFloorZ = m_CurFloorZ; Workspace * OldWorkRnds = m_WorkRnds; m_WorkRnds = (m_WorkRnds == &m_Workspace1) ? &m_Workspace2 : &m_Workspace1; // Reuse as much of the old workspace as possible: int DiffX = OldFloorX - a_NewFloorX; int DiffY = OldFloorY - a_NewFloorY; int DiffZ = OldFloorZ - a_NewFloorZ; for (int x = 0; x < 4; x++) { int cx = a_NewFloorX + x - 1; int OldX = x - DiffX; // Where would this X be in the old grid? for (int y = 0; y < 4; y++) { int cy = a_NewFloorY + y - 1; int OldY = y - DiffY; // Where would this Y be in the old grid? for (int z = 0; z < 4; z++) { int cz = a_NewFloorZ + z - 1; int OldZ = z - DiffZ; if ((OldX >= 0) && (OldX < 4) && (OldY >= 0) && (OldY < 4) && (OldZ >= 0) && (OldZ < 4)) { (*m_WorkRnds)[x][y][z] = (*OldWorkRnds)[OldX][OldY][OldZ]; } else { (*m_WorkRnds)[x][y][z] = static_cast(m_Noise.IntNoise3D(cx, cy, cz)); } } // for z } // for y } // for x m_CurFloorX = a_NewFloorX; m_CurFloorY = a_NewFloorY; m_CurFloorZ = a_NewFloorZ; } //////////////////////////////////////////////////////////////////////////////// // cNoise: cNoise::cNoise(int a_Seed) : m_Seed(a_Seed) { } cNoise::cNoise(const cNoise & a_Noise) : m_Seed(a_Noise.m_Seed) { } NOISE_DATATYPE cNoise::LinearNoise1D(NOISE_DATATYPE a_X) const { int BaseX = FAST_FLOOR(a_X); NOISE_DATATYPE FracX = a_X - BaseX; return LinearInterpolate(IntNoise1D(BaseX), IntNoise1D(BaseX + 1), FracX); } NOISE_DATATYPE cNoise::CosineNoise1D(NOISE_DATATYPE a_X) const { int BaseX = FAST_FLOOR(a_X); NOISE_DATATYPE FracX = a_X - BaseX; return CosineInterpolate(IntNoise1D(BaseX), IntNoise1D(BaseX + 1), FracX); } NOISE_DATATYPE cNoise::CubicNoise1D(NOISE_DATATYPE a_X) const { int BaseX = FAST_FLOOR(a_X); NOISE_DATATYPE FracX = a_X - BaseX; return CubicInterpolate(IntNoise1D(BaseX - 1), IntNoise1D(BaseX), IntNoise1D(BaseX + 1), IntNoise1D(BaseX + 2), FracX); } NOISE_DATATYPE cNoise::SmoothNoise1D(int a_X) const { return IntNoise1D(a_X) / 2 + IntNoise1D(a_X - 1) / 4 + IntNoise1D(a_X + 1) / 4; } NOISE_DATATYPE cNoise::CubicNoise2D(NOISE_DATATYPE a_X, NOISE_DATATYPE a_Y) const { const int BaseX = FAST_FLOOR(a_X); const int BaseY = FAST_FLOOR(a_Y); const NOISE_DATATYPE points[4][4] = { { IntNoise2D(BaseX - 1, BaseY - 1), IntNoise2D(BaseX, BaseY - 1), IntNoise2D(BaseX + 1, BaseY - 1), IntNoise2D(BaseX + 2, BaseY - 1), }, { IntNoise2D(BaseX - 1, BaseY), IntNoise2D(BaseX, BaseY), IntNoise2D(BaseX + 1, BaseY), IntNoise2D(BaseX + 2, BaseY), }, { IntNoise2D(BaseX - 1, BaseY + 1), IntNoise2D(BaseX, BaseY + 1), IntNoise2D(BaseX + 1, BaseY + 1), IntNoise2D(BaseX + 2, BaseY + 1), }, { IntNoise2D(BaseX - 1, BaseY + 2), IntNoise2D(BaseX, BaseY + 2), IntNoise2D(BaseX + 1, BaseY + 2), IntNoise2D(BaseX + 2, BaseY + 2), }, }; const NOISE_DATATYPE FracX = a_X - BaseX; const NOISE_DATATYPE interp1 = CubicInterpolate(points[0][0], points[0][1], points[0][2], points[0][3], FracX); const NOISE_DATATYPE interp2 = CubicInterpolate(points[1][0], points[1][1], points[1][2], points[1][3], FracX); const NOISE_DATATYPE interp3 = CubicInterpolate(points[2][0], points[2][1], points[2][2], points[2][3], FracX); const NOISE_DATATYPE interp4 = CubicInterpolate(points[3][0], points[3][1], points[3][2], points[3][3], FracX); const NOISE_DATATYPE FracY = a_Y - BaseY; return CubicInterpolate(interp1, interp2, interp3, interp4, FracY); } NOISE_DATATYPE cNoise::CubicNoise3D(NOISE_DATATYPE a_X, NOISE_DATATYPE a_Y, NOISE_DATATYPE a_Z) const { const int BaseX = FAST_FLOOR(a_X); const int BaseY = FAST_FLOOR(a_Y); const int BaseZ = FAST_FLOOR(a_Z); const NOISE_DATATYPE points1[4][4] = { { IntNoise3D(BaseX - 1, BaseY - 1, BaseZ - 1), IntNoise3D(BaseX, BaseY - 1, BaseZ - 1), IntNoise3D(BaseX + 1, BaseY - 1, BaseZ - 1), IntNoise3D(BaseX + 2, BaseY - 1, BaseZ - 1), }, { IntNoise3D(BaseX - 1, BaseY, BaseZ - 1), IntNoise3D(BaseX, BaseY, BaseZ - 1), IntNoise3D(BaseX + 1, BaseY, BaseZ - 1), IntNoise3D(BaseX + 2, BaseY, BaseZ - 1), }, { IntNoise3D(BaseX - 1, BaseY + 1, BaseZ - 1), IntNoise3D(BaseX, BaseY + 1, BaseZ - 1), IntNoise3D(BaseX + 1, BaseY + 1, BaseZ - 1), IntNoise3D(BaseX + 2, BaseY + 1, BaseZ - 1), }, { IntNoise3D(BaseX - 1, BaseY + 2, BaseZ - 1), IntNoise3D(BaseX, BaseY + 2, BaseZ - 1), IntNoise3D(BaseX + 1, BaseY + 2, BaseZ - 1), IntNoise3D(BaseX + 2, BaseY + 2, BaseZ - 1), }, }; const NOISE_DATATYPE FracX = (a_X) - BaseX; const NOISE_DATATYPE x1interp1 = CubicInterpolate(points1[0][0], points1[0][1], points1[0][2], points1[0][3], FracX); const NOISE_DATATYPE x1interp2 = CubicInterpolate(points1[1][0], points1[1][1], points1[1][2], points1[1][3], FracX); const NOISE_DATATYPE x1interp3 = CubicInterpolate(points1[2][0], points1[2][1], points1[2][2], points1[2][3], FracX); const NOISE_DATATYPE x1interp4 = CubicInterpolate(points1[3][0], points1[3][1], points1[3][2], points1[3][3], FracX); const NOISE_DATATYPE points2[4][4] = { { IntNoise3D(BaseX - 1, BaseY - 1, BaseZ), IntNoise3D(BaseX, BaseY - 1, BaseZ), IntNoise3D(BaseX + 1, BaseY - 1, BaseZ), IntNoise3D(BaseX + 2, BaseY - 1, BaseZ), }, { IntNoise3D(BaseX - 1, BaseY, BaseZ), IntNoise3D(BaseX, BaseY, BaseZ), IntNoise3D(BaseX + 1, BaseY, BaseZ), IntNoise3D(BaseX + 2, BaseY, BaseZ), }, { IntNoise3D(BaseX - 1, BaseY + 1, BaseZ), IntNoise3D(BaseX, BaseY + 1, BaseZ), IntNoise3D(BaseX + 1, BaseY + 1, BaseZ), IntNoise3D(BaseX + 2, BaseY + 1, BaseZ), }, { IntNoise3D(BaseX - 1, BaseY + 2, BaseZ), IntNoise3D(BaseX, BaseY + 2, BaseZ), IntNoise3D(BaseX + 1, BaseY + 2, BaseZ), IntNoise3D(BaseX + 2, BaseY + 2, BaseZ), }, }; const NOISE_DATATYPE x2interp1 = CubicInterpolate(points2[0][0], points2[0][1], points2[0][2], points2[0][3], FracX); const NOISE_DATATYPE x2interp2 = CubicInterpolate(points2[1][0], points2[1][1], points2[1][2], points2[1][3], FracX); const NOISE_DATATYPE x2interp3 = CubicInterpolate(points2[2][0], points2[2][1], points2[2][2], points2[2][3], FracX); const NOISE_DATATYPE x2interp4 = CubicInterpolate(points2[3][0], points2[3][1], points2[3][2], points2[3][3], FracX); const NOISE_DATATYPE points3[4][4] = { { IntNoise3D(BaseX - 1, BaseY - 1, BaseZ + 1), IntNoise3D(BaseX, BaseY - 1, BaseZ + 1), IntNoise3D(BaseX + 1, BaseY - 1, BaseZ + 1), IntNoise3D(BaseX + 2, BaseY - 1, BaseZ + 1), }, { IntNoise3D(BaseX - 1, BaseY, BaseZ + 1), IntNoise3D(BaseX, BaseY, BaseZ + 1), IntNoise3D(BaseX + 1, BaseY, BaseZ + 1), IntNoise3D(BaseX + 2, BaseY, BaseZ + 1), }, { IntNoise3D(BaseX - 1, BaseY + 1, BaseZ + 1), IntNoise3D(BaseX, BaseY + 1, BaseZ + 1), IntNoise3D(BaseX + 1, BaseY + 1, BaseZ + 1), IntNoise3D(BaseX + 2, BaseY + 1, BaseZ + 1), }, { IntNoise3D(BaseX - 1, BaseY + 2, BaseZ + 1), IntNoise3D(BaseX, BaseY + 2, BaseZ + 1), IntNoise3D(BaseX + 1, BaseY + 2, BaseZ + 1), IntNoise3D(BaseX + 2, BaseY + 2, BaseZ + 1), }, }; const NOISE_DATATYPE x3interp1 = CubicInterpolate(points3[0][0], points3[0][1], points3[0][2], points3[0][3], FracX); const NOISE_DATATYPE x3interp2 = CubicInterpolate(points3[1][0], points3[1][1], points3[1][2], points3[1][3], FracX); const NOISE_DATATYPE x3interp3 = CubicInterpolate(points3[2][0], points3[2][1], points3[2][2], points3[2][3], FracX); const NOISE_DATATYPE x3interp4 = CubicInterpolate(points3[3][0], points3[3][1], points3[3][2], points3[3][3], FracX); const NOISE_DATATYPE points4[4][4] = { { IntNoise3D(BaseX - 1, BaseY - 1, BaseZ + 2), IntNoise3D(BaseX, BaseY - 1, BaseZ + 2), IntNoise3D(BaseX + 1, BaseY - 1, BaseZ + 2), IntNoise3D(BaseX + 2, BaseY - 1, BaseZ + 2), }, { IntNoise3D(BaseX - 1, BaseY, BaseZ + 2), IntNoise3D(BaseX, BaseY, BaseZ + 2), IntNoise3D(BaseX + 1, BaseY, BaseZ + 2), IntNoise3D(BaseX + 2, BaseY, BaseZ + 2), }, { IntNoise3D(BaseX - 1, BaseY + 1, BaseZ + 2), IntNoise3D(BaseX, BaseY + 1, BaseZ + 2), IntNoise3D(BaseX + 1, BaseY + 1, BaseZ + 2), IntNoise3D(BaseX + 2, BaseY + 1, BaseZ + 2), }, { IntNoise3D(BaseX - 1, BaseY + 2, BaseZ + 2), IntNoise3D(BaseX, BaseY + 2, BaseZ + 2), IntNoise3D(BaseX + 1, BaseY + 2, BaseZ + 2), IntNoise3D(BaseX + 2, BaseY + 2, BaseZ + 2), }, }; const NOISE_DATATYPE x4interp1 = CubicInterpolate(points4[0][0], points4[0][1], points4[0][2], points4[0][3], FracX); const NOISE_DATATYPE x4interp2 = CubicInterpolate(points4[1][0], points4[1][1], points4[1][2], points4[1][3], FracX); const NOISE_DATATYPE x4interp3 = CubicInterpolate(points4[2][0], points4[2][1], points4[2][2], points4[2][3], FracX); const NOISE_DATATYPE x4interp4 = CubicInterpolate(points4[3][0], points4[3][1], points4[3][2], points4[3][3], FracX); const NOISE_DATATYPE FracY = (a_Y) - BaseY; const NOISE_DATATYPE yinterp1 = CubicInterpolate(x1interp1, x1interp2, x1interp3, x1interp4, FracY); const NOISE_DATATYPE yinterp2 = CubicInterpolate(x2interp1, x2interp2, x2interp3, x2interp4, FracY); const NOISE_DATATYPE yinterp3 = CubicInterpolate(x3interp1, x3interp2, x3interp3, x3interp4, FracY); const NOISE_DATATYPE yinterp4 = CubicInterpolate(x4interp1, x4interp2, x4interp3, x4interp4, FracY); const NOISE_DATATYPE FracZ = (a_Z) - BaseZ; return CubicInterpolate(yinterp1, yinterp2, yinterp3, yinterp4, FracZ); } //////////////////////////////////////////////////////////////////////////////// // cCubicNoise: cCubicNoise::cCubicNoise(int a_Seed) : m_Noise(a_Seed) { } void cCubicNoise::Generate2D( NOISE_DATATYPE * a_Array, ///< Array to generate into [x + a_SizeX * y] int a_SizeX, int a_SizeY, ///< Size of the array (num doubles), in each direction NOISE_DATATYPE a_StartX, NOISE_DATATYPE a_EndX, ///< Noise-space coords of the array in the X direction NOISE_DATATYPE a_StartY, NOISE_DATATYPE a_EndY ///< Noise-space coords of the array in the Y direction ) const { ASSERT(a_SizeX > 0); ASSERT(a_SizeY > 0); ASSERT(a_SizeX < MAX_SIZE); ASSERT(a_SizeY < MAX_SIZE); ASSERT(a_StartX < a_EndX); ASSERT(a_StartY < a_EndY); // Calculate the integral and fractional parts of each coord: int FloorX[MAX_SIZE]; int FloorY[MAX_SIZE]; NOISE_DATATYPE FracX[MAX_SIZE]; NOISE_DATATYPE FracY[MAX_SIZE]; int SameX[MAX_SIZE]; int SameY[MAX_SIZE]; int NumSameX, NumSameY; CalcFloorFrac(a_SizeX, a_StartX, a_EndX, FloorX, FracX, SameX, NumSameX); CalcFloorFrac(a_SizeY, a_StartY, a_EndY, FloorY, FracY, SameY, NumSameY); cCubicCell2D Cell(m_Noise, a_Array, a_SizeX, a_SizeY, FracX, FracY); Cell.InitWorkRnds(FloorX[0], FloorY[0]); // Calculate query values using Cell: int FromY = 0; for (int y = 0; y < NumSameY;) { int ToY = FromY + SameY[y]; int FromX = 0; int CurFloorY = FloorY[FromY]; for (int x = 0; x < NumSameX;) { int ToX = FromX + SameX[x]; Cell.Generate(FromX, ToX, FromY, ToY); if (++x < NumSameX) // Call Move() every time except for the last loop iteration { Cell.Move(FloorX[ToX], CurFloorY); FromX = ToX; } } if (++y < NumSameY) // Call Move() every time except for the last loop iteration { Cell.Move(FloorX[0], FloorY[ToY]); FromY = ToY; } } } void cCubicNoise::Generate3D( NOISE_DATATYPE * a_Array, ///< Array to generate into [x + a_SizeX * y] int a_SizeX, int a_SizeY, int a_SizeZ, ///< Size of the array (num doubles), in each direction NOISE_DATATYPE a_StartX, NOISE_DATATYPE a_EndX, ///< Noise-space coords of the array in the X direction NOISE_DATATYPE a_StartY, NOISE_DATATYPE a_EndY, ///< Noise-space coords of the array in the Y direction NOISE_DATATYPE a_StartZ, NOISE_DATATYPE a_EndZ ///< Noise-space coords of the array in the Y direction ) const { ASSERT(a_SizeX < MAX_SIZE); ASSERT(a_SizeY < MAX_SIZE); ASSERT(a_SizeZ < MAX_SIZE); ASSERT(a_StartX < a_EndX); ASSERT(a_StartY < a_EndY); ASSERT(a_StartZ < a_EndZ); // Calculate the integral and fractional parts of each coord: int FloorX[MAX_SIZE]; int FloorY[MAX_SIZE]; int FloorZ[MAX_SIZE]; NOISE_DATATYPE FracX[MAX_SIZE]; NOISE_DATATYPE FracY[MAX_SIZE]; NOISE_DATATYPE FracZ[MAX_SIZE]; int SameX[MAX_SIZE]; int SameY[MAX_SIZE]; int SameZ[MAX_SIZE]; int NumSameX, NumSameY, NumSameZ; CalcFloorFrac(a_SizeX, a_StartX, a_EndX, FloorX, FracX, SameX, NumSameX); CalcFloorFrac(a_SizeY, a_StartY, a_EndY, FloorY, FracY, SameY, NumSameY); CalcFloorFrac(a_SizeZ, a_StartZ, a_EndZ, FloorZ, FracZ, SameZ, NumSameZ); cCubicCell3D Cell( m_Noise, a_Array, a_SizeX, a_SizeY, a_SizeZ, FracX, FracY, FracZ ); Cell.InitWorkRnds(FloorX[0], FloorY[0], FloorZ[0]); // Calculate query values using Cell: int FromZ = 0; for (int z = 0; z < NumSameZ;) { int ToZ = FromZ + SameZ[z]; int CurFloorZ = FloorZ[FromZ]; int FromY = 0; for (int y = 0; y < NumSameY;) { int ToY = FromY + SameY[y]; int CurFloorY = FloorY[FromY]; int FromX = 0; for (int x = 0; x < NumSameX;) { int ToX = FromX + SameX[x]; Cell.Generate(FromX, ToX, FromY, ToY, FromZ, ToZ); if (++x < NumSameX) // Call Move() every time except for the last loop iteration { Cell.Move(FloorX[ToX], CurFloorY, CurFloorZ); FromX = ToX; } } if (++y < NumSameY) // Call Move() every time except for the last loop iteration { Cell.Move(FloorX[0], FloorY[ToY], CurFloorZ); FromY = ToY; } } // for y if (++z < NumSameZ) // Call Move() every time except for the last loop iteration { Cell.Move(FloorX[0], FloorY[0], FloorZ[ToZ]); FromZ = ToZ; } } // for z } void cCubicNoise::CalcFloorFrac( int a_Size, NOISE_DATATYPE a_Start, NOISE_DATATYPE a_End, int * a_Floor, NOISE_DATATYPE * a_Frac, int * a_Same, int & a_NumSame ) const { ASSERT(a_Size > 0); NOISE_DATATYPE val = a_Start; NOISE_DATATYPE dif = (a_End - a_Start) / (a_Size - 1); for (int i = 0; i < a_Size; i++) { a_Floor[i] = FAST_FLOOR(val); a_Frac[i] = val - a_Floor[i]; val += dif; } // Mark up the same floor values into a_Same / a_NumSame: int CurFloor = a_Floor[0]; int LastSame = 0; a_NumSame = 0; for (int i = 1; i < a_Size; i++) { if (a_Floor[i] != CurFloor) { a_Same[a_NumSame] = i - LastSame; LastSame = i; a_NumSame += 1; CurFloor = a_Floor[i]; } } // for i - a_Floor[] if (LastSame < a_Size) { a_Same[a_NumSame] = a_Size - LastSame; a_NumSame += 1; } } //////////////////////////////////////////////////////////////////////////////// // cImprovedNoise: cImprovedNoise::cImprovedNoise(int a_Seed) { // Initialize the permutations with identity: for (int i = 0; i < 256; i++) { m_Perm[i] = i; } // Randomize the permutation table - swap each element with a random other element: cNoise noise(a_Seed); for (int i = 0; i < 256; i++) { int rnd = (noise.IntNoise1DInt(i) / 7) % 256; std::swap(m_Perm[i], m_Perm[rnd]); } // Copy the lower 256 entries into upper 256 entries: for (int i = 0; i < 256; i++) { m_Perm[i + 256] = m_Perm[i]; } } void cImprovedNoise::Generate2D( NOISE_DATATYPE * a_Array, int a_SizeX, int a_SizeY, NOISE_DATATYPE a_StartX, NOISE_DATATYPE a_EndX, NOISE_DATATYPE a_StartY, NOISE_DATATYPE a_EndY ) const { size_t idx = 0; for (int y = 0; y < a_SizeY; y++) { NOISE_DATATYPE ratioY = static_cast(y) / (a_SizeY - 1); NOISE_DATATYPE noiseY = Lerp(a_StartY, a_EndY, ratioY); int noiseYInt = FAST_FLOOR(noiseY); int yCoord = noiseYInt & 255; NOISE_DATATYPE noiseYFrac = noiseY - noiseYInt; NOISE_DATATYPE fadeY = Fade(noiseYFrac); for (int x = 0; x < a_SizeX; x++) { NOISE_DATATYPE ratioX = static_cast(x) / (a_SizeX - 1); NOISE_DATATYPE noiseX = Lerp(a_StartX, a_EndX, ratioX); int noiseXInt = FAST_FLOOR(noiseX); int xCoord = noiseXInt & 255; NOISE_DATATYPE noiseXFrac = noiseX - noiseXInt; NOISE_DATATYPE fadeX = Fade(noiseXFrac); // Hash the coordinates: int A = m_Perm[xCoord] + yCoord; int AA = m_Perm[A]; int AB = m_Perm[A + 1]; int B = m_Perm[xCoord + 1] + yCoord; int BA = m_Perm[B]; int BB = m_Perm[B + 1]; // Lerp the gradients: a_Array[idx++] = Lerp( Lerp(Grad(m_Perm[AA], noiseXFrac, noiseYFrac, 0), Grad(m_Perm[BA], noiseXFrac - 1, noiseYFrac, 0), fadeX), Lerp(Grad(m_Perm[AB], noiseXFrac, noiseYFrac - 1, 0), Grad(m_Perm[BB], noiseXFrac - 1, noiseYFrac - 1, 0), fadeX), fadeY ); } // for x } // for y } void cImprovedNoise::Generate3D( NOISE_DATATYPE * a_Array, int a_SizeX, int a_SizeY, int a_SizeZ, NOISE_DATATYPE a_StartX, NOISE_DATATYPE a_EndX, NOISE_DATATYPE a_StartY, NOISE_DATATYPE a_EndY, NOISE_DATATYPE a_StartZ, NOISE_DATATYPE a_EndZ ) const { size_t idx = 0; for (int z = 0; z < a_SizeZ; z++) { NOISE_DATATYPE ratioZ = static_cast(z) / (a_SizeZ - 1); NOISE_DATATYPE noiseZ = Lerp(a_StartZ, a_EndZ, ratioZ); int noiseZInt = FAST_FLOOR(noiseZ); int zCoord = noiseZInt & 255; NOISE_DATATYPE noiseZFrac = noiseZ - noiseZInt; NOISE_DATATYPE fadeZ = Fade(noiseZFrac); for (int y = 0; y < a_SizeY; y++) { NOISE_DATATYPE ratioY = static_cast(y) / (a_SizeY - 1); NOISE_DATATYPE noiseY = Lerp(a_StartY, a_EndY, ratioY); int noiseYInt = FAST_FLOOR(noiseY); int yCoord = noiseYInt & 255; NOISE_DATATYPE noiseYFrac = noiseY - noiseYInt; NOISE_DATATYPE fadeY = Fade(noiseYFrac); for (int x = 0; x < a_SizeX; x++) { NOISE_DATATYPE ratioX = static_cast(x) / (a_SizeX - 1); NOISE_DATATYPE noiseX = Lerp(a_StartX, a_EndX, ratioX); int noiseXInt = FAST_FLOOR(noiseX); int xCoord = noiseXInt & 255; NOISE_DATATYPE noiseXFrac = noiseX - noiseXInt; NOISE_DATATYPE fadeX = Fade(noiseXFrac); // Hash the coordinates: int A = m_Perm[xCoord] + yCoord; int AA = m_Perm[A] + zCoord; int AB = m_Perm[A + 1] + zCoord; int B = m_Perm[xCoord + 1] + yCoord; int BA = m_Perm[B] + zCoord; int BB = m_Perm[B + 1] + zCoord; // Lerp the gradients: // TODO: This may be optimized by swapping the coords and recalculating most lerps only "once every x" a_Array[idx++] = Lerp( Lerp( Lerp(Grad(m_Perm[AA], noiseXFrac, noiseYFrac, noiseZFrac), Grad(m_Perm[BA], noiseXFrac - 1, noiseYFrac, noiseZFrac), fadeX), Lerp(Grad(m_Perm[AB], noiseXFrac, noiseYFrac - 1, noiseZFrac), Grad(m_Perm[BB], noiseXFrac - 1, noiseYFrac - 1, noiseZFrac), fadeX), fadeY ), Lerp( Lerp(Grad(m_Perm[AA + 1], noiseXFrac, noiseYFrac, noiseZFrac - 1), Grad(m_Perm[BA + 1], noiseXFrac - 1, noiseYFrac, noiseZFrac - 1), fadeX), Lerp(Grad(m_Perm[AB + 1], noiseXFrac, noiseYFrac - 1, noiseZFrac - 1), Grad(m_Perm[BB + 1], noiseXFrac - 1, noiseYFrac - 1, noiseZFrac - 1), fadeX), fadeY ), fadeZ ); } // for x } // for y } // for z } NOISE_DATATYPE cImprovedNoise::GetValueAt(int a_X, int a_Y, int a_Z) { // Hash the coordinates: a_X = a_X & 255; a_Y = a_Y & 255; a_Z = a_Z & 255; int A = m_Perm[a_X] + a_Y; int AA = m_Perm[A] + a_Z; return Grad(m_Perm[AA], 1, 1, 1); } ================================================ FILE: src/Noise/Noise.h ================================================ // Noise.h // Declares the cNoise, cCubicNoise and cPerlinNoise classes for generating noise #pragma once /** The datatype used by all the noise generators. */ typedef float NOISE_DATATYPE; #include "../Vector3.h" #include "OctavedNoise.h" #include "RidgedNoise.h" class cNoise { public: cNoise(int a_Seed); cNoise(const cNoise & a_Noise); // The following functions, if not marked INLINE, are about 20 % slower inline NOISE_DATATYPE IntNoise1D(int a_X) const; inline NOISE_DATATYPE IntNoise2D(int a_X, int a_Y) const; inline NOISE_DATATYPE IntNoise3D(int a_X, int a_Y, int a_Z) const; inline NOISE_DATATYPE IntNoise3D(Vector3i a_Pos) const; // Return a float number in the specified range: inline NOISE_DATATYPE IntNoise2DInRange(int a_X, int a_Y, float a_Min, float a_Max) const { return a_Min + std::abs(IntNoise2D(a_X, a_Y)) * (a_Max - a_Min); } // Note: These functions have a mod8-irregular chance - each of the mod8 remainders has different chance of occurrence. Divide by 8 to rectify. inline int IntNoise1DInt(int a_X) const; inline int IntNoise2DInt(int a_X, int a_Y) const; inline int IntNoise3DInt(int a_X, int a_Y, int a_Z) const; inline int IntNoise3DInt(Vector3i a_Pos) const; NOISE_DATATYPE LinearNoise1D(NOISE_DATATYPE a_X) const; NOISE_DATATYPE CosineNoise1D(NOISE_DATATYPE a_X) const; NOISE_DATATYPE CubicNoise1D (NOISE_DATATYPE a_X) const; NOISE_DATATYPE SmoothNoise1D(int a_X) const; NOISE_DATATYPE CubicNoise2D (NOISE_DATATYPE a_X, NOISE_DATATYPE a_Y) const; NOISE_DATATYPE CubicNoise3D (NOISE_DATATYPE a_X, NOISE_DATATYPE a_Y, NOISE_DATATYPE a_Z) const; void SetSeed(int a_Seed) { m_Seed = a_Seed; } int GetSeed(void) const { return m_Seed; } inline static NOISE_DATATYPE CubicInterpolate (NOISE_DATATYPE a_A, NOISE_DATATYPE a_B, NOISE_DATATYPE a_C, NOISE_DATATYPE a_D, NOISE_DATATYPE a_Pct); inline static NOISE_DATATYPE CosineInterpolate(NOISE_DATATYPE a_A, NOISE_DATATYPE a_B, NOISE_DATATYPE a_Pct); inline static NOISE_DATATYPE LinearInterpolate(NOISE_DATATYPE a_A, NOISE_DATATYPE a_B, NOISE_DATATYPE a_Pct); private: int m_Seed; } ; class cCubicNoise { public: /** Maximum size of each dimension of the query arrays. */ static const int MAX_SIZE = 512; /** Creates a new instance with the specified seed. */ cCubicNoise(int a_Seed); /** Fills a 2D array with the values of the noise. */ void Generate2D( NOISE_DATATYPE * a_Array, ///< Array to generate into [x + a_SizeX * y] int a_SizeX, int a_SizeY, ///< Count of the array, in each direction NOISE_DATATYPE a_StartX, NOISE_DATATYPE a_EndX, ///< Noise-space coords of the array in the X direction NOISE_DATATYPE a_StartY, NOISE_DATATYPE a_EndY ///< Noise-space coords of the array in the Y direction ) const; /** Fills a 3D array with the values of the noise. */ void Generate3D( NOISE_DATATYPE * a_Array, ///< Array to generate into [x + a_SizeX * y + a_SizeX * a_SizeY * z] int a_SizeX, int a_SizeY, int a_SizeZ, ///< Count of the array, in each direction NOISE_DATATYPE a_StartX, NOISE_DATATYPE a_EndX, ///< Noise-space coords of the array in the X direction NOISE_DATATYPE a_StartY, NOISE_DATATYPE a_EndY, ///< Noise-space coords of the array in the Y direction NOISE_DATATYPE a_StartZ, NOISE_DATATYPE a_EndZ ///< Noise-space coords of the array in the Z direction ) const; protected: /** Noise used for integral random values. */ cNoise m_Noise; /** Calculates the integral and fractional parts along one axis. a_Floor will receive the integral parts (array of a_Size ints). a_Frac will receive the fractional parts (array of a_Size floats). a_Same will receive the counts of items that have the same integral parts (array of up to a_Size ints). a_NumSame will receive the count of a_Same elements (total count of different integral parts). */ void CalcFloorFrac( int a_Size, NOISE_DATATYPE a_Start, NOISE_DATATYPE a_End, int * a_Floor, NOISE_DATATYPE * a_Frac, int * a_Same, int & a_NumSame ) const; } ; /** Improved noise, as described by Ken Perlin: https://mrl.nyu.edu/~perlin/paper445.pdf Implementation adapted from Perlin's Java implementation: https://mrl.nyu.edu/~perlin/noise/ */ class cImprovedNoise { public: /** Constructs a new instance of the noise obbject. Note that this operation is quite expensive (the permutation array being constructed). */ cImprovedNoise(int a_Seed); /** Fills a 2D array with the values of the noise. */ void Generate2D( NOISE_DATATYPE * a_Array, ///< Array to generate into [x + a_SizeX * y] int a_SizeX, int a_SizeY, ///< Count of the array, in each direction NOISE_DATATYPE a_StartX, NOISE_DATATYPE a_EndX, ///< Noise-space coords of the array in the X direction NOISE_DATATYPE a_StartY, NOISE_DATATYPE a_EndY ///< Noise-space coords of the array in the Y direction ) const; /** Fills a 3D array with the values of the noise. */ void Generate3D( NOISE_DATATYPE * a_Array, ///< Array to generate into [x + a_SizeX * y + a_SizeX * a_SizeY * z] int a_SizeX, int a_SizeY, int a_SizeZ, ///< Count of the array, in each direction NOISE_DATATYPE a_StartX, NOISE_DATATYPE a_EndX, ///< Noise-space coords of the array in the X direction NOISE_DATATYPE a_StartY, NOISE_DATATYPE a_EndY, ///< Noise-space coords of the array in the Y direction NOISE_DATATYPE a_StartZ, NOISE_DATATYPE a_EndZ ///< Noise-space coords of the array in the Z direction ) const; /** Returns the value at the specified integral coords. Used for raw speed measurement. */ NOISE_DATATYPE GetValueAt(int a_X, int a_Y, int a_Z); protected: /** The permutation table used by the noise function. Initialized using seed. */ int m_Perm[512]; /** Calculates the fade curve, 6 * t^5 - 15 * t^4 + 10 * t^3. */ inline static NOISE_DATATYPE Fade(NOISE_DATATYPE a_T) { return a_T * a_T * a_T * (a_T * (a_T * 6 - 15) + 10); } /** Returns the gradient value based on the hash. */ inline static NOISE_DATATYPE Grad(int a_Hash, NOISE_DATATYPE a_X, NOISE_DATATYPE a_Y, NOISE_DATATYPE a_Z) { int hash = a_Hash % 16; NOISE_DATATYPE u = (hash < 8) ? a_X : a_Y; NOISE_DATATYPE v = (hash < 4) ? a_Y : (((hash == 12) || (hash == 14)) ? a_X : a_Z); return (((hash & 1) == 0) ? u : -u) + (((hash & 2) == 0) ? v : -v); } }; typedef cOctavedNoise cPerlinNoise; typedef cOctavedNoise> cRidgedMultiNoise; //////////////////////////////////////////////////////////////////////////////// // Inline function definitions: // These need to be in the header, otherwise linker error occur in MSVC NOISE_DATATYPE cNoise::IntNoise1D(int a_X) const { int x = ((a_X * m_Seed) << 13) ^ a_X; return (1 - static_cast((x * (x * x * 15731 + 789221) + 1376312589) & 0x7fffffff) / 1073741824); // returns a float number in the range of [-1, 1] } NOISE_DATATYPE cNoise::IntNoise2D(int a_X, int a_Y) const { int n = a_X + a_Y * 57 + m_Seed * 57 * 57; n = (n << 13) ^ n; return (1 - static_cast((n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) / 1073741824); // returns a float number in the range of [-1, 1] } NOISE_DATATYPE cNoise::IntNoise3D(int a_X, int a_Y, int a_Z) const { int n = a_X + a_Y * 57 + a_Z * 57 * 57 + m_Seed * 57 * 57 * 57; n = (n << 13) ^ n; return (static_cast(1) - static_cast((n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) / 1073741824.0f ); // returns a float number in the range of [-1, 1] } NOISE_DATATYPE cNoise::IntNoise3D(Vector3i a_Pos) const { return IntNoise3D(a_Pos.x, a_Pos.y, a_Pos.z); } int cNoise::IntNoise1DInt(int a_X) const { int x = ((a_X * m_Seed) << 13) ^ a_X; return ((x * (x * x * 15731 + 789221) + 1376312589) & 0x7fffffff); } int cNoise::IntNoise2DInt(int a_X, int a_Y) const { int n = a_X + a_Y * 57 + m_Seed * 57 * 57; n = (n << 13) ^ n; return ((n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff); } int cNoise::IntNoise3DInt(int a_X, int a_Y, int a_Z) const { int n = a_X + a_Y * 57 + a_Z * 57 * 57 + m_Seed * 57 * 57 * 57; n = (n << 13) ^ n; return ((n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff); } int cNoise::IntNoise3DInt(Vector3i a_Pos) const { return IntNoise3DInt(a_Pos.x, a_Pos.y, a_Pos.z); } NOISE_DATATYPE cNoise::CubicInterpolate(NOISE_DATATYPE a_A, NOISE_DATATYPE a_B, NOISE_DATATYPE a_C, NOISE_DATATYPE a_D, NOISE_DATATYPE a_Pct) { NOISE_DATATYPE P = (a_D - a_C) - (a_A - a_B); NOISE_DATATYPE Q = (a_A - a_B) - P; NOISE_DATATYPE R = a_C - a_A; NOISE_DATATYPE S = a_B; return ((P * a_Pct + Q) * a_Pct + R) * a_Pct + S; } NOISE_DATATYPE cNoise::CosineInterpolate(NOISE_DATATYPE a_A, NOISE_DATATYPE a_B, NOISE_DATATYPE a_Pct) { const NOISE_DATATYPE ft = a_Pct * static_cast(3.1415927); const NOISE_DATATYPE f = static_cast(static_cast(1 - cos(ft)) * static_cast(0.5)); return a_A * (1 - f) + a_B * f; } NOISE_DATATYPE cNoise::LinearInterpolate(NOISE_DATATYPE a_A, NOISE_DATATYPE a_B, NOISE_DATATYPE a_Pct) { return a_A * (1 - a_Pct) + a_B * a_Pct; } //////////////////////////////////////////////////////////////////////////////// // Global functions: /** Exports the noise array into a file. a_Coeff specifies the value that each array value is multiplied by before being converted into a byte. */ extern void Debug2DNoise(const NOISE_DATATYPE * a_Array, size_t a_SizeX, size_t a_SizeY, const AString & a_FileNameBase, NOISE_DATATYPE a_Coeff = 32); /** Exports the noise array into a set of files, ordered by XY and XZ. a_Coeff specifies the value that each array value is multiplied by before being converted into a byte. */ extern void Debug3DNoise(const NOISE_DATATYPE * a_Array, size_t a_SizeX, size_t a_SizeY, size_t a_SizeZ, const AString & a_FileNameBase, NOISE_DATATYPE a_Coeff = 32); /** Linearly interpolates between two values. Assumes that a_Ratio is in range [0, 1]. */ inline NOISE_DATATYPE Lerp(NOISE_DATATYPE a_Val1, NOISE_DATATYPE a_Val2, NOISE_DATATYPE a_Ratio) { return a_Val1 + (a_Val2 - a_Val1) * a_Ratio; } /** Linearly interpolates between two values, clamping the ratio to [0, 1] first. */ inline NOISE_DATATYPE ClampedLerp(NOISE_DATATYPE a_Val1, NOISE_DATATYPE a_Val2, NOISE_DATATYPE a_Ratio) { if (a_Ratio < 0) { return a_Val1; } if (a_Ratio > 1) { return a_Val2; } return Lerp(a_Val1, a_Val2, a_Ratio); } ================================================ FILE: src/Noise/OctavedNoise.h ================================================ // OctavedNoise.h // Implements the cOctavedNoise class template representing a noise generator that layers several octaves of another noise #pragma once template class cOctavedNoise { public: cOctavedNoise(int a_Seed = 0): m_Seed(a_Seed) { } /** Sets a new seed for the generators. Relays the seed to all underlying octaves. */ void SetSeed(int a_Seed) { m_Seed = a_Seed; for (auto oct: m_Octaves) { oct->SetSeed(a_Seed); } } /** Adds a new octave to the list of octaves that compose this noise. */ void AddOctave(NOISE_DATATYPE a_Frequency, NOISE_DATATYPE a_Amplitude) { m_Octaves.emplace_back(m_Seed, a_Frequency, a_Amplitude); } /** Fills a 2D array with the values of the noise. */ void Generate2D( NOISE_DATATYPE * a_Array, ///< Array to generate into [x + a_SizeX * y] int a_SizeX, int a_SizeY, ///< Count of the array, in each direction NOISE_DATATYPE a_StartX, NOISE_DATATYPE a_EndX, ///< Noise-space coords of the array in the X direction NOISE_DATATYPE a_StartY, NOISE_DATATYPE a_EndY, ///< Noise-space coords of the array in the Y direction NOISE_DATATYPE * a_Workspace = nullptr ///< Workspace that this function can use and trash. ) const { // Check that state is alright: if (m_Octaves.empty()) { ASSERT(!"cOctavedNoise: No octaves to generate!"); return; } // Allocate the workspace on the heap, if it wasn't given: std::unique_ptr workspaceHeap; if (a_Workspace == nullptr) { workspaceHeap.reset(new NOISE_DATATYPE[ToUnsigned(a_SizeX * a_SizeY)]); a_Workspace = workspaceHeap.get(); } // Generate the first octave directly into array: int ArrayCount = a_SizeX * a_SizeY; { const cOctave & FirstOctave = m_Octaves.front(); FirstOctave.m_Noise.Generate2D( a_Workspace, a_SizeX, a_SizeY, a_StartX * FirstOctave.m_Frequency, a_EndX * FirstOctave.m_Frequency, a_StartY * FirstOctave.m_Frequency, a_EndY * FirstOctave.m_Frequency ); NOISE_DATATYPE Amplitude = FirstOctave.m_Amplitude; for (int i = 0; i < ArrayCount; i++) { a_Array[i] = a_Workspace[i] * Amplitude; } } // Add each octave: for (auto itr = m_Octaves.cbegin() + 1, end = m_Octaves.cend(); itr != end; ++itr) { // Generate the noise for the octave: itr->m_Noise.Generate2D( a_Workspace, a_SizeX, a_SizeY, a_StartX * itr->m_Frequency, a_EndX * itr->m_Frequency, a_StartY * itr->m_Frequency, a_EndY * itr->m_Frequency ); // Add it into the output: NOISE_DATATYPE Amplitude = itr->m_Amplitude; for (int i = 0; i < ArrayCount; i++) { a_Array[i] += a_Workspace[i] * Amplitude; } } // for itr - m_Octaves[] } /** Fills a 3D array with the values of the noise. */ void Generate3D( NOISE_DATATYPE * a_Array, ///< Array to generate into [x + a_SizeX * y + a_SizeX * a_SizeY * z] int a_SizeX, int a_SizeY, int a_SizeZ, ///< Count of the array, in each direction NOISE_DATATYPE a_StartX, NOISE_DATATYPE a_EndX, ///< Noise-space coords of the array in the X direction NOISE_DATATYPE a_StartY, NOISE_DATATYPE a_EndY, ///< Noise-space coords of the array in the Y direction NOISE_DATATYPE a_StartZ, NOISE_DATATYPE a_EndZ, ///< Noise-space coords of the array in the Z direction NOISE_DATATYPE * a_Workspace = nullptr ///< Workspace that this function can use and trash, same size as a_Array ) const { // Check that state is alright: if (m_Octaves.empty()) { ASSERT(!"cOctavedNoise: No octaves to generate!"); return; } // Allocate the workspace on the heap, if it wasn't given: std::unique_ptr workspaceHeap; if (a_Workspace == nullptr) { workspaceHeap.reset(new NOISE_DATATYPE[ToUnsigned(a_SizeX * a_SizeY * a_SizeZ)]); a_Workspace = workspaceHeap.get(); } // Generate the first octave directly into array: int ArrayCount = a_SizeX * a_SizeY * a_SizeZ; { const cOctave & FirstOctave = m_Octaves.front(); FirstOctave.m_Noise.Generate3D( a_Workspace, a_SizeX, a_SizeY, a_SizeZ, a_StartX * FirstOctave.m_Frequency, a_EndX * FirstOctave.m_Frequency, a_StartY * FirstOctave.m_Frequency, a_EndY * FirstOctave.m_Frequency, a_StartZ * FirstOctave.m_Frequency, a_EndZ * FirstOctave.m_Frequency ); NOISE_DATATYPE Amplitude = FirstOctave.m_Amplitude; for (int i = 0; i < ArrayCount; i++) { a_Array[i] = a_Workspace[i] * Amplitude; } } // Add each octave: for (auto itr = m_Octaves.cbegin() + 1, end = m_Octaves.cend(); itr != end; ++itr) { // Generate the noise for the octave: itr->m_Noise.Generate3D( a_Workspace, a_SizeX, a_SizeY, a_SizeZ, a_StartX * itr->m_Frequency, a_EndX * itr->m_Frequency, a_StartY * itr->m_Frequency, a_EndY * itr->m_Frequency, a_StartZ * itr->m_Frequency, a_EndZ * itr->m_Frequency ); // Add it into the output: NOISE_DATATYPE Amplitude = itr->m_Amplitude; for (int i = 0; i < ArrayCount; i++) { a_Array[i] += a_Workspace[i] * Amplitude; } } // for itr - m_Octaves[] } protected: /** Stores information and state for one octave of the noise. */ class cOctave { public: N m_Noise; /** Coord multiplier. */ NOISE_DATATYPE m_Frequency; /** Value multiplier. */ NOISE_DATATYPE m_Amplitude; cOctave(int a_Seed, NOISE_DATATYPE a_Frequency, NOISE_DATATYPE a_Amplitude) : m_Noise(a_Seed), m_Frequency(a_Frequency), m_Amplitude(a_Amplitude) { } } ; typedef std::vector cOctaves; /** The seed used by the underlying generators. */ int m_Seed; /** The octaves that compose this noise. */ cOctaves m_Octaves; }; ================================================ FILE: src/Noise/RidgedNoise.h ================================================ // RidgedNoise.h // Implements the cRidgedNoise template class that generates ridged noise based on another noise provider. #pragma once template class cRidgedNoise { public: /** Creates a new instance with the seed set to 0. */ cRidgedNoise(void): m_Noise(0) { } /** Creates a new instance with the specified seed. */ cRidgedNoise(int a_Seed): m_Noise(a_Seed) { } /** Sets the seed for the underlying noise. */ void SetSeed(int a_Seed) { m_Noise.SetSeed(a_Seed); } /** Fills a 2D array with the values of the noise. */ void Generate2D( NOISE_DATATYPE * a_Array, ///< Array to generate into [x + a_SizeX * y] int a_SizeX, int a_SizeY, ///< Count of the array, in each direction NOISE_DATATYPE a_StartX, NOISE_DATATYPE a_EndX, ///< Noise-space coords of the array in the X direction NOISE_DATATYPE a_StartY, NOISE_DATATYPE a_EndY ///< Noise-space coords of the array in the Y direction ) const { int ArrayCount = a_SizeX * a_SizeY; m_Noise.Generate2D( a_Array, a_SizeX, a_SizeY, a_StartX, a_EndX, a_StartY, a_EndY ); for (int i = 0; i < ArrayCount; i++) { a_Array[i] = std::abs(a_Array[i]); } } /** Fills a 3D array with the values of the noise. */ void Generate3D( NOISE_DATATYPE * a_Array, ///< Array to generate into [x + a_SizeX * y + a_SizeX * a_SizeY * z] int a_SizeX, int a_SizeY, int a_SizeZ, ///< Count of the array, in each direction NOISE_DATATYPE a_StartX, NOISE_DATATYPE a_EndX, ///< Noise-space coords of the array in the X direction NOISE_DATATYPE a_StartY, NOISE_DATATYPE a_EndY, ///< Noise-space coords of the array in the Y direction NOISE_DATATYPE a_StartZ, NOISE_DATATYPE a_EndZ ///< Noise-space coords of the array in the Z direction ) const { int ArrayCount = a_SizeX * a_SizeY * a_SizeZ; m_Noise.Generate2D( a_Array, a_SizeX, a_SizeY, a_SizeZ, a_StartX, a_EndX, a_StartY, a_EndY, a_StartZ, a_EndZ ); for (int i = 0; i < ArrayCount; i++) { a_Array[i] = std::abs(a_Array[i]); } } protected: N m_Noise; } ; ================================================ FILE: src/OSSupport/AtomicUniquePtr.h ================================================ #pragma once /** An RAII wrapper for std::atomic. */ template class cAtomicUniquePtr { public: static_assert(!std::is_array::value, "cAtomicUniquePtr does not support arrays"); DISALLOW_COPY_AND_ASSIGN(cAtomicUniquePtr); cAtomicUniquePtr() noexcept: m_Ptr(nullptr) { } cAtomicUniquePtr(std::unique_ptr a_Ptr) noexcept: m_Ptr(a_Ptr.release()) { } cAtomicUniquePtr & operator = (std::unique_ptr a_Ptr) noexcept { store(std::move(a_Ptr)); return *this; } ~cAtomicUniquePtr() noexcept { delete load(); } operator T * () const noexcept { return load(); } bool compare_exchange_weak(T *& a_Expected, std::unique_ptr && a_Desired, std::memory_order a_Order = std::memory_order_seq_cst) noexcept { bool DidExchange = m_Ptr.compare_exchange_weak(a_Expected, a_Desired.get(), a_Order); if (DidExchange) { // Only release ownership from the caller if the exchange occurred a_Desired.release(); } return DidExchange; } bool compare_exchange_strong(T *& a_Expected, std::unique_ptr && a_Desired, std::memory_order a_Order = std::memory_order_seq_cst) noexcept { bool DidExchange = m_Ptr.compare_exchange_strong(a_Expected, a_Desired.get(), a_Order); if (DidExchange) { // Only release ownership from the caller if the exchange occurred a_Desired.release(); } return DidExchange; } std::unique_ptr exchange(std::unique_ptr a_Ptr, std::memory_order a_Order = std::memory_order_seq_cst) noexcept { return std::unique_ptr{ m_Ptr.exchange(a_Ptr.release(), a_Order) }; } T * load(std::memory_order a_Order = std::memory_order_seq_cst) const noexcept { return m_Ptr.load(a_Order); } void store(std::unique_ptr a_Ptr, std::memory_order a_Order = std::memory_order_seq_cst) noexcept { // Store new value and delete old value delete m_Ptr.exchange(a_Ptr.release(), a_Order); } private: std::atomic m_Ptr; }; ================================================ FILE: src/OSSupport/CMakeLists.txt ================================================ target_sources( ${CMAKE_PROJECT_NAME} PRIVATE CriticalSection.cpp Event.cpp File.cpp GZipFile.cpp HostnameLookup.cpp IPLookup.cpp IsThread.cpp NetworkInterfaceEnum.cpp NetworkLookup.cpp NetworkSingleton.cpp ServerHandleImpl.cpp StackTrace.cpp TCPLinkImpl.cpp UDPEndpointImpl.cpp WinStackWalker.cpp AtomicUniquePtr.h ConsoleSignalHandler.h CriticalSection.h Event.h File.h GetAddressInfoError.h GZipFile.h HostnameLookup.h IPLookup.h IsThread.h MiniDumpWriter.h Network.h NetworkLookup.h NetworkSingleton.h Queue.h ServerHandleImpl.h SleepResolutionBooster.h StackTrace.h StartAsService.h Stopwatch.h TCPLinkImpl.h UDPEndpointImpl.h WinStackWalker.h ) ================================================ FILE: src/OSSupport/ConsoleSignalHandler.h ================================================ // ConsoleSignalHandler.h // Intercepts signals for graceful CTRL-C (and others) handling. // This file MUST NOT be included from anywhere other than main.cpp. #include // Because SIG_DFL or SIG_IGN could be NULL instead of nullptr, we need to disable the Clang warning here: #ifdef __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunknown-warning-option" #pragma clang diagnostic ignored "-Wunknown-pragmas" #pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" #endif static void NonCtrlHandler(int a_Signal) { LOGD("Terminate event raised from std::signal"); switch (a_Signal) { case SIGSEGV: { PrintStackTrace(); LOGERROR( "Failure report: \n\n" " :( | Cuberite has encountered an error and needs to close\n" " | SIGSEGV: Segmentation fault\n" " |\n" #ifdef BUILD_ID " | Cuberite " BUILD_SERIES_NAME " (id: " BUILD_ID ")\n" " | from commit " BUILD_COMMIT_ID "\n" #endif ); std::signal(SIGSEGV, SIG_DFL); return; } case SIGABRT: #ifdef SIGABRT_COMPAT case SIGABRT_COMPAT: #endif { PrintStackTrace(); LOGERROR( "Failure report: \n\n" " :( | Cuberite has encountered an error and needs to close\n" " | SIGABRT: Server self-terminated due to an internal fault\n" " |\n" #ifdef BUILD_ID " | Cuberite " BUILD_SERIES_NAME " (id: " BUILD_ID ")\n" " | from commit " BUILD_COMMIT_ID "\n" #endif ); std::signal(SIGSEGV, SIG_DFL); return; } case SIGINT: case SIGTERM: { // Server is shutting down, wait for it... cRoot::Stop(); return; } } } #ifdef __clang__ #pragma clang diagnostic pop #endif #ifdef _WIN32 /** Handle CTRL events in windows, including console window close. */ static BOOL CtrlHandler(DWORD fdwCtrlType) { cRoot::Stop(); LOGD("Terminate event raised from the Windows CtrlHandler"); // Delay as much as possible to try to get the server to shut down cleanly - 10 seconds given by Windows: std::this_thread::sleep_for(std::chrono::seconds(10)); // Returning from main() automatically aborts this handler thread. return TRUE; } #endif namespace ConsoleSignalHandler { static void Register() { std::signal(SIGSEGV, NonCtrlHandler); std::signal(SIGTERM, NonCtrlHandler); std::signal(SIGINT, NonCtrlHandler); std::signal(SIGABRT, NonCtrlHandler); #ifdef SIGABRT_COMPAT std::signal(SIGABRT_COMPAT, NonCtrlHandler); #endif #ifdef SIGPIPE std::signal(SIGPIPE, SIG_IGN); // Ignore (PR #2487). #endif #ifdef _WIN32 SetConsoleCtrlHandler(reinterpret_cast(CtrlHandler), TRUE); #endif } }; ================================================ FILE: src/OSSupport/CriticalSection.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "CriticalSection.h" //////////////////////////////////////////////////////////////////////////////// // cCriticalSection: cCriticalSection::cCriticalSection(): m_RecursionCount(0) { } void cCriticalSection::Lock() { m_Mutex.lock(); m_RecursionCount += 1; m_OwningThreadID = std::this_thread::get_id(); } void cCriticalSection::Unlock() { ASSERT(IsLockedByCurrentThread()); m_RecursionCount -= 1; m_Mutex.unlock(); } bool cCriticalSection::IsLocked(void) { return (m_RecursionCount > 0); } bool cCriticalSection::IsLockedByCurrentThread(void) { return ((m_RecursionCount > 0) && (m_OwningThreadID == std::this_thread::get_id())); } //////////////////////////////////////////////////////////////////////////////// // cCSLock cCSLock::cCSLock(cCriticalSection * a_CS) : m_CS(a_CS) , m_IsLocked(false) { Lock(); } cCSLock::cCSLock(cCriticalSection & a_CS) : m_CS(&a_CS) , m_IsLocked(false) { Lock(); } cCSLock::~cCSLock() { if (!m_IsLocked) { return; } Unlock(); } void cCSLock::Lock(void) { ASSERT(!m_IsLocked); m_IsLocked = true; m_CS->Lock(); } void cCSLock::Unlock(void) { ASSERT(m_IsLocked); m_IsLocked = false; m_CS->Unlock(); } //////////////////////////////////////////////////////////////////////////////// // cCSUnlock: cCSUnlock::cCSUnlock(cCSLock & a_Lock) : m_Lock(a_Lock) { m_Lock.Unlock(); } cCSUnlock::~cCSUnlock() { m_Lock.Lock(); } ================================================ FILE: src/OSSupport/CriticalSection.h ================================================ #pragma once class cCriticalSection { friend class cDeadlockDetect; // Allow the DeadlockDetect to read the internals, so that it may output some statistics public: void Lock(void); void Unlock(void); cCriticalSection(void); /** Returns true if the CS is currently locked. Note that since it relies on the m_RecursionCount value, it is inherently thread-unsafe, prone to false positives. Also, due to multithreading, the state can change between this when function is evaluated and the returned value is used. To be used in ASSERT(IsLocked()) only. */ bool IsLocked(void); /** Returns true if the CS is currently locked by the thread calling this function. Note that since it relies on the m_RecursionCount value, it is inherently thread-unsafe, prone to false positives. Also, due to multithreading, the state can change between this when function is evaluated and the returned value is used. To be used in ASSERT(IsLockedByCurrentThread()) only. */ bool IsLockedByCurrentThread(void); private: /** Number of times that this CS is currently locked (levels of recursion). Zero if not locked. Note that this value should be considered true only when the CS is locked; without the lock, it is UndefinedBehavior to even read it, but making it std::atomic would impose too much of a runtime penalty. It is only ever read without the lock in the DeadlockDetect, where the server is terminating anyway. */ int m_RecursionCount; /** ID of the thread that is currently holding the CS. Note that this value should be considered true only when the CS is locked; without the lock, it is UndefinedBehavior to even read it, but making it std::atomic would impose too much of a runtime penalty. When unlocked, the value stored here has no meaning, it may be an ID of a previous holder, or it could be any garbage. It is only ever read without the lock in the DeadlockDetect, where the server is terminating anyway. */ std::thread::id m_OwningThreadID; std::recursive_mutex m_Mutex; }; /** RAII for cCriticalSection - locks the CS on creation, unlocks on destruction */ class cCSLock { cCriticalSection * m_CS; // Unlike a cCriticalSection, this object should be used from a single thread, therefore access to m_IsLocked is not threadsafe // In Windows, it is an error to call cCriticalSection::Unlock() multiple times if the lock is not held, // therefore we need to check this value whether we are locked or not. bool m_IsLocked; public: cCSLock(cCriticalSection * a_CS); cCSLock(cCriticalSection & a_CS); ~cCSLock(); // Temporarily unlock or re-lock: void Lock(void); void Unlock(void); private: DISALLOW_COPY_AND_ASSIGN(cCSLock); } ; /** Temporary RAII unlock for a cCSLock. Useful for unlock-wait-relock scenarios */ class cCSUnlock { cCSLock & m_Lock; public: cCSUnlock(cCSLock & a_Lock); ~cCSUnlock(); private: DISALLOW_COPY_AND_ASSIGN(cCSUnlock); } ; ================================================ FILE: src/OSSupport/Event.cpp ================================================ // Event.cpp // Interfaces to the cEvent object representing a synchronization primitive that can be waited-for // Implemented using C++11 condition variable and mutex #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "Event.h" cEvent::cEvent(void) : m_ShouldContinue(false) { } void cEvent::Wait(void) { { std::unique_lock Lock(m_Mutex); m_CondVar.wait(Lock, [this](){ return m_ShouldContinue; }); m_ShouldContinue = false; } } bool cEvent::Wait(unsigned a_TimeoutMSec) { auto dst = std::chrono::system_clock::now() + std::chrono::milliseconds(a_TimeoutMSec); bool Result; { std::unique_lock Lock(m_Mutex); // We assume that this lock is acquired without much delay - we are the only user of the mutex Result = m_CondVar.wait_until(Lock, dst, [this](){ return m_ShouldContinue; }); m_ShouldContinue = false; } return Result; } void cEvent::Set(void) { { std::unique_lock Lock(m_Mutex); m_ShouldContinue = true; } m_CondVar.notify_one(); } void cEvent::SetAll(void) { { std::unique_lock Lock(m_Mutex); m_ShouldContinue = true; } m_CondVar.notify_all(); } ================================================ FILE: src/OSSupport/Event.h ================================================ // Event.h // Interfaces to the cEvent object representing a synchronization primitive that can be waited-for // Implemented using C++11 condition variable and mutex #pragma once class cEvent { public: cEvent(void); /** Waits until the event has been set. If the event has been set before it has been waited for, Wait() returns immediately. */ void Wait(void); /** Sets the event - releases one thread that has been waiting in Wait(). If there was no thread waiting, the next call to Wait() will not block. */ void Set(void); /** Sets the event - releases all threads that have been waiting in Wait(). If there was no thread waiting, the next call to Wait() will not block. */ void SetAll(void); /** Waits for the event until either it is signalled, or the (relative) timeout is passed. Returns true if the event was signalled, false if the timeout was hit or there was an error. */ bool Wait(unsigned a_TimeoutMSec); private: /** Used for checking for spurious wakeups. */ bool m_ShouldContinue; /** Mutex protecting m_ShouldContinue from multithreaded access. */ std::mutex m_Mutex; /** The condition variable used as the Event. */ std::condition_variable m_CondVar; } ; ================================================ FILE: src/OSSupport/File.cpp ================================================ // cFile.cpp // Implements the cFile class providing an OS-independent abstraction of a file. #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "File.h" #include #ifdef _WIN32 #include // for _SH_DENYWRITE #else #include #endif // _WIN32 cFile::cFile(void) : m_File(nullptr) { // Nothing needed yet } cFile::cFile(const AString & iFileName, eMode iMode) : m_File(nullptr) { Open(iFileName, iMode); } cFile::~cFile() { if (IsOpen()) { Close(); } } bool cFile::Open(const AString & iFileName, eMode iMode) { ASSERT(!IsOpen()); // You should close the file before opening another one if (IsOpen()) { Close(); } const char * Mode = nullptr; switch (iMode) { case fmRead: Mode = "rb"; break; case fmWrite: Mode = "wb"; break; case fmReadWrite: Mode = "rb+"; break; case fmAppend: Mode = "a+"; break; } if (Mode == nullptr) { ASSERT(!"Unhandled file mode"); return false; } #ifdef _WIN32 m_File = _fsopen((iFileName).c_str(), Mode, _SH_DENYWR); #else m_File = fopen((iFileName).c_str(), Mode); #endif // _WIN32 if ((m_File == nullptr) && (iMode == fmReadWrite)) { // Fix for MS not following C spec, opening "a" mode files for writing at the end only // The file open operation has been tried with "read update", fails if file not found // So now we know either the file doesn't exist or we don't have rights, no need to worry about file contents. // Simply re-open for read-writing, erasing existing contents: #ifdef _WIN32 m_File = _fsopen((iFileName).c_str(), "wb+", _SH_DENYWR); #else m_File = fopen((iFileName).c_str(), "wb+"); #endif // _WIN32 } return (m_File != nullptr); } void cFile::Close(void) { if (!IsOpen()) { // Closing an unopened file is a legal nop return; } fclose(m_File); m_File = nullptr; } bool cFile::IsOpen(void) const { return (m_File != nullptr); } bool cFile::IsEOF(void) const { ASSERT(IsOpen()); if (!IsOpen()) { // Unopened files behave as at EOF return true; } return (feof(m_File) != 0); } int cFile::Read (void * a_Buffer, size_t a_NumBytes) { ASSERT(IsOpen()); if (!IsOpen()) { return -1; } return static_cast(fread(a_Buffer, 1, a_NumBytes, m_File)); // fread() returns the portion of Count parameter actually read, so we need to send a_a_NumBytes as Count } ContiguousByteBuffer cFile::Read(size_t a_NumBytes) { ASSERT(IsOpen()); if (!IsOpen()) { return {}; } ContiguousByteBuffer res; res.resize(a_NumBytes); // TODO: investigate if worth hacking around std::string internals to avoid initialisation auto newSize = fread(res.data(), sizeof(std::byte), a_NumBytes, m_File); res.resize(newSize); return res; } int cFile::Write(const void * a_Buffer, size_t a_NumBytes) { ASSERT(IsOpen()); if (!IsOpen()) { return -1; } int res = static_cast(fwrite(a_Buffer, 1, a_NumBytes, m_File)); // fwrite() returns the portion of Count parameter actually written, so we need to send a_NumBytes as Count return res; } long cFile::Seek (int iPosition) { ASSERT(IsOpen()); if (!IsOpen()) { return -1; } if (fseek(m_File, iPosition, SEEK_SET) != 0) { return -1; } return ftell(m_File); } long cFile::Tell (void) const { ASSERT(IsOpen()); if (!IsOpen()) { return -1; } return ftell(m_File); } long cFile::GetSize(void) const { ASSERT(IsOpen()); if (!IsOpen()) { return -1; } long CurPos = Tell(); if (CurPos < 0) { return -1; } if (fseek(m_File, 0, SEEK_END) != 0) { return -1; } long res = Tell(); if (fseek(m_File, static_cast(CurPos), SEEK_SET) != 0) { return -1; } return res; } int cFile::ReadRestOfFile(AString & a_Contents) { ASSERT(IsOpen()); if (!IsOpen()) { return -1; } long TotalSize = GetSize(); if (TotalSize < 0) { return -1; } long Position = Tell(); if (Position < 0) { return -1; } auto DataSize = static_cast(TotalSize - Position); a_Contents.resize(DataSize); // TODO: investigate if worth hacking around std::string internals to avoid initialisation return Read(a_Contents.data(), DataSize); } bool cFile::Exists(const AString & a_FileName) { cFile test(a_FileName, fmRead); return test.IsOpen(); } bool cFile::Delete(const AString & a_Path) { if (IsFolder(a_Path)) { return DeleteFolder(a_Path); } else { return DeleteFile(a_Path); } } bool cFile::DeleteFolder(const AString & a_FolderName) { #ifdef _WIN32 return (RemoveDirectoryA(a_FolderName.c_str()) != 0); #else // _WIN32 return (rmdir(a_FolderName.c_str()) == 0); #endif // else _WIN32 } bool cFile::DeleteFolderContents(const AString & a_FolderName) { auto Contents = cFile::GetFolderContents(a_FolderName); for (const auto & item: Contents) { // Remove the item: auto WholePath = a_FolderName + GetPathSeparator() + item; if (IsFolder(WholePath)) { if (!DeleteFolderContents(WholePath)) { return false; } if (!DeleteFolder(WholePath)) { return false; } } else { if (!DeleteFile(WholePath)) { return false; } } } // for item - Contents[] // All deletes succeeded return true; } bool cFile::DeleteFile(const AString & a_FileName) { return (remove(a_FileName.c_str()) == 0); } bool cFile::Rename(const AString & a_OrigFileName, const AString & a_NewFileName) { return (rename(a_OrigFileName.c_str(), a_NewFileName.c_str()) == 0); } bool cFile::Copy(const AString & a_SrcFileName, const AString & a_DstFileName) { #ifdef _WIN32 return (CopyFileA(a_SrcFileName.c_str(), a_DstFileName.c_str(), FALSE) != 0); #else // Other OSs don't have a direct CopyFile equivalent, do it the harder way: std::ifstream src(a_SrcFileName.c_str(), std::ios::binary); std::ofstream dst(a_DstFileName.c_str(), std::ios::binary); if (dst.good()) { dst << src.rdbuf(); return true; } else { return false; } #endif } bool cFile::IsFolder(const AString & a_Path) { #ifdef _WIN32 DWORD FileAttrib = GetFileAttributesA(a_Path.c_str()); return ((FileAttrib != INVALID_FILE_ATTRIBUTES) && ((FileAttrib & FILE_ATTRIBUTE_DIRECTORY) != 0)); #else struct stat st; return ((stat(a_Path.c_str(), &st) == 0) && S_ISDIR(st.st_mode)); #endif } bool cFile::IsFile(const AString & a_Path) { #ifdef _WIN32 DWORD FileAttrib = GetFileAttributesA(a_Path.c_str()); return ((FileAttrib != INVALID_FILE_ATTRIBUTES) && ((FileAttrib & (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_DEVICE)) == 0)); #else struct stat st; return ((stat(a_Path.c_str(), &st) == 0) && S_ISREG(st.st_mode)); #endif } long cFile::GetSize(const AString & a_FileName) { struct stat st; if (stat(a_FileName.c_str(), &st) == 0) { return static_cast(st.st_size); } return -1; } bool cFile::CreateFolder(const AString & a_FolderPath) { #ifdef _WIN32 return (CreateDirectoryA(a_FolderPath.c_str(), nullptr) != 0); #else return (mkdir(a_FolderPath.c_str(), S_IRWXU | S_IRWXG | S_IRWXO) == 0); #endif } bool cFile::CreateFolderRecursive(const AString & a_FolderPath) { // Special case: Fail if the path is empty if (a_FolderPath.empty()) { return false; } // Go through each path element and create the folder: auto len = a_FolderPath.length(); for (decltype(len) i = 0; i < len; i++) { #ifdef _WIN32 if ((a_FolderPath[i] == '\\') || (a_FolderPath[i] == '/')) #else if (a_FolderPath[i] == '/') #endif { CreateFolder(a_FolderPath.substr(0, i)); } } CreateFolder(a_FolderPath); // Check the result by querying whether the final path exists: return IsFolder(a_FolderPath); } AStringVector cFile::GetFolderContents(const AString & a_Folder) { AStringVector AllFiles; #ifdef _WIN32 // If the folder name doesn't contain the terminating slash / backslash, add it: AString FileFilter = a_Folder; if ( !FileFilter.empty() && (FileFilter[FileFilter.length() - 1] != '\\') && (FileFilter[FileFilter.length() - 1] != '/') ) { FileFilter.push_back('\\'); } // Find all files / folders: FileFilter.append("*.*"); HANDLE hFind; WIN32_FIND_DATAA FindFileData; if ((hFind = FindFirstFileA(FileFilter.c_str(), &FindFileData)) != INVALID_HANDLE_VALUE) { do { if ( (strcmp(FindFileData.cFileName, ".") == 0) || (strcmp(FindFileData.cFileName, "..") == 0) ) { continue; } AllFiles.push_back(FindFileData.cFileName); } while (FindNextFileA(hFind, &FindFileData)); FindClose(hFind); } #else // _WIN32 DIR * dp; AString Folder = a_Folder; if (Folder.empty()) { Folder = "."; } if ((dp = opendir(Folder.c_str())) == nullptr) { LOGERROR("Error (%i) opening directory \"%s\"\n", errno, Folder.c_str()); } else { struct dirent *dirp; while ((dirp = readdir(dp)) != nullptr) { if ( (strcmp(dirp->d_name, ".") == 0) || (strcmp(dirp->d_name, "..") == 0) ) { continue; } AllFiles.push_back(dirp->d_name); } closedir(dp); } #endif // else _WIN32 return AllFiles; } AString cFile::ReadWholeFile(const AString & a_FileName) { cFile f; if (!f.Open(a_FileName, fmRead)) { return ""; } AString Contents; f.ReadRestOfFile(Contents); return Contents; } AString cFile::ChangeFileExt(const AString & a_FileName, const AString & a_NewExt) { auto res = a_FileName; // If the path separator is the last character of the string, return the string unmodified (refers to a folder): #if defined(_MSC_VER) // Find either path separator - MSVC CRT accepts slashes as separators, too auto LastPathSep = res.find_last_of("/\\"); #elif defined(_WIN32) // Windows with different CRTs support only the backslash separator auto LastPathSep = res.rfind('\\'); #else // Linux supports only the slash separator auto LastPathSep = res.rfind('/'); #endif if ((LastPathSep != AString::npos) && (LastPathSep + 1 == res.size())) { return res; } // Append or replace the extension: auto DotPos = res.rfind('.'); if ( (DotPos == AString::npos) || // No dot found ((LastPathSep != AString::npos) && (LastPathSep > DotPos)) // Last dot is before the last path separator (-> in folder name) ) { // No extension, just append the new one: if (!a_NewExt.empty() && (a_NewExt[0] != '.')) { // a_NewExt doesn't start with a dot, insert one: res.push_back('.'); } res.append(a_NewExt); } else { // Replace existing extension: if (!a_NewExt.empty() && (a_NewExt[0] != '.')) { // a_NewExt doesn't start with a dot, keep the current one: res.erase(DotPos + 1, AString::npos); } else { res.erase(DotPos, AString::npos); } res.append(a_NewExt); } return res; } unsigned cFile::GetLastModificationTime(const AString & a_FileName) { struct stat st; if (stat(a_FileName.c_str(), &st) < 0) { return 0; } #if defined(_WIN32) // Windows returns times in local time already return static_cast(st.st_mtime); #elif defined(ANDROID) // Identical to Linux below, but st_mtime is an unsigned long, so cast is needed: auto Time = static_cast(st.st_mtime); return static_cast(mktime(localtime(&Time))); #else // Linux returns UTC time, convert to local timezone: return static_cast(mktime(localtime(&st.st_mtime))); #endif } AString cFile::GetPathSeparator() { #ifdef _WIN32 return "\\"; #else return "/"; #endif } AString cFile::GetExecutableExt() { #ifdef _WIN32 return ".exe"; #else return ""; #endif } void cFile::Flush() { fflush(m_File); } template FileStream::FileStream(const std::string & Path) { // Except on failbit, which is what open sets on failure: FileStream::exceptions(FileStream::failbit | FileStream::badbit); // Open the file: FileStream::open(Path); // Only subsequently except on serious errors, and not on conditions like EOF or malformed input: FileStream::exceptions(FileStream::badbit); } template FileStream::FileStream(const std::string & Path, const typename FileStream::openmode Mode) { // Except on failbit, which is what open sets on failure: FileStream::exceptions(FileStream::failbit | FileStream::badbit); // Open the file: FileStream::open(Path, Mode); // Only subsequently except on serious errors, and not on conditions like EOF or malformed input: FileStream::exceptions(FileStream::badbit); } #ifdef __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wweak-template-vtables" // http://bugs.llvm.org/show_bug.cgi?id=18733 #endif // Instantiate the templated wrapper for input and output: template class FileStream; template class FileStream; #ifdef __clang__ #pragma clang diagnostic pop #endif ================================================ FILE: src/OSSupport/File.h ================================================ // cFile.h // Interfaces to the cFile class providing an OS-independent abstraction of a file. /* The object is optimized towards binary reads. The object has no multithreading locks, don't use from multiple threads! Usage: 1, Construct a cFile instance (no-param constructor) 2, Open a file using Open(), check return value for success 3, Read / write 4, Destroy the instance -- OR -- 1, Construct a cFile instance opening the file (filename-param constructor) 2, Check if the file was opened using IsOpen() 3, Read / write 4, Destroy the instance For reading entire files into memory, just use the static cFile::ReadWholeFile() */ #pragma once #include "StringUtils.h" // tolua_begin class cFile { public: // tolua_end inline static char PathSeparator() { #ifdef _WIN32 return '\\'; #else return '/'; #endif } /** The mode in which to open the file */ enum eMode { fmRead, // Read-only. If the file doesn't exist, object will not be valid fmWrite, // Write-only. If the file already exists, it will be overwritten fmReadWrite, // Read / write. If the file already exists, it will be left intact; writing will overwrite the data from the beginning fmAppend // Write-only. If the file already exists cursor will be moved to the end of the file } ; /** Simple constructor - creates an unopened file object, use Open() to open / create a real file */ cFile(void); /** Constructs and opens / creates the file specified, use IsOpen() to check for success */ cFile(const AString & iFileName, eMode iMode); /** Auto-closes the file, if open */ ~cFile(); bool Open(const AString & iFileName, eMode iMode); void Close(void); bool IsOpen(void) const; bool IsEOF(void) const; /** Reads up to a_NumBytes bytes into a_Buffer, returns the number of bytes actually read, or -1 on failure; asserts if not open */ int Read(void * a_Buffer, size_t a_NumBytes); /** Reads up to a_NumBytes bytes, returns the bytes actually read, or empty string on failure; asserts if not open */ std::basic_string Read(size_t a_NumBytes); /** Writes up to a_NumBytes bytes from a_Buffer, returns the number of bytes actually written, or -1 on failure; asserts if not open */ int Write(const void * a_Buffer, size_t a_NumBytes); int Write(std::string_view a_String) { return Write(a_String.data(), a_String.size()); } /** Seeks to iPosition bytes from file start, returns old position or -1 for failure; asserts if not open */ long Seek (int iPosition); /** Returns the current position (bytes from file start) or -1 for failure; asserts if not open */ long Tell (void) const; /** Returns the size of file, in bytes, or -1 for failure; asserts if not open */ long GetSize(void) const; /** Reads the file from current position till EOF into an AString; returns the number of bytes read or -1 for error */ int ReadRestOfFile(AString & a_Contents); /** Returns true if the file specified exists */ static bool Exists(const AString & a_FileName); // Exported in ManualBindings.cpp /** Deletes a file or a folder, returns true if successful. Prefer to use DeleteFile or DeleteFolder, since those don't have the penalty of checking whether a_Path is a folder. */ static bool Delete(const AString & a_Path); // Exported in ManualBindings.cpp /** Deletes a file, returns true if successful. Returns false if a_FileName points to a folder. */ static bool DeleteFile(const AString & a_FileName); // Exported in ManualBindings.cpp /** Deletes a folder, returns true if successful. Returns false if a_FolderName points to a file. */ static bool DeleteFolder(const AString & a_FolderName); // Exported in ManualBindings.cpp /** Deletes all content from the specified folder. The specified folder itself stays intact. Returns true on success, false on failure. */ static bool DeleteFolderContents(const AString & a_FolderName); // Exported in ManualBindings.cpp /** Renames a file or folder, returns true if successful. May fail if dest already exists (libc-dependant)! */ static bool Rename(const AString & a_OrigPath, const AString & a_NewPath); // Exported in ManualBindings.cpp /** Copies a file, returns true if successful. Overwrites the dest file if it already exists. */ static bool Copy(const AString & a_SrcFileName, const AString & a_DstFileName); // Exported in ManualBindings.cpp /** Returns true if the specified path is a folder */ static bool IsFolder(const AString & a_Path); // Exported in ManualBindings.cpp /** Returns true if the specified path is a regular file */ static bool IsFile(const AString & a_Path); // Exported in ManualBindings.cpp /** Returns the size of the file, or a negative number on error */ static long GetSize(const AString & a_FileName); // Exported in ManualBindings.cpp /** Creates a new folder with the specified name. Returns true if successful. Path may be relative or absolute */ static bool CreateFolder(const AString & a_FolderPath); // Exported in ManualBindings.cpp /** Creates a new folder with the specified name, creating its parents if needed. Path may be relative or absolute. Returns true if the folder exists at the end of the operation (either created, or already existed). Supports only paths that use the path separator used by the current platform (MSVC CRT supports slashes for file paths, too, but this function doesn't) */ static bool CreateFolderRecursive(const AString & a_FolderPath); // Exported in ManualBindings.cpp /** Returns the entire contents of the specified file as a string. Returns empty string on error. */ static AString ReadWholeFile(const AString & a_FileName); // Exported in ManualBindings.cpp /** Returns a_FileName with its extension changed to a_NewExt. a_FileName may contain path specification. */ static AString ChangeFileExt(const AString & a_FileName, const AString & a_NewExt); // Exported in ManualBindings.cpp /** Returns the last modification time (in current timezone) of the specified file. The value returned is in the same units as the value returned by time() function. If the file is not found / accessible, zero is returned. Works for folders, too, when specified without the trailing path separator. */ static unsigned GetLastModificationTime(const AString & a_FileName); // Exported in ManualBindings.cpp // tolua_begin /** Returns the path separator used by the current platform. Note that the platform / CRT may support additional path separators (such as slashes on Windows), these don't get reported. */ static AString GetPathSeparator(); /** Returns the customary executable extension used by the current platform. */ static AString GetExecutableExt(); // tolua_end /** Returns the list of all items in the specified folder (files, folders, nix pipes, whatever's there). */ static AStringVector GetFolderContents(const AString & a_Folder); // Exported in ManualBindings.cpp /** Flushes all the bufferef output into the file (only when writing) */ void Flush(); private: FILE * m_File; } ; // tolua_export /** A wrapper for file streams that enables exceptions. */ template class FileStream final : public StreamType { public: FileStream(const std::string & Path); FileStream(const std::string & Path, const typename FileStream::openmode Mode); }; using InputFileStream = FileStream; using OutputFileStream = FileStream; #ifdef __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wweak-template-vtables" // http://bugs.llvm.org/show_bug.cgi?id=18733 #endif extern template class FileStream; extern template class FileStream; #ifdef __clang__ #pragma clang diagnostic pop #endif ================================================ FILE: src/OSSupport/GZipFile.cpp ================================================ // GZipFile.cpp // Implements the cGZipFile class representing a RAII wrapper over zlib's GZip file routines #include "Globals.h" #include "File.h" #include "GZipFile.h" Compression::Result GZipFile::ReadRestOfFile(const std::string & a_FileName) { InputFileStream File(a_FileName, InputFileStream::binary); const std::string Input{ std::istreambuf_iterator(File), std::istreambuf_iterator() }; const ContiguousByteBufferView Data{ reinterpret_cast(Input.data()), Input.size() }; return Compression::Extractor().ExtractGZip(Data); } void GZipFile::Write(const std::string & a_FileName, ContiguousByteBufferView a_Contents) { OutputFileStream(a_FileName, OutputFileStream::binary) << Compression::Compressor().CompressGZip(a_Contents).GetStringView(); } ================================================ FILE: src/OSSupport/GZipFile.h ================================================ // GZipFile.h // Declares the GZipFile namespace representing a wrapper over a file stream that can read and write to GZip'd files #pragma once #include "StringCompression.h" namespace GZipFile { /** Reads the rest of the file and returns the decompressed contents. */ Compression::Result ReadRestOfFile(const std::string & a_FileName); /** Writes a_Contents into file, compressing it along the way. */ void Write(const std::string & a_FileName, ContiguousByteBufferView a_Contents); } ; ================================================ FILE: src/OSSupport/GetAddressInfoError.h ================================================ #pragma once /** Returns the readable form of a getaddressinfo type error code */ inline AString ErrorString(int a_ErrorCode) { // Note gai_strerror is not threadsafe on windows #ifdef _WIN32 char ErrorStr[GAI_STRERROR_BUFFER_SIZE + 1]; int MsgLen = FormatMessageA( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_MAX_WIDTH_MASK, nullptr, a_ErrorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), ErrorStr, sizeof(ErrorStr) - 1, nullptr ); return AString(ErrorStr, MsgLen); #else return gai_strerror(a_ErrorCode); #endif } ================================================ FILE: src/OSSupport/HostnameLookup.cpp ================================================ // HostnameLookup.cpp // Implements the cHostnameLookup class representing an in-progress hostname-to-IP lookup #include "Globals.h" #include "HostnameLookup.h" #include "NetworkSingleton.h" #include "GetAddressInfoError.h" //////////////////////////////////////////////////////////////////////////////// // cHostnameLookup: cHostnameLookup::cHostnameLookup(const AString & a_Hostname, cNetwork::cResolveNameCallbacksPtr a_Callbacks): m_Callbacks(std::move(a_Callbacks)), m_Hostname(a_Hostname) { } void cHostnameLookup::Lookup(const AString & a_Hostname, cNetwork::cResolveNameCallbacksPtr a_Callbacks) { // Cannot use std::make_shared here, constructor is not accessible cHostnameLookupPtr Lookup{ new cHostnameLookup(a_Hostname, std::move(a_Callbacks)) }; // Note the Lookup object is owned solely by this lambda which is destroyed after it runs cNetworkSingleton::Get().GetLookupThread().ScheduleLookup([=]() { // Start the lookup: addrinfo hints; memset(&hints, 0, sizeof(hints)); hints.ai_protocol = IPPROTO_TCP; hints.ai_socktype = SOCK_STREAM; hints.ai_family = AF_UNSPEC; hints.ai_flags = AI_CANONNAME; addrinfo * Result; int ErrCode = getaddrinfo(Lookup->m_Hostname.c_str(), nullptr, &hints, &Result); Lookup->Callback(ErrCode, Result); }); } void cHostnameLookup::Callback(int a_ErrCode, addrinfo * a_Addr) { // If an error has occurred, notify the error callback: if (a_ErrCode != 0) { m_Callbacks->OnError(a_ErrCode, ErrorString(a_ErrCode)); return; } // Call the success handler for each entry received: bool HasResolved = false; addrinfo * OrigAddr = a_Addr; for (;a_Addr != nullptr; a_Addr = a_Addr->ai_next) { char IP[128]; switch (a_Addr->ai_family) { case AF_INET: // IPv4 { sockaddr_in * sin = reinterpret_cast(a_Addr->ai_addr); if (!m_Callbacks->OnNameResolvedV4(m_Hostname, sin)) { // Callback indicated that the IP shouldn't be serialized to a string, just continue with the next address: HasResolved = true; continue; } evutil_inet_ntop(AF_INET, &(sin->sin_addr), IP, sizeof(IP)); break; } case AF_INET6: // IPv6 { sockaddr_in6 * sin = reinterpret_cast(a_Addr->ai_addr); if (!m_Callbacks->OnNameResolvedV6(m_Hostname, sin)) { // Callback indicated that the IP shouldn't be serialized to a string, just continue with the next address: HasResolved = true; continue; } evutil_inet_ntop(AF_INET6, &(sin->sin6_addr), IP, sizeof(IP)); break; } default: { // Unknown address family, handle as if this entry wasn't received continue; // for (a_Addr) } } m_Callbacks->OnNameResolved(m_Hostname, IP); HasResolved = true; } // for (a_Addr) // If only unsupported families were reported, call the Error handler: if (!HasResolved) { m_Callbacks->OnError(EAI_NONAME, ErrorString(EAI_NONAME)); } else { m_Callbacks->OnFinished(); } freeaddrinfo(OrigAddr); } //////////////////////////////////////////////////////////////////////////////// // cNetwork API: bool cNetwork::HostnameToIP( const AString & a_Hostname, cNetwork::cResolveNameCallbacksPtr a_Callbacks ) { cHostnameLookup::Lookup(a_Hostname, std::move(a_Callbacks)); return true; } ================================================ FILE: src/OSSupport/HostnameLookup.h ================================================ // HostnameLookup.h // Declares the cHostnameLookup class representing an in-progress hostname-to-IP lookup // This is an internal header, no-one outside OSSupport should need to include it; use Network.h instead #pragma once #include "Network.h" /** Holds information about an in-progress Hostname-to-IP lookup. */ class cHostnameLookup { public: /** Creates a lookup object and schedules the lookup. */ static void Lookup(const AString & a_Hostname, cNetwork::cResolveNameCallbacksPtr a_Callbacks); protected: /** Creates the lookup object. Doesn't start the lookup yet. */ cHostnameLookup(const AString & a_Hostname, cNetwork::cResolveNameCallbacksPtr a_Callbacks); /** The callbacks to call for resolved names / errors. */ cNetwork::cResolveNameCallbacksPtr m_Callbacks; /** The hostname that was queried (needed for the callbacks). */ AString m_Hostname; void Callback(int a_ErrCode, struct addrinfo * a_Addr); }; typedef std::shared_ptr cHostnameLookupPtr; typedef std::vector cHostnameLookupPtrs; ================================================ FILE: src/OSSupport/IPLookup.cpp ================================================ // IPLookup.cpp // Implements the cIPLookup class representing an IP-to-hostname lookup in progress. #include "Globals.h" #include "IPLookup.h" #include #include "NetworkSingleton.h" #include "GetAddressInfoError.h" //////////////////////////////////////////////////////////////////////////////// // cIPLookup: cIPLookup::cIPLookup(const AString & a_IP, cNetwork::cResolveNameCallbacksPtr a_Callbacks): m_Callbacks(std::move(a_Callbacks)), m_IP(a_IP) { ASSERT(m_Callbacks != nullptr); } void cIPLookup::Lookup(const AString & a_IP, cNetwork::cResolveNameCallbacksPtr a_Callbacks) { cIPLookupPtr Lookup{ new cIPLookup(a_IP, std::move(a_Callbacks)) }; // Cannot use std::make_shared here, constructor is not accessible // Note the Lookup object is owned solely by this lambda which is destroyed after it runs cNetworkSingleton::Get().GetLookupThread().ScheduleLookup([=]() { sockaddr_storage sa; int salen = sizeof(sa); memset(&sa, 0, sizeof(sa)); int ErrCode = evutil_parse_sockaddr_port(Lookup->m_IP.c_str(), reinterpret_cast(&sa), &salen); if (ErrCode != 0) { LOGD("Failed to parse IP address \"%s\".", Lookup->m_IP.c_str()); Lookup->Callback(ErrCode, nullptr); return; } char Hostname[NI_MAXHOST]; char ServInfo[NI_MAXSERV]; ErrCode = getnameinfo( reinterpret_cast(&sa), static_cast(salen), Hostname, sizeof(Hostname), ServInfo, sizeof(ServInfo), 0 ); Lookup->Callback(ErrCode, Hostname); }); } void cIPLookup::Callback(int a_Result, const char * a_Address) { // Call the proper callback based on the event received: if ((a_Result != 0) || (a_Address == nullptr)) { // An error has occurred, notify the error callback: m_Callbacks->OnError(a_Result, ErrorString(a_Result)); } else { // Call the success handler: m_Callbacks->OnNameResolved(a_Address, m_IP); m_Callbacks->OnFinished(); } } //////////////////////////////////////////////////////////////////////////////// // cNetwork API: bool cNetwork::IPToHostName( const AString & a_IP, cNetwork::cResolveNameCallbacksPtr a_Callbacks ) { cIPLookup::Lookup(a_IP, std::move(a_Callbacks)); return true; } ================================================ FILE: src/OSSupport/IPLookup.h ================================================ // IPLookup.h // Declares the cIPLookup class representing an IP-to-hostname lookup in progress. // This is an internal header, no-one outside OSSupport should need to include it; use Network.h instead #pragma once #include "Network.h" /** Holds information about an in-progress IP-to-Hostname lookup. */ class cIPLookup { public: /** Creates a lookup object and schedules the lookup. */ static void Lookup(const AString & a_IP, cNetwork::cResolveNameCallbacksPtr a_Callbacks); protected: /** The callbacks to call for resolved names / errors. */ cNetwork::cResolveNameCallbacksPtr m_Callbacks; /** The IP that was queried (needed for the callbacks). */ AString m_IP; /** Creates the lookup object. Doesn't start the lookup yet. */ cIPLookup(const AString & a_IP, cNetwork::cResolveNameCallbacksPtr a_Callbacks); /** Callback that is called by LibEvent when there's an event for the request. */ void Callback(int a_Result, const char * a_Address); }; typedef std::shared_ptr cIPLookupPtr; typedef std::vector cIPLookupPtrs; ================================================ FILE: src/OSSupport/IsThread.cpp ================================================ // IsThread.cpp // Implements the cIsThread class representing an OS-independent wrapper for a class that implements a thread. #include "Globals.h" #include "IsThread.h" //////////////////////////////////////////////////////////////////////////////// // cIsThread: cIsThread::cIsThread(AString && a_ThreadName) : m_ShouldTerminate(false), m_ThreadName(std::move(a_ThreadName)) { } cIsThread::~cIsThread() { Stop(); } void cIsThread::Start(void) { // Initialize the thread: m_Thread = std::thread(&cIsThread::Entrypoint, this); // Notify the thread that initialization is complete and it can run its code safely: m_Initialisation.Set(); } void cIsThread::Stop(void) { m_ShouldTerminate = true; { LOGD("Waiting for the %s thread to finish", m_ThreadName.c_str()); if (m_Thread.joinable()) { m_Thread.join(); } LOGD("The %s thread finished", m_ThreadName.c_str()); } m_ShouldTerminate = false; } void cIsThread::Entrypoint(void) { // Apply thread naming: SetThreadName(); // Wait for initialisation: m_Initialisation.Wait(); try { Execute(); } catch (const std::exception & Oops) { LOGERROR("Thread %s faulted with standard exception: %s", m_ThreadName.c_str(), Oops.what()); std::abort(); } catch (...) { LOGERROR("Thread %s faulted with unknown exception!", m_ThreadName.c_str()); std::abort(); } } void cIsThread::SetThreadName() const { #if defined(_MSC_VER) && !defined(NDEBUG) /* Sets the name of this thread. (When in MSVC, the debugger provides "thread naming" by catching special exceptions) Code adapted from MSDN: https://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx */ if (m_ThreadName.empty()) { return; } #pragma pack(push, 8) struct THREADNAME_INFO { DWORD dwType; // Must be 0x1000. LPCSTR szName; // Pointer to name (in user addr space). DWORD dwThreadID; // Thread ID (-1 = caller thread). DWORD dwFlags; // Reserved for future use, must be zero. }; #pragma pack(pop) const DWORD NAME_EXCEPTION = 0x406D1388; const THREADNAME_INFO Name = { 0x1000, m_ThreadName.c_str(), static_cast(-1), 0 }; __try { RaiseException(NAME_EXCEPTION, 0, sizeof(Name) / sizeof(ULONG_PTR), reinterpret_cast(&Name)); } __except (EXCEPTION_EXECUTE_HANDLER) { } #endif } ================================================ FILE: src/OSSupport/IsThread.h ================================================ // IsThread.h // Interfaces to the cIsThread class representing an OS-independent wrapper for a class that implements a thread. /* Usage: To have a new thread, declare a class descending from cIsThread. Then override its Execute() method to provide your thread processing. In the descending class' constructor call the Start() method to start the thread once you're finished with initialization. */ #pragma once class cIsThread { public: cIsThread(AString && a_ThreadName); virtual ~cIsThread(); /** Starts the thread; returns without waiting for the actual start. */ void Start(void); /** Signals the thread to terminate and waits until it's finished. */ void Stop(void); /** Returns true if the thread calling this function is the thread contained within this object. */ bool IsCurrentThread(void) const { return std::this_thread::get_id() == m_Thread.get_id(); } protected: /** This function, overloaded by the descendants, is called in the new thread. */ virtual void Execute(void) = 0; /** The overriden Execute() method should check this value periodically and terminate if this is true. */ std::atomic m_ShouldTerminate; private: /** The thread object which holds the created thread for later manipulation */ std::thread m_Thread; /** The name of the thread, used to aid debugging in IDEs which support named threads */ AString m_ThreadName; /** The event that is used to wait with the thread's execution until the thread object is fully initialized. This prevents the IsCurrentThread() call to fail because of a race-condition where the thread starts before m_Thread has been fully assigned. */ cEvent m_Initialisation; /** This is the main thread entrypoint. Wrapper for Execute() that waits for the initialization event, to prevent race conditions in thread initialization. */ void Entrypoint(void); /** Sets the name of the current thread to be the name provided in m_ThreadName. */ void SetThreadName() const; } ; ================================================ FILE: src/OSSupport/MiniDumpWriter.h ================================================ // MiniDumpWriter.h // 32-bit only: // When the server crashes, create a "dump file" containing the callstack of each thread and some variables; // let the user send us that crash file for analysis. // This file MUST NOT be included from anywhere other than main.cpp. /** Flags to control minidump contents on supported platforms. */ enum class MiniDumpFlags { WithDataSegments, WithFullMemory }; #if defined(_WIN32) && !defined(_WIN64) && defined(_MSC_VER) // 32-bit Windows app compiled in MSVC #include using MiniDumpWriteDumpFunction = decltype(&MiniDumpWriteDump); static HINSTANCE m_DbgHelp; static MiniDumpWriteDumpFunction s_WriteMiniDump; // The function in dbghlp DLL that creates dump files static wchar_t s_DumpFileName[MAX_PATH]; // Filename of the dump file; hes to be created before the dump handler kicks in static char s_ExceptionStack[128 * 1024]; // Substitute stack, just in case the handler kicks in because of "insufficient stack space" static MINIDUMP_TYPE s_DumpFlags = MiniDumpNormal; // By default dump only the stack and some helpers /** This function gets called just before the "program executed an illegal instruction and will be terminated" or similar. Its purpose is to create the crashdump using the dbghlp DLLs */ static LONG WINAPI LastChanceExceptionFilter(__in struct _EXCEPTION_POINTERS * a_ExceptionInfo) { char * newStack = &s_ExceptionStack[sizeof(s_ExceptionStack) - 1]; char * oldStack; // Use the substitute stack: _asm { mov oldStack, esp mov esp, newStack } MINIDUMP_EXCEPTION_INFORMATION ExcInformation; ExcInformation.ThreadId = GetCurrentThreadId(); ExcInformation.ExceptionPointers = a_ExceptionInfo; ExcInformation.ClientPointers = 0; // Write the dump file: HANDLE dumpFile = CreateFile(s_DumpFileName, GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); s_WriteMiniDump(GetCurrentProcess(), GetCurrentProcessId(), dumpFile, s_DumpFlags, (a_ExceptionInfo) ? &ExcInformation : nullptr, nullptr, nullptr); CloseHandle(dumpFile); // Revert to old stack: _asm { mov esp, oldStack } return 0; } namespace MiniDumpWriter { static void Register() { // Magic code to produce dump-files on Windows if the server crashes: m_DbgHelp = LoadLibrary(L"DBGHELP.DLL"); if (m_DbgHelp == INVALID_HANDLE_VALUE) { return; } s_WriteMiniDump = (MiniDumpWriteDumpFunction)GetProcAddress(m_DbgHelp, "MiniDumpWriteDump"); if (s_WriteMiniDump != nullptr) { ASSERT(swprintf(s_DumpFileName, ARRAYCOUNT(s_DumpFileName), L"crash_mcs_%x.dmp", GetCurrentProcessId()) > 0); SetUnhandledExceptionFilter(LastChanceExceptionFilter); } // End of dump-file magic } static void AddDumpFlags(const MiniDumpFlags a_Flags) { switch (a_Flags) { case MiniDumpFlags::WithDataSegments: { s_DumpFlags = static_cast(s_DumpFlags | MINIDUMP_TYPE::MiniDumpWithDataSegs); break; } case MiniDumpFlags::WithFullMemory: { s_DumpFlags = static_cast(s_DumpFlags | MINIDUMP_TYPE::MiniDumpWithFullMemory); break; } } } static void Unregister() { FreeLibrary(m_DbgHelp); } }; #else namespace MiniDumpWriter { static void Register() { } static void AddDumpFlags(const MiniDumpFlags) { } static void Unregister() { } }; #endif ================================================ FILE: src/OSSupport/Network.h ================================================ // Network.h // Declares the classes used for the Network API #pragma once #ifdef __FreeBSD__ #include #endif // fwd: class cTCPLink; typedef std::shared_ptr cTCPLinkPtr; typedef std::vector cTCPLinkPtrs; class cServerHandle; typedef std::shared_ptr cServerHandlePtr; typedef std::vector cServerHandlePtrs; class cCryptoKey; typedef std::shared_ptr cCryptoKeyPtr; class cX509Cert; typedef std::shared_ptr cX509CertPtr; /** Interface that provides the methods available on a single TCP connection. */ class cTCPLink { friend class cNetwork; public: class cCallbacks { public: // Force a virtual destructor for all descendants: virtual ~cCallbacks() {} /** Called when the cTCPLink for the connection is created. The callback may store the cTCPLink instance for later use, but it should remove it in OnError(), OnRemoteClosed() or right after Close(). */ virtual void OnLinkCreated(cTCPLinkPtr a_Link) = 0; /** Called when there's data incoming from the remote peer. */ virtual void OnReceivedData(const char * a_Data, size_t a_Length) = 0; /** Called when the remote end closes the connection. The link is still available for connection information query (IP / port). Sending data on the link is not an error, but the data won't be delivered. */ virtual void OnRemoteClosed(void) = 0; /** Called when the TLS handshake has been completed and communication can continue regularly. Has an empty default implementation, so that link callback descendants don't need to specify TLS handlers when they don't use TLS at all. */ virtual void OnTlsHandshakeCompleted(void) {} /** Called when an error is detected on the connection. */ virtual void OnError(int a_ErrorCode, const AString & a_ErrorMsg) = 0; }; typedef std::shared_ptr cCallbacksPtr; // Force a virtual destructor for all descendants: virtual ~cTCPLink() {} /** Queues the specified data for sending to the remote peer. Returns true on success, false on failure. Note that this success or failure only reports the queue status, not the actual data delivery. */ virtual bool Send(const void * a_Data, size_t a_Length) = 0; /** Queues the specified data for sending to the remote peer. Returns true on success, false on failure. Note that this success or failure only reports the queue status, not the actual data delivery. */ bool Send(const AString & a_Data) { return Send(a_Data.data(), a_Data.size()); } /** Returns the IP address of the local endpoint of the connection. */ virtual AString GetLocalIP(void) const = 0; /** Returns the port used by the local endpoint of the connection. */ virtual UInt16 GetLocalPort(void) const = 0; /** Returns the IP address of the remote endpoint of the connection. */ virtual AString GetRemoteIP(void) const = 0; /** Returns the port used by the remote endpoint of the connection. */ virtual UInt16 GetRemotePort(void) const = 0; /** Closes the link gracefully. The link will send any queued outgoing data, then it will send the FIN packet. The link will still receive incoming data from remote until the remote closes the connection. */ virtual void Shutdown(void) = 0; /** Drops the connection without any more processing. Sends the RST packet, queued outgoing and incoming data is lost. */ virtual void Close(void) = 0; /** Starts a TLS handshake as a client connection. If a client certificate should be used for the connection, set the certificate into a_OwnCertData and its corresponding private key to a_OwnPrivKeyData. If both are empty, no client cert is presented. a_OwnPrivKeyPassword is the password to be used for decoding PrivKey, empty if not passworded. Returns empty string on success, non-empty error description on failure. */ virtual AString StartTLSClient( cX509CertPtr a_OwnCert, cCryptoKeyPtr a_OwnPrivKey, cX509CertPtr a_TrustedRootCAs ) = 0; /** Starts a TLS handshake as a server connection. Set the server certificate into a_CertData and its corresponding private key to a_OwnPrivKeyData. a_OwnPrivKeyPassword is the password to be used for decoding PrivKey, empty if not passworded. a_StartTLSData is any data that should be pushed into the TLS before reading more data from the remote. This is used mainly for protocols starting TLS in the middle of communication, when the TLS start command can be received together with the TLS Client Hello message in one OnReceivedData() call, to re-queue the Client Hello message into the TLS handshake buffer. Returns empty string on success, non-empty error description on failure. */ virtual AString StartTLSServer( cX509CertPtr a_OwnCert, cCryptoKeyPtr a_OwnPrivKey, const AString & a_StartTLSData ) = 0; /** Returns the callbacks that are used. */ cCallbacksPtr GetCallbacks(void) const { return m_Callbacks; } protected: /** Callbacks to be used for the various situations. */ cCallbacksPtr m_Callbacks; /** Creates a new link, with the specified callbacks. */ cTCPLink(cCallbacksPtr a_Callbacks): m_Callbacks(std::move(a_Callbacks)) { } }; /** Interface that provides the methods available on a listening server socket. */ class cServerHandle { friend class cNetwork; public: // Force a virtual destructor for all descendants: virtual ~cServerHandle() {} /** Stops the server, no more incoming connections will be accepted. All current connections will be shut down (cTCPLink::Shutdown()). */ virtual void Close(void) = 0; /** Returns true if the server has been started correctly and is currently listening for incoming connections. */ virtual bool IsListening(void) const = 0; }; /** Interface that provides methods available on UDP communication endpoints. */ class cUDPEndpoint { public: /** Interface for the callbacks for events that can happen on the endpoint. */ class cCallbacks { public: // Force a virtual destructor in all descendants: virtual ~cCallbacks() {} /** Called when an error occurs on the endpoint. */ virtual void OnError(int a_ErrorCode, const AString & a_ErrorMsg) = 0; /** Called when there is an incoming datagram from a remote host. */ virtual void OnReceivedData(const char * a_Data, size_t a_Size, const AString & a_RemoteHost, UInt16 a_RemotePort) = 0; }; // Force a virtual destructor for all descendants: virtual ~cUDPEndpoint() {} /** Closes the underlying socket. Note that there still might be callbacks in-flight after this method returns. */ virtual void Close(void) = 0; /** Returns true if the endpoint is open. */ virtual bool IsOpen(void) const = 0; /** Returns the local port to which the underlying socket is bound. */ virtual UInt16 GetPort(void) const = 0; /** Sends the specified payload in a single UDP datagram to the specified host + port combination. Note that in order to send to a broadcast address, you need to call EnableBroadcasts() first. */ virtual bool Send(const AString & a_Payload, const AString & a_Host, UInt16 a_Port) = 0; /** Marks the socket as capable of sending broadcast, using whatever OS API is needed. Without this call, sending to a broadcast address using Send() may fail. */ virtual void EnableBroadcasts(void) = 0; protected: /** The callbacks used for various events on the endpoint. */ cCallbacks & m_Callbacks; /** Creates a new instance of an endpoint, with the specified callbacks. */ cUDPEndpoint(cCallbacks & a_Callbacks): m_Callbacks(a_Callbacks) { } }; typedef std::shared_ptr cUDPEndpointPtr; class cNetwork { public: /** Callbacks used for connecting to other servers as a client. */ class cConnectCallbacks { public: // Force a virtual destructor for all descendants: virtual ~cConnectCallbacks() {} /** Called when the Connect call succeeds. Provides the newly created link that can be used for communication. */ virtual void OnConnected(cTCPLink & a_Link) = 0; /** Called when the Connect call fails. */ virtual void OnError(int a_ErrorCode, const AString & a_ErrorMsg) = 0; }; typedef std::shared_ptr cConnectCallbacksPtr; /** Callbacks used when listening for incoming connections as a server. */ class cListenCallbacks { public: // Force a virtual destructor for all descendants: virtual ~cListenCallbacks() {} /** Called when the TCP server created with Listen() receives a new incoming connection. Returns the link callbacks that the server should use for the newly created link. If a nullptr is returned, the connection is dropped immediately; otherwise a new cTCPLink instance is created and OnAccepted() is called. */ virtual cTCPLink::cCallbacksPtr OnIncomingConnection(const AString & a_RemoteIPAddress, UInt16 a_RemotePort) = 0; /** Called when the TCP server created with Listen() creates a new link for an incoming connection. Provides the newly created Link that can be used for communication. Called right after a successful OnIncomingConnection(). */ virtual void OnAccepted(cTCPLink & a_Link) = 0; /** Called when the socket fails to listen on the specified port. */ virtual void OnError(int a_ErrorCode, const AString & a_ErrorMsg) = 0; }; typedef std::shared_ptr cListenCallbacksPtr; /** Callbacks used when resolving names to IPs. */ class cResolveNameCallbacks { public: // Force a virtual destructor for all descendants: virtual ~cResolveNameCallbacks() {} /** Called when the hostname is successfully resolved into an IP address. May be called multiple times if a name resolves to multiple addresses. a_IP may be either an IPv4 or an IPv6 address with their proper formatting. Each call to OnNameResolved() is preceded by a call to either OnNameResolvedV4() or OnNameResolvedV6(). */ virtual void OnNameResolved(const AString & a_Name, const AString & a_IP) = 0; /** Called when the hostname is successfully resolved into an IPv4 address. May be called multiple times if a name resolves to multiple addresses. Each call to OnNameResolvedV4 is followed by OnNameResolved with the IP address serialized to a string. If this callback returns false, the OnNameResolved() call is skipped for this address. */ virtual bool OnNameResolvedV4(const AString & a_Name, const sockaddr_in * a_IP) { return true; } /** Called when the hostname is successfully resolved into an IPv6 address. May be called multiple times if a name resolves to multiple addresses. Each call to OnNameResolvedV4 is followed by OnNameResolved with the IP address serialized to a string. If this callback returns false, the OnNameResolved() call is skipped for this address. */ virtual bool OnNameResolvedV6(const AString & a_Name, const sockaddr_in6 * a_IP) { return true; } /** Called when an error is encountered while resolving. If an error is reported, the OnFinished() callback is not called. */ virtual void OnError(int a_ErrorCode, const AString & a_ErrorMsg) = 0; /** Called when all the addresses resolved have been reported via the OnNameResolved() callback. Only called if there was no error reported. */ virtual void OnFinished(void) = 0; }; typedef std::shared_ptr cResolveNameCallbacksPtr; /** Queues a TCP connection to be made to the specified host. Calls one the connection callbacks (success, error) when the connection is successfully established, or upon failure. The a_LinkCallbacks is passed to the newly created cTCPLink. Returns true if queueing was successful, false on failure to queue. Note that the return value doesn't report the success of the actual connection; the connection is established asynchronously in the background. Implemented in TCPLinkImpl.cpp. */ static bool Connect( const AString & a_Host, UInt16 a_Port, cConnectCallbacksPtr a_ConnectCallbacks, cTCPLink::cCallbacksPtr a_LinkCallbacks ); /** Opens up the specified port for incoming connections. Calls an OnAccepted callback for each incoming connection. A cTCPLink with the specified link callbacks is created for each connection. Returns a cServerHandle that can be used to query the operation status and close the server. Implemented in ServerHandleImpl.cpp. */ static cServerHandlePtr Listen( UInt16 a_Port, cListenCallbacksPtr a_ListenCallbacks ); /** Queues a DNS query to resolve the specified hostname to IP address. Calls one of the callbacks when the resolving succeeds, or when it fails. Returns true if queueing was successful, false if not. Note that the return value doesn't report the success of the actual lookup; the lookup happens asynchronously on the background. Implemented in HostnameLookup.cpp. */ static bool HostnameToIP( const AString & a_Hostname, cResolveNameCallbacksPtr a_Callbacks ); /** Queues a DNS query to resolve the specified IP address to a hostname. Calls one of the callbacks when the resolving succeeds, or when it fails. Returns true if queueing was successful, false if not. Note that the return value doesn't report the success of the actual lookup; the lookup happens asynchronously on the background. Implemented in IPLookup.cpp. */ static bool IPToHostName( const AString & a_IP, cResolveNameCallbacksPtr a_Callbacks ); /** Opens up an UDP endpoint for sending and receiving UDP datagrams on the specified port. If a_Port is 0, the OS is free to assign any port number it likes to the endpoint. Returns the endpoint object that can be interacted with. */ static cUDPEndpointPtr CreateUDPEndpoint(UInt16 a_Port, cUDPEndpoint::cCallbacks & a_Callbacks); /** Returns all local IP addresses for network interfaces currently available. */ static AStringVector EnumLocalIPAddresses(void); }; ================================================ FILE: src/OSSupport/NetworkInterfaceEnum.cpp ================================================ // NetworkInterfaceEnum.cpp // Implements the cNetwork::EnumLocalIPAddresses() interface enumeration function #include "Globals.h" #include "Network.h" #include "event2/util.h" #if defined(_WIN32) #include #pragma comment(lib, "IPHLPAPI.lib") #elif !defined(ANDROID) // _WIN32 #include #include #include #include #endif // else _WIN32 #if defined(_WIN32) /** Converts the SOCKET_ADDRESS structure received from the OS into an IP address string. */ static AString PrintAddress(SOCKET_ADDRESS & a_Addr) { char IP[128]; switch (a_Addr.lpSockaddr->sa_family) { case AF_INET: { auto sin = reinterpret_cast(a_Addr.lpSockaddr); evutil_inet_ntop(a_Addr.lpSockaddr->sa_family, &(sin->sin_addr), IP, sizeof(IP)); break; } case AF_INET6: { auto sin = reinterpret_cast(a_Addr.lpSockaddr); evutil_inet_ntop(a_Addr.lpSockaddr->sa_family, &(sin->sin6_addr), IP, sizeof(IP)); break; } default: { IP[0] = 0; break; } } return IP; } #elif !defined(ANDROID) // _WIN32 static AString PrintAddress(ifaddrs * InterfaceAddress) { switch (InterfaceAddress->ifa_addr->sa_family) { case AF_INET: { // IPv4 char AddressBuffer[INET_ADDRSTRLEN]; sockaddr_in InternetSocket; std::memcpy(&InternetSocket, InterfaceAddress->ifa_addr, sizeof(InternetSocket)); inet_ntop(AF_INET, &InternetSocket.sin_addr, AddressBuffer, INET_ADDRSTRLEN); return AddressBuffer; } case AF_INET6: { // IPv6 char AddressBuffer[INET6_ADDRSTRLEN]; sockaddr_in6 InternetSocket; std::memcpy(&InternetSocket, InterfaceAddress->ifa_addr, sizeof(InternetSocket)); inet_ntop(AF_INET6, &InternetSocket.sin6_addr, AddressBuffer, INET6_ADDRSTRLEN); return AddressBuffer; } default: { LOG("Unknown address family: %i", InterfaceAddress->ifa_addr->sa_family); return ""; } } } #endif // else !ANDROID AStringVector cNetwork::EnumLocalIPAddresses(void) { AStringVector res; #if defined(_WIN32) // Query the OS for all adapters' addresses: char buffer[64 KiB]; // A buffer backing the address list PIP_ADAPTER_ADDRESSES pAddresses = reinterpret_cast(&buffer); ULONG outBufLen = sizeof(buffer); DWORD dwRetVal = GetAdaptersAddresses( AF_UNSPEC, GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_FRIENDLY_NAME, nullptr, pAddresses, &outBufLen ); if (dwRetVal != ERROR_SUCCESS) { LOG("GetAdaptersAddresses() failed: %u", dwRetVal); return res; } // Enumerate all active adapters for (auto pCurrAddresses = pAddresses; pCurrAddresses != nullptr; pCurrAddresses = pCurrAddresses->Next) { if (pCurrAddresses->OperStatus != IfOperStatusUp) { // Adapter not active, skip it: continue; } // Collect all IP addresses on this adapter: for (auto pUnicast = pCurrAddresses->FirstUnicastAddress; pUnicast != nullptr; pUnicast = pUnicast->Next) { auto Address = PrintAddress(pUnicast->Address); if (!Address.empty()) { res.push_back(Address); } } // for pUnicast } // for pCurrAddresses #elif !defined(ANDROID) // _WIN32 struct ifaddrs * ifAddrStruct = nullptr; getifaddrs(&ifAddrStruct); for (auto ifa = ifAddrStruct; ifa != nullptr; ifa = ifa->ifa_next) { if (ifa->ifa_addr == nullptr) { continue; } auto Address = PrintAddress(ifa); if (!Address.empty()) { res.emplace_back(Address); } } if (ifAddrStruct != nullptr) { freeifaddrs(ifAddrStruct); } #endif // else _WIN32 return res; } ================================================ FILE: src/OSSupport/NetworkLookup.cpp ================================================ // NetworkLookup.cpp // Implements the cNetworkLookup class representing an executor for asynchronous lookup tasks #include "Globals.h" #include "NetworkLookup.h" cNetworkLookup::cNetworkLookup() : cIsThread("Network Lookup Executor") { } cNetworkLookup::~cNetworkLookup() { Stop(); } void cNetworkLookup::ScheduleLookup(std::function a_Lookup) { m_WorkQueue.EnqueueItem(std::move(a_Lookup)); } void cNetworkLookup::Stop() { m_ShouldTerminate = true; m_WorkQueue.Clear(); m_WorkQueue.EnqueueItem([](){}); // Dummy work to wake up the thread cIsThread::Stop(); } void cNetworkLookup::Execute() { while (!m_ShouldTerminate) { // Execute the next task in the queue auto Work = m_WorkQueue.DequeueItem(); Work(); } } ================================================ FILE: src/OSSupport/NetworkLookup.h ================================================ // NetworkLookup.h // Declares the cNetworkLookup class representing an executor for asynchronous lookup tasks #pragma once #include #include "IsThread.h" #include "Queue.h" class cNetworkLookup : public cIsThread { public: cNetworkLookup(); virtual ~cNetworkLookup() override; /** Schedule a lookup task for execution. */ void ScheduleLookup(std::function a_Lookup); /** Cancels any scheduled lookups and joins the lookup thread. */ void Stop(); protected: /** Process the queue until the thread is stopped. */ virtual void Execute() override final; private: /** The queue of lookup tasks waiting to be executed. */ cQueue> m_WorkQueue; }; ================================================ FILE: src/OSSupport/NetworkSingleton.cpp ================================================ // NetworkSingleton.cpp // Implements the cNetworkSingleton class representing the storage for global data pertaining to network API // such as a list of all connections, all listening sockets and the LibEvent dispatch thread. #include "Globals.h" #include "NetworkSingleton.h" #include "Network.h" #include #include #include cNetworkSingleton::cNetworkSingleton() : m_HasTerminated(true) { } cNetworkSingleton::~cNetworkSingleton() noexcept(false) { // Check that Terminate has been called already: ASSERT(m_HasTerminated); } cNetworkSingleton & cNetworkSingleton::Get(void) { static cNetworkSingleton Instance; return Instance; } void cNetworkSingleton::Initialise(void) { // Start the lookup thread m_LookupThread.Start(); // Windows: initialize networking: #ifdef _WIN32 WSADATA wsaData; memset(&wsaData, 0, sizeof(wsaData)); int res = WSAStartup (MAKEWORD(2, 2), &wsaData); if (res != 0) { int err = WSAGetLastError(); LOGWARNING("WSAStartup failed: %d, WSAGLE = %d (%s)", res, err, evutil_socket_error_to_string(err)); exit(1); } #endif // _WIN32 // Initialize LibEvent logging: event_set_log_callback(LogCallback); // Initialize threading: #if defined(EVTHREAD_USE_WINDOWS_THREADS_IMPLEMENTED) evthread_use_windows_threads(); #elif defined(EVTHREAD_USE_PTHREADS_IMPLEMENTED) evthread_use_pthreads(); #else #error No threading implemented for EVTHREAD #endif // Create the main event_base: event_config * config = event_config_new(); event_config_set_flag(config, EVENT_BASE_FLAG_STARTUP_IOCP); m_EventBase = event_base_new_with_config(config); if (m_EventBase == nullptr) { LOGERROR("Failed to initialize LibEvent. The server will now terminate."); abort(); } event_config_free(config); // Create the event loop thread: m_HasTerminated = false; m_EventLoopThread = std::thread(RunEventLoop, this); m_StartupEvent.Wait(); // Wait for the LibEvent loop to actually start running (otherwise calling Terminate too soon would hang, see #3228) } void cNetworkSingleton::Terminate(void) { ASSERT(!m_HasTerminated); // Wait for the lookup thread to stop m_LookupThread.Stop(); // Wait for the LibEvent event loop to terminate: event_base_loopbreak(m_EventBase); m_EventLoopThread.join(); // Close all open connections: { cCSLock Lock(m_CS); // Must take copies because Close will modify lists auto Conns = m_Connections; for (auto & Conn : Conns) { Conn->Close(); } auto Servers = m_Servers; for (auto & Server : Servers) { Server->Close(); } // Closed handles should have removed themself ASSERT(m_Connections.empty()); ASSERT(m_Servers.empty()); } // Free the underlying LibEvent objects: event_base_free(m_EventBase); libevent_global_shutdown(); // Set the HasTerminated flag: // (Only set the flag after everything has been removed, to avoid the random failures in the Google-test, caused by links terminating after this flag was set) m_HasTerminated = true; } void cNetworkSingleton::LogCallback(int a_Severity, const char * a_Msg) { switch (a_Severity) { case _EVENT_LOG_DEBUG: LOGD ("LibEvent: %s", a_Msg); break; case _EVENT_LOG_MSG: LOG ("LibEvent: %s", a_Msg); break; case _EVENT_LOG_WARN: LOGWARNING("LibEvent: %s", a_Msg); break; case _EVENT_LOG_ERR: LOGERROR ("LibEvent: %s", a_Msg); break; default: { LOGWARNING("LibEvent: Unknown log severity (%d): %s", a_Severity, a_Msg); break; } } } void cNetworkSingleton::RunEventLoop(cNetworkSingleton * a_Self) { auto timer = evtimer_new(a_Self->m_EventBase, SignalizeStartup, a_Self); timeval timeout{}; // Zero timeout - execute immediately evtimer_add(timer, &timeout); event_base_loop(a_Self->m_EventBase, EVLOOP_NO_EXIT_ON_EMPTY); event_free(timer); } void cNetworkSingleton::SignalizeStartup(evutil_socket_t a_Socket, short a_Events, void * a_Self) { auto self = static_cast(a_Self); ASSERT(self != nullptr); self->m_StartupEvent.Set(); } void cNetworkSingleton::AddLink(const cTCPLinkPtr & a_Link) { ASSERT(!m_HasTerminated); cCSLock Lock(m_CS); m_Connections.push_back(a_Link); } void cNetworkSingleton::RemoveLink(const cTCPLink * a_Link) { ASSERT(!m_HasTerminated); cCSLock Lock(m_CS); for (auto itr = m_Connections.begin(), end = m_Connections.end(); itr != end; ++itr) { if (itr->get() == a_Link) { m_Connections.erase(itr); return; } } // for itr - m_Connections[] } void cNetworkSingleton::AddServer(const cServerHandlePtr & a_Server) { ASSERT(!m_HasTerminated); cCSLock Lock(m_CS); m_Servers.push_back(a_Server); } void cNetworkSingleton::RemoveServer(const cServerHandle * a_Server) { ASSERT(!m_HasTerminated); cCSLock Lock(m_CS); for (auto itr = m_Servers.begin(), end = m_Servers.end(); itr != end; ++itr) { if (itr->get() == a_Server) { m_Servers.erase(itr); return; } } // for itr - m_Servers[] } ================================================ FILE: src/OSSupport/NetworkSingleton.h ================================================ // NetworkSingleton.h // Declares the cNetworkSingleton class representing the storage for global data pertaining to network API // such as a list of all connections, all listening sockets and the LibEvent dispatch thread. // This is an internal header, no-one outside OSSupport should need to include it; use Network.h instead; // the only exception being the main app entrypoint that needs to call Terminate before quitting. #pragma once #include #include "NetworkLookup.h" #include "CriticalSection.h" #include "Event.h" // fwd: struct event_base; class cTCPLink; typedef std::shared_ptr cTCPLinkPtr; typedef std::vector cTCPLinkPtrs; class cServerHandle; typedef std::shared_ptr cServerHandlePtr; typedef std::vector cServerHandlePtrs; class cNetworkSingleton { public: cNetworkSingleton(); ~cNetworkSingleton() noexcept(false); /** Returns the singleton instance of this class */ static cNetworkSingleton & Get(void); /** Initialises all network-related threads. To be called on first run or after app restart. */ void Initialise(void); /** Terminates all network-related threads. To be used only on app shutdown or restart. MSVC runtime requires that the LibEvent networking be shut down before the main() function is exitted; this is the way to do it. */ void Terminate(void); /** Returns the main LibEvent handle for event registering. */ event_base * GetEventBase(void) { return m_EventBase; } /** Returns the thread used to perform hostname and IP lookups */ cNetworkLookup & GetLookupThread() { return m_LookupThread; } /** Adds the specified link to m_Connections. Used by the underlying link implementation when a new link is created. */ void AddLink(const cTCPLinkPtr & a_Link); /** Removes the specified link from m_Connections. Used by the underlying link implementation when the link is closed / errored. */ void RemoveLink(const cTCPLink * a_Link); /** Adds the specified link to m_Servers. Used by the underlying server handle implementation when a new listening server is created. Only servers that succeed in listening are added. */ void AddServer(const cServerHandlePtr & a_Server); /** Removes the specified server from m_Servers. Used by the underlying server handle implementation when the server is closed. */ void RemoveServer(const cServerHandle * a_Server); protected: /** The main LibEvent container for driving the event loop. */ event_base * m_EventBase; /** Container for all client connections, including ones with pending-connect. */ cTCPLinkPtrs m_Connections; /** Container for all servers that are currently active. */ cServerHandlePtrs m_Servers; /** Mutex protecting all containers against multithreaded access. */ cCriticalSection m_CS; /** Set to true if Terminate has been called. */ std::atomic m_HasTerminated; /** The thread in which the main LibEvent loop runs. */ std::thread m_EventLoopThread; /** Event that is signalled once the startup is finished and the LibEvent loop is running. */ cEvent m_StartupEvent; /** The thread on which hostname and ip address lookup is performed. */ cNetworkLookup m_LookupThread; /** Converts LibEvent-generated log events into log messages in MCS log. */ static void LogCallback(int a_Severity, const char * a_Msg); /** Implements the thread that runs LibEvent's event dispatcher loop. */ static void RunEventLoop(cNetworkSingleton * a_Self); /** Callback called by LibEvent when the event loop is started. */ static void SignalizeStartup(evutil_socket_t a_Socket, short a_Events, void * a_Self); }; ================================================ FILE: src/OSSupport/Queue.h ================================================ // Queue.h // Implements the cQueue class representing a thread safe queue #pragma once /* Items can be added multiple times to a queue, there are two functions for adding, EnqueueItem() and EnqueueItemIfNotPresent(). The first one always enqueues the specified item, the second one checks if the item is already present and only queues it if it isn't. Usage: To create a queue of type T, instantiate a cQueue object. You can also modify the behavior of the queue when deleting items and when adding items that are already in the queue by providing a second parameter, a class that implements the functions Delete() and Combine(). An example is given in cQueueFuncs and is used as the default behavior. */ /** This empty struct allows for the callback functions to be inlined */ template struct cQueueFuncs { public: /** Called when an Item is deleted from the queue without being returned */ static void Delete(T) {} /** Called when an Item is inserted with EnqueueItemIfNotPresent and there is another equal value already inserted */ static void Combine(T & a_existing, const T & a_new) { UNUSED(a_existing); UNUSED(a_new); } }; template > class cQueue { // The actual storage type for the queue typedef typename std::list QueueType; // Make iterator an alias for the QueueType's iterator typedef typename QueueType::iterator iterator; public: cQueue() {} ~cQueue() {} /** Enqueues an item to the queue, may block if other threads are accessing the queue. */ void EnqueueItem(ItemType a_Item) { cCSLock Lock(m_CS); m_Contents.push_back(a_Item); m_evtAdded.Set(); } /** Enqueues an item in the queue if not already present (as determined by operator ==). Blocks other threads from accessing the queue. */ void EnqueueItemIfNotPresent(ItemType a_Item) { cCSLock Lock(m_CS); for (iterator itr = m_Contents.begin(); itr != m_Contents.end(); ++itr) { if ((*itr) == a_Item) { Funcs::Combine(*itr, a_Item); return; } } m_Contents.push_back(a_Item); m_evtAdded.Set(); } /** Dequeues an item from the queue if any are present. Returns true if successful. Value of item is undefined if dequeuing was unsuccessful. */ bool TryDequeueItem(ItemType & item) { cCSLock Lock(m_CS); if (m_Contents.empty()) { return false; } item = m_Contents.front(); m_Contents.pop_front(); m_evtRemoved.Set(); return true; } /** Dequeues an item from the queue, blocking until an item is available. */ ItemType DequeueItem(void) { cCSLock Lock(m_CS); while (m_Contents.empty()) { cCSUnlock Unlock(Lock); m_evtAdded.Wait(); } ItemType item = m_Contents.front(); m_Contents.pop_front(); m_evtRemoved.Set(); return item; } /** Blocks until the queue is empty. */ void BlockTillEmpty(void) { cCSLock Lock(m_CS); while (!m_Contents.empty()) { cCSUnlock Unlock(Lock); m_evtRemoved.Wait(); } } /** Removes all Items from the Queue, calling Delete on each of them. */ void Clear(void) { cCSLock Lock(m_CS); while (!m_Contents.empty()) { Funcs::Delete(m_Contents.front()); m_Contents.pop_front(); } } /** Returns the size at time of being called. Do not use to determine whether to call DequeueItem(), use TryDequeueItem() instead */ size_t Size(void) { cCSLock Lock(m_CS); return m_Contents.size(); } /** Removes the item from the queue. If there are multiple such items, only the first one is removed. Returns true if the item has been removed, false if no such item found. */ bool Remove(ItemType a_Item) { cCSLock Lock(m_CS); for (iterator itr = m_Contents.begin(); itr != m_Contents.end(); ++itr) { if ((*itr) == a_Item) { m_Contents.erase(itr); m_evtRemoved.Set(); return true; } } return false; } /** Removes all items for which the predicate returns true. */ template void RemoveIf(Predicate a_Predicate) { cCSLock Lock(m_CS); for (auto itr = m_Contents.begin(); itr != m_Contents.end();) { if (a_Predicate(*itr)) { auto itr2 = itr; ++itr2; m_Contents.erase(itr); m_evtRemoved.Set(); itr = itr2; } else { ++itr; } } // for itr - m_Contents[] } private: /** The contents of the queue */ QueueType m_Contents; /** Mutex that protects access to the queue contents */ cCriticalSection m_CS; /** Event that is signalled when an item is added */ cEvent m_evtAdded; /** Event that is signalled when an item is removed (both dequeued or erased) */ cEvent m_evtRemoved; }; ================================================ FILE: src/OSSupport/ServerHandleImpl.cpp ================================================ // ServerHandleImpl.cpp // Implements the cServerHandleImpl class implementing the TCP server functionality #include "Globals.h" #include "ServerHandleImpl.h" #include "TCPLinkImpl.h" #include "NetworkSingleton.h" //////////////////////////////////////////////////////////////////////////////// // Globals: namespace ServerHandleImplHelper { static bool IsValidSocket(evutil_socket_t a_Socket) { #ifdef _WIN32 return (a_Socket != INVALID_SOCKET); #else // _WIN32 return (a_Socket >= 0); #endif // else _WIN32 } } //////////////////////////////////////////////////////////////////////////////// // cServerHandleImpl: cServerHandleImpl::cServerHandleImpl(cNetwork::cListenCallbacksPtr a_ListenCallbacks): m_ListenCallbacks(std::move(a_ListenCallbacks)), m_ConnListener(nullptr), m_SecondaryConnListener(nullptr), m_IsListening(false), m_ErrorCode(0) { } cServerHandleImpl::~cServerHandleImpl() { if (m_ConnListener != nullptr) { evconnlistener_free(m_ConnListener); } if (m_SecondaryConnListener != nullptr) { evconnlistener_free(m_SecondaryConnListener); } } void cServerHandleImpl::Close(void) { // Stop the listener sockets: if (m_ConnListener != nullptr) { evconnlistener_disable(m_ConnListener); } if (m_SecondaryConnListener != nullptr) { evconnlistener_disable(m_SecondaryConnListener); } m_IsListening = false; // Shutdown all connections: cTCPLinkImplPtrs Conns; { cCSLock Lock(m_CS); std::swap(Conns, m_Connections); } for (const auto & conn: Conns) { conn->Shutdown(); } // Remove the ptr to self, so that the object may be freed: m_SelfPtr.reset(); // Remove self from cNetworkSingleton: cNetworkSingleton::Get().RemoveServer(this); } cServerHandleImplPtr cServerHandleImpl::Listen( UInt16 a_Port, cNetwork::cListenCallbacksPtr a_ListenCallbacks ) { cServerHandleImplPtr res{new cServerHandleImpl(std::move(a_ListenCallbacks))}; res->m_SelfPtr = res; if (res->Listen(a_Port)) { cNetworkSingleton::Get().AddServer(res); } else { res->m_ListenCallbacks->OnError(res->m_ErrorCode, res->m_ErrorMsg); res->m_SelfPtr.reset(); } return res; } bool cServerHandleImpl::Listen(UInt16 a_Port) { // Make sure the cNetwork internals are innitialized: cNetworkSingleton::Get(); // Set up the main socket: // It should listen on IPv6 with IPv4 fallback, when available; IPv4 when IPv6 is not available. bool NeedsTwoSockets = false; int err = 0; evutil_socket_t MainSock = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP); if (!ServerHandleImplHelper::IsValidSocket(MainSock)) { // Failed to create IPv6 socket, create an IPv4 one instead: err = EVUTIL_SOCKET_ERROR(); LOGD("Failed to create IPv6 MainSock: %d (%s)", err, evutil_socket_error_to_string(err)); MainSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (!ServerHandleImplHelper::IsValidSocket(MainSock)) { m_ErrorCode = EVUTIL_SOCKET_ERROR(); m_ErrorMsg = fmt::format(FMT_STRING("Cannot create a server socket for port {}: {} ({})"), a_Port, m_ErrorCode, evutil_socket_error_to_string(m_ErrorCode) ); return false; } // Allow the port to be reused right after the socket closes: if (evutil_make_listen_socket_reuseable(MainSock) != 0) { m_ErrorCode = EVUTIL_SOCKET_ERROR(); m_ErrorMsg = fmt::format(FMT_STRING("Port {} cannot be made reusable: {} ({}). Restarting the server might not work."), a_Port, m_ErrorCode, evutil_socket_error_to_string(m_ErrorCode) ); LOG("%s", m_ErrorMsg); } // Bind to all interfaces: sockaddr_in name; memset(&name, 0, sizeof(name)); name.sin_family = AF_INET; name.sin_port = ntohs(a_Port); if (bind(MainSock, reinterpret_cast(&name), sizeof(name)) != 0) { m_ErrorCode = EVUTIL_SOCKET_ERROR(); m_ErrorMsg = fmt::format(FMT_STRING("Cannot bind IPv4 socket to port {}: {} ({})"), a_Port, m_ErrorCode, evutil_socket_error_to_string(m_ErrorCode) ); evutil_closesocket(MainSock); return false; } } else { // IPv6 socket created, switch it into "dualstack" mode: UInt32 Zero = 0; #ifdef _WIN32 // WinXP doesn't support this feature, so if the setting fails, create another socket later on: int res = setsockopt(MainSock, IPPROTO_IPV6, IPV6_V6ONLY, reinterpret_cast(&Zero), sizeof(Zero)); err = EVUTIL_SOCKET_ERROR(); NeedsTwoSockets = ((res == SOCKET_ERROR) && (err == WSAENOPROTOOPT)); #else setsockopt(MainSock, IPPROTO_IPV6, IPV6_V6ONLY, reinterpret_cast(&Zero), sizeof(Zero)); #endif // Allow the port to be reused right after the socket closes: if (evutil_make_listen_socket_reuseable(MainSock) != 0) { m_ErrorCode = EVUTIL_SOCKET_ERROR(); m_ErrorMsg = fmt::format(FMT_STRING("Port {} cannot be made reusable: {} ({}). Restarting the server might not work."), a_Port, m_ErrorCode, evutil_socket_error_to_string(m_ErrorCode) ); LOG("%s", m_ErrorMsg); } // Bind to all interfaces: sockaddr_in6 name; memset(&name, 0, sizeof(name)); name.sin6_family = AF_INET6; name.sin6_port = ntohs(a_Port); if (bind(MainSock, reinterpret_cast(&name), sizeof(name)) != 0) { m_ErrorCode = EVUTIL_SOCKET_ERROR(); m_ErrorMsg = fmt::format(FMT_STRING("Cannot bind IPv6 socket to port {}: {} ({})"), a_Port, m_ErrorCode, evutil_socket_error_to_string(m_ErrorCode)); evutil_closesocket(MainSock); return false; } } if (evutil_make_socket_nonblocking(MainSock) != 0) { m_ErrorCode = EVUTIL_SOCKET_ERROR(); m_ErrorMsg = fmt::format(FMT_STRING("Cannot make socket on port {} non-blocking: {} ({})"), a_Port, m_ErrorCode, evutil_socket_error_to_string(m_ErrorCode)); evutil_closesocket(MainSock); return false; } if (listen(MainSock, SOMAXCONN) != 0) { m_ErrorCode = EVUTIL_SOCKET_ERROR(); m_ErrorMsg = fmt::format(FMT_STRING("Cannot listen on port {}: {} ({})"), a_Port, m_ErrorCode, evutil_socket_error_to_string(m_ErrorCode)); evutil_closesocket(MainSock); return false; } m_ConnListener = evconnlistener_new(cNetworkSingleton::Get().GetEventBase(), Callback, this, LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE, 0, MainSock); m_IsListening = true; if (!NeedsTwoSockets) { return true; } // If a secondary socket is required (WinXP dual-stack), create it here: LOGD("Creating a second socket for IPv4"); evutil_socket_t SecondSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (!ServerHandleImplHelper::IsValidSocket(SecondSock)) { err = EVUTIL_SOCKET_ERROR(); LOGD("socket(AF_INET, ...) failed for secondary socket: %d, %s", err, evutil_socket_error_to_string(err)); return true; // Report as success, the primary socket is working } // Allow the port to be reused right after the socket closes: if (evutil_make_listen_socket_reuseable(SecondSock) != 0) { m_ErrorCode = EVUTIL_SOCKET_ERROR(); m_ErrorMsg = fmt::format(FMT_STRING("Port {} cannot be made reusable (second socket): {} ({}). Restarting the server might not work."), a_Port, m_ErrorCode, evutil_socket_error_to_string(m_ErrorCode) ); LOG("%s", m_ErrorMsg); } // Make the secondary socket nonblocking: if (evutil_make_socket_nonblocking(SecondSock) != 0) { err = EVUTIL_SOCKET_ERROR(); LOGD("evutil_make_socket_nonblocking() failed for secondary socket: %d, %s", err, evutil_socket_error_to_string(err)); evutil_closesocket(SecondSock); return true; // Report as success, the primary socket is working } // Bind to all IPv4 interfaces: sockaddr_in name; memset(&name, 0, sizeof(name)); name.sin_family = AF_INET; name.sin_port = ntohs(a_Port); if (bind(SecondSock, reinterpret_cast(&name), sizeof(name)) != 0) { err = EVUTIL_SOCKET_ERROR(); LOGD("Cannot bind secondary socket to port %d: %d (%s)", a_Port, err, evutil_socket_error_to_string(err)); evutil_closesocket(SecondSock); return true; // Report as success, the primary socket is working } if (listen(SecondSock, SOMAXCONN) != 0) { err = EVUTIL_SOCKET_ERROR(); LOGD("Cannot listen on secondary socket on port %d: %d (%s)", a_Port, err, evutil_socket_error_to_string(err)); evutil_closesocket(SecondSock); return true; // Report as success, the primary socket is working } UNUSED(err); m_SecondaryConnListener = evconnlistener_new(cNetworkSingleton::Get().GetEventBase(), Callback, this, LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE, 0, SecondSock); return true; } void cServerHandleImpl::Callback(evconnlistener * a_Listener, evutil_socket_t a_Socket, sockaddr * a_Addr, int a_Len, void * a_Self) { // Cast to true self: cServerHandleImpl * Self = static_cast(a_Self); ASSERT(Self != nullptr); ASSERT(Self->m_SelfPtr != nullptr); // Get the textual IP address and port number out of a_Addr: char IPAddress[128]; UInt16 Port = 0; switch (a_Addr->sa_family) { case AF_INET: { sockaddr_in * sin = reinterpret_cast(a_Addr); evutil_inet_ntop(AF_INET, &(sin->sin_addr), IPAddress, ARRAYCOUNT(IPAddress)); Port = ntohs(sin->sin_port); break; } case AF_INET6: { sockaddr_in6 * sin6 = reinterpret_cast(a_Addr); evutil_inet_ntop(AF_INET6, &(sin6->sin6_addr), IPAddress, ARRAYCOUNT(IPAddress)); Port = ntohs(sin6->sin6_port); break; } } // Call the OnIncomingConnection callback to get the link callbacks to use: cTCPLink::cCallbacksPtr LinkCallbacks = Self->m_ListenCallbacks->OnIncomingConnection(IPAddress, Port); if (LinkCallbacks == nullptr) { // Drop the connection: evutil_closesocket(a_Socket); return; } const int one = 1; setsockopt(a_Socket, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast(&one), sizeof(one)); // Create a new cTCPLink for the incoming connection: cTCPLinkImplPtr Link = std::make_shared(a_Socket, LinkCallbacks, Self->m_SelfPtr, a_Addr, static_cast(a_Len)); { cCSLock Lock(Self->m_CS); Self->m_Connections.push_back(Link); } // Lock(m_CS) LinkCallbacks->OnLinkCreated(Link); Link->Enable(Link); // Call the OnAccepted callback: Self->m_ListenCallbacks->OnAccepted(*Link); } void cServerHandleImpl::RemoveLink(const cTCPLinkImpl * a_Link) { cCSLock Lock(m_CS); for (auto itr = m_Connections.begin(), end = m_Connections.end(); itr != end; ++itr) { if (itr->get() == a_Link) { m_Connections.erase(itr); return; } } // for itr - m_Connections[] } //////////////////////////////////////////////////////////////////////////////// // cNetwork API: cServerHandlePtr cNetwork::Listen( UInt16 a_Port, cNetwork::cListenCallbacksPtr a_ListenCallbacks ) { return cServerHandleImpl::Listen(a_Port, std::move(a_ListenCallbacks)); } ================================================ FILE: src/OSSupport/ServerHandleImpl.h ================================================ // ServerHandleImpl.h // Declares the cServerHandleImpl class implementing the TCP server functionality // This is an internal header, no-one outside OSSupport should need to include it; use Network.h instead #pragma once #include "Network.h" #include #include "CriticalSection.h" // fwd: class cTCPLinkImpl; typedef std::shared_ptr cTCPLinkImplPtr; typedef std::vector cTCPLinkImplPtrs; class cServerHandleImpl; typedef std::shared_ptr cServerHandleImplPtr; typedef std::vector cServerHandleImplPtrs; class cServerHandleImpl: public cServerHandle { using Super = cServerHandle; friend class cTCPLinkImpl; public: /** Closes the server, dropping all the connections. */ virtual ~cServerHandleImpl() override; /** Creates a new server instance listening on the specified port. Both IPv4 and IPv6 interfaces are used, if possible. Always returns a server instance; in the event of a failure, the instance holds the error details. Use IsListening() to query success. */ static cServerHandleImplPtr Listen( UInt16 a_Port, cNetwork::cListenCallbacksPtr a_ListenCallbacks ); // cServerHandle overrides: virtual void Close(void) override; virtual bool IsListening(void) const override { return m_IsListening; } protected: /** The callbacks used to notify about incoming connections. */ cNetwork::cListenCallbacksPtr m_ListenCallbacks; /** The LibEvent handle representing the main listening socket. */ evconnlistener * m_ConnListener; /** The LibEvent handle representing the secondary listening socket (only when side-by-side listening is needed, such as WinXP). */ evconnlistener * m_SecondaryConnListener; /** Set to true when the server is initialized successfully and is listening for incoming connections. */ bool m_IsListening; /** Container for all currently active connections on this server. */ cTCPLinkImplPtrs m_Connections; /** Mutex protecting m_Connections againt multithreaded access. */ cCriticalSection m_CS; /** Contains the error code for the failure to listen. Only valid for non-listening instances. */ int m_ErrorCode; /** Contains the error message for the failure to listen. Only valid for non-listening instances. */ AString m_ErrorMsg; /** The SharedPtr to self, so that it can be passed to created links. */ cServerHandleImplPtr m_SelfPtr; /** Creates a new instance with the specified callbacks. Initializes the internals, but doesn't start listening yet. */ cServerHandleImpl(cNetwork::cListenCallbacksPtr a_ListenCallbacks); /** Starts listening on the specified port. Returns true if successful, false on failure. On failure, sets m_ErrorCode and m_ErrorMsg. */ bool Listen(UInt16 a_Port); /** The callback called by LibEvent upon incoming connection. */ static void Callback(evconnlistener * a_Listener, evutil_socket_t a_Socket, sockaddr * a_Addr, int a_Len, void * a_Self); /** Removes the specified link from m_Connections. Called by cTCPLinkImpl when the link is terminated. */ void RemoveLink(const cTCPLinkImpl * a_Link); }; ================================================ FILE: src/OSSupport/SleepResolutionBooster.h ================================================ // SleepResolutionBooster.h // Increases the accuracy of Sleep on Windows (GH #5140). // This file MUST NOT be included from anywhere other than main.cpp. #ifdef _WIN32 #include static TIMECAPS g_Resolution; namespace SleepResolutionBooster { static void Register() { // Default sleep resolution on Windows isn't accurate enough (GH #5140) so try to boost it: if ( (timeGetDevCaps(&g_Resolution, sizeof(g_Resolution)) == MMSYSERR_NOERROR) && (timeBeginPeriod(g_Resolution.wPeriodMin) == MMSYSERR_NOERROR) ) { return; } // Max < Min sentinel for failure, to prevent bogus timeEndPeriod calls: g_Resolution.wPeriodMax = 0; g_Resolution.wPeriodMin = 1; } static void Unregister() { if (g_Resolution.wPeriodMax >= g_Resolution.wPeriodMin) { timeEndPeriod(g_Resolution.wPeriodMin); } } }; #else namespace SleepResolutionBooster { static void Register() { } static void Unregister() { } }; #endif ================================================ FILE: src/OSSupport/StackTrace.cpp ================================================ // StackTrace.cpp // Implements the functions to print current stack traces #include "Globals.h" #include "StackTrace.h" #ifdef _WIN32 #include "WinStackWalker.h" #else #ifdef __GLIBC__ #include #endif #include #endif void PrintStackTrace(void) { #ifdef _WIN32 class PrintingStackWalker: public WinStackWalker { virtual void OnOutput(LPCSTR szText) override { std::fputs(szText, stdout); } } sw; sw.ShowCallstack(); #else #ifdef __GLIBC__ // Use the backtrace() function to get and output the stackTrace: // Code adapted from https://stackoverflow.com/questions/77005/how-to-generate-a-stacktrace-when-my-gcc-c-app-crashes void * stackTrace[30]; auto numItems = backtrace(stackTrace, ARRAYCOUNT(stackTrace)); backtrace_symbols_fd(stackTrace, numItems, STDERR_FILENO); #endif #endif } ================================================ FILE: src/OSSupport/StackTrace.h ================================================ // StackTrace.h // Declares the functions to print current stack trace /** Prints the stacktrace for the current thread. */ extern void PrintStackTrace(void); ================================================ FILE: src/OSSupport/StartAsService.h ================================================ // StartAsService.h // Handles startup as a Windows Service or UNIX daemon. // This file MUST NOT be included from anywhere other than main.cpp. #ifdef _WIN32 class StartAsService { public: /** Make a Windows service. */ template static bool MakeIntoService() { SERVICE_TABLE_ENTRY ServiceTable[] = { { g_ServiceName, (LPSERVICE_MAIN_FUNCTION)serviceMain }, { nullptr, nullptr } }; if (StartServiceCtrlDispatcher(ServiceTable) == FALSE) { throw std::system_error(GetLastError(), std::system_category()); } return true; } private: /** Set the internal status of the service */ static void serviceSetState(DWORD acceptedControls, DWORD newState, DWORD exitCode) { SERVICE_STATUS serviceStatus = {}; serviceStatus.dwCheckPoint = 0; serviceStatus.dwControlsAccepted = acceptedControls; serviceStatus.dwCurrentState = newState; serviceStatus.dwServiceSpecificExitCode = 0; serviceStatus.dwServiceType = SERVICE_WIN32; serviceStatus.dwWaitHint = 0; serviceStatus.dwWin32ExitCode = exitCode; if (SetServiceStatus(g_StatusHandle, &serviceStatus) == FALSE) { LOGERROR("SetServiceStatus() failed\n"); } } /** Handle stop events from the Service Control Manager */ static void WINAPI serviceCtrlHandler(DWORD CtrlCode) { if (CtrlCode == SERVICE_CONTROL_STOP) { std::raise(SIGINT); serviceSetState(0, SERVICE_STOP_PENDING, 0); } } /* Startup logic for running as a service */ template static void WINAPI serviceMain(DWORD argc, TCHAR *argv[]) { wchar_t applicationFilename[MAX_PATH]; wchar_t applicationDirectory[MAX_PATH]; // Get this binary's file path: if (GetModuleFileName(nullptr, applicationFilename, std::size(applicationFilename)) == 0) { serviceSetState(0, SERVICE_STOPPED, GetLastError()); return; } const auto LastComponent = std::wcsrchr(applicationFilename, L'\\'); if (LastComponent == nullptr) { serviceSetState(0, SERVICE_STOPPED, E_UNEXPECTED); return; } const auto LengthToLastComponent = LastComponent - applicationFilename; // Strip off the filename, keep only the path: std::wcsncpy(applicationDirectory, applicationFilename, LengthToLastComponent); applicationDirectory[LengthToLastComponent] = L'\0'; // Make sure new path is null terminated // Services are run by the SCM, and inherit its working directory - usually System32. // Set the working directory to the same location as the binary. if (SetCurrentDirectory(applicationDirectory) == FALSE) { serviceSetState(0, SERVICE_STOPPED, GetLastError()); return; } g_StatusHandle = RegisterServiceCtrlHandler(g_ServiceName, serviceCtrlHandler); if (g_StatusHandle == nullptr) { OutputDebugStringA("RegisterServiceCtrlHandler() failed\n"); serviceSetState(0, SERVICE_STOPPED, GetLastError()); return; } serviceSetState(SERVICE_ACCEPT_STOP, SERVICE_RUNNING, 0); char MultibyteArgV0[MAX_PATH]; char * MultibyteArgV[] = { MultibyteArgV0 }; const auto OutputSize = std::size(MultibyteArgV0); const auto TranslateResult = std::wcstombs(MultibyteArgV0, argv[0], OutputSize); if (TranslateResult == static_cast(-1)) { // Translation failed entirely (!): MultibyteArgV0[0] = '\0'; } else if (TranslateResult == OutputSize) { // Output too small: MultibyteArgV0[OutputSize - 1] = '\0'; } const auto Result = MainFunction(1, MultibyteArgV, true); const auto Return = (Result == EXIT_SUCCESS) ? S_OK : E_FAIL; serviceSetState(0, SERVICE_STOPPED, Return); } static inline SERVICE_STATUS_HANDLE g_StatusHandle = nullptr; static inline HANDLE g_ServiceThread = INVALID_HANDLE_VALUE; static inline wchar_t g_ServiceName[] = L"Cuberite"; }; #else struct StartAsService { /** Make a UNIX daemon. */ template static bool MakeIntoService() { pid_t pid = fork(); // fork() returns a negative value on error. if (pid < 0) { throw std::system_error(errno, std::system_category()); } // Check if we are the parent or child process. Parent stops here. if (pid > 0) { return true; } // Child process now goes quiet, running in the background. close(STDIN_FILENO); close(STDOUT_FILENO); close(STDERR_FILENO); return false; } }; #endif ================================================ FILE: src/OSSupport/Stopwatch.h ================================================ // Stopwatch.h // Implements the cStopwatch class that measures and logs time between its creation and destruction #pragma once class cStopwatch { public: cStopwatch(const AString & a_Name): m_Name(a_Name), m_StartTime(std::chrono::high_resolution_clock::now()) { } ~cStopwatch() { auto duration = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - m_StartTime).count(); LOG("Stopwatch: %s took %.03f sec", m_Name, static_cast(duration) / 1000); } protected: AString m_Name; std::chrono::high_resolution_clock::time_point m_StartTime; }; ================================================ FILE: src/OSSupport/TCPLinkImpl.cpp ================================================ // TCPLinkImpl.cpp // Implements the cTCPLinkImpl class implementing the TCP link functionality #include "Globals.h" #include "TCPLinkImpl.h" #include "../mbedTLS++/SslConfig.h" #include "NetworkSingleton.h" #include "ServerHandleImpl.h" #include "event2/buffer.h" //////////////////////////////////////////////////////////////////////////////// // cTCPLinkImpl: cTCPLinkImpl::cTCPLinkImpl(const std::string & a_Host, cTCPLink::cCallbacksPtr a_LinkCallbacks): Super(std::move(a_LinkCallbacks)), m_BufferEvent(bufferevent_socket_new(cNetworkSingleton::Get().GetEventBase(), -1, BEV_OPT_CLOSE_ON_FREE | BEV_OPT_THREADSAFE | BEV_OPT_DEFER_CALLBACKS | BEV_OPT_UNLOCK_CALLBACKS)), m_LocalPort(0), m_RemoteHost(a_Host), m_RemotePort(0), m_ShouldShutdown(false) { } cTCPLinkImpl::cTCPLinkImpl( evutil_socket_t a_Socket, cTCPLink::cCallbacksPtr a_LinkCallbacks, cServerHandleImplPtr a_Server, const sockaddr * a_Address, socklen_t a_AddrLen ): Super(std::move(a_LinkCallbacks)), m_BufferEvent(bufferevent_socket_new(cNetworkSingleton::Get().GetEventBase(), a_Socket, BEV_OPT_CLOSE_ON_FREE | BEV_OPT_THREADSAFE | BEV_OPT_DEFER_CALLBACKS | BEV_OPT_UNLOCK_CALLBACKS)), m_Server(std::move(a_Server)), m_LocalPort(0), m_RemotePort(0), m_ShouldShutdown(false) { // Update the endpoint addresses: UpdateLocalAddress(); UpdateAddress(a_Address, a_AddrLen, m_RemoteIP, m_RemotePort); } cTCPLinkImpl::~cTCPLinkImpl() { // If the TLS context still exists, free it: m_TlsContext.reset(); bufferevent_free(m_BufferEvent); } cTCPLinkImplPtr cTCPLinkImpl::Connect(const AString & a_Host, UInt16 a_Port, cTCPLink::cCallbacksPtr a_LinkCallbacks, cNetwork::cConnectCallbacksPtr a_ConnectCallbacks) { ASSERT(a_LinkCallbacks != nullptr); ASSERT(a_ConnectCallbacks != nullptr); // Create a new link: cTCPLinkImplPtr res{new cTCPLinkImpl(a_Host, std::move(a_LinkCallbacks))}; // Cannot use std::make_shared here, constructor is not accessible res->m_ConnectCallbacks = std::move(a_ConnectCallbacks); cNetworkSingleton::Get().AddLink(res); res->m_Callbacks->OnLinkCreated(res); res->Enable(res); // Callback to connect after performing lookup: class cHostnameCallback : public cNetwork::cResolveNameCallbacks { cTCPLinkImplPtr m_Link; UInt16 m_Port; bool m_IsConnecting; public: cHostnameCallback(cTCPLinkImplPtr a_Link, UInt16 a_ConnectPort): m_Link(std::move(a_Link)), m_Port(a_ConnectPort), m_IsConnecting(false) { } void DoConnect(const sockaddr * a_IP, int size) { // Make sure connect is only completed once if (!m_IsConnecting) { int ErrCode = bufferevent_socket_connect(m_Link->m_BufferEvent, a_IP, size); if (ErrCode == 0) { m_IsConnecting = true; } else { m_Link->GetCallbacks()->OnError(ErrCode, evutil_socket_error_to_string(ErrCode)); } } } virtual bool OnNameResolvedV4(const AString & a_Name, const sockaddr_in * a_IP) override { sockaddr_in Addr = *a_IP; Addr.sin_port = htons(m_Port); DoConnect(reinterpret_cast(&Addr), sizeof(Addr)); return false; // Don't care about recieving ip as string } virtual bool OnNameResolvedV6(const AString & a_Name, const sockaddr_in6 * a_IP) override { sockaddr_in6 Addr = *a_IP; Addr.sin6_port = htons(m_Port); DoConnect(reinterpret_cast(&Addr), sizeof(Addr)); return false; // Don't care about recieving ip as string } virtual void OnError(int a_ErrorCode, const AString & a_ErrorMsg) override { m_Link->GetCallbacks()->OnError(a_ErrorCode, a_ErrorMsg); cNetworkSingleton::Get().RemoveLink(m_Link.get()); } // Don't need to do anything for these virtual void OnFinished() override { } virtual void OnNameResolved(const AString & a_Name, const AString & a_IP) override { } }; // Schedule the host query cNetwork::HostnameToIP(a_Host, std::make_shared(res, a_Port)); return res; } void cTCPLinkImpl::Enable(cTCPLinkImplPtr a_Self) { // Take hold of a shared copy of self, to keep as long as the callbacks are coming: m_Self = std::move(a_Self); // Set the LibEvent callbacks and enable processing: bufferevent_setcb(m_BufferEvent, ReadCallback, WriteCallback, EventCallback, this); bufferevent_enable(m_BufferEvent, EV_READ | EV_WRITE); } bool cTCPLinkImpl::Send(const void * a_Data, size_t a_Length) { if (m_ShouldShutdown) { LOGD("%s: Cannot send data, the link is already shut down.", __FUNCTION__); return false; } // If running in TLS mode, push the data into the TLS context instead: if (m_TlsContext != nullptr) { m_TlsContext->Send(a_Data, a_Length); return true; } // Send the data: return SendRaw(a_Data, a_Length); } void cTCPLinkImpl::Shutdown(void) { // If running in TLS mode, notify the TLS layer: if (m_TlsContext != nullptr) { m_TlsContext->NotifyClose(); m_TlsContext->ResetSelf(); m_TlsContext.reset(); } // If there's no outgoing data, shutdown the socket directly: if (evbuffer_get_length(bufferevent_get_output(m_BufferEvent)) == 0) { DoActualShutdown(); return; } // There's still outgoing data in the LibEvent buffer, schedule a shutdown when it's written to OS's TCP stack: m_ShouldShutdown = true; } void cTCPLinkImpl::Close(void) { // If running in TLS mode, notify the TLS layer: if (m_TlsContext != nullptr) { m_TlsContext->NotifyClose(); m_TlsContext->ResetSelf(); m_TlsContext.reset(); } // Disable all events on the socket, but keep it alive: bufferevent_disable(m_BufferEvent, EV_READ | EV_WRITE); if (m_Server == nullptr) { cNetworkSingleton::Get().RemoveLink(this); } else { m_Server->RemoveLink(this); } m_Self.reset(); } AString cTCPLinkImpl::StartTLSClient( cX509CertPtr a_OwnCert, cCryptoKeyPtr a_OwnPrivKey, cX509CertPtr a_TrustedRootCAs ) { // Check preconditions: if (m_TlsContext != nullptr) { return "TLS is already active on this link"; } if ((a_OwnCert == nullptr) != (a_OwnPrivKey == nullptr)) { return "Either provide both the certificate and private key, or neither"; } // Create the TLS context: m_TlsContext = std::make_shared(*this); if ((a_OwnCert == nullptr) && (a_TrustedRootCAs == nullptr)) { // Use the (shared) default TLS config m_TlsContext->Initialize(true); } else { // Need a specialized config for the own certificate / trusted root CAs: auto Config = cSslConfig::MakeDefaultConfig(true); if (a_OwnCert != nullptr) { Config->SetOwnCert(std::move(a_OwnCert), std::move(a_OwnPrivKey)); } if (a_TrustedRootCAs != nullptr) { Config->SetAuthMode(eSslAuthMode::Required); Config->SetCACerts(std::move(a_TrustedRootCAs)); } m_TlsContext->Initialize(Config); } // Enable SNI / peer name verification: if (!m_RemoteHost.empty()) { m_TlsContext->SetExpectedPeerName(m_RemoteHost); } m_TlsContext->SetSelf(cLinkTlsContextWPtr(m_TlsContext)); // Start the handshake: m_TlsContext->Handshake(); return {}; } AString cTCPLinkImpl::StartTLSServer( cX509CertPtr a_OwnCert, cCryptoKeyPtr a_OwnPrivKey, const AString & a_StartTLSData ) { // Check preconditions: if (m_TlsContext != nullptr) { return "TLS is already active on this link"; } if ((a_OwnCert == nullptr) || (a_OwnPrivKey == nullptr)) { return "Provide the server certificate and private key"; } // Create the TLS context: m_TlsContext = std::make_shared(*this); { auto Config = cSslConfig::MakeDefaultConfig(false); Config->SetOwnCert(a_OwnCert, a_OwnPrivKey); m_TlsContext->Initialize(std::move(Config)); } m_TlsContext->SetSelf(cLinkTlsContextWPtr(m_TlsContext)); // Push the initial data: m_TlsContext->StoreReceivedData(a_StartTLSData.data(), a_StartTLSData.size()); // Start the handshake: m_TlsContext->Handshake(); return {}; } void cTCPLinkImpl::ReadCallback(bufferevent * a_BufferEvent, void * a_Self) { ASSERT(a_Self != nullptr); cTCPLinkImpl * Self = static_cast(a_Self); ASSERT(Self->m_BufferEvent == a_BufferEvent); ASSERT(Self->m_Callbacks != nullptr); // Read all the incoming data, in 1024-byte chunks: char data[1024]; size_t length; auto tlsContext = Self->m_TlsContext; while ((length = bufferevent_read(a_BufferEvent, data, sizeof(data))) > 0) { if (tlsContext != nullptr) { ASSERT(tlsContext->IsLink(Self)); tlsContext->StoreReceivedData(data, length); } else { Self->ReceivedCleartextData(data, length); } } } void cTCPLinkImpl::WriteCallback(bufferevent * a_BufferEvent, void * a_Self) { ASSERT(a_Self != nullptr); auto Self = static_cast(a_Self); ASSERT(Self->m_Callbacks != nullptr); // If there's no more data to write and the link has been scheduled for shutdown, do the shutdown: auto OutLen = evbuffer_get_length(bufferevent_get_output(Self->m_BufferEvent)); if ((OutLen == 0) && (Self->m_ShouldShutdown)) { Self->DoActualShutdown(); } } void cTCPLinkImpl::EventCallback(bufferevent * a_BufferEvent, short a_What, void * a_Self) { ASSERT(a_Self != nullptr); cTCPLinkImplPtr Self = static_cast(a_Self)->m_Self; if (Self == nullptr) { // The link has already been freed return; } // If an error is reported, call the error callback: if (a_What & BEV_EVENT_ERROR) { // Choose the proper callback to call based on whether we were waiting for connection or not: int err = EVUTIL_SOCKET_ERROR(); if (Self->m_ConnectCallbacks != nullptr) { if (err == 0) { // This could be a DNS failure err = bufferevent_socket_get_dns_error(a_BufferEvent); } Self->m_ConnectCallbacks->OnError(err, evutil_socket_error_to_string(err)); } else { Self->m_Callbacks->OnError(err, evutil_socket_error_to_string(err)); if (Self->m_Server == nullptr) { cNetworkSingleton::Get().RemoveLink(Self.get()); } else { Self->m_Server->RemoveLink(Self.get()); } } Self->m_Self.reset(); return; } // Pending connection succeeded, call the connection callback: if (a_What & BEV_EVENT_CONNECTED) { Self->UpdateLocalAddress(); Self->UpdateRemoteAddress(); if (Self->m_ConnectCallbacks != nullptr) { Self->m_ConnectCallbacks->OnConnected(*Self); // Reset the connect callbacks so that later errors get reported through the link callbacks: Self->m_ConnectCallbacks.reset(); return; } } // If the connection has been closed, call the link callback and remove the connection: if (a_What & BEV_EVENT_EOF) { // If running in TLS mode and there's data left in the TLS contect, report it: auto tlsContext = Self->m_TlsContext; if (tlsContext != nullptr) { tlsContext->FlushBuffers(); } Self->m_Callbacks->OnRemoteClosed(); if (Self->m_Server != nullptr) { Self->m_Server->RemoveLink(Self.get()); } else { cNetworkSingleton::Get().RemoveLink(Self.get()); } Self->m_Self.reset(); return; } // Unknown event, report it: LOGWARNING("cTCPLinkImpl: Unhandled LibEvent event %d (0x%x)", a_What, a_What); ASSERT(!"cTCPLinkImpl: Unhandled LibEvent event"); } void cTCPLinkImpl::UpdateAddress(const sockaddr * a_Address, socklen_t a_AddrLen, AString & a_IP, UInt16 & a_Port) { // Based on the family specified in the address, use the correct datastructure to convert to IP string: char IP[128]; switch (a_Address->sa_family) { case AF_INET: // IPv4: { const sockaddr_in * sin = reinterpret_cast(a_Address); evutil_inet_ntop(AF_INET, &(sin->sin_addr), IP, sizeof(IP)); a_Port = ntohs(sin->sin_port); break; } case AF_INET6: // IPv6 { const sockaddr_in6 * sin = reinterpret_cast(a_Address); evutil_inet_ntop(AF_INET6, &(sin->sin6_addr), IP, sizeof(IP)); a_Port = ntohs(sin->sin6_port); break; } default: { LOGWARNING("%s: Unknown socket address family: %d", __FUNCTION__, a_Address->sa_family); ASSERT(!"Unknown socket address family"); break; } } a_IP.assign(IP); } void cTCPLinkImpl::UpdateLocalAddress(void) { sockaddr_storage sa; socklen_t salen = static_cast(sizeof(sa)); getsockname(bufferevent_getfd(m_BufferEvent), reinterpret_cast(&sa), &salen); UpdateAddress(reinterpret_cast(&sa), salen, m_LocalIP, m_LocalPort); } void cTCPLinkImpl::UpdateRemoteAddress(void) { sockaddr_storage sa; socklen_t salen = static_cast(sizeof(sa)); getpeername(bufferevent_getfd(m_BufferEvent), reinterpret_cast(&sa), &salen); UpdateAddress(reinterpret_cast(&sa), salen, m_RemoteIP, m_RemotePort); } void cTCPLinkImpl::DoActualShutdown(void) { #ifdef _WIN32 shutdown(bufferevent_getfd(m_BufferEvent), SD_SEND); #else shutdown(bufferevent_getfd(m_BufferEvent), SHUT_WR); #endif bufferevent_disable(m_BufferEvent, EV_WRITE); } bool cTCPLinkImpl::SendRaw(const void * a_Data, size_t a_Length) { return (bufferevent_write(m_BufferEvent, a_Data, a_Length) == 0); } void cTCPLinkImpl::ReceivedCleartextData(const char * a_Data, size_t a_Length) { ASSERT(m_Callbacks != nullptr); m_Callbacks->OnReceivedData(a_Data, a_Length); } //////////////////////////////////////////////////////////////////////////////// // cTCPLinkImpl::cLinkTlsContext: cTCPLinkImpl::cLinkTlsContext::cLinkTlsContext(cTCPLinkImpl & a_Link): m_Link(a_Link) { } void cTCPLinkImpl::cLinkTlsContext::SetSelf(cLinkTlsContextWPtr a_Self) { m_Self = std::move(a_Self); } void cTCPLinkImpl::cLinkTlsContext::ResetSelf(void) { m_Self.reset(); } void cTCPLinkImpl::cLinkTlsContext::StoreReceivedData(const char * a_Data, size_t a_NumBytes) { // Hold self alive for the duration of this function cLinkTlsContextPtr Self(m_Self); m_EncryptedData.append(a_Data, a_NumBytes); // Try to finish a pending handshake: TryFinishHandshaking(); // Flush any cleartext data that can be "received": FlushBuffers(); } void cTCPLinkImpl::cLinkTlsContext::FlushBuffers(void) { // Hold self alive for the duration of this function cLinkTlsContextPtr Self(m_Self); // If the handshake didn't complete yet, bail out: if (!HasHandshaken()) { return; } char Buffer[1024]; int NumBytes; while ((NumBytes = ReadPlain(Buffer, sizeof(Buffer))) > 0) { m_Link.ReceivedCleartextData(Buffer, static_cast(NumBytes)); if (m_Self.expired()) { // The callback closed the SSL context, bail out return; } } } void cTCPLinkImpl::cLinkTlsContext::TryFinishHandshaking(void) { // Hold self alive for the duration of this function cLinkTlsContextPtr Self(m_Self); // If the handshake hasn't finished yet, retry: if (!HasHandshaken()) { Handshake(); // If the handshake succeeded, write all the queued plaintext data: if (HasHandshaken()) { m_Link.GetCallbacks()->OnTlsHandshakeCompleted(); WritePlain(m_CleartextData.data(), m_CleartextData.size()); m_CleartextData.clear(); } } } void cTCPLinkImpl::cLinkTlsContext::Send(const void * a_Data, size_t a_Length) { // Hold self alive for the duration of this function cLinkTlsContextPtr Self(m_Self); // If the handshake hasn't completed yet, queue the data: if (!HasHandshaken()) { m_CleartextData.append(reinterpret_cast(a_Data), a_Length); TryFinishHandshaking(); return; } // The connection is all set up, write the cleartext data into the SSL context: WritePlain(a_Data, a_Length); FlushBuffers(); } int cTCPLinkImpl::cLinkTlsContext::ReceiveEncrypted(unsigned char * a_Buffer, size_t a_NumBytes) { // Hold self alive for the duration of this function cLinkTlsContextPtr Self(m_Self); // If there's nothing queued in the buffer, report empty buffer: if (m_EncryptedData.empty()) { return MBEDTLS_ERR_SSL_WANT_READ; } // Copy as much data as possible to the provided buffer: size_t BytesToCopy = std::min(a_NumBytes, m_EncryptedData.size()); memcpy(a_Buffer, m_EncryptedData.data(), BytesToCopy); m_EncryptedData.erase(0, BytesToCopy); return static_cast(BytesToCopy); } int cTCPLinkImpl::cLinkTlsContext::SendEncrypted(const unsigned char * a_Buffer, size_t a_NumBytes) { m_Link.SendRaw(a_Buffer, a_NumBytes); return static_cast(a_NumBytes); } //////////////////////////////////////////////////////////////////////////////// // cNetwork API: bool cNetwork::Connect( const AString & a_Host, UInt16 a_Port, cNetwork::cConnectCallbacksPtr a_ConnectCallbacks, cTCPLink::cCallbacksPtr a_LinkCallbacks ) { // Add a connection request to the queue: cTCPLinkImplPtr Conn = cTCPLinkImpl::Connect(a_Host, a_Port, std::move(a_LinkCallbacks), std::move(a_ConnectCallbacks)); return (Conn != nullptr); } ================================================ FILE: src/OSSupport/TCPLinkImpl.h ================================================ // TCPLinkImpl.h // Declares the cTCPLinkImpl class implementing the TCP link functionality // This is an internal header, no-one outside OSSupport should need to include it; use Network.h instead #pragma once #include "Network.h" #include #include #include "../mbedTLS++/SslContext.h" // fwd: class cServerHandleImpl; typedef std::shared_ptr cServerHandleImplPtr; class cTCPLinkImpl; typedef std::shared_ptr cTCPLinkImplPtr; typedef std::vector cTCPLinkImplPtrs; class cTCPLinkImpl: public cTCPLink { using Super = cTCPLink; public: /** Creates a new link based on the given socket. Used for connections accepted in a server using cNetwork::Listen(). a_Host is the hostname used for TLS SNI (can be empty in cases TLS is not used). a_Address and a_AddrLen describe the remote peer that has connected. The link is created disabled, you need to call Enable() to start the regular communication. */ cTCPLinkImpl( evutil_socket_t a_Socket, cCallbacksPtr a_LinkCallbacks, cServerHandleImplPtr a_Server, const sockaddr * a_Address, socklen_t a_AddrLen ); /** Destroys the LibEvent handle representing the link. */ virtual ~cTCPLinkImpl() override; /** Queues a connection request to the specified host. a_ConnectCallbacks must be valid. Returns a link that has the connection request queued, or NULL for failure. */ static cTCPLinkImplPtr Connect(const AString & a_Host, UInt16 a_Port, cTCPLink::cCallbacksPtr a_LinkCallbacks, cNetwork::cConnectCallbacksPtr a_ConnectCallbacks); /** Enables communication over the link. Links are created with communication disabled, so that creation callbacks can be called first. This function then enables the regular communication to be reported. The a_Self parameter is used so that the socket can keep itself alive as long as the callbacks are coming. */ void Enable(cTCPLinkImplPtr a_Self); // cTCPLink overrides: virtual bool Send(const void * a_Data, size_t a_Length) override; virtual AString GetLocalIP(void) const override { return m_LocalIP; } virtual UInt16 GetLocalPort(void) const override { return m_LocalPort; } virtual AString GetRemoteIP(void) const override { return m_RemoteIP; } virtual UInt16 GetRemotePort(void) const override { return m_RemotePort; } virtual void Shutdown(void) override; virtual void Close(void) override; virtual AString StartTLSClient( cX509CertPtr a_OwnCert, cCryptoKeyPtr a_OwnPrivKey, cX509CertPtr a_TrustedRootCAs ) override; virtual AString StartTLSServer( cX509CertPtr a_OwnCert, cCryptoKeyPtr a_OwnPrivKey, const AString & a_StartTLSData ) override; protected: // fwd: class cLinkTlsContext; typedef std::shared_ptr cLinkTlsContextPtr; typedef std::weak_ptr cLinkTlsContextWPtr; /** Wrapper around cSslContext that is used when this link is being encrypted by SSL. */ class cLinkTlsContext : public cSslContext { cTCPLinkImpl & m_Link; /** Buffer for storing the incoming encrypted data until it is requested by the SSL decryptor. */ AString m_EncryptedData; /** Buffer for storing the outgoing cleartext data until the link has finished handshaking. */ AString m_CleartextData; /** Shared ownership of self, so that this object can keep itself alive for as long as it needs. */ cLinkTlsContextWPtr m_Self; public: cLinkTlsContext(cTCPLinkImpl & a_Link); /** Shares ownership of self, so that this object can keep itself alive for as long as it needs. */ void SetSelf(cLinkTlsContextWPtr a_Self); /** Removes the self ownership so that we can detect the SSL closure. */ void ResetSelf(void); /** Stores the specified block of data into the buffer of the data to be decrypted (incoming from remote). Also flushes the SSL buffers by attempting to read any data through the SSL context. */ void StoreReceivedData(const char * a_Data, size_t a_NumBytes); /** Tries to read any cleartext data available through the SSL, reports it in the link. */ void FlushBuffers(void); /** Tries to finish handshaking the SSL. */ void TryFinishHandshaking(void); /** Sends the specified cleartext data over the SSL to the remote peer. If the handshake hasn't been completed yet, queues the data for sending when it completes. */ void Send(const void * a_Data, size_t a_Length); // cSslContext overrides: virtual int ReceiveEncrypted(unsigned char * a_Buffer, size_t a_NumBytes) override; virtual int SendEncrypted(const unsigned char * a_Buffer, size_t a_NumBytes) override; /** Returns true if the context's associated TCP link is the same link as a_Link. */ bool IsLink(cTCPLinkImpl * a_Link) { return (a_Link == &m_Link); } }; /** Callbacks to call when the connection is established. May be NULL if not used. Only used for outgoing connections (cNetwork::Connect()). */ cNetwork::cConnectCallbacksPtr m_ConnectCallbacks; /** The LibEvent handle representing this connection. */ bufferevent * m_BufferEvent; /** The server handle that has created this link. Only valid for incoming connections, nullptr for outgoing connections. */ cServerHandleImplPtr m_Server; /** The IP address of the local endpoint. Valid only after the socket has been connected. */ AString m_LocalIP; /** The port of the local endpoint. Valid only after the socket has been connected. */ UInt16 m_LocalPort; /** The original host parameter which was used for creating the link, either hostname or IP address. Used for TLS SNI. */ AString m_RemoteHost; /** The IP address of the remote endpoint. Valid only after the socket has been connected. */ AString m_RemoteIP; /** The port of the remote endpoint. Valid only after the socket has been connected. */ UInt16 m_RemotePort; /** SharedPtr to self, used to keep this object alive as long as the callbacks are coming. Initialized in Enable(), cleared in Close() and EventCallback(RemoteClosed). */ cTCPLinkImplPtr m_Self; /** If true, Shutdown() has been called and is in queue. No more data is allowed to be sent via Send() and after all the currently buffered data is sent to the OS TCP stack, the socket gets shut down. */ bool m_ShouldShutdown; /** The SSL context used for encryption, if this link uses SSL. If valid, the link uses encryption through this context. */ cLinkTlsContextPtr m_TlsContext; /** Creates a new link to be queued to connect to a specified host:port. Used for outgoing connections created using cNetwork::Connect(). To be used only by the Connect() factory function. The link is created disabled, you need to call Enable() to start the regular communication. */ cTCPLinkImpl(const std::string & a_Host, const cCallbacksPtr a_LinkCallbacks); /** Callback that LibEvent calls when there's data available from the remote peer. */ static void ReadCallback(bufferevent * a_BufferEvent, void * a_Self); /** Callback that LibEvent calls when the remote peer can receive more data. */ static void WriteCallback(bufferevent * a_BufferEvent, void * a_Self); /** Callback that LibEvent calls when there's a non-data-related event on the socket. */ static void EventCallback(bufferevent * a_BufferEvent, short a_What, void * a_Self); /** Sets a_IP and a_Port to values read from a_Address, based on the correct address family. */ static void UpdateAddress(const sockaddr * a_Address, socklen_t a_AddrLen, AString & a_IP, UInt16 & a_Port); /** Updates m_LocalIP and m_LocalPort based on the metadata read from the socket. */ void UpdateLocalAddress(void); /** Updates m_RemoteIP and m_RemotePort based on the metadata read from the socket. */ void UpdateRemoteAddress(void); /** Calls shutdown on the link and disables LibEvent writing. Called after all data from LibEvent buffers is sent to the OS TCP stack and shutdown() has been called before. */ void DoActualShutdown(void); /** Sends the data directly to the socket (without the optional TLS). */ bool SendRaw(const void * a_Data, size_t a_Length); /** Called by the TLS when it has decoded a piece of incoming cleartext data from the socket. */ void ReceivedCleartextData(const char * a_Data, size_t a_Length); }; ================================================ FILE: src/OSSupport/UDPEndpointImpl.cpp ================================================ // UDPEndpointImpl.cpp // Implements the cUDPEndpointImpl class representing an implementation of an endpoint in UDP communication #include "Globals.h" #include "UDPEndpointImpl.h" #include "NetworkSingleton.h" //////////////////////////////////////////////////////////////////////////////// // Globals: namespace UDPEndpointImplHelper { static bool IsValidSocket(evutil_socket_t a_Socket) { #ifdef _WIN32 return (a_Socket != INVALID_SOCKET); #else // _WIN32 return (a_Socket >= 0); #endif // else _WIN32 } } /** Converts a_SrcAddr in IPv4 format to a_DstAddr in IPv6 format (using IPv4-mapped IPv6). */ static void ConvertIPv4ToMappedIPv6(sockaddr_in & a_SrcAddr, sockaddr_in6 & a_DstAddr) { memset(&a_DstAddr, 0, sizeof(a_DstAddr)); a_DstAddr.sin6_family = AF_INET6; a_DstAddr.sin6_addr.s6_addr[10] = 0xff; a_DstAddr.sin6_addr.s6_addr[11] = 0xff; a_DstAddr.sin6_addr.s6_addr[12] = static_cast((a_SrcAddr.sin_addr.s_addr >> 0) & 0xff); a_DstAddr.sin6_addr.s6_addr[13] = static_cast((a_SrcAddr.sin_addr.s_addr >> 8) & 0xff); a_DstAddr.sin6_addr.s6_addr[14] = static_cast((a_SrcAddr.sin_addr.s_addr >> 16) & 0xff); a_DstAddr.sin6_addr.s6_addr[15] = static_cast((a_SrcAddr.sin_addr.s_addr >> 24) & 0xff); a_DstAddr.sin6_port = a_SrcAddr.sin_port; } //////////////////////////////////////////////////////////////////////////////// // cUDPSendAfterLookup: /** A hostname-to-IP resolver callback that sends the data stored within to the resolved IP address. This is used for sending UDP datagrams to hostnames, so that the cUDPEndpoint::Send() doesn't block. Instead an instance of this callback is queued for resolving and the data is sent once the IP is resolved. */ class cUDPSendAfterLookup: public cNetwork::cResolveNameCallbacks { public: cUDPSendAfterLookup(const AString & a_Data, UInt16 a_Port, evutil_socket_t a_MainSock, evutil_socket_t a_SecondSock, bool a_IsMainSockIPv6): m_Data(a_Data), m_Port(a_Port), m_MainSock(a_MainSock), m_SecondSock(a_SecondSock), m_IsMainSockIPv6(a_IsMainSockIPv6), m_HasIPv4(false), m_HasIPv6(false) { } protected: /** The data to send after the hostname is resolved. */ AString m_Data; /** The port to which to send the data. */ UInt16 m_Port; /** The primary socket to use for sending. */ evutil_socket_t m_MainSock; /** The secondary socket to use for sending, if needed by the OS. */ evutil_socket_t m_SecondSock; /** True if m_MainSock is an IPv6 socket. */ bool m_IsMainSockIPv6; /** The IPv4 address resolved, if any. */ sockaddr_in m_AddrIPv4; /** Set to true if the name resolved to an IPv4 address. */ bool m_HasIPv4; /** The IPv6 address resolved, if any. */ sockaddr_in6 m_AddrIPv6; /** Set to true if the name resolved to an IPv6 address. */ bool m_HasIPv6; // cNetwork::cResolveNameCallbacks overrides: virtual void OnNameResolved(const AString & a_Name, const AString & a_PI) override { // Not needed } virtual bool OnNameResolvedV4(const AString & a_Name, const sockaddr_in * a_IP) override { if (!m_HasIPv4) { m_AddrIPv4 = *a_IP; m_AddrIPv4.sin_port = htons(m_Port); m_HasIPv4 = true; } // Don't want OnNameResolved() callback return false; } virtual bool OnNameResolvedV6(const AString & a_Name, const sockaddr_in6 * a_IP) override { if (!m_HasIPv6) { m_AddrIPv6 = *a_IP; m_AddrIPv6.sin6_port = htons(m_Port); m_HasIPv6 = true; } // Don't want OnNameResolved() callback return false; } virtual void OnFinished(void) override { // Send the actual data, through the correct socket and using the correct resolved address: if (m_IsMainSockIPv6) { if (m_HasIPv6) { sendto(m_MainSock, m_Data.data(), m_Data.size(), 0, reinterpret_cast(&m_AddrIPv6), static_cast(sizeof(m_AddrIPv6))); } else if (m_HasIPv4) { // If the secondary socket is valid, it is an IPv4 socket, so use that: if (m_SecondSock != -1) { sendto(m_SecondSock, m_Data.data(), m_Data.size(), 0, reinterpret_cast(&m_AddrIPv4), static_cast(sizeof(m_AddrIPv4))); } else { // Need an address conversion from IPv4 to IPv6-mapped-IPv4: ConvertIPv4ToMappedIPv6(m_AddrIPv4, m_AddrIPv6); sendto(m_MainSock, m_Data.data(), m_Data.size(), 0, reinterpret_cast(&m_AddrIPv6), static_cast(sizeof(m_AddrIPv6))); } } else { LOGD("UDP endpoint queued sendto: Name not resolved"); return; } } else // m_IsMainSockIPv6 { // Main socket is IPv4 only, only allow IPv4 dst address: if (!m_HasIPv4) { LOGD("UDP endpoint queued sendto: Name not resolved to IPv4 for an IPv4-only socket"); return; } sendto(m_MainSock, m_Data.data(), m_Data.size(), 0, reinterpret_cast(&m_AddrIPv4), static_cast(sizeof(m_AddrIPv4))); } } virtual void OnError(int a_ErrorCode, const AString & a_ErrorMsg) override { // Nothing needed } }; //////////////////////////////////////////////////////////////////////////////// // cUDPEndpointImpl: cUDPEndpointImpl::cUDPEndpointImpl(UInt16 a_Port, cUDPEndpoint::cCallbacks & a_Callbacks): Super(a_Callbacks), m_Port(0), m_MainSock(-1), m_IsMainSockIPv6(true), m_SecondarySock(-1), m_MainEvent(nullptr), m_SecondaryEvent(nullptr) { Open(a_Port); } cUDPEndpointImpl::~cUDPEndpointImpl() { Close(); } void cUDPEndpointImpl::Close(void) { if (m_Port == 0) { // Already closed return; } // Close the LibEvent handles: if (m_MainEvent != nullptr) { event_free(m_MainEvent); m_MainEvent = nullptr; } if (m_SecondaryEvent != nullptr) { event_free(m_SecondaryEvent); m_SecondaryEvent = nullptr; } // Close the OS sockets: evutil_closesocket(m_MainSock); m_MainSock = -1; evutil_closesocket(m_SecondarySock); m_SecondarySock = -1; // Mark as closed: m_Port = 0; } bool cUDPEndpointImpl::IsOpen(void) const { return (m_Port != 0); } UInt16 cUDPEndpointImpl::GetPort(void) const { return m_Port; } bool cUDPEndpointImpl::Send(const AString & a_Payload, const AString & a_Host, UInt16 a_Port) { // If a_Host is an IP address, send the data directly: sockaddr_storage sa; int salen = static_cast(sizeof(sa)); memset(&sa, 0, sizeof(sa)); if (evutil_parse_sockaddr_port(a_Host.c_str(), reinterpret_cast(&sa), &salen) != 0) { // a_Host is a hostname, we need to do a lookup first: auto queue = std::make_shared(a_Payload, a_Port, m_MainSock, m_SecondarySock, m_IsMainSockIPv6); return cNetwork::HostnameToIP(a_Host, queue); } // a_Host is an IP address and has been parsed into "sa" // Insert the correct port and send data: int NumSent; switch (sa.ss_family) { case AF_INET: { reinterpret_cast(&sa)->sin_port = htons(a_Port); if (m_IsMainSockIPv6) { if (UDPEndpointImplHelper::IsValidSocket(m_SecondarySock)) { // The secondary socket, which is always IPv4, is present: NumSent = static_cast(sendto(m_SecondarySock, a_Payload.data(), a_Payload.size(), 0, reinterpret_cast(&sa), static_cast(salen))); } else { // Need to convert IPv4 to IPv6 address before sending: sockaddr_in6 IPv6; ConvertIPv4ToMappedIPv6(*reinterpret_cast(&sa), IPv6); NumSent = static_cast(sendto(m_MainSock, a_Payload.data(), a_Payload.size(), 0, reinterpret_cast(&IPv6), static_cast(sizeof(IPv6)))); } } else { NumSent = static_cast(sendto(m_MainSock, a_Payload.data(), a_Payload.size(), 0, reinterpret_cast(&sa), static_cast(salen))); } break; } case AF_INET6: { reinterpret_cast(&sa)->sin6_port = htons(a_Port); NumSent = static_cast(sendto(m_MainSock, a_Payload.data(), a_Payload.size(), 0, reinterpret_cast(&sa), static_cast(salen))); break; } default: { LOGD("UDP sendto: Invalid address family for address \"%s\".", a_Host.c_str()); return false; } } return (NumSent > 0); } void cUDPEndpointImpl::EnableBroadcasts(void) { ASSERT(IsOpen()); // Enable broadcasts on the main socket: // Some OSes use ints, others use chars, so we try both int broadcastInt = 1; char broadcastChar = 1; // (Note that Windows uses const char * for option values, while Linux uses const void *) if (setsockopt(m_MainSock, SOL_SOCKET, SO_BROADCAST, reinterpret_cast(&broadcastInt), sizeof(broadcastInt)) == -1) { if (setsockopt(m_MainSock, SOL_SOCKET, SO_BROADCAST, &broadcastChar, sizeof(broadcastChar)) == -1) { int err = EVUTIL_SOCKET_ERROR(); LOGWARNING("Cannot enable broadcasts on port %d: %d (%s)", m_Port, err, evutil_socket_error_to_string(err)); return; } // Enable broadcasts on the secondary socket, if opened (use char, it worked for primary): if (UDPEndpointImplHelper::IsValidSocket(m_SecondarySock)) { if (setsockopt(m_SecondarySock, SOL_SOCKET, SO_BROADCAST, &broadcastChar, sizeof(broadcastChar)) == -1) { int err = EVUTIL_SOCKET_ERROR(); LOGWARNING("Cannot enable broadcasts on port %d (secondary): %d (%s)", m_Port, err, evutil_socket_error_to_string(err)); } } return; } // Enable broadcasts on the secondary socket, if opened (use int, it worked for primary): if (UDPEndpointImplHelper::IsValidSocket(m_SecondarySock)) { if (setsockopt(m_SecondarySock, SOL_SOCKET, SO_BROADCAST, reinterpret_cast(&broadcastInt), sizeof(broadcastInt)) == -1) { int err = EVUTIL_SOCKET_ERROR(); LOGWARNING("Cannot enable broadcasts on port %d (secondary): %d (%s)", m_Port, err, evutil_socket_error_to_string(err)); } } } void cUDPEndpointImpl::Open(UInt16 a_Port) { ASSERT(m_Port == 0); // Must not be already open // Make sure the cNetwork internals are innitialized: cNetworkSingleton::Get(); // Set up the main socket: // It should listen on IPv6 with IPv4 fallback, when available; IPv4 when IPv6 is not available. bool NeedsTwoSockets = false; m_IsMainSockIPv6 = true; m_MainSock = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); int err; if (!UDPEndpointImplHelper::IsValidSocket(m_MainSock)) { // Failed to create IPv6 socket, create an IPv4 one instead: m_IsMainSockIPv6 = false; err = EVUTIL_SOCKET_ERROR(); LOGD("UDP: Failed to create IPv6 MainSock: %d (%s)", err, evutil_socket_error_to_string(err)); m_MainSock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (!UDPEndpointImplHelper::IsValidSocket(m_MainSock)) { err = EVUTIL_SOCKET_ERROR(); m_Callbacks.OnError(err, fmt::format(FMT_STRING("Cannot create UDP socket for port {}: {} ({})"), a_Port, err, evutil_socket_error_to_string(err)) ); return; } // Allow the port to be reused right after the socket closes: if (evutil_make_listen_socket_reuseable(m_MainSock) != 0) { err = EVUTIL_SOCKET_ERROR(); LOG("UDP Port %d cannot be made reusable: %d (%s). Restarting the server might not work.", a_Port, err, evutil_socket_error_to_string(err) ); } // Bind to all interfaces: sockaddr_in name; memset(&name, 0, sizeof(name)); name.sin_family = AF_INET; name.sin_port = ntohs(a_Port); if (bind(m_MainSock, reinterpret_cast(&name), sizeof(name)) != 0) { err = EVUTIL_SOCKET_ERROR(); m_Callbacks.OnError(err, fmt::format(FMT_STRING("Cannot bind UDP port {}: {} ({})"), a_Port, err, evutil_socket_error_to_string(err)) ); evutil_closesocket(m_MainSock); return; } } else { // IPv6 socket created, switch it into "dualstack" mode: UInt32 Zero = 0; #ifdef _WIN32 // WinXP doesn't support this feature, so if the setting fails, create another socket later on: int res = setsockopt(m_MainSock, IPPROTO_IPV6, IPV6_V6ONLY, reinterpret_cast(&Zero), sizeof(Zero)); err = EVUTIL_SOCKET_ERROR(); NeedsTwoSockets = ((res == SOCKET_ERROR) && (err == WSAENOPROTOOPT)); #else setsockopt(m_MainSock, IPPROTO_IPV6, IPV6_V6ONLY, reinterpret_cast(&Zero), sizeof(Zero)); #endif // Allow the port to be reused right after the socket closes: if (evutil_make_listen_socket_reuseable(m_MainSock) != 0) { err = EVUTIL_SOCKET_ERROR(); LOG("UDP Port %d cannot be made reusable: %d (%s). Restarting the server might not work.", a_Port, err, evutil_socket_error_to_string(err) ); } // Bind to all interfaces: sockaddr_in6 name; memset(&name, 0, sizeof(name)); name.sin6_family = AF_INET6; name.sin6_port = ntohs(a_Port); if (bind(m_MainSock, reinterpret_cast(&name), sizeof(name)) != 0) { err = EVUTIL_SOCKET_ERROR(); m_Callbacks.OnError(err, fmt::format(FMT_STRING("Cannot bind to UDP port {}: {} ({})"), a_Port, err, evutil_socket_error_to_string(err)) ); evutil_closesocket(m_MainSock); return; } } if (evutil_make_socket_nonblocking(m_MainSock) != 0) { err = EVUTIL_SOCKET_ERROR(); m_Callbacks.OnError(err, fmt::format(FMT_STRING("Cannot make socket on UDP port {} nonblocking: {} ({})"), a_Port, err, evutil_socket_error_to_string(err)) ); evutil_closesocket(m_MainSock); return; } m_MainEvent = event_new(cNetworkSingleton::Get().GetEventBase(), m_MainSock, EV_READ | EV_PERSIST, RawCallback, this); event_add(m_MainEvent, nullptr); // Read the actual port number on which the socket is listening: { sockaddr_storage name; socklen_t namelen = static_cast(sizeof(name)); getsockname(m_MainSock, reinterpret_cast(&name), &namelen); switch (name.ss_family) { case AF_INET: { sockaddr_in * sin = reinterpret_cast(&name); m_Port = ntohs(sin->sin_port); break; } case AF_INET6: { sockaddr_in6 * sin6 = reinterpret_cast(&name); m_Port = ntohs(sin6->sin6_port); break; } } } // If we don't need to create another socket, bail out now: if (!NeedsTwoSockets) { return; } // If a secondary socket is required (WinXP dual-stack), create it here: LOGD("Creating a second UDP socket for IPv4"); m_SecondarySock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (!UDPEndpointImplHelper::IsValidSocket(m_SecondarySock)) { // Don't report as an error, the primary socket is working err = EVUTIL_SOCKET_ERROR(); LOGD("Socket creation failed for secondary UDP socket for port %d: %d, %s", m_Port, err, evutil_socket_error_to_string(err)); return; } // Allow the port to be reused right after the socket closes: if (evutil_make_listen_socket_reuseable(m_SecondarySock) != 0) { // Don't report as an error, the primary socket is working err = EVUTIL_SOCKET_ERROR(); LOGD("UDP Port %d cannot be made reusable (second socket): %d (%s). Restarting the server might not work.", a_Port, err, evutil_socket_error_to_string(err) ); evutil_closesocket(m_SecondarySock); m_SecondarySock = -1; return; } // Make the secondary socket nonblocking: if (evutil_make_socket_nonblocking(m_SecondarySock) != 0) { // Don't report as an error, the primary socket is working err = EVUTIL_SOCKET_ERROR(); LOGD("evutil_make_socket_nonblocking() failed for secondary UDP socket: %d, %s", err, evutil_socket_error_to_string(err)); evutil_closesocket(m_SecondarySock); m_SecondarySock = -1; return; } // Bind to all IPv4 interfaces: sockaddr_in name; memset(&name, 0, sizeof(name)); name.sin_family = AF_INET; name.sin_port = ntohs(m_Port); if (bind(m_SecondarySock, reinterpret_cast(&name), sizeof(name)) != 0) { // Don't report as an error, the primary socket is working err = EVUTIL_SOCKET_ERROR(); LOGD("Cannot bind secondary socket to UDP port %d: %d (%s)", m_Port, err, evutil_socket_error_to_string(err)); evutil_closesocket(m_SecondarySock); m_SecondarySock = -1; return; } m_SecondaryEvent = event_new(cNetworkSingleton::Get().GetEventBase(), m_SecondarySock, EV_READ | EV_PERSIST, RawCallback, this); event_add(m_SecondaryEvent, nullptr); } void cUDPEndpointImpl::RawCallback(evutil_socket_t a_Socket, short a_What, void * a_Self) { cUDPEndpointImpl * Self = reinterpret_cast(a_Self); Self->Callback(a_Socket, a_What); } void cUDPEndpointImpl::Callback(evutil_socket_t a_Socket, short a_What) { if ((a_What & EV_READ) != 0) { // Receive datagram from the socket: char buf[64 KiB]; sockaddr_storage sa; socklen_t salen = static_cast(sizeof(sa)); auto len = recvfrom(a_Socket, buf, sizeof(buf), 0, reinterpret_cast(&sa), &salen); if (len >= 0) { // Convert the remote IP address to a string: char RemoteHost[128]; UInt16 RemotePort; switch (sa.ss_family) { case AF_INET: { auto sin = reinterpret_cast(&sa); evutil_inet_ntop(sa.ss_family, &sin->sin_addr, RemoteHost, sizeof(RemoteHost)); RemotePort = ntohs(sin->sin_port); break; } case AF_INET6: { auto sin = reinterpret_cast(&sa); evutil_inet_ntop(sa.ss_family, &sin->sin6_addr, RemoteHost, sizeof(RemoteHost)); RemotePort = ntohs(sin->sin6_port); break; } default: { return; } } // Call the callback: m_Callbacks.OnReceivedData(buf, static_cast(len), RemoteHost, RemotePort); } } } //////////////////////////////////////////////////////////////////////////////// // cNetwork API: cUDPEndpointPtr cNetwork::CreateUDPEndpoint(UInt16 a_Port, cUDPEndpoint::cCallbacks & a_Callbacks) { return std::make_shared(a_Port, a_Callbacks); } ================================================ FILE: src/OSSupport/UDPEndpointImpl.h ================================================ // UDPEndpointImpl.h // Declares the cUDPEndpointImpl class representing an implementation of an endpoint in UDP communication #pragma once #include "Network.h" #include // fwd: class cUDPEndpointImpl; typedef std::shared_ptr cUDPEndpointImplPtr; class cUDPEndpointImpl: public cUDPEndpoint { using Super = cUDPEndpoint; public: /** Creates a new instance of the endpoint, with the specified callbacks. Tries to open on the specified port; if it fails, the endpoint is left in the "closed" state. If a_Port is 0, the OS is free to assign any port number it likes to the endpoint. */ cUDPEndpointImpl(UInt16 a_Port, cUDPEndpoint::cCallbacks & a_Callbacks); virtual ~cUDPEndpointImpl() override; // cUDPEndpoint overrides: virtual void Close(void) override; virtual bool IsOpen(void) const override; virtual UInt16 GetPort(void) const override; virtual bool Send(const AString & a_Payload, const AString & a_Host, UInt16 a_Port) override; virtual void EnableBroadcasts(void) override; protected: /** The local port on which the endpoint is open. If this is zero, it means the endpoint is closed - either opening has failed, or it has been closed explicitly. */ UInt16 m_Port; /** The primary underlying OS socket. */ evutil_socket_t m_MainSock; /** True if m_MainSock is in the IPv6 namespace (needs IPv6 addresses for sending). */ bool m_IsMainSockIPv6; /** The secondary OS socket (if primary doesn't support dualstack). */ evutil_socket_t m_SecondarySock; /** The LibEvent handle for the primary socket. */ event * m_MainEvent; /** The LibEvent handle for the secondary socket. */ event * m_SecondaryEvent; /** Creates and opens the socket on the specified port. If a_Port is 0, the OS is free to assign any port number it likes to the endpoint. If the opening fails, the OnError() callback is called and the endpoint is left "closed" (IsOpen() returns false). */ void Open(UInt16 a_Port); /** The callback that LibEvent calls when an event occurs on one of the sockets. Calls Callback() on a_Self. */ static void RawCallback(evutil_socket_t a_Socket, short a_What, void * a_Self); /** The callback that is called when an event occurs on one of the sockets. */ void Callback(evutil_socket_t a_Socket, short a_What); }; ================================================ FILE: src/OSSupport/WinStackWalker.cpp ================================================ // WinStackWalker.cpp // Implements the stack walking for Windows binaries /* LICENSE (https://www.opensource.org/licenses/bsd-license.php) Copyright (c) 2005-2010, Jochen Kalmbach All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and / or other materials provided with the distribution. Neither the name of Jochen Kalmbach nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. NOTE: 2017-06-16 madmaxoft: Removed the legacy VS code and generally cleaned up */ #include "Globals.h" #ifdef _WIN32 #include #pragma comment(lib, "version.lib") // for "VerQueryValue" #pragma warning(disable:4826) #pragma warning(disable:4996) // "GetVersionEx" was declared deprecated #include "WinStackWalker.h" #pragma pack(push, 8) #include #pragma pack(pop) // Copy szSrc to szDest, but at most nMaxDestSize bytes. Always NUL-terminate template static void MyStrCpy(CHAR (&szDest)[COUNT], const CHAR * szSrc) { auto len = strlen(szSrc); if (len < COUNT) { memcpy(szDest, szSrc, len + 1); } else { memcpy(szDest, szSrc, COUNT - 1); szDest[COUNT - 1] = 0; } } // Normally it should be enough to use 'CONTEXT_FULL' (better would be 'CONTEXT_ALL') #define USED_CONTEXT_FLAGS CONTEXT_FULL class StackWalkerInternal { public: StackWalkerInternal(WinStackWalker * parent, HANDLE hProcess) { m_parent = parent; m_hDbhHelp = nullptr; pSC = nullptr; m_hProcess = hProcess; m_szSymPath = nullptr; pSFTA = nullptr; pSGLFA = nullptr; pSGMB = nullptr; pSGMI = nullptr; pSGO = nullptr; pSGSFA = nullptr; pSI = nullptr; pSLM = nullptr; pSSO = nullptr; pSW = nullptr; pUDSN = nullptr; pSGSP = nullptr; } ~StackWalkerInternal() { if (pSC != nullptr) { pSC(m_hProcess); // SymCleanup } if (m_hDbhHelp != nullptr) { FreeLibrary(m_hDbhHelp); } m_hDbhHelp = nullptr; m_parent = nullptr; if (m_szSymPath != nullptr) { free(m_szSymPath); } m_szSymPath = nullptr; } BOOL Init(LPCSTR szSymPath) { if (m_parent == nullptr) { return FALSE; } // Dynamically load the Entry-Points for dbghelp.dll: // First try to load the newsest one from TCHAR szTemp[4096]; // But before wqe do this, we first check if the ".local" file exists if (GetModuleFileName(nullptr, szTemp, sizeof(szTemp)) > 0) { _tcscat_s(szTemp, _T(".local")); if (GetFileAttributes(szTemp) == INVALID_FILE_ATTRIBUTES) { // ".local" file does not exist, so we can try to load the dbghelp.dll from the "Debugging Tools for Windows" // Ok, first try the new path according to the archtitecture: #ifdef _M_IX86 if ((m_hDbhHelp == nullptr) && (GetEnvironmentVariable(_T("ProgramFiles"), szTemp, ARRAYCOUNT(szTemp)) > 0)) { _tcscat_s(szTemp, _T("\\Debugging Tools for Windows (x86)\\dbghelp.dll")); // now check if the file exists: if (GetFileAttributes(szTemp) != INVALID_FILE_ATTRIBUTES) { m_hDbhHelp = LoadLibrary(szTemp); } } #elif _M_X64 if ((m_hDbhHelp == nullptr) && (GetEnvironmentVariable(_T("ProgramFiles"), szTemp, ARRAYCOUNT(szTemp)) > 0)) { _tcscat_s(szTemp, _T("\\Debugging Tools for Windows (x64)\\dbghelp.dll")); // now check if the file exists: if (GetFileAttributes(szTemp) != INVALID_FILE_ATTRIBUTES) { m_hDbhHelp = LoadLibrary(szTemp); } } #elif _M_IA64 if ((m_hDbhHelp == nullptr) && (GetEnvironmentVariable(_T("ProgramFiles"), szTemp, ARRAYCOUNT(szTemp)) > 0)) { _tcscat_s(szTemp, _T("\\Debugging Tools for Windows (ia64)\\dbghelp.dll")); // now check if the file exists: if (GetFileAttributes(szTemp) != INVALID_FILE_ATTRIBUTES) { m_hDbhHelp = LoadLibrary(szTemp); } } #endif // If still not found, try the old directories... if ((m_hDbhHelp == nullptr) && (GetEnvironmentVariable(_T("ProgramFiles"), szTemp, ARRAYCOUNT(szTemp)) > 0)) { _tcscat_s(szTemp, _T("\\Debugging Tools for Windows\\dbghelp.dll")); // now check if the file exists: if (GetFileAttributes(szTemp) != INVALID_FILE_ATTRIBUTES) { m_hDbhHelp = LoadLibrary(szTemp); } } #if defined _M_X64 || defined _M_IA64 // Still not found? Then try to load the (old) 64-Bit version: if ((m_hDbhHelp == nullptr) && (GetEnvironmentVariable(_T("ProgramFiles"), szTemp, ARRAYCOUNT(szTemp)) > 0)) { _tcscat_s(szTemp, _T("\\Debugging Tools for Windows 64-Bit\\dbghelp.dll")); if (GetFileAttributes(szTemp) != INVALID_FILE_ATTRIBUTES) { m_hDbhHelp = LoadLibrary(szTemp); } } #endif } } if (m_hDbhHelp == nullptr) // if not already loaded, try to load a default-one { m_hDbhHelp = LoadLibrary(_T("dbghelp.dll")); } if (m_hDbhHelp == nullptr) { return FALSE; } pSI = (tSI)GetProcAddress(m_hDbhHelp, "SymInitialize"); pSC = (tSC)GetProcAddress(m_hDbhHelp, "SymCleanup"); pSW = (tSW)GetProcAddress(m_hDbhHelp, "StackWalk64"); pSGO = (tSGO)GetProcAddress(m_hDbhHelp, "SymGetOptions"); pSSO = (tSSO)GetProcAddress(m_hDbhHelp, "SymSetOptions"); pSFTA = (tSFTA)GetProcAddress(m_hDbhHelp, "SymFunctionTableAccess64"); pSGLFA = (tSGLFA)GetProcAddress(m_hDbhHelp, "SymGetLineFromAddr64"); pSGMB = (tSGMB)GetProcAddress(m_hDbhHelp, "SymGetModuleBase64"); pSGMI = (tSGMI)GetProcAddress(m_hDbhHelp, "SymGetModuleInfo64"); // pSGMI_V3 = (tSGMI_V3) GetProcAddress(m_hDbhHelp, "SymGetModuleInfo64"); pSGSFA = (tSGSFA)GetProcAddress(m_hDbhHelp, "SymGetSymFromAddr64"); pUDSN = (tUDSN)GetProcAddress(m_hDbhHelp, "UnDecorateSymbolName"); pSLM = (tSLM)GetProcAddress(m_hDbhHelp, "SymLoadModule64"); pSGSP = (tSGSP)GetProcAddress(m_hDbhHelp, "SymGetSearchPath"); if ( (pSC == nullptr) || (pSFTA == nullptr) || (pSGMB == nullptr) || (pSGMI == nullptr) || (pSGO == nullptr) || (pSGSFA == nullptr) || (pSI == nullptr) || (pSSO == nullptr) || (pSW == nullptr) || (pUDSN == nullptr) || (pSLM == nullptr) ) { FreeLibrary(m_hDbhHelp); m_hDbhHelp = nullptr; pSC = nullptr; return FALSE; } // SymInitialize if (szSymPath != nullptr) { m_szSymPath = _strdup(szSymPath); } if (this->pSI(m_hProcess, m_szSymPath, FALSE) == FALSE) { this->m_parent->OnDbgHelpErr("SymInitialize", GetLastError(), 0); } DWORD symOptions = this->pSGO(); // SymGetOptions symOptions |= SYMOPT_LOAD_LINES; symOptions |= SYMOPT_FAIL_CRITICAL_ERRORS; symOptions = this->pSSO(symOptions); char buf[WinStackWalker::STACKWALK_MAX_NAMELEN] = { 0 }; if (this->pSGSP != nullptr) { if (this->pSGSP(m_hProcess, buf, static_cast(sizeof(buf))) == FALSE) { this->m_parent->OnDbgHelpErr("SymGetSearchPath", GetLastError(), 0); } } char szUserName[1024] = { 0 }; DWORD dwSize = static_cast(sizeof(szUserName)); GetUserNameA(szUserName, &dwSize); this->m_parent->OnSymInit(buf, symOptions, szUserName); return TRUE; } WinStackWalker * m_parent; HMODULE m_hDbhHelp; HANDLE m_hProcess; LPSTR m_szSymPath; #pragma pack(push, 8) struct IMAGEHLP_MODULE64_V2 { DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_MODULE64) DWORD64 BaseOfImage; // base load address of module DWORD ImageSize; // virtual size of the loaded module DWORD TimeDateStamp; // date / time stamp from pe header DWORD CheckSum; // checksum from the pe header DWORD NumSyms; // number of symbols in the symbol table SYM_TYPE SymType; // type of symbols loaded CHAR ModuleName[32]; // module name CHAR ImageName[256]; // image name CHAR LoadedImageName[256]; // symbol file name }; #pragma pack(pop) // SymCleanup() typedef BOOL(__stdcall *tSC)(IN HANDLE hProcess); tSC pSC; // SymFunctionTableAccess64() typedef PVOID(__stdcall *tSFTA)(HANDLE hProcess, DWORD64 AddrBase); tSFTA pSFTA; // SymGetLineFromAddr64() typedef BOOL(__stdcall *tSGLFA)(IN HANDLE hProcess, IN DWORD64 dwAddr, OUT PDWORD pdwDisplacement, OUT PIMAGEHLP_LINE64 Line); tSGLFA pSGLFA; // SymGetModuleBase64() typedef DWORD64(__stdcall *tSGMB)(IN HANDLE hProcess, IN DWORD64 dwAddr); tSGMB pSGMB; // SymGetModuleInfo64() typedef BOOL(__stdcall *tSGMI)(IN HANDLE hProcess, IN DWORD64 dwAddr, OUT IMAGEHLP_MODULE64_V2 *ModuleInfo); tSGMI pSGMI; // // SymGetModuleInfo64() // typedef BOOL (__stdcall *tSGMI_V3)( IN HANDLE hProcess, IN DWORD64 dwAddr, OUT IMAGEHLP_MODULE64_V3 *ModuleInfo); // tSGMI_V3 pSGMI_V3; // SymGetOptions() typedef DWORD(__stdcall *tSGO)(VOID); tSGO pSGO; // SymGetSymFromAddr64() typedef BOOL(__stdcall *tSGSFA)(IN HANDLE hProcess, IN DWORD64 dwAddr, OUT PDWORD64 pdwDisplacement, OUT PIMAGEHLP_SYMBOL64 Symbol); tSGSFA pSGSFA; // SymInitialize() typedef BOOL(__stdcall *tSI)(IN HANDLE hProcess, IN PSTR UserSearchPath, IN BOOL fInvadeProcess); tSI pSI; // SymLoadModule64() typedef DWORD64(__stdcall *tSLM)(IN HANDLE hProcess, IN HANDLE hFile, IN PSTR ImageName, IN PSTR ModuleName, IN DWORD64 BaseOfDll, IN DWORD SizeOfDll); tSLM pSLM; // SymSetOptions() typedef DWORD(__stdcall *tSSO)(IN DWORD SymOptions); tSSO pSSO; // StackWalk64() typedef BOOL(__stdcall *tSW)( DWORD MachineType, HANDLE hProcess, HANDLE hThread, LPSTACKFRAME64 StackFrame, PVOID ContextRecord, PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine, PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine, PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine, PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress); tSW pSW; // UnDecorateSymbolName() typedef DWORD(__stdcall WINAPI *tUDSN)(PCSTR DecoratedName, PSTR UnDecoratedName, DWORD UndecoratedLength, DWORD Flags); tUDSN pUDSN; typedef BOOL(__stdcall WINAPI *tSGSP)(HANDLE hProcess, PSTR SearchPath, DWORD SearchPathLength); tSGSP pSGSP; private: // **************************************** ToolHelp32 ************************ #define MAX_MODULE_NAME32 255 #define TH32CS_SNAPMODULE 0x00000008 #pragma pack(push, 8) typedef struct tagMODULEENTRY32 { DWORD dwSize; DWORD th32ModuleID; // This module DWORD th32ProcessID; // owning process DWORD GlblcntUsage; // Global usage count on the module DWORD ProccntUsage; // Module usage count in th32ProcessID's context BYTE * modBaseAddr; // Base address of module in th32ProcessID's context DWORD modBaseSize; // Size in bytes of module starting at modBaseAddr HMODULE hModule; // The hModule of this module in th32ProcessID's context char szModule[MAX_MODULE_NAME32 + 1]; char szExePath[MAX_PATH]; } MODULEENTRY32; typedef MODULEENTRY32 * PMODULEENTRY32; typedef MODULEENTRY32 * LPMODULEENTRY32; #pragma pack(pop) BOOL GetModuleListTH32(HANDLE hProcess, DWORD pid) { // CreateToolhelp32Snapshot() typedef HANDLE(__stdcall *tCT32S)(DWORD dwFlags, DWORD th32ProcessID); // Module32First() typedef BOOL(__stdcall *tM32F)(HANDLE hSnapshot, LPMODULEENTRY32 lpme); // Module32Next() typedef BOOL(__stdcall *tM32N)(HANDLE hSnapshot, LPMODULEENTRY32 lpme); // try both dlls... const TCHAR *dllname[] = { _T("kernel32.dll"), _T("tlhelp32.dll") }; HINSTANCE hToolhelp = nullptr; tCT32S pCT32S = nullptr; tM32F pM32F = nullptr; tM32N pM32N = nullptr; HANDLE hSnap; MODULEENTRY32 me; me.dwSize = sizeof(me); BOOL keepGoing; for (size_t i = 0; i < ARRAYCOUNT(dllname); i++) { hToolhelp = LoadLibrary(dllname[i]); if (hToolhelp == nullptr) { continue; } pCT32S = (tCT32S)GetProcAddress(hToolhelp, "CreateToolhelp32Snapshot"); pM32F = (tM32F)GetProcAddress(hToolhelp, "Module32First"); pM32N = (tM32N)GetProcAddress(hToolhelp, "Module32Next"); if ((pCT32S != nullptr) && (pM32F != nullptr) && (pM32N != nullptr)) { break; // found the functions! } FreeLibrary(hToolhelp); hToolhelp = nullptr; } if (hToolhelp == nullptr) { return FALSE; } hSnap = pCT32S(TH32CS_SNAPMODULE, pid); if (hSnap == (HANDLE)-1) { FreeLibrary(hToolhelp); return FALSE; } keepGoing = !!pM32F(hSnap, &me); int cnt = 0; while (keepGoing) { this->LoadModule(hProcess, me.szExePath, me.szModule, (DWORD64)me.modBaseAddr, me.modBaseSize); cnt++; keepGoing = !!pM32N(hSnap, &me); } CloseHandle(hSnap); FreeLibrary(hToolhelp); if (cnt <= 0) { return FALSE; } return TRUE; } // GetModuleListTH32 // **************************************** PSAPI ************************ typedef struct _MODULEINFO { LPVOID lpBaseOfDll; DWORD SizeOfImage; LPVOID EntryPoint; } MODULEINFO, *LPMODULEINFO; BOOL GetModuleListPSAPI(HANDLE hProcess) { // EnumProcessModules() typedef BOOL(__stdcall *tEPM)(HANDLE hProcess, HMODULE *lphModule, DWORD cb, LPDWORD lpcbNeeded); // GetModuleFileNameEx() typedef DWORD(__stdcall *tGMFNE)(HANDLE hProcess, HMODULE hModule, LPSTR lpFilename, DWORD nSize); // GetModuleBaseName() typedef DWORD(__stdcall *tGMBN)(HANDLE hProcess, HMODULE hModule, LPSTR lpFilename, DWORD nSize); // GetModuleInformation() typedef BOOL(__stdcall *tGMI)(HANDLE hProcess, HMODULE hModule, LPMODULEINFO pmi, DWORD nSize); HINSTANCE hPsapi; tEPM pEPM; tGMFNE pGMFNE; tGMBN pGMBN; tGMI pGMI; DWORD i; DWORD cbNeeded; MODULEINFO mi; HMODULE *hMods = 0; char *tt = nullptr; char *tt2 = nullptr; const SIZE_T TTBUFLEN = 8096; int cnt = 0; hPsapi = LoadLibrary(_T("psapi.dll")); if (hPsapi == nullptr) { return FALSE; } pEPM = (tEPM)GetProcAddress(hPsapi, "EnumProcessModules"); pGMFNE = (tGMFNE)GetProcAddress(hPsapi, "GetModuleFileNameExA"); pGMBN = (tGMFNE)GetProcAddress(hPsapi, "GetModuleBaseNameA"); pGMI = (tGMI)GetProcAddress(hPsapi, "GetModuleInformation"); if ((pEPM == nullptr) || (pGMFNE == nullptr) || (pGMBN == nullptr) || (pGMI == nullptr)) { // we couldn't find all functions FreeLibrary(hPsapi); return FALSE; } hMods = (HMODULE*)malloc(sizeof(HMODULE) * (TTBUFLEN / sizeof HMODULE)); tt = (char*)malloc(sizeof(char) * TTBUFLEN); tt2 = (char*)malloc(sizeof(char) * TTBUFLEN); if ((hMods == nullptr) || (tt == nullptr) || (tt2 == nullptr)) { goto cleanup; } if (!pEPM(hProcess, hMods, TTBUFLEN, &cbNeeded)) { goto cleanup; } if (cbNeeded > TTBUFLEN) { goto cleanup; } for (i = 0; i < cbNeeded / sizeof hMods[0]; i++) { // base address, size pGMI(hProcess, hMods[i], &mi, sizeof mi); // image file name tt[0] = 0; pGMFNE(hProcess, hMods[i], tt, TTBUFLEN); // module name tt2[0] = 0; pGMBN(hProcess, hMods[i], tt2, TTBUFLEN); DWORD dwRes = this->LoadModule(hProcess, tt, tt2, (DWORD64)mi.lpBaseOfDll, mi.SizeOfImage); if (dwRes != ERROR_SUCCESS) { this->m_parent->OnDbgHelpErr("LoadModule", dwRes, 0); } cnt++; } cleanup: if (hPsapi != nullptr) { FreeLibrary(hPsapi); } if (tt2 != nullptr) { free(tt2); } if (tt != nullptr) { free(tt); } if (hMods != nullptr) { free(hMods); } return cnt != 0; } // GetModuleListPSAPI DWORD LoadModule(HANDLE hProcess, LPCSTR img, LPCSTR mod, DWORD64 baseAddr, DWORD size) { CHAR *szImg = _strdup(img); CHAR *szMod = _strdup(mod); DWORD result = ERROR_SUCCESS; if ((szImg == nullptr) || (szMod == nullptr)) { result = ERROR_NOT_ENOUGH_MEMORY; } else { if (pSLM(hProcess, 0, szImg, szMod, baseAddr, size) == 0) { result = GetLastError(); } } ULONGLONG fileVersion = 0; if ((m_parent != nullptr) && (szImg != nullptr)) { // try to retrive the file-version: if ((this->m_parent->m_options & WinStackWalker::RetrieveFileVersion) != 0) { VS_FIXEDFILEINFO *fInfo = nullptr; DWORD dwHandle; DWORD dwSize = GetFileVersionInfoSizeA(szImg, &dwHandle); if (dwSize > 0) { LPVOID vData = malloc(dwSize); if (vData != nullptr) { if (GetFileVersionInfoA(szImg, dwHandle, dwSize, vData) != 0) { UINT len; TCHAR szSubBlock[] = _T("\\"); if (VerQueryValue(vData, szSubBlock, (LPVOID*)&fInfo, &len) == 0) { fInfo = nullptr; } else { fileVersion = ((ULONGLONG)fInfo->dwFileVersionLS) + ((ULONGLONG)fInfo->dwFileVersionMS << 32); } } free(vData); } } } // Retrive some additional-infos about the module IMAGEHLP_MODULE64_V2 Module; const char *szSymType = "-unknown-"; if (this->GetModuleInfo(hProcess, baseAddr, &Module) != FALSE) { switch (Module.SymType) { case SymNone: szSymType = "-nosymbols-"; break; case SymCoff: szSymType = "COFF"; break; case SymCv: szSymType = "CV"; break; case SymPdb: szSymType = "PDB"; break; case SymExport: szSymType = "-exported-"; break; case SymDeferred: szSymType = "-deferred-"; break; case SymSym: szSymType = "SYM"; break; case 7: szSymType = "DIA"; break; case 8: szSymType = "Virtual"; break; } } this->m_parent->OnLoadModule(img, mod, baseAddr, size, result, szSymType, Module.LoadedImageName, fileVersion); } if (szImg != nullptr) { free(szImg); } if (szMod != nullptr) { free(szMod); } return result; } public: BOOL LoadModules(HANDLE hProcess, DWORD dwProcessId) { // first try toolhelp32 if (GetModuleListTH32(hProcess, dwProcessId)) { return true; } // then try psapi return GetModuleListPSAPI(hProcess); } BOOL GetModuleInfo(HANDLE hProcess, DWORD64 baseAddr, IMAGEHLP_MODULE64_V2 *pModuleInfo) { if (this->pSGMI == nullptr) { SetLastError(ERROR_DLL_INIT_FAILED); return FALSE; } pModuleInfo->SizeOfStruct = sizeof(IMAGEHLP_MODULE64_V2); void * pData = malloc(4096); // reserve enough memory, so the bug in v6.3.5.1 does not lead to memory-overwrites... if (pData == nullptr) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); return FALSE; } memcpy(pData, pModuleInfo, sizeof(IMAGEHLP_MODULE64_V2)); if (this->pSGMI(hProcess, baseAddr, (IMAGEHLP_MODULE64_V2*)pData) != FALSE) { // only copy as much memory as is reserved... memcpy(pModuleInfo, pData, sizeof(IMAGEHLP_MODULE64_V2)); pModuleInfo->SizeOfStruct = sizeof(IMAGEHLP_MODULE64_V2); free(pData); return TRUE; } free(pData); SetLastError(ERROR_DLL_INIT_FAILED); return FALSE; } }; // ############################################################# WinStackWalker::WinStackWalker(DWORD dwProcessId, HANDLE hProcess) { this->m_options = OptionsAll; this->m_modulesLoaded = FALSE; this->m_hProcess = hProcess; this->m_sw = new StackWalkerInternal(this, this->m_hProcess); this->m_dwProcessId = dwProcessId; this->m_szSymPath = nullptr; this->m_MaxRecursionCount = 1000; } WinStackWalker::WinStackWalker(int options, LPCSTR szSymPath, DWORD dwProcessId, HANDLE hProcess) { this->m_options = options; this->m_modulesLoaded = FALSE; this->m_hProcess = hProcess; this->m_sw = new StackWalkerInternal(this, this->m_hProcess); this->m_dwProcessId = dwProcessId; if (szSymPath != nullptr) { this->m_szSymPath = _strdup(szSymPath); this->m_options |= SymBuildPath; } else { this->m_szSymPath = nullptr; } this->m_MaxRecursionCount = 1000; } WinStackWalker::~WinStackWalker() { if (m_szSymPath != nullptr) { free(m_szSymPath); } m_szSymPath = nullptr; if (this->m_sw != nullptr) { delete this->m_sw; } this->m_sw = nullptr; } BOOL WinStackWalker::LoadModules() { if (this->m_sw == nullptr) { SetLastError(ERROR_DLL_INIT_FAILED); return FALSE; } if (m_modulesLoaded != FALSE) { return TRUE; } // Build the sym-path: char *szSymPath = nullptr; if ((this->m_options & SymBuildPath) != 0) { const size_t nSymPathLen = 4096; szSymPath = (char*)malloc(nSymPathLen); if (szSymPath == nullptr) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); return FALSE; } szSymPath[0] = 0; // Now first add the (optional) provided sympath: if (this->m_szSymPath != nullptr) { strcat_s(szSymPath, nSymPathLen, this->m_szSymPath); strcat_s(szSymPath, nSymPathLen, ";"); } strcat_s(szSymPath, nSymPathLen, ".;"); const DWORD nTempLen = 1024; char szTemp[nTempLen]; // Now add the current directory: if (GetCurrentDirectoryA(nTempLen, szTemp) > 0) { szTemp[nTempLen - 1] = 0; strcat_s(szSymPath, nSymPathLen, szTemp); strcat_s(szSymPath, nSymPathLen, ";"); } // Now add the path for the main-module: if (GetModuleFileNameA(nullptr, szTemp, nTempLen) > 0) { szTemp[nTempLen - 1] = 0; for (char *p = (szTemp + strlen(szTemp) - 1); p >= szTemp; --p) { // locate the rightmost path separator if ((*p == '\\') || (*p == '/') || (*p == ':')) { *p = 0; break; } } // for (search for path separator...) if (szTemp[0] != '\0') { strcat_s(szSymPath, nSymPathLen, szTemp); strcat_s(szSymPath, nSymPathLen, ";"); } } if (GetEnvironmentVariableA("_NT_SYMBOL_PATH", szTemp, nTempLen) > 0) { szTemp[nTempLen - 1] = 0; strcat_s(szSymPath, nSymPathLen, szTemp); strcat_s(szSymPath, nSymPathLen, ";"); } if (GetEnvironmentVariableA("_NT_ALTERNATE_SYMBOL_PATH", szTemp, nTempLen) > 0) { szTemp[nTempLen - 1] = 0; strcat_s(szSymPath, nSymPathLen, szTemp); strcat_s(szSymPath, nSymPathLen, ";"); } if (GetEnvironmentVariableA("SYSTEMROOT", szTemp, nTempLen) > 0) { szTemp[nTempLen - 1] = 0; strcat_s(szSymPath, nSymPathLen, szTemp); strcat_s(szSymPath, nSymPathLen, ";"); // also add the "system32"-directory: strcat_s(szTemp, nTempLen, "\\system32"); strcat_s(szSymPath, nSymPathLen, szTemp); strcat_s(szSymPath, nSymPathLen, ";"); } if ((this->m_options & SymUseSymSrv) != 0) { if (GetEnvironmentVariableA("SYSTEMDRIVE", szTemp, nTempLen) > 0) { szTemp[nTempLen - 1] = 0; strcat_s(szSymPath, nSymPathLen, "SRV*"); strcat_s(szSymPath, nSymPathLen, szTemp); strcat_s(szSymPath, nSymPathLen, "\\websymbols"); strcat_s(szSymPath, nSymPathLen, "*https://msdl.microsoft.com/download/symbols;"); } else { strcat_s(szSymPath, nSymPathLen, "SRV*c:\\websymbols*https://msdl.microsoft.com/download/symbols;"); } } } // if SymBuildPath // First Init the whole stuff... BOOL bRet = this->m_sw->Init(szSymPath); if (szSymPath != nullptr) { free(szSymPath); szSymPath = nullptr; } if (bRet == FALSE) { this->OnDbgHelpErr("Error while initializing dbghelp.dll", 0, 0); SetLastError(ERROR_DLL_INIT_FAILED); return FALSE; } bRet = this->m_sw->LoadModules(this->m_hProcess, this->m_dwProcessId); if (bRet != FALSE) { m_modulesLoaded = TRUE; } return bRet; } // The following is used to pass the "userData"-Pointer to the user-provided readMemoryFunction // This has to be done due to a problem with the "hProcess"-parameter in x64 // Because this class is in no case multi-threading-enabled (because of the limitations // of dbghelp.dll) it is "safe" to use a static-variable static WinStackWalker::PReadProcessMemoryRoutine s_readMemoryFunction = nullptr; static LPVOID s_readMemoryFunction_UserData = nullptr; BOOL WinStackWalker::ShowCallstack(HANDLE hThread, const CONTEXT *context, PReadProcessMemoryRoutine readMemoryFunction, LPVOID pUserData) { CONTEXT c; CallstackEntry csEntry; IMAGEHLP_SYMBOL64 *pSym = nullptr; StackWalkerInternal::IMAGEHLP_MODULE64_V2 Module; IMAGEHLP_LINE64 Line; int frameNum; bool bLastEntryCalled = true; int curRecursionCount = 0; if (!m_modulesLoaded) { this->LoadModules(); // ignore the result... } if (this->m_sw->m_hDbhHelp == nullptr) { SetLastError(ERROR_DLL_INIT_FAILED); return FALSE; } s_readMemoryFunction = readMemoryFunction; s_readMemoryFunction_UserData = pUserData; if (context == nullptr) { // If no context is provided, capture the context if (hThread == GetCurrentThread()) { GET_CURRENT_CONTEXT(c, USED_CONTEXT_FLAGS); } else { SuspendThread(hThread); memset(&c, 0, sizeof(CONTEXT)); c.ContextFlags = USED_CONTEXT_FLAGS; if (GetThreadContext(hThread, &c) == FALSE) { ResumeThread(hThread); return FALSE; } } } else { c = *context; } // init STACKFRAME for first call STACKFRAME64 s; // in / out stackframe memset(&s, 0, sizeof(s)); DWORD imageType; #ifdef _M_IX86 // normally, call ImageNtHeader() and use machine info from PE header imageType = IMAGE_FILE_MACHINE_I386; s.AddrPC.Offset = c.Eip; s.AddrPC.Mode = AddrModeFlat; s.AddrFrame.Offset = c.Ebp; s.AddrFrame.Mode = AddrModeFlat; s.AddrStack.Offset = c.Esp; s.AddrStack.Mode = AddrModeFlat; #elif _M_X64 imageType = IMAGE_FILE_MACHINE_AMD64; s.AddrPC.Offset = c.Rip; s.AddrPC.Mode = AddrModeFlat; s.AddrFrame.Offset = c.Rsp; s.AddrFrame.Mode = AddrModeFlat; s.AddrStack.Offset = c.Rsp; s.AddrStack.Mode = AddrModeFlat; #elif _M_IA64 imageType = IMAGE_FILE_MACHINE_IA64; s.AddrPC.Offset = c.StIIP; s.AddrPC.Mode = AddrModeFlat; s.AddrFrame.Offset = c.IntSp; s.AddrFrame.Mode = AddrModeFlat; s.AddrBStore.Offset = c.RsBSP; s.AddrBStore.Mode = AddrModeFlat; s.AddrStack.Offset = c.IntSp; s.AddrStack.Mode = AddrModeFlat; #else #error "Platform not supported!" #endif pSym = (IMAGEHLP_SYMBOL64 *)malloc(sizeof(IMAGEHLP_SYMBOL64) + STACKWALK_MAX_NAMELEN); if (!pSym) { goto cleanup; // not enough memory... } memset(pSym, 0, sizeof(IMAGEHLP_SYMBOL64) + STACKWALK_MAX_NAMELEN); pSym->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64); pSym->MaxNameLength = STACKWALK_MAX_NAMELEN; memset(&Line, 0, sizeof(Line)); Line.SizeOfStruct = sizeof(Line); memset(&Module, 0, sizeof(Module)); Module.SizeOfStruct = sizeof(Module); for (frameNum = 0; ; ++frameNum) { // get next stack frame (StackWalk64(), SymFunctionTableAccess64(), SymGetModuleBase64()) // if this returns ERROR_INVALID_ADDRESS (487) or ERROR_NOACCESS (998), you can // assume that either you are done, or that the stack is so hosed that the next // deeper frame could not be found. // CONTEXT need not to be suplied if imageTyp is IMAGE_FILE_MACHINE_I386! if (!this->m_sw->pSW(imageType, this->m_hProcess, hThread, &s, &c, myReadProcMem, this->m_sw->pSFTA, this->m_sw->pSGMB, nullptr)) { // INFO: "StackWalk64" does not set "GetLastError"... this->OnDbgHelpErr("StackWalk64", 0, s.AddrPC.Offset); break; } csEntry.offset = s.AddrPC.Offset; csEntry.name[0] = 0; csEntry.undName[0] = 0; csEntry.undFullName[0] = 0; csEntry.offsetFromSmybol = 0; csEntry.offsetFromLine = 0; csEntry.lineFileName[0] = 0; csEntry.lineNumber = 0; csEntry.loadedImageName[0] = 0; csEntry.moduleName[0] = 0; if (s.AddrPC.Offset == s.AddrReturn.Offset) { if ((this->m_MaxRecursionCount > 0) && (curRecursionCount > m_MaxRecursionCount)) { this->OnDbgHelpErr("StackWalk64-Endless-Callstack!", 0, s.AddrPC.Offset); break; } curRecursionCount++; } else { curRecursionCount = 0; } if (s.AddrPC.Offset != 0) { // we seem to have a valid PC // show procedure info (SymGetSymFromAddr64()) if (this->m_sw->pSGSFA(this->m_hProcess, s.AddrPC.Offset, &(csEntry.offsetFromSmybol), pSym) != FALSE) { MyStrCpy(csEntry.name, pSym->Name); // UnDecorateSymbolName() this->m_sw->pUDSN(pSym->Name, csEntry.undName, static_cast(sizeof(csEntry.undName)), UNDNAME_NAME_ONLY); this->m_sw->pUDSN(pSym->Name, csEntry.undFullName, static_cast(sizeof(csEntry.undFullName)), UNDNAME_COMPLETE); } else { this->OnDbgHelpErr("SymGetSymFromAddr64", GetLastError(), s.AddrPC.Offset); } // show line number info, NT5.0-method (SymGetLineFromAddr64()) if (this->m_sw->pSGLFA != nullptr) { if (this->m_sw->pSGLFA(this->m_hProcess, s.AddrPC.Offset, &(csEntry.offsetFromLine), &Line) != FALSE) { csEntry.lineNumber = Line.LineNumber; MyStrCpy(csEntry.lineFileName, Line.FileName); } else { this->OnDbgHelpErr("SymGetLineFromAddr64", GetLastError(), s.AddrPC.Offset); } } // show module info (SymGetModuleInfo64()) if (this->m_sw->GetModuleInfo(this->m_hProcess, s.AddrPC.Offset, &Module) != FALSE) { switch (Module.SymType) { case SymNone: csEntry.symTypeString = "-nosymbols-"; break; case SymCoff: csEntry.symTypeString = "COFF"; break; case SymCv: csEntry.symTypeString = "CV"; break; case SymPdb: csEntry.symTypeString = "PDB"; break; case SymExport: csEntry.symTypeString = "-exported-"; break; case SymDeferred: csEntry.symTypeString = "-deferred-"; break; case SymSym: csEntry.symTypeString = "SYM"; break; case SymDia: csEntry.symTypeString = "DIA"; break; case 8: csEntry.symTypeString = "Virtual"; break; default: csEntry.symTypeString = nullptr; break; } MyStrCpy(csEntry.moduleName, Module.ModuleName); csEntry.baseOfImage = Module.BaseOfImage; MyStrCpy(csEntry.loadedImageName, Module.LoadedImageName); } else { this->OnDbgHelpErr("SymGetModuleInfo64", GetLastError(), s.AddrPC.Offset); } } CallstackEntryType et = nextEntry; if (frameNum == 0) { et = firstEntry; } bLastEntryCalled = false; this->OnCallstackEntry(et, csEntry); if (s.AddrReturn.Offset == 0) { bLastEntryCalled = true; this->OnCallstackEntry(lastEntry, csEntry); SetLastError(ERROR_SUCCESS); break; } } // for (frameNum) cleanup: if (pSym) { free(pSym); } if (bLastEntryCalled == false) { this->OnCallstackEntry(lastEntry, csEntry); } if (context == nullptr) { ResumeThread(hThread); } return TRUE; } BOOL __stdcall WinStackWalker::myReadProcMem( HANDLE hProcess, DWORD64 qwBaseAddress, PVOID lpBuffer, DWORD nSize, LPDWORD lpNumberOfBytesRead ) { if (s_readMemoryFunction == nullptr) { SIZE_T st; BOOL bRet = ReadProcessMemory(hProcess, (LPVOID)qwBaseAddress, lpBuffer, nSize, &st); *lpNumberOfBytesRead = (DWORD)st; // printf("ReadMemory: hProcess: %p, baseAddr: %p, buffer: %p, size: %d, read: %d, result: %d\n", hProcess, (LPVOID) qwBaseAddress, lpBuffer, nSize, (DWORD) st, (DWORD) bRet); return bRet; } else { return s_readMemoryFunction(hProcess, qwBaseAddress, lpBuffer, nSize, lpNumberOfBytesRead, s_readMemoryFunction_UserData); } } void WinStackWalker::OnLoadModule(LPCSTR img, LPCSTR mod, DWORD64 baseAddr, DWORD size, DWORD result, LPCSTR symType, LPCSTR pdbName, ULONGLONG fileVersion) { /* // Uncomment to be notified of loaded DLL modules. char buffer[STACKWALK_MAX_NAMELEN]; if (fileVersion == 0) { _snprintf_s(buffer, sizeof(buffer), "%s:%s (%p), size: %d (result: %d), SymType: '%s', PDB: '%s'\n", img, mod, (LPVOID)baseAddr, size, result, symType, pdbName); } else { DWORD v4 = (DWORD)fileVersion & 0xFFFF; DWORD v3 = (DWORD)(fileVersion >> 16) & 0xFFFF; DWORD v2 = (DWORD)(fileVersion >> 32) & 0xFFFF; DWORD v1 = (DWORD)(fileVersion >> 48) & 0xFFFF; _snprintf_s(buffer, sizeof(buffer), "%s:%s (%p), size: %d (result: %d), SymType: '%s', PDB: '%s', fileVersion: %d.%d.%d.%d\n", img, mod, (LPVOID)baseAddr, size, result, symType, pdbName, v1, v2, v3, v4); } OnOutput(buffer); */ } void WinStackWalker::OnCallstackEntry(CallstackEntryType eType, CallstackEntry &entry) { CHAR buffer[STACKWALK_MAX_NAMELEN + MAX_PATH + 100]; if ((eType == lastEntry) || (entry.offset == 0)) { return; } if (entry.undFullName[0] != 0) { MyStrCpy(entry.name, entry.undFullName); } else if (entry.undName[0] != 0) { MyStrCpy(entry.name, entry.undName); } else if (entry.name[0] == 0) { MyStrCpy(entry.name, "(function-name not available)"); } if (entry.lineFileName[0] == 0) { MyStrCpy(entry.lineFileName, "(filename not available)"); if (entry.moduleName[0] == 0) { MyStrCpy(entry.moduleName, "(module-name not available)"); } _snprintf_s(buffer, sizeof(buffer), "%p (%s): %s: %s\n", (LPVOID)entry.offset, entry.moduleName, entry.lineFileName, entry.name); } else { _snprintf_s(buffer, sizeof(buffer), "%s (%d): %s\n", entry.lineFileName, entry.lineNumber, entry.name); } OnOutput(buffer); } void WinStackWalker::OnDbgHelpErr(LPCSTR szFuncName, DWORD gle, DWORD64 addr) { CHAR buffer[STACKWALK_MAX_NAMELEN]; _snprintf_s(buffer, sizeof(buffer), "ERROR: %s, GetLastError: %d (Address: %p)\n", szFuncName, gle, (LPVOID)addr); OnOutput(buffer); } void WinStackWalker::OnSymInit(LPCSTR szSearchPath, DWORD symOptions, LPCSTR szUserName) { CHAR buffer[STACKWALK_MAX_NAMELEN]; _snprintf_s(buffer, sizeof(buffer), "SymInit: Symbol-SearchPath: '%s', symOptions: %d, UserName: '%s'\n", szSearchPath, symOptions, szUserName); OnOutput(buffer); // Also display the OS-version OSVERSIONINFOEXA ver; ZeroMemory(&ver, sizeof(OSVERSIONINFOEXA)); ver.dwOSVersionInfoSize = sizeof(ver); if (GetVersionExA((OSVERSIONINFOA*)&ver) != FALSE) { _snprintf_s(buffer, sizeof(buffer), "OS-Version: %d.%d.%d (%s) 0x%x-0x%x\n", ver.dwMajorVersion, ver.dwMinorVersion, ver.dwBuildNumber, ver.szCSDVersion, ver.wSuiteMask, ver.wProductType ); OnOutput(buffer); } } void WinStackWalker::OnOutput(LPCSTR buffer) { OutputDebugStringA(buffer); } #endif // _WIN32 ================================================ FILE: src/OSSupport/WinStackWalker.h ================================================ // WinStackWalker.h // Declares the stack walking for Windows binaries /* LICENSE (https://www.opensource.org/licenses/bsd-license.php) Copyright (c) 2005-2010, Jochen Kalmbach All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and / or other materials provided with the distribution. Neither the name of Jochen Kalmbach nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once #ifdef _WIN32 // This is Windows-only code class StackWalkerInternal; // forward class WinStackWalker { public: enum StackWalkOptions { // No addition info will be retrived // (only the address is available) RetrieveNone = 0, // Try to get the symbol-name RetrieveSymbol = 1, // Try to get the line for this symbol RetrieveLine = 2, // Try to retrieve the module-infos RetrieveModuleInfo = 4, // Also retrieve the version for the DLL / EXE RetrieveFileVersion = 8, // Contains all the abouve RetrieveVerbose = 0xF, // Generate a "good" symbol-search-path SymBuildPath = 0x10, // Also use the public Microsoft-Symbol-Server SymUseSymSrv = 0x20, // Contains all the abouve "Sym"-options SymAll = 0x30, // Contains all options (default) OptionsAll = 0x3F }; WinStackWalker( int options = OptionsAll, LPCSTR szSymPath = nullptr, DWORD dwProcessId = GetCurrentProcessId(), HANDLE hProcess = GetCurrentProcess() ); WinStackWalker(DWORD dwProcessId, HANDLE hProcess); virtual ~WinStackWalker(); typedef BOOL(__stdcall *PReadProcessMemoryRoutine)( HANDLE hProcess, DWORD64 qwBaseAddress, PVOID lpBuffer, DWORD nSize, LPDWORD lpNumberOfBytesRead, LPVOID pUserData // optional data, which was passed in "ShowCallstack" ); BOOL LoadModules(); BOOL ShowCallstack( HANDLE hThread = GetCurrentThread(), const CONTEXT *context = nullptr, PReadProcessMemoryRoutine readMemoryFunction = nullptr, LPVOID pUserData = nullptr // optional to identify some data in the 'readMemoryFunction'-callback ); protected: enum { STACKWALK_MAX_NAMELEN = 1024, ///< Max name length for found symbols }; protected: // Entry for each Callstack-Entry struct CallstackEntry { DWORD64 offset; // if 0, we have no valid entry CHAR name[STACKWALK_MAX_NAMELEN]; CHAR undName[STACKWALK_MAX_NAMELEN]; CHAR undFullName[STACKWALK_MAX_NAMELEN]; DWORD64 offsetFromSmybol; DWORD offsetFromLine; DWORD lineNumber; CHAR lineFileName[STACKWALK_MAX_NAMELEN]; DWORD symType; LPCSTR symTypeString; CHAR moduleName[STACKWALK_MAX_NAMELEN]; DWORD64 baseOfImage; CHAR loadedImageName[STACKWALK_MAX_NAMELEN]; }; enum CallstackEntryType { firstEntry, nextEntry, lastEntry }; virtual void OnSymInit(LPCSTR szSearchPath, DWORD symOptions, LPCSTR szUserName); virtual void OnLoadModule(LPCSTR img, LPCSTR mod, DWORD64 baseAddr, DWORD size, DWORD result, LPCSTR symType, LPCSTR pdbName, ULONGLONG fileVersion); virtual void OnCallstackEntry(CallstackEntryType eType, CallstackEntry &entry); virtual void OnDbgHelpErr(LPCSTR szFuncName, DWORD gle, DWORD64 addr); virtual void OnOutput(LPCSTR szText); StackWalkerInternal *m_sw; HANDLE m_hProcess; DWORD m_dwProcessId; BOOL m_modulesLoaded; LPSTR m_szSymPath; int m_options; int m_MaxRecursionCount; static BOOL __stdcall myReadProcMem(HANDLE hProcess, DWORD64 qwBaseAddress, PVOID lpBuffer, DWORD nSize, LPDWORD lpNumberOfBytesRead); friend StackWalkerInternal; }; #define GET_CURRENT_CONTEXT(c, contextFlags) \ do \ { \ memset(&c, 0, sizeof(CONTEXT)); \ c.ContextFlags = contextFlags; \ RtlCaptureContext(&c); \ } while (false); #endif // _WIN32 ================================================ FILE: src/OpaqueWorld.h ================================================ #pragma once // fwd: class cBroadcastInterface; class cChunkInterface; class cForEachChunkProvider; class cWorld; class cWorldInterface; /** Utilities to allow casting a cWorld to one of its interfaces without including World.h. */ namespace World { // Defined in World.cpp cBroadcastInterface * GetBroadcastInterface(cWorld * a_World); cForEachChunkProvider * GetFECProvider (cWorld * a_World); cWorldInterface * GetWorldInterface (cWorld * a_World); inline cBroadcastInterface & GetBroadcastInterface(cWorld & a_World) { return *GetBroadcastInterface(&a_World); } inline cForEachChunkProvider & GetFECProvider (cWorld & a_World) { return *GetFECProvider(&a_World); } inline cWorldInterface & GetWorldInterface (cWorld & a_World) { return *GetWorldInterface(&a_World); } // cChunkInterface is more like a pimpl for cChunkMap than an interface so it needs to be returned by value cChunkInterface GetChunkInterface(cWorld & a_World); } ================================================ FILE: src/OverridesSettingsRepository.cpp ================================================ #include "Globals.h" #include "OverridesSettingsRepository.h" cOverridesSettingsRepository::cOverridesSettingsRepository(std::unique_ptr a_Main, cSettingsRepositoryInterface & a_Overrides) : m_Main(std::move(a_Main)), m_Overrides(&a_Overrides) { } bool cOverridesSettingsRepository::KeyExists(const AString a_keyName) const { return m_Overrides->KeyExists(a_keyName) || m_Main->KeyExists(a_keyName); } bool cOverridesSettingsRepository::HasValue(const AString & a_KeyName, const AString & a_ValueName) const { return m_Overrides->HasValue(a_KeyName, a_ValueName) || m_Main->HasValue(a_KeyName, a_ValueName); } int cOverridesSettingsRepository::AddKeyName(const AString & a_keyname) { if (m_Overrides->KeyExists(a_keyname)) { m_Overrides->AddKeyName(a_keyname); return 0; } return m_Main->AddKeyName(a_keyname); } bool cOverridesSettingsRepository::AddKeyComment(const AString & a_keyname, const AString & a_comment) { if (m_Overrides->KeyExists(a_keyname)) { return m_Overrides->AddKeyComment(a_keyname, a_comment); } return m_Main->AddKeyComment(a_keyname, a_comment); } AString cOverridesSettingsRepository::GetKeyComment(const AString & a_keyname, const int a_commentID) const { if (m_Overrides->KeyExists(a_keyname)) { return m_Overrides->GetKeyComment(a_keyname, a_commentID); } return m_Main->GetKeyComment(a_keyname, a_commentID); } bool cOverridesSettingsRepository::DeleteKeyComment(const AString & a_keyname, const int a_commentID) { if (m_Overrides->KeyExists(a_keyname)) { return m_Overrides->DeleteKeyComment(a_keyname, a_commentID); } return m_Main->DeleteKeyComment(a_keyname, a_commentID); } void cOverridesSettingsRepository::AddValue (const AString & a_KeyName, const AString & a_ValueName, const AString & a_Value) { if (m_Overrides->HasValue(a_KeyName, a_ValueName)) { m_Overrides->AddValue(a_KeyName, a_ValueName, a_Value); } else { m_Main->AddValue(a_KeyName, a_ValueName, a_Value); } } std::vector> cOverridesSettingsRepository::GetValues(AString a_keyName) { auto overrides = m_Overrides->GetValues(a_keyName); auto main = m_Main->GetValues(a_keyName); auto ret = overrides; for (const auto & mainpair : main) { bool found = false; for (const auto & overridepair : overrides) { if (overridepair.first == mainpair.first) { found = true; break; } } if (!found) { ret.push_back(mainpair); } } return ret; } AString cOverridesSettingsRepository::GetValue(const AString & a_KeyName, const AString & a_ValueName, const AString & defValue) const { if (m_Overrides->HasValue(a_KeyName, a_ValueName)) { return m_Overrides->GetValue(a_KeyName, a_ValueName, defValue); } else { return m_Main->GetValue(a_KeyName, a_ValueName, defValue); } } AString cOverridesSettingsRepository::GetValueSet (const AString & a_KeyName, const AString & a_ValueName, const AString & defValue) { if (m_Overrides->HasValue(a_KeyName, a_ValueName)) { return m_Overrides->GetValueSet(a_KeyName, a_ValueName, defValue); } else { return m_Main->GetValueSet(a_KeyName, a_ValueName, defValue); } } int cOverridesSettingsRepository::GetValueSetI(const AString & a_KeyName, const AString & a_ValueName, const int defValue) { if (m_Overrides->HasValue(a_KeyName, a_ValueName)) { return m_Overrides->GetValueSetI(a_KeyName, a_ValueName, defValue); } else { return m_Main->GetValueSetI(a_KeyName, a_ValueName, defValue); } } Int64 cOverridesSettingsRepository::GetValueSetI(const AString & a_KeyName, const AString & a_ValueName, const Int64 defValue) { if (m_Overrides->HasValue(a_KeyName, a_ValueName)) { return m_Overrides->GetValueSetI(a_KeyName, a_ValueName, defValue); } else { return m_Main->GetValueSetI(a_KeyName, a_ValueName, defValue); } } bool cOverridesSettingsRepository::GetValueSetB(const AString & a_KeyName, const AString & a_ValueName, const bool defValue) { if (m_Overrides->HasValue(a_KeyName, a_ValueName)) { return m_Overrides->GetValueSetB(a_KeyName, a_ValueName, defValue); } else { return m_Main->GetValueSetB(a_KeyName, a_ValueName, defValue); } } bool cOverridesSettingsRepository::SetValue (const AString & a_KeyName, const AString & a_ValueName, const AString & a_Value, const bool a_CreateIfNotExists) { if (m_Overrides->HasValue(a_KeyName, a_ValueName)) { return m_Overrides->SetValue(a_KeyName, a_ValueName, a_Value, a_CreateIfNotExists); } else { return m_Main->SetValue(a_KeyName, a_ValueName, a_Value, a_CreateIfNotExists); } } bool cOverridesSettingsRepository::SetValueI(const AString & a_KeyName, const AString & a_ValueName, const int a_Value, const bool a_CreateIfNotExists) { if (m_Overrides->HasValue(a_KeyName, a_ValueName)) { return m_Overrides->SetValueI(a_KeyName, a_ValueName, a_Value, a_CreateIfNotExists); } else { return m_Main->SetValueI(a_KeyName, a_ValueName, a_Value, a_CreateIfNotExists); } } bool cOverridesSettingsRepository::DeleteValue(const AString & a_KeyName, const AString & a_ValueName) { if (m_Overrides->HasValue(a_KeyName, a_ValueName)) { return m_Overrides->DeleteValue(a_KeyName, a_ValueName); } else { return m_Main->DeleteValue(a_KeyName, a_ValueName); } } bool cOverridesSettingsRepository::Flush() { return m_Overrides->Flush() && m_Main->Flush(); } ================================================ FILE: src/OverridesSettingsRepository.h ================================================ #pragma once #include "SettingsRepositoryInterface.h" class cOverridesSettingsRepository : public cSettingsRepositoryInterface { public: cOverridesSettingsRepository(std::unique_ptr a_Main, cSettingsRepositoryInterface & a_Overrides); virtual ~cOverridesSettingsRepository() override = default; virtual bool KeyExists(const AString keyname) const override; virtual bool HasValue(const AString & a_KeyName, const AString & a_ValueName) const override; virtual int AddKeyName(const AString & keyname) override; virtual bool AddKeyComment(const AString & keyname, const AString & comment) override; virtual AString GetKeyComment(const AString & keyname, const int commentID) const override; virtual bool DeleteKeyComment(const AString & keyname, const int commentID) override; virtual void AddValue (const AString & a_KeyName, const AString & a_ValueName, const AString & a_Value) override; virtual std::vector> GetValues(AString a_keyName) override; virtual AString GetValue (const AString & keyname, const AString & valuename, const AString & defValue = "") const override; virtual AString GetValueSet (const AString & keyname, const AString & valuename, const AString & defValue = "") override; virtual int GetValueSetI(const AString & keyname, const AString & valuename, const int defValue = 0) override; virtual Int64 GetValueSetI(const AString & keyname, const AString & valuename, const Int64 defValue = 0) override; virtual bool GetValueSetB(const AString & keyname, const AString & valuename, const bool defValue = false) override; virtual bool SetValue (const AString & a_KeyName, const AString & a_ValueName, const AString & a_Value, const bool a_CreateIfNotExists = true) override; virtual bool SetValueI(const AString & a_KeyName, const AString & a_ValueName, const int a_Value, const bool a_CreateIfNotExists = true) override; virtual bool DeleteValue(const AString & keyname, const AString & valuename) override; virtual bool Flush() override; private: std::unique_ptr m_Main; cSettingsRepositoryInterface * m_Overrides; }; ================================================ FILE: src/PalettedBlockArea.cpp ================================================ #include "Globals.h" #include "PalettedBlockArea.h" PalettedBlockArea::PalettedBlockArea() { // Nothing needed yet } PalettedBlockArea PalettedBlockArea::createFilled(Vector3i aSize, const AString & aBlockTypeName, const BlockState & aBlockState) { ASSERT(aSize.x > 0); ASSERT(aSize.y > 0); ASSERT(aSize.z > 0); PalettedBlockArea res; auto numBlocks = static_cast(aSize.x) * static_cast(aSize.y) * static_cast(aSize.z); if (numBlocks >= std::numeric_limits::max()) { // We use 32-bit indices in some functions (for ARM speed), so we need the entire area to fit into UInt32 throw std::runtime_error("Size is too large"); } res.mSize = aSize; res.mBlocks.resize(static_cast(numBlocks)); res.fill(aBlockTypeName, aBlockState); return res; } cCuboid PalettedBlockArea::whole() const { return cCuboid(Vector3i(), mSize); } void PalettedBlockArea::setBlock(Vector3i aPos, const AString & aBlockTypeName, const BlockState & aBlockState) { setBlock(aPos, paletteIndex(aBlockTypeName, aBlockState)); } void PalettedBlockArea::setBlock(Vector3i aPos, UInt32 aPaletteIndex) { ASSERT(isPositionValid(aPos)); ASSERT(aPaletteIndex < mPalette.count()); auto idx = positionToIndex(aPos); mBlocks[idx] = aPaletteIndex; } UInt32 PalettedBlockArea::paletteIndex(const AString & aBlockTypeName, const BlockState & aBlockState) { return mPalette.index(aBlockTypeName, aBlockState); } std::pair PalettedBlockArea::maybePaletteIndex(const AString & aBlockTypeName, const BlockState & aBlockState) const { return mPalette.maybeIndex(aBlockTypeName, aBlockState); } UInt32 PalettedBlockArea::blockPaletteIndex(Vector3i aPos) const { auto idx = positionToIndex(aPos); return mBlocks[idx]; } const std::pair & PalettedBlockArea::block(Vector3i aPos) const { return paletteEntry(blockPaletteIndex(aPos)); } const std::pair & PalettedBlockArea::paletteEntry(UInt32 aPaletteIndex) const { return mPalette.entry(aPaletteIndex); } bool PalettedBlockArea::isPositionValid(Vector3i aPos) const { return ( (aPos.x >= 0) && (aPos.y >= 0) && (aPos.z >= 0) && // Non-negative coords (aPos.x < mSize.x) && (aPos.y < mSize.y) && (aPos.z < mSize.z) // Fit into size ); } void PalettedBlockArea::fill(const AString & aBlockTypeName, const BlockState & aBlockState) { BlockTypePalette btp; auto idx = btp.index(aBlockTypeName, aBlockState); std::swap(mPalette, btp); std::fill(mBlocks.begin(), mBlocks.end(), idx); } void PalettedBlockArea::paste(const PalettedBlockArea & aSrc, const cCuboid & aSrcCuboid, Vector3i aDstOrigin) { // Clamp the src cuboid, first by src itself, then by this PBA's coord range: cCuboid srcCuboid(aSrcCuboid); srcCuboid.Sort(); srcCuboid.Clamp(aSrc.whole()); Vector3i maxSize = mSize - aDstOrigin; srcCuboid.ClampSize(maxSize); Vector3i dstOrigin(aDstOrigin); // If any aDstOrigin coord is lower than 0, adjust the coord and src cuboid size: if (dstOrigin.x < 0) { srcCuboid.p1.x -= dstOrigin.x; if (srcCuboid.p1.x >= srcCuboid.p2.x) { return; } dstOrigin.x = 0; } if (dstOrigin.y < 0) { srcCuboid.p1.y -= dstOrigin.y; if (srcCuboid.p1.y >= srcCuboid.p2.y) { return; } dstOrigin.y = 0; } if (dstOrigin.z < 0) { srcCuboid.p1.z -= dstOrigin.z; if (srcCuboid.p1.z >= srcCuboid.p2.z) { return; } dstOrigin.z = 0; } // Create a transform map from aSrc's palette to our palette: auto paletteTransform = mPalette.createTransformMapAddMissing(aSrc.mPalette); // Copy the data: UInt32 srcStrideY = static_cast(aSrc.size().x * aSrc.size().z); UInt32 srcStrideZ = static_cast(aSrc.size().x); UInt32 dstStrideY = static_cast(mSize.x * mSize.z); UInt32 dstStrideZ = static_cast(mSize.x); UInt32 minX = static_cast(srcCuboid.p1.x); UInt32 maxX = static_cast(srcCuboid.p2.x); UInt32 minY = static_cast(srcCuboid.p1.y); UInt32 maxY = static_cast(srcCuboid.p2.y); UInt32 minZ = static_cast(srcCuboid.p1.z); UInt32 maxZ = static_cast(srcCuboid.p2.z); UInt32 dstX = static_cast(dstOrigin.x); UInt32 dstY = static_cast(dstOrigin.y); UInt32 dstZ = static_cast(dstOrigin.z); for (UInt32 y = minY; y < maxY; ++y) { UInt32 srcOfsY = y * srcStrideY; UInt32 dstOfsY = (y - minY + dstY) * dstStrideY; for (UInt32 z = minZ; z < maxZ; ++z) { UInt32 srcOfs = srcOfsY + z * srcStrideZ + minX; UInt32 dstOfs = dstOfsY + (z - minZ + dstZ) * dstStrideZ + dstX; for (UInt32 x = minX; x < maxX; ++x) { mBlocks[dstOfs] = paletteTransform[aSrc.mBlocks[srcOfs]]; srcOfs += 1; dstOfs += 1; } } } } void PalettedBlockArea::crop(const cCuboid & aArea) { cCuboid area(aArea); area.Clamp(whole()); // Copy the data: UInt32 srcStrideY = static_cast(size().x * size().z); UInt32 srcStrideZ = static_cast(size().x); UInt32 dstStrideY = static_cast(area.DifX() * area.DifZ()); UInt32 dstStrideZ = static_cast(area.DifZ()); UInt32 minX = static_cast(area.p1.x); UInt32 maxX = static_cast(area.p2.x); UInt32 minY = static_cast(area.p1.y); UInt32 maxY = static_cast(area.p2.y); UInt32 minZ = static_cast(area.p1.z); UInt32 maxZ = static_cast(area.p2.z); for (UInt32 y = minY; y < maxY; ++y) { UInt32 srcOfsY = (y - minY) * srcStrideY; UInt32 dstOfsY = y * dstStrideY; for (UInt32 z = minZ; z < maxZ; ++z) { UInt32 srcOfs = srcOfsY + (z - minZ) * srcStrideZ + minX; UInt32 dstOfs = dstOfsY + z * dstStrideZ; for (UInt32 x = minX; x < maxX; ++x) { mBlocks[dstOfs] = mBlocks[srcOfs]; srcOfs += 1; dstOfs += 1; } } } } UInt32 PalettedBlockArea::positionToIndex(Vector3i aPos) const { ASSERT(isPositionValid(aPos)); return static_cast(aPos.x + aPos.z * mSize.x + aPos.y * mSize.x * mSize.z); } ================================================ FILE: src/PalettedBlockArea.h ================================================ #pragma once #include #include "Bindings/BlockTypePalette.h" #include "Cuboid.h" /** Represents an area of blocks that are represented using a palette. The object itself provides no thread safety, users of this class need to handle locking, if required. The PalettedBlockArea always contains Blocks and their associated BlockEntities, it may optionally contain Entities. There's no way to instantiate this class directly, you need to use either createFilled(), or read from cWorld. */ class PalettedBlockArea { public: /** Creates a new PBA of the specified size filled with the specified block. Throws if there is an error (memory allocation etc.) */ static PalettedBlockArea createFilled(Vector3i aSize, const AString & aBlockTypeName, const BlockState & aBlockState); /** Returns the actual size of the area in all 3 axes. */ const Vector3i & size() const { return mSize; } /** Returns a cCuboid that encompasses the entire PBA. Technically, {0, 0, 0} to mSize. */ cCuboid whole() const; /** Sets a single block using its full blockspec. The position must be valid (ASSERTed). If the block is not already in palette, it is added. */ void setBlock(Vector3i aPos, const AString & aBlockTypeName, const BlockState & aBlockState); /** Sets a single block using an index to the palette (retrieved earlier by paletteIndex()). The position must be valid (ASSERTed). The palette index must be valid (ASSERTed). */ void setBlock(Vector3i aPos, UInt32 aPaletteIndex); /** Returns the index into the palette that is used by the specified full blockspec. Adds the blockspec to palette if not already there. */ UInt32 paletteIndex(const AString & aBlockTypeName, const BlockState & aBlockState); /** Returns the into the palette that is used by the specified full blockspec. Returns if blockspec not in palette. */ std::pair maybePaletteIndex(const AString & aBlockTypeName, const BlockState & aBlockState) const; /** Returns the index into the palette for the block at the specified pos. The position must be valid (ASSERTed). */ UInt32 blockPaletteIndex(Vector3i aPos) const; /** Returns the full blockspec of the block at the specified position. The position must be valid (ASSERTed). */ const std::pair & block(Vector3i aPos) const; /** Returns the blockspec represented by the specified palette index. The index must be valid (ASSERTed). */ const std::pair & paletteEntry(UInt32 aPaletteIndex) const; /** Returns true if the specified position is within the size bounds of the area. */ bool isPositionValid(Vector3i aPos) const; /** Fills the entire PBA with a single block of the specified type. The palette is reset to one containing only the single block. */ void fill(const AString & aBlockTypeName, const BlockState & aBlockState); /** Pastes (copies verbatim) a cCuboid out of the src PBA into this PBA. aSrcCuboid is the coord range in aSrc that will be copied (min-coord is inclusive, max-coord is exclusive). aDstOrigin is the coord relative to this PBA where the lowest coords of the copied area will be put. aDstOrigin can be outside of this PBA's coord range (only part of the src is copied). Automatically crops aSrcCuboid so that the copied part is entirely inside this PBA's coord range. */ void paste(const PalettedBlockArea & aSrc, const cCuboid & aSrcCuboid, Vector3i aDstOrigin = Vector3i()); /** Pastes (copies verbatim) the entire src PBA into this PBA. aDstOrigin is the coord relative to this PBA where the lowest coords of the copied area will be put. aDstOrigin can be outside of this PBA's coord range (only part of the src is copied). Gracefully handles situations where the copied src PBA goes outside of this PBA's coord range. */ inline void paste(const PalettedBlockArea & aSrc, Vector3i aDstOrigin = Vector3i()) { paste(aSrc, aSrc.whole(), aDstOrigin); } /** Crops this PBA by the specified coords. aArea is first cropped to the size of this PBA (so it's only possible to shrink a PBA, not enlarge). */ void crop(const cCuboid & aArea); /** Returns the (reqd-only) palette used internally by this object. */ const BlockTypePalette & palette() { return mPalette; } protected: /** The palette used in the area. */ BlockTypePalette mPalette; /** The blocks contained in the area, stored as indices into mPalette. */ std::vector mBlocks; /** The size (dimensions) of the area. */ Vector3i mSize; /** Creates a new uninitialized instance (all sizes zero). */ PalettedBlockArea(); /** Converts the position to index in mBlocks. This may be removed later on when optimizing the RAM usage of this class by compressing low-palette-count PBAs. */ UInt32 positionToIndex(Vector3i aPos) const; }; ================================================ FILE: src/Physics/CMakeLists.txt ================================================ target_sources( ${CMAKE_PROJECT_NAME} PRIVATE Explodinator.cpp # Lightning.cpp Explodinator.h # Lightning.h ) ================================================ FILE: src/Physics/Explodinator.cpp ================================================ #include "Globals.h" #include "BlockInfo.h" #include "Explodinator.h" #include "Blocks/BlockHandler.h" #include "Blocks/ChunkInterface.h" #include "Chunk.h" #include "ClientHandle.h" #include "Entities/FallingBlock.h" #include "LineBlockTracer.h" #include "Simulator/SandSimulator.h" namespace Explodinator { static const auto StepUnit = 0.3f; static const auto KnockbackFactor = 25U; static const auto StepAttenuation = 0.225f; static const auto TraceCubeSideLength = 16U; static const auto BoundingBoxStepUnit = 0.5; /** Converts an absolute floating-point Position into a Chunk-relative one. */ static Vector3f AbsoluteToRelative(const Vector3f a_Position, const cChunkCoords a_ChunkPosition) { return { a_Position.x - a_ChunkPosition.m_ChunkX * cChunkDef::Width, a_Position.y, a_Position.z - a_ChunkPosition.m_ChunkZ * cChunkDef::Width }; } /** Make a From Chunk-relative Position into a To Chunk-relative position. */ static Vector3f RebaseRelativePosition(const cChunkCoords a_From, const cChunkCoords a_To, const Vector3f a_Position) { return { a_Position.x + (a_From.m_ChunkX - a_To.m_ChunkX) * cChunkDef::Width, a_Position.y, a_Position.z + (a_From.m_ChunkZ - a_To.m_ChunkZ) * cChunkDef::Width }; } /** Returns how much of an explosion Destruction Lazor's (tm) intensity the given block attenuates. Values are scaled as 0.3 * (0.3 + Wiki) since some compilers miss the constant folding optimisation. Wiki values are https://minecraft.wiki/w/Explosion#Blast_resistance as of 2021-02-06. */ static float GetExplosionAbsorption(const BLOCKTYPE Block) { switch (Block) { case E_BLOCK_BEDROCK: case E_BLOCK_COMMAND_BLOCK: case E_BLOCK_END_GATEWAY: case E_BLOCK_END_PORTAL: case E_BLOCK_END_PORTAL_FRAME: return 1080000.09f; case E_BLOCK_ANVIL: case E_BLOCK_ENCHANTMENT_TABLE: case E_BLOCK_OBSIDIAN: return 360.09f; case E_BLOCK_ENDER_CHEST: return 180.09f; case E_BLOCK_LAVA: case E_BLOCK_STATIONARY_LAVA: case E_BLOCK_WATER: case E_BLOCK_STATIONARY_WATER: return 30.09f; case E_BLOCK_DRAGON_EGG: case E_BLOCK_END_STONE: case E_BLOCK_END_BRICKS: return 2.79f; case E_BLOCK_STONE: case E_BLOCK_BLOCK_OF_COAL: case E_BLOCK_DIAMOND_BLOCK: case E_BLOCK_EMERALD_BLOCK: case E_BLOCK_GOLD_BLOCK: case E_BLOCK_IRON_BLOCK: case E_BLOCK_BLOCK_OF_REDSTONE: case E_BLOCK_BRICK: case E_BLOCK_BRICK_STAIRS: case E_BLOCK_COBBLESTONE: case E_BLOCK_COBBLESTONE_STAIRS: case E_BLOCK_IRON_BARS: case E_BLOCK_JUKEBOX: case E_BLOCK_MOSSY_COBBLESTONE: case E_BLOCK_NETHER_BRICK: case E_BLOCK_NETHER_BRICK_FENCE: case E_BLOCK_NETHER_BRICK_STAIRS: case E_BLOCK_PRISMARINE_BLOCK: case E_BLOCK_STONE_BRICKS: case E_BLOCK_STONE_BRICK_STAIRS: case E_BLOCK_COBBLESTONE_WALL: return 1.89f; case E_BLOCK_IRON_DOOR: case E_BLOCK_IRON_TRAPDOOR: case E_BLOCK_MOB_SPAWNER: return 1.59f; case E_BLOCK_HOPPER: return 1.53f; case E_BLOCK_TERRACOTTA: return 1.35f; case E_BLOCK_COBWEB: return 1.29f; case E_BLOCK_DISPENSER: case E_BLOCK_DROPPER: case E_BLOCK_FURNACE: case E_BLOCK_OBSERVER: return 1.14f; case E_BLOCK_BEACON: case E_BLOCK_COAL_ORE: case E_BLOCK_COCOA_POD: case E_BLOCK_DIAMOND_ORE: case E_BLOCK_EMERALD_ORE: case E_BLOCK_GOLD_ORE: case E_BLOCK_IRON_ORE: case E_BLOCK_LAPIS_BLOCK: case E_BLOCK_LAPIS_ORE: case E_BLOCK_NETHER_QUARTZ_ORE: case E_BLOCK_PLANKS: case E_BLOCK_REDSTONE_ORE: case E_BLOCK_FENCE: case E_BLOCK_FENCE_GATE: case E_BLOCK_WOODEN_DOOR: case E_BLOCK_WOODEN_SLAB: case E_BLOCK_WOODEN_STAIRS: case E_BLOCK_TRAPDOOR: return 0.99f; case E_BLOCK_CHEST: case E_BLOCK_WORKBENCH: case E_BLOCK_TRAPPED_CHEST: return 0.84f; case E_BLOCK_BONE_BLOCK: case E_BLOCK_CAULDRON: case E_BLOCK_LOG: return 0.69f; // nIcE case E_BLOCK_CONCRETE: return 0.63f; case E_BLOCK_BOOKCASE: return 0.54f; case E_BLOCK_STANDING_BANNER: case E_BLOCK_WALL_BANNER: case E_BLOCK_JACK_O_LANTERN: case E_BLOCK_MELON: case E_BLOCK_HEAD: case E_BLOCK_NETHER_WART_BLOCK: case E_BLOCK_PUMPKIN: case E_BLOCK_SIGN_POST: case E_BLOCK_WALLSIGN: return 0.39f; case E_BLOCK_QUARTZ_BLOCK: case E_BLOCK_QUARTZ_STAIRS: case E_BLOCK_RED_SANDSTONE: case E_BLOCK_RED_SANDSTONE_STAIRS: case E_BLOCK_SANDSTONE: case E_BLOCK_SANDSTONE_STAIRS: case E_BLOCK_WOOL: return 0.33f; case E_BLOCK_SILVERFISH_EGG: return 0.315f; case E_BLOCK_ACTIVATOR_RAIL: case E_BLOCK_DETECTOR_RAIL: case E_BLOCK_POWERED_RAIL: case E_BLOCK_RAIL: return 0.3f; case E_BLOCK_GRASS_PATH: case E_BLOCK_CLAY: case E_BLOCK_FARMLAND: case E_BLOCK_GRASS: case E_BLOCK_GRAVEL: case E_BLOCK_SPONGE: return 0.27f; case E_BLOCK_BREWING_STAND: case E_BLOCK_STONE_BUTTON: case E_BLOCK_WOODEN_BUTTON: case E_BLOCK_CAKE: case E_BLOCK_CONCRETE_POWDER: case E_BLOCK_DIRT: case E_BLOCK_FROSTED_ICE: case E_BLOCK_HAY_BALE: case E_BLOCK_ICE: return 0.24f; default: return 0.09f; } } /** Calculates the approximate percentage of an Entity's bounding box that is exposed to an explosion centred at Position. */ static float CalculateEntityExposure(const cChunk & a_Chunk, const cEntity & a_Entity, const Vector3f a_Position, const int a_SquareRadius) { class LineOfSightCallbacks final : public cLineBlockTracer::cCallbacks { virtual bool OnNextBlock(Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, eBlockFace a_EntryFace) override { return a_BlockType != E_BLOCK_AIR; } } Callback; const Vector3d Position = a_Position; unsigned Unobstructed = 0, Total = 0; const auto Box = a_Entity.GetBoundingBox(); cLineBlockTracer Tracer(*a_Chunk.GetWorld(), Callback); for (double X = Box.GetMinX(); X < Box.GetMaxX(); X += BoundingBoxStepUnit) { for (double Y = Box.GetMinY(); Y < Box.GetMaxY(); Y += BoundingBoxStepUnit) { for (double Z = Box.GetMinZ(); Z < Box.GetMaxZ(); Z += BoundingBoxStepUnit) { const Vector3d Destination{X, Y, Z}; if ((Destination - Position).SqrLength() > a_SquareRadius) { // Don't bother with points outside our designated area-of-effect // This is, surprisingly, a massive amount of work saved (~3m to detonate a sphere of 37k TNT before, ~1m after): continue; } if (Tracer.Trace(a_Position, Destination)) { Unobstructed++; } Total++; } } } return (Total == 0) ? 0 : (static_cast(Unobstructed) / Total); } /** Applies distance-based damage and knockback to all entities within the explosion's effect range. */ static void DamageEntities(const cChunk & a_Chunk, const Vector3f a_Position, const int a_Power) { const auto Radius = a_Power * 2; const auto SquareRadius = Radius * Radius; a_Chunk.GetWorld()->ForEachEntityInBox({ a_Position, Radius * 2.f }, [&a_Chunk, a_Position, a_Power, Radius, SquareRadius](cEntity & Entity) { // Percentage of rays unobstructed. const auto Exposure = CalculateEntityExposure(a_Chunk, Entity, a_Position, SquareRadius); const auto Direction = Entity.GetPosition() - a_Position; const auto Impact = (1 - (static_cast(Direction.Length()) / Radius)) * Exposure; // Don't apply damage to other TNT entities and falling blocks, they should be invincible: if (!Entity.IsTNT() && !Entity.IsFallingBlock()) { const auto Damage = (Impact * Impact + Impact) * 7 * a_Power + 1; Entity.TakeDamage(dtExplosion, nullptr, FloorC(Damage), 0); } // Impact reduced by armour, expensive call so only apply to Pawns: if (Entity.IsPawn()) { const auto ReducedImpact = Impact - Impact * Entity.GetEnchantmentBlastKnockbackReduction(); Entity.AddSpeed(Direction.NormalizeCopy() * KnockbackFactor * ReducedImpact); } else { Entity.AddSpeed(Direction.NormalizeCopy() * KnockbackFactor * Impact); } // Continue iteration: return false; }); } /** Returns true if block should always drop when exploded. Currently missing conduits from 1.13 */ static bool BlockAlwaysDrops(const BLOCKTYPE a_Block) { if (IsBlockShulkerBox(a_Block)) { return true; } switch (a_Block) { case E_BLOCK_DRAGON_EGG: case E_BLOCK_BEACON: case E_BLOCK_HEAD: return true; } return false; } /** Sets the block at the given position, updating surroundings. */ static void SetBlock(cWorld & a_World, cChunk & a_Chunk, const Vector3i a_AbsolutePosition, const Vector3i a_RelativePosition, const BLOCKTYPE a_DestroyedBlock, const BLOCKTYPE a_NewBlock, const cEntity * const a_ExplodingEntity) { const auto DestroyedMeta = a_Chunk.GetMeta(a_RelativePosition); // SetBlock wakes up all simulators for the area, so that water and lava flows and sand falls into the blasted holes // It also is responsible for calling cBlockHandler::OnNeighborChanged to pop off blocks that fail CanBeAt // An explicit call to cBlockHandler::OnBroken handles the destruction of multiblock structures // References at (FS #391, GH #4418): a_Chunk.SetBlock(a_RelativePosition, a_NewBlock, 0); cChunkInterface Interface(a_World.GetChunkMap()); cBlockHandler::For(a_DestroyedBlock).OnBroken(Interface, a_World, a_AbsolutePosition, a_DestroyedBlock, DestroyedMeta, a_ExplodingEntity); } /** Work out what should happen when an explosion destroys the given block. Tasks include lighting TNT, dropping pickups, setting fire and flinging shrapnel according to Minecraft rules. OK, _mostly_ Minecraft rules. */ static void DestroyBlock(cChunk & a_Chunk, const Vector3i a_Position, const int a_Power, const bool a_Fiery, const cEntity * const a_ExplodingEntity) { const auto DestroyedBlock = a_Chunk.GetBlock(a_Position); if (DestroyedBlock == E_BLOCK_AIR) { // There's nothing left for us here, but a barren and empty land // Let's go. return; } auto & World = *a_Chunk.GetWorld(); auto & Random = GetRandomProvider(); const auto Absolute = cChunkDef::RelativeToAbsolute(a_Position, a_Chunk.GetPos()); if (DestroyedBlock == E_BLOCK_TNT) // If the block is TNT we should set it off { // Random fuse between 10 to 30 game ticks. const int FuseTime = Random.RandInt(10, 30); // Activate the TNT, with initial velocity and no fuse sound: World.SpawnPrimedTNT(Vector3d(0.5, 0, 0.5) + Absolute, FuseTime, 1, false); } else if ((a_ExplodingEntity != nullptr) && (a_ExplodingEntity->IsTNT() || BlockAlwaysDrops(DestroyedBlock) || Random.RandBool(1.f / a_Power))) // For TNT explosions, destroying a block that always drops, or if RandBool, drop pickups { const auto DestroyedMeta = a_Chunk.GetMeta(a_Position); a_Chunk.GetWorld()->SpawnItemPickups(cBlockHandler::For(DestroyedBlock).ConvertToPickups(DestroyedMeta), Absolute); } else if (a_Fiery && Random.RandBool(1 / 3.0)) // 33% chance of starting fires if it can start fires { const auto Below = a_Position.addedY(-1); if ((Below.y >= 0) && cBlockInfo::FullyOccupiesVoxel(a_Chunk.GetBlock(Below))) { // Start a fire: SetBlock(World, a_Chunk, Absolute, a_Position, DestroyedBlock, E_BLOCK_FIRE, a_ExplodingEntity); return; } } else if (const auto Shrapnel = World.GetTNTShrapnelLevel(); (Shrapnel > slNone) && Random.RandBool(0)) // Currently 0% chance of flinging stuff around { // If the block is shrapnel-able, make a falling block entity out of it: if ( ((Shrapnel == slAll) && cBlockInfo::FullyOccupiesVoxel(DestroyedBlock)) || ((Shrapnel == slGravityAffectedOnly) && cSandSimulator::IsAllowedBlock(DestroyedBlock)) ) { const auto DestroyedMeta = a_Chunk.GetMeta(a_Position); auto FallingBlock = std::make_unique(Vector3d(0.5, 0, 0.5) + Absolute, DestroyedBlock, DestroyedMeta); // TODO: correct velocity FallingBlock->SetSpeedY(40); FallingBlock->Initialize(std::move(FallingBlock), World); } } SetBlock(World, a_Chunk, Absolute, a_Position, DestroyedBlock, E_BLOCK_AIR, a_ExplodingEntity); } /** Traces the path taken by one Explosion Lazor (tm) with given direction and intensity, that will destroy blocks until it is exhausted. */ static void DestructionTrace(cChunk * a_Chunk, Vector3f a_Origin, const Vector3f a_Direction, const int a_Power, const bool a_Fiery, float a_Intensity, const cEntity * const a_ExplodingEntity) { // The current position the ray is at. auto Checkpoint = a_Origin; // The displacement that the ray in one iteration step should travel. const auto Step = a_Direction.NormalizeCopy() * StepUnit; // Loop until intensity runs out: while (a_Intensity > 0) { auto Position = Checkpoint.Floor(); if (!cChunkDef::IsValidHeight(Position)) { break; } const auto Neighbour = a_Chunk->GetRelNeighborChunkAdjustCoords(Position); if ((Neighbour == nullptr) || !Neighbour->IsValid()) { break; } a_Intensity -= GetExplosionAbsorption(Neighbour->GetBlock(Position)); if (a_Intensity <= 0) { // The ray is exhausted: break; } DestroyBlock(*Neighbour, Position, a_Power, a_Fiery, a_ExplodingEntity); // Adjust coordinates to be relative to the neighbour chunk: Checkpoint = RebaseRelativePosition(a_Chunk->GetPos(), Neighbour->GetPos(), Checkpoint); a_Origin = RebaseRelativePosition(a_Chunk->GetPos(), Neighbour->GetPos(), a_Origin); a_Chunk = Neighbour; // Increment the simulation, weaken the ray: Checkpoint += Step; a_Intensity -= StepAttenuation; } } /** Returns a random intensity for an Explosion Lazor (tm) as a function of the explosion's power. */ static float RandomIntensity(MTRand & a_Random, const int a_Power) { return a_Power * (0.7f + a_Random.RandReal(0.6f)); } /** Sends out Explosion Lazors (tm) originating from the given position that destroy blocks. */ static void DamageBlocks(cChunk & a_Chunk, const Vector3f a_Position, const int a_Power, const bool a_Fiery, const cEntity * const a_ExplodingEntity) { // Oh boy... Better hope you have a hot cache, 'cos this little manoeuvre's gonna cost us 1352 raytraces in one tick... const int HalfSide = TraceCubeSideLength / 2; auto & Random = GetRandomProvider(); // The following loops implement the tracing algorithm described in http://minecraft.wiki/w/Explosion // Trace rays from the explosion centre to all points in a square of area TraceCubeSideLength * TraceCubeSideLength // for the top and bottom sides: for (float OffsetX = -HalfSide; OffsetX < HalfSide; OffsetX++) { for (float OffsetZ = -HalfSide; OffsetZ < HalfSide; OffsetZ++) { DestructionTrace(&a_Chunk, a_Position, Vector3f(OffsetX, +HalfSide, OffsetZ), a_Power, a_Fiery, RandomIntensity(Random, a_Power), a_ExplodingEntity); DestructionTrace(&a_Chunk, a_Position, Vector3f(OffsetX, -HalfSide, OffsetZ), a_Power, a_Fiery, RandomIntensity(Random, a_Power), a_ExplodingEntity); } } // Left and right sides, avoid duplicates at top and bottom edges: for (float OffsetX = -HalfSide; OffsetX < HalfSide; OffsetX++) { for (float OffsetY = -HalfSide + 1; OffsetY < HalfSide - 1; OffsetY++) { DestructionTrace(&a_Chunk, a_Position, Vector3f(OffsetX, OffsetY, +HalfSide), a_Power, a_Fiery, RandomIntensity(Random, a_Power), a_ExplodingEntity); DestructionTrace(&a_Chunk, a_Position, Vector3f(OffsetX, OffsetY, -HalfSide), a_Power, a_Fiery, RandomIntensity(Random, a_Power), a_ExplodingEntity); } } // Front and back sides, avoid all edges: for (float OffsetZ = -HalfSide + 1; OffsetZ < HalfSide - 1; OffsetZ++) { for (float OffsetY = -HalfSide + 1; OffsetY < HalfSide - 1; OffsetY++) { DestructionTrace(&a_Chunk, a_Position, Vector3f(+HalfSide, OffsetY, OffsetZ), a_Power, a_Fiery, RandomIntensity(Random, a_Power), a_ExplodingEntity); DestructionTrace(&a_Chunk, a_Position, Vector3f(-HalfSide, OffsetY, OffsetZ), a_Power, a_Fiery, RandomIntensity(Random, a_Power), a_ExplodingEntity); } } } /** Sends an explosion packet to all clients in the given chunk. */ static void LagTheClient(cChunk & a_Chunk, const Vector3f a_Position, const int a_Power) { for (const auto Client : a_Chunk.GetAllClients()) { Client->SendExplosion(a_Position, static_cast(a_Power)); } } void Kaboom(cWorld & a_World, const Vector3f a_Position, const int a_Power, const bool a_Fiery, const cEntity * const a_ExplodingEntity) { a_World.DoWithChunkAt(a_Position.Floor(), [a_Position, a_Power, a_Fiery, a_ExplodingEntity](cChunk & a_Chunk) { LagTheClient(a_Chunk, a_Position, a_Power); DamageEntities(a_Chunk, a_Position, a_Power); DamageBlocks(a_Chunk, AbsoluteToRelative(a_Position, a_Chunk.GetPos()), a_Power, a_Fiery, a_ExplodingEntity); return false; }); } } ================================================ FILE: src/Physics/Explodinator.h ================================================ #pragma once class cEntity; class cWorld; namespace Explodinator { /** Creates an explosion of Power, centred at Position, with ability to set fires as provided. For maximum efficiency, Position should be in the centre of the entity or block that exploded. The entity pointer is used to trigger OnBreak for the destroyed blocks. Kaboom indeed, you drunken wretch. */ void Kaboom(cWorld & World, Vector3f Position, int Power, bool Fiery, const cEntity * a_ExplodingEntity); } ================================================ FILE: src/ProbabDistrib.cpp ================================================ // ProbabDistrib.cpp // Implements the cProbabDistrib class representing a discrete probability distribution curve and random generator #include "Globals.h" #include "ProbabDistrib.h" cProbabDistrib::cProbabDistrib(int a_MaxValue) : m_MaxValue(a_MaxValue), m_Sum(-1) { } void cProbabDistrib::SetPoints(const cProbabDistrib::cPoints & a_Points) { ASSERT(!a_Points.empty()); m_Sum = 0; m_Cumulative.clear(); m_Cumulative.reserve(a_Points.size() + 1); int ProbSum = 0; int LastProb = 0; int LastValue = -1; if (a_Points[0].m_Value != 0) { m_Cumulative.emplace_back(0, 0); // Always push in the [0, 0] point for easier search algorithm bounds LastValue = 0; } for (cPoints::const_iterator itr = a_Points.begin(), end = a_Points.end(); itr != end; ++itr) { if (itr->m_Value == LastValue) { continue; } // Add the current trapezoid to the sum: ProbSum += (LastProb + itr->m_Probability) * (itr->m_Value - LastValue) / 2; LastProb = itr->m_Probability; LastValue = itr->m_Value; m_Cumulative.emplace_back(itr->m_Value, ProbSum); } // for itr - a_Points[] if (LastValue != m_MaxValue) { m_Cumulative.emplace_back(m_MaxValue, 0); // Always push in the last point for easier search algorithm bounds } m_Sum = ProbSum; } bool cProbabDistrib::SetDefString(const AString & a_DefString) { AStringVector Points = StringSplitAndTrim(a_DefString, ";"); if (Points.empty()) { return false; } cPoints Pts; for (AStringVector::const_iterator itr = Points.begin(), end = Points.end(); itr != end; ++itr) { AStringVector Split = StringSplitAndTrim(*itr, ","); if (Split.size() != 2) { // Bad format return false; } int Value = atoi(Split[0].c_str()); int Prob = atoi(Split[1].c_str()); if ( ((Value == 0) && (Split[0] != "0")) || ((Prob == 0) && (Split[1] != "0")) ) { // Number parse error return false; } Pts.emplace_back(Value, Prob); } // for itr - Points[] SetPoints(Pts); return true; } int cProbabDistrib::Random(MTRand & a_Rand) const { return MapValue(a_Rand.RandInt(m_Sum)); } int cProbabDistrib::MapValue(int a_OrigValue) const { ASSERT(a_OrigValue >= 0); ASSERT(a_OrigValue < m_Sum); // Binary search through m_Cumulative for placement: size_t Lo = 0; size_t Hi = m_Cumulative.size() - 1; while (Hi - Lo > 1) { size_t Mid = (Lo + Hi) / 2; int MidProbab = m_Cumulative[Mid].m_Probability; if (MidProbab < a_OrigValue) { Lo = Mid; } else { Hi = Mid; } } ASSERT(Hi - Lo == 1); // Linearly interpolate between Lo and Hi: int ProbDif = m_Cumulative[Hi].m_Probability - m_Cumulative[Lo].m_Probability; ProbDif = (ProbDif != 0) ? ProbDif : 1; int ValueDif = m_Cumulative[Hi].m_Value - m_Cumulative[Lo].m_Value; return m_Cumulative[Lo].m_Value + (a_OrigValue - m_Cumulative[Lo].m_Probability) * ValueDif / ProbDif; } ================================================ FILE: src/ProbabDistrib.h ================================================ // ProbabDistrib.h // Declares the cProbabDistrib class representing a discrete probability distribution curve and random generator /* Usage: 1, Create a cProbabDistrib instance 2, Initialize the distribution either programmatically, using the SetPoints() function, or using a definition string 3, Ask for random numbers in that probability distribution using the Random() function */ #pragma once #include "FastRandom.h" class cProbabDistrib { public: class cPoint { public: int m_Value; int m_Probability; cPoint(int a_Value, int a_Probability) : m_Value(a_Value), m_Probability(a_Probability) { } } ; typedef std::vector cPoints; cProbabDistrib(int a_MaxValue); /** Sets the distribution curve using an array of [value, probability] points, linearly interpolated. a_Points must not be empty. */ void SetPoints(const cPoints & a_Points); /** Sets the distribution curve using a definition string; returns true on successful parse */ bool SetDefString(const AString & a_DefString); /** Gets a random value from a_Rand, shapes it into the distribution curve and returns the value. */ int Random(MTRand & a_Rand) const; /** Maps value in range [0, m_Sum] into the range [0, m_MaxValue] using the stored probability */ int MapValue(int a_OrigValue) const; int GetSum(void) const { return m_Sum; } protected: int m_MaxValue; /** Cumulative probability of the values, sorted, for fast bsearch lookup */ cPoints m_Cumulative; /** Sum of all the probabilities across all values in the domain; -1 if not set */ int m_Sum; } ; ================================================ FILE: src/Protocol/Authenticator.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "Protocol/Authenticator.h" #include "ClientHandle.h" #include "HTTP/UrlClient.h" #include "HTTP/UrlParser.h" #include "IniFile.h" #include "JsonUtils.h" #include "json/json.h" #include "Protocol/MojangAPI.h" #include "Root.h" #include "Server.h" #include "UUID.h" constexpr char DEFAULT_AUTH_SERVER[] = "sessionserver.mojang.com"; constexpr char DEFAULT_AUTH_ADDRESS[] = "/session/minecraft/hasJoined?username=%USERNAME%&serverId=%SERVERID%"; cAuthenticator::cAuthenticator(void) : Super("Authenticator"), m_Server(DEFAULT_AUTH_SERVER), m_Address(DEFAULT_AUTH_ADDRESS), m_ShouldAuthenticate(true) { } cAuthenticator::~cAuthenticator() { Stop(); } void cAuthenticator::ReadSettings(cSettingsRepositoryInterface & a_Settings) { m_Server = a_Settings.GetValueSet ("Authentication", "Server", DEFAULT_AUTH_SERVER); m_Address = a_Settings.GetValueSet ("Authentication", "Address", DEFAULT_AUTH_ADDRESS); m_ShouldAuthenticate = a_Settings.GetValueSetB("Authentication", "Authenticate", true); // prepend https:// if missing constexpr std::string_view HttpPrefix = "http://"; constexpr std::string_view HttpsPrefix = "https://"; if ( (std::string_view(m_Server).substr(0, HttpPrefix.size()) != HttpPrefix) && (std::string_view(m_Server).substr(0, HttpsPrefix.size()) != HttpsPrefix) ) { m_Server = "https://" + m_Server; } { auto [IsSuccessful, ErrorMessage] = cUrlParser::Validate(m_Server); if (!IsSuccessful) { LOGWARNING("%s %d: Supplied invalid URL for configuration value [Authentication: Server]: \"%s\", using default! Error: %s", __FUNCTION__, __LINE__, m_Server.c_str(), ErrorMessage.c_str()); m_Server = DEFAULT_AUTH_SERVER; } } { auto [IsSuccessful, ErrorMessage] = cUrlParser::Validate(m_Server); if (!IsSuccessful) { LOGWARNING("%s %d: Supplied invalid URL for configuration value [Authentication: Address]: \"%s\", using default! Error: %s", __FUNCTION__, __LINE__, m_Address.c_str(), ErrorMessage.c_str()); m_Address = DEFAULT_AUTH_ADDRESS; } } } void cAuthenticator::Authenticate(int a_ClientID, const std::string_view a_Username, const std::string_view a_ServerHash) { if (!m_ShouldAuthenticate) { // An "authenticated" username, which is just what the client sent since auth is off. std::string OfflineUsername(a_Username); // A specially constructed UUID based wholly on the username. const auto OfflineUUID = cClientHandle::GenerateOfflineUUID(OfflineUsername); // "Authenticate" the user based on what little information we have: cRoot::Get()->GetServer()->AuthenticateUser(a_ClientID, std::move(OfflineUsername), OfflineUUID, Json::Value()); return; } cCSLock Lock(m_CS); m_Queue.emplace_back(a_ClientID, a_Username, a_ServerHash); m_QueueNonempty.Set(); } void cAuthenticator::Start(cSettingsRepositoryInterface & a_Settings) { ReadSettings(a_Settings); Super::Start(); } void cAuthenticator::Stop(void) { m_ShouldTerminate = true; m_QueueNonempty.Set(); Super::Stop(); } void cAuthenticator::Execute(void) { for (;;) { cCSLock Lock(m_CS); while (!m_ShouldTerminate && (m_Queue.size() == 0)) { cCSUnlock Unlock(Lock); m_QueueNonempty.Wait(); } if (m_ShouldTerminate) { return; } ASSERT(!m_Queue.empty()); cAuthenticator::cUser User = std::move(m_Queue.front()); int & ClientID = User.m_ClientID; AString & Username = User.m_Name; AString & ServerID = User.m_ServerID; m_Queue.pop_front(); Lock.Unlock(); cUUID UUID; Json::Value Properties; if (AuthWithYggdrasil(Username, ServerID, UUID, Properties)) { LOGINFO("User %s authenticated with UUID %s", Username.c_str(), UUID.ToShortString().c_str()); cRoot::Get()->GetServer()->AuthenticateUser(ClientID, std::move(Username), UUID, std::move(Properties)); } else { cRoot::Get()->KickUser(ClientID, "Failed to authenticate account!"); } } // for (-ever) } bool cAuthenticator::AuthWithYggdrasil(AString & a_UserName, const AString & a_ServerId, cUUID & a_UUID, Json::Value & a_Properties) const { LOGD("Trying to authenticate user %s", a_UserName.c_str()); // Create the GET request: AString ActualAddress = m_Address; ReplaceURL(ActualAddress, "%USERNAME%", a_UserName); ReplaceURL(ActualAddress, "%SERVERID%", a_ServerId); // Create and send the HTTP request auto [IsSuccessful, Response] = cUrlClient::BlockingGet(m_Server + ActualAddress); if (!IsSuccessful) { return false; } // Parse the Json response: if (Response.empty()) { return false; } Json::Value root; if (!JsonUtils::ParseString(Response, root)) { LOGWARNING("%s: Cannot parse received data (authentication) to JSON!", __FUNCTION__); return false; } a_UserName = root.get("name", "Unknown").asString(); a_Properties = root["properties"]; if (!a_UUID.FromString(root.get("id", "").asString())) { LOGWARNING("%s: Received invalid UUID format", __FUNCTION__); return false; } // Store the player's profile in the MojangAPI caches: cRoot::Get()->GetMojangAPI().AddPlayerProfile(a_UserName, a_UUID, a_Properties); return true; } #ifdef ENABLE_PROPERTIES /* In case we want to export this function to the plugin API later - don't forget to add the relevant INI configuration lines for DEFAULT_PROPERTIES_ADDRESS */ #define DEFAULT_PROPERTIES_ADDRESS "/session/minecraft/profile/%UUID%" // Gets the properties, such as skin, of a player based on their UUID via Mojang's API bool GetPlayerProperties(const AString & a_UUID, Json::Value & a_Properties); bool cAuthenticator::GetPlayerProperties(const AString & a_UUID, Json::Value & a_Properties) { LOGD("Trying to get properties for user %s", a_UUID.c_str()); // Create and send the HTTP request auto [IsSuccessful, Response] = cUrlClient::BlockingGet(m_Server + ActualAddress); if (!IsSuccessful) { return false; } // Parse the Json response: if (Response.empty()) { return false; } Json::Value root; Json::Reader reader; if (!reader.parse(Response, root, false)) { LOGWARNING("cAuthenticator: Cannot parse received properties data to JSON!"); return false; } a_Properties = root["properties"]; return true; } #endif ================================================ FILE: src/Protocol/Authenticator.h ================================================ // cAuthenticator.h // Interfaces to the cAuthenticator class representing the thread that authenticates users against the official Mojang servers // Authentication prevents "hackers" from joining with an arbitrary username (possibly impersonating the server admins) // For more info, see http://wiki.vg/Session // In Cuberite, authentication is implemented as a single thread that receives queued auth requests and dispatches them one by one. #pragma once #include "../OSSupport/IsThread.h" // fwd: class cUUID; class cSettingsRepositoryInterface; namespace Json { class Value; } class cAuthenticator: public cIsThread { using Super = cIsThread; public: cAuthenticator(); virtual ~cAuthenticator() override; /** (Re-)read server and address from INI: */ void ReadSettings(cSettingsRepositoryInterface & a_Settings); /** Queues a request for authenticating a user. If the auth fails, the user will be kicked */ void Authenticate(int a_ClientID, std::string_view a_Username, std::string_view a_ServerHash); /** Starts the authenticator thread. The thread may be started and stopped repeatedly */ void Start(cSettingsRepositoryInterface & a_Settings); /** Stops the authenticator thread. The thread may be started and stopped repeatedly */ void Stop(void); private: class cUser { public: int m_ClientID; AString m_Name; AString m_ServerID; cUser(int a_ClientID, const std::string_view a_Name, const std::string_view a_ServerID) : m_ClientID(a_ClientID), m_Name(a_Name), m_ServerID(a_ServerID) { } }; using cUserList = std::deque; cCriticalSection m_CS; cUserList m_Queue; cEvent m_QueueNonempty; /** The server that is to be contacted for auth / UUID conversions */ AString m_Server; /** The URL to use for auth, without server part. %USERNAME% will be replaced with actual user name. %SERVERID% will be replaced with server's ID. For example "/session/minecraft/hasJoined?username=%USERNAME%&serverId=%SERVERID%". */ AString m_Address; AString m_PropertiesAddress; bool m_ShouldAuthenticate; /** cIsThread override: */ virtual void Execute(void) override; /** Returns true if the user authenticated okay, false on error Returns the case-corrected username, UUID, and properties (eg. skin). */ bool AuthWithYggdrasil(AString & a_UserName, const AString & a_ServerId, cUUID & a_UUID, Json::Value & a_Properties) const; }; ================================================ FILE: src/Protocol/CMakeLists.txt ================================================ target_sources( ${CMAKE_PROJECT_NAME} PRIVATE Authenticator.cpp ChunkDataSerializer.cpp ForgeHandshake.cpp MojangAPI.cpp Packetizer.cpp Protocol_1_8.cpp Protocol_1_9.cpp Protocol_1_10.cpp Protocol_1_11.cpp Protocol_1_12.cpp Protocol_1_13.cpp Protocol_1_14.cpp ProtocolRecognizer.cpp RecipeMapper.cpp Authenticator.h ChunkDataSerializer.h ForgeHandshake.h MojangAPI.h Packetizer.h Protocol.h Protocol_1_8.h Protocol_1_9.h Protocol_1_10.h Protocol_1_11.h Protocol_1_12.h Protocol_1_13.h Protocol_1_14.h ProtocolRecognizer.h RecipeMapper.h ) add_subdirectory(Palettes) ================================================ FILE: src/Protocol/ChunkDataSerializer.cpp ================================================ #include "Globals.h" #include "ChunkDataSerializer.h" #include "Protocol_1_8.h" #include "Protocol_1_9.h" #include "../ClientHandle.h" #include "../WorldStorage/FastNBT.h" #include "Palettes/Upgrade.h" #include "Palettes/Palette_1_13.h" #include "Palettes/Palette_1_13_1.h" #include "Palettes/Palette_1_14.h" namespace { std::pair GetSectionBitmask(const ChunkBlockData & a_BlockData, const ChunkLightData & a_LightData) { size_t Present = 0; UInt16 Mask = 0; ChunkDef_ForEachSection(a_BlockData, a_LightData, { Present++; Mask |= (1 << Y); }); return { Mask, Present }; } auto PaletteLegacy(const BLOCKTYPE a_BlockType, const NIBBLETYPE a_Meta) { return (a_BlockType << 4) | a_Meta; } auto Palette393(const BLOCKTYPE a_BlockType, const NIBBLETYPE a_Meta) { return Palette_1_13::From(PaletteUpgrade::FromBlock(a_BlockType, a_Meta)); } auto Palette401(const BLOCKTYPE a_BlockType, const NIBBLETYPE a_Meta) { return Palette_1_13_1::From(PaletteUpgrade::FromBlock(a_BlockType, a_Meta)); } auto Palette477(const BLOCKTYPE a_BlockType, const NIBBLETYPE a_Meta) { return Palette_1_14::From(PaletteUpgrade::FromBlock(a_BlockType, a_Meta)); } } //////////////////////////////////////////////////////////////////////////////// // cChunkDataSerializer: cChunkDataSerializer::cChunkDataSerializer(const eDimension a_Dimension) : m_Packet(512 KiB), m_Dimension(a_Dimension) { } void cChunkDataSerializer::SendToClients(const int a_ChunkX, const int a_ChunkZ, const ChunkBlockData & a_BlockData, const ChunkLightData & a_LightData, const unsigned char * a_BiomeMap, const ClientHandles & a_SendTo) { for (const auto & Client : a_SendTo) { switch (static_cast(Client->GetProtocolVersion())) { case cProtocol::Version::v1_8_0: { Serialize(Client, a_ChunkX, a_ChunkZ, a_BlockData, a_LightData, a_BiomeMap, CacheVersion::v47); continue; } case cProtocol::Version::v1_9_0: case cProtocol::Version::v1_9_1: case cProtocol::Version::v1_9_2: { Serialize(Client, a_ChunkX, a_ChunkZ, a_BlockData, a_LightData, a_BiomeMap, CacheVersion::v107); continue; } case cProtocol::Version::v1_9_4: case cProtocol::Version::v1_10_0: case cProtocol::Version::v1_11_0: case cProtocol::Version::v1_11_1: case cProtocol::Version::v1_12: case cProtocol::Version::v1_12_1: case cProtocol::Version::v1_12_2: { Serialize(Client, a_ChunkX, a_ChunkZ, a_BlockData, a_LightData, a_BiomeMap, CacheVersion::v110); continue; } case cProtocol::Version::v1_13: { Serialize(Client, a_ChunkX, a_ChunkZ, a_BlockData, a_LightData, a_BiomeMap, CacheVersion::v393); // This version didn't last very long xD continue; } case cProtocol::Version::v1_13_1: case cProtocol::Version::v1_13_2: { Serialize(Client, a_ChunkX, a_ChunkZ, a_BlockData, a_LightData, a_BiomeMap, CacheVersion::v401); continue; } case cProtocol::Version::v1_14: case cProtocol::Version::v1_14_1: case cProtocol::Version::v1_14_2: case cProtocol::Version::v1_14_3: case cProtocol::Version::v1_14_4: { Serialize(Client, a_ChunkX, a_ChunkZ, a_BlockData, a_LightData, a_BiomeMap, CacheVersion::v477); continue; } } UNREACHABLE("Unknown chunk data serialization version"); } // Our cache is only persistent during the function call: for (auto & Cache : m_Cache) { Cache.Engaged = false; } } inline void cChunkDataSerializer::Serialize(const ClientHandles::value_type & a_Client, const int a_ChunkX, const int a_ChunkZ, const ChunkBlockData & a_BlockData, const ChunkLightData & a_LightData, const unsigned char * a_BiomeMap, const CacheVersion a_CacheVersion) { auto & Cache = m_Cache[static_cast(a_CacheVersion)]; if (Cache.Engaged) { // Success! We've done it already, just re-use: a_Client->SendChunkData(a_ChunkX, a_ChunkZ, Cache.ToSend); return; } switch (a_CacheVersion) { case CacheVersion::v47: { Serialize47(a_ChunkX, a_ChunkZ, a_BlockData, a_LightData, a_BiomeMap); break; } case CacheVersion::v107: { Serialize107(a_ChunkX, a_ChunkZ, a_BlockData, a_LightData, a_BiomeMap); break; } case CacheVersion::v110: { Serialize110(a_ChunkX, a_ChunkZ, a_BlockData, a_LightData, a_BiomeMap); break; } case CacheVersion::v393: { Serialize393<&Palette393>(a_ChunkX, a_ChunkZ, a_BlockData, a_LightData, a_BiomeMap); break; } case CacheVersion::v401: { Serialize393<&Palette401>(a_ChunkX, a_ChunkZ, a_BlockData, a_LightData, a_BiomeMap); break; } case CacheVersion::v477: { Serialize477(a_ChunkX, a_ChunkZ, a_BlockData, a_LightData, a_BiomeMap); break; } } CompressPacketInto(Cache); ASSERT(Cache.Engaged); // Cache must be populated now a_Client->SendChunkData(a_ChunkX, a_ChunkZ, Cache.ToSend); } inline void cChunkDataSerializer::Serialize47(const int a_ChunkX, const int a_ChunkZ, const ChunkBlockData & a_BlockData, const ChunkLightData & a_LightData, const unsigned char * a_BiomeMap) { // This function returns the fully compressed packet (including packet size), not the raw packet! const auto Bitmask = GetSectionBitmask(a_BlockData, a_LightData); // Create the packet: m_Packet.WriteVarInt32(0x21); // Packet id (Chunk Data packet) m_Packet.WriteBEInt32(a_ChunkX); m_Packet.WriteBEInt32(a_ChunkZ); m_Packet.WriteBool(true); // "Ground-up continuous", or rather, "biome data present" flag // Minecraft 1.8 does not like completely empty packets // Send one completely empty chunk section if this is the case m_Packet.WriteBEUInt16(Bitmask.first ? Bitmask.first : 1); // Write the chunk size: // Account for the single empty section if sending an empty chunk const int BiomeDataSize = cChunkDef::Width * cChunkDef::Width; const size_t ChunkSize = ( (Bitmask.second ? Bitmask.second : 1) * (ChunkBlockData::SectionBlockCount * 2 + ChunkLightData::SectionLightCount * 2) + // Blocks and lighting BiomeDataSize // Biome data ); m_Packet.WriteVarInt32(static_cast(ChunkSize)); // Chunk written as seperate arrays of (blocktype + meta), blocklight and skylight // each array stores all present sections of the same kind packed together // Write the block types to the packet: ChunkDef_ForEachSection(a_BlockData, a_LightData, { const bool BlocksExist = Blocks != nullptr; const bool MetasExist = Metas != nullptr; for (size_t BlockIdx = 0; BlockIdx != ChunkBlockData::SectionBlockCount; ++BlockIdx) { BLOCKTYPE BlockType = BlocksExist ? (*Blocks)[BlockIdx] : 0; NIBBLETYPE BlockMeta = MetasExist ? cChunkDef::ExpandNibble(Metas->data(), BlockIdx) : 0; m_Packet.WriteBEUInt8(static_cast(BlockType << 4) | BlockMeta); m_Packet.WriteBEUInt8(static_cast(BlockType >> 4)); } }); // Write the block lights: ChunkDef_ForEachSection(a_BlockData, a_LightData, { if (BlockLights == nullptr) { m_Packet.WriteBuf(ChunkLightData::SectionLightCount, ChunkLightData::DefaultBlockLightValue); } else { m_Packet.WriteBuf(BlockLights->data(), BlockLights->size()); } }); // Write the sky lights: ChunkDef_ForEachSection(a_BlockData, a_LightData, { if (SkyLights == nullptr) { m_Packet.WriteBuf(ChunkLightData::SectionLightCount, ChunkLightData::DefaultSkyLightValue); } else { m_Packet.WriteBuf(SkyLights->data(), SkyLights->size()); } }); // Serialize a single empty section if sending an empty chunk if (!Bitmask.first) { // Block data (all air) for (size_t i = 0; i < ChunkBlockData::SectionBlockCount * 2; i++) { m_Packet.WriteBEUInt8(0); } // Light data (XXX: sky light is not sent if in the nether) m_Packet.WriteBuf(ChunkLightData::SectionLightCount, ChunkLightData::DefaultSkyLightValue); m_Packet.WriteBuf(ChunkLightData::SectionLightCount, ChunkLightData::DefaultSkyLightValue); } // Write the biome data: m_Packet.WriteBuf(a_BiomeMap, BiomeDataSize); } inline void cChunkDataSerializer::Serialize107(const int a_ChunkX, const int a_ChunkZ, const ChunkBlockData & a_BlockData, const ChunkLightData & a_LightData, const unsigned char * a_BiomeMap) { // This function returns the fully compressed packet (including packet size), not the raw packet! // Below variables tagged static because of https://developercommunity.visualstudio.com/content/problem/367326 static constexpr UInt8 BitsPerEntry = 13; static constexpr size_t ChunkSectionDataArraySize = (ChunkBlockData::SectionBlockCount * BitsPerEntry) / 8 / 8; // Convert from bit count to long count const auto Bitmask = GetSectionBitmask(a_BlockData, a_LightData); // Create the packet: m_Packet.WriteVarInt32(0x20); // Packet id (Chunk Data packet) m_Packet.WriteBEInt32(a_ChunkX); m_Packet.WriteBEInt32(a_ChunkZ); m_Packet.WriteBool(true); // "Ground-up continuous", or rather, "biome data present" flag m_Packet.WriteVarInt32(Bitmask.first); size_t ChunkSectionSize = ( 1 + // Bits per block - set to 13, so the global palette is used and the palette has a length of 0 1 + // Palette length 2 + // Data array length VarInt - 2 bytes for the current value ChunkSectionDataArraySize * 8 + // Actual block data - multiplied by 8 because first number is longs ChunkLightData::SectionLightCount // Block light ); if (m_Dimension == dimOverworld) { // Sky light is only sent in the overworld. ChunkSectionSize += ChunkLightData::SectionLightCount; } const size_t BiomeDataSize = cChunkDef::Width * cChunkDef::Width; const size_t ChunkSize = ( ChunkSectionSize * Bitmask.second + BiomeDataSize ); // Write the chunk size: m_Packet.WriteVarInt32(static_cast(ChunkSize)); // Write each chunk section... ChunkDef_ForEachSection(a_BlockData, a_LightData, { m_Packet.WriteBEUInt8(BitsPerEntry); m_Packet.WriteVarInt32(0); // Palette length is 0 m_Packet.WriteVarInt32(static_cast(ChunkSectionDataArraySize)); WriteBlockSectionSeamless<&PaletteLegacy>(Blocks, Metas, BitsPerEntry); WriteLightSectionGrouped(BlockLights, SkyLights); }); // Write the biome data m_Packet.WriteBuf(a_BiomeMap, BiomeDataSize); } inline void cChunkDataSerializer::Serialize110(const int a_ChunkX, const int a_ChunkZ, const ChunkBlockData & a_BlockData, const ChunkLightData & a_LightData, const unsigned char * a_BiomeMap) { // This function returns the fully compressed packet (including packet size), not the raw packet! // Below variables tagged static because of https://developercommunity.visualstudio.com/content/problem/367326 static constexpr UInt8 BitsPerEntry = 13; static constexpr size_t ChunkSectionDataArraySize = (ChunkBlockData::SectionBlockCount * BitsPerEntry) / 8 / 8; // Convert from bit count to long count const auto Bitmask = GetSectionBitmask(a_BlockData, a_LightData); // Create the packet: m_Packet.WriteVarInt32(0x20); // Packet id (Chunk Data packet) m_Packet.WriteBEInt32(a_ChunkX); m_Packet.WriteBEInt32(a_ChunkZ); m_Packet.WriteBool(true); // "Ground-up continuous", or rather, "biome data present" flag m_Packet.WriteVarInt32(Bitmask.first); size_t ChunkSectionSize = ( 1 + // Bits per block - set to 13, so the global palette is used and the palette has a length of 0 1 + // Palette length 2 + // Data array length VarInt - 2 bytes for the current value ChunkSectionDataArraySize * 8 + // Actual block data - multiplied by 8 because first number is longs ChunkLightData::SectionLightCount // Block light ); if (m_Dimension == dimOverworld) { // Sky light is only sent in the overworld. ChunkSectionSize += ChunkLightData::SectionLightCount; } const size_t BiomeDataSize = cChunkDef::Width * cChunkDef::Width; const size_t ChunkSize = ( ChunkSectionSize * Bitmask.second + BiomeDataSize ); // Write the chunk size: m_Packet.WriteVarInt32(static_cast(ChunkSize)); // Write each chunk section... ChunkDef_ForEachSection(a_BlockData, a_LightData, { m_Packet.WriteBEUInt8(BitsPerEntry); m_Packet.WriteVarInt32(0); // Palette length is 0 m_Packet.WriteVarInt32(static_cast(ChunkSectionDataArraySize)); WriteBlockSectionSeamless<&PaletteLegacy>(Blocks, Metas, BitsPerEntry); WriteLightSectionGrouped(BlockLights, SkyLights); }); // Write the biome data m_Packet.WriteBuf(a_BiomeMap, BiomeDataSize); // Identify 1.9.4's tile entity list as empty m_Packet.WriteBEUInt8(0); } template inline void cChunkDataSerializer::Serialize393(const int a_ChunkX, const int a_ChunkZ, const ChunkBlockData & a_BlockData, const ChunkLightData & a_LightData, const unsigned char * a_BiomeMap) { // This function returns the fully compressed packet (including packet size), not the raw packet! // Below variables tagged static because of https://developercommunity.visualstudio.com/content/problem/367326 static constexpr UInt8 BitsPerEntry = 14; static constexpr size_t ChunkSectionDataArraySize = (ChunkBlockData::SectionBlockCount * BitsPerEntry) / 8 / 8; const auto Bitmask = GetSectionBitmask(a_BlockData, a_LightData); // Create the packet: m_Packet.WriteVarInt32(0x22); // Packet id (Chunk Data packet) m_Packet.WriteBEInt32(a_ChunkX); m_Packet.WriteBEInt32(a_ChunkZ); m_Packet.WriteBool(true); // "Ground-up continuous", or rather, "biome data present" flag m_Packet.WriteVarInt32(Bitmask.first); size_t ChunkSectionSize = ( 1 + // Bits per entry, BEUInt8, 1 byte m_Packet.GetVarIntSize(static_cast(ChunkSectionDataArraySize)) + // Field containing "size of whole section", VarInt32, variable size ChunkSectionDataArraySize * 8 + // Actual section data, lots of bytes (multiplier 1 long = 8 bytes) ChunkLightData::SectionLightCount // Size of blocklight which is always sent ); if (m_Dimension == dimOverworld) { // Sky light is only sent in the overworld. ChunkSectionSize += ChunkLightData::SectionLightCount; } const size_t BiomeDataSize = cChunkDef::Width * cChunkDef::Width; const size_t ChunkSize = ( ChunkSectionSize * Bitmask.second + BiomeDataSize * 4 // Biome data now BE ints ); // Write the chunk size in bytes: m_Packet.WriteVarInt32(static_cast(ChunkSize)); // Write each chunk section... ChunkDef_ForEachSection(a_BlockData, a_LightData, { m_Packet.WriteBEUInt8(BitsPerEntry); m_Packet.WriteVarInt32(static_cast(ChunkSectionDataArraySize)); WriteBlockSectionSeamless(Blocks, Metas, BitsPerEntry); WriteLightSectionGrouped(BlockLights, SkyLights); }); // Write the biome data for (size_t i = 0; i != BiomeDataSize; i++) { m_Packet.WriteBEUInt32(static_cast(a_BiomeMap[i])); } // Identify 1.9.4's tile entity list as empty m_Packet.WriteVarInt32(0); } inline void cChunkDataSerializer::Serialize477(const int a_ChunkX, const int a_ChunkZ, const ChunkBlockData & a_BlockData, const ChunkLightData & a_LightData, const unsigned char * a_BiomeMap) { // This function returns the fully compressed packet (including packet size), not the raw packet! // Below variables tagged static because of https://developercommunity.visualstudio.com/content/problem/367326 static constexpr UInt8 BitsPerEntry = 14; static constexpr size_t ChunkSectionDataArraySize = (ChunkBlockData::SectionBlockCount * BitsPerEntry) / 8 / 8; const auto Bitmask = GetSectionBitmask(a_BlockData, a_LightData); // Create the packet: m_Packet.WriteVarInt32(0x21); // Packet id (Chunk Data packet) m_Packet.WriteBEInt32(a_ChunkX); m_Packet.WriteBEInt32(a_ChunkZ); m_Packet.WriteBool(true); // "Ground-up continuous", or rather, "biome data present" flag m_Packet.WriteVarInt32(Bitmask.first); { cFastNBTWriter Writer; // TODO: client works fine without? // std::array Longz = {}; // Writer.AddLongArray("MOTION_BLOCKING", Longz.data(), Longz.size()); Writer.Finish(); m_Packet.Write(Writer.GetResult().data(), Writer.GetResult().size()); } const size_t ChunkSectionSize = ( 2 + // Block count, BEInt16, 2 bytes 1 + // Bits per entry, BEUInt8, 1 byte m_Packet.GetVarIntSize(static_cast(ChunkSectionDataArraySize)) + // Field containing "size of whole section", VarInt32, variable size ChunkSectionDataArraySize * 8 // Actual section data, lots of bytes (multiplier 1 long = 8 bytes) ); const size_t BiomeDataSize = cChunkDef::Width * cChunkDef::Width; const size_t ChunkSize = ( ChunkSectionSize * Bitmask.second + BiomeDataSize * 4 // Biome data now BE ints ); // Write the chunk size in bytes: m_Packet.WriteVarInt32(static_cast(ChunkSize)); // Write each chunk section... ChunkDef_ForEachSection(a_BlockData, a_LightData, { m_Packet.WriteBEInt16(ChunkBlockData::SectionBlockCount); // a temp fix to make sure sections don't disappear m_Packet.WriteBEUInt8(BitsPerEntry); m_Packet.WriteVarInt32(static_cast(ChunkSectionDataArraySize)); WriteBlockSectionSeamless<&Palette477>(Blocks, Metas, BitsPerEntry); }); // Write the biome data for (size_t i = 0; i != BiomeDataSize; i++) { m_Packet.WriteBEUInt32(a_BiomeMap[i]); } // Identify 1.9.4's tile entity list as empty m_Packet.WriteVarInt32(0); } template inline void cChunkDataSerializer::WriteBlockSectionSeamless(const ChunkBlockData::BlockArray * a_Blocks, const ChunkBlockData::MetaArray * a_Metas, const UInt8 a_BitsPerEntry) { // https://wiki.vg/Chunk_Format#Data_structure // We shift a UInt64 by a_BitsPerEntry, the latter cannot be too big: ASSERT(a_BitsPerEntry < 64); UInt64 Buffer = 0; // A buffer to compose multiple smaller bitsizes into one 64-bit number unsigned char BitIndex = 0; // The bit-position in Buffer that represents where to write next const bool BlocksExist = a_Blocks != nullptr; const bool MetasExist = a_Metas != nullptr; for (size_t Index = 0; Index != ChunkBlockData::SectionBlockCount; Index++) { const BLOCKTYPE BlockType = BlocksExist ? (*a_Blocks)[Index] : 0; const NIBBLETYPE BlockMeta = MetasExist ? cChunkDef::ExpandNibble(a_Metas->data(), Index) : 0; const auto Value = Palette(BlockType, BlockMeta); // Write as much as possible of Value, starting from BitIndex, into Buffer: Buffer |= static_cast(Value) << BitIndex; // The _signed_ count of bits in Value left to write const auto Remaining = static_cast(a_BitsPerEntry - (64 - BitIndex)); if (Remaining >= 0) { // There were some bits remaining: we've filled the buffer. Flush it: m_Packet.WriteBEUInt64(Buffer); // And write the remaining bits, setting the new BitIndex: Buffer = static_cast(Value >> (a_BitsPerEntry - Remaining)); BitIndex = static_cast(Remaining); } else { // It fit, excellent. BitIndex += a_BitsPerEntry; } } static_assert((ChunkBlockData::SectionBlockCount % 64) == 0, "Section must fit wholly into a 64-bit long array"); ASSERT(BitIndex == 0); ASSERT(Buffer == 0); } inline void cChunkDataSerializer::WriteLightSectionGrouped(const ChunkLightData::LightArray * const a_BlockLights, const ChunkLightData::LightArray * const a_SkyLights) { // Write lighting: if (a_BlockLights == nullptr) { m_Packet.WriteBuf(ChunkLightData::SectionLightCount, ChunkLightData::DefaultBlockLightValue); } else { m_Packet.WriteBuf(a_BlockLights->data(), a_BlockLights->size()); } // Skylight is only sent in the overworld; the nether and end do not use it: if (m_Dimension == dimOverworld) { if (a_SkyLights == nullptr) { m_Packet.WriteBuf(ChunkLightData::SectionLightCount, ChunkLightData::DefaultSkyLightValue); } else { m_Packet.WriteBuf(a_SkyLights->data(), a_SkyLights->size()); } } } inline void cChunkDataSerializer::CompressPacketInto(ChunkDataCache & a_Cache) { m_Compressor.ReadFrom(m_Packet); m_Packet.CommitRead(); cProtocol_1_8_0::CompressPacket(m_Compressor, a_Cache.ToSend); a_Cache.Engaged = true; } ================================================ FILE: src/Protocol/ChunkDataSerializer.h ================================================ #pragma once #include "../ByteBuffer.h" #include "../ChunkData.h" #include "../Defines.h" #include "CircularBufferCompressor.h" #include "StringCompression.h" class cByteBuffer; /** Serializes one chunk's data to (possibly multiple) protocol versions. Caches the serialized data for as long as this object lives, so that the same data can be sent to other clients using the same protocol. */ class cChunkDataSerializer { using ClientHandles = std::vector>; /** Enum to collapse protocol versions into a contiguous index. */ enum class CacheVersion { v47, v107, v110, v393, v401, v477, Last = CacheVersion::v477 }; /** A single cache entry containing the raw data, compressed data, and a validity flag. */ struct ChunkDataCache { ContiguousByteBuffer ToSend; bool Engaged = false; }; public: cChunkDataSerializer(eDimension a_Dimension); /** For each client, serializes the chunk into their protocol version and sends it. Parameters are the coordinates of the chunk to serialise, and the data and biome data read from the chunk. */ void SendToClients(int a_ChunkX, int a_ChunkZ, const ChunkBlockData & a_BlockData, const ChunkLightData & a_LightData, const unsigned char * a_BiomeMap, const ClientHandles & a_SendTo); private: /** Serialises the given chunk, storing the result into the given cache entry, and sends the data. If the cache entry is already present, simply re-uses it. */ inline void Serialize(const ClientHandles::value_type & a_Client, int a_ChunkX, int a_ChunkZ, const ChunkBlockData & a_BlockData, const ChunkLightData & a_LightData, const unsigned char * a_BiomeMap, CacheVersion a_CacheVersion); inline void Serialize47 (int a_ChunkX, int a_ChunkZ, const ChunkBlockData & a_BlockData, const ChunkLightData & a_LightData, const unsigned char * a_BiomeMap); // Release 1.8 inline void Serialize107(int a_ChunkX, int a_ChunkZ, const ChunkBlockData & a_BlockData, const ChunkLightData & a_LightData, const unsigned char * a_BiomeMap); // Release 1.9 inline void Serialize110(int a_ChunkX, int a_ChunkZ, const ChunkBlockData & a_BlockData, const ChunkLightData & a_LightData, const unsigned char * a_BiomeMap); // Release 1.9.4 template inline void Serialize393(int a_ChunkX, int a_ChunkZ, const ChunkBlockData & a_BlockData, const ChunkLightData & a_LightData, const unsigned char * a_BiomeMap); // Release 1.13 - 1.13.2 inline void Serialize477(int a_ChunkX, int a_ChunkZ, const ChunkBlockData & a_BlockData, const ChunkLightData & a_LightData, const unsigned char * a_BiomeMap); // Release 1.14 - 1.14.4 /** Writes all blocks in a chunk section into a series of Int64. Writes start from the bit directly subsequent to the previous write's end, possibly crossing over to the next Int64. */ template inline void WriteBlockSectionSeamless(const ChunkBlockData::BlockArray * a_Blocks, const ChunkBlockData::MetaArray * a_Metas, UInt8 a_BitsPerEntry); /** Copies all lights in a chunk section into the packet, block light followed immediately by sky light. */ inline void WriteLightSectionGrouped(const ChunkLightData::LightArray * a_BlockLights, const ChunkLightData::LightArray * a_SkyLights); /** Finalises the data, compresses it if required, and stores it into cache. */ inline void CompressPacketInto(ChunkDataCache & a_Cache); /** A staging area used to construct the chunk packet, persistent to avoid reallocating. */ cByteBuffer m_Packet; /** A compressor used to compress the chunk data. */ CircularBufferCompressor m_Compressor; /** The dimension for the World this Serializer is tied to. */ const eDimension m_Dimension; /** A cache, mapping protocol version to a fully serialised chunk. It is used during a single invocation of SendToClients with more than one client. */ std::array(CacheVersion::Last) + 1> m_Cache; } ; ================================================ FILE: src/Protocol/ForgeHandshake.cpp ================================================ // ForgeHandshake.cpp // Implements Forge protocol handshaking #include "Globals.h" #include "ForgeHandshake.h" #include "json/json.h" #include "../Server.h" #include "../ByteBuffer.h" #include "../Bindings/PluginManager.h" #include "../ClientHandle.h" #include "../Root.h" /** Discriminator byte values prefixing the FML|HS packets to determine their type. */ namespace Discriminator { static const Int8 ServerHello = 0; static const Int8 ClientHello = 1; static const Int8 ModList = 2; static const Int8 RegistryData = 3; // static const Int8 HandshakeReset = -2; static const Int8 HandshakeAck = -1; } /** Client handshake state phases. */ namespace ClientPhase { static const Int8 WAITINGSERVERDATA = 2; static const Int8 WAITINGSERVERCOMPLETE = 3; static const Int8 PENDINGCOMPLETE = 4; static const Int8 COMPLETE = 5; } /** Server handshake state phases. */ namespace ServerPhase { static const auto WAITINGCACK = std::byte(2); static const auto COMPLETE = std::byte(3); } cForgeHandshake::cForgeHandshake() : IsForgeClient(false), m_Errored(false) { } void cForgeHandshake::SetError(const AString & message) { LOGD("Forge handshake error: %s", message.c_str()); m_Errored = true; } void cForgeHandshake::AugmentServerListPing(cClientHandle & a_Client, Json::Value & a_ResponseValue) { auto ProtocolVersion = a_Client.GetProtocolVersion(); auto & Mods = cRoot::Get()->GetServer()->GetRegisteredForgeMods(ProtocolVersion); if (Mods.empty()) { return; } LOGD("Received server ping from version: %d", ProtocolVersion); Json::Value Modinfo; Modinfo["type"] = "FML"; Json::Value ModList(Json::arrayValue); for (auto & item: Mods) { Json::Value Mod; Mod["modid"] = item.first; Mod["version"] = item.second; ModList.append(Mod); } Modinfo["modList"] = ModList; a_ResponseValue["modinfo"] = Modinfo; } void cForgeHandshake::BeginForgeHandshake(cClientHandle & a_Client) { ASSERT(IsForgeClient); static const std::array Channels{{ "FML|HS", "FML", "FML|MP", "FML", "FORGE" }}; ContiguousByteBuffer ChannelsString; for (auto & Channel: Channels) { ChannelsString.append({ reinterpret_cast(Channel.data()), Channel.size() }); ChannelsString.push_back(std::byte(0)); } a_Client.SendPluginMessage("REGISTER", ChannelsString); SendServerHello(a_Client); } void cForgeHandshake::SendServerHello(cClientHandle & a_Client) { cByteBuffer Buf(6); // Discriminator | Byte | Always 0 for ServerHello Buf.WriteBEInt8(Discriminator::ServerHello); // FML protocol Version | Byte | Determined from NetworkRegistery. Currently 2. Buf.WriteBEInt8(2); // Dimension TODO Buf.WriteBEInt32(0); ContiguousByteBuffer Message; Buf.ReadAll(Message); a_Client.SendPluginMessage("FML|HS", Message); } AStringMap cForgeHandshake::ParseModList(const ContiguousByteBufferView a_Data) { AStringMap Mods; if (a_Data.size() < 4) { SetError(fmt::format(FMT_STRING("ParseModList invalid packet, missing length (size = {})"), a_Data.size())); return Mods; } cByteBuffer Buf(a_Data.size()); Buf.Write(a_Data.data(), a_Data.size()); UInt32 NumMods; if (!Buf.ReadVarInt32(NumMods)) { SetError("ParseModList failed to read mod count"); return Mods; } for (UInt32 i = 0; i < NumMods; ++i) { AString Name, Version; if (!Buf.ReadVarUTF8String(Name)) { SetError(fmt::format(FMT_STRING("ParseModList failed to read mod name at i = {}"), i)); break; } if (!Buf.ReadVarUTF8String(Version)) { SetError(fmt::format(FMT_STRING("ParseModList failed to read mod version at i = {}"), i)); break; } Mods.insert({Name, Version}); } return Mods; } void cForgeHandshake::HandleClientHello(cClientHandle & a_Client, const ContiguousByteBufferView a_Data) { if (a_Data.size() == 2) { const auto FmlProtocolVersion = static_cast(a_Data[1]); LOGD("Received ClientHello with FML protocol version %d", FmlProtocolVersion); if (FmlProtocolVersion != 2) { SetError(fmt::format(FMT_STRING("Unsupported FML client protocol version received in ClientHello: {}"), FmlProtocolVersion)); } } else { SetError(fmt::format(FMT_STRING("Received unexpected length of ClientHello: {}"), a_Data.size())); } } void cForgeHandshake::HandleModList(cClientHandle & a_Client, const ContiguousByteBufferView a_Data) { LOGD("Received ModList"); auto ClientMods = ParseModList(a_Data.substr(1)); AString ClientModsString; for (auto & item: ClientMods) { ClientModsString.append(fmt::format(FMT_STRING("{}@{}, "), item.first, item.second)); } LOG("Client connected with %zu mods: %s", ClientMods.size(), ClientModsString); a_Client.m_ForgeMods = ClientMods; // Let the plugins know about this event, they may refuse the player: if (cRoot::Get()->GetPluginManager()->CallHookLoginForge(a_Client, ClientMods)) { SetError("Modded client refused by plugin"); return; } // Send server ModList // Send server-side Forge mods registered by plugins const auto & ServerMods = a_Client.GetForgeMods(); const auto ModCount = ServerMods.size(); cByteBuffer Buf(256 * ModCount); Buf.WriteBEInt8(Discriminator::ModList); Buf.WriteVarInt32(static_cast(ModCount)); for (const auto & item: ServerMods) { Buf.WriteVarUTF8String(item.first); // name Buf.WriteVarUTF8String(item.second); // version } ContiguousByteBuffer ServerModList; Buf.ReadAll(ServerModList); a_Client.SendPluginMessage("FML|HS", ServerModList); } void cForgeHandshake::HandleHandshakeAck(cClientHandle & a_Client, const ContiguousByteBufferView a_Data) { if (a_Data.size() != 2) { SetError(fmt::format(FMT_STRING("Unexpected HandshakeAck packet length: {}"), a_Data.size())); return; } const auto Phase = static_cast(a_Data[1]); LOGD("Received client HandshakeAck with phase = %d", Phase); switch (Phase) { case ClientPhase::WAITINGSERVERDATA: { cByteBuffer Buf(1024); Buf.WriteBEInt8(Discriminator::RegistryData); // TODO: send real registry data bool HasMore = false; AString RegistryName = "potions"; UInt32 NumIDs = 0; UInt32 NumSubstitutions = 0; UInt32 NumDummies = 0; Buf.WriteBool(HasMore); Buf.WriteVarUTF8String(RegistryName); Buf.WriteVarInt32(NumIDs); Buf.WriteVarInt32(NumSubstitutions); Buf.WriteVarInt32(NumDummies); ContiguousByteBuffer RegistryData; Buf.ReadAll(RegistryData); a_Client.SendPluginMessage("FML|HS", RegistryData); break; } case ClientPhase::WAITINGSERVERCOMPLETE: { LOGD("Client finished receiving registry data; acknowledging"); ContiguousByteBuffer Ack; Ack.push_back(std::byte(Discriminator::HandshakeAck)); Ack.push_back(ServerPhase::WAITINGCACK); a_Client.SendPluginMessage("FML|HS", Ack); break; } case ClientPhase::PENDINGCOMPLETE: { LOGD("Client is pending completion; sending complete ack"); ContiguousByteBuffer Ack; Ack.push_back(std::byte(Discriminator::HandshakeAck)); Ack.push_back(ServerPhase::COMPLETE); a_Client.SendPluginMessage("FML|HS", Ack); break; } case ClientPhase::COMPLETE: { // Now finish logging in: a_Client.FinishAuthenticate(); break; } default: { SetError(fmt::format("Received unknown phase in Forge handshake acknowledgement: {}", Phase)); break; } } } void cForgeHandshake::DataReceived(cClientHandle & a_Client, const ContiguousByteBufferView a_Data) { if (!IsForgeClient) { SetError(fmt::format(FMT_STRING("Received unexpected Forge data from non-Forge client ({} bytes)"), a_Data.size())); return; } if (m_Errored) { LOGD("Received unexpected Forge data when in errored state, ignored"); return; } if (a_Data.size() <= 1) { SetError(fmt::format(FMT_STRING("Received unexpectedly short Forge data ({} bytes)"), a_Data.size())); return; } const auto Discriminator = static_cast(a_Data[0]); switch (Discriminator) { case Discriminator::ClientHello: HandleClientHello(a_Client, a_Data); break; case Discriminator::ModList: HandleModList(a_Client, a_Data); break; case Discriminator::HandshakeAck: HandleHandshakeAck(a_Client, a_Data); break; default: { SetError(fmt::format(FMT_STRING("Unexpected Forge packet {0} (0x{0:x}) received"), Discriminator)); return; } } } ================================================ FILE: src/Protocol/ForgeHandshake.h ================================================ // ForgeHandshake.h // Implements Forge protocol handshaking #pragma once #include #include "../UUID.h" #include "json/json.h" // fwd: class cClientHandle; class cForgeHandshake { public: /** True if the client advertised itself as a Forge client. */ bool IsForgeClient; cForgeHandshake(); /** Add the registered Forge mods to the server ping list packet. */ void AugmentServerListPing(cClientHandle & a_Client, Json::Value & ResponseValue); /** Begin the Forge Modloader Handshake (FML|HS) sequence. */ void BeginForgeHandshake(cClientHandle & a_Client); /** Send the ServerHello packet in the Forge handshake. */ void SendServerHello(cClientHandle & a_Client); /** Process received data from the client advancing the Forge handshake. */ void DataReceived(cClientHandle & a_Client, ContiguousByteBufferView a_Data); private: /** True if the Forge handshake is in an errored state. */ bool m_Errored; void HandleClientHello(cClientHandle & a_Client, ContiguousByteBufferView a_Data); void HandleModList(cClientHandle & a_Client, ContiguousByteBufferView a_Data); void HandleHandshakeAck(cClientHandle & a_Client, ContiguousByteBufferView a_Data); /** Set errored state to prevent further handshake message processing. */ void SetError(const AString & message); /** Parse the client ModList packet of installed Forge mods and versions. */ AStringMap ParseModList(ContiguousByteBufferView a_Data); }; ================================================ FILE: src/Protocol/MojangAPI.cpp ================================================ // MojangAPI.cpp // Implements the cMojangAPI class representing the various API points provided by Mojang's webservices, and a cache for their results #include "Globals.h" #include "MojangAPI.h" #include "HTTP/UrlClient.h" #include "IniFile.h" #include "JsonUtils.h" #include "json/json.h" #include "mbedTLS++/BlockingSslClientSocket.h" #include "mbedTLS++/SslConfig.h" #include "OSSupport/IsThread.h" #include "RankManager.h" #include "Root.h" #include "SQLiteCpp/Database.h" #include "SQLiteCpp/Statement.h" /** The maximum age for items to be kept in the cache. Any item older than this will be removed. */ const Int64 MAX_AGE = 7 * 24 * 60 * 60; // 7 days ago /** The maximum number of names to send in a single query */ const int MAX_PER_QUERY = 100; constexpr char DEFAULT_NAME_TO_UUID_SERVER[] = "api.mojang.com"; constexpr char DEFAULT_NAME_TO_UUID_ADDRESS[] = "/profiles/minecraft"; constexpr char DEFAULT_UUID_TO_PROFILE_SERVER[] = "sessionserver.mojang.com"; constexpr char DEFAULT_UUID_TO_PROFILE_ADDRESS[] = "/session/minecraft/profile/%UUID%?unsigned=false"; namespace MojangTrustedRootCAs { /** Returns the Options that should be used for cUrlClient queries to the Mojang APIs. */ static const AStringMap & UrlClientOptions() { static const AString CertString = // DigiCert Global Root CA (sessionserver.mojang.com, api.mojang.com) // Downloaded from https://www.digicert.com/kb/digicert-root-certificates.htm // DigiCert Global Root CA "-----BEGIN CERTIFICATE-----\n" "MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh\n" "MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\n" "d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD\n" "QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT\n" "MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j\n" "b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG\n" "9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB\n" "CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97\n" "nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt\n" "43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P\n" "T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4\n" "gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO\n" "BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR\n" "TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw\n" "DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr\n" "hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg\n" "06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF\n" "PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls\n" "YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk\n" "CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=\n" "-----END CERTIFICATE-----\n" // AAA Certificate Services (authserver.ely.by GH#4832) // Downloaded from https://www.tbs-certificates.co.uk/FAQ/en/Comodo_AAA_Certificate_Services.html "-----BEGIN CERTIFICATE-----\n" "MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEb\n" "MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow\n" "GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmlj\n" "YXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVowezEL\n" "MAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE\n" "BwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNVBAMM\n" "GEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEP\n" "ADCCAQoCggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQua\n" "BtDFcCLNSS1UY8y2bmhGC1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe\n" "3M/vg4aijJRPn2jymJBGhCfHdr/jzDUsi14HZGWCwEiwqJH5YZ92IFCokcdmtet4\n" "YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszWY19zjNoFmag4qMsXeDZR\n" "rOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjHYpy+g8cm\n" "ez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQU\n" "oBEKIz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF\n" "MAMBAf8wewYDVR0fBHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20v\n" "QUFBQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29t\n" "b2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2VzLmNybDANBgkqhkiG9w0BAQUF\n" "AAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm7l3sAg9g1o1Q\n" "GE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz\n" "Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2\n" "G9w84FoVxp7Z8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsi\n" "l2D4kF501KKaU73yqWjgom7C12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3\n" "smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg==\n" "-----END CERTIFICATE-----\n" ; static const AStringMap UrlClientOptions = {{"TrustedRootCAs", CertString}}; return UrlClientOptions; } } //////////////////////////////////////////////////////////////////////////////// // cMojangAPI::sProfile: cMojangAPI::sProfile::sProfile( const AString & a_PlayerName, const cUUID & a_UUID, const Json::Value & a_Properties, Int64 a_DateTime ) : m_PlayerName(a_PlayerName), m_UUID(a_UUID), m_Textures(), m_TexturesSignature(), m_DateTime(a_DateTime) { /* Example a_Profile contents: "properties": [ { "name": "textures", "value": "eyJ0aW1lc3RhbXAiOjE0MDcwNzAzMjEyNzEsInByb2ZpbGVJZCI6ImIxY2FmMjQyMDJhODQxYTc4MDU1YTA3OWM0NjBlZWU3IiwicHJvZmlsZU5hbWUiOiJ4b2Z0IiwiaXNQdWJsaWMiOnRydWUsInRleHR1cmVzIjp7IlNLSU4iOnsidXJsIjoiaHR0cDovL3RleHR1cmVzLm1pbmVjcmFmdC5uZXQvdGV4dHVyZS9iNzc5YmFiZjVhNTg3Zjk0OGFkNjc0N2VhOTEyNzU0MjliNjg4Mjk1YWUzYzA3YmQwZTJmNWJmNGQwNTIifX19", "signature": "XCty+jGEF39hEPrPhYNnCX087kPaoCjYruzYI/DS4nkL5hbjnkSM5Rh15hnUyv/FHhC8OF5rif3D1tQjtMI19KSVaXoUFXpbJM8/+PB8GDgEbX8Fc3u9nYkzOcM/xfxdYsFAdFhLQMkvase/BZLSuPhdy9DdI+TCrO7xuSTZfYmmwVuWo3w5gCY+mSIAnqltnOzaOOTcly75xvO0WYpVk7nJdnR2tvSi0wfrQPDrIg/uzhX7p0SnDqijmBU4QaNez/TNKiFxy69dAzt0RSotlQzqkDbyVKhhv9a4eY8h3pXi4UMftKEj4FAKczxLImkukJXuOn5NN15/Q+le0rJVBC60/xjKIVzltEsMN6qjWD0lQjey7WEL+4pGhCVuWY5KzuZjFvgqszuJTFz7lo+bcHiceldJtea8/fa02eTRObZvdLxbWC9ZfFY0IhpOVKfcLdno/ddDMNMQMi5kMrJ8MZZ/PcW1w5n7MMGWPGCla1kOaC55AL0QYSMGRVEZqgU9wXI5M7sHGZKGM4mWxkbEJYBkpI/p3GyxWgV6v33ZWlsz65TqlNrR1gCLaoFCm7Sif8NqPBZUAONHYon0roXhin/DyEanS93WV6i6FC1Wisscjq2AcvnOlgTo/5nN/1QsMbjNumuMGo37sqjRqlXoPb8zEUbAhhztYuJjEfQ2Rd8=" } ] */ // Parse the Textures and TexturesSignature from the Profile: if (!a_Properties.isArray()) { // Properties is not a valid array, bail out return; } Json::UInt Size = a_Properties.size(); for (Json::UInt i = 0; i < Size; i++) { const Json::Value & Prop = a_Properties[i]; if (Prop.get("name", "").asString() != "textures") { continue; } m_Textures = Prop.get("value", "").asString(); m_TexturesSignature = Prop.get("signature", "").asString(); break; } // for i - Properties[] } //////////////////////////////////////////////////////////////////////////////// // cMojangAPI::cUpdateThread: class cMojangAPI::cUpdateThread: public cIsThread { using Super = cIsThread; public: cUpdateThread(cMojangAPI & a_MojangAPI): Super("MojangAPI Updater"), m_MojangAPI(a_MojangAPI) { } virtual ~cUpdateThread() override { // Notify the thread that it should stop: m_ShouldTerminate = true; m_evtNotify.Set(); // Wait for the thread to actually finish work: Stop(); } protected: /** The cMojangAPI instance to update. */ cMojangAPI & m_MojangAPI; /** The event used for notifying that the thread should terminate, as well as timing. */ cEvent m_evtNotify; // cIsThread override: virtual void Execute(void) override { do { m_MojangAPI.Update(); } while (!m_ShouldTerminate && !m_evtNotify.Wait(60 * 60 * 1000)); // Repeat every 60 minutes until termination request } } ; //////////////////////////////////////////////////////////////////////////////// // cMojangAPI: cMojangAPI::cMojangAPI(): m_RankMgr(nullptr), m_UpdateThread(new cUpdateThread(*this)) { } cMojangAPI::~cMojangAPI() { SaveCachesToDisk(); } void cMojangAPI::Start(cSettingsRepositoryInterface & a_Settings, bool a_ShouldAuth) { auto NameToUUIDServer = a_Settings.GetValueSet("MojangAPI", "NameToUUIDServer", DEFAULT_NAME_TO_UUID_SERVER); auto NameToUUIDAddress = a_Settings.GetValueSet("MojangAPI", "NameToUUIDAddress", DEFAULT_NAME_TO_UUID_ADDRESS); auto UUIDToProfileServer = a_Settings.GetValueSet("MojangAPI", "UUIDToProfileServer", DEFAULT_UUID_TO_PROFILE_SERVER); auto UUIDToProfileAddress = a_Settings.GetValueSet("MojangAPI", "UUIDToProfileAddress", DEFAULT_UUID_TO_PROFILE_ADDRESS); m_NameToUUIDUrl = "https://" + NameToUUIDServer + NameToUUIDAddress; m_UUIDToProfileUrl = "https://" + UUIDToProfileServer + UUIDToProfileAddress; LoadCachesFromDisk(); if (a_ShouldAuth) { m_UpdateThread->Start(); } } cUUID cMojangAPI::GetUUIDFromPlayerName(const AString & a_PlayerName, bool a_UseOnlyCached) { // Convert the playername to lowercase: AString lcPlayerName = StrToLower(a_PlayerName); // Request the cache to query the name if not yet cached: if (!a_UseOnlyCached) { AStringVector PlayerNames{ lcPlayerName }; CacheNamesToUUIDs(PlayerNames); } // Retrieve from cache: cCSLock Lock(m_CSNameToUUID); cProfileMap::const_iterator itr = m_NameToUUID.find(lcPlayerName); if (itr == m_NameToUUID.end()) { // No UUID found return {}; } return itr->second.m_UUID; } AString cMojangAPI::GetPlayerNameFromUUID(const cUUID & a_UUID, bool a_UseOnlyCached) { // Retrieve from caches: { cCSLock Lock(m_CSUUIDToProfile); auto itr = m_UUIDToProfile.find(a_UUID); if (itr != m_UUIDToProfile.end()) { return itr->second.m_PlayerName; } } { cCSLock Lock(m_CSUUIDToName); auto itr = m_UUIDToName.find(a_UUID); if (itr != m_UUIDToName.end()) { return itr->second.m_PlayerName; } } // Name not yet cached, request cache and retry: if (!a_UseOnlyCached) { CacheUUIDToProfile(a_UUID); return GetPlayerNameFromUUID(a_UUID, true); } // No value found, none queried. Return an error: return {}; } std::vector cMojangAPI::GetUUIDsFromPlayerNames(const AStringVector & a_PlayerNames, bool a_UseOnlyCached) { // Convert all playernames to lowercase: AStringVector PlayerNames; for (AStringVector::const_iterator itr = a_PlayerNames.begin(), end = a_PlayerNames.end(); itr != end; ++itr) { PlayerNames.push_back(StrToLower(*itr)); } // for itr - a_PlayerNames[] // Request the cache to populate any names not yet contained: if (!a_UseOnlyCached) { CacheNamesToUUIDs(PlayerNames); } // Retrieve from cache: size_t idx = 0; std::vector res; res.resize(PlayerNames.size()); cCSLock Lock(m_CSNameToUUID); for (AStringVector::const_iterator itr = PlayerNames.begin(), end = PlayerNames.end(); itr != end; ++itr, ++idx) { cProfileMap::const_iterator itrN = m_NameToUUID.find(*itr); if (itrN != m_NameToUUID.end()) { res[idx] = itrN->second.m_UUID; } } // for itr - PlayerNames[] return res; } void cMojangAPI::AddPlayerNameToUUIDMapping(const AString & a_PlayerName, const cUUID & a_UUID) { Int64 Now = time(nullptr); { cCSLock Lock(m_CSNameToUUID); m_NameToUUID[StrToLower(a_PlayerName)] = sProfile(a_PlayerName, a_UUID, "", "", Now); } { cCSLock Lock(m_CSUUIDToName); m_UUIDToName[a_UUID] = sProfile(a_PlayerName, a_UUID, "", "", Now); } NotifyNameUUID(a_PlayerName, a_UUID); } void cMojangAPI::AddPlayerProfile(const AString & a_PlayerName, const cUUID & a_UUID, const Json::Value & a_Properties) { Int64 Now = time(nullptr); { cCSLock Lock(m_CSNameToUUID); m_NameToUUID[StrToLower(a_PlayerName)] = sProfile(a_PlayerName, a_UUID, "", "", Now); } { cCSLock Lock(m_CSUUIDToName); m_UUIDToName[a_UUID] = sProfile(a_PlayerName, a_UUID, "", "", Now); } { cCSLock Lock(m_CSUUIDToProfile); m_UUIDToProfile[a_UUID] = sProfile(a_PlayerName, a_UUID, a_Properties, Now); } NotifyNameUUID(a_PlayerName, a_UUID); } void cMojangAPI::LoadCachesFromDisk(void) { try { // Open up the SQLite DB: SQLite::Database db("MojangAPI.sqlite", SQLite::OPEN_READWRITE | SQLite::OPEN_CREATE); db.exec("CREATE TABLE IF NOT EXISTS PlayerNameToUUID (PlayerName, UUID, DateTime)"); db.exec("CREATE TABLE IF NOT EXISTS UUIDToProfile (UUID, PlayerName, Textures, TexturesSignature, DateTime)"); // Retrieve all entries: { SQLite::Statement stmt(db, "SELECT PlayerName, UUID, DateTime FROM PlayerNameToUUID"); while (stmt.executeStep()) { AString PlayerName = stmt.getColumn(0).getString(); AString StringUUID = stmt.getColumn(1).getString(); Int64 DateTime = stmt.getColumn(2).getInt64(); cUUID UUID; if (!UUID.FromString(StringUUID)) { continue; // Invalid UUID } m_NameToUUID[StrToLower(PlayerName)] = sProfile(PlayerName, UUID, "", "", DateTime); m_UUIDToName[UUID] = sProfile(PlayerName, UUID, "", "", DateTime); } } { SQLite::Statement stmt(db, "SELECT PlayerName, UUID, Textures, TexturesSignature, DateTime FROM UUIDToProfile"); while (stmt.executeStep()) { AString PlayerName = stmt.getColumn(0).getString(); AString StringUUID = stmt.getColumn(1).getString(); AString Textures = stmt.getColumn(2).getString(); AString TexturesSignature = stmt.getColumn(2).getString(); Int64 DateTime = stmt.getColumn(4).getInt64(); cUUID UUID; if (!UUID.FromString(StringUUID)) { continue; // Invalid UUID } m_UUIDToProfile[UUID] = sProfile(PlayerName, UUID, Textures, TexturesSignature, DateTime); } } } catch (const SQLite::Exception & ex) { LOGINFO("Loading MojangAPI cache failed: %s", ex.what()); } } void cMojangAPI::SaveCachesToDisk(void) { try { // Open up the SQLite DB: SQLite::Database db("MojangAPI.sqlite", SQLite::OPEN_READWRITE | SQLite::OPEN_CREATE); db.exec("CREATE TABLE IF NOT EXISTS PlayerNameToUUID (PlayerName, UUID, DateTime)"); db.exec("CREATE TABLE IF NOT EXISTS UUIDToProfile (UUID, PlayerName, Textures, TexturesSignature, DateTime)"); // Remove all entries: db.exec("DELETE FROM PlayerNameToUUID"); db.exec("DELETE FROM UUIDToProfile"); // Save all cache entries - m_PlayerNameToUUID: Int64 LimitDateTime = time(nullptr) - MAX_AGE; { SQLite::Statement stmt(db, "INSERT INTO PlayerNameToUUID(PlayerName, UUID, DateTime) VALUES (?, ?, ?)"); cCSLock Lock(m_CSNameToUUID); for (auto & NameToUUID : m_NameToUUID) { auto & Profile = NameToUUID.second; if (Profile.m_DateTime < LimitDateTime) { // This item is too old, do not save continue; } stmt.bind(1, Profile.m_PlayerName); stmt.bind(2, Profile.m_UUID.ToShortString()); stmt.bind(3, static_cast(Profile.m_DateTime)); stmt.exec(); stmt.reset(); } } // Save all cache entries - m_UUIDToProfile: { SQLite::Statement stmt(db, "INSERT INTO UUIDToProfile(UUID, PlayerName, Textures, TexturesSignature, DateTime) VALUES (?, ?, ?, ?, ?)"); cCSLock Lock(m_CSUUIDToProfile); for (auto & UUIDToProfile : m_UUIDToProfile) { auto & Profile = UUIDToProfile.second; if (Profile.m_DateTime < LimitDateTime) { // This item is too old, do not save continue; } stmt.bind(1, Profile.m_UUID.ToShortString()); stmt.bind(2, Profile.m_PlayerName); stmt.bind(3, Profile.m_Textures); stmt.bind(4, Profile.m_TexturesSignature); stmt.bind(5, static_cast(Profile.m_DateTime)); stmt.exec(); stmt.reset(); } } } catch (const SQLite::Exception & ex) { LOGINFO("Saving MojangAPI cache failed: %s", ex.what()); } } void cMojangAPI::CacheNamesToUUIDs(const AStringVector & a_PlayerNames) { // Create a list of names to query, by removing those that are already cached: AStringVector NamesToQuery; NamesToQuery.reserve(a_PlayerNames.size()); { cCSLock Lock(m_CSNameToUUID); for (AStringVector::const_iterator itr = a_PlayerNames.begin(), end = a_PlayerNames.end(); itr != end; ++itr) { if (m_NameToUUID.find(*itr) == m_NameToUUID.end()) { NamesToQuery.push_back(*itr); } } // for itr - a_PlayerNames[] } // Lock(m_CSNameToUUID) QueryNamesToUUIDs(NamesToQuery); } void cMojangAPI::QueryNamesToUUIDs(AStringVector & a_NamesToQuery) { while (!a_NamesToQuery.empty()) { // Create the request body - a JSON containing up to MAX_PER_QUERY playernames: Json::Value root; int Count = 0; auto itr = a_NamesToQuery.begin(); auto end = a_NamesToQuery.end(); for (; (itr != end) && (Count < MAX_PER_QUERY); ++itr, ++Count) { Json::Value req(*itr); root.append(req); } // for itr - a_PlayerNames[] a_NamesToQuery.erase(a_NamesToQuery.begin(), itr); auto RequestBody = JsonUtils::WriteFastString(root); // Create and send the HTTP request auto [IsSuccessful, Response] = cUrlClient::BlockingPost(m_NameToUUIDUrl, {}, std::move(RequestBody), MojangTrustedRootCAs::UrlClientOptions()); if (!IsSuccessful) { continue; } AString HexDump; // Parse the returned string into Json: AString ParseError; if (!JsonUtils::ParseString(Response, root, &ParseError) || !root.isArray()) { LOGWARNING("%s failed: Cannot parse received data (NameToUUID) to JSON: \"%s\"", __METHOD_NAME__, ParseError); LOGD("Response body:\n%s", CreateHexDump(HexDump, Response.data(), Response.size(), 16)); continue; } // Store the returned results into cache: Json::Value::UInt JsonCount = root.size(); Int64 Now = time(nullptr); { cCSLock Lock(m_CSNameToUUID); for (Json::Value::UInt idx = 0; idx < JsonCount; ++idx) { Json::Value & Val = root[idx]; AString JsonName = Val.get("name", "").asString(); cUUID JsonUUID; if (!JsonUUID.FromString(Val.get("id", "").asString())) { continue; } m_NameToUUID[StrToLower(JsonName)] = sProfile(JsonName, JsonUUID, "", "", Now); NotifyNameUUID(JsonName, JsonUUID); } // for idx - root[] } // cCSLock (m_CSNameToUUID) // Also cache the UUIDToName: { cCSLock Lock(m_CSUUIDToName); for (Json::Value::UInt idx = 0; idx < JsonCount; ++idx) { Json::Value & Val = root[idx]; AString JsonName = Val.get("name", "").asString(); cUUID JsonUUID; if (!JsonUUID.FromString(Val.get("id", "").asString())) { continue; } m_UUIDToName[JsonUUID] = sProfile(JsonName, JsonUUID, "", "", Now); } // for idx - root[] } } // while (!NamesToQuery.empty()) } void cMojangAPI::CacheUUIDToProfile(const cUUID & a_UUID) { // Check if already present: { cCSLock Lock(m_CSUUIDToProfile); if (m_UUIDToProfile.find(a_UUID) != m_UUIDToProfile.end()) { return; } } QueryUUIDToProfile(a_UUID); } void cMojangAPI::QueryUUIDToProfile(const cUUID & a_UUID) { // Create and send the HTTP request auto Url = m_UUIDToProfileUrl; ReplaceString(Url, "%UUID%", URLEncode(a_UUID.ToShortString())); auto [IsSuccessful, Response] = cUrlClient::BlockingGet(Url, {}, {}, MojangTrustedRootCAs::UrlClientOptions()); if (!IsSuccessful) { return; } // Parse the returned string into Json: Json::Value root; AString ParseError; if (!JsonUtils::ParseString(Response, root, &ParseError) || !root.isObject()) { LOGWARNING("%s failed: Cannot parse received data (NameToUUID) to JSON: \"%s\"", __FUNCTION__, ParseError); #ifdef NDEBUG AString HexDump; LOGD("Response body:\n%s", CreateHexDump(HexDump, Response.data(), Response.size(), 16).c_str()); #endif return; } /* Example response: { "id": "b1caf24202a841a78055a079c460eee7", "name": "xoft", "properties": [ { "name": "textures", "value": "eyJ0aW1lc3RhbXAiOjE0MDcwNzAzMjEyNzEsInByb2ZpbGVJZCI6ImIxY2FmMjQyMDJhODQxYTc4MDU1YTA3OWM0NjBlZWU3IiwicHJvZmlsZU5hbWUiOiJ4b2Z0IiwiaXNQdWJsaWMiOnRydWUsInRleHR1cmVzIjp7IlNLSU4iOnsidXJsIjoiaHR0cDovL3RleHR1cmVzLm1pbmVjcmFmdC5uZXQvdGV4dHVyZS9iNzc5YmFiZjVhNTg3Zjk0OGFkNjc0N2VhOTEyNzU0MjliNjg4Mjk1YWUzYzA3YmQwZTJmNWJmNGQwNTIifX19", "signature": "XCty+jGEF39hEPrPhYNnCX087kPaoCjYruzYI/DS4nkL5hbjnkSM5Rh15hnUyv/FHhC8OF5rif3D1tQjtMI19KSVaXoUFXpbJM8/+PB8GDgEbX8Fc3u9nYkzOcM/xfxdYsFAdFhLQMkvase/BZLSuPhdy9DdI+TCrO7xuSTZfYmmwVuWo3w5gCY+mSIAnqltnOzaOOTcly75xvO0WYpVk7nJdnR2tvSi0wfrQPDrIg/uzhX7p0SnDqijmBU4QaNez/TNKiFxy69dAzt0RSotlQzqkDbyVKhhv9a4eY8h3pXi4UMftKEj4FAKczxLImkukJXuOn5NN15/Q+le0rJVBC60/xjKIVzltEsMN6qjWD0lQjey7WEL+4pGhCVuWY5KzuZjFvgqszuJTFz7lo+bcHiceldJtea8/fa02eTRObZvdLxbWC9ZfFY0IhpOVKfcLdno/ddDMNMQMi5kMrJ8MZZ/PcW1w5n7MMGWPGCla1kOaC55AL0QYSMGRVEZqgU9wXI5M7sHGZKGM4mWxkbEJYBkpI/p3GyxWgV6v33ZWlsz65TqlNrR1gCLaoFCm7Sif8NqPBZUAONHYon0roXhin/DyEanS93WV6i6FC1Wisscjq2AcvnOlgTo/5nN/1QsMbjNumuMGo37sqjRqlXoPb8zEUbAhhztYuJjEfQ2Rd8=" } ] } */ // Store the returned result into caches: AString PlayerName = root.get("name", "").asString(); if (PlayerName.empty()) { // No valid playername, bail out return; } Json::Value Properties = root.get("properties", ""); Int64 Now = time(nullptr); { cCSLock Lock(m_CSUUIDToProfile); m_UUIDToProfile[a_UUID] = sProfile(PlayerName, a_UUID, Properties, Now); } { cCSLock Lock(m_CSUUIDToName); m_UUIDToName[a_UUID] = sProfile(PlayerName, a_UUID, Properties, Now); } { cCSLock Lock(m_CSNameToUUID); m_NameToUUID[StrToLower(PlayerName)] = sProfile(PlayerName, a_UUID, Properties, Now); } NotifyNameUUID(PlayerName, a_UUID); } void cMojangAPI::NotifyNameUUID(const AString & a_PlayerName, const cUUID & a_UUID) { // Notify the rank manager: cCSLock Lock(m_CSRankMgr); if (m_RankMgr != nullptr) { m_RankMgr->NotifyNameUUID(a_PlayerName, a_UUID); } } void cMojangAPI::Update(void) { Int64 LimitDateTime = time(nullptr) - MAX_AGE; // Re-query all playernames that are stale: AStringVector PlayerNames; { cCSLock Lock(m_CSNameToUUID); for (const auto & NameToUUID : m_NameToUUID) { if (NameToUUID.second.m_DateTime < LimitDateTime) { PlayerNames.push_back(NameToUUID.first); } } // for itr - m_NameToUUID[] } if (!PlayerNames.empty()) { LOG("%s: Updating name-to-uuid cache for %u names", __METHOD_NAME__, static_cast(PlayerNames.size())); QueryNamesToUUIDs(PlayerNames); } // Re-query all profiles that are stale: std::vector ProfileUUIDs; { cCSLock Lock(m_CSUUIDToProfile); for (const auto & UUIDToProfile : m_UUIDToProfile) { if (UUIDToProfile.second.m_DateTime < LimitDateTime) { ProfileUUIDs.push_back(UUIDToProfile.first); } } // for itr - m_UUIDToProfile[] } if (!ProfileUUIDs.empty()) { LOG("%s: Updating uuid-to-profile cache for %u uuids", __METHOD_NAME__, static_cast(ProfileUUIDs.size())); for (const auto & UUID : ProfileUUIDs) { QueryUUIDToProfile(UUID); } } } ================================================ FILE: src/Protocol/MojangAPI.h ================================================ // MojangAPI.h // Declares the cMojangAPI class representing the various API points provided by Mojang's webservices, and a cache for their results #pragma once #include #include "UUID.h" // fwd: ../RankManager.h" class cRankManager; namespace Json { class Value; } class cSettingsRepositoryInterface; // tolua_begin class cMojangAPI { public: // tolua_end cMojangAPI(void); ~cMojangAPI(); /** Initializes the API; reads the settings from the specified ini file. Loads cached results from disk. */ void Start(cSettingsRepositoryInterface & a_Settings, bool a_ShouldAuth); /** Converts a player name into a UUID. The UUID will be nil on error. If a_UseOnlyCached is true, the function only consults the cached values. If a_UseOnlyCached is false and the name is not found in the cache, it is looked up online, which is a blocking operation, do not use this in world-tick thread! If you have multiple names to resolve, use the GetUUIDsFromPlayerNames() function, it uses a single request for multiple names. */ cUUID GetUUIDFromPlayerName(const AString & a_PlayerName, bool a_UseOnlyCached = false); /** Converts a UUID into a playername. The returned playername will be empty on error. Uses both m_UUIDToName and m_UUIDToProfile to search for the value. Uses m_UUIDToProfile for cache. If a_UseOnlyCached is true, the function only consults the cached values. If a_UseOnlyCached is false and the name is not found in the cache, it is looked up online, which is a blocking operation, do not use this in world-tick thread! */ AString GetPlayerNameFromUUID(const cUUID & a_UUID, bool a_UseOnlyCached = false); /** Converts the player names into UUIDs. a_PlayerName[idx] will be converted to UUID and returned as idx-th value The UUID will be nil on error. If a_UseOnlyCached is true, only the cached values are returned. If a_UseOnlyCached is false, the names not found in the cache are looked up online, which is a blocking operation, do not use this in world-tick thread! */ std::vector GetUUIDsFromPlayerNames(const AStringVector & a_PlayerName, bool a_UseOnlyCached = false); /** Called by the Authenticator to add a PlayerName -> UUID mapping that it has received from authenticating a user. This adds the cache item and "refreshes" it if existing, adjusting its datetime stamp to now. */ void AddPlayerNameToUUIDMapping(const AString & a_PlayerName, const cUUID & a_UUID); /** Called by the Authenticator to add a profile that it has received from authenticating a user. Adds the profile to the respective mapping caches and updtes their datetime stamp to now. */ void AddPlayerProfile(const AString & a_PlayerName, const cUUID & a_UUID, const Json::Value & a_Properties); /** Sets the m_RankMgr that is used for name-uuid notifications. Accepts nullptr to remove the binding. */ void SetRankManager(cRankManager * a_RankManager) { m_RankMgr = a_RankManager; } protected: /** The thread that periodically checks for stale data and re-queries it from the server. */ class cUpdateThread; /** Holds data for a single player profile. */ struct sProfile { AString m_PlayerName; // Case-correct playername cUUID m_UUID; // Player UUID AString m_Textures; // The Textures field of the profile properties AString m_TexturesSignature; // The signature of the Textures field of the profile properties Int64 m_DateTime; // UNIXtime of the profile lookup /** Default constructor for the container's sake. */ sProfile(void) : m_PlayerName(), m_UUID(), m_Textures(), m_TexturesSignature(), m_DateTime(time(nullptr)) { } /** Constructor for the storage creation. */ sProfile( const AString & a_PlayerName, const cUUID & a_UUID, const AString & a_Textures, const AString & a_TexturesSignature, Int64 a_DateTime ) : m_PlayerName(a_PlayerName), m_UUID(a_UUID), m_Textures(a_Textures), m_TexturesSignature(a_TexturesSignature), m_DateTime(a_DateTime) { } /** Constructor that parses the values from the Json profile. */ sProfile( const AString & a_PlayerName, const cUUID & a_UUID, const Json::Value & a_Properties, Int64 a_DateTime ); }; using cProfileMap = std::map; using cUUIDProfileMap = std::map; /** The full URL to check when converting player names to UUIDs. For example: "https://api.mojang.com/profiles/page/1". */ AString m_NameToUUIDUrl; /** The full URL to use for converting UUID to profile. %UUID% will get replaced with the actual UUID. For example "https://sessionserver.mojang.com/session/minecraft/profile/%UUID%?unsigned=false". */ AString m_UUIDToProfileUrl; /** Cache for the Name-to-UUID lookups. The map key is lowercased PlayerName. Protected by m_CSNameToUUID. */ cProfileMap m_NameToUUID; /** Protects m_NameToUUID against simultaneous multi-threaded access. */ cCriticalSection m_CSNameToUUID; /** Cache for the Name-to-UUID lookups. The map key is lowercased short UUID. Protected by m_CSUUIDToName. */ cUUIDProfileMap m_UUIDToName; /** Protects m_UUIDToName against simultaneous multi-threaded access. */ cCriticalSection m_CSUUIDToName; /** Cache for the UUID-to-profile lookups. The map key is lowercased short UUID. Protected by m_CSUUIDToProfile. */ cUUIDProfileMap m_UUIDToProfile; /** Protects m_UUIDToProfile against simultaneous multi-threaded access. */ cCriticalSection m_CSUUIDToProfile; /** The rank manager that is notified of the name-uuid pairings. May be nullptr. Protected by m_CSRankMgr. */ cRankManager * m_RankMgr; /** Protects m_RankMgr agains simultaneous multi-threaded access. */ cCriticalSection m_CSRankMgr; /** The thread that periodically updates the stale data in the DB from the Mojang servers. */ std::shared_ptr m_UpdateThread; /** Loads the caches from a disk storage. */ void LoadCachesFromDisk(void); /** Saves the caches to a disk storage. */ void SaveCachesToDisk(void); /** Makes sure all specified names are in the m_PlayerNameToUUID cache. Downloads any missing ones from Mojang API servers. Names that are not valid are not added into the cache. ASSUMEs that a_PlayerNames contains lowercased player names. */ void CacheNamesToUUIDs(const AStringVector & a_PlayerNames); /** Queries all the specified names and stores them into the m_PlayerNameToUUID cache. Names that are not valid are not added into the cache. ASSUMEs that a_PlayerNames contans lowercased player names. For performance reasons takes a non-const reference and modifies the list given to it, until empty. */ void QueryNamesToUUIDs(AStringVector & a_PlayerNames); /** Makes sure the specified UUID is in the m_UUIDToProfile cache. If missing, downloads it from Mojang API servers. UUIDs that are not valid will not be added into the cache. */ void CacheUUIDToProfile(const cUUID & a_UUID); /** Queries the specified UUID's profile and stores it in the m_UUIDToProfile cache. If already present, updates the cache entry. UUIDs that are not valid will not be added into the cache. */ void QueryUUIDToProfile(const cUUID & a_UUID); /** Called for each name-uuid pairing that is discovered. If assigned, notifies the m_RankManager of the event. */ void NotifyNameUUID(const AString & a_PlayerName, const cUUID & a_PlayerUUID); /** Updates the stale values in the DB from the Mojang servers. Called from the cUpdateThread, blocks on the HTTPS API calls. */ void Update(void); } ; // tolua_export ================================================ FILE: src/Protocol/Packetizer.cpp ================================================ // Packetizer.cpp // Implements the cPacketizer class representing a wrapper for sending a single packet over a protocol. #include "Globals.h" #include "Packetizer.h" #include "../UUID.h" //////////////////////////////////////////////////////////////////////////////// // cPacketizer: cPacketizer::~cPacketizer() { m_Protocol.SendPacket(*this); } void cPacketizer::WriteByteAngle(double a_Angle) { WriteBEInt8(static_cast(255 * a_Angle / 360)); } void cPacketizer::WriteFPInt(double a_Value) { WriteBEInt32(static_cast(a_Value * 32)); } void cPacketizer::WriteUUID(const cUUID & a_UUID) { for (auto val : a_UUID.ToRaw()) { VERIFY(m_Out.WriteBEUInt8(val)); } } AString cPacketizer::PacketTypeToStr(cProtocol::ePacketType a_PacketType) { switch (a_PacketType) { case cProtocol::pktAttachEntity: return "pktAttachEntity"; case cProtocol::pktBlockAction: return "pktBlockAction"; case cProtocol::pktBlockBreakAnim: return "pktBlockBreakAnim"; case cProtocol::pktBlockChange: return "pktBlockChange"; case cProtocol::pktBlockChanges: return "pktBlockChanges"; case cProtocol::pktBossBar: return "pktBossBar"; case cProtocol::pktCameraSetTo: return "pktCameraSetTo"; case cProtocol::pktChatRaw: return "pktChatRaw"; case cProtocol::pktCollectEntity: return "pktCollectEntity"; case cProtocol::pktDestroyEntity: return "pktDestroyEntity"; case cProtocol::pktDifficulty: return "pktDifficulty"; case cProtocol::pktDisconnectDuringLogin: return "pktDisconnectDuringLogin"; case cProtocol::pktDisconnectDuringGame: return "pktDisconnectDuringGame"; case cProtocol::pktDisplayObjective: return "pktDisplayObjective"; case cProtocol::pktEditSign: return "pktEditSign"; case cProtocol::pktEncryptionRequest: return "pktEncryptionRequest"; case cProtocol::pktEntityAnimation: return "pktEntityAnimation"; case cProtocol::pktEntityEffect: return "pktEntityEffect"; case cProtocol::pktEntityEquipment: return "pktEntityEquipment"; case cProtocol::pktEntityHeadLook: return "pktEntityHeadLook"; case cProtocol::pktEntityLook: return "pktEntityLook"; case cProtocol::pktEntityMeta: return "pktEntityMeta"; case cProtocol::pktEntityProperties: return "pktEntityProperties"; case cProtocol::pktEntityRelMove: return "pktEntityRelMove"; case cProtocol::pktEntityRelMoveLook: return "pktEntityRelMoveLook"; case cProtocol::pktEntityStatus: return "pktEntityStatus"; case cProtocol::pktEntityVelocity: return "pktEntityVelocity"; case cProtocol::pktExperience: return "pktExperience"; case cProtocol::pktExplosion: return "pktExplosion"; case cProtocol::pktGameMode: return "pktGameMode"; case cProtocol::pktHeldItemChange: return "pktHeldItemChange"; case cProtocol::pktHorseWindowOpen: return "pktHorseWindowOpen"; case cProtocol::pktInventorySlot: return "pktInventorySlot"; case cProtocol::pktJoinGame: return "pktJoinGame"; case cProtocol::pktKeepAlive: return "pktKeepAlive"; case cProtocol::pktLeashEntity: return "pktLeashEntity"; case cProtocol::pktLoginSuccess: return "pktLoginSuccess"; case cProtocol::pktMapData: return "pktMapData"; case cProtocol::pktParticleEffect: return "pktParticleEffect"; case cProtocol::pktPingResponse: return "pktPingResponse"; case cProtocol::pktPlayerAbilities: return "pktPlayerAbilities"; case cProtocol::pktPlayerList: return "pktPlayerList"; case cProtocol::pktPlayerListHeaderFooter: return "pktPlayerListHeaderFooter"; case cProtocol::pktPlayerMoveLook: return "pktPlayerMoveLook"; case cProtocol::pktPluginMessage: return "pktPluginMessage"; case cProtocol::pktRemoveEntityEffect: return "pktRemoveEntityEffect"; case cProtocol::pktResourcePack: return "pktResourcePack"; case cProtocol::pktRespawn: return "pktRespawn"; case cProtocol::pktScoreboardObjective: return "pktScoreboardObjective"; case cProtocol::pktSpawnObject: return "pktSpawnObject"; case cProtocol::pktSoundEffect: return "pktSoundEffect"; case cProtocol::pktSoundParticleEffect: return "pktSoundParticleEffect"; case cProtocol::pktSpawnExperienceOrb: return "pktSpawnExperienceOrb"; case cProtocol::pktSpawnGlobalEntity: return "pktSpawnGlobalEntity"; case cProtocol::pktSpawnMob: return "pktSpawnMob"; case cProtocol::pktSpawnOtherPlayer: return "pktSpawnOtherPlayer"; case cProtocol::pktSpawnPainting: return "pktSpawnPainting"; case cProtocol::pktSpawnPosition: return "pktSpawnPosition"; case cProtocol::pktStartCompression: return "pktStartCompression"; case cProtocol::pktStatistics: return "pktStatistics"; case cProtocol::pktStatusResponse: return "pktStatusResponse"; case cProtocol::pktTabCompletionResults: return "pktTabCompletionResults"; case cProtocol::pktTeleportEntity: return "pktTeleportEntity"; case cProtocol::pktTimeUpdate: return "pktTimeUpdate"; case cProtocol::pktTitle: return "pktTitle"; case cProtocol::pktUnloadChunk: return "pktUnloadChunk"; case cProtocol::pktUnlockRecipe: return "pktUnlockRecipe"; case cProtocol::pktUpdateBlockEntity: return "pktUpdateBlockEntity"; case cProtocol::pktUpdateHealth: return "pktUpdateHealth"; case cProtocol::pktUpdateScore: return "pktUpdateScore"; case cProtocol::pktUpdateSign: return "pktUpdateSign"; case cProtocol::pktUseBed: return "pktUseBed"; case cProtocol::pktWeather: return "pktWeather"; case cProtocol::pktWindowItems: return "pktWindowItems"; case cProtocol::pktWindowClose: return "pktWindowClose"; case cProtocol::pktWindowOpen: return "pktWindowOpen"; case cProtocol::pktWindowProperty: return "pktWindowProperty"; } return fmt::format(FMT_STRING("Unknown packet type: 0x{:02x}"), a_PacketType); } ================================================ FILE: src/Protocol/Packetizer.h ================================================ // Packetizer.h // Declares the cPacketizer class representing a wrapper for sending a single packet over a protocol. // The class provides auto-locking, serialization and send-on-instance-destroy semantics #pragma once #include "Protocol.h" class cByteBuffer; // fwd: class cUUID; /** Macros used to read packets more easily */ #define HANDLE_READ(ByteBuf, Proc, Type, Var) \ Type Var; \ do { \ if (!ByteBuf.Proc(Var))\ {\ return;\ } \ } while (false) #define HANDLE_PACKET_READ(ByteBuf, Proc, Type, Var) \ Type Var; \ do { \ { \ if (!ByteBuf.Proc(Var)) \ { \ ByteBuf.CheckValid(); \ return false; \ } \ ByteBuf.CheckValid(); \ } \ } while (false) /** Composes an individual packet in the protocol's m_OutPacketBuffer; sends it just before being destructed. */ class cPacketizer { public: /** Starts serializing a new packet into the protocol's m_OutPacketBuffer. Locks the protocol's m_CSPacket to avoid multithreading issues. */ cPacketizer(cProtocol & a_Protocol, cProtocol::ePacketType a_PacketType) : m_Protocol(a_Protocol), m_Out(a_Protocol.m_OutPacketBuffer), m_Lock(a_Protocol.m_CSPacket), m_PacketType(a_PacketType) // Used for logging purposes { m_Out.WriteVarInt32(m_Protocol.GetPacketID(a_PacketType)); } /** Sends the packet via the contained protocol's SendPacket() function. */ ~cPacketizer(); inline void WriteBool(bool a_Value) { VERIFY(m_Out.WriteBool(a_Value)); } inline void WriteBEUInt8(UInt8 a_Value) { VERIFY(m_Out.WriteBEUInt8(a_Value)); } inline void WriteBEInt8(Int8 a_Value) { VERIFY(m_Out.WriteBEInt8(a_Value)); } inline void WriteBEInt16(Int16 a_Value) { VERIFY(m_Out.WriteBEInt16(a_Value)); } inline void WriteBEUInt16(UInt16 a_Value) { VERIFY(m_Out.WriteBEUInt16(a_Value)); } inline void WriteBEInt32(Int32 a_Value) { VERIFY(m_Out.WriteBEInt32(a_Value)); } inline void WriteBEUInt32(UInt32 a_Value) { VERIFY(m_Out.WriteBEUInt32(a_Value)); } inline void WriteBEInt64(Int64 a_Value) { VERIFY(m_Out.WriteBEInt64(a_Value)); } inline void WriteBEUInt64(UInt64 a_Value) { VERIFY(m_Out.WriteBEUInt64(a_Value)); } inline void WriteBEFloat(float a_Value) { VERIFY(m_Out.WriteBEFloat(a_Value)); } inline void WriteBEDouble(double a_Value) { VERIFY(m_Out.WriteBEDouble(a_Value)); } inline void WriteVarInt32(UInt32 a_Value) { VERIFY(m_Out.WriteVarInt32(a_Value)); } inline void WriteString(const AString & a_Value) { VERIFY(m_Out.WriteVarUTF8String(a_Value)); } inline void WriteBuf(const ContiguousByteBufferView a_Data) { VERIFY(m_Out.Write(a_Data.data(), a_Data.size())); } /** Writes the specified block position as a single encoded 64-bit BigEndian integer. The three coordinates are written in XYZ order. */ inline void WriteXYZPosition64(int a_BlockX, int a_BlockY, int a_BlockZ) { VERIFY(m_Out.WriteXYZPosition64(a_BlockX, a_BlockY, a_BlockZ)); } /** Writes the specified block position as a single encoded 64-bit BigEndian integer. The three coordinates are written in XYZ order. */ inline void WriteXYZPosition64(const Vector3i a_Position) { VERIFY(m_Out.WriteXYZPosition64(a_Position.x, a_Position.y, a_Position.z)); } /** Writes the specified block position as a single encoded 64-bit BigEndian integer. The three coordinates are written in XZY order, in 1.14+. */ inline void WriteXZYPosition64(int a_BlockX, int a_BlockY, int a_BlockZ) { VERIFY(m_Out.WriteXZYPosition64(a_BlockX, a_BlockY, a_BlockZ)); } /** Writes the specified block position as a single encoded 64-bit BigEndian integer. The three coordinates are written in XZY order, in 1.14+. */ inline void WriteXZYPosition64(const Vector3i a_Position) { VERIFY(m_Out.WriteXZYPosition64(a_Position.x, a_Position.y, a_Position.z)); } /** Writes the specified angle using a single byte. */ void WriteByteAngle(double a_Angle); /** Writes the double value as a 27:5 fixed-point integer. */ void WriteFPInt(double a_Value); /** Writes the specified UUID as a 128-bit BigEndian integer. */ void WriteUUID(const cUUID & a_UUID); cProtocol::ePacketType GetPacketType() const { return m_PacketType; } /** Returns the human-readable representation of the packet type. Used for logging the packets. */ static AString PacketTypeToStr(cProtocol::ePacketType a_PacketType); protected: /** The protocol instance in which the packet is being constructed. */ cProtocol & m_Protocol; /** The protocol's buffer for the constructed packet data. */ cByteBuffer & m_Out; /** The RAII lock preventing multithreaded access to the protocol buffer while constructing the packet. */ cCSLock m_Lock; /** Type of the contained packet. Used for logging purposes, the packet type is encoded into m_Out immediately in constructor. */ cProtocol::ePacketType m_PacketType; } ; ================================================ FILE: src/Protocol/Palettes/CMakeLists.txt ================================================ target_sources( ${CMAKE_PROJECT_NAME} PRIVATE Palette_1_13.cpp Palette_1_13_1.cpp Palette_1_14.cpp Palette_1_15.cpp Palette_1_16.cpp Upgrade.cpp Palette_1_13.h Palette_1_13_1.h Palette_1_14.h Palette_1_15.h Palette_1_16.h Upgrade.h ) ================================================ FILE: src/Protocol/Palettes/Palette_1_13.cpp ================================================ #include "Globals.h" #include "Palette_1_13.h" #include "Registries/BlockStates.h" namespace Palette_1_13 { UInt32 From(const BlockState Block) { using namespace Block; switch (Block.ID) { case AcaciaButton::AcaciaButton(AcaciaButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5399; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5400; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5401; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5402; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, true).ID: return 5403; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, false).ID: return 5404; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, true).ID: return 5405; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, false).ID: return 5406; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5407; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5408; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5409; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5410; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, true).ID: return 5411; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, false).ID: return 5412; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, true).ID: return 5413; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, false).ID: return 5414; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5415; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5416; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5417; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5418; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, true).ID: return 5419; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, false).ID: return 5420; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, true).ID: return 5421; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, false).ID: return 5422; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, true, true).ID: return 7869; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, true, false).ID: return 7870; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, false, true).ID: return 7871; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, false, false).ID: return 7872; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, true, true).ID: return 7873; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, true, false).ID: return 7874; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, false, true).ID: return 7875; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, false, false).ID: return 7876; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, true, true).ID: return 7877; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, true, false).ID: return 7878; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, false, true).ID: return 7879; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, false, false).ID: return 7880; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, true, true).ID: return 7881; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, true, false).ID: return 7882; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, false, true).ID: return 7883; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, false, false).ID: return 7884; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, true, true).ID: return 7885; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, true, false).ID: return 7886; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, false, true).ID: return 7887; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, false, false).ID: return 7888; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, true, true).ID: return 7889; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, true, false).ID: return 7890; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, false, true).ID: return 7891; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, false, false).ID: return 7892; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, true, true).ID: return 7893; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, true, false).ID: return 7894; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, false, true).ID: return 7895; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, false, false).ID: return 7896; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, true, true).ID: return 7897; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, true, false).ID: return 7898; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, false, true).ID: return 7899; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, false, false).ID: return 7900; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, true, true).ID: return 7901; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, true, false).ID: return 7902; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, false, true).ID: return 7903; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, false, false).ID: return 7904; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, true, true).ID: return 7905; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, true, false).ID: return 7906; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, false, true).ID: return 7907; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, false, false).ID: return 7908; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, true, true).ID: return 7909; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, true, false).ID: return 7910; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, false, true).ID: return 7911; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, false, false).ID: return 7912; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, true, true).ID: return 7913; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, true, false).ID: return 7914; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, false, true).ID: return 7915; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, false, false).ID: return 7916; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, true, true).ID: return 7917; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, true, false).ID: return 7918; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, false, true).ID: return 7919; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, false, false).ID: return 7920; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, true, true).ID: return 7921; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, true, false).ID: return 7922; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, false, true).ID: return 7923; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, false, false).ID: return 7924; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, true, true).ID: return 7925; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, true, false).ID: return 7926; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, false, true).ID: return 7927; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, false, false).ID: return 7928; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, true, true).ID: return 7929; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, true, false).ID: return 7930; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, false, true).ID: return 7931; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, false, false).ID: return 7932; case AcaciaFence::AcaciaFence(true, true, true, true).ID: return 7615; case AcaciaFence::AcaciaFence(true, true, true, false).ID: return 7616; case AcaciaFence::AcaciaFence(true, true, false, true).ID: return 7619; case AcaciaFence::AcaciaFence(true, true, false, false).ID: return 7620; case AcaciaFence::AcaciaFence(true, false, true, true).ID: return 7623; case AcaciaFence::AcaciaFence(true, false, true, false).ID: return 7624; case AcaciaFence::AcaciaFence(true, false, false, true).ID: return 7627; case AcaciaFence::AcaciaFence(true, false, false, false).ID: return 7628; case AcaciaFence::AcaciaFence(false, true, true, true).ID: return 7631; case AcaciaFence::AcaciaFence(false, true, true, false).ID: return 7632; case AcaciaFence::AcaciaFence(false, true, false, true).ID: return 7635; case AcaciaFence::AcaciaFence(false, true, false, false).ID: return 7636; case AcaciaFence::AcaciaFence(false, false, true, true).ID: return 7639; case AcaciaFence::AcaciaFence(false, false, true, false).ID: return 7640; case AcaciaFence::AcaciaFence(false, false, false, true).ID: return 7643; case AcaciaFence::AcaciaFence(false, false, false, false).ID: return 7644; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZM, true, true, true).ID: return 7453; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZM, true, true, false).ID: return 7454; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZM, true, false, true).ID: return 7455; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZM, true, false, false).ID: return 7456; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, true).ID: return 7457; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, false).ID: return 7458; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, true).ID: return 7459; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, false).ID: return 7460; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZP, true, true, true).ID: return 7461; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZP, true, true, false).ID: return 7462; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZP, true, false, true).ID: return 7463; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZP, true, false, false).ID: return 7464; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, true).ID: return 7465; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, false).ID: return 7466; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, true).ID: return 7467; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, false).ID: return 7468; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XM, true, true, true).ID: return 7469; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XM, true, true, false).ID: return 7470; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XM, true, false, true).ID: return 7471; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XM, true, false, false).ID: return 7472; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, true).ID: return 7473; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, false).ID: return 7474; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, true).ID: return 7475; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, false).ID: return 7476; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XP, true, true, true).ID: return 7477; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XP, true, true, false).ID: return 7478; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XP, true, false, true).ID: return 7479; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XP, true, false, false).ID: return 7480; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, true).ID: return 7481; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, false).ID: return 7482; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, true).ID: return 7483; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, false).ID: return 7484; case AcaciaLeaves::AcaciaLeaves(1, true).ID: return 200; case AcaciaLeaves::AcaciaLeaves(1, false).ID: return 201; case AcaciaLeaves::AcaciaLeaves(2, true).ID: return 202; case AcaciaLeaves::AcaciaLeaves(2, false).ID: return 203; case AcaciaLeaves::AcaciaLeaves(3, true).ID: return 204; case AcaciaLeaves::AcaciaLeaves(3, false).ID: return 205; case AcaciaLeaves::AcaciaLeaves(4, true).ID: return 206; case AcaciaLeaves::AcaciaLeaves(4, false).ID: return 207; case AcaciaLeaves::AcaciaLeaves(5, true).ID: return 208; case AcaciaLeaves::AcaciaLeaves(5, false).ID: return 209; case AcaciaLeaves::AcaciaLeaves(6, true).ID: return 210; case AcaciaLeaves::AcaciaLeaves(6, false).ID: return 211; case AcaciaLeaves::AcaciaLeaves(7, true).ID: return 212; case AcaciaLeaves::AcaciaLeaves(7, false).ID: return 213; case AcaciaLog::AcaciaLog(AcaciaLog::Axis::X).ID: return 84; case AcaciaLog::AcaciaLog(AcaciaLog::Axis::Y).ID: return 85; case AcaciaLog::AcaciaLog(AcaciaLog::Axis::Z).ID: return 86; case AcaciaPlanks::AcaciaPlanks().ID: return 19; case AcaciaPressurePlate::AcaciaPressurePlate(true).ID: return 3375; case AcaciaPressurePlate::AcaciaPressurePlate(false).ID: return 3376; case AcaciaSapling::AcaciaSapling(0).ID: return 29; case AcaciaSapling::AcaciaSapling(1).ID: return 30; case AcaciaSlab::AcaciaSlab(AcaciaSlab::Type::Top).ID: return 7282; case AcaciaSlab::AcaciaSlab(AcaciaSlab::Type::Bottom).ID: return 7284; case AcaciaSlab::AcaciaSlab(AcaciaSlab::Type::Double).ID: return 7286; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZM, AcaciaStairs::Half::Top, AcaciaStairs::Shape::Straight).ID: return 6333; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZM, AcaciaStairs::Half::Top, AcaciaStairs::Shape::InnerLeft).ID: return 6335; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZM, AcaciaStairs::Half::Top, AcaciaStairs::Shape::InnerRight).ID: return 6337; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZM, AcaciaStairs::Half::Top, AcaciaStairs::Shape::OuterLeft).ID: return 6339; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZM, AcaciaStairs::Half::Top, AcaciaStairs::Shape::OuterRight).ID: return 6341; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZM, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::Straight).ID: return 6343; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZM, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::InnerLeft).ID: return 6345; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZM, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::InnerRight).ID: return 6347; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZM, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::OuterLeft).ID: return 6349; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZM, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::OuterRight).ID: return 6351; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZP, AcaciaStairs::Half::Top, AcaciaStairs::Shape::Straight).ID: return 6353; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZP, AcaciaStairs::Half::Top, AcaciaStairs::Shape::InnerLeft).ID: return 6355; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZP, AcaciaStairs::Half::Top, AcaciaStairs::Shape::InnerRight).ID: return 6357; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZP, AcaciaStairs::Half::Top, AcaciaStairs::Shape::OuterLeft).ID: return 6359; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZP, AcaciaStairs::Half::Top, AcaciaStairs::Shape::OuterRight).ID: return 6361; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZP, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::Straight).ID: return 6363; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZP, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::InnerLeft).ID: return 6365; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZP, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::InnerRight).ID: return 6367; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZP, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::OuterLeft).ID: return 6369; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZP, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::OuterRight).ID: return 6371; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XM, AcaciaStairs::Half::Top, AcaciaStairs::Shape::Straight).ID: return 6373; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XM, AcaciaStairs::Half::Top, AcaciaStairs::Shape::InnerLeft).ID: return 6375; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XM, AcaciaStairs::Half::Top, AcaciaStairs::Shape::InnerRight).ID: return 6377; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XM, AcaciaStairs::Half::Top, AcaciaStairs::Shape::OuterLeft).ID: return 6379; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XM, AcaciaStairs::Half::Top, AcaciaStairs::Shape::OuterRight).ID: return 6381; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XM, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::Straight).ID: return 6383; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XM, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::InnerLeft).ID: return 6385; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XM, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::InnerRight).ID: return 6387; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XM, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::OuterLeft).ID: return 6389; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XM, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::OuterRight).ID: return 6391; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XP, AcaciaStairs::Half::Top, AcaciaStairs::Shape::Straight).ID: return 6393; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XP, AcaciaStairs::Half::Top, AcaciaStairs::Shape::InnerLeft).ID: return 6395; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XP, AcaciaStairs::Half::Top, AcaciaStairs::Shape::InnerRight).ID: return 6397; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XP, AcaciaStairs::Half::Top, AcaciaStairs::Shape::OuterLeft).ID: return 6399; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XP, AcaciaStairs::Half::Top, AcaciaStairs::Shape::OuterRight).ID: return 6401; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XP, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::Straight).ID: return 6403; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XP, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::InnerLeft).ID: return 6405; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XP, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::InnerRight).ID: return 6407; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XP, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::OuterLeft).ID: return 6409; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XP, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::OuterRight).ID: return 6411; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZM, AcaciaTrapdoor::Half::Top, true, true).ID: return 3850; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZM, AcaciaTrapdoor::Half::Top, true, false).ID: return 3852; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZM, AcaciaTrapdoor::Half::Top, false, true).ID: return 3854; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZM, AcaciaTrapdoor::Half::Top, false, false).ID: return 3856; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZM, AcaciaTrapdoor::Half::Bottom, true, true).ID: return 3858; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZM, AcaciaTrapdoor::Half::Bottom, true, false).ID: return 3860; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZM, AcaciaTrapdoor::Half::Bottom, false, true).ID: return 3862; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZM, AcaciaTrapdoor::Half::Bottom, false, false).ID: return 3864; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZP, AcaciaTrapdoor::Half::Top, true, true).ID: return 3866; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZP, AcaciaTrapdoor::Half::Top, true, false).ID: return 3868; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZP, AcaciaTrapdoor::Half::Top, false, true).ID: return 3870; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZP, AcaciaTrapdoor::Half::Top, false, false).ID: return 3872; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZP, AcaciaTrapdoor::Half::Bottom, true, true).ID: return 3874; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZP, AcaciaTrapdoor::Half::Bottom, true, false).ID: return 3876; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZP, AcaciaTrapdoor::Half::Bottom, false, true).ID: return 3878; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZP, AcaciaTrapdoor::Half::Bottom, false, false).ID: return 3880; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XM, AcaciaTrapdoor::Half::Top, true, true).ID: return 3882; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XM, AcaciaTrapdoor::Half::Top, true, false).ID: return 3884; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XM, AcaciaTrapdoor::Half::Top, false, true).ID: return 3886; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XM, AcaciaTrapdoor::Half::Top, false, false).ID: return 3888; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XM, AcaciaTrapdoor::Half::Bottom, true, true).ID: return 3890; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XM, AcaciaTrapdoor::Half::Bottom, true, false).ID: return 3892; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XM, AcaciaTrapdoor::Half::Bottom, false, true).ID: return 3894; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XM, AcaciaTrapdoor::Half::Bottom, false, false).ID: return 3896; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XP, AcaciaTrapdoor::Half::Top, true, true).ID: return 3898; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XP, AcaciaTrapdoor::Half::Top, true, false).ID: return 3900; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XP, AcaciaTrapdoor::Half::Top, false, true).ID: return 3902; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XP, AcaciaTrapdoor::Half::Top, false, false).ID: return 3904; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XP, AcaciaTrapdoor::Half::Bottom, true, true).ID: return 3906; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XP, AcaciaTrapdoor::Half::Bottom, true, false).ID: return 3908; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XP, AcaciaTrapdoor::Half::Bottom, false, true).ID: return 3910; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XP, AcaciaTrapdoor::Half::Bottom, false, false).ID: return 3912; case AcaciaWood::AcaciaWood(AcaciaWood::Axis::X).ID: return 120; case AcaciaWood::AcaciaWood(AcaciaWood::Axis::Y).ID: return 121; case AcaciaWood::AcaciaWood(AcaciaWood::Axis::Z).ID: return 122; case ActivatorRail::ActivatorRail(true, ActivatorRail::Shape::NorthSouth).ID: return 5780; case ActivatorRail::ActivatorRail(true, ActivatorRail::Shape::EastWest).ID: return 5781; case ActivatorRail::ActivatorRail(true, ActivatorRail::Shape::AscendingEast).ID: return 5782; case ActivatorRail::ActivatorRail(true, ActivatorRail::Shape::AscendingWest).ID: return 5783; case ActivatorRail::ActivatorRail(true, ActivatorRail::Shape::AscendingNorth).ID: return 5784; case ActivatorRail::ActivatorRail(true, ActivatorRail::Shape::AscendingSouth).ID: return 5785; case ActivatorRail::ActivatorRail(false, ActivatorRail::Shape::NorthSouth).ID: return 5786; case ActivatorRail::ActivatorRail(false, ActivatorRail::Shape::EastWest).ID: return 5787; case ActivatorRail::ActivatorRail(false, ActivatorRail::Shape::AscendingEast).ID: return 5788; case ActivatorRail::ActivatorRail(false, ActivatorRail::Shape::AscendingWest).ID: return 5789; case ActivatorRail::ActivatorRail(false, ActivatorRail::Shape::AscendingNorth).ID: return 5790; case ActivatorRail::ActivatorRail(false, ActivatorRail::Shape::AscendingSouth).ID: return 5791; case Air::Air().ID: return -0; case Allium::Allium().ID: return 1114; case Andesite::Andesite().ID: return 6; case Anvil::Anvil(eBlockFace::BLOCK_FACE_ZM).ID: return 5567; case Anvil::Anvil(eBlockFace::BLOCK_FACE_ZP).ID: return 5568; case Anvil::Anvil(eBlockFace::BLOCK_FACE_XM).ID: return 5569; case Anvil::Anvil(eBlockFace::BLOCK_FACE_XP).ID: return 5570; case AttachedMelonStem::AttachedMelonStem(eBlockFace::BLOCK_FACE_ZM).ID: return 4248; case AttachedMelonStem::AttachedMelonStem(eBlockFace::BLOCK_FACE_ZP).ID: return 4249; case AttachedMelonStem::AttachedMelonStem(eBlockFace::BLOCK_FACE_XM).ID: return 4250; case AttachedMelonStem::AttachedMelonStem(eBlockFace::BLOCK_FACE_XP).ID: return 4251; case AttachedPumpkinStem::AttachedPumpkinStem(eBlockFace::BLOCK_FACE_ZM).ID: return 4244; case AttachedPumpkinStem::AttachedPumpkinStem(eBlockFace::BLOCK_FACE_ZP).ID: return 4245; case AttachedPumpkinStem::AttachedPumpkinStem(eBlockFace::BLOCK_FACE_XM).ID: return 4246; case AttachedPumpkinStem::AttachedPumpkinStem(eBlockFace::BLOCK_FACE_XP).ID: return 4247; case AzureBluet::AzureBluet().ID: return 1115; case Barrier::Barrier().ID: return 6493; case Beacon::Beacon().ID: return 5136; case Bedrock::Bedrock().ID: return 33; case Beetroots::Beetroots(0).ID: return 8158; case Beetroots::Beetroots(1).ID: return 8159; case Beetroots::Beetroots(2).ID: return 8160; case Beetroots::Beetroots(3).ID: return 8161; case BirchButton::BirchButton(BirchButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5351; case BirchButton::BirchButton(BirchButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5352; case BirchButton::BirchButton(BirchButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5353; case BirchButton::BirchButton(BirchButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5354; case BirchButton::BirchButton(BirchButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, true).ID: return 5355; case BirchButton::BirchButton(BirchButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, false).ID: return 5356; case BirchButton::BirchButton(BirchButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, true).ID: return 5357; case BirchButton::BirchButton(BirchButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, false).ID: return 5358; case BirchButton::BirchButton(BirchButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5359; case BirchButton::BirchButton(BirchButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5360; case BirchButton::BirchButton(BirchButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5361; case BirchButton::BirchButton(BirchButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5362; case BirchButton::BirchButton(BirchButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, true).ID: return 5363; case BirchButton::BirchButton(BirchButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, false).ID: return 5364; case BirchButton::BirchButton(BirchButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, true).ID: return 5365; case BirchButton::BirchButton(BirchButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, false).ID: return 5366; case BirchButton::BirchButton(BirchButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5367; case BirchButton::BirchButton(BirchButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5368; case BirchButton::BirchButton(BirchButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5369; case BirchButton::BirchButton(BirchButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5370; case BirchButton::BirchButton(BirchButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, true).ID: return 5371; case BirchButton::BirchButton(BirchButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, false).ID: return 5372; case BirchButton::BirchButton(BirchButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, true).ID: return 5373; case BirchButton::BirchButton(BirchButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, false).ID: return 5374; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, true, true).ID: return 7741; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, true, false).ID: return 7742; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, false, true).ID: return 7743; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, false, false).ID: return 7744; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, true, true).ID: return 7745; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, true, false).ID: return 7746; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, false, true).ID: return 7747; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, false, false).ID: return 7748; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, true, true).ID: return 7749; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, true, false).ID: return 7750; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, false, true).ID: return 7751; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, false, false).ID: return 7752; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, true, true).ID: return 7753; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, true, false).ID: return 7754; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, false, true).ID: return 7755; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, false, false).ID: return 7756; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, true, true).ID: return 7757; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, true, false).ID: return 7758; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, false, true).ID: return 7759; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, false, false).ID: return 7760; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, true, true).ID: return 7761; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, true, false).ID: return 7762; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, false, true).ID: return 7763; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, false, false).ID: return 7764; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, true, true).ID: return 7765; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, true, false).ID: return 7766; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, false, true).ID: return 7767; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, false, false).ID: return 7768; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, true, true).ID: return 7769; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, true, false).ID: return 7770; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, false, true).ID: return 7771; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, false, false).ID: return 7772; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, true, true).ID: return 7773; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, true, false).ID: return 7774; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, false, true).ID: return 7775; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, false, false).ID: return 7776; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, true, true).ID: return 7777; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, true, false).ID: return 7778; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, false, true).ID: return 7779; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, false, false).ID: return 7780; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, true, true).ID: return 7781; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, true, false).ID: return 7782; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, false, true).ID: return 7783; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, false, false).ID: return 7784; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, true, true).ID: return 7785; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, true, false).ID: return 7786; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, false, true).ID: return 7787; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, false, false).ID: return 7788; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, true, true).ID: return 7789; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, true, false).ID: return 7790; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, false, true).ID: return 7791; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, false, false).ID: return 7792; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, true, true).ID: return 7793; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, true, false).ID: return 7794; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, false, true).ID: return 7795; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, false, false).ID: return 7796; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, true, true).ID: return 7797; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, true, false).ID: return 7798; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, false, true).ID: return 7799; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, false, false).ID: return 7800; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, true, true).ID: return 7801; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, true, false).ID: return 7802; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, false, true).ID: return 7803; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, false, false).ID: return 7804; case BirchFence::BirchFence(true, true, true, true).ID: return 7551; case BirchFence::BirchFence(true, true, true, false).ID: return 7552; case BirchFence::BirchFence(true, true, false, true).ID: return 7555; case BirchFence::BirchFence(true, true, false, false).ID: return 7556; case BirchFence::BirchFence(true, false, true, true).ID: return 7559; case BirchFence::BirchFence(true, false, true, false).ID: return 7560; case BirchFence::BirchFence(true, false, false, true).ID: return 7563; case BirchFence::BirchFence(true, false, false, false).ID: return 7564; case BirchFence::BirchFence(false, true, true, true).ID: return 7567; case BirchFence::BirchFence(false, true, true, false).ID: return 7568; case BirchFence::BirchFence(false, true, false, true).ID: return 7571; case BirchFence::BirchFence(false, true, false, false).ID: return 7572; case BirchFence::BirchFence(false, false, true, true).ID: return 7575; case BirchFence::BirchFence(false, false, true, false).ID: return 7576; case BirchFence::BirchFence(false, false, false, true).ID: return 7579; case BirchFence::BirchFence(false, false, false, false).ID: return 7580; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZM, true, true, true).ID: return 7389; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZM, true, true, false).ID: return 7390; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZM, true, false, true).ID: return 7391; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZM, true, false, false).ID: return 7392; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, true).ID: return 7393; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, false).ID: return 7394; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, true).ID: return 7395; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, false).ID: return 7396; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZP, true, true, true).ID: return 7397; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZP, true, true, false).ID: return 7398; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZP, true, false, true).ID: return 7399; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZP, true, false, false).ID: return 7400; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, true).ID: return 7401; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, false).ID: return 7402; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, true).ID: return 7403; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, false).ID: return 7404; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XM, true, true, true).ID: return 7405; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XM, true, true, false).ID: return 7406; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XM, true, false, true).ID: return 7407; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XM, true, false, false).ID: return 7408; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, true).ID: return 7409; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, false).ID: return 7410; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, true).ID: return 7411; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, false).ID: return 7412; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XP, true, true, true).ID: return 7413; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XP, true, true, false).ID: return 7414; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XP, true, false, true).ID: return 7415; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XP, true, false, false).ID: return 7416; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, true).ID: return 7417; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, false).ID: return 7418; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, true).ID: return 7419; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, false).ID: return 7420; case BirchLeaves::BirchLeaves(1, true).ID: return 172; case BirchLeaves::BirchLeaves(1, false).ID: return 173; case BirchLeaves::BirchLeaves(2, true).ID: return 174; case BirchLeaves::BirchLeaves(2, false).ID: return 175; case BirchLeaves::BirchLeaves(3, true).ID: return 176; case BirchLeaves::BirchLeaves(3, false).ID: return 177; case BirchLeaves::BirchLeaves(4, true).ID: return 178; case BirchLeaves::BirchLeaves(4, false).ID: return 179; case BirchLeaves::BirchLeaves(5, true).ID: return 180; case BirchLeaves::BirchLeaves(5, false).ID: return 181; case BirchLeaves::BirchLeaves(6, true).ID: return 182; case BirchLeaves::BirchLeaves(6, false).ID: return 183; case BirchLeaves::BirchLeaves(7, true).ID: return 184; case BirchLeaves::BirchLeaves(7, false).ID: return 185; case BirchLog::BirchLog(BirchLog::Axis::X).ID: return 78; case BirchLog::BirchLog(BirchLog::Axis::Y).ID: return 79; case BirchLog::BirchLog(BirchLog::Axis::Z).ID: return 80; case BirchPlanks::BirchPlanks().ID: return 17; case BirchPressurePlate::BirchPressurePlate(true).ID: return 3371; case BirchPressurePlate::BirchPressurePlate(false).ID: return 3372; case BirchSapling::BirchSapling(0).ID: return 25; case BirchSapling::BirchSapling(1).ID: return 26; case BirchSlab::BirchSlab(BirchSlab::Type::Top).ID: return 7270; case BirchSlab::BirchSlab(BirchSlab::Type::Bottom).ID: return 7272; case BirchSlab::BirchSlab(BirchSlab::Type::Double).ID: return 7274; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZM, BirchStairs::Half::Top, BirchStairs::Shape::Straight).ID: return 4965; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZM, BirchStairs::Half::Top, BirchStairs::Shape::InnerLeft).ID: return 4967; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZM, BirchStairs::Half::Top, BirchStairs::Shape::InnerRight).ID: return 4969; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZM, BirchStairs::Half::Top, BirchStairs::Shape::OuterLeft).ID: return 4971; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZM, BirchStairs::Half::Top, BirchStairs::Shape::OuterRight).ID: return 4973; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZM, BirchStairs::Half::Bottom, BirchStairs::Shape::Straight).ID: return 4975; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZM, BirchStairs::Half::Bottom, BirchStairs::Shape::InnerLeft).ID: return 4977; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZM, BirchStairs::Half::Bottom, BirchStairs::Shape::InnerRight).ID: return 4979; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZM, BirchStairs::Half::Bottom, BirchStairs::Shape::OuterLeft).ID: return 4981; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZM, BirchStairs::Half::Bottom, BirchStairs::Shape::OuterRight).ID: return 4983; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZP, BirchStairs::Half::Top, BirchStairs::Shape::Straight).ID: return 4985; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZP, BirchStairs::Half::Top, BirchStairs::Shape::InnerLeft).ID: return 4987; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZP, BirchStairs::Half::Top, BirchStairs::Shape::InnerRight).ID: return 4989; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZP, BirchStairs::Half::Top, BirchStairs::Shape::OuterLeft).ID: return 4991; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZP, BirchStairs::Half::Top, BirchStairs::Shape::OuterRight).ID: return 4993; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZP, BirchStairs::Half::Bottom, BirchStairs::Shape::Straight).ID: return 4995; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZP, BirchStairs::Half::Bottom, BirchStairs::Shape::InnerLeft).ID: return 4997; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZP, BirchStairs::Half::Bottom, BirchStairs::Shape::InnerRight).ID: return 4999; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZP, BirchStairs::Half::Bottom, BirchStairs::Shape::OuterLeft).ID: return 5001; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZP, BirchStairs::Half::Bottom, BirchStairs::Shape::OuterRight).ID: return 5003; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XM, BirchStairs::Half::Top, BirchStairs::Shape::Straight).ID: return 5005; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XM, BirchStairs::Half::Top, BirchStairs::Shape::InnerLeft).ID: return 5007; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XM, BirchStairs::Half::Top, BirchStairs::Shape::InnerRight).ID: return 5009; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XM, BirchStairs::Half::Top, BirchStairs::Shape::OuterLeft).ID: return 5011; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XM, BirchStairs::Half::Top, BirchStairs::Shape::OuterRight).ID: return 5013; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XM, BirchStairs::Half::Bottom, BirchStairs::Shape::Straight).ID: return 5015; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XM, BirchStairs::Half::Bottom, BirchStairs::Shape::InnerLeft).ID: return 5017; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XM, BirchStairs::Half::Bottom, BirchStairs::Shape::InnerRight).ID: return 5019; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XM, BirchStairs::Half::Bottom, BirchStairs::Shape::OuterLeft).ID: return 5021; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XM, BirchStairs::Half::Bottom, BirchStairs::Shape::OuterRight).ID: return 5023; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XP, BirchStairs::Half::Top, BirchStairs::Shape::Straight).ID: return 5025; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XP, BirchStairs::Half::Top, BirchStairs::Shape::InnerLeft).ID: return 5027; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XP, BirchStairs::Half::Top, BirchStairs::Shape::InnerRight).ID: return 5029; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XP, BirchStairs::Half::Top, BirchStairs::Shape::OuterLeft).ID: return 5031; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XP, BirchStairs::Half::Top, BirchStairs::Shape::OuterRight).ID: return 5033; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XP, BirchStairs::Half::Bottom, BirchStairs::Shape::Straight).ID: return 5035; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XP, BirchStairs::Half::Bottom, BirchStairs::Shape::InnerLeft).ID: return 5037; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XP, BirchStairs::Half::Bottom, BirchStairs::Shape::InnerRight).ID: return 5039; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XP, BirchStairs::Half::Bottom, BirchStairs::Shape::OuterLeft).ID: return 5041; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XP, BirchStairs::Half::Bottom, BirchStairs::Shape::OuterRight).ID: return 5043; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZM, BirchTrapdoor::Half::Top, true, true).ID: return 3722; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZM, BirchTrapdoor::Half::Top, true, false).ID: return 3724; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZM, BirchTrapdoor::Half::Top, false, true).ID: return 3726; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZM, BirchTrapdoor::Half::Top, false, false).ID: return 3728; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZM, BirchTrapdoor::Half::Bottom, true, true).ID: return 3730; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZM, BirchTrapdoor::Half::Bottom, true, false).ID: return 3732; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZM, BirchTrapdoor::Half::Bottom, false, true).ID: return 3734; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZM, BirchTrapdoor::Half::Bottom, false, false).ID: return 3736; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZP, BirchTrapdoor::Half::Top, true, true).ID: return 3738; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZP, BirchTrapdoor::Half::Top, true, false).ID: return 3740; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZP, BirchTrapdoor::Half::Top, false, true).ID: return 3742; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZP, BirchTrapdoor::Half::Top, false, false).ID: return 3744; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZP, BirchTrapdoor::Half::Bottom, true, true).ID: return 3746; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZP, BirchTrapdoor::Half::Bottom, true, false).ID: return 3748; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZP, BirchTrapdoor::Half::Bottom, false, true).ID: return 3750; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZP, BirchTrapdoor::Half::Bottom, false, false).ID: return 3752; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XM, BirchTrapdoor::Half::Top, true, true).ID: return 3754; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XM, BirchTrapdoor::Half::Top, true, false).ID: return 3756; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XM, BirchTrapdoor::Half::Top, false, true).ID: return 3758; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XM, BirchTrapdoor::Half::Top, false, false).ID: return 3760; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XM, BirchTrapdoor::Half::Bottom, true, true).ID: return 3762; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XM, BirchTrapdoor::Half::Bottom, true, false).ID: return 3764; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XM, BirchTrapdoor::Half::Bottom, false, true).ID: return 3766; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XM, BirchTrapdoor::Half::Bottom, false, false).ID: return 3768; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XP, BirchTrapdoor::Half::Top, true, true).ID: return 3770; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XP, BirchTrapdoor::Half::Top, true, false).ID: return 3772; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XP, BirchTrapdoor::Half::Top, false, true).ID: return 3774; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XP, BirchTrapdoor::Half::Top, false, false).ID: return 3776; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XP, BirchTrapdoor::Half::Bottom, true, true).ID: return 3778; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XP, BirchTrapdoor::Half::Bottom, true, false).ID: return 3780; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XP, BirchTrapdoor::Half::Bottom, false, true).ID: return 3782; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XP, BirchTrapdoor::Half::Bottom, false, false).ID: return 3784; case BirchWood::BirchWood(BirchWood::Axis::X).ID: return 114; case BirchWood::BirchWood(BirchWood::Axis::Y).ID: return 115; case BirchWood::BirchWood(BirchWood::Axis::Z).ID: return 116; case BlackBanner::BlackBanner(0).ID: return 7094; case BlackBanner::BlackBanner(1).ID: return 7095; case BlackBanner::BlackBanner(2).ID: return 7096; case BlackBanner::BlackBanner(3).ID: return 7097; case BlackBanner::BlackBanner(4).ID: return 7098; case BlackBanner::BlackBanner(5).ID: return 7099; case BlackBanner::BlackBanner(6).ID: return 7100; case BlackBanner::BlackBanner(7).ID: return 7101; case BlackBanner::BlackBanner(8).ID: return 7102; case BlackBanner::BlackBanner(9).ID: return 7103; case BlackBanner::BlackBanner(10).ID: return 7104; case BlackBanner::BlackBanner(11).ID: return 7105; case BlackBanner::BlackBanner(12).ID: return 7106; case BlackBanner::BlackBanner(13).ID: return 7107; case BlackBanner::BlackBanner(14).ID: return 7108; case BlackBanner::BlackBanner(15).ID: return 7109; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_ZM, true, BlackBed::Part::Head).ID: return 988; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_ZM, true, BlackBed::Part::Foot).ID: return 989; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_ZM, false, BlackBed::Part::Head).ID: return 990; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_ZM, false, BlackBed::Part::Foot).ID: return 991; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_ZP, true, BlackBed::Part::Head).ID: return 992; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_ZP, true, BlackBed::Part::Foot).ID: return 993; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_ZP, false, BlackBed::Part::Head).ID: return 994; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_ZP, false, BlackBed::Part::Foot).ID: return 995; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_XM, true, BlackBed::Part::Head).ID: return 996; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_XM, true, BlackBed::Part::Foot).ID: return 997; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_XM, false, BlackBed::Part::Head).ID: return 998; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_XM, false, BlackBed::Part::Foot).ID: return 999; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_XP, true, BlackBed::Part::Head).ID: return 1000; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_XP, true, BlackBed::Part::Foot).ID: return 1001; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_XP, false, BlackBed::Part::Head).ID: return 1002; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_XP, false, BlackBed::Part::Foot).ID: return 1003; case BlackCarpet::BlackCarpet().ID: return 6838; case BlackConcrete::BlackConcrete().ID: return 8392; case BlackConcretePowder::BlackConcretePowder().ID: return 8408; case BlackGlazedTerracotta::BlackGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 8373; case BlackGlazedTerracotta::BlackGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 8374; case BlackGlazedTerracotta::BlackGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 8375; case BlackGlazedTerracotta::BlackGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 8376; case BlackShulkerBox::BlackShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 8307; case BlackShulkerBox::BlackShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 8308; case BlackShulkerBox::BlackShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 8309; case BlackShulkerBox::BlackShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 8310; case BlackShulkerBox::BlackShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 8311; case BlackShulkerBox::BlackShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 8312; case BlackStainedGlass::BlackStainedGlass().ID: return 3592; case BlackStainedGlassPane::BlackStainedGlassPane(true, true, true, true).ID: return 6302; case BlackStainedGlassPane::BlackStainedGlassPane(true, true, true, false).ID: return 6303; case BlackStainedGlassPane::BlackStainedGlassPane(true, true, false, true).ID: return 6306; case BlackStainedGlassPane::BlackStainedGlassPane(true, true, false, false).ID: return 6307; case BlackStainedGlassPane::BlackStainedGlassPane(true, false, true, true).ID: return 6310; case BlackStainedGlassPane::BlackStainedGlassPane(true, false, true, false).ID: return 6311; case BlackStainedGlassPane::BlackStainedGlassPane(true, false, false, true).ID: return 6314; case BlackStainedGlassPane::BlackStainedGlassPane(true, false, false, false).ID: return 6315; case BlackStainedGlassPane::BlackStainedGlassPane(false, true, true, true).ID: return 6318; case BlackStainedGlassPane::BlackStainedGlassPane(false, true, true, false).ID: return 6319; case BlackStainedGlassPane::BlackStainedGlassPane(false, true, false, true).ID: return 6322; case BlackStainedGlassPane::BlackStainedGlassPane(false, true, false, false).ID: return 6323; case BlackStainedGlassPane::BlackStainedGlassPane(false, false, true, true).ID: return 6326; case BlackStainedGlassPane::BlackStainedGlassPane(false, false, true, false).ID: return 6327; case BlackStainedGlassPane::BlackStainedGlassPane(false, false, false, true).ID: return 6330; case BlackStainedGlassPane::BlackStainedGlassPane(false, false, false, false).ID: return 6331; case BlackTerracotta::BlackTerracotta().ID: return 5819; case BlackWallBanner::BlackWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 7170; case BlackWallBanner::BlackWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 7171; case BlackWallBanner::BlackWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 7172; case BlackWallBanner::BlackWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 7173; case BlackWool::BlackWool().ID: return 1098; case BlueBanner::BlueBanner(0).ID: return 7030; case BlueBanner::BlueBanner(1).ID: return 7031; case BlueBanner::BlueBanner(2).ID: return 7032; case BlueBanner::BlueBanner(3).ID: return 7033; case BlueBanner::BlueBanner(4).ID: return 7034; case BlueBanner::BlueBanner(5).ID: return 7035; case BlueBanner::BlueBanner(6).ID: return 7036; case BlueBanner::BlueBanner(7).ID: return 7037; case BlueBanner::BlueBanner(8).ID: return 7038; case BlueBanner::BlueBanner(9).ID: return 7039; case BlueBanner::BlueBanner(10).ID: return 7040; case BlueBanner::BlueBanner(11).ID: return 7041; case BlueBanner::BlueBanner(12).ID: return 7042; case BlueBanner::BlueBanner(13).ID: return 7043; case BlueBanner::BlueBanner(14).ID: return 7044; case BlueBanner::BlueBanner(15).ID: return 7045; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_ZM, true, BlueBed::Part::Head).ID: return 924; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_ZM, true, BlueBed::Part::Foot).ID: return 925; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_ZM, false, BlueBed::Part::Head).ID: return 926; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_ZM, false, BlueBed::Part::Foot).ID: return 927; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_ZP, true, BlueBed::Part::Head).ID: return 928; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_ZP, true, BlueBed::Part::Foot).ID: return 929; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_ZP, false, BlueBed::Part::Head).ID: return 930; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_ZP, false, BlueBed::Part::Foot).ID: return 931; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_XM, true, BlueBed::Part::Head).ID: return 932; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_XM, true, BlueBed::Part::Foot).ID: return 933; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_XM, false, BlueBed::Part::Head).ID: return 934; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_XM, false, BlueBed::Part::Foot).ID: return 935; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_XP, true, BlueBed::Part::Head).ID: return 936; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_XP, true, BlueBed::Part::Foot).ID: return 937; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_XP, false, BlueBed::Part::Head).ID: return 938; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_XP, false, BlueBed::Part::Foot).ID: return 939; case BlueCarpet::BlueCarpet().ID: return 6834; case BlueConcrete::BlueConcrete().ID: return 8388; case BlueConcretePowder::BlueConcretePowder().ID: return 8404; case BlueGlazedTerracotta::BlueGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 8357; case BlueGlazedTerracotta::BlueGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 8358; case BlueGlazedTerracotta::BlueGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 8359; case BlueGlazedTerracotta::BlueGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 8360; case BlueIce::BlueIce().ID: return 8572; case BlueOrchid::BlueOrchid().ID: return 1113; case BlueShulkerBox::BlueShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 8283; case BlueShulkerBox::BlueShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 8284; case BlueShulkerBox::BlueShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 8285; case BlueShulkerBox::BlueShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 8286; case BlueShulkerBox::BlueShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 8287; case BlueShulkerBox::BlueShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 8288; case BlueStainedGlass::BlueStainedGlass().ID: return 3588; case BlueStainedGlassPane::BlueStainedGlassPane(true, true, true, true).ID: return 6174; case BlueStainedGlassPane::BlueStainedGlassPane(true, true, true, false).ID: return 6175; case BlueStainedGlassPane::BlueStainedGlassPane(true, true, false, true).ID: return 6178; case BlueStainedGlassPane::BlueStainedGlassPane(true, true, false, false).ID: return 6179; case BlueStainedGlassPane::BlueStainedGlassPane(true, false, true, true).ID: return 6182; case BlueStainedGlassPane::BlueStainedGlassPane(true, false, true, false).ID: return 6183; case BlueStainedGlassPane::BlueStainedGlassPane(true, false, false, true).ID: return 6186; case BlueStainedGlassPane::BlueStainedGlassPane(true, false, false, false).ID: return 6187; case BlueStainedGlassPane::BlueStainedGlassPane(false, true, true, true).ID: return 6190; case BlueStainedGlassPane::BlueStainedGlassPane(false, true, true, false).ID: return 6191; case BlueStainedGlassPane::BlueStainedGlassPane(false, true, false, true).ID: return 6194; case BlueStainedGlassPane::BlueStainedGlassPane(false, true, false, false).ID: return 6195; case BlueStainedGlassPane::BlueStainedGlassPane(false, false, true, true).ID: return 6198; case BlueStainedGlassPane::BlueStainedGlassPane(false, false, true, false).ID: return 6199; case BlueStainedGlassPane::BlueStainedGlassPane(false, false, false, true).ID: return 6202; case BlueStainedGlassPane::BlueStainedGlassPane(false, false, false, false).ID: return 6203; case BlueTerracotta::BlueTerracotta().ID: return 5815; case BlueWallBanner::BlueWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 7154; case BlueWallBanner::BlueWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 7155; case BlueWallBanner::BlueWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 7156; case BlueWallBanner::BlueWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 7157; case BlueWool::BlueWool().ID: return 1094; case BoneBlock::BoneBlock(BoneBlock::Axis::X).ID: return 8195; case BoneBlock::BoneBlock(BoneBlock::Axis::Y).ID: return 8196; case BoneBlock::BoneBlock(BoneBlock::Axis::Z).ID: return 8197; case Bookshelf::Bookshelf().ID: return 1127; case BrainCoral::BrainCoral().ID: return 8460; case BrainCoralBlock::BrainCoralBlock().ID: return 8455; case BrainCoralFan::BrainCoralFan().ID: return 8557; case BrainCoralWallFan::BrainCoralWallFan(eBlockFace::BLOCK_FACE_ZM).ID: return 8513; case BrainCoralWallFan::BrainCoralWallFan(eBlockFace::BLOCK_FACE_ZP).ID: return 8515; case BrainCoralWallFan::BrainCoralWallFan(eBlockFace::BLOCK_FACE_XM).ID: return 8517; case BrainCoralWallFan::BrainCoralWallFan(eBlockFace::BLOCK_FACE_XP).ID: return 8519; case BrewingStand::BrewingStand(true, true, true).ID: return 4613; case BrewingStand::BrewingStand(true, true, false).ID: return 4614; case BrewingStand::BrewingStand(true, false, true).ID: return 4615; case BrewingStand::BrewingStand(true, false, false).ID: return 4616; case BrewingStand::BrewingStand(false, true, true).ID: return 4617; case BrewingStand::BrewingStand(false, true, false).ID: return 4618; case BrewingStand::BrewingStand(false, false, true).ID: return 4619; case BrewingStand::BrewingStand(false, false, false).ID: return 4620; case BrickSlab::BrickSlab(BrickSlab::Type::Top).ID: return 7318; case BrickSlab::BrickSlab(BrickSlab::Type::Bottom).ID: return 7320; case BrickSlab::BrickSlab(BrickSlab::Type::Double).ID: return 7322; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZM, BrickStairs::Half::Top, BrickStairs::Shape::Straight).ID: return 4333; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZM, BrickStairs::Half::Top, BrickStairs::Shape::InnerLeft).ID: return 4335; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZM, BrickStairs::Half::Top, BrickStairs::Shape::InnerRight).ID: return 4337; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZM, BrickStairs::Half::Top, BrickStairs::Shape::OuterLeft).ID: return 4339; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZM, BrickStairs::Half::Top, BrickStairs::Shape::OuterRight).ID: return 4341; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZM, BrickStairs::Half::Bottom, BrickStairs::Shape::Straight).ID: return 4343; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZM, BrickStairs::Half::Bottom, BrickStairs::Shape::InnerLeft).ID: return 4345; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZM, BrickStairs::Half::Bottom, BrickStairs::Shape::InnerRight).ID: return 4347; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZM, BrickStairs::Half::Bottom, BrickStairs::Shape::OuterLeft).ID: return 4349; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZM, BrickStairs::Half::Bottom, BrickStairs::Shape::OuterRight).ID: return 4351; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZP, BrickStairs::Half::Top, BrickStairs::Shape::Straight).ID: return 4353; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZP, BrickStairs::Half::Top, BrickStairs::Shape::InnerLeft).ID: return 4355; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZP, BrickStairs::Half::Top, BrickStairs::Shape::InnerRight).ID: return 4357; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZP, BrickStairs::Half::Top, BrickStairs::Shape::OuterLeft).ID: return 4359; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZP, BrickStairs::Half::Top, BrickStairs::Shape::OuterRight).ID: return 4361; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZP, BrickStairs::Half::Bottom, BrickStairs::Shape::Straight).ID: return 4363; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZP, BrickStairs::Half::Bottom, BrickStairs::Shape::InnerLeft).ID: return 4365; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZP, BrickStairs::Half::Bottom, BrickStairs::Shape::InnerRight).ID: return 4367; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZP, BrickStairs::Half::Bottom, BrickStairs::Shape::OuterLeft).ID: return 4369; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZP, BrickStairs::Half::Bottom, BrickStairs::Shape::OuterRight).ID: return 4371; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XM, BrickStairs::Half::Top, BrickStairs::Shape::Straight).ID: return 4373; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XM, BrickStairs::Half::Top, BrickStairs::Shape::InnerLeft).ID: return 4375; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XM, BrickStairs::Half::Top, BrickStairs::Shape::InnerRight).ID: return 4377; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XM, BrickStairs::Half::Top, BrickStairs::Shape::OuterLeft).ID: return 4379; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XM, BrickStairs::Half::Top, BrickStairs::Shape::OuterRight).ID: return 4381; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XM, BrickStairs::Half::Bottom, BrickStairs::Shape::Straight).ID: return 4383; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XM, BrickStairs::Half::Bottom, BrickStairs::Shape::InnerLeft).ID: return 4385; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XM, BrickStairs::Half::Bottom, BrickStairs::Shape::InnerRight).ID: return 4387; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XM, BrickStairs::Half::Bottom, BrickStairs::Shape::OuterLeft).ID: return 4389; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XM, BrickStairs::Half::Bottom, BrickStairs::Shape::OuterRight).ID: return 4391; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XP, BrickStairs::Half::Top, BrickStairs::Shape::Straight).ID: return 4393; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XP, BrickStairs::Half::Top, BrickStairs::Shape::InnerLeft).ID: return 4395; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XP, BrickStairs::Half::Top, BrickStairs::Shape::InnerRight).ID: return 4397; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XP, BrickStairs::Half::Top, BrickStairs::Shape::OuterLeft).ID: return 4399; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XP, BrickStairs::Half::Top, BrickStairs::Shape::OuterRight).ID: return 4401; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XP, BrickStairs::Half::Bottom, BrickStairs::Shape::Straight).ID: return 4403; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XP, BrickStairs::Half::Bottom, BrickStairs::Shape::InnerLeft).ID: return 4405; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XP, BrickStairs::Half::Bottom, BrickStairs::Shape::InnerRight).ID: return 4407; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XP, BrickStairs::Half::Bottom, BrickStairs::Shape::OuterLeft).ID: return 4409; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XP, BrickStairs::Half::Bottom, BrickStairs::Shape::OuterRight).ID: return 4411; case Bricks::Bricks().ID: return 1125; case BrownBanner::BrownBanner(0).ID: return 7046; case BrownBanner::BrownBanner(1).ID: return 7047; case BrownBanner::BrownBanner(2).ID: return 7048; case BrownBanner::BrownBanner(3).ID: return 7049; case BrownBanner::BrownBanner(4).ID: return 7050; case BrownBanner::BrownBanner(5).ID: return 7051; case BrownBanner::BrownBanner(6).ID: return 7052; case BrownBanner::BrownBanner(7).ID: return 7053; case BrownBanner::BrownBanner(8).ID: return 7054; case BrownBanner::BrownBanner(9).ID: return 7055; case BrownBanner::BrownBanner(10).ID: return 7056; case BrownBanner::BrownBanner(11).ID: return 7057; case BrownBanner::BrownBanner(12).ID: return 7058; case BrownBanner::BrownBanner(13).ID: return 7059; case BrownBanner::BrownBanner(14).ID: return 7060; case BrownBanner::BrownBanner(15).ID: return 7061; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_ZM, true, BrownBed::Part::Head).ID: return 940; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_ZM, true, BrownBed::Part::Foot).ID: return 941; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_ZM, false, BrownBed::Part::Head).ID: return 942; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_ZM, false, BrownBed::Part::Foot).ID: return 943; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_ZP, true, BrownBed::Part::Head).ID: return 944; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_ZP, true, BrownBed::Part::Foot).ID: return 945; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_ZP, false, BrownBed::Part::Head).ID: return 946; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_ZP, false, BrownBed::Part::Foot).ID: return 947; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_XM, true, BrownBed::Part::Head).ID: return 948; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_XM, true, BrownBed::Part::Foot).ID: return 949; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_XM, false, BrownBed::Part::Head).ID: return 950; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_XM, false, BrownBed::Part::Foot).ID: return 951; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_XP, true, BrownBed::Part::Head).ID: return 952; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_XP, true, BrownBed::Part::Foot).ID: return 953; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_XP, false, BrownBed::Part::Head).ID: return 954; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_XP, false, BrownBed::Part::Foot).ID: return 955; case BrownCarpet::BrownCarpet().ID: return 6835; case BrownConcrete::BrownConcrete().ID: return 8389; case BrownConcretePowder::BrownConcretePowder().ID: return 8405; case BrownGlazedTerracotta::BrownGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 8361; case BrownGlazedTerracotta::BrownGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 8362; case BrownGlazedTerracotta::BrownGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 8363; case BrownGlazedTerracotta::BrownGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 8364; case BrownMushroom::BrownMushroom().ID: return 1121; case BrownMushroomBlock::BrownMushroomBlock(true, true, true, true, true, true).ID: return 3987; case BrownMushroomBlock::BrownMushroomBlock(true, true, true, true, true, false).ID: return 3988; case BrownMushroomBlock::BrownMushroomBlock(true, true, true, true, false, true).ID: return 3989; case BrownMushroomBlock::BrownMushroomBlock(true, true, true, true, false, false).ID: return 3990; case BrownMushroomBlock::BrownMushroomBlock(true, true, true, false, true, true).ID: return 3991; case BrownMushroomBlock::BrownMushroomBlock(true, true, true, false, true, false).ID: return 3992; case BrownMushroomBlock::BrownMushroomBlock(true, true, true, false, false, true).ID: return 3993; case BrownMushroomBlock::BrownMushroomBlock(true, true, true, false, false, false).ID: return 3994; case BrownMushroomBlock::BrownMushroomBlock(true, true, false, true, true, true).ID: return 3995; case BrownMushroomBlock::BrownMushroomBlock(true, true, false, true, true, false).ID: return 3996; case BrownMushroomBlock::BrownMushroomBlock(true, true, false, true, false, true).ID: return 3997; case BrownMushroomBlock::BrownMushroomBlock(true, true, false, true, false, false).ID: return 3998; case BrownMushroomBlock::BrownMushroomBlock(true, true, false, false, true, true).ID: return 3999; case BrownMushroomBlock::BrownMushroomBlock(true, true, false, false, true, false).ID: return 4000; case BrownMushroomBlock::BrownMushroomBlock(true, true, false, false, false, true).ID: return 4001; case BrownMushroomBlock::BrownMushroomBlock(true, true, false, false, false, false).ID: return 4002; case BrownMushroomBlock::BrownMushroomBlock(true, false, true, true, true, true).ID: return 4003; case BrownMushroomBlock::BrownMushroomBlock(true, false, true, true, true, false).ID: return 4004; case BrownMushroomBlock::BrownMushroomBlock(true, false, true, true, false, true).ID: return 4005; case BrownMushroomBlock::BrownMushroomBlock(true, false, true, true, false, false).ID: return 4006; case BrownMushroomBlock::BrownMushroomBlock(true, false, true, false, true, true).ID: return 4007; case BrownMushroomBlock::BrownMushroomBlock(true, false, true, false, true, false).ID: return 4008; case BrownMushroomBlock::BrownMushroomBlock(true, false, true, false, false, true).ID: return 4009; case BrownMushroomBlock::BrownMushroomBlock(true, false, true, false, false, false).ID: return 4010; case BrownMushroomBlock::BrownMushroomBlock(true, false, false, true, true, true).ID: return 4011; case BrownMushroomBlock::BrownMushroomBlock(true, false, false, true, true, false).ID: return 4012; case BrownMushroomBlock::BrownMushroomBlock(true, false, false, true, false, true).ID: return 4013; case BrownMushroomBlock::BrownMushroomBlock(true, false, false, true, false, false).ID: return 4014; case BrownMushroomBlock::BrownMushroomBlock(true, false, false, false, true, true).ID: return 4015; case BrownMushroomBlock::BrownMushroomBlock(true, false, false, false, true, false).ID: return 4016; case BrownMushroomBlock::BrownMushroomBlock(true, false, false, false, false, true).ID: return 4017; case BrownMushroomBlock::BrownMushroomBlock(true, false, false, false, false, false).ID: return 4018; case BrownMushroomBlock::BrownMushroomBlock(false, true, true, true, true, true).ID: return 4019; case BrownMushroomBlock::BrownMushroomBlock(false, true, true, true, true, false).ID: return 4020; case BrownMushroomBlock::BrownMushroomBlock(false, true, true, true, false, true).ID: return 4021; case BrownMushroomBlock::BrownMushroomBlock(false, true, true, true, false, false).ID: return 4022; case BrownMushroomBlock::BrownMushroomBlock(false, true, true, false, true, true).ID: return 4023; case BrownMushroomBlock::BrownMushroomBlock(false, true, true, false, true, false).ID: return 4024; case BrownMushroomBlock::BrownMushroomBlock(false, true, true, false, false, true).ID: return 4025; case BrownMushroomBlock::BrownMushroomBlock(false, true, true, false, false, false).ID: return 4026; case BrownMushroomBlock::BrownMushroomBlock(false, true, false, true, true, true).ID: return 4027; case BrownMushroomBlock::BrownMushroomBlock(false, true, false, true, true, false).ID: return 4028; case BrownMushroomBlock::BrownMushroomBlock(false, true, false, true, false, true).ID: return 4029; case BrownMushroomBlock::BrownMushroomBlock(false, true, false, true, false, false).ID: return 4030; case BrownMushroomBlock::BrownMushroomBlock(false, true, false, false, true, true).ID: return 4031; case BrownMushroomBlock::BrownMushroomBlock(false, true, false, false, true, false).ID: return 4032; case BrownMushroomBlock::BrownMushroomBlock(false, true, false, false, false, true).ID: return 4033; case BrownMushroomBlock::BrownMushroomBlock(false, true, false, false, false, false).ID: return 4034; case BrownMushroomBlock::BrownMushroomBlock(false, false, true, true, true, true).ID: return 4035; case BrownMushroomBlock::BrownMushroomBlock(false, false, true, true, true, false).ID: return 4036; case BrownMushroomBlock::BrownMushroomBlock(false, false, true, true, false, true).ID: return 4037; case BrownMushroomBlock::BrownMushroomBlock(false, false, true, true, false, false).ID: return 4038; case BrownMushroomBlock::BrownMushroomBlock(false, false, true, false, true, true).ID: return 4039; case BrownMushroomBlock::BrownMushroomBlock(false, false, true, false, true, false).ID: return 4040; case BrownMushroomBlock::BrownMushroomBlock(false, false, true, false, false, true).ID: return 4041; case BrownMushroomBlock::BrownMushroomBlock(false, false, true, false, false, false).ID: return 4042; case BrownMushroomBlock::BrownMushroomBlock(false, false, false, true, true, true).ID: return 4043; case BrownMushroomBlock::BrownMushroomBlock(false, false, false, true, true, false).ID: return 4044; case BrownMushroomBlock::BrownMushroomBlock(false, false, false, true, false, true).ID: return 4045; case BrownMushroomBlock::BrownMushroomBlock(false, false, false, true, false, false).ID: return 4046; case BrownMushroomBlock::BrownMushroomBlock(false, false, false, false, true, true).ID: return 4047; case BrownMushroomBlock::BrownMushroomBlock(false, false, false, false, true, false).ID: return 4048; case BrownMushroomBlock::BrownMushroomBlock(false, false, false, false, false, true).ID: return 4049; case BrownMushroomBlock::BrownMushroomBlock(false, false, false, false, false, false).ID: return 4050; case BrownShulkerBox::BrownShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 8289; case BrownShulkerBox::BrownShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 8290; case BrownShulkerBox::BrownShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 8291; case BrownShulkerBox::BrownShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 8292; case BrownShulkerBox::BrownShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 8293; case BrownShulkerBox::BrownShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 8294; case BrownStainedGlass::BrownStainedGlass().ID: return 3589; case BrownStainedGlassPane::BrownStainedGlassPane(true, true, true, true).ID: return 6206; case BrownStainedGlassPane::BrownStainedGlassPane(true, true, true, false).ID: return 6207; case BrownStainedGlassPane::BrownStainedGlassPane(true, true, false, true).ID: return 6210; case BrownStainedGlassPane::BrownStainedGlassPane(true, true, false, false).ID: return 6211; case BrownStainedGlassPane::BrownStainedGlassPane(true, false, true, true).ID: return 6214; case BrownStainedGlassPane::BrownStainedGlassPane(true, false, true, false).ID: return 6215; case BrownStainedGlassPane::BrownStainedGlassPane(true, false, false, true).ID: return 6218; case BrownStainedGlassPane::BrownStainedGlassPane(true, false, false, false).ID: return 6219; case BrownStainedGlassPane::BrownStainedGlassPane(false, true, true, true).ID: return 6222; case BrownStainedGlassPane::BrownStainedGlassPane(false, true, true, false).ID: return 6223; case BrownStainedGlassPane::BrownStainedGlassPane(false, true, false, true).ID: return 6226; case BrownStainedGlassPane::BrownStainedGlassPane(false, true, false, false).ID: return 6227; case BrownStainedGlassPane::BrownStainedGlassPane(false, false, true, true).ID: return 6230; case BrownStainedGlassPane::BrownStainedGlassPane(false, false, true, false).ID: return 6231; case BrownStainedGlassPane::BrownStainedGlassPane(false, false, false, true).ID: return 6234; case BrownStainedGlassPane::BrownStainedGlassPane(false, false, false, false).ID: return 6235; case BrownTerracotta::BrownTerracotta().ID: return 5816; case BrownWallBanner::BrownWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 7158; case BrownWallBanner::BrownWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 7159; case BrownWallBanner::BrownWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 7160; case BrownWallBanner::BrownWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 7161; case BrownWool::BrownWool().ID: return 1095; case BubbleColumn::BubbleColumn(true).ID: return 8576; case BubbleColumn::BubbleColumn(false).ID: return 8577; case BubbleCoral::BubbleCoral().ID: return 8461; case BubbleCoralBlock::BubbleCoralBlock().ID: return 8456; case BubbleCoralFan::BubbleCoralFan().ID: return 8559; case BubbleCoralWallFan::BubbleCoralWallFan(eBlockFace::BLOCK_FACE_ZM).ID: return 8521; case BubbleCoralWallFan::BubbleCoralWallFan(eBlockFace::BLOCK_FACE_ZP).ID: return 8523; case BubbleCoralWallFan::BubbleCoralWallFan(eBlockFace::BLOCK_FACE_XM).ID: return 8525; case BubbleCoralWallFan::BubbleCoralWallFan(eBlockFace::BLOCK_FACE_XP).ID: return 8527; case Cactus::Cactus(0).ID: return 3425; case Cactus::Cactus(1).ID: return 3426; case Cactus::Cactus(2).ID: return 3427; case Cactus::Cactus(3).ID: return 3428; case Cactus::Cactus(4).ID: return 3429; case Cactus::Cactus(5).ID: return 3430; case Cactus::Cactus(6).ID: return 3431; case Cactus::Cactus(7).ID: return 3432; case Cactus::Cactus(8).ID: return 3433; case Cactus::Cactus(9).ID: return 3434; case Cactus::Cactus(10).ID: return 3435; case Cactus::Cactus(11).ID: return 3436; case Cactus::Cactus(12).ID: return 3437; case Cactus::Cactus(13).ID: return 3438; case Cactus::Cactus(14).ID: return 3439; case Cactus::Cactus(15).ID: return 3440; case Cake::Cake(0).ID: return 3506; case Cake::Cake(1).ID: return 3507; case Cake::Cake(2).ID: return 3508; case Cake::Cake(3).ID: return 3509; case Cake::Cake(4).ID: return 3510; case Cake::Cake(5).ID: return 3511; case Cake::Cake(6).ID: return 3512; case Carrots::Carrots(0).ID: return 5287; case Carrots::Carrots(1).ID: return 5288; case Carrots::Carrots(2).ID: return 5289; case Carrots::Carrots(3).ID: return 5290; case Carrots::Carrots(4).ID: return 5291; case Carrots::Carrots(5).ID: return 5292; case Carrots::Carrots(6).ID: return 5293; case Carrots::Carrots(7).ID: return 5294; case CarvedPumpkin::CarvedPumpkin(eBlockFace::BLOCK_FACE_ZM).ID: return 3498; case CarvedPumpkin::CarvedPumpkin(eBlockFace::BLOCK_FACE_ZP).ID: return 3499; case CarvedPumpkin::CarvedPumpkin(eBlockFace::BLOCK_FACE_XM).ID: return 3500; case CarvedPumpkin::CarvedPumpkin(eBlockFace::BLOCK_FACE_XP).ID: return 3501; case Cauldron::Cauldron(0).ID: return 4621; case Cauldron::Cauldron(1).ID: return 4622; case Cauldron::Cauldron(2).ID: return 4623; case Cauldron::Cauldron(3).ID: return 4624; case CaveAir::CaveAir().ID: return 8575; case ChainCommandBlock::ChainCommandBlock(true, eBlockFace::BLOCK_FACE_ZM).ID: return 8176; case ChainCommandBlock::ChainCommandBlock(true, eBlockFace::BLOCK_FACE_XP).ID: return 8177; case ChainCommandBlock::ChainCommandBlock(true, eBlockFace::BLOCK_FACE_ZP).ID: return 8178; case ChainCommandBlock::ChainCommandBlock(true, eBlockFace::BLOCK_FACE_XM).ID: return 8179; case ChainCommandBlock::ChainCommandBlock(true, eBlockFace::BLOCK_FACE_YP).ID: return 8180; case ChainCommandBlock::ChainCommandBlock(true, eBlockFace::BLOCK_FACE_YM).ID: return 8181; case ChainCommandBlock::ChainCommandBlock(false, eBlockFace::BLOCK_FACE_ZM).ID: return 8182; case ChainCommandBlock::ChainCommandBlock(false, eBlockFace::BLOCK_FACE_XP).ID: return 8183; case ChainCommandBlock::ChainCommandBlock(false, eBlockFace::BLOCK_FACE_ZP).ID: return 8184; case ChainCommandBlock::ChainCommandBlock(false, eBlockFace::BLOCK_FACE_XM).ID: return 8185; case ChainCommandBlock::ChainCommandBlock(false, eBlockFace::BLOCK_FACE_YP).ID: return 8186; case ChainCommandBlock::ChainCommandBlock(false, eBlockFace::BLOCK_FACE_YM).ID: return 8187; case Chest::Chest(eBlockFace::BLOCK_FACE_ZM, Chest::Type::Single).ID: return 1729; case Chest::Chest(eBlockFace::BLOCK_FACE_ZM, Chest::Type::Left).ID: return 1731; case Chest::Chest(eBlockFace::BLOCK_FACE_ZM, Chest::Type::Right).ID: return 1733; case Chest::Chest(eBlockFace::BLOCK_FACE_ZP, Chest::Type::Single).ID: return 1735; case Chest::Chest(eBlockFace::BLOCK_FACE_ZP, Chest::Type::Left).ID: return 1737; case Chest::Chest(eBlockFace::BLOCK_FACE_ZP, Chest::Type::Right).ID: return 1739; case Chest::Chest(eBlockFace::BLOCK_FACE_XM, Chest::Type::Single).ID: return 1741; case Chest::Chest(eBlockFace::BLOCK_FACE_XM, Chest::Type::Left).ID: return 1743; case Chest::Chest(eBlockFace::BLOCK_FACE_XM, Chest::Type::Right).ID: return 1745; case Chest::Chest(eBlockFace::BLOCK_FACE_XP, Chest::Type::Single).ID: return 1747; case Chest::Chest(eBlockFace::BLOCK_FACE_XP, Chest::Type::Left).ID: return 1749; case Chest::Chest(eBlockFace::BLOCK_FACE_XP, Chest::Type::Right).ID: return 1751; case ChippedAnvil::ChippedAnvil(eBlockFace::BLOCK_FACE_ZM).ID: return 5571; case ChippedAnvil::ChippedAnvil(eBlockFace::BLOCK_FACE_ZP).ID: return 5572; case ChippedAnvil::ChippedAnvil(eBlockFace::BLOCK_FACE_XM).ID: return 5573; case ChippedAnvil::ChippedAnvil(eBlockFace::BLOCK_FACE_XP).ID: return 5574; case ChiseledQuartzBlock::ChiseledQuartzBlock().ID: return 5696; case ChiseledRedSandstone::ChiseledRedSandstone().ID: return 7175; case ChiseledSandstone::ChiseledSandstone().ID: return 246; case ChiseledStoneBricks::ChiseledStoneBricks().ID: return 3986; case ChorusFlower::ChorusFlower(0).ID: return 8067; case ChorusFlower::ChorusFlower(1).ID: return 8068; case ChorusFlower::ChorusFlower(2).ID: return 8069; case ChorusFlower::ChorusFlower(3).ID: return 8070; case ChorusFlower::ChorusFlower(4).ID: return 8071; case ChorusFlower::ChorusFlower(5).ID: return 8072; case ChorusPlant::ChorusPlant(true, true, true, true, true, true).ID: return 8003; case ChorusPlant::ChorusPlant(true, true, true, true, true, false).ID: return 8004; case ChorusPlant::ChorusPlant(true, true, true, true, false, true).ID: return 8005; case ChorusPlant::ChorusPlant(true, true, true, true, false, false).ID: return 8006; case ChorusPlant::ChorusPlant(true, true, true, false, true, true).ID: return 8007; case ChorusPlant::ChorusPlant(true, true, true, false, true, false).ID: return 8008; case ChorusPlant::ChorusPlant(true, true, true, false, false, true).ID: return 8009; case ChorusPlant::ChorusPlant(true, true, true, false, false, false).ID: return 8010; case ChorusPlant::ChorusPlant(true, true, false, true, true, true).ID: return 8011; case ChorusPlant::ChorusPlant(true, true, false, true, true, false).ID: return 8012; case ChorusPlant::ChorusPlant(true, true, false, true, false, true).ID: return 8013; case ChorusPlant::ChorusPlant(true, true, false, true, false, false).ID: return 8014; case ChorusPlant::ChorusPlant(true, true, false, false, true, true).ID: return 8015; case ChorusPlant::ChorusPlant(true, true, false, false, true, false).ID: return 8016; case ChorusPlant::ChorusPlant(true, true, false, false, false, true).ID: return 8017; case ChorusPlant::ChorusPlant(true, true, false, false, false, false).ID: return 8018; case ChorusPlant::ChorusPlant(true, false, true, true, true, true).ID: return 8019; case ChorusPlant::ChorusPlant(true, false, true, true, true, false).ID: return 8020; case ChorusPlant::ChorusPlant(true, false, true, true, false, true).ID: return 8021; case ChorusPlant::ChorusPlant(true, false, true, true, false, false).ID: return 8022; case ChorusPlant::ChorusPlant(true, false, true, false, true, true).ID: return 8023; case ChorusPlant::ChorusPlant(true, false, true, false, true, false).ID: return 8024; case ChorusPlant::ChorusPlant(true, false, true, false, false, true).ID: return 8025; case ChorusPlant::ChorusPlant(true, false, true, false, false, false).ID: return 8026; case ChorusPlant::ChorusPlant(true, false, false, true, true, true).ID: return 8027; case ChorusPlant::ChorusPlant(true, false, false, true, true, false).ID: return 8028; case ChorusPlant::ChorusPlant(true, false, false, true, false, true).ID: return 8029; case ChorusPlant::ChorusPlant(true, false, false, true, false, false).ID: return 8030; case ChorusPlant::ChorusPlant(true, false, false, false, true, true).ID: return 8031; case ChorusPlant::ChorusPlant(true, false, false, false, true, false).ID: return 8032; case ChorusPlant::ChorusPlant(true, false, false, false, false, true).ID: return 8033; case ChorusPlant::ChorusPlant(true, false, false, false, false, false).ID: return 8034; case ChorusPlant::ChorusPlant(false, true, true, true, true, true).ID: return 8035; case ChorusPlant::ChorusPlant(false, true, true, true, true, false).ID: return 8036; case ChorusPlant::ChorusPlant(false, true, true, true, false, true).ID: return 8037; case ChorusPlant::ChorusPlant(false, true, true, true, false, false).ID: return 8038; case ChorusPlant::ChorusPlant(false, true, true, false, true, true).ID: return 8039; case ChorusPlant::ChorusPlant(false, true, true, false, true, false).ID: return 8040; case ChorusPlant::ChorusPlant(false, true, true, false, false, true).ID: return 8041; case ChorusPlant::ChorusPlant(false, true, true, false, false, false).ID: return 8042; case ChorusPlant::ChorusPlant(false, true, false, true, true, true).ID: return 8043; case ChorusPlant::ChorusPlant(false, true, false, true, true, false).ID: return 8044; case ChorusPlant::ChorusPlant(false, true, false, true, false, true).ID: return 8045; case ChorusPlant::ChorusPlant(false, true, false, true, false, false).ID: return 8046; case ChorusPlant::ChorusPlant(false, true, false, false, true, true).ID: return 8047; case ChorusPlant::ChorusPlant(false, true, false, false, true, false).ID: return 8048; case ChorusPlant::ChorusPlant(false, true, false, false, false, true).ID: return 8049; case ChorusPlant::ChorusPlant(false, true, false, false, false, false).ID: return 8050; case ChorusPlant::ChorusPlant(false, false, true, true, true, true).ID: return 8051; case ChorusPlant::ChorusPlant(false, false, true, true, true, false).ID: return 8052; case ChorusPlant::ChorusPlant(false, false, true, true, false, true).ID: return 8053; case ChorusPlant::ChorusPlant(false, false, true, true, false, false).ID: return 8054; case ChorusPlant::ChorusPlant(false, false, true, false, true, true).ID: return 8055; case ChorusPlant::ChorusPlant(false, false, true, false, true, false).ID: return 8056; case ChorusPlant::ChorusPlant(false, false, true, false, false, true).ID: return 8057; case ChorusPlant::ChorusPlant(false, false, true, false, false, false).ID: return 8058; case ChorusPlant::ChorusPlant(false, false, false, true, true, true).ID: return 8059; case ChorusPlant::ChorusPlant(false, false, false, true, true, false).ID: return 8060; case ChorusPlant::ChorusPlant(false, false, false, true, false, true).ID: return 8061; case ChorusPlant::ChorusPlant(false, false, false, true, false, false).ID: return 8062; case ChorusPlant::ChorusPlant(false, false, false, false, true, true).ID: return 8063; case ChorusPlant::ChorusPlant(false, false, false, false, true, false).ID: return 8064; case ChorusPlant::ChorusPlant(false, false, false, false, false, true).ID: return 8065; case ChorusPlant::ChorusPlant(false, false, false, false, false, false).ID: return 8066; case Clay::Clay().ID: return 3441; case CoalBlock::CoalBlock().ID: return 6840; case CoalOre::CoalOre().ID: return 71; case CoarseDirt::CoarseDirt().ID: return 11; case Cobblestone::Cobblestone().ID: return 14; case CobblestoneSlab::CobblestoneSlab(CobblestoneSlab::Type::Top).ID: return 7312; case CobblestoneSlab::CobblestoneSlab(CobblestoneSlab::Type::Bottom).ID: return 7314; case CobblestoneSlab::CobblestoneSlab(CobblestoneSlab::Type::Double).ID: return 7316; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::Straight).ID: return 3190; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::InnerLeft).ID: return 3192; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::InnerRight).ID: return 3194; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::OuterLeft).ID: return 3196; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::OuterRight).ID: return 3198; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::Straight).ID: return 3200; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::InnerLeft).ID: return 3202; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::InnerRight).ID: return 3204; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::OuterLeft).ID: return 3206; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::OuterRight).ID: return 3208; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::Straight).ID: return 3210; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::InnerLeft).ID: return 3212; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::InnerRight).ID: return 3214; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::OuterLeft).ID: return 3216; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::OuterRight).ID: return 3218; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::Straight).ID: return 3220; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::InnerLeft).ID: return 3222; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::InnerRight).ID: return 3224; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::OuterLeft).ID: return 3226; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::OuterRight).ID: return 3228; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XM, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::Straight).ID: return 3230; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XM, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::InnerLeft).ID: return 3232; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XM, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::InnerRight).ID: return 3234; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XM, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::OuterLeft).ID: return 3236; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XM, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::OuterRight).ID: return 3238; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XM, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::Straight).ID: return 3240; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XM, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::InnerLeft).ID: return 3242; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XM, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::InnerRight).ID: return 3244; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XM, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::OuterLeft).ID: return 3246; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XM, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::OuterRight).ID: return 3248; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XP, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::Straight).ID: return 3250; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XP, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::InnerLeft).ID: return 3252; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XP, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::InnerRight).ID: return 3254; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XP, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::OuterLeft).ID: return 3256; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XP, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::OuterRight).ID: return 3258; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XP, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::Straight).ID: return 3260; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XP, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::InnerLeft).ID: return 3262; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XP, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::InnerRight).ID: return 3264; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XP, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::OuterLeft).ID: return 3266; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XP, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::OuterRight).ID: return 3268; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::Low, CobblestoneWall::South::Low, true, CobblestoneWall::West::Low).ID: return 5139; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::Low, CobblestoneWall::South::Low, true, CobblestoneWall::West::None).ID: return 5140; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::Low, CobblestoneWall::South::Low, false, CobblestoneWall::West::Low).ID: return 5143; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::Low, CobblestoneWall::South::Low, false, CobblestoneWall::West::None).ID: return 5144; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::Low, CobblestoneWall::South::None, true, CobblestoneWall::West::Low).ID: return 5147; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::Low, CobblestoneWall::South::None, true, CobblestoneWall::West::None).ID: return 5148; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::Low, CobblestoneWall::South::None, false, CobblestoneWall::West::Low).ID: return 5151; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::Low, CobblestoneWall::South::None, false, CobblestoneWall::West::None).ID: return 5152; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::None, CobblestoneWall::South::Low, true, CobblestoneWall::West::Low).ID: return 5155; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::None, CobblestoneWall::South::Low, true, CobblestoneWall::West::None).ID: return 5156; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::None, CobblestoneWall::South::Low, false, CobblestoneWall::West::Low).ID: return 5159; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::None, CobblestoneWall::South::Low, false, CobblestoneWall::West::None).ID: return 5160; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::None, CobblestoneWall::South::None, true, CobblestoneWall::West::Low).ID: return 5163; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::None, CobblestoneWall::South::None, true, CobblestoneWall::West::None).ID: return 5164; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::None, CobblestoneWall::South::None, false, CobblestoneWall::West::Low).ID: return 5167; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::None, CobblestoneWall::South::None, false, CobblestoneWall::West::None).ID: return 5168; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::Low, CobblestoneWall::South::Low, true, CobblestoneWall::West::Low).ID: return 5171; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::Low, CobblestoneWall::South::Low, true, CobblestoneWall::West::None).ID: return 5172; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::Low, CobblestoneWall::South::Low, false, CobblestoneWall::West::Low).ID: return 5175; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::Low, CobblestoneWall::South::Low, false, CobblestoneWall::West::None).ID: return 5176; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::Low, CobblestoneWall::South::None, true, CobblestoneWall::West::Low).ID: return 5179; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::Low, CobblestoneWall::South::None, true, CobblestoneWall::West::None).ID: return 5180; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::Low, CobblestoneWall::South::None, false, CobblestoneWall::West::Low).ID: return 5183; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::Low, CobblestoneWall::South::None, false, CobblestoneWall::West::None).ID: return 5184; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::None, CobblestoneWall::South::Low, true, CobblestoneWall::West::Low).ID: return 5187; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::None, CobblestoneWall::South::Low, true, CobblestoneWall::West::None).ID: return 5188; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::None, CobblestoneWall::South::Low, false, CobblestoneWall::West::Low).ID: return 5191; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::None, CobblestoneWall::South::Low, false, CobblestoneWall::West::None).ID: return 5192; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::None, CobblestoneWall::South::None, true, CobblestoneWall::West::Low).ID: return 5195; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::None, CobblestoneWall::South::None, true, CobblestoneWall::West::None).ID: return 5196; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::None, CobblestoneWall::South::None, false, CobblestoneWall::West::Low).ID: return 5199; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::None, CobblestoneWall::South::None, false, CobblestoneWall::West::None).ID: return 5200; case Cobweb::Cobweb().ID: return 1040; case Cocoa::Cocoa(0, eBlockFace::BLOCK_FACE_ZM).ID: return 4638; case Cocoa::Cocoa(0, eBlockFace::BLOCK_FACE_ZP).ID: return 4639; case Cocoa::Cocoa(0, eBlockFace::BLOCK_FACE_XM).ID: return 4640; case Cocoa::Cocoa(0, eBlockFace::BLOCK_FACE_XP).ID: return 4641; case Cocoa::Cocoa(1, eBlockFace::BLOCK_FACE_ZM).ID: return 4642; case Cocoa::Cocoa(1, eBlockFace::BLOCK_FACE_ZP).ID: return 4643; case Cocoa::Cocoa(1, eBlockFace::BLOCK_FACE_XM).ID: return 4644; case Cocoa::Cocoa(1, eBlockFace::BLOCK_FACE_XP).ID: return 4645; case Cocoa::Cocoa(2, eBlockFace::BLOCK_FACE_ZM).ID: return 4646; case Cocoa::Cocoa(2, eBlockFace::BLOCK_FACE_ZP).ID: return 4647; case Cocoa::Cocoa(2, eBlockFace::BLOCK_FACE_XM).ID: return 4648; case Cocoa::Cocoa(2, eBlockFace::BLOCK_FACE_XP).ID: return 4649; case CommandBlock::CommandBlock(true, eBlockFace::BLOCK_FACE_ZM).ID: return 5124; case CommandBlock::CommandBlock(true, eBlockFace::BLOCK_FACE_XP).ID: return 5125; case CommandBlock::CommandBlock(true, eBlockFace::BLOCK_FACE_ZP).ID: return 5126; case CommandBlock::CommandBlock(true, eBlockFace::BLOCK_FACE_XM).ID: return 5127; case CommandBlock::CommandBlock(true, eBlockFace::BLOCK_FACE_YP).ID: return 5128; case CommandBlock::CommandBlock(true, eBlockFace::BLOCK_FACE_YM).ID: return 5129; case CommandBlock::CommandBlock(false, eBlockFace::BLOCK_FACE_ZM).ID: return 5130; case CommandBlock::CommandBlock(false, eBlockFace::BLOCK_FACE_XP).ID: return 5131; case CommandBlock::CommandBlock(false, eBlockFace::BLOCK_FACE_ZP).ID: return 5132; case CommandBlock::CommandBlock(false, eBlockFace::BLOCK_FACE_XM).ID: return 5133; case CommandBlock::CommandBlock(false, eBlockFace::BLOCK_FACE_YP).ID: return 5134; case CommandBlock::CommandBlock(false, eBlockFace::BLOCK_FACE_YM).ID: return 5135; case Comparator::Comparator(eBlockFace::BLOCK_FACE_ZM, Comparator::Mode::Compare, true).ID: return 5635; case Comparator::Comparator(eBlockFace::BLOCK_FACE_ZM, Comparator::Mode::Compare, false).ID: return 5636; case Comparator::Comparator(eBlockFace::BLOCK_FACE_ZM, Comparator::Mode::Subtract, true).ID: return 5637; case Comparator::Comparator(eBlockFace::BLOCK_FACE_ZM, Comparator::Mode::Subtract, false).ID: return 5638; case Comparator::Comparator(eBlockFace::BLOCK_FACE_ZP, Comparator::Mode::Compare, true).ID: return 5639; case Comparator::Comparator(eBlockFace::BLOCK_FACE_ZP, Comparator::Mode::Compare, false).ID: return 5640; case Comparator::Comparator(eBlockFace::BLOCK_FACE_ZP, Comparator::Mode::Subtract, true).ID: return 5641; case Comparator::Comparator(eBlockFace::BLOCK_FACE_ZP, Comparator::Mode::Subtract, false).ID: return 5642; case Comparator::Comparator(eBlockFace::BLOCK_FACE_XM, Comparator::Mode::Compare, true).ID: return 5643; case Comparator::Comparator(eBlockFace::BLOCK_FACE_XM, Comparator::Mode::Compare, false).ID: return 5644; case Comparator::Comparator(eBlockFace::BLOCK_FACE_XM, Comparator::Mode::Subtract, true).ID: return 5645; case Comparator::Comparator(eBlockFace::BLOCK_FACE_XM, Comparator::Mode::Subtract, false).ID: return 5646; case Comparator::Comparator(eBlockFace::BLOCK_FACE_XP, Comparator::Mode::Compare, true).ID: return 5647; case Comparator::Comparator(eBlockFace::BLOCK_FACE_XP, Comparator::Mode::Compare, false).ID: return 5648; case Comparator::Comparator(eBlockFace::BLOCK_FACE_XP, Comparator::Mode::Subtract, true).ID: return 5649; case Comparator::Comparator(eBlockFace::BLOCK_FACE_XP, Comparator::Mode::Subtract, false).ID: return 5650; case Conduit::Conduit().ID: return 8573; case CrackedStoneBricks::CrackedStoneBricks().ID: return 3985; case CraftingTable::CraftingTable().ID: return 3050; case CreeperHead::CreeperHead(0).ID: return 5531; case CreeperHead::CreeperHead(1).ID: return 5532; case CreeperHead::CreeperHead(2).ID: return 5533; case CreeperHead::CreeperHead(3).ID: return 5534; case CreeperHead::CreeperHead(4).ID: return 5535; case CreeperHead::CreeperHead(5).ID: return 5536; case CreeperHead::CreeperHead(6).ID: return 5537; case CreeperHead::CreeperHead(7).ID: return 5538; case CreeperHead::CreeperHead(8).ID: return 5539; case CreeperHead::CreeperHead(9).ID: return 5540; case CreeperHead::CreeperHead(10).ID: return 5541; case CreeperHead::CreeperHead(11).ID: return 5542; case CreeperHead::CreeperHead(12).ID: return 5543; case CreeperHead::CreeperHead(13).ID: return 5544; case CreeperHead::CreeperHead(14).ID: return 5545; case CreeperHead::CreeperHead(15).ID: return 5546; case CreeperWallHead::CreeperWallHead(eBlockFace::BLOCK_FACE_ZM).ID: return 5527; case CreeperWallHead::CreeperWallHead(eBlockFace::BLOCK_FACE_ZP).ID: return 5528; case CreeperWallHead::CreeperWallHead(eBlockFace::BLOCK_FACE_XM).ID: return 5529; case CreeperWallHead::CreeperWallHead(eBlockFace::BLOCK_FACE_XP).ID: return 5530; case CutRedSandstone::CutRedSandstone().ID: return 7176; case CutSandstone::CutSandstone().ID: return 247; case CyanBanner::CyanBanner(0).ID: return 6998; case CyanBanner::CyanBanner(1).ID: return 6999; case CyanBanner::CyanBanner(2).ID: return 7000; case CyanBanner::CyanBanner(3).ID: return 7001; case CyanBanner::CyanBanner(4).ID: return 7002; case CyanBanner::CyanBanner(5).ID: return 7003; case CyanBanner::CyanBanner(6).ID: return 7004; case CyanBanner::CyanBanner(7).ID: return 7005; case CyanBanner::CyanBanner(8).ID: return 7006; case CyanBanner::CyanBanner(9).ID: return 7007; case CyanBanner::CyanBanner(10).ID: return 7008; case CyanBanner::CyanBanner(11).ID: return 7009; case CyanBanner::CyanBanner(12).ID: return 7010; case CyanBanner::CyanBanner(13).ID: return 7011; case CyanBanner::CyanBanner(14).ID: return 7012; case CyanBanner::CyanBanner(15).ID: return 7013; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_ZM, true, CyanBed::Part::Head).ID: return 892; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_ZM, true, CyanBed::Part::Foot).ID: return 893; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_ZM, false, CyanBed::Part::Head).ID: return 894; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_ZM, false, CyanBed::Part::Foot).ID: return 895; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_ZP, true, CyanBed::Part::Head).ID: return 896; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_ZP, true, CyanBed::Part::Foot).ID: return 897; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_ZP, false, CyanBed::Part::Head).ID: return 898; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_ZP, false, CyanBed::Part::Foot).ID: return 899; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_XM, true, CyanBed::Part::Head).ID: return 900; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_XM, true, CyanBed::Part::Foot).ID: return 901; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_XM, false, CyanBed::Part::Head).ID: return 902; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_XM, false, CyanBed::Part::Foot).ID: return 903; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_XP, true, CyanBed::Part::Head).ID: return 904; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_XP, true, CyanBed::Part::Foot).ID: return 905; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_XP, false, CyanBed::Part::Head).ID: return 906; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_XP, false, CyanBed::Part::Foot).ID: return 907; case CyanCarpet::CyanCarpet().ID: return 6832; case CyanConcrete::CyanConcrete().ID: return 8386; case CyanConcretePowder::CyanConcretePowder().ID: return 8402; case CyanGlazedTerracotta::CyanGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 8349; case CyanGlazedTerracotta::CyanGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 8350; case CyanGlazedTerracotta::CyanGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 8351; case CyanGlazedTerracotta::CyanGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 8352; case CyanShulkerBox::CyanShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 8271; case CyanShulkerBox::CyanShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 8272; case CyanShulkerBox::CyanShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 8273; case CyanShulkerBox::CyanShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 8274; case CyanShulkerBox::CyanShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 8275; case CyanShulkerBox::CyanShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 8276; case CyanStainedGlass::CyanStainedGlass().ID: return 3586; case CyanStainedGlassPane::CyanStainedGlassPane(true, true, true, true).ID: return 6110; case CyanStainedGlassPane::CyanStainedGlassPane(true, true, true, false).ID: return 6111; case CyanStainedGlassPane::CyanStainedGlassPane(true, true, false, true).ID: return 6114; case CyanStainedGlassPane::CyanStainedGlassPane(true, true, false, false).ID: return 6115; case CyanStainedGlassPane::CyanStainedGlassPane(true, false, true, true).ID: return 6118; case CyanStainedGlassPane::CyanStainedGlassPane(true, false, true, false).ID: return 6119; case CyanStainedGlassPane::CyanStainedGlassPane(true, false, false, true).ID: return 6122; case CyanStainedGlassPane::CyanStainedGlassPane(true, false, false, false).ID: return 6123; case CyanStainedGlassPane::CyanStainedGlassPane(false, true, true, true).ID: return 6126; case CyanStainedGlassPane::CyanStainedGlassPane(false, true, true, false).ID: return 6127; case CyanStainedGlassPane::CyanStainedGlassPane(false, true, false, true).ID: return 6130; case CyanStainedGlassPane::CyanStainedGlassPane(false, true, false, false).ID: return 6131; case CyanStainedGlassPane::CyanStainedGlassPane(false, false, true, true).ID: return 6134; case CyanStainedGlassPane::CyanStainedGlassPane(false, false, true, false).ID: return 6135; case CyanStainedGlassPane::CyanStainedGlassPane(false, false, false, true).ID: return 6138; case CyanStainedGlassPane::CyanStainedGlassPane(false, false, false, false).ID: return 6139; case CyanTerracotta::CyanTerracotta().ID: return 5813; case CyanWallBanner::CyanWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 7146; case CyanWallBanner::CyanWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 7147; case CyanWallBanner::CyanWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 7148; case CyanWallBanner::CyanWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 7149; case CyanWool::CyanWool().ID: return 1092; case DamagedAnvil::DamagedAnvil(eBlockFace::BLOCK_FACE_ZM).ID: return 5575; case DamagedAnvil::DamagedAnvil(eBlockFace::BLOCK_FACE_ZP).ID: return 5576; case DamagedAnvil::DamagedAnvil(eBlockFace::BLOCK_FACE_XM).ID: return 5577; case DamagedAnvil::DamagedAnvil(eBlockFace::BLOCK_FACE_XP).ID: return 5578; case Dandelion::Dandelion().ID: return 1111; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5423; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5424; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5425; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5426; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, true).ID: return 5427; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, false).ID: return 5428; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, true).ID: return 5429; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, false).ID: return 5430; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5431; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5432; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5433; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5434; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, true).ID: return 5435; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, false).ID: return 5436; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, true).ID: return 5437; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, false).ID: return 5438; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5439; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5440; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5441; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5442; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, true).ID: return 5443; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, false).ID: return 5444; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, true).ID: return 5445; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, false).ID: return 5446; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, true, true).ID: return 7933; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, true, false).ID: return 7934; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, false, true).ID: return 7935; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, false, false).ID: return 7936; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, true, true).ID: return 7937; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, true, false).ID: return 7938; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, false, true).ID: return 7939; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, false, false).ID: return 7940; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, true, true).ID: return 7941; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, true, false).ID: return 7942; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, false, true).ID: return 7943; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, false, false).ID: return 7944; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, true, true).ID: return 7945; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, true, false).ID: return 7946; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, false, true).ID: return 7947; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, false, false).ID: return 7948; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, true, true).ID: return 7949; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, true, false).ID: return 7950; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, false, true).ID: return 7951; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, false, false).ID: return 7952; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, true, true).ID: return 7953; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, true, false).ID: return 7954; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, false, true).ID: return 7955; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, false, false).ID: return 7956; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, true, true).ID: return 7957; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, true, false).ID: return 7958; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, false, true).ID: return 7959; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, false, false).ID: return 7960; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, true, true).ID: return 7961; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, true, false).ID: return 7962; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, false, true).ID: return 7963; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, false, false).ID: return 7964; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, true, true).ID: return 7965; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, true, false).ID: return 7966; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, false, true).ID: return 7967; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, false, false).ID: return 7968; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, true, true).ID: return 7969; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, true, false).ID: return 7970; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, false, true).ID: return 7971; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, false, false).ID: return 7972; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, true, true).ID: return 7973; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, true, false).ID: return 7974; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, false, true).ID: return 7975; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, false, false).ID: return 7976; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, true, true).ID: return 7977; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, true, false).ID: return 7978; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, false, true).ID: return 7979; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, false, false).ID: return 7980; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, true, true).ID: return 7981; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, true, false).ID: return 7982; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, false, true).ID: return 7983; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, false, false).ID: return 7984; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, true, true).ID: return 7985; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, true, false).ID: return 7986; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, false, true).ID: return 7987; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, false, false).ID: return 7988; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, true, true).ID: return 7989; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, true, false).ID: return 7990; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, false, true).ID: return 7991; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, false, false).ID: return 7992; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, true, true).ID: return 7993; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, true, false).ID: return 7994; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, false, true).ID: return 7995; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, false, false).ID: return 7996; case DarkOakFence::DarkOakFence(true, true, true, true).ID: return 7647; case DarkOakFence::DarkOakFence(true, true, true, false).ID: return 7648; case DarkOakFence::DarkOakFence(true, true, false, true).ID: return 7651; case DarkOakFence::DarkOakFence(true, true, false, false).ID: return 7652; case DarkOakFence::DarkOakFence(true, false, true, true).ID: return 7655; case DarkOakFence::DarkOakFence(true, false, true, false).ID: return 7656; case DarkOakFence::DarkOakFence(true, false, false, true).ID: return 7659; case DarkOakFence::DarkOakFence(true, false, false, false).ID: return 7660; case DarkOakFence::DarkOakFence(false, true, true, true).ID: return 7663; case DarkOakFence::DarkOakFence(false, true, true, false).ID: return 7664; case DarkOakFence::DarkOakFence(false, true, false, true).ID: return 7667; case DarkOakFence::DarkOakFence(false, true, false, false).ID: return 7668; case DarkOakFence::DarkOakFence(false, false, true, true).ID: return 7671; case DarkOakFence::DarkOakFence(false, false, true, false).ID: return 7672; case DarkOakFence::DarkOakFence(false, false, false, true).ID: return 7675; case DarkOakFence::DarkOakFence(false, false, false, false).ID: return 7676; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZM, true, true, true).ID: return 7485; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZM, true, true, false).ID: return 7486; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZM, true, false, true).ID: return 7487; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZM, true, false, false).ID: return 7488; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, true).ID: return 7489; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, false).ID: return 7490; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, true).ID: return 7491; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, false).ID: return 7492; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZP, true, true, true).ID: return 7493; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZP, true, true, false).ID: return 7494; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZP, true, false, true).ID: return 7495; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZP, true, false, false).ID: return 7496; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, true).ID: return 7497; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, false).ID: return 7498; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, true).ID: return 7499; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, false).ID: return 7500; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XM, true, true, true).ID: return 7501; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XM, true, true, false).ID: return 7502; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XM, true, false, true).ID: return 7503; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XM, true, false, false).ID: return 7504; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, true).ID: return 7505; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, false).ID: return 7506; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, true).ID: return 7507; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, false).ID: return 7508; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XP, true, true, true).ID: return 7509; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XP, true, true, false).ID: return 7510; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XP, true, false, true).ID: return 7511; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XP, true, false, false).ID: return 7512; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, true).ID: return 7513; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, false).ID: return 7514; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, true).ID: return 7515; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, false).ID: return 7516; case DarkOakLeaves::DarkOakLeaves(1, true).ID: return 214; case DarkOakLeaves::DarkOakLeaves(1, false).ID: return 215; case DarkOakLeaves::DarkOakLeaves(2, true).ID: return 216; case DarkOakLeaves::DarkOakLeaves(2, false).ID: return 217; case DarkOakLeaves::DarkOakLeaves(3, true).ID: return 218; case DarkOakLeaves::DarkOakLeaves(3, false).ID: return 219; case DarkOakLeaves::DarkOakLeaves(4, true).ID: return 220; case DarkOakLeaves::DarkOakLeaves(4, false).ID: return 221; case DarkOakLeaves::DarkOakLeaves(5, true).ID: return 222; case DarkOakLeaves::DarkOakLeaves(5, false).ID: return 223; case DarkOakLeaves::DarkOakLeaves(6, true).ID: return 224; case DarkOakLeaves::DarkOakLeaves(6, false).ID: return 225; case DarkOakLeaves::DarkOakLeaves(7, true).ID: return 226; case DarkOakLeaves::DarkOakLeaves(7, false).ID: return 227; case DarkOakLog::DarkOakLog(DarkOakLog::Axis::X).ID: return 87; case DarkOakLog::DarkOakLog(DarkOakLog::Axis::Y).ID: return 88; case DarkOakLog::DarkOakLog(DarkOakLog::Axis::Z).ID: return 89; case DarkOakPlanks::DarkOakPlanks().ID: return 20; case DarkOakPressurePlate::DarkOakPressurePlate(true).ID: return 3377; case DarkOakPressurePlate::DarkOakPressurePlate(false).ID: return 3378; case DarkOakSapling::DarkOakSapling(0).ID: return 31; case DarkOakSapling::DarkOakSapling(1).ID: return 32; case DarkOakSlab::DarkOakSlab(DarkOakSlab::Type::Top).ID: return 7288; case DarkOakSlab::DarkOakSlab(DarkOakSlab::Type::Bottom).ID: return 7290; case DarkOakSlab::DarkOakSlab(DarkOakSlab::Type::Double).ID: return 7292; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZM, DarkOakStairs::Half::Top, DarkOakStairs::Shape::Straight).ID: return 6413; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZM, DarkOakStairs::Half::Top, DarkOakStairs::Shape::InnerLeft).ID: return 6415; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZM, DarkOakStairs::Half::Top, DarkOakStairs::Shape::InnerRight).ID: return 6417; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZM, DarkOakStairs::Half::Top, DarkOakStairs::Shape::OuterLeft).ID: return 6419; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZM, DarkOakStairs::Half::Top, DarkOakStairs::Shape::OuterRight).ID: return 6421; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZM, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::Straight).ID: return 6423; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZM, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::InnerLeft).ID: return 6425; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZM, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::InnerRight).ID: return 6427; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZM, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::OuterLeft).ID: return 6429; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZM, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::OuterRight).ID: return 6431; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZP, DarkOakStairs::Half::Top, DarkOakStairs::Shape::Straight).ID: return 6433; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZP, DarkOakStairs::Half::Top, DarkOakStairs::Shape::InnerLeft).ID: return 6435; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZP, DarkOakStairs::Half::Top, DarkOakStairs::Shape::InnerRight).ID: return 6437; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZP, DarkOakStairs::Half::Top, DarkOakStairs::Shape::OuterLeft).ID: return 6439; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZP, DarkOakStairs::Half::Top, DarkOakStairs::Shape::OuterRight).ID: return 6441; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZP, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::Straight).ID: return 6443; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZP, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::InnerLeft).ID: return 6445; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZP, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::InnerRight).ID: return 6447; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZP, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::OuterLeft).ID: return 6449; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZP, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::OuterRight).ID: return 6451; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XM, DarkOakStairs::Half::Top, DarkOakStairs::Shape::Straight).ID: return 6453; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XM, DarkOakStairs::Half::Top, DarkOakStairs::Shape::InnerLeft).ID: return 6455; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XM, DarkOakStairs::Half::Top, DarkOakStairs::Shape::InnerRight).ID: return 6457; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XM, DarkOakStairs::Half::Top, DarkOakStairs::Shape::OuterLeft).ID: return 6459; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XM, DarkOakStairs::Half::Top, DarkOakStairs::Shape::OuterRight).ID: return 6461; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XM, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::Straight).ID: return 6463; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XM, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::InnerLeft).ID: return 6465; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XM, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::InnerRight).ID: return 6467; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XM, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::OuterLeft).ID: return 6469; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XM, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::OuterRight).ID: return 6471; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XP, DarkOakStairs::Half::Top, DarkOakStairs::Shape::Straight).ID: return 6473; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XP, DarkOakStairs::Half::Top, DarkOakStairs::Shape::InnerLeft).ID: return 6475; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XP, DarkOakStairs::Half::Top, DarkOakStairs::Shape::InnerRight).ID: return 6477; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XP, DarkOakStairs::Half::Top, DarkOakStairs::Shape::OuterLeft).ID: return 6479; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XP, DarkOakStairs::Half::Top, DarkOakStairs::Shape::OuterRight).ID: return 6481; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XP, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::Straight).ID: return 6483; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XP, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::InnerLeft).ID: return 6485; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XP, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::InnerRight).ID: return 6487; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XP, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::OuterLeft).ID: return 6489; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XP, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::OuterRight).ID: return 6491; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZM, DarkOakTrapdoor::Half::Top, true, true).ID: return 3914; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZM, DarkOakTrapdoor::Half::Top, true, false).ID: return 3916; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZM, DarkOakTrapdoor::Half::Top, false, true).ID: return 3918; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZM, DarkOakTrapdoor::Half::Top, false, false).ID: return 3920; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZM, DarkOakTrapdoor::Half::Bottom, true, true).ID: return 3922; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZM, DarkOakTrapdoor::Half::Bottom, true, false).ID: return 3924; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZM, DarkOakTrapdoor::Half::Bottom, false, true).ID: return 3926; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZM, DarkOakTrapdoor::Half::Bottom, false, false).ID: return 3928; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZP, DarkOakTrapdoor::Half::Top, true, true).ID: return 3930; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZP, DarkOakTrapdoor::Half::Top, true, false).ID: return 3932; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZP, DarkOakTrapdoor::Half::Top, false, true).ID: return 3934; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZP, DarkOakTrapdoor::Half::Top, false, false).ID: return 3936; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZP, DarkOakTrapdoor::Half::Bottom, true, true).ID: return 3938; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZP, DarkOakTrapdoor::Half::Bottom, true, false).ID: return 3940; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZP, DarkOakTrapdoor::Half::Bottom, false, true).ID: return 3942; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZP, DarkOakTrapdoor::Half::Bottom, false, false).ID: return 3944; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XM, DarkOakTrapdoor::Half::Top, true, true).ID: return 3946; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XM, DarkOakTrapdoor::Half::Top, true, false).ID: return 3948; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XM, DarkOakTrapdoor::Half::Top, false, true).ID: return 3950; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XM, DarkOakTrapdoor::Half::Top, false, false).ID: return 3952; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XM, DarkOakTrapdoor::Half::Bottom, true, true).ID: return 3954; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XM, DarkOakTrapdoor::Half::Bottom, true, false).ID: return 3956; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XM, DarkOakTrapdoor::Half::Bottom, false, true).ID: return 3958; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XM, DarkOakTrapdoor::Half::Bottom, false, false).ID: return 3960; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XP, DarkOakTrapdoor::Half::Top, true, true).ID: return 3962; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XP, DarkOakTrapdoor::Half::Top, true, false).ID: return 3964; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XP, DarkOakTrapdoor::Half::Top, false, true).ID: return 3966; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XP, DarkOakTrapdoor::Half::Top, false, false).ID: return 3968; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XP, DarkOakTrapdoor::Half::Bottom, true, true).ID: return 3970; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XP, DarkOakTrapdoor::Half::Bottom, true, false).ID: return 3972; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XP, DarkOakTrapdoor::Half::Bottom, false, true).ID: return 3974; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XP, DarkOakTrapdoor::Half::Bottom, false, false).ID: return 3976; case DarkOakWood::DarkOakWood(DarkOakWood::Axis::X).ID: return 123; case DarkOakWood::DarkOakWood(DarkOakWood::Axis::Y).ID: return 124; case DarkOakWood::DarkOakWood(DarkOakWood::Axis::Z).ID: return 125; case DarkPrismarine::DarkPrismarine().ID: return 6560; case DarkPrismarineSlab::DarkPrismarineSlab(DarkPrismarineSlab::Type::Top).ID: return 6814; case DarkPrismarineSlab::DarkPrismarineSlab(DarkPrismarineSlab::Type::Bottom).ID: return 6816; case DarkPrismarineSlab::DarkPrismarineSlab(DarkPrismarineSlab::Type::Double).ID: return 6818; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZM, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::Straight).ID: return 6722; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZM, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::InnerLeft).ID: return 6724; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZM, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::InnerRight).ID: return 6726; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZM, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::OuterLeft).ID: return 6728; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZM, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::OuterRight).ID: return 6730; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZM, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::Straight).ID: return 6732; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZM, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::InnerLeft).ID: return 6734; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZM, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::InnerRight).ID: return 6736; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZM, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::OuterLeft).ID: return 6738; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZM, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::OuterRight).ID: return 6740; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZP, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::Straight).ID: return 6742; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZP, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::InnerLeft).ID: return 6744; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZP, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::InnerRight).ID: return 6746; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZP, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::OuterLeft).ID: return 6748; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZP, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::OuterRight).ID: return 6750; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZP, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::Straight).ID: return 6752; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZP, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::InnerLeft).ID: return 6754; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZP, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::InnerRight).ID: return 6756; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZP, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::OuterLeft).ID: return 6758; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZP, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::OuterRight).ID: return 6760; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XM, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::Straight).ID: return 6762; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XM, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::InnerLeft).ID: return 6764; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XM, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::InnerRight).ID: return 6766; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XM, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::OuterLeft).ID: return 6768; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XM, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::OuterRight).ID: return 6770; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XM, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::Straight).ID: return 6772; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XM, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::InnerLeft).ID: return 6774; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XM, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::InnerRight).ID: return 6776; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XM, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::OuterLeft).ID: return 6778; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XM, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::OuterRight).ID: return 6780; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XP, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::Straight).ID: return 6782; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XP, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::InnerLeft).ID: return 6784; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XP, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::InnerRight).ID: return 6786; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XP, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::OuterLeft).ID: return 6788; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XP, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::OuterRight).ID: return 6790; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XP, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::Straight).ID: return 6792; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XP, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::InnerLeft).ID: return 6794; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XP, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::InnerRight).ID: return 6796; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XP, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::OuterLeft).ID: return 6798; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XP, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::OuterRight).ID: return 6800; case DaylightDetector::DaylightDetector(true, 0).ID: return 5651; case DaylightDetector::DaylightDetector(true, 1).ID: return 5652; case DaylightDetector::DaylightDetector(true, 2).ID: return 5653; case DaylightDetector::DaylightDetector(true, 3).ID: return 5654; case DaylightDetector::DaylightDetector(true, 4).ID: return 5655; case DaylightDetector::DaylightDetector(true, 5).ID: return 5656; case DaylightDetector::DaylightDetector(true, 6).ID: return 5657; case DaylightDetector::DaylightDetector(true, 7).ID: return 5658; case DaylightDetector::DaylightDetector(true, 8).ID: return 5659; case DaylightDetector::DaylightDetector(true, 9).ID: return 5660; case DaylightDetector::DaylightDetector(true, 10).ID: return 5661; case DaylightDetector::DaylightDetector(true, 11).ID: return 5662; case DaylightDetector::DaylightDetector(true, 12).ID: return 5663; case DaylightDetector::DaylightDetector(true, 13).ID: return 5664; case DaylightDetector::DaylightDetector(true, 14).ID: return 5665; case DaylightDetector::DaylightDetector(true, 15).ID: return 5666; case DaylightDetector::DaylightDetector(false, 0).ID: return 5667; case DaylightDetector::DaylightDetector(false, 1).ID: return 5668; case DaylightDetector::DaylightDetector(false, 2).ID: return 5669; case DaylightDetector::DaylightDetector(false, 3).ID: return 5670; case DaylightDetector::DaylightDetector(false, 4).ID: return 5671; case DaylightDetector::DaylightDetector(false, 5).ID: return 5672; case DaylightDetector::DaylightDetector(false, 6).ID: return 5673; case DaylightDetector::DaylightDetector(false, 7).ID: return 5674; case DaylightDetector::DaylightDetector(false, 8).ID: return 5675; case DaylightDetector::DaylightDetector(false, 9).ID: return 5676; case DaylightDetector::DaylightDetector(false, 10).ID: return 5677; case DaylightDetector::DaylightDetector(false, 11).ID: return 5678; case DaylightDetector::DaylightDetector(false, 12).ID: return 5679; case DaylightDetector::DaylightDetector(false, 13).ID: return 5680; case DaylightDetector::DaylightDetector(false, 14).ID: return 5681; case DaylightDetector::DaylightDetector(false, 15).ID: return 5682; case DeadBrainCoralBlock::DeadBrainCoralBlock().ID: return 8450; case DeadBrainCoralFan::DeadBrainCoralFan().ID: return 8547; case DeadBrainCoralWallFan::DeadBrainCoralWallFan(eBlockFace::BLOCK_FACE_ZM).ID: return 8473; case DeadBrainCoralWallFan::DeadBrainCoralWallFan(eBlockFace::BLOCK_FACE_ZP).ID: return 8475; case DeadBrainCoralWallFan::DeadBrainCoralWallFan(eBlockFace::BLOCK_FACE_XM).ID: return 8477; case DeadBrainCoralWallFan::DeadBrainCoralWallFan(eBlockFace::BLOCK_FACE_XP).ID: return 8479; case DeadBubbleCoralBlock::DeadBubbleCoralBlock().ID: return 8451; case DeadBubbleCoralFan::DeadBubbleCoralFan().ID: return 8549; case DeadBubbleCoralWallFan::DeadBubbleCoralWallFan(eBlockFace::BLOCK_FACE_ZM).ID: return 8481; case DeadBubbleCoralWallFan::DeadBubbleCoralWallFan(eBlockFace::BLOCK_FACE_ZP).ID: return 8483; case DeadBubbleCoralWallFan::DeadBubbleCoralWallFan(eBlockFace::BLOCK_FACE_XM).ID: return 8485; case DeadBubbleCoralWallFan::DeadBubbleCoralWallFan(eBlockFace::BLOCK_FACE_XP).ID: return 8487; case DeadBush::DeadBush().ID: return 1043; case DeadFireCoralBlock::DeadFireCoralBlock().ID: return 8452; case DeadFireCoralFan::DeadFireCoralFan().ID: return 8551; case DeadFireCoralWallFan::DeadFireCoralWallFan(eBlockFace::BLOCK_FACE_ZM).ID: return 8489; case DeadFireCoralWallFan::DeadFireCoralWallFan(eBlockFace::BLOCK_FACE_ZP).ID: return 8491; case DeadFireCoralWallFan::DeadFireCoralWallFan(eBlockFace::BLOCK_FACE_XM).ID: return 8493; case DeadFireCoralWallFan::DeadFireCoralWallFan(eBlockFace::BLOCK_FACE_XP).ID: return 8495; case DeadHornCoralBlock::DeadHornCoralBlock().ID: return 8453; case DeadHornCoralFan::DeadHornCoralFan().ID: return 8553; case DeadHornCoralWallFan::DeadHornCoralWallFan(eBlockFace::BLOCK_FACE_ZM).ID: return 8497; case DeadHornCoralWallFan::DeadHornCoralWallFan(eBlockFace::BLOCK_FACE_ZP).ID: return 8499; case DeadHornCoralWallFan::DeadHornCoralWallFan(eBlockFace::BLOCK_FACE_XM).ID: return 8501; case DeadHornCoralWallFan::DeadHornCoralWallFan(eBlockFace::BLOCK_FACE_XP).ID: return 8503; case DeadTubeCoralBlock::DeadTubeCoralBlock().ID: return 8449; case DeadTubeCoralFan::DeadTubeCoralFan().ID: return 8545; case DeadTubeCoralWallFan::DeadTubeCoralWallFan(eBlockFace::BLOCK_FACE_ZM).ID: return 8465; case DeadTubeCoralWallFan::DeadTubeCoralWallFan(eBlockFace::BLOCK_FACE_ZP).ID: return 8467; case DeadTubeCoralWallFan::DeadTubeCoralWallFan(eBlockFace::BLOCK_FACE_XM).ID: return 8469; case DeadTubeCoralWallFan::DeadTubeCoralWallFan(eBlockFace::BLOCK_FACE_XP).ID: return 8471; case DetectorRail::DetectorRail(true, DetectorRail::Shape::NorthSouth).ID: return 1016; case DetectorRail::DetectorRail(true, DetectorRail::Shape::EastWest).ID: return 1017; case DetectorRail::DetectorRail(true, DetectorRail::Shape::AscendingEast).ID: return 1018; case DetectorRail::DetectorRail(true, DetectorRail::Shape::AscendingWest).ID: return 1019; case DetectorRail::DetectorRail(true, DetectorRail::Shape::AscendingNorth).ID: return 1020; case DetectorRail::DetectorRail(true, DetectorRail::Shape::AscendingSouth).ID: return 1021; case DetectorRail::DetectorRail(false, DetectorRail::Shape::NorthSouth).ID: return 1022; case DetectorRail::DetectorRail(false, DetectorRail::Shape::EastWest).ID: return 1023; case DetectorRail::DetectorRail(false, DetectorRail::Shape::AscendingEast).ID: return 1024; case DetectorRail::DetectorRail(false, DetectorRail::Shape::AscendingWest).ID: return 1025; case DetectorRail::DetectorRail(false, DetectorRail::Shape::AscendingNorth).ID: return 1026; case DetectorRail::DetectorRail(false, DetectorRail::Shape::AscendingSouth).ID: return 1027; case DiamondBlock::DiamondBlock().ID: return 3049; case DiamondOre::DiamondOre().ID: return 3048; case Diorite::Diorite().ID: return 4; case Dirt::Dirt().ID: return 10; case Dispenser::Dispenser(eBlockFace::BLOCK_FACE_ZM, true).ID: return 233; case Dispenser::Dispenser(eBlockFace::BLOCK_FACE_ZM, false).ID: return 234; case Dispenser::Dispenser(eBlockFace::BLOCK_FACE_XP, true).ID: return 235; case Dispenser::Dispenser(eBlockFace::BLOCK_FACE_XP, false).ID: return 236; case Dispenser::Dispenser(eBlockFace::BLOCK_FACE_ZP, true).ID: return 237; case Dispenser::Dispenser(eBlockFace::BLOCK_FACE_ZP, false).ID: return 238; case Dispenser::Dispenser(eBlockFace::BLOCK_FACE_XM, true).ID: return 239; case Dispenser::Dispenser(eBlockFace::BLOCK_FACE_XM, false).ID: return 240; case Dispenser::Dispenser(eBlockFace::BLOCK_FACE_YP, true).ID: return 241; case Dispenser::Dispenser(eBlockFace::BLOCK_FACE_YP, false).ID: return 242; case Dispenser::Dispenser(eBlockFace::BLOCK_FACE_YM, true).ID: return 243; case Dispenser::Dispenser(eBlockFace::BLOCK_FACE_YM, false).ID: return 244; case DragonEgg::DragonEgg().ID: return 4635; case DragonHead::DragonHead(0).ID: return 5551; case DragonHead::DragonHead(1).ID: return 5552; case DragonHead::DragonHead(2).ID: return 5553; case DragonHead::DragonHead(3).ID: return 5554; case DragonHead::DragonHead(4).ID: return 5555; case DragonHead::DragonHead(5).ID: return 5556; case DragonHead::DragonHead(6).ID: return 5557; case DragonHead::DragonHead(7).ID: return 5558; case DragonHead::DragonHead(8).ID: return 5559; case DragonHead::DragonHead(9).ID: return 5560; case DragonHead::DragonHead(10).ID: return 5561; case DragonHead::DragonHead(11).ID: return 5562; case DragonHead::DragonHead(12).ID: return 5563; case DragonHead::DragonHead(13).ID: return 5564; case DragonHead::DragonHead(14).ID: return 5565; case DragonHead::DragonHead(15).ID: return 5566; case DragonWallHead::DragonWallHead(eBlockFace::BLOCK_FACE_ZM).ID: return 5547; case DragonWallHead::DragonWallHead(eBlockFace::BLOCK_FACE_ZP).ID: return 5548; case DragonWallHead::DragonWallHead(eBlockFace::BLOCK_FACE_XM).ID: return 5549; case DragonWallHead::DragonWallHead(eBlockFace::BLOCK_FACE_XP).ID: return 5550; case DriedKelpBlock::DriedKelpBlock().ID: return 8436; case Dropper::Dropper(eBlockFace::BLOCK_FACE_ZM, true).ID: return 5792; case Dropper::Dropper(eBlockFace::BLOCK_FACE_ZM, false).ID: return 5793; case Dropper::Dropper(eBlockFace::BLOCK_FACE_XP, true).ID: return 5794; case Dropper::Dropper(eBlockFace::BLOCK_FACE_XP, false).ID: return 5795; case Dropper::Dropper(eBlockFace::BLOCK_FACE_ZP, true).ID: return 5796; case Dropper::Dropper(eBlockFace::BLOCK_FACE_ZP, false).ID: return 5797; case Dropper::Dropper(eBlockFace::BLOCK_FACE_XM, true).ID: return 5798; case Dropper::Dropper(eBlockFace::BLOCK_FACE_XM, false).ID: return 5799; case Dropper::Dropper(eBlockFace::BLOCK_FACE_YP, true).ID: return 5800; case Dropper::Dropper(eBlockFace::BLOCK_FACE_YP, false).ID: return 5801; case Dropper::Dropper(eBlockFace::BLOCK_FACE_YM, true).ID: return 5802; case Dropper::Dropper(eBlockFace::BLOCK_FACE_YM, false).ID: return 5803; case EmeraldBlock::EmeraldBlock().ID: return 4883; case EmeraldOre::EmeraldOre().ID: return 4730; case EnchantingTable::EnchantingTable().ID: return 4612; case EndGateway::EndGateway().ID: return 8163; case EndPortal::EndPortal().ID: return 4625; case EndPortalFrame::EndPortalFrame(true, eBlockFace::BLOCK_FACE_ZM).ID: return 4626; case EndPortalFrame::EndPortalFrame(true, eBlockFace::BLOCK_FACE_ZP).ID: return 4627; case EndPortalFrame::EndPortalFrame(true, eBlockFace::BLOCK_FACE_XM).ID: return 4628; case EndPortalFrame::EndPortalFrame(true, eBlockFace::BLOCK_FACE_XP).ID: return 4629; case EndPortalFrame::EndPortalFrame(false, eBlockFace::BLOCK_FACE_ZM).ID: return 4630; case EndPortalFrame::EndPortalFrame(false, eBlockFace::BLOCK_FACE_ZP).ID: return 4631; case EndPortalFrame::EndPortalFrame(false, eBlockFace::BLOCK_FACE_XM).ID: return 4632; case EndPortalFrame::EndPortalFrame(false, eBlockFace::BLOCK_FACE_XP).ID: return 4633; case EndRod::EndRod(eBlockFace::BLOCK_FACE_ZM).ID: return 7997; case EndRod::EndRod(eBlockFace::BLOCK_FACE_XP).ID: return 7998; case EndRod::EndRod(eBlockFace::BLOCK_FACE_ZP).ID: return 7999; case EndRod::EndRod(eBlockFace::BLOCK_FACE_XM).ID: return 8000; case EndRod::EndRod(eBlockFace::BLOCK_FACE_YP).ID: return 8001; case EndRod::EndRod(eBlockFace::BLOCK_FACE_YM).ID: return 8002; case EndStone::EndStone().ID: return 4634; case EndStoneBricks::EndStoneBricks().ID: return 8157; case EnderChest::EnderChest(eBlockFace::BLOCK_FACE_ZM).ID: return 4732; case EnderChest::EnderChest(eBlockFace::BLOCK_FACE_ZP).ID: return 4734; case EnderChest::EnderChest(eBlockFace::BLOCK_FACE_XM).ID: return 4736; case EnderChest::EnderChest(eBlockFace::BLOCK_FACE_XP).ID: return 4738; case Farmland::Farmland(0).ID: return 3059; case Farmland::Farmland(1).ID: return 3060; case Farmland::Farmland(2).ID: return 3061; case Farmland::Farmland(3).ID: return 3062; case Farmland::Farmland(4).ID: return 3063; case Farmland::Farmland(5).ID: return 3064; case Farmland::Farmland(6).ID: return 3065; case Farmland::Farmland(7).ID: return 3066; case Fern::Fern().ID: return 1042; case Fire::Fire(0, true, true, true, true, true).ID: return 1135; case Fire::Fire(0, true, true, true, true, false).ID: return 1136; case Fire::Fire(0, true, true, true, false, true).ID: return 1137; case Fire::Fire(0, true, true, true, false, false).ID: return 1138; case Fire::Fire(0, true, true, false, true, true).ID: return 1139; case Fire::Fire(0, true, true, false, true, false).ID: return 1140; case Fire::Fire(0, true, true, false, false, true).ID: return 1141; case Fire::Fire(0, true, true, false, false, false).ID: return 1142; case Fire::Fire(0, true, false, true, true, true).ID: return 1143; case Fire::Fire(0, true, false, true, true, false).ID: return 1144; case Fire::Fire(0, true, false, true, false, true).ID: return 1145; case Fire::Fire(0, true, false, true, false, false).ID: return 1146; case Fire::Fire(0, true, false, false, true, true).ID: return 1147; case Fire::Fire(0, true, false, false, true, false).ID: return 1148; case Fire::Fire(0, true, false, false, false, true).ID: return 1149; case Fire::Fire(0, true, false, false, false, false).ID: return 1150; case Fire::Fire(0, false, true, true, true, true).ID: return 1151; case Fire::Fire(0, false, true, true, true, false).ID: return 1152; case Fire::Fire(0, false, true, true, false, true).ID: return 1153; case Fire::Fire(0, false, true, true, false, false).ID: return 1154; case Fire::Fire(0, false, true, false, true, true).ID: return 1155; case Fire::Fire(0, false, true, false, true, false).ID: return 1156; case Fire::Fire(0, false, true, false, false, true).ID: return 1157; case Fire::Fire(0, false, true, false, false, false).ID: return 1158; case Fire::Fire(0, false, false, true, true, true).ID: return 1159; case Fire::Fire(0, false, false, true, true, false).ID: return 1160; case Fire::Fire(0, false, false, true, false, true).ID: return 1161; case Fire::Fire(0, false, false, true, false, false).ID: return 1162; case Fire::Fire(0, false, false, false, true, true).ID: return 1163; case Fire::Fire(0, false, false, false, true, false).ID: return 1164; case Fire::Fire(0, false, false, false, false, true).ID: return 1165; case Fire::Fire(0, false, false, false, false, false).ID: return 1166; case Fire::Fire(1, true, true, true, true, true).ID: return 1167; case Fire::Fire(1, true, true, true, true, false).ID: return 1168; case Fire::Fire(1, true, true, true, false, true).ID: return 1169; case Fire::Fire(1, true, true, true, false, false).ID: return 1170; case Fire::Fire(1, true, true, false, true, true).ID: return 1171; case Fire::Fire(1, true, true, false, true, false).ID: return 1172; case Fire::Fire(1, true, true, false, false, true).ID: return 1173; case Fire::Fire(1, true, true, false, false, false).ID: return 1174; case Fire::Fire(1, true, false, true, true, true).ID: return 1175; case Fire::Fire(1, true, false, true, true, false).ID: return 1176; case Fire::Fire(1, true, false, true, false, true).ID: return 1177; case Fire::Fire(1, true, false, true, false, false).ID: return 1178; case Fire::Fire(1, true, false, false, true, true).ID: return 1179; case Fire::Fire(1, true, false, false, true, false).ID: return 1180; case Fire::Fire(1, true, false, false, false, true).ID: return 1181; case Fire::Fire(1, true, false, false, false, false).ID: return 1182; case Fire::Fire(1, false, true, true, true, true).ID: return 1183; case Fire::Fire(1, false, true, true, true, false).ID: return 1184; case Fire::Fire(1, false, true, true, false, true).ID: return 1185; case Fire::Fire(1, false, true, true, false, false).ID: return 1186; case Fire::Fire(1, false, true, false, true, true).ID: return 1187; case Fire::Fire(1, false, true, false, true, false).ID: return 1188; case Fire::Fire(1, false, true, false, false, true).ID: return 1189; case Fire::Fire(1, false, true, false, false, false).ID: return 1190; case Fire::Fire(1, false, false, true, true, true).ID: return 1191; case Fire::Fire(1, false, false, true, true, false).ID: return 1192; case Fire::Fire(1, false, false, true, false, true).ID: return 1193; case Fire::Fire(1, false, false, true, false, false).ID: return 1194; case Fire::Fire(1, false, false, false, true, true).ID: return 1195; case Fire::Fire(1, false, false, false, true, false).ID: return 1196; case Fire::Fire(1, false, false, false, false, true).ID: return 1197; case Fire::Fire(1, false, false, false, false, false).ID: return 1198; case Fire::Fire(2, true, true, true, true, true).ID: return 1199; case Fire::Fire(2, true, true, true, true, false).ID: return 1200; case Fire::Fire(2, true, true, true, false, true).ID: return 1201; case Fire::Fire(2, true, true, true, false, false).ID: return 1202; case Fire::Fire(2, true, true, false, true, true).ID: return 1203; case Fire::Fire(2, true, true, false, true, false).ID: return 1204; case Fire::Fire(2, true, true, false, false, true).ID: return 1205; case Fire::Fire(2, true, true, false, false, false).ID: return 1206; case Fire::Fire(2, true, false, true, true, true).ID: return 1207; case Fire::Fire(2, true, false, true, true, false).ID: return 1208; case Fire::Fire(2, true, false, true, false, true).ID: return 1209; case Fire::Fire(2, true, false, true, false, false).ID: return 1210; case Fire::Fire(2, true, false, false, true, true).ID: return 1211; case Fire::Fire(2, true, false, false, true, false).ID: return 1212; case Fire::Fire(2, true, false, false, false, true).ID: return 1213; case Fire::Fire(2, true, false, false, false, false).ID: return 1214; case Fire::Fire(2, false, true, true, true, true).ID: return 1215; case Fire::Fire(2, false, true, true, true, false).ID: return 1216; case Fire::Fire(2, false, true, true, false, true).ID: return 1217; case Fire::Fire(2, false, true, true, false, false).ID: return 1218; case Fire::Fire(2, false, true, false, true, true).ID: return 1219; case Fire::Fire(2, false, true, false, true, false).ID: return 1220; case Fire::Fire(2, false, true, false, false, true).ID: return 1221; case Fire::Fire(2, false, true, false, false, false).ID: return 1222; case Fire::Fire(2, false, false, true, true, true).ID: return 1223; case Fire::Fire(2, false, false, true, true, false).ID: return 1224; case Fire::Fire(2, false, false, true, false, true).ID: return 1225; case Fire::Fire(2, false, false, true, false, false).ID: return 1226; case Fire::Fire(2, false, false, false, true, true).ID: return 1227; case Fire::Fire(2, false, false, false, true, false).ID: return 1228; case Fire::Fire(2, false, false, false, false, true).ID: return 1229; case Fire::Fire(2, false, false, false, false, false).ID: return 1230; case Fire::Fire(3, true, true, true, true, true).ID: return 1231; case Fire::Fire(3, true, true, true, true, false).ID: return 1232; case Fire::Fire(3, true, true, true, false, true).ID: return 1233; case Fire::Fire(3, true, true, true, false, false).ID: return 1234; case Fire::Fire(3, true, true, false, true, true).ID: return 1235; case Fire::Fire(3, true, true, false, true, false).ID: return 1236; case Fire::Fire(3, true, true, false, false, true).ID: return 1237; case Fire::Fire(3, true, true, false, false, false).ID: return 1238; case Fire::Fire(3, true, false, true, true, true).ID: return 1239; case Fire::Fire(3, true, false, true, true, false).ID: return 1240; case Fire::Fire(3, true, false, true, false, true).ID: return 1241; case Fire::Fire(3, true, false, true, false, false).ID: return 1242; case Fire::Fire(3, true, false, false, true, true).ID: return 1243; case Fire::Fire(3, true, false, false, true, false).ID: return 1244; case Fire::Fire(3, true, false, false, false, true).ID: return 1245; case Fire::Fire(3, true, false, false, false, false).ID: return 1246; case Fire::Fire(3, false, true, true, true, true).ID: return 1247; case Fire::Fire(3, false, true, true, true, false).ID: return 1248; case Fire::Fire(3, false, true, true, false, true).ID: return 1249; case Fire::Fire(3, false, true, true, false, false).ID: return 1250; case Fire::Fire(3, false, true, false, true, true).ID: return 1251; case Fire::Fire(3, false, true, false, true, false).ID: return 1252; case Fire::Fire(3, false, true, false, false, true).ID: return 1253; case Fire::Fire(3, false, true, false, false, false).ID: return 1254; case Fire::Fire(3, false, false, true, true, true).ID: return 1255; case Fire::Fire(3, false, false, true, true, false).ID: return 1256; case Fire::Fire(3, false, false, true, false, true).ID: return 1257; case Fire::Fire(3, false, false, true, false, false).ID: return 1258; case Fire::Fire(3, false, false, false, true, true).ID: return 1259; case Fire::Fire(3, false, false, false, true, false).ID: return 1260; case Fire::Fire(3, false, false, false, false, true).ID: return 1261; case Fire::Fire(3, false, false, false, false, false).ID: return 1262; case Fire::Fire(4, true, true, true, true, true).ID: return 1263; case Fire::Fire(4, true, true, true, true, false).ID: return 1264; case Fire::Fire(4, true, true, true, false, true).ID: return 1265; case Fire::Fire(4, true, true, true, false, false).ID: return 1266; case Fire::Fire(4, true, true, false, true, true).ID: return 1267; case Fire::Fire(4, true, true, false, true, false).ID: return 1268; case Fire::Fire(4, true, true, false, false, true).ID: return 1269; case Fire::Fire(4, true, true, false, false, false).ID: return 1270; case Fire::Fire(4, true, false, true, true, true).ID: return 1271; case Fire::Fire(4, true, false, true, true, false).ID: return 1272; case Fire::Fire(4, true, false, true, false, true).ID: return 1273; case Fire::Fire(4, true, false, true, false, false).ID: return 1274; case Fire::Fire(4, true, false, false, true, true).ID: return 1275; case Fire::Fire(4, true, false, false, true, false).ID: return 1276; case Fire::Fire(4, true, false, false, false, true).ID: return 1277; case Fire::Fire(4, true, false, false, false, false).ID: return 1278; case Fire::Fire(4, false, true, true, true, true).ID: return 1279; case Fire::Fire(4, false, true, true, true, false).ID: return 1280; case Fire::Fire(4, false, true, true, false, true).ID: return 1281; case Fire::Fire(4, false, true, true, false, false).ID: return 1282; case Fire::Fire(4, false, true, false, true, true).ID: return 1283; case Fire::Fire(4, false, true, false, true, false).ID: return 1284; case Fire::Fire(4, false, true, false, false, true).ID: return 1285; case Fire::Fire(4, false, true, false, false, false).ID: return 1286; case Fire::Fire(4, false, false, true, true, true).ID: return 1287; case Fire::Fire(4, false, false, true, true, false).ID: return 1288; case Fire::Fire(4, false, false, true, false, true).ID: return 1289; case Fire::Fire(4, false, false, true, false, false).ID: return 1290; case Fire::Fire(4, false, false, false, true, true).ID: return 1291; case Fire::Fire(4, false, false, false, true, false).ID: return 1292; case Fire::Fire(4, false, false, false, false, true).ID: return 1293; case Fire::Fire(4, false, false, false, false, false).ID: return 1294; case Fire::Fire(5, true, true, true, true, true).ID: return 1295; case Fire::Fire(5, true, true, true, true, false).ID: return 1296; case Fire::Fire(5, true, true, true, false, true).ID: return 1297; case Fire::Fire(5, true, true, true, false, false).ID: return 1298; case Fire::Fire(5, true, true, false, true, true).ID: return 1299; case Fire::Fire(5, true, true, false, true, false).ID: return 1300; case Fire::Fire(5, true, true, false, false, true).ID: return 1301; case Fire::Fire(5, true, true, false, false, false).ID: return 1302; case Fire::Fire(5, true, false, true, true, true).ID: return 1303; case Fire::Fire(5, true, false, true, true, false).ID: return 1304; case Fire::Fire(5, true, false, true, false, true).ID: return 1305; case Fire::Fire(5, true, false, true, false, false).ID: return 1306; case Fire::Fire(5, true, false, false, true, true).ID: return 1307; case Fire::Fire(5, true, false, false, true, false).ID: return 1308; case Fire::Fire(5, true, false, false, false, true).ID: return 1309; case Fire::Fire(5, true, false, false, false, false).ID: return 1310; case Fire::Fire(5, false, true, true, true, true).ID: return 1311; case Fire::Fire(5, false, true, true, true, false).ID: return 1312; case Fire::Fire(5, false, true, true, false, true).ID: return 1313; case Fire::Fire(5, false, true, true, false, false).ID: return 1314; case Fire::Fire(5, false, true, false, true, true).ID: return 1315; case Fire::Fire(5, false, true, false, true, false).ID: return 1316; case Fire::Fire(5, false, true, false, false, true).ID: return 1317; case Fire::Fire(5, false, true, false, false, false).ID: return 1318; case Fire::Fire(5, false, false, true, true, true).ID: return 1319; case Fire::Fire(5, false, false, true, true, false).ID: return 1320; case Fire::Fire(5, false, false, true, false, true).ID: return 1321; case Fire::Fire(5, false, false, true, false, false).ID: return 1322; case Fire::Fire(5, false, false, false, true, true).ID: return 1323; case Fire::Fire(5, false, false, false, true, false).ID: return 1324; case Fire::Fire(5, false, false, false, false, true).ID: return 1325; case Fire::Fire(5, false, false, false, false, false).ID: return 1326; case Fire::Fire(6, true, true, true, true, true).ID: return 1327; case Fire::Fire(6, true, true, true, true, false).ID: return 1328; case Fire::Fire(6, true, true, true, false, true).ID: return 1329; case Fire::Fire(6, true, true, true, false, false).ID: return 1330; case Fire::Fire(6, true, true, false, true, true).ID: return 1331; case Fire::Fire(6, true, true, false, true, false).ID: return 1332; case Fire::Fire(6, true, true, false, false, true).ID: return 1333; case Fire::Fire(6, true, true, false, false, false).ID: return 1334; case Fire::Fire(6, true, false, true, true, true).ID: return 1335; case Fire::Fire(6, true, false, true, true, false).ID: return 1336; case Fire::Fire(6, true, false, true, false, true).ID: return 1337; case Fire::Fire(6, true, false, true, false, false).ID: return 1338; case Fire::Fire(6, true, false, false, true, true).ID: return 1339; case Fire::Fire(6, true, false, false, true, false).ID: return 1340; case Fire::Fire(6, true, false, false, false, true).ID: return 1341; case Fire::Fire(6, true, false, false, false, false).ID: return 1342; case Fire::Fire(6, false, true, true, true, true).ID: return 1343; case Fire::Fire(6, false, true, true, true, false).ID: return 1344; case Fire::Fire(6, false, true, true, false, true).ID: return 1345; case Fire::Fire(6, false, true, true, false, false).ID: return 1346; case Fire::Fire(6, false, true, false, true, true).ID: return 1347; case Fire::Fire(6, false, true, false, true, false).ID: return 1348; case Fire::Fire(6, false, true, false, false, true).ID: return 1349; case Fire::Fire(6, false, true, false, false, false).ID: return 1350; case Fire::Fire(6, false, false, true, true, true).ID: return 1351; case Fire::Fire(6, false, false, true, true, false).ID: return 1352; case Fire::Fire(6, false, false, true, false, true).ID: return 1353; case Fire::Fire(6, false, false, true, false, false).ID: return 1354; case Fire::Fire(6, false, false, false, true, true).ID: return 1355; case Fire::Fire(6, false, false, false, true, false).ID: return 1356; case Fire::Fire(6, false, false, false, false, true).ID: return 1357; case Fire::Fire(6, false, false, false, false, false).ID: return 1358; case Fire::Fire(7, true, true, true, true, true).ID: return 1359; case Fire::Fire(7, true, true, true, true, false).ID: return 1360; case Fire::Fire(7, true, true, true, false, true).ID: return 1361; case Fire::Fire(7, true, true, true, false, false).ID: return 1362; case Fire::Fire(7, true, true, false, true, true).ID: return 1363; case Fire::Fire(7, true, true, false, true, false).ID: return 1364; case Fire::Fire(7, true, true, false, false, true).ID: return 1365; case Fire::Fire(7, true, true, false, false, false).ID: return 1366; case Fire::Fire(7, true, false, true, true, true).ID: return 1367; case Fire::Fire(7, true, false, true, true, false).ID: return 1368; case Fire::Fire(7, true, false, true, false, true).ID: return 1369; case Fire::Fire(7, true, false, true, false, false).ID: return 1370; case Fire::Fire(7, true, false, false, true, true).ID: return 1371; case Fire::Fire(7, true, false, false, true, false).ID: return 1372; case Fire::Fire(7, true, false, false, false, true).ID: return 1373; case Fire::Fire(7, true, false, false, false, false).ID: return 1374; case Fire::Fire(7, false, true, true, true, true).ID: return 1375; case Fire::Fire(7, false, true, true, true, false).ID: return 1376; case Fire::Fire(7, false, true, true, false, true).ID: return 1377; case Fire::Fire(7, false, true, true, false, false).ID: return 1378; case Fire::Fire(7, false, true, false, true, true).ID: return 1379; case Fire::Fire(7, false, true, false, true, false).ID: return 1380; case Fire::Fire(7, false, true, false, false, true).ID: return 1381; case Fire::Fire(7, false, true, false, false, false).ID: return 1382; case Fire::Fire(7, false, false, true, true, true).ID: return 1383; case Fire::Fire(7, false, false, true, true, false).ID: return 1384; case Fire::Fire(7, false, false, true, false, true).ID: return 1385; case Fire::Fire(7, false, false, true, false, false).ID: return 1386; case Fire::Fire(7, false, false, false, true, true).ID: return 1387; case Fire::Fire(7, false, false, false, true, false).ID: return 1388; case Fire::Fire(7, false, false, false, false, true).ID: return 1389; case Fire::Fire(7, false, false, false, false, false).ID: return 1390; case Fire::Fire(8, true, true, true, true, true).ID: return 1391; case Fire::Fire(8, true, true, true, true, false).ID: return 1392; case Fire::Fire(8, true, true, true, false, true).ID: return 1393; case Fire::Fire(8, true, true, true, false, false).ID: return 1394; case Fire::Fire(8, true, true, false, true, true).ID: return 1395; case Fire::Fire(8, true, true, false, true, false).ID: return 1396; case Fire::Fire(8, true, true, false, false, true).ID: return 1397; case Fire::Fire(8, true, true, false, false, false).ID: return 1398; case Fire::Fire(8, true, false, true, true, true).ID: return 1399; case Fire::Fire(8, true, false, true, true, false).ID: return 1400; case Fire::Fire(8, true, false, true, false, true).ID: return 1401; case Fire::Fire(8, true, false, true, false, false).ID: return 1402; case Fire::Fire(8, true, false, false, true, true).ID: return 1403; case Fire::Fire(8, true, false, false, true, false).ID: return 1404; case Fire::Fire(8, true, false, false, false, true).ID: return 1405; case Fire::Fire(8, true, false, false, false, false).ID: return 1406; case Fire::Fire(8, false, true, true, true, true).ID: return 1407; case Fire::Fire(8, false, true, true, true, false).ID: return 1408; case Fire::Fire(8, false, true, true, false, true).ID: return 1409; case Fire::Fire(8, false, true, true, false, false).ID: return 1410; case Fire::Fire(8, false, true, false, true, true).ID: return 1411; case Fire::Fire(8, false, true, false, true, false).ID: return 1412; case Fire::Fire(8, false, true, false, false, true).ID: return 1413; case Fire::Fire(8, false, true, false, false, false).ID: return 1414; case Fire::Fire(8, false, false, true, true, true).ID: return 1415; case Fire::Fire(8, false, false, true, true, false).ID: return 1416; case Fire::Fire(8, false, false, true, false, true).ID: return 1417; case Fire::Fire(8, false, false, true, false, false).ID: return 1418; case Fire::Fire(8, false, false, false, true, true).ID: return 1419; case Fire::Fire(8, false, false, false, true, false).ID: return 1420; case Fire::Fire(8, false, false, false, false, true).ID: return 1421; case Fire::Fire(8, false, false, false, false, false).ID: return 1422; case Fire::Fire(9, true, true, true, true, true).ID: return 1423; case Fire::Fire(9, true, true, true, true, false).ID: return 1424; case Fire::Fire(9, true, true, true, false, true).ID: return 1425; case Fire::Fire(9, true, true, true, false, false).ID: return 1426; case Fire::Fire(9, true, true, false, true, true).ID: return 1427; case Fire::Fire(9, true, true, false, true, false).ID: return 1428; case Fire::Fire(9, true, true, false, false, true).ID: return 1429; case Fire::Fire(9, true, true, false, false, false).ID: return 1430; case Fire::Fire(9, true, false, true, true, true).ID: return 1431; case Fire::Fire(9, true, false, true, true, false).ID: return 1432; case Fire::Fire(9, true, false, true, false, true).ID: return 1433; case Fire::Fire(9, true, false, true, false, false).ID: return 1434; case Fire::Fire(9, true, false, false, true, true).ID: return 1435; case Fire::Fire(9, true, false, false, true, false).ID: return 1436; case Fire::Fire(9, true, false, false, false, true).ID: return 1437; case Fire::Fire(9, true, false, false, false, false).ID: return 1438; case Fire::Fire(9, false, true, true, true, true).ID: return 1439; case Fire::Fire(9, false, true, true, true, false).ID: return 1440; case Fire::Fire(9, false, true, true, false, true).ID: return 1441; case Fire::Fire(9, false, true, true, false, false).ID: return 1442; case Fire::Fire(9, false, true, false, true, true).ID: return 1443; case Fire::Fire(9, false, true, false, true, false).ID: return 1444; case Fire::Fire(9, false, true, false, false, true).ID: return 1445; case Fire::Fire(9, false, true, false, false, false).ID: return 1446; case Fire::Fire(9, false, false, true, true, true).ID: return 1447; case Fire::Fire(9, false, false, true, true, false).ID: return 1448; case Fire::Fire(9, false, false, true, false, true).ID: return 1449; case Fire::Fire(9, false, false, true, false, false).ID: return 1450; case Fire::Fire(9, false, false, false, true, true).ID: return 1451; case Fire::Fire(9, false, false, false, true, false).ID: return 1452; case Fire::Fire(9, false, false, false, false, true).ID: return 1453; case Fire::Fire(9, false, false, false, false, false).ID: return 1454; case Fire::Fire(10, true, true, true, true, true).ID: return 1455; case Fire::Fire(10, true, true, true, true, false).ID: return 1456; case Fire::Fire(10, true, true, true, false, true).ID: return 1457; case Fire::Fire(10, true, true, true, false, false).ID: return 1458; case Fire::Fire(10, true, true, false, true, true).ID: return 1459; case Fire::Fire(10, true, true, false, true, false).ID: return 1460; case Fire::Fire(10, true, true, false, false, true).ID: return 1461; case Fire::Fire(10, true, true, false, false, false).ID: return 1462; case Fire::Fire(10, true, false, true, true, true).ID: return 1463; case Fire::Fire(10, true, false, true, true, false).ID: return 1464; case Fire::Fire(10, true, false, true, false, true).ID: return 1465; case Fire::Fire(10, true, false, true, false, false).ID: return 1466; case Fire::Fire(10, true, false, false, true, true).ID: return 1467; case Fire::Fire(10, true, false, false, true, false).ID: return 1468; case Fire::Fire(10, true, false, false, false, true).ID: return 1469; case Fire::Fire(10, true, false, false, false, false).ID: return 1470; case Fire::Fire(10, false, true, true, true, true).ID: return 1471; case Fire::Fire(10, false, true, true, true, false).ID: return 1472; case Fire::Fire(10, false, true, true, false, true).ID: return 1473; case Fire::Fire(10, false, true, true, false, false).ID: return 1474; case Fire::Fire(10, false, true, false, true, true).ID: return 1475; case Fire::Fire(10, false, true, false, true, false).ID: return 1476; case Fire::Fire(10, false, true, false, false, true).ID: return 1477; case Fire::Fire(10, false, true, false, false, false).ID: return 1478; case Fire::Fire(10, false, false, true, true, true).ID: return 1479; case Fire::Fire(10, false, false, true, true, false).ID: return 1480; case Fire::Fire(10, false, false, true, false, true).ID: return 1481; case Fire::Fire(10, false, false, true, false, false).ID: return 1482; case Fire::Fire(10, false, false, false, true, true).ID: return 1483; case Fire::Fire(10, false, false, false, true, false).ID: return 1484; case Fire::Fire(10, false, false, false, false, true).ID: return 1485; case Fire::Fire(10, false, false, false, false, false).ID: return 1486; case Fire::Fire(11, true, true, true, true, true).ID: return 1487; case Fire::Fire(11, true, true, true, true, false).ID: return 1488; case Fire::Fire(11, true, true, true, false, true).ID: return 1489; case Fire::Fire(11, true, true, true, false, false).ID: return 1490; case Fire::Fire(11, true, true, false, true, true).ID: return 1491; case Fire::Fire(11, true, true, false, true, false).ID: return 1492; case Fire::Fire(11, true, true, false, false, true).ID: return 1493; case Fire::Fire(11, true, true, false, false, false).ID: return 1494; case Fire::Fire(11, true, false, true, true, true).ID: return 1495; case Fire::Fire(11, true, false, true, true, false).ID: return 1496; case Fire::Fire(11, true, false, true, false, true).ID: return 1497; case Fire::Fire(11, true, false, true, false, false).ID: return 1498; case Fire::Fire(11, true, false, false, true, true).ID: return 1499; case Fire::Fire(11, true, false, false, true, false).ID: return 1500; case Fire::Fire(11, true, false, false, false, true).ID: return 1501; case Fire::Fire(11, true, false, false, false, false).ID: return 1502; case Fire::Fire(11, false, true, true, true, true).ID: return 1503; case Fire::Fire(11, false, true, true, true, false).ID: return 1504; case Fire::Fire(11, false, true, true, false, true).ID: return 1505; case Fire::Fire(11, false, true, true, false, false).ID: return 1506; case Fire::Fire(11, false, true, false, true, true).ID: return 1507; case Fire::Fire(11, false, true, false, true, false).ID: return 1508; case Fire::Fire(11, false, true, false, false, true).ID: return 1509; case Fire::Fire(11, false, true, false, false, false).ID: return 1510; case Fire::Fire(11, false, false, true, true, true).ID: return 1511; case Fire::Fire(11, false, false, true, true, false).ID: return 1512; case Fire::Fire(11, false, false, true, false, true).ID: return 1513; case Fire::Fire(11, false, false, true, false, false).ID: return 1514; case Fire::Fire(11, false, false, false, true, true).ID: return 1515; case Fire::Fire(11, false, false, false, true, false).ID: return 1516; case Fire::Fire(11, false, false, false, false, true).ID: return 1517; case Fire::Fire(11, false, false, false, false, false).ID: return 1518; case Fire::Fire(12, true, true, true, true, true).ID: return 1519; case Fire::Fire(12, true, true, true, true, false).ID: return 1520; case Fire::Fire(12, true, true, true, false, true).ID: return 1521; case Fire::Fire(12, true, true, true, false, false).ID: return 1522; case Fire::Fire(12, true, true, false, true, true).ID: return 1523; case Fire::Fire(12, true, true, false, true, false).ID: return 1524; case Fire::Fire(12, true, true, false, false, true).ID: return 1525; case Fire::Fire(12, true, true, false, false, false).ID: return 1526; case Fire::Fire(12, true, false, true, true, true).ID: return 1527; case Fire::Fire(12, true, false, true, true, false).ID: return 1528; case Fire::Fire(12, true, false, true, false, true).ID: return 1529; case Fire::Fire(12, true, false, true, false, false).ID: return 1530; case Fire::Fire(12, true, false, false, true, true).ID: return 1531; case Fire::Fire(12, true, false, false, true, false).ID: return 1532; case Fire::Fire(12, true, false, false, false, true).ID: return 1533; case Fire::Fire(12, true, false, false, false, false).ID: return 1534; case Fire::Fire(12, false, true, true, true, true).ID: return 1535; case Fire::Fire(12, false, true, true, true, false).ID: return 1536; case Fire::Fire(12, false, true, true, false, true).ID: return 1537; case Fire::Fire(12, false, true, true, false, false).ID: return 1538; case Fire::Fire(12, false, true, false, true, true).ID: return 1539; case Fire::Fire(12, false, true, false, true, false).ID: return 1540; case Fire::Fire(12, false, true, false, false, true).ID: return 1541; case Fire::Fire(12, false, true, false, false, false).ID: return 1542; case Fire::Fire(12, false, false, true, true, true).ID: return 1543; case Fire::Fire(12, false, false, true, true, false).ID: return 1544; case Fire::Fire(12, false, false, true, false, true).ID: return 1545; case Fire::Fire(12, false, false, true, false, false).ID: return 1546; case Fire::Fire(12, false, false, false, true, true).ID: return 1547; case Fire::Fire(12, false, false, false, true, false).ID: return 1548; case Fire::Fire(12, false, false, false, false, true).ID: return 1549; case Fire::Fire(12, false, false, false, false, false).ID: return 1550; case Fire::Fire(13, true, true, true, true, true).ID: return 1551; case Fire::Fire(13, true, true, true, true, false).ID: return 1552; case Fire::Fire(13, true, true, true, false, true).ID: return 1553; case Fire::Fire(13, true, true, true, false, false).ID: return 1554; case Fire::Fire(13, true, true, false, true, true).ID: return 1555; case Fire::Fire(13, true, true, false, true, false).ID: return 1556; case Fire::Fire(13, true, true, false, false, true).ID: return 1557; case Fire::Fire(13, true, true, false, false, false).ID: return 1558; case Fire::Fire(13, true, false, true, true, true).ID: return 1559; case Fire::Fire(13, true, false, true, true, false).ID: return 1560; case Fire::Fire(13, true, false, true, false, true).ID: return 1561; case Fire::Fire(13, true, false, true, false, false).ID: return 1562; case Fire::Fire(13, true, false, false, true, true).ID: return 1563; case Fire::Fire(13, true, false, false, true, false).ID: return 1564; case Fire::Fire(13, true, false, false, false, true).ID: return 1565; case Fire::Fire(13, true, false, false, false, false).ID: return 1566; case Fire::Fire(13, false, true, true, true, true).ID: return 1567; case Fire::Fire(13, false, true, true, true, false).ID: return 1568; case Fire::Fire(13, false, true, true, false, true).ID: return 1569; case Fire::Fire(13, false, true, true, false, false).ID: return 1570; case Fire::Fire(13, false, true, false, true, true).ID: return 1571; case Fire::Fire(13, false, true, false, true, false).ID: return 1572; case Fire::Fire(13, false, true, false, false, true).ID: return 1573; case Fire::Fire(13, false, true, false, false, false).ID: return 1574; case Fire::Fire(13, false, false, true, true, true).ID: return 1575; case Fire::Fire(13, false, false, true, true, false).ID: return 1576; case Fire::Fire(13, false, false, true, false, true).ID: return 1577; case Fire::Fire(13, false, false, true, false, false).ID: return 1578; case Fire::Fire(13, false, false, false, true, true).ID: return 1579; case Fire::Fire(13, false, false, false, true, false).ID: return 1580; case Fire::Fire(13, false, false, false, false, true).ID: return 1581; case Fire::Fire(13, false, false, false, false, false).ID: return 1582; case Fire::Fire(14, true, true, true, true, true).ID: return 1583; case Fire::Fire(14, true, true, true, true, false).ID: return 1584; case Fire::Fire(14, true, true, true, false, true).ID: return 1585; case Fire::Fire(14, true, true, true, false, false).ID: return 1586; case Fire::Fire(14, true, true, false, true, true).ID: return 1587; case Fire::Fire(14, true, true, false, true, false).ID: return 1588; case Fire::Fire(14, true, true, false, false, true).ID: return 1589; case Fire::Fire(14, true, true, false, false, false).ID: return 1590; case Fire::Fire(14, true, false, true, true, true).ID: return 1591; case Fire::Fire(14, true, false, true, true, false).ID: return 1592; case Fire::Fire(14, true, false, true, false, true).ID: return 1593; case Fire::Fire(14, true, false, true, false, false).ID: return 1594; case Fire::Fire(14, true, false, false, true, true).ID: return 1595; case Fire::Fire(14, true, false, false, true, false).ID: return 1596; case Fire::Fire(14, true, false, false, false, true).ID: return 1597; case Fire::Fire(14, true, false, false, false, false).ID: return 1598; case Fire::Fire(14, false, true, true, true, true).ID: return 1599; case Fire::Fire(14, false, true, true, true, false).ID: return 1600; case Fire::Fire(14, false, true, true, false, true).ID: return 1601; case Fire::Fire(14, false, true, true, false, false).ID: return 1602; case Fire::Fire(14, false, true, false, true, true).ID: return 1603; case Fire::Fire(14, false, true, false, true, false).ID: return 1604; case Fire::Fire(14, false, true, false, false, true).ID: return 1605; case Fire::Fire(14, false, true, false, false, false).ID: return 1606; case Fire::Fire(14, false, false, true, true, true).ID: return 1607; case Fire::Fire(14, false, false, true, true, false).ID: return 1608; case Fire::Fire(14, false, false, true, false, true).ID: return 1609; case Fire::Fire(14, false, false, true, false, false).ID: return 1610; case Fire::Fire(14, false, false, false, true, true).ID: return 1611; case Fire::Fire(14, false, false, false, true, false).ID: return 1612; case Fire::Fire(14, false, false, false, false, true).ID: return 1613; case Fire::Fire(14, false, false, false, false, false).ID: return 1614; case Fire::Fire(15, true, true, true, true, true).ID: return 1615; case Fire::Fire(15, true, true, true, true, false).ID: return 1616; case Fire::Fire(15, true, true, true, false, true).ID: return 1617; case Fire::Fire(15, true, true, true, false, false).ID: return 1618; case Fire::Fire(15, true, true, false, true, true).ID: return 1619; case Fire::Fire(15, true, true, false, true, false).ID: return 1620; case Fire::Fire(15, true, true, false, false, true).ID: return 1621; case Fire::Fire(15, true, true, false, false, false).ID: return 1622; case Fire::Fire(15, true, false, true, true, true).ID: return 1623; case Fire::Fire(15, true, false, true, true, false).ID: return 1624; case Fire::Fire(15, true, false, true, false, true).ID: return 1625; case Fire::Fire(15, true, false, true, false, false).ID: return 1626; case Fire::Fire(15, true, false, false, true, true).ID: return 1627; case Fire::Fire(15, true, false, false, true, false).ID: return 1628; case Fire::Fire(15, true, false, false, false, true).ID: return 1629; case Fire::Fire(15, true, false, false, false, false).ID: return 1630; case Fire::Fire(15, false, true, true, true, true).ID: return 1631; case Fire::Fire(15, false, true, true, true, false).ID: return 1632; case Fire::Fire(15, false, true, true, false, true).ID: return 1633; case Fire::Fire(15, false, true, true, false, false).ID: return 1634; case Fire::Fire(15, false, true, false, true, true).ID: return 1635; case Fire::Fire(15, false, true, false, true, false).ID: return 1636; case Fire::Fire(15, false, true, false, false, true).ID: return 1637; case Fire::Fire(15, false, true, false, false, false).ID: return 1638; case Fire::Fire(15, false, false, true, true, true).ID: return 1639; case Fire::Fire(15, false, false, true, true, false).ID: return 1640; case Fire::Fire(15, false, false, true, false, true).ID: return 1641; case Fire::Fire(15, false, false, true, false, false).ID: return 1642; case Fire::Fire(15, false, false, false, true, true).ID: return 1643; case Fire::Fire(15, false, false, false, true, false).ID: return 1644; case Fire::Fire(15, false, false, false, false, true).ID: return 1645; case Fire::Fire(15, false, false, false, false, false).ID: return 1646; case FireCoral::FireCoral().ID: return 8462; case FireCoralBlock::FireCoralBlock().ID: return 8457; case FireCoralFan::FireCoralFan().ID: return 8561; case FireCoralWallFan::FireCoralWallFan(eBlockFace::BLOCK_FACE_ZM).ID: return 8529; case FireCoralWallFan::FireCoralWallFan(eBlockFace::BLOCK_FACE_ZP).ID: return 8531; case FireCoralWallFan::FireCoralWallFan(eBlockFace::BLOCK_FACE_XM).ID: return 8533; case FireCoralWallFan::FireCoralWallFan(eBlockFace::BLOCK_FACE_XP).ID: return 8535; case FlowerPot::FlowerPot().ID: return 5265; case FrostedIce::FrostedIce(0).ID: return 8188; case FrostedIce::FrostedIce(1).ID: return 8189; case FrostedIce::FrostedIce(2).ID: return 8190; case FrostedIce::FrostedIce(3).ID: return 8191; case Furnace::Furnace(eBlockFace::BLOCK_FACE_ZM, true).ID: return 3067; case Furnace::Furnace(eBlockFace::BLOCK_FACE_ZM, false).ID: return 3068; case Furnace::Furnace(eBlockFace::BLOCK_FACE_ZP, true).ID: return 3069; case Furnace::Furnace(eBlockFace::BLOCK_FACE_ZP, false).ID: return 3070; case Furnace::Furnace(eBlockFace::BLOCK_FACE_XM, true).ID: return 3071; case Furnace::Furnace(eBlockFace::BLOCK_FACE_XM, false).ID: return 3072; case Furnace::Furnace(eBlockFace::BLOCK_FACE_XP, true).ID: return 3073; case Furnace::Furnace(eBlockFace::BLOCK_FACE_XP, false).ID: return 3074; case Glass::Glass().ID: return 230; case GlassPane::GlassPane(true, true, true, true).ID: return 4213; case GlassPane::GlassPane(true, true, true, false).ID: return 4214; case GlassPane::GlassPane(true, true, false, true).ID: return 4217; case GlassPane::GlassPane(true, true, false, false).ID: return 4218; case GlassPane::GlassPane(true, false, true, true).ID: return 4221; case GlassPane::GlassPane(true, false, true, false).ID: return 4222; case GlassPane::GlassPane(true, false, false, true).ID: return 4225; case GlassPane::GlassPane(true, false, false, false).ID: return 4226; case GlassPane::GlassPane(false, true, true, true).ID: return 4229; case GlassPane::GlassPane(false, true, true, false).ID: return 4230; case GlassPane::GlassPane(false, true, false, true).ID: return 4233; case GlassPane::GlassPane(false, true, false, false).ID: return 4234; case GlassPane::GlassPane(false, false, true, true).ID: return 4237; case GlassPane::GlassPane(false, false, true, false).ID: return 4238; case GlassPane::GlassPane(false, false, false, true).ID: return 4241; case GlassPane::GlassPane(false, false, false, false).ID: return 4242; case Glowstone::Glowstone().ID: return 3495; case GoldBlock::GoldBlock().ID: return 1123; case GoldOre::GoldOre().ID: return 69; case Granite::Granite().ID: return 2; case Grass::Grass().ID: return 1041; case GrassBlock::GrassBlock(true).ID: return 8; case GrassBlock::GrassBlock(false).ID: return 9; case GrassPath::GrassPath().ID: return 8162; case Gravel::Gravel().ID: return 68; case GrayBanner::GrayBanner(0).ID: return 6966; case GrayBanner::GrayBanner(1).ID: return 6967; case GrayBanner::GrayBanner(2).ID: return 6968; case GrayBanner::GrayBanner(3).ID: return 6969; case GrayBanner::GrayBanner(4).ID: return 6970; case GrayBanner::GrayBanner(5).ID: return 6971; case GrayBanner::GrayBanner(6).ID: return 6972; case GrayBanner::GrayBanner(7).ID: return 6973; case GrayBanner::GrayBanner(8).ID: return 6974; case GrayBanner::GrayBanner(9).ID: return 6975; case GrayBanner::GrayBanner(10).ID: return 6976; case GrayBanner::GrayBanner(11).ID: return 6977; case GrayBanner::GrayBanner(12).ID: return 6978; case GrayBanner::GrayBanner(13).ID: return 6979; case GrayBanner::GrayBanner(14).ID: return 6980; case GrayBanner::GrayBanner(15).ID: return 6981; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_ZM, true, GrayBed::Part::Head).ID: return 860; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_ZM, true, GrayBed::Part::Foot).ID: return 861; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_ZM, false, GrayBed::Part::Head).ID: return 862; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_ZM, false, GrayBed::Part::Foot).ID: return 863; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_ZP, true, GrayBed::Part::Head).ID: return 864; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_ZP, true, GrayBed::Part::Foot).ID: return 865; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_ZP, false, GrayBed::Part::Head).ID: return 866; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_ZP, false, GrayBed::Part::Foot).ID: return 867; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_XM, true, GrayBed::Part::Head).ID: return 868; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_XM, true, GrayBed::Part::Foot).ID: return 869; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_XM, false, GrayBed::Part::Head).ID: return 870; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_XM, false, GrayBed::Part::Foot).ID: return 871; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_XP, true, GrayBed::Part::Head).ID: return 872; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_XP, true, GrayBed::Part::Foot).ID: return 873; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_XP, false, GrayBed::Part::Head).ID: return 874; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_XP, false, GrayBed::Part::Foot).ID: return 875; case GrayCarpet::GrayCarpet().ID: return 6830; case GrayConcrete::GrayConcrete().ID: return 8384; case GrayConcretePowder::GrayConcretePowder().ID: return 8400; case GrayGlazedTerracotta::GrayGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 8341; case GrayGlazedTerracotta::GrayGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 8342; case GrayGlazedTerracotta::GrayGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 8343; case GrayGlazedTerracotta::GrayGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 8344; case GrayShulkerBox::GrayShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 8259; case GrayShulkerBox::GrayShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 8260; case GrayShulkerBox::GrayShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 8261; case GrayShulkerBox::GrayShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 8262; case GrayShulkerBox::GrayShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 8263; case GrayShulkerBox::GrayShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 8264; case GrayStainedGlass::GrayStainedGlass().ID: return 3584; case GrayStainedGlassPane::GrayStainedGlassPane(true, true, true, true).ID: return 6046; case GrayStainedGlassPane::GrayStainedGlassPane(true, true, true, false).ID: return 6047; case GrayStainedGlassPane::GrayStainedGlassPane(true, true, false, true).ID: return 6050; case GrayStainedGlassPane::GrayStainedGlassPane(true, true, false, false).ID: return 6051; case GrayStainedGlassPane::GrayStainedGlassPane(true, false, true, true).ID: return 6054; case GrayStainedGlassPane::GrayStainedGlassPane(true, false, true, false).ID: return 6055; case GrayStainedGlassPane::GrayStainedGlassPane(true, false, false, true).ID: return 6058; case GrayStainedGlassPane::GrayStainedGlassPane(true, false, false, false).ID: return 6059; case GrayStainedGlassPane::GrayStainedGlassPane(false, true, true, true).ID: return 6062; case GrayStainedGlassPane::GrayStainedGlassPane(false, true, true, false).ID: return 6063; case GrayStainedGlassPane::GrayStainedGlassPane(false, true, false, true).ID: return 6066; case GrayStainedGlassPane::GrayStainedGlassPane(false, true, false, false).ID: return 6067; case GrayStainedGlassPane::GrayStainedGlassPane(false, false, true, true).ID: return 6070; case GrayStainedGlassPane::GrayStainedGlassPane(false, false, true, false).ID: return 6071; case GrayStainedGlassPane::GrayStainedGlassPane(false, false, false, true).ID: return 6074; case GrayStainedGlassPane::GrayStainedGlassPane(false, false, false, false).ID: return 6075; case GrayTerracotta::GrayTerracotta().ID: return 5811; case GrayWallBanner::GrayWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 7138; case GrayWallBanner::GrayWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 7139; case GrayWallBanner::GrayWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 7140; case GrayWallBanner::GrayWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 7141; case GrayWool::GrayWool().ID: return 1090; case GreenBanner::GreenBanner(0).ID: return 7062; case GreenBanner::GreenBanner(1).ID: return 7063; case GreenBanner::GreenBanner(2).ID: return 7064; case GreenBanner::GreenBanner(3).ID: return 7065; case GreenBanner::GreenBanner(4).ID: return 7066; case GreenBanner::GreenBanner(5).ID: return 7067; case GreenBanner::GreenBanner(6).ID: return 7068; case GreenBanner::GreenBanner(7).ID: return 7069; case GreenBanner::GreenBanner(8).ID: return 7070; case GreenBanner::GreenBanner(9).ID: return 7071; case GreenBanner::GreenBanner(10).ID: return 7072; case GreenBanner::GreenBanner(11).ID: return 7073; case GreenBanner::GreenBanner(12).ID: return 7074; case GreenBanner::GreenBanner(13).ID: return 7075; case GreenBanner::GreenBanner(14).ID: return 7076; case GreenBanner::GreenBanner(15).ID: return 7077; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_ZM, true, GreenBed::Part::Head).ID: return 956; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_ZM, true, GreenBed::Part::Foot).ID: return 957; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_ZM, false, GreenBed::Part::Head).ID: return 958; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_ZM, false, GreenBed::Part::Foot).ID: return 959; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_ZP, true, GreenBed::Part::Head).ID: return 960; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_ZP, true, GreenBed::Part::Foot).ID: return 961; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_ZP, false, GreenBed::Part::Head).ID: return 962; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_ZP, false, GreenBed::Part::Foot).ID: return 963; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_XM, true, GreenBed::Part::Head).ID: return 964; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_XM, true, GreenBed::Part::Foot).ID: return 965; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_XM, false, GreenBed::Part::Head).ID: return 966; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_XM, false, GreenBed::Part::Foot).ID: return 967; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_XP, true, GreenBed::Part::Head).ID: return 968; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_XP, true, GreenBed::Part::Foot).ID: return 969; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_XP, false, GreenBed::Part::Head).ID: return 970; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_XP, false, GreenBed::Part::Foot).ID: return 971; case GreenCarpet::GreenCarpet().ID: return 6836; case GreenConcrete::GreenConcrete().ID: return 8390; case GreenConcretePowder::GreenConcretePowder().ID: return 8406; case GreenGlazedTerracotta::GreenGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 8365; case GreenGlazedTerracotta::GreenGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 8366; case GreenGlazedTerracotta::GreenGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 8367; case GreenGlazedTerracotta::GreenGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 8368; case GreenShulkerBox::GreenShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 8295; case GreenShulkerBox::GreenShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 8296; case GreenShulkerBox::GreenShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 8297; case GreenShulkerBox::GreenShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 8298; case GreenShulkerBox::GreenShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 8299; case GreenShulkerBox::GreenShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 8300; case GreenStainedGlass::GreenStainedGlass().ID: return 3590; case GreenStainedGlassPane::GreenStainedGlassPane(true, true, true, true).ID: return 6238; case GreenStainedGlassPane::GreenStainedGlassPane(true, true, true, false).ID: return 6239; case GreenStainedGlassPane::GreenStainedGlassPane(true, true, false, true).ID: return 6242; case GreenStainedGlassPane::GreenStainedGlassPane(true, true, false, false).ID: return 6243; case GreenStainedGlassPane::GreenStainedGlassPane(true, false, true, true).ID: return 6246; case GreenStainedGlassPane::GreenStainedGlassPane(true, false, true, false).ID: return 6247; case GreenStainedGlassPane::GreenStainedGlassPane(true, false, false, true).ID: return 6250; case GreenStainedGlassPane::GreenStainedGlassPane(true, false, false, false).ID: return 6251; case GreenStainedGlassPane::GreenStainedGlassPane(false, true, true, true).ID: return 6254; case GreenStainedGlassPane::GreenStainedGlassPane(false, true, true, false).ID: return 6255; case GreenStainedGlassPane::GreenStainedGlassPane(false, true, false, true).ID: return 6258; case GreenStainedGlassPane::GreenStainedGlassPane(false, true, false, false).ID: return 6259; case GreenStainedGlassPane::GreenStainedGlassPane(false, false, true, true).ID: return 6262; case GreenStainedGlassPane::GreenStainedGlassPane(false, false, true, false).ID: return 6263; case GreenStainedGlassPane::GreenStainedGlassPane(false, false, false, true).ID: return 6266; case GreenStainedGlassPane::GreenStainedGlassPane(false, false, false, false).ID: return 6267; case GreenTerracotta::GreenTerracotta().ID: return 5817; case GreenWallBanner::GreenWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 7162; case GreenWallBanner::GreenWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 7163; case GreenWallBanner::GreenWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 7164; case GreenWallBanner::GreenWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 7165; case GreenWool::GreenWool().ID: return 1096; case HayBale::HayBale(HayBale::Axis::X).ID: return 6820; case HayBale::HayBale(HayBale::Axis::Y).ID: return 6821; case HayBale::HayBale(HayBale::Axis::Z).ID: return 6822; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(0).ID: return 5619; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(1).ID: return 5620; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(2).ID: return 5621; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(3).ID: return 5622; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(4).ID: return 5623; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(5).ID: return 5624; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(6).ID: return 5625; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(7).ID: return 5626; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(8).ID: return 5627; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(9).ID: return 5628; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(10).ID: return 5629; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(11).ID: return 5630; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(12).ID: return 5631; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(13).ID: return 5632; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(14).ID: return 5633; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(15).ID: return 5634; case Hopper::Hopper(true, eBlockFace::BLOCK_FACE_YM).ID: return 5685; case Hopper::Hopper(true, eBlockFace::BLOCK_FACE_ZM).ID: return 5686; case Hopper::Hopper(true, eBlockFace::BLOCK_FACE_ZP).ID: return 5687; case Hopper::Hopper(true, eBlockFace::BLOCK_FACE_XM).ID: return 5688; case Hopper::Hopper(true, eBlockFace::BLOCK_FACE_XP).ID: return 5689; case Hopper::Hopper(false, eBlockFace::BLOCK_FACE_YM).ID: return 5690; case Hopper::Hopper(false, eBlockFace::BLOCK_FACE_ZM).ID: return 5691; case Hopper::Hopper(false, eBlockFace::BLOCK_FACE_ZP).ID: return 5692; case Hopper::Hopper(false, eBlockFace::BLOCK_FACE_XM).ID: return 5693; case Hopper::Hopper(false, eBlockFace::BLOCK_FACE_XP).ID: return 5694; case HornCoral::HornCoral().ID: return 8463; case HornCoralBlock::HornCoralBlock().ID: return 8458; case HornCoralFan::HornCoralFan().ID: return 8563; case HornCoralWallFan::HornCoralWallFan(eBlockFace::BLOCK_FACE_ZM).ID: return 8537; case HornCoralWallFan::HornCoralWallFan(eBlockFace::BLOCK_FACE_ZP).ID: return 8539; case HornCoralWallFan::HornCoralWallFan(eBlockFace::BLOCK_FACE_XM).ID: return 8541; case HornCoralWallFan::HornCoralWallFan(eBlockFace::BLOCK_FACE_XP).ID: return 8543; case Ice::Ice().ID: return 3423; case InfestedChiseledStoneBricks::InfestedChiseledStoneBricks().ID: return 3982; case InfestedCobblestone::InfestedCobblestone().ID: return 3978; case InfestedCrackedStoneBricks::InfestedCrackedStoneBricks().ID: return 3981; case InfestedMossyStoneBricks::InfestedMossyStoneBricks().ID: return 3980; case InfestedStone::InfestedStone().ID: return 3977; case InfestedStoneBricks::InfestedStoneBricks().ID: return 3979; case IronBars::IronBars(true, true, true, true).ID: return 4181; case IronBars::IronBars(true, true, true, false).ID: return 4182; case IronBars::IronBars(true, true, false, true).ID: return 4185; case IronBars::IronBars(true, true, false, false).ID: return 4186; case IronBars::IronBars(true, false, true, true).ID: return 4189; case IronBars::IronBars(true, false, true, false).ID: return 4190; case IronBars::IronBars(true, false, false, true).ID: return 4193; case IronBars::IronBars(true, false, false, false).ID: return 4194; case IronBars::IronBars(false, true, true, true).ID: return 4197; case IronBars::IronBars(false, true, true, false).ID: return 4198; case IronBars::IronBars(false, true, false, true).ID: return 4201; case IronBars::IronBars(false, true, false, false).ID: return 4202; case IronBars::IronBars(false, false, true, true).ID: return 4205; case IronBars::IronBars(false, false, true, false).ID: return 4206; case IronBars::IronBars(false, false, false, true).ID: return 4209; case IronBars::IronBars(false, false, false, false).ID: return 4210; case IronBlock::IronBlock().ID: return 1124; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Upper, IronDoor::Hinge::Left, true, true).ID: return 3303; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Upper, IronDoor::Hinge::Left, true, false).ID: return 3304; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Upper, IronDoor::Hinge::Left, false, true).ID: return 3305; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Upper, IronDoor::Hinge::Left, false, false).ID: return 3306; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Upper, IronDoor::Hinge::Right, true, true).ID: return 3307; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Upper, IronDoor::Hinge::Right, true, false).ID: return 3308; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Upper, IronDoor::Hinge::Right, false, true).ID: return 3309; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Upper, IronDoor::Hinge::Right, false, false).ID: return 3310; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Lower, IronDoor::Hinge::Left, true, true).ID: return 3311; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Lower, IronDoor::Hinge::Left, true, false).ID: return 3312; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Lower, IronDoor::Hinge::Left, false, true).ID: return 3313; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Lower, IronDoor::Hinge::Left, false, false).ID: return 3314; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Lower, IronDoor::Hinge::Right, true, true).ID: return 3315; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Lower, IronDoor::Hinge::Right, true, false).ID: return 3316; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Lower, IronDoor::Hinge::Right, false, true).ID: return 3317; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Lower, IronDoor::Hinge::Right, false, false).ID: return 3318; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Upper, IronDoor::Hinge::Left, true, true).ID: return 3319; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Upper, IronDoor::Hinge::Left, true, false).ID: return 3320; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Upper, IronDoor::Hinge::Left, false, true).ID: return 3321; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Upper, IronDoor::Hinge::Left, false, false).ID: return 3322; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Upper, IronDoor::Hinge::Right, true, true).ID: return 3323; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Upper, IronDoor::Hinge::Right, true, false).ID: return 3324; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Upper, IronDoor::Hinge::Right, false, true).ID: return 3325; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Upper, IronDoor::Hinge::Right, false, false).ID: return 3326; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Lower, IronDoor::Hinge::Left, true, true).ID: return 3327; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Lower, IronDoor::Hinge::Left, true, false).ID: return 3328; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Lower, IronDoor::Hinge::Left, false, true).ID: return 3329; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Lower, IronDoor::Hinge::Left, false, false).ID: return 3330; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Lower, IronDoor::Hinge::Right, true, true).ID: return 3331; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Lower, IronDoor::Hinge::Right, true, false).ID: return 3332; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Lower, IronDoor::Hinge::Right, false, true).ID: return 3333; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Lower, IronDoor::Hinge::Right, false, false).ID: return 3334; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Upper, IronDoor::Hinge::Left, true, true).ID: return 3335; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Upper, IronDoor::Hinge::Left, true, false).ID: return 3336; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Upper, IronDoor::Hinge::Left, false, true).ID: return 3337; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Upper, IronDoor::Hinge::Left, false, false).ID: return 3338; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Upper, IronDoor::Hinge::Right, true, true).ID: return 3339; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Upper, IronDoor::Hinge::Right, true, false).ID: return 3340; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Upper, IronDoor::Hinge::Right, false, true).ID: return 3341; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Upper, IronDoor::Hinge::Right, false, false).ID: return 3342; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Lower, IronDoor::Hinge::Left, true, true).ID: return 3343; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Lower, IronDoor::Hinge::Left, true, false).ID: return 3344; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Lower, IronDoor::Hinge::Left, false, true).ID: return 3345; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Lower, IronDoor::Hinge::Left, false, false).ID: return 3346; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Lower, IronDoor::Hinge::Right, true, true).ID: return 3347; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Lower, IronDoor::Hinge::Right, true, false).ID: return 3348; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Lower, IronDoor::Hinge::Right, false, true).ID: return 3349; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Lower, IronDoor::Hinge::Right, false, false).ID: return 3350; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Upper, IronDoor::Hinge::Left, true, true).ID: return 3351; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Upper, IronDoor::Hinge::Left, true, false).ID: return 3352; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Upper, IronDoor::Hinge::Left, false, true).ID: return 3353; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Upper, IronDoor::Hinge::Left, false, false).ID: return 3354; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Upper, IronDoor::Hinge::Right, true, true).ID: return 3355; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Upper, IronDoor::Hinge::Right, true, false).ID: return 3356; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Upper, IronDoor::Hinge::Right, false, true).ID: return 3357; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Upper, IronDoor::Hinge::Right, false, false).ID: return 3358; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Lower, IronDoor::Hinge::Left, true, true).ID: return 3359; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Lower, IronDoor::Hinge::Left, true, false).ID: return 3360; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Lower, IronDoor::Hinge::Left, false, true).ID: return 3361; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Lower, IronDoor::Hinge::Left, false, false).ID: return 3362; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Lower, IronDoor::Hinge::Right, true, true).ID: return 3363; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Lower, IronDoor::Hinge::Right, true, false).ID: return 3364; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Lower, IronDoor::Hinge::Right, false, true).ID: return 3365; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Lower, IronDoor::Hinge::Right, false, false).ID: return 3366; case IronOre::IronOre().ID: return 70; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZM, IronTrapdoor::Half::Top, true, true).ID: return 6495; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZM, IronTrapdoor::Half::Top, true, false).ID: return 6497; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZM, IronTrapdoor::Half::Top, false, true).ID: return 6499; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZM, IronTrapdoor::Half::Top, false, false).ID: return 6501; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZM, IronTrapdoor::Half::Bottom, true, true).ID: return 6503; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZM, IronTrapdoor::Half::Bottom, true, false).ID: return 6505; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZM, IronTrapdoor::Half::Bottom, false, true).ID: return 6507; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZM, IronTrapdoor::Half::Bottom, false, false).ID: return 6509; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZP, IronTrapdoor::Half::Top, true, true).ID: return 6511; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZP, IronTrapdoor::Half::Top, true, false).ID: return 6513; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZP, IronTrapdoor::Half::Top, false, true).ID: return 6515; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZP, IronTrapdoor::Half::Top, false, false).ID: return 6517; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZP, IronTrapdoor::Half::Bottom, true, true).ID: return 6519; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZP, IronTrapdoor::Half::Bottom, true, false).ID: return 6521; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZP, IronTrapdoor::Half::Bottom, false, true).ID: return 6523; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZP, IronTrapdoor::Half::Bottom, false, false).ID: return 6525; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XM, IronTrapdoor::Half::Top, true, true).ID: return 6527; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XM, IronTrapdoor::Half::Top, true, false).ID: return 6529; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XM, IronTrapdoor::Half::Top, false, true).ID: return 6531; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XM, IronTrapdoor::Half::Top, false, false).ID: return 6533; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XM, IronTrapdoor::Half::Bottom, true, true).ID: return 6535; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XM, IronTrapdoor::Half::Bottom, true, false).ID: return 6537; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XM, IronTrapdoor::Half::Bottom, false, true).ID: return 6539; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XM, IronTrapdoor::Half::Bottom, false, false).ID: return 6541; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XP, IronTrapdoor::Half::Top, true, true).ID: return 6543; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XP, IronTrapdoor::Half::Top, true, false).ID: return 6545; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XP, IronTrapdoor::Half::Top, false, true).ID: return 6547; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XP, IronTrapdoor::Half::Top, false, false).ID: return 6549; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XP, IronTrapdoor::Half::Bottom, true, true).ID: return 6551; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XP, IronTrapdoor::Half::Bottom, true, false).ID: return 6553; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XP, IronTrapdoor::Half::Bottom, false, true).ID: return 6555; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XP, IronTrapdoor::Half::Bottom, false, false).ID: return 6557; case JackOLantern::JackOLantern(eBlockFace::BLOCK_FACE_ZM).ID: return 3502; case JackOLantern::JackOLantern(eBlockFace::BLOCK_FACE_ZP).ID: return 3503; case JackOLantern::JackOLantern(eBlockFace::BLOCK_FACE_XM).ID: return 3504; case JackOLantern::JackOLantern(eBlockFace::BLOCK_FACE_XP).ID: return 3505; case Jukebox::Jukebox(true).ID: return 3458; case Jukebox::Jukebox(false).ID: return 3459; case JungleButton::JungleButton(JungleButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5375; case JungleButton::JungleButton(JungleButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5376; case JungleButton::JungleButton(JungleButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5377; case JungleButton::JungleButton(JungleButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5378; case JungleButton::JungleButton(JungleButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, true).ID: return 5379; case JungleButton::JungleButton(JungleButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, false).ID: return 5380; case JungleButton::JungleButton(JungleButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, true).ID: return 5381; case JungleButton::JungleButton(JungleButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, false).ID: return 5382; case JungleButton::JungleButton(JungleButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5383; case JungleButton::JungleButton(JungleButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5384; case JungleButton::JungleButton(JungleButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5385; case JungleButton::JungleButton(JungleButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5386; case JungleButton::JungleButton(JungleButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, true).ID: return 5387; case JungleButton::JungleButton(JungleButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, false).ID: return 5388; case JungleButton::JungleButton(JungleButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, true).ID: return 5389; case JungleButton::JungleButton(JungleButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, false).ID: return 5390; case JungleButton::JungleButton(JungleButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5391; case JungleButton::JungleButton(JungleButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5392; case JungleButton::JungleButton(JungleButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5393; case JungleButton::JungleButton(JungleButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5394; case JungleButton::JungleButton(JungleButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, true).ID: return 5395; case JungleButton::JungleButton(JungleButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, false).ID: return 5396; case JungleButton::JungleButton(JungleButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, true).ID: return 5397; case JungleButton::JungleButton(JungleButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, false).ID: return 5398; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, true, true).ID: return 7805; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, true, false).ID: return 7806; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, false, true).ID: return 7807; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, false, false).ID: return 7808; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, true, true).ID: return 7809; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, true, false).ID: return 7810; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, false, true).ID: return 7811; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, false, false).ID: return 7812; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, true, true).ID: return 7813; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, true, false).ID: return 7814; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, false, true).ID: return 7815; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, false, false).ID: return 7816; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, true, true).ID: return 7817; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, true, false).ID: return 7818; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, false, true).ID: return 7819; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, false, false).ID: return 7820; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, true, true).ID: return 7821; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, true, false).ID: return 7822; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, false, true).ID: return 7823; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, false, false).ID: return 7824; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, true, true).ID: return 7825; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, true, false).ID: return 7826; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, false, true).ID: return 7827; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, false, false).ID: return 7828; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, true, true).ID: return 7829; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, true, false).ID: return 7830; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, false, true).ID: return 7831; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, false, false).ID: return 7832; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, true, true).ID: return 7833; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, true, false).ID: return 7834; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, false, true).ID: return 7835; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, false, false).ID: return 7836; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, true, true).ID: return 7837; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, true, false).ID: return 7838; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, false, true).ID: return 7839; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, false, false).ID: return 7840; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, true, true).ID: return 7841; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, true, false).ID: return 7842; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, false, true).ID: return 7843; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, false, false).ID: return 7844; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, true, true).ID: return 7845; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, true, false).ID: return 7846; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, false, true).ID: return 7847; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, false, false).ID: return 7848; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, true, true).ID: return 7849; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, true, false).ID: return 7850; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, false, true).ID: return 7851; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, false, false).ID: return 7852; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, true, true).ID: return 7853; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, true, false).ID: return 7854; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, false, true).ID: return 7855; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, false, false).ID: return 7856; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, true, true).ID: return 7857; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, true, false).ID: return 7858; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, false, true).ID: return 7859; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, false, false).ID: return 7860; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, true, true).ID: return 7861; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, true, false).ID: return 7862; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, false, true).ID: return 7863; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, false, false).ID: return 7864; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, true, true).ID: return 7865; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, true, false).ID: return 7866; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, false, true).ID: return 7867; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, false, false).ID: return 7868; case JungleFence::JungleFence(true, true, true, true).ID: return 7583; case JungleFence::JungleFence(true, true, true, false).ID: return 7584; case JungleFence::JungleFence(true, true, false, true).ID: return 7587; case JungleFence::JungleFence(true, true, false, false).ID: return 7588; case JungleFence::JungleFence(true, false, true, true).ID: return 7591; case JungleFence::JungleFence(true, false, true, false).ID: return 7592; case JungleFence::JungleFence(true, false, false, true).ID: return 7595; case JungleFence::JungleFence(true, false, false, false).ID: return 7596; case JungleFence::JungleFence(false, true, true, true).ID: return 7599; case JungleFence::JungleFence(false, true, true, false).ID: return 7600; case JungleFence::JungleFence(false, true, false, true).ID: return 7603; case JungleFence::JungleFence(false, true, false, false).ID: return 7604; case JungleFence::JungleFence(false, false, true, true).ID: return 7607; case JungleFence::JungleFence(false, false, true, false).ID: return 7608; case JungleFence::JungleFence(false, false, false, true).ID: return 7611; case JungleFence::JungleFence(false, false, false, false).ID: return 7612; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZM, true, true, true).ID: return 7421; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZM, true, true, false).ID: return 7422; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZM, true, false, true).ID: return 7423; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZM, true, false, false).ID: return 7424; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, true).ID: return 7425; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, false).ID: return 7426; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, true).ID: return 7427; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, false).ID: return 7428; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZP, true, true, true).ID: return 7429; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZP, true, true, false).ID: return 7430; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZP, true, false, true).ID: return 7431; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZP, true, false, false).ID: return 7432; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, true).ID: return 7433; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, false).ID: return 7434; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, true).ID: return 7435; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, false).ID: return 7436; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XM, true, true, true).ID: return 7437; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XM, true, true, false).ID: return 7438; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XM, true, false, true).ID: return 7439; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XM, true, false, false).ID: return 7440; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, true).ID: return 7441; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, false).ID: return 7442; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, true).ID: return 7443; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, false).ID: return 7444; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XP, true, true, true).ID: return 7445; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XP, true, true, false).ID: return 7446; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XP, true, false, true).ID: return 7447; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XP, true, false, false).ID: return 7448; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, true).ID: return 7449; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, false).ID: return 7450; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, true).ID: return 7451; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, false).ID: return 7452; case JungleLeaves::JungleLeaves(1, true).ID: return 186; case JungleLeaves::JungleLeaves(1, false).ID: return 187; case JungleLeaves::JungleLeaves(2, true).ID: return 188; case JungleLeaves::JungleLeaves(2, false).ID: return 189; case JungleLeaves::JungleLeaves(3, true).ID: return 190; case JungleLeaves::JungleLeaves(3, false).ID: return 191; case JungleLeaves::JungleLeaves(4, true).ID: return 192; case JungleLeaves::JungleLeaves(4, false).ID: return 193; case JungleLeaves::JungleLeaves(5, true).ID: return 194; case JungleLeaves::JungleLeaves(5, false).ID: return 195; case JungleLeaves::JungleLeaves(6, true).ID: return 196; case JungleLeaves::JungleLeaves(6, false).ID: return 197; case JungleLeaves::JungleLeaves(7, true).ID: return 198; case JungleLeaves::JungleLeaves(7, false).ID: return 199; case JungleLog::JungleLog(JungleLog::Axis::X).ID: return 81; case JungleLog::JungleLog(JungleLog::Axis::Y).ID: return 82; case JungleLog::JungleLog(JungleLog::Axis::Z).ID: return 83; case JunglePlanks::JunglePlanks().ID: return 18; case JunglePressurePlate::JunglePressurePlate(true).ID: return 3373; case JunglePressurePlate::JunglePressurePlate(false).ID: return 3374; case JungleSapling::JungleSapling(0).ID: return 27; case JungleSapling::JungleSapling(1).ID: return 28; case JungleSlab::JungleSlab(JungleSlab::Type::Top).ID: return 7276; case JungleSlab::JungleSlab(JungleSlab::Type::Bottom).ID: return 7278; case JungleSlab::JungleSlab(JungleSlab::Type::Double).ID: return 7280; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZM, JungleStairs::Half::Top, JungleStairs::Shape::Straight).ID: return 5045; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZM, JungleStairs::Half::Top, JungleStairs::Shape::InnerLeft).ID: return 5047; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZM, JungleStairs::Half::Top, JungleStairs::Shape::InnerRight).ID: return 5049; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZM, JungleStairs::Half::Top, JungleStairs::Shape::OuterLeft).ID: return 5051; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZM, JungleStairs::Half::Top, JungleStairs::Shape::OuterRight).ID: return 5053; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZM, JungleStairs::Half::Bottom, JungleStairs::Shape::Straight).ID: return 5055; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZM, JungleStairs::Half::Bottom, JungleStairs::Shape::InnerLeft).ID: return 5057; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZM, JungleStairs::Half::Bottom, JungleStairs::Shape::InnerRight).ID: return 5059; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZM, JungleStairs::Half::Bottom, JungleStairs::Shape::OuterLeft).ID: return 5061; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZM, JungleStairs::Half::Bottom, JungleStairs::Shape::OuterRight).ID: return 5063; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZP, JungleStairs::Half::Top, JungleStairs::Shape::Straight).ID: return 5065; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZP, JungleStairs::Half::Top, JungleStairs::Shape::InnerLeft).ID: return 5067; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZP, JungleStairs::Half::Top, JungleStairs::Shape::InnerRight).ID: return 5069; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZP, JungleStairs::Half::Top, JungleStairs::Shape::OuterLeft).ID: return 5071; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZP, JungleStairs::Half::Top, JungleStairs::Shape::OuterRight).ID: return 5073; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZP, JungleStairs::Half::Bottom, JungleStairs::Shape::Straight).ID: return 5075; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZP, JungleStairs::Half::Bottom, JungleStairs::Shape::InnerLeft).ID: return 5077; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZP, JungleStairs::Half::Bottom, JungleStairs::Shape::InnerRight).ID: return 5079; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZP, JungleStairs::Half::Bottom, JungleStairs::Shape::OuterLeft).ID: return 5081; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZP, JungleStairs::Half::Bottom, JungleStairs::Shape::OuterRight).ID: return 5083; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XM, JungleStairs::Half::Top, JungleStairs::Shape::Straight).ID: return 5085; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XM, JungleStairs::Half::Top, JungleStairs::Shape::InnerLeft).ID: return 5087; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XM, JungleStairs::Half::Top, JungleStairs::Shape::InnerRight).ID: return 5089; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XM, JungleStairs::Half::Top, JungleStairs::Shape::OuterLeft).ID: return 5091; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XM, JungleStairs::Half::Top, JungleStairs::Shape::OuterRight).ID: return 5093; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XM, JungleStairs::Half::Bottom, JungleStairs::Shape::Straight).ID: return 5095; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XM, JungleStairs::Half::Bottom, JungleStairs::Shape::InnerLeft).ID: return 5097; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XM, JungleStairs::Half::Bottom, JungleStairs::Shape::InnerRight).ID: return 5099; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XM, JungleStairs::Half::Bottom, JungleStairs::Shape::OuterLeft).ID: return 5101; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XM, JungleStairs::Half::Bottom, JungleStairs::Shape::OuterRight).ID: return 5103; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XP, JungleStairs::Half::Top, JungleStairs::Shape::Straight).ID: return 5105; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XP, JungleStairs::Half::Top, JungleStairs::Shape::InnerLeft).ID: return 5107; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XP, JungleStairs::Half::Top, JungleStairs::Shape::InnerRight).ID: return 5109; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XP, JungleStairs::Half::Top, JungleStairs::Shape::OuterLeft).ID: return 5111; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XP, JungleStairs::Half::Top, JungleStairs::Shape::OuterRight).ID: return 5113; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XP, JungleStairs::Half::Bottom, JungleStairs::Shape::Straight).ID: return 5115; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XP, JungleStairs::Half::Bottom, JungleStairs::Shape::InnerLeft).ID: return 5117; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XP, JungleStairs::Half::Bottom, JungleStairs::Shape::InnerRight).ID: return 5119; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XP, JungleStairs::Half::Bottom, JungleStairs::Shape::OuterLeft).ID: return 5121; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XP, JungleStairs::Half::Bottom, JungleStairs::Shape::OuterRight).ID: return 5123; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZM, JungleTrapdoor::Half::Top, true, true).ID: return 3786; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZM, JungleTrapdoor::Half::Top, true, false).ID: return 3788; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZM, JungleTrapdoor::Half::Top, false, true).ID: return 3790; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZM, JungleTrapdoor::Half::Top, false, false).ID: return 3792; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZM, JungleTrapdoor::Half::Bottom, true, true).ID: return 3794; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZM, JungleTrapdoor::Half::Bottom, true, false).ID: return 3796; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZM, JungleTrapdoor::Half::Bottom, false, true).ID: return 3798; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZM, JungleTrapdoor::Half::Bottom, false, false).ID: return 3800; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZP, JungleTrapdoor::Half::Top, true, true).ID: return 3802; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZP, JungleTrapdoor::Half::Top, true, false).ID: return 3804; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZP, JungleTrapdoor::Half::Top, false, true).ID: return 3806; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZP, JungleTrapdoor::Half::Top, false, false).ID: return 3808; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZP, JungleTrapdoor::Half::Bottom, true, true).ID: return 3810; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZP, JungleTrapdoor::Half::Bottom, true, false).ID: return 3812; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZP, JungleTrapdoor::Half::Bottom, false, true).ID: return 3814; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZP, JungleTrapdoor::Half::Bottom, false, false).ID: return 3816; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XM, JungleTrapdoor::Half::Top, true, true).ID: return 3818; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XM, JungleTrapdoor::Half::Top, true, false).ID: return 3820; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XM, JungleTrapdoor::Half::Top, false, true).ID: return 3822; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XM, JungleTrapdoor::Half::Top, false, false).ID: return 3824; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XM, JungleTrapdoor::Half::Bottom, true, true).ID: return 3826; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XM, JungleTrapdoor::Half::Bottom, true, false).ID: return 3828; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XM, JungleTrapdoor::Half::Bottom, false, true).ID: return 3830; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XM, JungleTrapdoor::Half::Bottom, false, false).ID: return 3832; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XP, JungleTrapdoor::Half::Top, true, true).ID: return 3834; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XP, JungleTrapdoor::Half::Top, true, false).ID: return 3836; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XP, JungleTrapdoor::Half::Top, false, true).ID: return 3838; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XP, JungleTrapdoor::Half::Top, false, false).ID: return 3840; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XP, JungleTrapdoor::Half::Bottom, true, true).ID: return 3842; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XP, JungleTrapdoor::Half::Bottom, true, false).ID: return 3844; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XP, JungleTrapdoor::Half::Bottom, false, true).ID: return 3846; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XP, JungleTrapdoor::Half::Bottom, false, false).ID: return 3848; case JungleWood::JungleWood(JungleWood::Axis::X).ID: return 117; case JungleWood::JungleWood(JungleWood::Axis::Y).ID: return 118; case JungleWood::JungleWood(JungleWood::Axis::Z).ID: return 119; case Kelp::Kelp(0).ID: return 8409; case Kelp::Kelp(1).ID: return 8410; case Kelp::Kelp(2).ID: return 8411; case Kelp::Kelp(3).ID: return 8412; case Kelp::Kelp(4).ID: return 8413; case Kelp::Kelp(5).ID: return 8414; case Kelp::Kelp(6).ID: return 8415; case Kelp::Kelp(7).ID: return 8416; case Kelp::Kelp(8).ID: return 8417; case Kelp::Kelp(9).ID: return 8418; case Kelp::Kelp(10).ID: return 8419; case Kelp::Kelp(11).ID: return 8420; case Kelp::Kelp(12).ID: return 8421; case Kelp::Kelp(13).ID: return 8422; case Kelp::Kelp(14).ID: return 8423; case Kelp::Kelp(15).ID: return 8424; case Kelp::Kelp(16).ID: return 8425; case Kelp::Kelp(17).ID: return 8426; case Kelp::Kelp(18).ID: return 8427; case Kelp::Kelp(19).ID: return 8428; case Kelp::Kelp(20).ID: return 8429; case Kelp::Kelp(21).ID: return 8430; case Kelp::Kelp(22).ID: return 8431; case Kelp::Kelp(23).ID: return 8432; case Kelp::Kelp(24).ID: return 8433; case Kelp::Kelp(25).ID: return 8434; case KelpPlant::KelpPlant().ID: return 8435; case Ladder::Ladder(eBlockFace::BLOCK_FACE_ZM).ID: return 3172; case Ladder::Ladder(eBlockFace::BLOCK_FACE_ZP).ID: return 3174; case Ladder::Ladder(eBlockFace::BLOCK_FACE_XM).ID: return 3176; case Ladder::Ladder(eBlockFace::BLOCK_FACE_XP).ID: return 3178; case LapisBlock::LapisBlock().ID: return 232; case LapisOre::LapisOre().ID: return 231; case LargeFern::LargeFern(LargeFern::Half::Upper).ID: return 6852; case LargeFern::LargeFern(LargeFern::Half::Lower).ID: return 6853; case Lava::Lava(0).ID: return 50; case Lava::Lava(1).ID: return 51; case Lava::Lava(2).ID: return 52; case Lava::Lava(3).ID: return 53; case Lava::Lava(4).ID: return 54; case Lava::Lava(5).ID: return 55; case Lava::Lava(6).ID: return 56; case Lava::Lava(7).ID: return 57; case Lava::Lava(8).ID: return 58; case Lava::Lava(9).ID: return 59; case Lava::Lava(10).ID: return 60; case Lava::Lava(11).ID: return 61; case Lava::Lava(12).ID: return 62; case Lava::Lava(13).ID: return 63; case Lava::Lava(14).ID: return 64; case Lava::Lava(15).ID: return 65; case Lever::Lever(Lever::Face::Floor, eBlockFace::BLOCK_FACE_ZM, true).ID: return 3277; case Lever::Lever(Lever::Face::Floor, eBlockFace::BLOCK_FACE_ZM, false).ID: return 3278; case Lever::Lever(Lever::Face::Floor, eBlockFace::BLOCK_FACE_ZP, true).ID: return 3279; case Lever::Lever(Lever::Face::Floor, eBlockFace::BLOCK_FACE_ZP, false).ID: return 3280; case Lever::Lever(Lever::Face::Floor, eBlockFace::BLOCK_FACE_XM, true).ID: return 3281; case Lever::Lever(Lever::Face::Floor, eBlockFace::BLOCK_FACE_XM, false).ID: return 3282; case Lever::Lever(Lever::Face::Floor, eBlockFace::BLOCK_FACE_XP, true).ID: return 3283; case Lever::Lever(Lever::Face::Floor, eBlockFace::BLOCK_FACE_XP, false).ID: return 3284; case Lever::Lever(Lever::Face::Wall, eBlockFace::BLOCK_FACE_ZM, true).ID: return 3285; case Lever::Lever(Lever::Face::Wall, eBlockFace::BLOCK_FACE_ZM, false).ID: return 3286; case Lever::Lever(Lever::Face::Wall, eBlockFace::BLOCK_FACE_ZP, true).ID: return 3287; case Lever::Lever(Lever::Face::Wall, eBlockFace::BLOCK_FACE_ZP, false).ID: return 3288; case Lever::Lever(Lever::Face::Wall, eBlockFace::BLOCK_FACE_XM, true).ID: return 3289; case Lever::Lever(Lever::Face::Wall, eBlockFace::BLOCK_FACE_XM, false).ID: return 3290; case Lever::Lever(Lever::Face::Wall, eBlockFace::BLOCK_FACE_XP, true).ID: return 3291; case Lever::Lever(Lever::Face::Wall, eBlockFace::BLOCK_FACE_XP, false).ID: return 3292; case Lever::Lever(Lever::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, true).ID: return 3293; case Lever::Lever(Lever::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, false).ID: return 3294; case Lever::Lever(Lever::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, true).ID: return 3295; case Lever::Lever(Lever::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, false).ID: return 3296; case Lever::Lever(Lever::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, true).ID: return 3297; case Lever::Lever(Lever::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, false).ID: return 3298; case Lever::Lever(Lever::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, true).ID: return 3299; case Lever::Lever(Lever::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, false).ID: return 3300; case LightBlueBanner::LightBlueBanner(0).ID: return 6902; case LightBlueBanner::LightBlueBanner(1).ID: return 6903; case LightBlueBanner::LightBlueBanner(2).ID: return 6904; case LightBlueBanner::LightBlueBanner(3).ID: return 6905; case LightBlueBanner::LightBlueBanner(4).ID: return 6906; case LightBlueBanner::LightBlueBanner(5).ID: return 6907; case LightBlueBanner::LightBlueBanner(6).ID: return 6908; case LightBlueBanner::LightBlueBanner(7).ID: return 6909; case LightBlueBanner::LightBlueBanner(8).ID: return 6910; case LightBlueBanner::LightBlueBanner(9).ID: return 6911; case LightBlueBanner::LightBlueBanner(10).ID: return 6912; case LightBlueBanner::LightBlueBanner(11).ID: return 6913; case LightBlueBanner::LightBlueBanner(12).ID: return 6914; case LightBlueBanner::LightBlueBanner(13).ID: return 6915; case LightBlueBanner::LightBlueBanner(14).ID: return 6916; case LightBlueBanner::LightBlueBanner(15).ID: return 6917; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_ZM, true, LightBlueBed::Part::Head).ID: return 796; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_ZM, true, LightBlueBed::Part::Foot).ID: return 797; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_ZM, false, LightBlueBed::Part::Head).ID: return 798; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_ZM, false, LightBlueBed::Part::Foot).ID: return 799; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_ZP, true, LightBlueBed::Part::Head).ID: return 800; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_ZP, true, LightBlueBed::Part::Foot).ID: return 801; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_ZP, false, LightBlueBed::Part::Head).ID: return 802; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_ZP, false, LightBlueBed::Part::Foot).ID: return 803; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_XM, true, LightBlueBed::Part::Head).ID: return 804; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_XM, true, LightBlueBed::Part::Foot).ID: return 805; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_XM, false, LightBlueBed::Part::Head).ID: return 806; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_XM, false, LightBlueBed::Part::Foot).ID: return 807; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_XP, true, LightBlueBed::Part::Head).ID: return 808; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_XP, true, LightBlueBed::Part::Foot).ID: return 809; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_XP, false, LightBlueBed::Part::Head).ID: return 810; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_XP, false, LightBlueBed::Part::Foot).ID: return 811; case LightBlueCarpet::LightBlueCarpet().ID: return 6826; case LightBlueConcrete::LightBlueConcrete().ID: return 8380; case LightBlueConcretePowder::LightBlueConcretePowder().ID: return 8396; case LightBlueGlazedTerracotta::LightBlueGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 8325; case LightBlueGlazedTerracotta::LightBlueGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 8326; case LightBlueGlazedTerracotta::LightBlueGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 8327; case LightBlueGlazedTerracotta::LightBlueGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 8328; case LightBlueShulkerBox::LightBlueShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 8235; case LightBlueShulkerBox::LightBlueShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 8236; case LightBlueShulkerBox::LightBlueShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 8237; case LightBlueShulkerBox::LightBlueShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 8238; case LightBlueShulkerBox::LightBlueShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 8239; case LightBlueShulkerBox::LightBlueShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 8240; case LightBlueStainedGlass::LightBlueStainedGlass().ID: return 3580; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(true, true, true, true).ID: return 5918; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(true, true, true, false).ID: return 5919; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(true, true, false, true).ID: return 5922; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(true, true, false, false).ID: return 5923; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(true, false, true, true).ID: return 5926; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(true, false, true, false).ID: return 5927; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(true, false, false, true).ID: return 5930; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(true, false, false, false).ID: return 5931; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(false, true, true, true).ID: return 5934; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(false, true, true, false).ID: return 5935; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(false, true, false, true).ID: return 5938; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(false, true, false, false).ID: return 5939; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(false, false, true, true).ID: return 5942; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(false, false, true, false).ID: return 5943; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(false, false, false, true).ID: return 5946; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(false, false, false, false).ID: return 5947; case LightBlueTerracotta::LightBlueTerracotta().ID: return 5807; case LightBlueWallBanner::LightBlueWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 7122; case LightBlueWallBanner::LightBlueWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 7123; case LightBlueWallBanner::LightBlueWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 7124; case LightBlueWallBanner::LightBlueWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 7125; case LightBlueWool::LightBlueWool().ID: return 1086; case LightGrayBanner::LightGrayBanner(0).ID: return 6982; case LightGrayBanner::LightGrayBanner(1).ID: return 6983; case LightGrayBanner::LightGrayBanner(2).ID: return 6984; case LightGrayBanner::LightGrayBanner(3).ID: return 6985; case LightGrayBanner::LightGrayBanner(4).ID: return 6986; case LightGrayBanner::LightGrayBanner(5).ID: return 6987; case LightGrayBanner::LightGrayBanner(6).ID: return 6988; case LightGrayBanner::LightGrayBanner(7).ID: return 6989; case LightGrayBanner::LightGrayBanner(8).ID: return 6990; case LightGrayBanner::LightGrayBanner(9).ID: return 6991; case LightGrayBanner::LightGrayBanner(10).ID: return 6992; case LightGrayBanner::LightGrayBanner(11).ID: return 6993; case LightGrayBanner::LightGrayBanner(12).ID: return 6994; case LightGrayBanner::LightGrayBanner(13).ID: return 6995; case LightGrayBanner::LightGrayBanner(14).ID: return 6996; case LightGrayBanner::LightGrayBanner(15).ID: return 6997; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_ZM, true, LightGrayBed::Part::Head).ID: return 876; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_ZM, true, LightGrayBed::Part::Foot).ID: return 877; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_ZM, false, LightGrayBed::Part::Head).ID: return 878; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_ZM, false, LightGrayBed::Part::Foot).ID: return 879; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_ZP, true, LightGrayBed::Part::Head).ID: return 880; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_ZP, true, LightGrayBed::Part::Foot).ID: return 881; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_ZP, false, LightGrayBed::Part::Head).ID: return 882; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_ZP, false, LightGrayBed::Part::Foot).ID: return 883; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_XM, true, LightGrayBed::Part::Head).ID: return 884; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_XM, true, LightGrayBed::Part::Foot).ID: return 885; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_XM, false, LightGrayBed::Part::Head).ID: return 886; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_XM, false, LightGrayBed::Part::Foot).ID: return 887; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_XP, true, LightGrayBed::Part::Head).ID: return 888; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_XP, true, LightGrayBed::Part::Foot).ID: return 889; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_XP, false, LightGrayBed::Part::Head).ID: return 890; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_XP, false, LightGrayBed::Part::Foot).ID: return 891; case LightGrayCarpet::LightGrayCarpet().ID: return 6831; case LightGrayConcrete::LightGrayConcrete().ID: return 8385; case LightGrayConcretePowder::LightGrayConcretePowder().ID: return 8401; case LightGrayGlazedTerracotta::LightGrayGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 8345; case LightGrayGlazedTerracotta::LightGrayGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 8346; case LightGrayGlazedTerracotta::LightGrayGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 8347; case LightGrayGlazedTerracotta::LightGrayGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 8348; case LightGrayShulkerBox::LightGrayShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 8265; case LightGrayShulkerBox::LightGrayShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 8266; case LightGrayShulkerBox::LightGrayShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 8267; case LightGrayShulkerBox::LightGrayShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 8268; case LightGrayShulkerBox::LightGrayShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 8269; case LightGrayShulkerBox::LightGrayShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 8270; case LightGrayStainedGlass::LightGrayStainedGlass().ID: return 3585; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(true, true, true, true).ID: return 6078; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(true, true, true, false).ID: return 6079; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(true, true, false, true).ID: return 6082; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(true, true, false, false).ID: return 6083; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(true, false, true, true).ID: return 6086; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(true, false, true, false).ID: return 6087; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(true, false, false, true).ID: return 6090; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(true, false, false, false).ID: return 6091; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(false, true, true, true).ID: return 6094; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(false, true, true, false).ID: return 6095; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(false, true, false, true).ID: return 6098; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(false, true, false, false).ID: return 6099; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(false, false, true, true).ID: return 6102; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(false, false, true, false).ID: return 6103; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(false, false, false, true).ID: return 6106; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(false, false, false, false).ID: return 6107; case LightGrayTerracotta::LightGrayTerracotta().ID: return 5812; case LightGrayWallBanner::LightGrayWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 7142; case LightGrayWallBanner::LightGrayWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 7143; case LightGrayWallBanner::LightGrayWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 7144; case LightGrayWallBanner::LightGrayWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 7145; case LightGrayWool::LightGrayWool().ID: return 1091; case LightWeightedPressurePlate::LightWeightedPressurePlate(0).ID: return 5603; case LightWeightedPressurePlate::LightWeightedPressurePlate(1).ID: return 5604; case LightWeightedPressurePlate::LightWeightedPressurePlate(2).ID: return 5605; case LightWeightedPressurePlate::LightWeightedPressurePlate(3).ID: return 5606; case LightWeightedPressurePlate::LightWeightedPressurePlate(4).ID: return 5607; case LightWeightedPressurePlate::LightWeightedPressurePlate(5).ID: return 5608; case LightWeightedPressurePlate::LightWeightedPressurePlate(6).ID: return 5609; case LightWeightedPressurePlate::LightWeightedPressurePlate(7).ID: return 5610; case LightWeightedPressurePlate::LightWeightedPressurePlate(8).ID: return 5611; case LightWeightedPressurePlate::LightWeightedPressurePlate(9).ID: return 5612; case LightWeightedPressurePlate::LightWeightedPressurePlate(10).ID: return 5613; case LightWeightedPressurePlate::LightWeightedPressurePlate(11).ID: return 5614; case LightWeightedPressurePlate::LightWeightedPressurePlate(12).ID: return 5615; case LightWeightedPressurePlate::LightWeightedPressurePlate(13).ID: return 5616; case LightWeightedPressurePlate::LightWeightedPressurePlate(14).ID: return 5617; case LightWeightedPressurePlate::LightWeightedPressurePlate(15).ID: return 5618; case Lilac::Lilac(Lilac::Half::Upper).ID: return 6844; case Lilac::Lilac(Lilac::Half::Lower).ID: return 6845; case LilyPad::LilyPad().ID: return 4494; case LimeBanner::LimeBanner(0).ID: return 6934; case LimeBanner::LimeBanner(1).ID: return 6935; case LimeBanner::LimeBanner(2).ID: return 6936; case LimeBanner::LimeBanner(3).ID: return 6937; case LimeBanner::LimeBanner(4).ID: return 6938; case LimeBanner::LimeBanner(5).ID: return 6939; case LimeBanner::LimeBanner(6).ID: return 6940; case LimeBanner::LimeBanner(7).ID: return 6941; case LimeBanner::LimeBanner(8).ID: return 6942; case LimeBanner::LimeBanner(9).ID: return 6943; case LimeBanner::LimeBanner(10).ID: return 6944; case LimeBanner::LimeBanner(11).ID: return 6945; case LimeBanner::LimeBanner(12).ID: return 6946; case LimeBanner::LimeBanner(13).ID: return 6947; case LimeBanner::LimeBanner(14).ID: return 6948; case LimeBanner::LimeBanner(15).ID: return 6949; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_ZM, true, LimeBed::Part::Head).ID: return 828; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_ZM, true, LimeBed::Part::Foot).ID: return 829; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_ZM, false, LimeBed::Part::Head).ID: return 830; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_ZM, false, LimeBed::Part::Foot).ID: return 831; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_ZP, true, LimeBed::Part::Head).ID: return 832; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_ZP, true, LimeBed::Part::Foot).ID: return 833; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_ZP, false, LimeBed::Part::Head).ID: return 834; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_ZP, false, LimeBed::Part::Foot).ID: return 835; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_XM, true, LimeBed::Part::Head).ID: return 836; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_XM, true, LimeBed::Part::Foot).ID: return 837; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_XM, false, LimeBed::Part::Head).ID: return 838; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_XM, false, LimeBed::Part::Foot).ID: return 839; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_XP, true, LimeBed::Part::Head).ID: return 840; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_XP, true, LimeBed::Part::Foot).ID: return 841; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_XP, false, LimeBed::Part::Head).ID: return 842; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_XP, false, LimeBed::Part::Foot).ID: return 843; case LimeCarpet::LimeCarpet().ID: return 6828; case LimeConcrete::LimeConcrete().ID: return 8382; case LimeConcretePowder::LimeConcretePowder().ID: return 8398; case LimeGlazedTerracotta::LimeGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 8333; case LimeGlazedTerracotta::LimeGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 8334; case LimeGlazedTerracotta::LimeGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 8335; case LimeGlazedTerracotta::LimeGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 8336; case LimeShulkerBox::LimeShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 8247; case LimeShulkerBox::LimeShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 8248; case LimeShulkerBox::LimeShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 8249; case LimeShulkerBox::LimeShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 8250; case LimeShulkerBox::LimeShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 8251; case LimeShulkerBox::LimeShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 8252; case LimeStainedGlass::LimeStainedGlass().ID: return 3582; case LimeStainedGlassPane::LimeStainedGlassPane(true, true, true, true).ID: return 5982; case LimeStainedGlassPane::LimeStainedGlassPane(true, true, true, false).ID: return 5983; case LimeStainedGlassPane::LimeStainedGlassPane(true, true, false, true).ID: return 5986; case LimeStainedGlassPane::LimeStainedGlassPane(true, true, false, false).ID: return 5987; case LimeStainedGlassPane::LimeStainedGlassPane(true, false, true, true).ID: return 5990; case LimeStainedGlassPane::LimeStainedGlassPane(true, false, true, false).ID: return 5991; case LimeStainedGlassPane::LimeStainedGlassPane(true, false, false, true).ID: return 5994; case LimeStainedGlassPane::LimeStainedGlassPane(true, false, false, false).ID: return 5995; case LimeStainedGlassPane::LimeStainedGlassPane(false, true, true, true).ID: return 5998; case LimeStainedGlassPane::LimeStainedGlassPane(false, true, true, false).ID: return 5999; case LimeStainedGlassPane::LimeStainedGlassPane(false, true, false, true).ID: return 6002; case LimeStainedGlassPane::LimeStainedGlassPane(false, true, false, false).ID: return 6003; case LimeStainedGlassPane::LimeStainedGlassPane(false, false, true, true).ID: return 6006; case LimeStainedGlassPane::LimeStainedGlassPane(false, false, true, false).ID: return 6007; case LimeStainedGlassPane::LimeStainedGlassPane(false, false, false, true).ID: return 6010; case LimeStainedGlassPane::LimeStainedGlassPane(false, false, false, false).ID: return 6011; case LimeTerracotta::LimeTerracotta().ID: return 5809; case LimeWallBanner::LimeWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 7130; case LimeWallBanner::LimeWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 7131; case LimeWallBanner::LimeWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 7132; case LimeWallBanner::LimeWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 7133; case LimeWool::LimeWool().ID: return 1088; case MagentaBanner::MagentaBanner(0).ID: return 6886; case MagentaBanner::MagentaBanner(1).ID: return 6887; case MagentaBanner::MagentaBanner(2).ID: return 6888; case MagentaBanner::MagentaBanner(3).ID: return 6889; case MagentaBanner::MagentaBanner(4).ID: return 6890; case MagentaBanner::MagentaBanner(5).ID: return 6891; case MagentaBanner::MagentaBanner(6).ID: return 6892; case MagentaBanner::MagentaBanner(7).ID: return 6893; case MagentaBanner::MagentaBanner(8).ID: return 6894; case MagentaBanner::MagentaBanner(9).ID: return 6895; case MagentaBanner::MagentaBanner(10).ID: return 6896; case MagentaBanner::MagentaBanner(11).ID: return 6897; case MagentaBanner::MagentaBanner(12).ID: return 6898; case MagentaBanner::MagentaBanner(13).ID: return 6899; case MagentaBanner::MagentaBanner(14).ID: return 6900; case MagentaBanner::MagentaBanner(15).ID: return 6901; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_ZM, true, MagentaBed::Part::Head).ID: return 780; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_ZM, true, MagentaBed::Part::Foot).ID: return 781; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_ZM, false, MagentaBed::Part::Head).ID: return 782; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_ZM, false, MagentaBed::Part::Foot).ID: return 783; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_ZP, true, MagentaBed::Part::Head).ID: return 784; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_ZP, true, MagentaBed::Part::Foot).ID: return 785; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_ZP, false, MagentaBed::Part::Head).ID: return 786; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_ZP, false, MagentaBed::Part::Foot).ID: return 787; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_XM, true, MagentaBed::Part::Head).ID: return 788; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_XM, true, MagentaBed::Part::Foot).ID: return 789; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_XM, false, MagentaBed::Part::Head).ID: return 790; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_XM, false, MagentaBed::Part::Foot).ID: return 791; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_XP, true, MagentaBed::Part::Head).ID: return 792; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_XP, true, MagentaBed::Part::Foot).ID: return 793; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_XP, false, MagentaBed::Part::Head).ID: return 794; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_XP, false, MagentaBed::Part::Foot).ID: return 795; case MagentaCarpet::MagentaCarpet().ID: return 6825; case MagentaConcrete::MagentaConcrete().ID: return 8379; case MagentaConcretePowder::MagentaConcretePowder().ID: return 8395; case MagentaGlazedTerracotta::MagentaGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 8321; case MagentaGlazedTerracotta::MagentaGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 8322; case MagentaGlazedTerracotta::MagentaGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 8323; case MagentaGlazedTerracotta::MagentaGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 8324; case MagentaShulkerBox::MagentaShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 8229; case MagentaShulkerBox::MagentaShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 8230; case MagentaShulkerBox::MagentaShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 8231; case MagentaShulkerBox::MagentaShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 8232; case MagentaShulkerBox::MagentaShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 8233; case MagentaShulkerBox::MagentaShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 8234; case MagentaStainedGlass::MagentaStainedGlass().ID: return 3579; case MagentaStainedGlassPane::MagentaStainedGlassPane(true, true, true, true).ID: return 5886; case MagentaStainedGlassPane::MagentaStainedGlassPane(true, true, true, false).ID: return 5887; case MagentaStainedGlassPane::MagentaStainedGlassPane(true, true, false, true).ID: return 5890; case MagentaStainedGlassPane::MagentaStainedGlassPane(true, true, false, false).ID: return 5891; case MagentaStainedGlassPane::MagentaStainedGlassPane(true, false, true, true).ID: return 5894; case MagentaStainedGlassPane::MagentaStainedGlassPane(true, false, true, false).ID: return 5895; case MagentaStainedGlassPane::MagentaStainedGlassPane(true, false, false, true).ID: return 5898; case MagentaStainedGlassPane::MagentaStainedGlassPane(true, false, false, false).ID: return 5899; case MagentaStainedGlassPane::MagentaStainedGlassPane(false, true, true, true).ID: return 5902; case MagentaStainedGlassPane::MagentaStainedGlassPane(false, true, true, false).ID: return 5903; case MagentaStainedGlassPane::MagentaStainedGlassPane(false, true, false, true).ID: return 5906; case MagentaStainedGlassPane::MagentaStainedGlassPane(false, true, false, false).ID: return 5907; case MagentaStainedGlassPane::MagentaStainedGlassPane(false, false, true, true).ID: return 5910; case MagentaStainedGlassPane::MagentaStainedGlassPane(false, false, true, false).ID: return 5911; case MagentaStainedGlassPane::MagentaStainedGlassPane(false, false, false, true).ID: return 5914; case MagentaStainedGlassPane::MagentaStainedGlassPane(false, false, false, false).ID: return 5915; case MagentaTerracotta::MagentaTerracotta().ID: return 5806; case MagentaWallBanner::MagentaWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 7118; case MagentaWallBanner::MagentaWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 7119; case MagentaWallBanner::MagentaWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 7120; case MagentaWallBanner::MagentaWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 7121; case MagentaWool::MagentaWool().ID: return 1085; case MagmaBlock::MagmaBlock().ID: return 8192; case Melon::Melon().ID: return 4243; case MelonStem::MelonStem(0).ID: return 4260; case MelonStem::MelonStem(1).ID: return 4261; case MelonStem::MelonStem(2).ID: return 4262; case MelonStem::MelonStem(3).ID: return 4263; case MelonStem::MelonStem(4).ID: return 4264; case MelonStem::MelonStem(5).ID: return 4265; case MelonStem::MelonStem(6).ID: return 4266; case MelonStem::MelonStem(7).ID: return 4267; case MossyCobblestone::MossyCobblestone().ID: return 1128; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::Low, true, MossyCobblestoneWall::West::Low).ID: return 5203; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::Low, true, MossyCobblestoneWall::West::None).ID: return 5204; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::Low, false, MossyCobblestoneWall::West::Low).ID: return 5207; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::Low, false, MossyCobblestoneWall::West::None).ID: return 5208; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::None, true, MossyCobblestoneWall::West::Low).ID: return 5211; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::None, true, MossyCobblestoneWall::West::None).ID: return 5212; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::None, false, MossyCobblestoneWall::West::Low).ID: return 5215; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::None, false, MossyCobblestoneWall::West::None).ID: return 5216; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::Low, true, MossyCobblestoneWall::West::Low).ID: return 5219; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::Low, true, MossyCobblestoneWall::West::None).ID: return 5220; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::Low, false, MossyCobblestoneWall::West::Low).ID: return 5223; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::Low, false, MossyCobblestoneWall::West::None).ID: return 5224; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::None, true, MossyCobblestoneWall::West::Low).ID: return 5227; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::None, true, MossyCobblestoneWall::West::None).ID: return 5228; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::None, false, MossyCobblestoneWall::West::Low).ID: return 5231; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::None, false, MossyCobblestoneWall::West::None).ID: return 5232; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::Low, true, MossyCobblestoneWall::West::Low).ID: return 5235; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::Low, true, MossyCobblestoneWall::West::None).ID: return 5236; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::Low, false, MossyCobblestoneWall::West::Low).ID: return 5239; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::Low, false, MossyCobblestoneWall::West::None).ID: return 5240; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::None, true, MossyCobblestoneWall::West::Low).ID: return 5243; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::None, true, MossyCobblestoneWall::West::None).ID: return 5244; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::None, false, MossyCobblestoneWall::West::Low).ID: return 5247; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::None, false, MossyCobblestoneWall::West::None).ID: return 5248; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::Low, true, MossyCobblestoneWall::West::Low).ID: return 5251; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::Low, true, MossyCobblestoneWall::West::None).ID: return 5252; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::Low, false, MossyCobblestoneWall::West::Low).ID: return 5255; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::Low, false, MossyCobblestoneWall::West::None).ID: return 5256; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::None, true, MossyCobblestoneWall::West::Low).ID: return 5259; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::None, true, MossyCobblestoneWall::West::None).ID: return 5260; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::None, false, MossyCobblestoneWall::West::Low).ID: return 5263; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::None, false, MossyCobblestoneWall::West::None).ID: return 5264; case MossyStoneBricks::MossyStoneBricks().ID: return 3984; case MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_ZM, MovingPiston::Type::Normal).ID: return 1099; case MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_ZM, MovingPiston::Type::Sticky).ID: return 1100; case MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_XP, MovingPiston::Type::Normal).ID: return 1101; case MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_XP, MovingPiston::Type::Sticky).ID: return 1102; case MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_ZP, MovingPiston::Type::Normal).ID: return 1103; case MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_ZP, MovingPiston::Type::Sticky).ID: return 1104; case MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_XM, MovingPiston::Type::Normal).ID: return 1105; case MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_XM, MovingPiston::Type::Sticky).ID: return 1106; case MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_YP, MovingPiston::Type::Normal).ID: return 1107; case MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_YP, MovingPiston::Type::Sticky).ID: return 1108; case MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_YM, MovingPiston::Type::Normal).ID: return 1109; case MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_YM, MovingPiston::Type::Sticky).ID: return 1110; case MushroomStem::MushroomStem(true, true, true, true, true, true).ID: return 4115; case MushroomStem::MushroomStem(true, true, true, true, true, false).ID: return 4116; case MushroomStem::MushroomStem(true, true, true, true, false, true).ID: return 4117; case MushroomStem::MushroomStem(true, true, true, true, false, false).ID: return 4118; case MushroomStem::MushroomStem(true, true, true, false, true, true).ID: return 4119; case MushroomStem::MushroomStem(true, true, true, false, true, false).ID: return 4120; case MushroomStem::MushroomStem(true, true, true, false, false, true).ID: return 4121; case MushroomStem::MushroomStem(true, true, true, false, false, false).ID: return 4122; case MushroomStem::MushroomStem(true, true, false, true, true, true).ID: return 4123; case MushroomStem::MushroomStem(true, true, false, true, true, false).ID: return 4124; case MushroomStem::MushroomStem(true, true, false, true, false, true).ID: return 4125; case MushroomStem::MushroomStem(true, true, false, true, false, false).ID: return 4126; case MushroomStem::MushroomStem(true, true, false, false, true, true).ID: return 4127; case MushroomStem::MushroomStem(true, true, false, false, true, false).ID: return 4128; case MushroomStem::MushroomStem(true, true, false, false, false, true).ID: return 4129; case MushroomStem::MushroomStem(true, true, false, false, false, false).ID: return 4130; case MushroomStem::MushroomStem(true, false, true, true, true, true).ID: return 4131; case MushroomStem::MushroomStem(true, false, true, true, true, false).ID: return 4132; case MushroomStem::MushroomStem(true, false, true, true, false, true).ID: return 4133; case MushroomStem::MushroomStem(true, false, true, true, false, false).ID: return 4134; case MushroomStem::MushroomStem(true, false, true, false, true, true).ID: return 4135; case MushroomStem::MushroomStem(true, false, true, false, true, false).ID: return 4136; case MushroomStem::MushroomStem(true, false, true, false, false, true).ID: return 4137; case MushroomStem::MushroomStem(true, false, true, false, false, false).ID: return 4138; case MushroomStem::MushroomStem(true, false, false, true, true, true).ID: return 4139; case MushroomStem::MushroomStem(true, false, false, true, true, false).ID: return 4140; case MushroomStem::MushroomStem(true, false, false, true, false, true).ID: return 4141; case MushroomStem::MushroomStem(true, false, false, true, false, false).ID: return 4142; case MushroomStem::MushroomStem(true, false, false, false, true, true).ID: return 4143; case MushroomStem::MushroomStem(true, false, false, false, true, false).ID: return 4144; case MushroomStem::MushroomStem(true, false, false, false, false, true).ID: return 4145; case MushroomStem::MushroomStem(true, false, false, false, false, false).ID: return 4146; case MushroomStem::MushroomStem(false, true, true, true, true, true).ID: return 4147; case MushroomStem::MushroomStem(false, true, true, true, true, false).ID: return 4148; case MushroomStem::MushroomStem(false, true, true, true, false, true).ID: return 4149; case MushroomStem::MushroomStem(false, true, true, true, false, false).ID: return 4150; case MushroomStem::MushroomStem(false, true, true, false, true, true).ID: return 4151; case MushroomStem::MushroomStem(false, true, true, false, true, false).ID: return 4152; case MushroomStem::MushroomStem(false, true, true, false, false, true).ID: return 4153; case MushroomStem::MushroomStem(false, true, true, false, false, false).ID: return 4154; case MushroomStem::MushroomStem(false, true, false, true, true, true).ID: return 4155; case MushroomStem::MushroomStem(false, true, false, true, true, false).ID: return 4156; case MushroomStem::MushroomStem(false, true, false, true, false, true).ID: return 4157; case MushroomStem::MushroomStem(false, true, false, true, false, false).ID: return 4158; case MushroomStem::MushroomStem(false, true, false, false, true, true).ID: return 4159; case MushroomStem::MushroomStem(false, true, false, false, true, false).ID: return 4160; case MushroomStem::MushroomStem(false, true, false, false, false, true).ID: return 4161; case MushroomStem::MushroomStem(false, true, false, false, false, false).ID: return 4162; case MushroomStem::MushroomStem(false, false, true, true, true, true).ID: return 4163; case MushroomStem::MushroomStem(false, false, true, true, true, false).ID: return 4164; case MushroomStem::MushroomStem(false, false, true, true, false, true).ID: return 4165; case MushroomStem::MushroomStem(false, false, true, true, false, false).ID: return 4166; case MushroomStem::MushroomStem(false, false, true, false, true, true).ID: return 4167; case MushroomStem::MushroomStem(false, false, true, false, true, false).ID: return 4168; case MushroomStem::MushroomStem(false, false, true, false, false, true).ID: return 4169; case MushroomStem::MushroomStem(false, false, true, false, false, false).ID: return 4170; case MushroomStem::MushroomStem(false, false, false, true, true, true).ID: return 4171; case MushroomStem::MushroomStem(false, false, false, true, true, false).ID: return 4172; case MushroomStem::MushroomStem(false, false, false, true, false, true).ID: return 4173; case MushroomStem::MushroomStem(false, false, false, true, false, false).ID: return 4174; case MushroomStem::MushroomStem(false, false, false, false, true, true).ID: return 4175; case MushroomStem::MushroomStem(false, false, false, false, true, false).ID: return 4176; case MushroomStem::MushroomStem(false, false, false, false, false, true).ID: return 4177; case MushroomStem::MushroomStem(false, false, false, false, false, false).ID: return 4178; case Mycelium::Mycelium(true).ID: return 4492; case Mycelium::Mycelium(false).ID: return 4493; case NetherBrickFence::NetherBrickFence(true, true, true, true).ID: return 4498; case NetherBrickFence::NetherBrickFence(true, true, true, false).ID: return 4499; case NetherBrickFence::NetherBrickFence(true, true, false, true).ID: return 4502; case NetherBrickFence::NetherBrickFence(true, true, false, false).ID: return 4503; case NetherBrickFence::NetherBrickFence(true, false, true, true).ID: return 4506; case NetherBrickFence::NetherBrickFence(true, false, true, false).ID: return 4507; case NetherBrickFence::NetherBrickFence(true, false, false, true).ID: return 4510; case NetherBrickFence::NetherBrickFence(true, false, false, false).ID: return 4511; case NetherBrickFence::NetherBrickFence(false, true, true, true).ID: return 4514; case NetherBrickFence::NetherBrickFence(false, true, true, false).ID: return 4515; case NetherBrickFence::NetherBrickFence(false, true, false, true).ID: return 4518; case NetherBrickFence::NetherBrickFence(false, true, false, false).ID: return 4519; case NetherBrickFence::NetherBrickFence(false, false, true, true).ID: return 4522; case NetherBrickFence::NetherBrickFence(false, false, true, false).ID: return 4523; case NetherBrickFence::NetherBrickFence(false, false, false, true).ID: return 4526; case NetherBrickFence::NetherBrickFence(false, false, false, false).ID: return 4527; case NetherBrickSlab::NetherBrickSlab(NetherBrickSlab::Type::Top).ID: return 7330; case NetherBrickSlab::NetherBrickSlab(NetherBrickSlab::Type::Bottom).ID: return 7332; case NetherBrickSlab::NetherBrickSlab(NetherBrickSlab::Type::Double).ID: return 7334; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::Straight).ID: return 4529; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::InnerLeft).ID: return 4531; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::InnerRight).ID: return 4533; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::OuterLeft).ID: return 4535; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::OuterRight).ID: return 4537; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::Straight).ID: return 4539; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::InnerLeft).ID: return 4541; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::InnerRight).ID: return 4543; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::OuterLeft).ID: return 4545; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::OuterRight).ID: return 4547; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::Straight).ID: return 4549; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::InnerLeft).ID: return 4551; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::InnerRight).ID: return 4553; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::OuterLeft).ID: return 4555; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::OuterRight).ID: return 4557; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::Straight).ID: return 4559; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::InnerLeft).ID: return 4561; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::InnerRight).ID: return 4563; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::OuterLeft).ID: return 4565; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::OuterRight).ID: return 4567; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XM, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::Straight).ID: return 4569; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XM, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::InnerLeft).ID: return 4571; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XM, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::InnerRight).ID: return 4573; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XM, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::OuterLeft).ID: return 4575; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XM, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::OuterRight).ID: return 4577; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XM, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::Straight).ID: return 4579; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XM, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::InnerLeft).ID: return 4581; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XM, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::InnerRight).ID: return 4583; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XM, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::OuterLeft).ID: return 4585; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XM, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::OuterRight).ID: return 4587; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XP, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::Straight).ID: return 4589; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XP, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::InnerLeft).ID: return 4591; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XP, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::InnerRight).ID: return 4593; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XP, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::OuterLeft).ID: return 4595; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XP, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::OuterRight).ID: return 4597; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XP, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::Straight).ID: return 4599; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XP, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::InnerLeft).ID: return 4601; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XP, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::InnerRight).ID: return 4603; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XP, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::OuterLeft).ID: return 4605; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XP, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::OuterRight).ID: return 4607; case NetherBricks::NetherBricks().ID: return 4495; case NetherPortal::NetherPortal(NetherPortal::Axis::X).ID: return 3496; case NetherPortal::NetherPortal(NetherPortal::Axis::Z).ID: return 3497; case NetherQuartzOre::NetherQuartzOre().ID: return 5684; case NetherWart::NetherWart(0).ID: return 4608; case NetherWart::NetherWart(1).ID: return 4609; case NetherWart::NetherWart(2).ID: return 4610; case NetherWart::NetherWart(3).ID: return 4611; case NetherWartBlock::NetherWartBlock().ID: return 8193; case Netherrack::Netherrack().ID: return 3493; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 0, true).ID: return 248; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 0, false).ID: return 249; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 1, true).ID: return 250; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 1, false).ID: return 251; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 2, true).ID: return 252; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 2, false).ID: return 253; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 3, true).ID: return 254; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 3, false).ID: return 255; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 4, true).ID: return 256; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 4, false).ID: return 257; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 5, true).ID: return 258; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 5, false).ID: return 259; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 6, true).ID: return 260; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 6, false).ID: return 261; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 7, true).ID: return 262; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 7, false).ID: return 263; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 8, true).ID: return 264; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 8, false).ID: return 265; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 9, true).ID: return 266; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 9, false).ID: return 267; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 10, true).ID: return 268; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 10, false).ID: return 269; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 11, true).ID: return 270; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 11, false).ID: return 271; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 12, true).ID: return 272; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 12, false).ID: return 273; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 13, true).ID: return 274; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 13, false).ID: return 275; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 14, true).ID: return 276; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 14, false).ID: return 277; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 15, true).ID: return 278; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 15, false).ID: return 279; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 16, true).ID: return 280; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 16, false).ID: return 281; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 17, true).ID: return 282; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 17, false).ID: return 283; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 18, true).ID: return 284; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 18, false).ID: return 285; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 19, true).ID: return 286; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 19, false).ID: return 287; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 20, true).ID: return 288; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 20, false).ID: return 289; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 21, true).ID: return 290; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 21, false).ID: return 291; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 22, true).ID: return 292; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 22, false).ID: return 293; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 23, true).ID: return 294; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 23, false).ID: return 295; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 24, true).ID: return 296; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 24, false).ID: return 297; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 0, true).ID: return 298; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 0, false).ID: return 299; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 1, true).ID: return 300; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 1, false).ID: return 301; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 2, true).ID: return 302; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 2, false).ID: return 303; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 3, true).ID: return 304; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 3, false).ID: return 305; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 4, true).ID: return 306; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 4, false).ID: return 307; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 5, true).ID: return 308; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 5, false).ID: return 309; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 6, true).ID: return 310; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 6, false).ID: return 311; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 7, true).ID: return 312; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 7, false).ID: return 313; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 8, true).ID: return 314; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 8, false).ID: return 315; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 9, true).ID: return 316; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 9, false).ID: return 317; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 10, true).ID: return 318; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 10, false).ID: return 319; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 11, true).ID: return 320; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 11, false).ID: return 321; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 12, true).ID: return 322; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 12, false).ID: return 323; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 13, true).ID: return 324; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 13, false).ID: return 325; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 14, true).ID: return 326; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 14, false).ID: return 327; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 15, true).ID: return 328; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 15, false).ID: return 329; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 16, true).ID: return 330; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 16, false).ID: return 331; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 17, true).ID: return 332; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 17, false).ID: return 333; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 18, true).ID: return 334; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 18, false).ID: return 335; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 19, true).ID: return 336; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 19, false).ID: return 337; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 20, true).ID: return 338; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 20, false).ID: return 339; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 21, true).ID: return 340; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 21, false).ID: return 341; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 22, true).ID: return 342; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 22, false).ID: return 343; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 23, true).ID: return 344; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 23, false).ID: return 345; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 24, true).ID: return 346; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 24, false).ID: return 347; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 0, true).ID: return 348; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 0, false).ID: return 349; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 1, true).ID: return 350; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 1, false).ID: return 351; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 2, true).ID: return 352; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 2, false).ID: return 353; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 3, true).ID: return 354; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 3, false).ID: return 355; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 4, true).ID: return 356; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 4, false).ID: return 357; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 5, true).ID: return 358; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 5, false).ID: return 359; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 6, true).ID: return 360; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 6, false).ID: return 361; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 7, true).ID: return 362; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 7, false).ID: return 363; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 8, true).ID: return 364; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 8, false).ID: return 365; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 9, true).ID: return 366; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 9, false).ID: return 367; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 10, true).ID: return 368; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 10, false).ID: return 369; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 11, true).ID: return 370; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 11, false).ID: return 371; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 12, true).ID: return 372; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 12, false).ID: return 373; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 13, true).ID: return 374; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 13, false).ID: return 375; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 14, true).ID: return 376; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 14, false).ID: return 377; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 15, true).ID: return 378; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 15, false).ID: return 379; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 16, true).ID: return 380; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 16, false).ID: return 381; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 17, true).ID: return 382; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 17, false).ID: return 383; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 18, true).ID: return 384; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 18, false).ID: return 385; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 19, true).ID: return 386; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 19, false).ID: return 387; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 20, true).ID: return 388; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 20, false).ID: return 389; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 21, true).ID: return 390; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 21, false).ID: return 391; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 22, true).ID: return 392; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 22, false).ID: return 393; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 23, true).ID: return 394; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 23, false).ID: return 395; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 24, true).ID: return 396; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 24, false).ID: return 397; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 0, true).ID: return 398; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 0, false).ID: return 399; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 1, true).ID: return 400; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 1, false).ID: return 401; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 2, true).ID: return 402; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 2, false).ID: return 403; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 3, true).ID: return 404; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 3, false).ID: return 405; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 4, true).ID: return 406; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 4, false).ID: return 407; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 5, true).ID: return 408; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 5, false).ID: return 409; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 6, true).ID: return 410; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 6, false).ID: return 411; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 7, true).ID: return 412; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 7, false).ID: return 413; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 8, true).ID: return 414; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 8, false).ID: return 415; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 9, true).ID: return 416; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 9, false).ID: return 417; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 10, true).ID: return 418; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 10, false).ID: return 419; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 11, true).ID: return 420; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 11, false).ID: return 421; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 12, true).ID: return 422; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 12, false).ID: return 423; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 13, true).ID: return 424; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 13, false).ID: return 425; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 14, true).ID: return 426; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 14, false).ID: return 427; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 15, true).ID: return 428; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 15, false).ID: return 429; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 16, true).ID: return 430; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 16, false).ID: return 431; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 17, true).ID: return 432; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 17, false).ID: return 433; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 18, true).ID: return 434; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 18, false).ID: return 435; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 19, true).ID: return 436; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 19, false).ID: return 437; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 20, true).ID: return 438; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 20, false).ID: return 439; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 21, true).ID: return 440; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 21, false).ID: return 441; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 22, true).ID: return 442; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 22, false).ID: return 443; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 23, true).ID: return 444; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 23, false).ID: return 445; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 24, true).ID: return 446; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 24, false).ID: return 447; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 0, true).ID: return 448; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 0, false).ID: return 449; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 1, true).ID: return 450; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 1, false).ID: return 451; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 2, true).ID: return 452; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 2, false).ID: return 453; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 3, true).ID: return 454; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 3, false).ID: return 455; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 4, true).ID: return 456; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 4, false).ID: return 457; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 5, true).ID: return 458; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 5, false).ID: return 459; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 6, true).ID: return 460; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 6, false).ID: return 461; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 7, true).ID: return 462; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 7, false).ID: return 463; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 8, true).ID: return 464; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 8, false).ID: return 465; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 9, true).ID: return 466; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 9, false).ID: return 467; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 10, true).ID: return 468; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 10, false).ID: return 469; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 11, true).ID: return 470; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 11, false).ID: return 471; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 12, true).ID: return 472; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 12, false).ID: return 473; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 13, true).ID: return 474; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 13, false).ID: return 475; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 14, true).ID: return 476; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 14, false).ID: return 477; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 15, true).ID: return 478; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 15, false).ID: return 479; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 16, true).ID: return 480; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 16, false).ID: return 481; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 17, true).ID: return 482; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 17, false).ID: return 483; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 18, true).ID: return 484; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 18, false).ID: return 485; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 19, true).ID: return 486; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 19, false).ID: return 487; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 20, true).ID: return 488; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 20, false).ID: return 489; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 21, true).ID: return 490; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 21, false).ID: return 491; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 22, true).ID: return 492; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 22, false).ID: return 493; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 23, true).ID: return 494; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 23, false).ID: return 495; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 24, true).ID: return 496; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 24, false).ID: return 497; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 0, true).ID: return 498; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 0, false).ID: return 499; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 1, true).ID: return 500; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 1, false).ID: return 501; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 2, true).ID: return 502; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 2, false).ID: return 503; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 3, true).ID: return 504; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 3, false).ID: return 505; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 4, true).ID: return 506; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 4, false).ID: return 507; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 5, true).ID: return 508; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 5, false).ID: return 509; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 6, true).ID: return 510; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 6, false).ID: return 511; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 7, true).ID: return 512; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 7, false).ID: return 513; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 8, true).ID: return 514; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 8, false).ID: return 515; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 9, true).ID: return 516; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 9, false).ID: return 517; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 10, true).ID: return 518; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 10, false).ID: return 519; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 11, true).ID: return 520; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 11, false).ID: return 521; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 12, true).ID: return 522; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 12, false).ID: return 523; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 13, true).ID: return 524; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 13, false).ID: return 525; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 14, true).ID: return 526; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 14, false).ID: return 527; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 15, true).ID: return 528; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 15, false).ID: return 529; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 16, true).ID: return 530; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 16, false).ID: return 531; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 17, true).ID: return 532; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 17, false).ID: return 533; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 18, true).ID: return 534; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 18, false).ID: return 535; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 19, true).ID: return 536; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 19, false).ID: return 537; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 20, true).ID: return 538; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 20, false).ID: return 539; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 21, true).ID: return 540; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 21, false).ID: return 541; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 22, true).ID: return 542; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 22, false).ID: return 543; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 23, true).ID: return 544; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 23, false).ID: return 545; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 24, true).ID: return 546; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 24, false).ID: return 547; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 0, true).ID: return 548; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 0, false).ID: return 549; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 1, true).ID: return 550; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 1, false).ID: return 551; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 2, true).ID: return 552; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 2, false).ID: return 553; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 3, true).ID: return 554; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 3, false).ID: return 555; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 4, true).ID: return 556; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 4, false).ID: return 557; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 5, true).ID: return 558; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 5, false).ID: return 559; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 6, true).ID: return 560; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 6, false).ID: return 561; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 7, true).ID: return 562; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 7, false).ID: return 563; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 8, true).ID: return 564; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 8, false).ID: return 565; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 9, true).ID: return 566; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 9, false).ID: return 567; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 10, true).ID: return 568; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 10, false).ID: return 569; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 11, true).ID: return 570; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 11, false).ID: return 571; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 12, true).ID: return 572; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 12, false).ID: return 573; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 13, true).ID: return 574; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 13, false).ID: return 575; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 14, true).ID: return 576; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 14, false).ID: return 577; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 15, true).ID: return 578; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 15, false).ID: return 579; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 16, true).ID: return 580; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 16, false).ID: return 581; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 17, true).ID: return 582; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 17, false).ID: return 583; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 18, true).ID: return 584; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 18, false).ID: return 585; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 19, true).ID: return 586; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 19, false).ID: return 587; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 20, true).ID: return 588; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 20, false).ID: return 589; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 21, true).ID: return 590; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 21, false).ID: return 591; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 22, true).ID: return 592; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 22, false).ID: return 593; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 23, true).ID: return 594; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 23, false).ID: return 595; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 24, true).ID: return 596; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 24, false).ID: return 597; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 0, true).ID: return 598; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 0, false).ID: return 599; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 1, true).ID: return 600; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 1, false).ID: return 601; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 2, true).ID: return 602; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 2, false).ID: return 603; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 3, true).ID: return 604; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 3, false).ID: return 605; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 4, true).ID: return 606; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 4, false).ID: return 607; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 5, true).ID: return 608; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 5, false).ID: return 609; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 6, true).ID: return 610; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 6, false).ID: return 611; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 7, true).ID: return 612; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 7, false).ID: return 613; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 8, true).ID: return 614; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 8, false).ID: return 615; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 9, true).ID: return 616; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 9, false).ID: return 617; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 10, true).ID: return 618; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 10, false).ID: return 619; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 11, true).ID: return 620; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 11, false).ID: return 621; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 12, true).ID: return 622; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 12, false).ID: return 623; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 13, true).ID: return 624; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 13, false).ID: return 625; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 14, true).ID: return 626; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 14, false).ID: return 627; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 15, true).ID: return 628; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 15, false).ID: return 629; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 16, true).ID: return 630; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 16, false).ID: return 631; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 17, true).ID: return 632; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 17, false).ID: return 633; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 18, true).ID: return 634; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 18, false).ID: return 635; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 19, true).ID: return 636; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 19, false).ID: return 637; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 20, true).ID: return 638; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 20, false).ID: return 639; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 21, true).ID: return 640; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 21, false).ID: return 641; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 22, true).ID: return 642; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 22, false).ID: return 643; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 23, true).ID: return 644; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 23, false).ID: return 645; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 24, true).ID: return 646; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 24, false).ID: return 647; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 0, true).ID: return 648; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 0, false).ID: return 649; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 1, true).ID: return 650; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 1, false).ID: return 651; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 2, true).ID: return 652; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 2, false).ID: return 653; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 3, true).ID: return 654; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 3, false).ID: return 655; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 4, true).ID: return 656; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 4, false).ID: return 657; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 5, true).ID: return 658; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 5, false).ID: return 659; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 6, true).ID: return 660; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 6, false).ID: return 661; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 7, true).ID: return 662; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 7, false).ID: return 663; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 8, true).ID: return 664; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 8, false).ID: return 665; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 9, true).ID: return 666; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 9, false).ID: return 667; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 10, true).ID: return 668; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 10, false).ID: return 669; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 11, true).ID: return 670; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 11, false).ID: return 671; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 12, true).ID: return 672; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 12, false).ID: return 673; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 13, true).ID: return 674; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 13, false).ID: return 675; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 14, true).ID: return 676; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 14, false).ID: return 677; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 15, true).ID: return 678; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 15, false).ID: return 679; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 16, true).ID: return 680; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 16, false).ID: return 681; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 17, true).ID: return 682; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 17, false).ID: return 683; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 18, true).ID: return 684; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 18, false).ID: return 685; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 19, true).ID: return 686; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 19, false).ID: return 687; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 20, true).ID: return 688; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 20, false).ID: return 689; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 21, true).ID: return 690; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 21, false).ID: return 691; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 22, true).ID: return 692; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 22, false).ID: return 693; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 23, true).ID: return 694; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 23, false).ID: return 695; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 24, true).ID: return 696; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 24, false).ID: return 697; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 0, true).ID: return 698; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 0, false).ID: return 699; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 1, true).ID: return 700; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 1, false).ID: return 701; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 2, true).ID: return 702; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 2, false).ID: return 703; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 3, true).ID: return 704; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 3, false).ID: return 705; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 4, true).ID: return 706; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 4, false).ID: return 707; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 5, true).ID: return 708; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 5, false).ID: return 709; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 6, true).ID: return 710; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 6, false).ID: return 711; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 7, true).ID: return 712; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 7, false).ID: return 713; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 8, true).ID: return 714; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 8, false).ID: return 715; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 9, true).ID: return 716; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 9, false).ID: return 717; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 10, true).ID: return 718; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 10, false).ID: return 719; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 11, true).ID: return 720; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 11, false).ID: return 721; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 12, true).ID: return 722; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 12, false).ID: return 723; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 13, true).ID: return 724; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 13, false).ID: return 725; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 14, true).ID: return 726; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 14, false).ID: return 727; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 15, true).ID: return 728; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 15, false).ID: return 729; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 16, true).ID: return 730; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 16, false).ID: return 731; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 17, true).ID: return 732; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 17, false).ID: return 733; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 18, true).ID: return 734; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 18, false).ID: return 735; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 19, true).ID: return 736; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 19, false).ID: return 737; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 20, true).ID: return 738; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 20, false).ID: return 739; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 21, true).ID: return 740; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 21, false).ID: return 741; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 22, true).ID: return 742; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 22, false).ID: return 743; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 23, true).ID: return 744; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 23, false).ID: return 745; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 24, true).ID: return 746; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 24, false).ID: return 747; case OakButton::OakButton(OakButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5303; case OakButton::OakButton(OakButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5304; case OakButton::OakButton(OakButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5305; case OakButton::OakButton(OakButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5306; case OakButton::OakButton(OakButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, true).ID: return 5307; case OakButton::OakButton(OakButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, false).ID: return 5308; case OakButton::OakButton(OakButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, true).ID: return 5309; case OakButton::OakButton(OakButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, false).ID: return 5310; case OakButton::OakButton(OakButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5311; case OakButton::OakButton(OakButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5312; case OakButton::OakButton(OakButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5313; case OakButton::OakButton(OakButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5314; case OakButton::OakButton(OakButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, true).ID: return 5315; case OakButton::OakButton(OakButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, false).ID: return 5316; case OakButton::OakButton(OakButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, true).ID: return 5317; case OakButton::OakButton(OakButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, false).ID: return 5318; case OakButton::OakButton(OakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5319; case OakButton::OakButton(OakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5320; case OakButton::OakButton(OakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5321; case OakButton::OakButton(OakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5322; case OakButton::OakButton(OakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, true).ID: return 5323; case OakButton::OakButton(OakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, false).ID: return 5324; case OakButton::OakButton(OakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, true).ID: return 5325; case OakButton::OakButton(OakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, false).ID: return 5326; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Upper, OakDoor::Hinge::Left, true, true).ID: return 3107; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Upper, OakDoor::Hinge::Left, true, false).ID: return 3108; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Upper, OakDoor::Hinge::Left, false, true).ID: return 3109; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Upper, OakDoor::Hinge::Left, false, false).ID: return 3110; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Upper, OakDoor::Hinge::Right, true, true).ID: return 3111; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Upper, OakDoor::Hinge::Right, true, false).ID: return 3112; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Upper, OakDoor::Hinge::Right, false, true).ID: return 3113; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Upper, OakDoor::Hinge::Right, false, false).ID: return 3114; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Lower, OakDoor::Hinge::Left, true, true).ID: return 3115; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Lower, OakDoor::Hinge::Left, true, false).ID: return 3116; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Lower, OakDoor::Hinge::Left, false, true).ID: return 3117; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Lower, OakDoor::Hinge::Left, false, false).ID: return 3118; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Lower, OakDoor::Hinge::Right, true, true).ID: return 3119; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Lower, OakDoor::Hinge::Right, true, false).ID: return 3120; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Lower, OakDoor::Hinge::Right, false, true).ID: return 3121; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Lower, OakDoor::Hinge::Right, false, false).ID: return 3122; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Upper, OakDoor::Hinge::Left, true, true).ID: return 3123; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Upper, OakDoor::Hinge::Left, true, false).ID: return 3124; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Upper, OakDoor::Hinge::Left, false, true).ID: return 3125; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Upper, OakDoor::Hinge::Left, false, false).ID: return 3126; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Upper, OakDoor::Hinge::Right, true, true).ID: return 3127; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Upper, OakDoor::Hinge::Right, true, false).ID: return 3128; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Upper, OakDoor::Hinge::Right, false, true).ID: return 3129; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Upper, OakDoor::Hinge::Right, false, false).ID: return 3130; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Lower, OakDoor::Hinge::Left, true, true).ID: return 3131; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Lower, OakDoor::Hinge::Left, true, false).ID: return 3132; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Lower, OakDoor::Hinge::Left, false, true).ID: return 3133; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Lower, OakDoor::Hinge::Left, false, false).ID: return 3134; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Lower, OakDoor::Hinge::Right, true, true).ID: return 3135; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Lower, OakDoor::Hinge::Right, true, false).ID: return 3136; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Lower, OakDoor::Hinge::Right, false, true).ID: return 3137; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Lower, OakDoor::Hinge::Right, false, false).ID: return 3138; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Upper, OakDoor::Hinge::Left, true, true).ID: return 3139; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Upper, OakDoor::Hinge::Left, true, false).ID: return 3140; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Upper, OakDoor::Hinge::Left, false, true).ID: return 3141; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Upper, OakDoor::Hinge::Left, false, false).ID: return 3142; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Upper, OakDoor::Hinge::Right, true, true).ID: return 3143; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Upper, OakDoor::Hinge::Right, true, false).ID: return 3144; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Upper, OakDoor::Hinge::Right, false, true).ID: return 3145; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Upper, OakDoor::Hinge::Right, false, false).ID: return 3146; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Lower, OakDoor::Hinge::Left, true, true).ID: return 3147; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Lower, OakDoor::Hinge::Left, true, false).ID: return 3148; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Lower, OakDoor::Hinge::Left, false, true).ID: return 3149; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Lower, OakDoor::Hinge::Left, false, false).ID: return 3150; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Lower, OakDoor::Hinge::Right, true, true).ID: return 3151; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Lower, OakDoor::Hinge::Right, true, false).ID: return 3152; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Lower, OakDoor::Hinge::Right, false, true).ID: return 3153; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Lower, OakDoor::Hinge::Right, false, false).ID: return 3154; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Upper, OakDoor::Hinge::Left, true, true).ID: return 3155; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Upper, OakDoor::Hinge::Left, true, false).ID: return 3156; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Upper, OakDoor::Hinge::Left, false, true).ID: return 3157; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Upper, OakDoor::Hinge::Left, false, false).ID: return 3158; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Upper, OakDoor::Hinge::Right, true, true).ID: return 3159; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Upper, OakDoor::Hinge::Right, true, false).ID: return 3160; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Upper, OakDoor::Hinge::Right, false, true).ID: return 3161; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Upper, OakDoor::Hinge::Right, false, false).ID: return 3162; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Lower, OakDoor::Hinge::Left, true, true).ID: return 3163; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Lower, OakDoor::Hinge::Left, true, false).ID: return 3164; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Lower, OakDoor::Hinge::Left, false, true).ID: return 3165; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Lower, OakDoor::Hinge::Left, false, false).ID: return 3166; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Lower, OakDoor::Hinge::Right, true, true).ID: return 3167; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Lower, OakDoor::Hinge::Right, true, false).ID: return 3168; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Lower, OakDoor::Hinge::Right, false, true).ID: return 3169; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Lower, OakDoor::Hinge::Right, false, false).ID: return 3170; case OakFence::OakFence(true, true, true, true).ID: return 3462; case OakFence::OakFence(true, true, true, false).ID: return 3463; case OakFence::OakFence(true, true, false, true).ID: return 3466; case OakFence::OakFence(true, true, false, false).ID: return 3467; case OakFence::OakFence(true, false, true, true).ID: return 3470; case OakFence::OakFence(true, false, true, false).ID: return 3471; case OakFence::OakFence(true, false, false, true).ID: return 3474; case OakFence::OakFence(true, false, false, false).ID: return 3475; case OakFence::OakFence(false, true, true, true).ID: return 3478; case OakFence::OakFence(false, true, true, false).ID: return 3479; case OakFence::OakFence(false, true, false, true).ID: return 3482; case OakFence::OakFence(false, true, false, false).ID: return 3483; case OakFence::OakFence(false, false, true, true).ID: return 3486; case OakFence::OakFence(false, false, true, false).ID: return 3487; case OakFence::OakFence(false, false, false, true).ID: return 3490; case OakFence::OakFence(false, false, false, false).ID: return 3491; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZM, true, true, true).ID: return 4300; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZM, true, true, false).ID: return 4301; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZM, true, false, true).ID: return 4302; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZM, true, false, false).ID: return 4303; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, true).ID: return 4304; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, false).ID: return 4305; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, true).ID: return 4306; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, false).ID: return 4307; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZP, true, true, true).ID: return 4308; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZP, true, true, false).ID: return 4309; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZP, true, false, true).ID: return 4310; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZP, true, false, false).ID: return 4311; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, true).ID: return 4312; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, false).ID: return 4313; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, true).ID: return 4314; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, false).ID: return 4315; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XM, true, true, true).ID: return 4316; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XM, true, true, false).ID: return 4317; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XM, true, false, true).ID: return 4318; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XM, true, false, false).ID: return 4319; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, true).ID: return 4320; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, false).ID: return 4321; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, true).ID: return 4322; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, false).ID: return 4323; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XP, true, true, true).ID: return 4324; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XP, true, true, false).ID: return 4325; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XP, true, false, true).ID: return 4326; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XP, true, false, false).ID: return 4327; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, true).ID: return 4328; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, false).ID: return 4329; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, true).ID: return 4330; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, false).ID: return 4331; case OakLeaves::OakLeaves(1, true).ID: return 144; case OakLeaves::OakLeaves(1, false).ID: return 145; case OakLeaves::OakLeaves(2, true).ID: return 146; case OakLeaves::OakLeaves(2, false).ID: return 147; case OakLeaves::OakLeaves(3, true).ID: return 148; case OakLeaves::OakLeaves(3, false).ID: return 149; case OakLeaves::OakLeaves(4, true).ID: return 150; case OakLeaves::OakLeaves(4, false).ID: return 151; case OakLeaves::OakLeaves(5, true).ID: return 152; case OakLeaves::OakLeaves(5, false).ID: return 153; case OakLeaves::OakLeaves(6, true).ID: return 154; case OakLeaves::OakLeaves(6, false).ID: return 155; case OakLeaves::OakLeaves(7, true).ID: return 156; case OakLeaves::OakLeaves(7, false).ID: return 157; case OakLog::OakLog(OakLog::Axis::X).ID: return 72; case OakLog::OakLog(OakLog::Axis::Y).ID: return 73; case OakLog::OakLog(OakLog::Axis::Z).ID: return 74; case OakPlanks::OakPlanks().ID: return 15; case OakPressurePlate::OakPressurePlate(true).ID: return 3367; case OakPressurePlate::OakPressurePlate(false).ID: return 3368; case OakSapling::OakSapling(0).ID: return 21; case OakSapling::OakSapling(1).ID: return 22; case OakSlab::OakSlab(OakSlab::Type::Top).ID: return 7258; case OakSlab::OakSlab(OakSlab::Type::Bottom).ID: return 7260; case OakSlab::OakSlab(OakSlab::Type::Double).ID: return 7262; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZM, OakStairs::Half::Top, OakStairs::Shape::Straight).ID: return 1649; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZM, OakStairs::Half::Top, OakStairs::Shape::InnerLeft).ID: return 1651; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZM, OakStairs::Half::Top, OakStairs::Shape::InnerRight).ID: return 1653; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZM, OakStairs::Half::Top, OakStairs::Shape::OuterLeft).ID: return 1655; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZM, OakStairs::Half::Top, OakStairs::Shape::OuterRight).ID: return 1657; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZM, OakStairs::Half::Bottom, OakStairs::Shape::Straight).ID: return 1659; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZM, OakStairs::Half::Bottom, OakStairs::Shape::InnerLeft).ID: return 1661; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZM, OakStairs::Half::Bottom, OakStairs::Shape::InnerRight).ID: return 1663; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZM, OakStairs::Half::Bottom, OakStairs::Shape::OuterLeft).ID: return 1665; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZM, OakStairs::Half::Bottom, OakStairs::Shape::OuterRight).ID: return 1667; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZP, OakStairs::Half::Top, OakStairs::Shape::Straight).ID: return 1669; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZP, OakStairs::Half::Top, OakStairs::Shape::InnerLeft).ID: return 1671; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZP, OakStairs::Half::Top, OakStairs::Shape::InnerRight).ID: return 1673; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZP, OakStairs::Half::Top, OakStairs::Shape::OuterLeft).ID: return 1675; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZP, OakStairs::Half::Top, OakStairs::Shape::OuterRight).ID: return 1677; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZP, OakStairs::Half::Bottom, OakStairs::Shape::Straight).ID: return 1679; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZP, OakStairs::Half::Bottom, OakStairs::Shape::InnerLeft).ID: return 1681; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZP, OakStairs::Half::Bottom, OakStairs::Shape::InnerRight).ID: return 1683; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZP, OakStairs::Half::Bottom, OakStairs::Shape::OuterLeft).ID: return 1685; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZP, OakStairs::Half::Bottom, OakStairs::Shape::OuterRight).ID: return 1687; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XM, OakStairs::Half::Top, OakStairs::Shape::Straight).ID: return 1689; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XM, OakStairs::Half::Top, OakStairs::Shape::InnerLeft).ID: return 1691; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XM, OakStairs::Half::Top, OakStairs::Shape::InnerRight).ID: return 1693; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XM, OakStairs::Half::Top, OakStairs::Shape::OuterLeft).ID: return 1695; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XM, OakStairs::Half::Top, OakStairs::Shape::OuterRight).ID: return 1697; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XM, OakStairs::Half::Bottom, OakStairs::Shape::Straight).ID: return 1699; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XM, OakStairs::Half::Bottom, OakStairs::Shape::InnerLeft).ID: return 1701; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XM, OakStairs::Half::Bottom, OakStairs::Shape::InnerRight).ID: return 1703; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XM, OakStairs::Half::Bottom, OakStairs::Shape::OuterLeft).ID: return 1705; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XM, OakStairs::Half::Bottom, OakStairs::Shape::OuterRight).ID: return 1707; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XP, OakStairs::Half::Top, OakStairs::Shape::Straight).ID: return 1709; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XP, OakStairs::Half::Top, OakStairs::Shape::InnerLeft).ID: return 1711; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XP, OakStairs::Half::Top, OakStairs::Shape::InnerRight).ID: return 1713; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XP, OakStairs::Half::Top, OakStairs::Shape::OuterLeft).ID: return 1715; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XP, OakStairs::Half::Top, OakStairs::Shape::OuterRight).ID: return 1717; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XP, OakStairs::Half::Bottom, OakStairs::Shape::Straight).ID: return 1719; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XP, OakStairs::Half::Bottom, OakStairs::Shape::InnerLeft).ID: return 1721; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XP, OakStairs::Half::Bottom, OakStairs::Shape::InnerRight).ID: return 1723; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XP, OakStairs::Half::Bottom, OakStairs::Shape::OuterLeft).ID: return 1725; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XP, OakStairs::Half::Bottom, OakStairs::Shape::OuterRight).ID: return 1727; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZM, OakTrapdoor::Half::Top, true, true).ID: return 3594; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZM, OakTrapdoor::Half::Top, true, false).ID: return 3596; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZM, OakTrapdoor::Half::Top, false, true).ID: return 3598; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZM, OakTrapdoor::Half::Top, false, false).ID: return 3600; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZM, OakTrapdoor::Half::Bottom, true, true).ID: return 3602; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZM, OakTrapdoor::Half::Bottom, true, false).ID: return 3604; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZM, OakTrapdoor::Half::Bottom, false, true).ID: return 3606; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZM, OakTrapdoor::Half::Bottom, false, false).ID: return 3608; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZP, OakTrapdoor::Half::Top, true, true).ID: return 3610; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZP, OakTrapdoor::Half::Top, true, false).ID: return 3612; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZP, OakTrapdoor::Half::Top, false, true).ID: return 3614; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZP, OakTrapdoor::Half::Top, false, false).ID: return 3616; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZP, OakTrapdoor::Half::Bottom, true, true).ID: return 3618; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZP, OakTrapdoor::Half::Bottom, true, false).ID: return 3620; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZP, OakTrapdoor::Half::Bottom, false, true).ID: return 3622; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZP, OakTrapdoor::Half::Bottom, false, false).ID: return 3624; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XM, OakTrapdoor::Half::Top, true, true).ID: return 3626; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XM, OakTrapdoor::Half::Top, true, false).ID: return 3628; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XM, OakTrapdoor::Half::Top, false, true).ID: return 3630; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XM, OakTrapdoor::Half::Top, false, false).ID: return 3632; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XM, OakTrapdoor::Half::Bottom, true, true).ID: return 3634; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XM, OakTrapdoor::Half::Bottom, true, false).ID: return 3636; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XM, OakTrapdoor::Half::Bottom, false, true).ID: return 3638; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XM, OakTrapdoor::Half::Bottom, false, false).ID: return 3640; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XP, OakTrapdoor::Half::Top, true, true).ID: return 3642; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XP, OakTrapdoor::Half::Top, true, false).ID: return 3644; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XP, OakTrapdoor::Half::Top, false, true).ID: return 3646; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XP, OakTrapdoor::Half::Top, false, false).ID: return 3648; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XP, OakTrapdoor::Half::Bottom, true, true).ID: return 3650; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XP, OakTrapdoor::Half::Bottom, true, false).ID: return 3652; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XP, OakTrapdoor::Half::Bottom, false, true).ID: return 3654; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XP, OakTrapdoor::Half::Bottom, false, false).ID: return 3656; case OakWood::OakWood(OakWood::Axis::X).ID: return 108; case OakWood::OakWood(OakWood::Axis::Y).ID: return 109; case OakWood::OakWood(OakWood::Axis::Z).ID: return 110; case Observer::Observer(eBlockFace::BLOCK_FACE_ZM, true).ID: return 8199; case Observer::Observer(eBlockFace::BLOCK_FACE_ZM, false).ID: return 8200; case Observer::Observer(eBlockFace::BLOCK_FACE_XP, true).ID: return 8201; case Observer::Observer(eBlockFace::BLOCK_FACE_XP, false).ID: return 8202; case Observer::Observer(eBlockFace::BLOCK_FACE_ZP, true).ID: return 8203; case Observer::Observer(eBlockFace::BLOCK_FACE_ZP, false).ID: return 8204; case Observer::Observer(eBlockFace::BLOCK_FACE_XM, true).ID: return 8205; case Observer::Observer(eBlockFace::BLOCK_FACE_XM, false).ID: return 8206; case Observer::Observer(eBlockFace::BLOCK_FACE_YP, true).ID: return 8207; case Observer::Observer(eBlockFace::BLOCK_FACE_YP, false).ID: return 8208; case Observer::Observer(eBlockFace::BLOCK_FACE_YM, true).ID: return 8209; case Observer::Observer(eBlockFace::BLOCK_FACE_YM, false).ID: return 8210; case Obsidian::Obsidian().ID: return 1129; case OrangeBanner::OrangeBanner(0).ID: return 6870; case OrangeBanner::OrangeBanner(1).ID: return 6871; case OrangeBanner::OrangeBanner(2).ID: return 6872; case OrangeBanner::OrangeBanner(3).ID: return 6873; case OrangeBanner::OrangeBanner(4).ID: return 6874; case OrangeBanner::OrangeBanner(5).ID: return 6875; case OrangeBanner::OrangeBanner(6).ID: return 6876; case OrangeBanner::OrangeBanner(7).ID: return 6877; case OrangeBanner::OrangeBanner(8).ID: return 6878; case OrangeBanner::OrangeBanner(9).ID: return 6879; case OrangeBanner::OrangeBanner(10).ID: return 6880; case OrangeBanner::OrangeBanner(11).ID: return 6881; case OrangeBanner::OrangeBanner(12).ID: return 6882; case OrangeBanner::OrangeBanner(13).ID: return 6883; case OrangeBanner::OrangeBanner(14).ID: return 6884; case OrangeBanner::OrangeBanner(15).ID: return 6885; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_ZM, true, OrangeBed::Part::Head).ID: return 764; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_ZM, true, OrangeBed::Part::Foot).ID: return 765; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_ZM, false, OrangeBed::Part::Head).ID: return 766; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_ZM, false, OrangeBed::Part::Foot).ID: return 767; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_ZP, true, OrangeBed::Part::Head).ID: return 768; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_ZP, true, OrangeBed::Part::Foot).ID: return 769; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_ZP, false, OrangeBed::Part::Head).ID: return 770; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_ZP, false, OrangeBed::Part::Foot).ID: return 771; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_XM, true, OrangeBed::Part::Head).ID: return 772; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_XM, true, OrangeBed::Part::Foot).ID: return 773; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_XM, false, OrangeBed::Part::Head).ID: return 774; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_XM, false, OrangeBed::Part::Foot).ID: return 775; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_XP, true, OrangeBed::Part::Head).ID: return 776; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_XP, true, OrangeBed::Part::Foot).ID: return 777; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_XP, false, OrangeBed::Part::Head).ID: return 778; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_XP, false, OrangeBed::Part::Foot).ID: return 779; case OrangeCarpet::OrangeCarpet().ID: return 6824; case OrangeConcrete::OrangeConcrete().ID: return 8378; case OrangeConcretePowder::OrangeConcretePowder().ID: return 8394; case OrangeGlazedTerracotta::OrangeGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 8317; case OrangeGlazedTerracotta::OrangeGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 8318; case OrangeGlazedTerracotta::OrangeGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 8319; case OrangeGlazedTerracotta::OrangeGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 8320; case OrangeShulkerBox::OrangeShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 8223; case OrangeShulkerBox::OrangeShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 8224; case OrangeShulkerBox::OrangeShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 8225; case OrangeShulkerBox::OrangeShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 8226; case OrangeShulkerBox::OrangeShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 8227; case OrangeShulkerBox::OrangeShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 8228; case OrangeStainedGlass::OrangeStainedGlass().ID: return 3578; case OrangeStainedGlassPane::OrangeStainedGlassPane(true, true, true, true).ID: return 5854; case OrangeStainedGlassPane::OrangeStainedGlassPane(true, true, true, false).ID: return 5855; case OrangeStainedGlassPane::OrangeStainedGlassPane(true, true, false, true).ID: return 5858; case OrangeStainedGlassPane::OrangeStainedGlassPane(true, true, false, false).ID: return 5859; case OrangeStainedGlassPane::OrangeStainedGlassPane(true, false, true, true).ID: return 5862; case OrangeStainedGlassPane::OrangeStainedGlassPane(true, false, true, false).ID: return 5863; case OrangeStainedGlassPane::OrangeStainedGlassPane(true, false, false, true).ID: return 5866; case OrangeStainedGlassPane::OrangeStainedGlassPane(true, false, false, false).ID: return 5867; case OrangeStainedGlassPane::OrangeStainedGlassPane(false, true, true, true).ID: return 5870; case OrangeStainedGlassPane::OrangeStainedGlassPane(false, true, true, false).ID: return 5871; case OrangeStainedGlassPane::OrangeStainedGlassPane(false, true, false, true).ID: return 5874; case OrangeStainedGlassPane::OrangeStainedGlassPane(false, true, false, false).ID: return 5875; case OrangeStainedGlassPane::OrangeStainedGlassPane(false, false, true, true).ID: return 5878; case OrangeStainedGlassPane::OrangeStainedGlassPane(false, false, true, false).ID: return 5879; case OrangeStainedGlassPane::OrangeStainedGlassPane(false, false, false, true).ID: return 5882; case OrangeStainedGlassPane::OrangeStainedGlassPane(false, false, false, false).ID: return 5883; case OrangeTerracotta::OrangeTerracotta().ID: return 5805; case OrangeTulip::OrangeTulip().ID: return 1117; case OrangeWallBanner::OrangeWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 7114; case OrangeWallBanner::OrangeWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 7115; case OrangeWallBanner::OrangeWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 7116; case OrangeWallBanner::OrangeWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 7117; case OrangeWool::OrangeWool().ID: return 1084; case OxeyeDaisy::OxeyeDaisy().ID: return 1120; case PackedIce::PackedIce().ID: return 6841; case Peony::Peony(Peony::Half::Upper).ID: return 6848; case Peony::Peony(Peony::Half::Lower).ID: return 6849; case PetrifiedOakSlab::PetrifiedOakSlab(PetrifiedOakSlab::Type::Top).ID: return 7306; case PetrifiedOakSlab::PetrifiedOakSlab(PetrifiedOakSlab::Type::Bottom).ID: return 7308; case PetrifiedOakSlab::PetrifiedOakSlab(PetrifiedOakSlab::Type::Double).ID: return 7310; case PinkBanner::PinkBanner(0).ID: return 6950; case PinkBanner::PinkBanner(1).ID: return 6951; case PinkBanner::PinkBanner(2).ID: return 6952; case PinkBanner::PinkBanner(3).ID: return 6953; case PinkBanner::PinkBanner(4).ID: return 6954; case PinkBanner::PinkBanner(5).ID: return 6955; case PinkBanner::PinkBanner(6).ID: return 6956; case PinkBanner::PinkBanner(7).ID: return 6957; case PinkBanner::PinkBanner(8).ID: return 6958; case PinkBanner::PinkBanner(9).ID: return 6959; case PinkBanner::PinkBanner(10).ID: return 6960; case PinkBanner::PinkBanner(11).ID: return 6961; case PinkBanner::PinkBanner(12).ID: return 6962; case PinkBanner::PinkBanner(13).ID: return 6963; case PinkBanner::PinkBanner(14).ID: return 6964; case PinkBanner::PinkBanner(15).ID: return 6965; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_ZM, true, PinkBed::Part::Head).ID: return 844; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_ZM, true, PinkBed::Part::Foot).ID: return 845; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_ZM, false, PinkBed::Part::Head).ID: return 846; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_ZM, false, PinkBed::Part::Foot).ID: return 847; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_ZP, true, PinkBed::Part::Head).ID: return 848; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_ZP, true, PinkBed::Part::Foot).ID: return 849; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_ZP, false, PinkBed::Part::Head).ID: return 850; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_ZP, false, PinkBed::Part::Foot).ID: return 851; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_XM, true, PinkBed::Part::Head).ID: return 852; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_XM, true, PinkBed::Part::Foot).ID: return 853; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_XM, false, PinkBed::Part::Head).ID: return 854; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_XM, false, PinkBed::Part::Foot).ID: return 855; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_XP, true, PinkBed::Part::Head).ID: return 856; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_XP, true, PinkBed::Part::Foot).ID: return 857; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_XP, false, PinkBed::Part::Head).ID: return 858; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_XP, false, PinkBed::Part::Foot).ID: return 859; case PinkCarpet::PinkCarpet().ID: return 6829; case PinkConcrete::PinkConcrete().ID: return 8383; case PinkConcretePowder::PinkConcretePowder().ID: return 8399; case PinkGlazedTerracotta::PinkGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 8337; case PinkGlazedTerracotta::PinkGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 8338; case PinkGlazedTerracotta::PinkGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 8339; case PinkGlazedTerracotta::PinkGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 8340; case PinkShulkerBox::PinkShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 8253; case PinkShulkerBox::PinkShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 8254; case PinkShulkerBox::PinkShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 8255; case PinkShulkerBox::PinkShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 8256; case PinkShulkerBox::PinkShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 8257; case PinkShulkerBox::PinkShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 8258; case PinkStainedGlass::PinkStainedGlass().ID: return 3583; case PinkStainedGlassPane::PinkStainedGlassPane(true, true, true, true).ID: return 6014; case PinkStainedGlassPane::PinkStainedGlassPane(true, true, true, false).ID: return 6015; case PinkStainedGlassPane::PinkStainedGlassPane(true, true, false, true).ID: return 6018; case PinkStainedGlassPane::PinkStainedGlassPane(true, true, false, false).ID: return 6019; case PinkStainedGlassPane::PinkStainedGlassPane(true, false, true, true).ID: return 6022; case PinkStainedGlassPane::PinkStainedGlassPane(true, false, true, false).ID: return 6023; case PinkStainedGlassPane::PinkStainedGlassPane(true, false, false, true).ID: return 6026; case PinkStainedGlassPane::PinkStainedGlassPane(true, false, false, false).ID: return 6027; case PinkStainedGlassPane::PinkStainedGlassPane(false, true, true, true).ID: return 6030; case PinkStainedGlassPane::PinkStainedGlassPane(false, true, true, false).ID: return 6031; case PinkStainedGlassPane::PinkStainedGlassPane(false, true, false, true).ID: return 6034; case PinkStainedGlassPane::PinkStainedGlassPane(false, true, false, false).ID: return 6035; case PinkStainedGlassPane::PinkStainedGlassPane(false, false, true, true).ID: return 6038; case PinkStainedGlassPane::PinkStainedGlassPane(false, false, true, false).ID: return 6039; case PinkStainedGlassPane::PinkStainedGlassPane(false, false, false, true).ID: return 6042; case PinkStainedGlassPane::PinkStainedGlassPane(false, false, false, false).ID: return 6043; case PinkTerracotta::PinkTerracotta().ID: return 5810; case PinkTulip::PinkTulip().ID: return 1119; case PinkWallBanner::PinkWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 7134; case PinkWallBanner::PinkWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 7135; case PinkWallBanner::PinkWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 7136; case PinkWallBanner::PinkWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 7137; case PinkWool::PinkWool().ID: return 1089; case Piston::Piston(true, eBlockFace::BLOCK_FACE_ZM).ID: return 1047; case Piston::Piston(true, eBlockFace::BLOCK_FACE_XP).ID: return 1048; case Piston::Piston(true, eBlockFace::BLOCK_FACE_ZP).ID: return 1049; case Piston::Piston(true, eBlockFace::BLOCK_FACE_XM).ID: return 1050; case Piston::Piston(true, eBlockFace::BLOCK_FACE_YP).ID: return 1051; case Piston::Piston(true, eBlockFace::BLOCK_FACE_YM).ID: return 1052; case Piston::Piston(false, eBlockFace::BLOCK_FACE_ZM).ID: return 1053; case Piston::Piston(false, eBlockFace::BLOCK_FACE_XP).ID: return 1054; case Piston::Piston(false, eBlockFace::BLOCK_FACE_ZP).ID: return 1055; case Piston::Piston(false, eBlockFace::BLOCK_FACE_XM).ID: return 1056; case Piston::Piston(false, eBlockFace::BLOCK_FACE_YP).ID: return 1057; case Piston::Piston(false, eBlockFace::BLOCK_FACE_YM).ID: return 1058; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_ZM, true, PistonHead::Type::Normal).ID: return 1059; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_ZM, true, PistonHead::Type::Sticky).ID: return 1060; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_ZM, false, PistonHead::Type::Normal).ID: return 1061; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_ZM, false, PistonHead::Type::Sticky).ID: return 1062; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_XP, true, PistonHead::Type::Normal).ID: return 1063; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_XP, true, PistonHead::Type::Sticky).ID: return 1064; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_XP, false, PistonHead::Type::Normal).ID: return 1065; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_XP, false, PistonHead::Type::Sticky).ID: return 1066; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_ZP, true, PistonHead::Type::Normal).ID: return 1067; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_ZP, true, PistonHead::Type::Sticky).ID: return 1068; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_ZP, false, PistonHead::Type::Normal).ID: return 1069; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_ZP, false, PistonHead::Type::Sticky).ID: return 1070; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_XM, true, PistonHead::Type::Normal).ID: return 1071; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_XM, true, PistonHead::Type::Sticky).ID: return 1072; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_XM, false, PistonHead::Type::Normal).ID: return 1073; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_XM, false, PistonHead::Type::Sticky).ID: return 1074; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_YP, true, PistonHead::Type::Normal).ID: return 1075; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_YP, true, PistonHead::Type::Sticky).ID: return 1076; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_YP, false, PistonHead::Type::Normal).ID: return 1077; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_YP, false, PistonHead::Type::Sticky).ID: return 1078; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_YM, true, PistonHead::Type::Normal).ID: return 1079; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_YM, true, PistonHead::Type::Sticky).ID: return 1080; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_YM, false, PistonHead::Type::Normal).ID: return 1081; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_YM, false, PistonHead::Type::Sticky).ID: return 1082; case PlayerHead::PlayerHead(0).ID: return 5511; case PlayerHead::PlayerHead(1).ID: return 5512; case PlayerHead::PlayerHead(2).ID: return 5513; case PlayerHead::PlayerHead(3).ID: return 5514; case PlayerHead::PlayerHead(4).ID: return 5515; case PlayerHead::PlayerHead(5).ID: return 5516; case PlayerHead::PlayerHead(6).ID: return 5517; case PlayerHead::PlayerHead(7).ID: return 5518; case PlayerHead::PlayerHead(8).ID: return 5519; case PlayerHead::PlayerHead(9).ID: return 5520; case PlayerHead::PlayerHead(10).ID: return 5521; case PlayerHead::PlayerHead(11).ID: return 5522; case PlayerHead::PlayerHead(12).ID: return 5523; case PlayerHead::PlayerHead(13).ID: return 5524; case PlayerHead::PlayerHead(14).ID: return 5525; case PlayerHead::PlayerHead(15).ID: return 5526; case PlayerWallHead::PlayerWallHead(eBlockFace::BLOCK_FACE_ZM).ID: return 5507; case PlayerWallHead::PlayerWallHead(eBlockFace::BLOCK_FACE_ZP).ID: return 5508; case PlayerWallHead::PlayerWallHead(eBlockFace::BLOCK_FACE_XM).ID: return 5509; case PlayerWallHead::PlayerWallHead(eBlockFace::BLOCK_FACE_XP).ID: return 5510; case Podzol::Podzol(true).ID: return 12; case Podzol::Podzol(false).ID: return 13; case PolishedAndesite::PolishedAndesite().ID: return 7; case PolishedDiorite::PolishedDiorite().ID: return 5; case PolishedGranite::PolishedGranite().ID: return 3; case Poppy::Poppy().ID: return 1112; case Potatoes::Potatoes(0).ID: return 5295; case Potatoes::Potatoes(1).ID: return 5296; case Potatoes::Potatoes(2).ID: return 5297; case Potatoes::Potatoes(3).ID: return 5298; case Potatoes::Potatoes(4).ID: return 5299; case Potatoes::Potatoes(5).ID: return 5300; case Potatoes::Potatoes(6).ID: return 5301; case Potatoes::Potatoes(7).ID: return 5302; case PottedAcaciaSapling::PottedAcaciaSapling().ID: return 5270; case PottedAllium::PottedAllium().ID: return 5276; case PottedAzureBluet::PottedAzureBluet().ID: return 5277; case PottedBirchSapling::PottedBirchSapling().ID: return 5268; case PottedBlueOrchid::PottedBlueOrchid().ID: return 5275; case PottedBrownMushroom::PottedBrownMushroom().ID: return 5284; case PottedCactus::PottedCactus().ID: return 5286; case PottedDandelion::PottedDandelion().ID: return 5273; case PottedDarkOakSapling::PottedDarkOakSapling().ID: return 5271; case PottedDeadBush::PottedDeadBush().ID: return 5285; case PottedFern::PottedFern().ID: return 5272; case PottedJungleSapling::PottedJungleSapling().ID: return 5269; case PottedOakSapling::PottedOakSapling().ID: return 5266; case PottedOrangeTulip::PottedOrangeTulip().ID: return 5279; case PottedOxeyeDaisy::PottedOxeyeDaisy().ID: return 5282; case PottedPinkTulip::PottedPinkTulip().ID: return 5281; case PottedPoppy::PottedPoppy().ID: return 5274; case PottedRedMushroom::PottedRedMushroom().ID: return 5283; case PottedRedTulip::PottedRedTulip().ID: return 5278; case PottedSpruceSapling::PottedSpruceSapling().ID: return 5267; case PottedWhiteTulip::PottedWhiteTulip().ID: return 5280; case PoweredRail::PoweredRail(true, PoweredRail::Shape::NorthSouth).ID: return 1004; case PoweredRail::PoweredRail(true, PoweredRail::Shape::EastWest).ID: return 1005; case PoweredRail::PoweredRail(true, PoweredRail::Shape::AscendingEast).ID: return 1006; case PoweredRail::PoweredRail(true, PoweredRail::Shape::AscendingWest).ID: return 1007; case PoweredRail::PoweredRail(true, PoweredRail::Shape::AscendingNorth).ID: return 1008; case PoweredRail::PoweredRail(true, PoweredRail::Shape::AscendingSouth).ID: return 1009; case PoweredRail::PoweredRail(false, PoweredRail::Shape::NorthSouth).ID: return 1010; case PoweredRail::PoweredRail(false, PoweredRail::Shape::EastWest).ID: return 1011; case PoweredRail::PoweredRail(false, PoweredRail::Shape::AscendingEast).ID: return 1012; case PoweredRail::PoweredRail(false, PoweredRail::Shape::AscendingWest).ID: return 1013; case PoweredRail::PoweredRail(false, PoweredRail::Shape::AscendingNorth).ID: return 1014; case PoweredRail::PoweredRail(false, PoweredRail::Shape::AscendingSouth).ID: return 1015; case Prismarine::Prismarine().ID: return 6558; case PrismarineBrickSlab::PrismarineBrickSlab(PrismarineBrickSlab::Type::Top).ID: return 6808; case PrismarineBrickSlab::PrismarineBrickSlab(PrismarineBrickSlab::Type::Bottom).ID: return 6810; case PrismarineBrickSlab::PrismarineBrickSlab(PrismarineBrickSlab::Type::Double).ID: return 6812; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::Straight).ID: return 6642; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::InnerLeft).ID: return 6644; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::InnerRight).ID: return 6646; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::OuterLeft).ID: return 6648; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::OuterRight).ID: return 6650; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::Straight).ID: return 6652; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::InnerLeft).ID: return 6654; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::InnerRight).ID: return 6656; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::OuterLeft).ID: return 6658; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::OuterRight).ID: return 6660; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::Straight).ID: return 6662; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::InnerLeft).ID: return 6664; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::InnerRight).ID: return 6666; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::OuterLeft).ID: return 6668; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::OuterRight).ID: return 6670; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::Straight).ID: return 6672; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::InnerLeft).ID: return 6674; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::InnerRight).ID: return 6676; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::OuterLeft).ID: return 6678; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::OuterRight).ID: return 6680; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XM, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::Straight).ID: return 6682; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XM, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::InnerLeft).ID: return 6684; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XM, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::InnerRight).ID: return 6686; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XM, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::OuterLeft).ID: return 6688; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XM, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::OuterRight).ID: return 6690; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XM, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::Straight).ID: return 6692; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XM, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::InnerLeft).ID: return 6694; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XM, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::InnerRight).ID: return 6696; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XM, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::OuterLeft).ID: return 6698; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XM, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::OuterRight).ID: return 6700; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XP, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::Straight).ID: return 6702; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XP, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::InnerLeft).ID: return 6704; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XP, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::InnerRight).ID: return 6706; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XP, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::OuterLeft).ID: return 6708; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XP, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::OuterRight).ID: return 6710; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XP, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::Straight).ID: return 6712; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XP, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::InnerLeft).ID: return 6714; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XP, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::InnerRight).ID: return 6716; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XP, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::OuterLeft).ID: return 6718; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XP, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::OuterRight).ID: return 6720; case PrismarineBricks::PrismarineBricks().ID: return 6559; case PrismarineSlab::PrismarineSlab(PrismarineSlab::Type::Top).ID: return 6802; case PrismarineSlab::PrismarineSlab(PrismarineSlab::Type::Bottom).ID: return 6804; case PrismarineSlab::PrismarineSlab(PrismarineSlab::Type::Double).ID: return 6806; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineStairs::Half::Top, PrismarineStairs::Shape::Straight).ID: return 6562; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineStairs::Half::Top, PrismarineStairs::Shape::InnerLeft).ID: return 6564; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineStairs::Half::Top, PrismarineStairs::Shape::InnerRight).ID: return 6566; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineStairs::Half::Top, PrismarineStairs::Shape::OuterLeft).ID: return 6568; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineStairs::Half::Top, PrismarineStairs::Shape::OuterRight).ID: return 6570; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::Straight).ID: return 6572; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::InnerLeft).ID: return 6574; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::InnerRight).ID: return 6576; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::OuterLeft).ID: return 6578; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::OuterRight).ID: return 6580; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineStairs::Half::Top, PrismarineStairs::Shape::Straight).ID: return 6582; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineStairs::Half::Top, PrismarineStairs::Shape::InnerLeft).ID: return 6584; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineStairs::Half::Top, PrismarineStairs::Shape::InnerRight).ID: return 6586; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineStairs::Half::Top, PrismarineStairs::Shape::OuterLeft).ID: return 6588; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineStairs::Half::Top, PrismarineStairs::Shape::OuterRight).ID: return 6590; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::Straight).ID: return 6592; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::InnerLeft).ID: return 6594; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::InnerRight).ID: return 6596; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::OuterLeft).ID: return 6598; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::OuterRight).ID: return 6600; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XM, PrismarineStairs::Half::Top, PrismarineStairs::Shape::Straight).ID: return 6602; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XM, PrismarineStairs::Half::Top, PrismarineStairs::Shape::InnerLeft).ID: return 6604; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XM, PrismarineStairs::Half::Top, PrismarineStairs::Shape::InnerRight).ID: return 6606; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XM, PrismarineStairs::Half::Top, PrismarineStairs::Shape::OuterLeft).ID: return 6608; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XM, PrismarineStairs::Half::Top, PrismarineStairs::Shape::OuterRight).ID: return 6610; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XM, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::Straight).ID: return 6612; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XM, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::InnerLeft).ID: return 6614; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XM, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::InnerRight).ID: return 6616; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XM, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::OuterLeft).ID: return 6618; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XM, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::OuterRight).ID: return 6620; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XP, PrismarineStairs::Half::Top, PrismarineStairs::Shape::Straight).ID: return 6622; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XP, PrismarineStairs::Half::Top, PrismarineStairs::Shape::InnerLeft).ID: return 6624; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XP, PrismarineStairs::Half::Top, PrismarineStairs::Shape::InnerRight).ID: return 6626; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XP, PrismarineStairs::Half::Top, PrismarineStairs::Shape::OuterLeft).ID: return 6628; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XP, PrismarineStairs::Half::Top, PrismarineStairs::Shape::OuterRight).ID: return 6630; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XP, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::Straight).ID: return 6632; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XP, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::InnerLeft).ID: return 6634; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XP, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::InnerRight).ID: return 6636; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XP, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::OuterLeft).ID: return 6638; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XP, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::OuterRight).ID: return 6640; case Pumpkin::Pumpkin().ID: return 3492; case PumpkinStem::PumpkinStem(0).ID: return 4252; case PumpkinStem::PumpkinStem(1).ID: return 4253; case PumpkinStem::PumpkinStem(2).ID: return 4254; case PumpkinStem::PumpkinStem(3).ID: return 4255; case PumpkinStem::PumpkinStem(4).ID: return 4256; case PumpkinStem::PumpkinStem(5).ID: return 4257; case PumpkinStem::PumpkinStem(6).ID: return 4258; case PumpkinStem::PumpkinStem(7).ID: return 4259; case PurpleBanner::PurpleBanner(0).ID: return 7014; case PurpleBanner::PurpleBanner(1).ID: return 7015; case PurpleBanner::PurpleBanner(2).ID: return 7016; case PurpleBanner::PurpleBanner(3).ID: return 7017; case PurpleBanner::PurpleBanner(4).ID: return 7018; case PurpleBanner::PurpleBanner(5).ID: return 7019; case PurpleBanner::PurpleBanner(6).ID: return 7020; case PurpleBanner::PurpleBanner(7).ID: return 7021; case PurpleBanner::PurpleBanner(8).ID: return 7022; case PurpleBanner::PurpleBanner(9).ID: return 7023; case PurpleBanner::PurpleBanner(10).ID: return 7024; case PurpleBanner::PurpleBanner(11).ID: return 7025; case PurpleBanner::PurpleBanner(12).ID: return 7026; case PurpleBanner::PurpleBanner(13).ID: return 7027; case PurpleBanner::PurpleBanner(14).ID: return 7028; case PurpleBanner::PurpleBanner(15).ID: return 7029; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_ZM, true, PurpleBed::Part::Head).ID: return 908; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_ZM, true, PurpleBed::Part::Foot).ID: return 909; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_ZM, false, PurpleBed::Part::Head).ID: return 910; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_ZM, false, PurpleBed::Part::Foot).ID: return 911; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_ZP, true, PurpleBed::Part::Head).ID: return 912; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_ZP, true, PurpleBed::Part::Foot).ID: return 913; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_ZP, false, PurpleBed::Part::Head).ID: return 914; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_ZP, false, PurpleBed::Part::Foot).ID: return 915; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_XM, true, PurpleBed::Part::Head).ID: return 916; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_XM, true, PurpleBed::Part::Foot).ID: return 917; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_XM, false, PurpleBed::Part::Head).ID: return 918; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_XM, false, PurpleBed::Part::Foot).ID: return 919; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_XP, true, PurpleBed::Part::Head).ID: return 920; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_XP, true, PurpleBed::Part::Foot).ID: return 921; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_XP, false, PurpleBed::Part::Head).ID: return 922; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_XP, false, PurpleBed::Part::Foot).ID: return 923; case PurpleCarpet::PurpleCarpet().ID: return 6833; case PurpleConcrete::PurpleConcrete().ID: return 8387; case PurpleConcretePowder::PurpleConcretePowder().ID: return 8403; case PurpleGlazedTerracotta::PurpleGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 8353; case PurpleGlazedTerracotta::PurpleGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 8354; case PurpleGlazedTerracotta::PurpleGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 8355; case PurpleGlazedTerracotta::PurpleGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 8356; case PurpleShulkerBox::PurpleShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 8277; case PurpleShulkerBox::PurpleShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 8278; case PurpleShulkerBox::PurpleShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 8279; case PurpleShulkerBox::PurpleShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 8280; case PurpleShulkerBox::PurpleShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 8281; case PurpleShulkerBox::PurpleShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 8282; case PurpleStainedGlass::PurpleStainedGlass().ID: return 3587; case PurpleStainedGlassPane::PurpleStainedGlassPane(true, true, true, true).ID: return 6142; case PurpleStainedGlassPane::PurpleStainedGlassPane(true, true, true, false).ID: return 6143; case PurpleStainedGlassPane::PurpleStainedGlassPane(true, true, false, true).ID: return 6146; case PurpleStainedGlassPane::PurpleStainedGlassPane(true, true, false, false).ID: return 6147; case PurpleStainedGlassPane::PurpleStainedGlassPane(true, false, true, true).ID: return 6150; case PurpleStainedGlassPane::PurpleStainedGlassPane(true, false, true, false).ID: return 6151; case PurpleStainedGlassPane::PurpleStainedGlassPane(true, false, false, true).ID: return 6154; case PurpleStainedGlassPane::PurpleStainedGlassPane(true, false, false, false).ID: return 6155; case PurpleStainedGlassPane::PurpleStainedGlassPane(false, true, true, true).ID: return 6158; case PurpleStainedGlassPane::PurpleStainedGlassPane(false, true, true, false).ID: return 6159; case PurpleStainedGlassPane::PurpleStainedGlassPane(false, true, false, true).ID: return 6162; case PurpleStainedGlassPane::PurpleStainedGlassPane(false, true, false, false).ID: return 6163; case PurpleStainedGlassPane::PurpleStainedGlassPane(false, false, true, true).ID: return 6166; case PurpleStainedGlassPane::PurpleStainedGlassPane(false, false, true, false).ID: return 6167; case PurpleStainedGlassPane::PurpleStainedGlassPane(false, false, false, true).ID: return 6170; case PurpleStainedGlassPane::PurpleStainedGlassPane(false, false, false, false).ID: return 6171; case PurpleTerracotta::PurpleTerracotta().ID: return 5814; case PurpleWallBanner::PurpleWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 7150; case PurpleWallBanner::PurpleWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 7151; case PurpleWallBanner::PurpleWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 7152; case PurpleWallBanner::PurpleWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 7153; case PurpleWool::PurpleWool().ID: return 1093; case PurpurBlock::PurpurBlock().ID: return 8073; case PurpurPillar::PurpurPillar(PurpurPillar::Axis::X).ID: return 8074; case PurpurPillar::PurpurPillar(PurpurPillar::Axis::Y).ID: return 8075; case PurpurPillar::PurpurPillar(PurpurPillar::Axis::Z).ID: return 8076; case PurpurSlab::PurpurSlab(PurpurSlab::Type::Top).ID: return 7348; case PurpurSlab::PurpurSlab(PurpurSlab::Type::Bottom).ID: return 7350; case PurpurSlab::PurpurSlab(PurpurSlab::Type::Double).ID: return 7352; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZM, PurpurStairs::Half::Top, PurpurStairs::Shape::Straight).ID: return 8078; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZM, PurpurStairs::Half::Top, PurpurStairs::Shape::InnerLeft).ID: return 8080; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZM, PurpurStairs::Half::Top, PurpurStairs::Shape::InnerRight).ID: return 8082; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZM, PurpurStairs::Half::Top, PurpurStairs::Shape::OuterLeft).ID: return 8084; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZM, PurpurStairs::Half::Top, PurpurStairs::Shape::OuterRight).ID: return 8086; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZM, PurpurStairs::Half::Bottom, PurpurStairs::Shape::Straight).ID: return 8088; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZM, PurpurStairs::Half::Bottom, PurpurStairs::Shape::InnerLeft).ID: return 8090; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZM, PurpurStairs::Half::Bottom, PurpurStairs::Shape::InnerRight).ID: return 8092; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZM, PurpurStairs::Half::Bottom, PurpurStairs::Shape::OuterLeft).ID: return 8094; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZM, PurpurStairs::Half::Bottom, PurpurStairs::Shape::OuterRight).ID: return 8096; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZP, PurpurStairs::Half::Top, PurpurStairs::Shape::Straight).ID: return 8098; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZP, PurpurStairs::Half::Top, PurpurStairs::Shape::InnerLeft).ID: return 8100; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZP, PurpurStairs::Half::Top, PurpurStairs::Shape::InnerRight).ID: return 8102; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZP, PurpurStairs::Half::Top, PurpurStairs::Shape::OuterLeft).ID: return 8104; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZP, PurpurStairs::Half::Top, PurpurStairs::Shape::OuterRight).ID: return 8106; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZP, PurpurStairs::Half::Bottom, PurpurStairs::Shape::Straight).ID: return 8108; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZP, PurpurStairs::Half::Bottom, PurpurStairs::Shape::InnerLeft).ID: return 8110; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZP, PurpurStairs::Half::Bottom, PurpurStairs::Shape::InnerRight).ID: return 8112; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZP, PurpurStairs::Half::Bottom, PurpurStairs::Shape::OuterLeft).ID: return 8114; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZP, PurpurStairs::Half::Bottom, PurpurStairs::Shape::OuterRight).ID: return 8116; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XM, PurpurStairs::Half::Top, PurpurStairs::Shape::Straight).ID: return 8118; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XM, PurpurStairs::Half::Top, PurpurStairs::Shape::InnerLeft).ID: return 8120; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XM, PurpurStairs::Half::Top, PurpurStairs::Shape::InnerRight).ID: return 8122; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XM, PurpurStairs::Half::Top, PurpurStairs::Shape::OuterLeft).ID: return 8124; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XM, PurpurStairs::Half::Top, PurpurStairs::Shape::OuterRight).ID: return 8126; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XM, PurpurStairs::Half::Bottom, PurpurStairs::Shape::Straight).ID: return 8128; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XM, PurpurStairs::Half::Bottom, PurpurStairs::Shape::InnerLeft).ID: return 8130; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XM, PurpurStairs::Half::Bottom, PurpurStairs::Shape::InnerRight).ID: return 8132; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XM, PurpurStairs::Half::Bottom, PurpurStairs::Shape::OuterLeft).ID: return 8134; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XM, PurpurStairs::Half::Bottom, PurpurStairs::Shape::OuterRight).ID: return 8136; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XP, PurpurStairs::Half::Top, PurpurStairs::Shape::Straight).ID: return 8138; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XP, PurpurStairs::Half::Top, PurpurStairs::Shape::InnerLeft).ID: return 8140; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XP, PurpurStairs::Half::Top, PurpurStairs::Shape::InnerRight).ID: return 8142; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XP, PurpurStairs::Half::Top, PurpurStairs::Shape::OuterLeft).ID: return 8144; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XP, PurpurStairs::Half::Top, PurpurStairs::Shape::OuterRight).ID: return 8146; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XP, PurpurStairs::Half::Bottom, PurpurStairs::Shape::Straight).ID: return 8148; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XP, PurpurStairs::Half::Bottom, PurpurStairs::Shape::InnerLeft).ID: return 8150; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XP, PurpurStairs::Half::Bottom, PurpurStairs::Shape::InnerRight).ID: return 8152; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XP, PurpurStairs::Half::Bottom, PurpurStairs::Shape::OuterLeft).ID: return 8154; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XP, PurpurStairs::Half::Bottom, PurpurStairs::Shape::OuterRight).ID: return 8156; case QuartzBlock::QuartzBlock().ID: return 5695; case QuartzPillar::QuartzPillar(QuartzPillar::Axis::X).ID: return 5697; case QuartzPillar::QuartzPillar(QuartzPillar::Axis::Y).ID: return 5698; case QuartzPillar::QuartzPillar(QuartzPillar::Axis::Z).ID: return 5699; case QuartzSlab::QuartzSlab(QuartzSlab::Type::Top).ID: return 7336; case QuartzSlab::QuartzSlab(QuartzSlab::Type::Bottom).ID: return 7338; case QuartzSlab::QuartzSlab(QuartzSlab::Type::Double).ID: return 7340; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZM, QuartzStairs::Half::Top, QuartzStairs::Shape::Straight).ID: return 5701; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZM, QuartzStairs::Half::Top, QuartzStairs::Shape::InnerLeft).ID: return 5703; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZM, QuartzStairs::Half::Top, QuartzStairs::Shape::InnerRight).ID: return 5705; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZM, QuartzStairs::Half::Top, QuartzStairs::Shape::OuterLeft).ID: return 5707; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZM, QuartzStairs::Half::Top, QuartzStairs::Shape::OuterRight).ID: return 5709; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZM, QuartzStairs::Half::Bottom, QuartzStairs::Shape::Straight).ID: return 5711; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZM, QuartzStairs::Half::Bottom, QuartzStairs::Shape::InnerLeft).ID: return 5713; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZM, QuartzStairs::Half::Bottom, QuartzStairs::Shape::InnerRight).ID: return 5715; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZM, QuartzStairs::Half::Bottom, QuartzStairs::Shape::OuterLeft).ID: return 5717; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZM, QuartzStairs::Half::Bottom, QuartzStairs::Shape::OuterRight).ID: return 5719; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZP, QuartzStairs::Half::Top, QuartzStairs::Shape::Straight).ID: return 5721; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZP, QuartzStairs::Half::Top, QuartzStairs::Shape::InnerLeft).ID: return 5723; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZP, QuartzStairs::Half::Top, QuartzStairs::Shape::InnerRight).ID: return 5725; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZP, QuartzStairs::Half::Top, QuartzStairs::Shape::OuterLeft).ID: return 5727; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZP, QuartzStairs::Half::Top, QuartzStairs::Shape::OuterRight).ID: return 5729; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZP, QuartzStairs::Half::Bottom, QuartzStairs::Shape::Straight).ID: return 5731; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZP, QuartzStairs::Half::Bottom, QuartzStairs::Shape::InnerLeft).ID: return 5733; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZP, QuartzStairs::Half::Bottom, QuartzStairs::Shape::InnerRight).ID: return 5735; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZP, QuartzStairs::Half::Bottom, QuartzStairs::Shape::OuterLeft).ID: return 5737; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZP, QuartzStairs::Half::Bottom, QuartzStairs::Shape::OuterRight).ID: return 5739; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XM, QuartzStairs::Half::Top, QuartzStairs::Shape::Straight).ID: return 5741; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XM, QuartzStairs::Half::Top, QuartzStairs::Shape::InnerLeft).ID: return 5743; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XM, QuartzStairs::Half::Top, QuartzStairs::Shape::InnerRight).ID: return 5745; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XM, QuartzStairs::Half::Top, QuartzStairs::Shape::OuterLeft).ID: return 5747; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XM, QuartzStairs::Half::Top, QuartzStairs::Shape::OuterRight).ID: return 5749; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XM, QuartzStairs::Half::Bottom, QuartzStairs::Shape::Straight).ID: return 5751; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XM, QuartzStairs::Half::Bottom, QuartzStairs::Shape::InnerLeft).ID: return 5753; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XM, QuartzStairs::Half::Bottom, QuartzStairs::Shape::InnerRight).ID: return 5755; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XM, QuartzStairs::Half::Bottom, QuartzStairs::Shape::OuterLeft).ID: return 5757; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XM, QuartzStairs::Half::Bottom, QuartzStairs::Shape::OuterRight).ID: return 5759; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XP, QuartzStairs::Half::Top, QuartzStairs::Shape::Straight).ID: return 5761; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XP, QuartzStairs::Half::Top, QuartzStairs::Shape::InnerLeft).ID: return 5763; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XP, QuartzStairs::Half::Top, QuartzStairs::Shape::InnerRight).ID: return 5765; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XP, QuartzStairs::Half::Top, QuartzStairs::Shape::OuterLeft).ID: return 5767; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XP, QuartzStairs::Half::Top, QuartzStairs::Shape::OuterRight).ID: return 5769; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XP, QuartzStairs::Half::Bottom, QuartzStairs::Shape::Straight).ID: return 5771; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XP, QuartzStairs::Half::Bottom, QuartzStairs::Shape::InnerLeft).ID: return 5773; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XP, QuartzStairs::Half::Bottom, QuartzStairs::Shape::InnerRight).ID: return 5775; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XP, QuartzStairs::Half::Bottom, QuartzStairs::Shape::OuterLeft).ID: return 5777; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XP, QuartzStairs::Half::Bottom, QuartzStairs::Shape::OuterRight).ID: return 5779; case Rail::Rail(Rail::Shape::NorthSouth).ID: return 3179; case Rail::Rail(Rail::Shape::EastWest).ID: return 3180; case Rail::Rail(Rail::Shape::AscendingEast).ID: return 3181; case Rail::Rail(Rail::Shape::AscendingWest).ID: return 3182; case Rail::Rail(Rail::Shape::AscendingNorth).ID: return 3183; case Rail::Rail(Rail::Shape::AscendingSouth).ID: return 3184; case Rail::Rail(Rail::Shape::SouthEast).ID: return 3185; case Rail::Rail(Rail::Shape::SouthWest).ID: return 3186; case Rail::Rail(Rail::Shape::NorthWest).ID: return 3187; case Rail::Rail(Rail::Shape::NorthEast).ID: return 3188; case RedBanner::RedBanner(0).ID: return 7078; case RedBanner::RedBanner(1).ID: return 7079; case RedBanner::RedBanner(2).ID: return 7080; case RedBanner::RedBanner(3).ID: return 7081; case RedBanner::RedBanner(4).ID: return 7082; case RedBanner::RedBanner(5).ID: return 7083; case RedBanner::RedBanner(6).ID: return 7084; case RedBanner::RedBanner(7).ID: return 7085; case RedBanner::RedBanner(8).ID: return 7086; case RedBanner::RedBanner(9).ID: return 7087; case RedBanner::RedBanner(10).ID: return 7088; case RedBanner::RedBanner(11).ID: return 7089; case RedBanner::RedBanner(12).ID: return 7090; case RedBanner::RedBanner(13).ID: return 7091; case RedBanner::RedBanner(14).ID: return 7092; case RedBanner::RedBanner(15).ID: return 7093; case RedBed::RedBed(eBlockFace::BLOCK_FACE_ZM, true, RedBed::Part::Head).ID: return 972; case RedBed::RedBed(eBlockFace::BLOCK_FACE_ZM, true, RedBed::Part::Foot).ID: return 973; case RedBed::RedBed(eBlockFace::BLOCK_FACE_ZM, false, RedBed::Part::Head).ID: return 974; case RedBed::RedBed(eBlockFace::BLOCK_FACE_ZM, false, RedBed::Part::Foot).ID: return 975; case RedBed::RedBed(eBlockFace::BLOCK_FACE_ZP, true, RedBed::Part::Head).ID: return 976; case RedBed::RedBed(eBlockFace::BLOCK_FACE_ZP, true, RedBed::Part::Foot).ID: return 977; case RedBed::RedBed(eBlockFace::BLOCK_FACE_ZP, false, RedBed::Part::Head).ID: return 978; case RedBed::RedBed(eBlockFace::BLOCK_FACE_ZP, false, RedBed::Part::Foot).ID: return 979; case RedBed::RedBed(eBlockFace::BLOCK_FACE_XM, true, RedBed::Part::Head).ID: return 980; case RedBed::RedBed(eBlockFace::BLOCK_FACE_XM, true, RedBed::Part::Foot).ID: return 981; case RedBed::RedBed(eBlockFace::BLOCK_FACE_XM, false, RedBed::Part::Head).ID: return 982; case RedBed::RedBed(eBlockFace::BLOCK_FACE_XM, false, RedBed::Part::Foot).ID: return 983; case RedBed::RedBed(eBlockFace::BLOCK_FACE_XP, true, RedBed::Part::Head).ID: return 984; case RedBed::RedBed(eBlockFace::BLOCK_FACE_XP, true, RedBed::Part::Foot).ID: return 985; case RedBed::RedBed(eBlockFace::BLOCK_FACE_XP, false, RedBed::Part::Head).ID: return 986; case RedBed::RedBed(eBlockFace::BLOCK_FACE_XP, false, RedBed::Part::Foot).ID: return 987; case RedCarpet::RedCarpet().ID: return 6837; case RedConcrete::RedConcrete().ID: return 8391; case RedConcretePowder::RedConcretePowder().ID: return 8407; case RedGlazedTerracotta::RedGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 8369; case RedGlazedTerracotta::RedGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 8370; case RedGlazedTerracotta::RedGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 8371; case RedGlazedTerracotta::RedGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 8372; case RedMushroom::RedMushroom().ID: return 1122; case RedMushroomBlock::RedMushroomBlock(true, true, true, true, true, true).ID: return 4051; case RedMushroomBlock::RedMushroomBlock(true, true, true, true, true, false).ID: return 4052; case RedMushroomBlock::RedMushroomBlock(true, true, true, true, false, true).ID: return 4053; case RedMushroomBlock::RedMushroomBlock(true, true, true, true, false, false).ID: return 4054; case RedMushroomBlock::RedMushroomBlock(true, true, true, false, true, true).ID: return 4055; case RedMushroomBlock::RedMushroomBlock(true, true, true, false, true, false).ID: return 4056; case RedMushroomBlock::RedMushroomBlock(true, true, true, false, false, true).ID: return 4057; case RedMushroomBlock::RedMushroomBlock(true, true, true, false, false, false).ID: return 4058; case RedMushroomBlock::RedMushroomBlock(true, true, false, true, true, true).ID: return 4059; case RedMushroomBlock::RedMushroomBlock(true, true, false, true, true, false).ID: return 4060; case RedMushroomBlock::RedMushroomBlock(true, true, false, true, false, true).ID: return 4061; case RedMushroomBlock::RedMushroomBlock(true, true, false, true, false, false).ID: return 4062; case RedMushroomBlock::RedMushroomBlock(true, true, false, false, true, true).ID: return 4063; case RedMushroomBlock::RedMushroomBlock(true, true, false, false, true, false).ID: return 4064; case RedMushroomBlock::RedMushroomBlock(true, true, false, false, false, true).ID: return 4065; case RedMushroomBlock::RedMushroomBlock(true, true, false, false, false, false).ID: return 4066; case RedMushroomBlock::RedMushroomBlock(true, false, true, true, true, true).ID: return 4067; case RedMushroomBlock::RedMushroomBlock(true, false, true, true, true, false).ID: return 4068; case RedMushroomBlock::RedMushroomBlock(true, false, true, true, false, true).ID: return 4069; case RedMushroomBlock::RedMushroomBlock(true, false, true, true, false, false).ID: return 4070; case RedMushroomBlock::RedMushroomBlock(true, false, true, false, true, true).ID: return 4071; case RedMushroomBlock::RedMushroomBlock(true, false, true, false, true, false).ID: return 4072; case RedMushroomBlock::RedMushroomBlock(true, false, true, false, false, true).ID: return 4073; case RedMushroomBlock::RedMushroomBlock(true, false, true, false, false, false).ID: return 4074; case RedMushroomBlock::RedMushroomBlock(true, false, false, true, true, true).ID: return 4075; case RedMushroomBlock::RedMushroomBlock(true, false, false, true, true, false).ID: return 4076; case RedMushroomBlock::RedMushroomBlock(true, false, false, true, false, true).ID: return 4077; case RedMushroomBlock::RedMushroomBlock(true, false, false, true, false, false).ID: return 4078; case RedMushroomBlock::RedMushroomBlock(true, false, false, false, true, true).ID: return 4079; case RedMushroomBlock::RedMushroomBlock(true, false, false, false, true, false).ID: return 4080; case RedMushroomBlock::RedMushroomBlock(true, false, false, false, false, true).ID: return 4081; case RedMushroomBlock::RedMushroomBlock(true, false, false, false, false, false).ID: return 4082; case RedMushroomBlock::RedMushroomBlock(false, true, true, true, true, true).ID: return 4083; case RedMushroomBlock::RedMushroomBlock(false, true, true, true, true, false).ID: return 4084; case RedMushroomBlock::RedMushroomBlock(false, true, true, true, false, true).ID: return 4085; case RedMushroomBlock::RedMushroomBlock(false, true, true, true, false, false).ID: return 4086; case RedMushroomBlock::RedMushroomBlock(false, true, true, false, true, true).ID: return 4087; case RedMushroomBlock::RedMushroomBlock(false, true, true, false, true, false).ID: return 4088; case RedMushroomBlock::RedMushroomBlock(false, true, true, false, false, true).ID: return 4089; case RedMushroomBlock::RedMushroomBlock(false, true, true, false, false, false).ID: return 4090; case RedMushroomBlock::RedMushroomBlock(false, true, false, true, true, true).ID: return 4091; case RedMushroomBlock::RedMushroomBlock(false, true, false, true, true, false).ID: return 4092; case RedMushroomBlock::RedMushroomBlock(false, true, false, true, false, true).ID: return 4093; case RedMushroomBlock::RedMushroomBlock(false, true, false, true, false, false).ID: return 4094; case RedMushroomBlock::RedMushroomBlock(false, true, false, false, true, true).ID: return 4095; case RedMushroomBlock::RedMushroomBlock(false, true, false, false, true, false).ID: return 4096; case RedMushroomBlock::RedMushroomBlock(false, true, false, false, false, true).ID: return 4097; case RedMushroomBlock::RedMushroomBlock(false, true, false, false, false, false).ID: return 4098; case RedMushroomBlock::RedMushroomBlock(false, false, true, true, true, true).ID: return 4099; case RedMushroomBlock::RedMushroomBlock(false, false, true, true, true, false).ID: return 4100; case RedMushroomBlock::RedMushroomBlock(false, false, true, true, false, true).ID: return 4101; case RedMushroomBlock::RedMushroomBlock(false, false, true, true, false, false).ID: return 4102; case RedMushroomBlock::RedMushroomBlock(false, false, true, false, true, true).ID: return 4103; case RedMushroomBlock::RedMushroomBlock(false, false, true, false, true, false).ID: return 4104; case RedMushroomBlock::RedMushroomBlock(false, false, true, false, false, true).ID: return 4105; case RedMushroomBlock::RedMushroomBlock(false, false, true, false, false, false).ID: return 4106; case RedMushroomBlock::RedMushroomBlock(false, false, false, true, true, true).ID: return 4107; case RedMushroomBlock::RedMushroomBlock(false, false, false, true, true, false).ID: return 4108; case RedMushroomBlock::RedMushroomBlock(false, false, false, true, false, true).ID: return 4109; case RedMushroomBlock::RedMushroomBlock(false, false, false, true, false, false).ID: return 4110; case RedMushroomBlock::RedMushroomBlock(false, false, false, false, true, true).ID: return 4111; case RedMushroomBlock::RedMushroomBlock(false, false, false, false, true, false).ID: return 4112; case RedMushroomBlock::RedMushroomBlock(false, false, false, false, false, true).ID: return 4113; case RedMushroomBlock::RedMushroomBlock(false, false, false, false, false, false).ID: return 4114; case RedNetherBricks::RedNetherBricks().ID: return 8194; case RedSand::RedSand().ID: return 67; case RedSandstone::RedSandstone().ID: return 7174; case RedSandstoneSlab::RedSandstoneSlab(RedSandstoneSlab::Type::Top).ID: return 7342; case RedSandstoneSlab::RedSandstoneSlab(RedSandstoneSlab::Type::Bottom).ID: return 7344; case RedSandstoneSlab::RedSandstoneSlab(RedSandstoneSlab::Type::Double).ID: return 7346; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::Straight).ID: return 7178; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::InnerLeft).ID: return 7180; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::InnerRight).ID: return 7182; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::OuterLeft).ID: return 7184; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::OuterRight).ID: return 7186; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::Straight).ID: return 7188; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::InnerLeft).ID: return 7190; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::InnerRight).ID: return 7192; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::OuterLeft).ID: return 7194; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::OuterRight).ID: return 7196; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::Straight).ID: return 7198; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::InnerLeft).ID: return 7200; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::InnerRight).ID: return 7202; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::OuterLeft).ID: return 7204; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::OuterRight).ID: return 7206; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::Straight).ID: return 7208; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::InnerLeft).ID: return 7210; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::InnerRight).ID: return 7212; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::OuterLeft).ID: return 7214; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::OuterRight).ID: return 7216; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::Straight).ID: return 7218; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::InnerLeft).ID: return 7220; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::InnerRight).ID: return 7222; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::OuterLeft).ID: return 7224; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::OuterRight).ID: return 7226; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::Straight).ID: return 7228; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::InnerLeft).ID: return 7230; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::InnerRight).ID: return 7232; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::OuterLeft).ID: return 7234; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::OuterRight).ID: return 7236; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::Straight).ID: return 7238; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::InnerLeft).ID: return 7240; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::InnerRight).ID: return 7242; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::OuterLeft).ID: return 7244; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::OuterRight).ID: return 7246; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::Straight).ID: return 7248; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::InnerLeft).ID: return 7250; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::InnerRight).ID: return 7252; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::OuterLeft).ID: return 7254; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::OuterRight).ID: return 7256; case RedShulkerBox::RedShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 8301; case RedShulkerBox::RedShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 8302; case RedShulkerBox::RedShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 8303; case RedShulkerBox::RedShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 8304; case RedShulkerBox::RedShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 8305; case RedShulkerBox::RedShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 8306; case RedStainedGlass::RedStainedGlass().ID: return 3591; case RedStainedGlassPane::RedStainedGlassPane(true, true, true, true).ID: return 6270; case RedStainedGlassPane::RedStainedGlassPane(true, true, true, false).ID: return 6271; case RedStainedGlassPane::RedStainedGlassPane(true, true, false, true).ID: return 6274; case RedStainedGlassPane::RedStainedGlassPane(true, true, false, false).ID: return 6275; case RedStainedGlassPane::RedStainedGlassPane(true, false, true, true).ID: return 6278; case RedStainedGlassPane::RedStainedGlassPane(true, false, true, false).ID: return 6279; case RedStainedGlassPane::RedStainedGlassPane(true, false, false, true).ID: return 6282; case RedStainedGlassPane::RedStainedGlassPane(true, false, false, false).ID: return 6283; case RedStainedGlassPane::RedStainedGlassPane(false, true, true, true).ID: return 6286; case RedStainedGlassPane::RedStainedGlassPane(false, true, true, false).ID: return 6287; case RedStainedGlassPane::RedStainedGlassPane(false, true, false, true).ID: return 6290; case RedStainedGlassPane::RedStainedGlassPane(false, true, false, false).ID: return 6291; case RedStainedGlassPane::RedStainedGlassPane(false, false, true, true).ID: return 6294; case RedStainedGlassPane::RedStainedGlassPane(false, false, true, false).ID: return 6295; case RedStainedGlassPane::RedStainedGlassPane(false, false, false, true).ID: return 6298; case RedStainedGlassPane::RedStainedGlassPane(false, false, false, false).ID: return 6299; case RedTerracotta::RedTerracotta().ID: return 5818; case RedTulip::RedTulip().ID: return 1116; case RedWallBanner::RedWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 7166; case RedWallBanner::RedWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 7167; case RedWallBanner::RedWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 7168; case RedWallBanner::RedWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 7169; case RedWool::RedWool().ID: return 1097; case RedstoneBlock::RedstoneBlock().ID: return 5683; case RedstoneLamp::RedstoneLamp(true).ID: return 4636; case RedstoneLamp::RedstoneLamp(false).ID: return 4637; case RedstoneOre::RedstoneOre(true).ID: return 3379; case RedstoneOre::RedstoneOre(false).ID: return 3380; case RedstoneTorch::RedstoneTorch(true).ID: return 3381; case RedstoneTorch::RedstoneTorch(false).ID: return 3382; case RedstoneWallTorch::RedstoneWallTorch(eBlockFace::BLOCK_FACE_ZM, true).ID: return 3383; case RedstoneWallTorch::RedstoneWallTorch(eBlockFace::BLOCK_FACE_ZM, false).ID: return 3384; case RedstoneWallTorch::RedstoneWallTorch(eBlockFace::BLOCK_FACE_ZP, true).ID: return 3385; case RedstoneWallTorch::RedstoneWallTorch(eBlockFace::BLOCK_FACE_ZP, false).ID: return 3386; case RedstoneWallTorch::RedstoneWallTorch(eBlockFace::BLOCK_FACE_XM, true).ID: return 3387; case RedstoneWallTorch::RedstoneWallTorch(eBlockFace::BLOCK_FACE_XM, false).ID: return 3388; case RedstoneWallTorch::RedstoneWallTorch(eBlockFace::BLOCK_FACE_XP, true).ID: return 3389; case RedstoneWallTorch::RedstoneWallTorch(eBlockFace::BLOCK_FACE_XP, false).ID: return 3390; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 0, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 1752; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 0, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 1753; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 0, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 1754; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 0, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 1755; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 0, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 1756; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 0, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 1757; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 0, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 1758; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 0, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 1759; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 0, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 1760; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 1, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 1761; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 1, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 1762; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 1, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 1763; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 1, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 1764; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 1, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 1765; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 1, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 1766; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 1, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 1767; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 1, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 1768; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 1, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 1769; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 2, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 1770; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 2, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 1771; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 2, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 1772; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 2, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 1773; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 2, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 1774; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 2, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 1775; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 2, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 1776; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 2, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 1777; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 2, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 1778; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 3, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 1779; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 3, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 1780; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 3, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 1781; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 3, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 1782; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 3, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 1783; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 3, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 1784; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 3, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 1785; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 3, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 1786; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 3, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 1787; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 4, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 1788; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 4, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 1789; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 4, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 1790; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 4, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 1791; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 4, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 1792; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 4, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 1793; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 4, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 1794; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 4, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 1795; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 4, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 1796; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 5, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 1797; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 5, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 1798; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 5, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 1799; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 5, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 1800; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 5, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 1801; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 5, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 1802; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 5, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 1803; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 5, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 1804; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 5, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 1805; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 6, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 1806; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 6, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 1807; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 6, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 1808; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 6, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 1809; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 6, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 1810; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 6, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 1811; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 6, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 1812; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 6, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 1813; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 6, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 1814; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 7, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 1815; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 7, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 1816; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 7, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 1817; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 7, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 1818; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 7, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 1819; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 7, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 1820; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 7, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 1821; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 7, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 1822; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 7, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 1823; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 8, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 1824; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 8, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 1825; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 8, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 1826; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 8, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 1827; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 8, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 1828; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 8, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 1829; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 8, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 1830; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 8, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 1831; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 8, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 1832; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 9, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 1833; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 9, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 1834; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 9, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 1835; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 9, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 1836; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 9, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 1837; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 9, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 1838; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 9, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 1839; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 9, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 1840; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 9, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 1841; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 10, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 1842; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 10, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 1843; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 10, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 1844; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 10, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 1845; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 10, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 1846; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 10, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 1847; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 10, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 1848; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 10, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 1849; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 10, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 1850; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 11, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 1851; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 11, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 1852; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 11, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 1853; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 11, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 1854; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 11, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 1855; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 11, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 1856; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 11, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 1857; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 11, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 1858; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 11, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 1859; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 12, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 1860; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 12, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 1861; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 12, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 1862; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 12, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 1863; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 12, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 1864; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 12, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 1865; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 12, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 1866; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 12, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 1867; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 12, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 1868; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 13, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 1869; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 13, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 1870; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 13, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 1871; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 13, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 1872; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 13, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 1873; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 13, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 1874; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 13, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 1875; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 13, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 1876; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 13, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 1877; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 14, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 1878; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 14, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 1879; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 14, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 1880; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 14, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 1881; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 14, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 1882; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 14, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 1883; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 14, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 1884; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 14, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 1885; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 14, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 1886; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 15, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 1887; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 15, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 1888; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 15, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 1889; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 15, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 1890; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 15, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 1891; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 15, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 1892; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 15, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 1893; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 15, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 1894; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 15, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 1895; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 0, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 1896; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 0, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 1897; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 0, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 1898; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 0, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 1899; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 0, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 1900; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 0, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 1901; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 0, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 1902; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 0, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 1903; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 0, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 1904; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 1, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 1905; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 1, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 1906; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 1, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 1907; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 1, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 1908; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 1, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 1909; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 1, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 1910; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 1, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 1911; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 1, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 1912; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 1, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 1913; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 2, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 1914; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 2, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 1915; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 2, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 1916; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 2, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 1917; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 2, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 1918; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 2, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 1919; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 2, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 1920; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 2, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 1921; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 2, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 1922; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 3, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 1923; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 3, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 1924; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 3, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 1925; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 3, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 1926; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 3, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 1927; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 3, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 1928; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 3, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 1929; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 3, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 1930; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 3, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 1931; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 4, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 1932; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 4, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 1933; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 4, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 1934; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 4, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 1935; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 4, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 1936; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 4, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 1937; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 4, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 1938; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 4, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 1939; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 4, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 1940; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 5, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 1941; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 5, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 1942; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 5, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 1943; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 5, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 1944; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 5, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 1945; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 5, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 1946; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 5, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 1947; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 5, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 1948; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 5, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 1949; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 6, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 1950; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 6, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 1951; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 6, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 1952; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 6, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 1953; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 6, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 1954; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 6, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 1955; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 6, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 1956; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 6, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 1957; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 6, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 1958; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 7, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 1959; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 7, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 1960; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 7, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 1961; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 7, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 1962; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 7, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 1963; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 7, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 1964; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 7, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 1965; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 7, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 1966; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 7, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 1967; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 8, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 1968; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 8, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 1969; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 8, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 1970; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 8, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 1971; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 8, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 1972; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 8, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 1973; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 8, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 1974; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 8, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 1975; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 8, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 1976; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 9, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 1977; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 9, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 1978; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 9, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 1979; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 9, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 1980; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 9, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 1981; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 9, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 1982; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 9, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 1983; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 9, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 1984; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 9, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 1985; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 10, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 1986; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 10, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 1987; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 10, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 1988; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 10, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 1989; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 10, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 1990; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 10, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 1991; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 10, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 1992; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 10, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 1993; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 10, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 1994; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 11, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 1995; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 11, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 1996; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 11, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 1997; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 11, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 1998; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 11, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 1999; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 11, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2000; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 11, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2001; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 11, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2002; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 11, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2003; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 12, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2004; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 12, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2005; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 12, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2006; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 12, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2007; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 12, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2008; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 12, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2009; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 12, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2010; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 12, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2011; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 12, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2012; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 13, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2013; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 13, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2014; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 13, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2015; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 13, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2016; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 13, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2017; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 13, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2018; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 13, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2019; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 13, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2020; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 13, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2021; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 14, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2022; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 14, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2023; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 14, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2024; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 14, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2025; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 14, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2026; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 14, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2027; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 14, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2028; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 14, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2029; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 14, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2030; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 15, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2031; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 15, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2032; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 15, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2033; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 15, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2034; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 15, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2035; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 15, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2036; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 15, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2037; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 15, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2038; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 15, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2039; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 0, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2040; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 0, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2041; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 0, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2042; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 0, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2043; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 0, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2044; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 0, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2045; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 0, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2046; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 0, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2047; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 0, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2048; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 1, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2049; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 1, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2050; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 1, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2051; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 1, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2052; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 1, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2053; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 1, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2054; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 1, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2055; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 1, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2056; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 1, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2057; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 2, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2058; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 2, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2059; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 2, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2060; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 2, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2061; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 2, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2062; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 2, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2063; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 2, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2064; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 2, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2065; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 2, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2066; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 3, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2067; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 3, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2068; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 3, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2069; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 3, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2070; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 3, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2071; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 3, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2072; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 3, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2073; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 3, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2074; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 3, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2075; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 4, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2076; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 4, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2077; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 4, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2078; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 4, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2079; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 4, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2080; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 4, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2081; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 4, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2082; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 4, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2083; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 4, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2084; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 5, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2085; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 5, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2086; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 5, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2087; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 5, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2088; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 5, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2089; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 5, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2090; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 5, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2091; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 5, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2092; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 5, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2093; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 6, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2094; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 6, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2095; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 6, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2096; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 6, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2097; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 6, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2098; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 6, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2099; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 6, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2100; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 6, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2101; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 6, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2102; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 7, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2103; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 7, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2104; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 7, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2105; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 7, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2106; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 7, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2107; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 7, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2108; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 7, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2109; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 7, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2110; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 7, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2111; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 8, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2112; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 8, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2113; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 8, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2114; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 8, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2115; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 8, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2116; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 8, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2117; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 8, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2118; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 8, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2119; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 8, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2120; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 9, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2121; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 9, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2122; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 9, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2123; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 9, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2124; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 9, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2125; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 9, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2126; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 9, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2127; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 9, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2128; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 9, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2129; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 10, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2130; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 10, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2131; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 10, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2132; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 10, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2133; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 10, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2134; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 10, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2135; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 10, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2136; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 10, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2137; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 10, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2138; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 11, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2139; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 11, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2140; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 11, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2141; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 11, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2142; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 11, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2143; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 11, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2144; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 11, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2145; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 11, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2146; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 11, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2147; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 12, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2148; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 12, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2149; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 12, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2150; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 12, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2151; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 12, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2152; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 12, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2153; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 12, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2154; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 12, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2155; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 12, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2156; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 13, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2157; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 13, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2158; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 13, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2159; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 13, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2160; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 13, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2161; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 13, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2162; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 13, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2163; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 13, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2164; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 13, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2165; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 14, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2166; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 14, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2167; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 14, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2168; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 14, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2169; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 14, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2170; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 14, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2171; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 14, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2172; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 14, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2173; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 14, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2174; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 15, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2175; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 15, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2176; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 15, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2177; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 15, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2178; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 15, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2179; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 15, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2180; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 15, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2181; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 15, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2182; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 15, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2183; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 0, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2184; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 0, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2185; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 0, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2186; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 0, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2187; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 0, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2188; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 0, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2189; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 0, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2190; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 0, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2191; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 0, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2192; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 1, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2193; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 1, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2194; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 1, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2195; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 1, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2196; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 1, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2197; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 1, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2198; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 1, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2199; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 1, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2200; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 1, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2201; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 2, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2202; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 2, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2203; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 2, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2204; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 2, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2205; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 2, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2206; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 2, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2207; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 2, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2208; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 2, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2209; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 2, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2210; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 3, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2211; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 3, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2212; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 3, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2213; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 3, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2214; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 3, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2215; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 3, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2216; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 3, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2217; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 3, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2218; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 3, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2219; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 4, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2220; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 4, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2221; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 4, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2222; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 4, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2223; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 4, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2224; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 4, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2225; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 4, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2226; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 4, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2227; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 4, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2228; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 5, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2229; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 5, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2230; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 5, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2231; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 5, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2232; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 5, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2233; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 5, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2234; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 5, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2235; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 5, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2236; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 5, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2237; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 6, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2238; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 6, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2239; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 6, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2240; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 6, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2241; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 6, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2242; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 6, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2243; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 6, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2244; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 6, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2245; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 6, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2246; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 7, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2247; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 7, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2248; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 7, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2249; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 7, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2250; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 7, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2251; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 7, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2252; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 7, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2253; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 7, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2254; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 7, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2255; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 8, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2256; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 8, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2257; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 8, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2258; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 8, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2259; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 8, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2260; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 8, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2261; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 8, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2262; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 8, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2263; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 8, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2264; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 9, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2265; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 9, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2266; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 9, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2267; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 9, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2268; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 9, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2269; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 9, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2270; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 9, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2271; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 9, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2272; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 9, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2273; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 10, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2274; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 10, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2275; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 10, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2276; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 10, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2277; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 10, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2278; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 10, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2279; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 10, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2280; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 10, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2281; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 10, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2282; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 11, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2283; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 11, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2284; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 11, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2285; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 11, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2286; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 11, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2287; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 11, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2288; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 11, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2289; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 11, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2290; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 11, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2291; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 12, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2292; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 12, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2293; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 12, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2294; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 12, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2295; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 12, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2296; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 12, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2297; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 12, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2298; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 12, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2299; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 12, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2300; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 13, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2301; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 13, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2302; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 13, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2303; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 13, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2304; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 13, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2305; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 13, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2306; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 13, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2307; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 13, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2308; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 13, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2309; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 14, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2310; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 14, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2311; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 14, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2312; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 14, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2313; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 14, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2314; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 14, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2315; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 14, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2316; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 14, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2317; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 14, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2318; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 15, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2319; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 15, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2320; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 15, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2321; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 15, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2322; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 15, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2323; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 15, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2324; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 15, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2325; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 15, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2326; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 15, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2327; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 0, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2328; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 0, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2329; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 0, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2330; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 0, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2331; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 0, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2332; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 0, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2333; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 0, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2334; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 0, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2335; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 0, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2336; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 1, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2337; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 1, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2338; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 1, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2339; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 1, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2340; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 1, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2341; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 1, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2342; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 1, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2343; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 1, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2344; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 1, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2345; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 2, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2346; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 2, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2347; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 2, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2348; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 2, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2349; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 2, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2350; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 2, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2351; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 2, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2352; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 2, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2353; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 2, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2354; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 3, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2355; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 3, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2356; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 3, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2357; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 3, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2358; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 3, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2359; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 3, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2360; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 3, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2361; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 3, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2362; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 3, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2363; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 4, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2364; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 4, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2365; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 4, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2366; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 4, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2367; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 4, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2368; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 4, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2369; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 4, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2370; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 4, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2371; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 4, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2372; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 5, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2373; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 5, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2374; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 5, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2375; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 5, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2376; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 5, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2377; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 5, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2378; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 5, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2379; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 5, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2380; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 5, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2381; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 6, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2382; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 6, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2383; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 6, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2384; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 6, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2385; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 6, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2386; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 6, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2387; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 6, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2388; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 6, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2389; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 6, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2390; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 7, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2391; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 7, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2392; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 7, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2393; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 7, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2394; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 7, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2395; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 7, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2396; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 7, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2397; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 7, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2398; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 7, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2399; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 8, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2400; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 8, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2401; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 8, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2402; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 8, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2403; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 8, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2404; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 8, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2405; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 8, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2406; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 8, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2407; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 8, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2408; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 9, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2409; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 9, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2410; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 9, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2411; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 9, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2412; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 9, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2413; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 9, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2414; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 9, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2415; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 9, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2416; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 9, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2417; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 10, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2418; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 10, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2419; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 10, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2420; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 10, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2421; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 10, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2422; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 10, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2423; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 10, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2424; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 10, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2425; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 10, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2426; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 11, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2427; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 11, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2428; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 11, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2429; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 11, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2430; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 11, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2431; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 11, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2432; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 11, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2433; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 11, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2434; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 11, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2435; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 12, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2436; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 12, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2437; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 12, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2438; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 12, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2439; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 12, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2440; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 12, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2441; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 12, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2442; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 12, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2443; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 12, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2444; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 13, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2445; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 13, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2446; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 13, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2447; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 13, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2448; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 13, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2449; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 13, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2450; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 13, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2451; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 13, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2452; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 13, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2453; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 14, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2454; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 14, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2455; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 14, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2456; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 14, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2457; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 14, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2458; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 14, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2459; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 14, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2460; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 14, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2461; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 14, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2462; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 15, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2463; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 15, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2464; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 15, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2465; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 15, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2466; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 15, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2467; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 15, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2468; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 15, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2469; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 15, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2470; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 15, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2471; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 0, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2472; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 0, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2473; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 0, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2474; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 0, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2475; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 0, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2476; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 0, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2477; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 0, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2478; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 0, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2479; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 0, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2480; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 1, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2481; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 1, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2482; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 1, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2483; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 1, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2484; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 1, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2485; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 1, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2486; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 1, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2487; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 1, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2488; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 1, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2489; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 2, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2490; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 2, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2491; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 2, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2492; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 2, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2493; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 2, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2494; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 2, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2495; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 2, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2496; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 2, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2497; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 2, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2498; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 3, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2499; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 3, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2500; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 3, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2501; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 3, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2502; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 3, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2503; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 3, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2504; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 3, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2505; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 3, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2506; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 3, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2507; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 4, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2508; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 4, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2509; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 4, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2510; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 4, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2511; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 4, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2512; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 4, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2513; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 4, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2514; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 4, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2515; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 4, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2516; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 5, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2517; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 5, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2518; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 5, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2519; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 5, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2520; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 5, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2521; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 5, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2522; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 5, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2523; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 5, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2524; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 5, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2525; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 6, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2526; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 6, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2527; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 6, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2528; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 6, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2529; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 6, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2530; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 6, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2531; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 6, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2532; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 6, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2533; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 6, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2534; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 7, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2535; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 7, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2536; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 7, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2537; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 7, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2538; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 7, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2539; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 7, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2540; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 7, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2541; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 7, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2542; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 7, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2543; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 8, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2544; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 8, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2545; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 8, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2546; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 8, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2547; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 8, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2548; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 8, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2549; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 8, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2550; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 8, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2551; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 8, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2552; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 9, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2553; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 9, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2554; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 9, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2555; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 9, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2556; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 9, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2557; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 9, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2558; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 9, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2559; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 9, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2560; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 9, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2561; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 10, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2562; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 10, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2563; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 10, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2564; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 10, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2565; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 10, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2566; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 10, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2567; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 10, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2568; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 10, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2569; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 10, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2570; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 11, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2571; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 11, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2572; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 11, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2573; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 11, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2574; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 11, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2575; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 11, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2576; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 11, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2577; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 11, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2578; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 11, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2579; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 12, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2580; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 12, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2581; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 12, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2582; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 12, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2583; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 12, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2584; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 12, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2585; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 12, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2586; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 12, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2587; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 12, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2588; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 13, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2589; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 13, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2590; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 13, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2591; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 13, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2592; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 13, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2593; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 13, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2594; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 13, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2595; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 13, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2596; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 13, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2597; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 14, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2598; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 14, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2599; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 14, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2600; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 14, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2601; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 14, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2602; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 14, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2603; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 14, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2604; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 14, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2605; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 14, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2606; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 15, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2607; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 15, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2608; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 15, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2609; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 15, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2610; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 15, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2611; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 15, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2612; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 15, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2613; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 15, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2614; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 15, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2615; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 0, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2616; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 0, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2617; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 0, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2618; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 0, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2619; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 0, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2620; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 0, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2621; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 0, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2622; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 0, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2623; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 0, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2624; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 1, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2625; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 1, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2626; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 1, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2627; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 1, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2628; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 1, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2629; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 1, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2630; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 1, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2631; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 1, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2632; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 1, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2633; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 2, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2634; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 2, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2635; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 2, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2636; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 2, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2637; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 2, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2638; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 2, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2639; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 2, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2640; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 2, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2641; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 2, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2642; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 3, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2643; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 3, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2644; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 3, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2645; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 3, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2646; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 3, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2647; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 3, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2648; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 3, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2649; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 3, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2650; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 3, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2651; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 4, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2652; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 4, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2653; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 4, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2654; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 4, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2655; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 4, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2656; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 4, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2657; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 4, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2658; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 4, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2659; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 4, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2660; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 5, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2661; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 5, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2662; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 5, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2663; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 5, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2664; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 5, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2665; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 5, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2666; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 5, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2667; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 5, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2668; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 5, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2669; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 6, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2670; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 6, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2671; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 6, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2672; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 6, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2673; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 6, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2674; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 6, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2675; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 6, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2676; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 6, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2677; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 6, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2678; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 7, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2679; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 7, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2680; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 7, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2681; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 7, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2682; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 7, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2683; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 7, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2684; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 7, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2685; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 7, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2686; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 7, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2687; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 8, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2688; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 8, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2689; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 8, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2690; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 8, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2691; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 8, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2692; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 8, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2693; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 8, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2694; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 8, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2695; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 8, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2696; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 9, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2697; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 9, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2698; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 9, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2699; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 9, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2700; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 9, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2701; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 9, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2702; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 9, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2703; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 9, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2704; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 9, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2705; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 10, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2706; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 10, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2707; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 10, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2708; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 10, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2709; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 10, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2710; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 10, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2711; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 10, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2712; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 10, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2713; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 10, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2714; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 11, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2715; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 11, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2716; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 11, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2717; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 11, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2718; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 11, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2719; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 11, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2720; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 11, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2721; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 11, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2722; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 11, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2723; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 12, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2724; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 12, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2725; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 12, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2726; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 12, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2727; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 12, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2728; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 12, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2729; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 12, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2730; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 12, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2731; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 12, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2732; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 13, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2733; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 13, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2734; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 13, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2735; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 13, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2736; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 13, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2737; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 13, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2738; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 13, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2739; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 13, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2740; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 13, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2741; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 14, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2742; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 14, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2743; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 14, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2744; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 14, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2745; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 14, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2746; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 14, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2747; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 14, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2748; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 14, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2749; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 14, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2750; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 15, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2751; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 15, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2752; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 15, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2753; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 15, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2754; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 15, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2755; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 15, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2756; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 15, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2757; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 15, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2758; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 15, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2759; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 0, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2760; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 0, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2761; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 0, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2762; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 0, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2763; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 0, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2764; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 0, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2765; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 0, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2766; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 0, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2767; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 0, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2768; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 1, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2769; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 1, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2770; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 1, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2771; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 1, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2772; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 1, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2773; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 1, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2774; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 1, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2775; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 1, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2776; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 1, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2777; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 2, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2778; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 2, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2779; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 2, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2780; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 2, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2781; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 2, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2782; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 2, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2783; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 2, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2784; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 2, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2785; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 2, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2786; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 3, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2787; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 3, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2788; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 3, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2789; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 3, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2790; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 3, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2791; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 3, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2792; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 3, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2793; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 3, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2794; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 3, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2795; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 4, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2796; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 4, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2797; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 4, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2798; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 4, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2799; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 4, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2800; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 4, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2801; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 4, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2802; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 4, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2803; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 4, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2804; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 5, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2805; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 5, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2806; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 5, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2807; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 5, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2808; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 5, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2809; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 5, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2810; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 5, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2811; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 5, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2812; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 5, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2813; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 6, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2814; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 6, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2815; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 6, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2816; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 6, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2817; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 6, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2818; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 6, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2819; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 6, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2820; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 6, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2821; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 6, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2822; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 7, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2823; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 7, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2824; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 7, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2825; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 7, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2826; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 7, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2827; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 7, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2828; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 7, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2829; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 7, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2830; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 7, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2831; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 8, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2832; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 8, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2833; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 8, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2834; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 8, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2835; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 8, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2836; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 8, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2837; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 8, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2838; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 8, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2839; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 8, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2840; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 9, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2841; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 9, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2842; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 9, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2843; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 9, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2844; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 9, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2845; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 9, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2846; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 9, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2847; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 9, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2848; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 9, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2849; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 10, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2850; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 10, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2851; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 10, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2852; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 10, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2853; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 10, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2854; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 10, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2855; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 10, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2856; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 10, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2857; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 10, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2858; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 11, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2859; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 11, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2860; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 11, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2861; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 11, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2862; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 11, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2863; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 11, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2864; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 11, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2865; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 11, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2866; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 11, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2867; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 12, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2868; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 12, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2869; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 12, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2870; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 12, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2871; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 12, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2872; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 12, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2873; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 12, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2874; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 12, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2875; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 12, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2876; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 13, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2877; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 13, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2878; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 13, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2879; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 13, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2880; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 13, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2881; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 13, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2882; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 13, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2883; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 13, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2884; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 13, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2885; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 14, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2886; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 14, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2887; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 14, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2888; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 14, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2889; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 14, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2890; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 14, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2891; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 14, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2892; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 14, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2893; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 14, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2894; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 15, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2895; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 15, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2896; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 15, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2897; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 15, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2898; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 15, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2899; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 15, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2900; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 15, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2901; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 15, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2902; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 15, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2903; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 0, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2904; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 0, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2905; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 0, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2906; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 0, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2907; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 0, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2908; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 0, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2909; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 0, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2910; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 0, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2911; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 0, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2912; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 1, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2913; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 1, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2914; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 1, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2915; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 1, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2916; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 1, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2917; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 1, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2918; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 1, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2919; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 1, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2920; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 1, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2921; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 2, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2922; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 2, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2923; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 2, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2924; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 2, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2925; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 2, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2926; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 2, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2927; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 2, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2928; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 2, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2929; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 2, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2930; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 3, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2931; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 3, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2932; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 3, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2933; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 3, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2934; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 3, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2935; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 3, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2936; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 3, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2937; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 3, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2938; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 3, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2939; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 4, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2940; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 4, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2941; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 4, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2942; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 4, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2943; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 4, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2944; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 4, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2945; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 4, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2946; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 4, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2947; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 4, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2948; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 5, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2949; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 5, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2950; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 5, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2951; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 5, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2952; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 5, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2953; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 5, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2954; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 5, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2955; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 5, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2956; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 5, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2957; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 6, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2958; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 6, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2959; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 6, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2960; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 6, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2961; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 6, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2962; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 6, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2963; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 6, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2964; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 6, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2965; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 6, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2966; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 7, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2967; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 7, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2968; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 7, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2969; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 7, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2970; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 7, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2971; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 7, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2972; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 7, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2973; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 7, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2974; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 7, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2975; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 8, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2976; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 8, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2977; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 8, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2978; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 8, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2979; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 8, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2980; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 8, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2981; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 8, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2982; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 8, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2983; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 8, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2984; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 9, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2985; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 9, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2986; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 9, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2987; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 9, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2988; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 9, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2989; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 9, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2990; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 9, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2991; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 9, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2992; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 9, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2993; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 10, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2994; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 10, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2995; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 10, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2996; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 10, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2997; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 10, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2998; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 10, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2999; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 10, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3000; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 10, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3001; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 10, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3002; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 11, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3003; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 11, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3004; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 11, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3005; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 11, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3006; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 11, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3007; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 11, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3008; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 11, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3009; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 11, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3010; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 11, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3011; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 12, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3012; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 12, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3013; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 12, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3014; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 12, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3015; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 12, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3016; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 12, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3017; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 12, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3018; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 12, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3019; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 12, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3020; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 13, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3021; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 13, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3022; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 13, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3023; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 13, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3024; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 13, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3025; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 13, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3026; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 13, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3027; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 13, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3028; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 13, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3029; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 14, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3030; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 14, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3031; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 14, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3032; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 14, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3033; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 14, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3034; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 14, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3035; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 14, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3036; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 14, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3037; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 14, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3038; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 15, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3039; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 15, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3040; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 15, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3041; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 15, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3042; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 15, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3043; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 15, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3044; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 15, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3045; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 15, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3046; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 15, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3047; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_ZM, true, true).ID: return 3513; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_ZM, true, false).ID: return 3514; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_ZM, false, true).ID: return 3515; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_ZM, false, false).ID: return 3516; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_ZP, true, true).ID: return 3517; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_ZP, true, false).ID: return 3518; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_ZP, false, true).ID: return 3519; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_ZP, false, false).ID: return 3520; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_XM, true, true).ID: return 3521; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_XM, true, false).ID: return 3522; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_XM, false, true).ID: return 3523; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_XM, false, false).ID: return 3524; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_XP, true, true).ID: return 3525; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_XP, true, false).ID: return 3526; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_XP, false, true).ID: return 3527; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_XP, false, false).ID: return 3528; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_ZM, true, true).ID: return 3529; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_ZM, true, false).ID: return 3530; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_ZM, false, true).ID: return 3531; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_ZM, false, false).ID: return 3532; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_ZP, true, true).ID: return 3533; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_ZP, true, false).ID: return 3534; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_ZP, false, true).ID: return 3535; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_ZP, false, false).ID: return 3536; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_XM, true, true).ID: return 3537; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_XM, true, false).ID: return 3538; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_XM, false, true).ID: return 3539; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_XM, false, false).ID: return 3540; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_XP, true, true).ID: return 3541; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_XP, true, false).ID: return 3542; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_XP, false, true).ID: return 3543; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_XP, false, false).ID: return 3544; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_ZM, true, true).ID: return 3545; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_ZM, true, false).ID: return 3546; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_ZM, false, true).ID: return 3547; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_ZM, false, false).ID: return 3548; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_ZP, true, true).ID: return 3549; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_ZP, true, false).ID: return 3550; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_ZP, false, true).ID: return 3551; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_ZP, false, false).ID: return 3552; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_XM, true, true).ID: return 3553; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_XM, true, false).ID: return 3554; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_XM, false, true).ID: return 3555; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_XM, false, false).ID: return 3556; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_XP, true, true).ID: return 3557; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_XP, true, false).ID: return 3558; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_XP, false, true).ID: return 3559; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_XP, false, false).ID: return 3560; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_ZM, true, true).ID: return 3561; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_ZM, true, false).ID: return 3562; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_ZM, false, true).ID: return 3563; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_ZM, false, false).ID: return 3564; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_ZP, true, true).ID: return 3565; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_ZP, true, false).ID: return 3566; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_ZP, false, true).ID: return 3567; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_ZP, false, false).ID: return 3568; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_XM, true, true).ID: return 3569; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_XM, true, false).ID: return 3570; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_XM, false, true).ID: return 3571; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_XM, false, false).ID: return 3572; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_XP, true, true).ID: return 3573; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_XP, true, false).ID: return 3574; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_XP, false, true).ID: return 3575; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_XP, false, false).ID: return 3576; case RepeatingCommandBlock::RepeatingCommandBlock(true, eBlockFace::BLOCK_FACE_ZM).ID: return 8164; case RepeatingCommandBlock::RepeatingCommandBlock(true, eBlockFace::BLOCK_FACE_XP).ID: return 8165; case RepeatingCommandBlock::RepeatingCommandBlock(true, eBlockFace::BLOCK_FACE_ZP).ID: return 8166; case RepeatingCommandBlock::RepeatingCommandBlock(true, eBlockFace::BLOCK_FACE_XM).ID: return 8167; case RepeatingCommandBlock::RepeatingCommandBlock(true, eBlockFace::BLOCK_FACE_YP).ID: return 8168; case RepeatingCommandBlock::RepeatingCommandBlock(true, eBlockFace::BLOCK_FACE_YM).ID: return 8169; case RepeatingCommandBlock::RepeatingCommandBlock(false, eBlockFace::BLOCK_FACE_ZM).ID: return 8170; case RepeatingCommandBlock::RepeatingCommandBlock(false, eBlockFace::BLOCK_FACE_XP).ID: return 8171; case RepeatingCommandBlock::RepeatingCommandBlock(false, eBlockFace::BLOCK_FACE_ZP).ID: return 8172; case RepeatingCommandBlock::RepeatingCommandBlock(false, eBlockFace::BLOCK_FACE_XM).ID: return 8173; case RepeatingCommandBlock::RepeatingCommandBlock(false, eBlockFace::BLOCK_FACE_YP).ID: return 8174; case RepeatingCommandBlock::RepeatingCommandBlock(false, eBlockFace::BLOCK_FACE_YM).ID: return 8175; case RoseBush::RoseBush(RoseBush::Half::Upper).ID: return 6846; case RoseBush::RoseBush(RoseBush::Half::Lower).ID: return 6847; case Sand::Sand().ID: return 66; case Sandstone::Sandstone().ID: return 245; case SandstoneSlab::SandstoneSlab(SandstoneSlab::Type::Top).ID: return 7300; case SandstoneSlab::SandstoneSlab(SandstoneSlab::Type::Bottom).ID: return 7302; case SandstoneSlab::SandstoneSlab(SandstoneSlab::Type::Double).ID: return 7304; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SandstoneStairs::Half::Top, SandstoneStairs::Shape::Straight).ID: return 4651; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SandstoneStairs::Half::Top, SandstoneStairs::Shape::InnerLeft).ID: return 4653; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SandstoneStairs::Half::Top, SandstoneStairs::Shape::InnerRight).ID: return 4655; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SandstoneStairs::Half::Top, SandstoneStairs::Shape::OuterLeft).ID: return 4657; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SandstoneStairs::Half::Top, SandstoneStairs::Shape::OuterRight).ID: return 4659; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::Straight).ID: return 4661; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::InnerLeft).ID: return 4663; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::InnerRight).ID: return 4665; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::OuterLeft).ID: return 4667; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::OuterRight).ID: return 4669; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SandstoneStairs::Half::Top, SandstoneStairs::Shape::Straight).ID: return 4671; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SandstoneStairs::Half::Top, SandstoneStairs::Shape::InnerLeft).ID: return 4673; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SandstoneStairs::Half::Top, SandstoneStairs::Shape::InnerRight).ID: return 4675; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SandstoneStairs::Half::Top, SandstoneStairs::Shape::OuterLeft).ID: return 4677; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SandstoneStairs::Half::Top, SandstoneStairs::Shape::OuterRight).ID: return 4679; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::Straight).ID: return 4681; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::InnerLeft).ID: return 4683; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::InnerRight).ID: return 4685; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::OuterLeft).ID: return 4687; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::OuterRight).ID: return 4689; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XM, SandstoneStairs::Half::Top, SandstoneStairs::Shape::Straight).ID: return 4691; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XM, SandstoneStairs::Half::Top, SandstoneStairs::Shape::InnerLeft).ID: return 4693; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XM, SandstoneStairs::Half::Top, SandstoneStairs::Shape::InnerRight).ID: return 4695; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XM, SandstoneStairs::Half::Top, SandstoneStairs::Shape::OuterLeft).ID: return 4697; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XM, SandstoneStairs::Half::Top, SandstoneStairs::Shape::OuterRight).ID: return 4699; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XM, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::Straight).ID: return 4701; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XM, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::InnerLeft).ID: return 4703; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XM, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::InnerRight).ID: return 4705; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XM, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::OuterLeft).ID: return 4707; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XM, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::OuterRight).ID: return 4709; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XP, SandstoneStairs::Half::Top, SandstoneStairs::Shape::Straight).ID: return 4711; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XP, SandstoneStairs::Half::Top, SandstoneStairs::Shape::InnerLeft).ID: return 4713; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XP, SandstoneStairs::Half::Top, SandstoneStairs::Shape::InnerRight).ID: return 4715; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XP, SandstoneStairs::Half::Top, SandstoneStairs::Shape::OuterLeft).ID: return 4717; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XP, SandstoneStairs::Half::Top, SandstoneStairs::Shape::OuterRight).ID: return 4719; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XP, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::Straight).ID: return 4721; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XP, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::InnerLeft).ID: return 4723; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XP, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::InnerRight).ID: return 4725; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XP, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::OuterLeft).ID: return 4727; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XP, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::OuterRight).ID: return 4729; case SeaLantern::SeaLantern().ID: return 6819; case SeaPickle::SeaPickle(1).ID: return 8565; case SeaPickle::SeaPickle(2).ID: return 8567; case SeaPickle::SeaPickle(3).ID: return 8569; case SeaPickle::SeaPickle(4).ID: return 8571; case Seagrass::Seagrass().ID: return 1044; case ShulkerBox::ShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 8211; case ShulkerBox::ShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 8212; case ShulkerBox::ShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 8213; case ShulkerBox::ShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 8214; case ShulkerBox::ShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 8215; case ShulkerBox::ShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 8216; case OakSign::OakSign(0).ID: return 3076; case OakSign::OakSign(1).ID: return 3078; case OakSign::OakSign(2).ID: return 3080; case OakSign::OakSign(3).ID: return 3082; case OakSign::OakSign(4).ID: return 3084; case OakSign::OakSign(5).ID: return 3086; case OakSign::OakSign(6).ID: return 3088; case OakSign::OakSign(7).ID: return 3090; case OakSign::OakSign(8).ID: return 3092; case OakSign::OakSign(9).ID: return 3094; case OakSign::OakSign(10).ID: return 3096; case OakSign::OakSign(11).ID: return 3098; case OakSign::OakSign(12).ID: return 3100; case OakSign::OakSign(13).ID: return 3102; case OakSign::OakSign(14).ID: return 3104; case OakSign::OakSign(15).ID: return 3106; case SkeletonSkull::SkeletonSkull(0).ID: return 5451; case SkeletonSkull::SkeletonSkull(1).ID: return 5452; case SkeletonSkull::SkeletonSkull(2).ID: return 5453; case SkeletonSkull::SkeletonSkull(3).ID: return 5454; case SkeletonSkull::SkeletonSkull(4).ID: return 5455; case SkeletonSkull::SkeletonSkull(5).ID: return 5456; case SkeletonSkull::SkeletonSkull(6).ID: return 5457; case SkeletonSkull::SkeletonSkull(7).ID: return 5458; case SkeletonSkull::SkeletonSkull(8).ID: return 5459; case SkeletonSkull::SkeletonSkull(9).ID: return 5460; case SkeletonSkull::SkeletonSkull(10).ID: return 5461; case SkeletonSkull::SkeletonSkull(11).ID: return 5462; case SkeletonSkull::SkeletonSkull(12).ID: return 5463; case SkeletonSkull::SkeletonSkull(13).ID: return 5464; case SkeletonSkull::SkeletonSkull(14).ID: return 5465; case SkeletonSkull::SkeletonSkull(15).ID: return 5466; case SkeletonWallSkull::SkeletonWallSkull(eBlockFace::BLOCK_FACE_ZM).ID: return 5447; case SkeletonWallSkull::SkeletonWallSkull(eBlockFace::BLOCK_FACE_ZP).ID: return 5448; case SkeletonWallSkull::SkeletonWallSkull(eBlockFace::BLOCK_FACE_XM).ID: return 5449; case SkeletonWallSkull::SkeletonWallSkull(eBlockFace::BLOCK_FACE_XP).ID: return 5450; case SlimeBlock::SlimeBlock().ID: return 6492; case SmoothQuartz::SmoothQuartz().ID: return 7355; case SmoothRedSandstone::SmoothRedSandstone().ID: return 7356; case SmoothSandstone::SmoothSandstone().ID: return 7354; case SmoothStone::SmoothStone().ID: return 7353; case Snow::Snow(1).ID: return 3415; case Snow::Snow(2).ID: return 3416; case Snow::Snow(3).ID: return 3417; case Snow::Snow(4).ID: return 3418; case Snow::Snow(5).ID: return 3419; case Snow::Snow(6).ID: return 3420; case Snow::Snow(7).ID: return 3421; case Snow::Snow(8).ID: return 3422; case SnowBlock::SnowBlock().ID: return 3424; case SoulSand::SoulSand().ID: return 3494; case Spawner::Spawner().ID: return 1647; case Sponge::Sponge().ID: return 228; case SpruceButton::SpruceButton(SpruceButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5327; case SpruceButton::SpruceButton(SpruceButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5328; case SpruceButton::SpruceButton(SpruceButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5329; case SpruceButton::SpruceButton(SpruceButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5330; case SpruceButton::SpruceButton(SpruceButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, true).ID: return 5331; case SpruceButton::SpruceButton(SpruceButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, false).ID: return 5332; case SpruceButton::SpruceButton(SpruceButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, true).ID: return 5333; case SpruceButton::SpruceButton(SpruceButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, false).ID: return 5334; case SpruceButton::SpruceButton(SpruceButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5335; case SpruceButton::SpruceButton(SpruceButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5336; case SpruceButton::SpruceButton(SpruceButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5337; case SpruceButton::SpruceButton(SpruceButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5338; case SpruceButton::SpruceButton(SpruceButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, true).ID: return 5339; case SpruceButton::SpruceButton(SpruceButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, false).ID: return 5340; case SpruceButton::SpruceButton(SpruceButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, true).ID: return 5341; case SpruceButton::SpruceButton(SpruceButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, false).ID: return 5342; case SpruceButton::SpruceButton(SpruceButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5343; case SpruceButton::SpruceButton(SpruceButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5344; case SpruceButton::SpruceButton(SpruceButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5345; case SpruceButton::SpruceButton(SpruceButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5346; case SpruceButton::SpruceButton(SpruceButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, true).ID: return 5347; case SpruceButton::SpruceButton(SpruceButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, false).ID: return 5348; case SpruceButton::SpruceButton(SpruceButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, true).ID: return 5349; case SpruceButton::SpruceButton(SpruceButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, false).ID: return 5350; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, true, true).ID: return 7677; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, true, false).ID: return 7678; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, false, true).ID: return 7679; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, false, false).ID: return 7680; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, true, true).ID: return 7681; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, true, false).ID: return 7682; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, false, true).ID: return 7683; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, false, false).ID: return 7684; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, true, true).ID: return 7685; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, true, false).ID: return 7686; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, false, true).ID: return 7687; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, false, false).ID: return 7688; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, true, true).ID: return 7689; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, true, false).ID: return 7690; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, false, true).ID: return 7691; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, false, false).ID: return 7692; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, true, true).ID: return 7693; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, true, false).ID: return 7694; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, false, true).ID: return 7695; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, false, false).ID: return 7696; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, true, true).ID: return 7697; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, true, false).ID: return 7698; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, false, true).ID: return 7699; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, false, false).ID: return 7700; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, true, true).ID: return 7701; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, true, false).ID: return 7702; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, false, true).ID: return 7703; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, false, false).ID: return 7704; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, true, true).ID: return 7705; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, true, false).ID: return 7706; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, false, true).ID: return 7707; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, false, false).ID: return 7708; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, true, true).ID: return 7709; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, true, false).ID: return 7710; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, false, true).ID: return 7711; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, false, false).ID: return 7712; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, true, true).ID: return 7713; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, true, false).ID: return 7714; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, false, true).ID: return 7715; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, false, false).ID: return 7716; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, true, true).ID: return 7717; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, true, false).ID: return 7718; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, false, true).ID: return 7719; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, false, false).ID: return 7720; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, true, true).ID: return 7721; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, true, false).ID: return 7722; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, false, true).ID: return 7723; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, false, false).ID: return 7724; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, true, true).ID: return 7725; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, true, false).ID: return 7726; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, false, true).ID: return 7727; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, false, false).ID: return 7728; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, true, true).ID: return 7729; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, true, false).ID: return 7730; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, false, true).ID: return 7731; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, false, false).ID: return 7732; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, true, true).ID: return 7733; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, true, false).ID: return 7734; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, false, true).ID: return 7735; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, false, false).ID: return 7736; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, true, true).ID: return 7737; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, true, false).ID: return 7738; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, false, true).ID: return 7739; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, false, false).ID: return 7740; case SpruceFence::SpruceFence(true, true, true, true).ID: return 7519; case SpruceFence::SpruceFence(true, true, true, false).ID: return 7520; case SpruceFence::SpruceFence(true, true, false, true).ID: return 7523; case SpruceFence::SpruceFence(true, true, false, false).ID: return 7524; case SpruceFence::SpruceFence(true, false, true, true).ID: return 7527; case SpruceFence::SpruceFence(true, false, true, false).ID: return 7528; case SpruceFence::SpruceFence(true, false, false, true).ID: return 7531; case SpruceFence::SpruceFence(true, false, false, false).ID: return 7532; case SpruceFence::SpruceFence(false, true, true, true).ID: return 7535; case SpruceFence::SpruceFence(false, true, true, false).ID: return 7536; case SpruceFence::SpruceFence(false, true, false, true).ID: return 7539; case SpruceFence::SpruceFence(false, true, false, false).ID: return 7540; case SpruceFence::SpruceFence(false, false, true, true).ID: return 7543; case SpruceFence::SpruceFence(false, false, true, false).ID: return 7544; case SpruceFence::SpruceFence(false, false, false, true).ID: return 7547; case SpruceFence::SpruceFence(false, false, false, false).ID: return 7548; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZM, true, true, true).ID: return 7357; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZM, true, true, false).ID: return 7358; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZM, true, false, true).ID: return 7359; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZM, true, false, false).ID: return 7360; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, true).ID: return 7361; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, false).ID: return 7362; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, true).ID: return 7363; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, false).ID: return 7364; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZP, true, true, true).ID: return 7365; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZP, true, true, false).ID: return 7366; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZP, true, false, true).ID: return 7367; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZP, true, false, false).ID: return 7368; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, true).ID: return 7369; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, false).ID: return 7370; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, true).ID: return 7371; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, false).ID: return 7372; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XM, true, true, true).ID: return 7373; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XM, true, true, false).ID: return 7374; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XM, true, false, true).ID: return 7375; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XM, true, false, false).ID: return 7376; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, true).ID: return 7377; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, false).ID: return 7378; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, true).ID: return 7379; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, false).ID: return 7380; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XP, true, true, true).ID: return 7381; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XP, true, true, false).ID: return 7382; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XP, true, false, true).ID: return 7383; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XP, true, false, false).ID: return 7384; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, true).ID: return 7385; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, false).ID: return 7386; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, true).ID: return 7387; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, false).ID: return 7388; case SpruceLeaves::SpruceLeaves(1, true).ID: return 158; case SpruceLeaves::SpruceLeaves(1, false).ID: return 159; case SpruceLeaves::SpruceLeaves(2, true).ID: return 160; case SpruceLeaves::SpruceLeaves(2, false).ID: return 161; case SpruceLeaves::SpruceLeaves(3, true).ID: return 162; case SpruceLeaves::SpruceLeaves(3, false).ID: return 163; case SpruceLeaves::SpruceLeaves(4, true).ID: return 164; case SpruceLeaves::SpruceLeaves(4, false).ID: return 165; case SpruceLeaves::SpruceLeaves(5, true).ID: return 166; case SpruceLeaves::SpruceLeaves(5, false).ID: return 167; case SpruceLeaves::SpruceLeaves(6, true).ID: return 168; case SpruceLeaves::SpruceLeaves(6, false).ID: return 169; case SpruceLeaves::SpruceLeaves(7, true).ID: return 170; case SpruceLeaves::SpruceLeaves(7, false).ID: return 171; case SpruceLog::SpruceLog(SpruceLog::Axis::X).ID: return 75; case SpruceLog::SpruceLog(SpruceLog::Axis::Y).ID: return 76; case SpruceLog::SpruceLog(SpruceLog::Axis::Z).ID: return 77; case SprucePlanks::SprucePlanks().ID: return 16; case SprucePressurePlate::SprucePressurePlate(true).ID: return 3369; case SprucePressurePlate::SprucePressurePlate(false).ID: return 3370; case SpruceSapling::SpruceSapling(0).ID: return 23; case SpruceSapling::SpruceSapling(1).ID: return 24; case SpruceSlab::SpruceSlab(SpruceSlab::Type::Top).ID: return 7264; case SpruceSlab::SpruceSlab(SpruceSlab::Type::Bottom).ID: return 7266; case SpruceSlab::SpruceSlab(SpruceSlab::Type::Double).ID: return 7268; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZM, SpruceStairs::Half::Top, SpruceStairs::Shape::Straight).ID: return 4885; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZM, SpruceStairs::Half::Top, SpruceStairs::Shape::InnerLeft).ID: return 4887; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZM, SpruceStairs::Half::Top, SpruceStairs::Shape::InnerRight).ID: return 4889; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZM, SpruceStairs::Half::Top, SpruceStairs::Shape::OuterLeft).ID: return 4891; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZM, SpruceStairs::Half::Top, SpruceStairs::Shape::OuterRight).ID: return 4893; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZM, SpruceStairs::Half::Bottom, SpruceStairs::Shape::Straight).ID: return 4895; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZM, SpruceStairs::Half::Bottom, SpruceStairs::Shape::InnerLeft).ID: return 4897; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZM, SpruceStairs::Half::Bottom, SpruceStairs::Shape::InnerRight).ID: return 4899; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZM, SpruceStairs::Half::Bottom, SpruceStairs::Shape::OuterLeft).ID: return 4901; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZM, SpruceStairs::Half::Bottom, SpruceStairs::Shape::OuterRight).ID: return 4903; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZP, SpruceStairs::Half::Top, SpruceStairs::Shape::Straight).ID: return 4905; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZP, SpruceStairs::Half::Top, SpruceStairs::Shape::InnerLeft).ID: return 4907; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZP, SpruceStairs::Half::Top, SpruceStairs::Shape::InnerRight).ID: return 4909; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZP, SpruceStairs::Half::Top, SpruceStairs::Shape::OuterLeft).ID: return 4911; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZP, SpruceStairs::Half::Top, SpruceStairs::Shape::OuterRight).ID: return 4913; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZP, SpruceStairs::Half::Bottom, SpruceStairs::Shape::Straight).ID: return 4915; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZP, SpruceStairs::Half::Bottom, SpruceStairs::Shape::InnerLeft).ID: return 4917; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZP, SpruceStairs::Half::Bottom, SpruceStairs::Shape::InnerRight).ID: return 4919; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZP, SpruceStairs::Half::Bottom, SpruceStairs::Shape::OuterLeft).ID: return 4921; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZP, SpruceStairs::Half::Bottom, SpruceStairs::Shape::OuterRight).ID: return 4923; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XM, SpruceStairs::Half::Top, SpruceStairs::Shape::Straight).ID: return 4925; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XM, SpruceStairs::Half::Top, SpruceStairs::Shape::InnerLeft).ID: return 4927; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XM, SpruceStairs::Half::Top, SpruceStairs::Shape::InnerRight).ID: return 4929; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XM, SpruceStairs::Half::Top, SpruceStairs::Shape::OuterLeft).ID: return 4931; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XM, SpruceStairs::Half::Top, SpruceStairs::Shape::OuterRight).ID: return 4933; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XM, SpruceStairs::Half::Bottom, SpruceStairs::Shape::Straight).ID: return 4935; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XM, SpruceStairs::Half::Bottom, SpruceStairs::Shape::InnerLeft).ID: return 4937; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XM, SpruceStairs::Half::Bottom, SpruceStairs::Shape::InnerRight).ID: return 4939; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XM, SpruceStairs::Half::Bottom, SpruceStairs::Shape::OuterLeft).ID: return 4941; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XM, SpruceStairs::Half::Bottom, SpruceStairs::Shape::OuterRight).ID: return 4943; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XP, SpruceStairs::Half::Top, SpruceStairs::Shape::Straight).ID: return 4945; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XP, SpruceStairs::Half::Top, SpruceStairs::Shape::InnerLeft).ID: return 4947; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XP, SpruceStairs::Half::Top, SpruceStairs::Shape::InnerRight).ID: return 4949; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XP, SpruceStairs::Half::Top, SpruceStairs::Shape::OuterLeft).ID: return 4951; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XP, SpruceStairs::Half::Top, SpruceStairs::Shape::OuterRight).ID: return 4953; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XP, SpruceStairs::Half::Bottom, SpruceStairs::Shape::Straight).ID: return 4955; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XP, SpruceStairs::Half::Bottom, SpruceStairs::Shape::InnerLeft).ID: return 4957; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XP, SpruceStairs::Half::Bottom, SpruceStairs::Shape::InnerRight).ID: return 4959; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XP, SpruceStairs::Half::Bottom, SpruceStairs::Shape::OuterLeft).ID: return 4961; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XP, SpruceStairs::Half::Bottom, SpruceStairs::Shape::OuterRight).ID: return 4963; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZM, SpruceTrapdoor::Half::Top, true, true).ID: return 3658; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZM, SpruceTrapdoor::Half::Top, true, false).ID: return 3660; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZM, SpruceTrapdoor::Half::Top, false, true).ID: return 3662; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZM, SpruceTrapdoor::Half::Top, false, false).ID: return 3664; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZM, SpruceTrapdoor::Half::Bottom, true, true).ID: return 3666; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZM, SpruceTrapdoor::Half::Bottom, true, false).ID: return 3668; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZM, SpruceTrapdoor::Half::Bottom, false, true).ID: return 3670; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZM, SpruceTrapdoor::Half::Bottom, false, false).ID: return 3672; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZP, SpruceTrapdoor::Half::Top, true, true).ID: return 3674; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZP, SpruceTrapdoor::Half::Top, true, false).ID: return 3676; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZP, SpruceTrapdoor::Half::Top, false, true).ID: return 3678; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZP, SpruceTrapdoor::Half::Top, false, false).ID: return 3680; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZP, SpruceTrapdoor::Half::Bottom, true, true).ID: return 3682; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZP, SpruceTrapdoor::Half::Bottom, true, false).ID: return 3684; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZP, SpruceTrapdoor::Half::Bottom, false, true).ID: return 3686; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZP, SpruceTrapdoor::Half::Bottom, false, false).ID: return 3688; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XM, SpruceTrapdoor::Half::Top, true, true).ID: return 3690; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XM, SpruceTrapdoor::Half::Top, true, false).ID: return 3692; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XM, SpruceTrapdoor::Half::Top, false, true).ID: return 3694; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XM, SpruceTrapdoor::Half::Top, false, false).ID: return 3696; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XM, SpruceTrapdoor::Half::Bottom, true, true).ID: return 3698; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XM, SpruceTrapdoor::Half::Bottom, true, false).ID: return 3700; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XM, SpruceTrapdoor::Half::Bottom, false, true).ID: return 3702; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XM, SpruceTrapdoor::Half::Bottom, false, false).ID: return 3704; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XP, SpruceTrapdoor::Half::Top, true, true).ID: return 3706; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XP, SpruceTrapdoor::Half::Top, true, false).ID: return 3708; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XP, SpruceTrapdoor::Half::Top, false, true).ID: return 3710; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XP, SpruceTrapdoor::Half::Top, false, false).ID: return 3712; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XP, SpruceTrapdoor::Half::Bottom, true, true).ID: return 3714; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XP, SpruceTrapdoor::Half::Bottom, true, false).ID: return 3716; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XP, SpruceTrapdoor::Half::Bottom, false, true).ID: return 3718; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XP, SpruceTrapdoor::Half::Bottom, false, false).ID: return 3720; case SpruceWood::SpruceWood(SpruceWood::Axis::X).ID: return 111; case SpruceWood::SpruceWood(SpruceWood::Axis::Y).ID: return 112; case SpruceWood::SpruceWood(SpruceWood::Axis::Z).ID: return 113; case StickyPiston::StickyPiston(true, eBlockFace::BLOCK_FACE_ZM).ID: return 1028; case StickyPiston::StickyPiston(true, eBlockFace::BLOCK_FACE_XP).ID: return 1029; case StickyPiston::StickyPiston(true, eBlockFace::BLOCK_FACE_ZP).ID: return 1030; case StickyPiston::StickyPiston(true, eBlockFace::BLOCK_FACE_XM).ID: return 1031; case StickyPiston::StickyPiston(true, eBlockFace::BLOCK_FACE_YP).ID: return 1032; case StickyPiston::StickyPiston(true, eBlockFace::BLOCK_FACE_YM).ID: return 1033; case StickyPiston::StickyPiston(false, eBlockFace::BLOCK_FACE_ZM).ID: return 1034; case StickyPiston::StickyPiston(false, eBlockFace::BLOCK_FACE_XP).ID: return 1035; case StickyPiston::StickyPiston(false, eBlockFace::BLOCK_FACE_ZP).ID: return 1036; case StickyPiston::StickyPiston(false, eBlockFace::BLOCK_FACE_XM).ID: return 1037; case StickyPiston::StickyPiston(false, eBlockFace::BLOCK_FACE_YP).ID: return 1038; case StickyPiston::StickyPiston(false, eBlockFace::BLOCK_FACE_YM).ID: return 1039; case Stone::Stone().ID: return 1; case StoneBrickSlab::StoneBrickSlab(StoneBrickSlab::Type::Top).ID: return 7324; case StoneBrickSlab::StoneBrickSlab(StoneBrickSlab::Type::Bottom).ID: return 7326; case StoneBrickSlab::StoneBrickSlab(StoneBrickSlab::Type::Double).ID: return 7328; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::Straight).ID: return 4413; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::InnerLeft).ID: return 4415; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::InnerRight).ID: return 4417; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::OuterLeft).ID: return 4419; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::OuterRight).ID: return 4421; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::Straight).ID: return 4423; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::InnerLeft).ID: return 4425; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::InnerRight).ID: return 4427; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::OuterLeft).ID: return 4429; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::OuterRight).ID: return 4431; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::Straight).ID: return 4433; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::InnerLeft).ID: return 4435; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::InnerRight).ID: return 4437; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::OuterLeft).ID: return 4439; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::OuterRight).ID: return 4441; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::Straight).ID: return 4443; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::InnerLeft).ID: return 4445; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::InnerRight).ID: return 4447; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::OuterLeft).ID: return 4449; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::OuterRight).ID: return 4451; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XM, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::Straight).ID: return 4453; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XM, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::InnerLeft).ID: return 4455; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XM, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::InnerRight).ID: return 4457; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XM, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::OuterLeft).ID: return 4459; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XM, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::OuterRight).ID: return 4461; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XM, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::Straight).ID: return 4463; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XM, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::InnerLeft).ID: return 4465; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XM, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::InnerRight).ID: return 4467; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XM, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::OuterLeft).ID: return 4469; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XM, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::OuterRight).ID: return 4471; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XP, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::Straight).ID: return 4473; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XP, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::InnerLeft).ID: return 4475; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XP, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::InnerRight).ID: return 4477; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XP, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::OuterLeft).ID: return 4479; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XP, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::OuterRight).ID: return 4481; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XP, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::Straight).ID: return 4483; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XP, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::InnerLeft).ID: return 4485; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XP, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::InnerRight).ID: return 4487; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XP, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::OuterLeft).ID: return 4489; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XP, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::OuterRight).ID: return 4491; case StoneBricks::StoneBricks().ID: return 3983; case StoneButton::StoneButton(StoneButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, true).ID: return 3391; case StoneButton::StoneButton(StoneButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, false).ID: return 3392; case StoneButton::StoneButton(StoneButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, true).ID: return 3393; case StoneButton::StoneButton(StoneButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, false).ID: return 3394; case StoneButton::StoneButton(StoneButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, true).ID: return 3395; case StoneButton::StoneButton(StoneButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, false).ID: return 3396; case StoneButton::StoneButton(StoneButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, true).ID: return 3397; case StoneButton::StoneButton(StoneButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, false).ID: return 3398; case StoneButton::StoneButton(StoneButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, true).ID: return 3399; case StoneButton::StoneButton(StoneButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, false).ID: return 3400; case StoneButton::StoneButton(StoneButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, true).ID: return 3401; case StoneButton::StoneButton(StoneButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, false).ID: return 3402; case StoneButton::StoneButton(StoneButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, true).ID: return 3403; case StoneButton::StoneButton(StoneButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, false).ID: return 3404; case StoneButton::StoneButton(StoneButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, true).ID: return 3405; case StoneButton::StoneButton(StoneButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, false).ID: return 3406; case StoneButton::StoneButton(StoneButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, true).ID: return 3407; case StoneButton::StoneButton(StoneButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, false).ID: return 3408; case StoneButton::StoneButton(StoneButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, true).ID: return 3409; case StoneButton::StoneButton(StoneButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, false).ID: return 3410; case StoneButton::StoneButton(StoneButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, true).ID: return 3411; case StoneButton::StoneButton(StoneButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, false).ID: return 3412; case StoneButton::StoneButton(StoneButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, true).ID: return 3413; case StoneButton::StoneButton(StoneButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, false).ID: return 3414; case StonePressurePlate::StonePressurePlate(true).ID: return 3301; case StonePressurePlate::StonePressurePlate(false).ID: return 3302; case StoneSlab::StoneSlab(StoneSlab::Type::Top).ID: return 7294; case StoneSlab::StoneSlab(StoneSlab::Type::Bottom).ID: return 7296; case StoneSlab::StoneSlab(StoneSlab::Type::Double).ID: return 7298; case StrippedAcaciaLog::StrippedAcaciaLog(StrippedAcaciaLog::Axis::X).ID: return 99; case StrippedAcaciaLog::StrippedAcaciaLog(StrippedAcaciaLog::Axis::Y).ID: return 100; case StrippedAcaciaLog::StrippedAcaciaLog(StrippedAcaciaLog::Axis::Z).ID: return 101; case StrippedAcaciaWood::StrippedAcaciaWood(StrippedAcaciaWood::Axis::X).ID: return 138; case StrippedAcaciaWood::StrippedAcaciaWood(StrippedAcaciaWood::Axis::Y).ID: return 139; case StrippedAcaciaWood::StrippedAcaciaWood(StrippedAcaciaWood::Axis::Z).ID: return 140; case StrippedBirchLog::StrippedBirchLog(StrippedBirchLog::Axis::X).ID: return 93; case StrippedBirchLog::StrippedBirchLog(StrippedBirchLog::Axis::Y).ID: return 94; case StrippedBirchLog::StrippedBirchLog(StrippedBirchLog::Axis::Z).ID: return 95; case StrippedBirchWood::StrippedBirchWood(StrippedBirchWood::Axis::X).ID: return 132; case StrippedBirchWood::StrippedBirchWood(StrippedBirchWood::Axis::Y).ID: return 133; case StrippedBirchWood::StrippedBirchWood(StrippedBirchWood::Axis::Z).ID: return 134; case StrippedDarkOakLog::StrippedDarkOakLog(StrippedDarkOakLog::Axis::X).ID: return 102; case StrippedDarkOakLog::StrippedDarkOakLog(StrippedDarkOakLog::Axis::Y).ID: return 103; case StrippedDarkOakLog::StrippedDarkOakLog(StrippedDarkOakLog::Axis::Z).ID: return 104; case StrippedDarkOakWood::StrippedDarkOakWood(StrippedDarkOakWood::Axis::X).ID: return 141; case StrippedDarkOakWood::StrippedDarkOakWood(StrippedDarkOakWood::Axis::Y).ID: return 142; case StrippedDarkOakWood::StrippedDarkOakWood(StrippedDarkOakWood::Axis::Z).ID: return 143; case StrippedJungleLog::StrippedJungleLog(StrippedJungleLog::Axis::X).ID: return 96; case StrippedJungleLog::StrippedJungleLog(StrippedJungleLog::Axis::Y).ID: return 97; case StrippedJungleLog::StrippedJungleLog(StrippedJungleLog::Axis::Z).ID: return 98; case StrippedJungleWood::StrippedJungleWood(StrippedJungleWood::Axis::X).ID: return 135; case StrippedJungleWood::StrippedJungleWood(StrippedJungleWood::Axis::Y).ID: return 136; case StrippedJungleWood::StrippedJungleWood(StrippedJungleWood::Axis::Z).ID: return 137; case StrippedOakLog::StrippedOakLog(StrippedOakLog::Axis::X).ID: return 105; case StrippedOakLog::StrippedOakLog(StrippedOakLog::Axis::Y).ID: return 106; case StrippedOakLog::StrippedOakLog(StrippedOakLog::Axis::Z).ID: return 107; case StrippedOakWood::StrippedOakWood(StrippedOakWood::Axis::X).ID: return 126; case StrippedOakWood::StrippedOakWood(StrippedOakWood::Axis::Y).ID: return 127; case StrippedOakWood::StrippedOakWood(StrippedOakWood::Axis::Z).ID: return 128; case StrippedSpruceLog::StrippedSpruceLog(StrippedSpruceLog::Axis::X).ID: return 90; case StrippedSpruceLog::StrippedSpruceLog(StrippedSpruceLog::Axis::Y).ID: return 91; case StrippedSpruceLog::StrippedSpruceLog(StrippedSpruceLog::Axis::Z).ID: return 92; case StrippedSpruceWood::StrippedSpruceWood(StrippedSpruceWood::Axis::X).ID: return 129; case StrippedSpruceWood::StrippedSpruceWood(StrippedSpruceWood::Axis::Y).ID: return 130; case StrippedSpruceWood::StrippedSpruceWood(StrippedSpruceWood::Axis::Z).ID: return 131; case StructureBlock::StructureBlock(StructureBlock::Mode::Save).ID: return 8578; case StructureBlock::StructureBlock(StructureBlock::Mode::Load).ID: return 8579; case StructureBlock::StructureBlock(StructureBlock::Mode::Corner).ID: return 8580; case StructureBlock::StructureBlock(StructureBlock::Mode::Data).ID: return 8581; case StructureVoid::StructureVoid().ID: return 8198; case SugarCane::SugarCane(0).ID: return 3442; case SugarCane::SugarCane(1).ID: return 3443; case SugarCane::SugarCane(2).ID: return 3444; case SugarCane::SugarCane(3).ID: return 3445; case SugarCane::SugarCane(4).ID: return 3446; case SugarCane::SugarCane(5).ID: return 3447; case SugarCane::SugarCane(6).ID: return 3448; case SugarCane::SugarCane(7).ID: return 3449; case SugarCane::SugarCane(8).ID: return 3450; case SugarCane::SugarCane(9).ID: return 3451; case SugarCane::SugarCane(10).ID: return 3452; case SugarCane::SugarCane(11).ID: return 3453; case SugarCane::SugarCane(12).ID: return 3454; case SugarCane::SugarCane(13).ID: return 3455; case SugarCane::SugarCane(14).ID: return 3456; case SugarCane::SugarCane(15).ID: return 3457; case Sunflower::Sunflower(Sunflower::Half::Upper).ID: return 6842; case Sunflower::Sunflower(Sunflower::Half::Lower).ID: return 6843; case TNT::TNT(true).ID: return 1126; case TNT::TNT(false).ID: return 1126; case TallGrass::TallGrass(TallGrass::Half::Upper).ID: return 6850; case TallGrass::TallGrass(TallGrass::Half::Lower).ID: return 6851; case TallSeagrass::TallSeagrass(TallSeagrass::Half::Upper).ID: return 1045; case TallSeagrass::TallSeagrass(TallSeagrass::Half::Lower).ID: return 1046; case Terracotta::Terracotta().ID: return 6839; case Torch::Torch().ID: return 1130; case TrappedChest::TrappedChest(eBlockFace::BLOCK_FACE_ZM, TrappedChest::Type::Single).ID: return 5580; case TrappedChest::TrappedChest(eBlockFace::BLOCK_FACE_ZM, TrappedChest::Type::Left).ID: return 5582; case TrappedChest::TrappedChest(eBlockFace::BLOCK_FACE_ZM, TrappedChest::Type::Right).ID: return 5584; case TrappedChest::TrappedChest(eBlockFace::BLOCK_FACE_ZP, TrappedChest::Type::Single).ID: return 5586; case TrappedChest::TrappedChest(eBlockFace::BLOCK_FACE_ZP, TrappedChest::Type::Left).ID: return 5588; case TrappedChest::TrappedChest(eBlockFace::BLOCK_FACE_ZP, TrappedChest::Type::Right).ID: return 5590; case TrappedChest::TrappedChest(eBlockFace::BLOCK_FACE_XM, TrappedChest::Type::Single).ID: return 5592; case TrappedChest::TrappedChest(eBlockFace::BLOCK_FACE_XM, TrappedChest::Type::Left).ID: return 5594; case TrappedChest::TrappedChest(eBlockFace::BLOCK_FACE_XM, TrappedChest::Type::Right).ID: return 5596; case TrappedChest::TrappedChest(eBlockFace::BLOCK_FACE_XP, TrappedChest::Type::Single).ID: return 5598; case TrappedChest::TrappedChest(eBlockFace::BLOCK_FACE_XP, TrappedChest::Type::Left).ID: return 5600; case TrappedChest::TrappedChest(eBlockFace::BLOCK_FACE_XP, TrappedChest::Type::Right).ID: return 5602; case Tripwire::Tripwire(true, true, true, true, true, true, true).ID: return 4755; case Tripwire::Tripwire(true, true, true, true, true, true, false).ID: return 4756; case Tripwire::Tripwire(true, true, true, true, true, false, true).ID: return 4757; case Tripwire::Tripwire(true, true, true, true, true, false, false).ID: return 4758; case Tripwire::Tripwire(true, true, true, true, false, true, true).ID: return 4759; case Tripwire::Tripwire(true, true, true, true, false, true, false).ID: return 4760; case Tripwire::Tripwire(true, true, true, true, false, false, true).ID: return 4761; case Tripwire::Tripwire(true, true, true, true, false, false, false).ID: return 4762; case Tripwire::Tripwire(true, true, true, false, true, true, true).ID: return 4763; case Tripwire::Tripwire(true, true, true, false, true, true, false).ID: return 4764; case Tripwire::Tripwire(true, true, true, false, true, false, true).ID: return 4765; case Tripwire::Tripwire(true, true, true, false, true, false, false).ID: return 4766; case Tripwire::Tripwire(true, true, true, false, false, true, true).ID: return 4767; case Tripwire::Tripwire(true, true, true, false, false, true, false).ID: return 4768; case Tripwire::Tripwire(true, true, true, false, false, false, true).ID: return 4769; case Tripwire::Tripwire(true, true, true, false, false, false, false).ID: return 4770; case Tripwire::Tripwire(true, true, false, true, true, true, true).ID: return 4771; case Tripwire::Tripwire(true, true, false, true, true, true, false).ID: return 4772; case Tripwire::Tripwire(true, true, false, true, true, false, true).ID: return 4773; case Tripwire::Tripwire(true, true, false, true, true, false, false).ID: return 4774; case Tripwire::Tripwire(true, true, false, true, false, true, true).ID: return 4775; case Tripwire::Tripwire(true, true, false, true, false, true, false).ID: return 4776; case Tripwire::Tripwire(true, true, false, true, false, false, true).ID: return 4777; case Tripwire::Tripwire(true, true, false, true, false, false, false).ID: return 4778; case Tripwire::Tripwire(true, true, false, false, true, true, true).ID: return 4779; case Tripwire::Tripwire(true, true, false, false, true, true, false).ID: return 4780; case Tripwire::Tripwire(true, true, false, false, true, false, true).ID: return 4781; case Tripwire::Tripwire(true, true, false, false, true, false, false).ID: return 4782; case Tripwire::Tripwire(true, true, false, false, false, true, true).ID: return 4783; case Tripwire::Tripwire(true, true, false, false, false, true, false).ID: return 4784; case Tripwire::Tripwire(true, true, false, false, false, false, true).ID: return 4785; case Tripwire::Tripwire(true, true, false, false, false, false, false).ID: return 4786; case Tripwire::Tripwire(true, false, true, true, true, true, true).ID: return 4787; case Tripwire::Tripwire(true, false, true, true, true, true, false).ID: return 4788; case Tripwire::Tripwire(true, false, true, true, true, false, true).ID: return 4789; case Tripwire::Tripwire(true, false, true, true, true, false, false).ID: return 4790; case Tripwire::Tripwire(true, false, true, true, false, true, true).ID: return 4791; case Tripwire::Tripwire(true, false, true, true, false, true, false).ID: return 4792; case Tripwire::Tripwire(true, false, true, true, false, false, true).ID: return 4793; case Tripwire::Tripwire(true, false, true, true, false, false, false).ID: return 4794; case Tripwire::Tripwire(true, false, true, false, true, true, true).ID: return 4795; case Tripwire::Tripwire(true, false, true, false, true, true, false).ID: return 4796; case Tripwire::Tripwire(true, false, true, false, true, false, true).ID: return 4797; case Tripwire::Tripwire(true, false, true, false, true, false, false).ID: return 4798; case Tripwire::Tripwire(true, false, true, false, false, true, true).ID: return 4799; case Tripwire::Tripwire(true, false, true, false, false, true, false).ID: return 4800; case Tripwire::Tripwire(true, false, true, false, false, false, true).ID: return 4801; case Tripwire::Tripwire(true, false, true, false, false, false, false).ID: return 4802; case Tripwire::Tripwire(true, false, false, true, true, true, true).ID: return 4803; case Tripwire::Tripwire(true, false, false, true, true, true, false).ID: return 4804; case Tripwire::Tripwire(true, false, false, true, true, false, true).ID: return 4805; case Tripwire::Tripwire(true, false, false, true, true, false, false).ID: return 4806; case Tripwire::Tripwire(true, false, false, true, false, true, true).ID: return 4807; case Tripwire::Tripwire(true, false, false, true, false, true, false).ID: return 4808; case Tripwire::Tripwire(true, false, false, true, false, false, true).ID: return 4809; case Tripwire::Tripwire(true, false, false, true, false, false, false).ID: return 4810; case Tripwire::Tripwire(true, false, false, false, true, true, true).ID: return 4811; case Tripwire::Tripwire(true, false, false, false, true, true, false).ID: return 4812; case Tripwire::Tripwire(true, false, false, false, true, false, true).ID: return 4813; case Tripwire::Tripwire(true, false, false, false, true, false, false).ID: return 4814; case Tripwire::Tripwire(true, false, false, false, false, true, true).ID: return 4815; case Tripwire::Tripwire(true, false, false, false, false, true, false).ID: return 4816; case Tripwire::Tripwire(true, false, false, false, false, false, true).ID: return 4817; case Tripwire::Tripwire(true, false, false, false, false, false, false).ID: return 4818; case Tripwire::Tripwire(false, true, true, true, true, true, true).ID: return 4819; case Tripwire::Tripwire(false, true, true, true, true, true, false).ID: return 4820; case Tripwire::Tripwire(false, true, true, true, true, false, true).ID: return 4821; case Tripwire::Tripwire(false, true, true, true, true, false, false).ID: return 4822; case Tripwire::Tripwire(false, true, true, true, false, true, true).ID: return 4823; case Tripwire::Tripwire(false, true, true, true, false, true, false).ID: return 4824; case Tripwire::Tripwire(false, true, true, true, false, false, true).ID: return 4825; case Tripwire::Tripwire(false, true, true, true, false, false, false).ID: return 4826; case Tripwire::Tripwire(false, true, true, false, true, true, true).ID: return 4827; case Tripwire::Tripwire(false, true, true, false, true, true, false).ID: return 4828; case Tripwire::Tripwire(false, true, true, false, true, false, true).ID: return 4829; case Tripwire::Tripwire(false, true, true, false, true, false, false).ID: return 4830; case Tripwire::Tripwire(false, true, true, false, false, true, true).ID: return 4831; case Tripwire::Tripwire(false, true, true, false, false, true, false).ID: return 4832; case Tripwire::Tripwire(false, true, true, false, false, false, true).ID: return 4833; case Tripwire::Tripwire(false, true, true, false, false, false, false).ID: return 4834; case Tripwire::Tripwire(false, true, false, true, true, true, true).ID: return 4835; case Tripwire::Tripwire(false, true, false, true, true, true, false).ID: return 4836; case Tripwire::Tripwire(false, true, false, true, true, false, true).ID: return 4837; case Tripwire::Tripwire(false, true, false, true, true, false, false).ID: return 4838; case Tripwire::Tripwire(false, true, false, true, false, true, true).ID: return 4839; case Tripwire::Tripwire(false, true, false, true, false, true, false).ID: return 4840; case Tripwire::Tripwire(false, true, false, true, false, false, true).ID: return 4841; case Tripwire::Tripwire(false, true, false, true, false, false, false).ID: return 4842; case Tripwire::Tripwire(false, true, false, false, true, true, true).ID: return 4843; case Tripwire::Tripwire(false, true, false, false, true, true, false).ID: return 4844; case Tripwire::Tripwire(false, true, false, false, true, false, true).ID: return 4845; case Tripwire::Tripwire(false, true, false, false, true, false, false).ID: return 4846; case Tripwire::Tripwire(false, true, false, false, false, true, true).ID: return 4847; case Tripwire::Tripwire(false, true, false, false, false, true, false).ID: return 4848; case Tripwire::Tripwire(false, true, false, false, false, false, true).ID: return 4849; case Tripwire::Tripwire(false, true, false, false, false, false, false).ID: return 4850; case Tripwire::Tripwire(false, false, true, true, true, true, true).ID: return 4851; case Tripwire::Tripwire(false, false, true, true, true, true, false).ID: return 4852; case Tripwire::Tripwire(false, false, true, true, true, false, true).ID: return 4853; case Tripwire::Tripwire(false, false, true, true, true, false, false).ID: return 4854; case Tripwire::Tripwire(false, false, true, true, false, true, true).ID: return 4855; case Tripwire::Tripwire(false, false, true, true, false, true, false).ID: return 4856; case Tripwire::Tripwire(false, false, true, true, false, false, true).ID: return 4857; case Tripwire::Tripwire(false, false, true, true, false, false, false).ID: return 4858; case Tripwire::Tripwire(false, false, true, false, true, true, true).ID: return 4859; case Tripwire::Tripwire(false, false, true, false, true, true, false).ID: return 4860; case Tripwire::Tripwire(false, false, true, false, true, false, true).ID: return 4861; case Tripwire::Tripwire(false, false, true, false, true, false, false).ID: return 4862; case Tripwire::Tripwire(false, false, true, false, false, true, true).ID: return 4863; case Tripwire::Tripwire(false, false, true, false, false, true, false).ID: return 4864; case Tripwire::Tripwire(false, false, true, false, false, false, true).ID: return 4865; case Tripwire::Tripwire(false, false, true, false, false, false, false).ID: return 4866; case Tripwire::Tripwire(false, false, false, true, true, true, true).ID: return 4867; case Tripwire::Tripwire(false, false, false, true, true, true, false).ID: return 4868; case Tripwire::Tripwire(false, false, false, true, true, false, true).ID: return 4869; case Tripwire::Tripwire(false, false, false, true, true, false, false).ID: return 4870; case Tripwire::Tripwire(false, false, false, true, false, true, true).ID: return 4871; case Tripwire::Tripwire(false, false, false, true, false, true, false).ID: return 4872; case Tripwire::Tripwire(false, false, false, true, false, false, true).ID: return 4873; case Tripwire::Tripwire(false, false, false, true, false, false, false).ID: return 4874; case Tripwire::Tripwire(false, false, false, false, true, true, true).ID: return 4875; case Tripwire::Tripwire(false, false, false, false, true, true, false).ID: return 4876; case Tripwire::Tripwire(false, false, false, false, true, false, true).ID: return 4877; case Tripwire::Tripwire(false, false, false, false, true, false, false).ID: return 4878; case Tripwire::Tripwire(false, false, false, false, false, true, true).ID: return 4879; case Tripwire::Tripwire(false, false, false, false, false, true, false).ID: return 4880; case Tripwire::Tripwire(false, false, false, false, false, false, true).ID: return 4881; case Tripwire::Tripwire(false, false, false, false, false, false, false).ID: return 4882; case TripwireHook::TripwireHook(true, eBlockFace::BLOCK_FACE_ZM, true).ID: return 4739; case TripwireHook::TripwireHook(true, eBlockFace::BLOCK_FACE_ZM, false).ID: return 4740; case TripwireHook::TripwireHook(true, eBlockFace::BLOCK_FACE_ZP, true).ID: return 4741; case TripwireHook::TripwireHook(true, eBlockFace::BLOCK_FACE_ZP, false).ID: return 4742; case TripwireHook::TripwireHook(true, eBlockFace::BLOCK_FACE_XM, true).ID: return 4743; case TripwireHook::TripwireHook(true, eBlockFace::BLOCK_FACE_XM, false).ID: return 4744; case TripwireHook::TripwireHook(true, eBlockFace::BLOCK_FACE_XP, true).ID: return 4745; case TripwireHook::TripwireHook(true, eBlockFace::BLOCK_FACE_XP, false).ID: return 4746; case TripwireHook::TripwireHook(false, eBlockFace::BLOCK_FACE_ZM, true).ID: return 4747; case TripwireHook::TripwireHook(false, eBlockFace::BLOCK_FACE_ZM, false).ID: return 4748; case TripwireHook::TripwireHook(false, eBlockFace::BLOCK_FACE_ZP, true).ID: return 4749; case TripwireHook::TripwireHook(false, eBlockFace::BLOCK_FACE_ZP, false).ID: return 4750; case TripwireHook::TripwireHook(false, eBlockFace::BLOCK_FACE_XM, true).ID: return 4751; case TripwireHook::TripwireHook(false, eBlockFace::BLOCK_FACE_XM, false).ID: return 4752; case TripwireHook::TripwireHook(false, eBlockFace::BLOCK_FACE_XP, true).ID: return 4753; case TripwireHook::TripwireHook(false, eBlockFace::BLOCK_FACE_XP, false).ID: return 4754; case TubeCoral::TubeCoral().ID: return 8459; case TubeCoralBlock::TubeCoralBlock().ID: return 8454; case TubeCoralFan::TubeCoralFan().ID: return 8555; case TubeCoralWallFan::TubeCoralWallFan(eBlockFace::BLOCK_FACE_ZM).ID: return 8505; case TubeCoralWallFan::TubeCoralWallFan(eBlockFace::BLOCK_FACE_ZP).ID: return 8507; case TubeCoralWallFan::TubeCoralWallFan(eBlockFace::BLOCK_FACE_XM).ID: return 8509; case TubeCoralWallFan::TubeCoralWallFan(eBlockFace::BLOCK_FACE_XP).ID: return 8511; case TurtleEgg::TurtleEgg(1, 0).ID: return 8437; case TurtleEgg::TurtleEgg(1, 1).ID: return 8438; case TurtleEgg::TurtleEgg(1, 2).ID: return 8439; case TurtleEgg::TurtleEgg(2, 0).ID: return 8440; case TurtleEgg::TurtleEgg(2, 1).ID: return 8441; case TurtleEgg::TurtleEgg(2, 2).ID: return 8442; case TurtleEgg::TurtleEgg(3, 0).ID: return 8443; case TurtleEgg::TurtleEgg(3, 1).ID: return 8444; case TurtleEgg::TurtleEgg(3, 2).ID: return 8445; case TurtleEgg::TurtleEgg(4, 0).ID: return 8446; case TurtleEgg::TurtleEgg(4, 1).ID: return 8447; case TurtleEgg::TurtleEgg(4, 2).ID: return 8448; case Vine::Vine(true, true, true, true, true).ID: return 4268; case Vine::Vine(true, true, true, true, false).ID: return 4269; case Vine::Vine(true, true, true, false, true).ID: return 4270; case Vine::Vine(true, true, true, false, false).ID: return 4271; case Vine::Vine(true, true, false, true, true).ID: return 4272; case Vine::Vine(true, true, false, true, false).ID: return 4273; case Vine::Vine(true, true, false, false, true).ID: return 4274; case Vine::Vine(true, true, false, false, false).ID: return 4275; case Vine::Vine(true, false, true, true, true).ID: return 4276; case Vine::Vine(true, false, true, true, false).ID: return 4277; case Vine::Vine(true, false, true, false, true).ID: return 4278; case Vine::Vine(true, false, true, false, false).ID: return 4279; case Vine::Vine(true, false, false, true, true).ID: return 4280; case Vine::Vine(true, false, false, true, false).ID: return 4281; case Vine::Vine(true, false, false, false, true).ID: return 4282; case Vine::Vine(true, false, false, false, false).ID: return 4283; case Vine::Vine(false, true, true, true, true).ID: return 4284; case Vine::Vine(false, true, true, true, false).ID: return 4285; case Vine::Vine(false, true, true, false, true).ID: return 4286; case Vine::Vine(false, true, true, false, false).ID: return 4287; case Vine::Vine(false, true, false, true, true).ID: return 4288; case Vine::Vine(false, true, false, true, false).ID: return 4289; case Vine::Vine(false, true, false, false, true).ID: return 4290; case Vine::Vine(false, true, false, false, false).ID: return 4291; case Vine::Vine(false, false, true, true, true).ID: return 4292; case Vine::Vine(false, false, true, true, false).ID: return 4293; case Vine::Vine(false, false, true, false, true).ID: return 4294; case Vine::Vine(false, false, true, false, false).ID: return 4295; case Vine::Vine(false, false, false, true, true).ID: return 4296; case Vine::Vine(false, false, false, true, false).ID: return 4297; case Vine::Vine(false, false, false, false, true).ID: return 4298; case Vine::Vine(false, false, false, false, false).ID: return 4299; case VoidAir::VoidAir().ID: return 8574; case OakWallSign::OakWallSign(eBlockFace::BLOCK_FACE_ZM).ID: return 3270; case OakWallSign::OakWallSign(eBlockFace::BLOCK_FACE_ZP).ID: return 3272; case OakWallSign::OakWallSign(eBlockFace::BLOCK_FACE_XM).ID: return 3274; case OakWallSign::OakWallSign(eBlockFace::BLOCK_FACE_XP).ID: return 3276; case WallTorch::WallTorch(eBlockFace::BLOCK_FACE_ZM).ID: return 1131; case WallTorch::WallTorch(eBlockFace::BLOCK_FACE_ZP).ID: return 1132; case WallTorch::WallTorch(eBlockFace::BLOCK_FACE_XM).ID: return 1133; case WallTorch::WallTorch(eBlockFace::BLOCK_FACE_XP).ID: return 1134; case Water::Water(0).ID: return 34; case Water::Water(1).ID: return 35; case Water::Water(2).ID: return 36; case Water::Water(3).ID: return 37; case Water::Water(4).ID: return 38; case Water::Water(5).ID: return 39; case Water::Water(6).ID: return 40; case Water::Water(7).ID: return 41; case Water::Water(8).ID: return 42; case Water::Water(9).ID: return 43; case Water::Water(10).ID: return 44; case Water::Water(11).ID: return 45; case Water::Water(12).ID: return 46; case Water::Water(13).ID: return 47; case Water::Water(14).ID: return 48; case Water::Water(15).ID: return 49; case WetSponge::WetSponge().ID: return 229; case Wheat::Wheat(0).ID: return 3051; case Wheat::Wheat(1).ID: return 3052; case Wheat::Wheat(2).ID: return 3053; case Wheat::Wheat(3).ID: return 3054; case Wheat::Wheat(4).ID: return 3055; case Wheat::Wheat(5).ID: return 3056; case Wheat::Wheat(6).ID: return 3057; case Wheat::Wheat(7).ID: return 3058; case WhiteBanner::WhiteBanner(0).ID: return 6854; case WhiteBanner::WhiteBanner(1).ID: return 6855; case WhiteBanner::WhiteBanner(2).ID: return 6856; case WhiteBanner::WhiteBanner(3).ID: return 6857; case WhiteBanner::WhiteBanner(4).ID: return 6858; case WhiteBanner::WhiteBanner(5).ID: return 6859; case WhiteBanner::WhiteBanner(6).ID: return 6860; case WhiteBanner::WhiteBanner(7).ID: return 6861; case WhiteBanner::WhiteBanner(8).ID: return 6862; case WhiteBanner::WhiteBanner(9).ID: return 6863; case WhiteBanner::WhiteBanner(10).ID: return 6864; case WhiteBanner::WhiteBanner(11).ID: return 6865; case WhiteBanner::WhiteBanner(12).ID: return 6866; case WhiteBanner::WhiteBanner(13).ID: return 6867; case WhiteBanner::WhiteBanner(14).ID: return 6868; case WhiteBanner::WhiteBanner(15).ID: return 6869; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_ZM, true, WhiteBed::Part::Head).ID: return 748; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_ZM, true, WhiteBed::Part::Foot).ID: return 749; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_ZM, false, WhiteBed::Part::Head).ID: return 750; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_ZM, false, WhiteBed::Part::Foot).ID: return 751; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_ZP, true, WhiteBed::Part::Head).ID: return 752; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_ZP, true, WhiteBed::Part::Foot).ID: return 753; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_ZP, false, WhiteBed::Part::Head).ID: return 754; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_ZP, false, WhiteBed::Part::Foot).ID: return 755; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_XM, true, WhiteBed::Part::Head).ID: return 756; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_XM, true, WhiteBed::Part::Foot).ID: return 757; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_XM, false, WhiteBed::Part::Head).ID: return 758; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_XM, false, WhiteBed::Part::Foot).ID: return 759; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_XP, true, WhiteBed::Part::Head).ID: return 760; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_XP, true, WhiteBed::Part::Foot).ID: return 761; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_XP, false, WhiteBed::Part::Head).ID: return 762; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_XP, false, WhiteBed::Part::Foot).ID: return 763; case WhiteCarpet::WhiteCarpet().ID: return 6823; case WhiteConcrete::WhiteConcrete().ID: return 8377; case WhiteConcretePowder::WhiteConcretePowder().ID: return 8393; case WhiteGlazedTerracotta::WhiteGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 8313; case WhiteGlazedTerracotta::WhiteGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 8314; case WhiteGlazedTerracotta::WhiteGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 8315; case WhiteGlazedTerracotta::WhiteGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 8316; case WhiteShulkerBox::WhiteShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 8217; case WhiteShulkerBox::WhiteShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 8218; case WhiteShulkerBox::WhiteShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 8219; case WhiteShulkerBox::WhiteShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 8220; case WhiteShulkerBox::WhiteShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 8221; case WhiteShulkerBox::WhiteShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 8222; case WhiteStainedGlass::WhiteStainedGlass().ID: return 3577; case WhiteStainedGlassPane::WhiteStainedGlassPane(true, true, true, true).ID: return 5822; case WhiteStainedGlassPane::WhiteStainedGlassPane(true, true, true, false).ID: return 5823; case WhiteStainedGlassPane::WhiteStainedGlassPane(true, true, false, true).ID: return 5826; case WhiteStainedGlassPane::WhiteStainedGlassPane(true, true, false, false).ID: return 5827; case WhiteStainedGlassPane::WhiteStainedGlassPane(true, false, true, true).ID: return 5830; case WhiteStainedGlassPane::WhiteStainedGlassPane(true, false, true, false).ID: return 5831; case WhiteStainedGlassPane::WhiteStainedGlassPane(true, false, false, true).ID: return 5834; case WhiteStainedGlassPane::WhiteStainedGlassPane(true, false, false, false).ID: return 5835; case WhiteStainedGlassPane::WhiteStainedGlassPane(false, true, true, true).ID: return 5838; case WhiteStainedGlassPane::WhiteStainedGlassPane(false, true, true, false).ID: return 5839; case WhiteStainedGlassPane::WhiteStainedGlassPane(false, true, false, true).ID: return 5842; case WhiteStainedGlassPane::WhiteStainedGlassPane(false, true, false, false).ID: return 5843; case WhiteStainedGlassPane::WhiteStainedGlassPane(false, false, true, true).ID: return 5846; case WhiteStainedGlassPane::WhiteStainedGlassPane(false, false, true, false).ID: return 5847; case WhiteStainedGlassPane::WhiteStainedGlassPane(false, false, false, true).ID: return 5850; case WhiteStainedGlassPane::WhiteStainedGlassPane(false, false, false, false).ID: return 5851; case WhiteTerracotta::WhiteTerracotta().ID: return 5804; case WhiteTulip::WhiteTulip().ID: return 1118; case WhiteWallBanner::WhiteWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 7110; case WhiteWallBanner::WhiteWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 7111; case WhiteWallBanner::WhiteWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 7112; case WhiteWallBanner::WhiteWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 7113; case WhiteWool::WhiteWool().ID: return 1083; case WitherSkeletonSkull::WitherSkeletonSkull(0).ID: return 5471; case WitherSkeletonSkull::WitherSkeletonSkull(1).ID: return 5472; case WitherSkeletonSkull::WitherSkeletonSkull(2).ID: return 5473; case WitherSkeletonSkull::WitherSkeletonSkull(3).ID: return 5474; case WitherSkeletonSkull::WitherSkeletonSkull(4).ID: return 5475; case WitherSkeletonSkull::WitherSkeletonSkull(5).ID: return 5476; case WitherSkeletonSkull::WitherSkeletonSkull(6).ID: return 5477; case WitherSkeletonSkull::WitherSkeletonSkull(7).ID: return 5478; case WitherSkeletonSkull::WitherSkeletonSkull(8).ID: return 5479; case WitherSkeletonSkull::WitherSkeletonSkull(9).ID: return 5480; case WitherSkeletonSkull::WitherSkeletonSkull(10).ID: return 5481; case WitherSkeletonSkull::WitherSkeletonSkull(11).ID: return 5482; case WitherSkeletonSkull::WitherSkeletonSkull(12).ID: return 5483; case WitherSkeletonSkull::WitherSkeletonSkull(13).ID: return 5484; case WitherSkeletonSkull::WitherSkeletonSkull(14).ID: return 5485; case WitherSkeletonSkull::WitherSkeletonSkull(15).ID: return 5486; case WitherSkeletonWallSkull::WitherSkeletonWallSkull(eBlockFace::BLOCK_FACE_ZM).ID: return 5467; case WitherSkeletonWallSkull::WitherSkeletonWallSkull(eBlockFace::BLOCK_FACE_ZP).ID: return 5468; case WitherSkeletonWallSkull::WitherSkeletonWallSkull(eBlockFace::BLOCK_FACE_XM).ID: return 5469; case WitherSkeletonWallSkull::WitherSkeletonWallSkull(eBlockFace::BLOCK_FACE_XP).ID: return 5470; case YellowBanner::YellowBanner(0).ID: return 6918; case YellowBanner::YellowBanner(1).ID: return 6919; case YellowBanner::YellowBanner(2).ID: return 6920; case YellowBanner::YellowBanner(3).ID: return 6921; case YellowBanner::YellowBanner(4).ID: return 6922; case YellowBanner::YellowBanner(5).ID: return 6923; case YellowBanner::YellowBanner(6).ID: return 6924; case YellowBanner::YellowBanner(7).ID: return 6925; case YellowBanner::YellowBanner(8).ID: return 6926; case YellowBanner::YellowBanner(9).ID: return 6927; case YellowBanner::YellowBanner(10).ID: return 6928; case YellowBanner::YellowBanner(11).ID: return 6929; case YellowBanner::YellowBanner(12).ID: return 6930; case YellowBanner::YellowBanner(13).ID: return 6931; case YellowBanner::YellowBanner(14).ID: return 6932; case YellowBanner::YellowBanner(15).ID: return 6933; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_ZM, true, YellowBed::Part::Head).ID: return 812; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_ZM, true, YellowBed::Part::Foot).ID: return 813; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_ZM, false, YellowBed::Part::Head).ID: return 814; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_ZM, false, YellowBed::Part::Foot).ID: return 815; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_ZP, true, YellowBed::Part::Head).ID: return 816; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_ZP, true, YellowBed::Part::Foot).ID: return 817; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_ZP, false, YellowBed::Part::Head).ID: return 818; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_ZP, false, YellowBed::Part::Foot).ID: return 819; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_XM, true, YellowBed::Part::Head).ID: return 820; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_XM, true, YellowBed::Part::Foot).ID: return 821; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_XM, false, YellowBed::Part::Head).ID: return 822; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_XM, false, YellowBed::Part::Foot).ID: return 823; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_XP, true, YellowBed::Part::Head).ID: return 824; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_XP, true, YellowBed::Part::Foot).ID: return 825; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_XP, false, YellowBed::Part::Head).ID: return 826; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_XP, false, YellowBed::Part::Foot).ID: return 827; case YellowCarpet::YellowCarpet().ID: return 6827; case YellowConcrete::YellowConcrete().ID: return 8381; case YellowConcretePowder::YellowConcretePowder().ID: return 8397; case YellowGlazedTerracotta::YellowGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 8329; case YellowGlazedTerracotta::YellowGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 8330; case YellowGlazedTerracotta::YellowGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 8331; case YellowGlazedTerracotta::YellowGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 8332; case YellowShulkerBox::YellowShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 8241; case YellowShulkerBox::YellowShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 8242; case YellowShulkerBox::YellowShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 8243; case YellowShulkerBox::YellowShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 8244; case YellowShulkerBox::YellowShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 8245; case YellowShulkerBox::YellowShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 8246; case YellowStainedGlass::YellowStainedGlass().ID: return 3581; case YellowStainedGlassPane::YellowStainedGlassPane(true, true, true, true).ID: return 5950; case YellowStainedGlassPane::YellowStainedGlassPane(true, true, true, false).ID: return 5951; case YellowStainedGlassPane::YellowStainedGlassPane(true, true, false, true).ID: return 5954; case YellowStainedGlassPane::YellowStainedGlassPane(true, true, false, false).ID: return 5955; case YellowStainedGlassPane::YellowStainedGlassPane(true, false, true, true).ID: return 5958; case YellowStainedGlassPane::YellowStainedGlassPane(true, false, true, false).ID: return 5959; case YellowStainedGlassPane::YellowStainedGlassPane(true, false, false, true).ID: return 5962; case YellowStainedGlassPane::YellowStainedGlassPane(true, false, false, false).ID: return 5963; case YellowStainedGlassPane::YellowStainedGlassPane(false, true, true, true).ID: return 5966; case YellowStainedGlassPane::YellowStainedGlassPane(false, true, true, false).ID: return 5967; case YellowStainedGlassPane::YellowStainedGlassPane(false, true, false, true).ID: return 5970; case YellowStainedGlassPane::YellowStainedGlassPane(false, true, false, false).ID: return 5971; case YellowStainedGlassPane::YellowStainedGlassPane(false, false, true, true).ID: return 5974; case YellowStainedGlassPane::YellowStainedGlassPane(false, false, true, false).ID: return 5975; case YellowStainedGlassPane::YellowStainedGlassPane(false, false, false, true).ID: return 5978; case YellowStainedGlassPane::YellowStainedGlassPane(false, false, false, false).ID: return 5979; case YellowTerracotta::YellowTerracotta().ID: return 5808; case YellowWallBanner::YellowWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 7126; case YellowWallBanner::YellowWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 7127; case YellowWallBanner::YellowWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 7128; case YellowWallBanner::YellowWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 7129; case YellowWool::YellowWool().ID: return 1087; case ZombieHead::ZombieHead(0).ID: return 5491; case ZombieHead::ZombieHead(1).ID: return 5492; case ZombieHead::ZombieHead(2).ID: return 5493; case ZombieHead::ZombieHead(3).ID: return 5494; case ZombieHead::ZombieHead(4).ID: return 5495; case ZombieHead::ZombieHead(5).ID: return 5496; case ZombieHead::ZombieHead(6).ID: return 5497; case ZombieHead::ZombieHead(7).ID: return 5498; case ZombieHead::ZombieHead(8).ID: return 5499; case ZombieHead::ZombieHead(9).ID: return 5500; case ZombieHead::ZombieHead(10).ID: return 5501; case ZombieHead::ZombieHead(11).ID: return 5502; case ZombieHead::ZombieHead(12).ID: return 5503; case ZombieHead::ZombieHead(13).ID: return 5504; case ZombieHead::ZombieHead(14).ID: return 5505; case ZombieHead::ZombieHead(15).ID: return 5506; case ZombieWallHead::ZombieWallHead(eBlockFace::BLOCK_FACE_ZM).ID: return 5487; case ZombieWallHead::ZombieWallHead(eBlockFace::BLOCK_FACE_ZP).ID: return 5488; case ZombieWallHead::ZombieWallHead(eBlockFace::BLOCK_FACE_XM).ID: return 5489; case ZombieWallHead::ZombieWallHead(eBlockFace::BLOCK_FACE_XP).ID: return 5490; default: return 0; } } UInt32 From(const Item ID) { switch (ID) { case Item::AcaciaBoat: return 762; case Item::AcaciaButton: return 245; case Item::AcaciaDoor: return 460; case Item::AcaciaFence: return 179; case Item::AcaciaFenceGate: return 214; case Item::AcaciaLeaves: return 60; case Item::AcaciaLog: return 36; case Item::AcaciaPlanks: return 17; case Item::AcaciaPressurePlate: return 164; case Item::AcaciaSapling: return 23; case Item::AcaciaSlab: return 116; case Item::AcaciaStairs: return 301; case Item::AcaciaTrapdoor: return 191; case Item::AcaciaWood: return 54; case Item::ActivatorRail: return 261; case Item::Air: return -0; case Item::Allium: return 101; case Item::Andesite: return 6; case Item::Anvil: return 247; case Item::Apple: return 471; case Item::ArmorStand: return 721; case Item::Arrow: return 473; case Item::AzureBluet: return 102; case Item::BakedPotato: return 694; case Item::Barrier: return 279; case Item::BatSpawnEgg: return 634; case Item::Beacon: return 238; case Item::Bedrock: return 25; case Item::Beef: return 614; case Item::Beetroot: return 749; case Item::BeetrootSeeds: return 750; case Item::BeetrootSoup: return 751; case Item::BirchBoat: return 760; case Item::BirchButton: return 243; case Item::BirchDoor: return 458; case Item::BirchFence: return 177; case Item::BirchFenceGate: return 212; case Item::BirchLeaves: return 58; case Item::BirchLog: return 34; case Item::BirchPlanks: return 15; case Item::BirchPressurePlate: return 162; case Item::BirchSapling: return 21; case Item::BirchSlab: return 114; case Item::BirchStairs: return 235; case Item::BirchTrapdoor: return 189; case Item::BirchWood: return 52; case Item::BlackBanner: return 745; case Item::BlackBed: return 606; case Item::BlackCarpet: return 297; case Item::BlackConcrete: return 410; case Item::BlackConcretePowder: return 426; case Item::BlackGlazedTerracotta: return 394; case Item::BlackShulkerBox: return 378; case Item::BlackStainedGlass: return 326; case Item::BlackStainedGlassPane: return 342; case Item::BlackTerracotta: return 278; case Item::BlackWool: return 97; case Item::BlazePowder: return 628; case Item::BlazeRod: return 620; case Item::BlazeSpawnEgg: return 635; case Item::BlueBanner: return 741; case Item::BlueBed: return 602; case Item::BlueCarpet: return 293; case Item::BlueConcrete: return 406; case Item::BlueConcretePowder: return 422; case Item::BlueGlazedTerracotta: return 390; case Item::BlueIce: return 453; case Item::BlueOrchid: return 100; case Item::BlueShulkerBox: return 374; case Item::BlueStainedGlass: return 322; case Item::BlueStainedGlassPane: return 338; case Item::BlueTerracotta: return 274; case Item::BlueWool: return 93; case Item::Bone: return 588; case Item::BoneBlock: return 359; case Item::BoneMeal: return 587; case Item::Book: return 557; case Item::Bookshelf: return 137; case Item::Bow: return 472; case Item::Bowl: return 493; case Item::BrainCoral: return 439; case Item::BrainCoralBlock: return 434; case Item::BrainCoralFan: return 444; case Item::Bread: return 509; case Item::BrewingStand: return 630; case Item::Brick: return 551; case Item::BrickSlab: return 122; case Item::BrickStairs: return 216; case Item::Bricks: return 135; case Item::BrownBanner: return 742; case Item::BrownBed: return 603; case Item::BrownCarpet: return 294; case Item::BrownConcrete: return 407; case Item::BrownConcretePowder: return 423; case Item::BrownGlazedTerracotta: return 391; case Item::BrownMushroom: return 108; case Item::BrownMushroomBlock: return 203; case Item::BrownShulkerBox: return 375; case Item::BrownStainedGlass: return 323; case Item::BrownStainedGlassPane: return 339; case Item::BrownTerracotta: return 275; case Item::BrownWool: return 94; case Item::BubbleCoral: return 440; case Item::BubbleCoralBlock: return 435; case Item::BubbleCoralFan: return 445; case Item::Bucket: return 537; case Item::Cactus: return 172; case Item::GreenDye: return 574; case Item::Cake: return 590; case Item::Carrot: return 692; case Item::CarrotOnAStick: return 704; case Item::CarvedPumpkin: return 182; case Item::Cauldron: return 631; case Item::CaveSpiderSpawnEgg: return 636; case Item::ChainCommandBlock: return 355; case Item::ChainmailBoots: return 517; case Item::ChainmailChestplate: return 515; case Item::ChainmailHelmet: return 514; case Item::ChainmailLeggings: return 516; case Item::Charcoal: return 475; case Item::Chest: return 149; case Item::ChestMinecart: return 559; case Item::Chicken: return 616; case Item::ChickenSpawnEgg: return 637; case Item::ChippedAnvil: return 248; case Item::ChiseledQuartzBlock: return 257; case Item::ChiseledRedSandstone: return 351; case Item::ChiseledSandstone: return 69; case Item::ChiseledStoneBricks: return 202; case Item::ChorusFlower: return 143; case Item::ChorusFruit: return 747; case Item::ChorusPlant: return 142; case Item::Clay: return 173; case Item::ClayBall: return 552; case Item::Clock: return 564; case Item::Coal: return 474; case Item::CoalBlock: return 299; case Item::CoalOre: return 31; case Item::CoarseDirt: return 10; case Item::Cobblestone: return 12; case Item::CobblestoneSlab: return 121; case Item::CobblestoneStairs: return 157; case Item::CobblestoneWall: return 239; case Item::Cobweb: return 75; case Item::CocoaBeans: return 575; case Item::Cod: return 566; case Item::CodBucket: return 549; case Item::CodSpawnEgg: return 638; case Item::CommandBlock: return 237; case Item::CommandBlockMinecart: return 727; case Item::Comparator: return 463; case Item::Compass: return 562; case Item::Conduit: return 454; case Item::CookedBeef: return 615; case Item::CookedChicken: return 617; case Item::CookedCod: return 570; case Item::CookedMutton: return 729; case Item::CookedPorkchop: return 532; case Item::CookedRabbit: return 717; case Item::CookedSalmon: return 571; case Item::Cookie: return 607; case Item::CowSpawnEgg: return 639; case Item::CrackedStoneBricks: return 201; case Item::CraftingTable: return 152; case Item::CreeperHead: return 702; case Item::CreeperSpawnEgg: return 640; case Item::CutRedSandstone: return 352; case Item::CutSandstone: return 70; case Item::CyanBanner: return 739; case Item::CyanBed: return 600; case Item::CyanCarpet: return 291; case Item::CyanConcrete: return 404; case Item::CyanConcretePowder: return 420; case Item::CyanDye: return 578; case Item::CyanGlazedTerracotta: return 388; case Item::CyanShulkerBox: return 372; case Item::CyanStainedGlass: return 320; case Item::CyanStainedGlassPane: return 336; case Item::CyanTerracotta: return 272; case Item::CyanWool: return 91; case Item::DamagedAnvil: return 249; case Item::Dandelion: return 98; case Item::YellowDye: return 583; case Item::DarkOakBoat: return 763; case Item::DarkOakButton: return 246; case Item::DarkOakDoor: return 461; case Item::DarkOakFence: return 180; case Item::DarkOakFenceGate: return 215; case Item::DarkOakLeaves: return 61; case Item::DarkOakLog: return 37; case Item::DarkOakPlanks: return 18; case Item::DarkOakPressurePlate: return 165; case Item::DarkOakSapling: return 24; case Item::DarkOakSlab: return 117; case Item::DarkOakStairs: return 302; case Item::DarkOakTrapdoor: return 192; case Item::DarkOakWood: return 55; case Item::DarkPrismarine: return 345; case Item::DarkPrismarineSlab: return 130; case Item::DarkPrismarineStairs: return 348; case Item::DaylightDetector: return 253; case Item::DeadBrainCoralBlock: return 429; case Item::DeadBrainCoralFan: return 449; case Item::DeadBubbleCoralBlock: return 430; case Item::DeadBubbleCoralFan: return 450; case Item::DeadBush: return 78; case Item::DeadFireCoralBlock: return 431; case Item::DeadFireCoralFan: return 451; case Item::DeadHornCoralBlock: return 432; case Item::DeadHornCoralFan: return 452; case Item::DeadTubeCoralBlock: return 428; case Item::DeadTubeCoralFan: return 448; case Item::DebugStick: return 768; case Item::DetectorRail: return 73; case Item::Diamond: return 476; case Item::DiamondAxe: return 491; case Item::DiamondBlock: return 151; case Item::DiamondBoots: return 525; case Item::DiamondChestplate: return 523; case Item::DiamondHelmet: return 522; case Item::DiamondHoe: return 505; case Item::DiamondHorseArmor: return 724; case Item::DiamondLeggings: return 524; case Item::DiamondOre: return 150; case Item::DiamondPickaxe: return 490; case Item::DiamondShovel: return 489; case Item::DiamondSword: return 488; case Item::Diorite: return 4; case Item::Dirt: return 9; case Item::Dispenser: return 67; case Item::DolphinSpawnEgg: return 641; case Item::DonkeySpawnEgg: return 642; case Item::DragonBreath: return 752; case Item::DragonEgg: return 227; case Item::DragonHead: return 703; case Item::DriedKelp: return 611; case Item::DriedKelpBlock: return 555; case Item::Dropper: return 262; case Item::DrownedSpawnEgg: return 643; case Item::Egg: return 561; case Item::ElderGuardianSpawnEgg: return 644; case Item::Elytra: return 758; case Item::Emerald: return 689; case Item::EmeraldBlock: return 233; case Item::EmeraldOre: return 230; case Item::EnchantedBook: return 709; case Item::EnchantedGoldenApple: return 535; case Item::EnchantingTable: return 223; case Item::EndCrystal: return 746; case Item::EndPortalFrame: return 224; case Item::EndRod: return 141; case Item::EndStone: return 225; case Item::EndStoneBricks: return 226; case Item::EnderChest: return 231; case Item::EnderEye: return 632; case Item::EnderPearl: return 619; case Item::EndermanSpawnEgg: return 645; case Item::EndermiteSpawnEgg: return 646; case Item::EvokerSpawnEgg: return 647; case Item::ExperienceBottle: return 685; case Item::Farmland: return 153; case Item::Feather: return 500; case Item::FermentedSpiderEye: return 627; case Item::Fern: return 77; case Item::FilledMap: return 608; case Item::FireCharge: return 686; case Item::FireCoral: return 441; case Item::FireCoralBlock: return 436; case Item::FireCoralFan: return 446; case Item::FireworkRocket: return 707; case Item::FireworkStar: return 708; case Item::FishingRod: return 563; case Item::Flint: return 530; case Item::FlintAndSteel: return 470; case Item::FlowerPot: return 691; case Item::Furnace: return 154; case Item::FurnaceMinecart: return 560; case Item::GhastSpawnEgg: return 648; case Item::GhastTear: return 621; case Item::Glass: return 64; case Item::GlassBottle: return 625; case Item::GlassPane: return 207; case Item::GlisteringMelonSlice: return 633; case Item::Glowstone: return 185; case Item::GlowstoneDust: return 565; case Item::GoldBlock: return 110; case Item::GoldIngot: return 478; case Item::GoldNugget: return 622; case Item::GoldOre: return 29; case Item::GoldenApple: return 534; case Item::GoldenAxe: return 498; case Item::GoldenBoots: return 529; case Item::GoldenCarrot: return 697; case Item::GoldenChestplate: return 527; case Item::GoldenHelmet: return 526; case Item::GoldenHoe: return 506; case Item::GoldenHorseArmor: return 723; case Item::GoldenLeggings: return 528; case Item::GoldenPickaxe: return 497; case Item::GoldenShovel: return 496; case Item::GoldenSword: return 495; case Item::Granite: return 2; case Item::Grass: return 76; case Item::GrassBlock: return 8; case Item::GrassPath: return 304; case Item::Gravel: return 28; case Item::GrayBanner: return 737; case Item::GrayBed: return 598; case Item::GrayCarpet: return 289; case Item::GrayConcrete: return 402; case Item::GrayConcretePowder: return 418; case Item::GrayDye: return 580; case Item::GrayGlazedTerracotta: return 386; case Item::GrayShulkerBox: return 370; case Item::GrayStainedGlass: return 318; case Item::GrayStainedGlassPane: return 334; case Item::GrayTerracotta: return 270; case Item::GrayWool: return 89; case Item::GreenBanner: return 743; case Item::GreenBed: return 604; case Item::GreenCarpet: return 295; case Item::GreenConcrete: return 408; case Item::GreenConcretePowder: return 424; case Item::GreenGlazedTerracotta: return 392; case Item::GreenShulkerBox: return 376; case Item::GreenStainedGlass: return 324; case Item::GreenStainedGlassPane: return 340; case Item::GreenTerracotta: return 276; case Item::GreenWool: return 95; case Item::GuardianSpawnEgg: return 649; case Item::Gunpowder: return 501; case Item::HayBale: return 281; case Item::HeartOfTheSea: return 784; case Item::HeavyWeightedPressurePlate: return 252; case Item::Hopper: return 256; case Item::HopperMinecart: return 713; case Item::HornCoral: return 442; case Item::HornCoralBlock: return 437; case Item::HornCoralFan: return 447; case Item::HorseSpawnEgg: return 650; case Item::HuskSpawnEgg: return 651; case Item::Ice: return 170; case Item::InfestedChiseledStoneBricks: return 198; case Item::InfestedCobblestone: return 194; case Item::InfestedCrackedStoneBricks: return 197; case Item::InfestedMossyStoneBricks: return 196; case Item::InfestedStone: return 193; case Item::InfestedStoneBricks: return 195; case Item::InkSac: return 572; case Item::IronAxe: return 469; case Item::IronBars: return 206; case Item::IronBlock: return 111; case Item::IronBoots: return 521; case Item::IronChestplate: return 519; case Item::IronDoor: return 455; case Item::IronHelmet: return 518; case Item::IronHoe: return 504; case Item::IronHorseArmor: return 722; case Item::IronIngot: return 477; case Item::IronLeggings: return 520; case Item::IronNugget: return 766; case Item::IronOre: return 30; case Item::IronPickaxe: return 468; case Item::IronShovel: return 467; case Item::IronSword: return 479; case Item::IronTrapdoor: return 280; case Item::ItemFrame: return 690; case Item::JackOLantern: return 186; case Item::Jukebox: return 174; case Item::JungleBoat: return 761; case Item::JungleButton: return 244; case Item::JungleDoor: return 459; case Item::JungleFence: return 178; case Item::JungleFenceGate: return 213; case Item::JungleLeaves: return 59; case Item::JungleLog: return 35; case Item::JunglePlanks: return 16; case Item::JunglePressurePlate: return 163; case Item::JungleSapling: return 22; case Item::JungleSlab: return 115; case Item::JungleStairs: return 236; case Item::JungleTrapdoor: return 190; case Item::JungleWood: return 53; case Item::Kelp: return 554; case Item::KnowledgeBook: return 767; case Item::Ladder: return 155; case Item::LapisBlock: return 66; case Item::LapisLazuli: return 576; case Item::LapisOre: return 65; case Item::LargeFern: return 310; case Item::LavaBucket: return 539; case Item::Lead: return 725; case Item::Leather: return 545; case Item::LeatherBoots: return 513; case Item::LeatherChestplate: return 511; case Item::LeatherHelmet: return 510; case Item::LeatherLeggings: return 512; case Item::Lever: return 158; case Item::LightBlueBanner: return 733; case Item::LightBlueBed: return 594; case Item::LightBlueCarpet: return 285; case Item::LightBlueConcrete: return 398; case Item::LightBlueConcretePowder: return 414; case Item::LightBlueDye: return 584; case Item::LightBlueGlazedTerracotta: return 382; case Item::LightBlueShulkerBox: return 366; case Item::LightBlueStainedGlass: return 314; case Item::LightBlueStainedGlassPane: return 330; case Item::LightBlueTerracotta: return 266; case Item::LightBlueWool: return 85; case Item::LightGrayBanner: return 738; case Item::LightGrayBed: return 599; case Item::LightGrayCarpet: return 290; case Item::LightGrayConcrete: return 403; case Item::LightGrayConcretePowder: return 419; case Item::LightGrayDye: return 579; case Item::LightGrayGlazedTerracotta: return 387; case Item::LightGrayShulkerBox: return 371; case Item::LightGrayStainedGlass: return 319; case Item::LightGrayStainedGlassPane: return 335; case Item::LightGrayTerracotta: return 271; case Item::LightGrayWool: return 90; case Item::LightWeightedPressurePlate: return 251; case Item::Lilac: return 306; case Item::LilyPad: return 219; case Item::LimeBanner: return 735; case Item::LimeBed: return 596; case Item::LimeCarpet: return 287; case Item::LimeConcrete: return 400; case Item::LimeConcretePowder: return 416; case Item::LimeDye: return 582; case Item::LimeGlazedTerracotta: return 384; case Item::LimeShulkerBox: return 368; case Item::LimeStainedGlass: return 316; case Item::LimeStainedGlassPane: return 332; case Item::LimeTerracotta: return 268; case Item::LimeWool: return 87; case Item::LingeringPotion: return 756; case Item::LlamaSpawnEgg: return 652; case Item::MagentaBanner: return 732; case Item::MagentaBed: return 593; case Item::MagentaCarpet: return 284; case Item::MagentaConcrete: return 397; case Item::MagentaConcretePowder: return 413; case Item::MagentaDye: return 585; case Item::MagentaGlazedTerracotta: return 381; case Item::MagentaShulkerBox: return 365; case Item::MagentaStainedGlass: return 313; case Item::MagentaStainedGlassPane: return 329; case Item::MagentaTerracotta: return 265; case Item::MagentaWool: return 84; case Item::MagmaBlock: return 356; case Item::MagmaCream: return 629; case Item::MagmaCubeSpawnEgg: return 653; case Item::Map: return 696; case Item::Melon: return 208; case Item::MelonSeeds: return 613; case Item::MelonSlice: return 610; case Item::MilkBucket: return 546; case Item::Minecart: return 540; case Item::MooshroomSpawnEgg: return 654; case Item::MossyCobblestone: return 138; case Item::MossyCobblestoneWall: return 240; case Item::MossyStoneBricks: return 200; case Item::MuleSpawnEgg: return 655; case Item::MushroomStem: return 205; case Item::MushroomStew: return 494; case Item::MusicDisc11: return 779; case Item::MusicDisc13: return 769; case Item::MusicDiscBlocks: return 771; case Item::MusicDiscCat: return 770; case Item::MusicDiscChirp: return 772; case Item::MusicDiscFar: return 773; case Item::MusicDiscMall: return 774; case Item::MusicDiscMellohi: return 775; case Item::MusicDiscStal: return 776; case Item::MusicDiscStrad: return 777; case Item::MusicDiscWait: return 780; case Item::MusicDiscWard: return 778; case Item::Mutton: return 728; case Item::Mycelium: return 218; case Item::NameTag: return 726; case Item::NautilusShell: return 783; case Item::NetherBrick: return 710; case Item::NetherBrickFence: return 221; case Item::NetherBrickSlab: return 124; case Item::NetherBrickStairs: return 222; case Item::NetherBricks: return 220; case Item::NetherQuartzOre: return 255; case Item::NetherStar: return 705; case Item::NetherWart: return 623; case Item::NetherWartBlock: return 357; case Item::Netherrack: return 183; case Item::NoteBlock: return 71; case Item::OakBoat: return 544; case Item::OakButton: return 241; case Item::OakDoor: return 456; case Item::OakFence: return 175; case Item::OakFenceGate: return 210; case Item::OakLeaves: return 56; case Item::OakLog: return 32; case Item::OakPlanks: return 13; case Item::OakPressurePlate: return 160; case Item::OakSapling: return 19; case Item::OakSlab: return 112; case Item::OakStairs: return 148; case Item::OakTrapdoor: return 187; case Item::OakWood: return 50; case Item::Observer: return 361; case Item::Obsidian: return 139; case Item::OcelotSpawnEgg: return 656; case Item::OrangeBanner: return 731; case Item::OrangeBed: return 592; case Item::OrangeCarpet: return 283; case Item::OrangeConcrete: return 396; case Item::OrangeConcretePowder: return 412; case Item::OrangeDye: return 586; case Item::OrangeGlazedTerracotta: return 380; case Item::OrangeShulkerBox: return 364; case Item::OrangeStainedGlass: return 312; case Item::OrangeStainedGlassPane: return 328; case Item::OrangeTerracotta: return 264; case Item::OrangeTulip: return 104; case Item::OrangeWool: return 83; case Item::OxeyeDaisy: return 107; case Item::PackedIce: return 300; case Item::Painting: return 533; case Item::Paper: return 556; case Item::ParrotSpawnEgg: return 657; case Item::Peony: return 308; case Item::PetrifiedOakSlab: return 120; case Item::PhantomMembrane: return 782; case Item::PhantomSpawnEgg: return 658; case Item::PigSpawnEgg: return 659; case Item::PinkBanner: return 736; case Item::PinkBed: return 597; case Item::PinkCarpet: return 288; case Item::PinkConcrete: return 401; case Item::PinkConcretePowder: return 417; case Item::PinkDye: return 581; case Item::PinkGlazedTerracotta: return 385; case Item::PinkShulkerBox: return 369; case Item::PinkStainedGlass: return 317; case Item::PinkStainedGlassPane: return 333; case Item::PinkTerracotta: return 269; case Item::PinkTulip: return 106; case Item::PinkWool: return 88; case Item::Piston: return 81; case Item::PlayerHead: return 700; case Item::Podzol: return 11; case Item::PoisonousPotato: return 695; case Item::PolarBearSpawnEgg: return 660; case Item::PolishedAndesite: return 7; case Item::PolishedDiorite: return 5; case Item::PolishedGranite: return 3; case Item::PoppedChorusFruit: return 748; case Item::Poppy: return 99; case Item::Porkchop: return 531; case Item::Potato: return 693; case Item::Potion: return 624; case Item::PoweredRail: return 72; case Item::Prismarine: return 343; case Item::PrismarineBrickSlab: return 129; case Item::PrismarineBrickStairs: return 347; case Item::PrismarineBricks: return 344; case Item::PrismarineCrystals: return 715; case Item::PrismarineShard: return 714; case Item::PrismarineSlab: return 128; case Item::PrismarineStairs: return 346; case Item::Pufferfish: return 569; case Item::PufferfishBucket: return 547; case Item::PufferfishSpawnEgg: return 661; case Item::Pumpkin: return 181; case Item::PumpkinPie: return 706; case Item::PumpkinSeeds: return 612; case Item::PurpleBanner: return 740; case Item::PurpleBed: return 601; case Item::PurpleCarpet: return 292; case Item::PurpleConcrete: return 405; case Item::PurpleConcretePowder: return 421; case Item::PurpleDye: return 577; case Item::PurpleGlazedTerracotta: return 389; case Item::PurpleShulkerBox: return 373; case Item::PurpleStainedGlass: return 321; case Item::PurpleStainedGlassPane: return 337; case Item::PurpleTerracotta: return 273; case Item::PurpleWool: return 92; case Item::PurpurBlock: return 144; case Item::PurpurPillar: return 145; case Item::PurpurSlab: return 127; case Item::PurpurStairs: return 146; case Item::Quartz: return 711; case Item::QuartzBlock: return 258; case Item::QuartzPillar: return 259; case Item::QuartzSlab: return 125; case Item::QuartzStairs: return 260; case Item::Rabbit: return 716; case Item::RabbitFoot: return 719; case Item::RabbitHide: return 720; case Item::RabbitSpawnEgg: return 662; case Item::RabbitStew: return 718; case Item::Rail: return 156; case Item::RedBanner: return 744; case Item::RedBed: return 605; case Item::RedCarpet: return 296; case Item::RedConcrete: return 409; case Item::RedConcretePowder: return 425; case Item::RedGlazedTerracotta: return 393; case Item::RedMushroom: return 109; case Item::RedMushroomBlock: return 204; case Item::RedNetherBricks: return 358; case Item::RedSand: return 27; case Item::RedSandstone: return 350; case Item::RedSandstoneSlab: return 126; case Item::RedSandstoneStairs: return 353; case Item::RedShulkerBox: return 377; case Item::RedStainedGlass: return 325; case Item::RedStainedGlassPane: return 341; case Item::RedTerracotta: return 277; case Item::RedTulip: return 103; case Item::RedWool: return 96; case Item::Redstone: return 542; case Item::RedstoneBlock: return 254; case Item::RedstoneLamp: return 228; case Item::RedstoneOre: return 166; case Item::RedstoneTorch: return 167; case Item::Repeater: return 462; case Item::RepeatingCommandBlock: return 354; case Item::RoseBush: return 307; case Item::RedDye: return 573; case Item::RottenFlesh: return 618; case Item::Saddle: return 541; case Item::Salmon: return 567; case Item::SalmonBucket: return 548; case Item::SalmonSpawnEgg: return 663; case Item::Sand: return 26; case Item::Sandstone: return 68; case Item::SandstoneSlab: return 119; case Item::SandstoneStairs: return 229; case Item::Scute: return 466; case Item::SeaLantern: return 349; case Item::SeaPickle: return 80; case Item::Seagrass: return 79; case Item::Shears: return 609; case Item::SheepSpawnEgg: return 664; case Item::Shield: return 757; case Item::ShulkerBox: return 362; case Item::ShulkerShell: return 765; case Item::ShulkerSpawnEgg: return 665; case Item::OakSign: return 536; case Item::SilverfishSpawnEgg: return 666; case Item::SkeletonHorseSpawnEgg: return 668; case Item::SkeletonSkull: return 698; case Item::SkeletonSpawnEgg: return 667; case Item::SlimeBall: return 558; case Item::SlimeBlock: return 303; case Item::SlimeSpawnEgg: return 669; case Item::SmoothQuartz: return 131; case Item::SmoothRedSandstone: return 132; case Item::SmoothSandstone: return 133; case Item::SmoothStone: return 134; case Item::Snow: return 169; case Item::SnowBlock: return 171; case Item::Snowball: return 543; case Item::SoulSand: return 184; case Item::Spawner: return 147; case Item::SpectralArrow: return 754; case Item::SpiderEye: return 626; case Item::SpiderSpawnEgg: return 670; case Item::SplashPotion: return 753; case Item::Sponge: return 62; case Item::SpruceBoat: return 759; case Item::SpruceButton: return 242; case Item::SpruceDoor: return 457; case Item::SpruceFence: return 176; case Item::SpruceFenceGate: return 211; case Item::SpruceLeaves: return 57; case Item::SpruceLog: return 33; case Item::SprucePlanks: return 14; case Item::SprucePressurePlate: return 161; case Item::SpruceSapling: return 20; case Item::SpruceSlab: return 113; case Item::SpruceStairs: return 234; case Item::SpruceTrapdoor: return 188; case Item::SpruceWood: return 51; case Item::SquidSpawnEgg: return 671; case Item::Stick: return 492; case Item::StickyPiston: return 74; case Item::Stone: return 1; case Item::StoneAxe: return 487; case Item::StoneBrickSlab: return 123; case Item::StoneBrickStairs: return 217; case Item::StoneBricks: return 199; case Item::StoneButton: return 168; case Item::StoneHoe: return 503; case Item::StonePickaxe: return 486; case Item::StonePressurePlate: return 159; case Item::StoneShovel: return 485; case Item::StoneSlab: return 118; case Item::StoneSword: return 484; case Item::StraySpawnEgg: return 672; case Item::String: return 499; case Item::StrippedAcaciaLog: return 42; case Item::StrippedAcaciaWood: return 48; case Item::StrippedBirchLog: return 40; case Item::StrippedBirchWood: return 46; case Item::StrippedDarkOakLog: return 43; case Item::StrippedDarkOakWood: return 49; case Item::StrippedJungleLog: return 41; case Item::StrippedJungleWood: return 47; case Item::StrippedOakLog: return 38; case Item::StrippedOakWood: return 44; case Item::StrippedSpruceLog: return 39; case Item::StrippedSpruceWood: return 45; case Item::StructureBlock: return 464; case Item::StructureVoid: return 360; case Item::Sugar: return 589; case Item::SugarCane: return 553; case Item::Sunflower: return 305; case Item::TallGrass: return 309; case Item::Terracotta: return 298; case Item::TippedArrow: return 755; case Item::TNT: return 136; case Item::TNTMinecart: return 712; case Item::Torch: return 140; case Item::TotemOfUndying: return 764; case Item::TrappedChest: return 250; case Item::Trident: return 781; case Item::TripwireHook: return 232; case Item::TropicalFish: return 568; case Item::TropicalFishBucket: return 550; case Item::TropicalFishSpawnEgg: return 673; case Item::TubeCoral: return 438; case Item::TubeCoralBlock: return 433; case Item::TubeCoralFan: return 443; case Item::TurtleEgg: return 427; case Item::TurtleHelmet: return 465; case Item::TurtleSpawnEgg: return 674; case Item::VexSpawnEgg: return 675; case Item::VillagerSpawnEgg: return 676; case Item::VindicatorSpawnEgg: return 677; case Item::Vine: return 209; case Item::WaterBucket: return 538; case Item::WetSponge: return 63; case Item::Wheat: return 508; case Item::WheatSeeds: return 507; case Item::WhiteBanner: return 730; case Item::WhiteBed: return 591; case Item::WhiteCarpet: return 282; case Item::WhiteConcrete: return 395; case Item::WhiteConcretePowder: return 411; case Item::WhiteGlazedTerracotta: return 379; case Item::WhiteShulkerBox: return 363; case Item::WhiteStainedGlass: return 311; case Item::WhiteStainedGlassPane: return 327; case Item::WhiteTerracotta: return 263; case Item::WhiteTulip: return 105; case Item::WhiteWool: return 82; case Item::WitchSpawnEgg: return 678; case Item::WitherSkeletonSkull: return 699; case Item::WitherSkeletonSpawnEgg: return 679; case Item::WolfSpawnEgg: return 680; case Item::WoodenAxe: return 483; case Item::WoodenHoe: return 502; case Item::WoodenPickaxe: return 482; case Item::WoodenShovel: return 481; case Item::WoodenSword: return 480; case Item::WritableBook: return 687; case Item::WrittenBook: return 688; case Item::YellowBanner: return 734; case Item::YellowBed: return 595; case Item::YellowCarpet: return 286; case Item::YellowConcrete: return 399; case Item::YellowConcretePowder: return 415; case Item::YellowGlazedTerracotta: return 383; case Item::YellowShulkerBox: return 367; case Item::YellowStainedGlass: return 315; case Item::YellowStainedGlassPane: return 331; case Item::YellowTerracotta: return 267; case Item::YellowWool: return 86; case Item::ZombieHead: return 701; case Item::ZombieHorseSpawnEgg: return 682; case Item::ZombiePigmanSpawnEgg: return 683; case Item::ZombieSpawnEgg: return 681; case Item::ZombieVillagerSpawnEgg: return 684; default: return 0; } } UInt32 From(const CustomStatistic ID) { switch (ID) { case CustomStatistic::AnimalsBred: return 25; case CustomStatistic::AviateOneCm: return 17; case CustomStatistic::BoatOneCm: return 14; case CustomStatistic::CleanArmor: return 33; case CustomStatistic::CleanBanner: return 34; case CustomStatistic::ClimbOneCm: return 10; case CustomStatistic::CrouchOneCm: return 6; case CustomStatistic::DamageDealt: return 21; case CustomStatistic::DamageTaken: return 22; case CustomStatistic::Deaths: return 23; case CustomStatistic::Drop: return 20; case CustomStatistic::EatCakeSlice: return 30; case CustomStatistic::EnchantItem: return 45; case CustomStatistic::FallOneCm: return 9; case CustomStatistic::FillCauldron: return 31; case CustomStatistic::FishCaught: return 27; case CustomStatistic::FlyOneCm: return 11; case CustomStatistic::HorseOneCm: return 16; case CustomStatistic::InspectDispenser: return 39; case CustomStatistic::InspectDropper: return 37; case CustomStatistic::InspectHopper: return 38; case CustomStatistic::InteractWithBeacon: return 36; case CustomStatistic::InteractWithBrewingstand: return 35; case CustomStatistic::InteractWithCraftingTable: return 48; case CustomStatistic::InteractWithFurnace: return 47; case CustomStatistic::Jump: return 19; case CustomStatistic::LeaveGame: return 0; case CustomStatistic::MinecartOneCm: return 13; case CustomStatistic::MobKills: return 24; case CustomStatistic::OpenChest: return 49; case CustomStatistic::OpenEnderchest: return 44; case CustomStatistic::OpenShulkerBox: return 51; case CustomStatistic::PigOneCm: return 15; case CustomStatistic::PlayerKills: return 26; case CustomStatistic::PlayNoteblock: return 40; case CustomStatistic::PlayOneMinute: return 1; case CustomStatistic::PlayRecord: return 46; case CustomStatistic::PotFlower: return 42; case CustomStatistic::SleepInBed: return 50; case CustomStatistic::SneakTime: return 4; case CustomStatistic::SprintOneCm: return 7; case CustomStatistic::SwimOneCm: return 8; case CustomStatistic::TalkedToVillager: return 28; case CustomStatistic::TimeSinceDeath: return 2; case CustomStatistic::TimeSinceRest: return 3; case CustomStatistic::TradedWithVillager: return 29; case CustomStatistic::TriggerTrappedChest: return 43; case CustomStatistic::TuneNoteblock: return 41; case CustomStatistic::UseCauldron: return 32; case CustomStatistic::WalkOneCm: return 5; case CustomStatistic::WalkOnWaterOneCm: return 18; case CustomStatistic::WalkUnderWaterOneCm: return 12; default: return UInt32(-1); } } Item ToItem(const UInt32 ID) { switch (ID) { case 762: return Item::AcaciaBoat; case 245: return Item::AcaciaButton; case 460: return Item::AcaciaDoor; case 179: return Item::AcaciaFence; case 214: return Item::AcaciaFenceGate; case 60: return Item::AcaciaLeaves; case 36: return Item::AcaciaLog; case 17: return Item::AcaciaPlanks; case 164: return Item::AcaciaPressurePlate; case 23: return Item::AcaciaSapling; case 116: return Item::AcaciaSlab; case 301: return Item::AcaciaStairs; case 191: return Item::AcaciaTrapdoor; case 54: return Item::AcaciaWood; case 261: return Item::ActivatorRail; case -0: return Item::Air; case 101: return Item::Allium; case 6: return Item::Andesite; case 247: return Item::Anvil; case 471: return Item::Apple; case 721: return Item::ArmorStand; case 473: return Item::Arrow; case 102: return Item::AzureBluet; case 694: return Item::BakedPotato; case 279: return Item::Barrier; case 634: return Item::BatSpawnEgg; case 238: return Item::Beacon; case 25: return Item::Bedrock; case 614: return Item::Beef; case 749: return Item::Beetroot; case 750: return Item::BeetrootSeeds; case 751: return Item::BeetrootSoup; case 760: return Item::BirchBoat; case 243: return Item::BirchButton; case 458: return Item::BirchDoor; case 177: return Item::BirchFence; case 212: return Item::BirchFenceGate; case 58: return Item::BirchLeaves; case 34: return Item::BirchLog; case 15: return Item::BirchPlanks; case 162: return Item::BirchPressurePlate; case 21: return Item::BirchSapling; case 114: return Item::BirchSlab; case 235: return Item::BirchStairs; case 189: return Item::BirchTrapdoor; case 52: return Item::BirchWood; case 745: return Item::BlackBanner; case 606: return Item::BlackBed; case 297: return Item::BlackCarpet; case 410: return Item::BlackConcrete; case 426: return Item::BlackConcretePowder; case 394: return Item::BlackGlazedTerracotta; case 378: return Item::BlackShulkerBox; case 326: return Item::BlackStainedGlass; case 342: return Item::BlackStainedGlassPane; case 278: return Item::BlackTerracotta; case 97: return Item::BlackWool; case 628: return Item::BlazePowder; case 620: return Item::BlazeRod; case 635: return Item::BlazeSpawnEgg; case 741: return Item::BlueBanner; case 602: return Item::BlueBed; case 293: return Item::BlueCarpet; case 406: return Item::BlueConcrete; case 422: return Item::BlueConcretePowder; case 390: return Item::BlueGlazedTerracotta; case 453: return Item::BlueIce; case 100: return Item::BlueOrchid; case 374: return Item::BlueShulkerBox; case 322: return Item::BlueStainedGlass; case 338: return Item::BlueStainedGlassPane; case 274: return Item::BlueTerracotta; case 93: return Item::BlueWool; case 588: return Item::Bone; case 359: return Item::BoneBlock; case 587: return Item::BoneMeal; case 557: return Item::Book; case 137: return Item::Bookshelf; case 472: return Item::Bow; case 493: return Item::Bowl; case 439: return Item::BrainCoral; case 434: return Item::BrainCoralBlock; case 444: return Item::BrainCoralFan; case 509: return Item::Bread; case 630: return Item::BrewingStand; case 551: return Item::Brick; case 122: return Item::BrickSlab; case 216: return Item::BrickStairs; case 135: return Item::Bricks; case 742: return Item::BrownBanner; case 603: return Item::BrownBed; case 294: return Item::BrownCarpet; case 407: return Item::BrownConcrete; case 423: return Item::BrownConcretePowder; case 391: return Item::BrownGlazedTerracotta; case 108: return Item::BrownMushroom; case 203: return Item::BrownMushroomBlock; case 375: return Item::BrownShulkerBox; case 323: return Item::BrownStainedGlass; case 339: return Item::BrownStainedGlassPane; case 275: return Item::BrownTerracotta; case 94: return Item::BrownWool; case 440: return Item::BubbleCoral; case 435: return Item::BubbleCoralBlock; case 445: return Item::BubbleCoralFan; case 537: return Item::Bucket; case 172: return Item::Cactus; case 574: return Item::GreenDye; case 590: return Item::Cake; case 692: return Item::Carrot; case 704: return Item::CarrotOnAStick; case 182: return Item::CarvedPumpkin; case 631: return Item::Cauldron; case 636: return Item::CaveSpiderSpawnEgg; case 355: return Item::ChainCommandBlock; case 517: return Item::ChainmailBoots; case 515: return Item::ChainmailChestplate; case 514: return Item::ChainmailHelmet; case 516: return Item::ChainmailLeggings; case 475: return Item::Charcoal; case 149: return Item::Chest; case 559: return Item::ChestMinecart; case 616: return Item::Chicken; case 637: return Item::ChickenSpawnEgg; case 248: return Item::ChippedAnvil; case 257: return Item::ChiseledQuartzBlock; case 351: return Item::ChiseledRedSandstone; case 69: return Item::ChiseledSandstone; case 202: return Item::ChiseledStoneBricks; case 143: return Item::ChorusFlower; case 747: return Item::ChorusFruit; case 142: return Item::ChorusPlant; case 173: return Item::Clay; case 552: return Item::ClayBall; case 564: return Item::Clock; case 474: return Item::Coal; case 299: return Item::CoalBlock; case 31: return Item::CoalOre; case 10: return Item::CoarseDirt; case 12: return Item::Cobblestone; case 121: return Item::CobblestoneSlab; case 157: return Item::CobblestoneStairs; case 239: return Item::CobblestoneWall; case 75: return Item::Cobweb; case 575: return Item::CocoaBeans; case 566: return Item::Cod; case 549: return Item::CodBucket; case 638: return Item::CodSpawnEgg; case 237: return Item::CommandBlock; case 727: return Item::CommandBlockMinecart; case 463: return Item::Comparator; case 562: return Item::Compass; case 454: return Item::Conduit; case 615: return Item::CookedBeef; case 617: return Item::CookedChicken; case 570: return Item::CookedCod; case 729: return Item::CookedMutton; case 532: return Item::CookedPorkchop; case 717: return Item::CookedRabbit; case 571: return Item::CookedSalmon; case 607: return Item::Cookie; case 639: return Item::CowSpawnEgg; case 201: return Item::CrackedStoneBricks; case 152: return Item::CraftingTable; case 702: return Item::CreeperHead; case 640: return Item::CreeperSpawnEgg; case 352: return Item::CutRedSandstone; case 70: return Item::CutSandstone; case 739: return Item::CyanBanner; case 600: return Item::CyanBed; case 291: return Item::CyanCarpet; case 404: return Item::CyanConcrete; case 420: return Item::CyanConcretePowder; case 578: return Item::CyanDye; case 388: return Item::CyanGlazedTerracotta; case 372: return Item::CyanShulkerBox; case 320: return Item::CyanStainedGlass; case 336: return Item::CyanStainedGlassPane; case 272: return Item::CyanTerracotta; case 91: return Item::CyanWool; case 249: return Item::DamagedAnvil; case 98: return Item::Dandelion; case 583: return Item::YellowDye; case 763: return Item::DarkOakBoat; case 246: return Item::DarkOakButton; case 461: return Item::DarkOakDoor; case 180: return Item::DarkOakFence; case 215: return Item::DarkOakFenceGate; case 61: return Item::DarkOakLeaves; case 37: return Item::DarkOakLog; case 18: return Item::DarkOakPlanks; case 165: return Item::DarkOakPressurePlate; case 24: return Item::DarkOakSapling; case 117: return Item::DarkOakSlab; case 302: return Item::DarkOakStairs; case 192: return Item::DarkOakTrapdoor; case 55: return Item::DarkOakWood; case 345: return Item::DarkPrismarine; case 130: return Item::DarkPrismarineSlab; case 348: return Item::DarkPrismarineStairs; case 253: return Item::DaylightDetector; case 429: return Item::DeadBrainCoralBlock; case 449: return Item::DeadBrainCoralFan; case 430: return Item::DeadBubbleCoralBlock; case 450: return Item::DeadBubbleCoralFan; case 78: return Item::DeadBush; case 431: return Item::DeadFireCoralBlock; case 451: return Item::DeadFireCoralFan; case 432: return Item::DeadHornCoralBlock; case 452: return Item::DeadHornCoralFan; case 428: return Item::DeadTubeCoralBlock; case 448: return Item::DeadTubeCoralFan; case 768: return Item::DebugStick; case 73: return Item::DetectorRail; case 476: return Item::Diamond; case 491: return Item::DiamondAxe; case 151: return Item::DiamondBlock; case 525: return Item::DiamondBoots; case 523: return Item::DiamondChestplate; case 522: return Item::DiamondHelmet; case 505: return Item::DiamondHoe; case 724: return Item::DiamondHorseArmor; case 524: return Item::DiamondLeggings; case 150: return Item::DiamondOre; case 490: return Item::DiamondPickaxe; case 489: return Item::DiamondShovel; case 488: return Item::DiamondSword; case 4: return Item::Diorite; case 9: return Item::Dirt; case 67: return Item::Dispenser; case 641: return Item::DolphinSpawnEgg; case 642: return Item::DonkeySpawnEgg; case 752: return Item::DragonBreath; case 227: return Item::DragonEgg; case 703: return Item::DragonHead; case 611: return Item::DriedKelp; case 555: return Item::DriedKelpBlock; case 262: return Item::Dropper; case 643: return Item::DrownedSpawnEgg; case 561: return Item::Egg; case 644: return Item::ElderGuardianSpawnEgg; case 758: return Item::Elytra; case 689: return Item::Emerald; case 233: return Item::EmeraldBlock; case 230: return Item::EmeraldOre; case 709: return Item::EnchantedBook; case 535: return Item::EnchantedGoldenApple; case 223: return Item::EnchantingTable; case 746: return Item::EndCrystal; case 224: return Item::EndPortalFrame; case 141: return Item::EndRod; case 225: return Item::EndStone; case 226: return Item::EndStoneBricks; case 231: return Item::EnderChest; case 632: return Item::EnderEye; case 619: return Item::EnderPearl; case 645: return Item::EndermanSpawnEgg; case 646: return Item::EndermiteSpawnEgg; case 647: return Item::EvokerSpawnEgg; case 685: return Item::ExperienceBottle; case 153: return Item::Farmland; case 500: return Item::Feather; case 627: return Item::FermentedSpiderEye; case 77: return Item::Fern; case 608: return Item::FilledMap; case 686: return Item::FireCharge; case 441: return Item::FireCoral; case 436: return Item::FireCoralBlock; case 446: return Item::FireCoralFan; case 707: return Item::FireworkRocket; case 708: return Item::FireworkStar; case 563: return Item::FishingRod; case 530: return Item::Flint; case 470: return Item::FlintAndSteel; case 691: return Item::FlowerPot; case 154: return Item::Furnace; case 560: return Item::FurnaceMinecart; case 648: return Item::GhastSpawnEgg; case 621: return Item::GhastTear; case 64: return Item::Glass; case 625: return Item::GlassBottle; case 207: return Item::GlassPane; case 633: return Item::GlisteringMelonSlice; case 185: return Item::Glowstone; case 565: return Item::GlowstoneDust; case 110: return Item::GoldBlock; case 478: return Item::GoldIngot; case 622: return Item::GoldNugget; case 29: return Item::GoldOre; case 534: return Item::GoldenApple; case 498: return Item::GoldenAxe; case 529: return Item::GoldenBoots; case 697: return Item::GoldenCarrot; case 527: return Item::GoldenChestplate; case 526: return Item::GoldenHelmet; case 506: return Item::GoldenHoe; case 723: return Item::GoldenHorseArmor; case 528: return Item::GoldenLeggings; case 497: return Item::GoldenPickaxe; case 496: return Item::GoldenShovel; case 495: return Item::GoldenSword; case 2: return Item::Granite; case 76: return Item::Grass; case 8: return Item::GrassBlock; case 304: return Item::GrassPath; case 28: return Item::Gravel; case 737: return Item::GrayBanner; case 598: return Item::GrayBed; case 289: return Item::GrayCarpet; case 402: return Item::GrayConcrete; case 418: return Item::GrayConcretePowder; case 580: return Item::GrayDye; case 386: return Item::GrayGlazedTerracotta; case 370: return Item::GrayShulkerBox; case 318: return Item::GrayStainedGlass; case 334: return Item::GrayStainedGlassPane; case 270: return Item::GrayTerracotta; case 89: return Item::GrayWool; case 743: return Item::GreenBanner; case 604: return Item::GreenBed; case 295: return Item::GreenCarpet; case 408: return Item::GreenConcrete; case 424: return Item::GreenConcretePowder; case 392: return Item::GreenGlazedTerracotta; case 376: return Item::GreenShulkerBox; case 324: return Item::GreenStainedGlass; case 340: return Item::GreenStainedGlassPane; case 276: return Item::GreenTerracotta; case 95: return Item::GreenWool; case 649: return Item::GuardianSpawnEgg; case 501: return Item::Gunpowder; case 281: return Item::HayBale; case 784: return Item::HeartOfTheSea; case 252: return Item::HeavyWeightedPressurePlate; case 256: return Item::Hopper; case 713: return Item::HopperMinecart; case 442: return Item::HornCoral; case 437: return Item::HornCoralBlock; case 447: return Item::HornCoralFan; case 650: return Item::HorseSpawnEgg; case 651: return Item::HuskSpawnEgg; case 170: return Item::Ice; case 198: return Item::InfestedChiseledStoneBricks; case 194: return Item::InfestedCobblestone; case 197: return Item::InfestedCrackedStoneBricks; case 196: return Item::InfestedMossyStoneBricks; case 193: return Item::InfestedStone; case 195: return Item::InfestedStoneBricks; case 572: return Item::InkSac; case 469: return Item::IronAxe; case 206: return Item::IronBars; case 111: return Item::IronBlock; case 521: return Item::IronBoots; case 519: return Item::IronChestplate; case 455: return Item::IronDoor; case 518: return Item::IronHelmet; case 504: return Item::IronHoe; case 722: return Item::IronHorseArmor; case 477: return Item::IronIngot; case 520: return Item::IronLeggings; case 766: return Item::IronNugget; case 30: return Item::IronOre; case 468: return Item::IronPickaxe; case 467: return Item::IronShovel; case 479: return Item::IronSword; case 280: return Item::IronTrapdoor; case 690: return Item::ItemFrame; case 186: return Item::JackOLantern; case 174: return Item::Jukebox; case 761: return Item::JungleBoat; case 244: return Item::JungleButton; case 459: return Item::JungleDoor; case 178: return Item::JungleFence; case 213: return Item::JungleFenceGate; case 59: return Item::JungleLeaves; case 35: return Item::JungleLog; case 16: return Item::JunglePlanks; case 163: return Item::JunglePressurePlate; case 22: return Item::JungleSapling; case 115: return Item::JungleSlab; case 236: return Item::JungleStairs; case 190: return Item::JungleTrapdoor; case 53: return Item::JungleWood; case 554: return Item::Kelp; case 767: return Item::KnowledgeBook; case 155: return Item::Ladder; case 66: return Item::LapisBlock; case 576: return Item::LapisLazuli; case 65: return Item::LapisOre; case 310: return Item::LargeFern; case 539: return Item::LavaBucket; case 725: return Item::Lead; case 545: return Item::Leather; case 513: return Item::LeatherBoots; case 511: return Item::LeatherChestplate; case 510: return Item::LeatherHelmet; case 512: return Item::LeatherLeggings; case 158: return Item::Lever; case 733: return Item::LightBlueBanner; case 594: return Item::LightBlueBed; case 285: return Item::LightBlueCarpet; case 398: return Item::LightBlueConcrete; case 414: return Item::LightBlueConcretePowder; case 584: return Item::LightBlueDye; case 382: return Item::LightBlueGlazedTerracotta; case 366: return Item::LightBlueShulkerBox; case 314: return Item::LightBlueStainedGlass; case 330: return Item::LightBlueStainedGlassPane; case 266: return Item::LightBlueTerracotta; case 85: return Item::LightBlueWool; case 738: return Item::LightGrayBanner; case 599: return Item::LightGrayBed; case 290: return Item::LightGrayCarpet; case 403: return Item::LightGrayConcrete; case 419: return Item::LightGrayConcretePowder; case 579: return Item::LightGrayDye; case 387: return Item::LightGrayGlazedTerracotta; case 371: return Item::LightGrayShulkerBox; case 319: return Item::LightGrayStainedGlass; case 335: return Item::LightGrayStainedGlassPane; case 271: return Item::LightGrayTerracotta; case 90: return Item::LightGrayWool; case 251: return Item::LightWeightedPressurePlate; case 306: return Item::Lilac; case 219: return Item::LilyPad; case 735: return Item::LimeBanner; case 596: return Item::LimeBed; case 287: return Item::LimeCarpet; case 400: return Item::LimeConcrete; case 416: return Item::LimeConcretePowder; case 582: return Item::LimeDye; case 384: return Item::LimeGlazedTerracotta; case 368: return Item::LimeShulkerBox; case 316: return Item::LimeStainedGlass; case 332: return Item::LimeStainedGlassPane; case 268: return Item::LimeTerracotta; case 87: return Item::LimeWool; case 756: return Item::LingeringPotion; case 652: return Item::LlamaSpawnEgg; case 732: return Item::MagentaBanner; case 593: return Item::MagentaBed; case 284: return Item::MagentaCarpet; case 397: return Item::MagentaConcrete; case 413: return Item::MagentaConcretePowder; case 585: return Item::MagentaDye; case 381: return Item::MagentaGlazedTerracotta; case 365: return Item::MagentaShulkerBox; case 313: return Item::MagentaStainedGlass; case 329: return Item::MagentaStainedGlassPane; case 265: return Item::MagentaTerracotta; case 84: return Item::MagentaWool; case 356: return Item::MagmaBlock; case 629: return Item::MagmaCream; case 653: return Item::MagmaCubeSpawnEgg; case 696: return Item::Map; case 208: return Item::Melon; case 613: return Item::MelonSeeds; case 610: return Item::MelonSlice; case 546: return Item::MilkBucket; case 540: return Item::Minecart; case 654: return Item::MooshroomSpawnEgg; case 138: return Item::MossyCobblestone; case 240: return Item::MossyCobblestoneWall; case 200: return Item::MossyStoneBricks; case 655: return Item::MuleSpawnEgg; case 205: return Item::MushroomStem; case 494: return Item::MushroomStew; case 779: return Item::MusicDisc11; case 769: return Item::MusicDisc13; case 771: return Item::MusicDiscBlocks; case 770: return Item::MusicDiscCat; case 772: return Item::MusicDiscChirp; case 773: return Item::MusicDiscFar; case 774: return Item::MusicDiscMall; case 775: return Item::MusicDiscMellohi; case 776: return Item::MusicDiscStal; case 777: return Item::MusicDiscStrad; case 780: return Item::MusicDiscWait; case 778: return Item::MusicDiscWard; case 728: return Item::Mutton; case 218: return Item::Mycelium; case 726: return Item::NameTag; case 783: return Item::NautilusShell; case 710: return Item::NetherBrick; case 221: return Item::NetherBrickFence; case 124: return Item::NetherBrickSlab; case 222: return Item::NetherBrickStairs; case 220: return Item::NetherBricks; case 255: return Item::NetherQuartzOre; case 705: return Item::NetherStar; case 623: return Item::NetherWart; case 357: return Item::NetherWartBlock; case 183: return Item::Netherrack; case 71: return Item::NoteBlock; case 544: return Item::OakBoat; case 241: return Item::OakButton; case 456: return Item::OakDoor; case 175: return Item::OakFence; case 210: return Item::OakFenceGate; case 56: return Item::OakLeaves; case 32: return Item::OakLog; case 13: return Item::OakPlanks; case 160: return Item::OakPressurePlate; case 19: return Item::OakSapling; case 112: return Item::OakSlab; case 148: return Item::OakStairs; case 187: return Item::OakTrapdoor; case 50: return Item::OakWood; case 361: return Item::Observer; case 139: return Item::Obsidian; case 656: return Item::OcelotSpawnEgg; case 731: return Item::OrangeBanner; case 592: return Item::OrangeBed; case 283: return Item::OrangeCarpet; case 396: return Item::OrangeConcrete; case 412: return Item::OrangeConcretePowder; case 586: return Item::OrangeDye; case 380: return Item::OrangeGlazedTerracotta; case 364: return Item::OrangeShulkerBox; case 312: return Item::OrangeStainedGlass; case 328: return Item::OrangeStainedGlassPane; case 264: return Item::OrangeTerracotta; case 104: return Item::OrangeTulip; case 83: return Item::OrangeWool; case 107: return Item::OxeyeDaisy; case 300: return Item::PackedIce; case 533: return Item::Painting; case 556: return Item::Paper; case 657: return Item::ParrotSpawnEgg; case 308: return Item::Peony; case 120: return Item::PetrifiedOakSlab; case 782: return Item::PhantomMembrane; case 658: return Item::PhantomSpawnEgg; case 659: return Item::PigSpawnEgg; case 736: return Item::PinkBanner; case 597: return Item::PinkBed; case 288: return Item::PinkCarpet; case 401: return Item::PinkConcrete; case 417: return Item::PinkConcretePowder; case 581: return Item::PinkDye; case 385: return Item::PinkGlazedTerracotta; case 369: return Item::PinkShulkerBox; case 317: return Item::PinkStainedGlass; case 333: return Item::PinkStainedGlassPane; case 269: return Item::PinkTerracotta; case 106: return Item::PinkTulip; case 88: return Item::PinkWool; case 81: return Item::Piston; case 700: return Item::PlayerHead; case 11: return Item::Podzol; case 695: return Item::PoisonousPotato; case 660: return Item::PolarBearSpawnEgg; case 7: return Item::PolishedAndesite; case 5: return Item::PolishedDiorite; case 3: return Item::PolishedGranite; case 748: return Item::PoppedChorusFruit; case 99: return Item::Poppy; case 531: return Item::Porkchop; case 693: return Item::Potato; case 624: return Item::Potion; case 72: return Item::PoweredRail; case 343: return Item::Prismarine; case 129: return Item::PrismarineBrickSlab; case 347: return Item::PrismarineBrickStairs; case 344: return Item::PrismarineBricks; case 715: return Item::PrismarineCrystals; case 714: return Item::PrismarineShard; case 128: return Item::PrismarineSlab; case 346: return Item::PrismarineStairs; case 569: return Item::Pufferfish; case 547: return Item::PufferfishBucket; case 661: return Item::PufferfishSpawnEgg; case 181: return Item::Pumpkin; case 706: return Item::PumpkinPie; case 612: return Item::PumpkinSeeds; case 740: return Item::PurpleBanner; case 601: return Item::PurpleBed; case 292: return Item::PurpleCarpet; case 405: return Item::PurpleConcrete; case 421: return Item::PurpleConcretePowder; case 577: return Item::PurpleDye; case 389: return Item::PurpleGlazedTerracotta; case 373: return Item::PurpleShulkerBox; case 321: return Item::PurpleStainedGlass; case 337: return Item::PurpleStainedGlassPane; case 273: return Item::PurpleTerracotta; case 92: return Item::PurpleWool; case 144: return Item::PurpurBlock; case 145: return Item::PurpurPillar; case 127: return Item::PurpurSlab; case 146: return Item::PurpurStairs; case 711: return Item::Quartz; case 258: return Item::QuartzBlock; case 259: return Item::QuartzPillar; case 125: return Item::QuartzSlab; case 260: return Item::QuartzStairs; case 716: return Item::Rabbit; case 719: return Item::RabbitFoot; case 720: return Item::RabbitHide; case 662: return Item::RabbitSpawnEgg; case 718: return Item::RabbitStew; case 156: return Item::Rail; case 744: return Item::RedBanner; case 605: return Item::RedBed; case 296: return Item::RedCarpet; case 409: return Item::RedConcrete; case 425: return Item::RedConcretePowder; case 393: return Item::RedGlazedTerracotta; case 109: return Item::RedMushroom; case 204: return Item::RedMushroomBlock; case 358: return Item::RedNetherBricks; case 27: return Item::RedSand; case 350: return Item::RedSandstone; case 126: return Item::RedSandstoneSlab; case 353: return Item::RedSandstoneStairs; case 377: return Item::RedShulkerBox; case 325: return Item::RedStainedGlass; case 341: return Item::RedStainedGlassPane; case 277: return Item::RedTerracotta; case 103: return Item::RedTulip; case 96: return Item::RedWool; case 542: return Item::Redstone; case 254: return Item::RedstoneBlock; case 228: return Item::RedstoneLamp; case 166: return Item::RedstoneOre; case 167: return Item::RedstoneTorch; case 462: return Item::Repeater; case 354: return Item::RepeatingCommandBlock; case 307: return Item::RoseBush; case 573: return Item::RedDye; case 618: return Item::RottenFlesh; case 541: return Item::Saddle; case 567: return Item::Salmon; case 548: return Item::SalmonBucket; case 663: return Item::SalmonSpawnEgg; case 26: return Item::Sand; case 68: return Item::Sandstone; case 119: return Item::SandstoneSlab; case 229: return Item::SandstoneStairs; case 466: return Item::Scute; case 349: return Item::SeaLantern; case 80: return Item::SeaPickle; case 79: return Item::Seagrass; case 609: return Item::Shears; case 664: return Item::SheepSpawnEgg; case 757: return Item::Shield; case 362: return Item::ShulkerBox; case 765: return Item::ShulkerShell; case 665: return Item::ShulkerSpawnEgg; case 536: return Item::OakSign; case 666: return Item::SilverfishSpawnEgg; case 668: return Item::SkeletonHorseSpawnEgg; case 698: return Item::SkeletonSkull; case 667: return Item::SkeletonSpawnEgg; case 558: return Item::SlimeBall; case 303: return Item::SlimeBlock; case 669: return Item::SlimeSpawnEgg; case 131: return Item::SmoothQuartz; case 132: return Item::SmoothRedSandstone; case 133: return Item::SmoothSandstone; case 134: return Item::SmoothStone; case 169: return Item::Snow; case 171: return Item::SnowBlock; case 543: return Item::Snowball; case 184: return Item::SoulSand; case 147: return Item::Spawner; case 754: return Item::SpectralArrow; case 626: return Item::SpiderEye; case 670: return Item::SpiderSpawnEgg; case 753: return Item::SplashPotion; case 62: return Item::Sponge; case 759: return Item::SpruceBoat; case 242: return Item::SpruceButton; case 457: return Item::SpruceDoor; case 176: return Item::SpruceFence; case 211: return Item::SpruceFenceGate; case 57: return Item::SpruceLeaves; case 33: return Item::SpruceLog; case 14: return Item::SprucePlanks; case 161: return Item::SprucePressurePlate; case 20: return Item::SpruceSapling; case 113: return Item::SpruceSlab; case 234: return Item::SpruceStairs; case 188: return Item::SpruceTrapdoor; case 51: return Item::SpruceWood; case 671: return Item::SquidSpawnEgg; case 492: return Item::Stick; case 74: return Item::StickyPiston; case 1: return Item::Stone; case 487: return Item::StoneAxe; case 123: return Item::StoneBrickSlab; case 217: return Item::StoneBrickStairs; case 199: return Item::StoneBricks; case 168: return Item::StoneButton; case 503: return Item::StoneHoe; case 486: return Item::StonePickaxe; case 159: return Item::StonePressurePlate; case 485: return Item::StoneShovel; case 118: return Item::StoneSlab; case 484: return Item::StoneSword; case 672: return Item::StraySpawnEgg; case 499: return Item::String; case 42: return Item::StrippedAcaciaLog; case 48: return Item::StrippedAcaciaWood; case 40: return Item::StrippedBirchLog; case 46: return Item::StrippedBirchWood; case 43: return Item::StrippedDarkOakLog; case 49: return Item::StrippedDarkOakWood; case 41: return Item::StrippedJungleLog; case 47: return Item::StrippedJungleWood; case 38: return Item::StrippedOakLog; case 44: return Item::StrippedOakWood; case 39: return Item::StrippedSpruceLog; case 45: return Item::StrippedSpruceWood; case 464: return Item::StructureBlock; case 360: return Item::StructureVoid; case 589: return Item::Sugar; case 553: return Item::SugarCane; case 305: return Item::Sunflower; case 309: return Item::TallGrass; case 298: return Item::Terracotta; case 755: return Item::TippedArrow; case 136: return Item::TNT; case 712: return Item::TNTMinecart; case 140: return Item::Torch; case 764: return Item::TotemOfUndying; case 250: return Item::TrappedChest; case 781: return Item::Trident; case 232: return Item::TripwireHook; case 568: return Item::TropicalFish; case 550: return Item::TropicalFishBucket; case 673: return Item::TropicalFishSpawnEgg; case 438: return Item::TubeCoral; case 433: return Item::TubeCoralBlock; case 443: return Item::TubeCoralFan; case 427: return Item::TurtleEgg; case 465: return Item::TurtleHelmet; case 674: return Item::TurtleSpawnEgg; case 675: return Item::VexSpawnEgg; case 676: return Item::VillagerSpawnEgg; case 677: return Item::VindicatorSpawnEgg; case 209: return Item::Vine; case 538: return Item::WaterBucket; case 63: return Item::WetSponge; case 508: return Item::Wheat; case 507: return Item::WheatSeeds; case 730: return Item::WhiteBanner; case 591: return Item::WhiteBed; case 282: return Item::WhiteCarpet; case 395: return Item::WhiteConcrete; case 411: return Item::WhiteConcretePowder; case 379: return Item::WhiteGlazedTerracotta; case 363: return Item::WhiteShulkerBox; case 311: return Item::WhiteStainedGlass; case 327: return Item::WhiteStainedGlassPane; case 263: return Item::WhiteTerracotta; case 105: return Item::WhiteTulip; case 82: return Item::WhiteWool; case 678: return Item::WitchSpawnEgg; case 699: return Item::WitherSkeletonSkull; case 679: return Item::WitherSkeletonSpawnEgg; case 680: return Item::WolfSpawnEgg; case 483: return Item::WoodenAxe; case 502: return Item::WoodenHoe; case 482: return Item::WoodenPickaxe; case 481: return Item::WoodenShovel; case 480: return Item::WoodenSword; case 687: return Item::WritableBook; case 688: return Item::WrittenBook; case 734: return Item::YellowBanner; case 595: return Item::YellowBed; case 286: return Item::YellowCarpet; case 399: return Item::YellowConcrete; case 415: return Item::YellowConcretePowder; case 383: return Item::YellowGlazedTerracotta; case 367: return Item::YellowShulkerBox; case 315: return Item::YellowStainedGlass; case 331: return Item::YellowStainedGlassPane; case 267: return Item::YellowTerracotta; case 86: return Item::YellowWool; case 701: return Item::ZombieHead; case 682: return Item::ZombieHorseSpawnEgg; case 683: return Item::ZombiePigmanSpawnEgg; case 681: return Item::ZombieSpawnEgg; case 684: return Item::ZombieVillagerSpawnEgg; default: return Item::Air; } } } ================================================ FILE: src/Protocol/Palettes/Palette_1_13.h ================================================ #pragma once #include "BlockState.h" #include "Registries/Items.h" #include "Registries/CustomStatistics.h" namespace Palette_1_13 { UInt32 From(BlockState Block); UInt32 From(Item ID); UInt32 From(CustomStatistic ID); Item ToItem(UInt32 ID); } ================================================ FILE: src/Protocol/Palettes/Palette_1_13_1.cpp ================================================ #include "Globals.h" #include "Palette_1_13_1.h" #include "Registries/BlockStates.h" namespace Palette_1_13_1 { UInt32 From(const BlockState Block) { using namespace Block; switch (Block.ID) { case AcaciaButton::AcaciaButton(AcaciaButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5400; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5401; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5402; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5403; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, true).ID: return 5404; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, false).ID: return 5405; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, true).ID: return 5406; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, false).ID: return 5407; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5408; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5409; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5410; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5411; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, true).ID: return 5412; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, false).ID: return 5413; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, true).ID: return 5414; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, false).ID: return 5415; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5416; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5417; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5418; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5419; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, true).ID: return 5420; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, false).ID: return 5421; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, true).ID: return 5422; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, false).ID: return 5423; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, true, true).ID: return 7870; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, true, false).ID: return 7871; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, false, true).ID: return 7872; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, false, false).ID: return 7873; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, true, true).ID: return 7874; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, true, false).ID: return 7875; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, false, true).ID: return 7876; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, false, false).ID: return 7877; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, true, true).ID: return 7878; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, true, false).ID: return 7879; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, false, true).ID: return 7880; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, false, false).ID: return 7881; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, true, true).ID: return 7882; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, true, false).ID: return 7883; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, false, true).ID: return 7884; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, false, false).ID: return 7885; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, true, true).ID: return 7886; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, true, false).ID: return 7887; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, false, true).ID: return 7888; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, false, false).ID: return 7889; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, true, true).ID: return 7890; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, true, false).ID: return 7891; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, false, true).ID: return 7892; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, false, false).ID: return 7893; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, true, true).ID: return 7894; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, true, false).ID: return 7895; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, false, true).ID: return 7896; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, false, false).ID: return 7897; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, true, true).ID: return 7898; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, true, false).ID: return 7899; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, false, true).ID: return 7900; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, false, false).ID: return 7901; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, true, true).ID: return 7902; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, true, false).ID: return 7903; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, false, true).ID: return 7904; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, false, false).ID: return 7905; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, true, true).ID: return 7906; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, true, false).ID: return 7907; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, false, true).ID: return 7908; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, false, false).ID: return 7909; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, true, true).ID: return 7910; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, true, false).ID: return 7911; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, false, true).ID: return 7912; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, false, false).ID: return 7913; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, true, true).ID: return 7914; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, true, false).ID: return 7915; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, false, true).ID: return 7916; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, false, false).ID: return 7917; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, true, true).ID: return 7918; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, true, false).ID: return 7919; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, false, true).ID: return 7920; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, false, false).ID: return 7921; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, true, true).ID: return 7922; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, true, false).ID: return 7923; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, false, true).ID: return 7924; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, false, false).ID: return 7925; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, true, true).ID: return 7926; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, true, false).ID: return 7927; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, false, true).ID: return 7928; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, false, false).ID: return 7929; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, true, true).ID: return 7930; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, true, false).ID: return 7931; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, false, true).ID: return 7932; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, false, false).ID: return 7933; case AcaciaFence::AcaciaFence(true, true, true, true).ID: return 7616; case AcaciaFence::AcaciaFence(true, true, true, false).ID: return 7617; case AcaciaFence::AcaciaFence(true, true, false, true).ID: return 7620; case AcaciaFence::AcaciaFence(true, true, false, false).ID: return 7621; case AcaciaFence::AcaciaFence(true, false, true, true).ID: return 7624; case AcaciaFence::AcaciaFence(true, false, true, false).ID: return 7625; case AcaciaFence::AcaciaFence(true, false, false, true).ID: return 7628; case AcaciaFence::AcaciaFence(true, false, false, false).ID: return 7629; case AcaciaFence::AcaciaFence(false, true, true, true).ID: return 7632; case AcaciaFence::AcaciaFence(false, true, true, false).ID: return 7633; case AcaciaFence::AcaciaFence(false, true, false, true).ID: return 7636; case AcaciaFence::AcaciaFence(false, true, false, false).ID: return 7637; case AcaciaFence::AcaciaFence(false, false, true, true).ID: return 7640; case AcaciaFence::AcaciaFence(false, false, true, false).ID: return 7641; case AcaciaFence::AcaciaFence(false, false, false, true).ID: return 7644; case AcaciaFence::AcaciaFence(false, false, false, false).ID: return 7645; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZM, true, true, true).ID: return 7454; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZM, true, true, false).ID: return 7455; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZM, true, false, true).ID: return 7456; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZM, true, false, false).ID: return 7457; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, true).ID: return 7458; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, false).ID: return 7459; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, true).ID: return 7460; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, false).ID: return 7461; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZP, true, true, true).ID: return 7462; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZP, true, true, false).ID: return 7463; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZP, true, false, true).ID: return 7464; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZP, true, false, false).ID: return 7465; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, true).ID: return 7466; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, false).ID: return 7467; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, true).ID: return 7468; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, false).ID: return 7469; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XM, true, true, true).ID: return 7470; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XM, true, true, false).ID: return 7471; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XM, true, false, true).ID: return 7472; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XM, true, false, false).ID: return 7473; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, true).ID: return 7474; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, false).ID: return 7475; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, true).ID: return 7476; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, false).ID: return 7477; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XP, true, true, true).ID: return 7478; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XP, true, true, false).ID: return 7479; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XP, true, false, true).ID: return 7480; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XP, true, false, false).ID: return 7481; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, true).ID: return 7482; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, false).ID: return 7483; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, true).ID: return 7484; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, false).ID: return 7485; case AcaciaLeaves::AcaciaLeaves(1, true).ID: return 200; case AcaciaLeaves::AcaciaLeaves(1, false).ID: return 201; case AcaciaLeaves::AcaciaLeaves(2, true).ID: return 202; case AcaciaLeaves::AcaciaLeaves(2, false).ID: return 203; case AcaciaLeaves::AcaciaLeaves(3, true).ID: return 204; case AcaciaLeaves::AcaciaLeaves(3, false).ID: return 205; case AcaciaLeaves::AcaciaLeaves(4, true).ID: return 206; case AcaciaLeaves::AcaciaLeaves(4, false).ID: return 207; case AcaciaLeaves::AcaciaLeaves(5, true).ID: return 208; case AcaciaLeaves::AcaciaLeaves(5, false).ID: return 209; case AcaciaLeaves::AcaciaLeaves(6, true).ID: return 210; case AcaciaLeaves::AcaciaLeaves(6, false).ID: return 211; case AcaciaLeaves::AcaciaLeaves(7, true).ID: return 212; case AcaciaLeaves::AcaciaLeaves(7, false).ID: return 213; case AcaciaLog::AcaciaLog(AcaciaLog::Axis::X).ID: return 84; case AcaciaLog::AcaciaLog(AcaciaLog::Axis::Y).ID: return 85; case AcaciaLog::AcaciaLog(AcaciaLog::Axis::Z).ID: return 86; case AcaciaPlanks::AcaciaPlanks().ID: return 19; case AcaciaPressurePlate::AcaciaPressurePlate(true).ID: return 3376; case AcaciaPressurePlate::AcaciaPressurePlate(false).ID: return 3377; case AcaciaSapling::AcaciaSapling(0).ID: return 29; case AcaciaSapling::AcaciaSapling(1).ID: return 30; case AcaciaSlab::AcaciaSlab(AcaciaSlab::Type::Top).ID: return 7283; case AcaciaSlab::AcaciaSlab(AcaciaSlab::Type::Bottom).ID: return 7285; case AcaciaSlab::AcaciaSlab(AcaciaSlab::Type::Double).ID: return 7287; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZM, AcaciaStairs::Half::Top, AcaciaStairs::Shape::Straight).ID: return 6334; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZM, AcaciaStairs::Half::Top, AcaciaStairs::Shape::InnerLeft).ID: return 6336; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZM, AcaciaStairs::Half::Top, AcaciaStairs::Shape::InnerRight).ID: return 6338; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZM, AcaciaStairs::Half::Top, AcaciaStairs::Shape::OuterLeft).ID: return 6340; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZM, AcaciaStairs::Half::Top, AcaciaStairs::Shape::OuterRight).ID: return 6342; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZM, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::Straight).ID: return 6344; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZM, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::InnerLeft).ID: return 6346; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZM, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::InnerRight).ID: return 6348; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZM, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::OuterLeft).ID: return 6350; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZM, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::OuterRight).ID: return 6352; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZP, AcaciaStairs::Half::Top, AcaciaStairs::Shape::Straight).ID: return 6354; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZP, AcaciaStairs::Half::Top, AcaciaStairs::Shape::InnerLeft).ID: return 6356; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZP, AcaciaStairs::Half::Top, AcaciaStairs::Shape::InnerRight).ID: return 6358; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZP, AcaciaStairs::Half::Top, AcaciaStairs::Shape::OuterLeft).ID: return 6360; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZP, AcaciaStairs::Half::Top, AcaciaStairs::Shape::OuterRight).ID: return 6362; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZP, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::Straight).ID: return 6364; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZP, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::InnerLeft).ID: return 6366; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZP, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::InnerRight).ID: return 6368; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZP, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::OuterLeft).ID: return 6370; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZP, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::OuterRight).ID: return 6372; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XM, AcaciaStairs::Half::Top, AcaciaStairs::Shape::Straight).ID: return 6374; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XM, AcaciaStairs::Half::Top, AcaciaStairs::Shape::InnerLeft).ID: return 6376; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XM, AcaciaStairs::Half::Top, AcaciaStairs::Shape::InnerRight).ID: return 6378; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XM, AcaciaStairs::Half::Top, AcaciaStairs::Shape::OuterLeft).ID: return 6380; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XM, AcaciaStairs::Half::Top, AcaciaStairs::Shape::OuterRight).ID: return 6382; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XM, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::Straight).ID: return 6384; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XM, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::InnerLeft).ID: return 6386; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XM, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::InnerRight).ID: return 6388; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XM, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::OuterLeft).ID: return 6390; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XM, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::OuterRight).ID: return 6392; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XP, AcaciaStairs::Half::Top, AcaciaStairs::Shape::Straight).ID: return 6394; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XP, AcaciaStairs::Half::Top, AcaciaStairs::Shape::InnerLeft).ID: return 6396; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XP, AcaciaStairs::Half::Top, AcaciaStairs::Shape::InnerRight).ID: return 6398; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XP, AcaciaStairs::Half::Top, AcaciaStairs::Shape::OuterLeft).ID: return 6400; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XP, AcaciaStairs::Half::Top, AcaciaStairs::Shape::OuterRight).ID: return 6402; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XP, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::Straight).ID: return 6404; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XP, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::InnerLeft).ID: return 6406; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XP, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::InnerRight).ID: return 6408; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XP, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::OuterLeft).ID: return 6410; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XP, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::OuterRight).ID: return 6412; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZM, AcaciaTrapdoor::Half::Top, true, true).ID: return 3851; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZM, AcaciaTrapdoor::Half::Top, true, false).ID: return 3853; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZM, AcaciaTrapdoor::Half::Top, false, true).ID: return 3855; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZM, AcaciaTrapdoor::Half::Top, false, false).ID: return 3857; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZM, AcaciaTrapdoor::Half::Bottom, true, true).ID: return 3859; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZM, AcaciaTrapdoor::Half::Bottom, true, false).ID: return 3861; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZM, AcaciaTrapdoor::Half::Bottom, false, true).ID: return 3863; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZM, AcaciaTrapdoor::Half::Bottom, false, false).ID: return 3865; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZP, AcaciaTrapdoor::Half::Top, true, true).ID: return 3867; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZP, AcaciaTrapdoor::Half::Top, true, false).ID: return 3869; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZP, AcaciaTrapdoor::Half::Top, false, true).ID: return 3871; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZP, AcaciaTrapdoor::Half::Top, false, false).ID: return 3873; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZP, AcaciaTrapdoor::Half::Bottom, true, true).ID: return 3875; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZP, AcaciaTrapdoor::Half::Bottom, true, false).ID: return 3877; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZP, AcaciaTrapdoor::Half::Bottom, false, true).ID: return 3879; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZP, AcaciaTrapdoor::Half::Bottom, false, false).ID: return 3881; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XM, AcaciaTrapdoor::Half::Top, true, true).ID: return 3883; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XM, AcaciaTrapdoor::Half::Top, true, false).ID: return 3885; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XM, AcaciaTrapdoor::Half::Top, false, true).ID: return 3887; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XM, AcaciaTrapdoor::Half::Top, false, false).ID: return 3889; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XM, AcaciaTrapdoor::Half::Bottom, true, true).ID: return 3891; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XM, AcaciaTrapdoor::Half::Bottom, true, false).ID: return 3893; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XM, AcaciaTrapdoor::Half::Bottom, false, true).ID: return 3895; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XM, AcaciaTrapdoor::Half::Bottom, false, false).ID: return 3897; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XP, AcaciaTrapdoor::Half::Top, true, true).ID: return 3899; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XP, AcaciaTrapdoor::Half::Top, true, false).ID: return 3901; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XP, AcaciaTrapdoor::Half::Top, false, true).ID: return 3903; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XP, AcaciaTrapdoor::Half::Top, false, false).ID: return 3905; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XP, AcaciaTrapdoor::Half::Bottom, true, true).ID: return 3907; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XP, AcaciaTrapdoor::Half::Bottom, true, false).ID: return 3909; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XP, AcaciaTrapdoor::Half::Bottom, false, true).ID: return 3911; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XP, AcaciaTrapdoor::Half::Bottom, false, false).ID: return 3913; case AcaciaWood::AcaciaWood(AcaciaWood::Axis::X).ID: return 120; case AcaciaWood::AcaciaWood(AcaciaWood::Axis::Y).ID: return 121; case AcaciaWood::AcaciaWood(AcaciaWood::Axis::Z).ID: return 122; case ActivatorRail::ActivatorRail(true, ActivatorRail::Shape::NorthSouth).ID: return 5781; case ActivatorRail::ActivatorRail(true, ActivatorRail::Shape::EastWest).ID: return 5782; case ActivatorRail::ActivatorRail(true, ActivatorRail::Shape::AscendingEast).ID: return 5783; case ActivatorRail::ActivatorRail(true, ActivatorRail::Shape::AscendingWest).ID: return 5784; case ActivatorRail::ActivatorRail(true, ActivatorRail::Shape::AscendingNorth).ID: return 5785; case ActivatorRail::ActivatorRail(true, ActivatorRail::Shape::AscendingSouth).ID: return 5786; case ActivatorRail::ActivatorRail(false, ActivatorRail::Shape::NorthSouth).ID: return 5787; case ActivatorRail::ActivatorRail(false, ActivatorRail::Shape::EastWest).ID: return 5788; case ActivatorRail::ActivatorRail(false, ActivatorRail::Shape::AscendingEast).ID: return 5789; case ActivatorRail::ActivatorRail(false, ActivatorRail::Shape::AscendingWest).ID: return 5790; case ActivatorRail::ActivatorRail(false, ActivatorRail::Shape::AscendingNorth).ID: return 5791; case ActivatorRail::ActivatorRail(false, ActivatorRail::Shape::AscendingSouth).ID: return 5792; case Air::Air().ID: return -0; case Allium::Allium().ID: return 1114; case Andesite::Andesite().ID: return 6; case Anvil::Anvil(eBlockFace::BLOCK_FACE_ZM).ID: return 5568; case Anvil::Anvil(eBlockFace::BLOCK_FACE_ZP).ID: return 5569; case Anvil::Anvil(eBlockFace::BLOCK_FACE_XM).ID: return 5570; case Anvil::Anvil(eBlockFace::BLOCK_FACE_XP).ID: return 5571; case AttachedMelonStem::AttachedMelonStem(eBlockFace::BLOCK_FACE_ZM).ID: return 4249; case AttachedMelonStem::AttachedMelonStem(eBlockFace::BLOCK_FACE_ZP).ID: return 4250; case AttachedMelonStem::AttachedMelonStem(eBlockFace::BLOCK_FACE_XM).ID: return 4251; case AttachedMelonStem::AttachedMelonStem(eBlockFace::BLOCK_FACE_XP).ID: return 4252; case AttachedPumpkinStem::AttachedPumpkinStem(eBlockFace::BLOCK_FACE_ZM).ID: return 4245; case AttachedPumpkinStem::AttachedPumpkinStem(eBlockFace::BLOCK_FACE_ZP).ID: return 4246; case AttachedPumpkinStem::AttachedPumpkinStem(eBlockFace::BLOCK_FACE_XM).ID: return 4247; case AttachedPumpkinStem::AttachedPumpkinStem(eBlockFace::BLOCK_FACE_XP).ID: return 4248; case AzureBluet::AzureBluet().ID: return 1115; case Barrier::Barrier().ID: return 6494; case Beacon::Beacon().ID: return 5137; case Bedrock::Bedrock().ID: return 33; case Beetroots::Beetroots(0).ID: return 8159; case Beetroots::Beetroots(1).ID: return 8160; case Beetroots::Beetroots(2).ID: return 8161; case Beetroots::Beetroots(3).ID: return 8162; case BirchButton::BirchButton(BirchButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5352; case BirchButton::BirchButton(BirchButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5353; case BirchButton::BirchButton(BirchButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5354; case BirchButton::BirchButton(BirchButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5355; case BirchButton::BirchButton(BirchButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, true).ID: return 5356; case BirchButton::BirchButton(BirchButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, false).ID: return 5357; case BirchButton::BirchButton(BirchButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, true).ID: return 5358; case BirchButton::BirchButton(BirchButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, false).ID: return 5359; case BirchButton::BirchButton(BirchButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5360; case BirchButton::BirchButton(BirchButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5361; case BirchButton::BirchButton(BirchButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5362; case BirchButton::BirchButton(BirchButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5363; case BirchButton::BirchButton(BirchButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, true).ID: return 5364; case BirchButton::BirchButton(BirchButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, false).ID: return 5365; case BirchButton::BirchButton(BirchButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, true).ID: return 5366; case BirchButton::BirchButton(BirchButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, false).ID: return 5367; case BirchButton::BirchButton(BirchButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5368; case BirchButton::BirchButton(BirchButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5369; case BirchButton::BirchButton(BirchButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5370; case BirchButton::BirchButton(BirchButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5371; case BirchButton::BirchButton(BirchButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, true).ID: return 5372; case BirchButton::BirchButton(BirchButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, false).ID: return 5373; case BirchButton::BirchButton(BirchButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, true).ID: return 5374; case BirchButton::BirchButton(BirchButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, false).ID: return 5375; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, true, true).ID: return 7742; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, true, false).ID: return 7743; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, false, true).ID: return 7744; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, false, false).ID: return 7745; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, true, true).ID: return 7746; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, true, false).ID: return 7747; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, false, true).ID: return 7748; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, false, false).ID: return 7749; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, true, true).ID: return 7750; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, true, false).ID: return 7751; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, false, true).ID: return 7752; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, false, false).ID: return 7753; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, true, true).ID: return 7754; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, true, false).ID: return 7755; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, false, true).ID: return 7756; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, false, false).ID: return 7757; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, true, true).ID: return 7758; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, true, false).ID: return 7759; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, false, true).ID: return 7760; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, false, false).ID: return 7761; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, true, true).ID: return 7762; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, true, false).ID: return 7763; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, false, true).ID: return 7764; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, false, false).ID: return 7765; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, true, true).ID: return 7766; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, true, false).ID: return 7767; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, false, true).ID: return 7768; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, false, false).ID: return 7769; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, true, true).ID: return 7770; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, true, false).ID: return 7771; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, false, true).ID: return 7772; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, false, false).ID: return 7773; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, true, true).ID: return 7774; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, true, false).ID: return 7775; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, false, true).ID: return 7776; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, false, false).ID: return 7777; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, true, true).ID: return 7778; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, true, false).ID: return 7779; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, false, true).ID: return 7780; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, false, false).ID: return 7781; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, true, true).ID: return 7782; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, true, false).ID: return 7783; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, false, true).ID: return 7784; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, false, false).ID: return 7785; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, true, true).ID: return 7786; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, true, false).ID: return 7787; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, false, true).ID: return 7788; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, false, false).ID: return 7789; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, true, true).ID: return 7790; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, true, false).ID: return 7791; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, false, true).ID: return 7792; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, false, false).ID: return 7793; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, true, true).ID: return 7794; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, true, false).ID: return 7795; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, false, true).ID: return 7796; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, false, false).ID: return 7797; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, true, true).ID: return 7798; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, true, false).ID: return 7799; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, false, true).ID: return 7800; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, false, false).ID: return 7801; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, true, true).ID: return 7802; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, true, false).ID: return 7803; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, false, true).ID: return 7804; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, false, false).ID: return 7805; case BirchFence::BirchFence(true, true, true, true).ID: return 7552; case BirchFence::BirchFence(true, true, true, false).ID: return 7553; case BirchFence::BirchFence(true, true, false, true).ID: return 7556; case BirchFence::BirchFence(true, true, false, false).ID: return 7557; case BirchFence::BirchFence(true, false, true, true).ID: return 7560; case BirchFence::BirchFence(true, false, true, false).ID: return 7561; case BirchFence::BirchFence(true, false, false, true).ID: return 7564; case BirchFence::BirchFence(true, false, false, false).ID: return 7565; case BirchFence::BirchFence(false, true, true, true).ID: return 7568; case BirchFence::BirchFence(false, true, true, false).ID: return 7569; case BirchFence::BirchFence(false, true, false, true).ID: return 7572; case BirchFence::BirchFence(false, true, false, false).ID: return 7573; case BirchFence::BirchFence(false, false, true, true).ID: return 7576; case BirchFence::BirchFence(false, false, true, false).ID: return 7577; case BirchFence::BirchFence(false, false, false, true).ID: return 7580; case BirchFence::BirchFence(false, false, false, false).ID: return 7581; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZM, true, true, true).ID: return 7390; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZM, true, true, false).ID: return 7391; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZM, true, false, true).ID: return 7392; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZM, true, false, false).ID: return 7393; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, true).ID: return 7394; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, false).ID: return 7395; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, true).ID: return 7396; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, false).ID: return 7397; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZP, true, true, true).ID: return 7398; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZP, true, true, false).ID: return 7399; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZP, true, false, true).ID: return 7400; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZP, true, false, false).ID: return 7401; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, true).ID: return 7402; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, false).ID: return 7403; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, true).ID: return 7404; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, false).ID: return 7405; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XM, true, true, true).ID: return 7406; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XM, true, true, false).ID: return 7407; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XM, true, false, true).ID: return 7408; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XM, true, false, false).ID: return 7409; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, true).ID: return 7410; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, false).ID: return 7411; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, true).ID: return 7412; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, false).ID: return 7413; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XP, true, true, true).ID: return 7414; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XP, true, true, false).ID: return 7415; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XP, true, false, true).ID: return 7416; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XP, true, false, false).ID: return 7417; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, true).ID: return 7418; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, false).ID: return 7419; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, true).ID: return 7420; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, false).ID: return 7421; case BirchLeaves::BirchLeaves(1, true).ID: return 172; case BirchLeaves::BirchLeaves(1, false).ID: return 173; case BirchLeaves::BirchLeaves(2, true).ID: return 174; case BirchLeaves::BirchLeaves(2, false).ID: return 175; case BirchLeaves::BirchLeaves(3, true).ID: return 176; case BirchLeaves::BirchLeaves(3, false).ID: return 177; case BirchLeaves::BirchLeaves(4, true).ID: return 178; case BirchLeaves::BirchLeaves(4, false).ID: return 179; case BirchLeaves::BirchLeaves(5, true).ID: return 180; case BirchLeaves::BirchLeaves(5, false).ID: return 181; case BirchLeaves::BirchLeaves(6, true).ID: return 182; case BirchLeaves::BirchLeaves(6, false).ID: return 183; case BirchLeaves::BirchLeaves(7, true).ID: return 184; case BirchLeaves::BirchLeaves(7, false).ID: return 185; case BirchLog::BirchLog(BirchLog::Axis::X).ID: return 78; case BirchLog::BirchLog(BirchLog::Axis::Y).ID: return 79; case BirchLog::BirchLog(BirchLog::Axis::Z).ID: return 80; case BirchPlanks::BirchPlanks().ID: return 17; case BirchPressurePlate::BirchPressurePlate(true).ID: return 3372; case BirchPressurePlate::BirchPressurePlate(false).ID: return 3373; case BirchSapling::BirchSapling(0).ID: return 25; case BirchSapling::BirchSapling(1).ID: return 26; case BirchSlab::BirchSlab(BirchSlab::Type::Top).ID: return 7271; case BirchSlab::BirchSlab(BirchSlab::Type::Bottom).ID: return 7273; case BirchSlab::BirchSlab(BirchSlab::Type::Double).ID: return 7275; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZM, BirchStairs::Half::Top, BirchStairs::Shape::Straight).ID: return 4966; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZM, BirchStairs::Half::Top, BirchStairs::Shape::InnerLeft).ID: return 4968; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZM, BirchStairs::Half::Top, BirchStairs::Shape::InnerRight).ID: return 4970; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZM, BirchStairs::Half::Top, BirchStairs::Shape::OuterLeft).ID: return 4972; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZM, BirchStairs::Half::Top, BirchStairs::Shape::OuterRight).ID: return 4974; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZM, BirchStairs::Half::Bottom, BirchStairs::Shape::Straight).ID: return 4976; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZM, BirchStairs::Half::Bottom, BirchStairs::Shape::InnerLeft).ID: return 4978; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZM, BirchStairs::Half::Bottom, BirchStairs::Shape::InnerRight).ID: return 4980; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZM, BirchStairs::Half::Bottom, BirchStairs::Shape::OuterLeft).ID: return 4982; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZM, BirchStairs::Half::Bottom, BirchStairs::Shape::OuterRight).ID: return 4984; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZP, BirchStairs::Half::Top, BirchStairs::Shape::Straight).ID: return 4986; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZP, BirchStairs::Half::Top, BirchStairs::Shape::InnerLeft).ID: return 4988; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZP, BirchStairs::Half::Top, BirchStairs::Shape::InnerRight).ID: return 4990; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZP, BirchStairs::Half::Top, BirchStairs::Shape::OuterLeft).ID: return 4992; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZP, BirchStairs::Half::Top, BirchStairs::Shape::OuterRight).ID: return 4994; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZP, BirchStairs::Half::Bottom, BirchStairs::Shape::Straight).ID: return 4996; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZP, BirchStairs::Half::Bottom, BirchStairs::Shape::InnerLeft).ID: return 4998; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZP, BirchStairs::Half::Bottom, BirchStairs::Shape::InnerRight).ID: return 5000; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZP, BirchStairs::Half::Bottom, BirchStairs::Shape::OuterLeft).ID: return 5002; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZP, BirchStairs::Half::Bottom, BirchStairs::Shape::OuterRight).ID: return 5004; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XM, BirchStairs::Half::Top, BirchStairs::Shape::Straight).ID: return 5006; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XM, BirchStairs::Half::Top, BirchStairs::Shape::InnerLeft).ID: return 5008; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XM, BirchStairs::Half::Top, BirchStairs::Shape::InnerRight).ID: return 5010; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XM, BirchStairs::Half::Top, BirchStairs::Shape::OuterLeft).ID: return 5012; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XM, BirchStairs::Half::Top, BirchStairs::Shape::OuterRight).ID: return 5014; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XM, BirchStairs::Half::Bottom, BirchStairs::Shape::Straight).ID: return 5016; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XM, BirchStairs::Half::Bottom, BirchStairs::Shape::InnerLeft).ID: return 5018; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XM, BirchStairs::Half::Bottom, BirchStairs::Shape::InnerRight).ID: return 5020; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XM, BirchStairs::Half::Bottom, BirchStairs::Shape::OuterLeft).ID: return 5022; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XM, BirchStairs::Half::Bottom, BirchStairs::Shape::OuterRight).ID: return 5024; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XP, BirchStairs::Half::Top, BirchStairs::Shape::Straight).ID: return 5026; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XP, BirchStairs::Half::Top, BirchStairs::Shape::InnerLeft).ID: return 5028; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XP, BirchStairs::Half::Top, BirchStairs::Shape::InnerRight).ID: return 5030; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XP, BirchStairs::Half::Top, BirchStairs::Shape::OuterLeft).ID: return 5032; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XP, BirchStairs::Half::Top, BirchStairs::Shape::OuterRight).ID: return 5034; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XP, BirchStairs::Half::Bottom, BirchStairs::Shape::Straight).ID: return 5036; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XP, BirchStairs::Half::Bottom, BirchStairs::Shape::InnerLeft).ID: return 5038; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XP, BirchStairs::Half::Bottom, BirchStairs::Shape::InnerRight).ID: return 5040; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XP, BirchStairs::Half::Bottom, BirchStairs::Shape::OuterLeft).ID: return 5042; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XP, BirchStairs::Half::Bottom, BirchStairs::Shape::OuterRight).ID: return 5044; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZM, BirchTrapdoor::Half::Top, true, true).ID: return 3723; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZM, BirchTrapdoor::Half::Top, true, false).ID: return 3725; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZM, BirchTrapdoor::Half::Top, false, true).ID: return 3727; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZM, BirchTrapdoor::Half::Top, false, false).ID: return 3729; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZM, BirchTrapdoor::Half::Bottom, true, true).ID: return 3731; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZM, BirchTrapdoor::Half::Bottom, true, false).ID: return 3733; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZM, BirchTrapdoor::Half::Bottom, false, true).ID: return 3735; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZM, BirchTrapdoor::Half::Bottom, false, false).ID: return 3737; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZP, BirchTrapdoor::Half::Top, true, true).ID: return 3739; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZP, BirchTrapdoor::Half::Top, true, false).ID: return 3741; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZP, BirchTrapdoor::Half::Top, false, true).ID: return 3743; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZP, BirchTrapdoor::Half::Top, false, false).ID: return 3745; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZP, BirchTrapdoor::Half::Bottom, true, true).ID: return 3747; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZP, BirchTrapdoor::Half::Bottom, true, false).ID: return 3749; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZP, BirchTrapdoor::Half::Bottom, false, true).ID: return 3751; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZP, BirchTrapdoor::Half::Bottom, false, false).ID: return 3753; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XM, BirchTrapdoor::Half::Top, true, true).ID: return 3755; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XM, BirchTrapdoor::Half::Top, true, false).ID: return 3757; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XM, BirchTrapdoor::Half::Top, false, true).ID: return 3759; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XM, BirchTrapdoor::Half::Top, false, false).ID: return 3761; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XM, BirchTrapdoor::Half::Bottom, true, true).ID: return 3763; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XM, BirchTrapdoor::Half::Bottom, true, false).ID: return 3765; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XM, BirchTrapdoor::Half::Bottom, false, true).ID: return 3767; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XM, BirchTrapdoor::Half::Bottom, false, false).ID: return 3769; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XP, BirchTrapdoor::Half::Top, true, true).ID: return 3771; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XP, BirchTrapdoor::Half::Top, true, false).ID: return 3773; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XP, BirchTrapdoor::Half::Top, false, true).ID: return 3775; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XP, BirchTrapdoor::Half::Top, false, false).ID: return 3777; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XP, BirchTrapdoor::Half::Bottom, true, true).ID: return 3779; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XP, BirchTrapdoor::Half::Bottom, true, false).ID: return 3781; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XP, BirchTrapdoor::Half::Bottom, false, true).ID: return 3783; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XP, BirchTrapdoor::Half::Bottom, false, false).ID: return 3785; case BirchWood::BirchWood(BirchWood::Axis::X).ID: return 114; case BirchWood::BirchWood(BirchWood::Axis::Y).ID: return 115; case BirchWood::BirchWood(BirchWood::Axis::Z).ID: return 116; case BlackBanner::BlackBanner(0).ID: return 7095; case BlackBanner::BlackBanner(1).ID: return 7096; case BlackBanner::BlackBanner(2).ID: return 7097; case BlackBanner::BlackBanner(3).ID: return 7098; case BlackBanner::BlackBanner(4).ID: return 7099; case BlackBanner::BlackBanner(5).ID: return 7100; case BlackBanner::BlackBanner(6).ID: return 7101; case BlackBanner::BlackBanner(7).ID: return 7102; case BlackBanner::BlackBanner(8).ID: return 7103; case BlackBanner::BlackBanner(9).ID: return 7104; case BlackBanner::BlackBanner(10).ID: return 7105; case BlackBanner::BlackBanner(11).ID: return 7106; case BlackBanner::BlackBanner(12).ID: return 7107; case BlackBanner::BlackBanner(13).ID: return 7108; case BlackBanner::BlackBanner(14).ID: return 7109; case BlackBanner::BlackBanner(15).ID: return 7110; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_ZM, true, BlackBed::Part::Head).ID: return 988; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_ZM, true, BlackBed::Part::Foot).ID: return 989; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_ZM, false, BlackBed::Part::Head).ID: return 990; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_ZM, false, BlackBed::Part::Foot).ID: return 991; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_ZP, true, BlackBed::Part::Head).ID: return 992; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_ZP, true, BlackBed::Part::Foot).ID: return 993; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_ZP, false, BlackBed::Part::Head).ID: return 994; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_ZP, false, BlackBed::Part::Foot).ID: return 995; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_XM, true, BlackBed::Part::Head).ID: return 996; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_XM, true, BlackBed::Part::Foot).ID: return 997; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_XM, false, BlackBed::Part::Head).ID: return 998; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_XM, false, BlackBed::Part::Foot).ID: return 999; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_XP, true, BlackBed::Part::Head).ID: return 1000; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_XP, true, BlackBed::Part::Foot).ID: return 1001; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_XP, false, BlackBed::Part::Head).ID: return 1002; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_XP, false, BlackBed::Part::Foot).ID: return 1003; case BlackCarpet::BlackCarpet().ID: return 6839; case BlackConcrete::BlackConcrete().ID: return 8393; case BlackConcretePowder::BlackConcretePowder().ID: return 8409; case BlackGlazedTerracotta::BlackGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 8374; case BlackGlazedTerracotta::BlackGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 8375; case BlackGlazedTerracotta::BlackGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 8376; case BlackGlazedTerracotta::BlackGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 8377; case BlackShulkerBox::BlackShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 8308; case BlackShulkerBox::BlackShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 8309; case BlackShulkerBox::BlackShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 8310; case BlackShulkerBox::BlackShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 8311; case BlackShulkerBox::BlackShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 8312; case BlackShulkerBox::BlackShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 8313; case BlackStainedGlass::BlackStainedGlass().ID: return 3593; case BlackStainedGlassPane::BlackStainedGlassPane(true, true, true, true).ID: return 6303; case BlackStainedGlassPane::BlackStainedGlassPane(true, true, true, false).ID: return 6304; case BlackStainedGlassPane::BlackStainedGlassPane(true, true, false, true).ID: return 6307; case BlackStainedGlassPane::BlackStainedGlassPane(true, true, false, false).ID: return 6308; case BlackStainedGlassPane::BlackStainedGlassPane(true, false, true, true).ID: return 6311; case BlackStainedGlassPane::BlackStainedGlassPane(true, false, true, false).ID: return 6312; case BlackStainedGlassPane::BlackStainedGlassPane(true, false, false, true).ID: return 6315; case BlackStainedGlassPane::BlackStainedGlassPane(true, false, false, false).ID: return 6316; case BlackStainedGlassPane::BlackStainedGlassPane(false, true, true, true).ID: return 6319; case BlackStainedGlassPane::BlackStainedGlassPane(false, true, true, false).ID: return 6320; case BlackStainedGlassPane::BlackStainedGlassPane(false, true, false, true).ID: return 6323; case BlackStainedGlassPane::BlackStainedGlassPane(false, true, false, false).ID: return 6324; case BlackStainedGlassPane::BlackStainedGlassPane(false, false, true, true).ID: return 6327; case BlackStainedGlassPane::BlackStainedGlassPane(false, false, true, false).ID: return 6328; case BlackStainedGlassPane::BlackStainedGlassPane(false, false, false, true).ID: return 6331; case BlackStainedGlassPane::BlackStainedGlassPane(false, false, false, false).ID: return 6332; case BlackTerracotta::BlackTerracotta().ID: return 5820; case BlackWallBanner::BlackWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 7171; case BlackWallBanner::BlackWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 7172; case BlackWallBanner::BlackWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 7173; case BlackWallBanner::BlackWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 7174; case BlackWool::BlackWool().ID: return 1098; case BlueBanner::BlueBanner(0).ID: return 7031; case BlueBanner::BlueBanner(1).ID: return 7032; case BlueBanner::BlueBanner(2).ID: return 7033; case BlueBanner::BlueBanner(3).ID: return 7034; case BlueBanner::BlueBanner(4).ID: return 7035; case BlueBanner::BlueBanner(5).ID: return 7036; case BlueBanner::BlueBanner(6).ID: return 7037; case BlueBanner::BlueBanner(7).ID: return 7038; case BlueBanner::BlueBanner(8).ID: return 7039; case BlueBanner::BlueBanner(9).ID: return 7040; case BlueBanner::BlueBanner(10).ID: return 7041; case BlueBanner::BlueBanner(11).ID: return 7042; case BlueBanner::BlueBanner(12).ID: return 7043; case BlueBanner::BlueBanner(13).ID: return 7044; case BlueBanner::BlueBanner(14).ID: return 7045; case BlueBanner::BlueBanner(15).ID: return 7046; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_ZM, true, BlueBed::Part::Head).ID: return 924; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_ZM, true, BlueBed::Part::Foot).ID: return 925; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_ZM, false, BlueBed::Part::Head).ID: return 926; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_ZM, false, BlueBed::Part::Foot).ID: return 927; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_ZP, true, BlueBed::Part::Head).ID: return 928; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_ZP, true, BlueBed::Part::Foot).ID: return 929; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_ZP, false, BlueBed::Part::Head).ID: return 930; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_ZP, false, BlueBed::Part::Foot).ID: return 931; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_XM, true, BlueBed::Part::Head).ID: return 932; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_XM, true, BlueBed::Part::Foot).ID: return 933; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_XM, false, BlueBed::Part::Head).ID: return 934; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_XM, false, BlueBed::Part::Foot).ID: return 935; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_XP, true, BlueBed::Part::Head).ID: return 936; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_XP, true, BlueBed::Part::Foot).ID: return 937; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_XP, false, BlueBed::Part::Head).ID: return 938; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_XP, false, BlueBed::Part::Foot).ID: return 939; case BlueCarpet::BlueCarpet().ID: return 6835; case BlueConcrete::BlueConcrete().ID: return 8389; case BlueConcretePowder::BlueConcretePowder().ID: return 8405; case BlueGlazedTerracotta::BlueGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 8358; case BlueGlazedTerracotta::BlueGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 8359; case BlueGlazedTerracotta::BlueGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 8360; case BlueGlazedTerracotta::BlueGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 8361; case BlueIce::BlueIce().ID: return 8588; case BlueOrchid::BlueOrchid().ID: return 1113; case BlueShulkerBox::BlueShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 8284; case BlueShulkerBox::BlueShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 8285; case BlueShulkerBox::BlueShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 8286; case BlueShulkerBox::BlueShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 8287; case BlueShulkerBox::BlueShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 8288; case BlueShulkerBox::BlueShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 8289; case BlueStainedGlass::BlueStainedGlass().ID: return 3589; case BlueStainedGlassPane::BlueStainedGlassPane(true, true, true, true).ID: return 6175; case BlueStainedGlassPane::BlueStainedGlassPane(true, true, true, false).ID: return 6176; case BlueStainedGlassPane::BlueStainedGlassPane(true, true, false, true).ID: return 6179; case BlueStainedGlassPane::BlueStainedGlassPane(true, true, false, false).ID: return 6180; case BlueStainedGlassPane::BlueStainedGlassPane(true, false, true, true).ID: return 6183; case BlueStainedGlassPane::BlueStainedGlassPane(true, false, true, false).ID: return 6184; case BlueStainedGlassPane::BlueStainedGlassPane(true, false, false, true).ID: return 6187; case BlueStainedGlassPane::BlueStainedGlassPane(true, false, false, false).ID: return 6188; case BlueStainedGlassPane::BlueStainedGlassPane(false, true, true, true).ID: return 6191; case BlueStainedGlassPane::BlueStainedGlassPane(false, true, true, false).ID: return 6192; case BlueStainedGlassPane::BlueStainedGlassPane(false, true, false, true).ID: return 6195; case BlueStainedGlassPane::BlueStainedGlassPane(false, true, false, false).ID: return 6196; case BlueStainedGlassPane::BlueStainedGlassPane(false, false, true, true).ID: return 6199; case BlueStainedGlassPane::BlueStainedGlassPane(false, false, true, false).ID: return 6200; case BlueStainedGlassPane::BlueStainedGlassPane(false, false, false, true).ID: return 6203; case BlueStainedGlassPane::BlueStainedGlassPane(false, false, false, false).ID: return 6204; case BlueTerracotta::BlueTerracotta().ID: return 5816; case BlueWallBanner::BlueWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 7155; case BlueWallBanner::BlueWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 7156; case BlueWallBanner::BlueWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 7157; case BlueWallBanner::BlueWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 7158; case BlueWool::BlueWool().ID: return 1094; case BoneBlock::BoneBlock(BoneBlock::Axis::X).ID: return 8196; case BoneBlock::BoneBlock(BoneBlock::Axis::Y).ID: return 8197; case BoneBlock::BoneBlock(BoneBlock::Axis::Z).ID: return 8198; case Bookshelf::Bookshelf().ID: return 1128; case BrainCoral::BrainCoral().ID: return 8473; case BrainCoralBlock::BrainCoralBlock().ID: return 8456; case BrainCoralFan::BrainCoralFan().ID: return 8573; case BrainCoralWallFan::BrainCoralWallFan(eBlockFace::BLOCK_FACE_ZM).ID: return 8529; case BrainCoralWallFan::BrainCoralWallFan(eBlockFace::BLOCK_FACE_ZP).ID: return 8531; case BrainCoralWallFan::BrainCoralWallFan(eBlockFace::BLOCK_FACE_XM).ID: return 8533; case BrainCoralWallFan::BrainCoralWallFan(eBlockFace::BLOCK_FACE_XP).ID: return 8535; case BrewingStand::BrewingStand(true, true, true).ID: return 4614; case BrewingStand::BrewingStand(true, true, false).ID: return 4615; case BrewingStand::BrewingStand(true, false, true).ID: return 4616; case BrewingStand::BrewingStand(true, false, false).ID: return 4617; case BrewingStand::BrewingStand(false, true, true).ID: return 4618; case BrewingStand::BrewingStand(false, true, false).ID: return 4619; case BrewingStand::BrewingStand(false, false, true).ID: return 4620; case BrewingStand::BrewingStand(false, false, false).ID: return 4621; case BrickSlab::BrickSlab(BrickSlab::Type::Top).ID: return 7319; case BrickSlab::BrickSlab(BrickSlab::Type::Bottom).ID: return 7321; case BrickSlab::BrickSlab(BrickSlab::Type::Double).ID: return 7323; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZM, BrickStairs::Half::Top, BrickStairs::Shape::Straight).ID: return 4334; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZM, BrickStairs::Half::Top, BrickStairs::Shape::InnerLeft).ID: return 4336; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZM, BrickStairs::Half::Top, BrickStairs::Shape::InnerRight).ID: return 4338; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZM, BrickStairs::Half::Top, BrickStairs::Shape::OuterLeft).ID: return 4340; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZM, BrickStairs::Half::Top, BrickStairs::Shape::OuterRight).ID: return 4342; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZM, BrickStairs::Half::Bottom, BrickStairs::Shape::Straight).ID: return 4344; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZM, BrickStairs::Half::Bottom, BrickStairs::Shape::InnerLeft).ID: return 4346; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZM, BrickStairs::Half::Bottom, BrickStairs::Shape::InnerRight).ID: return 4348; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZM, BrickStairs::Half::Bottom, BrickStairs::Shape::OuterLeft).ID: return 4350; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZM, BrickStairs::Half::Bottom, BrickStairs::Shape::OuterRight).ID: return 4352; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZP, BrickStairs::Half::Top, BrickStairs::Shape::Straight).ID: return 4354; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZP, BrickStairs::Half::Top, BrickStairs::Shape::InnerLeft).ID: return 4356; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZP, BrickStairs::Half::Top, BrickStairs::Shape::InnerRight).ID: return 4358; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZP, BrickStairs::Half::Top, BrickStairs::Shape::OuterLeft).ID: return 4360; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZP, BrickStairs::Half::Top, BrickStairs::Shape::OuterRight).ID: return 4362; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZP, BrickStairs::Half::Bottom, BrickStairs::Shape::Straight).ID: return 4364; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZP, BrickStairs::Half::Bottom, BrickStairs::Shape::InnerLeft).ID: return 4366; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZP, BrickStairs::Half::Bottom, BrickStairs::Shape::InnerRight).ID: return 4368; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZP, BrickStairs::Half::Bottom, BrickStairs::Shape::OuterLeft).ID: return 4370; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZP, BrickStairs::Half::Bottom, BrickStairs::Shape::OuterRight).ID: return 4372; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XM, BrickStairs::Half::Top, BrickStairs::Shape::Straight).ID: return 4374; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XM, BrickStairs::Half::Top, BrickStairs::Shape::InnerLeft).ID: return 4376; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XM, BrickStairs::Half::Top, BrickStairs::Shape::InnerRight).ID: return 4378; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XM, BrickStairs::Half::Top, BrickStairs::Shape::OuterLeft).ID: return 4380; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XM, BrickStairs::Half::Top, BrickStairs::Shape::OuterRight).ID: return 4382; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XM, BrickStairs::Half::Bottom, BrickStairs::Shape::Straight).ID: return 4384; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XM, BrickStairs::Half::Bottom, BrickStairs::Shape::InnerLeft).ID: return 4386; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XM, BrickStairs::Half::Bottom, BrickStairs::Shape::InnerRight).ID: return 4388; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XM, BrickStairs::Half::Bottom, BrickStairs::Shape::OuterLeft).ID: return 4390; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XM, BrickStairs::Half::Bottom, BrickStairs::Shape::OuterRight).ID: return 4392; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XP, BrickStairs::Half::Top, BrickStairs::Shape::Straight).ID: return 4394; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XP, BrickStairs::Half::Top, BrickStairs::Shape::InnerLeft).ID: return 4396; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XP, BrickStairs::Half::Top, BrickStairs::Shape::InnerRight).ID: return 4398; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XP, BrickStairs::Half::Top, BrickStairs::Shape::OuterLeft).ID: return 4400; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XP, BrickStairs::Half::Top, BrickStairs::Shape::OuterRight).ID: return 4402; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XP, BrickStairs::Half::Bottom, BrickStairs::Shape::Straight).ID: return 4404; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XP, BrickStairs::Half::Bottom, BrickStairs::Shape::InnerLeft).ID: return 4406; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XP, BrickStairs::Half::Bottom, BrickStairs::Shape::InnerRight).ID: return 4408; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XP, BrickStairs::Half::Bottom, BrickStairs::Shape::OuterLeft).ID: return 4410; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XP, BrickStairs::Half::Bottom, BrickStairs::Shape::OuterRight).ID: return 4412; case Bricks::Bricks().ID: return 1125; case BrownBanner::BrownBanner(0).ID: return 7047; case BrownBanner::BrownBanner(1).ID: return 7048; case BrownBanner::BrownBanner(2).ID: return 7049; case BrownBanner::BrownBanner(3).ID: return 7050; case BrownBanner::BrownBanner(4).ID: return 7051; case BrownBanner::BrownBanner(5).ID: return 7052; case BrownBanner::BrownBanner(6).ID: return 7053; case BrownBanner::BrownBanner(7).ID: return 7054; case BrownBanner::BrownBanner(8).ID: return 7055; case BrownBanner::BrownBanner(9).ID: return 7056; case BrownBanner::BrownBanner(10).ID: return 7057; case BrownBanner::BrownBanner(11).ID: return 7058; case BrownBanner::BrownBanner(12).ID: return 7059; case BrownBanner::BrownBanner(13).ID: return 7060; case BrownBanner::BrownBanner(14).ID: return 7061; case BrownBanner::BrownBanner(15).ID: return 7062; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_ZM, true, BrownBed::Part::Head).ID: return 940; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_ZM, true, BrownBed::Part::Foot).ID: return 941; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_ZM, false, BrownBed::Part::Head).ID: return 942; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_ZM, false, BrownBed::Part::Foot).ID: return 943; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_ZP, true, BrownBed::Part::Head).ID: return 944; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_ZP, true, BrownBed::Part::Foot).ID: return 945; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_ZP, false, BrownBed::Part::Head).ID: return 946; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_ZP, false, BrownBed::Part::Foot).ID: return 947; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_XM, true, BrownBed::Part::Head).ID: return 948; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_XM, true, BrownBed::Part::Foot).ID: return 949; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_XM, false, BrownBed::Part::Head).ID: return 950; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_XM, false, BrownBed::Part::Foot).ID: return 951; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_XP, true, BrownBed::Part::Head).ID: return 952; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_XP, true, BrownBed::Part::Foot).ID: return 953; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_XP, false, BrownBed::Part::Head).ID: return 954; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_XP, false, BrownBed::Part::Foot).ID: return 955; case BrownCarpet::BrownCarpet().ID: return 6836; case BrownConcrete::BrownConcrete().ID: return 8390; case BrownConcretePowder::BrownConcretePowder().ID: return 8406; case BrownGlazedTerracotta::BrownGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 8362; case BrownGlazedTerracotta::BrownGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 8363; case BrownGlazedTerracotta::BrownGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 8364; case BrownGlazedTerracotta::BrownGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 8365; case BrownMushroom::BrownMushroom().ID: return 1121; case BrownMushroomBlock::BrownMushroomBlock(true, true, true, true, true, true).ID: return 3988; case BrownMushroomBlock::BrownMushroomBlock(true, true, true, true, true, false).ID: return 3989; case BrownMushroomBlock::BrownMushroomBlock(true, true, true, true, false, true).ID: return 3990; case BrownMushroomBlock::BrownMushroomBlock(true, true, true, true, false, false).ID: return 3991; case BrownMushroomBlock::BrownMushroomBlock(true, true, true, false, true, true).ID: return 3992; case BrownMushroomBlock::BrownMushroomBlock(true, true, true, false, true, false).ID: return 3993; case BrownMushroomBlock::BrownMushroomBlock(true, true, true, false, false, true).ID: return 3994; case BrownMushroomBlock::BrownMushroomBlock(true, true, true, false, false, false).ID: return 3995; case BrownMushroomBlock::BrownMushroomBlock(true, true, false, true, true, true).ID: return 3996; case BrownMushroomBlock::BrownMushroomBlock(true, true, false, true, true, false).ID: return 3997; case BrownMushroomBlock::BrownMushroomBlock(true, true, false, true, false, true).ID: return 3998; case BrownMushroomBlock::BrownMushroomBlock(true, true, false, true, false, false).ID: return 3999; case BrownMushroomBlock::BrownMushroomBlock(true, true, false, false, true, true).ID: return 4000; case BrownMushroomBlock::BrownMushroomBlock(true, true, false, false, true, false).ID: return 4001; case BrownMushroomBlock::BrownMushroomBlock(true, true, false, false, false, true).ID: return 4002; case BrownMushroomBlock::BrownMushroomBlock(true, true, false, false, false, false).ID: return 4003; case BrownMushroomBlock::BrownMushroomBlock(true, false, true, true, true, true).ID: return 4004; case BrownMushroomBlock::BrownMushroomBlock(true, false, true, true, true, false).ID: return 4005; case BrownMushroomBlock::BrownMushroomBlock(true, false, true, true, false, true).ID: return 4006; case BrownMushroomBlock::BrownMushroomBlock(true, false, true, true, false, false).ID: return 4007; case BrownMushroomBlock::BrownMushroomBlock(true, false, true, false, true, true).ID: return 4008; case BrownMushroomBlock::BrownMushroomBlock(true, false, true, false, true, false).ID: return 4009; case BrownMushroomBlock::BrownMushroomBlock(true, false, true, false, false, true).ID: return 4010; case BrownMushroomBlock::BrownMushroomBlock(true, false, true, false, false, false).ID: return 4011; case BrownMushroomBlock::BrownMushroomBlock(true, false, false, true, true, true).ID: return 4012; case BrownMushroomBlock::BrownMushroomBlock(true, false, false, true, true, false).ID: return 4013; case BrownMushroomBlock::BrownMushroomBlock(true, false, false, true, false, true).ID: return 4014; case BrownMushroomBlock::BrownMushroomBlock(true, false, false, true, false, false).ID: return 4015; case BrownMushroomBlock::BrownMushroomBlock(true, false, false, false, true, true).ID: return 4016; case BrownMushroomBlock::BrownMushroomBlock(true, false, false, false, true, false).ID: return 4017; case BrownMushroomBlock::BrownMushroomBlock(true, false, false, false, false, true).ID: return 4018; case BrownMushroomBlock::BrownMushroomBlock(true, false, false, false, false, false).ID: return 4019; case BrownMushroomBlock::BrownMushroomBlock(false, true, true, true, true, true).ID: return 4020; case BrownMushroomBlock::BrownMushroomBlock(false, true, true, true, true, false).ID: return 4021; case BrownMushroomBlock::BrownMushroomBlock(false, true, true, true, false, true).ID: return 4022; case BrownMushroomBlock::BrownMushroomBlock(false, true, true, true, false, false).ID: return 4023; case BrownMushroomBlock::BrownMushroomBlock(false, true, true, false, true, true).ID: return 4024; case BrownMushroomBlock::BrownMushroomBlock(false, true, true, false, true, false).ID: return 4025; case BrownMushroomBlock::BrownMushroomBlock(false, true, true, false, false, true).ID: return 4026; case BrownMushroomBlock::BrownMushroomBlock(false, true, true, false, false, false).ID: return 4027; case BrownMushroomBlock::BrownMushroomBlock(false, true, false, true, true, true).ID: return 4028; case BrownMushroomBlock::BrownMushroomBlock(false, true, false, true, true, false).ID: return 4029; case BrownMushroomBlock::BrownMushroomBlock(false, true, false, true, false, true).ID: return 4030; case BrownMushroomBlock::BrownMushroomBlock(false, true, false, true, false, false).ID: return 4031; case BrownMushroomBlock::BrownMushroomBlock(false, true, false, false, true, true).ID: return 4032; case BrownMushroomBlock::BrownMushroomBlock(false, true, false, false, true, false).ID: return 4033; case BrownMushroomBlock::BrownMushroomBlock(false, true, false, false, false, true).ID: return 4034; case BrownMushroomBlock::BrownMushroomBlock(false, true, false, false, false, false).ID: return 4035; case BrownMushroomBlock::BrownMushroomBlock(false, false, true, true, true, true).ID: return 4036; case BrownMushroomBlock::BrownMushroomBlock(false, false, true, true, true, false).ID: return 4037; case BrownMushroomBlock::BrownMushroomBlock(false, false, true, true, false, true).ID: return 4038; case BrownMushroomBlock::BrownMushroomBlock(false, false, true, true, false, false).ID: return 4039; case BrownMushroomBlock::BrownMushroomBlock(false, false, true, false, true, true).ID: return 4040; case BrownMushroomBlock::BrownMushroomBlock(false, false, true, false, true, false).ID: return 4041; case BrownMushroomBlock::BrownMushroomBlock(false, false, true, false, false, true).ID: return 4042; case BrownMushroomBlock::BrownMushroomBlock(false, false, true, false, false, false).ID: return 4043; case BrownMushroomBlock::BrownMushroomBlock(false, false, false, true, true, true).ID: return 4044; case BrownMushroomBlock::BrownMushroomBlock(false, false, false, true, true, false).ID: return 4045; case BrownMushroomBlock::BrownMushroomBlock(false, false, false, true, false, true).ID: return 4046; case BrownMushroomBlock::BrownMushroomBlock(false, false, false, true, false, false).ID: return 4047; case BrownMushroomBlock::BrownMushroomBlock(false, false, false, false, true, true).ID: return 4048; case BrownMushroomBlock::BrownMushroomBlock(false, false, false, false, true, false).ID: return 4049; case BrownMushroomBlock::BrownMushroomBlock(false, false, false, false, false, true).ID: return 4050; case BrownMushroomBlock::BrownMushroomBlock(false, false, false, false, false, false).ID: return 4051; case BrownShulkerBox::BrownShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 8290; case BrownShulkerBox::BrownShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 8291; case BrownShulkerBox::BrownShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 8292; case BrownShulkerBox::BrownShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 8293; case BrownShulkerBox::BrownShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 8294; case BrownShulkerBox::BrownShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 8295; case BrownStainedGlass::BrownStainedGlass().ID: return 3590; case BrownStainedGlassPane::BrownStainedGlassPane(true, true, true, true).ID: return 6207; case BrownStainedGlassPane::BrownStainedGlassPane(true, true, true, false).ID: return 6208; case BrownStainedGlassPane::BrownStainedGlassPane(true, true, false, true).ID: return 6211; case BrownStainedGlassPane::BrownStainedGlassPane(true, true, false, false).ID: return 6212; case BrownStainedGlassPane::BrownStainedGlassPane(true, false, true, true).ID: return 6215; case BrownStainedGlassPane::BrownStainedGlassPane(true, false, true, false).ID: return 6216; case BrownStainedGlassPane::BrownStainedGlassPane(true, false, false, true).ID: return 6219; case BrownStainedGlassPane::BrownStainedGlassPane(true, false, false, false).ID: return 6220; case BrownStainedGlassPane::BrownStainedGlassPane(false, true, true, true).ID: return 6223; case BrownStainedGlassPane::BrownStainedGlassPane(false, true, true, false).ID: return 6224; case BrownStainedGlassPane::BrownStainedGlassPane(false, true, false, true).ID: return 6227; case BrownStainedGlassPane::BrownStainedGlassPane(false, true, false, false).ID: return 6228; case BrownStainedGlassPane::BrownStainedGlassPane(false, false, true, true).ID: return 6231; case BrownStainedGlassPane::BrownStainedGlassPane(false, false, true, false).ID: return 6232; case BrownStainedGlassPane::BrownStainedGlassPane(false, false, false, true).ID: return 6235; case BrownStainedGlassPane::BrownStainedGlassPane(false, false, false, false).ID: return 6236; case BrownTerracotta::BrownTerracotta().ID: return 5817; case BrownWallBanner::BrownWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 7159; case BrownWallBanner::BrownWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 7160; case BrownWallBanner::BrownWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 7161; case BrownWallBanner::BrownWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 7162; case BrownWool::BrownWool().ID: return 1095; case BubbleColumn::BubbleColumn(true).ID: return 8593; case BubbleColumn::BubbleColumn(false).ID: return 8594; case BubbleCoral::BubbleCoral().ID: return 8475; case BubbleCoralBlock::BubbleCoralBlock().ID: return 8457; case BubbleCoralFan::BubbleCoralFan().ID: return 8575; case BubbleCoralWallFan::BubbleCoralWallFan(eBlockFace::BLOCK_FACE_ZM).ID: return 8537; case BubbleCoralWallFan::BubbleCoralWallFan(eBlockFace::BLOCK_FACE_ZP).ID: return 8539; case BubbleCoralWallFan::BubbleCoralWallFan(eBlockFace::BLOCK_FACE_XM).ID: return 8541; case BubbleCoralWallFan::BubbleCoralWallFan(eBlockFace::BLOCK_FACE_XP).ID: return 8543; case Cactus::Cactus(0).ID: return 3426; case Cactus::Cactus(1).ID: return 3427; case Cactus::Cactus(2).ID: return 3428; case Cactus::Cactus(3).ID: return 3429; case Cactus::Cactus(4).ID: return 3430; case Cactus::Cactus(5).ID: return 3431; case Cactus::Cactus(6).ID: return 3432; case Cactus::Cactus(7).ID: return 3433; case Cactus::Cactus(8).ID: return 3434; case Cactus::Cactus(9).ID: return 3435; case Cactus::Cactus(10).ID: return 3436; case Cactus::Cactus(11).ID: return 3437; case Cactus::Cactus(12).ID: return 3438; case Cactus::Cactus(13).ID: return 3439; case Cactus::Cactus(14).ID: return 3440; case Cactus::Cactus(15).ID: return 3441; case Cake::Cake(0).ID: return 3507; case Cake::Cake(1).ID: return 3508; case Cake::Cake(2).ID: return 3509; case Cake::Cake(3).ID: return 3510; case Cake::Cake(4).ID: return 3511; case Cake::Cake(5).ID: return 3512; case Cake::Cake(6).ID: return 3513; case Carrots::Carrots(0).ID: return 5288; case Carrots::Carrots(1).ID: return 5289; case Carrots::Carrots(2).ID: return 5290; case Carrots::Carrots(3).ID: return 5291; case Carrots::Carrots(4).ID: return 5292; case Carrots::Carrots(5).ID: return 5293; case Carrots::Carrots(6).ID: return 5294; case Carrots::Carrots(7).ID: return 5295; case CarvedPumpkin::CarvedPumpkin(eBlockFace::BLOCK_FACE_ZM).ID: return 3499; case CarvedPumpkin::CarvedPumpkin(eBlockFace::BLOCK_FACE_ZP).ID: return 3500; case CarvedPumpkin::CarvedPumpkin(eBlockFace::BLOCK_FACE_XM).ID: return 3501; case CarvedPumpkin::CarvedPumpkin(eBlockFace::BLOCK_FACE_XP).ID: return 3502; case Cauldron::Cauldron(0).ID: return 4622; case Cauldron::Cauldron(1).ID: return 4623; case Cauldron::Cauldron(2).ID: return 4624; case Cauldron::Cauldron(3).ID: return 4625; case CaveAir::CaveAir().ID: return 8592; case ChainCommandBlock::ChainCommandBlock(true, eBlockFace::BLOCK_FACE_ZM).ID: return 8177; case ChainCommandBlock::ChainCommandBlock(true, eBlockFace::BLOCK_FACE_XP).ID: return 8178; case ChainCommandBlock::ChainCommandBlock(true, eBlockFace::BLOCK_FACE_ZP).ID: return 8179; case ChainCommandBlock::ChainCommandBlock(true, eBlockFace::BLOCK_FACE_XM).ID: return 8180; case ChainCommandBlock::ChainCommandBlock(true, eBlockFace::BLOCK_FACE_YP).ID: return 8181; case ChainCommandBlock::ChainCommandBlock(true, eBlockFace::BLOCK_FACE_YM).ID: return 8182; case ChainCommandBlock::ChainCommandBlock(false, eBlockFace::BLOCK_FACE_ZM).ID: return 8183; case ChainCommandBlock::ChainCommandBlock(false, eBlockFace::BLOCK_FACE_XP).ID: return 8184; case ChainCommandBlock::ChainCommandBlock(false, eBlockFace::BLOCK_FACE_ZP).ID: return 8185; case ChainCommandBlock::ChainCommandBlock(false, eBlockFace::BLOCK_FACE_XM).ID: return 8186; case ChainCommandBlock::ChainCommandBlock(false, eBlockFace::BLOCK_FACE_YP).ID: return 8187; case ChainCommandBlock::ChainCommandBlock(false, eBlockFace::BLOCK_FACE_YM).ID: return 8188; case Chest::Chest(eBlockFace::BLOCK_FACE_ZM, Chest::Type::Single).ID: return 1730; case Chest::Chest(eBlockFace::BLOCK_FACE_ZM, Chest::Type::Left).ID: return 1732; case Chest::Chest(eBlockFace::BLOCK_FACE_ZM, Chest::Type::Right).ID: return 1734; case Chest::Chest(eBlockFace::BLOCK_FACE_ZP, Chest::Type::Single).ID: return 1736; case Chest::Chest(eBlockFace::BLOCK_FACE_ZP, Chest::Type::Left).ID: return 1738; case Chest::Chest(eBlockFace::BLOCK_FACE_ZP, Chest::Type::Right).ID: return 1740; case Chest::Chest(eBlockFace::BLOCK_FACE_XM, Chest::Type::Single).ID: return 1742; case Chest::Chest(eBlockFace::BLOCK_FACE_XM, Chest::Type::Left).ID: return 1744; case Chest::Chest(eBlockFace::BLOCK_FACE_XM, Chest::Type::Right).ID: return 1746; case Chest::Chest(eBlockFace::BLOCK_FACE_XP, Chest::Type::Single).ID: return 1748; case Chest::Chest(eBlockFace::BLOCK_FACE_XP, Chest::Type::Left).ID: return 1750; case Chest::Chest(eBlockFace::BLOCK_FACE_XP, Chest::Type::Right).ID: return 1752; case ChippedAnvil::ChippedAnvil(eBlockFace::BLOCK_FACE_ZM).ID: return 5572; case ChippedAnvil::ChippedAnvil(eBlockFace::BLOCK_FACE_ZP).ID: return 5573; case ChippedAnvil::ChippedAnvil(eBlockFace::BLOCK_FACE_XM).ID: return 5574; case ChippedAnvil::ChippedAnvil(eBlockFace::BLOCK_FACE_XP).ID: return 5575; case ChiseledQuartzBlock::ChiseledQuartzBlock().ID: return 5697; case ChiseledRedSandstone::ChiseledRedSandstone().ID: return 7176; case ChiseledSandstone::ChiseledSandstone().ID: return 246; case ChiseledStoneBricks::ChiseledStoneBricks().ID: return 3987; case ChorusFlower::ChorusFlower(0).ID: return 8068; case ChorusFlower::ChorusFlower(1).ID: return 8069; case ChorusFlower::ChorusFlower(2).ID: return 8070; case ChorusFlower::ChorusFlower(3).ID: return 8071; case ChorusFlower::ChorusFlower(4).ID: return 8072; case ChorusFlower::ChorusFlower(5).ID: return 8073; case ChorusPlant::ChorusPlant(true, true, true, true, true, true).ID: return 8004; case ChorusPlant::ChorusPlant(true, true, true, true, true, false).ID: return 8005; case ChorusPlant::ChorusPlant(true, true, true, true, false, true).ID: return 8006; case ChorusPlant::ChorusPlant(true, true, true, true, false, false).ID: return 8007; case ChorusPlant::ChorusPlant(true, true, true, false, true, true).ID: return 8008; case ChorusPlant::ChorusPlant(true, true, true, false, true, false).ID: return 8009; case ChorusPlant::ChorusPlant(true, true, true, false, false, true).ID: return 8010; case ChorusPlant::ChorusPlant(true, true, true, false, false, false).ID: return 8011; case ChorusPlant::ChorusPlant(true, true, false, true, true, true).ID: return 8012; case ChorusPlant::ChorusPlant(true, true, false, true, true, false).ID: return 8013; case ChorusPlant::ChorusPlant(true, true, false, true, false, true).ID: return 8014; case ChorusPlant::ChorusPlant(true, true, false, true, false, false).ID: return 8015; case ChorusPlant::ChorusPlant(true, true, false, false, true, true).ID: return 8016; case ChorusPlant::ChorusPlant(true, true, false, false, true, false).ID: return 8017; case ChorusPlant::ChorusPlant(true, true, false, false, false, true).ID: return 8018; case ChorusPlant::ChorusPlant(true, true, false, false, false, false).ID: return 8019; case ChorusPlant::ChorusPlant(true, false, true, true, true, true).ID: return 8020; case ChorusPlant::ChorusPlant(true, false, true, true, true, false).ID: return 8021; case ChorusPlant::ChorusPlant(true, false, true, true, false, true).ID: return 8022; case ChorusPlant::ChorusPlant(true, false, true, true, false, false).ID: return 8023; case ChorusPlant::ChorusPlant(true, false, true, false, true, true).ID: return 8024; case ChorusPlant::ChorusPlant(true, false, true, false, true, false).ID: return 8025; case ChorusPlant::ChorusPlant(true, false, true, false, false, true).ID: return 8026; case ChorusPlant::ChorusPlant(true, false, true, false, false, false).ID: return 8027; case ChorusPlant::ChorusPlant(true, false, false, true, true, true).ID: return 8028; case ChorusPlant::ChorusPlant(true, false, false, true, true, false).ID: return 8029; case ChorusPlant::ChorusPlant(true, false, false, true, false, true).ID: return 8030; case ChorusPlant::ChorusPlant(true, false, false, true, false, false).ID: return 8031; case ChorusPlant::ChorusPlant(true, false, false, false, true, true).ID: return 8032; case ChorusPlant::ChorusPlant(true, false, false, false, true, false).ID: return 8033; case ChorusPlant::ChorusPlant(true, false, false, false, false, true).ID: return 8034; case ChorusPlant::ChorusPlant(true, false, false, false, false, false).ID: return 8035; case ChorusPlant::ChorusPlant(false, true, true, true, true, true).ID: return 8036; case ChorusPlant::ChorusPlant(false, true, true, true, true, false).ID: return 8037; case ChorusPlant::ChorusPlant(false, true, true, true, false, true).ID: return 8038; case ChorusPlant::ChorusPlant(false, true, true, true, false, false).ID: return 8039; case ChorusPlant::ChorusPlant(false, true, true, false, true, true).ID: return 8040; case ChorusPlant::ChorusPlant(false, true, true, false, true, false).ID: return 8041; case ChorusPlant::ChorusPlant(false, true, true, false, false, true).ID: return 8042; case ChorusPlant::ChorusPlant(false, true, true, false, false, false).ID: return 8043; case ChorusPlant::ChorusPlant(false, true, false, true, true, true).ID: return 8044; case ChorusPlant::ChorusPlant(false, true, false, true, true, false).ID: return 8045; case ChorusPlant::ChorusPlant(false, true, false, true, false, true).ID: return 8046; case ChorusPlant::ChorusPlant(false, true, false, true, false, false).ID: return 8047; case ChorusPlant::ChorusPlant(false, true, false, false, true, true).ID: return 8048; case ChorusPlant::ChorusPlant(false, true, false, false, true, false).ID: return 8049; case ChorusPlant::ChorusPlant(false, true, false, false, false, true).ID: return 8050; case ChorusPlant::ChorusPlant(false, true, false, false, false, false).ID: return 8051; case ChorusPlant::ChorusPlant(false, false, true, true, true, true).ID: return 8052; case ChorusPlant::ChorusPlant(false, false, true, true, true, false).ID: return 8053; case ChorusPlant::ChorusPlant(false, false, true, true, false, true).ID: return 8054; case ChorusPlant::ChorusPlant(false, false, true, true, false, false).ID: return 8055; case ChorusPlant::ChorusPlant(false, false, true, false, true, true).ID: return 8056; case ChorusPlant::ChorusPlant(false, false, true, false, true, false).ID: return 8057; case ChorusPlant::ChorusPlant(false, false, true, false, false, true).ID: return 8058; case ChorusPlant::ChorusPlant(false, false, true, false, false, false).ID: return 8059; case ChorusPlant::ChorusPlant(false, false, false, true, true, true).ID: return 8060; case ChorusPlant::ChorusPlant(false, false, false, true, true, false).ID: return 8061; case ChorusPlant::ChorusPlant(false, false, false, true, false, true).ID: return 8062; case ChorusPlant::ChorusPlant(false, false, false, true, false, false).ID: return 8063; case ChorusPlant::ChorusPlant(false, false, false, false, true, true).ID: return 8064; case ChorusPlant::ChorusPlant(false, false, false, false, true, false).ID: return 8065; case ChorusPlant::ChorusPlant(false, false, false, false, false, true).ID: return 8066; case ChorusPlant::ChorusPlant(false, false, false, false, false, false).ID: return 8067; case Clay::Clay().ID: return 3442; case CoalBlock::CoalBlock().ID: return 6841; case CoalOre::CoalOre().ID: return 71; case CoarseDirt::CoarseDirt().ID: return 11; case Cobblestone::Cobblestone().ID: return 14; case CobblestoneSlab::CobblestoneSlab(CobblestoneSlab::Type::Top).ID: return 7313; case CobblestoneSlab::CobblestoneSlab(CobblestoneSlab::Type::Bottom).ID: return 7315; case CobblestoneSlab::CobblestoneSlab(CobblestoneSlab::Type::Double).ID: return 7317; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::Straight).ID: return 3191; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::InnerLeft).ID: return 3193; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::InnerRight).ID: return 3195; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::OuterLeft).ID: return 3197; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::OuterRight).ID: return 3199; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::Straight).ID: return 3201; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::InnerLeft).ID: return 3203; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::InnerRight).ID: return 3205; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::OuterLeft).ID: return 3207; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::OuterRight).ID: return 3209; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::Straight).ID: return 3211; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::InnerLeft).ID: return 3213; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::InnerRight).ID: return 3215; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::OuterLeft).ID: return 3217; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::OuterRight).ID: return 3219; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::Straight).ID: return 3221; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::InnerLeft).ID: return 3223; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::InnerRight).ID: return 3225; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::OuterLeft).ID: return 3227; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::OuterRight).ID: return 3229; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XM, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::Straight).ID: return 3231; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XM, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::InnerLeft).ID: return 3233; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XM, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::InnerRight).ID: return 3235; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XM, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::OuterLeft).ID: return 3237; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XM, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::OuterRight).ID: return 3239; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XM, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::Straight).ID: return 3241; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XM, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::InnerLeft).ID: return 3243; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XM, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::InnerRight).ID: return 3245; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XM, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::OuterLeft).ID: return 3247; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XM, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::OuterRight).ID: return 3249; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XP, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::Straight).ID: return 3251; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XP, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::InnerLeft).ID: return 3253; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XP, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::InnerRight).ID: return 3255; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XP, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::OuterLeft).ID: return 3257; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XP, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::OuterRight).ID: return 3259; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XP, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::Straight).ID: return 3261; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XP, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::InnerLeft).ID: return 3263; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XP, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::InnerRight).ID: return 3265; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XP, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::OuterLeft).ID: return 3267; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XP, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::OuterRight).ID: return 3269; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::Low, CobblestoneWall::South::Low, true, CobblestoneWall::West::Low).ID: return 5140; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::Low, CobblestoneWall::South::Low, true, CobblestoneWall::West::None).ID: return 5141; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::Low, CobblestoneWall::South::Low, false, CobblestoneWall::West::Low).ID: return 5144; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::Low, CobblestoneWall::South::Low, false, CobblestoneWall::West::None).ID: return 5145; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::Low, CobblestoneWall::South::None, true, CobblestoneWall::West::Low).ID: return 5148; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::Low, CobblestoneWall::South::None, true, CobblestoneWall::West::None).ID: return 5149; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::Low, CobblestoneWall::South::None, false, CobblestoneWall::West::Low).ID: return 5152; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::Low, CobblestoneWall::South::None, false, CobblestoneWall::West::None).ID: return 5153; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::None, CobblestoneWall::South::Low, true, CobblestoneWall::West::Low).ID: return 5156; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::None, CobblestoneWall::South::Low, true, CobblestoneWall::West::None).ID: return 5157; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::None, CobblestoneWall::South::Low, false, CobblestoneWall::West::Low).ID: return 5160; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::None, CobblestoneWall::South::Low, false, CobblestoneWall::West::None).ID: return 5161; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::None, CobblestoneWall::South::None, true, CobblestoneWall::West::Low).ID: return 5164; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::None, CobblestoneWall::South::None, true, CobblestoneWall::West::None).ID: return 5165; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::None, CobblestoneWall::South::None, false, CobblestoneWall::West::Low).ID: return 5168; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::None, CobblestoneWall::South::None, false, CobblestoneWall::West::None).ID: return 5169; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::Low, CobblestoneWall::South::Low, true, CobblestoneWall::West::Low).ID: return 5172; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::Low, CobblestoneWall::South::Low, true, CobblestoneWall::West::None).ID: return 5173; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::Low, CobblestoneWall::South::Low, false, CobblestoneWall::West::Low).ID: return 5176; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::Low, CobblestoneWall::South::Low, false, CobblestoneWall::West::None).ID: return 5177; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::Low, CobblestoneWall::South::None, true, CobblestoneWall::West::Low).ID: return 5180; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::Low, CobblestoneWall::South::None, true, CobblestoneWall::West::None).ID: return 5181; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::Low, CobblestoneWall::South::None, false, CobblestoneWall::West::Low).ID: return 5184; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::Low, CobblestoneWall::South::None, false, CobblestoneWall::West::None).ID: return 5185; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::None, CobblestoneWall::South::Low, true, CobblestoneWall::West::Low).ID: return 5188; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::None, CobblestoneWall::South::Low, true, CobblestoneWall::West::None).ID: return 5189; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::None, CobblestoneWall::South::Low, false, CobblestoneWall::West::Low).ID: return 5192; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::None, CobblestoneWall::South::Low, false, CobblestoneWall::West::None).ID: return 5193; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::None, CobblestoneWall::South::None, true, CobblestoneWall::West::Low).ID: return 5196; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::None, CobblestoneWall::South::None, true, CobblestoneWall::West::None).ID: return 5197; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::None, CobblestoneWall::South::None, false, CobblestoneWall::West::Low).ID: return 5200; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::None, CobblestoneWall::South::None, false, CobblestoneWall::West::None).ID: return 5201; case Cobweb::Cobweb().ID: return 1040; case Cocoa::Cocoa(0, eBlockFace::BLOCK_FACE_ZM).ID: return 4639; case Cocoa::Cocoa(0, eBlockFace::BLOCK_FACE_ZP).ID: return 4640; case Cocoa::Cocoa(0, eBlockFace::BLOCK_FACE_XM).ID: return 4641; case Cocoa::Cocoa(0, eBlockFace::BLOCK_FACE_XP).ID: return 4642; case Cocoa::Cocoa(1, eBlockFace::BLOCK_FACE_ZM).ID: return 4643; case Cocoa::Cocoa(1, eBlockFace::BLOCK_FACE_ZP).ID: return 4644; case Cocoa::Cocoa(1, eBlockFace::BLOCK_FACE_XM).ID: return 4645; case Cocoa::Cocoa(1, eBlockFace::BLOCK_FACE_XP).ID: return 4646; case Cocoa::Cocoa(2, eBlockFace::BLOCK_FACE_ZM).ID: return 4647; case Cocoa::Cocoa(2, eBlockFace::BLOCK_FACE_ZP).ID: return 4648; case Cocoa::Cocoa(2, eBlockFace::BLOCK_FACE_XM).ID: return 4649; case Cocoa::Cocoa(2, eBlockFace::BLOCK_FACE_XP).ID: return 4650; case CommandBlock::CommandBlock(true, eBlockFace::BLOCK_FACE_ZM).ID: return 5125; case CommandBlock::CommandBlock(true, eBlockFace::BLOCK_FACE_XP).ID: return 5126; case CommandBlock::CommandBlock(true, eBlockFace::BLOCK_FACE_ZP).ID: return 5127; case CommandBlock::CommandBlock(true, eBlockFace::BLOCK_FACE_XM).ID: return 5128; case CommandBlock::CommandBlock(true, eBlockFace::BLOCK_FACE_YP).ID: return 5129; case CommandBlock::CommandBlock(true, eBlockFace::BLOCK_FACE_YM).ID: return 5130; case CommandBlock::CommandBlock(false, eBlockFace::BLOCK_FACE_ZM).ID: return 5131; case CommandBlock::CommandBlock(false, eBlockFace::BLOCK_FACE_XP).ID: return 5132; case CommandBlock::CommandBlock(false, eBlockFace::BLOCK_FACE_ZP).ID: return 5133; case CommandBlock::CommandBlock(false, eBlockFace::BLOCK_FACE_XM).ID: return 5134; case CommandBlock::CommandBlock(false, eBlockFace::BLOCK_FACE_YP).ID: return 5135; case CommandBlock::CommandBlock(false, eBlockFace::BLOCK_FACE_YM).ID: return 5136; case Comparator::Comparator(eBlockFace::BLOCK_FACE_ZM, Comparator::Mode::Compare, true).ID: return 5636; case Comparator::Comparator(eBlockFace::BLOCK_FACE_ZM, Comparator::Mode::Compare, false).ID: return 5637; case Comparator::Comparator(eBlockFace::BLOCK_FACE_ZM, Comparator::Mode::Subtract, true).ID: return 5638; case Comparator::Comparator(eBlockFace::BLOCK_FACE_ZM, Comparator::Mode::Subtract, false).ID: return 5639; case Comparator::Comparator(eBlockFace::BLOCK_FACE_ZP, Comparator::Mode::Compare, true).ID: return 5640; case Comparator::Comparator(eBlockFace::BLOCK_FACE_ZP, Comparator::Mode::Compare, false).ID: return 5641; case Comparator::Comparator(eBlockFace::BLOCK_FACE_ZP, Comparator::Mode::Subtract, true).ID: return 5642; case Comparator::Comparator(eBlockFace::BLOCK_FACE_ZP, Comparator::Mode::Subtract, false).ID: return 5643; case Comparator::Comparator(eBlockFace::BLOCK_FACE_XM, Comparator::Mode::Compare, true).ID: return 5644; case Comparator::Comparator(eBlockFace::BLOCK_FACE_XM, Comparator::Mode::Compare, false).ID: return 5645; case Comparator::Comparator(eBlockFace::BLOCK_FACE_XM, Comparator::Mode::Subtract, true).ID: return 5646; case Comparator::Comparator(eBlockFace::BLOCK_FACE_XM, Comparator::Mode::Subtract, false).ID: return 5647; case Comparator::Comparator(eBlockFace::BLOCK_FACE_XP, Comparator::Mode::Compare, true).ID: return 5648; case Comparator::Comparator(eBlockFace::BLOCK_FACE_XP, Comparator::Mode::Compare, false).ID: return 5649; case Comparator::Comparator(eBlockFace::BLOCK_FACE_XP, Comparator::Mode::Subtract, true).ID: return 5650; case Comparator::Comparator(eBlockFace::BLOCK_FACE_XP, Comparator::Mode::Subtract, false).ID: return 5651; case Conduit::Conduit().ID: return 8590; case CrackedStoneBricks::CrackedStoneBricks().ID: return 3986; case CraftingTable::CraftingTable().ID: return 3051; case CreeperHead::CreeperHead(0).ID: return 5532; case CreeperHead::CreeperHead(1).ID: return 5533; case CreeperHead::CreeperHead(2).ID: return 5534; case CreeperHead::CreeperHead(3).ID: return 5535; case CreeperHead::CreeperHead(4).ID: return 5536; case CreeperHead::CreeperHead(5).ID: return 5537; case CreeperHead::CreeperHead(6).ID: return 5538; case CreeperHead::CreeperHead(7).ID: return 5539; case CreeperHead::CreeperHead(8).ID: return 5540; case CreeperHead::CreeperHead(9).ID: return 5541; case CreeperHead::CreeperHead(10).ID: return 5542; case CreeperHead::CreeperHead(11).ID: return 5543; case CreeperHead::CreeperHead(12).ID: return 5544; case CreeperHead::CreeperHead(13).ID: return 5545; case CreeperHead::CreeperHead(14).ID: return 5546; case CreeperHead::CreeperHead(15).ID: return 5547; case CreeperWallHead::CreeperWallHead(eBlockFace::BLOCK_FACE_ZM).ID: return 5528; case CreeperWallHead::CreeperWallHead(eBlockFace::BLOCK_FACE_ZP).ID: return 5529; case CreeperWallHead::CreeperWallHead(eBlockFace::BLOCK_FACE_XM).ID: return 5530; case CreeperWallHead::CreeperWallHead(eBlockFace::BLOCK_FACE_XP).ID: return 5531; case CutRedSandstone::CutRedSandstone().ID: return 7177; case CutSandstone::CutSandstone().ID: return 247; case CyanBanner::CyanBanner(0).ID: return 6999; case CyanBanner::CyanBanner(1).ID: return 7000; case CyanBanner::CyanBanner(2).ID: return 7001; case CyanBanner::CyanBanner(3).ID: return 7002; case CyanBanner::CyanBanner(4).ID: return 7003; case CyanBanner::CyanBanner(5).ID: return 7004; case CyanBanner::CyanBanner(6).ID: return 7005; case CyanBanner::CyanBanner(7).ID: return 7006; case CyanBanner::CyanBanner(8).ID: return 7007; case CyanBanner::CyanBanner(9).ID: return 7008; case CyanBanner::CyanBanner(10).ID: return 7009; case CyanBanner::CyanBanner(11).ID: return 7010; case CyanBanner::CyanBanner(12).ID: return 7011; case CyanBanner::CyanBanner(13).ID: return 7012; case CyanBanner::CyanBanner(14).ID: return 7013; case CyanBanner::CyanBanner(15).ID: return 7014; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_ZM, true, CyanBed::Part::Head).ID: return 892; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_ZM, true, CyanBed::Part::Foot).ID: return 893; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_ZM, false, CyanBed::Part::Head).ID: return 894; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_ZM, false, CyanBed::Part::Foot).ID: return 895; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_ZP, true, CyanBed::Part::Head).ID: return 896; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_ZP, true, CyanBed::Part::Foot).ID: return 897; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_ZP, false, CyanBed::Part::Head).ID: return 898; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_ZP, false, CyanBed::Part::Foot).ID: return 899; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_XM, true, CyanBed::Part::Head).ID: return 900; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_XM, true, CyanBed::Part::Foot).ID: return 901; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_XM, false, CyanBed::Part::Head).ID: return 902; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_XM, false, CyanBed::Part::Foot).ID: return 903; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_XP, true, CyanBed::Part::Head).ID: return 904; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_XP, true, CyanBed::Part::Foot).ID: return 905; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_XP, false, CyanBed::Part::Head).ID: return 906; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_XP, false, CyanBed::Part::Foot).ID: return 907; case CyanCarpet::CyanCarpet().ID: return 6833; case CyanConcrete::CyanConcrete().ID: return 8387; case CyanConcretePowder::CyanConcretePowder().ID: return 8403; case CyanGlazedTerracotta::CyanGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 8350; case CyanGlazedTerracotta::CyanGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 8351; case CyanGlazedTerracotta::CyanGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 8352; case CyanGlazedTerracotta::CyanGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 8353; case CyanShulkerBox::CyanShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 8272; case CyanShulkerBox::CyanShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 8273; case CyanShulkerBox::CyanShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 8274; case CyanShulkerBox::CyanShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 8275; case CyanShulkerBox::CyanShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 8276; case CyanShulkerBox::CyanShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 8277; case CyanStainedGlass::CyanStainedGlass().ID: return 3587; case CyanStainedGlassPane::CyanStainedGlassPane(true, true, true, true).ID: return 6111; case CyanStainedGlassPane::CyanStainedGlassPane(true, true, true, false).ID: return 6112; case CyanStainedGlassPane::CyanStainedGlassPane(true, true, false, true).ID: return 6115; case CyanStainedGlassPane::CyanStainedGlassPane(true, true, false, false).ID: return 6116; case CyanStainedGlassPane::CyanStainedGlassPane(true, false, true, true).ID: return 6119; case CyanStainedGlassPane::CyanStainedGlassPane(true, false, true, false).ID: return 6120; case CyanStainedGlassPane::CyanStainedGlassPane(true, false, false, true).ID: return 6123; case CyanStainedGlassPane::CyanStainedGlassPane(true, false, false, false).ID: return 6124; case CyanStainedGlassPane::CyanStainedGlassPane(false, true, true, true).ID: return 6127; case CyanStainedGlassPane::CyanStainedGlassPane(false, true, true, false).ID: return 6128; case CyanStainedGlassPane::CyanStainedGlassPane(false, true, false, true).ID: return 6131; case CyanStainedGlassPane::CyanStainedGlassPane(false, true, false, false).ID: return 6132; case CyanStainedGlassPane::CyanStainedGlassPane(false, false, true, true).ID: return 6135; case CyanStainedGlassPane::CyanStainedGlassPane(false, false, true, false).ID: return 6136; case CyanStainedGlassPane::CyanStainedGlassPane(false, false, false, true).ID: return 6139; case CyanStainedGlassPane::CyanStainedGlassPane(false, false, false, false).ID: return 6140; case CyanTerracotta::CyanTerracotta().ID: return 5814; case CyanWallBanner::CyanWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 7147; case CyanWallBanner::CyanWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 7148; case CyanWallBanner::CyanWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 7149; case CyanWallBanner::CyanWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 7150; case CyanWool::CyanWool().ID: return 1092; case DamagedAnvil::DamagedAnvil(eBlockFace::BLOCK_FACE_ZM).ID: return 5576; case DamagedAnvil::DamagedAnvil(eBlockFace::BLOCK_FACE_ZP).ID: return 5577; case DamagedAnvil::DamagedAnvil(eBlockFace::BLOCK_FACE_XM).ID: return 5578; case DamagedAnvil::DamagedAnvil(eBlockFace::BLOCK_FACE_XP).ID: return 5579; case Dandelion::Dandelion().ID: return 1111; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5424; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5425; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5426; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5427; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, true).ID: return 5428; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, false).ID: return 5429; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, true).ID: return 5430; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, false).ID: return 5431; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5432; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5433; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5434; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5435; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, true).ID: return 5436; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, false).ID: return 5437; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, true).ID: return 5438; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, false).ID: return 5439; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5440; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5441; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5442; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5443; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, true).ID: return 5444; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, false).ID: return 5445; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, true).ID: return 5446; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, false).ID: return 5447; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, true, true).ID: return 7934; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, true, false).ID: return 7935; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, false, true).ID: return 7936; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, false, false).ID: return 7937; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, true, true).ID: return 7938; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, true, false).ID: return 7939; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, false, true).ID: return 7940; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, false, false).ID: return 7941; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, true, true).ID: return 7942; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, true, false).ID: return 7943; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, false, true).ID: return 7944; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, false, false).ID: return 7945; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, true, true).ID: return 7946; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, true, false).ID: return 7947; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, false, true).ID: return 7948; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, false, false).ID: return 7949; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, true, true).ID: return 7950; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, true, false).ID: return 7951; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, false, true).ID: return 7952; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, false, false).ID: return 7953; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, true, true).ID: return 7954; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, true, false).ID: return 7955; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, false, true).ID: return 7956; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, false, false).ID: return 7957; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, true, true).ID: return 7958; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, true, false).ID: return 7959; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, false, true).ID: return 7960; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, false, false).ID: return 7961; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, true, true).ID: return 7962; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, true, false).ID: return 7963; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, false, true).ID: return 7964; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, false, false).ID: return 7965; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, true, true).ID: return 7966; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, true, false).ID: return 7967; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, false, true).ID: return 7968; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, false, false).ID: return 7969; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, true, true).ID: return 7970; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, true, false).ID: return 7971; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, false, true).ID: return 7972; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, false, false).ID: return 7973; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, true, true).ID: return 7974; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, true, false).ID: return 7975; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, false, true).ID: return 7976; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, false, false).ID: return 7977; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, true, true).ID: return 7978; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, true, false).ID: return 7979; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, false, true).ID: return 7980; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, false, false).ID: return 7981; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, true, true).ID: return 7982; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, true, false).ID: return 7983; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, false, true).ID: return 7984; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, false, false).ID: return 7985; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, true, true).ID: return 7986; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, true, false).ID: return 7987; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, false, true).ID: return 7988; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, false, false).ID: return 7989; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, true, true).ID: return 7990; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, true, false).ID: return 7991; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, false, true).ID: return 7992; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, false, false).ID: return 7993; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, true, true).ID: return 7994; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, true, false).ID: return 7995; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, false, true).ID: return 7996; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, false, false).ID: return 7997; case DarkOakFence::DarkOakFence(true, true, true, true).ID: return 7648; case DarkOakFence::DarkOakFence(true, true, true, false).ID: return 7649; case DarkOakFence::DarkOakFence(true, true, false, true).ID: return 7652; case DarkOakFence::DarkOakFence(true, true, false, false).ID: return 7653; case DarkOakFence::DarkOakFence(true, false, true, true).ID: return 7656; case DarkOakFence::DarkOakFence(true, false, true, false).ID: return 7657; case DarkOakFence::DarkOakFence(true, false, false, true).ID: return 7660; case DarkOakFence::DarkOakFence(true, false, false, false).ID: return 7661; case DarkOakFence::DarkOakFence(false, true, true, true).ID: return 7664; case DarkOakFence::DarkOakFence(false, true, true, false).ID: return 7665; case DarkOakFence::DarkOakFence(false, true, false, true).ID: return 7668; case DarkOakFence::DarkOakFence(false, true, false, false).ID: return 7669; case DarkOakFence::DarkOakFence(false, false, true, true).ID: return 7672; case DarkOakFence::DarkOakFence(false, false, true, false).ID: return 7673; case DarkOakFence::DarkOakFence(false, false, false, true).ID: return 7676; case DarkOakFence::DarkOakFence(false, false, false, false).ID: return 7677; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZM, true, true, true).ID: return 7486; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZM, true, true, false).ID: return 7487; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZM, true, false, true).ID: return 7488; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZM, true, false, false).ID: return 7489; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, true).ID: return 7490; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, false).ID: return 7491; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, true).ID: return 7492; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, false).ID: return 7493; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZP, true, true, true).ID: return 7494; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZP, true, true, false).ID: return 7495; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZP, true, false, true).ID: return 7496; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZP, true, false, false).ID: return 7497; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, true).ID: return 7498; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, false).ID: return 7499; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, true).ID: return 7500; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, false).ID: return 7501; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XM, true, true, true).ID: return 7502; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XM, true, true, false).ID: return 7503; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XM, true, false, true).ID: return 7504; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XM, true, false, false).ID: return 7505; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, true).ID: return 7506; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, false).ID: return 7507; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, true).ID: return 7508; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, false).ID: return 7509; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XP, true, true, true).ID: return 7510; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XP, true, true, false).ID: return 7511; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XP, true, false, true).ID: return 7512; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XP, true, false, false).ID: return 7513; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, true).ID: return 7514; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, false).ID: return 7515; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, true).ID: return 7516; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, false).ID: return 7517; case DarkOakLeaves::DarkOakLeaves(1, true).ID: return 214; case DarkOakLeaves::DarkOakLeaves(1, false).ID: return 215; case DarkOakLeaves::DarkOakLeaves(2, true).ID: return 216; case DarkOakLeaves::DarkOakLeaves(2, false).ID: return 217; case DarkOakLeaves::DarkOakLeaves(3, true).ID: return 218; case DarkOakLeaves::DarkOakLeaves(3, false).ID: return 219; case DarkOakLeaves::DarkOakLeaves(4, true).ID: return 220; case DarkOakLeaves::DarkOakLeaves(4, false).ID: return 221; case DarkOakLeaves::DarkOakLeaves(5, true).ID: return 222; case DarkOakLeaves::DarkOakLeaves(5, false).ID: return 223; case DarkOakLeaves::DarkOakLeaves(6, true).ID: return 224; case DarkOakLeaves::DarkOakLeaves(6, false).ID: return 225; case DarkOakLeaves::DarkOakLeaves(7, true).ID: return 226; case DarkOakLeaves::DarkOakLeaves(7, false).ID: return 227; case DarkOakLog::DarkOakLog(DarkOakLog::Axis::X).ID: return 87; case DarkOakLog::DarkOakLog(DarkOakLog::Axis::Y).ID: return 88; case DarkOakLog::DarkOakLog(DarkOakLog::Axis::Z).ID: return 89; case DarkOakPlanks::DarkOakPlanks().ID: return 20; case DarkOakPressurePlate::DarkOakPressurePlate(true).ID: return 3378; case DarkOakPressurePlate::DarkOakPressurePlate(false).ID: return 3379; case DarkOakSapling::DarkOakSapling(0).ID: return 31; case DarkOakSapling::DarkOakSapling(1).ID: return 32; case DarkOakSlab::DarkOakSlab(DarkOakSlab::Type::Top).ID: return 7289; case DarkOakSlab::DarkOakSlab(DarkOakSlab::Type::Bottom).ID: return 7291; case DarkOakSlab::DarkOakSlab(DarkOakSlab::Type::Double).ID: return 7293; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZM, DarkOakStairs::Half::Top, DarkOakStairs::Shape::Straight).ID: return 6414; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZM, DarkOakStairs::Half::Top, DarkOakStairs::Shape::InnerLeft).ID: return 6416; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZM, DarkOakStairs::Half::Top, DarkOakStairs::Shape::InnerRight).ID: return 6418; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZM, DarkOakStairs::Half::Top, DarkOakStairs::Shape::OuterLeft).ID: return 6420; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZM, DarkOakStairs::Half::Top, DarkOakStairs::Shape::OuterRight).ID: return 6422; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZM, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::Straight).ID: return 6424; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZM, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::InnerLeft).ID: return 6426; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZM, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::InnerRight).ID: return 6428; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZM, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::OuterLeft).ID: return 6430; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZM, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::OuterRight).ID: return 6432; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZP, DarkOakStairs::Half::Top, DarkOakStairs::Shape::Straight).ID: return 6434; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZP, DarkOakStairs::Half::Top, DarkOakStairs::Shape::InnerLeft).ID: return 6436; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZP, DarkOakStairs::Half::Top, DarkOakStairs::Shape::InnerRight).ID: return 6438; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZP, DarkOakStairs::Half::Top, DarkOakStairs::Shape::OuterLeft).ID: return 6440; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZP, DarkOakStairs::Half::Top, DarkOakStairs::Shape::OuterRight).ID: return 6442; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZP, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::Straight).ID: return 6444; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZP, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::InnerLeft).ID: return 6446; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZP, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::InnerRight).ID: return 6448; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZP, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::OuterLeft).ID: return 6450; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZP, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::OuterRight).ID: return 6452; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XM, DarkOakStairs::Half::Top, DarkOakStairs::Shape::Straight).ID: return 6454; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XM, DarkOakStairs::Half::Top, DarkOakStairs::Shape::InnerLeft).ID: return 6456; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XM, DarkOakStairs::Half::Top, DarkOakStairs::Shape::InnerRight).ID: return 6458; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XM, DarkOakStairs::Half::Top, DarkOakStairs::Shape::OuterLeft).ID: return 6460; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XM, DarkOakStairs::Half::Top, DarkOakStairs::Shape::OuterRight).ID: return 6462; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XM, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::Straight).ID: return 6464; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XM, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::InnerLeft).ID: return 6466; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XM, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::InnerRight).ID: return 6468; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XM, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::OuterLeft).ID: return 6470; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XM, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::OuterRight).ID: return 6472; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XP, DarkOakStairs::Half::Top, DarkOakStairs::Shape::Straight).ID: return 6474; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XP, DarkOakStairs::Half::Top, DarkOakStairs::Shape::InnerLeft).ID: return 6476; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XP, DarkOakStairs::Half::Top, DarkOakStairs::Shape::InnerRight).ID: return 6478; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XP, DarkOakStairs::Half::Top, DarkOakStairs::Shape::OuterLeft).ID: return 6480; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XP, DarkOakStairs::Half::Top, DarkOakStairs::Shape::OuterRight).ID: return 6482; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XP, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::Straight).ID: return 6484; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XP, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::InnerLeft).ID: return 6486; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XP, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::InnerRight).ID: return 6488; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XP, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::OuterLeft).ID: return 6490; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XP, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::OuterRight).ID: return 6492; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZM, DarkOakTrapdoor::Half::Top, true, true).ID: return 3915; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZM, DarkOakTrapdoor::Half::Top, true, false).ID: return 3917; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZM, DarkOakTrapdoor::Half::Top, false, true).ID: return 3919; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZM, DarkOakTrapdoor::Half::Top, false, false).ID: return 3921; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZM, DarkOakTrapdoor::Half::Bottom, true, true).ID: return 3923; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZM, DarkOakTrapdoor::Half::Bottom, true, false).ID: return 3925; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZM, DarkOakTrapdoor::Half::Bottom, false, true).ID: return 3927; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZM, DarkOakTrapdoor::Half::Bottom, false, false).ID: return 3929; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZP, DarkOakTrapdoor::Half::Top, true, true).ID: return 3931; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZP, DarkOakTrapdoor::Half::Top, true, false).ID: return 3933; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZP, DarkOakTrapdoor::Half::Top, false, true).ID: return 3935; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZP, DarkOakTrapdoor::Half::Top, false, false).ID: return 3937; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZP, DarkOakTrapdoor::Half::Bottom, true, true).ID: return 3939; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZP, DarkOakTrapdoor::Half::Bottom, true, false).ID: return 3941; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZP, DarkOakTrapdoor::Half::Bottom, false, true).ID: return 3943; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZP, DarkOakTrapdoor::Half::Bottom, false, false).ID: return 3945; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XM, DarkOakTrapdoor::Half::Top, true, true).ID: return 3947; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XM, DarkOakTrapdoor::Half::Top, true, false).ID: return 3949; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XM, DarkOakTrapdoor::Half::Top, false, true).ID: return 3951; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XM, DarkOakTrapdoor::Half::Top, false, false).ID: return 3953; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XM, DarkOakTrapdoor::Half::Bottom, true, true).ID: return 3955; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XM, DarkOakTrapdoor::Half::Bottom, true, false).ID: return 3957; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XM, DarkOakTrapdoor::Half::Bottom, false, true).ID: return 3959; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XM, DarkOakTrapdoor::Half::Bottom, false, false).ID: return 3961; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XP, DarkOakTrapdoor::Half::Top, true, true).ID: return 3963; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XP, DarkOakTrapdoor::Half::Top, true, false).ID: return 3965; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XP, DarkOakTrapdoor::Half::Top, false, true).ID: return 3967; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XP, DarkOakTrapdoor::Half::Top, false, false).ID: return 3969; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XP, DarkOakTrapdoor::Half::Bottom, true, true).ID: return 3971; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XP, DarkOakTrapdoor::Half::Bottom, true, false).ID: return 3973; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XP, DarkOakTrapdoor::Half::Bottom, false, true).ID: return 3975; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XP, DarkOakTrapdoor::Half::Bottom, false, false).ID: return 3977; case DarkOakWood::DarkOakWood(DarkOakWood::Axis::X).ID: return 123; case DarkOakWood::DarkOakWood(DarkOakWood::Axis::Y).ID: return 124; case DarkOakWood::DarkOakWood(DarkOakWood::Axis::Z).ID: return 125; case DarkPrismarine::DarkPrismarine().ID: return 6561; case DarkPrismarineSlab::DarkPrismarineSlab(DarkPrismarineSlab::Type::Top).ID: return 6815; case DarkPrismarineSlab::DarkPrismarineSlab(DarkPrismarineSlab::Type::Bottom).ID: return 6817; case DarkPrismarineSlab::DarkPrismarineSlab(DarkPrismarineSlab::Type::Double).ID: return 6819; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZM, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::Straight).ID: return 6723; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZM, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::InnerLeft).ID: return 6725; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZM, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::InnerRight).ID: return 6727; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZM, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::OuterLeft).ID: return 6729; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZM, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::OuterRight).ID: return 6731; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZM, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::Straight).ID: return 6733; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZM, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::InnerLeft).ID: return 6735; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZM, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::InnerRight).ID: return 6737; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZM, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::OuterLeft).ID: return 6739; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZM, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::OuterRight).ID: return 6741; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZP, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::Straight).ID: return 6743; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZP, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::InnerLeft).ID: return 6745; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZP, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::InnerRight).ID: return 6747; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZP, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::OuterLeft).ID: return 6749; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZP, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::OuterRight).ID: return 6751; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZP, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::Straight).ID: return 6753; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZP, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::InnerLeft).ID: return 6755; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZP, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::InnerRight).ID: return 6757; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZP, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::OuterLeft).ID: return 6759; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZP, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::OuterRight).ID: return 6761; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XM, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::Straight).ID: return 6763; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XM, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::InnerLeft).ID: return 6765; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XM, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::InnerRight).ID: return 6767; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XM, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::OuterLeft).ID: return 6769; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XM, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::OuterRight).ID: return 6771; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XM, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::Straight).ID: return 6773; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XM, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::InnerLeft).ID: return 6775; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XM, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::InnerRight).ID: return 6777; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XM, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::OuterLeft).ID: return 6779; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XM, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::OuterRight).ID: return 6781; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XP, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::Straight).ID: return 6783; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XP, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::InnerLeft).ID: return 6785; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XP, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::InnerRight).ID: return 6787; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XP, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::OuterLeft).ID: return 6789; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XP, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::OuterRight).ID: return 6791; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XP, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::Straight).ID: return 6793; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XP, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::InnerLeft).ID: return 6795; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XP, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::InnerRight).ID: return 6797; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XP, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::OuterLeft).ID: return 6799; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XP, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::OuterRight).ID: return 6801; case DaylightDetector::DaylightDetector(true, 0).ID: return 5652; case DaylightDetector::DaylightDetector(true, 1).ID: return 5653; case DaylightDetector::DaylightDetector(true, 2).ID: return 5654; case DaylightDetector::DaylightDetector(true, 3).ID: return 5655; case DaylightDetector::DaylightDetector(true, 4).ID: return 5656; case DaylightDetector::DaylightDetector(true, 5).ID: return 5657; case DaylightDetector::DaylightDetector(true, 6).ID: return 5658; case DaylightDetector::DaylightDetector(true, 7).ID: return 5659; case DaylightDetector::DaylightDetector(true, 8).ID: return 5660; case DaylightDetector::DaylightDetector(true, 9).ID: return 5661; case DaylightDetector::DaylightDetector(true, 10).ID: return 5662; case DaylightDetector::DaylightDetector(true, 11).ID: return 5663; case DaylightDetector::DaylightDetector(true, 12).ID: return 5664; case DaylightDetector::DaylightDetector(true, 13).ID: return 5665; case DaylightDetector::DaylightDetector(true, 14).ID: return 5666; case DaylightDetector::DaylightDetector(true, 15).ID: return 5667; case DaylightDetector::DaylightDetector(false, 0).ID: return 5668; case DaylightDetector::DaylightDetector(false, 1).ID: return 5669; case DaylightDetector::DaylightDetector(false, 2).ID: return 5670; case DaylightDetector::DaylightDetector(false, 3).ID: return 5671; case DaylightDetector::DaylightDetector(false, 4).ID: return 5672; case DaylightDetector::DaylightDetector(false, 5).ID: return 5673; case DaylightDetector::DaylightDetector(false, 6).ID: return 5674; case DaylightDetector::DaylightDetector(false, 7).ID: return 5675; case DaylightDetector::DaylightDetector(false, 8).ID: return 5676; case DaylightDetector::DaylightDetector(false, 9).ID: return 5677; case DaylightDetector::DaylightDetector(false, 10).ID: return 5678; case DaylightDetector::DaylightDetector(false, 11).ID: return 5679; case DaylightDetector::DaylightDetector(false, 12).ID: return 5680; case DaylightDetector::DaylightDetector(false, 13).ID: return 5681; case DaylightDetector::DaylightDetector(false, 14).ID: return 5682; case DaylightDetector::DaylightDetector(false, 15).ID: return 5683; case DeadBrainCoral::DeadBrainCoral().ID: return 8463; case DeadBrainCoralBlock::DeadBrainCoralBlock().ID: return 8451; case DeadBrainCoralFan::DeadBrainCoralFan().ID: return 8563; case DeadBrainCoralWallFan::DeadBrainCoralWallFan(eBlockFace::BLOCK_FACE_ZM).ID: return 8489; case DeadBrainCoralWallFan::DeadBrainCoralWallFan(eBlockFace::BLOCK_FACE_ZP).ID: return 8491; case DeadBrainCoralWallFan::DeadBrainCoralWallFan(eBlockFace::BLOCK_FACE_XM).ID: return 8493; case DeadBrainCoralWallFan::DeadBrainCoralWallFan(eBlockFace::BLOCK_FACE_XP).ID: return 8495; case DeadBubbleCoral::DeadBubbleCoral().ID: return 8465; case DeadBubbleCoralBlock::DeadBubbleCoralBlock().ID: return 8452; case DeadBubbleCoralFan::DeadBubbleCoralFan().ID: return 8565; case DeadBubbleCoralWallFan::DeadBubbleCoralWallFan(eBlockFace::BLOCK_FACE_ZM).ID: return 8497; case DeadBubbleCoralWallFan::DeadBubbleCoralWallFan(eBlockFace::BLOCK_FACE_ZP).ID: return 8499; case DeadBubbleCoralWallFan::DeadBubbleCoralWallFan(eBlockFace::BLOCK_FACE_XM).ID: return 8501; case DeadBubbleCoralWallFan::DeadBubbleCoralWallFan(eBlockFace::BLOCK_FACE_XP).ID: return 8503; case DeadBush::DeadBush().ID: return 1043; case DeadFireCoral::DeadFireCoral().ID: return 8467; case DeadFireCoralBlock::DeadFireCoralBlock().ID: return 8453; case DeadFireCoralFan::DeadFireCoralFan().ID: return 8567; case DeadFireCoralWallFan::DeadFireCoralWallFan(eBlockFace::BLOCK_FACE_ZM).ID: return 8505; case DeadFireCoralWallFan::DeadFireCoralWallFan(eBlockFace::BLOCK_FACE_ZP).ID: return 8507; case DeadFireCoralWallFan::DeadFireCoralWallFan(eBlockFace::BLOCK_FACE_XM).ID: return 8509; case DeadFireCoralWallFan::DeadFireCoralWallFan(eBlockFace::BLOCK_FACE_XP).ID: return 8511; case DeadHornCoral::DeadHornCoral().ID: return 8469; case DeadHornCoralBlock::DeadHornCoralBlock().ID: return 8454; case DeadHornCoralFan::DeadHornCoralFan().ID: return 8569; case DeadHornCoralWallFan::DeadHornCoralWallFan(eBlockFace::BLOCK_FACE_ZM).ID: return 8513; case DeadHornCoralWallFan::DeadHornCoralWallFan(eBlockFace::BLOCK_FACE_ZP).ID: return 8515; case DeadHornCoralWallFan::DeadHornCoralWallFan(eBlockFace::BLOCK_FACE_XM).ID: return 8517; case DeadHornCoralWallFan::DeadHornCoralWallFan(eBlockFace::BLOCK_FACE_XP).ID: return 8519; case DeadTubeCoral::DeadTubeCoral().ID: return 8461; case DeadTubeCoralBlock::DeadTubeCoralBlock().ID: return 8450; case DeadTubeCoralFan::DeadTubeCoralFan().ID: return 8561; case DeadTubeCoralWallFan::DeadTubeCoralWallFan(eBlockFace::BLOCK_FACE_ZM).ID: return 8481; case DeadTubeCoralWallFan::DeadTubeCoralWallFan(eBlockFace::BLOCK_FACE_ZP).ID: return 8483; case DeadTubeCoralWallFan::DeadTubeCoralWallFan(eBlockFace::BLOCK_FACE_XM).ID: return 8485; case DeadTubeCoralWallFan::DeadTubeCoralWallFan(eBlockFace::BLOCK_FACE_XP).ID: return 8487; case DetectorRail::DetectorRail(true, DetectorRail::Shape::NorthSouth).ID: return 1016; case DetectorRail::DetectorRail(true, DetectorRail::Shape::EastWest).ID: return 1017; case DetectorRail::DetectorRail(true, DetectorRail::Shape::AscendingEast).ID: return 1018; case DetectorRail::DetectorRail(true, DetectorRail::Shape::AscendingWest).ID: return 1019; case DetectorRail::DetectorRail(true, DetectorRail::Shape::AscendingNorth).ID: return 1020; case DetectorRail::DetectorRail(true, DetectorRail::Shape::AscendingSouth).ID: return 1021; case DetectorRail::DetectorRail(false, DetectorRail::Shape::NorthSouth).ID: return 1022; case DetectorRail::DetectorRail(false, DetectorRail::Shape::EastWest).ID: return 1023; case DetectorRail::DetectorRail(false, DetectorRail::Shape::AscendingEast).ID: return 1024; case DetectorRail::DetectorRail(false, DetectorRail::Shape::AscendingWest).ID: return 1025; case DetectorRail::DetectorRail(false, DetectorRail::Shape::AscendingNorth).ID: return 1026; case DetectorRail::DetectorRail(false, DetectorRail::Shape::AscendingSouth).ID: return 1027; case DiamondBlock::DiamondBlock().ID: return 3050; case DiamondOre::DiamondOre().ID: return 3049; case Diorite::Diorite().ID: return 4; case Dirt::Dirt().ID: return 10; case Dispenser::Dispenser(eBlockFace::BLOCK_FACE_ZM, true).ID: return 233; case Dispenser::Dispenser(eBlockFace::BLOCK_FACE_ZM, false).ID: return 234; case Dispenser::Dispenser(eBlockFace::BLOCK_FACE_XP, true).ID: return 235; case Dispenser::Dispenser(eBlockFace::BLOCK_FACE_XP, false).ID: return 236; case Dispenser::Dispenser(eBlockFace::BLOCK_FACE_ZP, true).ID: return 237; case Dispenser::Dispenser(eBlockFace::BLOCK_FACE_ZP, false).ID: return 238; case Dispenser::Dispenser(eBlockFace::BLOCK_FACE_XM, true).ID: return 239; case Dispenser::Dispenser(eBlockFace::BLOCK_FACE_XM, false).ID: return 240; case Dispenser::Dispenser(eBlockFace::BLOCK_FACE_YP, true).ID: return 241; case Dispenser::Dispenser(eBlockFace::BLOCK_FACE_YP, false).ID: return 242; case Dispenser::Dispenser(eBlockFace::BLOCK_FACE_YM, true).ID: return 243; case Dispenser::Dispenser(eBlockFace::BLOCK_FACE_YM, false).ID: return 244; case DragonEgg::DragonEgg().ID: return 4636; case DragonHead::DragonHead(0).ID: return 5552; case DragonHead::DragonHead(1).ID: return 5553; case DragonHead::DragonHead(2).ID: return 5554; case DragonHead::DragonHead(3).ID: return 5555; case DragonHead::DragonHead(4).ID: return 5556; case DragonHead::DragonHead(5).ID: return 5557; case DragonHead::DragonHead(6).ID: return 5558; case DragonHead::DragonHead(7).ID: return 5559; case DragonHead::DragonHead(8).ID: return 5560; case DragonHead::DragonHead(9).ID: return 5561; case DragonHead::DragonHead(10).ID: return 5562; case DragonHead::DragonHead(11).ID: return 5563; case DragonHead::DragonHead(12).ID: return 5564; case DragonHead::DragonHead(13).ID: return 5565; case DragonHead::DragonHead(14).ID: return 5566; case DragonHead::DragonHead(15).ID: return 5567; case DragonWallHead::DragonWallHead(eBlockFace::BLOCK_FACE_ZM).ID: return 5548; case DragonWallHead::DragonWallHead(eBlockFace::BLOCK_FACE_ZP).ID: return 5549; case DragonWallHead::DragonWallHead(eBlockFace::BLOCK_FACE_XM).ID: return 5550; case DragonWallHead::DragonWallHead(eBlockFace::BLOCK_FACE_XP).ID: return 5551; case DriedKelpBlock::DriedKelpBlock().ID: return 8437; case Dropper::Dropper(eBlockFace::BLOCK_FACE_ZM, true).ID: return 5793; case Dropper::Dropper(eBlockFace::BLOCK_FACE_ZM, false).ID: return 5794; case Dropper::Dropper(eBlockFace::BLOCK_FACE_XP, true).ID: return 5795; case Dropper::Dropper(eBlockFace::BLOCK_FACE_XP, false).ID: return 5796; case Dropper::Dropper(eBlockFace::BLOCK_FACE_ZP, true).ID: return 5797; case Dropper::Dropper(eBlockFace::BLOCK_FACE_ZP, false).ID: return 5798; case Dropper::Dropper(eBlockFace::BLOCK_FACE_XM, true).ID: return 5799; case Dropper::Dropper(eBlockFace::BLOCK_FACE_XM, false).ID: return 5800; case Dropper::Dropper(eBlockFace::BLOCK_FACE_YP, true).ID: return 5801; case Dropper::Dropper(eBlockFace::BLOCK_FACE_YP, false).ID: return 5802; case Dropper::Dropper(eBlockFace::BLOCK_FACE_YM, true).ID: return 5803; case Dropper::Dropper(eBlockFace::BLOCK_FACE_YM, false).ID: return 5804; case EmeraldBlock::EmeraldBlock().ID: return 4884; case EmeraldOre::EmeraldOre().ID: return 4731; case EnchantingTable::EnchantingTable().ID: return 4613; case EndGateway::EndGateway().ID: return 8164; case EndPortal::EndPortal().ID: return 4626; case EndPortalFrame::EndPortalFrame(true, eBlockFace::BLOCK_FACE_ZM).ID: return 4627; case EndPortalFrame::EndPortalFrame(true, eBlockFace::BLOCK_FACE_ZP).ID: return 4628; case EndPortalFrame::EndPortalFrame(true, eBlockFace::BLOCK_FACE_XM).ID: return 4629; case EndPortalFrame::EndPortalFrame(true, eBlockFace::BLOCK_FACE_XP).ID: return 4630; case EndPortalFrame::EndPortalFrame(false, eBlockFace::BLOCK_FACE_ZM).ID: return 4631; case EndPortalFrame::EndPortalFrame(false, eBlockFace::BLOCK_FACE_ZP).ID: return 4632; case EndPortalFrame::EndPortalFrame(false, eBlockFace::BLOCK_FACE_XM).ID: return 4633; case EndPortalFrame::EndPortalFrame(false, eBlockFace::BLOCK_FACE_XP).ID: return 4634; case EndRod::EndRod(eBlockFace::BLOCK_FACE_ZM).ID: return 7998; case EndRod::EndRod(eBlockFace::BLOCK_FACE_XP).ID: return 7999; case EndRod::EndRod(eBlockFace::BLOCK_FACE_ZP).ID: return 8000; case EndRod::EndRod(eBlockFace::BLOCK_FACE_XM).ID: return 8001; case EndRod::EndRod(eBlockFace::BLOCK_FACE_YP).ID: return 8002; case EndRod::EndRod(eBlockFace::BLOCK_FACE_YM).ID: return 8003; case EndStone::EndStone().ID: return 4635; case EndStoneBricks::EndStoneBricks().ID: return 8158; case EnderChest::EnderChest(eBlockFace::BLOCK_FACE_ZM).ID: return 4733; case EnderChest::EnderChest(eBlockFace::BLOCK_FACE_ZP).ID: return 4735; case EnderChest::EnderChest(eBlockFace::BLOCK_FACE_XM).ID: return 4737; case EnderChest::EnderChest(eBlockFace::BLOCK_FACE_XP).ID: return 4739; case Farmland::Farmland(0).ID: return 3060; case Farmland::Farmland(1).ID: return 3061; case Farmland::Farmland(2).ID: return 3062; case Farmland::Farmland(3).ID: return 3063; case Farmland::Farmland(4).ID: return 3064; case Farmland::Farmland(5).ID: return 3065; case Farmland::Farmland(6).ID: return 3066; case Farmland::Farmland(7).ID: return 3067; case Fern::Fern().ID: return 1042; case Fire::Fire(0, true, true, true, true, true).ID: return 1136; case Fire::Fire(0, true, true, true, true, false).ID: return 1137; case Fire::Fire(0, true, true, true, false, true).ID: return 1138; case Fire::Fire(0, true, true, true, false, false).ID: return 1139; case Fire::Fire(0, true, true, false, true, true).ID: return 1140; case Fire::Fire(0, true, true, false, true, false).ID: return 1141; case Fire::Fire(0, true, true, false, false, true).ID: return 1142; case Fire::Fire(0, true, true, false, false, false).ID: return 1143; case Fire::Fire(0, true, false, true, true, true).ID: return 1144; case Fire::Fire(0, true, false, true, true, false).ID: return 1145; case Fire::Fire(0, true, false, true, false, true).ID: return 1146; case Fire::Fire(0, true, false, true, false, false).ID: return 1147; case Fire::Fire(0, true, false, false, true, true).ID: return 1148; case Fire::Fire(0, true, false, false, true, false).ID: return 1149; case Fire::Fire(0, true, false, false, false, true).ID: return 1150; case Fire::Fire(0, true, false, false, false, false).ID: return 1151; case Fire::Fire(0, false, true, true, true, true).ID: return 1152; case Fire::Fire(0, false, true, true, true, false).ID: return 1153; case Fire::Fire(0, false, true, true, false, true).ID: return 1154; case Fire::Fire(0, false, true, true, false, false).ID: return 1155; case Fire::Fire(0, false, true, false, true, true).ID: return 1156; case Fire::Fire(0, false, true, false, true, false).ID: return 1157; case Fire::Fire(0, false, true, false, false, true).ID: return 1158; case Fire::Fire(0, false, true, false, false, false).ID: return 1159; case Fire::Fire(0, false, false, true, true, true).ID: return 1160; case Fire::Fire(0, false, false, true, true, false).ID: return 1161; case Fire::Fire(0, false, false, true, false, true).ID: return 1162; case Fire::Fire(0, false, false, true, false, false).ID: return 1163; case Fire::Fire(0, false, false, false, true, true).ID: return 1164; case Fire::Fire(0, false, false, false, true, false).ID: return 1165; case Fire::Fire(0, false, false, false, false, true).ID: return 1166; case Fire::Fire(0, false, false, false, false, false).ID: return 1167; case Fire::Fire(1, true, true, true, true, true).ID: return 1168; case Fire::Fire(1, true, true, true, true, false).ID: return 1169; case Fire::Fire(1, true, true, true, false, true).ID: return 1170; case Fire::Fire(1, true, true, true, false, false).ID: return 1171; case Fire::Fire(1, true, true, false, true, true).ID: return 1172; case Fire::Fire(1, true, true, false, true, false).ID: return 1173; case Fire::Fire(1, true, true, false, false, true).ID: return 1174; case Fire::Fire(1, true, true, false, false, false).ID: return 1175; case Fire::Fire(1, true, false, true, true, true).ID: return 1176; case Fire::Fire(1, true, false, true, true, false).ID: return 1177; case Fire::Fire(1, true, false, true, false, true).ID: return 1178; case Fire::Fire(1, true, false, true, false, false).ID: return 1179; case Fire::Fire(1, true, false, false, true, true).ID: return 1180; case Fire::Fire(1, true, false, false, true, false).ID: return 1181; case Fire::Fire(1, true, false, false, false, true).ID: return 1182; case Fire::Fire(1, true, false, false, false, false).ID: return 1183; case Fire::Fire(1, false, true, true, true, true).ID: return 1184; case Fire::Fire(1, false, true, true, true, false).ID: return 1185; case Fire::Fire(1, false, true, true, false, true).ID: return 1186; case Fire::Fire(1, false, true, true, false, false).ID: return 1187; case Fire::Fire(1, false, true, false, true, true).ID: return 1188; case Fire::Fire(1, false, true, false, true, false).ID: return 1189; case Fire::Fire(1, false, true, false, false, true).ID: return 1190; case Fire::Fire(1, false, true, false, false, false).ID: return 1191; case Fire::Fire(1, false, false, true, true, true).ID: return 1192; case Fire::Fire(1, false, false, true, true, false).ID: return 1193; case Fire::Fire(1, false, false, true, false, true).ID: return 1194; case Fire::Fire(1, false, false, true, false, false).ID: return 1195; case Fire::Fire(1, false, false, false, true, true).ID: return 1196; case Fire::Fire(1, false, false, false, true, false).ID: return 1197; case Fire::Fire(1, false, false, false, false, true).ID: return 1198; case Fire::Fire(1, false, false, false, false, false).ID: return 1199; case Fire::Fire(2, true, true, true, true, true).ID: return 1200; case Fire::Fire(2, true, true, true, true, false).ID: return 1201; case Fire::Fire(2, true, true, true, false, true).ID: return 1202; case Fire::Fire(2, true, true, true, false, false).ID: return 1203; case Fire::Fire(2, true, true, false, true, true).ID: return 1204; case Fire::Fire(2, true, true, false, true, false).ID: return 1205; case Fire::Fire(2, true, true, false, false, true).ID: return 1206; case Fire::Fire(2, true, true, false, false, false).ID: return 1207; case Fire::Fire(2, true, false, true, true, true).ID: return 1208; case Fire::Fire(2, true, false, true, true, false).ID: return 1209; case Fire::Fire(2, true, false, true, false, true).ID: return 1210; case Fire::Fire(2, true, false, true, false, false).ID: return 1211; case Fire::Fire(2, true, false, false, true, true).ID: return 1212; case Fire::Fire(2, true, false, false, true, false).ID: return 1213; case Fire::Fire(2, true, false, false, false, true).ID: return 1214; case Fire::Fire(2, true, false, false, false, false).ID: return 1215; case Fire::Fire(2, false, true, true, true, true).ID: return 1216; case Fire::Fire(2, false, true, true, true, false).ID: return 1217; case Fire::Fire(2, false, true, true, false, true).ID: return 1218; case Fire::Fire(2, false, true, true, false, false).ID: return 1219; case Fire::Fire(2, false, true, false, true, true).ID: return 1220; case Fire::Fire(2, false, true, false, true, false).ID: return 1221; case Fire::Fire(2, false, true, false, false, true).ID: return 1222; case Fire::Fire(2, false, true, false, false, false).ID: return 1223; case Fire::Fire(2, false, false, true, true, true).ID: return 1224; case Fire::Fire(2, false, false, true, true, false).ID: return 1225; case Fire::Fire(2, false, false, true, false, true).ID: return 1226; case Fire::Fire(2, false, false, true, false, false).ID: return 1227; case Fire::Fire(2, false, false, false, true, true).ID: return 1228; case Fire::Fire(2, false, false, false, true, false).ID: return 1229; case Fire::Fire(2, false, false, false, false, true).ID: return 1230; case Fire::Fire(2, false, false, false, false, false).ID: return 1231; case Fire::Fire(3, true, true, true, true, true).ID: return 1232; case Fire::Fire(3, true, true, true, true, false).ID: return 1233; case Fire::Fire(3, true, true, true, false, true).ID: return 1234; case Fire::Fire(3, true, true, true, false, false).ID: return 1235; case Fire::Fire(3, true, true, false, true, true).ID: return 1236; case Fire::Fire(3, true, true, false, true, false).ID: return 1237; case Fire::Fire(3, true, true, false, false, true).ID: return 1238; case Fire::Fire(3, true, true, false, false, false).ID: return 1239; case Fire::Fire(3, true, false, true, true, true).ID: return 1240; case Fire::Fire(3, true, false, true, true, false).ID: return 1241; case Fire::Fire(3, true, false, true, false, true).ID: return 1242; case Fire::Fire(3, true, false, true, false, false).ID: return 1243; case Fire::Fire(3, true, false, false, true, true).ID: return 1244; case Fire::Fire(3, true, false, false, true, false).ID: return 1245; case Fire::Fire(3, true, false, false, false, true).ID: return 1246; case Fire::Fire(3, true, false, false, false, false).ID: return 1247; case Fire::Fire(3, false, true, true, true, true).ID: return 1248; case Fire::Fire(3, false, true, true, true, false).ID: return 1249; case Fire::Fire(3, false, true, true, false, true).ID: return 1250; case Fire::Fire(3, false, true, true, false, false).ID: return 1251; case Fire::Fire(3, false, true, false, true, true).ID: return 1252; case Fire::Fire(3, false, true, false, true, false).ID: return 1253; case Fire::Fire(3, false, true, false, false, true).ID: return 1254; case Fire::Fire(3, false, true, false, false, false).ID: return 1255; case Fire::Fire(3, false, false, true, true, true).ID: return 1256; case Fire::Fire(3, false, false, true, true, false).ID: return 1257; case Fire::Fire(3, false, false, true, false, true).ID: return 1258; case Fire::Fire(3, false, false, true, false, false).ID: return 1259; case Fire::Fire(3, false, false, false, true, true).ID: return 1260; case Fire::Fire(3, false, false, false, true, false).ID: return 1261; case Fire::Fire(3, false, false, false, false, true).ID: return 1262; case Fire::Fire(3, false, false, false, false, false).ID: return 1263; case Fire::Fire(4, true, true, true, true, true).ID: return 1264; case Fire::Fire(4, true, true, true, true, false).ID: return 1265; case Fire::Fire(4, true, true, true, false, true).ID: return 1266; case Fire::Fire(4, true, true, true, false, false).ID: return 1267; case Fire::Fire(4, true, true, false, true, true).ID: return 1268; case Fire::Fire(4, true, true, false, true, false).ID: return 1269; case Fire::Fire(4, true, true, false, false, true).ID: return 1270; case Fire::Fire(4, true, true, false, false, false).ID: return 1271; case Fire::Fire(4, true, false, true, true, true).ID: return 1272; case Fire::Fire(4, true, false, true, true, false).ID: return 1273; case Fire::Fire(4, true, false, true, false, true).ID: return 1274; case Fire::Fire(4, true, false, true, false, false).ID: return 1275; case Fire::Fire(4, true, false, false, true, true).ID: return 1276; case Fire::Fire(4, true, false, false, true, false).ID: return 1277; case Fire::Fire(4, true, false, false, false, true).ID: return 1278; case Fire::Fire(4, true, false, false, false, false).ID: return 1279; case Fire::Fire(4, false, true, true, true, true).ID: return 1280; case Fire::Fire(4, false, true, true, true, false).ID: return 1281; case Fire::Fire(4, false, true, true, false, true).ID: return 1282; case Fire::Fire(4, false, true, true, false, false).ID: return 1283; case Fire::Fire(4, false, true, false, true, true).ID: return 1284; case Fire::Fire(4, false, true, false, true, false).ID: return 1285; case Fire::Fire(4, false, true, false, false, true).ID: return 1286; case Fire::Fire(4, false, true, false, false, false).ID: return 1287; case Fire::Fire(4, false, false, true, true, true).ID: return 1288; case Fire::Fire(4, false, false, true, true, false).ID: return 1289; case Fire::Fire(4, false, false, true, false, true).ID: return 1290; case Fire::Fire(4, false, false, true, false, false).ID: return 1291; case Fire::Fire(4, false, false, false, true, true).ID: return 1292; case Fire::Fire(4, false, false, false, true, false).ID: return 1293; case Fire::Fire(4, false, false, false, false, true).ID: return 1294; case Fire::Fire(4, false, false, false, false, false).ID: return 1295; case Fire::Fire(5, true, true, true, true, true).ID: return 1296; case Fire::Fire(5, true, true, true, true, false).ID: return 1297; case Fire::Fire(5, true, true, true, false, true).ID: return 1298; case Fire::Fire(5, true, true, true, false, false).ID: return 1299; case Fire::Fire(5, true, true, false, true, true).ID: return 1300; case Fire::Fire(5, true, true, false, true, false).ID: return 1301; case Fire::Fire(5, true, true, false, false, true).ID: return 1302; case Fire::Fire(5, true, true, false, false, false).ID: return 1303; case Fire::Fire(5, true, false, true, true, true).ID: return 1304; case Fire::Fire(5, true, false, true, true, false).ID: return 1305; case Fire::Fire(5, true, false, true, false, true).ID: return 1306; case Fire::Fire(5, true, false, true, false, false).ID: return 1307; case Fire::Fire(5, true, false, false, true, true).ID: return 1308; case Fire::Fire(5, true, false, false, true, false).ID: return 1309; case Fire::Fire(5, true, false, false, false, true).ID: return 1310; case Fire::Fire(5, true, false, false, false, false).ID: return 1311; case Fire::Fire(5, false, true, true, true, true).ID: return 1312; case Fire::Fire(5, false, true, true, true, false).ID: return 1313; case Fire::Fire(5, false, true, true, false, true).ID: return 1314; case Fire::Fire(5, false, true, true, false, false).ID: return 1315; case Fire::Fire(5, false, true, false, true, true).ID: return 1316; case Fire::Fire(5, false, true, false, true, false).ID: return 1317; case Fire::Fire(5, false, true, false, false, true).ID: return 1318; case Fire::Fire(5, false, true, false, false, false).ID: return 1319; case Fire::Fire(5, false, false, true, true, true).ID: return 1320; case Fire::Fire(5, false, false, true, true, false).ID: return 1321; case Fire::Fire(5, false, false, true, false, true).ID: return 1322; case Fire::Fire(5, false, false, true, false, false).ID: return 1323; case Fire::Fire(5, false, false, false, true, true).ID: return 1324; case Fire::Fire(5, false, false, false, true, false).ID: return 1325; case Fire::Fire(5, false, false, false, false, true).ID: return 1326; case Fire::Fire(5, false, false, false, false, false).ID: return 1327; case Fire::Fire(6, true, true, true, true, true).ID: return 1328; case Fire::Fire(6, true, true, true, true, false).ID: return 1329; case Fire::Fire(6, true, true, true, false, true).ID: return 1330; case Fire::Fire(6, true, true, true, false, false).ID: return 1331; case Fire::Fire(6, true, true, false, true, true).ID: return 1332; case Fire::Fire(6, true, true, false, true, false).ID: return 1333; case Fire::Fire(6, true, true, false, false, true).ID: return 1334; case Fire::Fire(6, true, true, false, false, false).ID: return 1335; case Fire::Fire(6, true, false, true, true, true).ID: return 1336; case Fire::Fire(6, true, false, true, true, false).ID: return 1337; case Fire::Fire(6, true, false, true, false, true).ID: return 1338; case Fire::Fire(6, true, false, true, false, false).ID: return 1339; case Fire::Fire(6, true, false, false, true, true).ID: return 1340; case Fire::Fire(6, true, false, false, true, false).ID: return 1341; case Fire::Fire(6, true, false, false, false, true).ID: return 1342; case Fire::Fire(6, true, false, false, false, false).ID: return 1343; case Fire::Fire(6, false, true, true, true, true).ID: return 1344; case Fire::Fire(6, false, true, true, true, false).ID: return 1345; case Fire::Fire(6, false, true, true, false, true).ID: return 1346; case Fire::Fire(6, false, true, true, false, false).ID: return 1347; case Fire::Fire(6, false, true, false, true, true).ID: return 1348; case Fire::Fire(6, false, true, false, true, false).ID: return 1349; case Fire::Fire(6, false, true, false, false, true).ID: return 1350; case Fire::Fire(6, false, true, false, false, false).ID: return 1351; case Fire::Fire(6, false, false, true, true, true).ID: return 1352; case Fire::Fire(6, false, false, true, true, false).ID: return 1353; case Fire::Fire(6, false, false, true, false, true).ID: return 1354; case Fire::Fire(6, false, false, true, false, false).ID: return 1355; case Fire::Fire(6, false, false, false, true, true).ID: return 1356; case Fire::Fire(6, false, false, false, true, false).ID: return 1357; case Fire::Fire(6, false, false, false, false, true).ID: return 1358; case Fire::Fire(6, false, false, false, false, false).ID: return 1359; case Fire::Fire(7, true, true, true, true, true).ID: return 1360; case Fire::Fire(7, true, true, true, true, false).ID: return 1361; case Fire::Fire(7, true, true, true, false, true).ID: return 1362; case Fire::Fire(7, true, true, true, false, false).ID: return 1363; case Fire::Fire(7, true, true, false, true, true).ID: return 1364; case Fire::Fire(7, true, true, false, true, false).ID: return 1365; case Fire::Fire(7, true, true, false, false, true).ID: return 1366; case Fire::Fire(7, true, true, false, false, false).ID: return 1367; case Fire::Fire(7, true, false, true, true, true).ID: return 1368; case Fire::Fire(7, true, false, true, true, false).ID: return 1369; case Fire::Fire(7, true, false, true, false, true).ID: return 1370; case Fire::Fire(7, true, false, true, false, false).ID: return 1371; case Fire::Fire(7, true, false, false, true, true).ID: return 1372; case Fire::Fire(7, true, false, false, true, false).ID: return 1373; case Fire::Fire(7, true, false, false, false, true).ID: return 1374; case Fire::Fire(7, true, false, false, false, false).ID: return 1375; case Fire::Fire(7, false, true, true, true, true).ID: return 1376; case Fire::Fire(7, false, true, true, true, false).ID: return 1377; case Fire::Fire(7, false, true, true, false, true).ID: return 1378; case Fire::Fire(7, false, true, true, false, false).ID: return 1379; case Fire::Fire(7, false, true, false, true, true).ID: return 1380; case Fire::Fire(7, false, true, false, true, false).ID: return 1381; case Fire::Fire(7, false, true, false, false, true).ID: return 1382; case Fire::Fire(7, false, true, false, false, false).ID: return 1383; case Fire::Fire(7, false, false, true, true, true).ID: return 1384; case Fire::Fire(7, false, false, true, true, false).ID: return 1385; case Fire::Fire(7, false, false, true, false, true).ID: return 1386; case Fire::Fire(7, false, false, true, false, false).ID: return 1387; case Fire::Fire(7, false, false, false, true, true).ID: return 1388; case Fire::Fire(7, false, false, false, true, false).ID: return 1389; case Fire::Fire(7, false, false, false, false, true).ID: return 1390; case Fire::Fire(7, false, false, false, false, false).ID: return 1391; case Fire::Fire(8, true, true, true, true, true).ID: return 1392; case Fire::Fire(8, true, true, true, true, false).ID: return 1393; case Fire::Fire(8, true, true, true, false, true).ID: return 1394; case Fire::Fire(8, true, true, true, false, false).ID: return 1395; case Fire::Fire(8, true, true, false, true, true).ID: return 1396; case Fire::Fire(8, true, true, false, true, false).ID: return 1397; case Fire::Fire(8, true, true, false, false, true).ID: return 1398; case Fire::Fire(8, true, true, false, false, false).ID: return 1399; case Fire::Fire(8, true, false, true, true, true).ID: return 1400; case Fire::Fire(8, true, false, true, true, false).ID: return 1401; case Fire::Fire(8, true, false, true, false, true).ID: return 1402; case Fire::Fire(8, true, false, true, false, false).ID: return 1403; case Fire::Fire(8, true, false, false, true, true).ID: return 1404; case Fire::Fire(8, true, false, false, true, false).ID: return 1405; case Fire::Fire(8, true, false, false, false, true).ID: return 1406; case Fire::Fire(8, true, false, false, false, false).ID: return 1407; case Fire::Fire(8, false, true, true, true, true).ID: return 1408; case Fire::Fire(8, false, true, true, true, false).ID: return 1409; case Fire::Fire(8, false, true, true, false, true).ID: return 1410; case Fire::Fire(8, false, true, true, false, false).ID: return 1411; case Fire::Fire(8, false, true, false, true, true).ID: return 1412; case Fire::Fire(8, false, true, false, true, false).ID: return 1413; case Fire::Fire(8, false, true, false, false, true).ID: return 1414; case Fire::Fire(8, false, true, false, false, false).ID: return 1415; case Fire::Fire(8, false, false, true, true, true).ID: return 1416; case Fire::Fire(8, false, false, true, true, false).ID: return 1417; case Fire::Fire(8, false, false, true, false, true).ID: return 1418; case Fire::Fire(8, false, false, true, false, false).ID: return 1419; case Fire::Fire(8, false, false, false, true, true).ID: return 1420; case Fire::Fire(8, false, false, false, true, false).ID: return 1421; case Fire::Fire(8, false, false, false, false, true).ID: return 1422; case Fire::Fire(8, false, false, false, false, false).ID: return 1423; case Fire::Fire(9, true, true, true, true, true).ID: return 1424; case Fire::Fire(9, true, true, true, true, false).ID: return 1425; case Fire::Fire(9, true, true, true, false, true).ID: return 1426; case Fire::Fire(9, true, true, true, false, false).ID: return 1427; case Fire::Fire(9, true, true, false, true, true).ID: return 1428; case Fire::Fire(9, true, true, false, true, false).ID: return 1429; case Fire::Fire(9, true, true, false, false, true).ID: return 1430; case Fire::Fire(9, true, true, false, false, false).ID: return 1431; case Fire::Fire(9, true, false, true, true, true).ID: return 1432; case Fire::Fire(9, true, false, true, true, false).ID: return 1433; case Fire::Fire(9, true, false, true, false, true).ID: return 1434; case Fire::Fire(9, true, false, true, false, false).ID: return 1435; case Fire::Fire(9, true, false, false, true, true).ID: return 1436; case Fire::Fire(9, true, false, false, true, false).ID: return 1437; case Fire::Fire(9, true, false, false, false, true).ID: return 1438; case Fire::Fire(9, true, false, false, false, false).ID: return 1439; case Fire::Fire(9, false, true, true, true, true).ID: return 1440; case Fire::Fire(9, false, true, true, true, false).ID: return 1441; case Fire::Fire(9, false, true, true, false, true).ID: return 1442; case Fire::Fire(9, false, true, true, false, false).ID: return 1443; case Fire::Fire(9, false, true, false, true, true).ID: return 1444; case Fire::Fire(9, false, true, false, true, false).ID: return 1445; case Fire::Fire(9, false, true, false, false, true).ID: return 1446; case Fire::Fire(9, false, true, false, false, false).ID: return 1447; case Fire::Fire(9, false, false, true, true, true).ID: return 1448; case Fire::Fire(9, false, false, true, true, false).ID: return 1449; case Fire::Fire(9, false, false, true, false, true).ID: return 1450; case Fire::Fire(9, false, false, true, false, false).ID: return 1451; case Fire::Fire(9, false, false, false, true, true).ID: return 1452; case Fire::Fire(9, false, false, false, true, false).ID: return 1453; case Fire::Fire(9, false, false, false, false, true).ID: return 1454; case Fire::Fire(9, false, false, false, false, false).ID: return 1455; case Fire::Fire(10, true, true, true, true, true).ID: return 1456; case Fire::Fire(10, true, true, true, true, false).ID: return 1457; case Fire::Fire(10, true, true, true, false, true).ID: return 1458; case Fire::Fire(10, true, true, true, false, false).ID: return 1459; case Fire::Fire(10, true, true, false, true, true).ID: return 1460; case Fire::Fire(10, true, true, false, true, false).ID: return 1461; case Fire::Fire(10, true, true, false, false, true).ID: return 1462; case Fire::Fire(10, true, true, false, false, false).ID: return 1463; case Fire::Fire(10, true, false, true, true, true).ID: return 1464; case Fire::Fire(10, true, false, true, true, false).ID: return 1465; case Fire::Fire(10, true, false, true, false, true).ID: return 1466; case Fire::Fire(10, true, false, true, false, false).ID: return 1467; case Fire::Fire(10, true, false, false, true, true).ID: return 1468; case Fire::Fire(10, true, false, false, true, false).ID: return 1469; case Fire::Fire(10, true, false, false, false, true).ID: return 1470; case Fire::Fire(10, true, false, false, false, false).ID: return 1471; case Fire::Fire(10, false, true, true, true, true).ID: return 1472; case Fire::Fire(10, false, true, true, true, false).ID: return 1473; case Fire::Fire(10, false, true, true, false, true).ID: return 1474; case Fire::Fire(10, false, true, true, false, false).ID: return 1475; case Fire::Fire(10, false, true, false, true, true).ID: return 1476; case Fire::Fire(10, false, true, false, true, false).ID: return 1477; case Fire::Fire(10, false, true, false, false, true).ID: return 1478; case Fire::Fire(10, false, true, false, false, false).ID: return 1479; case Fire::Fire(10, false, false, true, true, true).ID: return 1480; case Fire::Fire(10, false, false, true, true, false).ID: return 1481; case Fire::Fire(10, false, false, true, false, true).ID: return 1482; case Fire::Fire(10, false, false, true, false, false).ID: return 1483; case Fire::Fire(10, false, false, false, true, true).ID: return 1484; case Fire::Fire(10, false, false, false, true, false).ID: return 1485; case Fire::Fire(10, false, false, false, false, true).ID: return 1486; case Fire::Fire(10, false, false, false, false, false).ID: return 1487; case Fire::Fire(11, true, true, true, true, true).ID: return 1488; case Fire::Fire(11, true, true, true, true, false).ID: return 1489; case Fire::Fire(11, true, true, true, false, true).ID: return 1490; case Fire::Fire(11, true, true, true, false, false).ID: return 1491; case Fire::Fire(11, true, true, false, true, true).ID: return 1492; case Fire::Fire(11, true, true, false, true, false).ID: return 1493; case Fire::Fire(11, true, true, false, false, true).ID: return 1494; case Fire::Fire(11, true, true, false, false, false).ID: return 1495; case Fire::Fire(11, true, false, true, true, true).ID: return 1496; case Fire::Fire(11, true, false, true, true, false).ID: return 1497; case Fire::Fire(11, true, false, true, false, true).ID: return 1498; case Fire::Fire(11, true, false, true, false, false).ID: return 1499; case Fire::Fire(11, true, false, false, true, true).ID: return 1500; case Fire::Fire(11, true, false, false, true, false).ID: return 1501; case Fire::Fire(11, true, false, false, false, true).ID: return 1502; case Fire::Fire(11, true, false, false, false, false).ID: return 1503; case Fire::Fire(11, false, true, true, true, true).ID: return 1504; case Fire::Fire(11, false, true, true, true, false).ID: return 1505; case Fire::Fire(11, false, true, true, false, true).ID: return 1506; case Fire::Fire(11, false, true, true, false, false).ID: return 1507; case Fire::Fire(11, false, true, false, true, true).ID: return 1508; case Fire::Fire(11, false, true, false, true, false).ID: return 1509; case Fire::Fire(11, false, true, false, false, true).ID: return 1510; case Fire::Fire(11, false, true, false, false, false).ID: return 1511; case Fire::Fire(11, false, false, true, true, true).ID: return 1512; case Fire::Fire(11, false, false, true, true, false).ID: return 1513; case Fire::Fire(11, false, false, true, false, true).ID: return 1514; case Fire::Fire(11, false, false, true, false, false).ID: return 1515; case Fire::Fire(11, false, false, false, true, true).ID: return 1516; case Fire::Fire(11, false, false, false, true, false).ID: return 1517; case Fire::Fire(11, false, false, false, false, true).ID: return 1518; case Fire::Fire(11, false, false, false, false, false).ID: return 1519; case Fire::Fire(12, true, true, true, true, true).ID: return 1520; case Fire::Fire(12, true, true, true, true, false).ID: return 1521; case Fire::Fire(12, true, true, true, false, true).ID: return 1522; case Fire::Fire(12, true, true, true, false, false).ID: return 1523; case Fire::Fire(12, true, true, false, true, true).ID: return 1524; case Fire::Fire(12, true, true, false, true, false).ID: return 1525; case Fire::Fire(12, true, true, false, false, true).ID: return 1526; case Fire::Fire(12, true, true, false, false, false).ID: return 1527; case Fire::Fire(12, true, false, true, true, true).ID: return 1528; case Fire::Fire(12, true, false, true, true, false).ID: return 1529; case Fire::Fire(12, true, false, true, false, true).ID: return 1530; case Fire::Fire(12, true, false, true, false, false).ID: return 1531; case Fire::Fire(12, true, false, false, true, true).ID: return 1532; case Fire::Fire(12, true, false, false, true, false).ID: return 1533; case Fire::Fire(12, true, false, false, false, true).ID: return 1534; case Fire::Fire(12, true, false, false, false, false).ID: return 1535; case Fire::Fire(12, false, true, true, true, true).ID: return 1536; case Fire::Fire(12, false, true, true, true, false).ID: return 1537; case Fire::Fire(12, false, true, true, false, true).ID: return 1538; case Fire::Fire(12, false, true, true, false, false).ID: return 1539; case Fire::Fire(12, false, true, false, true, true).ID: return 1540; case Fire::Fire(12, false, true, false, true, false).ID: return 1541; case Fire::Fire(12, false, true, false, false, true).ID: return 1542; case Fire::Fire(12, false, true, false, false, false).ID: return 1543; case Fire::Fire(12, false, false, true, true, true).ID: return 1544; case Fire::Fire(12, false, false, true, true, false).ID: return 1545; case Fire::Fire(12, false, false, true, false, true).ID: return 1546; case Fire::Fire(12, false, false, true, false, false).ID: return 1547; case Fire::Fire(12, false, false, false, true, true).ID: return 1548; case Fire::Fire(12, false, false, false, true, false).ID: return 1549; case Fire::Fire(12, false, false, false, false, true).ID: return 1550; case Fire::Fire(12, false, false, false, false, false).ID: return 1551; case Fire::Fire(13, true, true, true, true, true).ID: return 1552; case Fire::Fire(13, true, true, true, true, false).ID: return 1553; case Fire::Fire(13, true, true, true, false, true).ID: return 1554; case Fire::Fire(13, true, true, true, false, false).ID: return 1555; case Fire::Fire(13, true, true, false, true, true).ID: return 1556; case Fire::Fire(13, true, true, false, true, false).ID: return 1557; case Fire::Fire(13, true, true, false, false, true).ID: return 1558; case Fire::Fire(13, true, true, false, false, false).ID: return 1559; case Fire::Fire(13, true, false, true, true, true).ID: return 1560; case Fire::Fire(13, true, false, true, true, false).ID: return 1561; case Fire::Fire(13, true, false, true, false, true).ID: return 1562; case Fire::Fire(13, true, false, true, false, false).ID: return 1563; case Fire::Fire(13, true, false, false, true, true).ID: return 1564; case Fire::Fire(13, true, false, false, true, false).ID: return 1565; case Fire::Fire(13, true, false, false, false, true).ID: return 1566; case Fire::Fire(13, true, false, false, false, false).ID: return 1567; case Fire::Fire(13, false, true, true, true, true).ID: return 1568; case Fire::Fire(13, false, true, true, true, false).ID: return 1569; case Fire::Fire(13, false, true, true, false, true).ID: return 1570; case Fire::Fire(13, false, true, true, false, false).ID: return 1571; case Fire::Fire(13, false, true, false, true, true).ID: return 1572; case Fire::Fire(13, false, true, false, true, false).ID: return 1573; case Fire::Fire(13, false, true, false, false, true).ID: return 1574; case Fire::Fire(13, false, true, false, false, false).ID: return 1575; case Fire::Fire(13, false, false, true, true, true).ID: return 1576; case Fire::Fire(13, false, false, true, true, false).ID: return 1577; case Fire::Fire(13, false, false, true, false, true).ID: return 1578; case Fire::Fire(13, false, false, true, false, false).ID: return 1579; case Fire::Fire(13, false, false, false, true, true).ID: return 1580; case Fire::Fire(13, false, false, false, true, false).ID: return 1581; case Fire::Fire(13, false, false, false, false, true).ID: return 1582; case Fire::Fire(13, false, false, false, false, false).ID: return 1583; case Fire::Fire(14, true, true, true, true, true).ID: return 1584; case Fire::Fire(14, true, true, true, true, false).ID: return 1585; case Fire::Fire(14, true, true, true, false, true).ID: return 1586; case Fire::Fire(14, true, true, true, false, false).ID: return 1587; case Fire::Fire(14, true, true, false, true, true).ID: return 1588; case Fire::Fire(14, true, true, false, true, false).ID: return 1589; case Fire::Fire(14, true, true, false, false, true).ID: return 1590; case Fire::Fire(14, true, true, false, false, false).ID: return 1591; case Fire::Fire(14, true, false, true, true, true).ID: return 1592; case Fire::Fire(14, true, false, true, true, false).ID: return 1593; case Fire::Fire(14, true, false, true, false, true).ID: return 1594; case Fire::Fire(14, true, false, true, false, false).ID: return 1595; case Fire::Fire(14, true, false, false, true, true).ID: return 1596; case Fire::Fire(14, true, false, false, true, false).ID: return 1597; case Fire::Fire(14, true, false, false, false, true).ID: return 1598; case Fire::Fire(14, true, false, false, false, false).ID: return 1599; case Fire::Fire(14, false, true, true, true, true).ID: return 1600; case Fire::Fire(14, false, true, true, true, false).ID: return 1601; case Fire::Fire(14, false, true, true, false, true).ID: return 1602; case Fire::Fire(14, false, true, true, false, false).ID: return 1603; case Fire::Fire(14, false, true, false, true, true).ID: return 1604; case Fire::Fire(14, false, true, false, true, false).ID: return 1605; case Fire::Fire(14, false, true, false, false, true).ID: return 1606; case Fire::Fire(14, false, true, false, false, false).ID: return 1607; case Fire::Fire(14, false, false, true, true, true).ID: return 1608; case Fire::Fire(14, false, false, true, true, false).ID: return 1609; case Fire::Fire(14, false, false, true, false, true).ID: return 1610; case Fire::Fire(14, false, false, true, false, false).ID: return 1611; case Fire::Fire(14, false, false, false, true, true).ID: return 1612; case Fire::Fire(14, false, false, false, true, false).ID: return 1613; case Fire::Fire(14, false, false, false, false, true).ID: return 1614; case Fire::Fire(14, false, false, false, false, false).ID: return 1615; case Fire::Fire(15, true, true, true, true, true).ID: return 1616; case Fire::Fire(15, true, true, true, true, false).ID: return 1617; case Fire::Fire(15, true, true, true, false, true).ID: return 1618; case Fire::Fire(15, true, true, true, false, false).ID: return 1619; case Fire::Fire(15, true, true, false, true, true).ID: return 1620; case Fire::Fire(15, true, true, false, true, false).ID: return 1621; case Fire::Fire(15, true, true, false, false, true).ID: return 1622; case Fire::Fire(15, true, true, false, false, false).ID: return 1623; case Fire::Fire(15, true, false, true, true, true).ID: return 1624; case Fire::Fire(15, true, false, true, true, false).ID: return 1625; case Fire::Fire(15, true, false, true, false, true).ID: return 1626; case Fire::Fire(15, true, false, true, false, false).ID: return 1627; case Fire::Fire(15, true, false, false, true, true).ID: return 1628; case Fire::Fire(15, true, false, false, true, false).ID: return 1629; case Fire::Fire(15, true, false, false, false, true).ID: return 1630; case Fire::Fire(15, true, false, false, false, false).ID: return 1631; case Fire::Fire(15, false, true, true, true, true).ID: return 1632; case Fire::Fire(15, false, true, true, true, false).ID: return 1633; case Fire::Fire(15, false, true, true, false, true).ID: return 1634; case Fire::Fire(15, false, true, true, false, false).ID: return 1635; case Fire::Fire(15, false, true, false, true, true).ID: return 1636; case Fire::Fire(15, false, true, false, true, false).ID: return 1637; case Fire::Fire(15, false, true, false, false, true).ID: return 1638; case Fire::Fire(15, false, true, false, false, false).ID: return 1639; case Fire::Fire(15, false, false, true, true, true).ID: return 1640; case Fire::Fire(15, false, false, true, true, false).ID: return 1641; case Fire::Fire(15, false, false, true, false, true).ID: return 1642; case Fire::Fire(15, false, false, true, false, false).ID: return 1643; case Fire::Fire(15, false, false, false, true, true).ID: return 1644; case Fire::Fire(15, false, false, false, true, false).ID: return 1645; case Fire::Fire(15, false, false, false, false, true).ID: return 1646; case Fire::Fire(15, false, false, false, false, false).ID: return 1647; case FireCoral::FireCoral().ID: return 8477; case FireCoralBlock::FireCoralBlock().ID: return 8458; case FireCoralFan::FireCoralFan().ID: return 8577; case FireCoralWallFan::FireCoralWallFan(eBlockFace::BLOCK_FACE_ZM).ID: return 8545; case FireCoralWallFan::FireCoralWallFan(eBlockFace::BLOCK_FACE_ZP).ID: return 8547; case FireCoralWallFan::FireCoralWallFan(eBlockFace::BLOCK_FACE_XM).ID: return 8549; case FireCoralWallFan::FireCoralWallFan(eBlockFace::BLOCK_FACE_XP).ID: return 8551; case FlowerPot::FlowerPot().ID: return 5266; case FrostedIce::FrostedIce(0).ID: return 8189; case FrostedIce::FrostedIce(1).ID: return 8190; case FrostedIce::FrostedIce(2).ID: return 8191; case FrostedIce::FrostedIce(3).ID: return 8192; case Furnace::Furnace(eBlockFace::BLOCK_FACE_ZM, true).ID: return 3068; case Furnace::Furnace(eBlockFace::BLOCK_FACE_ZM, false).ID: return 3069; case Furnace::Furnace(eBlockFace::BLOCK_FACE_ZP, true).ID: return 3070; case Furnace::Furnace(eBlockFace::BLOCK_FACE_ZP, false).ID: return 3071; case Furnace::Furnace(eBlockFace::BLOCK_FACE_XM, true).ID: return 3072; case Furnace::Furnace(eBlockFace::BLOCK_FACE_XM, false).ID: return 3073; case Furnace::Furnace(eBlockFace::BLOCK_FACE_XP, true).ID: return 3074; case Furnace::Furnace(eBlockFace::BLOCK_FACE_XP, false).ID: return 3075; case Glass::Glass().ID: return 230; case GlassPane::GlassPane(true, true, true, true).ID: return 4214; case GlassPane::GlassPane(true, true, true, false).ID: return 4215; case GlassPane::GlassPane(true, true, false, true).ID: return 4218; case GlassPane::GlassPane(true, true, false, false).ID: return 4219; case GlassPane::GlassPane(true, false, true, true).ID: return 4222; case GlassPane::GlassPane(true, false, true, false).ID: return 4223; case GlassPane::GlassPane(true, false, false, true).ID: return 4226; case GlassPane::GlassPane(true, false, false, false).ID: return 4227; case GlassPane::GlassPane(false, true, true, true).ID: return 4230; case GlassPane::GlassPane(false, true, true, false).ID: return 4231; case GlassPane::GlassPane(false, true, false, true).ID: return 4234; case GlassPane::GlassPane(false, true, false, false).ID: return 4235; case GlassPane::GlassPane(false, false, true, true).ID: return 4238; case GlassPane::GlassPane(false, false, true, false).ID: return 4239; case GlassPane::GlassPane(false, false, false, true).ID: return 4242; case GlassPane::GlassPane(false, false, false, false).ID: return 4243; case Glowstone::Glowstone().ID: return 3496; case GoldBlock::GoldBlock().ID: return 1123; case GoldOre::GoldOre().ID: return 69; case Granite::Granite().ID: return 2; case Grass::Grass().ID: return 1041; case GrassBlock::GrassBlock(true).ID: return 8; case GrassBlock::GrassBlock(false).ID: return 9; case GrassPath::GrassPath().ID: return 8163; case Gravel::Gravel().ID: return 68; case GrayBanner::GrayBanner(0).ID: return 6967; case GrayBanner::GrayBanner(1).ID: return 6968; case GrayBanner::GrayBanner(2).ID: return 6969; case GrayBanner::GrayBanner(3).ID: return 6970; case GrayBanner::GrayBanner(4).ID: return 6971; case GrayBanner::GrayBanner(5).ID: return 6972; case GrayBanner::GrayBanner(6).ID: return 6973; case GrayBanner::GrayBanner(7).ID: return 6974; case GrayBanner::GrayBanner(8).ID: return 6975; case GrayBanner::GrayBanner(9).ID: return 6976; case GrayBanner::GrayBanner(10).ID: return 6977; case GrayBanner::GrayBanner(11).ID: return 6978; case GrayBanner::GrayBanner(12).ID: return 6979; case GrayBanner::GrayBanner(13).ID: return 6980; case GrayBanner::GrayBanner(14).ID: return 6981; case GrayBanner::GrayBanner(15).ID: return 6982; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_ZM, true, GrayBed::Part::Head).ID: return 860; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_ZM, true, GrayBed::Part::Foot).ID: return 861; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_ZM, false, GrayBed::Part::Head).ID: return 862; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_ZM, false, GrayBed::Part::Foot).ID: return 863; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_ZP, true, GrayBed::Part::Head).ID: return 864; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_ZP, true, GrayBed::Part::Foot).ID: return 865; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_ZP, false, GrayBed::Part::Head).ID: return 866; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_ZP, false, GrayBed::Part::Foot).ID: return 867; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_XM, true, GrayBed::Part::Head).ID: return 868; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_XM, true, GrayBed::Part::Foot).ID: return 869; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_XM, false, GrayBed::Part::Head).ID: return 870; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_XM, false, GrayBed::Part::Foot).ID: return 871; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_XP, true, GrayBed::Part::Head).ID: return 872; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_XP, true, GrayBed::Part::Foot).ID: return 873; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_XP, false, GrayBed::Part::Head).ID: return 874; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_XP, false, GrayBed::Part::Foot).ID: return 875; case GrayCarpet::GrayCarpet().ID: return 6831; case GrayConcrete::GrayConcrete().ID: return 8385; case GrayConcretePowder::GrayConcretePowder().ID: return 8401; case GrayGlazedTerracotta::GrayGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 8342; case GrayGlazedTerracotta::GrayGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 8343; case GrayGlazedTerracotta::GrayGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 8344; case GrayGlazedTerracotta::GrayGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 8345; case GrayShulkerBox::GrayShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 8260; case GrayShulkerBox::GrayShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 8261; case GrayShulkerBox::GrayShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 8262; case GrayShulkerBox::GrayShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 8263; case GrayShulkerBox::GrayShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 8264; case GrayShulkerBox::GrayShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 8265; case GrayStainedGlass::GrayStainedGlass().ID: return 3585; case GrayStainedGlassPane::GrayStainedGlassPane(true, true, true, true).ID: return 6047; case GrayStainedGlassPane::GrayStainedGlassPane(true, true, true, false).ID: return 6048; case GrayStainedGlassPane::GrayStainedGlassPane(true, true, false, true).ID: return 6051; case GrayStainedGlassPane::GrayStainedGlassPane(true, true, false, false).ID: return 6052; case GrayStainedGlassPane::GrayStainedGlassPane(true, false, true, true).ID: return 6055; case GrayStainedGlassPane::GrayStainedGlassPane(true, false, true, false).ID: return 6056; case GrayStainedGlassPane::GrayStainedGlassPane(true, false, false, true).ID: return 6059; case GrayStainedGlassPane::GrayStainedGlassPane(true, false, false, false).ID: return 6060; case GrayStainedGlassPane::GrayStainedGlassPane(false, true, true, true).ID: return 6063; case GrayStainedGlassPane::GrayStainedGlassPane(false, true, true, false).ID: return 6064; case GrayStainedGlassPane::GrayStainedGlassPane(false, true, false, true).ID: return 6067; case GrayStainedGlassPane::GrayStainedGlassPane(false, true, false, false).ID: return 6068; case GrayStainedGlassPane::GrayStainedGlassPane(false, false, true, true).ID: return 6071; case GrayStainedGlassPane::GrayStainedGlassPane(false, false, true, false).ID: return 6072; case GrayStainedGlassPane::GrayStainedGlassPane(false, false, false, true).ID: return 6075; case GrayStainedGlassPane::GrayStainedGlassPane(false, false, false, false).ID: return 6076; case GrayTerracotta::GrayTerracotta().ID: return 5812; case GrayWallBanner::GrayWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 7139; case GrayWallBanner::GrayWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 7140; case GrayWallBanner::GrayWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 7141; case GrayWallBanner::GrayWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 7142; case GrayWool::GrayWool().ID: return 1090; case GreenBanner::GreenBanner(0).ID: return 7063; case GreenBanner::GreenBanner(1).ID: return 7064; case GreenBanner::GreenBanner(2).ID: return 7065; case GreenBanner::GreenBanner(3).ID: return 7066; case GreenBanner::GreenBanner(4).ID: return 7067; case GreenBanner::GreenBanner(5).ID: return 7068; case GreenBanner::GreenBanner(6).ID: return 7069; case GreenBanner::GreenBanner(7).ID: return 7070; case GreenBanner::GreenBanner(8).ID: return 7071; case GreenBanner::GreenBanner(9).ID: return 7072; case GreenBanner::GreenBanner(10).ID: return 7073; case GreenBanner::GreenBanner(11).ID: return 7074; case GreenBanner::GreenBanner(12).ID: return 7075; case GreenBanner::GreenBanner(13).ID: return 7076; case GreenBanner::GreenBanner(14).ID: return 7077; case GreenBanner::GreenBanner(15).ID: return 7078; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_ZM, true, GreenBed::Part::Head).ID: return 956; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_ZM, true, GreenBed::Part::Foot).ID: return 957; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_ZM, false, GreenBed::Part::Head).ID: return 958; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_ZM, false, GreenBed::Part::Foot).ID: return 959; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_ZP, true, GreenBed::Part::Head).ID: return 960; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_ZP, true, GreenBed::Part::Foot).ID: return 961; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_ZP, false, GreenBed::Part::Head).ID: return 962; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_ZP, false, GreenBed::Part::Foot).ID: return 963; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_XM, true, GreenBed::Part::Head).ID: return 964; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_XM, true, GreenBed::Part::Foot).ID: return 965; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_XM, false, GreenBed::Part::Head).ID: return 966; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_XM, false, GreenBed::Part::Foot).ID: return 967; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_XP, true, GreenBed::Part::Head).ID: return 968; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_XP, true, GreenBed::Part::Foot).ID: return 969; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_XP, false, GreenBed::Part::Head).ID: return 970; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_XP, false, GreenBed::Part::Foot).ID: return 971; case GreenCarpet::GreenCarpet().ID: return 6837; case GreenConcrete::GreenConcrete().ID: return 8391; case GreenConcretePowder::GreenConcretePowder().ID: return 8407; case GreenGlazedTerracotta::GreenGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 8366; case GreenGlazedTerracotta::GreenGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 8367; case GreenGlazedTerracotta::GreenGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 8368; case GreenGlazedTerracotta::GreenGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 8369; case GreenShulkerBox::GreenShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 8296; case GreenShulkerBox::GreenShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 8297; case GreenShulkerBox::GreenShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 8298; case GreenShulkerBox::GreenShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 8299; case GreenShulkerBox::GreenShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 8300; case GreenShulkerBox::GreenShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 8301; case GreenStainedGlass::GreenStainedGlass().ID: return 3591; case GreenStainedGlassPane::GreenStainedGlassPane(true, true, true, true).ID: return 6239; case GreenStainedGlassPane::GreenStainedGlassPane(true, true, true, false).ID: return 6240; case GreenStainedGlassPane::GreenStainedGlassPane(true, true, false, true).ID: return 6243; case GreenStainedGlassPane::GreenStainedGlassPane(true, true, false, false).ID: return 6244; case GreenStainedGlassPane::GreenStainedGlassPane(true, false, true, true).ID: return 6247; case GreenStainedGlassPane::GreenStainedGlassPane(true, false, true, false).ID: return 6248; case GreenStainedGlassPane::GreenStainedGlassPane(true, false, false, true).ID: return 6251; case GreenStainedGlassPane::GreenStainedGlassPane(true, false, false, false).ID: return 6252; case GreenStainedGlassPane::GreenStainedGlassPane(false, true, true, true).ID: return 6255; case GreenStainedGlassPane::GreenStainedGlassPane(false, true, true, false).ID: return 6256; case GreenStainedGlassPane::GreenStainedGlassPane(false, true, false, true).ID: return 6259; case GreenStainedGlassPane::GreenStainedGlassPane(false, true, false, false).ID: return 6260; case GreenStainedGlassPane::GreenStainedGlassPane(false, false, true, true).ID: return 6263; case GreenStainedGlassPane::GreenStainedGlassPane(false, false, true, false).ID: return 6264; case GreenStainedGlassPane::GreenStainedGlassPane(false, false, false, true).ID: return 6267; case GreenStainedGlassPane::GreenStainedGlassPane(false, false, false, false).ID: return 6268; case GreenTerracotta::GreenTerracotta().ID: return 5818; case GreenWallBanner::GreenWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 7163; case GreenWallBanner::GreenWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 7164; case GreenWallBanner::GreenWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 7165; case GreenWallBanner::GreenWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 7166; case GreenWool::GreenWool().ID: return 1096; case HayBale::HayBale(HayBale::Axis::X).ID: return 6821; case HayBale::HayBale(HayBale::Axis::Y).ID: return 6822; case HayBale::HayBale(HayBale::Axis::Z).ID: return 6823; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(0).ID: return 5620; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(1).ID: return 5621; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(2).ID: return 5622; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(3).ID: return 5623; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(4).ID: return 5624; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(5).ID: return 5625; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(6).ID: return 5626; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(7).ID: return 5627; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(8).ID: return 5628; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(9).ID: return 5629; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(10).ID: return 5630; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(11).ID: return 5631; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(12).ID: return 5632; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(13).ID: return 5633; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(14).ID: return 5634; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(15).ID: return 5635; case Hopper::Hopper(true, eBlockFace::BLOCK_FACE_YM).ID: return 5686; case Hopper::Hopper(true, eBlockFace::BLOCK_FACE_ZM).ID: return 5687; case Hopper::Hopper(true, eBlockFace::BLOCK_FACE_ZP).ID: return 5688; case Hopper::Hopper(true, eBlockFace::BLOCK_FACE_XM).ID: return 5689; case Hopper::Hopper(true, eBlockFace::BLOCK_FACE_XP).ID: return 5690; case Hopper::Hopper(false, eBlockFace::BLOCK_FACE_YM).ID: return 5691; case Hopper::Hopper(false, eBlockFace::BLOCK_FACE_ZM).ID: return 5692; case Hopper::Hopper(false, eBlockFace::BLOCK_FACE_ZP).ID: return 5693; case Hopper::Hopper(false, eBlockFace::BLOCK_FACE_XM).ID: return 5694; case Hopper::Hopper(false, eBlockFace::BLOCK_FACE_XP).ID: return 5695; case HornCoral::HornCoral().ID: return 8479; case HornCoralBlock::HornCoralBlock().ID: return 8459; case HornCoralFan::HornCoralFan().ID: return 8579; case HornCoralWallFan::HornCoralWallFan(eBlockFace::BLOCK_FACE_ZM).ID: return 8553; case HornCoralWallFan::HornCoralWallFan(eBlockFace::BLOCK_FACE_ZP).ID: return 8555; case HornCoralWallFan::HornCoralWallFan(eBlockFace::BLOCK_FACE_XM).ID: return 8557; case HornCoralWallFan::HornCoralWallFan(eBlockFace::BLOCK_FACE_XP).ID: return 8559; case Ice::Ice().ID: return 3424; case InfestedChiseledStoneBricks::InfestedChiseledStoneBricks().ID: return 3983; case InfestedCobblestone::InfestedCobblestone().ID: return 3979; case InfestedCrackedStoneBricks::InfestedCrackedStoneBricks().ID: return 3982; case InfestedMossyStoneBricks::InfestedMossyStoneBricks().ID: return 3981; case InfestedStone::InfestedStone().ID: return 3978; case InfestedStoneBricks::InfestedStoneBricks().ID: return 3980; case IronBars::IronBars(true, true, true, true).ID: return 4182; case IronBars::IronBars(true, true, true, false).ID: return 4183; case IronBars::IronBars(true, true, false, true).ID: return 4186; case IronBars::IronBars(true, true, false, false).ID: return 4187; case IronBars::IronBars(true, false, true, true).ID: return 4190; case IronBars::IronBars(true, false, true, false).ID: return 4191; case IronBars::IronBars(true, false, false, true).ID: return 4194; case IronBars::IronBars(true, false, false, false).ID: return 4195; case IronBars::IronBars(false, true, true, true).ID: return 4198; case IronBars::IronBars(false, true, true, false).ID: return 4199; case IronBars::IronBars(false, true, false, true).ID: return 4202; case IronBars::IronBars(false, true, false, false).ID: return 4203; case IronBars::IronBars(false, false, true, true).ID: return 4206; case IronBars::IronBars(false, false, true, false).ID: return 4207; case IronBars::IronBars(false, false, false, true).ID: return 4210; case IronBars::IronBars(false, false, false, false).ID: return 4211; case IronBlock::IronBlock().ID: return 1124; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Upper, IronDoor::Hinge::Left, true, true).ID: return 3304; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Upper, IronDoor::Hinge::Left, true, false).ID: return 3305; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Upper, IronDoor::Hinge::Left, false, true).ID: return 3306; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Upper, IronDoor::Hinge::Left, false, false).ID: return 3307; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Upper, IronDoor::Hinge::Right, true, true).ID: return 3308; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Upper, IronDoor::Hinge::Right, true, false).ID: return 3309; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Upper, IronDoor::Hinge::Right, false, true).ID: return 3310; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Upper, IronDoor::Hinge::Right, false, false).ID: return 3311; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Lower, IronDoor::Hinge::Left, true, true).ID: return 3312; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Lower, IronDoor::Hinge::Left, true, false).ID: return 3313; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Lower, IronDoor::Hinge::Left, false, true).ID: return 3314; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Lower, IronDoor::Hinge::Left, false, false).ID: return 3315; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Lower, IronDoor::Hinge::Right, true, true).ID: return 3316; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Lower, IronDoor::Hinge::Right, true, false).ID: return 3317; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Lower, IronDoor::Hinge::Right, false, true).ID: return 3318; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Lower, IronDoor::Hinge::Right, false, false).ID: return 3319; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Upper, IronDoor::Hinge::Left, true, true).ID: return 3320; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Upper, IronDoor::Hinge::Left, true, false).ID: return 3321; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Upper, IronDoor::Hinge::Left, false, true).ID: return 3322; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Upper, IronDoor::Hinge::Left, false, false).ID: return 3323; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Upper, IronDoor::Hinge::Right, true, true).ID: return 3324; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Upper, IronDoor::Hinge::Right, true, false).ID: return 3325; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Upper, IronDoor::Hinge::Right, false, true).ID: return 3326; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Upper, IronDoor::Hinge::Right, false, false).ID: return 3327; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Lower, IronDoor::Hinge::Left, true, true).ID: return 3328; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Lower, IronDoor::Hinge::Left, true, false).ID: return 3329; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Lower, IronDoor::Hinge::Left, false, true).ID: return 3330; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Lower, IronDoor::Hinge::Left, false, false).ID: return 3331; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Lower, IronDoor::Hinge::Right, true, true).ID: return 3332; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Lower, IronDoor::Hinge::Right, true, false).ID: return 3333; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Lower, IronDoor::Hinge::Right, false, true).ID: return 3334; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Lower, IronDoor::Hinge::Right, false, false).ID: return 3335; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Upper, IronDoor::Hinge::Left, true, true).ID: return 3336; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Upper, IronDoor::Hinge::Left, true, false).ID: return 3337; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Upper, IronDoor::Hinge::Left, false, true).ID: return 3338; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Upper, IronDoor::Hinge::Left, false, false).ID: return 3339; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Upper, IronDoor::Hinge::Right, true, true).ID: return 3340; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Upper, IronDoor::Hinge::Right, true, false).ID: return 3341; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Upper, IronDoor::Hinge::Right, false, true).ID: return 3342; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Upper, IronDoor::Hinge::Right, false, false).ID: return 3343; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Lower, IronDoor::Hinge::Left, true, true).ID: return 3344; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Lower, IronDoor::Hinge::Left, true, false).ID: return 3345; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Lower, IronDoor::Hinge::Left, false, true).ID: return 3346; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Lower, IronDoor::Hinge::Left, false, false).ID: return 3347; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Lower, IronDoor::Hinge::Right, true, true).ID: return 3348; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Lower, IronDoor::Hinge::Right, true, false).ID: return 3349; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Lower, IronDoor::Hinge::Right, false, true).ID: return 3350; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Lower, IronDoor::Hinge::Right, false, false).ID: return 3351; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Upper, IronDoor::Hinge::Left, true, true).ID: return 3352; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Upper, IronDoor::Hinge::Left, true, false).ID: return 3353; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Upper, IronDoor::Hinge::Left, false, true).ID: return 3354; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Upper, IronDoor::Hinge::Left, false, false).ID: return 3355; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Upper, IronDoor::Hinge::Right, true, true).ID: return 3356; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Upper, IronDoor::Hinge::Right, true, false).ID: return 3357; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Upper, IronDoor::Hinge::Right, false, true).ID: return 3358; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Upper, IronDoor::Hinge::Right, false, false).ID: return 3359; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Lower, IronDoor::Hinge::Left, true, true).ID: return 3360; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Lower, IronDoor::Hinge::Left, true, false).ID: return 3361; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Lower, IronDoor::Hinge::Left, false, true).ID: return 3362; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Lower, IronDoor::Hinge::Left, false, false).ID: return 3363; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Lower, IronDoor::Hinge::Right, true, true).ID: return 3364; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Lower, IronDoor::Hinge::Right, true, false).ID: return 3365; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Lower, IronDoor::Hinge::Right, false, true).ID: return 3366; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Lower, IronDoor::Hinge::Right, false, false).ID: return 3367; case IronOre::IronOre().ID: return 70; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZM, IronTrapdoor::Half::Top, true, true).ID: return 6496; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZM, IronTrapdoor::Half::Top, true, false).ID: return 6498; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZM, IronTrapdoor::Half::Top, false, true).ID: return 6500; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZM, IronTrapdoor::Half::Top, false, false).ID: return 6502; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZM, IronTrapdoor::Half::Bottom, true, true).ID: return 6504; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZM, IronTrapdoor::Half::Bottom, true, false).ID: return 6506; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZM, IronTrapdoor::Half::Bottom, false, true).ID: return 6508; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZM, IronTrapdoor::Half::Bottom, false, false).ID: return 6510; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZP, IronTrapdoor::Half::Top, true, true).ID: return 6512; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZP, IronTrapdoor::Half::Top, true, false).ID: return 6514; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZP, IronTrapdoor::Half::Top, false, true).ID: return 6516; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZP, IronTrapdoor::Half::Top, false, false).ID: return 6518; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZP, IronTrapdoor::Half::Bottom, true, true).ID: return 6520; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZP, IronTrapdoor::Half::Bottom, true, false).ID: return 6522; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZP, IronTrapdoor::Half::Bottom, false, true).ID: return 6524; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZP, IronTrapdoor::Half::Bottom, false, false).ID: return 6526; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XM, IronTrapdoor::Half::Top, true, true).ID: return 6528; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XM, IronTrapdoor::Half::Top, true, false).ID: return 6530; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XM, IronTrapdoor::Half::Top, false, true).ID: return 6532; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XM, IronTrapdoor::Half::Top, false, false).ID: return 6534; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XM, IronTrapdoor::Half::Bottom, true, true).ID: return 6536; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XM, IronTrapdoor::Half::Bottom, true, false).ID: return 6538; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XM, IronTrapdoor::Half::Bottom, false, true).ID: return 6540; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XM, IronTrapdoor::Half::Bottom, false, false).ID: return 6542; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XP, IronTrapdoor::Half::Top, true, true).ID: return 6544; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XP, IronTrapdoor::Half::Top, true, false).ID: return 6546; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XP, IronTrapdoor::Half::Top, false, true).ID: return 6548; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XP, IronTrapdoor::Half::Top, false, false).ID: return 6550; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XP, IronTrapdoor::Half::Bottom, true, true).ID: return 6552; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XP, IronTrapdoor::Half::Bottom, true, false).ID: return 6554; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XP, IronTrapdoor::Half::Bottom, false, true).ID: return 6556; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XP, IronTrapdoor::Half::Bottom, false, false).ID: return 6558; case JackOLantern::JackOLantern(eBlockFace::BLOCK_FACE_ZM).ID: return 3503; case JackOLantern::JackOLantern(eBlockFace::BLOCK_FACE_ZP).ID: return 3504; case JackOLantern::JackOLantern(eBlockFace::BLOCK_FACE_XM).ID: return 3505; case JackOLantern::JackOLantern(eBlockFace::BLOCK_FACE_XP).ID: return 3506; case Jukebox::Jukebox(true).ID: return 3459; case Jukebox::Jukebox(false).ID: return 3460; case JungleButton::JungleButton(JungleButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5376; case JungleButton::JungleButton(JungleButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5377; case JungleButton::JungleButton(JungleButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5378; case JungleButton::JungleButton(JungleButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5379; case JungleButton::JungleButton(JungleButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, true).ID: return 5380; case JungleButton::JungleButton(JungleButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, false).ID: return 5381; case JungleButton::JungleButton(JungleButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, true).ID: return 5382; case JungleButton::JungleButton(JungleButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, false).ID: return 5383; case JungleButton::JungleButton(JungleButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5384; case JungleButton::JungleButton(JungleButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5385; case JungleButton::JungleButton(JungleButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5386; case JungleButton::JungleButton(JungleButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5387; case JungleButton::JungleButton(JungleButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, true).ID: return 5388; case JungleButton::JungleButton(JungleButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, false).ID: return 5389; case JungleButton::JungleButton(JungleButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, true).ID: return 5390; case JungleButton::JungleButton(JungleButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, false).ID: return 5391; case JungleButton::JungleButton(JungleButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5392; case JungleButton::JungleButton(JungleButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5393; case JungleButton::JungleButton(JungleButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5394; case JungleButton::JungleButton(JungleButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5395; case JungleButton::JungleButton(JungleButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, true).ID: return 5396; case JungleButton::JungleButton(JungleButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, false).ID: return 5397; case JungleButton::JungleButton(JungleButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, true).ID: return 5398; case JungleButton::JungleButton(JungleButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, false).ID: return 5399; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, true, true).ID: return 7806; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, true, false).ID: return 7807; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, false, true).ID: return 7808; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, false, false).ID: return 7809; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, true, true).ID: return 7810; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, true, false).ID: return 7811; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, false, true).ID: return 7812; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, false, false).ID: return 7813; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, true, true).ID: return 7814; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, true, false).ID: return 7815; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, false, true).ID: return 7816; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, false, false).ID: return 7817; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, true, true).ID: return 7818; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, true, false).ID: return 7819; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, false, true).ID: return 7820; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, false, false).ID: return 7821; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, true, true).ID: return 7822; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, true, false).ID: return 7823; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, false, true).ID: return 7824; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, false, false).ID: return 7825; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, true, true).ID: return 7826; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, true, false).ID: return 7827; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, false, true).ID: return 7828; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, false, false).ID: return 7829; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, true, true).ID: return 7830; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, true, false).ID: return 7831; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, false, true).ID: return 7832; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, false, false).ID: return 7833; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, true, true).ID: return 7834; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, true, false).ID: return 7835; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, false, true).ID: return 7836; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, false, false).ID: return 7837; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, true, true).ID: return 7838; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, true, false).ID: return 7839; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, false, true).ID: return 7840; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, false, false).ID: return 7841; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, true, true).ID: return 7842; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, true, false).ID: return 7843; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, false, true).ID: return 7844; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, false, false).ID: return 7845; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, true, true).ID: return 7846; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, true, false).ID: return 7847; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, false, true).ID: return 7848; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, false, false).ID: return 7849; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, true, true).ID: return 7850; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, true, false).ID: return 7851; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, false, true).ID: return 7852; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, false, false).ID: return 7853; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, true, true).ID: return 7854; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, true, false).ID: return 7855; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, false, true).ID: return 7856; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, false, false).ID: return 7857; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, true, true).ID: return 7858; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, true, false).ID: return 7859; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, false, true).ID: return 7860; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, false, false).ID: return 7861; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, true, true).ID: return 7862; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, true, false).ID: return 7863; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, false, true).ID: return 7864; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, false, false).ID: return 7865; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, true, true).ID: return 7866; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, true, false).ID: return 7867; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, false, true).ID: return 7868; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, false, false).ID: return 7869; case JungleFence::JungleFence(true, true, true, true).ID: return 7584; case JungleFence::JungleFence(true, true, true, false).ID: return 7585; case JungleFence::JungleFence(true, true, false, true).ID: return 7588; case JungleFence::JungleFence(true, true, false, false).ID: return 7589; case JungleFence::JungleFence(true, false, true, true).ID: return 7592; case JungleFence::JungleFence(true, false, true, false).ID: return 7593; case JungleFence::JungleFence(true, false, false, true).ID: return 7596; case JungleFence::JungleFence(true, false, false, false).ID: return 7597; case JungleFence::JungleFence(false, true, true, true).ID: return 7600; case JungleFence::JungleFence(false, true, true, false).ID: return 7601; case JungleFence::JungleFence(false, true, false, true).ID: return 7604; case JungleFence::JungleFence(false, true, false, false).ID: return 7605; case JungleFence::JungleFence(false, false, true, true).ID: return 7608; case JungleFence::JungleFence(false, false, true, false).ID: return 7609; case JungleFence::JungleFence(false, false, false, true).ID: return 7612; case JungleFence::JungleFence(false, false, false, false).ID: return 7613; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZM, true, true, true).ID: return 7422; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZM, true, true, false).ID: return 7423; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZM, true, false, true).ID: return 7424; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZM, true, false, false).ID: return 7425; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, true).ID: return 7426; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, false).ID: return 7427; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, true).ID: return 7428; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, false).ID: return 7429; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZP, true, true, true).ID: return 7430; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZP, true, true, false).ID: return 7431; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZP, true, false, true).ID: return 7432; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZP, true, false, false).ID: return 7433; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, true).ID: return 7434; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, false).ID: return 7435; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, true).ID: return 7436; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, false).ID: return 7437; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XM, true, true, true).ID: return 7438; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XM, true, true, false).ID: return 7439; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XM, true, false, true).ID: return 7440; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XM, true, false, false).ID: return 7441; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, true).ID: return 7442; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, false).ID: return 7443; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, true).ID: return 7444; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, false).ID: return 7445; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XP, true, true, true).ID: return 7446; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XP, true, true, false).ID: return 7447; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XP, true, false, true).ID: return 7448; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XP, true, false, false).ID: return 7449; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, true).ID: return 7450; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, false).ID: return 7451; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, true).ID: return 7452; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, false).ID: return 7453; case JungleLeaves::JungleLeaves(1, true).ID: return 186; case JungleLeaves::JungleLeaves(1, false).ID: return 187; case JungleLeaves::JungleLeaves(2, true).ID: return 188; case JungleLeaves::JungleLeaves(2, false).ID: return 189; case JungleLeaves::JungleLeaves(3, true).ID: return 190; case JungleLeaves::JungleLeaves(3, false).ID: return 191; case JungleLeaves::JungleLeaves(4, true).ID: return 192; case JungleLeaves::JungleLeaves(4, false).ID: return 193; case JungleLeaves::JungleLeaves(5, true).ID: return 194; case JungleLeaves::JungleLeaves(5, false).ID: return 195; case JungleLeaves::JungleLeaves(6, true).ID: return 196; case JungleLeaves::JungleLeaves(6, false).ID: return 197; case JungleLeaves::JungleLeaves(7, true).ID: return 198; case JungleLeaves::JungleLeaves(7, false).ID: return 199; case JungleLog::JungleLog(JungleLog::Axis::X).ID: return 81; case JungleLog::JungleLog(JungleLog::Axis::Y).ID: return 82; case JungleLog::JungleLog(JungleLog::Axis::Z).ID: return 83; case JunglePlanks::JunglePlanks().ID: return 18; case JunglePressurePlate::JunglePressurePlate(true).ID: return 3374; case JunglePressurePlate::JunglePressurePlate(false).ID: return 3375; case JungleSapling::JungleSapling(0).ID: return 27; case JungleSapling::JungleSapling(1).ID: return 28; case JungleSlab::JungleSlab(JungleSlab::Type::Top).ID: return 7277; case JungleSlab::JungleSlab(JungleSlab::Type::Bottom).ID: return 7279; case JungleSlab::JungleSlab(JungleSlab::Type::Double).ID: return 7281; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZM, JungleStairs::Half::Top, JungleStairs::Shape::Straight).ID: return 5046; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZM, JungleStairs::Half::Top, JungleStairs::Shape::InnerLeft).ID: return 5048; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZM, JungleStairs::Half::Top, JungleStairs::Shape::InnerRight).ID: return 5050; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZM, JungleStairs::Half::Top, JungleStairs::Shape::OuterLeft).ID: return 5052; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZM, JungleStairs::Half::Top, JungleStairs::Shape::OuterRight).ID: return 5054; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZM, JungleStairs::Half::Bottom, JungleStairs::Shape::Straight).ID: return 5056; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZM, JungleStairs::Half::Bottom, JungleStairs::Shape::InnerLeft).ID: return 5058; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZM, JungleStairs::Half::Bottom, JungleStairs::Shape::InnerRight).ID: return 5060; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZM, JungleStairs::Half::Bottom, JungleStairs::Shape::OuterLeft).ID: return 5062; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZM, JungleStairs::Half::Bottom, JungleStairs::Shape::OuterRight).ID: return 5064; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZP, JungleStairs::Half::Top, JungleStairs::Shape::Straight).ID: return 5066; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZP, JungleStairs::Half::Top, JungleStairs::Shape::InnerLeft).ID: return 5068; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZP, JungleStairs::Half::Top, JungleStairs::Shape::InnerRight).ID: return 5070; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZP, JungleStairs::Half::Top, JungleStairs::Shape::OuterLeft).ID: return 5072; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZP, JungleStairs::Half::Top, JungleStairs::Shape::OuterRight).ID: return 5074; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZP, JungleStairs::Half::Bottom, JungleStairs::Shape::Straight).ID: return 5076; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZP, JungleStairs::Half::Bottom, JungleStairs::Shape::InnerLeft).ID: return 5078; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZP, JungleStairs::Half::Bottom, JungleStairs::Shape::InnerRight).ID: return 5080; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZP, JungleStairs::Half::Bottom, JungleStairs::Shape::OuterLeft).ID: return 5082; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZP, JungleStairs::Half::Bottom, JungleStairs::Shape::OuterRight).ID: return 5084; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XM, JungleStairs::Half::Top, JungleStairs::Shape::Straight).ID: return 5086; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XM, JungleStairs::Half::Top, JungleStairs::Shape::InnerLeft).ID: return 5088; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XM, JungleStairs::Half::Top, JungleStairs::Shape::InnerRight).ID: return 5090; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XM, JungleStairs::Half::Top, JungleStairs::Shape::OuterLeft).ID: return 5092; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XM, JungleStairs::Half::Top, JungleStairs::Shape::OuterRight).ID: return 5094; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XM, JungleStairs::Half::Bottom, JungleStairs::Shape::Straight).ID: return 5096; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XM, JungleStairs::Half::Bottom, JungleStairs::Shape::InnerLeft).ID: return 5098; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XM, JungleStairs::Half::Bottom, JungleStairs::Shape::InnerRight).ID: return 5100; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XM, JungleStairs::Half::Bottom, JungleStairs::Shape::OuterLeft).ID: return 5102; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XM, JungleStairs::Half::Bottom, JungleStairs::Shape::OuterRight).ID: return 5104; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XP, JungleStairs::Half::Top, JungleStairs::Shape::Straight).ID: return 5106; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XP, JungleStairs::Half::Top, JungleStairs::Shape::InnerLeft).ID: return 5108; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XP, JungleStairs::Half::Top, JungleStairs::Shape::InnerRight).ID: return 5110; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XP, JungleStairs::Half::Top, JungleStairs::Shape::OuterLeft).ID: return 5112; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XP, JungleStairs::Half::Top, JungleStairs::Shape::OuterRight).ID: return 5114; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XP, JungleStairs::Half::Bottom, JungleStairs::Shape::Straight).ID: return 5116; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XP, JungleStairs::Half::Bottom, JungleStairs::Shape::InnerLeft).ID: return 5118; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XP, JungleStairs::Half::Bottom, JungleStairs::Shape::InnerRight).ID: return 5120; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XP, JungleStairs::Half::Bottom, JungleStairs::Shape::OuterLeft).ID: return 5122; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XP, JungleStairs::Half::Bottom, JungleStairs::Shape::OuterRight).ID: return 5124; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZM, JungleTrapdoor::Half::Top, true, true).ID: return 3787; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZM, JungleTrapdoor::Half::Top, true, false).ID: return 3789; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZM, JungleTrapdoor::Half::Top, false, true).ID: return 3791; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZM, JungleTrapdoor::Half::Top, false, false).ID: return 3793; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZM, JungleTrapdoor::Half::Bottom, true, true).ID: return 3795; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZM, JungleTrapdoor::Half::Bottom, true, false).ID: return 3797; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZM, JungleTrapdoor::Half::Bottom, false, true).ID: return 3799; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZM, JungleTrapdoor::Half::Bottom, false, false).ID: return 3801; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZP, JungleTrapdoor::Half::Top, true, true).ID: return 3803; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZP, JungleTrapdoor::Half::Top, true, false).ID: return 3805; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZP, JungleTrapdoor::Half::Top, false, true).ID: return 3807; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZP, JungleTrapdoor::Half::Top, false, false).ID: return 3809; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZP, JungleTrapdoor::Half::Bottom, true, true).ID: return 3811; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZP, JungleTrapdoor::Half::Bottom, true, false).ID: return 3813; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZP, JungleTrapdoor::Half::Bottom, false, true).ID: return 3815; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZP, JungleTrapdoor::Half::Bottom, false, false).ID: return 3817; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XM, JungleTrapdoor::Half::Top, true, true).ID: return 3819; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XM, JungleTrapdoor::Half::Top, true, false).ID: return 3821; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XM, JungleTrapdoor::Half::Top, false, true).ID: return 3823; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XM, JungleTrapdoor::Half::Top, false, false).ID: return 3825; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XM, JungleTrapdoor::Half::Bottom, true, true).ID: return 3827; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XM, JungleTrapdoor::Half::Bottom, true, false).ID: return 3829; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XM, JungleTrapdoor::Half::Bottom, false, true).ID: return 3831; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XM, JungleTrapdoor::Half::Bottom, false, false).ID: return 3833; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XP, JungleTrapdoor::Half::Top, true, true).ID: return 3835; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XP, JungleTrapdoor::Half::Top, true, false).ID: return 3837; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XP, JungleTrapdoor::Half::Top, false, true).ID: return 3839; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XP, JungleTrapdoor::Half::Top, false, false).ID: return 3841; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XP, JungleTrapdoor::Half::Bottom, true, true).ID: return 3843; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XP, JungleTrapdoor::Half::Bottom, true, false).ID: return 3845; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XP, JungleTrapdoor::Half::Bottom, false, true).ID: return 3847; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XP, JungleTrapdoor::Half::Bottom, false, false).ID: return 3849; case JungleWood::JungleWood(JungleWood::Axis::X).ID: return 117; case JungleWood::JungleWood(JungleWood::Axis::Y).ID: return 118; case JungleWood::JungleWood(JungleWood::Axis::Z).ID: return 119; case Kelp::Kelp(0).ID: return 8410; case Kelp::Kelp(1).ID: return 8411; case Kelp::Kelp(2).ID: return 8412; case Kelp::Kelp(3).ID: return 8413; case Kelp::Kelp(4).ID: return 8414; case Kelp::Kelp(5).ID: return 8415; case Kelp::Kelp(6).ID: return 8416; case Kelp::Kelp(7).ID: return 8417; case Kelp::Kelp(8).ID: return 8418; case Kelp::Kelp(9).ID: return 8419; case Kelp::Kelp(10).ID: return 8420; case Kelp::Kelp(11).ID: return 8421; case Kelp::Kelp(12).ID: return 8422; case Kelp::Kelp(13).ID: return 8423; case Kelp::Kelp(14).ID: return 8424; case Kelp::Kelp(15).ID: return 8425; case Kelp::Kelp(16).ID: return 8426; case Kelp::Kelp(17).ID: return 8427; case Kelp::Kelp(18).ID: return 8428; case Kelp::Kelp(19).ID: return 8429; case Kelp::Kelp(20).ID: return 8430; case Kelp::Kelp(21).ID: return 8431; case Kelp::Kelp(22).ID: return 8432; case Kelp::Kelp(23).ID: return 8433; case Kelp::Kelp(24).ID: return 8434; case Kelp::Kelp(25).ID: return 8435; case KelpPlant::KelpPlant().ID: return 8436; case Ladder::Ladder(eBlockFace::BLOCK_FACE_ZM).ID: return 3173; case Ladder::Ladder(eBlockFace::BLOCK_FACE_ZP).ID: return 3175; case Ladder::Ladder(eBlockFace::BLOCK_FACE_XM).ID: return 3177; case Ladder::Ladder(eBlockFace::BLOCK_FACE_XP).ID: return 3179; case LapisBlock::LapisBlock().ID: return 232; case LapisOre::LapisOre().ID: return 231; case LargeFern::LargeFern(LargeFern::Half::Upper).ID: return 6853; case LargeFern::LargeFern(LargeFern::Half::Lower).ID: return 6854; case Lava::Lava(0).ID: return 50; case Lava::Lava(1).ID: return 51; case Lava::Lava(2).ID: return 52; case Lava::Lava(3).ID: return 53; case Lava::Lava(4).ID: return 54; case Lava::Lava(5).ID: return 55; case Lava::Lava(6).ID: return 56; case Lava::Lava(7).ID: return 57; case Lava::Lava(8).ID: return 58; case Lava::Lava(9).ID: return 59; case Lava::Lava(10).ID: return 60; case Lava::Lava(11).ID: return 61; case Lava::Lava(12).ID: return 62; case Lava::Lava(13).ID: return 63; case Lava::Lava(14).ID: return 64; case Lava::Lava(15).ID: return 65; case Lever::Lever(Lever::Face::Floor, eBlockFace::BLOCK_FACE_ZM, true).ID: return 3278; case Lever::Lever(Lever::Face::Floor, eBlockFace::BLOCK_FACE_ZM, false).ID: return 3279; case Lever::Lever(Lever::Face::Floor, eBlockFace::BLOCK_FACE_ZP, true).ID: return 3280; case Lever::Lever(Lever::Face::Floor, eBlockFace::BLOCK_FACE_ZP, false).ID: return 3281; case Lever::Lever(Lever::Face::Floor, eBlockFace::BLOCK_FACE_XM, true).ID: return 3282; case Lever::Lever(Lever::Face::Floor, eBlockFace::BLOCK_FACE_XM, false).ID: return 3283; case Lever::Lever(Lever::Face::Floor, eBlockFace::BLOCK_FACE_XP, true).ID: return 3284; case Lever::Lever(Lever::Face::Floor, eBlockFace::BLOCK_FACE_XP, false).ID: return 3285; case Lever::Lever(Lever::Face::Wall, eBlockFace::BLOCK_FACE_ZM, true).ID: return 3286; case Lever::Lever(Lever::Face::Wall, eBlockFace::BLOCK_FACE_ZM, false).ID: return 3287; case Lever::Lever(Lever::Face::Wall, eBlockFace::BLOCK_FACE_ZP, true).ID: return 3288; case Lever::Lever(Lever::Face::Wall, eBlockFace::BLOCK_FACE_ZP, false).ID: return 3289; case Lever::Lever(Lever::Face::Wall, eBlockFace::BLOCK_FACE_XM, true).ID: return 3290; case Lever::Lever(Lever::Face::Wall, eBlockFace::BLOCK_FACE_XM, false).ID: return 3291; case Lever::Lever(Lever::Face::Wall, eBlockFace::BLOCK_FACE_XP, true).ID: return 3292; case Lever::Lever(Lever::Face::Wall, eBlockFace::BLOCK_FACE_XP, false).ID: return 3293; case Lever::Lever(Lever::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, true).ID: return 3294; case Lever::Lever(Lever::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, false).ID: return 3295; case Lever::Lever(Lever::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, true).ID: return 3296; case Lever::Lever(Lever::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, false).ID: return 3297; case Lever::Lever(Lever::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, true).ID: return 3298; case Lever::Lever(Lever::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, false).ID: return 3299; case Lever::Lever(Lever::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, true).ID: return 3300; case Lever::Lever(Lever::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, false).ID: return 3301; case LightBlueBanner::LightBlueBanner(0).ID: return 6903; case LightBlueBanner::LightBlueBanner(1).ID: return 6904; case LightBlueBanner::LightBlueBanner(2).ID: return 6905; case LightBlueBanner::LightBlueBanner(3).ID: return 6906; case LightBlueBanner::LightBlueBanner(4).ID: return 6907; case LightBlueBanner::LightBlueBanner(5).ID: return 6908; case LightBlueBanner::LightBlueBanner(6).ID: return 6909; case LightBlueBanner::LightBlueBanner(7).ID: return 6910; case LightBlueBanner::LightBlueBanner(8).ID: return 6911; case LightBlueBanner::LightBlueBanner(9).ID: return 6912; case LightBlueBanner::LightBlueBanner(10).ID: return 6913; case LightBlueBanner::LightBlueBanner(11).ID: return 6914; case LightBlueBanner::LightBlueBanner(12).ID: return 6915; case LightBlueBanner::LightBlueBanner(13).ID: return 6916; case LightBlueBanner::LightBlueBanner(14).ID: return 6917; case LightBlueBanner::LightBlueBanner(15).ID: return 6918; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_ZM, true, LightBlueBed::Part::Head).ID: return 796; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_ZM, true, LightBlueBed::Part::Foot).ID: return 797; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_ZM, false, LightBlueBed::Part::Head).ID: return 798; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_ZM, false, LightBlueBed::Part::Foot).ID: return 799; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_ZP, true, LightBlueBed::Part::Head).ID: return 800; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_ZP, true, LightBlueBed::Part::Foot).ID: return 801; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_ZP, false, LightBlueBed::Part::Head).ID: return 802; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_ZP, false, LightBlueBed::Part::Foot).ID: return 803; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_XM, true, LightBlueBed::Part::Head).ID: return 804; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_XM, true, LightBlueBed::Part::Foot).ID: return 805; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_XM, false, LightBlueBed::Part::Head).ID: return 806; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_XM, false, LightBlueBed::Part::Foot).ID: return 807; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_XP, true, LightBlueBed::Part::Head).ID: return 808; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_XP, true, LightBlueBed::Part::Foot).ID: return 809; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_XP, false, LightBlueBed::Part::Head).ID: return 810; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_XP, false, LightBlueBed::Part::Foot).ID: return 811; case LightBlueCarpet::LightBlueCarpet().ID: return 6827; case LightBlueConcrete::LightBlueConcrete().ID: return 8381; case LightBlueConcretePowder::LightBlueConcretePowder().ID: return 8397; case LightBlueGlazedTerracotta::LightBlueGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 8326; case LightBlueGlazedTerracotta::LightBlueGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 8327; case LightBlueGlazedTerracotta::LightBlueGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 8328; case LightBlueGlazedTerracotta::LightBlueGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 8329; case LightBlueShulkerBox::LightBlueShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 8236; case LightBlueShulkerBox::LightBlueShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 8237; case LightBlueShulkerBox::LightBlueShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 8238; case LightBlueShulkerBox::LightBlueShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 8239; case LightBlueShulkerBox::LightBlueShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 8240; case LightBlueShulkerBox::LightBlueShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 8241; case LightBlueStainedGlass::LightBlueStainedGlass().ID: return 3581; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(true, true, true, true).ID: return 5919; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(true, true, true, false).ID: return 5920; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(true, true, false, true).ID: return 5923; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(true, true, false, false).ID: return 5924; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(true, false, true, true).ID: return 5927; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(true, false, true, false).ID: return 5928; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(true, false, false, true).ID: return 5931; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(true, false, false, false).ID: return 5932; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(false, true, true, true).ID: return 5935; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(false, true, true, false).ID: return 5936; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(false, true, false, true).ID: return 5939; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(false, true, false, false).ID: return 5940; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(false, false, true, true).ID: return 5943; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(false, false, true, false).ID: return 5944; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(false, false, false, true).ID: return 5947; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(false, false, false, false).ID: return 5948; case LightBlueTerracotta::LightBlueTerracotta().ID: return 5808; case LightBlueWallBanner::LightBlueWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 7123; case LightBlueWallBanner::LightBlueWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 7124; case LightBlueWallBanner::LightBlueWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 7125; case LightBlueWallBanner::LightBlueWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 7126; case LightBlueWool::LightBlueWool().ID: return 1086; case LightGrayBanner::LightGrayBanner(0).ID: return 6983; case LightGrayBanner::LightGrayBanner(1).ID: return 6984; case LightGrayBanner::LightGrayBanner(2).ID: return 6985; case LightGrayBanner::LightGrayBanner(3).ID: return 6986; case LightGrayBanner::LightGrayBanner(4).ID: return 6987; case LightGrayBanner::LightGrayBanner(5).ID: return 6988; case LightGrayBanner::LightGrayBanner(6).ID: return 6989; case LightGrayBanner::LightGrayBanner(7).ID: return 6990; case LightGrayBanner::LightGrayBanner(8).ID: return 6991; case LightGrayBanner::LightGrayBanner(9).ID: return 6992; case LightGrayBanner::LightGrayBanner(10).ID: return 6993; case LightGrayBanner::LightGrayBanner(11).ID: return 6994; case LightGrayBanner::LightGrayBanner(12).ID: return 6995; case LightGrayBanner::LightGrayBanner(13).ID: return 6996; case LightGrayBanner::LightGrayBanner(14).ID: return 6997; case LightGrayBanner::LightGrayBanner(15).ID: return 6998; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_ZM, true, LightGrayBed::Part::Head).ID: return 876; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_ZM, true, LightGrayBed::Part::Foot).ID: return 877; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_ZM, false, LightGrayBed::Part::Head).ID: return 878; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_ZM, false, LightGrayBed::Part::Foot).ID: return 879; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_ZP, true, LightGrayBed::Part::Head).ID: return 880; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_ZP, true, LightGrayBed::Part::Foot).ID: return 881; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_ZP, false, LightGrayBed::Part::Head).ID: return 882; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_ZP, false, LightGrayBed::Part::Foot).ID: return 883; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_XM, true, LightGrayBed::Part::Head).ID: return 884; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_XM, true, LightGrayBed::Part::Foot).ID: return 885; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_XM, false, LightGrayBed::Part::Head).ID: return 886; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_XM, false, LightGrayBed::Part::Foot).ID: return 887; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_XP, true, LightGrayBed::Part::Head).ID: return 888; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_XP, true, LightGrayBed::Part::Foot).ID: return 889; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_XP, false, LightGrayBed::Part::Head).ID: return 890; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_XP, false, LightGrayBed::Part::Foot).ID: return 891; case LightGrayCarpet::LightGrayCarpet().ID: return 6832; case LightGrayConcrete::LightGrayConcrete().ID: return 8386; case LightGrayConcretePowder::LightGrayConcretePowder().ID: return 8402; case LightGrayGlazedTerracotta::LightGrayGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 8346; case LightGrayGlazedTerracotta::LightGrayGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 8347; case LightGrayGlazedTerracotta::LightGrayGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 8348; case LightGrayGlazedTerracotta::LightGrayGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 8349; case LightGrayShulkerBox::LightGrayShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 8266; case LightGrayShulkerBox::LightGrayShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 8267; case LightGrayShulkerBox::LightGrayShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 8268; case LightGrayShulkerBox::LightGrayShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 8269; case LightGrayShulkerBox::LightGrayShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 8270; case LightGrayShulkerBox::LightGrayShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 8271; case LightGrayStainedGlass::LightGrayStainedGlass().ID: return 3586; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(true, true, true, true).ID: return 6079; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(true, true, true, false).ID: return 6080; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(true, true, false, true).ID: return 6083; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(true, true, false, false).ID: return 6084; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(true, false, true, true).ID: return 6087; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(true, false, true, false).ID: return 6088; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(true, false, false, true).ID: return 6091; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(true, false, false, false).ID: return 6092; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(false, true, true, true).ID: return 6095; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(false, true, true, false).ID: return 6096; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(false, true, false, true).ID: return 6099; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(false, true, false, false).ID: return 6100; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(false, false, true, true).ID: return 6103; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(false, false, true, false).ID: return 6104; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(false, false, false, true).ID: return 6107; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(false, false, false, false).ID: return 6108; case LightGrayTerracotta::LightGrayTerracotta().ID: return 5813; case LightGrayWallBanner::LightGrayWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 7143; case LightGrayWallBanner::LightGrayWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 7144; case LightGrayWallBanner::LightGrayWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 7145; case LightGrayWallBanner::LightGrayWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 7146; case LightGrayWool::LightGrayWool().ID: return 1091; case LightWeightedPressurePlate::LightWeightedPressurePlate(0).ID: return 5604; case LightWeightedPressurePlate::LightWeightedPressurePlate(1).ID: return 5605; case LightWeightedPressurePlate::LightWeightedPressurePlate(2).ID: return 5606; case LightWeightedPressurePlate::LightWeightedPressurePlate(3).ID: return 5607; case LightWeightedPressurePlate::LightWeightedPressurePlate(4).ID: return 5608; case LightWeightedPressurePlate::LightWeightedPressurePlate(5).ID: return 5609; case LightWeightedPressurePlate::LightWeightedPressurePlate(6).ID: return 5610; case LightWeightedPressurePlate::LightWeightedPressurePlate(7).ID: return 5611; case LightWeightedPressurePlate::LightWeightedPressurePlate(8).ID: return 5612; case LightWeightedPressurePlate::LightWeightedPressurePlate(9).ID: return 5613; case LightWeightedPressurePlate::LightWeightedPressurePlate(10).ID: return 5614; case LightWeightedPressurePlate::LightWeightedPressurePlate(11).ID: return 5615; case LightWeightedPressurePlate::LightWeightedPressurePlate(12).ID: return 5616; case LightWeightedPressurePlate::LightWeightedPressurePlate(13).ID: return 5617; case LightWeightedPressurePlate::LightWeightedPressurePlate(14).ID: return 5618; case LightWeightedPressurePlate::LightWeightedPressurePlate(15).ID: return 5619; case Lilac::Lilac(Lilac::Half::Upper).ID: return 6845; case Lilac::Lilac(Lilac::Half::Lower).ID: return 6846; case LilyPad::LilyPad().ID: return 4495; case LimeBanner::LimeBanner(0).ID: return 6935; case LimeBanner::LimeBanner(1).ID: return 6936; case LimeBanner::LimeBanner(2).ID: return 6937; case LimeBanner::LimeBanner(3).ID: return 6938; case LimeBanner::LimeBanner(4).ID: return 6939; case LimeBanner::LimeBanner(5).ID: return 6940; case LimeBanner::LimeBanner(6).ID: return 6941; case LimeBanner::LimeBanner(7).ID: return 6942; case LimeBanner::LimeBanner(8).ID: return 6943; case LimeBanner::LimeBanner(9).ID: return 6944; case LimeBanner::LimeBanner(10).ID: return 6945; case LimeBanner::LimeBanner(11).ID: return 6946; case LimeBanner::LimeBanner(12).ID: return 6947; case LimeBanner::LimeBanner(13).ID: return 6948; case LimeBanner::LimeBanner(14).ID: return 6949; case LimeBanner::LimeBanner(15).ID: return 6950; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_ZM, true, LimeBed::Part::Head).ID: return 828; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_ZM, true, LimeBed::Part::Foot).ID: return 829; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_ZM, false, LimeBed::Part::Head).ID: return 830; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_ZM, false, LimeBed::Part::Foot).ID: return 831; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_ZP, true, LimeBed::Part::Head).ID: return 832; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_ZP, true, LimeBed::Part::Foot).ID: return 833; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_ZP, false, LimeBed::Part::Head).ID: return 834; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_ZP, false, LimeBed::Part::Foot).ID: return 835; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_XM, true, LimeBed::Part::Head).ID: return 836; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_XM, true, LimeBed::Part::Foot).ID: return 837; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_XM, false, LimeBed::Part::Head).ID: return 838; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_XM, false, LimeBed::Part::Foot).ID: return 839; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_XP, true, LimeBed::Part::Head).ID: return 840; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_XP, true, LimeBed::Part::Foot).ID: return 841; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_XP, false, LimeBed::Part::Head).ID: return 842; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_XP, false, LimeBed::Part::Foot).ID: return 843; case LimeCarpet::LimeCarpet().ID: return 6829; case LimeConcrete::LimeConcrete().ID: return 8383; case LimeConcretePowder::LimeConcretePowder().ID: return 8399; case LimeGlazedTerracotta::LimeGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 8334; case LimeGlazedTerracotta::LimeGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 8335; case LimeGlazedTerracotta::LimeGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 8336; case LimeGlazedTerracotta::LimeGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 8337; case LimeShulkerBox::LimeShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 8248; case LimeShulkerBox::LimeShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 8249; case LimeShulkerBox::LimeShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 8250; case LimeShulkerBox::LimeShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 8251; case LimeShulkerBox::LimeShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 8252; case LimeShulkerBox::LimeShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 8253; case LimeStainedGlass::LimeStainedGlass().ID: return 3583; case LimeStainedGlassPane::LimeStainedGlassPane(true, true, true, true).ID: return 5983; case LimeStainedGlassPane::LimeStainedGlassPane(true, true, true, false).ID: return 5984; case LimeStainedGlassPane::LimeStainedGlassPane(true, true, false, true).ID: return 5987; case LimeStainedGlassPane::LimeStainedGlassPane(true, true, false, false).ID: return 5988; case LimeStainedGlassPane::LimeStainedGlassPane(true, false, true, true).ID: return 5991; case LimeStainedGlassPane::LimeStainedGlassPane(true, false, true, false).ID: return 5992; case LimeStainedGlassPane::LimeStainedGlassPane(true, false, false, true).ID: return 5995; case LimeStainedGlassPane::LimeStainedGlassPane(true, false, false, false).ID: return 5996; case LimeStainedGlassPane::LimeStainedGlassPane(false, true, true, true).ID: return 5999; case LimeStainedGlassPane::LimeStainedGlassPane(false, true, true, false).ID: return 6000; case LimeStainedGlassPane::LimeStainedGlassPane(false, true, false, true).ID: return 6003; case LimeStainedGlassPane::LimeStainedGlassPane(false, true, false, false).ID: return 6004; case LimeStainedGlassPane::LimeStainedGlassPane(false, false, true, true).ID: return 6007; case LimeStainedGlassPane::LimeStainedGlassPane(false, false, true, false).ID: return 6008; case LimeStainedGlassPane::LimeStainedGlassPane(false, false, false, true).ID: return 6011; case LimeStainedGlassPane::LimeStainedGlassPane(false, false, false, false).ID: return 6012; case LimeTerracotta::LimeTerracotta().ID: return 5810; case LimeWallBanner::LimeWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 7131; case LimeWallBanner::LimeWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 7132; case LimeWallBanner::LimeWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 7133; case LimeWallBanner::LimeWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 7134; case LimeWool::LimeWool().ID: return 1088; case MagentaBanner::MagentaBanner(0).ID: return 6887; case MagentaBanner::MagentaBanner(1).ID: return 6888; case MagentaBanner::MagentaBanner(2).ID: return 6889; case MagentaBanner::MagentaBanner(3).ID: return 6890; case MagentaBanner::MagentaBanner(4).ID: return 6891; case MagentaBanner::MagentaBanner(5).ID: return 6892; case MagentaBanner::MagentaBanner(6).ID: return 6893; case MagentaBanner::MagentaBanner(7).ID: return 6894; case MagentaBanner::MagentaBanner(8).ID: return 6895; case MagentaBanner::MagentaBanner(9).ID: return 6896; case MagentaBanner::MagentaBanner(10).ID: return 6897; case MagentaBanner::MagentaBanner(11).ID: return 6898; case MagentaBanner::MagentaBanner(12).ID: return 6899; case MagentaBanner::MagentaBanner(13).ID: return 6900; case MagentaBanner::MagentaBanner(14).ID: return 6901; case MagentaBanner::MagentaBanner(15).ID: return 6902; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_ZM, true, MagentaBed::Part::Head).ID: return 780; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_ZM, true, MagentaBed::Part::Foot).ID: return 781; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_ZM, false, MagentaBed::Part::Head).ID: return 782; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_ZM, false, MagentaBed::Part::Foot).ID: return 783; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_ZP, true, MagentaBed::Part::Head).ID: return 784; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_ZP, true, MagentaBed::Part::Foot).ID: return 785; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_ZP, false, MagentaBed::Part::Head).ID: return 786; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_ZP, false, MagentaBed::Part::Foot).ID: return 787; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_XM, true, MagentaBed::Part::Head).ID: return 788; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_XM, true, MagentaBed::Part::Foot).ID: return 789; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_XM, false, MagentaBed::Part::Head).ID: return 790; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_XM, false, MagentaBed::Part::Foot).ID: return 791; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_XP, true, MagentaBed::Part::Head).ID: return 792; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_XP, true, MagentaBed::Part::Foot).ID: return 793; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_XP, false, MagentaBed::Part::Head).ID: return 794; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_XP, false, MagentaBed::Part::Foot).ID: return 795; case MagentaCarpet::MagentaCarpet().ID: return 6826; case MagentaConcrete::MagentaConcrete().ID: return 8380; case MagentaConcretePowder::MagentaConcretePowder().ID: return 8396; case MagentaGlazedTerracotta::MagentaGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 8322; case MagentaGlazedTerracotta::MagentaGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 8323; case MagentaGlazedTerracotta::MagentaGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 8324; case MagentaGlazedTerracotta::MagentaGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 8325; case MagentaShulkerBox::MagentaShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 8230; case MagentaShulkerBox::MagentaShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 8231; case MagentaShulkerBox::MagentaShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 8232; case MagentaShulkerBox::MagentaShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 8233; case MagentaShulkerBox::MagentaShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 8234; case MagentaShulkerBox::MagentaShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 8235; case MagentaStainedGlass::MagentaStainedGlass().ID: return 3580; case MagentaStainedGlassPane::MagentaStainedGlassPane(true, true, true, true).ID: return 5887; case MagentaStainedGlassPane::MagentaStainedGlassPane(true, true, true, false).ID: return 5888; case MagentaStainedGlassPane::MagentaStainedGlassPane(true, true, false, true).ID: return 5891; case MagentaStainedGlassPane::MagentaStainedGlassPane(true, true, false, false).ID: return 5892; case MagentaStainedGlassPane::MagentaStainedGlassPane(true, false, true, true).ID: return 5895; case MagentaStainedGlassPane::MagentaStainedGlassPane(true, false, true, false).ID: return 5896; case MagentaStainedGlassPane::MagentaStainedGlassPane(true, false, false, true).ID: return 5899; case MagentaStainedGlassPane::MagentaStainedGlassPane(true, false, false, false).ID: return 5900; case MagentaStainedGlassPane::MagentaStainedGlassPane(false, true, true, true).ID: return 5903; case MagentaStainedGlassPane::MagentaStainedGlassPane(false, true, true, false).ID: return 5904; case MagentaStainedGlassPane::MagentaStainedGlassPane(false, true, false, true).ID: return 5907; case MagentaStainedGlassPane::MagentaStainedGlassPane(false, true, false, false).ID: return 5908; case MagentaStainedGlassPane::MagentaStainedGlassPane(false, false, true, true).ID: return 5911; case MagentaStainedGlassPane::MagentaStainedGlassPane(false, false, true, false).ID: return 5912; case MagentaStainedGlassPane::MagentaStainedGlassPane(false, false, false, true).ID: return 5915; case MagentaStainedGlassPane::MagentaStainedGlassPane(false, false, false, false).ID: return 5916; case MagentaTerracotta::MagentaTerracotta().ID: return 5807; case MagentaWallBanner::MagentaWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 7119; case MagentaWallBanner::MagentaWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 7120; case MagentaWallBanner::MagentaWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 7121; case MagentaWallBanner::MagentaWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 7122; case MagentaWool::MagentaWool().ID: return 1085; case MagmaBlock::MagmaBlock().ID: return 8193; case Melon::Melon().ID: return 4244; case MelonStem::MelonStem(0).ID: return 4261; case MelonStem::MelonStem(1).ID: return 4262; case MelonStem::MelonStem(2).ID: return 4263; case MelonStem::MelonStem(3).ID: return 4264; case MelonStem::MelonStem(4).ID: return 4265; case MelonStem::MelonStem(5).ID: return 4266; case MelonStem::MelonStem(6).ID: return 4267; case MelonStem::MelonStem(7).ID: return 4268; case MossyCobblestone::MossyCobblestone().ID: return 1129; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::Low, true, MossyCobblestoneWall::West::Low).ID: return 5204; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::Low, true, MossyCobblestoneWall::West::None).ID: return 5205; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::Low, false, MossyCobblestoneWall::West::Low).ID: return 5208; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::Low, false, MossyCobblestoneWall::West::None).ID: return 5209; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::None, true, MossyCobblestoneWall::West::Low).ID: return 5212; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::None, true, MossyCobblestoneWall::West::None).ID: return 5213; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::None, false, MossyCobblestoneWall::West::Low).ID: return 5216; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::None, false, MossyCobblestoneWall::West::None).ID: return 5217; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::Low, true, MossyCobblestoneWall::West::Low).ID: return 5220; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::Low, true, MossyCobblestoneWall::West::None).ID: return 5221; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::Low, false, MossyCobblestoneWall::West::Low).ID: return 5224; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::Low, false, MossyCobblestoneWall::West::None).ID: return 5225; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::None, true, MossyCobblestoneWall::West::Low).ID: return 5228; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::None, true, MossyCobblestoneWall::West::None).ID: return 5229; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::None, false, MossyCobblestoneWall::West::Low).ID: return 5232; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::None, false, MossyCobblestoneWall::West::None).ID: return 5233; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::Low, true, MossyCobblestoneWall::West::Low).ID: return 5236; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::Low, true, MossyCobblestoneWall::West::None).ID: return 5237; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::Low, false, MossyCobblestoneWall::West::Low).ID: return 5240; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::Low, false, MossyCobblestoneWall::West::None).ID: return 5241; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::None, true, MossyCobblestoneWall::West::Low).ID: return 5244; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::None, true, MossyCobblestoneWall::West::None).ID: return 5245; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::None, false, MossyCobblestoneWall::West::Low).ID: return 5248; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::None, false, MossyCobblestoneWall::West::None).ID: return 5249; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::Low, true, MossyCobblestoneWall::West::Low).ID: return 5252; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::Low, true, MossyCobblestoneWall::West::None).ID: return 5253; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::Low, false, MossyCobblestoneWall::West::Low).ID: return 5256; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::Low, false, MossyCobblestoneWall::West::None).ID: return 5257; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::None, true, MossyCobblestoneWall::West::Low).ID: return 5260; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::None, true, MossyCobblestoneWall::West::None).ID: return 5261; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::None, false, MossyCobblestoneWall::West::Low).ID: return 5264; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::None, false, MossyCobblestoneWall::West::None).ID: return 5265; case MossyStoneBricks::MossyStoneBricks().ID: return 3985; case MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_ZM, MovingPiston::Type::Normal).ID: return 1099; case MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_ZM, MovingPiston::Type::Sticky).ID: return 1100; case MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_XP, MovingPiston::Type::Normal).ID: return 1101; case MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_XP, MovingPiston::Type::Sticky).ID: return 1102; case MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_ZP, MovingPiston::Type::Normal).ID: return 1103; case MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_ZP, MovingPiston::Type::Sticky).ID: return 1104; case MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_XM, MovingPiston::Type::Normal).ID: return 1105; case MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_XM, MovingPiston::Type::Sticky).ID: return 1106; case MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_YP, MovingPiston::Type::Normal).ID: return 1107; case MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_YP, MovingPiston::Type::Sticky).ID: return 1108; case MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_YM, MovingPiston::Type::Normal).ID: return 1109; case MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_YM, MovingPiston::Type::Sticky).ID: return 1110; case MushroomStem::MushroomStem(true, true, true, true, true, true).ID: return 4116; case MushroomStem::MushroomStem(true, true, true, true, true, false).ID: return 4117; case MushroomStem::MushroomStem(true, true, true, true, false, true).ID: return 4118; case MushroomStem::MushroomStem(true, true, true, true, false, false).ID: return 4119; case MushroomStem::MushroomStem(true, true, true, false, true, true).ID: return 4120; case MushroomStem::MushroomStem(true, true, true, false, true, false).ID: return 4121; case MushroomStem::MushroomStem(true, true, true, false, false, true).ID: return 4122; case MushroomStem::MushroomStem(true, true, true, false, false, false).ID: return 4123; case MushroomStem::MushroomStem(true, true, false, true, true, true).ID: return 4124; case MushroomStem::MushroomStem(true, true, false, true, true, false).ID: return 4125; case MushroomStem::MushroomStem(true, true, false, true, false, true).ID: return 4126; case MushroomStem::MushroomStem(true, true, false, true, false, false).ID: return 4127; case MushroomStem::MushroomStem(true, true, false, false, true, true).ID: return 4128; case MushroomStem::MushroomStem(true, true, false, false, true, false).ID: return 4129; case MushroomStem::MushroomStem(true, true, false, false, false, true).ID: return 4130; case MushroomStem::MushroomStem(true, true, false, false, false, false).ID: return 4131; case MushroomStem::MushroomStem(true, false, true, true, true, true).ID: return 4132; case MushroomStem::MushroomStem(true, false, true, true, true, false).ID: return 4133; case MushroomStem::MushroomStem(true, false, true, true, false, true).ID: return 4134; case MushroomStem::MushroomStem(true, false, true, true, false, false).ID: return 4135; case MushroomStem::MushroomStem(true, false, true, false, true, true).ID: return 4136; case MushroomStem::MushroomStem(true, false, true, false, true, false).ID: return 4137; case MushroomStem::MushroomStem(true, false, true, false, false, true).ID: return 4138; case MushroomStem::MushroomStem(true, false, true, false, false, false).ID: return 4139; case MushroomStem::MushroomStem(true, false, false, true, true, true).ID: return 4140; case MushroomStem::MushroomStem(true, false, false, true, true, false).ID: return 4141; case MushroomStem::MushroomStem(true, false, false, true, false, true).ID: return 4142; case MushroomStem::MushroomStem(true, false, false, true, false, false).ID: return 4143; case MushroomStem::MushroomStem(true, false, false, false, true, true).ID: return 4144; case MushroomStem::MushroomStem(true, false, false, false, true, false).ID: return 4145; case MushroomStem::MushroomStem(true, false, false, false, false, true).ID: return 4146; case MushroomStem::MushroomStem(true, false, false, false, false, false).ID: return 4147; case MushroomStem::MushroomStem(false, true, true, true, true, true).ID: return 4148; case MushroomStem::MushroomStem(false, true, true, true, true, false).ID: return 4149; case MushroomStem::MushroomStem(false, true, true, true, false, true).ID: return 4150; case MushroomStem::MushroomStem(false, true, true, true, false, false).ID: return 4151; case MushroomStem::MushroomStem(false, true, true, false, true, true).ID: return 4152; case MushroomStem::MushroomStem(false, true, true, false, true, false).ID: return 4153; case MushroomStem::MushroomStem(false, true, true, false, false, true).ID: return 4154; case MushroomStem::MushroomStem(false, true, true, false, false, false).ID: return 4155; case MushroomStem::MushroomStem(false, true, false, true, true, true).ID: return 4156; case MushroomStem::MushroomStem(false, true, false, true, true, false).ID: return 4157; case MushroomStem::MushroomStem(false, true, false, true, false, true).ID: return 4158; case MushroomStem::MushroomStem(false, true, false, true, false, false).ID: return 4159; case MushroomStem::MushroomStem(false, true, false, false, true, true).ID: return 4160; case MushroomStem::MushroomStem(false, true, false, false, true, false).ID: return 4161; case MushroomStem::MushroomStem(false, true, false, false, false, true).ID: return 4162; case MushroomStem::MushroomStem(false, true, false, false, false, false).ID: return 4163; case MushroomStem::MushroomStem(false, false, true, true, true, true).ID: return 4164; case MushroomStem::MushroomStem(false, false, true, true, true, false).ID: return 4165; case MushroomStem::MushroomStem(false, false, true, true, false, true).ID: return 4166; case MushroomStem::MushroomStem(false, false, true, true, false, false).ID: return 4167; case MushroomStem::MushroomStem(false, false, true, false, true, true).ID: return 4168; case MushroomStem::MushroomStem(false, false, true, false, true, false).ID: return 4169; case MushroomStem::MushroomStem(false, false, true, false, false, true).ID: return 4170; case MushroomStem::MushroomStem(false, false, true, false, false, false).ID: return 4171; case MushroomStem::MushroomStem(false, false, false, true, true, true).ID: return 4172; case MushroomStem::MushroomStem(false, false, false, true, true, false).ID: return 4173; case MushroomStem::MushroomStem(false, false, false, true, false, true).ID: return 4174; case MushroomStem::MushroomStem(false, false, false, true, false, false).ID: return 4175; case MushroomStem::MushroomStem(false, false, false, false, true, true).ID: return 4176; case MushroomStem::MushroomStem(false, false, false, false, true, false).ID: return 4177; case MushroomStem::MushroomStem(false, false, false, false, false, true).ID: return 4178; case MushroomStem::MushroomStem(false, false, false, false, false, false).ID: return 4179; case Mycelium::Mycelium(true).ID: return 4493; case Mycelium::Mycelium(false).ID: return 4494; case NetherBrickFence::NetherBrickFence(true, true, true, true).ID: return 4499; case NetherBrickFence::NetherBrickFence(true, true, true, false).ID: return 4500; case NetherBrickFence::NetherBrickFence(true, true, false, true).ID: return 4503; case NetherBrickFence::NetherBrickFence(true, true, false, false).ID: return 4504; case NetherBrickFence::NetherBrickFence(true, false, true, true).ID: return 4507; case NetherBrickFence::NetherBrickFence(true, false, true, false).ID: return 4508; case NetherBrickFence::NetherBrickFence(true, false, false, true).ID: return 4511; case NetherBrickFence::NetherBrickFence(true, false, false, false).ID: return 4512; case NetherBrickFence::NetherBrickFence(false, true, true, true).ID: return 4515; case NetherBrickFence::NetherBrickFence(false, true, true, false).ID: return 4516; case NetherBrickFence::NetherBrickFence(false, true, false, true).ID: return 4519; case NetherBrickFence::NetherBrickFence(false, true, false, false).ID: return 4520; case NetherBrickFence::NetherBrickFence(false, false, true, true).ID: return 4523; case NetherBrickFence::NetherBrickFence(false, false, true, false).ID: return 4524; case NetherBrickFence::NetherBrickFence(false, false, false, true).ID: return 4527; case NetherBrickFence::NetherBrickFence(false, false, false, false).ID: return 4528; case NetherBrickSlab::NetherBrickSlab(NetherBrickSlab::Type::Top).ID: return 7331; case NetherBrickSlab::NetherBrickSlab(NetherBrickSlab::Type::Bottom).ID: return 7333; case NetherBrickSlab::NetherBrickSlab(NetherBrickSlab::Type::Double).ID: return 7335; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::Straight).ID: return 4530; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::InnerLeft).ID: return 4532; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::InnerRight).ID: return 4534; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::OuterLeft).ID: return 4536; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::OuterRight).ID: return 4538; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::Straight).ID: return 4540; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::InnerLeft).ID: return 4542; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::InnerRight).ID: return 4544; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::OuterLeft).ID: return 4546; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::OuterRight).ID: return 4548; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::Straight).ID: return 4550; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::InnerLeft).ID: return 4552; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::InnerRight).ID: return 4554; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::OuterLeft).ID: return 4556; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::OuterRight).ID: return 4558; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::Straight).ID: return 4560; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::InnerLeft).ID: return 4562; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::InnerRight).ID: return 4564; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::OuterLeft).ID: return 4566; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::OuterRight).ID: return 4568; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XM, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::Straight).ID: return 4570; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XM, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::InnerLeft).ID: return 4572; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XM, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::InnerRight).ID: return 4574; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XM, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::OuterLeft).ID: return 4576; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XM, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::OuterRight).ID: return 4578; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XM, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::Straight).ID: return 4580; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XM, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::InnerLeft).ID: return 4582; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XM, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::InnerRight).ID: return 4584; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XM, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::OuterLeft).ID: return 4586; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XM, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::OuterRight).ID: return 4588; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XP, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::Straight).ID: return 4590; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XP, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::InnerLeft).ID: return 4592; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XP, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::InnerRight).ID: return 4594; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XP, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::OuterLeft).ID: return 4596; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XP, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::OuterRight).ID: return 4598; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XP, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::Straight).ID: return 4600; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XP, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::InnerLeft).ID: return 4602; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XP, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::InnerRight).ID: return 4604; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XP, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::OuterLeft).ID: return 4606; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XP, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::OuterRight).ID: return 4608; case NetherBricks::NetherBricks().ID: return 4496; case NetherPortal::NetherPortal(NetherPortal::Axis::X).ID: return 3497; case NetherPortal::NetherPortal(NetherPortal::Axis::Z).ID: return 3498; case NetherQuartzOre::NetherQuartzOre().ID: return 5685; case NetherWart::NetherWart(0).ID: return 4609; case NetherWart::NetherWart(1).ID: return 4610; case NetherWart::NetherWart(2).ID: return 4611; case NetherWart::NetherWart(3).ID: return 4612; case NetherWartBlock::NetherWartBlock().ID: return 8194; case Netherrack::Netherrack().ID: return 3494; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 0, true).ID: return 248; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 0, false).ID: return 249; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 1, true).ID: return 250; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 1, false).ID: return 251; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 2, true).ID: return 252; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 2, false).ID: return 253; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 3, true).ID: return 254; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 3, false).ID: return 255; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 4, true).ID: return 256; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 4, false).ID: return 257; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 5, true).ID: return 258; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 5, false).ID: return 259; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 6, true).ID: return 260; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 6, false).ID: return 261; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 7, true).ID: return 262; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 7, false).ID: return 263; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 8, true).ID: return 264; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 8, false).ID: return 265; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 9, true).ID: return 266; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 9, false).ID: return 267; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 10, true).ID: return 268; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 10, false).ID: return 269; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 11, true).ID: return 270; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 11, false).ID: return 271; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 12, true).ID: return 272; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 12, false).ID: return 273; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 13, true).ID: return 274; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 13, false).ID: return 275; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 14, true).ID: return 276; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 14, false).ID: return 277; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 15, true).ID: return 278; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 15, false).ID: return 279; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 16, true).ID: return 280; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 16, false).ID: return 281; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 17, true).ID: return 282; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 17, false).ID: return 283; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 18, true).ID: return 284; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 18, false).ID: return 285; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 19, true).ID: return 286; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 19, false).ID: return 287; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 20, true).ID: return 288; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 20, false).ID: return 289; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 21, true).ID: return 290; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 21, false).ID: return 291; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 22, true).ID: return 292; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 22, false).ID: return 293; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 23, true).ID: return 294; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 23, false).ID: return 295; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 24, true).ID: return 296; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 24, false).ID: return 297; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 0, true).ID: return 298; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 0, false).ID: return 299; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 1, true).ID: return 300; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 1, false).ID: return 301; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 2, true).ID: return 302; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 2, false).ID: return 303; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 3, true).ID: return 304; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 3, false).ID: return 305; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 4, true).ID: return 306; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 4, false).ID: return 307; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 5, true).ID: return 308; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 5, false).ID: return 309; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 6, true).ID: return 310; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 6, false).ID: return 311; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 7, true).ID: return 312; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 7, false).ID: return 313; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 8, true).ID: return 314; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 8, false).ID: return 315; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 9, true).ID: return 316; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 9, false).ID: return 317; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 10, true).ID: return 318; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 10, false).ID: return 319; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 11, true).ID: return 320; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 11, false).ID: return 321; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 12, true).ID: return 322; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 12, false).ID: return 323; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 13, true).ID: return 324; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 13, false).ID: return 325; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 14, true).ID: return 326; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 14, false).ID: return 327; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 15, true).ID: return 328; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 15, false).ID: return 329; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 16, true).ID: return 330; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 16, false).ID: return 331; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 17, true).ID: return 332; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 17, false).ID: return 333; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 18, true).ID: return 334; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 18, false).ID: return 335; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 19, true).ID: return 336; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 19, false).ID: return 337; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 20, true).ID: return 338; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 20, false).ID: return 339; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 21, true).ID: return 340; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 21, false).ID: return 341; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 22, true).ID: return 342; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 22, false).ID: return 343; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 23, true).ID: return 344; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 23, false).ID: return 345; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 24, true).ID: return 346; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 24, false).ID: return 347; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 0, true).ID: return 348; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 0, false).ID: return 349; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 1, true).ID: return 350; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 1, false).ID: return 351; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 2, true).ID: return 352; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 2, false).ID: return 353; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 3, true).ID: return 354; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 3, false).ID: return 355; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 4, true).ID: return 356; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 4, false).ID: return 357; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 5, true).ID: return 358; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 5, false).ID: return 359; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 6, true).ID: return 360; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 6, false).ID: return 361; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 7, true).ID: return 362; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 7, false).ID: return 363; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 8, true).ID: return 364; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 8, false).ID: return 365; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 9, true).ID: return 366; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 9, false).ID: return 367; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 10, true).ID: return 368; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 10, false).ID: return 369; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 11, true).ID: return 370; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 11, false).ID: return 371; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 12, true).ID: return 372; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 12, false).ID: return 373; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 13, true).ID: return 374; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 13, false).ID: return 375; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 14, true).ID: return 376; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 14, false).ID: return 377; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 15, true).ID: return 378; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 15, false).ID: return 379; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 16, true).ID: return 380; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 16, false).ID: return 381; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 17, true).ID: return 382; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 17, false).ID: return 383; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 18, true).ID: return 384; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 18, false).ID: return 385; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 19, true).ID: return 386; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 19, false).ID: return 387; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 20, true).ID: return 388; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 20, false).ID: return 389; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 21, true).ID: return 390; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 21, false).ID: return 391; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 22, true).ID: return 392; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 22, false).ID: return 393; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 23, true).ID: return 394; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 23, false).ID: return 395; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 24, true).ID: return 396; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 24, false).ID: return 397; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 0, true).ID: return 398; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 0, false).ID: return 399; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 1, true).ID: return 400; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 1, false).ID: return 401; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 2, true).ID: return 402; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 2, false).ID: return 403; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 3, true).ID: return 404; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 3, false).ID: return 405; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 4, true).ID: return 406; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 4, false).ID: return 407; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 5, true).ID: return 408; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 5, false).ID: return 409; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 6, true).ID: return 410; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 6, false).ID: return 411; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 7, true).ID: return 412; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 7, false).ID: return 413; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 8, true).ID: return 414; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 8, false).ID: return 415; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 9, true).ID: return 416; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 9, false).ID: return 417; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 10, true).ID: return 418; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 10, false).ID: return 419; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 11, true).ID: return 420; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 11, false).ID: return 421; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 12, true).ID: return 422; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 12, false).ID: return 423; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 13, true).ID: return 424; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 13, false).ID: return 425; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 14, true).ID: return 426; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 14, false).ID: return 427; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 15, true).ID: return 428; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 15, false).ID: return 429; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 16, true).ID: return 430; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 16, false).ID: return 431; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 17, true).ID: return 432; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 17, false).ID: return 433; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 18, true).ID: return 434; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 18, false).ID: return 435; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 19, true).ID: return 436; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 19, false).ID: return 437; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 20, true).ID: return 438; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 20, false).ID: return 439; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 21, true).ID: return 440; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 21, false).ID: return 441; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 22, true).ID: return 442; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 22, false).ID: return 443; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 23, true).ID: return 444; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 23, false).ID: return 445; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 24, true).ID: return 446; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 24, false).ID: return 447; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 0, true).ID: return 448; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 0, false).ID: return 449; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 1, true).ID: return 450; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 1, false).ID: return 451; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 2, true).ID: return 452; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 2, false).ID: return 453; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 3, true).ID: return 454; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 3, false).ID: return 455; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 4, true).ID: return 456; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 4, false).ID: return 457; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 5, true).ID: return 458; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 5, false).ID: return 459; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 6, true).ID: return 460; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 6, false).ID: return 461; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 7, true).ID: return 462; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 7, false).ID: return 463; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 8, true).ID: return 464; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 8, false).ID: return 465; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 9, true).ID: return 466; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 9, false).ID: return 467; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 10, true).ID: return 468; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 10, false).ID: return 469; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 11, true).ID: return 470; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 11, false).ID: return 471; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 12, true).ID: return 472; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 12, false).ID: return 473; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 13, true).ID: return 474; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 13, false).ID: return 475; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 14, true).ID: return 476; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 14, false).ID: return 477; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 15, true).ID: return 478; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 15, false).ID: return 479; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 16, true).ID: return 480; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 16, false).ID: return 481; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 17, true).ID: return 482; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 17, false).ID: return 483; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 18, true).ID: return 484; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 18, false).ID: return 485; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 19, true).ID: return 486; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 19, false).ID: return 487; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 20, true).ID: return 488; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 20, false).ID: return 489; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 21, true).ID: return 490; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 21, false).ID: return 491; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 22, true).ID: return 492; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 22, false).ID: return 493; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 23, true).ID: return 494; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 23, false).ID: return 495; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 24, true).ID: return 496; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 24, false).ID: return 497; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 0, true).ID: return 498; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 0, false).ID: return 499; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 1, true).ID: return 500; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 1, false).ID: return 501; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 2, true).ID: return 502; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 2, false).ID: return 503; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 3, true).ID: return 504; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 3, false).ID: return 505; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 4, true).ID: return 506; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 4, false).ID: return 507; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 5, true).ID: return 508; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 5, false).ID: return 509; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 6, true).ID: return 510; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 6, false).ID: return 511; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 7, true).ID: return 512; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 7, false).ID: return 513; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 8, true).ID: return 514; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 8, false).ID: return 515; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 9, true).ID: return 516; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 9, false).ID: return 517; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 10, true).ID: return 518; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 10, false).ID: return 519; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 11, true).ID: return 520; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 11, false).ID: return 521; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 12, true).ID: return 522; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 12, false).ID: return 523; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 13, true).ID: return 524; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 13, false).ID: return 525; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 14, true).ID: return 526; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 14, false).ID: return 527; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 15, true).ID: return 528; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 15, false).ID: return 529; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 16, true).ID: return 530; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 16, false).ID: return 531; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 17, true).ID: return 532; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 17, false).ID: return 533; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 18, true).ID: return 534; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 18, false).ID: return 535; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 19, true).ID: return 536; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 19, false).ID: return 537; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 20, true).ID: return 538; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 20, false).ID: return 539; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 21, true).ID: return 540; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 21, false).ID: return 541; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 22, true).ID: return 542; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 22, false).ID: return 543; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 23, true).ID: return 544; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 23, false).ID: return 545; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 24, true).ID: return 546; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 24, false).ID: return 547; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 0, true).ID: return 548; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 0, false).ID: return 549; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 1, true).ID: return 550; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 1, false).ID: return 551; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 2, true).ID: return 552; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 2, false).ID: return 553; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 3, true).ID: return 554; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 3, false).ID: return 555; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 4, true).ID: return 556; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 4, false).ID: return 557; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 5, true).ID: return 558; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 5, false).ID: return 559; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 6, true).ID: return 560; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 6, false).ID: return 561; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 7, true).ID: return 562; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 7, false).ID: return 563; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 8, true).ID: return 564; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 8, false).ID: return 565; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 9, true).ID: return 566; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 9, false).ID: return 567; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 10, true).ID: return 568; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 10, false).ID: return 569; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 11, true).ID: return 570; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 11, false).ID: return 571; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 12, true).ID: return 572; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 12, false).ID: return 573; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 13, true).ID: return 574; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 13, false).ID: return 575; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 14, true).ID: return 576; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 14, false).ID: return 577; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 15, true).ID: return 578; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 15, false).ID: return 579; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 16, true).ID: return 580; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 16, false).ID: return 581; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 17, true).ID: return 582; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 17, false).ID: return 583; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 18, true).ID: return 584; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 18, false).ID: return 585; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 19, true).ID: return 586; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 19, false).ID: return 587; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 20, true).ID: return 588; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 20, false).ID: return 589; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 21, true).ID: return 590; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 21, false).ID: return 591; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 22, true).ID: return 592; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 22, false).ID: return 593; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 23, true).ID: return 594; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 23, false).ID: return 595; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 24, true).ID: return 596; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 24, false).ID: return 597; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 0, true).ID: return 598; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 0, false).ID: return 599; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 1, true).ID: return 600; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 1, false).ID: return 601; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 2, true).ID: return 602; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 2, false).ID: return 603; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 3, true).ID: return 604; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 3, false).ID: return 605; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 4, true).ID: return 606; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 4, false).ID: return 607; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 5, true).ID: return 608; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 5, false).ID: return 609; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 6, true).ID: return 610; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 6, false).ID: return 611; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 7, true).ID: return 612; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 7, false).ID: return 613; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 8, true).ID: return 614; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 8, false).ID: return 615; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 9, true).ID: return 616; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 9, false).ID: return 617; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 10, true).ID: return 618; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 10, false).ID: return 619; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 11, true).ID: return 620; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 11, false).ID: return 621; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 12, true).ID: return 622; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 12, false).ID: return 623; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 13, true).ID: return 624; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 13, false).ID: return 625; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 14, true).ID: return 626; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 14, false).ID: return 627; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 15, true).ID: return 628; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 15, false).ID: return 629; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 16, true).ID: return 630; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 16, false).ID: return 631; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 17, true).ID: return 632; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 17, false).ID: return 633; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 18, true).ID: return 634; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 18, false).ID: return 635; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 19, true).ID: return 636; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 19, false).ID: return 637; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 20, true).ID: return 638; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 20, false).ID: return 639; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 21, true).ID: return 640; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 21, false).ID: return 641; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 22, true).ID: return 642; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 22, false).ID: return 643; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 23, true).ID: return 644; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 23, false).ID: return 645; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 24, true).ID: return 646; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 24, false).ID: return 647; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 0, true).ID: return 648; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 0, false).ID: return 649; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 1, true).ID: return 650; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 1, false).ID: return 651; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 2, true).ID: return 652; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 2, false).ID: return 653; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 3, true).ID: return 654; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 3, false).ID: return 655; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 4, true).ID: return 656; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 4, false).ID: return 657; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 5, true).ID: return 658; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 5, false).ID: return 659; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 6, true).ID: return 660; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 6, false).ID: return 661; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 7, true).ID: return 662; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 7, false).ID: return 663; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 8, true).ID: return 664; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 8, false).ID: return 665; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 9, true).ID: return 666; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 9, false).ID: return 667; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 10, true).ID: return 668; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 10, false).ID: return 669; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 11, true).ID: return 670; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 11, false).ID: return 671; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 12, true).ID: return 672; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 12, false).ID: return 673; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 13, true).ID: return 674; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 13, false).ID: return 675; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 14, true).ID: return 676; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 14, false).ID: return 677; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 15, true).ID: return 678; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 15, false).ID: return 679; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 16, true).ID: return 680; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 16, false).ID: return 681; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 17, true).ID: return 682; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 17, false).ID: return 683; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 18, true).ID: return 684; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 18, false).ID: return 685; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 19, true).ID: return 686; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 19, false).ID: return 687; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 20, true).ID: return 688; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 20, false).ID: return 689; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 21, true).ID: return 690; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 21, false).ID: return 691; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 22, true).ID: return 692; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 22, false).ID: return 693; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 23, true).ID: return 694; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 23, false).ID: return 695; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 24, true).ID: return 696; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 24, false).ID: return 697; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 0, true).ID: return 698; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 0, false).ID: return 699; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 1, true).ID: return 700; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 1, false).ID: return 701; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 2, true).ID: return 702; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 2, false).ID: return 703; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 3, true).ID: return 704; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 3, false).ID: return 705; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 4, true).ID: return 706; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 4, false).ID: return 707; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 5, true).ID: return 708; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 5, false).ID: return 709; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 6, true).ID: return 710; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 6, false).ID: return 711; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 7, true).ID: return 712; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 7, false).ID: return 713; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 8, true).ID: return 714; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 8, false).ID: return 715; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 9, true).ID: return 716; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 9, false).ID: return 717; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 10, true).ID: return 718; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 10, false).ID: return 719; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 11, true).ID: return 720; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 11, false).ID: return 721; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 12, true).ID: return 722; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 12, false).ID: return 723; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 13, true).ID: return 724; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 13, false).ID: return 725; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 14, true).ID: return 726; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 14, false).ID: return 727; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 15, true).ID: return 728; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 15, false).ID: return 729; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 16, true).ID: return 730; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 16, false).ID: return 731; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 17, true).ID: return 732; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 17, false).ID: return 733; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 18, true).ID: return 734; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 18, false).ID: return 735; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 19, true).ID: return 736; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 19, false).ID: return 737; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 20, true).ID: return 738; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 20, false).ID: return 739; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 21, true).ID: return 740; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 21, false).ID: return 741; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 22, true).ID: return 742; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 22, false).ID: return 743; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 23, true).ID: return 744; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 23, false).ID: return 745; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 24, true).ID: return 746; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 24, false).ID: return 747; case OakButton::OakButton(OakButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5304; case OakButton::OakButton(OakButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5305; case OakButton::OakButton(OakButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5306; case OakButton::OakButton(OakButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5307; case OakButton::OakButton(OakButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, true).ID: return 5308; case OakButton::OakButton(OakButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, false).ID: return 5309; case OakButton::OakButton(OakButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, true).ID: return 5310; case OakButton::OakButton(OakButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, false).ID: return 5311; case OakButton::OakButton(OakButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5312; case OakButton::OakButton(OakButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5313; case OakButton::OakButton(OakButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5314; case OakButton::OakButton(OakButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5315; case OakButton::OakButton(OakButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, true).ID: return 5316; case OakButton::OakButton(OakButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, false).ID: return 5317; case OakButton::OakButton(OakButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, true).ID: return 5318; case OakButton::OakButton(OakButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, false).ID: return 5319; case OakButton::OakButton(OakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5320; case OakButton::OakButton(OakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5321; case OakButton::OakButton(OakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5322; case OakButton::OakButton(OakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5323; case OakButton::OakButton(OakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, true).ID: return 5324; case OakButton::OakButton(OakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, false).ID: return 5325; case OakButton::OakButton(OakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, true).ID: return 5326; case OakButton::OakButton(OakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, false).ID: return 5327; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Upper, OakDoor::Hinge::Left, true, true).ID: return 3108; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Upper, OakDoor::Hinge::Left, true, false).ID: return 3109; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Upper, OakDoor::Hinge::Left, false, true).ID: return 3110; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Upper, OakDoor::Hinge::Left, false, false).ID: return 3111; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Upper, OakDoor::Hinge::Right, true, true).ID: return 3112; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Upper, OakDoor::Hinge::Right, true, false).ID: return 3113; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Upper, OakDoor::Hinge::Right, false, true).ID: return 3114; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Upper, OakDoor::Hinge::Right, false, false).ID: return 3115; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Lower, OakDoor::Hinge::Left, true, true).ID: return 3116; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Lower, OakDoor::Hinge::Left, true, false).ID: return 3117; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Lower, OakDoor::Hinge::Left, false, true).ID: return 3118; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Lower, OakDoor::Hinge::Left, false, false).ID: return 3119; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Lower, OakDoor::Hinge::Right, true, true).ID: return 3120; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Lower, OakDoor::Hinge::Right, true, false).ID: return 3121; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Lower, OakDoor::Hinge::Right, false, true).ID: return 3122; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Lower, OakDoor::Hinge::Right, false, false).ID: return 3123; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Upper, OakDoor::Hinge::Left, true, true).ID: return 3124; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Upper, OakDoor::Hinge::Left, true, false).ID: return 3125; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Upper, OakDoor::Hinge::Left, false, true).ID: return 3126; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Upper, OakDoor::Hinge::Left, false, false).ID: return 3127; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Upper, OakDoor::Hinge::Right, true, true).ID: return 3128; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Upper, OakDoor::Hinge::Right, true, false).ID: return 3129; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Upper, OakDoor::Hinge::Right, false, true).ID: return 3130; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Upper, OakDoor::Hinge::Right, false, false).ID: return 3131; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Lower, OakDoor::Hinge::Left, true, true).ID: return 3132; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Lower, OakDoor::Hinge::Left, true, false).ID: return 3133; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Lower, OakDoor::Hinge::Left, false, true).ID: return 3134; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Lower, OakDoor::Hinge::Left, false, false).ID: return 3135; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Lower, OakDoor::Hinge::Right, true, true).ID: return 3136; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Lower, OakDoor::Hinge::Right, true, false).ID: return 3137; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Lower, OakDoor::Hinge::Right, false, true).ID: return 3138; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Lower, OakDoor::Hinge::Right, false, false).ID: return 3139; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Upper, OakDoor::Hinge::Left, true, true).ID: return 3140; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Upper, OakDoor::Hinge::Left, true, false).ID: return 3141; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Upper, OakDoor::Hinge::Left, false, true).ID: return 3142; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Upper, OakDoor::Hinge::Left, false, false).ID: return 3143; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Upper, OakDoor::Hinge::Right, true, true).ID: return 3144; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Upper, OakDoor::Hinge::Right, true, false).ID: return 3145; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Upper, OakDoor::Hinge::Right, false, true).ID: return 3146; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Upper, OakDoor::Hinge::Right, false, false).ID: return 3147; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Lower, OakDoor::Hinge::Left, true, true).ID: return 3148; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Lower, OakDoor::Hinge::Left, true, false).ID: return 3149; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Lower, OakDoor::Hinge::Left, false, true).ID: return 3150; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Lower, OakDoor::Hinge::Left, false, false).ID: return 3151; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Lower, OakDoor::Hinge::Right, true, true).ID: return 3152; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Lower, OakDoor::Hinge::Right, true, false).ID: return 3153; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Lower, OakDoor::Hinge::Right, false, true).ID: return 3154; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Lower, OakDoor::Hinge::Right, false, false).ID: return 3155; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Upper, OakDoor::Hinge::Left, true, true).ID: return 3156; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Upper, OakDoor::Hinge::Left, true, false).ID: return 3157; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Upper, OakDoor::Hinge::Left, false, true).ID: return 3158; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Upper, OakDoor::Hinge::Left, false, false).ID: return 3159; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Upper, OakDoor::Hinge::Right, true, true).ID: return 3160; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Upper, OakDoor::Hinge::Right, true, false).ID: return 3161; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Upper, OakDoor::Hinge::Right, false, true).ID: return 3162; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Upper, OakDoor::Hinge::Right, false, false).ID: return 3163; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Lower, OakDoor::Hinge::Left, true, true).ID: return 3164; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Lower, OakDoor::Hinge::Left, true, false).ID: return 3165; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Lower, OakDoor::Hinge::Left, false, true).ID: return 3166; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Lower, OakDoor::Hinge::Left, false, false).ID: return 3167; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Lower, OakDoor::Hinge::Right, true, true).ID: return 3168; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Lower, OakDoor::Hinge::Right, true, false).ID: return 3169; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Lower, OakDoor::Hinge::Right, false, true).ID: return 3170; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Lower, OakDoor::Hinge::Right, false, false).ID: return 3171; case OakFence::OakFence(true, true, true, true).ID: return 3463; case OakFence::OakFence(true, true, true, false).ID: return 3464; case OakFence::OakFence(true, true, false, true).ID: return 3467; case OakFence::OakFence(true, true, false, false).ID: return 3468; case OakFence::OakFence(true, false, true, true).ID: return 3471; case OakFence::OakFence(true, false, true, false).ID: return 3472; case OakFence::OakFence(true, false, false, true).ID: return 3475; case OakFence::OakFence(true, false, false, false).ID: return 3476; case OakFence::OakFence(false, true, true, true).ID: return 3479; case OakFence::OakFence(false, true, true, false).ID: return 3480; case OakFence::OakFence(false, true, false, true).ID: return 3483; case OakFence::OakFence(false, true, false, false).ID: return 3484; case OakFence::OakFence(false, false, true, true).ID: return 3487; case OakFence::OakFence(false, false, true, false).ID: return 3488; case OakFence::OakFence(false, false, false, true).ID: return 3491; case OakFence::OakFence(false, false, false, false).ID: return 3492; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZM, true, true, true).ID: return 4301; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZM, true, true, false).ID: return 4302; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZM, true, false, true).ID: return 4303; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZM, true, false, false).ID: return 4304; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, true).ID: return 4305; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, false).ID: return 4306; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, true).ID: return 4307; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, false).ID: return 4308; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZP, true, true, true).ID: return 4309; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZP, true, true, false).ID: return 4310; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZP, true, false, true).ID: return 4311; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZP, true, false, false).ID: return 4312; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, true).ID: return 4313; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, false).ID: return 4314; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, true).ID: return 4315; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, false).ID: return 4316; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XM, true, true, true).ID: return 4317; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XM, true, true, false).ID: return 4318; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XM, true, false, true).ID: return 4319; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XM, true, false, false).ID: return 4320; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, true).ID: return 4321; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, false).ID: return 4322; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, true).ID: return 4323; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, false).ID: return 4324; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XP, true, true, true).ID: return 4325; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XP, true, true, false).ID: return 4326; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XP, true, false, true).ID: return 4327; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XP, true, false, false).ID: return 4328; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, true).ID: return 4329; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, false).ID: return 4330; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, true).ID: return 4331; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, false).ID: return 4332; case OakLeaves::OakLeaves(1, true).ID: return 144; case OakLeaves::OakLeaves(1, false).ID: return 145; case OakLeaves::OakLeaves(2, true).ID: return 146; case OakLeaves::OakLeaves(2, false).ID: return 147; case OakLeaves::OakLeaves(3, true).ID: return 148; case OakLeaves::OakLeaves(3, false).ID: return 149; case OakLeaves::OakLeaves(4, true).ID: return 150; case OakLeaves::OakLeaves(4, false).ID: return 151; case OakLeaves::OakLeaves(5, true).ID: return 152; case OakLeaves::OakLeaves(5, false).ID: return 153; case OakLeaves::OakLeaves(6, true).ID: return 154; case OakLeaves::OakLeaves(6, false).ID: return 155; case OakLeaves::OakLeaves(7, true).ID: return 156; case OakLeaves::OakLeaves(7, false).ID: return 157; case OakLog::OakLog(OakLog::Axis::X).ID: return 72; case OakLog::OakLog(OakLog::Axis::Y).ID: return 73; case OakLog::OakLog(OakLog::Axis::Z).ID: return 74; case OakPlanks::OakPlanks().ID: return 15; case OakPressurePlate::OakPressurePlate(true).ID: return 3368; case OakPressurePlate::OakPressurePlate(false).ID: return 3369; case OakSapling::OakSapling(0).ID: return 21; case OakSapling::OakSapling(1).ID: return 22; case OakSlab::OakSlab(OakSlab::Type::Top).ID: return 7259; case OakSlab::OakSlab(OakSlab::Type::Bottom).ID: return 7261; case OakSlab::OakSlab(OakSlab::Type::Double).ID: return 7263; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZM, OakStairs::Half::Top, OakStairs::Shape::Straight).ID: return 1650; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZM, OakStairs::Half::Top, OakStairs::Shape::InnerLeft).ID: return 1652; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZM, OakStairs::Half::Top, OakStairs::Shape::InnerRight).ID: return 1654; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZM, OakStairs::Half::Top, OakStairs::Shape::OuterLeft).ID: return 1656; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZM, OakStairs::Half::Top, OakStairs::Shape::OuterRight).ID: return 1658; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZM, OakStairs::Half::Bottom, OakStairs::Shape::Straight).ID: return 1660; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZM, OakStairs::Half::Bottom, OakStairs::Shape::InnerLeft).ID: return 1662; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZM, OakStairs::Half::Bottom, OakStairs::Shape::InnerRight).ID: return 1664; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZM, OakStairs::Half::Bottom, OakStairs::Shape::OuterLeft).ID: return 1666; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZM, OakStairs::Half::Bottom, OakStairs::Shape::OuterRight).ID: return 1668; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZP, OakStairs::Half::Top, OakStairs::Shape::Straight).ID: return 1670; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZP, OakStairs::Half::Top, OakStairs::Shape::InnerLeft).ID: return 1672; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZP, OakStairs::Half::Top, OakStairs::Shape::InnerRight).ID: return 1674; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZP, OakStairs::Half::Top, OakStairs::Shape::OuterLeft).ID: return 1676; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZP, OakStairs::Half::Top, OakStairs::Shape::OuterRight).ID: return 1678; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZP, OakStairs::Half::Bottom, OakStairs::Shape::Straight).ID: return 1680; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZP, OakStairs::Half::Bottom, OakStairs::Shape::InnerLeft).ID: return 1682; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZP, OakStairs::Half::Bottom, OakStairs::Shape::InnerRight).ID: return 1684; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZP, OakStairs::Half::Bottom, OakStairs::Shape::OuterLeft).ID: return 1686; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZP, OakStairs::Half::Bottom, OakStairs::Shape::OuterRight).ID: return 1688; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XM, OakStairs::Half::Top, OakStairs::Shape::Straight).ID: return 1690; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XM, OakStairs::Half::Top, OakStairs::Shape::InnerLeft).ID: return 1692; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XM, OakStairs::Half::Top, OakStairs::Shape::InnerRight).ID: return 1694; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XM, OakStairs::Half::Top, OakStairs::Shape::OuterLeft).ID: return 1696; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XM, OakStairs::Half::Top, OakStairs::Shape::OuterRight).ID: return 1698; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XM, OakStairs::Half::Bottom, OakStairs::Shape::Straight).ID: return 1700; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XM, OakStairs::Half::Bottom, OakStairs::Shape::InnerLeft).ID: return 1702; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XM, OakStairs::Half::Bottom, OakStairs::Shape::InnerRight).ID: return 1704; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XM, OakStairs::Half::Bottom, OakStairs::Shape::OuterLeft).ID: return 1706; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XM, OakStairs::Half::Bottom, OakStairs::Shape::OuterRight).ID: return 1708; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XP, OakStairs::Half::Top, OakStairs::Shape::Straight).ID: return 1710; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XP, OakStairs::Half::Top, OakStairs::Shape::InnerLeft).ID: return 1712; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XP, OakStairs::Half::Top, OakStairs::Shape::InnerRight).ID: return 1714; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XP, OakStairs::Half::Top, OakStairs::Shape::OuterLeft).ID: return 1716; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XP, OakStairs::Half::Top, OakStairs::Shape::OuterRight).ID: return 1718; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XP, OakStairs::Half::Bottom, OakStairs::Shape::Straight).ID: return 1720; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XP, OakStairs::Half::Bottom, OakStairs::Shape::InnerLeft).ID: return 1722; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XP, OakStairs::Half::Bottom, OakStairs::Shape::InnerRight).ID: return 1724; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XP, OakStairs::Half::Bottom, OakStairs::Shape::OuterLeft).ID: return 1726; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XP, OakStairs::Half::Bottom, OakStairs::Shape::OuterRight).ID: return 1728; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZM, OakTrapdoor::Half::Top, true, true).ID: return 3595; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZM, OakTrapdoor::Half::Top, true, false).ID: return 3597; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZM, OakTrapdoor::Half::Top, false, true).ID: return 3599; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZM, OakTrapdoor::Half::Top, false, false).ID: return 3601; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZM, OakTrapdoor::Half::Bottom, true, true).ID: return 3603; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZM, OakTrapdoor::Half::Bottom, true, false).ID: return 3605; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZM, OakTrapdoor::Half::Bottom, false, true).ID: return 3607; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZM, OakTrapdoor::Half::Bottom, false, false).ID: return 3609; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZP, OakTrapdoor::Half::Top, true, true).ID: return 3611; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZP, OakTrapdoor::Half::Top, true, false).ID: return 3613; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZP, OakTrapdoor::Half::Top, false, true).ID: return 3615; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZP, OakTrapdoor::Half::Top, false, false).ID: return 3617; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZP, OakTrapdoor::Half::Bottom, true, true).ID: return 3619; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZP, OakTrapdoor::Half::Bottom, true, false).ID: return 3621; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZP, OakTrapdoor::Half::Bottom, false, true).ID: return 3623; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZP, OakTrapdoor::Half::Bottom, false, false).ID: return 3625; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XM, OakTrapdoor::Half::Top, true, true).ID: return 3627; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XM, OakTrapdoor::Half::Top, true, false).ID: return 3629; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XM, OakTrapdoor::Half::Top, false, true).ID: return 3631; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XM, OakTrapdoor::Half::Top, false, false).ID: return 3633; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XM, OakTrapdoor::Half::Bottom, true, true).ID: return 3635; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XM, OakTrapdoor::Half::Bottom, true, false).ID: return 3637; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XM, OakTrapdoor::Half::Bottom, false, true).ID: return 3639; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XM, OakTrapdoor::Half::Bottom, false, false).ID: return 3641; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XP, OakTrapdoor::Half::Top, true, true).ID: return 3643; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XP, OakTrapdoor::Half::Top, true, false).ID: return 3645; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XP, OakTrapdoor::Half::Top, false, true).ID: return 3647; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XP, OakTrapdoor::Half::Top, false, false).ID: return 3649; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XP, OakTrapdoor::Half::Bottom, true, true).ID: return 3651; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XP, OakTrapdoor::Half::Bottom, true, false).ID: return 3653; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XP, OakTrapdoor::Half::Bottom, false, true).ID: return 3655; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XP, OakTrapdoor::Half::Bottom, false, false).ID: return 3657; case OakWood::OakWood(OakWood::Axis::X).ID: return 108; case OakWood::OakWood(OakWood::Axis::Y).ID: return 109; case OakWood::OakWood(OakWood::Axis::Z).ID: return 110; case Observer::Observer(eBlockFace::BLOCK_FACE_ZM, true).ID: return 8200; case Observer::Observer(eBlockFace::BLOCK_FACE_ZM, false).ID: return 8201; case Observer::Observer(eBlockFace::BLOCK_FACE_XP, true).ID: return 8202; case Observer::Observer(eBlockFace::BLOCK_FACE_XP, false).ID: return 8203; case Observer::Observer(eBlockFace::BLOCK_FACE_ZP, true).ID: return 8204; case Observer::Observer(eBlockFace::BLOCK_FACE_ZP, false).ID: return 8205; case Observer::Observer(eBlockFace::BLOCK_FACE_XM, true).ID: return 8206; case Observer::Observer(eBlockFace::BLOCK_FACE_XM, false).ID: return 8207; case Observer::Observer(eBlockFace::BLOCK_FACE_YP, true).ID: return 8208; case Observer::Observer(eBlockFace::BLOCK_FACE_YP, false).ID: return 8209; case Observer::Observer(eBlockFace::BLOCK_FACE_YM, true).ID: return 8210; case Observer::Observer(eBlockFace::BLOCK_FACE_YM, false).ID: return 8211; case Obsidian::Obsidian().ID: return 1130; case OrangeBanner::OrangeBanner(0).ID: return 6871; case OrangeBanner::OrangeBanner(1).ID: return 6872; case OrangeBanner::OrangeBanner(2).ID: return 6873; case OrangeBanner::OrangeBanner(3).ID: return 6874; case OrangeBanner::OrangeBanner(4).ID: return 6875; case OrangeBanner::OrangeBanner(5).ID: return 6876; case OrangeBanner::OrangeBanner(6).ID: return 6877; case OrangeBanner::OrangeBanner(7).ID: return 6878; case OrangeBanner::OrangeBanner(8).ID: return 6879; case OrangeBanner::OrangeBanner(9).ID: return 6880; case OrangeBanner::OrangeBanner(10).ID: return 6881; case OrangeBanner::OrangeBanner(11).ID: return 6882; case OrangeBanner::OrangeBanner(12).ID: return 6883; case OrangeBanner::OrangeBanner(13).ID: return 6884; case OrangeBanner::OrangeBanner(14).ID: return 6885; case OrangeBanner::OrangeBanner(15).ID: return 6886; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_ZM, true, OrangeBed::Part::Head).ID: return 764; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_ZM, true, OrangeBed::Part::Foot).ID: return 765; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_ZM, false, OrangeBed::Part::Head).ID: return 766; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_ZM, false, OrangeBed::Part::Foot).ID: return 767; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_ZP, true, OrangeBed::Part::Head).ID: return 768; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_ZP, true, OrangeBed::Part::Foot).ID: return 769; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_ZP, false, OrangeBed::Part::Head).ID: return 770; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_ZP, false, OrangeBed::Part::Foot).ID: return 771; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_XM, true, OrangeBed::Part::Head).ID: return 772; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_XM, true, OrangeBed::Part::Foot).ID: return 773; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_XM, false, OrangeBed::Part::Head).ID: return 774; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_XM, false, OrangeBed::Part::Foot).ID: return 775; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_XP, true, OrangeBed::Part::Head).ID: return 776; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_XP, true, OrangeBed::Part::Foot).ID: return 777; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_XP, false, OrangeBed::Part::Head).ID: return 778; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_XP, false, OrangeBed::Part::Foot).ID: return 779; case OrangeCarpet::OrangeCarpet().ID: return 6825; case OrangeConcrete::OrangeConcrete().ID: return 8379; case OrangeConcretePowder::OrangeConcretePowder().ID: return 8395; case OrangeGlazedTerracotta::OrangeGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 8318; case OrangeGlazedTerracotta::OrangeGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 8319; case OrangeGlazedTerracotta::OrangeGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 8320; case OrangeGlazedTerracotta::OrangeGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 8321; case OrangeShulkerBox::OrangeShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 8224; case OrangeShulkerBox::OrangeShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 8225; case OrangeShulkerBox::OrangeShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 8226; case OrangeShulkerBox::OrangeShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 8227; case OrangeShulkerBox::OrangeShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 8228; case OrangeShulkerBox::OrangeShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 8229; case OrangeStainedGlass::OrangeStainedGlass().ID: return 3579; case OrangeStainedGlassPane::OrangeStainedGlassPane(true, true, true, true).ID: return 5855; case OrangeStainedGlassPane::OrangeStainedGlassPane(true, true, true, false).ID: return 5856; case OrangeStainedGlassPane::OrangeStainedGlassPane(true, true, false, true).ID: return 5859; case OrangeStainedGlassPane::OrangeStainedGlassPane(true, true, false, false).ID: return 5860; case OrangeStainedGlassPane::OrangeStainedGlassPane(true, false, true, true).ID: return 5863; case OrangeStainedGlassPane::OrangeStainedGlassPane(true, false, true, false).ID: return 5864; case OrangeStainedGlassPane::OrangeStainedGlassPane(true, false, false, true).ID: return 5867; case OrangeStainedGlassPane::OrangeStainedGlassPane(true, false, false, false).ID: return 5868; case OrangeStainedGlassPane::OrangeStainedGlassPane(false, true, true, true).ID: return 5871; case OrangeStainedGlassPane::OrangeStainedGlassPane(false, true, true, false).ID: return 5872; case OrangeStainedGlassPane::OrangeStainedGlassPane(false, true, false, true).ID: return 5875; case OrangeStainedGlassPane::OrangeStainedGlassPane(false, true, false, false).ID: return 5876; case OrangeStainedGlassPane::OrangeStainedGlassPane(false, false, true, true).ID: return 5879; case OrangeStainedGlassPane::OrangeStainedGlassPane(false, false, true, false).ID: return 5880; case OrangeStainedGlassPane::OrangeStainedGlassPane(false, false, false, true).ID: return 5883; case OrangeStainedGlassPane::OrangeStainedGlassPane(false, false, false, false).ID: return 5884; case OrangeTerracotta::OrangeTerracotta().ID: return 5806; case OrangeTulip::OrangeTulip().ID: return 1117; case OrangeWallBanner::OrangeWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 7115; case OrangeWallBanner::OrangeWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 7116; case OrangeWallBanner::OrangeWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 7117; case OrangeWallBanner::OrangeWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 7118; case OrangeWool::OrangeWool().ID: return 1084; case OxeyeDaisy::OxeyeDaisy().ID: return 1120; case PackedIce::PackedIce().ID: return 6842; case Peony::Peony(Peony::Half::Upper).ID: return 6849; case Peony::Peony(Peony::Half::Lower).ID: return 6850; case PetrifiedOakSlab::PetrifiedOakSlab(PetrifiedOakSlab::Type::Top).ID: return 7307; case PetrifiedOakSlab::PetrifiedOakSlab(PetrifiedOakSlab::Type::Bottom).ID: return 7309; case PetrifiedOakSlab::PetrifiedOakSlab(PetrifiedOakSlab::Type::Double).ID: return 7311; case PinkBanner::PinkBanner(0).ID: return 6951; case PinkBanner::PinkBanner(1).ID: return 6952; case PinkBanner::PinkBanner(2).ID: return 6953; case PinkBanner::PinkBanner(3).ID: return 6954; case PinkBanner::PinkBanner(4).ID: return 6955; case PinkBanner::PinkBanner(5).ID: return 6956; case PinkBanner::PinkBanner(6).ID: return 6957; case PinkBanner::PinkBanner(7).ID: return 6958; case PinkBanner::PinkBanner(8).ID: return 6959; case PinkBanner::PinkBanner(9).ID: return 6960; case PinkBanner::PinkBanner(10).ID: return 6961; case PinkBanner::PinkBanner(11).ID: return 6962; case PinkBanner::PinkBanner(12).ID: return 6963; case PinkBanner::PinkBanner(13).ID: return 6964; case PinkBanner::PinkBanner(14).ID: return 6965; case PinkBanner::PinkBanner(15).ID: return 6966; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_ZM, true, PinkBed::Part::Head).ID: return 844; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_ZM, true, PinkBed::Part::Foot).ID: return 845; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_ZM, false, PinkBed::Part::Head).ID: return 846; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_ZM, false, PinkBed::Part::Foot).ID: return 847; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_ZP, true, PinkBed::Part::Head).ID: return 848; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_ZP, true, PinkBed::Part::Foot).ID: return 849; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_ZP, false, PinkBed::Part::Head).ID: return 850; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_ZP, false, PinkBed::Part::Foot).ID: return 851; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_XM, true, PinkBed::Part::Head).ID: return 852; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_XM, true, PinkBed::Part::Foot).ID: return 853; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_XM, false, PinkBed::Part::Head).ID: return 854; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_XM, false, PinkBed::Part::Foot).ID: return 855; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_XP, true, PinkBed::Part::Head).ID: return 856; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_XP, true, PinkBed::Part::Foot).ID: return 857; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_XP, false, PinkBed::Part::Head).ID: return 858; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_XP, false, PinkBed::Part::Foot).ID: return 859; case PinkCarpet::PinkCarpet().ID: return 6830; case PinkConcrete::PinkConcrete().ID: return 8384; case PinkConcretePowder::PinkConcretePowder().ID: return 8400; case PinkGlazedTerracotta::PinkGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 8338; case PinkGlazedTerracotta::PinkGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 8339; case PinkGlazedTerracotta::PinkGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 8340; case PinkGlazedTerracotta::PinkGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 8341; case PinkShulkerBox::PinkShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 8254; case PinkShulkerBox::PinkShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 8255; case PinkShulkerBox::PinkShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 8256; case PinkShulkerBox::PinkShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 8257; case PinkShulkerBox::PinkShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 8258; case PinkShulkerBox::PinkShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 8259; case PinkStainedGlass::PinkStainedGlass().ID: return 3584; case PinkStainedGlassPane::PinkStainedGlassPane(true, true, true, true).ID: return 6015; case PinkStainedGlassPane::PinkStainedGlassPane(true, true, true, false).ID: return 6016; case PinkStainedGlassPane::PinkStainedGlassPane(true, true, false, true).ID: return 6019; case PinkStainedGlassPane::PinkStainedGlassPane(true, true, false, false).ID: return 6020; case PinkStainedGlassPane::PinkStainedGlassPane(true, false, true, true).ID: return 6023; case PinkStainedGlassPane::PinkStainedGlassPane(true, false, true, false).ID: return 6024; case PinkStainedGlassPane::PinkStainedGlassPane(true, false, false, true).ID: return 6027; case PinkStainedGlassPane::PinkStainedGlassPane(true, false, false, false).ID: return 6028; case PinkStainedGlassPane::PinkStainedGlassPane(false, true, true, true).ID: return 6031; case PinkStainedGlassPane::PinkStainedGlassPane(false, true, true, false).ID: return 6032; case PinkStainedGlassPane::PinkStainedGlassPane(false, true, false, true).ID: return 6035; case PinkStainedGlassPane::PinkStainedGlassPane(false, true, false, false).ID: return 6036; case PinkStainedGlassPane::PinkStainedGlassPane(false, false, true, true).ID: return 6039; case PinkStainedGlassPane::PinkStainedGlassPane(false, false, true, false).ID: return 6040; case PinkStainedGlassPane::PinkStainedGlassPane(false, false, false, true).ID: return 6043; case PinkStainedGlassPane::PinkStainedGlassPane(false, false, false, false).ID: return 6044; case PinkTerracotta::PinkTerracotta().ID: return 5811; case PinkTulip::PinkTulip().ID: return 1119; case PinkWallBanner::PinkWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 7135; case PinkWallBanner::PinkWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 7136; case PinkWallBanner::PinkWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 7137; case PinkWallBanner::PinkWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 7138; case PinkWool::PinkWool().ID: return 1089; case Piston::Piston(true, eBlockFace::BLOCK_FACE_ZM).ID: return 1047; case Piston::Piston(true, eBlockFace::BLOCK_FACE_XP).ID: return 1048; case Piston::Piston(true, eBlockFace::BLOCK_FACE_ZP).ID: return 1049; case Piston::Piston(true, eBlockFace::BLOCK_FACE_XM).ID: return 1050; case Piston::Piston(true, eBlockFace::BLOCK_FACE_YP).ID: return 1051; case Piston::Piston(true, eBlockFace::BLOCK_FACE_YM).ID: return 1052; case Piston::Piston(false, eBlockFace::BLOCK_FACE_ZM).ID: return 1053; case Piston::Piston(false, eBlockFace::BLOCK_FACE_XP).ID: return 1054; case Piston::Piston(false, eBlockFace::BLOCK_FACE_ZP).ID: return 1055; case Piston::Piston(false, eBlockFace::BLOCK_FACE_XM).ID: return 1056; case Piston::Piston(false, eBlockFace::BLOCK_FACE_YP).ID: return 1057; case Piston::Piston(false, eBlockFace::BLOCK_FACE_YM).ID: return 1058; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_ZM, true, PistonHead::Type::Normal).ID: return 1059; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_ZM, true, PistonHead::Type::Sticky).ID: return 1060; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_ZM, false, PistonHead::Type::Normal).ID: return 1061; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_ZM, false, PistonHead::Type::Sticky).ID: return 1062; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_XP, true, PistonHead::Type::Normal).ID: return 1063; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_XP, true, PistonHead::Type::Sticky).ID: return 1064; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_XP, false, PistonHead::Type::Normal).ID: return 1065; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_XP, false, PistonHead::Type::Sticky).ID: return 1066; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_ZP, true, PistonHead::Type::Normal).ID: return 1067; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_ZP, true, PistonHead::Type::Sticky).ID: return 1068; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_ZP, false, PistonHead::Type::Normal).ID: return 1069; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_ZP, false, PistonHead::Type::Sticky).ID: return 1070; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_XM, true, PistonHead::Type::Normal).ID: return 1071; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_XM, true, PistonHead::Type::Sticky).ID: return 1072; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_XM, false, PistonHead::Type::Normal).ID: return 1073; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_XM, false, PistonHead::Type::Sticky).ID: return 1074; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_YP, true, PistonHead::Type::Normal).ID: return 1075; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_YP, true, PistonHead::Type::Sticky).ID: return 1076; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_YP, false, PistonHead::Type::Normal).ID: return 1077; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_YP, false, PistonHead::Type::Sticky).ID: return 1078; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_YM, true, PistonHead::Type::Normal).ID: return 1079; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_YM, true, PistonHead::Type::Sticky).ID: return 1080; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_YM, false, PistonHead::Type::Normal).ID: return 1081; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_YM, false, PistonHead::Type::Sticky).ID: return 1082; case PlayerHead::PlayerHead(0).ID: return 5512; case PlayerHead::PlayerHead(1).ID: return 5513; case PlayerHead::PlayerHead(2).ID: return 5514; case PlayerHead::PlayerHead(3).ID: return 5515; case PlayerHead::PlayerHead(4).ID: return 5516; case PlayerHead::PlayerHead(5).ID: return 5517; case PlayerHead::PlayerHead(6).ID: return 5518; case PlayerHead::PlayerHead(7).ID: return 5519; case PlayerHead::PlayerHead(8).ID: return 5520; case PlayerHead::PlayerHead(9).ID: return 5521; case PlayerHead::PlayerHead(10).ID: return 5522; case PlayerHead::PlayerHead(11).ID: return 5523; case PlayerHead::PlayerHead(12).ID: return 5524; case PlayerHead::PlayerHead(13).ID: return 5525; case PlayerHead::PlayerHead(14).ID: return 5526; case PlayerHead::PlayerHead(15).ID: return 5527; case PlayerWallHead::PlayerWallHead(eBlockFace::BLOCK_FACE_ZM).ID: return 5508; case PlayerWallHead::PlayerWallHead(eBlockFace::BLOCK_FACE_ZP).ID: return 5509; case PlayerWallHead::PlayerWallHead(eBlockFace::BLOCK_FACE_XM).ID: return 5510; case PlayerWallHead::PlayerWallHead(eBlockFace::BLOCK_FACE_XP).ID: return 5511; case Podzol::Podzol(true).ID: return 12; case Podzol::Podzol(false).ID: return 13; case PolishedAndesite::PolishedAndesite().ID: return 7; case PolishedDiorite::PolishedDiorite().ID: return 5; case PolishedGranite::PolishedGranite().ID: return 3; case Poppy::Poppy().ID: return 1112; case Potatoes::Potatoes(0).ID: return 5296; case Potatoes::Potatoes(1).ID: return 5297; case Potatoes::Potatoes(2).ID: return 5298; case Potatoes::Potatoes(3).ID: return 5299; case Potatoes::Potatoes(4).ID: return 5300; case Potatoes::Potatoes(5).ID: return 5301; case Potatoes::Potatoes(6).ID: return 5302; case Potatoes::Potatoes(7).ID: return 5303; case PottedAcaciaSapling::PottedAcaciaSapling().ID: return 5271; case PottedAllium::PottedAllium().ID: return 5277; case PottedAzureBluet::PottedAzureBluet().ID: return 5278; case PottedBirchSapling::PottedBirchSapling().ID: return 5269; case PottedBlueOrchid::PottedBlueOrchid().ID: return 5276; case PottedBrownMushroom::PottedBrownMushroom().ID: return 5285; case PottedCactus::PottedCactus().ID: return 5287; case PottedDandelion::PottedDandelion().ID: return 5274; case PottedDarkOakSapling::PottedDarkOakSapling().ID: return 5272; case PottedDeadBush::PottedDeadBush().ID: return 5286; case PottedFern::PottedFern().ID: return 5273; case PottedJungleSapling::PottedJungleSapling().ID: return 5270; case PottedOakSapling::PottedOakSapling().ID: return 5267; case PottedOrangeTulip::PottedOrangeTulip().ID: return 5280; case PottedOxeyeDaisy::PottedOxeyeDaisy().ID: return 5283; case PottedPinkTulip::PottedPinkTulip().ID: return 5282; case PottedPoppy::PottedPoppy().ID: return 5275; case PottedRedMushroom::PottedRedMushroom().ID: return 5284; case PottedRedTulip::PottedRedTulip().ID: return 5279; case PottedSpruceSapling::PottedSpruceSapling().ID: return 5268; case PottedWhiteTulip::PottedWhiteTulip().ID: return 5281; case PoweredRail::PoweredRail(true, PoweredRail::Shape::NorthSouth).ID: return 1004; case PoweredRail::PoweredRail(true, PoweredRail::Shape::EastWest).ID: return 1005; case PoweredRail::PoweredRail(true, PoweredRail::Shape::AscendingEast).ID: return 1006; case PoweredRail::PoweredRail(true, PoweredRail::Shape::AscendingWest).ID: return 1007; case PoweredRail::PoweredRail(true, PoweredRail::Shape::AscendingNorth).ID: return 1008; case PoweredRail::PoweredRail(true, PoweredRail::Shape::AscendingSouth).ID: return 1009; case PoweredRail::PoweredRail(false, PoweredRail::Shape::NorthSouth).ID: return 1010; case PoweredRail::PoweredRail(false, PoweredRail::Shape::EastWest).ID: return 1011; case PoweredRail::PoweredRail(false, PoweredRail::Shape::AscendingEast).ID: return 1012; case PoweredRail::PoweredRail(false, PoweredRail::Shape::AscendingWest).ID: return 1013; case PoweredRail::PoweredRail(false, PoweredRail::Shape::AscendingNorth).ID: return 1014; case PoweredRail::PoweredRail(false, PoweredRail::Shape::AscendingSouth).ID: return 1015; case Prismarine::Prismarine().ID: return 6559; case PrismarineBrickSlab::PrismarineBrickSlab(PrismarineBrickSlab::Type::Top).ID: return 6809; case PrismarineBrickSlab::PrismarineBrickSlab(PrismarineBrickSlab::Type::Bottom).ID: return 6811; case PrismarineBrickSlab::PrismarineBrickSlab(PrismarineBrickSlab::Type::Double).ID: return 6813; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::Straight).ID: return 6643; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::InnerLeft).ID: return 6645; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::InnerRight).ID: return 6647; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::OuterLeft).ID: return 6649; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::OuterRight).ID: return 6651; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::Straight).ID: return 6653; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::InnerLeft).ID: return 6655; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::InnerRight).ID: return 6657; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::OuterLeft).ID: return 6659; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::OuterRight).ID: return 6661; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::Straight).ID: return 6663; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::InnerLeft).ID: return 6665; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::InnerRight).ID: return 6667; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::OuterLeft).ID: return 6669; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::OuterRight).ID: return 6671; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::Straight).ID: return 6673; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::InnerLeft).ID: return 6675; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::InnerRight).ID: return 6677; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::OuterLeft).ID: return 6679; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::OuterRight).ID: return 6681; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XM, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::Straight).ID: return 6683; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XM, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::InnerLeft).ID: return 6685; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XM, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::InnerRight).ID: return 6687; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XM, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::OuterLeft).ID: return 6689; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XM, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::OuterRight).ID: return 6691; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XM, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::Straight).ID: return 6693; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XM, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::InnerLeft).ID: return 6695; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XM, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::InnerRight).ID: return 6697; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XM, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::OuterLeft).ID: return 6699; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XM, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::OuterRight).ID: return 6701; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XP, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::Straight).ID: return 6703; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XP, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::InnerLeft).ID: return 6705; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XP, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::InnerRight).ID: return 6707; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XP, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::OuterLeft).ID: return 6709; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XP, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::OuterRight).ID: return 6711; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XP, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::Straight).ID: return 6713; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XP, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::InnerLeft).ID: return 6715; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XP, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::InnerRight).ID: return 6717; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XP, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::OuterLeft).ID: return 6719; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XP, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::OuterRight).ID: return 6721; case PrismarineBricks::PrismarineBricks().ID: return 6560; case PrismarineSlab::PrismarineSlab(PrismarineSlab::Type::Top).ID: return 6803; case PrismarineSlab::PrismarineSlab(PrismarineSlab::Type::Bottom).ID: return 6805; case PrismarineSlab::PrismarineSlab(PrismarineSlab::Type::Double).ID: return 6807; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineStairs::Half::Top, PrismarineStairs::Shape::Straight).ID: return 6563; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineStairs::Half::Top, PrismarineStairs::Shape::InnerLeft).ID: return 6565; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineStairs::Half::Top, PrismarineStairs::Shape::InnerRight).ID: return 6567; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineStairs::Half::Top, PrismarineStairs::Shape::OuterLeft).ID: return 6569; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineStairs::Half::Top, PrismarineStairs::Shape::OuterRight).ID: return 6571; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::Straight).ID: return 6573; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::InnerLeft).ID: return 6575; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::InnerRight).ID: return 6577; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::OuterLeft).ID: return 6579; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::OuterRight).ID: return 6581; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineStairs::Half::Top, PrismarineStairs::Shape::Straight).ID: return 6583; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineStairs::Half::Top, PrismarineStairs::Shape::InnerLeft).ID: return 6585; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineStairs::Half::Top, PrismarineStairs::Shape::InnerRight).ID: return 6587; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineStairs::Half::Top, PrismarineStairs::Shape::OuterLeft).ID: return 6589; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineStairs::Half::Top, PrismarineStairs::Shape::OuterRight).ID: return 6591; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::Straight).ID: return 6593; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::InnerLeft).ID: return 6595; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::InnerRight).ID: return 6597; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::OuterLeft).ID: return 6599; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::OuterRight).ID: return 6601; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XM, PrismarineStairs::Half::Top, PrismarineStairs::Shape::Straight).ID: return 6603; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XM, PrismarineStairs::Half::Top, PrismarineStairs::Shape::InnerLeft).ID: return 6605; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XM, PrismarineStairs::Half::Top, PrismarineStairs::Shape::InnerRight).ID: return 6607; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XM, PrismarineStairs::Half::Top, PrismarineStairs::Shape::OuterLeft).ID: return 6609; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XM, PrismarineStairs::Half::Top, PrismarineStairs::Shape::OuterRight).ID: return 6611; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XM, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::Straight).ID: return 6613; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XM, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::InnerLeft).ID: return 6615; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XM, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::InnerRight).ID: return 6617; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XM, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::OuterLeft).ID: return 6619; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XM, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::OuterRight).ID: return 6621; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XP, PrismarineStairs::Half::Top, PrismarineStairs::Shape::Straight).ID: return 6623; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XP, PrismarineStairs::Half::Top, PrismarineStairs::Shape::InnerLeft).ID: return 6625; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XP, PrismarineStairs::Half::Top, PrismarineStairs::Shape::InnerRight).ID: return 6627; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XP, PrismarineStairs::Half::Top, PrismarineStairs::Shape::OuterLeft).ID: return 6629; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XP, PrismarineStairs::Half::Top, PrismarineStairs::Shape::OuterRight).ID: return 6631; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XP, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::Straight).ID: return 6633; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XP, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::InnerLeft).ID: return 6635; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XP, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::InnerRight).ID: return 6637; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XP, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::OuterLeft).ID: return 6639; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XP, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::OuterRight).ID: return 6641; case Pumpkin::Pumpkin().ID: return 3493; case PumpkinStem::PumpkinStem(0).ID: return 4253; case PumpkinStem::PumpkinStem(1).ID: return 4254; case PumpkinStem::PumpkinStem(2).ID: return 4255; case PumpkinStem::PumpkinStem(3).ID: return 4256; case PumpkinStem::PumpkinStem(4).ID: return 4257; case PumpkinStem::PumpkinStem(5).ID: return 4258; case PumpkinStem::PumpkinStem(6).ID: return 4259; case PumpkinStem::PumpkinStem(7).ID: return 4260; case PurpleBanner::PurpleBanner(0).ID: return 7015; case PurpleBanner::PurpleBanner(1).ID: return 7016; case PurpleBanner::PurpleBanner(2).ID: return 7017; case PurpleBanner::PurpleBanner(3).ID: return 7018; case PurpleBanner::PurpleBanner(4).ID: return 7019; case PurpleBanner::PurpleBanner(5).ID: return 7020; case PurpleBanner::PurpleBanner(6).ID: return 7021; case PurpleBanner::PurpleBanner(7).ID: return 7022; case PurpleBanner::PurpleBanner(8).ID: return 7023; case PurpleBanner::PurpleBanner(9).ID: return 7024; case PurpleBanner::PurpleBanner(10).ID: return 7025; case PurpleBanner::PurpleBanner(11).ID: return 7026; case PurpleBanner::PurpleBanner(12).ID: return 7027; case PurpleBanner::PurpleBanner(13).ID: return 7028; case PurpleBanner::PurpleBanner(14).ID: return 7029; case PurpleBanner::PurpleBanner(15).ID: return 7030; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_ZM, true, PurpleBed::Part::Head).ID: return 908; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_ZM, true, PurpleBed::Part::Foot).ID: return 909; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_ZM, false, PurpleBed::Part::Head).ID: return 910; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_ZM, false, PurpleBed::Part::Foot).ID: return 911; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_ZP, true, PurpleBed::Part::Head).ID: return 912; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_ZP, true, PurpleBed::Part::Foot).ID: return 913; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_ZP, false, PurpleBed::Part::Head).ID: return 914; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_ZP, false, PurpleBed::Part::Foot).ID: return 915; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_XM, true, PurpleBed::Part::Head).ID: return 916; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_XM, true, PurpleBed::Part::Foot).ID: return 917; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_XM, false, PurpleBed::Part::Head).ID: return 918; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_XM, false, PurpleBed::Part::Foot).ID: return 919; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_XP, true, PurpleBed::Part::Head).ID: return 920; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_XP, true, PurpleBed::Part::Foot).ID: return 921; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_XP, false, PurpleBed::Part::Head).ID: return 922; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_XP, false, PurpleBed::Part::Foot).ID: return 923; case PurpleCarpet::PurpleCarpet().ID: return 6834; case PurpleConcrete::PurpleConcrete().ID: return 8388; case PurpleConcretePowder::PurpleConcretePowder().ID: return 8404; case PurpleGlazedTerracotta::PurpleGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 8354; case PurpleGlazedTerracotta::PurpleGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 8355; case PurpleGlazedTerracotta::PurpleGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 8356; case PurpleGlazedTerracotta::PurpleGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 8357; case PurpleShulkerBox::PurpleShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 8278; case PurpleShulkerBox::PurpleShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 8279; case PurpleShulkerBox::PurpleShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 8280; case PurpleShulkerBox::PurpleShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 8281; case PurpleShulkerBox::PurpleShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 8282; case PurpleShulkerBox::PurpleShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 8283; case PurpleStainedGlass::PurpleStainedGlass().ID: return 3588; case PurpleStainedGlassPane::PurpleStainedGlassPane(true, true, true, true).ID: return 6143; case PurpleStainedGlassPane::PurpleStainedGlassPane(true, true, true, false).ID: return 6144; case PurpleStainedGlassPane::PurpleStainedGlassPane(true, true, false, true).ID: return 6147; case PurpleStainedGlassPane::PurpleStainedGlassPane(true, true, false, false).ID: return 6148; case PurpleStainedGlassPane::PurpleStainedGlassPane(true, false, true, true).ID: return 6151; case PurpleStainedGlassPane::PurpleStainedGlassPane(true, false, true, false).ID: return 6152; case PurpleStainedGlassPane::PurpleStainedGlassPane(true, false, false, true).ID: return 6155; case PurpleStainedGlassPane::PurpleStainedGlassPane(true, false, false, false).ID: return 6156; case PurpleStainedGlassPane::PurpleStainedGlassPane(false, true, true, true).ID: return 6159; case PurpleStainedGlassPane::PurpleStainedGlassPane(false, true, true, false).ID: return 6160; case PurpleStainedGlassPane::PurpleStainedGlassPane(false, true, false, true).ID: return 6163; case PurpleStainedGlassPane::PurpleStainedGlassPane(false, true, false, false).ID: return 6164; case PurpleStainedGlassPane::PurpleStainedGlassPane(false, false, true, true).ID: return 6167; case PurpleStainedGlassPane::PurpleStainedGlassPane(false, false, true, false).ID: return 6168; case PurpleStainedGlassPane::PurpleStainedGlassPane(false, false, false, true).ID: return 6171; case PurpleStainedGlassPane::PurpleStainedGlassPane(false, false, false, false).ID: return 6172; case PurpleTerracotta::PurpleTerracotta().ID: return 5815; case PurpleWallBanner::PurpleWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 7151; case PurpleWallBanner::PurpleWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 7152; case PurpleWallBanner::PurpleWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 7153; case PurpleWallBanner::PurpleWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 7154; case PurpleWool::PurpleWool().ID: return 1093; case PurpurBlock::PurpurBlock().ID: return 8074; case PurpurPillar::PurpurPillar(PurpurPillar::Axis::X).ID: return 8075; case PurpurPillar::PurpurPillar(PurpurPillar::Axis::Y).ID: return 8076; case PurpurPillar::PurpurPillar(PurpurPillar::Axis::Z).ID: return 8077; case PurpurSlab::PurpurSlab(PurpurSlab::Type::Top).ID: return 7349; case PurpurSlab::PurpurSlab(PurpurSlab::Type::Bottom).ID: return 7351; case PurpurSlab::PurpurSlab(PurpurSlab::Type::Double).ID: return 7353; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZM, PurpurStairs::Half::Top, PurpurStairs::Shape::Straight).ID: return 8079; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZM, PurpurStairs::Half::Top, PurpurStairs::Shape::InnerLeft).ID: return 8081; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZM, PurpurStairs::Half::Top, PurpurStairs::Shape::InnerRight).ID: return 8083; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZM, PurpurStairs::Half::Top, PurpurStairs::Shape::OuterLeft).ID: return 8085; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZM, PurpurStairs::Half::Top, PurpurStairs::Shape::OuterRight).ID: return 8087; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZM, PurpurStairs::Half::Bottom, PurpurStairs::Shape::Straight).ID: return 8089; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZM, PurpurStairs::Half::Bottom, PurpurStairs::Shape::InnerLeft).ID: return 8091; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZM, PurpurStairs::Half::Bottom, PurpurStairs::Shape::InnerRight).ID: return 8093; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZM, PurpurStairs::Half::Bottom, PurpurStairs::Shape::OuterLeft).ID: return 8095; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZM, PurpurStairs::Half::Bottom, PurpurStairs::Shape::OuterRight).ID: return 8097; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZP, PurpurStairs::Half::Top, PurpurStairs::Shape::Straight).ID: return 8099; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZP, PurpurStairs::Half::Top, PurpurStairs::Shape::InnerLeft).ID: return 8101; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZP, PurpurStairs::Half::Top, PurpurStairs::Shape::InnerRight).ID: return 8103; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZP, PurpurStairs::Half::Top, PurpurStairs::Shape::OuterLeft).ID: return 8105; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZP, PurpurStairs::Half::Top, PurpurStairs::Shape::OuterRight).ID: return 8107; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZP, PurpurStairs::Half::Bottom, PurpurStairs::Shape::Straight).ID: return 8109; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZP, PurpurStairs::Half::Bottom, PurpurStairs::Shape::InnerLeft).ID: return 8111; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZP, PurpurStairs::Half::Bottom, PurpurStairs::Shape::InnerRight).ID: return 8113; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZP, PurpurStairs::Half::Bottom, PurpurStairs::Shape::OuterLeft).ID: return 8115; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZP, PurpurStairs::Half::Bottom, PurpurStairs::Shape::OuterRight).ID: return 8117; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XM, PurpurStairs::Half::Top, PurpurStairs::Shape::Straight).ID: return 8119; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XM, PurpurStairs::Half::Top, PurpurStairs::Shape::InnerLeft).ID: return 8121; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XM, PurpurStairs::Half::Top, PurpurStairs::Shape::InnerRight).ID: return 8123; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XM, PurpurStairs::Half::Top, PurpurStairs::Shape::OuterLeft).ID: return 8125; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XM, PurpurStairs::Half::Top, PurpurStairs::Shape::OuterRight).ID: return 8127; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XM, PurpurStairs::Half::Bottom, PurpurStairs::Shape::Straight).ID: return 8129; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XM, PurpurStairs::Half::Bottom, PurpurStairs::Shape::InnerLeft).ID: return 8131; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XM, PurpurStairs::Half::Bottom, PurpurStairs::Shape::InnerRight).ID: return 8133; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XM, PurpurStairs::Half::Bottom, PurpurStairs::Shape::OuterLeft).ID: return 8135; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XM, PurpurStairs::Half::Bottom, PurpurStairs::Shape::OuterRight).ID: return 8137; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XP, PurpurStairs::Half::Top, PurpurStairs::Shape::Straight).ID: return 8139; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XP, PurpurStairs::Half::Top, PurpurStairs::Shape::InnerLeft).ID: return 8141; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XP, PurpurStairs::Half::Top, PurpurStairs::Shape::InnerRight).ID: return 8143; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XP, PurpurStairs::Half::Top, PurpurStairs::Shape::OuterLeft).ID: return 8145; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XP, PurpurStairs::Half::Top, PurpurStairs::Shape::OuterRight).ID: return 8147; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XP, PurpurStairs::Half::Bottom, PurpurStairs::Shape::Straight).ID: return 8149; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XP, PurpurStairs::Half::Bottom, PurpurStairs::Shape::InnerLeft).ID: return 8151; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XP, PurpurStairs::Half::Bottom, PurpurStairs::Shape::InnerRight).ID: return 8153; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XP, PurpurStairs::Half::Bottom, PurpurStairs::Shape::OuterLeft).ID: return 8155; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XP, PurpurStairs::Half::Bottom, PurpurStairs::Shape::OuterRight).ID: return 8157; case QuartzBlock::QuartzBlock().ID: return 5696; case QuartzPillar::QuartzPillar(QuartzPillar::Axis::X).ID: return 5698; case QuartzPillar::QuartzPillar(QuartzPillar::Axis::Y).ID: return 5699; case QuartzPillar::QuartzPillar(QuartzPillar::Axis::Z).ID: return 5700; case QuartzSlab::QuartzSlab(QuartzSlab::Type::Top).ID: return 7337; case QuartzSlab::QuartzSlab(QuartzSlab::Type::Bottom).ID: return 7339; case QuartzSlab::QuartzSlab(QuartzSlab::Type::Double).ID: return 7341; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZM, QuartzStairs::Half::Top, QuartzStairs::Shape::Straight).ID: return 5702; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZM, QuartzStairs::Half::Top, QuartzStairs::Shape::InnerLeft).ID: return 5704; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZM, QuartzStairs::Half::Top, QuartzStairs::Shape::InnerRight).ID: return 5706; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZM, QuartzStairs::Half::Top, QuartzStairs::Shape::OuterLeft).ID: return 5708; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZM, QuartzStairs::Half::Top, QuartzStairs::Shape::OuterRight).ID: return 5710; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZM, QuartzStairs::Half::Bottom, QuartzStairs::Shape::Straight).ID: return 5712; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZM, QuartzStairs::Half::Bottom, QuartzStairs::Shape::InnerLeft).ID: return 5714; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZM, QuartzStairs::Half::Bottom, QuartzStairs::Shape::InnerRight).ID: return 5716; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZM, QuartzStairs::Half::Bottom, QuartzStairs::Shape::OuterLeft).ID: return 5718; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZM, QuartzStairs::Half::Bottom, QuartzStairs::Shape::OuterRight).ID: return 5720; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZP, QuartzStairs::Half::Top, QuartzStairs::Shape::Straight).ID: return 5722; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZP, QuartzStairs::Half::Top, QuartzStairs::Shape::InnerLeft).ID: return 5724; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZP, QuartzStairs::Half::Top, QuartzStairs::Shape::InnerRight).ID: return 5726; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZP, QuartzStairs::Half::Top, QuartzStairs::Shape::OuterLeft).ID: return 5728; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZP, QuartzStairs::Half::Top, QuartzStairs::Shape::OuterRight).ID: return 5730; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZP, QuartzStairs::Half::Bottom, QuartzStairs::Shape::Straight).ID: return 5732; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZP, QuartzStairs::Half::Bottom, QuartzStairs::Shape::InnerLeft).ID: return 5734; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZP, QuartzStairs::Half::Bottom, QuartzStairs::Shape::InnerRight).ID: return 5736; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZP, QuartzStairs::Half::Bottom, QuartzStairs::Shape::OuterLeft).ID: return 5738; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZP, QuartzStairs::Half::Bottom, QuartzStairs::Shape::OuterRight).ID: return 5740; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XM, QuartzStairs::Half::Top, QuartzStairs::Shape::Straight).ID: return 5742; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XM, QuartzStairs::Half::Top, QuartzStairs::Shape::InnerLeft).ID: return 5744; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XM, QuartzStairs::Half::Top, QuartzStairs::Shape::InnerRight).ID: return 5746; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XM, QuartzStairs::Half::Top, QuartzStairs::Shape::OuterLeft).ID: return 5748; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XM, QuartzStairs::Half::Top, QuartzStairs::Shape::OuterRight).ID: return 5750; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XM, QuartzStairs::Half::Bottom, QuartzStairs::Shape::Straight).ID: return 5752; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XM, QuartzStairs::Half::Bottom, QuartzStairs::Shape::InnerLeft).ID: return 5754; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XM, QuartzStairs::Half::Bottom, QuartzStairs::Shape::InnerRight).ID: return 5756; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XM, QuartzStairs::Half::Bottom, QuartzStairs::Shape::OuterLeft).ID: return 5758; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XM, QuartzStairs::Half::Bottom, QuartzStairs::Shape::OuterRight).ID: return 5760; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XP, QuartzStairs::Half::Top, QuartzStairs::Shape::Straight).ID: return 5762; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XP, QuartzStairs::Half::Top, QuartzStairs::Shape::InnerLeft).ID: return 5764; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XP, QuartzStairs::Half::Top, QuartzStairs::Shape::InnerRight).ID: return 5766; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XP, QuartzStairs::Half::Top, QuartzStairs::Shape::OuterLeft).ID: return 5768; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XP, QuartzStairs::Half::Top, QuartzStairs::Shape::OuterRight).ID: return 5770; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XP, QuartzStairs::Half::Bottom, QuartzStairs::Shape::Straight).ID: return 5772; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XP, QuartzStairs::Half::Bottom, QuartzStairs::Shape::InnerLeft).ID: return 5774; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XP, QuartzStairs::Half::Bottom, QuartzStairs::Shape::InnerRight).ID: return 5776; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XP, QuartzStairs::Half::Bottom, QuartzStairs::Shape::OuterLeft).ID: return 5778; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XP, QuartzStairs::Half::Bottom, QuartzStairs::Shape::OuterRight).ID: return 5780; case Rail::Rail(Rail::Shape::NorthSouth).ID: return 3180; case Rail::Rail(Rail::Shape::EastWest).ID: return 3181; case Rail::Rail(Rail::Shape::AscendingEast).ID: return 3182; case Rail::Rail(Rail::Shape::AscendingWest).ID: return 3183; case Rail::Rail(Rail::Shape::AscendingNorth).ID: return 3184; case Rail::Rail(Rail::Shape::AscendingSouth).ID: return 3185; case Rail::Rail(Rail::Shape::SouthEast).ID: return 3186; case Rail::Rail(Rail::Shape::SouthWest).ID: return 3187; case Rail::Rail(Rail::Shape::NorthWest).ID: return 3188; case Rail::Rail(Rail::Shape::NorthEast).ID: return 3189; case RedBanner::RedBanner(0).ID: return 7079; case RedBanner::RedBanner(1).ID: return 7080; case RedBanner::RedBanner(2).ID: return 7081; case RedBanner::RedBanner(3).ID: return 7082; case RedBanner::RedBanner(4).ID: return 7083; case RedBanner::RedBanner(5).ID: return 7084; case RedBanner::RedBanner(6).ID: return 7085; case RedBanner::RedBanner(7).ID: return 7086; case RedBanner::RedBanner(8).ID: return 7087; case RedBanner::RedBanner(9).ID: return 7088; case RedBanner::RedBanner(10).ID: return 7089; case RedBanner::RedBanner(11).ID: return 7090; case RedBanner::RedBanner(12).ID: return 7091; case RedBanner::RedBanner(13).ID: return 7092; case RedBanner::RedBanner(14).ID: return 7093; case RedBanner::RedBanner(15).ID: return 7094; case RedBed::RedBed(eBlockFace::BLOCK_FACE_ZM, true, RedBed::Part::Head).ID: return 972; case RedBed::RedBed(eBlockFace::BLOCK_FACE_ZM, true, RedBed::Part::Foot).ID: return 973; case RedBed::RedBed(eBlockFace::BLOCK_FACE_ZM, false, RedBed::Part::Head).ID: return 974; case RedBed::RedBed(eBlockFace::BLOCK_FACE_ZM, false, RedBed::Part::Foot).ID: return 975; case RedBed::RedBed(eBlockFace::BLOCK_FACE_ZP, true, RedBed::Part::Head).ID: return 976; case RedBed::RedBed(eBlockFace::BLOCK_FACE_ZP, true, RedBed::Part::Foot).ID: return 977; case RedBed::RedBed(eBlockFace::BLOCK_FACE_ZP, false, RedBed::Part::Head).ID: return 978; case RedBed::RedBed(eBlockFace::BLOCK_FACE_ZP, false, RedBed::Part::Foot).ID: return 979; case RedBed::RedBed(eBlockFace::BLOCK_FACE_XM, true, RedBed::Part::Head).ID: return 980; case RedBed::RedBed(eBlockFace::BLOCK_FACE_XM, true, RedBed::Part::Foot).ID: return 981; case RedBed::RedBed(eBlockFace::BLOCK_FACE_XM, false, RedBed::Part::Head).ID: return 982; case RedBed::RedBed(eBlockFace::BLOCK_FACE_XM, false, RedBed::Part::Foot).ID: return 983; case RedBed::RedBed(eBlockFace::BLOCK_FACE_XP, true, RedBed::Part::Head).ID: return 984; case RedBed::RedBed(eBlockFace::BLOCK_FACE_XP, true, RedBed::Part::Foot).ID: return 985; case RedBed::RedBed(eBlockFace::BLOCK_FACE_XP, false, RedBed::Part::Head).ID: return 986; case RedBed::RedBed(eBlockFace::BLOCK_FACE_XP, false, RedBed::Part::Foot).ID: return 987; case RedCarpet::RedCarpet().ID: return 6838; case RedConcrete::RedConcrete().ID: return 8392; case RedConcretePowder::RedConcretePowder().ID: return 8408; case RedGlazedTerracotta::RedGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 8370; case RedGlazedTerracotta::RedGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 8371; case RedGlazedTerracotta::RedGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 8372; case RedGlazedTerracotta::RedGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 8373; case RedMushroom::RedMushroom().ID: return 1122; case RedMushroomBlock::RedMushroomBlock(true, true, true, true, true, true).ID: return 4052; case RedMushroomBlock::RedMushroomBlock(true, true, true, true, true, false).ID: return 4053; case RedMushroomBlock::RedMushroomBlock(true, true, true, true, false, true).ID: return 4054; case RedMushroomBlock::RedMushroomBlock(true, true, true, true, false, false).ID: return 4055; case RedMushroomBlock::RedMushroomBlock(true, true, true, false, true, true).ID: return 4056; case RedMushroomBlock::RedMushroomBlock(true, true, true, false, true, false).ID: return 4057; case RedMushroomBlock::RedMushroomBlock(true, true, true, false, false, true).ID: return 4058; case RedMushroomBlock::RedMushroomBlock(true, true, true, false, false, false).ID: return 4059; case RedMushroomBlock::RedMushroomBlock(true, true, false, true, true, true).ID: return 4060; case RedMushroomBlock::RedMushroomBlock(true, true, false, true, true, false).ID: return 4061; case RedMushroomBlock::RedMushroomBlock(true, true, false, true, false, true).ID: return 4062; case RedMushroomBlock::RedMushroomBlock(true, true, false, true, false, false).ID: return 4063; case RedMushroomBlock::RedMushroomBlock(true, true, false, false, true, true).ID: return 4064; case RedMushroomBlock::RedMushroomBlock(true, true, false, false, true, false).ID: return 4065; case RedMushroomBlock::RedMushroomBlock(true, true, false, false, false, true).ID: return 4066; case RedMushroomBlock::RedMushroomBlock(true, true, false, false, false, false).ID: return 4067; case RedMushroomBlock::RedMushroomBlock(true, false, true, true, true, true).ID: return 4068; case RedMushroomBlock::RedMushroomBlock(true, false, true, true, true, false).ID: return 4069; case RedMushroomBlock::RedMushroomBlock(true, false, true, true, false, true).ID: return 4070; case RedMushroomBlock::RedMushroomBlock(true, false, true, true, false, false).ID: return 4071; case RedMushroomBlock::RedMushroomBlock(true, false, true, false, true, true).ID: return 4072; case RedMushroomBlock::RedMushroomBlock(true, false, true, false, true, false).ID: return 4073; case RedMushroomBlock::RedMushroomBlock(true, false, true, false, false, true).ID: return 4074; case RedMushroomBlock::RedMushroomBlock(true, false, true, false, false, false).ID: return 4075; case RedMushroomBlock::RedMushroomBlock(true, false, false, true, true, true).ID: return 4076; case RedMushroomBlock::RedMushroomBlock(true, false, false, true, true, false).ID: return 4077; case RedMushroomBlock::RedMushroomBlock(true, false, false, true, false, true).ID: return 4078; case RedMushroomBlock::RedMushroomBlock(true, false, false, true, false, false).ID: return 4079; case RedMushroomBlock::RedMushroomBlock(true, false, false, false, true, true).ID: return 4080; case RedMushroomBlock::RedMushroomBlock(true, false, false, false, true, false).ID: return 4081; case RedMushroomBlock::RedMushroomBlock(true, false, false, false, false, true).ID: return 4082; case RedMushroomBlock::RedMushroomBlock(true, false, false, false, false, false).ID: return 4083; case RedMushroomBlock::RedMushroomBlock(false, true, true, true, true, true).ID: return 4084; case RedMushroomBlock::RedMushroomBlock(false, true, true, true, true, false).ID: return 4085; case RedMushroomBlock::RedMushroomBlock(false, true, true, true, false, true).ID: return 4086; case RedMushroomBlock::RedMushroomBlock(false, true, true, true, false, false).ID: return 4087; case RedMushroomBlock::RedMushroomBlock(false, true, true, false, true, true).ID: return 4088; case RedMushroomBlock::RedMushroomBlock(false, true, true, false, true, false).ID: return 4089; case RedMushroomBlock::RedMushroomBlock(false, true, true, false, false, true).ID: return 4090; case RedMushroomBlock::RedMushroomBlock(false, true, true, false, false, false).ID: return 4091; case RedMushroomBlock::RedMushroomBlock(false, true, false, true, true, true).ID: return 4092; case RedMushroomBlock::RedMushroomBlock(false, true, false, true, true, false).ID: return 4093; case RedMushroomBlock::RedMushroomBlock(false, true, false, true, false, true).ID: return 4094; case RedMushroomBlock::RedMushroomBlock(false, true, false, true, false, false).ID: return 4095; case RedMushroomBlock::RedMushroomBlock(false, true, false, false, true, true).ID: return 4096; case RedMushroomBlock::RedMushroomBlock(false, true, false, false, true, false).ID: return 4097; case RedMushroomBlock::RedMushroomBlock(false, true, false, false, false, true).ID: return 4098; case RedMushroomBlock::RedMushroomBlock(false, true, false, false, false, false).ID: return 4099; case RedMushroomBlock::RedMushroomBlock(false, false, true, true, true, true).ID: return 4100; case RedMushroomBlock::RedMushroomBlock(false, false, true, true, true, false).ID: return 4101; case RedMushroomBlock::RedMushroomBlock(false, false, true, true, false, true).ID: return 4102; case RedMushroomBlock::RedMushroomBlock(false, false, true, true, false, false).ID: return 4103; case RedMushroomBlock::RedMushroomBlock(false, false, true, false, true, true).ID: return 4104; case RedMushroomBlock::RedMushroomBlock(false, false, true, false, true, false).ID: return 4105; case RedMushroomBlock::RedMushroomBlock(false, false, true, false, false, true).ID: return 4106; case RedMushroomBlock::RedMushroomBlock(false, false, true, false, false, false).ID: return 4107; case RedMushroomBlock::RedMushroomBlock(false, false, false, true, true, true).ID: return 4108; case RedMushroomBlock::RedMushroomBlock(false, false, false, true, true, false).ID: return 4109; case RedMushroomBlock::RedMushroomBlock(false, false, false, true, false, true).ID: return 4110; case RedMushroomBlock::RedMushroomBlock(false, false, false, true, false, false).ID: return 4111; case RedMushroomBlock::RedMushroomBlock(false, false, false, false, true, true).ID: return 4112; case RedMushroomBlock::RedMushroomBlock(false, false, false, false, true, false).ID: return 4113; case RedMushroomBlock::RedMushroomBlock(false, false, false, false, false, true).ID: return 4114; case RedMushroomBlock::RedMushroomBlock(false, false, false, false, false, false).ID: return 4115; case RedNetherBricks::RedNetherBricks().ID: return 8195; case RedSand::RedSand().ID: return 67; case RedSandstone::RedSandstone().ID: return 7175; case RedSandstoneSlab::RedSandstoneSlab(RedSandstoneSlab::Type::Top).ID: return 7343; case RedSandstoneSlab::RedSandstoneSlab(RedSandstoneSlab::Type::Bottom).ID: return 7345; case RedSandstoneSlab::RedSandstoneSlab(RedSandstoneSlab::Type::Double).ID: return 7347; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::Straight).ID: return 7179; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::InnerLeft).ID: return 7181; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::InnerRight).ID: return 7183; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::OuterLeft).ID: return 7185; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::OuterRight).ID: return 7187; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::Straight).ID: return 7189; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::InnerLeft).ID: return 7191; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::InnerRight).ID: return 7193; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::OuterLeft).ID: return 7195; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::OuterRight).ID: return 7197; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::Straight).ID: return 7199; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::InnerLeft).ID: return 7201; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::InnerRight).ID: return 7203; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::OuterLeft).ID: return 7205; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::OuterRight).ID: return 7207; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::Straight).ID: return 7209; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::InnerLeft).ID: return 7211; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::InnerRight).ID: return 7213; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::OuterLeft).ID: return 7215; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::OuterRight).ID: return 7217; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::Straight).ID: return 7219; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::InnerLeft).ID: return 7221; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::InnerRight).ID: return 7223; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::OuterLeft).ID: return 7225; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::OuterRight).ID: return 7227; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::Straight).ID: return 7229; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::InnerLeft).ID: return 7231; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::InnerRight).ID: return 7233; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::OuterLeft).ID: return 7235; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::OuterRight).ID: return 7237; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::Straight).ID: return 7239; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::InnerLeft).ID: return 7241; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::InnerRight).ID: return 7243; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::OuterLeft).ID: return 7245; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::OuterRight).ID: return 7247; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::Straight).ID: return 7249; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::InnerLeft).ID: return 7251; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::InnerRight).ID: return 7253; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::OuterLeft).ID: return 7255; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::OuterRight).ID: return 7257; case RedShulkerBox::RedShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 8302; case RedShulkerBox::RedShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 8303; case RedShulkerBox::RedShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 8304; case RedShulkerBox::RedShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 8305; case RedShulkerBox::RedShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 8306; case RedShulkerBox::RedShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 8307; case RedStainedGlass::RedStainedGlass().ID: return 3592; case RedStainedGlassPane::RedStainedGlassPane(true, true, true, true).ID: return 6271; case RedStainedGlassPane::RedStainedGlassPane(true, true, true, false).ID: return 6272; case RedStainedGlassPane::RedStainedGlassPane(true, true, false, true).ID: return 6275; case RedStainedGlassPane::RedStainedGlassPane(true, true, false, false).ID: return 6276; case RedStainedGlassPane::RedStainedGlassPane(true, false, true, true).ID: return 6279; case RedStainedGlassPane::RedStainedGlassPane(true, false, true, false).ID: return 6280; case RedStainedGlassPane::RedStainedGlassPane(true, false, false, true).ID: return 6283; case RedStainedGlassPane::RedStainedGlassPane(true, false, false, false).ID: return 6284; case RedStainedGlassPane::RedStainedGlassPane(false, true, true, true).ID: return 6287; case RedStainedGlassPane::RedStainedGlassPane(false, true, true, false).ID: return 6288; case RedStainedGlassPane::RedStainedGlassPane(false, true, false, true).ID: return 6291; case RedStainedGlassPane::RedStainedGlassPane(false, true, false, false).ID: return 6292; case RedStainedGlassPane::RedStainedGlassPane(false, false, true, true).ID: return 6295; case RedStainedGlassPane::RedStainedGlassPane(false, false, true, false).ID: return 6296; case RedStainedGlassPane::RedStainedGlassPane(false, false, false, true).ID: return 6299; case RedStainedGlassPane::RedStainedGlassPane(false, false, false, false).ID: return 6300; case RedTerracotta::RedTerracotta().ID: return 5819; case RedTulip::RedTulip().ID: return 1116; case RedWallBanner::RedWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 7167; case RedWallBanner::RedWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 7168; case RedWallBanner::RedWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 7169; case RedWallBanner::RedWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 7170; case RedWool::RedWool().ID: return 1097; case RedstoneBlock::RedstoneBlock().ID: return 5684; case RedstoneLamp::RedstoneLamp(true).ID: return 4637; case RedstoneLamp::RedstoneLamp(false).ID: return 4638; case RedstoneOre::RedstoneOre(true).ID: return 3380; case RedstoneOre::RedstoneOre(false).ID: return 3381; case RedstoneTorch::RedstoneTorch(true).ID: return 3382; case RedstoneTorch::RedstoneTorch(false).ID: return 3383; case RedstoneWallTorch::RedstoneWallTorch(eBlockFace::BLOCK_FACE_ZM, true).ID: return 3384; case RedstoneWallTorch::RedstoneWallTorch(eBlockFace::BLOCK_FACE_ZM, false).ID: return 3385; case RedstoneWallTorch::RedstoneWallTorch(eBlockFace::BLOCK_FACE_ZP, true).ID: return 3386; case RedstoneWallTorch::RedstoneWallTorch(eBlockFace::BLOCK_FACE_ZP, false).ID: return 3387; case RedstoneWallTorch::RedstoneWallTorch(eBlockFace::BLOCK_FACE_XM, true).ID: return 3388; case RedstoneWallTorch::RedstoneWallTorch(eBlockFace::BLOCK_FACE_XM, false).ID: return 3389; case RedstoneWallTorch::RedstoneWallTorch(eBlockFace::BLOCK_FACE_XP, true).ID: return 3390; case RedstoneWallTorch::RedstoneWallTorch(eBlockFace::BLOCK_FACE_XP, false).ID: return 3391; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 0, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 1753; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 0, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 1754; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 0, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 1755; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 0, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 1756; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 0, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 1757; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 0, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 1758; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 0, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 1759; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 0, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 1760; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 0, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 1761; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 1, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 1762; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 1, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 1763; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 1, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 1764; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 1, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 1765; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 1, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 1766; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 1, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 1767; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 1, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 1768; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 1, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 1769; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 1, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 1770; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 2, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 1771; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 2, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 1772; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 2, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 1773; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 2, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 1774; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 2, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 1775; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 2, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 1776; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 2, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 1777; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 2, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 1778; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 2, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 1779; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 3, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 1780; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 3, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 1781; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 3, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 1782; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 3, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 1783; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 3, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 1784; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 3, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 1785; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 3, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 1786; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 3, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 1787; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 3, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 1788; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 4, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 1789; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 4, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 1790; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 4, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 1791; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 4, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 1792; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 4, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 1793; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 4, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 1794; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 4, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 1795; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 4, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 1796; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 4, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 1797; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 5, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 1798; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 5, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 1799; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 5, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 1800; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 5, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 1801; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 5, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 1802; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 5, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 1803; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 5, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 1804; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 5, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 1805; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 5, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 1806; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 6, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 1807; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 6, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 1808; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 6, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 1809; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 6, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 1810; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 6, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 1811; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 6, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 1812; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 6, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 1813; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 6, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 1814; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 6, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 1815; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 7, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 1816; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 7, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 1817; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 7, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 1818; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 7, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 1819; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 7, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 1820; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 7, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 1821; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 7, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 1822; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 7, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 1823; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 7, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 1824; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 8, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 1825; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 8, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 1826; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 8, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 1827; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 8, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 1828; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 8, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 1829; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 8, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 1830; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 8, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 1831; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 8, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 1832; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 8, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 1833; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 9, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 1834; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 9, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 1835; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 9, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 1836; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 9, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 1837; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 9, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 1838; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 9, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 1839; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 9, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 1840; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 9, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 1841; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 9, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 1842; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 10, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 1843; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 10, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 1844; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 10, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 1845; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 10, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 1846; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 10, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 1847; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 10, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 1848; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 10, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 1849; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 10, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 1850; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 10, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 1851; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 11, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 1852; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 11, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 1853; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 11, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 1854; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 11, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 1855; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 11, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 1856; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 11, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 1857; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 11, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 1858; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 11, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 1859; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 11, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 1860; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 12, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 1861; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 12, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 1862; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 12, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 1863; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 12, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 1864; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 12, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 1865; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 12, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 1866; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 12, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 1867; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 12, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 1868; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 12, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 1869; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 13, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 1870; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 13, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 1871; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 13, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 1872; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 13, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 1873; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 13, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 1874; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 13, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 1875; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 13, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 1876; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 13, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 1877; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 13, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 1878; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 14, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 1879; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 14, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 1880; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 14, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 1881; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 14, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 1882; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 14, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 1883; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 14, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 1884; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 14, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 1885; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 14, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 1886; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 14, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 1887; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 15, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 1888; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 15, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 1889; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 15, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 1890; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 15, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 1891; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 15, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 1892; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 15, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 1893; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 15, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 1894; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 15, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 1895; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 15, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 1896; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 0, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 1897; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 0, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 1898; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 0, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 1899; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 0, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 1900; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 0, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 1901; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 0, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 1902; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 0, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 1903; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 0, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 1904; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 0, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 1905; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 1, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 1906; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 1, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 1907; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 1, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 1908; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 1, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 1909; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 1, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 1910; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 1, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 1911; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 1, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 1912; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 1, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 1913; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 1, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 1914; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 2, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 1915; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 2, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 1916; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 2, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 1917; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 2, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 1918; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 2, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 1919; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 2, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 1920; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 2, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 1921; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 2, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 1922; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 2, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 1923; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 3, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 1924; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 3, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 1925; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 3, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 1926; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 3, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 1927; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 3, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 1928; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 3, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 1929; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 3, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 1930; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 3, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 1931; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 3, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 1932; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 4, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 1933; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 4, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 1934; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 4, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 1935; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 4, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 1936; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 4, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 1937; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 4, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 1938; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 4, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 1939; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 4, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 1940; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 4, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 1941; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 5, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 1942; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 5, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 1943; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 5, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 1944; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 5, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 1945; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 5, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 1946; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 5, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 1947; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 5, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 1948; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 5, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 1949; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 5, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 1950; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 6, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 1951; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 6, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 1952; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 6, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 1953; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 6, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 1954; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 6, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 1955; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 6, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 1956; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 6, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 1957; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 6, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 1958; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 6, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 1959; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 7, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 1960; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 7, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 1961; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 7, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 1962; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 7, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 1963; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 7, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 1964; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 7, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 1965; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 7, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 1966; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 7, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 1967; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 7, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 1968; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 8, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 1969; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 8, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 1970; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 8, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 1971; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 8, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 1972; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 8, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 1973; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 8, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 1974; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 8, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 1975; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 8, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 1976; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 8, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 1977; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 9, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 1978; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 9, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 1979; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 9, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 1980; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 9, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 1981; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 9, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 1982; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 9, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 1983; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 9, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 1984; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 9, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 1985; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 9, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 1986; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 10, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 1987; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 10, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 1988; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 10, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 1989; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 10, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 1990; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 10, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 1991; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 10, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 1992; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 10, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 1993; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 10, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 1994; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 10, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 1995; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 11, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 1996; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 11, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 1997; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 11, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 1998; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 11, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 1999; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 11, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2000; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 11, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2001; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 11, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2002; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 11, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2003; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 11, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2004; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 12, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2005; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 12, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2006; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 12, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2007; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 12, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2008; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 12, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2009; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 12, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2010; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 12, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2011; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 12, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2012; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 12, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2013; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 13, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2014; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 13, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2015; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 13, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2016; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 13, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2017; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 13, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2018; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 13, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2019; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 13, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2020; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 13, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2021; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 13, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2022; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 14, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2023; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 14, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2024; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 14, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2025; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 14, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2026; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 14, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2027; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 14, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2028; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 14, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2029; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 14, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2030; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 14, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2031; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 15, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2032; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 15, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2033; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 15, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2034; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 15, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2035; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 15, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2036; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 15, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2037; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 15, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2038; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 15, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2039; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 15, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2040; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 0, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2041; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 0, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2042; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 0, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2043; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 0, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2044; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 0, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2045; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 0, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2046; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 0, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2047; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 0, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2048; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 0, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2049; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 1, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2050; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 1, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2051; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 1, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2052; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 1, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2053; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 1, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2054; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 1, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2055; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 1, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2056; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 1, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2057; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 1, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2058; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 2, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2059; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 2, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2060; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 2, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2061; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 2, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2062; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 2, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2063; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 2, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2064; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 2, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2065; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 2, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2066; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 2, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2067; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 3, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2068; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 3, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2069; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 3, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2070; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 3, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2071; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 3, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2072; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 3, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2073; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 3, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2074; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 3, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2075; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 3, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2076; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 4, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2077; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 4, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2078; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 4, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2079; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 4, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2080; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 4, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2081; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 4, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2082; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 4, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2083; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 4, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2084; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 4, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2085; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 5, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2086; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 5, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2087; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 5, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2088; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 5, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2089; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 5, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2090; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 5, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2091; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 5, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2092; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 5, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2093; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 5, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2094; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 6, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2095; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 6, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2096; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 6, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2097; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 6, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2098; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 6, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2099; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 6, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2100; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 6, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2101; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 6, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2102; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 6, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2103; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 7, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2104; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 7, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2105; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 7, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2106; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 7, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2107; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 7, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2108; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 7, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2109; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 7, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2110; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 7, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2111; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 7, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2112; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 8, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2113; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 8, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2114; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 8, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2115; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 8, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2116; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 8, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2117; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 8, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2118; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 8, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2119; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 8, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2120; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 8, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2121; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 9, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2122; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 9, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2123; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 9, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2124; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 9, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2125; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 9, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2126; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 9, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2127; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 9, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2128; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 9, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2129; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 9, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2130; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 10, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2131; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 10, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2132; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 10, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2133; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 10, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2134; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 10, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2135; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 10, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2136; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 10, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2137; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 10, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2138; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 10, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2139; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 11, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2140; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 11, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2141; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 11, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2142; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 11, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2143; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 11, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2144; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 11, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2145; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 11, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2146; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 11, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2147; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 11, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2148; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 12, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2149; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 12, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2150; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 12, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2151; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 12, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2152; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 12, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2153; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 12, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2154; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 12, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2155; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 12, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2156; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 12, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2157; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 13, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2158; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 13, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2159; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 13, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2160; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 13, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2161; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 13, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2162; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 13, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2163; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 13, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2164; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 13, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2165; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 13, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2166; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 14, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2167; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 14, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2168; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 14, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2169; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 14, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2170; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 14, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2171; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 14, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2172; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 14, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2173; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 14, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2174; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 14, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2175; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 15, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2176; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 15, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2177; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 15, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2178; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 15, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2179; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 15, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2180; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 15, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2181; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 15, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2182; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 15, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2183; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 15, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2184; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 0, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2185; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 0, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2186; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 0, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2187; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 0, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2188; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 0, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2189; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 0, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2190; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 0, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2191; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 0, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2192; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 0, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2193; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 1, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2194; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 1, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2195; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 1, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2196; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 1, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2197; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 1, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2198; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 1, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2199; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 1, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2200; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 1, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2201; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 1, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2202; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 2, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2203; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 2, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2204; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 2, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2205; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 2, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2206; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 2, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2207; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 2, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2208; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 2, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2209; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 2, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2210; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 2, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2211; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 3, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2212; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 3, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2213; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 3, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2214; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 3, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2215; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 3, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2216; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 3, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2217; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 3, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2218; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 3, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2219; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 3, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2220; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 4, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2221; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 4, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2222; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 4, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2223; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 4, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2224; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 4, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2225; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 4, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2226; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 4, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2227; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 4, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2228; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 4, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2229; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 5, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2230; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 5, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2231; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 5, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2232; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 5, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2233; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 5, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2234; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 5, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2235; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 5, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2236; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 5, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2237; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 5, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2238; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 6, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2239; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 6, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2240; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 6, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2241; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 6, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2242; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 6, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2243; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 6, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2244; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 6, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2245; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 6, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2246; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 6, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2247; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 7, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2248; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 7, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2249; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 7, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2250; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 7, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2251; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 7, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2252; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 7, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2253; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 7, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2254; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 7, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2255; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 7, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2256; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 8, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2257; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 8, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2258; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 8, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2259; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 8, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2260; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 8, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2261; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 8, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2262; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 8, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2263; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 8, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2264; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 8, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2265; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 9, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2266; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 9, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2267; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 9, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2268; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 9, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2269; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 9, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2270; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 9, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2271; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 9, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2272; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 9, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2273; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 9, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2274; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 10, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2275; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 10, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2276; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 10, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2277; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 10, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2278; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 10, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2279; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 10, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2280; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 10, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2281; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 10, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2282; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 10, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2283; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 11, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2284; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 11, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2285; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 11, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2286; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 11, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2287; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 11, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2288; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 11, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2289; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 11, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2290; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 11, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2291; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 11, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2292; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 12, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2293; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 12, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2294; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 12, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2295; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 12, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2296; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 12, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2297; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 12, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2298; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 12, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2299; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 12, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2300; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 12, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2301; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 13, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2302; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 13, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2303; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 13, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2304; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 13, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2305; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 13, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2306; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 13, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2307; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 13, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2308; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 13, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2309; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 13, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2310; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 14, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2311; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 14, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2312; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 14, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2313; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 14, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2314; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 14, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2315; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 14, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2316; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 14, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2317; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 14, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2318; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 14, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2319; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 15, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2320; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 15, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2321; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 15, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2322; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 15, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2323; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 15, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2324; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 15, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2325; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 15, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2326; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 15, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2327; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 15, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2328; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 0, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2329; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 0, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2330; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 0, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2331; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 0, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2332; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 0, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2333; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 0, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2334; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 0, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2335; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 0, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2336; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 0, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2337; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 1, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2338; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 1, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2339; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 1, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2340; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 1, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2341; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 1, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2342; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 1, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2343; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 1, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2344; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 1, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2345; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 1, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2346; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 2, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2347; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 2, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2348; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 2, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2349; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 2, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2350; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 2, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2351; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 2, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2352; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 2, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2353; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 2, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2354; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 2, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2355; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 3, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2356; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 3, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2357; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 3, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2358; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 3, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2359; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 3, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2360; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 3, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2361; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 3, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2362; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 3, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2363; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 3, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2364; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 4, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2365; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 4, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2366; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 4, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2367; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 4, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2368; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 4, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2369; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 4, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2370; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 4, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2371; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 4, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2372; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 4, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2373; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 5, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2374; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 5, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2375; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 5, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2376; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 5, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2377; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 5, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2378; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 5, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2379; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 5, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2380; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 5, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2381; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 5, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2382; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 6, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2383; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 6, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2384; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 6, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2385; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 6, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2386; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 6, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2387; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 6, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2388; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 6, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2389; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 6, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2390; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 6, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2391; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 7, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2392; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 7, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2393; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 7, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2394; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 7, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2395; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 7, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2396; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 7, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2397; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 7, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2398; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 7, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2399; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 7, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2400; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 8, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2401; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 8, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2402; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 8, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2403; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 8, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2404; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 8, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2405; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 8, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2406; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 8, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2407; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 8, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2408; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 8, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2409; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 9, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2410; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 9, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2411; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 9, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2412; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 9, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2413; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 9, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2414; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 9, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2415; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 9, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2416; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 9, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2417; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 9, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2418; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 10, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2419; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 10, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2420; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 10, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2421; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 10, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2422; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 10, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2423; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 10, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2424; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 10, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2425; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 10, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2426; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 10, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2427; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 11, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2428; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 11, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2429; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 11, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2430; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 11, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2431; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 11, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2432; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 11, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2433; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 11, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2434; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 11, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2435; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 11, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2436; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 12, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2437; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 12, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2438; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 12, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2439; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 12, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2440; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 12, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2441; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 12, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2442; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 12, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2443; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 12, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2444; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 12, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2445; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 13, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2446; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 13, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2447; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 13, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2448; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 13, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2449; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 13, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2450; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 13, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2451; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 13, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2452; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 13, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2453; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 13, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2454; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 14, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2455; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 14, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2456; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 14, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2457; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 14, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2458; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 14, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2459; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 14, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2460; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 14, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2461; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 14, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2462; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 14, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2463; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 15, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2464; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 15, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2465; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 15, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2466; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 15, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2467; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 15, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2468; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 15, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2469; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 15, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2470; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 15, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2471; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 15, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2472; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 0, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2473; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 0, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2474; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 0, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2475; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 0, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2476; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 0, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2477; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 0, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2478; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 0, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2479; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 0, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2480; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 0, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2481; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 1, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2482; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 1, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2483; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 1, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2484; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 1, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2485; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 1, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2486; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 1, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2487; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 1, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2488; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 1, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2489; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 1, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2490; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 2, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2491; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 2, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2492; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 2, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2493; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 2, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2494; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 2, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2495; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 2, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2496; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 2, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2497; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 2, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2498; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 2, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2499; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 3, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2500; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 3, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2501; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 3, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2502; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 3, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2503; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 3, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2504; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 3, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2505; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 3, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2506; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 3, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2507; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 3, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2508; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 4, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2509; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 4, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2510; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 4, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2511; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 4, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2512; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 4, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2513; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 4, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2514; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 4, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2515; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 4, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2516; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 4, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2517; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 5, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2518; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 5, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2519; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 5, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2520; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 5, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2521; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 5, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2522; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 5, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2523; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 5, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2524; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 5, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2525; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 5, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2526; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 6, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2527; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 6, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2528; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 6, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2529; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 6, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2530; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 6, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2531; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 6, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2532; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 6, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2533; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 6, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2534; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 6, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2535; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 7, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2536; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 7, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2537; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 7, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2538; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 7, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2539; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 7, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2540; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 7, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2541; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 7, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2542; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 7, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2543; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 7, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2544; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 8, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2545; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 8, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2546; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 8, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2547; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 8, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2548; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 8, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2549; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 8, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2550; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 8, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2551; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 8, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2552; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 8, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2553; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 9, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2554; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 9, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2555; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 9, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2556; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 9, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2557; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 9, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2558; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 9, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2559; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 9, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2560; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 9, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2561; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 9, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2562; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 10, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2563; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 10, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2564; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 10, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2565; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 10, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2566; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 10, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2567; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 10, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2568; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 10, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2569; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 10, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2570; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 10, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2571; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 11, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2572; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 11, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2573; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 11, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2574; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 11, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2575; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 11, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2576; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 11, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2577; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 11, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2578; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 11, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2579; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 11, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2580; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 12, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2581; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 12, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2582; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 12, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2583; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 12, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2584; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 12, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2585; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 12, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2586; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 12, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2587; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 12, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2588; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 12, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2589; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 13, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2590; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 13, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2591; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 13, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2592; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 13, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2593; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 13, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2594; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 13, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2595; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 13, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2596; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 13, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2597; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 13, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2598; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 14, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2599; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 14, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2600; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 14, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2601; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 14, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2602; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 14, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2603; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 14, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2604; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 14, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2605; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 14, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2606; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 14, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2607; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 15, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2608; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 15, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2609; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 15, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2610; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 15, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2611; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 15, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2612; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 15, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2613; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 15, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2614; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 15, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2615; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 15, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2616; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 0, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2617; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 0, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2618; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 0, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2619; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 0, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2620; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 0, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2621; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 0, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2622; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 0, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2623; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 0, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2624; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 0, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2625; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 1, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2626; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 1, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2627; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 1, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2628; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 1, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2629; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 1, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2630; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 1, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2631; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 1, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2632; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 1, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2633; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 1, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2634; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 2, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2635; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 2, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2636; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 2, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2637; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 2, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2638; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 2, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2639; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 2, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2640; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 2, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2641; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 2, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2642; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 2, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2643; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 3, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2644; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 3, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2645; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 3, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2646; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 3, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2647; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 3, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2648; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 3, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2649; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 3, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2650; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 3, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2651; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 3, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2652; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 4, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2653; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 4, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2654; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 4, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2655; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 4, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2656; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 4, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2657; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 4, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2658; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 4, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2659; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 4, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2660; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 4, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2661; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 5, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2662; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 5, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2663; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 5, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2664; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 5, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2665; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 5, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2666; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 5, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2667; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 5, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2668; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 5, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2669; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 5, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2670; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 6, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2671; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 6, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2672; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 6, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2673; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 6, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2674; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 6, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2675; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 6, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2676; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 6, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2677; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 6, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2678; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 6, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2679; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 7, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2680; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 7, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2681; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 7, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2682; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 7, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2683; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 7, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2684; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 7, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2685; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 7, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2686; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 7, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2687; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 7, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2688; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 8, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2689; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 8, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2690; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 8, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2691; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 8, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2692; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 8, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2693; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 8, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2694; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 8, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2695; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 8, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2696; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 8, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2697; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 9, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2698; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 9, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2699; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 9, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2700; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 9, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2701; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 9, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2702; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 9, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2703; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 9, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2704; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 9, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2705; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 9, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2706; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 10, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2707; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 10, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2708; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 10, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2709; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 10, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2710; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 10, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2711; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 10, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2712; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 10, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2713; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 10, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2714; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 10, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2715; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 11, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2716; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 11, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2717; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 11, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2718; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 11, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2719; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 11, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2720; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 11, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2721; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 11, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2722; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 11, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2723; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 11, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2724; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 12, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2725; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 12, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2726; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 12, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2727; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 12, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2728; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 12, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2729; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 12, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2730; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 12, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2731; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 12, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2732; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 12, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2733; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 13, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2734; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 13, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2735; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 13, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2736; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 13, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2737; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 13, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2738; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 13, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2739; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 13, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2740; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 13, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2741; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 13, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2742; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 14, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2743; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 14, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2744; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 14, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2745; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 14, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2746; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 14, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2747; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 14, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2748; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 14, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2749; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 14, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2750; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 14, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2751; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 15, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2752; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 15, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2753; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 15, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2754; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 15, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2755; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 15, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2756; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 15, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2757; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 15, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2758; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 15, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2759; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 15, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2760; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 0, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2761; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 0, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2762; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 0, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2763; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 0, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2764; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 0, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2765; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 0, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2766; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 0, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2767; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 0, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2768; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 0, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2769; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 1, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2770; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 1, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2771; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 1, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2772; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 1, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2773; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 1, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2774; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 1, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2775; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 1, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2776; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 1, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2777; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 1, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2778; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 2, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2779; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 2, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2780; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 2, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2781; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 2, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2782; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 2, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2783; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 2, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2784; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 2, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2785; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 2, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2786; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 2, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2787; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 3, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2788; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 3, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2789; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 3, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2790; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 3, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2791; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 3, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2792; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 3, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2793; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 3, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2794; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 3, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2795; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 3, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2796; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 4, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2797; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 4, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2798; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 4, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2799; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 4, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2800; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 4, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2801; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 4, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2802; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 4, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2803; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 4, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2804; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 4, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2805; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 5, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2806; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 5, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2807; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 5, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2808; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 5, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2809; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 5, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2810; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 5, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2811; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 5, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2812; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 5, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2813; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 5, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2814; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 6, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2815; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 6, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2816; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 6, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2817; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 6, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2818; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 6, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2819; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 6, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2820; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 6, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2821; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 6, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2822; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 6, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2823; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 7, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2824; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 7, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2825; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 7, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2826; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 7, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2827; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 7, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2828; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 7, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2829; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 7, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2830; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 7, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2831; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 7, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2832; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 8, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2833; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 8, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2834; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 8, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2835; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 8, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2836; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 8, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2837; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 8, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2838; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 8, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2839; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 8, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2840; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 8, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2841; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 9, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2842; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 9, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2843; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 9, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2844; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 9, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2845; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 9, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2846; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 9, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2847; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 9, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2848; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 9, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2849; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 9, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2850; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 10, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2851; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 10, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2852; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 10, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2853; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 10, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2854; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 10, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2855; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 10, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2856; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 10, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2857; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 10, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2858; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 10, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2859; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 11, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2860; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 11, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2861; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 11, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2862; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 11, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2863; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 11, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2864; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 11, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2865; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 11, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2866; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 11, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2867; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 11, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2868; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 12, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2869; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 12, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2870; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 12, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2871; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 12, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2872; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 12, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2873; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 12, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2874; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 12, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2875; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 12, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2876; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 12, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2877; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 13, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2878; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 13, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2879; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 13, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2880; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 13, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2881; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 13, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2882; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 13, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2883; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 13, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2884; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 13, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2885; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 13, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2886; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 14, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2887; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 14, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2888; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 14, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2889; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 14, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2890; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 14, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2891; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 14, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2892; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 14, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2893; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 14, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2894; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 14, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2895; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 15, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2896; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 15, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2897; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 15, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2898; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 15, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2899; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 15, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2900; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 15, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2901; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 15, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2902; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 15, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2903; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 15, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2904; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 0, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2905; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 0, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2906; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 0, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2907; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 0, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2908; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 0, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2909; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 0, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2910; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 0, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2911; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 0, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2912; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 0, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2913; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 1, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2914; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 1, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2915; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 1, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2916; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 1, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2917; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 1, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2918; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 1, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2919; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 1, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2920; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 1, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2921; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 1, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2922; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 2, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2923; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 2, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2924; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 2, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2925; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 2, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2926; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 2, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2927; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 2, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2928; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 2, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2929; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 2, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2930; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 2, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2931; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 3, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2932; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 3, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2933; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 3, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2934; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 3, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2935; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 3, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2936; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 3, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2937; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 3, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2938; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 3, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2939; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 3, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2940; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 4, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2941; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 4, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2942; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 4, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2943; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 4, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2944; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 4, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2945; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 4, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2946; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 4, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2947; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 4, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2948; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 4, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2949; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 5, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2950; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 5, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2951; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 5, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2952; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 5, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2953; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 5, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2954; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 5, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2955; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 5, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2956; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 5, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2957; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 5, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2958; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 6, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2959; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 6, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2960; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 6, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2961; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 6, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2962; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 6, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2963; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 6, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2964; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 6, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2965; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 6, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2966; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 6, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2967; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 7, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2968; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 7, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2969; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 7, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2970; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 7, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2971; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 7, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2972; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 7, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2973; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 7, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2974; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 7, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2975; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 7, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2976; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 8, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2977; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 8, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2978; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 8, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2979; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 8, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2980; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 8, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2981; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 8, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2982; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 8, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2983; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 8, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2984; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 8, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2985; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 9, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2986; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 9, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2987; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 9, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2988; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 9, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2989; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 9, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2990; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 9, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2991; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 9, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2992; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 9, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2993; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 9, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2994; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 10, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2995; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 10, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2996; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 10, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2997; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 10, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2998; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 10, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2999; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 10, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3000; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 10, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3001; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 10, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3002; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 10, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3003; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 11, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3004; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 11, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3005; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 11, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3006; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 11, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3007; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 11, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3008; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 11, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3009; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 11, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3010; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 11, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3011; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 11, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3012; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 12, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3013; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 12, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3014; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 12, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3015; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 12, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3016; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 12, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3017; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 12, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3018; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 12, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3019; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 12, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3020; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 12, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3021; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 13, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3022; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 13, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3023; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 13, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3024; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 13, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3025; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 13, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3026; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 13, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3027; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 13, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3028; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 13, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3029; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 13, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3030; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 14, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3031; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 14, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3032; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 14, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3033; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 14, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3034; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 14, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3035; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 14, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3036; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 14, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3037; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 14, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3038; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 14, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3039; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 15, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3040; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 15, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3041; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 15, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3042; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 15, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3043; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 15, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3044; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 15, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3045; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 15, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3046; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 15, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3047; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 15, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3048; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_ZM, true, true).ID: return 3514; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_ZM, true, false).ID: return 3515; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_ZM, false, true).ID: return 3516; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_ZM, false, false).ID: return 3517; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_ZP, true, true).ID: return 3518; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_ZP, true, false).ID: return 3519; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_ZP, false, true).ID: return 3520; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_ZP, false, false).ID: return 3521; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_XM, true, true).ID: return 3522; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_XM, true, false).ID: return 3523; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_XM, false, true).ID: return 3524; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_XM, false, false).ID: return 3525; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_XP, true, true).ID: return 3526; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_XP, true, false).ID: return 3527; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_XP, false, true).ID: return 3528; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_XP, false, false).ID: return 3529; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_ZM, true, true).ID: return 3530; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_ZM, true, false).ID: return 3531; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_ZM, false, true).ID: return 3532; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_ZM, false, false).ID: return 3533; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_ZP, true, true).ID: return 3534; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_ZP, true, false).ID: return 3535; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_ZP, false, true).ID: return 3536; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_ZP, false, false).ID: return 3537; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_XM, true, true).ID: return 3538; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_XM, true, false).ID: return 3539; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_XM, false, true).ID: return 3540; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_XM, false, false).ID: return 3541; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_XP, true, true).ID: return 3542; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_XP, true, false).ID: return 3543; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_XP, false, true).ID: return 3544; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_XP, false, false).ID: return 3545; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_ZM, true, true).ID: return 3546; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_ZM, true, false).ID: return 3547; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_ZM, false, true).ID: return 3548; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_ZM, false, false).ID: return 3549; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_ZP, true, true).ID: return 3550; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_ZP, true, false).ID: return 3551; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_ZP, false, true).ID: return 3552; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_ZP, false, false).ID: return 3553; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_XM, true, true).ID: return 3554; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_XM, true, false).ID: return 3555; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_XM, false, true).ID: return 3556; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_XM, false, false).ID: return 3557; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_XP, true, true).ID: return 3558; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_XP, true, false).ID: return 3559; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_XP, false, true).ID: return 3560; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_XP, false, false).ID: return 3561; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_ZM, true, true).ID: return 3562; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_ZM, true, false).ID: return 3563; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_ZM, false, true).ID: return 3564; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_ZM, false, false).ID: return 3565; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_ZP, true, true).ID: return 3566; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_ZP, true, false).ID: return 3567; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_ZP, false, true).ID: return 3568; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_ZP, false, false).ID: return 3569; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_XM, true, true).ID: return 3570; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_XM, true, false).ID: return 3571; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_XM, false, true).ID: return 3572; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_XM, false, false).ID: return 3573; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_XP, true, true).ID: return 3574; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_XP, true, false).ID: return 3575; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_XP, false, true).ID: return 3576; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_XP, false, false).ID: return 3577; case RepeatingCommandBlock::RepeatingCommandBlock(true, eBlockFace::BLOCK_FACE_ZM).ID: return 8165; case RepeatingCommandBlock::RepeatingCommandBlock(true, eBlockFace::BLOCK_FACE_XP).ID: return 8166; case RepeatingCommandBlock::RepeatingCommandBlock(true, eBlockFace::BLOCK_FACE_ZP).ID: return 8167; case RepeatingCommandBlock::RepeatingCommandBlock(true, eBlockFace::BLOCK_FACE_XM).ID: return 8168; case RepeatingCommandBlock::RepeatingCommandBlock(true, eBlockFace::BLOCK_FACE_YP).ID: return 8169; case RepeatingCommandBlock::RepeatingCommandBlock(true, eBlockFace::BLOCK_FACE_YM).ID: return 8170; case RepeatingCommandBlock::RepeatingCommandBlock(false, eBlockFace::BLOCK_FACE_ZM).ID: return 8171; case RepeatingCommandBlock::RepeatingCommandBlock(false, eBlockFace::BLOCK_FACE_XP).ID: return 8172; case RepeatingCommandBlock::RepeatingCommandBlock(false, eBlockFace::BLOCK_FACE_ZP).ID: return 8173; case RepeatingCommandBlock::RepeatingCommandBlock(false, eBlockFace::BLOCK_FACE_XM).ID: return 8174; case RepeatingCommandBlock::RepeatingCommandBlock(false, eBlockFace::BLOCK_FACE_YP).ID: return 8175; case RepeatingCommandBlock::RepeatingCommandBlock(false, eBlockFace::BLOCK_FACE_YM).ID: return 8176; case RoseBush::RoseBush(RoseBush::Half::Upper).ID: return 6847; case RoseBush::RoseBush(RoseBush::Half::Lower).ID: return 6848; case Sand::Sand().ID: return 66; case Sandstone::Sandstone().ID: return 245; case SandstoneSlab::SandstoneSlab(SandstoneSlab::Type::Top).ID: return 7301; case SandstoneSlab::SandstoneSlab(SandstoneSlab::Type::Bottom).ID: return 7303; case SandstoneSlab::SandstoneSlab(SandstoneSlab::Type::Double).ID: return 7305; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SandstoneStairs::Half::Top, SandstoneStairs::Shape::Straight).ID: return 4652; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SandstoneStairs::Half::Top, SandstoneStairs::Shape::InnerLeft).ID: return 4654; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SandstoneStairs::Half::Top, SandstoneStairs::Shape::InnerRight).ID: return 4656; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SandstoneStairs::Half::Top, SandstoneStairs::Shape::OuterLeft).ID: return 4658; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SandstoneStairs::Half::Top, SandstoneStairs::Shape::OuterRight).ID: return 4660; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::Straight).ID: return 4662; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::InnerLeft).ID: return 4664; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::InnerRight).ID: return 4666; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::OuterLeft).ID: return 4668; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::OuterRight).ID: return 4670; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SandstoneStairs::Half::Top, SandstoneStairs::Shape::Straight).ID: return 4672; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SandstoneStairs::Half::Top, SandstoneStairs::Shape::InnerLeft).ID: return 4674; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SandstoneStairs::Half::Top, SandstoneStairs::Shape::InnerRight).ID: return 4676; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SandstoneStairs::Half::Top, SandstoneStairs::Shape::OuterLeft).ID: return 4678; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SandstoneStairs::Half::Top, SandstoneStairs::Shape::OuterRight).ID: return 4680; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::Straight).ID: return 4682; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::InnerLeft).ID: return 4684; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::InnerRight).ID: return 4686; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::OuterLeft).ID: return 4688; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::OuterRight).ID: return 4690; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XM, SandstoneStairs::Half::Top, SandstoneStairs::Shape::Straight).ID: return 4692; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XM, SandstoneStairs::Half::Top, SandstoneStairs::Shape::InnerLeft).ID: return 4694; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XM, SandstoneStairs::Half::Top, SandstoneStairs::Shape::InnerRight).ID: return 4696; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XM, SandstoneStairs::Half::Top, SandstoneStairs::Shape::OuterLeft).ID: return 4698; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XM, SandstoneStairs::Half::Top, SandstoneStairs::Shape::OuterRight).ID: return 4700; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XM, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::Straight).ID: return 4702; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XM, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::InnerLeft).ID: return 4704; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XM, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::InnerRight).ID: return 4706; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XM, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::OuterLeft).ID: return 4708; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XM, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::OuterRight).ID: return 4710; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XP, SandstoneStairs::Half::Top, SandstoneStairs::Shape::Straight).ID: return 4712; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XP, SandstoneStairs::Half::Top, SandstoneStairs::Shape::InnerLeft).ID: return 4714; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XP, SandstoneStairs::Half::Top, SandstoneStairs::Shape::InnerRight).ID: return 4716; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XP, SandstoneStairs::Half::Top, SandstoneStairs::Shape::OuterLeft).ID: return 4718; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XP, SandstoneStairs::Half::Top, SandstoneStairs::Shape::OuterRight).ID: return 4720; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XP, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::Straight).ID: return 4722; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XP, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::InnerLeft).ID: return 4724; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XP, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::InnerRight).ID: return 4726; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XP, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::OuterLeft).ID: return 4728; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XP, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::OuterRight).ID: return 4730; case SeaLantern::SeaLantern().ID: return 6820; case SeaPickle::SeaPickle(1).ID: return 8581; case SeaPickle::SeaPickle(2).ID: return 8583; case SeaPickle::SeaPickle(3).ID: return 8585; case SeaPickle::SeaPickle(4).ID: return 8587; case Seagrass::Seagrass().ID: return 1044; case ShulkerBox::ShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 8212; case ShulkerBox::ShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 8213; case ShulkerBox::ShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 8214; case ShulkerBox::ShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 8215; case ShulkerBox::ShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 8216; case ShulkerBox::ShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 8217; case OakSign::OakSign(0).ID: return 3077; case OakSign::OakSign(1).ID: return 3079; case OakSign::OakSign(2).ID: return 3081; case OakSign::OakSign(3).ID: return 3083; case OakSign::OakSign(4).ID: return 3085; case OakSign::OakSign(5).ID: return 3087; case OakSign::OakSign(6).ID: return 3089; case OakSign::OakSign(7).ID: return 3091; case OakSign::OakSign(8).ID: return 3093; case OakSign::OakSign(9).ID: return 3095; case OakSign::OakSign(10).ID: return 3097; case OakSign::OakSign(11).ID: return 3099; case OakSign::OakSign(12).ID: return 3101; case OakSign::OakSign(13).ID: return 3103; case OakSign::OakSign(14).ID: return 3105; case OakSign::OakSign(15).ID: return 3107; case SkeletonSkull::SkeletonSkull(0).ID: return 5452; case SkeletonSkull::SkeletonSkull(1).ID: return 5453; case SkeletonSkull::SkeletonSkull(2).ID: return 5454; case SkeletonSkull::SkeletonSkull(3).ID: return 5455; case SkeletonSkull::SkeletonSkull(4).ID: return 5456; case SkeletonSkull::SkeletonSkull(5).ID: return 5457; case SkeletonSkull::SkeletonSkull(6).ID: return 5458; case SkeletonSkull::SkeletonSkull(7).ID: return 5459; case SkeletonSkull::SkeletonSkull(8).ID: return 5460; case SkeletonSkull::SkeletonSkull(9).ID: return 5461; case SkeletonSkull::SkeletonSkull(10).ID: return 5462; case SkeletonSkull::SkeletonSkull(11).ID: return 5463; case SkeletonSkull::SkeletonSkull(12).ID: return 5464; case SkeletonSkull::SkeletonSkull(13).ID: return 5465; case SkeletonSkull::SkeletonSkull(14).ID: return 5466; case SkeletonSkull::SkeletonSkull(15).ID: return 5467; case SkeletonWallSkull::SkeletonWallSkull(eBlockFace::BLOCK_FACE_ZM).ID: return 5448; case SkeletonWallSkull::SkeletonWallSkull(eBlockFace::BLOCK_FACE_ZP).ID: return 5449; case SkeletonWallSkull::SkeletonWallSkull(eBlockFace::BLOCK_FACE_XM).ID: return 5450; case SkeletonWallSkull::SkeletonWallSkull(eBlockFace::BLOCK_FACE_XP).ID: return 5451; case SlimeBlock::SlimeBlock().ID: return 6493; case SmoothQuartz::SmoothQuartz().ID: return 7356; case SmoothRedSandstone::SmoothRedSandstone().ID: return 7357; case SmoothSandstone::SmoothSandstone().ID: return 7355; case SmoothStone::SmoothStone().ID: return 7354; case Snow::Snow(1).ID: return 3416; case Snow::Snow(2).ID: return 3417; case Snow::Snow(3).ID: return 3418; case Snow::Snow(4).ID: return 3419; case Snow::Snow(5).ID: return 3420; case Snow::Snow(6).ID: return 3421; case Snow::Snow(7).ID: return 3422; case Snow::Snow(8).ID: return 3423; case SnowBlock::SnowBlock().ID: return 3425; case SoulSand::SoulSand().ID: return 3495; case Spawner::Spawner().ID: return 1648; case Sponge::Sponge().ID: return 228; case SpruceButton::SpruceButton(SpruceButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5328; case SpruceButton::SpruceButton(SpruceButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5329; case SpruceButton::SpruceButton(SpruceButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5330; case SpruceButton::SpruceButton(SpruceButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5331; case SpruceButton::SpruceButton(SpruceButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, true).ID: return 5332; case SpruceButton::SpruceButton(SpruceButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, false).ID: return 5333; case SpruceButton::SpruceButton(SpruceButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, true).ID: return 5334; case SpruceButton::SpruceButton(SpruceButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, false).ID: return 5335; case SpruceButton::SpruceButton(SpruceButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5336; case SpruceButton::SpruceButton(SpruceButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5337; case SpruceButton::SpruceButton(SpruceButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5338; case SpruceButton::SpruceButton(SpruceButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5339; case SpruceButton::SpruceButton(SpruceButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, true).ID: return 5340; case SpruceButton::SpruceButton(SpruceButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, false).ID: return 5341; case SpruceButton::SpruceButton(SpruceButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, true).ID: return 5342; case SpruceButton::SpruceButton(SpruceButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, false).ID: return 5343; case SpruceButton::SpruceButton(SpruceButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5344; case SpruceButton::SpruceButton(SpruceButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5345; case SpruceButton::SpruceButton(SpruceButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5346; case SpruceButton::SpruceButton(SpruceButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5347; case SpruceButton::SpruceButton(SpruceButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, true).ID: return 5348; case SpruceButton::SpruceButton(SpruceButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, false).ID: return 5349; case SpruceButton::SpruceButton(SpruceButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, true).ID: return 5350; case SpruceButton::SpruceButton(SpruceButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, false).ID: return 5351; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, true, true).ID: return 7678; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, true, false).ID: return 7679; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, false, true).ID: return 7680; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, false, false).ID: return 7681; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, true, true).ID: return 7682; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, true, false).ID: return 7683; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, false, true).ID: return 7684; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, false, false).ID: return 7685; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, true, true).ID: return 7686; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, true, false).ID: return 7687; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, false, true).ID: return 7688; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, false, false).ID: return 7689; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, true, true).ID: return 7690; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, true, false).ID: return 7691; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, false, true).ID: return 7692; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, false, false).ID: return 7693; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, true, true).ID: return 7694; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, true, false).ID: return 7695; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, false, true).ID: return 7696; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, false, false).ID: return 7697; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, true, true).ID: return 7698; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, true, false).ID: return 7699; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, false, true).ID: return 7700; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, false, false).ID: return 7701; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, true, true).ID: return 7702; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, true, false).ID: return 7703; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, false, true).ID: return 7704; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, false, false).ID: return 7705; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, true, true).ID: return 7706; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, true, false).ID: return 7707; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, false, true).ID: return 7708; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, false, false).ID: return 7709; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, true, true).ID: return 7710; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, true, false).ID: return 7711; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, false, true).ID: return 7712; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, false, false).ID: return 7713; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, true, true).ID: return 7714; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, true, false).ID: return 7715; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, false, true).ID: return 7716; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, false, false).ID: return 7717; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, true, true).ID: return 7718; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, true, false).ID: return 7719; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, false, true).ID: return 7720; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, false, false).ID: return 7721; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, true, true).ID: return 7722; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, true, false).ID: return 7723; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, false, true).ID: return 7724; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, false, false).ID: return 7725; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, true, true).ID: return 7726; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, true, false).ID: return 7727; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, false, true).ID: return 7728; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, false, false).ID: return 7729; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, true, true).ID: return 7730; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, true, false).ID: return 7731; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, false, true).ID: return 7732; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, false, false).ID: return 7733; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, true, true).ID: return 7734; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, true, false).ID: return 7735; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, false, true).ID: return 7736; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, false, false).ID: return 7737; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, true, true).ID: return 7738; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, true, false).ID: return 7739; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, false, true).ID: return 7740; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, false, false).ID: return 7741; case SpruceFence::SpruceFence(true, true, true, true).ID: return 7520; case SpruceFence::SpruceFence(true, true, true, false).ID: return 7521; case SpruceFence::SpruceFence(true, true, false, true).ID: return 7524; case SpruceFence::SpruceFence(true, true, false, false).ID: return 7525; case SpruceFence::SpruceFence(true, false, true, true).ID: return 7528; case SpruceFence::SpruceFence(true, false, true, false).ID: return 7529; case SpruceFence::SpruceFence(true, false, false, true).ID: return 7532; case SpruceFence::SpruceFence(true, false, false, false).ID: return 7533; case SpruceFence::SpruceFence(false, true, true, true).ID: return 7536; case SpruceFence::SpruceFence(false, true, true, false).ID: return 7537; case SpruceFence::SpruceFence(false, true, false, true).ID: return 7540; case SpruceFence::SpruceFence(false, true, false, false).ID: return 7541; case SpruceFence::SpruceFence(false, false, true, true).ID: return 7544; case SpruceFence::SpruceFence(false, false, true, false).ID: return 7545; case SpruceFence::SpruceFence(false, false, false, true).ID: return 7548; case SpruceFence::SpruceFence(false, false, false, false).ID: return 7549; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZM, true, true, true).ID: return 7358; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZM, true, true, false).ID: return 7359; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZM, true, false, true).ID: return 7360; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZM, true, false, false).ID: return 7361; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, true).ID: return 7362; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, false).ID: return 7363; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, true).ID: return 7364; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, false).ID: return 7365; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZP, true, true, true).ID: return 7366; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZP, true, true, false).ID: return 7367; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZP, true, false, true).ID: return 7368; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZP, true, false, false).ID: return 7369; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, true).ID: return 7370; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, false).ID: return 7371; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, true).ID: return 7372; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, false).ID: return 7373; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XM, true, true, true).ID: return 7374; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XM, true, true, false).ID: return 7375; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XM, true, false, true).ID: return 7376; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XM, true, false, false).ID: return 7377; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, true).ID: return 7378; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, false).ID: return 7379; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, true).ID: return 7380; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, false).ID: return 7381; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XP, true, true, true).ID: return 7382; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XP, true, true, false).ID: return 7383; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XP, true, false, true).ID: return 7384; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XP, true, false, false).ID: return 7385; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, true).ID: return 7386; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, false).ID: return 7387; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, true).ID: return 7388; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, false).ID: return 7389; case SpruceLeaves::SpruceLeaves(1, true).ID: return 158; case SpruceLeaves::SpruceLeaves(1, false).ID: return 159; case SpruceLeaves::SpruceLeaves(2, true).ID: return 160; case SpruceLeaves::SpruceLeaves(2, false).ID: return 161; case SpruceLeaves::SpruceLeaves(3, true).ID: return 162; case SpruceLeaves::SpruceLeaves(3, false).ID: return 163; case SpruceLeaves::SpruceLeaves(4, true).ID: return 164; case SpruceLeaves::SpruceLeaves(4, false).ID: return 165; case SpruceLeaves::SpruceLeaves(5, true).ID: return 166; case SpruceLeaves::SpruceLeaves(5, false).ID: return 167; case SpruceLeaves::SpruceLeaves(6, true).ID: return 168; case SpruceLeaves::SpruceLeaves(6, false).ID: return 169; case SpruceLeaves::SpruceLeaves(7, true).ID: return 170; case SpruceLeaves::SpruceLeaves(7, false).ID: return 171; case SpruceLog::SpruceLog(SpruceLog::Axis::X).ID: return 75; case SpruceLog::SpruceLog(SpruceLog::Axis::Y).ID: return 76; case SpruceLog::SpruceLog(SpruceLog::Axis::Z).ID: return 77; case SprucePlanks::SprucePlanks().ID: return 16; case SprucePressurePlate::SprucePressurePlate(true).ID: return 3370; case SprucePressurePlate::SprucePressurePlate(false).ID: return 3371; case SpruceSapling::SpruceSapling(0).ID: return 23; case SpruceSapling::SpruceSapling(1).ID: return 24; case SpruceSlab::SpruceSlab(SpruceSlab::Type::Top).ID: return 7265; case SpruceSlab::SpruceSlab(SpruceSlab::Type::Bottom).ID: return 7267; case SpruceSlab::SpruceSlab(SpruceSlab::Type::Double).ID: return 7269; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZM, SpruceStairs::Half::Top, SpruceStairs::Shape::Straight).ID: return 4886; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZM, SpruceStairs::Half::Top, SpruceStairs::Shape::InnerLeft).ID: return 4888; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZM, SpruceStairs::Half::Top, SpruceStairs::Shape::InnerRight).ID: return 4890; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZM, SpruceStairs::Half::Top, SpruceStairs::Shape::OuterLeft).ID: return 4892; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZM, SpruceStairs::Half::Top, SpruceStairs::Shape::OuterRight).ID: return 4894; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZM, SpruceStairs::Half::Bottom, SpruceStairs::Shape::Straight).ID: return 4896; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZM, SpruceStairs::Half::Bottom, SpruceStairs::Shape::InnerLeft).ID: return 4898; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZM, SpruceStairs::Half::Bottom, SpruceStairs::Shape::InnerRight).ID: return 4900; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZM, SpruceStairs::Half::Bottom, SpruceStairs::Shape::OuterLeft).ID: return 4902; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZM, SpruceStairs::Half::Bottom, SpruceStairs::Shape::OuterRight).ID: return 4904; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZP, SpruceStairs::Half::Top, SpruceStairs::Shape::Straight).ID: return 4906; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZP, SpruceStairs::Half::Top, SpruceStairs::Shape::InnerLeft).ID: return 4908; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZP, SpruceStairs::Half::Top, SpruceStairs::Shape::InnerRight).ID: return 4910; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZP, SpruceStairs::Half::Top, SpruceStairs::Shape::OuterLeft).ID: return 4912; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZP, SpruceStairs::Half::Top, SpruceStairs::Shape::OuterRight).ID: return 4914; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZP, SpruceStairs::Half::Bottom, SpruceStairs::Shape::Straight).ID: return 4916; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZP, SpruceStairs::Half::Bottom, SpruceStairs::Shape::InnerLeft).ID: return 4918; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZP, SpruceStairs::Half::Bottom, SpruceStairs::Shape::InnerRight).ID: return 4920; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZP, SpruceStairs::Half::Bottom, SpruceStairs::Shape::OuterLeft).ID: return 4922; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZP, SpruceStairs::Half::Bottom, SpruceStairs::Shape::OuterRight).ID: return 4924; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XM, SpruceStairs::Half::Top, SpruceStairs::Shape::Straight).ID: return 4926; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XM, SpruceStairs::Half::Top, SpruceStairs::Shape::InnerLeft).ID: return 4928; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XM, SpruceStairs::Half::Top, SpruceStairs::Shape::InnerRight).ID: return 4930; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XM, SpruceStairs::Half::Top, SpruceStairs::Shape::OuterLeft).ID: return 4932; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XM, SpruceStairs::Half::Top, SpruceStairs::Shape::OuterRight).ID: return 4934; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XM, SpruceStairs::Half::Bottom, SpruceStairs::Shape::Straight).ID: return 4936; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XM, SpruceStairs::Half::Bottom, SpruceStairs::Shape::InnerLeft).ID: return 4938; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XM, SpruceStairs::Half::Bottom, SpruceStairs::Shape::InnerRight).ID: return 4940; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XM, SpruceStairs::Half::Bottom, SpruceStairs::Shape::OuterLeft).ID: return 4942; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XM, SpruceStairs::Half::Bottom, SpruceStairs::Shape::OuterRight).ID: return 4944; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XP, SpruceStairs::Half::Top, SpruceStairs::Shape::Straight).ID: return 4946; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XP, SpruceStairs::Half::Top, SpruceStairs::Shape::InnerLeft).ID: return 4948; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XP, SpruceStairs::Half::Top, SpruceStairs::Shape::InnerRight).ID: return 4950; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XP, SpruceStairs::Half::Top, SpruceStairs::Shape::OuterLeft).ID: return 4952; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XP, SpruceStairs::Half::Top, SpruceStairs::Shape::OuterRight).ID: return 4954; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XP, SpruceStairs::Half::Bottom, SpruceStairs::Shape::Straight).ID: return 4956; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XP, SpruceStairs::Half::Bottom, SpruceStairs::Shape::InnerLeft).ID: return 4958; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XP, SpruceStairs::Half::Bottom, SpruceStairs::Shape::InnerRight).ID: return 4960; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XP, SpruceStairs::Half::Bottom, SpruceStairs::Shape::OuterLeft).ID: return 4962; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XP, SpruceStairs::Half::Bottom, SpruceStairs::Shape::OuterRight).ID: return 4964; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZM, SpruceTrapdoor::Half::Top, true, true).ID: return 3659; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZM, SpruceTrapdoor::Half::Top, true, false).ID: return 3661; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZM, SpruceTrapdoor::Half::Top, false, true).ID: return 3663; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZM, SpruceTrapdoor::Half::Top, false, false).ID: return 3665; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZM, SpruceTrapdoor::Half::Bottom, true, true).ID: return 3667; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZM, SpruceTrapdoor::Half::Bottom, true, false).ID: return 3669; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZM, SpruceTrapdoor::Half::Bottom, false, true).ID: return 3671; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZM, SpruceTrapdoor::Half::Bottom, false, false).ID: return 3673; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZP, SpruceTrapdoor::Half::Top, true, true).ID: return 3675; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZP, SpruceTrapdoor::Half::Top, true, false).ID: return 3677; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZP, SpruceTrapdoor::Half::Top, false, true).ID: return 3679; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZP, SpruceTrapdoor::Half::Top, false, false).ID: return 3681; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZP, SpruceTrapdoor::Half::Bottom, true, true).ID: return 3683; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZP, SpruceTrapdoor::Half::Bottom, true, false).ID: return 3685; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZP, SpruceTrapdoor::Half::Bottom, false, true).ID: return 3687; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZP, SpruceTrapdoor::Half::Bottom, false, false).ID: return 3689; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XM, SpruceTrapdoor::Half::Top, true, true).ID: return 3691; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XM, SpruceTrapdoor::Half::Top, true, false).ID: return 3693; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XM, SpruceTrapdoor::Half::Top, false, true).ID: return 3695; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XM, SpruceTrapdoor::Half::Top, false, false).ID: return 3697; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XM, SpruceTrapdoor::Half::Bottom, true, true).ID: return 3699; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XM, SpruceTrapdoor::Half::Bottom, true, false).ID: return 3701; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XM, SpruceTrapdoor::Half::Bottom, false, true).ID: return 3703; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XM, SpruceTrapdoor::Half::Bottom, false, false).ID: return 3705; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XP, SpruceTrapdoor::Half::Top, true, true).ID: return 3707; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XP, SpruceTrapdoor::Half::Top, true, false).ID: return 3709; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XP, SpruceTrapdoor::Half::Top, false, true).ID: return 3711; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XP, SpruceTrapdoor::Half::Top, false, false).ID: return 3713; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XP, SpruceTrapdoor::Half::Bottom, true, true).ID: return 3715; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XP, SpruceTrapdoor::Half::Bottom, true, false).ID: return 3717; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XP, SpruceTrapdoor::Half::Bottom, false, true).ID: return 3719; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XP, SpruceTrapdoor::Half::Bottom, false, false).ID: return 3721; case SpruceWood::SpruceWood(SpruceWood::Axis::X).ID: return 111; case SpruceWood::SpruceWood(SpruceWood::Axis::Y).ID: return 112; case SpruceWood::SpruceWood(SpruceWood::Axis::Z).ID: return 113; case StickyPiston::StickyPiston(true, eBlockFace::BLOCK_FACE_ZM).ID: return 1028; case StickyPiston::StickyPiston(true, eBlockFace::BLOCK_FACE_XP).ID: return 1029; case StickyPiston::StickyPiston(true, eBlockFace::BLOCK_FACE_ZP).ID: return 1030; case StickyPiston::StickyPiston(true, eBlockFace::BLOCK_FACE_XM).ID: return 1031; case StickyPiston::StickyPiston(true, eBlockFace::BLOCK_FACE_YP).ID: return 1032; case StickyPiston::StickyPiston(true, eBlockFace::BLOCK_FACE_YM).ID: return 1033; case StickyPiston::StickyPiston(false, eBlockFace::BLOCK_FACE_ZM).ID: return 1034; case StickyPiston::StickyPiston(false, eBlockFace::BLOCK_FACE_XP).ID: return 1035; case StickyPiston::StickyPiston(false, eBlockFace::BLOCK_FACE_ZP).ID: return 1036; case StickyPiston::StickyPiston(false, eBlockFace::BLOCK_FACE_XM).ID: return 1037; case StickyPiston::StickyPiston(false, eBlockFace::BLOCK_FACE_YP).ID: return 1038; case StickyPiston::StickyPiston(false, eBlockFace::BLOCK_FACE_YM).ID: return 1039; case Stone::Stone().ID: return 1; case StoneBrickSlab::StoneBrickSlab(StoneBrickSlab::Type::Top).ID: return 7325; case StoneBrickSlab::StoneBrickSlab(StoneBrickSlab::Type::Bottom).ID: return 7327; case StoneBrickSlab::StoneBrickSlab(StoneBrickSlab::Type::Double).ID: return 7329; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::Straight).ID: return 4414; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::InnerLeft).ID: return 4416; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::InnerRight).ID: return 4418; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::OuterLeft).ID: return 4420; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::OuterRight).ID: return 4422; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::Straight).ID: return 4424; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::InnerLeft).ID: return 4426; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::InnerRight).ID: return 4428; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::OuterLeft).ID: return 4430; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::OuterRight).ID: return 4432; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::Straight).ID: return 4434; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::InnerLeft).ID: return 4436; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::InnerRight).ID: return 4438; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::OuterLeft).ID: return 4440; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::OuterRight).ID: return 4442; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::Straight).ID: return 4444; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::InnerLeft).ID: return 4446; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::InnerRight).ID: return 4448; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::OuterLeft).ID: return 4450; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::OuterRight).ID: return 4452; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XM, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::Straight).ID: return 4454; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XM, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::InnerLeft).ID: return 4456; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XM, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::InnerRight).ID: return 4458; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XM, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::OuterLeft).ID: return 4460; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XM, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::OuterRight).ID: return 4462; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XM, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::Straight).ID: return 4464; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XM, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::InnerLeft).ID: return 4466; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XM, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::InnerRight).ID: return 4468; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XM, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::OuterLeft).ID: return 4470; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XM, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::OuterRight).ID: return 4472; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XP, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::Straight).ID: return 4474; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XP, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::InnerLeft).ID: return 4476; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XP, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::InnerRight).ID: return 4478; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XP, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::OuterLeft).ID: return 4480; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XP, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::OuterRight).ID: return 4482; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XP, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::Straight).ID: return 4484; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XP, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::InnerLeft).ID: return 4486; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XP, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::InnerRight).ID: return 4488; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XP, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::OuterLeft).ID: return 4490; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XP, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::OuterRight).ID: return 4492; case StoneBricks::StoneBricks().ID: return 3984; case StoneButton::StoneButton(StoneButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, true).ID: return 3392; case StoneButton::StoneButton(StoneButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, false).ID: return 3393; case StoneButton::StoneButton(StoneButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, true).ID: return 3394; case StoneButton::StoneButton(StoneButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, false).ID: return 3395; case StoneButton::StoneButton(StoneButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, true).ID: return 3396; case StoneButton::StoneButton(StoneButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, false).ID: return 3397; case StoneButton::StoneButton(StoneButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, true).ID: return 3398; case StoneButton::StoneButton(StoneButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, false).ID: return 3399; case StoneButton::StoneButton(StoneButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, true).ID: return 3400; case StoneButton::StoneButton(StoneButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, false).ID: return 3401; case StoneButton::StoneButton(StoneButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, true).ID: return 3402; case StoneButton::StoneButton(StoneButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, false).ID: return 3403; case StoneButton::StoneButton(StoneButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, true).ID: return 3404; case StoneButton::StoneButton(StoneButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, false).ID: return 3405; case StoneButton::StoneButton(StoneButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, true).ID: return 3406; case StoneButton::StoneButton(StoneButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, false).ID: return 3407; case StoneButton::StoneButton(StoneButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, true).ID: return 3408; case StoneButton::StoneButton(StoneButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, false).ID: return 3409; case StoneButton::StoneButton(StoneButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, true).ID: return 3410; case StoneButton::StoneButton(StoneButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, false).ID: return 3411; case StoneButton::StoneButton(StoneButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, true).ID: return 3412; case StoneButton::StoneButton(StoneButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, false).ID: return 3413; case StoneButton::StoneButton(StoneButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, true).ID: return 3414; case StoneButton::StoneButton(StoneButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, false).ID: return 3415; case StonePressurePlate::StonePressurePlate(true).ID: return 3302; case StonePressurePlate::StonePressurePlate(false).ID: return 3303; case StoneSlab::StoneSlab(StoneSlab::Type::Top).ID: return 7295; case StoneSlab::StoneSlab(StoneSlab::Type::Bottom).ID: return 7297; case StoneSlab::StoneSlab(StoneSlab::Type::Double).ID: return 7299; case StrippedAcaciaLog::StrippedAcaciaLog(StrippedAcaciaLog::Axis::X).ID: return 99; case StrippedAcaciaLog::StrippedAcaciaLog(StrippedAcaciaLog::Axis::Y).ID: return 100; case StrippedAcaciaLog::StrippedAcaciaLog(StrippedAcaciaLog::Axis::Z).ID: return 101; case StrippedAcaciaWood::StrippedAcaciaWood(StrippedAcaciaWood::Axis::X).ID: return 138; case StrippedAcaciaWood::StrippedAcaciaWood(StrippedAcaciaWood::Axis::Y).ID: return 139; case StrippedAcaciaWood::StrippedAcaciaWood(StrippedAcaciaWood::Axis::Z).ID: return 140; case StrippedBirchLog::StrippedBirchLog(StrippedBirchLog::Axis::X).ID: return 93; case StrippedBirchLog::StrippedBirchLog(StrippedBirchLog::Axis::Y).ID: return 94; case StrippedBirchLog::StrippedBirchLog(StrippedBirchLog::Axis::Z).ID: return 95; case StrippedBirchWood::StrippedBirchWood(StrippedBirchWood::Axis::X).ID: return 132; case StrippedBirchWood::StrippedBirchWood(StrippedBirchWood::Axis::Y).ID: return 133; case StrippedBirchWood::StrippedBirchWood(StrippedBirchWood::Axis::Z).ID: return 134; case StrippedDarkOakLog::StrippedDarkOakLog(StrippedDarkOakLog::Axis::X).ID: return 102; case StrippedDarkOakLog::StrippedDarkOakLog(StrippedDarkOakLog::Axis::Y).ID: return 103; case StrippedDarkOakLog::StrippedDarkOakLog(StrippedDarkOakLog::Axis::Z).ID: return 104; case StrippedDarkOakWood::StrippedDarkOakWood(StrippedDarkOakWood::Axis::X).ID: return 141; case StrippedDarkOakWood::StrippedDarkOakWood(StrippedDarkOakWood::Axis::Y).ID: return 142; case StrippedDarkOakWood::StrippedDarkOakWood(StrippedDarkOakWood::Axis::Z).ID: return 143; case StrippedJungleLog::StrippedJungleLog(StrippedJungleLog::Axis::X).ID: return 96; case StrippedJungleLog::StrippedJungleLog(StrippedJungleLog::Axis::Y).ID: return 97; case StrippedJungleLog::StrippedJungleLog(StrippedJungleLog::Axis::Z).ID: return 98; case StrippedJungleWood::StrippedJungleWood(StrippedJungleWood::Axis::X).ID: return 135; case StrippedJungleWood::StrippedJungleWood(StrippedJungleWood::Axis::Y).ID: return 136; case StrippedJungleWood::StrippedJungleWood(StrippedJungleWood::Axis::Z).ID: return 137; case StrippedOakLog::StrippedOakLog(StrippedOakLog::Axis::X).ID: return 105; case StrippedOakLog::StrippedOakLog(StrippedOakLog::Axis::Y).ID: return 106; case StrippedOakLog::StrippedOakLog(StrippedOakLog::Axis::Z).ID: return 107; case StrippedOakWood::StrippedOakWood(StrippedOakWood::Axis::X).ID: return 126; case StrippedOakWood::StrippedOakWood(StrippedOakWood::Axis::Y).ID: return 127; case StrippedOakWood::StrippedOakWood(StrippedOakWood::Axis::Z).ID: return 128; case StrippedSpruceLog::StrippedSpruceLog(StrippedSpruceLog::Axis::X).ID: return 90; case StrippedSpruceLog::StrippedSpruceLog(StrippedSpruceLog::Axis::Y).ID: return 91; case StrippedSpruceLog::StrippedSpruceLog(StrippedSpruceLog::Axis::Z).ID: return 92; case StrippedSpruceWood::StrippedSpruceWood(StrippedSpruceWood::Axis::X).ID: return 129; case StrippedSpruceWood::StrippedSpruceWood(StrippedSpruceWood::Axis::Y).ID: return 130; case StrippedSpruceWood::StrippedSpruceWood(StrippedSpruceWood::Axis::Z).ID: return 131; case StructureBlock::StructureBlock(StructureBlock::Mode::Save).ID: return 8595; case StructureBlock::StructureBlock(StructureBlock::Mode::Load).ID: return 8596; case StructureBlock::StructureBlock(StructureBlock::Mode::Corner).ID: return 8597; case StructureBlock::StructureBlock(StructureBlock::Mode::Data).ID: return 8598; case StructureVoid::StructureVoid().ID: return 8199; case SugarCane::SugarCane(0).ID: return 3443; case SugarCane::SugarCane(1).ID: return 3444; case SugarCane::SugarCane(2).ID: return 3445; case SugarCane::SugarCane(3).ID: return 3446; case SugarCane::SugarCane(4).ID: return 3447; case SugarCane::SugarCane(5).ID: return 3448; case SugarCane::SugarCane(6).ID: return 3449; case SugarCane::SugarCane(7).ID: return 3450; case SugarCane::SugarCane(8).ID: return 3451; case SugarCane::SugarCane(9).ID: return 3452; case SugarCane::SugarCane(10).ID: return 3453; case SugarCane::SugarCane(11).ID: return 3454; case SugarCane::SugarCane(12).ID: return 3455; case SugarCane::SugarCane(13).ID: return 3456; case SugarCane::SugarCane(14).ID: return 3457; case SugarCane::SugarCane(15).ID: return 3458; case Sunflower::Sunflower(Sunflower::Half::Upper).ID: return 6843; case Sunflower::Sunflower(Sunflower::Half::Lower).ID: return 6844; case TNT::TNT(true).ID: return 1126; case TNT::TNT(false).ID: return 1127; case TallGrass::TallGrass(TallGrass::Half::Upper).ID: return 6851; case TallGrass::TallGrass(TallGrass::Half::Lower).ID: return 6852; case TallSeagrass::TallSeagrass(TallSeagrass::Half::Upper).ID: return 1045; case TallSeagrass::TallSeagrass(TallSeagrass::Half::Lower).ID: return 1046; case Terracotta::Terracotta().ID: return 6840; case Torch::Torch().ID: return 1131; case TrappedChest::TrappedChest(eBlockFace::BLOCK_FACE_ZM, TrappedChest::Type::Single).ID: return 5581; case TrappedChest::TrappedChest(eBlockFace::BLOCK_FACE_ZM, TrappedChest::Type::Left).ID: return 5583; case TrappedChest::TrappedChest(eBlockFace::BLOCK_FACE_ZM, TrappedChest::Type::Right).ID: return 5585; case TrappedChest::TrappedChest(eBlockFace::BLOCK_FACE_ZP, TrappedChest::Type::Single).ID: return 5587; case TrappedChest::TrappedChest(eBlockFace::BLOCK_FACE_ZP, TrappedChest::Type::Left).ID: return 5589; case TrappedChest::TrappedChest(eBlockFace::BLOCK_FACE_ZP, TrappedChest::Type::Right).ID: return 5591; case TrappedChest::TrappedChest(eBlockFace::BLOCK_FACE_XM, TrappedChest::Type::Single).ID: return 5593; case TrappedChest::TrappedChest(eBlockFace::BLOCK_FACE_XM, TrappedChest::Type::Left).ID: return 5595; case TrappedChest::TrappedChest(eBlockFace::BLOCK_FACE_XM, TrappedChest::Type::Right).ID: return 5597; case TrappedChest::TrappedChest(eBlockFace::BLOCK_FACE_XP, TrappedChest::Type::Single).ID: return 5599; case TrappedChest::TrappedChest(eBlockFace::BLOCK_FACE_XP, TrappedChest::Type::Left).ID: return 5601; case TrappedChest::TrappedChest(eBlockFace::BLOCK_FACE_XP, TrappedChest::Type::Right).ID: return 5603; case Tripwire::Tripwire(true, true, true, true, true, true, true).ID: return 4756; case Tripwire::Tripwire(true, true, true, true, true, true, false).ID: return 4757; case Tripwire::Tripwire(true, true, true, true, true, false, true).ID: return 4758; case Tripwire::Tripwire(true, true, true, true, true, false, false).ID: return 4759; case Tripwire::Tripwire(true, true, true, true, false, true, true).ID: return 4760; case Tripwire::Tripwire(true, true, true, true, false, true, false).ID: return 4761; case Tripwire::Tripwire(true, true, true, true, false, false, true).ID: return 4762; case Tripwire::Tripwire(true, true, true, true, false, false, false).ID: return 4763; case Tripwire::Tripwire(true, true, true, false, true, true, true).ID: return 4764; case Tripwire::Tripwire(true, true, true, false, true, true, false).ID: return 4765; case Tripwire::Tripwire(true, true, true, false, true, false, true).ID: return 4766; case Tripwire::Tripwire(true, true, true, false, true, false, false).ID: return 4767; case Tripwire::Tripwire(true, true, true, false, false, true, true).ID: return 4768; case Tripwire::Tripwire(true, true, true, false, false, true, false).ID: return 4769; case Tripwire::Tripwire(true, true, true, false, false, false, true).ID: return 4770; case Tripwire::Tripwire(true, true, true, false, false, false, false).ID: return 4771; case Tripwire::Tripwire(true, true, false, true, true, true, true).ID: return 4772; case Tripwire::Tripwire(true, true, false, true, true, true, false).ID: return 4773; case Tripwire::Tripwire(true, true, false, true, true, false, true).ID: return 4774; case Tripwire::Tripwire(true, true, false, true, true, false, false).ID: return 4775; case Tripwire::Tripwire(true, true, false, true, false, true, true).ID: return 4776; case Tripwire::Tripwire(true, true, false, true, false, true, false).ID: return 4777; case Tripwire::Tripwire(true, true, false, true, false, false, true).ID: return 4778; case Tripwire::Tripwire(true, true, false, true, false, false, false).ID: return 4779; case Tripwire::Tripwire(true, true, false, false, true, true, true).ID: return 4780; case Tripwire::Tripwire(true, true, false, false, true, true, false).ID: return 4781; case Tripwire::Tripwire(true, true, false, false, true, false, true).ID: return 4782; case Tripwire::Tripwire(true, true, false, false, true, false, false).ID: return 4783; case Tripwire::Tripwire(true, true, false, false, false, true, true).ID: return 4784; case Tripwire::Tripwire(true, true, false, false, false, true, false).ID: return 4785; case Tripwire::Tripwire(true, true, false, false, false, false, true).ID: return 4786; case Tripwire::Tripwire(true, true, false, false, false, false, false).ID: return 4787; case Tripwire::Tripwire(true, false, true, true, true, true, true).ID: return 4788; case Tripwire::Tripwire(true, false, true, true, true, true, false).ID: return 4789; case Tripwire::Tripwire(true, false, true, true, true, false, true).ID: return 4790; case Tripwire::Tripwire(true, false, true, true, true, false, false).ID: return 4791; case Tripwire::Tripwire(true, false, true, true, false, true, true).ID: return 4792; case Tripwire::Tripwire(true, false, true, true, false, true, false).ID: return 4793; case Tripwire::Tripwire(true, false, true, true, false, false, true).ID: return 4794; case Tripwire::Tripwire(true, false, true, true, false, false, false).ID: return 4795; case Tripwire::Tripwire(true, false, true, false, true, true, true).ID: return 4796; case Tripwire::Tripwire(true, false, true, false, true, true, false).ID: return 4797; case Tripwire::Tripwire(true, false, true, false, true, false, true).ID: return 4798; case Tripwire::Tripwire(true, false, true, false, true, false, false).ID: return 4799; case Tripwire::Tripwire(true, false, true, false, false, true, true).ID: return 4800; case Tripwire::Tripwire(true, false, true, false, false, true, false).ID: return 4801; case Tripwire::Tripwire(true, false, true, false, false, false, true).ID: return 4802; case Tripwire::Tripwire(true, false, true, false, false, false, false).ID: return 4803; case Tripwire::Tripwire(true, false, false, true, true, true, true).ID: return 4804; case Tripwire::Tripwire(true, false, false, true, true, true, false).ID: return 4805; case Tripwire::Tripwire(true, false, false, true, true, false, true).ID: return 4806; case Tripwire::Tripwire(true, false, false, true, true, false, false).ID: return 4807; case Tripwire::Tripwire(true, false, false, true, false, true, true).ID: return 4808; case Tripwire::Tripwire(true, false, false, true, false, true, false).ID: return 4809; case Tripwire::Tripwire(true, false, false, true, false, false, true).ID: return 4810; case Tripwire::Tripwire(true, false, false, true, false, false, false).ID: return 4811; case Tripwire::Tripwire(true, false, false, false, true, true, true).ID: return 4812; case Tripwire::Tripwire(true, false, false, false, true, true, false).ID: return 4813; case Tripwire::Tripwire(true, false, false, false, true, false, true).ID: return 4814; case Tripwire::Tripwire(true, false, false, false, true, false, false).ID: return 4815; case Tripwire::Tripwire(true, false, false, false, false, true, true).ID: return 4816; case Tripwire::Tripwire(true, false, false, false, false, true, false).ID: return 4817; case Tripwire::Tripwire(true, false, false, false, false, false, true).ID: return 4818; case Tripwire::Tripwire(true, false, false, false, false, false, false).ID: return 4819; case Tripwire::Tripwire(false, true, true, true, true, true, true).ID: return 4820; case Tripwire::Tripwire(false, true, true, true, true, true, false).ID: return 4821; case Tripwire::Tripwire(false, true, true, true, true, false, true).ID: return 4822; case Tripwire::Tripwire(false, true, true, true, true, false, false).ID: return 4823; case Tripwire::Tripwire(false, true, true, true, false, true, true).ID: return 4824; case Tripwire::Tripwire(false, true, true, true, false, true, false).ID: return 4825; case Tripwire::Tripwire(false, true, true, true, false, false, true).ID: return 4826; case Tripwire::Tripwire(false, true, true, true, false, false, false).ID: return 4827; case Tripwire::Tripwire(false, true, true, false, true, true, true).ID: return 4828; case Tripwire::Tripwire(false, true, true, false, true, true, false).ID: return 4829; case Tripwire::Tripwire(false, true, true, false, true, false, true).ID: return 4830; case Tripwire::Tripwire(false, true, true, false, true, false, false).ID: return 4831; case Tripwire::Tripwire(false, true, true, false, false, true, true).ID: return 4832; case Tripwire::Tripwire(false, true, true, false, false, true, false).ID: return 4833; case Tripwire::Tripwire(false, true, true, false, false, false, true).ID: return 4834; case Tripwire::Tripwire(false, true, true, false, false, false, false).ID: return 4835; case Tripwire::Tripwire(false, true, false, true, true, true, true).ID: return 4836; case Tripwire::Tripwire(false, true, false, true, true, true, false).ID: return 4837; case Tripwire::Tripwire(false, true, false, true, true, false, true).ID: return 4838; case Tripwire::Tripwire(false, true, false, true, true, false, false).ID: return 4839; case Tripwire::Tripwire(false, true, false, true, false, true, true).ID: return 4840; case Tripwire::Tripwire(false, true, false, true, false, true, false).ID: return 4841; case Tripwire::Tripwire(false, true, false, true, false, false, true).ID: return 4842; case Tripwire::Tripwire(false, true, false, true, false, false, false).ID: return 4843; case Tripwire::Tripwire(false, true, false, false, true, true, true).ID: return 4844; case Tripwire::Tripwire(false, true, false, false, true, true, false).ID: return 4845; case Tripwire::Tripwire(false, true, false, false, true, false, true).ID: return 4846; case Tripwire::Tripwire(false, true, false, false, true, false, false).ID: return 4847; case Tripwire::Tripwire(false, true, false, false, false, true, true).ID: return 4848; case Tripwire::Tripwire(false, true, false, false, false, true, false).ID: return 4849; case Tripwire::Tripwire(false, true, false, false, false, false, true).ID: return 4850; case Tripwire::Tripwire(false, true, false, false, false, false, false).ID: return 4851; case Tripwire::Tripwire(false, false, true, true, true, true, true).ID: return 4852; case Tripwire::Tripwire(false, false, true, true, true, true, false).ID: return 4853; case Tripwire::Tripwire(false, false, true, true, true, false, true).ID: return 4854; case Tripwire::Tripwire(false, false, true, true, true, false, false).ID: return 4855; case Tripwire::Tripwire(false, false, true, true, false, true, true).ID: return 4856; case Tripwire::Tripwire(false, false, true, true, false, true, false).ID: return 4857; case Tripwire::Tripwire(false, false, true, true, false, false, true).ID: return 4858; case Tripwire::Tripwire(false, false, true, true, false, false, false).ID: return 4859; case Tripwire::Tripwire(false, false, true, false, true, true, true).ID: return 4860; case Tripwire::Tripwire(false, false, true, false, true, true, false).ID: return 4861; case Tripwire::Tripwire(false, false, true, false, true, false, true).ID: return 4862; case Tripwire::Tripwire(false, false, true, false, true, false, false).ID: return 4863; case Tripwire::Tripwire(false, false, true, false, false, true, true).ID: return 4864; case Tripwire::Tripwire(false, false, true, false, false, true, false).ID: return 4865; case Tripwire::Tripwire(false, false, true, false, false, false, true).ID: return 4866; case Tripwire::Tripwire(false, false, true, false, false, false, false).ID: return 4867; case Tripwire::Tripwire(false, false, false, true, true, true, true).ID: return 4868; case Tripwire::Tripwire(false, false, false, true, true, true, false).ID: return 4869; case Tripwire::Tripwire(false, false, false, true, true, false, true).ID: return 4870; case Tripwire::Tripwire(false, false, false, true, true, false, false).ID: return 4871; case Tripwire::Tripwire(false, false, false, true, false, true, true).ID: return 4872; case Tripwire::Tripwire(false, false, false, true, false, true, false).ID: return 4873; case Tripwire::Tripwire(false, false, false, true, false, false, true).ID: return 4874; case Tripwire::Tripwire(false, false, false, true, false, false, false).ID: return 4875; case Tripwire::Tripwire(false, false, false, false, true, true, true).ID: return 4876; case Tripwire::Tripwire(false, false, false, false, true, true, false).ID: return 4877; case Tripwire::Tripwire(false, false, false, false, true, false, true).ID: return 4878; case Tripwire::Tripwire(false, false, false, false, true, false, false).ID: return 4879; case Tripwire::Tripwire(false, false, false, false, false, true, true).ID: return 4880; case Tripwire::Tripwire(false, false, false, false, false, true, false).ID: return 4881; case Tripwire::Tripwire(false, false, false, false, false, false, true).ID: return 4882; case Tripwire::Tripwire(false, false, false, false, false, false, false).ID: return 4883; case TripwireHook::TripwireHook(true, eBlockFace::BLOCK_FACE_ZM, true).ID: return 4740; case TripwireHook::TripwireHook(true, eBlockFace::BLOCK_FACE_ZM, false).ID: return 4741; case TripwireHook::TripwireHook(true, eBlockFace::BLOCK_FACE_ZP, true).ID: return 4742; case TripwireHook::TripwireHook(true, eBlockFace::BLOCK_FACE_ZP, false).ID: return 4743; case TripwireHook::TripwireHook(true, eBlockFace::BLOCK_FACE_XM, true).ID: return 4744; case TripwireHook::TripwireHook(true, eBlockFace::BLOCK_FACE_XM, false).ID: return 4745; case TripwireHook::TripwireHook(true, eBlockFace::BLOCK_FACE_XP, true).ID: return 4746; case TripwireHook::TripwireHook(true, eBlockFace::BLOCK_FACE_XP, false).ID: return 4747; case TripwireHook::TripwireHook(false, eBlockFace::BLOCK_FACE_ZM, true).ID: return 4748; case TripwireHook::TripwireHook(false, eBlockFace::BLOCK_FACE_ZM, false).ID: return 4749; case TripwireHook::TripwireHook(false, eBlockFace::BLOCK_FACE_ZP, true).ID: return 4750; case TripwireHook::TripwireHook(false, eBlockFace::BLOCK_FACE_ZP, false).ID: return 4751; case TripwireHook::TripwireHook(false, eBlockFace::BLOCK_FACE_XM, true).ID: return 4752; case TripwireHook::TripwireHook(false, eBlockFace::BLOCK_FACE_XM, false).ID: return 4753; case TripwireHook::TripwireHook(false, eBlockFace::BLOCK_FACE_XP, true).ID: return 4754; case TripwireHook::TripwireHook(false, eBlockFace::BLOCK_FACE_XP, false).ID: return 4755; case TubeCoral::TubeCoral().ID: return 8471; case TubeCoralBlock::TubeCoralBlock().ID: return 8455; case TubeCoralFan::TubeCoralFan().ID: return 8571; case TubeCoralWallFan::TubeCoralWallFan(eBlockFace::BLOCK_FACE_ZM).ID: return 8521; case TubeCoralWallFan::TubeCoralWallFan(eBlockFace::BLOCK_FACE_ZP).ID: return 8523; case TubeCoralWallFan::TubeCoralWallFan(eBlockFace::BLOCK_FACE_XM).ID: return 8525; case TubeCoralWallFan::TubeCoralWallFan(eBlockFace::BLOCK_FACE_XP).ID: return 8527; case TurtleEgg::TurtleEgg(1, 0).ID: return 8438; case TurtleEgg::TurtleEgg(1, 1).ID: return 8439; case TurtleEgg::TurtleEgg(1, 2).ID: return 8440; case TurtleEgg::TurtleEgg(2, 0).ID: return 8441; case TurtleEgg::TurtleEgg(2, 1).ID: return 8442; case TurtleEgg::TurtleEgg(2, 2).ID: return 8443; case TurtleEgg::TurtleEgg(3, 0).ID: return 8444; case TurtleEgg::TurtleEgg(3, 1).ID: return 8445; case TurtleEgg::TurtleEgg(3, 2).ID: return 8446; case TurtleEgg::TurtleEgg(4, 0).ID: return 8447; case TurtleEgg::TurtleEgg(4, 1).ID: return 8448; case TurtleEgg::TurtleEgg(4, 2).ID: return 8449; case Vine::Vine(true, true, true, true, true).ID: return 4269; case Vine::Vine(true, true, true, true, false).ID: return 4270; case Vine::Vine(true, true, true, false, true).ID: return 4271; case Vine::Vine(true, true, true, false, false).ID: return 4272; case Vine::Vine(true, true, false, true, true).ID: return 4273; case Vine::Vine(true, true, false, true, false).ID: return 4274; case Vine::Vine(true, true, false, false, true).ID: return 4275; case Vine::Vine(true, true, false, false, false).ID: return 4276; case Vine::Vine(true, false, true, true, true).ID: return 4277; case Vine::Vine(true, false, true, true, false).ID: return 4278; case Vine::Vine(true, false, true, false, true).ID: return 4279; case Vine::Vine(true, false, true, false, false).ID: return 4280; case Vine::Vine(true, false, false, true, true).ID: return 4281; case Vine::Vine(true, false, false, true, false).ID: return 4282; case Vine::Vine(true, false, false, false, true).ID: return 4283; case Vine::Vine(true, false, false, false, false).ID: return 4284; case Vine::Vine(false, true, true, true, true).ID: return 4285; case Vine::Vine(false, true, true, true, false).ID: return 4286; case Vine::Vine(false, true, true, false, true).ID: return 4287; case Vine::Vine(false, true, true, false, false).ID: return 4288; case Vine::Vine(false, true, false, true, true).ID: return 4289; case Vine::Vine(false, true, false, true, false).ID: return 4290; case Vine::Vine(false, true, false, false, true).ID: return 4291; case Vine::Vine(false, true, false, false, false).ID: return 4292; case Vine::Vine(false, false, true, true, true).ID: return 4293; case Vine::Vine(false, false, true, true, false).ID: return 4294; case Vine::Vine(false, false, true, false, true).ID: return 4295; case Vine::Vine(false, false, true, false, false).ID: return 4296; case Vine::Vine(false, false, false, true, true).ID: return 4297; case Vine::Vine(false, false, false, true, false).ID: return 4298; case Vine::Vine(false, false, false, false, true).ID: return 4299; case Vine::Vine(false, false, false, false, false).ID: return 4300; case VoidAir::VoidAir().ID: return 8591; case OakWallSign::OakWallSign(eBlockFace::BLOCK_FACE_ZM).ID: return 3271; case OakWallSign::OakWallSign(eBlockFace::BLOCK_FACE_ZP).ID: return 3273; case OakWallSign::OakWallSign(eBlockFace::BLOCK_FACE_XM).ID: return 3275; case OakWallSign::OakWallSign(eBlockFace::BLOCK_FACE_XP).ID: return 3277; case WallTorch::WallTorch(eBlockFace::BLOCK_FACE_ZM).ID: return 1132; case WallTorch::WallTorch(eBlockFace::BLOCK_FACE_ZP).ID: return 1133; case WallTorch::WallTorch(eBlockFace::BLOCK_FACE_XM).ID: return 1134; case WallTorch::WallTorch(eBlockFace::BLOCK_FACE_XP).ID: return 1135; case Water::Water(0).ID: return 34; case Water::Water(1).ID: return 35; case Water::Water(2).ID: return 36; case Water::Water(3).ID: return 37; case Water::Water(4).ID: return 38; case Water::Water(5).ID: return 39; case Water::Water(6).ID: return 40; case Water::Water(7).ID: return 41; case Water::Water(8).ID: return 42; case Water::Water(9).ID: return 43; case Water::Water(10).ID: return 44; case Water::Water(11).ID: return 45; case Water::Water(12).ID: return 46; case Water::Water(13).ID: return 47; case Water::Water(14).ID: return 48; case Water::Water(15).ID: return 49; case WetSponge::WetSponge().ID: return 229; case Wheat::Wheat(0).ID: return 3052; case Wheat::Wheat(1).ID: return 3053; case Wheat::Wheat(2).ID: return 3054; case Wheat::Wheat(3).ID: return 3055; case Wheat::Wheat(4).ID: return 3056; case Wheat::Wheat(5).ID: return 3057; case Wheat::Wheat(6).ID: return 3058; case Wheat::Wheat(7).ID: return 3059; case WhiteBanner::WhiteBanner(0).ID: return 6855; case WhiteBanner::WhiteBanner(1).ID: return 6856; case WhiteBanner::WhiteBanner(2).ID: return 6857; case WhiteBanner::WhiteBanner(3).ID: return 6858; case WhiteBanner::WhiteBanner(4).ID: return 6859; case WhiteBanner::WhiteBanner(5).ID: return 6860; case WhiteBanner::WhiteBanner(6).ID: return 6861; case WhiteBanner::WhiteBanner(7).ID: return 6862; case WhiteBanner::WhiteBanner(8).ID: return 6863; case WhiteBanner::WhiteBanner(9).ID: return 6864; case WhiteBanner::WhiteBanner(10).ID: return 6865; case WhiteBanner::WhiteBanner(11).ID: return 6866; case WhiteBanner::WhiteBanner(12).ID: return 6867; case WhiteBanner::WhiteBanner(13).ID: return 6868; case WhiteBanner::WhiteBanner(14).ID: return 6869; case WhiteBanner::WhiteBanner(15).ID: return 6870; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_ZM, true, WhiteBed::Part::Head).ID: return 748; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_ZM, true, WhiteBed::Part::Foot).ID: return 749; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_ZM, false, WhiteBed::Part::Head).ID: return 750; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_ZM, false, WhiteBed::Part::Foot).ID: return 751; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_ZP, true, WhiteBed::Part::Head).ID: return 752; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_ZP, true, WhiteBed::Part::Foot).ID: return 753; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_ZP, false, WhiteBed::Part::Head).ID: return 754; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_ZP, false, WhiteBed::Part::Foot).ID: return 755; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_XM, true, WhiteBed::Part::Head).ID: return 756; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_XM, true, WhiteBed::Part::Foot).ID: return 757; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_XM, false, WhiteBed::Part::Head).ID: return 758; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_XM, false, WhiteBed::Part::Foot).ID: return 759; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_XP, true, WhiteBed::Part::Head).ID: return 760; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_XP, true, WhiteBed::Part::Foot).ID: return 761; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_XP, false, WhiteBed::Part::Head).ID: return 762; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_XP, false, WhiteBed::Part::Foot).ID: return 763; case WhiteCarpet::WhiteCarpet().ID: return 6824; case WhiteConcrete::WhiteConcrete().ID: return 8378; case WhiteConcretePowder::WhiteConcretePowder().ID: return 8394; case WhiteGlazedTerracotta::WhiteGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 8314; case WhiteGlazedTerracotta::WhiteGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 8315; case WhiteGlazedTerracotta::WhiteGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 8316; case WhiteGlazedTerracotta::WhiteGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 8317; case WhiteShulkerBox::WhiteShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 8218; case WhiteShulkerBox::WhiteShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 8219; case WhiteShulkerBox::WhiteShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 8220; case WhiteShulkerBox::WhiteShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 8221; case WhiteShulkerBox::WhiteShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 8222; case WhiteShulkerBox::WhiteShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 8223; case WhiteStainedGlass::WhiteStainedGlass().ID: return 3578; case WhiteStainedGlassPane::WhiteStainedGlassPane(true, true, true, true).ID: return 5823; case WhiteStainedGlassPane::WhiteStainedGlassPane(true, true, true, false).ID: return 5824; case WhiteStainedGlassPane::WhiteStainedGlassPane(true, true, false, true).ID: return 5827; case WhiteStainedGlassPane::WhiteStainedGlassPane(true, true, false, false).ID: return 5828; case WhiteStainedGlassPane::WhiteStainedGlassPane(true, false, true, true).ID: return 5831; case WhiteStainedGlassPane::WhiteStainedGlassPane(true, false, true, false).ID: return 5832; case WhiteStainedGlassPane::WhiteStainedGlassPane(true, false, false, true).ID: return 5835; case WhiteStainedGlassPane::WhiteStainedGlassPane(true, false, false, false).ID: return 5836; case WhiteStainedGlassPane::WhiteStainedGlassPane(false, true, true, true).ID: return 5839; case WhiteStainedGlassPane::WhiteStainedGlassPane(false, true, true, false).ID: return 5840; case WhiteStainedGlassPane::WhiteStainedGlassPane(false, true, false, true).ID: return 5843; case WhiteStainedGlassPane::WhiteStainedGlassPane(false, true, false, false).ID: return 5844; case WhiteStainedGlassPane::WhiteStainedGlassPane(false, false, true, true).ID: return 5847; case WhiteStainedGlassPane::WhiteStainedGlassPane(false, false, true, false).ID: return 5848; case WhiteStainedGlassPane::WhiteStainedGlassPane(false, false, false, true).ID: return 5851; case WhiteStainedGlassPane::WhiteStainedGlassPane(false, false, false, false).ID: return 5852; case WhiteTerracotta::WhiteTerracotta().ID: return 5805; case WhiteTulip::WhiteTulip().ID: return 1118; case WhiteWallBanner::WhiteWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 7111; case WhiteWallBanner::WhiteWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 7112; case WhiteWallBanner::WhiteWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 7113; case WhiteWallBanner::WhiteWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 7114; case WhiteWool::WhiteWool().ID: return 1083; case WitherSkeletonSkull::WitherSkeletonSkull(0).ID: return 5472; case WitherSkeletonSkull::WitherSkeletonSkull(1).ID: return 5473; case WitherSkeletonSkull::WitherSkeletonSkull(2).ID: return 5474; case WitherSkeletonSkull::WitherSkeletonSkull(3).ID: return 5475; case WitherSkeletonSkull::WitherSkeletonSkull(4).ID: return 5476; case WitherSkeletonSkull::WitherSkeletonSkull(5).ID: return 5477; case WitherSkeletonSkull::WitherSkeletonSkull(6).ID: return 5478; case WitherSkeletonSkull::WitherSkeletonSkull(7).ID: return 5479; case WitherSkeletonSkull::WitherSkeletonSkull(8).ID: return 5480; case WitherSkeletonSkull::WitherSkeletonSkull(9).ID: return 5481; case WitherSkeletonSkull::WitherSkeletonSkull(10).ID: return 5482; case WitherSkeletonSkull::WitherSkeletonSkull(11).ID: return 5483; case WitherSkeletonSkull::WitherSkeletonSkull(12).ID: return 5484; case WitherSkeletonSkull::WitherSkeletonSkull(13).ID: return 5485; case WitherSkeletonSkull::WitherSkeletonSkull(14).ID: return 5486; case WitherSkeletonSkull::WitherSkeletonSkull(15).ID: return 5487; case WitherSkeletonWallSkull::WitherSkeletonWallSkull(eBlockFace::BLOCK_FACE_ZM).ID: return 5468; case WitherSkeletonWallSkull::WitherSkeletonWallSkull(eBlockFace::BLOCK_FACE_ZP).ID: return 5469; case WitherSkeletonWallSkull::WitherSkeletonWallSkull(eBlockFace::BLOCK_FACE_XM).ID: return 5470; case WitherSkeletonWallSkull::WitherSkeletonWallSkull(eBlockFace::BLOCK_FACE_XP).ID: return 5471; case YellowBanner::YellowBanner(0).ID: return 6919; case YellowBanner::YellowBanner(1).ID: return 6920; case YellowBanner::YellowBanner(2).ID: return 6921; case YellowBanner::YellowBanner(3).ID: return 6922; case YellowBanner::YellowBanner(4).ID: return 6923; case YellowBanner::YellowBanner(5).ID: return 6924; case YellowBanner::YellowBanner(6).ID: return 6925; case YellowBanner::YellowBanner(7).ID: return 6926; case YellowBanner::YellowBanner(8).ID: return 6927; case YellowBanner::YellowBanner(9).ID: return 6928; case YellowBanner::YellowBanner(10).ID: return 6929; case YellowBanner::YellowBanner(11).ID: return 6930; case YellowBanner::YellowBanner(12).ID: return 6931; case YellowBanner::YellowBanner(13).ID: return 6932; case YellowBanner::YellowBanner(14).ID: return 6933; case YellowBanner::YellowBanner(15).ID: return 6934; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_ZM, true, YellowBed::Part::Head).ID: return 812; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_ZM, true, YellowBed::Part::Foot).ID: return 813; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_ZM, false, YellowBed::Part::Head).ID: return 814; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_ZM, false, YellowBed::Part::Foot).ID: return 815; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_ZP, true, YellowBed::Part::Head).ID: return 816; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_ZP, true, YellowBed::Part::Foot).ID: return 817; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_ZP, false, YellowBed::Part::Head).ID: return 818; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_ZP, false, YellowBed::Part::Foot).ID: return 819; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_XM, true, YellowBed::Part::Head).ID: return 820; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_XM, true, YellowBed::Part::Foot).ID: return 821; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_XM, false, YellowBed::Part::Head).ID: return 822; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_XM, false, YellowBed::Part::Foot).ID: return 823; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_XP, true, YellowBed::Part::Head).ID: return 824; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_XP, true, YellowBed::Part::Foot).ID: return 825; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_XP, false, YellowBed::Part::Head).ID: return 826; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_XP, false, YellowBed::Part::Foot).ID: return 827; case YellowCarpet::YellowCarpet().ID: return 6828; case YellowConcrete::YellowConcrete().ID: return 8382; case YellowConcretePowder::YellowConcretePowder().ID: return 8398; case YellowGlazedTerracotta::YellowGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 8330; case YellowGlazedTerracotta::YellowGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 8331; case YellowGlazedTerracotta::YellowGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 8332; case YellowGlazedTerracotta::YellowGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 8333; case YellowShulkerBox::YellowShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 8242; case YellowShulkerBox::YellowShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 8243; case YellowShulkerBox::YellowShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 8244; case YellowShulkerBox::YellowShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 8245; case YellowShulkerBox::YellowShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 8246; case YellowShulkerBox::YellowShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 8247; case YellowStainedGlass::YellowStainedGlass().ID: return 3582; case YellowStainedGlassPane::YellowStainedGlassPane(true, true, true, true).ID: return 5951; case YellowStainedGlassPane::YellowStainedGlassPane(true, true, true, false).ID: return 5952; case YellowStainedGlassPane::YellowStainedGlassPane(true, true, false, true).ID: return 5955; case YellowStainedGlassPane::YellowStainedGlassPane(true, true, false, false).ID: return 5956; case YellowStainedGlassPane::YellowStainedGlassPane(true, false, true, true).ID: return 5959; case YellowStainedGlassPane::YellowStainedGlassPane(true, false, true, false).ID: return 5960; case YellowStainedGlassPane::YellowStainedGlassPane(true, false, false, true).ID: return 5963; case YellowStainedGlassPane::YellowStainedGlassPane(true, false, false, false).ID: return 5964; case YellowStainedGlassPane::YellowStainedGlassPane(false, true, true, true).ID: return 5967; case YellowStainedGlassPane::YellowStainedGlassPane(false, true, true, false).ID: return 5968; case YellowStainedGlassPane::YellowStainedGlassPane(false, true, false, true).ID: return 5971; case YellowStainedGlassPane::YellowStainedGlassPane(false, true, false, false).ID: return 5972; case YellowStainedGlassPane::YellowStainedGlassPane(false, false, true, true).ID: return 5975; case YellowStainedGlassPane::YellowStainedGlassPane(false, false, true, false).ID: return 5976; case YellowStainedGlassPane::YellowStainedGlassPane(false, false, false, true).ID: return 5979; case YellowStainedGlassPane::YellowStainedGlassPane(false, false, false, false).ID: return 5980; case YellowTerracotta::YellowTerracotta().ID: return 5809; case YellowWallBanner::YellowWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 7127; case YellowWallBanner::YellowWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 7128; case YellowWallBanner::YellowWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 7129; case YellowWallBanner::YellowWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 7130; case YellowWool::YellowWool().ID: return 1087; case ZombieHead::ZombieHead(0).ID: return 5492; case ZombieHead::ZombieHead(1).ID: return 5493; case ZombieHead::ZombieHead(2).ID: return 5494; case ZombieHead::ZombieHead(3).ID: return 5495; case ZombieHead::ZombieHead(4).ID: return 5496; case ZombieHead::ZombieHead(5).ID: return 5497; case ZombieHead::ZombieHead(6).ID: return 5498; case ZombieHead::ZombieHead(7).ID: return 5499; case ZombieHead::ZombieHead(8).ID: return 5500; case ZombieHead::ZombieHead(9).ID: return 5501; case ZombieHead::ZombieHead(10).ID: return 5502; case ZombieHead::ZombieHead(11).ID: return 5503; case ZombieHead::ZombieHead(12).ID: return 5504; case ZombieHead::ZombieHead(13).ID: return 5505; case ZombieHead::ZombieHead(14).ID: return 5506; case ZombieHead::ZombieHead(15).ID: return 5507; case ZombieWallHead::ZombieWallHead(eBlockFace::BLOCK_FACE_ZM).ID: return 5488; case ZombieWallHead::ZombieWallHead(eBlockFace::BLOCK_FACE_ZP).ID: return 5489; case ZombieWallHead::ZombieWallHead(eBlockFace::BLOCK_FACE_XM).ID: return 5490; case ZombieWallHead::ZombieWallHead(eBlockFace::BLOCK_FACE_XP).ID: return 5491; default: return 0; } } UInt32 From(const Item ID) { switch (ID) { case Item::AcaciaBoat: return 767; case Item::AcaciaButton: return 245; case Item::AcaciaDoor: return 465; case Item::AcaciaFence: return 179; case Item::AcaciaFenceGate: return 214; case Item::AcaciaLeaves: return 60; case Item::AcaciaLog: return 36; case Item::AcaciaPlanks: return 17; case Item::AcaciaPressurePlate: return 164; case Item::AcaciaSapling: return 23; case Item::AcaciaSlab: return 116; case Item::AcaciaStairs: return 301; case Item::AcaciaTrapdoor: return 191; case Item::AcaciaWood: return 54; case Item::ActivatorRail: return 261; case Item::Air: return -0; case Item::Allium: return 101; case Item::Andesite: return 6; case Item::Anvil: return 247; case Item::Apple: return 476; case Item::ArmorStand: return 726; case Item::Arrow: return 478; case Item::AzureBluet: return 102; case Item::BakedPotato: return 699; case Item::Barrier: return 279; case Item::BatSpawnEgg: return 639; case Item::Beacon: return 238; case Item::Bedrock: return 25; case Item::Beef: return 619; case Item::Beetroot: return 754; case Item::BeetrootSeeds: return 755; case Item::BeetrootSoup: return 756; case Item::BirchBoat: return 765; case Item::BirchButton: return 243; case Item::BirchDoor: return 463; case Item::BirchFence: return 177; case Item::BirchFenceGate: return 212; case Item::BirchLeaves: return 58; case Item::BirchLog: return 34; case Item::BirchPlanks: return 15; case Item::BirchPressurePlate: return 162; case Item::BirchSapling: return 21; case Item::BirchSlab: return 114; case Item::BirchStairs: return 235; case Item::BirchTrapdoor: return 189; case Item::BirchWood: return 52; case Item::BlackBanner: return 750; case Item::BlackBed: return 611; case Item::BlackCarpet: return 297; case Item::BlackConcrete: return 410; case Item::BlackConcretePowder: return 426; case Item::BlackGlazedTerracotta: return 394; case Item::BlackShulkerBox: return 378; case Item::BlackStainedGlass: return 326; case Item::BlackStainedGlassPane: return 342; case Item::BlackTerracotta: return 278; case Item::BlackWool: return 97; case Item::BlazePowder: return 633; case Item::BlazeRod: return 625; case Item::BlazeSpawnEgg: return 640; case Item::BlueBanner: return 746; case Item::BlueBed: return 607; case Item::BlueCarpet: return 293; case Item::BlueConcrete: return 406; case Item::BlueConcretePowder: return 422; case Item::BlueGlazedTerracotta: return 390; case Item::BlueIce: return 458; case Item::BlueOrchid: return 100; case Item::BlueShulkerBox: return 374; case Item::BlueStainedGlass: return 322; case Item::BlueStainedGlassPane: return 338; case Item::BlueTerracotta: return 274; case Item::BlueWool: return 93; case Item::Bone: return 593; case Item::BoneBlock: return 359; case Item::BoneMeal: return 592; case Item::Book: return 562; case Item::Bookshelf: return 137; case Item::Bow: return 477; case Item::Bowl: return 498; case Item::BrainCoral: return 439; case Item::BrainCoralBlock: return 434; case Item::BrainCoralFan: return 449; case Item::Bread: return 514; case Item::BrewingStand: return 635; case Item::Brick: return 556; case Item::BrickSlab: return 122; case Item::BrickStairs: return 216; case Item::Bricks: return 135; case Item::BrownBanner: return 747; case Item::BrownBed: return 608; case Item::BrownCarpet: return 294; case Item::BrownConcrete: return 407; case Item::BrownConcretePowder: return 423; case Item::BrownGlazedTerracotta: return 391; case Item::BrownMushroom: return 108; case Item::BrownMushroomBlock: return 203; case Item::BrownShulkerBox: return 375; case Item::BrownStainedGlass: return 323; case Item::BrownStainedGlassPane: return 339; case Item::BrownTerracotta: return 275; case Item::BrownWool: return 94; case Item::BubbleCoral: return 440; case Item::BubbleCoralBlock: return 435; case Item::BubbleCoralFan: return 450; case Item::Bucket: return 542; case Item::Cactus: return 172; case Item::GreenDye: return 579; case Item::Cake: return 595; case Item::Carrot: return 697; case Item::CarrotOnAStick: return 709; case Item::CarvedPumpkin: return 182; case Item::Cauldron: return 636; case Item::CaveSpiderSpawnEgg: return 641; case Item::ChainCommandBlock: return 355; case Item::ChainmailBoots: return 522; case Item::ChainmailChestplate: return 520; case Item::ChainmailHelmet: return 519; case Item::ChainmailLeggings: return 521; case Item::Charcoal: return 480; case Item::Chest: return 149; case Item::ChestMinecart: return 564; case Item::Chicken: return 621; case Item::ChickenSpawnEgg: return 642; case Item::ChippedAnvil: return 248; case Item::ChiseledQuartzBlock: return 257; case Item::ChiseledRedSandstone: return 351; case Item::ChiseledSandstone: return 69; case Item::ChiseledStoneBricks: return 202; case Item::ChorusFlower: return 143; case Item::ChorusFruit: return 752; case Item::ChorusPlant: return 142; case Item::Clay: return 173; case Item::ClayBall: return 557; case Item::Clock: return 569; case Item::Coal: return 479; case Item::CoalBlock: return 299; case Item::CoalOre: return 31; case Item::CoarseDirt: return 10; case Item::Cobblestone: return 12; case Item::CobblestoneSlab: return 121; case Item::CobblestoneStairs: return 157; case Item::CobblestoneWall: return 239; case Item::Cobweb: return 75; case Item::CocoaBeans: return 580; case Item::Cod: return 571; case Item::CodBucket: return 554; case Item::CodSpawnEgg: return 643; case Item::CommandBlock: return 237; case Item::CommandBlockMinecart: return 732; case Item::Comparator: return 468; case Item::Compass: return 567; case Item::Conduit: return 459; case Item::CookedBeef: return 620; case Item::CookedChicken: return 622; case Item::CookedCod: return 575; case Item::CookedMutton: return 734; case Item::CookedPorkchop: return 537; case Item::CookedRabbit: return 722; case Item::CookedSalmon: return 576; case Item::Cookie: return 612; case Item::CowSpawnEgg: return 644; case Item::CrackedStoneBricks: return 201; case Item::CraftingTable: return 152; case Item::CreeperHead: return 707; case Item::CreeperSpawnEgg: return 645; case Item::CutRedSandstone: return 352; case Item::CutSandstone: return 70; case Item::CyanBanner: return 744; case Item::CyanBed: return 605; case Item::CyanCarpet: return 291; case Item::CyanConcrete: return 404; case Item::CyanConcretePowder: return 420; case Item::CyanDye: return 583; case Item::CyanGlazedTerracotta: return 388; case Item::CyanShulkerBox: return 372; case Item::CyanStainedGlass: return 320; case Item::CyanStainedGlassPane: return 336; case Item::CyanTerracotta: return 272; case Item::CyanWool: return 91; case Item::DamagedAnvil: return 249; case Item::Dandelion: return 98; case Item::YellowDye: return 588; case Item::DarkOakBoat: return 768; case Item::DarkOakButton: return 246; case Item::DarkOakDoor: return 466; case Item::DarkOakFence: return 180; case Item::DarkOakFenceGate: return 215; case Item::DarkOakLeaves: return 61; case Item::DarkOakLog: return 37; case Item::DarkOakPlanks: return 18; case Item::DarkOakPressurePlate: return 165; case Item::DarkOakSapling: return 24; case Item::DarkOakSlab: return 117; case Item::DarkOakStairs: return 302; case Item::DarkOakTrapdoor: return 192; case Item::DarkOakWood: return 55; case Item::DarkPrismarine: return 345; case Item::DarkPrismarineSlab: return 130; case Item::DarkPrismarineStairs: return 348; case Item::DaylightDetector: return 253; case Item::DeadBrainCoral: return 443; case Item::DeadBrainCoralBlock: return 429; case Item::DeadBrainCoralFan: return 454; case Item::DeadBubbleCoral: return 444; case Item::DeadBubbleCoralBlock: return 430; case Item::DeadBubbleCoralFan: return 455; case Item::DeadBush: return 78; case Item::DeadFireCoral: return 445; case Item::DeadFireCoralBlock: return 431; case Item::DeadFireCoralFan: return 456; case Item::DeadHornCoral: return 446; case Item::DeadHornCoralBlock: return 432; case Item::DeadHornCoralFan: return 457; case Item::DeadTubeCoral: return 447; case Item::DeadTubeCoralBlock: return 428; case Item::DeadTubeCoralFan: return 453; case Item::DebugStick: return 773; case Item::DetectorRail: return 73; case Item::Diamond: return 481; case Item::DiamondAxe: return 496; case Item::DiamondBlock: return 151; case Item::DiamondBoots: return 530; case Item::DiamondChestplate: return 528; case Item::DiamondHelmet: return 527; case Item::DiamondHoe: return 510; case Item::DiamondHorseArmor: return 729; case Item::DiamondLeggings: return 529; case Item::DiamondOre: return 150; case Item::DiamondPickaxe: return 495; case Item::DiamondShovel: return 494; case Item::DiamondSword: return 493; case Item::Diorite: return 4; case Item::Dirt: return 9; case Item::Dispenser: return 67; case Item::DolphinSpawnEgg: return 646; case Item::DonkeySpawnEgg: return 647; case Item::DragonBreath: return 757; case Item::DragonEgg: return 227; case Item::DragonHead: return 708; case Item::DriedKelp: return 616; case Item::DriedKelpBlock: return 560; case Item::Dropper: return 262; case Item::DrownedSpawnEgg: return 648; case Item::Egg: return 566; case Item::ElderGuardianSpawnEgg: return 649; case Item::Elytra: return 763; case Item::Emerald: return 694; case Item::EmeraldBlock: return 233; case Item::EmeraldOre: return 230; case Item::EnchantedBook: return 714; case Item::EnchantedGoldenApple: return 540; case Item::EnchantingTable: return 223; case Item::EndCrystal: return 751; case Item::EndPortalFrame: return 224; case Item::EndRod: return 141; case Item::EndStone: return 225; case Item::EndStoneBricks: return 226; case Item::EnderChest: return 231; case Item::EnderEye: return 637; case Item::EnderPearl: return 624; case Item::EndermanSpawnEgg: return 650; case Item::EndermiteSpawnEgg: return 651; case Item::EvokerSpawnEgg: return 652; case Item::ExperienceBottle: return 690; case Item::Farmland: return 153; case Item::Feather: return 505; case Item::FermentedSpiderEye: return 632; case Item::Fern: return 77; case Item::FilledMap: return 613; case Item::FireCharge: return 691; case Item::FireCoral: return 441; case Item::FireCoralBlock: return 436; case Item::FireCoralFan: return 451; case Item::FireworkRocket: return 712; case Item::FireworkStar: return 713; case Item::FishingRod: return 568; case Item::Flint: return 535; case Item::FlintAndSteel: return 475; case Item::FlowerPot: return 696; case Item::Furnace: return 154; case Item::FurnaceMinecart: return 565; case Item::GhastSpawnEgg: return 653; case Item::GhastTear: return 626; case Item::Glass: return 64; case Item::GlassBottle: return 630; case Item::GlassPane: return 207; case Item::GlisteringMelonSlice: return 638; case Item::Glowstone: return 185; case Item::GlowstoneDust: return 570; case Item::GoldBlock: return 110; case Item::GoldIngot: return 483; case Item::GoldNugget: return 627; case Item::GoldOre: return 29; case Item::GoldenApple: return 539; case Item::GoldenAxe: return 503; case Item::GoldenBoots: return 534; case Item::GoldenCarrot: return 702; case Item::GoldenChestplate: return 532; case Item::GoldenHelmet: return 531; case Item::GoldenHoe: return 511; case Item::GoldenHorseArmor: return 728; case Item::GoldenLeggings: return 533; case Item::GoldenPickaxe: return 502; case Item::GoldenShovel: return 501; case Item::GoldenSword: return 500; case Item::Granite: return 2; case Item::Grass: return 76; case Item::GrassBlock: return 8; case Item::GrassPath: return 304; case Item::Gravel: return 28; case Item::GrayBanner: return 742; case Item::GrayBed: return 603; case Item::GrayCarpet: return 289; case Item::GrayConcrete: return 402; case Item::GrayConcretePowder: return 418; case Item::GrayDye: return 585; case Item::GrayGlazedTerracotta: return 386; case Item::GrayShulkerBox: return 370; case Item::GrayStainedGlass: return 318; case Item::GrayStainedGlassPane: return 334; case Item::GrayTerracotta: return 270; case Item::GrayWool: return 89; case Item::GreenBanner: return 748; case Item::GreenBed: return 609; case Item::GreenCarpet: return 295; case Item::GreenConcrete: return 408; case Item::GreenConcretePowder: return 424; case Item::GreenGlazedTerracotta: return 392; case Item::GreenShulkerBox: return 376; case Item::GreenStainedGlass: return 324; case Item::GreenStainedGlassPane: return 340; case Item::GreenTerracotta: return 276; case Item::GreenWool: return 95; case Item::GuardianSpawnEgg: return 654; case Item::Gunpowder: return 506; case Item::HayBale: return 281; case Item::HeartOfTheSea: return 789; case Item::HeavyWeightedPressurePlate: return 252; case Item::Hopper: return 256; case Item::HopperMinecart: return 718; case Item::HornCoral: return 442; case Item::HornCoralBlock: return 437; case Item::HornCoralFan: return 452; case Item::HorseSpawnEgg: return 655; case Item::HuskSpawnEgg: return 656; case Item::Ice: return 170; case Item::InfestedChiseledStoneBricks: return 198; case Item::InfestedCobblestone: return 194; case Item::InfestedCrackedStoneBricks: return 197; case Item::InfestedMossyStoneBricks: return 196; case Item::InfestedStone: return 193; case Item::InfestedStoneBricks: return 195; case Item::InkSac: return 577; case Item::IronAxe: return 474; case Item::IronBars: return 206; case Item::IronBlock: return 111; case Item::IronBoots: return 526; case Item::IronChestplate: return 524; case Item::IronDoor: return 460; case Item::IronHelmet: return 523; case Item::IronHoe: return 509; case Item::IronHorseArmor: return 727; case Item::IronIngot: return 482; case Item::IronLeggings: return 525; case Item::IronNugget: return 771; case Item::IronOre: return 30; case Item::IronPickaxe: return 473; case Item::IronShovel: return 472; case Item::IronSword: return 484; case Item::IronTrapdoor: return 280; case Item::ItemFrame: return 695; case Item::JackOLantern: return 186; case Item::Jukebox: return 174; case Item::JungleBoat: return 766; case Item::JungleButton: return 244; case Item::JungleDoor: return 464; case Item::JungleFence: return 178; case Item::JungleFenceGate: return 213; case Item::JungleLeaves: return 59; case Item::JungleLog: return 35; case Item::JunglePlanks: return 16; case Item::JunglePressurePlate: return 163; case Item::JungleSapling: return 22; case Item::JungleSlab: return 115; case Item::JungleStairs: return 236; case Item::JungleTrapdoor: return 190; case Item::JungleWood: return 53; case Item::Kelp: return 559; case Item::KnowledgeBook: return 772; case Item::Ladder: return 155; case Item::LapisBlock: return 66; case Item::LapisLazuli: return 581; case Item::LapisOre: return 65; case Item::LargeFern: return 310; case Item::LavaBucket: return 544; case Item::Lead: return 730; case Item::Leather: return 550; case Item::LeatherBoots: return 518; case Item::LeatherChestplate: return 516; case Item::LeatherHelmet: return 515; case Item::LeatherLeggings: return 517; case Item::Lever: return 158; case Item::LightBlueBanner: return 738; case Item::LightBlueBed: return 599; case Item::LightBlueCarpet: return 285; case Item::LightBlueConcrete: return 398; case Item::LightBlueConcretePowder: return 414; case Item::LightBlueDye: return 589; case Item::LightBlueGlazedTerracotta: return 382; case Item::LightBlueShulkerBox: return 366; case Item::LightBlueStainedGlass: return 314; case Item::LightBlueStainedGlassPane: return 330; case Item::LightBlueTerracotta: return 266; case Item::LightBlueWool: return 85; case Item::LightGrayBanner: return 743; case Item::LightGrayBed: return 604; case Item::LightGrayCarpet: return 290; case Item::LightGrayConcrete: return 403; case Item::LightGrayConcretePowder: return 419; case Item::LightGrayDye: return 584; case Item::LightGrayGlazedTerracotta: return 387; case Item::LightGrayShulkerBox: return 371; case Item::LightGrayStainedGlass: return 319; case Item::LightGrayStainedGlassPane: return 335; case Item::LightGrayTerracotta: return 271; case Item::LightGrayWool: return 90; case Item::LightWeightedPressurePlate: return 251; case Item::Lilac: return 306; case Item::LilyPad: return 219; case Item::LimeBanner: return 740; case Item::LimeBed: return 601; case Item::LimeCarpet: return 287; case Item::LimeConcrete: return 400; case Item::LimeConcretePowder: return 416; case Item::LimeDye: return 587; case Item::LimeGlazedTerracotta: return 384; case Item::LimeShulkerBox: return 368; case Item::LimeStainedGlass: return 316; case Item::LimeStainedGlassPane: return 332; case Item::LimeTerracotta: return 268; case Item::LimeWool: return 87; case Item::LingeringPotion: return 761; case Item::LlamaSpawnEgg: return 657; case Item::MagentaBanner: return 737; case Item::MagentaBed: return 598; case Item::MagentaCarpet: return 284; case Item::MagentaConcrete: return 397; case Item::MagentaConcretePowder: return 413; case Item::MagentaDye: return 590; case Item::MagentaGlazedTerracotta: return 381; case Item::MagentaShulkerBox: return 365; case Item::MagentaStainedGlass: return 313; case Item::MagentaStainedGlassPane: return 329; case Item::MagentaTerracotta: return 265; case Item::MagentaWool: return 84; case Item::MagmaBlock: return 356; case Item::MagmaCream: return 634; case Item::MagmaCubeSpawnEgg: return 658; case Item::Map: return 701; case Item::Melon: return 208; case Item::MelonSeeds: return 618; case Item::MelonSlice: return 615; case Item::MilkBucket: return 551; case Item::Minecart: return 545; case Item::MooshroomSpawnEgg: return 659; case Item::MossyCobblestone: return 138; case Item::MossyCobblestoneWall: return 240; case Item::MossyStoneBricks: return 200; case Item::MuleSpawnEgg: return 660; case Item::MushroomStem: return 205; case Item::MushroomStew: return 499; case Item::MusicDisc11: return 784; case Item::MusicDisc13: return 774; case Item::MusicDiscBlocks: return 776; case Item::MusicDiscCat: return 775; case Item::MusicDiscChirp: return 777; case Item::MusicDiscFar: return 778; case Item::MusicDiscMall: return 779; case Item::MusicDiscMellohi: return 780; case Item::MusicDiscStal: return 781; case Item::MusicDiscStrad: return 782; case Item::MusicDiscWait: return 785; case Item::MusicDiscWard: return 783; case Item::Mutton: return 733; case Item::Mycelium: return 218; case Item::NameTag: return 731; case Item::NautilusShell: return 788; case Item::NetherBrick: return 715; case Item::NetherBrickFence: return 221; case Item::NetherBrickSlab: return 124; case Item::NetherBrickStairs: return 222; case Item::NetherBricks: return 220; case Item::NetherQuartzOre: return 255; case Item::NetherStar: return 710; case Item::NetherWart: return 628; case Item::NetherWartBlock: return 357; case Item::Netherrack: return 183; case Item::NoteBlock: return 71; case Item::OakBoat: return 549; case Item::OakButton: return 241; case Item::OakDoor: return 461; case Item::OakFence: return 175; case Item::OakFenceGate: return 210; case Item::OakLeaves: return 56; case Item::OakLog: return 32; case Item::OakPlanks: return 13; case Item::OakPressurePlate: return 160; case Item::OakSapling: return 19; case Item::OakSlab: return 112; case Item::OakStairs: return 148; case Item::OakTrapdoor: return 187; case Item::OakWood: return 50; case Item::Observer: return 361; case Item::Obsidian: return 139; case Item::OcelotSpawnEgg: return 661; case Item::OrangeBanner: return 736; case Item::OrangeBed: return 597; case Item::OrangeCarpet: return 283; case Item::OrangeConcrete: return 396; case Item::OrangeConcretePowder: return 412; case Item::OrangeDye: return 591; case Item::OrangeGlazedTerracotta: return 380; case Item::OrangeShulkerBox: return 364; case Item::OrangeStainedGlass: return 312; case Item::OrangeStainedGlassPane: return 328; case Item::OrangeTerracotta: return 264; case Item::OrangeTulip: return 104; case Item::OrangeWool: return 83; case Item::OxeyeDaisy: return 107; case Item::PackedIce: return 300; case Item::Painting: return 538; case Item::Paper: return 561; case Item::ParrotSpawnEgg: return 662; case Item::Peony: return 308; case Item::PetrifiedOakSlab: return 120; case Item::PhantomMembrane: return 787; case Item::PhantomSpawnEgg: return 663; case Item::PigSpawnEgg: return 664; case Item::PinkBanner: return 741; case Item::PinkBed: return 602; case Item::PinkCarpet: return 288; case Item::PinkConcrete: return 401; case Item::PinkConcretePowder: return 417; case Item::PinkDye: return 586; case Item::PinkGlazedTerracotta: return 385; case Item::PinkShulkerBox: return 369; case Item::PinkStainedGlass: return 317; case Item::PinkStainedGlassPane: return 333; case Item::PinkTerracotta: return 269; case Item::PinkTulip: return 106; case Item::PinkWool: return 88; case Item::Piston: return 81; case Item::PlayerHead: return 705; case Item::Podzol: return 11; case Item::PoisonousPotato: return 700; case Item::PolarBearSpawnEgg: return 665; case Item::PolishedAndesite: return 7; case Item::PolishedDiorite: return 5; case Item::PolishedGranite: return 3; case Item::PoppedChorusFruit: return 753; case Item::Poppy: return 99; case Item::Porkchop: return 536; case Item::Potato: return 698; case Item::Potion: return 629; case Item::PoweredRail: return 72; case Item::Prismarine: return 343; case Item::PrismarineBrickSlab: return 129; case Item::PrismarineBrickStairs: return 347; case Item::PrismarineBricks: return 344; case Item::PrismarineCrystals: return 720; case Item::PrismarineShard: return 719; case Item::PrismarineSlab: return 128; case Item::PrismarineStairs: return 346; case Item::Pufferfish: return 574; case Item::PufferfishBucket: return 552; case Item::PufferfishSpawnEgg: return 666; case Item::Pumpkin: return 181; case Item::PumpkinPie: return 711; case Item::PumpkinSeeds: return 617; case Item::PurpleBanner: return 745; case Item::PurpleBed: return 606; case Item::PurpleCarpet: return 292; case Item::PurpleConcrete: return 405; case Item::PurpleConcretePowder: return 421; case Item::PurpleDye: return 582; case Item::PurpleGlazedTerracotta: return 389; case Item::PurpleShulkerBox: return 373; case Item::PurpleStainedGlass: return 321; case Item::PurpleStainedGlassPane: return 337; case Item::PurpleTerracotta: return 273; case Item::PurpleWool: return 92; case Item::PurpurBlock: return 144; case Item::PurpurPillar: return 145; case Item::PurpurSlab: return 127; case Item::PurpurStairs: return 146; case Item::Quartz: return 716; case Item::QuartzBlock: return 258; case Item::QuartzPillar: return 259; case Item::QuartzSlab: return 125; case Item::QuartzStairs: return 260; case Item::Rabbit: return 721; case Item::RabbitFoot: return 724; case Item::RabbitHide: return 725; case Item::RabbitSpawnEgg: return 667; case Item::RabbitStew: return 723; case Item::Rail: return 156; case Item::RedBanner: return 749; case Item::RedBed: return 610; case Item::RedCarpet: return 296; case Item::RedConcrete: return 409; case Item::RedConcretePowder: return 425; case Item::RedGlazedTerracotta: return 393; case Item::RedMushroom: return 109; case Item::RedMushroomBlock: return 204; case Item::RedNetherBricks: return 358; case Item::RedSand: return 27; case Item::RedSandstone: return 350; case Item::RedSandstoneSlab: return 126; case Item::RedSandstoneStairs: return 353; case Item::RedShulkerBox: return 377; case Item::RedStainedGlass: return 325; case Item::RedStainedGlassPane: return 341; case Item::RedTerracotta: return 277; case Item::RedTulip: return 103; case Item::RedWool: return 96; case Item::Redstone: return 547; case Item::RedstoneBlock: return 254; case Item::RedstoneLamp: return 228; case Item::RedstoneOre: return 166; case Item::RedstoneTorch: return 167; case Item::Repeater: return 467; case Item::RepeatingCommandBlock: return 354; case Item::RoseBush: return 307; case Item::RedDye: return 578; case Item::RottenFlesh: return 623; case Item::Saddle: return 546; case Item::Salmon: return 572; case Item::SalmonBucket: return 553; case Item::SalmonSpawnEgg: return 668; case Item::Sand: return 26; case Item::Sandstone: return 68; case Item::SandstoneSlab: return 119; case Item::SandstoneStairs: return 229; case Item::Scute: return 471; case Item::SeaLantern: return 349; case Item::SeaPickle: return 80; case Item::Seagrass: return 79; case Item::Shears: return 614; case Item::SheepSpawnEgg: return 669; case Item::Shield: return 762; case Item::ShulkerBox: return 362; case Item::ShulkerShell: return 770; case Item::ShulkerSpawnEgg: return 670; case Item::OakSign: return 541; case Item::SilverfishSpawnEgg: return 671; case Item::SkeletonHorseSpawnEgg: return 673; case Item::SkeletonSkull: return 703; case Item::SkeletonSpawnEgg: return 672; case Item::SlimeBall: return 563; case Item::SlimeBlock: return 303; case Item::SlimeSpawnEgg: return 674; case Item::SmoothQuartz: return 131; case Item::SmoothRedSandstone: return 132; case Item::SmoothSandstone: return 133; case Item::SmoothStone: return 134; case Item::Snow: return 169; case Item::SnowBlock: return 171; case Item::Snowball: return 548; case Item::SoulSand: return 184; case Item::Spawner: return 147; case Item::SpectralArrow: return 759; case Item::SpiderEye: return 631; case Item::SpiderSpawnEgg: return 675; case Item::SplashPotion: return 758; case Item::Sponge: return 62; case Item::SpruceBoat: return 764; case Item::SpruceButton: return 242; case Item::SpruceDoor: return 462; case Item::SpruceFence: return 176; case Item::SpruceFenceGate: return 211; case Item::SpruceLeaves: return 57; case Item::SpruceLog: return 33; case Item::SprucePlanks: return 14; case Item::SprucePressurePlate: return 161; case Item::SpruceSapling: return 20; case Item::SpruceSlab: return 113; case Item::SpruceStairs: return 234; case Item::SpruceTrapdoor: return 188; case Item::SpruceWood: return 51; case Item::SquidSpawnEgg: return 676; case Item::Stick: return 497; case Item::StickyPiston: return 74; case Item::Stone: return 1; case Item::StoneAxe: return 492; case Item::StoneBrickSlab: return 123; case Item::StoneBrickStairs: return 217; case Item::StoneBricks: return 199; case Item::StoneButton: return 168; case Item::StoneHoe: return 508; case Item::StonePickaxe: return 491; case Item::StonePressurePlate: return 159; case Item::StoneShovel: return 490; case Item::StoneSlab: return 118; case Item::StoneSword: return 489; case Item::StraySpawnEgg: return 677; case Item::String: return 504; case Item::StrippedAcaciaLog: return 42; case Item::StrippedAcaciaWood: return 48; case Item::StrippedBirchLog: return 40; case Item::StrippedBirchWood: return 46; case Item::StrippedDarkOakLog: return 43; case Item::StrippedDarkOakWood: return 49; case Item::StrippedJungleLog: return 41; case Item::StrippedJungleWood: return 47; case Item::StrippedOakLog: return 38; case Item::StrippedOakWood: return 44; case Item::StrippedSpruceLog: return 39; case Item::StrippedSpruceWood: return 45; case Item::StructureBlock: return 469; case Item::StructureVoid: return 360; case Item::Sugar: return 594; case Item::SugarCane: return 558; case Item::Sunflower: return 305; case Item::TallGrass: return 309; case Item::Terracotta: return 298; case Item::TippedArrow: return 760; case Item::TNT: return 136; case Item::TNTMinecart: return 717; case Item::Torch: return 140; case Item::TotemOfUndying: return 769; case Item::TrappedChest: return 250; case Item::Trident: return 786; case Item::TripwireHook: return 232; case Item::TropicalFish: return 573; case Item::TropicalFishBucket: return 555; case Item::TropicalFishSpawnEgg: return 678; case Item::TubeCoral: return 438; case Item::TubeCoralBlock: return 433; case Item::TubeCoralFan: return 448; case Item::TurtleEgg: return 427; case Item::TurtleHelmet: return 470; case Item::TurtleSpawnEgg: return 679; case Item::VexSpawnEgg: return 680; case Item::VillagerSpawnEgg: return 681; case Item::VindicatorSpawnEgg: return 682; case Item::Vine: return 209; case Item::WaterBucket: return 543; case Item::WetSponge: return 63; case Item::Wheat: return 513; case Item::WheatSeeds: return 512; case Item::WhiteBanner: return 735; case Item::WhiteBed: return 596; case Item::WhiteCarpet: return 282; case Item::WhiteConcrete: return 395; case Item::WhiteConcretePowder: return 411; case Item::WhiteGlazedTerracotta: return 379; case Item::WhiteShulkerBox: return 363; case Item::WhiteStainedGlass: return 311; case Item::WhiteStainedGlassPane: return 327; case Item::WhiteTerracotta: return 263; case Item::WhiteTulip: return 105; case Item::WhiteWool: return 82; case Item::WitchSpawnEgg: return 683; case Item::WitherSkeletonSkull: return 704; case Item::WitherSkeletonSpawnEgg: return 684; case Item::WolfSpawnEgg: return 685; case Item::WoodenAxe: return 488; case Item::WoodenHoe: return 507; case Item::WoodenPickaxe: return 487; case Item::WoodenShovel: return 486; case Item::WoodenSword: return 485; case Item::WritableBook: return 692; case Item::WrittenBook: return 693; case Item::YellowBanner: return 739; case Item::YellowBed: return 600; case Item::YellowCarpet: return 286; case Item::YellowConcrete: return 399; case Item::YellowConcretePowder: return 415; case Item::YellowGlazedTerracotta: return 383; case Item::YellowShulkerBox: return 367; case Item::YellowStainedGlass: return 315; case Item::YellowStainedGlassPane: return 331; case Item::YellowTerracotta: return 267; case Item::YellowWool: return 86; case Item::ZombieHead: return 706; case Item::ZombieHorseSpawnEgg: return 687; case Item::ZombiePigmanSpawnEgg: return 688; case Item::ZombieSpawnEgg: return 686; case Item::ZombieVillagerSpawnEgg: return 689; default: return 0; } } UInt32 From(const CustomStatistic ID) { switch (ID) { case CustomStatistic::AnimalsBred: return 30; case CustomStatistic::AviateOneCm: return 17; case CustomStatistic::BoatOneCm: return 14; case CustomStatistic::CleanArmor: return 38; case CustomStatistic::CleanBanner: return 39; case CustomStatistic::CleanShulkerBox: return 40; case CustomStatistic::ClimbOneCm: return 10; case CustomStatistic::CrouchOneCm: return 6; case CustomStatistic::DamageAbsorbed: return 26; case CustomStatistic::DamageBlockedByShield: return 25; case CustomStatistic::DamageDealt: return 21; case CustomStatistic::DamageDealtAbsorbed: return 22; case CustomStatistic::DamageDealtResisted: return 23; case CustomStatistic::DamageResisted: return 27; case CustomStatistic::DamageTaken: return 24; case CustomStatistic::Deaths: return 28; case CustomStatistic::Drop: return 20; case CustomStatistic::EatCakeSlice: return 35; case CustomStatistic::EnchantItem: return 51; case CustomStatistic::FallOneCm: return 9; case CustomStatistic::FillCauldron: return 36; case CustomStatistic::FishCaught: return 32; case CustomStatistic::FlyOneCm: return 11; case CustomStatistic::HorseOneCm: return 16; case CustomStatistic::InspectDispenser: return 45; case CustomStatistic::InspectDropper: return 43; case CustomStatistic::InspectHopper: return 44; case CustomStatistic::InteractWithBeacon: return 42; case CustomStatistic::InteractWithBrewingstand: return 41; case CustomStatistic::InteractWithCraftingTable: return 54; case CustomStatistic::InteractWithFurnace: return 53; case CustomStatistic::Jump: return 19; case CustomStatistic::LeaveGame: return 0; case CustomStatistic::MinecartOneCm: return 13; case CustomStatistic::MobKills: return 29; case CustomStatistic::OpenChest: return 55; case CustomStatistic::OpenEnderchest: return 50; case CustomStatistic::OpenShulkerBox: return 57; case CustomStatistic::PigOneCm: return 15; case CustomStatistic::PlayerKills: return 31; case CustomStatistic::PlayNoteblock: return 46; case CustomStatistic::PlayOneMinute: return 1; case CustomStatistic::PlayRecord: return 52; case CustomStatistic::PotFlower: return 48; case CustomStatistic::SleepInBed: return 56; case CustomStatistic::SneakTime: return 4; case CustomStatistic::SprintOneCm: return 7; case CustomStatistic::SwimOneCm: return 8; case CustomStatistic::TalkedToVillager: return 33; case CustomStatistic::TimeSinceDeath: return 2; case CustomStatistic::TimeSinceRest: return 3; case CustomStatistic::TradedWithVillager: return 34; case CustomStatistic::TriggerTrappedChest: return 49; case CustomStatistic::TuneNoteblock: return 47; case CustomStatistic::UseCauldron: return 37; case CustomStatistic::WalkOneCm: return 5; case CustomStatistic::WalkOnWaterOneCm: return 18; case CustomStatistic::WalkUnderWaterOneCm: return 12; default: return UInt32(-1); } } Item ToItem(const UInt32 ID) { switch (ID) { case 767: return Item::AcaciaBoat; case 245: return Item::AcaciaButton; case 465: return Item::AcaciaDoor; case 179: return Item::AcaciaFence; case 214: return Item::AcaciaFenceGate; case 60: return Item::AcaciaLeaves; case 36: return Item::AcaciaLog; case 17: return Item::AcaciaPlanks; case 164: return Item::AcaciaPressurePlate; case 23: return Item::AcaciaSapling; case 116: return Item::AcaciaSlab; case 301: return Item::AcaciaStairs; case 191: return Item::AcaciaTrapdoor; case 54: return Item::AcaciaWood; case 261: return Item::ActivatorRail; case -0: return Item::Air; case 101: return Item::Allium; case 6: return Item::Andesite; case 247: return Item::Anvil; case 476: return Item::Apple; case 726: return Item::ArmorStand; case 478: return Item::Arrow; case 102: return Item::AzureBluet; case 699: return Item::BakedPotato; case 279: return Item::Barrier; case 639: return Item::BatSpawnEgg; case 238: return Item::Beacon; case 25: return Item::Bedrock; case 619: return Item::Beef; case 754: return Item::Beetroot; case 755: return Item::BeetrootSeeds; case 756: return Item::BeetrootSoup; case 765: return Item::BirchBoat; case 243: return Item::BirchButton; case 463: return Item::BirchDoor; case 177: return Item::BirchFence; case 212: return Item::BirchFenceGate; case 58: return Item::BirchLeaves; case 34: return Item::BirchLog; case 15: return Item::BirchPlanks; case 162: return Item::BirchPressurePlate; case 21: return Item::BirchSapling; case 114: return Item::BirchSlab; case 235: return Item::BirchStairs; case 189: return Item::BirchTrapdoor; case 52: return Item::BirchWood; case 750: return Item::BlackBanner; case 611: return Item::BlackBed; case 297: return Item::BlackCarpet; case 410: return Item::BlackConcrete; case 426: return Item::BlackConcretePowder; case 394: return Item::BlackGlazedTerracotta; case 378: return Item::BlackShulkerBox; case 326: return Item::BlackStainedGlass; case 342: return Item::BlackStainedGlassPane; case 278: return Item::BlackTerracotta; case 97: return Item::BlackWool; case 633: return Item::BlazePowder; case 625: return Item::BlazeRod; case 640: return Item::BlazeSpawnEgg; case 746: return Item::BlueBanner; case 607: return Item::BlueBed; case 293: return Item::BlueCarpet; case 406: return Item::BlueConcrete; case 422: return Item::BlueConcretePowder; case 390: return Item::BlueGlazedTerracotta; case 458: return Item::BlueIce; case 100: return Item::BlueOrchid; case 374: return Item::BlueShulkerBox; case 322: return Item::BlueStainedGlass; case 338: return Item::BlueStainedGlassPane; case 274: return Item::BlueTerracotta; case 93: return Item::BlueWool; case 593: return Item::Bone; case 359: return Item::BoneBlock; case 592: return Item::BoneMeal; case 562: return Item::Book; case 137: return Item::Bookshelf; case 477: return Item::Bow; case 498: return Item::Bowl; case 439: return Item::BrainCoral; case 434: return Item::BrainCoralBlock; case 449: return Item::BrainCoralFan; case 514: return Item::Bread; case 635: return Item::BrewingStand; case 556: return Item::Brick; case 122: return Item::BrickSlab; case 216: return Item::BrickStairs; case 135: return Item::Bricks; case 747: return Item::BrownBanner; case 608: return Item::BrownBed; case 294: return Item::BrownCarpet; case 407: return Item::BrownConcrete; case 423: return Item::BrownConcretePowder; case 391: return Item::BrownGlazedTerracotta; case 108: return Item::BrownMushroom; case 203: return Item::BrownMushroomBlock; case 375: return Item::BrownShulkerBox; case 323: return Item::BrownStainedGlass; case 339: return Item::BrownStainedGlassPane; case 275: return Item::BrownTerracotta; case 94: return Item::BrownWool; case 440: return Item::BubbleCoral; case 435: return Item::BubbleCoralBlock; case 450: return Item::BubbleCoralFan; case 542: return Item::Bucket; case 172: return Item::Cactus; case 579: return Item::GreenDye; case 595: return Item::Cake; case 697: return Item::Carrot; case 709: return Item::CarrotOnAStick; case 182: return Item::CarvedPumpkin; case 636: return Item::Cauldron; case 641: return Item::CaveSpiderSpawnEgg; case 355: return Item::ChainCommandBlock; case 522: return Item::ChainmailBoots; case 520: return Item::ChainmailChestplate; case 519: return Item::ChainmailHelmet; case 521: return Item::ChainmailLeggings; case 480: return Item::Charcoal; case 149: return Item::Chest; case 564: return Item::ChestMinecart; case 621: return Item::Chicken; case 642: return Item::ChickenSpawnEgg; case 248: return Item::ChippedAnvil; case 257: return Item::ChiseledQuartzBlock; case 351: return Item::ChiseledRedSandstone; case 69: return Item::ChiseledSandstone; case 202: return Item::ChiseledStoneBricks; case 143: return Item::ChorusFlower; case 752: return Item::ChorusFruit; case 142: return Item::ChorusPlant; case 173: return Item::Clay; case 557: return Item::ClayBall; case 569: return Item::Clock; case 479: return Item::Coal; case 299: return Item::CoalBlock; case 31: return Item::CoalOre; case 10: return Item::CoarseDirt; case 12: return Item::Cobblestone; case 121: return Item::CobblestoneSlab; case 157: return Item::CobblestoneStairs; case 239: return Item::CobblestoneWall; case 75: return Item::Cobweb; case 580: return Item::CocoaBeans; case 571: return Item::Cod; case 554: return Item::CodBucket; case 643: return Item::CodSpawnEgg; case 237: return Item::CommandBlock; case 732: return Item::CommandBlockMinecart; case 468: return Item::Comparator; case 567: return Item::Compass; case 459: return Item::Conduit; case 620: return Item::CookedBeef; case 622: return Item::CookedChicken; case 575: return Item::CookedCod; case 734: return Item::CookedMutton; case 537: return Item::CookedPorkchop; case 722: return Item::CookedRabbit; case 576: return Item::CookedSalmon; case 612: return Item::Cookie; case 644: return Item::CowSpawnEgg; case 201: return Item::CrackedStoneBricks; case 152: return Item::CraftingTable; case 707: return Item::CreeperHead; case 645: return Item::CreeperSpawnEgg; case 352: return Item::CutRedSandstone; case 70: return Item::CutSandstone; case 744: return Item::CyanBanner; case 605: return Item::CyanBed; case 291: return Item::CyanCarpet; case 404: return Item::CyanConcrete; case 420: return Item::CyanConcretePowder; case 583: return Item::CyanDye; case 388: return Item::CyanGlazedTerracotta; case 372: return Item::CyanShulkerBox; case 320: return Item::CyanStainedGlass; case 336: return Item::CyanStainedGlassPane; case 272: return Item::CyanTerracotta; case 91: return Item::CyanWool; case 249: return Item::DamagedAnvil; case 98: return Item::Dandelion; case 588: return Item::YellowDye; case 768: return Item::DarkOakBoat; case 246: return Item::DarkOakButton; case 466: return Item::DarkOakDoor; case 180: return Item::DarkOakFence; case 215: return Item::DarkOakFenceGate; case 61: return Item::DarkOakLeaves; case 37: return Item::DarkOakLog; case 18: return Item::DarkOakPlanks; case 165: return Item::DarkOakPressurePlate; case 24: return Item::DarkOakSapling; case 117: return Item::DarkOakSlab; case 302: return Item::DarkOakStairs; case 192: return Item::DarkOakTrapdoor; case 55: return Item::DarkOakWood; case 345: return Item::DarkPrismarine; case 130: return Item::DarkPrismarineSlab; case 348: return Item::DarkPrismarineStairs; case 253: return Item::DaylightDetector; case 443: return Item::DeadBrainCoral; case 429: return Item::DeadBrainCoralBlock; case 454: return Item::DeadBrainCoralFan; case 444: return Item::DeadBubbleCoral; case 430: return Item::DeadBubbleCoralBlock; case 455: return Item::DeadBubbleCoralFan; case 78: return Item::DeadBush; case 445: return Item::DeadFireCoral; case 431: return Item::DeadFireCoralBlock; case 456: return Item::DeadFireCoralFan; case 446: return Item::DeadHornCoral; case 432: return Item::DeadHornCoralBlock; case 457: return Item::DeadHornCoralFan; case 447: return Item::DeadTubeCoral; case 428: return Item::DeadTubeCoralBlock; case 453: return Item::DeadTubeCoralFan; case 773: return Item::DebugStick; case 73: return Item::DetectorRail; case 481: return Item::Diamond; case 496: return Item::DiamondAxe; case 151: return Item::DiamondBlock; case 530: return Item::DiamondBoots; case 528: return Item::DiamondChestplate; case 527: return Item::DiamondHelmet; case 510: return Item::DiamondHoe; case 729: return Item::DiamondHorseArmor; case 529: return Item::DiamondLeggings; case 150: return Item::DiamondOre; case 495: return Item::DiamondPickaxe; case 494: return Item::DiamondShovel; case 493: return Item::DiamondSword; case 4: return Item::Diorite; case 9: return Item::Dirt; case 67: return Item::Dispenser; case 646: return Item::DolphinSpawnEgg; case 647: return Item::DonkeySpawnEgg; case 757: return Item::DragonBreath; case 227: return Item::DragonEgg; case 708: return Item::DragonHead; case 616: return Item::DriedKelp; case 560: return Item::DriedKelpBlock; case 262: return Item::Dropper; case 648: return Item::DrownedSpawnEgg; case 566: return Item::Egg; case 649: return Item::ElderGuardianSpawnEgg; case 763: return Item::Elytra; case 694: return Item::Emerald; case 233: return Item::EmeraldBlock; case 230: return Item::EmeraldOre; case 714: return Item::EnchantedBook; case 540: return Item::EnchantedGoldenApple; case 223: return Item::EnchantingTable; case 751: return Item::EndCrystal; case 224: return Item::EndPortalFrame; case 141: return Item::EndRod; case 225: return Item::EndStone; case 226: return Item::EndStoneBricks; case 231: return Item::EnderChest; case 637: return Item::EnderEye; case 624: return Item::EnderPearl; case 650: return Item::EndermanSpawnEgg; case 651: return Item::EndermiteSpawnEgg; case 652: return Item::EvokerSpawnEgg; case 690: return Item::ExperienceBottle; case 153: return Item::Farmland; case 505: return Item::Feather; case 632: return Item::FermentedSpiderEye; case 77: return Item::Fern; case 613: return Item::FilledMap; case 691: return Item::FireCharge; case 441: return Item::FireCoral; case 436: return Item::FireCoralBlock; case 451: return Item::FireCoralFan; case 712: return Item::FireworkRocket; case 713: return Item::FireworkStar; case 568: return Item::FishingRod; case 535: return Item::Flint; case 475: return Item::FlintAndSteel; case 696: return Item::FlowerPot; case 154: return Item::Furnace; case 565: return Item::FurnaceMinecart; case 653: return Item::GhastSpawnEgg; case 626: return Item::GhastTear; case 64: return Item::Glass; case 630: return Item::GlassBottle; case 207: return Item::GlassPane; case 638: return Item::GlisteringMelonSlice; case 185: return Item::Glowstone; case 570: return Item::GlowstoneDust; case 110: return Item::GoldBlock; case 483: return Item::GoldIngot; case 627: return Item::GoldNugget; case 29: return Item::GoldOre; case 539: return Item::GoldenApple; case 503: return Item::GoldenAxe; case 534: return Item::GoldenBoots; case 702: return Item::GoldenCarrot; case 532: return Item::GoldenChestplate; case 531: return Item::GoldenHelmet; case 511: return Item::GoldenHoe; case 728: return Item::GoldenHorseArmor; case 533: return Item::GoldenLeggings; case 502: return Item::GoldenPickaxe; case 501: return Item::GoldenShovel; case 500: return Item::GoldenSword; case 2: return Item::Granite; case 76: return Item::Grass; case 8: return Item::GrassBlock; case 304: return Item::GrassPath; case 28: return Item::Gravel; case 742: return Item::GrayBanner; case 603: return Item::GrayBed; case 289: return Item::GrayCarpet; case 402: return Item::GrayConcrete; case 418: return Item::GrayConcretePowder; case 585: return Item::GrayDye; case 386: return Item::GrayGlazedTerracotta; case 370: return Item::GrayShulkerBox; case 318: return Item::GrayStainedGlass; case 334: return Item::GrayStainedGlassPane; case 270: return Item::GrayTerracotta; case 89: return Item::GrayWool; case 748: return Item::GreenBanner; case 609: return Item::GreenBed; case 295: return Item::GreenCarpet; case 408: return Item::GreenConcrete; case 424: return Item::GreenConcretePowder; case 392: return Item::GreenGlazedTerracotta; case 376: return Item::GreenShulkerBox; case 324: return Item::GreenStainedGlass; case 340: return Item::GreenStainedGlassPane; case 276: return Item::GreenTerracotta; case 95: return Item::GreenWool; case 654: return Item::GuardianSpawnEgg; case 506: return Item::Gunpowder; case 281: return Item::HayBale; case 789: return Item::HeartOfTheSea; case 252: return Item::HeavyWeightedPressurePlate; case 256: return Item::Hopper; case 718: return Item::HopperMinecart; case 442: return Item::HornCoral; case 437: return Item::HornCoralBlock; case 452: return Item::HornCoralFan; case 655: return Item::HorseSpawnEgg; case 656: return Item::HuskSpawnEgg; case 170: return Item::Ice; case 198: return Item::InfestedChiseledStoneBricks; case 194: return Item::InfestedCobblestone; case 197: return Item::InfestedCrackedStoneBricks; case 196: return Item::InfestedMossyStoneBricks; case 193: return Item::InfestedStone; case 195: return Item::InfestedStoneBricks; case 577: return Item::InkSac; case 474: return Item::IronAxe; case 206: return Item::IronBars; case 111: return Item::IronBlock; case 526: return Item::IronBoots; case 524: return Item::IronChestplate; case 460: return Item::IronDoor; case 523: return Item::IronHelmet; case 509: return Item::IronHoe; case 727: return Item::IronHorseArmor; case 482: return Item::IronIngot; case 525: return Item::IronLeggings; case 771: return Item::IronNugget; case 30: return Item::IronOre; case 473: return Item::IronPickaxe; case 472: return Item::IronShovel; case 484: return Item::IronSword; case 280: return Item::IronTrapdoor; case 695: return Item::ItemFrame; case 186: return Item::JackOLantern; case 174: return Item::Jukebox; case 766: return Item::JungleBoat; case 244: return Item::JungleButton; case 464: return Item::JungleDoor; case 178: return Item::JungleFence; case 213: return Item::JungleFenceGate; case 59: return Item::JungleLeaves; case 35: return Item::JungleLog; case 16: return Item::JunglePlanks; case 163: return Item::JunglePressurePlate; case 22: return Item::JungleSapling; case 115: return Item::JungleSlab; case 236: return Item::JungleStairs; case 190: return Item::JungleTrapdoor; case 53: return Item::JungleWood; case 559: return Item::Kelp; case 772: return Item::KnowledgeBook; case 155: return Item::Ladder; case 66: return Item::LapisBlock; case 581: return Item::LapisLazuli; case 65: return Item::LapisOre; case 310: return Item::LargeFern; case 544: return Item::LavaBucket; case 730: return Item::Lead; case 550: return Item::Leather; case 518: return Item::LeatherBoots; case 516: return Item::LeatherChestplate; case 515: return Item::LeatherHelmet; case 517: return Item::LeatherLeggings; case 158: return Item::Lever; case 738: return Item::LightBlueBanner; case 599: return Item::LightBlueBed; case 285: return Item::LightBlueCarpet; case 398: return Item::LightBlueConcrete; case 414: return Item::LightBlueConcretePowder; case 589: return Item::LightBlueDye; case 382: return Item::LightBlueGlazedTerracotta; case 366: return Item::LightBlueShulkerBox; case 314: return Item::LightBlueStainedGlass; case 330: return Item::LightBlueStainedGlassPane; case 266: return Item::LightBlueTerracotta; case 85: return Item::LightBlueWool; case 743: return Item::LightGrayBanner; case 604: return Item::LightGrayBed; case 290: return Item::LightGrayCarpet; case 403: return Item::LightGrayConcrete; case 419: return Item::LightGrayConcretePowder; case 584: return Item::LightGrayDye; case 387: return Item::LightGrayGlazedTerracotta; case 371: return Item::LightGrayShulkerBox; case 319: return Item::LightGrayStainedGlass; case 335: return Item::LightGrayStainedGlassPane; case 271: return Item::LightGrayTerracotta; case 90: return Item::LightGrayWool; case 251: return Item::LightWeightedPressurePlate; case 306: return Item::Lilac; case 219: return Item::LilyPad; case 740: return Item::LimeBanner; case 601: return Item::LimeBed; case 287: return Item::LimeCarpet; case 400: return Item::LimeConcrete; case 416: return Item::LimeConcretePowder; case 587: return Item::LimeDye; case 384: return Item::LimeGlazedTerracotta; case 368: return Item::LimeShulkerBox; case 316: return Item::LimeStainedGlass; case 332: return Item::LimeStainedGlassPane; case 268: return Item::LimeTerracotta; case 87: return Item::LimeWool; case 761: return Item::LingeringPotion; case 657: return Item::LlamaSpawnEgg; case 737: return Item::MagentaBanner; case 598: return Item::MagentaBed; case 284: return Item::MagentaCarpet; case 397: return Item::MagentaConcrete; case 413: return Item::MagentaConcretePowder; case 590: return Item::MagentaDye; case 381: return Item::MagentaGlazedTerracotta; case 365: return Item::MagentaShulkerBox; case 313: return Item::MagentaStainedGlass; case 329: return Item::MagentaStainedGlassPane; case 265: return Item::MagentaTerracotta; case 84: return Item::MagentaWool; case 356: return Item::MagmaBlock; case 634: return Item::MagmaCream; case 658: return Item::MagmaCubeSpawnEgg; case 701: return Item::Map; case 208: return Item::Melon; case 618: return Item::MelonSeeds; case 615: return Item::MelonSlice; case 551: return Item::MilkBucket; case 545: return Item::Minecart; case 659: return Item::MooshroomSpawnEgg; case 138: return Item::MossyCobblestone; case 240: return Item::MossyCobblestoneWall; case 200: return Item::MossyStoneBricks; case 660: return Item::MuleSpawnEgg; case 205: return Item::MushroomStem; case 499: return Item::MushroomStew; case 784: return Item::MusicDisc11; case 774: return Item::MusicDisc13; case 776: return Item::MusicDiscBlocks; case 775: return Item::MusicDiscCat; case 777: return Item::MusicDiscChirp; case 778: return Item::MusicDiscFar; case 779: return Item::MusicDiscMall; case 780: return Item::MusicDiscMellohi; case 781: return Item::MusicDiscStal; case 782: return Item::MusicDiscStrad; case 785: return Item::MusicDiscWait; case 783: return Item::MusicDiscWard; case 733: return Item::Mutton; case 218: return Item::Mycelium; case 731: return Item::NameTag; case 788: return Item::NautilusShell; case 715: return Item::NetherBrick; case 221: return Item::NetherBrickFence; case 124: return Item::NetherBrickSlab; case 222: return Item::NetherBrickStairs; case 220: return Item::NetherBricks; case 255: return Item::NetherQuartzOre; case 710: return Item::NetherStar; case 628: return Item::NetherWart; case 357: return Item::NetherWartBlock; case 183: return Item::Netherrack; case 71: return Item::NoteBlock; case 549: return Item::OakBoat; case 241: return Item::OakButton; case 461: return Item::OakDoor; case 175: return Item::OakFence; case 210: return Item::OakFenceGate; case 56: return Item::OakLeaves; case 32: return Item::OakLog; case 13: return Item::OakPlanks; case 160: return Item::OakPressurePlate; case 19: return Item::OakSapling; case 112: return Item::OakSlab; case 148: return Item::OakStairs; case 187: return Item::OakTrapdoor; case 50: return Item::OakWood; case 361: return Item::Observer; case 139: return Item::Obsidian; case 661: return Item::OcelotSpawnEgg; case 736: return Item::OrangeBanner; case 597: return Item::OrangeBed; case 283: return Item::OrangeCarpet; case 396: return Item::OrangeConcrete; case 412: return Item::OrangeConcretePowder; case 591: return Item::OrangeDye; case 380: return Item::OrangeGlazedTerracotta; case 364: return Item::OrangeShulkerBox; case 312: return Item::OrangeStainedGlass; case 328: return Item::OrangeStainedGlassPane; case 264: return Item::OrangeTerracotta; case 104: return Item::OrangeTulip; case 83: return Item::OrangeWool; case 107: return Item::OxeyeDaisy; case 300: return Item::PackedIce; case 538: return Item::Painting; case 561: return Item::Paper; case 662: return Item::ParrotSpawnEgg; case 308: return Item::Peony; case 120: return Item::PetrifiedOakSlab; case 787: return Item::PhantomMembrane; case 663: return Item::PhantomSpawnEgg; case 664: return Item::PigSpawnEgg; case 741: return Item::PinkBanner; case 602: return Item::PinkBed; case 288: return Item::PinkCarpet; case 401: return Item::PinkConcrete; case 417: return Item::PinkConcretePowder; case 586: return Item::PinkDye; case 385: return Item::PinkGlazedTerracotta; case 369: return Item::PinkShulkerBox; case 317: return Item::PinkStainedGlass; case 333: return Item::PinkStainedGlassPane; case 269: return Item::PinkTerracotta; case 106: return Item::PinkTulip; case 88: return Item::PinkWool; case 81: return Item::Piston; case 705: return Item::PlayerHead; case 11: return Item::Podzol; case 700: return Item::PoisonousPotato; case 665: return Item::PolarBearSpawnEgg; case 7: return Item::PolishedAndesite; case 5: return Item::PolishedDiorite; case 3: return Item::PolishedGranite; case 753: return Item::PoppedChorusFruit; case 99: return Item::Poppy; case 536: return Item::Porkchop; case 698: return Item::Potato; case 629: return Item::Potion; case 72: return Item::PoweredRail; case 343: return Item::Prismarine; case 129: return Item::PrismarineBrickSlab; case 347: return Item::PrismarineBrickStairs; case 344: return Item::PrismarineBricks; case 720: return Item::PrismarineCrystals; case 719: return Item::PrismarineShard; case 128: return Item::PrismarineSlab; case 346: return Item::PrismarineStairs; case 574: return Item::Pufferfish; case 552: return Item::PufferfishBucket; case 666: return Item::PufferfishSpawnEgg; case 181: return Item::Pumpkin; case 711: return Item::PumpkinPie; case 617: return Item::PumpkinSeeds; case 745: return Item::PurpleBanner; case 606: return Item::PurpleBed; case 292: return Item::PurpleCarpet; case 405: return Item::PurpleConcrete; case 421: return Item::PurpleConcretePowder; case 582: return Item::PurpleDye; case 389: return Item::PurpleGlazedTerracotta; case 373: return Item::PurpleShulkerBox; case 321: return Item::PurpleStainedGlass; case 337: return Item::PurpleStainedGlassPane; case 273: return Item::PurpleTerracotta; case 92: return Item::PurpleWool; case 144: return Item::PurpurBlock; case 145: return Item::PurpurPillar; case 127: return Item::PurpurSlab; case 146: return Item::PurpurStairs; case 716: return Item::Quartz; case 258: return Item::QuartzBlock; case 259: return Item::QuartzPillar; case 125: return Item::QuartzSlab; case 260: return Item::QuartzStairs; case 721: return Item::Rabbit; case 724: return Item::RabbitFoot; case 725: return Item::RabbitHide; case 667: return Item::RabbitSpawnEgg; case 723: return Item::RabbitStew; case 156: return Item::Rail; case 749: return Item::RedBanner; case 610: return Item::RedBed; case 296: return Item::RedCarpet; case 409: return Item::RedConcrete; case 425: return Item::RedConcretePowder; case 393: return Item::RedGlazedTerracotta; case 109: return Item::RedMushroom; case 204: return Item::RedMushroomBlock; case 358: return Item::RedNetherBricks; case 27: return Item::RedSand; case 350: return Item::RedSandstone; case 126: return Item::RedSandstoneSlab; case 353: return Item::RedSandstoneStairs; case 377: return Item::RedShulkerBox; case 325: return Item::RedStainedGlass; case 341: return Item::RedStainedGlassPane; case 277: return Item::RedTerracotta; case 103: return Item::RedTulip; case 96: return Item::RedWool; case 547: return Item::Redstone; case 254: return Item::RedstoneBlock; case 228: return Item::RedstoneLamp; case 166: return Item::RedstoneOre; case 167: return Item::RedstoneTorch; case 467: return Item::Repeater; case 354: return Item::RepeatingCommandBlock; case 307: return Item::RoseBush; case 578: return Item::RedDye; case 623: return Item::RottenFlesh; case 546: return Item::Saddle; case 572: return Item::Salmon; case 553: return Item::SalmonBucket; case 668: return Item::SalmonSpawnEgg; case 26: return Item::Sand; case 68: return Item::Sandstone; case 119: return Item::SandstoneSlab; case 229: return Item::SandstoneStairs; case 471: return Item::Scute; case 349: return Item::SeaLantern; case 80: return Item::SeaPickle; case 79: return Item::Seagrass; case 614: return Item::Shears; case 669: return Item::SheepSpawnEgg; case 762: return Item::Shield; case 362: return Item::ShulkerBox; case 770: return Item::ShulkerShell; case 670: return Item::ShulkerSpawnEgg; case 541: return Item::OakSign; case 671: return Item::SilverfishSpawnEgg; case 673: return Item::SkeletonHorseSpawnEgg; case 703: return Item::SkeletonSkull; case 672: return Item::SkeletonSpawnEgg; case 563: return Item::SlimeBall; case 303: return Item::SlimeBlock; case 674: return Item::SlimeSpawnEgg; case 131: return Item::SmoothQuartz; case 132: return Item::SmoothRedSandstone; case 133: return Item::SmoothSandstone; case 134: return Item::SmoothStone; case 169: return Item::Snow; case 171: return Item::SnowBlock; case 548: return Item::Snowball; case 184: return Item::SoulSand; case 147: return Item::Spawner; case 759: return Item::SpectralArrow; case 631: return Item::SpiderEye; case 675: return Item::SpiderSpawnEgg; case 758: return Item::SplashPotion; case 62: return Item::Sponge; case 764: return Item::SpruceBoat; case 242: return Item::SpruceButton; case 462: return Item::SpruceDoor; case 176: return Item::SpruceFence; case 211: return Item::SpruceFenceGate; case 57: return Item::SpruceLeaves; case 33: return Item::SpruceLog; case 14: return Item::SprucePlanks; case 161: return Item::SprucePressurePlate; case 20: return Item::SpruceSapling; case 113: return Item::SpruceSlab; case 234: return Item::SpruceStairs; case 188: return Item::SpruceTrapdoor; case 51: return Item::SpruceWood; case 676: return Item::SquidSpawnEgg; case 497: return Item::Stick; case 74: return Item::StickyPiston; case 1: return Item::Stone; case 492: return Item::StoneAxe; case 123: return Item::StoneBrickSlab; case 217: return Item::StoneBrickStairs; case 199: return Item::StoneBricks; case 168: return Item::StoneButton; case 508: return Item::StoneHoe; case 491: return Item::StonePickaxe; case 159: return Item::StonePressurePlate; case 490: return Item::StoneShovel; case 118: return Item::StoneSlab; case 489: return Item::StoneSword; case 677: return Item::StraySpawnEgg; case 504: return Item::String; case 42: return Item::StrippedAcaciaLog; case 48: return Item::StrippedAcaciaWood; case 40: return Item::StrippedBirchLog; case 46: return Item::StrippedBirchWood; case 43: return Item::StrippedDarkOakLog; case 49: return Item::StrippedDarkOakWood; case 41: return Item::StrippedJungleLog; case 47: return Item::StrippedJungleWood; case 38: return Item::StrippedOakLog; case 44: return Item::StrippedOakWood; case 39: return Item::StrippedSpruceLog; case 45: return Item::StrippedSpruceWood; case 469: return Item::StructureBlock; case 360: return Item::StructureVoid; case 594: return Item::Sugar; case 558: return Item::SugarCane; case 305: return Item::Sunflower; case 309: return Item::TallGrass; case 298: return Item::Terracotta; case 760: return Item::TippedArrow; case 136: return Item::TNT; case 717: return Item::TNTMinecart; case 140: return Item::Torch; case 769: return Item::TotemOfUndying; case 250: return Item::TrappedChest; case 786: return Item::Trident; case 232: return Item::TripwireHook; case 573: return Item::TropicalFish; case 555: return Item::TropicalFishBucket; case 678: return Item::TropicalFishSpawnEgg; case 438: return Item::TubeCoral; case 433: return Item::TubeCoralBlock; case 448: return Item::TubeCoralFan; case 427: return Item::TurtleEgg; case 470: return Item::TurtleHelmet; case 679: return Item::TurtleSpawnEgg; case 680: return Item::VexSpawnEgg; case 681: return Item::VillagerSpawnEgg; case 682: return Item::VindicatorSpawnEgg; case 209: return Item::Vine; case 543: return Item::WaterBucket; case 63: return Item::WetSponge; case 513: return Item::Wheat; case 512: return Item::WheatSeeds; case 735: return Item::WhiteBanner; case 596: return Item::WhiteBed; case 282: return Item::WhiteCarpet; case 395: return Item::WhiteConcrete; case 411: return Item::WhiteConcretePowder; case 379: return Item::WhiteGlazedTerracotta; case 363: return Item::WhiteShulkerBox; case 311: return Item::WhiteStainedGlass; case 327: return Item::WhiteStainedGlassPane; case 263: return Item::WhiteTerracotta; case 105: return Item::WhiteTulip; case 82: return Item::WhiteWool; case 683: return Item::WitchSpawnEgg; case 704: return Item::WitherSkeletonSkull; case 684: return Item::WitherSkeletonSpawnEgg; case 685: return Item::WolfSpawnEgg; case 488: return Item::WoodenAxe; case 507: return Item::WoodenHoe; case 487: return Item::WoodenPickaxe; case 486: return Item::WoodenShovel; case 485: return Item::WoodenSword; case 692: return Item::WritableBook; case 693: return Item::WrittenBook; case 739: return Item::YellowBanner; case 600: return Item::YellowBed; case 286: return Item::YellowCarpet; case 399: return Item::YellowConcrete; case 415: return Item::YellowConcretePowder; case 383: return Item::YellowGlazedTerracotta; case 367: return Item::YellowShulkerBox; case 315: return Item::YellowStainedGlass; case 331: return Item::YellowStainedGlassPane; case 267: return Item::YellowTerracotta; case 86: return Item::YellowWool; case 706: return Item::ZombieHead; case 687: return Item::ZombieHorseSpawnEgg; case 688: return Item::ZombiePigmanSpawnEgg; case 686: return Item::ZombieSpawnEgg; case 689: return Item::ZombieVillagerSpawnEgg; default: return Item::Air; } } } ================================================ FILE: src/Protocol/Palettes/Palette_1_13_1.h ================================================ #pragma once #include "BlockState.h" #include "Registries/Items.h" #include "Registries/CustomStatistics.h" namespace Palette_1_13_1 { UInt32 From(BlockState Block); UInt32 From(Item ID); UInt32 From(CustomStatistic ID); Item ToItem(UInt32 ID); } ================================================ FILE: src/Protocol/Palettes/Palette_1_14.cpp ================================================ #include "Globals.h" #include "Palette_1_14.h" #include "Registries/BlockStates.h" namespace Palette_1_14 { UInt32 From(const BlockState Block) { using namespace Block; switch (Block.ID) { case AcaciaButton::AcaciaButton(AcaciaButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5906; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5907; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5908; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5909; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, true).ID: return 5910; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, false).ID: return 5911; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, true).ID: return 5912; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, false).ID: return 5913; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5914; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5915; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5916; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5917; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, true).ID: return 5918; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, false).ID: return 5919; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, true).ID: return 5920; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, false).ID: return 5921; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5922; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5923; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5924; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5925; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, true).ID: return 5926; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, false).ID: return 5927; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, true).ID: return 5928; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, false).ID: return 5929; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, true, true).ID: return 8394; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, true, false).ID: return 8395; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, false, true).ID: return 8396; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, false, false).ID: return 8397; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, true, true).ID: return 8398; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, true, false).ID: return 8399; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, false, true).ID: return 8400; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, false, false).ID: return 8401; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, true, true).ID: return 8402; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, true, false).ID: return 8403; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, false, true).ID: return 8404; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, false, false).ID: return 8405; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, true, true).ID: return 8406; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, true, false).ID: return 8407; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, false, true).ID: return 8408; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, false, false).ID: return 8409; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, true, true).ID: return 8410; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, true, false).ID: return 8411; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, false, true).ID: return 8412; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, false, false).ID: return 8413; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, true, true).ID: return 8414; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, true, false).ID: return 8415; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, false, true).ID: return 8416; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, false, false).ID: return 8417; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, true, true).ID: return 8418; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, true, false).ID: return 8419; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, false, true).ID: return 8420; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, false, false).ID: return 8421; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, true, true).ID: return 8422; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, true, false).ID: return 8423; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, false, true).ID: return 8424; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, false, false).ID: return 8425; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, true, true).ID: return 8426; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, true, false).ID: return 8427; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, false, true).ID: return 8428; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, false, false).ID: return 8429; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, true, true).ID: return 8430; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, true, false).ID: return 8431; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, false, true).ID: return 8432; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, false, false).ID: return 8433; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, true, true).ID: return 8434; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, true, false).ID: return 8435; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, false, true).ID: return 8436; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, false, false).ID: return 8437; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, true, true).ID: return 8438; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, true, false).ID: return 8439; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, false, true).ID: return 8440; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, false, false).ID: return 8441; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, true, true).ID: return 8442; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, true, false).ID: return 8443; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, false, true).ID: return 8444; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, false, false).ID: return 8445; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, true, true).ID: return 8446; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, true, false).ID: return 8447; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, false, true).ID: return 8448; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, false, false).ID: return 8449; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, true, true).ID: return 8450; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, true, false).ID: return 8451; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, false, true).ID: return 8452; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, false, false).ID: return 8453; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, true, true).ID: return 8454; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, true, false).ID: return 8455; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, false, true).ID: return 8456; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, false, false).ID: return 8457; case AcaciaFence::AcaciaFence(true, true, true, true).ID: return 8140; case AcaciaFence::AcaciaFence(true, true, true, false).ID: return 8141; case AcaciaFence::AcaciaFence(true, true, false, true).ID: return 8144; case AcaciaFence::AcaciaFence(true, true, false, false).ID: return 8145; case AcaciaFence::AcaciaFence(true, false, true, true).ID: return 8148; case AcaciaFence::AcaciaFence(true, false, true, false).ID: return 8149; case AcaciaFence::AcaciaFence(true, false, false, true).ID: return 8152; case AcaciaFence::AcaciaFence(true, false, false, false).ID: return 8153; case AcaciaFence::AcaciaFence(false, true, true, true).ID: return 8156; case AcaciaFence::AcaciaFence(false, true, true, false).ID: return 8157; case AcaciaFence::AcaciaFence(false, true, false, true).ID: return 8160; case AcaciaFence::AcaciaFence(false, true, false, false).ID: return 8161; case AcaciaFence::AcaciaFence(false, false, true, true).ID: return 8164; case AcaciaFence::AcaciaFence(false, false, true, false).ID: return 8165; case AcaciaFence::AcaciaFence(false, false, false, true).ID: return 8168; case AcaciaFence::AcaciaFence(false, false, false, false).ID: return 8169; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZM, true, true, true).ID: return 7978; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZM, true, true, false).ID: return 7979; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZM, true, false, true).ID: return 7980; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZM, true, false, false).ID: return 7981; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, true).ID: return 7982; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, false).ID: return 7983; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, true).ID: return 7984; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, false).ID: return 7985; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZP, true, true, true).ID: return 7986; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZP, true, true, false).ID: return 7987; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZP, true, false, true).ID: return 7988; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZP, true, false, false).ID: return 7989; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, true).ID: return 7990; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, false).ID: return 7991; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, true).ID: return 7992; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, false).ID: return 7993; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XM, true, true, true).ID: return 7994; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XM, true, true, false).ID: return 7995; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XM, true, false, true).ID: return 7996; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XM, true, false, false).ID: return 7997; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, true).ID: return 7998; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, false).ID: return 7999; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, true).ID: return 8000; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, false).ID: return 8001; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XP, true, true, true).ID: return 8002; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XP, true, true, false).ID: return 8003; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XP, true, false, true).ID: return 8004; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XP, true, false, false).ID: return 8005; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, true).ID: return 8006; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, false).ID: return 8007; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, true).ID: return 8008; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, false).ID: return 8009; case AcaciaLeaves::AcaciaLeaves(1, true).ID: return 200; case AcaciaLeaves::AcaciaLeaves(1, false).ID: return 201; case AcaciaLeaves::AcaciaLeaves(2, true).ID: return 202; case AcaciaLeaves::AcaciaLeaves(2, false).ID: return 203; case AcaciaLeaves::AcaciaLeaves(3, true).ID: return 204; case AcaciaLeaves::AcaciaLeaves(3, false).ID: return 205; case AcaciaLeaves::AcaciaLeaves(4, true).ID: return 206; case AcaciaLeaves::AcaciaLeaves(4, false).ID: return 207; case AcaciaLeaves::AcaciaLeaves(5, true).ID: return 208; case AcaciaLeaves::AcaciaLeaves(5, false).ID: return 209; case AcaciaLeaves::AcaciaLeaves(6, true).ID: return 210; case AcaciaLeaves::AcaciaLeaves(6, false).ID: return 211; case AcaciaLeaves::AcaciaLeaves(7, true).ID: return 212; case AcaciaLeaves::AcaciaLeaves(7, false).ID: return 213; case AcaciaLog::AcaciaLog(AcaciaLog::Axis::X).ID: return 84; case AcaciaLog::AcaciaLog(AcaciaLog::Axis::Y).ID: return 85; case AcaciaLog::AcaciaLog(AcaciaLog::Axis::Z).ID: return 86; case AcaciaPlanks::AcaciaPlanks().ID: return 19; case AcaciaPressurePlate::AcaciaPressurePlate(true).ID: return 3879; case AcaciaPressurePlate::AcaciaPressurePlate(false).ID: return 3880; case AcaciaSapling::AcaciaSapling(0).ID: return 29; case AcaciaSapling::AcaciaSapling(1).ID: return 30; case AcaciaSign::AcaciaSign(0).ID: return 3476; case AcaciaSign::AcaciaSign(1).ID: return 3478; case AcaciaSign::AcaciaSign(2).ID: return 3480; case AcaciaSign::AcaciaSign(3).ID: return 3482; case AcaciaSign::AcaciaSign(4).ID: return 3484; case AcaciaSign::AcaciaSign(5).ID: return 3486; case AcaciaSign::AcaciaSign(6).ID: return 3488; case AcaciaSign::AcaciaSign(7).ID: return 3490; case AcaciaSign::AcaciaSign(8).ID: return 3492; case AcaciaSign::AcaciaSign(9).ID: return 3494; case AcaciaSign::AcaciaSign(10).ID: return 3496; case AcaciaSign::AcaciaSign(11).ID: return 3498; case AcaciaSign::AcaciaSign(12).ID: return 3500; case AcaciaSign::AcaciaSign(13).ID: return 3502; case AcaciaSign::AcaciaSign(14).ID: return 3504; case AcaciaSign::AcaciaSign(15).ID: return 3506; case AcaciaSlab::AcaciaSlab(AcaciaSlab::Type::Top).ID: return 7789; case AcaciaSlab::AcaciaSlab(AcaciaSlab::Type::Bottom).ID: return 7791; case AcaciaSlab::AcaciaSlab(AcaciaSlab::Type::Double).ID: return 7793; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZM, AcaciaStairs::Half::Top, AcaciaStairs::Shape::Straight).ID: return 6840; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZM, AcaciaStairs::Half::Top, AcaciaStairs::Shape::InnerLeft).ID: return 6842; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZM, AcaciaStairs::Half::Top, AcaciaStairs::Shape::InnerRight).ID: return 6844; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZM, AcaciaStairs::Half::Top, AcaciaStairs::Shape::OuterLeft).ID: return 6846; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZM, AcaciaStairs::Half::Top, AcaciaStairs::Shape::OuterRight).ID: return 6848; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZM, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::Straight).ID: return 6850; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZM, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::InnerLeft).ID: return 6852; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZM, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::InnerRight).ID: return 6854; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZM, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::OuterLeft).ID: return 6856; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZM, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::OuterRight).ID: return 6858; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZP, AcaciaStairs::Half::Top, AcaciaStairs::Shape::Straight).ID: return 6860; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZP, AcaciaStairs::Half::Top, AcaciaStairs::Shape::InnerLeft).ID: return 6862; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZP, AcaciaStairs::Half::Top, AcaciaStairs::Shape::InnerRight).ID: return 6864; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZP, AcaciaStairs::Half::Top, AcaciaStairs::Shape::OuterLeft).ID: return 6866; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZP, AcaciaStairs::Half::Top, AcaciaStairs::Shape::OuterRight).ID: return 6868; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZP, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::Straight).ID: return 6870; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZP, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::InnerLeft).ID: return 6872; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZP, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::InnerRight).ID: return 6874; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZP, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::OuterLeft).ID: return 6876; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZP, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::OuterRight).ID: return 6878; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XM, AcaciaStairs::Half::Top, AcaciaStairs::Shape::Straight).ID: return 6880; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XM, AcaciaStairs::Half::Top, AcaciaStairs::Shape::InnerLeft).ID: return 6882; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XM, AcaciaStairs::Half::Top, AcaciaStairs::Shape::InnerRight).ID: return 6884; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XM, AcaciaStairs::Half::Top, AcaciaStairs::Shape::OuterLeft).ID: return 6886; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XM, AcaciaStairs::Half::Top, AcaciaStairs::Shape::OuterRight).ID: return 6888; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XM, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::Straight).ID: return 6890; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XM, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::InnerLeft).ID: return 6892; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XM, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::InnerRight).ID: return 6894; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XM, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::OuterLeft).ID: return 6896; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XM, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::OuterRight).ID: return 6898; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XP, AcaciaStairs::Half::Top, AcaciaStairs::Shape::Straight).ID: return 6900; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XP, AcaciaStairs::Half::Top, AcaciaStairs::Shape::InnerLeft).ID: return 6902; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XP, AcaciaStairs::Half::Top, AcaciaStairs::Shape::InnerRight).ID: return 6904; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XP, AcaciaStairs::Half::Top, AcaciaStairs::Shape::OuterLeft).ID: return 6906; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XP, AcaciaStairs::Half::Top, AcaciaStairs::Shape::OuterRight).ID: return 6908; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XP, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::Straight).ID: return 6910; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XP, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::InnerLeft).ID: return 6912; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XP, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::InnerRight).ID: return 6914; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XP, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::OuterLeft).ID: return 6916; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XP, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::OuterRight).ID: return 6918; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZM, AcaciaTrapdoor::Half::Top, true, true).ID: return 4354; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZM, AcaciaTrapdoor::Half::Top, true, false).ID: return 4356; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZM, AcaciaTrapdoor::Half::Top, false, true).ID: return 4358; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZM, AcaciaTrapdoor::Half::Top, false, false).ID: return 4360; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZM, AcaciaTrapdoor::Half::Bottom, true, true).ID: return 4362; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZM, AcaciaTrapdoor::Half::Bottom, true, false).ID: return 4364; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZM, AcaciaTrapdoor::Half::Bottom, false, true).ID: return 4366; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZM, AcaciaTrapdoor::Half::Bottom, false, false).ID: return 4368; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZP, AcaciaTrapdoor::Half::Top, true, true).ID: return 4370; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZP, AcaciaTrapdoor::Half::Top, true, false).ID: return 4372; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZP, AcaciaTrapdoor::Half::Top, false, true).ID: return 4374; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZP, AcaciaTrapdoor::Half::Top, false, false).ID: return 4376; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZP, AcaciaTrapdoor::Half::Bottom, true, true).ID: return 4378; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZP, AcaciaTrapdoor::Half::Bottom, true, false).ID: return 4380; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZP, AcaciaTrapdoor::Half::Bottom, false, true).ID: return 4382; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZP, AcaciaTrapdoor::Half::Bottom, false, false).ID: return 4384; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XM, AcaciaTrapdoor::Half::Top, true, true).ID: return 4386; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XM, AcaciaTrapdoor::Half::Top, true, false).ID: return 4388; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XM, AcaciaTrapdoor::Half::Top, false, true).ID: return 4390; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XM, AcaciaTrapdoor::Half::Top, false, false).ID: return 4392; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XM, AcaciaTrapdoor::Half::Bottom, true, true).ID: return 4394; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XM, AcaciaTrapdoor::Half::Bottom, true, false).ID: return 4396; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XM, AcaciaTrapdoor::Half::Bottom, false, true).ID: return 4398; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XM, AcaciaTrapdoor::Half::Bottom, false, false).ID: return 4400; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XP, AcaciaTrapdoor::Half::Top, true, true).ID: return 4402; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XP, AcaciaTrapdoor::Half::Top, true, false).ID: return 4404; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XP, AcaciaTrapdoor::Half::Top, false, true).ID: return 4406; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XP, AcaciaTrapdoor::Half::Top, false, false).ID: return 4408; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XP, AcaciaTrapdoor::Half::Bottom, true, true).ID: return 4410; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XP, AcaciaTrapdoor::Half::Bottom, true, false).ID: return 4412; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XP, AcaciaTrapdoor::Half::Bottom, false, true).ID: return 4414; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XP, AcaciaTrapdoor::Half::Bottom, false, false).ID: return 4416; case AcaciaWallSign::AcaciaWallSign(eBlockFace::BLOCK_FACE_ZM).ID: return 3758; case AcaciaWallSign::AcaciaWallSign(eBlockFace::BLOCK_FACE_ZP).ID: return 3760; case AcaciaWallSign::AcaciaWallSign(eBlockFace::BLOCK_FACE_XM).ID: return 3762; case AcaciaWallSign::AcaciaWallSign(eBlockFace::BLOCK_FACE_XP).ID: return 3764; case AcaciaWood::AcaciaWood(AcaciaWood::Axis::X).ID: return 120; case AcaciaWood::AcaciaWood(AcaciaWood::Axis::Y).ID: return 121; case AcaciaWood::AcaciaWood(AcaciaWood::Axis::Z).ID: return 122; case ActivatorRail::ActivatorRail(true, ActivatorRail::Shape::NorthSouth).ID: return 6287; case ActivatorRail::ActivatorRail(true, ActivatorRail::Shape::EastWest).ID: return 6288; case ActivatorRail::ActivatorRail(true, ActivatorRail::Shape::AscendingEast).ID: return 6289; case ActivatorRail::ActivatorRail(true, ActivatorRail::Shape::AscendingWest).ID: return 6290; case ActivatorRail::ActivatorRail(true, ActivatorRail::Shape::AscendingNorth).ID: return 6291; case ActivatorRail::ActivatorRail(true, ActivatorRail::Shape::AscendingSouth).ID: return 6292; case ActivatorRail::ActivatorRail(false, ActivatorRail::Shape::NorthSouth).ID: return 6293; case ActivatorRail::ActivatorRail(false, ActivatorRail::Shape::EastWest).ID: return 6294; case ActivatorRail::ActivatorRail(false, ActivatorRail::Shape::AscendingEast).ID: return 6295; case ActivatorRail::ActivatorRail(false, ActivatorRail::Shape::AscendingWest).ID: return 6296; case ActivatorRail::ActivatorRail(false, ActivatorRail::Shape::AscendingNorth).ID: return 6297; case ActivatorRail::ActivatorRail(false, ActivatorRail::Shape::AscendingSouth).ID: return 6298; case Air::Air().ID: return -0; case Allium::Allium().ID: return 1414; case Andesite::Andesite().ID: return 6; case AndesiteSlab::AndesiteSlab(AndesiteSlab::Type::Top).ID: return 10308; case AndesiteSlab::AndesiteSlab(AndesiteSlab::Type::Bottom).ID: return 10310; case AndesiteSlab::AndesiteSlab(AndesiteSlab::Type::Double).ID: return 10312; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_ZM, AndesiteStairs::Half::Top, AndesiteStairs::Shape::Straight).ID: return 9934; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_ZM, AndesiteStairs::Half::Top, AndesiteStairs::Shape::InnerLeft).ID: return 9936; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_ZM, AndesiteStairs::Half::Top, AndesiteStairs::Shape::InnerRight).ID: return 9938; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_ZM, AndesiteStairs::Half::Top, AndesiteStairs::Shape::OuterLeft).ID: return 9940; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_ZM, AndesiteStairs::Half::Top, AndesiteStairs::Shape::OuterRight).ID: return 9942; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_ZM, AndesiteStairs::Half::Bottom, AndesiteStairs::Shape::Straight).ID: return 9944; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_ZM, AndesiteStairs::Half::Bottom, AndesiteStairs::Shape::InnerLeft).ID: return 9946; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_ZM, AndesiteStairs::Half::Bottom, AndesiteStairs::Shape::InnerRight).ID: return 9948; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_ZM, AndesiteStairs::Half::Bottom, AndesiteStairs::Shape::OuterLeft).ID: return 9950; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_ZM, AndesiteStairs::Half::Bottom, AndesiteStairs::Shape::OuterRight).ID: return 9952; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_ZP, AndesiteStairs::Half::Top, AndesiteStairs::Shape::Straight).ID: return 9954; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_ZP, AndesiteStairs::Half::Top, AndesiteStairs::Shape::InnerLeft).ID: return 9956; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_ZP, AndesiteStairs::Half::Top, AndesiteStairs::Shape::InnerRight).ID: return 9958; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_ZP, AndesiteStairs::Half::Top, AndesiteStairs::Shape::OuterLeft).ID: return 9960; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_ZP, AndesiteStairs::Half::Top, AndesiteStairs::Shape::OuterRight).ID: return 9962; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_ZP, AndesiteStairs::Half::Bottom, AndesiteStairs::Shape::Straight).ID: return 9964; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_ZP, AndesiteStairs::Half::Bottom, AndesiteStairs::Shape::InnerLeft).ID: return 9966; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_ZP, AndesiteStairs::Half::Bottom, AndesiteStairs::Shape::InnerRight).ID: return 9968; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_ZP, AndesiteStairs::Half::Bottom, AndesiteStairs::Shape::OuterLeft).ID: return 9970; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_ZP, AndesiteStairs::Half::Bottom, AndesiteStairs::Shape::OuterRight).ID: return 9972; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_XM, AndesiteStairs::Half::Top, AndesiteStairs::Shape::Straight).ID: return 9974; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_XM, AndesiteStairs::Half::Top, AndesiteStairs::Shape::InnerLeft).ID: return 9976; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_XM, AndesiteStairs::Half::Top, AndesiteStairs::Shape::InnerRight).ID: return 9978; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_XM, AndesiteStairs::Half::Top, AndesiteStairs::Shape::OuterLeft).ID: return 9980; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_XM, AndesiteStairs::Half::Top, AndesiteStairs::Shape::OuterRight).ID: return 9982; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_XM, AndesiteStairs::Half::Bottom, AndesiteStairs::Shape::Straight).ID: return 9984; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_XM, AndesiteStairs::Half::Bottom, AndesiteStairs::Shape::InnerLeft).ID: return 9986; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_XM, AndesiteStairs::Half::Bottom, AndesiteStairs::Shape::InnerRight).ID: return 9988; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_XM, AndesiteStairs::Half::Bottom, AndesiteStairs::Shape::OuterLeft).ID: return 9990; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_XM, AndesiteStairs::Half::Bottom, AndesiteStairs::Shape::OuterRight).ID: return 9992; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_XP, AndesiteStairs::Half::Top, AndesiteStairs::Shape::Straight).ID: return 9994; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_XP, AndesiteStairs::Half::Top, AndesiteStairs::Shape::InnerLeft).ID: return 9996; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_XP, AndesiteStairs::Half::Top, AndesiteStairs::Shape::InnerRight).ID: return 9998; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_XP, AndesiteStairs::Half::Top, AndesiteStairs::Shape::OuterLeft).ID: return 10000; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_XP, AndesiteStairs::Half::Top, AndesiteStairs::Shape::OuterRight).ID: return 10002; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_XP, AndesiteStairs::Half::Bottom, AndesiteStairs::Shape::Straight).ID: return 10004; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_XP, AndesiteStairs::Half::Bottom, AndesiteStairs::Shape::InnerLeft).ID: return 10006; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_XP, AndesiteStairs::Half::Bottom, AndesiteStairs::Shape::InnerRight).ID: return 10008; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_XP, AndesiteStairs::Half::Bottom, AndesiteStairs::Shape::OuterLeft).ID: return 10010; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_XP, AndesiteStairs::Half::Bottom, AndesiteStairs::Shape::OuterRight).ID: return 10012; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::Low, AndesiteWall::South::Low, true, AndesiteWall::West::Low).ID: return 10781; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::Low, AndesiteWall::South::Low, true, AndesiteWall::West::None).ID: return 10782; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::Low, AndesiteWall::South::Low, false, AndesiteWall::West::Low).ID: return 10785; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::Low, AndesiteWall::South::Low, false, AndesiteWall::West::None).ID: return 10786; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::Low, AndesiteWall::South::None, true, AndesiteWall::West::Low).ID: return 10789; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::Low, AndesiteWall::South::None, true, AndesiteWall::West::None).ID: return 10790; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::Low, AndesiteWall::South::None, false, AndesiteWall::West::Low).ID: return 10793; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::Low, AndesiteWall::South::None, false, AndesiteWall::West::None).ID: return 10794; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::None, AndesiteWall::South::Low, true, AndesiteWall::West::Low).ID: return 10797; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::None, AndesiteWall::South::Low, true, AndesiteWall::West::None).ID: return 10798; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::None, AndesiteWall::South::Low, false, AndesiteWall::West::Low).ID: return 10801; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::None, AndesiteWall::South::Low, false, AndesiteWall::West::None).ID: return 10802; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::None, AndesiteWall::South::None, true, AndesiteWall::West::Low).ID: return 10805; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::None, AndesiteWall::South::None, true, AndesiteWall::West::None).ID: return 10806; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::None, AndesiteWall::South::None, false, AndesiteWall::West::Low).ID: return 10809; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::None, AndesiteWall::South::None, false, AndesiteWall::West::None).ID: return 10810; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::Low, AndesiteWall::South::Low, true, AndesiteWall::West::Low).ID: return 10813; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::Low, AndesiteWall::South::Low, true, AndesiteWall::West::None).ID: return 10814; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::Low, AndesiteWall::South::Low, false, AndesiteWall::West::Low).ID: return 10817; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::Low, AndesiteWall::South::Low, false, AndesiteWall::West::None).ID: return 10818; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::Low, AndesiteWall::South::None, true, AndesiteWall::West::Low).ID: return 10821; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::Low, AndesiteWall::South::None, true, AndesiteWall::West::None).ID: return 10822; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::Low, AndesiteWall::South::None, false, AndesiteWall::West::Low).ID: return 10825; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::Low, AndesiteWall::South::None, false, AndesiteWall::West::None).ID: return 10826; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::None, AndesiteWall::South::Low, true, AndesiteWall::West::Low).ID: return 10829; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::None, AndesiteWall::South::Low, true, AndesiteWall::West::None).ID: return 10830; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::None, AndesiteWall::South::Low, false, AndesiteWall::West::Low).ID: return 10833; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::None, AndesiteWall::South::Low, false, AndesiteWall::West::None).ID: return 10834; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::None, AndesiteWall::South::None, true, AndesiteWall::West::Low).ID: return 10837; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::None, AndesiteWall::South::None, true, AndesiteWall::West::None).ID: return 10838; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::None, AndesiteWall::South::None, false, AndesiteWall::West::Low).ID: return 10841; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::None, AndesiteWall::South::None, false, AndesiteWall::West::None).ID: return 10842; case Anvil::Anvil(eBlockFace::BLOCK_FACE_ZM).ID: return 6074; case Anvil::Anvil(eBlockFace::BLOCK_FACE_ZP).ID: return 6075; case Anvil::Anvil(eBlockFace::BLOCK_FACE_XM).ID: return 6076; case Anvil::Anvil(eBlockFace::BLOCK_FACE_XP).ID: return 6077; case AttachedMelonStem::AttachedMelonStem(eBlockFace::BLOCK_FACE_ZM).ID: return 4752; case AttachedMelonStem::AttachedMelonStem(eBlockFace::BLOCK_FACE_ZP).ID: return 4753; case AttachedMelonStem::AttachedMelonStem(eBlockFace::BLOCK_FACE_XM).ID: return 4754; case AttachedMelonStem::AttachedMelonStem(eBlockFace::BLOCK_FACE_XP).ID: return 4755; case AttachedPumpkinStem::AttachedPumpkinStem(eBlockFace::BLOCK_FACE_ZM).ID: return 4748; case AttachedPumpkinStem::AttachedPumpkinStem(eBlockFace::BLOCK_FACE_ZP).ID: return 4749; case AttachedPumpkinStem::AttachedPumpkinStem(eBlockFace::BLOCK_FACE_XM).ID: return 4750; case AttachedPumpkinStem::AttachedPumpkinStem(eBlockFace::BLOCK_FACE_XP).ID: return 4751; case AzureBluet::AzureBluet().ID: return 1415; case Bamboo::Bamboo(0, Bamboo::Leaves::None, 0).ID: return 9116; case Bamboo::Bamboo(0, Bamboo::Leaves::None, 1).ID: return 9117; case Bamboo::Bamboo(0, Bamboo::Leaves::Small, 0).ID: return 9118; case Bamboo::Bamboo(0, Bamboo::Leaves::Small, 1).ID: return 9119; case Bamboo::Bamboo(0, Bamboo::Leaves::Large, 0).ID: return 9120; case Bamboo::Bamboo(0, Bamboo::Leaves::Large, 1).ID: return 9121; case Bamboo::Bamboo(1, Bamboo::Leaves::None, 0).ID: return 9122; case Bamboo::Bamboo(1, Bamboo::Leaves::None, 1).ID: return 9123; case Bamboo::Bamboo(1, Bamboo::Leaves::Small, 0).ID: return 9124; case Bamboo::Bamboo(1, Bamboo::Leaves::Small, 1).ID: return 9125; case Bamboo::Bamboo(1, Bamboo::Leaves::Large, 0).ID: return 9126; case Bamboo::Bamboo(1, Bamboo::Leaves::Large, 1).ID: return 9127; case BambooSapling::BambooSapling().ID: return 9115; case Barrel::Barrel(eBlockFace::BLOCK_FACE_ZM, true).ID: return 11135; case Barrel::Barrel(eBlockFace::BLOCK_FACE_ZM, false).ID: return 11136; case Barrel::Barrel(eBlockFace::BLOCK_FACE_XP, true).ID: return 11137; case Barrel::Barrel(eBlockFace::BLOCK_FACE_XP, false).ID: return 11138; case Barrel::Barrel(eBlockFace::BLOCK_FACE_ZP, true).ID: return 11139; case Barrel::Barrel(eBlockFace::BLOCK_FACE_ZP, false).ID: return 11140; case Barrel::Barrel(eBlockFace::BLOCK_FACE_XM, true).ID: return 11141; case Barrel::Barrel(eBlockFace::BLOCK_FACE_XM, false).ID: return 11142; case Barrel::Barrel(eBlockFace::BLOCK_FACE_YP, true).ID: return 11143; case Barrel::Barrel(eBlockFace::BLOCK_FACE_YP, false).ID: return 11144; case Barrel::Barrel(eBlockFace::BLOCK_FACE_YM, true).ID: return 11145; case Barrel::Barrel(eBlockFace::BLOCK_FACE_YM, false).ID: return 11146; case Barrier::Barrier().ID: return 7000; case Beacon::Beacon().ID: return 5640; case Bedrock::Bedrock().ID: return 33; case Beetroots::Beetroots(0).ID: return 8683; case Beetroots::Beetroots(1).ID: return 8684; case Beetroots::Beetroots(2).ID: return 8685; case Beetroots::Beetroots(3).ID: return 8686; case Bell::Bell(Bell::Attachment::Floor, eBlockFace::BLOCK_FACE_ZM, false).ID: return 11198; case Bell::Bell(Bell::Attachment::Floor, eBlockFace::BLOCK_FACE_ZP, false).ID: return 11199; case Bell::Bell(Bell::Attachment::Floor, eBlockFace::BLOCK_FACE_XM, false).ID: return 11200; case Bell::Bell(Bell::Attachment::Floor, eBlockFace::BLOCK_FACE_XP, false).ID: return 11201; case Bell::Bell(Bell::Attachment::Ceiling, eBlockFace::BLOCK_FACE_ZM, false).ID: return 11202; case Bell::Bell(Bell::Attachment::Ceiling, eBlockFace::BLOCK_FACE_ZP, false).ID: return 11203; case Bell::Bell(Bell::Attachment::Ceiling, eBlockFace::BLOCK_FACE_XM, false).ID: return 11204; case Bell::Bell(Bell::Attachment::Ceiling, eBlockFace::BLOCK_FACE_XP, false).ID: return 11205; case Bell::Bell(Bell::Attachment::SingleWall, eBlockFace::BLOCK_FACE_ZM, false).ID: return 11206; case Bell::Bell(Bell::Attachment::SingleWall, eBlockFace::BLOCK_FACE_ZP, false).ID: return 11207; case Bell::Bell(Bell::Attachment::SingleWall, eBlockFace::BLOCK_FACE_XM, false).ID: return 11208; case Bell::Bell(Bell::Attachment::SingleWall, eBlockFace::BLOCK_FACE_XP, false).ID: return 11209; case Bell::Bell(Bell::Attachment::DoubleWall, eBlockFace::BLOCK_FACE_ZM, false).ID: return 11210; case Bell::Bell(Bell::Attachment::DoubleWall, eBlockFace::BLOCK_FACE_ZP, false).ID: return 11211; case Bell::Bell(Bell::Attachment::DoubleWall, eBlockFace::BLOCK_FACE_XM, false).ID: return 11212; case Bell::Bell(Bell::Attachment::DoubleWall, eBlockFace::BLOCK_FACE_XP, false).ID: return 11213; case BirchButton::BirchButton(BirchButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5858; case BirchButton::BirchButton(BirchButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5859; case BirchButton::BirchButton(BirchButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5860; case BirchButton::BirchButton(BirchButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5861; case BirchButton::BirchButton(BirchButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, true).ID: return 5862; case BirchButton::BirchButton(BirchButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, false).ID: return 5863; case BirchButton::BirchButton(BirchButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, true).ID: return 5864; case BirchButton::BirchButton(BirchButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, false).ID: return 5865; case BirchButton::BirchButton(BirchButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5866; case BirchButton::BirchButton(BirchButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5867; case BirchButton::BirchButton(BirchButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5868; case BirchButton::BirchButton(BirchButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5869; case BirchButton::BirchButton(BirchButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, true).ID: return 5870; case BirchButton::BirchButton(BirchButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, false).ID: return 5871; case BirchButton::BirchButton(BirchButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, true).ID: return 5872; case BirchButton::BirchButton(BirchButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, false).ID: return 5873; case BirchButton::BirchButton(BirchButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5874; case BirchButton::BirchButton(BirchButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5875; case BirchButton::BirchButton(BirchButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5876; case BirchButton::BirchButton(BirchButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5877; case BirchButton::BirchButton(BirchButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, true).ID: return 5878; case BirchButton::BirchButton(BirchButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, false).ID: return 5879; case BirchButton::BirchButton(BirchButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, true).ID: return 5880; case BirchButton::BirchButton(BirchButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, false).ID: return 5881; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, true, true).ID: return 8266; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, true, false).ID: return 8267; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, false, true).ID: return 8268; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, false, false).ID: return 8269; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, true, true).ID: return 8270; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, true, false).ID: return 8271; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, false, true).ID: return 8272; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, false, false).ID: return 8273; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, true, true).ID: return 8274; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, true, false).ID: return 8275; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, false, true).ID: return 8276; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, false, false).ID: return 8277; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, true, true).ID: return 8278; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, true, false).ID: return 8279; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, false, true).ID: return 8280; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, false, false).ID: return 8281; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, true, true).ID: return 8282; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, true, false).ID: return 8283; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, false, true).ID: return 8284; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, false, false).ID: return 8285; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, true, true).ID: return 8286; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, true, false).ID: return 8287; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, false, true).ID: return 8288; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, false, false).ID: return 8289; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, true, true).ID: return 8290; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, true, false).ID: return 8291; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, false, true).ID: return 8292; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, false, false).ID: return 8293; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, true, true).ID: return 8294; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, true, false).ID: return 8295; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, false, true).ID: return 8296; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, false, false).ID: return 8297; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, true, true).ID: return 8298; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, true, false).ID: return 8299; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, false, true).ID: return 8300; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, false, false).ID: return 8301; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, true, true).ID: return 8302; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, true, false).ID: return 8303; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, false, true).ID: return 8304; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, false, false).ID: return 8305; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, true, true).ID: return 8306; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, true, false).ID: return 8307; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, false, true).ID: return 8308; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, false, false).ID: return 8309; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, true, true).ID: return 8310; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, true, false).ID: return 8311; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, false, true).ID: return 8312; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, false, false).ID: return 8313; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, true, true).ID: return 8314; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, true, false).ID: return 8315; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, false, true).ID: return 8316; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, false, false).ID: return 8317; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, true, true).ID: return 8318; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, true, false).ID: return 8319; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, false, true).ID: return 8320; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, false, false).ID: return 8321; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, true, true).ID: return 8322; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, true, false).ID: return 8323; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, false, true).ID: return 8324; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, false, false).ID: return 8325; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, true, true).ID: return 8326; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, true, false).ID: return 8327; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, false, true).ID: return 8328; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, false, false).ID: return 8329; case BirchFence::BirchFence(true, true, true, true).ID: return 8076; case BirchFence::BirchFence(true, true, true, false).ID: return 8077; case BirchFence::BirchFence(true, true, false, true).ID: return 8080; case BirchFence::BirchFence(true, true, false, false).ID: return 8081; case BirchFence::BirchFence(true, false, true, true).ID: return 8084; case BirchFence::BirchFence(true, false, true, false).ID: return 8085; case BirchFence::BirchFence(true, false, false, true).ID: return 8088; case BirchFence::BirchFence(true, false, false, false).ID: return 8089; case BirchFence::BirchFence(false, true, true, true).ID: return 8092; case BirchFence::BirchFence(false, true, true, false).ID: return 8093; case BirchFence::BirchFence(false, true, false, true).ID: return 8096; case BirchFence::BirchFence(false, true, false, false).ID: return 8097; case BirchFence::BirchFence(false, false, true, true).ID: return 8100; case BirchFence::BirchFence(false, false, true, false).ID: return 8101; case BirchFence::BirchFence(false, false, false, true).ID: return 8104; case BirchFence::BirchFence(false, false, false, false).ID: return 8105; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZM, true, true, true).ID: return 7914; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZM, true, true, false).ID: return 7915; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZM, true, false, true).ID: return 7916; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZM, true, false, false).ID: return 7917; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, true).ID: return 7918; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, false).ID: return 7919; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, true).ID: return 7920; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, false).ID: return 7921; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZP, true, true, true).ID: return 7922; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZP, true, true, false).ID: return 7923; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZP, true, false, true).ID: return 7924; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZP, true, false, false).ID: return 7925; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, true).ID: return 7926; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, false).ID: return 7927; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, true).ID: return 7928; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, false).ID: return 7929; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XM, true, true, true).ID: return 7930; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XM, true, true, false).ID: return 7931; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XM, true, false, true).ID: return 7932; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XM, true, false, false).ID: return 7933; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, true).ID: return 7934; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, false).ID: return 7935; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, true).ID: return 7936; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, false).ID: return 7937; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XP, true, true, true).ID: return 7938; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XP, true, true, false).ID: return 7939; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XP, true, false, true).ID: return 7940; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XP, true, false, false).ID: return 7941; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, true).ID: return 7942; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, false).ID: return 7943; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, true).ID: return 7944; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, false).ID: return 7945; case BirchLeaves::BirchLeaves(1, true).ID: return 172; case BirchLeaves::BirchLeaves(1, false).ID: return 173; case BirchLeaves::BirchLeaves(2, true).ID: return 174; case BirchLeaves::BirchLeaves(2, false).ID: return 175; case BirchLeaves::BirchLeaves(3, true).ID: return 176; case BirchLeaves::BirchLeaves(3, false).ID: return 177; case BirchLeaves::BirchLeaves(4, true).ID: return 178; case BirchLeaves::BirchLeaves(4, false).ID: return 179; case BirchLeaves::BirchLeaves(5, true).ID: return 180; case BirchLeaves::BirchLeaves(5, false).ID: return 181; case BirchLeaves::BirchLeaves(6, true).ID: return 182; case BirchLeaves::BirchLeaves(6, false).ID: return 183; case BirchLeaves::BirchLeaves(7, true).ID: return 184; case BirchLeaves::BirchLeaves(7, false).ID: return 185; case BirchLog::BirchLog(BirchLog::Axis::X).ID: return 78; case BirchLog::BirchLog(BirchLog::Axis::Y).ID: return 79; case BirchLog::BirchLog(BirchLog::Axis::Z).ID: return 80; case BirchPlanks::BirchPlanks().ID: return 17; case BirchPressurePlate::BirchPressurePlate(true).ID: return 3875; case BirchPressurePlate::BirchPressurePlate(false).ID: return 3876; case BirchSapling::BirchSapling(0).ID: return 25; case BirchSapling::BirchSapling(1).ID: return 26; case BirchSign::BirchSign(0).ID: return 3444; case BirchSign::BirchSign(1).ID: return 3446; case BirchSign::BirchSign(2).ID: return 3448; case BirchSign::BirchSign(3).ID: return 3450; case BirchSign::BirchSign(4).ID: return 3452; case BirchSign::BirchSign(5).ID: return 3454; case BirchSign::BirchSign(6).ID: return 3456; case BirchSign::BirchSign(7).ID: return 3458; case BirchSign::BirchSign(8).ID: return 3460; case BirchSign::BirchSign(9).ID: return 3462; case BirchSign::BirchSign(10).ID: return 3464; case BirchSign::BirchSign(11).ID: return 3466; case BirchSign::BirchSign(12).ID: return 3468; case BirchSign::BirchSign(13).ID: return 3470; case BirchSign::BirchSign(14).ID: return 3472; case BirchSign::BirchSign(15).ID: return 3474; case BirchSlab::BirchSlab(BirchSlab::Type::Top).ID: return 7777; case BirchSlab::BirchSlab(BirchSlab::Type::Bottom).ID: return 7779; case BirchSlab::BirchSlab(BirchSlab::Type::Double).ID: return 7781; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZM, BirchStairs::Half::Top, BirchStairs::Shape::Straight).ID: return 5469; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZM, BirchStairs::Half::Top, BirchStairs::Shape::InnerLeft).ID: return 5471; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZM, BirchStairs::Half::Top, BirchStairs::Shape::InnerRight).ID: return 5473; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZM, BirchStairs::Half::Top, BirchStairs::Shape::OuterLeft).ID: return 5475; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZM, BirchStairs::Half::Top, BirchStairs::Shape::OuterRight).ID: return 5477; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZM, BirchStairs::Half::Bottom, BirchStairs::Shape::Straight).ID: return 5479; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZM, BirchStairs::Half::Bottom, BirchStairs::Shape::InnerLeft).ID: return 5481; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZM, BirchStairs::Half::Bottom, BirchStairs::Shape::InnerRight).ID: return 5483; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZM, BirchStairs::Half::Bottom, BirchStairs::Shape::OuterLeft).ID: return 5485; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZM, BirchStairs::Half::Bottom, BirchStairs::Shape::OuterRight).ID: return 5487; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZP, BirchStairs::Half::Top, BirchStairs::Shape::Straight).ID: return 5489; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZP, BirchStairs::Half::Top, BirchStairs::Shape::InnerLeft).ID: return 5491; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZP, BirchStairs::Half::Top, BirchStairs::Shape::InnerRight).ID: return 5493; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZP, BirchStairs::Half::Top, BirchStairs::Shape::OuterLeft).ID: return 5495; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZP, BirchStairs::Half::Top, BirchStairs::Shape::OuterRight).ID: return 5497; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZP, BirchStairs::Half::Bottom, BirchStairs::Shape::Straight).ID: return 5499; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZP, BirchStairs::Half::Bottom, BirchStairs::Shape::InnerLeft).ID: return 5501; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZP, BirchStairs::Half::Bottom, BirchStairs::Shape::InnerRight).ID: return 5503; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZP, BirchStairs::Half::Bottom, BirchStairs::Shape::OuterLeft).ID: return 5505; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZP, BirchStairs::Half::Bottom, BirchStairs::Shape::OuterRight).ID: return 5507; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XM, BirchStairs::Half::Top, BirchStairs::Shape::Straight).ID: return 5509; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XM, BirchStairs::Half::Top, BirchStairs::Shape::InnerLeft).ID: return 5511; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XM, BirchStairs::Half::Top, BirchStairs::Shape::InnerRight).ID: return 5513; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XM, BirchStairs::Half::Top, BirchStairs::Shape::OuterLeft).ID: return 5515; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XM, BirchStairs::Half::Top, BirchStairs::Shape::OuterRight).ID: return 5517; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XM, BirchStairs::Half::Bottom, BirchStairs::Shape::Straight).ID: return 5519; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XM, BirchStairs::Half::Bottom, BirchStairs::Shape::InnerLeft).ID: return 5521; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XM, BirchStairs::Half::Bottom, BirchStairs::Shape::InnerRight).ID: return 5523; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XM, BirchStairs::Half::Bottom, BirchStairs::Shape::OuterLeft).ID: return 5525; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XM, BirchStairs::Half::Bottom, BirchStairs::Shape::OuterRight).ID: return 5527; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XP, BirchStairs::Half::Top, BirchStairs::Shape::Straight).ID: return 5529; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XP, BirchStairs::Half::Top, BirchStairs::Shape::InnerLeft).ID: return 5531; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XP, BirchStairs::Half::Top, BirchStairs::Shape::InnerRight).ID: return 5533; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XP, BirchStairs::Half::Top, BirchStairs::Shape::OuterLeft).ID: return 5535; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XP, BirchStairs::Half::Top, BirchStairs::Shape::OuterRight).ID: return 5537; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XP, BirchStairs::Half::Bottom, BirchStairs::Shape::Straight).ID: return 5539; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XP, BirchStairs::Half::Bottom, BirchStairs::Shape::InnerLeft).ID: return 5541; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XP, BirchStairs::Half::Bottom, BirchStairs::Shape::InnerRight).ID: return 5543; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XP, BirchStairs::Half::Bottom, BirchStairs::Shape::OuterLeft).ID: return 5545; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XP, BirchStairs::Half::Bottom, BirchStairs::Shape::OuterRight).ID: return 5547; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZM, BirchTrapdoor::Half::Top, true, true).ID: return 4226; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZM, BirchTrapdoor::Half::Top, true, false).ID: return 4228; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZM, BirchTrapdoor::Half::Top, false, true).ID: return 4230; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZM, BirchTrapdoor::Half::Top, false, false).ID: return 4232; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZM, BirchTrapdoor::Half::Bottom, true, true).ID: return 4234; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZM, BirchTrapdoor::Half::Bottom, true, false).ID: return 4236; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZM, BirchTrapdoor::Half::Bottom, false, true).ID: return 4238; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZM, BirchTrapdoor::Half::Bottom, false, false).ID: return 4240; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZP, BirchTrapdoor::Half::Top, true, true).ID: return 4242; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZP, BirchTrapdoor::Half::Top, true, false).ID: return 4244; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZP, BirchTrapdoor::Half::Top, false, true).ID: return 4246; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZP, BirchTrapdoor::Half::Top, false, false).ID: return 4248; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZP, BirchTrapdoor::Half::Bottom, true, true).ID: return 4250; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZP, BirchTrapdoor::Half::Bottom, true, false).ID: return 4252; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZP, BirchTrapdoor::Half::Bottom, false, true).ID: return 4254; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZP, BirchTrapdoor::Half::Bottom, false, false).ID: return 4256; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XM, BirchTrapdoor::Half::Top, true, true).ID: return 4258; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XM, BirchTrapdoor::Half::Top, true, false).ID: return 4260; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XM, BirchTrapdoor::Half::Top, false, true).ID: return 4262; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XM, BirchTrapdoor::Half::Top, false, false).ID: return 4264; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XM, BirchTrapdoor::Half::Bottom, true, true).ID: return 4266; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XM, BirchTrapdoor::Half::Bottom, true, false).ID: return 4268; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XM, BirchTrapdoor::Half::Bottom, false, true).ID: return 4270; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XM, BirchTrapdoor::Half::Bottom, false, false).ID: return 4272; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XP, BirchTrapdoor::Half::Top, true, true).ID: return 4274; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XP, BirchTrapdoor::Half::Top, true, false).ID: return 4276; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XP, BirchTrapdoor::Half::Top, false, true).ID: return 4278; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XP, BirchTrapdoor::Half::Top, false, false).ID: return 4280; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XP, BirchTrapdoor::Half::Bottom, true, true).ID: return 4282; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XP, BirchTrapdoor::Half::Bottom, true, false).ID: return 4284; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XP, BirchTrapdoor::Half::Bottom, false, true).ID: return 4286; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XP, BirchTrapdoor::Half::Bottom, false, false).ID: return 4288; case BirchWallSign::BirchWallSign(eBlockFace::BLOCK_FACE_ZM).ID: return 3750; case BirchWallSign::BirchWallSign(eBlockFace::BLOCK_FACE_ZP).ID: return 3752; case BirchWallSign::BirchWallSign(eBlockFace::BLOCK_FACE_XM).ID: return 3754; case BirchWallSign::BirchWallSign(eBlockFace::BLOCK_FACE_XP).ID: return 3756; case BirchWood::BirchWood(BirchWood::Axis::X).ID: return 114; case BirchWood::BirchWood(BirchWood::Axis::Y).ID: return 115; case BirchWood::BirchWood(BirchWood::Axis::Z).ID: return 116; case BlackBanner::BlackBanner(0).ID: return 7601; case BlackBanner::BlackBanner(1).ID: return 7602; case BlackBanner::BlackBanner(2).ID: return 7603; case BlackBanner::BlackBanner(3).ID: return 7604; case BlackBanner::BlackBanner(4).ID: return 7605; case BlackBanner::BlackBanner(5).ID: return 7606; case BlackBanner::BlackBanner(6).ID: return 7607; case BlackBanner::BlackBanner(7).ID: return 7608; case BlackBanner::BlackBanner(8).ID: return 7609; case BlackBanner::BlackBanner(9).ID: return 7610; case BlackBanner::BlackBanner(10).ID: return 7611; case BlackBanner::BlackBanner(11).ID: return 7612; case BlackBanner::BlackBanner(12).ID: return 7613; case BlackBanner::BlackBanner(13).ID: return 7614; case BlackBanner::BlackBanner(14).ID: return 7615; case BlackBanner::BlackBanner(15).ID: return 7616; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_ZM, true, BlackBed::Part::Head).ID: return 1288; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_ZM, true, BlackBed::Part::Foot).ID: return 1289; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_ZM, false, BlackBed::Part::Head).ID: return 1290; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_ZM, false, BlackBed::Part::Foot).ID: return 1291; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_ZP, true, BlackBed::Part::Head).ID: return 1292; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_ZP, true, BlackBed::Part::Foot).ID: return 1293; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_ZP, false, BlackBed::Part::Head).ID: return 1294; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_ZP, false, BlackBed::Part::Foot).ID: return 1295; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_XM, true, BlackBed::Part::Head).ID: return 1296; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_XM, true, BlackBed::Part::Foot).ID: return 1297; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_XM, false, BlackBed::Part::Head).ID: return 1298; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_XM, false, BlackBed::Part::Foot).ID: return 1299; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_XP, true, BlackBed::Part::Head).ID: return 1300; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_XP, true, BlackBed::Part::Foot).ID: return 1301; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_XP, false, BlackBed::Part::Head).ID: return 1302; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_XP, false, BlackBed::Part::Foot).ID: return 1303; case BlackCarpet::BlackCarpet().ID: return 7345; case BlackConcrete::BlackConcrete().ID: return 8917; case BlackConcretePowder::BlackConcretePowder().ID: return 8933; case BlackGlazedTerracotta::BlackGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 8898; case BlackGlazedTerracotta::BlackGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 8899; case BlackGlazedTerracotta::BlackGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 8900; case BlackGlazedTerracotta::BlackGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 8901; case BlackShulkerBox::BlackShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 8832; case BlackShulkerBox::BlackShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 8833; case BlackShulkerBox::BlackShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 8834; case BlackShulkerBox::BlackShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 8835; case BlackShulkerBox::BlackShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 8836; case BlackShulkerBox::BlackShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 8837; case BlackStainedGlass::BlackStainedGlass().ID: return 4096; case BlackStainedGlassPane::BlackStainedGlassPane(true, true, true, true).ID: return 6809; case BlackStainedGlassPane::BlackStainedGlassPane(true, true, true, false).ID: return 6810; case BlackStainedGlassPane::BlackStainedGlassPane(true, true, false, true).ID: return 6813; case BlackStainedGlassPane::BlackStainedGlassPane(true, true, false, false).ID: return 6814; case BlackStainedGlassPane::BlackStainedGlassPane(true, false, true, true).ID: return 6817; case BlackStainedGlassPane::BlackStainedGlassPane(true, false, true, false).ID: return 6818; case BlackStainedGlassPane::BlackStainedGlassPane(true, false, false, true).ID: return 6821; case BlackStainedGlassPane::BlackStainedGlassPane(true, false, false, false).ID: return 6822; case BlackStainedGlassPane::BlackStainedGlassPane(false, true, true, true).ID: return 6825; case BlackStainedGlassPane::BlackStainedGlassPane(false, true, true, false).ID: return 6826; case BlackStainedGlassPane::BlackStainedGlassPane(false, true, false, true).ID: return 6829; case BlackStainedGlassPane::BlackStainedGlassPane(false, true, false, false).ID: return 6830; case BlackStainedGlassPane::BlackStainedGlassPane(false, false, true, true).ID: return 6833; case BlackStainedGlassPane::BlackStainedGlassPane(false, false, true, false).ID: return 6834; case BlackStainedGlassPane::BlackStainedGlassPane(false, false, false, true).ID: return 6837; case BlackStainedGlassPane::BlackStainedGlassPane(false, false, false, false).ID: return 6838; case BlackTerracotta::BlackTerracotta().ID: return 6326; case BlackWallBanner::BlackWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 7677; case BlackWallBanner::BlackWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 7678; case BlackWallBanner::BlackWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 7679; case BlackWallBanner::BlackWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 7680; case BlackWool::BlackWool().ID: return 1398; case BlastFurnace::BlastFurnace(eBlockFace::BLOCK_FACE_ZM, true).ID: return 11155; case BlastFurnace::BlastFurnace(eBlockFace::BLOCK_FACE_ZM, false).ID: return 11156; case BlastFurnace::BlastFurnace(eBlockFace::BLOCK_FACE_ZP, true).ID: return 11157; case BlastFurnace::BlastFurnace(eBlockFace::BLOCK_FACE_ZP, false).ID: return 11158; case BlastFurnace::BlastFurnace(eBlockFace::BLOCK_FACE_XM, true).ID: return 11159; case BlastFurnace::BlastFurnace(eBlockFace::BLOCK_FACE_XM, false).ID: return 11160; case BlastFurnace::BlastFurnace(eBlockFace::BLOCK_FACE_XP, true).ID: return 11161; case BlastFurnace::BlastFurnace(eBlockFace::BLOCK_FACE_XP, false).ID: return 11162; case BlueBanner::BlueBanner(0).ID: return 7537; case BlueBanner::BlueBanner(1).ID: return 7538; case BlueBanner::BlueBanner(2).ID: return 7539; case BlueBanner::BlueBanner(3).ID: return 7540; case BlueBanner::BlueBanner(4).ID: return 7541; case BlueBanner::BlueBanner(5).ID: return 7542; case BlueBanner::BlueBanner(6).ID: return 7543; case BlueBanner::BlueBanner(7).ID: return 7544; case BlueBanner::BlueBanner(8).ID: return 7545; case BlueBanner::BlueBanner(9).ID: return 7546; case BlueBanner::BlueBanner(10).ID: return 7547; case BlueBanner::BlueBanner(11).ID: return 7548; case BlueBanner::BlueBanner(12).ID: return 7549; case BlueBanner::BlueBanner(13).ID: return 7550; case BlueBanner::BlueBanner(14).ID: return 7551; case BlueBanner::BlueBanner(15).ID: return 7552; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_ZM, true, BlueBed::Part::Head).ID: return 1224; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_ZM, true, BlueBed::Part::Foot).ID: return 1225; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_ZM, false, BlueBed::Part::Head).ID: return 1226; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_ZM, false, BlueBed::Part::Foot).ID: return 1227; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_ZP, true, BlueBed::Part::Head).ID: return 1228; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_ZP, true, BlueBed::Part::Foot).ID: return 1229; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_ZP, false, BlueBed::Part::Head).ID: return 1230; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_ZP, false, BlueBed::Part::Foot).ID: return 1231; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_XM, true, BlueBed::Part::Head).ID: return 1232; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_XM, true, BlueBed::Part::Foot).ID: return 1233; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_XM, false, BlueBed::Part::Head).ID: return 1234; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_XM, false, BlueBed::Part::Foot).ID: return 1235; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_XP, true, BlueBed::Part::Head).ID: return 1236; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_XP, true, BlueBed::Part::Foot).ID: return 1237; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_XP, false, BlueBed::Part::Head).ID: return 1238; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_XP, false, BlueBed::Part::Foot).ID: return 1239; case BlueCarpet::BlueCarpet().ID: return 7341; case BlueConcrete::BlueConcrete().ID: return 8913; case BlueConcretePowder::BlueConcretePowder().ID: return 8929; case BlueGlazedTerracotta::BlueGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 8882; case BlueGlazedTerracotta::BlueGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 8883; case BlueGlazedTerracotta::BlueGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 8884; case BlueGlazedTerracotta::BlueGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 8885; case BlueIce::BlueIce().ID: return 9112; case BlueOrchid::BlueOrchid().ID: return 1413; case BlueShulkerBox::BlueShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 8808; case BlueShulkerBox::BlueShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 8809; case BlueShulkerBox::BlueShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 8810; case BlueShulkerBox::BlueShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 8811; case BlueShulkerBox::BlueShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 8812; case BlueShulkerBox::BlueShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 8813; case BlueStainedGlass::BlueStainedGlass().ID: return 4092; case BlueStainedGlassPane::BlueStainedGlassPane(true, true, true, true).ID: return 6681; case BlueStainedGlassPane::BlueStainedGlassPane(true, true, true, false).ID: return 6682; case BlueStainedGlassPane::BlueStainedGlassPane(true, true, false, true).ID: return 6685; case BlueStainedGlassPane::BlueStainedGlassPane(true, true, false, false).ID: return 6686; case BlueStainedGlassPane::BlueStainedGlassPane(true, false, true, true).ID: return 6689; case BlueStainedGlassPane::BlueStainedGlassPane(true, false, true, false).ID: return 6690; case BlueStainedGlassPane::BlueStainedGlassPane(true, false, false, true).ID: return 6693; case BlueStainedGlassPane::BlueStainedGlassPane(true, false, false, false).ID: return 6694; case BlueStainedGlassPane::BlueStainedGlassPane(false, true, true, true).ID: return 6697; case BlueStainedGlassPane::BlueStainedGlassPane(false, true, true, false).ID: return 6698; case BlueStainedGlassPane::BlueStainedGlassPane(false, true, false, true).ID: return 6701; case BlueStainedGlassPane::BlueStainedGlassPane(false, true, false, false).ID: return 6702; case BlueStainedGlassPane::BlueStainedGlassPane(false, false, true, true).ID: return 6705; case BlueStainedGlassPane::BlueStainedGlassPane(false, false, true, false).ID: return 6706; case BlueStainedGlassPane::BlueStainedGlassPane(false, false, false, true).ID: return 6709; case BlueStainedGlassPane::BlueStainedGlassPane(false, false, false, false).ID: return 6710; case BlueTerracotta::BlueTerracotta().ID: return 6322; case BlueWallBanner::BlueWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 7661; case BlueWallBanner::BlueWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 7662; case BlueWallBanner::BlueWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 7663; case BlueWallBanner::BlueWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 7664; case BlueWool::BlueWool().ID: return 1394; case BoneBlock::BoneBlock(BoneBlock::Axis::X).ID: return 8720; case BoneBlock::BoneBlock(BoneBlock::Axis::Y).ID: return 8721; case BoneBlock::BoneBlock(BoneBlock::Axis::Z).ID: return 8722; case Bookshelf::Bookshelf().ID: return 1431; case BrainCoral::BrainCoral().ID: return 8997; case BrainCoralBlock::BrainCoralBlock().ID: return 8980; case BrainCoralFan::BrainCoralFan().ID: return 9017; case BrainCoralWallFan::BrainCoralWallFan(eBlockFace::BLOCK_FACE_ZM).ID: return 9073; case BrainCoralWallFan::BrainCoralWallFan(eBlockFace::BLOCK_FACE_ZP).ID: return 9075; case BrainCoralWallFan::BrainCoralWallFan(eBlockFace::BLOCK_FACE_XM).ID: return 9077; case BrainCoralWallFan::BrainCoralWallFan(eBlockFace::BLOCK_FACE_XP).ID: return 9079; case BrewingStand::BrewingStand(true, true, true).ID: return 5117; case BrewingStand::BrewingStand(true, true, false).ID: return 5118; case BrewingStand::BrewingStand(true, false, true).ID: return 5119; case BrewingStand::BrewingStand(true, false, false).ID: return 5120; case BrewingStand::BrewingStand(false, true, true).ID: return 5121; case BrewingStand::BrewingStand(false, true, false).ID: return 5122; case BrewingStand::BrewingStand(false, false, true).ID: return 5123; case BrewingStand::BrewingStand(false, false, false).ID: return 5124; case BrickSlab::BrickSlab(BrickSlab::Type::Top).ID: return 7837; case BrickSlab::BrickSlab(BrickSlab::Type::Bottom).ID: return 7839; case BrickSlab::BrickSlab(BrickSlab::Type::Double).ID: return 7841; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZM, BrickStairs::Half::Top, BrickStairs::Shape::Straight).ID: return 4837; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZM, BrickStairs::Half::Top, BrickStairs::Shape::InnerLeft).ID: return 4839; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZM, BrickStairs::Half::Top, BrickStairs::Shape::InnerRight).ID: return 4841; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZM, BrickStairs::Half::Top, BrickStairs::Shape::OuterLeft).ID: return 4843; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZM, BrickStairs::Half::Top, BrickStairs::Shape::OuterRight).ID: return 4845; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZM, BrickStairs::Half::Bottom, BrickStairs::Shape::Straight).ID: return 4847; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZM, BrickStairs::Half::Bottom, BrickStairs::Shape::InnerLeft).ID: return 4849; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZM, BrickStairs::Half::Bottom, BrickStairs::Shape::InnerRight).ID: return 4851; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZM, BrickStairs::Half::Bottom, BrickStairs::Shape::OuterLeft).ID: return 4853; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZM, BrickStairs::Half::Bottom, BrickStairs::Shape::OuterRight).ID: return 4855; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZP, BrickStairs::Half::Top, BrickStairs::Shape::Straight).ID: return 4857; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZP, BrickStairs::Half::Top, BrickStairs::Shape::InnerLeft).ID: return 4859; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZP, BrickStairs::Half::Top, BrickStairs::Shape::InnerRight).ID: return 4861; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZP, BrickStairs::Half::Top, BrickStairs::Shape::OuterLeft).ID: return 4863; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZP, BrickStairs::Half::Top, BrickStairs::Shape::OuterRight).ID: return 4865; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZP, BrickStairs::Half::Bottom, BrickStairs::Shape::Straight).ID: return 4867; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZP, BrickStairs::Half::Bottom, BrickStairs::Shape::InnerLeft).ID: return 4869; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZP, BrickStairs::Half::Bottom, BrickStairs::Shape::InnerRight).ID: return 4871; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZP, BrickStairs::Half::Bottom, BrickStairs::Shape::OuterLeft).ID: return 4873; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZP, BrickStairs::Half::Bottom, BrickStairs::Shape::OuterRight).ID: return 4875; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XM, BrickStairs::Half::Top, BrickStairs::Shape::Straight).ID: return 4877; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XM, BrickStairs::Half::Top, BrickStairs::Shape::InnerLeft).ID: return 4879; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XM, BrickStairs::Half::Top, BrickStairs::Shape::InnerRight).ID: return 4881; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XM, BrickStairs::Half::Top, BrickStairs::Shape::OuterLeft).ID: return 4883; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XM, BrickStairs::Half::Top, BrickStairs::Shape::OuterRight).ID: return 4885; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XM, BrickStairs::Half::Bottom, BrickStairs::Shape::Straight).ID: return 4887; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XM, BrickStairs::Half::Bottom, BrickStairs::Shape::InnerLeft).ID: return 4889; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XM, BrickStairs::Half::Bottom, BrickStairs::Shape::InnerRight).ID: return 4891; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XM, BrickStairs::Half::Bottom, BrickStairs::Shape::OuterLeft).ID: return 4893; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XM, BrickStairs::Half::Bottom, BrickStairs::Shape::OuterRight).ID: return 4895; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XP, BrickStairs::Half::Top, BrickStairs::Shape::Straight).ID: return 4897; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XP, BrickStairs::Half::Top, BrickStairs::Shape::InnerLeft).ID: return 4899; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XP, BrickStairs::Half::Top, BrickStairs::Shape::InnerRight).ID: return 4901; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XP, BrickStairs::Half::Top, BrickStairs::Shape::OuterLeft).ID: return 4903; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XP, BrickStairs::Half::Top, BrickStairs::Shape::OuterRight).ID: return 4905; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XP, BrickStairs::Half::Bottom, BrickStairs::Shape::Straight).ID: return 4907; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XP, BrickStairs::Half::Bottom, BrickStairs::Shape::InnerLeft).ID: return 4909; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XP, BrickStairs::Half::Bottom, BrickStairs::Shape::InnerRight).ID: return 4911; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XP, BrickStairs::Half::Bottom, BrickStairs::Shape::OuterLeft).ID: return 4913; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XP, BrickStairs::Half::Bottom, BrickStairs::Shape::OuterRight).ID: return 4915; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::Low, BrickWall::South::Low, true, BrickWall::West::Low).ID: return 10333; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::Low, BrickWall::South::Low, true, BrickWall::West::None).ID: return 10334; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::Low, BrickWall::South::Low, false, BrickWall::West::Low).ID: return 10337; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::Low, BrickWall::South::Low, false, BrickWall::West::None).ID: return 10338; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::Low, BrickWall::South::None, true, BrickWall::West::Low).ID: return 10341; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::Low, BrickWall::South::None, true, BrickWall::West::None).ID: return 10342; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::Low, BrickWall::South::None, false, BrickWall::West::Low).ID: return 10345; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::Low, BrickWall::South::None, false, BrickWall::West::None).ID: return 10346; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::None, BrickWall::South::Low, true, BrickWall::West::Low).ID: return 10349; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::None, BrickWall::South::Low, true, BrickWall::West::None).ID: return 10350; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::None, BrickWall::South::Low, false, BrickWall::West::Low).ID: return 10353; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::None, BrickWall::South::Low, false, BrickWall::West::None).ID: return 10354; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::None, BrickWall::South::None, true, BrickWall::West::Low).ID: return 10357; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::None, BrickWall::South::None, true, BrickWall::West::None).ID: return 10358; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::None, BrickWall::South::None, false, BrickWall::West::Low).ID: return 10361; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::None, BrickWall::South::None, false, BrickWall::West::None).ID: return 10362; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::Low, BrickWall::South::Low, true, BrickWall::West::Low).ID: return 10365; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::Low, BrickWall::South::Low, true, BrickWall::West::None).ID: return 10366; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::Low, BrickWall::South::Low, false, BrickWall::West::Low).ID: return 10369; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::Low, BrickWall::South::Low, false, BrickWall::West::None).ID: return 10370; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::Low, BrickWall::South::None, true, BrickWall::West::Low).ID: return 10373; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::Low, BrickWall::South::None, true, BrickWall::West::None).ID: return 10374; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::Low, BrickWall::South::None, false, BrickWall::West::Low).ID: return 10377; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::Low, BrickWall::South::None, false, BrickWall::West::None).ID: return 10378; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::None, BrickWall::South::Low, true, BrickWall::West::Low).ID: return 10381; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::None, BrickWall::South::Low, true, BrickWall::West::None).ID: return 10382; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::None, BrickWall::South::Low, false, BrickWall::West::Low).ID: return 10385; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::None, BrickWall::South::Low, false, BrickWall::West::None).ID: return 10386; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::None, BrickWall::South::None, true, BrickWall::West::Low).ID: return 10389; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::None, BrickWall::South::None, true, BrickWall::West::None).ID: return 10390; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::None, BrickWall::South::None, false, BrickWall::West::Low).ID: return 10393; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::None, BrickWall::South::None, false, BrickWall::West::None).ID: return 10394; case Bricks::Bricks().ID: return 1428; case BrownBanner::BrownBanner(0).ID: return 7553; case BrownBanner::BrownBanner(1).ID: return 7554; case BrownBanner::BrownBanner(2).ID: return 7555; case BrownBanner::BrownBanner(3).ID: return 7556; case BrownBanner::BrownBanner(4).ID: return 7557; case BrownBanner::BrownBanner(5).ID: return 7558; case BrownBanner::BrownBanner(6).ID: return 7559; case BrownBanner::BrownBanner(7).ID: return 7560; case BrownBanner::BrownBanner(8).ID: return 7561; case BrownBanner::BrownBanner(9).ID: return 7562; case BrownBanner::BrownBanner(10).ID: return 7563; case BrownBanner::BrownBanner(11).ID: return 7564; case BrownBanner::BrownBanner(12).ID: return 7565; case BrownBanner::BrownBanner(13).ID: return 7566; case BrownBanner::BrownBanner(14).ID: return 7567; case BrownBanner::BrownBanner(15).ID: return 7568; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_ZM, true, BrownBed::Part::Head).ID: return 1240; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_ZM, true, BrownBed::Part::Foot).ID: return 1241; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_ZM, false, BrownBed::Part::Head).ID: return 1242; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_ZM, false, BrownBed::Part::Foot).ID: return 1243; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_ZP, true, BrownBed::Part::Head).ID: return 1244; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_ZP, true, BrownBed::Part::Foot).ID: return 1245; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_ZP, false, BrownBed::Part::Head).ID: return 1246; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_ZP, false, BrownBed::Part::Foot).ID: return 1247; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_XM, true, BrownBed::Part::Head).ID: return 1248; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_XM, true, BrownBed::Part::Foot).ID: return 1249; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_XM, false, BrownBed::Part::Head).ID: return 1250; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_XM, false, BrownBed::Part::Foot).ID: return 1251; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_XP, true, BrownBed::Part::Head).ID: return 1252; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_XP, true, BrownBed::Part::Foot).ID: return 1253; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_XP, false, BrownBed::Part::Head).ID: return 1254; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_XP, false, BrownBed::Part::Foot).ID: return 1255; case BrownCarpet::BrownCarpet().ID: return 7342; case BrownConcrete::BrownConcrete().ID: return 8914; case BrownConcretePowder::BrownConcretePowder().ID: return 8930; case BrownGlazedTerracotta::BrownGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 8886; case BrownGlazedTerracotta::BrownGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 8887; case BrownGlazedTerracotta::BrownGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 8888; case BrownGlazedTerracotta::BrownGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 8889; case BrownMushroom::BrownMushroom().ID: return 1424; case BrownMushroomBlock::BrownMushroomBlock(true, true, true, true, true, true).ID: return 4491; case BrownMushroomBlock::BrownMushroomBlock(true, true, true, true, true, false).ID: return 4492; case BrownMushroomBlock::BrownMushroomBlock(true, true, true, true, false, true).ID: return 4493; case BrownMushroomBlock::BrownMushroomBlock(true, true, true, true, false, false).ID: return 4494; case BrownMushroomBlock::BrownMushroomBlock(true, true, true, false, true, true).ID: return 4495; case BrownMushroomBlock::BrownMushroomBlock(true, true, true, false, true, false).ID: return 4496; case BrownMushroomBlock::BrownMushroomBlock(true, true, true, false, false, true).ID: return 4497; case BrownMushroomBlock::BrownMushroomBlock(true, true, true, false, false, false).ID: return 4498; case BrownMushroomBlock::BrownMushroomBlock(true, true, false, true, true, true).ID: return 4499; case BrownMushroomBlock::BrownMushroomBlock(true, true, false, true, true, false).ID: return 4500; case BrownMushroomBlock::BrownMushroomBlock(true, true, false, true, false, true).ID: return 4501; case BrownMushroomBlock::BrownMushroomBlock(true, true, false, true, false, false).ID: return 4502; case BrownMushroomBlock::BrownMushroomBlock(true, true, false, false, true, true).ID: return 4503; case BrownMushroomBlock::BrownMushroomBlock(true, true, false, false, true, false).ID: return 4504; case BrownMushroomBlock::BrownMushroomBlock(true, true, false, false, false, true).ID: return 4505; case BrownMushroomBlock::BrownMushroomBlock(true, true, false, false, false, false).ID: return 4506; case BrownMushroomBlock::BrownMushroomBlock(true, false, true, true, true, true).ID: return 4507; case BrownMushroomBlock::BrownMushroomBlock(true, false, true, true, true, false).ID: return 4508; case BrownMushroomBlock::BrownMushroomBlock(true, false, true, true, false, true).ID: return 4509; case BrownMushroomBlock::BrownMushroomBlock(true, false, true, true, false, false).ID: return 4510; case BrownMushroomBlock::BrownMushroomBlock(true, false, true, false, true, true).ID: return 4511; case BrownMushroomBlock::BrownMushroomBlock(true, false, true, false, true, false).ID: return 4512; case BrownMushroomBlock::BrownMushroomBlock(true, false, true, false, false, true).ID: return 4513; case BrownMushroomBlock::BrownMushroomBlock(true, false, true, false, false, false).ID: return 4514; case BrownMushroomBlock::BrownMushroomBlock(true, false, false, true, true, true).ID: return 4515; case BrownMushroomBlock::BrownMushroomBlock(true, false, false, true, true, false).ID: return 4516; case BrownMushroomBlock::BrownMushroomBlock(true, false, false, true, false, true).ID: return 4517; case BrownMushroomBlock::BrownMushroomBlock(true, false, false, true, false, false).ID: return 4518; case BrownMushroomBlock::BrownMushroomBlock(true, false, false, false, true, true).ID: return 4519; case BrownMushroomBlock::BrownMushroomBlock(true, false, false, false, true, false).ID: return 4520; case BrownMushroomBlock::BrownMushroomBlock(true, false, false, false, false, true).ID: return 4521; case BrownMushroomBlock::BrownMushroomBlock(true, false, false, false, false, false).ID: return 4522; case BrownMushroomBlock::BrownMushroomBlock(false, true, true, true, true, true).ID: return 4523; case BrownMushroomBlock::BrownMushroomBlock(false, true, true, true, true, false).ID: return 4524; case BrownMushroomBlock::BrownMushroomBlock(false, true, true, true, false, true).ID: return 4525; case BrownMushroomBlock::BrownMushroomBlock(false, true, true, true, false, false).ID: return 4526; case BrownMushroomBlock::BrownMushroomBlock(false, true, true, false, true, true).ID: return 4527; case BrownMushroomBlock::BrownMushroomBlock(false, true, true, false, true, false).ID: return 4528; case BrownMushroomBlock::BrownMushroomBlock(false, true, true, false, false, true).ID: return 4529; case BrownMushroomBlock::BrownMushroomBlock(false, true, true, false, false, false).ID: return 4530; case BrownMushroomBlock::BrownMushroomBlock(false, true, false, true, true, true).ID: return 4531; case BrownMushroomBlock::BrownMushroomBlock(false, true, false, true, true, false).ID: return 4532; case BrownMushroomBlock::BrownMushroomBlock(false, true, false, true, false, true).ID: return 4533; case BrownMushroomBlock::BrownMushroomBlock(false, true, false, true, false, false).ID: return 4534; case BrownMushroomBlock::BrownMushroomBlock(false, true, false, false, true, true).ID: return 4535; case BrownMushroomBlock::BrownMushroomBlock(false, true, false, false, true, false).ID: return 4536; case BrownMushroomBlock::BrownMushroomBlock(false, true, false, false, false, true).ID: return 4537; case BrownMushroomBlock::BrownMushroomBlock(false, true, false, false, false, false).ID: return 4538; case BrownMushroomBlock::BrownMushroomBlock(false, false, true, true, true, true).ID: return 4539; case BrownMushroomBlock::BrownMushroomBlock(false, false, true, true, true, false).ID: return 4540; case BrownMushroomBlock::BrownMushroomBlock(false, false, true, true, false, true).ID: return 4541; case BrownMushroomBlock::BrownMushroomBlock(false, false, true, true, false, false).ID: return 4542; case BrownMushroomBlock::BrownMushroomBlock(false, false, true, false, true, true).ID: return 4543; case BrownMushroomBlock::BrownMushroomBlock(false, false, true, false, true, false).ID: return 4544; case BrownMushroomBlock::BrownMushroomBlock(false, false, true, false, false, true).ID: return 4545; case BrownMushroomBlock::BrownMushroomBlock(false, false, true, false, false, false).ID: return 4546; case BrownMushroomBlock::BrownMushroomBlock(false, false, false, true, true, true).ID: return 4547; case BrownMushroomBlock::BrownMushroomBlock(false, false, false, true, true, false).ID: return 4548; case BrownMushroomBlock::BrownMushroomBlock(false, false, false, true, false, true).ID: return 4549; case BrownMushroomBlock::BrownMushroomBlock(false, false, false, true, false, false).ID: return 4550; case BrownMushroomBlock::BrownMushroomBlock(false, false, false, false, true, true).ID: return 4551; case BrownMushroomBlock::BrownMushroomBlock(false, false, false, false, true, false).ID: return 4552; case BrownMushroomBlock::BrownMushroomBlock(false, false, false, false, false, true).ID: return 4553; case BrownMushroomBlock::BrownMushroomBlock(false, false, false, false, false, false).ID: return 4554; case BrownShulkerBox::BrownShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 8814; case BrownShulkerBox::BrownShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 8815; case BrownShulkerBox::BrownShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 8816; case BrownShulkerBox::BrownShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 8817; case BrownShulkerBox::BrownShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 8818; case BrownShulkerBox::BrownShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 8819; case BrownStainedGlass::BrownStainedGlass().ID: return 4093; case BrownStainedGlassPane::BrownStainedGlassPane(true, true, true, true).ID: return 6713; case BrownStainedGlassPane::BrownStainedGlassPane(true, true, true, false).ID: return 6714; case BrownStainedGlassPane::BrownStainedGlassPane(true, true, false, true).ID: return 6717; case BrownStainedGlassPane::BrownStainedGlassPane(true, true, false, false).ID: return 6718; case BrownStainedGlassPane::BrownStainedGlassPane(true, false, true, true).ID: return 6721; case BrownStainedGlassPane::BrownStainedGlassPane(true, false, true, false).ID: return 6722; case BrownStainedGlassPane::BrownStainedGlassPane(true, false, false, true).ID: return 6725; case BrownStainedGlassPane::BrownStainedGlassPane(true, false, false, false).ID: return 6726; case BrownStainedGlassPane::BrownStainedGlassPane(false, true, true, true).ID: return 6729; case BrownStainedGlassPane::BrownStainedGlassPane(false, true, true, false).ID: return 6730; case BrownStainedGlassPane::BrownStainedGlassPane(false, true, false, true).ID: return 6733; case BrownStainedGlassPane::BrownStainedGlassPane(false, true, false, false).ID: return 6734; case BrownStainedGlassPane::BrownStainedGlassPane(false, false, true, true).ID: return 6737; case BrownStainedGlassPane::BrownStainedGlassPane(false, false, true, false).ID: return 6738; case BrownStainedGlassPane::BrownStainedGlassPane(false, false, false, true).ID: return 6741; case BrownStainedGlassPane::BrownStainedGlassPane(false, false, false, false).ID: return 6742; case BrownTerracotta::BrownTerracotta().ID: return 6323; case BrownWallBanner::BrownWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 7665; case BrownWallBanner::BrownWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 7666; case BrownWallBanner::BrownWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 7667; case BrownWallBanner::BrownWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 7668; case BrownWool::BrownWool().ID: return 1395; case BubbleColumn::BubbleColumn(true).ID: return 9131; case BubbleColumn::BubbleColumn(false).ID: return 9132; case BubbleCoral::BubbleCoral().ID: return 8999; case BubbleCoralBlock::BubbleCoralBlock().ID: return 8981; case BubbleCoralFan::BubbleCoralFan().ID: return 9019; case BubbleCoralWallFan::BubbleCoralWallFan(eBlockFace::BLOCK_FACE_ZM).ID: return 9081; case BubbleCoralWallFan::BubbleCoralWallFan(eBlockFace::BLOCK_FACE_ZP).ID: return 9083; case BubbleCoralWallFan::BubbleCoralWallFan(eBlockFace::BLOCK_FACE_XM).ID: return 9085; case BubbleCoralWallFan::BubbleCoralWallFan(eBlockFace::BLOCK_FACE_XP).ID: return 9087; case Cactus::Cactus(0).ID: return 3929; case Cactus::Cactus(1).ID: return 3930; case Cactus::Cactus(2).ID: return 3931; case Cactus::Cactus(3).ID: return 3932; case Cactus::Cactus(4).ID: return 3933; case Cactus::Cactus(5).ID: return 3934; case Cactus::Cactus(6).ID: return 3935; case Cactus::Cactus(7).ID: return 3936; case Cactus::Cactus(8).ID: return 3937; case Cactus::Cactus(9).ID: return 3938; case Cactus::Cactus(10).ID: return 3939; case Cactus::Cactus(11).ID: return 3940; case Cactus::Cactus(12).ID: return 3941; case Cactus::Cactus(13).ID: return 3942; case Cactus::Cactus(14).ID: return 3943; case Cactus::Cactus(15).ID: return 3944; case Cake::Cake(0).ID: return 4010; case Cake::Cake(1).ID: return 4011; case Cake::Cake(2).ID: return 4012; case Cake::Cake(3).ID: return 4013; case Cake::Cake(4).ID: return 4014; case Cake::Cake(5).ID: return 4015; case Cake::Cake(6).ID: return 4016; case Campfire::Campfire(eBlockFace::BLOCK_FACE_ZM, true, true).ID: return 11217; case Campfire::Campfire(eBlockFace::BLOCK_FACE_ZM, true, false).ID: return 11219; case Campfire::Campfire(eBlockFace::BLOCK_FACE_ZM, false, true).ID: return 11221; case Campfire::Campfire(eBlockFace::BLOCK_FACE_ZM, false, false).ID: return 11223; case Campfire::Campfire(eBlockFace::BLOCK_FACE_ZP, true, true).ID: return 11225; case Campfire::Campfire(eBlockFace::BLOCK_FACE_ZP, true, false).ID: return 11227; case Campfire::Campfire(eBlockFace::BLOCK_FACE_ZP, false, true).ID: return 11229; case Campfire::Campfire(eBlockFace::BLOCK_FACE_ZP, false, false).ID: return 11231; case Campfire::Campfire(eBlockFace::BLOCK_FACE_XM, true, true).ID: return 11233; case Campfire::Campfire(eBlockFace::BLOCK_FACE_XM, true, false).ID: return 11235; case Campfire::Campfire(eBlockFace::BLOCK_FACE_XM, false, true).ID: return 11237; case Campfire::Campfire(eBlockFace::BLOCK_FACE_XM, false, false).ID: return 11239; case Campfire::Campfire(eBlockFace::BLOCK_FACE_XP, true, true).ID: return 11241; case Campfire::Campfire(eBlockFace::BLOCK_FACE_XP, true, false).ID: return 11243; case Campfire::Campfire(eBlockFace::BLOCK_FACE_XP, false, true).ID: return 11245; case Campfire::Campfire(eBlockFace::BLOCK_FACE_XP, false, false).ID: return 11247; case Carrots::Carrots(0).ID: return 5794; case Carrots::Carrots(1).ID: return 5795; case Carrots::Carrots(2).ID: return 5796; case Carrots::Carrots(3).ID: return 5797; case Carrots::Carrots(4).ID: return 5798; case Carrots::Carrots(5).ID: return 5799; case Carrots::Carrots(6).ID: return 5800; case Carrots::Carrots(7).ID: return 5801; case CartographyTable::CartographyTable().ID: return 11163; case CarvedPumpkin::CarvedPumpkin(eBlockFace::BLOCK_FACE_ZM).ID: return 4002; case CarvedPumpkin::CarvedPumpkin(eBlockFace::BLOCK_FACE_ZP).ID: return 4003; case CarvedPumpkin::CarvedPumpkin(eBlockFace::BLOCK_FACE_XM).ID: return 4004; case CarvedPumpkin::CarvedPumpkin(eBlockFace::BLOCK_FACE_XP).ID: return 4005; case Cauldron::Cauldron(0).ID: return 5125; case Cauldron::Cauldron(1).ID: return 5126; case Cauldron::Cauldron(2).ID: return 5127; case Cauldron::Cauldron(3).ID: return 5128; case CaveAir::CaveAir().ID: return 9130; case ChainCommandBlock::ChainCommandBlock(true, eBlockFace::BLOCK_FACE_ZM).ID: return 8701; case ChainCommandBlock::ChainCommandBlock(true, eBlockFace::BLOCK_FACE_XP).ID: return 8702; case ChainCommandBlock::ChainCommandBlock(true, eBlockFace::BLOCK_FACE_ZP).ID: return 8703; case ChainCommandBlock::ChainCommandBlock(true, eBlockFace::BLOCK_FACE_XM).ID: return 8704; case ChainCommandBlock::ChainCommandBlock(true, eBlockFace::BLOCK_FACE_YP).ID: return 8705; case ChainCommandBlock::ChainCommandBlock(true, eBlockFace::BLOCK_FACE_YM).ID: return 8706; case ChainCommandBlock::ChainCommandBlock(false, eBlockFace::BLOCK_FACE_ZM).ID: return 8707; case ChainCommandBlock::ChainCommandBlock(false, eBlockFace::BLOCK_FACE_XP).ID: return 8708; case ChainCommandBlock::ChainCommandBlock(false, eBlockFace::BLOCK_FACE_ZP).ID: return 8709; case ChainCommandBlock::ChainCommandBlock(false, eBlockFace::BLOCK_FACE_XM).ID: return 8710; case ChainCommandBlock::ChainCommandBlock(false, eBlockFace::BLOCK_FACE_YP).ID: return 8711; case ChainCommandBlock::ChainCommandBlock(false, eBlockFace::BLOCK_FACE_YM).ID: return 8712; case Chest::Chest(eBlockFace::BLOCK_FACE_ZM, Chest::Type::Single).ID: return 2033; case Chest::Chest(eBlockFace::BLOCK_FACE_ZM, Chest::Type::Left).ID: return 2035; case Chest::Chest(eBlockFace::BLOCK_FACE_ZM, Chest::Type::Right).ID: return 2037; case Chest::Chest(eBlockFace::BLOCK_FACE_ZP, Chest::Type::Single).ID: return 2039; case Chest::Chest(eBlockFace::BLOCK_FACE_ZP, Chest::Type::Left).ID: return 2041; case Chest::Chest(eBlockFace::BLOCK_FACE_ZP, Chest::Type::Right).ID: return 2043; case Chest::Chest(eBlockFace::BLOCK_FACE_XM, Chest::Type::Single).ID: return 2045; case Chest::Chest(eBlockFace::BLOCK_FACE_XM, Chest::Type::Left).ID: return 2047; case Chest::Chest(eBlockFace::BLOCK_FACE_XM, Chest::Type::Right).ID: return 2049; case Chest::Chest(eBlockFace::BLOCK_FACE_XP, Chest::Type::Single).ID: return 2051; case Chest::Chest(eBlockFace::BLOCK_FACE_XP, Chest::Type::Left).ID: return 2053; case Chest::Chest(eBlockFace::BLOCK_FACE_XP, Chest::Type::Right).ID: return 2055; case ChippedAnvil::ChippedAnvil(eBlockFace::BLOCK_FACE_ZM).ID: return 6078; case ChippedAnvil::ChippedAnvil(eBlockFace::BLOCK_FACE_ZP).ID: return 6079; case ChippedAnvil::ChippedAnvil(eBlockFace::BLOCK_FACE_XM).ID: return 6080; case ChippedAnvil::ChippedAnvil(eBlockFace::BLOCK_FACE_XP).ID: return 6081; case ChiseledQuartzBlock::ChiseledQuartzBlock().ID: return 6203; case ChiseledRedSandstone::ChiseledRedSandstone().ID: return 7682; case ChiseledSandstone::ChiseledSandstone().ID: return 246; case ChiseledStoneBricks::ChiseledStoneBricks().ID: return 4484; case ChorusFlower::ChorusFlower(0).ID: return 8592; case ChorusFlower::ChorusFlower(1).ID: return 8593; case ChorusFlower::ChorusFlower(2).ID: return 8594; case ChorusFlower::ChorusFlower(3).ID: return 8595; case ChorusFlower::ChorusFlower(4).ID: return 8596; case ChorusFlower::ChorusFlower(5).ID: return 8597; case ChorusPlant::ChorusPlant(true, true, true, true, true, true).ID: return 8528; case ChorusPlant::ChorusPlant(true, true, true, true, true, false).ID: return 8529; case ChorusPlant::ChorusPlant(true, true, true, true, false, true).ID: return 8530; case ChorusPlant::ChorusPlant(true, true, true, true, false, false).ID: return 8531; case ChorusPlant::ChorusPlant(true, true, true, false, true, true).ID: return 8532; case ChorusPlant::ChorusPlant(true, true, true, false, true, false).ID: return 8533; case ChorusPlant::ChorusPlant(true, true, true, false, false, true).ID: return 8534; case ChorusPlant::ChorusPlant(true, true, true, false, false, false).ID: return 8535; case ChorusPlant::ChorusPlant(true, true, false, true, true, true).ID: return 8536; case ChorusPlant::ChorusPlant(true, true, false, true, true, false).ID: return 8537; case ChorusPlant::ChorusPlant(true, true, false, true, false, true).ID: return 8538; case ChorusPlant::ChorusPlant(true, true, false, true, false, false).ID: return 8539; case ChorusPlant::ChorusPlant(true, true, false, false, true, true).ID: return 8540; case ChorusPlant::ChorusPlant(true, true, false, false, true, false).ID: return 8541; case ChorusPlant::ChorusPlant(true, true, false, false, false, true).ID: return 8542; case ChorusPlant::ChorusPlant(true, true, false, false, false, false).ID: return 8543; case ChorusPlant::ChorusPlant(true, false, true, true, true, true).ID: return 8544; case ChorusPlant::ChorusPlant(true, false, true, true, true, false).ID: return 8545; case ChorusPlant::ChorusPlant(true, false, true, true, false, true).ID: return 8546; case ChorusPlant::ChorusPlant(true, false, true, true, false, false).ID: return 8547; case ChorusPlant::ChorusPlant(true, false, true, false, true, true).ID: return 8548; case ChorusPlant::ChorusPlant(true, false, true, false, true, false).ID: return 8549; case ChorusPlant::ChorusPlant(true, false, true, false, false, true).ID: return 8550; case ChorusPlant::ChorusPlant(true, false, true, false, false, false).ID: return 8551; case ChorusPlant::ChorusPlant(true, false, false, true, true, true).ID: return 8552; case ChorusPlant::ChorusPlant(true, false, false, true, true, false).ID: return 8553; case ChorusPlant::ChorusPlant(true, false, false, true, false, true).ID: return 8554; case ChorusPlant::ChorusPlant(true, false, false, true, false, false).ID: return 8555; case ChorusPlant::ChorusPlant(true, false, false, false, true, true).ID: return 8556; case ChorusPlant::ChorusPlant(true, false, false, false, true, false).ID: return 8557; case ChorusPlant::ChorusPlant(true, false, false, false, false, true).ID: return 8558; case ChorusPlant::ChorusPlant(true, false, false, false, false, false).ID: return 8559; case ChorusPlant::ChorusPlant(false, true, true, true, true, true).ID: return 8560; case ChorusPlant::ChorusPlant(false, true, true, true, true, false).ID: return 8561; case ChorusPlant::ChorusPlant(false, true, true, true, false, true).ID: return 8562; case ChorusPlant::ChorusPlant(false, true, true, true, false, false).ID: return 8563; case ChorusPlant::ChorusPlant(false, true, true, false, true, true).ID: return 8564; case ChorusPlant::ChorusPlant(false, true, true, false, true, false).ID: return 8565; case ChorusPlant::ChorusPlant(false, true, true, false, false, true).ID: return 8566; case ChorusPlant::ChorusPlant(false, true, true, false, false, false).ID: return 8567; case ChorusPlant::ChorusPlant(false, true, false, true, true, true).ID: return 8568; case ChorusPlant::ChorusPlant(false, true, false, true, true, false).ID: return 8569; case ChorusPlant::ChorusPlant(false, true, false, true, false, true).ID: return 8570; case ChorusPlant::ChorusPlant(false, true, false, true, false, false).ID: return 8571; case ChorusPlant::ChorusPlant(false, true, false, false, true, true).ID: return 8572; case ChorusPlant::ChorusPlant(false, true, false, false, true, false).ID: return 8573; case ChorusPlant::ChorusPlant(false, true, false, false, false, true).ID: return 8574; case ChorusPlant::ChorusPlant(false, true, false, false, false, false).ID: return 8575; case ChorusPlant::ChorusPlant(false, false, true, true, true, true).ID: return 8576; case ChorusPlant::ChorusPlant(false, false, true, true, true, false).ID: return 8577; case ChorusPlant::ChorusPlant(false, false, true, true, false, true).ID: return 8578; case ChorusPlant::ChorusPlant(false, false, true, true, false, false).ID: return 8579; case ChorusPlant::ChorusPlant(false, false, true, false, true, true).ID: return 8580; case ChorusPlant::ChorusPlant(false, false, true, false, true, false).ID: return 8581; case ChorusPlant::ChorusPlant(false, false, true, false, false, true).ID: return 8582; case ChorusPlant::ChorusPlant(false, false, true, false, false, false).ID: return 8583; case ChorusPlant::ChorusPlant(false, false, false, true, true, true).ID: return 8584; case ChorusPlant::ChorusPlant(false, false, false, true, true, false).ID: return 8585; case ChorusPlant::ChorusPlant(false, false, false, true, false, true).ID: return 8586; case ChorusPlant::ChorusPlant(false, false, false, true, false, false).ID: return 8587; case ChorusPlant::ChorusPlant(false, false, false, false, true, true).ID: return 8588; case ChorusPlant::ChorusPlant(false, false, false, false, true, false).ID: return 8589; case ChorusPlant::ChorusPlant(false, false, false, false, false, true).ID: return 8590; case ChorusPlant::ChorusPlant(false, false, false, false, false, false).ID: return 8591; case Clay::Clay().ID: return 3945; case CoalBlock::CoalBlock().ID: return 7347; case CoalOre::CoalOre().ID: return 71; case CoarseDirt::CoarseDirt().ID: return 11; case Cobblestone::Cobblestone().ID: return 14; case CobblestoneSlab::CobblestoneSlab(CobblestoneSlab::Type::Top).ID: return 7831; case CobblestoneSlab::CobblestoneSlab(CobblestoneSlab::Type::Bottom).ID: return 7833; case CobblestoneSlab::CobblestoneSlab(CobblestoneSlab::Type::Double).ID: return 7835; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::Straight).ID: return 3654; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::InnerLeft).ID: return 3656; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::InnerRight).ID: return 3658; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::OuterLeft).ID: return 3660; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::OuterRight).ID: return 3662; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::Straight).ID: return 3664; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::InnerLeft).ID: return 3666; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::InnerRight).ID: return 3668; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::OuterLeft).ID: return 3670; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::OuterRight).ID: return 3672; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::Straight).ID: return 3674; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::InnerLeft).ID: return 3676; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::InnerRight).ID: return 3678; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::OuterLeft).ID: return 3680; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::OuterRight).ID: return 3682; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::Straight).ID: return 3684; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::InnerLeft).ID: return 3686; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::InnerRight).ID: return 3688; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::OuterLeft).ID: return 3690; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::OuterRight).ID: return 3692; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XM, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::Straight).ID: return 3694; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XM, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::InnerLeft).ID: return 3696; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XM, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::InnerRight).ID: return 3698; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XM, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::OuterLeft).ID: return 3700; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XM, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::OuterRight).ID: return 3702; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XM, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::Straight).ID: return 3704; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XM, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::InnerLeft).ID: return 3706; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XM, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::InnerRight).ID: return 3708; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XM, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::OuterLeft).ID: return 3710; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XM, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::OuterRight).ID: return 3712; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XP, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::Straight).ID: return 3714; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XP, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::InnerLeft).ID: return 3716; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XP, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::InnerRight).ID: return 3718; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XP, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::OuterLeft).ID: return 3720; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XP, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::OuterRight).ID: return 3722; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XP, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::Straight).ID: return 3724; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XP, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::InnerLeft).ID: return 3726; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XP, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::InnerRight).ID: return 3728; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XP, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::OuterLeft).ID: return 3730; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XP, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::OuterRight).ID: return 3732; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::Low, CobblestoneWall::South::Low, true, CobblestoneWall::West::Low).ID: return 5643; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::Low, CobblestoneWall::South::Low, true, CobblestoneWall::West::None).ID: return 5644; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::Low, CobblestoneWall::South::Low, false, CobblestoneWall::West::Low).ID: return 5647; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::Low, CobblestoneWall::South::Low, false, CobblestoneWall::West::None).ID: return 5648; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::Low, CobblestoneWall::South::None, true, CobblestoneWall::West::Low).ID: return 5651; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::Low, CobblestoneWall::South::None, true, CobblestoneWall::West::None).ID: return 5652; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::Low, CobblestoneWall::South::None, false, CobblestoneWall::West::Low).ID: return 5655; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::Low, CobblestoneWall::South::None, false, CobblestoneWall::West::None).ID: return 5656; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::None, CobblestoneWall::South::Low, true, CobblestoneWall::West::Low).ID: return 5659; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::None, CobblestoneWall::South::Low, true, CobblestoneWall::West::None).ID: return 5660; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::None, CobblestoneWall::South::Low, false, CobblestoneWall::West::Low).ID: return 5663; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::None, CobblestoneWall::South::Low, false, CobblestoneWall::West::None).ID: return 5664; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::None, CobblestoneWall::South::None, true, CobblestoneWall::West::Low).ID: return 5667; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::None, CobblestoneWall::South::None, true, CobblestoneWall::West::None).ID: return 5668; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::None, CobblestoneWall::South::None, false, CobblestoneWall::West::Low).ID: return 5671; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::None, CobblestoneWall::South::None, false, CobblestoneWall::West::None).ID: return 5672; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::Low, CobblestoneWall::South::Low, true, CobblestoneWall::West::Low).ID: return 5675; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::Low, CobblestoneWall::South::Low, true, CobblestoneWall::West::None).ID: return 5676; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::Low, CobblestoneWall::South::Low, false, CobblestoneWall::West::Low).ID: return 5679; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::Low, CobblestoneWall::South::Low, false, CobblestoneWall::West::None).ID: return 5680; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::Low, CobblestoneWall::South::None, true, CobblestoneWall::West::Low).ID: return 5683; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::Low, CobblestoneWall::South::None, true, CobblestoneWall::West::None).ID: return 5684; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::Low, CobblestoneWall::South::None, false, CobblestoneWall::West::Low).ID: return 5687; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::Low, CobblestoneWall::South::None, false, CobblestoneWall::West::None).ID: return 5688; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::None, CobblestoneWall::South::Low, true, CobblestoneWall::West::Low).ID: return 5691; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::None, CobblestoneWall::South::Low, true, CobblestoneWall::West::None).ID: return 5692; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::None, CobblestoneWall::South::Low, false, CobblestoneWall::West::Low).ID: return 5695; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::None, CobblestoneWall::South::Low, false, CobblestoneWall::West::None).ID: return 5696; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::None, CobblestoneWall::South::None, true, CobblestoneWall::West::Low).ID: return 5699; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::None, CobblestoneWall::South::None, true, CobblestoneWall::West::None).ID: return 5700; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::None, CobblestoneWall::South::None, false, CobblestoneWall::West::Low).ID: return 5703; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::None, CobblestoneWall::South::None, false, CobblestoneWall::West::None).ID: return 5704; case Cobweb::Cobweb().ID: return 1340; case Cocoa::Cocoa(0, eBlockFace::BLOCK_FACE_ZM).ID: return 5142; case Cocoa::Cocoa(0, eBlockFace::BLOCK_FACE_ZP).ID: return 5143; case Cocoa::Cocoa(0, eBlockFace::BLOCK_FACE_XM).ID: return 5144; case Cocoa::Cocoa(0, eBlockFace::BLOCK_FACE_XP).ID: return 5145; case Cocoa::Cocoa(1, eBlockFace::BLOCK_FACE_ZM).ID: return 5146; case Cocoa::Cocoa(1, eBlockFace::BLOCK_FACE_ZP).ID: return 5147; case Cocoa::Cocoa(1, eBlockFace::BLOCK_FACE_XM).ID: return 5148; case Cocoa::Cocoa(1, eBlockFace::BLOCK_FACE_XP).ID: return 5149; case Cocoa::Cocoa(2, eBlockFace::BLOCK_FACE_ZM).ID: return 5150; case Cocoa::Cocoa(2, eBlockFace::BLOCK_FACE_ZP).ID: return 5151; case Cocoa::Cocoa(2, eBlockFace::BLOCK_FACE_XM).ID: return 5152; case Cocoa::Cocoa(2, eBlockFace::BLOCK_FACE_XP).ID: return 5153; case CommandBlock::CommandBlock(true, eBlockFace::BLOCK_FACE_ZM).ID: return 5628; case CommandBlock::CommandBlock(true, eBlockFace::BLOCK_FACE_XP).ID: return 5629; case CommandBlock::CommandBlock(true, eBlockFace::BLOCK_FACE_ZP).ID: return 5630; case CommandBlock::CommandBlock(true, eBlockFace::BLOCK_FACE_XM).ID: return 5631; case CommandBlock::CommandBlock(true, eBlockFace::BLOCK_FACE_YP).ID: return 5632; case CommandBlock::CommandBlock(true, eBlockFace::BLOCK_FACE_YM).ID: return 5633; case CommandBlock::CommandBlock(false, eBlockFace::BLOCK_FACE_ZM).ID: return 5634; case CommandBlock::CommandBlock(false, eBlockFace::BLOCK_FACE_XP).ID: return 5635; case CommandBlock::CommandBlock(false, eBlockFace::BLOCK_FACE_ZP).ID: return 5636; case CommandBlock::CommandBlock(false, eBlockFace::BLOCK_FACE_XM).ID: return 5637; case CommandBlock::CommandBlock(false, eBlockFace::BLOCK_FACE_YP).ID: return 5638; case CommandBlock::CommandBlock(false, eBlockFace::BLOCK_FACE_YM).ID: return 5639; case Comparator::Comparator(eBlockFace::BLOCK_FACE_ZM, Comparator::Mode::Compare, true).ID: return 6142; case Comparator::Comparator(eBlockFace::BLOCK_FACE_ZM, Comparator::Mode::Compare, false).ID: return 6143; case Comparator::Comparator(eBlockFace::BLOCK_FACE_ZM, Comparator::Mode::Subtract, true).ID: return 6144; case Comparator::Comparator(eBlockFace::BLOCK_FACE_ZM, Comparator::Mode::Subtract, false).ID: return 6145; case Comparator::Comparator(eBlockFace::BLOCK_FACE_ZP, Comparator::Mode::Compare, true).ID: return 6146; case Comparator::Comparator(eBlockFace::BLOCK_FACE_ZP, Comparator::Mode::Compare, false).ID: return 6147; case Comparator::Comparator(eBlockFace::BLOCK_FACE_ZP, Comparator::Mode::Subtract, true).ID: return 6148; case Comparator::Comparator(eBlockFace::BLOCK_FACE_ZP, Comparator::Mode::Subtract, false).ID: return 6149; case Comparator::Comparator(eBlockFace::BLOCK_FACE_XM, Comparator::Mode::Compare, true).ID: return 6150; case Comparator::Comparator(eBlockFace::BLOCK_FACE_XM, Comparator::Mode::Compare, false).ID: return 6151; case Comparator::Comparator(eBlockFace::BLOCK_FACE_XM, Comparator::Mode::Subtract, true).ID: return 6152; case Comparator::Comparator(eBlockFace::BLOCK_FACE_XM, Comparator::Mode::Subtract, false).ID: return 6153; case Comparator::Comparator(eBlockFace::BLOCK_FACE_XP, Comparator::Mode::Compare, true).ID: return 6154; case Comparator::Comparator(eBlockFace::BLOCK_FACE_XP, Comparator::Mode::Compare, false).ID: return 6155; case Comparator::Comparator(eBlockFace::BLOCK_FACE_XP, Comparator::Mode::Subtract, true).ID: return 6156; case Comparator::Comparator(eBlockFace::BLOCK_FACE_XP, Comparator::Mode::Subtract, false).ID: return 6157; case Composter::Composter(0).ID: return 11262; case Composter::Composter(1).ID: return 11263; case Composter::Composter(2).ID: return 11264; case Composter::Composter(3).ID: return 11265; case Composter::Composter(4).ID: return 11266; case Composter::Composter(5).ID: return 11267; case Composter::Composter(6).ID: return 11268; case Composter::Composter(7).ID: return 11269; case Composter::Composter(8).ID: return 11270; case Conduit::Conduit().ID: return 9114; case Cornflower::Cornflower().ID: return 1421; case CrackedStoneBricks::CrackedStoneBricks().ID: return 4483; case CraftingTable::CraftingTable().ID: return 3354; case CreeperHead::CreeperHead(0).ID: return 6034; case CreeperHead::CreeperHead(1).ID: return 6035; case CreeperHead::CreeperHead(2).ID: return 6036; case CreeperHead::CreeperHead(3).ID: return 6037; case CreeperHead::CreeperHead(4).ID: return 6038; case CreeperHead::CreeperHead(5).ID: return 6039; case CreeperHead::CreeperHead(6).ID: return 6040; case CreeperHead::CreeperHead(7).ID: return 6041; case CreeperHead::CreeperHead(8).ID: return 6042; case CreeperHead::CreeperHead(9).ID: return 6043; case CreeperHead::CreeperHead(10).ID: return 6044; case CreeperHead::CreeperHead(11).ID: return 6045; case CreeperHead::CreeperHead(12).ID: return 6046; case CreeperHead::CreeperHead(13).ID: return 6047; case CreeperHead::CreeperHead(14).ID: return 6048; case CreeperHead::CreeperHead(15).ID: return 6049; case CreeperWallHead::CreeperWallHead(eBlockFace::BLOCK_FACE_ZM).ID: return 6050; case CreeperWallHead::CreeperWallHead(eBlockFace::BLOCK_FACE_ZP).ID: return 6051; case CreeperWallHead::CreeperWallHead(eBlockFace::BLOCK_FACE_XM).ID: return 6052; case CreeperWallHead::CreeperWallHead(eBlockFace::BLOCK_FACE_XP).ID: return 6053; case CutRedSandstone::CutRedSandstone().ID: return 7683; case CutRedSandstoneSlab::CutRedSandstoneSlab(CutRedSandstoneSlab::Type::Top).ID: return 7867; case CutRedSandstoneSlab::CutRedSandstoneSlab(CutRedSandstoneSlab::Type::Bottom).ID: return 7869; case CutRedSandstoneSlab::CutRedSandstoneSlab(CutRedSandstoneSlab::Type::Double).ID: return 7871; case CutSandstone::CutSandstone().ID: return 247; case CutSandstoneSlab::CutSandstoneSlab(CutSandstoneSlab::Type::Top).ID: return 7819; case CutSandstoneSlab::CutSandstoneSlab(CutSandstoneSlab::Type::Bottom).ID: return 7821; case CutSandstoneSlab::CutSandstoneSlab(CutSandstoneSlab::Type::Double).ID: return 7823; case CyanBanner::CyanBanner(0).ID: return 7505; case CyanBanner::CyanBanner(1).ID: return 7506; case CyanBanner::CyanBanner(2).ID: return 7507; case CyanBanner::CyanBanner(3).ID: return 7508; case CyanBanner::CyanBanner(4).ID: return 7509; case CyanBanner::CyanBanner(5).ID: return 7510; case CyanBanner::CyanBanner(6).ID: return 7511; case CyanBanner::CyanBanner(7).ID: return 7512; case CyanBanner::CyanBanner(8).ID: return 7513; case CyanBanner::CyanBanner(9).ID: return 7514; case CyanBanner::CyanBanner(10).ID: return 7515; case CyanBanner::CyanBanner(11).ID: return 7516; case CyanBanner::CyanBanner(12).ID: return 7517; case CyanBanner::CyanBanner(13).ID: return 7518; case CyanBanner::CyanBanner(14).ID: return 7519; case CyanBanner::CyanBanner(15).ID: return 7520; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_ZM, true, CyanBed::Part::Head).ID: return 1192; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_ZM, true, CyanBed::Part::Foot).ID: return 1193; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_ZM, false, CyanBed::Part::Head).ID: return 1194; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_ZM, false, CyanBed::Part::Foot).ID: return 1195; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_ZP, true, CyanBed::Part::Head).ID: return 1196; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_ZP, true, CyanBed::Part::Foot).ID: return 1197; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_ZP, false, CyanBed::Part::Head).ID: return 1198; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_ZP, false, CyanBed::Part::Foot).ID: return 1199; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_XM, true, CyanBed::Part::Head).ID: return 1200; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_XM, true, CyanBed::Part::Foot).ID: return 1201; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_XM, false, CyanBed::Part::Head).ID: return 1202; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_XM, false, CyanBed::Part::Foot).ID: return 1203; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_XP, true, CyanBed::Part::Head).ID: return 1204; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_XP, true, CyanBed::Part::Foot).ID: return 1205; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_XP, false, CyanBed::Part::Head).ID: return 1206; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_XP, false, CyanBed::Part::Foot).ID: return 1207; case CyanCarpet::CyanCarpet().ID: return 7339; case CyanConcrete::CyanConcrete().ID: return 8911; case CyanConcretePowder::CyanConcretePowder().ID: return 8927; case CyanGlazedTerracotta::CyanGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 8874; case CyanGlazedTerracotta::CyanGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 8875; case CyanGlazedTerracotta::CyanGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 8876; case CyanGlazedTerracotta::CyanGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 8877; case CyanShulkerBox::CyanShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 8796; case CyanShulkerBox::CyanShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 8797; case CyanShulkerBox::CyanShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 8798; case CyanShulkerBox::CyanShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 8799; case CyanShulkerBox::CyanShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 8800; case CyanShulkerBox::CyanShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 8801; case CyanStainedGlass::CyanStainedGlass().ID: return 4090; case CyanStainedGlassPane::CyanStainedGlassPane(true, true, true, true).ID: return 6617; case CyanStainedGlassPane::CyanStainedGlassPane(true, true, true, false).ID: return 6618; case CyanStainedGlassPane::CyanStainedGlassPane(true, true, false, true).ID: return 6621; case CyanStainedGlassPane::CyanStainedGlassPane(true, true, false, false).ID: return 6622; case CyanStainedGlassPane::CyanStainedGlassPane(true, false, true, true).ID: return 6625; case CyanStainedGlassPane::CyanStainedGlassPane(true, false, true, false).ID: return 6626; case CyanStainedGlassPane::CyanStainedGlassPane(true, false, false, true).ID: return 6629; case CyanStainedGlassPane::CyanStainedGlassPane(true, false, false, false).ID: return 6630; case CyanStainedGlassPane::CyanStainedGlassPane(false, true, true, true).ID: return 6633; case CyanStainedGlassPane::CyanStainedGlassPane(false, true, true, false).ID: return 6634; case CyanStainedGlassPane::CyanStainedGlassPane(false, true, false, true).ID: return 6637; case CyanStainedGlassPane::CyanStainedGlassPane(false, true, false, false).ID: return 6638; case CyanStainedGlassPane::CyanStainedGlassPane(false, false, true, true).ID: return 6641; case CyanStainedGlassPane::CyanStainedGlassPane(false, false, true, false).ID: return 6642; case CyanStainedGlassPane::CyanStainedGlassPane(false, false, false, true).ID: return 6645; case CyanStainedGlassPane::CyanStainedGlassPane(false, false, false, false).ID: return 6646; case CyanTerracotta::CyanTerracotta().ID: return 6320; case CyanWallBanner::CyanWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 7653; case CyanWallBanner::CyanWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 7654; case CyanWallBanner::CyanWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 7655; case CyanWallBanner::CyanWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 7656; case CyanWool::CyanWool().ID: return 1392; case DamagedAnvil::DamagedAnvil(eBlockFace::BLOCK_FACE_ZM).ID: return 6082; case DamagedAnvil::DamagedAnvil(eBlockFace::BLOCK_FACE_ZP).ID: return 6083; case DamagedAnvil::DamagedAnvil(eBlockFace::BLOCK_FACE_XM).ID: return 6084; case DamagedAnvil::DamagedAnvil(eBlockFace::BLOCK_FACE_XP).ID: return 6085; case Dandelion::Dandelion().ID: return 1411; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5930; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5931; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5932; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5933; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, true).ID: return 5934; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, false).ID: return 5935; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, true).ID: return 5936; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, false).ID: return 5937; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5938; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5939; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5940; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5941; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, true).ID: return 5942; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, false).ID: return 5943; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, true).ID: return 5944; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, false).ID: return 5945; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5946; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5947; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5948; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5949; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, true).ID: return 5950; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, false).ID: return 5951; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, true).ID: return 5952; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, false).ID: return 5953; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, true, true).ID: return 8458; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, true, false).ID: return 8459; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, false, true).ID: return 8460; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, false, false).ID: return 8461; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, true, true).ID: return 8462; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, true, false).ID: return 8463; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, false, true).ID: return 8464; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, false, false).ID: return 8465; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, true, true).ID: return 8466; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, true, false).ID: return 8467; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, false, true).ID: return 8468; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, false, false).ID: return 8469; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, true, true).ID: return 8470; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, true, false).ID: return 8471; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, false, true).ID: return 8472; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, false, false).ID: return 8473; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, true, true).ID: return 8474; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, true, false).ID: return 8475; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, false, true).ID: return 8476; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, false, false).ID: return 8477; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, true, true).ID: return 8478; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, true, false).ID: return 8479; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, false, true).ID: return 8480; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, false, false).ID: return 8481; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, true, true).ID: return 8482; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, true, false).ID: return 8483; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, false, true).ID: return 8484; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, false, false).ID: return 8485; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, true, true).ID: return 8486; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, true, false).ID: return 8487; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, false, true).ID: return 8488; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, false, false).ID: return 8489; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, true, true).ID: return 8490; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, true, false).ID: return 8491; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, false, true).ID: return 8492; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, false, false).ID: return 8493; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, true, true).ID: return 8494; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, true, false).ID: return 8495; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, false, true).ID: return 8496; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, false, false).ID: return 8497; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, true, true).ID: return 8498; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, true, false).ID: return 8499; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, false, true).ID: return 8500; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, false, false).ID: return 8501; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, true, true).ID: return 8502; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, true, false).ID: return 8503; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, false, true).ID: return 8504; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, false, false).ID: return 8505; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, true, true).ID: return 8506; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, true, false).ID: return 8507; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, false, true).ID: return 8508; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, false, false).ID: return 8509; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, true, true).ID: return 8510; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, true, false).ID: return 8511; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, false, true).ID: return 8512; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, false, false).ID: return 8513; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, true, true).ID: return 8514; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, true, false).ID: return 8515; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, false, true).ID: return 8516; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, false, false).ID: return 8517; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, true, true).ID: return 8518; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, true, false).ID: return 8519; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, false, true).ID: return 8520; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, false, false).ID: return 8521; case DarkOakFence::DarkOakFence(true, true, true, true).ID: return 8172; case DarkOakFence::DarkOakFence(true, true, true, false).ID: return 8173; case DarkOakFence::DarkOakFence(true, true, false, true).ID: return 8176; case DarkOakFence::DarkOakFence(true, true, false, false).ID: return 8177; case DarkOakFence::DarkOakFence(true, false, true, true).ID: return 8180; case DarkOakFence::DarkOakFence(true, false, true, false).ID: return 8181; case DarkOakFence::DarkOakFence(true, false, false, true).ID: return 8184; case DarkOakFence::DarkOakFence(true, false, false, false).ID: return 8185; case DarkOakFence::DarkOakFence(false, true, true, true).ID: return 8188; case DarkOakFence::DarkOakFence(false, true, true, false).ID: return 8189; case DarkOakFence::DarkOakFence(false, true, false, true).ID: return 8192; case DarkOakFence::DarkOakFence(false, true, false, false).ID: return 8193; case DarkOakFence::DarkOakFence(false, false, true, true).ID: return 8196; case DarkOakFence::DarkOakFence(false, false, true, false).ID: return 8197; case DarkOakFence::DarkOakFence(false, false, false, true).ID: return 8200; case DarkOakFence::DarkOakFence(false, false, false, false).ID: return 8201; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZM, true, true, true).ID: return 8010; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZM, true, true, false).ID: return 8011; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZM, true, false, true).ID: return 8012; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZM, true, false, false).ID: return 8013; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, true).ID: return 8014; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, false).ID: return 8015; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, true).ID: return 8016; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, false).ID: return 8017; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZP, true, true, true).ID: return 8018; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZP, true, true, false).ID: return 8019; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZP, true, false, true).ID: return 8020; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZP, true, false, false).ID: return 8021; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, true).ID: return 8022; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, false).ID: return 8023; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, true).ID: return 8024; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, false).ID: return 8025; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XM, true, true, true).ID: return 8026; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XM, true, true, false).ID: return 8027; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XM, true, false, true).ID: return 8028; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XM, true, false, false).ID: return 8029; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, true).ID: return 8030; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, false).ID: return 8031; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, true).ID: return 8032; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, false).ID: return 8033; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XP, true, true, true).ID: return 8034; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XP, true, true, false).ID: return 8035; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XP, true, false, true).ID: return 8036; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XP, true, false, false).ID: return 8037; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, true).ID: return 8038; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, false).ID: return 8039; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, true).ID: return 8040; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, false).ID: return 8041; case DarkOakLeaves::DarkOakLeaves(1, true).ID: return 214; case DarkOakLeaves::DarkOakLeaves(1, false).ID: return 215; case DarkOakLeaves::DarkOakLeaves(2, true).ID: return 216; case DarkOakLeaves::DarkOakLeaves(2, false).ID: return 217; case DarkOakLeaves::DarkOakLeaves(3, true).ID: return 218; case DarkOakLeaves::DarkOakLeaves(3, false).ID: return 219; case DarkOakLeaves::DarkOakLeaves(4, true).ID: return 220; case DarkOakLeaves::DarkOakLeaves(4, false).ID: return 221; case DarkOakLeaves::DarkOakLeaves(5, true).ID: return 222; case DarkOakLeaves::DarkOakLeaves(5, false).ID: return 223; case DarkOakLeaves::DarkOakLeaves(6, true).ID: return 224; case DarkOakLeaves::DarkOakLeaves(6, false).ID: return 225; case DarkOakLeaves::DarkOakLeaves(7, true).ID: return 226; case DarkOakLeaves::DarkOakLeaves(7, false).ID: return 227; case DarkOakLog::DarkOakLog(DarkOakLog::Axis::X).ID: return 87; case DarkOakLog::DarkOakLog(DarkOakLog::Axis::Y).ID: return 88; case DarkOakLog::DarkOakLog(DarkOakLog::Axis::Z).ID: return 89; case DarkOakPlanks::DarkOakPlanks().ID: return 20; case DarkOakPressurePlate::DarkOakPressurePlate(true).ID: return 3881; case DarkOakPressurePlate::DarkOakPressurePlate(false).ID: return 3882; case DarkOakSapling::DarkOakSapling(0).ID: return 31; case DarkOakSapling::DarkOakSapling(1).ID: return 32; case DarkOakSign::DarkOakSign(0).ID: return 3540; case DarkOakSign::DarkOakSign(1).ID: return 3542; case DarkOakSign::DarkOakSign(2).ID: return 3544; case DarkOakSign::DarkOakSign(3).ID: return 3546; case DarkOakSign::DarkOakSign(4).ID: return 3548; case DarkOakSign::DarkOakSign(5).ID: return 3550; case DarkOakSign::DarkOakSign(6).ID: return 3552; case DarkOakSign::DarkOakSign(7).ID: return 3554; case DarkOakSign::DarkOakSign(8).ID: return 3556; case DarkOakSign::DarkOakSign(9).ID: return 3558; case DarkOakSign::DarkOakSign(10).ID: return 3560; case DarkOakSign::DarkOakSign(11).ID: return 3562; case DarkOakSign::DarkOakSign(12).ID: return 3564; case DarkOakSign::DarkOakSign(13).ID: return 3566; case DarkOakSign::DarkOakSign(14).ID: return 3568; case DarkOakSign::DarkOakSign(15).ID: return 3570; case DarkOakSlab::DarkOakSlab(DarkOakSlab::Type::Top).ID: return 7795; case DarkOakSlab::DarkOakSlab(DarkOakSlab::Type::Bottom).ID: return 7797; case DarkOakSlab::DarkOakSlab(DarkOakSlab::Type::Double).ID: return 7799; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZM, DarkOakStairs::Half::Top, DarkOakStairs::Shape::Straight).ID: return 6920; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZM, DarkOakStairs::Half::Top, DarkOakStairs::Shape::InnerLeft).ID: return 6922; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZM, DarkOakStairs::Half::Top, DarkOakStairs::Shape::InnerRight).ID: return 6924; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZM, DarkOakStairs::Half::Top, DarkOakStairs::Shape::OuterLeft).ID: return 6926; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZM, DarkOakStairs::Half::Top, DarkOakStairs::Shape::OuterRight).ID: return 6928; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZM, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::Straight).ID: return 6930; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZM, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::InnerLeft).ID: return 6932; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZM, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::InnerRight).ID: return 6934; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZM, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::OuterLeft).ID: return 6936; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZM, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::OuterRight).ID: return 6938; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZP, DarkOakStairs::Half::Top, DarkOakStairs::Shape::Straight).ID: return 6940; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZP, DarkOakStairs::Half::Top, DarkOakStairs::Shape::InnerLeft).ID: return 6942; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZP, DarkOakStairs::Half::Top, DarkOakStairs::Shape::InnerRight).ID: return 6944; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZP, DarkOakStairs::Half::Top, DarkOakStairs::Shape::OuterLeft).ID: return 6946; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZP, DarkOakStairs::Half::Top, DarkOakStairs::Shape::OuterRight).ID: return 6948; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZP, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::Straight).ID: return 6950; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZP, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::InnerLeft).ID: return 6952; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZP, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::InnerRight).ID: return 6954; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZP, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::OuterLeft).ID: return 6956; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZP, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::OuterRight).ID: return 6958; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XM, DarkOakStairs::Half::Top, DarkOakStairs::Shape::Straight).ID: return 6960; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XM, DarkOakStairs::Half::Top, DarkOakStairs::Shape::InnerLeft).ID: return 6962; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XM, DarkOakStairs::Half::Top, DarkOakStairs::Shape::InnerRight).ID: return 6964; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XM, DarkOakStairs::Half::Top, DarkOakStairs::Shape::OuterLeft).ID: return 6966; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XM, DarkOakStairs::Half::Top, DarkOakStairs::Shape::OuterRight).ID: return 6968; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XM, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::Straight).ID: return 6970; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XM, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::InnerLeft).ID: return 6972; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XM, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::InnerRight).ID: return 6974; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XM, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::OuterLeft).ID: return 6976; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XM, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::OuterRight).ID: return 6978; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XP, DarkOakStairs::Half::Top, DarkOakStairs::Shape::Straight).ID: return 6980; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XP, DarkOakStairs::Half::Top, DarkOakStairs::Shape::InnerLeft).ID: return 6982; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XP, DarkOakStairs::Half::Top, DarkOakStairs::Shape::InnerRight).ID: return 6984; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XP, DarkOakStairs::Half::Top, DarkOakStairs::Shape::OuterLeft).ID: return 6986; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XP, DarkOakStairs::Half::Top, DarkOakStairs::Shape::OuterRight).ID: return 6988; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XP, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::Straight).ID: return 6990; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XP, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::InnerLeft).ID: return 6992; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XP, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::InnerRight).ID: return 6994; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XP, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::OuterLeft).ID: return 6996; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XP, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::OuterRight).ID: return 6998; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZM, DarkOakTrapdoor::Half::Top, true, true).ID: return 4418; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZM, DarkOakTrapdoor::Half::Top, true, false).ID: return 4420; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZM, DarkOakTrapdoor::Half::Top, false, true).ID: return 4422; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZM, DarkOakTrapdoor::Half::Top, false, false).ID: return 4424; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZM, DarkOakTrapdoor::Half::Bottom, true, true).ID: return 4426; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZM, DarkOakTrapdoor::Half::Bottom, true, false).ID: return 4428; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZM, DarkOakTrapdoor::Half::Bottom, false, true).ID: return 4430; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZM, DarkOakTrapdoor::Half::Bottom, false, false).ID: return 4432; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZP, DarkOakTrapdoor::Half::Top, true, true).ID: return 4434; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZP, DarkOakTrapdoor::Half::Top, true, false).ID: return 4436; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZP, DarkOakTrapdoor::Half::Top, false, true).ID: return 4438; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZP, DarkOakTrapdoor::Half::Top, false, false).ID: return 4440; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZP, DarkOakTrapdoor::Half::Bottom, true, true).ID: return 4442; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZP, DarkOakTrapdoor::Half::Bottom, true, false).ID: return 4444; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZP, DarkOakTrapdoor::Half::Bottom, false, true).ID: return 4446; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZP, DarkOakTrapdoor::Half::Bottom, false, false).ID: return 4448; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XM, DarkOakTrapdoor::Half::Top, true, true).ID: return 4450; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XM, DarkOakTrapdoor::Half::Top, true, false).ID: return 4452; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XM, DarkOakTrapdoor::Half::Top, false, true).ID: return 4454; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XM, DarkOakTrapdoor::Half::Top, false, false).ID: return 4456; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XM, DarkOakTrapdoor::Half::Bottom, true, true).ID: return 4458; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XM, DarkOakTrapdoor::Half::Bottom, true, false).ID: return 4460; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XM, DarkOakTrapdoor::Half::Bottom, false, true).ID: return 4462; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XM, DarkOakTrapdoor::Half::Bottom, false, false).ID: return 4464; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XP, DarkOakTrapdoor::Half::Top, true, true).ID: return 4466; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XP, DarkOakTrapdoor::Half::Top, true, false).ID: return 4468; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XP, DarkOakTrapdoor::Half::Top, false, true).ID: return 4470; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XP, DarkOakTrapdoor::Half::Top, false, false).ID: return 4472; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XP, DarkOakTrapdoor::Half::Bottom, true, true).ID: return 4474; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XP, DarkOakTrapdoor::Half::Bottom, true, false).ID: return 4476; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XP, DarkOakTrapdoor::Half::Bottom, false, true).ID: return 4478; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XP, DarkOakTrapdoor::Half::Bottom, false, false).ID: return 4480; case DarkOakWallSign::DarkOakWallSign(eBlockFace::BLOCK_FACE_ZM).ID: return 3774; case DarkOakWallSign::DarkOakWallSign(eBlockFace::BLOCK_FACE_ZP).ID: return 3776; case DarkOakWallSign::DarkOakWallSign(eBlockFace::BLOCK_FACE_XM).ID: return 3778; case DarkOakWallSign::DarkOakWallSign(eBlockFace::BLOCK_FACE_XP).ID: return 3780; case DarkOakWood::DarkOakWood(DarkOakWood::Axis::X).ID: return 123; case DarkOakWood::DarkOakWood(DarkOakWood::Axis::Y).ID: return 124; case DarkOakWood::DarkOakWood(DarkOakWood::Axis::Z).ID: return 125; case DarkPrismarine::DarkPrismarine().ID: return 7067; case DarkPrismarineSlab::DarkPrismarineSlab(DarkPrismarineSlab::Type::Top).ID: return 7321; case DarkPrismarineSlab::DarkPrismarineSlab(DarkPrismarineSlab::Type::Bottom).ID: return 7323; case DarkPrismarineSlab::DarkPrismarineSlab(DarkPrismarineSlab::Type::Double).ID: return 7325; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZM, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::Straight).ID: return 7229; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZM, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::InnerLeft).ID: return 7231; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZM, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::InnerRight).ID: return 7233; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZM, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::OuterLeft).ID: return 7235; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZM, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::OuterRight).ID: return 7237; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZM, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::Straight).ID: return 7239; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZM, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::InnerLeft).ID: return 7241; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZM, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::InnerRight).ID: return 7243; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZM, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::OuterLeft).ID: return 7245; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZM, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::OuterRight).ID: return 7247; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZP, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::Straight).ID: return 7249; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZP, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::InnerLeft).ID: return 7251; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZP, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::InnerRight).ID: return 7253; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZP, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::OuterLeft).ID: return 7255; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZP, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::OuterRight).ID: return 7257; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZP, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::Straight).ID: return 7259; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZP, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::InnerLeft).ID: return 7261; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZP, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::InnerRight).ID: return 7263; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZP, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::OuterLeft).ID: return 7265; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZP, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::OuterRight).ID: return 7267; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XM, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::Straight).ID: return 7269; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XM, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::InnerLeft).ID: return 7271; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XM, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::InnerRight).ID: return 7273; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XM, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::OuterLeft).ID: return 7275; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XM, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::OuterRight).ID: return 7277; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XM, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::Straight).ID: return 7279; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XM, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::InnerLeft).ID: return 7281; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XM, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::InnerRight).ID: return 7283; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XM, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::OuterLeft).ID: return 7285; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XM, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::OuterRight).ID: return 7287; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XP, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::Straight).ID: return 7289; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XP, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::InnerLeft).ID: return 7291; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XP, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::InnerRight).ID: return 7293; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XP, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::OuterLeft).ID: return 7295; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XP, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::OuterRight).ID: return 7297; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XP, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::Straight).ID: return 7299; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XP, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::InnerLeft).ID: return 7301; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XP, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::InnerRight).ID: return 7303; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XP, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::OuterLeft).ID: return 7305; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XP, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::OuterRight).ID: return 7307; case DaylightDetector::DaylightDetector(true, 0).ID: return 6158; case DaylightDetector::DaylightDetector(true, 1).ID: return 6159; case DaylightDetector::DaylightDetector(true, 2).ID: return 6160; case DaylightDetector::DaylightDetector(true, 3).ID: return 6161; case DaylightDetector::DaylightDetector(true, 4).ID: return 6162; case DaylightDetector::DaylightDetector(true, 5).ID: return 6163; case DaylightDetector::DaylightDetector(true, 6).ID: return 6164; case DaylightDetector::DaylightDetector(true, 7).ID: return 6165; case DaylightDetector::DaylightDetector(true, 8).ID: return 6166; case DaylightDetector::DaylightDetector(true, 9).ID: return 6167; case DaylightDetector::DaylightDetector(true, 10).ID: return 6168; case DaylightDetector::DaylightDetector(true, 11).ID: return 6169; case DaylightDetector::DaylightDetector(true, 12).ID: return 6170; case DaylightDetector::DaylightDetector(true, 13).ID: return 6171; case DaylightDetector::DaylightDetector(true, 14).ID: return 6172; case DaylightDetector::DaylightDetector(true, 15).ID: return 6173; case DaylightDetector::DaylightDetector(false, 0).ID: return 6174; case DaylightDetector::DaylightDetector(false, 1).ID: return 6175; case DaylightDetector::DaylightDetector(false, 2).ID: return 6176; case DaylightDetector::DaylightDetector(false, 3).ID: return 6177; case DaylightDetector::DaylightDetector(false, 4).ID: return 6178; case DaylightDetector::DaylightDetector(false, 5).ID: return 6179; case DaylightDetector::DaylightDetector(false, 6).ID: return 6180; case DaylightDetector::DaylightDetector(false, 7).ID: return 6181; case DaylightDetector::DaylightDetector(false, 8).ID: return 6182; case DaylightDetector::DaylightDetector(false, 9).ID: return 6183; case DaylightDetector::DaylightDetector(false, 10).ID: return 6184; case DaylightDetector::DaylightDetector(false, 11).ID: return 6185; case DaylightDetector::DaylightDetector(false, 12).ID: return 6186; case DaylightDetector::DaylightDetector(false, 13).ID: return 6187; case DaylightDetector::DaylightDetector(false, 14).ID: return 6188; case DaylightDetector::DaylightDetector(false, 15).ID: return 6189; case DeadBrainCoral::DeadBrainCoral().ID: return 8987; case DeadBrainCoralBlock::DeadBrainCoralBlock().ID: return 8975; case DeadBrainCoralFan::DeadBrainCoralFan().ID: return 9007; case DeadBrainCoralWallFan::DeadBrainCoralWallFan(eBlockFace::BLOCK_FACE_ZM).ID: return 9033; case DeadBrainCoralWallFan::DeadBrainCoralWallFan(eBlockFace::BLOCK_FACE_ZP).ID: return 9035; case DeadBrainCoralWallFan::DeadBrainCoralWallFan(eBlockFace::BLOCK_FACE_XM).ID: return 9037; case DeadBrainCoralWallFan::DeadBrainCoralWallFan(eBlockFace::BLOCK_FACE_XP).ID: return 9039; case DeadBubbleCoral::DeadBubbleCoral().ID: return 8989; case DeadBubbleCoralBlock::DeadBubbleCoralBlock().ID: return 8976; case DeadBubbleCoralFan::DeadBubbleCoralFan().ID: return 9009; case DeadBubbleCoralWallFan::DeadBubbleCoralWallFan(eBlockFace::BLOCK_FACE_ZM).ID: return 9041; case DeadBubbleCoralWallFan::DeadBubbleCoralWallFan(eBlockFace::BLOCK_FACE_ZP).ID: return 9043; case DeadBubbleCoralWallFan::DeadBubbleCoralWallFan(eBlockFace::BLOCK_FACE_XM).ID: return 9045; case DeadBubbleCoralWallFan::DeadBubbleCoralWallFan(eBlockFace::BLOCK_FACE_XP).ID: return 9047; case DeadBush::DeadBush().ID: return 1343; case DeadFireCoral::DeadFireCoral().ID: return 8991; case DeadFireCoralBlock::DeadFireCoralBlock().ID: return 8977; case DeadFireCoralFan::DeadFireCoralFan().ID: return 9011; case DeadFireCoralWallFan::DeadFireCoralWallFan(eBlockFace::BLOCK_FACE_ZM).ID: return 9049; case DeadFireCoralWallFan::DeadFireCoralWallFan(eBlockFace::BLOCK_FACE_ZP).ID: return 9051; case DeadFireCoralWallFan::DeadFireCoralWallFan(eBlockFace::BLOCK_FACE_XM).ID: return 9053; case DeadFireCoralWallFan::DeadFireCoralWallFan(eBlockFace::BLOCK_FACE_XP).ID: return 9055; case DeadHornCoral::DeadHornCoral().ID: return 8993; case DeadHornCoralBlock::DeadHornCoralBlock().ID: return 8978; case DeadHornCoralFan::DeadHornCoralFan().ID: return 9013; case DeadHornCoralWallFan::DeadHornCoralWallFan(eBlockFace::BLOCK_FACE_ZM).ID: return 9057; case DeadHornCoralWallFan::DeadHornCoralWallFan(eBlockFace::BLOCK_FACE_ZP).ID: return 9059; case DeadHornCoralWallFan::DeadHornCoralWallFan(eBlockFace::BLOCK_FACE_XM).ID: return 9061; case DeadHornCoralWallFan::DeadHornCoralWallFan(eBlockFace::BLOCK_FACE_XP).ID: return 9063; case DeadTubeCoral::DeadTubeCoral().ID: return 8985; case DeadTubeCoralBlock::DeadTubeCoralBlock().ID: return 8974; case DeadTubeCoralFan::DeadTubeCoralFan().ID: return 9005; case DeadTubeCoralWallFan::DeadTubeCoralWallFan(eBlockFace::BLOCK_FACE_ZM).ID: return 9025; case DeadTubeCoralWallFan::DeadTubeCoralWallFan(eBlockFace::BLOCK_FACE_ZP).ID: return 9027; case DeadTubeCoralWallFan::DeadTubeCoralWallFan(eBlockFace::BLOCK_FACE_XM).ID: return 9029; case DeadTubeCoralWallFan::DeadTubeCoralWallFan(eBlockFace::BLOCK_FACE_XP).ID: return 9031; case DetectorRail::DetectorRail(true, DetectorRail::Shape::NorthSouth).ID: return 1316; case DetectorRail::DetectorRail(true, DetectorRail::Shape::EastWest).ID: return 1317; case DetectorRail::DetectorRail(true, DetectorRail::Shape::AscendingEast).ID: return 1318; case DetectorRail::DetectorRail(true, DetectorRail::Shape::AscendingWest).ID: return 1319; case DetectorRail::DetectorRail(true, DetectorRail::Shape::AscendingNorth).ID: return 1320; case DetectorRail::DetectorRail(true, DetectorRail::Shape::AscendingSouth).ID: return 1321; case DetectorRail::DetectorRail(false, DetectorRail::Shape::NorthSouth).ID: return 1322; case DetectorRail::DetectorRail(false, DetectorRail::Shape::EastWest).ID: return 1323; case DetectorRail::DetectorRail(false, DetectorRail::Shape::AscendingEast).ID: return 1324; case DetectorRail::DetectorRail(false, DetectorRail::Shape::AscendingWest).ID: return 1325; case DetectorRail::DetectorRail(false, DetectorRail::Shape::AscendingNorth).ID: return 1326; case DetectorRail::DetectorRail(false, DetectorRail::Shape::AscendingSouth).ID: return 1327; case DiamondBlock::DiamondBlock().ID: return 3353; case DiamondOre::DiamondOre().ID: return 3352; case Diorite::Diorite().ID: return 4; case DioriteSlab::DioriteSlab(DioriteSlab::Type::Top).ID: return 10326; case DioriteSlab::DioriteSlab(DioriteSlab::Type::Bottom).ID: return 10328; case DioriteSlab::DioriteSlab(DioriteSlab::Type::Double).ID: return 10330; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_ZM, DioriteStairs::Half::Top, DioriteStairs::Shape::Straight).ID: return 10174; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_ZM, DioriteStairs::Half::Top, DioriteStairs::Shape::InnerLeft).ID: return 10176; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_ZM, DioriteStairs::Half::Top, DioriteStairs::Shape::InnerRight).ID: return 10178; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_ZM, DioriteStairs::Half::Top, DioriteStairs::Shape::OuterLeft).ID: return 10180; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_ZM, DioriteStairs::Half::Top, DioriteStairs::Shape::OuterRight).ID: return 10182; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_ZM, DioriteStairs::Half::Bottom, DioriteStairs::Shape::Straight).ID: return 10184; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_ZM, DioriteStairs::Half::Bottom, DioriteStairs::Shape::InnerLeft).ID: return 10186; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_ZM, DioriteStairs::Half::Bottom, DioriteStairs::Shape::InnerRight).ID: return 10188; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_ZM, DioriteStairs::Half::Bottom, DioriteStairs::Shape::OuterLeft).ID: return 10190; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_ZM, DioriteStairs::Half::Bottom, DioriteStairs::Shape::OuterRight).ID: return 10192; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_ZP, DioriteStairs::Half::Top, DioriteStairs::Shape::Straight).ID: return 10194; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_ZP, DioriteStairs::Half::Top, DioriteStairs::Shape::InnerLeft).ID: return 10196; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_ZP, DioriteStairs::Half::Top, DioriteStairs::Shape::InnerRight).ID: return 10198; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_ZP, DioriteStairs::Half::Top, DioriteStairs::Shape::OuterLeft).ID: return 10200; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_ZP, DioriteStairs::Half::Top, DioriteStairs::Shape::OuterRight).ID: return 10202; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_ZP, DioriteStairs::Half::Bottom, DioriteStairs::Shape::Straight).ID: return 10204; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_ZP, DioriteStairs::Half::Bottom, DioriteStairs::Shape::InnerLeft).ID: return 10206; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_ZP, DioriteStairs::Half::Bottom, DioriteStairs::Shape::InnerRight).ID: return 10208; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_ZP, DioriteStairs::Half::Bottom, DioriteStairs::Shape::OuterLeft).ID: return 10210; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_ZP, DioriteStairs::Half::Bottom, DioriteStairs::Shape::OuterRight).ID: return 10212; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_XM, DioriteStairs::Half::Top, DioriteStairs::Shape::Straight).ID: return 10214; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_XM, DioriteStairs::Half::Top, DioriteStairs::Shape::InnerLeft).ID: return 10216; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_XM, DioriteStairs::Half::Top, DioriteStairs::Shape::InnerRight).ID: return 10218; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_XM, DioriteStairs::Half::Top, DioriteStairs::Shape::OuterLeft).ID: return 10220; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_XM, DioriteStairs::Half::Top, DioriteStairs::Shape::OuterRight).ID: return 10222; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_XM, DioriteStairs::Half::Bottom, DioriteStairs::Shape::Straight).ID: return 10224; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_XM, DioriteStairs::Half::Bottom, DioriteStairs::Shape::InnerLeft).ID: return 10226; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_XM, DioriteStairs::Half::Bottom, DioriteStairs::Shape::InnerRight).ID: return 10228; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_XM, DioriteStairs::Half::Bottom, DioriteStairs::Shape::OuterLeft).ID: return 10230; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_XM, DioriteStairs::Half::Bottom, DioriteStairs::Shape::OuterRight).ID: return 10232; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_XP, DioriteStairs::Half::Top, DioriteStairs::Shape::Straight).ID: return 10234; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_XP, DioriteStairs::Half::Top, DioriteStairs::Shape::InnerLeft).ID: return 10236; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_XP, DioriteStairs::Half::Top, DioriteStairs::Shape::InnerRight).ID: return 10238; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_XP, DioriteStairs::Half::Top, DioriteStairs::Shape::OuterLeft).ID: return 10240; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_XP, DioriteStairs::Half::Top, DioriteStairs::Shape::OuterRight).ID: return 10242; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_XP, DioriteStairs::Half::Bottom, DioriteStairs::Shape::Straight).ID: return 10244; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_XP, DioriteStairs::Half::Bottom, DioriteStairs::Shape::InnerLeft).ID: return 10246; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_XP, DioriteStairs::Half::Bottom, DioriteStairs::Shape::InnerRight).ID: return 10248; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_XP, DioriteStairs::Half::Bottom, DioriteStairs::Shape::OuterLeft).ID: return 10250; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_XP, DioriteStairs::Half::Bottom, DioriteStairs::Shape::OuterRight).ID: return 10252; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::Low, DioriteWall::South::Low, true, DioriteWall::West::Low).ID: return 11037; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::Low, DioriteWall::South::Low, true, DioriteWall::West::None).ID: return 11038; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::Low, DioriteWall::South::Low, false, DioriteWall::West::Low).ID: return 11041; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::Low, DioriteWall::South::Low, false, DioriteWall::West::None).ID: return 11042; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::Low, DioriteWall::South::None, true, DioriteWall::West::Low).ID: return 11045; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::Low, DioriteWall::South::None, true, DioriteWall::West::None).ID: return 11046; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::Low, DioriteWall::South::None, false, DioriteWall::West::Low).ID: return 11049; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::Low, DioriteWall::South::None, false, DioriteWall::West::None).ID: return 11050; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::None, DioriteWall::South::Low, true, DioriteWall::West::Low).ID: return 11053; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::None, DioriteWall::South::Low, true, DioriteWall::West::None).ID: return 11054; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::None, DioriteWall::South::Low, false, DioriteWall::West::Low).ID: return 11057; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::None, DioriteWall::South::Low, false, DioriteWall::West::None).ID: return 11058; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::None, DioriteWall::South::None, true, DioriteWall::West::Low).ID: return 11061; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::None, DioriteWall::South::None, true, DioriteWall::West::None).ID: return 11062; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::None, DioriteWall::South::None, false, DioriteWall::West::Low).ID: return 11065; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::None, DioriteWall::South::None, false, DioriteWall::West::None).ID: return 11066; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::Low, DioriteWall::South::Low, true, DioriteWall::West::Low).ID: return 11069; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::Low, DioriteWall::South::Low, true, DioriteWall::West::None).ID: return 11070; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::Low, DioriteWall::South::Low, false, DioriteWall::West::Low).ID: return 11073; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::Low, DioriteWall::South::Low, false, DioriteWall::West::None).ID: return 11074; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::Low, DioriteWall::South::None, true, DioriteWall::West::Low).ID: return 11077; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::Low, DioriteWall::South::None, true, DioriteWall::West::None).ID: return 11078; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::Low, DioriteWall::South::None, false, DioriteWall::West::Low).ID: return 11081; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::Low, DioriteWall::South::None, false, DioriteWall::West::None).ID: return 11082; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::None, DioriteWall::South::Low, true, DioriteWall::West::Low).ID: return 11085; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::None, DioriteWall::South::Low, true, DioriteWall::West::None).ID: return 11086; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::None, DioriteWall::South::Low, false, DioriteWall::West::Low).ID: return 11089; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::None, DioriteWall::South::Low, false, DioriteWall::West::None).ID: return 11090; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::None, DioriteWall::South::None, true, DioriteWall::West::Low).ID: return 11093; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::None, DioriteWall::South::None, true, DioriteWall::West::None).ID: return 11094; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::None, DioriteWall::South::None, false, DioriteWall::West::Low).ID: return 11097; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::None, DioriteWall::South::None, false, DioriteWall::West::None).ID: return 11098; case Dirt::Dirt().ID: return 10; case Dispenser::Dispenser(eBlockFace::BLOCK_FACE_ZM, true).ID: return 233; case Dispenser::Dispenser(eBlockFace::BLOCK_FACE_ZM, false).ID: return 234; case Dispenser::Dispenser(eBlockFace::BLOCK_FACE_XP, true).ID: return 235; case Dispenser::Dispenser(eBlockFace::BLOCK_FACE_XP, false).ID: return 236; case Dispenser::Dispenser(eBlockFace::BLOCK_FACE_ZP, true).ID: return 237; case Dispenser::Dispenser(eBlockFace::BLOCK_FACE_ZP, false).ID: return 238; case Dispenser::Dispenser(eBlockFace::BLOCK_FACE_XM, true).ID: return 239; case Dispenser::Dispenser(eBlockFace::BLOCK_FACE_XM, false).ID: return 240; case Dispenser::Dispenser(eBlockFace::BLOCK_FACE_YP, true).ID: return 241; case Dispenser::Dispenser(eBlockFace::BLOCK_FACE_YP, false).ID: return 242; case Dispenser::Dispenser(eBlockFace::BLOCK_FACE_YM, true).ID: return 243; case Dispenser::Dispenser(eBlockFace::BLOCK_FACE_YM, false).ID: return 244; case DragonEgg::DragonEgg().ID: return 5139; case DragonHead::DragonHead(0).ID: return 6054; case DragonHead::DragonHead(1).ID: return 6055; case DragonHead::DragonHead(2).ID: return 6056; case DragonHead::DragonHead(3).ID: return 6057; case DragonHead::DragonHead(4).ID: return 6058; case DragonHead::DragonHead(5).ID: return 6059; case DragonHead::DragonHead(6).ID: return 6060; case DragonHead::DragonHead(7).ID: return 6061; case DragonHead::DragonHead(8).ID: return 6062; case DragonHead::DragonHead(9).ID: return 6063; case DragonHead::DragonHead(10).ID: return 6064; case DragonHead::DragonHead(11).ID: return 6065; case DragonHead::DragonHead(12).ID: return 6066; case DragonHead::DragonHead(13).ID: return 6067; case DragonHead::DragonHead(14).ID: return 6068; case DragonHead::DragonHead(15).ID: return 6069; case DragonWallHead::DragonWallHead(eBlockFace::BLOCK_FACE_ZM).ID: return 6070; case DragonWallHead::DragonWallHead(eBlockFace::BLOCK_FACE_ZP).ID: return 6071; case DragonWallHead::DragonWallHead(eBlockFace::BLOCK_FACE_XM).ID: return 6072; case DragonWallHead::DragonWallHead(eBlockFace::BLOCK_FACE_XP).ID: return 6073; case DriedKelpBlock::DriedKelpBlock().ID: return 8961; case Dropper::Dropper(eBlockFace::BLOCK_FACE_ZM, true).ID: return 6299; case Dropper::Dropper(eBlockFace::BLOCK_FACE_ZM, false).ID: return 6300; case Dropper::Dropper(eBlockFace::BLOCK_FACE_XP, true).ID: return 6301; case Dropper::Dropper(eBlockFace::BLOCK_FACE_XP, false).ID: return 6302; case Dropper::Dropper(eBlockFace::BLOCK_FACE_ZP, true).ID: return 6303; case Dropper::Dropper(eBlockFace::BLOCK_FACE_ZP, false).ID: return 6304; case Dropper::Dropper(eBlockFace::BLOCK_FACE_XM, true).ID: return 6305; case Dropper::Dropper(eBlockFace::BLOCK_FACE_XM, false).ID: return 6306; case Dropper::Dropper(eBlockFace::BLOCK_FACE_YP, true).ID: return 6307; case Dropper::Dropper(eBlockFace::BLOCK_FACE_YP, false).ID: return 6308; case Dropper::Dropper(eBlockFace::BLOCK_FACE_YM, true).ID: return 6309; case Dropper::Dropper(eBlockFace::BLOCK_FACE_YM, false).ID: return 6310; case EmeraldBlock::EmeraldBlock().ID: return 5387; case EmeraldOre::EmeraldOre().ID: return 5234; case EnchantingTable::EnchantingTable().ID: return 5116; case EndGateway::EndGateway().ID: return 8688; case EndPortal::EndPortal().ID: return 5129; case EndPortalFrame::EndPortalFrame(true, eBlockFace::BLOCK_FACE_ZM).ID: return 5130; case EndPortalFrame::EndPortalFrame(true, eBlockFace::BLOCK_FACE_ZP).ID: return 5131; case EndPortalFrame::EndPortalFrame(true, eBlockFace::BLOCK_FACE_XM).ID: return 5132; case EndPortalFrame::EndPortalFrame(true, eBlockFace::BLOCK_FACE_XP).ID: return 5133; case EndPortalFrame::EndPortalFrame(false, eBlockFace::BLOCK_FACE_ZM).ID: return 5134; case EndPortalFrame::EndPortalFrame(false, eBlockFace::BLOCK_FACE_ZP).ID: return 5135; case EndPortalFrame::EndPortalFrame(false, eBlockFace::BLOCK_FACE_XM).ID: return 5136; case EndPortalFrame::EndPortalFrame(false, eBlockFace::BLOCK_FACE_XP).ID: return 5137; case EndRod::EndRod(eBlockFace::BLOCK_FACE_ZM).ID: return 8522; case EndRod::EndRod(eBlockFace::BLOCK_FACE_XP).ID: return 8523; case EndRod::EndRod(eBlockFace::BLOCK_FACE_ZP).ID: return 8524; case EndRod::EndRod(eBlockFace::BLOCK_FACE_XM).ID: return 8525; case EndRod::EndRod(eBlockFace::BLOCK_FACE_YP).ID: return 8526; case EndRod::EndRod(eBlockFace::BLOCK_FACE_YM).ID: return 8527; case EndStone::EndStone().ID: return 5138; case EndStoneBrickSlab::EndStoneBrickSlab(EndStoneBrickSlab::Type::Top).ID: return 10284; case EndStoneBrickSlab::EndStoneBrickSlab(EndStoneBrickSlab::Type::Bottom).ID: return 10286; case EndStoneBrickSlab::EndStoneBrickSlab(EndStoneBrickSlab::Type::Double).ID: return 10288; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, EndStoneBrickStairs::Half::Top, EndStoneBrickStairs::Shape::Straight).ID: return 9534; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, EndStoneBrickStairs::Half::Top, EndStoneBrickStairs::Shape::InnerLeft).ID: return 9536; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, EndStoneBrickStairs::Half::Top, EndStoneBrickStairs::Shape::InnerRight).ID: return 9538; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, EndStoneBrickStairs::Half::Top, EndStoneBrickStairs::Shape::OuterLeft).ID: return 9540; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, EndStoneBrickStairs::Half::Top, EndStoneBrickStairs::Shape::OuterRight).ID: return 9542; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, EndStoneBrickStairs::Half::Bottom, EndStoneBrickStairs::Shape::Straight).ID: return 9544; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, EndStoneBrickStairs::Half::Bottom, EndStoneBrickStairs::Shape::InnerLeft).ID: return 9546; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, EndStoneBrickStairs::Half::Bottom, EndStoneBrickStairs::Shape::InnerRight).ID: return 9548; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, EndStoneBrickStairs::Half::Bottom, EndStoneBrickStairs::Shape::OuterLeft).ID: return 9550; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, EndStoneBrickStairs::Half::Bottom, EndStoneBrickStairs::Shape::OuterRight).ID: return 9552; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, EndStoneBrickStairs::Half::Top, EndStoneBrickStairs::Shape::Straight).ID: return 9554; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, EndStoneBrickStairs::Half::Top, EndStoneBrickStairs::Shape::InnerLeft).ID: return 9556; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, EndStoneBrickStairs::Half::Top, EndStoneBrickStairs::Shape::InnerRight).ID: return 9558; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, EndStoneBrickStairs::Half::Top, EndStoneBrickStairs::Shape::OuterLeft).ID: return 9560; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, EndStoneBrickStairs::Half::Top, EndStoneBrickStairs::Shape::OuterRight).ID: return 9562; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, EndStoneBrickStairs::Half::Bottom, EndStoneBrickStairs::Shape::Straight).ID: return 9564; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, EndStoneBrickStairs::Half::Bottom, EndStoneBrickStairs::Shape::InnerLeft).ID: return 9566; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, EndStoneBrickStairs::Half::Bottom, EndStoneBrickStairs::Shape::InnerRight).ID: return 9568; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, EndStoneBrickStairs::Half::Bottom, EndStoneBrickStairs::Shape::OuterLeft).ID: return 9570; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, EndStoneBrickStairs::Half::Bottom, EndStoneBrickStairs::Shape::OuterRight).ID: return 9572; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_XM, EndStoneBrickStairs::Half::Top, EndStoneBrickStairs::Shape::Straight).ID: return 9574; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_XM, EndStoneBrickStairs::Half::Top, EndStoneBrickStairs::Shape::InnerLeft).ID: return 9576; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_XM, EndStoneBrickStairs::Half::Top, EndStoneBrickStairs::Shape::InnerRight).ID: return 9578; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_XM, EndStoneBrickStairs::Half::Top, EndStoneBrickStairs::Shape::OuterLeft).ID: return 9580; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_XM, EndStoneBrickStairs::Half::Top, EndStoneBrickStairs::Shape::OuterRight).ID: return 9582; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_XM, EndStoneBrickStairs::Half::Bottom, EndStoneBrickStairs::Shape::Straight).ID: return 9584; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_XM, EndStoneBrickStairs::Half::Bottom, EndStoneBrickStairs::Shape::InnerLeft).ID: return 9586; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_XM, EndStoneBrickStairs::Half::Bottom, EndStoneBrickStairs::Shape::InnerRight).ID: return 9588; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_XM, EndStoneBrickStairs::Half::Bottom, EndStoneBrickStairs::Shape::OuterLeft).ID: return 9590; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_XM, EndStoneBrickStairs::Half::Bottom, EndStoneBrickStairs::Shape::OuterRight).ID: return 9592; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_XP, EndStoneBrickStairs::Half::Top, EndStoneBrickStairs::Shape::Straight).ID: return 9594; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_XP, EndStoneBrickStairs::Half::Top, EndStoneBrickStairs::Shape::InnerLeft).ID: return 9596; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_XP, EndStoneBrickStairs::Half::Top, EndStoneBrickStairs::Shape::InnerRight).ID: return 9598; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_XP, EndStoneBrickStairs::Half::Top, EndStoneBrickStairs::Shape::OuterLeft).ID: return 9600; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_XP, EndStoneBrickStairs::Half::Top, EndStoneBrickStairs::Shape::OuterRight).ID: return 9602; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_XP, EndStoneBrickStairs::Half::Bottom, EndStoneBrickStairs::Shape::Straight).ID: return 9604; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_XP, EndStoneBrickStairs::Half::Bottom, EndStoneBrickStairs::Shape::InnerLeft).ID: return 9606; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_XP, EndStoneBrickStairs::Half::Bottom, EndStoneBrickStairs::Shape::InnerRight).ID: return 9608; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_XP, EndStoneBrickStairs::Half::Bottom, EndStoneBrickStairs::Shape::OuterLeft).ID: return 9610; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_XP, EndStoneBrickStairs::Half::Bottom, EndStoneBrickStairs::Shape::OuterRight).ID: return 9612; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::Low, true, EndStoneBrickWall::West::Low).ID: return 10973; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::Low, true, EndStoneBrickWall::West::None).ID: return 10974; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::Low, false, EndStoneBrickWall::West::Low).ID: return 10977; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::Low, false, EndStoneBrickWall::West::None).ID: return 10978; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::None, true, EndStoneBrickWall::West::Low).ID: return 10981; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::None, true, EndStoneBrickWall::West::None).ID: return 10982; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::None, false, EndStoneBrickWall::West::Low).ID: return 10985; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::None, false, EndStoneBrickWall::West::None).ID: return 10986; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::None, EndStoneBrickWall::South::Low, true, EndStoneBrickWall::West::Low).ID: return 10989; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::None, EndStoneBrickWall::South::Low, true, EndStoneBrickWall::West::None).ID: return 10990; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::None, EndStoneBrickWall::South::Low, false, EndStoneBrickWall::West::Low).ID: return 10993; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::None, EndStoneBrickWall::South::Low, false, EndStoneBrickWall::West::None).ID: return 10994; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::None, EndStoneBrickWall::South::None, true, EndStoneBrickWall::West::Low).ID: return 10997; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::None, EndStoneBrickWall::South::None, true, EndStoneBrickWall::West::None).ID: return 10998; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::None, EndStoneBrickWall::South::None, false, EndStoneBrickWall::West::Low).ID: return 11001; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::None, EndStoneBrickWall::South::None, false, EndStoneBrickWall::West::None).ID: return 11002; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::Low, true, EndStoneBrickWall::West::Low).ID: return 11005; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::Low, true, EndStoneBrickWall::West::None).ID: return 11006; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::Low, false, EndStoneBrickWall::West::Low).ID: return 11009; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::Low, false, EndStoneBrickWall::West::None).ID: return 11010; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::None, true, EndStoneBrickWall::West::Low).ID: return 11013; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::None, true, EndStoneBrickWall::West::None).ID: return 11014; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::None, false, EndStoneBrickWall::West::Low).ID: return 11017; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::None, false, EndStoneBrickWall::West::None).ID: return 11018; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::None, EndStoneBrickWall::South::Low, true, EndStoneBrickWall::West::Low).ID: return 11021; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::None, EndStoneBrickWall::South::Low, true, EndStoneBrickWall::West::None).ID: return 11022; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::None, EndStoneBrickWall::South::Low, false, EndStoneBrickWall::West::Low).ID: return 11025; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::None, EndStoneBrickWall::South::Low, false, EndStoneBrickWall::West::None).ID: return 11026; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::None, EndStoneBrickWall::South::None, true, EndStoneBrickWall::West::Low).ID: return 11029; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::None, EndStoneBrickWall::South::None, true, EndStoneBrickWall::West::None).ID: return 11030; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::None, EndStoneBrickWall::South::None, false, EndStoneBrickWall::West::Low).ID: return 11033; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::None, EndStoneBrickWall::South::None, false, EndStoneBrickWall::West::None).ID: return 11034; case EndStoneBricks::EndStoneBricks().ID: return 8682; case EnderChest::EnderChest(eBlockFace::BLOCK_FACE_ZM).ID: return 5236; case EnderChest::EnderChest(eBlockFace::BLOCK_FACE_ZP).ID: return 5238; case EnderChest::EnderChest(eBlockFace::BLOCK_FACE_XM).ID: return 5240; case EnderChest::EnderChest(eBlockFace::BLOCK_FACE_XP).ID: return 5242; case Farmland::Farmland(0).ID: return 3363; case Farmland::Farmland(1).ID: return 3364; case Farmland::Farmland(2).ID: return 3365; case Farmland::Farmland(3).ID: return 3366; case Farmland::Farmland(4).ID: return 3367; case Farmland::Farmland(5).ID: return 3368; case Farmland::Farmland(6).ID: return 3369; case Farmland::Farmland(7).ID: return 3370; case Fern::Fern().ID: return 1342; case Fire::Fire(0, true, true, true, true, true).ID: return 1439; case Fire::Fire(0, true, true, true, true, false).ID: return 1440; case Fire::Fire(0, true, true, true, false, true).ID: return 1441; case Fire::Fire(0, true, true, true, false, false).ID: return 1442; case Fire::Fire(0, true, true, false, true, true).ID: return 1443; case Fire::Fire(0, true, true, false, true, false).ID: return 1444; case Fire::Fire(0, true, true, false, false, true).ID: return 1445; case Fire::Fire(0, true, true, false, false, false).ID: return 1446; case Fire::Fire(0, true, false, true, true, true).ID: return 1447; case Fire::Fire(0, true, false, true, true, false).ID: return 1448; case Fire::Fire(0, true, false, true, false, true).ID: return 1449; case Fire::Fire(0, true, false, true, false, false).ID: return 1450; case Fire::Fire(0, true, false, false, true, true).ID: return 1451; case Fire::Fire(0, true, false, false, true, false).ID: return 1452; case Fire::Fire(0, true, false, false, false, true).ID: return 1453; case Fire::Fire(0, true, false, false, false, false).ID: return 1454; case Fire::Fire(0, false, true, true, true, true).ID: return 1455; case Fire::Fire(0, false, true, true, true, false).ID: return 1456; case Fire::Fire(0, false, true, true, false, true).ID: return 1457; case Fire::Fire(0, false, true, true, false, false).ID: return 1458; case Fire::Fire(0, false, true, false, true, true).ID: return 1459; case Fire::Fire(0, false, true, false, true, false).ID: return 1460; case Fire::Fire(0, false, true, false, false, true).ID: return 1461; case Fire::Fire(0, false, true, false, false, false).ID: return 1462; case Fire::Fire(0, false, false, true, true, true).ID: return 1463; case Fire::Fire(0, false, false, true, true, false).ID: return 1464; case Fire::Fire(0, false, false, true, false, true).ID: return 1465; case Fire::Fire(0, false, false, true, false, false).ID: return 1466; case Fire::Fire(0, false, false, false, true, true).ID: return 1467; case Fire::Fire(0, false, false, false, true, false).ID: return 1468; case Fire::Fire(0, false, false, false, false, true).ID: return 1469; case Fire::Fire(0, false, false, false, false, false).ID: return 1470; case Fire::Fire(1, true, true, true, true, true).ID: return 1471; case Fire::Fire(1, true, true, true, true, false).ID: return 1472; case Fire::Fire(1, true, true, true, false, true).ID: return 1473; case Fire::Fire(1, true, true, true, false, false).ID: return 1474; case Fire::Fire(1, true, true, false, true, true).ID: return 1475; case Fire::Fire(1, true, true, false, true, false).ID: return 1476; case Fire::Fire(1, true, true, false, false, true).ID: return 1477; case Fire::Fire(1, true, true, false, false, false).ID: return 1478; case Fire::Fire(1, true, false, true, true, true).ID: return 1479; case Fire::Fire(1, true, false, true, true, false).ID: return 1480; case Fire::Fire(1, true, false, true, false, true).ID: return 1481; case Fire::Fire(1, true, false, true, false, false).ID: return 1482; case Fire::Fire(1, true, false, false, true, true).ID: return 1483; case Fire::Fire(1, true, false, false, true, false).ID: return 1484; case Fire::Fire(1, true, false, false, false, true).ID: return 1485; case Fire::Fire(1, true, false, false, false, false).ID: return 1486; case Fire::Fire(1, false, true, true, true, true).ID: return 1487; case Fire::Fire(1, false, true, true, true, false).ID: return 1488; case Fire::Fire(1, false, true, true, false, true).ID: return 1489; case Fire::Fire(1, false, true, true, false, false).ID: return 1490; case Fire::Fire(1, false, true, false, true, true).ID: return 1491; case Fire::Fire(1, false, true, false, true, false).ID: return 1492; case Fire::Fire(1, false, true, false, false, true).ID: return 1493; case Fire::Fire(1, false, true, false, false, false).ID: return 1494; case Fire::Fire(1, false, false, true, true, true).ID: return 1495; case Fire::Fire(1, false, false, true, true, false).ID: return 1496; case Fire::Fire(1, false, false, true, false, true).ID: return 1497; case Fire::Fire(1, false, false, true, false, false).ID: return 1498; case Fire::Fire(1, false, false, false, true, true).ID: return 1499; case Fire::Fire(1, false, false, false, true, false).ID: return 1500; case Fire::Fire(1, false, false, false, false, true).ID: return 1501; case Fire::Fire(1, false, false, false, false, false).ID: return 1502; case Fire::Fire(2, true, true, true, true, true).ID: return 1503; case Fire::Fire(2, true, true, true, true, false).ID: return 1504; case Fire::Fire(2, true, true, true, false, true).ID: return 1505; case Fire::Fire(2, true, true, true, false, false).ID: return 1506; case Fire::Fire(2, true, true, false, true, true).ID: return 1507; case Fire::Fire(2, true, true, false, true, false).ID: return 1508; case Fire::Fire(2, true, true, false, false, true).ID: return 1509; case Fire::Fire(2, true, true, false, false, false).ID: return 1510; case Fire::Fire(2, true, false, true, true, true).ID: return 1511; case Fire::Fire(2, true, false, true, true, false).ID: return 1512; case Fire::Fire(2, true, false, true, false, true).ID: return 1513; case Fire::Fire(2, true, false, true, false, false).ID: return 1514; case Fire::Fire(2, true, false, false, true, true).ID: return 1515; case Fire::Fire(2, true, false, false, true, false).ID: return 1516; case Fire::Fire(2, true, false, false, false, true).ID: return 1517; case Fire::Fire(2, true, false, false, false, false).ID: return 1518; case Fire::Fire(2, false, true, true, true, true).ID: return 1519; case Fire::Fire(2, false, true, true, true, false).ID: return 1520; case Fire::Fire(2, false, true, true, false, true).ID: return 1521; case Fire::Fire(2, false, true, true, false, false).ID: return 1522; case Fire::Fire(2, false, true, false, true, true).ID: return 1523; case Fire::Fire(2, false, true, false, true, false).ID: return 1524; case Fire::Fire(2, false, true, false, false, true).ID: return 1525; case Fire::Fire(2, false, true, false, false, false).ID: return 1526; case Fire::Fire(2, false, false, true, true, true).ID: return 1527; case Fire::Fire(2, false, false, true, true, false).ID: return 1528; case Fire::Fire(2, false, false, true, false, true).ID: return 1529; case Fire::Fire(2, false, false, true, false, false).ID: return 1530; case Fire::Fire(2, false, false, false, true, true).ID: return 1531; case Fire::Fire(2, false, false, false, true, false).ID: return 1532; case Fire::Fire(2, false, false, false, false, true).ID: return 1533; case Fire::Fire(2, false, false, false, false, false).ID: return 1534; case Fire::Fire(3, true, true, true, true, true).ID: return 1535; case Fire::Fire(3, true, true, true, true, false).ID: return 1536; case Fire::Fire(3, true, true, true, false, true).ID: return 1537; case Fire::Fire(3, true, true, true, false, false).ID: return 1538; case Fire::Fire(3, true, true, false, true, true).ID: return 1539; case Fire::Fire(3, true, true, false, true, false).ID: return 1540; case Fire::Fire(3, true, true, false, false, true).ID: return 1541; case Fire::Fire(3, true, true, false, false, false).ID: return 1542; case Fire::Fire(3, true, false, true, true, true).ID: return 1543; case Fire::Fire(3, true, false, true, true, false).ID: return 1544; case Fire::Fire(3, true, false, true, false, true).ID: return 1545; case Fire::Fire(3, true, false, true, false, false).ID: return 1546; case Fire::Fire(3, true, false, false, true, true).ID: return 1547; case Fire::Fire(3, true, false, false, true, false).ID: return 1548; case Fire::Fire(3, true, false, false, false, true).ID: return 1549; case Fire::Fire(3, true, false, false, false, false).ID: return 1550; case Fire::Fire(3, false, true, true, true, true).ID: return 1551; case Fire::Fire(3, false, true, true, true, false).ID: return 1552; case Fire::Fire(3, false, true, true, false, true).ID: return 1553; case Fire::Fire(3, false, true, true, false, false).ID: return 1554; case Fire::Fire(3, false, true, false, true, true).ID: return 1555; case Fire::Fire(3, false, true, false, true, false).ID: return 1556; case Fire::Fire(3, false, true, false, false, true).ID: return 1557; case Fire::Fire(3, false, true, false, false, false).ID: return 1558; case Fire::Fire(3, false, false, true, true, true).ID: return 1559; case Fire::Fire(3, false, false, true, true, false).ID: return 1560; case Fire::Fire(3, false, false, true, false, true).ID: return 1561; case Fire::Fire(3, false, false, true, false, false).ID: return 1562; case Fire::Fire(3, false, false, false, true, true).ID: return 1563; case Fire::Fire(3, false, false, false, true, false).ID: return 1564; case Fire::Fire(3, false, false, false, false, true).ID: return 1565; case Fire::Fire(3, false, false, false, false, false).ID: return 1566; case Fire::Fire(4, true, true, true, true, true).ID: return 1567; case Fire::Fire(4, true, true, true, true, false).ID: return 1568; case Fire::Fire(4, true, true, true, false, true).ID: return 1569; case Fire::Fire(4, true, true, true, false, false).ID: return 1570; case Fire::Fire(4, true, true, false, true, true).ID: return 1571; case Fire::Fire(4, true, true, false, true, false).ID: return 1572; case Fire::Fire(4, true, true, false, false, true).ID: return 1573; case Fire::Fire(4, true, true, false, false, false).ID: return 1574; case Fire::Fire(4, true, false, true, true, true).ID: return 1575; case Fire::Fire(4, true, false, true, true, false).ID: return 1576; case Fire::Fire(4, true, false, true, false, true).ID: return 1577; case Fire::Fire(4, true, false, true, false, false).ID: return 1578; case Fire::Fire(4, true, false, false, true, true).ID: return 1579; case Fire::Fire(4, true, false, false, true, false).ID: return 1580; case Fire::Fire(4, true, false, false, false, true).ID: return 1581; case Fire::Fire(4, true, false, false, false, false).ID: return 1582; case Fire::Fire(4, false, true, true, true, true).ID: return 1583; case Fire::Fire(4, false, true, true, true, false).ID: return 1584; case Fire::Fire(4, false, true, true, false, true).ID: return 1585; case Fire::Fire(4, false, true, true, false, false).ID: return 1586; case Fire::Fire(4, false, true, false, true, true).ID: return 1587; case Fire::Fire(4, false, true, false, true, false).ID: return 1588; case Fire::Fire(4, false, true, false, false, true).ID: return 1589; case Fire::Fire(4, false, true, false, false, false).ID: return 1590; case Fire::Fire(4, false, false, true, true, true).ID: return 1591; case Fire::Fire(4, false, false, true, true, false).ID: return 1592; case Fire::Fire(4, false, false, true, false, true).ID: return 1593; case Fire::Fire(4, false, false, true, false, false).ID: return 1594; case Fire::Fire(4, false, false, false, true, true).ID: return 1595; case Fire::Fire(4, false, false, false, true, false).ID: return 1596; case Fire::Fire(4, false, false, false, false, true).ID: return 1597; case Fire::Fire(4, false, false, false, false, false).ID: return 1598; case Fire::Fire(5, true, true, true, true, true).ID: return 1599; case Fire::Fire(5, true, true, true, true, false).ID: return 1600; case Fire::Fire(5, true, true, true, false, true).ID: return 1601; case Fire::Fire(5, true, true, true, false, false).ID: return 1602; case Fire::Fire(5, true, true, false, true, true).ID: return 1603; case Fire::Fire(5, true, true, false, true, false).ID: return 1604; case Fire::Fire(5, true, true, false, false, true).ID: return 1605; case Fire::Fire(5, true, true, false, false, false).ID: return 1606; case Fire::Fire(5, true, false, true, true, true).ID: return 1607; case Fire::Fire(5, true, false, true, true, false).ID: return 1608; case Fire::Fire(5, true, false, true, false, true).ID: return 1609; case Fire::Fire(5, true, false, true, false, false).ID: return 1610; case Fire::Fire(5, true, false, false, true, true).ID: return 1611; case Fire::Fire(5, true, false, false, true, false).ID: return 1612; case Fire::Fire(5, true, false, false, false, true).ID: return 1613; case Fire::Fire(5, true, false, false, false, false).ID: return 1614; case Fire::Fire(5, false, true, true, true, true).ID: return 1615; case Fire::Fire(5, false, true, true, true, false).ID: return 1616; case Fire::Fire(5, false, true, true, false, true).ID: return 1617; case Fire::Fire(5, false, true, true, false, false).ID: return 1618; case Fire::Fire(5, false, true, false, true, true).ID: return 1619; case Fire::Fire(5, false, true, false, true, false).ID: return 1620; case Fire::Fire(5, false, true, false, false, true).ID: return 1621; case Fire::Fire(5, false, true, false, false, false).ID: return 1622; case Fire::Fire(5, false, false, true, true, true).ID: return 1623; case Fire::Fire(5, false, false, true, true, false).ID: return 1624; case Fire::Fire(5, false, false, true, false, true).ID: return 1625; case Fire::Fire(5, false, false, true, false, false).ID: return 1626; case Fire::Fire(5, false, false, false, true, true).ID: return 1627; case Fire::Fire(5, false, false, false, true, false).ID: return 1628; case Fire::Fire(5, false, false, false, false, true).ID: return 1629; case Fire::Fire(5, false, false, false, false, false).ID: return 1630; case Fire::Fire(6, true, true, true, true, true).ID: return 1631; case Fire::Fire(6, true, true, true, true, false).ID: return 1632; case Fire::Fire(6, true, true, true, false, true).ID: return 1633; case Fire::Fire(6, true, true, true, false, false).ID: return 1634; case Fire::Fire(6, true, true, false, true, true).ID: return 1635; case Fire::Fire(6, true, true, false, true, false).ID: return 1636; case Fire::Fire(6, true, true, false, false, true).ID: return 1637; case Fire::Fire(6, true, true, false, false, false).ID: return 1638; case Fire::Fire(6, true, false, true, true, true).ID: return 1639; case Fire::Fire(6, true, false, true, true, false).ID: return 1640; case Fire::Fire(6, true, false, true, false, true).ID: return 1641; case Fire::Fire(6, true, false, true, false, false).ID: return 1642; case Fire::Fire(6, true, false, false, true, true).ID: return 1643; case Fire::Fire(6, true, false, false, true, false).ID: return 1644; case Fire::Fire(6, true, false, false, false, true).ID: return 1645; case Fire::Fire(6, true, false, false, false, false).ID: return 1646; case Fire::Fire(6, false, true, true, true, true).ID: return 1647; case Fire::Fire(6, false, true, true, true, false).ID: return 1648; case Fire::Fire(6, false, true, true, false, true).ID: return 1649; case Fire::Fire(6, false, true, true, false, false).ID: return 1650; case Fire::Fire(6, false, true, false, true, true).ID: return 1651; case Fire::Fire(6, false, true, false, true, false).ID: return 1652; case Fire::Fire(6, false, true, false, false, true).ID: return 1653; case Fire::Fire(6, false, true, false, false, false).ID: return 1654; case Fire::Fire(6, false, false, true, true, true).ID: return 1655; case Fire::Fire(6, false, false, true, true, false).ID: return 1656; case Fire::Fire(6, false, false, true, false, true).ID: return 1657; case Fire::Fire(6, false, false, true, false, false).ID: return 1658; case Fire::Fire(6, false, false, false, true, true).ID: return 1659; case Fire::Fire(6, false, false, false, true, false).ID: return 1660; case Fire::Fire(6, false, false, false, false, true).ID: return 1661; case Fire::Fire(6, false, false, false, false, false).ID: return 1662; case Fire::Fire(7, true, true, true, true, true).ID: return 1663; case Fire::Fire(7, true, true, true, true, false).ID: return 1664; case Fire::Fire(7, true, true, true, false, true).ID: return 1665; case Fire::Fire(7, true, true, true, false, false).ID: return 1666; case Fire::Fire(7, true, true, false, true, true).ID: return 1667; case Fire::Fire(7, true, true, false, true, false).ID: return 1668; case Fire::Fire(7, true, true, false, false, true).ID: return 1669; case Fire::Fire(7, true, true, false, false, false).ID: return 1670; case Fire::Fire(7, true, false, true, true, true).ID: return 1671; case Fire::Fire(7, true, false, true, true, false).ID: return 1672; case Fire::Fire(7, true, false, true, false, true).ID: return 1673; case Fire::Fire(7, true, false, true, false, false).ID: return 1674; case Fire::Fire(7, true, false, false, true, true).ID: return 1675; case Fire::Fire(7, true, false, false, true, false).ID: return 1676; case Fire::Fire(7, true, false, false, false, true).ID: return 1677; case Fire::Fire(7, true, false, false, false, false).ID: return 1678; case Fire::Fire(7, false, true, true, true, true).ID: return 1679; case Fire::Fire(7, false, true, true, true, false).ID: return 1680; case Fire::Fire(7, false, true, true, false, true).ID: return 1681; case Fire::Fire(7, false, true, true, false, false).ID: return 1682; case Fire::Fire(7, false, true, false, true, true).ID: return 1683; case Fire::Fire(7, false, true, false, true, false).ID: return 1684; case Fire::Fire(7, false, true, false, false, true).ID: return 1685; case Fire::Fire(7, false, true, false, false, false).ID: return 1686; case Fire::Fire(7, false, false, true, true, true).ID: return 1687; case Fire::Fire(7, false, false, true, true, false).ID: return 1688; case Fire::Fire(7, false, false, true, false, true).ID: return 1689; case Fire::Fire(7, false, false, true, false, false).ID: return 1690; case Fire::Fire(7, false, false, false, true, true).ID: return 1691; case Fire::Fire(7, false, false, false, true, false).ID: return 1692; case Fire::Fire(7, false, false, false, false, true).ID: return 1693; case Fire::Fire(7, false, false, false, false, false).ID: return 1694; case Fire::Fire(8, true, true, true, true, true).ID: return 1695; case Fire::Fire(8, true, true, true, true, false).ID: return 1696; case Fire::Fire(8, true, true, true, false, true).ID: return 1697; case Fire::Fire(8, true, true, true, false, false).ID: return 1698; case Fire::Fire(8, true, true, false, true, true).ID: return 1699; case Fire::Fire(8, true, true, false, true, false).ID: return 1700; case Fire::Fire(8, true, true, false, false, true).ID: return 1701; case Fire::Fire(8, true, true, false, false, false).ID: return 1702; case Fire::Fire(8, true, false, true, true, true).ID: return 1703; case Fire::Fire(8, true, false, true, true, false).ID: return 1704; case Fire::Fire(8, true, false, true, false, true).ID: return 1705; case Fire::Fire(8, true, false, true, false, false).ID: return 1706; case Fire::Fire(8, true, false, false, true, true).ID: return 1707; case Fire::Fire(8, true, false, false, true, false).ID: return 1708; case Fire::Fire(8, true, false, false, false, true).ID: return 1709; case Fire::Fire(8, true, false, false, false, false).ID: return 1710; case Fire::Fire(8, false, true, true, true, true).ID: return 1711; case Fire::Fire(8, false, true, true, true, false).ID: return 1712; case Fire::Fire(8, false, true, true, false, true).ID: return 1713; case Fire::Fire(8, false, true, true, false, false).ID: return 1714; case Fire::Fire(8, false, true, false, true, true).ID: return 1715; case Fire::Fire(8, false, true, false, true, false).ID: return 1716; case Fire::Fire(8, false, true, false, false, true).ID: return 1717; case Fire::Fire(8, false, true, false, false, false).ID: return 1718; case Fire::Fire(8, false, false, true, true, true).ID: return 1719; case Fire::Fire(8, false, false, true, true, false).ID: return 1720; case Fire::Fire(8, false, false, true, false, true).ID: return 1721; case Fire::Fire(8, false, false, true, false, false).ID: return 1722; case Fire::Fire(8, false, false, false, true, true).ID: return 1723; case Fire::Fire(8, false, false, false, true, false).ID: return 1724; case Fire::Fire(8, false, false, false, false, true).ID: return 1725; case Fire::Fire(8, false, false, false, false, false).ID: return 1726; case Fire::Fire(9, true, true, true, true, true).ID: return 1727; case Fire::Fire(9, true, true, true, true, false).ID: return 1728; case Fire::Fire(9, true, true, true, false, true).ID: return 1729; case Fire::Fire(9, true, true, true, false, false).ID: return 1730; case Fire::Fire(9, true, true, false, true, true).ID: return 1731; case Fire::Fire(9, true, true, false, true, false).ID: return 1732; case Fire::Fire(9, true, true, false, false, true).ID: return 1733; case Fire::Fire(9, true, true, false, false, false).ID: return 1734; case Fire::Fire(9, true, false, true, true, true).ID: return 1735; case Fire::Fire(9, true, false, true, true, false).ID: return 1736; case Fire::Fire(9, true, false, true, false, true).ID: return 1737; case Fire::Fire(9, true, false, true, false, false).ID: return 1738; case Fire::Fire(9, true, false, false, true, true).ID: return 1739; case Fire::Fire(9, true, false, false, true, false).ID: return 1740; case Fire::Fire(9, true, false, false, false, true).ID: return 1741; case Fire::Fire(9, true, false, false, false, false).ID: return 1742; case Fire::Fire(9, false, true, true, true, true).ID: return 1743; case Fire::Fire(9, false, true, true, true, false).ID: return 1744; case Fire::Fire(9, false, true, true, false, true).ID: return 1745; case Fire::Fire(9, false, true, true, false, false).ID: return 1746; case Fire::Fire(9, false, true, false, true, true).ID: return 1747; case Fire::Fire(9, false, true, false, true, false).ID: return 1748; case Fire::Fire(9, false, true, false, false, true).ID: return 1749; case Fire::Fire(9, false, true, false, false, false).ID: return 1750; case Fire::Fire(9, false, false, true, true, true).ID: return 1751; case Fire::Fire(9, false, false, true, true, false).ID: return 1752; case Fire::Fire(9, false, false, true, false, true).ID: return 1753; case Fire::Fire(9, false, false, true, false, false).ID: return 1754; case Fire::Fire(9, false, false, false, true, true).ID: return 1755; case Fire::Fire(9, false, false, false, true, false).ID: return 1756; case Fire::Fire(9, false, false, false, false, true).ID: return 1757; case Fire::Fire(9, false, false, false, false, false).ID: return 1758; case Fire::Fire(10, true, true, true, true, true).ID: return 1759; case Fire::Fire(10, true, true, true, true, false).ID: return 1760; case Fire::Fire(10, true, true, true, false, true).ID: return 1761; case Fire::Fire(10, true, true, true, false, false).ID: return 1762; case Fire::Fire(10, true, true, false, true, true).ID: return 1763; case Fire::Fire(10, true, true, false, true, false).ID: return 1764; case Fire::Fire(10, true, true, false, false, true).ID: return 1765; case Fire::Fire(10, true, true, false, false, false).ID: return 1766; case Fire::Fire(10, true, false, true, true, true).ID: return 1767; case Fire::Fire(10, true, false, true, true, false).ID: return 1768; case Fire::Fire(10, true, false, true, false, true).ID: return 1769; case Fire::Fire(10, true, false, true, false, false).ID: return 1770; case Fire::Fire(10, true, false, false, true, true).ID: return 1771; case Fire::Fire(10, true, false, false, true, false).ID: return 1772; case Fire::Fire(10, true, false, false, false, true).ID: return 1773; case Fire::Fire(10, true, false, false, false, false).ID: return 1774; case Fire::Fire(10, false, true, true, true, true).ID: return 1775; case Fire::Fire(10, false, true, true, true, false).ID: return 1776; case Fire::Fire(10, false, true, true, false, true).ID: return 1777; case Fire::Fire(10, false, true, true, false, false).ID: return 1778; case Fire::Fire(10, false, true, false, true, true).ID: return 1779; case Fire::Fire(10, false, true, false, true, false).ID: return 1780; case Fire::Fire(10, false, true, false, false, true).ID: return 1781; case Fire::Fire(10, false, true, false, false, false).ID: return 1782; case Fire::Fire(10, false, false, true, true, true).ID: return 1783; case Fire::Fire(10, false, false, true, true, false).ID: return 1784; case Fire::Fire(10, false, false, true, false, true).ID: return 1785; case Fire::Fire(10, false, false, true, false, false).ID: return 1786; case Fire::Fire(10, false, false, false, true, true).ID: return 1787; case Fire::Fire(10, false, false, false, true, false).ID: return 1788; case Fire::Fire(10, false, false, false, false, true).ID: return 1789; case Fire::Fire(10, false, false, false, false, false).ID: return 1790; case Fire::Fire(11, true, true, true, true, true).ID: return 1791; case Fire::Fire(11, true, true, true, true, false).ID: return 1792; case Fire::Fire(11, true, true, true, false, true).ID: return 1793; case Fire::Fire(11, true, true, true, false, false).ID: return 1794; case Fire::Fire(11, true, true, false, true, true).ID: return 1795; case Fire::Fire(11, true, true, false, true, false).ID: return 1796; case Fire::Fire(11, true, true, false, false, true).ID: return 1797; case Fire::Fire(11, true, true, false, false, false).ID: return 1798; case Fire::Fire(11, true, false, true, true, true).ID: return 1799; case Fire::Fire(11, true, false, true, true, false).ID: return 1800; case Fire::Fire(11, true, false, true, false, true).ID: return 1801; case Fire::Fire(11, true, false, true, false, false).ID: return 1802; case Fire::Fire(11, true, false, false, true, true).ID: return 1803; case Fire::Fire(11, true, false, false, true, false).ID: return 1804; case Fire::Fire(11, true, false, false, false, true).ID: return 1805; case Fire::Fire(11, true, false, false, false, false).ID: return 1806; case Fire::Fire(11, false, true, true, true, true).ID: return 1807; case Fire::Fire(11, false, true, true, true, false).ID: return 1808; case Fire::Fire(11, false, true, true, false, true).ID: return 1809; case Fire::Fire(11, false, true, true, false, false).ID: return 1810; case Fire::Fire(11, false, true, false, true, true).ID: return 1811; case Fire::Fire(11, false, true, false, true, false).ID: return 1812; case Fire::Fire(11, false, true, false, false, true).ID: return 1813; case Fire::Fire(11, false, true, false, false, false).ID: return 1814; case Fire::Fire(11, false, false, true, true, true).ID: return 1815; case Fire::Fire(11, false, false, true, true, false).ID: return 1816; case Fire::Fire(11, false, false, true, false, true).ID: return 1817; case Fire::Fire(11, false, false, true, false, false).ID: return 1818; case Fire::Fire(11, false, false, false, true, true).ID: return 1819; case Fire::Fire(11, false, false, false, true, false).ID: return 1820; case Fire::Fire(11, false, false, false, false, true).ID: return 1821; case Fire::Fire(11, false, false, false, false, false).ID: return 1822; case Fire::Fire(12, true, true, true, true, true).ID: return 1823; case Fire::Fire(12, true, true, true, true, false).ID: return 1824; case Fire::Fire(12, true, true, true, false, true).ID: return 1825; case Fire::Fire(12, true, true, true, false, false).ID: return 1826; case Fire::Fire(12, true, true, false, true, true).ID: return 1827; case Fire::Fire(12, true, true, false, true, false).ID: return 1828; case Fire::Fire(12, true, true, false, false, true).ID: return 1829; case Fire::Fire(12, true, true, false, false, false).ID: return 1830; case Fire::Fire(12, true, false, true, true, true).ID: return 1831; case Fire::Fire(12, true, false, true, true, false).ID: return 1832; case Fire::Fire(12, true, false, true, false, true).ID: return 1833; case Fire::Fire(12, true, false, true, false, false).ID: return 1834; case Fire::Fire(12, true, false, false, true, true).ID: return 1835; case Fire::Fire(12, true, false, false, true, false).ID: return 1836; case Fire::Fire(12, true, false, false, false, true).ID: return 1837; case Fire::Fire(12, true, false, false, false, false).ID: return 1838; case Fire::Fire(12, false, true, true, true, true).ID: return 1839; case Fire::Fire(12, false, true, true, true, false).ID: return 1840; case Fire::Fire(12, false, true, true, false, true).ID: return 1841; case Fire::Fire(12, false, true, true, false, false).ID: return 1842; case Fire::Fire(12, false, true, false, true, true).ID: return 1843; case Fire::Fire(12, false, true, false, true, false).ID: return 1844; case Fire::Fire(12, false, true, false, false, true).ID: return 1845; case Fire::Fire(12, false, true, false, false, false).ID: return 1846; case Fire::Fire(12, false, false, true, true, true).ID: return 1847; case Fire::Fire(12, false, false, true, true, false).ID: return 1848; case Fire::Fire(12, false, false, true, false, true).ID: return 1849; case Fire::Fire(12, false, false, true, false, false).ID: return 1850; case Fire::Fire(12, false, false, false, true, true).ID: return 1851; case Fire::Fire(12, false, false, false, true, false).ID: return 1852; case Fire::Fire(12, false, false, false, false, true).ID: return 1853; case Fire::Fire(12, false, false, false, false, false).ID: return 1854; case Fire::Fire(13, true, true, true, true, true).ID: return 1855; case Fire::Fire(13, true, true, true, true, false).ID: return 1856; case Fire::Fire(13, true, true, true, false, true).ID: return 1857; case Fire::Fire(13, true, true, true, false, false).ID: return 1858; case Fire::Fire(13, true, true, false, true, true).ID: return 1859; case Fire::Fire(13, true, true, false, true, false).ID: return 1860; case Fire::Fire(13, true, true, false, false, true).ID: return 1861; case Fire::Fire(13, true, true, false, false, false).ID: return 1862; case Fire::Fire(13, true, false, true, true, true).ID: return 1863; case Fire::Fire(13, true, false, true, true, false).ID: return 1864; case Fire::Fire(13, true, false, true, false, true).ID: return 1865; case Fire::Fire(13, true, false, true, false, false).ID: return 1866; case Fire::Fire(13, true, false, false, true, true).ID: return 1867; case Fire::Fire(13, true, false, false, true, false).ID: return 1868; case Fire::Fire(13, true, false, false, false, true).ID: return 1869; case Fire::Fire(13, true, false, false, false, false).ID: return 1870; case Fire::Fire(13, false, true, true, true, true).ID: return 1871; case Fire::Fire(13, false, true, true, true, false).ID: return 1872; case Fire::Fire(13, false, true, true, false, true).ID: return 1873; case Fire::Fire(13, false, true, true, false, false).ID: return 1874; case Fire::Fire(13, false, true, false, true, true).ID: return 1875; case Fire::Fire(13, false, true, false, true, false).ID: return 1876; case Fire::Fire(13, false, true, false, false, true).ID: return 1877; case Fire::Fire(13, false, true, false, false, false).ID: return 1878; case Fire::Fire(13, false, false, true, true, true).ID: return 1879; case Fire::Fire(13, false, false, true, true, false).ID: return 1880; case Fire::Fire(13, false, false, true, false, true).ID: return 1881; case Fire::Fire(13, false, false, true, false, false).ID: return 1882; case Fire::Fire(13, false, false, false, true, true).ID: return 1883; case Fire::Fire(13, false, false, false, true, false).ID: return 1884; case Fire::Fire(13, false, false, false, false, true).ID: return 1885; case Fire::Fire(13, false, false, false, false, false).ID: return 1886; case Fire::Fire(14, true, true, true, true, true).ID: return 1887; case Fire::Fire(14, true, true, true, true, false).ID: return 1888; case Fire::Fire(14, true, true, true, false, true).ID: return 1889; case Fire::Fire(14, true, true, true, false, false).ID: return 1890; case Fire::Fire(14, true, true, false, true, true).ID: return 1891; case Fire::Fire(14, true, true, false, true, false).ID: return 1892; case Fire::Fire(14, true, true, false, false, true).ID: return 1893; case Fire::Fire(14, true, true, false, false, false).ID: return 1894; case Fire::Fire(14, true, false, true, true, true).ID: return 1895; case Fire::Fire(14, true, false, true, true, false).ID: return 1896; case Fire::Fire(14, true, false, true, false, true).ID: return 1897; case Fire::Fire(14, true, false, true, false, false).ID: return 1898; case Fire::Fire(14, true, false, false, true, true).ID: return 1899; case Fire::Fire(14, true, false, false, true, false).ID: return 1900; case Fire::Fire(14, true, false, false, false, true).ID: return 1901; case Fire::Fire(14, true, false, false, false, false).ID: return 1902; case Fire::Fire(14, false, true, true, true, true).ID: return 1903; case Fire::Fire(14, false, true, true, true, false).ID: return 1904; case Fire::Fire(14, false, true, true, false, true).ID: return 1905; case Fire::Fire(14, false, true, true, false, false).ID: return 1906; case Fire::Fire(14, false, true, false, true, true).ID: return 1907; case Fire::Fire(14, false, true, false, true, false).ID: return 1908; case Fire::Fire(14, false, true, false, false, true).ID: return 1909; case Fire::Fire(14, false, true, false, false, false).ID: return 1910; case Fire::Fire(14, false, false, true, true, true).ID: return 1911; case Fire::Fire(14, false, false, true, true, false).ID: return 1912; case Fire::Fire(14, false, false, true, false, true).ID: return 1913; case Fire::Fire(14, false, false, true, false, false).ID: return 1914; case Fire::Fire(14, false, false, false, true, true).ID: return 1915; case Fire::Fire(14, false, false, false, true, false).ID: return 1916; case Fire::Fire(14, false, false, false, false, true).ID: return 1917; case Fire::Fire(14, false, false, false, false, false).ID: return 1918; case Fire::Fire(15, true, true, true, true, true).ID: return 1919; case Fire::Fire(15, true, true, true, true, false).ID: return 1920; case Fire::Fire(15, true, true, true, false, true).ID: return 1921; case Fire::Fire(15, true, true, true, false, false).ID: return 1922; case Fire::Fire(15, true, true, false, true, true).ID: return 1923; case Fire::Fire(15, true, true, false, true, false).ID: return 1924; case Fire::Fire(15, true, true, false, false, true).ID: return 1925; case Fire::Fire(15, true, true, false, false, false).ID: return 1926; case Fire::Fire(15, true, false, true, true, true).ID: return 1927; case Fire::Fire(15, true, false, true, true, false).ID: return 1928; case Fire::Fire(15, true, false, true, false, true).ID: return 1929; case Fire::Fire(15, true, false, true, false, false).ID: return 1930; case Fire::Fire(15, true, false, false, true, true).ID: return 1931; case Fire::Fire(15, true, false, false, true, false).ID: return 1932; case Fire::Fire(15, true, false, false, false, true).ID: return 1933; case Fire::Fire(15, true, false, false, false, false).ID: return 1934; case Fire::Fire(15, false, true, true, true, true).ID: return 1935; case Fire::Fire(15, false, true, true, true, false).ID: return 1936; case Fire::Fire(15, false, true, true, false, true).ID: return 1937; case Fire::Fire(15, false, true, true, false, false).ID: return 1938; case Fire::Fire(15, false, true, false, true, true).ID: return 1939; case Fire::Fire(15, false, true, false, true, false).ID: return 1940; case Fire::Fire(15, false, true, false, false, true).ID: return 1941; case Fire::Fire(15, false, true, false, false, false).ID: return 1942; case Fire::Fire(15, false, false, true, true, true).ID: return 1943; case Fire::Fire(15, false, false, true, true, false).ID: return 1944; case Fire::Fire(15, false, false, true, false, true).ID: return 1945; case Fire::Fire(15, false, false, true, false, false).ID: return 1946; case Fire::Fire(15, false, false, false, true, true).ID: return 1947; case Fire::Fire(15, false, false, false, true, false).ID: return 1948; case Fire::Fire(15, false, false, false, false, true).ID: return 1949; case Fire::Fire(15, false, false, false, false, false).ID: return 1950; case FireCoral::FireCoral().ID: return 9001; case FireCoralBlock::FireCoralBlock().ID: return 8982; case FireCoralFan::FireCoralFan().ID: return 9021; case FireCoralWallFan::FireCoralWallFan(eBlockFace::BLOCK_FACE_ZM).ID: return 9089; case FireCoralWallFan::FireCoralWallFan(eBlockFace::BLOCK_FACE_ZP).ID: return 9091; case FireCoralWallFan::FireCoralWallFan(eBlockFace::BLOCK_FACE_XM).ID: return 9093; case FireCoralWallFan::FireCoralWallFan(eBlockFace::BLOCK_FACE_XP).ID: return 9095; case FletchingTable::FletchingTable().ID: return 11164; case FlowerPot::FlowerPot().ID: return 5769; case FrostedIce::FrostedIce(0).ID: return 8713; case FrostedIce::FrostedIce(1).ID: return 8714; case FrostedIce::FrostedIce(2).ID: return 8715; case FrostedIce::FrostedIce(3).ID: return 8716; case Furnace::Furnace(eBlockFace::BLOCK_FACE_ZM, true).ID: return 3371; case Furnace::Furnace(eBlockFace::BLOCK_FACE_ZM, false).ID: return 3372; case Furnace::Furnace(eBlockFace::BLOCK_FACE_ZP, true).ID: return 3373; case Furnace::Furnace(eBlockFace::BLOCK_FACE_ZP, false).ID: return 3374; case Furnace::Furnace(eBlockFace::BLOCK_FACE_XM, true).ID: return 3375; case Furnace::Furnace(eBlockFace::BLOCK_FACE_XM, false).ID: return 3376; case Furnace::Furnace(eBlockFace::BLOCK_FACE_XP, true).ID: return 3377; case Furnace::Furnace(eBlockFace::BLOCK_FACE_XP, false).ID: return 3378; case Glass::Glass().ID: return 230; case GlassPane::GlassPane(true, true, true, true).ID: return 4717; case GlassPane::GlassPane(true, true, true, false).ID: return 4718; case GlassPane::GlassPane(true, true, false, true).ID: return 4721; case GlassPane::GlassPane(true, true, false, false).ID: return 4722; case GlassPane::GlassPane(true, false, true, true).ID: return 4725; case GlassPane::GlassPane(true, false, true, false).ID: return 4726; case GlassPane::GlassPane(true, false, false, true).ID: return 4729; case GlassPane::GlassPane(true, false, false, false).ID: return 4730; case GlassPane::GlassPane(false, true, true, true).ID: return 4733; case GlassPane::GlassPane(false, true, true, false).ID: return 4734; case GlassPane::GlassPane(false, true, false, true).ID: return 4737; case GlassPane::GlassPane(false, true, false, false).ID: return 4738; case GlassPane::GlassPane(false, false, true, true).ID: return 4741; case GlassPane::GlassPane(false, false, true, false).ID: return 4742; case GlassPane::GlassPane(false, false, false, true).ID: return 4745; case GlassPane::GlassPane(false, false, false, false).ID: return 4746; case Glowstone::Glowstone().ID: return 3999; case GoldBlock::GoldBlock().ID: return 1426; case GoldOre::GoldOre().ID: return 69; case Granite::Granite().ID: return 2; case GraniteSlab::GraniteSlab(GraniteSlab::Type::Top).ID: return 10302; case GraniteSlab::GraniteSlab(GraniteSlab::Type::Bottom).ID: return 10304; case GraniteSlab::GraniteSlab(GraniteSlab::Type::Double).ID: return 10306; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_ZM, GraniteStairs::Half::Top, GraniteStairs::Shape::Straight).ID: return 9854; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_ZM, GraniteStairs::Half::Top, GraniteStairs::Shape::InnerLeft).ID: return 9856; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_ZM, GraniteStairs::Half::Top, GraniteStairs::Shape::InnerRight).ID: return 9858; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_ZM, GraniteStairs::Half::Top, GraniteStairs::Shape::OuterLeft).ID: return 9860; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_ZM, GraniteStairs::Half::Top, GraniteStairs::Shape::OuterRight).ID: return 9862; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_ZM, GraniteStairs::Half::Bottom, GraniteStairs::Shape::Straight).ID: return 9864; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_ZM, GraniteStairs::Half::Bottom, GraniteStairs::Shape::InnerLeft).ID: return 9866; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_ZM, GraniteStairs::Half::Bottom, GraniteStairs::Shape::InnerRight).ID: return 9868; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_ZM, GraniteStairs::Half::Bottom, GraniteStairs::Shape::OuterLeft).ID: return 9870; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_ZM, GraniteStairs::Half::Bottom, GraniteStairs::Shape::OuterRight).ID: return 9872; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_ZP, GraniteStairs::Half::Top, GraniteStairs::Shape::Straight).ID: return 9874; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_ZP, GraniteStairs::Half::Top, GraniteStairs::Shape::InnerLeft).ID: return 9876; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_ZP, GraniteStairs::Half::Top, GraniteStairs::Shape::InnerRight).ID: return 9878; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_ZP, GraniteStairs::Half::Top, GraniteStairs::Shape::OuterLeft).ID: return 9880; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_ZP, GraniteStairs::Half::Top, GraniteStairs::Shape::OuterRight).ID: return 9882; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_ZP, GraniteStairs::Half::Bottom, GraniteStairs::Shape::Straight).ID: return 9884; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_ZP, GraniteStairs::Half::Bottom, GraniteStairs::Shape::InnerLeft).ID: return 9886; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_ZP, GraniteStairs::Half::Bottom, GraniteStairs::Shape::InnerRight).ID: return 9888; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_ZP, GraniteStairs::Half::Bottom, GraniteStairs::Shape::OuterLeft).ID: return 9890; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_ZP, GraniteStairs::Half::Bottom, GraniteStairs::Shape::OuterRight).ID: return 9892; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_XM, GraniteStairs::Half::Top, GraniteStairs::Shape::Straight).ID: return 9894; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_XM, GraniteStairs::Half::Top, GraniteStairs::Shape::InnerLeft).ID: return 9896; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_XM, GraniteStairs::Half::Top, GraniteStairs::Shape::InnerRight).ID: return 9898; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_XM, GraniteStairs::Half::Top, GraniteStairs::Shape::OuterLeft).ID: return 9900; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_XM, GraniteStairs::Half::Top, GraniteStairs::Shape::OuterRight).ID: return 9902; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_XM, GraniteStairs::Half::Bottom, GraniteStairs::Shape::Straight).ID: return 9904; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_XM, GraniteStairs::Half::Bottom, GraniteStairs::Shape::InnerLeft).ID: return 9906; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_XM, GraniteStairs::Half::Bottom, GraniteStairs::Shape::InnerRight).ID: return 9908; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_XM, GraniteStairs::Half::Bottom, GraniteStairs::Shape::OuterLeft).ID: return 9910; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_XM, GraniteStairs::Half::Bottom, GraniteStairs::Shape::OuterRight).ID: return 9912; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_XP, GraniteStairs::Half::Top, GraniteStairs::Shape::Straight).ID: return 9914; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_XP, GraniteStairs::Half::Top, GraniteStairs::Shape::InnerLeft).ID: return 9916; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_XP, GraniteStairs::Half::Top, GraniteStairs::Shape::InnerRight).ID: return 9918; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_XP, GraniteStairs::Half::Top, GraniteStairs::Shape::OuterLeft).ID: return 9920; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_XP, GraniteStairs::Half::Top, GraniteStairs::Shape::OuterRight).ID: return 9922; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_XP, GraniteStairs::Half::Bottom, GraniteStairs::Shape::Straight).ID: return 9924; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_XP, GraniteStairs::Half::Bottom, GraniteStairs::Shape::InnerLeft).ID: return 9926; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_XP, GraniteStairs::Half::Bottom, GraniteStairs::Shape::InnerRight).ID: return 9928; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_XP, GraniteStairs::Half::Bottom, GraniteStairs::Shape::OuterLeft).ID: return 9930; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_XP, GraniteStairs::Half::Bottom, GraniteStairs::Shape::OuterRight).ID: return 9932; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::Low, GraniteWall::South::Low, true, GraniteWall::West::Low).ID: return 10589; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::Low, GraniteWall::South::Low, true, GraniteWall::West::None).ID: return 10590; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::Low, GraniteWall::South::Low, false, GraniteWall::West::Low).ID: return 10593; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::Low, GraniteWall::South::Low, false, GraniteWall::West::None).ID: return 10594; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::Low, GraniteWall::South::None, true, GraniteWall::West::Low).ID: return 10597; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::Low, GraniteWall::South::None, true, GraniteWall::West::None).ID: return 10598; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::Low, GraniteWall::South::None, false, GraniteWall::West::Low).ID: return 10601; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::Low, GraniteWall::South::None, false, GraniteWall::West::None).ID: return 10602; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::None, GraniteWall::South::Low, true, GraniteWall::West::Low).ID: return 10605; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::None, GraniteWall::South::Low, true, GraniteWall::West::None).ID: return 10606; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::None, GraniteWall::South::Low, false, GraniteWall::West::Low).ID: return 10609; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::None, GraniteWall::South::Low, false, GraniteWall::West::None).ID: return 10610; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::None, GraniteWall::South::None, true, GraniteWall::West::Low).ID: return 10613; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::None, GraniteWall::South::None, true, GraniteWall::West::None).ID: return 10614; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::None, GraniteWall::South::None, false, GraniteWall::West::Low).ID: return 10617; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::None, GraniteWall::South::None, false, GraniteWall::West::None).ID: return 10618; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::Low, GraniteWall::South::Low, true, GraniteWall::West::Low).ID: return 10621; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::Low, GraniteWall::South::Low, true, GraniteWall::West::None).ID: return 10622; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::Low, GraniteWall::South::Low, false, GraniteWall::West::Low).ID: return 10625; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::Low, GraniteWall::South::Low, false, GraniteWall::West::None).ID: return 10626; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::Low, GraniteWall::South::None, true, GraniteWall::West::Low).ID: return 10629; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::Low, GraniteWall::South::None, true, GraniteWall::West::None).ID: return 10630; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::Low, GraniteWall::South::None, false, GraniteWall::West::Low).ID: return 10633; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::Low, GraniteWall::South::None, false, GraniteWall::West::None).ID: return 10634; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::None, GraniteWall::South::Low, true, GraniteWall::West::Low).ID: return 10637; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::None, GraniteWall::South::Low, true, GraniteWall::West::None).ID: return 10638; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::None, GraniteWall::South::Low, false, GraniteWall::West::Low).ID: return 10641; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::None, GraniteWall::South::Low, false, GraniteWall::West::None).ID: return 10642; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::None, GraniteWall::South::None, true, GraniteWall::West::Low).ID: return 10645; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::None, GraniteWall::South::None, true, GraniteWall::West::None).ID: return 10646; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::None, GraniteWall::South::None, false, GraniteWall::West::Low).ID: return 10649; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::None, GraniteWall::South::None, false, GraniteWall::West::None).ID: return 10650; case Grass::Grass().ID: return 1341; case GrassBlock::GrassBlock(true).ID: return 8; case GrassBlock::GrassBlock(false).ID: return 9; case GrassPath::GrassPath().ID: return 8687; case Gravel::Gravel().ID: return 68; case GrayBanner::GrayBanner(0).ID: return 7473; case GrayBanner::GrayBanner(1).ID: return 7474; case GrayBanner::GrayBanner(2).ID: return 7475; case GrayBanner::GrayBanner(3).ID: return 7476; case GrayBanner::GrayBanner(4).ID: return 7477; case GrayBanner::GrayBanner(5).ID: return 7478; case GrayBanner::GrayBanner(6).ID: return 7479; case GrayBanner::GrayBanner(7).ID: return 7480; case GrayBanner::GrayBanner(8).ID: return 7481; case GrayBanner::GrayBanner(9).ID: return 7482; case GrayBanner::GrayBanner(10).ID: return 7483; case GrayBanner::GrayBanner(11).ID: return 7484; case GrayBanner::GrayBanner(12).ID: return 7485; case GrayBanner::GrayBanner(13).ID: return 7486; case GrayBanner::GrayBanner(14).ID: return 7487; case GrayBanner::GrayBanner(15).ID: return 7488; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_ZM, true, GrayBed::Part::Head).ID: return 1160; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_ZM, true, GrayBed::Part::Foot).ID: return 1161; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_ZM, false, GrayBed::Part::Head).ID: return 1162; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_ZM, false, GrayBed::Part::Foot).ID: return 1163; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_ZP, true, GrayBed::Part::Head).ID: return 1164; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_ZP, true, GrayBed::Part::Foot).ID: return 1165; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_ZP, false, GrayBed::Part::Head).ID: return 1166; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_ZP, false, GrayBed::Part::Foot).ID: return 1167; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_XM, true, GrayBed::Part::Head).ID: return 1168; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_XM, true, GrayBed::Part::Foot).ID: return 1169; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_XM, false, GrayBed::Part::Head).ID: return 1170; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_XM, false, GrayBed::Part::Foot).ID: return 1171; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_XP, true, GrayBed::Part::Head).ID: return 1172; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_XP, true, GrayBed::Part::Foot).ID: return 1173; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_XP, false, GrayBed::Part::Head).ID: return 1174; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_XP, false, GrayBed::Part::Foot).ID: return 1175; case GrayCarpet::GrayCarpet().ID: return 7337; case GrayConcrete::GrayConcrete().ID: return 8909; case GrayConcretePowder::GrayConcretePowder().ID: return 8925; case GrayGlazedTerracotta::GrayGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 8866; case GrayGlazedTerracotta::GrayGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 8867; case GrayGlazedTerracotta::GrayGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 8868; case GrayGlazedTerracotta::GrayGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 8869; case GrayShulkerBox::GrayShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 8784; case GrayShulkerBox::GrayShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 8785; case GrayShulkerBox::GrayShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 8786; case GrayShulkerBox::GrayShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 8787; case GrayShulkerBox::GrayShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 8788; case GrayShulkerBox::GrayShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 8789; case GrayStainedGlass::GrayStainedGlass().ID: return 4088; case GrayStainedGlassPane::GrayStainedGlassPane(true, true, true, true).ID: return 6553; case GrayStainedGlassPane::GrayStainedGlassPane(true, true, true, false).ID: return 6554; case GrayStainedGlassPane::GrayStainedGlassPane(true, true, false, true).ID: return 6557; case GrayStainedGlassPane::GrayStainedGlassPane(true, true, false, false).ID: return 6558; case GrayStainedGlassPane::GrayStainedGlassPane(true, false, true, true).ID: return 6561; case GrayStainedGlassPane::GrayStainedGlassPane(true, false, true, false).ID: return 6562; case GrayStainedGlassPane::GrayStainedGlassPane(true, false, false, true).ID: return 6565; case GrayStainedGlassPane::GrayStainedGlassPane(true, false, false, false).ID: return 6566; case GrayStainedGlassPane::GrayStainedGlassPane(false, true, true, true).ID: return 6569; case GrayStainedGlassPane::GrayStainedGlassPane(false, true, true, false).ID: return 6570; case GrayStainedGlassPane::GrayStainedGlassPane(false, true, false, true).ID: return 6573; case GrayStainedGlassPane::GrayStainedGlassPane(false, true, false, false).ID: return 6574; case GrayStainedGlassPane::GrayStainedGlassPane(false, false, true, true).ID: return 6577; case GrayStainedGlassPane::GrayStainedGlassPane(false, false, true, false).ID: return 6578; case GrayStainedGlassPane::GrayStainedGlassPane(false, false, false, true).ID: return 6581; case GrayStainedGlassPane::GrayStainedGlassPane(false, false, false, false).ID: return 6582; case GrayTerracotta::GrayTerracotta().ID: return 6318; case GrayWallBanner::GrayWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 7645; case GrayWallBanner::GrayWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 7646; case GrayWallBanner::GrayWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 7647; case GrayWallBanner::GrayWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 7648; case GrayWool::GrayWool().ID: return 1390; case GreenBanner::GreenBanner(0).ID: return 7569; case GreenBanner::GreenBanner(1).ID: return 7570; case GreenBanner::GreenBanner(2).ID: return 7571; case GreenBanner::GreenBanner(3).ID: return 7572; case GreenBanner::GreenBanner(4).ID: return 7573; case GreenBanner::GreenBanner(5).ID: return 7574; case GreenBanner::GreenBanner(6).ID: return 7575; case GreenBanner::GreenBanner(7).ID: return 7576; case GreenBanner::GreenBanner(8).ID: return 7577; case GreenBanner::GreenBanner(9).ID: return 7578; case GreenBanner::GreenBanner(10).ID: return 7579; case GreenBanner::GreenBanner(11).ID: return 7580; case GreenBanner::GreenBanner(12).ID: return 7581; case GreenBanner::GreenBanner(13).ID: return 7582; case GreenBanner::GreenBanner(14).ID: return 7583; case GreenBanner::GreenBanner(15).ID: return 7584; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_ZM, true, GreenBed::Part::Head).ID: return 1256; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_ZM, true, GreenBed::Part::Foot).ID: return 1257; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_ZM, false, GreenBed::Part::Head).ID: return 1258; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_ZM, false, GreenBed::Part::Foot).ID: return 1259; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_ZP, true, GreenBed::Part::Head).ID: return 1260; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_ZP, true, GreenBed::Part::Foot).ID: return 1261; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_ZP, false, GreenBed::Part::Head).ID: return 1262; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_ZP, false, GreenBed::Part::Foot).ID: return 1263; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_XM, true, GreenBed::Part::Head).ID: return 1264; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_XM, true, GreenBed::Part::Foot).ID: return 1265; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_XM, false, GreenBed::Part::Head).ID: return 1266; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_XM, false, GreenBed::Part::Foot).ID: return 1267; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_XP, true, GreenBed::Part::Head).ID: return 1268; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_XP, true, GreenBed::Part::Foot).ID: return 1269; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_XP, false, GreenBed::Part::Head).ID: return 1270; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_XP, false, GreenBed::Part::Foot).ID: return 1271; case GreenCarpet::GreenCarpet().ID: return 7343; case GreenConcrete::GreenConcrete().ID: return 8915; case GreenConcretePowder::GreenConcretePowder().ID: return 8931; case GreenGlazedTerracotta::GreenGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 8890; case GreenGlazedTerracotta::GreenGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 8891; case GreenGlazedTerracotta::GreenGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 8892; case GreenGlazedTerracotta::GreenGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 8893; case GreenShulkerBox::GreenShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 8820; case GreenShulkerBox::GreenShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 8821; case GreenShulkerBox::GreenShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 8822; case GreenShulkerBox::GreenShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 8823; case GreenShulkerBox::GreenShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 8824; case GreenShulkerBox::GreenShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 8825; case GreenStainedGlass::GreenStainedGlass().ID: return 4094; case GreenStainedGlassPane::GreenStainedGlassPane(true, true, true, true).ID: return 6745; case GreenStainedGlassPane::GreenStainedGlassPane(true, true, true, false).ID: return 6746; case GreenStainedGlassPane::GreenStainedGlassPane(true, true, false, true).ID: return 6749; case GreenStainedGlassPane::GreenStainedGlassPane(true, true, false, false).ID: return 6750; case GreenStainedGlassPane::GreenStainedGlassPane(true, false, true, true).ID: return 6753; case GreenStainedGlassPane::GreenStainedGlassPane(true, false, true, false).ID: return 6754; case GreenStainedGlassPane::GreenStainedGlassPane(true, false, false, true).ID: return 6757; case GreenStainedGlassPane::GreenStainedGlassPane(true, false, false, false).ID: return 6758; case GreenStainedGlassPane::GreenStainedGlassPane(false, true, true, true).ID: return 6761; case GreenStainedGlassPane::GreenStainedGlassPane(false, true, true, false).ID: return 6762; case GreenStainedGlassPane::GreenStainedGlassPane(false, true, false, true).ID: return 6765; case GreenStainedGlassPane::GreenStainedGlassPane(false, true, false, false).ID: return 6766; case GreenStainedGlassPane::GreenStainedGlassPane(false, false, true, true).ID: return 6769; case GreenStainedGlassPane::GreenStainedGlassPane(false, false, true, false).ID: return 6770; case GreenStainedGlassPane::GreenStainedGlassPane(false, false, false, true).ID: return 6773; case GreenStainedGlassPane::GreenStainedGlassPane(false, false, false, false).ID: return 6774; case GreenTerracotta::GreenTerracotta().ID: return 6324; case GreenWallBanner::GreenWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 7669; case GreenWallBanner::GreenWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 7670; case GreenWallBanner::GreenWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 7671; case GreenWallBanner::GreenWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 7672; case GreenWool::GreenWool().ID: return 1396; case Grindstone::Grindstone(Grindstone::Face::Floor, eBlockFace::BLOCK_FACE_ZM).ID: return 11165; case Grindstone::Grindstone(Grindstone::Face::Floor, eBlockFace::BLOCK_FACE_ZP).ID: return 11166; case Grindstone::Grindstone(Grindstone::Face::Floor, eBlockFace::BLOCK_FACE_XM).ID: return 11167; case Grindstone::Grindstone(Grindstone::Face::Floor, eBlockFace::BLOCK_FACE_XP).ID: return 11168; case Grindstone::Grindstone(Grindstone::Face::Wall, eBlockFace::BLOCK_FACE_ZM).ID: return 11169; case Grindstone::Grindstone(Grindstone::Face::Wall, eBlockFace::BLOCK_FACE_ZP).ID: return 11170; case Grindstone::Grindstone(Grindstone::Face::Wall, eBlockFace::BLOCK_FACE_XM).ID: return 11171; case Grindstone::Grindstone(Grindstone::Face::Wall, eBlockFace::BLOCK_FACE_XP).ID: return 11172; case Grindstone::Grindstone(Grindstone::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM).ID: return 11173; case Grindstone::Grindstone(Grindstone::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP).ID: return 11174; case Grindstone::Grindstone(Grindstone::Face::Ceiling, eBlockFace::BLOCK_FACE_XM).ID: return 11175; case Grindstone::Grindstone(Grindstone::Face::Ceiling, eBlockFace::BLOCK_FACE_XP).ID: return 11176; case HayBale::HayBale(HayBale::Axis::X).ID: return 7327; case HayBale::HayBale(HayBale::Axis::Y).ID: return 7328; case HayBale::HayBale(HayBale::Axis::Z).ID: return 7329; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(0).ID: return 6126; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(1).ID: return 6127; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(2).ID: return 6128; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(3).ID: return 6129; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(4).ID: return 6130; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(5).ID: return 6131; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(6).ID: return 6132; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(7).ID: return 6133; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(8).ID: return 6134; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(9).ID: return 6135; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(10).ID: return 6136; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(11).ID: return 6137; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(12).ID: return 6138; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(13).ID: return 6139; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(14).ID: return 6140; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(15).ID: return 6141; case Hopper::Hopper(true, eBlockFace::BLOCK_FACE_YM).ID: return 6192; case Hopper::Hopper(true, eBlockFace::BLOCK_FACE_ZM).ID: return 6193; case Hopper::Hopper(true, eBlockFace::BLOCK_FACE_ZP).ID: return 6194; case Hopper::Hopper(true, eBlockFace::BLOCK_FACE_XM).ID: return 6195; case Hopper::Hopper(true, eBlockFace::BLOCK_FACE_XP).ID: return 6196; case Hopper::Hopper(false, eBlockFace::BLOCK_FACE_YM).ID: return 6197; case Hopper::Hopper(false, eBlockFace::BLOCK_FACE_ZM).ID: return 6198; case Hopper::Hopper(false, eBlockFace::BLOCK_FACE_ZP).ID: return 6199; case Hopper::Hopper(false, eBlockFace::BLOCK_FACE_XM).ID: return 6200; case Hopper::Hopper(false, eBlockFace::BLOCK_FACE_XP).ID: return 6201; case HornCoral::HornCoral().ID: return 9003; case HornCoralBlock::HornCoralBlock().ID: return 8983; case HornCoralFan::HornCoralFan().ID: return 9023; case HornCoralWallFan::HornCoralWallFan(eBlockFace::BLOCK_FACE_ZM).ID: return 9097; case HornCoralWallFan::HornCoralWallFan(eBlockFace::BLOCK_FACE_ZP).ID: return 9099; case HornCoralWallFan::HornCoralWallFan(eBlockFace::BLOCK_FACE_XM).ID: return 9101; case HornCoralWallFan::HornCoralWallFan(eBlockFace::BLOCK_FACE_XP).ID: return 9103; case Ice::Ice().ID: return 3927; case InfestedChiseledStoneBricks::InfestedChiseledStoneBricks().ID: return 4490; case InfestedCobblestone::InfestedCobblestone().ID: return 4486; case InfestedCrackedStoneBricks::InfestedCrackedStoneBricks().ID: return 4489; case InfestedMossyStoneBricks::InfestedMossyStoneBricks().ID: return 4488; case InfestedStone::InfestedStone().ID: return 4485; case InfestedStoneBricks::InfestedStoneBricks().ID: return 4487; case IronBars::IronBars(true, true, true, true).ID: return 4685; case IronBars::IronBars(true, true, true, false).ID: return 4686; case IronBars::IronBars(true, true, false, true).ID: return 4689; case IronBars::IronBars(true, true, false, false).ID: return 4690; case IronBars::IronBars(true, false, true, true).ID: return 4693; case IronBars::IronBars(true, false, true, false).ID: return 4694; case IronBars::IronBars(true, false, false, true).ID: return 4697; case IronBars::IronBars(true, false, false, false).ID: return 4698; case IronBars::IronBars(false, true, true, true).ID: return 4701; case IronBars::IronBars(false, true, true, false).ID: return 4702; case IronBars::IronBars(false, true, false, true).ID: return 4705; case IronBars::IronBars(false, true, false, false).ID: return 4706; case IronBars::IronBars(false, false, true, true).ID: return 4709; case IronBars::IronBars(false, false, true, false).ID: return 4710; case IronBars::IronBars(false, false, false, true).ID: return 4713; case IronBars::IronBars(false, false, false, false).ID: return 4714; case IronBlock::IronBlock().ID: return 1427; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Upper, IronDoor::Hinge::Left, true, true).ID: return 3807; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Upper, IronDoor::Hinge::Left, true, false).ID: return 3808; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Upper, IronDoor::Hinge::Left, false, true).ID: return 3809; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Upper, IronDoor::Hinge::Left, false, false).ID: return 3810; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Upper, IronDoor::Hinge::Right, true, true).ID: return 3811; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Upper, IronDoor::Hinge::Right, true, false).ID: return 3812; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Upper, IronDoor::Hinge::Right, false, true).ID: return 3813; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Upper, IronDoor::Hinge::Right, false, false).ID: return 3814; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Lower, IronDoor::Hinge::Left, true, true).ID: return 3815; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Lower, IronDoor::Hinge::Left, true, false).ID: return 3816; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Lower, IronDoor::Hinge::Left, false, true).ID: return 3817; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Lower, IronDoor::Hinge::Left, false, false).ID: return 3818; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Lower, IronDoor::Hinge::Right, true, true).ID: return 3819; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Lower, IronDoor::Hinge::Right, true, false).ID: return 3820; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Lower, IronDoor::Hinge::Right, false, true).ID: return 3821; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Lower, IronDoor::Hinge::Right, false, false).ID: return 3822; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Upper, IronDoor::Hinge::Left, true, true).ID: return 3823; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Upper, IronDoor::Hinge::Left, true, false).ID: return 3824; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Upper, IronDoor::Hinge::Left, false, true).ID: return 3825; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Upper, IronDoor::Hinge::Left, false, false).ID: return 3826; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Upper, IronDoor::Hinge::Right, true, true).ID: return 3827; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Upper, IronDoor::Hinge::Right, true, false).ID: return 3828; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Upper, IronDoor::Hinge::Right, false, true).ID: return 3829; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Upper, IronDoor::Hinge::Right, false, false).ID: return 3830; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Lower, IronDoor::Hinge::Left, true, true).ID: return 3831; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Lower, IronDoor::Hinge::Left, true, false).ID: return 3832; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Lower, IronDoor::Hinge::Left, false, true).ID: return 3833; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Lower, IronDoor::Hinge::Left, false, false).ID: return 3834; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Lower, IronDoor::Hinge::Right, true, true).ID: return 3835; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Lower, IronDoor::Hinge::Right, true, false).ID: return 3836; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Lower, IronDoor::Hinge::Right, false, true).ID: return 3837; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Lower, IronDoor::Hinge::Right, false, false).ID: return 3838; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Upper, IronDoor::Hinge::Left, true, true).ID: return 3839; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Upper, IronDoor::Hinge::Left, true, false).ID: return 3840; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Upper, IronDoor::Hinge::Left, false, true).ID: return 3841; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Upper, IronDoor::Hinge::Left, false, false).ID: return 3842; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Upper, IronDoor::Hinge::Right, true, true).ID: return 3843; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Upper, IronDoor::Hinge::Right, true, false).ID: return 3844; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Upper, IronDoor::Hinge::Right, false, true).ID: return 3845; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Upper, IronDoor::Hinge::Right, false, false).ID: return 3846; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Lower, IronDoor::Hinge::Left, true, true).ID: return 3847; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Lower, IronDoor::Hinge::Left, true, false).ID: return 3848; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Lower, IronDoor::Hinge::Left, false, true).ID: return 3849; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Lower, IronDoor::Hinge::Left, false, false).ID: return 3850; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Lower, IronDoor::Hinge::Right, true, true).ID: return 3851; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Lower, IronDoor::Hinge::Right, true, false).ID: return 3852; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Lower, IronDoor::Hinge::Right, false, true).ID: return 3853; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Lower, IronDoor::Hinge::Right, false, false).ID: return 3854; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Upper, IronDoor::Hinge::Left, true, true).ID: return 3855; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Upper, IronDoor::Hinge::Left, true, false).ID: return 3856; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Upper, IronDoor::Hinge::Left, false, true).ID: return 3857; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Upper, IronDoor::Hinge::Left, false, false).ID: return 3858; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Upper, IronDoor::Hinge::Right, true, true).ID: return 3859; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Upper, IronDoor::Hinge::Right, true, false).ID: return 3860; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Upper, IronDoor::Hinge::Right, false, true).ID: return 3861; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Upper, IronDoor::Hinge::Right, false, false).ID: return 3862; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Lower, IronDoor::Hinge::Left, true, true).ID: return 3863; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Lower, IronDoor::Hinge::Left, true, false).ID: return 3864; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Lower, IronDoor::Hinge::Left, false, true).ID: return 3865; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Lower, IronDoor::Hinge::Left, false, false).ID: return 3866; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Lower, IronDoor::Hinge::Right, true, true).ID: return 3867; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Lower, IronDoor::Hinge::Right, true, false).ID: return 3868; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Lower, IronDoor::Hinge::Right, false, true).ID: return 3869; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Lower, IronDoor::Hinge::Right, false, false).ID: return 3870; case IronOre::IronOre().ID: return 70; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZM, IronTrapdoor::Half::Top, true, true).ID: return 7002; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZM, IronTrapdoor::Half::Top, true, false).ID: return 7004; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZM, IronTrapdoor::Half::Top, false, true).ID: return 7006; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZM, IronTrapdoor::Half::Top, false, false).ID: return 7008; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZM, IronTrapdoor::Half::Bottom, true, true).ID: return 7010; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZM, IronTrapdoor::Half::Bottom, true, false).ID: return 7012; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZM, IronTrapdoor::Half::Bottom, false, true).ID: return 7014; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZM, IronTrapdoor::Half::Bottom, false, false).ID: return 7016; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZP, IronTrapdoor::Half::Top, true, true).ID: return 7018; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZP, IronTrapdoor::Half::Top, true, false).ID: return 7020; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZP, IronTrapdoor::Half::Top, false, true).ID: return 7022; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZP, IronTrapdoor::Half::Top, false, false).ID: return 7024; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZP, IronTrapdoor::Half::Bottom, true, true).ID: return 7026; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZP, IronTrapdoor::Half::Bottom, true, false).ID: return 7028; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZP, IronTrapdoor::Half::Bottom, false, true).ID: return 7030; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZP, IronTrapdoor::Half::Bottom, false, false).ID: return 7032; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XM, IronTrapdoor::Half::Top, true, true).ID: return 7034; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XM, IronTrapdoor::Half::Top, true, false).ID: return 7036; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XM, IronTrapdoor::Half::Top, false, true).ID: return 7038; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XM, IronTrapdoor::Half::Top, false, false).ID: return 7040; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XM, IronTrapdoor::Half::Bottom, true, true).ID: return 7042; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XM, IronTrapdoor::Half::Bottom, true, false).ID: return 7044; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XM, IronTrapdoor::Half::Bottom, false, true).ID: return 7046; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XM, IronTrapdoor::Half::Bottom, false, false).ID: return 7048; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XP, IronTrapdoor::Half::Top, true, true).ID: return 7050; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XP, IronTrapdoor::Half::Top, true, false).ID: return 7052; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XP, IronTrapdoor::Half::Top, false, true).ID: return 7054; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XP, IronTrapdoor::Half::Top, false, false).ID: return 7056; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XP, IronTrapdoor::Half::Bottom, true, true).ID: return 7058; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XP, IronTrapdoor::Half::Bottom, true, false).ID: return 7060; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XP, IronTrapdoor::Half::Bottom, false, true).ID: return 7062; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XP, IronTrapdoor::Half::Bottom, false, false).ID: return 7064; case JackOLantern::JackOLantern(eBlockFace::BLOCK_FACE_ZM).ID: return 4006; case JackOLantern::JackOLantern(eBlockFace::BLOCK_FACE_ZP).ID: return 4007; case JackOLantern::JackOLantern(eBlockFace::BLOCK_FACE_XM).ID: return 4008; case JackOLantern::JackOLantern(eBlockFace::BLOCK_FACE_XP).ID: return 4009; case Jigsaw::Jigsaw(Jigsaw::Orientation::NorthUp).ID: return 11256; case Jigsaw::Jigsaw(Jigsaw::Orientation::EastUp).ID: return 11257; case Jigsaw::Jigsaw(Jigsaw::Orientation::SouthUp).ID: return 11258; case Jigsaw::Jigsaw(Jigsaw::Orientation::WestUp).ID: return 11259; case Jigsaw::Jigsaw(Jigsaw::Orientation::UpSouth).ID: return 11260; case Jigsaw::Jigsaw(Jigsaw::Orientation::DownSouth).ID: return 11261; case Jukebox::Jukebox(true).ID: return 3962; case Jukebox::Jukebox(false).ID: return 3963; case JungleButton::JungleButton(JungleButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5882; case JungleButton::JungleButton(JungleButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5883; case JungleButton::JungleButton(JungleButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5884; case JungleButton::JungleButton(JungleButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5885; case JungleButton::JungleButton(JungleButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, true).ID: return 5886; case JungleButton::JungleButton(JungleButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, false).ID: return 5887; case JungleButton::JungleButton(JungleButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, true).ID: return 5888; case JungleButton::JungleButton(JungleButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, false).ID: return 5889; case JungleButton::JungleButton(JungleButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5890; case JungleButton::JungleButton(JungleButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5891; case JungleButton::JungleButton(JungleButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5892; case JungleButton::JungleButton(JungleButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5893; case JungleButton::JungleButton(JungleButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, true).ID: return 5894; case JungleButton::JungleButton(JungleButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, false).ID: return 5895; case JungleButton::JungleButton(JungleButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, true).ID: return 5896; case JungleButton::JungleButton(JungleButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, false).ID: return 5897; case JungleButton::JungleButton(JungleButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5898; case JungleButton::JungleButton(JungleButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5899; case JungleButton::JungleButton(JungleButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5900; case JungleButton::JungleButton(JungleButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5901; case JungleButton::JungleButton(JungleButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, true).ID: return 5902; case JungleButton::JungleButton(JungleButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, false).ID: return 5903; case JungleButton::JungleButton(JungleButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, true).ID: return 5904; case JungleButton::JungleButton(JungleButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, false).ID: return 5905; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, true, true).ID: return 8330; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, true, false).ID: return 8331; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, false, true).ID: return 8332; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, false, false).ID: return 8333; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, true, true).ID: return 8334; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, true, false).ID: return 8335; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, false, true).ID: return 8336; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, false, false).ID: return 8337; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, true, true).ID: return 8338; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, true, false).ID: return 8339; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, false, true).ID: return 8340; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, false, false).ID: return 8341; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, true, true).ID: return 8342; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, true, false).ID: return 8343; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, false, true).ID: return 8344; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, false, false).ID: return 8345; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, true, true).ID: return 8346; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, true, false).ID: return 8347; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, false, true).ID: return 8348; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, false, false).ID: return 8349; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, true, true).ID: return 8350; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, true, false).ID: return 8351; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, false, true).ID: return 8352; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, false, false).ID: return 8353; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, true, true).ID: return 8354; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, true, false).ID: return 8355; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, false, true).ID: return 8356; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, false, false).ID: return 8357; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, true, true).ID: return 8358; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, true, false).ID: return 8359; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, false, true).ID: return 8360; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, false, false).ID: return 8361; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, true, true).ID: return 8362; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, true, false).ID: return 8363; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, false, true).ID: return 8364; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, false, false).ID: return 8365; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, true, true).ID: return 8366; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, true, false).ID: return 8367; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, false, true).ID: return 8368; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, false, false).ID: return 8369; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, true, true).ID: return 8370; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, true, false).ID: return 8371; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, false, true).ID: return 8372; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, false, false).ID: return 8373; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, true, true).ID: return 8374; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, true, false).ID: return 8375; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, false, true).ID: return 8376; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, false, false).ID: return 8377; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, true, true).ID: return 8378; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, true, false).ID: return 8379; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, false, true).ID: return 8380; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, false, false).ID: return 8381; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, true, true).ID: return 8382; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, true, false).ID: return 8383; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, false, true).ID: return 8384; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, false, false).ID: return 8385; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, true, true).ID: return 8386; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, true, false).ID: return 8387; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, false, true).ID: return 8388; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, false, false).ID: return 8389; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, true, true).ID: return 8390; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, true, false).ID: return 8391; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, false, true).ID: return 8392; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, false, false).ID: return 8393; case JungleFence::JungleFence(true, true, true, true).ID: return 8108; case JungleFence::JungleFence(true, true, true, false).ID: return 8109; case JungleFence::JungleFence(true, true, false, true).ID: return 8112; case JungleFence::JungleFence(true, true, false, false).ID: return 8113; case JungleFence::JungleFence(true, false, true, true).ID: return 8116; case JungleFence::JungleFence(true, false, true, false).ID: return 8117; case JungleFence::JungleFence(true, false, false, true).ID: return 8120; case JungleFence::JungleFence(true, false, false, false).ID: return 8121; case JungleFence::JungleFence(false, true, true, true).ID: return 8124; case JungleFence::JungleFence(false, true, true, false).ID: return 8125; case JungleFence::JungleFence(false, true, false, true).ID: return 8128; case JungleFence::JungleFence(false, true, false, false).ID: return 8129; case JungleFence::JungleFence(false, false, true, true).ID: return 8132; case JungleFence::JungleFence(false, false, true, false).ID: return 8133; case JungleFence::JungleFence(false, false, false, true).ID: return 8136; case JungleFence::JungleFence(false, false, false, false).ID: return 8137; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZM, true, true, true).ID: return 7946; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZM, true, true, false).ID: return 7947; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZM, true, false, true).ID: return 7948; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZM, true, false, false).ID: return 7949; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, true).ID: return 7950; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, false).ID: return 7951; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, true).ID: return 7952; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, false).ID: return 7953; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZP, true, true, true).ID: return 7954; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZP, true, true, false).ID: return 7955; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZP, true, false, true).ID: return 7956; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZP, true, false, false).ID: return 7957; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, true).ID: return 7958; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, false).ID: return 7959; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, true).ID: return 7960; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, false).ID: return 7961; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XM, true, true, true).ID: return 7962; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XM, true, true, false).ID: return 7963; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XM, true, false, true).ID: return 7964; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XM, true, false, false).ID: return 7965; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, true).ID: return 7966; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, false).ID: return 7967; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, true).ID: return 7968; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, false).ID: return 7969; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XP, true, true, true).ID: return 7970; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XP, true, true, false).ID: return 7971; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XP, true, false, true).ID: return 7972; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XP, true, false, false).ID: return 7973; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, true).ID: return 7974; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, false).ID: return 7975; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, true).ID: return 7976; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, false).ID: return 7977; case JungleLeaves::JungleLeaves(1, true).ID: return 186; case JungleLeaves::JungleLeaves(1, false).ID: return 187; case JungleLeaves::JungleLeaves(2, true).ID: return 188; case JungleLeaves::JungleLeaves(2, false).ID: return 189; case JungleLeaves::JungleLeaves(3, true).ID: return 190; case JungleLeaves::JungleLeaves(3, false).ID: return 191; case JungleLeaves::JungleLeaves(4, true).ID: return 192; case JungleLeaves::JungleLeaves(4, false).ID: return 193; case JungleLeaves::JungleLeaves(5, true).ID: return 194; case JungleLeaves::JungleLeaves(5, false).ID: return 195; case JungleLeaves::JungleLeaves(6, true).ID: return 196; case JungleLeaves::JungleLeaves(6, false).ID: return 197; case JungleLeaves::JungleLeaves(7, true).ID: return 198; case JungleLeaves::JungleLeaves(7, false).ID: return 199; case JungleLog::JungleLog(JungleLog::Axis::X).ID: return 81; case JungleLog::JungleLog(JungleLog::Axis::Y).ID: return 82; case JungleLog::JungleLog(JungleLog::Axis::Z).ID: return 83; case JunglePlanks::JunglePlanks().ID: return 18; case JunglePressurePlate::JunglePressurePlate(true).ID: return 3877; case JunglePressurePlate::JunglePressurePlate(false).ID: return 3878; case JungleSapling::JungleSapling(0).ID: return 27; case JungleSapling::JungleSapling(1).ID: return 28; case JungleSign::JungleSign(0).ID: return 3508; case JungleSign::JungleSign(1).ID: return 3510; case JungleSign::JungleSign(2).ID: return 3512; case JungleSign::JungleSign(3).ID: return 3514; case JungleSign::JungleSign(4).ID: return 3516; case JungleSign::JungleSign(5).ID: return 3518; case JungleSign::JungleSign(6).ID: return 3520; case JungleSign::JungleSign(7).ID: return 3522; case JungleSign::JungleSign(8).ID: return 3524; case JungleSign::JungleSign(9).ID: return 3526; case JungleSign::JungleSign(10).ID: return 3528; case JungleSign::JungleSign(11).ID: return 3530; case JungleSign::JungleSign(12).ID: return 3532; case JungleSign::JungleSign(13).ID: return 3534; case JungleSign::JungleSign(14).ID: return 3536; case JungleSign::JungleSign(15).ID: return 3538; case JungleSlab::JungleSlab(JungleSlab::Type::Top).ID: return 7783; case JungleSlab::JungleSlab(JungleSlab::Type::Bottom).ID: return 7785; case JungleSlab::JungleSlab(JungleSlab::Type::Double).ID: return 7787; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZM, JungleStairs::Half::Top, JungleStairs::Shape::Straight).ID: return 5549; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZM, JungleStairs::Half::Top, JungleStairs::Shape::InnerLeft).ID: return 5551; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZM, JungleStairs::Half::Top, JungleStairs::Shape::InnerRight).ID: return 5553; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZM, JungleStairs::Half::Top, JungleStairs::Shape::OuterLeft).ID: return 5555; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZM, JungleStairs::Half::Top, JungleStairs::Shape::OuterRight).ID: return 5557; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZM, JungleStairs::Half::Bottom, JungleStairs::Shape::Straight).ID: return 5559; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZM, JungleStairs::Half::Bottom, JungleStairs::Shape::InnerLeft).ID: return 5561; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZM, JungleStairs::Half::Bottom, JungleStairs::Shape::InnerRight).ID: return 5563; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZM, JungleStairs::Half::Bottom, JungleStairs::Shape::OuterLeft).ID: return 5565; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZM, JungleStairs::Half::Bottom, JungleStairs::Shape::OuterRight).ID: return 5567; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZP, JungleStairs::Half::Top, JungleStairs::Shape::Straight).ID: return 5569; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZP, JungleStairs::Half::Top, JungleStairs::Shape::InnerLeft).ID: return 5571; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZP, JungleStairs::Half::Top, JungleStairs::Shape::InnerRight).ID: return 5573; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZP, JungleStairs::Half::Top, JungleStairs::Shape::OuterLeft).ID: return 5575; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZP, JungleStairs::Half::Top, JungleStairs::Shape::OuterRight).ID: return 5577; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZP, JungleStairs::Half::Bottom, JungleStairs::Shape::Straight).ID: return 5579; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZP, JungleStairs::Half::Bottom, JungleStairs::Shape::InnerLeft).ID: return 5581; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZP, JungleStairs::Half::Bottom, JungleStairs::Shape::InnerRight).ID: return 5583; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZP, JungleStairs::Half::Bottom, JungleStairs::Shape::OuterLeft).ID: return 5585; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZP, JungleStairs::Half::Bottom, JungleStairs::Shape::OuterRight).ID: return 5587; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XM, JungleStairs::Half::Top, JungleStairs::Shape::Straight).ID: return 5589; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XM, JungleStairs::Half::Top, JungleStairs::Shape::InnerLeft).ID: return 5591; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XM, JungleStairs::Half::Top, JungleStairs::Shape::InnerRight).ID: return 5593; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XM, JungleStairs::Half::Top, JungleStairs::Shape::OuterLeft).ID: return 5595; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XM, JungleStairs::Half::Top, JungleStairs::Shape::OuterRight).ID: return 5597; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XM, JungleStairs::Half::Bottom, JungleStairs::Shape::Straight).ID: return 5599; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XM, JungleStairs::Half::Bottom, JungleStairs::Shape::InnerLeft).ID: return 5601; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XM, JungleStairs::Half::Bottom, JungleStairs::Shape::InnerRight).ID: return 5603; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XM, JungleStairs::Half::Bottom, JungleStairs::Shape::OuterLeft).ID: return 5605; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XM, JungleStairs::Half::Bottom, JungleStairs::Shape::OuterRight).ID: return 5607; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XP, JungleStairs::Half::Top, JungleStairs::Shape::Straight).ID: return 5609; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XP, JungleStairs::Half::Top, JungleStairs::Shape::InnerLeft).ID: return 5611; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XP, JungleStairs::Half::Top, JungleStairs::Shape::InnerRight).ID: return 5613; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XP, JungleStairs::Half::Top, JungleStairs::Shape::OuterLeft).ID: return 5615; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XP, JungleStairs::Half::Top, JungleStairs::Shape::OuterRight).ID: return 5617; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XP, JungleStairs::Half::Bottom, JungleStairs::Shape::Straight).ID: return 5619; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XP, JungleStairs::Half::Bottom, JungleStairs::Shape::InnerLeft).ID: return 5621; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XP, JungleStairs::Half::Bottom, JungleStairs::Shape::InnerRight).ID: return 5623; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XP, JungleStairs::Half::Bottom, JungleStairs::Shape::OuterLeft).ID: return 5625; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XP, JungleStairs::Half::Bottom, JungleStairs::Shape::OuterRight).ID: return 5627; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZM, JungleTrapdoor::Half::Top, true, true).ID: return 4290; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZM, JungleTrapdoor::Half::Top, true, false).ID: return 4292; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZM, JungleTrapdoor::Half::Top, false, true).ID: return 4294; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZM, JungleTrapdoor::Half::Top, false, false).ID: return 4296; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZM, JungleTrapdoor::Half::Bottom, true, true).ID: return 4298; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZM, JungleTrapdoor::Half::Bottom, true, false).ID: return 4300; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZM, JungleTrapdoor::Half::Bottom, false, true).ID: return 4302; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZM, JungleTrapdoor::Half::Bottom, false, false).ID: return 4304; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZP, JungleTrapdoor::Half::Top, true, true).ID: return 4306; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZP, JungleTrapdoor::Half::Top, true, false).ID: return 4308; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZP, JungleTrapdoor::Half::Top, false, true).ID: return 4310; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZP, JungleTrapdoor::Half::Top, false, false).ID: return 4312; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZP, JungleTrapdoor::Half::Bottom, true, true).ID: return 4314; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZP, JungleTrapdoor::Half::Bottom, true, false).ID: return 4316; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZP, JungleTrapdoor::Half::Bottom, false, true).ID: return 4318; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZP, JungleTrapdoor::Half::Bottom, false, false).ID: return 4320; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XM, JungleTrapdoor::Half::Top, true, true).ID: return 4322; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XM, JungleTrapdoor::Half::Top, true, false).ID: return 4324; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XM, JungleTrapdoor::Half::Top, false, true).ID: return 4326; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XM, JungleTrapdoor::Half::Top, false, false).ID: return 4328; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XM, JungleTrapdoor::Half::Bottom, true, true).ID: return 4330; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XM, JungleTrapdoor::Half::Bottom, true, false).ID: return 4332; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XM, JungleTrapdoor::Half::Bottom, false, true).ID: return 4334; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XM, JungleTrapdoor::Half::Bottom, false, false).ID: return 4336; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XP, JungleTrapdoor::Half::Top, true, true).ID: return 4338; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XP, JungleTrapdoor::Half::Top, true, false).ID: return 4340; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XP, JungleTrapdoor::Half::Top, false, true).ID: return 4342; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XP, JungleTrapdoor::Half::Top, false, false).ID: return 4344; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XP, JungleTrapdoor::Half::Bottom, true, true).ID: return 4346; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XP, JungleTrapdoor::Half::Bottom, true, false).ID: return 4348; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XP, JungleTrapdoor::Half::Bottom, false, true).ID: return 4350; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XP, JungleTrapdoor::Half::Bottom, false, false).ID: return 4352; case JungleWallSign::JungleWallSign(eBlockFace::BLOCK_FACE_ZM).ID: return 3766; case JungleWallSign::JungleWallSign(eBlockFace::BLOCK_FACE_ZP).ID: return 3768; case JungleWallSign::JungleWallSign(eBlockFace::BLOCK_FACE_XM).ID: return 3770; case JungleWallSign::JungleWallSign(eBlockFace::BLOCK_FACE_XP).ID: return 3772; case JungleWood::JungleWood(JungleWood::Axis::X).ID: return 117; case JungleWood::JungleWood(JungleWood::Axis::Y).ID: return 118; case JungleWood::JungleWood(JungleWood::Axis::Z).ID: return 119; case Kelp::Kelp(0).ID: return 8934; case Kelp::Kelp(1).ID: return 8935; case Kelp::Kelp(2).ID: return 8936; case Kelp::Kelp(3).ID: return 8937; case Kelp::Kelp(4).ID: return 8938; case Kelp::Kelp(5).ID: return 8939; case Kelp::Kelp(6).ID: return 8940; case Kelp::Kelp(7).ID: return 8941; case Kelp::Kelp(8).ID: return 8942; case Kelp::Kelp(9).ID: return 8943; case Kelp::Kelp(10).ID: return 8944; case Kelp::Kelp(11).ID: return 8945; case Kelp::Kelp(12).ID: return 8946; case Kelp::Kelp(13).ID: return 8947; case Kelp::Kelp(14).ID: return 8948; case Kelp::Kelp(15).ID: return 8949; case Kelp::Kelp(16).ID: return 8950; case Kelp::Kelp(17).ID: return 8951; case Kelp::Kelp(18).ID: return 8952; case Kelp::Kelp(19).ID: return 8953; case Kelp::Kelp(20).ID: return 8954; case Kelp::Kelp(21).ID: return 8955; case Kelp::Kelp(22).ID: return 8956; case Kelp::Kelp(23).ID: return 8957; case Kelp::Kelp(24).ID: return 8958; case Kelp::Kelp(25).ID: return 8959; case KelpPlant::KelpPlant().ID: return 8960; case Ladder::Ladder(eBlockFace::BLOCK_FACE_ZM).ID: return 3636; case Ladder::Ladder(eBlockFace::BLOCK_FACE_ZP).ID: return 3638; case Ladder::Ladder(eBlockFace::BLOCK_FACE_XM).ID: return 3640; case Ladder::Ladder(eBlockFace::BLOCK_FACE_XP).ID: return 3642; case Lantern::Lantern(true).ID: return 11214; case Lantern::Lantern(false).ID: return 11215; case LapisBlock::LapisBlock().ID: return 232; case LapisOre::LapisOre().ID: return 231; case LargeFern::LargeFern(LargeFern::Half::Upper).ID: return 7359; case LargeFern::LargeFern(LargeFern::Half::Lower).ID: return 7360; case Lava::Lava(0).ID: return 50; case Lava::Lava(1).ID: return 51; case Lava::Lava(2).ID: return 52; case Lava::Lava(3).ID: return 53; case Lava::Lava(4).ID: return 54; case Lava::Lava(5).ID: return 55; case Lava::Lava(6).ID: return 56; case Lava::Lava(7).ID: return 57; case Lava::Lava(8).ID: return 58; case Lava::Lava(9).ID: return 59; case Lava::Lava(10).ID: return 60; case Lava::Lava(11).ID: return 61; case Lava::Lava(12).ID: return 62; case Lava::Lava(13).ID: return 63; case Lava::Lava(14).ID: return 64; case Lava::Lava(15).ID: return 65; case Lectern::Lectern(eBlockFace::BLOCK_FACE_ZM, true, true).ID: return 11177; case Lectern::Lectern(eBlockFace::BLOCK_FACE_ZM, true, false).ID: return 11178; case Lectern::Lectern(eBlockFace::BLOCK_FACE_ZM, false, true).ID: return 11179; case Lectern::Lectern(eBlockFace::BLOCK_FACE_ZM, false, false).ID: return 11180; case Lectern::Lectern(eBlockFace::BLOCK_FACE_ZP, true, true).ID: return 11181; case Lectern::Lectern(eBlockFace::BLOCK_FACE_ZP, true, false).ID: return 11182; case Lectern::Lectern(eBlockFace::BLOCK_FACE_ZP, false, true).ID: return 11183; case Lectern::Lectern(eBlockFace::BLOCK_FACE_ZP, false, false).ID: return 11184; case Lectern::Lectern(eBlockFace::BLOCK_FACE_XM, true, true).ID: return 11185; case Lectern::Lectern(eBlockFace::BLOCK_FACE_XM, true, false).ID: return 11186; case Lectern::Lectern(eBlockFace::BLOCK_FACE_XM, false, true).ID: return 11187; case Lectern::Lectern(eBlockFace::BLOCK_FACE_XM, false, false).ID: return 11188; case Lectern::Lectern(eBlockFace::BLOCK_FACE_XP, true, true).ID: return 11189; case Lectern::Lectern(eBlockFace::BLOCK_FACE_XP, true, false).ID: return 11190; case Lectern::Lectern(eBlockFace::BLOCK_FACE_XP, false, true).ID: return 11191; case Lectern::Lectern(eBlockFace::BLOCK_FACE_XP, false, false).ID: return 11192; case Lever::Lever(Lever::Face::Floor, eBlockFace::BLOCK_FACE_ZM, true).ID: return 3781; case Lever::Lever(Lever::Face::Floor, eBlockFace::BLOCK_FACE_ZM, false).ID: return 3782; case Lever::Lever(Lever::Face::Floor, eBlockFace::BLOCK_FACE_ZP, true).ID: return 3783; case Lever::Lever(Lever::Face::Floor, eBlockFace::BLOCK_FACE_ZP, false).ID: return 3784; case Lever::Lever(Lever::Face::Floor, eBlockFace::BLOCK_FACE_XM, true).ID: return 3785; case Lever::Lever(Lever::Face::Floor, eBlockFace::BLOCK_FACE_XM, false).ID: return 3786; case Lever::Lever(Lever::Face::Floor, eBlockFace::BLOCK_FACE_XP, true).ID: return 3787; case Lever::Lever(Lever::Face::Floor, eBlockFace::BLOCK_FACE_XP, false).ID: return 3788; case Lever::Lever(Lever::Face::Wall, eBlockFace::BLOCK_FACE_ZM, true).ID: return 3789; case Lever::Lever(Lever::Face::Wall, eBlockFace::BLOCK_FACE_ZM, false).ID: return 3790; case Lever::Lever(Lever::Face::Wall, eBlockFace::BLOCK_FACE_ZP, true).ID: return 3791; case Lever::Lever(Lever::Face::Wall, eBlockFace::BLOCK_FACE_ZP, false).ID: return 3792; case Lever::Lever(Lever::Face::Wall, eBlockFace::BLOCK_FACE_XM, true).ID: return 3793; case Lever::Lever(Lever::Face::Wall, eBlockFace::BLOCK_FACE_XM, false).ID: return 3794; case Lever::Lever(Lever::Face::Wall, eBlockFace::BLOCK_FACE_XP, true).ID: return 3795; case Lever::Lever(Lever::Face::Wall, eBlockFace::BLOCK_FACE_XP, false).ID: return 3796; case Lever::Lever(Lever::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, true).ID: return 3797; case Lever::Lever(Lever::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, false).ID: return 3798; case Lever::Lever(Lever::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, true).ID: return 3799; case Lever::Lever(Lever::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, false).ID: return 3800; case Lever::Lever(Lever::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, true).ID: return 3801; case Lever::Lever(Lever::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, false).ID: return 3802; case Lever::Lever(Lever::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, true).ID: return 3803; case Lever::Lever(Lever::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, false).ID: return 3804; case LightBlueBanner::LightBlueBanner(0).ID: return 7409; case LightBlueBanner::LightBlueBanner(1).ID: return 7410; case LightBlueBanner::LightBlueBanner(2).ID: return 7411; case LightBlueBanner::LightBlueBanner(3).ID: return 7412; case LightBlueBanner::LightBlueBanner(4).ID: return 7413; case LightBlueBanner::LightBlueBanner(5).ID: return 7414; case LightBlueBanner::LightBlueBanner(6).ID: return 7415; case LightBlueBanner::LightBlueBanner(7).ID: return 7416; case LightBlueBanner::LightBlueBanner(8).ID: return 7417; case LightBlueBanner::LightBlueBanner(9).ID: return 7418; case LightBlueBanner::LightBlueBanner(10).ID: return 7419; case LightBlueBanner::LightBlueBanner(11).ID: return 7420; case LightBlueBanner::LightBlueBanner(12).ID: return 7421; case LightBlueBanner::LightBlueBanner(13).ID: return 7422; case LightBlueBanner::LightBlueBanner(14).ID: return 7423; case LightBlueBanner::LightBlueBanner(15).ID: return 7424; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_ZM, true, LightBlueBed::Part::Head).ID: return 1096; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_ZM, true, LightBlueBed::Part::Foot).ID: return 1097; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_ZM, false, LightBlueBed::Part::Head).ID: return 1098; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_ZM, false, LightBlueBed::Part::Foot).ID: return 1099; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_ZP, true, LightBlueBed::Part::Head).ID: return 1100; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_ZP, true, LightBlueBed::Part::Foot).ID: return 1101; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_ZP, false, LightBlueBed::Part::Head).ID: return 1102; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_ZP, false, LightBlueBed::Part::Foot).ID: return 1103; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_XM, true, LightBlueBed::Part::Head).ID: return 1104; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_XM, true, LightBlueBed::Part::Foot).ID: return 1105; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_XM, false, LightBlueBed::Part::Head).ID: return 1106; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_XM, false, LightBlueBed::Part::Foot).ID: return 1107; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_XP, true, LightBlueBed::Part::Head).ID: return 1108; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_XP, true, LightBlueBed::Part::Foot).ID: return 1109; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_XP, false, LightBlueBed::Part::Head).ID: return 1110; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_XP, false, LightBlueBed::Part::Foot).ID: return 1111; case LightBlueCarpet::LightBlueCarpet().ID: return 7333; case LightBlueConcrete::LightBlueConcrete().ID: return 8905; case LightBlueConcretePowder::LightBlueConcretePowder().ID: return 8921; case LightBlueGlazedTerracotta::LightBlueGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 8850; case LightBlueGlazedTerracotta::LightBlueGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 8851; case LightBlueGlazedTerracotta::LightBlueGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 8852; case LightBlueGlazedTerracotta::LightBlueGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 8853; case LightBlueShulkerBox::LightBlueShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 8760; case LightBlueShulkerBox::LightBlueShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 8761; case LightBlueShulkerBox::LightBlueShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 8762; case LightBlueShulkerBox::LightBlueShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 8763; case LightBlueShulkerBox::LightBlueShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 8764; case LightBlueShulkerBox::LightBlueShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 8765; case LightBlueStainedGlass::LightBlueStainedGlass().ID: return 4084; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(true, true, true, true).ID: return 6425; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(true, true, true, false).ID: return 6426; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(true, true, false, true).ID: return 6429; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(true, true, false, false).ID: return 6430; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(true, false, true, true).ID: return 6433; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(true, false, true, false).ID: return 6434; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(true, false, false, true).ID: return 6437; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(true, false, false, false).ID: return 6438; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(false, true, true, true).ID: return 6441; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(false, true, true, false).ID: return 6442; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(false, true, false, true).ID: return 6445; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(false, true, false, false).ID: return 6446; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(false, false, true, true).ID: return 6449; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(false, false, true, false).ID: return 6450; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(false, false, false, true).ID: return 6453; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(false, false, false, false).ID: return 6454; case LightBlueTerracotta::LightBlueTerracotta().ID: return 6314; case LightBlueWallBanner::LightBlueWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 7629; case LightBlueWallBanner::LightBlueWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 7630; case LightBlueWallBanner::LightBlueWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 7631; case LightBlueWallBanner::LightBlueWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 7632; case LightBlueWool::LightBlueWool().ID: return 1386; case LightGrayBanner::LightGrayBanner(0).ID: return 7489; case LightGrayBanner::LightGrayBanner(1).ID: return 7490; case LightGrayBanner::LightGrayBanner(2).ID: return 7491; case LightGrayBanner::LightGrayBanner(3).ID: return 7492; case LightGrayBanner::LightGrayBanner(4).ID: return 7493; case LightGrayBanner::LightGrayBanner(5).ID: return 7494; case LightGrayBanner::LightGrayBanner(6).ID: return 7495; case LightGrayBanner::LightGrayBanner(7).ID: return 7496; case LightGrayBanner::LightGrayBanner(8).ID: return 7497; case LightGrayBanner::LightGrayBanner(9).ID: return 7498; case LightGrayBanner::LightGrayBanner(10).ID: return 7499; case LightGrayBanner::LightGrayBanner(11).ID: return 7500; case LightGrayBanner::LightGrayBanner(12).ID: return 7501; case LightGrayBanner::LightGrayBanner(13).ID: return 7502; case LightGrayBanner::LightGrayBanner(14).ID: return 7503; case LightGrayBanner::LightGrayBanner(15).ID: return 7504; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_ZM, true, LightGrayBed::Part::Head).ID: return 1176; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_ZM, true, LightGrayBed::Part::Foot).ID: return 1177; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_ZM, false, LightGrayBed::Part::Head).ID: return 1178; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_ZM, false, LightGrayBed::Part::Foot).ID: return 1179; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_ZP, true, LightGrayBed::Part::Head).ID: return 1180; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_ZP, true, LightGrayBed::Part::Foot).ID: return 1181; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_ZP, false, LightGrayBed::Part::Head).ID: return 1182; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_ZP, false, LightGrayBed::Part::Foot).ID: return 1183; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_XM, true, LightGrayBed::Part::Head).ID: return 1184; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_XM, true, LightGrayBed::Part::Foot).ID: return 1185; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_XM, false, LightGrayBed::Part::Head).ID: return 1186; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_XM, false, LightGrayBed::Part::Foot).ID: return 1187; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_XP, true, LightGrayBed::Part::Head).ID: return 1188; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_XP, true, LightGrayBed::Part::Foot).ID: return 1189; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_XP, false, LightGrayBed::Part::Head).ID: return 1190; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_XP, false, LightGrayBed::Part::Foot).ID: return 1191; case LightGrayCarpet::LightGrayCarpet().ID: return 7338; case LightGrayConcrete::LightGrayConcrete().ID: return 8910; case LightGrayConcretePowder::LightGrayConcretePowder().ID: return 8926; case LightGrayGlazedTerracotta::LightGrayGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 8870; case LightGrayGlazedTerracotta::LightGrayGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 8871; case LightGrayGlazedTerracotta::LightGrayGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 8872; case LightGrayGlazedTerracotta::LightGrayGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 8873; case LightGrayShulkerBox::LightGrayShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 8790; case LightGrayShulkerBox::LightGrayShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 8791; case LightGrayShulkerBox::LightGrayShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 8792; case LightGrayShulkerBox::LightGrayShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 8793; case LightGrayShulkerBox::LightGrayShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 8794; case LightGrayShulkerBox::LightGrayShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 8795; case LightGrayStainedGlass::LightGrayStainedGlass().ID: return 4089; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(true, true, true, true).ID: return 6585; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(true, true, true, false).ID: return 6586; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(true, true, false, true).ID: return 6589; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(true, true, false, false).ID: return 6590; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(true, false, true, true).ID: return 6593; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(true, false, true, false).ID: return 6594; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(true, false, false, true).ID: return 6597; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(true, false, false, false).ID: return 6598; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(false, true, true, true).ID: return 6601; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(false, true, true, false).ID: return 6602; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(false, true, false, true).ID: return 6605; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(false, true, false, false).ID: return 6606; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(false, false, true, true).ID: return 6609; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(false, false, true, false).ID: return 6610; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(false, false, false, true).ID: return 6613; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(false, false, false, false).ID: return 6614; case LightGrayTerracotta::LightGrayTerracotta().ID: return 6319; case LightGrayWallBanner::LightGrayWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 7649; case LightGrayWallBanner::LightGrayWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 7650; case LightGrayWallBanner::LightGrayWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 7651; case LightGrayWallBanner::LightGrayWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 7652; case LightGrayWool::LightGrayWool().ID: return 1391; case LightWeightedPressurePlate::LightWeightedPressurePlate(0).ID: return 6110; case LightWeightedPressurePlate::LightWeightedPressurePlate(1).ID: return 6111; case LightWeightedPressurePlate::LightWeightedPressurePlate(2).ID: return 6112; case LightWeightedPressurePlate::LightWeightedPressurePlate(3).ID: return 6113; case LightWeightedPressurePlate::LightWeightedPressurePlate(4).ID: return 6114; case LightWeightedPressurePlate::LightWeightedPressurePlate(5).ID: return 6115; case LightWeightedPressurePlate::LightWeightedPressurePlate(6).ID: return 6116; case LightWeightedPressurePlate::LightWeightedPressurePlate(7).ID: return 6117; case LightWeightedPressurePlate::LightWeightedPressurePlate(8).ID: return 6118; case LightWeightedPressurePlate::LightWeightedPressurePlate(9).ID: return 6119; case LightWeightedPressurePlate::LightWeightedPressurePlate(10).ID: return 6120; case LightWeightedPressurePlate::LightWeightedPressurePlate(11).ID: return 6121; case LightWeightedPressurePlate::LightWeightedPressurePlate(12).ID: return 6122; case LightWeightedPressurePlate::LightWeightedPressurePlate(13).ID: return 6123; case LightWeightedPressurePlate::LightWeightedPressurePlate(14).ID: return 6124; case LightWeightedPressurePlate::LightWeightedPressurePlate(15).ID: return 6125; case Lilac::Lilac(Lilac::Half::Upper).ID: return 7351; case Lilac::Lilac(Lilac::Half::Lower).ID: return 7352; case LilyOfTheValley::LilyOfTheValley().ID: return 1423; case LilyPad::LilyPad().ID: return 4998; case LimeBanner::LimeBanner(0).ID: return 7441; case LimeBanner::LimeBanner(1).ID: return 7442; case LimeBanner::LimeBanner(2).ID: return 7443; case LimeBanner::LimeBanner(3).ID: return 7444; case LimeBanner::LimeBanner(4).ID: return 7445; case LimeBanner::LimeBanner(5).ID: return 7446; case LimeBanner::LimeBanner(6).ID: return 7447; case LimeBanner::LimeBanner(7).ID: return 7448; case LimeBanner::LimeBanner(8).ID: return 7449; case LimeBanner::LimeBanner(9).ID: return 7450; case LimeBanner::LimeBanner(10).ID: return 7451; case LimeBanner::LimeBanner(11).ID: return 7452; case LimeBanner::LimeBanner(12).ID: return 7453; case LimeBanner::LimeBanner(13).ID: return 7454; case LimeBanner::LimeBanner(14).ID: return 7455; case LimeBanner::LimeBanner(15).ID: return 7456; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_ZM, true, LimeBed::Part::Head).ID: return 1128; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_ZM, true, LimeBed::Part::Foot).ID: return 1129; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_ZM, false, LimeBed::Part::Head).ID: return 1130; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_ZM, false, LimeBed::Part::Foot).ID: return 1131; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_ZP, true, LimeBed::Part::Head).ID: return 1132; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_ZP, true, LimeBed::Part::Foot).ID: return 1133; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_ZP, false, LimeBed::Part::Head).ID: return 1134; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_ZP, false, LimeBed::Part::Foot).ID: return 1135; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_XM, true, LimeBed::Part::Head).ID: return 1136; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_XM, true, LimeBed::Part::Foot).ID: return 1137; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_XM, false, LimeBed::Part::Head).ID: return 1138; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_XM, false, LimeBed::Part::Foot).ID: return 1139; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_XP, true, LimeBed::Part::Head).ID: return 1140; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_XP, true, LimeBed::Part::Foot).ID: return 1141; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_XP, false, LimeBed::Part::Head).ID: return 1142; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_XP, false, LimeBed::Part::Foot).ID: return 1143; case LimeCarpet::LimeCarpet().ID: return 7335; case LimeConcrete::LimeConcrete().ID: return 8907; case LimeConcretePowder::LimeConcretePowder().ID: return 8923; case LimeGlazedTerracotta::LimeGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 8858; case LimeGlazedTerracotta::LimeGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 8859; case LimeGlazedTerracotta::LimeGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 8860; case LimeGlazedTerracotta::LimeGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 8861; case LimeShulkerBox::LimeShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 8772; case LimeShulkerBox::LimeShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 8773; case LimeShulkerBox::LimeShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 8774; case LimeShulkerBox::LimeShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 8775; case LimeShulkerBox::LimeShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 8776; case LimeShulkerBox::LimeShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 8777; case LimeStainedGlass::LimeStainedGlass().ID: return 4086; case LimeStainedGlassPane::LimeStainedGlassPane(true, true, true, true).ID: return 6489; case LimeStainedGlassPane::LimeStainedGlassPane(true, true, true, false).ID: return 6490; case LimeStainedGlassPane::LimeStainedGlassPane(true, true, false, true).ID: return 6493; case LimeStainedGlassPane::LimeStainedGlassPane(true, true, false, false).ID: return 6494; case LimeStainedGlassPane::LimeStainedGlassPane(true, false, true, true).ID: return 6497; case LimeStainedGlassPane::LimeStainedGlassPane(true, false, true, false).ID: return 6498; case LimeStainedGlassPane::LimeStainedGlassPane(true, false, false, true).ID: return 6501; case LimeStainedGlassPane::LimeStainedGlassPane(true, false, false, false).ID: return 6502; case LimeStainedGlassPane::LimeStainedGlassPane(false, true, true, true).ID: return 6505; case LimeStainedGlassPane::LimeStainedGlassPane(false, true, true, false).ID: return 6506; case LimeStainedGlassPane::LimeStainedGlassPane(false, true, false, true).ID: return 6509; case LimeStainedGlassPane::LimeStainedGlassPane(false, true, false, false).ID: return 6510; case LimeStainedGlassPane::LimeStainedGlassPane(false, false, true, true).ID: return 6513; case LimeStainedGlassPane::LimeStainedGlassPane(false, false, true, false).ID: return 6514; case LimeStainedGlassPane::LimeStainedGlassPane(false, false, false, true).ID: return 6517; case LimeStainedGlassPane::LimeStainedGlassPane(false, false, false, false).ID: return 6518; case LimeTerracotta::LimeTerracotta().ID: return 6316; case LimeWallBanner::LimeWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 7637; case LimeWallBanner::LimeWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 7638; case LimeWallBanner::LimeWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 7639; case LimeWallBanner::LimeWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 7640; case LimeWool::LimeWool().ID: return 1388; case Loom::Loom(eBlockFace::BLOCK_FACE_ZM).ID: return 11131; case Loom::Loom(eBlockFace::BLOCK_FACE_ZP).ID: return 11132; case Loom::Loom(eBlockFace::BLOCK_FACE_XM).ID: return 11133; case Loom::Loom(eBlockFace::BLOCK_FACE_XP).ID: return 11134; case MagentaBanner::MagentaBanner(0).ID: return 7393; case MagentaBanner::MagentaBanner(1).ID: return 7394; case MagentaBanner::MagentaBanner(2).ID: return 7395; case MagentaBanner::MagentaBanner(3).ID: return 7396; case MagentaBanner::MagentaBanner(4).ID: return 7397; case MagentaBanner::MagentaBanner(5).ID: return 7398; case MagentaBanner::MagentaBanner(6).ID: return 7399; case MagentaBanner::MagentaBanner(7).ID: return 7400; case MagentaBanner::MagentaBanner(8).ID: return 7401; case MagentaBanner::MagentaBanner(9).ID: return 7402; case MagentaBanner::MagentaBanner(10).ID: return 7403; case MagentaBanner::MagentaBanner(11).ID: return 7404; case MagentaBanner::MagentaBanner(12).ID: return 7405; case MagentaBanner::MagentaBanner(13).ID: return 7406; case MagentaBanner::MagentaBanner(14).ID: return 7407; case MagentaBanner::MagentaBanner(15).ID: return 7408; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_ZM, true, MagentaBed::Part::Head).ID: return 1080; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_ZM, true, MagentaBed::Part::Foot).ID: return 1081; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_ZM, false, MagentaBed::Part::Head).ID: return 1082; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_ZM, false, MagentaBed::Part::Foot).ID: return 1083; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_ZP, true, MagentaBed::Part::Head).ID: return 1084; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_ZP, true, MagentaBed::Part::Foot).ID: return 1085; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_ZP, false, MagentaBed::Part::Head).ID: return 1086; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_ZP, false, MagentaBed::Part::Foot).ID: return 1087; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_XM, true, MagentaBed::Part::Head).ID: return 1088; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_XM, true, MagentaBed::Part::Foot).ID: return 1089; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_XM, false, MagentaBed::Part::Head).ID: return 1090; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_XM, false, MagentaBed::Part::Foot).ID: return 1091; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_XP, true, MagentaBed::Part::Head).ID: return 1092; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_XP, true, MagentaBed::Part::Foot).ID: return 1093; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_XP, false, MagentaBed::Part::Head).ID: return 1094; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_XP, false, MagentaBed::Part::Foot).ID: return 1095; case MagentaCarpet::MagentaCarpet().ID: return 7332; case MagentaConcrete::MagentaConcrete().ID: return 8904; case MagentaConcretePowder::MagentaConcretePowder().ID: return 8920; case MagentaGlazedTerracotta::MagentaGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 8846; case MagentaGlazedTerracotta::MagentaGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 8847; case MagentaGlazedTerracotta::MagentaGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 8848; case MagentaGlazedTerracotta::MagentaGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 8849; case MagentaShulkerBox::MagentaShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 8754; case MagentaShulkerBox::MagentaShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 8755; case MagentaShulkerBox::MagentaShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 8756; case MagentaShulkerBox::MagentaShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 8757; case MagentaShulkerBox::MagentaShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 8758; case MagentaShulkerBox::MagentaShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 8759; case MagentaStainedGlass::MagentaStainedGlass().ID: return 4083; case MagentaStainedGlassPane::MagentaStainedGlassPane(true, true, true, true).ID: return 6393; case MagentaStainedGlassPane::MagentaStainedGlassPane(true, true, true, false).ID: return 6394; case MagentaStainedGlassPane::MagentaStainedGlassPane(true, true, false, true).ID: return 6397; case MagentaStainedGlassPane::MagentaStainedGlassPane(true, true, false, false).ID: return 6398; case MagentaStainedGlassPane::MagentaStainedGlassPane(true, false, true, true).ID: return 6401; case MagentaStainedGlassPane::MagentaStainedGlassPane(true, false, true, false).ID: return 6402; case MagentaStainedGlassPane::MagentaStainedGlassPane(true, false, false, true).ID: return 6405; case MagentaStainedGlassPane::MagentaStainedGlassPane(true, false, false, false).ID: return 6406; case MagentaStainedGlassPane::MagentaStainedGlassPane(false, true, true, true).ID: return 6409; case MagentaStainedGlassPane::MagentaStainedGlassPane(false, true, true, false).ID: return 6410; case MagentaStainedGlassPane::MagentaStainedGlassPane(false, true, false, true).ID: return 6413; case MagentaStainedGlassPane::MagentaStainedGlassPane(false, true, false, false).ID: return 6414; case MagentaStainedGlassPane::MagentaStainedGlassPane(false, false, true, true).ID: return 6417; case MagentaStainedGlassPane::MagentaStainedGlassPane(false, false, true, false).ID: return 6418; case MagentaStainedGlassPane::MagentaStainedGlassPane(false, false, false, true).ID: return 6421; case MagentaStainedGlassPane::MagentaStainedGlassPane(false, false, false, false).ID: return 6422; case MagentaTerracotta::MagentaTerracotta().ID: return 6313; case MagentaWallBanner::MagentaWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 7625; case MagentaWallBanner::MagentaWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 7626; case MagentaWallBanner::MagentaWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 7627; case MagentaWallBanner::MagentaWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 7628; case MagentaWool::MagentaWool().ID: return 1385; case MagmaBlock::MagmaBlock().ID: return 8717; case Melon::Melon().ID: return 4747; case MelonStem::MelonStem(0).ID: return 4764; case MelonStem::MelonStem(1).ID: return 4765; case MelonStem::MelonStem(2).ID: return 4766; case MelonStem::MelonStem(3).ID: return 4767; case MelonStem::MelonStem(4).ID: return 4768; case MelonStem::MelonStem(5).ID: return 4769; case MelonStem::MelonStem(6).ID: return 4770; case MelonStem::MelonStem(7).ID: return 4771; case MossyCobblestone::MossyCobblestone().ID: return 1432; case MossyCobblestoneSlab::MossyCobblestoneSlab(MossyCobblestoneSlab::Type::Top).ID: return 10278; case MossyCobblestoneSlab::MossyCobblestoneSlab(MossyCobblestoneSlab::Type::Bottom).ID: return 10280; case MossyCobblestoneSlab::MossyCobblestoneSlab(MossyCobblestoneSlab::Type::Double).ID: return 10282; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, MossyCobblestoneStairs::Half::Top, MossyCobblestoneStairs::Shape::Straight).ID: return 9454; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, MossyCobblestoneStairs::Half::Top, MossyCobblestoneStairs::Shape::InnerLeft).ID: return 9456; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, MossyCobblestoneStairs::Half::Top, MossyCobblestoneStairs::Shape::InnerRight).ID: return 9458; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, MossyCobblestoneStairs::Half::Top, MossyCobblestoneStairs::Shape::OuterLeft).ID: return 9460; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, MossyCobblestoneStairs::Half::Top, MossyCobblestoneStairs::Shape::OuterRight).ID: return 9462; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, MossyCobblestoneStairs::Half::Bottom, MossyCobblestoneStairs::Shape::Straight).ID: return 9464; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, MossyCobblestoneStairs::Half::Bottom, MossyCobblestoneStairs::Shape::InnerLeft).ID: return 9466; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, MossyCobblestoneStairs::Half::Bottom, MossyCobblestoneStairs::Shape::InnerRight).ID: return 9468; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, MossyCobblestoneStairs::Half::Bottom, MossyCobblestoneStairs::Shape::OuterLeft).ID: return 9470; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, MossyCobblestoneStairs::Half::Bottom, MossyCobblestoneStairs::Shape::OuterRight).ID: return 9472; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, MossyCobblestoneStairs::Half::Top, MossyCobblestoneStairs::Shape::Straight).ID: return 9474; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, MossyCobblestoneStairs::Half::Top, MossyCobblestoneStairs::Shape::InnerLeft).ID: return 9476; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, MossyCobblestoneStairs::Half::Top, MossyCobblestoneStairs::Shape::InnerRight).ID: return 9478; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, MossyCobblestoneStairs::Half::Top, MossyCobblestoneStairs::Shape::OuterLeft).ID: return 9480; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, MossyCobblestoneStairs::Half::Top, MossyCobblestoneStairs::Shape::OuterRight).ID: return 9482; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, MossyCobblestoneStairs::Half::Bottom, MossyCobblestoneStairs::Shape::Straight).ID: return 9484; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, MossyCobblestoneStairs::Half::Bottom, MossyCobblestoneStairs::Shape::InnerLeft).ID: return 9486; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, MossyCobblestoneStairs::Half::Bottom, MossyCobblestoneStairs::Shape::InnerRight).ID: return 9488; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, MossyCobblestoneStairs::Half::Bottom, MossyCobblestoneStairs::Shape::OuterLeft).ID: return 9490; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, MossyCobblestoneStairs::Half::Bottom, MossyCobblestoneStairs::Shape::OuterRight).ID: return 9492; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_XM, MossyCobblestoneStairs::Half::Top, MossyCobblestoneStairs::Shape::Straight).ID: return 9494; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_XM, MossyCobblestoneStairs::Half::Top, MossyCobblestoneStairs::Shape::InnerLeft).ID: return 9496; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_XM, MossyCobblestoneStairs::Half::Top, MossyCobblestoneStairs::Shape::InnerRight).ID: return 9498; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_XM, MossyCobblestoneStairs::Half::Top, MossyCobblestoneStairs::Shape::OuterLeft).ID: return 9500; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_XM, MossyCobblestoneStairs::Half::Top, MossyCobblestoneStairs::Shape::OuterRight).ID: return 9502; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_XM, MossyCobblestoneStairs::Half::Bottom, MossyCobblestoneStairs::Shape::Straight).ID: return 9504; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_XM, MossyCobblestoneStairs::Half::Bottom, MossyCobblestoneStairs::Shape::InnerLeft).ID: return 9506; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_XM, MossyCobblestoneStairs::Half::Bottom, MossyCobblestoneStairs::Shape::InnerRight).ID: return 9508; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_XM, MossyCobblestoneStairs::Half::Bottom, MossyCobblestoneStairs::Shape::OuterLeft).ID: return 9510; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_XM, MossyCobblestoneStairs::Half::Bottom, MossyCobblestoneStairs::Shape::OuterRight).ID: return 9512; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_XP, MossyCobblestoneStairs::Half::Top, MossyCobblestoneStairs::Shape::Straight).ID: return 9514; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_XP, MossyCobblestoneStairs::Half::Top, MossyCobblestoneStairs::Shape::InnerLeft).ID: return 9516; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_XP, MossyCobblestoneStairs::Half::Top, MossyCobblestoneStairs::Shape::InnerRight).ID: return 9518; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_XP, MossyCobblestoneStairs::Half::Top, MossyCobblestoneStairs::Shape::OuterLeft).ID: return 9520; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_XP, MossyCobblestoneStairs::Half::Top, MossyCobblestoneStairs::Shape::OuterRight).ID: return 9522; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_XP, MossyCobblestoneStairs::Half::Bottom, MossyCobblestoneStairs::Shape::Straight).ID: return 9524; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_XP, MossyCobblestoneStairs::Half::Bottom, MossyCobblestoneStairs::Shape::InnerLeft).ID: return 9526; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_XP, MossyCobblestoneStairs::Half::Bottom, MossyCobblestoneStairs::Shape::InnerRight).ID: return 9528; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_XP, MossyCobblestoneStairs::Half::Bottom, MossyCobblestoneStairs::Shape::OuterLeft).ID: return 9530; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_XP, MossyCobblestoneStairs::Half::Bottom, MossyCobblestoneStairs::Shape::OuterRight).ID: return 9532; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::Low, true, MossyCobblestoneWall::West::Low).ID: return 5707; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::Low, true, MossyCobblestoneWall::West::None).ID: return 5708; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::Low, false, MossyCobblestoneWall::West::Low).ID: return 5711; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::Low, false, MossyCobblestoneWall::West::None).ID: return 5712; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::None, true, MossyCobblestoneWall::West::Low).ID: return 5715; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::None, true, MossyCobblestoneWall::West::None).ID: return 5716; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::None, false, MossyCobblestoneWall::West::Low).ID: return 5719; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::None, false, MossyCobblestoneWall::West::None).ID: return 5720; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::Low, true, MossyCobblestoneWall::West::Low).ID: return 5723; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::Low, true, MossyCobblestoneWall::West::None).ID: return 5724; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::Low, false, MossyCobblestoneWall::West::Low).ID: return 5727; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::Low, false, MossyCobblestoneWall::West::None).ID: return 5728; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::None, true, MossyCobblestoneWall::West::Low).ID: return 5731; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::None, true, MossyCobblestoneWall::West::None).ID: return 5732; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::None, false, MossyCobblestoneWall::West::Low).ID: return 5735; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::None, false, MossyCobblestoneWall::West::None).ID: return 5736; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::Low, true, MossyCobblestoneWall::West::Low).ID: return 5739; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::Low, true, MossyCobblestoneWall::West::None).ID: return 5740; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::Low, false, MossyCobblestoneWall::West::Low).ID: return 5743; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::Low, false, MossyCobblestoneWall::West::None).ID: return 5744; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::None, true, MossyCobblestoneWall::West::Low).ID: return 5747; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::None, true, MossyCobblestoneWall::West::None).ID: return 5748; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::None, false, MossyCobblestoneWall::West::Low).ID: return 5751; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::None, false, MossyCobblestoneWall::West::None).ID: return 5752; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::Low, true, MossyCobblestoneWall::West::Low).ID: return 5755; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::Low, true, MossyCobblestoneWall::West::None).ID: return 5756; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::Low, false, MossyCobblestoneWall::West::Low).ID: return 5759; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::Low, false, MossyCobblestoneWall::West::None).ID: return 5760; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::None, true, MossyCobblestoneWall::West::Low).ID: return 5763; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::None, true, MossyCobblestoneWall::West::None).ID: return 5764; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::None, false, MossyCobblestoneWall::West::Low).ID: return 5767; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::None, false, MossyCobblestoneWall::West::None).ID: return 5768; case MossyStoneBrickSlab::MossyStoneBrickSlab(MossyStoneBrickSlab::Type::Top).ID: return 10266; case MossyStoneBrickSlab::MossyStoneBrickSlab(MossyStoneBrickSlab::Type::Bottom).ID: return 10268; case MossyStoneBrickSlab::MossyStoneBrickSlab(MossyStoneBrickSlab::Type::Double).ID: return 10270; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, MossyStoneBrickStairs::Half::Top, MossyStoneBrickStairs::Shape::Straight).ID: return 9294; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, MossyStoneBrickStairs::Half::Top, MossyStoneBrickStairs::Shape::InnerLeft).ID: return 9296; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, MossyStoneBrickStairs::Half::Top, MossyStoneBrickStairs::Shape::InnerRight).ID: return 9298; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, MossyStoneBrickStairs::Half::Top, MossyStoneBrickStairs::Shape::OuterLeft).ID: return 9300; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, MossyStoneBrickStairs::Half::Top, MossyStoneBrickStairs::Shape::OuterRight).ID: return 9302; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, MossyStoneBrickStairs::Half::Bottom, MossyStoneBrickStairs::Shape::Straight).ID: return 9304; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, MossyStoneBrickStairs::Half::Bottom, MossyStoneBrickStairs::Shape::InnerLeft).ID: return 9306; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, MossyStoneBrickStairs::Half::Bottom, MossyStoneBrickStairs::Shape::InnerRight).ID: return 9308; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, MossyStoneBrickStairs::Half::Bottom, MossyStoneBrickStairs::Shape::OuterLeft).ID: return 9310; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, MossyStoneBrickStairs::Half::Bottom, MossyStoneBrickStairs::Shape::OuterRight).ID: return 9312; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, MossyStoneBrickStairs::Half::Top, MossyStoneBrickStairs::Shape::Straight).ID: return 9314; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, MossyStoneBrickStairs::Half::Top, MossyStoneBrickStairs::Shape::InnerLeft).ID: return 9316; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, MossyStoneBrickStairs::Half::Top, MossyStoneBrickStairs::Shape::InnerRight).ID: return 9318; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, MossyStoneBrickStairs::Half::Top, MossyStoneBrickStairs::Shape::OuterLeft).ID: return 9320; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, MossyStoneBrickStairs::Half::Top, MossyStoneBrickStairs::Shape::OuterRight).ID: return 9322; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, MossyStoneBrickStairs::Half::Bottom, MossyStoneBrickStairs::Shape::Straight).ID: return 9324; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, MossyStoneBrickStairs::Half::Bottom, MossyStoneBrickStairs::Shape::InnerLeft).ID: return 9326; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, MossyStoneBrickStairs::Half::Bottom, MossyStoneBrickStairs::Shape::InnerRight).ID: return 9328; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, MossyStoneBrickStairs::Half::Bottom, MossyStoneBrickStairs::Shape::OuterLeft).ID: return 9330; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, MossyStoneBrickStairs::Half::Bottom, MossyStoneBrickStairs::Shape::OuterRight).ID: return 9332; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_XM, MossyStoneBrickStairs::Half::Top, MossyStoneBrickStairs::Shape::Straight).ID: return 9334; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_XM, MossyStoneBrickStairs::Half::Top, MossyStoneBrickStairs::Shape::InnerLeft).ID: return 9336; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_XM, MossyStoneBrickStairs::Half::Top, MossyStoneBrickStairs::Shape::InnerRight).ID: return 9338; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_XM, MossyStoneBrickStairs::Half::Top, MossyStoneBrickStairs::Shape::OuterLeft).ID: return 9340; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_XM, MossyStoneBrickStairs::Half::Top, MossyStoneBrickStairs::Shape::OuterRight).ID: return 9342; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_XM, MossyStoneBrickStairs::Half::Bottom, MossyStoneBrickStairs::Shape::Straight).ID: return 9344; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_XM, MossyStoneBrickStairs::Half::Bottom, MossyStoneBrickStairs::Shape::InnerLeft).ID: return 9346; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_XM, MossyStoneBrickStairs::Half::Bottom, MossyStoneBrickStairs::Shape::InnerRight).ID: return 9348; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_XM, MossyStoneBrickStairs::Half::Bottom, MossyStoneBrickStairs::Shape::OuterLeft).ID: return 9350; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_XM, MossyStoneBrickStairs::Half::Bottom, MossyStoneBrickStairs::Shape::OuterRight).ID: return 9352; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_XP, MossyStoneBrickStairs::Half::Top, MossyStoneBrickStairs::Shape::Straight).ID: return 9354; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_XP, MossyStoneBrickStairs::Half::Top, MossyStoneBrickStairs::Shape::InnerLeft).ID: return 9356; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_XP, MossyStoneBrickStairs::Half::Top, MossyStoneBrickStairs::Shape::InnerRight).ID: return 9358; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_XP, MossyStoneBrickStairs::Half::Top, MossyStoneBrickStairs::Shape::OuterLeft).ID: return 9360; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_XP, MossyStoneBrickStairs::Half::Top, MossyStoneBrickStairs::Shape::OuterRight).ID: return 9362; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_XP, MossyStoneBrickStairs::Half::Bottom, MossyStoneBrickStairs::Shape::Straight).ID: return 9364; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_XP, MossyStoneBrickStairs::Half::Bottom, MossyStoneBrickStairs::Shape::InnerLeft).ID: return 9366; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_XP, MossyStoneBrickStairs::Half::Bottom, MossyStoneBrickStairs::Shape::InnerRight).ID: return 9368; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_XP, MossyStoneBrickStairs::Half::Bottom, MossyStoneBrickStairs::Shape::OuterLeft).ID: return 9370; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_XP, MossyStoneBrickStairs::Half::Bottom, MossyStoneBrickStairs::Shape::OuterRight).ID: return 9372; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::Low, true, MossyStoneBrickWall::West::Low).ID: return 10525; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::Low, true, MossyStoneBrickWall::West::None).ID: return 10526; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::Low, false, MossyStoneBrickWall::West::Low).ID: return 10529; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::Low, false, MossyStoneBrickWall::West::None).ID: return 10530; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::None, true, MossyStoneBrickWall::West::Low).ID: return 10533; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::None, true, MossyStoneBrickWall::West::None).ID: return 10534; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::None, false, MossyStoneBrickWall::West::Low).ID: return 10537; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::None, false, MossyStoneBrickWall::West::None).ID: return 10538; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::Low, true, MossyStoneBrickWall::West::Low).ID: return 10541; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::Low, true, MossyStoneBrickWall::West::None).ID: return 10542; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::Low, false, MossyStoneBrickWall::West::Low).ID: return 10545; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::Low, false, MossyStoneBrickWall::West::None).ID: return 10546; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::None, true, MossyStoneBrickWall::West::Low).ID: return 10549; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::None, true, MossyStoneBrickWall::West::None).ID: return 10550; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::None, false, MossyStoneBrickWall::West::Low).ID: return 10553; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::None, false, MossyStoneBrickWall::West::None).ID: return 10554; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::Low, true, MossyStoneBrickWall::West::Low).ID: return 10557; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::Low, true, MossyStoneBrickWall::West::None).ID: return 10558; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::Low, false, MossyStoneBrickWall::West::Low).ID: return 10561; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::Low, false, MossyStoneBrickWall::West::None).ID: return 10562; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::None, true, MossyStoneBrickWall::West::Low).ID: return 10565; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::None, true, MossyStoneBrickWall::West::None).ID: return 10566; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::None, false, MossyStoneBrickWall::West::Low).ID: return 10569; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::None, false, MossyStoneBrickWall::West::None).ID: return 10570; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::Low, true, MossyStoneBrickWall::West::Low).ID: return 10573; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::Low, true, MossyStoneBrickWall::West::None).ID: return 10574; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::Low, false, MossyStoneBrickWall::West::Low).ID: return 10577; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::Low, false, MossyStoneBrickWall::West::None).ID: return 10578; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::None, true, MossyStoneBrickWall::West::Low).ID: return 10581; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::None, true, MossyStoneBrickWall::West::None).ID: return 10582; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::None, false, MossyStoneBrickWall::West::Low).ID: return 10585; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::None, false, MossyStoneBrickWall::West::None).ID: return 10586; case MossyStoneBricks::MossyStoneBricks().ID: return 4482; case MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_ZM, MovingPiston::Type::Normal).ID: return 1399; case MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_ZM, MovingPiston::Type::Sticky).ID: return 1400; case MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_XP, MovingPiston::Type::Normal).ID: return 1401; case MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_XP, MovingPiston::Type::Sticky).ID: return 1402; case MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_ZP, MovingPiston::Type::Normal).ID: return 1403; case MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_ZP, MovingPiston::Type::Sticky).ID: return 1404; case MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_XM, MovingPiston::Type::Normal).ID: return 1405; case MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_XM, MovingPiston::Type::Sticky).ID: return 1406; case MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_YP, MovingPiston::Type::Normal).ID: return 1407; case MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_YP, MovingPiston::Type::Sticky).ID: return 1408; case MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_YM, MovingPiston::Type::Normal).ID: return 1409; case MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_YM, MovingPiston::Type::Sticky).ID: return 1410; case MushroomStem::MushroomStem(true, true, true, true, true, true).ID: return 4619; case MushroomStem::MushroomStem(true, true, true, true, true, false).ID: return 4620; case MushroomStem::MushroomStem(true, true, true, true, false, true).ID: return 4621; case MushroomStem::MushroomStem(true, true, true, true, false, false).ID: return 4622; case MushroomStem::MushroomStem(true, true, true, false, true, true).ID: return 4623; case MushroomStem::MushroomStem(true, true, true, false, true, false).ID: return 4624; case MushroomStem::MushroomStem(true, true, true, false, false, true).ID: return 4625; case MushroomStem::MushroomStem(true, true, true, false, false, false).ID: return 4626; case MushroomStem::MushroomStem(true, true, false, true, true, true).ID: return 4627; case MushroomStem::MushroomStem(true, true, false, true, true, false).ID: return 4628; case MushroomStem::MushroomStem(true, true, false, true, false, true).ID: return 4629; case MushroomStem::MushroomStem(true, true, false, true, false, false).ID: return 4630; case MushroomStem::MushroomStem(true, true, false, false, true, true).ID: return 4631; case MushroomStem::MushroomStem(true, true, false, false, true, false).ID: return 4632; case MushroomStem::MushroomStem(true, true, false, false, false, true).ID: return 4633; case MushroomStem::MushroomStem(true, true, false, false, false, false).ID: return 4634; case MushroomStem::MushroomStem(true, false, true, true, true, true).ID: return 4635; case MushroomStem::MushroomStem(true, false, true, true, true, false).ID: return 4636; case MushroomStem::MushroomStem(true, false, true, true, false, true).ID: return 4637; case MushroomStem::MushroomStem(true, false, true, true, false, false).ID: return 4638; case MushroomStem::MushroomStem(true, false, true, false, true, true).ID: return 4639; case MushroomStem::MushroomStem(true, false, true, false, true, false).ID: return 4640; case MushroomStem::MushroomStem(true, false, true, false, false, true).ID: return 4641; case MushroomStem::MushroomStem(true, false, true, false, false, false).ID: return 4642; case MushroomStem::MushroomStem(true, false, false, true, true, true).ID: return 4643; case MushroomStem::MushroomStem(true, false, false, true, true, false).ID: return 4644; case MushroomStem::MushroomStem(true, false, false, true, false, true).ID: return 4645; case MushroomStem::MushroomStem(true, false, false, true, false, false).ID: return 4646; case MushroomStem::MushroomStem(true, false, false, false, true, true).ID: return 4647; case MushroomStem::MushroomStem(true, false, false, false, true, false).ID: return 4648; case MushroomStem::MushroomStem(true, false, false, false, false, true).ID: return 4649; case MushroomStem::MushroomStem(true, false, false, false, false, false).ID: return 4650; case MushroomStem::MushroomStem(false, true, true, true, true, true).ID: return 4651; case MushroomStem::MushroomStem(false, true, true, true, true, false).ID: return 4652; case MushroomStem::MushroomStem(false, true, true, true, false, true).ID: return 4653; case MushroomStem::MushroomStem(false, true, true, true, false, false).ID: return 4654; case MushroomStem::MushroomStem(false, true, true, false, true, true).ID: return 4655; case MushroomStem::MushroomStem(false, true, true, false, true, false).ID: return 4656; case MushroomStem::MushroomStem(false, true, true, false, false, true).ID: return 4657; case MushroomStem::MushroomStem(false, true, true, false, false, false).ID: return 4658; case MushroomStem::MushroomStem(false, true, false, true, true, true).ID: return 4659; case MushroomStem::MushroomStem(false, true, false, true, true, false).ID: return 4660; case MushroomStem::MushroomStem(false, true, false, true, false, true).ID: return 4661; case MushroomStem::MushroomStem(false, true, false, true, false, false).ID: return 4662; case MushroomStem::MushroomStem(false, true, false, false, true, true).ID: return 4663; case MushroomStem::MushroomStem(false, true, false, false, true, false).ID: return 4664; case MushroomStem::MushroomStem(false, true, false, false, false, true).ID: return 4665; case MushroomStem::MushroomStem(false, true, false, false, false, false).ID: return 4666; case MushroomStem::MushroomStem(false, false, true, true, true, true).ID: return 4667; case MushroomStem::MushroomStem(false, false, true, true, true, false).ID: return 4668; case MushroomStem::MushroomStem(false, false, true, true, false, true).ID: return 4669; case MushroomStem::MushroomStem(false, false, true, true, false, false).ID: return 4670; case MushroomStem::MushroomStem(false, false, true, false, true, true).ID: return 4671; case MushroomStem::MushroomStem(false, false, true, false, true, false).ID: return 4672; case MushroomStem::MushroomStem(false, false, true, false, false, true).ID: return 4673; case MushroomStem::MushroomStem(false, false, true, false, false, false).ID: return 4674; case MushroomStem::MushroomStem(false, false, false, true, true, true).ID: return 4675; case MushroomStem::MushroomStem(false, false, false, true, true, false).ID: return 4676; case MushroomStem::MushroomStem(false, false, false, true, false, true).ID: return 4677; case MushroomStem::MushroomStem(false, false, false, true, false, false).ID: return 4678; case MushroomStem::MushroomStem(false, false, false, false, true, true).ID: return 4679; case MushroomStem::MushroomStem(false, false, false, false, true, false).ID: return 4680; case MushroomStem::MushroomStem(false, false, false, false, false, true).ID: return 4681; case MushroomStem::MushroomStem(false, false, false, false, false, false).ID: return 4682; case Mycelium::Mycelium(true).ID: return 4996; case Mycelium::Mycelium(false).ID: return 4997; case NetherBrickFence::NetherBrickFence(true, true, true, true).ID: return 5002; case NetherBrickFence::NetherBrickFence(true, true, true, false).ID: return 5003; case NetherBrickFence::NetherBrickFence(true, true, false, true).ID: return 5006; case NetherBrickFence::NetherBrickFence(true, true, false, false).ID: return 5007; case NetherBrickFence::NetherBrickFence(true, false, true, true).ID: return 5010; case NetherBrickFence::NetherBrickFence(true, false, true, false).ID: return 5011; case NetherBrickFence::NetherBrickFence(true, false, false, true).ID: return 5014; case NetherBrickFence::NetherBrickFence(true, false, false, false).ID: return 5015; case NetherBrickFence::NetherBrickFence(false, true, true, true).ID: return 5018; case NetherBrickFence::NetherBrickFence(false, true, true, false).ID: return 5019; case NetherBrickFence::NetherBrickFence(false, true, false, true).ID: return 5022; case NetherBrickFence::NetherBrickFence(false, true, false, false).ID: return 5023; case NetherBrickFence::NetherBrickFence(false, false, true, true).ID: return 5026; case NetherBrickFence::NetherBrickFence(false, false, true, false).ID: return 5027; case NetherBrickFence::NetherBrickFence(false, false, false, true).ID: return 5030; case NetherBrickFence::NetherBrickFence(false, false, false, false).ID: return 5031; case NetherBrickSlab::NetherBrickSlab(NetherBrickSlab::Type::Top).ID: return 7849; case NetherBrickSlab::NetherBrickSlab(NetherBrickSlab::Type::Bottom).ID: return 7851; case NetherBrickSlab::NetherBrickSlab(NetherBrickSlab::Type::Double).ID: return 7853; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::Straight).ID: return 5033; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::InnerLeft).ID: return 5035; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::InnerRight).ID: return 5037; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::OuterLeft).ID: return 5039; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::OuterRight).ID: return 5041; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::Straight).ID: return 5043; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::InnerLeft).ID: return 5045; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::InnerRight).ID: return 5047; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::OuterLeft).ID: return 5049; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::OuterRight).ID: return 5051; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::Straight).ID: return 5053; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::InnerLeft).ID: return 5055; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::InnerRight).ID: return 5057; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::OuterLeft).ID: return 5059; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::OuterRight).ID: return 5061; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::Straight).ID: return 5063; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::InnerLeft).ID: return 5065; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::InnerRight).ID: return 5067; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::OuterLeft).ID: return 5069; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::OuterRight).ID: return 5071; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XM, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::Straight).ID: return 5073; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XM, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::InnerLeft).ID: return 5075; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XM, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::InnerRight).ID: return 5077; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XM, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::OuterLeft).ID: return 5079; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XM, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::OuterRight).ID: return 5081; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XM, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::Straight).ID: return 5083; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XM, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::InnerLeft).ID: return 5085; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XM, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::InnerRight).ID: return 5087; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XM, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::OuterLeft).ID: return 5089; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XM, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::OuterRight).ID: return 5091; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XP, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::Straight).ID: return 5093; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XP, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::InnerLeft).ID: return 5095; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XP, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::InnerRight).ID: return 5097; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XP, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::OuterLeft).ID: return 5099; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XP, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::OuterRight).ID: return 5101; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XP, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::Straight).ID: return 5103; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XP, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::InnerLeft).ID: return 5105; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XP, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::InnerRight).ID: return 5107; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XP, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::OuterLeft).ID: return 5109; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XP, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::OuterRight).ID: return 5111; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::Low, NetherBrickWall::South::Low, true, NetherBrickWall::West::Low).ID: return 10717; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::Low, NetherBrickWall::South::Low, true, NetherBrickWall::West::None).ID: return 10718; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::Low, NetherBrickWall::South::Low, false, NetherBrickWall::West::Low).ID: return 10721; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::Low, NetherBrickWall::South::Low, false, NetherBrickWall::West::None).ID: return 10722; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::Low, NetherBrickWall::South::None, true, NetherBrickWall::West::Low).ID: return 10725; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::Low, NetherBrickWall::South::None, true, NetherBrickWall::West::None).ID: return 10726; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::Low, NetherBrickWall::South::None, false, NetherBrickWall::West::Low).ID: return 10729; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::Low, NetherBrickWall::South::None, false, NetherBrickWall::West::None).ID: return 10730; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::None, NetherBrickWall::South::Low, true, NetherBrickWall::West::Low).ID: return 10733; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::None, NetherBrickWall::South::Low, true, NetherBrickWall::West::None).ID: return 10734; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::None, NetherBrickWall::South::Low, false, NetherBrickWall::West::Low).ID: return 10737; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::None, NetherBrickWall::South::Low, false, NetherBrickWall::West::None).ID: return 10738; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::None, NetherBrickWall::South::None, true, NetherBrickWall::West::Low).ID: return 10741; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::None, NetherBrickWall::South::None, true, NetherBrickWall::West::None).ID: return 10742; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::None, NetherBrickWall::South::None, false, NetherBrickWall::West::Low).ID: return 10745; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::None, NetherBrickWall::South::None, false, NetherBrickWall::West::None).ID: return 10746; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::Low, NetherBrickWall::South::Low, true, NetherBrickWall::West::Low).ID: return 10749; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::Low, NetherBrickWall::South::Low, true, NetherBrickWall::West::None).ID: return 10750; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::Low, NetherBrickWall::South::Low, false, NetherBrickWall::West::Low).ID: return 10753; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::Low, NetherBrickWall::South::Low, false, NetherBrickWall::West::None).ID: return 10754; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::Low, NetherBrickWall::South::None, true, NetherBrickWall::West::Low).ID: return 10757; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::Low, NetherBrickWall::South::None, true, NetherBrickWall::West::None).ID: return 10758; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::Low, NetherBrickWall::South::None, false, NetherBrickWall::West::Low).ID: return 10761; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::Low, NetherBrickWall::South::None, false, NetherBrickWall::West::None).ID: return 10762; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::None, NetherBrickWall::South::Low, true, NetherBrickWall::West::Low).ID: return 10765; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::None, NetherBrickWall::South::Low, true, NetherBrickWall::West::None).ID: return 10766; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::None, NetherBrickWall::South::Low, false, NetherBrickWall::West::Low).ID: return 10769; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::None, NetherBrickWall::South::Low, false, NetherBrickWall::West::None).ID: return 10770; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::None, NetherBrickWall::South::None, true, NetherBrickWall::West::Low).ID: return 10773; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::None, NetherBrickWall::South::None, true, NetherBrickWall::West::None).ID: return 10774; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::None, NetherBrickWall::South::None, false, NetherBrickWall::West::Low).ID: return 10777; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::None, NetherBrickWall::South::None, false, NetherBrickWall::West::None).ID: return 10778; case NetherBricks::NetherBricks().ID: return 4999; case NetherPortal::NetherPortal(NetherPortal::Axis::X).ID: return 4000; case NetherPortal::NetherPortal(NetherPortal::Axis::Z).ID: return 4001; case NetherQuartzOre::NetherQuartzOre().ID: return 6191; case NetherWart::NetherWart(0).ID: return 5112; case NetherWart::NetherWart(1).ID: return 5113; case NetherWart::NetherWart(2).ID: return 5114; case NetherWart::NetherWart(3).ID: return 5115; case NetherWartBlock::NetherWartBlock().ID: return 8718; case Netherrack::Netherrack().ID: return 3997; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 0, true).ID: return 248; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 0, false).ID: return 249; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 1, true).ID: return 250; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 1, false).ID: return 251; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 2, true).ID: return 252; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 2, false).ID: return 253; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 3, true).ID: return 254; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 3, false).ID: return 255; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 4, true).ID: return 256; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 4, false).ID: return 257; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 5, true).ID: return 258; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 5, false).ID: return 259; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 6, true).ID: return 260; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 6, false).ID: return 261; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 7, true).ID: return 262; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 7, false).ID: return 263; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 8, true).ID: return 264; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 8, false).ID: return 265; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 9, true).ID: return 266; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 9, false).ID: return 267; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 10, true).ID: return 268; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 10, false).ID: return 269; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 11, true).ID: return 270; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 11, false).ID: return 271; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 12, true).ID: return 272; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 12, false).ID: return 273; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 13, true).ID: return 274; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 13, false).ID: return 275; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 14, true).ID: return 276; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 14, false).ID: return 277; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 15, true).ID: return 278; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 15, false).ID: return 279; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 16, true).ID: return 280; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 16, false).ID: return 281; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 17, true).ID: return 282; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 17, false).ID: return 283; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 18, true).ID: return 284; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 18, false).ID: return 285; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 19, true).ID: return 286; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 19, false).ID: return 287; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 20, true).ID: return 288; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 20, false).ID: return 289; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 21, true).ID: return 290; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 21, false).ID: return 291; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 22, true).ID: return 292; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 22, false).ID: return 293; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 23, true).ID: return 294; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 23, false).ID: return 295; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 24, true).ID: return 296; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 24, false).ID: return 297; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 0, true).ID: return 298; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 0, false).ID: return 299; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 1, true).ID: return 300; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 1, false).ID: return 301; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 2, true).ID: return 302; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 2, false).ID: return 303; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 3, true).ID: return 304; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 3, false).ID: return 305; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 4, true).ID: return 306; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 4, false).ID: return 307; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 5, true).ID: return 308; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 5, false).ID: return 309; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 6, true).ID: return 310; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 6, false).ID: return 311; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 7, true).ID: return 312; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 7, false).ID: return 313; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 8, true).ID: return 314; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 8, false).ID: return 315; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 9, true).ID: return 316; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 9, false).ID: return 317; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 10, true).ID: return 318; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 10, false).ID: return 319; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 11, true).ID: return 320; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 11, false).ID: return 321; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 12, true).ID: return 322; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 12, false).ID: return 323; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 13, true).ID: return 324; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 13, false).ID: return 325; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 14, true).ID: return 326; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 14, false).ID: return 327; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 15, true).ID: return 328; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 15, false).ID: return 329; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 16, true).ID: return 330; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 16, false).ID: return 331; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 17, true).ID: return 332; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 17, false).ID: return 333; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 18, true).ID: return 334; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 18, false).ID: return 335; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 19, true).ID: return 336; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 19, false).ID: return 337; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 20, true).ID: return 338; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 20, false).ID: return 339; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 21, true).ID: return 340; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 21, false).ID: return 341; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 22, true).ID: return 342; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 22, false).ID: return 343; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 23, true).ID: return 344; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 23, false).ID: return 345; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 24, true).ID: return 346; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 24, false).ID: return 347; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 0, true).ID: return 348; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 0, false).ID: return 349; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 1, true).ID: return 350; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 1, false).ID: return 351; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 2, true).ID: return 352; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 2, false).ID: return 353; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 3, true).ID: return 354; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 3, false).ID: return 355; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 4, true).ID: return 356; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 4, false).ID: return 357; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 5, true).ID: return 358; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 5, false).ID: return 359; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 6, true).ID: return 360; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 6, false).ID: return 361; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 7, true).ID: return 362; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 7, false).ID: return 363; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 8, true).ID: return 364; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 8, false).ID: return 365; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 9, true).ID: return 366; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 9, false).ID: return 367; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 10, true).ID: return 368; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 10, false).ID: return 369; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 11, true).ID: return 370; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 11, false).ID: return 371; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 12, true).ID: return 372; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 12, false).ID: return 373; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 13, true).ID: return 374; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 13, false).ID: return 375; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 14, true).ID: return 376; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 14, false).ID: return 377; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 15, true).ID: return 378; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 15, false).ID: return 379; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 16, true).ID: return 380; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 16, false).ID: return 381; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 17, true).ID: return 382; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 17, false).ID: return 383; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 18, true).ID: return 384; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 18, false).ID: return 385; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 19, true).ID: return 386; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 19, false).ID: return 387; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 20, true).ID: return 388; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 20, false).ID: return 389; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 21, true).ID: return 390; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 21, false).ID: return 391; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 22, true).ID: return 392; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 22, false).ID: return 393; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 23, true).ID: return 394; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 23, false).ID: return 395; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 24, true).ID: return 396; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 24, false).ID: return 397; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 0, true).ID: return 398; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 0, false).ID: return 399; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 1, true).ID: return 400; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 1, false).ID: return 401; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 2, true).ID: return 402; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 2, false).ID: return 403; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 3, true).ID: return 404; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 3, false).ID: return 405; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 4, true).ID: return 406; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 4, false).ID: return 407; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 5, true).ID: return 408; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 5, false).ID: return 409; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 6, true).ID: return 410; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 6, false).ID: return 411; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 7, true).ID: return 412; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 7, false).ID: return 413; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 8, true).ID: return 414; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 8, false).ID: return 415; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 9, true).ID: return 416; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 9, false).ID: return 417; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 10, true).ID: return 418; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 10, false).ID: return 419; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 11, true).ID: return 420; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 11, false).ID: return 421; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 12, true).ID: return 422; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 12, false).ID: return 423; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 13, true).ID: return 424; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 13, false).ID: return 425; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 14, true).ID: return 426; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 14, false).ID: return 427; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 15, true).ID: return 428; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 15, false).ID: return 429; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 16, true).ID: return 430; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 16, false).ID: return 431; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 17, true).ID: return 432; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 17, false).ID: return 433; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 18, true).ID: return 434; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 18, false).ID: return 435; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 19, true).ID: return 436; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 19, false).ID: return 437; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 20, true).ID: return 438; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 20, false).ID: return 439; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 21, true).ID: return 440; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 21, false).ID: return 441; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 22, true).ID: return 442; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 22, false).ID: return 443; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 23, true).ID: return 444; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 23, false).ID: return 445; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 24, true).ID: return 446; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 24, false).ID: return 447; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 0, true).ID: return 448; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 0, false).ID: return 449; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 1, true).ID: return 450; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 1, false).ID: return 451; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 2, true).ID: return 452; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 2, false).ID: return 453; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 3, true).ID: return 454; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 3, false).ID: return 455; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 4, true).ID: return 456; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 4, false).ID: return 457; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 5, true).ID: return 458; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 5, false).ID: return 459; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 6, true).ID: return 460; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 6, false).ID: return 461; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 7, true).ID: return 462; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 7, false).ID: return 463; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 8, true).ID: return 464; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 8, false).ID: return 465; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 9, true).ID: return 466; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 9, false).ID: return 467; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 10, true).ID: return 468; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 10, false).ID: return 469; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 11, true).ID: return 470; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 11, false).ID: return 471; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 12, true).ID: return 472; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 12, false).ID: return 473; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 13, true).ID: return 474; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 13, false).ID: return 475; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 14, true).ID: return 476; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 14, false).ID: return 477; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 15, true).ID: return 478; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 15, false).ID: return 479; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 16, true).ID: return 480; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 16, false).ID: return 481; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 17, true).ID: return 482; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 17, false).ID: return 483; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 18, true).ID: return 484; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 18, false).ID: return 485; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 19, true).ID: return 486; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 19, false).ID: return 487; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 20, true).ID: return 488; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 20, false).ID: return 489; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 21, true).ID: return 490; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 21, false).ID: return 491; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 22, true).ID: return 492; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 22, false).ID: return 493; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 23, true).ID: return 494; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 23, false).ID: return 495; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 24, true).ID: return 496; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 24, false).ID: return 497; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 0, true).ID: return 498; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 0, false).ID: return 499; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 1, true).ID: return 500; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 1, false).ID: return 501; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 2, true).ID: return 502; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 2, false).ID: return 503; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 3, true).ID: return 504; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 3, false).ID: return 505; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 4, true).ID: return 506; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 4, false).ID: return 507; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 5, true).ID: return 508; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 5, false).ID: return 509; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 6, true).ID: return 510; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 6, false).ID: return 511; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 7, true).ID: return 512; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 7, false).ID: return 513; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 8, true).ID: return 514; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 8, false).ID: return 515; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 9, true).ID: return 516; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 9, false).ID: return 517; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 10, true).ID: return 518; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 10, false).ID: return 519; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 11, true).ID: return 520; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 11, false).ID: return 521; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 12, true).ID: return 522; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 12, false).ID: return 523; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 13, true).ID: return 524; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 13, false).ID: return 525; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 14, true).ID: return 526; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 14, false).ID: return 527; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 15, true).ID: return 528; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 15, false).ID: return 529; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 16, true).ID: return 530; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 16, false).ID: return 531; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 17, true).ID: return 532; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 17, false).ID: return 533; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 18, true).ID: return 534; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 18, false).ID: return 535; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 19, true).ID: return 536; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 19, false).ID: return 537; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 20, true).ID: return 538; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 20, false).ID: return 539; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 21, true).ID: return 540; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 21, false).ID: return 541; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 22, true).ID: return 542; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 22, false).ID: return 543; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 23, true).ID: return 544; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 23, false).ID: return 545; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 24, true).ID: return 546; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 24, false).ID: return 547; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 0, true).ID: return 548; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 0, false).ID: return 549; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 1, true).ID: return 550; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 1, false).ID: return 551; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 2, true).ID: return 552; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 2, false).ID: return 553; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 3, true).ID: return 554; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 3, false).ID: return 555; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 4, true).ID: return 556; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 4, false).ID: return 557; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 5, true).ID: return 558; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 5, false).ID: return 559; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 6, true).ID: return 560; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 6, false).ID: return 561; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 7, true).ID: return 562; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 7, false).ID: return 563; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 8, true).ID: return 564; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 8, false).ID: return 565; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 9, true).ID: return 566; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 9, false).ID: return 567; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 10, true).ID: return 568; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 10, false).ID: return 569; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 11, true).ID: return 570; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 11, false).ID: return 571; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 12, true).ID: return 572; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 12, false).ID: return 573; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 13, true).ID: return 574; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 13, false).ID: return 575; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 14, true).ID: return 576; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 14, false).ID: return 577; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 15, true).ID: return 578; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 15, false).ID: return 579; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 16, true).ID: return 580; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 16, false).ID: return 581; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 17, true).ID: return 582; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 17, false).ID: return 583; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 18, true).ID: return 584; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 18, false).ID: return 585; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 19, true).ID: return 586; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 19, false).ID: return 587; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 20, true).ID: return 588; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 20, false).ID: return 589; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 21, true).ID: return 590; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 21, false).ID: return 591; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 22, true).ID: return 592; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 22, false).ID: return 593; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 23, true).ID: return 594; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 23, false).ID: return 595; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 24, true).ID: return 596; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 24, false).ID: return 597; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 0, true).ID: return 598; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 0, false).ID: return 599; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 1, true).ID: return 600; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 1, false).ID: return 601; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 2, true).ID: return 602; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 2, false).ID: return 603; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 3, true).ID: return 604; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 3, false).ID: return 605; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 4, true).ID: return 606; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 4, false).ID: return 607; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 5, true).ID: return 608; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 5, false).ID: return 609; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 6, true).ID: return 610; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 6, false).ID: return 611; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 7, true).ID: return 612; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 7, false).ID: return 613; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 8, true).ID: return 614; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 8, false).ID: return 615; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 9, true).ID: return 616; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 9, false).ID: return 617; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 10, true).ID: return 618; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 10, false).ID: return 619; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 11, true).ID: return 620; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 11, false).ID: return 621; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 12, true).ID: return 622; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 12, false).ID: return 623; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 13, true).ID: return 624; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 13, false).ID: return 625; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 14, true).ID: return 626; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 14, false).ID: return 627; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 15, true).ID: return 628; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 15, false).ID: return 629; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 16, true).ID: return 630; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 16, false).ID: return 631; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 17, true).ID: return 632; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 17, false).ID: return 633; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 18, true).ID: return 634; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 18, false).ID: return 635; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 19, true).ID: return 636; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 19, false).ID: return 637; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 20, true).ID: return 638; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 20, false).ID: return 639; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 21, true).ID: return 640; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 21, false).ID: return 641; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 22, true).ID: return 642; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 22, false).ID: return 643; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 23, true).ID: return 644; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 23, false).ID: return 645; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 24, true).ID: return 646; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 24, false).ID: return 647; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 0, true).ID: return 648; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 0, false).ID: return 649; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 1, true).ID: return 650; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 1, false).ID: return 651; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 2, true).ID: return 652; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 2, false).ID: return 653; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 3, true).ID: return 654; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 3, false).ID: return 655; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 4, true).ID: return 656; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 4, false).ID: return 657; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 5, true).ID: return 658; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 5, false).ID: return 659; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 6, true).ID: return 660; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 6, false).ID: return 661; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 7, true).ID: return 662; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 7, false).ID: return 663; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 8, true).ID: return 664; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 8, false).ID: return 665; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 9, true).ID: return 666; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 9, false).ID: return 667; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 10, true).ID: return 668; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 10, false).ID: return 669; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 11, true).ID: return 670; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 11, false).ID: return 671; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 12, true).ID: return 672; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 12, false).ID: return 673; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 13, true).ID: return 674; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 13, false).ID: return 675; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 14, true).ID: return 676; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 14, false).ID: return 677; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 15, true).ID: return 678; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 15, false).ID: return 679; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 16, true).ID: return 680; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 16, false).ID: return 681; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 17, true).ID: return 682; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 17, false).ID: return 683; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 18, true).ID: return 684; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 18, false).ID: return 685; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 19, true).ID: return 686; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 19, false).ID: return 687; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 20, true).ID: return 688; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 20, false).ID: return 689; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 21, true).ID: return 690; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 21, false).ID: return 691; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 22, true).ID: return 692; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 22, false).ID: return 693; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 23, true).ID: return 694; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 23, false).ID: return 695; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 24, true).ID: return 696; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 24, false).ID: return 697; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 0, true).ID: return 698; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 0, false).ID: return 699; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 1, true).ID: return 700; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 1, false).ID: return 701; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 2, true).ID: return 702; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 2, false).ID: return 703; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 3, true).ID: return 704; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 3, false).ID: return 705; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 4, true).ID: return 706; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 4, false).ID: return 707; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 5, true).ID: return 708; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 5, false).ID: return 709; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 6, true).ID: return 710; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 6, false).ID: return 711; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 7, true).ID: return 712; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 7, false).ID: return 713; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 8, true).ID: return 714; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 8, false).ID: return 715; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 9, true).ID: return 716; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 9, false).ID: return 717; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 10, true).ID: return 718; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 10, false).ID: return 719; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 11, true).ID: return 720; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 11, false).ID: return 721; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 12, true).ID: return 722; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 12, false).ID: return 723; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 13, true).ID: return 724; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 13, false).ID: return 725; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 14, true).ID: return 726; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 14, false).ID: return 727; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 15, true).ID: return 728; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 15, false).ID: return 729; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 16, true).ID: return 730; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 16, false).ID: return 731; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 17, true).ID: return 732; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 17, false).ID: return 733; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 18, true).ID: return 734; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 18, false).ID: return 735; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 19, true).ID: return 736; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 19, false).ID: return 737; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 20, true).ID: return 738; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 20, false).ID: return 739; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 21, true).ID: return 740; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 21, false).ID: return 741; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 22, true).ID: return 742; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 22, false).ID: return 743; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 23, true).ID: return 744; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 23, false).ID: return 745; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 24, true).ID: return 746; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 24, false).ID: return 747; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 0, true).ID: return 748; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 0, false).ID: return 749; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 1, true).ID: return 750; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 1, false).ID: return 751; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 2, true).ID: return 752; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 2, false).ID: return 753; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 3, true).ID: return 754; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 3, false).ID: return 755; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 4, true).ID: return 756; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 4, false).ID: return 757; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 5, true).ID: return 758; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 5, false).ID: return 759; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 6, true).ID: return 760; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 6, false).ID: return 761; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 7, true).ID: return 762; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 7, false).ID: return 763; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 8, true).ID: return 764; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 8, false).ID: return 765; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 9, true).ID: return 766; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 9, false).ID: return 767; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 10, true).ID: return 768; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 10, false).ID: return 769; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 11, true).ID: return 770; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 11, false).ID: return 771; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 12, true).ID: return 772; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 12, false).ID: return 773; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 13, true).ID: return 774; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 13, false).ID: return 775; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 14, true).ID: return 776; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 14, false).ID: return 777; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 15, true).ID: return 778; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 15, false).ID: return 779; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 16, true).ID: return 780; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 16, false).ID: return 781; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 17, true).ID: return 782; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 17, false).ID: return 783; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 18, true).ID: return 784; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 18, false).ID: return 785; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 19, true).ID: return 786; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 19, false).ID: return 787; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 20, true).ID: return 788; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 20, false).ID: return 789; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 21, true).ID: return 790; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 21, false).ID: return 791; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 22, true).ID: return 792; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 22, false).ID: return 793; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 23, true).ID: return 794; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 23, false).ID: return 795; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 24, true).ID: return 796; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 24, false).ID: return 797; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 0, true).ID: return 798; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 0, false).ID: return 799; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 1, true).ID: return 800; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 1, false).ID: return 801; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 2, true).ID: return 802; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 2, false).ID: return 803; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 3, true).ID: return 804; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 3, false).ID: return 805; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 4, true).ID: return 806; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 4, false).ID: return 807; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 5, true).ID: return 808; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 5, false).ID: return 809; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 6, true).ID: return 810; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 6, false).ID: return 811; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 7, true).ID: return 812; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 7, false).ID: return 813; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 8, true).ID: return 814; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 8, false).ID: return 815; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 9, true).ID: return 816; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 9, false).ID: return 817; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 10, true).ID: return 818; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 10, false).ID: return 819; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 11, true).ID: return 820; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 11, false).ID: return 821; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 12, true).ID: return 822; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 12, false).ID: return 823; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 13, true).ID: return 824; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 13, false).ID: return 825; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 14, true).ID: return 826; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 14, false).ID: return 827; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 15, true).ID: return 828; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 15, false).ID: return 829; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 16, true).ID: return 830; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 16, false).ID: return 831; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 17, true).ID: return 832; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 17, false).ID: return 833; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 18, true).ID: return 834; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 18, false).ID: return 835; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 19, true).ID: return 836; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 19, false).ID: return 837; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 20, true).ID: return 838; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 20, false).ID: return 839; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 21, true).ID: return 840; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 21, false).ID: return 841; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 22, true).ID: return 842; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 22, false).ID: return 843; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 23, true).ID: return 844; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 23, false).ID: return 845; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 24, true).ID: return 846; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 24, false).ID: return 847; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 0, true).ID: return 848; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 0, false).ID: return 849; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 1, true).ID: return 850; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 1, false).ID: return 851; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 2, true).ID: return 852; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 2, false).ID: return 853; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 3, true).ID: return 854; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 3, false).ID: return 855; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 4, true).ID: return 856; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 4, false).ID: return 857; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 5, true).ID: return 858; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 5, false).ID: return 859; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 6, true).ID: return 860; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 6, false).ID: return 861; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 7, true).ID: return 862; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 7, false).ID: return 863; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 8, true).ID: return 864; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 8, false).ID: return 865; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 9, true).ID: return 866; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 9, false).ID: return 867; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 10, true).ID: return 868; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 10, false).ID: return 869; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 11, true).ID: return 870; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 11, false).ID: return 871; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 12, true).ID: return 872; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 12, false).ID: return 873; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 13, true).ID: return 874; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 13, false).ID: return 875; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 14, true).ID: return 876; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 14, false).ID: return 877; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 15, true).ID: return 878; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 15, false).ID: return 879; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 16, true).ID: return 880; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 16, false).ID: return 881; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 17, true).ID: return 882; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 17, false).ID: return 883; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 18, true).ID: return 884; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 18, false).ID: return 885; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 19, true).ID: return 886; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 19, false).ID: return 887; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 20, true).ID: return 888; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 20, false).ID: return 889; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 21, true).ID: return 890; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 21, false).ID: return 891; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 22, true).ID: return 892; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 22, false).ID: return 893; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 23, true).ID: return 894; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 23, false).ID: return 895; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 24, true).ID: return 896; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 24, false).ID: return 897; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 0, true).ID: return 898; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 0, false).ID: return 899; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 1, true).ID: return 900; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 1, false).ID: return 901; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 2, true).ID: return 902; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 2, false).ID: return 903; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 3, true).ID: return 904; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 3, false).ID: return 905; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 4, true).ID: return 906; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 4, false).ID: return 907; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 5, true).ID: return 908; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 5, false).ID: return 909; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 6, true).ID: return 910; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 6, false).ID: return 911; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 7, true).ID: return 912; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 7, false).ID: return 913; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 8, true).ID: return 914; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 8, false).ID: return 915; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 9, true).ID: return 916; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 9, false).ID: return 917; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 10, true).ID: return 918; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 10, false).ID: return 919; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 11, true).ID: return 920; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 11, false).ID: return 921; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 12, true).ID: return 922; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 12, false).ID: return 923; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 13, true).ID: return 924; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 13, false).ID: return 925; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 14, true).ID: return 926; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 14, false).ID: return 927; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 15, true).ID: return 928; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 15, false).ID: return 929; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 16, true).ID: return 930; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 16, false).ID: return 931; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 17, true).ID: return 932; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 17, false).ID: return 933; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 18, true).ID: return 934; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 18, false).ID: return 935; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 19, true).ID: return 936; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 19, false).ID: return 937; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 20, true).ID: return 938; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 20, false).ID: return 939; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 21, true).ID: return 940; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 21, false).ID: return 941; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 22, true).ID: return 942; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 22, false).ID: return 943; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 23, true).ID: return 944; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 23, false).ID: return 945; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 24, true).ID: return 946; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 24, false).ID: return 947; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 0, true).ID: return 948; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 0, false).ID: return 949; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 1, true).ID: return 950; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 1, false).ID: return 951; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 2, true).ID: return 952; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 2, false).ID: return 953; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 3, true).ID: return 954; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 3, false).ID: return 955; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 4, true).ID: return 956; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 4, false).ID: return 957; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 5, true).ID: return 958; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 5, false).ID: return 959; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 6, true).ID: return 960; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 6, false).ID: return 961; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 7, true).ID: return 962; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 7, false).ID: return 963; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 8, true).ID: return 964; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 8, false).ID: return 965; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 9, true).ID: return 966; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 9, false).ID: return 967; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 10, true).ID: return 968; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 10, false).ID: return 969; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 11, true).ID: return 970; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 11, false).ID: return 971; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 12, true).ID: return 972; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 12, false).ID: return 973; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 13, true).ID: return 974; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 13, false).ID: return 975; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 14, true).ID: return 976; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 14, false).ID: return 977; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 15, true).ID: return 978; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 15, false).ID: return 979; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 16, true).ID: return 980; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 16, false).ID: return 981; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 17, true).ID: return 982; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 17, false).ID: return 983; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 18, true).ID: return 984; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 18, false).ID: return 985; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 19, true).ID: return 986; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 19, false).ID: return 987; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 20, true).ID: return 988; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 20, false).ID: return 989; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 21, true).ID: return 990; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 21, false).ID: return 991; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 22, true).ID: return 992; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 22, false).ID: return 993; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 23, true).ID: return 994; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 23, false).ID: return 995; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 24, true).ID: return 996; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 24, false).ID: return 997; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 0, true).ID: return 998; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 0, false).ID: return 999; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 1, true).ID: return 1000; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 1, false).ID: return 1001; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 2, true).ID: return 1002; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 2, false).ID: return 1003; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 3, true).ID: return 1004; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 3, false).ID: return 1005; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 4, true).ID: return 1006; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 4, false).ID: return 1007; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 5, true).ID: return 1008; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 5, false).ID: return 1009; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 6, true).ID: return 1010; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 6, false).ID: return 1011; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 7, true).ID: return 1012; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 7, false).ID: return 1013; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 8, true).ID: return 1014; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 8, false).ID: return 1015; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 9, true).ID: return 1016; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 9, false).ID: return 1017; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 10, true).ID: return 1018; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 10, false).ID: return 1019; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 11, true).ID: return 1020; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 11, false).ID: return 1021; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 12, true).ID: return 1022; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 12, false).ID: return 1023; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 13, true).ID: return 1024; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 13, false).ID: return 1025; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 14, true).ID: return 1026; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 14, false).ID: return 1027; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 15, true).ID: return 1028; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 15, false).ID: return 1029; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 16, true).ID: return 1030; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 16, false).ID: return 1031; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 17, true).ID: return 1032; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 17, false).ID: return 1033; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 18, true).ID: return 1034; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 18, false).ID: return 1035; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 19, true).ID: return 1036; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 19, false).ID: return 1037; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 20, true).ID: return 1038; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 20, false).ID: return 1039; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 21, true).ID: return 1040; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 21, false).ID: return 1041; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 22, true).ID: return 1042; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 22, false).ID: return 1043; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 23, true).ID: return 1044; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 23, false).ID: return 1045; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 24, true).ID: return 1046; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 24, false).ID: return 1047; case OakButton::OakButton(OakButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5810; case OakButton::OakButton(OakButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5811; case OakButton::OakButton(OakButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5812; case OakButton::OakButton(OakButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5813; case OakButton::OakButton(OakButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, true).ID: return 5814; case OakButton::OakButton(OakButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, false).ID: return 5815; case OakButton::OakButton(OakButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, true).ID: return 5816; case OakButton::OakButton(OakButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, false).ID: return 5817; case OakButton::OakButton(OakButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5818; case OakButton::OakButton(OakButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5819; case OakButton::OakButton(OakButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5820; case OakButton::OakButton(OakButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5821; case OakButton::OakButton(OakButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, true).ID: return 5822; case OakButton::OakButton(OakButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, false).ID: return 5823; case OakButton::OakButton(OakButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, true).ID: return 5824; case OakButton::OakButton(OakButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, false).ID: return 5825; case OakButton::OakButton(OakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5826; case OakButton::OakButton(OakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5827; case OakButton::OakButton(OakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5828; case OakButton::OakButton(OakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5829; case OakButton::OakButton(OakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, true).ID: return 5830; case OakButton::OakButton(OakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, false).ID: return 5831; case OakButton::OakButton(OakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, true).ID: return 5832; case OakButton::OakButton(OakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, false).ID: return 5833; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Upper, OakDoor::Hinge::Left, true, true).ID: return 3571; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Upper, OakDoor::Hinge::Left, true, false).ID: return 3572; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Upper, OakDoor::Hinge::Left, false, true).ID: return 3573; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Upper, OakDoor::Hinge::Left, false, false).ID: return 3574; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Upper, OakDoor::Hinge::Right, true, true).ID: return 3575; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Upper, OakDoor::Hinge::Right, true, false).ID: return 3576; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Upper, OakDoor::Hinge::Right, false, true).ID: return 3577; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Upper, OakDoor::Hinge::Right, false, false).ID: return 3578; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Lower, OakDoor::Hinge::Left, true, true).ID: return 3579; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Lower, OakDoor::Hinge::Left, true, false).ID: return 3580; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Lower, OakDoor::Hinge::Left, false, true).ID: return 3581; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Lower, OakDoor::Hinge::Left, false, false).ID: return 3582; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Lower, OakDoor::Hinge::Right, true, true).ID: return 3583; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Lower, OakDoor::Hinge::Right, true, false).ID: return 3584; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Lower, OakDoor::Hinge::Right, false, true).ID: return 3585; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Lower, OakDoor::Hinge::Right, false, false).ID: return 3586; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Upper, OakDoor::Hinge::Left, true, true).ID: return 3587; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Upper, OakDoor::Hinge::Left, true, false).ID: return 3588; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Upper, OakDoor::Hinge::Left, false, true).ID: return 3589; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Upper, OakDoor::Hinge::Left, false, false).ID: return 3590; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Upper, OakDoor::Hinge::Right, true, true).ID: return 3591; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Upper, OakDoor::Hinge::Right, true, false).ID: return 3592; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Upper, OakDoor::Hinge::Right, false, true).ID: return 3593; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Upper, OakDoor::Hinge::Right, false, false).ID: return 3594; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Lower, OakDoor::Hinge::Left, true, true).ID: return 3595; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Lower, OakDoor::Hinge::Left, true, false).ID: return 3596; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Lower, OakDoor::Hinge::Left, false, true).ID: return 3597; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Lower, OakDoor::Hinge::Left, false, false).ID: return 3598; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Lower, OakDoor::Hinge::Right, true, true).ID: return 3599; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Lower, OakDoor::Hinge::Right, true, false).ID: return 3600; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Lower, OakDoor::Hinge::Right, false, true).ID: return 3601; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Lower, OakDoor::Hinge::Right, false, false).ID: return 3602; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Upper, OakDoor::Hinge::Left, true, true).ID: return 3603; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Upper, OakDoor::Hinge::Left, true, false).ID: return 3604; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Upper, OakDoor::Hinge::Left, false, true).ID: return 3605; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Upper, OakDoor::Hinge::Left, false, false).ID: return 3606; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Upper, OakDoor::Hinge::Right, true, true).ID: return 3607; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Upper, OakDoor::Hinge::Right, true, false).ID: return 3608; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Upper, OakDoor::Hinge::Right, false, true).ID: return 3609; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Upper, OakDoor::Hinge::Right, false, false).ID: return 3610; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Lower, OakDoor::Hinge::Left, true, true).ID: return 3611; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Lower, OakDoor::Hinge::Left, true, false).ID: return 3612; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Lower, OakDoor::Hinge::Left, false, true).ID: return 3613; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Lower, OakDoor::Hinge::Left, false, false).ID: return 3614; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Lower, OakDoor::Hinge::Right, true, true).ID: return 3615; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Lower, OakDoor::Hinge::Right, true, false).ID: return 3616; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Lower, OakDoor::Hinge::Right, false, true).ID: return 3617; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Lower, OakDoor::Hinge::Right, false, false).ID: return 3618; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Upper, OakDoor::Hinge::Left, true, true).ID: return 3619; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Upper, OakDoor::Hinge::Left, true, false).ID: return 3620; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Upper, OakDoor::Hinge::Left, false, true).ID: return 3621; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Upper, OakDoor::Hinge::Left, false, false).ID: return 3622; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Upper, OakDoor::Hinge::Right, true, true).ID: return 3623; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Upper, OakDoor::Hinge::Right, true, false).ID: return 3624; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Upper, OakDoor::Hinge::Right, false, true).ID: return 3625; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Upper, OakDoor::Hinge::Right, false, false).ID: return 3626; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Lower, OakDoor::Hinge::Left, true, true).ID: return 3627; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Lower, OakDoor::Hinge::Left, true, false).ID: return 3628; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Lower, OakDoor::Hinge::Left, false, true).ID: return 3629; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Lower, OakDoor::Hinge::Left, false, false).ID: return 3630; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Lower, OakDoor::Hinge::Right, true, true).ID: return 3631; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Lower, OakDoor::Hinge::Right, true, false).ID: return 3632; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Lower, OakDoor::Hinge::Right, false, true).ID: return 3633; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Lower, OakDoor::Hinge::Right, false, false).ID: return 3634; case OakFence::OakFence(true, true, true, true).ID: return 3966; case OakFence::OakFence(true, true, true, false).ID: return 3967; case OakFence::OakFence(true, true, false, true).ID: return 3970; case OakFence::OakFence(true, true, false, false).ID: return 3971; case OakFence::OakFence(true, false, true, true).ID: return 3974; case OakFence::OakFence(true, false, true, false).ID: return 3975; case OakFence::OakFence(true, false, false, true).ID: return 3978; case OakFence::OakFence(true, false, false, false).ID: return 3979; case OakFence::OakFence(false, true, true, true).ID: return 3982; case OakFence::OakFence(false, true, true, false).ID: return 3983; case OakFence::OakFence(false, true, false, true).ID: return 3986; case OakFence::OakFence(false, true, false, false).ID: return 3987; case OakFence::OakFence(false, false, true, true).ID: return 3990; case OakFence::OakFence(false, false, true, false).ID: return 3991; case OakFence::OakFence(false, false, false, true).ID: return 3994; case OakFence::OakFence(false, false, false, false).ID: return 3995; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZM, true, true, true).ID: return 4804; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZM, true, true, false).ID: return 4805; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZM, true, false, true).ID: return 4806; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZM, true, false, false).ID: return 4807; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, true).ID: return 4808; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, false).ID: return 4809; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, true).ID: return 4810; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, false).ID: return 4811; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZP, true, true, true).ID: return 4812; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZP, true, true, false).ID: return 4813; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZP, true, false, true).ID: return 4814; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZP, true, false, false).ID: return 4815; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, true).ID: return 4816; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, false).ID: return 4817; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, true).ID: return 4818; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, false).ID: return 4819; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XM, true, true, true).ID: return 4820; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XM, true, true, false).ID: return 4821; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XM, true, false, true).ID: return 4822; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XM, true, false, false).ID: return 4823; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, true).ID: return 4824; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, false).ID: return 4825; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, true).ID: return 4826; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, false).ID: return 4827; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XP, true, true, true).ID: return 4828; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XP, true, true, false).ID: return 4829; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XP, true, false, true).ID: return 4830; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XP, true, false, false).ID: return 4831; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, true).ID: return 4832; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, false).ID: return 4833; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, true).ID: return 4834; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, false).ID: return 4835; case OakLeaves::OakLeaves(1, true).ID: return 144; case OakLeaves::OakLeaves(1, false).ID: return 145; case OakLeaves::OakLeaves(2, true).ID: return 146; case OakLeaves::OakLeaves(2, false).ID: return 147; case OakLeaves::OakLeaves(3, true).ID: return 148; case OakLeaves::OakLeaves(3, false).ID: return 149; case OakLeaves::OakLeaves(4, true).ID: return 150; case OakLeaves::OakLeaves(4, false).ID: return 151; case OakLeaves::OakLeaves(5, true).ID: return 152; case OakLeaves::OakLeaves(5, false).ID: return 153; case OakLeaves::OakLeaves(6, true).ID: return 154; case OakLeaves::OakLeaves(6, false).ID: return 155; case OakLeaves::OakLeaves(7, true).ID: return 156; case OakLeaves::OakLeaves(7, false).ID: return 157; case OakLog::OakLog(OakLog::Axis::X).ID: return 72; case OakLog::OakLog(OakLog::Axis::Y).ID: return 73; case OakLog::OakLog(OakLog::Axis::Z).ID: return 74; case OakPlanks::OakPlanks().ID: return 15; case OakPressurePlate::OakPressurePlate(true).ID: return 3871; case OakPressurePlate::OakPressurePlate(false).ID: return 3872; case OakSapling::OakSapling(0).ID: return 21; case OakSapling::OakSapling(1).ID: return 22; case OakSign::OakSign(0).ID: return 3380; case OakSign::OakSign(1).ID: return 3382; case OakSign::OakSign(2).ID: return 3384; case OakSign::OakSign(3).ID: return 3386; case OakSign::OakSign(4).ID: return 3388; case OakSign::OakSign(5).ID: return 3390; case OakSign::OakSign(6).ID: return 3392; case OakSign::OakSign(7).ID: return 3394; case OakSign::OakSign(8).ID: return 3396; case OakSign::OakSign(9).ID: return 3398; case OakSign::OakSign(10).ID: return 3400; case OakSign::OakSign(11).ID: return 3402; case OakSign::OakSign(12).ID: return 3404; case OakSign::OakSign(13).ID: return 3406; case OakSign::OakSign(14).ID: return 3408; case OakSign::OakSign(15).ID: return 3410; case OakSlab::OakSlab(OakSlab::Type::Top).ID: return 7765; case OakSlab::OakSlab(OakSlab::Type::Bottom).ID: return 7767; case OakSlab::OakSlab(OakSlab::Type::Double).ID: return 7769; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZM, OakStairs::Half::Top, OakStairs::Shape::Straight).ID: return 1953; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZM, OakStairs::Half::Top, OakStairs::Shape::InnerLeft).ID: return 1955; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZM, OakStairs::Half::Top, OakStairs::Shape::InnerRight).ID: return 1957; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZM, OakStairs::Half::Top, OakStairs::Shape::OuterLeft).ID: return 1959; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZM, OakStairs::Half::Top, OakStairs::Shape::OuterRight).ID: return 1961; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZM, OakStairs::Half::Bottom, OakStairs::Shape::Straight).ID: return 1963; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZM, OakStairs::Half::Bottom, OakStairs::Shape::InnerLeft).ID: return 1965; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZM, OakStairs::Half::Bottom, OakStairs::Shape::InnerRight).ID: return 1967; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZM, OakStairs::Half::Bottom, OakStairs::Shape::OuterLeft).ID: return 1969; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZM, OakStairs::Half::Bottom, OakStairs::Shape::OuterRight).ID: return 1971; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZP, OakStairs::Half::Top, OakStairs::Shape::Straight).ID: return 1973; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZP, OakStairs::Half::Top, OakStairs::Shape::InnerLeft).ID: return 1975; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZP, OakStairs::Half::Top, OakStairs::Shape::InnerRight).ID: return 1977; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZP, OakStairs::Half::Top, OakStairs::Shape::OuterLeft).ID: return 1979; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZP, OakStairs::Half::Top, OakStairs::Shape::OuterRight).ID: return 1981; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZP, OakStairs::Half::Bottom, OakStairs::Shape::Straight).ID: return 1983; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZP, OakStairs::Half::Bottom, OakStairs::Shape::InnerLeft).ID: return 1985; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZP, OakStairs::Half::Bottom, OakStairs::Shape::InnerRight).ID: return 1987; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZP, OakStairs::Half::Bottom, OakStairs::Shape::OuterLeft).ID: return 1989; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZP, OakStairs::Half::Bottom, OakStairs::Shape::OuterRight).ID: return 1991; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XM, OakStairs::Half::Top, OakStairs::Shape::Straight).ID: return 1993; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XM, OakStairs::Half::Top, OakStairs::Shape::InnerLeft).ID: return 1995; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XM, OakStairs::Half::Top, OakStairs::Shape::InnerRight).ID: return 1997; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XM, OakStairs::Half::Top, OakStairs::Shape::OuterLeft).ID: return 1999; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XM, OakStairs::Half::Top, OakStairs::Shape::OuterRight).ID: return 2001; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XM, OakStairs::Half::Bottom, OakStairs::Shape::Straight).ID: return 2003; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XM, OakStairs::Half::Bottom, OakStairs::Shape::InnerLeft).ID: return 2005; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XM, OakStairs::Half::Bottom, OakStairs::Shape::InnerRight).ID: return 2007; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XM, OakStairs::Half::Bottom, OakStairs::Shape::OuterLeft).ID: return 2009; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XM, OakStairs::Half::Bottom, OakStairs::Shape::OuterRight).ID: return 2011; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XP, OakStairs::Half::Top, OakStairs::Shape::Straight).ID: return 2013; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XP, OakStairs::Half::Top, OakStairs::Shape::InnerLeft).ID: return 2015; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XP, OakStairs::Half::Top, OakStairs::Shape::InnerRight).ID: return 2017; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XP, OakStairs::Half::Top, OakStairs::Shape::OuterLeft).ID: return 2019; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XP, OakStairs::Half::Top, OakStairs::Shape::OuterRight).ID: return 2021; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XP, OakStairs::Half::Bottom, OakStairs::Shape::Straight).ID: return 2023; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XP, OakStairs::Half::Bottom, OakStairs::Shape::InnerLeft).ID: return 2025; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XP, OakStairs::Half::Bottom, OakStairs::Shape::InnerRight).ID: return 2027; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XP, OakStairs::Half::Bottom, OakStairs::Shape::OuterLeft).ID: return 2029; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XP, OakStairs::Half::Bottom, OakStairs::Shape::OuterRight).ID: return 2031; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZM, OakTrapdoor::Half::Top, true, true).ID: return 4098; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZM, OakTrapdoor::Half::Top, true, false).ID: return 4100; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZM, OakTrapdoor::Half::Top, false, true).ID: return 4102; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZM, OakTrapdoor::Half::Top, false, false).ID: return 4104; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZM, OakTrapdoor::Half::Bottom, true, true).ID: return 4106; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZM, OakTrapdoor::Half::Bottom, true, false).ID: return 4108; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZM, OakTrapdoor::Half::Bottom, false, true).ID: return 4110; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZM, OakTrapdoor::Half::Bottom, false, false).ID: return 4112; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZP, OakTrapdoor::Half::Top, true, true).ID: return 4114; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZP, OakTrapdoor::Half::Top, true, false).ID: return 4116; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZP, OakTrapdoor::Half::Top, false, true).ID: return 4118; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZP, OakTrapdoor::Half::Top, false, false).ID: return 4120; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZP, OakTrapdoor::Half::Bottom, true, true).ID: return 4122; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZP, OakTrapdoor::Half::Bottom, true, false).ID: return 4124; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZP, OakTrapdoor::Half::Bottom, false, true).ID: return 4126; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZP, OakTrapdoor::Half::Bottom, false, false).ID: return 4128; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XM, OakTrapdoor::Half::Top, true, true).ID: return 4130; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XM, OakTrapdoor::Half::Top, true, false).ID: return 4132; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XM, OakTrapdoor::Half::Top, false, true).ID: return 4134; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XM, OakTrapdoor::Half::Top, false, false).ID: return 4136; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XM, OakTrapdoor::Half::Bottom, true, true).ID: return 4138; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XM, OakTrapdoor::Half::Bottom, true, false).ID: return 4140; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XM, OakTrapdoor::Half::Bottom, false, true).ID: return 4142; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XM, OakTrapdoor::Half::Bottom, false, false).ID: return 4144; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XP, OakTrapdoor::Half::Top, true, true).ID: return 4146; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XP, OakTrapdoor::Half::Top, true, false).ID: return 4148; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XP, OakTrapdoor::Half::Top, false, true).ID: return 4150; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XP, OakTrapdoor::Half::Top, false, false).ID: return 4152; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XP, OakTrapdoor::Half::Bottom, true, true).ID: return 4154; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XP, OakTrapdoor::Half::Bottom, true, false).ID: return 4156; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XP, OakTrapdoor::Half::Bottom, false, true).ID: return 4158; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XP, OakTrapdoor::Half::Bottom, false, false).ID: return 4160; case OakWallSign::OakWallSign(eBlockFace::BLOCK_FACE_ZM).ID: return 3734; case OakWallSign::OakWallSign(eBlockFace::BLOCK_FACE_ZP).ID: return 3736; case OakWallSign::OakWallSign(eBlockFace::BLOCK_FACE_XM).ID: return 3738; case OakWallSign::OakWallSign(eBlockFace::BLOCK_FACE_XP).ID: return 3740; case OakWood::OakWood(OakWood::Axis::X).ID: return 108; case OakWood::OakWood(OakWood::Axis::Y).ID: return 109; case OakWood::OakWood(OakWood::Axis::Z).ID: return 110; case Observer::Observer(eBlockFace::BLOCK_FACE_ZM, true).ID: return 8724; case Observer::Observer(eBlockFace::BLOCK_FACE_ZM, false).ID: return 8725; case Observer::Observer(eBlockFace::BLOCK_FACE_XP, true).ID: return 8726; case Observer::Observer(eBlockFace::BLOCK_FACE_XP, false).ID: return 8727; case Observer::Observer(eBlockFace::BLOCK_FACE_ZP, true).ID: return 8728; case Observer::Observer(eBlockFace::BLOCK_FACE_ZP, false).ID: return 8729; case Observer::Observer(eBlockFace::BLOCK_FACE_XM, true).ID: return 8730; case Observer::Observer(eBlockFace::BLOCK_FACE_XM, false).ID: return 8731; case Observer::Observer(eBlockFace::BLOCK_FACE_YP, true).ID: return 8732; case Observer::Observer(eBlockFace::BLOCK_FACE_YP, false).ID: return 8733; case Observer::Observer(eBlockFace::BLOCK_FACE_YM, true).ID: return 8734; case Observer::Observer(eBlockFace::BLOCK_FACE_YM, false).ID: return 8735; case Obsidian::Obsidian().ID: return 1433; case OrangeBanner::OrangeBanner(0).ID: return 7377; case OrangeBanner::OrangeBanner(1).ID: return 7378; case OrangeBanner::OrangeBanner(2).ID: return 7379; case OrangeBanner::OrangeBanner(3).ID: return 7380; case OrangeBanner::OrangeBanner(4).ID: return 7381; case OrangeBanner::OrangeBanner(5).ID: return 7382; case OrangeBanner::OrangeBanner(6).ID: return 7383; case OrangeBanner::OrangeBanner(7).ID: return 7384; case OrangeBanner::OrangeBanner(8).ID: return 7385; case OrangeBanner::OrangeBanner(9).ID: return 7386; case OrangeBanner::OrangeBanner(10).ID: return 7387; case OrangeBanner::OrangeBanner(11).ID: return 7388; case OrangeBanner::OrangeBanner(12).ID: return 7389; case OrangeBanner::OrangeBanner(13).ID: return 7390; case OrangeBanner::OrangeBanner(14).ID: return 7391; case OrangeBanner::OrangeBanner(15).ID: return 7392; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_ZM, true, OrangeBed::Part::Head).ID: return 1064; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_ZM, true, OrangeBed::Part::Foot).ID: return 1065; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_ZM, false, OrangeBed::Part::Head).ID: return 1066; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_ZM, false, OrangeBed::Part::Foot).ID: return 1067; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_ZP, true, OrangeBed::Part::Head).ID: return 1068; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_ZP, true, OrangeBed::Part::Foot).ID: return 1069; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_ZP, false, OrangeBed::Part::Head).ID: return 1070; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_ZP, false, OrangeBed::Part::Foot).ID: return 1071; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_XM, true, OrangeBed::Part::Head).ID: return 1072; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_XM, true, OrangeBed::Part::Foot).ID: return 1073; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_XM, false, OrangeBed::Part::Head).ID: return 1074; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_XM, false, OrangeBed::Part::Foot).ID: return 1075; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_XP, true, OrangeBed::Part::Head).ID: return 1076; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_XP, true, OrangeBed::Part::Foot).ID: return 1077; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_XP, false, OrangeBed::Part::Head).ID: return 1078; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_XP, false, OrangeBed::Part::Foot).ID: return 1079; case OrangeCarpet::OrangeCarpet().ID: return 7331; case OrangeConcrete::OrangeConcrete().ID: return 8903; case OrangeConcretePowder::OrangeConcretePowder().ID: return 8919; case OrangeGlazedTerracotta::OrangeGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 8842; case OrangeGlazedTerracotta::OrangeGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 8843; case OrangeGlazedTerracotta::OrangeGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 8844; case OrangeGlazedTerracotta::OrangeGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 8845; case OrangeShulkerBox::OrangeShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 8748; case OrangeShulkerBox::OrangeShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 8749; case OrangeShulkerBox::OrangeShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 8750; case OrangeShulkerBox::OrangeShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 8751; case OrangeShulkerBox::OrangeShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 8752; case OrangeShulkerBox::OrangeShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 8753; case OrangeStainedGlass::OrangeStainedGlass().ID: return 4082; case OrangeStainedGlassPane::OrangeStainedGlassPane(true, true, true, true).ID: return 6361; case OrangeStainedGlassPane::OrangeStainedGlassPane(true, true, true, false).ID: return 6362; case OrangeStainedGlassPane::OrangeStainedGlassPane(true, true, false, true).ID: return 6365; case OrangeStainedGlassPane::OrangeStainedGlassPane(true, true, false, false).ID: return 6366; case OrangeStainedGlassPane::OrangeStainedGlassPane(true, false, true, true).ID: return 6369; case OrangeStainedGlassPane::OrangeStainedGlassPane(true, false, true, false).ID: return 6370; case OrangeStainedGlassPane::OrangeStainedGlassPane(true, false, false, true).ID: return 6373; case OrangeStainedGlassPane::OrangeStainedGlassPane(true, false, false, false).ID: return 6374; case OrangeStainedGlassPane::OrangeStainedGlassPane(false, true, true, true).ID: return 6377; case OrangeStainedGlassPane::OrangeStainedGlassPane(false, true, true, false).ID: return 6378; case OrangeStainedGlassPane::OrangeStainedGlassPane(false, true, false, true).ID: return 6381; case OrangeStainedGlassPane::OrangeStainedGlassPane(false, true, false, false).ID: return 6382; case OrangeStainedGlassPane::OrangeStainedGlassPane(false, false, true, true).ID: return 6385; case OrangeStainedGlassPane::OrangeStainedGlassPane(false, false, true, false).ID: return 6386; case OrangeStainedGlassPane::OrangeStainedGlassPane(false, false, false, true).ID: return 6389; case OrangeStainedGlassPane::OrangeStainedGlassPane(false, false, false, false).ID: return 6390; case OrangeTerracotta::OrangeTerracotta().ID: return 6312; case OrangeTulip::OrangeTulip().ID: return 1417; case OrangeWallBanner::OrangeWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 7621; case OrangeWallBanner::OrangeWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 7622; case OrangeWallBanner::OrangeWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 7623; case OrangeWallBanner::OrangeWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 7624; case OrangeWool::OrangeWool().ID: return 1384; case OxeyeDaisy::OxeyeDaisy().ID: return 1420; case PackedIce::PackedIce().ID: return 7348; case Peony::Peony(Peony::Half::Upper).ID: return 7355; case Peony::Peony(Peony::Half::Lower).ID: return 7356; case PetrifiedOakSlab::PetrifiedOakSlab(PetrifiedOakSlab::Type::Top).ID: return 7825; case PetrifiedOakSlab::PetrifiedOakSlab(PetrifiedOakSlab::Type::Bottom).ID: return 7827; case PetrifiedOakSlab::PetrifiedOakSlab(PetrifiedOakSlab::Type::Double).ID: return 7829; case PinkBanner::PinkBanner(0).ID: return 7457; case PinkBanner::PinkBanner(1).ID: return 7458; case PinkBanner::PinkBanner(2).ID: return 7459; case PinkBanner::PinkBanner(3).ID: return 7460; case PinkBanner::PinkBanner(4).ID: return 7461; case PinkBanner::PinkBanner(5).ID: return 7462; case PinkBanner::PinkBanner(6).ID: return 7463; case PinkBanner::PinkBanner(7).ID: return 7464; case PinkBanner::PinkBanner(8).ID: return 7465; case PinkBanner::PinkBanner(9).ID: return 7466; case PinkBanner::PinkBanner(10).ID: return 7467; case PinkBanner::PinkBanner(11).ID: return 7468; case PinkBanner::PinkBanner(12).ID: return 7469; case PinkBanner::PinkBanner(13).ID: return 7470; case PinkBanner::PinkBanner(14).ID: return 7471; case PinkBanner::PinkBanner(15).ID: return 7472; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_ZM, true, PinkBed::Part::Head).ID: return 1144; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_ZM, true, PinkBed::Part::Foot).ID: return 1145; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_ZM, false, PinkBed::Part::Head).ID: return 1146; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_ZM, false, PinkBed::Part::Foot).ID: return 1147; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_ZP, true, PinkBed::Part::Head).ID: return 1148; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_ZP, true, PinkBed::Part::Foot).ID: return 1149; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_ZP, false, PinkBed::Part::Head).ID: return 1150; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_ZP, false, PinkBed::Part::Foot).ID: return 1151; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_XM, true, PinkBed::Part::Head).ID: return 1152; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_XM, true, PinkBed::Part::Foot).ID: return 1153; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_XM, false, PinkBed::Part::Head).ID: return 1154; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_XM, false, PinkBed::Part::Foot).ID: return 1155; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_XP, true, PinkBed::Part::Head).ID: return 1156; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_XP, true, PinkBed::Part::Foot).ID: return 1157; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_XP, false, PinkBed::Part::Head).ID: return 1158; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_XP, false, PinkBed::Part::Foot).ID: return 1159; case PinkCarpet::PinkCarpet().ID: return 7336; case PinkConcrete::PinkConcrete().ID: return 8908; case PinkConcretePowder::PinkConcretePowder().ID: return 8924; case PinkGlazedTerracotta::PinkGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 8862; case PinkGlazedTerracotta::PinkGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 8863; case PinkGlazedTerracotta::PinkGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 8864; case PinkGlazedTerracotta::PinkGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 8865; case PinkShulkerBox::PinkShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 8778; case PinkShulkerBox::PinkShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 8779; case PinkShulkerBox::PinkShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 8780; case PinkShulkerBox::PinkShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 8781; case PinkShulkerBox::PinkShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 8782; case PinkShulkerBox::PinkShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 8783; case PinkStainedGlass::PinkStainedGlass().ID: return 4087; case PinkStainedGlassPane::PinkStainedGlassPane(true, true, true, true).ID: return 6521; case PinkStainedGlassPane::PinkStainedGlassPane(true, true, true, false).ID: return 6522; case PinkStainedGlassPane::PinkStainedGlassPane(true, true, false, true).ID: return 6525; case PinkStainedGlassPane::PinkStainedGlassPane(true, true, false, false).ID: return 6526; case PinkStainedGlassPane::PinkStainedGlassPane(true, false, true, true).ID: return 6529; case PinkStainedGlassPane::PinkStainedGlassPane(true, false, true, false).ID: return 6530; case PinkStainedGlassPane::PinkStainedGlassPane(true, false, false, true).ID: return 6533; case PinkStainedGlassPane::PinkStainedGlassPane(true, false, false, false).ID: return 6534; case PinkStainedGlassPane::PinkStainedGlassPane(false, true, true, true).ID: return 6537; case PinkStainedGlassPane::PinkStainedGlassPane(false, true, true, false).ID: return 6538; case PinkStainedGlassPane::PinkStainedGlassPane(false, true, false, true).ID: return 6541; case PinkStainedGlassPane::PinkStainedGlassPane(false, true, false, false).ID: return 6542; case PinkStainedGlassPane::PinkStainedGlassPane(false, false, true, true).ID: return 6545; case PinkStainedGlassPane::PinkStainedGlassPane(false, false, true, false).ID: return 6546; case PinkStainedGlassPane::PinkStainedGlassPane(false, false, false, true).ID: return 6549; case PinkStainedGlassPane::PinkStainedGlassPane(false, false, false, false).ID: return 6550; case PinkTerracotta::PinkTerracotta().ID: return 6317; case PinkTulip::PinkTulip().ID: return 1419; case PinkWallBanner::PinkWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 7641; case PinkWallBanner::PinkWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 7642; case PinkWallBanner::PinkWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 7643; case PinkWallBanner::PinkWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 7644; case PinkWool::PinkWool().ID: return 1389; case Piston::Piston(true, eBlockFace::BLOCK_FACE_ZM).ID: return 1347; case Piston::Piston(true, eBlockFace::BLOCK_FACE_XP).ID: return 1348; case Piston::Piston(true, eBlockFace::BLOCK_FACE_ZP).ID: return 1349; case Piston::Piston(true, eBlockFace::BLOCK_FACE_XM).ID: return 1350; case Piston::Piston(true, eBlockFace::BLOCK_FACE_YP).ID: return 1351; case Piston::Piston(true, eBlockFace::BLOCK_FACE_YM).ID: return 1352; case Piston::Piston(false, eBlockFace::BLOCK_FACE_ZM).ID: return 1353; case Piston::Piston(false, eBlockFace::BLOCK_FACE_XP).ID: return 1354; case Piston::Piston(false, eBlockFace::BLOCK_FACE_ZP).ID: return 1355; case Piston::Piston(false, eBlockFace::BLOCK_FACE_XM).ID: return 1356; case Piston::Piston(false, eBlockFace::BLOCK_FACE_YP).ID: return 1357; case Piston::Piston(false, eBlockFace::BLOCK_FACE_YM).ID: return 1358; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_ZM, true, PistonHead::Type::Normal).ID: return 1359; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_ZM, true, PistonHead::Type::Sticky).ID: return 1360; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_ZM, false, PistonHead::Type::Normal).ID: return 1361; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_ZM, false, PistonHead::Type::Sticky).ID: return 1362; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_XP, true, PistonHead::Type::Normal).ID: return 1363; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_XP, true, PistonHead::Type::Sticky).ID: return 1364; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_XP, false, PistonHead::Type::Normal).ID: return 1365; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_XP, false, PistonHead::Type::Sticky).ID: return 1366; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_ZP, true, PistonHead::Type::Normal).ID: return 1367; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_ZP, true, PistonHead::Type::Sticky).ID: return 1368; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_ZP, false, PistonHead::Type::Normal).ID: return 1369; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_ZP, false, PistonHead::Type::Sticky).ID: return 1370; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_XM, true, PistonHead::Type::Normal).ID: return 1371; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_XM, true, PistonHead::Type::Sticky).ID: return 1372; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_XM, false, PistonHead::Type::Normal).ID: return 1373; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_XM, false, PistonHead::Type::Sticky).ID: return 1374; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_YP, true, PistonHead::Type::Normal).ID: return 1375; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_YP, true, PistonHead::Type::Sticky).ID: return 1376; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_YP, false, PistonHead::Type::Normal).ID: return 1377; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_YP, false, PistonHead::Type::Sticky).ID: return 1378; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_YM, true, PistonHead::Type::Normal).ID: return 1379; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_YM, true, PistonHead::Type::Sticky).ID: return 1380; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_YM, false, PistonHead::Type::Normal).ID: return 1381; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_YM, false, PistonHead::Type::Sticky).ID: return 1382; case PlayerHead::PlayerHead(0).ID: return 6014; case PlayerHead::PlayerHead(1).ID: return 6015; case PlayerHead::PlayerHead(2).ID: return 6016; case PlayerHead::PlayerHead(3).ID: return 6017; case PlayerHead::PlayerHead(4).ID: return 6018; case PlayerHead::PlayerHead(5).ID: return 6019; case PlayerHead::PlayerHead(6).ID: return 6020; case PlayerHead::PlayerHead(7).ID: return 6021; case PlayerHead::PlayerHead(8).ID: return 6022; case PlayerHead::PlayerHead(9).ID: return 6023; case PlayerHead::PlayerHead(10).ID: return 6024; case PlayerHead::PlayerHead(11).ID: return 6025; case PlayerHead::PlayerHead(12).ID: return 6026; case PlayerHead::PlayerHead(13).ID: return 6027; case PlayerHead::PlayerHead(14).ID: return 6028; case PlayerHead::PlayerHead(15).ID: return 6029; case PlayerWallHead::PlayerWallHead(eBlockFace::BLOCK_FACE_ZM).ID: return 6030; case PlayerWallHead::PlayerWallHead(eBlockFace::BLOCK_FACE_ZP).ID: return 6031; case PlayerWallHead::PlayerWallHead(eBlockFace::BLOCK_FACE_XM).ID: return 6032; case PlayerWallHead::PlayerWallHead(eBlockFace::BLOCK_FACE_XP).ID: return 6033; case Podzol::Podzol(true).ID: return 12; case Podzol::Podzol(false).ID: return 13; case PolishedAndesite::PolishedAndesite().ID: return 7; case PolishedAndesiteSlab::PolishedAndesiteSlab(PolishedAndesiteSlab::Type::Top).ID: return 10320; case PolishedAndesiteSlab::PolishedAndesiteSlab(PolishedAndesiteSlab::Type::Bottom).ID: return 10322; case PolishedAndesiteSlab::PolishedAndesiteSlab(PolishedAndesiteSlab::Type::Double).ID: return 10324; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedAndesiteStairs::Half::Top, PolishedAndesiteStairs::Shape::Straight).ID: return 10094; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedAndesiteStairs::Half::Top, PolishedAndesiteStairs::Shape::InnerLeft).ID: return 10096; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedAndesiteStairs::Half::Top, PolishedAndesiteStairs::Shape::InnerRight).ID: return 10098; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedAndesiteStairs::Half::Top, PolishedAndesiteStairs::Shape::OuterLeft).ID: return 10100; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedAndesiteStairs::Half::Top, PolishedAndesiteStairs::Shape::OuterRight).ID: return 10102; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedAndesiteStairs::Half::Bottom, PolishedAndesiteStairs::Shape::Straight).ID: return 10104; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedAndesiteStairs::Half::Bottom, PolishedAndesiteStairs::Shape::InnerLeft).ID: return 10106; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedAndesiteStairs::Half::Bottom, PolishedAndesiteStairs::Shape::InnerRight).ID: return 10108; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedAndesiteStairs::Half::Bottom, PolishedAndesiteStairs::Shape::OuterLeft).ID: return 10110; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedAndesiteStairs::Half::Bottom, PolishedAndesiteStairs::Shape::OuterRight).ID: return 10112; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedAndesiteStairs::Half::Top, PolishedAndesiteStairs::Shape::Straight).ID: return 10114; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedAndesiteStairs::Half::Top, PolishedAndesiteStairs::Shape::InnerLeft).ID: return 10116; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedAndesiteStairs::Half::Top, PolishedAndesiteStairs::Shape::InnerRight).ID: return 10118; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedAndesiteStairs::Half::Top, PolishedAndesiteStairs::Shape::OuterLeft).ID: return 10120; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedAndesiteStairs::Half::Top, PolishedAndesiteStairs::Shape::OuterRight).ID: return 10122; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedAndesiteStairs::Half::Bottom, PolishedAndesiteStairs::Shape::Straight).ID: return 10124; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedAndesiteStairs::Half::Bottom, PolishedAndesiteStairs::Shape::InnerLeft).ID: return 10126; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedAndesiteStairs::Half::Bottom, PolishedAndesiteStairs::Shape::InnerRight).ID: return 10128; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedAndesiteStairs::Half::Bottom, PolishedAndesiteStairs::Shape::OuterLeft).ID: return 10130; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedAndesiteStairs::Half::Bottom, PolishedAndesiteStairs::Shape::OuterRight).ID: return 10132; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_XM, PolishedAndesiteStairs::Half::Top, PolishedAndesiteStairs::Shape::Straight).ID: return 10134; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_XM, PolishedAndesiteStairs::Half::Top, PolishedAndesiteStairs::Shape::InnerLeft).ID: return 10136; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_XM, PolishedAndesiteStairs::Half::Top, PolishedAndesiteStairs::Shape::InnerRight).ID: return 10138; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_XM, PolishedAndesiteStairs::Half::Top, PolishedAndesiteStairs::Shape::OuterLeft).ID: return 10140; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_XM, PolishedAndesiteStairs::Half::Top, PolishedAndesiteStairs::Shape::OuterRight).ID: return 10142; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_XM, PolishedAndesiteStairs::Half::Bottom, PolishedAndesiteStairs::Shape::Straight).ID: return 10144; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_XM, PolishedAndesiteStairs::Half::Bottom, PolishedAndesiteStairs::Shape::InnerLeft).ID: return 10146; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_XM, PolishedAndesiteStairs::Half::Bottom, PolishedAndesiteStairs::Shape::InnerRight).ID: return 10148; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_XM, PolishedAndesiteStairs::Half::Bottom, PolishedAndesiteStairs::Shape::OuterLeft).ID: return 10150; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_XM, PolishedAndesiteStairs::Half::Bottom, PolishedAndesiteStairs::Shape::OuterRight).ID: return 10152; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_XP, PolishedAndesiteStairs::Half::Top, PolishedAndesiteStairs::Shape::Straight).ID: return 10154; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_XP, PolishedAndesiteStairs::Half::Top, PolishedAndesiteStairs::Shape::InnerLeft).ID: return 10156; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_XP, PolishedAndesiteStairs::Half::Top, PolishedAndesiteStairs::Shape::InnerRight).ID: return 10158; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_XP, PolishedAndesiteStairs::Half::Top, PolishedAndesiteStairs::Shape::OuterLeft).ID: return 10160; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_XP, PolishedAndesiteStairs::Half::Top, PolishedAndesiteStairs::Shape::OuterRight).ID: return 10162; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_XP, PolishedAndesiteStairs::Half::Bottom, PolishedAndesiteStairs::Shape::Straight).ID: return 10164; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_XP, PolishedAndesiteStairs::Half::Bottom, PolishedAndesiteStairs::Shape::InnerLeft).ID: return 10166; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_XP, PolishedAndesiteStairs::Half::Bottom, PolishedAndesiteStairs::Shape::InnerRight).ID: return 10168; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_XP, PolishedAndesiteStairs::Half::Bottom, PolishedAndesiteStairs::Shape::OuterLeft).ID: return 10170; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_XP, PolishedAndesiteStairs::Half::Bottom, PolishedAndesiteStairs::Shape::OuterRight).ID: return 10172; case PolishedDiorite::PolishedDiorite().ID: return 5; case PolishedDioriteSlab::PolishedDioriteSlab(PolishedDioriteSlab::Type::Top).ID: return 10272; case PolishedDioriteSlab::PolishedDioriteSlab(PolishedDioriteSlab::Type::Bottom).ID: return 10274; case PolishedDioriteSlab::PolishedDioriteSlab(PolishedDioriteSlab::Type::Double).ID: return 10276; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedDioriteStairs::Half::Top, PolishedDioriteStairs::Shape::Straight).ID: return 9374; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedDioriteStairs::Half::Top, PolishedDioriteStairs::Shape::InnerLeft).ID: return 9376; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedDioriteStairs::Half::Top, PolishedDioriteStairs::Shape::InnerRight).ID: return 9378; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedDioriteStairs::Half::Top, PolishedDioriteStairs::Shape::OuterLeft).ID: return 9380; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedDioriteStairs::Half::Top, PolishedDioriteStairs::Shape::OuterRight).ID: return 9382; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedDioriteStairs::Half::Bottom, PolishedDioriteStairs::Shape::Straight).ID: return 9384; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedDioriteStairs::Half::Bottom, PolishedDioriteStairs::Shape::InnerLeft).ID: return 9386; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedDioriteStairs::Half::Bottom, PolishedDioriteStairs::Shape::InnerRight).ID: return 9388; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedDioriteStairs::Half::Bottom, PolishedDioriteStairs::Shape::OuterLeft).ID: return 9390; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedDioriteStairs::Half::Bottom, PolishedDioriteStairs::Shape::OuterRight).ID: return 9392; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedDioriteStairs::Half::Top, PolishedDioriteStairs::Shape::Straight).ID: return 9394; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedDioriteStairs::Half::Top, PolishedDioriteStairs::Shape::InnerLeft).ID: return 9396; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedDioriteStairs::Half::Top, PolishedDioriteStairs::Shape::InnerRight).ID: return 9398; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedDioriteStairs::Half::Top, PolishedDioriteStairs::Shape::OuterLeft).ID: return 9400; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedDioriteStairs::Half::Top, PolishedDioriteStairs::Shape::OuterRight).ID: return 9402; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedDioriteStairs::Half::Bottom, PolishedDioriteStairs::Shape::Straight).ID: return 9404; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedDioriteStairs::Half::Bottom, PolishedDioriteStairs::Shape::InnerLeft).ID: return 9406; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedDioriteStairs::Half::Bottom, PolishedDioriteStairs::Shape::InnerRight).ID: return 9408; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedDioriteStairs::Half::Bottom, PolishedDioriteStairs::Shape::OuterLeft).ID: return 9410; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedDioriteStairs::Half::Bottom, PolishedDioriteStairs::Shape::OuterRight).ID: return 9412; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_XM, PolishedDioriteStairs::Half::Top, PolishedDioriteStairs::Shape::Straight).ID: return 9414; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_XM, PolishedDioriteStairs::Half::Top, PolishedDioriteStairs::Shape::InnerLeft).ID: return 9416; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_XM, PolishedDioriteStairs::Half::Top, PolishedDioriteStairs::Shape::InnerRight).ID: return 9418; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_XM, PolishedDioriteStairs::Half::Top, PolishedDioriteStairs::Shape::OuterLeft).ID: return 9420; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_XM, PolishedDioriteStairs::Half::Top, PolishedDioriteStairs::Shape::OuterRight).ID: return 9422; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_XM, PolishedDioriteStairs::Half::Bottom, PolishedDioriteStairs::Shape::Straight).ID: return 9424; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_XM, PolishedDioriteStairs::Half::Bottom, PolishedDioriteStairs::Shape::InnerLeft).ID: return 9426; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_XM, PolishedDioriteStairs::Half::Bottom, PolishedDioriteStairs::Shape::InnerRight).ID: return 9428; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_XM, PolishedDioriteStairs::Half::Bottom, PolishedDioriteStairs::Shape::OuterLeft).ID: return 9430; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_XM, PolishedDioriteStairs::Half::Bottom, PolishedDioriteStairs::Shape::OuterRight).ID: return 9432; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_XP, PolishedDioriteStairs::Half::Top, PolishedDioriteStairs::Shape::Straight).ID: return 9434; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_XP, PolishedDioriteStairs::Half::Top, PolishedDioriteStairs::Shape::InnerLeft).ID: return 9436; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_XP, PolishedDioriteStairs::Half::Top, PolishedDioriteStairs::Shape::InnerRight).ID: return 9438; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_XP, PolishedDioriteStairs::Half::Top, PolishedDioriteStairs::Shape::OuterLeft).ID: return 9440; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_XP, PolishedDioriteStairs::Half::Top, PolishedDioriteStairs::Shape::OuterRight).ID: return 9442; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_XP, PolishedDioriteStairs::Half::Bottom, PolishedDioriteStairs::Shape::Straight).ID: return 9444; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_XP, PolishedDioriteStairs::Half::Bottom, PolishedDioriteStairs::Shape::InnerLeft).ID: return 9446; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_XP, PolishedDioriteStairs::Half::Bottom, PolishedDioriteStairs::Shape::InnerRight).ID: return 9448; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_XP, PolishedDioriteStairs::Half::Bottom, PolishedDioriteStairs::Shape::OuterLeft).ID: return 9450; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_XP, PolishedDioriteStairs::Half::Bottom, PolishedDioriteStairs::Shape::OuterRight).ID: return 9452; case PolishedGranite::PolishedGranite().ID: return 3; case PolishedGraniteSlab::PolishedGraniteSlab(PolishedGraniteSlab::Type::Top).ID: return 10254; case PolishedGraniteSlab::PolishedGraniteSlab(PolishedGraniteSlab::Type::Bottom).ID: return 10256; case PolishedGraniteSlab::PolishedGraniteSlab(PolishedGraniteSlab::Type::Double).ID: return 10258; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedGraniteStairs::Half::Top, PolishedGraniteStairs::Shape::Straight).ID: return 9134; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedGraniteStairs::Half::Top, PolishedGraniteStairs::Shape::InnerLeft).ID: return 9136; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedGraniteStairs::Half::Top, PolishedGraniteStairs::Shape::InnerRight).ID: return 9138; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedGraniteStairs::Half::Top, PolishedGraniteStairs::Shape::OuterLeft).ID: return 9140; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedGraniteStairs::Half::Top, PolishedGraniteStairs::Shape::OuterRight).ID: return 9142; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedGraniteStairs::Half::Bottom, PolishedGraniteStairs::Shape::Straight).ID: return 9144; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedGraniteStairs::Half::Bottom, PolishedGraniteStairs::Shape::InnerLeft).ID: return 9146; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedGraniteStairs::Half::Bottom, PolishedGraniteStairs::Shape::InnerRight).ID: return 9148; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedGraniteStairs::Half::Bottom, PolishedGraniteStairs::Shape::OuterLeft).ID: return 9150; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedGraniteStairs::Half::Bottom, PolishedGraniteStairs::Shape::OuterRight).ID: return 9152; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedGraniteStairs::Half::Top, PolishedGraniteStairs::Shape::Straight).ID: return 9154; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedGraniteStairs::Half::Top, PolishedGraniteStairs::Shape::InnerLeft).ID: return 9156; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedGraniteStairs::Half::Top, PolishedGraniteStairs::Shape::InnerRight).ID: return 9158; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedGraniteStairs::Half::Top, PolishedGraniteStairs::Shape::OuterLeft).ID: return 9160; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedGraniteStairs::Half::Top, PolishedGraniteStairs::Shape::OuterRight).ID: return 9162; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedGraniteStairs::Half::Bottom, PolishedGraniteStairs::Shape::Straight).ID: return 9164; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedGraniteStairs::Half::Bottom, PolishedGraniteStairs::Shape::InnerLeft).ID: return 9166; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedGraniteStairs::Half::Bottom, PolishedGraniteStairs::Shape::InnerRight).ID: return 9168; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedGraniteStairs::Half::Bottom, PolishedGraniteStairs::Shape::OuterLeft).ID: return 9170; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedGraniteStairs::Half::Bottom, PolishedGraniteStairs::Shape::OuterRight).ID: return 9172; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_XM, PolishedGraniteStairs::Half::Top, PolishedGraniteStairs::Shape::Straight).ID: return 9174; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_XM, PolishedGraniteStairs::Half::Top, PolishedGraniteStairs::Shape::InnerLeft).ID: return 9176; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_XM, PolishedGraniteStairs::Half::Top, PolishedGraniteStairs::Shape::InnerRight).ID: return 9178; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_XM, PolishedGraniteStairs::Half::Top, PolishedGraniteStairs::Shape::OuterLeft).ID: return 9180; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_XM, PolishedGraniteStairs::Half::Top, PolishedGraniteStairs::Shape::OuterRight).ID: return 9182; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_XM, PolishedGraniteStairs::Half::Bottom, PolishedGraniteStairs::Shape::Straight).ID: return 9184; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_XM, PolishedGraniteStairs::Half::Bottom, PolishedGraniteStairs::Shape::InnerLeft).ID: return 9186; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_XM, PolishedGraniteStairs::Half::Bottom, PolishedGraniteStairs::Shape::InnerRight).ID: return 9188; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_XM, PolishedGraniteStairs::Half::Bottom, PolishedGraniteStairs::Shape::OuterLeft).ID: return 9190; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_XM, PolishedGraniteStairs::Half::Bottom, PolishedGraniteStairs::Shape::OuterRight).ID: return 9192; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_XP, PolishedGraniteStairs::Half::Top, PolishedGraniteStairs::Shape::Straight).ID: return 9194; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_XP, PolishedGraniteStairs::Half::Top, PolishedGraniteStairs::Shape::InnerLeft).ID: return 9196; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_XP, PolishedGraniteStairs::Half::Top, PolishedGraniteStairs::Shape::InnerRight).ID: return 9198; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_XP, PolishedGraniteStairs::Half::Top, PolishedGraniteStairs::Shape::OuterLeft).ID: return 9200; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_XP, PolishedGraniteStairs::Half::Top, PolishedGraniteStairs::Shape::OuterRight).ID: return 9202; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_XP, PolishedGraniteStairs::Half::Bottom, PolishedGraniteStairs::Shape::Straight).ID: return 9204; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_XP, PolishedGraniteStairs::Half::Bottom, PolishedGraniteStairs::Shape::InnerLeft).ID: return 9206; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_XP, PolishedGraniteStairs::Half::Bottom, PolishedGraniteStairs::Shape::InnerRight).ID: return 9208; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_XP, PolishedGraniteStairs::Half::Bottom, PolishedGraniteStairs::Shape::OuterLeft).ID: return 9210; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_XP, PolishedGraniteStairs::Half::Bottom, PolishedGraniteStairs::Shape::OuterRight).ID: return 9212; case Poppy::Poppy().ID: return 1412; case Potatoes::Potatoes(0).ID: return 5802; case Potatoes::Potatoes(1).ID: return 5803; case Potatoes::Potatoes(2).ID: return 5804; case Potatoes::Potatoes(3).ID: return 5805; case Potatoes::Potatoes(4).ID: return 5806; case Potatoes::Potatoes(5).ID: return 5807; case Potatoes::Potatoes(6).ID: return 5808; case Potatoes::Potatoes(7).ID: return 5809; case PottedAcaciaSapling::PottedAcaciaSapling().ID: return 5774; case PottedAllium::PottedAllium().ID: return 5780; case PottedAzureBluet::PottedAzureBluet().ID: return 5781; case PottedBamboo::PottedBamboo().ID: return 9128; case PottedBirchSapling::PottedBirchSapling().ID: return 5772; case PottedBlueOrchid::PottedBlueOrchid().ID: return 5779; case PottedBrownMushroom::PottedBrownMushroom().ID: return 5791; case PottedCactus::PottedCactus().ID: return 5793; case PottedCornflower::PottedCornflower().ID: return 5787; case PottedDandelion::PottedDandelion().ID: return 5777; case PottedDarkOakSapling::PottedDarkOakSapling().ID: return 5775; case PottedDeadBush::PottedDeadBush().ID: return 5792; case PottedFern::PottedFern().ID: return 5776; case PottedJungleSapling::PottedJungleSapling().ID: return 5773; case PottedLilyOfTheValley::PottedLilyOfTheValley().ID: return 5788; case PottedOakSapling::PottedOakSapling().ID: return 5770; case PottedOrangeTulip::PottedOrangeTulip().ID: return 5783; case PottedOxeyeDaisy::PottedOxeyeDaisy().ID: return 5786; case PottedPinkTulip::PottedPinkTulip().ID: return 5785; case PottedPoppy::PottedPoppy().ID: return 5778; case PottedRedMushroom::PottedRedMushroom().ID: return 5790; case PottedRedTulip::PottedRedTulip().ID: return 5782; case PottedSpruceSapling::PottedSpruceSapling().ID: return 5771; case PottedWhiteTulip::PottedWhiteTulip().ID: return 5784; case PottedWitherRose::PottedWitherRose().ID: return 5789; case PoweredRail::PoweredRail(true, PoweredRail::Shape::NorthSouth).ID: return 1304; case PoweredRail::PoweredRail(true, PoweredRail::Shape::EastWest).ID: return 1305; case PoweredRail::PoweredRail(true, PoweredRail::Shape::AscendingEast).ID: return 1306; case PoweredRail::PoweredRail(true, PoweredRail::Shape::AscendingWest).ID: return 1307; case PoweredRail::PoweredRail(true, PoweredRail::Shape::AscendingNorth).ID: return 1308; case PoweredRail::PoweredRail(true, PoweredRail::Shape::AscendingSouth).ID: return 1309; case PoweredRail::PoweredRail(false, PoweredRail::Shape::NorthSouth).ID: return 1310; case PoweredRail::PoweredRail(false, PoweredRail::Shape::EastWest).ID: return 1311; case PoweredRail::PoweredRail(false, PoweredRail::Shape::AscendingEast).ID: return 1312; case PoweredRail::PoweredRail(false, PoweredRail::Shape::AscendingWest).ID: return 1313; case PoweredRail::PoweredRail(false, PoweredRail::Shape::AscendingNorth).ID: return 1314; case PoweredRail::PoweredRail(false, PoweredRail::Shape::AscendingSouth).ID: return 1315; case Prismarine::Prismarine().ID: return 7065; case PrismarineBrickSlab::PrismarineBrickSlab(PrismarineBrickSlab::Type::Top).ID: return 7315; case PrismarineBrickSlab::PrismarineBrickSlab(PrismarineBrickSlab::Type::Bottom).ID: return 7317; case PrismarineBrickSlab::PrismarineBrickSlab(PrismarineBrickSlab::Type::Double).ID: return 7319; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::Straight).ID: return 7149; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::InnerLeft).ID: return 7151; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::InnerRight).ID: return 7153; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::OuterLeft).ID: return 7155; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::OuterRight).ID: return 7157; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::Straight).ID: return 7159; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::InnerLeft).ID: return 7161; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::InnerRight).ID: return 7163; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::OuterLeft).ID: return 7165; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::OuterRight).ID: return 7167; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::Straight).ID: return 7169; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::InnerLeft).ID: return 7171; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::InnerRight).ID: return 7173; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::OuterLeft).ID: return 7175; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::OuterRight).ID: return 7177; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::Straight).ID: return 7179; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::InnerLeft).ID: return 7181; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::InnerRight).ID: return 7183; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::OuterLeft).ID: return 7185; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::OuterRight).ID: return 7187; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XM, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::Straight).ID: return 7189; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XM, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::InnerLeft).ID: return 7191; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XM, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::InnerRight).ID: return 7193; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XM, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::OuterLeft).ID: return 7195; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XM, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::OuterRight).ID: return 7197; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XM, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::Straight).ID: return 7199; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XM, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::InnerLeft).ID: return 7201; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XM, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::InnerRight).ID: return 7203; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XM, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::OuterLeft).ID: return 7205; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XM, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::OuterRight).ID: return 7207; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XP, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::Straight).ID: return 7209; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XP, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::InnerLeft).ID: return 7211; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XP, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::InnerRight).ID: return 7213; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XP, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::OuterLeft).ID: return 7215; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XP, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::OuterRight).ID: return 7217; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XP, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::Straight).ID: return 7219; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XP, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::InnerLeft).ID: return 7221; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XP, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::InnerRight).ID: return 7223; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XP, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::OuterLeft).ID: return 7225; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XP, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::OuterRight).ID: return 7227; case PrismarineBricks::PrismarineBricks().ID: return 7066; case PrismarineSlab::PrismarineSlab(PrismarineSlab::Type::Top).ID: return 7309; case PrismarineSlab::PrismarineSlab(PrismarineSlab::Type::Bottom).ID: return 7311; case PrismarineSlab::PrismarineSlab(PrismarineSlab::Type::Double).ID: return 7313; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineStairs::Half::Top, PrismarineStairs::Shape::Straight).ID: return 7069; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineStairs::Half::Top, PrismarineStairs::Shape::InnerLeft).ID: return 7071; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineStairs::Half::Top, PrismarineStairs::Shape::InnerRight).ID: return 7073; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineStairs::Half::Top, PrismarineStairs::Shape::OuterLeft).ID: return 7075; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineStairs::Half::Top, PrismarineStairs::Shape::OuterRight).ID: return 7077; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::Straight).ID: return 7079; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::InnerLeft).ID: return 7081; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::InnerRight).ID: return 7083; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::OuterLeft).ID: return 7085; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::OuterRight).ID: return 7087; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineStairs::Half::Top, PrismarineStairs::Shape::Straight).ID: return 7089; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineStairs::Half::Top, PrismarineStairs::Shape::InnerLeft).ID: return 7091; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineStairs::Half::Top, PrismarineStairs::Shape::InnerRight).ID: return 7093; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineStairs::Half::Top, PrismarineStairs::Shape::OuterLeft).ID: return 7095; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineStairs::Half::Top, PrismarineStairs::Shape::OuterRight).ID: return 7097; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::Straight).ID: return 7099; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::InnerLeft).ID: return 7101; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::InnerRight).ID: return 7103; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::OuterLeft).ID: return 7105; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::OuterRight).ID: return 7107; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XM, PrismarineStairs::Half::Top, PrismarineStairs::Shape::Straight).ID: return 7109; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XM, PrismarineStairs::Half::Top, PrismarineStairs::Shape::InnerLeft).ID: return 7111; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XM, PrismarineStairs::Half::Top, PrismarineStairs::Shape::InnerRight).ID: return 7113; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XM, PrismarineStairs::Half::Top, PrismarineStairs::Shape::OuterLeft).ID: return 7115; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XM, PrismarineStairs::Half::Top, PrismarineStairs::Shape::OuterRight).ID: return 7117; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XM, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::Straight).ID: return 7119; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XM, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::InnerLeft).ID: return 7121; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XM, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::InnerRight).ID: return 7123; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XM, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::OuterLeft).ID: return 7125; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XM, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::OuterRight).ID: return 7127; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XP, PrismarineStairs::Half::Top, PrismarineStairs::Shape::Straight).ID: return 7129; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XP, PrismarineStairs::Half::Top, PrismarineStairs::Shape::InnerLeft).ID: return 7131; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XP, PrismarineStairs::Half::Top, PrismarineStairs::Shape::InnerRight).ID: return 7133; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XP, PrismarineStairs::Half::Top, PrismarineStairs::Shape::OuterLeft).ID: return 7135; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XP, PrismarineStairs::Half::Top, PrismarineStairs::Shape::OuterRight).ID: return 7137; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XP, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::Straight).ID: return 7139; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XP, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::InnerLeft).ID: return 7141; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XP, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::InnerRight).ID: return 7143; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XP, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::OuterLeft).ID: return 7145; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XP, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::OuterRight).ID: return 7147; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::Low, PrismarineWall::South::Low, true, PrismarineWall::West::Low).ID: return 10397; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::Low, PrismarineWall::South::Low, true, PrismarineWall::West::None).ID: return 10398; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::Low, PrismarineWall::South::Low, false, PrismarineWall::West::Low).ID: return 10401; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::Low, PrismarineWall::South::Low, false, PrismarineWall::West::None).ID: return 10402; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::Low, PrismarineWall::South::None, true, PrismarineWall::West::Low).ID: return 10405; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::Low, PrismarineWall::South::None, true, PrismarineWall::West::None).ID: return 10406; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::Low, PrismarineWall::South::None, false, PrismarineWall::West::Low).ID: return 10409; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::Low, PrismarineWall::South::None, false, PrismarineWall::West::None).ID: return 10410; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::None, PrismarineWall::South::Low, true, PrismarineWall::West::Low).ID: return 10413; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::None, PrismarineWall::South::Low, true, PrismarineWall::West::None).ID: return 10414; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::None, PrismarineWall::South::Low, false, PrismarineWall::West::Low).ID: return 10417; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::None, PrismarineWall::South::Low, false, PrismarineWall::West::None).ID: return 10418; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::None, PrismarineWall::South::None, true, PrismarineWall::West::Low).ID: return 10421; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::None, PrismarineWall::South::None, true, PrismarineWall::West::None).ID: return 10422; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::None, PrismarineWall::South::None, false, PrismarineWall::West::Low).ID: return 10425; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::None, PrismarineWall::South::None, false, PrismarineWall::West::None).ID: return 10426; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::Low, PrismarineWall::South::Low, true, PrismarineWall::West::Low).ID: return 10429; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::Low, PrismarineWall::South::Low, true, PrismarineWall::West::None).ID: return 10430; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::Low, PrismarineWall::South::Low, false, PrismarineWall::West::Low).ID: return 10433; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::Low, PrismarineWall::South::Low, false, PrismarineWall::West::None).ID: return 10434; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::Low, PrismarineWall::South::None, true, PrismarineWall::West::Low).ID: return 10437; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::Low, PrismarineWall::South::None, true, PrismarineWall::West::None).ID: return 10438; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::Low, PrismarineWall::South::None, false, PrismarineWall::West::Low).ID: return 10441; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::Low, PrismarineWall::South::None, false, PrismarineWall::West::None).ID: return 10442; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::None, PrismarineWall::South::Low, true, PrismarineWall::West::Low).ID: return 10445; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::None, PrismarineWall::South::Low, true, PrismarineWall::West::None).ID: return 10446; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::None, PrismarineWall::South::Low, false, PrismarineWall::West::Low).ID: return 10449; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::None, PrismarineWall::South::Low, false, PrismarineWall::West::None).ID: return 10450; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::None, PrismarineWall::South::None, true, PrismarineWall::West::Low).ID: return 10453; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::None, PrismarineWall::South::None, true, PrismarineWall::West::None).ID: return 10454; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::None, PrismarineWall::South::None, false, PrismarineWall::West::Low).ID: return 10457; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::None, PrismarineWall::South::None, false, PrismarineWall::West::None).ID: return 10458; case Pumpkin::Pumpkin().ID: return 3996; case PumpkinStem::PumpkinStem(0).ID: return 4756; case PumpkinStem::PumpkinStem(1).ID: return 4757; case PumpkinStem::PumpkinStem(2).ID: return 4758; case PumpkinStem::PumpkinStem(3).ID: return 4759; case PumpkinStem::PumpkinStem(4).ID: return 4760; case PumpkinStem::PumpkinStem(5).ID: return 4761; case PumpkinStem::PumpkinStem(6).ID: return 4762; case PumpkinStem::PumpkinStem(7).ID: return 4763; case PurpleBanner::PurpleBanner(0).ID: return 7521; case PurpleBanner::PurpleBanner(1).ID: return 7522; case PurpleBanner::PurpleBanner(2).ID: return 7523; case PurpleBanner::PurpleBanner(3).ID: return 7524; case PurpleBanner::PurpleBanner(4).ID: return 7525; case PurpleBanner::PurpleBanner(5).ID: return 7526; case PurpleBanner::PurpleBanner(6).ID: return 7527; case PurpleBanner::PurpleBanner(7).ID: return 7528; case PurpleBanner::PurpleBanner(8).ID: return 7529; case PurpleBanner::PurpleBanner(9).ID: return 7530; case PurpleBanner::PurpleBanner(10).ID: return 7531; case PurpleBanner::PurpleBanner(11).ID: return 7532; case PurpleBanner::PurpleBanner(12).ID: return 7533; case PurpleBanner::PurpleBanner(13).ID: return 7534; case PurpleBanner::PurpleBanner(14).ID: return 7535; case PurpleBanner::PurpleBanner(15).ID: return 7536; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_ZM, true, PurpleBed::Part::Head).ID: return 1208; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_ZM, true, PurpleBed::Part::Foot).ID: return 1209; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_ZM, false, PurpleBed::Part::Head).ID: return 1210; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_ZM, false, PurpleBed::Part::Foot).ID: return 1211; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_ZP, true, PurpleBed::Part::Head).ID: return 1212; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_ZP, true, PurpleBed::Part::Foot).ID: return 1213; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_ZP, false, PurpleBed::Part::Head).ID: return 1214; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_ZP, false, PurpleBed::Part::Foot).ID: return 1215; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_XM, true, PurpleBed::Part::Head).ID: return 1216; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_XM, true, PurpleBed::Part::Foot).ID: return 1217; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_XM, false, PurpleBed::Part::Head).ID: return 1218; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_XM, false, PurpleBed::Part::Foot).ID: return 1219; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_XP, true, PurpleBed::Part::Head).ID: return 1220; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_XP, true, PurpleBed::Part::Foot).ID: return 1221; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_XP, false, PurpleBed::Part::Head).ID: return 1222; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_XP, false, PurpleBed::Part::Foot).ID: return 1223; case PurpleCarpet::PurpleCarpet().ID: return 7340; case PurpleConcrete::PurpleConcrete().ID: return 8912; case PurpleConcretePowder::PurpleConcretePowder().ID: return 8928; case PurpleGlazedTerracotta::PurpleGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 8878; case PurpleGlazedTerracotta::PurpleGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 8879; case PurpleGlazedTerracotta::PurpleGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 8880; case PurpleGlazedTerracotta::PurpleGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 8881; case PurpleShulkerBox::PurpleShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 8802; case PurpleShulkerBox::PurpleShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 8803; case PurpleShulkerBox::PurpleShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 8804; case PurpleShulkerBox::PurpleShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 8805; case PurpleShulkerBox::PurpleShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 8806; case PurpleShulkerBox::PurpleShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 8807; case PurpleStainedGlass::PurpleStainedGlass().ID: return 4091; case PurpleStainedGlassPane::PurpleStainedGlassPane(true, true, true, true).ID: return 6649; case PurpleStainedGlassPane::PurpleStainedGlassPane(true, true, true, false).ID: return 6650; case PurpleStainedGlassPane::PurpleStainedGlassPane(true, true, false, true).ID: return 6653; case PurpleStainedGlassPane::PurpleStainedGlassPane(true, true, false, false).ID: return 6654; case PurpleStainedGlassPane::PurpleStainedGlassPane(true, false, true, true).ID: return 6657; case PurpleStainedGlassPane::PurpleStainedGlassPane(true, false, true, false).ID: return 6658; case PurpleStainedGlassPane::PurpleStainedGlassPane(true, false, false, true).ID: return 6661; case PurpleStainedGlassPane::PurpleStainedGlassPane(true, false, false, false).ID: return 6662; case PurpleStainedGlassPane::PurpleStainedGlassPane(false, true, true, true).ID: return 6665; case PurpleStainedGlassPane::PurpleStainedGlassPane(false, true, true, false).ID: return 6666; case PurpleStainedGlassPane::PurpleStainedGlassPane(false, true, false, true).ID: return 6669; case PurpleStainedGlassPane::PurpleStainedGlassPane(false, true, false, false).ID: return 6670; case PurpleStainedGlassPane::PurpleStainedGlassPane(false, false, true, true).ID: return 6673; case PurpleStainedGlassPane::PurpleStainedGlassPane(false, false, true, false).ID: return 6674; case PurpleStainedGlassPane::PurpleStainedGlassPane(false, false, false, true).ID: return 6677; case PurpleStainedGlassPane::PurpleStainedGlassPane(false, false, false, false).ID: return 6678; case PurpleTerracotta::PurpleTerracotta().ID: return 6321; case PurpleWallBanner::PurpleWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 7657; case PurpleWallBanner::PurpleWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 7658; case PurpleWallBanner::PurpleWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 7659; case PurpleWallBanner::PurpleWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 7660; case PurpleWool::PurpleWool().ID: return 1393; case PurpurBlock::PurpurBlock().ID: return 8598; case PurpurPillar::PurpurPillar(PurpurPillar::Axis::X).ID: return 8599; case PurpurPillar::PurpurPillar(PurpurPillar::Axis::Y).ID: return 8600; case PurpurPillar::PurpurPillar(PurpurPillar::Axis::Z).ID: return 8601; case PurpurSlab::PurpurSlab(PurpurSlab::Type::Top).ID: return 7873; case PurpurSlab::PurpurSlab(PurpurSlab::Type::Bottom).ID: return 7875; case PurpurSlab::PurpurSlab(PurpurSlab::Type::Double).ID: return 7877; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZM, PurpurStairs::Half::Top, PurpurStairs::Shape::Straight).ID: return 8603; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZM, PurpurStairs::Half::Top, PurpurStairs::Shape::InnerLeft).ID: return 8605; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZM, PurpurStairs::Half::Top, PurpurStairs::Shape::InnerRight).ID: return 8607; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZM, PurpurStairs::Half::Top, PurpurStairs::Shape::OuterLeft).ID: return 8609; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZM, PurpurStairs::Half::Top, PurpurStairs::Shape::OuterRight).ID: return 8611; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZM, PurpurStairs::Half::Bottom, PurpurStairs::Shape::Straight).ID: return 8613; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZM, PurpurStairs::Half::Bottom, PurpurStairs::Shape::InnerLeft).ID: return 8615; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZM, PurpurStairs::Half::Bottom, PurpurStairs::Shape::InnerRight).ID: return 8617; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZM, PurpurStairs::Half::Bottom, PurpurStairs::Shape::OuterLeft).ID: return 8619; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZM, PurpurStairs::Half::Bottom, PurpurStairs::Shape::OuterRight).ID: return 8621; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZP, PurpurStairs::Half::Top, PurpurStairs::Shape::Straight).ID: return 8623; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZP, PurpurStairs::Half::Top, PurpurStairs::Shape::InnerLeft).ID: return 8625; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZP, PurpurStairs::Half::Top, PurpurStairs::Shape::InnerRight).ID: return 8627; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZP, PurpurStairs::Half::Top, PurpurStairs::Shape::OuterLeft).ID: return 8629; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZP, PurpurStairs::Half::Top, PurpurStairs::Shape::OuterRight).ID: return 8631; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZP, PurpurStairs::Half::Bottom, PurpurStairs::Shape::Straight).ID: return 8633; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZP, PurpurStairs::Half::Bottom, PurpurStairs::Shape::InnerLeft).ID: return 8635; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZP, PurpurStairs::Half::Bottom, PurpurStairs::Shape::InnerRight).ID: return 8637; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZP, PurpurStairs::Half::Bottom, PurpurStairs::Shape::OuterLeft).ID: return 8639; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZP, PurpurStairs::Half::Bottom, PurpurStairs::Shape::OuterRight).ID: return 8641; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XM, PurpurStairs::Half::Top, PurpurStairs::Shape::Straight).ID: return 8643; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XM, PurpurStairs::Half::Top, PurpurStairs::Shape::InnerLeft).ID: return 8645; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XM, PurpurStairs::Half::Top, PurpurStairs::Shape::InnerRight).ID: return 8647; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XM, PurpurStairs::Half::Top, PurpurStairs::Shape::OuterLeft).ID: return 8649; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XM, PurpurStairs::Half::Top, PurpurStairs::Shape::OuterRight).ID: return 8651; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XM, PurpurStairs::Half::Bottom, PurpurStairs::Shape::Straight).ID: return 8653; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XM, PurpurStairs::Half::Bottom, PurpurStairs::Shape::InnerLeft).ID: return 8655; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XM, PurpurStairs::Half::Bottom, PurpurStairs::Shape::InnerRight).ID: return 8657; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XM, PurpurStairs::Half::Bottom, PurpurStairs::Shape::OuterLeft).ID: return 8659; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XM, PurpurStairs::Half::Bottom, PurpurStairs::Shape::OuterRight).ID: return 8661; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XP, PurpurStairs::Half::Top, PurpurStairs::Shape::Straight).ID: return 8663; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XP, PurpurStairs::Half::Top, PurpurStairs::Shape::InnerLeft).ID: return 8665; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XP, PurpurStairs::Half::Top, PurpurStairs::Shape::InnerRight).ID: return 8667; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XP, PurpurStairs::Half::Top, PurpurStairs::Shape::OuterLeft).ID: return 8669; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XP, PurpurStairs::Half::Top, PurpurStairs::Shape::OuterRight).ID: return 8671; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XP, PurpurStairs::Half::Bottom, PurpurStairs::Shape::Straight).ID: return 8673; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XP, PurpurStairs::Half::Bottom, PurpurStairs::Shape::InnerLeft).ID: return 8675; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XP, PurpurStairs::Half::Bottom, PurpurStairs::Shape::InnerRight).ID: return 8677; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XP, PurpurStairs::Half::Bottom, PurpurStairs::Shape::OuterLeft).ID: return 8679; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XP, PurpurStairs::Half::Bottom, PurpurStairs::Shape::OuterRight).ID: return 8681; case QuartzBlock::QuartzBlock().ID: return 6202; case QuartzPillar::QuartzPillar(QuartzPillar::Axis::X).ID: return 6204; case QuartzPillar::QuartzPillar(QuartzPillar::Axis::Y).ID: return 6205; case QuartzPillar::QuartzPillar(QuartzPillar::Axis::Z).ID: return 6206; case QuartzSlab::QuartzSlab(QuartzSlab::Type::Top).ID: return 7855; case QuartzSlab::QuartzSlab(QuartzSlab::Type::Bottom).ID: return 7857; case QuartzSlab::QuartzSlab(QuartzSlab::Type::Double).ID: return 7859; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZM, QuartzStairs::Half::Top, QuartzStairs::Shape::Straight).ID: return 6208; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZM, QuartzStairs::Half::Top, QuartzStairs::Shape::InnerLeft).ID: return 6210; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZM, QuartzStairs::Half::Top, QuartzStairs::Shape::InnerRight).ID: return 6212; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZM, QuartzStairs::Half::Top, QuartzStairs::Shape::OuterLeft).ID: return 6214; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZM, QuartzStairs::Half::Top, QuartzStairs::Shape::OuterRight).ID: return 6216; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZM, QuartzStairs::Half::Bottom, QuartzStairs::Shape::Straight).ID: return 6218; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZM, QuartzStairs::Half::Bottom, QuartzStairs::Shape::InnerLeft).ID: return 6220; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZM, QuartzStairs::Half::Bottom, QuartzStairs::Shape::InnerRight).ID: return 6222; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZM, QuartzStairs::Half::Bottom, QuartzStairs::Shape::OuterLeft).ID: return 6224; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZM, QuartzStairs::Half::Bottom, QuartzStairs::Shape::OuterRight).ID: return 6226; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZP, QuartzStairs::Half::Top, QuartzStairs::Shape::Straight).ID: return 6228; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZP, QuartzStairs::Half::Top, QuartzStairs::Shape::InnerLeft).ID: return 6230; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZP, QuartzStairs::Half::Top, QuartzStairs::Shape::InnerRight).ID: return 6232; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZP, QuartzStairs::Half::Top, QuartzStairs::Shape::OuterLeft).ID: return 6234; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZP, QuartzStairs::Half::Top, QuartzStairs::Shape::OuterRight).ID: return 6236; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZP, QuartzStairs::Half::Bottom, QuartzStairs::Shape::Straight).ID: return 6238; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZP, QuartzStairs::Half::Bottom, QuartzStairs::Shape::InnerLeft).ID: return 6240; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZP, QuartzStairs::Half::Bottom, QuartzStairs::Shape::InnerRight).ID: return 6242; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZP, QuartzStairs::Half::Bottom, QuartzStairs::Shape::OuterLeft).ID: return 6244; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZP, QuartzStairs::Half::Bottom, QuartzStairs::Shape::OuterRight).ID: return 6246; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XM, QuartzStairs::Half::Top, QuartzStairs::Shape::Straight).ID: return 6248; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XM, QuartzStairs::Half::Top, QuartzStairs::Shape::InnerLeft).ID: return 6250; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XM, QuartzStairs::Half::Top, QuartzStairs::Shape::InnerRight).ID: return 6252; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XM, QuartzStairs::Half::Top, QuartzStairs::Shape::OuterLeft).ID: return 6254; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XM, QuartzStairs::Half::Top, QuartzStairs::Shape::OuterRight).ID: return 6256; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XM, QuartzStairs::Half::Bottom, QuartzStairs::Shape::Straight).ID: return 6258; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XM, QuartzStairs::Half::Bottom, QuartzStairs::Shape::InnerLeft).ID: return 6260; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XM, QuartzStairs::Half::Bottom, QuartzStairs::Shape::InnerRight).ID: return 6262; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XM, QuartzStairs::Half::Bottom, QuartzStairs::Shape::OuterLeft).ID: return 6264; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XM, QuartzStairs::Half::Bottom, QuartzStairs::Shape::OuterRight).ID: return 6266; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XP, QuartzStairs::Half::Top, QuartzStairs::Shape::Straight).ID: return 6268; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XP, QuartzStairs::Half::Top, QuartzStairs::Shape::InnerLeft).ID: return 6270; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XP, QuartzStairs::Half::Top, QuartzStairs::Shape::InnerRight).ID: return 6272; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XP, QuartzStairs::Half::Top, QuartzStairs::Shape::OuterLeft).ID: return 6274; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XP, QuartzStairs::Half::Top, QuartzStairs::Shape::OuterRight).ID: return 6276; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XP, QuartzStairs::Half::Bottom, QuartzStairs::Shape::Straight).ID: return 6278; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XP, QuartzStairs::Half::Bottom, QuartzStairs::Shape::InnerLeft).ID: return 6280; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XP, QuartzStairs::Half::Bottom, QuartzStairs::Shape::InnerRight).ID: return 6282; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XP, QuartzStairs::Half::Bottom, QuartzStairs::Shape::OuterLeft).ID: return 6284; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XP, QuartzStairs::Half::Bottom, QuartzStairs::Shape::OuterRight).ID: return 6286; case Rail::Rail(Rail::Shape::NorthSouth).ID: return 3643; case Rail::Rail(Rail::Shape::EastWest).ID: return 3644; case Rail::Rail(Rail::Shape::AscendingEast).ID: return 3645; case Rail::Rail(Rail::Shape::AscendingWest).ID: return 3646; case Rail::Rail(Rail::Shape::AscendingNorth).ID: return 3647; case Rail::Rail(Rail::Shape::AscendingSouth).ID: return 3648; case Rail::Rail(Rail::Shape::SouthEast).ID: return 3649; case Rail::Rail(Rail::Shape::SouthWest).ID: return 3650; case Rail::Rail(Rail::Shape::NorthWest).ID: return 3651; case Rail::Rail(Rail::Shape::NorthEast).ID: return 3652; case RedBanner::RedBanner(0).ID: return 7585; case RedBanner::RedBanner(1).ID: return 7586; case RedBanner::RedBanner(2).ID: return 7587; case RedBanner::RedBanner(3).ID: return 7588; case RedBanner::RedBanner(4).ID: return 7589; case RedBanner::RedBanner(5).ID: return 7590; case RedBanner::RedBanner(6).ID: return 7591; case RedBanner::RedBanner(7).ID: return 7592; case RedBanner::RedBanner(8).ID: return 7593; case RedBanner::RedBanner(9).ID: return 7594; case RedBanner::RedBanner(10).ID: return 7595; case RedBanner::RedBanner(11).ID: return 7596; case RedBanner::RedBanner(12).ID: return 7597; case RedBanner::RedBanner(13).ID: return 7598; case RedBanner::RedBanner(14).ID: return 7599; case RedBanner::RedBanner(15).ID: return 7600; case RedBed::RedBed(eBlockFace::BLOCK_FACE_ZM, true, RedBed::Part::Head).ID: return 1272; case RedBed::RedBed(eBlockFace::BLOCK_FACE_ZM, true, RedBed::Part::Foot).ID: return 1273; case RedBed::RedBed(eBlockFace::BLOCK_FACE_ZM, false, RedBed::Part::Head).ID: return 1274; case RedBed::RedBed(eBlockFace::BLOCK_FACE_ZM, false, RedBed::Part::Foot).ID: return 1275; case RedBed::RedBed(eBlockFace::BLOCK_FACE_ZP, true, RedBed::Part::Head).ID: return 1276; case RedBed::RedBed(eBlockFace::BLOCK_FACE_ZP, true, RedBed::Part::Foot).ID: return 1277; case RedBed::RedBed(eBlockFace::BLOCK_FACE_ZP, false, RedBed::Part::Head).ID: return 1278; case RedBed::RedBed(eBlockFace::BLOCK_FACE_ZP, false, RedBed::Part::Foot).ID: return 1279; case RedBed::RedBed(eBlockFace::BLOCK_FACE_XM, true, RedBed::Part::Head).ID: return 1280; case RedBed::RedBed(eBlockFace::BLOCK_FACE_XM, true, RedBed::Part::Foot).ID: return 1281; case RedBed::RedBed(eBlockFace::BLOCK_FACE_XM, false, RedBed::Part::Head).ID: return 1282; case RedBed::RedBed(eBlockFace::BLOCK_FACE_XM, false, RedBed::Part::Foot).ID: return 1283; case RedBed::RedBed(eBlockFace::BLOCK_FACE_XP, true, RedBed::Part::Head).ID: return 1284; case RedBed::RedBed(eBlockFace::BLOCK_FACE_XP, true, RedBed::Part::Foot).ID: return 1285; case RedBed::RedBed(eBlockFace::BLOCK_FACE_XP, false, RedBed::Part::Head).ID: return 1286; case RedBed::RedBed(eBlockFace::BLOCK_FACE_XP, false, RedBed::Part::Foot).ID: return 1287; case RedCarpet::RedCarpet().ID: return 7344; case RedConcrete::RedConcrete().ID: return 8916; case RedConcretePowder::RedConcretePowder().ID: return 8932; case RedGlazedTerracotta::RedGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 8894; case RedGlazedTerracotta::RedGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 8895; case RedGlazedTerracotta::RedGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 8896; case RedGlazedTerracotta::RedGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 8897; case RedMushroom::RedMushroom().ID: return 1425; case RedMushroomBlock::RedMushroomBlock(true, true, true, true, true, true).ID: return 4555; case RedMushroomBlock::RedMushroomBlock(true, true, true, true, true, false).ID: return 4556; case RedMushroomBlock::RedMushroomBlock(true, true, true, true, false, true).ID: return 4557; case RedMushroomBlock::RedMushroomBlock(true, true, true, true, false, false).ID: return 4558; case RedMushroomBlock::RedMushroomBlock(true, true, true, false, true, true).ID: return 4559; case RedMushroomBlock::RedMushroomBlock(true, true, true, false, true, false).ID: return 4560; case RedMushroomBlock::RedMushroomBlock(true, true, true, false, false, true).ID: return 4561; case RedMushroomBlock::RedMushroomBlock(true, true, true, false, false, false).ID: return 4562; case RedMushroomBlock::RedMushroomBlock(true, true, false, true, true, true).ID: return 4563; case RedMushroomBlock::RedMushroomBlock(true, true, false, true, true, false).ID: return 4564; case RedMushroomBlock::RedMushroomBlock(true, true, false, true, false, true).ID: return 4565; case RedMushroomBlock::RedMushroomBlock(true, true, false, true, false, false).ID: return 4566; case RedMushroomBlock::RedMushroomBlock(true, true, false, false, true, true).ID: return 4567; case RedMushroomBlock::RedMushroomBlock(true, true, false, false, true, false).ID: return 4568; case RedMushroomBlock::RedMushroomBlock(true, true, false, false, false, true).ID: return 4569; case RedMushroomBlock::RedMushroomBlock(true, true, false, false, false, false).ID: return 4570; case RedMushroomBlock::RedMushroomBlock(true, false, true, true, true, true).ID: return 4571; case RedMushroomBlock::RedMushroomBlock(true, false, true, true, true, false).ID: return 4572; case RedMushroomBlock::RedMushroomBlock(true, false, true, true, false, true).ID: return 4573; case RedMushroomBlock::RedMushroomBlock(true, false, true, true, false, false).ID: return 4574; case RedMushroomBlock::RedMushroomBlock(true, false, true, false, true, true).ID: return 4575; case RedMushroomBlock::RedMushroomBlock(true, false, true, false, true, false).ID: return 4576; case RedMushroomBlock::RedMushroomBlock(true, false, true, false, false, true).ID: return 4577; case RedMushroomBlock::RedMushroomBlock(true, false, true, false, false, false).ID: return 4578; case RedMushroomBlock::RedMushroomBlock(true, false, false, true, true, true).ID: return 4579; case RedMushroomBlock::RedMushroomBlock(true, false, false, true, true, false).ID: return 4580; case RedMushroomBlock::RedMushroomBlock(true, false, false, true, false, true).ID: return 4581; case RedMushroomBlock::RedMushroomBlock(true, false, false, true, false, false).ID: return 4582; case RedMushroomBlock::RedMushroomBlock(true, false, false, false, true, true).ID: return 4583; case RedMushroomBlock::RedMushroomBlock(true, false, false, false, true, false).ID: return 4584; case RedMushroomBlock::RedMushroomBlock(true, false, false, false, false, true).ID: return 4585; case RedMushroomBlock::RedMushroomBlock(true, false, false, false, false, false).ID: return 4586; case RedMushroomBlock::RedMushroomBlock(false, true, true, true, true, true).ID: return 4587; case RedMushroomBlock::RedMushroomBlock(false, true, true, true, true, false).ID: return 4588; case RedMushroomBlock::RedMushroomBlock(false, true, true, true, false, true).ID: return 4589; case RedMushroomBlock::RedMushroomBlock(false, true, true, true, false, false).ID: return 4590; case RedMushroomBlock::RedMushroomBlock(false, true, true, false, true, true).ID: return 4591; case RedMushroomBlock::RedMushroomBlock(false, true, true, false, true, false).ID: return 4592; case RedMushroomBlock::RedMushroomBlock(false, true, true, false, false, true).ID: return 4593; case RedMushroomBlock::RedMushroomBlock(false, true, true, false, false, false).ID: return 4594; case RedMushroomBlock::RedMushroomBlock(false, true, false, true, true, true).ID: return 4595; case RedMushroomBlock::RedMushroomBlock(false, true, false, true, true, false).ID: return 4596; case RedMushroomBlock::RedMushroomBlock(false, true, false, true, false, true).ID: return 4597; case RedMushroomBlock::RedMushroomBlock(false, true, false, true, false, false).ID: return 4598; case RedMushroomBlock::RedMushroomBlock(false, true, false, false, true, true).ID: return 4599; case RedMushroomBlock::RedMushroomBlock(false, true, false, false, true, false).ID: return 4600; case RedMushroomBlock::RedMushroomBlock(false, true, false, false, false, true).ID: return 4601; case RedMushroomBlock::RedMushroomBlock(false, true, false, false, false, false).ID: return 4602; case RedMushroomBlock::RedMushroomBlock(false, false, true, true, true, true).ID: return 4603; case RedMushroomBlock::RedMushroomBlock(false, false, true, true, true, false).ID: return 4604; case RedMushroomBlock::RedMushroomBlock(false, false, true, true, false, true).ID: return 4605; case RedMushroomBlock::RedMushroomBlock(false, false, true, true, false, false).ID: return 4606; case RedMushroomBlock::RedMushroomBlock(false, false, true, false, true, true).ID: return 4607; case RedMushroomBlock::RedMushroomBlock(false, false, true, false, true, false).ID: return 4608; case RedMushroomBlock::RedMushroomBlock(false, false, true, false, false, true).ID: return 4609; case RedMushroomBlock::RedMushroomBlock(false, false, true, false, false, false).ID: return 4610; case RedMushroomBlock::RedMushroomBlock(false, false, false, true, true, true).ID: return 4611; case RedMushroomBlock::RedMushroomBlock(false, false, false, true, true, false).ID: return 4612; case RedMushroomBlock::RedMushroomBlock(false, false, false, true, false, true).ID: return 4613; case RedMushroomBlock::RedMushroomBlock(false, false, false, true, false, false).ID: return 4614; case RedMushroomBlock::RedMushroomBlock(false, false, false, false, true, true).ID: return 4615; case RedMushroomBlock::RedMushroomBlock(false, false, false, false, true, false).ID: return 4616; case RedMushroomBlock::RedMushroomBlock(false, false, false, false, false, true).ID: return 4617; case RedMushroomBlock::RedMushroomBlock(false, false, false, false, false, false).ID: return 4618; case RedNetherBrickSlab::RedNetherBrickSlab(RedNetherBrickSlab::Type::Top).ID: return 10314; case RedNetherBrickSlab::RedNetherBrickSlab(RedNetherBrickSlab::Type::Bottom).ID: return 10316; case RedNetherBrickSlab::RedNetherBrickSlab(RedNetherBrickSlab::Type::Double).ID: return 10318; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, RedNetherBrickStairs::Half::Top, RedNetherBrickStairs::Shape::Straight).ID: return 10014; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, RedNetherBrickStairs::Half::Top, RedNetherBrickStairs::Shape::InnerLeft).ID: return 10016; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, RedNetherBrickStairs::Half::Top, RedNetherBrickStairs::Shape::InnerRight).ID: return 10018; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, RedNetherBrickStairs::Half::Top, RedNetherBrickStairs::Shape::OuterLeft).ID: return 10020; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, RedNetherBrickStairs::Half::Top, RedNetherBrickStairs::Shape::OuterRight).ID: return 10022; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, RedNetherBrickStairs::Half::Bottom, RedNetherBrickStairs::Shape::Straight).ID: return 10024; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, RedNetherBrickStairs::Half::Bottom, RedNetherBrickStairs::Shape::InnerLeft).ID: return 10026; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, RedNetherBrickStairs::Half::Bottom, RedNetherBrickStairs::Shape::InnerRight).ID: return 10028; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, RedNetherBrickStairs::Half::Bottom, RedNetherBrickStairs::Shape::OuterLeft).ID: return 10030; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, RedNetherBrickStairs::Half::Bottom, RedNetherBrickStairs::Shape::OuterRight).ID: return 10032; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, RedNetherBrickStairs::Half::Top, RedNetherBrickStairs::Shape::Straight).ID: return 10034; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, RedNetherBrickStairs::Half::Top, RedNetherBrickStairs::Shape::InnerLeft).ID: return 10036; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, RedNetherBrickStairs::Half::Top, RedNetherBrickStairs::Shape::InnerRight).ID: return 10038; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, RedNetherBrickStairs::Half::Top, RedNetherBrickStairs::Shape::OuterLeft).ID: return 10040; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, RedNetherBrickStairs::Half::Top, RedNetherBrickStairs::Shape::OuterRight).ID: return 10042; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, RedNetherBrickStairs::Half::Bottom, RedNetherBrickStairs::Shape::Straight).ID: return 10044; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, RedNetherBrickStairs::Half::Bottom, RedNetherBrickStairs::Shape::InnerLeft).ID: return 10046; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, RedNetherBrickStairs::Half::Bottom, RedNetherBrickStairs::Shape::InnerRight).ID: return 10048; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, RedNetherBrickStairs::Half::Bottom, RedNetherBrickStairs::Shape::OuterLeft).ID: return 10050; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, RedNetherBrickStairs::Half::Bottom, RedNetherBrickStairs::Shape::OuterRight).ID: return 10052; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_XM, RedNetherBrickStairs::Half::Top, RedNetherBrickStairs::Shape::Straight).ID: return 10054; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_XM, RedNetherBrickStairs::Half::Top, RedNetherBrickStairs::Shape::InnerLeft).ID: return 10056; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_XM, RedNetherBrickStairs::Half::Top, RedNetherBrickStairs::Shape::InnerRight).ID: return 10058; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_XM, RedNetherBrickStairs::Half::Top, RedNetherBrickStairs::Shape::OuterLeft).ID: return 10060; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_XM, RedNetherBrickStairs::Half::Top, RedNetherBrickStairs::Shape::OuterRight).ID: return 10062; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_XM, RedNetherBrickStairs::Half::Bottom, RedNetherBrickStairs::Shape::Straight).ID: return 10064; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_XM, RedNetherBrickStairs::Half::Bottom, RedNetherBrickStairs::Shape::InnerLeft).ID: return 10066; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_XM, RedNetherBrickStairs::Half::Bottom, RedNetherBrickStairs::Shape::InnerRight).ID: return 10068; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_XM, RedNetherBrickStairs::Half::Bottom, RedNetherBrickStairs::Shape::OuterLeft).ID: return 10070; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_XM, RedNetherBrickStairs::Half::Bottom, RedNetherBrickStairs::Shape::OuterRight).ID: return 10072; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_XP, RedNetherBrickStairs::Half::Top, RedNetherBrickStairs::Shape::Straight).ID: return 10074; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_XP, RedNetherBrickStairs::Half::Top, RedNetherBrickStairs::Shape::InnerLeft).ID: return 10076; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_XP, RedNetherBrickStairs::Half::Top, RedNetherBrickStairs::Shape::InnerRight).ID: return 10078; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_XP, RedNetherBrickStairs::Half::Top, RedNetherBrickStairs::Shape::OuterLeft).ID: return 10080; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_XP, RedNetherBrickStairs::Half::Top, RedNetherBrickStairs::Shape::OuterRight).ID: return 10082; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_XP, RedNetherBrickStairs::Half::Bottom, RedNetherBrickStairs::Shape::Straight).ID: return 10084; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_XP, RedNetherBrickStairs::Half::Bottom, RedNetherBrickStairs::Shape::InnerLeft).ID: return 10086; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_XP, RedNetherBrickStairs::Half::Bottom, RedNetherBrickStairs::Shape::InnerRight).ID: return 10088; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_XP, RedNetherBrickStairs::Half::Bottom, RedNetherBrickStairs::Shape::OuterLeft).ID: return 10090; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_XP, RedNetherBrickStairs::Half::Bottom, RedNetherBrickStairs::Shape::OuterRight).ID: return 10092; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::Low, true, RedNetherBrickWall::West::Low).ID: return 10845; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::Low, true, RedNetherBrickWall::West::None).ID: return 10846; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::Low, false, RedNetherBrickWall::West::Low).ID: return 10849; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::Low, false, RedNetherBrickWall::West::None).ID: return 10850; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::None, true, RedNetherBrickWall::West::Low).ID: return 10853; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::None, true, RedNetherBrickWall::West::None).ID: return 10854; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::None, false, RedNetherBrickWall::West::Low).ID: return 10857; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::None, false, RedNetherBrickWall::West::None).ID: return 10858; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::None, RedNetherBrickWall::South::Low, true, RedNetherBrickWall::West::Low).ID: return 10861; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::None, RedNetherBrickWall::South::Low, true, RedNetherBrickWall::West::None).ID: return 10862; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::None, RedNetherBrickWall::South::Low, false, RedNetherBrickWall::West::Low).ID: return 10865; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::None, RedNetherBrickWall::South::Low, false, RedNetherBrickWall::West::None).ID: return 10866; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::None, RedNetherBrickWall::South::None, true, RedNetherBrickWall::West::Low).ID: return 10869; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::None, RedNetherBrickWall::South::None, true, RedNetherBrickWall::West::None).ID: return 10870; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::None, RedNetherBrickWall::South::None, false, RedNetherBrickWall::West::Low).ID: return 10873; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::None, RedNetherBrickWall::South::None, false, RedNetherBrickWall::West::None).ID: return 10874; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::Low, true, RedNetherBrickWall::West::Low).ID: return 10877; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::Low, true, RedNetherBrickWall::West::None).ID: return 10878; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::Low, false, RedNetherBrickWall::West::Low).ID: return 10881; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::Low, false, RedNetherBrickWall::West::None).ID: return 10882; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::None, true, RedNetherBrickWall::West::Low).ID: return 10885; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::None, true, RedNetherBrickWall::West::None).ID: return 10886; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::None, false, RedNetherBrickWall::West::Low).ID: return 10889; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::None, false, RedNetherBrickWall::West::None).ID: return 10890; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::None, RedNetherBrickWall::South::Low, true, RedNetherBrickWall::West::Low).ID: return 10893; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::None, RedNetherBrickWall::South::Low, true, RedNetherBrickWall::West::None).ID: return 10894; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::None, RedNetherBrickWall::South::Low, false, RedNetherBrickWall::West::Low).ID: return 10897; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::None, RedNetherBrickWall::South::Low, false, RedNetherBrickWall::West::None).ID: return 10898; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::None, RedNetherBrickWall::South::None, true, RedNetherBrickWall::West::Low).ID: return 10901; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::None, RedNetherBrickWall::South::None, true, RedNetherBrickWall::West::None).ID: return 10902; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::None, RedNetherBrickWall::South::None, false, RedNetherBrickWall::West::Low).ID: return 10905; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::None, RedNetherBrickWall::South::None, false, RedNetherBrickWall::West::None).ID: return 10906; case RedNetherBricks::RedNetherBricks().ID: return 8719; case RedSand::RedSand().ID: return 67; case RedSandstone::RedSandstone().ID: return 7681; case RedSandstoneSlab::RedSandstoneSlab(RedSandstoneSlab::Type::Top).ID: return 7861; case RedSandstoneSlab::RedSandstoneSlab(RedSandstoneSlab::Type::Bottom).ID: return 7863; case RedSandstoneSlab::RedSandstoneSlab(RedSandstoneSlab::Type::Double).ID: return 7865; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::Straight).ID: return 7685; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::InnerLeft).ID: return 7687; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::InnerRight).ID: return 7689; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::OuterLeft).ID: return 7691; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::OuterRight).ID: return 7693; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::Straight).ID: return 7695; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::InnerLeft).ID: return 7697; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::InnerRight).ID: return 7699; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::OuterLeft).ID: return 7701; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::OuterRight).ID: return 7703; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::Straight).ID: return 7705; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::InnerLeft).ID: return 7707; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::InnerRight).ID: return 7709; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::OuterLeft).ID: return 7711; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::OuterRight).ID: return 7713; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::Straight).ID: return 7715; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::InnerLeft).ID: return 7717; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::InnerRight).ID: return 7719; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::OuterLeft).ID: return 7721; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::OuterRight).ID: return 7723; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::Straight).ID: return 7725; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::InnerLeft).ID: return 7727; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::InnerRight).ID: return 7729; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::OuterLeft).ID: return 7731; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::OuterRight).ID: return 7733; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::Straight).ID: return 7735; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::InnerLeft).ID: return 7737; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::InnerRight).ID: return 7739; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::OuterLeft).ID: return 7741; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::OuterRight).ID: return 7743; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::Straight).ID: return 7745; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::InnerLeft).ID: return 7747; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::InnerRight).ID: return 7749; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::OuterLeft).ID: return 7751; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::OuterRight).ID: return 7753; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::Straight).ID: return 7755; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::InnerLeft).ID: return 7757; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::InnerRight).ID: return 7759; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::OuterLeft).ID: return 7761; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::OuterRight).ID: return 7763; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::Low, RedSandstoneWall::South::Low, true, RedSandstoneWall::West::Low).ID: return 10461; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::Low, RedSandstoneWall::South::Low, true, RedSandstoneWall::West::None).ID: return 10462; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::Low, RedSandstoneWall::South::Low, false, RedSandstoneWall::West::Low).ID: return 10465; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::Low, RedSandstoneWall::South::Low, false, RedSandstoneWall::West::None).ID: return 10466; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::Low, RedSandstoneWall::South::None, true, RedSandstoneWall::West::Low).ID: return 10469; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::Low, RedSandstoneWall::South::None, true, RedSandstoneWall::West::None).ID: return 10470; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::Low, RedSandstoneWall::South::None, false, RedSandstoneWall::West::Low).ID: return 10473; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::Low, RedSandstoneWall::South::None, false, RedSandstoneWall::West::None).ID: return 10474; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::None, RedSandstoneWall::South::Low, true, RedSandstoneWall::West::Low).ID: return 10477; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::None, RedSandstoneWall::South::Low, true, RedSandstoneWall::West::None).ID: return 10478; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::None, RedSandstoneWall::South::Low, false, RedSandstoneWall::West::Low).ID: return 10481; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::None, RedSandstoneWall::South::Low, false, RedSandstoneWall::West::None).ID: return 10482; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::None, RedSandstoneWall::South::None, true, RedSandstoneWall::West::Low).ID: return 10485; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::None, RedSandstoneWall::South::None, true, RedSandstoneWall::West::None).ID: return 10486; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::None, RedSandstoneWall::South::None, false, RedSandstoneWall::West::Low).ID: return 10489; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::None, RedSandstoneWall::South::None, false, RedSandstoneWall::West::None).ID: return 10490; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::Low, RedSandstoneWall::South::Low, true, RedSandstoneWall::West::Low).ID: return 10493; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::Low, RedSandstoneWall::South::Low, true, RedSandstoneWall::West::None).ID: return 10494; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::Low, RedSandstoneWall::South::Low, false, RedSandstoneWall::West::Low).ID: return 10497; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::Low, RedSandstoneWall::South::Low, false, RedSandstoneWall::West::None).ID: return 10498; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::Low, RedSandstoneWall::South::None, true, RedSandstoneWall::West::Low).ID: return 10501; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::Low, RedSandstoneWall::South::None, true, RedSandstoneWall::West::None).ID: return 10502; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::Low, RedSandstoneWall::South::None, false, RedSandstoneWall::West::Low).ID: return 10505; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::Low, RedSandstoneWall::South::None, false, RedSandstoneWall::West::None).ID: return 10506; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::None, RedSandstoneWall::South::Low, true, RedSandstoneWall::West::Low).ID: return 10509; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::None, RedSandstoneWall::South::Low, true, RedSandstoneWall::West::None).ID: return 10510; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::None, RedSandstoneWall::South::Low, false, RedSandstoneWall::West::Low).ID: return 10513; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::None, RedSandstoneWall::South::Low, false, RedSandstoneWall::West::None).ID: return 10514; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::None, RedSandstoneWall::South::None, true, RedSandstoneWall::West::Low).ID: return 10517; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::None, RedSandstoneWall::South::None, true, RedSandstoneWall::West::None).ID: return 10518; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::None, RedSandstoneWall::South::None, false, RedSandstoneWall::West::Low).ID: return 10521; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::None, RedSandstoneWall::South::None, false, RedSandstoneWall::West::None).ID: return 10522; case RedShulkerBox::RedShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 8826; case RedShulkerBox::RedShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 8827; case RedShulkerBox::RedShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 8828; case RedShulkerBox::RedShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 8829; case RedShulkerBox::RedShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 8830; case RedShulkerBox::RedShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 8831; case RedStainedGlass::RedStainedGlass().ID: return 4095; case RedStainedGlassPane::RedStainedGlassPane(true, true, true, true).ID: return 6777; case RedStainedGlassPane::RedStainedGlassPane(true, true, true, false).ID: return 6778; case RedStainedGlassPane::RedStainedGlassPane(true, true, false, true).ID: return 6781; case RedStainedGlassPane::RedStainedGlassPane(true, true, false, false).ID: return 6782; case RedStainedGlassPane::RedStainedGlassPane(true, false, true, true).ID: return 6785; case RedStainedGlassPane::RedStainedGlassPane(true, false, true, false).ID: return 6786; case RedStainedGlassPane::RedStainedGlassPane(true, false, false, true).ID: return 6789; case RedStainedGlassPane::RedStainedGlassPane(true, false, false, false).ID: return 6790; case RedStainedGlassPane::RedStainedGlassPane(false, true, true, true).ID: return 6793; case RedStainedGlassPane::RedStainedGlassPane(false, true, true, false).ID: return 6794; case RedStainedGlassPane::RedStainedGlassPane(false, true, false, true).ID: return 6797; case RedStainedGlassPane::RedStainedGlassPane(false, true, false, false).ID: return 6798; case RedStainedGlassPane::RedStainedGlassPane(false, false, true, true).ID: return 6801; case RedStainedGlassPane::RedStainedGlassPane(false, false, true, false).ID: return 6802; case RedStainedGlassPane::RedStainedGlassPane(false, false, false, true).ID: return 6805; case RedStainedGlassPane::RedStainedGlassPane(false, false, false, false).ID: return 6806; case RedTerracotta::RedTerracotta().ID: return 6325; case RedTulip::RedTulip().ID: return 1416; case RedWallBanner::RedWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 7673; case RedWallBanner::RedWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 7674; case RedWallBanner::RedWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 7675; case RedWallBanner::RedWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 7676; case RedWool::RedWool().ID: return 1397; case RedstoneBlock::RedstoneBlock().ID: return 6190; case RedstoneLamp::RedstoneLamp(true).ID: return 5140; case RedstoneLamp::RedstoneLamp(false).ID: return 5141; case RedstoneOre::RedstoneOre(true).ID: return 3883; case RedstoneOre::RedstoneOre(false).ID: return 3884; case RedstoneTorch::RedstoneTorch(true).ID: return 3885; case RedstoneTorch::RedstoneTorch(false).ID: return 3886; case RedstoneWallTorch::RedstoneWallTorch(eBlockFace::BLOCK_FACE_ZM, true).ID: return 3887; case RedstoneWallTorch::RedstoneWallTorch(eBlockFace::BLOCK_FACE_ZM, false).ID: return 3888; case RedstoneWallTorch::RedstoneWallTorch(eBlockFace::BLOCK_FACE_ZP, true).ID: return 3889; case RedstoneWallTorch::RedstoneWallTorch(eBlockFace::BLOCK_FACE_ZP, false).ID: return 3890; case RedstoneWallTorch::RedstoneWallTorch(eBlockFace::BLOCK_FACE_XM, true).ID: return 3891; case RedstoneWallTorch::RedstoneWallTorch(eBlockFace::BLOCK_FACE_XM, false).ID: return 3892; case RedstoneWallTorch::RedstoneWallTorch(eBlockFace::BLOCK_FACE_XP, true).ID: return 3893; case RedstoneWallTorch::RedstoneWallTorch(eBlockFace::BLOCK_FACE_XP, false).ID: return 3894; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 0, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2056; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 0, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2057; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 0, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2058; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 0, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2059; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 0, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2060; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 0, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2061; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 0, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2062; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 0, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2063; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 0, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2064; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 1, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2065; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 1, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2066; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 1, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2067; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 1, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2068; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 1, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2069; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 1, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2070; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 1, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2071; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 1, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2072; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 1, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2073; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 2, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2074; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 2, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2075; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 2, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2076; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 2, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2077; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 2, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2078; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 2, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2079; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 2, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2080; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 2, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2081; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 2, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2082; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 3, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2083; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 3, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2084; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 3, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2085; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 3, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2086; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 3, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2087; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 3, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2088; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 3, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2089; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 3, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2090; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 3, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2091; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 4, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2092; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 4, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2093; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 4, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2094; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 4, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2095; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 4, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2096; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 4, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2097; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 4, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2098; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 4, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2099; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 4, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2100; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 5, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2101; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 5, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2102; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 5, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2103; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 5, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2104; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 5, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2105; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 5, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2106; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 5, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2107; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 5, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2108; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 5, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2109; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 6, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2110; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 6, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2111; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 6, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2112; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 6, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2113; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 6, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2114; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 6, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2115; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 6, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2116; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 6, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2117; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 6, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2118; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 7, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2119; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 7, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2120; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 7, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2121; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 7, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2122; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 7, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2123; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 7, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2124; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 7, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2125; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 7, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2126; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 7, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2127; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 8, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2128; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 8, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2129; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 8, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2130; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 8, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2131; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 8, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2132; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 8, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2133; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 8, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2134; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 8, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2135; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 8, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2136; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 9, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2137; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 9, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2138; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 9, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2139; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 9, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2140; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 9, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2141; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 9, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2142; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 9, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2143; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 9, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2144; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 9, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2145; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 10, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2146; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 10, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2147; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 10, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2148; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 10, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2149; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 10, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2150; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 10, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2151; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 10, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2152; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 10, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2153; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 10, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2154; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 11, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2155; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 11, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2156; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 11, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2157; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 11, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2158; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 11, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2159; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 11, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2160; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 11, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2161; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 11, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2162; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 11, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2163; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 12, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2164; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 12, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2165; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 12, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2166; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 12, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2167; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 12, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2168; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 12, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2169; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 12, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2170; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 12, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2171; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 12, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2172; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 13, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2173; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 13, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2174; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 13, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2175; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 13, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2176; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 13, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2177; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 13, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2178; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 13, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2179; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 13, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2180; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 13, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2181; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 14, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2182; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 14, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2183; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 14, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2184; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 14, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2185; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 14, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2186; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 14, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2187; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 14, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2188; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 14, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2189; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 14, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2190; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 15, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2191; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 15, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2192; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 15, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2193; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 15, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2194; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 15, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2195; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 15, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2196; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 15, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2197; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 15, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2198; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 15, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2199; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 0, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2200; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 0, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2201; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 0, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2202; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 0, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2203; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 0, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2204; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 0, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2205; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 0, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2206; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 0, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2207; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 0, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2208; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 1, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2209; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 1, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2210; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 1, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2211; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 1, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2212; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 1, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2213; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 1, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2214; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 1, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2215; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 1, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2216; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 1, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2217; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 2, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2218; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 2, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2219; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 2, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2220; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 2, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2221; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 2, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2222; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 2, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2223; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 2, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2224; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 2, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2225; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 2, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2226; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 3, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2227; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 3, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2228; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 3, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2229; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 3, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2230; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 3, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2231; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 3, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2232; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 3, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2233; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 3, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2234; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 3, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2235; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 4, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2236; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 4, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2237; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 4, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2238; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 4, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2239; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 4, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2240; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 4, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2241; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 4, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2242; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 4, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2243; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 4, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2244; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 5, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2245; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 5, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2246; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 5, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2247; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 5, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2248; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 5, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2249; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 5, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2250; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 5, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2251; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 5, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2252; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 5, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2253; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 6, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2254; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 6, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2255; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 6, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2256; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 6, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2257; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 6, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2258; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 6, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2259; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 6, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2260; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 6, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2261; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 6, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2262; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 7, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2263; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 7, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2264; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 7, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2265; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 7, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2266; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 7, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2267; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 7, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2268; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 7, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2269; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 7, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2270; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 7, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2271; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 8, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2272; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 8, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2273; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 8, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2274; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 8, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2275; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 8, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2276; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 8, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2277; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 8, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2278; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 8, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2279; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 8, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2280; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 9, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2281; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 9, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2282; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 9, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2283; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 9, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2284; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 9, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2285; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 9, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2286; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 9, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2287; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 9, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2288; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 9, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2289; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 10, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2290; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 10, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2291; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 10, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2292; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 10, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2293; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 10, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2294; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 10, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2295; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 10, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2296; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 10, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2297; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 10, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2298; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 11, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2299; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 11, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2300; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 11, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2301; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 11, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2302; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 11, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2303; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 11, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2304; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 11, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2305; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 11, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2306; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 11, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2307; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 12, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2308; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 12, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2309; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 12, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2310; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 12, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2311; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 12, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2312; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 12, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2313; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 12, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2314; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 12, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2315; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 12, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2316; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 13, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2317; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 13, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2318; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 13, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2319; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 13, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2320; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 13, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2321; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 13, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2322; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 13, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2323; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 13, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2324; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 13, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2325; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 14, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2326; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 14, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2327; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 14, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2328; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 14, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2329; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 14, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2330; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 14, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2331; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 14, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2332; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 14, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2333; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 14, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2334; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 15, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2335; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 15, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2336; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 15, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2337; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 15, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2338; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 15, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2339; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 15, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2340; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 15, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2341; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 15, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2342; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 15, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2343; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 0, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2344; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 0, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2345; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 0, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2346; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 0, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2347; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 0, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2348; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 0, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2349; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 0, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2350; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 0, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2351; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 0, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2352; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 1, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2353; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 1, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2354; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 1, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2355; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 1, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2356; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 1, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2357; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 1, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2358; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 1, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2359; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 1, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2360; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 1, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2361; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 2, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2362; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 2, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2363; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 2, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2364; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 2, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2365; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 2, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2366; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 2, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2367; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 2, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2368; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 2, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2369; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 2, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2370; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 3, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2371; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 3, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2372; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 3, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2373; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 3, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2374; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 3, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2375; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 3, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2376; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 3, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2377; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 3, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2378; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 3, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2379; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 4, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2380; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 4, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2381; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 4, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2382; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 4, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2383; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 4, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2384; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 4, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2385; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 4, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2386; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 4, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2387; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 4, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2388; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 5, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2389; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 5, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2390; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 5, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2391; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 5, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2392; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 5, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2393; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 5, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2394; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 5, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2395; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 5, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2396; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 5, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2397; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 6, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2398; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 6, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2399; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 6, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2400; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 6, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2401; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 6, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2402; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 6, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2403; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 6, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2404; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 6, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2405; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 6, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2406; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 7, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2407; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 7, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2408; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 7, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2409; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 7, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2410; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 7, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2411; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 7, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2412; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 7, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2413; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 7, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2414; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 7, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2415; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 8, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2416; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 8, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2417; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 8, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2418; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 8, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2419; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 8, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2420; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 8, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2421; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 8, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2422; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 8, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2423; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 8, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2424; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 9, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2425; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 9, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2426; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 9, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2427; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 9, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2428; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 9, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2429; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 9, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2430; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 9, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2431; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 9, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2432; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 9, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2433; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 10, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2434; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 10, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2435; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 10, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2436; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 10, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2437; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 10, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2438; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 10, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2439; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 10, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2440; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 10, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2441; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 10, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2442; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 11, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2443; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 11, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2444; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 11, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2445; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 11, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2446; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 11, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2447; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 11, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2448; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 11, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2449; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 11, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2450; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 11, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2451; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 12, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2452; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 12, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2453; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 12, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2454; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 12, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2455; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 12, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2456; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 12, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2457; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 12, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2458; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 12, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2459; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 12, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2460; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 13, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2461; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 13, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2462; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 13, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2463; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 13, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2464; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 13, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2465; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 13, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2466; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 13, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2467; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 13, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2468; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 13, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2469; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 14, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2470; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 14, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2471; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 14, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2472; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 14, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2473; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 14, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2474; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 14, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2475; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 14, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2476; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 14, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2477; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 14, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2478; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 15, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2479; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 15, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2480; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 15, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2481; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 15, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2482; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 15, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2483; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 15, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2484; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 15, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2485; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 15, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2486; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 15, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2487; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 0, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2488; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 0, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2489; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 0, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2490; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 0, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2491; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 0, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2492; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 0, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2493; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 0, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2494; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 0, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2495; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 0, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2496; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 1, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2497; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 1, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2498; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 1, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2499; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 1, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2500; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 1, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2501; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 1, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2502; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 1, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2503; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 1, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2504; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 1, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2505; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 2, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2506; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 2, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2507; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 2, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2508; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 2, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2509; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 2, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2510; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 2, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2511; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 2, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2512; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 2, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2513; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 2, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2514; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 3, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2515; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 3, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2516; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 3, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2517; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 3, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2518; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 3, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2519; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 3, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2520; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 3, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2521; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 3, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2522; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 3, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2523; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 4, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2524; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 4, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2525; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 4, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2526; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 4, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2527; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 4, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2528; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 4, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2529; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 4, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2530; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 4, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2531; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 4, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2532; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 5, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2533; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 5, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2534; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 5, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2535; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 5, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2536; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 5, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2537; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 5, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2538; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 5, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2539; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 5, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2540; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 5, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2541; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 6, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2542; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 6, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2543; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 6, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2544; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 6, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2545; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 6, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2546; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 6, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2547; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 6, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2548; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 6, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2549; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 6, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2550; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 7, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2551; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 7, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2552; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 7, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2553; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 7, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2554; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 7, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2555; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 7, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2556; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 7, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2557; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 7, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2558; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 7, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2559; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 8, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2560; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 8, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2561; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 8, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2562; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 8, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2563; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 8, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2564; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 8, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2565; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 8, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2566; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 8, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2567; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 8, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2568; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 9, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2569; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 9, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2570; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 9, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2571; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 9, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2572; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 9, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2573; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 9, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2574; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 9, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2575; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 9, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2576; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 9, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2577; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 10, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2578; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 10, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2579; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 10, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2580; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 10, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2581; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 10, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2582; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 10, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2583; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 10, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2584; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 10, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2585; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 10, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2586; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 11, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2587; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 11, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2588; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 11, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2589; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 11, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2590; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 11, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2591; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 11, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2592; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 11, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2593; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 11, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2594; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 11, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2595; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 12, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2596; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 12, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2597; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 12, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2598; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 12, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2599; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 12, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2600; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 12, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2601; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 12, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2602; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 12, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2603; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 12, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2604; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 13, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2605; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 13, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2606; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 13, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2607; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 13, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2608; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 13, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2609; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 13, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2610; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 13, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2611; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 13, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2612; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 13, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2613; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 14, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2614; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 14, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2615; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 14, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2616; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 14, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2617; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 14, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2618; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 14, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2619; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 14, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2620; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 14, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2621; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 14, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2622; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 15, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2623; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 15, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2624; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 15, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2625; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 15, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2626; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 15, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2627; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 15, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2628; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 15, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2629; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 15, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2630; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 15, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2631; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 0, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2632; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 0, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2633; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 0, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2634; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 0, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2635; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 0, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2636; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 0, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2637; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 0, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2638; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 0, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2639; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 0, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2640; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 1, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2641; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 1, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2642; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 1, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2643; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 1, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2644; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 1, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2645; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 1, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2646; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 1, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2647; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 1, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2648; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 1, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2649; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 2, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2650; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 2, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2651; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 2, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2652; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 2, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2653; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 2, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2654; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 2, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2655; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 2, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2656; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 2, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2657; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 2, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2658; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 3, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2659; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 3, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2660; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 3, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2661; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 3, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2662; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 3, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2663; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 3, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2664; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 3, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2665; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 3, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2666; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 3, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2667; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 4, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2668; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 4, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2669; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 4, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2670; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 4, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2671; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 4, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2672; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 4, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2673; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 4, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2674; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 4, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2675; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 4, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2676; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 5, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2677; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 5, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2678; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 5, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2679; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 5, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2680; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 5, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2681; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 5, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2682; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 5, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2683; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 5, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2684; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 5, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2685; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 6, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2686; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 6, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2687; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 6, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2688; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 6, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2689; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 6, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2690; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 6, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2691; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 6, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2692; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 6, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2693; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 6, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2694; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 7, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2695; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 7, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2696; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 7, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2697; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 7, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2698; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 7, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2699; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 7, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2700; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 7, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2701; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 7, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2702; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 7, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2703; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 8, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2704; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 8, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2705; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 8, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2706; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 8, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2707; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 8, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2708; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 8, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2709; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 8, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2710; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 8, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2711; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 8, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2712; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 9, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2713; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 9, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2714; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 9, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2715; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 9, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2716; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 9, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2717; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 9, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2718; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 9, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2719; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 9, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2720; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 9, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2721; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 10, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2722; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 10, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2723; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 10, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2724; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 10, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2725; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 10, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2726; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 10, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2727; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 10, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2728; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 10, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2729; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 10, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2730; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 11, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2731; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 11, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2732; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 11, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2733; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 11, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2734; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 11, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2735; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 11, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2736; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 11, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2737; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 11, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2738; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 11, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2739; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 12, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2740; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 12, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2741; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 12, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2742; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 12, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2743; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 12, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2744; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 12, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2745; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 12, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2746; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 12, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2747; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 12, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2748; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 13, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2749; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 13, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2750; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 13, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2751; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 13, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2752; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 13, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2753; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 13, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2754; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 13, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2755; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 13, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2756; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 13, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2757; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 14, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2758; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 14, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2759; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 14, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2760; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 14, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2761; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 14, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2762; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 14, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2763; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 14, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2764; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 14, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2765; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 14, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2766; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 15, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2767; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 15, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2768; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 15, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2769; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 15, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2770; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 15, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2771; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 15, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2772; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 15, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2773; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 15, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2774; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 15, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2775; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 0, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2776; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 0, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2777; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 0, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2778; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 0, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2779; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 0, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2780; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 0, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2781; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 0, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2782; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 0, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2783; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 0, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2784; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 1, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2785; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 1, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2786; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 1, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2787; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 1, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2788; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 1, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2789; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 1, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2790; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 1, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2791; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 1, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2792; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 1, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2793; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 2, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2794; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 2, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2795; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 2, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2796; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 2, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2797; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 2, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2798; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 2, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2799; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 2, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2800; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 2, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2801; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 2, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2802; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 3, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2803; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 3, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2804; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 3, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2805; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 3, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2806; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 3, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2807; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 3, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2808; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 3, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2809; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 3, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2810; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 3, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2811; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 4, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2812; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 4, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2813; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 4, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2814; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 4, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2815; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 4, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2816; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 4, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2817; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 4, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2818; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 4, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2819; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 4, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2820; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 5, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2821; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 5, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2822; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 5, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2823; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 5, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2824; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 5, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2825; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 5, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2826; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 5, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2827; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 5, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2828; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 5, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2829; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 6, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2830; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 6, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2831; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 6, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2832; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 6, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2833; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 6, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2834; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 6, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2835; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 6, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2836; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 6, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2837; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 6, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2838; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 7, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2839; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 7, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2840; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 7, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2841; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 7, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2842; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 7, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2843; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 7, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2844; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 7, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2845; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 7, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2846; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 7, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2847; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 8, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2848; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 8, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2849; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 8, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2850; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 8, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2851; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 8, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2852; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 8, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2853; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 8, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2854; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 8, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2855; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 8, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2856; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 9, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2857; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 9, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2858; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 9, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2859; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 9, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2860; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 9, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2861; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 9, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2862; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 9, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2863; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 9, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2864; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 9, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2865; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 10, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2866; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 10, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2867; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 10, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2868; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 10, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2869; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 10, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2870; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 10, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2871; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 10, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2872; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 10, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2873; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 10, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2874; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 11, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2875; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 11, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2876; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 11, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2877; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 11, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2878; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 11, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2879; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 11, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2880; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 11, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2881; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 11, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2882; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 11, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2883; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 12, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2884; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 12, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2885; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 12, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2886; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 12, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2887; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 12, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2888; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 12, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2889; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 12, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2890; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 12, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2891; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 12, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2892; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 13, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2893; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 13, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2894; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 13, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2895; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 13, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2896; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 13, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2897; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 13, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2898; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 13, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2899; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 13, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2900; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 13, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2901; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 14, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2902; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 14, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2903; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 14, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2904; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 14, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2905; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 14, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2906; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 14, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2907; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 14, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2908; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 14, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2909; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 14, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2910; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 15, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2911; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 15, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2912; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 15, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2913; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 15, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2914; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 15, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2915; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 15, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2916; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 15, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2917; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 15, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2918; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 15, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2919; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 0, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2920; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 0, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2921; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 0, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2922; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 0, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2923; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 0, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2924; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 0, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2925; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 0, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2926; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 0, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2927; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 0, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2928; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 1, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2929; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 1, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2930; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 1, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2931; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 1, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2932; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 1, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2933; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 1, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2934; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 1, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2935; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 1, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2936; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 1, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2937; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 2, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2938; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 2, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2939; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 2, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2940; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 2, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2941; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 2, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2942; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 2, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2943; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 2, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2944; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 2, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2945; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 2, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2946; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 3, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2947; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 3, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2948; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 3, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2949; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 3, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2950; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 3, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2951; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 3, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2952; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 3, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2953; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 3, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2954; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 3, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2955; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 4, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2956; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 4, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2957; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 4, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2958; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 4, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2959; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 4, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2960; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 4, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2961; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 4, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2962; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 4, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2963; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 4, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2964; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 5, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2965; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 5, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2966; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 5, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2967; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 5, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2968; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 5, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2969; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 5, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2970; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 5, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2971; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 5, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2972; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 5, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2973; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 6, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2974; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 6, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2975; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 6, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2976; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 6, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2977; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 6, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2978; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 6, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2979; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 6, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2980; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 6, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2981; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 6, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2982; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 7, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2983; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 7, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2984; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 7, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2985; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 7, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2986; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 7, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2987; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 7, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2988; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 7, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2989; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 7, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2990; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 7, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2991; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 8, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2992; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 8, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2993; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 8, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2994; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 8, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2995; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 8, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2996; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 8, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2997; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 8, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2998; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 8, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2999; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 8, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3000; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 9, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3001; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 9, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3002; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 9, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3003; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 9, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3004; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 9, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3005; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 9, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3006; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 9, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3007; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 9, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3008; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 9, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3009; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 10, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3010; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 10, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3011; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 10, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3012; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 10, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3013; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 10, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3014; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 10, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3015; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 10, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3016; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 10, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3017; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 10, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3018; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 11, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3019; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 11, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3020; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 11, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3021; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 11, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3022; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 11, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3023; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 11, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3024; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 11, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3025; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 11, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3026; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 11, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3027; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 12, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3028; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 12, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3029; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 12, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3030; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 12, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3031; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 12, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3032; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 12, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3033; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 12, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3034; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 12, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3035; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 12, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3036; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 13, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3037; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 13, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3038; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 13, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3039; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 13, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3040; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 13, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3041; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 13, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3042; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 13, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3043; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 13, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3044; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 13, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3045; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 14, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3046; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 14, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3047; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 14, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3048; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 14, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3049; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 14, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3050; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 14, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3051; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 14, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3052; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 14, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3053; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 14, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3054; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 15, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3055; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 15, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3056; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 15, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3057; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 15, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3058; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 15, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3059; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 15, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3060; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 15, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3061; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 15, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3062; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 15, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3063; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 0, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3064; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 0, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3065; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 0, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3066; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 0, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3067; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 0, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3068; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 0, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3069; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 0, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3070; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 0, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3071; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 0, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3072; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 1, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3073; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 1, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3074; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 1, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3075; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 1, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3076; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 1, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3077; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 1, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3078; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 1, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3079; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 1, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3080; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 1, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3081; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 2, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3082; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 2, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3083; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 2, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3084; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 2, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3085; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 2, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3086; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 2, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3087; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 2, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3088; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 2, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3089; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 2, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3090; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 3, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3091; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 3, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3092; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 3, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3093; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 3, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3094; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 3, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3095; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 3, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3096; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 3, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3097; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 3, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3098; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 3, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3099; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 4, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3100; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 4, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3101; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 4, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3102; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 4, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3103; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 4, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3104; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 4, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3105; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 4, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3106; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 4, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3107; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 4, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3108; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 5, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3109; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 5, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3110; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 5, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3111; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 5, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3112; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 5, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3113; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 5, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3114; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 5, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3115; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 5, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3116; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 5, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3117; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 6, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3118; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 6, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3119; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 6, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3120; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 6, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3121; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 6, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3122; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 6, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3123; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 6, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3124; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 6, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3125; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 6, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3126; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 7, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3127; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 7, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3128; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 7, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3129; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 7, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3130; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 7, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3131; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 7, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3132; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 7, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3133; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 7, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3134; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 7, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3135; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 8, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3136; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 8, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3137; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 8, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3138; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 8, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3139; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 8, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3140; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 8, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3141; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 8, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3142; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 8, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3143; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 8, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3144; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 9, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3145; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 9, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3146; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 9, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3147; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 9, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3148; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 9, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3149; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 9, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3150; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 9, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3151; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 9, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3152; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 9, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3153; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 10, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3154; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 10, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3155; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 10, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3156; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 10, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3157; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 10, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3158; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 10, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3159; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 10, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3160; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 10, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3161; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 10, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3162; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 11, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3163; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 11, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3164; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 11, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3165; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 11, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3166; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 11, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3167; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 11, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3168; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 11, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3169; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 11, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3170; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 11, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3171; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 12, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3172; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 12, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3173; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 12, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3174; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 12, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3175; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 12, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3176; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 12, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3177; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 12, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3178; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 12, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3179; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 12, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3180; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 13, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3181; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 13, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3182; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 13, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3183; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 13, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3184; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 13, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3185; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 13, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3186; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 13, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3187; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 13, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3188; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 13, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3189; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 14, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3190; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 14, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3191; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 14, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3192; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 14, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3193; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 14, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3194; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 14, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3195; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 14, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3196; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 14, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3197; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 14, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3198; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 15, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3199; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 15, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3200; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 15, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3201; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 15, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3202; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 15, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3203; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 15, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3204; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 15, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3205; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 15, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3206; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 15, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3207; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 0, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3208; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 0, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3209; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 0, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3210; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 0, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3211; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 0, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3212; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 0, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3213; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 0, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3214; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 0, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3215; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 0, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3216; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 1, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3217; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 1, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3218; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 1, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3219; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 1, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3220; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 1, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3221; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 1, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3222; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 1, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3223; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 1, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3224; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 1, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3225; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 2, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3226; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 2, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3227; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 2, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3228; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 2, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3229; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 2, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3230; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 2, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3231; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 2, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3232; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 2, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3233; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 2, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3234; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 3, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3235; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 3, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3236; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 3, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3237; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 3, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3238; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 3, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3239; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 3, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3240; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 3, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3241; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 3, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3242; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 3, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3243; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 4, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3244; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 4, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3245; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 4, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3246; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 4, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3247; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 4, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3248; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 4, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3249; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 4, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3250; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 4, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3251; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 4, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3252; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 5, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3253; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 5, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3254; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 5, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3255; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 5, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3256; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 5, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3257; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 5, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3258; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 5, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3259; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 5, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3260; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 5, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3261; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 6, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3262; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 6, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3263; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 6, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3264; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 6, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3265; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 6, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3266; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 6, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3267; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 6, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3268; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 6, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3269; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 6, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3270; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 7, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3271; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 7, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3272; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 7, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3273; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 7, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3274; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 7, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3275; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 7, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3276; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 7, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3277; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 7, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3278; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 7, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3279; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 8, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3280; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 8, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3281; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 8, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3282; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 8, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3283; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 8, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3284; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 8, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3285; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 8, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3286; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 8, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3287; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 8, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3288; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 9, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3289; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 9, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3290; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 9, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3291; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 9, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3292; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 9, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3293; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 9, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3294; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 9, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3295; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 9, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3296; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 9, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3297; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 10, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3298; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 10, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3299; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 10, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3300; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 10, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3301; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 10, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3302; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 10, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3303; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 10, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3304; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 10, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3305; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 10, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3306; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 11, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3307; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 11, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3308; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 11, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3309; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 11, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3310; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 11, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3311; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 11, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3312; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 11, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3313; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 11, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3314; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 11, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3315; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 12, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3316; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 12, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3317; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 12, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3318; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 12, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3319; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 12, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3320; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 12, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3321; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 12, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3322; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 12, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3323; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 12, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3324; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 13, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3325; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 13, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3326; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 13, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3327; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 13, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3328; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 13, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3329; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 13, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3330; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 13, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3331; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 13, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3332; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 13, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3333; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 14, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3334; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 14, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3335; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 14, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3336; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 14, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3337; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 14, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3338; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 14, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3339; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 14, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3340; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 14, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3341; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 14, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3342; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 15, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3343; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 15, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3344; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 15, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3345; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 15, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3346; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 15, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3347; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 15, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3348; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 15, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3349; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 15, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3350; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 15, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3351; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_ZM, true, true).ID: return 4017; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_ZM, true, false).ID: return 4018; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_ZM, false, true).ID: return 4019; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_ZM, false, false).ID: return 4020; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_ZP, true, true).ID: return 4021; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_ZP, true, false).ID: return 4022; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_ZP, false, true).ID: return 4023; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_ZP, false, false).ID: return 4024; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_XM, true, true).ID: return 4025; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_XM, true, false).ID: return 4026; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_XM, false, true).ID: return 4027; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_XM, false, false).ID: return 4028; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_XP, true, true).ID: return 4029; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_XP, true, false).ID: return 4030; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_XP, false, true).ID: return 4031; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_XP, false, false).ID: return 4032; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_ZM, true, true).ID: return 4033; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_ZM, true, false).ID: return 4034; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_ZM, false, true).ID: return 4035; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_ZM, false, false).ID: return 4036; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_ZP, true, true).ID: return 4037; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_ZP, true, false).ID: return 4038; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_ZP, false, true).ID: return 4039; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_ZP, false, false).ID: return 4040; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_XM, true, true).ID: return 4041; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_XM, true, false).ID: return 4042; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_XM, false, true).ID: return 4043; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_XM, false, false).ID: return 4044; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_XP, true, true).ID: return 4045; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_XP, true, false).ID: return 4046; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_XP, false, true).ID: return 4047; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_XP, false, false).ID: return 4048; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_ZM, true, true).ID: return 4049; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_ZM, true, false).ID: return 4050; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_ZM, false, true).ID: return 4051; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_ZM, false, false).ID: return 4052; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_ZP, true, true).ID: return 4053; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_ZP, true, false).ID: return 4054; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_ZP, false, true).ID: return 4055; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_ZP, false, false).ID: return 4056; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_XM, true, true).ID: return 4057; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_XM, true, false).ID: return 4058; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_XM, false, true).ID: return 4059; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_XM, false, false).ID: return 4060; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_XP, true, true).ID: return 4061; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_XP, true, false).ID: return 4062; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_XP, false, true).ID: return 4063; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_XP, false, false).ID: return 4064; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_ZM, true, true).ID: return 4065; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_ZM, true, false).ID: return 4066; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_ZM, false, true).ID: return 4067; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_ZM, false, false).ID: return 4068; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_ZP, true, true).ID: return 4069; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_ZP, true, false).ID: return 4070; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_ZP, false, true).ID: return 4071; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_ZP, false, false).ID: return 4072; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_XM, true, true).ID: return 4073; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_XM, true, false).ID: return 4074; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_XM, false, true).ID: return 4075; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_XM, false, false).ID: return 4076; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_XP, true, true).ID: return 4077; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_XP, true, false).ID: return 4078; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_XP, false, true).ID: return 4079; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_XP, false, false).ID: return 4080; case RepeatingCommandBlock::RepeatingCommandBlock(true, eBlockFace::BLOCK_FACE_ZM).ID: return 8689; case RepeatingCommandBlock::RepeatingCommandBlock(true, eBlockFace::BLOCK_FACE_XP).ID: return 8690; case RepeatingCommandBlock::RepeatingCommandBlock(true, eBlockFace::BLOCK_FACE_ZP).ID: return 8691; case RepeatingCommandBlock::RepeatingCommandBlock(true, eBlockFace::BLOCK_FACE_XM).ID: return 8692; case RepeatingCommandBlock::RepeatingCommandBlock(true, eBlockFace::BLOCK_FACE_YP).ID: return 8693; case RepeatingCommandBlock::RepeatingCommandBlock(true, eBlockFace::BLOCK_FACE_YM).ID: return 8694; case RepeatingCommandBlock::RepeatingCommandBlock(false, eBlockFace::BLOCK_FACE_ZM).ID: return 8695; case RepeatingCommandBlock::RepeatingCommandBlock(false, eBlockFace::BLOCK_FACE_XP).ID: return 8696; case RepeatingCommandBlock::RepeatingCommandBlock(false, eBlockFace::BLOCK_FACE_ZP).ID: return 8697; case RepeatingCommandBlock::RepeatingCommandBlock(false, eBlockFace::BLOCK_FACE_XM).ID: return 8698; case RepeatingCommandBlock::RepeatingCommandBlock(false, eBlockFace::BLOCK_FACE_YP).ID: return 8699; case RepeatingCommandBlock::RepeatingCommandBlock(false, eBlockFace::BLOCK_FACE_YM).ID: return 8700; case RoseBush::RoseBush(RoseBush::Half::Upper).ID: return 7353; case RoseBush::RoseBush(RoseBush::Half::Lower).ID: return 7354; case Sand::Sand().ID: return 66; case Sandstone::Sandstone().ID: return 245; case SandstoneSlab::SandstoneSlab(SandstoneSlab::Type::Top).ID: return 7813; case SandstoneSlab::SandstoneSlab(SandstoneSlab::Type::Bottom).ID: return 7815; case SandstoneSlab::SandstoneSlab(SandstoneSlab::Type::Double).ID: return 7817; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SandstoneStairs::Half::Top, SandstoneStairs::Shape::Straight).ID: return 5155; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SandstoneStairs::Half::Top, SandstoneStairs::Shape::InnerLeft).ID: return 5157; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SandstoneStairs::Half::Top, SandstoneStairs::Shape::InnerRight).ID: return 5159; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SandstoneStairs::Half::Top, SandstoneStairs::Shape::OuterLeft).ID: return 5161; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SandstoneStairs::Half::Top, SandstoneStairs::Shape::OuterRight).ID: return 5163; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::Straight).ID: return 5165; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::InnerLeft).ID: return 5167; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::InnerRight).ID: return 5169; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::OuterLeft).ID: return 5171; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::OuterRight).ID: return 5173; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SandstoneStairs::Half::Top, SandstoneStairs::Shape::Straight).ID: return 5175; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SandstoneStairs::Half::Top, SandstoneStairs::Shape::InnerLeft).ID: return 5177; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SandstoneStairs::Half::Top, SandstoneStairs::Shape::InnerRight).ID: return 5179; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SandstoneStairs::Half::Top, SandstoneStairs::Shape::OuterLeft).ID: return 5181; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SandstoneStairs::Half::Top, SandstoneStairs::Shape::OuterRight).ID: return 5183; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::Straight).ID: return 5185; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::InnerLeft).ID: return 5187; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::InnerRight).ID: return 5189; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::OuterLeft).ID: return 5191; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::OuterRight).ID: return 5193; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XM, SandstoneStairs::Half::Top, SandstoneStairs::Shape::Straight).ID: return 5195; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XM, SandstoneStairs::Half::Top, SandstoneStairs::Shape::InnerLeft).ID: return 5197; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XM, SandstoneStairs::Half::Top, SandstoneStairs::Shape::InnerRight).ID: return 5199; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XM, SandstoneStairs::Half::Top, SandstoneStairs::Shape::OuterLeft).ID: return 5201; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XM, SandstoneStairs::Half::Top, SandstoneStairs::Shape::OuterRight).ID: return 5203; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XM, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::Straight).ID: return 5205; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XM, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::InnerLeft).ID: return 5207; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XM, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::InnerRight).ID: return 5209; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XM, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::OuterLeft).ID: return 5211; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XM, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::OuterRight).ID: return 5213; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XP, SandstoneStairs::Half::Top, SandstoneStairs::Shape::Straight).ID: return 5215; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XP, SandstoneStairs::Half::Top, SandstoneStairs::Shape::InnerLeft).ID: return 5217; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XP, SandstoneStairs::Half::Top, SandstoneStairs::Shape::InnerRight).ID: return 5219; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XP, SandstoneStairs::Half::Top, SandstoneStairs::Shape::OuterLeft).ID: return 5221; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XP, SandstoneStairs::Half::Top, SandstoneStairs::Shape::OuterRight).ID: return 5223; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XP, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::Straight).ID: return 5225; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XP, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::InnerLeft).ID: return 5227; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XP, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::InnerRight).ID: return 5229; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XP, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::OuterLeft).ID: return 5231; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XP, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::OuterRight).ID: return 5233; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::Low, SandstoneWall::South::Low, true, SandstoneWall::West::Low).ID: return 10909; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::Low, SandstoneWall::South::Low, true, SandstoneWall::West::None).ID: return 10910; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::Low, SandstoneWall::South::Low, false, SandstoneWall::West::Low).ID: return 10913; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::Low, SandstoneWall::South::Low, false, SandstoneWall::West::None).ID: return 10914; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::Low, SandstoneWall::South::None, true, SandstoneWall::West::Low).ID: return 10917; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::Low, SandstoneWall::South::None, true, SandstoneWall::West::None).ID: return 10918; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::Low, SandstoneWall::South::None, false, SandstoneWall::West::Low).ID: return 10921; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::Low, SandstoneWall::South::None, false, SandstoneWall::West::None).ID: return 10922; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::None, SandstoneWall::South::Low, true, SandstoneWall::West::Low).ID: return 10925; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::None, SandstoneWall::South::Low, true, SandstoneWall::West::None).ID: return 10926; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::None, SandstoneWall::South::Low, false, SandstoneWall::West::Low).ID: return 10929; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::None, SandstoneWall::South::Low, false, SandstoneWall::West::None).ID: return 10930; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::None, SandstoneWall::South::None, true, SandstoneWall::West::Low).ID: return 10933; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::None, SandstoneWall::South::None, true, SandstoneWall::West::None).ID: return 10934; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::None, SandstoneWall::South::None, false, SandstoneWall::West::Low).ID: return 10937; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::None, SandstoneWall::South::None, false, SandstoneWall::West::None).ID: return 10938; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::Low, SandstoneWall::South::Low, true, SandstoneWall::West::Low).ID: return 10941; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::Low, SandstoneWall::South::Low, true, SandstoneWall::West::None).ID: return 10942; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::Low, SandstoneWall::South::Low, false, SandstoneWall::West::Low).ID: return 10945; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::Low, SandstoneWall::South::Low, false, SandstoneWall::West::None).ID: return 10946; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::Low, SandstoneWall::South::None, true, SandstoneWall::West::Low).ID: return 10949; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::Low, SandstoneWall::South::None, true, SandstoneWall::West::None).ID: return 10950; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::Low, SandstoneWall::South::None, false, SandstoneWall::West::Low).ID: return 10953; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::Low, SandstoneWall::South::None, false, SandstoneWall::West::None).ID: return 10954; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::None, SandstoneWall::South::Low, true, SandstoneWall::West::Low).ID: return 10957; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::None, SandstoneWall::South::Low, true, SandstoneWall::West::None).ID: return 10958; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::None, SandstoneWall::South::Low, false, SandstoneWall::West::Low).ID: return 10961; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::None, SandstoneWall::South::Low, false, SandstoneWall::West::None).ID: return 10962; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::None, SandstoneWall::South::None, true, SandstoneWall::West::Low).ID: return 10965; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::None, SandstoneWall::South::None, true, SandstoneWall::West::None).ID: return 10966; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::None, SandstoneWall::South::None, false, SandstoneWall::West::Low).ID: return 10969; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::None, SandstoneWall::South::None, false, SandstoneWall::West::None).ID: return 10970; case Scaffolding::Scaffolding(true, 0).ID: return 11100; case Scaffolding::Scaffolding(true, 1).ID: return 11102; case Scaffolding::Scaffolding(true, 2).ID: return 11104; case Scaffolding::Scaffolding(true, 3).ID: return 11106; case Scaffolding::Scaffolding(true, 4).ID: return 11108; case Scaffolding::Scaffolding(true, 5).ID: return 11110; case Scaffolding::Scaffolding(true, 6).ID: return 11112; case Scaffolding::Scaffolding(true, 7).ID: return 11114; case Scaffolding::Scaffolding(false, 0).ID: return 11116; case Scaffolding::Scaffolding(false, 1).ID: return 11118; case Scaffolding::Scaffolding(false, 2).ID: return 11120; case Scaffolding::Scaffolding(false, 3).ID: return 11122; case Scaffolding::Scaffolding(false, 4).ID: return 11124; case Scaffolding::Scaffolding(false, 5).ID: return 11126; case Scaffolding::Scaffolding(false, 6).ID: return 11128; case Scaffolding::Scaffolding(false, 7).ID: return 11130; case SeaLantern::SeaLantern().ID: return 7326; case SeaPickle::SeaPickle(1).ID: return 9105; case SeaPickle::SeaPickle(2).ID: return 9107; case SeaPickle::SeaPickle(3).ID: return 9109; case SeaPickle::SeaPickle(4).ID: return 9111; case Seagrass::Seagrass().ID: return 1344; case ShulkerBox::ShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 8736; case ShulkerBox::ShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 8737; case ShulkerBox::ShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 8738; case ShulkerBox::ShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 8739; case ShulkerBox::ShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 8740; case ShulkerBox::ShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 8741; case SkeletonSkull::SkeletonSkull(0).ID: return 5954; case SkeletonSkull::SkeletonSkull(1).ID: return 5955; case SkeletonSkull::SkeletonSkull(2).ID: return 5956; case SkeletonSkull::SkeletonSkull(3).ID: return 5957; case SkeletonSkull::SkeletonSkull(4).ID: return 5958; case SkeletonSkull::SkeletonSkull(5).ID: return 5959; case SkeletonSkull::SkeletonSkull(6).ID: return 5960; case SkeletonSkull::SkeletonSkull(7).ID: return 5961; case SkeletonSkull::SkeletonSkull(8).ID: return 5962; case SkeletonSkull::SkeletonSkull(9).ID: return 5963; case SkeletonSkull::SkeletonSkull(10).ID: return 5964; case SkeletonSkull::SkeletonSkull(11).ID: return 5965; case SkeletonSkull::SkeletonSkull(12).ID: return 5966; case SkeletonSkull::SkeletonSkull(13).ID: return 5967; case SkeletonSkull::SkeletonSkull(14).ID: return 5968; case SkeletonSkull::SkeletonSkull(15).ID: return 5969; case SkeletonWallSkull::SkeletonWallSkull(eBlockFace::BLOCK_FACE_ZM).ID: return 5970; case SkeletonWallSkull::SkeletonWallSkull(eBlockFace::BLOCK_FACE_ZP).ID: return 5971; case SkeletonWallSkull::SkeletonWallSkull(eBlockFace::BLOCK_FACE_XM).ID: return 5972; case SkeletonWallSkull::SkeletonWallSkull(eBlockFace::BLOCK_FACE_XP).ID: return 5973; case SlimeBlock::SlimeBlock().ID: return 6999; case SmithingTable::SmithingTable().ID: return 11193; case Smoker::Smoker(eBlockFace::BLOCK_FACE_ZM, true).ID: return 11147; case Smoker::Smoker(eBlockFace::BLOCK_FACE_ZM, false).ID: return 11148; case Smoker::Smoker(eBlockFace::BLOCK_FACE_ZP, true).ID: return 11149; case Smoker::Smoker(eBlockFace::BLOCK_FACE_ZP, false).ID: return 11150; case Smoker::Smoker(eBlockFace::BLOCK_FACE_XM, true).ID: return 11151; case Smoker::Smoker(eBlockFace::BLOCK_FACE_XM, false).ID: return 11152; case Smoker::Smoker(eBlockFace::BLOCK_FACE_XP, true).ID: return 11153; case Smoker::Smoker(eBlockFace::BLOCK_FACE_XP, false).ID: return 11154; case SmoothQuartz::SmoothQuartz().ID: return 7880; case SmoothQuartzSlab::SmoothQuartzSlab(SmoothQuartzSlab::Type::Top).ID: return 10296; case SmoothQuartzSlab::SmoothQuartzSlab(SmoothQuartzSlab::Type::Bottom).ID: return 10298; case SmoothQuartzSlab::SmoothQuartzSlab(SmoothQuartzSlab::Type::Double).ID: return 10300; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_ZM, SmoothQuartzStairs::Half::Top, SmoothQuartzStairs::Shape::Straight).ID: return 9774; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_ZM, SmoothQuartzStairs::Half::Top, SmoothQuartzStairs::Shape::InnerLeft).ID: return 9776; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_ZM, SmoothQuartzStairs::Half::Top, SmoothQuartzStairs::Shape::InnerRight).ID: return 9778; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_ZM, SmoothQuartzStairs::Half::Top, SmoothQuartzStairs::Shape::OuterLeft).ID: return 9780; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_ZM, SmoothQuartzStairs::Half::Top, SmoothQuartzStairs::Shape::OuterRight).ID: return 9782; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_ZM, SmoothQuartzStairs::Half::Bottom, SmoothQuartzStairs::Shape::Straight).ID: return 9784; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_ZM, SmoothQuartzStairs::Half::Bottom, SmoothQuartzStairs::Shape::InnerLeft).ID: return 9786; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_ZM, SmoothQuartzStairs::Half::Bottom, SmoothQuartzStairs::Shape::InnerRight).ID: return 9788; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_ZM, SmoothQuartzStairs::Half::Bottom, SmoothQuartzStairs::Shape::OuterLeft).ID: return 9790; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_ZM, SmoothQuartzStairs::Half::Bottom, SmoothQuartzStairs::Shape::OuterRight).ID: return 9792; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_ZP, SmoothQuartzStairs::Half::Top, SmoothQuartzStairs::Shape::Straight).ID: return 9794; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_ZP, SmoothQuartzStairs::Half::Top, SmoothQuartzStairs::Shape::InnerLeft).ID: return 9796; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_ZP, SmoothQuartzStairs::Half::Top, SmoothQuartzStairs::Shape::InnerRight).ID: return 9798; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_ZP, SmoothQuartzStairs::Half::Top, SmoothQuartzStairs::Shape::OuterLeft).ID: return 9800; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_ZP, SmoothQuartzStairs::Half::Top, SmoothQuartzStairs::Shape::OuterRight).ID: return 9802; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_ZP, SmoothQuartzStairs::Half::Bottom, SmoothQuartzStairs::Shape::Straight).ID: return 9804; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_ZP, SmoothQuartzStairs::Half::Bottom, SmoothQuartzStairs::Shape::InnerLeft).ID: return 9806; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_ZP, SmoothQuartzStairs::Half::Bottom, SmoothQuartzStairs::Shape::InnerRight).ID: return 9808; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_ZP, SmoothQuartzStairs::Half::Bottom, SmoothQuartzStairs::Shape::OuterLeft).ID: return 9810; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_ZP, SmoothQuartzStairs::Half::Bottom, SmoothQuartzStairs::Shape::OuterRight).ID: return 9812; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_XM, SmoothQuartzStairs::Half::Top, SmoothQuartzStairs::Shape::Straight).ID: return 9814; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_XM, SmoothQuartzStairs::Half::Top, SmoothQuartzStairs::Shape::InnerLeft).ID: return 9816; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_XM, SmoothQuartzStairs::Half::Top, SmoothQuartzStairs::Shape::InnerRight).ID: return 9818; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_XM, SmoothQuartzStairs::Half::Top, SmoothQuartzStairs::Shape::OuterLeft).ID: return 9820; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_XM, SmoothQuartzStairs::Half::Top, SmoothQuartzStairs::Shape::OuterRight).ID: return 9822; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_XM, SmoothQuartzStairs::Half::Bottom, SmoothQuartzStairs::Shape::Straight).ID: return 9824; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_XM, SmoothQuartzStairs::Half::Bottom, SmoothQuartzStairs::Shape::InnerLeft).ID: return 9826; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_XM, SmoothQuartzStairs::Half::Bottom, SmoothQuartzStairs::Shape::InnerRight).ID: return 9828; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_XM, SmoothQuartzStairs::Half::Bottom, SmoothQuartzStairs::Shape::OuterLeft).ID: return 9830; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_XM, SmoothQuartzStairs::Half::Bottom, SmoothQuartzStairs::Shape::OuterRight).ID: return 9832; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_XP, SmoothQuartzStairs::Half::Top, SmoothQuartzStairs::Shape::Straight).ID: return 9834; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_XP, SmoothQuartzStairs::Half::Top, SmoothQuartzStairs::Shape::InnerLeft).ID: return 9836; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_XP, SmoothQuartzStairs::Half::Top, SmoothQuartzStairs::Shape::InnerRight).ID: return 9838; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_XP, SmoothQuartzStairs::Half::Top, SmoothQuartzStairs::Shape::OuterLeft).ID: return 9840; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_XP, SmoothQuartzStairs::Half::Top, SmoothQuartzStairs::Shape::OuterRight).ID: return 9842; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_XP, SmoothQuartzStairs::Half::Bottom, SmoothQuartzStairs::Shape::Straight).ID: return 9844; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_XP, SmoothQuartzStairs::Half::Bottom, SmoothQuartzStairs::Shape::InnerLeft).ID: return 9846; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_XP, SmoothQuartzStairs::Half::Bottom, SmoothQuartzStairs::Shape::InnerRight).ID: return 9848; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_XP, SmoothQuartzStairs::Half::Bottom, SmoothQuartzStairs::Shape::OuterLeft).ID: return 9850; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_XP, SmoothQuartzStairs::Half::Bottom, SmoothQuartzStairs::Shape::OuterRight).ID: return 9852; case SmoothRedSandstone::SmoothRedSandstone().ID: return 7881; case SmoothRedSandstoneSlab::SmoothRedSandstoneSlab(SmoothRedSandstoneSlab::Type::Top).ID: return 10260; case SmoothRedSandstoneSlab::SmoothRedSandstoneSlab(SmoothRedSandstoneSlab::Type::Bottom).ID: return 10262; case SmoothRedSandstoneSlab::SmoothRedSandstoneSlab(SmoothRedSandstoneSlab::Type::Double).ID: return 10264; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SmoothRedSandstoneStairs::Half::Top, SmoothRedSandstoneStairs::Shape::Straight).ID: return 9214; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SmoothRedSandstoneStairs::Half::Top, SmoothRedSandstoneStairs::Shape::InnerLeft).ID: return 9216; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SmoothRedSandstoneStairs::Half::Top, SmoothRedSandstoneStairs::Shape::InnerRight).ID: return 9218; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SmoothRedSandstoneStairs::Half::Top, SmoothRedSandstoneStairs::Shape::OuterLeft).ID: return 9220; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SmoothRedSandstoneStairs::Half::Top, SmoothRedSandstoneStairs::Shape::OuterRight).ID: return 9222; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SmoothRedSandstoneStairs::Half::Bottom, SmoothRedSandstoneStairs::Shape::Straight).ID: return 9224; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SmoothRedSandstoneStairs::Half::Bottom, SmoothRedSandstoneStairs::Shape::InnerLeft).ID: return 9226; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SmoothRedSandstoneStairs::Half::Bottom, SmoothRedSandstoneStairs::Shape::InnerRight).ID: return 9228; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SmoothRedSandstoneStairs::Half::Bottom, SmoothRedSandstoneStairs::Shape::OuterLeft).ID: return 9230; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SmoothRedSandstoneStairs::Half::Bottom, SmoothRedSandstoneStairs::Shape::OuterRight).ID: return 9232; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SmoothRedSandstoneStairs::Half::Top, SmoothRedSandstoneStairs::Shape::Straight).ID: return 9234; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SmoothRedSandstoneStairs::Half::Top, SmoothRedSandstoneStairs::Shape::InnerLeft).ID: return 9236; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SmoothRedSandstoneStairs::Half::Top, SmoothRedSandstoneStairs::Shape::InnerRight).ID: return 9238; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SmoothRedSandstoneStairs::Half::Top, SmoothRedSandstoneStairs::Shape::OuterLeft).ID: return 9240; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SmoothRedSandstoneStairs::Half::Top, SmoothRedSandstoneStairs::Shape::OuterRight).ID: return 9242; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SmoothRedSandstoneStairs::Half::Bottom, SmoothRedSandstoneStairs::Shape::Straight).ID: return 9244; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SmoothRedSandstoneStairs::Half::Bottom, SmoothRedSandstoneStairs::Shape::InnerLeft).ID: return 9246; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SmoothRedSandstoneStairs::Half::Bottom, SmoothRedSandstoneStairs::Shape::InnerRight).ID: return 9248; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SmoothRedSandstoneStairs::Half::Bottom, SmoothRedSandstoneStairs::Shape::OuterLeft).ID: return 9250; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SmoothRedSandstoneStairs::Half::Bottom, SmoothRedSandstoneStairs::Shape::OuterRight).ID: return 9252; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, SmoothRedSandstoneStairs::Half::Top, SmoothRedSandstoneStairs::Shape::Straight).ID: return 9254; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, SmoothRedSandstoneStairs::Half::Top, SmoothRedSandstoneStairs::Shape::InnerLeft).ID: return 9256; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, SmoothRedSandstoneStairs::Half::Top, SmoothRedSandstoneStairs::Shape::InnerRight).ID: return 9258; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, SmoothRedSandstoneStairs::Half::Top, SmoothRedSandstoneStairs::Shape::OuterLeft).ID: return 9260; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, SmoothRedSandstoneStairs::Half::Top, SmoothRedSandstoneStairs::Shape::OuterRight).ID: return 9262; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, SmoothRedSandstoneStairs::Half::Bottom, SmoothRedSandstoneStairs::Shape::Straight).ID: return 9264; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, SmoothRedSandstoneStairs::Half::Bottom, SmoothRedSandstoneStairs::Shape::InnerLeft).ID: return 9266; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, SmoothRedSandstoneStairs::Half::Bottom, SmoothRedSandstoneStairs::Shape::InnerRight).ID: return 9268; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, SmoothRedSandstoneStairs::Half::Bottom, SmoothRedSandstoneStairs::Shape::OuterLeft).ID: return 9270; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, SmoothRedSandstoneStairs::Half::Bottom, SmoothRedSandstoneStairs::Shape::OuterRight).ID: return 9272; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, SmoothRedSandstoneStairs::Half::Top, SmoothRedSandstoneStairs::Shape::Straight).ID: return 9274; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, SmoothRedSandstoneStairs::Half::Top, SmoothRedSandstoneStairs::Shape::InnerLeft).ID: return 9276; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, SmoothRedSandstoneStairs::Half::Top, SmoothRedSandstoneStairs::Shape::InnerRight).ID: return 9278; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, SmoothRedSandstoneStairs::Half::Top, SmoothRedSandstoneStairs::Shape::OuterLeft).ID: return 9280; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, SmoothRedSandstoneStairs::Half::Top, SmoothRedSandstoneStairs::Shape::OuterRight).ID: return 9282; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, SmoothRedSandstoneStairs::Half::Bottom, SmoothRedSandstoneStairs::Shape::Straight).ID: return 9284; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, SmoothRedSandstoneStairs::Half::Bottom, SmoothRedSandstoneStairs::Shape::InnerLeft).ID: return 9286; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, SmoothRedSandstoneStairs::Half::Bottom, SmoothRedSandstoneStairs::Shape::InnerRight).ID: return 9288; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, SmoothRedSandstoneStairs::Half::Bottom, SmoothRedSandstoneStairs::Shape::OuterLeft).ID: return 9290; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, SmoothRedSandstoneStairs::Half::Bottom, SmoothRedSandstoneStairs::Shape::OuterRight).ID: return 9292; case SmoothSandstone::SmoothSandstone().ID: return 7879; case SmoothSandstoneSlab::SmoothSandstoneSlab(SmoothSandstoneSlab::Type::Top).ID: return 10290; case SmoothSandstoneSlab::SmoothSandstoneSlab(SmoothSandstoneSlab::Type::Bottom).ID: return 10292; case SmoothSandstoneSlab::SmoothSandstoneSlab(SmoothSandstoneSlab::Type::Double).ID: return 10294; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SmoothSandstoneStairs::Half::Top, SmoothSandstoneStairs::Shape::Straight).ID: return 9694; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SmoothSandstoneStairs::Half::Top, SmoothSandstoneStairs::Shape::InnerLeft).ID: return 9696; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SmoothSandstoneStairs::Half::Top, SmoothSandstoneStairs::Shape::InnerRight).ID: return 9698; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SmoothSandstoneStairs::Half::Top, SmoothSandstoneStairs::Shape::OuterLeft).ID: return 9700; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SmoothSandstoneStairs::Half::Top, SmoothSandstoneStairs::Shape::OuterRight).ID: return 9702; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SmoothSandstoneStairs::Half::Bottom, SmoothSandstoneStairs::Shape::Straight).ID: return 9704; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SmoothSandstoneStairs::Half::Bottom, SmoothSandstoneStairs::Shape::InnerLeft).ID: return 9706; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SmoothSandstoneStairs::Half::Bottom, SmoothSandstoneStairs::Shape::InnerRight).ID: return 9708; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SmoothSandstoneStairs::Half::Bottom, SmoothSandstoneStairs::Shape::OuterLeft).ID: return 9710; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SmoothSandstoneStairs::Half::Bottom, SmoothSandstoneStairs::Shape::OuterRight).ID: return 9712; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SmoothSandstoneStairs::Half::Top, SmoothSandstoneStairs::Shape::Straight).ID: return 9714; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SmoothSandstoneStairs::Half::Top, SmoothSandstoneStairs::Shape::InnerLeft).ID: return 9716; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SmoothSandstoneStairs::Half::Top, SmoothSandstoneStairs::Shape::InnerRight).ID: return 9718; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SmoothSandstoneStairs::Half::Top, SmoothSandstoneStairs::Shape::OuterLeft).ID: return 9720; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SmoothSandstoneStairs::Half::Top, SmoothSandstoneStairs::Shape::OuterRight).ID: return 9722; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SmoothSandstoneStairs::Half::Bottom, SmoothSandstoneStairs::Shape::Straight).ID: return 9724; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SmoothSandstoneStairs::Half::Bottom, SmoothSandstoneStairs::Shape::InnerLeft).ID: return 9726; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SmoothSandstoneStairs::Half::Bottom, SmoothSandstoneStairs::Shape::InnerRight).ID: return 9728; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SmoothSandstoneStairs::Half::Bottom, SmoothSandstoneStairs::Shape::OuterLeft).ID: return 9730; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SmoothSandstoneStairs::Half::Bottom, SmoothSandstoneStairs::Shape::OuterRight).ID: return 9732; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_XM, SmoothSandstoneStairs::Half::Top, SmoothSandstoneStairs::Shape::Straight).ID: return 9734; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_XM, SmoothSandstoneStairs::Half::Top, SmoothSandstoneStairs::Shape::InnerLeft).ID: return 9736; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_XM, SmoothSandstoneStairs::Half::Top, SmoothSandstoneStairs::Shape::InnerRight).ID: return 9738; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_XM, SmoothSandstoneStairs::Half::Top, SmoothSandstoneStairs::Shape::OuterLeft).ID: return 9740; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_XM, SmoothSandstoneStairs::Half::Top, SmoothSandstoneStairs::Shape::OuterRight).ID: return 9742; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_XM, SmoothSandstoneStairs::Half::Bottom, SmoothSandstoneStairs::Shape::Straight).ID: return 9744; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_XM, SmoothSandstoneStairs::Half::Bottom, SmoothSandstoneStairs::Shape::InnerLeft).ID: return 9746; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_XM, SmoothSandstoneStairs::Half::Bottom, SmoothSandstoneStairs::Shape::InnerRight).ID: return 9748; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_XM, SmoothSandstoneStairs::Half::Bottom, SmoothSandstoneStairs::Shape::OuterLeft).ID: return 9750; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_XM, SmoothSandstoneStairs::Half::Bottom, SmoothSandstoneStairs::Shape::OuterRight).ID: return 9752; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_XP, SmoothSandstoneStairs::Half::Top, SmoothSandstoneStairs::Shape::Straight).ID: return 9754; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_XP, SmoothSandstoneStairs::Half::Top, SmoothSandstoneStairs::Shape::InnerLeft).ID: return 9756; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_XP, SmoothSandstoneStairs::Half::Top, SmoothSandstoneStairs::Shape::InnerRight).ID: return 9758; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_XP, SmoothSandstoneStairs::Half::Top, SmoothSandstoneStairs::Shape::OuterLeft).ID: return 9760; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_XP, SmoothSandstoneStairs::Half::Top, SmoothSandstoneStairs::Shape::OuterRight).ID: return 9762; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_XP, SmoothSandstoneStairs::Half::Bottom, SmoothSandstoneStairs::Shape::Straight).ID: return 9764; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_XP, SmoothSandstoneStairs::Half::Bottom, SmoothSandstoneStairs::Shape::InnerLeft).ID: return 9766; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_XP, SmoothSandstoneStairs::Half::Bottom, SmoothSandstoneStairs::Shape::InnerRight).ID: return 9768; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_XP, SmoothSandstoneStairs::Half::Bottom, SmoothSandstoneStairs::Shape::OuterLeft).ID: return 9770; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_XP, SmoothSandstoneStairs::Half::Bottom, SmoothSandstoneStairs::Shape::OuterRight).ID: return 9772; case SmoothStone::SmoothStone().ID: return 7878; case SmoothStoneSlab::SmoothStoneSlab(SmoothStoneSlab::Type::Top).ID: return 7807; case SmoothStoneSlab::SmoothStoneSlab(SmoothStoneSlab::Type::Bottom).ID: return 7809; case SmoothStoneSlab::SmoothStoneSlab(SmoothStoneSlab::Type::Double).ID: return 7811; case Snow::Snow(1).ID: return 3919; case Snow::Snow(2).ID: return 3920; case Snow::Snow(3).ID: return 3921; case Snow::Snow(4).ID: return 3922; case Snow::Snow(5).ID: return 3923; case Snow::Snow(6).ID: return 3924; case Snow::Snow(7).ID: return 3925; case Snow::Snow(8).ID: return 3926; case SnowBlock::SnowBlock().ID: return 3928; case SoulSand::SoulSand().ID: return 3998; case Spawner::Spawner().ID: return 1951; case Sponge::Sponge().ID: return 228; case SpruceButton::SpruceButton(SpruceButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5834; case SpruceButton::SpruceButton(SpruceButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5835; case SpruceButton::SpruceButton(SpruceButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5836; case SpruceButton::SpruceButton(SpruceButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5837; case SpruceButton::SpruceButton(SpruceButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, true).ID: return 5838; case SpruceButton::SpruceButton(SpruceButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, false).ID: return 5839; case SpruceButton::SpruceButton(SpruceButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, true).ID: return 5840; case SpruceButton::SpruceButton(SpruceButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, false).ID: return 5841; case SpruceButton::SpruceButton(SpruceButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5842; case SpruceButton::SpruceButton(SpruceButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5843; case SpruceButton::SpruceButton(SpruceButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5844; case SpruceButton::SpruceButton(SpruceButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5845; case SpruceButton::SpruceButton(SpruceButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, true).ID: return 5846; case SpruceButton::SpruceButton(SpruceButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, false).ID: return 5847; case SpruceButton::SpruceButton(SpruceButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, true).ID: return 5848; case SpruceButton::SpruceButton(SpruceButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, false).ID: return 5849; case SpruceButton::SpruceButton(SpruceButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5850; case SpruceButton::SpruceButton(SpruceButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5851; case SpruceButton::SpruceButton(SpruceButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5852; case SpruceButton::SpruceButton(SpruceButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5853; case SpruceButton::SpruceButton(SpruceButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, true).ID: return 5854; case SpruceButton::SpruceButton(SpruceButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, false).ID: return 5855; case SpruceButton::SpruceButton(SpruceButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, true).ID: return 5856; case SpruceButton::SpruceButton(SpruceButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, false).ID: return 5857; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, true, true).ID: return 8202; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, true, false).ID: return 8203; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, false, true).ID: return 8204; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, false, false).ID: return 8205; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, true, true).ID: return 8206; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, true, false).ID: return 8207; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, false, true).ID: return 8208; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, false, false).ID: return 8209; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, true, true).ID: return 8210; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, true, false).ID: return 8211; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, false, true).ID: return 8212; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, false, false).ID: return 8213; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, true, true).ID: return 8214; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, true, false).ID: return 8215; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, false, true).ID: return 8216; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, false, false).ID: return 8217; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, true, true).ID: return 8218; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, true, false).ID: return 8219; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, false, true).ID: return 8220; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, false, false).ID: return 8221; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, true, true).ID: return 8222; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, true, false).ID: return 8223; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, false, true).ID: return 8224; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, false, false).ID: return 8225; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, true, true).ID: return 8226; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, true, false).ID: return 8227; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, false, true).ID: return 8228; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, false, false).ID: return 8229; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, true, true).ID: return 8230; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, true, false).ID: return 8231; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, false, true).ID: return 8232; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, false, false).ID: return 8233; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, true, true).ID: return 8234; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, true, false).ID: return 8235; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, false, true).ID: return 8236; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, false, false).ID: return 8237; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, true, true).ID: return 8238; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, true, false).ID: return 8239; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, false, true).ID: return 8240; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, false, false).ID: return 8241; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, true, true).ID: return 8242; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, true, false).ID: return 8243; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, false, true).ID: return 8244; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, false, false).ID: return 8245; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, true, true).ID: return 8246; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, true, false).ID: return 8247; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, false, true).ID: return 8248; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, false, false).ID: return 8249; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, true, true).ID: return 8250; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, true, false).ID: return 8251; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, false, true).ID: return 8252; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, false, false).ID: return 8253; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, true, true).ID: return 8254; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, true, false).ID: return 8255; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, false, true).ID: return 8256; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, false, false).ID: return 8257; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, true, true).ID: return 8258; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, true, false).ID: return 8259; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, false, true).ID: return 8260; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, false, false).ID: return 8261; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, true, true).ID: return 8262; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, true, false).ID: return 8263; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, false, true).ID: return 8264; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, false, false).ID: return 8265; case SpruceFence::SpruceFence(true, true, true, true).ID: return 8044; case SpruceFence::SpruceFence(true, true, true, false).ID: return 8045; case SpruceFence::SpruceFence(true, true, false, true).ID: return 8048; case SpruceFence::SpruceFence(true, true, false, false).ID: return 8049; case SpruceFence::SpruceFence(true, false, true, true).ID: return 8052; case SpruceFence::SpruceFence(true, false, true, false).ID: return 8053; case SpruceFence::SpruceFence(true, false, false, true).ID: return 8056; case SpruceFence::SpruceFence(true, false, false, false).ID: return 8057; case SpruceFence::SpruceFence(false, true, true, true).ID: return 8060; case SpruceFence::SpruceFence(false, true, true, false).ID: return 8061; case SpruceFence::SpruceFence(false, true, false, true).ID: return 8064; case SpruceFence::SpruceFence(false, true, false, false).ID: return 8065; case SpruceFence::SpruceFence(false, false, true, true).ID: return 8068; case SpruceFence::SpruceFence(false, false, true, false).ID: return 8069; case SpruceFence::SpruceFence(false, false, false, true).ID: return 8072; case SpruceFence::SpruceFence(false, false, false, false).ID: return 8073; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZM, true, true, true).ID: return 7882; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZM, true, true, false).ID: return 7883; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZM, true, false, true).ID: return 7884; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZM, true, false, false).ID: return 7885; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, true).ID: return 7886; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, false).ID: return 7887; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, true).ID: return 7888; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, false).ID: return 7889; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZP, true, true, true).ID: return 7890; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZP, true, true, false).ID: return 7891; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZP, true, false, true).ID: return 7892; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZP, true, false, false).ID: return 7893; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, true).ID: return 7894; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, false).ID: return 7895; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, true).ID: return 7896; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, false).ID: return 7897; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XM, true, true, true).ID: return 7898; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XM, true, true, false).ID: return 7899; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XM, true, false, true).ID: return 7900; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XM, true, false, false).ID: return 7901; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, true).ID: return 7902; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, false).ID: return 7903; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, true).ID: return 7904; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, false).ID: return 7905; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XP, true, true, true).ID: return 7906; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XP, true, true, false).ID: return 7907; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XP, true, false, true).ID: return 7908; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XP, true, false, false).ID: return 7909; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, true).ID: return 7910; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, false).ID: return 7911; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, true).ID: return 7912; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, false).ID: return 7913; case SpruceLeaves::SpruceLeaves(1, true).ID: return 158; case SpruceLeaves::SpruceLeaves(1, false).ID: return 159; case SpruceLeaves::SpruceLeaves(2, true).ID: return 160; case SpruceLeaves::SpruceLeaves(2, false).ID: return 161; case SpruceLeaves::SpruceLeaves(3, true).ID: return 162; case SpruceLeaves::SpruceLeaves(3, false).ID: return 163; case SpruceLeaves::SpruceLeaves(4, true).ID: return 164; case SpruceLeaves::SpruceLeaves(4, false).ID: return 165; case SpruceLeaves::SpruceLeaves(5, true).ID: return 166; case SpruceLeaves::SpruceLeaves(5, false).ID: return 167; case SpruceLeaves::SpruceLeaves(6, true).ID: return 168; case SpruceLeaves::SpruceLeaves(6, false).ID: return 169; case SpruceLeaves::SpruceLeaves(7, true).ID: return 170; case SpruceLeaves::SpruceLeaves(7, false).ID: return 171; case SpruceLog::SpruceLog(SpruceLog::Axis::X).ID: return 75; case SpruceLog::SpruceLog(SpruceLog::Axis::Y).ID: return 76; case SpruceLog::SpruceLog(SpruceLog::Axis::Z).ID: return 77; case SprucePlanks::SprucePlanks().ID: return 16; case SprucePressurePlate::SprucePressurePlate(true).ID: return 3873; case SprucePressurePlate::SprucePressurePlate(false).ID: return 3874; case SpruceSapling::SpruceSapling(0).ID: return 23; case SpruceSapling::SpruceSapling(1).ID: return 24; case SpruceSign::SpruceSign(0).ID: return 3412; case SpruceSign::SpruceSign(1).ID: return 3414; case SpruceSign::SpruceSign(2).ID: return 3416; case SpruceSign::SpruceSign(3).ID: return 3418; case SpruceSign::SpruceSign(4).ID: return 3420; case SpruceSign::SpruceSign(5).ID: return 3422; case SpruceSign::SpruceSign(6).ID: return 3424; case SpruceSign::SpruceSign(7).ID: return 3426; case SpruceSign::SpruceSign(8).ID: return 3428; case SpruceSign::SpruceSign(9).ID: return 3430; case SpruceSign::SpruceSign(10).ID: return 3432; case SpruceSign::SpruceSign(11).ID: return 3434; case SpruceSign::SpruceSign(12).ID: return 3436; case SpruceSign::SpruceSign(13).ID: return 3438; case SpruceSign::SpruceSign(14).ID: return 3440; case SpruceSign::SpruceSign(15).ID: return 3442; case SpruceSlab::SpruceSlab(SpruceSlab::Type::Top).ID: return 7771; case SpruceSlab::SpruceSlab(SpruceSlab::Type::Bottom).ID: return 7773; case SpruceSlab::SpruceSlab(SpruceSlab::Type::Double).ID: return 7775; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZM, SpruceStairs::Half::Top, SpruceStairs::Shape::Straight).ID: return 5389; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZM, SpruceStairs::Half::Top, SpruceStairs::Shape::InnerLeft).ID: return 5391; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZM, SpruceStairs::Half::Top, SpruceStairs::Shape::InnerRight).ID: return 5393; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZM, SpruceStairs::Half::Top, SpruceStairs::Shape::OuterLeft).ID: return 5395; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZM, SpruceStairs::Half::Top, SpruceStairs::Shape::OuterRight).ID: return 5397; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZM, SpruceStairs::Half::Bottom, SpruceStairs::Shape::Straight).ID: return 5399; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZM, SpruceStairs::Half::Bottom, SpruceStairs::Shape::InnerLeft).ID: return 5401; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZM, SpruceStairs::Half::Bottom, SpruceStairs::Shape::InnerRight).ID: return 5403; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZM, SpruceStairs::Half::Bottom, SpruceStairs::Shape::OuterLeft).ID: return 5405; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZM, SpruceStairs::Half::Bottom, SpruceStairs::Shape::OuterRight).ID: return 5407; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZP, SpruceStairs::Half::Top, SpruceStairs::Shape::Straight).ID: return 5409; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZP, SpruceStairs::Half::Top, SpruceStairs::Shape::InnerLeft).ID: return 5411; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZP, SpruceStairs::Half::Top, SpruceStairs::Shape::InnerRight).ID: return 5413; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZP, SpruceStairs::Half::Top, SpruceStairs::Shape::OuterLeft).ID: return 5415; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZP, SpruceStairs::Half::Top, SpruceStairs::Shape::OuterRight).ID: return 5417; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZP, SpruceStairs::Half::Bottom, SpruceStairs::Shape::Straight).ID: return 5419; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZP, SpruceStairs::Half::Bottom, SpruceStairs::Shape::InnerLeft).ID: return 5421; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZP, SpruceStairs::Half::Bottom, SpruceStairs::Shape::InnerRight).ID: return 5423; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZP, SpruceStairs::Half::Bottom, SpruceStairs::Shape::OuterLeft).ID: return 5425; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZP, SpruceStairs::Half::Bottom, SpruceStairs::Shape::OuterRight).ID: return 5427; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XM, SpruceStairs::Half::Top, SpruceStairs::Shape::Straight).ID: return 5429; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XM, SpruceStairs::Half::Top, SpruceStairs::Shape::InnerLeft).ID: return 5431; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XM, SpruceStairs::Half::Top, SpruceStairs::Shape::InnerRight).ID: return 5433; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XM, SpruceStairs::Half::Top, SpruceStairs::Shape::OuterLeft).ID: return 5435; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XM, SpruceStairs::Half::Top, SpruceStairs::Shape::OuterRight).ID: return 5437; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XM, SpruceStairs::Half::Bottom, SpruceStairs::Shape::Straight).ID: return 5439; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XM, SpruceStairs::Half::Bottom, SpruceStairs::Shape::InnerLeft).ID: return 5441; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XM, SpruceStairs::Half::Bottom, SpruceStairs::Shape::InnerRight).ID: return 5443; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XM, SpruceStairs::Half::Bottom, SpruceStairs::Shape::OuterLeft).ID: return 5445; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XM, SpruceStairs::Half::Bottom, SpruceStairs::Shape::OuterRight).ID: return 5447; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XP, SpruceStairs::Half::Top, SpruceStairs::Shape::Straight).ID: return 5449; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XP, SpruceStairs::Half::Top, SpruceStairs::Shape::InnerLeft).ID: return 5451; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XP, SpruceStairs::Half::Top, SpruceStairs::Shape::InnerRight).ID: return 5453; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XP, SpruceStairs::Half::Top, SpruceStairs::Shape::OuterLeft).ID: return 5455; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XP, SpruceStairs::Half::Top, SpruceStairs::Shape::OuterRight).ID: return 5457; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XP, SpruceStairs::Half::Bottom, SpruceStairs::Shape::Straight).ID: return 5459; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XP, SpruceStairs::Half::Bottom, SpruceStairs::Shape::InnerLeft).ID: return 5461; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XP, SpruceStairs::Half::Bottom, SpruceStairs::Shape::InnerRight).ID: return 5463; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XP, SpruceStairs::Half::Bottom, SpruceStairs::Shape::OuterLeft).ID: return 5465; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XP, SpruceStairs::Half::Bottom, SpruceStairs::Shape::OuterRight).ID: return 5467; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZM, SpruceTrapdoor::Half::Top, true, true).ID: return 4162; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZM, SpruceTrapdoor::Half::Top, true, false).ID: return 4164; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZM, SpruceTrapdoor::Half::Top, false, true).ID: return 4166; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZM, SpruceTrapdoor::Half::Top, false, false).ID: return 4168; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZM, SpruceTrapdoor::Half::Bottom, true, true).ID: return 4170; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZM, SpruceTrapdoor::Half::Bottom, true, false).ID: return 4172; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZM, SpruceTrapdoor::Half::Bottom, false, true).ID: return 4174; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZM, SpruceTrapdoor::Half::Bottom, false, false).ID: return 4176; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZP, SpruceTrapdoor::Half::Top, true, true).ID: return 4178; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZP, SpruceTrapdoor::Half::Top, true, false).ID: return 4180; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZP, SpruceTrapdoor::Half::Top, false, true).ID: return 4182; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZP, SpruceTrapdoor::Half::Top, false, false).ID: return 4184; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZP, SpruceTrapdoor::Half::Bottom, true, true).ID: return 4186; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZP, SpruceTrapdoor::Half::Bottom, true, false).ID: return 4188; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZP, SpruceTrapdoor::Half::Bottom, false, true).ID: return 4190; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZP, SpruceTrapdoor::Half::Bottom, false, false).ID: return 4192; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XM, SpruceTrapdoor::Half::Top, true, true).ID: return 4194; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XM, SpruceTrapdoor::Half::Top, true, false).ID: return 4196; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XM, SpruceTrapdoor::Half::Top, false, true).ID: return 4198; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XM, SpruceTrapdoor::Half::Top, false, false).ID: return 4200; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XM, SpruceTrapdoor::Half::Bottom, true, true).ID: return 4202; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XM, SpruceTrapdoor::Half::Bottom, true, false).ID: return 4204; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XM, SpruceTrapdoor::Half::Bottom, false, true).ID: return 4206; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XM, SpruceTrapdoor::Half::Bottom, false, false).ID: return 4208; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XP, SpruceTrapdoor::Half::Top, true, true).ID: return 4210; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XP, SpruceTrapdoor::Half::Top, true, false).ID: return 4212; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XP, SpruceTrapdoor::Half::Top, false, true).ID: return 4214; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XP, SpruceTrapdoor::Half::Top, false, false).ID: return 4216; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XP, SpruceTrapdoor::Half::Bottom, true, true).ID: return 4218; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XP, SpruceTrapdoor::Half::Bottom, true, false).ID: return 4220; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XP, SpruceTrapdoor::Half::Bottom, false, true).ID: return 4222; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XP, SpruceTrapdoor::Half::Bottom, false, false).ID: return 4224; case SpruceWallSign::SpruceWallSign(eBlockFace::BLOCK_FACE_ZM).ID: return 3742; case SpruceWallSign::SpruceWallSign(eBlockFace::BLOCK_FACE_ZP).ID: return 3744; case SpruceWallSign::SpruceWallSign(eBlockFace::BLOCK_FACE_XM).ID: return 3746; case SpruceWallSign::SpruceWallSign(eBlockFace::BLOCK_FACE_XP).ID: return 3748; case SpruceWood::SpruceWood(SpruceWood::Axis::X).ID: return 111; case SpruceWood::SpruceWood(SpruceWood::Axis::Y).ID: return 112; case SpruceWood::SpruceWood(SpruceWood::Axis::Z).ID: return 113; case StickyPiston::StickyPiston(true, eBlockFace::BLOCK_FACE_ZM).ID: return 1328; case StickyPiston::StickyPiston(true, eBlockFace::BLOCK_FACE_XP).ID: return 1329; case StickyPiston::StickyPiston(true, eBlockFace::BLOCK_FACE_ZP).ID: return 1330; case StickyPiston::StickyPiston(true, eBlockFace::BLOCK_FACE_XM).ID: return 1331; case StickyPiston::StickyPiston(true, eBlockFace::BLOCK_FACE_YP).ID: return 1332; case StickyPiston::StickyPiston(true, eBlockFace::BLOCK_FACE_YM).ID: return 1333; case StickyPiston::StickyPiston(false, eBlockFace::BLOCK_FACE_ZM).ID: return 1334; case StickyPiston::StickyPiston(false, eBlockFace::BLOCK_FACE_XP).ID: return 1335; case StickyPiston::StickyPiston(false, eBlockFace::BLOCK_FACE_ZP).ID: return 1336; case StickyPiston::StickyPiston(false, eBlockFace::BLOCK_FACE_XM).ID: return 1337; case StickyPiston::StickyPiston(false, eBlockFace::BLOCK_FACE_YP).ID: return 1338; case StickyPiston::StickyPiston(false, eBlockFace::BLOCK_FACE_YM).ID: return 1339; case Stone::Stone().ID: return 1; case StoneBrickSlab::StoneBrickSlab(StoneBrickSlab::Type::Top).ID: return 7843; case StoneBrickSlab::StoneBrickSlab(StoneBrickSlab::Type::Bottom).ID: return 7845; case StoneBrickSlab::StoneBrickSlab(StoneBrickSlab::Type::Double).ID: return 7847; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::Straight).ID: return 4917; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::InnerLeft).ID: return 4919; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::InnerRight).ID: return 4921; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::OuterLeft).ID: return 4923; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::OuterRight).ID: return 4925; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::Straight).ID: return 4927; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::InnerLeft).ID: return 4929; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::InnerRight).ID: return 4931; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::OuterLeft).ID: return 4933; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::OuterRight).ID: return 4935; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::Straight).ID: return 4937; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::InnerLeft).ID: return 4939; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::InnerRight).ID: return 4941; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::OuterLeft).ID: return 4943; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::OuterRight).ID: return 4945; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::Straight).ID: return 4947; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::InnerLeft).ID: return 4949; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::InnerRight).ID: return 4951; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::OuterLeft).ID: return 4953; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::OuterRight).ID: return 4955; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XM, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::Straight).ID: return 4957; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XM, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::InnerLeft).ID: return 4959; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XM, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::InnerRight).ID: return 4961; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XM, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::OuterLeft).ID: return 4963; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XM, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::OuterRight).ID: return 4965; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XM, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::Straight).ID: return 4967; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XM, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::InnerLeft).ID: return 4969; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XM, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::InnerRight).ID: return 4971; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XM, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::OuterLeft).ID: return 4973; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XM, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::OuterRight).ID: return 4975; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XP, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::Straight).ID: return 4977; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XP, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::InnerLeft).ID: return 4979; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XP, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::InnerRight).ID: return 4981; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XP, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::OuterLeft).ID: return 4983; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XP, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::OuterRight).ID: return 4985; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XP, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::Straight).ID: return 4987; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XP, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::InnerLeft).ID: return 4989; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XP, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::InnerRight).ID: return 4991; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XP, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::OuterLeft).ID: return 4993; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XP, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::OuterRight).ID: return 4995; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::Low, StoneBrickWall::South::Low, true, StoneBrickWall::West::Low).ID: return 10653; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::Low, StoneBrickWall::South::Low, true, StoneBrickWall::West::None).ID: return 10654; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::Low, StoneBrickWall::South::Low, false, StoneBrickWall::West::Low).ID: return 10657; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::Low, StoneBrickWall::South::Low, false, StoneBrickWall::West::None).ID: return 10658; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::Low, StoneBrickWall::South::None, true, StoneBrickWall::West::Low).ID: return 10661; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::Low, StoneBrickWall::South::None, true, StoneBrickWall::West::None).ID: return 10662; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::Low, StoneBrickWall::South::None, false, StoneBrickWall::West::Low).ID: return 10665; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::Low, StoneBrickWall::South::None, false, StoneBrickWall::West::None).ID: return 10666; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::None, StoneBrickWall::South::Low, true, StoneBrickWall::West::Low).ID: return 10669; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::None, StoneBrickWall::South::Low, true, StoneBrickWall::West::None).ID: return 10670; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::None, StoneBrickWall::South::Low, false, StoneBrickWall::West::Low).ID: return 10673; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::None, StoneBrickWall::South::Low, false, StoneBrickWall::West::None).ID: return 10674; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::None, StoneBrickWall::South::None, true, StoneBrickWall::West::Low).ID: return 10677; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::None, StoneBrickWall::South::None, true, StoneBrickWall::West::None).ID: return 10678; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::None, StoneBrickWall::South::None, false, StoneBrickWall::West::Low).ID: return 10681; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::None, StoneBrickWall::South::None, false, StoneBrickWall::West::None).ID: return 10682; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::Low, StoneBrickWall::South::Low, true, StoneBrickWall::West::Low).ID: return 10685; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::Low, StoneBrickWall::South::Low, true, StoneBrickWall::West::None).ID: return 10686; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::Low, StoneBrickWall::South::Low, false, StoneBrickWall::West::Low).ID: return 10689; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::Low, StoneBrickWall::South::Low, false, StoneBrickWall::West::None).ID: return 10690; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::Low, StoneBrickWall::South::None, true, StoneBrickWall::West::Low).ID: return 10693; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::Low, StoneBrickWall::South::None, true, StoneBrickWall::West::None).ID: return 10694; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::Low, StoneBrickWall::South::None, false, StoneBrickWall::West::Low).ID: return 10697; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::Low, StoneBrickWall::South::None, false, StoneBrickWall::West::None).ID: return 10698; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::None, StoneBrickWall::South::Low, true, StoneBrickWall::West::Low).ID: return 10701; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::None, StoneBrickWall::South::Low, true, StoneBrickWall::West::None).ID: return 10702; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::None, StoneBrickWall::South::Low, false, StoneBrickWall::West::Low).ID: return 10705; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::None, StoneBrickWall::South::Low, false, StoneBrickWall::West::None).ID: return 10706; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::None, StoneBrickWall::South::None, true, StoneBrickWall::West::Low).ID: return 10709; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::None, StoneBrickWall::South::None, true, StoneBrickWall::West::None).ID: return 10710; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::None, StoneBrickWall::South::None, false, StoneBrickWall::West::Low).ID: return 10713; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::None, StoneBrickWall::South::None, false, StoneBrickWall::West::None).ID: return 10714; case StoneBricks::StoneBricks().ID: return 4481; case StoneButton::StoneButton(StoneButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, true).ID: return 3895; case StoneButton::StoneButton(StoneButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, false).ID: return 3896; case StoneButton::StoneButton(StoneButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, true).ID: return 3897; case StoneButton::StoneButton(StoneButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, false).ID: return 3898; case StoneButton::StoneButton(StoneButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, true).ID: return 3899; case StoneButton::StoneButton(StoneButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, false).ID: return 3900; case StoneButton::StoneButton(StoneButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, true).ID: return 3901; case StoneButton::StoneButton(StoneButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, false).ID: return 3902; case StoneButton::StoneButton(StoneButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, true).ID: return 3903; case StoneButton::StoneButton(StoneButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, false).ID: return 3904; case StoneButton::StoneButton(StoneButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, true).ID: return 3905; case StoneButton::StoneButton(StoneButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, false).ID: return 3906; case StoneButton::StoneButton(StoneButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, true).ID: return 3907; case StoneButton::StoneButton(StoneButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, false).ID: return 3908; case StoneButton::StoneButton(StoneButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, true).ID: return 3909; case StoneButton::StoneButton(StoneButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, false).ID: return 3910; case StoneButton::StoneButton(StoneButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, true).ID: return 3911; case StoneButton::StoneButton(StoneButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, false).ID: return 3912; case StoneButton::StoneButton(StoneButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, true).ID: return 3913; case StoneButton::StoneButton(StoneButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, false).ID: return 3914; case StoneButton::StoneButton(StoneButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, true).ID: return 3915; case StoneButton::StoneButton(StoneButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, false).ID: return 3916; case StoneButton::StoneButton(StoneButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, true).ID: return 3917; case StoneButton::StoneButton(StoneButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, false).ID: return 3918; case StonePressurePlate::StonePressurePlate(true).ID: return 3805; case StonePressurePlate::StonePressurePlate(false).ID: return 3806; case StoneSlab::StoneSlab(StoneSlab::Type::Top).ID: return 7801; case StoneSlab::StoneSlab(StoneSlab::Type::Bottom).ID: return 7803; case StoneSlab::StoneSlab(StoneSlab::Type::Double).ID: return 7805; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_ZM, StoneStairs::Half::Top, StoneStairs::Shape::Straight).ID: return 9614; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_ZM, StoneStairs::Half::Top, StoneStairs::Shape::InnerLeft).ID: return 9616; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_ZM, StoneStairs::Half::Top, StoneStairs::Shape::InnerRight).ID: return 9618; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_ZM, StoneStairs::Half::Top, StoneStairs::Shape::OuterLeft).ID: return 9620; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_ZM, StoneStairs::Half::Top, StoneStairs::Shape::OuterRight).ID: return 9622; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_ZM, StoneStairs::Half::Bottom, StoneStairs::Shape::Straight).ID: return 9624; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_ZM, StoneStairs::Half::Bottom, StoneStairs::Shape::InnerLeft).ID: return 9626; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_ZM, StoneStairs::Half::Bottom, StoneStairs::Shape::InnerRight).ID: return 9628; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_ZM, StoneStairs::Half::Bottom, StoneStairs::Shape::OuterLeft).ID: return 9630; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_ZM, StoneStairs::Half::Bottom, StoneStairs::Shape::OuterRight).ID: return 9632; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_ZP, StoneStairs::Half::Top, StoneStairs::Shape::Straight).ID: return 9634; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_ZP, StoneStairs::Half::Top, StoneStairs::Shape::InnerLeft).ID: return 9636; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_ZP, StoneStairs::Half::Top, StoneStairs::Shape::InnerRight).ID: return 9638; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_ZP, StoneStairs::Half::Top, StoneStairs::Shape::OuterLeft).ID: return 9640; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_ZP, StoneStairs::Half::Top, StoneStairs::Shape::OuterRight).ID: return 9642; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_ZP, StoneStairs::Half::Bottom, StoneStairs::Shape::Straight).ID: return 9644; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_ZP, StoneStairs::Half::Bottom, StoneStairs::Shape::InnerLeft).ID: return 9646; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_ZP, StoneStairs::Half::Bottom, StoneStairs::Shape::InnerRight).ID: return 9648; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_ZP, StoneStairs::Half::Bottom, StoneStairs::Shape::OuterLeft).ID: return 9650; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_ZP, StoneStairs::Half::Bottom, StoneStairs::Shape::OuterRight).ID: return 9652; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_XM, StoneStairs::Half::Top, StoneStairs::Shape::Straight).ID: return 9654; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_XM, StoneStairs::Half::Top, StoneStairs::Shape::InnerLeft).ID: return 9656; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_XM, StoneStairs::Half::Top, StoneStairs::Shape::InnerRight).ID: return 9658; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_XM, StoneStairs::Half::Top, StoneStairs::Shape::OuterLeft).ID: return 9660; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_XM, StoneStairs::Half::Top, StoneStairs::Shape::OuterRight).ID: return 9662; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_XM, StoneStairs::Half::Bottom, StoneStairs::Shape::Straight).ID: return 9664; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_XM, StoneStairs::Half::Bottom, StoneStairs::Shape::InnerLeft).ID: return 9666; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_XM, StoneStairs::Half::Bottom, StoneStairs::Shape::InnerRight).ID: return 9668; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_XM, StoneStairs::Half::Bottom, StoneStairs::Shape::OuterLeft).ID: return 9670; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_XM, StoneStairs::Half::Bottom, StoneStairs::Shape::OuterRight).ID: return 9672; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_XP, StoneStairs::Half::Top, StoneStairs::Shape::Straight).ID: return 9674; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_XP, StoneStairs::Half::Top, StoneStairs::Shape::InnerLeft).ID: return 9676; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_XP, StoneStairs::Half::Top, StoneStairs::Shape::InnerRight).ID: return 9678; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_XP, StoneStairs::Half::Top, StoneStairs::Shape::OuterLeft).ID: return 9680; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_XP, StoneStairs::Half::Top, StoneStairs::Shape::OuterRight).ID: return 9682; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_XP, StoneStairs::Half::Bottom, StoneStairs::Shape::Straight).ID: return 9684; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_XP, StoneStairs::Half::Bottom, StoneStairs::Shape::InnerLeft).ID: return 9686; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_XP, StoneStairs::Half::Bottom, StoneStairs::Shape::InnerRight).ID: return 9688; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_XP, StoneStairs::Half::Bottom, StoneStairs::Shape::OuterLeft).ID: return 9690; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_XP, StoneStairs::Half::Bottom, StoneStairs::Shape::OuterRight).ID: return 9692; case Stonecutter::Stonecutter(eBlockFace::BLOCK_FACE_ZM).ID: return 11194; case Stonecutter::Stonecutter(eBlockFace::BLOCK_FACE_ZP).ID: return 11195; case Stonecutter::Stonecutter(eBlockFace::BLOCK_FACE_XM).ID: return 11196; case Stonecutter::Stonecutter(eBlockFace::BLOCK_FACE_XP).ID: return 11197; case StrippedAcaciaLog::StrippedAcaciaLog(StrippedAcaciaLog::Axis::X).ID: return 99; case StrippedAcaciaLog::StrippedAcaciaLog(StrippedAcaciaLog::Axis::Y).ID: return 100; case StrippedAcaciaLog::StrippedAcaciaLog(StrippedAcaciaLog::Axis::Z).ID: return 101; case StrippedAcaciaWood::StrippedAcaciaWood(StrippedAcaciaWood::Axis::X).ID: return 138; case StrippedAcaciaWood::StrippedAcaciaWood(StrippedAcaciaWood::Axis::Y).ID: return 139; case StrippedAcaciaWood::StrippedAcaciaWood(StrippedAcaciaWood::Axis::Z).ID: return 140; case StrippedBirchLog::StrippedBirchLog(StrippedBirchLog::Axis::X).ID: return 93; case StrippedBirchLog::StrippedBirchLog(StrippedBirchLog::Axis::Y).ID: return 94; case StrippedBirchLog::StrippedBirchLog(StrippedBirchLog::Axis::Z).ID: return 95; case StrippedBirchWood::StrippedBirchWood(StrippedBirchWood::Axis::X).ID: return 132; case StrippedBirchWood::StrippedBirchWood(StrippedBirchWood::Axis::Y).ID: return 133; case StrippedBirchWood::StrippedBirchWood(StrippedBirchWood::Axis::Z).ID: return 134; case StrippedDarkOakLog::StrippedDarkOakLog(StrippedDarkOakLog::Axis::X).ID: return 102; case StrippedDarkOakLog::StrippedDarkOakLog(StrippedDarkOakLog::Axis::Y).ID: return 103; case StrippedDarkOakLog::StrippedDarkOakLog(StrippedDarkOakLog::Axis::Z).ID: return 104; case StrippedDarkOakWood::StrippedDarkOakWood(StrippedDarkOakWood::Axis::X).ID: return 141; case StrippedDarkOakWood::StrippedDarkOakWood(StrippedDarkOakWood::Axis::Y).ID: return 142; case StrippedDarkOakWood::StrippedDarkOakWood(StrippedDarkOakWood::Axis::Z).ID: return 143; case StrippedJungleLog::StrippedJungleLog(StrippedJungleLog::Axis::X).ID: return 96; case StrippedJungleLog::StrippedJungleLog(StrippedJungleLog::Axis::Y).ID: return 97; case StrippedJungleLog::StrippedJungleLog(StrippedJungleLog::Axis::Z).ID: return 98; case StrippedJungleWood::StrippedJungleWood(StrippedJungleWood::Axis::X).ID: return 135; case StrippedJungleWood::StrippedJungleWood(StrippedJungleWood::Axis::Y).ID: return 136; case StrippedJungleWood::StrippedJungleWood(StrippedJungleWood::Axis::Z).ID: return 137; case StrippedOakLog::StrippedOakLog(StrippedOakLog::Axis::X).ID: return 105; case StrippedOakLog::StrippedOakLog(StrippedOakLog::Axis::Y).ID: return 106; case StrippedOakLog::StrippedOakLog(StrippedOakLog::Axis::Z).ID: return 107; case StrippedOakWood::StrippedOakWood(StrippedOakWood::Axis::X).ID: return 126; case StrippedOakWood::StrippedOakWood(StrippedOakWood::Axis::Y).ID: return 127; case StrippedOakWood::StrippedOakWood(StrippedOakWood::Axis::Z).ID: return 128; case StrippedSpruceLog::StrippedSpruceLog(StrippedSpruceLog::Axis::X).ID: return 90; case StrippedSpruceLog::StrippedSpruceLog(StrippedSpruceLog::Axis::Y).ID: return 91; case StrippedSpruceLog::StrippedSpruceLog(StrippedSpruceLog::Axis::Z).ID: return 92; case StrippedSpruceWood::StrippedSpruceWood(StrippedSpruceWood::Axis::X).ID: return 129; case StrippedSpruceWood::StrippedSpruceWood(StrippedSpruceWood::Axis::Y).ID: return 130; case StrippedSpruceWood::StrippedSpruceWood(StrippedSpruceWood::Axis::Z).ID: return 131; case StructureBlock::StructureBlock(StructureBlock::Mode::Save).ID: return 11252; case StructureBlock::StructureBlock(StructureBlock::Mode::Load).ID: return 11253; case StructureBlock::StructureBlock(StructureBlock::Mode::Corner).ID: return 11254; case StructureBlock::StructureBlock(StructureBlock::Mode::Data).ID: return 11255; case StructureVoid::StructureVoid().ID: return 8723; case SugarCane::SugarCane(0).ID: return 3946; case SugarCane::SugarCane(1).ID: return 3947; case SugarCane::SugarCane(2).ID: return 3948; case SugarCane::SugarCane(3).ID: return 3949; case SugarCane::SugarCane(4).ID: return 3950; case SugarCane::SugarCane(5).ID: return 3951; case SugarCane::SugarCane(6).ID: return 3952; case SugarCane::SugarCane(7).ID: return 3953; case SugarCane::SugarCane(8).ID: return 3954; case SugarCane::SugarCane(9).ID: return 3955; case SugarCane::SugarCane(10).ID: return 3956; case SugarCane::SugarCane(11).ID: return 3957; case SugarCane::SugarCane(12).ID: return 3958; case SugarCane::SugarCane(13).ID: return 3959; case SugarCane::SugarCane(14).ID: return 3960; case SugarCane::SugarCane(15).ID: return 3961; case Sunflower::Sunflower(Sunflower::Half::Upper).ID: return 7349; case Sunflower::Sunflower(Sunflower::Half::Lower).ID: return 7350; case SweetBerryBush::SweetBerryBush(0).ID: return 11248; case SweetBerryBush::SweetBerryBush(1).ID: return 11249; case SweetBerryBush::SweetBerryBush(2).ID: return 11250; case SweetBerryBush::SweetBerryBush(3).ID: return 11251; case TNT::TNT(true).ID: return 1429; case TNT::TNT(false).ID: return 1430; case TallGrass::TallGrass(TallGrass::Half::Upper).ID: return 7357; case TallGrass::TallGrass(TallGrass::Half::Lower).ID: return 7358; case TallSeagrass::TallSeagrass(TallSeagrass::Half::Upper).ID: return 1345; case TallSeagrass::TallSeagrass(TallSeagrass::Half::Lower).ID: return 1346; case Terracotta::Terracotta().ID: return 7346; case Torch::Torch().ID: return 1434; case TrappedChest::TrappedChest(eBlockFace::BLOCK_FACE_ZM, TrappedChest::Type::Single).ID: return 6087; case TrappedChest::TrappedChest(eBlockFace::BLOCK_FACE_ZM, TrappedChest::Type::Left).ID: return 6089; case TrappedChest::TrappedChest(eBlockFace::BLOCK_FACE_ZM, TrappedChest::Type::Right).ID: return 6091; case TrappedChest::TrappedChest(eBlockFace::BLOCK_FACE_ZP, TrappedChest::Type::Single).ID: return 6093; case TrappedChest::TrappedChest(eBlockFace::BLOCK_FACE_ZP, TrappedChest::Type::Left).ID: return 6095; case TrappedChest::TrappedChest(eBlockFace::BLOCK_FACE_ZP, TrappedChest::Type::Right).ID: return 6097; case TrappedChest::TrappedChest(eBlockFace::BLOCK_FACE_XM, TrappedChest::Type::Single).ID: return 6099; case TrappedChest::TrappedChest(eBlockFace::BLOCK_FACE_XM, TrappedChest::Type::Left).ID: return 6101; case TrappedChest::TrappedChest(eBlockFace::BLOCK_FACE_XM, TrappedChest::Type::Right).ID: return 6103; case TrappedChest::TrappedChest(eBlockFace::BLOCK_FACE_XP, TrappedChest::Type::Single).ID: return 6105; case TrappedChest::TrappedChest(eBlockFace::BLOCK_FACE_XP, TrappedChest::Type::Left).ID: return 6107; case TrappedChest::TrappedChest(eBlockFace::BLOCK_FACE_XP, TrappedChest::Type::Right).ID: return 6109; case Tripwire::Tripwire(true, true, true, true, true, true, true).ID: return 5259; case Tripwire::Tripwire(true, true, true, true, true, true, false).ID: return 5260; case Tripwire::Tripwire(true, true, true, true, true, false, true).ID: return 5261; case Tripwire::Tripwire(true, true, true, true, true, false, false).ID: return 5262; case Tripwire::Tripwire(true, true, true, true, false, true, true).ID: return 5263; case Tripwire::Tripwire(true, true, true, true, false, true, false).ID: return 5264; case Tripwire::Tripwire(true, true, true, true, false, false, true).ID: return 5265; case Tripwire::Tripwire(true, true, true, true, false, false, false).ID: return 5266; case Tripwire::Tripwire(true, true, true, false, true, true, true).ID: return 5267; case Tripwire::Tripwire(true, true, true, false, true, true, false).ID: return 5268; case Tripwire::Tripwire(true, true, true, false, true, false, true).ID: return 5269; case Tripwire::Tripwire(true, true, true, false, true, false, false).ID: return 5270; case Tripwire::Tripwire(true, true, true, false, false, true, true).ID: return 5271; case Tripwire::Tripwire(true, true, true, false, false, true, false).ID: return 5272; case Tripwire::Tripwire(true, true, true, false, false, false, true).ID: return 5273; case Tripwire::Tripwire(true, true, true, false, false, false, false).ID: return 5274; case Tripwire::Tripwire(true, true, false, true, true, true, true).ID: return 5275; case Tripwire::Tripwire(true, true, false, true, true, true, false).ID: return 5276; case Tripwire::Tripwire(true, true, false, true, true, false, true).ID: return 5277; case Tripwire::Tripwire(true, true, false, true, true, false, false).ID: return 5278; case Tripwire::Tripwire(true, true, false, true, false, true, true).ID: return 5279; case Tripwire::Tripwire(true, true, false, true, false, true, false).ID: return 5280; case Tripwire::Tripwire(true, true, false, true, false, false, true).ID: return 5281; case Tripwire::Tripwire(true, true, false, true, false, false, false).ID: return 5282; case Tripwire::Tripwire(true, true, false, false, true, true, true).ID: return 5283; case Tripwire::Tripwire(true, true, false, false, true, true, false).ID: return 5284; case Tripwire::Tripwire(true, true, false, false, true, false, true).ID: return 5285; case Tripwire::Tripwire(true, true, false, false, true, false, false).ID: return 5286; case Tripwire::Tripwire(true, true, false, false, false, true, true).ID: return 5287; case Tripwire::Tripwire(true, true, false, false, false, true, false).ID: return 5288; case Tripwire::Tripwire(true, true, false, false, false, false, true).ID: return 5289; case Tripwire::Tripwire(true, true, false, false, false, false, false).ID: return 5290; case Tripwire::Tripwire(true, false, true, true, true, true, true).ID: return 5291; case Tripwire::Tripwire(true, false, true, true, true, true, false).ID: return 5292; case Tripwire::Tripwire(true, false, true, true, true, false, true).ID: return 5293; case Tripwire::Tripwire(true, false, true, true, true, false, false).ID: return 5294; case Tripwire::Tripwire(true, false, true, true, false, true, true).ID: return 5295; case Tripwire::Tripwire(true, false, true, true, false, true, false).ID: return 5296; case Tripwire::Tripwire(true, false, true, true, false, false, true).ID: return 5297; case Tripwire::Tripwire(true, false, true, true, false, false, false).ID: return 5298; case Tripwire::Tripwire(true, false, true, false, true, true, true).ID: return 5299; case Tripwire::Tripwire(true, false, true, false, true, true, false).ID: return 5300; case Tripwire::Tripwire(true, false, true, false, true, false, true).ID: return 5301; case Tripwire::Tripwire(true, false, true, false, true, false, false).ID: return 5302; case Tripwire::Tripwire(true, false, true, false, false, true, true).ID: return 5303; case Tripwire::Tripwire(true, false, true, false, false, true, false).ID: return 5304; case Tripwire::Tripwire(true, false, true, false, false, false, true).ID: return 5305; case Tripwire::Tripwire(true, false, true, false, false, false, false).ID: return 5306; case Tripwire::Tripwire(true, false, false, true, true, true, true).ID: return 5307; case Tripwire::Tripwire(true, false, false, true, true, true, false).ID: return 5308; case Tripwire::Tripwire(true, false, false, true, true, false, true).ID: return 5309; case Tripwire::Tripwire(true, false, false, true, true, false, false).ID: return 5310; case Tripwire::Tripwire(true, false, false, true, false, true, true).ID: return 5311; case Tripwire::Tripwire(true, false, false, true, false, true, false).ID: return 5312; case Tripwire::Tripwire(true, false, false, true, false, false, true).ID: return 5313; case Tripwire::Tripwire(true, false, false, true, false, false, false).ID: return 5314; case Tripwire::Tripwire(true, false, false, false, true, true, true).ID: return 5315; case Tripwire::Tripwire(true, false, false, false, true, true, false).ID: return 5316; case Tripwire::Tripwire(true, false, false, false, true, false, true).ID: return 5317; case Tripwire::Tripwire(true, false, false, false, true, false, false).ID: return 5318; case Tripwire::Tripwire(true, false, false, false, false, true, true).ID: return 5319; case Tripwire::Tripwire(true, false, false, false, false, true, false).ID: return 5320; case Tripwire::Tripwire(true, false, false, false, false, false, true).ID: return 5321; case Tripwire::Tripwire(true, false, false, false, false, false, false).ID: return 5322; case Tripwire::Tripwire(false, true, true, true, true, true, true).ID: return 5323; case Tripwire::Tripwire(false, true, true, true, true, true, false).ID: return 5324; case Tripwire::Tripwire(false, true, true, true, true, false, true).ID: return 5325; case Tripwire::Tripwire(false, true, true, true, true, false, false).ID: return 5326; case Tripwire::Tripwire(false, true, true, true, false, true, true).ID: return 5327; case Tripwire::Tripwire(false, true, true, true, false, true, false).ID: return 5328; case Tripwire::Tripwire(false, true, true, true, false, false, true).ID: return 5329; case Tripwire::Tripwire(false, true, true, true, false, false, false).ID: return 5330; case Tripwire::Tripwire(false, true, true, false, true, true, true).ID: return 5331; case Tripwire::Tripwire(false, true, true, false, true, true, false).ID: return 5332; case Tripwire::Tripwire(false, true, true, false, true, false, true).ID: return 5333; case Tripwire::Tripwire(false, true, true, false, true, false, false).ID: return 5334; case Tripwire::Tripwire(false, true, true, false, false, true, true).ID: return 5335; case Tripwire::Tripwire(false, true, true, false, false, true, false).ID: return 5336; case Tripwire::Tripwire(false, true, true, false, false, false, true).ID: return 5337; case Tripwire::Tripwire(false, true, true, false, false, false, false).ID: return 5338; case Tripwire::Tripwire(false, true, false, true, true, true, true).ID: return 5339; case Tripwire::Tripwire(false, true, false, true, true, true, false).ID: return 5340; case Tripwire::Tripwire(false, true, false, true, true, false, true).ID: return 5341; case Tripwire::Tripwire(false, true, false, true, true, false, false).ID: return 5342; case Tripwire::Tripwire(false, true, false, true, false, true, true).ID: return 5343; case Tripwire::Tripwire(false, true, false, true, false, true, false).ID: return 5344; case Tripwire::Tripwire(false, true, false, true, false, false, true).ID: return 5345; case Tripwire::Tripwire(false, true, false, true, false, false, false).ID: return 5346; case Tripwire::Tripwire(false, true, false, false, true, true, true).ID: return 5347; case Tripwire::Tripwire(false, true, false, false, true, true, false).ID: return 5348; case Tripwire::Tripwire(false, true, false, false, true, false, true).ID: return 5349; case Tripwire::Tripwire(false, true, false, false, true, false, false).ID: return 5350; case Tripwire::Tripwire(false, true, false, false, false, true, true).ID: return 5351; case Tripwire::Tripwire(false, true, false, false, false, true, false).ID: return 5352; case Tripwire::Tripwire(false, true, false, false, false, false, true).ID: return 5353; case Tripwire::Tripwire(false, true, false, false, false, false, false).ID: return 5354; case Tripwire::Tripwire(false, false, true, true, true, true, true).ID: return 5355; case Tripwire::Tripwire(false, false, true, true, true, true, false).ID: return 5356; case Tripwire::Tripwire(false, false, true, true, true, false, true).ID: return 5357; case Tripwire::Tripwire(false, false, true, true, true, false, false).ID: return 5358; case Tripwire::Tripwire(false, false, true, true, false, true, true).ID: return 5359; case Tripwire::Tripwire(false, false, true, true, false, true, false).ID: return 5360; case Tripwire::Tripwire(false, false, true, true, false, false, true).ID: return 5361; case Tripwire::Tripwire(false, false, true, true, false, false, false).ID: return 5362; case Tripwire::Tripwire(false, false, true, false, true, true, true).ID: return 5363; case Tripwire::Tripwire(false, false, true, false, true, true, false).ID: return 5364; case Tripwire::Tripwire(false, false, true, false, true, false, true).ID: return 5365; case Tripwire::Tripwire(false, false, true, false, true, false, false).ID: return 5366; case Tripwire::Tripwire(false, false, true, false, false, true, true).ID: return 5367; case Tripwire::Tripwire(false, false, true, false, false, true, false).ID: return 5368; case Tripwire::Tripwire(false, false, true, false, false, false, true).ID: return 5369; case Tripwire::Tripwire(false, false, true, false, false, false, false).ID: return 5370; case Tripwire::Tripwire(false, false, false, true, true, true, true).ID: return 5371; case Tripwire::Tripwire(false, false, false, true, true, true, false).ID: return 5372; case Tripwire::Tripwire(false, false, false, true, true, false, true).ID: return 5373; case Tripwire::Tripwire(false, false, false, true, true, false, false).ID: return 5374; case Tripwire::Tripwire(false, false, false, true, false, true, true).ID: return 5375; case Tripwire::Tripwire(false, false, false, true, false, true, false).ID: return 5376; case Tripwire::Tripwire(false, false, false, true, false, false, true).ID: return 5377; case Tripwire::Tripwire(false, false, false, true, false, false, false).ID: return 5378; case Tripwire::Tripwire(false, false, false, false, true, true, true).ID: return 5379; case Tripwire::Tripwire(false, false, false, false, true, true, false).ID: return 5380; case Tripwire::Tripwire(false, false, false, false, true, false, true).ID: return 5381; case Tripwire::Tripwire(false, false, false, false, true, false, false).ID: return 5382; case Tripwire::Tripwire(false, false, false, false, false, true, true).ID: return 5383; case Tripwire::Tripwire(false, false, false, false, false, true, false).ID: return 5384; case Tripwire::Tripwire(false, false, false, false, false, false, true).ID: return 5385; case Tripwire::Tripwire(false, false, false, false, false, false, false).ID: return 5386; case TripwireHook::TripwireHook(true, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5243; case TripwireHook::TripwireHook(true, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5244; case TripwireHook::TripwireHook(true, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5245; case TripwireHook::TripwireHook(true, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5246; case TripwireHook::TripwireHook(true, eBlockFace::BLOCK_FACE_XM, true).ID: return 5247; case TripwireHook::TripwireHook(true, eBlockFace::BLOCK_FACE_XM, false).ID: return 5248; case TripwireHook::TripwireHook(true, eBlockFace::BLOCK_FACE_XP, true).ID: return 5249; case TripwireHook::TripwireHook(true, eBlockFace::BLOCK_FACE_XP, false).ID: return 5250; case TripwireHook::TripwireHook(false, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5251; case TripwireHook::TripwireHook(false, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5252; case TripwireHook::TripwireHook(false, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5253; case TripwireHook::TripwireHook(false, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5254; case TripwireHook::TripwireHook(false, eBlockFace::BLOCK_FACE_XM, true).ID: return 5255; case TripwireHook::TripwireHook(false, eBlockFace::BLOCK_FACE_XM, false).ID: return 5256; case TripwireHook::TripwireHook(false, eBlockFace::BLOCK_FACE_XP, true).ID: return 5257; case TripwireHook::TripwireHook(false, eBlockFace::BLOCK_FACE_XP, false).ID: return 5258; case TubeCoral::TubeCoral().ID: return 8995; case TubeCoralBlock::TubeCoralBlock().ID: return 8979; case TubeCoralFan::TubeCoralFan().ID: return 9015; case TubeCoralWallFan::TubeCoralWallFan(eBlockFace::BLOCK_FACE_ZM).ID: return 9065; case TubeCoralWallFan::TubeCoralWallFan(eBlockFace::BLOCK_FACE_ZP).ID: return 9067; case TubeCoralWallFan::TubeCoralWallFan(eBlockFace::BLOCK_FACE_XM).ID: return 9069; case TubeCoralWallFan::TubeCoralWallFan(eBlockFace::BLOCK_FACE_XP).ID: return 9071; case TurtleEgg::TurtleEgg(1, 0).ID: return 8962; case TurtleEgg::TurtleEgg(1, 1).ID: return 8963; case TurtleEgg::TurtleEgg(1, 2).ID: return 8964; case TurtleEgg::TurtleEgg(2, 0).ID: return 8965; case TurtleEgg::TurtleEgg(2, 1).ID: return 8966; case TurtleEgg::TurtleEgg(2, 2).ID: return 8967; case TurtleEgg::TurtleEgg(3, 0).ID: return 8968; case TurtleEgg::TurtleEgg(3, 1).ID: return 8969; case TurtleEgg::TurtleEgg(3, 2).ID: return 8970; case TurtleEgg::TurtleEgg(4, 0).ID: return 8971; case TurtleEgg::TurtleEgg(4, 1).ID: return 8972; case TurtleEgg::TurtleEgg(4, 2).ID: return 8973; case Vine::Vine(true, true, true, true, true).ID: return 4772; case Vine::Vine(true, true, true, true, false).ID: return 4773; case Vine::Vine(true, true, true, false, true).ID: return 4774; case Vine::Vine(true, true, true, false, false).ID: return 4775; case Vine::Vine(true, true, false, true, true).ID: return 4776; case Vine::Vine(true, true, false, true, false).ID: return 4777; case Vine::Vine(true, true, false, false, true).ID: return 4778; case Vine::Vine(true, true, false, false, false).ID: return 4779; case Vine::Vine(true, false, true, true, true).ID: return 4780; case Vine::Vine(true, false, true, true, false).ID: return 4781; case Vine::Vine(true, false, true, false, true).ID: return 4782; case Vine::Vine(true, false, true, false, false).ID: return 4783; case Vine::Vine(true, false, false, true, true).ID: return 4784; case Vine::Vine(true, false, false, true, false).ID: return 4785; case Vine::Vine(true, false, false, false, true).ID: return 4786; case Vine::Vine(true, false, false, false, false).ID: return 4787; case Vine::Vine(false, true, true, true, true).ID: return 4788; case Vine::Vine(false, true, true, true, false).ID: return 4789; case Vine::Vine(false, true, true, false, true).ID: return 4790; case Vine::Vine(false, true, true, false, false).ID: return 4791; case Vine::Vine(false, true, false, true, true).ID: return 4792; case Vine::Vine(false, true, false, true, false).ID: return 4793; case Vine::Vine(false, true, false, false, true).ID: return 4794; case Vine::Vine(false, true, false, false, false).ID: return 4795; case Vine::Vine(false, false, true, true, true).ID: return 4796; case Vine::Vine(false, false, true, true, false).ID: return 4797; case Vine::Vine(false, false, true, false, true).ID: return 4798; case Vine::Vine(false, false, true, false, false).ID: return 4799; case Vine::Vine(false, false, false, true, true).ID: return 4800; case Vine::Vine(false, false, false, true, false).ID: return 4801; case Vine::Vine(false, false, false, false, true).ID: return 4802; case Vine::Vine(false, false, false, false, false).ID: return 4803; case VoidAir::VoidAir().ID: return 9129; case WallTorch::WallTorch(eBlockFace::BLOCK_FACE_ZM).ID: return 1435; case WallTorch::WallTorch(eBlockFace::BLOCK_FACE_ZP).ID: return 1436; case WallTorch::WallTorch(eBlockFace::BLOCK_FACE_XM).ID: return 1437; case WallTorch::WallTorch(eBlockFace::BLOCK_FACE_XP).ID: return 1438; case Water::Water(0).ID: return 34; case Water::Water(1).ID: return 35; case Water::Water(2).ID: return 36; case Water::Water(3).ID: return 37; case Water::Water(4).ID: return 38; case Water::Water(5).ID: return 39; case Water::Water(6).ID: return 40; case Water::Water(7).ID: return 41; case Water::Water(8).ID: return 42; case Water::Water(9).ID: return 43; case Water::Water(10).ID: return 44; case Water::Water(11).ID: return 45; case Water::Water(12).ID: return 46; case Water::Water(13).ID: return 47; case Water::Water(14).ID: return 48; case Water::Water(15).ID: return 49; case WetSponge::WetSponge().ID: return 229; case Wheat::Wheat(0).ID: return 3355; case Wheat::Wheat(1).ID: return 3356; case Wheat::Wheat(2).ID: return 3357; case Wheat::Wheat(3).ID: return 3358; case Wheat::Wheat(4).ID: return 3359; case Wheat::Wheat(5).ID: return 3360; case Wheat::Wheat(6).ID: return 3361; case Wheat::Wheat(7).ID: return 3362; case WhiteBanner::WhiteBanner(0).ID: return 7361; case WhiteBanner::WhiteBanner(1).ID: return 7362; case WhiteBanner::WhiteBanner(2).ID: return 7363; case WhiteBanner::WhiteBanner(3).ID: return 7364; case WhiteBanner::WhiteBanner(4).ID: return 7365; case WhiteBanner::WhiteBanner(5).ID: return 7366; case WhiteBanner::WhiteBanner(6).ID: return 7367; case WhiteBanner::WhiteBanner(7).ID: return 7368; case WhiteBanner::WhiteBanner(8).ID: return 7369; case WhiteBanner::WhiteBanner(9).ID: return 7370; case WhiteBanner::WhiteBanner(10).ID: return 7371; case WhiteBanner::WhiteBanner(11).ID: return 7372; case WhiteBanner::WhiteBanner(12).ID: return 7373; case WhiteBanner::WhiteBanner(13).ID: return 7374; case WhiteBanner::WhiteBanner(14).ID: return 7375; case WhiteBanner::WhiteBanner(15).ID: return 7376; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_ZM, true, WhiteBed::Part::Head).ID: return 1048; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_ZM, true, WhiteBed::Part::Foot).ID: return 1049; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_ZM, false, WhiteBed::Part::Head).ID: return 1050; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_ZM, false, WhiteBed::Part::Foot).ID: return 1051; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_ZP, true, WhiteBed::Part::Head).ID: return 1052; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_ZP, true, WhiteBed::Part::Foot).ID: return 1053; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_ZP, false, WhiteBed::Part::Head).ID: return 1054; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_ZP, false, WhiteBed::Part::Foot).ID: return 1055; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_XM, true, WhiteBed::Part::Head).ID: return 1056; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_XM, true, WhiteBed::Part::Foot).ID: return 1057; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_XM, false, WhiteBed::Part::Head).ID: return 1058; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_XM, false, WhiteBed::Part::Foot).ID: return 1059; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_XP, true, WhiteBed::Part::Head).ID: return 1060; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_XP, true, WhiteBed::Part::Foot).ID: return 1061; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_XP, false, WhiteBed::Part::Head).ID: return 1062; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_XP, false, WhiteBed::Part::Foot).ID: return 1063; case WhiteCarpet::WhiteCarpet().ID: return 7330; case WhiteConcrete::WhiteConcrete().ID: return 8902; case WhiteConcretePowder::WhiteConcretePowder().ID: return 8918; case WhiteGlazedTerracotta::WhiteGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 8838; case WhiteGlazedTerracotta::WhiteGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 8839; case WhiteGlazedTerracotta::WhiteGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 8840; case WhiteGlazedTerracotta::WhiteGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 8841; case WhiteShulkerBox::WhiteShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 8742; case WhiteShulkerBox::WhiteShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 8743; case WhiteShulkerBox::WhiteShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 8744; case WhiteShulkerBox::WhiteShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 8745; case WhiteShulkerBox::WhiteShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 8746; case WhiteShulkerBox::WhiteShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 8747; case WhiteStainedGlass::WhiteStainedGlass().ID: return 4081; case WhiteStainedGlassPane::WhiteStainedGlassPane(true, true, true, true).ID: return 6329; case WhiteStainedGlassPane::WhiteStainedGlassPane(true, true, true, false).ID: return 6330; case WhiteStainedGlassPane::WhiteStainedGlassPane(true, true, false, true).ID: return 6333; case WhiteStainedGlassPane::WhiteStainedGlassPane(true, true, false, false).ID: return 6334; case WhiteStainedGlassPane::WhiteStainedGlassPane(true, false, true, true).ID: return 6337; case WhiteStainedGlassPane::WhiteStainedGlassPane(true, false, true, false).ID: return 6338; case WhiteStainedGlassPane::WhiteStainedGlassPane(true, false, false, true).ID: return 6341; case WhiteStainedGlassPane::WhiteStainedGlassPane(true, false, false, false).ID: return 6342; case WhiteStainedGlassPane::WhiteStainedGlassPane(false, true, true, true).ID: return 6345; case WhiteStainedGlassPane::WhiteStainedGlassPane(false, true, true, false).ID: return 6346; case WhiteStainedGlassPane::WhiteStainedGlassPane(false, true, false, true).ID: return 6349; case WhiteStainedGlassPane::WhiteStainedGlassPane(false, true, false, false).ID: return 6350; case WhiteStainedGlassPane::WhiteStainedGlassPane(false, false, true, true).ID: return 6353; case WhiteStainedGlassPane::WhiteStainedGlassPane(false, false, true, false).ID: return 6354; case WhiteStainedGlassPane::WhiteStainedGlassPane(false, false, false, true).ID: return 6357; case WhiteStainedGlassPane::WhiteStainedGlassPane(false, false, false, false).ID: return 6358; case WhiteTerracotta::WhiteTerracotta().ID: return 6311; case WhiteTulip::WhiteTulip().ID: return 1418; case WhiteWallBanner::WhiteWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 7617; case WhiteWallBanner::WhiteWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 7618; case WhiteWallBanner::WhiteWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 7619; case WhiteWallBanner::WhiteWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 7620; case WhiteWool::WhiteWool().ID: return 1383; case WitherRose::WitherRose().ID: return 1422; case WitherSkeletonSkull::WitherSkeletonSkull(0).ID: return 5974; case WitherSkeletonSkull::WitherSkeletonSkull(1).ID: return 5975; case WitherSkeletonSkull::WitherSkeletonSkull(2).ID: return 5976; case WitherSkeletonSkull::WitherSkeletonSkull(3).ID: return 5977; case WitherSkeletonSkull::WitherSkeletonSkull(4).ID: return 5978; case WitherSkeletonSkull::WitherSkeletonSkull(5).ID: return 5979; case WitherSkeletonSkull::WitherSkeletonSkull(6).ID: return 5980; case WitherSkeletonSkull::WitherSkeletonSkull(7).ID: return 5981; case WitherSkeletonSkull::WitherSkeletonSkull(8).ID: return 5982; case WitherSkeletonSkull::WitherSkeletonSkull(9).ID: return 5983; case WitherSkeletonSkull::WitherSkeletonSkull(10).ID: return 5984; case WitherSkeletonSkull::WitherSkeletonSkull(11).ID: return 5985; case WitherSkeletonSkull::WitherSkeletonSkull(12).ID: return 5986; case WitherSkeletonSkull::WitherSkeletonSkull(13).ID: return 5987; case WitherSkeletonSkull::WitherSkeletonSkull(14).ID: return 5988; case WitherSkeletonSkull::WitherSkeletonSkull(15).ID: return 5989; case WitherSkeletonWallSkull::WitherSkeletonWallSkull(eBlockFace::BLOCK_FACE_ZM).ID: return 5990; case WitherSkeletonWallSkull::WitherSkeletonWallSkull(eBlockFace::BLOCK_FACE_ZP).ID: return 5991; case WitherSkeletonWallSkull::WitherSkeletonWallSkull(eBlockFace::BLOCK_FACE_XM).ID: return 5992; case WitherSkeletonWallSkull::WitherSkeletonWallSkull(eBlockFace::BLOCK_FACE_XP).ID: return 5993; case YellowBanner::YellowBanner(0).ID: return 7425; case YellowBanner::YellowBanner(1).ID: return 7426; case YellowBanner::YellowBanner(2).ID: return 7427; case YellowBanner::YellowBanner(3).ID: return 7428; case YellowBanner::YellowBanner(4).ID: return 7429; case YellowBanner::YellowBanner(5).ID: return 7430; case YellowBanner::YellowBanner(6).ID: return 7431; case YellowBanner::YellowBanner(7).ID: return 7432; case YellowBanner::YellowBanner(8).ID: return 7433; case YellowBanner::YellowBanner(9).ID: return 7434; case YellowBanner::YellowBanner(10).ID: return 7435; case YellowBanner::YellowBanner(11).ID: return 7436; case YellowBanner::YellowBanner(12).ID: return 7437; case YellowBanner::YellowBanner(13).ID: return 7438; case YellowBanner::YellowBanner(14).ID: return 7439; case YellowBanner::YellowBanner(15).ID: return 7440; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_ZM, true, YellowBed::Part::Head).ID: return 1112; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_ZM, true, YellowBed::Part::Foot).ID: return 1113; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_ZM, false, YellowBed::Part::Head).ID: return 1114; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_ZM, false, YellowBed::Part::Foot).ID: return 1115; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_ZP, true, YellowBed::Part::Head).ID: return 1116; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_ZP, true, YellowBed::Part::Foot).ID: return 1117; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_ZP, false, YellowBed::Part::Head).ID: return 1118; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_ZP, false, YellowBed::Part::Foot).ID: return 1119; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_XM, true, YellowBed::Part::Head).ID: return 1120; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_XM, true, YellowBed::Part::Foot).ID: return 1121; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_XM, false, YellowBed::Part::Head).ID: return 1122; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_XM, false, YellowBed::Part::Foot).ID: return 1123; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_XP, true, YellowBed::Part::Head).ID: return 1124; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_XP, true, YellowBed::Part::Foot).ID: return 1125; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_XP, false, YellowBed::Part::Head).ID: return 1126; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_XP, false, YellowBed::Part::Foot).ID: return 1127; case YellowCarpet::YellowCarpet().ID: return 7334; case YellowConcrete::YellowConcrete().ID: return 8906; case YellowConcretePowder::YellowConcretePowder().ID: return 8922; case YellowGlazedTerracotta::YellowGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 8854; case YellowGlazedTerracotta::YellowGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 8855; case YellowGlazedTerracotta::YellowGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 8856; case YellowGlazedTerracotta::YellowGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 8857; case YellowShulkerBox::YellowShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 8766; case YellowShulkerBox::YellowShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 8767; case YellowShulkerBox::YellowShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 8768; case YellowShulkerBox::YellowShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 8769; case YellowShulkerBox::YellowShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 8770; case YellowShulkerBox::YellowShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 8771; case YellowStainedGlass::YellowStainedGlass().ID: return 4085; case YellowStainedGlassPane::YellowStainedGlassPane(true, true, true, true).ID: return 6457; case YellowStainedGlassPane::YellowStainedGlassPane(true, true, true, false).ID: return 6458; case YellowStainedGlassPane::YellowStainedGlassPane(true, true, false, true).ID: return 6461; case YellowStainedGlassPane::YellowStainedGlassPane(true, true, false, false).ID: return 6462; case YellowStainedGlassPane::YellowStainedGlassPane(true, false, true, true).ID: return 6465; case YellowStainedGlassPane::YellowStainedGlassPane(true, false, true, false).ID: return 6466; case YellowStainedGlassPane::YellowStainedGlassPane(true, false, false, true).ID: return 6469; case YellowStainedGlassPane::YellowStainedGlassPane(true, false, false, false).ID: return 6470; case YellowStainedGlassPane::YellowStainedGlassPane(false, true, true, true).ID: return 6473; case YellowStainedGlassPane::YellowStainedGlassPane(false, true, true, false).ID: return 6474; case YellowStainedGlassPane::YellowStainedGlassPane(false, true, false, true).ID: return 6477; case YellowStainedGlassPane::YellowStainedGlassPane(false, true, false, false).ID: return 6478; case YellowStainedGlassPane::YellowStainedGlassPane(false, false, true, true).ID: return 6481; case YellowStainedGlassPane::YellowStainedGlassPane(false, false, true, false).ID: return 6482; case YellowStainedGlassPane::YellowStainedGlassPane(false, false, false, true).ID: return 6485; case YellowStainedGlassPane::YellowStainedGlassPane(false, false, false, false).ID: return 6486; case YellowTerracotta::YellowTerracotta().ID: return 6315; case YellowWallBanner::YellowWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 7633; case YellowWallBanner::YellowWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 7634; case YellowWallBanner::YellowWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 7635; case YellowWallBanner::YellowWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 7636; case YellowWool::YellowWool().ID: return 1387; case ZombieHead::ZombieHead(0).ID: return 5994; case ZombieHead::ZombieHead(1).ID: return 5995; case ZombieHead::ZombieHead(2).ID: return 5996; case ZombieHead::ZombieHead(3).ID: return 5997; case ZombieHead::ZombieHead(4).ID: return 5998; case ZombieHead::ZombieHead(5).ID: return 5999; case ZombieHead::ZombieHead(6).ID: return 6000; case ZombieHead::ZombieHead(7).ID: return 6001; case ZombieHead::ZombieHead(8).ID: return 6002; case ZombieHead::ZombieHead(9).ID: return 6003; case ZombieHead::ZombieHead(10).ID: return 6004; case ZombieHead::ZombieHead(11).ID: return 6005; case ZombieHead::ZombieHead(12).ID: return 6006; case ZombieHead::ZombieHead(13).ID: return 6007; case ZombieHead::ZombieHead(14).ID: return 6008; case ZombieHead::ZombieHead(15).ID: return 6009; case ZombieWallHead::ZombieWallHead(eBlockFace::BLOCK_FACE_ZM).ID: return 6010; case ZombieWallHead::ZombieWallHead(eBlockFace::BLOCK_FACE_ZP).ID: return 6011; case ZombieWallHead::ZombieWallHead(eBlockFace::BLOCK_FACE_XM).ID: return 6012; case ZombieWallHead::ZombieWallHead(eBlockFace::BLOCK_FACE_XP).ID: return 6013; default: return 0; } } UInt32 From(const Item ID) { switch (ID) { case Item::AcaciaBoat: return 833; case Item::AcaciaButton: return 263; case Item::AcaciaDoor: return 511; case Item::AcaciaFence: return 185; case Item::AcaciaFenceGate: return 220; case Item::AcaciaLeaves: return 60; case Item::AcaciaLog: return 36; case Item::AcaciaPlanks: return 17; case Item::AcaciaPressurePlate: return 170; case Item::AcaciaSapling: return 23; case Item::AcaciaSign: return 593; case Item::AcaciaSlab: return 119; case Item::AcaciaStairs: return 319; case Item::AcaciaTrapdoor: return 197; case Item::AcaciaWood: return 54; case Item::ActivatorRail: return 279; case Item::Air: return -0; case Item::Allium: return 101; case Item::Andesite: return 6; case Item::AndesiteSlab: return 501; case Item::AndesiteStairs: return 488; case Item::AndesiteWall: return 254; case Item::Anvil: return 265; case Item::Apple: return 524; case Item::ArmorStand: return 791; case Item::Arrow: return 526; case Item::AzureBluet: return 102; case Item::BakedPotato: return 764; case Item::Bamboo: return 614; case Item::Barrel: return 864; case Item::Barrier: return 297; case Item::BatSpawnEgg: return 697; case Item::Beacon: return 244; case Item::Bedrock: return 25; case Item::Beef: return 677; case Item::Beetroot: return 820; case Item::BeetrootSeeds: return 821; case Item::BeetrootSoup: return 822; case Item::Bell: return 873; case Item::BirchBoat: return 831; case Item::BirchButton: return 261; case Item::BirchDoor: return 509; case Item::BirchFence: return 183; case Item::BirchFenceGate: return 218; case Item::BirchLeaves: return 58; case Item::BirchLog: return 34; case Item::BirchPlanks: return 15; case Item::BirchPressurePlate: return 168; case Item::BirchSapling: return 21; case Item::BirchSign: return 591; case Item::BirchSlab: return 117; case Item::BirchStairs: return 241; case Item::BirchTrapdoor: return 195; case Item::BirchWood: return 52; case Item::BlackBanner: return 816; case Item::BlackBed: return 669; case Item::BlackCarpet: return 315; case Item::BlackConcrete: return 428; case Item::BlackConcretePowder: return 444; case Item::BlackDye: return 649; case Item::BlackGlazedTerracotta: return 412; case Item::BlackShulkerBox: return 396; case Item::BlackStainedGlass: return 344; case Item::BlackStainedGlassPane: return 360; case Item::BlackTerracotta: return 296; case Item::BlackWool: return 97; case Item::BlastFurnace: return 866; case Item::BlazePowder: return 691; case Item::BlazeRod: return 683; case Item::BlazeSpawnEgg: return 698; case Item::BlueBanner: return 812; case Item::BlueBed: return 665; case Item::BlueCarpet: return 311; case Item::BlueConcrete: return 424; case Item::BlueConcretePowder: return 440; case Item::BlueDye: return 647; case Item::BlueGlazedTerracotta: return 408; case Item::BlueIce: return 476; case Item::BlueOrchid: return 100; case Item::BlueShulkerBox: return 392; case Item::BlueStainedGlass: return 340; case Item::BlueStainedGlassPane: return 356; case Item::BlueTerracotta: return 292; case Item::BlueWool: return 93; case Item::Bone: return 651; case Item::BoneBlock: return 377; case Item::BoneMeal: return 646; case Item::Book: return 616; case Item::Bookshelf: return 143; case Item::Bow: return 525; case Item::Bowl: return 546; case Item::BrainCoral: return 457; case Item::BrainCoralBlock: return 452; case Item::BrainCoralFan: return 467; case Item::Bread: return 562; case Item::BrewingStand: return 693; case Item::Brick: return 609; case Item::BrickSlab: return 127; case Item::BrickStairs: return 222; case Item::BrickWall: return 247; case Item::Bricks: return 141; case Item::BrownBanner: return 813; case Item::BrownBed: return 666; case Item::BrownCarpet: return 312; case Item::BrownConcrete: return 425; case Item::BrownConcretePowder: return 441; case Item::BrownDye: return 648; case Item::BrownGlazedTerracotta: return 409; case Item::BrownMushroom: return 111; case Item::BrownMushroomBlock: return 209; case Item::BrownShulkerBox: return 393; case Item::BrownStainedGlass: return 341; case Item::BrownStainedGlassPane: return 357; case Item::BrownTerracotta: return 293; case Item::BrownWool: return 94; case Item::BubbleCoral: return 458; case Item::BubbleCoralBlock: return 453; case Item::BubbleCoralFan: return 468; case Item::Bucket: return 595; case Item::Cactus: return 178; case Item::Cake: return 653; case Item::Campfire: return 876; case Item::Carrot: return 762; case Item::CarrotOnAStick: return 774; case Item::CartographyTable: return 867; case Item::CarvedPumpkin: return 188; case Item::CatSpawnEgg: return 699; case Item::Cauldron: return 694; case Item::CaveSpiderSpawnEgg: return 700; case Item::ChainCommandBlock: return 373; case Item::ChainmailBoots: return 570; case Item::ChainmailChestplate: return 568; case Item::ChainmailHelmet: return 567; case Item::ChainmailLeggings: return 569; case Item::Charcoal: return 528; case Item::Chest: return 155; case Item::ChestMinecart: return 618; case Item::Chicken: return 679; case Item::ChickenSpawnEgg: return 701; case Item::ChippedAnvil: return 266; case Item::ChiseledQuartzBlock: return 275; case Item::ChiseledRedSandstone: return 369; case Item::ChiseledSandstone: return 69; case Item::ChiseledStoneBricks: return 208; case Item::ChorusFlower: return 149; case Item::ChorusFruit: return 818; case Item::ChorusPlant: return 148; case Item::Clay: return 179; case Item::ClayBall: return 610; case Item::Clock: return 623; case Item::Coal: return 527; case Item::CoalBlock: return 317; case Item::CoalOre: return 31; case Item::CoarseDirt: return 10; case Item::Cobblestone: return 12; case Item::CobblestoneSlab: return 126; case Item::CobblestoneStairs: return 163; case Item::CobblestoneWall: return 245; case Item::Cobweb: return 75; case Item::CocoaBeans: return 634; case Item::Cod: return 625; case Item::CodBucket: return 607; case Item::CodSpawnEgg: return 702; case Item::CommandBlock: return 243; case Item::CommandBlockMinecart: return 798; case Item::Comparator: return 514; case Item::Compass: return 621; case Item::Composter: return 517; case Item::Conduit: return 477; case Item::CookedBeef: return 678; case Item::CookedChicken: return 680; case Item::CookedCod: return 629; case Item::CookedMutton: return 800; case Item::CookedPorkchop: return 585; case Item::CookedRabbit: return 787; case Item::CookedSalmon: return 630; case Item::Cookie: return 670; case Item::Cornflower: return 108; case Item::CowSpawnEgg: return 703; case Item::CrackedStoneBricks: return 207; case Item::CraftingTable: return 158; case Item::CreeperBannerPattern: return 860; case Item::CreeperHead: return 772; case Item::CreeperSpawnEgg: return 704; case Item::Crossbow: return 856; case Item::CutRedSandstone: return 370; case Item::CutRedSandstoneSlab: return 132; case Item::CutSandstone: return 70; case Item::CutSandstoneSlab: return 124; case Item::CyanBanner: return 810; case Item::CyanBed: return 663; case Item::CyanCarpet: return 309; case Item::CyanConcrete: return 422; case Item::CyanConcretePowder: return 438; case Item::CyanDye: return 637; case Item::CyanGlazedTerracotta: return 406; case Item::CyanShulkerBox: return 390; case Item::CyanStainedGlass: return 338; case Item::CyanStainedGlassPane: return 354; case Item::CyanTerracotta: return 290; case Item::CyanWool: return 91; case Item::DamagedAnvil: return 267; case Item::Dandelion: return 98; case Item::DarkOakBoat: return 834; case Item::DarkOakButton: return 264; case Item::DarkOakDoor: return 512; case Item::DarkOakFence: return 186; case Item::DarkOakFenceGate: return 221; case Item::DarkOakLeaves: return 61; case Item::DarkOakLog: return 37; case Item::DarkOakPlanks: return 18; case Item::DarkOakPressurePlate: return 171; case Item::DarkOakSapling: return 24; case Item::DarkOakSign: return 594; case Item::DarkOakSlab: return 120; case Item::DarkOakStairs: return 320; case Item::DarkOakTrapdoor: return 198; case Item::DarkOakWood: return 55; case Item::DarkPrismarine: return 363; case Item::DarkPrismarineSlab: return 136; case Item::DarkPrismarineStairs: return 366; case Item::DaylightDetector: return 271; case Item::DeadBrainCoral: return 461; case Item::DeadBrainCoralBlock: return 447; case Item::DeadBrainCoralFan: return 472; case Item::DeadBubbleCoral: return 462; case Item::DeadBubbleCoralBlock: return 448; case Item::DeadBubbleCoralFan: return 473; case Item::DeadBush: return 78; case Item::DeadFireCoral: return 463; case Item::DeadFireCoralBlock: return 449; case Item::DeadFireCoralFan: return 474; case Item::DeadHornCoral: return 464; case Item::DeadHornCoralBlock: return 450; case Item::DeadHornCoralFan: return 475; case Item::DeadTubeCoral: return 465; case Item::DeadTubeCoralBlock: return 446; case Item::DeadTubeCoralFan: return 471; case Item::DebugStick: return 839; case Item::DetectorRail: return 73; case Item::Diamond: return 529; case Item::DiamondAxe: return 544; case Item::DiamondBlock: return 157; case Item::DiamondBoots: return 578; case Item::DiamondChestplate: return 576; case Item::DiamondHelmet: return 575; case Item::DiamondHoe: return 558; case Item::DiamondHorseArmor: return 794; case Item::DiamondLeggings: return 577; case Item::DiamondOre: return 156; case Item::DiamondPickaxe: return 543; case Item::DiamondShovel: return 542; case Item::DiamondSword: return 541; case Item::Diorite: return 4; case Item::DioriteSlab: return 504; case Item::DioriteStairs: return 491; case Item::DioriteWall: return 258; case Item::Dirt: return 9; case Item::Dispenser: return 67; case Item::DolphinSpawnEgg: return 705; case Item::DonkeySpawnEgg: return 706; case Item::DragonBreath: return 823; case Item::DragonEgg: return 233; case Item::DragonHead: return 773; case Item::DriedKelp: return 674; case Item::DriedKelpBlock: return 613; case Item::Dropper: return 280; case Item::DrownedSpawnEgg: return 707; case Item::Egg: return 620; case Item::ElderGuardianSpawnEgg: return 708; case Item::Elytra: return 829; case Item::Emerald: return 759; case Item::EmeraldBlock: return 239; case Item::EmeraldOre: return 236; case Item::EnchantedBook: return 779; case Item::EnchantedGoldenApple: return 588; case Item::EnchantingTable: return 229; case Item::EndCrystal: return 817; case Item::EndPortalFrame: return 230; case Item::EndRod: return 147; case Item::EndStone: return 231; case Item::EndStoneBrickSlab: return 497; case Item::EndStoneBrickStairs: return 483; case Item::EndStoneBrickWall: return 257; case Item::EndStoneBricks: return 232; case Item::EnderChest: return 237; case Item::EnderEye: return 695; case Item::EnderPearl: return 682; case Item::EndermanSpawnEgg: return 709; case Item::EndermiteSpawnEgg: return 710; case Item::EvokerSpawnEgg: return 711; case Item::ExperienceBottle: return 755; case Item::Farmland: return 159; case Item::Feather: return 553; case Item::FermentedSpiderEye: return 690; case Item::Fern: return 77; case Item::FilledMap: return 671; case Item::FireCharge: return 756; case Item::FireCoral: return 459; case Item::FireCoralBlock: return 454; case Item::FireCoralFan: return 469; case Item::FireworkRocket: return 777; case Item::FireworkStar: return 778; case Item::FishingRod: return 622; case Item::FletchingTable: return 868; case Item::Flint: return 583; case Item::FlintAndSteel: return 523; case Item::FlowerBannerPattern: return 859; case Item::FlowerPot: return 761; case Item::FoxSpawnEgg: return 712; case Item::Furnace: return 160; case Item::FurnaceMinecart: return 619; case Item::GhastSpawnEgg: return 713; case Item::GhastTear: return 684; case Item::Glass: return 64; case Item::GlassBottle: return 688; case Item::GlassPane: return 213; case Item::GlisteringMelonSlice: return 696; case Item::GlobeBannerPattern: return 863; case Item::Glowstone: return 191; case Item::GlowstoneDust: return 624; case Item::GoldBlock: return 113; case Item::GoldIngot: return 531; case Item::GoldNugget: return 685; case Item::GoldOre: return 29; case Item::GoldenApple: return 587; case Item::GoldenAxe: return 551; case Item::GoldenBoots: return 582; case Item::GoldenCarrot: return 767; case Item::GoldenChestplate: return 580; case Item::GoldenHelmet: return 579; case Item::GoldenHoe: return 559; case Item::GoldenHorseArmor: return 793; case Item::GoldenLeggings: return 581; case Item::GoldenPickaxe: return 550; case Item::GoldenShovel: return 549; case Item::GoldenSword: return 548; case Item::Granite: return 2; case Item::GraniteSlab: return 500; case Item::GraniteStairs: return 487; case Item::GraniteWall: return 251; case Item::Grass: return 76; case Item::GrassBlock: return 8; case Item::GrassPath: return 322; case Item::Gravel: return 28; case Item::GrayBanner: return 808; case Item::GrayBed: return 661; case Item::GrayCarpet: return 307; case Item::GrayConcrete: return 420; case Item::GrayConcretePowder: return 436; case Item::GrayDye: return 639; case Item::GrayGlazedTerracotta: return 404; case Item::GrayShulkerBox: return 388; case Item::GrayStainedGlass: return 336; case Item::GrayStainedGlassPane: return 352; case Item::GrayTerracotta: return 288; case Item::GrayWool: return 89; case Item::GreenBanner: return 814; case Item::GreenBed: return 667; case Item::GreenCarpet: return 313; case Item::GreenConcrete: return 426; case Item::GreenConcretePowder: return 442; case Item::GreenDye: return 633; case Item::GreenGlazedTerracotta: return 410; case Item::GreenShulkerBox: return 394; case Item::GreenStainedGlass: return 342; case Item::GreenStainedGlassPane: return 358; case Item::GreenTerracotta: return 294; case Item::GreenWool: return 95; case Item::Grindstone: return 869; case Item::GuardianSpawnEgg: return 714; case Item::Gunpowder: return 554; case Item::HayBale: return 299; case Item::HeartOfTheSea: return 855; case Item::HeavyWeightedPressurePlate: return 270; case Item::Hopper: return 274; case Item::HopperMinecart: return 783; case Item::HornCoral: return 460; case Item::HornCoralBlock: return 455; case Item::HornCoralFan: return 470; case Item::HorseSpawnEgg: return 715; case Item::HuskSpawnEgg: return 716; case Item::Ice: return 176; case Item::InfestedChiseledStoneBricks: return 204; case Item::InfestedCobblestone: return 200; case Item::InfestedCrackedStoneBricks: return 203; case Item::InfestedMossyStoneBricks: return 202; case Item::InfestedStone: return 199; case Item::InfestedStoneBricks: return 201; case Item::InkSac: return 631; case Item::IronAxe: return 522; case Item::IronBars: return 212; case Item::IronBlock: return 114; case Item::IronBoots: return 574; case Item::IronChestplate: return 572; case Item::IronDoor: return 506; case Item::IronHelmet: return 571; case Item::IronHoe: return 557; case Item::IronHorseArmor: return 792; case Item::IronIngot: return 530; case Item::IronLeggings: return 573; case Item::IronNugget: return 837; case Item::IronOre: return 30; case Item::IronPickaxe: return 521; case Item::IronShovel: return 520; case Item::IronSword: return 532; case Item::IronTrapdoor: return 298; case Item::ItemFrame: return 760; case Item::JackOLantern: return 192; case Item::Jigsaw: return 516; case Item::Jukebox: return 180; case Item::JungleBoat: return 832; case Item::JungleButton: return 262; case Item::JungleDoor: return 510; case Item::JungleFence: return 184; case Item::JungleFenceGate: return 219; case Item::JungleLeaves: return 59; case Item::JungleLog: return 35; case Item::JunglePlanks: return 16; case Item::JunglePressurePlate: return 169; case Item::JungleSapling: return 22; case Item::JungleSign: return 592; case Item::JungleSlab: return 118; case Item::JungleStairs: return 242; case Item::JungleTrapdoor: return 196; case Item::JungleWood: return 53; case Item::Kelp: return 612; case Item::KnowledgeBook: return 838; case Item::Ladder: return 161; case Item::Lantern: return 874; case Item::LapisBlock: return 66; case Item::LapisLazuli: return 635; case Item::LapisOre: return 65; case Item::LargeFern: return 328; case Item::LavaBucket: return 597; case Item::Lead: return 796; case Item::Leather: return 603; case Item::LeatherBoots: return 566; case Item::LeatherChestplate: return 564; case Item::LeatherHelmet: return 563; case Item::LeatherHorseArmor: return 795; case Item::LeatherLeggings: return 565; case Item::Lectern: return 870; case Item::Lever: return 164; case Item::LightBlueBanner: return 804; case Item::LightBlueBed: return 657; case Item::LightBlueCarpet: return 303; case Item::LightBlueConcrete: return 416; case Item::LightBlueConcretePowder: return 432; case Item::LightBlueDye: return 643; case Item::LightBlueGlazedTerracotta: return 400; case Item::LightBlueShulkerBox: return 384; case Item::LightBlueStainedGlass: return 332; case Item::LightBlueStainedGlassPane: return 348; case Item::LightBlueTerracotta: return 284; case Item::LightBlueWool: return 85; case Item::LightGrayBanner: return 809; case Item::LightGrayBed: return 662; case Item::LightGrayCarpet: return 308; case Item::LightGrayConcrete: return 421; case Item::LightGrayConcretePowder: return 437; case Item::LightGrayDye: return 638; case Item::LightGrayGlazedTerracotta: return 405; case Item::LightGrayShulkerBox: return 389; case Item::LightGrayStainedGlass: return 337; case Item::LightGrayStainedGlassPane: return 353; case Item::LightGrayTerracotta: return 289; case Item::LightGrayWool: return 90; case Item::LightWeightedPressurePlate: return 269; case Item::Lilac: return 324; case Item::LilyOfTheValley: return 109; case Item::LilyPad: return 225; case Item::LimeBanner: return 806; case Item::LimeBed: return 659; case Item::LimeCarpet: return 305; case Item::LimeConcrete: return 418; case Item::LimeConcretePowder: return 434; case Item::LimeDye: return 641; case Item::LimeGlazedTerracotta: return 402; case Item::LimeShulkerBox: return 386; case Item::LimeStainedGlass: return 334; case Item::LimeStainedGlassPane: return 350; case Item::LimeTerracotta: return 286; case Item::LimeWool: return 87; case Item::LingeringPotion: return 827; case Item::LlamaSpawnEgg: return 717; case Item::Loom: return 858; case Item::MagentaBanner: return 803; case Item::MagentaBed: return 656; case Item::MagentaCarpet: return 302; case Item::MagentaConcrete: return 415; case Item::MagentaConcretePowder: return 431; case Item::MagentaDye: return 644; case Item::MagentaGlazedTerracotta: return 399; case Item::MagentaShulkerBox: return 383; case Item::MagentaStainedGlass: return 331; case Item::MagentaStainedGlassPane: return 347; case Item::MagentaTerracotta: return 283; case Item::MagentaWool: return 84; case Item::MagmaBlock: return 374; case Item::MagmaCream: return 692; case Item::MagmaCubeSpawnEgg: return 718; case Item::Map: return 766; case Item::Melon: return 214; case Item::MelonSeeds: return 676; case Item::MelonSlice: return 673; case Item::MilkBucket: return 604; case Item::Minecart: return 598; case Item::MojangBannerPattern: return 862; case Item::MooshroomSpawnEgg: return 719; case Item::MossyCobblestone: return 144; case Item::MossyCobblestoneSlab: return 496; case Item::MossyCobblestoneStairs: return 482; case Item::MossyCobblestoneWall: return 246; case Item::MossyStoneBrickSlab: return 494; case Item::MossyStoneBrickStairs: return 480; case Item::MossyStoneBrickWall: return 250; case Item::MossyStoneBricks: return 206; case Item::MuleSpawnEgg: return 720; case Item::MushroomStem: return 211; case Item::MushroomStew: return 547; case Item::MusicDisc11: return 850; case Item::MusicDisc13: return 840; case Item::MusicDiscBlocks: return 842; case Item::MusicDiscCat: return 841; case Item::MusicDiscChirp: return 843; case Item::MusicDiscFar: return 844; case Item::MusicDiscMall: return 845; case Item::MusicDiscMellohi: return 846; case Item::MusicDiscStal: return 847; case Item::MusicDiscStrad: return 848; case Item::MusicDiscWait: return 851; case Item::MusicDiscWard: return 849; case Item::Mutton: return 799; case Item::Mycelium: return 224; case Item::NameTag: return 797; case Item::NautilusShell: return 854; case Item::NetherBrick: return 780; case Item::NetherBrickFence: return 227; case Item::NetherBrickSlab: return 129; case Item::NetherBrickStairs: return 228; case Item::NetherBrickWall: return 253; case Item::NetherBricks: return 226; case Item::NetherQuartzOre: return 273; case Item::NetherStar: return 775; case Item::NetherWart: return 686; case Item::NetherWartBlock: return 375; case Item::Netherrack: return 189; case Item::NoteBlock: return 71; case Item::OakBoat: return 602; case Item::OakButton: return 259; case Item::OakDoor: return 507; case Item::OakFence: return 181; case Item::OakFenceGate: return 216; case Item::OakLeaves: return 56; case Item::OakLog: return 32; case Item::OakPlanks: return 13; case Item::OakPressurePlate: return 166; case Item::OakSapling: return 19; case Item::OakSign: return 589; case Item::OakSlab: return 115; case Item::OakStairs: return 154; case Item::OakTrapdoor: return 193; case Item::OakWood: return 50; case Item::Observer: return 379; case Item::Obsidian: return 145; case Item::OcelotSpawnEgg: return 721; case Item::OrangeBanner: return 802; case Item::OrangeBed: return 655; case Item::OrangeCarpet: return 301; case Item::OrangeConcrete: return 414; case Item::OrangeConcretePowder: return 430; case Item::OrangeDye: return 645; case Item::OrangeGlazedTerracotta: return 398; case Item::OrangeShulkerBox: return 382; case Item::OrangeStainedGlass: return 330; case Item::OrangeStainedGlassPane: return 346; case Item::OrangeTerracotta: return 282; case Item::OrangeTulip: return 104; case Item::OrangeWool: return 83; case Item::OxeyeDaisy: return 107; case Item::PackedIce: return 318; case Item::Painting: return 586; case Item::PandaSpawnEgg: return 722; case Item::Paper: return 615; case Item::ParrotSpawnEgg: return 723; case Item::Peony: return 326; case Item::PetrifiedOakSlab: return 125; case Item::PhantomMembrane: return 853; case Item::PhantomSpawnEgg: return 724; case Item::PigSpawnEgg: return 725; case Item::PillagerSpawnEgg: return 726; case Item::PinkBanner: return 807; case Item::PinkBed: return 660; case Item::PinkCarpet: return 306; case Item::PinkConcrete: return 419; case Item::PinkConcretePowder: return 435; case Item::PinkDye: return 640; case Item::PinkGlazedTerracotta: return 403; case Item::PinkShulkerBox: return 387; case Item::PinkStainedGlass: return 335; case Item::PinkStainedGlassPane: return 351; case Item::PinkTerracotta: return 287; case Item::PinkTulip: return 106; case Item::PinkWool: return 88; case Item::Piston: return 81; case Item::PlayerHead: return 770; case Item::Podzol: return 11; case Item::PoisonousPotato: return 765; case Item::PolarBearSpawnEgg: return 727; case Item::PolishedAndesite: return 7; case Item::PolishedAndesiteSlab: return 503; case Item::PolishedAndesiteStairs: return 490; case Item::PolishedDiorite: return 5; case Item::PolishedDioriteSlab: return 495; case Item::PolishedDioriteStairs: return 481; case Item::PolishedGranite: return 3; case Item::PolishedGraniteSlab: return 492; case Item::PolishedGraniteStairs: return 478; case Item::PoppedChorusFruit: return 819; case Item::Poppy: return 99; case Item::Porkchop: return 584; case Item::Potato: return 763; case Item::Potion: return 687; case Item::PoweredRail: return 72; case Item::Prismarine: return 361; case Item::PrismarineBrickSlab: return 135; case Item::PrismarineBrickStairs: return 365; case Item::PrismarineBricks: return 362; case Item::PrismarineCrystals: return 785; case Item::PrismarineShard: return 784; case Item::PrismarineSlab: return 134; case Item::PrismarineStairs: return 364; case Item::PrismarineWall: return 248; case Item::Pufferfish: return 628; case Item::PufferfishBucket: return 605; case Item::PufferfishSpawnEgg: return 728; case Item::Pumpkin: return 187; case Item::PumpkinPie: return 776; case Item::PumpkinSeeds: return 675; case Item::PurpleBanner: return 811; case Item::PurpleBed: return 664; case Item::PurpleCarpet: return 310; case Item::PurpleConcrete: return 423; case Item::PurpleConcretePowder: return 439; case Item::PurpleDye: return 636; case Item::PurpleGlazedTerracotta: return 407; case Item::PurpleShulkerBox: return 391; case Item::PurpleStainedGlass: return 339; case Item::PurpleStainedGlassPane: return 355; case Item::PurpleTerracotta: return 291; case Item::PurpleWool: return 92; case Item::PurpurBlock: return 150; case Item::PurpurPillar: return 151; case Item::PurpurSlab: return 133; case Item::PurpurStairs: return 152; case Item::Quartz: return 781; case Item::QuartzBlock: return 276; case Item::QuartzPillar: return 277; case Item::QuartzSlab: return 130; case Item::QuartzStairs: return 278; case Item::Rabbit: return 786; case Item::RabbitFoot: return 789; case Item::RabbitHide: return 790; case Item::RabbitSpawnEgg: return 729; case Item::RabbitStew: return 788; case Item::Rail: return 162; case Item::RavagerSpawnEgg: return 730; case Item::RedBanner: return 815; case Item::RedBed: return 668; case Item::RedCarpet: return 314; case Item::RedConcrete: return 427; case Item::RedConcretePowder: return 443; case Item::RedDye: return 632; case Item::RedGlazedTerracotta: return 411; case Item::RedMushroom: return 112; case Item::RedMushroomBlock: return 210; case Item::RedNetherBrickSlab: return 502; case Item::RedNetherBrickStairs: return 489; case Item::RedNetherBrickWall: return 255; case Item::RedNetherBricks: return 376; case Item::RedSand: return 27; case Item::RedSandstone: return 368; case Item::RedSandstoneSlab: return 131; case Item::RedSandstoneStairs: return 371; case Item::RedSandstoneWall: return 249; case Item::RedShulkerBox: return 395; case Item::RedStainedGlass: return 343; case Item::RedStainedGlassPane: return 359; case Item::RedTerracotta: return 295; case Item::RedTulip: return 103; case Item::RedWool: return 96; case Item::Redstone: return 600; case Item::RedstoneBlock: return 272; case Item::RedstoneLamp: return 234; case Item::RedstoneOre: return 172; case Item::RedstoneTorch: return 173; case Item::Repeater: return 513; case Item::RepeatingCommandBlock: return 372; case Item::RoseBush: return 325; case Item::RottenFlesh: return 681; case Item::Saddle: return 599; case Item::Salmon: return 626; case Item::SalmonBucket: return 606; case Item::SalmonSpawnEgg: return 731; case Item::Sand: return 26; case Item::Sandstone: return 68; case Item::SandstoneSlab: return 123; case Item::SandstoneStairs: return 235; case Item::SandstoneWall: return 256; case Item::Scaffolding: return 505; case Item::Scute: return 519; case Item::SeaLantern: return 367; case Item::SeaPickle: return 80; case Item::Seagrass: return 79; case Item::Shears: return 672; case Item::SheepSpawnEgg: return 732; case Item::Shield: return 828; case Item::ShulkerBox: return 380; case Item::ShulkerShell: return 836; case Item::ShulkerSpawnEgg: return 733; case Item::SilverfishSpawnEgg: return 734; case Item::SkeletonHorseSpawnEgg: return 736; case Item::SkeletonSkull: return 768; case Item::SkeletonSpawnEgg: return 735; case Item::SkullBannerPattern: return 861; case Item::SlimeBall: return 617; case Item::SlimeBlock: return 321; case Item::SlimeSpawnEgg: return 737; case Item::SmithingTable: return 871; case Item::Smoker: return 865; case Item::SmoothQuartz: return 137; case Item::SmoothQuartzSlab: return 499; case Item::SmoothQuartzStairs: return 486; case Item::SmoothRedSandstone: return 138; case Item::SmoothRedSandstoneSlab: return 493; case Item::SmoothRedSandstoneStairs: return 479; case Item::SmoothSandstone: return 139; case Item::SmoothSandstoneSlab: return 498; case Item::SmoothSandstoneStairs: return 485; case Item::SmoothStone: return 140; case Item::SmoothStoneSlab: return 122; case Item::Snow: return 175; case Item::SnowBlock: return 177; case Item::Snowball: return 601; case Item::SoulSand: return 190; case Item::Spawner: return 153; case Item::SpectralArrow: return 825; case Item::SpiderEye: return 689; case Item::SpiderSpawnEgg: return 738; case Item::SplashPotion: return 824; case Item::Sponge: return 62; case Item::SpruceBoat: return 830; case Item::SpruceButton: return 260; case Item::SpruceDoor: return 508; case Item::SpruceFence: return 182; case Item::SpruceFenceGate: return 217; case Item::SpruceLeaves: return 57; case Item::SpruceLog: return 33; case Item::SprucePlanks: return 14; case Item::SprucePressurePlate: return 167; case Item::SpruceSapling: return 20; case Item::SpruceSign: return 590; case Item::SpruceSlab: return 116; case Item::SpruceStairs: return 240; case Item::SpruceTrapdoor: return 194; case Item::SpruceWood: return 51; case Item::SquidSpawnEgg: return 739; case Item::Stick: return 545; case Item::StickyPiston: return 74; case Item::Stone: return 1; case Item::StoneAxe: return 540; case Item::StoneBrickSlab: return 128; case Item::StoneBrickStairs: return 223; case Item::StoneBrickWall: return 252; case Item::StoneBricks: return 205; case Item::StoneButton: return 174; case Item::StoneHoe: return 556; case Item::StonePickaxe: return 539; case Item::StonePressurePlate: return 165; case Item::StoneShovel: return 538; case Item::StoneSlab: return 121; case Item::StoneStairs: return 484; case Item::StoneSword: return 537; case Item::Stonecutter: return 872; case Item::StraySpawnEgg: return 740; case Item::String: return 552; case Item::StrippedAcaciaLog: return 42; case Item::StrippedAcaciaWood: return 48; case Item::StrippedBirchLog: return 40; case Item::StrippedBirchWood: return 46; case Item::StrippedDarkOakLog: return 43; case Item::StrippedDarkOakWood: return 49; case Item::StrippedJungleLog: return 41; case Item::StrippedJungleWood: return 47; case Item::StrippedOakLog: return 38; case Item::StrippedOakWood: return 44; case Item::StrippedSpruceLog: return 39; case Item::StrippedSpruceWood: return 45; case Item::StructureBlock: return 515; case Item::StructureVoid: return 378; case Item::Sugar: return 652; case Item::SugarCane: return 611; case Item::Sunflower: return 323; case Item::SuspiciousStew: return 857; case Item::SweetBerries: return 875; case Item::TallGrass: return 327; case Item::Terracotta: return 316; case Item::TippedArrow: return 826; case Item::TNT: return 142; case Item::TNTMinecart: return 782; case Item::Torch: return 146; case Item::TotemOfUndying: return 835; case Item::TraderLlamaSpawnEgg: return 741; case Item::TrappedChest: return 268; case Item::Trident: return 852; case Item::TripwireHook: return 238; case Item::TropicalFish: return 627; case Item::TropicalFishBucket: return 608; case Item::TropicalFishSpawnEgg: return 742; case Item::TubeCoral: return 456; case Item::TubeCoralBlock: return 451; case Item::TubeCoralFan: return 466; case Item::TurtleEgg: return 445; case Item::TurtleHelmet: return 518; case Item::TurtleSpawnEgg: return 743; case Item::VexSpawnEgg: return 744; case Item::VillagerSpawnEgg: return 745; case Item::VindicatorSpawnEgg: return 746; case Item::Vine: return 215; case Item::WanderingTraderSpawnEgg: return 747; case Item::WaterBucket: return 596; case Item::WetSponge: return 63; case Item::Wheat: return 561; case Item::WheatSeeds: return 560; case Item::WhiteBanner: return 801; case Item::WhiteBed: return 654; case Item::WhiteCarpet: return 300; case Item::WhiteConcrete: return 413; case Item::WhiteConcretePowder: return 429; case Item::WhiteDye: return 650; case Item::WhiteGlazedTerracotta: return 397; case Item::WhiteShulkerBox: return 381; case Item::WhiteStainedGlass: return 329; case Item::WhiteStainedGlassPane: return 345; case Item::WhiteTerracotta: return 281; case Item::WhiteTulip: return 105; case Item::WhiteWool: return 82; case Item::WitchSpawnEgg: return 748; case Item::WitherRose: return 110; case Item::WitherSkeletonSkull: return 769; case Item::WitherSkeletonSpawnEgg: return 749; case Item::WolfSpawnEgg: return 750; case Item::WoodenAxe: return 536; case Item::WoodenHoe: return 555; case Item::WoodenPickaxe: return 535; case Item::WoodenShovel: return 534; case Item::WoodenSword: return 533; case Item::WritableBook: return 757; case Item::WrittenBook: return 758; case Item::YellowBanner: return 805; case Item::YellowBed: return 658; case Item::YellowCarpet: return 304; case Item::YellowConcrete: return 417; case Item::YellowConcretePowder: return 433; case Item::YellowDye: return 642; case Item::YellowGlazedTerracotta: return 401; case Item::YellowShulkerBox: return 385; case Item::YellowStainedGlass: return 333; case Item::YellowStainedGlassPane: return 349; case Item::YellowTerracotta: return 285; case Item::YellowWool: return 86; case Item::ZombieHead: return 771; case Item::ZombieHorseSpawnEgg: return 752; case Item::ZombiePigmanSpawnEgg: return 753; case Item::ZombieSpawnEgg: return 751; case Item::ZombieVillagerSpawnEgg: return 754; default: return 0; } } UInt32 From(const CustomStatistic ID) { switch (ID) { case CustomStatistic::AnimalsBred: return 30; case CustomStatistic::AviateOneCm: return 17; case CustomStatistic::BellRing: return 66; case CustomStatistic::BoatOneCm: return 14; case CustomStatistic::CleanArmor: return 38; case CustomStatistic::CleanBanner: return 39; case CustomStatistic::CleanShulkerBox: return 40; case CustomStatistic::ClimbOneCm: return 10; case CustomStatistic::CrouchOneCm: return 6; case CustomStatistic::DamageAbsorbed: return 26; case CustomStatistic::DamageBlockedByShield: return 25; case CustomStatistic::DamageDealt: return 21; case CustomStatistic::DamageDealtAbsorbed: return 22; case CustomStatistic::DamageDealtResisted: return 23; case CustomStatistic::DamageResisted: return 27; case CustomStatistic::DamageTaken: return 24; case CustomStatistic::Deaths: return 28; case CustomStatistic::Drop: return 20; case CustomStatistic::EatCakeSlice: return 35; case CustomStatistic::EnchantItem: return 51; case CustomStatistic::FallOneCm: return 9; case CustomStatistic::FillCauldron: return 36; case CustomStatistic::FishCaught: return 32; case CustomStatistic::FlyOneCm: return 11; case CustomStatistic::HorseOneCm: return 16; case CustomStatistic::InspectDispenser: return 45; case CustomStatistic::InspectDropper: return 43; case CustomStatistic::InspectHopper: return 44; case CustomStatistic::InteractWithBeacon: return 42; case CustomStatistic::InteractWithBlastFurnace: return 59; case CustomStatistic::InteractWithBrewingstand: return 41; case CustomStatistic::InteractWithCampfire: return 62; case CustomStatistic::InteractWithCartographyTable: return 63; case CustomStatistic::InteractWithCraftingTable: return 54; case CustomStatistic::InteractWithFurnace: return 53; case CustomStatistic::InteractWithLectern: return 61; case CustomStatistic::InteractWithLoom: return 64; case CustomStatistic::InteractWithSmoker: return 60; case CustomStatistic::InteractWithStonecutter: return 65; case CustomStatistic::Jump: return 19; case CustomStatistic::LeaveGame: return 0; case CustomStatistic::MinecartOneCm: return 13; case CustomStatistic::MobKills: return 29; case CustomStatistic::OpenBarrel: return 58; case CustomStatistic::OpenChest: return 55; case CustomStatistic::OpenEnderchest: return 50; case CustomStatistic::OpenShulkerBox: return 57; case CustomStatistic::PigOneCm: return 15; case CustomStatistic::PlayerKills: return 31; case CustomStatistic::PlayNoteblock: return 46; case CustomStatistic::PlayOneMinute: return 1; case CustomStatistic::PlayRecord: return 52; case CustomStatistic::PotFlower: return 48; case CustomStatistic::RaidTrigger: return 67; case CustomStatistic::RaidWin: return 68; case CustomStatistic::SleepInBed: return 56; case CustomStatistic::SneakTime: return 4; case CustomStatistic::SprintOneCm: return 7; case CustomStatistic::SwimOneCm: return 18; case CustomStatistic::TalkedToVillager: return 33; case CustomStatistic::TimeSinceDeath: return 2; case CustomStatistic::TimeSinceRest: return 3; case CustomStatistic::TradedWithVillager: return 34; case CustomStatistic::TriggerTrappedChest: return 49; case CustomStatistic::TuneNoteblock: return 47; case CustomStatistic::UseCauldron: return 37; case CustomStatistic::WalkOneCm: return 5; case CustomStatistic::WalkOnWaterOneCm: return 8; case CustomStatistic::WalkUnderWaterOneCm: return 12; default: return static_cast(-1); } } Item ToItem(const UInt32 ID) { switch (ID) { case 833: return Item::AcaciaBoat; case 263: return Item::AcaciaButton; case 511: return Item::AcaciaDoor; case 185: return Item::AcaciaFence; case 220: return Item::AcaciaFenceGate; case 60: return Item::AcaciaLeaves; case 36: return Item::AcaciaLog; case 17: return Item::AcaciaPlanks; case 170: return Item::AcaciaPressurePlate; case 23: return Item::AcaciaSapling; case 593: return Item::AcaciaSign; case 119: return Item::AcaciaSlab; case 319: return Item::AcaciaStairs; case 197: return Item::AcaciaTrapdoor; case 54: return Item::AcaciaWood; case 279: return Item::ActivatorRail; case -0: return Item::Air; case 101: return Item::Allium; case 6: return Item::Andesite; case 501: return Item::AndesiteSlab; case 488: return Item::AndesiteStairs; case 254: return Item::AndesiteWall; case 265: return Item::Anvil; case 524: return Item::Apple; case 791: return Item::ArmorStand; case 526: return Item::Arrow; case 102: return Item::AzureBluet; case 764: return Item::BakedPotato; case 614: return Item::Bamboo; case 864: return Item::Barrel; case 297: return Item::Barrier; case 697: return Item::BatSpawnEgg; case 244: return Item::Beacon; case 25: return Item::Bedrock; case 677: return Item::Beef; case 820: return Item::Beetroot; case 821: return Item::BeetrootSeeds; case 822: return Item::BeetrootSoup; case 873: return Item::Bell; case 831: return Item::BirchBoat; case 261: return Item::BirchButton; case 509: return Item::BirchDoor; case 183: return Item::BirchFence; case 218: return Item::BirchFenceGate; case 58: return Item::BirchLeaves; case 34: return Item::BirchLog; case 15: return Item::BirchPlanks; case 168: return Item::BirchPressurePlate; case 21: return Item::BirchSapling; case 591: return Item::BirchSign; case 117: return Item::BirchSlab; case 241: return Item::BirchStairs; case 195: return Item::BirchTrapdoor; case 52: return Item::BirchWood; case 816: return Item::BlackBanner; case 669: return Item::BlackBed; case 315: return Item::BlackCarpet; case 428: return Item::BlackConcrete; case 444: return Item::BlackConcretePowder; case 649: return Item::BlackDye; case 412: return Item::BlackGlazedTerracotta; case 396: return Item::BlackShulkerBox; case 344: return Item::BlackStainedGlass; case 360: return Item::BlackStainedGlassPane; case 296: return Item::BlackTerracotta; case 97: return Item::BlackWool; case 866: return Item::BlastFurnace; case 691: return Item::BlazePowder; case 683: return Item::BlazeRod; case 698: return Item::BlazeSpawnEgg; case 812: return Item::BlueBanner; case 665: return Item::BlueBed; case 311: return Item::BlueCarpet; case 424: return Item::BlueConcrete; case 440: return Item::BlueConcretePowder; case 647: return Item::BlueDye; case 408: return Item::BlueGlazedTerracotta; case 476: return Item::BlueIce; case 100: return Item::BlueOrchid; case 392: return Item::BlueShulkerBox; case 340: return Item::BlueStainedGlass; case 356: return Item::BlueStainedGlassPane; case 292: return Item::BlueTerracotta; case 93: return Item::BlueWool; case 651: return Item::Bone; case 377: return Item::BoneBlock; case 646: return Item::BoneMeal; case 616: return Item::Book; case 143: return Item::Bookshelf; case 525: return Item::Bow; case 546: return Item::Bowl; case 457: return Item::BrainCoral; case 452: return Item::BrainCoralBlock; case 467: return Item::BrainCoralFan; case 562: return Item::Bread; case 693: return Item::BrewingStand; case 609: return Item::Brick; case 127: return Item::BrickSlab; case 222: return Item::BrickStairs; case 247: return Item::BrickWall; case 141: return Item::Bricks; case 813: return Item::BrownBanner; case 666: return Item::BrownBed; case 312: return Item::BrownCarpet; case 425: return Item::BrownConcrete; case 441: return Item::BrownConcretePowder; case 648: return Item::BrownDye; case 409: return Item::BrownGlazedTerracotta; case 111: return Item::BrownMushroom; case 209: return Item::BrownMushroomBlock; case 393: return Item::BrownShulkerBox; case 341: return Item::BrownStainedGlass; case 357: return Item::BrownStainedGlassPane; case 293: return Item::BrownTerracotta; case 94: return Item::BrownWool; case 458: return Item::BubbleCoral; case 453: return Item::BubbleCoralBlock; case 468: return Item::BubbleCoralFan; case 595: return Item::Bucket; case 178: return Item::Cactus; case 653: return Item::Cake; case 876: return Item::Campfire; case 762: return Item::Carrot; case 774: return Item::CarrotOnAStick; case 867: return Item::CartographyTable; case 188: return Item::CarvedPumpkin; case 699: return Item::CatSpawnEgg; case 694: return Item::Cauldron; case 700: return Item::CaveSpiderSpawnEgg; case 373: return Item::ChainCommandBlock; case 570: return Item::ChainmailBoots; case 568: return Item::ChainmailChestplate; case 567: return Item::ChainmailHelmet; case 569: return Item::ChainmailLeggings; case 528: return Item::Charcoal; case 155: return Item::Chest; case 618: return Item::ChestMinecart; case 679: return Item::Chicken; case 701: return Item::ChickenSpawnEgg; case 266: return Item::ChippedAnvil; case 275: return Item::ChiseledQuartzBlock; case 369: return Item::ChiseledRedSandstone; case 69: return Item::ChiseledSandstone; case 208: return Item::ChiseledStoneBricks; case 149: return Item::ChorusFlower; case 818: return Item::ChorusFruit; case 148: return Item::ChorusPlant; case 179: return Item::Clay; case 610: return Item::ClayBall; case 623: return Item::Clock; case 527: return Item::Coal; case 317: return Item::CoalBlock; case 31: return Item::CoalOre; case 10: return Item::CoarseDirt; case 12: return Item::Cobblestone; case 126: return Item::CobblestoneSlab; case 163: return Item::CobblestoneStairs; case 245: return Item::CobblestoneWall; case 75: return Item::Cobweb; case 634: return Item::CocoaBeans; case 625: return Item::Cod; case 607: return Item::CodBucket; case 702: return Item::CodSpawnEgg; case 243: return Item::CommandBlock; case 798: return Item::CommandBlockMinecart; case 514: return Item::Comparator; case 621: return Item::Compass; case 517: return Item::Composter; case 477: return Item::Conduit; case 678: return Item::CookedBeef; case 680: return Item::CookedChicken; case 629: return Item::CookedCod; case 800: return Item::CookedMutton; case 585: return Item::CookedPorkchop; case 787: return Item::CookedRabbit; case 630: return Item::CookedSalmon; case 670: return Item::Cookie; case 108: return Item::Cornflower; case 703: return Item::CowSpawnEgg; case 207: return Item::CrackedStoneBricks; case 158: return Item::CraftingTable; case 860: return Item::CreeperBannerPattern; case 772: return Item::CreeperHead; case 704: return Item::CreeperSpawnEgg; case 856: return Item::Crossbow; case 370: return Item::CutRedSandstone; case 132: return Item::CutRedSandstoneSlab; case 70: return Item::CutSandstone; case 124: return Item::CutSandstoneSlab; case 810: return Item::CyanBanner; case 663: return Item::CyanBed; case 309: return Item::CyanCarpet; case 422: return Item::CyanConcrete; case 438: return Item::CyanConcretePowder; case 637: return Item::CyanDye; case 406: return Item::CyanGlazedTerracotta; case 390: return Item::CyanShulkerBox; case 338: return Item::CyanStainedGlass; case 354: return Item::CyanStainedGlassPane; case 290: return Item::CyanTerracotta; case 91: return Item::CyanWool; case 267: return Item::DamagedAnvil; case 98: return Item::Dandelion; case 834: return Item::DarkOakBoat; case 264: return Item::DarkOakButton; case 512: return Item::DarkOakDoor; case 186: return Item::DarkOakFence; case 221: return Item::DarkOakFenceGate; case 61: return Item::DarkOakLeaves; case 37: return Item::DarkOakLog; case 18: return Item::DarkOakPlanks; case 171: return Item::DarkOakPressurePlate; case 24: return Item::DarkOakSapling; case 594: return Item::DarkOakSign; case 120: return Item::DarkOakSlab; case 320: return Item::DarkOakStairs; case 198: return Item::DarkOakTrapdoor; case 55: return Item::DarkOakWood; case 363: return Item::DarkPrismarine; case 136: return Item::DarkPrismarineSlab; case 366: return Item::DarkPrismarineStairs; case 271: return Item::DaylightDetector; case 461: return Item::DeadBrainCoral; case 447: return Item::DeadBrainCoralBlock; case 472: return Item::DeadBrainCoralFan; case 462: return Item::DeadBubbleCoral; case 448: return Item::DeadBubbleCoralBlock; case 473: return Item::DeadBubbleCoralFan; case 78: return Item::DeadBush; case 463: return Item::DeadFireCoral; case 449: return Item::DeadFireCoralBlock; case 474: return Item::DeadFireCoralFan; case 464: return Item::DeadHornCoral; case 450: return Item::DeadHornCoralBlock; case 475: return Item::DeadHornCoralFan; case 465: return Item::DeadTubeCoral; case 446: return Item::DeadTubeCoralBlock; case 471: return Item::DeadTubeCoralFan; case 839: return Item::DebugStick; case 73: return Item::DetectorRail; case 529: return Item::Diamond; case 544: return Item::DiamondAxe; case 157: return Item::DiamondBlock; case 578: return Item::DiamondBoots; case 576: return Item::DiamondChestplate; case 575: return Item::DiamondHelmet; case 558: return Item::DiamondHoe; case 794: return Item::DiamondHorseArmor; case 577: return Item::DiamondLeggings; case 156: return Item::DiamondOre; case 543: return Item::DiamondPickaxe; case 542: return Item::DiamondShovel; case 541: return Item::DiamondSword; case 4: return Item::Diorite; case 504: return Item::DioriteSlab; case 491: return Item::DioriteStairs; case 258: return Item::DioriteWall; case 9: return Item::Dirt; case 67: return Item::Dispenser; case 705: return Item::DolphinSpawnEgg; case 706: return Item::DonkeySpawnEgg; case 823: return Item::DragonBreath; case 233: return Item::DragonEgg; case 773: return Item::DragonHead; case 674: return Item::DriedKelp; case 613: return Item::DriedKelpBlock; case 280: return Item::Dropper; case 707: return Item::DrownedSpawnEgg; case 620: return Item::Egg; case 708: return Item::ElderGuardianSpawnEgg; case 829: return Item::Elytra; case 759: return Item::Emerald; case 239: return Item::EmeraldBlock; case 236: return Item::EmeraldOre; case 779: return Item::EnchantedBook; case 588: return Item::EnchantedGoldenApple; case 229: return Item::EnchantingTable; case 817: return Item::EndCrystal; case 230: return Item::EndPortalFrame; case 147: return Item::EndRod; case 231: return Item::EndStone; case 497: return Item::EndStoneBrickSlab; case 483: return Item::EndStoneBrickStairs; case 257: return Item::EndStoneBrickWall; case 232: return Item::EndStoneBricks; case 237: return Item::EnderChest; case 695: return Item::EnderEye; case 682: return Item::EnderPearl; case 709: return Item::EndermanSpawnEgg; case 710: return Item::EndermiteSpawnEgg; case 711: return Item::EvokerSpawnEgg; case 755: return Item::ExperienceBottle; case 159: return Item::Farmland; case 553: return Item::Feather; case 690: return Item::FermentedSpiderEye; case 77: return Item::Fern; case 671: return Item::FilledMap; case 756: return Item::FireCharge; case 459: return Item::FireCoral; case 454: return Item::FireCoralBlock; case 469: return Item::FireCoralFan; case 777: return Item::FireworkRocket; case 778: return Item::FireworkStar; case 622: return Item::FishingRod; case 868: return Item::FletchingTable; case 583: return Item::Flint; case 523: return Item::FlintAndSteel; case 859: return Item::FlowerBannerPattern; case 761: return Item::FlowerPot; case 712: return Item::FoxSpawnEgg; case 160: return Item::Furnace; case 619: return Item::FurnaceMinecart; case 713: return Item::GhastSpawnEgg; case 684: return Item::GhastTear; case 64: return Item::Glass; case 688: return Item::GlassBottle; case 213: return Item::GlassPane; case 696: return Item::GlisteringMelonSlice; case 863: return Item::GlobeBannerPattern; case 191: return Item::Glowstone; case 624: return Item::GlowstoneDust; case 113: return Item::GoldBlock; case 531: return Item::GoldIngot; case 685: return Item::GoldNugget; case 29: return Item::GoldOre; case 587: return Item::GoldenApple; case 551: return Item::GoldenAxe; case 582: return Item::GoldenBoots; case 767: return Item::GoldenCarrot; case 580: return Item::GoldenChestplate; case 579: return Item::GoldenHelmet; case 559: return Item::GoldenHoe; case 793: return Item::GoldenHorseArmor; case 581: return Item::GoldenLeggings; case 550: return Item::GoldenPickaxe; case 549: return Item::GoldenShovel; case 548: return Item::GoldenSword; case 2: return Item::Granite; case 500: return Item::GraniteSlab; case 487: return Item::GraniteStairs; case 251: return Item::GraniteWall; case 76: return Item::Grass; case 8: return Item::GrassBlock; case 322: return Item::GrassPath; case 28: return Item::Gravel; case 808: return Item::GrayBanner; case 661: return Item::GrayBed; case 307: return Item::GrayCarpet; case 420: return Item::GrayConcrete; case 436: return Item::GrayConcretePowder; case 639: return Item::GrayDye; case 404: return Item::GrayGlazedTerracotta; case 388: return Item::GrayShulkerBox; case 336: return Item::GrayStainedGlass; case 352: return Item::GrayStainedGlassPane; case 288: return Item::GrayTerracotta; case 89: return Item::GrayWool; case 814: return Item::GreenBanner; case 667: return Item::GreenBed; case 313: return Item::GreenCarpet; case 426: return Item::GreenConcrete; case 442: return Item::GreenConcretePowder; case 633: return Item::GreenDye; case 410: return Item::GreenGlazedTerracotta; case 394: return Item::GreenShulkerBox; case 342: return Item::GreenStainedGlass; case 358: return Item::GreenStainedGlassPane; case 294: return Item::GreenTerracotta; case 95: return Item::GreenWool; case 869: return Item::Grindstone; case 714: return Item::GuardianSpawnEgg; case 554: return Item::Gunpowder; case 299: return Item::HayBale; case 855: return Item::HeartOfTheSea; case 270: return Item::HeavyWeightedPressurePlate; case 274: return Item::Hopper; case 783: return Item::HopperMinecart; case 460: return Item::HornCoral; case 455: return Item::HornCoralBlock; case 470: return Item::HornCoralFan; case 715: return Item::HorseSpawnEgg; case 716: return Item::HuskSpawnEgg; case 176: return Item::Ice; case 204: return Item::InfestedChiseledStoneBricks; case 200: return Item::InfestedCobblestone; case 203: return Item::InfestedCrackedStoneBricks; case 202: return Item::InfestedMossyStoneBricks; case 199: return Item::InfestedStone; case 201: return Item::InfestedStoneBricks; case 631: return Item::InkSac; case 522: return Item::IronAxe; case 212: return Item::IronBars; case 114: return Item::IronBlock; case 574: return Item::IronBoots; case 572: return Item::IronChestplate; case 506: return Item::IronDoor; case 571: return Item::IronHelmet; case 557: return Item::IronHoe; case 792: return Item::IronHorseArmor; case 530: return Item::IronIngot; case 573: return Item::IronLeggings; case 837: return Item::IronNugget; case 30: return Item::IronOre; case 521: return Item::IronPickaxe; case 520: return Item::IronShovel; case 532: return Item::IronSword; case 298: return Item::IronTrapdoor; case 760: return Item::ItemFrame; case 192: return Item::JackOLantern; case 516: return Item::Jigsaw; case 180: return Item::Jukebox; case 832: return Item::JungleBoat; case 262: return Item::JungleButton; case 510: return Item::JungleDoor; case 184: return Item::JungleFence; case 219: return Item::JungleFenceGate; case 59: return Item::JungleLeaves; case 35: return Item::JungleLog; case 16: return Item::JunglePlanks; case 169: return Item::JunglePressurePlate; case 22: return Item::JungleSapling; case 592: return Item::JungleSign; case 118: return Item::JungleSlab; case 242: return Item::JungleStairs; case 196: return Item::JungleTrapdoor; case 53: return Item::JungleWood; case 612: return Item::Kelp; case 838: return Item::KnowledgeBook; case 161: return Item::Ladder; case 874: return Item::Lantern; case 66: return Item::LapisBlock; case 635: return Item::LapisLazuli; case 65: return Item::LapisOre; case 328: return Item::LargeFern; case 597: return Item::LavaBucket; case 796: return Item::Lead; case 603: return Item::Leather; case 566: return Item::LeatherBoots; case 564: return Item::LeatherChestplate; case 563: return Item::LeatherHelmet; case 795: return Item::LeatherHorseArmor; case 565: return Item::LeatherLeggings; case 870: return Item::Lectern; case 164: return Item::Lever; case 804: return Item::LightBlueBanner; case 657: return Item::LightBlueBed; case 303: return Item::LightBlueCarpet; case 416: return Item::LightBlueConcrete; case 432: return Item::LightBlueConcretePowder; case 643: return Item::LightBlueDye; case 400: return Item::LightBlueGlazedTerracotta; case 384: return Item::LightBlueShulkerBox; case 332: return Item::LightBlueStainedGlass; case 348: return Item::LightBlueStainedGlassPane; case 284: return Item::LightBlueTerracotta; case 85: return Item::LightBlueWool; case 809: return Item::LightGrayBanner; case 662: return Item::LightGrayBed; case 308: return Item::LightGrayCarpet; case 421: return Item::LightGrayConcrete; case 437: return Item::LightGrayConcretePowder; case 638: return Item::LightGrayDye; case 405: return Item::LightGrayGlazedTerracotta; case 389: return Item::LightGrayShulkerBox; case 337: return Item::LightGrayStainedGlass; case 353: return Item::LightGrayStainedGlassPane; case 289: return Item::LightGrayTerracotta; case 90: return Item::LightGrayWool; case 269: return Item::LightWeightedPressurePlate; case 324: return Item::Lilac; case 109: return Item::LilyOfTheValley; case 225: return Item::LilyPad; case 806: return Item::LimeBanner; case 659: return Item::LimeBed; case 305: return Item::LimeCarpet; case 418: return Item::LimeConcrete; case 434: return Item::LimeConcretePowder; case 641: return Item::LimeDye; case 402: return Item::LimeGlazedTerracotta; case 386: return Item::LimeShulkerBox; case 334: return Item::LimeStainedGlass; case 350: return Item::LimeStainedGlassPane; case 286: return Item::LimeTerracotta; case 87: return Item::LimeWool; case 827: return Item::LingeringPotion; case 717: return Item::LlamaSpawnEgg; case 858: return Item::Loom; case 803: return Item::MagentaBanner; case 656: return Item::MagentaBed; case 302: return Item::MagentaCarpet; case 415: return Item::MagentaConcrete; case 431: return Item::MagentaConcretePowder; case 644: return Item::MagentaDye; case 399: return Item::MagentaGlazedTerracotta; case 383: return Item::MagentaShulkerBox; case 331: return Item::MagentaStainedGlass; case 347: return Item::MagentaStainedGlassPane; case 283: return Item::MagentaTerracotta; case 84: return Item::MagentaWool; case 374: return Item::MagmaBlock; case 692: return Item::MagmaCream; case 718: return Item::MagmaCubeSpawnEgg; case 766: return Item::Map; case 214: return Item::Melon; case 676: return Item::MelonSeeds; case 673: return Item::MelonSlice; case 604: return Item::MilkBucket; case 598: return Item::Minecart; case 862: return Item::MojangBannerPattern; case 719: return Item::MooshroomSpawnEgg; case 144: return Item::MossyCobblestone; case 496: return Item::MossyCobblestoneSlab; case 482: return Item::MossyCobblestoneStairs; case 246: return Item::MossyCobblestoneWall; case 494: return Item::MossyStoneBrickSlab; case 480: return Item::MossyStoneBrickStairs; case 250: return Item::MossyStoneBrickWall; case 206: return Item::MossyStoneBricks; case 720: return Item::MuleSpawnEgg; case 211: return Item::MushroomStem; case 547: return Item::MushroomStew; case 850: return Item::MusicDisc11; case 840: return Item::MusicDisc13; case 842: return Item::MusicDiscBlocks; case 841: return Item::MusicDiscCat; case 843: return Item::MusicDiscChirp; case 844: return Item::MusicDiscFar; case 845: return Item::MusicDiscMall; case 846: return Item::MusicDiscMellohi; case 847: return Item::MusicDiscStal; case 848: return Item::MusicDiscStrad; case 851: return Item::MusicDiscWait; case 849: return Item::MusicDiscWard; case 799: return Item::Mutton; case 224: return Item::Mycelium; case 797: return Item::NameTag; case 854: return Item::NautilusShell; case 780: return Item::NetherBrick; case 227: return Item::NetherBrickFence; case 129: return Item::NetherBrickSlab; case 228: return Item::NetherBrickStairs; case 253: return Item::NetherBrickWall; case 226: return Item::NetherBricks; case 273: return Item::NetherQuartzOre; case 775: return Item::NetherStar; case 686: return Item::NetherWart; case 375: return Item::NetherWartBlock; case 189: return Item::Netherrack; case 71: return Item::NoteBlock; case 602: return Item::OakBoat; case 259: return Item::OakButton; case 507: return Item::OakDoor; case 181: return Item::OakFence; case 216: return Item::OakFenceGate; case 56: return Item::OakLeaves; case 32: return Item::OakLog; case 13: return Item::OakPlanks; case 166: return Item::OakPressurePlate; case 19: return Item::OakSapling; case 589: return Item::OakSign; case 115: return Item::OakSlab; case 154: return Item::OakStairs; case 193: return Item::OakTrapdoor; case 50: return Item::OakWood; case 379: return Item::Observer; case 145: return Item::Obsidian; case 721: return Item::OcelotSpawnEgg; case 802: return Item::OrangeBanner; case 655: return Item::OrangeBed; case 301: return Item::OrangeCarpet; case 414: return Item::OrangeConcrete; case 430: return Item::OrangeConcretePowder; case 645: return Item::OrangeDye; case 398: return Item::OrangeGlazedTerracotta; case 382: return Item::OrangeShulkerBox; case 330: return Item::OrangeStainedGlass; case 346: return Item::OrangeStainedGlassPane; case 282: return Item::OrangeTerracotta; case 104: return Item::OrangeTulip; case 83: return Item::OrangeWool; case 107: return Item::OxeyeDaisy; case 318: return Item::PackedIce; case 586: return Item::Painting; case 722: return Item::PandaSpawnEgg; case 615: return Item::Paper; case 723: return Item::ParrotSpawnEgg; case 326: return Item::Peony; case 125: return Item::PetrifiedOakSlab; case 853: return Item::PhantomMembrane; case 724: return Item::PhantomSpawnEgg; case 725: return Item::PigSpawnEgg; case 726: return Item::PillagerSpawnEgg; case 807: return Item::PinkBanner; case 660: return Item::PinkBed; case 306: return Item::PinkCarpet; case 419: return Item::PinkConcrete; case 435: return Item::PinkConcretePowder; case 640: return Item::PinkDye; case 403: return Item::PinkGlazedTerracotta; case 387: return Item::PinkShulkerBox; case 335: return Item::PinkStainedGlass; case 351: return Item::PinkStainedGlassPane; case 287: return Item::PinkTerracotta; case 106: return Item::PinkTulip; case 88: return Item::PinkWool; case 81: return Item::Piston; case 770: return Item::PlayerHead; case 11: return Item::Podzol; case 765: return Item::PoisonousPotato; case 727: return Item::PolarBearSpawnEgg; case 7: return Item::PolishedAndesite; case 503: return Item::PolishedAndesiteSlab; case 490: return Item::PolishedAndesiteStairs; case 5: return Item::PolishedDiorite; case 495: return Item::PolishedDioriteSlab; case 481: return Item::PolishedDioriteStairs; case 3: return Item::PolishedGranite; case 492: return Item::PolishedGraniteSlab; case 478: return Item::PolishedGraniteStairs; case 819: return Item::PoppedChorusFruit; case 99: return Item::Poppy; case 584: return Item::Porkchop; case 763: return Item::Potato; case 687: return Item::Potion; case 72: return Item::PoweredRail; case 361: return Item::Prismarine; case 135: return Item::PrismarineBrickSlab; case 365: return Item::PrismarineBrickStairs; case 362: return Item::PrismarineBricks; case 785: return Item::PrismarineCrystals; case 784: return Item::PrismarineShard; case 134: return Item::PrismarineSlab; case 364: return Item::PrismarineStairs; case 248: return Item::PrismarineWall; case 628: return Item::Pufferfish; case 605: return Item::PufferfishBucket; case 728: return Item::PufferfishSpawnEgg; case 187: return Item::Pumpkin; case 776: return Item::PumpkinPie; case 675: return Item::PumpkinSeeds; case 811: return Item::PurpleBanner; case 664: return Item::PurpleBed; case 310: return Item::PurpleCarpet; case 423: return Item::PurpleConcrete; case 439: return Item::PurpleConcretePowder; case 636: return Item::PurpleDye; case 407: return Item::PurpleGlazedTerracotta; case 391: return Item::PurpleShulkerBox; case 339: return Item::PurpleStainedGlass; case 355: return Item::PurpleStainedGlassPane; case 291: return Item::PurpleTerracotta; case 92: return Item::PurpleWool; case 150: return Item::PurpurBlock; case 151: return Item::PurpurPillar; case 133: return Item::PurpurSlab; case 152: return Item::PurpurStairs; case 781: return Item::Quartz; case 276: return Item::QuartzBlock; case 277: return Item::QuartzPillar; case 130: return Item::QuartzSlab; case 278: return Item::QuartzStairs; case 786: return Item::Rabbit; case 789: return Item::RabbitFoot; case 790: return Item::RabbitHide; case 729: return Item::RabbitSpawnEgg; case 788: return Item::RabbitStew; case 162: return Item::Rail; case 730: return Item::RavagerSpawnEgg; case 815: return Item::RedBanner; case 668: return Item::RedBed; case 314: return Item::RedCarpet; case 427: return Item::RedConcrete; case 443: return Item::RedConcretePowder; case 632: return Item::RedDye; case 411: return Item::RedGlazedTerracotta; case 112: return Item::RedMushroom; case 210: return Item::RedMushroomBlock; case 502: return Item::RedNetherBrickSlab; case 489: return Item::RedNetherBrickStairs; case 255: return Item::RedNetherBrickWall; case 376: return Item::RedNetherBricks; case 27: return Item::RedSand; case 368: return Item::RedSandstone; case 131: return Item::RedSandstoneSlab; case 371: return Item::RedSandstoneStairs; case 249: return Item::RedSandstoneWall; case 395: return Item::RedShulkerBox; case 343: return Item::RedStainedGlass; case 359: return Item::RedStainedGlassPane; case 295: return Item::RedTerracotta; case 103: return Item::RedTulip; case 96: return Item::RedWool; case 600: return Item::Redstone; case 272: return Item::RedstoneBlock; case 234: return Item::RedstoneLamp; case 172: return Item::RedstoneOre; case 173: return Item::RedstoneTorch; case 513: return Item::Repeater; case 372: return Item::RepeatingCommandBlock; case 325: return Item::RoseBush; case 681: return Item::RottenFlesh; case 599: return Item::Saddle; case 626: return Item::Salmon; case 606: return Item::SalmonBucket; case 731: return Item::SalmonSpawnEgg; case 26: return Item::Sand; case 68: return Item::Sandstone; case 123: return Item::SandstoneSlab; case 235: return Item::SandstoneStairs; case 256: return Item::SandstoneWall; case 505: return Item::Scaffolding; case 519: return Item::Scute; case 367: return Item::SeaLantern; case 80: return Item::SeaPickle; case 79: return Item::Seagrass; case 672: return Item::Shears; case 732: return Item::SheepSpawnEgg; case 828: return Item::Shield; case 380: return Item::ShulkerBox; case 836: return Item::ShulkerShell; case 733: return Item::ShulkerSpawnEgg; case 734: return Item::SilverfishSpawnEgg; case 736: return Item::SkeletonHorseSpawnEgg; case 768: return Item::SkeletonSkull; case 735: return Item::SkeletonSpawnEgg; case 861: return Item::SkullBannerPattern; case 617: return Item::SlimeBall; case 321: return Item::SlimeBlock; case 737: return Item::SlimeSpawnEgg; case 871: return Item::SmithingTable; case 865: return Item::Smoker; case 137: return Item::SmoothQuartz; case 499: return Item::SmoothQuartzSlab; case 486: return Item::SmoothQuartzStairs; case 138: return Item::SmoothRedSandstone; case 493: return Item::SmoothRedSandstoneSlab; case 479: return Item::SmoothRedSandstoneStairs; case 139: return Item::SmoothSandstone; case 498: return Item::SmoothSandstoneSlab; case 485: return Item::SmoothSandstoneStairs; case 140: return Item::SmoothStone; case 122: return Item::SmoothStoneSlab; case 175: return Item::Snow; case 177: return Item::SnowBlock; case 601: return Item::Snowball; case 190: return Item::SoulSand; case 153: return Item::Spawner; case 825: return Item::SpectralArrow; case 689: return Item::SpiderEye; case 738: return Item::SpiderSpawnEgg; case 824: return Item::SplashPotion; case 62: return Item::Sponge; case 830: return Item::SpruceBoat; case 260: return Item::SpruceButton; case 508: return Item::SpruceDoor; case 182: return Item::SpruceFence; case 217: return Item::SpruceFenceGate; case 57: return Item::SpruceLeaves; case 33: return Item::SpruceLog; case 14: return Item::SprucePlanks; case 167: return Item::SprucePressurePlate; case 20: return Item::SpruceSapling; case 590: return Item::SpruceSign; case 116: return Item::SpruceSlab; case 240: return Item::SpruceStairs; case 194: return Item::SpruceTrapdoor; case 51: return Item::SpruceWood; case 739: return Item::SquidSpawnEgg; case 545: return Item::Stick; case 74: return Item::StickyPiston; case 1: return Item::Stone; case 540: return Item::StoneAxe; case 128: return Item::StoneBrickSlab; case 223: return Item::StoneBrickStairs; case 252: return Item::StoneBrickWall; case 205: return Item::StoneBricks; case 174: return Item::StoneButton; case 556: return Item::StoneHoe; case 539: return Item::StonePickaxe; case 165: return Item::StonePressurePlate; case 538: return Item::StoneShovel; case 121: return Item::StoneSlab; case 484: return Item::StoneStairs; case 537: return Item::StoneSword; case 872: return Item::Stonecutter; case 740: return Item::StraySpawnEgg; case 552: return Item::String; case 42: return Item::StrippedAcaciaLog; case 48: return Item::StrippedAcaciaWood; case 40: return Item::StrippedBirchLog; case 46: return Item::StrippedBirchWood; case 43: return Item::StrippedDarkOakLog; case 49: return Item::StrippedDarkOakWood; case 41: return Item::StrippedJungleLog; case 47: return Item::StrippedJungleWood; case 38: return Item::StrippedOakLog; case 44: return Item::StrippedOakWood; case 39: return Item::StrippedSpruceLog; case 45: return Item::StrippedSpruceWood; case 515: return Item::StructureBlock; case 378: return Item::StructureVoid; case 652: return Item::Sugar; case 611: return Item::SugarCane; case 323: return Item::Sunflower; case 857: return Item::SuspiciousStew; case 875: return Item::SweetBerries; case 327: return Item::TallGrass; case 316: return Item::Terracotta; case 826: return Item::TippedArrow; case 142: return Item::TNT; case 782: return Item::TNTMinecart; case 146: return Item::Torch; case 835: return Item::TotemOfUndying; case 741: return Item::TraderLlamaSpawnEgg; case 268: return Item::TrappedChest; case 852: return Item::Trident; case 238: return Item::TripwireHook; case 627: return Item::TropicalFish; case 608: return Item::TropicalFishBucket; case 742: return Item::TropicalFishSpawnEgg; case 456: return Item::TubeCoral; case 451: return Item::TubeCoralBlock; case 466: return Item::TubeCoralFan; case 445: return Item::TurtleEgg; case 518: return Item::TurtleHelmet; case 743: return Item::TurtleSpawnEgg; case 744: return Item::VexSpawnEgg; case 745: return Item::VillagerSpawnEgg; case 746: return Item::VindicatorSpawnEgg; case 215: return Item::Vine; case 747: return Item::WanderingTraderSpawnEgg; case 596: return Item::WaterBucket; case 63: return Item::WetSponge; case 561: return Item::Wheat; case 560: return Item::WheatSeeds; case 801: return Item::WhiteBanner; case 654: return Item::WhiteBed; case 300: return Item::WhiteCarpet; case 413: return Item::WhiteConcrete; case 429: return Item::WhiteConcretePowder; case 650: return Item::WhiteDye; case 397: return Item::WhiteGlazedTerracotta; case 381: return Item::WhiteShulkerBox; case 329: return Item::WhiteStainedGlass; case 345: return Item::WhiteStainedGlassPane; case 281: return Item::WhiteTerracotta; case 105: return Item::WhiteTulip; case 82: return Item::WhiteWool; case 748: return Item::WitchSpawnEgg; case 110: return Item::WitherRose; case 769: return Item::WitherSkeletonSkull; case 749: return Item::WitherSkeletonSpawnEgg; case 750: return Item::WolfSpawnEgg; case 536: return Item::WoodenAxe; case 555: return Item::WoodenHoe; case 535: return Item::WoodenPickaxe; case 534: return Item::WoodenShovel; case 533: return Item::WoodenSword; case 757: return Item::WritableBook; case 758: return Item::WrittenBook; case 805: return Item::YellowBanner; case 658: return Item::YellowBed; case 304: return Item::YellowCarpet; case 417: return Item::YellowConcrete; case 433: return Item::YellowConcretePowder; case 642: return Item::YellowDye; case 401: return Item::YellowGlazedTerracotta; case 385: return Item::YellowShulkerBox; case 333: return Item::YellowStainedGlass; case 349: return Item::YellowStainedGlassPane; case 285: return Item::YellowTerracotta; case 86: return Item::YellowWool; case 771: return Item::ZombieHead; case 752: return Item::ZombieHorseSpawnEgg; case 753: return Item::ZombiePigmanSpawnEgg; case 751: return Item::ZombieSpawnEgg; case 754: return Item::ZombieVillagerSpawnEgg; default: return Item::Air; } } } ================================================ FILE: src/Protocol/Palettes/Palette_1_14.h ================================================ #pragma once #include "BlockState.h" #include "Registries/Items.h" #include "Registries/CustomStatistics.h" namespace Palette_1_14 { UInt32 From(BlockState Block); UInt32 From(Item ID); UInt32 From(CustomStatistic ID); Item ToItem(UInt32 ID); } ================================================ FILE: src/Protocol/Palettes/Palette_1_15.cpp ================================================ #include "Globals.h" #include "Palette_1_15.h" #include "Registries/BlockStates.h" namespace Palette_1_15 { UInt32 From(const BlockState Block) { using namespace Block; switch (Block.ID) { case AcaciaButton::AcaciaButton(AcaciaButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5906; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5907; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5908; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5909; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, true).ID: return 5910; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, false).ID: return 5911; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, true).ID: return 5912; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, false).ID: return 5913; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5914; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5915; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5916; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5917; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, true).ID: return 5918; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, false).ID: return 5919; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, true).ID: return 5920; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, false).ID: return 5921; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5922; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5923; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5924; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5925; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, true).ID: return 5926; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, false).ID: return 5927; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, true).ID: return 5928; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, false).ID: return 5929; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, true, true).ID: return 8394; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, true, false).ID: return 8395; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, false, true).ID: return 8396; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, false, false).ID: return 8397; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, true, true).ID: return 8398; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, true, false).ID: return 8399; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, false, true).ID: return 8400; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, false, false).ID: return 8401; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, true, true).ID: return 8402; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, true, false).ID: return 8403; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, false, true).ID: return 8404; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, false, false).ID: return 8405; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, true, true).ID: return 8406; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, true, false).ID: return 8407; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, false, true).ID: return 8408; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, false, false).ID: return 8409; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, true, true).ID: return 8410; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, true, false).ID: return 8411; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, false, true).ID: return 8412; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, false, false).ID: return 8413; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, true, true).ID: return 8414; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, true, false).ID: return 8415; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, false, true).ID: return 8416; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, false, false).ID: return 8417; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, true, true).ID: return 8418; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, true, false).ID: return 8419; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, false, true).ID: return 8420; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, false, false).ID: return 8421; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, true, true).ID: return 8422; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, true, false).ID: return 8423; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, false, true).ID: return 8424; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, false, false).ID: return 8425; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, true, true).ID: return 8426; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, true, false).ID: return 8427; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, false, true).ID: return 8428; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, false, false).ID: return 8429; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, true, true).ID: return 8430; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, true, false).ID: return 8431; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, false, true).ID: return 8432; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, false, false).ID: return 8433; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, true, true).ID: return 8434; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, true, false).ID: return 8435; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, false, true).ID: return 8436; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, false, false).ID: return 8437; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, true, true).ID: return 8438; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, true, false).ID: return 8439; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, false, true).ID: return 8440; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, false, false).ID: return 8441; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, true, true).ID: return 8442; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, true, false).ID: return 8443; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, false, true).ID: return 8444; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, false, false).ID: return 8445; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, true, true).ID: return 8446; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, true, false).ID: return 8447; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, false, true).ID: return 8448; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, false, false).ID: return 8449; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, true, true).ID: return 8450; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, true, false).ID: return 8451; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, false, true).ID: return 8452; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, false, false).ID: return 8453; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, true, true).ID: return 8454; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, true, false).ID: return 8455; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, false, true).ID: return 8456; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, false, false).ID: return 8457; case AcaciaFence::AcaciaFence(true, true, true, true).ID: return 8140; case AcaciaFence::AcaciaFence(true, true, true, false).ID: return 8141; case AcaciaFence::AcaciaFence(true, true, false, true).ID: return 8144; case AcaciaFence::AcaciaFence(true, true, false, false).ID: return 8145; case AcaciaFence::AcaciaFence(true, false, true, true).ID: return 8148; case AcaciaFence::AcaciaFence(true, false, true, false).ID: return 8149; case AcaciaFence::AcaciaFence(true, false, false, true).ID: return 8152; case AcaciaFence::AcaciaFence(true, false, false, false).ID: return 8153; case AcaciaFence::AcaciaFence(false, true, true, true).ID: return 8156; case AcaciaFence::AcaciaFence(false, true, true, false).ID: return 8157; case AcaciaFence::AcaciaFence(false, true, false, true).ID: return 8160; case AcaciaFence::AcaciaFence(false, true, false, false).ID: return 8161; case AcaciaFence::AcaciaFence(false, false, true, true).ID: return 8164; case AcaciaFence::AcaciaFence(false, false, true, false).ID: return 8165; case AcaciaFence::AcaciaFence(false, false, false, true).ID: return 8168; case AcaciaFence::AcaciaFence(false, false, false, false).ID: return 8169; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZM, true, true, true).ID: return 7978; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZM, true, true, false).ID: return 7979; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZM, true, false, true).ID: return 7980; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZM, true, false, false).ID: return 7981; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, true).ID: return 7982; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, false).ID: return 7983; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, true).ID: return 7984; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, false).ID: return 7985; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZP, true, true, true).ID: return 7986; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZP, true, true, false).ID: return 7987; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZP, true, false, true).ID: return 7988; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZP, true, false, false).ID: return 7989; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, true).ID: return 7990; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, false).ID: return 7991; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, true).ID: return 7992; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, false).ID: return 7993; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XM, true, true, true).ID: return 7994; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XM, true, true, false).ID: return 7995; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XM, true, false, true).ID: return 7996; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XM, true, false, false).ID: return 7997; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, true).ID: return 7998; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, false).ID: return 7999; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, true).ID: return 8000; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, false).ID: return 8001; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XP, true, true, true).ID: return 8002; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XP, true, true, false).ID: return 8003; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XP, true, false, true).ID: return 8004; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XP, true, false, false).ID: return 8005; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, true).ID: return 8006; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, false).ID: return 8007; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, true).ID: return 8008; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, false).ID: return 8009; case AcaciaLeaves::AcaciaLeaves(1, true).ID: return 200; case AcaciaLeaves::AcaciaLeaves(1, false).ID: return 201; case AcaciaLeaves::AcaciaLeaves(2, true).ID: return 202; case AcaciaLeaves::AcaciaLeaves(2, false).ID: return 203; case AcaciaLeaves::AcaciaLeaves(3, true).ID: return 204; case AcaciaLeaves::AcaciaLeaves(3, false).ID: return 205; case AcaciaLeaves::AcaciaLeaves(4, true).ID: return 206; case AcaciaLeaves::AcaciaLeaves(4, false).ID: return 207; case AcaciaLeaves::AcaciaLeaves(5, true).ID: return 208; case AcaciaLeaves::AcaciaLeaves(5, false).ID: return 209; case AcaciaLeaves::AcaciaLeaves(6, true).ID: return 210; case AcaciaLeaves::AcaciaLeaves(6, false).ID: return 211; case AcaciaLeaves::AcaciaLeaves(7, true).ID: return 212; case AcaciaLeaves::AcaciaLeaves(7, false).ID: return 213; case AcaciaLog::AcaciaLog(AcaciaLog::Axis::X).ID: return 84; case AcaciaLog::AcaciaLog(AcaciaLog::Axis::Y).ID: return 85; case AcaciaLog::AcaciaLog(AcaciaLog::Axis::Z).ID: return 86; case AcaciaPlanks::AcaciaPlanks().ID: return 19; case AcaciaPressurePlate::AcaciaPressurePlate(true).ID: return 3879; case AcaciaPressurePlate::AcaciaPressurePlate(false).ID: return 3880; case AcaciaSapling::AcaciaSapling(0).ID: return 29; case AcaciaSapling::AcaciaSapling(1).ID: return 30; case AcaciaSign::AcaciaSign(0).ID: return 3476; case AcaciaSign::AcaciaSign(1).ID: return 3478; case AcaciaSign::AcaciaSign(2).ID: return 3480; case AcaciaSign::AcaciaSign(3).ID: return 3482; case AcaciaSign::AcaciaSign(4).ID: return 3484; case AcaciaSign::AcaciaSign(5).ID: return 3486; case AcaciaSign::AcaciaSign(6).ID: return 3488; case AcaciaSign::AcaciaSign(7).ID: return 3490; case AcaciaSign::AcaciaSign(8).ID: return 3492; case AcaciaSign::AcaciaSign(9).ID: return 3494; case AcaciaSign::AcaciaSign(10).ID: return 3496; case AcaciaSign::AcaciaSign(11).ID: return 3498; case AcaciaSign::AcaciaSign(12).ID: return 3500; case AcaciaSign::AcaciaSign(13).ID: return 3502; case AcaciaSign::AcaciaSign(14).ID: return 3504; case AcaciaSign::AcaciaSign(15).ID: return 3506; case AcaciaSlab::AcaciaSlab(AcaciaSlab::Type::Top).ID: return 7789; case AcaciaSlab::AcaciaSlab(AcaciaSlab::Type::Bottom).ID: return 7791; case AcaciaSlab::AcaciaSlab(AcaciaSlab::Type::Double).ID: return 7793; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZM, AcaciaStairs::Half::Top, AcaciaStairs::Shape::Straight).ID: return 6840; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZM, AcaciaStairs::Half::Top, AcaciaStairs::Shape::InnerLeft).ID: return 6842; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZM, AcaciaStairs::Half::Top, AcaciaStairs::Shape::InnerRight).ID: return 6844; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZM, AcaciaStairs::Half::Top, AcaciaStairs::Shape::OuterLeft).ID: return 6846; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZM, AcaciaStairs::Half::Top, AcaciaStairs::Shape::OuterRight).ID: return 6848; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZM, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::Straight).ID: return 6850; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZM, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::InnerLeft).ID: return 6852; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZM, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::InnerRight).ID: return 6854; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZM, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::OuterLeft).ID: return 6856; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZM, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::OuterRight).ID: return 6858; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZP, AcaciaStairs::Half::Top, AcaciaStairs::Shape::Straight).ID: return 6860; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZP, AcaciaStairs::Half::Top, AcaciaStairs::Shape::InnerLeft).ID: return 6862; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZP, AcaciaStairs::Half::Top, AcaciaStairs::Shape::InnerRight).ID: return 6864; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZP, AcaciaStairs::Half::Top, AcaciaStairs::Shape::OuterLeft).ID: return 6866; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZP, AcaciaStairs::Half::Top, AcaciaStairs::Shape::OuterRight).ID: return 6868; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZP, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::Straight).ID: return 6870; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZP, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::InnerLeft).ID: return 6872; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZP, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::InnerRight).ID: return 6874; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZP, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::OuterLeft).ID: return 6876; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZP, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::OuterRight).ID: return 6878; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XM, AcaciaStairs::Half::Top, AcaciaStairs::Shape::Straight).ID: return 6880; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XM, AcaciaStairs::Half::Top, AcaciaStairs::Shape::InnerLeft).ID: return 6882; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XM, AcaciaStairs::Half::Top, AcaciaStairs::Shape::InnerRight).ID: return 6884; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XM, AcaciaStairs::Half::Top, AcaciaStairs::Shape::OuterLeft).ID: return 6886; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XM, AcaciaStairs::Half::Top, AcaciaStairs::Shape::OuterRight).ID: return 6888; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XM, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::Straight).ID: return 6890; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XM, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::InnerLeft).ID: return 6892; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XM, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::InnerRight).ID: return 6894; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XM, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::OuterLeft).ID: return 6896; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XM, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::OuterRight).ID: return 6898; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XP, AcaciaStairs::Half::Top, AcaciaStairs::Shape::Straight).ID: return 6900; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XP, AcaciaStairs::Half::Top, AcaciaStairs::Shape::InnerLeft).ID: return 6902; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XP, AcaciaStairs::Half::Top, AcaciaStairs::Shape::InnerRight).ID: return 6904; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XP, AcaciaStairs::Half::Top, AcaciaStairs::Shape::OuterLeft).ID: return 6906; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XP, AcaciaStairs::Half::Top, AcaciaStairs::Shape::OuterRight).ID: return 6908; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XP, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::Straight).ID: return 6910; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XP, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::InnerLeft).ID: return 6912; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XP, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::InnerRight).ID: return 6914; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XP, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::OuterLeft).ID: return 6916; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XP, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::OuterRight).ID: return 6918; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZM, AcaciaTrapdoor::Half::Top, true, true).ID: return 4354; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZM, AcaciaTrapdoor::Half::Top, true, false).ID: return 4356; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZM, AcaciaTrapdoor::Half::Top, false, true).ID: return 4358; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZM, AcaciaTrapdoor::Half::Top, false, false).ID: return 4360; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZM, AcaciaTrapdoor::Half::Bottom, true, true).ID: return 4362; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZM, AcaciaTrapdoor::Half::Bottom, true, false).ID: return 4364; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZM, AcaciaTrapdoor::Half::Bottom, false, true).ID: return 4366; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZM, AcaciaTrapdoor::Half::Bottom, false, false).ID: return 4368; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZP, AcaciaTrapdoor::Half::Top, true, true).ID: return 4370; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZP, AcaciaTrapdoor::Half::Top, true, false).ID: return 4372; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZP, AcaciaTrapdoor::Half::Top, false, true).ID: return 4374; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZP, AcaciaTrapdoor::Half::Top, false, false).ID: return 4376; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZP, AcaciaTrapdoor::Half::Bottom, true, true).ID: return 4378; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZP, AcaciaTrapdoor::Half::Bottom, true, false).ID: return 4380; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZP, AcaciaTrapdoor::Half::Bottom, false, true).ID: return 4382; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZP, AcaciaTrapdoor::Half::Bottom, false, false).ID: return 4384; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XM, AcaciaTrapdoor::Half::Top, true, true).ID: return 4386; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XM, AcaciaTrapdoor::Half::Top, true, false).ID: return 4388; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XM, AcaciaTrapdoor::Half::Top, false, true).ID: return 4390; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XM, AcaciaTrapdoor::Half::Top, false, false).ID: return 4392; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XM, AcaciaTrapdoor::Half::Bottom, true, true).ID: return 4394; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XM, AcaciaTrapdoor::Half::Bottom, true, false).ID: return 4396; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XM, AcaciaTrapdoor::Half::Bottom, false, true).ID: return 4398; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XM, AcaciaTrapdoor::Half::Bottom, false, false).ID: return 4400; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XP, AcaciaTrapdoor::Half::Top, true, true).ID: return 4402; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XP, AcaciaTrapdoor::Half::Top, true, false).ID: return 4404; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XP, AcaciaTrapdoor::Half::Top, false, true).ID: return 4406; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XP, AcaciaTrapdoor::Half::Top, false, false).ID: return 4408; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XP, AcaciaTrapdoor::Half::Bottom, true, true).ID: return 4410; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XP, AcaciaTrapdoor::Half::Bottom, true, false).ID: return 4412; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XP, AcaciaTrapdoor::Half::Bottom, false, true).ID: return 4414; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XP, AcaciaTrapdoor::Half::Bottom, false, false).ID: return 4416; case AcaciaWallSign::AcaciaWallSign(eBlockFace::BLOCK_FACE_ZM).ID: return 3758; case AcaciaWallSign::AcaciaWallSign(eBlockFace::BLOCK_FACE_ZP).ID: return 3760; case AcaciaWallSign::AcaciaWallSign(eBlockFace::BLOCK_FACE_XM).ID: return 3762; case AcaciaWallSign::AcaciaWallSign(eBlockFace::BLOCK_FACE_XP).ID: return 3764; case AcaciaWood::AcaciaWood(AcaciaWood::Axis::X).ID: return 120; case AcaciaWood::AcaciaWood(AcaciaWood::Axis::Y).ID: return 121; case AcaciaWood::AcaciaWood(AcaciaWood::Axis::Z).ID: return 122; case ActivatorRail::ActivatorRail(true, ActivatorRail::Shape::NorthSouth).ID: return 6287; case ActivatorRail::ActivatorRail(true, ActivatorRail::Shape::EastWest).ID: return 6288; case ActivatorRail::ActivatorRail(true, ActivatorRail::Shape::AscendingEast).ID: return 6289; case ActivatorRail::ActivatorRail(true, ActivatorRail::Shape::AscendingWest).ID: return 6290; case ActivatorRail::ActivatorRail(true, ActivatorRail::Shape::AscendingNorth).ID: return 6291; case ActivatorRail::ActivatorRail(true, ActivatorRail::Shape::AscendingSouth).ID: return 6292; case ActivatorRail::ActivatorRail(false, ActivatorRail::Shape::NorthSouth).ID: return 6293; case ActivatorRail::ActivatorRail(false, ActivatorRail::Shape::EastWest).ID: return 6294; case ActivatorRail::ActivatorRail(false, ActivatorRail::Shape::AscendingEast).ID: return 6295; case ActivatorRail::ActivatorRail(false, ActivatorRail::Shape::AscendingWest).ID: return 6296; case ActivatorRail::ActivatorRail(false, ActivatorRail::Shape::AscendingNorth).ID: return 6297; case ActivatorRail::ActivatorRail(false, ActivatorRail::Shape::AscendingSouth).ID: return 6298; case Air::Air().ID: return -0; case Allium::Allium().ID: return 1414; case Andesite::Andesite().ID: return 6; case AndesiteSlab::AndesiteSlab(AndesiteSlab::Type::Top).ID: return 10308; case AndesiteSlab::AndesiteSlab(AndesiteSlab::Type::Bottom).ID: return 10310; case AndesiteSlab::AndesiteSlab(AndesiteSlab::Type::Double).ID: return 10312; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_ZM, AndesiteStairs::Half::Top, AndesiteStairs::Shape::Straight).ID: return 9934; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_ZM, AndesiteStairs::Half::Top, AndesiteStairs::Shape::InnerLeft).ID: return 9936; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_ZM, AndesiteStairs::Half::Top, AndesiteStairs::Shape::InnerRight).ID: return 9938; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_ZM, AndesiteStairs::Half::Top, AndesiteStairs::Shape::OuterLeft).ID: return 9940; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_ZM, AndesiteStairs::Half::Top, AndesiteStairs::Shape::OuterRight).ID: return 9942; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_ZM, AndesiteStairs::Half::Bottom, AndesiteStairs::Shape::Straight).ID: return 9944; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_ZM, AndesiteStairs::Half::Bottom, AndesiteStairs::Shape::InnerLeft).ID: return 9946; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_ZM, AndesiteStairs::Half::Bottom, AndesiteStairs::Shape::InnerRight).ID: return 9948; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_ZM, AndesiteStairs::Half::Bottom, AndesiteStairs::Shape::OuterLeft).ID: return 9950; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_ZM, AndesiteStairs::Half::Bottom, AndesiteStairs::Shape::OuterRight).ID: return 9952; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_ZP, AndesiteStairs::Half::Top, AndesiteStairs::Shape::Straight).ID: return 9954; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_ZP, AndesiteStairs::Half::Top, AndesiteStairs::Shape::InnerLeft).ID: return 9956; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_ZP, AndesiteStairs::Half::Top, AndesiteStairs::Shape::InnerRight).ID: return 9958; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_ZP, AndesiteStairs::Half::Top, AndesiteStairs::Shape::OuterLeft).ID: return 9960; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_ZP, AndesiteStairs::Half::Top, AndesiteStairs::Shape::OuterRight).ID: return 9962; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_ZP, AndesiteStairs::Half::Bottom, AndesiteStairs::Shape::Straight).ID: return 9964; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_ZP, AndesiteStairs::Half::Bottom, AndesiteStairs::Shape::InnerLeft).ID: return 9966; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_ZP, AndesiteStairs::Half::Bottom, AndesiteStairs::Shape::InnerRight).ID: return 9968; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_ZP, AndesiteStairs::Half::Bottom, AndesiteStairs::Shape::OuterLeft).ID: return 9970; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_ZP, AndesiteStairs::Half::Bottom, AndesiteStairs::Shape::OuterRight).ID: return 9972; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_XM, AndesiteStairs::Half::Top, AndesiteStairs::Shape::Straight).ID: return 9974; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_XM, AndesiteStairs::Half::Top, AndesiteStairs::Shape::InnerLeft).ID: return 9976; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_XM, AndesiteStairs::Half::Top, AndesiteStairs::Shape::InnerRight).ID: return 9978; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_XM, AndesiteStairs::Half::Top, AndesiteStairs::Shape::OuterLeft).ID: return 9980; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_XM, AndesiteStairs::Half::Top, AndesiteStairs::Shape::OuterRight).ID: return 9982; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_XM, AndesiteStairs::Half::Bottom, AndesiteStairs::Shape::Straight).ID: return 9984; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_XM, AndesiteStairs::Half::Bottom, AndesiteStairs::Shape::InnerLeft).ID: return 9986; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_XM, AndesiteStairs::Half::Bottom, AndesiteStairs::Shape::InnerRight).ID: return 9988; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_XM, AndesiteStairs::Half::Bottom, AndesiteStairs::Shape::OuterLeft).ID: return 9990; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_XM, AndesiteStairs::Half::Bottom, AndesiteStairs::Shape::OuterRight).ID: return 9992; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_XP, AndesiteStairs::Half::Top, AndesiteStairs::Shape::Straight).ID: return 9994; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_XP, AndesiteStairs::Half::Top, AndesiteStairs::Shape::InnerLeft).ID: return 9996; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_XP, AndesiteStairs::Half::Top, AndesiteStairs::Shape::InnerRight).ID: return 9998; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_XP, AndesiteStairs::Half::Top, AndesiteStairs::Shape::OuterLeft).ID: return 10000; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_XP, AndesiteStairs::Half::Top, AndesiteStairs::Shape::OuterRight).ID: return 10002; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_XP, AndesiteStairs::Half::Bottom, AndesiteStairs::Shape::Straight).ID: return 10004; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_XP, AndesiteStairs::Half::Bottom, AndesiteStairs::Shape::InnerLeft).ID: return 10006; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_XP, AndesiteStairs::Half::Bottom, AndesiteStairs::Shape::InnerRight).ID: return 10008; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_XP, AndesiteStairs::Half::Bottom, AndesiteStairs::Shape::OuterLeft).ID: return 10010; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_XP, AndesiteStairs::Half::Bottom, AndesiteStairs::Shape::OuterRight).ID: return 10012; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::Low, AndesiteWall::South::Low, true, AndesiteWall::West::Low).ID: return 10781; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::Low, AndesiteWall::South::Low, true, AndesiteWall::West::None).ID: return 10782; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::Low, AndesiteWall::South::Low, false, AndesiteWall::West::Low).ID: return 10785; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::Low, AndesiteWall::South::Low, false, AndesiteWall::West::None).ID: return 10786; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::Low, AndesiteWall::South::None, true, AndesiteWall::West::Low).ID: return 10789; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::Low, AndesiteWall::South::None, true, AndesiteWall::West::None).ID: return 10790; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::Low, AndesiteWall::South::None, false, AndesiteWall::West::Low).ID: return 10793; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::Low, AndesiteWall::South::None, false, AndesiteWall::West::None).ID: return 10794; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::None, AndesiteWall::South::Low, true, AndesiteWall::West::Low).ID: return 10797; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::None, AndesiteWall::South::Low, true, AndesiteWall::West::None).ID: return 10798; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::None, AndesiteWall::South::Low, false, AndesiteWall::West::Low).ID: return 10801; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::None, AndesiteWall::South::Low, false, AndesiteWall::West::None).ID: return 10802; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::None, AndesiteWall::South::None, true, AndesiteWall::West::Low).ID: return 10805; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::None, AndesiteWall::South::None, true, AndesiteWall::West::None).ID: return 10806; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::None, AndesiteWall::South::None, false, AndesiteWall::West::Low).ID: return 10809; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::None, AndesiteWall::South::None, false, AndesiteWall::West::None).ID: return 10810; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::Low, AndesiteWall::South::Low, true, AndesiteWall::West::Low).ID: return 10813; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::Low, AndesiteWall::South::Low, true, AndesiteWall::West::None).ID: return 10814; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::Low, AndesiteWall::South::Low, false, AndesiteWall::West::Low).ID: return 10817; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::Low, AndesiteWall::South::Low, false, AndesiteWall::West::None).ID: return 10818; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::Low, AndesiteWall::South::None, true, AndesiteWall::West::Low).ID: return 10821; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::Low, AndesiteWall::South::None, true, AndesiteWall::West::None).ID: return 10822; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::Low, AndesiteWall::South::None, false, AndesiteWall::West::Low).ID: return 10825; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::Low, AndesiteWall::South::None, false, AndesiteWall::West::None).ID: return 10826; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::None, AndesiteWall::South::Low, true, AndesiteWall::West::Low).ID: return 10829; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::None, AndesiteWall::South::Low, true, AndesiteWall::West::None).ID: return 10830; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::None, AndesiteWall::South::Low, false, AndesiteWall::West::Low).ID: return 10833; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::None, AndesiteWall::South::Low, false, AndesiteWall::West::None).ID: return 10834; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::None, AndesiteWall::South::None, true, AndesiteWall::West::Low).ID: return 10837; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::None, AndesiteWall::South::None, true, AndesiteWall::West::None).ID: return 10838; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::None, AndesiteWall::South::None, false, AndesiteWall::West::Low).ID: return 10841; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::None, AndesiteWall::South::None, false, AndesiteWall::West::None).ID: return 10842; case Anvil::Anvil(eBlockFace::BLOCK_FACE_ZM).ID: return 6074; case Anvil::Anvil(eBlockFace::BLOCK_FACE_ZP).ID: return 6075; case Anvil::Anvil(eBlockFace::BLOCK_FACE_XM).ID: return 6076; case Anvil::Anvil(eBlockFace::BLOCK_FACE_XP).ID: return 6077; case AttachedMelonStem::AttachedMelonStem(eBlockFace::BLOCK_FACE_ZM).ID: return 4752; case AttachedMelonStem::AttachedMelonStem(eBlockFace::BLOCK_FACE_ZP).ID: return 4753; case AttachedMelonStem::AttachedMelonStem(eBlockFace::BLOCK_FACE_XM).ID: return 4754; case AttachedMelonStem::AttachedMelonStem(eBlockFace::BLOCK_FACE_XP).ID: return 4755; case AttachedPumpkinStem::AttachedPumpkinStem(eBlockFace::BLOCK_FACE_ZM).ID: return 4748; case AttachedPumpkinStem::AttachedPumpkinStem(eBlockFace::BLOCK_FACE_ZP).ID: return 4749; case AttachedPumpkinStem::AttachedPumpkinStem(eBlockFace::BLOCK_FACE_XM).ID: return 4750; case AttachedPumpkinStem::AttachedPumpkinStem(eBlockFace::BLOCK_FACE_XP).ID: return 4751; case AzureBluet::AzureBluet().ID: return 1415; case Bamboo::Bamboo(0, Bamboo::Leaves::None, 0).ID: return 9116; case Bamboo::Bamboo(0, Bamboo::Leaves::None, 1).ID: return 9117; case Bamboo::Bamboo(0, Bamboo::Leaves::Small, 0).ID: return 9118; case Bamboo::Bamboo(0, Bamboo::Leaves::Small, 1).ID: return 9119; case Bamboo::Bamboo(0, Bamboo::Leaves::Large, 0).ID: return 9120; case Bamboo::Bamboo(0, Bamboo::Leaves::Large, 1).ID: return 9121; case Bamboo::Bamboo(1, Bamboo::Leaves::None, 0).ID: return 9122; case Bamboo::Bamboo(1, Bamboo::Leaves::None, 1).ID: return 9123; case Bamboo::Bamboo(1, Bamboo::Leaves::Small, 0).ID: return 9124; case Bamboo::Bamboo(1, Bamboo::Leaves::Small, 1).ID: return 9125; case Bamboo::Bamboo(1, Bamboo::Leaves::Large, 0).ID: return 9126; case Bamboo::Bamboo(1, Bamboo::Leaves::Large, 1).ID: return 9127; case BambooSapling::BambooSapling().ID: return 9115; case Barrel::Barrel(eBlockFace::BLOCK_FACE_ZM, true).ID: return 11135; case Barrel::Barrel(eBlockFace::BLOCK_FACE_ZM, false).ID: return 11136; case Barrel::Barrel(eBlockFace::BLOCK_FACE_XP, true).ID: return 11137; case Barrel::Barrel(eBlockFace::BLOCK_FACE_XP, false).ID: return 11138; case Barrel::Barrel(eBlockFace::BLOCK_FACE_ZP, true).ID: return 11139; case Barrel::Barrel(eBlockFace::BLOCK_FACE_ZP, false).ID: return 11140; case Barrel::Barrel(eBlockFace::BLOCK_FACE_XM, true).ID: return 11141; case Barrel::Barrel(eBlockFace::BLOCK_FACE_XM, false).ID: return 11142; case Barrel::Barrel(eBlockFace::BLOCK_FACE_YP, true).ID: return 11143; case Barrel::Barrel(eBlockFace::BLOCK_FACE_YP, false).ID: return 11144; case Barrel::Barrel(eBlockFace::BLOCK_FACE_YM, true).ID: return 11145; case Barrel::Barrel(eBlockFace::BLOCK_FACE_YM, false).ID: return 11146; case Barrier::Barrier().ID: return 7000; case Beacon::Beacon().ID: return 5640; case Bedrock::Bedrock().ID: return 33; case BeeNest::BeeNest(eBlockFace::BLOCK_FACE_ZM, 0).ID: return 11287; case BeeNest::BeeNest(eBlockFace::BLOCK_FACE_ZM, 1).ID: return 11288; case BeeNest::BeeNest(eBlockFace::BLOCK_FACE_ZM, 2).ID: return 11289; case BeeNest::BeeNest(eBlockFace::BLOCK_FACE_ZM, 3).ID: return 11290; case BeeNest::BeeNest(eBlockFace::BLOCK_FACE_ZM, 4).ID: return 11291; case BeeNest::BeeNest(eBlockFace::BLOCK_FACE_ZM, 5).ID: return 11292; case BeeNest::BeeNest(eBlockFace::BLOCK_FACE_ZP, 0).ID: return 11293; case BeeNest::BeeNest(eBlockFace::BLOCK_FACE_ZP, 1).ID: return 11294; case BeeNest::BeeNest(eBlockFace::BLOCK_FACE_ZP, 2).ID: return 11295; case BeeNest::BeeNest(eBlockFace::BLOCK_FACE_ZP, 3).ID: return 11296; case BeeNest::BeeNest(eBlockFace::BLOCK_FACE_ZP, 4).ID: return 11297; case BeeNest::BeeNest(eBlockFace::BLOCK_FACE_ZP, 5).ID: return 11298; case BeeNest::BeeNest(eBlockFace::BLOCK_FACE_XM, 0).ID: return 11299; case BeeNest::BeeNest(eBlockFace::BLOCK_FACE_XM, 1).ID: return 11300; case BeeNest::BeeNest(eBlockFace::BLOCK_FACE_XM, 2).ID: return 11301; case BeeNest::BeeNest(eBlockFace::BLOCK_FACE_XM, 3).ID: return 11302; case BeeNest::BeeNest(eBlockFace::BLOCK_FACE_XM, 4).ID: return 11303; case BeeNest::BeeNest(eBlockFace::BLOCK_FACE_XM, 5).ID: return 11304; case BeeNest::BeeNest(eBlockFace::BLOCK_FACE_XP, 0).ID: return 11305; case BeeNest::BeeNest(eBlockFace::BLOCK_FACE_XP, 1).ID: return 11306; case BeeNest::BeeNest(eBlockFace::BLOCK_FACE_XP, 2).ID: return 11307; case BeeNest::BeeNest(eBlockFace::BLOCK_FACE_XP, 3).ID: return 11308; case BeeNest::BeeNest(eBlockFace::BLOCK_FACE_XP, 4).ID: return 11309; case BeeNest::BeeNest(eBlockFace::BLOCK_FACE_XP, 5).ID: return 11310; case Beehive::Beehive(eBlockFace::BLOCK_FACE_ZM, 0).ID: return 11311; case Beehive::Beehive(eBlockFace::BLOCK_FACE_ZM, 1).ID: return 11312; case Beehive::Beehive(eBlockFace::BLOCK_FACE_ZM, 2).ID: return 11313; case Beehive::Beehive(eBlockFace::BLOCK_FACE_ZM, 3).ID: return 11314; case Beehive::Beehive(eBlockFace::BLOCK_FACE_ZM, 4).ID: return 11315; case Beehive::Beehive(eBlockFace::BLOCK_FACE_ZM, 5).ID: return 11316; case Beehive::Beehive(eBlockFace::BLOCK_FACE_ZP, 0).ID: return 11317; case Beehive::Beehive(eBlockFace::BLOCK_FACE_ZP, 1).ID: return 11318; case Beehive::Beehive(eBlockFace::BLOCK_FACE_ZP, 2).ID: return 11319; case Beehive::Beehive(eBlockFace::BLOCK_FACE_ZP, 3).ID: return 11320; case Beehive::Beehive(eBlockFace::BLOCK_FACE_ZP, 4).ID: return 11321; case Beehive::Beehive(eBlockFace::BLOCK_FACE_ZP, 5).ID: return 11322; case Beehive::Beehive(eBlockFace::BLOCK_FACE_XM, 0).ID: return 11323; case Beehive::Beehive(eBlockFace::BLOCK_FACE_XM, 1).ID: return 11324; case Beehive::Beehive(eBlockFace::BLOCK_FACE_XM, 2).ID: return 11325; case Beehive::Beehive(eBlockFace::BLOCK_FACE_XM, 3).ID: return 11326; case Beehive::Beehive(eBlockFace::BLOCK_FACE_XM, 4).ID: return 11327; case Beehive::Beehive(eBlockFace::BLOCK_FACE_XM, 5).ID: return 11328; case Beehive::Beehive(eBlockFace::BLOCK_FACE_XP, 0).ID: return 11329; case Beehive::Beehive(eBlockFace::BLOCK_FACE_XP, 1).ID: return 11330; case Beehive::Beehive(eBlockFace::BLOCK_FACE_XP, 2).ID: return 11331; case Beehive::Beehive(eBlockFace::BLOCK_FACE_XP, 3).ID: return 11332; case Beehive::Beehive(eBlockFace::BLOCK_FACE_XP, 4).ID: return 11333; case Beehive::Beehive(eBlockFace::BLOCK_FACE_XP, 5).ID: return 11334; case Beetroots::Beetroots(0).ID: return 8683; case Beetroots::Beetroots(1).ID: return 8684; case Beetroots::Beetroots(2).ID: return 8685; case Beetroots::Beetroots(3).ID: return 8686; case Bell::Bell(Bell::Attachment::Floor, eBlockFace::BLOCK_FACE_ZM, true).ID: return 11198; case Bell::Bell(Bell::Attachment::Floor, eBlockFace::BLOCK_FACE_ZM, false).ID: return 11199; case Bell::Bell(Bell::Attachment::Floor, eBlockFace::BLOCK_FACE_ZP, true).ID: return 11200; case Bell::Bell(Bell::Attachment::Floor, eBlockFace::BLOCK_FACE_ZP, false).ID: return 11201; case Bell::Bell(Bell::Attachment::Floor, eBlockFace::BLOCK_FACE_XM, true).ID: return 11202; case Bell::Bell(Bell::Attachment::Floor, eBlockFace::BLOCK_FACE_XM, false).ID: return 11203; case Bell::Bell(Bell::Attachment::Floor, eBlockFace::BLOCK_FACE_XP, true).ID: return 11204; case Bell::Bell(Bell::Attachment::Floor, eBlockFace::BLOCK_FACE_XP, false).ID: return 11205; case Bell::Bell(Bell::Attachment::Ceiling, eBlockFace::BLOCK_FACE_ZM, true).ID: return 11206; case Bell::Bell(Bell::Attachment::Ceiling, eBlockFace::BLOCK_FACE_ZM, false).ID: return 11207; case Bell::Bell(Bell::Attachment::Ceiling, eBlockFace::BLOCK_FACE_ZP, true).ID: return 11208; case Bell::Bell(Bell::Attachment::Ceiling, eBlockFace::BLOCK_FACE_ZP, false).ID: return 11209; case Bell::Bell(Bell::Attachment::Ceiling, eBlockFace::BLOCK_FACE_XM, true).ID: return 11210; case Bell::Bell(Bell::Attachment::Ceiling, eBlockFace::BLOCK_FACE_XM, false).ID: return 11211; case Bell::Bell(Bell::Attachment::Ceiling, eBlockFace::BLOCK_FACE_XP, true).ID: return 11212; case Bell::Bell(Bell::Attachment::Ceiling, eBlockFace::BLOCK_FACE_XP, false).ID: return 11213; case Bell::Bell(Bell::Attachment::SingleWall, eBlockFace::BLOCK_FACE_ZM, true).ID: return 11214; case Bell::Bell(Bell::Attachment::SingleWall, eBlockFace::BLOCK_FACE_ZM, false).ID: return 11215; case Bell::Bell(Bell::Attachment::SingleWall, eBlockFace::BLOCK_FACE_ZP, true).ID: return 11216; case Bell::Bell(Bell::Attachment::SingleWall, eBlockFace::BLOCK_FACE_ZP, false).ID: return 11217; case Bell::Bell(Bell::Attachment::SingleWall, eBlockFace::BLOCK_FACE_XM, true).ID: return 11218; case Bell::Bell(Bell::Attachment::SingleWall, eBlockFace::BLOCK_FACE_XM, false).ID: return 11219; case Bell::Bell(Bell::Attachment::SingleWall, eBlockFace::BLOCK_FACE_XP, true).ID: return 11220; case Bell::Bell(Bell::Attachment::SingleWall, eBlockFace::BLOCK_FACE_XP, false).ID: return 11221; case Bell::Bell(Bell::Attachment::DoubleWall, eBlockFace::BLOCK_FACE_ZM, true).ID: return 11222; case Bell::Bell(Bell::Attachment::DoubleWall, eBlockFace::BLOCK_FACE_ZM, false).ID: return 11223; case Bell::Bell(Bell::Attachment::DoubleWall, eBlockFace::BLOCK_FACE_ZP, true).ID: return 11224; case Bell::Bell(Bell::Attachment::DoubleWall, eBlockFace::BLOCK_FACE_ZP, false).ID: return 11225; case Bell::Bell(Bell::Attachment::DoubleWall, eBlockFace::BLOCK_FACE_XM, true).ID: return 11226; case Bell::Bell(Bell::Attachment::DoubleWall, eBlockFace::BLOCK_FACE_XM, false).ID: return 11227; case Bell::Bell(Bell::Attachment::DoubleWall, eBlockFace::BLOCK_FACE_XP, true).ID: return 11228; case Bell::Bell(Bell::Attachment::DoubleWall, eBlockFace::BLOCK_FACE_XP, false).ID: return 11229; case BirchButton::BirchButton(BirchButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5858; case BirchButton::BirchButton(BirchButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5859; case BirchButton::BirchButton(BirchButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5860; case BirchButton::BirchButton(BirchButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5861; case BirchButton::BirchButton(BirchButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, true).ID: return 5862; case BirchButton::BirchButton(BirchButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, false).ID: return 5863; case BirchButton::BirchButton(BirchButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, true).ID: return 5864; case BirchButton::BirchButton(BirchButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, false).ID: return 5865; case BirchButton::BirchButton(BirchButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5866; case BirchButton::BirchButton(BirchButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5867; case BirchButton::BirchButton(BirchButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5868; case BirchButton::BirchButton(BirchButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5869; case BirchButton::BirchButton(BirchButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, true).ID: return 5870; case BirchButton::BirchButton(BirchButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, false).ID: return 5871; case BirchButton::BirchButton(BirchButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, true).ID: return 5872; case BirchButton::BirchButton(BirchButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, false).ID: return 5873; case BirchButton::BirchButton(BirchButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5874; case BirchButton::BirchButton(BirchButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5875; case BirchButton::BirchButton(BirchButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5876; case BirchButton::BirchButton(BirchButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5877; case BirchButton::BirchButton(BirchButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, true).ID: return 5878; case BirchButton::BirchButton(BirchButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, false).ID: return 5879; case BirchButton::BirchButton(BirchButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, true).ID: return 5880; case BirchButton::BirchButton(BirchButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, false).ID: return 5881; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, true, true).ID: return 8266; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, true, false).ID: return 8267; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, false, true).ID: return 8268; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, false, false).ID: return 8269; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, true, true).ID: return 8270; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, true, false).ID: return 8271; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, false, true).ID: return 8272; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, false, false).ID: return 8273; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, true, true).ID: return 8274; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, true, false).ID: return 8275; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, false, true).ID: return 8276; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, false, false).ID: return 8277; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, true, true).ID: return 8278; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, true, false).ID: return 8279; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, false, true).ID: return 8280; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, false, false).ID: return 8281; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, true, true).ID: return 8282; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, true, false).ID: return 8283; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, false, true).ID: return 8284; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, false, false).ID: return 8285; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, true, true).ID: return 8286; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, true, false).ID: return 8287; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, false, true).ID: return 8288; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, false, false).ID: return 8289; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, true, true).ID: return 8290; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, true, false).ID: return 8291; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, false, true).ID: return 8292; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, false, false).ID: return 8293; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, true, true).ID: return 8294; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, true, false).ID: return 8295; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, false, true).ID: return 8296; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, false, false).ID: return 8297; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, true, true).ID: return 8298; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, true, false).ID: return 8299; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, false, true).ID: return 8300; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, false, false).ID: return 8301; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, true, true).ID: return 8302; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, true, false).ID: return 8303; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, false, true).ID: return 8304; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, false, false).ID: return 8305; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, true, true).ID: return 8306; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, true, false).ID: return 8307; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, false, true).ID: return 8308; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, false, false).ID: return 8309; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, true, true).ID: return 8310; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, true, false).ID: return 8311; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, false, true).ID: return 8312; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, false, false).ID: return 8313; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, true, true).ID: return 8314; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, true, false).ID: return 8315; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, false, true).ID: return 8316; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, false, false).ID: return 8317; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, true, true).ID: return 8318; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, true, false).ID: return 8319; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, false, true).ID: return 8320; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, false, false).ID: return 8321; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, true, true).ID: return 8322; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, true, false).ID: return 8323; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, false, true).ID: return 8324; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, false, false).ID: return 8325; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, true, true).ID: return 8326; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, true, false).ID: return 8327; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, false, true).ID: return 8328; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, false, false).ID: return 8329; case BirchFence::BirchFence(true, true, true, true).ID: return 8076; case BirchFence::BirchFence(true, true, true, false).ID: return 8077; case BirchFence::BirchFence(true, true, false, true).ID: return 8080; case BirchFence::BirchFence(true, true, false, false).ID: return 8081; case BirchFence::BirchFence(true, false, true, true).ID: return 8084; case BirchFence::BirchFence(true, false, true, false).ID: return 8085; case BirchFence::BirchFence(true, false, false, true).ID: return 8088; case BirchFence::BirchFence(true, false, false, false).ID: return 8089; case BirchFence::BirchFence(false, true, true, true).ID: return 8092; case BirchFence::BirchFence(false, true, true, false).ID: return 8093; case BirchFence::BirchFence(false, true, false, true).ID: return 8096; case BirchFence::BirchFence(false, true, false, false).ID: return 8097; case BirchFence::BirchFence(false, false, true, true).ID: return 8100; case BirchFence::BirchFence(false, false, true, false).ID: return 8101; case BirchFence::BirchFence(false, false, false, true).ID: return 8104; case BirchFence::BirchFence(false, false, false, false).ID: return 8105; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZM, true, true, true).ID: return 7914; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZM, true, true, false).ID: return 7915; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZM, true, false, true).ID: return 7916; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZM, true, false, false).ID: return 7917; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, true).ID: return 7918; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, false).ID: return 7919; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, true).ID: return 7920; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, false).ID: return 7921; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZP, true, true, true).ID: return 7922; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZP, true, true, false).ID: return 7923; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZP, true, false, true).ID: return 7924; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZP, true, false, false).ID: return 7925; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, true).ID: return 7926; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, false).ID: return 7927; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, true).ID: return 7928; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, false).ID: return 7929; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XM, true, true, true).ID: return 7930; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XM, true, true, false).ID: return 7931; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XM, true, false, true).ID: return 7932; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XM, true, false, false).ID: return 7933; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, true).ID: return 7934; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, false).ID: return 7935; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, true).ID: return 7936; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, false).ID: return 7937; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XP, true, true, true).ID: return 7938; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XP, true, true, false).ID: return 7939; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XP, true, false, true).ID: return 7940; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XP, true, false, false).ID: return 7941; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, true).ID: return 7942; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, false).ID: return 7943; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, true).ID: return 7944; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, false).ID: return 7945; case BirchLeaves::BirchLeaves(1, true).ID: return 172; case BirchLeaves::BirchLeaves(1, false).ID: return 173; case BirchLeaves::BirchLeaves(2, true).ID: return 174; case BirchLeaves::BirchLeaves(2, false).ID: return 175; case BirchLeaves::BirchLeaves(3, true).ID: return 176; case BirchLeaves::BirchLeaves(3, false).ID: return 177; case BirchLeaves::BirchLeaves(4, true).ID: return 178; case BirchLeaves::BirchLeaves(4, false).ID: return 179; case BirchLeaves::BirchLeaves(5, true).ID: return 180; case BirchLeaves::BirchLeaves(5, false).ID: return 181; case BirchLeaves::BirchLeaves(6, true).ID: return 182; case BirchLeaves::BirchLeaves(6, false).ID: return 183; case BirchLeaves::BirchLeaves(7, true).ID: return 184; case BirchLeaves::BirchLeaves(7, false).ID: return 185; case BirchLog::BirchLog(BirchLog::Axis::X).ID: return 78; case BirchLog::BirchLog(BirchLog::Axis::Y).ID: return 79; case BirchLog::BirchLog(BirchLog::Axis::Z).ID: return 80; case BirchPlanks::BirchPlanks().ID: return 17; case BirchPressurePlate::BirchPressurePlate(true).ID: return 3875; case BirchPressurePlate::BirchPressurePlate(false).ID: return 3876; case BirchSapling::BirchSapling(0).ID: return 25; case BirchSapling::BirchSapling(1).ID: return 26; case BirchSign::BirchSign(0).ID: return 3444; case BirchSign::BirchSign(1).ID: return 3446; case BirchSign::BirchSign(2).ID: return 3448; case BirchSign::BirchSign(3).ID: return 3450; case BirchSign::BirchSign(4).ID: return 3452; case BirchSign::BirchSign(5).ID: return 3454; case BirchSign::BirchSign(6).ID: return 3456; case BirchSign::BirchSign(7).ID: return 3458; case BirchSign::BirchSign(8).ID: return 3460; case BirchSign::BirchSign(9).ID: return 3462; case BirchSign::BirchSign(10).ID: return 3464; case BirchSign::BirchSign(11).ID: return 3466; case BirchSign::BirchSign(12).ID: return 3468; case BirchSign::BirchSign(13).ID: return 3470; case BirchSign::BirchSign(14).ID: return 3472; case BirchSign::BirchSign(15).ID: return 3474; case BirchSlab::BirchSlab(BirchSlab::Type::Top).ID: return 7777; case BirchSlab::BirchSlab(BirchSlab::Type::Bottom).ID: return 7779; case BirchSlab::BirchSlab(BirchSlab::Type::Double).ID: return 7781; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZM, BirchStairs::Half::Top, BirchStairs::Shape::Straight).ID: return 5469; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZM, BirchStairs::Half::Top, BirchStairs::Shape::InnerLeft).ID: return 5471; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZM, BirchStairs::Half::Top, BirchStairs::Shape::InnerRight).ID: return 5473; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZM, BirchStairs::Half::Top, BirchStairs::Shape::OuterLeft).ID: return 5475; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZM, BirchStairs::Half::Top, BirchStairs::Shape::OuterRight).ID: return 5477; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZM, BirchStairs::Half::Bottom, BirchStairs::Shape::Straight).ID: return 5479; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZM, BirchStairs::Half::Bottom, BirchStairs::Shape::InnerLeft).ID: return 5481; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZM, BirchStairs::Half::Bottom, BirchStairs::Shape::InnerRight).ID: return 5483; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZM, BirchStairs::Half::Bottom, BirchStairs::Shape::OuterLeft).ID: return 5485; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZM, BirchStairs::Half::Bottom, BirchStairs::Shape::OuterRight).ID: return 5487; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZP, BirchStairs::Half::Top, BirchStairs::Shape::Straight).ID: return 5489; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZP, BirchStairs::Half::Top, BirchStairs::Shape::InnerLeft).ID: return 5491; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZP, BirchStairs::Half::Top, BirchStairs::Shape::InnerRight).ID: return 5493; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZP, BirchStairs::Half::Top, BirchStairs::Shape::OuterLeft).ID: return 5495; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZP, BirchStairs::Half::Top, BirchStairs::Shape::OuterRight).ID: return 5497; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZP, BirchStairs::Half::Bottom, BirchStairs::Shape::Straight).ID: return 5499; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZP, BirchStairs::Half::Bottom, BirchStairs::Shape::InnerLeft).ID: return 5501; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZP, BirchStairs::Half::Bottom, BirchStairs::Shape::InnerRight).ID: return 5503; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZP, BirchStairs::Half::Bottom, BirchStairs::Shape::OuterLeft).ID: return 5505; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZP, BirchStairs::Half::Bottom, BirchStairs::Shape::OuterRight).ID: return 5507; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XM, BirchStairs::Half::Top, BirchStairs::Shape::Straight).ID: return 5509; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XM, BirchStairs::Half::Top, BirchStairs::Shape::InnerLeft).ID: return 5511; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XM, BirchStairs::Half::Top, BirchStairs::Shape::InnerRight).ID: return 5513; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XM, BirchStairs::Half::Top, BirchStairs::Shape::OuterLeft).ID: return 5515; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XM, BirchStairs::Half::Top, BirchStairs::Shape::OuterRight).ID: return 5517; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XM, BirchStairs::Half::Bottom, BirchStairs::Shape::Straight).ID: return 5519; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XM, BirchStairs::Half::Bottom, BirchStairs::Shape::InnerLeft).ID: return 5521; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XM, BirchStairs::Half::Bottom, BirchStairs::Shape::InnerRight).ID: return 5523; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XM, BirchStairs::Half::Bottom, BirchStairs::Shape::OuterLeft).ID: return 5525; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XM, BirchStairs::Half::Bottom, BirchStairs::Shape::OuterRight).ID: return 5527; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XP, BirchStairs::Half::Top, BirchStairs::Shape::Straight).ID: return 5529; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XP, BirchStairs::Half::Top, BirchStairs::Shape::InnerLeft).ID: return 5531; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XP, BirchStairs::Half::Top, BirchStairs::Shape::InnerRight).ID: return 5533; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XP, BirchStairs::Half::Top, BirchStairs::Shape::OuterLeft).ID: return 5535; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XP, BirchStairs::Half::Top, BirchStairs::Shape::OuterRight).ID: return 5537; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XP, BirchStairs::Half::Bottom, BirchStairs::Shape::Straight).ID: return 5539; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XP, BirchStairs::Half::Bottom, BirchStairs::Shape::InnerLeft).ID: return 5541; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XP, BirchStairs::Half::Bottom, BirchStairs::Shape::InnerRight).ID: return 5543; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XP, BirchStairs::Half::Bottom, BirchStairs::Shape::OuterLeft).ID: return 5545; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XP, BirchStairs::Half::Bottom, BirchStairs::Shape::OuterRight).ID: return 5547; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZM, BirchTrapdoor::Half::Top, true, true).ID: return 4226; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZM, BirchTrapdoor::Half::Top, true, false).ID: return 4228; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZM, BirchTrapdoor::Half::Top, false, true).ID: return 4230; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZM, BirchTrapdoor::Half::Top, false, false).ID: return 4232; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZM, BirchTrapdoor::Half::Bottom, true, true).ID: return 4234; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZM, BirchTrapdoor::Half::Bottom, true, false).ID: return 4236; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZM, BirchTrapdoor::Half::Bottom, false, true).ID: return 4238; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZM, BirchTrapdoor::Half::Bottom, false, false).ID: return 4240; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZP, BirchTrapdoor::Half::Top, true, true).ID: return 4242; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZP, BirchTrapdoor::Half::Top, true, false).ID: return 4244; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZP, BirchTrapdoor::Half::Top, false, true).ID: return 4246; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZP, BirchTrapdoor::Half::Top, false, false).ID: return 4248; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZP, BirchTrapdoor::Half::Bottom, true, true).ID: return 4250; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZP, BirchTrapdoor::Half::Bottom, true, false).ID: return 4252; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZP, BirchTrapdoor::Half::Bottom, false, true).ID: return 4254; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZP, BirchTrapdoor::Half::Bottom, false, false).ID: return 4256; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XM, BirchTrapdoor::Half::Top, true, true).ID: return 4258; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XM, BirchTrapdoor::Half::Top, true, false).ID: return 4260; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XM, BirchTrapdoor::Half::Top, false, true).ID: return 4262; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XM, BirchTrapdoor::Half::Top, false, false).ID: return 4264; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XM, BirchTrapdoor::Half::Bottom, true, true).ID: return 4266; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XM, BirchTrapdoor::Half::Bottom, true, false).ID: return 4268; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XM, BirchTrapdoor::Half::Bottom, false, true).ID: return 4270; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XM, BirchTrapdoor::Half::Bottom, false, false).ID: return 4272; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XP, BirchTrapdoor::Half::Top, true, true).ID: return 4274; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XP, BirchTrapdoor::Half::Top, true, false).ID: return 4276; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XP, BirchTrapdoor::Half::Top, false, true).ID: return 4278; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XP, BirchTrapdoor::Half::Top, false, false).ID: return 4280; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XP, BirchTrapdoor::Half::Bottom, true, true).ID: return 4282; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XP, BirchTrapdoor::Half::Bottom, true, false).ID: return 4284; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XP, BirchTrapdoor::Half::Bottom, false, true).ID: return 4286; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XP, BirchTrapdoor::Half::Bottom, false, false).ID: return 4288; case BirchWallSign::BirchWallSign(eBlockFace::BLOCK_FACE_ZM).ID: return 3750; case BirchWallSign::BirchWallSign(eBlockFace::BLOCK_FACE_ZP).ID: return 3752; case BirchWallSign::BirchWallSign(eBlockFace::BLOCK_FACE_XM).ID: return 3754; case BirchWallSign::BirchWallSign(eBlockFace::BLOCK_FACE_XP).ID: return 3756; case BirchWood::BirchWood(BirchWood::Axis::X).ID: return 114; case BirchWood::BirchWood(BirchWood::Axis::Y).ID: return 115; case BirchWood::BirchWood(BirchWood::Axis::Z).ID: return 116; case BlackBanner::BlackBanner(0).ID: return 7601; case BlackBanner::BlackBanner(1).ID: return 7602; case BlackBanner::BlackBanner(2).ID: return 7603; case BlackBanner::BlackBanner(3).ID: return 7604; case BlackBanner::BlackBanner(4).ID: return 7605; case BlackBanner::BlackBanner(5).ID: return 7606; case BlackBanner::BlackBanner(6).ID: return 7607; case BlackBanner::BlackBanner(7).ID: return 7608; case BlackBanner::BlackBanner(8).ID: return 7609; case BlackBanner::BlackBanner(9).ID: return 7610; case BlackBanner::BlackBanner(10).ID: return 7611; case BlackBanner::BlackBanner(11).ID: return 7612; case BlackBanner::BlackBanner(12).ID: return 7613; case BlackBanner::BlackBanner(13).ID: return 7614; case BlackBanner::BlackBanner(14).ID: return 7615; case BlackBanner::BlackBanner(15).ID: return 7616; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_ZM, true, BlackBed::Part::Head).ID: return 1288; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_ZM, true, BlackBed::Part::Foot).ID: return 1289; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_ZM, false, BlackBed::Part::Head).ID: return 1290; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_ZM, false, BlackBed::Part::Foot).ID: return 1291; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_ZP, true, BlackBed::Part::Head).ID: return 1292; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_ZP, true, BlackBed::Part::Foot).ID: return 1293; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_ZP, false, BlackBed::Part::Head).ID: return 1294; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_ZP, false, BlackBed::Part::Foot).ID: return 1295; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_XM, true, BlackBed::Part::Head).ID: return 1296; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_XM, true, BlackBed::Part::Foot).ID: return 1297; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_XM, false, BlackBed::Part::Head).ID: return 1298; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_XM, false, BlackBed::Part::Foot).ID: return 1299; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_XP, true, BlackBed::Part::Head).ID: return 1300; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_XP, true, BlackBed::Part::Foot).ID: return 1301; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_XP, false, BlackBed::Part::Head).ID: return 1302; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_XP, false, BlackBed::Part::Foot).ID: return 1303; case BlackCarpet::BlackCarpet().ID: return 7345; case BlackConcrete::BlackConcrete().ID: return 8917; case BlackConcretePowder::BlackConcretePowder().ID: return 8933; case BlackGlazedTerracotta::BlackGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 8898; case BlackGlazedTerracotta::BlackGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 8899; case BlackGlazedTerracotta::BlackGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 8900; case BlackGlazedTerracotta::BlackGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 8901; case BlackShulkerBox::BlackShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 8832; case BlackShulkerBox::BlackShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 8833; case BlackShulkerBox::BlackShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 8834; case BlackShulkerBox::BlackShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 8835; case BlackShulkerBox::BlackShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 8836; case BlackShulkerBox::BlackShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 8837; case BlackStainedGlass::BlackStainedGlass().ID: return 4096; case BlackStainedGlassPane::BlackStainedGlassPane(true, true, true, true).ID: return 6809; case BlackStainedGlassPane::BlackStainedGlassPane(true, true, true, false).ID: return 6810; case BlackStainedGlassPane::BlackStainedGlassPane(true, true, false, true).ID: return 6813; case BlackStainedGlassPane::BlackStainedGlassPane(true, true, false, false).ID: return 6814; case BlackStainedGlassPane::BlackStainedGlassPane(true, false, true, true).ID: return 6817; case BlackStainedGlassPane::BlackStainedGlassPane(true, false, true, false).ID: return 6818; case BlackStainedGlassPane::BlackStainedGlassPane(true, false, false, true).ID: return 6821; case BlackStainedGlassPane::BlackStainedGlassPane(true, false, false, false).ID: return 6822; case BlackStainedGlassPane::BlackStainedGlassPane(false, true, true, true).ID: return 6825; case BlackStainedGlassPane::BlackStainedGlassPane(false, true, true, false).ID: return 6826; case BlackStainedGlassPane::BlackStainedGlassPane(false, true, false, true).ID: return 6829; case BlackStainedGlassPane::BlackStainedGlassPane(false, true, false, false).ID: return 6830; case BlackStainedGlassPane::BlackStainedGlassPane(false, false, true, true).ID: return 6833; case BlackStainedGlassPane::BlackStainedGlassPane(false, false, true, false).ID: return 6834; case BlackStainedGlassPane::BlackStainedGlassPane(false, false, false, true).ID: return 6837; case BlackStainedGlassPane::BlackStainedGlassPane(false, false, false, false).ID: return 6838; case BlackTerracotta::BlackTerracotta().ID: return 6326; case BlackWallBanner::BlackWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 7677; case BlackWallBanner::BlackWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 7678; case BlackWallBanner::BlackWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 7679; case BlackWallBanner::BlackWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 7680; case BlackWool::BlackWool().ID: return 1398; case BlastFurnace::BlastFurnace(eBlockFace::BLOCK_FACE_ZM, true).ID: return 11155; case BlastFurnace::BlastFurnace(eBlockFace::BLOCK_FACE_ZM, false).ID: return 11156; case BlastFurnace::BlastFurnace(eBlockFace::BLOCK_FACE_ZP, true).ID: return 11157; case BlastFurnace::BlastFurnace(eBlockFace::BLOCK_FACE_ZP, false).ID: return 11158; case BlastFurnace::BlastFurnace(eBlockFace::BLOCK_FACE_XM, true).ID: return 11159; case BlastFurnace::BlastFurnace(eBlockFace::BLOCK_FACE_XM, false).ID: return 11160; case BlastFurnace::BlastFurnace(eBlockFace::BLOCK_FACE_XP, true).ID: return 11161; case BlastFurnace::BlastFurnace(eBlockFace::BLOCK_FACE_XP, false).ID: return 11162; case BlueBanner::BlueBanner(0).ID: return 7537; case BlueBanner::BlueBanner(1).ID: return 7538; case BlueBanner::BlueBanner(2).ID: return 7539; case BlueBanner::BlueBanner(3).ID: return 7540; case BlueBanner::BlueBanner(4).ID: return 7541; case BlueBanner::BlueBanner(5).ID: return 7542; case BlueBanner::BlueBanner(6).ID: return 7543; case BlueBanner::BlueBanner(7).ID: return 7544; case BlueBanner::BlueBanner(8).ID: return 7545; case BlueBanner::BlueBanner(9).ID: return 7546; case BlueBanner::BlueBanner(10).ID: return 7547; case BlueBanner::BlueBanner(11).ID: return 7548; case BlueBanner::BlueBanner(12).ID: return 7549; case BlueBanner::BlueBanner(13).ID: return 7550; case BlueBanner::BlueBanner(14).ID: return 7551; case BlueBanner::BlueBanner(15).ID: return 7552; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_ZM, true, BlueBed::Part::Head).ID: return 1224; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_ZM, true, BlueBed::Part::Foot).ID: return 1225; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_ZM, false, BlueBed::Part::Head).ID: return 1226; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_ZM, false, BlueBed::Part::Foot).ID: return 1227; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_ZP, true, BlueBed::Part::Head).ID: return 1228; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_ZP, true, BlueBed::Part::Foot).ID: return 1229; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_ZP, false, BlueBed::Part::Head).ID: return 1230; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_ZP, false, BlueBed::Part::Foot).ID: return 1231; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_XM, true, BlueBed::Part::Head).ID: return 1232; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_XM, true, BlueBed::Part::Foot).ID: return 1233; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_XM, false, BlueBed::Part::Head).ID: return 1234; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_XM, false, BlueBed::Part::Foot).ID: return 1235; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_XP, true, BlueBed::Part::Head).ID: return 1236; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_XP, true, BlueBed::Part::Foot).ID: return 1237; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_XP, false, BlueBed::Part::Head).ID: return 1238; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_XP, false, BlueBed::Part::Foot).ID: return 1239; case BlueCarpet::BlueCarpet().ID: return 7341; case BlueConcrete::BlueConcrete().ID: return 8913; case BlueConcretePowder::BlueConcretePowder().ID: return 8929; case BlueGlazedTerracotta::BlueGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 8882; case BlueGlazedTerracotta::BlueGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 8883; case BlueGlazedTerracotta::BlueGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 8884; case BlueGlazedTerracotta::BlueGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 8885; case BlueIce::BlueIce().ID: return 9112; case BlueOrchid::BlueOrchid().ID: return 1413; case BlueShulkerBox::BlueShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 8808; case BlueShulkerBox::BlueShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 8809; case BlueShulkerBox::BlueShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 8810; case BlueShulkerBox::BlueShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 8811; case BlueShulkerBox::BlueShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 8812; case BlueShulkerBox::BlueShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 8813; case BlueStainedGlass::BlueStainedGlass().ID: return 4092; case BlueStainedGlassPane::BlueStainedGlassPane(true, true, true, true).ID: return 6681; case BlueStainedGlassPane::BlueStainedGlassPane(true, true, true, false).ID: return 6682; case BlueStainedGlassPane::BlueStainedGlassPane(true, true, false, true).ID: return 6685; case BlueStainedGlassPane::BlueStainedGlassPane(true, true, false, false).ID: return 6686; case BlueStainedGlassPane::BlueStainedGlassPane(true, false, true, true).ID: return 6689; case BlueStainedGlassPane::BlueStainedGlassPane(true, false, true, false).ID: return 6690; case BlueStainedGlassPane::BlueStainedGlassPane(true, false, false, true).ID: return 6693; case BlueStainedGlassPane::BlueStainedGlassPane(true, false, false, false).ID: return 6694; case BlueStainedGlassPane::BlueStainedGlassPane(false, true, true, true).ID: return 6697; case BlueStainedGlassPane::BlueStainedGlassPane(false, true, true, false).ID: return 6698; case BlueStainedGlassPane::BlueStainedGlassPane(false, true, false, true).ID: return 6701; case BlueStainedGlassPane::BlueStainedGlassPane(false, true, false, false).ID: return 6702; case BlueStainedGlassPane::BlueStainedGlassPane(false, false, true, true).ID: return 6705; case BlueStainedGlassPane::BlueStainedGlassPane(false, false, true, false).ID: return 6706; case BlueStainedGlassPane::BlueStainedGlassPane(false, false, false, true).ID: return 6709; case BlueStainedGlassPane::BlueStainedGlassPane(false, false, false, false).ID: return 6710; case BlueTerracotta::BlueTerracotta().ID: return 6322; case BlueWallBanner::BlueWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 7661; case BlueWallBanner::BlueWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 7662; case BlueWallBanner::BlueWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 7663; case BlueWallBanner::BlueWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 7664; case BlueWool::BlueWool().ID: return 1394; case BoneBlock::BoneBlock(BoneBlock::Axis::X).ID: return 8720; case BoneBlock::BoneBlock(BoneBlock::Axis::Y).ID: return 8721; case BoneBlock::BoneBlock(BoneBlock::Axis::Z).ID: return 8722; case Bookshelf::Bookshelf().ID: return 1431; case BrainCoral::BrainCoral().ID: return 8997; case BrainCoralBlock::BrainCoralBlock().ID: return 8980; case BrainCoralFan::BrainCoralFan().ID: return 9017; case BrainCoralWallFan::BrainCoralWallFan(eBlockFace::BLOCK_FACE_ZM).ID: return 9073; case BrainCoralWallFan::BrainCoralWallFan(eBlockFace::BLOCK_FACE_ZP).ID: return 9075; case BrainCoralWallFan::BrainCoralWallFan(eBlockFace::BLOCK_FACE_XM).ID: return 9077; case BrainCoralWallFan::BrainCoralWallFan(eBlockFace::BLOCK_FACE_XP).ID: return 9079; case BrewingStand::BrewingStand(true, true, true).ID: return 5117; case BrewingStand::BrewingStand(true, true, false).ID: return 5118; case BrewingStand::BrewingStand(true, false, true).ID: return 5119; case BrewingStand::BrewingStand(true, false, false).ID: return 5120; case BrewingStand::BrewingStand(false, true, true).ID: return 5121; case BrewingStand::BrewingStand(false, true, false).ID: return 5122; case BrewingStand::BrewingStand(false, false, true).ID: return 5123; case BrewingStand::BrewingStand(false, false, false).ID: return 5124; case BrickSlab::BrickSlab(BrickSlab::Type::Top).ID: return 7837; case BrickSlab::BrickSlab(BrickSlab::Type::Bottom).ID: return 7839; case BrickSlab::BrickSlab(BrickSlab::Type::Double).ID: return 7841; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZM, BrickStairs::Half::Top, BrickStairs::Shape::Straight).ID: return 4837; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZM, BrickStairs::Half::Top, BrickStairs::Shape::InnerLeft).ID: return 4839; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZM, BrickStairs::Half::Top, BrickStairs::Shape::InnerRight).ID: return 4841; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZM, BrickStairs::Half::Top, BrickStairs::Shape::OuterLeft).ID: return 4843; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZM, BrickStairs::Half::Top, BrickStairs::Shape::OuterRight).ID: return 4845; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZM, BrickStairs::Half::Bottom, BrickStairs::Shape::Straight).ID: return 4847; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZM, BrickStairs::Half::Bottom, BrickStairs::Shape::InnerLeft).ID: return 4849; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZM, BrickStairs::Half::Bottom, BrickStairs::Shape::InnerRight).ID: return 4851; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZM, BrickStairs::Half::Bottom, BrickStairs::Shape::OuterLeft).ID: return 4853; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZM, BrickStairs::Half::Bottom, BrickStairs::Shape::OuterRight).ID: return 4855; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZP, BrickStairs::Half::Top, BrickStairs::Shape::Straight).ID: return 4857; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZP, BrickStairs::Half::Top, BrickStairs::Shape::InnerLeft).ID: return 4859; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZP, BrickStairs::Half::Top, BrickStairs::Shape::InnerRight).ID: return 4861; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZP, BrickStairs::Half::Top, BrickStairs::Shape::OuterLeft).ID: return 4863; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZP, BrickStairs::Half::Top, BrickStairs::Shape::OuterRight).ID: return 4865; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZP, BrickStairs::Half::Bottom, BrickStairs::Shape::Straight).ID: return 4867; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZP, BrickStairs::Half::Bottom, BrickStairs::Shape::InnerLeft).ID: return 4869; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZP, BrickStairs::Half::Bottom, BrickStairs::Shape::InnerRight).ID: return 4871; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZP, BrickStairs::Half::Bottom, BrickStairs::Shape::OuterLeft).ID: return 4873; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZP, BrickStairs::Half::Bottom, BrickStairs::Shape::OuterRight).ID: return 4875; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XM, BrickStairs::Half::Top, BrickStairs::Shape::Straight).ID: return 4877; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XM, BrickStairs::Half::Top, BrickStairs::Shape::InnerLeft).ID: return 4879; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XM, BrickStairs::Half::Top, BrickStairs::Shape::InnerRight).ID: return 4881; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XM, BrickStairs::Half::Top, BrickStairs::Shape::OuterLeft).ID: return 4883; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XM, BrickStairs::Half::Top, BrickStairs::Shape::OuterRight).ID: return 4885; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XM, BrickStairs::Half::Bottom, BrickStairs::Shape::Straight).ID: return 4887; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XM, BrickStairs::Half::Bottom, BrickStairs::Shape::InnerLeft).ID: return 4889; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XM, BrickStairs::Half::Bottom, BrickStairs::Shape::InnerRight).ID: return 4891; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XM, BrickStairs::Half::Bottom, BrickStairs::Shape::OuterLeft).ID: return 4893; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XM, BrickStairs::Half::Bottom, BrickStairs::Shape::OuterRight).ID: return 4895; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XP, BrickStairs::Half::Top, BrickStairs::Shape::Straight).ID: return 4897; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XP, BrickStairs::Half::Top, BrickStairs::Shape::InnerLeft).ID: return 4899; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XP, BrickStairs::Half::Top, BrickStairs::Shape::InnerRight).ID: return 4901; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XP, BrickStairs::Half::Top, BrickStairs::Shape::OuterLeft).ID: return 4903; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XP, BrickStairs::Half::Top, BrickStairs::Shape::OuterRight).ID: return 4905; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XP, BrickStairs::Half::Bottom, BrickStairs::Shape::Straight).ID: return 4907; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XP, BrickStairs::Half::Bottom, BrickStairs::Shape::InnerLeft).ID: return 4909; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XP, BrickStairs::Half::Bottom, BrickStairs::Shape::InnerRight).ID: return 4911; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XP, BrickStairs::Half::Bottom, BrickStairs::Shape::OuterLeft).ID: return 4913; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XP, BrickStairs::Half::Bottom, BrickStairs::Shape::OuterRight).ID: return 4915; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::Low, BrickWall::South::Low, true, BrickWall::West::Low).ID: return 10333; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::Low, BrickWall::South::Low, true, BrickWall::West::None).ID: return 10334; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::Low, BrickWall::South::Low, false, BrickWall::West::Low).ID: return 10337; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::Low, BrickWall::South::Low, false, BrickWall::West::None).ID: return 10338; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::Low, BrickWall::South::None, true, BrickWall::West::Low).ID: return 10341; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::Low, BrickWall::South::None, true, BrickWall::West::None).ID: return 10342; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::Low, BrickWall::South::None, false, BrickWall::West::Low).ID: return 10345; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::Low, BrickWall::South::None, false, BrickWall::West::None).ID: return 10346; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::None, BrickWall::South::Low, true, BrickWall::West::Low).ID: return 10349; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::None, BrickWall::South::Low, true, BrickWall::West::None).ID: return 10350; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::None, BrickWall::South::Low, false, BrickWall::West::Low).ID: return 10353; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::None, BrickWall::South::Low, false, BrickWall::West::None).ID: return 10354; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::None, BrickWall::South::None, true, BrickWall::West::Low).ID: return 10357; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::None, BrickWall::South::None, true, BrickWall::West::None).ID: return 10358; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::None, BrickWall::South::None, false, BrickWall::West::Low).ID: return 10361; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::None, BrickWall::South::None, false, BrickWall::West::None).ID: return 10362; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::Low, BrickWall::South::Low, true, BrickWall::West::Low).ID: return 10365; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::Low, BrickWall::South::Low, true, BrickWall::West::None).ID: return 10366; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::Low, BrickWall::South::Low, false, BrickWall::West::Low).ID: return 10369; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::Low, BrickWall::South::Low, false, BrickWall::West::None).ID: return 10370; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::Low, BrickWall::South::None, true, BrickWall::West::Low).ID: return 10373; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::Low, BrickWall::South::None, true, BrickWall::West::None).ID: return 10374; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::Low, BrickWall::South::None, false, BrickWall::West::Low).ID: return 10377; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::Low, BrickWall::South::None, false, BrickWall::West::None).ID: return 10378; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::None, BrickWall::South::Low, true, BrickWall::West::Low).ID: return 10381; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::None, BrickWall::South::Low, true, BrickWall::West::None).ID: return 10382; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::None, BrickWall::South::Low, false, BrickWall::West::Low).ID: return 10385; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::None, BrickWall::South::Low, false, BrickWall::West::None).ID: return 10386; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::None, BrickWall::South::None, true, BrickWall::West::Low).ID: return 10389; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::None, BrickWall::South::None, true, BrickWall::West::None).ID: return 10390; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::None, BrickWall::South::None, false, BrickWall::West::Low).ID: return 10393; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::None, BrickWall::South::None, false, BrickWall::West::None).ID: return 10394; case Bricks::Bricks().ID: return 1428; case BrownBanner::BrownBanner(0).ID: return 7553; case BrownBanner::BrownBanner(1).ID: return 7554; case BrownBanner::BrownBanner(2).ID: return 7555; case BrownBanner::BrownBanner(3).ID: return 7556; case BrownBanner::BrownBanner(4).ID: return 7557; case BrownBanner::BrownBanner(5).ID: return 7558; case BrownBanner::BrownBanner(6).ID: return 7559; case BrownBanner::BrownBanner(7).ID: return 7560; case BrownBanner::BrownBanner(8).ID: return 7561; case BrownBanner::BrownBanner(9).ID: return 7562; case BrownBanner::BrownBanner(10).ID: return 7563; case BrownBanner::BrownBanner(11).ID: return 7564; case BrownBanner::BrownBanner(12).ID: return 7565; case BrownBanner::BrownBanner(13).ID: return 7566; case BrownBanner::BrownBanner(14).ID: return 7567; case BrownBanner::BrownBanner(15).ID: return 7568; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_ZM, true, BrownBed::Part::Head).ID: return 1240; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_ZM, true, BrownBed::Part::Foot).ID: return 1241; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_ZM, false, BrownBed::Part::Head).ID: return 1242; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_ZM, false, BrownBed::Part::Foot).ID: return 1243; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_ZP, true, BrownBed::Part::Head).ID: return 1244; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_ZP, true, BrownBed::Part::Foot).ID: return 1245; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_ZP, false, BrownBed::Part::Head).ID: return 1246; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_ZP, false, BrownBed::Part::Foot).ID: return 1247; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_XM, true, BrownBed::Part::Head).ID: return 1248; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_XM, true, BrownBed::Part::Foot).ID: return 1249; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_XM, false, BrownBed::Part::Head).ID: return 1250; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_XM, false, BrownBed::Part::Foot).ID: return 1251; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_XP, true, BrownBed::Part::Head).ID: return 1252; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_XP, true, BrownBed::Part::Foot).ID: return 1253; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_XP, false, BrownBed::Part::Head).ID: return 1254; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_XP, false, BrownBed::Part::Foot).ID: return 1255; case BrownCarpet::BrownCarpet().ID: return 7342; case BrownConcrete::BrownConcrete().ID: return 8914; case BrownConcretePowder::BrownConcretePowder().ID: return 8930; case BrownGlazedTerracotta::BrownGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 8886; case BrownGlazedTerracotta::BrownGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 8887; case BrownGlazedTerracotta::BrownGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 8888; case BrownGlazedTerracotta::BrownGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 8889; case BrownMushroom::BrownMushroom().ID: return 1424; case BrownMushroomBlock::BrownMushroomBlock(true, true, true, true, true, true).ID: return 4491; case BrownMushroomBlock::BrownMushroomBlock(true, true, true, true, true, false).ID: return 4492; case BrownMushroomBlock::BrownMushroomBlock(true, true, true, true, false, true).ID: return 4493; case BrownMushroomBlock::BrownMushroomBlock(true, true, true, true, false, false).ID: return 4494; case BrownMushroomBlock::BrownMushroomBlock(true, true, true, false, true, true).ID: return 4495; case BrownMushroomBlock::BrownMushroomBlock(true, true, true, false, true, false).ID: return 4496; case BrownMushroomBlock::BrownMushroomBlock(true, true, true, false, false, true).ID: return 4497; case BrownMushroomBlock::BrownMushroomBlock(true, true, true, false, false, false).ID: return 4498; case BrownMushroomBlock::BrownMushroomBlock(true, true, false, true, true, true).ID: return 4499; case BrownMushroomBlock::BrownMushroomBlock(true, true, false, true, true, false).ID: return 4500; case BrownMushroomBlock::BrownMushroomBlock(true, true, false, true, false, true).ID: return 4501; case BrownMushroomBlock::BrownMushroomBlock(true, true, false, true, false, false).ID: return 4502; case BrownMushroomBlock::BrownMushroomBlock(true, true, false, false, true, true).ID: return 4503; case BrownMushroomBlock::BrownMushroomBlock(true, true, false, false, true, false).ID: return 4504; case BrownMushroomBlock::BrownMushroomBlock(true, true, false, false, false, true).ID: return 4505; case BrownMushroomBlock::BrownMushroomBlock(true, true, false, false, false, false).ID: return 4506; case BrownMushroomBlock::BrownMushroomBlock(true, false, true, true, true, true).ID: return 4507; case BrownMushroomBlock::BrownMushroomBlock(true, false, true, true, true, false).ID: return 4508; case BrownMushroomBlock::BrownMushroomBlock(true, false, true, true, false, true).ID: return 4509; case BrownMushroomBlock::BrownMushroomBlock(true, false, true, true, false, false).ID: return 4510; case BrownMushroomBlock::BrownMushroomBlock(true, false, true, false, true, true).ID: return 4511; case BrownMushroomBlock::BrownMushroomBlock(true, false, true, false, true, false).ID: return 4512; case BrownMushroomBlock::BrownMushroomBlock(true, false, true, false, false, true).ID: return 4513; case BrownMushroomBlock::BrownMushroomBlock(true, false, true, false, false, false).ID: return 4514; case BrownMushroomBlock::BrownMushroomBlock(true, false, false, true, true, true).ID: return 4515; case BrownMushroomBlock::BrownMushroomBlock(true, false, false, true, true, false).ID: return 4516; case BrownMushroomBlock::BrownMushroomBlock(true, false, false, true, false, true).ID: return 4517; case BrownMushroomBlock::BrownMushroomBlock(true, false, false, true, false, false).ID: return 4518; case BrownMushroomBlock::BrownMushroomBlock(true, false, false, false, true, true).ID: return 4519; case BrownMushroomBlock::BrownMushroomBlock(true, false, false, false, true, false).ID: return 4520; case BrownMushroomBlock::BrownMushroomBlock(true, false, false, false, false, true).ID: return 4521; case BrownMushroomBlock::BrownMushroomBlock(true, false, false, false, false, false).ID: return 4522; case BrownMushroomBlock::BrownMushroomBlock(false, true, true, true, true, true).ID: return 4523; case BrownMushroomBlock::BrownMushroomBlock(false, true, true, true, true, false).ID: return 4524; case BrownMushroomBlock::BrownMushroomBlock(false, true, true, true, false, true).ID: return 4525; case BrownMushroomBlock::BrownMushroomBlock(false, true, true, true, false, false).ID: return 4526; case BrownMushroomBlock::BrownMushroomBlock(false, true, true, false, true, true).ID: return 4527; case BrownMushroomBlock::BrownMushroomBlock(false, true, true, false, true, false).ID: return 4528; case BrownMushroomBlock::BrownMushroomBlock(false, true, true, false, false, true).ID: return 4529; case BrownMushroomBlock::BrownMushroomBlock(false, true, true, false, false, false).ID: return 4530; case BrownMushroomBlock::BrownMushroomBlock(false, true, false, true, true, true).ID: return 4531; case BrownMushroomBlock::BrownMushroomBlock(false, true, false, true, true, false).ID: return 4532; case BrownMushroomBlock::BrownMushroomBlock(false, true, false, true, false, true).ID: return 4533; case BrownMushroomBlock::BrownMushroomBlock(false, true, false, true, false, false).ID: return 4534; case BrownMushroomBlock::BrownMushroomBlock(false, true, false, false, true, true).ID: return 4535; case BrownMushroomBlock::BrownMushroomBlock(false, true, false, false, true, false).ID: return 4536; case BrownMushroomBlock::BrownMushroomBlock(false, true, false, false, false, true).ID: return 4537; case BrownMushroomBlock::BrownMushroomBlock(false, true, false, false, false, false).ID: return 4538; case BrownMushroomBlock::BrownMushroomBlock(false, false, true, true, true, true).ID: return 4539; case BrownMushroomBlock::BrownMushroomBlock(false, false, true, true, true, false).ID: return 4540; case BrownMushroomBlock::BrownMushroomBlock(false, false, true, true, false, true).ID: return 4541; case BrownMushroomBlock::BrownMushroomBlock(false, false, true, true, false, false).ID: return 4542; case BrownMushroomBlock::BrownMushroomBlock(false, false, true, false, true, true).ID: return 4543; case BrownMushroomBlock::BrownMushroomBlock(false, false, true, false, true, false).ID: return 4544; case BrownMushroomBlock::BrownMushroomBlock(false, false, true, false, false, true).ID: return 4545; case BrownMushroomBlock::BrownMushroomBlock(false, false, true, false, false, false).ID: return 4546; case BrownMushroomBlock::BrownMushroomBlock(false, false, false, true, true, true).ID: return 4547; case BrownMushroomBlock::BrownMushroomBlock(false, false, false, true, true, false).ID: return 4548; case BrownMushroomBlock::BrownMushroomBlock(false, false, false, true, false, true).ID: return 4549; case BrownMushroomBlock::BrownMushroomBlock(false, false, false, true, false, false).ID: return 4550; case BrownMushroomBlock::BrownMushroomBlock(false, false, false, false, true, true).ID: return 4551; case BrownMushroomBlock::BrownMushroomBlock(false, false, false, false, true, false).ID: return 4552; case BrownMushroomBlock::BrownMushroomBlock(false, false, false, false, false, true).ID: return 4553; case BrownMushroomBlock::BrownMushroomBlock(false, false, false, false, false, false).ID: return 4554; case BrownShulkerBox::BrownShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 8814; case BrownShulkerBox::BrownShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 8815; case BrownShulkerBox::BrownShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 8816; case BrownShulkerBox::BrownShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 8817; case BrownShulkerBox::BrownShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 8818; case BrownShulkerBox::BrownShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 8819; case BrownStainedGlass::BrownStainedGlass().ID: return 4093; case BrownStainedGlassPane::BrownStainedGlassPane(true, true, true, true).ID: return 6713; case BrownStainedGlassPane::BrownStainedGlassPane(true, true, true, false).ID: return 6714; case BrownStainedGlassPane::BrownStainedGlassPane(true, true, false, true).ID: return 6717; case BrownStainedGlassPane::BrownStainedGlassPane(true, true, false, false).ID: return 6718; case BrownStainedGlassPane::BrownStainedGlassPane(true, false, true, true).ID: return 6721; case BrownStainedGlassPane::BrownStainedGlassPane(true, false, true, false).ID: return 6722; case BrownStainedGlassPane::BrownStainedGlassPane(true, false, false, true).ID: return 6725; case BrownStainedGlassPane::BrownStainedGlassPane(true, false, false, false).ID: return 6726; case BrownStainedGlassPane::BrownStainedGlassPane(false, true, true, true).ID: return 6729; case BrownStainedGlassPane::BrownStainedGlassPane(false, true, true, false).ID: return 6730; case BrownStainedGlassPane::BrownStainedGlassPane(false, true, false, true).ID: return 6733; case BrownStainedGlassPane::BrownStainedGlassPane(false, true, false, false).ID: return 6734; case BrownStainedGlassPane::BrownStainedGlassPane(false, false, true, true).ID: return 6737; case BrownStainedGlassPane::BrownStainedGlassPane(false, false, true, false).ID: return 6738; case BrownStainedGlassPane::BrownStainedGlassPane(false, false, false, true).ID: return 6741; case BrownStainedGlassPane::BrownStainedGlassPane(false, false, false, false).ID: return 6742; case BrownTerracotta::BrownTerracotta().ID: return 6323; case BrownWallBanner::BrownWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 7665; case BrownWallBanner::BrownWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 7666; case BrownWallBanner::BrownWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 7667; case BrownWallBanner::BrownWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 7668; case BrownWool::BrownWool().ID: return 1395; case BubbleColumn::BubbleColumn(true).ID: return 9131; case BubbleColumn::BubbleColumn(false).ID: return 9132; case BubbleCoral::BubbleCoral().ID: return 8999; case BubbleCoralBlock::BubbleCoralBlock().ID: return 8981; case BubbleCoralFan::BubbleCoralFan().ID: return 9019; case BubbleCoralWallFan::BubbleCoralWallFan(eBlockFace::BLOCK_FACE_ZM).ID: return 9081; case BubbleCoralWallFan::BubbleCoralWallFan(eBlockFace::BLOCK_FACE_ZP).ID: return 9083; case BubbleCoralWallFan::BubbleCoralWallFan(eBlockFace::BLOCK_FACE_XM).ID: return 9085; case BubbleCoralWallFan::BubbleCoralWallFan(eBlockFace::BLOCK_FACE_XP).ID: return 9087; case Cactus::Cactus(0).ID: return 3929; case Cactus::Cactus(1).ID: return 3930; case Cactus::Cactus(2).ID: return 3931; case Cactus::Cactus(3).ID: return 3932; case Cactus::Cactus(4).ID: return 3933; case Cactus::Cactus(5).ID: return 3934; case Cactus::Cactus(6).ID: return 3935; case Cactus::Cactus(7).ID: return 3936; case Cactus::Cactus(8).ID: return 3937; case Cactus::Cactus(9).ID: return 3938; case Cactus::Cactus(10).ID: return 3939; case Cactus::Cactus(11).ID: return 3940; case Cactus::Cactus(12).ID: return 3941; case Cactus::Cactus(13).ID: return 3942; case Cactus::Cactus(14).ID: return 3943; case Cactus::Cactus(15).ID: return 3944; case Cake::Cake(0).ID: return 4010; case Cake::Cake(1).ID: return 4011; case Cake::Cake(2).ID: return 4012; case Cake::Cake(3).ID: return 4013; case Cake::Cake(4).ID: return 4014; case Cake::Cake(5).ID: return 4015; case Cake::Cake(6).ID: return 4016; case Campfire::Campfire(eBlockFace::BLOCK_FACE_ZM, true, true).ID: return 11233; case Campfire::Campfire(eBlockFace::BLOCK_FACE_ZM, true, false).ID: return 11235; case Campfire::Campfire(eBlockFace::BLOCK_FACE_ZM, false, true).ID: return 11237; case Campfire::Campfire(eBlockFace::BLOCK_FACE_ZM, false, false).ID: return 11239; case Campfire::Campfire(eBlockFace::BLOCK_FACE_ZP, true, true).ID: return 11241; case Campfire::Campfire(eBlockFace::BLOCK_FACE_ZP, true, false).ID: return 11243; case Campfire::Campfire(eBlockFace::BLOCK_FACE_ZP, false, true).ID: return 11245; case Campfire::Campfire(eBlockFace::BLOCK_FACE_ZP, false, false).ID: return 11247; case Campfire::Campfire(eBlockFace::BLOCK_FACE_XM, true, true).ID: return 11249; case Campfire::Campfire(eBlockFace::BLOCK_FACE_XM, true, false).ID: return 11251; case Campfire::Campfire(eBlockFace::BLOCK_FACE_XM, false, true).ID: return 11253; case Campfire::Campfire(eBlockFace::BLOCK_FACE_XM, false, false).ID: return 11255; case Campfire::Campfire(eBlockFace::BLOCK_FACE_XP, true, true).ID: return 11257; case Campfire::Campfire(eBlockFace::BLOCK_FACE_XP, true, false).ID: return 11259; case Campfire::Campfire(eBlockFace::BLOCK_FACE_XP, false, true).ID: return 11261; case Campfire::Campfire(eBlockFace::BLOCK_FACE_XP, false, false).ID: return 11263; case Carrots::Carrots(0).ID: return 5794; case Carrots::Carrots(1).ID: return 5795; case Carrots::Carrots(2).ID: return 5796; case Carrots::Carrots(3).ID: return 5797; case Carrots::Carrots(4).ID: return 5798; case Carrots::Carrots(5).ID: return 5799; case Carrots::Carrots(6).ID: return 5800; case Carrots::Carrots(7).ID: return 5801; case CartographyTable::CartographyTable().ID: return 11163; case CarvedPumpkin::CarvedPumpkin(eBlockFace::BLOCK_FACE_ZM).ID: return 4002; case CarvedPumpkin::CarvedPumpkin(eBlockFace::BLOCK_FACE_ZP).ID: return 4003; case CarvedPumpkin::CarvedPumpkin(eBlockFace::BLOCK_FACE_XM).ID: return 4004; case CarvedPumpkin::CarvedPumpkin(eBlockFace::BLOCK_FACE_XP).ID: return 4005; case Cauldron::Cauldron(0).ID: return 5125; case Cauldron::Cauldron(1).ID: return 5126; case Cauldron::Cauldron(2).ID: return 5127; case Cauldron::Cauldron(3).ID: return 5128; case CaveAir::CaveAir().ID: return 9130; case ChainCommandBlock::ChainCommandBlock(true, eBlockFace::BLOCK_FACE_ZM).ID: return 8701; case ChainCommandBlock::ChainCommandBlock(true, eBlockFace::BLOCK_FACE_XP).ID: return 8702; case ChainCommandBlock::ChainCommandBlock(true, eBlockFace::BLOCK_FACE_ZP).ID: return 8703; case ChainCommandBlock::ChainCommandBlock(true, eBlockFace::BLOCK_FACE_XM).ID: return 8704; case ChainCommandBlock::ChainCommandBlock(true, eBlockFace::BLOCK_FACE_YP).ID: return 8705; case ChainCommandBlock::ChainCommandBlock(true, eBlockFace::BLOCK_FACE_YM).ID: return 8706; case ChainCommandBlock::ChainCommandBlock(false, eBlockFace::BLOCK_FACE_ZM).ID: return 8707; case ChainCommandBlock::ChainCommandBlock(false, eBlockFace::BLOCK_FACE_XP).ID: return 8708; case ChainCommandBlock::ChainCommandBlock(false, eBlockFace::BLOCK_FACE_ZP).ID: return 8709; case ChainCommandBlock::ChainCommandBlock(false, eBlockFace::BLOCK_FACE_XM).ID: return 8710; case ChainCommandBlock::ChainCommandBlock(false, eBlockFace::BLOCK_FACE_YP).ID: return 8711; case ChainCommandBlock::ChainCommandBlock(false, eBlockFace::BLOCK_FACE_YM).ID: return 8712; case Chest::Chest(eBlockFace::BLOCK_FACE_ZM, Chest::Type::Single).ID: return 2033; case Chest::Chest(eBlockFace::BLOCK_FACE_ZM, Chest::Type::Left).ID: return 2035; case Chest::Chest(eBlockFace::BLOCK_FACE_ZM, Chest::Type::Right).ID: return 2037; case Chest::Chest(eBlockFace::BLOCK_FACE_ZP, Chest::Type::Single).ID: return 2039; case Chest::Chest(eBlockFace::BLOCK_FACE_ZP, Chest::Type::Left).ID: return 2041; case Chest::Chest(eBlockFace::BLOCK_FACE_ZP, Chest::Type::Right).ID: return 2043; case Chest::Chest(eBlockFace::BLOCK_FACE_XM, Chest::Type::Single).ID: return 2045; case Chest::Chest(eBlockFace::BLOCK_FACE_XM, Chest::Type::Left).ID: return 2047; case Chest::Chest(eBlockFace::BLOCK_FACE_XM, Chest::Type::Right).ID: return 2049; case Chest::Chest(eBlockFace::BLOCK_FACE_XP, Chest::Type::Single).ID: return 2051; case Chest::Chest(eBlockFace::BLOCK_FACE_XP, Chest::Type::Left).ID: return 2053; case Chest::Chest(eBlockFace::BLOCK_FACE_XP, Chest::Type::Right).ID: return 2055; case ChippedAnvil::ChippedAnvil(eBlockFace::BLOCK_FACE_ZM).ID: return 6078; case ChippedAnvil::ChippedAnvil(eBlockFace::BLOCK_FACE_ZP).ID: return 6079; case ChippedAnvil::ChippedAnvil(eBlockFace::BLOCK_FACE_XM).ID: return 6080; case ChippedAnvil::ChippedAnvil(eBlockFace::BLOCK_FACE_XP).ID: return 6081; case ChiseledQuartzBlock::ChiseledQuartzBlock().ID: return 6203; case ChiseledRedSandstone::ChiseledRedSandstone().ID: return 7682; case ChiseledSandstone::ChiseledSandstone().ID: return 246; case ChiseledStoneBricks::ChiseledStoneBricks().ID: return 4484; case ChorusFlower::ChorusFlower(0).ID: return 8592; case ChorusFlower::ChorusFlower(1).ID: return 8593; case ChorusFlower::ChorusFlower(2).ID: return 8594; case ChorusFlower::ChorusFlower(3).ID: return 8595; case ChorusFlower::ChorusFlower(4).ID: return 8596; case ChorusFlower::ChorusFlower(5).ID: return 8597; case ChorusPlant::ChorusPlant(true, true, true, true, true, true).ID: return 8528; case ChorusPlant::ChorusPlant(true, true, true, true, true, false).ID: return 8529; case ChorusPlant::ChorusPlant(true, true, true, true, false, true).ID: return 8530; case ChorusPlant::ChorusPlant(true, true, true, true, false, false).ID: return 8531; case ChorusPlant::ChorusPlant(true, true, true, false, true, true).ID: return 8532; case ChorusPlant::ChorusPlant(true, true, true, false, true, false).ID: return 8533; case ChorusPlant::ChorusPlant(true, true, true, false, false, true).ID: return 8534; case ChorusPlant::ChorusPlant(true, true, true, false, false, false).ID: return 8535; case ChorusPlant::ChorusPlant(true, true, false, true, true, true).ID: return 8536; case ChorusPlant::ChorusPlant(true, true, false, true, true, false).ID: return 8537; case ChorusPlant::ChorusPlant(true, true, false, true, false, true).ID: return 8538; case ChorusPlant::ChorusPlant(true, true, false, true, false, false).ID: return 8539; case ChorusPlant::ChorusPlant(true, true, false, false, true, true).ID: return 8540; case ChorusPlant::ChorusPlant(true, true, false, false, true, false).ID: return 8541; case ChorusPlant::ChorusPlant(true, true, false, false, false, true).ID: return 8542; case ChorusPlant::ChorusPlant(true, true, false, false, false, false).ID: return 8543; case ChorusPlant::ChorusPlant(true, false, true, true, true, true).ID: return 8544; case ChorusPlant::ChorusPlant(true, false, true, true, true, false).ID: return 8545; case ChorusPlant::ChorusPlant(true, false, true, true, false, true).ID: return 8546; case ChorusPlant::ChorusPlant(true, false, true, true, false, false).ID: return 8547; case ChorusPlant::ChorusPlant(true, false, true, false, true, true).ID: return 8548; case ChorusPlant::ChorusPlant(true, false, true, false, true, false).ID: return 8549; case ChorusPlant::ChorusPlant(true, false, true, false, false, true).ID: return 8550; case ChorusPlant::ChorusPlant(true, false, true, false, false, false).ID: return 8551; case ChorusPlant::ChorusPlant(true, false, false, true, true, true).ID: return 8552; case ChorusPlant::ChorusPlant(true, false, false, true, true, false).ID: return 8553; case ChorusPlant::ChorusPlant(true, false, false, true, false, true).ID: return 8554; case ChorusPlant::ChorusPlant(true, false, false, true, false, false).ID: return 8555; case ChorusPlant::ChorusPlant(true, false, false, false, true, true).ID: return 8556; case ChorusPlant::ChorusPlant(true, false, false, false, true, false).ID: return 8557; case ChorusPlant::ChorusPlant(true, false, false, false, false, true).ID: return 8558; case ChorusPlant::ChorusPlant(true, false, false, false, false, false).ID: return 8559; case ChorusPlant::ChorusPlant(false, true, true, true, true, true).ID: return 8560; case ChorusPlant::ChorusPlant(false, true, true, true, true, false).ID: return 8561; case ChorusPlant::ChorusPlant(false, true, true, true, false, true).ID: return 8562; case ChorusPlant::ChorusPlant(false, true, true, true, false, false).ID: return 8563; case ChorusPlant::ChorusPlant(false, true, true, false, true, true).ID: return 8564; case ChorusPlant::ChorusPlant(false, true, true, false, true, false).ID: return 8565; case ChorusPlant::ChorusPlant(false, true, true, false, false, true).ID: return 8566; case ChorusPlant::ChorusPlant(false, true, true, false, false, false).ID: return 8567; case ChorusPlant::ChorusPlant(false, true, false, true, true, true).ID: return 8568; case ChorusPlant::ChorusPlant(false, true, false, true, true, false).ID: return 8569; case ChorusPlant::ChorusPlant(false, true, false, true, false, true).ID: return 8570; case ChorusPlant::ChorusPlant(false, true, false, true, false, false).ID: return 8571; case ChorusPlant::ChorusPlant(false, true, false, false, true, true).ID: return 8572; case ChorusPlant::ChorusPlant(false, true, false, false, true, false).ID: return 8573; case ChorusPlant::ChorusPlant(false, true, false, false, false, true).ID: return 8574; case ChorusPlant::ChorusPlant(false, true, false, false, false, false).ID: return 8575; case ChorusPlant::ChorusPlant(false, false, true, true, true, true).ID: return 8576; case ChorusPlant::ChorusPlant(false, false, true, true, true, false).ID: return 8577; case ChorusPlant::ChorusPlant(false, false, true, true, false, true).ID: return 8578; case ChorusPlant::ChorusPlant(false, false, true, true, false, false).ID: return 8579; case ChorusPlant::ChorusPlant(false, false, true, false, true, true).ID: return 8580; case ChorusPlant::ChorusPlant(false, false, true, false, true, false).ID: return 8581; case ChorusPlant::ChorusPlant(false, false, true, false, false, true).ID: return 8582; case ChorusPlant::ChorusPlant(false, false, true, false, false, false).ID: return 8583; case ChorusPlant::ChorusPlant(false, false, false, true, true, true).ID: return 8584; case ChorusPlant::ChorusPlant(false, false, false, true, true, false).ID: return 8585; case ChorusPlant::ChorusPlant(false, false, false, true, false, true).ID: return 8586; case ChorusPlant::ChorusPlant(false, false, false, true, false, false).ID: return 8587; case ChorusPlant::ChorusPlant(false, false, false, false, true, true).ID: return 8588; case ChorusPlant::ChorusPlant(false, false, false, false, true, false).ID: return 8589; case ChorusPlant::ChorusPlant(false, false, false, false, false, true).ID: return 8590; case ChorusPlant::ChorusPlant(false, false, false, false, false, false).ID: return 8591; case Clay::Clay().ID: return 3945; case CoalBlock::CoalBlock().ID: return 7347; case CoalOre::CoalOre().ID: return 71; case CoarseDirt::CoarseDirt().ID: return 11; case Cobblestone::Cobblestone().ID: return 14; case CobblestoneSlab::CobblestoneSlab(CobblestoneSlab::Type::Top).ID: return 7831; case CobblestoneSlab::CobblestoneSlab(CobblestoneSlab::Type::Bottom).ID: return 7833; case CobblestoneSlab::CobblestoneSlab(CobblestoneSlab::Type::Double).ID: return 7835; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::Straight).ID: return 3654; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::InnerLeft).ID: return 3656; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::InnerRight).ID: return 3658; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::OuterLeft).ID: return 3660; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::OuterRight).ID: return 3662; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::Straight).ID: return 3664; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::InnerLeft).ID: return 3666; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::InnerRight).ID: return 3668; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::OuterLeft).ID: return 3670; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::OuterRight).ID: return 3672; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::Straight).ID: return 3674; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::InnerLeft).ID: return 3676; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::InnerRight).ID: return 3678; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::OuterLeft).ID: return 3680; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::OuterRight).ID: return 3682; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::Straight).ID: return 3684; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::InnerLeft).ID: return 3686; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::InnerRight).ID: return 3688; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::OuterLeft).ID: return 3690; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::OuterRight).ID: return 3692; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XM, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::Straight).ID: return 3694; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XM, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::InnerLeft).ID: return 3696; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XM, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::InnerRight).ID: return 3698; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XM, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::OuterLeft).ID: return 3700; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XM, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::OuterRight).ID: return 3702; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XM, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::Straight).ID: return 3704; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XM, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::InnerLeft).ID: return 3706; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XM, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::InnerRight).ID: return 3708; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XM, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::OuterLeft).ID: return 3710; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XM, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::OuterRight).ID: return 3712; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XP, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::Straight).ID: return 3714; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XP, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::InnerLeft).ID: return 3716; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XP, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::InnerRight).ID: return 3718; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XP, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::OuterLeft).ID: return 3720; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XP, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::OuterRight).ID: return 3722; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XP, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::Straight).ID: return 3724; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XP, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::InnerLeft).ID: return 3726; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XP, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::InnerRight).ID: return 3728; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XP, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::OuterLeft).ID: return 3730; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XP, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::OuterRight).ID: return 3732; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::Low, CobblestoneWall::South::Low, true, CobblestoneWall::West::Low).ID: return 5643; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::Low, CobblestoneWall::South::Low, true, CobblestoneWall::West::None).ID: return 5644; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::Low, CobblestoneWall::South::Low, false, CobblestoneWall::West::Low).ID: return 5647; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::Low, CobblestoneWall::South::Low, false, CobblestoneWall::West::None).ID: return 5648; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::Low, CobblestoneWall::South::None, true, CobblestoneWall::West::Low).ID: return 5651; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::Low, CobblestoneWall::South::None, true, CobblestoneWall::West::None).ID: return 5652; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::Low, CobblestoneWall::South::None, false, CobblestoneWall::West::Low).ID: return 5655; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::Low, CobblestoneWall::South::None, false, CobblestoneWall::West::None).ID: return 5656; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::None, CobblestoneWall::South::Low, true, CobblestoneWall::West::Low).ID: return 5659; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::None, CobblestoneWall::South::Low, true, CobblestoneWall::West::None).ID: return 5660; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::None, CobblestoneWall::South::Low, false, CobblestoneWall::West::Low).ID: return 5663; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::None, CobblestoneWall::South::Low, false, CobblestoneWall::West::None).ID: return 5664; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::None, CobblestoneWall::South::None, true, CobblestoneWall::West::Low).ID: return 5667; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::None, CobblestoneWall::South::None, true, CobblestoneWall::West::None).ID: return 5668; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::None, CobblestoneWall::South::None, false, CobblestoneWall::West::Low).ID: return 5671; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::None, CobblestoneWall::South::None, false, CobblestoneWall::West::None).ID: return 5672; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::Low, CobblestoneWall::South::Low, true, CobblestoneWall::West::Low).ID: return 5675; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::Low, CobblestoneWall::South::Low, true, CobblestoneWall::West::None).ID: return 5676; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::Low, CobblestoneWall::South::Low, false, CobblestoneWall::West::Low).ID: return 5679; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::Low, CobblestoneWall::South::Low, false, CobblestoneWall::West::None).ID: return 5680; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::Low, CobblestoneWall::South::None, true, CobblestoneWall::West::Low).ID: return 5683; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::Low, CobblestoneWall::South::None, true, CobblestoneWall::West::None).ID: return 5684; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::Low, CobblestoneWall::South::None, false, CobblestoneWall::West::Low).ID: return 5687; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::Low, CobblestoneWall::South::None, false, CobblestoneWall::West::None).ID: return 5688; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::None, CobblestoneWall::South::Low, true, CobblestoneWall::West::Low).ID: return 5691; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::None, CobblestoneWall::South::Low, true, CobblestoneWall::West::None).ID: return 5692; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::None, CobblestoneWall::South::Low, false, CobblestoneWall::West::Low).ID: return 5695; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::None, CobblestoneWall::South::Low, false, CobblestoneWall::West::None).ID: return 5696; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::None, CobblestoneWall::South::None, true, CobblestoneWall::West::Low).ID: return 5699; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::None, CobblestoneWall::South::None, true, CobblestoneWall::West::None).ID: return 5700; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::None, CobblestoneWall::South::None, false, CobblestoneWall::West::Low).ID: return 5703; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::None, CobblestoneWall::South::None, false, CobblestoneWall::West::None).ID: return 5704; case Cobweb::Cobweb().ID: return 1340; case Cocoa::Cocoa(0, eBlockFace::BLOCK_FACE_ZM).ID: return 5142; case Cocoa::Cocoa(0, eBlockFace::BLOCK_FACE_ZP).ID: return 5143; case Cocoa::Cocoa(0, eBlockFace::BLOCK_FACE_XM).ID: return 5144; case Cocoa::Cocoa(0, eBlockFace::BLOCK_FACE_XP).ID: return 5145; case Cocoa::Cocoa(1, eBlockFace::BLOCK_FACE_ZM).ID: return 5146; case Cocoa::Cocoa(1, eBlockFace::BLOCK_FACE_ZP).ID: return 5147; case Cocoa::Cocoa(1, eBlockFace::BLOCK_FACE_XM).ID: return 5148; case Cocoa::Cocoa(1, eBlockFace::BLOCK_FACE_XP).ID: return 5149; case Cocoa::Cocoa(2, eBlockFace::BLOCK_FACE_ZM).ID: return 5150; case Cocoa::Cocoa(2, eBlockFace::BLOCK_FACE_ZP).ID: return 5151; case Cocoa::Cocoa(2, eBlockFace::BLOCK_FACE_XM).ID: return 5152; case Cocoa::Cocoa(2, eBlockFace::BLOCK_FACE_XP).ID: return 5153; case CommandBlock::CommandBlock(true, eBlockFace::BLOCK_FACE_ZM).ID: return 5628; case CommandBlock::CommandBlock(true, eBlockFace::BLOCK_FACE_XP).ID: return 5629; case CommandBlock::CommandBlock(true, eBlockFace::BLOCK_FACE_ZP).ID: return 5630; case CommandBlock::CommandBlock(true, eBlockFace::BLOCK_FACE_XM).ID: return 5631; case CommandBlock::CommandBlock(true, eBlockFace::BLOCK_FACE_YP).ID: return 5632; case CommandBlock::CommandBlock(true, eBlockFace::BLOCK_FACE_YM).ID: return 5633; case CommandBlock::CommandBlock(false, eBlockFace::BLOCK_FACE_ZM).ID: return 5634; case CommandBlock::CommandBlock(false, eBlockFace::BLOCK_FACE_XP).ID: return 5635; case CommandBlock::CommandBlock(false, eBlockFace::BLOCK_FACE_ZP).ID: return 5636; case CommandBlock::CommandBlock(false, eBlockFace::BLOCK_FACE_XM).ID: return 5637; case CommandBlock::CommandBlock(false, eBlockFace::BLOCK_FACE_YP).ID: return 5638; case CommandBlock::CommandBlock(false, eBlockFace::BLOCK_FACE_YM).ID: return 5639; case Comparator::Comparator(eBlockFace::BLOCK_FACE_ZM, Comparator::Mode::Compare, true).ID: return 6142; case Comparator::Comparator(eBlockFace::BLOCK_FACE_ZM, Comparator::Mode::Compare, false).ID: return 6143; case Comparator::Comparator(eBlockFace::BLOCK_FACE_ZM, Comparator::Mode::Subtract, true).ID: return 6144; case Comparator::Comparator(eBlockFace::BLOCK_FACE_ZM, Comparator::Mode::Subtract, false).ID: return 6145; case Comparator::Comparator(eBlockFace::BLOCK_FACE_ZP, Comparator::Mode::Compare, true).ID: return 6146; case Comparator::Comparator(eBlockFace::BLOCK_FACE_ZP, Comparator::Mode::Compare, false).ID: return 6147; case Comparator::Comparator(eBlockFace::BLOCK_FACE_ZP, Comparator::Mode::Subtract, true).ID: return 6148; case Comparator::Comparator(eBlockFace::BLOCK_FACE_ZP, Comparator::Mode::Subtract, false).ID: return 6149; case Comparator::Comparator(eBlockFace::BLOCK_FACE_XM, Comparator::Mode::Compare, true).ID: return 6150; case Comparator::Comparator(eBlockFace::BLOCK_FACE_XM, Comparator::Mode::Compare, false).ID: return 6151; case Comparator::Comparator(eBlockFace::BLOCK_FACE_XM, Comparator::Mode::Subtract, true).ID: return 6152; case Comparator::Comparator(eBlockFace::BLOCK_FACE_XM, Comparator::Mode::Subtract, false).ID: return 6153; case Comparator::Comparator(eBlockFace::BLOCK_FACE_XP, Comparator::Mode::Compare, true).ID: return 6154; case Comparator::Comparator(eBlockFace::BLOCK_FACE_XP, Comparator::Mode::Compare, false).ID: return 6155; case Comparator::Comparator(eBlockFace::BLOCK_FACE_XP, Comparator::Mode::Subtract, true).ID: return 6156; case Comparator::Comparator(eBlockFace::BLOCK_FACE_XP, Comparator::Mode::Subtract, false).ID: return 6157; case Composter::Composter(0).ID: return 11278; case Composter::Composter(1).ID: return 11279; case Composter::Composter(2).ID: return 11280; case Composter::Composter(3).ID: return 11281; case Composter::Composter(4).ID: return 11282; case Composter::Composter(5).ID: return 11283; case Composter::Composter(6).ID: return 11284; case Composter::Composter(7).ID: return 11285; case Composter::Composter(8).ID: return 11286; case Conduit::Conduit().ID: return 9114; case Cornflower::Cornflower().ID: return 1421; case CrackedStoneBricks::CrackedStoneBricks().ID: return 4483; case CraftingTable::CraftingTable().ID: return 3354; case CreeperHead::CreeperHead(0).ID: return 6034; case CreeperHead::CreeperHead(1).ID: return 6035; case CreeperHead::CreeperHead(2).ID: return 6036; case CreeperHead::CreeperHead(3).ID: return 6037; case CreeperHead::CreeperHead(4).ID: return 6038; case CreeperHead::CreeperHead(5).ID: return 6039; case CreeperHead::CreeperHead(6).ID: return 6040; case CreeperHead::CreeperHead(7).ID: return 6041; case CreeperHead::CreeperHead(8).ID: return 6042; case CreeperHead::CreeperHead(9).ID: return 6043; case CreeperHead::CreeperHead(10).ID: return 6044; case CreeperHead::CreeperHead(11).ID: return 6045; case CreeperHead::CreeperHead(12).ID: return 6046; case CreeperHead::CreeperHead(13).ID: return 6047; case CreeperHead::CreeperHead(14).ID: return 6048; case CreeperHead::CreeperHead(15).ID: return 6049; case CreeperWallHead::CreeperWallHead(eBlockFace::BLOCK_FACE_ZM).ID: return 6050; case CreeperWallHead::CreeperWallHead(eBlockFace::BLOCK_FACE_ZP).ID: return 6051; case CreeperWallHead::CreeperWallHead(eBlockFace::BLOCK_FACE_XM).ID: return 6052; case CreeperWallHead::CreeperWallHead(eBlockFace::BLOCK_FACE_XP).ID: return 6053; case CutRedSandstone::CutRedSandstone().ID: return 7683; case CutRedSandstoneSlab::CutRedSandstoneSlab(CutRedSandstoneSlab::Type::Top).ID: return 7867; case CutRedSandstoneSlab::CutRedSandstoneSlab(CutRedSandstoneSlab::Type::Bottom).ID: return 7869; case CutRedSandstoneSlab::CutRedSandstoneSlab(CutRedSandstoneSlab::Type::Double).ID: return 7871; case CutSandstone::CutSandstone().ID: return 247; case CutSandstoneSlab::CutSandstoneSlab(CutSandstoneSlab::Type::Top).ID: return 7819; case CutSandstoneSlab::CutSandstoneSlab(CutSandstoneSlab::Type::Bottom).ID: return 7821; case CutSandstoneSlab::CutSandstoneSlab(CutSandstoneSlab::Type::Double).ID: return 7823; case CyanBanner::CyanBanner(0).ID: return 7505; case CyanBanner::CyanBanner(1).ID: return 7506; case CyanBanner::CyanBanner(2).ID: return 7507; case CyanBanner::CyanBanner(3).ID: return 7508; case CyanBanner::CyanBanner(4).ID: return 7509; case CyanBanner::CyanBanner(5).ID: return 7510; case CyanBanner::CyanBanner(6).ID: return 7511; case CyanBanner::CyanBanner(7).ID: return 7512; case CyanBanner::CyanBanner(8).ID: return 7513; case CyanBanner::CyanBanner(9).ID: return 7514; case CyanBanner::CyanBanner(10).ID: return 7515; case CyanBanner::CyanBanner(11).ID: return 7516; case CyanBanner::CyanBanner(12).ID: return 7517; case CyanBanner::CyanBanner(13).ID: return 7518; case CyanBanner::CyanBanner(14).ID: return 7519; case CyanBanner::CyanBanner(15).ID: return 7520; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_ZM, true, CyanBed::Part::Head).ID: return 1192; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_ZM, true, CyanBed::Part::Foot).ID: return 1193; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_ZM, false, CyanBed::Part::Head).ID: return 1194; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_ZM, false, CyanBed::Part::Foot).ID: return 1195; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_ZP, true, CyanBed::Part::Head).ID: return 1196; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_ZP, true, CyanBed::Part::Foot).ID: return 1197; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_ZP, false, CyanBed::Part::Head).ID: return 1198; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_ZP, false, CyanBed::Part::Foot).ID: return 1199; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_XM, true, CyanBed::Part::Head).ID: return 1200; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_XM, true, CyanBed::Part::Foot).ID: return 1201; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_XM, false, CyanBed::Part::Head).ID: return 1202; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_XM, false, CyanBed::Part::Foot).ID: return 1203; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_XP, true, CyanBed::Part::Head).ID: return 1204; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_XP, true, CyanBed::Part::Foot).ID: return 1205; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_XP, false, CyanBed::Part::Head).ID: return 1206; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_XP, false, CyanBed::Part::Foot).ID: return 1207; case CyanCarpet::CyanCarpet().ID: return 7339; case CyanConcrete::CyanConcrete().ID: return 8911; case CyanConcretePowder::CyanConcretePowder().ID: return 8927; case CyanGlazedTerracotta::CyanGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 8874; case CyanGlazedTerracotta::CyanGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 8875; case CyanGlazedTerracotta::CyanGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 8876; case CyanGlazedTerracotta::CyanGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 8877; case CyanShulkerBox::CyanShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 8796; case CyanShulkerBox::CyanShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 8797; case CyanShulkerBox::CyanShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 8798; case CyanShulkerBox::CyanShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 8799; case CyanShulkerBox::CyanShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 8800; case CyanShulkerBox::CyanShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 8801; case CyanStainedGlass::CyanStainedGlass().ID: return 4090; case CyanStainedGlassPane::CyanStainedGlassPane(true, true, true, true).ID: return 6617; case CyanStainedGlassPane::CyanStainedGlassPane(true, true, true, false).ID: return 6618; case CyanStainedGlassPane::CyanStainedGlassPane(true, true, false, true).ID: return 6621; case CyanStainedGlassPane::CyanStainedGlassPane(true, true, false, false).ID: return 6622; case CyanStainedGlassPane::CyanStainedGlassPane(true, false, true, true).ID: return 6625; case CyanStainedGlassPane::CyanStainedGlassPane(true, false, true, false).ID: return 6626; case CyanStainedGlassPane::CyanStainedGlassPane(true, false, false, true).ID: return 6629; case CyanStainedGlassPane::CyanStainedGlassPane(true, false, false, false).ID: return 6630; case CyanStainedGlassPane::CyanStainedGlassPane(false, true, true, true).ID: return 6633; case CyanStainedGlassPane::CyanStainedGlassPane(false, true, true, false).ID: return 6634; case CyanStainedGlassPane::CyanStainedGlassPane(false, true, false, true).ID: return 6637; case CyanStainedGlassPane::CyanStainedGlassPane(false, true, false, false).ID: return 6638; case CyanStainedGlassPane::CyanStainedGlassPane(false, false, true, true).ID: return 6641; case CyanStainedGlassPane::CyanStainedGlassPane(false, false, true, false).ID: return 6642; case CyanStainedGlassPane::CyanStainedGlassPane(false, false, false, true).ID: return 6645; case CyanStainedGlassPane::CyanStainedGlassPane(false, false, false, false).ID: return 6646; case CyanTerracotta::CyanTerracotta().ID: return 6320; case CyanWallBanner::CyanWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 7653; case CyanWallBanner::CyanWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 7654; case CyanWallBanner::CyanWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 7655; case CyanWallBanner::CyanWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 7656; case CyanWool::CyanWool().ID: return 1392; case DamagedAnvil::DamagedAnvil(eBlockFace::BLOCK_FACE_ZM).ID: return 6082; case DamagedAnvil::DamagedAnvil(eBlockFace::BLOCK_FACE_ZP).ID: return 6083; case DamagedAnvil::DamagedAnvil(eBlockFace::BLOCK_FACE_XM).ID: return 6084; case DamagedAnvil::DamagedAnvil(eBlockFace::BLOCK_FACE_XP).ID: return 6085; case Dandelion::Dandelion().ID: return 1411; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5930; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5931; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5932; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5933; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, true).ID: return 5934; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, false).ID: return 5935; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, true).ID: return 5936; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, false).ID: return 5937; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5938; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5939; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5940; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5941; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, true).ID: return 5942; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, false).ID: return 5943; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, true).ID: return 5944; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, false).ID: return 5945; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5946; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5947; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5948; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5949; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, true).ID: return 5950; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, false).ID: return 5951; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, true).ID: return 5952; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, false).ID: return 5953; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, true, true).ID: return 8458; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, true, false).ID: return 8459; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, false, true).ID: return 8460; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, false, false).ID: return 8461; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, true, true).ID: return 8462; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, true, false).ID: return 8463; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, false, true).ID: return 8464; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, false, false).ID: return 8465; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, true, true).ID: return 8466; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, true, false).ID: return 8467; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, false, true).ID: return 8468; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, false, false).ID: return 8469; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, true, true).ID: return 8470; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, true, false).ID: return 8471; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, false, true).ID: return 8472; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, false, false).ID: return 8473; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, true, true).ID: return 8474; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, true, false).ID: return 8475; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, false, true).ID: return 8476; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, false, false).ID: return 8477; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, true, true).ID: return 8478; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, true, false).ID: return 8479; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, false, true).ID: return 8480; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, false, false).ID: return 8481; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, true, true).ID: return 8482; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, true, false).ID: return 8483; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, false, true).ID: return 8484; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, false, false).ID: return 8485; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, true, true).ID: return 8486; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, true, false).ID: return 8487; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, false, true).ID: return 8488; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, false, false).ID: return 8489; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, true, true).ID: return 8490; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, true, false).ID: return 8491; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, false, true).ID: return 8492; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, false, false).ID: return 8493; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, true, true).ID: return 8494; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, true, false).ID: return 8495; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, false, true).ID: return 8496; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, false, false).ID: return 8497; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, true, true).ID: return 8498; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, true, false).ID: return 8499; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, false, true).ID: return 8500; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, false, false).ID: return 8501; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, true, true).ID: return 8502; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, true, false).ID: return 8503; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, false, true).ID: return 8504; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, false, false).ID: return 8505; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, true, true).ID: return 8506; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, true, false).ID: return 8507; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, false, true).ID: return 8508; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, false, false).ID: return 8509; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, true, true).ID: return 8510; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, true, false).ID: return 8511; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, false, true).ID: return 8512; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, false, false).ID: return 8513; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, true, true).ID: return 8514; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, true, false).ID: return 8515; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, false, true).ID: return 8516; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, false, false).ID: return 8517; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, true, true).ID: return 8518; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, true, false).ID: return 8519; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, false, true).ID: return 8520; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, false, false).ID: return 8521; case DarkOakFence::DarkOakFence(true, true, true, true).ID: return 8172; case DarkOakFence::DarkOakFence(true, true, true, false).ID: return 8173; case DarkOakFence::DarkOakFence(true, true, false, true).ID: return 8176; case DarkOakFence::DarkOakFence(true, true, false, false).ID: return 8177; case DarkOakFence::DarkOakFence(true, false, true, true).ID: return 8180; case DarkOakFence::DarkOakFence(true, false, true, false).ID: return 8181; case DarkOakFence::DarkOakFence(true, false, false, true).ID: return 8184; case DarkOakFence::DarkOakFence(true, false, false, false).ID: return 8185; case DarkOakFence::DarkOakFence(false, true, true, true).ID: return 8188; case DarkOakFence::DarkOakFence(false, true, true, false).ID: return 8189; case DarkOakFence::DarkOakFence(false, true, false, true).ID: return 8192; case DarkOakFence::DarkOakFence(false, true, false, false).ID: return 8193; case DarkOakFence::DarkOakFence(false, false, true, true).ID: return 8196; case DarkOakFence::DarkOakFence(false, false, true, false).ID: return 8197; case DarkOakFence::DarkOakFence(false, false, false, true).ID: return 8200; case DarkOakFence::DarkOakFence(false, false, false, false).ID: return 8201; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZM, true, true, true).ID: return 8010; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZM, true, true, false).ID: return 8011; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZM, true, false, true).ID: return 8012; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZM, true, false, false).ID: return 8013; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, true).ID: return 8014; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, false).ID: return 8015; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, true).ID: return 8016; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, false).ID: return 8017; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZP, true, true, true).ID: return 8018; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZP, true, true, false).ID: return 8019; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZP, true, false, true).ID: return 8020; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZP, true, false, false).ID: return 8021; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, true).ID: return 8022; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, false).ID: return 8023; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, true).ID: return 8024; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, false).ID: return 8025; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XM, true, true, true).ID: return 8026; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XM, true, true, false).ID: return 8027; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XM, true, false, true).ID: return 8028; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XM, true, false, false).ID: return 8029; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, true).ID: return 8030; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, false).ID: return 8031; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, true).ID: return 8032; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, false).ID: return 8033; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XP, true, true, true).ID: return 8034; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XP, true, true, false).ID: return 8035; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XP, true, false, true).ID: return 8036; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XP, true, false, false).ID: return 8037; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, true).ID: return 8038; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, false).ID: return 8039; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, true).ID: return 8040; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, false).ID: return 8041; case DarkOakLeaves::DarkOakLeaves(1, true).ID: return 214; case DarkOakLeaves::DarkOakLeaves(1, false).ID: return 215; case DarkOakLeaves::DarkOakLeaves(2, true).ID: return 216; case DarkOakLeaves::DarkOakLeaves(2, false).ID: return 217; case DarkOakLeaves::DarkOakLeaves(3, true).ID: return 218; case DarkOakLeaves::DarkOakLeaves(3, false).ID: return 219; case DarkOakLeaves::DarkOakLeaves(4, true).ID: return 220; case DarkOakLeaves::DarkOakLeaves(4, false).ID: return 221; case DarkOakLeaves::DarkOakLeaves(5, true).ID: return 222; case DarkOakLeaves::DarkOakLeaves(5, false).ID: return 223; case DarkOakLeaves::DarkOakLeaves(6, true).ID: return 224; case DarkOakLeaves::DarkOakLeaves(6, false).ID: return 225; case DarkOakLeaves::DarkOakLeaves(7, true).ID: return 226; case DarkOakLeaves::DarkOakLeaves(7, false).ID: return 227; case DarkOakLog::DarkOakLog(DarkOakLog::Axis::X).ID: return 87; case DarkOakLog::DarkOakLog(DarkOakLog::Axis::Y).ID: return 88; case DarkOakLog::DarkOakLog(DarkOakLog::Axis::Z).ID: return 89; case DarkOakPlanks::DarkOakPlanks().ID: return 20; case DarkOakPressurePlate::DarkOakPressurePlate(true).ID: return 3881; case DarkOakPressurePlate::DarkOakPressurePlate(false).ID: return 3882; case DarkOakSapling::DarkOakSapling(0).ID: return 31; case DarkOakSapling::DarkOakSapling(1).ID: return 32; case DarkOakSign::DarkOakSign(0).ID: return 3540; case DarkOakSign::DarkOakSign(1).ID: return 3542; case DarkOakSign::DarkOakSign(2).ID: return 3544; case DarkOakSign::DarkOakSign(3).ID: return 3546; case DarkOakSign::DarkOakSign(4).ID: return 3548; case DarkOakSign::DarkOakSign(5).ID: return 3550; case DarkOakSign::DarkOakSign(6).ID: return 3552; case DarkOakSign::DarkOakSign(7).ID: return 3554; case DarkOakSign::DarkOakSign(8).ID: return 3556; case DarkOakSign::DarkOakSign(9).ID: return 3558; case DarkOakSign::DarkOakSign(10).ID: return 3560; case DarkOakSign::DarkOakSign(11).ID: return 3562; case DarkOakSign::DarkOakSign(12).ID: return 3564; case DarkOakSign::DarkOakSign(13).ID: return 3566; case DarkOakSign::DarkOakSign(14).ID: return 3568; case DarkOakSign::DarkOakSign(15).ID: return 3570; case DarkOakSlab::DarkOakSlab(DarkOakSlab::Type::Top).ID: return 7795; case DarkOakSlab::DarkOakSlab(DarkOakSlab::Type::Bottom).ID: return 7797; case DarkOakSlab::DarkOakSlab(DarkOakSlab::Type::Double).ID: return 7799; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZM, DarkOakStairs::Half::Top, DarkOakStairs::Shape::Straight).ID: return 6920; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZM, DarkOakStairs::Half::Top, DarkOakStairs::Shape::InnerLeft).ID: return 6922; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZM, DarkOakStairs::Half::Top, DarkOakStairs::Shape::InnerRight).ID: return 6924; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZM, DarkOakStairs::Half::Top, DarkOakStairs::Shape::OuterLeft).ID: return 6926; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZM, DarkOakStairs::Half::Top, DarkOakStairs::Shape::OuterRight).ID: return 6928; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZM, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::Straight).ID: return 6930; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZM, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::InnerLeft).ID: return 6932; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZM, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::InnerRight).ID: return 6934; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZM, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::OuterLeft).ID: return 6936; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZM, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::OuterRight).ID: return 6938; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZP, DarkOakStairs::Half::Top, DarkOakStairs::Shape::Straight).ID: return 6940; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZP, DarkOakStairs::Half::Top, DarkOakStairs::Shape::InnerLeft).ID: return 6942; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZP, DarkOakStairs::Half::Top, DarkOakStairs::Shape::InnerRight).ID: return 6944; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZP, DarkOakStairs::Half::Top, DarkOakStairs::Shape::OuterLeft).ID: return 6946; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZP, DarkOakStairs::Half::Top, DarkOakStairs::Shape::OuterRight).ID: return 6948; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZP, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::Straight).ID: return 6950; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZP, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::InnerLeft).ID: return 6952; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZP, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::InnerRight).ID: return 6954; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZP, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::OuterLeft).ID: return 6956; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZP, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::OuterRight).ID: return 6958; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XM, DarkOakStairs::Half::Top, DarkOakStairs::Shape::Straight).ID: return 6960; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XM, DarkOakStairs::Half::Top, DarkOakStairs::Shape::InnerLeft).ID: return 6962; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XM, DarkOakStairs::Half::Top, DarkOakStairs::Shape::InnerRight).ID: return 6964; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XM, DarkOakStairs::Half::Top, DarkOakStairs::Shape::OuterLeft).ID: return 6966; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XM, DarkOakStairs::Half::Top, DarkOakStairs::Shape::OuterRight).ID: return 6968; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XM, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::Straight).ID: return 6970; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XM, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::InnerLeft).ID: return 6972; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XM, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::InnerRight).ID: return 6974; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XM, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::OuterLeft).ID: return 6976; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XM, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::OuterRight).ID: return 6978; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XP, DarkOakStairs::Half::Top, DarkOakStairs::Shape::Straight).ID: return 6980; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XP, DarkOakStairs::Half::Top, DarkOakStairs::Shape::InnerLeft).ID: return 6982; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XP, DarkOakStairs::Half::Top, DarkOakStairs::Shape::InnerRight).ID: return 6984; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XP, DarkOakStairs::Half::Top, DarkOakStairs::Shape::OuterLeft).ID: return 6986; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XP, DarkOakStairs::Half::Top, DarkOakStairs::Shape::OuterRight).ID: return 6988; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XP, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::Straight).ID: return 6990; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XP, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::InnerLeft).ID: return 6992; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XP, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::InnerRight).ID: return 6994; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XP, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::OuterLeft).ID: return 6996; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XP, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::OuterRight).ID: return 6998; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZM, DarkOakTrapdoor::Half::Top, true, true).ID: return 4418; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZM, DarkOakTrapdoor::Half::Top, true, false).ID: return 4420; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZM, DarkOakTrapdoor::Half::Top, false, true).ID: return 4422; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZM, DarkOakTrapdoor::Half::Top, false, false).ID: return 4424; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZM, DarkOakTrapdoor::Half::Bottom, true, true).ID: return 4426; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZM, DarkOakTrapdoor::Half::Bottom, true, false).ID: return 4428; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZM, DarkOakTrapdoor::Half::Bottom, false, true).ID: return 4430; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZM, DarkOakTrapdoor::Half::Bottom, false, false).ID: return 4432; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZP, DarkOakTrapdoor::Half::Top, true, true).ID: return 4434; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZP, DarkOakTrapdoor::Half::Top, true, false).ID: return 4436; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZP, DarkOakTrapdoor::Half::Top, false, true).ID: return 4438; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZP, DarkOakTrapdoor::Half::Top, false, false).ID: return 4440; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZP, DarkOakTrapdoor::Half::Bottom, true, true).ID: return 4442; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZP, DarkOakTrapdoor::Half::Bottom, true, false).ID: return 4444; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZP, DarkOakTrapdoor::Half::Bottom, false, true).ID: return 4446; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZP, DarkOakTrapdoor::Half::Bottom, false, false).ID: return 4448; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XM, DarkOakTrapdoor::Half::Top, true, true).ID: return 4450; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XM, DarkOakTrapdoor::Half::Top, true, false).ID: return 4452; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XM, DarkOakTrapdoor::Half::Top, false, true).ID: return 4454; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XM, DarkOakTrapdoor::Half::Top, false, false).ID: return 4456; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XM, DarkOakTrapdoor::Half::Bottom, true, true).ID: return 4458; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XM, DarkOakTrapdoor::Half::Bottom, true, false).ID: return 4460; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XM, DarkOakTrapdoor::Half::Bottom, false, true).ID: return 4462; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XM, DarkOakTrapdoor::Half::Bottom, false, false).ID: return 4464; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XP, DarkOakTrapdoor::Half::Top, true, true).ID: return 4466; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XP, DarkOakTrapdoor::Half::Top, true, false).ID: return 4468; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XP, DarkOakTrapdoor::Half::Top, false, true).ID: return 4470; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XP, DarkOakTrapdoor::Half::Top, false, false).ID: return 4472; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XP, DarkOakTrapdoor::Half::Bottom, true, true).ID: return 4474; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XP, DarkOakTrapdoor::Half::Bottom, true, false).ID: return 4476; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XP, DarkOakTrapdoor::Half::Bottom, false, true).ID: return 4478; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XP, DarkOakTrapdoor::Half::Bottom, false, false).ID: return 4480; case DarkOakWallSign::DarkOakWallSign(eBlockFace::BLOCK_FACE_ZM).ID: return 3774; case DarkOakWallSign::DarkOakWallSign(eBlockFace::BLOCK_FACE_ZP).ID: return 3776; case DarkOakWallSign::DarkOakWallSign(eBlockFace::BLOCK_FACE_XM).ID: return 3778; case DarkOakWallSign::DarkOakWallSign(eBlockFace::BLOCK_FACE_XP).ID: return 3780; case DarkOakWood::DarkOakWood(DarkOakWood::Axis::X).ID: return 123; case DarkOakWood::DarkOakWood(DarkOakWood::Axis::Y).ID: return 124; case DarkOakWood::DarkOakWood(DarkOakWood::Axis::Z).ID: return 125; case DarkPrismarine::DarkPrismarine().ID: return 7067; case DarkPrismarineSlab::DarkPrismarineSlab(DarkPrismarineSlab::Type::Top).ID: return 7321; case DarkPrismarineSlab::DarkPrismarineSlab(DarkPrismarineSlab::Type::Bottom).ID: return 7323; case DarkPrismarineSlab::DarkPrismarineSlab(DarkPrismarineSlab::Type::Double).ID: return 7325; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZM, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::Straight).ID: return 7229; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZM, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::InnerLeft).ID: return 7231; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZM, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::InnerRight).ID: return 7233; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZM, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::OuterLeft).ID: return 7235; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZM, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::OuterRight).ID: return 7237; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZM, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::Straight).ID: return 7239; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZM, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::InnerLeft).ID: return 7241; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZM, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::InnerRight).ID: return 7243; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZM, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::OuterLeft).ID: return 7245; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZM, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::OuterRight).ID: return 7247; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZP, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::Straight).ID: return 7249; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZP, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::InnerLeft).ID: return 7251; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZP, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::InnerRight).ID: return 7253; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZP, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::OuterLeft).ID: return 7255; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZP, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::OuterRight).ID: return 7257; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZP, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::Straight).ID: return 7259; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZP, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::InnerLeft).ID: return 7261; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZP, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::InnerRight).ID: return 7263; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZP, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::OuterLeft).ID: return 7265; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZP, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::OuterRight).ID: return 7267; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XM, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::Straight).ID: return 7269; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XM, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::InnerLeft).ID: return 7271; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XM, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::InnerRight).ID: return 7273; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XM, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::OuterLeft).ID: return 7275; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XM, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::OuterRight).ID: return 7277; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XM, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::Straight).ID: return 7279; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XM, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::InnerLeft).ID: return 7281; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XM, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::InnerRight).ID: return 7283; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XM, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::OuterLeft).ID: return 7285; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XM, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::OuterRight).ID: return 7287; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XP, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::Straight).ID: return 7289; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XP, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::InnerLeft).ID: return 7291; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XP, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::InnerRight).ID: return 7293; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XP, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::OuterLeft).ID: return 7295; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XP, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::OuterRight).ID: return 7297; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XP, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::Straight).ID: return 7299; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XP, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::InnerLeft).ID: return 7301; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XP, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::InnerRight).ID: return 7303; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XP, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::OuterLeft).ID: return 7305; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XP, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::OuterRight).ID: return 7307; case DaylightDetector::DaylightDetector(true, 0).ID: return 6158; case DaylightDetector::DaylightDetector(true, 1).ID: return 6159; case DaylightDetector::DaylightDetector(true, 2).ID: return 6160; case DaylightDetector::DaylightDetector(true, 3).ID: return 6161; case DaylightDetector::DaylightDetector(true, 4).ID: return 6162; case DaylightDetector::DaylightDetector(true, 5).ID: return 6163; case DaylightDetector::DaylightDetector(true, 6).ID: return 6164; case DaylightDetector::DaylightDetector(true, 7).ID: return 6165; case DaylightDetector::DaylightDetector(true, 8).ID: return 6166; case DaylightDetector::DaylightDetector(true, 9).ID: return 6167; case DaylightDetector::DaylightDetector(true, 10).ID: return 6168; case DaylightDetector::DaylightDetector(true, 11).ID: return 6169; case DaylightDetector::DaylightDetector(true, 12).ID: return 6170; case DaylightDetector::DaylightDetector(true, 13).ID: return 6171; case DaylightDetector::DaylightDetector(true, 14).ID: return 6172; case DaylightDetector::DaylightDetector(true, 15).ID: return 6173; case DaylightDetector::DaylightDetector(false, 0).ID: return 6174; case DaylightDetector::DaylightDetector(false, 1).ID: return 6175; case DaylightDetector::DaylightDetector(false, 2).ID: return 6176; case DaylightDetector::DaylightDetector(false, 3).ID: return 6177; case DaylightDetector::DaylightDetector(false, 4).ID: return 6178; case DaylightDetector::DaylightDetector(false, 5).ID: return 6179; case DaylightDetector::DaylightDetector(false, 6).ID: return 6180; case DaylightDetector::DaylightDetector(false, 7).ID: return 6181; case DaylightDetector::DaylightDetector(false, 8).ID: return 6182; case DaylightDetector::DaylightDetector(false, 9).ID: return 6183; case DaylightDetector::DaylightDetector(false, 10).ID: return 6184; case DaylightDetector::DaylightDetector(false, 11).ID: return 6185; case DaylightDetector::DaylightDetector(false, 12).ID: return 6186; case DaylightDetector::DaylightDetector(false, 13).ID: return 6187; case DaylightDetector::DaylightDetector(false, 14).ID: return 6188; case DaylightDetector::DaylightDetector(false, 15).ID: return 6189; case DeadBrainCoral::DeadBrainCoral().ID: return 8987; case DeadBrainCoralBlock::DeadBrainCoralBlock().ID: return 8975; case DeadBrainCoralFan::DeadBrainCoralFan().ID: return 9007; case DeadBrainCoralWallFan::DeadBrainCoralWallFan(eBlockFace::BLOCK_FACE_ZM).ID: return 9033; case DeadBrainCoralWallFan::DeadBrainCoralWallFan(eBlockFace::BLOCK_FACE_ZP).ID: return 9035; case DeadBrainCoralWallFan::DeadBrainCoralWallFan(eBlockFace::BLOCK_FACE_XM).ID: return 9037; case DeadBrainCoralWallFan::DeadBrainCoralWallFan(eBlockFace::BLOCK_FACE_XP).ID: return 9039; case DeadBubbleCoral::DeadBubbleCoral().ID: return 8989; case DeadBubbleCoralBlock::DeadBubbleCoralBlock().ID: return 8976; case DeadBubbleCoralFan::DeadBubbleCoralFan().ID: return 9009; case DeadBubbleCoralWallFan::DeadBubbleCoralWallFan(eBlockFace::BLOCK_FACE_ZM).ID: return 9041; case DeadBubbleCoralWallFan::DeadBubbleCoralWallFan(eBlockFace::BLOCK_FACE_ZP).ID: return 9043; case DeadBubbleCoralWallFan::DeadBubbleCoralWallFan(eBlockFace::BLOCK_FACE_XM).ID: return 9045; case DeadBubbleCoralWallFan::DeadBubbleCoralWallFan(eBlockFace::BLOCK_FACE_XP).ID: return 9047; case DeadBush::DeadBush().ID: return 1343; case DeadFireCoral::DeadFireCoral().ID: return 8991; case DeadFireCoralBlock::DeadFireCoralBlock().ID: return 8977; case DeadFireCoralFan::DeadFireCoralFan().ID: return 9011; case DeadFireCoralWallFan::DeadFireCoralWallFan(eBlockFace::BLOCK_FACE_ZM).ID: return 9049; case DeadFireCoralWallFan::DeadFireCoralWallFan(eBlockFace::BLOCK_FACE_ZP).ID: return 9051; case DeadFireCoralWallFan::DeadFireCoralWallFan(eBlockFace::BLOCK_FACE_XM).ID: return 9053; case DeadFireCoralWallFan::DeadFireCoralWallFan(eBlockFace::BLOCK_FACE_XP).ID: return 9055; case DeadHornCoral::DeadHornCoral().ID: return 8993; case DeadHornCoralBlock::DeadHornCoralBlock().ID: return 8978; case DeadHornCoralFan::DeadHornCoralFan().ID: return 9013; case DeadHornCoralWallFan::DeadHornCoralWallFan(eBlockFace::BLOCK_FACE_ZM).ID: return 9057; case DeadHornCoralWallFan::DeadHornCoralWallFan(eBlockFace::BLOCK_FACE_ZP).ID: return 9059; case DeadHornCoralWallFan::DeadHornCoralWallFan(eBlockFace::BLOCK_FACE_XM).ID: return 9061; case DeadHornCoralWallFan::DeadHornCoralWallFan(eBlockFace::BLOCK_FACE_XP).ID: return 9063; case DeadTubeCoral::DeadTubeCoral().ID: return 8985; case DeadTubeCoralBlock::DeadTubeCoralBlock().ID: return 8974; case DeadTubeCoralFan::DeadTubeCoralFan().ID: return 9005; case DeadTubeCoralWallFan::DeadTubeCoralWallFan(eBlockFace::BLOCK_FACE_ZM).ID: return 9025; case DeadTubeCoralWallFan::DeadTubeCoralWallFan(eBlockFace::BLOCK_FACE_ZP).ID: return 9027; case DeadTubeCoralWallFan::DeadTubeCoralWallFan(eBlockFace::BLOCK_FACE_XM).ID: return 9029; case DeadTubeCoralWallFan::DeadTubeCoralWallFan(eBlockFace::BLOCK_FACE_XP).ID: return 9031; case DetectorRail::DetectorRail(true, DetectorRail::Shape::NorthSouth).ID: return 1316; case DetectorRail::DetectorRail(true, DetectorRail::Shape::EastWest).ID: return 1317; case DetectorRail::DetectorRail(true, DetectorRail::Shape::AscendingEast).ID: return 1318; case DetectorRail::DetectorRail(true, DetectorRail::Shape::AscendingWest).ID: return 1319; case DetectorRail::DetectorRail(true, DetectorRail::Shape::AscendingNorth).ID: return 1320; case DetectorRail::DetectorRail(true, DetectorRail::Shape::AscendingSouth).ID: return 1321; case DetectorRail::DetectorRail(false, DetectorRail::Shape::NorthSouth).ID: return 1322; case DetectorRail::DetectorRail(false, DetectorRail::Shape::EastWest).ID: return 1323; case DetectorRail::DetectorRail(false, DetectorRail::Shape::AscendingEast).ID: return 1324; case DetectorRail::DetectorRail(false, DetectorRail::Shape::AscendingWest).ID: return 1325; case DetectorRail::DetectorRail(false, DetectorRail::Shape::AscendingNorth).ID: return 1326; case DetectorRail::DetectorRail(false, DetectorRail::Shape::AscendingSouth).ID: return 1327; case DiamondBlock::DiamondBlock().ID: return 3353; case DiamondOre::DiamondOre().ID: return 3352; case Diorite::Diorite().ID: return 4; case DioriteSlab::DioriteSlab(DioriteSlab::Type::Top).ID: return 10326; case DioriteSlab::DioriteSlab(DioriteSlab::Type::Bottom).ID: return 10328; case DioriteSlab::DioriteSlab(DioriteSlab::Type::Double).ID: return 10330; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_ZM, DioriteStairs::Half::Top, DioriteStairs::Shape::Straight).ID: return 10174; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_ZM, DioriteStairs::Half::Top, DioriteStairs::Shape::InnerLeft).ID: return 10176; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_ZM, DioriteStairs::Half::Top, DioriteStairs::Shape::InnerRight).ID: return 10178; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_ZM, DioriteStairs::Half::Top, DioriteStairs::Shape::OuterLeft).ID: return 10180; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_ZM, DioriteStairs::Half::Top, DioriteStairs::Shape::OuterRight).ID: return 10182; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_ZM, DioriteStairs::Half::Bottom, DioriteStairs::Shape::Straight).ID: return 10184; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_ZM, DioriteStairs::Half::Bottom, DioriteStairs::Shape::InnerLeft).ID: return 10186; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_ZM, DioriteStairs::Half::Bottom, DioriteStairs::Shape::InnerRight).ID: return 10188; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_ZM, DioriteStairs::Half::Bottom, DioriteStairs::Shape::OuterLeft).ID: return 10190; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_ZM, DioriteStairs::Half::Bottom, DioriteStairs::Shape::OuterRight).ID: return 10192; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_ZP, DioriteStairs::Half::Top, DioriteStairs::Shape::Straight).ID: return 10194; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_ZP, DioriteStairs::Half::Top, DioriteStairs::Shape::InnerLeft).ID: return 10196; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_ZP, DioriteStairs::Half::Top, DioriteStairs::Shape::InnerRight).ID: return 10198; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_ZP, DioriteStairs::Half::Top, DioriteStairs::Shape::OuterLeft).ID: return 10200; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_ZP, DioriteStairs::Half::Top, DioriteStairs::Shape::OuterRight).ID: return 10202; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_ZP, DioriteStairs::Half::Bottom, DioriteStairs::Shape::Straight).ID: return 10204; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_ZP, DioriteStairs::Half::Bottom, DioriteStairs::Shape::InnerLeft).ID: return 10206; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_ZP, DioriteStairs::Half::Bottom, DioriteStairs::Shape::InnerRight).ID: return 10208; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_ZP, DioriteStairs::Half::Bottom, DioriteStairs::Shape::OuterLeft).ID: return 10210; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_ZP, DioriteStairs::Half::Bottom, DioriteStairs::Shape::OuterRight).ID: return 10212; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_XM, DioriteStairs::Half::Top, DioriteStairs::Shape::Straight).ID: return 10214; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_XM, DioriteStairs::Half::Top, DioriteStairs::Shape::InnerLeft).ID: return 10216; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_XM, DioriteStairs::Half::Top, DioriteStairs::Shape::InnerRight).ID: return 10218; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_XM, DioriteStairs::Half::Top, DioriteStairs::Shape::OuterLeft).ID: return 10220; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_XM, DioriteStairs::Half::Top, DioriteStairs::Shape::OuterRight).ID: return 10222; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_XM, DioriteStairs::Half::Bottom, DioriteStairs::Shape::Straight).ID: return 10224; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_XM, DioriteStairs::Half::Bottom, DioriteStairs::Shape::InnerLeft).ID: return 10226; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_XM, DioriteStairs::Half::Bottom, DioriteStairs::Shape::InnerRight).ID: return 10228; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_XM, DioriteStairs::Half::Bottom, DioriteStairs::Shape::OuterLeft).ID: return 10230; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_XM, DioriteStairs::Half::Bottom, DioriteStairs::Shape::OuterRight).ID: return 10232; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_XP, DioriteStairs::Half::Top, DioriteStairs::Shape::Straight).ID: return 10234; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_XP, DioriteStairs::Half::Top, DioriteStairs::Shape::InnerLeft).ID: return 10236; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_XP, DioriteStairs::Half::Top, DioriteStairs::Shape::InnerRight).ID: return 10238; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_XP, DioriteStairs::Half::Top, DioriteStairs::Shape::OuterLeft).ID: return 10240; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_XP, DioriteStairs::Half::Top, DioriteStairs::Shape::OuterRight).ID: return 10242; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_XP, DioriteStairs::Half::Bottom, DioriteStairs::Shape::Straight).ID: return 10244; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_XP, DioriteStairs::Half::Bottom, DioriteStairs::Shape::InnerLeft).ID: return 10246; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_XP, DioriteStairs::Half::Bottom, DioriteStairs::Shape::InnerRight).ID: return 10248; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_XP, DioriteStairs::Half::Bottom, DioriteStairs::Shape::OuterLeft).ID: return 10250; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_XP, DioriteStairs::Half::Bottom, DioriteStairs::Shape::OuterRight).ID: return 10252; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::Low, DioriteWall::South::Low, true, DioriteWall::West::Low).ID: return 11037; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::Low, DioriteWall::South::Low, true, DioriteWall::West::None).ID: return 11038; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::Low, DioriteWall::South::Low, false, DioriteWall::West::Low).ID: return 11041; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::Low, DioriteWall::South::Low, false, DioriteWall::West::None).ID: return 11042; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::Low, DioriteWall::South::None, true, DioriteWall::West::Low).ID: return 11045; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::Low, DioriteWall::South::None, true, DioriteWall::West::None).ID: return 11046; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::Low, DioriteWall::South::None, false, DioriteWall::West::Low).ID: return 11049; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::Low, DioriteWall::South::None, false, DioriteWall::West::None).ID: return 11050; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::None, DioriteWall::South::Low, true, DioriteWall::West::Low).ID: return 11053; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::None, DioriteWall::South::Low, true, DioriteWall::West::None).ID: return 11054; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::None, DioriteWall::South::Low, false, DioriteWall::West::Low).ID: return 11057; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::None, DioriteWall::South::Low, false, DioriteWall::West::None).ID: return 11058; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::None, DioriteWall::South::None, true, DioriteWall::West::Low).ID: return 11061; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::None, DioriteWall::South::None, true, DioriteWall::West::None).ID: return 11062; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::None, DioriteWall::South::None, false, DioriteWall::West::Low).ID: return 11065; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::None, DioriteWall::South::None, false, DioriteWall::West::None).ID: return 11066; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::Low, DioriteWall::South::Low, true, DioriteWall::West::Low).ID: return 11069; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::Low, DioriteWall::South::Low, true, DioriteWall::West::None).ID: return 11070; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::Low, DioriteWall::South::Low, false, DioriteWall::West::Low).ID: return 11073; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::Low, DioriteWall::South::Low, false, DioriteWall::West::None).ID: return 11074; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::Low, DioriteWall::South::None, true, DioriteWall::West::Low).ID: return 11077; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::Low, DioriteWall::South::None, true, DioriteWall::West::None).ID: return 11078; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::Low, DioriteWall::South::None, false, DioriteWall::West::Low).ID: return 11081; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::Low, DioriteWall::South::None, false, DioriteWall::West::None).ID: return 11082; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::None, DioriteWall::South::Low, true, DioriteWall::West::Low).ID: return 11085; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::None, DioriteWall::South::Low, true, DioriteWall::West::None).ID: return 11086; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::None, DioriteWall::South::Low, false, DioriteWall::West::Low).ID: return 11089; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::None, DioriteWall::South::Low, false, DioriteWall::West::None).ID: return 11090; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::None, DioriteWall::South::None, true, DioriteWall::West::Low).ID: return 11093; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::None, DioriteWall::South::None, true, DioriteWall::West::None).ID: return 11094; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::None, DioriteWall::South::None, false, DioriteWall::West::Low).ID: return 11097; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::None, DioriteWall::South::None, false, DioriteWall::West::None).ID: return 11098; case Dirt::Dirt().ID: return 10; case Dispenser::Dispenser(eBlockFace::BLOCK_FACE_ZM, true).ID: return 233; case Dispenser::Dispenser(eBlockFace::BLOCK_FACE_ZM, false).ID: return 234; case Dispenser::Dispenser(eBlockFace::BLOCK_FACE_XP, true).ID: return 235; case Dispenser::Dispenser(eBlockFace::BLOCK_FACE_XP, false).ID: return 236; case Dispenser::Dispenser(eBlockFace::BLOCK_FACE_ZP, true).ID: return 237; case Dispenser::Dispenser(eBlockFace::BLOCK_FACE_ZP, false).ID: return 238; case Dispenser::Dispenser(eBlockFace::BLOCK_FACE_XM, true).ID: return 239; case Dispenser::Dispenser(eBlockFace::BLOCK_FACE_XM, false).ID: return 240; case Dispenser::Dispenser(eBlockFace::BLOCK_FACE_YP, true).ID: return 241; case Dispenser::Dispenser(eBlockFace::BLOCK_FACE_YP, false).ID: return 242; case Dispenser::Dispenser(eBlockFace::BLOCK_FACE_YM, true).ID: return 243; case Dispenser::Dispenser(eBlockFace::BLOCK_FACE_YM, false).ID: return 244; case DragonEgg::DragonEgg().ID: return 5139; case DragonHead::DragonHead(0).ID: return 6054; case DragonHead::DragonHead(1).ID: return 6055; case DragonHead::DragonHead(2).ID: return 6056; case DragonHead::DragonHead(3).ID: return 6057; case DragonHead::DragonHead(4).ID: return 6058; case DragonHead::DragonHead(5).ID: return 6059; case DragonHead::DragonHead(6).ID: return 6060; case DragonHead::DragonHead(7).ID: return 6061; case DragonHead::DragonHead(8).ID: return 6062; case DragonHead::DragonHead(9).ID: return 6063; case DragonHead::DragonHead(10).ID: return 6064; case DragonHead::DragonHead(11).ID: return 6065; case DragonHead::DragonHead(12).ID: return 6066; case DragonHead::DragonHead(13).ID: return 6067; case DragonHead::DragonHead(14).ID: return 6068; case DragonHead::DragonHead(15).ID: return 6069; case DragonWallHead::DragonWallHead(eBlockFace::BLOCK_FACE_ZM).ID: return 6070; case DragonWallHead::DragonWallHead(eBlockFace::BLOCK_FACE_ZP).ID: return 6071; case DragonWallHead::DragonWallHead(eBlockFace::BLOCK_FACE_XM).ID: return 6072; case DragonWallHead::DragonWallHead(eBlockFace::BLOCK_FACE_XP).ID: return 6073; case DriedKelpBlock::DriedKelpBlock().ID: return 8961; case Dropper::Dropper(eBlockFace::BLOCK_FACE_ZM, true).ID: return 6299; case Dropper::Dropper(eBlockFace::BLOCK_FACE_ZM, false).ID: return 6300; case Dropper::Dropper(eBlockFace::BLOCK_FACE_XP, true).ID: return 6301; case Dropper::Dropper(eBlockFace::BLOCK_FACE_XP, false).ID: return 6302; case Dropper::Dropper(eBlockFace::BLOCK_FACE_ZP, true).ID: return 6303; case Dropper::Dropper(eBlockFace::BLOCK_FACE_ZP, false).ID: return 6304; case Dropper::Dropper(eBlockFace::BLOCK_FACE_XM, true).ID: return 6305; case Dropper::Dropper(eBlockFace::BLOCK_FACE_XM, false).ID: return 6306; case Dropper::Dropper(eBlockFace::BLOCK_FACE_YP, true).ID: return 6307; case Dropper::Dropper(eBlockFace::BLOCK_FACE_YP, false).ID: return 6308; case Dropper::Dropper(eBlockFace::BLOCK_FACE_YM, true).ID: return 6309; case Dropper::Dropper(eBlockFace::BLOCK_FACE_YM, false).ID: return 6310; case EmeraldBlock::EmeraldBlock().ID: return 5387; case EmeraldOre::EmeraldOre().ID: return 5234; case EnchantingTable::EnchantingTable().ID: return 5116; case EndGateway::EndGateway().ID: return 8688; case EndPortal::EndPortal().ID: return 5129; case EndPortalFrame::EndPortalFrame(true, eBlockFace::BLOCK_FACE_ZM).ID: return 5130; case EndPortalFrame::EndPortalFrame(true, eBlockFace::BLOCK_FACE_ZP).ID: return 5131; case EndPortalFrame::EndPortalFrame(true, eBlockFace::BLOCK_FACE_XM).ID: return 5132; case EndPortalFrame::EndPortalFrame(true, eBlockFace::BLOCK_FACE_XP).ID: return 5133; case EndPortalFrame::EndPortalFrame(false, eBlockFace::BLOCK_FACE_ZM).ID: return 5134; case EndPortalFrame::EndPortalFrame(false, eBlockFace::BLOCK_FACE_ZP).ID: return 5135; case EndPortalFrame::EndPortalFrame(false, eBlockFace::BLOCK_FACE_XM).ID: return 5136; case EndPortalFrame::EndPortalFrame(false, eBlockFace::BLOCK_FACE_XP).ID: return 5137; case EndRod::EndRod(eBlockFace::BLOCK_FACE_ZM).ID: return 8522; case EndRod::EndRod(eBlockFace::BLOCK_FACE_XP).ID: return 8523; case EndRod::EndRod(eBlockFace::BLOCK_FACE_ZP).ID: return 8524; case EndRod::EndRod(eBlockFace::BLOCK_FACE_XM).ID: return 8525; case EndRod::EndRod(eBlockFace::BLOCK_FACE_YP).ID: return 8526; case EndRod::EndRod(eBlockFace::BLOCK_FACE_YM).ID: return 8527; case EndStone::EndStone().ID: return 5138; case EndStoneBrickSlab::EndStoneBrickSlab(EndStoneBrickSlab::Type::Top).ID: return 10284; case EndStoneBrickSlab::EndStoneBrickSlab(EndStoneBrickSlab::Type::Bottom).ID: return 10286; case EndStoneBrickSlab::EndStoneBrickSlab(EndStoneBrickSlab::Type::Double).ID: return 10288; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, EndStoneBrickStairs::Half::Top, EndStoneBrickStairs::Shape::Straight).ID: return 9534; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, EndStoneBrickStairs::Half::Top, EndStoneBrickStairs::Shape::InnerLeft).ID: return 9536; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, EndStoneBrickStairs::Half::Top, EndStoneBrickStairs::Shape::InnerRight).ID: return 9538; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, EndStoneBrickStairs::Half::Top, EndStoneBrickStairs::Shape::OuterLeft).ID: return 9540; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, EndStoneBrickStairs::Half::Top, EndStoneBrickStairs::Shape::OuterRight).ID: return 9542; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, EndStoneBrickStairs::Half::Bottom, EndStoneBrickStairs::Shape::Straight).ID: return 9544; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, EndStoneBrickStairs::Half::Bottom, EndStoneBrickStairs::Shape::InnerLeft).ID: return 9546; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, EndStoneBrickStairs::Half::Bottom, EndStoneBrickStairs::Shape::InnerRight).ID: return 9548; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, EndStoneBrickStairs::Half::Bottom, EndStoneBrickStairs::Shape::OuterLeft).ID: return 9550; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, EndStoneBrickStairs::Half::Bottom, EndStoneBrickStairs::Shape::OuterRight).ID: return 9552; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, EndStoneBrickStairs::Half::Top, EndStoneBrickStairs::Shape::Straight).ID: return 9554; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, EndStoneBrickStairs::Half::Top, EndStoneBrickStairs::Shape::InnerLeft).ID: return 9556; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, EndStoneBrickStairs::Half::Top, EndStoneBrickStairs::Shape::InnerRight).ID: return 9558; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, EndStoneBrickStairs::Half::Top, EndStoneBrickStairs::Shape::OuterLeft).ID: return 9560; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, EndStoneBrickStairs::Half::Top, EndStoneBrickStairs::Shape::OuterRight).ID: return 9562; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, EndStoneBrickStairs::Half::Bottom, EndStoneBrickStairs::Shape::Straight).ID: return 9564; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, EndStoneBrickStairs::Half::Bottom, EndStoneBrickStairs::Shape::InnerLeft).ID: return 9566; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, EndStoneBrickStairs::Half::Bottom, EndStoneBrickStairs::Shape::InnerRight).ID: return 9568; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, EndStoneBrickStairs::Half::Bottom, EndStoneBrickStairs::Shape::OuterLeft).ID: return 9570; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, EndStoneBrickStairs::Half::Bottom, EndStoneBrickStairs::Shape::OuterRight).ID: return 9572; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_XM, EndStoneBrickStairs::Half::Top, EndStoneBrickStairs::Shape::Straight).ID: return 9574; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_XM, EndStoneBrickStairs::Half::Top, EndStoneBrickStairs::Shape::InnerLeft).ID: return 9576; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_XM, EndStoneBrickStairs::Half::Top, EndStoneBrickStairs::Shape::InnerRight).ID: return 9578; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_XM, EndStoneBrickStairs::Half::Top, EndStoneBrickStairs::Shape::OuterLeft).ID: return 9580; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_XM, EndStoneBrickStairs::Half::Top, EndStoneBrickStairs::Shape::OuterRight).ID: return 9582; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_XM, EndStoneBrickStairs::Half::Bottom, EndStoneBrickStairs::Shape::Straight).ID: return 9584; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_XM, EndStoneBrickStairs::Half::Bottom, EndStoneBrickStairs::Shape::InnerLeft).ID: return 9586; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_XM, EndStoneBrickStairs::Half::Bottom, EndStoneBrickStairs::Shape::InnerRight).ID: return 9588; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_XM, EndStoneBrickStairs::Half::Bottom, EndStoneBrickStairs::Shape::OuterLeft).ID: return 9590; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_XM, EndStoneBrickStairs::Half::Bottom, EndStoneBrickStairs::Shape::OuterRight).ID: return 9592; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_XP, EndStoneBrickStairs::Half::Top, EndStoneBrickStairs::Shape::Straight).ID: return 9594; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_XP, EndStoneBrickStairs::Half::Top, EndStoneBrickStairs::Shape::InnerLeft).ID: return 9596; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_XP, EndStoneBrickStairs::Half::Top, EndStoneBrickStairs::Shape::InnerRight).ID: return 9598; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_XP, EndStoneBrickStairs::Half::Top, EndStoneBrickStairs::Shape::OuterLeft).ID: return 9600; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_XP, EndStoneBrickStairs::Half::Top, EndStoneBrickStairs::Shape::OuterRight).ID: return 9602; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_XP, EndStoneBrickStairs::Half::Bottom, EndStoneBrickStairs::Shape::Straight).ID: return 9604; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_XP, EndStoneBrickStairs::Half::Bottom, EndStoneBrickStairs::Shape::InnerLeft).ID: return 9606; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_XP, EndStoneBrickStairs::Half::Bottom, EndStoneBrickStairs::Shape::InnerRight).ID: return 9608; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_XP, EndStoneBrickStairs::Half::Bottom, EndStoneBrickStairs::Shape::OuterLeft).ID: return 9610; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_XP, EndStoneBrickStairs::Half::Bottom, EndStoneBrickStairs::Shape::OuterRight).ID: return 9612; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::Low, true, EndStoneBrickWall::West::Low).ID: return 10973; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::Low, true, EndStoneBrickWall::West::None).ID: return 10974; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::Low, false, EndStoneBrickWall::West::Low).ID: return 10977; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::Low, false, EndStoneBrickWall::West::None).ID: return 10978; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::None, true, EndStoneBrickWall::West::Low).ID: return 10981; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::None, true, EndStoneBrickWall::West::None).ID: return 10982; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::None, false, EndStoneBrickWall::West::Low).ID: return 10985; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::None, false, EndStoneBrickWall::West::None).ID: return 10986; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::None, EndStoneBrickWall::South::Low, true, EndStoneBrickWall::West::Low).ID: return 10989; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::None, EndStoneBrickWall::South::Low, true, EndStoneBrickWall::West::None).ID: return 10990; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::None, EndStoneBrickWall::South::Low, false, EndStoneBrickWall::West::Low).ID: return 10993; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::None, EndStoneBrickWall::South::Low, false, EndStoneBrickWall::West::None).ID: return 10994; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::None, EndStoneBrickWall::South::None, true, EndStoneBrickWall::West::Low).ID: return 10997; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::None, EndStoneBrickWall::South::None, true, EndStoneBrickWall::West::None).ID: return 10998; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::None, EndStoneBrickWall::South::None, false, EndStoneBrickWall::West::Low).ID: return 11001; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::None, EndStoneBrickWall::South::None, false, EndStoneBrickWall::West::None).ID: return 11002; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::Low, true, EndStoneBrickWall::West::Low).ID: return 11005; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::Low, true, EndStoneBrickWall::West::None).ID: return 11006; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::Low, false, EndStoneBrickWall::West::Low).ID: return 11009; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::Low, false, EndStoneBrickWall::West::None).ID: return 11010; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::None, true, EndStoneBrickWall::West::Low).ID: return 11013; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::None, true, EndStoneBrickWall::West::None).ID: return 11014; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::None, false, EndStoneBrickWall::West::Low).ID: return 11017; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::None, false, EndStoneBrickWall::West::None).ID: return 11018; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::None, EndStoneBrickWall::South::Low, true, EndStoneBrickWall::West::Low).ID: return 11021; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::None, EndStoneBrickWall::South::Low, true, EndStoneBrickWall::West::None).ID: return 11022; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::None, EndStoneBrickWall::South::Low, false, EndStoneBrickWall::West::Low).ID: return 11025; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::None, EndStoneBrickWall::South::Low, false, EndStoneBrickWall::West::None).ID: return 11026; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::None, EndStoneBrickWall::South::None, true, EndStoneBrickWall::West::Low).ID: return 11029; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::None, EndStoneBrickWall::South::None, true, EndStoneBrickWall::West::None).ID: return 11030; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::None, EndStoneBrickWall::South::None, false, EndStoneBrickWall::West::Low).ID: return 11033; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::None, EndStoneBrickWall::South::None, false, EndStoneBrickWall::West::None).ID: return 11034; case EndStoneBricks::EndStoneBricks().ID: return 8682; case EnderChest::EnderChest(eBlockFace::BLOCK_FACE_ZM).ID: return 5236; case EnderChest::EnderChest(eBlockFace::BLOCK_FACE_ZP).ID: return 5238; case EnderChest::EnderChest(eBlockFace::BLOCK_FACE_XM).ID: return 5240; case EnderChest::EnderChest(eBlockFace::BLOCK_FACE_XP).ID: return 5242; case Farmland::Farmland(0).ID: return 3363; case Farmland::Farmland(1).ID: return 3364; case Farmland::Farmland(2).ID: return 3365; case Farmland::Farmland(3).ID: return 3366; case Farmland::Farmland(4).ID: return 3367; case Farmland::Farmland(5).ID: return 3368; case Farmland::Farmland(6).ID: return 3369; case Farmland::Farmland(7).ID: return 3370; case Fern::Fern().ID: return 1342; case Fire::Fire(0, true, true, true, true, true).ID: return 1439; case Fire::Fire(0, true, true, true, true, false).ID: return 1440; case Fire::Fire(0, true, true, true, false, true).ID: return 1441; case Fire::Fire(0, true, true, true, false, false).ID: return 1442; case Fire::Fire(0, true, true, false, true, true).ID: return 1443; case Fire::Fire(0, true, true, false, true, false).ID: return 1444; case Fire::Fire(0, true, true, false, false, true).ID: return 1445; case Fire::Fire(0, true, true, false, false, false).ID: return 1446; case Fire::Fire(0, true, false, true, true, true).ID: return 1447; case Fire::Fire(0, true, false, true, true, false).ID: return 1448; case Fire::Fire(0, true, false, true, false, true).ID: return 1449; case Fire::Fire(0, true, false, true, false, false).ID: return 1450; case Fire::Fire(0, true, false, false, true, true).ID: return 1451; case Fire::Fire(0, true, false, false, true, false).ID: return 1452; case Fire::Fire(0, true, false, false, false, true).ID: return 1453; case Fire::Fire(0, true, false, false, false, false).ID: return 1454; case Fire::Fire(0, false, true, true, true, true).ID: return 1455; case Fire::Fire(0, false, true, true, true, false).ID: return 1456; case Fire::Fire(0, false, true, true, false, true).ID: return 1457; case Fire::Fire(0, false, true, true, false, false).ID: return 1458; case Fire::Fire(0, false, true, false, true, true).ID: return 1459; case Fire::Fire(0, false, true, false, true, false).ID: return 1460; case Fire::Fire(0, false, true, false, false, true).ID: return 1461; case Fire::Fire(0, false, true, false, false, false).ID: return 1462; case Fire::Fire(0, false, false, true, true, true).ID: return 1463; case Fire::Fire(0, false, false, true, true, false).ID: return 1464; case Fire::Fire(0, false, false, true, false, true).ID: return 1465; case Fire::Fire(0, false, false, true, false, false).ID: return 1466; case Fire::Fire(0, false, false, false, true, true).ID: return 1467; case Fire::Fire(0, false, false, false, true, false).ID: return 1468; case Fire::Fire(0, false, false, false, false, true).ID: return 1469; case Fire::Fire(0, false, false, false, false, false).ID: return 1470; case Fire::Fire(1, true, true, true, true, true).ID: return 1471; case Fire::Fire(1, true, true, true, true, false).ID: return 1472; case Fire::Fire(1, true, true, true, false, true).ID: return 1473; case Fire::Fire(1, true, true, true, false, false).ID: return 1474; case Fire::Fire(1, true, true, false, true, true).ID: return 1475; case Fire::Fire(1, true, true, false, true, false).ID: return 1476; case Fire::Fire(1, true, true, false, false, true).ID: return 1477; case Fire::Fire(1, true, true, false, false, false).ID: return 1478; case Fire::Fire(1, true, false, true, true, true).ID: return 1479; case Fire::Fire(1, true, false, true, true, false).ID: return 1480; case Fire::Fire(1, true, false, true, false, true).ID: return 1481; case Fire::Fire(1, true, false, true, false, false).ID: return 1482; case Fire::Fire(1, true, false, false, true, true).ID: return 1483; case Fire::Fire(1, true, false, false, true, false).ID: return 1484; case Fire::Fire(1, true, false, false, false, true).ID: return 1485; case Fire::Fire(1, true, false, false, false, false).ID: return 1486; case Fire::Fire(1, false, true, true, true, true).ID: return 1487; case Fire::Fire(1, false, true, true, true, false).ID: return 1488; case Fire::Fire(1, false, true, true, false, true).ID: return 1489; case Fire::Fire(1, false, true, true, false, false).ID: return 1490; case Fire::Fire(1, false, true, false, true, true).ID: return 1491; case Fire::Fire(1, false, true, false, true, false).ID: return 1492; case Fire::Fire(1, false, true, false, false, true).ID: return 1493; case Fire::Fire(1, false, true, false, false, false).ID: return 1494; case Fire::Fire(1, false, false, true, true, true).ID: return 1495; case Fire::Fire(1, false, false, true, true, false).ID: return 1496; case Fire::Fire(1, false, false, true, false, true).ID: return 1497; case Fire::Fire(1, false, false, true, false, false).ID: return 1498; case Fire::Fire(1, false, false, false, true, true).ID: return 1499; case Fire::Fire(1, false, false, false, true, false).ID: return 1500; case Fire::Fire(1, false, false, false, false, true).ID: return 1501; case Fire::Fire(1, false, false, false, false, false).ID: return 1502; case Fire::Fire(2, true, true, true, true, true).ID: return 1503; case Fire::Fire(2, true, true, true, true, false).ID: return 1504; case Fire::Fire(2, true, true, true, false, true).ID: return 1505; case Fire::Fire(2, true, true, true, false, false).ID: return 1506; case Fire::Fire(2, true, true, false, true, true).ID: return 1507; case Fire::Fire(2, true, true, false, true, false).ID: return 1508; case Fire::Fire(2, true, true, false, false, true).ID: return 1509; case Fire::Fire(2, true, true, false, false, false).ID: return 1510; case Fire::Fire(2, true, false, true, true, true).ID: return 1511; case Fire::Fire(2, true, false, true, true, false).ID: return 1512; case Fire::Fire(2, true, false, true, false, true).ID: return 1513; case Fire::Fire(2, true, false, true, false, false).ID: return 1514; case Fire::Fire(2, true, false, false, true, true).ID: return 1515; case Fire::Fire(2, true, false, false, true, false).ID: return 1516; case Fire::Fire(2, true, false, false, false, true).ID: return 1517; case Fire::Fire(2, true, false, false, false, false).ID: return 1518; case Fire::Fire(2, false, true, true, true, true).ID: return 1519; case Fire::Fire(2, false, true, true, true, false).ID: return 1520; case Fire::Fire(2, false, true, true, false, true).ID: return 1521; case Fire::Fire(2, false, true, true, false, false).ID: return 1522; case Fire::Fire(2, false, true, false, true, true).ID: return 1523; case Fire::Fire(2, false, true, false, true, false).ID: return 1524; case Fire::Fire(2, false, true, false, false, true).ID: return 1525; case Fire::Fire(2, false, true, false, false, false).ID: return 1526; case Fire::Fire(2, false, false, true, true, true).ID: return 1527; case Fire::Fire(2, false, false, true, true, false).ID: return 1528; case Fire::Fire(2, false, false, true, false, true).ID: return 1529; case Fire::Fire(2, false, false, true, false, false).ID: return 1530; case Fire::Fire(2, false, false, false, true, true).ID: return 1531; case Fire::Fire(2, false, false, false, true, false).ID: return 1532; case Fire::Fire(2, false, false, false, false, true).ID: return 1533; case Fire::Fire(2, false, false, false, false, false).ID: return 1534; case Fire::Fire(3, true, true, true, true, true).ID: return 1535; case Fire::Fire(3, true, true, true, true, false).ID: return 1536; case Fire::Fire(3, true, true, true, false, true).ID: return 1537; case Fire::Fire(3, true, true, true, false, false).ID: return 1538; case Fire::Fire(3, true, true, false, true, true).ID: return 1539; case Fire::Fire(3, true, true, false, true, false).ID: return 1540; case Fire::Fire(3, true, true, false, false, true).ID: return 1541; case Fire::Fire(3, true, true, false, false, false).ID: return 1542; case Fire::Fire(3, true, false, true, true, true).ID: return 1543; case Fire::Fire(3, true, false, true, true, false).ID: return 1544; case Fire::Fire(3, true, false, true, false, true).ID: return 1545; case Fire::Fire(3, true, false, true, false, false).ID: return 1546; case Fire::Fire(3, true, false, false, true, true).ID: return 1547; case Fire::Fire(3, true, false, false, true, false).ID: return 1548; case Fire::Fire(3, true, false, false, false, true).ID: return 1549; case Fire::Fire(3, true, false, false, false, false).ID: return 1550; case Fire::Fire(3, false, true, true, true, true).ID: return 1551; case Fire::Fire(3, false, true, true, true, false).ID: return 1552; case Fire::Fire(3, false, true, true, false, true).ID: return 1553; case Fire::Fire(3, false, true, true, false, false).ID: return 1554; case Fire::Fire(3, false, true, false, true, true).ID: return 1555; case Fire::Fire(3, false, true, false, true, false).ID: return 1556; case Fire::Fire(3, false, true, false, false, true).ID: return 1557; case Fire::Fire(3, false, true, false, false, false).ID: return 1558; case Fire::Fire(3, false, false, true, true, true).ID: return 1559; case Fire::Fire(3, false, false, true, true, false).ID: return 1560; case Fire::Fire(3, false, false, true, false, true).ID: return 1561; case Fire::Fire(3, false, false, true, false, false).ID: return 1562; case Fire::Fire(3, false, false, false, true, true).ID: return 1563; case Fire::Fire(3, false, false, false, true, false).ID: return 1564; case Fire::Fire(3, false, false, false, false, true).ID: return 1565; case Fire::Fire(3, false, false, false, false, false).ID: return 1566; case Fire::Fire(4, true, true, true, true, true).ID: return 1567; case Fire::Fire(4, true, true, true, true, false).ID: return 1568; case Fire::Fire(4, true, true, true, false, true).ID: return 1569; case Fire::Fire(4, true, true, true, false, false).ID: return 1570; case Fire::Fire(4, true, true, false, true, true).ID: return 1571; case Fire::Fire(4, true, true, false, true, false).ID: return 1572; case Fire::Fire(4, true, true, false, false, true).ID: return 1573; case Fire::Fire(4, true, true, false, false, false).ID: return 1574; case Fire::Fire(4, true, false, true, true, true).ID: return 1575; case Fire::Fire(4, true, false, true, true, false).ID: return 1576; case Fire::Fire(4, true, false, true, false, true).ID: return 1577; case Fire::Fire(4, true, false, true, false, false).ID: return 1578; case Fire::Fire(4, true, false, false, true, true).ID: return 1579; case Fire::Fire(4, true, false, false, true, false).ID: return 1580; case Fire::Fire(4, true, false, false, false, true).ID: return 1581; case Fire::Fire(4, true, false, false, false, false).ID: return 1582; case Fire::Fire(4, false, true, true, true, true).ID: return 1583; case Fire::Fire(4, false, true, true, true, false).ID: return 1584; case Fire::Fire(4, false, true, true, false, true).ID: return 1585; case Fire::Fire(4, false, true, true, false, false).ID: return 1586; case Fire::Fire(4, false, true, false, true, true).ID: return 1587; case Fire::Fire(4, false, true, false, true, false).ID: return 1588; case Fire::Fire(4, false, true, false, false, true).ID: return 1589; case Fire::Fire(4, false, true, false, false, false).ID: return 1590; case Fire::Fire(4, false, false, true, true, true).ID: return 1591; case Fire::Fire(4, false, false, true, true, false).ID: return 1592; case Fire::Fire(4, false, false, true, false, true).ID: return 1593; case Fire::Fire(4, false, false, true, false, false).ID: return 1594; case Fire::Fire(4, false, false, false, true, true).ID: return 1595; case Fire::Fire(4, false, false, false, true, false).ID: return 1596; case Fire::Fire(4, false, false, false, false, true).ID: return 1597; case Fire::Fire(4, false, false, false, false, false).ID: return 1598; case Fire::Fire(5, true, true, true, true, true).ID: return 1599; case Fire::Fire(5, true, true, true, true, false).ID: return 1600; case Fire::Fire(5, true, true, true, false, true).ID: return 1601; case Fire::Fire(5, true, true, true, false, false).ID: return 1602; case Fire::Fire(5, true, true, false, true, true).ID: return 1603; case Fire::Fire(5, true, true, false, true, false).ID: return 1604; case Fire::Fire(5, true, true, false, false, true).ID: return 1605; case Fire::Fire(5, true, true, false, false, false).ID: return 1606; case Fire::Fire(5, true, false, true, true, true).ID: return 1607; case Fire::Fire(5, true, false, true, true, false).ID: return 1608; case Fire::Fire(5, true, false, true, false, true).ID: return 1609; case Fire::Fire(5, true, false, true, false, false).ID: return 1610; case Fire::Fire(5, true, false, false, true, true).ID: return 1611; case Fire::Fire(5, true, false, false, true, false).ID: return 1612; case Fire::Fire(5, true, false, false, false, true).ID: return 1613; case Fire::Fire(5, true, false, false, false, false).ID: return 1614; case Fire::Fire(5, false, true, true, true, true).ID: return 1615; case Fire::Fire(5, false, true, true, true, false).ID: return 1616; case Fire::Fire(5, false, true, true, false, true).ID: return 1617; case Fire::Fire(5, false, true, true, false, false).ID: return 1618; case Fire::Fire(5, false, true, false, true, true).ID: return 1619; case Fire::Fire(5, false, true, false, true, false).ID: return 1620; case Fire::Fire(5, false, true, false, false, true).ID: return 1621; case Fire::Fire(5, false, true, false, false, false).ID: return 1622; case Fire::Fire(5, false, false, true, true, true).ID: return 1623; case Fire::Fire(5, false, false, true, true, false).ID: return 1624; case Fire::Fire(5, false, false, true, false, true).ID: return 1625; case Fire::Fire(5, false, false, true, false, false).ID: return 1626; case Fire::Fire(5, false, false, false, true, true).ID: return 1627; case Fire::Fire(5, false, false, false, true, false).ID: return 1628; case Fire::Fire(5, false, false, false, false, true).ID: return 1629; case Fire::Fire(5, false, false, false, false, false).ID: return 1630; case Fire::Fire(6, true, true, true, true, true).ID: return 1631; case Fire::Fire(6, true, true, true, true, false).ID: return 1632; case Fire::Fire(6, true, true, true, false, true).ID: return 1633; case Fire::Fire(6, true, true, true, false, false).ID: return 1634; case Fire::Fire(6, true, true, false, true, true).ID: return 1635; case Fire::Fire(6, true, true, false, true, false).ID: return 1636; case Fire::Fire(6, true, true, false, false, true).ID: return 1637; case Fire::Fire(6, true, true, false, false, false).ID: return 1638; case Fire::Fire(6, true, false, true, true, true).ID: return 1639; case Fire::Fire(6, true, false, true, true, false).ID: return 1640; case Fire::Fire(6, true, false, true, false, true).ID: return 1641; case Fire::Fire(6, true, false, true, false, false).ID: return 1642; case Fire::Fire(6, true, false, false, true, true).ID: return 1643; case Fire::Fire(6, true, false, false, true, false).ID: return 1644; case Fire::Fire(6, true, false, false, false, true).ID: return 1645; case Fire::Fire(6, true, false, false, false, false).ID: return 1646; case Fire::Fire(6, false, true, true, true, true).ID: return 1647; case Fire::Fire(6, false, true, true, true, false).ID: return 1648; case Fire::Fire(6, false, true, true, false, true).ID: return 1649; case Fire::Fire(6, false, true, true, false, false).ID: return 1650; case Fire::Fire(6, false, true, false, true, true).ID: return 1651; case Fire::Fire(6, false, true, false, true, false).ID: return 1652; case Fire::Fire(6, false, true, false, false, true).ID: return 1653; case Fire::Fire(6, false, true, false, false, false).ID: return 1654; case Fire::Fire(6, false, false, true, true, true).ID: return 1655; case Fire::Fire(6, false, false, true, true, false).ID: return 1656; case Fire::Fire(6, false, false, true, false, true).ID: return 1657; case Fire::Fire(6, false, false, true, false, false).ID: return 1658; case Fire::Fire(6, false, false, false, true, true).ID: return 1659; case Fire::Fire(6, false, false, false, true, false).ID: return 1660; case Fire::Fire(6, false, false, false, false, true).ID: return 1661; case Fire::Fire(6, false, false, false, false, false).ID: return 1662; case Fire::Fire(7, true, true, true, true, true).ID: return 1663; case Fire::Fire(7, true, true, true, true, false).ID: return 1664; case Fire::Fire(7, true, true, true, false, true).ID: return 1665; case Fire::Fire(7, true, true, true, false, false).ID: return 1666; case Fire::Fire(7, true, true, false, true, true).ID: return 1667; case Fire::Fire(7, true, true, false, true, false).ID: return 1668; case Fire::Fire(7, true, true, false, false, true).ID: return 1669; case Fire::Fire(7, true, true, false, false, false).ID: return 1670; case Fire::Fire(7, true, false, true, true, true).ID: return 1671; case Fire::Fire(7, true, false, true, true, false).ID: return 1672; case Fire::Fire(7, true, false, true, false, true).ID: return 1673; case Fire::Fire(7, true, false, true, false, false).ID: return 1674; case Fire::Fire(7, true, false, false, true, true).ID: return 1675; case Fire::Fire(7, true, false, false, true, false).ID: return 1676; case Fire::Fire(7, true, false, false, false, true).ID: return 1677; case Fire::Fire(7, true, false, false, false, false).ID: return 1678; case Fire::Fire(7, false, true, true, true, true).ID: return 1679; case Fire::Fire(7, false, true, true, true, false).ID: return 1680; case Fire::Fire(7, false, true, true, false, true).ID: return 1681; case Fire::Fire(7, false, true, true, false, false).ID: return 1682; case Fire::Fire(7, false, true, false, true, true).ID: return 1683; case Fire::Fire(7, false, true, false, true, false).ID: return 1684; case Fire::Fire(7, false, true, false, false, true).ID: return 1685; case Fire::Fire(7, false, true, false, false, false).ID: return 1686; case Fire::Fire(7, false, false, true, true, true).ID: return 1687; case Fire::Fire(7, false, false, true, true, false).ID: return 1688; case Fire::Fire(7, false, false, true, false, true).ID: return 1689; case Fire::Fire(7, false, false, true, false, false).ID: return 1690; case Fire::Fire(7, false, false, false, true, true).ID: return 1691; case Fire::Fire(7, false, false, false, true, false).ID: return 1692; case Fire::Fire(7, false, false, false, false, true).ID: return 1693; case Fire::Fire(7, false, false, false, false, false).ID: return 1694; case Fire::Fire(8, true, true, true, true, true).ID: return 1695; case Fire::Fire(8, true, true, true, true, false).ID: return 1696; case Fire::Fire(8, true, true, true, false, true).ID: return 1697; case Fire::Fire(8, true, true, true, false, false).ID: return 1698; case Fire::Fire(8, true, true, false, true, true).ID: return 1699; case Fire::Fire(8, true, true, false, true, false).ID: return 1700; case Fire::Fire(8, true, true, false, false, true).ID: return 1701; case Fire::Fire(8, true, true, false, false, false).ID: return 1702; case Fire::Fire(8, true, false, true, true, true).ID: return 1703; case Fire::Fire(8, true, false, true, true, false).ID: return 1704; case Fire::Fire(8, true, false, true, false, true).ID: return 1705; case Fire::Fire(8, true, false, true, false, false).ID: return 1706; case Fire::Fire(8, true, false, false, true, true).ID: return 1707; case Fire::Fire(8, true, false, false, true, false).ID: return 1708; case Fire::Fire(8, true, false, false, false, true).ID: return 1709; case Fire::Fire(8, true, false, false, false, false).ID: return 1710; case Fire::Fire(8, false, true, true, true, true).ID: return 1711; case Fire::Fire(8, false, true, true, true, false).ID: return 1712; case Fire::Fire(8, false, true, true, false, true).ID: return 1713; case Fire::Fire(8, false, true, true, false, false).ID: return 1714; case Fire::Fire(8, false, true, false, true, true).ID: return 1715; case Fire::Fire(8, false, true, false, true, false).ID: return 1716; case Fire::Fire(8, false, true, false, false, true).ID: return 1717; case Fire::Fire(8, false, true, false, false, false).ID: return 1718; case Fire::Fire(8, false, false, true, true, true).ID: return 1719; case Fire::Fire(8, false, false, true, true, false).ID: return 1720; case Fire::Fire(8, false, false, true, false, true).ID: return 1721; case Fire::Fire(8, false, false, true, false, false).ID: return 1722; case Fire::Fire(8, false, false, false, true, true).ID: return 1723; case Fire::Fire(8, false, false, false, true, false).ID: return 1724; case Fire::Fire(8, false, false, false, false, true).ID: return 1725; case Fire::Fire(8, false, false, false, false, false).ID: return 1726; case Fire::Fire(9, true, true, true, true, true).ID: return 1727; case Fire::Fire(9, true, true, true, true, false).ID: return 1728; case Fire::Fire(9, true, true, true, false, true).ID: return 1729; case Fire::Fire(9, true, true, true, false, false).ID: return 1730; case Fire::Fire(9, true, true, false, true, true).ID: return 1731; case Fire::Fire(9, true, true, false, true, false).ID: return 1732; case Fire::Fire(9, true, true, false, false, true).ID: return 1733; case Fire::Fire(9, true, true, false, false, false).ID: return 1734; case Fire::Fire(9, true, false, true, true, true).ID: return 1735; case Fire::Fire(9, true, false, true, true, false).ID: return 1736; case Fire::Fire(9, true, false, true, false, true).ID: return 1737; case Fire::Fire(9, true, false, true, false, false).ID: return 1738; case Fire::Fire(9, true, false, false, true, true).ID: return 1739; case Fire::Fire(9, true, false, false, true, false).ID: return 1740; case Fire::Fire(9, true, false, false, false, true).ID: return 1741; case Fire::Fire(9, true, false, false, false, false).ID: return 1742; case Fire::Fire(9, false, true, true, true, true).ID: return 1743; case Fire::Fire(9, false, true, true, true, false).ID: return 1744; case Fire::Fire(9, false, true, true, false, true).ID: return 1745; case Fire::Fire(9, false, true, true, false, false).ID: return 1746; case Fire::Fire(9, false, true, false, true, true).ID: return 1747; case Fire::Fire(9, false, true, false, true, false).ID: return 1748; case Fire::Fire(9, false, true, false, false, true).ID: return 1749; case Fire::Fire(9, false, true, false, false, false).ID: return 1750; case Fire::Fire(9, false, false, true, true, true).ID: return 1751; case Fire::Fire(9, false, false, true, true, false).ID: return 1752; case Fire::Fire(9, false, false, true, false, true).ID: return 1753; case Fire::Fire(9, false, false, true, false, false).ID: return 1754; case Fire::Fire(9, false, false, false, true, true).ID: return 1755; case Fire::Fire(9, false, false, false, true, false).ID: return 1756; case Fire::Fire(9, false, false, false, false, true).ID: return 1757; case Fire::Fire(9, false, false, false, false, false).ID: return 1758; case Fire::Fire(10, true, true, true, true, true).ID: return 1759; case Fire::Fire(10, true, true, true, true, false).ID: return 1760; case Fire::Fire(10, true, true, true, false, true).ID: return 1761; case Fire::Fire(10, true, true, true, false, false).ID: return 1762; case Fire::Fire(10, true, true, false, true, true).ID: return 1763; case Fire::Fire(10, true, true, false, true, false).ID: return 1764; case Fire::Fire(10, true, true, false, false, true).ID: return 1765; case Fire::Fire(10, true, true, false, false, false).ID: return 1766; case Fire::Fire(10, true, false, true, true, true).ID: return 1767; case Fire::Fire(10, true, false, true, true, false).ID: return 1768; case Fire::Fire(10, true, false, true, false, true).ID: return 1769; case Fire::Fire(10, true, false, true, false, false).ID: return 1770; case Fire::Fire(10, true, false, false, true, true).ID: return 1771; case Fire::Fire(10, true, false, false, true, false).ID: return 1772; case Fire::Fire(10, true, false, false, false, true).ID: return 1773; case Fire::Fire(10, true, false, false, false, false).ID: return 1774; case Fire::Fire(10, false, true, true, true, true).ID: return 1775; case Fire::Fire(10, false, true, true, true, false).ID: return 1776; case Fire::Fire(10, false, true, true, false, true).ID: return 1777; case Fire::Fire(10, false, true, true, false, false).ID: return 1778; case Fire::Fire(10, false, true, false, true, true).ID: return 1779; case Fire::Fire(10, false, true, false, true, false).ID: return 1780; case Fire::Fire(10, false, true, false, false, true).ID: return 1781; case Fire::Fire(10, false, true, false, false, false).ID: return 1782; case Fire::Fire(10, false, false, true, true, true).ID: return 1783; case Fire::Fire(10, false, false, true, true, false).ID: return 1784; case Fire::Fire(10, false, false, true, false, true).ID: return 1785; case Fire::Fire(10, false, false, true, false, false).ID: return 1786; case Fire::Fire(10, false, false, false, true, true).ID: return 1787; case Fire::Fire(10, false, false, false, true, false).ID: return 1788; case Fire::Fire(10, false, false, false, false, true).ID: return 1789; case Fire::Fire(10, false, false, false, false, false).ID: return 1790; case Fire::Fire(11, true, true, true, true, true).ID: return 1791; case Fire::Fire(11, true, true, true, true, false).ID: return 1792; case Fire::Fire(11, true, true, true, false, true).ID: return 1793; case Fire::Fire(11, true, true, true, false, false).ID: return 1794; case Fire::Fire(11, true, true, false, true, true).ID: return 1795; case Fire::Fire(11, true, true, false, true, false).ID: return 1796; case Fire::Fire(11, true, true, false, false, true).ID: return 1797; case Fire::Fire(11, true, true, false, false, false).ID: return 1798; case Fire::Fire(11, true, false, true, true, true).ID: return 1799; case Fire::Fire(11, true, false, true, true, false).ID: return 1800; case Fire::Fire(11, true, false, true, false, true).ID: return 1801; case Fire::Fire(11, true, false, true, false, false).ID: return 1802; case Fire::Fire(11, true, false, false, true, true).ID: return 1803; case Fire::Fire(11, true, false, false, true, false).ID: return 1804; case Fire::Fire(11, true, false, false, false, true).ID: return 1805; case Fire::Fire(11, true, false, false, false, false).ID: return 1806; case Fire::Fire(11, false, true, true, true, true).ID: return 1807; case Fire::Fire(11, false, true, true, true, false).ID: return 1808; case Fire::Fire(11, false, true, true, false, true).ID: return 1809; case Fire::Fire(11, false, true, true, false, false).ID: return 1810; case Fire::Fire(11, false, true, false, true, true).ID: return 1811; case Fire::Fire(11, false, true, false, true, false).ID: return 1812; case Fire::Fire(11, false, true, false, false, true).ID: return 1813; case Fire::Fire(11, false, true, false, false, false).ID: return 1814; case Fire::Fire(11, false, false, true, true, true).ID: return 1815; case Fire::Fire(11, false, false, true, true, false).ID: return 1816; case Fire::Fire(11, false, false, true, false, true).ID: return 1817; case Fire::Fire(11, false, false, true, false, false).ID: return 1818; case Fire::Fire(11, false, false, false, true, true).ID: return 1819; case Fire::Fire(11, false, false, false, true, false).ID: return 1820; case Fire::Fire(11, false, false, false, false, true).ID: return 1821; case Fire::Fire(11, false, false, false, false, false).ID: return 1822; case Fire::Fire(12, true, true, true, true, true).ID: return 1823; case Fire::Fire(12, true, true, true, true, false).ID: return 1824; case Fire::Fire(12, true, true, true, false, true).ID: return 1825; case Fire::Fire(12, true, true, true, false, false).ID: return 1826; case Fire::Fire(12, true, true, false, true, true).ID: return 1827; case Fire::Fire(12, true, true, false, true, false).ID: return 1828; case Fire::Fire(12, true, true, false, false, true).ID: return 1829; case Fire::Fire(12, true, true, false, false, false).ID: return 1830; case Fire::Fire(12, true, false, true, true, true).ID: return 1831; case Fire::Fire(12, true, false, true, true, false).ID: return 1832; case Fire::Fire(12, true, false, true, false, true).ID: return 1833; case Fire::Fire(12, true, false, true, false, false).ID: return 1834; case Fire::Fire(12, true, false, false, true, true).ID: return 1835; case Fire::Fire(12, true, false, false, true, false).ID: return 1836; case Fire::Fire(12, true, false, false, false, true).ID: return 1837; case Fire::Fire(12, true, false, false, false, false).ID: return 1838; case Fire::Fire(12, false, true, true, true, true).ID: return 1839; case Fire::Fire(12, false, true, true, true, false).ID: return 1840; case Fire::Fire(12, false, true, true, false, true).ID: return 1841; case Fire::Fire(12, false, true, true, false, false).ID: return 1842; case Fire::Fire(12, false, true, false, true, true).ID: return 1843; case Fire::Fire(12, false, true, false, true, false).ID: return 1844; case Fire::Fire(12, false, true, false, false, true).ID: return 1845; case Fire::Fire(12, false, true, false, false, false).ID: return 1846; case Fire::Fire(12, false, false, true, true, true).ID: return 1847; case Fire::Fire(12, false, false, true, true, false).ID: return 1848; case Fire::Fire(12, false, false, true, false, true).ID: return 1849; case Fire::Fire(12, false, false, true, false, false).ID: return 1850; case Fire::Fire(12, false, false, false, true, true).ID: return 1851; case Fire::Fire(12, false, false, false, true, false).ID: return 1852; case Fire::Fire(12, false, false, false, false, true).ID: return 1853; case Fire::Fire(12, false, false, false, false, false).ID: return 1854; case Fire::Fire(13, true, true, true, true, true).ID: return 1855; case Fire::Fire(13, true, true, true, true, false).ID: return 1856; case Fire::Fire(13, true, true, true, false, true).ID: return 1857; case Fire::Fire(13, true, true, true, false, false).ID: return 1858; case Fire::Fire(13, true, true, false, true, true).ID: return 1859; case Fire::Fire(13, true, true, false, true, false).ID: return 1860; case Fire::Fire(13, true, true, false, false, true).ID: return 1861; case Fire::Fire(13, true, true, false, false, false).ID: return 1862; case Fire::Fire(13, true, false, true, true, true).ID: return 1863; case Fire::Fire(13, true, false, true, true, false).ID: return 1864; case Fire::Fire(13, true, false, true, false, true).ID: return 1865; case Fire::Fire(13, true, false, true, false, false).ID: return 1866; case Fire::Fire(13, true, false, false, true, true).ID: return 1867; case Fire::Fire(13, true, false, false, true, false).ID: return 1868; case Fire::Fire(13, true, false, false, false, true).ID: return 1869; case Fire::Fire(13, true, false, false, false, false).ID: return 1870; case Fire::Fire(13, false, true, true, true, true).ID: return 1871; case Fire::Fire(13, false, true, true, true, false).ID: return 1872; case Fire::Fire(13, false, true, true, false, true).ID: return 1873; case Fire::Fire(13, false, true, true, false, false).ID: return 1874; case Fire::Fire(13, false, true, false, true, true).ID: return 1875; case Fire::Fire(13, false, true, false, true, false).ID: return 1876; case Fire::Fire(13, false, true, false, false, true).ID: return 1877; case Fire::Fire(13, false, true, false, false, false).ID: return 1878; case Fire::Fire(13, false, false, true, true, true).ID: return 1879; case Fire::Fire(13, false, false, true, true, false).ID: return 1880; case Fire::Fire(13, false, false, true, false, true).ID: return 1881; case Fire::Fire(13, false, false, true, false, false).ID: return 1882; case Fire::Fire(13, false, false, false, true, true).ID: return 1883; case Fire::Fire(13, false, false, false, true, false).ID: return 1884; case Fire::Fire(13, false, false, false, false, true).ID: return 1885; case Fire::Fire(13, false, false, false, false, false).ID: return 1886; case Fire::Fire(14, true, true, true, true, true).ID: return 1887; case Fire::Fire(14, true, true, true, true, false).ID: return 1888; case Fire::Fire(14, true, true, true, false, true).ID: return 1889; case Fire::Fire(14, true, true, true, false, false).ID: return 1890; case Fire::Fire(14, true, true, false, true, true).ID: return 1891; case Fire::Fire(14, true, true, false, true, false).ID: return 1892; case Fire::Fire(14, true, true, false, false, true).ID: return 1893; case Fire::Fire(14, true, true, false, false, false).ID: return 1894; case Fire::Fire(14, true, false, true, true, true).ID: return 1895; case Fire::Fire(14, true, false, true, true, false).ID: return 1896; case Fire::Fire(14, true, false, true, false, true).ID: return 1897; case Fire::Fire(14, true, false, true, false, false).ID: return 1898; case Fire::Fire(14, true, false, false, true, true).ID: return 1899; case Fire::Fire(14, true, false, false, true, false).ID: return 1900; case Fire::Fire(14, true, false, false, false, true).ID: return 1901; case Fire::Fire(14, true, false, false, false, false).ID: return 1902; case Fire::Fire(14, false, true, true, true, true).ID: return 1903; case Fire::Fire(14, false, true, true, true, false).ID: return 1904; case Fire::Fire(14, false, true, true, false, true).ID: return 1905; case Fire::Fire(14, false, true, true, false, false).ID: return 1906; case Fire::Fire(14, false, true, false, true, true).ID: return 1907; case Fire::Fire(14, false, true, false, true, false).ID: return 1908; case Fire::Fire(14, false, true, false, false, true).ID: return 1909; case Fire::Fire(14, false, true, false, false, false).ID: return 1910; case Fire::Fire(14, false, false, true, true, true).ID: return 1911; case Fire::Fire(14, false, false, true, true, false).ID: return 1912; case Fire::Fire(14, false, false, true, false, true).ID: return 1913; case Fire::Fire(14, false, false, true, false, false).ID: return 1914; case Fire::Fire(14, false, false, false, true, true).ID: return 1915; case Fire::Fire(14, false, false, false, true, false).ID: return 1916; case Fire::Fire(14, false, false, false, false, true).ID: return 1917; case Fire::Fire(14, false, false, false, false, false).ID: return 1918; case Fire::Fire(15, true, true, true, true, true).ID: return 1919; case Fire::Fire(15, true, true, true, true, false).ID: return 1920; case Fire::Fire(15, true, true, true, false, true).ID: return 1921; case Fire::Fire(15, true, true, true, false, false).ID: return 1922; case Fire::Fire(15, true, true, false, true, true).ID: return 1923; case Fire::Fire(15, true, true, false, true, false).ID: return 1924; case Fire::Fire(15, true, true, false, false, true).ID: return 1925; case Fire::Fire(15, true, true, false, false, false).ID: return 1926; case Fire::Fire(15, true, false, true, true, true).ID: return 1927; case Fire::Fire(15, true, false, true, true, false).ID: return 1928; case Fire::Fire(15, true, false, true, false, true).ID: return 1929; case Fire::Fire(15, true, false, true, false, false).ID: return 1930; case Fire::Fire(15, true, false, false, true, true).ID: return 1931; case Fire::Fire(15, true, false, false, true, false).ID: return 1932; case Fire::Fire(15, true, false, false, false, true).ID: return 1933; case Fire::Fire(15, true, false, false, false, false).ID: return 1934; case Fire::Fire(15, false, true, true, true, true).ID: return 1935; case Fire::Fire(15, false, true, true, true, false).ID: return 1936; case Fire::Fire(15, false, true, true, false, true).ID: return 1937; case Fire::Fire(15, false, true, true, false, false).ID: return 1938; case Fire::Fire(15, false, true, false, true, true).ID: return 1939; case Fire::Fire(15, false, true, false, true, false).ID: return 1940; case Fire::Fire(15, false, true, false, false, true).ID: return 1941; case Fire::Fire(15, false, true, false, false, false).ID: return 1942; case Fire::Fire(15, false, false, true, true, true).ID: return 1943; case Fire::Fire(15, false, false, true, true, false).ID: return 1944; case Fire::Fire(15, false, false, true, false, true).ID: return 1945; case Fire::Fire(15, false, false, true, false, false).ID: return 1946; case Fire::Fire(15, false, false, false, true, true).ID: return 1947; case Fire::Fire(15, false, false, false, true, false).ID: return 1948; case Fire::Fire(15, false, false, false, false, true).ID: return 1949; case Fire::Fire(15, false, false, false, false, false).ID: return 1950; case FireCoral::FireCoral().ID: return 9001; case FireCoralBlock::FireCoralBlock().ID: return 8982; case FireCoralFan::FireCoralFan().ID: return 9021; case FireCoralWallFan::FireCoralWallFan(eBlockFace::BLOCK_FACE_ZM).ID: return 9089; case FireCoralWallFan::FireCoralWallFan(eBlockFace::BLOCK_FACE_ZP).ID: return 9091; case FireCoralWallFan::FireCoralWallFan(eBlockFace::BLOCK_FACE_XM).ID: return 9093; case FireCoralWallFan::FireCoralWallFan(eBlockFace::BLOCK_FACE_XP).ID: return 9095; case FletchingTable::FletchingTable().ID: return 11164; case FlowerPot::FlowerPot().ID: return 5769; case FrostedIce::FrostedIce(0).ID: return 8713; case FrostedIce::FrostedIce(1).ID: return 8714; case FrostedIce::FrostedIce(2).ID: return 8715; case FrostedIce::FrostedIce(3).ID: return 8716; case Furnace::Furnace(eBlockFace::BLOCK_FACE_ZM, true).ID: return 3371; case Furnace::Furnace(eBlockFace::BLOCK_FACE_ZM, false).ID: return 3372; case Furnace::Furnace(eBlockFace::BLOCK_FACE_ZP, true).ID: return 3373; case Furnace::Furnace(eBlockFace::BLOCK_FACE_ZP, false).ID: return 3374; case Furnace::Furnace(eBlockFace::BLOCK_FACE_XM, true).ID: return 3375; case Furnace::Furnace(eBlockFace::BLOCK_FACE_XM, false).ID: return 3376; case Furnace::Furnace(eBlockFace::BLOCK_FACE_XP, true).ID: return 3377; case Furnace::Furnace(eBlockFace::BLOCK_FACE_XP, false).ID: return 3378; case Glass::Glass().ID: return 230; case GlassPane::GlassPane(true, true, true, true).ID: return 4717; case GlassPane::GlassPane(true, true, true, false).ID: return 4718; case GlassPane::GlassPane(true, true, false, true).ID: return 4721; case GlassPane::GlassPane(true, true, false, false).ID: return 4722; case GlassPane::GlassPane(true, false, true, true).ID: return 4725; case GlassPane::GlassPane(true, false, true, false).ID: return 4726; case GlassPane::GlassPane(true, false, false, true).ID: return 4729; case GlassPane::GlassPane(true, false, false, false).ID: return 4730; case GlassPane::GlassPane(false, true, true, true).ID: return 4733; case GlassPane::GlassPane(false, true, true, false).ID: return 4734; case GlassPane::GlassPane(false, true, false, true).ID: return 4737; case GlassPane::GlassPane(false, true, false, false).ID: return 4738; case GlassPane::GlassPane(false, false, true, true).ID: return 4741; case GlassPane::GlassPane(false, false, true, false).ID: return 4742; case GlassPane::GlassPane(false, false, false, true).ID: return 4745; case GlassPane::GlassPane(false, false, false, false).ID: return 4746; case Glowstone::Glowstone().ID: return 3999; case GoldBlock::GoldBlock().ID: return 1426; case GoldOre::GoldOre().ID: return 69; case Granite::Granite().ID: return 2; case GraniteSlab::GraniteSlab(GraniteSlab::Type::Top).ID: return 10302; case GraniteSlab::GraniteSlab(GraniteSlab::Type::Bottom).ID: return 10304; case GraniteSlab::GraniteSlab(GraniteSlab::Type::Double).ID: return 10306; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_ZM, GraniteStairs::Half::Top, GraniteStairs::Shape::Straight).ID: return 9854; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_ZM, GraniteStairs::Half::Top, GraniteStairs::Shape::InnerLeft).ID: return 9856; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_ZM, GraniteStairs::Half::Top, GraniteStairs::Shape::InnerRight).ID: return 9858; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_ZM, GraniteStairs::Half::Top, GraniteStairs::Shape::OuterLeft).ID: return 9860; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_ZM, GraniteStairs::Half::Top, GraniteStairs::Shape::OuterRight).ID: return 9862; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_ZM, GraniteStairs::Half::Bottom, GraniteStairs::Shape::Straight).ID: return 9864; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_ZM, GraniteStairs::Half::Bottom, GraniteStairs::Shape::InnerLeft).ID: return 9866; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_ZM, GraniteStairs::Half::Bottom, GraniteStairs::Shape::InnerRight).ID: return 9868; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_ZM, GraniteStairs::Half::Bottom, GraniteStairs::Shape::OuterLeft).ID: return 9870; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_ZM, GraniteStairs::Half::Bottom, GraniteStairs::Shape::OuterRight).ID: return 9872; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_ZP, GraniteStairs::Half::Top, GraniteStairs::Shape::Straight).ID: return 9874; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_ZP, GraniteStairs::Half::Top, GraniteStairs::Shape::InnerLeft).ID: return 9876; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_ZP, GraniteStairs::Half::Top, GraniteStairs::Shape::InnerRight).ID: return 9878; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_ZP, GraniteStairs::Half::Top, GraniteStairs::Shape::OuterLeft).ID: return 9880; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_ZP, GraniteStairs::Half::Top, GraniteStairs::Shape::OuterRight).ID: return 9882; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_ZP, GraniteStairs::Half::Bottom, GraniteStairs::Shape::Straight).ID: return 9884; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_ZP, GraniteStairs::Half::Bottom, GraniteStairs::Shape::InnerLeft).ID: return 9886; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_ZP, GraniteStairs::Half::Bottom, GraniteStairs::Shape::InnerRight).ID: return 9888; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_ZP, GraniteStairs::Half::Bottom, GraniteStairs::Shape::OuterLeft).ID: return 9890; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_ZP, GraniteStairs::Half::Bottom, GraniteStairs::Shape::OuterRight).ID: return 9892; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_XM, GraniteStairs::Half::Top, GraniteStairs::Shape::Straight).ID: return 9894; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_XM, GraniteStairs::Half::Top, GraniteStairs::Shape::InnerLeft).ID: return 9896; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_XM, GraniteStairs::Half::Top, GraniteStairs::Shape::InnerRight).ID: return 9898; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_XM, GraniteStairs::Half::Top, GraniteStairs::Shape::OuterLeft).ID: return 9900; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_XM, GraniteStairs::Half::Top, GraniteStairs::Shape::OuterRight).ID: return 9902; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_XM, GraniteStairs::Half::Bottom, GraniteStairs::Shape::Straight).ID: return 9904; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_XM, GraniteStairs::Half::Bottom, GraniteStairs::Shape::InnerLeft).ID: return 9906; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_XM, GraniteStairs::Half::Bottom, GraniteStairs::Shape::InnerRight).ID: return 9908; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_XM, GraniteStairs::Half::Bottom, GraniteStairs::Shape::OuterLeft).ID: return 9910; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_XM, GraniteStairs::Half::Bottom, GraniteStairs::Shape::OuterRight).ID: return 9912; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_XP, GraniteStairs::Half::Top, GraniteStairs::Shape::Straight).ID: return 9914; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_XP, GraniteStairs::Half::Top, GraniteStairs::Shape::InnerLeft).ID: return 9916; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_XP, GraniteStairs::Half::Top, GraniteStairs::Shape::InnerRight).ID: return 9918; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_XP, GraniteStairs::Half::Top, GraniteStairs::Shape::OuterLeft).ID: return 9920; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_XP, GraniteStairs::Half::Top, GraniteStairs::Shape::OuterRight).ID: return 9922; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_XP, GraniteStairs::Half::Bottom, GraniteStairs::Shape::Straight).ID: return 9924; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_XP, GraniteStairs::Half::Bottom, GraniteStairs::Shape::InnerLeft).ID: return 9926; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_XP, GraniteStairs::Half::Bottom, GraniteStairs::Shape::InnerRight).ID: return 9928; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_XP, GraniteStairs::Half::Bottom, GraniteStairs::Shape::OuterLeft).ID: return 9930; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_XP, GraniteStairs::Half::Bottom, GraniteStairs::Shape::OuterRight).ID: return 9932; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::Low, GraniteWall::South::Low, true, GraniteWall::West::Low).ID: return 10589; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::Low, GraniteWall::South::Low, true, GraniteWall::West::None).ID: return 10590; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::Low, GraniteWall::South::Low, false, GraniteWall::West::Low).ID: return 10593; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::Low, GraniteWall::South::Low, false, GraniteWall::West::None).ID: return 10594; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::Low, GraniteWall::South::None, true, GraniteWall::West::Low).ID: return 10597; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::Low, GraniteWall::South::None, true, GraniteWall::West::None).ID: return 10598; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::Low, GraniteWall::South::None, false, GraniteWall::West::Low).ID: return 10601; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::Low, GraniteWall::South::None, false, GraniteWall::West::None).ID: return 10602; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::None, GraniteWall::South::Low, true, GraniteWall::West::Low).ID: return 10605; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::None, GraniteWall::South::Low, true, GraniteWall::West::None).ID: return 10606; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::None, GraniteWall::South::Low, false, GraniteWall::West::Low).ID: return 10609; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::None, GraniteWall::South::Low, false, GraniteWall::West::None).ID: return 10610; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::None, GraniteWall::South::None, true, GraniteWall::West::Low).ID: return 10613; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::None, GraniteWall::South::None, true, GraniteWall::West::None).ID: return 10614; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::None, GraniteWall::South::None, false, GraniteWall::West::Low).ID: return 10617; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::None, GraniteWall::South::None, false, GraniteWall::West::None).ID: return 10618; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::Low, GraniteWall::South::Low, true, GraniteWall::West::Low).ID: return 10621; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::Low, GraniteWall::South::Low, true, GraniteWall::West::None).ID: return 10622; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::Low, GraniteWall::South::Low, false, GraniteWall::West::Low).ID: return 10625; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::Low, GraniteWall::South::Low, false, GraniteWall::West::None).ID: return 10626; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::Low, GraniteWall::South::None, true, GraniteWall::West::Low).ID: return 10629; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::Low, GraniteWall::South::None, true, GraniteWall::West::None).ID: return 10630; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::Low, GraniteWall::South::None, false, GraniteWall::West::Low).ID: return 10633; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::Low, GraniteWall::South::None, false, GraniteWall::West::None).ID: return 10634; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::None, GraniteWall::South::Low, true, GraniteWall::West::Low).ID: return 10637; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::None, GraniteWall::South::Low, true, GraniteWall::West::None).ID: return 10638; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::None, GraniteWall::South::Low, false, GraniteWall::West::Low).ID: return 10641; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::None, GraniteWall::South::Low, false, GraniteWall::West::None).ID: return 10642; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::None, GraniteWall::South::None, true, GraniteWall::West::Low).ID: return 10645; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::None, GraniteWall::South::None, true, GraniteWall::West::None).ID: return 10646; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::None, GraniteWall::South::None, false, GraniteWall::West::Low).ID: return 10649; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::None, GraniteWall::South::None, false, GraniteWall::West::None).ID: return 10650; case Grass::Grass().ID: return 1341; case GrassBlock::GrassBlock(true).ID: return 8; case GrassBlock::GrassBlock(false).ID: return 9; case GrassPath::GrassPath().ID: return 8687; case Gravel::Gravel().ID: return 68; case GrayBanner::GrayBanner(0).ID: return 7473; case GrayBanner::GrayBanner(1).ID: return 7474; case GrayBanner::GrayBanner(2).ID: return 7475; case GrayBanner::GrayBanner(3).ID: return 7476; case GrayBanner::GrayBanner(4).ID: return 7477; case GrayBanner::GrayBanner(5).ID: return 7478; case GrayBanner::GrayBanner(6).ID: return 7479; case GrayBanner::GrayBanner(7).ID: return 7480; case GrayBanner::GrayBanner(8).ID: return 7481; case GrayBanner::GrayBanner(9).ID: return 7482; case GrayBanner::GrayBanner(10).ID: return 7483; case GrayBanner::GrayBanner(11).ID: return 7484; case GrayBanner::GrayBanner(12).ID: return 7485; case GrayBanner::GrayBanner(13).ID: return 7486; case GrayBanner::GrayBanner(14).ID: return 7487; case GrayBanner::GrayBanner(15).ID: return 7488; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_ZM, true, GrayBed::Part::Head).ID: return 1160; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_ZM, true, GrayBed::Part::Foot).ID: return 1161; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_ZM, false, GrayBed::Part::Head).ID: return 1162; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_ZM, false, GrayBed::Part::Foot).ID: return 1163; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_ZP, true, GrayBed::Part::Head).ID: return 1164; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_ZP, true, GrayBed::Part::Foot).ID: return 1165; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_ZP, false, GrayBed::Part::Head).ID: return 1166; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_ZP, false, GrayBed::Part::Foot).ID: return 1167; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_XM, true, GrayBed::Part::Head).ID: return 1168; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_XM, true, GrayBed::Part::Foot).ID: return 1169; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_XM, false, GrayBed::Part::Head).ID: return 1170; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_XM, false, GrayBed::Part::Foot).ID: return 1171; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_XP, true, GrayBed::Part::Head).ID: return 1172; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_XP, true, GrayBed::Part::Foot).ID: return 1173; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_XP, false, GrayBed::Part::Head).ID: return 1174; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_XP, false, GrayBed::Part::Foot).ID: return 1175; case GrayCarpet::GrayCarpet().ID: return 7337; case GrayConcrete::GrayConcrete().ID: return 8909; case GrayConcretePowder::GrayConcretePowder().ID: return 8925; case GrayGlazedTerracotta::GrayGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 8866; case GrayGlazedTerracotta::GrayGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 8867; case GrayGlazedTerracotta::GrayGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 8868; case GrayGlazedTerracotta::GrayGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 8869; case GrayShulkerBox::GrayShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 8784; case GrayShulkerBox::GrayShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 8785; case GrayShulkerBox::GrayShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 8786; case GrayShulkerBox::GrayShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 8787; case GrayShulkerBox::GrayShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 8788; case GrayShulkerBox::GrayShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 8789; case GrayStainedGlass::GrayStainedGlass().ID: return 4088; case GrayStainedGlassPane::GrayStainedGlassPane(true, true, true, true).ID: return 6553; case GrayStainedGlassPane::GrayStainedGlassPane(true, true, true, false).ID: return 6554; case GrayStainedGlassPane::GrayStainedGlassPane(true, true, false, true).ID: return 6557; case GrayStainedGlassPane::GrayStainedGlassPane(true, true, false, false).ID: return 6558; case GrayStainedGlassPane::GrayStainedGlassPane(true, false, true, true).ID: return 6561; case GrayStainedGlassPane::GrayStainedGlassPane(true, false, true, false).ID: return 6562; case GrayStainedGlassPane::GrayStainedGlassPane(true, false, false, true).ID: return 6565; case GrayStainedGlassPane::GrayStainedGlassPane(true, false, false, false).ID: return 6566; case GrayStainedGlassPane::GrayStainedGlassPane(false, true, true, true).ID: return 6569; case GrayStainedGlassPane::GrayStainedGlassPane(false, true, true, false).ID: return 6570; case GrayStainedGlassPane::GrayStainedGlassPane(false, true, false, true).ID: return 6573; case GrayStainedGlassPane::GrayStainedGlassPane(false, true, false, false).ID: return 6574; case GrayStainedGlassPane::GrayStainedGlassPane(false, false, true, true).ID: return 6577; case GrayStainedGlassPane::GrayStainedGlassPane(false, false, true, false).ID: return 6578; case GrayStainedGlassPane::GrayStainedGlassPane(false, false, false, true).ID: return 6581; case GrayStainedGlassPane::GrayStainedGlassPane(false, false, false, false).ID: return 6582; case GrayTerracotta::GrayTerracotta().ID: return 6318; case GrayWallBanner::GrayWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 7645; case GrayWallBanner::GrayWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 7646; case GrayWallBanner::GrayWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 7647; case GrayWallBanner::GrayWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 7648; case GrayWool::GrayWool().ID: return 1390; case GreenBanner::GreenBanner(0).ID: return 7569; case GreenBanner::GreenBanner(1).ID: return 7570; case GreenBanner::GreenBanner(2).ID: return 7571; case GreenBanner::GreenBanner(3).ID: return 7572; case GreenBanner::GreenBanner(4).ID: return 7573; case GreenBanner::GreenBanner(5).ID: return 7574; case GreenBanner::GreenBanner(6).ID: return 7575; case GreenBanner::GreenBanner(7).ID: return 7576; case GreenBanner::GreenBanner(8).ID: return 7577; case GreenBanner::GreenBanner(9).ID: return 7578; case GreenBanner::GreenBanner(10).ID: return 7579; case GreenBanner::GreenBanner(11).ID: return 7580; case GreenBanner::GreenBanner(12).ID: return 7581; case GreenBanner::GreenBanner(13).ID: return 7582; case GreenBanner::GreenBanner(14).ID: return 7583; case GreenBanner::GreenBanner(15).ID: return 7584; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_ZM, true, GreenBed::Part::Head).ID: return 1256; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_ZM, true, GreenBed::Part::Foot).ID: return 1257; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_ZM, false, GreenBed::Part::Head).ID: return 1258; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_ZM, false, GreenBed::Part::Foot).ID: return 1259; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_ZP, true, GreenBed::Part::Head).ID: return 1260; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_ZP, true, GreenBed::Part::Foot).ID: return 1261; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_ZP, false, GreenBed::Part::Head).ID: return 1262; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_ZP, false, GreenBed::Part::Foot).ID: return 1263; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_XM, true, GreenBed::Part::Head).ID: return 1264; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_XM, true, GreenBed::Part::Foot).ID: return 1265; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_XM, false, GreenBed::Part::Head).ID: return 1266; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_XM, false, GreenBed::Part::Foot).ID: return 1267; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_XP, true, GreenBed::Part::Head).ID: return 1268; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_XP, true, GreenBed::Part::Foot).ID: return 1269; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_XP, false, GreenBed::Part::Head).ID: return 1270; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_XP, false, GreenBed::Part::Foot).ID: return 1271; case GreenCarpet::GreenCarpet().ID: return 7343; case GreenConcrete::GreenConcrete().ID: return 8915; case GreenConcretePowder::GreenConcretePowder().ID: return 8931; case GreenGlazedTerracotta::GreenGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 8890; case GreenGlazedTerracotta::GreenGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 8891; case GreenGlazedTerracotta::GreenGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 8892; case GreenGlazedTerracotta::GreenGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 8893; case GreenShulkerBox::GreenShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 8820; case GreenShulkerBox::GreenShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 8821; case GreenShulkerBox::GreenShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 8822; case GreenShulkerBox::GreenShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 8823; case GreenShulkerBox::GreenShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 8824; case GreenShulkerBox::GreenShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 8825; case GreenStainedGlass::GreenStainedGlass().ID: return 4094; case GreenStainedGlassPane::GreenStainedGlassPane(true, true, true, true).ID: return 6745; case GreenStainedGlassPane::GreenStainedGlassPane(true, true, true, false).ID: return 6746; case GreenStainedGlassPane::GreenStainedGlassPane(true, true, false, true).ID: return 6749; case GreenStainedGlassPane::GreenStainedGlassPane(true, true, false, false).ID: return 6750; case GreenStainedGlassPane::GreenStainedGlassPane(true, false, true, true).ID: return 6753; case GreenStainedGlassPane::GreenStainedGlassPane(true, false, true, false).ID: return 6754; case GreenStainedGlassPane::GreenStainedGlassPane(true, false, false, true).ID: return 6757; case GreenStainedGlassPane::GreenStainedGlassPane(true, false, false, false).ID: return 6758; case GreenStainedGlassPane::GreenStainedGlassPane(false, true, true, true).ID: return 6761; case GreenStainedGlassPane::GreenStainedGlassPane(false, true, true, false).ID: return 6762; case GreenStainedGlassPane::GreenStainedGlassPane(false, true, false, true).ID: return 6765; case GreenStainedGlassPane::GreenStainedGlassPane(false, true, false, false).ID: return 6766; case GreenStainedGlassPane::GreenStainedGlassPane(false, false, true, true).ID: return 6769; case GreenStainedGlassPane::GreenStainedGlassPane(false, false, true, false).ID: return 6770; case GreenStainedGlassPane::GreenStainedGlassPane(false, false, false, true).ID: return 6773; case GreenStainedGlassPane::GreenStainedGlassPane(false, false, false, false).ID: return 6774; case GreenTerracotta::GreenTerracotta().ID: return 6324; case GreenWallBanner::GreenWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 7669; case GreenWallBanner::GreenWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 7670; case GreenWallBanner::GreenWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 7671; case GreenWallBanner::GreenWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 7672; case GreenWool::GreenWool().ID: return 1396; case Grindstone::Grindstone(Grindstone::Face::Floor, eBlockFace::BLOCK_FACE_ZM).ID: return 11165; case Grindstone::Grindstone(Grindstone::Face::Floor, eBlockFace::BLOCK_FACE_ZP).ID: return 11166; case Grindstone::Grindstone(Grindstone::Face::Floor, eBlockFace::BLOCK_FACE_XM).ID: return 11167; case Grindstone::Grindstone(Grindstone::Face::Floor, eBlockFace::BLOCK_FACE_XP).ID: return 11168; case Grindstone::Grindstone(Grindstone::Face::Wall, eBlockFace::BLOCK_FACE_ZM).ID: return 11169; case Grindstone::Grindstone(Grindstone::Face::Wall, eBlockFace::BLOCK_FACE_ZP).ID: return 11170; case Grindstone::Grindstone(Grindstone::Face::Wall, eBlockFace::BLOCK_FACE_XM).ID: return 11171; case Grindstone::Grindstone(Grindstone::Face::Wall, eBlockFace::BLOCK_FACE_XP).ID: return 11172; case Grindstone::Grindstone(Grindstone::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM).ID: return 11173; case Grindstone::Grindstone(Grindstone::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP).ID: return 11174; case Grindstone::Grindstone(Grindstone::Face::Ceiling, eBlockFace::BLOCK_FACE_XM).ID: return 11175; case Grindstone::Grindstone(Grindstone::Face::Ceiling, eBlockFace::BLOCK_FACE_XP).ID: return 11176; case HayBale::HayBale(HayBale::Axis::X).ID: return 7327; case HayBale::HayBale(HayBale::Axis::Y).ID: return 7328; case HayBale::HayBale(HayBale::Axis::Z).ID: return 7329; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(0).ID: return 6126; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(1).ID: return 6127; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(2).ID: return 6128; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(3).ID: return 6129; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(4).ID: return 6130; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(5).ID: return 6131; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(6).ID: return 6132; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(7).ID: return 6133; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(8).ID: return 6134; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(9).ID: return 6135; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(10).ID: return 6136; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(11).ID: return 6137; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(12).ID: return 6138; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(13).ID: return 6139; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(14).ID: return 6140; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(15).ID: return 6141; case HoneyBlock::HoneyBlock().ID: return 11335; case HoneycombBlock::HoneycombBlock().ID: return 11336; case Hopper::Hopper(true, eBlockFace::BLOCK_FACE_YM).ID: return 6192; case Hopper::Hopper(true, eBlockFace::BLOCK_FACE_ZM).ID: return 6193; case Hopper::Hopper(true, eBlockFace::BLOCK_FACE_ZP).ID: return 6194; case Hopper::Hopper(true, eBlockFace::BLOCK_FACE_XM).ID: return 6195; case Hopper::Hopper(true, eBlockFace::BLOCK_FACE_XP).ID: return 6196; case Hopper::Hopper(false, eBlockFace::BLOCK_FACE_YM).ID: return 6197; case Hopper::Hopper(false, eBlockFace::BLOCK_FACE_ZM).ID: return 6198; case Hopper::Hopper(false, eBlockFace::BLOCK_FACE_ZP).ID: return 6199; case Hopper::Hopper(false, eBlockFace::BLOCK_FACE_XM).ID: return 6200; case Hopper::Hopper(false, eBlockFace::BLOCK_FACE_XP).ID: return 6201; case HornCoral::HornCoral().ID: return 9003; case HornCoralBlock::HornCoralBlock().ID: return 8983; case HornCoralFan::HornCoralFan().ID: return 9023; case HornCoralWallFan::HornCoralWallFan(eBlockFace::BLOCK_FACE_ZM).ID: return 9097; case HornCoralWallFan::HornCoralWallFan(eBlockFace::BLOCK_FACE_ZP).ID: return 9099; case HornCoralWallFan::HornCoralWallFan(eBlockFace::BLOCK_FACE_XM).ID: return 9101; case HornCoralWallFan::HornCoralWallFan(eBlockFace::BLOCK_FACE_XP).ID: return 9103; case Ice::Ice().ID: return 3927; case InfestedChiseledStoneBricks::InfestedChiseledStoneBricks().ID: return 4490; case InfestedCobblestone::InfestedCobblestone().ID: return 4486; case InfestedCrackedStoneBricks::InfestedCrackedStoneBricks().ID: return 4489; case InfestedMossyStoneBricks::InfestedMossyStoneBricks().ID: return 4488; case InfestedStone::InfestedStone().ID: return 4485; case InfestedStoneBricks::InfestedStoneBricks().ID: return 4487; case IronBars::IronBars(true, true, true, true).ID: return 4685; case IronBars::IronBars(true, true, true, false).ID: return 4686; case IronBars::IronBars(true, true, false, true).ID: return 4689; case IronBars::IronBars(true, true, false, false).ID: return 4690; case IronBars::IronBars(true, false, true, true).ID: return 4693; case IronBars::IronBars(true, false, true, false).ID: return 4694; case IronBars::IronBars(true, false, false, true).ID: return 4697; case IronBars::IronBars(true, false, false, false).ID: return 4698; case IronBars::IronBars(false, true, true, true).ID: return 4701; case IronBars::IronBars(false, true, true, false).ID: return 4702; case IronBars::IronBars(false, true, false, true).ID: return 4705; case IronBars::IronBars(false, true, false, false).ID: return 4706; case IronBars::IronBars(false, false, true, true).ID: return 4709; case IronBars::IronBars(false, false, true, false).ID: return 4710; case IronBars::IronBars(false, false, false, true).ID: return 4713; case IronBars::IronBars(false, false, false, false).ID: return 4714; case IronBlock::IronBlock().ID: return 1427; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Upper, IronDoor::Hinge::Left, true, true).ID: return 3807; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Upper, IronDoor::Hinge::Left, true, false).ID: return 3808; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Upper, IronDoor::Hinge::Left, false, true).ID: return 3809; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Upper, IronDoor::Hinge::Left, false, false).ID: return 3810; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Upper, IronDoor::Hinge::Right, true, true).ID: return 3811; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Upper, IronDoor::Hinge::Right, true, false).ID: return 3812; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Upper, IronDoor::Hinge::Right, false, true).ID: return 3813; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Upper, IronDoor::Hinge::Right, false, false).ID: return 3814; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Lower, IronDoor::Hinge::Left, true, true).ID: return 3815; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Lower, IronDoor::Hinge::Left, true, false).ID: return 3816; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Lower, IronDoor::Hinge::Left, false, true).ID: return 3817; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Lower, IronDoor::Hinge::Left, false, false).ID: return 3818; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Lower, IronDoor::Hinge::Right, true, true).ID: return 3819; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Lower, IronDoor::Hinge::Right, true, false).ID: return 3820; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Lower, IronDoor::Hinge::Right, false, true).ID: return 3821; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Lower, IronDoor::Hinge::Right, false, false).ID: return 3822; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Upper, IronDoor::Hinge::Left, true, true).ID: return 3823; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Upper, IronDoor::Hinge::Left, true, false).ID: return 3824; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Upper, IronDoor::Hinge::Left, false, true).ID: return 3825; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Upper, IronDoor::Hinge::Left, false, false).ID: return 3826; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Upper, IronDoor::Hinge::Right, true, true).ID: return 3827; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Upper, IronDoor::Hinge::Right, true, false).ID: return 3828; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Upper, IronDoor::Hinge::Right, false, true).ID: return 3829; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Upper, IronDoor::Hinge::Right, false, false).ID: return 3830; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Lower, IronDoor::Hinge::Left, true, true).ID: return 3831; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Lower, IronDoor::Hinge::Left, true, false).ID: return 3832; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Lower, IronDoor::Hinge::Left, false, true).ID: return 3833; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Lower, IronDoor::Hinge::Left, false, false).ID: return 3834; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Lower, IronDoor::Hinge::Right, true, true).ID: return 3835; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Lower, IronDoor::Hinge::Right, true, false).ID: return 3836; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Lower, IronDoor::Hinge::Right, false, true).ID: return 3837; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Lower, IronDoor::Hinge::Right, false, false).ID: return 3838; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Upper, IronDoor::Hinge::Left, true, true).ID: return 3839; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Upper, IronDoor::Hinge::Left, true, false).ID: return 3840; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Upper, IronDoor::Hinge::Left, false, true).ID: return 3841; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Upper, IronDoor::Hinge::Left, false, false).ID: return 3842; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Upper, IronDoor::Hinge::Right, true, true).ID: return 3843; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Upper, IronDoor::Hinge::Right, true, false).ID: return 3844; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Upper, IronDoor::Hinge::Right, false, true).ID: return 3845; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Upper, IronDoor::Hinge::Right, false, false).ID: return 3846; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Lower, IronDoor::Hinge::Left, true, true).ID: return 3847; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Lower, IronDoor::Hinge::Left, true, false).ID: return 3848; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Lower, IronDoor::Hinge::Left, false, true).ID: return 3849; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Lower, IronDoor::Hinge::Left, false, false).ID: return 3850; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Lower, IronDoor::Hinge::Right, true, true).ID: return 3851; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Lower, IronDoor::Hinge::Right, true, false).ID: return 3852; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Lower, IronDoor::Hinge::Right, false, true).ID: return 3853; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Lower, IronDoor::Hinge::Right, false, false).ID: return 3854; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Upper, IronDoor::Hinge::Left, true, true).ID: return 3855; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Upper, IronDoor::Hinge::Left, true, false).ID: return 3856; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Upper, IronDoor::Hinge::Left, false, true).ID: return 3857; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Upper, IronDoor::Hinge::Left, false, false).ID: return 3858; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Upper, IronDoor::Hinge::Right, true, true).ID: return 3859; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Upper, IronDoor::Hinge::Right, true, false).ID: return 3860; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Upper, IronDoor::Hinge::Right, false, true).ID: return 3861; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Upper, IronDoor::Hinge::Right, false, false).ID: return 3862; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Lower, IronDoor::Hinge::Left, true, true).ID: return 3863; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Lower, IronDoor::Hinge::Left, true, false).ID: return 3864; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Lower, IronDoor::Hinge::Left, false, true).ID: return 3865; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Lower, IronDoor::Hinge::Left, false, false).ID: return 3866; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Lower, IronDoor::Hinge::Right, true, true).ID: return 3867; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Lower, IronDoor::Hinge::Right, true, false).ID: return 3868; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Lower, IronDoor::Hinge::Right, false, true).ID: return 3869; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Lower, IronDoor::Hinge::Right, false, false).ID: return 3870; case IronOre::IronOre().ID: return 70; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZM, IronTrapdoor::Half::Top, true, true).ID: return 7002; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZM, IronTrapdoor::Half::Top, true, false).ID: return 7004; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZM, IronTrapdoor::Half::Top, false, true).ID: return 7006; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZM, IronTrapdoor::Half::Top, false, false).ID: return 7008; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZM, IronTrapdoor::Half::Bottom, true, true).ID: return 7010; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZM, IronTrapdoor::Half::Bottom, true, false).ID: return 7012; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZM, IronTrapdoor::Half::Bottom, false, true).ID: return 7014; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZM, IronTrapdoor::Half::Bottom, false, false).ID: return 7016; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZP, IronTrapdoor::Half::Top, true, true).ID: return 7018; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZP, IronTrapdoor::Half::Top, true, false).ID: return 7020; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZP, IronTrapdoor::Half::Top, false, true).ID: return 7022; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZP, IronTrapdoor::Half::Top, false, false).ID: return 7024; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZP, IronTrapdoor::Half::Bottom, true, true).ID: return 7026; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZP, IronTrapdoor::Half::Bottom, true, false).ID: return 7028; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZP, IronTrapdoor::Half::Bottom, false, true).ID: return 7030; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZP, IronTrapdoor::Half::Bottom, false, false).ID: return 7032; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XM, IronTrapdoor::Half::Top, true, true).ID: return 7034; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XM, IronTrapdoor::Half::Top, true, false).ID: return 7036; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XM, IronTrapdoor::Half::Top, false, true).ID: return 7038; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XM, IronTrapdoor::Half::Top, false, false).ID: return 7040; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XM, IronTrapdoor::Half::Bottom, true, true).ID: return 7042; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XM, IronTrapdoor::Half::Bottom, true, false).ID: return 7044; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XM, IronTrapdoor::Half::Bottom, false, true).ID: return 7046; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XM, IronTrapdoor::Half::Bottom, false, false).ID: return 7048; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XP, IronTrapdoor::Half::Top, true, true).ID: return 7050; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XP, IronTrapdoor::Half::Top, true, false).ID: return 7052; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XP, IronTrapdoor::Half::Top, false, true).ID: return 7054; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XP, IronTrapdoor::Half::Top, false, false).ID: return 7056; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XP, IronTrapdoor::Half::Bottom, true, true).ID: return 7058; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XP, IronTrapdoor::Half::Bottom, true, false).ID: return 7060; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XP, IronTrapdoor::Half::Bottom, false, true).ID: return 7062; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XP, IronTrapdoor::Half::Bottom, false, false).ID: return 7064; case JackOLantern::JackOLantern(eBlockFace::BLOCK_FACE_ZM).ID: return 4006; case JackOLantern::JackOLantern(eBlockFace::BLOCK_FACE_ZP).ID: return 4007; case JackOLantern::JackOLantern(eBlockFace::BLOCK_FACE_XM).ID: return 4008; case JackOLantern::JackOLantern(eBlockFace::BLOCK_FACE_XP).ID: return 4009; case Jigsaw::Jigsaw(Jigsaw::Orientation::NorthUp).ID: return 11272; case Jigsaw::Jigsaw(Jigsaw::Orientation::EastUp).ID: return 11273; case Jigsaw::Jigsaw(Jigsaw::Orientation::SouthUp).ID: return 11274; case Jigsaw::Jigsaw(Jigsaw::Orientation::WestUp).ID: return 11275; case Jigsaw::Jigsaw(Jigsaw::Orientation::UpSouth).ID: return 11276; case Jigsaw::Jigsaw(Jigsaw::Orientation::DownSouth).ID: return 11277; case Jukebox::Jukebox(true).ID: return 3962; case Jukebox::Jukebox(false).ID: return 3963; case JungleButton::JungleButton(JungleButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5882; case JungleButton::JungleButton(JungleButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5883; case JungleButton::JungleButton(JungleButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5884; case JungleButton::JungleButton(JungleButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5885; case JungleButton::JungleButton(JungleButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, true).ID: return 5886; case JungleButton::JungleButton(JungleButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, false).ID: return 5887; case JungleButton::JungleButton(JungleButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, true).ID: return 5888; case JungleButton::JungleButton(JungleButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, false).ID: return 5889; case JungleButton::JungleButton(JungleButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5890; case JungleButton::JungleButton(JungleButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5891; case JungleButton::JungleButton(JungleButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5892; case JungleButton::JungleButton(JungleButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5893; case JungleButton::JungleButton(JungleButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, true).ID: return 5894; case JungleButton::JungleButton(JungleButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, false).ID: return 5895; case JungleButton::JungleButton(JungleButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, true).ID: return 5896; case JungleButton::JungleButton(JungleButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, false).ID: return 5897; case JungleButton::JungleButton(JungleButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5898; case JungleButton::JungleButton(JungleButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5899; case JungleButton::JungleButton(JungleButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5900; case JungleButton::JungleButton(JungleButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5901; case JungleButton::JungleButton(JungleButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, true).ID: return 5902; case JungleButton::JungleButton(JungleButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, false).ID: return 5903; case JungleButton::JungleButton(JungleButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, true).ID: return 5904; case JungleButton::JungleButton(JungleButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, false).ID: return 5905; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, true, true).ID: return 8330; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, true, false).ID: return 8331; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, false, true).ID: return 8332; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, false, false).ID: return 8333; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, true, true).ID: return 8334; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, true, false).ID: return 8335; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, false, true).ID: return 8336; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, false, false).ID: return 8337; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, true, true).ID: return 8338; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, true, false).ID: return 8339; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, false, true).ID: return 8340; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, false, false).ID: return 8341; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, true, true).ID: return 8342; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, true, false).ID: return 8343; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, false, true).ID: return 8344; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, false, false).ID: return 8345; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, true, true).ID: return 8346; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, true, false).ID: return 8347; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, false, true).ID: return 8348; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, false, false).ID: return 8349; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, true, true).ID: return 8350; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, true, false).ID: return 8351; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, false, true).ID: return 8352; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, false, false).ID: return 8353; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, true, true).ID: return 8354; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, true, false).ID: return 8355; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, false, true).ID: return 8356; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, false, false).ID: return 8357; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, true, true).ID: return 8358; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, true, false).ID: return 8359; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, false, true).ID: return 8360; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, false, false).ID: return 8361; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, true, true).ID: return 8362; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, true, false).ID: return 8363; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, false, true).ID: return 8364; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, false, false).ID: return 8365; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, true, true).ID: return 8366; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, true, false).ID: return 8367; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, false, true).ID: return 8368; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, false, false).ID: return 8369; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, true, true).ID: return 8370; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, true, false).ID: return 8371; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, false, true).ID: return 8372; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, false, false).ID: return 8373; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, true, true).ID: return 8374; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, true, false).ID: return 8375; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, false, true).ID: return 8376; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, false, false).ID: return 8377; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, true, true).ID: return 8378; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, true, false).ID: return 8379; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, false, true).ID: return 8380; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, false, false).ID: return 8381; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, true, true).ID: return 8382; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, true, false).ID: return 8383; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, false, true).ID: return 8384; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, false, false).ID: return 8385; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, true, true).ID: return 8386; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, true, false).ID: return 8387; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, false, true).ID: return 8388; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, false, false).ID: return 8389; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, true, true).ID: return 8390; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, true, false).ID: return 8391; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, false, true).ID: return 8392; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, false, false).ID: return 8393; case JungleFence::JungleFence(true, true, true, true).ID: return 8108; case JungleFence::JungleFence(true, true, true, false).ID: return 8109; case JungleFence::JungleFence(true, true, false, true).ID: return 8112; case JungleFence::JungleFence(true, true, false, false).ID: return 8113; case JungleFence::JungleFence(true, false, true, true).ID: return 8116; case JungleFence::JungleFence(true, false, true, false).ID: return 8117; case JungleFence::JungleFence(true, false, false, true).ID: return 8120; case JungleFence::JungleFence(true, false, false, false).ID: return 8121; case JungleFence::JungleFence(false, true, true, true).ID: return 8124; case JungleFence::JungleFence(false, true, true, false).ID: return 8125; case JungleFence::JungleFence(false, true, false, true).ID: return 8128; case JungleFence::JungleFence(false, true, false, false).ID: return 8129; case JungleFence::JungleFence(false, false, true, true).ID: return 8132; case JungleFence::JungleFence(false, false, true, false).ID: return 8133; case JungleFence::JungleFence(false, false, false, true).ID: return 8136; case JungleFence::JungleFence(false, false, false, false).ID: return 8137; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZM, true, true, true).ID: return 7946; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZM, true, true, false).ID: return 7947; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZM, true, false, true).ID: return 7948; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZM, true, false, false).ID: return 7949; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, true).ID: return 7950; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, false).ID: return 7951; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, true).ID: return 7952; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, false).ID: return 7953; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZP, true, true, true).ID: return 7954; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZP, true, true, false).ID: return 7955; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZP, true, false, true).ID: return 7956; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZP, true, false, false).ID: return 7957; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, true).ID: return 7958; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, false).ID: return 7959; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, true).ID: return 7960; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, false).ID: return 7961; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XM, true, true, true).ID: return 7962; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XM, true, true, false).ID: return 7963; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XM, true, false, true).ID: return 7964; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XM, true, false, false).ID: return 7965; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, true).ID: return 7966; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, false).ID: return 7967; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, true).ID: return 7968; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, false).ID: return 7969; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XP, true, true, true).ID: return 7970; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XP, true, true, false).ID: return 7971; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XP, true, false, true).ID: return 7972; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XP, true, false, false).ID: return 7973; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, true).ID: return 7974; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, false).ID: return 7975; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, true).ID: return 7976; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, false).ID: return 7977; case JungleLeaves::JungleLeaves(1, true).ID: return 186; case JungleLeaves::JungleLeaves(1, false).ID: return 187; case JungleLeaves::JungleLeaves(2, true).ID: return 188; case JungleLeaves::JungleLeaves(2, false).ID: return 189; case JungleLeaves::JungleLeaves(3, true).ID: return 190; case JungleLeaves::JungleLeaves(3, false).ID: return 191; case JungleLeaves::JungleLeaves(4, true).ID: return 192; case JungleLeaves::JungleLeaves(4, false).ID: return 193; case JungleLeaves::JungleLeaves(5, true).ID: return 194; case JungleLeaves::JungleLeaves(5, false).ID: return 195; case JungleLeaves::JungleLeaves(6, true).ID: return 196; case JungleLeaves::JungleLeaves(6, false).ID: return 197; case JungleLeaves::JungleLeaves(7, true).ID: return 198; case JungleLeaves::JungleLeaves(7, false).ID: return 199; case JungleLog::JungleLog(JungleLog::Axis::X).ID: return 81; case JungleLog::JungleLog(JungleLog::Axis::Y).ID: return 82; case JungleLog::JungleLog(JungleLog::Axis::Z).ID: return 83; case JunglePlanks::JunglePlanks().ID: return 18; case JunglePressurePlate::JunglePressurePlate(true).ID: return 3877; case JunglePressurePlate::JunglePressurePlate(false).ID: return 3878; case JungleSapling::JungleSapling(0).ID: return 27; case JungleSapling::JungleSapling(1).ID: return 28; case JungleSign::JungleSign(0).ID: return 3508; case JungleSign::JungleSign(1).ID: return 3510; case JungleSign::JungleSign(2).ID: return 3512; case JungleSign::JungleSign(3).ID: return 3514; case JungleSign::JungleSign(4).ID: return 3516; case JungleSign::JungleSign(5).ID: return 3518; case JungleSign::JungleSign(6).ID: return 3520; case JungleSign::JungleSign(7).ID: return 3522; case JungleSign::JungleSign(8).ID: return 3524; case JungleSign::JungleSign(9).ID: return 3526; case JungleSign::JungleSign(10).ID: return 3528; case JungleSign::JungleSign(11).ID: return 3530; case JungleSign::JungleSign(12).ID: return 3532; case JungleSign::JungleSign(13).ID: return 3534; case JungleSign::JungleSign(14).ID: return 3536; case JungleSign::JungleSign(15).ID: return 3538; case JungleSlab::JungleSlab(JungleSlab::Type::Top).ID: return 7783; case JungleSlab::JungleSlab(JungleSlab::Type::Bottom).ID: return 7785; case JungleSlab::JungleSlab(JungleSlab::Type::Double).ID: return 7787; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZM, JungleStairs::Half::Top, JungleStairs::Shape::Straight).ID: return 5549; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZM, JungleStairs::Half::Top, JungleStairs::Shape::InnerLeft).ID: return 5551; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZM, JungleStairs::Half::Top, JungleStairs::Shape::InnerRight).ID: return 5553; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZM, JungleStairs::Half::Top, JungleStairs::Shape::OuterLeft).ID: return 5555; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZM, JungleStairs::Half::Top, JungleStairs::Shape::OuterRight).ID: return 5557; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZM, JungleStairs::Half::Bottom, JungleStairs::Shape::Straight).ID: return 5559; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZM, JungleStairs::Half::Bottom, JungleStairs::Shape::InnerLeft).ID: return 5561; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZM, JungleStairs::Half::Bottom, JungleStairs::Shape::InnerRight).ID: return 5563; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZM, JungleStairs::Half::Bottom, JungleStairs::Shape::OuterLeft).ID: return 5565; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZM, JungleStairs::Half::Bottom, JungleStairs::Shape::OuterRight).ID: return 5567; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZP, JungleStairs::Half::Top, JungleStairs::Shape::Straight).ID: return 5569; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZP, JungleStairs::Half::Top, JungleStairs::Shape::InnerLeft).ID: return 5571; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZP, JungleStairs::Half::Top, JungleStairs::Shape::InnerRight).ID: return 5573; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZP, JungleStairs::Half::Top, JungleStairs::Shape::OuterLeft).ID: return 5575; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZP, JungleStairs::Half::Top, JungleStairs::Shape::OuterRight).ID: return 5577; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZP, JungleStairs::Half::Bottom, JungleStairs::Shape::Straight).ID: return 5579; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZP, JungleStairs::Half::Bottom, JungleStairs::Shape::InnerLeft).ID: return 5581; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZP, JungleStairs::Half::Bottom, JungleStairs::Shape::InnerRight).ID: return 5583; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZP, JungleStairs::Half::Bottom, JungleStairs::Shape::OuterLeft).ID: return 5585; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZP, JungleStairs::Half::Bottom, JungleStairs::Shape::OuterRight).ID: return 5587; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XM, JungleStairs::Half::Top, JungleStairs::Shape::Straight).ID: return 5589; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XM, JungleStairs::Half::Top, JungleStairs::Shape::InnerLeft).ID: return 5591; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XM, JungleStairs::Half::Top, JungleStairs::Shape::InnerRight).ID: return 5593; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XM, JungleStairs::Half::Top, JungleStairs::Shape::OuterLeft).ID: return 5595; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XM, JungleStairs::Half::Top, JungleStairs::Shape::OuterRight).ID: return 5597; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XM, JungleStairs::Half::Bottom, JungleStairs::Shape::Straight).ID: return 5599; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XM, JungleStairs::Half::Bottom, JungleStairs::Shape::InnerLeft).ID: return 5601; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XM, JungleStairs::Half::Bottom, JungleStairs::Shape::InnerRight).ID: return 5603; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XM, JungleStairs::Half::Bottom, JungleStairs::Shape::OuterLeft).ID: return 5605; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XM, JungleStairs::Half::Bottom, JungleStairs::Shape::OuterRight).ID: return 5607; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XP, JungleStairs::Half::Top, JungleStairs::Shape::Straight).ID: return 5609; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XP, JungleStairs::Half::Top, JungleStairs::Shape::InnerLeft).ID: return 5611; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XP, JungleStairs::Half::Top, JungleStairs::Shape::InnerRight).ID: return 5613; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XP, JungleStairs::Half::Top, JungleStairs::Shape::OuterLeft).ID: return 5615; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XP, JungleStairs::Half::Top, JungleStairs::Shape::OuterRight).ID: return 5617; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XP, JungleStairs::Half::Bottom, JungleStairs::Shape::Straight).ID: return 5619; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XP, JungleStairs::Half::Bottom, JungleStairs::Shape::InnerLeft).ID: return 5621; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XP, JungleStairs::Half::Bottom, JungleStairs::Shape::InnerRight).ID: return 5623; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XP, JungleStairs::Half::Bottom, JungleStairs::Shape::OuterLeft).ID: return 5625; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XP, JungleStairs::Half::Bottom, JungleStairs::Shape::OuterRight).ID: return 5627; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZM, JungleTrapdoor::Half::Top, true, true).ID: return 4290; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZM, JungleTrapdoor::Half::Top, true, false).ID: return 4292; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZM, JungleTrapdoor::Half::Top, false, true).ID: return 4294; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZM, JungleTrapdoor::Half::Top, false, false).ID: return 4296; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZM, JungleTrapdoor::Half::Bottom, true, true).ID: return 4298; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZM, JungleTrapdoor::Half::Bottom, true, false).ID: return 4300; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZM, JungleTrapdoor::Half::Bottom, false, true).ID: return 4302; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZM, JungleTrapdoor::Half::Bottom, false, false).ID: return 4304; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZP, JungleTrapdoor::Half::Top, true, true).ID: return 4306; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZP, JungleTrapdoor::Half::Top, true, false).ID: return 4308; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZP, JungleTrapdoor::Half::Top, false, true).ID: return 4310; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZP, JungleTrapdoor::Half::Top, false, false).ID: return 4312; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZP, JungleTrapdoor::Half::Bottom, true, true).ID: return 4314; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZP, JungleTrapdoor::Half::Bottom, true, false).ID: return 4316; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZP, JungleTrapdoor::Half::Bottom, false, true).ID: return 4318; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZP, JungleTrapdoor::Half::Bottom, false, false).ID: return 4320; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XM, JungleTrapdoor::Half::Top, true, true).ID: return 4322; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XM, JungleTrapdoor::Half::Top, true, false).ID: return 4324; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XM, JungleTrapdoor::Half::Top, false, true).ID: return 4326; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XM, JungleTrapdoor::Half::Top, false, false).ID: return 4328; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XM, JungleTrapdoor::Half::Bottom, true, true).ID: return 4330; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XM, JungleTrapdoor::Half::Bottom, true, false).ID: return 4332; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XM, JungleTrapdoor::Half::Bottom, false, true).ID: return 4334; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XM, JungleTrapdoor::Half::Bottom, false, false).ID: return 4336; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XP, JungleTrapdoor::Half::Top, true, true).ID: return 4338; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XP, JungleTrapdoor::Half::Top, true, false).ID: return 4340; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XP, JungleTrapdoor::Half::Top, false, true).ID: return 4342; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XP, JungleTrapdoor::Half::Top, false, false).ID: return 4344; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XP, JungleTrapdoor::Half::Bottom, true, true).ID: return 4346; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XP, JungleTrapdoor::Half::Bottom, true, false).ID: return 4348; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XP, JungleTrapdoor::Half::Bottom, false, true).ID: return 4350; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XP, JungleTrapdoor::Half::Bottom, false, false).ID: return 4352; case JungleWallSign::JungleWallSign(eBlockFace::BLOCK_FACE_ZM).ID: return 3766; case JungleWallSign::JungleWallSign(eBlockFace::BLOCK_FACE_ZP).ID: return 3768; case JungleWallSign::JungleWallSign(eBlockFace::BLOCK_FACE_XM).ID: return 3770; case JungleWallSign::JungleWallSign(eBlockFace::BLOCK_FACE_XP).ID: return 3772; case JungleWood::JungleWood(JungleWood::Axis::X).ID: return 117; case JungleWood::JungleWood(JungleWood::Axis::Y).ID: return 118; case JungleWood::JungleWood(JungleWood::Axis::Z).ID: return 119; case Kelp::Kelp(0).ID: return 8934; case Kelp::Kelp(1).ID: return 8935; case Kelp::Kelp(2).ID: return 8936; case Kelp::Kelp(3).ID: return 8937; case Kelp::Kelp(4).ID: return 8938; case Kelp::Kelp(5).ID: return 8939; case Kelp::Kelp(6).ID: return 8940; case Kelp::Kelp(7).ID: return 8941; case Kelp::Kelp(8).ID: return 8942; case Kelp::Kelp(9).ID: return 8943; case Kelp::Kelp(10).ID: return 8944; case Kelp::Kelp(11).ID: return 8945; case Kelp::Kelp(12).ID: return 8946; case Kelp::Kelp(13).ID: return 8947; case Kelp::Kelp(14).ID: return 8948; case Kelp::Kelp(15).ID: return 8949; case Kelp::Kelp(16).ID: return 8950; case Kelp::Kelp(17).ID: return 8951; case Kelp::Kelp(18).ID: return 8952; case Kelp::Kelp(19).ID: return 8953; case Kelp::Kelp(20).ID: return 8954; case Kelp::Kelp(21).ID: return 8955; case Kelp::Kelp(22).ID: return 8956; case Kelp::Kelp(23).ID: return 8957; case Kelp::Kelp(24).ID: return 8958; case Kelp::Kelp(25).ID: return 8959; case KelpPlant::KelpPlant().ID: return 8960; case Ladder::Ladder(eBlockFace::BLOCK_FACE_ZM).ID: return 3636; case Ladder::Ladder(eBlockFace::BLOCK_FACE_ZP).ID: return 3638; case Ladder::Ladder(eBlockFace::BLOCK_FACE_XM).ID: return 3640; case Ladder::Ladder(eBlockFace::BLOCK_FACE_XP).ID: return 3642; case Lantern::Lantern(true).ID: return 11230; case Lantern::Lantern(false).ID: return 11231; case LapisBlock::LapisBlock().ID: return 232; case LapisOre::LapisOre().ID: return 231; case LargeFern::LargeFern(LargeFern::Half::Upper).ID: return 7359; case LargeFern::LargeFern(LargeFern::Half::Lower).ID: return 7360; case Lava::Lava(0).ID: return 50; case Lava::Lava(1).ID: return 51; case Lava::Lava(2).ID: return 52; case Lava::Lava(3).ID: return 53; case Lava::Lava(4).ID: return 54; case Lava::Lava(5).ID: return 55; case Lava::Lava(6).ID: return 56; case Lava::Lava(7).ID: return 57; case Lava::Lava(8).ID: return 58; case Lava::Lava(9).ID: return 59; case Lava::Lava(10).ID: return 60; case Lava::Lava(11).ID: return 61; case Lava::Lava(12).ID: return 62; case Lava::Lava(13).ID: return 63; case Lava::Lava(14).ID: return 64; case Lava::Lava(15).ID: return 65; case Lectern::Lectern(eBlockFace::BLOCK_FACE_ZM, true, true).ID: return 11177; case Lectern::Lectern(eBlockFace::BLOCK_FACE_ZM, true, false).ID: return 11178; case Lectern::Lectern(eBlockFace::BLOCK_FACE_ZM, false, true).ID: return 11179; case Lectern::Lectern(eBlockFace::BLOCK_FACE_ZM, false, false).ID: return 11180; case Lectern::Lectern(eBlockFace::BLOCK_FACE_ZP, true, true).ID: return 11181; case Lectern::Lectern(eBlockFace::BLOCK_FACE_ZP, true, false).ID: return 11182; case Lectern::Lectern(eBlockFace::BLOCK_FACE_ZP, false, true).ID: return 11183; case Lectern::Lectern(eBlockFace::BLOCK_FACE_ZP, false, false).ID: return 11184; case Lectern::Lectern(eBlockFace::BLOCK_FACE_XM, true, true).ID: return 11185; case Lectern::Lectern(eBlockFace::BLOCK_FACE_XM, true, false).ID: return 11186; case Lectern::Lectern(eBlockFace::BLOCK_FACE_XM, false, true).ID: return 11187; case Lectern::Lectern(eBlockFace::BLOCK_FACE_XM, false, false).ID: return 11188; case Lectern::Lectern(eBlockFace::BLOCK_FACE_XP, true, true).ID: return 11189; case Lectern::Lectern(eBlockFace::BLOCK_FACE_XP, true, false).ID: return 11190; case Lectern::Lectern(eBlockFace::BLOCK_FACE_XP, false, true).ID: return 11191; case Lectern::Lectern(eBlockFace::BLOCK_FACE_XP, false, false).ID: return 11192; case Lever::Lever(Lever::Face::Floor, eBlockFace::BLOCK_FACE_ZM, true).ID: return 3781; case Lever::Lever(Lever::Face::Floor, eBlockFace::BLOCK_FACE_ZM, false).ID: return 3782; case Lever::Lever(Lever::Face::Floor, eBlockFace::BLOCK_FACE_ZP, true).ID: return 3783; case Lever::Lever(Lever::Face::Floor, eBlockFace::BLOCK_FACE_ZP, false).ID: return 3784; case Lever::Lever(Lever::Face::Floor, eBlockFace::BLOCK_FACE_XM, true).ID: return 3785; case Lever::Lever(Lever::Face::Floor, eBlockFace::BLOCK_FACE_XM, false).ID: return 3786; case Lever::Lever(Lever::Face::Floor, eBlockFace::BLOCK_FACE_XP, true).ID: return 3787; case Lever::Lever(Lever::Face::Floor, eBlockFace::BLOCK_FACE_XP, false).ID: return 3788; case Lever::Lever(Lever::Face::Wall, eBlockFace::BLOCK_FACE_ZM, true).ID: return 3789; case Lever::Lever(Lever::Face::Wall, eBlockFace::BLOCK_FACE_ZM, false).ID: return 3790; case Lever::Lever(Lever::Face::Wall, eBlockFace::BLOCK_FACE_ZP, true).ID: return 3791; case Lever::Lever(Lever::Face::Wall, eBlockFace::BLOCK_FACE_ZP, false).ID: return 3792; case Lever::Lever(Lever::Face::Wall, eBlockFace::BLOCK_FACE_XM, true).ID: return 3793; case Lever::Lever(Lever::Face::Wall, eBlockFace::BLOCK_FACE_XM, false).ID: return 3794; case Lever::Lever(Lever::Face::Wall, eBlockFace::BLOCK_FACE_XP, true).ID: return 3795; case Lever::Lever(Lever::Face::Wall, eBlockFace::BLOCK_FACE_XP, false).ID: return 3796; case Lever::Lever(Lever::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, true).ID: return 3797; case Lever::Lever(Lever::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, false).ID: return 3798; case Lever::Lever(Lever::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, true).ID: return 3799; case Lever::Lever(Lever::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, false).ID: return 3800; case Lever::Lever(Lever::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, true).ID: return 3801; case Lever::Lever(Lever::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, false).ID: return 3802; case Lever::Lever(Lever::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, true).ID: return 3803; case Lever::Lever(Lever::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, false).ID: return 3804; case LightBlueBanner::LightBlueBanner(0).ID: return 7409; case LightBlueBanner::LightBlueBanner(1).ID: return 7410; case LightBlueBanner::LightBlueBanner(2).ID: return 7411; case LightBlueBanner::LightBlueBanner(3).ID: return 7412; case LightBlueBanner::LightBlueBanner(4).ID: return 7413; case LightBlueBanner::LightBlueBanner(5).ID: return 7414; case LightBlueBanner::LightBlueBanner(6).ID: return 7415; case LightBlueBanner::LightBlueBanner(7).ID: return 7416; case LightBlueBanner::LightBlueBanner(8).ID: return 7417; case LightBlueBanner::LightBlueBanner(9).ID: return 7418; case LightBlueBanner::LightBlueBanner(10).ID: return 7419; case LightBlueBanner::LightBlueBanner(11).ID: return 7420; case LightBlueBanner::LightBlueBanner(12).ID: return 7421; case LightBlueBanner::LightBlueBanner(13).ID: return 7422; case LightBlueBanner::LightBlueBanner(14).ID: return 7423; case LightBlueBanner::LightBlueBanner(15).ID: return 7424; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_ZM, true, LightBlueBed::Part::Head).ID: return 1096; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_ZM, true, LightBlueBed::Part::Foot).ID: return 1097; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_ZM, false, LightBlueBed::Part::Head).ID: return 1098; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_ZM, false, LightBlueBed::Part::Foot).ID: return 1099; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_ZP, true, LightBlueBed::Part::Head).ID: return 1100; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_ZP, true, LightBlueBed::Part::Foot).ID: return 1101; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_ZP, false, LightBlueBed::Part::Head).ID: return 1102; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_ZP, false, LightBlueBed::Part::Foot).ID: return 1103; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_XM, true, LightBlueBed::Part::Head).ID: return 1104; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_XM, true, LightBlueBed::Part::Foot).ID: return 1105; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_XM, false, LightBlueBed::Part::Head).ID: return 1106; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_XM, false, LightBlueBed::Part::Foot).ID: return 1107; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_XP, true, LightBlueBed::Part::Head).ID: return 1108; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_XP, true, LightBlueBed::Part::Foot).ID: return 1109; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_XP, false, LightBlueBed::Part::Head).ID: return 1110; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_XP, false, LightBlueBed::Part::Foot).ID: return 1111; case LightBlueCarpet::LightBlueCarpet().ID: return 7333; case LightBlueConcrete::LightBlueConcrete().ID: return 8905; case LightBlueConcretePowder::LightBlueConcretePowder().ID: return 8921; case LightBlueGlazedTerracotta::LightBlueGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 8850; case LightBlueGlazedTerracotta::LightBlueGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 8851; case LightBlueGlazedTerracotta::LightBlueGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 8852; case LightBlueGlazedTerracotta::LightBlueGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 8853; case LightBlueShulkerBox::LightBlueShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 8760; case LightBlueShulkerBox::LightBlueShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 8761; case LightBlueShulkerBox::LightBlueShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 8762; case LightBlueShulkerBox::LightBlueShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 8763; case LightBlueShulkerBox::LightBlueShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 8764; case LightBlueShulkerBox::LightBlueShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 8765; case LightBlueStainedGlass::LightBlueStainedGlass().ID: return 4084; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(true, true, true, true).ID: return 6425; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(true, true, true, false).ID: return 6426; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(true, true, false, true).ID: return 6429; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(true, true, false, false).ID: return 6430; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(true, false, true, true).ID: return 6433; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(true, false, true, false).ID: return 6434; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(true, false, false, true).ID: return 6437; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(true, false, false, false).ID: return 6438; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(false, true, true, true).ID: return 6441; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(false, true, true, false).ID: return 6442; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(false, true, false, true).ID: return 6445; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(false, true, false, false).ID: return 6446; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(false, false, true, true).ID: return 6449; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(false, false, true, false).ID: return 6450; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(false, false, false, true).ID: return 6453; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(false, false, false, false).ID: return 6454; case LightBlueTerracotta::LightBlueTerracotta().ID: return 6314; case LightBlueWallBanner::LightBlueWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 7629; case LightBlueWallBanner::LightBlueWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 7630; case LightBlueWallBanner::LightBlueWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 7631; case LightBlueWallBanner::LightBlueWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 7632; case LightBlueWool::LightBlueWool().ID: return 1386; case LightGrayBanner::LightGrayBanner(0).ID: return 7489; case LightGrayBanner::LightGrayBanner(1).ID: return 7490; case LightGrayBanner::LightGrayBanner(2).ID: return 7491; case LightGrayBanner::LightGrayBanner(3).ID: return 7492; case LightGrayBanner::LightGrayBanner(4).ID: return 7493; case LightGrayBanner::LightGrayBanner(5).ID: return 7494; case LightGrayBanner::LightGrayBanner(6).ID: return 7495; case LightGrayBanner::LightGrayBanner(7).ID: return 7496; case LightGrayBanner::LightGrayBanner(8).ID: return 7497; case LightGrayBanner::LightGrayBanner(9).ID: return 7498; case LightGrayBanner::LightGrayBanner(10).ID: return 7499; case LightGrayBanner::LightGrayBanner(11).ID: return 7500; case LightGrayBanner::LightGrayBanner(12).ID: return 7501; case LightGrayBanner::LightGrayBanner(13).ID: return 7502; case LightGrayBanner::LightGrayBanner(14).ID: return 7503; case LightGrayBanner::LightGrayBanner(15).ID: return 7504; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_ZM, true, LightGrayBed::Part::Head).ID: return 1176; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_ZM, true, LightGrayBed::Part::Foot).ID: return 1177; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_ZM, false, LightGrayBed::Part::Head).ID: return 1178; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_ZM, false, LightGrayBed::Part::Foot).ID: return 1179; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_ZP, true, LightGrayBed::Part::Head).ID: return 1180; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_ZP, true, LightGrayBed::Part::Foot).ID: return 1181; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_ZP, false, LightGrayBed::Part::Head).ID: return 1182; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_ZP, false, LightGrayBed::Part::Foot).ID: return 1183; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_XM, true, LightGrayBed::Part::Head).ID: return 1184; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_XM, true, LightGrayBed::Part::Foot).ID: return 1185; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_XM, false, LightGrayBed::Part::Head).ID: return 1186; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_XM, false, LightGrayBed::Part::Foot).ID: return 1187; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_XP, true, LightGrayBed::Part::Head).ID: return 1188; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_XP, true, LightGrayBed::Part::Foot).ID: return 1189; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_XP, false, LightGrayBed::Part::Head).ID: return 1190; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_XP, false, LightGrayBed::Part::Foot).ID: return 1191; case LightGrayCarpet::LightGrayCarpet().ID: return 7338; case LightGrayConcrete::LightGrayConcrete().ID: return 8910; case LightGrayConcretePowder::LightGrayConcretePowder().ID: return 8926; case LightGrayGlazedTerracotta::LightGrayGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 8870; case LightGrayGlazedTerracotta::LightGrayGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 8871; case LightGrayGlazedTerracotta::LightGrayGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 8872; case LightGrayGlazedTerracotta::LightGrayGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 8873; case LightGrayShulkerBox::LightGrayShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 8790; case LightGrayShulkerBox::LightGrayShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 8791; case LightGrayShulkerBox::LightGrayShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 8792; case LightGrayShulkerBox::LightGrayShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 8793; case LightGrayShulkerBox::LightGrayShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 8794; case LightGrayShulkerBox::LightGrayShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 8795; case LightGrayStainedGlass::LightGrayStainedGlass().ID: return 4089; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(true, true, true, true).ID: return 6585; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(true, true, true, false).ID: return 6586; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(true, true, false, true).ID: return 6589; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(true, true, false, false).ID: return 6590; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(true, false, true, true).ID: return 6593; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(true, false, true, false).ID: return 6594; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(true, false, false, true).ID: return 6597; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(true, false, false, false).ID: return 6598; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(false, true, true, true).ID: return 6601; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(false, true, true, false).ID: return 6602; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(false, true, false, true).ID: return 6605; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(false, true, false, false).ID: return 6606; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(false, false, true, true).ID: return 6609; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(false, false, true, false).ID: return 6610; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(false, false, false, true).ID: return 6613; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(false, false, false, false).ID: return 6614; case LightGrayTerracotta::LightGrayTerracotta().ID: return 6319; case LightGrayWallBanner::LightGrayWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 7649; case LightGrayWallBanner::LightGrayWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 7650; case LightGrayWallBanner::LightGrayWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 7651; case LightGrayWallBanner::LightGrayWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 7652; case LightGrayWool::LightGrayWool().ID: return 1391; case LightWeightedPressurePlate::LightWeightedPressurePlate(0).ID: return 6110; case LightWeightedPressurePlate::LightWeightedPressurePlate(1).ID: return 6111; case LightWeightedPressurePlate::LightWeightedPressurePlate(2).ID: return 6112; case LightWeightedPressurePlate::LightWeightedPressurePlate(3).ID: return 6113; case LightWeightedPressurePlate::LightWeightedPressurePlate(4).ID: return 6114; case LightWeightedPressurePlate::LightWeightedPressurePlate(5).ID: return 6115; case LightWeightedPressurePlate::LightWeightedPressurePlate(6).ID: return 6116; case LightWeightedPressurePlate::LightWeightedPressurePlate(7).ID: return 6117; case LightWeightedPressurePlate::LightWeightedPressurePlate(8).ID: return 6118; case LightWeightedPressurePlate::LightWeightedPressurePlate(9).ID: return 6119; case LightWeightedPressurePlate::LightWeightedPressurePlate(10).ID: return 6120; case LightWeightedPressurePlate::LightWeightedPressurePlate(11).ID: return 6121; case LightWeightedPressurePlate::LightWeightedPressurePlate(12).ID: return 6122; case LightWeightedPressurePlate::LightWeightedPressurePlate(13).ID: return 6123; case LightWeightedPressurePlate::LightWeightedPressurePlate(14).ID: return 6124; case LightWeightedPressurePlate::LightWeightedPressurePlate(15).ID: return 6125; case Lilac::Lilac(Lilac::Half::Upper).ID: return 7351; case Lilac::Lilac(Lilac::Half::Lower).ID: return 7352; case LilyOfTheValley::LilyOfTheValley().ID: return 1423; case LilyPad::LilyPad().ID: return 4998; case LimeBanner::LimeBanner(0).ID: return 7441; case LimeBanner::LimeBanner(1).ID: return 7442; case LimeBanner::LimeBanner(2).ID: return 7443; case LimeBanner::LimeBanner(3).ID: return 7444; case LimeBanner::LimeBanner(4).ID: return 7445; case LimeBanner::LimeBanner(5).ID: return 7446; case LimeBanner::LimeBanner(6).ID: return 7447; case LimeBanner::LimeBanner(7).ID: return 7448; case LimeBanner::LimeBanner(8).ID: return 7449; case LimeBanner::LimeBanner(9).ID: return 7450; case LimeBanner::LimeBanner(10).ID: return 7451; case LimeBanner::LimeBanner(11).ID: return 7452; case LimeBanner::LimeBanner(12).ID: return 7453; case LimeBanner::LimeBanner(13).ID: return 7454; case LimeBanner::LimeBanner(14).ID: return 7455; case LimeBanner::LimeBanner(15).ID: return 7456; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_ZM, true, LimeBed::Part::Head).ID: return 1128; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_ZM, true, LimeBed::Part::Foot).ID: return 1129; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_ZM, false, LimeBed::Part::Head).ID: return 1130; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_ZM, false, LimeBed::Part::Foot).ID: return 1131; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_ZP, true, LimeBed::Part::Head).ID: return 1132; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_ZP, true, LimeBed::Part::Foot).ID: return 1133; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_ZP, false, LimeBed::Part::Head).ID: return 1134; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_ZP, false, LimeBed::Part::Foot).ID: return 1135; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_XM, true, LimeBed::Part::Head).ID: return 1136; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_XM, true, LimeBed::Part::Foot).ID: return 1137; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_XM, false, LimeBed::Part::Head).ID: return 1138; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_XM, false, LimeBed::Part::Foot).ID: return 1139; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_XP, true, LimeBed::Part::Head).ID: return 1140; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_XP, true, LimeBed::Part::Foot).ID: return 1141; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_XP, false, LimeBed::Part::Head).ID: return 1142; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_XP, false, LimeBed::Part::Foot).ID: return 1143; case LimeCarpet::LimeCarpet().ID: return 7335; case LimeConcrete::LimeConcrete().ID: return 8907; case LimeConcretePowder::LimeConcretePowder().ID: return 8923; case LimeGlazedTerracotta::LimeGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 8858; case LimeGlazedTerracotta::LimeGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 8859; case LimeGlazedTerracotta::LimeGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 8860; case LimeGlazedTerracotta::LimeGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 8861; case LimeShulkerBox::LimeShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 8772; case LimeShulkerBox::LimeShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 8773; case LimeShulkerBox::LimeShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 8774; case LimeShulkerBox::LimeShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 8775; case LimeShulkerBox::LimeShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 8776; case LimeShulkerBox::LimeShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 8777; case LimeStainedGlass::LimeStainedGlass().ID: return 4086; case LimeStainedGlassPane::LimeStainedGlassPane(true, true, true, true).ID: return 6489; case LimeStainedGlassPane::LimeStainedGlassPane(true, true, true, false).ID: return 6490; case LimeStainedGlassPane::LimeStainedGlassPane(true, true, false, true).ID: return 6493; case LimeStainedGlassPane::LimeStainedGlassPane(true, true, false, false).ID: return 6494; case LimeStainedGlassPane::LimeStainedGlassPane(true, false, true, true).ID: return 6497; case LimeStainedGlassPane::LimeStainedGlassPane(true, false, true, false).ID: return 6498; case LimeStainedGlassPane::LimeStainedGlassPane(true, false, false, true).ID: return 6501; case LimeStainedGlassPane::LimeStainedGlassPane(true, false, false, false).ID: return 6502; case LimeStainedGlassPane::LimeStainedGlassPane(false, true, true, true).ID: return 6505; case LimeStainedGlassPane::LimeStainedGlassPane(false, true, true, false).ID: return 6506; case LimeStainedGlassPane::LimeStainedGlassPane(false, true, false, true).ID: return 6509; case LimeStainedGlassPane::LimeStainedGlassPane(false, true, false, false).ID: return 6510; case LimeStainedGlassPane::LimeStainedGlassPane(false, false, true, true).ID: return 6513; case LimeStainedGlassPane::LimeStainedGlassPane(false, false, true, false).ID: return 6514; case LimeStainedGlassPane::LimeStainedGlassPane(false, false, false, true).ID: return 6517; case LimeStainedGlassPane::LimeStainedGlassPane(false, false, false, false).ID: return 6518; case LimeTerracotta::LimeTerracotta().ID: return 6316; case LimeWallBanner::LimeWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 7637; case LimeWallBanner::LimeWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 7638; case LimeWallBanner::LimeWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 7639; case LimeWallBanner::LimeWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 7640; case LimeWool::LimeWool().ID: return 1388; case Loom::Loom(eBlockFace::BLOCK_FACE_ZM).ID: return 11131; case Loom::Loom(eBlockFace::BLOCK_FACE_ZP).ID: return 11132; case Loom::Loom(eBlockFace::BLOCK_FACE_XM).ID: return 11133; case Loom::Loom(eBlockFace::BLOCK_FACE_XP).ID: return 11134; case MagentaBanner::MagentaBanner(0).ID: return 7393; case MagentaBanner::MagentaBanner(1).ID: return 7394; case MagentaBanner::MagentaBanner(2).ID: return 7395; case MagentaBanner::MagentaBanner(3).ID: return 7396; case MagentaBanner::MagentaBanner(4).ID: return 7397; case MagentaBanner::MagentaBanner(5).ID: return 7398; case MagentaBanner::MagentaBanner(6).ID: return 7399; case MagentaBanner::MagentaBanner(7).ID: return 7400; case MagentaBanner::MagentaBanner(8).ID: return 7401; case MagentaBanner::MagentaBanner(9).ID: return 7402; case MagentaBanner::MagentaBanner(10).ID: return 7403; case MagentaBanner::MagentaBanner(11).ID: return 7404; case MagentaBanner::MagentaBanner(12).ID: return 7405; case MagentaBanner::MagentaBanner(13).ID: return 7406; case MagentaBanner::MagentaBanner(14).ID: return 7407; case MagentaBanner::MagentaBanner(15).ID: return 7408; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_ZM, true, MagentaBed::Part::Head).ID: return 1080; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_ZM, true, MagentaBed::Part::Foot).ID: return 1081; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_ZM, false, MagentaBed::Part::Head).ID: return 1082; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_ZM, false, MagentaBed::Part::Foot).ID: return 1083; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_ZP, true, MagentaBed::Part::Head).ID: return 1084; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_ZP, true, MagentaBed::Part::Foot).ID: return 1085; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_ZP, false, MagentaBed::Part::Head).ID: return 1086; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_ZP, false, MagentaBed::Part::Foot).ID: return 1087; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_XM, true, MagentaBed::Part::Head).ID: return 1088; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_XM, true, MagentaBed::Part::Foot).ID: return 1089; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_XM, false, MagentaBed::Part::Head).ID: return 1090; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_XM, false, MagentaBed::Part::Foot).ID: return 1091; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_XP, true, MagentaBed::Part::Head).ID: return 1092; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_XP, true, MagentaBed::Part::Foot).ID: return 1093; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_XP, false, MagentaBed::Part::Head).ID: return 1094; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_XP, false, MagentaBed::Part::Foot).ID: return 1095; case MagentaCarpet::MagentaCarpet().ID: return 7332; case MagentaConcrete::MagentaConcrete().ID: return 8904; case MagentaConcretePowder::MagentaConcretePowder().ID: return 8920; case MagentaGlazedTerracotta::MagentaGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 8846; case MagentaGlazedTerracotta::MagentaGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 8847; case MagentaGlazedTerracotta::MagentaGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 8848; case MagentaGlazedTerracotta::MagentaGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 8849; case MagentaShulkerBox::MagentaShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 8754; case MagentaShulkerBox::MagentaShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 8755; case MagentaShulkerBox::MagentaShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 8756; case MagentaShulkerBox::MagentaShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 8757; case MagentaShulkerBox::MagentaShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 8758; case MagentaShulkerBox::MagentaShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 8759; case MagentaStainedGlass::MagentaStainedGlass().ID: return 4083; case MagentaStainedGlassPane::MagentaStainedGlassPane(true, true, true, true).ID: return 6393; case MagentaStainedGlassPane::MagentaStainedGlassPane(true, true, true, false).ID: return 6394; case MagentaStainedGlassPane::MagentaStainedGlassPane(true, true, false, true).ID: return 6397; case MagentaStainedGlassPane::MagentaStainedGlassPane(true, true, false, false).ID: return 6398; case MagentaStainedGlassPane::MagentaStainedGlassPane(true, false, true, true).ID: return 6401; case MagentaStainedGlassPane::MagentaStainedGlassPane(true, false, true, false).ID: return 6402; case MagentaStainedGlassPane::MagentaStainedGlassPane(true, false, false, true).ID: return 6405; case MagentaStainedGlassPane::MagentaStainedGlassPane(true, false, false, false).ID: return 6406; case MagentaStainedGlassPane::MagentaStainedGlassPane(false, true, true, true).ID: return 6409; case MagentaStainedGlassPane::MagentaStainedGlassPane(false, true, true, false).ID: return 6410; case MagentaStainedGlassPane::MagentaStainedGlassPane(false, true, false, true).ID: return 6413; case MagentaStainedGlassPane::MagentaStainedGlassPane(false, true, false, false).ID: return 6414; case MagentaStainedGlassPane::MagentaStainedGlassPane(false, false, true, true).ID: return 6417; case MagentaStainedGlassPane::MagentaStainedGlassPane(false, false, true, false).ID: return 6418; case MagentaStainedGlassPane::MagentaStainedGlassPane(false, false, false, true).ID: return 6421; case MagentaStainedGlassPane::MagentaStainedGlassPane(false, false, false, false).ID: return 6422; case MagentaTerracotta::MagentaTerracotta().ID: return 6313; case MagentaWallBanner::MagentaWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 7625; case MagentaWallBanner::MagentaWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 7626; case MagentaWallBanner::MagentaWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 7627; case MagentaWallBanner::MagentaWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 7628; case MagentaWool::MagentaWool().ID: return 1385; case MagmaBlock::MagmaBlock().ID: return 8717; case Melon::Melon().ID: return 4747; case MelonStem::MelonStem(0).ID: return 4764; case MelonStem::MelonStem(1).ID: return 4765; case MelonStem::MelonStem(2).ID: return 4766; case MelonStem::MelonStem(3).ID: return 4767; case MelonStem::MelonStem(4).ID: return 4768; case MelonStem::MelonStem(5).ID: return 4769; case MelonStem::MelonStem(6).ID: return 4770; case MelonStem::MelonStem(7).ID: return 4771; case MossyCobblestone::MossyCobblestone().ID: return 1432; case MossyCobblestoneSlab::MossyCobblestoneSlab(MossyCobblestoneSlab::Type::Top).ID: return 10278; case MossyCobblestoneSlab::MossyCobblestoneSlab(MossyCobblestoneSlab::Type::Bottom).ID: return 10280; case MossyCobblestoneSlab::MossyCobblestoneSlab(MossyCobblestoneSlab::Type::Double).ID: return 10282; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, MossyCobblestoneStairs::Half::Top, MossyCobblestoneStairs::Shape::Straight).ID: return 9454; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, MossyCobblestoneStairs::Half::Top, MossyCobblestoneStairs::Shape::InnerLeft).ID: return 9456; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, MossyCobblestoneStairs::Half::Top, MossyCobblestoneStairs::Shape::InnerRight).ID: return 9458; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, MossyCobblestoneStairs::Half::Top, MossyCobblestoneStairs::Shape::OuterLeft).ID: return 9460; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, MossyCobblestoneStairs::Half::Top, MossyCobblestoneStairs::Shape::OuterRight).ID: return 9462; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, MossyCobblestoneStairs::Half::Bottom, MossyCobblestoneStairs::Shape::Straight).ID: return 9464; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, MossyCobblestoneStairs::Half::Bottom, MossyCobblestoneStairs::Shape::InnerLeft).ID: return 9466; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, MossyCobblestoneStairs::Half::Bottom, MossyCobblestoneStairs::Shape::InnerRight).ID: return 9468; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, MossyCobblestoneStairs::Half::Bottom, MossyCobblestoneStairs::Shape::OuterLeft).ID: return 9470; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, MossyCobblestoneStairs::Half::Bottom, MossyCobblestoneStairs::Shape::OuterRight).ID: return 9472; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, MossyCobblestoneStairs::Half::Top, MossyCobblestoneStairs::Shape::Straight).ID: return 9474; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, MossyCobblestoneStairs::Half::Top, MossyCobblestoneStairs::Shape::InnerLeft).ID: return 9476; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, MossyCobblestoneStairs::Half::Top, MossyCobblestoneStairs::Shape::InnerRight).ID: return 9478; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, MossyCobblestoneStairs::Half::Top, MossyCobblestoneStairs::Shape::OuterLeft).ID: return 9480; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, MossyCobblestoneStairs::Half::Top, MossyCobblestoneStairs::Shape::OuterRight).ID: return 9482; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, MossyCobblestoneStairs::Half::Bottom, MossyCobblestoneStairs::Shape::Straight).ID: return 9484; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, MossyCobblestoneStairs::Half::Bottom, MossyCobblestoneStairs::Shape::InnerLeft).ID: return 9486; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, MossyCobblestoneStairs::Half::Bottom, MossyCobblestoneStairs::Shape::InnerRight).ID: return 9488; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, MossyCobblestoneStairs::Half::Bottom, MossyCobblestoneStairs::Shape::OuterLeft).ID: return 9490; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, MossyCobblestoneStairs::Half::Bottom, MossyCobblestoneStairs::Shape::OuterRight).ID: return 9492; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_XM, MossyCobblestoneStairs::Half::Top, MossyCobblestoneStairs::Shape::Straight).ID: return 9494; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_XM, MossyCobblestoneStairs::Half::Top, MossyCobblestoneStairs::Shape::InnerLeft).ID: return 9496; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_XM, MossyCobblestoneStairs::Half::Top, MossyCobblestoneStairs::Shape::InnerRight).ID: return 9498; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_XM, MossyCobblestoneStairs::Half::Top, MossyCobblestoneStairs::Shape::OuterLeft).ID: return 9500; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_XM, MossyCobblestoneStairs::Half::Top, MossyCobblestoneStairs::Shape::OuterRight).ID: return 9502; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_XM, MossyCobblestoneStairs::Half::Bottom, MossyCobblestoneStairs::Shape::Straight).ID: return 9504; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_XM, MossyCobblestoneStairs::Half::Bottom, MossyCobblestoneStairs::Shape::InnerLeft).ID: return 9506; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_XM, MossyCobblestoneStairs::Half::Bottom, MossyCobblestoneStairs::Shape::InnerRight).ID: return 9508; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_XM, MossyCobblestoneStairs::Half::Bottom, MossyCobblestoneStairs::Shape::OuterLeft).ID: return 9510; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_XM, MossyCobblestoneStairs::Half::Bottom, MossyCobblestoneStairs::Shape::OuterRight).ID: return 9512; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_XP, MossyCobblestoneStairs::Half::Top, MossyCobblestoneStairs::Shape::Straight).ID: return 9514; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_XP, MossyCobblestoneStairs::Half::Top, MossyCobblestoneStairs::Shape::InnerLeft).ID: return 9516; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_XP, MossyCobblestoneStairs::Half::Top, MossyCobblestoneStairs::Shape::InnerRight).ID: return 9518; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_XP, MossyCobblestoneStairs::Half::Top, MossyCobblestoneStairs::Shape::OuterLeft).ID: return 9520; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_XP, MossyCobblestoneStairs::Half::Top, MossyCobblestoneStairs::Shape::OuterRight).ID: return 9522; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_XP, MossyCobblestoneStairs::Half::Bottom, MossyCobblestoneStairs::Shape::Straight).ID: return 9524; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_XP, MossyCobblestoneStairs::Half::Bottom, MossyCobblestoneStairs::Shape::InnerLeft).ID: return 9526; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_XP, MossyCobblestoneStairs::Half::Bottom, MossyCobblestoneStairs::Shape::InnerRight).ID: return 9528; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_XP, MossyCobblestoneStairs::Half::Bottom, MossyCobblestoneStairs::Shape::OuterLeft).ID: return 9530; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_XP, MossyCobblestoneStairs::Half::Bottom, MossyCobblestoneStairs::Shape::OuterRight).ID: return 9532; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::Low, true, MossyCobblestoneWall::West::Low).ID: return 5707; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::Low, true, MossyCobblestoneWall::West::None).ID: return 5708; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::Low, false, MossyCobblestoneWall::West::Low).ID: return 5711; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::Low, false, MossyCobblestoneWall::West::None).ID: return 5712; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::None, true, MossyCobblestoneWall::West::Low).ID: return 5715; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::None, true, MossyCobblestoneWall::West::None).ID: return 5716; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::None, false, MossyCobblestoneWall::West::Low).ID: return 5719; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::None, false, MossyCobblestoneWall::West::None).ID: return 5720; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::Low, true, MossyCobblestoneWall::West::Low).ID: return 5723; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::Low, true, MossyCobblestoneWall::West::None).ID: return 5724; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::Low, false, MossyCobblestoneWall::West::Low).ID: return 5727; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::Low, false, MossyCobblestoneWall::West::None).ID: return 5728; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::None, true, MossyCobblestoneWall::West::Low).ID: return 5731; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::None, true, MossyCobblestoneWall::West::None).ID: return 5732; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::None, false, MossyCobblestoneWall::West::Low).ID: return 5735; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::None, false, MossyCobblestoneWall::West::None).ID: return 5736; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::Low, true, MossyCobblestoneWall::West::Low).ID: return 5739; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::Low, true, MossyCobblestoneWall::West::None).ID: return 5740; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::Low, false, MossyCobblestoneWall::West::Low).ID: return 5743; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::Low, false, MossyCobblestoneWall::West::None).ID: return 5744; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::None, true, MossyCobblestoneWall::West::Low).ID: return 5747; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::None, true, MossyCobblestoneWall::West::None).ID: return 5748; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::None, false, MossyCobblestoneWall::West::Low).ID: return 5751; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::None, false, MossyCobblestoneWall::West::None).ID: return 5752; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::Low, true, MossyCobblestoneWall::West::Low).ID: return 5755; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::Low, true, MossyCobblestoneWall::West::None).ID: return 5756; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::Low, false, MossyCobblestoneWall::West::Low).ID: return 5759; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::Low, false, MossyCobblestoneWall::West::None).ID: return 5760; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::None, true, MossyCobblestoneWall::West::Low).ID: return 5763; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::None, true, MossyCobblestoneWall::West::None).ID: return 5764; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::None, false, MossyCobblestoneWall::West::Low).ID: return 5767; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::None, false, MossyCobblestoneWall::West::None).ID: return 5768; case MossyStoneBrickSlab::MossyStoneBrickSlab(MossyStoneBrickSlab::Type::Top).ID: return 10266; case MossyStoneBrickSlab::MossyStoneBrickSlab(MossyStoneBrickSlab::Type::Bottom).ID: return 10268; case MossyStoneBrickSlab::MossyStoneBrickSlab(MossyStoneBrickSlab::Type::Double).ID: return 10270; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, MossyStoneBrickStairs::Half::Top, MossyStoneBrickStairs::Shape::Straight).ID: return 9294; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, MossyStoneBrickStairs::Half::Top, MossyStoneBrickStairs::Shape::InnerLeft).ID: return 9296; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, MossyStoneBrickStairs::Half::Top, MossyStoneBrickStairs::Shape::InnerRight).ID: return 9298; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, MossyStoneBrickStairs::Half::Top, MossyStoneBrickStairs::Shape::OuterLeft).ID: return 9300; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, MossyStoneBrickStairs::Half::Top, MossyStoneBrickStairs::Shape::OuterRight).ID: return 9302; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, MossyStoneBrickStairs::Half::Bottom, MossyStoneBrickStairs::Shape::Straight).ID: return 9304; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, MossyStoneBrickStairs::Half::Bottom, MossyStoneBrickStairs::Shape::InnerLeft).ID: return 9306; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, MossyStoneBrickStairs::Half::Bottom, MossyStoneBrickStairs::Shape::InnerRight).ID: return 9308; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, MossyStoneBrickStairs::Half::Bottom, MossyStoneBrickStairs::Shape::OuterLeft).ID: return 9310; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, MossyStoneBrickStairs::Half::Bottom, MossyStoneBrickStairs::Shape::OuterRight).ID: return 9312; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, MossyStoneBrickStairs::Half::Top, MossyStoneBrickStairs::Shape::Straight).ID: return 9314; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, MossyStoneBrickStairs::Half::Top, MossyStoneBrickStairs::Shape::InnerLeft).ID: return 9316; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, MossyStoneBrickStairs::Half::Top, MossyStoneBrickStairs::Shape::InnerRight).ID: return 9318; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, MossyStoneBrickStairs::Half::Top, MossyStoneBrickStairs::Shape::OuterLeft).ID: return 9320; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, MossyStoneBrickStairs::Half::Top, MossyStoneBrickStairs::Shape::OuterRight).ID: return 9322; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, MossyStoneBrickStairs::Half::Bottom, MossyStoneBrickStairs::Shape::Straight).ID: return 9324; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, MossyStoneBrickStairs::Half::Bottom, MossyStoneBrickStairs::Shape::InnerLeft).ID: return 9326; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, MossyStoneBrickStairs::Half::Bottom, MossyStoneBrickStairs::Shape::InnerRight).ID: return 9328; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, MossyStoneBrickStairs::Half::Bottom, MossyStoneBrickStairs::Shape::OuterLeft).ID: return 9330; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, MossyStoneBrickStairs::Half::Bottom, MossyStoneBrickStairs::Shape::OuterRight).ID: return 9332; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_XM, MossyStoneBrickStairs::Half::Top, MossyStoneBrickStairs::Shape::Straight).ID: return 9334; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_XM, MossyStoneBrickStairs::Half::Top, MossyStoneBrickStairs::Shape::InnerLeft).ID: return 9336; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_XM, MossyStoneBrickStairs::Half::Top, MossyStoneBrickStairs::Shape::InnerRight).ID: return 9338; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_XM, MossyStoneBrickStairs::Half::Top, MossyStoneBrickStairs::Shape::OuterLeft).ID: return 9340; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_XM, MossyStoneBrickStairs::Half::Top, MossyStoneBrickStairs::Shape::OuterRight).ID: return 9342; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_XM, MossyStoneBrickStairs::Half::Bottom, MossyStoneBrickStairs::Shape::Straight).ID: return 9344; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_XM, MossyStoneBrickStairs::Half::Bottom, MossyStoneBrickStairs::Shape::InnerLeft).ID: return 9346; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_XM, MossyStoneBrickStairs::Half::Bottom, MossyStoneBrickStairs::Shape::InnerRight).ID: return 9348; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_XM, MossyStoneBrickStairs::Half::Bottom, MossyStoneBrickStairs::Shape::OuterLeft).ID: return 9350; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_XM, MossyStoneBrickStairs::Half::Bottom, MossyStoneBrickStairs::Shape::OuterRight).ID: return 9352; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_XP, MossyStoneBrickStairs::Half::Top, MossyStoneBrickStairs::Shape::Straight).ID: return 9354; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_XP, MossyStoneBrickStairs::Half::Top, MossyStoneBrickStairs::Shape::InnerLeft).ID: return 9356; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_XP, MossyStoneBrickStairs::Half::Top, MossyStoneBrickStairs::Shape::InnerRight).ID: return 9358; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_XP, MossyStoneBrickStairs::Half::Top, MossyStoneBrickStairs::Shape::OuterLeft).ID: return 9360; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_XP, MossyStoneBrickStairs::Half::Top, MossyStoneBrickStairs::Shape::OuterRight).ID: return 9362; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_XP, MossyStoneBrickStairs::Half::Bottom, MossyStoneBrickStairs::Shape::Straight).ID: return 9364; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_XP, MossyStoneBrickStairs::Half::Bottom, MossyStoneBrickStairs::Shape::InnerLeft).ID: return 9366; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_XP, MossyStoneBrickStairs::Half::Bottom, MossyStoneBrickStairs::Shape::InnerRight).ID: return 9368; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_XP, MossyStoneBrickStairs::Half::Bottom, MossyStoneBrickStairs::Shape::OuterLeft).ID: return 9370; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_XP, MossyStoneBrickStairs::Half::Bottom, MossyStoneBrickStairs::Shape::OuterRight).ID: return 9372; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::Low, true, MossyStoneBrickWall::West::Low).ID: return 10525; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::Low, true, MossyStoneBrickWall::West::None).ID: return 10526; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::Low, false, MossyStoneBrickWall::West::Low).ID: return 10529; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::Low, false, MossyStoneBrickWall::West::None).ID: return 10530; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::None, true, MossyStoneBrickWall::West::Low).ID: return 10533; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::None, true, MossyStoneBrickWall::West::None).ID: return 10534; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::None, false, MossyStoneBrickWall::West::Low).ID: return 10537; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::None, false, MossyStoneBrickWall::West::None).ID: return 10538; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::Low, true, MossyStoneBrickWall::West::Low).ID: return 10541; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::Low, true, MossyStoneBrickWall::West::None).ID: return 10542; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::Low, false, MossyStoneBrickWall::West::Low).ID: return 10545; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::Low, false, MossyStoneBrickWall::West::None).ID: return 10546; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::None, true, MossyStoneBrickWall::West::Low).ID: return 10549; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::None, true, MossyStoneBrickWall::West::None).ID: return 10550; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::None, false, MossyStoneBrickWall::West::Low).ID: return 10553; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::None, false, MossyStoneBrickWall::West::None).ID: return 10554; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::Low, true, MossyStoneBrickWall::West::Low).ID: return 10557; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::Low, true, MossyStoneBrickWall::West::None).ID: return 10558; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::Low, false, MossyStoneBrickWall::West::Low).ID: return 10561; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::Low, false, MossyStoneBrickWall::West::None).ID: return 10562; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::None, true, MossyStoneBrickWall::West::Low).ID: return 10565; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::None, true, MossyStoneBrickWall::West::None).ID: return 10566; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::None, false, MossyStoneBrickWall::West::Low).ID: return 10569; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::None, false, MossyStoneBrickWall::West::None).ID: return 10570; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::Low, true, MossyStoneBrickWall::West::Low).ID: return 10573; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::Low, true, MossyStoneBrickWall::West::None).ID: return 10574; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::Low, false, MossyStoneBrickWall::West::Low).ID: return 10577; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::Low, false, MossyStoneBrickWall::West::None).ID: return 10578; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::None, true, MossyStoneBrickWall::West::Low).ID: return 10581; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::None, true, MossyStoneBrickWall::West::None).ID: return 10582; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::None, false, MossyStoneBrickWall::West::Low).ID: return 10585; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::None, false, MossyStoneBrickWall::West::None).ID: return 10586; case MossyStoneBricks::MossyStoneBricks().ID: return 4482; case MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_ZM, MovingPiston::Type::Normal).ID: return 1399; case MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_ZM, MovingPiston::Type::Sticky).ID: return 1400; case MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_XP, MovingPiston::Type::Normal).ID: return 1401; case MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_XP, MovingPiston::Type::Sticky).ID: return 1402; case MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_ZP, MovingPiston::Type::Normal).ID: return 1403; case MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_ZP, MovingPiston::Type::Sticky).ID: return 1404; case MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_XM, MovingPiston::Type::Normal).ID: return 1405; case MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_XM, MovingPiston::Type::Sticky).ID: return 1406; case MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_YP, MovingPiston::Type::Normal).ID: return 1407; case MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_YP, MovingPiston::Type::Sticky).ID: return 1408; case MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_YM, MovingPiston::Type::Normal).ID: return 1409; case MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_YM, MovingPiston::Type::Sticky).ID: return 1410; case MushroomStem::MushroomStem(true, true, true, true, true, true).ID: return 4619; case MushroomStem::MushroomStem(true, true, true, true, true, false).ID: return 4620; case MushroomStem::MushroomStem(true, true, true, true, false, true).ID: return 4621; case MushroomStem::MushroomStem(true, true, true, true, false, false).ID: return 4622; case MushroomStem::MushroomStem(true, true, true, false, true, true).ID: return 4623; case MushroomStem::MushroomStem(true, true, true, false, true, false).ID: return 4624; case MushroomStem::MushroomStem(true, true, true, false, false, true).ID: return 4625; case MushroomStem::MushroomStem(true, true, true, false, false, false).ID: return 4626; case MushroomStem::MushroomStem(true, true, false, true, true, true).ID: return 4627; case MushroomStem::MushroomStem(true, true, false, true, true, false).ID: return 4628; case MushroomStem::MushroomStem(true, true, false, true, false, true).ID: return 4629; case MushroomStem::MushroomStem(true, true, false, true, false, false).ID: return 4630; case MushroomStem::MushroomStem(true, true, false, false, true, true).ID: return 4631; case MushroomStem::MushroomStem(true, true, false, false, true, false).ID: return 4632; case MushroomStem::MushroomStem(true, true, false, false, false, true).ID: return 4633; case MushroomStem::MushroomStem(true, true, false, false, false, false).ID: return 4634; case MushroomStem::MushroomStem(true, false, true, true, true, true).ID: return 4635; case MushroomStem::MushroomStem(true, false, true, true, true, false).ID: return 4636; case MushroomStem::MushroomStem(true, false, true, true, false, true).ID: return 4637; case MushroomStem::MushroomStem(true, false, true, true, false, false).ID: return 4638; case MushroomStem::MushroomStem(true, false, true, false, true, true).ID: return 4639; case MushroomStem::MushroomStem(true, false, true, false, true, false).ID: return 4640; case MushroomStem::MushroomStem(true, false, true, false, false, true).ID: return 4641; case MushroomStem::MushroomStem(true, false, true, false, false, false).ID: return 4642; case MushroomStem::MushroomStem(true, false, false, true, true, true).ID: return 4643; case MushroomStem::MushroomStem(true, false, false, true, true, false).ID: return 4644; case MushroomStem::MushroomStem(true, false, false, true, false, true).ID: return 4645; case MushroomStem::MushroomStem(true, false, false, true, false, false).ID: return 4646; case MushroomStem::MushroomStem(true, false, false, false, true, true).ID: return 4647; case MushroomStem::MushroomStem(true, false, false, false, true, false).ID: return 4648; case MushroomStem::MushroomStem(true, false, false, false, false, true).ID: return 4649; case MushroomStem::MushroomStem(true, false, false, false, false, false).ID: return 4650; case MushroomStem::MushroomStem(false, true, true, true, true, true).ID: return 4651; case MushroomStem::MushroomStem(false, true, true, true, true, false).ID: return 4652; case MushroomStem::MushroomStem(false, true, true, true, false, true).ID: return 4653; case MushroomStem::MushroomStem(false, true, true, true, false, false).ID: return 4654; case MushroomStem::MushroomStem(false, true, true, false, true, true).ID: return 4655; case MushroomStem::MushroomStem(false, true, true, false, true, false).ID: return 4656; case MushroomStem::MushroomStem(false, true, true, false, false, true).ID: return 4657; case MushroomStem::MushroomStem(false, true, true, false, false, false).ID: return 4658; case MushroomStem::MushroomStem(false, true, false, true, true, true).ID: return 4659; case MushroomStem::MushroomStem(false, true, false, true, true, false).ID: return 4660; case MushroomStem::MushroomStem(false, true, false, true, false, true).ID: return 4661; case MushroomStem::MushroomStem(false, true, false, true, false, false).ID: return 4662; case MushroomStem::MushroomStem(false, true, false, false, true, true).ID: return 4663; case MushroomStem::MushroomStem(false, true, false, false, true, false).ID: return 4664; case MushroomStem::MushroomStem(false, true, false, false, false, true).ID: return 4665; case MushroomStem::MushroomStem(false, true, false, false, false, false).ID: return 4666; case MushroomStem::MushroomStem(false, false, true, true, true, true).ID: return 4667; case MushroomStem::MushroomStem(false, false, true, true, true, false).ID: return 4668; case MushroomStem::MushroomStem(false, false, true, true, false, true).ID: return 4669; case MushroomStem::MushroomStem(false, false, true, true, false, false).ID: return 4670; case MushroomStem::MushroomStem(false, false, true, false, true, true).ID: return 4671; case MushroomStem::MushroomStem(false, false, true, false, true, false).ID: return 4672; case MushroomStem::MushroomStem(false, false, true, false, false, true).ID: return 4673; case MushroomStem::MushroomStem(false, false, true, false, false, false).ID: return 4674; case MushroomStem::MushroomStem(false, false, false, true, true, true).ID: return 4675; case MushroomStem::MushroomStem(false, false, false, true, true, false).ID: return 4676; case MushroomStem::MushroomStem(false, false, false, true, false, true).ID: return 4677; case MushroomStem::MushroomStem(false, false, false, true, false, false).ID: return 4678; case MushroomStem::MushroomStem(false, false, false, false, true, true).ID: return 4679; case MushroomStem::MushroomStem(false, false, false, false, true, false).ID: return 4680; case MushroomStem::MushroomStem(false, false, false, false, false, true).ID: return 4681; case MushroomStem::MushroomStem(false, false, false, false, false, false).ID: return 4682; case Mycelium::Mycelium(true).ID: return 4996; case Mycelium::Mycelium(false).ID: return 4997; case NetherBrickFence::NetherBrickFence(true, true, true, true).ID: return 5002; case NetherBrickFence::NetherBrickFence(true, true, true, false).ID: return 5003; case NetherBrickFence::NetherBrickFence(true, true, false, true).ID: return 5006; case NetherBrickFence::NetherBrickFence(true, true, false, false).ID: return 5007; case NetherBrickFence::NetherBrickFence(true, false, true, true).ID: return 5010; case NetherBrickFence::NetherBrickFence(true, false, true, false).ID: return 5011; case NetherBrickFence::NetherBrickFence(true, false, false, true).ID: return 5014; case NetherBrickFence::NetherBrickFence(true, false, false, false).ID: return 5015; case NetherBrickFence::NetherBrickFence(false, true, true, true).ID: return 5018; case NetherBrickFence::NetherBrickFence(false, true, true, false).ID: return 5019; case NetherBrickFence::NetherBrickFence(false, true, false, true).ID: return 5022; case NetherBrickFence::NetherBrickFence(false, true, false, false).ID: return 5023; case NetherBrickFence::NetherBrickFence(false, false, true, true).ID: return 5026; case NetherBrickFence::NetherBrickFence(false, false, true, false).ID: return 5027; case NetherBrickFence::NetherBrickFence(false, false, false, true).ID: return 5030; case NetherBrickFence::NetherBrickFence(false, false, false, false).ID: return 5031; case NetherBrickSlab::NetherBrickSlab(NetherBrickSlab::Type::Top).ID: return 7849; case NetherBrickSlab::NetherBrickSlab(NetherBrickSlab::Type::Bottom).ID: return 7851; case NetherBrickSlab::NetherBrickSlab(NetherBrickSlab::Type::Double).ID: return 7853; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::Straight).ID: return 5033; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::InnerLeft).ID: return 5035; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::InnerRight).ID: return 5037; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::OuterLeft).ID: return 5039; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::OuterRight).ID: return 5041; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::Straight).ID: return 5043; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::InnerLeft).ID: return 5045; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::InnerRight).ID: return 5047; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::OuterLeft).ID: return 5049; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::OuterRight).ID: return 5051; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::Straight).ID: return 5053; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::InnerLeft).ID: return 5055; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::InnerRight).ID: return 5057; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::OuterLeft).ID: return 5059; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::OuterRight).ID: return 5061; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::Straight).ID: return 5063; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::InnerLeft).ID: return 5065; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::InnerRight).ID: return 5067; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::OuterLeft).ID: return 5069; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::OuterRight).ID: return 5071; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XM, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::Straight).ID: return 5073; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XM, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::InnerLeft).ID: return 5075; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XM, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::InnerRight).ID: return 5077; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XM, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::OuterLeft).ID: return 5079; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XM, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::OuterRight).ID: return 5081; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XM, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::Straight).ID: return 5083; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XM, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::InnerLeft).ID: return 5085; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XM, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::InnerRight).ID: return 5087; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XM, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::OuterLeft).ID: return 5089; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XM, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::OuterRight).ID: return 5091; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XP, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::Straight).ID: return 5093; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XP, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::InnerLeft).ID: return 5095; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XP, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::InnerRight).ID: return 5097; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XP, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::OuterLeft).ID: return 5099; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XP, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::OuterRight).ID: return 5101; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XP, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::Straight).ID: return 5103; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XP, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::InnerLeft).ID: return 5105; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XP, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::InnerRight).ID: return 5107; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XP, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::OuterLeft).ID: return 5109; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XP, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::OuterRight).ID: return 5111; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::Low, NetherBrickWall::South::Low, true, NetherBrickWall::West::Low).ID: return 10717; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::Low, NetherBrickWall::South::Low, true, NetherBrickWall::West::None).ID: return 10718; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::Low, NetherBrickWall::South::Low, false, NetherBrickWall::West::Low).ID: return 10721; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::Low, NetherBrickWall::South::Low, false, NetherBrickWall::West::None).ID: return 10722; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::Low, NetherBrickWall::South::None, true, NetherBrickWall::West::Low).ID: return 10725; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::Low, NetherBrickWall::South::None, true, NetherBrickWall::West::None).ID: return 10726; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::Low, NetherBrickWall::South::None, false, NetherBrickWall::West::Low).ID: return 10729; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::Low, NetherBrickWall::South::None, false, NetherBrickWall::West::None).ID: return 10730; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::None, NetherBrickWall::South::Low, true, NetherBrickWall::West::Low).ID: return 10733; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::None, NetherBrickWall::South::Low, true, NetherBrickWall::West::None).ID: return 10734; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::None, NetherBrickWall::South::Low, false, NetherBrickWall::West::Low).ID: return 10737; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::None, NetherBrickWall::South::Low, false, NetherBrickWall::West::None).ID: return 10738; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::None, NetherBrickWall::South::None, true, NetherBrickWall::West::Low).ID: return 10741; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::None, NetherBrickWall::South::None, true, NetherBrickWall::West::None).ID: return 10742; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::None, NetherBrickWall::South::None, false, NetherBrickWall::West::Low).ID: return 10745; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::None, NetherBrickWall::South::None, false, NetherBrickWall::West::None).ID: return 10746; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::Low, NetherBrickWall::South::Low, true, NetherBrickWall::West::Low).ID: return 10749; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::Low, NetherBrickWall::South::Low, true, NetherBrickWall::West::None).ID: return 10750; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::Low, NetherBrickWall::South::Low, false, NetherBrickWall::West::Low).ID: return 10753; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::Low, NetherBrickWall::South::Low, false, NetherBrickWall::West::None).ID: return 10754; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::Low, NetherBrickWall::South::None, true, NetherBrickWall::West::Low).ID: return 10757; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::Low, NetherBrickWall::South::None, true, NetherBrickWall::West::None).ID: return 10758; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::Low, NetherBrickWall::South::None, false, NetherBrickWall::West::Low).ID: return 10761; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::Low, NetherBrickWall::South::None, false, NetherBrickWall::West::None).ID: return 10762; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::None, NetherBrickWall::South::Low, true, NetherBrickWall::West::Low).ID: return 10765; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::None, NetherBrickWall::South::Low, true, NetherBrickWall::West::None).ID: return 10766; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::None, NetherBrickWall::South::Low, false, NetherBrickWall::West::Low).ID: return 10769; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::None, NetherBrickWall::South::Low, false, NetherBrickWall::West::None).ID: return 10770; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::None, NetherBrickWall::South::None, true, NetherBrickWall::West::Low).ID: return 10773; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::None, NetherBrickWall::South::None, true, NetherBrickWall::West::None).ID: return 10774; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::None, NetherBrickWall::South::None, false, NetherBrickWall::West::Low).ID: return 10777; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::None, NetherBrickWall::South::None, false, NetherBrickWall::West::None).ID: return 10778; case NetherBricks::NetherBricks().ID: return 4999; case NetherPortal::NetherPortal(NetherPortal::Axis::X).ID: return 4000; case NetherPortal::NetherPortal(NetherPortal::Axis::Z).ID: return 4001; case NetherQuartzOre::NetherQuartzOre().ID: return 6191; case NetherWart::NetherWart(0).ID: return 5112; case NetherWart::NetherWart(1).ID: return 5113; case NetherWart::NetherWart(2).ID: return 5114; case NetherWart::NetherWart(3).ID: return 5115; case NetherWartBlock::NetherWartBlock().ID: return 8718; case Netherrack::Netherrack().ID: return 3997; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 0, true).ID: return 248; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 0, false).ID: return 249; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 1, true).ID: return 250; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 1, false).ID: return 251; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 2, true).ID: return 252; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 2, false).ID: return 253; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 3, true).ID: return 254; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 3, false).ID: return 255; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 4, true).ID: return 256; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 4, false).ID: return 257; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 5, true).ID: return 258; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 5, false).ID: return 259; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 6, true).ID: return 260; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 6, false).ID: return 261; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 7, true).ID: return 262; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 7, false).ID: return 263; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 8, true).ID: return 264; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 8, false).ID: return 265; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 9, true).ID: return 266; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 9, false).ID: return 267; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 10, true).ID: return 268; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 10, false).ID: return 269; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 11, true).ID: return 270; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 11, false).ID: return 271; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 12, true).ID: return 272; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 12, false).ID: return 273; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 13, true).ID: return 274; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 13, false).ID: return 275; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 14, true).ID: return 276; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 14, false).ID: return 277; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 15, true).ID: return 278; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 15, false).ID: return 279; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 16, true).ID: return 280; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 16, false).ID: return 281; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 17, true).ID: return 282; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 17, false).ID: return 283; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 18, true).ID: return 284; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 18, false).ID: return 285; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 19, true).ID: return 286; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 19, false).ID: return 287; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 20, true).ID: return 288; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 20, false).ID: return 289; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 21, true).ID: return 290; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 21, false).ID: return 291; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 22, true).ID: return 292; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 22, false).ID: return 293; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 23, true).ID: return 294; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 23, false).ID: return 295; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 24, true).ID: return 296; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 24, false).ID: return 297; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 0, true).ID: return 298; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 0, false).ID: return 299; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 1, true).ID: return 300; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 1, false).ID: return 301; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 2, true).ID: return 302; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 2, false).ID: return 303; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 3, true).ID: return 304; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 3, false).ID: return 305; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 4, true).ID: return 306; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 4, false).ID: return 307; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 5, true).ID: return 308; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 5, false).ID: return 309; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 6, true).ID: return 310; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 6, false).ID: return 311; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 7, true).ID: return 312; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 7, false).ID: return 313; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 8, true).ID: return 314; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 8, false).ID: return 315; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 9, true).ID: return 316; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 9, false).ID: return 317; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 10, true).ID: return 318; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 10, false).ID: return 319; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 11, true).ID: return 320; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 11, false).ID: return 321; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 12, true).ID: return 322; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 12, false).ID: return 323; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 13, true).ID: return 324; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 13, false).ID: return 325; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 14, true).ID: return 326; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 14, false).ID: return 327; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 15, true).ID: return 328; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 15, false).ID: return 329; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 16, true).ID: return 330; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 16, false).ID: return 331; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 17, true).ID: return 332; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 17, false).ID: return 333; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 18, true).ID: return 334; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 18, false).ID: return 335; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 19, true).ID: return 336; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 19, false).ID: return 337; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 20, true).ID: return 338; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 20, false).ID: return 339; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 21, true).ID: return 340; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 21, false).ID: return 341; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 22, true).ID: return 342; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 22, false).ID: return 343; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 23, true).ID: return 344; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 23, false).ID: return 345; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 24, true).ID: return 346; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 24, false).ID: return 347; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 0, true).ID: return 348; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 0, false).ID: return 349; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 1, true).ID: return 350; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 1, false).ID: return 351; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 2, true).ID: return 352; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 2, false).ID: return 353; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 3, true).ID: return 354; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 3, false).ID: return 355; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 4, true).ID: return 356; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 4, false).ID: return 357; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 5, true).ID: return 358; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 5, false).ID: return 359; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 6, true).ID: return 360; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 6, false).ID: return 361; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 7, true).ID: return 362; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 7, false).ID: return 363; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 8, true).ID: return 364; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 8, false).ID: return 365; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 9, true).ID: return 366; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 9, false).ID: return 367; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 10, true).ID: return 368; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 10, false).ID: return 369; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 11, true).ID: return 370; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 11, false).ID: return 371; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 12, true).ID: return 372; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 12, false).ID: return 373; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 13, true).ID: return 374; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 13, false).ID: return 375; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 14, true).ID: return 376; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 14, false).ID: return 377; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 15, true).ID: return 378; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 15, false).ID: return 379; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 16, true).ID: return 380; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 16, false).ID: return 381; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 17, true).ID: return 382; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 17, false).ID: return 383; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 18, true).ID: return 384; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 18, false).ID: return 385; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 19, true).ID: return 386; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 19, false).ID: return 387; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 20, true).ID: return 388; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 20, false).ID: return 389; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 21, true).ID: return 390; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 21, false).ID: return 391; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 22, true).ID: return 392; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 22, false).ID: return 393; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 23, true).ID: return 394; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 23, false).ID: return 395; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 24, true).ID: return 396; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 24, false).ID: return 397; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 0, true).ID: return 398; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 0, false).ID: return 399; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 1, true).ID: return 400; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 1, false).ID: return 401; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 2, true).ID: return 402; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 2, false).ID: return 403; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 3, true).ID: return 404; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 3, false).ID: return 405; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 4, true).ID: return 406; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 4, false).ID: return 407; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 5, true).ID: return 408; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 5, false).ID: return 409; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 6, true).ID: return 410; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 6, false).ID: return 411; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 7, true).ID: return 412; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 7, false).ID: return 413; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 8, true).ID: return 414; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 8, false).ID: return 415; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 9, true).ID: return 416; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 9, false).ID: return 417; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 10, true).ID: return 418; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 10, false).ID: return 419; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 11, true).ID: return 420; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 11, false).ID: return 421; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 12, true).ID: return 422; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 12, false).ID: return 423; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 13, true).ID: return 424; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 13, false).ID: return 425; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 14, true).ID: return 426; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 14, false).ID: return 427; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 15, true).ID: return 428; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 15, false).ID: return 429; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 16, true).ID: return 430; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 16, false).ID: return 431; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 17, true).ID: return 432; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 17, false).ID: return 433; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 18, true).ID: return 434; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 18, false).ID: return 435; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 19, true).ID: return 436; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 19, false).ID: return 437; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 20, true).ID: return 438; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 20, false).ID: return 439; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 21, true).ID: return 440; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 21, false).ID: return 441; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 22, true).ID: return 442; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 22, false).ID: return 443; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 23, true).ID: return 444; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 23, false).ID: return 445; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 24, true).ID: return 446; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 24, false).ID: return 447; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 0, true).ID: return 448; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 0, false).ID: return 449; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 1, true).ID: return 450; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 1, false).ID: return 451; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 2, true).ID: return 452; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 2, false).ID: return 453; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 3, true).ID: return 454; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 3, false).ID: return 455; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 4, true).ID: return 456; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 4, false).ID: return 457; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 5, true).ID: return 458; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 5, false).ID: return 459; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 6, true).ID: return 460; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 6, false).ID: return 461; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 7, true).ID: return 462; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 7, false).ID: return 463; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 8, true).ID: return 464; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 8, false).ID: return 465; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 9, true).ID: return 466; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 9, false).ID: return 467; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 10, true).ID: return 468; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 10, false).ID: return 469; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 11, true).ID: return 470; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 11, false).ID: return 471; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 12, true).ID: return 472; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 12, false).ID: return 473; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 13, true).ID: return 474; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 13, false).ID: return 475; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 14, true).ID: return 476; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 14, false).ID: return 477; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 15, true).ID: return 478; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 15, false).ID: return 479; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 16, true).ID: return 480; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 16, false).ID: return 481; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 17, true).ID: return 482; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 17, false).ID: return 483; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 18, true).ID: return 484; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 18, false).ID: return 485; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 19, true).ID: return 486; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 19, false).ID: return 487; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 20, true).ID: return 488; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 20, false).ID: return 489; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 21, true).ID: return 490; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 21, false).ID: return 491; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 22, true).ID: return 492; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 22, false).ID: return 493; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 23, true).ID: return 494; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 23, false).ID: return 495; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 24, true).ID: return 496; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 24, false).ID: return 497; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 0, true).ID: return 498; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 0, false).ID: return 499; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 1, true).ID: return 500; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 1, false).ID: return 501; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 2, true).ID: return 502; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 2, false).ID: return 503; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 3, true).ID: return 504; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 3, false).ID: return 505; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 4, true).ID: return 506; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 4, false).ID: return 507; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 5, true).ID: return 508; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 5, false).ID: return 509; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 6, true).ID: return 510; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 6, false).ID: return 511; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 7, true).ID: return 512; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 7, false).ID: return 513; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 8, true).ID: return 514; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 8, false).ID: return 515; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 9, true).ID: return 516; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 9, false).ID: return 517; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 10, true).ID: return 518; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 10, false).ID: return 519; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 11, true).ID: return 520; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 11, false).ID: return 521; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 12, true).ID: return 522; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 12, false).ID: return 523; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 13, true).ID: return 524; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 13, false).ID: return 525; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 14, true).ID: return 526; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 14, false).ID: return 527; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 15, true).ID: return 528; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 15, false).ID: return 529; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 16, true).ID: return 530; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 16, false).ID: return 531; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 17, true).ID: return 532; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 17, false).ID: return 533; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 18, true).ID: return 534; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 18, false).ID: return 535; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 19, true).ID: return 536; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 19, false).ID: return 537; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 20, true).ID: return 538; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 20, false).ID: return 539; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 21, true).ID: return 540; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 21, false).ID: return 541; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 22, true).ID: return 542; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 22, false).ID: return 543; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 23, true).ID: return 544; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 23, false).ID: return 545; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 24, true).ID: return 546; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 24, false).ID: return 547; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 0, true).ID: return 548; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 0, false).ID: return 549; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 1, true).ID: return 550; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 1, false).ID: return 551; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 2, true).ID: return 552; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 2, false).ID: return 553; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 3, true).ID: return 554; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 3, false).ID: return 555; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 4, true).ID: return 556; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 4, false).ID: return 557; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 5, true).ID: return 558; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 5, false).ID: return 559; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 6, true).ID: return 560; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 6, false).ID: return 561; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 7, true).ID: return 562; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 7, false).ID: return 563; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 8, true).ID: return 564; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 8, false).ID: return 565; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 9, true).ID: return 566; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 9, false).ID: return 567; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 10, true).ID: return 568; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 10, false).ID: return 569; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 11, true).ID: return 570; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 11, false).ID: return 571; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 12, true).ID: return 572; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 12, false).ID: return 573; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 13, true).ID: return 574; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 13, false).ID: return 575; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 14, true).ID: return 576; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 14, false).ID: return 577; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 15, true).ID: return 578; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 15, false).ID: return 579; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 16, true).ID: return 580; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 16, false).ID: return 581; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 17, true).ID: return 582; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 17, false).ID: return 583; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 18, true).ID: return 584; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 18, false).ID: return 585; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 19, true).ID: return 586; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 19, false).ID: return 587; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 20, true).ID: return 588; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 20, false).ID: return 589; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 21, true).ID: return 590; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 21, false).ID: return 591; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 22, true).ID: return 592; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 22, false).ID: return 593; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 23, true).ID: return 594; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 23, false).ID: return 595; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 24, true).ID: return 596; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 24, false).ID: return 597; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 0, true).ID: return 598; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 0, false).ID: return 599; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 1, true).ID: return 600; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 1, false).ID: return 601; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 2, true).ID: return 602; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 2, false).ID: return 603; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 3, true).ID: return 604; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 3, false).ID: return 605; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 4, true).ID: return 606; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 4, false).ID: return 607; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 5, true).ID: return 608; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 5, false).ID: return 609; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 6, true).ID: return 610; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 6, false).ID: return 611; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 7, true).ID: return 612; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 7, false).ID: return 613; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 8, true).ID: return 614; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 8, false).ID: return 615; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 9, true).ID: return 616; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 9, false).ID: return 617; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 10, true).ID: return 618; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 10, false).ID: return 619; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 11, true).ID: return 620; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 11, false).ID: return 621; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 12, true).ID: return 622; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 12, false).ID: return 623; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 13, true).ID: return 624; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 13, false).ID: return 625; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 14, true).ID: return 626; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 14, false).ID: return 627; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 15, true).ID: return 628; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 15, false).ID: return 629; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 16, true).ID: return 630; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 16, false).ID: return 631; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 17, true).ID: return 632; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 17, false).ID: return 633; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 18, true).ID: return 634; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 18, false).ID: return 635; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 19, true).ID: return 636; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 19, false).ID: return 637; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 20, true).ID: return 638; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 20, false).ID: return 639; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 21, true).ID: return 640; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 21, false).ID: return 641; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 22, true).ID: return 642; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 22, false).ID: return 643; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 23, true).ID: return 644; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 23, false).ID: return 645; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 24, true).ID: return 646; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 24, false).ID: return 647; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 0, true).ID: return 648; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 0, false).ID: return 649; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 1, true).ID: return 650; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 1, false).ID: return 651; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 2, true).ID: return 652; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 2, false).ID: return 653; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 3, true).ID: return 654; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 3, false).ID: return 655; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 4, true).ID: return 656; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 4, false).ID: return 657; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 5, true).ID: return 658; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 5, false).ID: return 659; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 6, true).ID: return 660; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 6, false).ID: return 661; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 7, true).ID: return 662; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 7, false).ID: return 663; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 8, true).ID: return 664; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 8, false).ID: return 665; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 9, true).ID: return 666; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 9, false).ID: return 667; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 10, true).ID: return 668; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 10, false).ID: return 669; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 11, true).ID: return 670; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 11, false).ID: return 671; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 12, true).ID: return 672; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 12, false).ID: return 673; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 13, true).ID: return 674; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 13, false).ID: return 675; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 14, true).ID: return 676; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 14, false).ID: return 677; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 15, true).ID: return 678; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 15, false).ID: return 679; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 16, true).ID: return 680; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 16, false).ID: return 681; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 17, true).ID: return 682; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 17, false).ID: return 683; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 18, true).ID: return 684; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 18, false).ID: return 685; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 19, true).ID: return 686; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 19, false).ID: return 687; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 20, true).ID: return 688; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 20, false).ID: return 689; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 21, true).ID: return 690; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 21, false).ID: return 691; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 22, true).ID: return 692; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 22, false).ID: return 693; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 23, true).ID: return 694; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 23, false).ID: return 695; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 24, true).ID: return 696; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 24, false).ID: return 697; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 0, true).ID: return 698; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 0, false).ID: return 699; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 1, true).ID: return 700; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 1, false).ID: return 701; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 2, true).ID: return 702; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 2, false).ID: return 703; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 3, true).ID: return 704; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 3, false).ID: return 705; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 4, true).ID: return 706; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 4, false).ID: return 707; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 5, true).ID: return 708; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 5, false).ID: return 709; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 6, true).ID: return 710; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 6, false).ID: return 711; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 7, true).ID: return 712; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 7, false).ID: return 713; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 8, true).ID: return 714; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 8, false).ID: return 715; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 9, true).ID: return 716; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 9, false).ID: return 717; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 10, true).ID: return 718; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 10, false).ID: return 719; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 11, true).ID: return 720; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 11, false).ID: return 721; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 12, true).ID: return 722; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 12, false).ID: return 723; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 13, true).ID: return 724; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 13, false).ID: return 725; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 14, true).ID: return 726; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 14, false).ID: return 727; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 15, true).ID: return 728; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 15, false).ID: return 729; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 16, true).ID: return 730; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 16, false).ID: return 731; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 17, true).ID: return 732; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 17, false).ID: return 733; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 18, true).ID: return 734; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 18, false).ID: return 735; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 19, true).ID: return 736; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 19, false).ID: return 737; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 20, true).ID: return 738; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 20, false).ID: return 739; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 21, true).ID: return 740; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 21, false).ID: return 741; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 22, true).ID: return 742; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 22, false).ID: return 743; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 23, true).ID: return 744; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 23, false).ID: return 745; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 24, true).ID: return 746; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 24, false).ID: return 747; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 0, true).ID: return 748; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 0, false).ID: return 749; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 1, true).ID: return 750; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 1, false).ID: return 751; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 2, true).ID: return 752; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 2, false).ID: return 753; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 3, true).ID: return 754; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 3, false).ID: return 755; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 4, true).ID: return 756; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 4, false).ID: return 757; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 5, true).ID: return 758; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 5, false).ID: return 759; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 6, true).ID: return 760; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 6, false).ID: return 761; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 7, true).ID: return 762; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 7, false).ID: return 763; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 8, true).ID: return 764; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 8, false).ID: return 765; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 9, true).ID: return 766; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 9, false).ID: return 767; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 10, true).ID: return 768; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 10, false).ID: return 769; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 11, true).ID: return 770; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 11, false).ID: return 771; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 12, true).ID: return 772; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 12, false).ID: return 773; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 13, true).ID: return 774; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 13, false).ID: return 775; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 14, true).ID: return 776; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 14, false).ID: return 777; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 15, true).ID: return 778; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 15, false).ID: return 779; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 16, true).ID: return 780; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 16, false).ID: return 781; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 17, true).ID: return 782; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 17, false).ID: return 783; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 18, true).ID: return 784; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 18, false).ID: return 785; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 19, true).ID: return 786; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 19, false).ID: return 787; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 20, true).ID: return 788; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 20, false).ID: return 789; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 21, true).ID: return 790; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 21, false).ID: return 791; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 22, true).ID: return 792; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 22, false).ID: return 793; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 23, true).ID: return 794; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 23, false).ID: return 795; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 24, true).ID: return 796; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 24, false).ID: return 797; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 0, true).ID: return 798; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 0, false).ID: return 799; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 1, true).ID: return 800; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 1, false).ID: return 801; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 2, true).ID: return 802; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 2, false).ID: return 803; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 3, true).ID: return 804; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 3, false).ID: return 805; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 4, true).ID: return 806; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 4, false).ID: return 807; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 5, true).ID: return 808; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 5, false).ID: return 809; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 6, true).ID: return 810; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 6, false).ID: return 811; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 7, true).ID: return 812; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 7, false).ID: return 813; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 8, true).ID: return 814; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 8, false).ID: return 815; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 9, true).ID: return 816; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 9, false).ID: return 817; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 10, true).ID: return 818; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 10, false).ID: return 819; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 11, true).ID: return 820; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 11, false).ID: return 821; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 12, true).ID: return 822; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 12, false).ID: return 823; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 13, true).ID: return 824; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 13, false).ID: return 825; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 14, true).ID: return 826; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 14, false).ID: return 827; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 15, true).ID: return 828; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 15, false).ID: return 829; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 16, true).ID: return 830; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 16, false).ID: return 831; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 17, true).ID: return 832; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 17, false).ID: return 833; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 18, true).ID: return 834; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 18, false).ID: return 835; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 19, true).ID: return 836; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 19, false).ID: return 837; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 20, true).ID: return 838; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 20, false).ID: return 839; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 21, true).ID: return 840; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 21, false).ID: return 841; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 22, true).ID: return 842; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 22, false).ID: return 843; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 23, true).ID: return 844; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 23, false).ID: return 845; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 24, true).ID: return 846; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 24, false).ID: return 847; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 0, true).ID: return 848; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 0, false).ID: return 849; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 1, true).ID: return 850; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 1, false).ID: return 851; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 2, true).ID: return 852; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 2, false).ID: return 853; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 3, true).ID: return 854; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 3, false).ID: return 855; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 4, true).ID: return 856; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 4, false).ID: return 857; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 5, true).ID: return 858; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 5, false).ID: return 859; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 6, true).ID: return 860; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 6, false).ID: return 861; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 7, true).ID: return 862; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 7, false).ID: return 863; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 8, true).ID: return 864; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 8, false).ID: return 865; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 9, true).ID: return 866; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 9, false).ID: return 867; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 10, true).ID: return 868; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 10, false).ID: return 869; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 11, true).ID: return 870; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 11, false).ID: return 871; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 12, true).ID: return 872; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 12, false).ID: return 873; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 13, true).ID: return 874; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 13, false).ID: return 875; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 14, true).ID: return 876; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 14, false).ID: return 877; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 15, true).ID: return 878; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 15, false).ID: return 879; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 16, true).ID: return 880; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 16, false).ID: return 881; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 17, true).ID: return 882; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 17, false).ID: return 883; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 18, true).ID: return 884; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 18, false).ID: return 885; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 19, true).ID: return 886; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 19, false).ID: return 887; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 20, true).ID: return 888; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 20, false).ID: return 889; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 21, true).ID: return 890; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 21, false).ID: return 891; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 22, true).ID: return 892; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 22, false).ID: return 893; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 23, true).ID: return 894; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 23, false).ID: return 895; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 24, true).ID: return 896; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 24, false).ID: return 897; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 0, true).ID: return 898; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 0, false).ID: return 899; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 1, true).ID: return 900; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 1, false).ID: return 901; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 2, true).ID: return 902; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 2, false).ID: return 903; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 3, true).ID: return 904; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 3, false).ID: return 905; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 4, true).ID: return 906; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 4, false).ID: return 907; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 5, true).ID: return 908; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 5, false).ID: return 909; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 6, true).ID: return 910; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 6, false).ID: return 911; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 7, true).ID: return 912; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 7, false).ID: return 913; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 8, true).ID: return 914; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 8, false).ID: return 915; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 9, true).ID: return 916; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 9, false).ID: return 917; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 10, true).ID: return 918; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 10, false).ID: return 919; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 11, true).ID: return 920; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 11, false).ID: return 921; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 12, true).ID: return 922; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 12, false).ID: return 923; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 13, true).ID: return 924; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 13, false).ID: return 925; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 14, true).ID: return 926; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 14, false).ID: return 927; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 15, true).ID: return 928; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 15, false).ID: return 929; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 16, true).ID: return 930; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 16, false).ID: return 931; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 17, true).ID: return 932; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 17, false).ID: return 933; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 18, true).ID: return 934; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 18, false).ID: return 935; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 19, true).ID: return 936; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 19, false).ID: return 937; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 20, true).ID: return 938; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 20, false).ID: return 939; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 21, true).ID: return 940; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 21, false).ID: return 941; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 22, true).ID: return 942; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 22, false).ID: return 943; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 23, true).ID: return 944; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 23, false).ID: return 945; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 24, true).ID: return 946; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 24, false).ID: return 947; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 0, true).ID: return 948; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 0, false).ID: return 949; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 1, true).ID: return 950; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 1, false).ID: return 951; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 2, true).ID: return 952; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 2, false).ID: return 953; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 3, true).ID: return 954; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 3, false).ID: return 955; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 4, true).ID: return 956; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 4, false).ID: return 957; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 5, true).ID: return 958; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 5, false).ID: return 959; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 6, true).ID: return 960; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 6, false).ID: return 961; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 7, true).ID: return 962; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 7, false).ID: return 963; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 8, true).ID: return 964; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 8, false).ID: return 965; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 9, true).ID: return 966; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 9, false).ID: return 967; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 10, true).ID: return 968; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 10, false).ID: return 969; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 11, true).ID: return 970; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 11, false).ID: return 971; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 12, true).ID: return 972; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 12, false).ID: return 973; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 13, true).ID: return 974; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 13, false).ID: return 975; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 14, true).ID: return 976; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 14, false).ID: return 977; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 15, true).ID: return 978; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 15, false).ID: return 979; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 16, true).ID: return 980; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 16, false).ID: return 981; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 17, true).ID: return 982; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 17, false).ID: return 983; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 18, true).ID: return 984; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 18, false).ID: return 985; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 19, true).ID: return 986; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 19, false).ID: return 987; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 20, true).ID: return 988; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 20, false).ID: return 989; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 21, true).ID: return 990; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 21, false).ID: return 991; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 22, true).ID: return 992; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 22, false).ID: return 993; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 23, true).ID: return 994; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 23, false).ID: return 995; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 24, true).ID: return 996; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 24, false).ID: return 997; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 0, true).ID: return 998; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 0, false).ID: return 999; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 1, true).ID: return 1000; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 1, false).ID: return 1001; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 2, true).ID: return 1002; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 2, false).ID: return 1003; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 3, true).ID: return 1004; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 3, false).ID: return 1005; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 4, true).ID: return 1006; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 4, false).ID: return 1007; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 5, true).ID: return 1008; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 5, false).ID: return 1009; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 6, true).ID: return 1010; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 6, false).ID: return 1011; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 7, true).ID: return 1012; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 7, false).ID: return 1013; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 8, true).ID: return 1014; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 8, false).ID: return 1015; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 9, true).ID: return 1016; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 9, false).ID: return 1017; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 10, true).ID: return 1018; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 10, false).ID: return 1019; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 11, true).ID: return 1020; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 11, false).ID: return 1021; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 12, true).ID: return 1022; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 12, false).ID: return 1023; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 13, true).ID: return 1024; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 13, false).ID: return 1025; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 14, true).ID: return 1026; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 14, false).ID: return 1027; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 15, true).ID: return 1028; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 15, false).ID: return 1029; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 16, true).ID: return 1030; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 16, false).ID: return 1031; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 17, true).ID: return 1032; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 17, false).ID: return 1033; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 18, true).ID: return 1034; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 18, false).ID: return 1035; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 19, true).ID: return 1036; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 19, false).ID: return 1037; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 20, true).ID: return 1038; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 20, false).ID: return 1039; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 21, true).ID: return 1040; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 21, false).ID: return 1041; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 22, true).ID: return 1042; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 22, false).ID: return 1043; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 23, true).ID: return 1044; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 23, false).ID: return 1045; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 24, true).ID: return 1046; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 24, false).ID: return 1047; case OakButton::OakButton(OakButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5810; case OakButton::OakButton(OakButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5811; case OakButton::OakButton(OakButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5812; case OakButton::OakButton(OakButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5813; case OakButton::OakButton(OakButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, true).ID: return 5814; case OakButton::OakButton(OakButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, false).ID: return 5815; case OakButton::OakButton(OakButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, true).ID: return 5816; case OakButton::OakButton(OakButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, false).ID: return 5817; case OakButton::OakButton(OakButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5818; case OakButton::OakButton(OakButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5819; case OakButton::OakButton(OakButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5820; case OakButton::OakButton(OakButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5821; case OakButton::OakButton(OakButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, true).ID: return 5822; case OakButton::OakButton(OakButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, false).ID: return 5823; case OakButton::OakButton(OakButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, true).ID: return 5824; case OakButton::OakButton(OakButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, false).ID: return 5825; case OakButton::OakButton(OakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5826; case OakButton::OakButton(OakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5827; case OakButton::OakButton(OakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5828; case OakButton::OakButton(OakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5829; case OakButton::OakButton(OakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, true).ID: return 5830; case OakButton::OakButton(OakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, false).ID: return 5831; case OakButton::OakButton(OakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, true).ID: return 5832; case OakButton::OakButton(OakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, false).ID: return 5833; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Upper, OakDoor::Hinge::Left, true, true).ID: return 3571; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Upper, OakDoor::Hinge::Left, true, false).ID: return 3572; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Upper, OakDoor::Hinge::Left, false, true).ID: return 3573; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Upper, OakDoor::Hinge::Left, false, false).ID: return 3574; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Upper, OakDoor::Hinge::Right, true, true).ID: return 3575; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Upper, OakDoor::Hinge::Right, true, false).ID: return 3576; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Upper, OakDoor::Hinge::Right, false, true).ID: return 3577; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Upper, OakDoor::Hinge::Right, false, false).ID: return 3578; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Lower, OakDoor::Hinge::Left, true, true).ID: return 3579; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Lower, OakDoor::Hinge::Left, true, false).ID: return 3580; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Lower, OakDoor::Hinge::Left, false, true).ID: return 3581; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Lower, OakDoor::Hinge::Left, false, false).ID: return 3582; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Lower, OakDoor::Hinge::Right, true, true).ID: return 3583; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Lower, OakDoor::Hinge::Right, true, false).ID: return 3584; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Lower, OakDoor::Hinge::Right, false, true).ID: return 3585; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Lower, OakDoor::Hinge::Right, false, false).ID: return 3586; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Upper, OakDoor::Hinge::Left, true, true).ID: return 3587; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Upper, OakDoor::Hinge::Left, true, false).ID: return 3588; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Upper, OakDoor::Hinge::Left, false, true).ID: return 3589; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Upper, OakDoor::Hinge::Left, false, false).ID: return 3590; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Upper, OakDoor::Hinge::Right, true, true).ID: return 3591; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Upper, OakDoor::Hinge::Right, true, false).ID: return 3592; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Upper, OakDoor::Hinge::Right, false, true).ID: return 3593; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Upper, OakDoor::Hinge::Right, false, false).ID: return 3594; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Lower, OakDoor::Hinge::Left, true, true).ID: return 3595; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Lower, OakDoor::Hinge::Left, true, false).ID: return 3596; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Lower, OakDoor::Hinge::Left, false, true).ID: return 3597; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Lower, OakDoor::Hinge::Left, false, false).ID: return 3598; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Lower, OakDoor::Hinge::Right, true, true).ID: return 3599; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Lower, OakDoor::Hinge::Right, true, false).ID: return 3600; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Lower, OakDoor::Hinge::Right, false, true).ID: return 3601; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Lower, OakDoor::Hinge::Right, false, false).ID: return 3602; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Upper, OakDoor::Hinge::Left, true, true).ID: return 3603; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Upper, OakDoor::Hinge::Left, true, false).ID: return 3604; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Upper, OakDoor::Hinge::Left, false, true).ID: return 3605; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Upper, OakDoor::Hinge::Left, false, false).ID: return 3606; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Upper, OakDoor::Hinge::Right, true, true).ID: return 3607; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Upper, OakDoor::Hinge::Right, true, false).ID: return 3608; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Upper, OakDoor::Hinge::Right, false, true).ID: return 3609; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Upper, OakDoor::Hinge::Right, false, false).ID: return 3610; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Lower, OakDoor::Hinge::Left, true, true).ID: return 3611; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Lower, OakDoor::Hinge::Left, true, false).ID: return 3612; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Lower, OakDoor::Hinge::Left, false, true).ID: return 3613; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Lower, OakDoor::Hinge::Left, false, false).ID: return 3614; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Lower, OakDoor::Hinge::Right, true, true).ID: return 3615; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Lower, OakDoor::Hinge::Right, true, false).ID: return 3616; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Lower, OakDoor::Hinge::Right, false, true).ID: return 3617; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Lower, OakDoor::Hinge::Right, false, false).ID: return 3618; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Upper, OakDoor::Hinge::Left, true, true).ID: return 3619; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Upper, OakDoor::Hinge::Left, true, false).ID: return 3620; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Upper, OakDoor::Hinge::Left, false, true).ID: return 3621; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Upper, OakDoor::Hinge::Left, false, false).ID: return 3622; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Upper, OakDoor::Hinge::Right, true, true).ID: return 3623; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Upper, OakDoor::Hinge::Right, true, false).ID: return 3624; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Upper, OakDoor::Hinge::Right, false, true).ID: return 3625; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Upper, OakDoor::Hinge::Right, false, false).ID: return 3626; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Lower, OakDoor::Hinge::Left, true, true).ID: return 3627; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Lower, OakDoor::Hinge::Left, true, false).ID: return 3628; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Lower, OakDoor::Hinge::Left, false, true).ID: return 3629; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Lower, OakDoor::Hinge::Left, false, false).ID: return 3630; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Lower, OakDoor::Hinge::Right, true, true).ID: return 3631; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Lower, OakDoor::Hinge::Right, true, false).ID: return 3632; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Lower, OakDoor::Hinge::Right, false, true).ID: return 3633; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Lower, OakDoor::Hinge::Right, false, false).ID: return 3634; case OakFence::OakFence(true, true, true, true).ID: return 3966; case OakFence::OakFence(true, true, true, false).ID: return 3967; case OakFence::OakFence(true, true, false, true).ID: return 3970; case OakFence::OakFence(true, true, false, false).ID: return 3971; case OakFence::OakFence(true, false, true, true).ID: return 3974; case OakFence::OakFence(true, false, true, false).ID: return 3975; case OakFence::OakFence(true, false, false, true).ID: return 3978; case OakFence::OakFence(true, false, false, false).ID: return 3979; case OakFence::OakFence(false, true, true, true).ID: return 3982; case OakFence::OakFence(false, true, true, false).ID: return 3983; case OakFence::OakFence(false, true, false, true).ID: return 3986; case OakFence::OakFence(false, true, false, false).ID: return 3987; case OakFence::OakFence(false, false, true, true).ID: return 3990; case OakFence::OakFence(false, false, true, false).ID: return 3991; case OakFence::OakFence(false, false, false, true).ID: return 3994; case OakFence::OakFence(false, false, false, false).ID: return 3995; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZM, true, true, true).ID: return 4804; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZM, true, true, false).ID: return 4805; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZM, true, false, true).ID: return 4806; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZM, true, false, false).ID: return 4807; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, true).ID: return 4808; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, false).ID: return 4809; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, true).ID: return 4810; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, false).ID: return 4811; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZP, true, true, true).ID: return 4812; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZP, true, true, false).ID: return 4813; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZP, true, false, true).ID: return 4814; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZP, true, false, false).ID: return 4815; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, true).ID: return 4816; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, false).ID: return 4817; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, true).ID: return 4818; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, false).ID: return 4819; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XM, true, true, true).ID: return 4820; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XM, true, true, false).ID: return 4821; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XM, true, false, true).ID: return 4822; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XM, true, false, false).ID: return 4823; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, true).ID: return 4824; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, false).ID: return 4825; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, true).ID: return 4826; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, false).ID: return 4827; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XP, true, true, true).ID: return 4828; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XP, true, true, false).ID: return 4829; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XP, true, false, true).ID: return 4830; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XP, true, false, false).ID: return 4831; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, true).ID: return 4832; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, false).ID: return 4833; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, true).ID: return 4834; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, false).ID: return 4835; case OakLeaves::OakLeaves(1, true).ID: return 144; case OakLeaves::OakLeaves(1, false).ID: return 145; case OakLeaves::OakLeaves(2, true).ID: return 146; case OakLeaves::OakLeaves(2, false).ID: return 147; case OakLeaves::OakLeaves(3, true).ID: return 148; case OakLeaves::OakLeaves(3, false).ID: return 149; case OakLeaves::OakLeaves(4, true).ID: return 150; case OakLeaves::OakLeaves(4, false).ID: return 151; case OakLeaves::OakLeaves(5, true).ID: return 152; case OakLeaves::OakLeaves(5, false).ID: return 153; case OakLeaves::OakLeaves(6, true).ID: return 154; case OakLeaves::OakLeaves(6, false).ID: return 155; case OakLeaves::OakLeaves(7, true).ID: return 156; case OakLeaves::OakLeaves(7, false).ID: return 157; case OakLog::OakLog(OakLog::Axis::X).ID: return 72; case OakLog::OakLog(OakLog::Axis::Y).ID: return 73; case OakLog::OakLog(OakLog::Axis::Z).ID: return 74; case OakPlanks::OakPlanks().ID: return 15; case OakPressurePlate::OakPressurePlate(true).ID: return 3871; case OakPressurePlate::OakPressurePlate(false).ID: return 3872; case OakSapling::OakSapling(0).ID: return 21; case OakSapling::OakSapling(1).ID: return 22; case OakSign::OakSign(0).ID: return 3380; case OakSign::OakSign(1).ID: return 3382; case OakSign::OakSign(2).ID: return 3384; case OakSign::OakSign(3).ID: return 3386; case OakSign::OakSign(4).ID: return 3388; case OakSign::OakSign(5).ID: return 3390; case OakSign::OakSign(6).ID: return 3392; case OakSign::OakSign(7).ID: return 3394; case OakSign::OakSign(8).ID: return 3396; case OakSign::OakSign(9).ID: return 3398; case OakSign::OakSign(10).ID: return 3400; case OakSign::OakSign(11).ID: return 3402; case OakSign::OakSign(12).ID: return 3404; case OakSign::OakSign(13).ID: return 3406; case OakSign::OakSign(14).ID: return 3408; case OakSign::OakSign(15).ID: return 3410; case OakSlab::OakSlab(OakSlab::Type::Top).ID: return 7765; case OakSlab::OakSlab(OakSlab::Type::Bottom).ID: return 7767; case OakSlab::OakSlab(OakSlab::Type::Double).ID: return 7769; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZM, OakStairs::Half::Top, OakStairs::Shape::Straight).ID: return 1953; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZM, OakStairs::Half::Top, OakStairs::Shape::InnerLeft).ID: return 1955; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZM, OakStairs::Half::Top, OakStairs::Shape::InnerRight).ID: return 1957; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZM, OakStairs::Half::Top, OakStairs::Shape::OuterLeft).ID: return 1959; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZM, OakStairs::Half::Top, OakStairs::Shape::OuterRight).ID: return 1961; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZM, OakStairs::Half::Bottom, OakStairs::Shape::Straight).ID: return 1963; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZM, OakStairs::Half::Bottom, OakStairs::Shape::InnerLeft).ID: return 1965; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZM, OakStairs::Half::Bottom, OakStairs::Shape::InnerRight).ID: return 1967; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZM, OakStairs::Half::Bottom, OakStairs::Shape::OuterLeft).ID: return 1969; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZM, OakStairs::Half::Bottom, OakStairs::Shape::OuterRight).ID: return 1971; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZP, OakStairs::Half::Top, OakStairs::Shape::Straight).ID: return 1973; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZP, OakStairs::Half::Top, OakStairs::Shape::InnerLeft).ID: return 1975; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZP, OakStairs::Half::Top, OakStairs::Shape::InnerRight).ID: return 1977; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZP, OakStairs::Half::Top, OakStairs::Shape::OuterLeft).ID: return 1979; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZP, OakStairs::Half::Top, OakStairs::Shape::OuterRight).ID: return 1981; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZP, OakStairs::Half::Bottom, OakStairs::Shape::Straight).ID: return 1983; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZP, OakStairs::Half::Bottom, OakStairs::Shape::InnerLeft).ID: return 1985; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZP, OakStairs::Half::Bottom, OakStairs::Shape::InnerRight).ID: return 1987; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZP, OakStairs::Half::Bottom, OakStairs::Shape::OuterLeft).ID: return 1989; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZP, OakStairs::Half::Bottom, OakStairs::Shape::OuterRight).ID: return 1991; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XM, OakStairs::Half::Top, OakStairs::Shape::Straight).ID: return 1993; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XM, OakStairs::Half::Top, OakStairs::Shape::InnerLeft).ID: return 1995; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XM, OakStairs::Half::Top, OakStairs::Shape::InnerRight).ID: return 1997; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XM, OakStairs::Half::Top, OakStairs::Shape::OuterLeft).ID: return 1999; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XM, OakStairs::Half::Top, OakStairs::Shape::OuterRight).ID: return 2001; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XM, OakStairs::Half::Bottom, OakStairs::Shape::Straight).ID: return 2003; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XM, OakStairs::Half::Bottom, OakStairs::Shape::InnerLeft).ID: return 2005; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XM, OakStairs::Half::Bottom, OakStairs::Shape::InnerRight).ID: return 2007; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XM, OakStairs::Half::Bottom, OakStairs::Shape::OuterLeft).ID: return 2009; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XM, OakStairs::Half::Bottom, OakStairs::Shape::OuterRight).ID: return 2011; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XP, OakStairs::Half::Top, OakStairs::Shape::Straight).ID: return 2013; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XP, OakStairs::Half::Top, OakStairs::Shape::InnerLeft).ID: return 2015; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XP, OakStairs::Half::Top, OakStairs::Shape::InnerRight).ID: return 2017; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XP, OakStairs::Half::Top, OakStairs::Shape::OuterLeft).ID: return 2019; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XP, OakStairs::Half::Top, OakStairs::Shape::OuterRight).ID: return 2021; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XP, OakStairs::Half::Bottom, OakStairs::Shape::Straight).ID: return 2023; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XP, OakStairs::Half::Bottom, OakStairs::Shape::InnerLeft).ID: return 2025; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XP, OakStairs::Half::Bottom, OakStairs::Shape::InnerRight).ID: return 2027; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XP, OakStairs::Half::Bottom, OakStairs::Shape::OuterLeft).ID: return 2029; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XP, OakStairs::Half::Bottom, OakStairs::Shape::OuterRight).ID: return 2031; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZM, OakTrapdoor::Half::Top, true, true).ID: return 4098; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZM, OakTrapdoor::Half::Top, true, false).ID: return 4100; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZM, OakTrapdoor::Half::Top, false, true).ID: return 4102; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZM, OakTrapdoor::Half::Top, false, false).ID: return 4104; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZM, OakTrapdoor::Half::Bottom, true, true).ID: return 4106; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZM, OakTrapdoor::Half::Bottom, true, false).ID: return 4108; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZM, OakTrapdoor::Half::Bottom, false, true).ID: return 4110; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZM, OakTrapdoor::Half::Bottom, false, false).ID: return 4112; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZP, OakTrapdoor::Half::Top, true, true).ID: return 4114; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZP, OakTrapdoor::Half::Top, true, false).ID: return 4116; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZP, OakTrapdoor::Half::Top, false, true).ID: return 4118; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZP, OakTrapdoor::Half::Top, false, false).ID: return 4120; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZP, OakTrapdoor::Half::Bottom, true, true).ID: return 4122; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZP, OakTrapdoor::Half::Bottom, true, false).ID: return 4124; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZP, OakTrapdoor::Half::Bottom, false, true).ID: return 4126; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZP, OakTrapdoor::Half::Bottom, false, false).ID: return 4128; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XM, OakTrapdoor::Half::Top, true, true).ID: return 4130; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XM, OakTrapdoor::Half::Top, true, false).ID: return 4132; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XM, OakTrapdoor::Half::Top, false, true).ID: return 4134; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XM, OakTrapdoor::Half::Top, false, false).ID: return 4136; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XM, OakTrapdoor::Half::Bottom, true, true).ID: return 4138; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XM, OakTrapdoor::Half::Bottom, true, false).ID: return 4140; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XM, OakTrapdoor::Half::Bottom, false, true).ID: return 4142; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XM, OakTrapdoor::Half::Bottom, false, false).ID: return 4144; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XP, OakTrapdoor::Half::Top, true, true).ID: return 4146; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XP, OakTrapdoor::Half::Top, true, false).ID: return 4148; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XP, OakTrapdoor::Half::Top, false, true).ID: return 4150; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XP, OakTrapdoor::Half::Top, false, false).ID: return 4152; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XP, OakTrapdoor::Half::Bottom, true, true).ID: return 4154; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XP, OakTrapdoor::Half::Bottom, true, false).ID: return 4156; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XP, OakTrapdoor::Half::Bottom, false, true).ID: return 4158; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XP, OakTrapdoor::Half::Bottom, false, false).ID: return 4160; case OakWallSign::OakWallSign(eBlockFace::BLOCK_FACE_ZM).ID: return 3734; case OakWallSign::OakWallSign(eBlockFace::BLOCK_FACE_ZP).ID: return 3736; case OakWallSign::OakWallSign(eBlockFace::BLOCK_FACE_XM).ID: return 3738; case OakWallSign::OakWallSign(eBlockFace::BLOCK_FACE_XP).ID: return 3740; case OakWood::OakWood(OakWood::Axis::X).ID: return 108; case OakWood::OakWood(OakWood::Axis::Y).ID: return 109; case OakWood::OakWood(OakWood::Axis::Z).ID: return 110; case Observer::Observer(eBlockFace::BLOCK_FACE_ZM, true).ID: return 8724; case Observer::Observer(eBlockFace::BLOCK_FACE_ZM, false).ID: return 8725; case Observer::Observer(eBlockFace::BLOCK_FACE_XP, true).ID: return 8726; case Observer::Observer(eBlockFace::BLOCK_FACE_XP, false).ID: return 8727; case Observer::Observer(eBlockFace::BLOCK_FACE_ZP, true).ID: return 8728; case Observer::Observer(eBlockFace::BLOCK_FACE_ZP, false).ID: return 8729; case Observer::Observer(eBlockFace::BLOCK_FACE_XM, true).ID: return 8730; case Observer::Observer(eBlockFace::BLOCK_FACE_XM, false).ID: return 8731; case Observer::Observer(eBlockFace::BLOCK_FACE_YP, true).ID: return 8732; case Observer::Observer(eBlockFace::BLOCK_FACE_YP, false).ID: return 8733; case Observer::Observer(eBlockFace::BLOCK_FACE_YM, true).ID: return 8734; case Observer::Observer(eBlockFace::BLOCK_FACE_YM, false).ID: return 8735; case Obsidian::Obsidian().ID: return 1433; case OrangeBanner::OrangeBanner(0).ID: return 7377; case OrangeBanner::OrangeBanner(1).ID: return 7378; case OrangeBanner::OrangeBanner(2).ID: return 7379; case OrangeBanner::OrangeBanner(3).ID: return 7380; case OrangeBanner::OrangeBanner(4).ID: return 7381; case OrangeBanner::OrangeBanner(5).ID: return 7382; case OrangeBanner::OrangeBanner(6).ID: return 7383; case OrangeBanner::OrangeBanner(7).ID: return 7384; case OrangeBanner::OrangeBanner(8).ID: return 7385; case OrangeBanner::OrangeBanner(9).ID: return 7386; case OrangeBanner::OrangeBanner(10).ID: return 7387; case OrangeBanner::OrangeBanner(11).ID: return 7388; case OrangeBanner::OrangeBanner(12).ID: return 7389; case OrangeBanner::OrangeBanner(13).ID: return 7390; case OrangeBanner::OrangeBanner(14).ID: return 7391; case OrangeBanner::OrangeBanner(15).ID: return 7392; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_ZM, true, OrangeBed::Part::Head).ID: return 1064; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_ZM, true, OrangeBed::Part::Foot).ID: return 1065; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_ZM, false, OrangeBed::Part::Head).ID: return 1066; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_ZM, false, OrangeBed::Part::Foot).ID: return 1067; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_ZP, true, OrangeBed::Part::Head).ID: return 1068; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_ZP, true, OrangeBed::Part::Foot).ID: return 1069; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_ZP, false, OrangeBed::Part::Head).ID: return 1070; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_ZP, false, OrangeBed::Part::Foot).ID: return 1071; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_XM, true, OrangeBed::Part::Head).ID: return 1072; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_XM, true, OrangeBed::Part::Foot).ID: return 1073; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_XM, false, OrangeBed::Part::Head).ID: return 1074; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_XM, false, OrangeBed::Part::Foot).ID: return 1075; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_XP, true, OrangeBed::Part::Head).ID: return 1076; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_XP, true, OrangeBed::Part::Foot).ID: return 1077; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_XP, false, OrangeBed::Part::Head).ID: return 1078; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_XP, false, OrangeBed::Part::Foot).ID: return 1079; case OrangeCarpet::OrangeCarpet().ID: return 7331; case OrangeConcrete::OrangeConcrete().ID: return 8903; case OrangeConcretePowder::OrangeConcretePowder().ID: return 8919; case OrangeGlazedTerracotta::OrangeGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 8842; case OrangeGlazedTerracotta::OrangeGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 8843; case OrangeGlazedTerracotta::OrangeGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 8844; case OrangeGlazedTerracotta::OrangeGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 8845; case OrangeShulkerBox::OrangeShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 8748; case OrangeShulkerBox::OrangeShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 8749; case OrangeShulkerBox::OrangeShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 8750; case OrangeShulkerBox::OrangeShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 8751; case OrangeShulkerBox::OrangeShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 8752; case OrangeShulkerBox::OrangeShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 8753; case OrangeStainedGlass::OrangeStainedGlass().ID: return 4082; case OrangeStainedGlassPane::OrangeStainedGlassPane(true, true, true, true).ID: return 6361; case OrangeStainedGlassPane::OrangeStainedGlassPane(true, true, true, false).ID: return 6362; case OrangeStainedGlassPane::OrangeStainedGlassPane(true, true, false, true).ID: return 6365; case OrangeStainedGlassPane::OrangeStainedGlassPane(true, true, false, false).ID: return 6366; case OrangeStainedGlassPane::OrangeStainedGlassPane(true, false, true, true).ID: return 6369; case OrangeStainedGlassPane::OrangeStainedGlassPane(true, false, true, false).ID: return 6370; case OrangeStainedGlassPane::OrangeStainedGlassPane(true, false, false, true).ID: return 6373; case OrangeStainedGlassPane::OrangeStainedGlassPane(true, false, false, false).ID: return 6374; case OrangeStainedGlassPane::OrangeStainedGlassPane(false, true, true, true).ID: return 6377; case OrangeStainedGlassPane::OrangeStainedGlassPane(false, true, true, false).ID: return 6378; case OrangeStainedGlassPane::OrangeStainedGlassPane(false, true, false, true).ID: return 6381; case OrangeStainedGlassPane::OrangeStainedGlassPane(false, true, false, false).ID: return 6382; case OrangeStainedGlassPane::OrangeStainedGlassPane(false, false, true, true).ID: return 6385; case OrangeStainedGlassPane::OrangeStainedGlassPane(false, false, true, false).ID: return 6386; case OrangeStainedGlassPane::OrangeStainedGlassPane(false, false, false, true).ID: return 6389; case OrangeStainedGlassPane::OrangeStainedGlassPane(false, false, false, false).ID: return 6390; case OrangeTerracotta::OrangeTerracotta().ID: return 6312; case OrangeTulip::OrangeTulip().ID: return 1417; case OrangeWallBanner::OrangeWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 7621; case OrangeWallBanner::OrangeWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 7622; case OrangeWallBanner::OrangeWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 7623; case OrangeWallBanner::OrangeWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 7624; case OrangeWool::OrangeWool().ID: return 1384; case OxeyeDaisy::OxeyeDaisy().ID: return 1420; case PackedIce::PackedIce().ID: return 7348; case Peony::Peony(Peony::Half::Upper).ID: return 7355; case Peony::Peony(Peony::Half::Lower).ID: return 7356; case PetrifiedOakSlab::PetrifiedOakSlab(PetrifiedOakSlab::Type::Top).ID: return 7825; case PetrifiedOakSlab::PetrifiedOakSlab(PetrifiedOakSlab::Type::Bottom).ID: return 7827; case PetrifiedOakSlab::PetrifiedOakSlab(PetrifiedOakSlab::Type::Double).ID: return 7829; case PinkBanner::PinkBanner(0).ID: return 7457; case PinkBanner::PinkBanner(1).ID: return 7458; case PinkBanner::PinkBanner(2).ID: return 7459; case PinkBanner::PinkBanner(3).ID: return 7460; case PinkBanner::PinkBanner(4).ID: return 7461; case PinkBanner::PinkBanner(5).ID: return 7462; case PinkBanner::PinkBanner(6).ID: return 7463; case PinkBanner::PinkBanner(7).ID: return 7464; case PinkBanner::PinkBanner(8).ID: return 7465; case PinkBanner::PinkBanner(9).ID: return 7466; case PinkBanner::PinkBanner(10).ID: return 7467; case PinkBanner::PinkBanner(11).ID: return 7468; case PinkBanner::PinkBanner(12).ID: return 7469; case PinkBanner::PinkBanner(13).ID: return 7470; case PinkBanner::PinkBanner(14).ID: return 7471; case PinkBanner::PinkBanner(15).ID: return 7472; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_ZM, true, PinkBed::Part::Head).ID: return 1144; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_ZM, true, PinkBed::Part::Foot).ID: return 1145; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_ZM, false, PinkBed::Part::Head).ID: return 1146; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_ZM, false, PinkBed::Part::Foot).ID: return 1147; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_ZP, true, PinkBed::Part::Head).ID: return 1148; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_ZP, true, PinkBed::Part::Foot).ID: return 1149; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_ZP, false, PinkBed::Part::Head).ID: return 1150; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_ZP, false, PinkBed::Part::Foot).ID: return 1151; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_XM, true, PinkBed::Part::Head).ID: return 1152; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_XM, true, PinkBed::Part::Foot).ID: return 1153; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_XM, false, PinkBed::Part::Head).ID: return 1154; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_XM, false, PinkBed::Part::Foot).ID: return 1155; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_XP, true, PinkBed::Part::Head).ID: return 1156; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_XP, true, PinkBed::Part::Foot).ID: return 1157; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_XP, false, PinkBed::Part::Head).ID: return 1158; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_XP, false, PinkBed::Part::Foot).ID: return 1159; case PinkCarpet::PinkCarpet().ID: return 7336; case PinkConcrete::PinkConcrete().ID: return 8908; case PinkConcretePowder::PinkConcretePowder().ID: return 8924; case PinkGlazedTerracotta::PinkGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 8862; case PinkGlazedTerracotta::PinkGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 8863; case PinkGlazedTerracotta::PinkGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 8864; case PinkGlazedTerracotta::PinkGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 8865; case PinkShulkerBox::PinkShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 8778; case PinkShulkerBox::PinkShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 8779; case PinkShulkerBox::PinkShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 8780; case PinkShulkerBox::PinkShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 8781; case PinkShulkerBox::PinkShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 8782; case PinkShulkerBox::PinkShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 8783; case PinkStainedGlass::PinkStainedGlass().ID: return 4087; case PinkStainedGlassPane::PinkStainedGlassPane(true, true, true, true).ID: return 6521; case PinkStainedGlassPane::PinkStainedGlassPane(true, true, true, false).ID: return 6522; case PinkStainedGlassPane::PinkStainedGlassPane(true, true, false, true).ID: return 6525; case PinkStainedGlassPane::PinkStainedGlassPane(true, true, false, false).ID: return 6526; case PinkStainedGlassPane::PinkStainedGlassPane(true, false, true, true).ID: return 6529; case PinkStainedGlassPane::PinkStainedGlassPane(true, false, true, false).ID: return 6530; case PinkStainedGlassPane::PinkStainedGlassPane(true, false, false, true).ID: return 6533; case PinkStainedGlassPane::PinkStainedGlassPane(true, false, false, false).ID: return 6534; case PinkStainedGlassPane::PinkStainedGlassPane(false, true, true, true).ID: return 6537; case PinkStainedGlassPane::PinkStainedGlassPane(false, true, true, false).ID: return 6538; case PinkStainedGlassPane::PinkStainedGlassPane(false, true, false, true).ID: return 6541; case PinkStainedGlassPane::PinkStainedGlassPane(false, true, false, false).ID: return 6542; case PinkStainedGlassPane::PinkStainedGlassPane(false, false, true, true).ID: return 6545; case PinkStainedGlassPane::PinkStainedGlassPane(false, false, true, false).ID: return 6546; case PinkStainedGlassPane::PinkStainedGlassPane(false, false, false, true).ID: return 6549; case PinkStainedGlassPane::PinkStainedGlassPane(false, false, false, false).ID: return 6550; case PinkTerracotta::PinkTerracotta().ID: return 6317; case PinkTulip::PinkTulip().ID: return 1419; case PinkWallBanner::PinkWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 7641; case PinkWallBanner::PinkWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 7642; case PinkWallBanner::PinkWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 7643; case PinkWallBanner::PinkWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 7644; case PinkWool::PinkWool().ID: return 1389; case Piston::Piston(true, eBlockFace::BLOCK_FACE_ZM).ID: return 1347; case Piston::Piston(true, eBlockFace::BLOCK_FACE_XP).ID: return 1348; case Piston::Piston(true, eBlockFace::BLOCK_FACE_ZP).ID: return 1349; case Piston::Piston(true, eBlockFace::BLOCK_FACE_XM).ID: return 1350; case Piston::Piston(true, eBlockFace::BLOCK_FACE_YP).ID: return 1351; case Piston::Piston(true, eBlockFace::BLOCK_FACE_YM).ID: return 1352; case Piston::Piston(false, eBlockFace::BLOCK_FACE_ZM).ID: return 1353; case Piston::Piston(false, eBlockFace::BLOCK_FACE_XP).ID: return 1354; case Piston::Piston(false, eBlockFace::BLOCK_FACE_ZP).ID: return 1355; case Piston::Piston(false, eBlockFace::BLOCK_FACE_XM).ID: return 1356; case Piston::Piston(false, eBlockFace::BLOCK_FACE_YP).ID: return 1357; case Piston::Piston(false, eBlockFace::BLOCK_FACE_YM).ID: return 1358; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_ZM, true, PistonHead::Type::Normal).ID: return 1359; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_ZM, true, PistonHead::Type::Sticky).ID: return 1360; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_ZM, false, PistonHead::Type::Normal).ID: return 1361; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_ZM, false, PistonHead::Type::Sticky).ID: return 1362; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_XP, true, PistonHead::Type::Normal).ID: return 1363; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_XP, true, PistonHead::Type::Sticky).ID: return 1364; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_XP, false, PistonHead::Type::Normal).ID: return 1365; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_XP, false, PistonHead::Type::Sticky).ID: return 1366; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_ZP, true, PistonHead::Type::Normal).ID: return 1367; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_ZP, true, PistonHead::Type::Sticky).ID: return 1368; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_ZP, false, PistonHead::Type::Normal).ID: return 1369; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_ZP, false, PistonHead::Type::Sticky).ID: return 1370; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_XM, true, PistonHead::Type::Normal).ID: return 1371; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_XM, true, PistonHead::Type::Sticky).ID: return 1372; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_XM, false, PistonHead::Type::Normal).ID: return 1373; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_XM, false, PistonHead::Type::Sticky).ID: return 1374; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_YP, true, PistonHead::Type::Normal).ID: return 1375; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_YP, true, PistonHead::Type::Sticky).ID: return 1376; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_YP, false, PistonHead::Type::Normal).ID: return 1377; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_YP, false, PistonHead::Type::Sticky).ID: return 1378; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_YM, true, PistonHead::Type::Normal).ID: return 1379; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_YM, true, PistonHead::Type::Sticky).ID: return 1380; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_YM, false, PistonHead::Type::Normal).ID: return 1381; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_YM, false, PistonHead::Type::Sticky).ID: return 1382; case PlayerHead::PlayerHead(0).ID: return 6014; case PlayerHead::PlayerHead(1).ID: return 6015; case PlayerHead::PlayerHead(2).ID: return 6016; case PlayerHead::PlayerHead(3).ID: return 6017; case PlayerHead::PlayerHead(4).ID: return 6018; case PlayerHead::PlayerHead(5).ID: return 6019; case PlayerHead::PlayerHead(6).ID: return 6020; case PlayerHead::PlayerHead(7).ID: return 6021; case PlayerHead::PlayerHead(8).ID: return 6022; case PlayerHead::PlayerHead(9).ID: return 6023; case PlayerHead::PlayerHead(10).ID: return 6024; case PlayerHead::PlayerHead(11).ID: return 6025; case PlayerHead::PlayerHead(12).ID: return 6026; case PlayerHead::PlayerHead(13).ID: return 6027; case PlayerHead::PlayerHead(14).ID: return 6028; case PlayerHead::PlayerHead(15).ID: return 6029; case PlayerWallHead::PlayerWallHead(eBlockFace::BLOCK_FACE_ZM).ID: return 6030; case PlayerWallHead::PlayerWallHead(eBlockFace::BLOCK_FACE_ZP).ID: return 6031; case PlayerWallHead::PlayerWallHead(eBlockFace::BLOCK_FACE_XM).ID: return 6032; case PlayerWallHead::PlayerWallHead(eBlockFace::BLOCK_FACE_XP).ID: return 6033; case Podzol::Podzol(true).ID: return 12; case Podzol::Podzol(false).ID: return 13; case PolishedAndesite::PolishedAndesite().ID: return 7; case PolishedAndesiteSlab::PolishedAndesiteSlab(PolishedAndesiteSlab::Type::Top).ID: return 10320; case PolishedAndesiteSlab::PolishedAndesiteSlab(PolishedAndesiteSlab::Type::Bottom).ID: return 10322; case PolishedAndesiteSlab::PolishedAndesiteSlab(PolishedAndesiteSlab::Type::Double).ID: return 10324; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedAndesiteStairs::Half::Top, PolishedAndesiteStairs::Shape::Straight).ID: return 10094; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedAndesiteStairs::Half::Top, PolishedAndesiteStairs::Shape::InnerLeft).ID: return 10096; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedAndesiteStairs::Half::Top, PolishedAndesiteStairs::Shape::InnerRight).ID: return 10098; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedAndesiteStairs::Half::Top, PolishedAndesiteStairs::Shape::OuterLeft).ID: return 10100; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedAndesiteStairs::Half::Top, PolishedAndesiteStairs::Shape::OuterRight).ID: return 10102; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedAndesiteStairs::Half::Bottom, PolishedAndesiteStairs::Shape::Straight).ID: return 10104; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedAndesiteStairs::Half::Bottom, PolishedAndesiteStairs::Shape::InnerLeft).ID: return 10106; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedAndesiteStairs::Half::Bottom, PolishedAndesiteStairs::Shape::InnerRight).ID: return 10108; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedAndesiteStairs::Half::Bottom, PolishedAndesiteStairs::Shape::OuterLeft).ID: return 10110; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedAndesiteStairs::Half::Bottom, PolishedAndesiteStairs::Shape::OuterRight).ID: return 10112; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedAndesiteStairs::Half::Top, PolishedAndesiteStairs::Shape::Straight).ID: return 10114; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedAndesiteStairs::Half::Top, PolishedAndesiteStairs::Shape::InnerLeft).ID: return 10116; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedAndesiteStairs::Half::Top, PolishedAndesiteStairs::Shape::InnerRight).ID: return 10118; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedAndesiteStairs::Half::Top, PolishedAndesiteStairs::Shape::OuterLeft).ID: return 10120; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedAndesiteStairs::Half::Top, PolishedAndesiteStairs::Shape::OuterRight).ID: return 10122; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedAndesiteStairs::Half::Bottom, PolishedAndesiteStairs::Shape::Straight).ID: return 10124; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedAndesiteStairs::Half::Bottom, PolishedAndesiteStairs::Shape::InnerLeft).ID: return 10126; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedAndesiteStairs::Half::Bottom, PolishedAndesiteStairs::Shape::InnerRight).ID: return 10128; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedAndesiteStairs::Half::Bottom, PolishedAndesiteStairs::Shape::OuterLeft).ID: return 10130; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedAndesiteStairs::Half::Bottom, PolishedAndesiteStairs::Shape::OuterRight).ID: return 10132; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_XM, PolishedAndesiteStairs::Half::Top, PolishedAndesiteStairs::Shape::Straight).ID: return 10134; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_XM, PolishedAndesiteStairs::Half::Top, PolishedAndesiteStairs::Shape::InnerLeft).ID: return 10136; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_XM, PolishedAndesiteStairs::Half::Top, PolishedAndesiteStairs::Shape::InnerRight).ID: return 10138; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_XM, PolishedAndesiteStairs::Half::Top, PolishedAndesiteStairs::Shape::OuterLeft).ID: return 10140; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_XM, PolishedAndesiteStairs::Half::Top, PolishedAndesiteStairs::Shape::OuterRight).ID: return 10142; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_XM, PolishedAndesiteStairs::Half::Bottom, PolishedAndesiteStairs::Shape::Straight).ID: return 10144; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_XM, PolishedAndesiteStairs::Half::Bottom, PolishedAndesiteStairs::Shape::InnerLeft).ID: return 10146; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_XM, PolishedAndesiteStairs::Half::Bottom, PolishedAndesiteStairs::Shape::InnerRight).ID: return 10148; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_XM, PolishedAndesiteStairs::Half::Bottom, PolishedAndesiteStairs::Shape::OuterLeft).ID: return 10150; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_XM, PolishedAndesiteStairs::Half::Bottom, PolishedAndesiteStairs::Shape::OuterRight).ID: return 10152; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_XP, PolishedAndesiteStairs::Half::Top, PolishedAndesiteStairs::Shape::Straight).ID: return 10154; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_XP, PolishedAndesiteStairs::Half::Top, PolishedAndesiteStairs::Shape::InnerLeft).ID: return 10156; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_XP, PolishedAndesiteStairs::Half::Top, PolishedAndesiteStairs::Shape::InnerRight).ID: return 10158; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_XP, PolishedAndesiteStairs::Half::Top, PolishedAndesiteStairs::Shape::OuterLeft).ID: return 10160; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_XP, PolishedAndesiteStairs::Half::Top, PolishedAndesiteStairs::Shape::OuterRight).ID: return 10162; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_XP, PolishedAndesiteStairs::Half::Bottom, PolishedAndesiteStairs::Shape::Straight).ID: return 10164; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_XP, PolishedAndesiteStairs::Half::Bottom, PolishedAndesiteStairs::Shape::InnerLeft).ID: return 10166; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_XP, PolishedAndesiteStairs::Half::Bottom, PolishedAndesiteStairs::Shape::InnerRight).ID: return 10168; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_XP, PolishedAndesiteStairs::Half::Bottom, PolishedAndesiteStairs::Shape::OuterLeft).ID: return 10170; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_XP, PolishedAndesiteStairs::Half::Bottom, PolishedAndesiteStairs::Shape::OuterRight).ID: return 10172; case PolishedDiorite::PolishedDiorite().ID: return 5; case PolishedDioriteSlab::PolishedDioriteSlab(PolishedDioriteSlab::Type::Top).ID: return 10272; case PolishedDioriteSlab::PolishedDioriteSlab(PolishedDioriteSlab::Type::Bottom).ID: return 10274; case PolishedDioriteSlab::PolishedDioriteSlab(PolishedDioriteSlab::Type::Double).ID: return 10276; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedDioriteStairs::Half::Top, PolishedDioriteStairs::Shape::Straight).ID: return 9374; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedDioriteStairs::Half::Top, PolishedDioriteStairs::Shape::InnerLeft).ID: return 9376; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedDioriteStairs::Half::Top, PolishedDioriteStairs::Shape::InnerRight).ID: return 9378; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedDioriteStairs::Half::Top, PolishedDioriteStairs::Shape::OuterLeft).ID: return 9380; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedDioriteStairs::Half::Top, PolishedDioriteStairs::Shape::OuterRight).ID: return 9382; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedDioriteStairs::Half::Bottom, PolishedDioriteStairs::Shape::Straight).ID: return 9384; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedDioriteStairs::Half::Bottom, PolishedDioriteStairs::Shape::InnerLeft).ID: return 9386; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedDioriteStairs::Half::Bottom, PolishedDioriteStairs::Shape::InnerRight).ID: return 9388; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedDioriteStairs::Half::Bottom, PolishedDioriteStairs::Shape::OuterLeft).ID: return 9390; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedDioriteStairs::Half::Bottom, PolishedDioriteStairs::Shape::OuterRight).ID: return 9392; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedDioriteStairs::Half::Top, PolishedDioriteStairs::Shape::Straight).ID: return 9394; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedDioriteStairs::Half::Top, PolishedDioriteStairs::Shape::InnerLeft).ID: return 9396; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedDioriteStairs::Half::Top, PolishedDioriteStairs::Shape::InnerRight).ID: return 9398; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedDioriteStairs::Half::Top, PolishedDioriteStairs::Shape::OuterLeft).ID: return 9400; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedDioriteStairs::Half::Top, PolishedDioriteStairs::Shape::OuterRight).ID: return 9402; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedDioriteStairs::Half::Bottom, PolishedDioriteStairs::Shape::Straight).ID: return 9404; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedDioriteStairs::Half::Bottom, PolishedDioriteStairs::Shape::InnerLeft).ID: return 9406; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedDioriteStairs::Half::Bottom, PolishedDioriteStairs::Shape::InnerRight).ID: return 9408; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedDioriteStairs::Half::Bottom, PolishedDioriteStairs::Shape::OuterLeft).ID: return 9410; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedDioriteStairs::Half::Bottom, PolishedDioriteStairs::Shape::OuterRight).ID: return 9412; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_XM, PolishedDioriteStairs::Half::Top, PolishedDioriteStairs::Shape::Straight).ID: return 9414; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_XM, PolishedDioriteStairs::Half::Top, PolishedDioriteStairs::Shape::InnerLeft).ID: return 9416; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_XM, PolishedDioriteStairs::Half::Top, PolishedDioriteStairs::Shape::InnerRight).ID: return 9418; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_XM, PolishedDioriteStairs::Half::Top, PolishedDioriteStairs::Shape::OuterLeft).ID: return 9420; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_XM, PolishedDioriteStairs::Half::Top, PolishedDioriteStairs::Shape::OuterRight).ID: return 9422; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_XM, PolishedDioriteStairs::Half::Bottom, PolishedDioriteStairs::Shape::Straight).ID: return 9424; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_XM, PolishedDioriteStairs::Half::Bottom, PolishedDioriteStairs::Shape::InnerLeft).ID: return 9426; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_XM, PolishedDioriteStairs::Half::Bottom, PolishedDioriteStairs::Shape::InnerRight).ID: return 9428; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_XM, PolishedDioriteStairs::Half::Bottom, PolishedDioriteStairs::Shape::OuterLeft).ID: return 9430; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_XM, PolishedDioriteStairs::Half::Bottom, PolishedDioriteStairs::Shape::OuterRight).ID: return 9432; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_XP, PolishedDioriteStairs::Half::Top, PolishedDioriteStairs::Shape::Straight).ID: return 9434; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_XP, PolishedDioriteStairs::Half::Top, PolishedDioriteStairs::Shape::InnerLeft).ID: return 9436; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_XP, PolishedDioriteStairs::Half::Top, PolishedDioriteStairs::Shape::InnerRight).ID: return 9438; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_XP, PolishedDioriteStairs::Half::Top, PolishedDioriteStairs::Shape::OuterLeft).ID: return 9440; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_XP, PolishedDioriteStairs::Half::Top, PolishedDioriteStairs::Shape::OuterRight).ID: return 9442; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_XP, PolishedDioriteStairs::Half::Bottom, PolishedDioriteStairs::Shape::Straight).ID: return 9444; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_XP, PolishedDioriteStairs::Half::Bottom, PolishedDioriteStairs::Shape::InnerLeft).ID: return 9446; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_XP, PolishedDioriteStairs::Half::Bottom, PolishedDioriteStairs::Shape::InnerRight).ID: return 9448; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_XP, PolishedDioriteStairs::Half::Bottom, PolishedDioriteStairs::Shape::OuterLeft).ID: return 9450; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_XP, PolishedDioriteStairs::Half::Bottom, PolishedDioriteStairs::Shape::OuterRight).ID: return 9452; case PolishedGranite::PolishedGranite().ID: return 3; case PolishedGraniteSlab::PolishedGraniteSlab(PolishedGraniteSlab::Type::Top).ID: return 10254; case PolishedGraniteSlab::PolishedGraniteSlab(PolishedGraniteSlab::Type::Bottom).ID: return 10256; case PolishedGraniteSlab::PolishedGraniteSlab(PolishedGraniteSlab::Type::Double).ID: return 10258; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedGraniteStairs::Half::Top, PolishedGraniteStairs::Shape::Straight).ID: return 9134; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedGraniteStairs::Half::Top, PolishedGraniteStairs::Shape::InnerLeft).ID: return 9136; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedGraniteStairs::Half::Top, PolishedGraniteStairs::Shape::InnerRight).ID: return 9138; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedGraniteStairs::Half::Top, PolishedGraniteStairs::Shape::OuterLeft).ID: return 9140; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedGraniteStairs::Half::Top, PolishedGraniteStairs::Shape::OuterRight).ID: return 9142; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedGraniteStairs::Half::Bottom, PolishedGraniteStairs::Shape::Straight).ID: return 9144; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedGraniteStairs::Half::Bottom, PolishedGraniteStairs::Shape::InnerLeft).ID: return 9146; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedGraniteStairs::Half::Bottom, PolishedGraniteStairs::Shape::InnerRight).ID: return 9148; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedGraniteStairs::Half::Bottom, PolishedGraniteStairs::Shape::OuterLeft).ID: return 9150; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedGraniteStairs::Half::Bottom, PolishedGraniteStairs::Shape::OuterRight).ID: return 9152; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedGraniteStairs::Half::Top, PolishedGraniteStairs::Shape::Straight).ID: return 9154; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedGraniteStairs::Half::Top, PolishedGraniteStairs::Shape::InnerLeft).ID: return 9156; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedGraniteStairs::Half::Top, PolishedGraniteStairs::Shape::InnerRight).ID: return 9158; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedGraniteStairs::Half::Top, PolishedGraniteStairs::Shape::OuterLeft).ID: return 9160; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedGraniteStairs::Half::Top, PolishedGraniteStairs::Shape::OuterRight).ID: return 9162; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedGraniteStairs::Half::Bottom, PolishedGraniteStairs::Shape::Straight).ID: return 9164; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedGraniteStairs::Half::Bottom, PolishedGraniteStairs::Shape::InnerLeft).ID: return 9166; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedGraniteStairs::Half::Bottom, PolishedGraniteStairs::Shape::InnerRight).ID: return 9168; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedGraniteStairs::Half::Bottom, PolishedGraniteStairs::Shape::OuterLeft).ID: return 9170; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedGraniteStairs::Half::Bottom, PolishedGraniteStairs::Shape::OuterRight).ID: return 9172; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_XM, PolishedGraniteStairs::Half::Top, PolishedGraniteStairs::Shape::Straight).ID: return 9174; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_XM, PolishedGraniteStairs::Half::Top, PolishedGraniteStairs::Shape::InnerLeft).ID: return 9176; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_XM, PolishedGraniteStairs::Half::Top, PolishedGraniteStairs::Shape::InnerRight).ID: return 9178; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_XM, PolishedGraniteStairs::Half::Top, PolishedGraniteStairs::Shape::OuterLeft).ID: return 9180; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_XM, PolishedGraniteStairs::Half::Top, PolishedGraniteStairs::Shape::OuterRight).ID: return 9182; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_XM, PolishedGraniteStairs::Half::Bottom, PolishedGraniteStairs::Shape::Straight).ID: return 9184; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_XM, PolishedGraniteStairs::Half::Bottom, PolishedGraniteStairs::Shape::InnerLeft).ID: return 9186; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_XM, PolishedGraniteStairs::Half::Bottom, PolishedGraniteStairs::Shape::InnerRight).ID: return 9188; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_XM, PolishedGraniteStairs::Half::Bottom, PolishedGraniteStairs::Shape::OuterLeft).ID: return 9190; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_XM, PolishedGraniteStairs::Half::Bottom, PolishedGraniteStairs::Shape::OuterRight).ID: return 9192; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_XP, PolishedGraniteStairs::Half::Top, PolishedGraniteStairs::Shape::Straight).ID: return 9194; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_XP, PolishedGraniteStairs::Half::Top, PolishedGraniteStairs::Shape::InnerLeft).ID: return 9196; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_XP, PolishedGraniteStairs::Half::Top, PolishedGraniteStairs::Shape::InnerRight).ID: return 9198; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_XP, PolishedGraniteStairs::Half::Top, PolishedGraniteStairs::Shape::OuterLeft).ID: return 9200; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_XP, PolishedGraniteStairs::Half::Top, PolishedGraniteStairs::Shape::OuterRight).ID: return 9202; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_XP, PolishedGraniteStairs::Half::Bottom, PolishedGraniteStairs::Shape::Straight).ID: return 9204; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_XP, PolishedGraniteStairs::Half::Bottom, PolishedGraniteStairs::Shape::InnerLeft).ID: return 9206; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_XP, PolishedGraniteStairs::Half::Bottom, PolishedGraniteStairs::Shape::InnerRight).ID: return 9208; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_XP, PolishedGraniteStairs::Half::Bottom, PolishedGraniteStairs::Shape::OuterLeft).ID: return 9210; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_XP, PolishedGraniteStairs::Half::Bottom, PolishedGraniteStairs::Shape::OuterRight).ID: return 9212; case Poppy::Poppy().ID: return 1412; case Potatoes::Potatoes(0).ID: return 5802; case Potatoes::Potatoes(1).ID: return 5803; case Potatoes::Potatoes(2).ID: return 5804; case Potatoes::Potatoes(3).ID: return 5805; case Potatoes::Potatoes(4).ID: return 5806; case Potatoes::Potatoes(5).ID: return 5807; case Potatoes::Potatoes(6).ID: return 5808; case Potatoes::Potatoes(7).ID: return 5809; case PottedAcaciaSapling::PottedAcaciaSapling().ID: return 5774; case PottedAllium::PottedAllium().ID: return 5780; case PottedAzureBluet::PottedAzureBluet().ID: return 5781; case PottedBamboo::PottedBamboo().ID: return 9128; case PottedBirchSapling::PottedBirchSapling().ID: return 5772; case PottedBlueOrchid::PottedBlueOrchid().ID: return 5779; case PottedBrownMushroom::PottedBrownMushroom().ID: return 5791; case PottedCactus::PottedCactus().ID: return 5793; case PottedCornflower::PottedCornflower().ID: return 5787; case PottedDandelion::PottedDandelion().ID: return 5777; case PottedDarkOakSapling::PottedDarkOakSapling().ID: return 5775; case PottedDeadBush::PottedDeadBush().ID: return 5792; case PottedFern::PottedFern().ID: return 5776; case PottedJungleSapling::PottedJungleSapling().ID: return 5773; case PottedLilyOfTheValley::PottedLilyOfTheValley().ID: return 5788; case PottedOakSapling::PottedOakSapling().ID: return 5770; case PottedOrangeTulip::PottedOrangeTulip().ID: return 5783; case PottedOxeyeDaisy::PottedOxeyeDaisy().ID: return 5786; case PottedPinkTulip::PottedPinkTulip().ID: return 5785; case PottedPoppy::PottedPoppy().ID: return 5778; case PottedRedMushroom::PottedRedMushroom().ID: return 5790; case PottedRedTulip::PottedRedTulip().ID: return 5782; case PottedSpruceSapling::PottedSpruceSapling().ID: return 5771; case PottedWhiteTulip::PottedWhiteTulip().ID: return 5784; case PottedWitherRose::PottedWitherRose().ID: return 5789; case PoweredRail::PoweredRail(true, PoweredRail::Shape::NorthSouth).ID: return 1304; case PoweredRail::PoweredRail(true, PoweredRail::Shape::EastWest).ID: return 1305; case PoweredRail::PoweredRail(true, PoweredRail::Shape::AscendingEast).ID: return 1306; case PoweredRail::PoweredRail(true, PoweredRail::Shape::AscendingWest).ID: return 1307; case PoweredRail::PoweredRail(true, PoweredRail::Shape::AscendingNorth).ID: return 1308; case PoweredRail::PoweredRail(true, PoweredRail::Shape::AscendingSouth).ID: return 1309; case PoweredRail::PoweredRail(false, PoweredRail::Shape::NorthSouth).ID: return 1310; case PoweredRail::PoweredRail(false, PoweredRail::Shape::EastWest).ID: return 1311; case PoweredRail::PoweredRail(false, PoweredRail::Shape::AscendingEast).ID: return 1312; case PoweredRail::PoweredRail(false, PoweredRail::Shape::AscendingWest).ID: return 1313; case PoweredRail::PoweredRail(false, PoweredRail::Shape::AscendingNorth).ID: return 1314; case PoweredRail::PoweredRail(false, PoweredRail::Shape::AscendingSouth).ID: return 1315; case Prismarine::Prismarine().ID: return 7065; case PrismarineBrickSlab::PrismarineBrickSlab(PrismarineBrickSlab::Type::Top).ID: return 7315; case PrismarineBrickSlab::PrismarineBrickSlab(PrismarineBrickSlab::Type::Bottom).ID: return 7317; case PrismarineBrickSlab::PrismarineBrickSlab(PrismarineBrickSlab::Type::Double).ID: return 7319; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::Straight).ID: return 7149; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::InnerLeft).ID: return 7151; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::InnerRight).ID: return 7153; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::OuterLeft).ID: return 7155; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::OuterRight).ID: return 7157; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::Straight).ID: return 7159; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::InnerLeft).ID: return 7161; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::InnerRight).ID: return 7163; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::OuterLeft).ID: return 7165; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::OuterRight).ID: return 7167; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::Straight).ID: return 7169; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::InnerLeft).ID: return 7171; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::InnerRight).ID: return 7173; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::OuterLeft).ID: return 7175; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::OuterRight).ID: return 7177; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::Straight).ID: return 7179; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::InnerLeft).ID: return 7181; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::InnerRight).ID: return 7183; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::OuterLeft).ID: return 7185; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::OuterRight).ID: return 7187; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XM, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::Straight).ID: return 7189; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XM, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::InnerLeft).ID: return 7191; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XM, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::InnerRight).ID: return 7193; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XM, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::OuterLeft).ID: return 7195; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XM, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::OuterRight).ID: return 7197; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XM, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::Straight).ID: return 7199; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XM, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::InnerLeft).ID: return 7201; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XM, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::InnerRight).ID: return 7203; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XM, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::OuterLeft).ID: return 7205; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XM, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::OuterRight).ID: return 7207; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XP, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::Straight).ID: return 7209; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XP, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::InnerLeft).ID: return 7211; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XP, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::InnerRight).ID: return 7213; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XP, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::OuterLeft).ID: return 7215; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XP, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::OuterRight).ID: return 7217; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XP, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::Straight).ID: return 7219; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XP, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::InnerLeft).ID: return 7221; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XP, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::InnerRight).ID: return 7223; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XP, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::OuterLeft).ID: return 7225; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XP, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::OuterRight).ID: return 7227; case PrismarineBricks::PrismarineBricks().ID: return 7066; case PrismarineSlab::PrismarineSlab(PrismarineSlab::Type::Top).ID: return 7309; case PrismarineSlab::PrismarineSlab(PrismarineSlab::Type::Bottom).ID: return 7311; case PrismarineSlab::PrismarineSlab(PrismarineSlab::Type::Double).ID: return 7313; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineStairs::Half::Top, PrismarineStairs::Shape::Straight).ID: return 7069; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineStairs::Half::Top, PrismarineStairs::Shape::InnerLeft).ID: return 7071; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineStairs::Half::Top, PrismarineStairs::Shape::InnerRight).ID: return 7073; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineStairs::Half::Top, PrismarineStairs::Shape::OuterLeft).ID: return 7075; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineStairs::Half::Top, PrismarineStairs::Shape::OuterRight).ID: return 7077; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::Straight).ID: return 7079; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::InnerLeft).ID: return 7081; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::InnerRight).ID: return 7083; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::OuterLeft).ID: return 7085; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::OuterRight).ID: return 7087; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineStairs::Half::Top, PrismarineStairs::Shape::Straight).ID: return 7089; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineStairs::Half::Top, PrismarineStairs::Shape::InnerLeft).ID: return 7091; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineStairs::Half::Top, PrismarineStairs::Shape::InnerRight).ID: return 7093; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineStairs::Half::Top, PrismarineStairs::Shape::OuterLeft).ID: return 7095; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineStairs::Half::Top, PrismarineStairs::Shape::OuterRight).ID: return 7097; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::Straight).ID: return 7099; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::InnerLeft).ID: return 7101; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::InnerRight).ID: return 7103; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::OuterLeft).ID: return 7105; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::OuterRight).ID: return 7107; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XM, PrismarineStairs::Half::Top, PrismarineStairs::Shape::Straight).ID: return 7109; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XM, PrismarineStairs::Half::Top, PrismarineStairs::Shape::InnerLeft).ID: return 7111; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XM, PrismarineStairs::Half::Top, PrismarineStairs::Shape::InnerRight).ID: return 7113; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XM, PrismarineStairs::Half::Top, PrismarineStairs::Shape::OuterLeft).ID: return 7115; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XM, PrismarineStairs::Half::Top, PrismarineStairs::Shape::OuterRight).ID: return 7117; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XM, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::Straight).ID: return 7119; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XM, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::InnerLeft).ID: return 7121; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XM, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::InnerRight).ID: return 7123; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XM, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::OuterLeft).ID: return 7125; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XM, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::OuterRight).ID: return 7127; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XP, PrismarineStairs::Half::Top, PrismarineStairs::Shape::Straight).ID: return 7129; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XP, PrismarineStairs::Half::Top, PrismarineStairs::Shape::InnerLeft).ID: return 7131; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XP, PrismarineStairs::Half::Top, PrismarineStairs::Shape::InnerRight).ID: return 7133; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XP, PrismarineStairs::Half::Top, PrismarineStairs::Shape::OuterLeft).ID: return 7135; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XP, PrismarineStairs::Half::Top, PrismarineStairs::Shape::OuterRight).ID: return 7137; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XP, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::Straight).ID: return 7139; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XP, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::InnerLeft).ID: return 7141; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XP, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::InnerRight).ID: return 7143; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XP, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::OuterLeft).ID: return 7145; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XP, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::OuterRight).ID: return 7147; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::Low, PrismarineWall::South::Low, true, PrismarineWall::West::Low).ID: return 10397; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::Low, PrismarineWall::South::Low, true, PrismarineWall::West::None).ID: return 10398; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::Low, PrismarineWall::South::Low, false, PrismarineWall::West::Low).ID: return 10401; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::Low, PrismarineWall::South::Low, false, PrismarineWall::West::None).ID: return 10402; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::Low, PrismarineWall::South::None, true, PrismarineWall::West::Low).ID: return 10405; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::Low, PrismarineWall::South::None, true, PrismarineWall::West::None).ID: return 10406; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::Low, PrismarineWall::South::None, false, PrismarineWall::West::Low).ID: return 10409; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::Low, PrismarineWall::South::None, false, PrismarineWall::West::None).ID: return 10410; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::None, PrismarineWall::South::Low, true, PrismarineWall::West::Low).ID: return 10413; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::None, PrismarineWall::South::Low, true, PrismarineWall::West::None).ID: return 10414; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::None, PrismarineWall::South::Low, false, PrismarineWall::West::Low).ID: return 10417; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::None, PrismarineWall::South::Low, false, PrismarineWall::West::None).ID: return 10418; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::None, PrismarineWall::South::None, true, PrismarineWall::West::Low).ID: return 10421; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::None, PrismarineWall::South::None, true, PrismarineWall::West::None).ID: return 10422; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::None, PrismarineWall::South::None, false, PrismarineWall::West::Low).ID: return 10425; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::None, PrismarineWall::South::None, false, PrismarineWall::West::None).ID: return 10426; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::Low, PrismarineWall::South::Low, true, PrismarineWall::West::Low).ID: return 10429; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::Low, PrismarineWall::South::Low, true, PrismarineWall::West::None).ID: return 10430; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::Low, PrismarineWall::South::Low, false, PrismarineWall::West::Low).ID: return 10433; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::Low, PrismarineWall::South::Low, false, PrismarineWall::West::None).ID: return 10434; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::Low, PrismarineWall::South::None, true, PrismarineWall::West::Low).ID: return 10437; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::Low, PrismarineWall::South::None, true, PrismarineWall::West::None).ID: return 10438; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::Low, PrismarineWall::South::None, false, PrismarineWall::West::Low).ID: return 10441; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::Low, PrismarineWall::South::None, false, PrismarineWall::West::None).ID: return 10442; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::None, PrismarineWall::South::Low, true, PrismarineWall::West::Low).ID: return 10445; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::None, PrismarineWall::South::Low, true, PrismarineWall::West::None).ID: return 10446; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::None, PrismarineWall::South::Low, false, PrismarineWall::West::Low).ID: return 10449; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::None, PrismarineWall::South::Low, false, PrismarineWall::West::None).ID: return 10450; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::None, PrismarineWall::South::None, true, PrismarineWall::West::Low).ID: return 10453; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::None, PrismarineWall::South::None, true, PrismarineWall::West::None).ID: return 10454; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::None, PrismarineWall::South::None, false, PrismarineWall::West::Low).ID: return 10457; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::None, PrismarineWall::South::None, false, PrismarineWall::West::None).ID: return 10458; case Pumpkin::Pumpkin().ID: return 3996; case PumpkinStem::PumpkinStem(0).ID: return 4756; case PumpkinStem::PumpkinStem(1).ID: return 4757; case PumpkinStem::PumpkinStem(2).ID: return 4758; case PumpkinStem::PumpkinStem(3).ID: return 4759; case PumpkinStem::PumpkinStem(4).ID: return 4760; case PumpkinStem::PumpkinStem(5).ID: return 4761; case PumpkinStem::PumpkinStem(6).ID: return 4762; case PumpkinStem::PumpkinStem(7).ID: return 4763; case PurpleBanner::PurpleBanner(0).ID: return 7521; case PurpleBanner::PurpleBanner(1).ID: return 7522; case PurpleBanner::PurpleBanner(2).ID: return 7523; case PurpleBanner::PurpleBanner(3).ID: return 7524; case PurpleBanner::PurpleBanner(4).ID: return 7525; case PurpleBanner::PurpleBanner(5).ID: return 7526; case PurpleBanner::PurpleBanner(6).ID: return 7527; case PurpleBanner::PurpleBanner(7).ID: return 7528; case PurpleBanner::PurpleBanner(8).ID: return 7529; case PurpleBanner::PurpleBanner(9).ID: return 7530; case PurpleBanner::PurpleBanner(10).ID: return 7531; case PurpleBanner::PurpleBanner(11).ID: return 7532; case PurpleBanner::PurpleBanner(12).ID: return 7533; case PurpleBanner::PurpleBanner(13).ID: return 7534; case PurpleBanner::PurpleBanner(14).ID: return 7535; case PurpleBanner::PurpleBanner(15).ID: return 7536; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_ZM, true, PurpleBed::Part::Head).ID: return 1208; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_ZM, true, PurpleBed::Part::Foot).ID: return 1209; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_ZM, false, PurpleBed::Part::Head).ID: return 1210; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_ZM, false, PurpleBed::Part::Foot).ID: return 1211; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_ZP, true, PurpleBed::Part::Head).ID: return 1212; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_ZP, true, PurpleBed::Part::Foot).ID: return 1213; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_ZP, false, PurpleBed::Part::Head).ID: return 1214; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_ZP, false, PurpleBed::Part::Foot).ID: return 1215; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_XM, true, PurpleBed::Part::Head).ID: return 1216; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_XM, true, PurpleBed::Part::Foot).ID: return 1217; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_XM, false, PurpleBed::Part::Head).ID: return 1218; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_XM, false, PurpleBed::Part::Foot).ID: return 1219; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_XP, true, PurpleBed::Part::Head).ID: return 1220; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_XP, true, PurpleBed::Part::Foot).ID: return 1221; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_XP, false, PurpleBed::Part::Head).ID: return 1222; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_XP, false, PurpleBed::Part::Foot).ID: return 1223; case PurpleCarpet::PurpleCarpet().ID: return 7340; case PurpleConcrete::PurpleConcrete().ID: return 8912; case PurpleConcretePowder::PurpleConcretePowder().ID: return 8928; case PurpleGlazedTerracotta::PurpleGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 8878; case PurpleGlazedTerracotta::PurpleGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 8879; case PurpleGlazedTerracotta::PurpleGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 8880; case PurpleGlazedTerracotta::PurpleGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 8881; case PurpleShulkerBox::PurpleShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 8802; case PurpleShulkerBox::PurpleShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 8803; case PurpleShulkerBox::PurpleShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 8804; case PurpleShulkerBox::PurpleShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 8805; case PurpleShulkerBox::PurpleShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 8806; case PurpleShulkerBox::PurpleShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 8807; case PurpleStainedGlass::PurpleStainedGlass().ID: return 4091; case PurpleStainedGlassPane::PurpleStainedGlassPane(true, true, true, true).ID: return 6649; case PurpleStainedGlassPane::PurpleStainedGlassPane(true, true, true, false).ID: return 6650; case PurpleStainedGlassPane::PurpleStainedGlassPane(true, true, false, true).ID: return 6653; case PurpleStainedGlassPane::PurpleStainedGlassPane(true, true, false, false).ID: return 6654; case PurpleStainedGlassPane::PurpleStainedGlassPane(true, false, true, true).ID: return 6657; case PurpleStainedGlassPane::PurpleStainedGlassPane(true, false, true, false).ID: return 6658; case PurpleStainedGlassPane::PurpleStainedGlassPane(true, false, false, true).ID: return 6661; case PurpleStainedGlassPane::PurpleStainedGlassPane(true, false, false, false).ID: return 6662; case PurpleStainedGlassPane::PurpleStainedGlassPane(false, true, true, true).ID: return 6665; case PurpleStainedGlassPane::PurpleStainedGlassPane(false, true, true, false).ID: return 6666; case PurpleStainedGlassPane::PurpleStainedGlassPane(false, true, false, true).ID: return 6669; case PurpleStainedGlassPane::PurpleStainedGlassPane(false, true, false, false).ID: return 6670; case PurpleStainedGlassPane::PurpleStainedGlassPane(false, false, true, true).ID: return 6673; case PurpleStainedGlassPane::PurpleStainedGlassPane(false, false, true, false).ID: return 6674; case PurpleStainedGlassPane::PurpleStainedGlassPane(false, false, false, true).ID: return 6677; case PurpleStainedGlassPane::PurpleStainedGlassPane(false, false, false, false).ID: return 6678; case PurpleTerracotta::PurpleTerracotta().ID: return 6321; case PurpleWallBanner::PurpleWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 7657; case PurpleWallBanner::PurpleWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 7658; case PurpleWallBanner::PurpleWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 7659; case PurpleWallBanner::PurpleWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 7660; case PurpleWool::PurpleWool().ID: return 1393; case PurpurBlock::PurpurBlock().ID: return 8598; case PurpurPillar::PurpurPillar(PurpurPillar::Axis::X).ID: return 8599; case PurpurPillar::PurpurPillar(PurpurPillar::Axis::Y).ID: return 8600; case PurpurPillar::PurpurPillar(PurpurPillar::Axis::Z).ID: return 8601; case PurpurSlab::PurpurSlab(PurpurSlab::Type::Top).ID: return 7873; case PurpurSlab::PurpurSlab(PurpurSlab::Type::Bottom).ID: return 7875; case PurpurSlab::PurpurSlab(PurpurSlab::Type::Double).ID: return 7877; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZM, PurpurStairs::Half::Top, PurpurStairs::Shape::Straight).ID: return 8603; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZM, PurpurStairs::Half::Top, PurpurStairs::Shape::InnerLeft).ID: return 8605; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZM, PurpurStairs::Half::Top, PurpurStairs::Shape::InnerRight).ID: return 8607; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZM, PurpurStairs::Half::Top, PurpurStairs::Shape::OuterLeft).ID: return 8609; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZM, PurpurStairs::Half::Top, PurpurStairs::Shape::OuterRight).ID: return 8611; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZM, PurpurStairs::Half::Bottom, PurpurStairs::Shape::Straight).ID: return 8613; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZM, PurpurStairs::Half::Bottom, PurpurStairs::Shape::InnerLeft).ID: return 8615; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZM, PurpurStairs::Half::Bottom, PurpurStairs::Shape::InnerRight).ID: return 8617; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZM, PurpurStairs::Half::Bottom, PurpurStairs::Shape::OuterLeft).ID: return 8619; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZM, PurpurStairs::Half::Bottom, PurpurStairs::Shape::OuterRight).ID: return 8621; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZP, PurpurStairs::Half::Top, PurpurStairs::Shape::Straight).ID: return 8623; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZP, PurpurStairs::Half::Top, PurpurStairs::Shape::InnerLeft).ID: return 8625; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZP, PurpurStairs::Half::Top, PurpurStairs::Shape::InnerRight).ID: return 8627; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZP, PurpurStairs::Half::Top, PurpurStairs::Shape::OuterLeft).ID: return 8629; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZP, PurpurStairs::Half::Top, PurpurStairs::Shape::OuterRight).ID: return 8631; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZP, PurpurStairs::Half::Bottom, PurpurStairs::Shape::Straight).ID: return 8633; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZP, PurpurStairs::Half::Bottom, PurpurStairs::Shape::InnerLeft).ID: return 8635; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZP, PurpurStairs::Half::Bottom, PurpurStairs::Shape::InnerRight).ID: return 8637; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZP, PurpurStairs::Half::Bottom, PurpurStairs::Shape::OuterLeft).ID: return 8639; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZP, PurpurStairs::Half::Bottom, PurpurStairs::Shape::OuterRight).ID: return 8641; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XM, PurpurStairs::Half::Top, PurpurStairs::Shape::Straight).ID: return 8643; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XM, PurpurStairs::Half::Top, PurpurStairs::Shape::InnerLeft).ID: return 8645; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XM, PurpurStairs::Half::Top, PurpurStairs::Shape::InnerRight).ID: return 8647; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XM, PurpurStairs::Half::Top, PurpurStairs::Shape::OuterLeft).ID: return 8649; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XM, PurpurStairs::Half::Top, PurpurStairs::Shape::OuterRight).ID: return 8651; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XM, PurpurStairs::Half::Bottom, PurpurStairs::Shape::Straight).ID: return 8653; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XM, PurpurStairs::Half::Bottom, PurpurStairs::Shape::InnerLeft).ID: return 8655; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XM, PurpurStairs::Half::Bottom, PurpurStairs::Shape::InnerRight).ID: return 8657; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XM, PurpurStairs::Half::Bottom, PurpurStairs::Shape::OuterLeft).ID: return 8659; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XM, PurpurStairs::Half::Bottom, PurpurStairs::Shape::OuterRight).ID: return 8661; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XP, PurpurStairs::Half::Top, PurpurStairs::Shape::Straight).ID: return 8663; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XP, PurpurStairs::Half::Top, PurpurStairs::Shape::InnerLeft).ID: return 8665; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XP, PurpurStairs::Half::Top, PurpurStairs::Shape::InnerRight).ID: return 8667; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XP, PurpurStairs::Half::Top, PurpurStairs::Shape::OuterLeft).ID: return 8669; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XP, PurpurStairs::Half::Top, PurpurStairs::Shape::OuterRight).ID: return 8671; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XP, PurpurStairs::Half::Bottom, PurpurStairs::Shape::Straight).ID: return 8673; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XP, PurpurStairs::Half::Bottom, PurpurStairs::Shape::InnerLeft).ID: return 8675; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XP, PurpurStairs::Half::Bottom, PurpurStairs::Shape::InnerRight).ID: return 8677; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XP, PurpurStairs::Half::Bottom, PurpurStairs::Shape::OuterLeft).ID: return 8679; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XP, PurpurStairs::Half::Bottom, PurpurStairs::Shape::OuterRight).ID: return 8681; case QuartzBlock::QuartzBlock().ID: return 6202; case QuartzPillar::QuartzPillar(QuartzPillar::Axis::X).ID: return 6204; case QuartzPillar::QuartzPillar(QuartzPillar::Axis::Y).ID: return 6205; case QuartzPillar::QuartzPillar(QuartzPillar::Axis::Z).ID: return 6206; case QuartzSlab::QuartzSlab(QuartzSlab::Type::Top).ID: return 7855; case QuartzSlab::QuartzSlab(QuartzSlab::Type::Bottom).ID: return 7857; case QuartzSlab::QuartzSlab(QuartzSlab::Type::Double).ID: return 7859; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZM, QuartzStairs::Half::Top, QuartzStairs::Shape::Straight).ID: return 6208; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZM, QuartzStairs::Half::Top, QuartzStairs::Shape::InnerLeft).ID: return 6210; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZM, QuartzStairs::Half::Top, QuartzStairs::Shape::InnerRight).ID: return 6212; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZM, QuartzStairs::Half::Top, QuartzStairs::Shape::OuterLeft).ID: return 6214; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZM, QuartzStairs::Half::Top, QuartzStairs::Shape::OuterRight).ID: return 6216; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZM, QuartzStairs::Half::Bottom, QuartzStairs::Shape::Straight).ID: return 6218; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZM, QuartzStairs::Half::Bottom, QuartzStairs::Shape::InnerLeft).ID: return 6220; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZM, QuartzStairs::Half::Bottom, QuartzStairs::Shape::InnerRight).ID: return 6222; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZM, QuartzStairs::Half::Bottom, QuartzStairs::Shape::OuterLeft).ID: return 6224; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZM, QuartzStairs::Half::Bottom, QuartzStairs::Shape::OuterRight).ID: return 6226; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZP, QuartzStairs::Half::Top, QuartzStairs::Shape::Straight).ID: return 6228; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZP, QuartzStairs::Half::Top, QuartzStairs::Shape::InnerLeft).ID: return 6230; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZP, QuartzStairs::Half::Top, QuartzStairs::Shape::InnerRight).ID: return 6232; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZP, QuartzStairs::Half::Top, QuartzStairs::Shape::OuterLeft).ID: return 6234; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZP, QuartzStairs::Half::Top, QuartzStairs::Shape::OuterRight).ID: return 6236; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZP, QuartzStairs::Half::Bottom, QuartzStairs::Shape::Straight).ID: return 6238; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZP, QuartzStairs::Half::Bottom, QuartzStairs::Shape::InnerLeft).ID: return 6240; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZP, QuartzStairs::Half::Bottom, QuartzStairs::Shape::InnerRight).ID: return 6242; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZP, QuartzStairs::Half::Bottom, QuartzStairs::Shape::OuterLeft).ID: return 6244; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZP, QuartzStairs::Half::Bottom, QuartzStairs::Shape::OuterRight).ID: return 6246; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XM, QuartzStairs::Half::Top, QuartzStairs::Shape::Straight).ID: return 6248; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XM, QuartzStairs::Half::Top, QuartzStairs::Shape::InnerLeft).ID: return 6250; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XM, QuartzStairs::Half::Top, QuartzStairs::Shape::InnerRight).ID: return 6252; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XM, QuartzStairs::Half::Top, QuartzStairs::Shape::OuterLeft).ID: return 6254; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XM, QuartzStairs::Half::Top, QuartzStairs::Shape::OuterRight).ID: return 6256; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XM, QuartzStairs::Half::Bottom, QuartzStairs::Shape::Straight).ID: return 6258; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XM, QuartzStairs::Half::Bottom, QuartzStairs::Shape::InnerLeft).ID: return 6260; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XM, QuartzStairs::Half::Bottom, QuartzStairs::Shape::InnerRight).ID: return 6262; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XM, QuartzStairs::Half::Bottom, QuartzStairs::Shape::OuterLeft).ID: return 6264; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XM, QuartzStairs::Half::Bottom, QuartzStairs::Shape::OuterRight).ID: return 6266; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XP, QuartzStairs::Half::Top, QuartzStairs::Shape::Straight).ID: return 6268; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XP, QuartzStairs::Half::Top, QuartzStairs::Shape::InnerLeft).ID: return 6270; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XP, QuartzStairs::Half::Top, QuartzStairs::Shape::InnerRight).ID: return 6272; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XP, QuartzStairs::Half::Top, QuartzStairs::Shape::OuterLeft).ID: return 6274; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XP, QuartzStairs::Half::Top, QuartzStairs::Shape::OuterRight).ID: return 6276; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XP, QuartzStairs::Half::Bottom, QuartzStairs::Shape::Straight).ID: return 6278; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XP, QuartzStairs::Half::Bottom, QuartzStairs::Shape::InnerLeft).ID: return 6280; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XP, QuartzStairs::Half::Bottom, QuartzStairs::Shape::InnerRight).ID: return 6282; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XP, QuartzStairs::Half::Bottom, QuartzStairs::Shape::OuterLeft).ID: return 6284; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XP, QuartzStairs::Half::Bottom, QuartzStairs::Shape::OuterRight).ID: return 6286; case Rail::Rail(Rail::Shape::NorthSouth).ID: return 3643; case Rail::Rail(Rail::Shape::EastWest).ID: return 3644; case Rail::Rail(Rail::Shape::AscendingEast).ID: return 3645; case Rail::Rail(Rail::Shape::AscendingWest).ID: return 3646; case Rail::Rail(Rail::Shape::AscendingNorth).ID: return 3647; case Rail::Rail(Rail::Shape::AscendingSouth).ID: return 3648; case Rail::Rail(Rail::Shape::SouthEast).ID: return 3649; case Rail::Rail(Rail::Shape::SouthWest).ID: return 3650; case Rail::Rail(Rail::Shape::NorthWest).ID: return 3651; case Rail::Rail(Rail::Shape::NorthEast).ID: return 3652; case RedBanner::RedBanner(0).ID: return 7585; case RedBanner::RedBanner(1).ID: return 7586; case RedBanner::RedBanner(2).ID: return 7587; case RedBanner::RedBanner(3).ID: return 7588; case RedBanner::RedBanner(4).ID: return 7589; case RedBanner::RedBanner(5).ID: return 7590; case RedBanner::RedBanner(6).ID: return 7591; case RedBanner::RedBanner(7).ID: return 7592; case RedBanner::RedBanner(8).ID: return 7593; case RedBanner::RedBanner(9).ID: return 7594; case RedBanner::RedBanner(10).ID: return 7595; case RedBanner::RedBanner(11).ID: return 7596; case RedBanner::RedBanner(12).ID: return 7597; case RedBanner::RedBanner(13).ID: return 7598; case RedBanner::RedBanner(14).ID: return 7599; case RedBanner::RedBanner(15).ID: return 7600; case RedBed::RedBed(eBlockFace::BLOCK_FACE_ZM, true, RedBed::Part::Head).ID: return 1272; case RedBed::RedBed(eBlockFace::BLOCK_FACE_ZM, true, RedBed::Part::Foot).ID: return 1273; case RedBed::RedBed(eBlockFace::BLOCK_FACE_ZM, false, RedBed::Part::Head).ID: return 1274; case RedBed::RedBed(eBlockFace::BLOCK_FACE_ZM, false, RedBed::Part::Foot).ID: return 1275; case RedBed::RedBed(eBlockFace::BLOCK_FACE_ZP, true, RedBed::Part::Head).ID: return 1276; case RedBed::RedBed(eBlockFace::BLOCK_FACE_ZP, true, RedBed::Part::Foot).ID: return 1277; case RedBed::RedBed(eBlockFace::BLOCK_FACE_ZP, false, RedBed::Part::Head).ID: return 1278; case RedBed::RedBed(eBlockFace::BLOCK_FACE_ZP, false, RedBed::Part::Foot).ID: return 1279; case RedBed::RedBed(eBlockFace::BLOCK_FACE_XM, true, RedBed::Part::Head).ID: return 1280; case RedBed::RedBed(eBlockFace::BLOCK_FACE_XM, true, RedBed::Part::Foot).ID: return 1281; case RedBed::RedBed(eBlockFace::BLOCK_FACE_XM, false, RedBed::Part::Head).ID: return 1282; case RedBed::RedBed(eBlockFace::BLOCK_FACE_XM, false, RedBed::Part::Foot).ID: return 1283; case RedBed::RedBed(eBlockFace::BLOCK_FACE_XP, true, RedBed::Part::Head).ID: return 1284; case RedBed::RedBed(eBlockFace::BLOCK_FACE_XP, true, RedBed::Part::Foot).ID: return 1285; case RedBed::RedBed(eBlockFace::BLOCK_FACE_XP, false, RedBed::Part::Head).ID: return 1286; case RedBed::RedBed(eBlockFace::BLOCK_FACE_XP, false, RedBed::Part::Foot).ID: return 1287; case RedCarpet::RedCarpet().ID: return 7344; case RedConcrete::RedConcrete().ID: return 8916; case RedConcretePowder::RedConcretePowder().ID: return 8932; case RedGlazedTerracotta::RedGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 8894; case RedGlazedTerracotta::RedGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 8895; case RedGlazedTerracotta::RedGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 8896; case RedGlazedTerracotta::RedGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 8897; case RedMushroom::RedMushroom().ID: return 1425; case RedMushroomBlock::RedMushroomBlock(true, true, true, true, true, true).ID: return 4555; case RedMushroomBlock::RedMushroomBlock(true, true, true, true, true, false).ID: return 4556; case RedMushroomBlock::RedMushroomBlock(true, true, true, true, false, true).ID: return 4557; case RedMushroomBlock::RedMushroomBlock(true, true, true, true, false, false).ID: return 4558; case RedMushroomBlock::RedMushroomBlock(true, true, true, false, true, true).ID: return 4559; case RedMushroomBlock::RedMushroomBlock(true, true, true, false, true, false).ID: return 4560; case RedMushroomBlock::RedMushroomBlock(true, true, true, false, false, true).ID: return 4561; case RedMushroomBlock::RedMushroomBlock(true, true, true, false, false, false).ID: return 4562; case RedMushroomBlock::RedMushroomBlock(true, true, false, true, true, true).ID: return 4563; case RedMushroomBlock::RedMushroomBlock(true, true, false, true, true, false).ID: return 4564; case RedMushroomBlock::RedMushroomBlock(true, true, false, true, false, true).ID: return 4565; case RedMushroomBlock::RedMushroomBlock(true, true, false, true, false, false).ID: return 4566; case RedMushroomBlock::RedMushroomBlock(true, true, false, false, true, true).ID: return 4567; case RedMushroomBlock::RedMushroomBlock(true, true, false, false, true, false).ID: return 4568; case RedMushroomBlock::RedMushroomBlock(true, true, false, false, false, true).ID: return 4569; case RedMushroomBlock::RedMushroomBlock(true, true, false, false, false, false).ID: return 4570; case RedMushroomBlock::RedMushroomBlock(true, false, true, true, true, true).ID: return 4571; case RedMushroomBlock::RedMushroomBlock(true, false, true, true, true, false).ID: return 4572; case RedMushroomBlock::RedMushroomBlock(true, false, true, true, false, true).ID: return 4573; case RedMushroomBlock::RedMushroomBlock(true, false, true, true, false, false).ID: return 4574; case RedMushroomBlock::RedMushroomBlock(true, false, true, false, true, true).ID: return 4575; case RedMushroomBlock::RedMushroomBlock(true, false, true, false, true, false).ID: return 4576; case RedMushroomBlock::RedMushroomBlock(true, false, true, false, false, true).ID: return 4577; case RedMushroomBlock::RedMushroomBlock(true, false, true, false, false, false).ID: return 4578; case RedMushroomBlock::RedMushroomBlock(true, false, false, true, true, true).ID: return 4579; case RedMushroomBlock::RedMushroomBlock(true, false, false, true, true, false).ID: return 4580; case RedMushroomBlock::RedMushroomBlock(true, false, false, true, false, true).ID: return 4581; case RedMushroomBlock::RedMushroomBlock(true, false, false, true, false, false).ID: return 4582; case RedMushroomBlock::RedMushroomBlock(true, false, false, false, true, true).ID: return 4583; case RedMushroomBlock::RedMushroomBlock(true, false, false, false, true, false).ID: return 4584; case RedMushroomBlock::RedMushroomBlock(true, false, false, false, false, true).ID: return 4585; case RedMushroomBlock::RedMushroomBlock(true, false, false, false, false, false).ID: return 4586; case RedMushroomBlock::RedMushroomBlock(false, true, true, true, true, true).ID: return 4587; case RedMushroomBlock::RedMushroomBlock(false, true, true, true, true, false).ID: return 4588; case RedMushroomBlock::RedMushroomBlock(false, true, true, true, false, true).ID: return 4589; case RedMushroomBlock::RedMushroomBlock(false, true, true, true, false, false).ID: return 4590; case RedMushroomBlock::RedMushroomBlock(false, true, true, false, true, true).ID: return 4591; case RedMushroomBlock::RedMushroomBlock(false, true, true, false, true, false).ID: return 4592; case RedMushroomBlock::RedMushroomBlock(false, true, true, false, false, true).ID: return 4593; case RedMushroomBlock::RedMushroomBlock(false, true, true, false, false, false).ID: return 4594; case RedMushroomBlock::RedMushroomBlock(false, true, false, true, true, true).ID: return 4595; case RedMushroomBlock::RedMushroomBlock(false, true, false, true, true, false).ID: return 4596; case RedMushroomBlock::RedMushroomBlock(false, true, false, true, false, true).ID: return 4597; case RedMushroomBlock::RedMushroomBlock(false, true, false, true, false, false).ID: return 4598; case RedMushroomBlock::RedMushroomBlock(false, true, false, false, true, true).ID: return 4599; case RedMushroomBlock::RedMushroomBlock(false, true, false, false, true, false).ID: return 4600; case RedMushroomBlock::RedMushroomBlock(false, true, false, false, false, true).ID: return 4601; case RedMushroomBlock::RedMushroomBlock(false, true, false, false, false, false).ID: return 4602; case RedMushroomBlock::RedMushroomBlock(false, false, true, true, true, true).ID: return 4603; case RedMushroomBlock::RedMushroomBlock(false, false, true, true, true, false).ID: return 4604; case RedMushroomBlock::RedMushroomBlock(false, false, true, true, false, true).ID: return 4605; case RedMushroomBlock::RedMushroomBlock(false, false, true, true, false, false).ID: return 4606; case RedMushroomBlock::RedMushroomBlock(false, false, true, false, true, true).ID: return 4607; case RedMushroomBlock::RedMushroomBlock(false, false, true, false, true, false).ID: return 4608; case RedMushroomBlock::RedMushroomBlock(false, false, true, false, false, true).ID: return 4609; case RedMushroomBlock::RedMushroomBlock(false, false, true, false, false, false).ID: return 4610; case RedMushroomBlock::RedMushroomBlock(false, false, false, true, true, true).ID: return 4611; case RedMushroomBlock::RedMushroomBlock(false, false, false, true, true, false).ID: return 4612; case RedMushroomBlock::RedMushroomBlock(false, false, false, true, false, true).ID: return 4613; case RedMushroomBlock::RedMushroomBlock(false, false, false, true, false, false).ID: return 4614; case RedMushroomBlock::RedMushroomBlock(false, false, false, false, true, true).ID: return 4615; case RedMushroomBlock::RedMushroomBlock(false, false, false, false, true, false).ID: return 4616; case RedMushroomBlock::RedMushroomBlock(false, false, false, false, false, true).ID: return 4617; case RedMushroomBlock::RedMushroomBlock(false, false, false, false, false, false).ID: return 4618; case RedNetherBrickSlab::RedNetherBrickSlab(RedNetherBrickSlab::Type::Top).ID: return 10314; case RedNetherBrickSlab::RedNetherBrickSlab(RedNetherBrickSlab::Type::Bottom).ID: return 10316; case RedNetherBrickSlab::RedNetherBrickSlab(RedNetherBrickSlab::Type::Double).ID: return 10318; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, RedNetherBrickStairs::Half::Top, RedNetherBrickStairs::Shape::Straight).ID: return 10014; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, RedNetherBrickStairs::Half::Top, RedNetherBrickStairs::Shape::InnerLeft).ID: return 10016; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, RedNetherBrickStairs::Half::Top, RedNetherBrickStairs::Shape::InnerRight).ID: return 10018; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, RedNetherBrickStairs::Half::Top, RedNetherBrickStairs::Shape::OuterLeft).ID: return 10020; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, RedNetherBrickStairs::Half::Top, RedNetherBrickStairs::Shape::OuterRight).ID: return 10022; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, RedNetherBrickStairs::Half::Bottom, RedNetherBrickStairs::Shape::Straight).ID: return 10024; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, RedNetherBrickStairs::Half::Bottom, RedNetherBrickStairs::Shape::InnerLeft).ID: return 10026; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, RedNetherBrickStairs::Half::Bottom, RedNetherBrickStairs::Shape::InnerRight).ID: return 10028; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, RedNetherBrickStairs::Half::Bottom, RedNetherBrickStairs::Shape::OuterLeft).ID: return 10030; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, RedNetherBrickStairs::Half::Bottom, RedNetherBrickStairs::Shape::OuterRight).ID: return 10032; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, RedNetherBrickStairs::Half::Top, RedNetherBrickStairs::Shape::Straight).ID: return 10034; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, RedNetherBrickStairs::Half::Top, RedNetherBrickStairs::Shape::InnerLeft).ID: return 10036; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, RedNetherBrickStairs::Half::Top, RedNetherBrickStairs::Shape::InnerRight).ID: return 10038; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, RedNetherBrickStairs::Half::Top, RedNetherBrickStairs::Shape::OuterLeft).ID: return 10040; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, RedNetherBrickStairs::Half::Top, RedNetherBrickStairs::Shape::OuterRight).ID: return 10042; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, RedNetherBrickStairs::Half::Bottom, RedNetherBrickStairs::Shape::Straight).ID: return 10044; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, RedNetherBrickStairs::Half::Bottom, RedNetherBrickStairs::Shape::InnerLeft).ID: return 10046; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, RedNetherBrickStairs::Half::Bottom, RedNetherBrickStairs::Shape::InnerRight).ID: return 10048; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, RedNetherBrickStairs::Half::Bottom, RedNetherBrickStairs::Shape::OuterLeft).ID: return 10050; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, RedNetherBrickStairs::Half::Bottom, RedNetherBrickStairs::Shape::OuterRight).ID: return 10052; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_XM, RedNetherBrickStairs::Half::Top, RedNetherBrickStairs::Shape::Straight).ID: return 10054; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_XM, RedNetherBrickStairs::Half::Top, RedNetherBrickStairs::Shape::InnerLeft).ID: return 10056; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_XM, RedNetherBrickStairs::Half::Top, RedNetherBrickStairs::Shape::InnerRight).ID: return 10058; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_XM, RedNetherBrickStairs::Half::Top, RedNetherBrickStairs::Shape::OuterLeft).ID: return 10060; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_XM, RedNetherBrickStairs::Half::Top, RedNetherBrickStairs::Shape::OuterRight).ID: return 10062; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_XM, RedNetherBrickStairs::Half::Bottom, RedNetherBrickStairs::Shape::Straight).ID: return 10064; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_XM, RedNetherBrickStairs::Half::Bottom, RedNetherBrickStairs::Shape::InnerLeft).ID: return 10066; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_XM, RedNetherBrickStairs::Half::Bottom, RedNetherBrickStairs::Shape::InnerRight).ID: return 10068; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_XM, RedNetherBrickStairs::Half::Bottom, RedNetherBrickStairs::Shape::OuterLeft).ID: return 10070; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_XM, RedNetherBrickStairs::Half::Bottom, RedNetherBrickStairs::Shape::OuterRight).ID: return 10072; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_XP, RedNetherBrickStairs::Half::Top, RedNetherBrickStairs::Shape::Straight).ID: return 10074; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_XP, RedNetherBrickStairs::Half::Top, RedNetherBrickStairs::Shape::InnerLeft).ID: return 10076; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_XP, RedNetherBrickStairs::Half::Top, RedNetherBrickStairs::Shape::InnerRight).ID: return 10078; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_XP, RedNetherBrickStairs::Half::Top, RedNetherBrickStairs::Shape::OuterLeft).ID: return 10080; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_XP, RedNetherBrickStairs::Half::Top, RedNetherBrickStairs::Shape::OuterRight).ID: return 10082; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_XP, RedNetherBrickStairs::Half::Bottom, RedNetherBrickStairs::Shape::Straight).ID: return 10084; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_XP, RedNetherBrickStairs::Half::Bottom, RedNetherBrickStairs::Shape::InnerLeft).ID: return 10086; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_XP, RedNetherBrickStairs::Half::Bottom, RedNetherBrickStairs::Shape::InnerRight).ID: return 10088; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_XP, RedNetherBrickStairs::Half::Bottom, RedNetherBrickStairs::Shape::OuterLeft).ID: return 10090; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_XP, RedNetherBrickStairs::Half::Bottom, RedNetherBrickStairs::Shape::OuterRight).ID: return 10092; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::Low, true, RedNetherBrickWall::West::Low).ID: return 10845; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::Low, true, RedNetherBrickWall::West::None).ID: return 10846; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::Low, false, RedNetherBrickWall::West::Low).ID: return 10849; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::Low, false, RedNetherBrickWall::West::None).ID: return 10850; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::None, true, RedNetherBrickWall::West::Low).ID: return 10853; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::None, true, RedNetherBrickWall::West::None).ID: return 10854; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::None, false, RedNetherBrickWall::West::Low).ID: return 10857; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::None, false, RedNetherBrickWall::West::None).ID: return 10858; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::None, RedNetherBrickWall::South::Low, true, RedNetherBrickWall::West::Low).ID: return 10861; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::None, RedNetherBrickWall::South::Low, true, RedNetherBrickWall::West::None).ID: return 10862; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::None, RedNetherBrickWall::South::Low, false, RedNetherBrickWall::West::Low).ID: return 10865; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::None, RedNetherBrickWall::South::Low, false, RedNetherBrickWall::West::None).ID: return 10866; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::None, RedNetherBrickWall::South::None, true, RedNetherBrickWall::West::Low).ID: return 10869; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::None, RedNetherBrickWall::South::None, true, RedNetherBrickWall::West::None).ID: return 10870; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::None, RedNetherBrickWall::South::None, false, RedNetherBrickWall::West::Low).ID: return 10873; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::None, RedNetherBrickWall::South::None, false, RedNetherBrickWall::West::None).ID: return 10874; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::Low, true, RedNetherBrickWall::West::Low).ID: return 10877; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::Low, true, RedNetherBrickWall::West::None).ID: return 10878; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::Low, false, RedNetherBrickWall::West::Low).ID: return 10881; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::Low, false, RedNetherBrickWall::West::None).ID: return 10882; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::None, true, RedNetherBrickWall::West::Low).ID: return 10885; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::None, true, RedNetherBrickWall::West::None).ID: return 10886; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::None, false, RedNetherBrickWall::West::Low).ID: return 10889; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::None, false, RedNetherBrickWall::West::None).ID: return 10890; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::None, RedNetherBrickWall::South::Low, true, RedNetherBrickWall::West::Low).ID: return 10893; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::None, RedNetherBrickWall::South::Low, true, RedNetherBrickWall::West::None).ID: return 10894; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::None, RedNetherBrickWall::South::Low, false, RedNetherBrickWall::West::Low).ID: return 10897; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::None, RedNetherBrickWall::South::Low, false, RedNetherBrickWall::West::None).ID: return 10898; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::None, RedNetherBrickWall::South::None, true, RedNetherBrickWall::West::Low).ID: return 10901; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::None, RedNetherBrickWall::South::None, true, RedNetherBrickWall::West::None).ID: return 10902; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::None, RedNetherBrickWall::South::None, false, RedNetherBrickWall::West::Low).ID: return 10905; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::None, RedNetherBrickWall::South::None, false, RedNetherBrickWall::West::None).ID: return 10906; case RedNetherBricks::RedNetherBricks().ID: return 8719; case RedSand::RedSand().ID: return 67; case RedSandstone::RedSandstone().ID: return 7681; case RedSandstoneSlab::RedSandstoneSlab(RedSandstoneSlab::Type::Top).ID: return 7861; case RedSandstoneSlab::RedSandstoneSlab(RedSandstoneSlab::Type::Bottom).ID: return 7863; case RedSandstoneSlab::RedSandstoneSlab(RedSandstoneSlab::Type::Double).ID: return 7865; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::Straight).ID: return 7685; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::InnerLeft).ID: return 7687; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::InnerRight).ID: return 7689; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::OuterLeft).ID: return 7691; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::OuterRight).ID: return 7693; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::Straight).ID: return 7695; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::InnerLeft).ID: return 7697; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::InnerRight).ID: return 7699; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::OuterLeft).ID: return 7701; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::OuterRight).ID: return 7703; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::Straight).ID: return 7705; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::InnerLeft).ID: return 7707; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::InnerRight).ID: return 7709; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::OuterLeft).ID: return 7711; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::OuterRight).ID: return 7713; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::Straight).ID: return 7715; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::InnerLeft).ID: return 7717; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::InnerRight).ID: return 7719; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::OuterLeft).ID: return 7721; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::OuterRight).ID: return 7723; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::Straight).ID: return 7725; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::InnerLeft).ID: return 7727; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::InnerRight).ID: return 7729; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::OuterLeft).ID: return 7731; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::OuterRight).ID: return 7733; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::Straight).ID: return 7735; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::InnerLeft).ID: return 7737; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::InnerRight).ID: return 7739; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::OuterLeft).ID: return 7741; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::OuterRight).ID: return 7743; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::Straight).ID: return 7745; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::InnerLeft).ID: return 7747; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::InnerRight).ID: return 7749; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::OuterLeft).ID: return 7751; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::OuterRight).ID: return 7753; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::Straight).ID: return 7755; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::InnerLeft).ID: return 7757; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::InnerRight).ID: return 7759; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::OuterLeft).ID: return 7761; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::OuterRight).ID: return 7763; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::Low, RedSandstoneWall::South::Low, true, RedSandstoneWall::West::Low).ID: return 10461; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::Low, RedSandstoneWall::South::Low, true, RedSandstoneWall::West::None).ID: return 10462; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::Low, RedSandstoneWall::South::Low, false, RedSandstoneWall::West::Low).ID: return 10465; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::Low, RedSandstoneWall::South::Low, false, RedSandstoneWall::West::None).ID: return 10466; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::Low, RedSandstoneWall::South::None, true, RedSandstoneWall::West::Low).ID: return 10469; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::Low, RedSandstoneWall::South::None, true, RedSandstoneWall::West::None).ID: return 10470; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::Low, RedSandstoneWall::South::None, false, RedSandstoneWall::West::Low).ID: return 10473; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::Low, RedSandstoneWall::South::None, false, RedSandstoneWall::West::None).ID: return 10474; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::None, RedSandstoneWall::South::Low, true, RedSandstoneWall::West::Low).ID: return 10477; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::None, RedSandstoneWall::South::Low, true, RedSandstoneWall::West::None).ID: return 10478; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::None, RedSandstoneWall::South::Low, false, RedSandstoneWall::West::Low).ID: return 10481; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::None, RedSandstoneWall::South::Low, false, RedSandstoneWall::West::None).ID: return 10482; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::None, RedSandstoneWall::South::None, true, RedSandstoneWall::West::Low).ID: return 10485; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::None, RedSandstoneWall::South::None, true, RedSandstoneWall::West::None).ID: return 10486; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::None, RedSandstoneWall::South::None, false, RedSandstoneWall::West::Low).ID: return 10489; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::None, RedSandstoneWall::South::None, false, RedSandstoneWall::West::None).ID: return 10490; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::Low, RedSandstoneWall::South::Low, true, RedSandstoneWall::West::Low).ID: return 10493; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::Low, RedSandstoneWall::South::Low, true, RedSandstoneWall::West::None).ID: return 10494; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::Low, RedSandstoneWall::South::Low, false, RedSandstoneWall::West::Low).ID: return 10497; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::Low, RedSandstoneWall::South::Low, false, RedSandstoneWall::West::None).ID: return 10498; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::Low, RedSandstoneWall::South::None, true, RedSandstoneWall::West::Low).ID: return 10501; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::Low, RedSandstoneWall::South::None, true, RedSandstoneWall::West::None).ID: return 10502; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::Low, RedSandstoneWall::South::None, false, RedSandstoneWall::West::Low).ID: return 10505; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::Low, RedSandstoneWall::South::None, false, RedSandstoneWall::West::None).ID: return 10506; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::None, RedSandstoneWall::South::Low, true, RedSandstoneWall::West::Low).ID: return 10509; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::None, RedSandstoneWall::South::Low, true, RedSandstoneWall::West::None).ID: return 10510; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::None, RedSandstoneWall::South::Low, false, RedSandstoneWall::West::Low).ID: return 10513; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::None, RedSandstoneWall::South::Low, false, RedSandstoneWall::West::None).ID: return 10514; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::None, RedSandstoneWall::South::None, true, RedSandstoneWall::West::Low).ID: return 10517; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::None, RedSandstoneWall::South::None, true, RedSandstoneWall::West::None).ID: return 10518; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::None, RedSandstoneWall::South::None, false, RedSandstoneWall::West::Low).ID: return 10521; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::None, RedSandstoneWall::South::None, false, RedSandstoneWall::West::None).ID: return 10522; case RedShulkerBox::RedShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 8826; case RedShulkerBox::RedShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 8827; case RedShulkerBox::RedShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 8828; case RedShulkerBox::RedShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 8829; case RedShulkerBox::RedShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 8830; case RedShulkerBox::RedShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 8831; case RedStainedGlass::RedStainedGlass().ID: return 4095; case RedStainedGlassPane::RedStainedGlassPane(true, true, true, true).ID: return 6777; case RedStainedGlassPane::RedStainedGlassPane(true, true, true, false).ID: return 6778; case RedStainedGlassPane::RedStainedGlassPane(true, true, false, true).ID: return 6781; case RedStainedGlassPane::RedStainedGlassPane(true, true, false, false).ID: return 6782; case RedStainedGlassPane::RedStainedGlassPane(true, false, true, true).ID: return 6785; case RedStainedGlassPane::RedStainedGlassPane(true, false, true, false).ID: return 6786; case RedStainedGlassPane::RedStainedGlassPane(true, false, false, true).ID: return 6789; case RedStainedGlassPane::RedStainedGlassPane(true, false, false, false).ID: return 6790; case RedStainedGlassPane::RedStainedGlassPane(false, true, true, true).ID: return 6793; case RedStainedGlassPane::RedStainedGlassPane(false, true, true, false).ID: return 6794; case RedStainedGlassPane::RedStainedGlassPane(false, true, false, true).ID: return 6797; case RedStainedGlassPane::RedStainedGlassPane(false, true, false, false).ID: return 6798; case RedStainedGlassPane::RedStainedGlassPane(false, false, true, true).ID: return 6801; case RedStainedGlassPane::RedStainedGlassPane(false, false, true, false).ID: return 6802; case RedStainedGlassPane::RedStainedGlassPane(false, false, false, true).ID: return 6805; case RedStainedGlassPane::RedStainedGlassPane(false, false, false, false).ID: return 6806; case RedTerracotta::RedTerracotta().ID: return 6325; case RedTulip::RedTulip().ID: return 1416; case RedWallBanner::RedWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 7673; case RedWallBanner::RedWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 7674; case RedWallBanner::RedWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 7675; case RedWallBanner::RedWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 7676; case RedWool::RedWool().ID: return 1397; case RedstoneBlock::RedstoneBlock().ID: return 6190; case RedstoneLamp::RedstoneLamp(true).ID: return 5140; case RedstoneLamp::RedstoneLamp(false).ID: return 5141; case RedstoneOre::RedstoneOre(true).ID: return 3883; case RedstoneOre::RedstoneOre(false).ID: return 3884; case RedstoneTorch::RedstoneTorch(true).ID: return 3885; case RedstoneTorch::RedstoneTorch(false).ID: return 3886; case RedstoneWallTorch::RedstoneWallTorch(eBlockFace::BLOCK_FACE_ZM, true).ID: return 3887; case RedstoneWallTorch::RedstoneWallTorch(eBlockFace::BLOCK_FACE_ZM, false).ID: return 3888; case RedstoneWallTorch::RedstoneWallTorch(eBlockFace::BLOCK_FACE_ZP, true).ID: return 3889; case RedstoneWallTorch::RedstoneWallTorch(eBlockFace::BLOCK_FACE_ZP, false).ID: return 3890; case RedstoneWallTorch::RedstoneWallTorch(eBlockFace::BLOCK_FACE_XM, true).ID: return 3891; case RedstoneWallTorch::RedstoneWallTorch(eBlockFace::BLOCK_FACE_XM, false).ID: return 3892; case RedstoneWallTorch::RedstoneWallTorch(eBlockFace::BLOCK_FACE_XP, true).ID: return 3893; case RedstoneWallTorch::RedstoneWallTorch(eBlockFace::BLOCK_FACE_XP, false).ID: return 3894; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 0, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2056; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 0, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2057; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 0, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2058; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 0, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2059; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 0, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2060; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 0, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2061; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 0, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2062; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 0, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2063; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 0, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2064; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 1, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2065; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 1, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2066; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 1, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2067; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 1, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2068; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 1, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2069; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 1, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2070; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 1, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2071; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 1, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2072; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 1, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2073; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 2, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2074; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 2, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2075; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 2, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2076; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 2, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2077; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 2, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2078; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 2, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2079; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 2, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2080; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 2, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2081; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 2, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2082; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 3, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2083; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 3, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2084; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 3, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2085; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 3, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2086; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 3, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2087; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 3, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2088; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 3, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2089; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 3, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2090; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 3, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2091; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 4, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2092; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 4, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2093; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 4, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2094; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 4, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2095; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 4, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2096; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 4, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2097; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 4, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2098; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 4, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2099; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 4, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2100; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 5, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2101; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 5, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2102; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 5, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2103; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 5, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2104; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 5, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2105; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 5, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2106; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 5, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2107; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 5, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2108; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 5, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2109; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 6, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2110; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 6, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2111; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 6, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2112; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 6, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2113; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 6, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2114; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 6, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2115; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 6, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2116; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 6, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2117; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 6, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2118; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 7, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2119; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 7, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2120; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 7, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2121; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 7, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2122; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 7, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2123; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 7, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2124; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 7, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2125; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 7, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2126; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 7, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2127; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 8, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2128; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 8, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2129; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 8, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2130; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 8, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2131; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 8, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2132; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 8, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2133; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 8, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2134; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 8, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2135; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 8, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2136; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 9, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2137; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 9, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2138; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 9, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2139; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 9, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2140; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 9, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2141; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 9, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2142; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 9, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2143; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 9, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2144; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 9, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2145; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 10, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2146; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 10, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2147; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 10, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2148; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 10, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2149; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 10, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2150; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 10, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2151; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 10, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2152; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 10, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2153; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 10, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2154; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 11, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2155; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 11, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2156; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 11, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2157; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 11, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2158; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 11, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2159; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 11, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2160; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 11, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2161; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 11, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2162; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 11, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2163; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 12, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2164; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 12, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2165; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 12, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2166; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 12, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2167; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 12, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2168; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 12, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2169; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 12, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2170; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 12, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2171; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 12, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2172; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 13, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2173; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 13, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2174; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 13, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2175; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 13, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2176; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 13, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2177; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 13, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2178; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 13, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2179; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 13, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2180; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 13, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2181; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 14, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2182; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 14, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2183; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 14, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2184; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 14, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2185; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 14, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2186; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 14, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2187; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 14, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2188; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 14, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2189; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 14, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2190; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 15, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2191; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 15, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2192; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 15, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2193; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 15, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2194; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 15, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2195; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 15, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2196; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 15, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2197; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 15, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2198; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 15, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2199; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 0, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2200; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 0, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2201; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 0, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2202; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 0, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2203; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 0, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2204; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 0, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2205; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 0, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2206; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 0, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2207; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 0, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2208; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 1, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2209; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 1, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2210; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 1, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2211; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 1, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2212; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 1, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2213; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 1, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2214; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 1, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2215; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 1, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2216; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 1, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2217; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 2, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2218; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 2, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2219; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 2, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2220; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 2, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2221; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 2, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2222; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 2, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2223; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 2, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2224; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 2, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2225; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 2, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2226; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 3, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2227; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 3, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2228; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 3, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2229; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 3, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2230; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 3, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2231; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 3, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2232; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 3, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2233; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 3, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2234; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 3, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2235; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 4, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2236; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 4, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2237; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 4, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2238; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 4, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2239; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 4, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2240; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 4, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2241; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 4, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2242; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 4, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2243; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 4, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2244; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 5, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2245; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 5, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2246; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 5, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2247; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 5, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2248; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 5, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2249; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 5, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2250; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 5, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2251; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 5, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2252; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 5, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2253; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 6, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2254; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 6, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2255; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 6, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2256; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 6, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2257; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 6, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2258; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 6, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2259; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 6, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2260; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 6, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2261; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 6, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2262; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 7, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2263; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 7, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2264; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 7, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2265; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 7, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2266; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 7, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2267; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 7, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2268; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 7, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2269; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 7, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2270; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 7, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2271; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 8, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2272; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 8, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2273; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 8, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2274; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 8, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2275; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 8, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2276; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 8, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2277; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 8, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2278; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 8, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2279; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 8, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2280; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 9, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2281; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 9, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2282; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 9, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2283; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 9, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2284; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 9, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2285; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 9, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2286; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 9, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2287; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 9, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2288; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 9, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2289; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 10, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2290; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 10, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2291; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 10, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2292; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 10, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2293; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 10, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2294; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 10, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2295; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 10, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2296; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 10, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2297; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 10, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2298; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 11, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2299; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 11, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2300; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 11, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2301; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 11, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2302; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 11, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2303; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 11, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2304; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 11, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2305; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 11, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2306; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 11, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2307; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 12, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2308; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 12, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2309; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 12, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2310; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 12, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2311; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 12, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2312; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 12, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2313; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 12, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2314; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 12, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2315; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 12, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2316; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 13, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2317; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 13, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2318; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 13, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2319; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 13, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2320; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 13, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2321; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 13, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2322; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 13, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2323; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 13, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2324; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 13, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2325; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 14, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2326; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 14, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2327; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 14, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2328; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 14, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2329; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 14, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2330; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 14, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2331; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 14, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2332; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 14, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2333; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 14, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2334; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 15, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2335; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 15, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2336; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 15, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2337; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 15, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2338; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 15, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2339; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 15, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2340; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 15, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2341; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 15, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2342; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 15, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2343; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 0, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2344; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 0, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2345; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 0, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2346; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 0, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2347; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 0, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2348; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 0, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2349; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 0, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2350; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 0, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2351; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 0, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2352; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 1, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2353; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 1, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2354; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 1, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2355; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 1, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2356; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 1, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2357; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 1, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2358; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 1, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2359; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 1, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2360; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 1, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2361; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 2, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2362; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 2, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2363; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 2, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2364; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 2, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2365; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 2, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2366; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 2, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2367; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 2, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2368; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 2, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2369; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 2, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2370; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 3, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2371; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 3, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2372; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 3, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2373; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 3, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2374; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 3, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2375; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 3, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2376; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 3, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2377; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 3, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2378; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 3, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2379; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 4, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2380; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 4, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2381; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 4, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2382; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 4, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2383; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 4, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2384; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 4, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2385; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 4, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2386; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 4, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2387; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 4, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2388; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 5, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2389; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 5, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2390; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 5, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2391; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 5, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2392; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 5, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2393; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 5, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2394; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 5, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2395; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 5, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2396; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 5, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2397; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 6, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2398; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 6, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2399; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 6, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2400; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 6, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2401; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 6, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2402; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 6, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2403; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 6, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2404; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 6, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2405; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 6, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2406; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 7, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2407; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 7, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2408; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 7, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2409; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 7, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2410; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 7, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2411; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 7, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2412; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 7, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2413; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 7, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2414; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 7, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2415; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 8, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2416; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 8, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2417; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 8, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2418; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 8, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2419; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 8, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2420; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 8, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2421; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 8, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2422; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 8, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2423; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 8, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2424; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 9, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2425; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 9, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2426; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 9, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2427; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 9, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2428; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 9, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2429; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 9, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2430; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 9, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2431; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 9, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2432; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 9, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2433; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 10, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2434; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 10, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2435; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 10, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2436; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 10, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2437; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 10, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2438; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 10, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2439; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 10, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2440; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 10, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2441; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 10, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2442; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 11, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2443; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 11, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2444; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 11, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2445; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 11, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2446; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 11, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2447; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 11, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2448; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 11, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2449; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 11, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2450; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 11, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2451; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 12, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2452; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 12, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2453; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 12, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2454; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 12, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2455; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 12, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2456; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 12, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2457; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 12, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2458; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 12, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2459; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 12, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2460; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 13, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2461; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 13, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2462; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 13, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2463; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 13, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2464; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 13, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2465; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 13, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2466; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 13, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2467; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 13, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2468; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 13, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2469; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 14, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2470; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 14, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2471; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 14, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2472; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 14, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2473; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 14, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2474; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 14, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2475; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 14, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2476; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 14, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2477; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 14, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2478; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 15, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2479; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 15, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2480; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 15, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2481; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 15, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2482; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 15, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2483; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 15, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2484; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 15, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2485; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 15, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2486; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 15, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2487; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 0, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2488; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 0, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2489; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 0, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2490; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 0, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2491; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 0, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2492; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 0, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2493; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 0, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2494; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 0, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2495; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 0, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2496; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 1, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2497; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 1, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2498; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 1, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2499; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 1, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2500; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 1, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2501; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 1, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2502; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 1, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2503; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 1, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2504; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 1, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2505; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 2, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2506; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 2, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2507; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 2, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2508; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 2, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2509; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 2, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2510; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 2, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2511; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 2, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2512; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 2, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2513; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 2, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2514; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 3, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2515; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 3, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2516; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 3, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2517; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 3, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2518; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 3, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2519; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 3, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2520; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 3, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2521; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 3, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2522; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 3, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2523; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 4, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2524; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 4, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2525; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 4, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2526; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 4, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2527; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 4, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2528; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 4, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2529; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 4, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2530; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 4, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2531; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 4, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2532; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 5, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2533; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 5, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2534; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 5, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2535; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 5, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2536; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 5, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2537; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 5, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2538; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 5, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2539; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 5, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2540; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 5, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2541; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 6, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2542; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 6, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2543; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 6, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2544; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 6, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2545; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 6, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2546; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 6, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2547; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 6, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2548; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 6, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2549; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 6, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2550; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 7, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2551; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 7, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2552; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 7, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2553; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 7, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2554; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 7, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2555; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 7, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2556; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 7, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2557; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 7, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2558; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 7, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2559; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 8, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2560; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 8, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2561; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 8, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2562; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 8, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2563; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 8, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2564; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 8, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2565; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 8, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2566; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 8, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2567; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 8, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2568; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 9, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2569; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 9, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2570; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 9, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2571; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 9, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2572; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 9, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2573; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 9, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2574; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 9, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2575; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 9, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2576; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 9, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2577; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 10, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2578; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 10, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2579; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 10, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2580; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 10, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2581; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 10, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2582; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 10, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2583; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 10, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2584; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 10, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2585; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 10, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2586; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 11, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2587; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 11, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2588; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 11, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2589; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 11, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2590; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 11, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2591; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 11, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2592; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 11, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2593; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 11, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2594; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 11, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2595; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 12, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2596; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 12, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2597; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 12, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2598; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 12, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2599; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 12, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2600; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 12, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2601; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 12, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2602; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 12, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2603; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 12, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2604; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 13, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2605; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 13, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2606; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 13, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2607; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 13, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2608; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 13, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2609; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 13, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2610; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 13, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2611; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 13, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2612; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 13, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2613; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 14, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2614; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 14, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2615; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 14, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2616; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 14, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2617; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 14, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2618; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 14, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2619; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 14, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2620; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 14, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2621; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 14, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2622; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 15, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2623; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 15, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2624; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 15, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2625; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 15, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2626; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 15, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2627; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 15, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2628; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 15, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2629; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 15, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2630; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 15, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2631; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 0, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2632; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 0, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2633; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 0, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2634; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 0, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2635; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 0, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2636; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 0, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2637; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 0, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2638; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 0, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2639; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 0, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2640; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 1, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2641; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 1, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2642; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 1, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2643; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 1, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2644; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 1, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2645; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 1, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2646; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 1, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2647; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 1, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2648; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 1, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2649; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 2, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2650; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 2, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2651; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 2, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2652; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 2, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2653; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 2, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2654; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 2, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2655; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 2, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2656; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 2, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2657; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 2, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2658; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 3, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2659; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 3, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2660; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 3, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2661; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 3, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2662; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 3, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2663; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 3, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2664; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 3, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2665; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 3, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2666; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 3, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2667; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 4, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2668; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 4, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2669; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 4, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2670; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 4, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2671; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 4, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2672; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 4, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2673; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 4, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2674; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 4, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2675; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 4, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2676; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 5, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2677; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 5, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2678; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 5, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2679; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 5, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2680; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 5, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2681; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 5, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2682; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 5, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2683; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 5, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2684; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 5, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2685; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 6, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2686; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 6, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2687; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 6, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2688; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 6, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2689; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 6, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2690; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 6, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2691; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 6, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2692; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 6, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2693; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 6, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2694; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 7, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2695; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 7, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2696; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 7, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2697; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 7, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2698; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 7, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2699; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 7, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2700; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 7, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2701; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 7, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2702; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 7, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2703; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 8, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2704; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 8, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2705; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 8, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2706; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 8, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2707; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 8, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2708; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 8, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2709; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 8, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2710; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 8, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2711; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 8, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2712; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 9, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2713; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 9, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2714; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 9, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2715; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 9, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2716; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 9, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2717; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 9, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2718; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 9, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2719; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 9, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2720; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 9, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2721; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 10, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2722; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 10, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2723; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 10, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2724; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 10, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2725; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 10, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2726; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 10, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2727; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 10, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2728; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 10, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2729; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 10, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2730; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 11, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2731; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 11, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2732; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 11, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2733; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 11, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2734; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 11, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2735; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 11, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2736; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 11, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2737; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 11, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2738; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 11, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2739; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 12, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2740; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 12, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2741; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 12, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2742; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 12, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2743; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 12, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2744; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 12, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2745; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 12, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2746; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 12, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2747; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 12, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2748; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 13, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2749; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 13, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2750; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 13, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2751; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 13, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2752; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 13, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2753; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 13, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2754; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 13, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2755; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 13, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2756; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 13, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2757; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 14, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2758; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 14, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2759; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 14, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2760; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 14, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2761; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 14, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2762; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 14, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2763; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 14, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2764; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 14, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2765; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 14, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2766; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 15, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2767; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 15, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2768; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 15, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2769; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 15, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2770; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 15, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2771; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 15, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2772; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 15, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2773; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 15, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2774; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 15, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2775; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 0, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2776; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 0, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2777; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 0, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2778; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 0, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2779; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 0, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2780; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 0, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2781; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 0, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2782; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 0, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2783; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 0, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2784; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 1, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2785; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 1, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2786; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 1, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2787; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 1, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2788; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 1, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2789; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 1, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2790; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 1, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2791; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 1, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2792; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 1, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2793; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 2, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2794; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 2, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2795; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 2, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2796; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 2, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2797; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 2, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2798; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 2, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2799; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 2, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2800; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 2, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2801; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 2, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2802; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 3, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2803; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 3, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2804; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 3, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2805; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 3, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2806; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 3, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2807; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 3, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2808; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 3, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2809; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 3, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2810; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 3, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2811; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 4, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2812; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 4, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2813; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 4, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2814; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 4, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2815; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 4, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2816; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 4, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2817; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 4, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2818; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 4, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2819; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 4, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2820; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 5, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2821; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 5, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2822; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 5, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2823; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 5, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2824; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 5, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2825; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 5, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2826; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 5, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2827; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 5, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2828; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 5, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2829; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 6, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2830; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 6, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2831; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 6, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2832; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 6, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2833; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 6, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2834; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 6, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2835; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 6, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2836; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 6, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2837; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 6, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2838; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 7, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2839; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 7, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2840; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 7, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2841; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 7, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2842; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 7, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2843; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 7, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2844; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 7, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2845; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 7, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2846; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 7, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2847; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 8, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2848; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 8, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2849; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 8, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2850; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 8, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2851; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 8, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2852; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 8, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2853; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 8, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2854; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 8, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2855; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 8, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2856; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 9, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2857; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 9, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2858; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 9, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2859; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 9, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2860; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 9, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2861; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 9, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2862; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 9, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2863; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 9, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2864; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 9, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2865; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 10, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2866; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 10, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2867; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 10, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2868; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 10, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2869; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 10, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2870; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 10, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2871; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 10, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2872; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 10, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2873; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 10, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2874; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 11, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2875; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 11, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2876; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 11, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2877; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 11, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2878; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 11, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2879; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 11, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2880; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 11, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2881; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 11, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2882; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 11, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2883; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 12, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2884; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 12, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2885; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 12, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2886; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 12, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2887; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 12, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2888; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 12, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2889; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 12, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2890; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 12, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2891; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 12, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2892; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 13, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2893; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 13, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2894; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 13, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2895; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 13, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2896; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 13, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2897; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 13, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2898; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 13, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2899; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 13, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2900; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 13, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2901; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 14, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2902; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 14, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2903; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 14, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2904; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 14, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2905; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 14, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2906; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 14, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2907; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 14, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2908; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 14, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2909; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 14, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2910; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 15, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2911; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 15, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2912; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 15, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2913; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 15, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2914; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 15, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2915; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 15, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2916; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 15, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2917; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 15, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2918; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 15, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2919; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 0, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2920; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 0, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2921; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 0, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2922; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 0, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2923; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 0, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2924; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 0, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2925; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 0, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2926; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 0, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2927; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 0, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2928; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 1, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2929; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 1, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2930; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 1, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2931; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 1, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2932; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 1, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2933; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 1, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2934; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 1, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2935; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 1, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2936; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 1, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2937; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 2, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2938; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 2, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2939; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 2, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2940; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 2, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2941; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 2, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2942; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 2, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2943; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 2, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2944; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 2, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2945; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 2, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2946; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 3, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2947; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 3, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2948; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 3, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2949; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 3, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2950; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 3, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2951; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 3, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2952; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 3, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2953; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 3, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2954; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 3, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2955; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 4, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2956; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 4, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2957; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 4, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2958; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 4, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2959; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 4, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2960; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 4, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2961; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 4, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2962; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 4, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2963; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 4, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2964; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 5, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2965; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 5, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2966; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 5, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2967; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 5, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2968; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 5, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2969; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 5, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2970; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 5, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2971; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 5, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2972; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 5, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2973; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 6, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2974; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 6, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2975; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 6, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2976; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 6, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2977; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 6, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2978; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 6, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2979; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 6, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2980; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 6, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2981; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 6, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2982; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 7, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2983; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 7, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2984; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 7, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2985; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 7, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2986; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 7, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2987; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 7, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2988; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 7, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2989; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 7, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2990; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 7, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2991; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 8, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2992; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 8, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2993; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 8, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2994; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 8, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2995; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 8, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2996; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 8, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2997; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 8, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2998; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 8, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2999; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 8, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3000; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 9, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3001; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 9, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3002; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 9, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3003; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 9, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3004; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 9, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3005; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 9, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3006; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 9, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3007; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 9, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3008; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 9, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3009; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 10, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3010; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 10, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3011; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 10, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3012; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 10, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3013; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 10, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3014; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 10, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3015; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 10, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3016; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 10, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3017; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 10, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3018; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 11, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3019; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 11, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3020; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 11, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3021; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 11, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3022; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 11, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3023; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 11, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3024; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 11, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3025; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 11, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3026; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 11, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3027; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 12, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3028; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 12, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3029; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 12, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3030; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 12, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3031; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 12, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3032; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 12, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3033; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 12, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3034; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 12, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3035; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 12, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3036; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 13, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3037; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 13, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3038; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 13, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3039; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 13, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3040; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 13, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3041; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 13, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3042; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 13, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3043; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 13, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3044; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 13, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3045; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 14, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3046; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 14, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3047; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 14, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3048; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 14, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3049; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 14, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3050; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 14, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3051; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 14, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3052; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 14, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3053; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 14, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3054; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 15, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3055; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 15, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3056; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 15, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3057; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 15, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3058; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 15, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3059; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 15, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3060; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 15, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3061; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 15, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3062; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 15, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3063; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 0, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3064; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 0, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3065; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 0, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3066; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 0, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3067; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 0, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3068; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 0, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3069; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 0, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3070; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 0, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3071; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 0, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3072; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 1, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3073; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 1, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3074; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 1, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3075; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 1, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3076; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 1, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3077; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 1, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3078; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 1, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3079; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 1, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3080; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 1, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3081; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 2, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3082; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 2, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3083; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 2, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3084; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 2, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3085; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 2, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3086; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 2, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3087; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 2, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3088; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 2, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3089; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 2, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3090; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 3, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3091; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 3, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3092; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 3, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3093; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 3, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3094; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 3, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3095; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 3, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3096; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 3, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3097; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 3, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3098; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 3, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3099; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 4, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3100; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 4, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3101; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 4, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3102; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 4, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3103; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 4, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3104; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 4, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3105; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 4, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3106; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 4, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3107; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 4, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3108; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 5, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3109; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 5, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3110; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 5, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3111; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 5, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3112; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 5, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3113; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 5, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3114; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 5, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3115; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 5, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3116; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 5, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3117; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 6, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3118; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 6, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3119; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 6, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3120; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 6, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3121; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 6, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3122; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 6, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3123; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 6, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3124; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 6, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3125; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 6, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3126; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 7, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3127; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 7, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3128; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 7, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3129; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 7, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3130; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 7, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3131; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 7, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3132; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 7, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3133; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 7, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3134; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 7, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3135; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 8, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3136; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 8, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3137; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 8, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3138; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 8, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3139; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 8, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3140; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 8, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3141; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 8, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3142; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 8, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3143; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 8, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3144; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 9, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3145; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 9, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3146; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 9, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3147; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 9, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3148; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 9, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3149; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 9, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3150; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 9, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3151; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 9, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3152; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 9, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3153; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 10, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3154; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 10, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3155; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 10, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3156; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 10, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3157; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 10, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3158; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 10, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3159; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 10, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3160; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 10, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3161; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 10, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3162; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 11, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3163; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 11, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3164; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 11, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3165; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 11, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3166; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 11, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3167; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 11, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3168; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 11, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3169; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 11, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3170; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 11, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3171; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 12, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3172; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 12, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3173; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 12, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3174; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 12, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3175; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 12, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3176; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 12, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3177; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 12, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3178; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 12, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3179; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 12, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3180; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 13, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3181; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 13, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3182; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 13, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3183; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 13, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3184; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 13, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3185; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 13, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3186; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 13, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3187; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 13, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3188; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 13, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3189; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 14, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3190; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 14, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3191; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 14, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3192; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 14, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3193; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 14, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3194; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 14, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3195; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 14, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3196; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 14, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3197; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 14, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3198; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 15, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3199; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 15, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3200; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 15, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3201; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 15, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3202; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 15, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3203; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 15, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3204; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 15, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3205; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 15, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3206; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 15, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3207; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 0, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3208; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 0, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3209; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 0, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3210; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 0, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3211; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 0, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3212; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 0, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3213; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 0, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3214; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 0, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3215; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 0, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3216; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 1, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3217; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 1, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3218; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 1, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3219; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 1, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3220; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 1, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3221; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 1, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3222; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 1, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3223; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 1, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3224; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 1, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3225; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 2, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3226; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 2, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3227; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 2, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3228; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 2, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3229; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 2, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3230; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 2, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3231; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 2, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3232; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 2, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3233; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 2, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3234; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 3, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3235; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 3, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3236; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 3, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3237; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 3, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3238; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 3, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3239; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 3, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3240; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 3, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3241; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 3, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3242; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 3, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3243; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 4, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3244; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 4, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3245; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 4, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3246; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 4, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3247; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 4, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3248; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 4, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3249; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 4, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3250; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 4, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3251; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 4, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3252; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 5, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3253; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 5, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3254; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 5, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3255; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 5, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3256; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 5, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3257; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 5, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3258; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 5, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3259; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 5, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3260; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 5, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3261; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 6, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3262; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 6, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3263; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 6, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3264; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 6, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3265; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 6, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3266; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 6, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3267; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 6, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3268; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 6, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3269; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 6, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3270; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 7, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3271; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 7, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3272; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 7, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3273; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 7, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3274; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 7, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3275; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 7, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3276; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 7, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3277; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 7, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3278; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 7, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3279; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 8, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3280; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 8, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3281; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 8, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3282; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 8, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3283; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 8, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3284; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 8, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3285; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 8, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3286; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 8, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3287; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 8, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3288; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 9, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3289; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 9, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3290; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 9, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3291; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 9, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3292; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 9, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3293; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 9, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3294; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 9, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3295; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 9, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3296; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 9, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3297; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 10, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3298; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 10, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3299; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 10, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3300; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 10, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3301; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 10, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3302; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 10, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3303; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 10, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3304; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 10, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3305; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 10, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3306; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 11, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3307; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 11, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3308; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 11, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3309; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 11, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3310; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 11, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3311; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 11, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3312; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 11, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3313; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 11, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3314; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 11, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3315; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 12, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3316; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 12, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3317; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 12, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3318; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 12, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3319; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 12, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3320; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 12, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3321; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 12, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3322; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 12, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3323; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 12, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3324; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 13, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3325; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 13, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3326; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 13, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3327; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 13, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3328; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 13, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3329; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 13, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3330; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 13, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3331; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 13, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3332; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 13, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3333; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 14, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3334; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 14, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3335; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 14, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3336; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 14, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3337; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 14, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3338; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 14, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3339; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 14, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3340; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 14, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3341; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 14, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3342; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 15, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3343; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 15, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3344; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 15, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3345; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 15, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3346; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 15, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3347; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 15, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3348; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 15, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3349; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 15, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3350; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 15, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3351; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_ZM, true, true).ID: return 4017; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_ZM, true, false).ID: return 4018; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_ZM, false, true).ID: return 4019; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_ZM, false, false).ID: return 4020; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_ZP, true, true).ID: return 4021; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_ZP, true, false).ID: return 4022; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_ZP, false, true).ID: return 4023; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_ZP, false, false).ID: return 4024; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_XM, true, true).ID: return 4025; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_XM, true, false).ID: return 4026; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_XM, false, true).ID: return 4027; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_XM, false, false).ID: return 4028; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_XP, true, true).ID: return 4029; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_XP, true, false).ID: return 4030; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_XP, false, true).ID: return 4031; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_XP, false, false).ID: return 4032; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_ZM, true, true).ID: return 4033; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_ZM, true, false).ID: return 4034; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_ZM, false, true).ID: return 4035; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_ZM, false, false).ID: return 4036; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_ZP, true, true).ID: return 4037; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_ZP, true, false).ID: return 4038; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_ZP, false, true).ID: return 4039; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_ZP, false, false).ID: return 4040; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_XM, true, true).ID: return 4041; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_XM, true, false).ID: return 4042; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_XM, false, true).ID: return 4043; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_XM, false, false).ID: return 4044; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_XP, true, true).ID: return 4045; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_XP, true, false).ID: return 4046; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_XP, false, true).ID: return 4047; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_XP, false, false).ID: return 4048; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_ZM, true, true).ID: return 4049; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_ZM, true, false).ID: return 4050; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_ZM, false, true).ID: return 4051; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_ZM, false, false).ID: return 4052; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_ZP, true, true).ID: return 4053; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_ZP, true, false).ID: return 4054; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_ZP, false, true).ID: return 4055; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_ZP, false, false).ID: return 4056; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_XM, true, true).ID: return 4057; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_XM, true, false).ID: return 4058; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_XM, false, true).ID: return 4059; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_XM, false, false).ID: return 4060; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_XP, true, true).ID: return 4061; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_XP, true, false).ID: return 4062; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_XP, false, true).ID: return 4063; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_XP, false, false).ID: return 4064; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_ZM, true, true).ID: return 4065; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_ZM, true, false).ID: return 4066; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_ZM, false, true).ID: return 4067; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_ZM, false, false).ID: return 4068; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_ZP, true, true).ID: return 4069; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_ZP, true, false).ID: return 4070; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_ZP, false, true).ID: return 4071; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_ZP, false, false).ID: return 4072; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_XM, true, true).ID: return 4073; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_XM, true, false).ID: return 4074; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_XM, false, true).ID: return 4075; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_XM, false, false).ID: return 4076; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_XP, true, true).ID: return 4077; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_XP, true, false).ID: return 4078; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_XP, false, true).ID: return 4079; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_XP, false, false).ID: return 4080; case RepeatingCommandBlock::RepeatingCommandBlock(true, eBlockFace::BLOCK_FACE_ZM).ID: return 8689; case RepeatingCommandBlock::RepeatingCommandBlock(true, eBlockFace::BLOCK_FACE_XP).ID: return 8690; case RepeatingCommandBlock::RepeatingCommandBlock(true, eBlockFace::BLOCK_FACE_ZP).ID: return 8691; case RepeatingCommandBlock::RepeatingCommandBlock(true, eBlockFace::BLOCK_FACE_XM).ID: return 8692; case RepeatingCommandBlock::RepeatingCommandBlock(true, eBlockFace::BLOCK_FACE_YP).ID: return 8693; case RepeatingCommandBlock::RepeatingCommandBlock(true, eBlockFace::BLOCK_FACE_YM).ID: return 8694; case RepeatingCommandBlock::RepeatingCommandBlock(false, eBlockFace::BLOCK_FACE_ZM).ID: return 8695; case RepeatingCommandBlock::RepeatingCommandBlock(false, eBlockFace::BLOCK_FACE_XP).ID: return 8696; case RepeatingCommandBlock::RepeatingCommandBlock(false, eBlockFace::BLOCK_FACE_ZP).ID: return 8697; case RepeatingCommandBlock::RepeatingCommandBlock(false, eBlockFace::BLOCK_FACE_XM).ID: return 8698; case RepeatingCommandBlock::RepeatingCommandBlock(false, eBlockFace::BLOCK_FACE_YP).ID: return 8699; case RepeatingCommandBlock::RepeatingCommandBlock(false, eBlockFace::BLOCK_FACE_YM).ID: return 8700; case RoseBush::RoseBush(RoseBush::Half::Upper).ID: return 7353; case RoseBush::RoseBush(RoseBush::Half::Lower).ID: return 7354; case Sand::Sand().ID: return 66; case Sandstone::Sandstone().ID: return 245; case SandstoneSlab::SandstoneSlab(SandstoneSlab::Type::Top).ID: return 7813; case SandstoneSlab::SandstoneSlab(SandstoneSlab::Type::Bottom).ID: return 7815; case SandstoneSlab::SandstoneSlab(SandstoneSlab::Type::Double).ID: return 7817; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SandstoneStairs::Half::Top, SandstoneStairs::Shape::Straight).ID: return 5155; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SandstoneStairs::Half::Top, SandstoneStairs::Shape::InnerLeft).ID: return 5157; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SandstoneStairs::Half::Top, SandstoneStairs::Shape::InnerRight).ID: return 5159; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SandstoneStairs::Half::Top, SandstoneStairs::Shape::OuterLeft).ID: return 5161; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SandstoneStairs::Half::Top, SandstoneStairs::Shape::OuterRight).ID: return 5163; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::Straight).ID: return 5165; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::InnerLeft).ID: return 5167; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::InnerRight).ID: return 5169; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::OuterLeft).ID: return 5171; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::OuterRight).ID: return 5173; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SandstoneStairs::Half::Top, SandstoneStairs::Shape::Straight).ID: return 5175; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SandstoneStairs::Half::Top, SandstoneStairs::Shape::InnerLeft).ID: return 5177; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SandstoneStairs::Half::Top, SandstoneStairs::Shape::InnerRight).ID: return 5179; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SandstoneStairs::Half::Top, SandstoneStairs::Shape::OuterLeft).ID: return 5181; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SandstoneStairs::Half::Top, SandstoneStairs::Shape::OuterRight).ID: return 5183; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::Straight).ID: return 5185; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::InnerLeft).ID: return 5187; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::InnerRight).ID: return 5189; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::OuterLeft).ID: return 5191; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::OuterRight).ID: return 5193; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XM, SandstoneStairs::Half::Top, SandstoneStairs::Shape::Straight).ID: return 5195; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XM, SandstoneStairs::Half::Top, SandstoneStairs::Shape::InnerLeft).ID: return 5197; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XM, SandstoneStairs::Half::Top, SandstoneStairs::Shape::InnerRight).ID: return 5199; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XM, SandstoneStairs::Half::Top, SandstoneStairs::Shape::OuterLeft).ID: return 5201; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XM, SandstoneStairs::Half::Top, SandstoneStairs::Shape::OuterRight).ID: return 5203; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XM, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::Straight).ID: return 5205; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XM, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::InnerLeft).ID: return 5207; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XM, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::InnerRight).ID: return 5209; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XM, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::OuterLeft).ID: return 5211; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XM, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::OuterRight).ID: return 5213; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XP, SandstoneStairs::Half::Top, SandstoneStairs::Shape::Straight).ID: return 5215; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XP, SandstoneStairs::Half::Top, SandstoneStairs::Shape::InnerLeft).ID: return 5217; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XP, SandstoneStairs::Half::Top, SandstoneStairs::Shape::InnerRight).ID: return 5219; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XP, SandstoneStairs::Half::Top, SandstoneStairs::Shape::OuterLeft).ID: return 5221; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XP, SandstoneStairs::Half::Top, SandstoneStairs::Shape::OuterRight).ID: return 5223; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XP, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::Straight).ID: return 5225; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XP, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::InnerLeft).ID: return 5227; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XP, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::InnerRight).ID: return 5229; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XP, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::OuterLeft).ID: return 5231; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XP, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::OuterRight).ID: return 5233; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::Low, SandstoneWall::South::Low, true, SandstoneWall::West::Low).ID: return 10909; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::Low, SandstoneWall::South::Low, true, SandstoneWall::West::None).ID: return 10910; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::Low, SandstoneWall::South::Low, false, SandstoneWall::West::Low).ID: return 10913; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::Low, SandstoneWall::South::Low, false, SandstoneWall::West::None).ID: return 10914; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::Low, SandstoneWall::South::None, true, SandstoneWall::West::Low).ID: return 10917; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::Low, SandstoneWall::South::None, true, SandstoneWall::West::None).ID: return 10918; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::Low, SandstoneWall::South::None, false, SandstoneWall::West::Low).ID: return 10921; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::Low, SandstoneWall::South::None, false, SandstoneWall::West::None).ID: return 10922; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::None, SandstoneWall::South::Low, true, SandstoneWall::West::Low).ID: return 10925; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::None, SandstoneWall::South::Low, true, SandstoneWall::West::None).ID: return 10926; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::None, SandstoneWall::South::Low, false, SandstoneWall::West::Low).ID: return 10929; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::None, SandstoneWall::South::Low, false, SandstoneWall::West::None).ID: return 10930; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::None, SandstoneWall::South::None, true, SandstoneWall::West::Low).ID: return 10933; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::None, SandstoneWall::South::None, true, SandstoneWall::West::None).ID: return 10934; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::None, SandstoneWall::South::None, false, SandstoneWall::West::Low).ID: return 10937; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::None, SandstoneWall::South::None, false, SandstoneWall::West::None).ID: return 10938; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::Low, SandstoneWall::South::Low, true, SandstoneWall::West::Low).ID: return 10941; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::Low, SandstoneWall::South::Low, true, SandstoneWall::West::None).ID: return 10942; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::Low, SandstoneWall::South::Low, false, SandstoneWall::West::Low).ID: return 10945; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::Low, SandstoneWall::South::Low, false, SandstoneWall::West::None).ID: return 10946; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::Low, SandstoneWall::South::None, true, SandstoneWall::West::Low).ID: return 10949; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::Low, SandstoneWall::South::None, true, SandstoneWall::West::None).ID: return 10950; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::Low, SandstoneWall::South::None, false, SandstoneWall::West::Low).ID: return 10953; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::Low, SandstoneWall::South::None, false, SandstoneWall::West::None).ID: return 10954; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::None, SandstoneWall::South::Low, true, SandstoneWall::West::Low).ID: return 10957; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::None, SandstoneWall::South::Low, true, SandstoneWall::West::None).ID: return 10958; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::None, SandstoneWall::South::Low, false, SandstoneWall::West::Low).ID: return 10961; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::None, SandstoneWall::South::Low, false, SandstoneWall::West::None).ID: return 10962; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::None, SandstoneWall::South::None, true, SandstoneWall::West::Low).ID: return 10965; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::None, SandstoneWall::South::None, true, SandstoneWall::West::None).ID: return 10966; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::None, SandstoneWall::South::None, false, SandstoneWall::West::Low).ID: return 10969; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::None, SandstoneWall::South::None, false, SandstoneWall::West::None).ID: return 10970; case Scaffolding::Scaffolding(true, 0).ID: return 11100; case Scaffolding::Scaffolding(true, 1).ID: return 11102; case Scaffolding::Scaffolding(true, 2).ID: return 11104; case Scaffolding::Scaffolding(true, 3).ID: return 11106; case Scaffolding::Scaffolding(true, 4).ID: return 11108; case Scaffolding::Scaffolding(true, 5).ID: return 11110; case Scaffolding::Scaffolding(true, 6).ID: return 11112; case Scaffolding::Scaffolding(true, 7).ID: return 11114; case Scaffolding::Scaffolding(false, 0).ID: return 11116; case Scaffolding::Scaffolding(false, 1).ID: return 11118; case Scaffolding::Scaffolding(false, 2).ID: return 11120; case Scaffolding::Scaffolding(false, 3).ID: return 11122; case Scaffolding::Scaffolding(false, 4).ID: return 11124; case Scaffolding::Scaffolding(false, 5).ID: return 11126; case Scaffolding::Scaffolding(false, 6).ID: return 11128; case Scaffolding::Scaffolding(false, 7).ID: return 11130; case SeaLantern::SeaLantern().ID: return 7326; case SeaPickle::SeaPickle(1).ID: return 9105; case SeaPickle::SeaPickle(2).ID: return 9107; case SeaPickle::SeaPickle(3).ID: return 9109; case SeaPickle::SeaPickle(4).ID: return 9111; case Seagrass::Seagrass().ID: return 1344; case ShulkerBox::ShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 8736; case ShulkerBox::ShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 8737; case ShulkerBox::ShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 8738; case ShulkerBox::ShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 8739; case ShulkerBox::ShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 8740; case ShulkerBox::ShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 8741; case SkeletonSkull::SkeletonSkull(0).ID: return 5954; case SkeletonSkull::SkeletonSkull(1).ID: return 5955; case SkeletonSkull::SkeletonSkull(2).ID: return 5956; case SkeletonSkull::SkeletonSkull(3).ID: return 5957; case SkeletonSkull::SkeletonSkull(4).ID: return 5958; case SkeletonSkull::SkeletonSkull(5).ID: return 5959; case SkeletonSkull::SkeletonSkull(6).ID: return 5960; case SkeletonSkull::SkeletonSkull(7).ID: return 5961; case SkeletonSkull::SkeletonSkull(8).ID: return 5962; case SkeletonSkull::SkeletonSkull(9).ID: return 5963; case SkeletonSkull::SkeletonSkull(10).ID: return 5964; case SkeletonSkull::SkeletonSkull(11).ID: return 5965; case SkeletonSkull::SkeletonSkull(12).ID: return 5966; case SkeletonSkull::SkeletonSkull(13).ID: return 5967; case SkeletonSkull::SkeletonSkull(14).ID: return 5968; case SkeletonSkull::SkeletonSkull(15).ID: return 5969; case SkeletonWallSkull::SkeletonWallSkull(eBlockFace::BLOCK_FACE_ZM).ID: return 5970; case SkeletonWallSkull::SkeletonWallSkull(eBlockFace::BLOCK_FACE_ZP).ID: return 5971; case SkeletonWallSkull::SkeletonWallSkull(eBlockFace::BLOCK_FACE_XM).ID: return 5972; case SkeletonWallSkull::SkeletonWallSkull(eBlockFace::BLOCK_FACE_XP).ID: return 5973; case SlimeBlock::SlimeBlock().ID: return 6999; case SmithingTable::SmithingTable().ID: return 11193; case Smoker::Smoker(eBlockFace::BLOCK_FACE_ZM, true).ID: return 11147; case Smoker::Smoker(eBlockFace::BLOCK_FACE_ZM, false).ID: return 11148; case Smoker::Smoker(eBlockFace::BLOCK_FACE_ZP, true).ID: return 11149; case Smoker::Smoker(eBlockFace::BLOCK_FACE_ZP, false).ID: return 11150; case Smoker::Smoker(eBlockFace::BLOCK_FACE_XM, true).ID: return 11151; case Smoker::Smoker(eBlockFace::BLOCK_FACE_XM, false).ID: return 11152; case Smoker::Smoker(eBlockFace::BLOCK_FACE_XP, true).ID: return 11153; case Smoker::Smoker(eBlockFace::BLOCK_FACE_XP, false).ID: return 11154; case SmoothQuartz::SmoothQuartz().ID: return 7880; case SmoothQuartzSlab::SmoothQuartzSlab(SmoothQuartzSlab::Type::Top).ID: return 10296; case SmoothQuartzSlab::SmoothQuartzSlab(SmoothQuartzSlab::Type::Bottom).ID: return 10298; case SmoothQuartzSlab::SmoothQuartzSlab(SmoothQuartzSlab::Type::Double).ID: return 10300; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_ZM, SmoothQuartzStairs::Half::Top, SmoothQuartzStairs::Shape::Straight).ID: return 9774; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_ZM, SmoothQuartzStairs::Half::Top, SmoothQuartzStairs::Shape::InnerLeft).ID: return 9776; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_ZM, SmoothQuartzStairs::Half::Top, SmoothQuartzStairs::Shape::InnerRight).ID: return 9778; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_ZM, SmoothQuartzStairs::Half::Top, SmoothQuartzStairs::Shape::OuterLeft).ID: return 9780; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_ZM, SmoothQuartzStairs::Half::Top, SmoothQuartzStairs::Shape::OuterRight).ID: return 9782; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_ZM, SmoothQuartzStairs::Half::Bottom, SmoothQuartzStairs::Shape::Straight).ID: return 9784; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_ZM, SmoothQuartzStairs::Half::Bottom, SmoothQuartzStairs::Shape::InnerLeft).ID: return 9786; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_ZM, SmoothQuartzStairs::Half::Bottom, SmoothQuartzStairs::Shape::InnerRight).ID: return 9788; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_ZM, SmoothQuartzStairs::Half::Bottom, SmoothQuartzStairs::Shape::OuterLeft).ID: return 9790; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_ZM, SmoothQuartzStairs::Half::Bottom, SmoothQuartzStairs::Shape::OuterRight).ID: return 9792; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_ZP, SmoothQuartzStairs::Half::Top, SmoothQuartzStairs::Shape::Straight).ID: return 9794; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_ZP, SmoothQuartzStairs::Half::Top, SmoothQuartzStairs::Shape::InnerLeft).ID: return 9796; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_ZP, SmoothQuartzStairs::Half::Top, SmoothQuartzStairs::Shape::InnerRight).ID: return 9798; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_ZP, SmoothQuartzStairs::Half::Top, SmoothQuartzStairs::Shape::OuterLeft).ID: return 9800; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_ZP, SmoothQuartzStairs::Half::Top, SmoothQuartzStairs::Shape::OuterRight).ID: return 9802; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_ZP, SmoothQuartzStairs::Half::Bottom, SmoothQuartzStairs::Shape::Straight).ID: return 9804; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_ZP, SmoothQuartzStairs::Half::Bottom, SmoothQuartzStairs::Shape::InnerLeft).ID: return 9806; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_ZP, SmoothQuartzStairs::Half::Bottom, SmoothQuartzStairs::Shape::InnerRight).ID: return 9808; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_ZP, SmoothQuartzStairs::Half::Bottom, SmoothQuartzStairs::Shape::OuterLeft).ID: return 9810; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_ZP, SmoothQuartzStairs::Half::Bottom, SmoothQuartzStairs::Shape::OuterRight).ID: return 9812; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_XM, SmoothQuartzStairs::Half::Top, SmoothQuartzStairs::Shape::Straight).ID: return 9814; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_XM, SmoothQuartzStairs::Half::Top, SmoothQuartzStairs::Shape::InnerLeft).ID: return 9816; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_XM, SmoothQuartzStairs::Half::Top, SmoothQuartzStairs::Shape::InnerRight).ID: return 9818; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_XM, SmoothQuartzStairs::Half::Top, SmoothQuartzStairs::Shape::OuterLeft).ID: return 9820; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_XM, SmoothQuartzStairs::Half::Top, SmoothQuartzStairs::Shape::OuterRight).ID: return 9822; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_XM, SmoothQuartzStairs::Half::Bottom, SmoothQuartzStairs::Shape::Straight).ID: return 9824; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_XM, SmoothQuartzStairs::Half::Bottom, SmoothQuartzStairs::Shape::InnerLeft).ID: return 9826; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_XM, SmoothQuartzStairs::Half::Bottom, SmoothQuartzStairs::Shape::InnerRight).ID: return 9828; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_XM, SmoothQuartzStairs::Half::Bottom, SmoothQuartzStairs::Shape::OuterLeft).ID: return 9830; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_XM, SmoothQuartzStairs::Half::Bottom, SmoothQuartzStairs::Shape::OuterRight).ID: return 9832; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_XP, SmoothQuartzStairs::Half::Top, SmoothQuartzStairs::Shape::Straight).ID: return 9834; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_XP, SmoothQuartzStairs::Half::Top, SmoothQuartzStairs::Shape::InnerLeft).ID: return 9836; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_XP, SmoothQuartzStairs::Half::Top, SmoothQuartzStairs::Shape::InnerRight).ID: return 9838; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_XP, SmoothQuartzStairs::Half::Top, SmoothQuartzStairs::Shape::OuterLeft).ID: return 9840; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_XP, SmoothQuartzStairs::Half::Top, SmoothQuartzStairs::Shape::OuterRight).ID: return 9842; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_XP, SmoothQuartzStairs::Half::Bottom, SmoothQuartzStairs::Shape::Straight).ID: return 9844; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_XP, SmoothQuartzStairs::Half::Bottom, SmoothQuartzStairs::Shape::InnerLeft).ID: return 9846; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_XP, SmoothQuartzStairs::Half::Bottom, SmoothQuartzStairs::Shape::InnerRight).ID: return 9848; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_XP, SmoothQuartzStairs::Half::Bottom, SmoothQuartzStairs::Shape::OuterLeft).ID: return 9850; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_XP, SmoothQuartzStairs::Half::Bottom, SmoothQuartzStairs::Shape::OuterRight).ID: return 9852; case SmoothRedSandstone::SmoothRedSandstone().ID: return 7881; case SmoothRedSandstoneSlab::SmoothRedSandstoneSlab(SmoothRedSandstoneSlab::Type::Top).ID: return 10260; case SmoothRedSandstoneSlab::SmoothRedSandstoneSlab(SmoothRedSandstoneSlab::Type::Bottom).ID: return 10262; case SmoothRedSandstoneSlab::SmoothRedSandstoneSlab(SmoothRedSandstoneSlab::Type::Double).ID: return 10264; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SmoothRedSandstoneStairs::Half::Top, SmoothRedSandstoneStairs::Shape::Straight).ID: return 9214; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SmoothRedSandstoneStairs::Half::Top, SmoothRedSandstoneStairs::Shape::InnerLeft).ID: return 9216; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SmoothRedSandstoneStairs::Half::Top, SmoothRedSandstoneStairs::Shape::InnerRight).ID: return 9218; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SmoothRedSandstoneStairs::Half::Top, SmoothRedSandstoneStairs::Shape::OuterLeft).ID: return 9220; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SmoothRedSandstoneStairs::Half::Top, SmoothRedSandstoneStairs::Shape::OuterRight).ID: return 9222; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SmoothRedSandstoneStairs::Half::Bottom, SmoothRedSandstoneStairs::Shape::Straight).ID: return 9224; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SmoothRedSandstoneStairs::Half::Bottom, SmoothRedSandstoneStairs::Shape::InnerLeft).ID: return 9226; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SmoothRedSandstoneStairs::Half::Bottom, SmoothRedSandstoneStairs::Shape::InnerRight).ID: return 9228; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SmoothRedSandstoneStairs::Half::Bottom, SmoothRedSandstoneStairs::Shape::OuterLeft).ID: return 9230; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SmoothRedSandstoneStairs::Half::Bottom, SmoothRedSandstoneStairs::Shape::OuterRight).ID: return 9232; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SmoothRedSandstoneStairs::Half::Top, SmoothRedSandstoneStairs::Shape::Straight).ID: return 9234; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SmoothRedSandstoneStairs::Half::Top, SmoothRedSandstoneStairs::Shape::InnerLeft).ID: return 9236; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SmoothRedSandstoneStairs::Half::Top, SmoothRedSandstoneStairs::Shape::InnerRight).ID: return 9238; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SmoothRedSandstoneStairs::Half::Top, SmoothRedSandstoneStairs::Shape::OuterLeft).ID: return 9240; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SmoothRedSandstoneStairs::Half::Top, SmoothRedSandstoneStairs::Shape::OuterRight).ID: return 9242; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SmoothRedSandstoneStairs::Half::Bottom, SmoothRedSandstoneStairs::Shape::Straight).ID: return 9244; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SmoothRedSandstoneStairs::Half::Bottom, SmoothRedSandstoneStairs::Shape::InnerLeft).ID: return 9246; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SmoothRedSandstoneStairs::Half::Bottom, SmoothRedSandstoneStairs::Shape::InnerRight).ID: return 9248; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SmoothRedSandstoneStairs::Half::Bottom, SmoothRedSandstoneStairs::Shape::OuterLeft).ID: return 9250; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SmoothRedSandstoneStairs::Half::Bottom, SmoothRedSandstoneStairs::Shape::OuterRight).ID: return 9252; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, SmoothRedSandstoneStairs::Half::Top, SmoothRedSandstoneStairs::Shape::Straight).ID: return 9254; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, SmoothRedSandstoneStairs::Half::Top, SmoothRedSandstoneStairs::Shape::InnerLeft).ID: return 9256; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, SmoothRedSandstoneStairs::Half::Top, SmoothRedSandstoneStairs::Shape::InnerRight).ID: return 9258; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, SmoothRedSandstoneStairs::Half::Top, SmoothRedSandstoneStairs::Shape::OuterLeft).ID: return 9260; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, SmoothRedSandstoneStairs::Half::Top, SmoothRedSandstoneStairs::Shape::OuterRight).ID: return 9262; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, SmoothRedSandstoneStairs::Half::Bottom, SmoothRedSandstoneStairs::Shape::Straight).ID: return 9264; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, SmoothRedSandstoneStairs::Half::Bottom, SmoothRedSandstoneStairs::Shape::InnerLeft).ID: return 9266; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, SmoothRedSandstoneStairs::Half::Bottom, SmoothRedSandstoneStairs::Shape::InnerRight).ID: return 9268; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, SmoothRedSandstoneStairs::Half::Bottom, SmoothRedSandstoneStairs::Shape::OuterLeft).ID: return 9270; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, SmoothRedSandstoneStairs::Half::Bottom, SmoothRedSandstoneStairs::Shape::OuterRight).ID: return 9272; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, SmoothRedSandstoneStairs::Half::Top, SmoothRedSandstoneStairs::Shape::Straight).ID: return 9274; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, SmoothRedSandstoneStairs::Half::Top, SmoothRedSandstoneStairs::Shape::InnerLeft).ID: return 9276; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, SmoothRedSandstoneStairs::Half::Top, SmoothRedSandstoneStairs::Shape::InnerRight).ID: return 9278; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, SmoothRedSandstoneStairs::Half::Top, SmoothRedSandstoneStairs::Shape::OuterLeft).ID: return 9280; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, SmoothRedSandstoneStairs::Half::Top, SmoothRedSandstoneStairs::Shape::OuterRight).ID: return 9282; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, SmoothRedSandstoneStairs::Half::Bottom, SmoothRedSandstoneStairs::Shape::Straight).ID: return 9284; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, SmoothRedSandstoneStairs::Half::Bottom, SmoothRedSandstoneStairs::Shape::InnerLeft).ID: return 9286; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, SmoothRedSandstoneStairs::Half::Bottom, SmoothRedSandstoneStairs::Shape::InnerRight).ID: return 9288; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, SmoothRedSandstoneStairs::Half::Bottom, SmoothRedSandstoneStairs::Shape::OuterLeft).ID: return 9290; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, SmoothRedSandstoneStairs::Half::Bottom, SmoothRedSandstoneStairs::Shape::OuterRight).ID: return 9292; case SmoothSandstone::SmoothSandstone().ID: return 7879; case SmoothSandstoneSlab::SmoothSandstoneSlab(SmoothSandstoneSlab::Type::Top).ID: return 10290; case SmoothSandstoneSlab::SmoothSandstoneSlab(SmoothSandstoneSlab::Type::Bottom).ID: return 10292; case SmoothSandstoneSlab::SmoothSandstoneSlab(SmoothSandstoneSlab::Type::Double).ID: return 10294; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SmoothSandstoneStairs::Half::Top, SmoothSandstoneStairs::Shape::Straight).ID: return 9694; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SmoothSandstoneStairs::Half::Top, SmoothSandstoneStairs::Shape::InnerLeft).ID: return 9696; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SmoothSandstoneStairs::Half::Top, SmoothSandstoneStairs::Shape::InnerRight).ID: return 9698; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SmoothSandstoneStairs::Half::Top, SmoothSandstoneStairs::Shape::OuterLeft).ID: return 9700; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SmoothSandstoneStairs::Half::Top, SmoothSandstoneStairs::Shape::OuterRight).ID: return 9702; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SmoothSandstoneStairs::Half::Bottom, SmoothSandstoneStairs::Shape::Straight).ID: return 9704; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SmoothSandstoneStairs::Half::Bottom, SmoothSandstoneStairs::Shape::InnerLeft).ID: return 9706; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SmoothSandstoneStairs::Half::Bottom, SmoothSandstoneStairs::Shape::InnerRight).ID: return 9708; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SmoothSandstoneStairs::Half::Bottom, SmoothSandstoneStairs::Shape::OuterLeft).ID: return 9710; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SmoothSandstoneStairs::Half::Bottom, SmoothSandstoneStairs::Shape::OuterRight).ID: return 9712; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SmoothSandstoneStairs::Half::Top, SmoothSandstoneStairs::Shape::Straight).ID: return 9714; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SmoothSandstoneStairs::Half::Top, SmoothSandstoneStairs::Shape::InnerLeft).ID: return 9716; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SmoothSandstoneStairs::Half::Top, SmoothSandstoneStairs::Shape::InnerRight).ID: return 9718; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SmoothSandstoneStairs::Half::Top, SmoothSandstoneStairs::Shape::OuterLeft).ID: return 9720; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SmoothSandstoneStairs::Half::Top, SmoothSandstoneStairs::Shape::OuterRight).ID: return 9722; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SmoothSandstoneStairs::Half::Bottom, SmoothSandstoneStairs::Shape::Straight).ID: return 9724; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SmoothSandstoneStairs::Half::Bottom, SmoothSandstoneStairs::Shape::InnerLeft).ID: return 9726; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SmoothSandstoneStairs::Half::Bottom, SmoothSandstoneStairs::Shape::InnerRight).ID: return 9728; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SmoothSandstoneStairs::Half::Bottom, SmoothSandstoneStairs::Shape::OuterLeft).ID: return 9730; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SmoothSandstoneStairs::Half::Bottom, SmoothSandstoneStairs::Shape::OuterRight).ID: return 9732; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_XM, SmoothSandstoneStairs::Half::Top, SmoothSandstoneStairs::Shape::Straight).ID: return 9734; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_XM, SmoothSandstoneStairs::Half::Top, SmoothSandstoneStairs::Shape::InnerLeft).ID: return 9736; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_XM, SmoothSandstoneStairs::Half::Top, SmoothSandstoneStairs::Shape::InnerRight).ID: return 9738; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_XM, SmoothSandstoneStairs::Half::Top, SmoothSandstoneStairs::Shape::OuterLeft).ID: return 9740; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_XM, SmoothSandstoneStairs::Half::Top, SmoothSandstoneStairs::Shape::OuterRight).ID: return 9742; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_XM, SmoothSandstoneStairs::Half::Bottom, SmoothSandstoneStairs::Shape::Straight).ID: return 9744; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_XM, SmoothSandstoneStairs::Half::Bottom, SmoothSandstoneStairs::Shape::InnerLeft).ID: return 9746; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_XM, SmoothSandstoneStairs::Half::Bottom, SmoothSandstoneStairs::Shape::InnerRight).ID: return 9748; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_XM, SmoothSandstoneStairs::Half::Bottom, SmoothSandstoneStairs::Shape::OuterLeft).ID: return 9750; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_XM, SmoothSandstoneStairs::Half::Bottom, SmoothSandstoneStairs::Shape::OuterRight).ID: return 9752; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_XP, SmoothSandstoneStairs::Half::Top, SmoothSandstoneStairs::Shape::Straight).ID: return 9754; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_XP, SmoothSandstoneStairs::Half::Top, SmoothSandstoneStairs::Shape::InnerLeft).ID: return 9756; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_XP, SmoothSandstoneStairs::Half::Top, SmoothSandstoneStairs::Shape::InnerRight).ID: return 9758; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_XP, SmoothSandstoneStairs::Half::Top, SmoothSandstoneStairs::Shape::OuterLeft).ID: return 9760; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_XP, SmoothSandstoneStairs::Half::Top, SmoothSandstoneStairs::Shape::OuterRight).ID: return 9762; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_XP, SmoothSandstoneStairs::Half::Bottom, SmoothSandstoneStairs::Shape::Straight).ID: return 9764; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_XP, SmoothSandstoneStairs::Half::Bottom, SmoothSandstoneStairs::Shape::InnerLeft).ID: return 9766; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_XP, SmoothSandstoneStairs::Half::Bottom, SmoothSandstoneStairs::Shape::InnerRight).ID: return 9768; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_XP, SmoothSandstoneStairs::Half::Bottom, SmoothSandstoneStairs::Shape::OuterLeft).ID: return 9770; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_XP, SmoothSandstoneStairs::Half::Bottom, SmoothSandstoneStairs::Shape::OuterRight).ID: return 9772; case SmoothStone::SmoothStone().ID: return 7878; case SmoothStoneSlab::SmoothStoneSlab(SmoothStoneSlab::Type::Top).ID: return 7807; case SmoothStoneSlab::SmoothStoneSlab(SmoothStoneSlab::Type::Bottom).ID: return 7809; case SmoothStoneSlab::SmoothStoneSlab(SmoothStoneSlab::Type::Double).ID: return 7811; case Snow::Snow(1).ID: return 3919; case Snow::Snow(2).ID: return 3920; case Snow::Snow(3).ID: return 3921; case Snow::Snow(4).ID: return 3922; case Snow::Snow(5).ID: return 3923; case Snow::Snow(6).ID: return 3924; case Snow::Snow(7).ID: return 3925; case Snow::Snow(8).ID: return 3926; case SnowBlock::SnowBlock().ID: return 3928; case SoulSand::SoulSand().ID: return 3998; case Spawner::Spawner().ID: return 1951; case Sponge::Sponge().ID: return 228; case SpruceButton::SpruceButton(SpruceButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5834; case SpruceButton::SpruceButton(SpruceButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5835; case SpruceButton::SpruceButton(SpruceButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5836; case SpruceButton::SpruceButton(SpruceButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5837; case SpruceButton::SpruceButton(SpruceButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, true).ID: return 5838; case SpruceButton::SpruceButton(SpruceButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, false).ID: return 5839; case SpruceButton::SpruceButton(SpruceButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, true).ID: return 5840; case SpruceButton::SpruceButton(SpruceButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, false).ID: return 5841; case SpruceButton::SpruceButton(SpruceButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5842; case SpruceButton::SpruceButton(SpruceButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5843; case SpruceButton::SpruceButton(SpruceButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5844; case SpruceButton::SpruceButton(SpruceButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5845; case SpruceButton::SpruceButton(SpruceButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, true).ID: return 5846; case SpruceButton::SpruceButton(SpruceButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, false).ID: return 5847; case SpruceButton::SpruceButton(SpruceButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, true).ID: return 5848; case SpruceButton::SpruceButton(SpruceButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, false).ID: return 5849; case SpruceButton::SpruceButton(SpruceButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5850; case SpruceButton::SpruceButton(SpruceButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5851; case SpruceButton::SpruceButton(SpruceButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5852; case SpruceButton::SpruceButton(SpruceButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5853; case SpruceButton::SpruceButton(SpruceButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, true).ID: return 5854; case SpruceButton::SpruceButton(SpruceButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, false).ID: return 5855; case SpruceButton::SpruceButton(SpruceButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, true).ID: return 5856; case SpruceButton::SpruceButton(SpruceButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, false).ID: return 5857; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, true, true).ID: return 8202; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, true, false).ID: return 8203; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, false, true).ID: return 8204; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, false, false).ID: return 8205; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, true, true).ID: return 8206; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, true, false).ID: return 8207; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, false, true).ID: return 8208; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, false, false).ID: return 8209; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, true, true).ID: return 8210; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, true, false).ID: return 8211; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, false, true).ID: return 8212; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, false, false).ID: return 8213; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, true, true).ID: return 8214; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, true, false).ID: return 8215; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, false, true).ID: return 8216; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, false, false).ID: return 8217; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, true, true).ID: return 8218; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, true, false).ID: return 8219; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, false, true).ID: return 8220; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, false, false).ID: return 8221; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, true, true).ID: return 8222; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, true, false).ID: return 8223; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, false, true).ID: return 8224; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, false, false).ID: return 8225; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, true, true).ID: return 8226; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, true, false).ID: return 8227; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, false, true).ID: return 8228; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, false, false).ID: return 8229; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, true, true).ID: return 8230; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, true, false).ID: return 8231; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, false, true).ID: return 8232; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, false, false).ID: return 8233; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, true, true).ID: return 8234; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, true, false).ID: return 8235; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, false, true).ID: return 8236; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, false, false).ID: return 8237; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, true, true).ID: return 8238; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, true, false).ID: return 8239; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, false, true).ID: return 8240; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, false, false).ID: return 8241; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, true, true).ID: return 8242; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, true, false).ID: return 8243; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, false, true).ID: return 8244; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, false, false).ID: return 8245; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, true, true).ID: return 8246; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, true, false).ID: return 8247; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, false, true).ID: return 8248; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, false, false).ID: return 8249; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, true, true).ID: return 8250; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, true, false).ID: return 8251; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, false, true).ID: return 8252; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, false, false).ID: return 8253; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, true, true).ID: return 8254; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, true, false).ID: return 8255; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, false, true).ID: return 8256; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, false, false).ID: return 8257; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, true, true).ID: return 8258; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, true, false).ID: return 8259; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, false, true).ID: return 8260; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, false, false).ID: return 8261; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, true, true).ID: return 8262; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, true, false).ID: return 8263; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, false, true).ID: return 8264; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, false, false).ID: return 8265; case SpruceFence::SpruceFence(true, true, true, true).ID: return 8044; case SpruceFence::SpruceFence(true, true, true, false).ID: return 8045; case SpruceFence::SpruceFence(true, true, false, true).ID: return 8048; case SpruceFence::SpruceFence(true, true, false, false).ID: return 8049; case SpruceFence::SpruceFence(true, false, true, true).ID: return 8052; case SpruceFence::SpruceFence(true, false, true, false).ID: return 8053; case SpruceFence::SpruceFence(true, false, false, true).ID: return 8056; case SpruceFence::SpruceFence(true, false, false, false).ID: return 8057; case SpruceFence::SpruceFence(false, true, true, true).ID: return 8060; case SpruceFence::SpruceFence(false, true, true, false).ID: return 8061; case SpruceFence::SpruceFence(false, true, false, true).ID: return 8064; case SpruceFence::SpruceFence(false, true, false, false).ID: return 8065; case SpruceFence::SpruceFence(false, false, true, true).ID: return 8068; case SpruceFence::SpruceFence(false, false, true, false).ID: return 8069; case SpruceFence::SpruceFence(false, false, false, true).ID: return 8072; case SpruceFence::SpruceFence(false, false, false, false).ID: return 8073; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZM, true, true, true).ID: return 7882; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZM, true, true, false).ID: return 7883; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZM, true, false, true).ID: return 7884; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZM, true, false, false).ID: return 7885; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, true).ID: return 7886; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, false).ID: return 7887; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, true).ID: return 7888; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, false).ID: return 7889; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZP, true, true, true).ID: return 7890; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZP, true, true, false).ID: return 7891; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZP, true, false, true).ID: return 7892; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZP, true, false, false).ID: return 7893; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, true).ID: return 7894; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, false).ID: return 7895; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, true).ID: return 7896; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, false).ID: return 7897; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XM, true, true, true).ID: return 7898; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XM, true, true, false).ID: return 7899; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XM, true, false, true).ID: return 7900; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XM, true, false, false).ID: return 7901; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, true).ID: return 7902; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, false).ID: return 7903; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, true).ID: return 7904; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, false).ID: return 7905; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XP, true, true, true).ID: return 7906; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XP, true, true, false).ID: return 7907; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XP, true, false, true).ID: return 7908; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XP, true, false, false).ID: return 7909; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, true).ID: return 7910; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, false).ID: return 7911; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, true).ID: return 7912; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, false).ID: return 7913; case SpruceLeaves::SpruceLeaves(1, true).ID: return 158; case SpruceLeaves::SpruceLeaves(1, false).ID: return 159; case SpruceLeaves::SpruceLeaves(2, true).ID: return 160; case SpruceLeaves::SpruceLeaves(2, false).ID: return 161; case SpruceLeaves::SpruceLeaves(3, true).ID: return 162; case SpruceLeaves::SpruceLeaves(3, false).ID: return 163; case SpruceLeaves::SpruceLeaves(4, true).ID: return 164; case SpruceLeaves::SpruceLeaves(4, false).ID: return 165; case SpruceLeaves::SpruceLeaves(5, true).ID: return 166; case SpruceLeaves::SpruceLeaves(5, false).ID: return 167; case SpruceLeaves::SpruceLeaves(6, true).ID: return 168; case SpruceLeaves::SpruceLeaves(6, false).ID: return 169; case SpruceLeaves::SpruceLeaves(7, true).ID: return 170; case SpruceLeaves::SpruceLeaves(7, false).ID: return 171; case SpruceLog::SpruceLog(SpruceLog::Axis::X).ID: return 75; case SpruceLog::SpruceLog(SpruceLog::Axis::Y).ID: return 76; case SpruceLog::SpruceLog(SpruceLog::Axis::Z).ID: return 77; case SprucePlanks::SprucePlanks().ID: return 16; case SprucePressurePlate::SprucePressurePlate(true).ID: return 3873; case SprucePressurePlate::SprucePressurePlate(false).ID: return 3874; case SpruceSapling::SpruceSapling(0).ID: return 23; case SpruceSapling::SpruceSapling(1).ID: return 24; case SpruceSign::SpruceSign(0).ID: return 3412; case SpruceSign::SpruceSign(1).ID: return 3414; case SpruceSign::SpruceSign(2).ID: return 3416; case SpruceSign::SpruceSign(3).ID: return 3418; case SpruceSign::SpruceSign(4).ID: return 3420; case SpruceSign::SpruceSign(5).ID: return 3422; case SpruceSign::SpruceSign(6).ID: return 3424; case SpruceSign::SpruceSign(7).ID: return 3426; case SpruceSign::SpruceSign(8).ID: return 3428; case SpruceSign::SpruceSign(9).ID: return 3430; case SpruceSign::SpruceSign(10).ID: return 3432; case SpruceSign::SpruceSign(11).ID: return 3434; case SpruceSign::SpruceSign(12).ID: return 3436; case SpruceSign::SpruceSign(13).ID: return 3438; case SpruceSign::SpruceSign(14).ID: return 3440; case SpruceSign::SpruceSign(15).ID: return 3442; case SpruceSlab::SpruceSlab(SpruceSlab::Type::Top).ID: return 7771; case SpruceSlab::SpruceSlab(SpruceSlab::Type::Bottom).ID: return 7773; case SpruceSlab::SpruceSlab(SpruceSlab::Type::Double).ID: return 7775; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZM, SpruceStairs::Half::Top, SpruceStairs::Shape::Straight).ID: return 5389; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZM, SpruceStairs::Half::Top, SpruceStairs::Shape::InnerLeft).ID: return 5391; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZM, SpruceStairs::Half::Top, SpruceStairs::Shape::InnerRight).ID: return 5393; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZM, SpruceStairs::Half::Top, SpruceStairs::Shape::OuterLeft).ID: return 5395; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZM, SpruceStairs::Half::Top, SpruceStairs::Shape::OuterRight).ID: return 5397; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZM, SpruceStairs::Half::Bottom, SpruceStairs::Shape::Straight).ID: return 5399; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZM, SpruceStairs::Half::Bottom, SpruceStairs::Shape::InnerLeft).ID: return 5401; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZM, SpruceStairs::Half::Bottom, SpruceStairs::Shape::InnerRight).ID: return 5403; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZM, SpruceStairs::Half::Bottom, SpruceStairs::Shape::OuterLeft).ID: return 5405; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZM, SpruceStairs::Half::Bottom, SpruceStairs::Shape::OuterRight).ID: return 5407; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZP, SpruceStairs::Half::Top, SpruceStairs::Shape::Straight).ID: return 5409; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZP, SpruceStairs::Half::Top, SpruceStairs::Shape::InnerLeft).ID: return 5411; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZP, SpruceStairs::Half::Top, SpruceStairs::Shape::InnerRight).ID: return 5413; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZP, SpruceStairs::Half::Top, SpruceStairs::Shape::OuterLeft).ID: return 5415; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZP, SpruceStairs::Half::Top, SpruceStairs::Shape::OuterRight).ID: return 5417; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZP, SpruceStairs::Half::Bottom, SpruceStairs::Shape::Straight).ID: return 5419; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZP, SpruceStairs::Half::Bottom, SpruceStairs::Shape::InnerLeft).ID: return 5421; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZP, SpruceStairs::Half::Bottom, SpruceStairs::Shape::InnerRight).ID: return 5423; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZP, SpruceStairs::Half::Bottom, SpruceStairs::Shape::OuterLeft).ID: return 5425; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZP, SpruceStairs::Half::Bottom, SpruceStairs::Shape::OuterRight).ID: return 5427; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XM, SpruceStairs::Half::Top, SpruceStairs::Shape::Straight).ID: return 5429; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XM, SpruceStairs::Half::Top, SpruceStairs::Shape::InnerLeft).ID: return 5431; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XM, SpruceStairs::Half::Top, SpruceStairs::Shape::InnerRight).ID: return 5433; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XM, SpruceStairs::Half::Top, SpruceStairs::Shape::OuterLeft).ID: return 5435; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XM, SpruceStairs::Half::Top, SpruceStairs::Shape::OuterRight).ID: return 5437; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XM, SpruceStairs::Half::Bottom, SpruceStairs::Shape::Straight).ID: return 5439; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XM, SpruceStairs::Half::Bottom, SpruceStairs::Shape::InnerLeft).ID: return 5441; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XM, SpruceStairs::Half::Bottom, SpruceStairs::Shape::InnerRight).ID: return 5443; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XM, SpruceStairs::Half::Bottom, SpruceStairs::Shape::OuterLeft).ID: return 5445; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XM, SpruceStairs::Half::Bottom, SpruceStairs::Shape::OuterRight).ID: return 5447; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XP, SpruceStairs::Half::Top, SpruceStairs::Shape::Straight).ID: return 5449; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XP, SpruceStairs::Half::Top, SpruceStairs::Shape::InnerLeft).ID: return 5451; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XP, SpruceStairs::Half::Top, SpruceStairs::Shape::InnerRight).ID: return 5453; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XP, SpruceStairs::Half::Top, SpruceStairs::Shape::OuterLeft).ID: return 5455; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XP, SpruceStairs::Half::Top, SpruceStairs::Shape::OuterRight).ID: return 5457; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XP, SpruceStairs::Half::Bottom, SpruceStairs::Shape::Straight).ID: return 5459; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XP, SpruceStairs::Half::Bottom, SpruceStairs::Shape::InnerLeft).ID: return 5461; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XP, SpruceStairs::Half::Bottom, SpruceStairs::Shape::InnerRight).ID: return 5463; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XP, SpruceStairs::Half::Bottom, SpruceStairs::Shape::OuterLeft).ID: return 5465; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XP, SpruceStairs::Half::Bottom, SpruceStairs::Shape::OuterRight).ID: return 5467; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZM, SpruceTrapdoor::Half::Top, true, true).ID: return 4162; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZM, SpruceTrapdoor::Half::Top, true, false).ID: return 4164; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZM, SpruceTrapdoor::Half::Top, false, true).ID: return 4166; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZM, SpruceTrapdoor::Half::Top, false, false).ID: return 4168; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZM, SpruceTrapdoor::Half::Bottom, true, true).ID: return 4170; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZM, SpruceTrapdoor::Half::Bottom, true, false).ID: return 4172; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZM, SpruceTrapdoor::Half::Bottom, false, true).ID: return 4174; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZM, SpruceTrapdoor::Half::Bottom, false, false).ID: return 4176; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZP, SpruceTrapdoor::Half::Top, true, true).ID: return 4178; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZP, SpruceTrapdoor::Half::Top, true, false).ID: return 4180; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZP, SpruceTrapdoor::Half::Top, false, true).ID: return 4182; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZP, SpruceTrapdoor::Half::Top, false, false).ID: return 4184; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZP, SpruceTrapdoor::Half::Bottom, true, true).ID: return 4186; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZP, SpruceTrapdoor::Half::Bottom, true, false).ID: return 4188; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZP, SpruceTrapdoor::Half::Bottom, false, true).ID: return 4190; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZP, SpruceTrapdoor::Half::Bottom, false, false).ID: return 4192; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XM, SpruceTrapdoor::Half::Top, true, true).ID: return 4194; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XM, SpruceTrapdoor::Half::Top, true, false).ID: return 4196; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XM, SpruceTrapdoor::Half::Top, false, true).ID: return 4198; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XM, SpruceTrapdoor::Half::Top, false, false).ID: return 4200; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XM, SpruceTrapdoor::Half::Bottom, true, true).ID: return 4202; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XM, SpruceTrapdoor::Half::Bottom, true, false).ID: return 4204; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XM, SpruceTrapdoor::Half::Bottom, false, true).ID: return 4206; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XM, SpruceTrapdoor::Half::Bottom, false, false).ID: return 4208; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XP, SpruceTrapdoor::Half::Top, true, true).ID: return 4210; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XP, SpruceTrapdoor::Half::Top, true, false).ID: return 4212; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XP, SpruceTrapdoor::Half::Top, false, true).ID: return 4214; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XP, SpruceTrapdoor::Half::Top, false, false).ID: return 4216; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XP, SpruceTrapdoor::Half::Bottom, true, true).ID: return 4218; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XP, SpruceTrapdoor::Half::Bottom, true, false).ID: return 4220; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XP, SpruceTrapdoor::Half::Bottom, false, true).ID: return 4222; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XP, SpruceTrapdoor::Half::Bottom, false, false).ID: return 4224; case SpruceWallSign::SpruceWallSign(eBlockFace::BLOCK_FACE_ZM).ID: return 3742; case SpruceWallSign::SpruceWallSign(eBlockFace::BLOCK_FACE_ZP).ID: return 3744; case SpruceWallSign::SpruceWallSign(eBlockFace::BLOCK_FACE_XM).ID: return 3746; case SpruceWallSign::SpruceWallSign(eBlockFace::BLOCK_FACE_XP).ID: return 3748; case SpruceWood::SpruceWood(SpruceWood::Axis::X).ID: return 111; case SpruceWood::SpruceWood(SpruceWood::Axis::Y).ID: return 112; case SpruceWood::SpruceWood(SpruceWood::Axis::Z).ID: return 113; case StickyPiston::StickyPiston(true, eBlockFace::BLOCK_FACE_ZM).ID: return 1328; case StickyPiston::StickyPiston(true, eBlockFace::BLOCK_FACE_XP).ID: return 1329; case StickyPiston::StickyPiston(true, eBlockFace::BLOCK_FACE_ZP).ID: return 1330; case StickyPiston::StickyPiston(true, eBlockFace::BLOCK_FACE_XM).ID: return 1331; case StickyPiston::StickyPiston(true, eBlockFace::BLOCK_FACE_YP).ID: return 1332; case StickyPiston::StickyPiston(true, eBlockFace::BLOCK_FACE_YM).ID: return 1333; case StickyPiston::StickyPiston(false, eBlockFace::BLOCK_FACE_ZM).ID: return 1334; case StickyPiston::StickyPiston(false, eBlockFace::BLOCK_FACE_XP).ID: return 1335; case StickyPiston::StickyPiston(false, eBlockFace::BLOCK_FACE_ZP).ID: return 1336; case StickyPiston::StickyPiston(false, eBlockFace::BLOCK_FACE_XM).ID: return 1337; case StickyPiston::StickyPiston(false, eBlockFace::BLOCK_FACE_YP).ID: return 1338; case StickyPiston::StickyPiston(false, eBlockFace::BLOCK_FACE_YM).ID: return 1339; case Stone::Stone().ID: return 1; case StoneBrickSlab::StoneBrickSlab(StoneBrickSlab::Type::Top).ID: return 7843; case StoneBrickSlab::StoneBrickSlab(StoneBrickSlab::Type::Bottom).ID: return 7845; case StoneBrickSlab::StoneBrickSlab(StoneBrickSlab::Type::Double).ID: return 7847; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::Straight).ID: return 4917; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::InnerLeft).ID: return 4919; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::InnerRight).ID: return 4921; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::OuterLeft).ID: return 4923; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::OuterRight).ID: return 4925; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::Straight).ID: return 4927; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::InnerLeft).ID: return 4929; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::InnerRight).ID: return 4931; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::OuterLeft).ID: return 4933; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::OuterRight).ID: return 4935; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::Straight).ID: return 4937; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::InnerLeft).ID: return 4939; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::InnerRight).ID: return 4941; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::OuterLeft).ID: return 4943; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::OuterRight).ID: return 4945; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::Straight).ID: return 4947; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::InnerLeft).ID: return 4949; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::InnerRight).ID: return 4951; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::OuterLeft).ID: return 4953; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::OuterRight).ID: return 4955; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XM, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::Straight).ID: return 4957; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XM, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::InnerLeft).ID: return 4959; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XM, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::InnerRight).ID: return 4961; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XM, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::OuterLeft).ID: return 4963; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XM, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::OuterRight).ID: return 4965; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XM, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::Straight).ID: return 4967; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XM, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::InnerLeft).ID: return 4969; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XM, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::InnerRight).ID: return 4971; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XM, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::OuterLeft).ID: return 4973; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XM, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::OuterRight).ID: return 4975; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XP, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::Straight).ID: return 4977; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XP, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::InnerLeft).ID: return 4979; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XP, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::InnerRight).ID: return 4981; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XP, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::OuterLeft).ID: return 4983; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XP, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::OuterRight).ID: return 4985; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XP, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::Straight).ID: return 4987; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XP, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::InnerLeft).ID: return 4989; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XP, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::InnerRight).ID: return 4991; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XP, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::OuterLeft).ID: return 4993; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XP, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::OuterRight).ID: return 4995; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::Low, StoneBrickWall::South::Low, true, StoneBrickWall::West::Low).ID: return 10653; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::Low, StoneBrickWall::South::Low, true, StoneBrickWall::West::None).ID: return 10654; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::Low, StoneBrickWall::South::Low, false, StoneBrickWall::West::Low).ID: return 10657; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::Low, StoneBrickWall::South::Low, false, StoneBrickWall::West::None).ID: return 10658; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::Low, StoneBrickWall::South::None, true, StoneBrickWall::West::Low).ID: return 10661; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::Low, StoneBrickWall::South::None, true, StoneBrickWall::West::None).ID: return 10662; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::Low, StoneBrickWall::South::None, false, StoneBrickWall::West::Low).ID: return 10665; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::Low, StoneBrickWall::South::None, false, StoneBrickWall::West::None).ID: return 10666; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::None, StoneBrickWall::South::Low, true, StoneBrickWall::West::Low).ID: return 10669; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::None, StoneBrickWall::South::Low, true, StoneBrickWall::West::None).ID: return 10670; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::None, StoneBrickWall::South::Low, false, StoneBrickWall::West::Low).ID: return 10673; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::None, StoneBrickWall::South::Low, false, StoneBrickWall::West::None).ID: return 10674; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::None, StoneBrickWall::South::None, true, StoneBrickWall::West::Low).ID: return 10677; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::None, StoneBrickWall::South::None, true, StoneBrickWall::West::None).ID: return 10678; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::None, StoneBrickWall::South::None, false, StoneBrickWall::West::Low).ID: return 10681; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::None, StoneBrickWall::South::None, false, StoneBrickWall::West::None).ID: return 10682; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::Low, StoneBrickWall::South::Low, true, StoneBrickWall::West::Low).ID: return 10685; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::Low, StoneBrickWall::South::Low, true, StoneBrickWall::West::None).ID: return 10686; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::Low, StoneBrickWall::South::Low, false, StoneBrickWall::West::Low).ID: return 10689; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::Low, StoneBrickWall::South::Low, false, StoneBrickWall::West::None).ID: return 10690; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::Low, StoneBrickWall::South::None, true, StoneBrickWall::West::Low).ID: return 10693; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::Low, StoneBrickWall::South::None, true, StoneBrickWall::West::None).ID: return 10694; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::Low, StoneBrickWall::South::None, false, StoneBrickWall::West::Low).ID: return 10697; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::Low, StoneBrickWall::South::None, false, StoneBrickWall::West::None).ID: return 10698; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::None, StoneBrickWall::South::Low, true, StoneBrickWall::West::Low).ID: return 10701; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::None, StoneBrickWall::South::Low, true, StoneBrickWall::West::None).ID: return 10702; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::None, StoneBrickWall::South::Low, false, StoneBrickWall::West::Low).ID: return 10705; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::None, StoneBrickWall::South::Low, false, StoneBrickWall::West::None).ID: return 10706; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::None, StoneBrickWall::South::None, true, StoneBrickWall::West::Low).ID: return 10709; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::None, StoneBrickWall::South::None, true, StoneBrickWall::West::None).ID: return 10710; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::None, StoneBrickWall::South::None, false, StoneBrickWall::West::Low).ID: return 10713; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::None, StoneBrickWall::South::None, false, StoneBrickWall::West::None).ID: return 10714; case StoneBricks::StoneBricks().ID: return 4481; case StoneButton::StoneButton(StoneButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, true).ID: return 3895; case StoneButton::StoneButton(StoneButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, false).ID: return 3896; case StoneButton::StoneButton(StoneButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, true).ID: return 3897; case StoneButton::StoneButton(StoneButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, false).ID: return 3898; case StoneButton::StoneButton(StoneButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, true).ID: return 3899; case StoneButton::StoneButton(StoneButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, false).ID: return 3900; case StoneButton::StoneButton(StoneButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, true).ID: return 3901; case StoneButton::StoneButton(StoneButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, false).ID: return 3902; case StoneButton::StoneButton(StoneButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, true).ID: return 3903; case StoneButton::StoneButton(StoneButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, false).ID: return 3904; case StoneButton::StoneButton(StoneButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, true).ID: return 3905; case StoneButton::StoneButton(StoneButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, false).ID: return 3906; case StoneButton::StoneButton(StoneButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, true).ID: return 3907; case StoneButton::StoneButton(StoneButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, false).ID: return 3908; case StoneButton::StoneButton(StoneButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, true).ID: return 3909; case StoneButton::StoneButton(StoneButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, false).ID: return 3910; case StoneButton::StoneButton(StoneButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, true).ID: return 3911; case StoneButton::StoneButton(StoneButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, false).ID: return 3912; case StoneButton::StoneButton(StoneButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, true).ID: return 3913; case StoneButton::StoneButton(StoneButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, false).ID: return 3914; case StoneButton::StoneButton(StoneButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, true).ID: return 3915; case StoneButton::StoneButton(StoneButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, false).ID: return 3916; case StoneButton::StoneButton(StoneButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, true).ID: return 3917; case StoneButton::StoneButton(StoneButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, false).ID: return 3918; case StonePressurePlate::StonePressurePlate(true).ID: return 3805; case StonePressurePlate::StonePressurePlate(false).ID: return 3806; case StoneSlab::StoneSlab(StoneSlab::Type::Top).ID: return 7801; case StoneSlab::StoneSlab(StoneSlab::Type::Bottom).ID: return 7803; case StoneSlab::StoneSlab(StoneSlab::Type::Double).ID: return 7805; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_ZM, StoneStairs::Half::Top, StoneStairs::Shape::Straight).ID: return 9614; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_ZM, StoneStairs::Half::Top, StoneStairs::Shape::InnerLeft).ID: return 9616; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_ZM, StoneStairs::Half::Top, StoneStairs::Shape::InnerRight).ID: return 9618; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_ZM, StoneStairs::Half::Top, StoneStairs::Shape::OuterLeft).ID: return 9620; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_ZM, StoneStairs::Half::Top, StoneStairs::Shape::OuterRight).ID: return 9622; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_ZM, StoneStairs::Half::Bottom, StoneStairs::Shape::Straight).ID: return 9624; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_ZM, StoneStairs::Half::Bottom, StoneStairs::Shape::InnerLeft).ID: return 9626; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_ZM, StoneStairs::Half::Bottom, StoneStairs::Shape::InnerRight).ID: return 9628; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_ZM, StoneStairs::Half::Bottom, StoneStairs::Shape::OuterLeft).ID: return 9630; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_ZM, StoneStairs::Half::Bottom, StoneStairs::Shape::OuterRight).ID: return 9632; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_ZP, StoneStairs::Half::Top, StoneStairs::Shape::Straight).ID: return 9634; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_ZP, StoneStairs::Half::Top, StoneStairs::Shape::InnerLeft).ID: return 9636; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_ZP, StoneStairs::Half::Top, StoneStairs::Shape::InnerRight).ID: return 9638; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_ZP, StoneStairs::Half::Top, StoneStairs::Shape::OuterLeft).ID: return 9640; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_ZP, StoneStairs::Half::Top, StoneStairs::Shape::OuterRight).ID: return 9642; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_ZP, StoneStairs::Half::Bottom, StoneStairs::Shape::Straight).ID: return 9644; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_ZP, StoneStairs::Half::Bottom, StoneStairs::Shape::InnerLeft).ID: return 9646; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_ZP, StoneStairs::Half::Bottom, StoneStairs::Shape::InnerRight).ID: return 9648; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_ZP, StoneStairs::Half::Bottom, StoneStairs::Shape::OuterLeft).ID: return 9650; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_ZP, StoneStairs::Half::Bottom, StoneStairs::Shape::OuterRight).ID: return 9652; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_XM, StoneStairs::Half::Top, StoneStairs::Shape::Straight).ID: return 9654; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_XM, StoneStairs::Half::Top, StoneStairs::Shape::InnerLeft).ID: return 9656; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_XM, StoneStairs::Half::Top, StoneStairs::Shape::InnerRight).ID: return 9658; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_XM, StoneStairs::Half::Top, StoneStairs::Shape::OuterLeft).ID: return 9660; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_XM, StoneStairs::Half::Top, StoneStairs::Shape::OuterRight).ID: return 9662; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_XM, StoneStairs::Half::Bottom, StoneStairs::Shape::Straight).ID: return 9664; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_XM, StoneStairs::Half::Bottom, StoneStairs::Shape::InnerLeft).ID: return 9666; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_XM, StoneStairs::Half::Bottom, StoneStairs::Shape::InnerRight).ID: return 9668; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_XM, StoneStairs::Half::Bottom, StoneStairs::Shape::OuterLeft).ID: return 9670; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_XM, StoneStairs::Half::Bottom, StoneStairs::Shape::OuterRight).ID: return 9672; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_XP, StoneStairs::Half::Top, StoneStairs::Shape::Straight).ID: return 9674; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_XP, StoneStairs::Half::Top, StoneStairs::Shape::InnerLeft).ID: return 9676; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_XP, StoneStairs::Half::Top, StoneStairs::Shape::InnerRight).ID: return 9678; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_XP, StoneStairs::Half::Top, StoneStairs::Shape::OuterLeft).ID: return 9680; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_XP, StoneStairs::Half::Top, StoneStairs::Shape::OuterRight).ID: return 9682; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_XP, StoneStairs::Half::Bottom, StoneStairs::Shape::Straight).ID: return 9684; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_XP, StoneStairs::Half::Bottom, StoneStairs::Shape::InnerLeft).ID: return 9686; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_XP, StoneStairs::Half::Bottom, StoneStairs::Shape::InnerRight).ID: return 9688; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_XP, StoneStairs::Half::Bottom, StoneStairs::Shape::OuterLeft).ID: return 9690; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_XP, StoneStairs::Half::Bottom, StoneStairs::Shape::OuterRight).ID: return 9692; case Stonecutter::Stonecutter(eBlockFace::BLOCK_FACE_ZM).ID: return 11194; case Stonecutter::Stonecutter(eBlockFace::BLOCK_FACE_ZP).ID: return 11195; case Stonecutter::Stonecutter(eBlockFace::BLOCK_FACE_XM).ID: return 11196; case Stonecutter::Stonecutter(eBlockFace::BLOCK_FACE_XP).ID: return 11197; case StrippedAcaciaLog::StrippedAcaciaLog(StrippedAcaciaLog::Axis::X).ID: return 99; case StrippedAcaciaLog::StrippedAcaciaLog(StrippedAcaciaLog::Axis::Y).ID: return 100; case StrippedAcaciaLog::StrippedAcaciaLog(StrippedAcaciaLog::Axis::Z).ID: return 101; case StrippedAcaciaWood::StrippedAcaciaWood(StrippedAcaciaWood::Axis::X).ID: return 138; case StrippedAcaciaWood::StrippedAcaciaWood(StrippedAcaciaWood::Axis::Y).ID: return 139; case StrippedAcaciaWood::StrippedAcaciaWood(StrippedAcaciaWood::Axis::Z).ID: return 140; case StrippedBirchLog::StrippedBirchLog(StrippedBirchLog::Axis::X).ID: return 93; case StrippedBirchLog::StrippedBirchLog(StrippedBirchLog::Axis::Y).ID: return 94; case StrippedBirchLog::StrippedBirchLog(StrippedBirchLog::Axis::Z).ID: return 95; case StrippedBirchWood::StrippedBirchWood(StrippedBirchWood::Axis::X).ID: return 132; case StrippedBirchWood::StrippedBirchWood(StrippedBirchWood::Axis::Y).ID: return 133; case StrippedBirchWood::StrippedBirchWood(StrippedBirchWood::Axis::Z).ID: return 134; case StrippedDarkOakLog::StrippedDarkOakLog(StrippedDarkOakLog::Axis::X).ID: return 102; case StrippedDarkOakLog::StrippedDarkOakLog(StrippedDarkOakLog::Axis::Y).ID: return 103; case StrippedDarkOakLog::StrippedDarkOakLog(StrippedDarkOakLog::Axis::Z).ID: return 104; case StrippedDarkOakWood::StrippedDarkOakWood(StrippedDarkOakWood::Axis::X).ID: return 141; case StrippedDarkOakWood::StrippedDarkOakWood(StrippedDarkOakWood::Axis::Y).ID: return 142; case StrippedDarkOakWood::StrippedDarkOakWood(StrippedDarkOakWood::Axis::Z).ID: return 143; case StrippedJungleLog::StrippedJungleLog(StrippedJungleLog::Axis::X).ID: return 96; case StrippedJungleLog::StrippedJungleLog(StrippedJungleLog::Axis::Y).ID: return 97; case StrippedJungleLog::StrippedJungleLog(StrippedJungleLog::Axis::Z).ID: return 98; case StrippedJungleWood::StrippedJungleWood(StrippedJungleWood::Axis::X).ID: return 135; case StrippedJungleWood::StrippedJungleWood(StrippedJungleWood::Axis::Y).ID: return 136; case StrippedJungleWood::StrippedJungleWood(StrippedJungleWood::Axis::Z).ID: return 137; case StrippedOakLog::StrippedOakLog(StrippedOakLog::Axis::X).ID: return 105; case StrippedOakLog::StrippedOakLog(StrippedOakLog::Axis::Y).ID: return 106; case StrippedOakLog::StrippedOakLog(StrippedOakLog::Axis::Z).ID: return 107; case StrippedOakWood::StrippedOakWood(StrippedOakWood::Axis::X).ID: return 126; case StrippedOakWood::StrippedOakWood(StrippedOakWood::Axis::Y).ID: return 127; case StrippedOakWood::StrippedOakWood(StrippedOakWood::Axis::Z).ID: return 128; case StrippedSpruceLog::StrippedSpruceLog(StrippedSpruceLog::Axis::X).ID: return 90; case StrippedSpruceLog::StrippedSpruceLog(StrippedSpruceLog::Axis::Y).ID: return 91; case StrippedSpruceLog::StrippedSpruceLog(StrippedSpruceLog::Axis::Z).ID: return 92; case StrippedSpruceWood::StrippedSpruceWood(StrippedSpruceWood::Axis::X).ID: return 129; case StrippedSpruceWood::StrippedSpruceWood(StrippedSpruceWood::Axis::Y).ID: return 130; case StrippedSpruceWood::StrippedSpruceWood(StrippedSpruceWood::Axis::Z).ID: return 131; case StructureBlock::StructureBlock(StructureBlock::Mode::Save).ID: return 11268; case StructureBlock::StructureBlock(StructureBlock::Mode::Load).ID: return 11269; case StructureBlock::StructureBlock(StructureBlock::Mode::Corner).ID: return 11270; case StructureBlock::StructureBlock(StructureBlock::Mode::Data).ID: return 11271; case StructureVoid::StructureVoid().ID: return 8723; case SugarCane::SugarCane(0).ID: return 3946; case SugarCane::SugarCane(1).ID: return 3947; case SugarCane::SugarCane(2).ID: return 3948; case SugarCane::SugarCane(3).ID: return 3949; case SugarCane::SugarCane(4).ID: return 3950; case SugarCane::SugarCane(5).ID: return 3951; case SugarCane::SugarCane(6).ID: return 3952; case SugarCane::SugarCane(7).ID: return 3953; case SugarCane::SugarCane(8).ID: return 3954; case SugarCane::SugarCane(9).ID: return 3955; case SugarCane::SugarCane(10).ID: return 3956; case SugarCane::SugarCane(11).ID: return 3957; case SugarCane::SugarCane(12).ID: return 3958; case SugarCane::SugarCane(13).ID: return 3959; case SugarCane::SugarCane(14).ID: return 3960; case SugarCane::SugarCane(15).ID: return 3961; case Sunflower::Sunflower(Sunflower::Half::Upper).ID: return 7349; case Sunflower::Sunflower(Sunflower::Half::Lower).ID: return 7350; case SweetBerryBush::SweetBerryBush(0).ID: return 11264; case SweetBerryBush::SweetBerryBush(1).ID: return 11265; case SweetBerryBush::SweetBerryBush(2).ID: return 11266; case SweetBerryBush::SweetBerryBush(3).ID: return 11267; case TNT::TNT(true).ID: return 1429; case TNT::TNT(false).ID: return 1430; case TallGrass::TallGrass(TallGrass::Half::Upper).ID: return 7357; case TallGrass::TallGrass(TallGrass::Half::Lower).ID: return 7358; case TallSeagrass::TallSeagrass(TallSeagrass::Half::Upper).ID: return 1345; case TallSeagrass::TallSeagrass(TallSeagrass::Half::Lower).ID: return 1346; case Terracotta::Terracotta().ID: return 7346; case Torch::Torch().ID: return 1434; case TrappedChest::TrappedChest(eBlockFace::BLOCK_FACE_ZM, TrappedChest::Type::Single).ID: return 6087; case TrappedChest::TrappedChest(eBlockFace::BLOCK_FACE_ZM, TrappedChest::Type::Left).ID: return 6089; case TrappedChest::TrappedChest(eBlockFace::BLOCK_FACE_ZM, TrappedChest::Type::Right).ID: return 6091; case TrappedChest::TrappedChest(eBlockFace::BLOCK_FACE_ZP, TrappedChest::Type::Single).ID: return 6093; case TrappedChest::TrappedChest(eBlockFace::BLOCK_FACE_ZP, TrappedChest::Type::Left).ID: return 6095; case TrappedChest::TrappedChest(eBlockFace::BLOCK_FACE_ZP, TrappedChest::Type::Right).ID: return 6097; case TrappedChest::TrappedChest(eBlockFace::BLOCK_FACE_XM, TrappedChest::Type::Single).ID: return 6099; case TrappedChest::TrappedChest(eBlockFace::BLOCK_FACE_XM, TrappedChest::Type::Left).ID: return 6101; case TrappedChest::TrappedChest(eBlockFace::BLOCK_FACE_XM, TrappedChest::Type::Right).ID: return 6103; case TrappedChest::TrappedChest(eBlockFace::BLOCK_FACE_XP, TrappedChest::Type::Single).ID: return 6105; case TrappedChest::TrappedChest(eBlockFace::BLOCK_FACE_XP, TrappedChest::Type::Left).ID: return 6107; case TrappedChest::TrappedChest(eBlockFace::BLOCK_FACE_XP, TrappedChest::Type::Right).ID: return 6109; case Tripwire::Tripwire(true, true, true, true, true, true, true).ID: return 5259; case Tripwire::Tripwire(true, true, true, true, true, true, false).ID: return 5260; case Tripwire::Tripwire(true, true, true, true, true, false, true).ID: return 5261; case Tripwire::Tripwire(true, true, true, true, true, false, false).ID: return 5262; case Tripwire::Tripwire(true, true, true, true, false, true, true).ID: return 5263; case Tripwire::Tripwire(true, true, true, true, false, true, false).ID: return 5264; case Tripwire::Tripwire(true, true, true, true, false, false, true).ID: return 5265; case Tripwire::Tripwire(true, true, true, true, false, false, false).ID: return 5266; case Tripwire::Tripwire(true, true, true, false, true, true, true).ID: return 5267; case Tripwire::Tripwire(true, true, true, false, true, true, false).ID: return 5268; case Tripwire::Tripwire(true, true, true, false, true, false, true).ID: return 5269; case Tripwire::Tripwire(true, true, true, false, true, false, false).ID: return 5270; case Tripwire::Tripwire(true, true, true, false, false, true, true).ID: return 5271; case Tripwire::Tripwire(true, true, true, false, false, true, false).ID: return 5272; case Tripwire::Tripwire(true, true, true, false, false, false, true).ID: return 5273; case Tripwire::Tripwire(true, true, true, false, false, false, false).ID: return 5274; case Tripwire::Tripwire(true, true, false, true, true, true, true).ID: return 5275; case Tripwire::Tripwire(true, true, false, true, true, true, false).ID: return 5276; case Tripwire::Tripwire(true, true, false, true, true, false, true).ID: return 5277; case Tripwire::Tripwire(true, true, false, true, true, false, false).ID: return 5278; case Tripwire::Tripwire(true, true, false, true, false, true, true).ID: return 5279; case Tripwire::Tripwire(true, true, false, true, false, true, false).ID: return 5280; case Tripwire::Tripwire(true, true, false, true, false, false, true).ID: return 5281; case Tripwire::Tripwire(true, true, false, true, false, false, false).ID: return 5282; case Tripwire::Tripwire(true, true, false, false, true, true, true).ID: return 5283; case Tripwire::Tripwire(true, true, false, false, true, true, false).ID: return 5284; case Tripwire::Tripwire(true, true, false, false, true, false, true).ID: return 5285; case Tripwire::Tripwire(true, true, false, false, true, false, false).ID: return 5286; case Tripwire::Tripwire(true, true, false, false, false, true, true).ID: return 5287; case Tripwire::Tripwire(true, true, false, false, false, true, false).ID: return 5288; case Tripwire::Tripwire(true, true, false, false, false, false, true).ID: return 5289; case Tripwire::Tripwire(true, true, false, false, false, false, false).ID: return 5290; case Tripwire::Tripwire(true, false, true, true, true, true, true).ID: return 5291; case Tripwire::Tripwire(true, false, true, true, true, true, false).ID: return 5292; case Tripwire::Tripwire(true, false, true, true, true, false, true).ID: return 5293; case Tripwire::Tripwire(true, false, true, true, true, false, false).ID: return 5294; case Tripwire::Tripwire(true, false, true, true, false, true, true).ID: return 5295; case Tripwire::Tripwire(true, false, true, true, false, true, false).ID: return 5296; case Tripwire::Tripwire(true, false, true, true, false, false, true).ID: return 5297; case Tripwire::Tripwire(true, false, true, true, false, false, false).ID: return 5298; case Tripwire::Tripwire(true, false, true, false, true, true, true).ID: return 5299; case Tripwire::Tripwire(true, false, true, false, true, true, false).ID: return 5300; case Tripwire::Tripwire(true, false, true, false, true, false, true).ID: return 5301; case Tripwire::Tripwire(true, false, true, false, true, false, false).ID: return 5302; case Tripwire::Tripwire(true, false, true, false, false, true, true).ID: return 5303; case Tripwire::Tripwire(true, false, true, false, false, true, false).ID: return 5304; case Tripwire::Tripwire(true, false, true, false, false, false, true).ID: return 5305; case Tripwire::Tripwire(true, false, true, false, false, false, false).ID: return 5306; case Tripwire::Tripwire(true, false, false, true, true, true, true).ID: return 5307; case Tripwire::Tripwire(true, false, false, true, true, true, false).ID: return 5308; case Tripwire::Tripwire(true, false, false, true, true, false, true).ID: return 5309; case Tripwire::Tripwire(true, false, false, true, true, false, false).ID: return 5310; case Tripwire::Tripwire(true, false, false, true, false, true, true).ID: return 5311; case Tripwire::Tripwire(true, false, false, true, false, true, false).ID: return 5312; case Tripwire::Tripwire(true, false, false, true, false, false, true).ID: return 5313; case Tripwire::Tripwire(true, false, false, true, false, false, false).ID: return 5314; case Tripwire::Tripwire(true, false, false, false, true, true, true).ID: return 5315; case Tripwire::Tripwire(true, false, false, false, true, true, false).ID: return 5316; case Tripwire::Tripwire(true, false, false, false, true, false, true).ID: return 5317; case Tripwire::Tripwire(true, false, false, false, true, false, false).ID: return 5318; case Tripwire::Tripwire(true, false, false, false, false, true, true).ID: return 5319; case Tripwire::Tripwire(true, false, false, false, false, true, false).ID: return 5320; case Tripwire::Tripwire(true, false, false, false, false, false, true).ID: return 5321; case Tripwire::Tripwire(true, false, false, false, false, false, false).ID: return 5322; case Tripwire::Tripwire(false, true, true, true, true, true, true).ID: return 5323; case Tripwire::Tripwire(false, true, true, true, true, true, false).ID: return 5324; case Tripwire::Tripwire(false, true, true, true, true, false, true).ID: return 5325; case Tripwire::Tripwire(false, true, true, true, true, false, false).ID: return 5326; case Tripwire::Tripwire(false, true, true, true, false, true, true).ID: return 5327; case Tripwire::Tripwire(false, true, true, true, false, true, false).ID: return 5328; case Tripwire::Tripwire(false, true, true, true, false, false, true).ID: return 5329; case Tripwire::Tripwire(false, true, true, true, false, false, false).ID: return 5330; case Tripwire::Tripwire(false, true, true, false, true, true, true).ID: return 5331; case Tripwire::Tripwire(false, true, true, false, true, true, false).ID: return 5332; case Tripwire::Tripwire(false, true, true, false, true, false, true).ID: return 5333; case Tripwire::Tripwire(false, true, true, false, true, false, false).ID: return 5334; case Tripwire::Tripwire(false, true, true, false, false, true, true).ID: return 5335; case Tripwire::Tripwire(false, true, true, false, false, true, false).ID: return 5336; case Tripwire::Tripwire(false, true, true, false, false, false, true).ID: return 5337; case Tripwire::Tripwire(false, true, true, false, false, false, false).ID: return 5338; case Tripwire::Tripwire(false, true, false, true, true, true, true).ID: return 5339; case Tripwire::Tripwire(false, true, false, true, true, true, false).ID: return 5340; case Tripwire::Tripwire(false, true, false, true, true, false, true).ID: return 5341; case Tripwire::Tripwire(false, true, false, true, true, false, false).ID: return 5342; case Tripwire::Tripwire(false, true, false, true, false, true, true).ID: return 5343; case Tripwire::Tripwire(false, true, false, true, false, true, false).ID: return 5344; case Tripwire::Tripwire(false, true, false, true, false, false, true).ID: return 5345; case Tripwire::Tripwire(false, true, false, true, false, false, false).ID: return 5346; case Tripwire::Tripwire(false, true, false, false, true, true, true).ID: return 5347; case Tripwire::Tripwire(false, true, false, false, true, true, false).ID: return 5348; case Tripwire::Tripwire(false, true, false, false, true, false, true).ID: return 5349; case Tripwire::Tripwire(false, true, false, false, true, false, false).ID: return 5350; case Tripwire::Tripwire(false, true, false, false, false, true, true).ID: return 5351; case Tripwire::Tripwire(false, true, false, false, false, true, false).ID: return 5352; case Tripwire::Tripwire(false, true, false, false, false, false, true).ID: return 5353; case Tripwire::Tripwire(false, true, false, false, false, false, false).ID: return 5354; case Tripwire::Tripwire(false, false, true, true, true, true, true).ID: return 5355; case Tripwire::Tripwire(false, false, true, true, true, true, false).ID: return 5356; case Tripwire::Tripwire(false, false, true, true, true, false, true).ID: return 5357; case Tripwire::Tripwire(false, false, true, true, true, false, false).ID: return 5358; case Tripwire::Tripwire(false, false, true, true, false, true, true).ID: return 5359; case Tripwire::Tripwire(false, false, true, true, false, true, false).ID: return 5360; case Tripwire::Tripwire(false, false, true, true, false, false, true).ID: return 5361; case Tripwire::Tripwire(false, false, true, true, false, false, false).ID: return 5362; case Tripwire::Tripwire(false, false, true, false, true, true, true).ID: return 5363; case Tripwire::Tripwire(false, false, true, false, true, true, false).ID: return 5364; case Tripwire::Tripwire(false, false, true, false, true, false, true).ID: return 5365; case Tripwire::Tripwire(false, false, true, false, true, false, false).ID: return 5366; case Tripwire::Tripwire(false, false, true, false, false, true, true).ID: return 5367; case Tripwire::Tripwire(false, false, true, false, false, true, false).ID: return 5368; case Tripwire::Tripwire(false, false, true, false, false, false, true).ID: return 5369; case Tripwire::Tripwire(false, false, true, false, false, false, false).ID: return 5370; case Tripwire::Tripwire(false, false, false, true, true, true, true).ID: return 5371; case Tripwire::Tripwire(false, false, false, true, true, true, false).ID: return 5372; case Tripwire::Tripwire(false, false, false, true, true, false, true).ID: return 5373; case Tripwire::Tripwire(false, false, false, true, true, false, false).ID: return 5374; case Tripwire::Tripwire(false, false, false, true, false, true, true).ID: return 5375; case Tripwire::Tripwire(false, false, false, true, false, true, false).ID: return 5376; case Tripwire::Tripwire(false, false, false, true, false, false, true).ID: return 5377; case Tripwire::Tripwire(false, false, false, true, false, false, false).ID: return 5378; case Tripwire::Tripwire(false, false, false, false, true, true, true).ID: return 5379; case Tripwire::Tripwire(false, false, false, false, true, true, false).ID: return 5380; case Tripwire::Tripwire(false, false, false, false, true, false, true).ID: return 5381; case Tripwire::Tripwire(false, false, false, false, true, false, false).ID: return 5382; case Tripwire::Tripwire(false, false, false, false, false, true, true).ID: return 5383; case Tripwire::Tripwire(false, false, false, false, false, true, false).ID: return 5384; case Tripwire::Tripwire(false, false, false, false, false, false, true).ID: return 5385; case Tripwire::Tripwire(false, false, false, false, false, false, false).ID: return 5386; case TripwireHook::TripwireHook(true, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5243; case TripwireHook::TripwireHook(true, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5244; case TripwireHook::TripwireHook(true, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5245; case TripwireHook::TripwireHook(true, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5246; case TripwireHook::TripwireHook(true, eBlockFace::BLOCK_FACE_XM, true).ID: return 5247; case TripwireHook::TripwireHook(true, eBlockFace::BLOCK_FACE_XM, false).ID: return 5248; case TripwireHook::TripwireHook(true, eBlockFace::BLOCK_FACE_XP, true).ID: return 5249; case TripwireHook::TripwireHook(true, eBlockFace::BLOCK_FACE_XP, false).ID: return 5250; case TripwireHook::TripwireHook(false, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5251; case TripwireHook::TripwireHook(false, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5252; case TripwireHook::TripwireHook(false, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5253; case TripwireHook::TripwireHook(false, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5254; case TripwireHook::TripwireHook(false, eBlockFace::BLOCK_FACE_XM, true).ID: return 5255; case TripwireHook::TripwireHook(false, eBlockFace::BLOCK_FACE_XM, false).ID: return 5256; case TripwireHook::TripwireHook(false, eBlockFace::BLOCK_FACE_XP, true).ID: return 5257; case TripwireHook::TripwireHook(false, eBlockFace::BLOCK_FACE_XP, false).ID: return 5258; case TubeCoral::TubeCoral().ID: return 8995; case TubeCoralBlock::TubeCoralBlock().ID: return 8979; case TubeCoralFan::TubeCoralFan().ID: return 9015; case TubeCoralWallFan::TubeCoralWallFan(eBlockFace::BLOCK_FACE_ZM).ID: return 9065; case TubeCoralWallFan::TubeCoralWallFan(eBlockFace::BLOCK_FACE_ZP).ID: return 9067; case TubeCoralWallFan::TubeCoralWallFan(eBlockFace::BLOCK_FACE_XM).ID: return 9069; case TubeCoralWallFan::TubeCoralWallFan(eBlockFace::BLOCK_FACE_XP).ID: return 9071; case TurtleEgg::TurtleEgg(1, 0).ID: return 8962; case TurtleEgg::TurtleEgg(1, 1).ID: return 8963; case TurtleEgg::TurtleEgg(1, 2).ID: return 8964; case TurtleEgg::TurtleEgg(2, 0).ID: return 8965; case TurtleEgg::TurtleEgg(2, 1).ID: return 8966; case TurtleEgg::TurtleEgg(2, 2).ID: return 8967; case TurtleEgg::TurtleEgg(3, 0).ID: return 8968; case TurtleEgg::TurtleEgg(3, 1).ID: return 8969; case TurtleEgg::TurtleEgg(3, 2).ID: return 8970; case TurtleEgg::TurtleEgg(4, 0).ID: return 8971; case TurtleEgg::TurtleEgg(4, 1).ID: return 8972; case TurtleEgg::TurtleEgg(4, 2).ID: return 8973; case Vine::Vine(true, true, true, true, true).ID: return 4772; case Vine::Vine(true, true, true, true, false).ID: return 4773; case Vine::Vine(true, true, true, false, true).ID: return 4774; case Vine::Vine(true, true, true, false, false).ID: return 4775; case Vine::Vine(true, true, false, true, true).ID: return 4776; case Vine::Vine(true, true, false, true, false).ID: return 4777; case Vine::Vine(true, true, false, false, true).ID: return 4778; case Vine::Vine(true, true, false, false, false).ID: return 4779; case Vine::Vine(true, false, true, true, true).ID: return 4780; case Vine::Vine(true, false, true, true, false).ID: return 4781; case Vine::Vine(true, false, true, false, true).ID: return 4782; case Vine::Vine(true, false, true, false, false).ID: return 4783; case Vine::Vine(true, false, false, true, true).ID: return 4784; case Vine::Vine(true, false, false, true, false).ID: return 4785; case Vine::Vine(true, false, false, false, true).ID: return 4786; case Vine::Vine(true, false, false, false, false).ID: return 4787; case Vine::Vine(false, true, true, true, true).ID: return 4788; case Vine::Vine(false, true, true, true, false).ID: return 4789; case Vine::Vine(false, true, true, false, true).ID: return 4790; case Vine::Vine(false, true, true, false, false).ID: return 4791; case Vine::Vine(false, true, false, true, true).ID: return 4792; case Vine::Vine(false, true, false, true, false).ID: return 4793; case Vine::Vine(false, true, false, false, true).ID: return 4794; case Vine::Vine(false, true, false, false, false).ID: return 4795; case Vine::Vine(false, false, true, true, true).ID: return 4796; case Vine::Vine(false, false, true, true, false).ID: return 4797; case Vine::Vine(false, false, true, false, true).ID: return 4798; case Vine::Vine(false, false, true, false, false).ID: return 4799; case Vine::Vine(false, false, false, true, true).ID: return 4800; case Vine::Vine(false, false, false, true, false).ID: return 4801; case Vine::Vine(false, false, false, false, true).ID: return 4802; case Vine::Vine(false, false, false, false, false).ID: return 4803; case VoidAir::VoidAir().ID: return 9129; case WallTorch::WallTorch(eBlockFace::BLOCK_FACE_ZM).ID: return 1435; case WallTorch::WallTorch(eBlockFace::BLOCK_FACE_ZP).ID: return 1436; case WallTorch::WallTorch(eBlockFace::BLOCK_FACE_XM).ID: return 1437; case WallTorch::WallTorch(eBlockFace::BLOCK_FACE_XP).ID: return 1438; case Water::Water(0).ID: return 34; case Water::Water(1).ID: return 35; case Water::Water(2).ID: return 36; case Water::Water(3).ID: return 37; case Water::Water(4).ID: return 38; case Water::Water(5).ID: return 39; case Water::Water(6).ID: return 40; case Water::Water(7).ID: return 41; case Water::Water(8).ID: return 42; case Water::Water(9).ID: return 43; case Water::Water(10).ID: return 44; case Water::Water(11).ID: return 45; case Water::Water(12).ID: return 46; case Water::Water(13).ID: return 47; case Water::Water(14).ID: return 48; case Water::Water(15).ID: return 49; case WetSponge::WetSponge().ID: return 229; case Wheat::Wheat(0).ID: return 3355; case Wheat::Wheat(1).ID: return 3356; case Wheat::Wheat(2).ID: return 3357; case Wheat::Wheat(3).ID: return 3358; case Wheat::Wheat(4).ID: return 3359; case Wheat::Wheat(5).ID: return 3360; case Wheat::Wheat(6).ID: return 3361; case Wheat::Wheat(7).ID: return 3362; case WhiteBanner::WhiteBanner(0).ID: return 7361; case WhiteBanner::WhiteBanner(1).ID: return 7362; case WhiteBanner::WhiteBanner(2).ID: return 7363; case WhiteBanner::WhiteBanner(3).ID: return 7364; case WhiteBanner::WhiteBanner(4).ID: return 7365; case WhiteBanner::WhiteBanner(5).ID: return 7366; case WhiteBanner::WhiteBanner(6).ID: return 7367; case WhiteBanner::WhiteBanner(7).ID: return 7368; case WhiteBanner::WhiteBanner(8).ID: return 7369; case WhiteBanner::WhiteBanner(9).ID: return 7370; case WhiteBanner::WhiteBanner(10).ID: return 7371; case WhiteBanner::WhiteBanner(11).ID: return 7372; case WhiteBanner::WhiteBanner(12).ID: return 7373; case WhiteBanner::WhiteBanner(13).ID: return 7374; case WhiteBanner::WhiteBanner(14).ID: return 7375; case WhiteBanner::WhiteBanner(15).ID: return 7376; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_ZM, true, WhiteBed::Part::Head).ID: return 1048; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_ZM, true, WhiteBed::Part::Foot).ID: return 1049; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_ZM, false, WhiteBed::Part::Head).ID: return 1050; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_ZM, false, WhiteBed::Part::Foot).ID: return 1051; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_ZP, true, WhiteBed::Part::Head).ID: return 1052; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_ZP, true, WhiteBed::Part::Foot).ID: return 1053; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_ZP, false, WhiteBed::Part::Head).ID: return 1054; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_ZP, false, WhiteBed::Part::Foot).ID: return 1055; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_XM, true, WhiteBed::Part::Head).ID: return 1056; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_XM, true, WhiteBed::Part::Foot).ID: return 1057; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_XM, false, WhiteBed::Part::Head).ID: return 1058; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_XM, false, WhiteBed::Part::Foot).ID: return 1059; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_XP, true, WhiteBed::Part::Head).ID: return 1060; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_XP, true, WhiteBed::Part::Foot).ID: return 1061; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_XP, false, WhiteBed::Part::Head).ID: return 1062; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_XP, false, WhiteBed::Part::Foot).ID: return 1063; case WhiteCarpet::WhiteCarpet().ID: return 7330; case WhiteConcrete::WhiteConcrete().ID: return 8902; case WhiteConcretePowder::WhiteConcretePowder().ID: return 8918; case WhiteGlazedTerracotta::WhiteGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 8838; case WhiteGlazedTerracotta::WhiteGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 8839; case WhiteGlazedTerracotta::WhiteGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 8840; case WhiteGlazedTerracotta::WhiteGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 8841; case WhiteShulkerBox::WhiteShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 8742; case WhiteShulkerBox::WhiteShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 8743; case WhiteShulkerBox::WhiteShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 8744; case WhiteShulkerBox::WhiteShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 8745; case WhiteShulkerBox::WhiteShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 8746; case WhiteShulkerBox::WhiteShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 8747; case WhiteStainedGlass::WhiteStainedGlass().ID: return 4081; case WhiteStainedGlassPane::WhiteStainedGlassPane(true, true, true, true).ID: return 6329; case WhiteStainedGlassPane::WhiteStainedGlassPane(true, true, true, false).ID: return 6330; case WhiteStainedGlassPane::WhiteStainedGlassPane(true, true, false, true).ID: return 6333; case WhiteStainedGlassPane::WhiteStainedGlassPane(true, true, false, false).ID: return 6334; case WhiteStainedGlassPane::WhiteStainedGlassPane(true, false, true, true).ID: return 6337; case WhiteStainedGlassPane::WhiteStainedGlassPane(true, false, true, false).ID: return 6338; case WhiteStainedGlassPane::WhiteStainedGlassPane(true, false, false, true).ID: return 6341; case WhiteStainedGlassPane::WhiteStainedGlassPane(true, false, false, false).ID: return 6342; case WhiteStainedGlassPane::WhiteStainedGlassPane(false, true, true, true).ID: return 6345; case WhiteStainedGlassPane::WhiteStainedGlassPane(false, true, true, false).ID: return 6346; case WhiteStainedGlassPane::WhiteStainedGlassPane(false, true, false, true).ID: return 6349; case WhiteStainedGlassPane::WhiteStainedGlassPane(false, true, false, false).ID: return 6350; case WhiteStainedGlassPane::WhiteStainedGlassPane(false, false, true, true).ID: return 6353; case WhiteStainedGlassPane::WhiteStainedGlassPane(false, false, true, false).ID: return 6354; case WhiteStainedGlassPane::WhiteStainedGlassPane(false, false, false, true).ID: return 6357; case WhiteStainedGlassPane::WhiteStainedGlassPane(false, false, false, false).ID: return 6358; case WhiteTerracotta::WhiteTerracotta().ID: return 6311; case WhiteTulip::WhiteTulip().ID: return 1418; case WhiteWallBanner::WhiteWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 7617; case WhiteWallBanner::WhiteWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 7618; case WhiteWallBanner::WhiteWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 7619; case WhiteWallBanner::WhiteWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 7620; case WhiteWool::WhiteWool().ID: return 1383; case WitherRose::WitherRose().ID: return 1422; case WitherSkeletonSkull::WitherSkeletonSkull(0).ID: return 5974; case WitherSkeletonSkull::WitherSkeletonSkull(1).ID: return 5975; case WitherSkeletonSkull::WitherSkeletonSkull(2).ID: return 5976; case WitherSkeletonSkull::WitherSkeletonSkull(3).ID: return 5977; case WitherSkeletonSkull::WitherSkeletonSkull(4).ID: return 5978; case WitherSkeletonSkull::WitherSkeletonSkull(5).ID: return 5979; case WitherSkeletonSkull::WitherSkeletonSkull(6).ID: return 5980; case WitherSkeletonSkull::WitherSkeletonSkull(7).ID: return 5981; case WitherSkeletonSkull::WitherSkeletonSkull(8).ID: return 5982; case WitherSkeletonSkull::WitherSkeletonSkull(9).ID: return 5983; case WitherSkeletonSkull::WitherSkeletonSkull(10).ID: return 5984; case WitherSkeletonSkull::WitherSkeletonSkull(11).ID: return 5985; case WitherSkeletonSkull::WitherSkeletonSkull(12).ID: return 5986; case WitherSkeletonSkull::WitherSkeletonSkull(13).ID: return 5987; case WitherSkeletonSkull::WitherSkeletonSkull(14).ID: return 5988; case WitherSkeletonSkull::WitherSkeletonSkull(15).ID: return 5989; case WitherSkeletonWallSkull::WitherSkeletonWallSkull(eBlockFace::BLOCK_FACE_ZM).ID: return 5990; case WitherSkeletonWallSkull::WitherSkeletonWallSkull(eBlockFace::BLOCK_FACE_ZP).ID: return 5991; case WitherSkeletonWallSkull::WitherSkeletonWallSkull(eBlockFace::BLOCK_FACE_XM).ID: return 5992; case WitherSkeletonWallSkull::WitherSkeletonWallSkull(eBlockFace::BLOCK_FACE_XP).ID: return 5993; case YellowBanner::YellowBanner(0).ID: return 7425; case YellowBanner::YellowBanner(1).ID: return 7426; case YellowBanner::YellowBanner(2).ID: return 7427; case YellowBanner::YellowBanner(3).ID: return 7428; case YellowBanner::YellowBanner(4).ID: return 7429; case YellowBanner::YellowBanner(5).ID: return 7430; case YellowBanner::YellowBanner(6).ID: return 7431; case YellowBanner::YellowBanner(7).ID: return 7432; case YellowBanner::YellowBanner(8).ID: return 7433; case YellowBanner::YellowBanner(9).ID: return 7434; case YellowBanner::YellowBanner(10).ID: return 7435; case YellowBanner::YellowBanner(11).ID: return 7436; case YellowBanner::YellowBanner(12).ID: return 7437; case YellowBanner::YellowBanner(13).ID: return 7438; case YellowBanner::YellowBanner(14).ID: return 7439; case YellowBanner::YellowBanner(15).ID: return 7440; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_ZM, true, YellowBed::Part::Head).ID: return 1112; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_ZM, true, YellowBed::Part::Foot).ID: return 1113; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_ZM, false, YellowBed::Part::Head).ID: return 1114; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_ZM, false, YellowBed::Part::Foot).ID: return 1115; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_ZP, true, YellowBed::Part::Head).ID: return 1116; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_ZP, true, YellowBed::Part::Foot).ID: return 1117; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_ZP, false, YellowBed::Part::Head).ID: return 1118; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_ZP, false, YellowBed::Part::Foot).ID: return 1119; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_XM, true, YellowBed::Part::Head).ID: return 1120; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_XM, true, YellowBed::Part::Foot).ID: return 1121; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_XM, false, YellowBed::Part::Head).ID: return 1122; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_XM, false, YellowBed::Part::Foot).ID: return 1123; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_XP, true, YellowBed::Part::Head).ID: return 1124; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_XP, true, YellowBed::Part::Foot).ID: return 1125; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_XP, false, YellowBed::Part::Head).ID: return 1126; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_XP, false, YellowBed::Part::Foot).ID: return 1127; case YellowCarpet::YellowCarpet().ID: return 7334; case YellowConcrete::YellowConcrete().ID: return 8906; case YellowConcretePowder::YellowConcretePowder().ID: return 8922; case YellowGlazedTerracotta::YellowGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 8854; case YellowGlazedTerracotta::YellowGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 8855; case YellowGlazedTerracotta::YellowGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 8856; case YellowGlazedTerracotta::YellowGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 8857; case YellowShulkerBox::YellowShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 8766; case YellowShulkerBox::YellowShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 8767; case YellowShulkerBox::YellowShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 8768; case YellowShulkerBox::YellowShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 8769; case YellowShulkerBox::YellowShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 8770; case YellowShulkerBox::YellowShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 8771; case YellowStainedGlass::YellowStainedGlass().ID: return 4085; case YellowStainedGlassPane::YellowStainedGlassPane(true, true, true, true).ID: return 6457; case YellowStainedGlassPane::YellowStainedGlassPane(true, true, true, false).ID: return 6458; case YellowStainedGlassPane::YellowStainedGlassPane(true, true, false, true).ID: return 6461; case YellowStainedGlassPane::YellowStainedGlassPane(true, true, false, false).ID: return 6462; case YellowStainedGlassPane::YellowStainedGlassPane(true, false, true, true).ID: return 6465; case YellowStainedGlassPane::YellowStainedGlassPane(true, false, true, false).ID: return 6466; case YellowStainedGlassPane::YellowStainedGlassPane(true, false, false, true).ID: return 6469; case YellowStainedGlassPane::YellowStainedGlassPane(true, false, false, false).ID: return 6470; case YellowStainedGlassPane::YellowStainedGlassPane(false, true, true, true).ID: return 6473; case YellowStainedGlassPane::YellowStainedGlassPane(false, true, true, false).ID: return 6474; case YellowStainedGlassPane::YellowStainedGlassPane(false, true, false, true).ID: return 6477; case YellowStainedGlassPane::YellowStainedGlassPane(false, true, false, false).ID: return 6478; case YellowStainedGlassPane::YellowStainedGlassPane(false, false, true, true).ID: return 6481; case YellowStainedGlassPane::YellowStainedGlassPane(false, false, true, false).ID: return 6482; case YellowStainedGlassPane::YellowStainedGlassPane(false, false, false, true).ID: return 6485; case YellowStainedGlassPane::YellowStainedGlassPane(false, false, false, false).ID: return 6486; case YellowTerracotta::YellowTerracotta().ID: return 6315; case YellowWallBanner::YellowWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 7633; case YellowWallBanner::YellowWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 7634; case YellowWallBanner::YellowWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 7635; case YellowWallBanner::YellowWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 7636; case YellowWool::YellowWool().ID: return 1387; case ZombieHead::ZombieHead(0).ID: return 5994; case ZombieHead::ZombieHead(1).ID: return 5995; case ZombieHead::ZombieHead(2).ID: return 5996; case ZombieHead::ZombieHead(3).ID: return 5997; case ZombieHead::ZombieHead(4).ID: return 5998; case ZombieHead::ZombieHead(5).ID: return 5999; case ZombieHead::ZombieHead(6).ID: return 6000; case ZombieHead::ZombieHead(7).ID: return 6001; case ZombieHead::ZombieHead(8).ID: return 6002; case ZombieHead::ZombieHead(9).ID: return 6003; case ZombieHead::ZombieHead(10).ID: return 6004; case ZombieHead::ZombieHead(11).ID: return 6005; case ZombieHead::ZombieHead(12).ID: return 6006; case ZombieHead::ZombieHead(13).ID: return 6007; case ZombieHead::ZombieHead(14).ID: return 6008; case ZombieHead::ZombieHead(15).ID: return 6009; case ZombieWallHead::ZombieWallHead(eBlockFace::BLOCK_FACE_ZM).ID: return 6010; case ZombieWallHead::ZombieWallHead(eBlockFace::BLOCK_FACE_ZP).ID: return 6011; case ZombieWallHead::ZombieWallHead(eBlockFace::BLOCK_FACE_XM).ID: return 6012; case ZombieWallHead::ZombieWallHead(eBlockFace::BLOCK_FACE_XP).ID: return 6013; default: return 0; } } UInt32 From(const Item ID) { switch (ID) { case Item::AcaciaBoat: return 834; case Item::AcaciaButton: return 263; case Item::AcaciaDoor: return 511; case Item::AcaciaFence: return 185; case Item::AcaciaFenceGate: return 220; case Item::AcaciaLeaves: return 60; case Item::AcaciaLog: return 36; case Item::AcaciaPlanks: return 17; case Item::AcaciaPressurePlate: return 170; case Item::AcaciaSapling: return 23; case Item::AcaciaSign: return 593; case Item::AcaciaSlab: return 119; case Item::AcaciaStairs: return 319; case Item::AcaciaTrapdoor: return 197; case Item::AcaciaWood: return 54; case Item::ActivatorRail: return 279; case Item::Air: return -0; case Item::Allium: return 101; case Item::Andesite: return 6; case Item::AndesiteSlab: return 501; case Item::AndesiteStairs: return 488; case Item::AndesiteWall: return 254; case Item::Anvil: return 265; case Item::Apple: return 524; case Item::ArmorStand: return 792; case Item::Arrow: return 526; case Item::AzureBluet: return 102; case Item::BakedPotato: return 765; case Item::Bamboo: return 614; case Item::Barrel: return 865; case Item::Barrier: return 297; case Item::BatSpawnEgg: return 697; case Item::Beacon: return 244; case Item::Bedrock: return 25; case Item::BeeNest: return 879; case Item::BeeSpawnEgg: return 698; case Item::Beef: return 677; case Item::Beehive: return 880; case Item::Beetroot: return 821; case Item::BeetrootSeeds: return 822; case Item::BeetrootSoup: return 823; case Item::Bell: return 874; case Item::BirchBoat: return 832; case Item::BirchButton: return 261; case Item::BirchDoor: return 509; case Item::BirchFence: return 183; case Item::BirchFenceGate: return 218; case Item::BirchLeaves: return 58; case Item::BirchLog: return 34; case Item::BirchPlanks: return 15; case Item::BirchPressurePlate: return 168; case Item::BirchSapling: return 21; case Item::BirchSign: return 591; case Item::BirchSlab: return 117; case Item::BirchStairs: return 241; case Item::BirchTrapdoor: return 195; case Item::BirchWood: return 52; case Item::BlackBanner: return 817; case Item::BlackBed: return 669; case Item::BlackCarpet: return 315; case Item::BlackConcrete: return 428; case Item::BlackConcretePowder: return 444; case Item::BlackDye: return 649; case Item::BlackGlazedTerracotta: return 412; case Item::BlackShulkerBox: return 396; case Item::BlackStainedGlass: return 344; case Item::BlackStainedGlassPane: return 360; case Item::BlackTerracotta: return 296; case Item::BlackWool: return 97; case Item::BlastFurnace: return 867; case Item::BlazePowder: return 691; case Item::BlazeRod: return 683; case Item::BlazeSpawnEgg: return 699; case Item::BlueBanner: return 813; case Item::BlueBed: return 665; case Item::BlueCarpet: return 311; case Item::BlueConcrete: return 424; case Item::BlueConcretePowder: return 440; case Item::BlueDye: return 647; case Item::BlueGlazedTerracotta: return 408; case Item::BlueIce: return 476; case Item::BlueOrchid: return 100; case Item::BlueShulkerBox: return 392; case Item::BlueStainedGlass: return 340; case Item::BlueStainedGlassPane: return 356; case Item::BlueTerracotta: return 292; case Item::BlueWool: return 93; case Item::Bone: return 651; case Item::BoneBlock: return 377; case Item::BoneMeal: return 646; case Item::Book: return 616; case Item::Bookshelf: return 143; case Item::Bow: return 525; case Item::Bowl: return 546; case Item::BrainCoral: return 457; case Item::BrainCoralBlock: return 452; case Item::BrainCoralFan: return 467; case Item::Bread: return 562; case Item::BrewingStand: return 693; case Item::Brick: return 609; case Item::BrickSlab: return 127; case Item::BrickStairs: return 222; case Item::BrickWall: return 247; case Item::Bricks: return 141; case Item::BrownBanner: return 814; case Item::BrownBed: return 666; case Item::BrownCarpet: return 312; case Item::BrownConcrete: return 425; case Item::BrownConcretePowder: return 441; case Item::BrownDye: return 648; case Item::BrownGlazedTerracotta: return 409; case Item::BrownMushroom: return 111; case Item::BrownMushroomBlock: return 209; case Item::BrownShulkerBox: return 393; case Item::BrownStainedGlass: return 341; case Item::BrownStainedGlassPane: return 357; case Item::BrownTerracotta: return 293; case Item::BrownWool: return 94; case Item::BubbleCoral: return 458; case Item::BubbleCoralBlock: return 453; case Item::BubbleCoralFan: return 468; case Item::Bucket: return 595; case Item::Cactus: return 178; case Item::Cake: return 653; case Item::Campfire: return 877; case Item::Carrot: return 763; case Item::CarrotOnAStick: return 775; case Item::CartographyTable: return 868; case Item::CarvedPumpkin: return 188; case Item::CatSpawnEgg: return 700; case Item::Cauldron: return 694; case Item::CaveSpiderSpawnEgg: return 701; case Item::ChainCommandBlock: return 373; case Item::ChainmailBoots: return 570; case Item::ChainmailChestplate: return 568; case Item::ChainmailHelmet: return 567; case Item::ChainmailLeggings: return 569; case Item::Charcoal: return 528; case Item::Chest: return 155; case Item::ChestMinecart: return 618; case Item::Chicken: return 679; case Item::ChickenSpawnEgg: return 702; case Item::ChippedAnvil: return 266; case Item::ChiseledQuartzBlock: return 275; case Item::ChiseledRedSandstone: return 369; case Item::ChiseledSandstone: return 69; case Item::ChiseledStoneBricks: return 208; case Item::ChorusFlower: return 149; case Item::ChorusFruit: return 819; case Item::ChorusPlant: return 148; case Item::Clay: return 179; case Item::ClayBall: return 610; case Item::Clock: return 623; case Item::Coal: return 527; case Item::CoalBlock: return 317; case Item::CoalOre: return 31; case Item::CoarseDirt: return 10; case Item::Cobblestone: return 12; case Item::CobblestoneSlab: return 126; case Item::CobblestoneStairs: return 163; case Item::CobblestoneWall: return 245; case Item::Cobweb: return 75; case Item::CocoaBeans: return 634; case Item::Cod: return 625; case Item::CodBucket: return 607; case Item::CodSpawnEgg: return 703; case Item::CommandBlock: return 243; case Item::CommandBlockMinecart: return 799; case Item::Comparator: return 514; case Item::Compass: return 621; case Item::Composter: return 517; case Item::Conduit: return 477; case Item::CookedBeef: return 678; case Item::CookedChicken: return 680; case Item::CookedCod: return 629; case Item::CookedMutton: return 801; case Item::CookedPorkchop: return 585; case Item::CookedRabbit: return 788; case Item::CookedSalmon: return 630; case Item::Cookie: return 670; case Item::Cornflower: return 108; case Item::CowSpawnEgg: return 704; case Item::CrackedStoneBricks: return 207; case Item::CraftingTable: return 158; case Item::CreeperBannerPattern: return 861; case Item::CreeperHead: return 773; case Item::CreeperSpawnEgg: return 705; case Item::Crossbow: return 857; case Item::CutRedSandstone: return 370; case Item::CutRedSandstoneSlab: return 132; case Item::CutSandstone: return 70; case Item::CutSandstoneSlab: return 124; case Item::CyanBanner: return 811; case Item::CyanBed: return 663; case Item::CyanCarpet: return 309; case Item::CyanConcrete: return 422; case Item::CyanConcretePowder: return 438; case Item::CyanDye: return 637; case Item::CyanGlazedTerracotta: return 406; case Item::CyanShulkerBox: return 390; case Item::CyanStainedGlass: return 338; case Item::CyanStainedGlassPane: return 354; case Item::CyanTerracotta: return 290; case Item::CyanWool: return 91; case Item::DamagedAnvil: return 267; case Item::Dandelion: return 98; case Item::DarkOakBoat: return 835; case Item::DarkOakButton: return 264; case Item::DarkOakDoor: return 512; case Item::DarkOakFence: return 186; case Item::DarkOakFenceGate: return 221; case Item::DarkOakLeaves: return 61; case Item::DarkOakLog: return 37; case Item::DarkOakPlanks: return 18; case Item::DarkOakPressurePlate: return 171; case Item::DarkOakSapling: return 24; case Item::DarkOakSign: return 594; case Item::DarkOakSlab: return 120; case Item::DarkOakStairs: return 320; case Item::DarkOakTrapdoor: return 198; case Item::DarkOakWood: return 55; case Item::DarkPrismarine: return 363; case Item::DarkPrismarineSlab: return 136; case Item::DarkPrismarineStairs: return 366; case Item::DaylightDetector: return 271; case Item::DeadBrainCoral: return 461; case Item::DeadBrainCoralBlock: return 447; case Item::DeadBrainCoralFan: return 472; case Item::DeadBubbleCoral: return 462; case Item::DeadBubbleCoralBlock: return 448; case Item::DeadBubbleCoralFan: return 473; case Item::DeadBush: return 78; case Item::DeadFireCoral: return 463; case Item::DeadFireCoralBlock: return 449; case Item::DeadFireCoralFan: return 474; case Item::DeadHornCoral: return 464; case Item::DeadHornCoralBlock: return 450; case Item::DeadHornCoralFan: return 475; case Item::DeadTubeCoral: return 465; case Item::DeadTubeCoralBlock: return 446; case Item::DeadTubeCoralFan: return 471; case Item::DebugStick: return 840; case Item::DetectorRail: return 73; case Item::Diamond: return 529; case Item::DiamondAxe: return 544; case Item::DiamondBlock: return 157; case Item::DiamondBoots: return 578; case Item::DiamondChestplate: return 576; case Item::DiamondHelmet: return 575; case Item::DiamondHoe: return 558; case Item::DiamondHorseArmor: return 795; case Item::DiamondLeggings: return 577; case Item::DiamondOre: return 156; case Item::DiamondPickaxe: return 543; case Item::DiamondShovel: return 542; case Item::DiamondSword: return 541; case Item::Diorite: return 4; case Item::DioriteSlab: return 504; case Item::DioriteStairs: return 491; case Item::DioriteWall: return 258; case Item::Dirt: return 9; case Item::Dispenser: return 67; case Item::DolphinSpawnEgg: return 706; case Item::DonkeySpawnEgg: return 707; case Item::DragonBreath: return 824; case Item::DragonEgg: return 233; case Item::DragonHead: return 774; case Item::DriedKelp: return 674; case Item::DriedKelpBlock: return 613; case Item::Dropper: return 280; case Item::DrownedSpawnEgg: return 708; case Item::Egg: return 620; case Item::ElderGuardianSpawnEgg: return 709; case Item::Elytra: return 830; case Item::Emerald: return 760; case Item::EmeraldBlock: return 239; case Item::EmeraldOre: return 236; case Item::EnchantedBook: return 780; case Item::EnchantedGoldenApple: return 588; case Item::EnchantingTable: return 229; case Item::EndCrystal: return 818; case Item::EndPortalFrame: return 230; case Item::EndRod: return 147; case Item::EndStone: return 231; case Item::EndStoneBrickSlab: return 497; case Item::EndStoneBrickStairs: return 483; case Item::EndStoneBrickWall: return 257; case Item::EndStoneBricks: return 232; case Item::EnderChest: return 237; case Item::EnderEye: return 695; case Item::EnderPearl: return 682; case Item::EndermanSpawnEgg: return 710; case Item::EndermiteSpawnEgg: return 711; case Item::EvokerSpawnEgg: return 712; case Item::ExperienceBottle: return 756; case Item::Farmland: return 159; case Item::Feather: return 553; case Item::FermentedSpiderEye: return 690; case Item::Fern: return 77; case Item::FilledMap: return 671; case Item::FireCharge: return 757; case Item::FireCoral: return 459; case Item::FireCoralBlock: return 454; case Item::FireCoralFan: return 469; case Item::FireworkRocket: return 778; case Item::FireworkStar: return 779; case Item::FishingRod: return 622; case Item::FletchingTable: return 869; case Item::Flint: return 583; case Item::FlintAndSteel: return 523; case Item::FlowerBannerPattern: return 860; case Item::FlowerPot: return 762; case Item::FoxSpawnEgg: return 713; case Item::Furnace: return 160; case Item::FurnaceMinecart: return 619; case Item::GhastSpawnEgg: return 714; case Item::GhastTear: return 684; case Item::Glass: return 64; case Item::GlassBottle: return 688; case Item::GlassPane: return 213; case Item::GlisteringMelonSlice: return 696; case Item::GlobeBannerPattern: return 864; case Item::Glowstone: return 191; case Item::GlowstoneDust: return 624; case Item::GoldBlock: return 113; case Item::GoldIngot: return 531; case Item::GoldNugget: return 685; case Item::GoldOre: return 29; case Item::GoldenApple: return 587; case Item::GoldenAxe: return 551; case Item::GoldenBoots: return 582; case Item::GoldenCarrot: return 768; case Item::GoldenChestplate: return 580; case Item::GoldenHelmet: return 579; case Item::GoldenHoe: return 559; case Item::GoldenHorseArmor: return 794; case Item::GoldenLeggings: return 581; case Item::GoldenPickaxe: return 550; case Item::GoldenShovel: return 549; case Item::GoldenSword: return 548; case Item::Granite: return 2; case Item::GraniteSlab: return 500; case Item::GraniteStairs: return 487; case Item::GraniteWall: return 251; case Item::Grass: return 76; case Item::GrassBlock: return 8; case Item::GrassPath: return 322; case Item::Gravel: return 28; case Item::GrayBanner: return 809; case Item::GrayBed: return 661; case Item::GrayCarpet: return 307; case Item::GrayConcrete: return 420; case Item::GrayConcretePowder: return 436; case Item::GrayDye: return 639; case Item::GrayGlazedTerracotta: return 404; case Item::GrayShulkerBox: return 388; case Item::GrayStainedGlass: return 336; case Item::GrayStainedGlassPane: return 352; case Item::GrayTerracotta: return 288; case Item::GrayWool: return 89; case Item::GreenBanner: return 815; case Item::GreenBed: return 667; case Item::GreenCarpet: return 313; case Item::GreenConcrete: return 426; case Item::GreenConcretePowder: return 442; case Item::GreenDye: return 633; case Item::GreenGlazedTerracotta: return 410; case Item::GreenShulkerBox: return 394; case Item::GreenStainedGlass: return 342; case Item::GreenStainedGlassPane: return 358; case Item::GreenTerracotta: return 294; case Item::GreenWool: return 95; case Item::Grindstone: return 870; case Item::GuardianSpawnEgg: return 715; case Item::Gunpowder: return 554; case Item::HayBale: return 299; case Item::HeartOfTheSea: return 856; case Item::HeavyWeightedPressurePlate: return 270; case Item::HoneyBlock: return 882; case Item::HoneyBottle: return 881; case Item::Honeycomb: return 878; case Item::HoneycombBlock: return 883; case Item::Hopper: return 274; case Item::HopperMinecart: return 784; case Item::HornCoral: return 460; case Item::HornCoralBlock: return 455; case Item::HornCoralFan: return 470; case Item::HorseSpawnEgg: return 716; case Item::HuskSpawnEgg: return 717; case Item::Ice: return 176; case Item::InfestedChiseledStoneBricks: return 204; case Item::InfestedCobblestone: return 200; case Item::InfestedCrackedStoneBricks: return 203; case Item::InfestedMossyStoneBricks: return 202; case Item::InfestedStone: return 199; case Item::InfestedStoneBricks: return 201; case Item::InkSac: return 631; case Item::IronAxe: return 522; case Item::IronBars: return 212; case Item::IronBlock: return 114; case Item::IronBoots: return 574; case Item::IronChestplate: return 572; case Item::IronDoor: return 506; case Item::IronHelmet: return 571; case Item::IronHoe: return 557; case Item::IronHorseArmor: return 793; case Item::IronIngot: return 530; case Item::IronLeggings: return 573; case Item::IronNugget: return 838; case Item::IronOre: return 30; case Item::IronPickaxe: return 521; case Item::IronShovel: return 520; case Item::IronSword: return 532; case Item::IronTrapdoor: return 298; case Item::ItemFrame: return 761; case Item::JackOLantern: return 192; case Item::Jigsaw: return 516; case Item::Jukebox: return 180; case Item::JungleBoat: return 833; case Item::JungleButton: return 262; case Item::JungleDoor: return 510; case Item::JungleFence: return 184; case Item::JungleFenceGate: return 219; case Item::JungleLeaves: return 59; case Item::JungleLog: return 35; case Item::JunglePlanks: return 16; case Item::JunglePressurePlate: return 169; case Item::JungleSapling: return 22; case Item::JungleSign: return 592; case Item::JungleSlab: return 118; case Item::JungleStairs: return 242; case Item::JungleTrapdoor: return 196; case Item::JungleWood: return 53; case Item::Kelp: return 612; case Item::KnowledgeBook: return 839; case Item::Ladder: return 161; case Item::Lantern: return 875; case Item::LapisBlock: return 66; case Item::LapisLazuli: return 635; case Item::LapisOre: return 65; case Item::LargeFern: return 328; case Item::LavaBucket: return 597; case Item::Lead: return 797; case Item::Leather: return 603; case Item::LeatherBoots: return 566; case Item::LeatherChestplate: return 564; case Item::LeatherHelmet: return 563; case Item::LeatherHorseArmor: return 796; case Item::LeatherLeggings: return 565; case Item::Lectern: return 871; case Item::Lever: return 164; case Item::LightBlueBanner: return 805; case Item::LightBlueBed: return 657; case Item::LightBlueCarpet: return 303; case Item::LightBlueConcrete: return 416; case Item::LightBlueConcretePowder: return 432; case Item::LightBlueDye: return 643; case Item::LightBlueGlazedTerracotta: return 400; case Item::LightBlueShulkerBox: return 384; case Item::LightBlueStainedGlass: return 332; case Item::LightBlueStainedGlassPane: return 348; case Item::LightBlueTerracotta: return 284; case Item::LightBlueWool: return 85; case Item::LightGrayBanner: return 810; case Item::LightGrayBed: return 662; case Item::LightGrayCarpet: return 308; case Item::LightGrayConcrete: return 421; case Item::LightGrayConcretePowder: return 437; case Item::LightGrayDye: return 638; case Item::LightGrayGlazedTerracotta: return 405; case Item::LightGrayShulkerBox: return 389; case Item::LightGrayStainedGlass: return 337; case Item::LightGrayStainedGlassPane: return 353; case Item::LightGrayTerracotta: return 289; case Item::LightGrayWool: return 90; case Item::LightWeightedPressurePlate: return 269; case Item::Lilac: return 324; case Item::LilyOfTheValley: return 109; case Item::LilyPad: return 225; case Item::LimeBanner: return 807; case Item::LimeBed: return 659; case Item::LimeCarpet: return 305; case Item::LimeConcrete: return 418; case Item::LimeConcretePowder: return 434; case Item::LimeDye: return 641; case Item::LimeGlazedTerracotta: return 402; case Item::LimeShulkerBox: return 386; case Item::LimeStainedGlass: return 334; case Item::LimeStainedGlassPane: return 350; case Item::LimeTerracotta: return 286; case Item::LimeWool: return 87; case Item::LingeringPotion: return 828; case Item::LlamaSpawnEgg: return 718; case Item::Loom: return 859; case Item::MagentaBanner: return 804; case Item::MagentaBed: return 656; case Item::MagentaCarpet: return 302; case Item::MagentaConcrete: return 415; case Item::MagentaConcretePowder: return 431; case Item::MagentaDye: return 644; case Item::MagentaGlazedTerracotta: return 399; case Item::MagentaShulkerBox: return 383; case Item::MagentaStainedGlass: return 331; case Item::MagentaStainedGlassPane: return 347; case Item::MagentaTerracotta: return 283; case Item::MagentaWool: return 84; case Item::MagmaBlock: return 374; case Item::MagmaCream: return 692; case Item::MagmaCubeSpawnEgg: return 719; case Item::Map: return 767; case Item::Melon: return 214; case Item::MelonSeeds: return 676; case Item::MelonSlice: return 673; case Item::MilkBucket: return 604; case Item::Minecart: return 598; case Item::MojangBannerPattern: return 863; case Item::MooshroomSpawnEgg: return 720; case Item::MossyCobblestone: return 144; case Item::MossyCobblestoneSlab: return 496; case Item::MossyCobblestoneStairs: return 482; case Item::MossyCobblestoneWall: return 246; case Item::MossyStoneBrickSlab: return 494; case Item::MossyStoneBrickStairs: return 480; case Item::MossyStoneBrickWall: return 250; case Item::MossyStoneBricks: return 206; case Item::MuleSpawnEgg: return 721; case Item::MushroomStem: return 211; case Item::MushroomStew: return 547; case Item::MusicDisc11: return 851; case Item::MusicDisc13: return 841; case Item::MusicDiscBlocks: return 843; case Item::MusicDiscCat: return 842; case Item::MusicDiscChirp: return 844; case Item::MusicDiscFar: return 845; case Item::MusicDiscMall: return 846; case Item::MusicDiscMellohi: return 847; case Item::MusicDiscStal: return 848; case Item::MusicDiscStrad: return 849; case Item::MusicDiscWait: return 852; case Item::MusicDiscWard: return 850; case Item::Mutton: return 800; case Item::Mycelium: return 224; case Item::NameTag: return 798; case Item::NautilusShell: return 855; case Item::NetherBrick: return 781; case Item::NetherBrickFence: return 227; case Item::NetherBrickSlab: return 129; case Item::NetherBrickStairs: return 228; case Item::NetherBrickWall: return 253; case Item::NetherBricks: return 226; case Item::NetherQuartzOre: return 273; case Item::NetherStar: return 776; case Item::NetherWart: return 686; case Item::NetherWartBlock: return 375; case Item::Netherrack: return 189; case Item::NoteBlock: return 71; case Item::OakBoat: return 602; case Item::OakButton: return 259; case Item::OakDoor: return 507; case Item::OakFence: return 181; case Item::OakFenceGate: return 216; case Item::OakLeaves: return 56; case Item::OakLog: return 32; case Item::OakPlanks: return 13; case Item::OakPressurePlate: return 166; case Item::OakSapling: return 19; case Item::OakSign: return 589; case Item::OakSlab: return 115; case Item::OakStairs: return 154; case Item::OakTrapdoor: return 193; case Item::OakWood: return 50; case Item::Observer: return 379; case Item::Obsidian: return 145; case Item::OcelotSpawnEgg: return 722; case Item::OrangeBanner: return 803; case Item::OrangeBed: return 655; case Item::OrangeCarpet: return 301; case Item::OrangeConcrete: return 414; case Item::OrangeConcretePowder: return 430; case Item::OrangeDye: return 645; case Item::OrangeGlazedTerracotta: return 398; case Item::OrangeShulkerBox: return 382; case Item::OrangeStainedGlass: return 330; case Item::OrangeStainedGlassPane: return 346; case Item::OrangeTerracotta: return 282; case Item::OrangeTulip: return 104; case Item::OrangeWool: return 83; case Item::OxeyeDaisy: return 107; case Item::PackedIce: return 318; case Item::Painting: return 586; case Item::PandaSpawnEgg: return 723; case Item::Paper: return 615; case Item::ParrotSpawnEgg: return 724; case Item::Peony: return 326; case Item::PetrifiedOakSlab: return 125; case Item::PhantomMembrane: return 854; case Item::PhantomSpawnEgg: return 725; case Item::PigSpawnEgg: return 726; case Item::PillagerSpawnEgg: return 727; case Item::PinkBanner: return 808; case Item::PinkBed: return 660; case Item::PinkCarpet: return 306; case Item::PinkConcrete: return 419; case Item::PinkConcretePowder: return 435; case Item::PinkDye: return 640; case Item::PinkGlazedTerracotta: return 403; case Item::PinkShulkerBox: return 387; case Item::PinkStainedGlass: return 335; case Item::PinkStainedGlassPane: return 351; case Item::PinkTerracotta: return 287; case Item::PinkTulip: return 106; case Item::PinkWool: return 88; case Item::Piston: return 81; case Item::PlayerHead: return 771; case Item::Podzol: return 11; case Item::PoisonousPotato: return 766; case Item::PolarBearSpawnEgg: return 728; case Item::PolishedAndesite: return 7; case Item::PolishedAndesiteSlab: return 503; case Item::PolishedAndesiteStairs: return 490; case Item::PolishedDiorite: return 5; case Item::PolishedDioriteSlab: return 495; case Item::PolishedDioriteStairs: return 481; case Item::PolishedGranite: return 3; case Item::PolishedGraniteSlab: return 492; case Item::PolishedGraniteStairs: return 478; case Item::PoppedChorusFruit: return 820; case Item::Poppy: return 99; case Item::Porkchop: return 584; case Item::Potato: return 764; case Item::Potion: return 687; case Item::PoweredRail: return 72; case Item::Prismarine: return 361; case Item::PrismarineBrickSlab: return 135; case Item::PrismarineBrickStairs: return 365; case Item::PrismarineBricks: return 362; case Item::PrismarineCrystals: return 786; case Item::PrismarineShard: return 785; case Item::PrismarineSlab: return 134; case Item::PrismarineStairs: return 364; case Item::PrismarineWall: return 248; case Item::Pufferfish: return 628; case Item::PufferfishBucket: return 605; case Item::PufferfishSpawnEgg: return 729; case Item::Pumpkin: return 187; case Item::PumpkinPie: return 777; case Item::PumpkinSeeds: return 675; case Item::PurpleBanner: return 812; case Item::PurpleBed: return 664; case Item::PurpleCarpet: return 310; case Item::PurpleConcrete: return 423; case Item::PurpleConcretePowder: return 439; case Item::PurpleDye: return 636; case Item::PurpleGlazedTerracotta: return 407; case Item::PurpleShulkerBox: return 391; case Item::PurpleStainedGlass: return 339; case Item::PurpleStainedGlassPane: return 355; case Item::PurpleTerracotta: return 291; case Item::PurpleWool: return 92; case Item::PurpurBlock: return 150; case Item::PurpurPillar: return 151; case Item::PurpurSlab: return 133; case Item::PurpurStairs: return 152; case Item::Quartz: return 782; case Item::QuartzBlock: return 276; case Item::QuartzPillar: return 277; case Item::QuartzSlab: return 130; case Item::QuartzStairs: return 278; case Item::Rabbit: return 787; case Item::RabbitFoot: return 790; case Item::RabbitHide: return 791; case Item::RabbitSpawnEgg: return 730; case Item::RabbitStew: return 789; case Item::Rail: return 162; case Item::RavagerSpawnEgg: return 731; case Item::RedBanner: return 816; case Item::RedBed: return 668; case Item::RedCarpet: return 314; case Item::RedConcrete: return 427; case Item::RedConcretePowder: return 443; case Item::RedDye: return 632; case Item::RedGlazedTerracotta: return 411; case Item::RedMushroom: return 112; case Item::RedMushroomBlock: return 210; case Item::RedNetherBrickSlab: return 502; case Item::RedNetherBrickStairs: return 489; case Item::RedNetherBrickWall: return 255; case Item::RedNetherBricks: return 376; case Item::RedSand: return 27; case Item::RedSandstone: return 368; case Item::RedSandstoneSlab: return 131; case Item::RedSandstoneStairs: return 371; case Item::RedSandstoneWall: return 249; case Item::RedShulkerBox: return 395; case Item::RedStainedGlass: return 343; case Item::RedStainedGlassPane: return 359; case Item::RedTerracotta: return 295; case Item::RedTulip: return 103; case Item::RedWool: return 96; case Item::Redstone: return 600; case Item::RedstoneBlock: return 272; case Item::RedstoneLamp: return 234; case Item::RedstoneOre: return 172; case Item::RedstoneTorch: return 173; case Item::Repeater: return 513; case Item::RepeatingCommandBlock: return 372; case Item::RoseBush: return 325; case Item::RottenFlesh: return 681; case Item::Saddle: return 599; case Item::Salmon: return 626; case Item::SalmonBucket: return 606; case Item::SalmonSpawnEgg: return 732; case Item::Sand: return 26; case Item::Sandstone: return 68; case Item::SandstoneSlab: return 123; case Item::SandstoneStairs: return 235; case Item::SandstoneWall: return 256; case Item::Scaffolding: return 505; case Item::Scute: return 519; case Item::SeaLantern: return 367; case Item::SeaPickle: return 80; case Item::Seagrass: return 79; case Item::Shears: return 672; case Item::SheepSpawnEgg: return 733; case Item::Shield: return 829; case Item::ShulkerBox: return 380; case Item::ShulkerShell: return 837; case Item::ShulkerSpawnEgg: return 734; case Item::SilverfishSpawnEgg: return 735; case Item::SkeletonHorseSpawnEgg: return 737; case Item::SkeletonSkull: return 769; case Item::SkeletonSpawnEgg: return 736; case Item::SkullBannerPattern: return 862; case Item::SlimeBall: return 617; case Item::SlimeBlock: return 321; case Item::SlimeSpawnEgg: return 738; case Item::SmithingTable: return 872; case Item::Smoker: return 866; case Item::SmoothQuartz: return 137; case Item::SmoothQuartzSlab: return 499; case Item::SmoothQuartzStairs: return 486; case Item::SmoothRedSandstone: return 138; case Item::SmoothRedSandstoneSlab: return 493; case Item::SmoothRedSandstoneStairs: return 479; case Item::SmoothSandstone: return 139; case Item::SmoothSandstoneSlab: return 498; case Item::SmoothSandstoneStairs: return 485; case Item::SmoothStone: return 140; case Item::SmoothStoneSlab: return 122; case Item::Snow: return 175; case Item::SnowBlock: return 177; case Item::Snowball: return 601; case Item::SoulSand: return 190; case Item::Spawner: return 153; case Item::SpectralArrow: return 826; case Item::SpiderEye: return 689; case Item::SpiderSpawnEgg: return 739; case Item::SplashPotion: return 825; case Item::Sponge: return 62; case Item::SpruceBoat: return 831; case Item::SpruceButton: return 260; case Item::SpruceDoor: return 508; case Item::SpruceFence: return 182; case Item::SpruceFenceGate: return 217; case Item::SpruceLeaves: return 57; case Item::SpruceLog: return 33; case Item::SprucePlanks: return 14; case Item::SprucePressurePlate: return 167; case Item::SpruceSapling: return 20; case Item::SpruceSign: return 590; case Item::SpruceSlab: return 116; case Item::SpruceStairs: return 240; case Item::SpruceTrapdoor: return 194; case Item::SpruceWood: return 51; case Item::SquidSpawnEgg: return 740; case Item::Stick: return 545; case Item::StickyPiston: return 74; case Item::Stone: return 1; case Item::StoneAxe: return 540; case Item::StoneBrickSlab: return 128; case Item::StoneBrickStairs: return 223; case Item::StoneBrickWall: return 252; case Item::StoneBricks: return 205; case Item::StoneButton: return 174; case Item::StoneHoe: return 556; case Item::StonePickaxe: return 539; case Item::StonePressurePlate: return 165; case Item::StoneShovel: return 538; case Item::StoneSlab: return 121; case Item::StoneStairs: return 484; case Item::StoneSword: return 537; case Item::Stonecutter: return 873; case Item::StraySpawnEgg: return 741; case Item::String: return 552; case Item::StrippedAcaciaLog: return 42; case Item::StrippedAcaciaWood: return 48; case Item::StrippedBirchLog: return 40; case Item::StrippedBirchWood: return 46; case Item::StrippedDarkOakLog: return 43; case Item::StrippedDarkOakWood: return 49; case Item::StrippedJungleLog: return 41; case Item::StrippedJungleWood: return 47; case Item::StrippedOakLog: return 38; case Item::StrippedOakWood: return 44; case Item::StrippedSpruceLog: return 39; case Item::StrippedSpruceWood: return 45; case Item::StructureBlock: return 515; case Item::StructureVoid: return 378; case Item::Sugar: return 652; case Item::SugarCane: return 611; case Item::Sunflower: return 323; case Item::SuspiciousStew: return 858; case Item::SweetBerries: return 876; case Item::TallGrass: return 327; case Item::Terracotta: return 316; case Item::TippedArrow: return 827; case Item::TNT: return 142; case Item::TNTMinecart: return 783; case Item::Torch: return 146; case Item::TotemOfUndying: return 836; case Item::TraderLlamaSpawnEgg: return 742; case Item::TrappedChest: return 268; case Item::Trident: return 853; case Item::TripwireHook: return 238; case Item::TropicalFish: return 627; case Item::TropicalFishBucket: return 608; case Item::TropicalFishSpawnEgg: return 743; case Item::TubeCoral: return 456; case Item::TubeCoralBlock: return 451; case Item::TubeCoralFan: return 466; case Item::TurtleEgg: return 445; case Item::TurtleHelmet: return 518; case Item::TurtleSpawnEgg: return 744; case Item::VexSpawnEgg: return 745; case Item::VillagerSpawnEgg: return 746; case Item::VindicatorSpawnEgg: return 747; case Item::Vine: return 215; case Item::WanderingTraderSpawnEgg: return 748; case Item::WaterBucket: return 596; case Item::WetSponge: return 63; case Item::Wheat: return 561; case Item::WheatSeeds: return 560; case Item::WhiteBanner: return 802; case Item::WhiteBed: return 654; case Item::WhiteCarpet: return 300; case Item::WhiteConcrete: return 413; case Item::WhiteConcretePowder: return 429; case Item::WhiteDye: return 650; case Item::WhiteGlazedTerracotta: return 397; case Item::WhiteShulkerBox: return 381; case Item::WhiteStainedGlass: return 329; case Item::WhiteStainedGlassPane: return 345; case Item::WhiteTerracotta: return 281; case Item::WhiteTulip: return 105; case Item::WhiteWool: return 82; case Item::WitchSpawnEgg: return 749; case Item::WitherRose: return 110; case Item::WitherSkeletonSkull: return 770; case Item::WitherSkeletonSpawnEgg: return 750; case Item::WolfSpawnEgg: return 751; case Item::WoodenAxe: return 536; case Item::WoodenHoe: return 555; case Item::WoodenPickaxe: return 535; case Item::WoodenShovel: return 534; case Item::WoodenSword: return 533; case Item::WritableBook: return 758; case Item::WrittenBook: return 759; case Item::YellowBanner: return 806; case Item::YellowBed: return 658; case Item::YellowCarpet: return 304; case Item::YellowConcrete: return 417; case Item::YellowConcretePowder: return 433; case Item::YellowDye: return 642; case Item::YellowGlazedTerracotta: return 401; case Item::YellowShulkerBox: return 385; case Item::YellowStainedGlass: return 333; case Item::YellowStainedGlassPane: return 349; case Item::YellowTerracotta: return 285; case Item::YellowWool: return 86; case Item::ZombieHead: return 772; case Item::ZombieHorseSpawnEgg: return 753; case Item::ZombiePigmanSpawnEgg: return 754; case Item::ZombieSpawnEgg: return 752; case Item::ZombieVillagerSpawnEgg: return 755; default: return 0; } } UInt32 From(const CustomStatistic ID) { switch (ID) { case CustomStatistic::AnimalsBred: return 30; case CustomStatistic::AviateOneCm: return 17; case CustomStatistic::BellRing: return 66; case CustomStatistic::BoatOneCm: return 14; case CustomStatistic::CleanArmor: return 38; case CustomStatistic::CleanBanner: return 39; case CustomStatistic::CleanShulkerBox: return 40; case CustomStatistic::ClimbOneCm: return 10; case CustomStatistic::CrouchOneCm: return 6; case CustomStatistic::DamageAbsorbed: return 26; case CustomStatistic::DamageBlockedByShield: return 25; case CustomStatistic::DamageDealt: return 21; case CustomStatistic::DamageDealtAbsorbed: return 22; case CustomStatistic::DamageDealtResisted: return 23; case CustomStatistic::DamageResisted: return 27; case CustomStatistic::DamageTaken: return 24; case CustomStatistic::Deaths: return 28; case CustomStatistic::Drop: return 20; case CustomStatistic::EatCakeSlice: return 35; case CustomStatistic::EnchantItem: return 51; case CustomStatistic::FallOneCm: return 9; case CustomStatistic::FillCauldron: return 36; case CustomStatistic::FishCaught: return 32; case CustomStatistic::FlyOneCm: return 11; case CustomStatistic::HorseOneCm: return 16; case CustomStatistic::InspectDispenser: return 45; case CustomStatistic::InspectDropper: return 43; case CustomStatistic::InspectHopper: return 44; case CustomStatistic::InteractWithAnvil: return 69; case CustomStatistic::InteractWithBeacon: return 42; case CustomStatistic::InteractWithBlastFurnace: return 59; case CustomStatistic::InteractWithBrewingstand: return 41; case CustomStatistic::InteractWithCampfire: return 62; case CustomStatistic::InteractWithCartographyTable: return 63; case CustomStatistic::InteractWithCraftingTable: return 54; case CustomStatistic::InteractWithFurnace: return 53; case CustomStatistic::InteractWithGrindstone: return 70; case CustomStatistic::InteractWithLectern: return 61; case CustomStatistic::InteractWithLoom: return 64; case CustomStatistic::InteractWithSmoker: return 60; case CustomStatistic::InteractWithStonecutter: return 65; case CustomStatistic::Jump: return 19; case CustomStatistic::LeaveGame: return -0; case CustomStatistic::MinecartOneCm: return 13; case CustomStatistic::MobKills: return 29; case CustomStatistic::OpenBarrel: return 58; case CustomStatistic::OpenChest: return 55; case CustomStatistic::OpenEnderchest: return 50; case CustomStatistic::OpenShulkerBox: return 57; case CustomStatistic::PigOneCm: return 15; case CustomStatistic::PlayNoteblock: return 46; case CustomStatistic::PlayOneMinute: return 1; case CustomStatistic::PlayRecord: return 52; case CustomStatistic::PlayerKills: return 31; case CustomStatistic::PotFlower: return 48; case CustomStatistic::RaidTrigger: return 67; case CustomStatistic::RaidWin: return 68; case CustomStatistic::SleepInBed: return 56; case CustomStatistic::SneakTime: return 4; case CustomStatistic::SprintOneCm: return 7; case CustomStatistic::SwimOneCm: return 18; case CustomStatistic::TalkedToVillager: return 33; case CustomStatistic::TimeSinceDeath: return 2; case CustomStatistic::TimeSinceRest: return 3; case CustomStatistic::TradedWithVillager: return 34; case CustomStatistic::TriggerTrappedChest: return 49; case CustomStatistic::TuneNoteblock: return 47; case CustomStatistic::UseCauldron: return 37; case CustomStatistic::WalkOnWaterOneCm: return 8; case CustomStatistic::WalkOneCm: return 5; case CustomStatistic::WalkUnderWaterOneCm: return 12; default: return UInt32(-1); } } Item ToItem(const UInt32 ID) { switch (ID) { case 834: return Item::AcaciaBoat; case 263: return Item::AcaciaButton; case 511: return Item::AcaciaDoor; case 185: return Item::AcaciaFence; case 220: return Item::AcaciaFenceGate; case 60: return Item::AcaciaLeaves; case 36: return Item::AcaciaLog; case 17: return Item::AcaciaPlanks; case 170: return Item::AcaciaPressurePlate; case 23: return Item::AcaciaSapling; case 593: return Item::AcaciaSign; case 119: return Item::AcaciaSlab; case 319: return Item::AcaciaStairs; case 197: return Item::AcaciaTrapdoor; case 54: return Item::AcaciaWood; case 279: return Item::ActivatorRail; case -0: return Item::Air; case 101: return Item::Allium; case 6: return Item::Andesite; case 501: return Item::AndesiteSlab; case 488: return Item::AndesiteStairs; case 254: return Item::AndesiteWall; case 265: return Item::Anvil; case 524: return Item::Apple; case 792: return Item::ArmorStand; case 526: return Item::Arrow; case 102: return Item::AzureBluet; case 765: return Item::BakedPotato; case 614: return Item::Bamboo; case 865: return Item::Barrel; case 297: return Item::Barrier; case 697: return Item::BatSpawnEgg; case 244: return Item::Beacon; case 25: return Item::Bedrock; case 879: return Item::BeeNest; case 698: return Item::BeeSpawnEgg; case 677: return Item::Beef; case 880: return Item::Beehive; case 821: return Item::Beetroot; case 822: return Item::BeetrootSeeds; case 823: return Item::BeetrootSoup; case 874: return Item::Bell; case 832: return Item::BirchBoat; case 261: return Item::BirchButton; case 509: return Item::BirchDoor; case 183: return Item::BirchFence; case 218: return Item::BirchFenceGate; case 58: return Item::BirchLeaves; case 34: return Item::BirchLog; case 15: return Item::BirchPlanks; case 168: return Item::BirchPressurePlate; case 21: return Item::BirchSapling; case 591: return Item::BirchSign; case 117: return Item::BirchSlab; case 241: return Item::BirchStairs; case 195: return Item::BirchTrapdoor; case 52: return Item::BirchWood; case 817: return Item::BlackBanner; case 669: return Item::BlackBed; case 315: return Item::BlackCarpet; case 428: return Item::BlackConcrete; case 444: return Item::BlackConcretePowder; case 649: return Item::BlackDye; case 412: return Item::BlackGlazedTerracotta; case 396: return Item::BlackShulkerBox; case 344: return Item::BlackStainedGlass; case 360: return Item::BlackStainedGlassPane; case 296: return Item::BlackTerracotta; case 97: return Item::BlackWool; case 867: return Item::BlastFurnace; case 691: return Item::BlazePowder; case 683: return Item::BlazeRod; case 699: return Item::BlazeSpawnEgg; case 813: return Item::BlueBanner; case 665: return Item::BlueBed; case 311: return Item::BlueCarpet; case 424: return Item::BlueConcrete; case 440: return Item::BlueConcretePowder; case 647: return Item::BlueDye; case 408: return Item::BlueGlazedTerracotta; case 476: return Item::BlueIce; case 100: return Item::BlueOrchid; case 392: return Item::BlueShulkerBox; case 340: return Item::BlueStainedGlass; case 356: return Item::BlueStainedGlassPane; case 292: return Item::BlueTerracotta; case 93: return Item::BlueWool; case 651: return Item::Bone; case 377: return Item::BoneBlock; case 646: return Item::BoneMeal; case 616: return Item::Book; case 143: return Item::Bookshelf; case 525: return Item::Bow; case 546: return Item::Bowl; case 457: return Item::BrainCoral; case 452: return Item::BrainCoralBlock; case 467: return Item::BrainCoralFan; case 562: return Item::Bread; case 693: return Item::BrewingStand; case 609: return Item::Brick; case 127: return Item::BrickSlab; case 222: return Item::BrickStairs; case 247: return Item::BrickWall; case 141: return Item::Bricks; case 814: return Item::BrownBanner; case 666: return Item::BrownBed; case 312: return Item::BrownCarpet; case 425: return Item::BrownConcrete; case 441: return Item::BrownConcretePowder; case 648: return Item::BrownDye; case 409: return Item::BrownGlazedTerracotta; case 111: return Item::BrownMushroom; case 209: return Item::BrownMushroomBlock; case 393: return Item::BrownShulkerBox; case 341: return Item::BrownStainedGlass; case 357: return Item::BrownStainedGlassPane; case 293: return Item::BrownTerracotta; case 94: return Item::BrownWool; case 458: return Item::BubbleCoral; case 453: return Item::BubbleCoralBlock; case 468: return Item::BubbleCoralFan; case 595: return Item::Bucket; case 178: return Item::Cactus; case 653: return Item::Cake; case 877: return Item::Campfire; case 763: return Item::Carrot; case 775: return Item::CarrotOnAStick; case 868: return Item::CartographyTable; case 188: return Item::CarvedPumpkin; case 700: return Item::CatSpawnEgg; case 694: return Item::Cauldron; case 701: return Item::CaveSpiderSpawnEgg; case 373: return Item::ChainCommandBlock; case 570: return Item::ChainmailBoots; case 568: return Item::ChainmailChestplate; case 567: return Item::ChainmailHelmet; case 569: return Item::ChainmailLeggings; case 528: return Item::Charcoal; case 155: return Item::Chest; case 618: return Item::ChestMinecart; case 679: return Item::Chicken; case 702: return Item::ChickenSpawnEgg; case 266: return Item::ChippedAnvil; case 275: return Item::ChiseledQuartzBlock; case 369: return Item::ChiseledRedSandstone; case 69: return Item::ChiseledSandstone; case 208: return Item::ChiseledStoneBricks; case 149: return Item::ChorusFlower; case 819: return Item::ChorusFruit; case 148: return Item::ChorusPlant; case 179: return Item::Clay; case 610: return Item::ClayBall; case 623: return Item::Clock; case 527: return Item::Coal; case 317: return Item::CoalBlock; case 31: return Item::CoalOre; case 10: return Item::CoarseDirt; case 12: return Item::Cobblestone; case 126: return Item::CobblestoneSlab; case 163: return Item::CobblestoneStairs; case 245: return Item::CobblestoneWall; case 75: return Item::Cobweb; case 634: return Item::CocoaBeans; case 625: return Item::Cod; case 607: return Item::CodBucket; case 703: return Item::CodSpawnEgg; case 243: return Item::CommandBlock; case 799: return Item::CommandBlockMinecart; case 514: return Item::Comparator; case 621: return Item::Compass; case 517: return Item::Composter; case 477: return Item::Conduit; case 678: return Item::CookedBeef; case 680: return Item::CookedChicken; case 629: return Item::CookedCod; case 801: return Item::CookedMutton; case 585: return Item::CookedPorkchop; case 788: return Item::CookedRabbit; case 630: return Item::CookedSalmon; case 670: return Item::Cookie; case 108: return Item::Cornflower; case 704: return Item::CowSpawnEgg; case 207: return Item::CrackedStoneBricks; case 158: return Item::CraftingTable; case 861: return Item::CreeperBannerPattern; case 773: return Item::CreeperHead; case 705: return Item::CreeperSpawnEgg; case 857: return Item::Crossbow; case 370: return Item::CutRedSandstone; case 132: return Item::CutRedSandstoneSlab; case 70: return Item::CutSandstone; case 124: return Item::CutSandstoneSlab; case 811: return Item::CyanBanner; case 663: return Item::CyanBed; case 309: return Item::CyanCarpet; case 422: return Item::CyanConcrete; case 438: return Item::CyanConcretePowder; case 637: return Item::CyanDye; case 406: return Item::CyanGlazedTerracotta; case 390: return Item::CyanShulkerBox; case 338: return Item::CyanStainedGlass; case 354: return Item::CyanStainedGlassPane; case 290: return Item::CyanTerracotta; case 91: return Item::CyanWool; case 267: return Item::DamagedAnvil; case 98: return Item::Dandelion; case 835: return Item::DarkOakBoat; case 264: return Item::DarkOakButton; case 512: return Item::DarkOakDoor; case 186: return Item::DarkOakFence; case 221: return Item::DarkOakFenceGate; case 61: return Item::DarkOakLeaves; case 37: return Item::DarkOakLog; case 18: return Item::DarkOakPlanks; case 171: return Item::DarkOakPressurePlate; case 24: return Item::DarkOakSapling; case 594: return Item::DarkOakSign; case 120: return Item::DarkOakSlab; case 320: return Item::DarkOakStairs; case 198: return Item::DarkOakTrapdoor; case 55: return Item::DarkOakWood; case 363: return Item::DarkPrismarine; case 136: return Item::DarkPrismarineSlab; case 366: return Item::DarkPrismarineStairs; case 271: return Item::DaylightDetector; case 461: return Item::DeadBrainCoral; case 447: return Item::DeadBrainCoralBlock; case 472: return Item::DeadBrainCoralFan; case 462: return Item::DeadBubbleCoral; case 448: return Item::DeadBubbleCoralBlock; case 473: return Item::DeadBubbleCoralFan; case 78: return Item::DeadBush; case 463: return Item::DeadFireCoral; case 449: return Item::DeadFireCoralBlock; case 474: return Item::DeadFireCoralFan; case 464: return Item::DeadHornCoral; case 450: return Item::DeadHornCoralBlock; case 475: return Item::DeadHornCoralFan; case 465: return Item::DeadTubeCoral; case 446: return Item::DeadTubeCoralBlock; case 471: return Item::DeadTubeCoralFan; case 840: return Item::DebugStick; case 73: return Item::DetectorRail; case 529: return Item::Diamond; case 544: return Item::DiamondAxe; case 157: return Item::DiamondBlock; case 578: return Item::DiamondBoots; case 576: return Item::DiamondChestplate; case 575: return Item::DiamondHelmet; case 558: return Item::DiamondHoe; case 795: return Item::DiamondHorseArmor; case 577: return Item::DiamondLeggings; case 156: return Item::DiamondOre; case 543: return Item::DiamondPickaxe; case 542: return Item::DiamondShovel; case 541: return Item::DiamondSword; case 4: return Item::Diorite; case 504: return Item::DioriteSlab; case 491: return Item::DioriteStairs; case 258: return Item::DioriteWall; case 9: return Item::Dirt; case 67: return Item::Dispenser; case 706: return Item::DolphinSpawnEgg; case 707: return Item::DonkeySpawnEgg; case 824: return Item::DragonBreath; case 233: return Item::DragonEgg; case 774: return Item::DragonHead; case 674: return Item::DriedKelp; case 613: return Item::DriedKelpBlock; case 280: return Item::Dropper; case 708: return Item::DrownedSpawnEgg; case 620: return Item::Egg; case 709: return Item::ElderGuardianSpawnEgg; case 830: return Item::Elytra; case 760: return Item::Emerald; case 239: return Item::EmeraldBlock; case 236: return Item::EmeraldOre; case 780: return Item::EnchantedBook; case 588: return Item::EnchantedGoldenApple; case 229: return Item::EnchantingTable; case 818: return Item::EndCrystal; case 230: return Item::EndPortalFrame; case 147: return Item::EndRod; case 231: return Item::EndStone; case 497: return Item::EndStoneBrickSlab; case 483: return Item::EndStoneBrickStairs; case 257: return Item::EndStoneBrickWall; case 232: return Item::EndStoneBricks; case 237: return Item::EnderChest; case 695: return Item::EnderEye; case 682: return Item::EnderPearl; case 710: return Item::EndermanSpawnEgg; case 711: return Item::EndermiteSpawnEgg; case 712: return Item::EvokerSpawnEgg; case 756: return Item::ExperienceBottle; case 159: return Item::Farmland; case 553: return Item::Feather; case 690: return Item::FermentedSpiderEye; case 77: return Item::Fern; case 671: return Item::FilledMap; case 757: return Item::FireCharge; case 459: return Item::FireCoral; case 454: return Item::FireCoralBlock; case 469: return Item::FireCoralFan; case 778: return Item::FireworkRocket; case 779: return Item::FireworkStar; case 622: return Item::FishingRod; case 869: return Item::FletchingTable; case 583: return Item::Flint; case 523: return Item::FlintAndSteel; case 860: return Item::FlowerBannerPattern; case 762: return Item::FlowerPot; case 713: return Item::FoxSpawnEgg; case 160: return Item::Furnace; case 619: return Item::FurnaceMinecart; case 714: return Item::GhastSpawnEgg; case 684: return Item::GhastTear; case 64: return Item::Glass; case 688: return Item::GlassBottle; case 213: return Item::GlassPane; case 696: return Item::GlisteringMelonSlice; case 864: return Item::GlobeBannerPattern; case 191: return Item::Glowstone; case 624: return Item::GlowstoneDust; case 113: return Item::GoldBlock; case 531: return Item::GoldIngot; case 685: return Item::GoldNugget; case 29: return Item::GoldOre; case 587: return Item::GoldenApple; case 551: return Item::GoldenAxe; case 582: return Item::GoldenBoots; case 768: return Item::GoldenCarrot; case 580: return Item::GoldenChestplate; case 579: return Item::GoldenHelmet; case 559: return Item::GoldenHoe; case 794: return Item::GoldenHorseArmor; case 581: return Item::GoldenLeggings; case 550: return Item::GoldenPickaxe; case 549: return Item::GoldenShovel; case 548: return Item::GoldenSword; case 2: return Item::Granite; case 500: return Item::GraniteSlab; case 487: return Item::GraniteStairs; case 251: return Item::GraniteWall; case 76: return Item::Grass; case 8: return Item::GrassBlock; case 322: return Item::GrassPath; case 28: return Item::Gravel; case 809: return Item::GrayBanner; case 661: return Item::GrayBed; case 307: return Item::GrayCarpet; case 420: return Item::GrayConcrete; case 436: return Item::GrayConcretePowder; case 639: return Item::GrayDye; case 404: return Item::GrayGlazedTerracotta; case 388: return Item::GrayShulkerBox; case 336: return Item::GrayStainedGlass; case 352: return Item::GrayStainedGlassPane; case 288: return Item::GrayTerracotta; case 89: return Item::GrayWool; case 815: return Item::GreenBanner; case 667: return Item::GreenBed; case 313: return Item::GreenCarpet; case 426: return Item::GreenConcrete; case 442: return Item::GreenConcretePowder; case 633: return Item::GreenDye; case 410: return Item::GreenGlazedTerracotta; case 394: return Item::GreenShulkerBox; case 342: return Item::GreenStainedGlass; case 358: return Item::GreenStainedGlassPane; case 294: return Item::GreenTerracotta; case 95: return Item::GreenWool; case 870: return Item::Grindstone; case 715: return Item::GuardianSpawnEgg; case 554: return Item::Gunpowder; case 299: return Item::HayBale; case 856: return Item::HeartOfTheSea; case 270: return Item::HeavyWeightedPressurePlate; case 882: return Item::HoneyBlock; case 881: return Item::HoneyBottle; case 878: return Item::Honeycomb; case 883: return Item::HoneycombBlock; case 274: return Item::Hopper; case 784: return Item::HopperMinecart; case 460: return Item::HornCoral; case 455: return Item::HornCoralBlock; case 470: return Item::HornCoralFan; case 716: return Item::HorseSpawnEgg; case 717: return Item::HuskSpawnEgg; case 176: return Item::Ice; case 204: return Item::InfestedChiseledStoneBricks; case 200: return Item::InfestedCobblestone; case 203: return Item::InfestedCrackedStoneBricks; case 202: return Item::InfestedMossyStoneBricks; case 199: return Item::InfestedStone; case 201: return Item::InfestedStoneBricks; case 631: return Item::InkSac; case 522: return Item::IronAxe; case 212: return Item::IronBars; case 114: return Item::IronBlock; case 574: return Item::IronBoots; case 572: return Item::IronChestplate; case 506: return Item::IronDoor; case 571: return Item::IronHelmet; case 557: return Item::IronHoe; case 793: return Item::IronHorseArmor; case 530: return Item::IronIngot; case 573: return Item::IronLeggings; case 838: return Item::IronNugget; case 30: return Item::IronOre; case 521: return Item::IronPickaxe; case 520: return Item::IronShovel; case 532: return Item::IronSword; case 298: return Item::IronTrapdoor; case 761: return Item::ItemFrame; case 192: return Item::JackOLantern; case 516: return Item::Jigsaw; case 180: return Item::Jukebox; case 833: return Item::JungleBoat; case 262: return Item::JungleButton; case 510: return Item::JungleDoor; case 184: return Item::JungleFence; case 219: return Item::JungleFenceGate; case 59: return Item::JungleLeaves; case 35: return Item::JungleLog; case 16: return Item::JunglePlanks; case 169: return Item::JunglePressurePlate; case 22: return Item::JungleSapling; case 592: return Item::JungleSign; case 118: return Item::JungleSlab; case 242: return Item::JungleStairs; case 196: return Item::JungleTrapdoor; case 53: return Item::JungleWood; case 612: return Item::Kelp; case 839: return Item::KnowledgeBook; case 161: return Item::Ladder; case 875: return Item::Lantern; case 66: return Item::LapisBlock; case 635: return Item::LapisLazuli; case 65: return Item::LapisOre; case 328: return Item::LargeFern; case 597: return Item::LavaBucket; case 797: return Item::Lead; case 603: return Item::Leather; case 566: return Item::LeatherBoots; case 564: return Item::LeatherChestplate; case 563: return Item::LeatherHelmet; case 796: return Item::LeatherHorseArmor; case 565: return Item::LeatherLeggings; case 871: return Item::Lectern; case 164: return Item::Lever; case 805: return Item::LightBlueBanner; case 657: return Item::LightBlueBed; case 303: return Item::LightBlueCarpet; case 416: return Item::LightBlueConcrete; case 432: return Item::LightBlueConcretePowder; case 643: return Item::LightBlueDye; case 400: return Item::LightBlueGlazedTerracotta; case 384: return Item::LightBlueShulkerBox; case 332: return Item::LightBlueStainedGlass; case 348: return Item::LightBlueStainedGlassPane; case 284: return Item::LightBlueTerracotta; case 85: return Item::LightBlueWool; case 810: return Item::LightGrayBanner; case 662: return Item::LightGrayBed; case 308: return Item::LightGrayCarpet; case 421: return Item::LightGrayConcrete; case 437: return Item::LightGrayConcretePowder; case 638: return Item::LightGrayDye; case 405: return Item::LightGrayGlazedTerracotta; case 389: return Item::LightGrayShulkerBox; case 337: return Item::LightGrayStainedGlass; case 353: return Item::LightGrayStainedGlassPane; case 289: return Item::LightGrayTerracotta; case 90: return Item::LightGrayWool; case 269: return Item::LightWeightedPressurePlate; case 324: return Item::Lilac; case 109: return Item::LilyOfTheValley; case 225: return Item::LilyPad; case 807: return Item::LimeBanner; case 659: return Item::LimeBed; case 305: return Item::LimeCarpet; case 418: return Item::LimeConcrete; case 434: return Item::LimeConcretePowder; case 641: return Item::LimeDye; case 402: return Item::LimeGlazedTerracotta; case 386: return Item::LimeShulkerBox; case 334: return Item::LimeStainedGlass; case 350: return Item::LimeStainedGlassPane; case 286: return Item::LimeTerracotta; case 87: return Item::LimeWool; case 828: return Item::LingeringPotion; case 718: return Item::LlamaSpawnEgg; case 859: return Item::Loom; case 804: return Item::MagentaBanner; case 656: return Item::MagentaBed; case 302: return Item::MagentaCarpet; case 415: return Item::MagentaConcrete; case 431: return Item::MagentaConcretePowder; case 644: return Item::MagentaDye; case 399: return Item::MagentaGlazedTerracotta; case 383: return Item::MagentaShulkerBox; case 331: return Item::MagentaStainedGlass; case 347: return Item::MagentaStainedGlassPane; case 283: return Item::MagentaTerracotta; case 84: return Item::MagentaWool; case 374: return Item::MagmaBlock; case 692: return Item::MagmaCream; case 719: return Item::MagmaCubeSpawnEgg; case 767: return Item::Map; case 214: return Item::Melon; case 676: return Item::MelonSeeds; case 673: return Item::MelonSlice; case 604: return Item::MilkBucket; case 598: return Item::Minecart; case 863: return Item::MojangBannerPattern; case 720: return Item::MooshroomSpawnEgg; case 144: return Item::MossyCobblestone; case 496: return Item::MossyCobblestoneSlab; case 482: return Item::MossyCobblestoneStairs; case 246: return Item::MossyCobblestoneWall; case 494: return Item::MossyStoneBrickSlab; case 480: return Item::MossyStoneBrickStairs; case 250: return Item::MossyStoneBrickWall; case 206: return Item::MossyStoneBricks; case 721: return Item::MuleSpawnEgg; case 211: return Item::MushroomStem; case 547: return Item::MushroomStew; case 851: return Item::MusicDisc11; case 841: return Item::MusicDisc13; case 843: return Item::MusicDiscBlocks; case 842: return Item::MusicDiscCat; case 844: return Item::MusicDiscChirp; case 845: return Item::MusicDiscFar; case 846: return Item::MusicDiscMall; case 847: return Item::MusicDiscMellohi; case 848: return Item::MusicDiscStal; case 849: return Item::MusicDiscStrad; case 852: return Item::MusicDiscWait; case 850: return Item::MusicDiscWard; case 800: return Item::Mutton; case 224: return Item::Mycelium; case 798: return Item::NameTag; case 855: return Item::NautilusShell; case 781: return Item::NetherBrick; case 227: return Item::NetherBrickFence; case 129: return Item::NetherBrickSlab; case 228: return Item::NetherBrickStairs; case 253: return Item::NetherBrickWall; case 226: return Item::NetherBricks; case 273: return Item::NetherQuartzOre; case 776: return Item::NetherStar; case 686: return Item::NetherWart; case 375: return Item::NetherWartBlock; case 189: return Item::Netherrack; case 71: return Item::NoteBlock; case 602: return Item::OakBoat; case 259: return Item::OakButton; case 507: return Item::OakDoor; case 181: return Item::OakFence; case 216: return Item::OakFenceGate; case 56: return Item::OakLeaves; case 32: return Item::OakLog; case 13: return Item::OakPlanks; case 166: return Item::OakPressurePlate; case 19: return Item::OakSapling; case 589: return Item::OakSign; case 115: return Item::OakSlab; case 154: return Item::OakStairs; case 193: return Item::OakTrapdoor; case 50: return Item::OakWood; case 379: return Item::Observer; case 145: return Item::Obsidian; case 722: return Item::OcelotSpawnEgg; case 803: return Item::OrangeBanner; case 655: return Item::OrangeBed; case 301: return Item::OrangeCarpet; case 414: return Item::OrangeConcrete; case 430: return Item::OrangeConcretePowder; case 645: return Item::OrangeDye; case 398: return Item::OrangeGlazedTerracotta; case 382: return Item::OrangeShulkerBox; case 330: return Item::OrangeStainedGlass; case 346: return Item::OrangeStainedGlassPane; case 282: return Item::OrangeTerracotta; case 104: return Item::OrangeTulip; case 83: return Item::OrangeWool; case 107: return Item::OxeyeDaisy; case 318: return Item::PackedIce; case 586: return Item::Painting; case 723: return Item::PandaSpawnEgg; case 615: return Item::Paper; case 724: return Item::ParrotSpawnEgg; case 326: return Item::Peony; case 125: return Item::PetrifiedOakSlab; case 854: return Item::PhantomMembrane; case 725: return Item::PhantomSpawnEgg; case 726: return Item::PigSpawnEgg; case 727: return Item::PillagerSpawnEgg; case 808: return Item::PinkBanner; case 660: return Item::PinkBed; case 306: return Item::PinkCarpet; case 419: return Item::PinkConcrete; case 435: return Item::PinkConcretePowder; case 640: return Item::PinkDye; case 403: return Item::PinkGlazedTerracotta; case 387: return Item::PinkShulkerBox; case 335: return Item::PinkStainedGlass; case 351: return Item::PinkStainedGlassPane; case 287: return Item::PinkTerracotta; case 106: return Item::PinkTulip; case 88: return Item::PinkWool; case 81: return Item::Piston; case 771: return Item::PlayerHead; case 11: return Item::Podzol; case 766: return Item::PoisonousPotato; case 728: return Item::PolarBearSpawnEgg; case 7: return Item::PolishedAndesite; case 503: return Item::PolishedAndesiteSlab; case 490: return Item::PolishedAndesiteStairs; case 5: return Item::PolishedDiorite; case 495: return Item::PolishedDioriteSlab; case 481: return Item::PolishedDioriteStairs; case 3: return Item::PolishedGranite; case 492: return Item::PolishedGraniteSlab; case 478: return Item::PolishedGraniteStairs; case 820: return Item::PoppedChorusFruit; case 99: return Item::Poppy; case 584: return Item::Porkchop; case 764: return Item::Potato; case 687: return Item::Potion; case 72: return Item::PoweredRail; case 361: return Item::Prismarine; case 135: return Item::PrismarineBrickSlab; case 365: return Item::PrismarineBrickStairs; case 362: return Item::PrismarineBricks; case 786: return Item::PrismarineCrystals; case 785: return Item::PrismarineShard; case 134: return Item::PrismarineSlab; case 364: return Item::PrismarineStairs; case 248: return Item::PrismarineWall; case 628: return Item::Pufferfish; case 605: return Item::PufferfishBucket; case 729: return Item::PufferfishSpawnEgg; case 187: return Item::Pumpkin; case 777: return Item::PumpkinPie; case 675: return Item::PumpkinSeeds; case 812: return Item::PurpleBanner; case 664: return Item::PurpleBed; case 310: return Item::PurpleCarpet; case 423: return Item::PurpleConcrete; case 439: return Item::PurpleConcretePowder; case 636: return Item::PurpleDye; case 407: return Item::PurpleGlazedTerracotta; case 391: return Item::PurpleShulkerBox; case 339: return Item::PurpleStainedGlass; case 355: return Item::PurpleStainedGlassPane; case 291: return Item::PurpleTerracotta; case 92: return Item::PurpleWool; case 150: return Item::PurpurBlock; case 151: return Item::PurpurPillar; case 133: return Item::PurpurSlab; case 152: return Item::PurpurStairs; case 782: return Item::Quartz; case 276: return Item::QuartzBlock; case 277: return Item::QuartzPillar; case 130: return Item::QuartzSlab; case 278: return Item::QuartzStairs; case 787: return Item::Rabbit; case 790: return Item::RabbitFoot; case 791: return Item::RabbitHide; case 730: return Item::RabbitSpawnEgg; case 789: return Item::RabbitStew; case 162: return Item::Rail; case 731: return Item::RavagerSpawnEgg; case 816: return Item::RedBanner; case 668: return Item::RedBed; case 314: return Item::RedCarpet; case 427: return Item::RedConcrete; case 443: return Item::RedConcretePowder; case 632: return Item::RedDye; case 411: return Item::RedGlazedTerracotta; case 112: return Item::RedMushroom; case 210: return Item::RedMushroomBlock; case 502: return Item::RedNetherBrickSlab; case 489: return Item::RedNetherBrickStairs; case 255: return Item::RedNetherBrickWall; case 376: return Item::RedNetherBricks; case 27: return Item::RedSand; case 368: return Item::RedSandstone; case 131: return Item::RedSandstoneSlab; case 371: return Item::RedSandstoneStairs; case 249: return Item::RedSandstoneWall; case 395: return Item::RedShulkerBox; case 343: return Item::RedStainedGlass; case 359: return Item::RedStainedGlassPane; case 295: return Item::RedTerracotta; case 103: return Item::RedTulip; case 96: return Item::RedWool; case 600: return Item::Redstone; case 272: return Item::RedstoneBlock; case 234: return Item::RedstoneLamp; case 172: return Item::RedstoneOre; case 173: return Item::RedstoneTorch; case 513: return Item::Repeater; case 372: return Item::RepeatingCommandBlock; case 325: return Item::RoseBush; case 681: return Item::RottenFlesh; case 599: return Item::Saddle; case 626: return Item::Salmon; case 606: return Item::SalmonBucket; case 732: return Item::SalmonSpawnEgg; case 26: return Item::Sand; case 68: return Item::Sandstone; case 123: return Item::SandstoneSlab; case 235: return Item::SandstoneStairs; case 256: return Item::SandstoneWall; case 505: return Item::Scaffolding; case 519: return Item::Scute; case 367: return Item::SeaLantern; case 80: return Item::SeaPickle; case 79: return Item::Seagrass; case 672: return Item::Shears; case 733: return Item::SheepSpawnEgg; case 829: return Item::Shield; case 380: return Item::ShulkerBox; case 837: return Item::ShulkerShell; case 734: return Item::ShulkerSpawnEgg; case 735: return Item::SilverfishSpawnEgg; case 737: return Item::SkeletonHorseSpawnEgg; case 769: return Item::SkeletonSkull; case 736: return Item::SkeletonSpawnEgg; case 862: return Item::SkullBannerPattern; case 617: return Item::SlimeBall; case 321: return Item::SlimeBlock; case 738: return Item::SlimeSpawnEgg; case 872: return Item::SmithingTable; case 866: return Item::Smoker; case 137: return Item::SmoothQuartz; case 499: return Item::SmoothQuartzSlab; case 486: return Item::SmoothQuartzStairs; case 138: return Item::SmoothRedSandstone; case 493: return Item::SmoothRedSandstoneSlab; case 479: return Item::SmoothRedSandstoneStairs; case 139: return Item::SmoothSandstone; case 498: return Item::SmoothSandstoneSlab; case 485: return Item::SmoothSandstoneStairs; case 140: return Item::SmoothStone; case 122: return Item::SmoothStoneSlab; case 175: return Item::Snow; case 177: return Item::SnowBlock; case 601: return Item::Snowball; case 190: return Item::SoulSand; case 153: return Item::Spawner; case 826: return Item::SpectralArrow; case 689: return Item::SpiderEye; case 739: return Item::SpiderSpawnEgg; case 825: return Item::SplashPotion; case 62: return Item::Sponge; case 831: return Item::SpruceBoat; case 260: return Item::SpruceButton; case 508: return Item::SpruceDoor; case 182: return Item::SpruceFence; case 217: return Item::SpruceFenceGate; case 57: return Item::SpruceLeaves; case 33: return Item::SpruceLog; case 14: return Item::SprucePlanks; case 167: return Item::SprucePressurePlate; case 20: return Item::SpruceSapling; case 590: return Item::SpruceSign; case 116: return Item::SpruceSlab; case 240: return Item::SpruceStairs; case 194: return Item::SpruceTrapdoor; case 51: return Item::SpruceWood; case 740: return Item::SquidSpawnEgg; case 545: return Item::Stick; case 74: return Item::StickyPiston; case 1: return Item::Stone; case 540: return Item::StoneAxe; case 128: return Item::StoneBrickSlab; case 223: return Item::StoneBrickStairs; case 252: return Item::StoneBrickWall; case 205: return Item::StoneBricks; case 174: return Item::StoneButton; case 556: return Item::StoneHoe; case 539: return Item::StonePickaxe; case 165: return Item::StonePressurePlate; case 538: return Item::StoneShovel; case 121: return Item::StoneSlab; case 484: return Item::StoneStairs; case 537: return Item::StoneSword; case 873: return Item::Stonecutter; case 741: return Item::StraySpawnEgg; case 552: return Item::String; case 42: return Item::StrippedAcaciaLog; case 48: return Item::StrippedAcaciaWood; case 40: return Item::StrippedBirchLog; case 46: return Item::StrippedBirchWood; case 43: return Item::StrippedDarkOakLog; case 49: return Item::StrippedDarkOakWood; case 41: return Item::StrippedJungleLog; case 47: return Item::StrippedJungleWood; case 38: return Item::StrippedOakLog; case 44: return Item::StrippedOakWood; case 39: return Item::StrippedSpruceLog; case 45: return Item::StrippedSpruceWood; case 515: return Item::StructureBlock; case 378: return Item::StructureVoid; case 652: return Item::Sugar; case 611: return Item::SugarCane; case 323: return Item::Sunflower; case 858: return Item::SuspiciousStew; case 876: return Item::SweetBerries; case 327: return Item::TallGrass; case 316: return Item::Terracotta; case 827: return Item::TippedArrow; case 142: return Item::TNT; case 783: return Item::TNTMinecart; case 146: return Item::Torch; case 836: return Item::TotemOfUndying; case 742: return Item::TraderLlamaSpawnEgg; case 268: return Item::TrappedChest; case 853: return Item::Trident; case 238: return Item::TripwireHook; case 627: return Item::TropicalFish; case 608: return Item::TropicalFishBucket; case 743: return Item::TropicalFishSpawnEgg; case 456: return Item::TubeCoral; case 451: return Item::TubeCoralBlock; case 466: return Item::TubeCoralFan; case 445: return Item::TurtleEgg; case 518: return Item::TurtleHelmet; case 744: return Item::TurtleSpawnEgg; case 745: return Item::VexSpawnEgg; case 746: return Item::VillagerSpawnEgg; case 747: return Item::VindicatorSpawnEgg; case 215: return Item::Vine; case 748: return Item::WanderingTraderSpawnEgg; case 596: return Item::WaterBucket; case 63: return Item::WetSponge; case 561: return Item::Wheat; case 560: return Item::WheatSeeds; case 802: return Item::WhiteBanner; case 654: return Item::WhiteBed; case 300: return Item::WhiteCarpet; case 413: return Item::WhiteConcrete; case 429: return Item::WhiteConcretePowder; case 650: return Item::WhiteDye; case 397: return Item::WhiteGlazedTerracotta; case 381: return Item::WhiteShulkerBox; case 329: return Item::WhiteStainedGlass; case 345: return Item::WhiteStainedGlassPane; case 281: return Item::WhiteTerracotta; case 105: return Item::WhiteTulip; case 82: return Item::WhiteWool; case 749: return Item::WitchSpawnEgg; case 110: return Item::WitherRose; case 770: return Item::WitherSkeletonSkull; case 750: return Item::WitherSkeletonSpawnEgg; case 751: return Item::WolfSpawnEgg; case 536: return Item::WoodenAxe; case 555: return Item::WoodenHoe; case 535: return Item::WoodenPickaxe; case 534: return Item::WoodenShovel; case 533: return Item::WoodenSword; case 758: return Item::WritableBook; case 759: return Item::WrittenBook; case 806: return Item::YellowBanner; case 658: return Item::YellowBed; case 304: return Item::YellowCarpet; case 417: return Item::YellowConcrete; case 433: return Item::YellowConcretePowder; case 642: return Item::YellowDye; case 401: return Item::YellowGlazedTerracotta; case 385: return Item::YellowShulkerBox; case 333: return Item::YellowStainedGlass; case 349: return Item::YellowStainedGlassPane; case 285: return Item::YellowTerracotta; case 86: return Item::YellowWool; case 772: return Item::ZombieHead; case 753: return Item::ZombieHorseSpawnEgg; case 754: return Item::ZombiePigmanSpawnEgg; case 752: return Item::ZombieSpawnEgg; case 755: return Item::ZombieVillagerSpawnEgg; default: return Item::Air; } } } ================================================ FILE: src/Protocol/Palettes/Palette_1_15.h ================================================ #pragma once #include "BlockState.h" #include "Registries/Items.h" #include "Registries/CustomStatistics.h" namespace Palette_1_15 { UInt32 From(BlockState Block); UInt32 From(Item ID); UInt32 From(CustomStatistic ID); Item ToItem(UInt32 ID); } ================================================ FILE: src/Protocol/Palettes/Palette_1_16.cpp ================================================ #include "Globals.h" #include "Palette_1_16.h" #include "Registries/BlockStates.h" namespace Palette_1_16 { UInt32 From(const BlockState Block) { using namespace Block; switch (Block.ID) { case AcaciaButton::AcaciaButton(AcaciaButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, true).ID: return 6442; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, false).ID: return 6443; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, true).ID: return 6444; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, false).ID: return 6445; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, true).ID: return 6446; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, false).ID: return 6447; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, true).ID: return 6448; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, false).ID: return 6449; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, true).ID: return 6450; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, false).ID: return 6451; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, true).ID: return 6452; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, false).ID: return 6453; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, true).ID: return 6454; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, false).ID: return 6455; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, true).ID: return 6456; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, false).ID: return 6457; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, true).ID: return 6458; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, false).ID: return 6459; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, true).ID: return 6460; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, false).ID: return 6461; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, true).ID: return 6462; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, false).ID: return 6463; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, true).ID: return 6464; case AcaciaButton::AcaciaButton(AcaciaButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, false).ID: return 6465; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, true, true).ID: return 8930; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, true, false).ID: return 8931; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, false, true).ID: return 8932; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, false, false).ID: return 8933; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, true, true).ID: return 8934; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, true, false).ID: return 8935; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, false, true).ID: return 8936; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, false, false).ID: return 8937; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, true, true).ID: return 8938; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, true, false).ID: return 8939; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, false, true).ID: return 8940; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, false, false).ID: return 8941; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, true, true).ID: return 8942; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, true, false).ID: return 8943; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, false, true).ID: return 8944; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, false, false).ID: return 8945; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, true, true).ID: return 8946; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, true, false).ID: return 8947; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, false, true).ID: return 8948; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, false, false).ID: return 8949; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, true, true).ID: return 8950; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, true, false).ID: return 8951; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, false, true).ID: return 8952; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, false, false).ID: return 8953; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, true, true).ID: return 8954; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, true, false).ID: return 8955; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, false, true).ID: return 8956; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, false, false).ID: return 8957; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, true, true).ID: return 8958; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, true, false).ID: return 8959; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, false, true).ID: return 8960; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, false, false).ID: return 8961; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, true, true).ID: return 8962; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, true, false).ID: return 8963; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, false, true).ID: return 8964; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, false, false).ID: return 8965; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, true, true).ID: return 8966; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, true, false).ID: return 8967; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, false, true).ID: return 8968; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, false, false).ID: return 8969; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, true, true).ID: return 8970; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, true, false).ID: return 8971; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, false, true).ID: return 8972; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, false, false).ID: return 8973; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, true, true).ID: return 8974; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, true, false).ID: return 8975; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, false, true).ID: return 8976; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, false, false).ID: return 8977; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, true, true).ID: return 8978; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, true, false).ID: return 8979; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, false, true).ID: return 8980; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, false, false).ID: return 8981; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, true, true).ID: return 8982; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, true, false).ID: return 8983; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, false, true).ID: return 8984; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, false, false).ID: return 8985; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, true, true).ID: return 8986; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, true, false).ID: return 8987; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, false, true).ID: return 8988; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Left, false, false).ID: return 8989; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, true, true).ID: return 8990; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, true, false).ID: return 8991; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, false, true).ID: return 8992; case AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, false, false).ID: return 8993; case AcaciaFence::AcaciaFence(true, true, true, true).ID: return 8676; case AcaciaFence::AcaciaFence(true, true, true, false).ID: return 8677; case AcaciaFence::AcaciaFence(true, true, false, true).ID: return 8680; case AcaciaFence::AcaciaFence(true, true, false, false).ID: return 8681; case AcaciaFence::AcaciaFence(true, false, true, true).ID: return 8684; case AcaciaFence::AcaciaFence(true, false, true, false).ID: return 8685; case AcaciaFence::AcaciaFence(true, false, false, true).ID: return 8688; case AcaciaFence::AcaciaFence(true, false, false, false).ID: return 8689; case AcaciaFence::AcaciaFence(false, true, true, true).ID: return 8692; case AcaciaFence::AcaciaFence(false, true, true, false).ID: return 8693; case AcaciaFence::AcaciaFence(false, true, false, true).ID: return 8696; case AcaciaFence::AcaciaFence(false, true, false, false).ID: return 8697; case AcaciaFence::AcaciaFence(false, false, true, true).ID: return 8700; case AcaciaFence::AcaciaFence(false, false, true, false).ID: return 8701; case AcaciaFence::AcaciaFence(false, false, false, true).ID: return 8704; case AcaciaFence::AcaciaFence(false, false, false, false).ID: return 8705; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZM, true, true, true).ID: return 8514; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZM, true, true, false).ID: return 8515; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZM, true, false, true).ID: return 8516; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZM, true, false, false).ID: return 8517; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, true).ID: return 8518; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, false).ID: return 8519; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, true).ID: return 8520; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, false).ID: return 8521; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZP, true, true, true).ID: return 8522; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZP, true, true, false).ID: return 8523; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZP, true, false, true).ID: return 8524; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZP, true, false, false).ID: return 8525; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, true).ID: return 8526; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, false).ID: return 8527; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, true).ID: return 8528; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, false).ID: return 8529; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XM, true, true, true).ID: return 8530; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XM, true, true, false).ID: return 8531; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XM, true, false, true).ID: return 8532; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XM, true, false, false).ID: return 8533; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, true).ID: return 8534; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, false).ID: return 8535; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, true).ID: return 8536; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, false).ID: return 8537; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XP, true, true, true).ID: return 8538; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XP, true, true, false).ID: return 8539; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XP, true, false, true).ID: return 8540; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XP, true, false, false).ID: return 8541; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, true).ID: return 8542; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, false).ID: return 8543; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, true).ID: return 8544; case AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, false).ID: return 8545; case AcaciaLeaves::AcaciaLeaves(1, true).ID: return 201; case AcaciaLeaves::AcaciaLeaves(1, false).ID: return 202; case AcaciaLeaves::AcaciaLeaves(2, true).ID: return 203; case AcaciaLeaves::AcaciaLeaves(2, false).ID: return 204; case AcaciaLeaves::AcaciaLeaves(3, true).ID: return 205; case AcaciaLeaves::AcaciaLeaves(3, false).ID: return 206; case AcaciaLeaves::AcaciaLeaves(4, true).ID: return 207; case AcaciaLeaves::AcaciaLeaves(4, false).ID: return 208; case AcaciaLeaves::AcaciaLeaves(5, true).ID: return 209; case AcaciaLeaves::AcaciaLeaves(5, false).ID: return 210; case AcaciaLeaves::AcaciaLeaves(6, true).ID: return 211; case AcaciaLeaves::AcaciaLeaves(6, false).ID: return 212; case AcaciaLeaves::AcaciaLeaves(7, true).ID: return 213; case AcaciaLeaves::AcaciaLeaves(7, false).ID: return 214; case AcaciaLog::AcaciaLog(AcaciaLog::Axis::X).ID: return 85; case AcaciaLog::AcaciaLog(AcaciaLog::Axis::Y).ID: return 86; case AcaciaLog::AcaciaLog(AcaciaLog::Axis::Z).ID: return 87; case AcaciaPlanks::AcaciaPlanks().ID: return 19; case AcaciaPressurePlate::AcaciaPressurePlate(true).ID: return 3881; case AcaciaPressurePlate::AcaciaPressurePlate(false).ID: return 3882; case AcaciaSapling::AcaciaSapling(0).ID: return 29; case AcaciaSapling::AcaciaSapling(1).ID: return 30; case AcaciaSign::AcaciaSign(0).ID: return 3478; case AcaciaSign::AcaciaSign(1).ID: return 3480; case AcaciaSign::AcaciaSign(2).ID: return 3482; case AcaciaSign::AcaciaSign(3).ID: return 3484; case AcaciaSign::AcaciaSign(4).ID: return 3486; case AcaciaSign::AcaciaSign(5).ID: return 3488; case AcaciaSign::AcaciaSign(6).ID: return 3490; case AcaciaSign::AcaciaSign(7).ID: return 3492; case AcaciaSign::AcaciaSign(8).ID: return 3494; case AcaciaSign::AcaciaSign(9).ID: return 3496; case AcaciaSign::AcaciaSign(10).ID: return 3498; case AcaciaSign::AcaciaSign(11).ID: return 3500; case AcaciaSign::AcaciaSign(12).ID: return 3502; case AcaciaSign::AcaciaSign(13).ID: return 3504; case AcaciaSign::AcaciaSign(14).ID: return 3506; case AcaciaSign::AcaciaSign(15).ID: return 3508; case AcaciaSlab::AcaciaSlab(AcaciaSlab::Type::Top).ID: return 8325; case AcaciaSlab::AcaciaSlab(AcaciaSlab::Type::Bottom).ID: return 8327; case AcaciaSlab::AcaciaSlab(AcaciaSlab::Type::Double).ID: return 8329; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZM, AcaciaStairs::Half::Top, AcaciaStairs::Shape::Straight).ID: return 7376; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZM, AcaciaStairs::Half::Top, AcaciaStairs::Shape::InnerLeft).ID: return 7378; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZM, AcaciaStairs::Half::Top, AcaciaStairs::Shape::InnerRight).ID: return 7380; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZM, AcaciaStairs::Half::Top, AcaciaStairs::Shape::OuterLeft).ID: return 7382; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZM, AcaciaStairs::Half::Top, AcaciaStairs::Shape::OuterRight).ID: return 7384; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZM, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::Straight).ID: return 7386; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZM, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::InnerLeft).ID: return 7388; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZM, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::InnerRight).ID: return 7390; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZM, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::OuterLeft).ID: return 7392; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZM, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::OuterRight).ID: return 7394; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZP, AcaciaStairs::Half::Top, AcaciaStairs::Shape::Straight).ID: return 7396; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZP, AcaciaStairs::Half::Top, AcaciaStairs::Shape::InnerLeft).ID: return 7398; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZP, AcaciaStairs::Half::Top, AcaciaStairs::Shape::InnerRight).ID: return 7400; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZP, AcaciaStairs::Half::Top, AcaciaStairs::Shape::OuterLeft).ID: return 7402; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZP, AcaciaStairs::Half::Top, AcaciaStairs::Shape::OuterRight).ID: return 7404; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZP, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::Straight).ID: return 7406; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZP, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::InnerLeft).ID: return 7408; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZP, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::InnerRight).ID: return 7410; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZP, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::OuterLeft).ID: return 7412; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZP, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::OuterRight).ID: return 7414; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XM, AcaciaStairs::Half::Top, AcaciaStairs::Shape::Straight).ID: return 7416; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XM, AcaciaStairs::Half::Top, AcaciaStairs::Shape::InnerLeft).ID: return 7418; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XM, AcaciaStairs::Half::Top, AcaciaStairs::Shape::InnerRight).ID: return 7420; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XM, AcaciaStairs::Half::Top, AcaciaStairs::Shape::OuterLeft).ID: return 7422; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XM, AcaciaStairs::Half::Top, AcaciaStairs::Shape::OuterRight).ID: return 7424; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XM, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::Straight).ID: return 7426; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XM, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::InnerLeft).ID: return 7428; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XM, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::InnerRight).ID: return 7430; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XM, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::OuterLeft).ID: return 7432; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XM, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::OuterRight).ID: return 7434; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XP, AcaciaStairs::Half::Top, AcaciaStairs::Shape::Straight).ID: return 7436; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XP, AcaciaStairs::Half::Top, AcaciaStairs::Shape::InnerLeft).ID: return 7438; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XP, AcaciaStairs::Half::Top, AcaciaStairs::Shape::InnerRight).ID: return 7440; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XP, AcaciaStairs::Half::Top, AcaciaStairs::Shape::OuterLeft).ID: return 7442; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XP, AcaciaStairs::Half::Top, AcaciaStairs::Shape::OuterRight).ID: return 7444; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XP, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::Straight).ID: return 7446; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XP, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::InnerLeft).ID: return 7448; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XP, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::InnerRight).ID: return 7450; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XP, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::OuterLeft).ID: return 7452; case AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XP, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::OuterRight).ID: return 7454; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZM, AcaciaTrapdoor::Half::Top, true, true).ID: return 4368; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZM, AcaciaTrapdoor::Half::Top, true, false).ID: return 4370; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZM, AcaciaTrapdoor::Half::Top, false, true).ID: return 4372; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZM, AcaciaTrapdoor::Half::Top, false, false).ID: return 4374; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZM, AcaciaTrapdoor::Half::Bottom, true, true).ID: return 4376; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZM, AcaciaTrapdoor::Half::Bottom, true, false).ID: return 4378; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZM, AcaciaTrapdoor::Half::Bottom, false, true).ID: return 4380; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZM, AcaciaTrapdoor::Half::Bottom, false, false).ID: return 4382; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZP, AcaciaTrapdoor::Half::Top, true, true).ID: return 4384; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZP, AcaciaTrapdoor::Half::Top, true, false).ID: return 4386; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZP, AcaciaTrapdoor::Half::Top, false, true).ID: return 4388; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZP, AcaciaTrapdoor::Half::Top, false, false).ID: return 4390; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZP, AcaciaTrapdoor::Half::Bottom, true, true).ID: return 4392; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZP, AcaciaTrapdoor::Half::Bottom, true, false).ID: return 4394; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZP, AcaciaTrapdoor::Half::Bottom, false, true).ID: return 4396; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_ZP, AcaciaTrapdoor::Half::Bottom, false, false).ID: return 4398; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XM, AcaciaTrapdoor::Half::Top, true, true).ID: return 4400; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XM, AcaciaTrapdoor::Half::Top, true, false).ID: return 4402; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XM, AcaciaTrapdoor::Half::Top, false, true).ID: return 4404; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XM, AcaciaTrapdoor::Half::Top, false, false).ID: return 4406; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XM, AcaciaTrapdoor::Half::Bottom, true, true).ID: return 4408; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XM, AcaciaTrapdoor::Half::Bottom, true, false).ID: return 4410; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XM, AcaciaTrapdoor::Half::Bottom, false, true).ID: return 4412; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XM, AcaciaTrapdoor::Half::Bottom, false, false).ID: return 4414; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XP, AcaciaTrapdoor::Half::Top, true, true).ID: return 4416; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XP, AcaciaTrapdoor::Half::Top, true, false).ID: return 4418; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XP, AcaciaTrapdoor::Half::Top, false, true).ID: return 4420; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XP, AcaciaTrapdoor::Half::Top, false, false).ID: return 4422; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XP, AcaciaTrapdoor::Half::Bottom, true, true).ID: return 4424; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XP, AcaciaTrapdoor::Half::Bottom, true, false).ID: return 4426; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XP, AcaciaTrapdoor::Half::Bottom, false, true).ID: return 4428; case AcaciaTrapdoor::AcaciaTrapdoor(eBlockFace::BLOCK_FACE_XP, AcaciaTrapdoor::Half::Bottom, false, false).ID: return 4430; case AcaciaWallSign::AcaciaWallSign(eBlockFace::BLOCK_FACE_ZM).ID: return 3760; case AcaciaWallSign::AcaciaWallSign(eBlockFace::BLOCK_FACE_ZP).ID: return 3762; case AcaciaWallSign::AcaciaWallSign(eBlockFace::BLOCK_FACE_XM).ID: return 3764; case AcaciaWallSign::AcaciaWallSign(eBlockFace::BLOCK_FACE_XP).ID: return 3766; case AcaciaWood::AcaciaWood(AcaciaWood::Axis::X).ID: return 121; case AcaciaWood::AcaciaWood(AcaciaWood::Axis::Y).ID: return 122; case AcaciaWood::AcaciaWood(AcaciaWood::Axis::Z).ID: return 123; case ActivatorRail::ActivatorRail(true, ActivatorRail::Shape::NorthSouth).ID: return 6823; case ActivatorRail::ActivatorRail(true, ActivatorRail::Shape::EastWest).ID: return 6824; case ActivatorRail::ActivatorRail(true, ActivatorRail::Shape::AscendingEast).ID: return 6825; case ActivatorRail::ActivatorRail(true, ActivatorRail::Shape::AscendingWest).ID: return 6826; case ActivatorRail::ActivatorRail(true, ActivatorRail::Shape::AscendingNorth).ID: return 6827; case ActivatorRail::ActivatorRail(true, ActivatorRail::Shape::AscendingSouth).ID: return 6828; case ActivatorRail::ActivatorRail(false, ActivatorRail::Shape::NorthSouth).ID: return 6829; case ActivatorRail::ActivatorRail(false, ActivatorRail::Shape::EastWest).ID: return 6830; case ActivatorRail::ActivatorRail(false, ActivatorRail::Shape::AscendingEast).ID: return 6831; case ActivatorRail::ActivatorRail(false, ActivatorRail::Shape::AscendingWest).ID: return 6832; case ActivatorRail::ActivatorRail(false, ActivatorRail::Shape::AscendingNorth).ID: return 6833; case ActivatorRail::ActivatorRail(false, ActivatorRail::Shape::AscendingSouth).ID: return 6834; case Air::Air().ID: return -0; case Allium::Allium().ID: return 1415; case AncientDebris::AncientDebris().ID: return 15827; case Andesite::Andesite().ID: return 6; case AndesiteSlab::AndesiteSlab(AndesiteSlab::Type::Top).ID: return 10844; case AndesiteSlab::AndesiteSlab(AndesiteSlab::Type::Bottom).ID: return 10846; case AndesiteSlab::AndesiteSlab(AndesiteSlab::Type::Double).ID: return 10848; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_ZM, AndesiteStairs::Half::Top, AndesiteStairs::Shape::Straight).ID: return 10470; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_ZM, AndesiteStairs::Half::Top, AndesiteStairs::Shape::InnerLeft).ID: return 10472; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_ZM, AndesiteStairs::Half::Top, AndesiteStairs::Shape::InnerRight).ID: return 10474; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_ZM, AndesiteStairs::Half::Top, AndesiteStairs::Shape::OuterLeft).ID: return 10476; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_ZM, AndesiteStairs::Half::Top, AndesiteStairs::Shape::OuterRight).ID: return 10478; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_ZM, AndesiteStairs::Half::Bottom, AndesiteStairs::Shape::Straight).ID: return 10480; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_ZM, AndesiteStairs::Half::Bottom, AndesiteStairs::Shape::InnerLeft).ID: return 10482; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_ZM, AndesiteStairs::Half::Bottom, AndesiteStairs::Shape::InnerRight).ID: return 10484; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_ZM, AndesiteStairs::Half::Bottom, AndesiteStairs::Shape::OuterLeft).ID: return 10486; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_ZM, AndesiteStairs::Half::Bottom, AndesiteStairs::Shape::OuterRight).ID: return 10488; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_ZP, AndesiteStairs::Half::Top, AndesiteStairs::Shape::Straight).ID: return 10490; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_ZP, AndesiteStairs::Half::Top, AndesiteStairs::Shape::InnerLeft).ID: return 10492; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_ZP, AndesiteStairs::Half::Top, AndesiteStairs::Shape::InnerRight).ID: return 10494; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_ZP, AndesiteStairs::Half::Top, AndesiteStairs::Shape::OuterLeft).ID: return 10496; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_ZP, AndesiteStairs::Half::Top, AndesiteStairs::Shape::OuterRight).ID: return 10498; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_ZP, AndesiteStairs::Half::Bottom, AndesiteStairs::Shape::Straight).ID: return 10500; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_ZP, AndesiteStairs::Half::Bottom, AndesiteStairs::Shape::InnerLeft).ID: return 10502; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_ZP, AndesiteStairs::Half::Bottom, AndesiteStairs::Shape::InnerRight).ID: return 10504; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_ZP, AndesiteStairs::Half::Bottom, AndesiteStairs::Shape::OuterLeft).ID: return 10506; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_ZP, AndesiteStairs::Half::Bottom, AndesiteStairs::Shape::OuterRight).ID: return 10508; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_XM, AndesiteStairs::Half::Top, AndesiteStairs::Shape::Straight).ID: return 10510; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_XM, AndesiteStairs::Half::Top, AndesiteStairs::Shape::InnerLeft).ID: return 10512; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_XM, AndesiteStairs::Half::Top, AndesiteStairs::Shape::InnerRight).ID: return 10514; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_XM, AndesiteStairs::Half::Top, AndesiteStairs::Shape::OuterLeft).ID: return 10516; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_XM, AndesiteStairs::Half::Top, AndesiteStairs::Shape::OuterRight).ID: return 10518; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_XM, AndesiteStairs::Half::Bottom, AndesiteStairs::Shape::Straight).ID: return 10520; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_XM, AndesiteStairs::Half::Bottom, AndesiteStairs::Shape::InnerLeft).ID: return 10522; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_XM, AndesiteStairs::Half::Bottom, AndesiteStairs::Shape::InnerRight).ID: return 10524; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_XM, AndesiteStairs::Half::Bottom, AndesiteStairs::Shape::OuterLeft).ID: return 10526; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_XM, AndesiteStairs::Half::Bottom, AndesiteStairs::Shape::OuterRight).ID: return 10528; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_XP, AndesiteStairs::Half::Top, AndesiteStairs::Shape::Straight).ID: return 10530; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_XP, AndesiteStairs::Half::Top, AndesiteStairs::Shape::InnerLeft).ID: return 10532; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_XP, AndesiteStairs::Half::Top, AndesiteStairs::Shape::InnerRight).ID: return 10534; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_XP, AndesiteStairs::Half::Top, AndesiteStairs::Shape::OuterLeft).ID: return 10536; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_XP, AndesiteStairs::Half::Top, AndesiteStairs::Shape::OuterRight).ID: return 10538; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_XP, AndesiteStairs::Half::Bottom, AndesiteStairs::Shape::Straight).ID: return 10540; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_XP, AndesiteStairs::Half::Bottom, AndesiteStairs::Shape::InnerLeft).ID: return 10542; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_XP, AndesiteStairs::Half::Bottom, AndesiteStairs::Shape::InnerRight).ID: return 10544; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_XP, AndesiteStairs::Half::Bottom, AndesiteStairs::Shape::OuterLeft).ID: return 10546; case AndesiteStairs::AndesiteStairs(eBlockFace::BLOCK_FACE_XP, AndesiteStairs::Half::Bottom, AndesiteStairs::Shape::OuterRight).ID: return 10548; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::None, AndesiteWall::South::None, true, AndesiteWall::West::None).ID: return 13138; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::None, AndesiteWall::South::None, true, AndesiteWall::West::Low).ID: return 13139; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::None, AndesiteWall::South::None, true, AndesiteWall::West::Tall).ID: return 13140; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::None, AndesiteWall::South::None, false, AndesiteWall::West::None).ID: return 13144; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::None, AndesiteWall::South::None, false, AndesiteWall::West::Low).ID: return 13145; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::None, AndesiteWall::South::None, false, AndesiteWall::West::Tall).ID: return 13146; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::None, AndesiteWall::South::Low, true, AndesiteWall::West::None).ID: return 13150; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::None, AndesiteWall::South::Low, true, AndesiteWall::West::Low).ID: return 13151; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::None, AndesiteWall::South::Low, true, AndesiteWall::West::Tall).ID: return 13152; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::None, AndesiteWall::South::Low, false, AndesiteWall::West::None).ID: return 13156; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::None, AndesiteWall::South::Low, false, AndesiteWall::West::Low).ID: return 13157; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::None, AndesiteWall::South::Low, false, AndesiteWall::West::Tall).ID: return 13158; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::None, AndesiteWall::South::Tall, true, AndesiteWall::West::None).ID: return 13162; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::None, AndesiteWall::South::Tall, true, AndesiteWall::West::Low).ID: return 13163; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::None, AndesiteWall::South::Tall, true, AndesiteWall::West::Tall).ID: return 13164; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::None, AndesiteWall::South::Tall, false, AndesiteWall::West::None).ID: return 13168; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::None, AndesiteWall::South::Tall, false, AndesiteWall::West::Low).ID: return 13169; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::None, AndesiteWall::South::Tall, false, AndesiteWall::West::Tall).ID: return 13170; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::Low, AndesiteWall::South::None, true, AndesiteWall::West::None).ID: return 13174; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::Low, AndesiteWall::South::None, true, AndesiteWall::West::Low).ID: return 13175; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::Low, AndesiteWall::South::None, true, AndesiteWall::West::Tall).ID: return 13176; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::Low, AndesiteWall::South::None, false, AndesiteWall::West::None).ID: return 13180; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::Low, AndesiteWall::South::None, false, AndesiteWall::West::Low).ID: return 13181; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::Low, AndesiteWall::South::None, false, AndesiteWall::West::Tall).ID: return 13182; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::Low, AndesiteWall::South::Low, true, AndesiteWall::West::None).ID: return 13186; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::Low, AndesiteWall::South::Low, true, AndesiteWall::West::Low).ID: return 13187; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::Low, AndesiteWall::South::Low, true, AndesiteWall::West::Tall).ID: return 13188; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::Low, AndesiteWall::South::Low, false, AndesiteWall::West::None).ID: return 13192; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::Low, AndesiteWall::South::Low, false, AndesiteWall::West::Low).ID: return 13193; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::Low, AndesiteWall::South::Low, false, AndesiteWall::West::Tall).ID: return 13194; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::Low, AndesiteWall::South::Tall, true, AndesiteWall::West::None).ID: return 13198; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::Low, AndesiteWall::South::Tall, true, AndesiteWall::West::Low).ID: return 13199; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::Low, AndesiteWall::South::Tall, true, AndesiteWall::West::Tall).ID: return 13200; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::Low, AndesiteWall::South::Tall, false, AndesiteWall::West::None).ID: return 13204; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::Low, AndesiteWall::South::Tall, false, AndesiteWall::West::Low).ID: return 13205; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::Low, AndesiteWall::South::Tall, false, AndesiteWall::West::Tall).ID: return 13206; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::Tall, AndesiteWall::South::None, true, AndesiteWall::West::None).ID: return 13210; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::Tall, AndesiteWall::South::None, true, AndesiteWall::West::Low).ID: return 13211; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::Tall, AndesiteWall::South::None, true, AndesiteWall::West::Tall).ID: return 13212; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::Tall, AndesiteWall::South::None, false, AndesiteWall::West::None).ID: return 13216; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::Tall, AndesiteWall::South::None, false, AndesiteWall::West::Low).ID: return 13217; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::Tall, AndesiteWall::South::None, false, AndesiteWall::West::Tall).ID: return 13218; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::Tall, AndesiteWall::South::Low, true, AndesiteWall::West::None).ID: return 13222; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::Tall, AndesiteWall::South::Low, true, AndesiteWall::West::Low).ID: return 13223; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::Tall, AndesiteWall::South::Low, true, AndesiteWall::West::Tall).ID: return 13224; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::Tall, AndesiteWall::South::Low, false, AndesiteWall::West::None).ID: return 13228; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::Tall, AndesiteWall::South::Low, false, AndesiteWall::West::Low).ID: return 13229; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::Tall, AndesiteWall::South::Low, false, AndesiteWall::West::Tall).ID: return 13230; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::Tall, AndesiteWall::South::Tall, true, AndesiteWall::West::None).ID: return 13234; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::Tall, AndesiteWall::South::Tall, true, AndesiteWall::West::Low).ID: return 13235; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::Tall, AndesiteWall::South::Tall, true, AndesiteWall::West::Tall).ID: return 13236; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::Tall, AndesiteWall::South::Tall, false, AndesiteWall::West::None).ID: return 13240; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::Tall, AndesiteWall::South::Tall, false, AndesiteWall::West::Low).ID: return 13241; case AndesiteWall::AndesiteWall(AndesiteWall::East::None, AndesiteWall::North::Tall, AndesiteWall::South::Tall, false, AndesiteWall::West::Tall).ID: return 13242; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::None, AndesiteWall::South::None, true, AndesiteWall::West::None).ID: return 13246; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::None, AndesiteWall::South::None, true, AndesiteWall::West::Low).ID: return 13247; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::None, AndesiteWall::South::None, true, AndesiteWall::West::Tall).ID: return 13248; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::None, AndesiteWall::South::None, false, AndesiteWall::West::None).ID: return 13252; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::None, AndesiteWall::South::None, false, AndesiteWall::West::Low).ID: return 13253; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::None, AndesiteWall::South::None, false, AndesiteWall::West::Tall).ID: return 13254; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::None, AndesiteWall::South::Low, true, AndesiteWall::West::None).ID: return 13258; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::None, AndesiteWall::South::Low, true, AndesiteWall::West::Low).ID: return 13259; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::None, AndesiteWall::South::Low, true, AndesiteWall::West::Tall).ID: return 13260; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::None, AndesiteWall::South::Low, false, AndesiteWall::West::None).ID: return 13264; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::None, AndesiteWall::South::Low, false, AndesiteWall::West::Low).ID: return 13265; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::None, AndesiteWall::South::Low, false, AndesiteWall::West::Tall).ID: return 13266; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::None, AndesiteWall::South::Tall, true, AndesiteWall::West::None).ID: return 13270; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::None, AndesiteWall::South::Tall, true, AndesiteWall::West::Low).ID: return 13271; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::None, AndesiteWall::South::Tall, true, AndesiteWall::West::Tall).ID: return 13272; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::None, AndesiteWall::South::Tall, false, AndesiteWall::West::None).ID: return 13276; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::None, AndesiteWall::South::Tall, false, AndesiteWall::West::Low).ID: return 13277; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::None, AndesiteWall::South::Tall, false, AndesiteWall::West::Tall).ID: return 13278; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::Low, AndesiteWall::South::None, true, AndesiteWall::West::None).ID: return 13282; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::Low, AndesiteWall::South::None, true, AndesiteWall::West::Low).ID: return 13283; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::Low, AndesiteWall::South::None, true, AndesiteWall::West::Tall).ID: return 13284; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::Low, AndesiteWall::South::None, false, AndesiteWall::West::None).ID: return 13288; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::Low, AndesiteWall::South::None, false, AndesiteWall::West::Low).ID: return 13289; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::Low, AndesiteWall::South::None, false, AndesiteWall::West::Tall).ID: return 13290; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::Low, AndesiteWall::South::Low, true, AndesiteWall::West::None).ID: return 13294; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::Low, AndesiteWall::South::Low, true, AndesiteWall::West::Low).ID: return 13295; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::Low, AndesiteWall::South::Low, true, AndesiteWall::West::Tall).ID: return 13296; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::Low, AndesiteWall::South::Low, false, AndesiteWall::West::None).ID: return 13300; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::Low, AndesiteWall::South::Low, false, AndesiteWall::West::Low).ID: return 13301; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::Low, AndesiteWall::South::Low, false, AndesiteWall::West::Tall).ID: return 13302; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::Low, AndesiteWall::South::Tall, true, AndesiteWall::West::None).ID: return 13306; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::Low, AndesiteWall::South::Tall, true, AndesiteWall::West::Low).ID: return 13307; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::Low, AndesiteWall::South::Tall, true, AndesiteWall::West::Tall).ID: return 13308; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::Low, AndesiteWall::South::Tall, false, AndesiteWall::West::None).ID: return 13312; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::Low, AndesiteWall::South::Tall, false, AndesiteWall::West::Low).ID: return 13313; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::Low, AndesiteWall::South::Tall, false, AndesiteWall::West::Tall).ID: return 13314; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::Tall, AndesiteWall::South::None, true, AndesiteWall::West::None).ID: return 13318; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::Tall, AndesiteWall::South::None, true, AndesiteWall::West::Low).ID: return 13319; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::Tall, AndesiteWall::South::None, true, AndesiteWall::West::Tall).ID: return 13320; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::Tall, AndesiteWall::South::None, false, AndesiteWall::West::None).ID: return 13324; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::Tall, AndesiteWall::South::None, false, AndesiteWall::West::Low).ID: return 13325; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::Tall, AndesiteWall::South::None, false, AndesiteWall::West::Tall).ID: return 13326; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::Tall, AndesiteWall::South::Low, true, AndesiteWall::West::None).ID: return 13330; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::Tall, AndesiteWall::South::Low, true, AndesiteWall::West::Low).ID: return 13331; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::Tall, AndesiteWall::South::Low, true, AndesiteWall::West::Tall).ID: return 13332; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::Tall, AndesiteWall::South::Low, false, AndesiteWall::West::None).ID: return 13336; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::Tall, AndesiteWall::South::Low, false, AndesiteWall::West::Low).ID: return 13337; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::Tall, AndesiteWall::South::Low, false, AndesiteWall::West::Tall).ID: return 13338; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::Tall, AndesiteWall::South::Tall, true, AndesiteWall::West::None).ID: return 13342; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::Tall, AndesiteWall::South::Tall, true, AndesiteWall::West::Low).ID: return 13343; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::Tall, AndesiteWall::South::Tall, true, AndesiteWall::West::Tall).ID: return 13344; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::Tall, AndesiteWall::South::Tall, false, AndesiteWall::West::None).ID: return 13348; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::Tall, AndesiteWall::South::Tall, false, AndesiteWall::West::Low).ID: return 13349; case AndesiteWall::AndesiteWall(AndesiteWall::East::Low, AndesiteWall::North::Tall, AndesiteWall::South::Tall, false, AndesiteWall::West::Tall).ID: return 13350; case AndesiteWall::AndesiteWall(AndesiteWall::East::Tall, AndesiteWall::North::None, AndesiteWall::South::None, true, AndesiteWall::West::None).ID: return 13354; case AndesiteWall::AndesiteWall(AndesiteWall::East::Tall, AndesiteWall::North::None, AndesiteWall::South::None, true, AndesiteWall::West::Low).ID: return 13355; case AndesiteWall::AndesiteWall(AndesiteWall::East::Tall, AndesiteWall::North::None, AndesiteWall::South::None, true, AndesiteWall::West::Tall).ID: return 13356; case AndesiteWall::AndesiteWall(AndesiteWall::East::Tall, AndesiteWall::North::None, AndesiteWall::South::None, false, AndesiteWall::West::None).ID: return 13360; case AndesiteWall::AndesiteWall(AndesiteWall::East::Tall, AndesiteWall::North::None, AndesiteWall::South::None, false, AndesiteWall::West::Low).ID: return 13361; case AndesiteWall::AndesiteWall(AndesiteWall::East::Tall, AndesiteWall::North::None, AndesiteWall::South::None, false, AndesiteWall::West::Tall).ID: return 13362; case AndesiteWall::AndesiteWall(AndesiteWall::East::Tall, AndesiteWall::North::None, AndesiteWall::South::Low, true, AndesiteWall::West::None).ID: return 13366; case AndesiteWall::AndesiteWall(AndesiteWall::East::Tall, AndesiteWall::North::None, AndesiteWall::South::Low, true, AndesiteWall::West::Low).ID: return 13367; case AndesiteWall::AndesiteWall(AndesiteWall::East::Tall, AndesiteWall::North::None, AndesiteWall::South::Low, true, AndesiteWall::West::Tall).ID: return 13368; case AndesiteWall::AndesiteWall(AndesiteWall::East::Tall, AndesiteWall::North::None, AndesiteWall::South::Low, false, AndesiteWall::West::None).ID: return 13372; case AndesiteWall::AndesiteWall(AndesiteWall::East::Tall, AndesiteWall::North::None, AndesiteWall::South::Low, false, AndesiteWall::West::Low).ID: return 13373; case AndesiteWall::AndesiteWall(AndesiteWall::East::Tall, AndesiteWall::North::None, AndesiteWall::South::Low, false, AndesiteWall::West::Tall).ID: return 13374; case AndesiteWall::AndesiteWall(AndesiteWall::East::Tall, AndesiteWall::North::None, AndesiteWall::South::Tall, true, AndesiteWall::West::None).ID: return 13378; case AndesiteWall::AndesiteWall(AndesiteWall::East::Tall, AndesiteWall::North::None, AndesiteWall::South::Tall, true, AndesiteWall::West::Low).ID: return 13379; case AndesiteWall::AndesiteWall(AndesiteWall::East::Tall, AndesiteWall::North::None, AndesiteWall::South::Tall, true, AndesiteWall::West::Tall).ID: return 13380; case AndesiteWall::AndesiteWall(AndesiteWall::East::Tall, AndesiteWall::North::None, AndesiteWall::South::Tall, false, AndesiteWall::West::None).ID: return 13384; case AndesiteWall::AndesiteWall(AndesiteWall::East::Tall, AndesiteWall::North::None, AndesiteWall::South::Tall, false, AndesiteWall::West::Low).ID: return 13385; case AndesiteWall::AndesiteWall(AndesiteWall::East::Tall, AndesiteWall::North::None, AndesiteWall::South::Tall, false, AndesiteWall::West::Tall).ID: return 13386; case AndesiteWall::AndesiteWall(AndesiteWall::East::Tall, AndesiteWall::North::Low, AndesiteWall::South::None, true, AndesiteWall::West::None).ID: return 13390; case AndesiteWall::AndesiteWall(AndesiteWall::East::Tall, AndesiteWall::North::Low, AndesiteWall::South::None, true, AndesiteWall::West::Low).ID: return 13391; case AndesiteWall::AndesiteWall(AndesiteWall::East::Tall, AndesiteWall::North::Low, AndesiteWall::South::None, true, AndesiteWall::West::Tall).ID: return 13392; case AndesiteWall::AndesiteWall(AndesiteWall::East::Tall, AndesiteWall::North::Low, AndesiteWall::South::None, false, AndesiteWall::West::None).ID: return 13396; case AndesiteWall::AndesiteWall(AndesiteWall::East::Tall, AndesiteWall::North::Low, AndesiteWall::South::None, false, AndesiteWall::West::Low).ID: return 13397; case AndesiteWall::AndesiteWall(AndesiteWall::East::Tall, AndesiteWall::North::Low, AndesiteWall::South::None, false, AndesiteWall::West::Tall).ID: return 13398; case AndesiteWall::AndesiteWall(AndesiteWall::East::Tall, AndesiteWall::North::Low, AndesiteWall::South::Low, true, AndesiteWall::West::None).ID: return 13402; case AndesiteWall::AndesiteWall(AndesiteWall::East::Tall, AndesiteWall::North::Low, AndesiteWall::South::Low, true, AndesiteWall::West::Low).ID: return 13403; case AndesiteWall::AndesiteWall(AndesiteWall::East::Tall, AndesiteWall::North::Low, AndesiteWall::South::Low, true, AndesiteWall::West::Tall).ID: return 13404; case AndesiteWall::AndesiteWall(AndesiteWall::East::Tall, AndesiteWall::North::Low, AndesiteWall::South::Low, false, AndesiteWall::West::None).ID: return 13408; case AndesiteWall::AndesiteWall(AndesiteWall::East::Tall, AndesiteWall::North::Low, AndesiteWall::South::Low, false, AndesiteWall::West::Low).ID: return 13409; case AndesiteWall::AndesiteWall(AndesiteWall::East::Tall, AndesiteWall::North::Low, AndesiteWall::South::Low, false, AndesiteWall::West::Tall).ID: return 13410; case AndesiteWall::AndesiteWall(AndesiteWall::East::Tall, AndesiteWall::North::Low, AndesiteWall::South::Tall, true, AndesiteWall::West::None).ID: return 13414; case AndesiteWall::AndesiteWall(AndesiteWall::East::Tall, AndesiteWall::North::Low, AndesiteWall::South::Tall, true, AndesiteWall::West::Low).ID: return 13415; case AndesiteWall::AndesiteWall(AndesiteWall::East::Tall, AndesiteWall::North::Low, AndesiteWall::South::Tall, true, AndesiteWall::West::Tall).ID: return 13416; case AndesiteWall::AndesiteWall(AndesiteWall::East::Tall, AndesiteWall::North::Low, AndesiteWall::South::Tall, false, AndesiteWall::West::None).ID: return 13420; case AndesiteWall::AndesiteWall(AndesiteWall::East::Tall, AndesiteWall::North::Low, AndesiteWall::South::Tall, false, AndesiteWall::West::Low).ID: return 13421; case AndesiteWall::AndesiteWall(AndesiteWall::East::Tall, AndesiteWall::North::Low, AndesiteWall::South::Tall, false, AndesiteWall::West::Tall).ID: return 13422; case AndesiteWall::AndesiteWall(AndesiteWall::East::Tall, AndesiteWall::North::Tall, AndesiteWall::South::None, true, AndesiteWall::West::None).ID: return 13426; case AndesiteWall::AndesiteWall(AndesiteWall::East::Tall, AndesiteWall::North::Tall, AndesiteWall::South::None, true, AndesiteWall::West::Low).ID: return 13427; case AndesiteWall::AndesiteWall(AndesiteWall::East::Tall, AndesiteWall::North::Tall, AndesiteWall::South::None, true, AndesiteWall::West::Tall).ID: return 13428; case AndesiteWall::AndesiteWall(AndesiteWall::East::Tall, AndesiteWall::North::Tall, AndesiteWall::South::None, false, AndesiteWall::West::None).ID: return 13432; case AndesiteWall::AndesiteWall(AndesiteWall::East::Tall, AndesiteWall::North::Tall, AndesiteWall::South::None, false, AndesiteWall::West::Low).ID: return 13433; case AndesiteWall::AndesiteWall(AndesiteWall::East::Tall, AndesiteWall::North::Tall, AndesiteWall::South::None, false, AndesiteWall::West::Tall).ID: return 13434; case AndesiteWall::AndesiteWall(AndesiteWall::East::Tall, AndesiteWall::North::Tall, AndesiteWall::South::Low, true, AndesiteWall::West::None).ID: return 13438; case AndesiteWall::AndesiteWall(AndesiteWall::East::Tall, AndesiteWall::North::Tall, AndesiteWall::South::Low, true, AndesiteWall::West::Low).ID: return 13439; case AndesiteWall::AndesiteWall(AndesiteWall::East::Tall, AndesiteWall::North::Tall, AndesiteWall::South::Low, true, AndesiteWall::West::Tall).ID: return 13440; case AndesiteWall::AndesiteWall(AndesiteWall::East::Tall, AndesiteWall::North::Tall, AndesiteWall::South::Low, false, AndesiteWall::West::None).ID: return 13444; case AndesiteWall::AndesiteWall(AndesiteWall::East::Tall, AndesiteWall::North::Tall, AndesiteWall::South::Low, false, AndesiteWall::West::Low).ID: return 13445; case AndesiteWall::AndesiteWall(AndesiteWall::East::Tall, AndesiteWall::North::Tall, AndesiteWall::South::Low, false, AndesiteWall::West::Tall).ID: return 13446; case AndesiteWall::AndesiteWall(AndesiteWall::East::Tall, AndesiteWall::North::Tall, AndesiteWall::South::Tall, true, AndesiteWall::West::None).ID: return 13450; case AndesiteWall::AndesiteWall(AndesiteWall::East::Tall, AndesiteWall::North::Tall, AndesiteWall::South::Tall, true, AndesiteWall::West::Low).ID: return 13451; case AndesiteWall::AndesiteWall(AndesiteWall::East::Tall, AndesiteWall::North::Tall, AndesiteWall::South::Tall, true, AndesiteWall::West::Tall).ID: return 13452; case AndesiteWall::AndesiteWall(AndesiteWall::East::Tall, AndesiteWall::North::Tall, AndesiteWall::South::Tall, false, AndesiteWall::West::None).ID: return 13456; case AndesiteWall::AndesiteWall(AndesiteWall::East::Tall, AndesiteWall::North::Tall, AndesiteWall::South::Tall, false, AndesiteWall::West::Low).ID: return 13457; case AndesiteWall::AndesiteWall(AndesiteWall::East::Tall, AndesiteWall::North::Tall, AndesiteWall::South::Tall, false, AndesiteWall::West::Tall).ID: return 13458; case Anvil::Anvil(eBlockFace::BLOCK_FACE_ZM).ID: return 6610; case Anvil::Anvil(eBlockFace::BLOCK_FACE_ZP).ID: return 6611; case Anvil::Anvil(eBlockFace::BLOCK_FACE_XM).ID: return 6612; case Anvil::Anvil(eBlockFace::BLOCK_FACE_XP).ID: return 6613; case AttachedMelonStem::AttachedMelonStem(eBlockFace::BLOCK_FACE_ZM).ID: return 4768; case AttachedMelonStem::AttachedMelonStem(eBlockFace::BLOCK_FACE_ZP).ID: return 4769; case AttachedMelonStem::AttachedMelonStem(eBlockFace::BLOCK_FACE_XM).ID: return 4770; case AttachedMelonStem::AttachedMelonStem(eBlockFace::BLOCK_FACE_XP).ID: return 4771; case AttachedPumpkinStem::AttachedPumpkinStem(eBlockFace::BLOCK_FACE_ZM).ID: return 4764; case AttachedPumpkinStem::AttachedPumpkinStem(eBlockFace::BLOCK_FACE_ZP).ID: return 4765; case AttachedPumpkinStem::AttachedPumpkinStem(eBlockFace::BLOCK_FACE_XM).ID: return 4766; case AttachedPumpkinStem::AttachedPumpkinStem(eBlockFace::BLOCK_FACE_XP).ID: return 4767; case AzureBluet::AzureBluet().ID: return 1416; case Bamboo::Bamboo(0, Bamboo::Leaves::None, 0).ID: return 9652; case Bamboo::Bamboo(0, Bamboo::Leaves::None, 1).ID: return 9653; case Bamboo::Bamboo(0, Bamboo::Leaves::Small, 0).ID: return 9654; case Bamboo::Bamboo(0, Bamboo::Leaves::Small, 1).ID: return 9655; case Bamboo::Bamboo(0, Bamboo::Leaves::Large, 0).ID: return 9656; case Bamboo::Bamboo(0, Bamboo::Leaves::Large, 1).ID: return 9657; case Bamboo::Bamboo(1, Bamboo::Leaves::None, 0).ID: return 9658; case Bamboo::Bamboo(1, Bamboo::Leaves::None, 1).ID: return 9659; case Bamboo::Bamboo(1, Bamboo::Leaves::Small, 0).ID: return 9660; case Bamboo::Bamboo(1, Bamboo::Leaves::Small, 1).ID: return 9661; case Bamboo::Bamboo(1, Bamboo::Leaves::Large, 0).ID: return 9662; case Bamboo::Bamboo(1, Bamboo::Leaves::Large, 1).ID: return 9663; case BambooSapling::BambooSapling().ID: return 9651; case Barrel::Barrel(eBlockFace::BLOCK_FACE_ZM, true).ID: return 14791; case Barrel::Barrel(eBlockFace::BLOCK_FACE_ZM, false).ID: return 14792; case Barrel::Barrel(eBlockFace::BLOCK_FACE_XP, true).ID: return 14793; case Barrel::Barrel(eBlockFace::BLOCK_FACE_XP, false).ID: return 14794; case Barrel::Barrel(eBlockFace::BLOCK_FACE_ZP, true).ID: return 14795; case Barrel::Barrel(eBlockFace::BLOCK_FACE_ZP, false).ID: return 14796; case Barrel::Barrel(eBlockFace::BLOCK_FACE_XM, true).ID: return 14797; case Barrel::Barrel(eBlockFace::BLOCK_FACE_XM, false).ID: return 14798; case Barrel::Barrel(eBlockFace::BLOCK_FACE_YP, true).ID: return 14799; case Barrel::Barrel(eBlockFace::BLOCK_FACE_YP, false).ID: return 14800; case Barrel::Barrel(eBlockFace::BLOCK_FACE_YM, true).ID: return 14801; case Barrel::Barrel(eBlockFace::BLOCK_FACE_YM, false).ID: return 14802; case Barrier::Barrier().ID: return 7536; case Basalt::Basalt(Basalt::Axis::X).ID: return 4002; case Basalt::Basalt(Basalt::Axis::Y).ID: return 4003; case Basalt::Basalt(Basalt::Axis::Z).ID: return 4004; case Beacon::Beacon().ID: return 5656; case Bedrock::Bedrock().ID: return 33; case BeeNest::BeeNest(eBlockFace::BLOCK_FACE_ZM, 0).ID: return 15776; case BeeNest::BeeNest(eBlockFace::BLOCK_FACE_ZM, 1).ID: return 15777; case BeeNest::BeeNest(eBlockFace::BLOCK_FACE_ZM, 2).ID: return 15778; case BeeNest::BeeNest(eBlockFace::BLOCK_FACE_ZM, 3).ID: return 15779; case BeeNest::BeeNest(eBlockFace::BLOCK_FACE_ZM, 4).ID: return 15780; case BeeNest::BeeNest(eBlockFace::BLOCK_FACE_ZM, 5).ID: return 15781; case BeeNest::BeeNest(eBlockFace::BLOCK_FACE_ZP, 0).ID: return 15782; case BeeNest::BeeNest(eBlockFace::BLOCK_FACE_ZP, 1).ID: return 15783; case BeeNest::BeeNest(eBlockFace::BLOCK_FACE_ZP, 2).ID: return 15784; case BeeNest::BeeNest(eBlockFace::BLOCK_FACE_ZP, 3).ID: return 15785; case BeeNest::BeeNest(eBlockFace::BLOCK_FACE_ZP, 4).ID: return 15786; case BeeNest::BeeNest(eBlockFace::BLOCK_FACE_ZP, 5).ID: return 15787; case BeeNest::BeeNest(eBlockFace::BLOCK_FACE_XM, 0).ID: return 15788; case BeeNest::BeeNest(eBlockFace::BLOCK_FACE_XM, 1).ID: return 15789; case BeeNest::BeeNest(eBlockFace::BLOCK_FACE_XM, 2).ID: return 15790; case BeeNest::BeeNest(eBlockFace::BLOCK_FACE_XM, 3).ID: return 15791; case BeeNest::BeeNest(eBlockFace::BLOCK_FACE_XM, 4).ID: return 15792; case BeeNest::BeeNest(eBlockFace::BLOCK_FACE_XM, 5).ID: return 15793; case BeeNest::BeeNest(eBlockFace::BLOCK_FACE_XP, 0).ID: return 15794; case BeeNest::BeeNest(eBlockFace::BLOCK_FACE_XP, 1).ID: return 15795; case BeeNest::BeeNest(eBlockFace::BLOCK_FACE_XP, 2).ID: return 15796; case BeeNest::BeeNest(eBlockFace::BLOCK_FACE_XP, 3).ID: return 15797; case BeeNest::BeeNest(eBlockFace::BLOCK_FACE_XP, 4).ID: return 15798; case BeeNest::BeeNest(eBlockFace::BLOCK_FACE_XP, 5).ID: return 15799; case Beehive::Beehive(eBlockFace::BLOCK_FACE_ZM, 0).ID: return 15800; case Beehive::Beehive(eBlockFace::BLOCK_FACE_ZM, 1).ID: return 15801; case Beehive::Beehive(eBlockFace::BLOCK_FACE_ZM, 2).ID: return 15802; case Beehive::Beehive(eBlockFace::BLOCK_FACE_ZM, 3).ID: return 15803; case Beehive::Beehive(eBlockFace::BLOCK_FACE_ZM, 4).ID: return 15804; case Beehive::Beehive(eBlockFace::BLOCK_FACE_ZM, 5).ID: return 15805; case Beehive::Beehive(eBlockFace::BLOCK_FACE_ZP, 0).ID: return 15806; case Beehive::Beehive(eBlockFace::BLOCK_FACE_ZP, 1).ID: return 15807; case Beehive::Beehive(eBlockFace::BLOCK_FACE_ZP, 2).ID: return 15808; case Beehive::Beehive(eBlockFace::BLOCK_FACE_ZP, 3).ID: return 15809; case Beehive::Beehive(eBlockFace::BLOCK_FACE_ZP, 4).ID: return 15810; case Beehive::Beehive(eBlockFace::BLOCK_FACE_ZP, 5).ID: return 15811; case Beehive::Beehive(eBlockFace::BLOCK_FACE_XM, 0).ID: return 15812; case Beehive::Beehive(eBlockFace::BLOCK_FACE_XM, 1).ID: return 15813; case Beehive::Beehive(eBlockFace::BLOCK_FACE_XM, 2).ID: return 15814; case Beehive::Beehive(eBlockFace::BLOCK_FACE_XM, 3).ID: return 15815; case Beehive::Beehive(eBlockFace::BLOCK_FACE_XM, 4).ID: return 15816; case Beehive::Beehive(eBlockFace::BLOCK_FACE_XM, 5).ID: return 15817; case Beehive::Beehive(eBlockFace::BLOCK_FACE_XP, 0).ID: return 15818; case Beehive::Beehive(eBlockFace::BLOCK_FACE_XP, 1).ID: return 15819; case Beehive::Beehive(eBlockFace::BLOCK_FACE_XP, 2).ID: return 15820; case Beehive::Beehive(eBlockFace::BLOCK_FACE_XP, 3).ID: return 15821; case Beehive::Beehive(eBlockFace::BLOCK_FACE_XP, 4).ID: return 15822; case Beehive::Beehive(eBlockFace::BLOCK_FACE_XP, 5).ID: return 15823; case Beetroots::Beetroots(0).ID: return 9219; case Beetroots::Beetroots(1).ID: return 9220; case Beetroots::Beetroots(2).ID: return 9221; case Beetroots::Beetroots(3).ID: return 9222; case Bell::Bell(Bell::Attachment::Floor, eBlockFace::BLOCK_FACE_ZM, true).ID: return 14854; case Bell::Bell(Bell::Attachment::Floor, eBlockFace::BLOCK_FACE_ZM, false).ID: return 14855; case Bell::Bell(Bell::Attachment::Floor, eBlockFace::BLOCK_FACE_ZP, true).ID: return 14856; case Bell::Bell(Bell::Attachment::Floor, eBlockFace::BLOCK_FACE_ZP, false).ID: return 14857; case Bell::Bell(Bell::Attachment::Floor, eBlockFace::BLOCK_FACE_XM, true).ID: return 14858; case Bell::Bell(Bell::Attachment::Floor, eBlockFace::BLOCK_FACE_XM, false).ID: return 14859; case Bell::Bell(Bell::Attachment::Floor, eBlockFace::BLOCK_FACE_XP, true).ID: return 14860; case Bell::Bell(Bell::Attachment::Floor, eBlockFace::BLOCK_FACE_XP, false).ID: return 14861; case Bell::Bell(Bell::Attachment::Ceiling, eBlockFace::BLOCK_FACE_ZM, true).ID: return 14862; case Bell::Bell(Bell::Attachment::Ceiling, eBlockFace::BLOCK_FACE_ZM, false).ID: return 14863; case Bell::Bell(Bell::Attachment::Ceiling, eBlockFace::BLOCK_FACE_ZP, true).ID: return 14864; case Bell::Bell(Bell::Attachment::Ceiling, eBlockFace::BLOCK_FACE_ZP, false).ID: return 14865; case Bell::Bell(Bell::Attachment::Ceiling, eBlockFace::BLOCK_FACE_XM, true).ID: return 14866; case Bell::Bell(Bell::Attachment::Ceiling, eBlockFace::BLOCK_FACE_XM, false).ID: return 14867; case Bell::Bell(Bell::Attachment::Ceiling, eBlockFace::BLOCK_FACE_XP, true).ID: return 14868; case Bell::Bell(Bell::Attachment::Ceiling, eBlockFace::BLOCK_FACE_XP, false).ID: return 14869; case Bell::Bell(Bell::Attachment::SingleWall, eBlockFace::BLOCK_FACE_ZM, true).ID: return 14870; case Bell::Bell(Bell::Attachment::SingleWall, eBlockFace::BLOCK_FACE_ZM, false).ID: return 14871; case Bell::Bell(Bell::Attachment::SingleWall, eBlockFace::BLOCK_FACE_ZP, true).ID: return 14872; case Bell::Bell(Bell::Attachment::SingleWall, eBlockFace::BLOCK_FACE_ZP, false).ID: return 14873; case Bell::Bell(Bell::Attachment::SingleWall, eBlockFace::BLOCK_FACE_XM, true).ID: return 14874; case Bell::Bell(Bell::Attachment::SingleWall, eBlockFace::BLOCK_FACE_XM, false).ID: return 14875; case Bell::Bell(Bell::Attachment::SingleWall, eBlockFace::BLOCK_FACE_XP, true).ID: return 14876; case Bell::Bell(Bell::Attachment::SingleWall, eBlockFace::BLOCK_FACE_XP, false).ID: return 14877; case Bell::Bell(Bell::Attachment::DoubleWall, eBlockFace::BLOCK_FACE_ZM, true).ID: return 14878; case Bell::Bell(Bell::Attachment::DoubleWall, eBlockFace::BLOCK_FACE_ZM, false).ID: return 14879; case Bell::Bell(Bell::Attachment::DoubleWall, eBlockFace::BLOCK_FACE_ZP, true).ID: return 14880; case Bell::Bell(Bell::Attachment::DoubleWall, eBlockFace::BLOCK_FACE_ZP, false).ID: return 14881; case Bell::Bell(Bell::Attachment::DoubleWall, eBlockFace::BLOCK_FACE_XM, true).ID: return 14882; case Bell::Bell(Bell::Attachment::DoubleWall, eBlockFace::BLOCK_FACE_XM, false).ID: return 14883; case Bell::Bell(Bell::Attachment::DoubleWall, eBlockFace::BLOCK_FACE_XP, true).ID: return 14884; case Bell::Bell(Bell::Attachment::DoubleWall, eBlockFace::BLOCK_FACE_XP, false).ID: return 14885; case BirchButton::BirchButton(BirchButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, true).ID: return 6394; case BirchButton::BirchButton(BirchButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, false).ID: return 6395; case BirchButton::BirchButton(BirchButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, true).ID: return 6396; case BirchButton::BirchButton(BirchButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, false).ID: return 6397; case BirchButton::BirchButton(BirchButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, true).ID: return 6398; case BirchButton::BirchButton(BirchButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, false).ID: return 6399; case BirchButton::BirchButton(BirchButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, true).ID: return 6400; case BirchButton::BirchButton(BirchButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, false).ID: return 6401; case BirchButton::BirchButton(BirchButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, true).ID: return 6402; case BirchButton::BirchButton(BirchButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, false).ID: return 6403; case BirchButton::BirchButton(BirchButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, true).ID: return 6404; case BirchButton::BirchButton(BirchButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, false).ID: return 6405; case BirchButton::BirchButton(BirchButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, true).ID: return 6406; case BirchButton::BirchButton(BirchButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, false).ID: return 6407; case BirchButton::BirchButton(BirchButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, true).ID: return 6408; case BirchButton::BirchButton(BirchButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, false).ID: return 6409; case BirchButton::BirchButton(BirchButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, true).ID: return 6410; case BirchButton::BirchButton(BirchButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, false).ID: return 6411; case BirchButton::BirchButton(BirchButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, true).ID: return 6412; case BirchButton::BirchButton(BirchButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, false).ID: return 6413; case BirchButton::BirchButton(BirchButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, true).ID: return 6414; case BirchButton::BirchButton(BirchButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, false).ID: return 6415; case BirchButton::BirchButton(BirchButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, true).ID: return 6416; case BirchButton::BirchButton(BirchButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, false).ID: return 6417; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, true, true).ID: return 8802; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, true, false).ID: return 8803; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, false, true).ID: return 8804; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, false, false).ID: return 8805; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, true, true).ID: return 8806; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, true, false).ID: return 8807; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, false, true).ID: return 8808; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, false, false).ID: return 8809; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, true, true).ID: return 8810; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, true, false).ID: return 8811; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, false, true).ID: return 8812; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, false, false).ID: return 8813; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, true, true).ID: return 8814; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, true, false).ID: return 8815; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, false, true).ID: return 8816; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, false, false).ID: return 8817; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, true, true).ID: return 8818; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, true, false).ID: return 8819; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, false, true).ID: return 8820; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, false, false).ID: return 8821; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, true, true).ID: return 8822; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, true, false).ID: return 8823; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, false, true).ID: return 8824; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, false, false).ID: return 8825; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, true, true).ID: return 8826; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, true, false).ID: return 8827; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, false, true).ID: return 8828; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, false, false).ID: return 8829; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, true, true).ID: return 8830; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, true, false).ID: return 8831; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, false, true).ID: return 8832; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, false, false).ID: return 8833; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, true, true).ID: return 8834; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, true, false).ID: return 8835; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, false, true).ID: return 8836; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, false, false).ID: return 8837; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, true, true).ID: return 8838; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, true, false).ID: return 8839; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, false, true).ID: return 8840; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, false, false).ID: return 8841; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, true, true).ID: return 8842; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, true, false).ID: return 8843; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, false, true).ID: return 8844; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, false, false).ID: return 8845; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, true, true).ID: return 8846; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, true, false).ID: return 8847; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, false, true).ID: return 8848; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, false, false).ID: return 8849; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, true, true).ID: return 8850; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, true, false).ID: return 8851; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, false, true).ID: return 8852; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, false, false).ID: return 8853; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, true, true).ID: return 8854; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, true, false).ID: return 8855; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, false, true).ID: return 8856; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, false, false).ID: return 8857; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, true, true).ID: return 8858; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, true, false).ID: return 8859; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, false, true).ID: return 8860; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Lower, BirchDoor::Hinge::Left, false, false).ID: return 8861; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, true, true).ID: return 8862; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, true, false).ID: return 8863; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, false, true).ID: return 8864; case BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, false, false).ID: return 8865; case BirchFence::BirchFence(true, true, true, true).ID: return 8612; case BirchFence::BirchFence(true, true, true, false).ID: return 8613; case BirchFence::BirchFence(true, true, false, true).ID: return 8616; case BirchFence::BirchFence(true, true, false, false).ID: return 8617; case BirchFence::BirchFence(true, false, true, true).ID: return 8620; case BirchFence::BirchFence(true, false, true, false).ID: return 8621; case BirchFence::BirchFence(true, false, false, true).ID: return 8624; case BirchFence::BirchFence(true, false, false, false).ID: return 8625; case BirchFence::BirchFence(false, true, true, true).ID: return 8628; case BirchFence::BirchFence(false, true, true, false).ID: return 8629; case BirchFence::BirchFence(false, true, false, true).ID: return 8632; case BirchFence::BirchFence(false, true, false, false).ID: return 8633; case BirchFence::BirchFence(false, false, true, true).ID: return 8636; case BirchFence::BirchFence(false, false, true, false).ID: return 8637; case BirchFence::BirchFence(false, false, false, true).ID: return 8640; case BirchFence::BirchFence(false, false, false, false).ID: return 8641; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZM, true, true, true).ID: return 8450; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZM, true, true, false).ID: return 8451; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZM, true, false, true).ID: return 8452; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZM, true, false, false).ID: return 8453; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, true).ID: return 8454; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, false).ID: return 8455; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, true).ID: return 8456; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, false).ID: return 8457; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZP, true, true, true).ID: return 8458; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZP, true, true, false).ID: return 8459; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZP, true, false, true).ID: return 8460; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZP, true, false, false).ID: return 8461; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, true).ID: return 8462; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, false).ID: return 8463; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, true).ID: return 8464; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, false).ID: return 8465; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XM, true, true, true).ID: return 8466; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XM, true, true, false).ID: return 8467; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XM, true, false, true).ID: return 8468; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XM, true, false, false).ID: return 8469; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, true).ID: return 8470; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, false).ID: return 8471; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, true).ID: return 8472; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, false).ID: return 8473; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XP, true, true, true).ID: return 8474; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XP, true, true, false).ID: return 8475; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XP, true, false, true).ID: return 8476; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XP, true, false, false).ID: return 8477; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, true).ID: return 8478; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, false).ID: return 8479; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, true).ID: return 8480; case BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, false).ID: return 8481; case BirchLeaves::BirchLeaves(1, true).ID: return 173; case BirchLeaves::BirchLeaves(1, false).ID: return 174; case BirchLeaves::BirchLeaves(2, true).ID: return 175; case BirchLeaves::BirchLeaves(2, false).ID: return 176; case BirchLeaves::BirchLeaves(3, true).ID: return 177; case BirchLeaves::BirchLeaves(3, false).ID: return 178; case BirchLeaves::BirchLeaves(4, true).ID: return 179; case BirchLeaves::BirchLeaves(4, false).ID: return 180; case BirchLeaves::BirchLeaves(5, true).ID: return 181; case BirchLeaves::BirchLeaves(5, false).ID: return 182; case BirchLeaves::BirchLeaves(6, true).ID: return 183; case BirchLeaves::BirchLeaves(6, false).ID: return 184; case BirchLeaves::BirchLeaves(7, true).ID: return 185; case BirchLeaves::BirchLeaves(7, false).ID: return 186; case BirchLog::BirchLog(BirchLog::Axis::X).ID: return 79; case BirchLog::BirchLog(BirchLog::Axis::Y).ID: return 80; case BirchLog::BirchLog(BirchLog::Axis::Z).ID: return 81; case BirchPlanks::BirchPlanks().ID: return 17; case BirchPressurePlate::BirchPressurePlate(true).ID: return 3877; case BirchPressurePlate::BirchPressurePlate(false).ID: return 3878; case BirchSapling::BirchSapling(0).ID: return 25; case BirchSapling::BirchSapling(1).ID: return 26; case BirchSign::BirchSign(0).ID: return 3446; case BirchSign::BirchSign(1).ID: return 3448; case BirchSign::BirchSign(2).ID: return 3450; case BirchSign::BirchSign(3).ID: return 3452; case BirchSign::BirchSign(4).ID: return 3454; case BirchSign::BirchSign(5).ID: return 3456; case BirchSign::BirchSign(6).ID: return 3458; case BirchSign::BirchSign(7).ID: return 3460; case BirchSign::BirchSign(8).ID: return 3462; case BirchSign::BirchSign(9).ID: return 3464; case BirchSign::BirchSign(10).ID: return 3466; case BirchSign::BirchSign(11).ID: return 3468; case BirchSign::BirchSign(12).ID: return 3470; case BirchSign::BirchSign(13).ID: return 3472; case BirchSign::BirchSign(14).ID: return 3474; case BirchSign::BirchSign(15).ID: return 3476; case BirchSlab::BirchSlab(BirchSlab::Type::Top).ID: return 8313; case BirchSlab::BirchSlab(BirchSlab::Type::Bottom).ID: return 8315; case BirchSlab::BirchSlab(BirchSlab::Type::Double).ID: return 8317; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZM, BirchStairs::Half::Top, BirchStairs::Shape::Straight).ID: return 5485; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZM, BirchStairs::Half::Top, BirchStairs::Shape::InnerLeft).ID: return 5487; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZM, BirchStairs::Half::Top, BirchStairs::Shape::InnerRight).ID: return 5489; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZM, BirchStairs::Half::Top, BirchStairs::Shape::OuterLeft).ID: return 5491; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZM, BirchStairs::Half::Top, BirchStairs::Shape::OuterRight).ID: return 5493; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZM, BirchStairs::Half::Bottom, BirchStairs::Shape::Straight).ID: return 5495; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZM, BirchStairs::Half::Bottom, BirchStairs::Shape::InnerLeft).ID: return 5497; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZM, BirchStairs::Half::Bottom, BirchStairs::Shape::InnerRight).ID: return 5499; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZM, BirchStairs::Half::Bottom, BirchStairs::Shape::OuterLeft).ID: return 5501; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZM, BirchStairs::Half::Bottom, BirchStairs::Shape::OuterRight).ID: return 5503; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZP, BirchStairs::Half::Top, BirchStairs::Shape::Straight).ID: return 5505; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZP, BirchStairs::Half::Top, BirchStairs::Shape::InnerLeft).ID: return 5507; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZP, BirchStairs::Half::Top, BirchStairs::Shape::InnerRight).ID: return 5509; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZP, BirchStairs::Half::Top, BirchStairs::Shape::OuterLeft).ID: return 5511; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZP, BirchStairs::Half::Top, BirchStairs::Shape::OuterRight).ID: return 5513; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZP, BirchStairs::Half::Bottom, BirchStairs::Shape::Straight).ID: return 5515; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZP, BirchStairs::Half::Bottom, BirchStairs::Shape::InnerLeft).ID: return 5517; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZP, BirchStairs::Half::Bottom, BirchStairs::Shape::InnerRight).ID: return 5519; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZP, BirchStairs::Half::Bottom, BirchStairs::Shape::OuterLeft).ID: return 5521; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZP, BirchStairs::Half::Bottom, BirchStairs::Shape::OuterRight).ID: return 5523; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XM, BirchStairs::Half::Top, BirchStairs::Shape::Straight).ID: return 5525; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XM, BirchStairs::Half::Top, BirchStairs::Shape::InnerLeft).ID: return 5527; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XM, BirchStairs::Half::Top, BirchStairs::Shape::InnerRight).ID: return 5529; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XM, BirchStairs::Half::Top, BirchStairs::Shape::OuterLeft).ID: return 5531; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XM, BirchStairs::Half::Top, BirchStairs::Shape::OuterRight).ID: return 5533; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XM, BirchStairs::Half::Bottom, BirchStairs::Shape::Straight).ID: return 5535; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XM, BirchStairs::Half::Bottom, BirchStairs::Shape::InnerLeft).ID: return 5537; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XM, BirchStairs::Half::Bottom, BirchStairs::Shape::InnerRight).ID: return 5539; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XM, BirchStairs::Half::Bottom, BirchStairs::Shape::OuterLeft).ID: return 5541; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XM, BirchStairs::Half::Bottom, BirchStairs::Shape::OuterRight).ID: return 5543; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XP, BirchStairs::Half::Top, BirchStairs::Shape::Straight).ID: return 5545; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XP, BirchStairs::Half::Top, BirchStairs::Shape::InnerLeft).ID: return 5547; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XP, BirchStairs::Half::Top, BirchStairs::Shape::InnerRight).ID: return 5549; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XP, BirchStairs::Half::Top, BirchStairs::Shape::OuterLeft).ID: return 5551; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XP, BirchStairs::Half::Top, BirchStairs::Shape::OuterRight).ID: return 5553; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XP, BirchStairs::Half::Bottom, BirchStairs::Shape::Straight).ID: return 5555; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XP, BirchStairs::Half::Bottom, BirchStairs::Shape::InnerLeft).ID: return 5557; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XP, BirchStairs::Half::Bottom, BirchStairs::Shape::InnerRight).ID: return 5559; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XP, BirchStairs::Half::Bottom, BirchStairs::Shape::OuterLeft).ID: return 5561; case BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XP, BirchStairs::Half::Bottom, BirchStairs::Shape::OuterRight).ID: return 5563; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZM, BirchTrapdoor::Half::Top, true, true).ID: return 4240; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZM, BirchTrapdoor::Half::Top, true, false).ID: return 4242; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZM, BirchTrapdoor::Half::Top, false, true).ID: return 4244; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZM, BirchTrapdoor::Half::Top, false, false).ID: return 4246; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZM, BirchTrapdoor::Half::Bottom, true, true).ID: return 4248; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZM, BirchTrapdoor::Half::Bottom, true, false).ID: return 4250; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZM, BirchTrapdoor::Half::Bottom, false, true).ID: return 4252; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZM, BirchTrapdoor::Half::Bottom, false, false).ID: return 4254; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZP, BirchTrapdoor::Half::Top, true, true).ID: return 4256; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZP, BirchTrapdoor::Half::Top, true, false).ID: return 4258; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZP, BirchTrapdoor::Half::Top, false, true).ID: return 4260; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZP, BirchTrapdoor::Half::Top, false, false).ID: return 4262; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZP, BirchTrapdoor::Half::Bottom, true, true).ID: return 4264; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZP, BirchTrapdoor::Half::Bottom, true, false).ID: return 4266; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZP, BirchTrapdoor::Half::Bottom, false, true).ID: return 4268; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_ZP, BirchTrapdoor::Half::Bottom, false, false).ID: return 4270; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XM, BirchTrapdoor::Half::Top, true, true).ID: return 4272; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XM, BirchTrapdoor::Half::Top, true, false).ID: return 4274; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XM, BirchTrapdoor::Half::Top, false, true).ID: return 4276; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XM, BirchTrapdoor::Half::Top, false, false).ID: return 4278; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XM, BirchTrapdoor::Half::Bottom, true, true).ID: return 4280; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XM, BirchTrapdoor::Half::Bottom, true, false).ID: return 4282; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XM, BirchTrapdoor::Half::Bottom, false, true).ID: return 4284; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XM, BirchTrapdoor::Half::Bottom, false, false).ID: return 4286; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XP, BirchTrapdoor::Half::Top, true, true).ID: return 4288; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XP, BirchTrapdoor::Half::Top, true, false).ID: return 4290; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XP, BirchTrapdoor::Half::Top, false, true).ID: return 4292; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XP, BirchTrapdoor::Half::Top, false, false).ID: return 4294; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XP, BirchTrapdoor::Half::Bottom, true, true).ID: return 4296; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XP, BirchTrapdoor::Half::Bottom, true, false).ID: return 4298; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XP, BirchTrapdoor::Half::Bottom, false, true).ID: return 4300; case BirchTrapdoor::BirchTrapdoor(eBlockFace::BLOCK_FACE_XP, BirchTrapdoor::Half::Bottom, false, false).ID: return 4302; case BirchWallSign::BirchWallSign(eBlockFace::BLOCK_FACE_ZM).ID: return 3752; case BirchWallSign::BirchWallSign(eBlockFace::BLOCK_FACE_ZP).ID: return 3754; case BirchWallSign::BirchWallSign(eBlockFace::BLOCK_FACE_XM).ID: return 3756; case BirchWallSign::BirchWallSign(eBlockFace::BLOCK_FACE_XP).ID: return 3758; case BirchWood::BirchWood(BirchWood::Axis::X).ID: return 115; case BirchWood::BirchWood(BirchWood::Axis::Y).ID: return 116; case BirchWood::BirchWood(BirchWood::Axis::Z).ID: return 117; case BlackBanner::BlackBanner(0).ID: return 8137; case BlackBanner::BlackBanner(1).ID: return 8138; case BlackBanner::BlackBanner(2).ID: return 8139; case BlackBanner::BlackBanner(3).ID: return 8140; case BlackBanner::BlackBanner(4).ID: return 8141; case BlackBanner::BlackBanner(5).ID: return 8142; case BlackBanner::BlackBanner(6).ID: return 8143; case BlackBanner::BlackBanner(7).ID: return 8144; case BlackBanner::BlackBanner(8).ID: return 8145; case BlackBanner::BlackBanner(9).ID: return 8146; case BlackBanner::BlackBanner(10).ID: return 8147; case BlackBanner::BlackBanner(11).ID: return 8148; case BlackBanner::BlackBanner(12).ID: return 8149; case BlackBanner::BlackBanner(13).ID: return 8150; case BlackBanner::BlackBanner(14).ID: return 8151; case BlackBanner::BlackBanner(15).ID: return 8152; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_ZM, true, BlackBed::Part::Head).ID: return 1289; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_ZM, true, BlackBed::Part::Foot).ID: return 1290; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_ZM, false, BlackBed::Part::Head).ID: return 1291; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_ZM, false, BlackBed::Part::Foot).ID: return 1292; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_ZP, true, BlackBed::Part::Head).ID: return 1293; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_ZP, true, BlackBed::Part::Foot).ID: return 1294; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_ZP, false, BlackBed::Part::Head).ID: return 1295; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_ZP, false, BlackBed::Part::Foot).ID: return 1296; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_XM, true, BlackBed::Part::Head).ID: return 1297; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_XM, true, BlackBed::Part::Foot).ID: return 1298; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_XM, false, BlackBed::Part::Head).ID: return 1299; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_XM, false, BlackBed::Part::Foot).ID: return 1300; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_XP, true, BlackBed::Part::Head).ID: return 1301; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_XP, true, BlackBed::Part::Foot).ID: return 1302; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_XP, false, BlackBed::Part::Head).ID: return 1303; case BlackBed::BlackBed(eBlockFace::BLOCK_FACE_XP, false, BlackBed::Part::Foot).ID: return 1304; case BlackCarpet::BlackCarpet().ID: return 7881; case BlackConcrete::BlackConcrete().ID: return 9453; case BlackConcretePowder::BlackConcretePowder().ID: return 9469; case BlackGlazedTerracotta::BlackGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 9434; case BlackGlazedTerracotta::BlackGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 9435; case BlackGlazedTerracotta::BlackGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 9436; case BlackGlazedTerracotta::BlackGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 9437; case BlackShulkerBox::BlackShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 9368; case BlackShulkerBox::BlackShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 9369; case BlackShulkerBox::BlackShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 9370; case BlackShulkerBox::BlackShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 9371; case BlackShulkerBox::BlackShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 9372; case BlackShulkerBox::BlackShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 9373; case BlackStainedGlass::BlackStainedGlass().ID: return 4110; case BlackStainedGlassPane::BlackStainedGlassPane(true, true, true, true).ID: return 7345; case BlackStainedGlassPane::BlackStainedGlassPane(true, true, true, false).ID: return 7346; case BlackStainedGlassPane::BlackStainedGlassPane(true, true, false, true).ID: return 7349; case BlackStainedGlassPane::BlackStainedGlassPane(true, true, false, false).ID: return 7350; case BlackStainedGlassPane::BlackStainedGlassPane(true, false, true, true).ID: return 7353; case BlackStainedGlassPane::BlackStainedGlassPane(true, false, true, false).ID: return 7354; case BlackStainedGlassPane::BlackStainedGlassPane(true, false, false, true).ID: return 7357; case BlackStainedGlassPane::BlackStainedGlassPane(true, false, false, false).ID: return 7358; case BlackStainedGlassPane::BlackStainedGlassPane(false, true, true, true).ID: return 7361; case BlackStainedGlassPane::BlackStainedGlassPane(false, true, true, false).ID: return 7362; case BlackStainedGlassPane::BlackStainedGlassPane(false, true, false, true).ID: return 7365; case BlackStainedGlassPane::BlackStainedGlassPane(false, true, false, false).ID: return 7366; case BlackStainedGlassPane::BlackStainedGlassPane(false, false, true, true).ID: return 7369; case BlackStainedGlassPane::BlackStainedGlassPane(false, false, true, false).ID: return 7370; case BlackStainedGlassPane::BlackStainedGlassPane(false, false, false, true).ID: return 7373; case BlackStainedGlassPane::BlackStainedGlassPane(false, false, false, false).ID: return 7374; case BlackTerracotta::BlackTerracotta().ID: return 6862; case BlackWallBanner::BlackWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 8213; case BlackWallBanner::BlackWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 8214; case BlackWallBanner::BlackWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 8215; case BlackWallBanner::BlackWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 8216; case BlackWool::BlackWool().ID: return 1399; case Blackstone::Blackstone().ID: return 15839; case BlackstoneSlab::BlackstoneSlab(BlackstoneSlab::Type::Top).ID: return 16245; case BlackstoneSlab::BlackstoneSlab(BlackstoneSlab::Type::Bottom).ID: return 16247; case BlackstoneSlab::BlackstoneSlab(BlackstoneSlab::Type::Double).ID: return 16249; case BlackstoneStairs::BlackstoneStairs(eBlockFace::BLOCK_FACE_ZM, BlackstoneStairs::Half::Top, BlackstoneStairs::Shape::Straight).ID: return 15841; case BlackstoneStairs::BlackstoneStairs(eBlockFace::BLOCK_FACE_ZM, BlackstoneStairs::Half::Top, BlackstoneStairs::Shape::InnerLeft).ID: return 15843; case BlackstoneStairs::BlackstoneStairs(eBlockFace::BLOCK_FACE_ZM, BlackstoneStairs::Half::Top, BlackstoneStairs::Shape::InnerRight).ID: return 15845; case BlackstoneStairs::BlackstoneStairs(eBlockFace::BLOCK_FACE_ZM, BlackstoneStairs::Half::Top, BlackstoneStairs::Shape::OuterLeft).ID: return 15847; case BlackstoneStairs::BlackstoneStairs(eBlockFace::BLOCK_FACE_ZM, BlackstoneStairs::Half::Top, BlackstoneStairs::Shape::OuterRight).ID: return 15849; case BlackstoneStairs::BlackstoneStairs(eBlockFace::BLOCK_FACE_ZM, BlackstoneStairs::Half::Bottom, BlackstoneStairs::Shape::Straight).ID: return 15851; case BlackstoneStairs::BlackstoneStairs(eBlockFace::BLOCK_FACE_ZM, BlackstoneStairs::Half::Bottom, BlackstoneStairs::Shape::InnerLeft).ID: return 15853; case BlackstoneStairs::BlackstoneStairs(eBlockFace::BLOCK_FACE_ZM, BlackstoneStairs::Half::Bottom, BlackstoneStairs::Shape::InnerRight).ID: return 15855; case BlackstoneStairs::BlackstoneStairs(eBlockFace::BLOCK_FACE_ZM, BlackstoneStairs::Half::Bottom, BlackstoneStairs::Shape::OuterLeft).ID: return 15857; case BlackstoneStairs::BlackstoneStairs(eBlockFace::BLOCK_FACE_ZM, BlackstoneStairs::Half::Bottom, BlackstoneStairs::Shape::OuterRight).ID: return 15859; case BlackstoneStairs::BlackstoneStairs(eBlockFace::BLOCK_FACE_ZP, BlackstoneStairs::Half::Top, BlackstoneStairs::Shape::Straight).ID: return 15861; case BlackstoneStairs::BlackstoneStairs(eBlockFace::BLOCK_FACE_ZP, BlackstoneStairs::Half::Top, BlackstoneStairs::Shape::InnerLeft).ID: return 15863; case BlackstoneStairs::BlackstoneStairs(eBlockFace::BLOCK_FACE_ZP, BlackstoneStairs::Half::Top, BlackstoneStairs::Shape::InnerRight).ID: return 15865; case BlackstoneStairs::BlackstoneStairs(eBlockFace::BLOCK_FACE_ZP, BlackstoneStairs::Half::Top, BlackstoneStairs::Shape::OuterLeft).ID: return 15867; case BlackstoneStairs::BlackstoneStairs(eBlockFace::BLOCK_FACE_ZP, BlackstoneStairs::Half::Top, BlackstoneStairs::Shape::OuterRight).ID: return 15869; case BlackstoneStairs::BlackstoneStairs(eBlockFace::BLOCK_FACE_ZP, BlackstoneStairs::Half::Bottom, BlackstoneStairs::Shape::Straight).ID: return 15871; case BlackstoneStairs::BlackstoneStairs(eBlockFace::BLOCK_FACE_ZP, BlackstoneStairs::Half::Bottom, BlackstoneStairs::Shape::InnerLeft).ID: return 15873; case BlackstoneStairs::BlackstoneStairs(eBlockFace::BLOCK_FACE_ZP, BlackstoneStairs::Half::Bottom, BlackstoneStairs::Shape::InnerRight).ID: return 15875; case BlackstoneStairs::BlackstoneStairs(eBlockFace::BLOCK_FACE_ZP, BlackstoneStairs::Half::Bottom, BlackstoneStairs::Shape::OuterLeft).ID: return 15877; case BlackstoneStairs::BlackstoneStairs(eBlockFace::BLOCK_FACE_ZP, BlackstoneStairs::Half::Bottom, BlackstoneStairs::Shape::OuterRight).ID: return 15879; case BlackstoneStairs::BlackstoneStairs(eBlockFace::BLOCK_FACE_XM, BlackstoneStairs::Half::Top, BlackstoneStairs::Shape::Straight).ID: return 15881; case BlackstoneStairs::BlackstoneStairs(eBlockFace::BLOCK_FACE_XM, BlackstoneStairs::Half::Top, BlackstoneStairs::Shape::InnerLeft).ID: return 15883; case BlackstoneStairs::BlackstoneStairs(eBlockFace::BLOCK_FACE_XM, BlackstoneStairs::Half::Top, BlackstoneStairs::Shape::InnerRight).ID: return 15885; case BlackstoneStairs::BlackstoneStairs(eBlockFace::BLOCK_FACE_XM, BlackstoneStairs::Half::Top, BlackstoneStairs::Shape::OuterLeft).ID: return 15887; case BlackstoneStairs::BlackstoneStairs(eBlockFace::BLOCK_FACE_XM, BlackstoneStairs::Half::Top, BlackstoneStairs::Shape::OuterRight).ID: return 15889; case BlackstoneStairs::BlackstoneStairs(eBlockFace::BLOCK_FACE_XM, BlackstoneStairs::Half::Bottom, BlackstoneStairs::Shape::Straight).ID: return 15891; case BlackstoneStairs::BlackstoneStairs(eBlockFace::BLOCK_FACE_XM, BlackstoneStairs::Half::Bottom, BlackstoneStairs::Shape::InnerLeft).ID: return 15893; case BlackstoneStairs::BlackstoneStairs(eBlockFace::BLOCK_FACE_XM, BlackstoneStairs::Half::Bottom, BlackstoneStairs::Shape::InnerRight).ID: return 15895; case BlackstoneStairs::BlackstoneStairs(eBlockFace::BLOCK_FACE_XM, BlackstoneStairs::Half::Bottom, BlackstoneStairs::Shape::OuterLeft).ID: return 15897; case BlackstoneStairs::BlackstoneStairs(eBlockFace::BLOCK_FACE_XM, BlackstoneStairs::Half::Bottom, BlackstoneStairs::Shape::OuterRight).ID: return 15899; case BlackstoneStairs::BlackstoneStairs(eBlockFace::BLOCK_FACE_XP, BlackstoneStairs::Half::Top, BlackstoneStairs::Shape::Straight).ID: return 15901; case BlackstoneStairs::BlackstoneStairs(eBlockFace::BLOCK_FACE_XP, BlackstoneStairs::Half::Top, BlackstoneStairs::Shape::InnerLeft).ID: return 15903; case BlackstoneStairs::BlackstoneStairs(eBlockFace::BLOCK_FACE_XP, BlackstoneStairs::Half::Top, BlackstoneStairs::Shape::InnerRight).ID: return 15905; case BlackstoneStairs::BlackstoneStairs(eBlockFace::BLOCK_FACE_XP, BlackstoneStairs::Half::Top, BlackstoneStairs::Shape::OuterLeft).ID: return 15907; case BlackstoneStairs::BlackstoneStairs(eBlockFace::BLOCK_FACE_XP, BlackstoneStairs::Half::Top, BlackstoneStairs::Shape::OuterRight).ID: return 15909; case BlackstoneStairs::BlackstoneStairs(eBlockFace::BLOCK_FACE_XP, BlackstoneStairs::Half::Bottom, BlackstoneStairs::Shape::Straight).ID: return 15911; case BlackstoneStairs::BlackstoneStairs(eBlockFace::BLOCK_FACE_XP, BlackstoneStairs::Half::Bottom, BlackstoneStairs::Shape::InnerLeft).ID: return 15913; case BlackstoneStairs::BlackstoneStairs(eBlockFace::BLOCK_FACE_XP, BlackstoneStairs::Half::Bottom, BlackstoneStairs::Shape::InnerRight).ID: return 15915; case BlackstoneStairs::BlackstoneStairs(eBlockFace::BLOCK_FACE_XP, BlackstoneStairs::Half::Bottom, BlackstoneStairs::Shape::OuterLeft).ID: return 15917; case BlackstoneStairs::BlackstoneStairs(eBlockFace::BLOCK_FACE_XP, BlackstoneStairs::Half::Bottom, BlackstoneStairs::Shape::OuterRight).ID: return 15919; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::None, BlackstoneWall::North::None, BlackstoneWall::South::None, true, BlackstoneWall::West::None).ID: return 15923; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::None, BlackstoneWall::North::None, BlackstoneWall::South::None, true, BlackstoneWall::West::Low).ID: return 15924; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::None, BlackstoneWall::North::None, BlackstoneWall::South::None, true, BlackstoneWall::West::Tall).ID: return 15925; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::None, BlackstoneWall::North::None, BlackstoneWall::South::None, false, BlackstoneWall::West::None).ID: return 15929; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::None, BlackstoneWall::North::None, BlackstoneWall::South::None, false, BlackstoneWall::West::Low).ID: return 15930; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::None, BlackstoneWall::North::None, BlackstoneWall::South::None, false, BlackstoneWall::West::Tall).ID: return 15931; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::None, BlackstoneWall::North::None, BlackstoneWall::South::Low, true, BlackstoneWall::West::None).ID: return 15935; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::None, BlackstoneWall::North::None, BlackstoneWall::South::Low, true, BlackstoneWall::West::Low).ID: return 15936; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::None, BlackstoneWall::North::None, BlackstoneWall::South::Low, true, BlackstoneWall::West::Tall).ID: return 15937; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::None, BlackstoneWall::North::None, BlackstoneWall::South::Low, false, BlackstoneWall::West::None).ID: return 15941; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::None, BlackstoneWall::North::None, BlackstoneWall::South::Low, false, BlackstoneWall::West::Low).ID: return 15942; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::None, BlackstoneWall::North::None, BlackstoneWall::South::Low, false, BlackstoneWall::West::Tall).ID: return 15943; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::None, BlackstoneWall::North::None, BlackstoneWall::South::Tall, true, BlackstoneWall::West::None).ID: return 15947; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::None, BlackstoneWall::North::None, BlackstoneWall::South::Tall, true, BlackstoneWall::West::Low).ID: return 15948; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::None, BlackstoneWall::North::None, BlackstoneWall::South::Tall, true, BlackstoneWall::West::Tall).ID: return 15949; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::None, BlackstoneWall::North::None, BlackstoneWall::South::Tall, false, BlackstoneWall::West::None).ID: return 15953; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::None, BlackstoneWall::North::None, BlackstoneWall::South::Tall, false, BlackstoneWall::West::Low).ID: return 15954; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::None, BlackstoneWall::North::None, BlackstoneWall::South::Tall, false, BlackstoneWall::West::Tall).ID: return 15955; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::None, BlackstoneWall::North::Low, BlackstoneWall::South::None, true, BlackstoneWall::West::None).ID: return 15959; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::None, BlackstoneWall::North::Low, BlackstoneWall::South::None, true, BlackstoneWall::West::Low).ID: return 15960; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::None, BlackstoneWall::North::Low, BlackstoneWall::South::None, true, BlackstoneWall::West::Tall).ID: return 15961; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::None, BlackstoneWall::North::Low, BlackstoneWall::South::None, false, BlackstoneWall::West::None).ID: return 15965; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::None, BlackstoneWall::North::Low, BlackstoneWall::South::None, false, BlackstoneWall::West::Low).ID: return 15966; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::None, BlackstoneWall::North::Low, BlackstoneWall::South::None, false, BlackstoneWall::West::Tall).ID: return 15967; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::None, BlackstoneWall::North::Low, BlackstoneWall::South::Low, true, BlackstoneWall::West::None).ID: return 15971; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::None, BlackstoneWall::North::Low, BlackstoneWall::South::Low, true, BlackstoneWall::West::Low).ID: return 15972; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::None, BlackstoneWall::North::Low, BlackstoneWall::South::Low, true, BlackstoneWall::West::Tall).ID: return 15973; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::None, BlackstoneWall::North::Low, BlackstoneWall::South::Low, false, BlackstoneWall::West::None).ID: return 15977; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::None, BlackstoneWall::North::Low, BlackstoneWall::South::Low, false, BlackstoneWall::West::Low).ID: return 15978; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::None, BlackstoneWall::North::Low, BlackstoneWall::South::Low, false, BlackstoneWall::West::Tall).ID: return 15979; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::None, BlackstoneWall::North::Low, BlackstoneWall::South::Tall, true, BlackstoneWall::West::None).ID: return 15983; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::None, BlackstoneWall::North::Low, BlackstoneWall::South::Tall, true, BlackstoneWall::West::Low).ID: return 15984; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::None, BlackstoneWall::North::Low, BlackstoneWall::South::Tall, true, BlackstoneWall::West::Tall).ID: return 15985; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::None, BlackstoneWall::North::Low, BlackstoneWall::South::Tall, false, BlackstoneWall::West::None).ID: return 15989; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::None, BlackstoneWall::North::Low, BlackstoneWall::South::Tall, false, BlackstoneWall::West::Low).ID: return 15990; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::None, BlackstoneWall::North::Low, BlackstoneWall::South::Tall, false, BlackstoneWall::West::Tall).ID: return 15991; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::None, BlackstoneWall::North::Tall, BlackstoneWall::South::None, true, BlackstoneWall::West::None).ID: return 15995; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::None, BlackstoneWall::North::Tall, BlackstoneWall::South::None, true, BlackstoneWall::West::Low).ID: return 15996; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::None, BlackstoneWall::North::Tall, BlackstoneWall::South::None, true, BlackstoneWall::West::Tall).ID: return 15997; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::None, BlackstoneWall::North::Tall, BlackstoneWall::South::None, false, BlackstoneWall::West::None).ID: return 16001; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::None, BlackstoneWall::North::Tall, BlackstoneWall::South::None, false, BlackstoneWall::West::Low).ID: return 16002; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::None, BlackstoneWall::North::Tall, BlackstoneWall::South::None, false, BlackstoneWall::West::Tall).ID: return 16003; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::None, BlackstoneWall::North::Tall, BlackstoneWall::South::Low, true, BlackstoneWall::West::None).ID: return 16007; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::None, BlackstoneWall::North::Tall, BlackstoneWall::South::Low, true, BlackstoneWall::West::Low).ID: return 16008; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::None, BlackstoneWall::North::Tall, BlackstoneWall::South::Low, true, BlackstoneWall::West::Tall).ID: return 16009; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::None, BlackstoneWall::North::Tall, BlackstoneWall::South::Low, false, BlackstoneWall::West::None).ID: return 16013; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::None, BlackstoneWall::North::Tall, BlackstoneWall::South::Low, false, BlackstoneWall::West::Low).ID: return 16014; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::None, BlackstoneWall::North::Tall, BlackstoneWall::South::Low, false, BlackstoneWall::West::Tall).ID: return 16015; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::None, BlackstoneWall::North::Tall, BlackstoneWall::South::Tall, true, BlackstoneWall::West::None).ID: return 16019; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::None, BlackstoneWall::North::Tall, BlackstoneWall::South::Tall, true, BlackstoneWall::West::Low).ID: return 16020; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::None, BlackstoneWall::North::Tall, BlackstoneWall::South::Tall, true, BlackstoneWall::West::Tall).ID: return 16021; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::None, BlackstoneWall::North::Tall, BlackstoneWall::South::Tall, false, BlackstoneWall::West::None).ID: return 16025; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::None, BlackstoneWall::North::Tall, BlackstoneWall::South::Tall, false, BlackstoneWall::West::Low).ID: return 16026; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::None, BlackstoneWall::North::Tall, BlackstoneWall::South::Tall, false, BlackstoneWall::West::Tall).ID: return 16027; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Low, BlackstoneWall::North::None, BlackstoneWall::South::None, true, BlackstoneWall::West::None).ID: return 16031; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Low, BlackstoneWall::North::None, BlackstoneWall::South::None, true, BlackstoneWall::West::Low).ID: return 16032; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Low, BlackstoneWall::North::None, BlackstoneWall::South::None, true, BlackstoneWall::West::Tall).ID: return 16033; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Low, BlackstoneWall::North::None, BlackstoneWall::South::None, false, BlackstoneWall::West::None).ID: return 16037; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Low, BlackstoneWall::North::None, BlackstoneWall::South::None, false, BlackstoneWall::West::Low).ID: return 16038; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Low, BlackstoneWall::North::None, BlackstoneWall::South::None, false, BlackstoneWall::West::Tall).ID: return 16039; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Low, BlackstoneWall::North::None, BlackstoneWall::South::Low, true, BlackstoneWall::West::None).ID: return 16043; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Low, BlackstoneWall::North::None, BlackstoneWall::South::Low, true, BlackstoneWall::West::Low).ID: return 16044; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Low, BlackstoneWall::North::None, BlackstoneWall::South::Low, true, BlackstoneWall::West::Tall).ID: return 16045; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Low, BlackstoneWall::North::None, BlackstoneWall::South::Low, false, BlackstoneWall::West::None).ID: return 16049; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Low, BlackstoneWall::North::None, BlackstoneWall::South::Low, false, BlackstoneWall::West::Low).ID: return 16050; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Low, BlackstoneWall::North::None, BlackstoneWall::South::Low, false, BlackstoneWall::West::Tall).ID: return 16051; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Low, BlackstoneWall::North::None, BlackstoneWall::South::Tall, true, BlackstoneWall::West::None).ID: return 16055; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Low, BlackstoneWall::North::None, BlackstoneWall::South::Tall, true, BlackstoneWall::West::Low).ID: return 16056; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Low, BlackstoneWall::North::None, BlackstoneWall::South::Tall, true, BlackstoneWall::West::Tall).ID: return 16057; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Low, BlackstoneWall::North::None, BlackstoneWall::South::Tall, false, BlackstoneWall::West::None).ID: return 16061; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Low, BlackstoneWall::North::None, BlackstoneWall::South::Tall, false, BlackstoneWall::West::Low).ID: return 16062; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Low, BlackstoneWall::North::None, BlackstoneWall::South::Tall, false, BlackstoneWall::West::Tall).ID: return 16063; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Low, BlackstoneWall::North::Low, BlackstoneWall::South::None, true, BlackstoneWall::West::None).ID: return 16067; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Low, BlackstoneWall::North::Low, BlackstoneWall::South::None, true, BlackstoneWall::West::Low).ID: return 16068; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Low, BlackstoneWall::North::Low, BlackstoneWall::South::None, true, BlackstoneWall::West::Tall).ID: return 16069; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Low, BlackstoneWall::North::Low, BlackstoneWall::South::None, false, BlackstoneWall::West::None).ID: return 16073; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Low, BlackstoneWall::North::Low, BlackstoneWall::South::None, false, BlackstoneWall::West::Low).ID: return 16074; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Low, BlackstoneWall::North::Low, BlackstoneWall::South::None, false, BlackstoneWall::West::Tall).ID: return 16075; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Low, BlackstoneWall::North::Low, BlackstoneWall::South::Low, true, BlackstoneWall::West::None).ID: return 16079; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Low, BlackstoneWall::North::Low, BlackstoneWall::South::Low, true, BlackstoneWall::West::Low).ID: return 16080; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Low, BlackstoneWall::North::Low, BlackstoneWall::South::Low, true, BlackstoneWall::West::Tall).ID: return 16081; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Low, BlackstoneWall::North::Low, BlackstoneWall::South::Low, false, BlackstoneWall::West::None).ID: return 16085; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Low, BlackstoneWall::North::Low, BlackstoneWall::South::Low, false, BlackstoneWall::West::Low).ID: return 16086; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Low, BlackstoneWall::North::Low, BlackstoneWall::South::Low, false, BlackstoneWall::West::Tall).ID: return 16087; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Low, BlackstoneWall::North::Low, BlackstoneWall::South::Tall, true, BlackstoneWall::West::None).ID: return 16091; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Low, BlackstoneWall::North::Low, BlackstoneWall::South::Tall, true, BlackstoneWall::West::Low).ID: return 16092; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Low, BlackstoneWall::North::Low, BlackstoneWall::South::Tall, true, BlackstoneWall::West::Tall).ID: return 16093; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Low, BlackstoneWall::North::Low, BlackstoneWall::South::Tall, false, BlackstoneWall::West::None).ID: return 16097; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Low, BlackstoneWall::North::Low, BlackstoneWall::South::Tall, false, BlackstoneWall::West::Low).ID: return 16098; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Low, BlackstoneWall::North::Low, BlackstoneWall::South::Tall, false, BlackstoneWall::West::Tall).ID: return 16099; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Low, BlackstoneWall::North::Tall, BlackstoneWall::South::None, true, BlackstoneWall::West::None).ID: return 16103; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Low, BlackstoneWall::North::Tall, BlackstoneWall::South::None, true, BlackstoneWall::West::Low).ID: return 16104; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Low, BlackstoneWall::North::Tall, BlackstoneWall::South::None, true, BlackstoneWall::West::Tall).ID: return 16105; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Low, BlackstoneWall::North::Tall, BlackstoneWall::South::None, false, BlackstoneWall::West::None).ID: return 16109; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Low, BlackstoneWall::North::Tall, BlackstoneWall::South::None, false, BlackstoneWall::West::Low).ID: return 16110; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Low, BlackstoneWall::North::Tall, BlackstoneWall::South::None, false, BlackstoneWall::West::Tall).ID: return 16111; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Low, BlackstoneWall::North::Tall, BlackstoneWall::South::Low, true, BlackstoneWall::West::None).ID: return 16115; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Low, BlackstoneWall::North::Tall, BlackstoneWall::South::Low, true, BlackstoneWall::West::Low).ID: return 16116; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Low, BlackstoneWall::North::Tall, BlackstoneWall::South::Low, true, BlackstoneWall::West::Tall).ID: return 16117; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Low, BlackstoneWall::North::Tall, BlackstoneWall::South::Low, false, BlackstoneWall::West::None).ID: return 16121; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Low, BlackstoneWall::North::Tall, BlackstoneWall::South::Low, false, BlackstoneWall::West::Low).ID: return 16122; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Low, BlackstoneWall::North::Tall, BlackstoneWall::South::Low, false, BlackstoneWall::West::Tall).ID: return 16123; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Low, BlackstoneWall::North::Tall, BlackstoneWall::South::Tall, true, BlackstoneWall::West::None).ID: return 16127; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Low, BlackstoneWall::North::Tall, BlackstoneWall::South::Tall, true, BlackstoneWall::West::Low).ID: return 16128; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Low, BlackstoneWall::North::Tall, BlackstoneWall::South::Tall, true, BlackstoneWall::West::Tall).ID: return 16129; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Low, BlackstoneWall::North::Tall, BlackstoneWall::South::Tall, false, BlackstoneWall::West::None).ID: return 16133; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Low, BlackstoneWall::North::Tall, BlackstoneWall::South::Tall, false, BlackstoneWall::West::Low).ID: return 16134; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Low, BlackstoneWall::North::Tall, BlackstoneWall::South::Tall, false, BlackstoneWall::West::Tall).ID: return 16135; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Tall, BlackstoneWall::North::None, BlackstoneWall::South::None, true, BlackstoneWall::West::None).ID: return 16139; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Tall, BlackstoneWall::North::None, BlackstoneWall::South::None, true, BlackstoneWall::West::Low).ID: return 16140; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Tall, BlackstoneWall::North::None, BlackstoneWall::South::None, true, BlackstoneWall::West::Tall).ID: return 16141; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Tall, BlackstoneWall::North::None, BlackstoneWall::South::None, false, BlackstoneWall::West::None).ID: return 16145; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Tall, BlackstoneWall::North::None, BlackstoneWall::South::None, false, BlackstoneWall::West::Low).ID: return 16146; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Tall, BlackstoneWall::North::None, BlackstoneWall::South::None, false, BlackstoneWall::West::Tall).ID: return 16147; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Tall, BlackstoneWall::North::None, BlackstoneWall::South::Low, true, BlackstoneWall::West::None).ID: return 16151; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Tall, BlackstoneWall::North::None, BlackstoneWall::South::Low, true, BlackstoneWall::West::Low).ID: return 16152; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Tall, BlackstoneWall::North::None, BlackstoneWall::South::Low, true, BlackstoneWall::West::Tall).ID: return 16153; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Tall, BlackstoneWall::North::None, BlackstoneWall::South::Low, false, BlackstoneWall::West::None).ID: return 16157; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Tall, BlackstoneWall::North::None, BlackstoneWall::South::Low, false, BlackstoneWall::West::Low).ID: return 16158; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Tall, BlackstoneWall::North::None, BlackstoneWall::South::Low, false, BlackstoneWall::West::Tall).ID: return 16159; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Tall, BlackstoneWall::North::None, BlackstoneWall::South::Tall, true, BlackstoneWall::West::None).ID: return 16163; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Tall, BlackstoneWall::North::None, BlackstoneWall::South::Tall, true, BlackstoneWall::West::Low).ID: return 16164; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Tall, BlackstoneWall::North::None, BlackstoneWall::South::Tall, true, BlackstoneWall::West::Tall).ID: return 16165; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Tall, BlackstoneWall::North::None, BlackstoneWall::South::Tall, false, BlackstoneWall::West::None).ID: return 16169; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Tall, BlackstoneWall::North::None, BlackstoneWall::South::Tall, false, BlackstoneWall::West::Low).ID: return 16170; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Tall, BlackstoneWall::North::None, BlackstoneWall::South::Tall, false, BlackstoneWall::West::Tall).ID: return 16171; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Tall, BlackstoneWall::North::Low, BlackstoneWall::South::None, true, BlackstoneWall::West::None).ID: return 16175; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Tall, BlackstoneWall::North::Low, BlackstoneWall::South::None, true, BlackstoneWall::West::Low).ID: return 16176; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Tall, BlackstoneWall::North::Low, BlackstoneWall::South::None, true, BlackstoneWall::West::Tall).ID: return 16177; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Tall, BlackstoneWall::North::Low, BlackstoneWall::South::None, false, BlackstoneWall::West::None).ID: return 16181; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Tall, BlackstoneWall::North::Low, BlackstoneWall::South::None, false, BlackstoneWall::West::Low).ID: return 16182; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Tall, BlackstoneWall::North::Low, BlackstoneWall::South::None, false, BlackstoneWall::West::Tall).ID: return 16183; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Tall, BlackstoneWall::North::Low, BlackstoneWall::South::Low, true, BlackstoneWall::West::None).ID: return 16187; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Tall, BlackstoneWall::North::Low, BlackstoneWall::South::Low, true, BlackstoneWall::West::Low).ID: return 16188; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Tall, BlackstoneWall::North::Low, BlackstoneWall::South::Low, true, BlackstoneWall::West::Tall).ID: return 16189; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Tall, BlackstoneWall::North::Low, BlackstoneWall::South::Low, false, BlackstoneWall::West::None).ID: return 16193; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Tall, BlackstoneWall::North::Low, BlackstoneWall::South::Low, false, BlackstoneWall::West::Low).ID: return 16194; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Tall, BlackstoneWall::North::Low, BlackstoneWall::South::Low, false, BlackstoneWall::West::Tall).ID: return 16195; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Tall, BlackstoneWall::North::Low, BlackstoneWall::South::Tall, true, BlackstoneWall::West::None).ID: return 16199; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Tall, BlackstoneWall::North::Low, BlackstoneWall::South::Tall, true, BlackstoneWall::West::Low).ID: return 16200; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Tall, BlackstoneWall::North::Low, BlackstoneWall::South::Tall, true, BlackstoneWall::West::Tall).ID: return 16201; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Tall, BlackstoneWall::North::Low, BlackstoneWall::South::Tall, false, BlackstoneWall::West::None).ID: return 16205; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Tall, BlackstoneWall::North::Low, BlackstoneWall::South::Tall, false, BlackstoneWall::West::Low).ID: return 16206; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Tall, BlackstoneWall::North::Low, BlackstoneWall::South::Tall, false, BlackstoneWall::West::Tall).ID: return 16207; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Tall, BlackstoneWall::North::Tall, BlackstoneWall::South::None, true, BlackstoneWall::West::None).ID: return 16211; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Tall, BlackstoneWall::North::Tall, BlackstoneWall::South::None, true, BlackstoneWall::West::Low).ID: return 16212; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Tall, BlackstoneWall::North::Tall, BlackstoneWall::South::None, true, BlackstoneWall::West::Tall).ID: return 16213; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Tall, BlackstoneWall::North::Tall, BlackstoneWall::South::None, false, BlackstoneWall::West::None).ID: return 16217; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Tall, BlackstoneWall::North::Tall, BlackstoneWall::South::None, false, BlackstoneWall::West::Low).ID: return 16218; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Tall, BlackstoneWall::North::Tall, BlackstoneWall::South::None, false, BlackstoneWall::West::Tall).ID: return 16219; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Tall, BlackstoneWall::North::Tall, BlackstoneWall::South::Low, true, BlackstoneWall::West::None).ID: return 16223; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Tall, BlackstoneWall::North::Tall, BlackstoneWall::South::Low, true, BlackstoneWall::West::Low).ID: return 16224; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Tall, BlackstoneWall::North::Tall, BlackstoneWall::South::Low, true, BlackstoneWall::West::Tall).ID: return 16225; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Tall, BlackstoneWall::North::Tall, BlackstoneWall::South::Low, false, BlackstoneWall::West::None).ID: return 16229; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Tall, BlackstoneWall::North::Tall, BlackstoneWall::South::Low, false, BlackstoneWall::West::Low).ID: return 16230; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Tall, BlackstoneWall::North::Tall, BlackstoneWall::South::Low, false, BlackstoneWall::West::Tall).ID: return 16231; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Tall, BlackstoneWall::North::Tall, BlackstoneWall::South::Tall, true, BlackstoneWall::West::None).ID: return 16235; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Tall, BlackstoneWall::North::Tall, BlackstoneWall::South::Tall, true, BlackstoneWall::West::Low).ID: return 16236; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Tall, BlackstoneWall::North::Tall, BlackstoneWall::South::Tall, true, BlackstoneWall::West::Tall).ID: return 16237; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Tall, BlackstoneWall::North::Tall, BlackstoneWall::South::Tall, false, BlackstoneWall::West::None).ID: return 16241; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Tall, BlackstoneWall::North::Tall, BlackstoneWall::South::Tall, false, BlackstoneWall::West::Low).ID: return 16242; case BlackstoneWall::BlackstoneWall(BlackstoneWall::East::Tall, BlackstoneWall::North::Tall, BlackstoneWall::South::Tall, false, BlackstoneWall::West::Tall).ID: return 16243; case BlastFurnace::BlastFurnace(eBlockFace::BLOCK_FACE_ZM, true).ID: return 14811; case BlastFurnace::BlastFurnace(eBlockFace::BLOCK_FACE_ZM, false).ID: return 14812; case BlastFurnace::BlastFurnace(eBlockFace::BLOCK_FACE_ZP, true).ID: return 14813; case BlastFurnace::BlastFurnace(eBlockFace::BLOCK_FACE_ZP, false).ID: return 14814; case BlastFurnace::BlastFurnace(eBlockFace::BLOCK_FACE_XM, true).ID: return 14815; case BlastFurnace::BlastFurnace(eBlockFace::BLOCK_FACE_XM, false).ID: return 14816; case BlastFurnace::BlastFurnace(eBlockFace::BLOCK_FACE_XP, true).ID: return 14817; case BlastFurnace::BlastFurnace(eBlockFace::BLOCK_FACE_XP, false).ID: return 14818; case BlueBanner::BlueBanner(0).ID: return 8073; case BlueBanner::BlueBanner(1).ID: return 8074; case BlueBanner::BlueBanner(2).ID: return 8075; case BlueBanner::BlueBanner(3).ID: return 8076; case BlueBanner::BlueBanner(4).ID: return 8077; case BlueBanner::BlueBanner(5).ID: return 8078; case BlueBanner::BlueBanner(6).ID: return 8079; case BlueBanner::BlueBanner(7).ID: return 8080; case BlueBanner::BlueBanner(8).ID: return 8081; case BlueBanner::BlueBanner(9).ID: return 8082; case BlueBanner::BlueBanner(10).ID: return 8083; case BlueBanner::BlueBanner(11).ID: return 8084; case BlueBanner::BlueBanner(12).ID: return 8085; case BlueBanner::BlueBanner(13).ID: return 8086; case BlueBanner::BlueBanner(14).ID: return 8087; case BlueBanner::BlueBanner(15).ID: return 8088; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_ZM, true, BlueBed::Part::Head).ID: return 1225; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_ZM, true, BlueBed::Part::Foot).ID: return 1226; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_ZM, false, BlueBed::Part::Head).ID: return 1227; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_ZM, false, BlueBed::Part::Foot).ID: return 1228; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_ZP, true, BlueBed::Part::Head).ID: return 1229; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_ZP, true, BlueBed::Part::Foot).ID: return 1230; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_ZP, false, BlueBed::Part::Head).ID: return 1231; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_ZP, false, BlueBed::Part::Foot).ID: return 1232; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_XM, true, BlueBed::Part::Head).ID: return 1233; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_XM, true, BlueBed::Part::Foot).ID: return 1234; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_XM, false, BlueBed::Part::Head).ID: return 1235; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_XM, false, BlueBed::Part::Foot).ID: return 1236; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_XP, true, BlueBed::Part::Head).ID: return 1237; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_XP, true, BlueBed::Part::Foot).ID: return 1238; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_XP, false, BlueBed::Part::Head).ID: return 1239; case BlueBed::BlueBed(eBlockFace::BLOCK_FACE_XP, false, BlueBed::Part::Foot).ID: return 1240; case BlueCarpet::BlueCarpet().ID: return 7877; case BlueConcrete::BlueConcrete().ID: return 9449; case BlueConcretePowder::BlueConcretePowder().ID: return 9465; case BlueGlazedTerracotta::BlueGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 9418; case BlueGlazedTerracotta::BlueGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 9419; case BlueGlazedTerracotta::BlueGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 9420; case BlueGlazedTerracotta::BlueGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 9421; case BlueIce::BlueIce().ID: return 9648; case BlueOrchid::BlueOrchid().ID: return 1414; case BlueShulkerBox::BlueShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 9344; case BlueShulkerBox::BlueShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 9345; case BlueShulkerBox::BlueShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 9346; case BlueShulkerBox::BlueShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 9347; case BlueShulkerBox::BlueShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 9348; case BlueShulkerBox::BlueShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 9349; case BlueStainedGlass::BlueStainedGlass().ID: return 4106; case BlueStainedGlassPane::BlueStainedGlassPane(true, true, true, true).ID: return 7217; case BlueStainedGlassPane::BlueStainedGlassPane(true, true, true, false).ID: return 7218; case BlueStainedGlassPane::BlueStainedGlassPane(true, true, false, true).ID: return 7221; case BlueStainedGlassPane::BlueStainedGlassPane(true, true, false, false).ID: return 7222; case BlueStainedGlassPane::BlueStainedGlassPane(true, false, true, true).ID: return 7225; case BlueStainedGlassPane::BlueStainedGlassPane(true, false, true, false).ID: return 7226; case BlueStainedGlassPane::BlueStainedGlassPane(true, false, false, true).ID: return 7229; case BlueStainedGlassPane::BlueStainedGlassPane(true, false, false, false).ID: return 7230; case BlueStainedGlassPane::BlueStainedGlassPane(false, true, true, true).ID: return 7233; case BlueStainedGlassPane::BlueStainedGlassPane(false, true, true, false).ID: return 7234; case BlueStainedGlassPane::BlueStainedGlassPane(false, true, false, true).ID: return 7237; case BlueStainedGlassPane::BlueStainedGlassPane(false, true, false, false).ID: return 7238; case BlueStainedGlassPane::BlueStainedGlassPane(false, false, true, true).ID: return 7241; case BlueStainedGlassPane::BlueStainedGlassPane(false, false, true, false).ID: return 7242; case BlueStainedGlassPane::BlueStainedGlassPane(false, false, false, true).ID: return 7245; case BlueStainedGlassPane::BlueStainedGlassPane(false, false, false, false).ID: return 7246; case BlueTerracotta::BlueTerracotta().ID: return 6858; case BlueWallBanner::BlueWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 8197; case BlueWallBanner::BlueWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 8198; case BlueWallBanner::BlueWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 8199; case BlueWallBanner::BlueWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 8200; case BlueWool::BlueWool().ID: return 1395; case BoneBlock::BoneBlock(BoneBlock::Axis::X).ID: return 9256; case BoneBlock::BoneBlock(BoneBlock::Axis::Y).ID: return 9257; case BoneBlock::BoneBlock(BoneBlock::Axis::Z).ID: return 9258; case Bookshelf::Bookshelf().ID: return 1432; case BrainCoral::BrainCoral().ID: return 9533; case BrainCoralBlock::BrainCoralBlock().ID: return 9516; case BrainCoralFan::BrainCoralFan().ID: return 9553; case BrainCoralWallFan::BrainCoralWallFan(eBlockFace::BLOCK_FACE_ZM).ID: return 9609; case BrainCoralWallFan::BrainCoralWallFan(eBlockFace::BLOCK_FACE_ZP).ID: return 9611; case BrainCoralWallFan::BrainCoralWallFan(eBlockFace::BLOCK_FACE_XM).ID: return 9613; case BrainCoralWallFan::BrainCoralWallFan(eBlockFace::BLOCK_FACE_XP).ID: return 9615; case BrewingStand::BrewingStand(true, true, true).ID: return 5133; case BrewingStand::BrewingStand(true, true, false).ID: return 5134; case BrewingStand::BrewingStand(true, false, true).ID: return 5135; case BrewingStand::BrewingStand(true, false, false).ID: return 5136; case BrewingStand::BrewingStand(false, true, true).ID: return 5137; case BrewingStand::BrewingStand(false, true, false).ID: return 5138; case BrewingStand::BrewingStand(false, false, true).ID: return 5139; case BrewingStand::BrewingStand(false, false, false).ID: return 5140; case BrickSlab::BrickSlab(BrickSlab::Type::Top).ID: return 8373; case BrickSlab::BrickSlab(BrickSlab::Type::Bottom).ID: return 8375; case BrickSlab::BrickSlab(BrickSlab::Type::Double).ID: return 8377; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZM, BrickStairs::Half::Top, BrickStairs::Shape::Straight).ID: return 4853; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZM, BrickStairs::Half::Top, BrickStairs::Shape::InnerLeft).ID: return 4855; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZM, BrickStairs::Half::Top, BrickStairs::Shape::InnerRight).ID: return 4857; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZM, BrickStairs::Half::Top, BrickStairs::Shape::OuterLeft).ID: return 4859; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZM, BrickStairs::Half::Top, BrickStairs::Shape::OuterRight).ID: return 4861; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZM, BrickStairs::Half::Bottom, BrickStairs::Shape::Straight).ID: return 4863; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZM, BrickStairs::Half::Bottom, BrickStairs::Shape::InnerLeft).ID: return 4865; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZM, BrickStairs::Half::Bottom, BrickStairs::Shape::InnerRight).ID: return 4867; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZM, BrickStairs::Half::Bottom, BrickStairs::Shape::OuterLeft).ID: return 4869; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZM, BrickStairs::Half::Bottom, BrickStairs::Shape::OuterRight).ID: return 4871; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZP, BrickStairs::Half::Top, BrickStairs::Shape::Straight).ID: return 4873; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZP, BrickStairs::Half::Top, BrickStairs::Shape::InnerLeft).ID: return 4875; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZP, BrickStairs::Half::Top, BrickStairs::Shape::InnerRight).ID: return 4877; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZP, BrickStairs::Half::Top, BrickStairs::Shape::OuterLeft).ID: return 4879; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZP, BrickStairs::Half::Top, BrickStairs::Shape::OuterRight).ID: return 4881; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZP, BrickStairs::Half::Bottom, BrickStairs::Shape::Straight).ID: return 4883; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZP, BrickStairs::Half::Bottom, BrickStairs::Shape::InnerLeft).ID: return 4885; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZP, BrickStairs::Half::Bottom, BrickStairs::Shape::InnerRight).ID: return 4887; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZP, BrickStairs::Half::Bottom, BrickStairs::Shape::OuterLeft).ID: return 4889; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZP, BrickStairs::Half::Bottom, BrickStairs::Shape::OuterRight).ID: return 4891; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XM, BrickStairs::Half::Top, BrickStairs::Shape::Straight).ID: return 4893; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XM, BrickStairs::Half::Top, BrickStairs::Shape::InnerLeft).ID: return 4895; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XM, BrickStairs::Half::Top, BrickStairs::Shape::InnerRight).ID: return 4897; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XM, BrickStairs::Half::Top, BrickStairs::Shape::OuterLeft).ID: return 4899; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XM, BrickStairs::Half::Top, BrickStairs::Shape::OuterRight).ID: return 4901; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XM, BrickStairs::Half::Bottom, BrickStairs::Shape::Straight).ID: return 4903; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XM, BrickStairs::Half::Bottom, BrickStairs::Shape::InnerLeft).ID: return 4905; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XM, BrickStairs::Half::Bottom, BrickStairs::Shape::InnerRight).ID: return 4907; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XM, BrickStairs::Half::Bottom, BrickStairs::Shape::OuterLeft).ID: return 4909; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XM, BrickStairs::Half::Bottom, BrickStairs::Shape::OuterRight).ID: return 4911; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XP, BrickStairs::Half::Top, BrickStairs::Shape::Straight).ID: return 4913; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XP, BrickStairs::Half::Top, BrickStairs::Shape::InnerLeft).ID: return 4915; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XP, BrickStairs::Half::Top, BrickStairs::Shape::InnerRight).ID: return 4917; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XP, BrickStairs::Half::Top, BrickStairs::Shape::OuterLeft).ID: return 4919; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XP, BrickStairs::Half::Top, BrickStairs::Shape::OuterRight).ID: return 4921; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XP, BrickStairs::Half::Bottom, BrickStairs::Shape::Straight).ID: return 4923; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XP, BrickStairs::Half::Bottom, BrickStairs::Shape::InnerLeft).ID: return 4925; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XP, BrickStairs::Half::Bottom, BrickStairs::Shape::InnerRight).ID: return 4927; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XP, BrickStairs::Half::Bottom, BrickStairs::Shape::OuterLeft).ID: return 4929; case BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XP, BrickStairs::Half::Bottom, BrickStairs::Shape::OuterRight).ID: return 4931; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::None, BrickWall::South::None, true, BrickWall::West::None).ID: return 10870; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::None, BrickWall::South::None, true, BrickWall::West::Low).ID: return 10871; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::None, BrickWall::South::None, true, BrickWall::West::Tall).ID: return 10872; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::None, BrickWall::South::None, false, BrickWall::West::None).ID: return 10876; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::None, BrickWall::South::None, false, BrickWall::West::Low).ID: return 10877; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::None, BrickWall::South::None, false, BrickWall::West::Tall).ID: return 10878; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::None, BrickWall::South::Low, true, BrickWall::West::None).ID: return 10882; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::None, BrickWall::South::Low, true, BrickWall::West::Low).ID: return 10883; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::None, BrickWall::South::Low, true, BrickWall::West::Tall).ID: return 10884; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::None, BrickWall::South::Low, false, BrickWall::West::None).ID: return 10888; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::None, BrickWall::South::Low, false, BrickWall::West::Low).ID: return 10889; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::None, BrickWall::South::Low, false, BrickWall::West::Tall).ID: return 10890; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::None, BrickWall::South::Tall, true, BrickWall::West::None).ID: return 10894; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::None, BrickWall::South::Tall, true, BrickWall::West::Low).ID: return 10895; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::None, BrickWall::South::Tall, true, BrickWall::West::Tall).ID: return 10896; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::None, BrickWall::South::Tall, false, BrickWall::West::None).ID: return 10900; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::None, BrickWall::South::Tall, false, BrickWall::West::Low).ID: return 10901; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::None, BrickWall::South::Tall, false, BrickWall::West::Tall).ID: return 10902; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::Low, BrickWall::South::None, true, BrickWall::West::None).ID: return 10906; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::Low, BrickWall::South::None, true, BrickWall::West::Low).ID: return 10907; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::Low, BrickWall::South::None, true, BrickWall::West::Tall).ID: return 10908; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::Low, BrickWall::South::None, false, BrickWall::West::None).ID: return 10912; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::Low, BrickWall::South::None, false, BrickWall::West::Low).ID: return 10913; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::Low, BrickWall::South::None, false, BrickWall::West::Tall).ID: return 10914; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::Low, BrickWall::South::Low, true, BrickWall::West::None).ID: return 10918; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::Low, BrickWall::South::Low, true, BrickWall::West::Low).ID: return 10919; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::Low, BrickWall::South::Low, true, BrickWall::West::Tall).ID: return 10920; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::Low, BrickWall::South::Low, false, BrickWall::West::None).ID: return 10924; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::Low, BrickWall::South::Low, false, BrickWall::West::Low).ID: return 10925; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::Low, BrickWall::South::Low, false, BrickWall::West::Tall).ID: return 10926; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::Low, BrickWall::South::Tall, true, BrickWall::West::None).ID: return 10930; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::Low, BrickWall::South::Tall, true, BrickWall::West::Low).ID: return 10931; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::Low, BrickWall::South::Tall, true, BrickWall::West::Tall).ID: return 10932; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::Low, BrickWall::South::Tall, false, BrickWall::West::None).ID: return 10936; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::Low, BrickWall::South::Tall, false, BrickWall::West::Low).ID: return 10937; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::Low, BrickWall::South::Tall, false, BrickWall::West::Tall).ID: return 10938; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::Tall, BrickWall::South::None, true, BrickWall::West::None).ID: return 10942; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::Tall, BrickWall::South::None, true, BrickWall::West::Low).ID: return 10943; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::Tall, BrickWall::South::None, true, BrickWall::West::Tall).ID: return 10944; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::Tall, BrickWall::South::None, false, BrickWall::West::None).ID: return 10948; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::Tall, BrickWall::South::None, false, BrickWall::West::Low).ID: return 10949; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::Tall, BrickWall::South::None, false, BrickWall::West::Tall).ID: return 10950; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::Tall, BrickWall::South::Low, true, BrickWall::West::None).ID: return 10954; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::Tall, BrickWall::South::Low, true, BrickWall::West::Low).ID: return 10955; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::Tall, BrickWall::South::Low, true, BrickWall::West::Tall).ID: return 10956; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::Tall, BrickWall::South::Low, false, BrickWall::West::None).ID: return 10960; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::Tall, BrickWall::South::Low, false, BrickWall::West::Low).ID: return 10961; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::Tall, BrickWall::South::Low, false, BrickWall::West::Tall).ID: return 10962; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::Tall, BrickWall::South::Tall, true, BrickWall::West::None).ID: return 10966; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::Tall, BrickWall::South::Tall, true, BrickWall::West::Low).ID: return 10967; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::Tall, BrickWall::South::Tall, true, BrickWall::West::Tall).ID: return 10968; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::Tall, BrickWall::South::Tall, false, BrickWall::West::None).ID: return 10972; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::Tall, BrickWall::South::Tall, false, BrickWall::West::Low).ID: return 10973; case BrickWall::BrickWall(BrickWall::East::None, BrickWall::North::Tall, BrickWall::South::Tall, false, BrickWall::West::Tall).ID: return 10974; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::None, BrickWall::South::None, true, BrickWall::West::None).ID: return 10978; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::None, BrickWall::South::None, true, BrickWall::West::Low).ID: return 10979; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::None, BrickWall::South::None, true, BrickWall::West::Tall).ID: return 10980; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::None, BrickWall::South::None, false, BrickWall::West::None).ID: return 10984; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::None, BrickWall::South::None, false, BrickWall::West::Low).ID: return 10985; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::None, BrickWall::South::None, false, BrickWall::West::Tall).ID: return 10986; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::None, BrickWall::South::Low, true, BrickWall::West::None).ID: return 10990; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::None, BrickWall::South::Low, true, BrickWall::West::Low).ID: return 10991; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::None, BrickWall::South::Low, true, BrickWall::West::Tall).ID: return 10992; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::None, BrickWall::South::Low, false, BrickWall::West::None).ID: return 10996; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::None, BrickWall::South::Low, false, BrickWall::West::Low).ID: return 10997; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::None, BrickWall::South::Low, false, BrickWall::West::Tall).ID: return 10998; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::None, BrickWall::South::Tall, true, BrickWall::West::None).ID: return 11002; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::None, BrickWall::South::Tall, true, BrickWall::West::Low).ID: return 11003; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::None, BrickWall::South::Tall, true, BrickWall::West::Tall).ID: return 11004; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::None, BrickWall::South::Tall, false, BrickWall::West::None).ID: return 11008; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::None, BrickWall::South::Tall, false, BrickWall::West::Low).ID: return 11009; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::None, BrickWall::South::Tall, false, BrickWall::West::Tall).ID: return 11010; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::Low, BrickWall::South::None, true, BrickWall::West::None).ID: return 11014; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::Low, BrickWall::South::None, true, BrickWall::West::Low).ID: return 11015; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::Low, BrickWall::South::None, true, BrickWall::West::Tall).ID: return 11016; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::Low, BrickWall::South::None, false, BrickWall::West::None).ID: return 11020; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::Low, BrickWall::South::None, false, BrickWall::West::Low).ID: return 11021; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::Low, BrickWall::South::None, false, BrickWall::West::Tall).ID: return 11022; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::Low, BrickWall::South::Low, true, BrickWall::West::None).ID: return 11026; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::Low, BrickWall::South::Low, true, BrickWall::West::Low).ID: return 11027; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::Low, BrickWall::South::Low, true, BrickWall::West::Tall).ID: return 11028; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::Low, BrickWall::South::Low, false, BrickWall::West::None).ID: return 11032; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::Low, BrickWall::South::Low, false, BrickWall::West::Low).ID: return 11033; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::Low, BrickWall::South::Low, false, BrickWall::West::Tall).ID: return 11034; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::Low, BrickWall::South::Tall, true, BrickWall::West::None).ID: return 11038; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::Low, BrickWall::South::Tall, true, BrickWall::West::Low).ID: return 11039; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::Low, BrickWall::South::Tall, true, BrickWall::West::Tall).ID: return 11040; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::Low, BrickWall::South::Tall, false, BrickWall::West::None).ID: return 11044; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::Low, BrickWall::South::Tall, false, BrickWall::West::Low).ID: return 11045; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::Low, BrickWall::South::Tall, false, BrickWall::West::Tall).ID: return 11046; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::Tall, BrickWall::South::None, true, BrickWall::West::None).ID: return 11050; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::Tall, BrickWall::South::None, true, BrickWall::West::Low).ID: return 11051; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::Tall, BrickWall::South::None, true, BrickWall::West::Tall).ID: return 11052; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::Tall, BrickWall::South::None, false, BrickWall::West::None).ID: return 11056; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::Tall, BrickWall::South::None, false, BrickWall::West::Low).ID: return 11057; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::Tall, BrickWall::South::None, false, BrickWall::West::Tall).ID: return 11058; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::Tall, BrickWall::South::Low, true, BrickWall::West::None).ID: return 11062; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::Tall, BrickWall::South::Low, true, BrickWall::West::Low).ID: return 11063; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::Tall, BrickWall::South::Low, true, BrickWall::West::Tall).ID: return 11064; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::Tall, BrickWall::South::Low, false, BrickWall::West::None).ID: return 11068; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::Tall, BrickWall::South::Low, false, BrickWall::West::Low).ID: return 11069; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::Tall, BrickWall::South::Low, false, BrickWall::West::Tall).ID: return 11070; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::Tall, BrickWall::South::Tall, true, BrickWall::West::None).ID: return 11074; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::Tall, BrickWall::South::Tall, true, BrickWall::West::Low).ID: return 11075; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::Tall, BrickWall::South::Tall, true, BrickWall::West::Tall).ID: return 11076; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::Tall, BrickWall::South::Tall, false, BrickWall::West::None).ID: return 11080; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::Tall, BrickWall::South::Tall, false, BrickWall::West::Low).ID: return 11081; case BrickWall::BrickWall(BrickWall::East::Low, BrickWall::North::Tall, BrickWall::South::Tall, false, BrickWall::West::Tall).ID: return 11082; case BrickWall::BrickWall(BrickWall::East::Tall, BrickWall::North::None, BrickWall::South::None, true, BrickWall::West::None).ID: return 11086; case BrickWall::BrickWall(BrickWall::East::Tall, BrickWall::North::None, BrickWall::South::None, true, BrickWall::West::Low).ID: return 11087; case BrickWall::BrickWall(BrickWall::East::Tall, BrickWall::North::None, BrickWall::South::None, true, BrickWall::West::Tall).ID: return 11088; case BrickWall::BrickWall(BrickWall::East::Tall, BrickWall::North::None, BrickWall::South::None, false, BrickWall::West::None).ID: return 11092; case BrickWall::BrickWall(BrickWall::East::Tall, BrickWall::North::None, BrickWall::South::None, false, BrickWall::West::Low).ID: return 11093; case BrickWall::BrickWall(BrickWall::East::Tall, BrickWall::North::None, BrickWall::South::None, false, BrickWall::West::Tall).ID: return 11094; case BrickWall::BrickWall(BrickWall::East::Tall, BrickWall::North::None, BrickWall::South::Low, true, BrickWall::West::None).ID: return 11098; case BrickWall::BrickWall(BrickWall::East::Tall, BrickWall::North::None, BrickWall::South::Low, true, BrickWall::West::Low).ID: return 11099; case BrickWall::BrickWall(BrickWall::East::Tall, BrickWall::North::None, BrickWall::South::Low, true, BrickWall::West::Tall).ID: return 11100; case BrickWall::BrickWall(BrickWall::East::Tall, BrickWall::North::None, BrickWall::South::Low, false, BrickWall::West::None).ID: return 11104; case BrickWall::BrickWall(BrickWall::East::Tall, BrickWall::North::None, BrickWall::South::Low, false, BrickWall::West::Low).ID: return 11105; case BrickWall::BrickWall(BrickWall::East::Tall, BrickWall::North::None, BrickWall::South::Low, false, BrickWall::West::Tall).ID: return 11106; case BrickWall::BrickWall(BrickWall::East::Tall, BrickWall::North::None, BrickWall::South::Tall, true, BrickWall::West::None).ID: return 11110; case BrickWall::BrickWall(BrickWall::East::Tall, BrickWall::North::None, BrickWall::South::Tall, true, BrickWall::West::Low).ID: return 11111; case BrickWall::BrickWall(BrickWall::East::Tall, BrickWall::North::None, BrickWall::South::Tall, true, BrickWall::West::Tall).ID: return 11112; case BrickWall::BrickWall(BrickWall::East::Tall, BrickWall::North::None, BrickWall::South::Tall, false, BrickWall::West::None).ID: return 11116; case BrickWall::BrickWall(BrickWall::East::Tall, BrickWall::North::None, BrickWall::South::Tall, false, BrickWall::West::Low).ID: return 11117; case BrickWall::BrickWall(BrickWall::East::Tall, BrickWall::North::None, BrickWall::South::Tall, false, BrickWall::West::Tall).ID: return 11118; case BrickWall::BrickWall(BrickWall::East::Tall, BrickWall::North::Low, BrickWall::South::None, true, BrickWall::West::None).ID: return 11122; case BrickWall::BrickWall(BrickWall::East::Tall, BrickWall::North::Low, BrickWall::South::None, true, BrickWall::West::Low).ID: return 11123; case BrickWall::BrickWall(BrickWall::East::Tall, BrickWall::North::Low, BrickWall::South::None, true, BrickWall::West::Tall).ID: return 11124; case BrickWall::BrickWall(BrickWall::East::Tall, BrickWall::North::Low, BrickWall::South::None, false, BrickWall::West::None).ID: return 11128; case BrickWall::BrickWall(BrickWall::East::Tall, BrickWall::North::Low, BrickWall::South::None, false, BrickWall::West::Low).ID: return 11129; case BrickWall::BrickWall(BrickWall::East::Tall, BrickWall::North::Low, BrickWall::South::None, false, BrickWall::West::Tall).ID: return 11130; case BrickWall::BrickWall(BrickWall::East::Tall, BrickWall::North::Low, BrickWall::South::Low, true, BrickWall::West::None).ID: return 11134; case BrickWall::BrickWall(BrickWall::East::Tall, BrickWall::North::Low, BrickWall::South::Low, true, BrickWall::West::Low).ID: return 11135; case BrickWall::BrickWall(BrickWall::East::Tall, BrickWall::North::Low, BrickWall::South::Low, true, BrickWall::West::Tall).ID: return 11136; case BrickWall::BrickWall(BrickWall::East::Tall, BrickWall::North::Low, BrickWall::South::Low, false, BrickWall::West::None).ID: return 11140; case BrickWall::BrickWall(BrickWall::East::Tall, BrickWall::North::Low, BrickWall::South::Low, false, BrickWall::West::Low).ID: return 11141; case BrickWall::BrickWall(BrickWall::East::Tall, BrickWall::North::Low, BrickWall::South::Low, false, BrickWall::West::Tall).ID: return 11142; case BrickWall::BrickWall(BrickWall::East::Tall, BrickWall::North::Low, BrickWall::South::Tall, true, BrickWall::West::None).ID: return 11146; case BrickWall::BrickWall(BrickWall::East::Tall, BrickWall::North::Low, BrickWall::South::Tall, true, BrickWall::West::Low).ID: return 11147; case BrickWall::BrickWall(BrickWall::East::Tall, BrickWall::North::Low, BrickWall::South::Tall, true, BrickWall::West::Tall).ID: return 11148; case BrickWall::BrickWall(BrickWall::East::Tall, BrickWall::North::Low, BrickWall::South::Tall, false, BrickWall::West::None).ID: return 11152; case BrickWall::BrickWall(BrickWall::East::Tall, BrickWall::North::Low, BrickWall::South::Tall, false, BrickWall::West::Low).ID: return 11153; case BrickWall::BrickWall(BrickWall::East::Tall, BrickWall::North::Low, BrickWall::South::Tall, false, BrickWall::West::Tall).ID: return 11154; case BrickWall::BrickWall(BrickWall::East::Tall, BrickWall::North::Tall, BrickWall::South::None, true, BrickWall::West::None).ID: return 11158; case BrickWall::BrickWall(BrickWall::East::Tall, BrickWall::North::Tall, BrickWall::South::None, true, BrickWall::West::Low).ID: return 11159; case BrickWall::BrickWall(BrickWall::East::Tall, BrickWall::North::Tall, BrickWall::South::None, true, BrickWall::West::Tall).ID: return 11160; case BrickWall::BrickWall(BrickWall::East::Tall, BrickWall::North::Tall, BrickWall::South::None, false, BrickWall::West::None).ID: return 11164; case BrickWall::BrickWall(BrickWall::East::Tall, BrickWall::North::Tall, BrickWall::South::None, false, BrickWall::West::Low).ID: return 11165; case BrickWall::BrickWall(BrickWall::East::Tall, BrickWall::North::Tall, BrickWall::South::None, false, BrickWall::West::Tall).ID: return 11166; case BrickWall::BrickWall(BrickWall::East::Tall, BrickWall::North::Tall, BrickWall::South::Low, true, BrickWall::West::None).ID: return 11170; case BrickWall::BrickWall(BrickWall::East::Tall, BrickWall::North::Tall, BrickWall::South::Low, true, BrickWall::West::Low).ID: return 11171; case BrickWall::BrickWall(BrickWall::East::Tall, BrickWall::North::Tall, BrickWall::South::Low, true, BrickWall::West::Tall).ID: return 11172; case BrickWall::BrickWall(BrickWall::East::Tall, BrickWall::North::Tall, BrickWall::South::Low, false, BrickWall::West::None).ID: return 11176; case BrickWall::BrickWall(BrickWall::East::Tall, BrickWall::North::Tall, BrickWall::South::Low, false, BrickWall::West::Low).ID: return 11177; case BrickWall::BrickWall(BrickWall::East::Tall, BrickWall::North::Tall, BrickWall::South::Low, false, BrickWall::West::Tall).ID: return 11178; case BrickWall::BrickWall(BrickWall::East::Tall, BrickWall::North::Tall, BrickWall::South::Tall, true, BrickWall::West::None).ID: return 11182; case BrickWall::BrickWall(BrickWall::East::Tall, BrickWall::North::Tall, BrickWall::South::Tall, true, BrickWall::West::Low).ID: return 11183; case BrickWall::BrickWall(BrickWall::East::Tall, BrickWall::North::Tall, BrickWall::South::Tall, true, BrickWall::West::Tall).ID: return 11184; case BrickWall::BrickWall(BrickWall::East::Tall, BrickWall::North::Tall, BrickWall::South::Tall, false, BrickWall::West::None).ID: return 11188; case BrickWall::BrickWall(BrickWall::East::Tall, BrickWall::North::Tall, BrickWall::South::Tall, false, BrickWall::West::Low).ID: return 11189; case BrickWall::BrickWall(BrickWall::East::Tall, BrickWall::North::Tall, BrickWall::South::Tall, false, BrickWall::West::Tall).ID: return 11190; case Bricks::Bricks().ID: return 1429; case BrownBanner::BrownBanner(0).ID: return 8089; case BrownBanner::BrownBanner(1).ID: return 8090; case BrownBanner::BrownBanner(2).ID: return 8091; case BrownBanner::BrownBanner(3).ID: return 8092; case BrownBanner::BrownBanner(4).ID: return 8093; case BrownBanner::BrownBanner(5).ID: return 8094; case BrownBanner::BrownBanner(6).ID: return 8095; case BrownBanner::BrownBanner(7).ID: return 8096; case BrownBanner::BrownBanner(8).ID: return 8097; case BrownBanner::BrownBanner(9).ID: return 8098; case BrownBanner::BrownBanner(10).ID: return 8099; case BrownBanner::BrownBanner(11).ID: return 8100; case BrownBanner::BrownBanner(12).ID: return 8101; case BrownBanner::BrownBanner(13).ID: return 8102; case BrownBanner::BrownBanner(14).ID: return 8103; case BrownBanner::BrownBanner(15).ID: return 8104; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_ZM, true, BrownBed::Part::Head).ID: return 1241; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_ZM, true, BrownBed::Part::Foot).ID: return 1242; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_ZM, false, BrownBed::Part::Head).ID: return 1243; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_ZM, false, BrownBed::Part::Foot).ID: return 1244; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_ZP, true, BrownBed::Part::Head).ID: return 1245; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_ZP, true, BrownBed::Part::Foot).ID: return 1246; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_ZP, false, BrownBed::Part::Head).ID: return 1247; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_ZP, false, BrownBed::Part::Foot).ID: return 1248; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_XM, true, BrownBed::Part::Head).ID: return 1249; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_XM, true, BrownBed::Part::Foot).ID: return 1250; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_XM, false, BrownBed::Part::Head).ID: return 1251; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_XM, false, BrownBed::Part::Foot).ID: return 1252; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_XP, true, BrownBed::Part::Head).ID: return 1253; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_XP, true, BrownBed::Part::Foot).ID: return 1254; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_XP, false, BrownBed::Part::Head).ID: return 1255; case BrownBed::BrownBed(eBlockFace::BLOCK_FACE_XP, false, BrownBed::Part::Foot).ID: return 1256; case BrownCarpet::BrownCarpet().ID: return 7878; case BrownConcrete::BrownConcrete().ID: return 9450; case BrownConcretePowder::BrownConcretePowder().ID: return 9466; case BrownGlazedTerracotta::BrownGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 9422; case BrownGlazedTerracotta::BrownGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 9423; case BrownGlazedTerracotta::BrownGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 9424; case BrownGlazedTerracotta::BrownGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 9425; case BrownMushroom::BrownMushroom().ID: return 1425; case BrownMushroomBlock::BrownMushroomBlock(true, true, true, true, true, true).ID: return 4505; case BrownMushroomBlock::BrownMushroomBlock(true, true, true, true, true, false).ID: return 4506; case BrownMushroomBlock::BrownMushroomBlock(true, true, true, true, false, true).ID: return 4507; case BrownMushroomBlock::BrownMushroomBlock(true, true, true, true, false, false).ID: return 4508; case BrownMushroomBlock::BrownMushroomBlock(true, true, true, false, true, true).ID: return 4509; case BrownMushroomBlock::BrownMushroomBlock(true, true, true, false, true, false).ID: return 4510; case BrownMushroomBlock::BrownMushroomBlock(true, true, true, false, false, true).ID: return 4511; case BrownMushroomBlock::BrownMushroomBlock(true, true, true, false, false, false).ID: return 4512; case BrownMushroomBlock::BrownMushroomBlock(true, true, false, true, true, true).ID: return 4513; case BrownMushroomBlock::BrownMushroomBlock(true, true, false, true, true, false).ID: return 4514; case BrownMushroomBlock::BrownMushroomBlock(true, true, false, true, false, true).ID: return 4515; case BrownMushroomBlock::BrownMushroomBlock(true, true, false, true, false, false).ID: return 4516; case BrownMushroomBlock::BrownMushroomBlock(true, true, false, false, true, true).ID: return 4517; case BrownMushroomBlock::BrownMushroomBlock(true, true, false, false, true, false).ID: return 4518; case BrownMushroomBlock::BrownMushroomBlock(true, true, false, false, false, true).ID: return 4519; case BrownMushroomBlock::BrownMushroomBlock(true, true, false, false, false, false).ID: return 4520; case BrownMushroomBlock::BrownMushroomBlock(true, false, true, true, true, true).ID: return 4521; case BrownMushroomBlock::BrownMushroomBlock(true, false, true, true, true, false).ID: return 4522; case BrownMushroomBlock::BrownMushroomBlock(true, false, true, true, false, true).ID: return 4523; case BrownMushroomBlock::BrownMushroomBlock(true, false, true, true, false, false).ID: return 4524; case BrownMushroomBlock::BrownMushroomBlock(true, false, true, false, true, true).ID: return 4525; case BrownMushroomBlock::BrownMushroomBlock(true, false, true, false, true, false).ID: return 4526; case BrownMushroomBlock::BrownMushroomBlock(true, false, true, false, false, true).ID: return 4527; case BrownMushroomBlock::BrownMushroomBlock(true, false, true, false, false, false).ID: return 4528; case BrownMushroomBlock::BrownMushroomBlock(true, false, false, true, true, true).ID: return 4529; case BrownMushroomBlock::BrownMushroomBlock(true, false, false, true, true, false).ID: return 4530; case BrownMushroomBlock::BrownMushroomBlock(true, false, false, true, false, true).ID: return 4531; case BrownMushroomBlock::BrownMushroomBlock(true, false, false, true, false, false).ID: return 4532; case BrownMushroomBlock::BrownMushroomBlock(true, false, false, false, true, true).ID: return 4533; case BrownMushroomBlock::BrownMushroomBlock(true, false, false, false, true, false).ID: return 4534; case BrownMushroomBlock::BrownMushroomBlock(true, false, false, false, false, true).ID: return 4535; case BrownMushroomBlock::BrownMushroomBlock(true, false, false, false, false, false).ID: return 4536; case BrownMushroomBlock::BrownMushroomBlock(false, true, true, true, true, true).ID: return 4537; case BrownMushroomBlock::BrownMushroomBlock(false, true, true, true, true, false).ID: return 4538; case BrownMushroomBlock::BrownMushroomBlock(false, true, true, true, false, true).ID: return 4539; case BrownMushroomBlock::BrownMushroomBlock(false, true, true, true, false, false).ID: return 4540; case BrownMushroomBlock::BrownMushroomBlock(false, true, true, false, true, true).ID: return 4541; case BrownMushroomBlock::BrownMushroomBlock(false, true, true, false, true, false).ID: return 4542; case BrownMushroomBlock::BrownMushroomBlock(false, true, true, false, false, true).ID: return 4543; case BrownMushroomBlock::BrownMushroomBlock(false, true, true, false, false, false).ID: return 4544; case BrownMushroomBlock::BrownMushroomBlock(false, true, false, true, true, true).ID: return 4545; case BrownMushroomBlock::BrownMushroomBlock(false, true, false, true, true, false).ID: return 4546; case BrownMushroomBlock::BrownMushroomBlock(false, true, false, true, false, true).ID: return 4547; case BrownMushroomBlock::BrownMushroomBlock(false, true, false, true, false, false).ID: return 4548; case BrownMushroomBlock::BrownMushroomBlock(false, true, false, false, true, true).ID: return 4549; case BrownMushroomBlock::BrownMushroomBlock(false, true, false, false, true, false).ID: return 4550; case BrownMushroomBlock::BrownMushroomBlock(false, true, false, false, false, true).ID: return 4551; case BrownMushroomBlock::BrownMushroomBlock(false, true, false, false, false, false).ID: return 4552; case BrownMushroomBlock::BrownMushroomBlock(false, false, true, true, true, true).ID: return 4553; case BrownMushroomBlock::BrownMushroomBlock(false, false, true, true, true, false).ID: return 4554; case BrownMushroomBlock::BrownMushroomBlock(false, false, true, true, false, true).ID: return 4555; case BrownMushroomBlock::BrownMushroomBlock(false, false, true, true, false, false).ID: return 4556; case BrownMushroomBlock::BrownMushroomBlock(false, false, true, false, true, true).ID: return 4557; case BrownMushroomBlock::BrownMushroomBlock(false, false, true, false, true, false).ID: return 4558; case BrownMushroomBlock::BrownMushroomBlock(false, false, true, false, false, true).ID: return 4559; case BrownMushroomBlock::BrownMushroomBlock(false, false, true, false, false, false).ID: return 4560; case BrownMushroomBlock::BrownMushroomBlock(false, false, false, true, true, true).ID: return 4561; case BrownMushroomBlock::BrownMushroomBlock(false, false, false, true, true, false).ID: return 4562; case BrownMushroomBlock::BrownMushroomBlock(false, false, false, true, false, true).ID: return 4563; case BrownMushroomBlock::BrownMushroomBlock(false, false, false, true, false, false).ID: return 4564; case BrownMushroomBlock::BrownMushroomBlock(false, false, false, false, true, true).ID: return 4565; case BrownMushroomBlock::BrownMushroomBlock(false, false, false, false, true, false).ID: return 4566; case BrownMushroomBlock::BrownMushroomBlock(false, false, false, false, false, true).ID: return 4567; case BrownMushroomBlock::BrownMushroomBlock(false, false, false, false, false, false).ID: return 4568; case BrownShulkerBox::BrownShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 9350; case BrownShulkerBox::BrownShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 9351; case BrownShulkerBox::BrownShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 9352; case BrownShulkerBox::BrownShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 9353; case BrownShulkerBox::BrownShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 9354; case BrownShulkerBox::BrownShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 9355; case BrownStainedGlass::BrownStainedGlass().ID: return 4107; case BrownStainedGlassPane::BrownStainedGlassPane(true, true, true, true).ID: return 7249; case BrownStainedGlassPane::BrownStainedGlassPane(true, true, true, false).ID: return 7250; case BrownStainedGlassPane::BrownStainedGlassPane(true, true, false, true).ID: return 7253; case BrownStainedGlassPane::BrownStainedGlassPane(true, true, false, false).ID: return 7254; case BrownStainedGlassPane::BrownStainedGlassPane(true, false, true, true).ID: return 7257; case BrownStainedGlassPane::BrownStainedGlassPane(true, false, true, false).ID: return 7258; case BrownStainedGlassPane::BrownStainedGlassPane(true, false, false, true).ID: return 7261; case BrownStainedGlassPane::BrownStainedGlassPane(true, false, false, false).ID: return 7262; case BrownStainedGlassPane::BrownStainedGlassPane(false, true, true, true).ID: return 7265; case BrownStainedGlassPane::BrownStainedGlassPane(false, true, true, false).ID: return 7266; case BrownStainedGlassPane::BrownStainedGlassPane(false, true, false, true).ID: return 7269; case BrownStainedGlassPane::BrownStainedGlassPane(false, true, false, false).ID: return 7270; case BrownStainedGlassPane::BrownStainedGlassPane(false, false, true, true).ID: return 7273; case BrownStainedGlassPane::BrownStainedGlassPane(false, false, true, false).ID: return 7274; case BrownStainedGlassPane::BrownStainedGlassPane(false, false, false, true).ID: return 7277; case BrownStainedGlassPane::BrownStainedGlassPane(false, false, false, false).ID: return 7278; case BrownTerracotta::BrownTerracotta().ID: return 6859; case BrownWallBanner::BrownWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 8201; case BrownWallBanner::BrownWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 8202; case BrownWallBanner::BrownWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 8203; case BrownWallBanner::BrownWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 8204; case BrownWool::BrownWool().ID: return 1396; case BubbleColumn::BubbleColumn(true).ID: return 9667; case BubbleColumn::BubbleColumn(false).ID: return 9668; case BubbleCoral::BubbleCoral().ID: return 9535; case BubbleCoralBlock::BubbleCoralBlock().ID: return 9517; case BubbleCoralFan::BubbleCoralFan().ID: return 9555; case BubbleCoralWallFan::BubbleCoralWallFan(eBlockFace::BLOCK_FACE_ZM).ID: return 9617; case BubbleCoralWallFan::BubbleCoralWallFan(eBlockFace::BLOCK_FACE_ZP).ID: return 9619; case BubbleCoralWallFan::BubbleCoralWallFan(eBlockFace::BLOCK_FACE_XM).ID: return 9621; case BubbleCoralWallFan::BubbleCoralWallFan(eBlockFace::BLOCK_FACE_XP).ID: return 9623; case Cactus::Cactus(0).ID: return 3931; case Cactus::Cactus(1).ID: return 3932; case Cactus::Cactus(2).ID: return 3933; case Cactus::Cactus(3).ID: return 3934; case Cactus::Cactus(4).ID: return 3935; case Cactus::Cactus(5).ID: return 3936; case Cactus::Cactus(6).ID: return 3937; case Cactus::Cactus(7).ID: return 3938; case Cactus::Cactus(8).ID: return 3939; case Cactus::Cactus(9).ID: return 3940; case Cactus::Cactus(10).ID: return 3941; case Cactus::Cactus(11).ID: return 3942; case Cactus::Cactus(12).ID: return 3943; case Cactus::Cactus(13).ID: return 3944; case Cactus::Cactus(14).ID: return 3945; case Cactus::Cactus(15).ID: return 3946; case Cake::Cake(0).ID: return 4024; case Cake::Cake(1).ID: return 4025; case Cake::Cake(2).ID: return 4026; case Cake::Cake(3).ID: return 4027; case Cake::Cake(4).ID: return 4028; case Cake::Cake(5).ID: return 4029; case Cake::Cake(6).ID: return 4030; case Campfire::Campfire(eBlockFace::BLOCK_FACE_ZM, true, true).ID: return 14891; case Campfire::Campfire(eBlockFace::BLOCK_FACE_ZM, true, false).ID: return 14893; case Campfire::Campfire(eBlockFace::BLOCK_FACE_ZM, false, true).ID: return 14895; case Campfire::Campfire(eBlockFace::BLOCK_FACE_ZM, false, false).ID: return 14897; case Campfire::Campfire(eBlockFace::BLOCK_FACE_ZP, true, true).ID: return 14899; case Campfire::Campfire(eBlockFace::BLOCK_FACE_ZP, true, false).ID: return 14901; case Campfire::Campfire(eBlockFace::BLOCK_FACE_ZP, false, true).ID: return 14903; case Campfire::Campfire(eBlockFace::BLOCK_FACE_ZP, false, false).ID: return 14905; case Campfire::Campfire(eBlockFace::BLOCK_FACE_XM, true, true).ID: return 14907; case Campfire::Campfire(eBlockFace::BLOCK_FACE_XM, true, false).ID: return 14909; case Campfire::Campfire(eBlockFace::BLOCK_FACE_XM, false, true).ID: return 14911; case Campfire::Campfire(eBlockFace::BLOCK_FACE_XM, false, false).ID: return 14913; case Campfire::Campfire(eBlockFace::BLOCK_FACE_XP, true, true).ID: return 14915; case Campfire::Campfire(eBlockFace::BLOCK_FACE_XP, true, false).ID: return 14917; case Campfire::Campfire(eBlockFace::BLOCK_FACE_XP, false, true).ID: return 14919; case Campfire::Campfire(eBlockFace::BLOCK_FACE_XP, false, false).ID: return 14921; case Carrots::Carrots(0).ID: return 6330; case Carrots::Carrots(1).ID: return 6331; case Carrots::Carrots(2).ID: return 6332; case Carrots::Carrots(3).ID: return 6333; case Carrots::Carrots(4).ID: return 6334; case Carrots::Carrots(5).ID: return 6335; case Carrots::Carrots(6).ID: return 6336; case Carrots::Carrots(7).ID: return 6337; case CartographyTable::CartographyTable().ID: return 14819; case CarvedPumpkin::CarvedPumpkin(eBlockFace::BLOCK_FACE_ZM).ID: return 4016; case CarvedPumpkin::CarvedPumpkin(eBlockFace::BLOCK_FACE_ZP).ID: return 4017; case CarvedPumpkin::CarvedPumpkin(eBlockFace::BLOCK_FACE_XM).ID: return 4018; case CarvedPumpkin::CarvedPumpkin(eBlockFace::BLOCK_FACE_XP).ID: return 4019; case Cauldron::Cauldron(0).ID: return 5141; case Cauldron::Cauldron(1).ID: return 5142; case Cauldron::Cauldron(2).ID: return 5143; case Cauldron::Cauldron(3).ID: return 5144; case CaveAir::CaveAir().ID: return 9666; case Chain::Chain().ID: return 4730; case ChainCommandBlock::ChainCommandBlock(true, eBlockFace::BLOCK_FACE_ZM).ID: return 9237; case ChainCommandBlock::ChainCommandBlock(true, eBlockFace::BLOCK_FACE_XP).ID: return 9238; case ChainCommandBlock::ChainCommandBlock(true, eBlockFace::BLOCK_FACE_ZP).ID: return 9239; case ChainCommandBlock::ChainCommandBlock(true, eBlockFace::BLOCK_FACE_XM).ID: return 9240; case ChainCommandBlock::ChainCommandBlock(true, eBlockFace::BLOCK_FACE_YP).ID: return 9241; case ChainCommandBlock::ChainCommandBlock(true, eBlockFace::BLOCK_FACE_YM).ID: return 9242; case ChainCommandBlock::ChainCommandBlock(false, eBlockFace::BLOCK_FACE_ZM).ID: return 9243; case ChainCommandBlock::ChainCommandBlock(false, eBlockFace::BLOCK_FACE_XP).ID: return 9244; case ChainCommandBlock::ChainCommandBlock(false, eBlockFace::BLOCK_FACE_ZP).ID: return 9245; case ChainCommandBlock::ChainCommandBlock(false, eBlockFace::BLOCK_FACE_XM).ID: return 9246; case ChainCommandBlock::ChainCommandBlock(false, eBlockFace::BLOCK_FACE_YP).ID: return 9247; case ChainCommandBlock::ChainCommandBlock(false, eBlockFace::BLOCK_FACE_YM).ID: return 9248; case Chest::Chest(eBlockFace::BLOCK_FACE_ZM, Chest::Type::Single).ID: return 2035; case Chest::Chest(eBlockFace::BLOCK_FACE_ZM, Chest::Type::Left).ID: return 2037; case Chest::Chest(eBlockFace::BLOCK_FACE_ZM, Chest::Type::Right).ID: return 2039; case Chest::Chest(eBlockFace::BLOCK_FACE_ZP, Chest::Type::Single).ID: return 2041; case Chest::Chest(eBlockFace::BLOCK_FACE_ZP, Chest::Type::Left).ID: return 2043; case Chest::Chest(eBlockFace::BLOCK_FACE_ZP, Chest::Type::Right).ID: return 2045; case Chest::Chest(eBlockFace::BLOCK_FACE_XM, Chest::Type::Single).ID: return 2047; case Chest::Chest(eBlockFace::BLOCK_FACE_XM, Chest::Type::Left).ID: return 2049; case Chest::Chest(eBlockFace::BLOCK_FACE_XM, Chest::Type::Right).ID: return 2051; case Chest::Chest(eBlockFace::BLOCK_FACE_XP, Chest::Type::Single).ID: return 2053; case Chest::Chest(eBlockFace::BLOCK_FACE_XP, Chest::Type::Left).ID: return 2055; case Chest::Chest(eBlockFace::BLOCK_FACE_XP, Chest::Type::Right).ID: return 2057; case ChippedAnvil::ChippedAnvil(eBlockFace::BLOCK_FACE_ZM).ID: return 6614; case ChippedAnvil::ChippedAnvil(eBlockFace::BLOCK_FACE_ZP).ID: return 6615; case ChippedAnvil::ChippedAnvil(eBlockFace::BLOCK_FACE_XM).ID: return 6616; case ChippedAnvil::ChippedAnvil(eBlockFace::BLOCK_FACE_XP).ID: return 6617; case ChiseledNetherBricks::ChiseledNetherBricks().ID: return 17101; case ChiseledPolishedBlackstone::ChiseledPolishedBlackstone().ID: return 16253; case ChiseledQuartzBlock::ChiseledQuartzBlock().ID: return 6739; case ChiseledRedSandstone::ChiseledRedSandstone().ID: return 8218; case ChiseledSandstone::ChiseledSandstone().ID: return 247; case ChiseledStoneBricks::ChiseledStoneBricks().ID: return 4498; case ChorusFlower::ChorusFlower(0).ID: return 9128; case ChorusFlower::ChorusFlower(1).ID: return 9129; case ChorusFlower::ChorusFlower(2).ID: return 9130; case ChorusFlower::ChorusFlower(3).ID: return 9131; case ChorusFlower::ChorusFlower(4).ID: return 9132; case ChorusFlower::ChorusFlower(5).ID: return 9133; case ChorusPlant::ChorusPlant(true, true, true, true, true, true).ID: return 9064; case ChorusPlant::ChorusPlant(true, true, true, true, true, false).ID: return 9065; case ChorusPlant::ChorusPlant(true, true, true, true, false, true).ID: return 9066; case ChorusPlant::ChorusPlant(true, true, true, true, false, false).ID: return 9067; case ChorusPlant::ChorusPlant(true, true, true, false, true, true).ID: return 9068; case ChorusPlant::ChorusPlant(true, true, true, false, true, false).ID: return 9069; case ChorusPlant::ChorusPlant(true, true, true, false, false, true).ID: return 9070; case ChorusPlant::ChorusPlant(true, true, true, false, false, false).ID: return 9071; case ChorusPlant::ChorusPlant(true, true, false, true, true, true).ID: return 9072; case ChorusPlant::ChorusPlant(true, true, false, true, true, false).ID: return 9073; case ChorusPlant::ChorusPlant(true, true, false, true, false, true).ID: return 9074; case ChorusPlant::ChorusPlant(true, true, false, true, false, false).ID: return 9075; case ChorusPlant::ChorusPlant(true, true, false, false, true, true).ID: return 9076; case ChorusPlant::ChorusPlant(true, true, false, false, true, false).ID: return 9077; case ChorusPlant::ChorusPlant(true, true, false, false, false, true).ID: return 9078; case ChorusPlant::ChorusPlant(true, true, false, false, false, false).ID: return 9079; case ChorusPlant::ChorusPlant(true, false, true, true, true, true).ID: return 9080; case ChorusPlant::ChorusPlant(true, false, true, true, true, false).ID: return 9081; case ChorusPlant::ChorusPlant(true, false, true, true, false, true).ID: return 9082; case ChorusPlant::ChorusPlant(true, false, true, true, false, false).ID: return 9083; case ChorusPlant::ChorusPlant(true, false, true, false, true, true).ID: return 9084; case ChorusPlant::ChorusPlant(true, false, true, false, true, false).ID: return 9085; case ChorusPlant::ChorusPlant(true, false, true, false, false, true).ID: return 9086; case ChorusPlant::ChorusPlant(true, false, true, false, false, false).ID: return 9087; case ChorusPlant::ChorusPlant(true, false, false, true, true, true).ID: return 9088; case ChorusPlant::ChorusPlant(true, false, false, true, true, false).ID: return 9089; case ChorusPlant::ChorusPlant(true, false, false, true, false, true).ID: return 9090; case ChorusPlant::ChorusPlant(true, false, false, true, false, false).ID: return 9091; case ChorusPlant::ChorusPlant(true, false, false, false, true, true).ID: return 9092; case ChorusPlant::ChorusPlant(true, false, false, false, true, false).ID: return 9093; case ChorusPlant::ChorusPlant(true, false, false, false, false, true).ID: return 9094; case ChorusPlant::ChorusPlant(true, false, false, false, false, false).ID: return 9095; case ChorusPlant::ChorusPlant(false, true, true, true, true, true).ID: return 9096; case ChorusPlant::ChorusPlant(false, true, true, true, true, false).ID: return 9097; case ChorusPlant::ChorusPlant(false, true, true, true, false, true).ID: return 9098; case ChorusPlant::ChorusPlant(false, true, true, true, false, false).ID: return 9099; case ChorusPlant::ChorusPlant(false, true, true, false, true, true).ID: return 9100; case ChorusPlant::ChorusPlant(false, true, true, false, true, false).ID: return 9101; case ChorusPlant::ChorusPlant(false, true, true, false, false, true).ID: return 9102; case ChorusPlant::ChorusPlant(false, true, true, false, false, false).ID: return 9103; case ChorusPlant::ChorusPlant(false, true, false, true, true, true).ID: return 9104; case ChorusPlant::ChorusPlant(false, true, false, true, true, false).ID: return 9105; case ChorusPlant::ChorusPlant(false, true, false, true, false, true).ID: return 9106; case ChorusPlant::ChorusPlant(false, true, false, true, false, false).ID: return 9107; case ChorusPlant::ChorusPlant(false, true, false, false, true, true).ID: return 9108; case ChorusPlant::ChorusPlant(false, true, false, false, true, false).ID: return 9109; case ChorusPlant::ChorusPlant(false, true, false, false, false, true).ID: return 9110; case ChorusPlant::ChorusPlant(false, true, false, false, false, false).ID: return 9111; case ChorusPlant::ChorusPlant(false, false, true, true, true, true).ID: return 9112; case ChorusPlant::ChorusPlant(false, false, true, true, true, false).ID: return 9113; case ChorusPlant::ChorusPlant(false, false, true, true, false, true).ID: return 9114; case ChorusPlant::ChorusPlant(false, false, true, true, false, false).ID: return 9115; case ChorusPlant::ChorusPlant(false, false, true, false, true, true).ID: return 9116; case ChorusPlant::ChorusPlant(false, false, true, false, true, false).ID: return 9117; case ChorusPlant::ChorusPlant(false, false, true, false, false, true).ID: return 9118; case ChorusPlant::ChorusPlant(false, false, true, false, false, false).ID: return 9119; case ChorusPlant::ChorusPlant(false, false, false, true, true, true).ID: return 9120; case ChorusPlant::ChorusPlant(false, false, false, true, true, false).ID: return 9121; case ChorusPlant::ChorusPlant(false, false, false, true, false, true).ID: return 9122; case ChorusPlant::ChorusPlant(false, false, false, true, false, false).ID: return 9123; case ChorusPlant::ChorusPlant(false, false, false, false, true, true).ID: return 9124; case ChorusPlant::ChorusPlant(false, false, false, false, true, false).ID: return 9125; case ChorusPlant::ChorusPlant(false, false, false, false, false, true).ID: return 9126; case ChorusPlant::ChorusPlant(false, false, false, false, false, false).ID: return 9127; case Clay::Clay().ID: return 3947; case CoalBlock::CoalBlock().ID: return 7883; case CoalOre::CoalOre().ID: return 71; case CoarseDirt::CoarseDirt().ID: return 11; case Cobblestone::Cobblestone().ID: return 14; case CobblestoneSlab::CobblestoneSlab(CobblestoneSlab::Type::Top).ID: return 8367; case CobblestoneSlab::CobblestoneSlab(CobblestoneSlab::Type::Bottom).ID: return 8369; case CobblestoneSlab::CobblestoneSlab(CobblestoneSlab::Type::Double).ID: return 8371; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::Straight).ID: return 3656; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::InnerLeft).ID: return 3658; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::InnerRight).ID: return 3660; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::OuterLeft).ID: return 3662; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::OuterRight).ID: return 3664; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::Straight).ID: return 3666; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::InnerLeft).ID: return 3668; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::InnerRight).ID: return 3670; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::OuterLeft).ID: return 3672; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::OuterRight).ID: return 3674; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::Straight).ID: return 3676; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::InnerLeft).ID: return 3678; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::InnerRight).ID: return 3680; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::OuterLeft).ID: return 3682; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::OuterRight).ID: return 3684; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::Straight).ID: return 3686; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::InnerLeft).ID: return 3688; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::InnerRight).ID: return 3690; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::OuterLeft).ID: return 3692; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::OuterRight).ID: return 3694; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XM, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::Straight).ID: return 3696; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XM, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::InnerLeft).ID: return 3698; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XM, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::InnerRight).ID: return 3700; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XM, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::OuterLeft).ID: return 3702; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XM, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::OuterRight).ID: return 3704; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XM, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::Straight).ID: return 3706; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XM, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::InnerLeft).ID: return 3708; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XM, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::InnerRight).ID: return 3710; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XM, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::OuterLeft).ID: return 3712; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XM, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::OuterRight).ID: return 3714; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XP, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::Straight).ID: return 3716; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XP, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::InnerLeft).ID: return 3718; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XP, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::InnerRight).ID: return 3720; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XP, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::OuterLeft).ID: return 3722; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XP, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::OuterRight).ID: return 3724; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XP, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::Straight).ID: return 3726; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XP, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::InnerLeft).ID: return 3728; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XP, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::InnerRight).ID: return 3730; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XP, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::OuterLeft).ID: return 3732; case CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XP, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::OuterRight).ID: return 3734; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::None, CobblestoneWall::South::None, true, CobblestoneWall::West::None).ID: return 5660; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::None, CobblestoneWall::South::None, true, CobblestoneWall::West::Low).ID: return 5661; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::None, CobblestoneWall::South::None, true, CobblestoneWall::West::Tall).ID: return 5662; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::None, CobblestoneWall::South::None, false, CobblestoneWall::West::None).ID: return 5666; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::None, CobblestoneWall::South::None, false, CobblestoneWall::West::Low).ID: return 5667; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::None, CobblestoneWall::South::None, false, CobblestoneWall::West::Tall).ID: return 5668; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::None, CobblestoneWall::South::Low, true, CobblestoneWall::West::None).ID: return 5672; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::None, CobblestoneWall::South::Low, true, CobblestoneWall::West::Low).ID: return 5673; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::None, CobblestoneWall::South::Low, true, CobblestoneWall::West::Tall).ID: return 5674; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::None, CobblestoneWall::South::Low, false, CobblestoneWall::West::None).ID: return 5678; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::None, CobblestoneWall::South::Low, false, CobblestoneWall::West::Low).ID: return 5679; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::None, CobblestoneWall::South::Low, false, CobblestoneWall::West::Tall).ID: return 5680; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::None, CobblestoneWall::South::Tall, true, CobblestoneWall::West::None).ID: return 5684; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::None, CobblestoneWall::South::Tall, true, CobblestoneWall::West::Low).ID: return 5685; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::None, CobblestoneWall::South::Tall, true, CobblestoneWall::West::Tall).ID: return 5686; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::None, CobblestoneWall::South::Tall, false, CobblestoneWall::West::None).ID: return 5690; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::None, CobblestoneWall::South::Tall, false, CobblestoneWall::West::Low).ID: return 5691; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::None, CobblestoneWall::South::Tall, false, CobblestoneWall::West::Tall).ID: return 5692; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::Low, CobblestoneWall::South::None, true, CobblestoneWall::West::None).ID: return 5696; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::Low, CobblestoneWall::South::None, true, CobblestoneWall::West::Low).ID: return 5697; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::Low, CobblestoneWall::South::None, true, CobblestoneWall::West::Tall).ID: return 5698; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::Low, CobblestoneWall::South::None, false, CobblestoneWall::West::None).ID: return 5702; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::Low, CobblestoneWall::South::None, false, CobblestoneWall::West::Low).ID: return 5703; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::Low, CobblestoneWall::South::None, false, CobblestoneWall::West::Tall).ID: return 5704; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::Low, CobblestoneWall::South::Low, true, CobblestoneWall::West::None).ID: return 5708; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::Low, CobblestoneWall::South::Low, true, CobblestoneWall::West::Low).ID: return 5709; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::Low, CobblestoneWall::South::Low, true, CobblestoneWall::West::Tall).ID: return 5710; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::Low, CobblestoneWall::South::Low, false, CobblestoneWall::West::None).ID: return 5714; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::Low, CobblestoneWall::South::Low, false, CobblestoneWall::West::Low).ID: return 5715; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::Low, CobblestoneWall::South::Low, false, CobblestoneWall::West::Tall).ID: return 5716; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::Low, CobblestoneWall::South::Tall, true, CobblestoneWall::West::None).ID: return 5720; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::Low, CobblestoneWall::South::Tall, true, CobblestoneWall::West::Low).ID: return 5721; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::Low, CobblestoneWall::South::Tall, true, CobblestoneWall::West::Tall).ID: return 5722; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::Low, CobblestoneWall::South::Tall, false, CobblestoneWall::West::None).ID: return 5726; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::Low, CobblestoneWall::South::Tall, false, CobblestoneWall::West::Low).ID: return 5727; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::Low, CobblestoneWall::South::Tall, false, CobblestoneWall::West::Tall).ID: return 5728; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::Tall, CobblestoneWall::South::None, true, CobblestoneWall::West::None).ID: return 5732; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::Tall, CobblestoneWall::South::None, true, CobblestoneWall::West::Low).ID: return 5733; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::Tall, CobblestoneWall::South::None, true, CobblestoneWall::West::Tall).ID: return 5734; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::Tall, CobblestoneWall::South::None, false, CobblestoneWall::West::None).ID: return 5738; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::Tall, CobblestoneWall::South::None, false, CobblestoneWall::West::Low).ID: return 5739; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::Tall, CobblestoneWall::South::None, false, CobblestoneWall::West::Tall).ID: return 5740; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::Tall, CobblestoneWall::South::Low, true, CobblestoneWall::West::None).ID: return 5744; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::Tall, CobblestoneWall::South::Low, true, CobblestoneWall::West::Low).ID: return 5745; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::Tall, CobblestoneWall::South::Low, true, CobblestoneWall::West::Tall).ID: return 5746; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::Tall, CobblestoneWall::South::Low, false, CobblestoneWall::West::None).ID: return 5750; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::Tall, CobblestoneWall::South::Low, false, CobblestoneWall::West::Low).ID: return 5751; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::Tall, CobblestoneWall::South::Low, false, CobblestoneWall::West::Tall).ID: return 5752; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::Tall, CobblestoneWall::South::Tall, true, CobblestoneWall::West::None).ID: return 5756; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::Tall, CobblestoneWall::South::Tall, true, CobblestoneWall::West::Low).ID: return 5757; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::Tall, CobblestoneWall::South::Tall, true, CobblestoneWall::West::Tall).ID: return 5758; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::Tall, CobblestoneWall::South::Tall, false, CobblestoneWall::West::None).ID: return 5762; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::Tall, CobblestoneWall::South::Tall, false, CobblestoneWall::West::Low).ID: return 5763; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::Tall, CobblestoneWall::South::Tall, false, CobblestoneWall::West::Tall).ID: return 5764; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::None, CobblestoneWall::South::None, true, CobblestoneWall::West::None).ID: return 5768; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::None, CobblestoneWall::South::None, true, CobblestoneWall::West::Low).ID: return 5769; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::None, CobblestoneWall::South::None, true, CobblestoneWall::West::Tall).ID: return 5770; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::None, CobblestoneWall::South::None, false, CobblestoneWall::West::None).ID: return 5774; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::None, CobblestoneWall::South::None, false, CobblestoneWall::West::Low).ID: return 5775; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::None, CobblestoneWall::South::None, false, CobblestoneWall::West::Tall).ID: return 5776; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::None, CobblestoneWall::South::Low, true, CobblestoneWall::West::None).ID: return 5780; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::None, CobblestoneWall::South::Low, true, CobblestoneWall::West::Low).ID: return 5781; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::None, CobblestoneWall::South::Low, true, CobblestoneWall::West::Tall).ID: return 5782; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::None, CobblestoneWall::South::Low, false, CobblestoneWall::West::None).ID: return 5786; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::None, CobblestoneWall::South::Low, false, CobblestoneWall::West::Low).ID: return 5787; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::None, CobblestoneWall::South::Low, false, CobblestoneWall::West::Tall).ID: return 5788; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::None, CobblestoneWall::South::Tall, true, CobblestoneWall::West::None).ID: return 5792; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::None, CobblestoneWall::South::Tall, true, CobblestoneWall::West::Low).ID: return 5793; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::None, CobblestoneWall::South::Tall, true, CobblestoneWall::West::Tall).ID: return 5794; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::None, CobblestoneWall::South::Tall, false, CobblestoneWall::West::None).ID: return 5798; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::None, CobblestoneWall::South::Tall, false, CobblestoneWall::West::Low).ID: return 5799; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::None, CobblestoneWall::South::Tall, false, CobblestoneWall::West::Tall).ID: return 5800; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::Low, CobblestoneWall::South::None, true, CobblestoneWall::West::None).ID: return 5804; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::Low, CobblestoneWall::South::None, true, CobblestoneWall::West::Low).ID: return 5805; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::Low, CobblestoneWall::South::None, true, CobblestoneWall::West::Tall).ID: return 5806; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::Low, CobblestoneWall::South::None, false, CobblestoneWall::West::None).ID: return 5810; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::Low, CobblestoneWall::South::None, false, CobblestoneWall::West::Low).ID: return 5811; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::Low, CobblestoneWall::South::None, false, CobblestoneWall::West::Tall).ID: return 5812; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::Low, CobblestoneWall::South::Low, true, CobblestoneWall::West::None).ID: return 5816; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::Low, CobblestoneWall::South::Low, true, CobblestoneWall::West::Low).ID: return 5817; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::Low, CobblestoneWall::South::Low, true, CobblestoneWall::West::Tall).ID: return 5818; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::Low, CobblestoneWall::South::Low, false, CobblestoneWall::West::None).ID: return 5822; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::Low, CobblestoneWall::South::Low, false, CobblestoneWall::West::Low).ID: return 5823; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::Low, CobblestoneWall::South::Low, false, CobblestoneWall::West::Tall).ID: return 5824; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::Low, CobblestoneWall::South::Tall, true, CobblestoneWall::West::None).ID: return 5828; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::Low, CobblestoneWall::South::Tall, true, CobblestoneWall::West::Low).ID: return 5829; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::Low, CobblestoneWall::South::Tall, true, CobblestoneWall::West::Tall).ID: return 5830; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::Low, CobblestoneWall::South::Tall, false, CobblestoneWall::West::None).ID: return 5834; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::Low, CobblestoneWall::South::Tall, false, CobblestoneWall::West::Low).ID: return 5835; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::Low, CobblestoneWall::South::Tall, false, CobblestoneWall::West::Tall).ID: return 5836; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::Tall, CobblestoneWall::South::None, true, CobblestoneWall::West::None).ID: return 5840; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::Tall, CobblestoneWall::South::None, true, CobblestoneWall::West::Low).ID: return 5841; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::Tall, CobblestoneWall::South::None, true, CobblestoneWall::West::Tall).ID: return 5842; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::Tall, CobblestoneWall::South::None, false, CobblestoneWall::West::None).ID: return 5846; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::Tall, CobblestoneWall::South::None, false, CobblestoneWall::West::Low).ID: return 5847; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::Tall, CobblestoneWall::South::None, false, CobblestoneWall::West::Tall).ID: return 5848; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::Tall, CobblestoneWall::South::Low, true, CobblestoneWall::West::None).ID: return 5852; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::Tall, CobblestoneWall::South::Low, true, CobblestoneWall::West::Low).ID: return 5853; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::Tall, CobblestoneWall::South::Low, true, CobblestoneWall::West::Tall).ID: return 5854; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::Tall, CobblestoneWall::South::Low, false, CobblestoneWall::West::None).ID: return 5858; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::Tall, CobblestoneWall::South::Low, false, CobblestoneWall::West::Low).ID: return 5859; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::Tall, CobblestoneWall::South::Low, false, CobblestoneWall::West::Tall).ID: return 5860; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::Tall, CobblestoneWall::South::Tall, true, CobblestoneWall::West::None).ID: return 5864; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::Tall, CobblestoneWall::South::Tall, true, CobblestoneWall::West::Low).ID: return 5865; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::Tall, CobblestoneWall::South::Tall, true, CobblestoneWall::West::Tall).ID: return 5866; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::Tall, CobblestoneWall::South::Tall, false, CobblestoneWall::West::None).ID: return 5870; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::Tall, CobblestoneWall::South::Tall, false, CobblestoneWall::West::Low).ID: return 5871; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Low, CobblestoneWall::North::Tall, CobblestoneWall::South::Tall, false, CobblestoneWall::West::Tall).ID: return 5872; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Tall, CobblestoneWall::North::None, CobblestoneWall::South::None, true, CobblestoneWall::West::None).ID: return 5876; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Tall, CobblestoneWall::North::None, CobblestoneWall::South::None, true, CobblestoneWall::West::Low).ID: return 5877; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Tall, CobblestoneWall::North::None, CobblestoneWall::South::None, true, CobblestoneWall::West::Tall).ID: return 5878; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Tall, CobblestoneWall::North::None, CobblestoneWall::South::None, false, CobblestoneWall::West::None).ID: return 5882; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Tall, CobblestoneWall::North::None, CobblestoneWall::South::None, false, CobblestoneWall::West::Low).ID: return 5883; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Tall, CobblestoneWall::North::None, CobblestoneWall::South::None, false, CobblestoneWall::West::Tall).ID: return 5884; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Tall, CobblestoneWall::North::None, CobblestoneWall::South::Low, true, CobblestoneWall::West::None).ID: return 5888; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Tall, CobblestoneWall::North::None, CobblestoneWall::South::Low, true, CobblestoneWall::West::Low).ID: return 5889; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Tall, CobblestoneWall::North::None, CobblestoneWall::South::Low, true, CobblestoneWall::West::Tall).ID: return 5890; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Tall, CobblestoneWall::North::None, CobblestoneWall::South::Low, false, CobblestoneWall::West::None).ID: return 5894; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Tall, CobblestoneWall::North::None, CobblestoneWall::South::Low, false, CobblestoneWall::West::Low).ID: return 5895; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Tall, CobblestoneWall::North::None, CobblestoneWall::South::Low, false, CobblestoneWall::West::Tall).ID: return 5896; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Tall, CobblestoneWall::North::None, CobblestoneWall::South::Tall, true, CobblestoneWall::West::None).ID: return 5900; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Tall, CobblestoneWall::North::None, CobblestoneWall::South::Tall, true, CobblestoneWall::West::Low).ID: return 5901; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Tall, CobblestoneWall::North::None, CobblestoneWall::South::Tall, true, CobblestoneWall::West::Tall).ID: return 5902; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Tall, CobblestoneWall::North::None, CobblestoneWall::South::Tall, false, CobblestoneWall::West::None).ID: return 5906; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Tall, CobblestoneWall::North::None, CobblestoneWall::South::Tall, false, CobblestoneWall::West::Low).ID: return 5907; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Tall, CobblestoneWall::North::None, CobblestoneWall::South::Tall, false, CobblestoneWall::West::Tall).ID: return 5908; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Tall, CobblestoneWall::North::Low, CobblestoneWall::South::None, true, CobblestoneWall::West::None).ID: return 5912; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Tall, CobblestoneWall::North::Low, CobblestoneWall::South::None, true, CobblestoneWall::West::Low).ID: return 5913; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Tall, CobblestoneWall::North::Low, CobblestoneWall::South::None, true, CobblestoneWall::West::Tall).ID: return 5914; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Tall, CobblestoneWall::North::Low, CobblestoneWall::South::None, false, CobblestoneWall::West::None).ID: return 5918; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Tall, CobblestoneWall::North::Low, CobblestoneWall::South::None, false, CobblestoneWall::West::Low).ID: return 5919; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Tall, CobblestoneWall::North::Low, CobblestoneWall::South::None, false, CobblestoneWall::West::Tall).ID: return 5920; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Tall, CobblestoneWall::North::Low, CobblestoneWall::South::Low, true, CobblestoneWall::West::None).ID: return 5924; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Tall, CobblestoneWall::North::Low, CobblestoneWall::South::Low, true, CobblestoneWall::West::Low).ID: return 5925; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Tall, CobblestoneWall::North::Low, CobblestoneWall::South::Low, true, CobblestoneWall::West::Tall).ID: return 5926; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Tall, CobblestoneWall::North::Low, CobblestoneWall::South::Low, false, CobblestoneWall::West::None).ID: return 5930; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Tall, CobblestoneWall::North::Low, CobblestoneWall::South::Low, false, CobblestoneWall::West::Low).ID: return 5931; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Tall, CobblestoneWall::North::Low, CobblestoneWall::South::Low, false, CobblestoneWall::West::Tall).ID: return 5932; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Tall, CobblestoneWall::North::Low, CobblestoneWall::South::Tall, true, CobblestoneWall::West::None).ID: return 5936; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Tall, CobblestoneWall::North::Low, CobblestoneWall::South::Tall, true, CobblestoneWall::West::Low).ID: return 5937; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Tall, CobblestoneWall::North::Low, CobblestoneWall::South::Tall, true, CobblestoneWall::West::Tall).ID: return 5938; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Tall, CobblestoneWall::North::Low, CobblestoneWall::South::Tall, false, CobblestoneWall::West::None).ID: return 5942; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Tall, CobblestoneWall::North::Low, CobblestoneWall::South::Tall, false, CobblestoneWall::West::Low).ID: return 5943; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Tall, CobblestoneWall::North::Low, CobblestoneWall::South::Tall, false, CobblestoneWall::West::Tall).ID: return 5944; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Tall, CobblestoneWall::North::Tall, CobblestoneWall::South::None, true, CobblestoneWall::West::None).ID: return 5948; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Tall, CobblestoneWall::North::Tall, CobblestoneWall::South::None, true, CobblestoneWall::West::Low).ID: return 5949; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Tall, CobblestoneWall::North::Tall, CobblestoneWall::South::None, true, CobblestoneWall::West::Tall).ID: return 5950; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Tall, CobblestoneWall::North::Tall, CobblestoneWall::South::None, false, CobblestoneWall::West::None).ID: return 5954; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Tall, CobblestoneWall::North::Tall, CobblestoneWall::South::None, false, CobblestoneWall::West::Low).ID: return 5955; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Tall, CobblestoneWall::North::Tall, CobblestoneWall::South::None, false, CobblestoneWall::West::Tall).ID: return 5956; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Tall, CobblestoneWall::North::Tall, CobblestoneWall::South::Low, true, CobblestoneWall::West::None).ID: return 5960; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Tall, CobblestoneWall::North::Tall, CobblestoneWall::South::Low, true, CobblestoneWall::West::Low).ID: return 5961; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Tall, CobblestoneWall::North::Tall, CobblestoneWall::South::Low, true, CobblestoneWall::West::Tall).ID: return 5962; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Tall, CobblestoneWall::North::Tall, CobblestoneWall::South::Low, false, CobblestoneWall::West::None).ID: return 5966; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Tall, CobblestoneWall::North::Tall, CobblestoneWall::South::Low, false, CobblestoneWall::West::Low).ID: return 5967; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Tall, CobblestoneWall::North::Tall, CobblestoneWall::South::Low, false, CobblestoneWall::West::Tall).ID: return 5968; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Tall, CobblestoneWall::North::Tall, CobblestoneWall::South::Tall, true, CobblestoneWall::West::None).ID: return 5972; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Tall, CobblestoneWall::North::Tall, CobblestoneWall::South::Tall, true, CobblestoneWall::West::Low).ID: return 5973; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Tall, CobblestoneWall::North::Tall, CobblestoneWall::South::Tall, true, CobblestoneWall::West::Tall).ID: return 5974; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Tall, CobblestoneWall::North::Tall, CobblestoneWall::South::Tall, false, CobblestoneWall::West::None).ID: return 5978; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Tall, CobblestoneWall::North::Tall, CobblestoneWall::South::Tall, false, CobblestoneWall::West::Low).ID: return 5979; case CobblestoneWall::CobblestoneWall(CobblestoneWall::East::Tall, CobblestoneWall::North::Tall, CobblestoneWall::South::Tall, false, CobblestoneWall::West::Tall).ID: return 5980; case Cobweb::Cobweb().ID: return 1341; case Cocoa::Cocoa(0, eBlockFace::BLOCK_FACE_ZM).ID: return 5158; case Cocoa::Cocoa(0, eBlockFace::BLOCK_FACE_ZP).ID: return 5159; case Cocoa::Cocoa(0, eBlockFace::BLOCK_FACE_XM).ID: return 5160; case Cocoa::Cocoa(0, eBlockFace::BLOCK_FACE_XP).ID: return 5161; case Cocoa::Cocoa(1, eBlockFace::BLOCK_FACE_ZM).ID: return 5162; case Cocoa::Cocoa(1, eBlockFace::BLOCK_FACE_ZP).ID: return 5163; case Cocoa::Cocoa(1, eBlockFace::BLOCK_FACE_XM).ID: return 5164; case Cocoa::Cocoa(1, eBlockFace::BLOCK_FACE_XP).ID: return 5165; case Cocoa::Cocoa(2, eBlockFace::BLOCK_FACE_ZM).ID: return 5166; case Cocoa::Cocoa(2, eBlockFace::BLOCK_FACE_ZP).ID: return 5167; case Cocoa::Cocoa(2, eBlockFace::BLOCK_FACE_XM).ID: return 5168; case Cocoa::Cocoa(2, eBlockFace::BLOCK_FACE_XP).ID: return 5169; case CommandBlock::CommandBlock(true, eBlockFace::BLOCK_FACE_ZM).ID: return 5644; case CommandBlock::CommandBlock(true, eBlockFace::BLOCK_FACE_XP).ID: return 5645; case CommandBlock::CommandBlock(true, eBlockFace::BLOCK_FACE_ZP).ID: return 5646; case CommandBlock::CommandBlock(true, eBlockFace::BLOCK_FACE_XM).ID: return 5647; case CommandBlock::CommandBlock(true, eBlockFace::BLOCK_FACE_YP).ID: return 5648; case CommandBlock::CommandBlock(true, eBlockFace::BLOCK_FACE_YM).ID: return 5649; case CommandBlock::CommandBlock(false, eBlockFace::BLOCK_FACE_ZM).ID: return 5650; case CommandBlock::CommandBlock(false, eBlockFace::BLOCK_FACE_XP).ID: return 5651; case CommandBlock::CommandBlock(false, eBlockFace::BLOCK_FACE_ZP).ID: return 5652; case CommandBlock::CommandBlock(false, eBlockFace::BLOCK_FACE_XM).ID: return 5653; case CommandBlock::CommandBlock(false, eBlockFace::BLOCK_FACE_YP).ID: return 5654; case CommandBlock::CommandBlock(false, eBlockFace::BLOCK_FACE_YM).ID: return 5655; case Comparator::Comparator(eBlockFace::BLOCK_FACE_ZM, Comparator::Mode::Compare, true).ID: return 6678; case Comparator::Comparator(eBlockFace::BLOCK_FACE_ZM, Comparator::Mode::Compare, false).ID: return 6679; case Comparator::Comparator(eBlockFace::BLOCK_FACE_ZM, Comparator::Mode::Subtract, true).ID: return 6680; case Comparator::Comparator(eBlockFace::BLOCK_FACE_ZM, Comparator::Mode::Subtract, false).ID: return 6681; case Comparator::Comparator(eBlockFace::BLOCK_FACE_ZP, Comparator::Mode::Compare, true).ID: return 6682; case Comparator::Comparator(eBlockFace::BLOCK_FACE_ZP, Comparator::Mode::Compare, false).ID: return 6683; case Comparator::Comparator(eBlockFace::BLOCK_FACE_ZP, Comparator::Mode::Subtract, true).ID: return 6684; case Comparator::Comparator(eBlockFace::BLOCK_FACE_ZP, Comparator::Mode::Subtract, false).ID: return 6685; case Comparator::Comparator(eBlockFace::BLOCK_FACE_XM, Comparator::Mode::Compare, true).ID: return 6686; case Comparator::Comparator(eBlockFace::BLOCK_FACE_XM, Comparator::Mode::Compare, false).ID: return 6687; case Comparator::Comparator(eBlockFace::BLOCK_FACE_XM, Comparator::Mode::Subtract, true).ID: return 6688; case Comparator::Comparator(eBlockFace::BLOCK_FACE_XM, Comparator::Mode::Subtract, false).ID: return 6689; case Comparator::Comparator(eBlockFace::BLOCK_FACE_XP, Comparator::Mode::Compare, true).ID: return 6690; case Comparator::Comparator(eBlockFace::BLOCK_FACE_XP, Comparator::Mode::Compare, false).ID: return 6691; case Comparator::Comparator(eBlockFace::BLOCK_FACE_XP, Comparator::Mode::Subtract, true).ID: return 6692; case Comparator::Comparator(eBlockFace::BLOCK_FACE_XP, Comparator::Mode::Subtract, false).ID: return 6693; case Composter::Composter(0).ID: return 15751; case Composter::Composter(1).ID: return 15752; case Composter::Composter(2).ID: return 15753; case Composter::Composter(3).ID: return 15754; case Composter::Composter(4).ID: return 15755; case Composter::Composter(5).ID: return 15756; case Composter::Composter(6).ID: return 15757; case Composter::Composter(7).ID: return 15758; case Composter::Composter(8).ID: return 15759; case Conduit::Conduit().ID: return 9650; case Cornflower::Cornflower().ID: return 1422; case CrackedNetherBricks::CrackedNetherBricks().ID: return 17102; case CrackedPolishedBlackstoneBricks::CrackedPolishedBlackstoneBricks().ID: return 16252; case CrackedStoneBricks::CrackedStoneBricks().ID: return 4497; case CraftingTable::CraftingTable().ID: return 3356; case CreeperHead::CreeperHead(0).ID: return 6570; case CreeperHead::CreeperHead(1).ID: return 6571; case CreeperHead::CreeperHead(2).ID: return 6572; case CreeperHead::CreeperHead(3).ID: return 6573; case CreeperHead::CreeperHead(4).ID: return 6574; case CreeperHead::CreeperHead(5).ID: return 6575; case CreeperHead::CreeperHead(6).ID: return 6576; case CreeperHead::CreeperHead(7).ID: return 6577; case CreeperHead::CreeperHead(8).ID: return 6578; case CreeperHead::CreeperHead(9).ID: return 6579; case CreeperHead::CreeperHead(10).ID: return 6580; case CreeperHead::CreeperHead(11).ID: return 6581; case CreeperHead::CreeperHead(12).ID: return 6582; case CreeperHead::CreeperHead(13).ID: return 6583; case CreeperHead::CreeperHead(14).ID: return 6584; case CreeperHead::CreeperHead(15).ID: return 6585; case CreeperWallHead::CreeperWallHead(eBlockFace::BLOCK_FACE_ZM).ID: return 6586; case CreeperWallHead::CreeperWallHead(eBlockFace::BLOCK_FACE_ZP).ID: return 6587; case CreeperWallHead::CreeperWallHead(eBlockFace::BLOCK_FACE_XM).ID: return 6588; case CreeperWallHead::CreeperWallHead(eBlockFace::BLOCK_FACE_XP).ID: return 6589; case CrimsonButton::CrimsonButton(CrimsonButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, true).ID: return 15479; case CrimsonButton::CrimsonButton(CrimsonButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, false).ID: return 15480; case CrimsonButton::CrimsonButton(CrimsonButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, true).ID: return 15481; case CrimsonButton::CrimsonButton(CrimsonButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, false).ID: return 15482; case CrimsonButton::CrimsonButton(CrimsonButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, true).ID: return 15483; case CrimsonButton::CrimsonButton(CrimsonButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, false).ID: return 15484; case CrimsonButton::CrimsonButton(CrimsonButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, true).ID: return 15485; case CrimsonButton::CrimsonButton(CrimsonButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, false).ID: return 15486; case CrimsonButton::CrimsonButton(CrimsonButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, true).ID: return 15487; case CrimsonButton::CrimsonButton(CrimsonButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, false).ID: return 15488; case CrimsonButton::CrimsonButton(CrimsonButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, true).ID: return 15489; case CrimsonButton::CrimsonButton(CrimsonButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, false).ID: return 15490; case CrimsonButton::CrimsonButton(CrimsonButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, true).ID: return 15491; case CrimsonButton::CrimsonButton(CrimsonButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, false).ID: return 15492; case CrimsonButton::CrimsonButton(CrimsonButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, true).ID: return 15493; case CrimsonButton::CrimsonButton(CrimsonButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, false).ID: return 15494; case CrimsonButton::CrimsonButton(CrimsonButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, true).ID: return 15495; case CrimsonButton::CrimsonButton(CrimsonButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, false).ID: return 15496; case CrimsonButton::CrimsonButton(CrimsonButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, true).ID: return 15497; case CrimsonButton::CrimsonButton(CrimsonButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, false).ID: return 15498; case CrimsonButton::CrimsonButton(CrimsonButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, true).ID: return 15499; case CrimsonButton::CrimsonButton(CrimsonButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, false).ID: return 15500; case CrimsonButton::CrimsonButton(CrimsonButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, true).ID: return 15501; case CrimsonButton::CrimsonButton(CrimsonButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, false).ID: return 15502; case CrimsonDoor::CrimsonDoor(eBlockFace::BLOCK_FACE_ZM, CrimsonDoor::Half::Upper, CrimsonDoor::Hinge::Left, true, true).ID: return 15527; case CrimsonDoor::CrimsonDoor(eBlockFace::BLOCK_FACE_ZM, CrimsonDoor::Half::Upper, CrimsonDoor::Hinge::Left, true, false).ID: return 15528; case CrimsonDoor::CrimsonDoor(eBlockFace::BLOCK_FACE_ZM, CrimsonDoor::Half::Upper, CrimsonDoor::Hinge::Left, false, true).ID: return 15529; case CrimsonDoor::CrimsonDoor(eBlockFace::BLOCK_FACE_ZM, CrimsonDoor::Half::Upper, CrimsonDoor::Hinge::Left, false, false).ID: return 15530; case CrimsonDoor::CrimsonDoor(eBlockFace::BLOCK_FACE_ZM, CrimsonDoor::Half::Upper, CrimsonDoor::Hinge::Right, true, true).ID: return 15531; case CrimsonDoor::CrimsonDoor(eBlockFace::BLOCK_FACE_ZM, CrimsonDoor::Half::Upper, CrimsonDoor::Hinge::Right, true, false).ID: return 15532; case CrimsonDoor::CrimsonDoor(eBlockFace::BLOCK_FACE_ZM, CrimsonDoor::Half::Upper, CrimsonDoor::Hinge::Right, false, true).ID: return 15533; case CrimsonDoor::CrimsonDoor(eBlockFace::BLOCK_FACE_ZM, CrimsonDoor::Half::Upper, CrimsonDoor::Hinge::Right, false, false).ID: return 15534; case CrimsonDoor::CrimsonDoor(eBlockFace::BLOCK_FACE_ZM, CrimsonDoor::Half::Lower, CrimsonDoor::Hinge::Left, true, true).ID: return 15535; case CrimsonDoor::CrimsonDoor(eBlockFace::BLOCK_FACE_ZM, CrimsonDoor::Half::Lower, CrimsonDoor::Hinge::Left, true, false).ID: return 15536; case CrimsonDoor::CrimsonDoor(eBlockFace::BLOCK_FACE_ZM, CrimsonDoor::Half::Lower, CrimsonDoor::Hinge::Left, false, true).ID: return 15537; case CrimsonDoor::CrimsonDoor(eBlockFace::BLOCK_FACE_ZM, CrimsonDoor::Half::Lower, CrimsonDoor::Hinge::Left, false, false).ID: return 15538; case CrimsonDoor::CrimsonDoor(eBlockFace::BLOCK_FACE_ZM, CrimsonDoor::Half::Lower, CrimsonDoor::Hinge::Right, true, true).ID: return 15539; case CrimsonDoor::CrimsonDoor(eBlockFace::BLOCK_FACE_ZM, CrimsonDoor::Half::Lower, CrimsonDoor::Hinge::Right, true, false).ID: return 15540; case CrimsonDoor::CrimsonDoor(eBlockFace::BLOCK_FACE_ZM, CrimsonDoor::Half::Lower, CrimsonDoor::Hinge::Right, false, true).ID: return 15541; case CrimsonDoor::CrimsonDoor(eBlockFace::BLOCK_FACE_ZM, CrimsonDoor::Half::Lower, CrimsonDoor::Hinge::Right, false, false).ID: return 15542; case CrimsonDoor::CrimsonDoor(eBlockFace::BLOCK_FACE_ZP, CrimsonDoor::Half::Upper, CrimsonDoor::Hinge::Left, true, true).ID: return 15543; case CrimsonDoor::CrimsonDoor(eBlockFace::BLOCK_FACE_ZP, CrimsonDoor::Half::Upper, CrimsonDoor::Hinge::Left, true, false).ID: return 15544; case CrimsonDoor::CrimsonDoor(eBlockFace::BLOCK_FACE_ZP, CrimsonDoor::Half::Upper, CrimsonDoor::Hinge::Left, false, true).ID: return 15545; case CrimsonDoor::CrimsonDoor(eBlockFace::BLOCK_FACE_ZP, CrimsonDoor::Half::Upper, CrimsonDoor::Hinge::Left, false, false).ID: return 15546; case CrimsonDoor::CrimsonDoor(eBlockFace::BLOCK_FACE_ZP, CrimsonDoor::Half::Upper, CrimsonDoor::Hinge::Right, true, true).ID: return 15547; case CrimsonDoor::CrimsonDoor(eBlockFace::BLOCK_FACE_ZP, CrimsonDoor::Half::Upper, CrimsonDoor::Hinge::Right, true, false).ID: return 15548; case CrimsonDoor::CrimsonDoor(eBlockFace::BLOCK_FACE_ZP, CrimsonDoor::Half::Upper, CrimsonDoor::Hinge::Right, false, true).ID: return 15549; case CrimsonDoor::CrimsonDoor(eBlockFace::BLOCK_FACE_ZP, CrimsonDoor::Half::Upper, CrimsonDoor::Hinge::Right, false, false).ID: return 15550; case CrimsonDoor::CrimsonDoor(eBlockFace::BLOCK_FACE_ZP, CrimsonDoor::Half::Lower, CrimsonDoor::Hinge::Left, true, true).ID: return 15551; case CrimsonDoor::CrimsonDoor(eBlockFace::BLOCK_FACE_ZP, CrimsonDoor::Half::Lower, CrimsonDoor::Hinge::Left, true, false).ID: return 15552; case CrimsonDoor::CrimsonDoor(eBlockFace::BLOCK_FACE_ZP, CrimsonDoor::Half::Lower, CrimsonDoor::Hinge::Left, false, true).ID: return 15553; case CrimsonDoor::CrimsonDoor(eBlockFace::BLOCK_FACE_ZP, CrimsonDoor::Half::Lower, CrimsonDoor::Hinge::Left, false, false).ID: return 15554; case CrimsonDoor::CrimsonDoor(eBlockFace::BLOCK_FACE_ZP, CrimsonDoor::Half::Lower, CrimsonDoor::Hinge::Right, true, true).ID: return 15555; case CrimsonDoor::CrimsonDoor(eBlockFace::BLOCK_FACE_ZP, CrimsonDoor::Half::Lower, CrimsonDoor::Hinge::Right, true, false).ID: return 15556; case CrimsonDoor::CrimsonDoor(eBlockFace::BLOCK_FACE_ZP, CrimsonDoor::Half::Lower, CrimsonDoor::Hinge::Right, false, true).ID: return 15557; case CrimsonDoor::CrimsonDoor(eBlockFace::BLOCK_FACE_ZP, CrimsonDoor::Half::Lower, CrimsonDoor::Hinge::Right, false, false).ID: return 15558; case CrimsonDoor::CrimsonDoor(eBlockFace::BLOCK_FACE_XM, CrimsonDoor::Half::Upper, CrimsonDoor::Hinge::Left, true, true).ID: return 15559; case CrimsonDoor::CrimsonDoor(eBlockFace::BLOCK_FACE_XM, CrimsonDoor::Half::Upper, CrimsonDoor::Hinge::Left, true, false).ID: return 15560; case CrimsonDoor::CrimsonDoor(eBlockFace::BLOCK_FACE_XM, CrimsonDoor::Half::Upper, CrimsonDoor::Hinge::Left, false, true).ID: return 15561; case CrimsonDoor::CrimsonDoor(eBlockFace::BLOCK_FACE_XM, CrimsonDoor::Half::Upper, CrimsonDoor::Hinge::Left, false, false).ID: return 15562; case CrimsonDoor::CrimsonDoor(eBlockFace::BLOCK_FACE_XM, CrimsonDoor::Half::Upper, CrimsonDoor::Hinge::Right, true, true).ID: return 15563; case CrimsonDoor::CrimsonDoor(eBlockFace::BLOCK_FACE_XM, CrimsonDoor::Half::Upper, CrimsonDoor::Hinge::Right, true, false).ID: return 15564; case CrimsonDoor::CrimsonDoor(eBlockFace::BLOCK_FACE_XM, CrimsonDoor::Half::Upper, CrimsonDoor::Hinge::Right, false, true).ID: return 15565; case CrimsonDoor::CrimsonDoor(eBlockFace::BLOCK_FACE_XM, CrimsonDoor::Half::Upper, CrimsonDoor::Hinge::Right, false, false).ID: return 15566; case CrimsonDoor::CrimsonDoor(eBlockFace::BLOCK_FACE_XM, CrimsonDoor::Half::Lower, CrimsonDoor::Hinge::Left, true, true).ID: return 15567; case CrimsonDoor::CrimsonDoor(eBlockFace::BLOCK_FACE_XM, CrimsonDoor::Half::Lower, CrimsonDoor::Hinge::Left, true, false).ID: return 15568; case CrimsonDoor::CrimsonDoor(eBlockFace::BLOCK_FACE_XM, CrimsonDoor::Half::Lower, CrimsonDoor::Hinge::Left, false, true).ID: return 15569; case CrimsonDoor::CrimsonDoor(eBlockFace::BLOCK_FACE_XM, CrimsonDoor::Half::Lower, CrimsonDoor::Hinge::Left, false, false).ID: return 15570; case CrimsonDoor::CrimsonDoor(eBlockFace::BLOCK_FACE_XM, CrimsonDoor::Half::Lower, CrimsonDoor::Hinge::Right, true, true).ID: return 15571; case CrimsonDoor::CrimsonDoor(eBlockFace::BLOCK_FACE_XM, CrimsonDoor::Half::Lower, CrimsonDoor::Hinge::Right, true, false).ID: return 15572; case CrimsonDoor::CrimsonDoor(eBlockFace::BLOCK_FACE_XM, CrimsonDoor::Half::Lower, CrimsonDoor::Hinge::Right, false, true).ID: return 15573; case CrimsonDoor::CrimsonDoor(eBlockFace::BLOCK_FACE_XM, CrimsonDoor::Half::Lower, CrimsonDoor::Hinge::Right, false, false).ID: return 15574; case CrimsonDoor::CrimsonDoor(eBlockFace::BLOCK_FACE_XP, CrimsonDoor::Half::Upper, CrimsonDoor::Hinge::Left, true, true).ID: return 15575; case CrimsonDoor::CrimsonDoor(eBlockFace::BLOCK_FACE_XP, CrimsonDoor::Half::Upper, CrimsonDoor::Hinge::Left, true, false).ID: return 15576; case CrimsonDoor::CrimsonDoor(eBlockFace::BLOCK_FACE_XP, CrimsonDoor::Half::Upper, CrimsonDoor::Hinge::Left, false, true).ID: return 15577; case CrimsonDoor::CrimsonDoor(eBlockFace::BLOCK_FACE_XP, CrimsonDoor::Half::Upper, CrimsonDoor::Hinge::Left, false, false).ID: return 15578; case CrimsonDoor::CrimsonDoor(eBlockFace::BLOCK_FACE_XP, CrimsonDoor::Half::Upper, CrimsonDoor::Hinge::Right, true, true).ID: return 15579; case CrimsonDoor::CrimsonDoor(eBlockFace::BLOCK_FACE_XP, CrimsonDoor::Half::Upper, CrimsonDoor::Hinge::Right, true, false).ID: return 15580; case CrimsonDoor::CrimsonDoor(eBlockFace::BLOCK_FACE_XP, CrimsonDoor::Half::Upper, CrimsonDoor::Hinge::Right, false, true).ID: return 15581; case CrimsonDoor::CrimsonDoor(eBlockFace::BLOCK_FACE_XP, CrimsonDoor::Half::Upper, CrimsonDoor::Hinge::Right, false, false).ID: return 15582; case CrimsonDoor::CrimsonDoor(eBlockFace::BLOCK_FACE_XP, CrimsonDoor::Half::Lower, CrimsonDoor::Hinge::Left, true, true).ID: return 15583; case CrimsonDoor::CrimsonDoor(eBlockFace::BLOCK_FACE_XP, CrimsonDoor::Half::Lower, CrimsonDoor::Hinge::Left, true, false).ID: return 15584; case CrimsonDoor::CrimsonDoor(eBlockFace::BLOCK_FACE_XP, CrimsonDoor::Half::Lower, CrimsonDoor::Hinge::Left, false, true).ID: return 15585; case CrimsonDoor::CrimsonDoor(eBlockFace::BLOCK_FACE_XP, CrimsonDoor::Half::Lower, CrimsonDoor::Hinge::Left, false, false).ID: return 15586; case CrimsonDoor::CrimsonDoor(eBlockFace::BLOCK_FACE_XP, CrimsonDoor::Half::Lower, CrimsonDoor::Hinge::Right, true, true).ID: return 15587; case CrimsonDoor::CrimsonDoor(eBlockFace::BLOCK_FACE_XP, CrimsonDoor::Half::Lower, CrimsonDoor::Hinge::Right, true, false).ID: return 15588; case CrimsonDoor::CrimsonDoor(eBlockFace::BLOCK_FACE_XP, CrimsonDoor::Half::Lower, CrimsonDoor::Hinge::Right, false, true).ID: return 15589; case CrimsonDoor::CrimsonDoor(eBlockFace::BLOCK_FACE_XP, CrimsonDoor::Half::Lower, CrimsonDoor::Hinge::Right, false, false).ID: return 15590; case CrimsonFence::CrimsonFence(true, true, true, true).ID: return 15065; case CrimsonFence::CrimsonFence(true, true, true, false).ID: return 15066; case CrimsonFence::CrimsonFence(true, true, false, true).ID: return 15069; case CrimsonFence::CrimsonFence(true, true, false, false).ID: return 15070; case CrimsonFence::CrimsonFence(true, false, true, true).ID: return 15073; case CrimsonFence::CrimsonFence(true, false, true, false).ID: return 15074; case CrimsonFence::CrimsonFence(true, false, false, true).ID: return 15077; case CrimsonFence::CrimsonFence(true, false, false, false).ID: return 15078; case CrimsonFence::CrimsonFence(false, true, true, true).ID: return 15081; case CrimsonFence::CrimsonFence(false, true, true, false).ID: return 15082; case CrimsonFence::CrimsonFence(false, true, false, true).ID: return 15085; case CrimsonFence::CrimsonFence(false, true, false, false).ID: return 15086; case CrimsonFence::CrimsonFence(false, false, true, true).ID: return 15089; case CrimsonFence::CrimsonFence(false, false, true, false).ID: return 15090; case CrimsonFence::CrimsonFence(false, false, false, true).ID: return 15093; case CrimsonFence::CrimsonFence(false, false, false, false).ID: return 15094; case CrimsonFenceGate::CrimsonFenceGate(eBlockFace::BLOCK_FACE_ZM, true, true, true).ID: return 15255; case CrimsonFenceGate::CrimsonFenceGate(eBlockFace::BLOCK_FACE_ZM, true, true, false).ID: return 15256; case CrimsonFenceGate::CrimsonFenceGate(eBlockFace::BLOCK_FACE_ZM, true, false, true).ID: return 15257; case CrimsonFenceGate::CrimsonFenceGate(eBlockFace::BLOCK_FACE_ZM, true, false, false).ID: return 15258; case CrimsonFenceGate::CrimsonFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, true).ID: return 15259; case CrimsonFenceGate::CrimsonFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, false).ID: return 15260; case CrimsonFenceGate::CrimsonFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, true).ID: return 15261; case CrimsonFenceGate::CrimsonFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, false).ID: return 15262; case CrimsonFenceGate::CrimsonFenceGate(eBlockFace::BLOCK_FACE_ZP, true, true, true).ID: return 15263; case CrimsonFenceGate::CrimsonFenceGate(eBlockFace::BLOCK_FACE_ZP, true, true, false).ID: return 15264; case CrimsonFenceGate::CrimsonFenceGate(eBlockFace::BLOCK_FACE_ZP, true, false, true).ID: return 15265; case CrimsonFenceGate::CrimsonFenceGate(eBlockFace::BLOCK_FACE_ZP, true, false, false).ID: return 15266; case CrimsonFenceGate::CrimsonFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, true).ID: return 15267; case CrimsonFenceGate::CrimsonFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, false).ID: return 15268; case CrimsonFenceGate::CrimsonFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, true).ID: return 15269; case CrimsonFenceGate::CrimsonFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, false).ID: return 15270; case CrimsonFenceGate::CrimsonFenceGate(eBlockFace::BLOCK_FACE_XM, true, true, true).ID: return 15271; case CrimsonFenceGate::CrimsonFenceGate(eBlockFace::BLOCK_FACE_XM, true, true, false).ID: return 15272; case CrimsonFenceGate::CrimsonFenceGate(eBlockFace::BLOCK_FACE_XM, true, false, true).ID: return 15273; case CrimsonFenceGate::CrimsonFenceGate(eBlockFace::BLOCK_FACE_XM, true, false, false).ID: return 15274; case CrimsonFenceGate::CrimsonFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, true).ID: return 15275; case CrimsonFenceGate::CrimsonFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, false).ID: return 15276; case CrimsonFenceGate::CrimsonFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, true).ID: return 15277; case CrimsonFenceGate::CrimsonFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, false).ID: return 15278; case CrimsonFenceGate::CrimsonFenceGate(eBlockFace::BLOCK_FACE_XP, true, true, true).ID: return 15279; case CrimsonFenceGate::CrimsonFenceGate(eBlockFace::BLOCK_FACE_XP, true, true, false).ID: return 15280; case CrimsonFenceGate::CrimsonFenceGate(eBlockFace::BLOCK_FACE_XP, true, false, true).ID: return 15281; case CrimsonFenceGate::CrimsonFenceGate(eBlockFace::BLOCK_FACE_XP, true, false, false).ID: return 15282; case CrimsonFenceGate::CrimsonFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, true).ID: return 15283; case CrimsonFenceGate::CrimsonFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, false).ID: return 15284; case CrimsonFenceGate::CrimsonFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, true).ID: return 15285; case CrimsonFenceGate::CrimsonFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, false).ID: return 15286; case CrimsonFungus::CrimsonFungus().ID: return 14988; case CrimsonHyphae::CrimsonHyphae(CrimsonHyphae::Axis::X).ID: return 14981; case CrimsonHyphae::CrimsonHyphae(CrimsonHyphae::Axis::Y).ID: return 14982; case CrimsonHyphae::CrimsonHyphae(CrimsonHyphae::Axis::Z).ID: return 14983; case CrimsonNylium::CrimsonNylium().ID: return 14987; case CrimsonPlanks::CrimsonPlanks().ID: return 15045; case CrimsonPressurePlate::CrimsonPressurePlate(true).ID: return 15059; case CrimsonPressurePlate::CrimsonPressurePlate(false).ID: return 15060; case CrimsonRoots::CrimsonRoots().ID: return 15044; case CrimsonSign::CrimsonSign(0).ID: return 15656; case CrimsonSign::CrimsonSign(1).ID: return 15658; case CrimsonSign::CrimsonSign(2).ID: return 15660; case CrimsonSign::CrimsonSign(3).ID: return 15662; case CrimsonSign::CrimsonSign(4).ID: return 15664; case CrimsonSign::CrimsonSign(5).ID: return 15666; case CrimsonSign::CrimsonSign(6).ID: return 15668; case CrimsonSign::CrimsonSign(7).ID: return 15670; case CrimsonSign::CrimsonSign(8).ID: return 15672; case CrimsonSign::CrimsonSign(9).ID: return 15674; case CrimsonSign::CrimsonSign(10).ID: return 15676; case CrimsonSign::CrimsonSign(11).ID: return 15678; case CrimsonSign::CrimsonSign(12).ID: return 15680; case CrimsonSign::CrimsonSign(13).ID: return 15682; case CrimsonSign::CrimsonSign(14).ID: return 15684; case CrimsonSign::CrimsonSign(15).ID: return 15686; case CrimsonSlab::CrimsonSlab(CrimsonSlab::Type::Top).ID: return 15048; case CrimsonSlab::CrimsonSlab(CrimsonSlab::Type::Bottom).ID: return 15050; case CrimsonSlab::CrimsonSlab(CrimsonSlab::Type::Double).ID: return 15052; case CrimsonStairs::CrimsonStairs(eBlockFace::BLOCK_FACE_ZM, CrimsonStairs::Half::Top, CrimsonStairs::Shape::Straight).ID: return 15320; case CrimsonStairs::CrimsonStairs(eBlockFace::BLOCK_FACE_ZM, CrimsonStairs::Half::Top, CrimsonStairs::Shape::InnerLeft).ID: return 15322; case CrimsonStairs::CrimsonStairs(eBlockFace::BLOCK_FACE_ZM, CrimsonStairs::Half::Top, CrimsonStairs::Shape::InnerRight).ID: return 15324; case CrimsonStairs::CrimsonStairs(eBlockFace::BLOCK_FACE_ZM, CrimsonStairs::Half::Top, CrimsonStairs::Shape::OuterLeft).ID: return 15326; case CrimsonStairs::CrimsonStairs(eBlockFace::BLOCK_FACE_ZM, CrimsonStairs::Half::Top, CrimsonStairs::Shape::OuterRight).ID: return 15328; case CrimsonStairs::CrimsonStairs(eBlockFace::BLOCK_FACE_ZM, CrimsonStairs::Half::Bottom, CrimsonStairs::Shape::Straight).ID: return 15330; case CrimsonStairs::CrimsonStairs(eBlockFace::BLOCK_FACE_ZM, CrimsonStairs::Half::Bottom, CrimsonStairs::Shape::InnerLeft).ID: return 15332; case CrimsonStairs::CrimsonStairs(eBlockFace::BLOCK_FACE_ZM, CrimsonStairs::Half::Bottom, CrimsonStairs::Shape::InnerRight).ID: return 15334; case CrimsonStairs::CrimsonStairs(eBlockFace::BLOCK_FACE_ZM, CrimsonStairs::Half::Bottom, CrimsonStairs::Shape::OuterLeft).ID: return 15336; case CrimsonStairs::CrimsonStairs(eBlockFace::BLOCK_FACE_ZM, CrimsonStairs::Half::Bottom, CrimsonStairs::Shape::OuterRight).ID: return 15338; case CrimsonStairs::CrimsonStairs(eBlockFace::BLOCK_FACE_ZP, CrimsonStairs::Half::Top, CrimsonStairs::Shape::Straight).ID: return 15340; case CrimsonStairs::CrimsonStairs(eBlockFace::BLOCK_FACE_ZP, CrimsonStairs::Half::Top, CrimsonStairs::Shape::InnerLeft).ID: return 15342; case CrimsonStairs::CrimsonStairs(eBlockFace::BLOCK_FACE_ZP, CrimsonStairs::Half::Top, CrimsonStairs::Shape::InnerRight).ID: return 15344; case CrimsonStairs::CrimsonStairs(eBlockFace::BLOCK_FACE_ZP, CrimsonStairs::Half::Top, CrimsonStairs::Shape::OuterLeft).ID: return 15346; case CrimsonStairs::CrimsonStairs(eBlockFace::BLOCK_FACE_ZP, CrimsonStairs::Half::Top, CrimsonStairs::Shape::OuterRight).ID: return 15348; case CrimsonStairs::CrimsonStairs(eBlockFace::BLOCK_FACE_ZP, CrimsonStairs::Half::Bottom, CrimsonStairs::Shape::Straight).ID: return 15350; case CrimsonStairs::CrimsonStairs(eBlockFace::BLOCK_FACE_ZP, CrimsonStairs::Half::Bottom, CrimsonStairs::Shape::InnerLeft).ID: return 15352; case CrimsonStairs::CrimsonStairs(eBlockFace::BLOCK_FACE_ZP, CrimsonStairs::Half::Bottom, CrimsonStairs::Shape::InnerRight).ID: return 15354; case CrimsonStairs::CrimsonStairs(eBlockFace::BLOCK_FACE_ZP, CrimsonStairs::Half::Bottom, CrimsonStairs::Shape::OuterLeft).ID: return 15356; case CrimsonStairs::CrimsonStairs(eBlockFace::BLOCK_FACE_ZP, CrimsonStairs::Half::Bottom, CrimsonStairs::Shape::OuterRight).ID: return 15358; case CrimsonStairs::CrimsonStairs(eBlockFace::BLOCK_FACE_XM, CrimsonStairs::Half::Top, CrimsonStairs::Shape::Straight).ID: return 15360; case CrimsonStairs::CrimsonStairs(eBlockFace::BLOCK_FACE_XM, CrimsonStairs::Half::Top, CrimsonStairs::Shape::InnerLeft).ID: return 15362; case CrimsonStairs::CrimsonStairs(eBlockFace::BLOCK_FACE_XM, CrimsonStairs::Half::Top, CrimsonStairs::Shape::InnerRight).ID: return 15364; case CrimsonStairs::CrimsonStairs(eBlockFace::BLOCK_FACE_XM, CrimsonStairs::Half::Top, CrimsonStairs::Shape::OuterLeft).ID: return 15366; case CrimsonStairs::CrimsonStairs(eBlockFace::BLOCK_FACE_XM, CrimsonStairs::Half::Top, CrimsonStairs::Shape::OuterRight).ID: return 15368; case CrimsonStairs::CrimsonStairs(eBlockFace::BLOCK_FACE_XM, CrimsonStairs::Half::Bottom, CrimsonStairs::Shape::Straight).ID: return 15370; case CrimsonStairs::CrimsonStairs(eBlockFace::BLOCK_FACE_XM, CrimsonStairs::Half::Bottom, CrimsonStairs::Shape::InnerLeft).ID: return 15372; case CrimsonStairs::CrimsonStairs(eBlockFace::BLOCK_FACE_XM, CrimsonStairs::Half::Bottom, CrimsonStairs::Shape::InnerRight).ID: return 15374; case CrimsonStairs::CrimsonStairs(eBlockFace::BLOCK_FACE_XM, CrimsonStairs::Half::Bottom, CrimsonStairs::Shape::OuterLeft).ID: return 15376; case CrimsonStairs::CrimsonStairs(eBlockFace::BLOCK_FACE_XM, CrimsonStairs::Half::Bottom, CrimsonStairs::Shape::OuterRight).ID: return 15378; case CrimsonStairs::CrimsonStairs(eBlockFace::BLOCK_FACE_XP, CrimsonStairs::Half::Top, CrimsonStairs::Shape::Straight).ID: return 15380; case CrimsonStairs::CrimsonStairs(eBlockFace::BLOCK_FACE_XP, CrimsonStairs::Half::Top, CrimsonStairs::Shape::InnerLeft).ID: return 15382; case CrimsonStairs::CrimsonStairs(eBlockFace::BLOCK_FACE_XP, CrimsonStairs::Half::Top, CrimsonStairs::Shape::InnerRight).ID: return 15384; case CrimsonStairs::CrimsonStairs(eBlockFace::BLOCK_FACE_XP, CrimsonStairs::Half::Top, CrimsonStairs::Shape::OuterLeft).ID: return 15386; case CrimsonStairs::CrimsonStairs(eBlockFace::BLOCK_FACE_XP, CrimsonStairs::Half::Top, CrimsonStairs::Shape::OuterRight).ID: return 15388; case CrimsonStairs::CrimsonStairs(eBlockFace::BLOCK_FACE_XP, CrimsonStairs::Half::Bottom, CrimsonStairs::Shape::Straight).ID: return 15390; case CrimsonStairs::CrimsonStairs(eBlockFace::BLOCK_FACE_XP, CrimsonStairs::Half::Bottom, CrimsonStairs::Shape::InnerLeft).ID: return 15392; case CrimsonStairs::CrimsonStairs(eBlockFace::BLOCK_FACE_XP, CrimsonStairs::Half::Bottom, CrimsonStairs::Shape::InnerRight).ID: return 15394; case CrimsonStairs::CrimsonStairs(eBlockFace::BLOCK_FACE_XP, CrimsonStairs::Half::Bottom, CrimsonStairs::Shape::OuterLeft).ID: return 15396; case CrimsonStairs::CrimsonStairs(eBlockFace::BLOCK_FACE_XP, CrimsonStairs::Half::Bottom, CrimsonStairs::Shape::OuterRight).ID: return 15398; case CrimsonStem::CrimsonStem(CrimsonStem::Axis::X).ID: return 14975; case CrimsonStem::CrimsonStem(CrimsonStem::Axis::Y).ID: return 14976; case CrimsonStem::CrimsonStem(CrimsonStem::Axis::Z).ID: return 14977; case CrimsonTrapdoor::CrimsonTrapdoor(eBlockFace::BLOCK_FACE_ZM, CrimsonTrapdoor::Half::Top, true, true).ID: return 15128; case CrimsonTrapdoor::CrimsonTrapdoor(eBlockFace::BLOCK_FACE_ZM, CrimsonTrapdoor::Half::Top, true, false).ID: return 15130; case CrimsonTrapdoor::CrimsonTrapdoor(eBlockFace::BLOCK_FACE_ZM, CrimsonTrapdoor::Half::Top, false, true).ID: return 15132; case CrimsonTrapdoor::CrimsonTrapdoor(eBlockFace::BLOCK_FACE_ZM, CrimsonTrapdoor::Half::Top, false, false).ID: return 15134; case CrimsonTrapdoor::CrimsonTrapdoor(eBlockFace::BLOCK_FACE_ZM, CrimsonTrapdoor::Half::Bottom, true, true).ID: return 15136; case CrimsonTrapdoor::CrimsonTrapdoor(eBlockFace::BLOCK_FACE_ZM, CrimsonTrapdoor::Half::Bottom, true, false).ID: return 15138; case CrimsonTrapdoor::CrimsonTrapdoor(eBlockFace::BLOCK_FACE_ZM, CrimsonTrapdoor::Half::Bottom, false, true).ID: return 15140; case CrimsonTrapdoor::CrimsonTrapdoor(eBlockFace::BLOCK_FACE_ZM, CrimsonTrapdoor::Half::Bottom, false, false).ID: return 15142; case CrimsonTrapdoor::CrimsonTrapdoor(eBlockFace::BLOCK_FACE_ZP, CrimsonTrapdoor::Half::Top, true, true).ID: return 15144; case CrimsonTrapdoor::CrimsonTrapdoor(eBlockFace::BLOCK_FACE_ZP, CrimsonTrapdoor::Half::Top, true, false).ID: return 15146; case CrimsonTrapdoor::CrimsonTrapdoor(eBlockFace::BLOCK_FACE_ZP, CrimsonTrapdoor::Half::Top, false, true).ID: return 15148; case CrimsonTrapdoor::CrimsonTrapdoor(eBlockFace::BLOCK_FACE_ZP, CrimsonTrapdoor::Half::Top, false, false).ID: return 15150; case CrimsonTrapdoor::CrimsonTrapdoor(eBlockFace::BLOCK_FACE_ZP, CrimsonTrapdoor::Half::Bottom, true, true).ID: return 15152; case CrimsonTrapdoor::CrimsonTrapdoor(eBlockFace::BLOCK_FACE_ZP, CrimsonTrapdoor::Half::Bottom, true, false).ID: return 15154; case CrimsonTrapdoor::CrimsonTrapdoor(eBlockFace::BLOCK_FACE_ZP, CrimsonTrapdoor::Half::Bottom, false, true).ID: return 15156; case CrimsonTrapdoor::CrimsonTrapdoor(eBlockFace::BLOCK_FACE_ZP, CrimsonTrapdoor::Half::Bottom, false, false).ID: return 15158; case CrimsonTrapdoor::CrimsonTrapdoor(eBlockFace::BLOCK_FACE_XM, CrimsonTrapdoor::Half::Top, true, true).ID: return 15160; case CrimsonTrapdoor::CrimsonTrapdoor(eBlockFace::BLOCK_FACE_XM, CrimsonTrapdoor::Half::Top, true, false).ID: return 15162; case CrimsonTrapdoor::CrimsonTrapdoor(eBlockFace::BLOCK_FACE_XM, CrimsonTrapdoor::Half::Top, false, true).ID: return 15164; case CrimsonTrapdoor::CrimsonTrapdoor(eBlockFace::BLOCK_FACE_XM, CrimsonTrapdoor::Half::Top, false, false).ID: return 15166; case CrimsonTrapdoor::CrimsonTrapdoor(eBlockFace::BLOCK_FACE_XM, CrimsonTrapdoor::Half::Bottom, true, true).ID: return 15168; case CrimsonTrapdoor::CrimsonTrapdoor(eBlockFace::BLOCK_FACE_XM, CrimsonTrapdoor::Half::Bottom, true, false).ID: return 15170; case CrimsonTrapdoor::CrimsonTrapdoor(eBlockFace::BLOCK_FACE_XM, CrimsonTrapdoor::Half::Bottom, false, true).ID: return 15172; case CrimsonTrapdoor::CrimsonTrapdoor(eBlockFace::BLOCK_FACE_XM, CrimsonTrapdoor::Half::Bottom, false, false).ID: return 15174; case CrimsonTrapdoor::CrimsonTrapdoor(eBlockFace::BLOCK_FACE_XP, CrimsonTrapdoor::Half::Top, true, true).ID: return 15176; case CrimsonTrapdoor::CrimsonTrapdoor(eBlockFace::BLOCK_FACE_XP, CrimsonTrapdoor::Half::Top, true, false).ID: return 15178; case CrimsonTrapdoor::CrimsonTrapdoor(eBlockFace::BLOCK_FACE_XP, CrimsonTrapdoor::Half::Top, false, true).ID: return 15180; case CrimsonTrapdoor::CrimsonTrapdoor(eBlockFace::BLOCK_FACE_XP, CrimsonTrapdoor::Half::Top, false, false).ID: return 15182; case CrimsonTrapdoor::CrimsonTrapdoor(eBlockFace::BLOCK_FACE_XP, CrimsonTrapdoor::Half::Bottom, true, true).ID: return 15184; case CrimsonTrapdoor::CrimsonTrapdoor(eBlockFace::BLOCK_FACE_XP, CrimsonTrapdoor::Half::Bottom, true, false).ID: return 15186; case CrimsonTrapdoor::CrimsonTrapdoor(eBlockFace::BLOCK_FACE_XP, CrimsonTrapdoor::Half::Bottom, false, true).ID: return 15188; case CrimsonTrapdoor::CrimsonTrapdoor(eBlockFace::BLOCK_FACE_XP, CrimsonTrapdoor::Half::Bottom, false, false).ID: return 15190; case CrimsonWallSign::CrimsonWallSign(eBlockFace::BLOCK_FACE_ZM).ID: return 15720; case CrimsonWallSign::CrimsonWallSign(eBlockFace::BLOCK_FACE_ZP).ID: return 15722; case CrimsonWallSign::CrimsonWallSign(eBlockFace::BLOCK_FACE_XM).ID: return 15724; case CrimsonWallSign::CrimsonWallSign(eBlockFace::BLOCK_FACE_XP).ID: return 15726; case CryingObsidian::CryingObsidian().ID: return 15828; case CutRedSandstone::CutRedSandstone().ID: return 8219; case CutRedSandstoneSlab::CutRedSandstoneSlab(CutRedSandstoneSlab::Type::Top).ID: return 8403; case CutRedSandstoneSlab::CutRedSandstoneSlab(CutRedSandstoneSlab::Type::Bottom).ID: return 8405; case CutRedSandstoneSlab::CutRedSandstoneSlab(CutRedSandstoneSlab::Type::Double).ID: return 8407; case CutSandstone::CutSandstone().ID: return 248; case CutSandstoneSlab::CutSandstoneSlab(CutSandstoneSlab::Type::Top).ID: return 8355; case CutSandstoneSlab::CutSandstoneSlab(CutSandstoneSlab::Type::Bottom).ID: return 8357; case CutSandstoneSlab::CutSandstoneSlab(CutSandstoneSlab::Type::Double).ID: return 8359; case CyanBanner::CyanBanner(0).ID: return 8041; case CyanBanner::CyanBanner(1).ID: return 8042; case CyanBanner::CyanBanner(2).ID: return 8043; case CyanBanner::CyanBanner(3).ID: return 8044; case CyanBanner::CyanBanner(4).ID: return 8045; case CyanBanner::CyanBanner(5).ID: return 8046; case CyanBanner::CyanBanner(6).ID: return 8047; case CyanBanner::CyanBanner(7).ID: return 8048; case CyanBanner::CyanBanner(8).ID: return 8049; case CyanBanner::CyanBanner(9).ID: return 8050; case CyanBanner::CyanBanner(10).ID: return 8051; case CyanBanner::CyanBanner(11).ID: return 8052; case CyanBanner::CyanBanner(12).ID: return 8053; case CyanBanner::CyanBanner(13).ID: return 8054; case CyanBanner::CyanBanner(14).ID: return 8055; case CyanBanner::CyanBanner(15).ID: return 8056; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_ZM, true, CyanBed::Part::Head).ID: return 1193; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_ZM, true, CyanBed::Part::Foot).ID: return 1194; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_ZM, false, CyanBed::Part::Head).ID: return 1195; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_ZM, false, CyanBed::Part::Foot).ID: return 1196; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_ZP, true, CyanBed::Part::Head).ID: return 1197; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_ZP, true, CyanBed::Part::Foot).ID: return 1198; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_ZP, false, CyanBed::Part::Head).ID: return 1199; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_ZP, false, CyanBed::Part::Foot).ID: return 1200; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_XM, true, CyanBed::Part::Head).ID: return 1201; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_XM, true, CyanBed::Part::Foot).ID: return 1202; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_XM, false, CyanBed::Part::Head).ID: return 1203; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_XM, false, CyanBed::Part::Foot).ID: return 1204; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_XP, true, CyanBed::Part::Head).ID: return 1205; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_XP, true, CyanBed::Part::Foot).ID: return 1206; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_XP, false, CyanBed::Part::Head).ID: return 1207; case CyanBed::CyanBed(eBlockFace::BLOCK_FACE_XP, false, CyanBed::Part::Foot).ID: return 1208; case CyanCarpet::CyanCarpet().ID: return 7875; case CyanConcrete::CyanConcrete().ID: return 9447; case CyanConcretePowder::CyanConcretePowder().ID: return 9463; case CyanGlazedTerracotta::CyanGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 9410; case CyanGlazedTerracotta::CyanGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 9411; case CyanGlazedTerracotta::CyanGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 9412; case CyanGlazedTerracotta::CyanGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 9413; case CyanShulkerBox::CyanShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 9332; case CyanShulkerBox::CyanShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 9333; case CyanShulkerBox::CyanShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 9334; case CyanShulkerBox::CyanShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 9335; case CyanShulkerBox::CyanShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 9336; case CyanShulkerBox::CyanShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 9337; case CyanStainedGlass::CyanStainedGlass().ID: return 4104; case CyanStainedGlassPane::CyanStainedGlassPane(true, true, true, true).ID: return 7153; case CyanStainedGlassPane::CyanStainedGlassPane(true, true, true, false).ID: return 7154; case CyanStainedGlassPane::CyanStainedGlassPane(true, true, false, true).ID: return 7157; case CyanStainedGlassPane::CyanStainedGlassPane(true, true, false, false).ID: return 7158; case CyanStainedGlassPane::CyanStainedGlassPane(true, false, true, true).ID: return 7161; case CyanStainedGlassPane::CyanStainedGlassPane(true, false, true, false).ID: return 7162; case CyanStainedGlassPane::CyanStainedGlassPane(true, false, false, true).ID: return 7165; case CyanStainedGlassPane::CyanStainedGlassPane(true, false, false, false).ID: return 7166; case CyanStainedGlassPane::CyanStainedGlassPane(false, true, true, true).ID: return 7169; case CyanStainedGlassPane::CyanStainedGlassPane(false, true, true, false).ID: return 7170; case CyanStainedGlassPane::CyanStainedGlassPane(false, true, false, true).ID: return 7173; case CyanStainedGlassPane::CyanStainedGlassPane(false, true, false, false).ID: return 7174; case CyanStainedGlassPane::CyanStainedGlassPane(false, false, true, true).ID: return 7177; case CyanStainedGlassPane::CyanStainedGlassPane(false, false, true, false).ID: return 7178; case CyanStainedGlassPane::CyanStainedGlassPane(false, false, false, true).ID: return 7181; case CyanStainedGlassPane::CyanStainedGlassPane(false, false, false, false).ID: return 7182; case CyanTerracotta::CyanTerracotta().ID: return 6856; case CyanWallBanner::CyanWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 8189; case CyanWallBanner::CyanWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 8190; case CyanWallBanner::CyanWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 8191; case CyanWallBanner::CyanWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 8192; case CyanWool::CyanWool().ID: return 1393; case DamagedAnvil::DamagedAnvil(eBlockFace::BLOCK_FACE_ZM).ID: return 6618; case DamagedAnvil::DamagedAnvil(eBlockFace::BLOCK_FACE_ZP).ID: return 6619; case DamagedAnvil::DamagedAnvil(eBlockFace::BLOCK_FACE_XM).ID: return 6620; case DamagedAnvil::DamagedAnvil(eBlockFace::BLOCK_FACE_XP).ID: return 6621; case Dandelion::Dandelion().ID: return 1412; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, true).ID: return 6466; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, false).ID: return 6467; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, true).ID: return 6468; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, false).ID: return 6469; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, true).ID: return 6470; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, false).ID: return 6471; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, true).ID: return 6472; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, false).ID: return 6473; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, true).ID: return 6474; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, false).ID: return 6475; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, true).ID: return 6476; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, false).ID: return 6477; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, true).ID: return 6478; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, false).ID: return 6479; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, true).ID: return 6480; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, false).ID: return 6481; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, true).ID: return 6482; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, false).ID: return 6483; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, true).ID: return 6484; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, false).ID: return 6485; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, true).ID: return 6486; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, false).ID: return 6487; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, true).ID: return 6488; case DarkOakButton::DarkOakButton(DarkOakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, false).ID: return 6489; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, true, true).ID: return 8994; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, true, false).ID: return 8995; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, false, true).ID: return 8996; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, false, false).ID: return 8997; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, true, true).ID: return 8998; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, true, false).ID: return 8999; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, false, true).ID: return 9000; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, false, false).ID: return 9001; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, true, true).ID: return 9002; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, true, false).ID: return 9003; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, false, true).ID: return 9004; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, false, false).ID: return 9005; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, true, true).ID: return 9006; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, true, false).ID: return 9007; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, false, true).ID: return 9008; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, false, false).ID: return 9009; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, true, true).ID: return 9010; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, true, false).ID: return 9011; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, false, true).ID: return 9012; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, false, false).ID: return 9013; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, true, true).ID: return 9014; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, true, false).ID: return 9015; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, false, true).ID: return 9016; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, false, false).ID: return 9017; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, true, true).ID: return 9018; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, true, false).ID: return 9019; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, false, true).ID: return 9020; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, false, false).ID: return 9021; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, true, true).ID: return 9022; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, true, false).ID: return 9023; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, false, true).ID: return 9024; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, false, false).ID: return 9025; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, true, true).ID: return 9026; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, true, false).ID: return 9027; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, false, true).ID: return 9028; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, false, false).ID: return 9029; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, true, true).ID: return 9030; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, true, false).ID: return 9031; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, false, true).ID: return 9032; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, false, false).ID: return 9033; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, true, true).ID: return 9034; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, true, false).ID: return 9035; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, false, true).ID: return 9036; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, false, false).ID: return 9037; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, true, true).ID: return 9038; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, true, false).ID: return 9039; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, false, true).ID: return 9040; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, false, false).ID: return 9041; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, true, true).ID: return 9042; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, true, false).ID: return 9043; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, false, true).ID: return 9044; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, false, false).ID: return 9045; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, true, true).ID: return 9046; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, true, false).ID: return 9047; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, false, true).ID: return 9048; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, false, false).ID: return 9049; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, true, true).ID: return 9050; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, true, false).ID: return 9051; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, false, true).ID: return 9052; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Left, false, false).ID: return 9053; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, true, true).ID: return 9054; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, true, false).ID: return 9055; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, false, true).ID: return 9056; case DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, false, false).ID: return 9057; case DarkOakFence::DarkOakFence(true, true, true, true).ID: return 8708; case DarkOakFence::DarkOakFence(true, true, true, false).ID: return 8709; case DarkOakFence::DarkOakFence(true, true, false, true).ID: return 8712; case DarkOakFence::DarkOakFence(true, true, false, false).ID: return 8713; case DarkOakFence::DarkOakFence(true, false, true, true).ID: return 8716; case DarkOakFence::DarkOakFence(true, false, true, false).ID: return 8717; case DarkOakFence::DarkOakFence(true, false, false, true).ID: return 8720; case DarkOakFence::DarkOakFence(true, false, false, false).ID: return 8721; case DarkOakFence::DarkOakFence(false, true, true, true).ID: return 8724; case DarkOakFence::DarkOakFence(false, true, true, false).ID: return 8725; case DarkOakFence::DarkOakFence(false, true, false, true).ID: return 8728; case DarkOakFence::DarkOakFence(false, true, false, false).ID: return 8729; case DarkOakFence::DarkOakFence(false, false, true, true).ID: return 8732; case DarkOakFence::DarkOakFence(false, false, true, false).ID: return 8733; case DarkOakFence::DarkOakFence(false, false, false, true).ID: return 8736; case DarkOakFence::DarkOakFence(false, false, false, false).ID: return 8737; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZM, true, true, true).ID: return 8546; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZM, true, true, false).ID: return 8547; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZM, true, false, true).ID: return 8548; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZM, true, false, false).ID: return 8549; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, true).ID: return 8550; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, false).ID: return 8551; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, true).ID: return 8552; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, false).ID: return 8553; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZP, true, true, true).ID: return 8554; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZP, true, true, false).ID: return 8555; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZP, true, false, true).ID: return 8556; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZP, true, false, false).ID: return 8557; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, true).ID: return 8558; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, false).ID: return 8559; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, true).ID: return 8560; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, false).ID: return 8561; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XM, true, true, true).ID: return 8562; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XM, true, true, false).ID: return 8563; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XM, true, false, true).ID: return 8564; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XM, true, false, false).ID: return 8565; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, true).ID: return 8566; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, false).ID: return 8567; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, true).ID: return 8568; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, false).ID: return 8569; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XP, true, true, true).ID: return 8570; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XP, true, true, false).ID: return 8571; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XP, true, false, true).ID: return 8572; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XP, true, false, false).ID: return 8573; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, true).ID: return 8574; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, false).ID: return 8575; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, true).ID: return 8576; case DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, false).ID: return 8577; case DarkOakLeaves::DarkOakLeaves(1, true).ID: return 215; case DarkOakLeaves::DarkOakLeaves(1, false).ID: return 216; case DarkOakLeaves::DarkOakLeaves(2, true).ID: return 217; case DarkOakLeaves::DarkOakLeaves(2, false).ID: return 218; case DarkOakLeaves::DarkOakLeaves(3, true).ID: return 219; case DarkOakLeaves::DarkOakLeaves(3, false).ID: return 220; case DarkOakLeaves::DarkOakLeaves(4, true).ID: return 221; case DarkOakLeaves::DarkOakLeaves(4, false).ID: return 222; case DarkOakLeaves::DarkOakLeaves(5, true).ID: return 223; case DarkOakLeaves::DarkOakLeaves(5, false).ID: return 224; case DarkOakLeaves::DarkOakLeaves(6, true).ID: return 225; case DarkOakLeaves::DarkOakLeaves(6, false).ID: return 226; case DarkOakLeaves::DarkOakLeaves(7, true).ID: return 227; case DarkOakLeaves::DarkOakLeaves(7, false).ID: return 228; case DarkOakLog::DarkOakLog(DarkOakLog::Axis::X).ID: return 88; case DarkOakLog::DarkOakLog(DarkOakLog::Axis::Y).ID: return 89; case DarkOakLog::DarkOakLog(DarkOakLog::Axis::Z).ID: return 90; case DarkOakPlanks::DarkOakPlanks().ID: return 20; case DarkOakPressurePlate::DarkOakPressurePlate(true).ID: return 3883; case DarkOakPressurePlate::DarkOakPressurePlate(false).ID: return 3884; case DarkOakSapling::DarkOakSapling(0).ID: return 31; case DarkOakSapling::DarkOakSapling(1).ID: return 32; case DarkOakSign::DarkOakSign(0).ID: return 3542; case DarkOakSign::DarkOakSign(1).ID: return 3544; case DarkOakSign::DarkOakSign(2).ID: return 3546; case DarkOakSign::DarkOakSign(3).ID: return 3548; case DarkOakSign::DarkOakSign(4).ID: return 3550; case DarkOakSign::DarkOakSign(5).ID: return 3552; case DarkOakSign::DarkOakSign(6).ID: return 3554; case DarkOakSign::DarkOakSign(7).ID: return 3556; case DarkOakSign::DarkOakSign(8).ID: return 3558; case DarkOakSign::DarkOakSign(9).ID: return 3560; case DarkOakSign::DarkOakSign(10).ID: return 3562; case DarkOakSign::DarkOakSign(11).ID: return 3564; case DarkOakSign::DarkOakSign(12).ID: return 3566; case DarkOakSign::DarkOakSign(13).ID: return 3568; case DarkOakSign::DarkOakSign(14).ID: return 3570; case DarkOakSign::DarkOakSign(15).ID: return 3572; case DarkOakSlab::DarkOakSlab(DarkOakSlab::Type::Top).ID: return 8331; case DarkOakSlab::DarkOakSlab(DarkOakSlab::Type::Bottom).ID: return 8333; case DarkOakSlab::DarkOakSlab(DarkOakSlab::Type::Double).ID: return 8335; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZM, DarkOakStairs::Half::Top, DarkOakStairs::Shape::Straight).ID: return 7456; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZM, DarkOakStairs::Half::Top, DarkOakStairs::Shape::InnerLeft).ID: return 7458; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZM, DarkOakStairs::Half::Top, DarkOakStairs::Shape::InnerRight).ID: return 7460; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZM, DarkOakStairs::Half::Top, DarkOakStairs::Shape::OuterLeft).ID: return 7462; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZM, DarkOakStairs::Half::Top, DarkOakStairs::Shape::OuterRight).ID: return 7464; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZM, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::Straight).ID: return 7466; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZM, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::InnerLeft).ID: return 7468; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZM, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::InnerRight).ID: return 7470; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZM, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::OuterLeft).ID: return 7472; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZM, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::OuterRight).ID: return 7474; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZP, DarkOakStairs::Half::Top, DarkOakStairs::Shape::Straight).ID: return 7476; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZP, DarkOakStairs::Half::Top, DarkOakStairs::Shape::InnerLeft).ID: return 7478; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZP, DarkOakStairs::Half::Top, DarkOakStairs::Shape::InnerRight).ID: return 7480; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZP, DarkOakStairs::Half::Top, DarkOakStairs::Shape::OuterLeft).ID: return 7482; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZP, DarkOakStairs::Half::Top, DarkOakStairs::Shape::OuterRight).ID: return 7484; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZP, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::Straight).ID: return 7486; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZP, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::InnerLeft).ID: return 7488; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZP, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::InnerRight).ID: return 7490; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZP, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::OuterLeft).ID: return 7492; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZP, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::OuterRight).ID: return 7494; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XM, DarkOakStairs::Half::Top, DarkOakStairs::Shape::Straight).ID: return 7496; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XM, DarkOakStairs::Half::Top, DarkOakStairs::Shape::InnerLeft).ID: return 7498; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XM, DarkOakStairs::Half::Top, DarkOakStairs::Shape::InnerRight).ID: return 7500; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XM, DarkOakStairs::Half::Top, DarkOakStairs::Shape::OuterLeft).ID: return 7502; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XM, DarkOakStairs::Half::Top, DarkOakStairs::Shape::OuterRight).ID: return 7504; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XM, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::Straight).ID: return 7506; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XM, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::InnerLeft).ID: return 7508; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XM, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::InnerRight).ID: return 7510; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XM, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::OuterLeft).ID: return 7512; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XM, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::OuterRight).ID: return 7514; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XP, DarkOakStairs::Half::Top, DarkOakStairs::Shape::Straight).ID: return 7516; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XP, DarkOakStairs::Half::Top, DarkOakStairs::Shape::InnerLeft).ID: return 7518; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XP, DarkOakStairs::Half::Top, DarkOakStairs::Shape::InnerRight).ID: return 7520; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XP, DarkOakStairs::Half::Top, DarkOakStairs::Shape::OuterLeft).ID: return 7522; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XP, DarkOakStairs::Half::Top, DarkOakStairs::Shape::OuterRight).ID: return 7524; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XP, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::Straight).ID: return 7526; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XP, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::InnerLeft).ID: return 7528; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XP, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::InnerRight).ID: return 7530; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XP, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::OuterLeft).ID: return 7532; case DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XP, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::OuterRight).ID: return 7534; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZM, DarkOakTrapdoor::Half::Top, true, true).ID: return 4432; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZM, DarkOakTrapdoor::Half::Top, true, false).ID: return 4434; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZM, DarkOakTrapdoor::Half::Top, false, true).ID: return 4436; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZM, DarkOakTrapdoor::Half::Top, false, false).ID: return 4438; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZM, DarkOakTrapdoor::Half::Bottom, true, true).ID: return 4440; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZM, DarkOakTrapdoor::Half::Bottom, true, false).ID: return 4442; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZM, DarkOakTrapdoor::Half::Bottom, false, true).ID: return 4444; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZM, DarkOakTrapdoor::Half::Bottom, false, false).ID: return 4446; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZP, DarkOakTrapdoor::Half::Top, true, true).ID: return 4448; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZP, DarkOakTrapdoor::Half::Top, true, false).ID: return 4450; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZP, DarkOakTrapdoor::Half::Top, false, true).ID: return 4452; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZP, DarkOakTrapdoor::Half::Top, false, false).ID: return 4454; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZP, DarkOakTrapdoor::Half::Bottom, true, true).ID: return 4456; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZP, DarkOakTrapdoor::Half::Bottom, true, false).ID: return 4458; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZP, DarkOakTrapdoor::Half::Bottom, false, true).ID: return 4460; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_ZP, DarkOakTrapdoor::Half::Bottom, false, false).ID: return 4462; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XM, DarkOakTrapdoor::Half::Top, true, true).ID: return 4464; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XM, DarkOakTrapdoor::Half::Top, true, false).ID: return 4466; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XM, DarkOakTrapdoor::Half::Top, false, true).ID: return 4468; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XM, DarkOakTrapdoor::Half::Top, false, false).ID: return 4470; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XM, DarkOakTrapdoor::Half::Bottom, true, true).ID: return 4472; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XM, DarkOakTrapdoor::Half::Bottom, true, false).ID: return 4474; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XM, DarkOakTrapdoor::Half::Bottom, false, true).ID: return 4476; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XM, DarkOakTrapdoor::Half::Bottom, false, false).ID: return 4478; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XP, DarkOakTrapdoor::Half::Top, true, true).ID: return 4480; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XP, DarkOakTrapdoor::Half::Top, true, false).ID: return 4482; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XP, DarkOakTrapdoor::Half::Top, false, true).ID: return 4484; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XP, DarkOakTrapdoor::Half::Top, false, false).ID: return 4486; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XP, DarkOakTrapdoor::Half::Bottom, true, true).ID: return 4488; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XP, DarkOakTrapdoor::Half::Bottom, true, false).ID: return 4490; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XP, DarkOakTrapdoor::Half::Bottom, false, true).ID: return 4492; case DarkOakTrapdoor::DarkOakTrapdoor(eBlockFace::BLOCK_FACE_XP, DarkOakTrapdoor::Half::Bottom, false, false).ID: return 4494; case DarkOakWallSign::DarkOakWallSign(eBlockFace::BLOCK_FACE_ZM).ID: return 3776; case DarkOakWallSign::DarkOakWallSign(eBlockFace::BLOCK_FACE_ZP).ID: return 3778; case DarkOakWallSign::DarkOakWallSign(eBlockFace::BLOCK_FACE_XM).ID: return 3780; case DarkOakWallSign::DarkOakWallSign(eBlockFace::BLOCK_FACE_XP).ID: return 3782; case DarkOakWood::DarkOakWood(DarkOakWood::Axis::X).ID: return 124; case DarkOakWood::DarkOakWood(DarkOakWood::Axis::Y).ID: return 125; case DarkOakWood::DarkOakWood(DarkOakWood::Axis::Z).ID: return 126; case DarkPrismarine::DarkPrismarine().ID: return 7603; case DarkPrismarineSlab::DarkPrismarineSlab(DarkPrismarineSlab::Type::Top).ID: return 7857; case DarkPrismarineSlab::DarkPrismarineSlab(DarkPrismarineSlab::Type::Bottom).ID: return 7859; case DarkPrismarineSlab::DarkPrismarineSlab(DarkPrismarineSlab::Type::Double).ID: return 7861; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZM, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::Straight).ID: return 7765; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZM, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::InnerLeft).ID: return 7767; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZM, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::InnerRight).ID: return 7769; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZM, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::OuterLeft).ID: return 7771; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZM, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::OuterRight).ID: return 7773; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZM, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::Straight).ID: return 7775; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZM, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::InnerLeft).ID: return 7777; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZM, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::InnerRight).ID: return 7779; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZM, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::OuterLeft).ID: return 7781; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZM, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::OuterRight).ID: return 7783; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZP, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::Straight).ID: return 7785; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZP, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::InnerLeft).ID: return 7787; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZP, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::InnerRight).ID: return 7789; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZP, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::OuterLeft).ID: return 7791; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZP, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::OuterRight).ID: return 7793; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZP, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::Straight).ID: return 7795; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZP, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::InnerLeft).ID: return 7797; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZP, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::InnerRight).ID: return 7799; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZP, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::OuterLeft).ID: return 7801; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_ZP, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::OuterRight).ID: return 7803; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XM, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::Straight).ID: return 7805; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XM, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::InnerLeft).ID: return 7807; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XM, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::InnerRight).ID: return 7809; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XM, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::OuterLeft).ID: return 7811; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XM, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::OuterRight).ID: return 7813; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XM, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::Straight).ID: return 7815; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XM, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::InnerLeft).ID: return 7817; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XM, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::InnerRight).ID: return 7819; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XM, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::OuterLeft).ID: return 7821; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XM, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::OuterRight).ID: return 7823; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XP, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::Straight).ID: return 7825; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XP, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::InnerLeft).ID: return 7827; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XP, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::InnerRight).ID: return 7829; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XP, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::OuterLeft).ID: return 7831; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XP, DarkPrismarineStairs::Half::Top, DarkPrismarineStairs::Shape::OuterRight).ID: return 7833; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XP, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::Straight).ID: return 7835; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XP, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::InnerLeft).ID: return 7837; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XP, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::InnerRight).ID: return 7839; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XP, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::OuterLeft).ID: return 7841; case DarkPrismarineStairs::DarkPrismarineStairs(eBlockFace::BLOCK_FACE_XP, DarkPrismarineStairs::Half::Bottom, DarkPrismarineStairs::Shape::OuterRight).ID: return 7843; case DaylightDetector::DaylightDetector(true, 0).ID: return 6694; case DaylightDetector::DaylightDetector(true, 1).ID: return 6695; case DaylightDetector::DaylightDetector(true, 2).ID: return 6696; case DaylightDetector::DaylightDetector(true, 3).ID: return 6697; case DaylightDetector::DaylightDetector(true, 4).ID: return 6698; case DaylightDetector::DaylightDetector(true, 5).ID: return 6699; case DaylightDetector::DaylightDetector(true, 6).ID: return 6700; case DaylightDetector::DaylightDetector(true, 7).ID: return 6701; case DaylightDetector::DaylightDetector(true, 8).ID: return 6702; case DaylightDetector::DaylightDetector(true, 9).ID: return 6703; case DaylightDetector::DaylightDetector(true, 10).ID: return 6704; case DaylightDetector::DaylightDetector(true, 11).ID: return 6705; case DaylightDetector::DaylightDetector(true, 12).ID: return 6706; case DaylightDetector::DaylightDetector(true, 13).ID: return 6707; case DaylightDetector::DaylightDetector(true, 14).ID: return 6708; case DaylightDetector::DaylightDetector(true, 15).ID: return 6709; case DaylightDetector::DaylightDetector(false, 0).ID: return 6710; case DaylightDetector::DaylightDetector(false, 1).ID: return 6711; case DaylightDetector::DaylightDetector(false, 2).ID: return 6712; case DaylightDetector::DaylightDetector(false, 3).ID: return 6713; case DaylightDetector::DaylightDetector(false, 4).ID: return 6714; case DaylightDetector::DaylightDetector(false, 5).ID: return 6715; case DaylightDetector::DaylightDetector(false, 6).ID: return 6716; case DaylightDetector::DaylightDetector(false, 7).ID: return 6717; case DaylightDetector::DaylightDetector(false, 8).ID: return 6718; case DaylightDetector::DaylightDetector(false, 9).ID: return 6719; case DaylightDetector::DaylightDetector(false, 10).ID: return 6720; case DaylightDetector::DaylightDetector(false, 11).ID: return 6721; case DaylightDetector::DaylightDetector(false, 12).ID: return 6722; case DaylightDetector::DaylightDetector(false, 13).ID: return 6723; case DaylightDetector::DaylightDetector(false, 14).ID: return 6724; case DaylightDetector::DaylightDetector(false, 15).ID: return 6725; case DeadBrainCoral::DeadBrainCoral().ID: return 9523; case DeadBrainCoralBlock::DeadBrainCoralBlock().ID: return 9511; case DeadBrainCoralFan::DeadBrainCoralFan().ID: return 9543; case DeadBrainCoralWallFan::DeadBrainCoralWallFan(eBlockFace::BLOCK_FACE_ZM).ID: return 9569; case DeadBrainCoralWallFan::DeadBrainCoralWallFan(eBlockFace::BLOCK_FACE_ZP).ID: return 9571; case DeadBrainCoralWallFan::DeadBrainCoralWallFan(eBlockFace::BLOCK_FACE_XM).ID: return 9573; case DeadBrainCoralWallFan::DeadBrainCoralWallFan(eBlockFace::BLOCK_FACE_XP).ID: return 9575; case DeadBubbleCoral::DeadBubbleCoral().ID: return 9525; case DeadBubbleCoralBlock::DeadBubbleCoralBlock().ID: return 9512; case DeadBubbleCoralFan::DeadBubbleCoralFan().ID: return 9545; case DeadBubbleCoralWallFan::DeadBubbleCoralWallFan(eBlockFace::BLOCK_FACE_ZM).ID: return 9577; case DeadBubbleCoralWallFan::DeadBubbleCoralWallFan(eBlockFace::BLOCK_FACE_ZP).ID: return 9579; case DeadBubbleCoralWallFan::DeadBubbleCoralWallFan(eBlockFace::BLOCK_FACE_XM).ID: return 9581; case DeadBubbleCoralWallFan::DeadBubbleCoralWallFan(eBlockFace::BLOCK_FACE_XP).ID: return 9583; case DeadBush::DeadBush().ID: return 1344; case DeadFireCoral::DeadFireCoral().ID: return 9527; case DeadFireCoralBlock::DeadFireCoralBlock().ID: return 9513; case DeadFireCoralFan::DeadFireCoralFan().ID: return 9547; case DeadFireCoralWallFan::DeadFireCoralWallFan(eBlockFace::BLOCK_FACE_ZM).ID: return 9585; case DeadFireCoralWallFan::DeadFireCoralWallFan(eBlockFace::BLOCK_FACE_ZP).ID: return 9587; case DeadFireCoralWallFan::DeadFireCoralWallFan(eBlockFace::BLOCK_FACE_XM).ID: return 9589; case DeadFireCoralWallFan::DeadFireCoralWallFan(eBlockFace::BLOCK_FACE_XP).ID: return 9591; case DeadHornCoral::DeadHornCoral().ID: return 9529; case DeadHornCoralBlock::DeadHornCoralBlock().ID: return 9514; case DeadHornCoralFan::DeadHornCoralFan().ID: return 9549; case DeadHornCoralWallFan::DeadHornCoralWallFan(eBlockFace::BLOCK_FACE_ZM).ID: return 9593; case DeadHornCoralWallFan::DeadHornCoralWallFan(eBlockFace::BLOCK_FACE_ZP).ID: return 9595; case DeadHornCoralWallFan::DeadHornCoralWallFan(eBlockFace::BLOCK_FACE_XM).ID: return 9597; case DeadHornCoralWallFan::DeadHornCoralWallFan(eBlockFace::BLOCK_FACE_XP).ID: return 9599; case DeadTubeCoral::DeadTubeCoral().ID: return 9521; case DeadTubeCoralBlock::DeadTubeCoralBlock().ID: return 9510; case DeadTubeCoralFan::DeadTubeCoralFan().ID: return 9541; case DeadTubeCoralWallFan::DeadTubeCoralWallFan(eBlockFace::BLOCK_FACE_ZM).ID: return 9561; case DeadTubeCoralWallFan::DeadTubeCoralWallFan(eBlockFace::BLOCK_FACE_ZP).ID: return 9563; case DeadTubeCoralWallFan::DeadTubeCoralWallFan(eBlockFace::BLOCK_FACE_XM).ID: return 9565; case DeadTubeCoralWallFan::DeadTubeCoralWallFan(eBlockFace::BLOCK_FACE_XP).ID: return 9567; case DetectorRail::DetectorRail(true, DetectorRail::Shape::NorthSouth).ID: return 1317; case DetectorRail::DetectorRail(true, DetectorRail::Shape::EastWest).ID: return 1318; case DetectorRail::DetectorRail(true, DetectorRail::Shape::AscendingEast).ID: return 1319; case DetectorRail::DetectorRail(true, DetectorRail::Shape::AscendingWest).ID: return 1320; case DetectorRail::DetectorRail(true, DetectorRail::Shape::AscendingNorth).ID: return 1321; case DetectorRail::DetectorRail(true, DetectorRail::Shape::AscendingSouth).ID: return 1322; case DetectorRail::DetectorRail(false, DetectorRail::Shape::NorthSouth).ID: return 1323; case DetectorRail::DetectorRail(false, DetectorRail::Shape::EastWest).ID: return 1324; case DetectorRail::DetectorRail(false, DetectorRail::Shape::AscendingEast).ID: return 1325; case DetectorRail::DetectorRail(false, DetectorRail::Shape::AscendingWest).ID: return 1326; case DetectorRail::DetectorRail(false, DetectorRail::Shape::AscendingNorth).ID: return 1327; case DetectorRail::DetectorRail(false, DetectorRail::Shape::AscendingSouth).ID: return 1328; case DiamondBlock::DiamondBlock().ID: return 3355; case DiamondOre::DiamondOre().ID: return 3354; case Diorite::Diorite().ID: return 4; case DioriteSlab::DioriteSlab(DioriteSlab::Type::Top).ID: return 10862; case DioriteSlab::DioriteSlab(DioriteSlab::Type::Bottom).ID: return 10864; case DioriteSlab::DioriteSlab(DioriteSlab::Type::Double).ID: return 10866; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_ZM, DioriteStairs::Half::Top, DioriteStairs::Shape::Straight).ID: return 10710; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_ZM, DioriteStairs::Half::Top, DioriteStairs::Shape::InnerLeft).ID: return 10712; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_ZM, DioriteStairs::Half::Top, DioriteStairs::Shape::InnerRight).ID: return 10714; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_ZM, DioriteStairs::Half::Top, DioriteStairs::Shape::OuterLeft).ID: return 10716; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_ZM, DioriteStairs::Half::Top, DioriteStairs::Shape::OuterRight).ID: return 10718; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_ZM, DioriteStairs::Half::Bottom, DioriteStairs::Shape::Straight).ID: return 10720; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_ZM, DioriteStairs::Half::Bottom, DioriteStairs::Shape::InnerLeft).ID: return 10722; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_ZM, DioriteStairs::Half::Bottom, DioriteStairs::Shape::InnerRight).ID: return 10724; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_ZM, DioriteStairs::Half::Bottom, DioriteStairs::Shape::OuterLeft).ID: return 10726; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_ZM, DioriteStairs::Half::Bottom, DioriteStairs::Shape::OuterRight).ID: return 10728; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_ZP, DioriteStairs::Half::Top, DioriteStairs::Shape::Straight).ID: return 10730; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_ZP, DioriteStairs::Half::Top, DioriteStairs::Shape::InnerLeft).ID: return 10732; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_ZP, DioriteStairs::Half::Top, DioriteStairs::Shape::InnerRight).ID: return 10734; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_ZP, DioriteStairs::Half::Top, DioriteStairs::Shape::OuterLeft).ID: return 10736; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_ZP, DioriteStairs::Half::Top, DioriteStairs::Shape::OuterRight).ID: return 10738; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_ZP, DioriteStairs::Half::Bottom, DioriteStairs::Shape::Straight).ID: return 10740; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_ZP, DioriteStairs::Half::Bottom, DioriteStairs::Shape::InnerLeft).ID: return 10742; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_ZP, DioriteStairs::Half::Bottom, DioriteStairs::Shape::InnerRight).ID: return 10744; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_ZP, DioriteStairs::Half::Bottom, DioriteStairs::Shape::OuterLeft).ID: return 10746; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_ZP, DioriteStairs::Half::Bottom, DioriteStairs::Shape::OuterRight).ID: return 10748; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_XM, DioriteStairs::Half::Top, DioriteStairs::Shape::Straight).ID: return 10750; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_XM, DioriteStairs::Half::Top, DioriteStairs::Shape::InnerLeft).ID: return 10752; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_XM, DioriteStairs::Half::Top, DioriteStairs::Shape::InnerRight).ID: return 10754; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_XM, DioriteStairs::Half::Top, DioriteStairs::Shape::OuterLeft).ID: return 10756; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_XM, DioriteStairs::Half::Top, DioriteStairs::Shape::OuterRight).ID: return 10758; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_XM, DioriteStairs::Half::Bottom, DioriteStairs::Shape::Straight).ID: return 10760; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_XM, DioriteStairs::Half::Bottom, DioriteStairs::Shape::InnerLeft).ID: return 10762; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_XM, DioriteStairs::Half::Bottom, DioriteStairs::Shape::InnerRight).ID: return 10764; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_XM, DioriteStairs::Half::Bottom, DioriteStairs::Shape::OuterLeft).ID: return 10766; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_XM, DioriteStairs::Half::Bottom, DioriteStairs::Shape::OuterRight).ID: return 10768; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_XP, DioriteStairs::Half::Top, DioriteStairs::Shape::Straight).ID: return 10770; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_XP, DioriteStairs::Half::Top, DioriteStairs::Shape::InnerLeft).ID: return 10772; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_XP, DioriteStairs::Half::Top, DioriteStairs::Shape::InnerRight).ID: return 10774; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_XP, DioriteStairs::Half::Top, DioriteStairs::Shape::OuterLeft).ID: return 10776; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_XP, DioriteStairs::Half::Top, DioriteStairs::Shape::OuterRight).ID: return 10778; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_XP, DioriteStairs::Half::Bottom, DioriteStairs::Shape::Straight).ID: return 10780; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_XP, DioriteStairs::Half::Bottom, DioriteStairs::Shape::InnerLeft).ID: return 10782; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_XP, DioriteStairs::Half::Bottom, DioriteStairs::Shape::InnerRight).ID: return 10784; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_XP, DioriteStairs::Half::Bottom, DioriteStairs::Shape::OuterLeft).ID: return 10786; case DioriteStairs::DioriteStairs(eBlockFace::BLOCK_FACE_XP, DioriteStairs::Half::Bottom, DioriteStairs::Shape::OuterRight).ID: return 10788; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::None, DioriteWall::South::None, true, DioriteWall::West::None).ID: return 14434; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::None, DioriteWall::South::None, true, DioriteWall::West::Low).ID: return 14435; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::None, DioriteWall::South::None, true, DioriteWall::West::Tall).ID: return 14436; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::None, DioriteWall::South::None, false, DioriteWall::West::None).ID: return 14440; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::None, DioriteWall::South::None, false, DioriteWall::West::Low).ID: return 14441; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::None, DioriteWall::South::None, false, DioriteWall::West::Tall).ID: return 14442; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::None, DioriteWall::South::Low, true, DioriteWall::West::None).ID: return 14446; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::None, DioriteWall::South::Low, true, DioriteWall::West::Low).ID: return 14447; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::None, DioriteWall::South::Low, true, DioriteWall::West::Tall).ID: return 14448; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::None, DioriteWall::South::Low, false, DioriteWall::West::None).ID: return 14452; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::None, DioriteWall::South::Low, false, DioriteWall::West::Low).ID: return 14453; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::None, DioriteWall::South::Low, false, DioriteWall::West::Tall).ID: return 14454; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::None, DioriteWall::South::Tall, true, DioriteWall::West::None).ID: return 14458; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::None, DioriteWall::South::Tall, true, DioriteWall::West::Low).ID: return 14459; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::None, DioriteWall::South::Tall, true, DioriteWall::West::Tall).ID: return 14460; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::None, DioriteWall::South::Tall, false, DioriteWall::West::None).ID: return 14464; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::None, DioriteWall::South::Tall, false, DioriteWall::West::Low).ID: return 14465; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::None, DioriteWall::South::Tall, false, DioriteWall::West::Tall).ID: return 14466; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::Low, DioriteWall::South::None, true, DioriteWall::West::None).ID: return 14470; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::Low, DioriteWall::South::None, true, DioriteWall::West::Low).ID: return 14471; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::Low, DioriteWall::South::None, true, DioriteWall::West::Tall).ID: return 14472; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::Low, DioriteWall::South::None, false, DioriteWall::West::None).ID: return 14476; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::Low, DioriteWall::South::None, false, DioriteWall::West::Low).ID: return 14477; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::Low, DioriteWall::South::None, false, DioriteWall::West::Tall).ID: return 14478; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::Low, DioriteWall::South::Low, true, DioriteWall::West::None).ID: return 14482; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::Low, DioriteWall::South::Low, true, DioriteWall::West::Low).ID: return 14483; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::Low, DioriteWall::South::Low, true, DioriteWall::West::Tall).ID: return 14484; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::Low, DioriteWall::South::Low, false, DioriteWall::West::None).ID: return 14488; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::Low, DioriteWall::South::Low, false, DioriteWall::West::Low).ID: return 14489; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::Low, DioriteWall::South::Low, false, DioriteWall::West::Tall).ID: return 14490; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::Low, DioriteWall::South::Tall, true, DioriteWall::West::None).ID: return 14494; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::Low, DioriteWall::South::Tall, true, DioriteWall::West::Low).ID: return 14495; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::Low, DioriteWall::South::Tall, true, DioriteWall::West::Tall).ID: return 14496; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::Low, DioriteWall::South::Tall, false, DioriteWall::West::None).ID: return 14500; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::Low, DioriteWall::South::Tall, false, DioriteWall::West::Low).ID: return 14501; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::Low, DioriteWall::South::Tall, false, DioriteWall::West::Tall).ID: return 14502; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::Tall, DioriteWall::South::None, true, DioriteWall::West::None).ID: return 14506; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::Tall, DioriteWall::South::None, true, DioriteWall::West::Low).ID: return 14507; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::Tall, DioriteWall::South::None, true, DioriteWall::West::Tall).ID: return 14508; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::Tall, DioriteWall::South::None, false, DioriteWall::West::None).ID: return 14512; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::Tall, DioriteWall::South::None, false, DioriteWall::West::Low).ID: return 14513; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::Tall, DioriteWall::South::None, false, DioriteWall::West::Tall).ID: return 14514; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::Tall, DioriteWall::South::Low, true, DioriteWall::West::None).ID: return 14518; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::Tall, DioriteWall::South::Low, true, DioriteWall::West::Low).ID: return 14519; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::Tall, DioriteWall::South::Low, true, DioriteWall::West::Tall).ID: return 14520; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::Tall, DioriteWall::South::Low, false, DioriteWall::West::None).ID: return 14524; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::Tall, DioriteWall::South::Low, false, DioriteWall::West::Low).ID: return 14525; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::Tall, DioriteWall::South::Low, false, DioriteWall::West::Tall).ID: return 14526; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::Tall, DioriteWall::South::Tall, true, DioriteWall::West::None).ID: return 14530; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::Tall, DioriteWall::South::Tall, true, DioriteWall::West::Low).ID: return 14531; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::Tall, DioriteWall::South::Tall, true, DioriteWall::West::Tall).ID: return 14532; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::Tall, DioriteWall::South::Tall, false, DioriteWall::West::None).ID: return 14536; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::Tall, DioriteWall::South::Tall, false, DioriteWall::West::Low).ID: return 14537; case DioriteWall::DioriteWall(DioriteWall::East::None, DioriteWall::North::Tall, DioriteWall::South::Tall, false, DioriteWall::West::Tall).ID: return 14538; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::None, DioriteWall::South::None, true, DioriteWall::West::None).ID: return 14542; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::None, DioriteWall::South::None, true, DioriteWall::West::Low).ID: return 14543; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::None, DioriteWall::South::None, true, DioriteWall::West::Tall).ID: return 14544; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::None, DioriteWall::South::None, false, DioriteWall::West::None).ID: return 14548; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::None, DioriteWall::South::None, false, DioriteWall::West::Low).ID: return 14549; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::None, DioriteWall::South::None, false, DioriteWall::West::Tall).ID: return 14550; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::None, DioriteWall::South::Low, true, DioriteWall::West::None).ID: return 14554; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::None, DioriteWall::South::Low, true, DioriteWall::West::Low).ID: return 14555; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::None, DioriteWall::South::Low, true, DioriteWall::West::Tall).ID: return 14556; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::None, DioriteWall::South::Low, false, DioriteWall::West::None).ID: return 14560; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::None, DioriteWall::South::Low, false, DioriteWall::West::Low).ID: return 14561; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::None, DioriteWall::South::Low, false, DioriteWall::West::Tall).ID: return 14562; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::None, DioriteWall::South::Tall, true, DioriteWall::West::None).ID: return 14566; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::None, DioriteWall::South::Tall, true, DioriteWall::West::Low).ID: return 14567; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::None, DioriteWall::South::Tall, true, DioriteWall::West::Tall).ID: return 14568; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::None, DioriteWall::South::Tall, false, DioriteWall::West::None).ID: return 14572; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::None, DioriteWall::South::Tall, false, DioriteWall::West::Low).ID: return 14573; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::None, DioriteWall::South::Tall, false, DioriteWall::West::Tall).ID: return 14574; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::Low, DioriteWall::South::None, true, DioriteWall::West::None).ID: return 14578; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::Low, DioriteWall::South::None, true, DioriteWall::West::Low).ID: return 14579; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::Low, DioriteWall::South::None, true, DioriteWall::West::Tall).ID: return 14580; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::Low, DioriteWall::South::None, false, DioriteWall::West::None).ID: return 14584; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::Low, DioriteWall::South::None, false, DioriteWall::West::Low).ID: return 14585; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::Low, DioriteWall::South::None, false, DioriteWall::West::Tall).ID: return 14586; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::Low, DioriteWall::South::Low, true, DioriteWall::West::None).ID: return 14590; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::Low, DioriteWall::South::Low, true, DioriteWall::West::Low).ID: return 14591; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::Low, DioriteWall::South::Low, true, DioriteWall::West::Tall).ID: return 14592; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::Low, DioriteWall::South::Low, false, DioriteWall::West::None).ID: return 14596; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::Low, DioriteWall::South::Low, false, DioriteWall::West::Low).ID: return 14597; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::Low, DioriteWall::South::Low, false, DioriteWall::West::Tall).ID: return 14598; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::Low, DioriteWall::South::Tall, true, DioriteWall::West::None).ID: return 14602; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::Low, DioriteWall::South::Tall, true, DioriteWall::West::Low).ID: return 14603; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::Low, DioriteWall::South::Tall, true, DioriteWall::West::Tall).ID: return 14604; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::Low, DioriteWall::South::Tall, false, DioriteWall::West::None).ID: return 14608; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::Low, DioriteWall::South::Tall, false, DioriteWall::West::Low).ID: return 14609; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::Low, DioriteWall::South::Tall, false, DioriteWall::West::Tall).ID: return 14610; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::Tall, DioriteWall::South::None, true, DioriteWall::West::None).ID: return 14614; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::Tall, DioriteWall::South::None, true, DioriteWall::West::Low).ID: return 14615; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::Tall, DioriteWall::South::None, true, DioriteWall::West::Tall).ID: return 14616; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::Tall, DioriteWall::South::None, false, DioriteWall::West::None).ID: return 14620; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::Tall, DioriteWall::South::None, false, DioriteWall::West::Low).ID: return 14621; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::Tall, DioriteWall::South::None, false, DioriteWall::West::Tall).ID: return 14622; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::Tall, DioriteWall::South::Low, true, DioriteWall::West::None).ID: return 14626; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::Tall, DioriteWall::South::Low, true, DioriteWall::West::Low).ID: return 14627; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::Tall, DioriteWall::South::Low, true, DioriteWall::West::Tall).ID: return 14628; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::Tall, DioriteWall::South::Low, false, DioriteWall::West::None).ID: return 14632; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::Tall, DioriteWall::South::Low, false, DioriteWall::West::Low).ID: return 14633; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::Tall, DioriteWall::South::Low, false, DioriteWall::West::Tall).ID: return 14634; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::Tall, DioriteWall::South::Tall, true, DioriteWall::West::None).ID: return 14638; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::Tall, DioriteWall::South::Tall, true, DioriteWall::West::Low).ID: return 14639; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::Tall, DioriteWall::South::Tall, true, DioriteWall::West::Tall).ID: return 14640; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::Tall, DioriteWall::South::Tall, false, DioriteWall::West::None).ID: return 14644; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::Tall, DioriteWall::South::Tall, false, DioriteWall::West::Low).ID: return 14645; case DioriteWall::DioriteWall(DioriteWall::East::Low, DioriteWall::North::Tall, DioriteWall::South::Tall, false, DioriteWall::West::Tall).ID: return 14646; case DioriteWall::DioriteWall(DioriteWall::East::Tall, DioriteWall::North::None, DioriteWall::South::None, true, DioriteWall::West::None).ID: return 14650; case DioriteWall::DioriteWall(DioriteWall::East::Tall, DioriteWall::North::None, DioriteWall::South::None, true, DioriteWall::West::Low).ID: return 14651; case DioriteWall::DioriteWall(DioriteWall::East::Tall, DioriteWall::North::None, DioriteWall::South::None, true, DioriteWall::West::Tall).ID: return 14652; case DioriteWall::DioriteWall(DioriteWall::East::Tall, DioriteWall::North::None, DioriteWall::South::None, false, DioriteWall::West::None).ID: return 14656; case DioriteWall::DioriteWall(DioriteWall::East::Tall, DioriteWall::North::None, DioriteWall::South::None, false, DioriteWall::West::Low).ID: return 14657; case DioriteWall::DioriteWall(DioriteWall::East::Tall, DioriteWall::North::None, DioriteWall::South::None, false, DioriteWall::West::Tall).ID: return 14658; case DioriteWall::DioriteWall(DioriteWall::East::Tall, DioriteWall::North::None, DioriteWall::South::Low, true, DioriteWall::West::None).ID: return 14662; case DioriteWall::DioriteWall(DioriteWall::East::Tall, DioriteWall::North::None, DioriteWall::South::Low, true, DioriteWall::West::Low).ID: return 14663; case DioriteWall::DioriteWall(DioriteWall::East::Tall, DioriteWall::North::None, DioriteWall::South::Low, true, DioriteWall::West::Tall).ID: return 14664; case DioriteWall::DioriteWall(DioriteWall::East::Tall, DioriteWall::North::None, DioriteWall::South::Low, false, DioriteWall::West::None).ID: return 14668; case DioriteWall::DioriteWall(DioriteWall::East::Tall, DioriteWall::North::None, DioriteWall::South::Low, false, DioriteWall::West::Low).ID: return 14669; case DioriteWall::DioriteWall(DioriteWall::East::Tall, DioriteWall::North::None, DioriteWall::South::Low, false, DioriteWall::West::Tall).ID: return 14670; case DioriteWall::DioriteWall(DioriteWall::East::Tall, DioriteWall::North::None, DioriteWall::South::Tall, true, DioriteWall::West::None).ID: return 14674; case DioriteWall::DioriteWall(DioriteWall::East::Tall, DioriteWall::North::None, DioriteWall::South::Tall, true, DioriteWall::West::Low).ID: return 14675; case DioriteWall::DioriteWall(DioriteWall::East::Tall, DioriteWall::North::None, DioriteWall::South::Tall, true, DioriteWall::West::Tall).ID: return 14676; case DioriteWall::DioriteWall(DioriteWall::East::Tall, DioriteWall::North::None, DioriteWall::South::Tall, false, DioriteWall::West::None).ID: return 14680; case DioriteWall::DioriteWall(DioriteWall::East::Tall, DioriteWall::North::None, DioriteWall::South::Tall, false, DioriteWall::West::Low).ID: return 14681; case DioriteWall::DioriteWall(DioriteWall::East::Tall, DioriteWall::North::None, DioriteWall::South::Tall, false, DioriteWall::West::Tall).ID: return 14682; case DioriteWall::DioriteWall(DioriteWall::East::Tall, DioriteWall::North::Low, DioriteWall::South::None, true, DioriteWall::West::None).ID: return 14686; case DioriteWall::DioriteWall(DioriteWall::East::Tall, DioriteWall::North::Low, DioriteWall::South::None, true, DioriteWall::West::Low).ID: return 14687; case DioriteWall::DioriteWall(DioriteWall::East::Tall, DioriteWall::North::Low, DioriteWall::South::None, true, DioriteWall::West::Tall).ID: return 14688; case DioriteWall::DioriteWall(DioriteWall::East::Tall, DioriteWall::North::Low, DioriteWall::South::None, false, DioriteWall::West::None).ID: return 14692; case DioriteWall::DioriteWall(DioriteWall::East::Tall, DioriteWall::North::Low, DioriteWall::South::None, false, DioriteWall::West::Low).ID: return 14693; case DioriteWall::DioriteWall(DioriteWall::East::Tall, DioriteWall::North::Low, DioriteWall::South::None, false, DioriteWall::West::Tall).ID: return 14694; case DioriteWall::DioriteWall(DioriteWall::East::Tall, DioriteWall::North::Low, DioriteWall::South::Low, true, DioriteWall::West::None).ID: return 14698; case DioriteWall::DioriteWall(DioriteWall::East::Tall, DioriteWall::North::Low, DioriteWall::South::Low, true, DioriteWall::West::Low).ID: return 14699; case DioriteWall::DioriteWall(DioriteWall::East::Tall, DioriteWall::North::Low, DioriteWall::South::Low, true, DioriteWall::West::Tall).ID: return 14700; case DioriteWall::DioriteWall(DioriteWall::East::Tall, DioriteWall::North::Low, DioriteWall::South::Low, false, DioriteWall::West::None).ID: return 14704; case DioriteWall::DioriteWall(DioriteWall::East::Tall, DioriteWall::North::Low, DioriteWall::South::Low, false, DioriteWall::West::Low).ID: return 14705; case DioriteWall::DioriteWall(DioriteWall::East::Tall, DioriteWall::North::Low, DioriteWall::South::Low, false, DioriteWall::West::Tall).ID: return 14706; case DioriteWall::DioriteWall(DioriteWall::East::Tall, DioriteWall::North::Low, DioriteWall::South::Tall, true, DioriteWall::West::None).ID: return 14710; case DioriteWall::DioriteWall(DioriteWall::East::Tall, DioriteWall::North::Low, DioriteWall::South::Tall, true, DioriteWall::West::Low).ID: return 14711; case DioriteWall::DioriteWall(DioriteWall::East::Tall, DioriteWall::North::Low, DioriteWall::South::Tall, true, DioriteWall::West::Tall).ID: return 14712; case DioriteWall::DioriteWall(DioriteWall::East::Tall, DioriteWall::North::Low, DioriteWall::South::Tall, false, DioriteWall::West::None).ID: return 14716; case DioriteWall::DioriteWall(DioriteWall::East::Tall, DioriteWall::North::Low, DioriteWall::South::Tall, false, DioriteWall::West::Low).ID: return 14717; case DioriteWall::DioriteWall(DioriteWall::East::Tall, DioriteWall::North::Low, DioriteWall::South::Tall, false, DioriteWall::West::Tall).ID: return 14718; case DioriteWall::DioriteWall(DioriteWall::East::Tall, DioriteWall::North::Tall, DioriteWall::South::None, true, DioriteWall::West::None).ID: return 14722; case DioriteWall::DioriteWall(DioriteWall::East::Tall, DioriteWall::North::Tall, DioriteWall::South::None, true, DioriteWall::West::Low).ID: return 14723; case DioriteWall::DioriteWall(DioriteWall::East::Tall, DioriteWall::North::Tall, DioriteWall::South::None, true, DioriteWall::West::Tall).ID: return 14724; case DioriteWall::DioriteWall(DioriteWall::East::Tall, DioriteWall::North::Tall, DioriteWall::South::None, false, DioriteWall::West::None).ID: return 14728; case DioriteWall::DioriteWall(DioriteWall::East::Tall, DioriteWall::North::Tall, DioriteWall::South::None, false, DioriteWall::West::Low).ID: return 14729; case DioriteWall::DioriteWall(DioriteWall::East::Tall, DioriteWall::North::Tall, DioriteWall::South::None, false, DioriteWall::West::Tall).ID: return 14730; case DioriteWall::DioriteWall(DioriteWall::East::Tall, DioriteWall::North::Tall, DioriteWall::South::Low, true, DioriteWall::West::None).ID: return 14734; case DioriteWall::DioriteWall(DioriteWall::East::Tall, DioriteWall::North::Tall, DioriteWall::South::Low, true, DioriteWall::West::Low).ID: return 14735; case DioriteWall::DioriteWall(DioriteWall::East::Tall, DioriteWall::North::Tall, DioriteWall::South::Low, true, DioriteWall::West::Tall).ID: return 14736; case DioriteWall::DioriteWall(DioriteWall::East::Tall, DioriteWall::North::Tall, DioriteWall::South::Low, false, DioriteWall::West::None).ID: return 14740; case DioriteWall::DioriteWall(DioriteWall::East::Tall, DioriteWall::North::Tall, DioriteWall::South::Low, false, DioriteWall::West::Low).ID: return 14741; case DioriteWall::DioriteWall(DioriteWall::East::Tall, DioriteWall::North::Tall, DioriteWall::South::Low, false, DioriteWall::West::Tall).ID: return 14742; case DioriteWall::DioriteWall(DioriteWall::East::Tall, DioriteWall::North::Tall, DioriteWall::South::Tall, true, DioriteWall::West::None).ID: return 14746; case DioriteWall::DioriteWall(DioriteWall::East::Tall, DioriteWall::North::Tall, DioriteWall::South::Tall, true, DioriteWall::West::Low).ID: return 14747; case DioriteWall::DioriteWall(DioriteWall::East::Tall, DioriteWall::North::Tall, DioriteWall::South::Tall, true, DioriteWall::West::Tall).ID: return 14748; case DioriteWall::DioriteWall(DioriteWall::East::Tall, DioriteWall::North::Tall, DioriteWall::South::Tall, false, DioriteWall::West::None).ID: return 14752; case DioriteWall::DioriteWall(DioriteWall::East::Tall, DioriteWall::North::Tall, DioriteWall::South::Tall, false, DioriteWall::West::Low).ID: return 14753; case DioriteWall::DioriteWall(DioriteWall::East::Tall, DioriteWall::North::Tall, DioriteWall::South::Tall, false, DioriteWall::West::Tall).ID: return 14754; case Dirt::Dirt().ID: return 10; case Dispenser::Dispenser(eBlockFace::BLOCK_FACE_ZM, true).ID: return 234; case Dispenser::Dispenser(eBlockFace::BLOCK_FACE_ZM, false).ID: return 235; case Dispenser::Dispenser(eBlockFace::BLOCK_FACE_XP, true).ID: return 236; case Dispenser::Dispenser(eBlockFace::BLOCK_FACE_XP, false).ID: return 237; case Dispenser::Dispenser(eBlockFace::BLOCK_FACE_ZP, true).ID: return 238; case Dispenser::Dispenser(eBlockFace::BLOCK_FACE_ZP, false).ID: return 239; case Dispenser::Dispenser(eBlockFace::BLOCK_FACE_XM, true).ID: return 240; case Dispenser::Dispenser(eBlockFace::BLOCK_FACE_XM, false).ID: return 241; case Dispenser::Dispenser(eBlockFace::BLOCK_FACE_YP, true).ID: return 242; case Dispenser::Dispenser(eBlockFace::BLOCK_FACE_YP, false).ID: return 243; case Dispenser::Dispenser(eBlockFace::BLOCK_FACE_YM, true).ID: return 244; case Dispenser::Dispenser(eBlockFace::BLOCK_FACE_YM, false).ID: return 245; case DragonEgg::DragonEgg().ID: return 5155; case DragonHead::DragonHead(0).ID: return 6590; case DragonHead::DragonHead(1).ID: return 6591; case DragonHead::DragonHead(2).ID: return 6592; case DragonHead::DragonHead(3).ID: return 6593; case DragonHead::DragonHead(4).ID: return 6594; case DragonHead::DragonHead(5).ID: return 6595; case DragonHead::DragonHead(6).ID: return 6596; case DragonHead::DragonHead(7).ID: return 6597; case DragonHead::DragonHead(8).ID: return 6598; case DragonHead::DragonHead(9).ID: return 6599; case DragonHead::DragonHead(10).ID: return 6600; case DragonHead::DragonHead(11).ID: return 6601; case DragonHead::DragonHead(12).ID: return 6602; case DragonHead::DragonHead(13).ID: return 6603; case DragonHead::DragonHead(14).ID: return 6604; case DragonHead::DragonHead(15).ID: return 6605; case DragonWallHead::DragonWallHead(eBlockFace::BLOCK_FACE_ZM).ID: return 6606; case DragonWallHead::DragonWallHead(eBlockFace::BLOCK_FACE_ZP).ID: return 6607; case DragonWallHead::DragonWallHead(eBlockFace::BLOCK_FACE_XM).ID: return 6608; case DragonWallHead::DragonWallHead(eBlockFace::BLOCK_FACE_XP).ID: return 6609; case DriedKelpBlock::DriedKelpBlock().ID: return 9497; case Dropper::Dropper(eBlockFace::BLOCK_FACE_ZM, true).ID: return 6835; case Dropper::Dropper(eBlockFace::BLOCK_FACE_ZM, false).ID: return 6836; case Dropper::Dropper(eBlockFace::BLOCK_FACE_XP, true).ID: return 6837; case Dropper::Dropper(eBlockFace::BLOCK_FACE_XP, false).ID: return 6838; case Dropper::Dropper(eBlockFace::BLOCK_FACE_ZP, true).ID: return 6839; case Dropper::Dropper(eBlockFace::BLOCK_FACE_ZP, false).ID: return 6840; case Dropper::Dropper(eBlockFace::BLOCK_FACE_XM, true).ID: return 6841; case Dropper::Dropper(eBlockFace::BLOCK_FACE_XM, false).ID: return 6842; case Dropper::Dropper(eBlockFace::BLOCK_FACE_YP, true).ID: return 6843; case Dropper::Dropper(eBlockFace::BLOCK_FACE_YP, false).ID: return 6844; case Dropper::Dropper(eBlockFace::BLOCK_FACE_YM, true).ID: return 6845; case Dropper::Dropper(eBlockFace::BLOCK_FACE_YM, false).ID: return 6846; case EmeraldBlock::EmeraldBlock().ID: return 5403; case EmeraldOre::EmeraldOre().ID: return 5250; case EnchantingTable::EnchantingTable().ID: return 5132; case EndGateway::EndGateway().ID: return 9224; case EndPortal::EndPortal().ID: return 5145; case EndPortalFrame::EndPortalFrame(true, eBlockFace::BLOCK_FACE_ZM).ID: return 5146; case EndPortalFrame::EndPortalFrame(true, eBlockFace::BLOCK_FACE_ZP).ID: return 5147; case EndPortalFrame::EndPortalFrame(true, eBlockFace::BLOCK_FACE_XM).ID: return 5148; case EndPortalFrame::EndPortalFrame(true, eBlockFace::BLOCK_FACE_XP).ID: return 5149; case EndPortalFrame::EndPortalFrame(false, eBlockFace::BLOCK_FACE_ZM).ID: return 5150; case EndPortalFrame::EndPortalFrame(false, eBlockFace::BLOCK_FACE_ZP).ID: return 5151; case EndPortalFrame::EndPortalFrame(false, eBlockFace::BLOCK_FACE_XM).ID: return 5152; case EndPortalFrame::EndPortalFrame(false, eBlockFace::BLOCK_FACE_XP).ID: return 5153; case EndRod::EndRod(eBlockFace::BLOCK_FACE_ZM).ID: return 9058; case EndRod::EndRod(eBlockFace::BLOCK_FACE_XP).ID: return 9059; case EndRod::EndRod(eBlockFace::BLOCK_FACE_ZP).ID: return 9060; case EndRod::EndRod(eBlockFace::BLOCK_FACE_XM).ID: return 9061; case EndRod::EndRod(eBlockFace::BLOCK_FACE_YP).ID: return 9062; case EndRod::EndRod(eBlockFace::BLOCK_FACE_YM).ID: return 9063; case EndStone::EndStone().ID: return 5154; case EndStoneBrickSlab::EndStoneBrickSlab(EndStoneBrickSlab::Type::Top).ID: return 10820; case EndStoneBrickSlab::EndStoneBrickSlab(EndStoneBrickSlab::Type::Bottom).ID: return 10822; case EndStoneBrickSlab::EndStoneBrickSlab(EndStoneBrickSlab::Type::Double).ID: return 10824; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, EndStoneBrickStairs::Half::Top, EndStoneBrickStairs::Shape::Straight).ID: return 10070; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, EndStoneBrickStairs::Half::Top, EndStoneBrickStairs::Shape::InnerLeft).ID: return 10072; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, EndStoneBrickStairs::Half::Top, EndStoneBrickStairs::Shape::InnerRight).ID: return 10074; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, EndStoneBrickStairs::Half::Top, EndStoneBrickStairs::Shape::OuterLeft).ID: return 10076; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, EndStoneBrickStairs::Half::Top, EndStoneBrickStairs::Shape::OuterRight).ID: return 10078; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, EndStoneBrickStairs::Half::Bottom, EndStoneBrickStairs::Shape::Straight).ID: return 10080; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, EndStoneBrickStairs::Half::Bottom, EndStoneBrickStairs::Shape::InnerLeft).ID: return 10082; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, EndStoneBrickStairs::Half::Bottom, EndStoneBrickStairs::Shape::InnerRight).ID: return 10084; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, EndStoneBrickStairs::Half::Bottom, EndStoneBrickStairs::Shape::OuterLeft).ID: return 10086; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, EndStoneBrickStairs::Half::Bottom, EndStoneBrickStairs::Shape::OuterRight).ID: return 10088; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, EndStoneBrickStairs::Half::Top, EndStoneBrickStairs::Shape::Straight).ID: return 10090; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, EndStoneBrickStairs::Half::Top, EndStoneBrickStairs::Shape::InnerLeft).ID: return 10092; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, EndStoneBrickStairs::Half::Top, EndStoneBrickStairs::Shape::InnerRight).ID: return 10094; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, EndStoneBrickStairs::Half::Top, EndStoneBrickStairs::Shape::OuterLeft).ID: return 10096; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, EndStoneBrickStairs::Half::Top, EndStoneBrickStairs::Shape::OuterRight).ID: return 10098; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, EndStoneBrickStairs::Half::Bottom, EndStoneBrickStairs::Shape::Straight).ID: return 10100; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, EndStoneBrickStairs::Half::Bottom, EndStoneBrickStairs::Shape::InnerLeft).ID: return 10102; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, EndStoneBrickStairs::Half::Bottom, EndStoneBrickStairs::Shape::InnerRight).ID: return 10104; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, EndStoneBrickStairs::Half::Bottom, EndStoneBrickStairs::Shape::OuterLeft).ID: return 10106; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, EndStoneBrickStairs::Half::Bottom, EndStoneBrickStairs::Shape::OuterRight).ID: return 10108; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_XM, EndStoneBrickStairs::Half::Top, EndStoneBrickStairs::Shape::Straight).ID: return 10110; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_XM, EndStoneBrickStairs::Half::Top, EndStoneBrickStairs::Shape::InnerLeft).ID: return 10112; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_XM, EndStoneBrickStairs::Half::Top, EndStoneBrickStairs::Shape::InnerRight).ID: return 10114; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_XM, EndStoneBrickStairs::Half::Top, EndStoneBrickStairs::Shape::OuterLeft).ID: return 10116; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_XM, EndStoneBrickStairs::Half::Top, EndStoneBrickStairs::Shape::OuterRight).ID: return 10118; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_XM, EndStoneBrickStairs::Half::Bottom, EndStoneBrickStairs::Shape::Straight).ID: return 10120; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_XM, EndStoneBrickStairs::Half::Bottom, EndStoneBrickStairs::Shape::InnerLeft).ID: return 10122; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_XM, EndStoneBrickStairs::Half::Bottom, EndStoneBrickStairs::Shape::InnerRight).ID: return 10124; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_XM, EndStoneBrickStairs::Half::Bottom, EndStoneBrickStairs::Shape::OuterLeft).ID: return 10126; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_XM, EndStoneBrickStairs::Half::Bottom, EndStoneBrickStairs::Shape::OuterRight).ID: return 10128; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_XP, EndStoneBrickStairs::Half::Top, EndStoneBrickStairs::Shape::Straight).ID: return 10130; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_XP, EndStoneBrickStairs::Half::Top, EndStoneBrickStairs::Shape::InnerLeft).ID: return 10132; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_XP, EndStoneBrickStairs::Half::Top, EndStoneBrickStairs::Shape::InnerRight).ID: return 10134; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_XP, EndStoneBrickStairs::Half::Top, EndStoneBrickStairs::Shape::OuterLeft).ID: return 10136; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_XP, EndStoneBrickStairs::Half::Top, EndStoneBrickStairs::Shape::OuterRight).ID: return 10138; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_XP, EndStoneBrickStairs::Half::Bottom, EndStoneBrickStairs::Shape::Straight).ID: return 10140; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_XP, EndStoneBrickStairs::Half::Bottom, EndStoneBrickStairs::Shape::InnerLeft).ID: return 10142; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_XP, EndStoneBrickStairs::Half::Bottom, EndStoneBrickStairs::Shape::InnerRight).ID: return 10144; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_XP, EndStoneBrickStairs::Half::Bottom, EndStoneBrickStairs::Shape::OuterLeft).ID: return 10146; case EndStoneBrickStairs::EndStoneBrickStairs(eBlockFace::BLOCK_FACE_XP, EndStoneBrickStairs::Half::Bottom, EndStoneBrickStairs::Shape::OuterRight).ID: return 10148; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::None, EndStoneBrickWall::South::None, true, EndStoneBrickWall::West::None).ID: return 14110; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::None, EndStoneBrickWall::South::None, true, EndStoneBrickWall::West::Low).ID: return 14111; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::None, EndStoneBrickWall::South::None, true, EndStoneBrickWall::West::Tall).ID: return 14112; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::None, EndStoneBrickWall::South::None, false, EndStoneBrickWall::West::None).ID: return 14116; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::None, EndStoneBrickWall::South::None, false, EndStoneBrickWall::West::Low).ID: return 14117; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::None, EndStoneBrickWall::South::None, false, EndStoneBrickWall::West::Tall).ID: return 14118; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::None, EndStoneBrickWall::South::Low, true, EndStoneBrickWall::West::None).ID: return 14122; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::None, EndStoneBrickWall::South::Low, true, EndStoneBrickWall::West::Low).ID: return 14123; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::None, EndStoneBrickWall::South::Low, true, EndStoneBrickWall::West::Tall).ID: return 14124; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::None, EndStoneBrickWall::South::Low, false, EndStoneBrickWall::West::None).ID: return 14128; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::None, EndStoneBrickWall::South::Low, false, EndStoneBrickWall::West::Low).ID: return 14129; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::None, EndStoneBrickWall::South::Low, false, EndStoneBrickWall::West::Tall).ID: return 14130; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::None, EndStoneBrickWall::South::Tall, true, EndStoneBrickWall::West::None).ID: return 14134; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::None, EndStoneBrickWall::South::Tall, true, EndStoneBrickWall::West::Low).ID: return 14135; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::None, EndStoneBrickWall::South::Tall, true, EndStoneBrickWall::West::Tall).ID: return 14136; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::None, EndStoneBrickWall::South::Tall, false, EndStoneBrickWall::West::None).ID: return 14140; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::None, EndStoneBrickWall::South::Tall, false, EndStoneBrickWall::West::Low).ID: return 14141; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::None, EndStoneBrickWall::South::Tall, false, EndStoneBrickWall::West::Tall).ID: return 14142; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::None, true, EndStoneBrickWall::West::None).ID: return 14146; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::None, true, EndStoneBrickWall::West::Low).ID: return 14147; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::None, true, EndStoneBrickWall::West::Tall).ID: return 14148; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::None, false, EndStoneBrickWall::West::None).ID: return 14152; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::None, false, EndStoneBrickWall::West::Low).ID: return 14153; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::None, false, EndStoneBrickWall::West::Tall).ID: return 14154; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::Low, true, EndStoneBrickWall::West::None).ID: return 14158; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::Low, true, EndStoneBrickWall::West::Low).ID: return 14159; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::Low, true, EndStoneBrickWall::West::Tall).ID: return 14160; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::Low, false, EndStoneBrickWall::West::None).ID: return 14164; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::Low, false, EndStoneBrickWall::West::Low).ID: return 14165; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::Low, false, EndStoneBrickWall::West::Tall).ID: return 14166; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::Tall, true, EndStoneBrickWall::West::None).ID: return 14170; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::Tall, true, EndStoneBrickWall::West::Low).ID: return 14171; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::Tall, true, EndStoneBrickWall::West::Tall).ID: return 14172; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::Tall, false, EndStoneBrickWall::West::None).ID: return 14176; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::Tall, false, EndStoneBrickWall::West::Low).ID: return 14177; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::Tall, false, EndStoneBrickWall::West::Tall).ID: return 14178; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::Tall, EndStoneBrickWall::South::None, true, EndStoneBrickWall::West::None).ID: return 14182; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::Tall, EndStoneBrickWall::South::None, true, EndStoneBrickWall::West::Low).ID: return 14183; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::Tall, EndStoneBrickWall::South::None, true, EndStoneBrickWall::West::Tall).ID: return 14184; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::Tall, EndStoneBrickWall::South::None, false, EndStoneBrickWall::West::None).ID: return 14188; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::Tall, EndStoneBrickWall::South::None, false, EndStoneBrickWall::West::Low).ID: return 14189; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::Tall, EndStoneBrickWall::South::None, false, EndStoneBrickWall::West::Tall).ID: return 14190; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::Tall, EndStoneBrickWall::South::Low, true, EndStoneBrickWall::West::None).ID: return 14194; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::Tall, EndStoneBrickWall::South::Low, true, EndStoneBrickWall::West::Low).ID: return 14195; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::Tall, EndStoneBrickWall::South::Low, true, EndStoneBrickWall::West::Tall).ID: return 14196; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::Tall, EndStoneBrickWall::South::Low, false, EndStoneBrickWall::West::None).ID: return 14200; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::Tall, EndStoneBrickWall::South::Low, false, EndStoneBrickWall::West::Low).ID: return 14201; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::Tall, EndStoneBrickWall::South::Low, false, EndStoneBrickWall::West::Tall).ID: return 14202; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::Tall, EndStoneBrickWall::South::Tall, true, EndStoneBrickWall::West::None).ID: return 14206; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::Tall, EndStoneBrickWall::South::Tall, true, EndStoneBrickWall::West::Low).ID: return 14207; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::Tall, EndStoneBrickWall::South::Tall, true, EndStoneBrickWall::West::Tall).ID: return 14208; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::Tall, EndStoneBrickWall::South::Tall, false, EndStoneBrickWall::West::None).ID: return 14212; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::Tall, EndStoneBrickWall::South::Tall, false, EndStoneBrickWall::West::Low).ID: return 14213; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::None, EndStoneBrickWall::North::Tall, EndStoneBrickWall::South::Tall, false, EndStoneBrickWall::West::Tall).ID: return 14214; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::None, EndStoneBrickWall::South::None, true, EndStoneBrickWall::West::None).ID: return 14218; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::None, EndStoneBrickWall::South::None, true, EndStoneBrickWall::West::Low).ID: return 14219; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::None, EndStoneBrickWall::South::None, true, EndStoneBrickWall::West::Tall).ID: return 14220; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::None, EndStoneBrickWall::South::None, false, EndStoneBrickWall::West::None).ID: return 14224; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::None, EndStoneBrickWall::South::None, false, EndStoneBrickWall::West::Low).ID: return 14225; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::None, EndStoneBrickWall::South::None, false, EndStoneBrickWall::West::Tall).ID: return 14226; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::None, EndStoneBrickWall::South::Low, true, EndStoneBrickWall::West::None).ID: return 14230; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::None, EndStoneBrickWall::South::Low, true, EndStoneBrickWall::West::Low).ID: return 14231; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::None, EndStoneBrickWall::South::Low, true, EndStoneBrickWall::West::Tall).ID: return 14232; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::None, EndStoneBrickWall::South::Low, false, EndStoneBrickWall::West::None).ID: return 14236; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::None, EndStoneBrickWall::South::Low, false, EndStoneBrickWall::West::Low).ID: return 14237; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::None, EndStoneBrickWall::South::Low, false, EndStoneBrickWall::West::Tall).ID: return 14238; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::None, EndStoneBrickWall::South::Tall, true, EndStoneBrickWall::West::None).ID: return 14242; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::None, EndStoneBrickWall::South::Tall, true, EndStoneBrickWall::West::Low).ID: return 14243; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::None, EndStoneBrickWall::South::Tall, true, EndStoneBrickWall::West::Tall).ID: return 14244; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::None, EndStoneBrickWall::South::Tall, false, EndStoneBrickWall::West::None).ID: return 14248; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::None, EndStoneBrickWall::South::Tall, false, EndStoneBrickWall::West::Low).ID: return 14249; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::None, EndStoneBrickWall::South::Tall, false, EndStoneBrickWall::West::Tall).ID: return 14250; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::None, true, EndStoneBrickWall::West::None).ID: return 14254; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::None, true, EndStoneBrickWall::West::Low).ID: return 14255; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::None, true, EndStoneBrickWall::West::Tall).ID: return 14256; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::None, false, EndStoneBrickWall::West::None).ID: return 14260; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::None, false, EndStoneBrickWall::West::Low).ID: return 14261; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::None, false, EndStoneBrickWall::West::Tall).ID: return 14262; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::Low, true, EndStoneBrickWall::West::None).ID: return 14266; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::Low, true, EndStoneBrickWall::West::Low).ID: return 14267; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::Low, true, EndStoneBrickWall::West::Tall).ID: return 14268; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::Low, false, EndStoneBrickWall::West::None).ID: return 14272; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::Low, false, EndStoneBrickWall::West::Low).ID: return 14273; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::Low, false, EndStoneBrickWall::West::Tall).ID: return 14274; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::Tall, true, EndStoneBrickWall::West::None).ID: return 14278; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::Tall, true, EndStoneBrickWall::West::Low).ID: return 14279; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::Tall, true, EndStoneBrickWall::West::Tall).ID: return 14280; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::Tall, false, EndStoneBrickWall::West::None).ID: return 14284; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::Tall, false, EndStoneBrickWall::West::Low).ID: return 14285; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::Tall, false, EndStoneBrickWall::West::Tall).ID: return 14286; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::Tall, EndStoneBrickWall::South::None, true, EndStoneBrickWall::West::None).ID: return 14290; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::Tall, EndStoneBrickWall::South::None, true, EndStoneBrickWall::West::Low).ID: return 14291; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::Tall, EndStoneBrickWall::South::None, true, EndStoneBrickWall::West::Tall).ID: return 14292; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::Tall, EndStoneBrickWall::South::None, false, EndStoneBrickWall::West::None).ID: return 14296; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::Tall, EndStoneBrickWall::South::None, false, EndStoneBrickWall::West::Low).ID: return 14297; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::Tall, EndStoneBrickWall::South::None, false, EndStoneBrickWall::West::Tall).ID: return 14298; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::Tall, EndStoneBrickWall::South::Low, true, EndStoneBrickWall::West::None).ID: return 14302; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::Tall, EndStoneBrickWall::South::Low, true, EndStoneBrickWall::West::Low).ID: return 14303; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::Tall, EndStoneBrickWall::South::Low, true, EndStoneBrickWall::West::Tall).ID: return 14304; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::Tall, EndStoneBrickWall::South::Low, false, EndStoneBrickWall::West::None).ID: return 14308; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::Tall, EndStoneBrickWall::South::Low, false, EndStoneBrickWall::West::Low).ID: return 14309; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::Tall, EndStoneBrickWall::South::Low, false, EndStoneBrickWall::West::Tall).ID: return 14310; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::Tall, EndStoneBrickWall::South::Tall, true, EndStoneBrickWall::West::None).ID: return 14314; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::Tall, EndStoneBrickWall::South::Tall, true, EndStoneBrickWall::West::Low).ID: return 14315; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::Tall, EndStoneBrickWall::South::Tall, true, EndStoneBrickWall::West::Tall).ID: return 14316; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::Tall, EndStoneBrickWall::South::Tall, false, EndStoneBrickWall::West::None).ID: return 14320; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::Tall, EndStoneBrickWall::South::Tall, false, EndStoneBrickWall::West::Low).ID: return 14321; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Low, EndStoneBrickWall::North::Tall, EndStoneBrickWall::South::Tall, false, EndStoneBrickWall::West::Tall).ID: return 14322; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Tall, EndStoneBrickWall::North::None, EndStoneBrickWall::South::None, true, EndStoneBrickWall::West::None).ID: return 14326; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Tall, EndStoneBrickWall::North::None, EndStoneBrickWall::South::None, true, EndStoneBrickWall::West::Low).ID: return 14327; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Tall, EndStoneBrickWall::North::None, EndStoneBrickWall::South::None, true, EndStoneBrickWall::West::Tall).ID: return 14328; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Tall, EndStoneBrickWall::North::None, EndStoneBrickWall::South::None, false, EndStoneBrickWall::West::None).ID: return 14332; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Tall, EndStoneBrickWall::North::None, EndStoneBrickWall::South::None, false, EndStoneBrickWall::West::Low).ID: return 14333; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Tall, EndStoneBrickWall::North::None, EndStoneBrickWall::South::None, false, EndStoneBrickWall::West::Tall).ID: return 14334; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Tall, EndStoneBrickWall::North::None, EndStoneBrickWall::South::Low, true, EndStoneBrickWall::West::None).ID: return 14338; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Tall, EndStoneBrickWall::North::None, EndStoneBrickWall::South::Low, true, EndStoneBrickWall::West::Low).ID: return 14339; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Tall, EndStoneBrickWall::North::None, EndStoneBrickWall::South::Low, true, EndStoneBrickWall::West::Tall).ID: return 14340; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Tall, EndStoneBrickWall::North::None, EndStoneBrickWall::South::Low, false, EndStoneBrickWall::West::None).ID: return 14344; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Tall, EndStoneBrickWall::North::None, EndStoneBrickWall::South::Low, false, EndStoneBrickWall::West::Low).ID: return 14345; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Tall, EndStoneBrickWall::North::None, EndStoneBrickWall::South::Low, false, EndStoneBrickWall::West::Tall).ID: return 14346; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Tall, EndStoneBrickWall::North::None, EndStoneBrickWall::South::Tall, true, EndStoneBrickWall::West::None).ID: return 14350; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Tall, EndStoneBrickWall::North::None, EndStoneBrickWall::South::Tall, true, EndStoneBrickWall::West::Low).ID: return 14351; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Tall, EndStoneBrickWall::North::None, EndStoneBrickWall::South::Tall, true, EndStoneBrickWall::West::Tall).ID: return 14352; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Tall, EndStoneBrickWall::North::None, EndStoneBrickWall::South::Tall, false, EndStoneBrickWall::West::None).ID: return 14356; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Tall, EndStoneBrickWall::North::None, EndStoneBrickWall::South::Tall, false, EndStoneBrickWall::West::Low).ID: return 14357; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Tall, EndStoneBrickWall::North::None, EndStoneBrickWall::South::Tall, false, EndStoneBrickWall::West::Tall).ID: return 14358; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Tall, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::None, true, EndStoneBrickWall::West::None).ID: return 14362; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Tall, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::None, true, EndStoneBrickWall::West::Low).ID: return 14363; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Tall, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::None, true, EndStoneBrickWall::West::Tall).ID: return 14364; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Tall, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::None, false, EndStoneBrickWall::West::None).ID: return 14368; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Tall, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::None, false, EndStoneBrickWall::West::Low).ID: return 14369; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Tall, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::None, false, EndStoneBrickWall::West::Tall).ID: return 14370; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Tall, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::Low, true, EndStoneBrickWall::West::None).ID: return 14374; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Tall, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::Low, true, EndStoneBrickWall::West::Low).ID: return 14375; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Tall, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::Low, true, EndStoneBrickWall::West::Tall).ID: return 14376; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Tall, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::Low, false, EndStoneBrickWall::West::None).ID: return 14380; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Tall, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::Low, false, EndStoneBrickWall::West::Low).ID: return 14381; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Tall, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::Low, false, EndStoneBrickWall::West::Tall).ID: return 14382; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Tall, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::Tall, true, EndStoneBrickWall::West::None).ID: return 14386; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Tall, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::Tall, true, EndStoneBrickWall::West::Low).ID: return 14387; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Tall, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::Tall, true, EndStoneBrickWall::West::Tall).ID: return 14388; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Tall, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::Tall, false, EndStoneBrickWall::West::None).ID: return 14392; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Tall, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::Tall, false, EndStoneBrickWall::West::Low).ID: return 14393; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Tall, EndStoneBrickWall::North::Low, EndStoneBrickWall::South::Tall, false, EndStoneBrickWall::West::Tall).ID: return 14394; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Tall, EndStoneBrickWall::North::Tall, EndStoneBrickWall::South::None, true, EndStoneBrickWall::West::None).ID: return 14398; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Tall, EndStoneBrickWall::North::Tall, EndStoneBrickWall::South::None, true, EndStoneBrickWall::West::Low).ID: return 14399; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Tall, EndStoneBrickWall::North::Tall, EndStoneBrickWall::South::None, true, EndStoneBrickWall::West::Tall).ID: return 14400; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Tall, EndStoneBrickWall::North::Tall, EndStoneBrickWall::South::None, false, EndStoneBrickWall::West::None).ID: return 14404; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Tall, EndStoneBrickWall::North::Tall, EndStoneBrickWall::South::None, false, EndStoneBrickWall::West::Low).ID: return 14405; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Tall, EndStoneBrickWall::North::Tall, EndStoneBrickWall::South::None, false, EndStoneBrickWall::West::Tall).ID: return 14406; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Tall, EndStoneBrickWall::North::Tall, EndStoneBrickWall::South::Low, true, EndStoneBrickWall::West::None).ID: return 14410; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Tall, EndStoneBrickWall::North::Tall, EndStoneBrickWall::South::Low, true, EndStoneBrickWall::West::Low).ID: return 14411; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Tall, EndStoneBrickWall::North::Tall, EndStoneBrickWall::South::Low, true, EndStoneBrickWall::West::Tall).ID: return 14412; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Tall, EndStoneBrickWall::North::Tall, EndStoneBrickWall::South::Low, false, EndStoneBrickWall::West::None).ID: return 14416; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Tall, EndStoneBrickWall::North::Tall, EndStoneBrickWall::South::Low, false, EndStoneBrickWall::West::Low).ID: return 14417; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Tall, EndStoneBrickWall::North::Tall, EndStoneBrickWall::South::Low, false, EndStoneBrickWall::West::Tall).ID: return 14418; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Tall, EndStoneBrickWall::North::Tall, EndStoneBrickWall::South::Tall, true, EndStoneBrickWall::West::None).ID: return 14422; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Tall, EndStoneBrickWall::North::Tall, EndStoneBrickWall::South::Tall, true, EndStoneBrickWall::West::Low).ID: return 14423; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Tall, EndStoneBrickWall::North::Tall, EndStoneBrickWall::South::Tall, true, EndStoneBrickWall::West::Tall).ID: return 14424; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Tall, EndStoneBrickWall::North::Tall, EndStoneBrickWall::South::Tall, false, EndStoneBrickWall::West::None).ID: return 14428; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Tall, EndStoneBrickWall::North::Tall, EndStoneBrickWall::South::Tall, false, EndStoneBrickWall::West::Low).ID: return 14429; case EndStoneBrickWall::EndStoneBrickWall(EndStoneBrickWall::East::Tall, EndStoneBrickWall::North::Tall, EndStoneBrickWall::South::Tall, false, EndStoneBrickWall::West::Tall).ID: return 14430; case EndStoneBricks::EndStoneBricks().ID: return 9218; case EnderChest::EnderChest(eBlockFace::BLOCK_FACE_ZM).ID: return 5252; case EnderChest::EnderChest(eBlockFace::BLOCK_FACE_ZP).ID: return 5254; case EnderChest::EnderChest(eBlockFace::BLOCK_FACE_XM).ID: return 5256; case EnderChest::EnderChest(eBlockFace::BLOCK_FACE_XP).ID: return 5258; case Farmland::Farmland(0).ID: return 3365; case Farmland::Farmland(1).ID: return 3366; case Farmland::Farmland(2).ID: return 3367; case Farmland::Farmland(3).ID: return 3368; case Farmland::Farmland(4).ID: return 3369; case Farmland::Farmland(5).ID: return 3370; case Farmland::Farmland(6).ID: return 3371; case Farmland::Farmland(7).ID: return 3372; case Fern::Fern().ID: return 1343; case Fire::Fire(0, true, true, true, true, true).ID: return 1440; case Fire::Fire(0, true, true, true, true, false).ID: return 1441; case Fire::Fire(0, true, true, true, false, true).ID: return 1442; case Fire::Fire(0, true, true, true, false, false).ID: return 1443; case Fire::Fire(0, true, true, false, true, true).ID: return 1444; case Fire::Fire(0, true, true, false, true, false).ID: return 1445; case Fire::Fire(0, true, true, false, false, true).ID: return 1446; case Fire::Fire(0, true, true, false, false, false).ID: return 1447; case Fire::Fire(0, true, false, true, true, true).ID: return 1448; case Fire::Fire(0, true, false, true, true, false).ID: return 1449; case Fire::Fire(0, true, false, true, false, true).ID: return 1450; case Fire::Fire(0, true, false, true, false, false).ID: return 1451; case Fire::Fire(0, true, false, false, true, true).ID: return 1452; case Fire::Fire(0, true, false, false, true, false).ID: return 1453; case Fire::Fire(0, true, false, false, false, true).ID: return 1454; case Fire::Fire(0, true, false, false, false, false).ID: return 1455; case Fire::Fire(0, false, true, true, true, true).ID: return 1456; case Fire::Fire(0, false, true, true, true, false).ID: return 1457; case Fire::Fire(0, false, true, true, false, true).ID: return 1458; case Fire::Fire(0, false, true, true, false, false).ID: return 1459; case Fire::Fire(0, false, true, false, true, true).ID: return 1460; case Fire::Fire(0, false, true, false, true, false).ID: return 1461; case Fire::Fire(0, false, true, false, false, true).ID: return 1462; case Fire::Fire(0, false, true, false, false, false).ID: return 1463; case Fire::Fire(0, false, false, true, true, true).ID: return 1464; case Fire::Fire(0, false, false, true, true, false).ID: return 1465; case Fire::Fire(0, false, false, true, false, true).ID: return 1466; case Fire::Fire(0, false, false, true, false, false).ID: return 1467; case Fire::Fire(0, false, false, false, true, true).ID: return 1468; case Fire::Fire(0, false, false, false, true, false).ID: return 1469; case Fire::Fire(0, false, false, false, false, true).ID: return 1470; case Fire::Fire(0, false, false, false, false, false).ID: return 1471; case Fire::Fire(1, true, true, true, true, true).ID: return 1472; case Fire::Fire(1, true, true, true, true, false).ID: return 1473; case Fire::Fire(1, true, true, true, false, true).ID: return 1474; case Fire::Fire(1, true, true, true, false, false).ID: return 1475; case Fire::Fire(1, true, true, false, true, true).ID: return 1476; case Fire::Fire(1, true, true, false, true, false).ID: return 1477; case Fire::Fire(1, true, true, false, false, true).ID: return 1478; case Fire::Fire(1, true, true, false, false, false).ID: return 1479; case Fire::Fire(1, true, false, true, true, true).ID: return 1480; case Fire::Fire(1, true, false, true, true, false).ID: return 1481; case Fire::Fire(1, true, false, true, false, true).ID: return 1482; case Fire::Fire(1, true, false, true, false, false).ID: return 1483; case Fire::Fire(1, true, false, false, true, true).ID: return 1484; case Fire::Fire(1, true, false, false, true, false).ID: return 1485; case Fire::Fire(1, true, false, false, false, true).ID: return 1486; case Fire::Fire(1, true, false, false, false, false).ID: return 1487; case Fire::Fire(1, false, true, true, true, true).ID: return 1488; case Fire::Fire(1, false, true, true, true, false).ID: return 1489; case Fire::Fire(1, false, true, true, false, true).ID: return 1490; case Fire::Fire(1, false, true, true, false, false).ID: return 1491; case Fire::Fire(1, false, true, false, true, true).ID: return 1492; case Fire::Fire(1, false, true, false, true, false).ID: return 1493; case Fire::Fire(1, false, true, false, false, true).ID: return 1494; case Fire::Fire(1, false, true, false, false, false).ID: return 1495; case Fire::Fire(1, false, false, true, true, true).ID: return 1496; case Fire::Fire(1, false, false, true, true, false).ID: return 1497; case Fire::Fire(1, false, false, true, false, true).ID: return 1498; case Fire::Fire(1, false, false, true, false, false).ID: return 1499; case Fire::Fire(1, false, false, false, true, true).ID: return 1500; case Fire::Fire(1, false, false, false, true, false).ID: return 1501; case Fire::Fire(1, false, false, false, false, true).ID: return 1502; case Fire::Fire(1, false, false, false, false, false).ID: return 1503; case Fire::Fire(2, true, true, true, true, true).ID: return 1504; case Fire::Fire(2, true, true, true, true, false).ID: return 1505; case Fire::Fire(2, true, true, true, false, true).ID: return 1506; case Fire::Fire(2, true, true, true, false, false).ID: return 1507; case Fire::Fire(2, true, true, false, true, true).ID: return 1508; case Fire::Fire(2, true, true, false, true, false).ID: return 1509; case Fire::Fire(2, true, true, false, false, true).ID: return 1510; case Fire::Fire(2, true, true, false, false, false).ID: return 1511; case Fire::Fire(2, true, false, true, true, true).ID: return 1512; case Fire::Fire(2, true, false, true, true, false).ID: return 1513; case Fire::Fire(2, true, false, true, false, true).ID: return 1514; case Fire::Fire(2, true, false, true, false, false).ID: return 1515; case Fire::Fire(2, true, false, false, true, true).ID: return 1516; case Fire::Fire(2, true, false, false, true, false).ID: return 1517; case Fire::Fire(2, true, false, false, false, true).ID: return 1518; case Fire::Fire(2, true, false, false, false, false).ID: return 1519; case Fire::Fire(2, false, true, true, true, true).ID: return 1520; case Fire::Fire(2, false, true, true, true, false).ID: return 1521; case Fire::Fire(2, false, true, true, false, true).ID: return 1522; case Fire::Fire(2, false, true, true, false, false).ID: return 1523; case Fire::Fire(2, false, true, false, true, true).ID: return 1524; case Fire::Fire(2, false, true, false, true, false).ID: return 1525; case Fire::Fire(2, false, true, false, false, true).ID: return 1526; case Fire::Fire(2, false, true, false, false, false).ID: return 1527; case Fire::Fire(2, false, false, true, true, true).ID: return 1528; case Fire::Fire(2, false, false, true, true, false).ID: return 1529; case Fire::Fire(2, false, false, true, false, true).ID: return 1530; case Fire::Fire(2, false, false, true, false, false).ID: return 1531; case Fire::Fire(2, false, false, false, true, true).ID: return 1532; case Fire::Fire(2, false, false, false, true, false).ID: return 1533; case Fire::Fire(2, false, false, false, false, true).ID: return 1534; case Fire::Fire(2, false, false, false, false, false).ID: return 1535; case Fire::Fire(3, true, true, true, true, true).ID: return 1536; case Fire::Fire(3, true, true, true, true, false).ID: return 1537; case Fire::Fire(3, true, true, true, false, true).ID: return 1538; case Fire::Fire(3, true, true, true, false, false).ID: return 1539; case Fire::Fire(3, true, true, false, true, true).ID: return 1540; case Fire::Fire(3, true, true, false, true, false).ID: return 1541; case Fire::Fire(3, true, true, false, false, true).ID: return 1542; case Fire::Fire(3, true, true, false, false, false).ID: return 1543; case Fire::Fire(3, true, false, true, true, true).ID: return 1544; case Fire::Fire(3, true, false, true, true, false).ID: return 1545; case Fire::Fire(3, true, false, true, false, true).ID: return 1546; case Fire::Fire(3, true, false, true, false, false).ID: return 1547; case Fire::Fire(3, true, false, false, true, true).ID: return 1548; case Fire::Fire(3, true, false, false, true, false).ID: return 1549; case Fire::Fire(3, true, false, false, false, true).ID: return 1550; case Fire::Fire(3, true, false, false, false, false).ID: return 1551; case Fire::Fire(3, false, true, true, true, true).ID: return 1552; case Fire::Fire(3, false, true, true, true, false).ID: return 1553; case Fire::Fire(3, false, true, true, false, true).ID: return 1554; case Fire::Fire(3, false, true, true, false, false).ID: return 1555; case Fire::Fire(3, false, true, false, true, true).ID: return 1556; case Fire::Fire(3, false, true, false, true, false).ID: return 1557; case Fire::Fire(3, false, true, false, false, true).ID: return 1558; case Fire::Fire(3, false, true, false, false, false).ID: return 1559; case Fire::Fire(3, false, false, true, true, true).ID: return 1560; case Fire::Fire(3, false, false, true, true, false).ID: return 1561; case Fire::Fire(3, false, false, true, false, true).ID: return 1562; case Fire::Fire(3, false, false, true, false, false).ID: return 1563; case Fire::Fire(3, false, false, false, true, true).ID: return 1564; case Fire::Fire(3, false, false, false, true, false).ID: return 1565; case Fire::Fire(3, false, false, false, false, true).ID: return 1566; case Fire::Fire(3, false, false, false, false, false).ID: return 1567; case Fire::Fire(4, true, true, true, true, true).ID: return 1568; case Fire::Fire(4, true, true, true, true, false).ID: return 1569; case Fire::Fire(4, true, true, true, false, true).ID: return 1570; case Fire::Fire(4, true, true, true, false, false).ID: return 1571; case Fire::Fire(4, true, true, false, true, true).ID: return 1572; case Fire::Fire(4, true, true, false, true, false).ID: return 1573; case Fire::Fire(4, true, true, false, false, true).ID: return 1574; case Fire::Fire(4, true, true, false, false, false).ID: return 1575; case Fire::Fire(4, true, false, true, true, true).ID: return 1576; case Fire::Fire(4, true, false, true, true, false).ID: return 1577; case Fire::Fire(4, true, false, true, false, true).ID: return 1578; case Fire::Fire(4, true, false, true, false, false).ID: return 1579; case Fire::Fire(4, true, false, false, true, true).ID: return 1580; case Fire::Fire(4, true, false, false, true, false).ID: return 1581; case Fire::Fire(4, true, false, false, false, true).ID: return 1582; case Fire::Fire(4, true, false, false, false, false).ID: return 1583; case Fire::Fire(4, false, true, true, true, true).ID: return 1584; case Fire::Fire(4, false, true, true, true, false).ID: return 1585; case Fire::Fire(4, false, true, true, false, true).ID: return 1586; case Fire::Fire(4, false, true, true, false, false).ID: return 1587; case Fire::Fire(4, false, true, false, true, true).ID: return 1588; case Fire::Fire(4, false, true, false, true, false).ID: return 1589; case Fire::Fire(4, false, true, false, false, true).ID: return 1590; case Fire::Fire(4, false, true, false, false, false).ID: return 1591; case Fire::Fire(4, false, false, true, true, true).ID: return 1592; case Fire::Fire(4, false, false, true, true, false).ID: return 1593; case Fire::Fire(4, false, false, true, false, true).ID: return 1594; case Fire::Fire(4, false, false, true, false, false).ID: return 1595; case Fire::Fire(4, false, false, false, true, true).ID: return 1596; case Fire::Fire(4, false, false, false, true, false).ID: return 1597; case Fire::Fire(4, false, false, false, false, true).ID: return 1598; case Fire::Fire(4, false, false, false, false, false).ID: return 1599; case Fire::Fire(5, true, true, true, true, true).ID: return 1600; case Fire::Fire(5, true, true, true, true, false).ID: return 1601; case Fire::Fire(5, true, true, true, false, true).ID: return 1602; case Fire::Fire(5, true, true, true, false, false).ID: return 1603; case Fire::Fire(5, true, true, false, true, true).ID: return 1604; case Fire::Fire(5, true, true, false, true, false).ID: return 1605; case Fire::Fire(5, true, true, false, false, true).ID: return 1606; case Fire::Fire(5, true, true, false, false, false).ID: return 1607; case Fire::Fire(5, true, false, true, true, true).ID: return 1608; case Fire::Fire(5, true, false, true, true, false).ID: return 1609; case Fire::Fire(5, true, false, true, false, true).ID: return 1610; case Fire::Fire(5, true, false, true, false, false).ID: return 1611; case Fire::Fire(5, true, false, false, true, true).ID: return 1612; case Fire::Fire(5, true, false, false, true, false).ID: return 1613; case Fire::Fire(5, true, false, false, false, true).ID: return 1614; case Fire::Fire(5, true, false, false, false, false).ID: return 1615; case Fire::Fire(5, false, true, true, true, true).ID: return 1616; case Fire::Fire(5, false, true, true, true, false).ID: return 1617; case Fire::Fire(5, false, true, true, false, true).ID: return 1618; case Fire::Fire(5, false, true, true, false, false).ID: return 1619; case Fire::Fire(5, false, true, false, true, true).ID: return 1620; case Fire::Fire(5, false, true, false, true, false).ID: return 1621; case Fire::Fire(5, false, true, false, false, true).ID: return 1622; case Fire::Fire(5, false, true, false, false, false).ID: return 1623; case Fire::Fire(5, false, false, true, true, true).ID: return 1624; case Fire::Fire(5, false, false, true, true, false).ID: return 1625; case Fire::Fire(5, false, false, true, false, true).ID: return 1626; case Fire::Fire(5, false, false, true, false, false).ID: return 1627; case Fire::Fire(5, false, false, false, true, true).ID: return 1628; case Fire::Fire(5, false, false, false, true, false).ID: return 1629; case Fire::Fire(5, false, false, false, false, true).ID: return 1630; case Fire::Fire(5, false, false, false, false, false).ID: return 1631; case Fire::Fire(6, true, true, true, true, true).ID: return 1632; case Fire::Fire(6, true, true, true, true, false).ID: return 1633; case Fire::Fire(6, true, true, true, false, true).ID: return 1634; case Fire::Fire(6, true, true, true, false, false).ID: return 1635; case Fire::Fire(6, true, true, false, true, true).ID: return 1636; case Fire::Fire(6, true, true, false, true, false).ID: return 1637; case Fire::Fire(6, true, true, false, false, true).ID: return 1638; case Fire::Fire(6, true, true, false, false, false).ID: return 1639; case Fire::Fire(6, true, false, true, true, true).ID: return 1640; case Fire::Fire(6, true, false, true, true, false).ID: return 1641; case Fire::Fire(6, true, false, true, false, true).ID: return 1642; case Fire::Fire(6, true, false, true, false, false).ID: return 1643; case Fire::Fire(6, true, false, false, true, true).ID: return 1644; case Fire::Fire(6, true, false, false, true, false).ID: return 1645; case Fire::Fire(6, true, false, false, false, true).ID: return 1646; case Fire::Fire(6, true, false, false, false, false).ID: return 1647; case Fire::Fire(6, false, true, true, true, true).ID: return 1648; case Fire::Fire(6, false, true, true, true, false).ID: return 1649; case Fire::Fire(6, false, true, true, false, true).ID: return 1650; case Fire::Fire(6, false, true, true, false, false).ID: return 1651; case Fire::Fire(6, false, true, false, true, true).ID: return 1652; case Fire::Fire(6, false, true, false, true, false).ID: return 1653; case Fire::Fire(6, false, true, false, false, true).ID: return 1654; case Fire::Fire(6, false, true, false, false, false).ID: return 1655; case Fire::Fire(6, false, false, true, true, true).ID: return 1656; case Fire::Fire(6, false, false, true, true, false).ID: return 1657; case Fire::Fire(6, false, false, true, false, true).ID: return 1658; case Fire::Fire(6, false, false, true, false, false).ID: return 1659; case Fire::Fire(6, false, false, false, true, true).ID: return 1660; case Fire::Fire(6, false, false, false, true, false).ID: return 1661; case Fire::Fire(6, false, false, false, false, true).ID: return 1662; case Fire::Fire(6, false, false, false, false, false).ID: return 1663; case Fire::Fire(7, true, true, true, true, true).ID: return 1664; case Fire::Fire(7, true, true, true, true, false).ID: return 1665; case Fire::Fire(7, true, true, true, false, true).ID: return 1666; case Fire::Fire(7, true, true, true, false, false).ID: return 1667; case Fire::Fire(7, true, true, false, true, true).ID: return 1668; case Fire::Fire(7, true, true, false, true, false).ID: return 1669; case Fire::Fire(7, true, true, false, false, true).ID: return 1670; case Fire::Fire(7, true, true, false, false, false).ID: return 1671; case Fire::Fire(7, true, false, true, true, true).ID: return 1672; case Fire::Fire(7, true, false, true, true, false).ID: return 1673; case Fire::Fire(7, true, false, true, false, true).ID: return 1674; case Fire::Fire(7, true, false, true, false, false).ID: return 1675; case Fire::Fire(7, true, false, false, true, true).ID: return 1676; case Fire::Fire(7, true, false, false, true, false).ID: return 1677; case Fire::Fire(7, true, false, false, false, true).ID: return 1678; case Fire::Fire(7, true, false, false, false, false).ID: return 1679; case Fire::Fire(7, false, true, true, true, true).ID: return 1680; case Fire::Fire(7, false, true, true, true, false).ID: return 1681; case Fire::Fire(7, false, true, true, false, true).ID: return 1682; case Fire::Fire(7, false, true, true, false, false).ID: return 1683; case Fire::Fire(7, false, true, false, true, true).ID: return 1684; case Fire::Fire(7, false, true, false, true, false).ID: return 1685; case Fire::Fire(7, false, true, false, false, true).ID: return 1686; case Fire::Fire(7, false, true, false, false, false).ID: return 1687; case Fire::Fire(7, false, false, true, true, true).ID: return 1688; case Fire::Fire(7, false, false, true, true, false).ID: return 1689; case Fire::Fire(7, false, false, true, false, true).ID: return 1690; case Fire::Fire(7, false, false, true, false, false).ID: return 1691; case Fire::Fire(7, false, false, false, true, true).ID: return 1692; case Fire::Fire(7, false, false, false, true, false).ID: return 1693; case Fire::Fire(7, false, false, false, false, true).ID: return 1694; case Fire::Fire(7, false, false, false, false, false).ID: return 1695; case Fire::Fire(8, true, true, true, true, true).ID: return 1696; case Fire::Fire(8, true, true, true, true, false).ID: return 1697; case Fire::Fire(8, true, true, true, false, true).ID: return 1698; case Fire::Fire(8, true, true, true, false, false).ID: return 1699; case Fire::Fire(8, true, true, false, true, true).ID: return 1700; case Fire::Fire(8, true, true, false, true, false).ID: return 1701; case Fire::Fire(8, true, true, false, false, true).ID: return 1702; case Fire::Fire(8, true, true, false, false, false).ID: return 1703; case Fire::Fire(8, true, false, true, true, true).ID: return 1704; case Fire::Fire(8, true, false, true, true, false).ID: return 1705; case Fire::Fire(8, true, false, true, false, true).ID: return 1706; case Fire::Fire(8, true, false, true, false, false).ID: return 1707; case Fire::Fire(8, true, false, false, true, true).ID: return 1708; case Fire::Fire(8, true, false, false, true, false).ID: return 1709; case Fire::Fire(8, true, false, false, false, true).ID: return 1710; case Fire::Fire(8, true, false, false, false, false).ID: return 1711; case Fire::Fire(8, false, true, true, true, true).ID: return 1712; case Fire::Fire(8, false, true, true, true, false).ID: return 1713; case Fire::Fire(8, false, true, true, false, true).ID: return 1714; case Fire::Fire(8, false, true, true, false, false).ID: return 1715; case Fire::Fire(8, false, true, false, true, true).ID: return 1716; case Fire::Fire(8, false, true, false, true, false).ID: return 1717; case Fire::Fire(8, false, true, false, false, true).ID: return 1718; case Fire::Fire(8, false, true, false, false, false).ID: return 1719; case Fire::Fire(8, false, false, true, true, true).ID: return 1720; case Fire::Fire(8, false, false, true, true, false).ID: return 1721; case Fire::Fire(8, false, false, true, false, true).ID: return 1722; case Fire::Fire(8, false, false, true, false, false).ID: return 1723; case Fire::Fire(8, false, false, false, true, true).ID: return 1724; case Fire::Fire(8, false, false, false, true, false).ID: return 1725; case Fire::Fire(8, false, false, false, false, true).ID: return 1726; case Fire::Fire(8, false, false, false, false, false).ID: return 1727; case Fire::Fire(9, true, true, true, true, true).ID: return 1728; case Fire::Fire(9, true, true, true, true, false).ID: return 1729; case Fire::Fire(9, true, true, true, false, true).ID: return 1730; case Fire::Fire(9, true, true, true, false, false).ID: return 1731; case Fire::Fire(9, true, true, false, true, true).ID: return 1732; case Fire::Fire(9, true, true, false, true, false).ID: return 1733; case Fire::Fire(9, true, true, false, false, true).ID: return 1734; case Fire::Fire(9, true, true, false, false, false).ID: return 1735; case Fire::Fire(9, true, false, true, true, true).ID: return 1736; case Fire::Fire(9, true, false, true, true, false).ID: return 1737; case Fire::Fire(9, true, false, true, false, true).ID: return 1738; case Fire::Fire(9, true, false, true, false, false).ID: return 1739; case Fire::Fire(9, true, false, false, true, true).ID: return 1740; case Fire::Fire(9, true, false, false, true, false).ID: return 1741; case Fire::Fire(9, true, false, false, false, true).ID: return 1742; case Fire::Fire(9, true, false, false, false, false).ID: return 1743; case Fire::Fire(9, false, true, true, true, true).ID: return 1744; case Fire::Fire(9, false, true, true, true, false).ID: return 1745; case Fire::Fire(9, false, true, true, false, true).ID: return 1746; case Fire::Fire(9, false, true, true, false, false).ID: return 1747; case Fire::Fire(9, false, true, false, true, true).ID: return 1748; case Fire::Fire(9, false, true, false, true, false).ID: return 1749; case Fire::Fire(9, false, true, false, false, true).ID: return 1750; case Fire::Fire(9, false, true, false, false, false).ID: return 1751; case Fire::Fire(9, false, false, true, true, true).ID: return 1752; case Fire::Fire(9, false, false, true, true, false).ID: return 1753; case Fire::Fire(9, false, false, true, false, true).ID: return 1754; case Fire::Fire(9, false, false, true, false, false).ID: return 1755; case Fire::Fire(9, false, false, false, true, true).ID: return 1756; case Fire::Fire(9, false, false, false, true, false).ID: return 1757; case Fire::Fire(9, false, false, false, false, true).ID: return 1758; case Fire::Fire(9, false, false, false, false, false).ID: return 1759; case Fire::Fire(10, true, true, true, true, true).ID: return 1760; case Fire::Fire(10, true, true, true, true, false).ID: return 1761; case Fire::Fire(10, true, true, true, false, true).ID: return 1762; case Fire::Fire(10, true, true, true, false, false).ID: return 1763; case Fire::Fire(10, true, true, false, true, true).ID: return 1764; case Fire::Fire(10, true, true, false, true, false).ID: return 1765; case Fire::Fire(10, true, true, false, false, true).ID: return 1766; case Fire::Fire(10, true, true, false, false, false).ID: return 1767; case Fire::Fire(10, true, false, true, true, true).ID: return 1768; case Fire::Fire(10, true, false, true, true, false).ID: return 1769; case Fire::Fire(10, true, false, true, false, true).ID: return 1770; case Fire::Fire(10, true, false, true, false, false).ID: return 1771; case Fire::Fire(10, true, false, false, true, true).ID: return 1772; case Fire::Fire(10, true, false, false, true, false).ID: return 1773; case Fire::Fire(10, true, false, false, false, true).ID: return 1774; case Fire::Fire(10, true, false, false, false, false).ID: return 1775; case Fire::Fire(10, false, true, true, true, true).ID: return 1776; case Fire::Fire(10, false, true, true, true, false).ID: return 1777; case Fire::Fire(10, false, true, true, false, true).ID: return 1778; case Fire::Fire(10, false, true, true, false, false).ID: return 1779; case Fire::Fire(10, false, true, false, true, true).ID: return 1780; case Fire::Fire(10, false, true, false, true, false).ID: return 1781; case Fire::Fire(10, false, true, false, false, true).ID: return 1782; case Fire::Fire(10, false, true, false, false, false).ID: return 1783; case Fire::Fire(10, false, false, true, true, true).ID: return 1784; case Fire::Fire(10, false, false, true, true, false).ID: return 1785; case Fire::Fire(10, false, false, true, false, true).ID: return 1786; case Fire::Fire(10, false, false, true, false, false).ID: return 1787; case Fire::Fire(10, false, false, false, true, true).ID: return 1788; case Fire::Fire(10, false, false, false, true, false).ID: return 1789; case Fire::Fire(10, false, false, false, false, true).ID: return 1790; case Fire::Fire(10, false, false, false, false, false).ID: return 1791; case Fire::Fire(11, true, true, true, true, true).ID: return 1792; case Fire::Fire(11, true, true, true, true, false).ID: return 1793; case Fire::Fire(11, true, true, true, false, true).ID: return 1794; case Fire::Fire(11, true, true, true, false, false).ID: return 1795; case Fire::Fire(11, true, true, false, true, true).ID: return 1796; case Fire::Fire(11, true, true, false, true, false).ID: return 1797; case Fire::Fire(11, true, true, false, false, true).ID: return 1798; case Fire::Fire(11, true, true, false, false, false).ID: return 1799; case Fire::Fire(11, true, false, true, true, true).ID: return 1800; case Fire::Fire(11, true, false, true, true, false).ID: return 1801; case Fire::Fire(11, true, false, true, false, true).ID: return 1802; case Fire::Fire(11, true, false, true, false, false).ID: return 1803; case Fire::Fire(11, true, false, false, true, true).ID: return 1804; case Fire::Fire(11, true, false, false, true, false).ID: return 1805; case Fire::Fire(11, true, false, false, false, true).ID: return 1806; case Fire::Fire(11, true, false, false, false, false).ID: return 1807; case Fire::Fire(11, false, true, true, true, true).ID: return 1808; case Fire::Fire(11, false, true, true, true, false).ID: return 1809; case Fire::Fire(11, false, true, true, false, true).ID: return 1810; case Fire::Fire(11, false, true, true, false, false).ID: return 1811; case Fire::Fire(11, false, true, false, true, true).ID: return 1812; case Fire::Fire(11, false, true, false, true, false).ID: return 1813; case Fire::Fire(11, false, true, false, false, true).ID: return 1814; case Fire::Fire(11, false, true, false, false, false).ID: return 1815; case Fire::Fire(11, false, false, true, true, true).ID: return 1816; case Fire::Fire(11, false, false, true, true, false).ID: return 1817; case Fire::Fire(11, false, false, true, false, true).ID: return 1818; case Fire::Fire(11, false, false, true, false, false).ID: return 1819; case Fire::Fire(11, false, false, false, true, true).ID: return 1820; case Fire::Fire(11, false, false, false, true, false).ID: return 1821; case Fire::Fire(11, false, false, false, false, true).ID: return 1822; case Fire::Fire(11, false, false, false, false, false).ID: return 1823; case Fire::Fire(12, true, true, true, true, true).ID: return 1824; case Fire::Fire(12, true, true, true, true, false).ID: return 1825; case Fire::Fire(12, true, true, true, false, true).ID: return 1826; case Fire::Fire(12, true, true, true, false, false).ID: return 1827; case Fire::Fire(12, true, true, false, true, true).ID: return 1828; case Fire::Fire(12, true, true, false, true, false).ID: return 1829; case Fire::Fire(12, true, true, false, false, true).ID: return 1830; case Fire::Fire(12, true, true, false, false, false).ID: return 1831; case Fire::Fire(12, true, false, true, true, true).ID: return 1832; case Fire::Fire(12, true, false, true, true, false).ID: return 1833; case Fire::Fire(12, true, false, true, false, true).ID: return 1834; case Fire::Fire(12, true, false, true, false, false).ID: return 1835; case Fire::Fire(12, true, false, false, true, true).ID: return 1836; case Fire::Fire(12, true, false, false, true, false).ID: return 1837; case Fire::Fire(12, true, false, false, false, true).ID: return 1838; case Fire::Fire(12, true, false, false, false, false).ID: return 1839; case Fire::Fire(12, false, true, true, true, true).ID: return 1840; case Fire::Fire(12, false, true, true, true, false).ID: return 1841; case Fire::Fire(12, false, true, true, false, true).ID: return 1842; case Fire::Fire(12, false, true, true, false, false).ID: return 1843; case Fire::Fire(12, false, true, false, true, true).ID: return 1844; case Fire::Fire(12, false, true, false, true, false).ID: return 1845; case Fire::Fire(12, false, true, false, false, true).ID: return 1846; case Fire::Fire(12, false, true, false, false, false).ID: return 1847; case Fire::Fire(12, false, false, true, true, true).ID: return 1848; case Fire::Fire(12, false, false, true, true, false).ID: return 1849; case Fire::Fire(12, false, false, true, false, true).ID: return 1850; case Fire::Fire(12, false, false, true, false, false).ID: return 1851; case Fire::Fire(12, false, false, false, true, true).ID: return 1852; case Fire::Fire(12, false, false, false, true, false).ID: return 1853; case Fire::Fire(12, false, false, false, false, true).ID: return 1854; case Fire::Fire(12, false, false, false, false, false).ID: return 1855; case Fire::Fire(13, true, true, true, true, true).ID: return 1856; case Fire::Fire(13, true, true, true, true, false).ID: return 1857; case Fire::Fire(13, true, true, true, false, true).ID: return 1858; case Fire::Fire(13, true, true, true, false, false).ID: return 1859; case Fire::Fire(13, true, true, false, true, true).ID: return 1860; case Fire::Fire(13, true, true, false, true, false).ID: return 1861; case Fire::Fire(13, true, true, false, false, true).ID: return 1862; case Fire::Fire(13, true, true, false, false, false).ID: return 1863; case Fire::Fire(13, true, false, true, true, true).ID: return 1864; case Fire::Fire(13, true, false, true, true, false).ID: return 1865; case Fire::Fire(13, true, false, true, false, true).ID: return 1866; case Fire::Fire(13, true, false, true, false, false).ID: return 1867; case Fire::Fire(13, true, false, false, true, true).ID: return 1868; case Fire::Fire(13, true, false, false, true, false).ID: return 1869; case Fire::Fire(13, true, false, false, false, true).ID: return 1870; case Fire::Fire(13, true, false, false, false, false).ID: return 1871; case Fire::Fire(13, false, true, true, true, true).ID: return 1872; case Fire::Fire(13, false, true, true, true, false).ID: return 1873; case Fire::Fire(13, false, true, true, false, true).ID: return 1874; case Fire::Fire(13, false, true, true, false, false).ID: return 1875; case Fire::Fire(13, false, true, false, true, true).ID: return 1876; case Fire::Fire(13, false, true, false, true, false).ID: return 1877; case Fire::Fire(13, false, true, false, false, true).ID: return 1878; case Fire::Fire(13, false, true, false, false, false).ID: return 1879; case Fire::Fire(13, false, false, true, true, true).ID: return 1880; case Fire::Fire(13, false, false, true, true, false).ID: return 1881; case Fire::Fire(13, false, false, true, false, true).ID: return 1882; case Fire::Fire(13, false, false, true, false, false).ID: return 1883; case Fire::Fire(13, false, false, false, true, true).ID: return 1884; case Fire::Fire(13, false, false, false, true, false).ID: return 1885; case Fire::Fire(13, false, false, false, false, true).ID: return 1886; case Fire::Fire(13, false, false, false, false, false).ID: return 1887; case Fire::Fire(14, true, true, true, true, true).ID: return 1888; case Fire::Fire(14, true, true, true, true, false).ID: return 1889; case Fire::Fire(14, true, true, true, false, true).ID: return 1890; case Fire::Fire(14, true, true, true, false, false).ID: return 1891; case Fire::Fire(14, true, true, false, true, true).ID: return 1892; case Fire::Fire(14, true, true, false, true, false).ID: return 1893; case Fire::Fire(14, true, true, false, false, true).ID: return 1894; case Fire::Fire(14, true, true, false, false, false).ID: return 1895; case Fire::Fire(14, true, false, true, true, true).ID: return 1896; case Fire::Fire(14, true, false, true, true, false).ID: return 1897; case Fire::Fire(14, true, false, true, false, true).ID: return 1898; case Fire::Fire(14, true, false, true, false, false).ID: return 1899; case Fire::Fire(14, true, false, false, true, true).ID: return 1900; case Fire::Fire(14, true, false, false, true, false).ID: return 1901; case Fire::Fire(14, true, false, false, false, true).ID: return 1902; case Fire::Fire(14, true, false, false, false, false).ID: return 1903; case Fire::Fire(14, false, true, true, true, true).ID: return 1904; case Fire::Fire(14, false, true, true, true, false).ID: return 1905; case Fire::Fire(14, false, true, true, false, true).ID: return 1906; case Fire::Fire(14, false, true, true, false, false).ID: return 1907; case Fire::Fire(14, false, true, false, true, true).ID: return 1908; case Fire::Fire(14, false, true, false, true, false).ID: return 1909; case Fire::Fire(14, false, true, false, false, true).ID: return 1910; case Fire::Fire(14, false, true, false, false, false).ID: return 1911; case Fire::Fire(14, false, false, true, true, true).ID: return 1912; case Fire::Fire(14, false, false, true, true, false).ID: return 1913; case Fire::Fire(14, false, false, true, false, true).ID: return 1914; case Fire::Fire(14, false, false, true, false, false).ID: return 1915; case Fire::Fire(14, false, false, false, true, true).ID: return 1916; case Fire::Fire(14, false, false, false, true, false).ID: return 1917; case Fire::Fire(14, false, false, false, false, true).ID: return 1918; case Fire::Fire(14, false, false, false, false, false).ID: return 1919; case Fire::Fire(15, true, true, true, true, true).ID: return 1920; case Fire::Fire(15, true, true, true, true, false).ID: return 1921; case Fire::Fire(15, true, true, true, false, true).ID: return 1922; case Fire::Fire(15, true, true, true, false, false).ID: return 1923; case Fire::Fire(15, true, true, false, true, true).ID: return 1924; case Fire::Fire(15, true, true, false, true, false).ID: return 1925; case Fire::Fire(15, true, true, false, false, true).ID: return 1926; case Fire::Fire(15, true, true, false, false, false).ID: return 1927; case Fire::Fire(15, true, false, true, true, true).ID: return 1928; case Fire::Fire(15, true, false, true, true, false).ID: return 1929; case Fire::Fire(15, true, false, true, false, true).ID: return 1930; case Fire::Fire(15, true, false, true, false, false).ID: return 1931; case Fire::Fire(15, true, false, false, true, true).ID: return 1932; case Fire::Fire(15, true, false, false, true, false).ID: return 1933; case Fire::Fire(15, true, false, false, false, true).ID: return 1934; case Fire::Fire(15, true, false, false, false, false).ID: return 1935; case Fire::Fire(15, false, true, true, true, true).ID: return 1936; case Fire::Fire(15, false, true, true, true, false).ID: return 1937; case Fire::Fire(15, false, true, true, false, true).ID: return 1938; case Fire::Fire(15, false, true, true, false, false).ID: return 1939; case Fire::Fire(15, false, true, false, true, true).ID: return 1940; case Fire::Fire(15, false, true, false, true, false).ID: return 1941; case Fire::Fire(15, false, true, false, false, true).ID: return 1942; case Fire::Fire(15, false, true, false, false, false).ID: return 1943; case Fire::Fire(15, false, false, true, true, true).ID: return 1944; case Fire::Fire(15, false, false, true, true, false).ID: return 1945; case Fire::Fire(15, false, false, true, false, true).ID: return 1946; case Fire::Fire(15, false, false, true, false, false).ID: return 1947; case Fire::Fire(15, false, false, false, true, true).ID: return 1948; case Fire::Fire(15, false, false, false, true, false).ID: return 1949; case Fire::Fire(15, false, false, false, false, true).ID: return 1950; case Fire::Fire(15, false, false, false, false, false).ID: return 1951; case FireCoral::FireCoral().ID: return 9537; case FireCoralBlock::FireCoralBlock().ID: return 9518; case FireCoralFan::FireCoralFan().ID: return 9557; case FireCoralWallFan::FireCoralWallFan(eBlockFace::BLOCK_FACE_ZM).ID: return 9625; case FireCoralWallFan::FireCoralWallFan(eBlockFace::BLOCK_FACE_ZP).ID: return 9627; case FireCoralWallFan::FireCoralWallFan(eBlockFace::BLOCK_FACE_XM).ID: return 9629; case FireCoralWallFan::FireCoralWallFan(eBlockFace::BLOCK_FACE_XP).ID: return 9631; case FletchingTable::FletchingTable().ID: return 14820; case FlowerPot::FlowerPot().ID: return 6305; case FrostedIce::FrostedIce(0).ID: return 9249; case FrostedIce::FrostedIce(1).ID: return 9250; case FrostedIce::FrostedIce(2).ID: return 9251; case FrostedIce::FrostedIce(3).ID: return 9252; case Furnace::Furnace(eBlockFace::BLOCK_FACE_ZM, true).ID: return 3373; case Furnace::Furnace(eBlockFace::BLOCK_FACE_ZM, false).ID: return 3374; case Furnace::Furnace(eBlockFace::BLOCK_FACE_ZP, true).ID: return 3375; case Furnace::Furnace(eBlockFace::BLOCK_FACE_ZP, false).ID: return 3376; case Furnace::Furnace(eBlockFace::BLOCK_FACE_XM, true).ID: return 3377; case Furnace::Furnace(eBlockFace::BLOCK_FACE_XM, false).ID: return 3378; case Furnace::Furnace(eBlockFace::BLOCK_FACE_XP, true).ID: return 3379; case Furnace::Furnace(eBlockFace::BLOCK_FACE_XP, false).ID: return 3380; case GildedBlackstone::GildedBlackstone().ID: return 16664; case Glass::Glass().ID: return 231; case GlassPane::GlassPane(true, true, true, true).ID: return 4733; case GlassPane::GlassPane(true, true, true, false).ID: return 4734; case GlassPane::GlassPane(true, true, false, true).ID: return 4737; case GlassPane::GlassPane(true, true, false, false).ID: return 4738; case GlassPane::GlassPane(true, false, true, true).ID: return 4741; case GlassPane::GlassPane(true, false, true, false).ID: return 4742; case GlassPane::GlassPane(true, false, false, true).ID: return 4745; case GlassPane::GlassPane(true, false, false, false).ID: return 4746; case GlassPane::GlassPane(false, true, true, true).ID: return 4749; case GlassPane::GlassPane(false, true, true, false).ID: return 4750; case GlassPane::GlassPane(false, true, false, true).ID: return 4753; case GlassPane::GlassPane(false, true, false, false).ID: return 4754; case GlassPane::GlassPane(false, false, true, true).ID: return 4757; case GlassPane::GlassPane(false, false, true, false).ID: return 4758; case GlassPane::GlassPane(false, false, false, true).ID: return 4761; case GlassPane::GlassPane(false, false, false, false).ID: return 4762; case Glowstone::Glowstone().ID: return 4013; case GoldBlock::GoldBlock().ID: return 1427; case GoldOre::GoldOre().ID: return 69; case Granite::Granite().ID: return 2; case GraniteSlab::GraniteSlab(GraniteSlab::Type::Top).ID: return 10838; case GraniteSlab::GraniteSlab(GraniteSlab::Type::Bottom).ID: return 10840; case GraniteSlab::GraniteSlab(GraniteSlab::Type::Double).ID: return 10842; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_ZM, GraniteStairs::Half::Top, GraniteStairs::Shape::Straight).ID: return 10390; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_ZM, GraniteStairs::Half::Top, GraniteStairs::Shape::InnerLeft).ID: return 10392; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_ZM, GraniteStairs::Half::Top, GraniteStairs::Shape::InnerRight).ID: return 10394; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_ZM, GraniteStairs::Half::Top, GraniteStairs::Shape::OuterLeft).ID: return 10396; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_ZM, GraniteStairs::Half::Top, GraniteStairs::Shape::OuterRight).ID: return 10398; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_ZM, GraniteStairs::Half::Bottom, GraniteStairs::Shape::Straight).ID: return 10400; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_ZM, GraniteStairs::Half::Bottom, GraniteStairs::Shape::InnerLeft).ID: return 10402; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_ZM, GraniteStairs::Half::Bottom, GraniteStairs::Shape::InnerRight).ID: return 10404; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_ZM, GraniteStairs::Half::Bottom, GraniteStairs::Shape::OuterLeft).ID: return 10406; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_ZM, GraniteStairs::Half::Bottom, GraniteStairs::Shape::OuterRight).ID: return 10408; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_ZP, GraniteStairs::Half::Top, GraniteStairs::Shape::Straight).ID: return 10410; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_ZP, GraniteStairs::Half::Top, GraniteStairs::Shape::InnerLeft).ID: return 10412; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_ZP, GraniteStairs::Half::Top, GraniteStairs::Shape::InnerRight).ID: return 10414; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_ZP, GraniteStairs::Half::Top, GraniteStairs::Shape::OuterLeft).ID: return 10416; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_ZP, GraniteStairs::Half::Top, GraniteStairs::Shape::OuterRight).ID: return 10418; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_ZP, GraniteStairs::Half::Bottom, GraniteStairs::Shape::Straight).ID: return 10420; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_ZP, GraniteStairs::Half::Bottom, GraniteStairs::Shape::InnerLeft).ID: return 10422; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_ZP, GraniteStairs::Half::Bottom, GraniteStairs::Shape::InnerRight).ID: return 10424; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_ZP, GraniteStairs::Half::Bottom, GraniteStairs::Shape::OuterLeft).ID: return 10426; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_ZP, GraniteStairs::Half::Bottom, GraniteStairs::Shape::OuterRight).ID: return 10428; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_XM, GraniteStairs::Half::Top, GraniteStairs::Shape::Straight).ID: return 10430; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_XM, GraniteStairs::Half::Top, GraniteStairs::Shape::InnerLeft).ID: return 10432; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_XM, GraniteStairs::Half::Top, GraniteStairs::Shape::InnerRight).ID: return 10434; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_XM, GraniteStairs::Half::Top, GraniteStairs::Shape::OuterLeft).ID: return 10436; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_XM, GraniteStairs::Half::Top, GraniteStairs::Shape::OuterRight).ID: return 10438; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_XM, GraniteStairs::Half::Bottom, GraniteStairs::Shape::Straight).ID: return 10440; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_XM, GraniteStairs::Half::Bottom, GraniteStairs::Shape::InnerLeft).ID: return 10442; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_XM, GraniteStairs::Half::Bottom, GraniteStairs::Shape::InnerRight).ID: return 10444; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_XM, GraniteStairs::Half::Bottom, GraniteStairs::Shape::OuterLeft).ID: return 10446; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_XM, GraniteStairs::Half::Bottom, GraniteStairs::Shape::OuterRight).ID: return 10448; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_XP, GraniteStairs::Half::Top, GraniteStairs::Shape::Straight).ID: return 10450; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_XP, GraniteStairs::Half::Top, GraniteStairs::Shape::InnerLeft).ID: return 10452; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_XP, GraniteStairs::Half::Top, GraniteStairs::Shape::InnerRight).ID: return 10454; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_XP, GraniteStairs::Half::Top, GraniteStairs::Shape::OuterLeft).ID: return 10456; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_XP, GraniteStairs::Half::Top, GraniteStairs::Shape::OuterRight).ID: return 10458; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_XP, GraniteStairs::Half::Bottom, GraniteStairs::Shape::Straight).ID: return 10460; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_XP, GraniteStairs::Half::Bottom, GraniteStairs::Shape::InnerLeft).ID: return 10462; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_XP, GraniteStairs::Half::Bottom, GraniteStairs::Shape::InnerRight).ID: return 10464; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_XP, GraniteStairs::Half::Bottom, GraniteStairs::Shape::OuterLeft).ID: return 10466; case GraniteStairs::GraniteStairs(eBlockFace::BLOCK_FACE_XP, GraniteStairs::Half::Bottom, GraniteStairs::Shape::OuterRight).ID: return 10468; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::None, GraniteWall::South::None, true, GraniteWall::West::None).ID: return 12166; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::None, GraniteWall::South::None, true, GraniteWall::West::Low).ID: return 12167; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::None, GraniteWall::South::None, true, GraniteWall::West::Tall).ID: return 12168; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::None, GraniteWall::South::None, false, GraniteWall::West::None).ID: return 12172; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::None, GraniteWall::South::None, false, GraniteWall::West::Low).ID: return 12173; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::None, GraniteWall::South::None, false, GraniteWall::West::Tall).ID: return 12174; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::None, GraniteWall::South::Low, true, GraniteWall::West::None).ID: return 12178; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::None, GraniteWall::South::Low, true, GraniteWall::West::Low).ID: return 12179; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::None, GraniteWall::South::Low, true, GraniteWall::West::Tall).ID: return 12180; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::None, GraniteWall::South::Low, false, GraniteWall::West::None).ID: return 12184; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::None, GraniteWall::South::Low, false, GraniteWall::West::Low).ID: return 12185; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::None, GraniteWall::South::Low, false, GraniteWall::West::Tall).ID: return 12186; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::None, GraniteWall::South::Tall, true, GraniteWall::West::None).ID: return 12190; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::None, GraniteWall::South::Tall, true, GraniteWall::West::Low).ID: return 12191; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::None, GraniteWall::South::Tall, true, GraniteWall::West::Tall).ID: return 12192; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::None, GraniteWall::South::Tall, false, GraniteWall::West::None).ID: return 12196; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::None, GraniteWall::South::Tall, false, GraniteWall::West::Low).ID: return 12197; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::None, GraniteWall::South::Tall, false, GraniteWall::West::Tall).ID: return 12198; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::Low, GraniteWall::South::None, true, GraniteWall::West::None).ID: return 12202; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::Low, GraniteWall::South::None, true, GraniteWall::West::Low).ID: return 12203; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::Low, GraniteWall::South::None, true, GraniteWall::West::Tall).ID: return 12204; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::Low, GraniteWall::South::None, false, GraniteWall::West::None).ID: return 12208; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::Low, GraniteWall::South::None, false, GraniteWall::West::Low).ID: return 12209; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::Low, GraniteWall::South::None, false, GraniteWall::West::Tall).ID: return 12210; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::Low, GraniteWall::South::Low, true, GraniteWall::West::None).ID: return 12214; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::Low, GraniteWall::South::Low, true, GraniteWall::West::Low).ID: return 12215; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::Low, GraniteWall::South::Low, true, GraniteWall::West::Tall).ID: return 12216; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::Low, GraniteWall::South::Low, false, GraniteWall::West::None).ID: return 12220; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::Low, GraniteWall::South::Low, false, GraniteWall::West::Low).ID: return 12221; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::Low, GraniteWall::South::Low, false, GraniteWall::West::Tall).ID: return 12222; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::Low, GraniteWall::South::Tall, true, GraniteWall::West::None).ID: return 12226; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::Low, GraniteWall::South::Tall, true, GraniteWall::West::Low).ID: return 12227; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::Low, GraniteWall::South::Tall, true, GraniteWall::West::Tall).ID: return 12228; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::Low, GraniteWall::South::Tall, false, GraniteWall::West::None).ID: return 12232; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::Low, GraniteWall::South::Tall, false, GraniteWall::West::Low).ID: return 12233; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::Low, GraniteWall::South::Tall, false, GraniteWall::West::Tall).ID: return 12234; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::Tall, GraniteWall::South::None, true, GraniteWall::West::None).ID: return 12238; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::Tall, GraniteWall::South::None, true, GraniteWall::West::Low).ID: return 12239; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::Tall, GraniteWall::South::None, true, GraniteWall::West::Tall).ID: return 12240; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::Tall, GraniteWall::South::None, false, GraniteWall::West::None).ID: return 12244; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::Tall, GraniteWall::South::None, false, GraniteWall::West::Low).ID: return 12245; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::Tall, GraniteWall::South::None, false, GraniteWall::West::Tall).ID: return 12246; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::Tall, GraniteWall::South::Low, true, GraniteWall::West::None).ID: return 12250; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::Tall, GraniteWall::South::Low, true, GraniteWall::West::Low).ID: return 12251; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::Tall, GraniteWall::South::Low, true, GraniteWall::West::Tall).ID: return 12252; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::Tall, GraniteWall::South::Low, false, GraniteWall::West::None).ID: return 12256; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::Tall, GraniteWall::South::Low, false, GraniteWall::West::Low).ID: return 12257; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::Tall, GraniteWall::South::Low, false, GraniteWall::West::Tall).ID: return 12258; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::Tall, GraniteWall::South::Tall, true, GraniteWall::West::None).ID: return 12262; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::Tall, GraniteWall::South::Tall, true, GraniteWall::West::Low).ID: return 12263; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::Tall, GraniteWall::South::Tall, true, GraniteWall::West::Tall).ID: return 12264; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::Tall, GraniteWall::South::Tall, false, GraniteWall::West::None).ID: return 12268; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::Tall, GraniteWall::South::Tall, false, GraniteWall::West::Low).ID: return 12269; case GraniteWall::GraniteWall(GraniteWall::East::None, GraniteWall::North::Tall, GraniteWall::South::Tall, false, GraniteWall::West::Tall).ID: return 12270; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::None, GraniteWall::South::None, true, GraniteWall::West::None).ID: return 12274; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::None, GraniteWall::South::None, true, GraniteWall::West::Low).ID: return 12275; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::None, GraniteWall::South::None, true, GraniteWall::West::Tall).ID: return 12276; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::None, GraniteWall::South::None, false, GraniteWall::West::None).ID: return 12280; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::None, GraniteWall::South::None, false, GraniteWall::West::Low).ID: return 12281; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::None, GraniteWall::South::None, false, GraniteWall::West::Tall).ID: return 12282; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::None, GraniteWall::South::Low, true, GraniteWall::West::None).ID: return 12286; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::None, GraniteWall::South::Low, true, GraniteWall::West::Low).ID: return 12287; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::None, GraniteWall::South::Low, true, GraniteWall::West::Tall).ID: return 12288; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::None, GraniteWall::South::Low, false, GraniteWall::West::None).ID: return 12292; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::None, GraniteWall::South::Low, false, GraniteWall::West::Low).ID: return 12293; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::None, GraniteWall::South::Low, false, GraniteWall::West::Tall).ID: return 12294; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::None, GraniteWall::South::Tall, true, GraniteWall::West::None).ID: return 12298; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::None, GraniteWall::South::Tall, true, GraniteWall::West::Low).ID: return 12299; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::None, GraniteWall::South::Tall, true, GraniteWall::West::Tall).ID: return 12300; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::None, GraniteWall::South::Tall, false, GraniteWall::West::None).ID: return 12304; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::None, GraniteWall::South::Tall, false, GraniteWall::West::Low).ID: return 12305; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::None, GraniteWall::South::Tall, false, GraniteWall::West::Tall).ID: return 12306; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::Low, GraniteWall::South::None, true, GraniteWall::West::None).ID: return 12310; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::Low, GraniteWall::South::None, true, GraniteWall::West::Low).ID: return 12311; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::Low, GraniteWall::South::None, true, GraniteWall::West::Tall).ID: return 12312; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::Low, GraniteWall::South::None, false, GraniteWall::West::None).ID: return 12316; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::Low, GraniteWall::South::None, false, GraniteWall::West::Low).ID: return 12317; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::Low, GraniteWall::South::None, false, GraniteWall::West::Tall).ID: return 12318; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::Low, GraniteWall::South::Low, true, GraniteWall::West::None).ID: return 12322; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::Low, GraniteWall::South::Low, true, GraniteWall::West::Low).ID: return 12323; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::Low, GraniteWall::South::Low, true, GraniteWall::West::Tall).ID: return 12324; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::Low, GraniteWall::South::Low, false, GraniteWall::West::None).ID: return 12328; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::Low, GraniteWall::South::Low, false, GraniteWall::West::Low).ID: return 12329; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::Low, GraniteWall::South::Low, false, GraniteWall::West::Tall).ID: return 12330; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::Low, GraniteWall::South::Tall, true, GraniteWall::West::None).ID: return 12334; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::Low, GraniteWall::South::Tall, true, GraniteWall::West::Low).ID: return 12335; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::Low, GraniteWall::South::Tall, true, GraniteWall::West::Tall).ID: return 12336; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::Low, GraniteWall::South::Tall, false, GraniteWall::West::None).ID: return 12340; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::Low, GraniteWall::South::Tall, false, GraniteWall::West::Low).ID: return 12341; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::Low, GraniteWall::South::Tall, false, GraniteWall::West::Tall).ID: return 12342; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::Tall, GraniteWall::South::None, true, GraniteWall::West::None).ID: return 12346; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::Tall, GraniteWall::South::None, true, GraniteWall::West::Low).ID: return 12347; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::Tall, GraniteWall::South::None, true, GraniteWall::West::Tall).ID: return 12348; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::Tall, GraniteWall::South::None, false, GraniteWall::West::None).ID: return 12352; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::Tall, GraniteWall::South::None, false, GraniteWall::West::Low).ID: return 12353; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::Tall, GraniteWall::South::None, false, GraniteWall::West::Tall).ID: return 12354; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::Tall, GraniteWall::South::Low, true, GraniteWall::West::None).ID: return 12358; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::Tall, GraniteWall::South::Low, true, GraniteWall::West::Low).ID: return 12359; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::Tall, GraniteWall::South::Low, true, GraniteWall::West::Tall).ID: return 12360; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::Tall, GraniteWall::South::Low, false, GraniteWall::West::None).ID: return 12364; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::Tall, GraniteWall::South::Low, false, GraniteWall::West::Low).ID: return 12365; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::Tall, GraniteWall::South::Low, false, GraniteWall::West::Tall).ID: return 12366; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::Tall, GraniteWall::South::Tall, true, GraniteWall::West::None).ID: return 12370; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::Tall, GraniteWall::South::Tall, true, GraniteWall::West::Low).ID: return 12371; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::Tall, GraniteWall::South::Tall, true, GraniteWall::West::Tall).ID: return 12372; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::Tall, GraniteWall::South::Tall, false, GraniteWall::West::None).ID: return 12376; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::Tall, GraniteWall::South::Tall, false, GraniteWall::West::Low).ID: return 12377; case GraniteWall::GraniteWall(GraniteWall::East::Low, GraniteWall::North::Tall, GraniteWall::South::Tall, false, GraniteWall::West::Tall).ID: return 12378; case GraniteWall::GraniteWall(GraniteWall::East::Tall, GraniteWall::North::None, GraniteWall::South::None, true, GraniteWall::West::None).ID: return 12382; case GraniteWall::GraniteWall(GraniteWall::East::Tall, GraniteWall::North::None, GraniteWall::South::None, true, GraniteWall::West::Low).ID: return 12383; case GraniteWall::GraniteWall(GraniteWall::East::Tall, GraniteWall::North::None, GraniteWall::South::None, true, GraniteWall::West::Tall).ID: return 12384; case GraniteWall::GraniteWall(GraniteWall::East::Tall, GraniteWall::North::None, GraniteWall::South::None, false, GraniteWall::West::None).ID: return 12388; case GraniteWall::GraniteWall(GraniteWall::East::Tall, GraniteWall::North::None, GraniteWall::South::None, false, GraniteWall::West::Low).ID: return 12389; case GraniteWall::GraniteWall(GraniteWall::East::Tall, GraniteWall::North::None, GraniteWall::South::None, false, GraniteWall::West::Tall).ID: return 12390; case GraniteWall::GraniteWall(GraniteWall::East::Tall, GraniteWall::North::None, GraniteWall::South::Low, true, GraniteWall::West::None).ID: return 12394; case GraniteWall::GraniteWall(GraniteWall::East::Tall, GraniteWall::North::None, GraniteWall::South::Low, true, GraniteWall::West::Low).ID: return 12395; case GraniteWall::GraniteWall(GraniteWall::East::Tall, GraniteWall::North::None, GraniteWall::South::Low, true, GraniteWall::West::Tall).ID: return 12396; case GraniteWall::GraniteWall(GraniteWall::East::Tall, GraniteWall::North::None, GraniteWall::South::Low, false, GraniteWall::West::None).ID: return 12400; case GraniteWall::GraniteWall(GraniteWall::East::Tall, GraniteWall::North::None, GraniteWall::South::Low, false, GraniteWall::West::Low).ID: return 12401; case GraniteWall::GraniteWall(GraniteWall::East::Tall, GraniteWall::North::None, GraniteWall::South::Low, false, GraniteWall::West::Tall).ID: return 12402; case GraniteWall::GraniteWall(GraniteWall::East::Tall, GraniteWall::North::None, GraniteWall::South::Tall, true, GraniteWall::West::None).ID: return 12406; case GraniteWall::GraniteWall(GraniteWall::East::Tall, GraniteWall::North::None, GraniteWall::South::Tall, true, GraniteWall::West::Low).ID: return 12407; case GraniteWall::GraniteWall(GraniteWall::East::Tall, GraniteWall::North::None, GraniteWall::South::Tall, true, GraniteWall::West::Tall).ID: return 12408; case GraniteWall::GraniteWall(GraniteWall::East::Tall, GraniteWall::North::None, GraniteWall::South::Tall, false, GraniteWall::West::None).ID: return 12412; case GraniteWall::GraniteWall(GraniteWall::East::Tall, GraniteWall::North::None, GraniteWall::South::Tall, false, GraniteWall::West::Low).ID: return 12413; case GraniteWall::GraniteWall(GraniteWall::East::Tall, GraniteWall::North::None, GraniteWall::South::Tall, false, GraniteWall::West::Tall).ID: return 12414; case GraniteWall::GraniteWall(GraniteWall::East::Tall, GraniteWall::North::Low, GraniteWall::South::None, true, GraniteWall::West::None).ID: return 12418; case GraniteWall::GraniteWall(GraniteWall::East::Tall, GraniteWall::North::Low, GraniteWall::South::None, true, GraniteWall::West::Low).ID: return 12419; case GraniteWall::GraniteWall(GraniteWall::East::Tall, GraniteWall::North::Low, GraniteWall::South::None, true, GraniteWall::West::Tall).ID: return 12420; case GraniteWall::GraniteWall(GraniteWall::East::Tall, GraniteWall::North::Low, GraniteWall::South::None, false, GraniteWall::West::None).ID: return 12424; case GraniteWall::GraniteWall(GraniteWall::East::Tall, GraniteWall::North::Low, GraniteWall::South::None, false, GraniteWall::West::Low).ID: return 12425; case GraniteWall::GraniteWall(GraniteWall::East::Tall, GraniteWall::North::Low, GraniteWall::South::None, false, GraniteWall::West::Tall).ID: return 12426; case GraniteWall::GraniteWall(GraniteWall::East::Tall, GraniteWall::North::Low, GraniteWall::South::Low, true, GraniteWall::West::None).ID: return 12430; case GraniteWall::GraniteWall(GraniteWall::East::Tall, GraniteWall::North::Low, GraniteWall::South::Low, true, GraniteWall::West::Low).ID: return 12431; case GraniteWall::GraniteWall(GraniteWall::East::Tall, GraniteWall::North::Low, GraniteWall::South::Low, true, GraniteWall::West::Tall).ID: return 12432; case GraniteWall::GraniteWall(GraniteWall::East::Tall, GraniteWall::North::Low, GraniteWall::South::Low, false, GraniteWall::West::None).ID: return 12436; case GraniteWall::GraniteWall(GraniteWall::East::Tall, GraniteWall::North::Low, GraniteWall::South::Low, false, GraniteWall::West::Low).ID: return 12437; case GraniteWall::GraniteWall(GraniteWall::East::Tall, GraniteWall::North::Low, GraniteWall::South::Low, false, GraniteWall::West::Tall).ID: return 12438; case GraniteWall::GraniteWall(GraniteWall::East::Tall, GraniteWall::North::Low, GraniteWall::South::Tall, true, GraniteWall::West::None).ID: return 12442; case GraniteWall::GraniteWall(GraniteWall::East::Tall, GraniteWall::North::Low, GraniteWall::South::Tall, true, GraniteWall::West::Low).ID: return 12443; case GraniteWall::GraniteWall(GraniteWall::East::Tall, GraniteWall::North::Low, GraniteWall::South::Tall, true, GraniteWall::West::Tall).ID: return 12444; case GraniteWall::GraniteWall(GraniteWall::East::Tall, GraniteWall::North::Low, GraniteWall::South::Tall, false, GraniteWall::West::None).ID: return 12448; case GraniteWall::GraniteWall(GraniteWall::East::Tall, GraniteWall::North::Low, GraniteWall::South::Tall, false, GraniteWall::West::Low).ID: return 12449; case GraniteWall::GraniteWall(GraniteWall::East::Tall, GraniteWall::North::Low, GraniteWall::South::Tall, false, GraniteWall::West::Tall).ID: return 12450; case GraniteWall::GraniteWall(GraniteWall::East::Tall, GraniteWall::North::Tall, GraniteWall::South::None, true, GraniteWall::West::None).ID: return 12454; case GraniteWall::GraniteWall(GraniteWall::East::Tall, GraniteWall::North::Tall, GraniteWall::South::None, true, GraniteWall::West::Low).ID: return 12455; case GraniteWall::GraniteWall(GraniteWall::East::Tall, GraniteWall::North::Tall, GraniteWall::South::None, true, GraniteWall::West::Tall).ID: return 12456; case GraniteWall::GraniteWall(GraniteWall::East::Tall, GraniteWall::North::Tall, GraniteWall::South::None, false, GraniteWall::West::None).ID: return 12460; case GraniteWall::GraniteWall(GraniteWall::East::Tall, GraniteWall::North::Tall, GraniteWall::South::None, false, GraniteWall::West::Low).ID: return 12461; case GraniteWall::GraniteWall(GraniteWall::East::Tall, GraniteWall::North::Tall, GraniteWall::South::None, false, GraniteWall::West::Tall).ID: return 12462; case GraniteWall::GraniteWall(GraniteWall::East::Tall, GraniteWall::North::Tall, GraniteWall::South::Low, true, GraniteWall::West::None).ID: return 12466; case GraniteWall::GraniteWall(GraniteWall::East::Tall, GraniteWall::North::Tall, GraniteWall::South::Low, true, GraniteWall::West::Low).ID: return 12467; case GraniteWall::GraniteWall(GraniteWall::East::Tall, GraniteWall::North::Tall, GraniteWall::South::Low, true, GraniteWall::West::Tall).ID: return 12468; case GraniteWall::GraniteWall(GraniteWall::East::Tall, GraniteWall::North::Tall, GraniteWall::South::Low, false, GraniteWall::West::None).ID: return 12472; case GraniteWall::GraniteWall(GraniteWall::East::Tall, GraniteWall::North::Tall, GraniteWall::South::Low, false, GraniteWall::West::Low).ID: return 12473; case GraniteWall::GraniteWall(GraniteWall::East::Tall, GraniteWall::North::Tall, GraniteWall::South::Low, false, GraniteWall::West::Tall).ID: return 12474; case GraniteWall::GraniteWall(GraniteWall::East::Tall, GraniteWall::North::Tall, GraniteWall::South::Tall, true, GraniteWall::West::None).ID: return 12478; case GraniteWall::GraniteWall(GraniteWall::East::Tall, GraniteWall::North::Tall, GraniteWall::South::Tall, true, GraniteWall::West::Low).ID: return 12479; case GraniteWall::GraniteWall(GraniteWall::East::Tall, GraniteWall::North::Tall, GraniteWall::South::Tall, true, GraniteWall::West::Tall).ID: return 12480; case GraniteWall::GraniteWall(GraniteWall::East::Tall, GraniteWall::North::Tall, GraniteWall::South::Tall, false, GraniteWall::West::None).ID: return 12484; case GraniteWall::GraniteWall(GraniteWall::East::Tall, GraniteWall::North::Tall, GraniteWall::South::Tall, false, GraniteWall::West::Low).ID: return 12485; case GraniteWall::GraniteWall(GraniteWall::East::Tall, GraniteWall::North::Tall, GraniteWall::South::Tall, false, GraniteWall::West::Tall).ID: return 12486; case Grass::Grass().ID: return 1342; case GrassBlock::GrassBlock(true).ID: return 8; case GrassBlock::GrassBlock(false).ID: return 9; case GrassPath::GrassPath().ID: return 9223; case Gravel::Gravel().ID: return 68; case GrayBanner::GrayBanner(0).ID: return 8009; case GrayBanner::GrayBanner(1).ID: return 8010; case GrayBanner::GrayBanner(2).ID: return 8011; case GrayBanner::GrayBanner(3).ID: return 8012; case GrayBanner::GrayBanner(4).ID: return 8013; case GrayBanner::GrayBanner(5).ID: return 8014; case GrayBanner::GrayBanner(6).ID: return 8015; case GrayBanner::GrayBanner(7).ID: return 8016; case GrayBanner::GrayBanner(8).ID: return 8017; case GrayBanner::GrayBanner(9).ID: return 8018; case GrayBanner::GrayBanner(10).ID: return 8019; case GrayBanner::GrayBanner(11).ID: return 8020; case GrayBanner::GrayBanner(12).ID: return 8021; case GrayBanner::GrayBanner(13).ID: return 8022; case GrayBanner::GrayBanner(14).ID: return 8023; case GrayBanner::GrayBanner(15).ID: return 8024; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_ZM, true, GrayBed::Part::Head).ID: return 1161; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_ZM, true, GrayBed::Part::Foot).ID: return 1162; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_ZM, false, GrayBed::Part::Head).ID: return 1163; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_ZM, false, GrayBed::Part::Foot).ID: return 1164; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_ZP, true, GrayBed::Part::Head).ID: return 1165; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_ZP, true, GrayBed::Part::Foot).ID: return 1166; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_ZP, false, GrayBed::Part::Head).ID: return 1167; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_ZP, false, GrayBed::Part::Foot).ID: return 1168; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_XM, true, GrayBed::Part::Head).ID: return 1169; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_XM, true, GrayBed::Part::Foot).ID: return 1170; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_XM, false, GrayBed::Part::Head).ID: return 1171; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_XM, false, GrayBed::Part::Foot).ID: return 1172; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_XP, true, GrayBed::Part::Head).ID: return 1173; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_XP, true, GrayBed::Part::Foot).ID: return 1174; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_XP, false, GrayBed::Part::Head).ID: return 1175; case GrayBed::GrayBed(eBlockFace::BLOCK_FACE_XP, false, GrayBed::Part::Foot).ID: return 1176; case GrayCarpet::GrayCarpet().ID: return 7873; case GrayConcrete::GrayConcrete().ID: return 9445; case GrayConcretePowder::GrayConcretePowder().ID: return 9461; case GrayGlazedTerracotta::GrayGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 9402; case GrayGlazedTerracotta::GrayGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 9403; case GrayGlazedTerracotta::GrayGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 9404; case GrayGlazedTerracotta::GrayGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 9405; case GrayShulkerBox::GrayShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 9320; case GrayShulkerBox::GrayShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 9321; case GrayShulkerBox::GrayShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 9322; case GrayShulkerBox::GrayShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 9323; case GrayShulkerBox::GrayShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 9324; case GrayShulkerBox::GrayShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 9325; case GrayStainedGlass::GrayStainedGlass().ID: return 4102; case GrayStainedGlassPane::GrayStainedGlassPane(true, true, true, true).ID: return 7089; case GrayStainedGlassPane::GrayStainedGlassPane(true, true, true, false).ID: return 7090; case GrayStainedGlassPane::GrayStainedGlassPane(true, true, false, true).ID: return 7093; case GrayStainedGlassPane::GrayStainedGlassPane(true, true, false, false).ID: return 7094; case GrayStainedGlassPane::GrayStainedGlassPane(true, false, true, true).ID: return 7097; case GrayStainedGlassPane::GrayStainedGlassPane(true, false, true, false).ID: return 7098; case GrayStainedGlassPane::GrayStainedGlassPane(true, false, false, true).ID: return 7101; case GrayStainedGlassPane::GrayStainedGlassPane(true, false, false, false).ID: return 7102; case GrayStainedGlassPane::GrayStainedGlassPane(false, true, true, true).ID: return 7105; case GrayStainedGlassPane::GrayStainedGlassPane(false, true, true, false).ID: return 7106; case GrayStainedGlassPane::GrayStainedGlassPane(false, true, false, true).ID: return 7109; case GrayStainedGlassPane::GrayStainedGlassPane(false, true, false, false).ID: return 7110; case GrayStainedGlassPane::GrayStainedGlassPane(false, false, true, true).ID: return 7113; case GrayStainedGlassPane::GrayStainedGlassPane(false, false, true, false).ID: return 7114; case GrayStainedGlassPane::GrayStainedGlassPane(false, false, false, true).ID: return 7117; case GrayStainedGlassPane::GrayStainedGlassPane(false, false, false, false).ID: return 7118; case GrayTerracotta::GrayTerracotta().ID: return 6854; case GrayWallBanner::GrayWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 8181; case GrayWallBanner::GrayWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 8182; case GrayWallBanner::GrayWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 8183; case GrayWallBanner::GrayWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 8184; case GrayWool::GrayWool().ID: return 1391; case GreenBanner::GreenBanner(0).ID: return 8105; case GreenBanner::GreenBanner(1).ID: return 8106; case GreenBanner::GreenBanner(2).ID: return 8107; case GreenBanner::GreenBanner(3).ID: return 8108; case GreenBanner::GreenBanner(4).ID: return 8109; case GreenBanner::GreenBanner(5).ID: return 8110; case GreenBanner::GreenBanner(6).ID: return 8111; case GreenBanner::GreenBanner(7).ID: return 8112; case GreenBanner::GreenBanner(8).ID: return 8113; case GreenBanner::GreenBanner(9).ID: return 8114; case GreenBanner::GreenBanner(10).ID: return 8115; case GreenBanner::GreenBanner(11).ID: return 8116; case GreenBanner::GreenBanner(12).ID: return 8117; case GreenBanner::GreenBanner(13).ID: return 8118; case GreenBanner::GreenBanner(14).ID: return 8119; case GreenBanner::GreenBanner(15).ID: return 8120; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_ZM, true, GreenBed::Part::Head).ID: return 1257; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_ZM, true, GreenBed::Part::Foot).ID: return 1258; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_ZM, false, GreenBed::Part::Head).ID: return 1259; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_ZM, false, GreenBed::Part::Foot).ID: return 1260; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_ZP, true, GreenBed::Part::Head).ID: return 1261; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_ZP, true, GreenBed::Part::Foot).ID: return 1262; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_ZP, false, GreenBed::Part::Head).ID: return 1263; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_ZP, false, GreenBed::Part::Foot).ID: return 1264; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_XM, true, GreenBed::Part::Head).ID: return 1265; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_XM, true, GreenBed::Part::Foot).ID: return 1266; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_XM, false, GreenBed::Part::Head).ID: return 1267; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_XM, false, GreenBed::Part::Foot).ID: return 1268; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_XP, true, GreenBed::Part::Head).ID: return 1269; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_XP, true, GreenBed::Part::Foot).ID: return 1270; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_XP, false, GreenBed::Part::Head).ID: return 1271; case GreenBed::GreenBed(eBlockFace::BLOCK_FACE_XP, false, GreenBed::Part::Foot).ID: return 1272; case GreenCarpet::GreenCarpet().ID: return 7879; case GreenConcrete::GreenConcrete().ID: return 9451; case GreenConcretePowder::GreenConcretePowder().ID: return 9467; case GreenGlazedTerracotta::GreenGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 9426; case GreenGlazedTerracotta::GreenGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 9427; case GreenGlazedTerracotta::GreenGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 9428; case GreenGlazedTerracotta::GreenGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 9429; case GreenShulkerBox::GreenShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 9356; case GreenShulkerBox::GreenShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 9357; case GreenShulkerBox::GreenShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 9358; case GreenShulkerBox::GreenShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 9359; case GreenShulkerBox::GreenShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 9360; case GreenShulkerBox::GreenShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 9361; case GreenStainedGlass::GreenStainedGlass().ID: return 4108; case GreenStainedGlassPane::GreenStainedGlassPane(true, true, true, true).ID: return 7281; case GreenStainedGlassPane::GreenStainedGlassPane(true, true, true, false).ID: return 7282; case GreenStainedGlassPane::GreenStainedGlassPane(true, true, false, true).ID: return 7285; case GreenStainedGlassPane::GreenStainedGlassPane(true, true, false, false).ID: return 7286; case GreenStainedGlassPane::GreenStainedGlassPane(true, false, true, true).ID: return 7289; case GreenStainedGlassPane::GreenStainedGlassPane(true, false, true, false).ID: return 7290; case GreenStainedGlassPane::GreenStainedGlassPane(true, false, false, true).ID: return 7293; case GreenStainedGlassPane::GreenStainedGlassPane(true, false, false, false).ID: return 7294; case GreenStainedGlassPane::GreenStainedGlassPane(false, true, true, true).ID: return 7297; case GreenStainedGlassPane::GreenStainedGlassPane(false, true, true, false).ID: return 7298; case GreenStainedGlassPane::GreenStainedGlassPane(false, true, false, true).ID: return 7301; case GreenStainedGlassPane::GreenStainedGlassPane(false, true, false, false).ID: return 7302; case GreenStainedGlassPane::GreenStainedGlassPane(false, false, true, true).ID: return 7305; case GreenStainedGlassPane::GreenStainedGlassPane(false, false, true, false).ID: return 7306; case GreenStainedGlassPane::GreenStainedGlassPane(false, false, false, true).ID: return 7309; case GreenStainedGlassPane::GreenStainedGlassPane(false, false, false, false).ID: return 7310; case GreenTerracotta::GreenTerracotta().ID: return 6860; case GreenWallBanner::GreenWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 8205; case GreenWallBanner::GreenWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 8206; case GreenWallBanner::GreenWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 8207; case GreenWallBanner::GreenWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 8208; case GreenWool::GreenWool().ID: return 1397; case Grindstone::Grindstone(Grindstone::Face::Floor, eBlockFace::BLOCK_FACE_ZM).ID: return 14821; case Grindstone::Grindstone(Grindstone::Face::Floor, eBlockFace::BLOCK_FACE_ZP).ID: return 14822; case Grindstone::Grindstone(Grindstone::Face::Floor, eBlockFace::BLOCK_FACE_XM).ID: return 14823; case Grindstone::Grindstone(Grindstone::Face::Floor, eBlockFace::BLOCK_FACE_XP).ID: return 14824; case Grindstone::Grindstone(Grindstone::Face::Wall, eBlockFace::BLOCK_FACE_ZM).ID: return 14825; case Grindstone::Grindstone(Grindstone::Face::Wall, eBlockFace::BLOCK_FACE_ZP).ID: return 14826; case Grindstone::Grindstone(Grindstone::Face::Wall, eBlockFace::BLOCK_FACE_XM).ID: return 14827; case Grindstone::Grindstone(Grindstone::Face::Wall, eBlockFace::BLOCK_FACE_XP).ID: return 14828; case Grindstone::Grindstone(Grindstone::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM).ID: return 14829; case Grindstone::Grindstone(Grindstone::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP).ID: return 14830; case Grindstone::Grindstone(Grindstone::Face::Ceiling, eBlockFace::BLOCK_FACE_XM).ID: return 14831; case Grindstone::Grindstone(Grindstone::Face::Ceiling, eBlockFace::BLOCK_FACE_XP).ID: return 14832; case HayBale::HayBale(HayBale::Axis::X).ID: return 7863; case HayBale::HayBale(HayBale::Axis::Y).ID: return 7864; case HayBale::HayBale(HayBale::Axis::Z).ID: return 7865; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(0).ID: return 6662; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(1).ID: return 6663; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(2).ID: return 6664; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(3).ID: return 6665; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(4).ID: return 6666; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(5).ID: return 6667; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(6).ID: return 6668; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(7).ID: return 6669; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(8).ID: return 6670; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(9).ID: return 6671; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(10).ID: return 6672; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(11).ID: return 6673; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(12).ID: return 6674; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(13).ID: return 6675; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(14).ID: return 6676; case HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(15).ID: return 6677; case HoneyBlock::HoneyBlock().ID: return 15824; case HoneycombBlock::HoneycombBlock().ID: return 15825; case Hopper::Hopper(true, eBlockFace::BLOCK_FACE_YM).ID: return 6728; case Hopper::Hopper(true, eBlockFace::BLOCK_FACE_ZM).ID: return 6729; case Hopper::Hopper(true, eBlockFace::BLOCK_FACE_ZP).ID: return 6730; case Hopper::Hopper(true, eBlockFace::BLOCK_FACE_XM).ID: return 6731; case Hopper::Hopper(true, eBlockFace::BLOCK_FACE_XP).ID: return 6732; case Hopper::Hopper(false, eBlockFace::BLOCK_FACE_YM).ID: return 6733; case Hopper::Hopper(false, eBlockFace::BLOCK_FACE_ZM).ID: return 6734; case Hopper::Hopper(false, eBlockFace::BLOCK_FACE_ZP).ID: return 6735; case Hopper::Hopper(false, eBlockFace::BLOCK_FACE_XM).ID: return 6736; case Hopper::Hopper(false, eBlockFace::BLOCK_FACE_XP).ID: return 6737; case HornCoral::HornCoral().ID: return 9539; case HornCoralBlock::HornCoralBlock().ID: return 9519; case HornCoralFan::HornCoralFan().ID: return 9559; case HornCoralWallFan::HornCoralWallFan(eBlockFace::BLOCK_FACE_ZM).ID: return 9633; case HornCoralWallFan::HornCoralWallFan(eBlockFace::BLOCK_FACE_ZP).ID: return 9635; case HornCoralWallFan::HornCoralWallFan(eBlockFace::BLOCK_FACE_XM).ID: return 9637; case HornCoralWallFan::HornCoralWallFan(eBlockFace::BLOCK_FACE_XP).ID: return 9639; case Ice::Ice().ID: return 3929; case InfestedChiseledStoneBricks::InfestedChiseledStoneBricks().ID: return 4504; case InfestedCobblestone::InfestedCobblestone().ID: return 4500; case InfestedCrackedStoneBricks::InfestedCrackedStoneBricks().ID: return 4503; case InfestedMossyStoneBricks::InfestedMossyStoneBricks().ID: return 4502; case InfestedStone::InfestedStone().ID: return 4499; case InfestedStoneBricks::InfestedStoneBricks().ID: return 4501; case IronBars::IronBars(true, true, true, true).ID: return 4699; case IronBars::IronBars(true, true, true, false).ID: return 4700; case IronBars::IronBars(true, true, false, true).ID: return 4703; case IronBars::IronBars(true, true, false, false).ID: return 4704; case IronBars::IronBars(true, false, true, true).ID: return 4707; case IronBars::IronBars(true, false, true, false).ID: return 4708; case IronBars::IronBars(true, false, false, true).ID: return 4711; case IronBars::IronBars(true, false, false, false).ID: return 4712; case IronBars::IronBars(false, true, true, true).ID: return 4715; case IronBars::IronBars(false, true, true, false).ID: return 4716; case IronBars::IronBars(false, true, false, true).ID: return 4719; case IronBars::IronBars(false, true, false, false).ID: return 4720; case IronBars::IronBars(false, false, true, true).ID: return 4723; case IronBars::IronBars(false, false, true, false).ID: return 4724; case IronBars::IronBars(false, false, false, true).ID: return 4727; case IronBars::IronBars(false, false, false, false).ID: return 4728; case IronBlock::IronBlock().ID: return 1428; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Upper, IronDoor::Hinge::Left, true, true).ID: return 3809; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Upper, IronDoor::Hinge::Left, true, false).ID: return 3810; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Upper, IronDoor::Hinge::Left, false, true).ID: return 3811; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Upper, IronDoor::Hinge::Left, false, false).ID: return 3812; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Upper, IronDoor::Hinge::Right, true, true).ID: return 3813; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Upper, IronDoor::Hinge::Right, true, false).ID: return 3814; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Upper, IronDoor::Hinge::Right, false, true).ID: return 3815; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Upper, IronDoor::Hinge::Right, false, false).ID: return 3816; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Lower, IronDoor::Hinge::Left, true, true).ID: return 3817; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Lower, IronDoor::Hinge::Left, true, false).ID: return 3818; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Lower, IronDoor::Hinge::Left, false, true).ID: return 3819; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Lower, IronDoor::Hinge::Left, false, false).ID: return 3820; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Lower, IronDoor::Hinge::Right, true, true).ID: return 3821; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Lower, IronDoor::Hinge::Right, true, false).ID: return 3822; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Lower, IronDoor::Hinge::Right, false, true).ID: return 3823; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Lower, IronDoor::Hinge::Right, false, false).ID: return 3824; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Upper, IronDoor::Hinge::Left, true, true).ID: return 3825; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Upper, IronDoor::Hinge::Left, true, false).ID: return 3826; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Upper, IronDoor::Hinge::Left, false, true).ID: return 3827; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Upper, IronDoor::Hinge::Left, false, false).ID: return 3828; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Upper, IronDoor::Hinge::Right, true, true).ID: return 3829; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Upper, IronDoor::Hinge::Right, true, false).ID: return 3830; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Upper, IronDoor::Hinge::Right, false, true).ID: return 3831; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Upper, IronDoor::Hinge::Right, false, false).ID: return 3832; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Lower, IronDoor::Hinge::Left, true, true).ID: return 3833; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Lower, IronDoor::Hinge::Left, true, false).ID: return 3834; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Lower, IronDoor::Hinge::Left, false, true).ID: return 3835; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Lower, IronDoor::Hinge::Left, false, false).ID: return 3836; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Lower, IronDoor::Hinge::Right, true, true).ID: return 3837; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Lower, IronDoor::Hinge::Right, true, false).ID: return 3838; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Lower, IronDoor::Hinge::Right, false, true).ID: return 3839; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Lower, IronDoor::Hinge::Right, false, false).ID: return 3840; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Upper, IronDoor::Hinge::Left, true, true).ID: return 3841; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Upper, IronDoor::Hinge::Left, true, false).ID: return 3842; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Upper, IronDoor::Hinge::Left, false, true).ID: return 3843; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Upper, IronDoor::Hinge::Left, false, false).ID: return 3844; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Upper, IronDoor::Hinge::Right, true, true).ID: return 3845; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Upper, IronDoor::Hinge::Right, true, false).ID: return 3846; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Upper, IronDoor::Hinge::Right, false, true).ID: return 3847; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Upper, IronDoor::Hinge::Right, false, false).ID: return 3848; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Lower, IronDoor::Hinge::Left, true, true).ID: return 3849; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Lower, IronDoor::Hinge::Left, true, false).ID: return 3850; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Lower, IronDoor::Hinge::Left, false, true).ID: return 3851; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Lower, IronDoor::Hinge::Left, false, false).ID: return 3852; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Lower, IronDoor::Hinge::Right, true, true).ID: return 3853; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Lower, IronDoor::Hinge::Right, true, false).ID: return 3854; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Lower, IronDoor::Hinge::Right, false, true).ID: return 3855; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Lower, IronDoor::Hinge::Right, false, false).ID: return 3856; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Upper, IronDoor::Hinge::Left, true, true).ID: return 3857; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Upper, IronDoor::Hinge::Left, true, false).ID: return 3858; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Upper, IronDoor::Hinge::Left, false, true).ID: return 3859; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Upper, IronDoor::Hinge::Left, false, false).ID: return 3860; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Upper, IronDoor::Hinge::Right, true, true).ID: return 3861; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Upper, IronDoor::Hinge::Right, true, false).ID: return 3862; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Upper, IronDoor::Hinge::Right, false, true).ID: return 3863; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Upper, IronDoor::Hinge::Right, false, false).ID: return 3864; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Lower, IronDoor::Hinge::Left, true, true).ID: return 3865; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Lower, IronDoor::Hinge::Left, true, false).ID: return 3866; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Lower, IronDoor::Hinge::Left, false, true).ID: return 3867; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Lower, IronDoor::Hinge::Left, false, false).ID: return 3868; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Lower, IronDoor::Hinge::Right, true, true).ID: return 3869; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Lower, IronDoor::Hinge::Right, true, false).ID: return 3870; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Lower, IronDoor::Hinge::Right, false, true).ID: return 3871; case IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Lower, IronDoor::Hinge::Right, false, false).ID: return 3872; case IronOre::IronOre().ID: return 70; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZM, IronTrapdoor::Half::Top, true, true).ID: return 7538; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZM, IronTrapdoor::Half::Top, true, false).ID: return 7540; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZM, IronTrapdoor::Half::Top, false, true).ID: return 7542; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZM, IronTrapdoor::Half::Top, false, false).ID: return 7544; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZM, IronTrapdoor::Half::Bottom, true, true).ID: return 7546; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZM, IronTrapdoor::Half::Bottom, true, false).ID: return 7548; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZM, IronTrapdoor::Half::Bottom, false, true).ID: return 7550; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZM, IronTrapdoor::Half::Bottom, false, false).ID: return 7552; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZP, IronTrapdoor::Half::Top, true, true).ID: return 7554; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZP, IronTrapdoor::Half::Top, true, false).ID: return 7556; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZP, IronTrapdoor::Half::Top, false, true).ID: return 7558; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZP, IronTrapdoor::Half::Top, false, false).ID: return 7560; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZP, IronTrapdoor::Half::Bottom, true, true).ID: return 7562; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZP, IronTrapdoor::Half::Bottom, true, false).ID: return 7564; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZP, IronTrapdoor::Half::Bottom, false, true).ID: return 7566; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZP, IronTrapdoor::Half::Bottom, false, false).ID: return 7568; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XM, IronTrapdoor::Half::Top, true, true).ID: return 7570; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XM, IronTrapdoor::Half::Top, true, false).ID: return 7572; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XM, IronTrapdoor::Half::Top, false, true).ID: return 7574; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XM, IronTrapdoor::Half::Top, false, false).ID: return 7576; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XM, IronTrapdoor::Half::Bottom, true, true).ID: return 7578; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XM, IronTrapdoor::Half::Bottom, true, false).ID: return 7580; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XM, IronTrapdoor::Half::Bottom, false, true).ID: return 7582; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XM, IronTrapdoor::Half::Bottom, false, false).ID: return 7584; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XP, IronTrapdoor::Half::Top, true, true).ID: return 7586; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XP, IronTrapdoor::Half::Top, true, false).ID: return 7588; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XP, IronTrapdoor::Half::Top, false, true).ID: return 7590; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XP, IronTrapdoor::Half::Top, false, false).ID: return 7592; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XP, IronTrapdoor::Half::Bottom, true, true).ID: return 7594; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XP, IronTrapdoor::Half::Bottom, true, false).ID: return 7596; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XP, IronTrapdoor::Half::Bottom, false, true).ID: return 7598; case IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XP, IronTrapdoor::Half::Bottom, false, false).ID: return 7600; case JackOLantern::JackOLantern(eBlockFace::BLOCK_FACE_ZM).ID: return 4020; case JackOLantern::JackOLantern(eBlockFace::BLOCK_FACE_ZP).ID: return 4021; case JackOLantern::JackOLantern(eBlockFace::BLOCK_FACE_XM).ID: return 4022; case JackOLantern::JackOLantern(eBlockFace::BLOCK_FACE_XP).ID: return 4023; case Jigsaw::Jigsaw(Jigsaw::Orientation::DownEast).ID: return 15739; case Jigsaw::Jigsaw(Jigsaw::Orientation::DownNorth).ID: return 15740; case Jigsaw::Jigsaw(Jigsaw::Orientation::DownSouth).ID: return 15741; case Jigsaw::Jigsaw(Jigsaw::Orientation::DownWest).ID: return 15742; case Jigsaw::Jigsaw(Jigsaw::Orientation::UpEast).ID: return 15743; case Jigsaw::Jigsaw(Jigsaw::Orientation::UpNorth).ID: return 15744; case Jigsaw::Jigsaw(Jigsaw::Orientation::UpSouth).ID: return 15745; case Jigsaw::Jigsaw(Jigsaw::Orientation::UpWest).ID: return 15746; case Jigsaw::Jigsaw(Jigsaw::Orientation::WestUp).ID: return 15747; case Jigsaw::Jigsaw(Jigsaw::Orientation::EastUp).ID: return 15748; case Jigsaw::Jigsaw(Jigsaw::Orientation::NorthUp).ID: return 15749; case Jigsaw::Jigsaw(Jigsaw::Orientation::SouthUp).ID: return 15750; case Jukebox::Jukebox(true).ID: return 3964; case Jukebox::Jukebox(false).ID: return 3965; case JungleButton::JungleButton(JungleButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, true).ID: return 6418; case JungleButton::JungleButton(JungleButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, false).ID: return 6419; case JungleButton::JungleButton(JungleButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, true).ID: return 6420; case JungleButton::JungleButton(JungleButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, false).ID: return 6421; case JungleButton::JungleButton(JungleButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, true).ID: return 6422; case JungleButton::JungleButton(JungleButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, false).ID: return 6423; case JungleButton::JungleButton(JungleButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, true).ID: return 6424; case JungleButton::JungleButton(JungleButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, false).ID: return 6425; case JungleButton::JungleButton(JungleButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, true).ID: return 6426; case JungleButton::JungleButton(JungleButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, false).ID: return 6427; case JungleButton::JungleButton(JungleButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, true).ID: return 6428; case JungleButton::JungleButton(JungleButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, false).ID: return 6429; case JungleButton::JungleButton(JungleButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, true).ID: return 6430; case JungleButton::JungleButton(JungleButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, false).ID: return 6431; case JungleButton::JungleButton(JungleButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, true).ID: return 6432; case JungleButton::JungleButton(JungleButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, false).ID: return 6433; case JungleButton::JungleButton(JungleButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, true).ID: return 6434; case JungleButton::JungleButton(JungleButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, false).ID: return 6435; case JungleButton::JungleButton(JungleButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, true).ID: return 6436; case JungleButton::JungleButton(JungleButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, false).ID: return 6437; case JungleButton::JungleButton(JungleButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, true).ID: return 6438; case JungleButton::JungleButton(JungleButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, false).ID: return 6439; case JungleButton::JungleButton(JungleButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, true).ID: return 6440; case JungleButton::JungleButton(JungleButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, false).ID: return 6441; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, true, true).ID: return 8866; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, true, false).ID: return 8867; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, false, true).ID: return 8868; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, false, false).ID: return 8869; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, true, true).ID: return 8870; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, true, false).ID: return 8871; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, false, true).ID: return 8872; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, false, false).ID: return 8873; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, true, true).ID: return 8874; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, true, false).ID: return 8875; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, false, true).ID: return 8876; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, false, false).ID: return 8877; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, true, true).ID: return 8878; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, true, false).ID: return 8879; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, false, true).ID: return 8880; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, false, false).ID: return 8881; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, true, true).ID: return 8882; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, true, false).ID: return 8883; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, false, true).ID: return 8884; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, false, false).ID: return 8885; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, true, true).ID: return 8886; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, true, false).ID: return 8887; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, false, true).ID: return 8888; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, false, false).ID: return 8889; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, true, true).ID: return 8890; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, true, false).ID: return 8891; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, false, true).ID: return 8892; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, false, false).ID: return 8893; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, true, true).ID: return 8894; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, true, false).ID: return 8895; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, false, true).ID: return 8896; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, false, false).ID: return 8897; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, true, true).ID: return 8898; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, true, false).ID: return 8899; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, false, true).ID: return 8900; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, false, false).ID: return 8901; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, true, true).ID: return 8902; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, true, false).ID: return 8903; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, false, true).ID: return 8904; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, false, false).ID: return 8905; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, true, true).ID: return 8906; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, true, false).ID: return 8907; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, false, true).ID: return 8908; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, false, false).ID: return 8909; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, true, true).ID: return 8910; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, true, false).ID: return 8911; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, false, true).ID: return 8912; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, false, false).ID: return 8913; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, true, true).ID: return 8914; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, true, false).ID: return 8915; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, false, true).ID: return 8916; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, false, false).ID: return 8917; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, true, true).ID: return 8918; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, true, false).ID: return 8919; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, false, true).ID: return 8920; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, false, false).ID: return 8921; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, true, true).ID: return 8922; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, true, false).ID: return 8923; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, false, true).ID: return 8924; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Lower, JungleDoor::Hinge::Left, false, false).ID: return 8925; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, true, true).ID: return 8926; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, true, false).ID: return 8927; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, false, true).ID: return 8928; case JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, false, false).ID: return 8929; case JungleFence::JungleFence(true, true, true, true).ID: return 8644; case JungleFence::JungleFence(true, true, true, false).ID: return 8645; case JungleFence::JungleFence(true, true, false, true).ID: return 8648; case JungleFence::JungleFence(true, true, false, false).ID: return 8649; case JungleFence::JungleFence(true, false, true, true).ID: return 8652; case JungleFence::JungleFence(true, false, true, false).ID: return 8653; case JungleFence::JungleFence(true, false, false, true).ID: return 8656; case JungleFence::JungleFence(true, false, false, false).ID: return 8657; case JungleFence::JungleFence(false, true, true, true).ID: return 8660; case JungleFence::JungleFence(false, true, true, false).ID: return 8661; case JungleFence::JungleFence(false, true, false, true).ID: return 8664; case JungleFence::JungleFence(false, true, false, false).ID: return 8665; case JungleFence::JungleFence(false, false, true, true).ID: return 8668; case JungleFence::JungleFence(false, false, true, false).ID: return 8669; case JungleFence::JungleFence(false, false, false, true).ID: return 8672; case JungleFence::JungleFence(false, false, false, false).ID: return 8673; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZM, true, true, true).ID: return 8482; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZM, true, true, false).ID: return 8483; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZM, true, false, true).ID: return 8484; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZM, true, false, false).ID: return 8485; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, true).ID: return 8486; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, false).ID: return 8487; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, true).ID: return 8488; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, false).ID: return 8489; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZP, true, true, true).ID: return 8490; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZP, true, true, false).ID: return 8491; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZP, true, false, true).ID: return 8492; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZP, true, false, false).ID: return 8493; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, true).ID: return 8494; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, false).ID: return 8495; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, true).ID: return 8496; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, false).ID: return 8497; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XM, true, true, true).ID: return 8498; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XM, true, true, false).ID: return 8499; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XM, true, false, true).ID: return 8500; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XM, true, false, false).ID: return 8501; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, true).ID: return 8502; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, false).ID: return 8503; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, true).ID: return 8504; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, false).ID: return 8505; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XP, true, true, true).ID: return 8506; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XP, true, true, false).ID: return 8507; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XP, true, false, true).ID: return 8508; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XP, true, false, false).ID: return 8509; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, true).ID: return 8510; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, false).ID: return 8511; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, true).ID: return 8512; case JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, false).ID: return 8513; case JungleLeaves::JungleLeaves(1, true).ID: return 187; case JungleLeaves::JungleLeaves(1, false).ID: return 188; case JungleLeaves::JungleLeaves(2, true).ID: return 189; case JungleLeaves::JungleLeaves(2, false).ID: return 190; case JungleLeaves::JungleLeaves(3, true).ID: return 191; case JungleLeaves::JungleLeaves(3, false).ID: return 192; case JungleLeaves::JungleLeaves(4, true).ID: return 193; case JungleLeaves::JungleLeaves(4, false).ID: return 194; case JungleLeaves::JungleLeaves(5, true).ID: return 195; case JungleLeaves::JungleLeaves(5, false).ID: return 196; case JungleLeaves::JungleLeaves(6, true).ID: return 197; case JungleLeaves::JungleLeaves(6, false).ID: return 198; case JungleLeaves::JungleLeaves(7, true).ID: return 199; case JungleLeaves::JungleLeaves(7, false).ID: return 200; case JungleLog::JungleLog(JungleLog::Axis::X).ID: return 82; case JungleLog::JungleLog(JungleLog::Axis::Y).ID: return 83; case JungleLog::JungleLog(JungleLog::Axis::Z).ID: return 84; case JunglePlanks::JunglePlanks().ID: return 18; case JunglePressurePlate::JunglePressurePlate(true).ID: return 3879; case JunglePressurePlate::JunglePressurePlate(false).ID: return 3880; case JungleSapling::JungleSapling(0).ID: return 27; case JungleSapling::JungleSapling(1).ID: return 28; case JungleSign::JungleSign(0).ID: return 3510; case JungleSign::JungleSign(1).ID: return 3512; case JungleSign::JungleSign(2).ID: return 3514; case JungleSign::JungleSign(3).ID: return 3516; case JungleSign::JungleSign(4).ID: return 3518; case JungleSign::JungleSign(5).ID: return 3520; case JungleSign::JungleSign(6).ID: return 3522; case JungleSign::JungleSign(7).ID: return 3524; case JungleSign::JungleSign(8).ID: return 3526; case JungleSign::JungleSign(9).ID: return 3528; case JungleSign::JungleSign(10).ID: return 3530; case JungleSign::JungleSign(11).ID: return 3532; case JungleSign::JungleSign(12).ID: return 3534; case JungleSign::JungleSign(13).ID: return 3536; case JungleSign::JungleSign(14).ID: return 3538; case JungleSign::JungleSign(15).ID: return 3540; case JungleSlab::JungleSlab(JungleSlab::Type::Top).ID: return 8319; case JungleSlab::JungleSlab(JungleSlab::Type::Bottom).ID: return 8321; case JungleSlab::JungleSlab(JungleSlab::Type::Double).ID: return 8323; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZM, JungleStairs::Half::Top, JungleStairs::Shape::Straight).ID: return 5565; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZM, JungleStairs::Half::Top, JungleStairs::Shape::InnerLeft).ID: return 5567; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZM, JungleStairs::Half::Top, JungleStairs::Shape::InnerRight).ID: return 5569; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZM, JungleStairs::Half::Top, JungleStairs::Shape::OuterLeft).ID: return 5571; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZM, JungleStairs::Half::Top, JungleStairs::Shape::OuterRight).ID: return 5573; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZM, JungleStairs::Half::Bottom, JungleStairs::Shape::Straight).ID: return 5575; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZM, JungleStairs::Half::Bottom, JungleStairs::Shape::InnerLeft).ID: return 5577; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZM, JungleStairs::Half::Bottom, JungleStairs::Shape::InnerRight).ID: return 5579; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZM, JungleStairs::Half::Bottom, JungleStairs::Shape::OuterLeft).ID: return 5581; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZM, JungleStairs::Half::Bottom, JungleStairs::Shape::OuterRight).ID: return 5583; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZP, JungleStairs::Half::Top, JungleStairs::Shape::Straight).ID: return 5585; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZP, JungleStairs::Half::Top, JungleStairs::Shape::InnerLeft).ID: return 5587; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZP, JungleStairs::Half::Top, JungleStairs::Shape::InnerRight).ID: return 5589; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZP, JungleStairs::Half::Top, JungleStairs::Shape::OuterLeft).ID: return 5591; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZP, JungleStairs::Half::Top, JungleStairs::Shape::OuterRight).ID: return 5593; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZP, JungleStairs::Half::Bottom, JungleStairs::Shape::Straight).ID: return 5595; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZP, JungleStairs::Half::Bottom, JungleStairs::Shape::InnerLeft).ID: return 5597; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZP, JungleStairs::Half::Bottom, JungleStairs::Shape::InnerRight).ID: return 5599; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZP, JungleStairs::Half::Bottom, JungleStairs::Shape::OuterLeft).ID: return 5601; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZP, JungleStairs::Half::Bottom, JungleStairs::Shape::OuterRight).ID: return 5603; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XM, JungleStairs::Half::Top, JungleStairs::Shape::Straight).ID: return 5605; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XM, JungleStairs::Half::Top, JungleStairs::Shape::InnerLeft).ID: return 5607; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XM, JungleStairs::Half::Top, JungleStairs::Shape::InnerRight).ID: return 5609; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XM, JungleStairs::Half::Top, JungleStairs::Shape::OuterLeft).ID: return 5611; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XM, JungleStairs::Half::Top, JungleStairs::Shape::OuterRight).ID: return 5613; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XM, JungleStairs::Half::Bottom, JungleStairs::Shape::Straight).ID: return 5615; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XM, JungleStairs::Half::Bottom, JungleStairs::Shape::InnerLeft).ID: return 5617; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XM, JungleStairs::Half::Bottom, JungleStairs::Shape::InnerRight).ID: return 5619; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XM, JungleStairs::Half::Bottom, JungleStairs::Shape::OuterLeft).ID: return 5621; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XM, JungleStairs::Half::Bottom, JungleStairs::Shape::OuterRight).ID: return 5623; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XP, JungleStairs::Half::Top, JungleStairs::Shape::Straight).ID: return 5625; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XP, JungleStairs::Half::Top, JungleStairs::Shape::InnerLeft).ID: return 5627; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XP, JungleStairs::Half::Top, JungleStairs::Shape::InnerRight).ID: return 5629; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XP, JungleStairs::Half::Top, JungleStairs::Shape::OuterLeft).ID: return 5631; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XP, JungleStairs::Half::Top, JungleStairs::Shape::OuterRight).ID: return 5633; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XP, JungleStairs::Half::Bottom, JungleStairs::Shape::Straight).ID: return 5635; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XP, JungleStairs::Half::Bottom, JungleStairs::Shape::InnerLeft).ID: return 5637; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XP, JungleStairs::Half::Bottom, JungleStairs::Shape::InnerRight).ID: return 5639; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XP, JungleStairs::Half::Bottom, JungleStairs::Shape::OuterLeft).ID: return 5641; case JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XP, JungleStairs::Half::Bottom, JungleStairs::Shape::OuterRight).ID: return 5643; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZM, JungleTrapdoor::Half::Top, true, true).ID: return 4304; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZM, JungleTrapdoor::Half::Top, true, false).ID: return 4306; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZM, JungleTrapdoor::Half::Top, false, true).ID: return 4308; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZM, JungleTrapdoor::Half::Top, false, false).ID: return 4310; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZM, JungleTrapdoor::Half::Bottom, true, true).ID: return 4312; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZM, JungleTrapdoor::Half::Bottom, true, false).ID: return 4314; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZM, JungleTrapdoor::Half::Bottom, false, true).ID: return 4316; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZM, JungleTrapdoor::Half::Bottom, false, false).ID: return 4318; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZP, JungleTrapdoor::Half::Top, true, true).ID: return 4320; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZP, JungleTrapdoor::Half::Top, true, false).ID: return 4322; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZP, JungleTrapdoor::Half::Top, false, true).ID: return 4324; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZP, JungleTrapdoor::Half::Top, false, false).ID: return 4326; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZP, JungleTrapdoor::Half::Bottom, true, true).ID: return 4328; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZP, JungleTrapdoor::Half::Bottom, true, false).ID: return 4330; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZP, JungleTrapdoor::Half::Bottom, false, true).ID: return 4332; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_ZP, JungleTrapdoor::Half::Bottom, false, false).ID: return 4334; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XM, JungleTrapdoor::Half::Top, true, true).ID: return 4336; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XM, JungleTrapdoor::Half::Top, true, false).ID: return 4338; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XM, JungleTrapdoor::Half::Top, false, true).ID: return 4340; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XM, JungleTrapdoor::Half::Top, false, false).ID: return 4342; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XM, JungleTrapdoor::Half::Bottom, true, true).ID: return 4344; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XM, JungleTrapdoor::Half::Bottom, true, false).ID: return 4346; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XM, JungleTrapdoor::Half::Bottom, false, true).ID: return 4348; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XM, JungleTrapdoor::Half::Bottom, false, false).ID: return 4350; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XP, JungleTrapdoor::Half::Top, true, true).ID: return 4352; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XP, JungleTrapdoor::Half::Top, true, false).ID: return 4354; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XP, JungleTrapdoor::Half::Top, false, true).ID: return 4356; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XP, JungleTrapdoor::Half::Top, false, false).ID: return 4358; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XP, JungleTrapdoor::Half::Bottom, true, true).ID: return 4360; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XP, JungleTrapdoor::Half::Bottom, true, false).ID: return 4362; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XP, JungleTrapdoor::Half::Bottom, false, true).ID: return 4364; case JungleTrapdoor::JungleTrapdoor(eBlockFace::BLOCK_FACE_XP, JungleTrapdoor::Half::Bottom, false, false).ID: return 4366; case JungleWallSign::JungleWallSign(eBlockFace::BLOCK_FACE_ZM).ID: return 3768; case JungleWallSign::JungleWallSign(eBlockFace::BLOCK_FACE_ZP).ID: return 3770; case JungleWallSign::JungleWallSign(eBlockFace::BLOCK_FACE_XM).ID: return 3772; case JungleWallSign::JungleWallSign(eBlockFace::BLOCK_FACE_XP).ID: return 3774; case JungleWood::JungleWood(JungleWood::Axis::X).ID: return 118; case JungleWood::JungleWood(JungleWood::Axis::Y).ID: return 119; case JungleWood::JungleWood(JungleWood::Axis::Z).ID: return 120; case Kelp::Kelp(0).ID: return 9470; case Kelp::Kelp(1).ID: return 9471; case Kelp::Kelp(2).ID: return 9472; case Kelp::Kelp(3).ID: return 9473; case Kelp::Kelp(4).ID: return 9474; case Kelp::Kelp(5).ID: return 9475; case Kelp::Kelp(6).ID: return 9476; case Kelp::Kelp(7).ID: return 9477; case Kelp::Kelp(8).ID: return 9478; case Kelp::Kelp(9).ID: return 9479; case Kelp::Kelp(10).ID: return 9480; case Kelp::Kelp(11).ID: return 9481; case Kelp::Kelp(12).ID: return 9482; case Kelp::Kelp(13).ID: return 9483; case Kelp::Kelp(14).ID: return 9484; case Kelp::Kelp(15).ID: return 9485; case Kelp::Kelp(16).ID: return 9486; case Kelp::Kelp(17).ID: return 9487; case Kelp::Kelp(18).ID: return 9488; case Kelp::Kelp(19).ID: return 9489; case Kelp::Kelp(20).ID: return 9490; case Kelp::Kelp(21).ID: return 9491; case Kelp::Kelp(22).ID: return 9492; case Kelp::Kelp(23).ID: return 9493; case Kelp::Kelp(24).ID: return 9494; case Kelp::Kelp(25).ID: return 9495; case KelpPlant::KelpPlant().ID: return 9496; case Ladder::Ladder(eBlockFace::BLOCK_FACE_ZM).ID: return 3638; case Ladder::Ladder(eBlockFace::BLOCK_FACE_ZP).ID: return 3640; case Ladder::Ladder(eBlockFace::BLOCK_FACE_XM).ID: return 3642; case Ladder::Ladder(eBlockFace::BLOCK_FACE_XP).ID: return 3644; case Lantern::Lantern(true).ID: return 14886; case Lantern::Lantern(false).ID: return 14887; case LapisBlock::LapisBlock().ID: return 233; case LapisOre::LapisOre().ID: return 232; case LargeFern::LargeFern(LargeFern::Half::Upper).ID: return 7895; case LargeFern::LargeFern(LargeFern::Half::Lower).ID: return 7896; case Lava::Lava(0).ID: return 50; case Lava::Lava(1).ID: return 51; case Lava::Lava(2).ID: return 52; case Lava::Lava(3).ID: return 53; case Lava::Lava(4).ID: return 54; case Lava::Lava(5).ID: return 55; case Lava::Lava(6).ID: return 56; case Lava::Lava(7).ID: return 57; case Lava::Lava(8).ID: return 58; case Lava::Lava(9).ID: return 59; case Lava::Lava(10).ID: return 60; case Lava::Lava(11).ID: return 61; case Lava::Lava(12).ID: return 62; case Lava::Lava(13).ID: return 63; case Lava::Lava(14).ID: return 64; case Lava::Lava(15).ID: return 65; case Lectern::Lectern(eBlockFace::BLOCK_FACE_ZM, true, true).ID: return 14833; case Lectern::Lectern(eBlockFace::BLOCK_FACE_ZM, true, false).ID: return 14834; case Lectern::Lectern(eBlockFace::BLOCK_FACE_ZM, false, true).ID: return 14835; case Lectern::Lectern(eBlockFace::BLOCK_FACE_ZM, false, false).ID: return 14836; case Lectern::Lectern(eBlockFace::BLOCK_FACE_ZP, true, true).ID: return 14837; case Lectern::Lectern(eBlockFace::BLOCK_FACE_ZP, true, false).ID: return 14838; case Lectern::Lectern(eBlockFace::BLOCK_FACE_ZP, false, true).ID: return 14839; case Lectern::Lectern(eBlockFace::BLOCK_FACE_ZP, false, false).ID: return 14840; case Lectern::Lectern(eBlockFace::BLOCK_FACE_XM, true, true).ID: return 14841; case Lectern::Lectern(eBlockFace::BLOCK_FACE_XM, true, false).ID: return 14842; case Lectern::Lectern(eBlockFace::BLOCK_FACE_XM, false, true).ID: return 14843; case Lectern::Lectern(eBlockFace::BLOCK_FACE_XM, false, false).ID: return 14844; case Lectern::Lectern(eBlockFace::BLOCK_FACE_XP, true, true).ID: return 14845; case Lectern::Lectern(eBlockFace::BLOCK_FACE_XP, true, false).ID: return 14846; case Lectern::Lectern(eBlockFace::BLOCK_FACE_XP, false, true).ID: return 14847; case Lectern::Lectern(eBlockFace::BLOCK_FACE_XP, false, false).ID: return 14848; case Lever::Lever(Lever::Face::Floor, eBlockFace::BLOCK_FACE_ZM, true).ID: return 3783; case Lever::Lever(Lever::Face::Floor, eBlockFace::BLOCK_FACE_ZM, false).ID: return 3784; case Lever::Lever(Lever::Face::Floor, eBlockFace::BLOCK_FACE_ZP, true).ID: return 3785; case Lever::Lever(Lever::Face::Floor, eBlockFace::BLOCK_FACE_ZP, false).ID: return 3786; case Lever::Lever(Lever::Face::Floor, eBlockFace::BLOCK_FACE_XM, true).ID: return 3787; case Lever::Lever(Lever::Face::Floor, eBlockFace::BLOCK_FACE_XM, false).ID: return 3788; case Lever::Lever(Lever::Face::Floor, eBlockFace::BLOCK_FACE_XP, true).ID: return 3789; case Lever::Lever(Lever::Face::Floor, eBlockFace::BLOCK_FACE_XP, false).ID: return 3790; case Lever::Lever(Lever::Face::Wall, eBlockFace::BLOCK_FACE_ZM, true).ID: return 3791; case Lever::Lever(Lever::Face::Wall, eBlockFace::BLOCK_FACE_ZM, false).ID: return 3792; case Lever::Lever(Lever::Face::Wall, eBlockFace::BLOCK_FACE_ZP, true).ID: return 3793; case Lever::Lever(Lever::Face::Wall, eBlockFace::BLOCK_FACE_ZP, false).ID: return 3794; case Lever::Lever(Lever::Face::Wall, eBlockFace::BLOCK_FACE_XM, true).ID: return 3795; case Lever::Lever(Lever::Face::Wall, eBlockFace::BLOCK_FACE_XM, false).ID: return 3796; case Lever::Lever(Lever::Face::Wall, eBlockFace::BLOCK_FACE_XP, true).ID: return 3797; case Lever::Lever(Lever::Face::Wall, eBlockFace::BLOCK_FACE_XP, false).ID: return 3798; case Lever::Lever(Lever::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, true).ID: return 3799; case Lever::Lever(Lever::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, false).ID: return 3800; case Lever::Lever(Lever::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, true).ID: return 3801; case Lever::Lever(Lever::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, false).ID: return 3802; case Lever::Lever(Lever::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, true).ID: return 3803; case Lever::Lever(Lever::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, false).ID: return 3804; case Lever::Lever(Lever::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, true).ID: return 3805; case Lever::Lever(Lever::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, false).ID: return 3806; case LightBlueBanner::LightBlueBanner(0).ID: return 7945; case LightBlueBanner::LightBlueBanner(1).ID: return 7946; case LightBlueBanner::LightBlueBanner(2).ID: return 7947; case LightBlueBanner::LightBlueBanner(3).ID: return 7948; case LightBlueBanner::LightBlueBanner(4).ID: return 7949; case LightBlueBanner::LightBlueBanner(5).ID: return 7950; case LightBlueBanner::LightBlueBanner(6).ID: return 7951; case LightBlueBanner::LightBlueBanner(7).ID: return 7952; case LightBlueBanner::LightBlueBanner(8).ID: return 7953; case LightBlueBanner::LightBlueBanner(9).ID: return 7954; case LightBlueBanner::LightBlueBanner(10).ID: return 7955; case LightBlueBanner::LightBlueBanner(11).ID: return 7956; case LightBlueBanner::LightBlueBanner(12).ID: return 7957; case LightBlueBanner::LightBlueBanner(13).ID: return 7958; case LightBlueBanner::LightBlueBanner(14).ID: return 7959; case LightBlueBanner::LightBlueBanner(15).ID: return 7960; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_ZM, true, LightBlueBed::Part::Head).ID: return 1097; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_ZM, true, LightBlueBed::Part::Foot).ID: return 1098; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_ZM, false, LightBlueBed::Part::Head).ID: return 1099; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_ZM, false, LightBlueBed::Part::Foot).ID: return 1100; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_ZP, true, LightBlueBed::Part::Head).ID: return 1101; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_ZP, true, LightBlueBed::Part::Foot).ID: return 1102; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_ZP, false, LightBlueBed::Part::Head).ID: return 1103; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_ZP, false, LightBlueBed::Part::Foot).ID: return 1104; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_XM, true, LightBlueBed::Part::Head).ID: return 1105; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_XM, true, LightBlueBed::Part::Foot).ID: return 1106; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_XM, false, LightBlueBed::Part::Head).ID: return 1107; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_XM, false, LightBlueBed::Part::Foot).ID: return 1108; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_XP, true, LightBlueBed::Part::Head).ID: return 1109; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_XP, true, LightBlueBed::Part::Foot).ID: return 1110; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_XP, false, LightBlueBed::Part::Head).ID: return 1111; case LightBlueBed::LightBlueBed(eBlockFace::BLOCK_FACE_XP, false, LightBlueBed::Part::Foot).ID: return 1112; case LightBlueCarpet::LightBlueCarpet().ID: return 7869; case LightBlueConcrete::LightBlueConcrete().ID: return 9441; case LightBlueConcretePowder::LightBlueConcretePowder().ID: return 9457; case LightBlueGlazedTerracotta::LightBlueGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 9386; case LightBlueGlazedTerracotta::LightBlueGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 9387; case LightBlueGlazedTerracotta::LightBlueGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 9388; case LightBlueGlazedTerracotta::LightBlueGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 9389; case LightBlueShulkerBox::LightBlueShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 9296; case LightBlueShulkerBox::LightBlueShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 9297; case LightBlueShulkerBox::LightBlueShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 9298; case LightBlueShulkerBox::LightBlueShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 9299; case LightBlueShulkerBox::LightBlueShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 9300; case LightBlueShulkerBox::LightBlueShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 9301; case LightBlueStainedGlass::LightBlueStainedGlass().ID: return 4098; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(true, true, true, true).ID: return 6961; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(true, true, true, false).ID: return 6962; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(true, true, false, true).ID: return 6965; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(true, true, false, false).ID: return 6966; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(true, false, true, true).ID: return 6969; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(true, false, true, false).ID: return 6970; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(true, false, false, true).ID: return 6973; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(true, false, false, false).ID: return 6974; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(false, true, true, true).ID: return 6977; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(false, true, true, false).ID: return 6978; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(false, true, false, true).ID: return 6981; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(false, true, false, false).ID: return 6982; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(false, false, true, true).ID: return 6985; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(false, false, true, false).ID: return 6986; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(false, false, false, true).ID: return 6989; case LightBlueStainedGlassPane::LightBlueStainedGlassPane(false, false, false, false).ID: return 6990; case LightBlueTerracotta::LightBlueTerracotta().ID: return 6850; case LightBlueWallBanner::LightBlueWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 8165; case LightBlueWallBanner::LightBlueWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 8166; case LightBlueWallBanner::LightBlueWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 8167; case LightBlueWallBanner::LightBlueWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 8168; case LightBlueWool::LightBlueWool().ID: return 1387; case LightGrayBanner::LightGrayBanner(0).ID: return 8025; case LightGrayBanner::LightGrayBanner(1).ID: return 8026; case LightGrayBanner::LightGrayBanner(2).ID: return 8027; case LightGrayBanner::LightGrayBanner(3).ID: return 8028; case LightGrayBanner::LightGrayBanner(4).ID: return 8029; case LightGrayBanner::LightGrayBanner(5).ID: return 8030; case LightGrayBanner::LightGrayBanner(6).ID: return 8031; case LightGrayBanner::LightGrayBanner(7).ID: return 8032; case LightGrayBanner::LightGrayBanner(8).ID: return 8033; case LightGrayBanner::LightGrayBanner(9).ID: return 8034; case LightGrayBanner::LightGrayBanner(10).ID: return 8035; case LightGrayBanner::LightGrayBanner(11).ID: return 8036; case LightGrayBanner::LightGrayBanner(12).ID: return 8037; case LightGrayBanner::LightGrayBanner(13).ID: return 8038; case LightGrayBanner::LightGrayBanner(14).ID: return 8039; case LightGrayBanner::LightGrayBanner(15).ID: return 8040; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_ZM, true, LightGrayBed::Part::Head).ID: return 1177; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_ZM, true, LightGrayBed::Part::Foot).ID: return 1178; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_ZM, false, LightGrayBed::Part::Head).ID: return 1179; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_ZM, false, LightGrayBed::Part::Foot).ID: return 1180; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_ZP, true, LightGrayBed::Part::Head).ID: return 1181; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_ZP, true, LightGrayBed::Part::Foot).ID: return 1182; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_ZP, false, LightGrayBed::Part::Head).ID: return 1183; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_ZP, false, LightGrayBed::Part::Foot).ID: return 1184; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_XM, true, LightGrayBed::Part::Head).ID: return 1185; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_XM, true, LightGrayBed::Part::Foot).ID: return 1186; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_XM, false, LightGrayBed::Part::Head).ID: return 1187; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_XM, false, LightGrayBed::Part::Foot).ID: return 1188; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_XP, true, LightGrayBed::Part::Head).ID: return 1189; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_XP, true, LightGrayBed::Part::Foot).ID: return 1190; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_XP, false, LightGrayBed::Part::Head).ID: return 1191; case LightGrayBed::LightGrayBed(eBlockFace::BLOCK_FACE_XP, false, LightGrayBed::Part::Foot).ID: return 1192; case LightGrayCarpet::LightGrayCarpet().ID: return 7874; case LightGrayConcrete::LightGrayConcrete().ID: return 9446; case LightGrayConcretePowder::LightGrayConcretePowder().ID: return 9462; case LightGrayGlazedTerracotta::LightGrayGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 9406; case LightGrayGlazedTerracotta::LightGrayGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 9407; case LightGrayGlazedTerracotta::LightGrayGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 9408; case LightGrayGlazedTerracotta::LightGrayGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 9409; case LightGrayShulkerBox::LightGrayShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 9326; case LightGrayShulkerBox::LightGrayShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 9327; case LightGrayShulkerBox::LightGrayShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 9328; case LightGrayShulkerBox::LightGrayShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 9329; case LightGrayShulkerBox::LightGrayShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 9330; case LightGrayShulkerBox::LightGrayShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 9331; case LightGrayStainedGlass::LightGrayStainedGlass().ID: return 4103; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(true, true, true, true).ID: return 7121; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(true, true, true, false).ID: return 7122; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(true, true, false, true).ID: return 7125; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(true, true, false, false).ID: return 7126; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(true, false, true, true).ID: return 7129; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(true, false, true, false).ID: return 7130; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(true, false, false, true).ID: return 7133; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(true, false, false, false).ID: return 7134; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(false, true, true, true).ID: return 7137; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(false, true, true, false).ID: return 7138; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(false, true, false, true).ID: return 7141; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(false, true, false, false).ID: return 7142; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(false, false, true, true).ID: return 7145; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(false, false, true, false).ID: return 7146; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(false, false, false, true).ID: return 7149; case LightGrayStainedGlassPane::LightGrayStainedGlassPane(false, false, false, false).ID: return 7150; case LightGrayTerracotta::LightGrayTerracotta().ID: return 6855; case LightGrayWallBanner::LightGrayWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 8185; case LightGrayWallBanner::LightGrayWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 8186; case LightGrayWallBanner::LightGrayWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 8187; case LightGrayWallBanner::LightGrayWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 8188; case LightGrayWool::LightGrayWool().ID: return 1392; case LightWeightedPressurePlate::LightWeightedPressurePlate(0).ID: return 6646; case LightWeightedPressurePlate::LightWeightedPressurePlate(1).ID: return 6647; case LightWeightedPressurePlate::LightWeightedPressurePlate(2).ID: return 6648; case LightWeightedPressurePlate::LightWeightedPressurePlate(3).ID: return 6649; case LightWeightedPressurePlate::LightWeightedPressurePlate(4).ID: return 6650; case LightWeightedPressurePlate::LightWeightedPressurePlate(5).ID: return 6651; case LightWeightedPressurePlate::LightWeightedPressurePlate(6).ID: return 6652; case LightWeightedPressurePlate::LightWeightedPressurePlate(7).ID: return 6653; case LightWeightedPressurePlate::LightWeightedPressurePlate(8).ID: return 6654; case LightWeightedPressurePlate::LightWeightedPressurePlate(9).ID: return 6655; case LightWeightedPressurePlate::LightWeightedPressurePlate(10).ID: return 6656; case LightWeightedPressurePlate::LightWeightedPressurePlate(11).ID: return 6657; case LightWeightedPressurePlate::LightWeightedPressurePlate(12).ID: return 6658; case LightWeightedPressurePlate::LightWeightedPressurePlate(13).ID: return 6659; case LightWeightedPressurePlate::LightWeightedPressurePlate(14).ID: return 6660; case LightWeightedPressurePlate::LightWeightedPressurePlate(15).ID: return 6661; case Lilac::Lilac(Lilac::Half::Upper).ID: return 7887; case Lilac::Lilac(Lilac::Half::Lower).ID: return 7888; case LilyOfTheValley::LilyOfTheValley().ID: return 1424; case LilyPad::LilyPad().ID: return 5014; case LimeBanner::LimeBanner(0).ID: return 7977; case LimeBanner::LimeBanner(1).ID: return 7978; case LimeBanner::LimeBanner(2).ID: return 7979; case LimeBanner::LimeBanner(3).ID: return 7980; case LimeBanner::LimeBanner(4).ID: return 7981; case LimeBanner::LimeBanner(5).ID: return 7982; case LimeBanner::LimeBanner(6).ID: return 7983; case LimeBanner::LimeBanner(7).ID: return 7984; case LimeBanner::LimeBanner(8).ID: return 7985; case LimeBanner::LimeBanner(9).ID: return 7986; case LimeBanner::LimeBanner(10).ID: return 7987; case LimeBanner::LimeBanner(11).ID: return 7988; case LimeBanner::LimeBanner(12).ID: return 7989; case LimeBanner::LimeBanner(13).ID: return 7990; case LimeBanner::LimeBanner(14).ID: return 7991; case LimeBanner::LimeBanner(15).ID: return 7992; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_ZM, true, LimeBed::Part::Head).ID: return 1129; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_ZM, true, LimeBed::Part::Foot).ID: return 1130; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_ZM, false, LimeBed::Part::Head).ID: return 1131; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_ZM, false, LimeBed::Part::Foot).ID: return 1132; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_ZP, true, LimeBed::Part::Head).ID: return 1133; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_ZP, true, LimeBed::Part::Foot).ID: return 1134; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_ZP, false, LimeBed::Part::Head).ID: return 1135; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_ZP, false, LimeBed::Part::Foot).ID: return 1136; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_XM, true, LimeBed::Part::Head).ID: return 1137; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_XM, true, LimeBed::Part::Foot).ID: return 1138; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_XM, false, LimeBed::Part::Head).ID: return 1139; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_XM, false, LimeBed::Part::Foot).ID: return 1140; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_XP, true, LimeBed::Part::Head).ID: return 1141; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_XP, true, LimeBed::Part::Foot).ID: return 1142; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_XP, false, LimeBed::Part::Head).ID: return 1143; case LimeBed::LimeBed(eBlockFace::BLOCK_FACE_XP, false, LimeBed::Part::Foot).ID: return 1144; case LimeCarpet::LimeCarpet().ID: return 7871; case LimeConcrete::LimeConcrete().ID: return 9443; case LimeConcretePowder::LimeConcretePowder().ID: return 9459; case LimeGlazedTerracotta::LimeGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 9394; case LimeGlazedTerracotta::LimeGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 9395; case LimeGlazedTerracotta::LimeGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 9396; case LimeGlazedTerracotta::LimeGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 9397; case LimeShulkerBox::LimeShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 9308; case LimeShulkerBox::LimeShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 9309; case LimeShulkerBox::LimeShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 9310; case LimeShulkerBox::LimeShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 9311; case LimeShulkerBox::LimeShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 9312; case LimeShulkerBox::LimeShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 9313; case LimeStainedGlass::LimeStainedGlass().ID: return 4100; case LimeStainedGlassPane::LimeStainedGlassPane(true, true, true, true).ID: return 7025; case LimeStainedGlassPane::LimeStainedGlassPane(true, true, true, false).ID: return 7026; case LimeStainedGlassPane::LimeStainedGlassPane(true, true, false, true).ID: return 7029; case LimeStainedGlassPane::LimeStainedGlassPane(true, true, false, false).ID: return 7030; case LimeStainedGlassPane::LimeStainedGlassPane(true, false, true, true).ID: return 7033; case LimeStainedGlassPane::LimeStainedGlassPane(true, false, true, false).ID: return 7034; case LimeStainedGlassPane::LimeStainedGlassPane(true, false, false, true).ID: return 7037; case LimeStainedGlassPane::LimeStainedGlassPane(true, false, false, false).ID: return 7038; case LimeStainedGlassPane::LimeStainedGlassPane(false, true, true, true).ID: return 7041; case LimeStainedGlassPane::LimeStainedGlassPane(false, true, true, false).ID: return 7042; case LimeStainedGlassPane::LimeStainedGlassPane(false, true, false, true).ID: return 7045; case LimeStainedGlassPane::LimeStainedGlassPane(false, true, false, false).ID: return 7046; case LimeStainedGlassPane::LimeStainedGlassPane(false, false, true, true).ID: return 7049; case LimeStainedGlassPane::LimeStainedGlassPane(false, false, true, false).ID: return 7050; case LimeStainedGlassPane::LimeStainedGlassPane(false, false, false, true).ID: return 7053; case LimeStainedGlassPane::LimeStainedGlassPane(false, false, false, false).ID: return 7054; case LimeTerracotta::LimeTerracotta().ID: return 6852; case LimeWallBanner::LimeWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 8173; case LimeWallBanner::LimeWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 8174; case LimeWallBanner::LimeWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 8175; case LimeWallBanner::LimeWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 8176; case LimeWool::LimeWool().ID: return 1389; case Lodestone::Lodestone().ID: return 15838; case Loom::Loom(eBlockFace::BLOCK_FACE_ZM).ID: return 14787; case Loom::Loom(eBlockFace::BLOCK_FACE_ZP).ID: return 14788; case Loom::Loom(eBlockFace::BLOCK_FACE_XM).ID: return 14789; case Loom::Loom(eBlockFace::BLOCK_FACE_XP).ID: return 14790; case MagentaBanner::MagentaBanner(0).ID: return 7929; case MagentaBanner::MagentaBanner(1).ID: return 7930; case MagentaBanner::MagentaBanner(2).ID: return 7931; case MagentaBanner::MagentaBanner(3).ID: return 7932; case MagentaBanner::MagentaBanner(4).ID: return 7933; case MagentaBanner::MagentaBanner(5).ID: return 7934; case MagentaBanner::MagentaBanner(6).ID: return 7935; case MagentaBanner::MagentaBanner(7).ID: return 7936; case MagentaBanner::MagentaBanner(8).ID: return 7937; case MagentaBanner::MagentaBanner(9).ID: return 7938; case MagentaBanner::MagentaBanner(10).ID: return 7939; case MagentaBanner::MagentaBanner(11).ID: return 7940; case MagentaBanner::MagentaBanner(12).ID: return 7941; case MagentaBanner::MagentaBanner(13).ID: return 7942; case MagentaBanner::MagentaBanner(14).ID: return 7943; case MagentaBanner::MagentaBanner(15).ID: return 7944; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_ZM, true, MagentaBed::Part::Head).ID: return 1081; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_ZM, true, MagentaBed::Part::Foot).ID: return 1082; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_ZM, false, MagentaBed::Part::Head).ID: return 1083; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_ZM, false, MagentaBed::Part::Foot).ID: return 1084; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_ZP, true, MagentaBed::Part::Head).ID: return 1085; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_ZP, true, MagentaBed::Part::Foot).ID: return 1086; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_ZP, false, MagentaBed::Part::Head).ID: return 1087; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_ZP, false, MagentaBed::Part::Foot).ID: return 1088; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_XM, true, MagentaBed::Part::Head).ID: return 1089; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_XM, true, MagentaBed::Part::Foot).ID: return 1090; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_XM, false, MagentaBed::Part::Head).ID: return 1091; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_XM, false, MagentaBed::Part::Foot).ID: return 1092; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_XP, true, MagentaBed::Part::Head).ID: return 1093; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_XP, true, MagentaBed::Part::Foot).ID: return 1094; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_XP, false, MagentaBed::Part::Head).ID: return 1095; case MagentaBed::MagentaBed(eBlockFace::BLOCK_FACE_XP, false, MagentaBed::Part::Foot).ID: return 1096; case MagentaCarpet::MagentaCarpet().ID: return 7868; case MagentaConcrete::MagentaConcrete().ID: return 9440; case MagentaConcretePowder::MagentaConcretePowder().ID: return 9456; case MagentaGlazedTerracotta::MagentaGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 9382; case MagentaGlazedTerracotta::MagentaGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 9383; case MagentaGlazedTerracotta::MagentaGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 9384; case MagentaGlazedTerracotta::MagentaGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 9385; case MagentaShulkerBox::MagentaShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 9290; case MagentaShulkerBox::MagentaShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 9291; case MagentaShulkerBox::MagentaShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 9292; case MagentaShulkerBox::MagentaShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 9293; case MagentaShulkerBox::MagentaShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 9294; case MagentaShulkerBox::MagentaShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 9295; case MagentaStainedGlass::MagentaStainedGlass().ID: return 4097; case MagentaStainedGlassPane::MagentaStainedGlassPane(true, true, true, true).ID: return 6929; case MagentaStainedGlassPane::MagentaStainedGlassPane(true, true, true, false).ID: return 6930; case MagentaStainedGlassPane::MagentaStainedGlassPane(true, true, false, true).ID: return 6933; case MagentaStainedGlassPane::MagentaStainedGlassPane(true, true, false, false).ID: return 6934; case MagentaStainedGlassPane::MagentaStainedGlassPane(true, false, true, true).ID: return 6937; case MagentaStainedGlassPane::MagentaStainedGlassPane(true, false, true, false).ID: return 6938; case MagentaStainedGlassPane::MagentaStainedGlassPane(true, false, false, true).ID: return 6941; case MagentaStainedGlassPane::MagentaStainedGlassPane(true, false, false, false).ID: return 6942; case MagentaStainedGlassPane::MagentaStainedGlassPane(false, true, true, true).ID: return 6945; case MagentaStainedGlassPane::MagentaStainedGlassPane(false, true, true, false).ID: return 6946; case MagentaStainedGlassPane::MagentaStainedGlassPane(false, true, false, true).ID: return 6949; case MagentaStainedGlassPane::MagentaStainedGlassPane(false, true, false, false).ID: return 6950; case MagentaStainedGlassPane::MagentaStainedGlassPane(false, false, true, true).ID: return 6953; case MagentaStainedGlassPane::MagentaStainedGlassPane(false, false, true, false).ID: return 6954; case MagentaStainedGlassPane::MagentaStainedGlassPane(false, false, false, true).ID: return 6957; case MagentaStainedGlassPane::MagentaStainedGlassPane(false, false, false, false).ID: return 6958; case MagentaTerracotta::MagentaTerracotta().ID: return 6849; case MagentaWallBanner::MagentaWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 8161; case MagentaWallBanner::MagentaWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 8162; case MagentaWallBanner::MagentaWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 8163; case MagentaWallBanner::MagentaWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 8164; case MagentaWool::MagentaWool().ID: return 1386; case MagmaBlock::MagmaBlock().ID: return 9253; case Melon::Melon().ID: return 4763; case MelonStem::MelonStem(0).ID: return 4780; case MelonStem::MelonStem(1).ID: return 4781; case MelonStem::MelonStem(2).ID: return 4782; case MelonStem::MelonStem(3).ID: return 4783; case MelonStem::MelonStem(4).ID: return 4784; case MelonStem::MelonStem(5).ID: return 4785; case MelonStem::MelonStem(6).ID: return 4786; case MelonStem::MelonStem(7).ID: return 4787; case MossyCobblestone::MossyCobblestone().ID: return 1433; case MossyCobblestoneSlab::MossyCobblestoneSlab(MossyCobblestoneSlab::Type::Top).ID: return 10814; case MossyCobblestoneSlab::MossyCobblestoneSlab(MossyCobblestoneSlab::Type::Bottom).ID: return 10816; case MossyCobblestoneSlab::MossyCobblestoneSlab(MossyCobblestoneSlab::Type::Double).ID: return 10818; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, MossyCobblestoneStairs::Half::Top, MossyCobblestoneStairs::Shape::Straight).ID: return 9990; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, MossyCobblestoneStairs::Half::Top, MossyCobblestoneStairs::Shape::InnerLeft).ID: return 9992; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, MossyCobblestoneStairs::Half::Top, MossyCobblestoneStairs::Shape::InnerRight).ID: return 9994; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, MossyCobblestoneStairs::Half::Top, MossyCobblestoneStairs::Shape::OuterLeft).ID: return 9996; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, MossyCobblestoneStairs::Half::Top, MossyCobblestoneStairs::Shape::OuterRight).ID: return 9998; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, MossyCobblestoneStairs::Half::Bottom, MossyCobblestoneStairs::Shape::Straight).ID: return 10000; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, MossyCobblestoneStairs::Half::Bottom, MossyCobblestoneStairs::Shape::InnerLeft).ID: return 10002; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, MossyCobblestoneStairs::Half::Bottom, MossyCobblestoneStairs::Shape::InnerRight).ID: return 10004; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, MossyCobblestoneStairs::Half::Bottom, MossyCobblestoneStairs::Shape::OuterLeft).ID: return 10006; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, MossyCobblestoneStairs::Half::Bottom, MossyCobblestoneStairs::Shape::OuterRight).ID: return 10008; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, MossyCobblestoneStairs::Half::Top, MossyCobblestoneStairs::Shape::Straight).ID: return 10010; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, MossyCobblestoneStairs::Half::Top, MossyCobblestoneStairs::Shape::InnerLeft).ID: return 10012; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, MossyCobblestoneStairs::Half::Top, MossyCobblestoneStairs::Shape::InnerRight).ID: return 10014; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, MossyCobblestoneStairs::Half::Top, MossyCobblestoneStairs::Shape::OuterLeft).ID: return 10016; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, MossyCobblestoneStairs::Half::Top, MossyCobblestoneStairs::Shape::OuterRight).ID: return 10018; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, MossyCobblestoneStairs::Half::Bottom, MossyCobblestoneStairs::Shape::Straight).ID: return 10020; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, MossyCobblestoneStairs::Half::Bottom, MossyCobblestoneStairs::Shape::InnerLeft).ID: return 10022; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, MossyCobblestoneStairs::Half::Bottom, MossyCobblestoneStairs::Shape::InnerRight).ID: return 10024; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, MossyCobblestoneStairs::Half::Bottom, MossyCobblestoneStairs::Shape::OuterLeft).ID: return 10026; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, MossyCobblestoneStairs::Half::Bottom, MossyCobblestoneStairs::Shape::OuterRight).ID: return 10028; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_XM, MossyCobblestoneStairs::Half::Top, MossyCobblestoneStairs::Shape::Straight).ID: return 10030; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_XM, MossyCobblestoneStairs::Half::Top, MossyCobblestoneStairs::Shape::InnerLeft).ID: return 10032; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_XM, MossyCobblestoneStairs::Half::Top, MossyCobblestoneStairs::Shape::InnerRight).ID: return 10034; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_XM, MossyCobblestoneStairs::Half::Top, MossyCobblestoneStairs::Shape::OuterLeft).ID: return 10036; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_XM, MossyCobblestoneStairs::Half::Top, MossyCobblestoneStairs::Shape::OuterRight).ID: return 10038; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_XM, MossyCobblestoneStairs::Half::Bottom, MossyCobblestoneStairs::Shape::Straight).ID: return 10040; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_XM, MossyCobblestoneStairs::Half::Bottom, MossyCobblestoneStairs::Shape::InnerLeft).ID: return 10042; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_XM, MossyCobblestoneStairs::Half::Bottom, MossyCobblestoneStairs::Shape::InnerRight).ID: return 10044; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_XM, MossyCobblestoneStairs::Half::Bottom, MossyCobblestoneStairs::Shape::OuterLeft).ID: return 10046; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_XM, MossyCobblestoneStairs::Half::Bottom, MossyCobblestoneStairs::Shape::OuterRight).ID: return 10048; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_XP, MossyCobblestoneStairs::Half::Top, MossyCobblestoneStairs::Shape::Straight).ID: return 10050; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_XP, MossyCobblestoneStairs::Half::Top, MossyCobblestoneStairs::Shape::InnerLeft).ID: return 10052; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_XP, MossyCobblestoneStairs::Half::Top, MossyCobblestoneStairs::Shape::InnerRight).ID: return 10054; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_XP, MossyCobblestoneStairs::Half::Top, MossyCobblestoneStairs::Shape::OuterLeft).ID: return 10056; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_XP, MossyCobblestoneStairs::Half::Top, MossyCobblestoneStairs::Shape::OuterRight).ID: return 10058; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_XP, MossyCobblestoneStairs::Half::Bottom, MossyCobblestoneStairs::Shape::Straight).ID: return 10060; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_XP, MossyCobblestoneStairs::Half::Bottom, MossyCobblestoneStairs::Shape::InnerLeft).ID: return 10062; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_XP, MossyCobblestoneStairs::Half::Bottom, MossyCobblestoneStairs::Shape::InnerRight).ID: return 10064; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_XP, MossyCobblestoneStairs::Half::Bottom, MossyCobblestoneStairs::Shape::OuterLeft).ID: return 10066; case MossyCobblestoneStairs::MossyCobblestoneStairs(eBlockFace::BLOCK_FACE_XP, MossyCobblestoneStairs::Half::Bottom, MossyCobblestoneStairs::Shape::OuterRight).ID: return 10068; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::None, true, MossyCobblestoneWall::West::None).ID: return 5984; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::None, true, MossyCobblestoneWall::West::Low).ID: return 5985; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::None, true, MossyCobblestoneWall::West::Tall).ID: return 5986; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::None, false, MossyCobblestoneWall::West::None).ID: return 5990; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::None, false, MossyCobblestoneWall::West::Low).ID: return 5991; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::None, false, MossyCobblestoneWall::West::Tall).ID: return 5992; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::Low, true, MossyCobblestoneWall::West::None).ID: return 5996; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::Low, true, MossyCobblestoneWall::West::Low).ID: return 5997; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::Low, true, MossyCobblestoneWall::West::Tall).ID: return 5998; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::Low, false, MossyCobblestoneWall::West::None).ID: return 6002; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::Low, false, MossyCobblestoneWall::West::Low).ID: return 6003; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::Low, false, MossyCobblestoneWall::West::Tall).ID: return 6004; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::Tall, true, MossyCobblestoneWall::West::None).ID: return 6008; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::Tall, true, MossyCobblestoneWall::West::Low).ID: return 6009; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::Tall, true, MossyCobblestoneWall::West::Tall).ID: return 6010; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::Tall, false, MossyCobblestoneWall::West::None).ID: return 6014; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::Tall, false, MossyCobblestoneWall::West::Low).ID: return 6015; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::Tall, false, MossyCobblestoneWall::West::Tall).ID: return 6016; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::None, true, MossyCobblestoneWall::West::None).ID: return 6020; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::None, true, MossyCobblestoneWall::West::Low).ID: return 6021; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::None, true, MossyCobblestoneWall::West::Tall).ID: return 6022; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::None, false, MossyCobblestoneWall::West::None).ID: return 6026; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::None, false, MossyCobblestoneWall::West::Low).ID: return 6027; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::None, false, MossyCobblestoneWall::West::Tall).ID: return 6028; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::Low, true, MossyCobblestoneWall::West::None).ID: return 6032; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::Low, true, MossyCobblestoneWall::West::Low).ID: return 6033; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::Low, true, MossyCobblestoneWall::West::Tall).ID: return 6034; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::Low, false, MossyCobblestoneWall::West::None).ID: return 6038; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::Low, false, MossyCobblestoneWall::West::Low).ID: return 6039; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::Low, false, MossyCobblestoneWall::West::Tall).ID: return 6040; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::Tall, true, MossyCobblestoneWall::West::None).ID: return 6044; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::Tall, true, MossyCobblestoneWall::West::Low).ID: return 6045; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::Tall, true, MossyCobblestoneWall::West::Tall).ID: return 6046; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::Tall, false, MossyCobblestoneWall::West::None).ID: return 6050; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::Tall, false, MossyCobblestoneWall::West::Low).ID: return 6051; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::Tall, false, MossyCobblestoneWall::West::Tall).ID: return 6052; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::Tall, MossyCobblestoneWall::South::None, true, MossyCobblestoneWall::West::None).ID: return 6056; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::Tall, MossyCobblestoneWall::South::None, true, MossyCobblestoneWall::West::Low).ID: return 6057; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::Tall, MossyCobblestoneWall::South::None, true, MossyCobblestoneWall::West::Tall).ID: return 6058; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::Tall, MossyCobblestoneWall::South::None, false, MossyCobblestoneWall::West::None).ID: return 6062; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::Tall, MossyCobblestoneWall::South::None, false, MossyCobblestoneWall::West::Low).ID: return 6063; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::Tall, MossyCobblestoneWall::South::None, false, MossyCobblestoneWall::West::Tall).ID: return 6064; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::Tall, MossyCobblestoneWall::South::Low, true, MossyCobblestoneWall::West::None).ID: return 6068; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::Tall, MossyCobblestoneWall::South::Low, true, MossyCobblestoneWall::West::Low).ID: return 6069; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::Tall, MossyCobblestoneWall::South::Low, true, MossyCobblestoneWall::West::Tall).ID: return 6070; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::Tall, MossyCobblestoneWall::South::Low, false, MossyCobblestoneWall::West::None).ID: return 6074; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::Tall, MossyCobblestoneWall::South::Low, false, MossyCobblestoneWall::West::Low).ID: return 6075; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::Tall, MossyCobblestoneWall::South::Low, false, MossyCobblestoneWall::West::Tall).ID: return 6076; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::Tall, MossyCobblestoneWall::South::Tall, true, MossyCobblestoneWall::West::None).ID: return 6080; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::Tall, MossyCobblestoneWall::South::Tall, true, MossyCobblestoneWall::West::Low).ID: return 6081; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::Tall, MossyCobblestoneWall::South::Tall, true, MossyCobblestoneWall::West::Tall).ID: return 6082; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::Tall, MossyCobblestoneWall::South::Tall, false, MossyCobblestoneWall::West::None).ID: return 6086; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::Tall, MossyCobblestoneWall::South::Tall, false, MossyCobblestoneWall::West::Low).ID: return 6087; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::Tall, MossyCobblestoneWall::South::Tall, false, MossyCobblestoneWall::West::Tall).ID: return 6088; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::None, true, MossyCobblestoneWall::West::None).ID: return 6092; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::None, true, MossyCobblestoneWall::West::Low).ID: return 6093; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::None, true, MossyCobblestoneWall::West::Tall).ID: return 6094; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::None, false, MossyCobblestoneWall::West::None).ID: return 6098; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::None, false, MossyCobblestoneWall::West::Low).ID: return 6099; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::None, false, MossyCobblestoneWall::West::Tall).ID: return 6100; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::Low, true, MossyCobblestoneWall::West::None).ID: return 6104; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::Low, true, MossyCobblestoneWall::West::Low).ID: return 6105; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::Low, true, MossyCobblestoneWall::West::Tall).ID: return 6106; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::Low, false, MossyCobblestoneWall::West::None).ID: return 6110; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::Low, false, MossyCobblestoneWall::West::Low).ID: return 6111; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::Low, false, MossyCobblestoneWall::West::Tall).ID: return 6112; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::Tall, true, MossyCobblestoneWall::West::None).ID: return 6116; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::Tall, true, MossyCobblestoneWall::West::Low).ID: return 6117; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::Tall, true, MossyCobblestoneWall::West::Tall).ID: return 6118; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::Tall, false, MossyCobblestoneWall::West::None).ID: return 6122; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::Tall, false, MossyCobblestoneWall::West::Low).ID: return 6123; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::Tall, false, MossyCobblestoneWall::West::Tall).ID: return 6124; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::None, true, MossyCobblestoneWall::West::None).ID: return 6128; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::None, true, MossyCobblestoneWall::West::Low).ID: return 6129; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::None, true, MossyCobblestoneWall::West::Tall).ID: return 6130; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::None, false, MossyCobblestoneWall::West::None).ID: return 6134; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::None, false, MossyCobblestoneWall::West::Low).ID: return 6135; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::None, false, MossyCobblestoneWall::West::Tall).ID: return 6136; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::Low, true, MossyCobblestoneWall::West::None).ID: return 6140; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::Low, true, MossyCobblestoneWall::West::Low).ID: return 6141; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::Low, true, MossyCobblestoneWall::West::Tall).ID: return 6142; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::Low, false, MossyCobblestoneWall::West::None).ID: return 6146; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::Low, false, MossyCobblestoneWall::West::Low).ID: return 6147; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::Low, false, MossyCobblestoneWall::West::Tall).ID: return 6148; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::Tall, true, MossyCobblestoneWall::West::None).ID: return 6152; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::Tall, true, MossyCobblestoneWall::West::Low).ID: return 6153; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::Tall, true, MossyCobblestoneWall::West::Tall).ID: return 6154; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::Tall, false, MossyCobblestoneWall::West::None).ID: return 6158; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::Tall, false, MossyCobblestoneWall::West::Low).ID: return 6159; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::Tall, false, MossyCobblestoneWall::West::Tall).ID: return 6160; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::Tall, MossyCobblestoneWall::South::None, true, MossyCobblestoneWall::West::None).ID: return 6164; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::Tall, MossyCobblestoneWall::South::None, true, MossyCobblestoneWall::West::Low).ID: return 6165; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::Tall, MossyCobblestoneWall::South::None, true, MossyCobblestoneWall::West::Tall).ID: return 6166; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::Tall, MossyCobblestoneWall::South::None, false, MossyCobblestoneWall::West::None).ID: return 6170; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::Tall, MossyCobblestoneWall::South::None, false, MossyCobblestoneWall::West::Low).ID: return 6171; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::Tall, MossyCobblestoneWall::South::None, false, MossyCobblestoneWall::West::Tall).ID: return 6172; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::Tall, MossyCobblestoneWall::South::Low, true, MossyCobblestoneWall::West::None).ID: return 6176; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::Tall, MossyCobblestoneWall::South::Low, true, MossyCobblestoneWall::West::Low).ID: return 6177; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::Tall, MossyCobblestoneWall::South::Low, true, MossyCobblestoneWall::West::Tall).ID: return 6178; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::Tall, MossyCobblestoneWall::South::Low, false, MossyCobblestoneWall::West::None).ID: return 6182; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::Tall, MossyCobblestoneWall::South::Low, false, MossyCobblestoneWall::West::Low).ID: return 6183; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::Tall, MossyCobblestoneWall::South::Low, false, MossyCobblestoneWall::West::Tall).ID: return 6184; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::Tall, MossyCobblestoneWall::South::Tall, true, MossyCobblestoneWall::West::None).ID: return 6188; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::Tall, MossyCobblestoneWall::South::Tall, true, MossyCobblestoneWall::West::Low).ID: return 6189; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::Tall, MossyCobblestoneWall::South::Tall, true, MossyCobblestoneWall::West::Tall).ID: return 6190; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::Tall, MossyCobblestoneWall::South::Tall, false, MossyCobblestoneWall::West::None).ID: return 6194; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::Tall, MossyCobblestoneWall::South::Tall, false, MossyCobblestoneWall::West::Low).ID: return 6195; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Low, MossyCobblestoneWall::North::Tall, MossyCobblestoneWall::South::Tall, false, MossyCobblestoneWall::West::Tall).ID: return 6196; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Tall, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::None, true, MossyCobblestoneWall::West::None).ID: return 6200; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Tall, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::None, true, MossyCobblestoneWall::West::Low).ID: return 6201; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Tall, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::None, true, MossyCobblestoneWall::West::Tall).ID: return 6202; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Tall, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::None, false, MossyCobblestoneWall::West::None).ID: return 6206; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Tall, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::None, false, MossyCobblestoneWall::West::Low).ID: return 6207; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Tall, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::None, false, MossyCobblestoneWall::West::Tall).ID: return 6208; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Tall, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::Low, true, MossyCobblestoneWall::West::None).ID: return 6212; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Tall, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::Low, true, MossyCobblestoneWall::West::Low).ID: return 6213; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Tall, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::Low, true, MossyCobblestoneWall::West::Tall).ID: return 6214; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Tall, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::Low, false, MossyCobblestoneWall::West::None).ID: return 6218; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Tall, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::Low, false, MossyCobblestoneWall::West::Low).ID: return 6219; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Tall, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::Low, false, MossyCobblestoneWall::West::Tall).ID: return 6220; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Tall, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::Tall, true, MossyCobblestoneWall::West::None).ID: return 6224; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Tall, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::Tall, true, MossyCobblestoneWall::West::Low).ID: return 6225; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Tall, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::Tall, true, MossyCobblestoneWall::West::Tall).ID: return 6226; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Tall, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::Tall, false, MossyCobblestoneWall::West::None).ID: return 6230; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Tall, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::Tall, false, MossyCobblestoneWall::West::Low).ID: return 6231; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Tall, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::Tall, false, MossyCobblestoneWall::West::Tall).ID: return 6232; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Tall, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::None, true, MossyCobblestoneWall::West::None).ID: return 6236; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Tall, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::None, true, MossyCobblestoneWall::West::Low).ID: return 6237; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Tall, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::None, true, MossyCobblestoneWall::West::Tall).ID: return 6238; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Tall, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::None, false, MossyCobblestoneWall::West::None).ID: return 6242; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Tall, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::None, false, MossyCobblestoneWall::West::Low).ID: return 6243; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Tall, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::None, false, MossyCobblestoneWall::West::Tall).ID: return 6244; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Tall, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::Low, true, MossyCobblestoneWall::West::None).ID: return 6248; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Tall, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::Low, true, MossyCobblestoneWall::West::Low).ID: return 6249; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Tall, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::Low, true, MossyCobblestoneWall::West::Tall).ID: return 6250; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Tall, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::Low, false, MossyCobblestoneWall::West::None).ID: return 6254; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Tall, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::Low, false, MossyCobblestoneWall::West::Low).ID: return 6255; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Tall, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::Low, false, MossyCobblestoneWall::West::Tall).ID: return 6256; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Tall, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::Tall, true, MossyCobblestoneWall::West::None).ID: return 6260; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Tall, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::Tall, true, MossyCobblestoneWall::West::Low).ID: return 6261; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Tall, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::Tall, true, MossyCobblestoneWall::West::Tall).ID: return 6262; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Tall, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::Tall, false, MossyCobblestoneWall::West::None).ID: return 6266; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Tall, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::Tall, false, MossyCobblestoneWall::West::Low).ID: return 6267; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Tall, MossyCobblestoneWall::North::Low, MossyCobblestoneWall::South::Tall, false, MossyCobblestoneWall::West::Tall).ID: return 6268; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Tall, MossyCobblestoneWall::North::Tall, MossyCobblestoneWall::South::None, true, MossyCobblestoneWall::West::None).ID: return 6272; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Tall, MossyCobblestoneWall::North::Tall, MossyCobblestoneWall::South::None, true, MossyCobblestoneWall::West::Low).ID: return 6273; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Tall, MossyCobblestoneWall::North::Tall, MossyCobblestoneWall::South::None, true, MossyCobblestoneWall::West::Tall).ID: return 6274; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Tall, MossyCobblestoneWall::North::Tall, MossyCobblestoneWall::South::None, false, MossyCobblestoneWall::West::None).ID: return 6278; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Tall, MossyCobblestoneWall::North::Tall, MossyCobblestoneWall::South::None, false, MossyCobblestoneWall::West::Low).ID: return 6279; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Tall, MossyCobblestoneWall::North::Tall, MossyCobblestoneWall::South::None, false, MossyCobblestoneWall::West::Tall).ID: return 6280; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Tall, MossyCobblestoneWall::North::Tall, MossyCobblestoneWall::South::Low, true, MossyCobblestoneWall::West::None).ID: return 6284; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Tall, MossyCobblestoneWall::North::Tall, MossyCobblestoneWall::South::Low, true, MossyCobblestoneWall::West::Low).ID: return 6285; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Tall, MossyCobblestoneWall::North::Tall, MossyCobblestoneWall::South::Low, true, MossyCobblestoneWall::West::Tall).ID: return 6286; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Tall, MossyCobblestoneWall::North::Tall, MossyCobblestoneWall::South::Low, false, MossyCobblestoneWall::West::None).ID: return 6290; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Tall, MossyCobblestoneWall::North::Tall, MossyCobblestoneWall::South::Low, false, MossyCobblestoneWall::West::Low).ID: return 6291; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Tall, MossyCobblestoneWall::North::Tall, MossyCobblestoneWall::South::Low, false, MossyCobblestoneWall::West::Tall).ID: return 6292; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Tall, MossyCobblestoneWall::North::Tall, MossyCobblestoneWall::South::Tall, true, MossyCobblestoneWall::West::None).ID: return 6296; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Tall, MossyCobblestoneWall::North::Tall, MossyCobblestoneWall::South::Tall, true, MossyCobblestoneWall::West::Low).ID: return 6297; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Tall, MossyCobblestoneWall::North::Tall, MossyCobblestoneWall::South::Tall, true, MossyCobblestoneWall::West::Tall).ID: return 6298; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Tall, MossyCobblestoneWall::North::Tall, MossyCobblestoneWall::South::Tall, false, MossyCobblestoneWall::West::None).ID: return 6302; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Tall, MossyCobblestoneWall::North::Tall, MossyCobblestoneWall::South::Tall, false, MossyCobblestoneWall::West::Low).ID: return 6303; case MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::Tall, MossyCobblestoneWall::North::Tall, MossyCobblestoneWall::South::Tall, false, MossyCobblestoneWall::West::Tall).ID: return 6304; case MossyStoneBrickSlab::MossyStoneBrickSlab(MossyStoneBrickSlab::Type::Top).ID: return 10802; case MossyStoneBrickSlab::MossyStoneBrickSlab(MossyStoneBrickSlab::Type::Bottom).ID: return 10804; case MossyStoneBrickSlab::MossyStoneBrickSlab(MossyStoneBrickSlab::Type::Double).ID: return 10806; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, MossyStoneBrickStairs::Half::Top, MossyStoneBrickStairs::Shape::Straight).ID: return 9830; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, MossyStoneBrickStairs::Half::Top, MossyStoneBrickStairs::Shape::InnerLeft).ID: return 9832; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, MossyStoneBrickStairs::Half::Top, MossyStoneBrickStairs::Shape::InnerRight).ID: return 9834; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, MossyStoneBrickStairs::Half::Top, MossyStoneBrickStairs::Shape::OuterLeft).ID: return 9836; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, MossyStoneBrickStairs::Half::Top, MossyStoneBrickStairs::Shape::OuterRight).ID: return 9838; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, MossyStoneBrickStairs::Half::Bottom, MossyStoneBrickStairs::Shape::Straight).ID: return 9840; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, MossyStoneBrickStairs::Half::Bottom, MossyStoneBrickStairs::Shape::InnerLeft).ID: return 9842; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, MossyStoneBrickStairs::Half::Bottom, MossyStoneBrickStairs::Shape::InnerRight).ID: return 9844; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, MossyStoneBrickStairs::Half::Bottom, MossyStoneBrickStairs::Shape::OuterLeft).ID: return 9846; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, MossyStoneBrickStairs::Half::Bottom, MossyStoneBrickStairs::Shape::OuterRight).ID: return 9848; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, MossyStoneBrickStairs::Half::Top, MossyStoneBrickStairs::Shape::Straight).ID: return 9850; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, MossyStoneBrickStairs::Half::Top, MossyStoneBrickStairs::Shape::InnerLeft).ID: return 9852; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, MossyStoneBrickStairs::Half::Top, MossyStoneBrickStairs::Shape::InnerRight).ID: return 9854; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, MossyStoneBrickStairs::Half::Top, MossyStoneBrickStairs::Shape::OuterLeft).ID: return 9856; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, MossyStoneBrickStairs::Half::Top, MossyStoneBrickStairs::Shape::OuterRight).ID: return 9858; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, MossyStoneBrickStairs::Half::Bottom, MossyStoneBrickStairs::Shape::Straight).ID: return 9860; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, MossyStoneBrickStairs::Half::Bottom, MossyStoneBrickStairs::Shape::InnerLeft).ID: return 9862; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, MossyStoneBrickStairs::Half::Bottom, MossyStoneBrickStairs::Shape::InnerRight).ID: return 9864; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, MossyStoneBrickStairs::Half::Bottom, MossyStoneBrickStairs::Shape::OuterLeft).ID: return 9866; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, MossyStoneBrickStairs::Half::Bottom, MossyStoneBrickStairs::Shape::OuterRight).ID: return 9868; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_XM, MossyStoneBrickStairs::Half::Top, MossyStoneBrickStairs::Shape::Straight).ID: return 9870; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_XM, MossyStoneBrickStairs::Half::Top, MossyStoneBrickStairs::Shape::InnerLeft).ID: return 9872; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_XM, MossyStoneBrickStairs::Half::Top, MossyStoneBrickStairs::Shape::InnerRight).ID: return 9874; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_XM, MossyStoneBrickStairs::Half::Top, MossyStoneBrickStairs::Shape::OuterLeft).ID: return 9876; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_XM, MossyStoneBrickStairs::Half::Top, MossyStoneBrickStairs::Shape::OuterRight).ID: return 9878; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_XM, MossyStoneBrickStairs::Half::Bottom, MossyStoneBrickStairs::Shape::Straight).ID: return 9880; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_XM, MossyStoneBrickStairs::Half::Bottom, MossyStoneBrickStairs::Shape::InnerLeft).ID: return 9882; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_XM, MossyStoneBrickStairs::Half::Bottom, MossyStoneBrickStairs::Shape::InnerRight).ID: return 9884; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_XM, MossyStoneBrickStairs::Half::Bottom, MossyStoneBrickStairs::Shape::OuterLeft).ID: return 9886; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_XM, MossyStoneBrickStairs::Half::Bottom, MossyStoneBrickStairs::Shape::OuterRight).ID: return 9888; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_XP, MossyStoneBrickStairs::Half::Top, MossyStoneBrickStairs::Shape::Straight).ID: return 9890; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_XP, MossyStoneBrickStairs::Half::Top, MossyStoneBrickStairs::Shape::InnerLeft).ID: return 9892; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_XP, MossyStoneBrickStairs::Half::Top, MossyStoneBrickStairs::Shape::InnerRight).ID: return 9894; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_XP, MossyStoneBrickStairs::Half::Top, MossyStoneBrickStairs::Shape::OuterLeft).ID: return 9896; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_XP, MossyStoneBrickStairs::Half::Top, MossyStoneBrickStairs::Shape::OuterRight).ID: return 9898; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_XP, MossyStoneBrickStairs::Half::Bottom, MossyStoneBrickStairs::Shape::Straight).ID: return 9900; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_XP, MossyStoneBrickStairs::Half::Bottom, MossyStoneBrickStairs::Shape::InnerLeft).ID: return 9902; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_XP, MossyStoneBrickStairs::Half::Bottom, MossyStoneBrickStairs::Shape::InnerRight).ID: return 9904; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_XP, MossyStoneBrickStairs::Half::Bottom, MossyStoneBrickStairs::Shape::OuterLeft).ID: return 9906; case MossyStoneBrickStairs::MossyStoneBrickStairs(eBlockFace::BLOCK_FACE_XP, MossyStoneBrickStairs::Half::Bottom, MossyStoneBrickStairs::Shape::OuterRight).ID: return 9908; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::None, true, MossyStoneBrickWall::West::None).ID: return 11842; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::None, true, MossyStoneBrickWall::West::Low).ID: return 11843; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::None, true, MossyStoneBrickWall::West::Tall).ID: return 11844; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::None, false, MossyStoneBrickWall::West::None).ID: return 11848; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::None, false, MossyStoneBrickWall::West::Low).ID: return 11849; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::None, false, MossyStoneBrickWall::West::Tall).ID: return 11850; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::Low, true, MossyStoneBrickWall::West::None).ID: return 11854; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::Low, true, MossyStoneBrickWall::West::Low).ID: return 11855; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::Low, true, MossyStoneBrickWall::West::Tall).ID: return 11856; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::Low, false, MossyStoneBrickWall::West::None).ID: return 11860; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::Low, false, MossyStoneBrickWall::West::Low).ID: return 11861; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::Low, false, MossyStoneBrickWall::West::Tall).ID: return 11862; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::Tall, true, MossyStoneBrickWall::West::None).ID: return 11866; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::Tall, true, MossyStoneBrickWall::West::Low).ID: return 11867; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::Tall, true, MossyStoneBrickWall::West::Tall).ID: return 11868; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::Tall, false, MossyStoneBrickWall::West::None).ID: return 11872; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::Tall, false, MossyStoneBrickWall::West::Low).ID: return 11873; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::Tall, false, MossyStoneBrickWall::West::Tall).ID: return 11874; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::None, true, MossyStoneBrickWall::West::None).ID: return 11878; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::None, true, MossyStoneBrickWall::West::Low).ID: return 11879; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::None, true, MossyStoneBrickWall::West::Tall).ID: return 11880; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::None, false, MossyStoneBrickWall::West::None).ID: return 11884; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::None, false, MossyStoneBrickWall::West::Low).ID: return 11885; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::None, false, MossyStoneBrickWall::West::Tall).ID: return 11886; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::Low, true, MossyStoneBrickWall::West::None).ID: return 11890; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::Low, true, MossyStoneBrickWall::West::Low).ID: return 11891; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::Low, true, MossyStoneBrickWall::West::Tall).ID: return 11892; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::Low, false, MossyStoneBrickWall::West::None).ID: return 11896; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::Low, false, MossyStoneBrickWall::West::Low).ID: return 11897; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::Low, false, MossyStoneBrickWall::West::Tall).ID: return 11898; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::Tall, true, MossyStoneBrickWall::West::None).ID: return 11902; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::Tall, true, MossyStoneBrickWall::West::Low).ID: return 11903; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::Tall, true, MossyStoneBrickWall::West::Tall).ID: return 11904; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::Tall, false, MossyStoneBrickWall::West::None).ID: return 11908; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::Tall, false, MossyStoneBrickWall::West::Low).ID: return 11909; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::Tall, false, MossyStoneBrickWall::West::Tall).ID: return 11910; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::Tall, MossyStoneBrickWall::South::None, true, MossyStoneBrickWall::West::None).ID: return 11914; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::Tall, MossyStoneBrickWall::South::None, true, MossyStoneBrickWall::West::Low).ID: return 11915; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::Tall, MossyStoneBrickWall::South::None, true, MossyStoneBrickWall::West::Tall).ID: return 11916; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::Tall, MossyStoneBrickWall::South::None, false, MossyStoneBrickWall::West::None).ID: return 11920; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::Tall, MossyStoneBrickWall::South::None, false, MossyStoneBrickWall::West::Low).ID: return 11921; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::Tall, MossyStoneBrickWall::South::None, false, MossyStoneBrickWall::West::Tall).ID: return 11922; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::Tall, MossyStoneBrickWall::South::Low, true, MossyStoneBrickWall::West::None).ID: return 11926; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::Tall, MossyStoneBrickWall::South::Low, true, MossyStoneBrickWall::West::Low).ID: return 11927; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::Tall, MossyStoneBrickWall::South::Low, true, MossyStoneBrickWall::West::Tall).ID: return 11928; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::Tall, MossyStoneBrickWall::South::Low, false, MossyStoneBrickWall::West::None).ID: return 11932; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::Tall, MossyStoneBrickWall::South::Low, false, MossyStoneBrickWall::West::Low).ID: return 11933; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::Tall, MossyStoneBrickWall::South::Low, false, MossyStoneBrickWall::West::Tall).ID: return 11934; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::Tall, MossyStoneBrickWall::South::Tall, true, MossyStoneBrickWall::West::None).ID: return 11938; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::Tall, MossyStoneBrickWall::South::Tall, true, MossyStoneBrickWall::West::Low).ID: return 11939; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::Tall, MossyStoneBrickWall::South::Tall, true, MossyStoneBrickWall::West::Tall).ID: return 11940; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::Tall, MossyStoneBrickWall::South::Tall, false, MossyStoneBrickWall::West::None).ID: return 11944; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::Tall, MossyStoneBrickWall::South::Tall, false, MossyStoneBrickWall::West::Low).ID: return 11945; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::None, MossyStoneBrickWall::North::Tall, MossyStoneBrickWall::South::Tall, false, MossyStoneBrickWall::West::Tall).ID: return 11946; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::None, true, MossyStoneBrickWall::West::None).ID: return 11950; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::None, true, MossyStoneBrickWall::West::Low).ID: return 11951; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::None, true, MossyStoneBrickWall::West::Tall).ID: return 11952; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::None, false, MossyStoneBrickWall::West::None).ID: return 11956; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::None, false, MossyStoneBrickWall::West::Low).ID: return 11957; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::None, false, MossyStoneBrickWall::West::Tall).ID: return 11958; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::Low, true, MossyStoneBrickWall::West::None).ID: return 11962; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::Low, true, MossyStoneBrickWall::West::Low).ID: return 11963; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::Low, true, MossyStoneBrickWall::West::Tall).ID: return 11964; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::Low, false, MossyStoneBrickWall::West::None).ID: return 11968; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::Low, false, MossyStoneBrickWall::West::Low).ID: return 11969; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::Low, false, MossyStoneBrickWall::West::Tall).ID: return 11970; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::Tall, true, MossyStoneBrickWall::West::None).ID: return 11974; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::Tall, true, MossyStoneBrickWall::West::Low).ID: return 11975; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::Tall, true, MossyStoneBrickWall::West::Tall).ID: return 11976; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::Tall, false, MossyStoneBrickWall::West::None).ID: return 11980; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::Tall, false, MossyStoneBrickWall::West::Low).ID: return 11981; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::Tall, false, MossyStoneBrickWall::West::Tall).ID: return 11982; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::None, true, MossyStoneBrickWall::West::None).ID: return 11986; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::None, true, MossyStoneBrickWall::West::Low).ID: return 11987; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::None, true, MossyStoneBrickWall::West::Tall).ID: return 11988; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::None, false, MossyStoneBrickWall::West::None).ID: return 11992; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::None, false, MossyStoneBrickWall::West::Low).ID: return 11993; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::None, false, MossyStoneBrickWall::West::Tall).ID: return 11994; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::Low, true, MossyStoneBrickWall::West::None).ID: return 11998; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::Low, true, MossyStoneBrickWall::West::Low).ID: return 11999; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::Low, true, MossyStoneBrickWall::West::Tall).ID: return 12000; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::Low, false, MossyStoneBrickWall::West::None).ID: return 12004; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::Low, false, MossyStoneBrickWall::West::Low).ID: return 12005; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::Low, false, MossyStoneBrickWall::West::Tall).ID: return 12006; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::Tall, true, MossyStoneBrickWall::West::None).ID: return 12010; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::Tall, true, MossyStoneBrickWall::West::Low).ID: return 12011; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::Tall, true, MossyStoneBrickWall::West::Tall).ID: return 12012; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::Tall, false, MossyStoneBrickWall::West::None).ID: return 12016; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::Tall, false, MossyStoneBrickWall::West::Low).ID: return 12017; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::Tall, false, MossyStoneBrickWall::West::Tall).ID: return 12018; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::Tall, MossyStoneBrickWall::South::None, true, MossyStoneBrickWall::West::None).ID: return 12022; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::Tall, MossyStoneBrickWall::South::None, true, MossyStoneBrickWall::West::Low).ID: return 12023; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::Tall, MossyStoneBrickWall::South::None, true, MossyStoneBrickWall::West::Tall).ID: return 12024; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::Tall, MossyStoneBrickWall::South::None, false, MossyStoneBrickWall::West::None).ID: return 12028; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::Tall, MossyStoneBrickWall::South::None, false, MossyStoneBrickWall::West::Low).ID: return 12029; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::Tall, MossyStoneBrickWall::South::None, false, MossyStoneBrickWall::West::Tall).ID: return 12030; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::Tall, MossyStoneBrickWall::South::Low, true, MossyStoneBrickWall::West::None).ID: return 12034; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::Tall, MossyStoneBrickWall::South::Low, true, MossyStoneBrickWall::West::Low).ID: return 12035; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::Tall, MossyStoneBrickWall::South::Low, true, MossyStoneBrickWall::West::Tall).ID: return 12036; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::Tall, MossyStoneBrickWall::South::Low, false, MossyStoneBrickWall::West::None).ID: return 12040; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::Tall, MossyStoneBrickWall::South::Low, false, MossyStoneBrickWall::West::Low).ID: return 12041; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::Tall, MossyStoneBrickWall::South::Low, false, MossyStoneBrickWall::West::Tall).ID: return 12042; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::Tall, MossyStoneBrickWall::South::Tall, true, MossyStoneBrickWall::West::None).ID: return 12046; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::Tall, MossyStoneBrickWall::South::Tall, true, MossyStoneBrickWall::West::Low).ID: return 12047; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::Tall, MossyStoneBrickWall::South::Tall, true, MossyStoneBrickWall::West::Tall).ID: return 12048; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::Tall, MossyStoneBrickWall::South::Tall, false, MossyStoneBrickWall::West::None).ID: return 12052; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::Tall, MossyStoneBrickWall::South::Tall, false, MossyStoneBrickWall::West::Low).ID: return 12053; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Low, MossyStoneBrickWall::North::Tall, MossyStoneBrickWall::South::Tall, false, MossyStoneBrickWall::West::Tall).ID: return 12054; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Tall, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::None, true, MossyStoneBrickWall::West::None).ID: return 12058; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Tall, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::None, true, MossyStoneBrickWall::West::Low).ID: return 12059; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Tall, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::None, true, MossyStoneBrickWall::West::Tall).ID: return 12060; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Tall, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::None, false, MossyStoneBrickWall::West::None).ID: return 12064; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Tall, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::None, false, MossyStoneBrickWall::West::Low).ID: return 12065; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Tall, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::None, false, MossyStoneBrickWall::West::Tall).ID: return 12066; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Tall, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::Low, true, MossyStoneBrickWall::West::None).ID: return 12070; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Tall, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::Low, true, MossyStoneBrickWall::West::Low).ID: return 12071; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Tall, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::Low, true, MossyStoneBrickWall::West::Tall).ID: return 12072; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Tall, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::Low, false, MossyStoneBrickWall::West::None).ID: return 12076; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Tall, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::Low, false, MossyStoneBrickWall::West::Low).ID: return 12077; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Tall, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::Low, false, MossyStoneBrickWall::West::Tall).ID: return 12078; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Tall, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::Tall, true, MossyStoneBrickWall::West::None).ID: return 12082; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Tall, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::Tall, true, MossyStoneBrickWall::West::Low).ID: return 12083; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Tall, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::Tall, true, MossyStoneBrickWall::West::Tall).ID: return 12084; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Tall, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::Tall, false, MossyStoneBrickWall::West::None).ID: return 12088; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Tall, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::Tall, false, MossyStoneBrickWall::West::Low).ID: return 12089; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Tall, MossyStoneBrickWall::North::None, MossyStoneBrickWall::South::Tall, false, MossyStoneBrickWall::West::Tall).ID: return 12090; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Tall, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::None, true, MossyStoneBrickWall::West::None).ID: return 12094; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Tall, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::None, true, MossyStoneBrickWall::West::Low).ID: return 12095; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Tall, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::None, true, MossyStoneBrickWall::West::Tall).ID: return 12096; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Tall, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::None, false, MossyStoneBrickWall::West::None).ID: return 12100; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Tall, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::None, false, MossyStoneBrickWall::West::Low).ID: return 12101; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Tall, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::None, false, MossyStoneBrickWall::West::Tall).ID: return 12102; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Tall, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::Low, true, MossyStoneBrickWall::West::None).ID: return 12106; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Tall, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::Low, true, MossyStoneBrickWall::West::Low).ID: return 12107; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Tall, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::Low, true, MossyStoneBrickWall::West::Tall).ID: return 12108; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Tall, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::Low, false, MossyStoneBrickWall::West::None).ID: return 12112; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Tall, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::Low, false, MossyStoneBrickWall::West::Low).ID: return 12113; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Tall, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::Low, false, MossyStoneBrickWall::West::Tall).ID: return 12114; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Tall, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::Tall, true, MossyStoneBrickWall::West::None).ID: return 12118; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Tall, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::Tall, true, MossyStoneBrickWall::West::Low).ID: return 12119; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Tall, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::Tall, true, MossyStoneBrickWall::West::Tall).ID: return 12120; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Tall, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::Tall, false, MossyStoneBrickWall::West::None).ID: return 12124; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Tall, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::Tall, false, MossyStoneBrickWall::West::Low).ID: return 12125; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Tall, MossyStoneBrickWall::North::Low, MossyStoneBrickWall::South::Tall, false, MossyStoneBrickWall::West::Tall).ID: return 12126; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Tall, MossyStoneBrickWall::North::Tall, MossyStoneBrickWall::South::None, true, MossyStoneBrickWall::West::None).ID: return 12130; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Tall, MossyStoneBrickWall::North::Tall, MossyStoneBrickWall::South::None, true, MossyStoneBrickWall::West::Low).ID: return 12131; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Tall, MossyStoneBrickWall::North::Tall, MossyStoneBrickWall::South::None, true, MossyStoneBrickWall::West::Tall).ID: return 12132; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Tall, MossyStoneBrickWall::North::Tall, MossyStoneBrickWall::South::None, false, MossyStoneBrickWall::West::None).ID: return 12136; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Tall, MossyStoneBrickWall::North::Tall, MossyStoneBrickWall::South::None, false, MossyStoneBrickWall::West::Low).ID: return 12137; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Tall, MossyStoneBrickWall::North::Tall, MossyStoneBrickWall::South::None, false, MossyStoneBrickWall::West::Tall).ID: return 12138; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Tall, MossyStoneBrickWall::North::Tall, MossyStoneBrickWall::South::Low, true, MossyStoneBrickWall::West::None).ID: return 12142; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Tall, MossyStoneBrickWall::North::Tall, MossyStoneBrickWall::South::Low, true, MossyStoneBrickWall::West::Low).ID: return 12143; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Tall, MossyStoneBrickWall::North::Tall, MossyStoneBrickWall::South::Low, true, MossyStoneBrickWall::West::Tall).ID: return 12144; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Tall, MossyStoneBrickWall::North::Tall, MossyStoneBrickWall::South::Low, false, MossyStoneBrickWall::West::None).ID: return 12148; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Tall, MossyStoneBrickWall::North::Tall, MossyStoneBrickWall::South::Low, false, MossyStoneBrickWall::West::Low).ID: return 12149; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Tall, MossyStoneBrickWall::North::Tall, MossyStoneBrickWall::South::Low, false, MossyStoneBrickWall::West::Tall).ID: return 12150; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Tall, MossyStoneBrickWall::North::Tall, MossyStoneBrickWall::South::Tall, true, MossyStoneBrickWall::West::None).ID: return 12154; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Tall, MossyStoneBrickWall::North::Tall, MossyStoneBrickWall::South::Tall, true, MossyStoneBrickWall::West::Low).ID: return 12155; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Tall, MossyStoneBrickWall::North::Tall, MossyStoneBrickWall::South::Tall, true, MossyStoneBrickWall::West::Tall).ID: return 12156; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Tall, MossyStoneBrickWall::North::Tall, MossyStoneBrickWall::South::Tall, false, MossyStoneBrickWall::West::None).ID: return 12160; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Tall, MossyStoneBrickWall::North::Tall, MossyStoneBrickWall::South::Tall, false, MossyStoneBrickWall::West::Low).ID: return 12161; case MossyStoneBrickWall::MossyStoneBrickWall(MossyStoneBrickWall::East::Tall, MossyStoneBrickWall::North::Tall, MossyStoneBrickWall::South::Tall, false, MossyStoneBrickWall::West::Tall).ID: return 12162; case MossyStoneBricks::MossyStoneBricks().ID: return 4496; case MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_ZM, MovingPiston::Type::Normal).ID: return 1400; case MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_ZM, MovingPiston::Type::Sticky).ID: return 1401; case MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_XP, MovingPiston::Type::Normal).ID: return 1402; case MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_XP, MovingPiston::Type::Sticky).ID: return 1403; case MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_ZP, MovingPiston::Type::Normal).ID: return 1404; case MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_ZP, MovingPiston::Type::Sticky).ID: return 1405; case MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_XM, MovingPiston::Type::Normal).ID: return 1406; case MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_XM, MovingPiston::Type::Sticky).ID: return 1407; case MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_YP, MovingPiston::Type::Normal).ID: return 1408; case MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_YP, MovingPiston::Type::Sticky).ID: return 1409; case MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_YM, MovingPiston::Type::Normal).ID: return 1410; case MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_YM, MovingPiston::Type::Sticky).ID: return 1411; case MushroomStem::MushroomStem(true, true, true, true, true, true).ID: return 4633; case MushroomStem::MushroomStem(true, true, true, true, true, false).ID: return 4634; case MushroomStem::MushroomStem(true, true, true, true, false, true).ID: return 4635; case MushroomStem::MushroomStem(true, true, true, true, false, false).ID: return 4636; case MushroomStem::MushroomStem(true, true, true, false, true, true).ID: return 4637; case MushroomStem::MushroomStem(true, true, true, false, true, false).ID: return 4638; case MushroomStem::MushroomStem(true, true, true, false, false, true).ID: return 4639; case MushroomStem::MushroomStem(true, true, true, false, false, false).ID: return 4640; case MushroomStem::MushroomStem(true, true, false, true, true, true).ID: return 4641; case MushroomStem::MushroomStem(true, true, false, true, true, false).ID: return 4642; case MushroomStem::MushroomStem(true, true, false, true, false, true).ID: return 4643; case MushroomStem::MushroomStem(true, true, false, true, false, false).ID: return 4644; case MushroomStem::MushroomStem(true, true, false, false, true, true).ID: return 4645; case MushroomStem::MushroomStem(true, true, false, false, true, false).ID: return 4646; case MushroomStem::MushroomStem(true, true, false, false, false, true).ID: return 4647; case MushroomStem::MushroomStem(true, true, false, false, false, false).ID: return 4648; case MushroomStem::MushroomStem(true, false, true, true, true, true).ID: return 4649; case MushroomStem::MushroomStem(true, false, true, true, true, false).ID: return 4650; case MushroomStem::MushroomStem(true, false, true, true, false, true).ID: return 4651; case MushroomStem::MushroomStem(true, false, true, true, false, false).ID: return 4652; case MushroomStem::MushroomStem(true, false, true, false, true, true).ID: return 4653; case MushroomStem::MushroomStem(true, false, true, false, true, false).ID: return 4654; case MushroomStem::MushroomStem(true, false, true, false, false, true).ID: return 4655; case MushroomStem::MushroomStem(true, false, true, false, false, false).ID: return 4656; case MushroomStem::MushroomStem(true, false, false, true, true, true).ID: return 4657; case MushroomStem::MushroomStem(true, false, false, true, true, false).ID: return 4658; case MushroomStem::MushroomStem(true, false, false, true, false, true).ID: return 4659; case MushroomStem::MushroomStem(true, false, false, true, false, false).ID: return 4660; case MushroomStem::MushroomStem(true, false, false, false, true, true).ID: return 4661; case MushroomStem::MushroomStem(true, false, false, false, true, false).ID: return 4662; case MushroomStem::MushroomStem(true, false, false, false, false, true).ID: return 4663; case MushroomStem::MushroomStem(true, false, false, false, false, false).ID: return 4664; case MushroomStem::MushroomStem(false, true, true, true, true, true).ID: return 4665; case MushroomStem::MushroomStem(false, true, true, true, true, false).ID: return 4666; case MushroomStem::MushroomStem(false, true, true, true, false, true).ID: return 4667; case MushroomStem::MushroomStem(false, true, true, true, false, false).ID: return 4668; case MushroomStem::MushroomStem(false, true, true, false, true, true).ID: return 4669; case MushroomStem::MushroomStem(false, true, true, false, true, false).ID: return 4670; case MushroomStem::MushroomStem(false, true, true, false, false, true).ID: return 4671; case MushroomStem::MushroomStem(false, true, true, false, false, false).ID: return 4672; case MushroomStem::MushroomStem(false, true, false, true, true, true).ID: return 4673; case MushroomStem::MushroomStem(false, true, false, true, true, false).ID: return 4674; case MushroomStem::MushroomStem(false, true, false, true, false, true).ID: return 4675; case MushroomStem::MushroomStem(false, true, false, true, false, false).ID: return 4676; case MushroomStem::MushroomStem(false, true, false, false, true, true).ID: return 4677; case MushroomStem::MushroomStem(false, true, false, false, true, false).ID: return 4678; case MushroomStem::MushroomStem(false, true, false, false, false, true).ID: return 4679; case MushroomStem::MushroomStem(false, true, false, false, false, false).ID: return 4680; case MushroomStem::MushroomStem(false, false, true, true, true, true).ID: return 4681; case MushroomStem::MushroomStem(false, false, true, true, true, false).ID: return 4682; case MushroomStem::MushroomStem(false, false, true, true, false, true).ID: return 4683; case MushroomStem::MushroomStem(false, false, true, true, false, false).ID: return 4684; case MushroomStem::MushroomStem(false, false, true, false, true, true).ID: return 4685; case MushroomStem::MushroomStem(false, false, true, false, true, false).ID: return 4686; case MushroomStem::MushroomStem(false, false, true, false, false, true).ID: return 4687; case MushroomStem::MushroomStem(false, false, true, false, false, false).ID: return 4688; case MushroomStem::MushroomStem(false, false, false, true, true, true).ID: return 4689; case MushroomStem::MushroomStem(false, false, false, true, true, false).ID: return 4690; case MushroomStem::MushroomStem(false, false, false, true, false, true).ID: return 4691; case MushroomStem::MushroomStem(false, false, false, true, false, false).ID: return 4692; case MushroomStem::MushroomStem(false, false, false, false, true, true).ID: return 4693; case MushroomStem::MushroomStem(false, false, false, false, true, false).ID: return 4694; case MushroomStem::MushroomStem(false, false, false, false, false, true).ID: return 4695; case MushroomStem::MushroomStem(false, false, false, false, false, false).ID: return 4696; case Mycelium::Mycelium(true).ID: return 5012; case Mycelium::Mycelium(false).ID: return 5013; case NetherBrickFence::NetherBrickFence(true, true, true, true).ID: return 5018; case NetherBrickFence::NetherBrickFence(true, true, true, false).ID: return 5019; case NetherBrickFence::NetherBrickFence(true, true, false, true).ID: return 5022; case NetherBrickFence::NetherBrickFence(true, true, false, false).ID: return 5023; case NetherBrickFence::NetherBrickFence(true, false, true, true).ID: return 5026; case NetherBrickFence::NetherBrickFence(true, false, true, false).ID: return 5027; case NetherBrickFence::NetherBrickFence(true, false, false, true).ID: return 5030; case NetherBrickFence::NetherBrickFence(true, false, false, false).ID: return 5031; case NetherBrickFence::NetherBrickFence(false, true, true, true).ID: return 5034; case NetherBrickFence::NetherBrickFence(false, true, true, false).ID: return 5035; case NetherBrickFence::NetherBrickFence(false, true, false, true).ID: return 5038; case NetherBrickFence::NetherBrickFence(false, true, false, false).ID: return 5039; case NetherBrickFence::NetherBrickFence(false, false, true, true).ID: return 5042; case NetherBrickFence::NetherBrickFence(false, false, true, false).ID: return 5043; case NetherBrickFence::NetherBrickFence(false, false, false, true).ID: return 5046; case NetherBrickFence::NetherBrickFence(false, false, false, false).ID: return 5047; case NetherBrickSlab::NetherBrickSlab(NetherBrickSlab::Type::Top).ID: return 8385; case NetherBrickSlab::NetherBrickSlab(NetherBrickSlab::Type::Bottom).ID: return 8387; case NetherBrickSlab::NetherBrickSlab(NetherBrickSlab::Type::Double).ID: return 8389; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::Straight).ID: return 5049; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::InnerLeft).ID: return 5051; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::InnerRight).ID: return 5053; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::OuterLeft).ID: return 5055; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::OuterRight).ID: return 5057; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::Straight).ID: return 5059; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::InnerLeft).ID: return 5061; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::InnerRight).ID: return 5063; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::OuterLeft).ID: return 5065; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::OuterRight).ID: return 5067; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::Straight).ID: return 5069; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::InnerLeft).ID: return 5071; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::InnerRight).ID: return 5073; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::OuterLeft).ID: return 5075; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::OuterRight).ID: return 5077; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::Straight).ID: return 5079; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::InnerLeft).ID: return 5081; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::InnerRight).ID: return 5083; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::OuterLeft).ID: return 5085; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::OuterRight).ID: return 5087; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XM, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::Straight).ID: return 5089; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XM, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::InnerLeft).ID: return 5091; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XM, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::InnerRight).ID: return 5093; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XM, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::OuterLeft).ID: return 5095; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XM, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::OuterRight).ID: return 5097; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XM, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::Straight).ID: return 5099; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XM, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::InnerLeft).ID: return 5101; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XM, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::InnerRight).ID: return 5103; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XM, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::OuterLeft).ID: return 5105; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XM, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::OuterRight).ID: return 5107; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XP, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::Straight).ID: return 5109; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XP, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::InnerLeft).ID: return 5111; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XP, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::InnerRight).ID: return 5113; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XP, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::OuterLeft).ID: return 5115; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XP, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::OuterRight).ID: return 5117; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XP, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::Straight).ID: return 5119; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XP, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::InnerLeft).ID: return 5121; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XP, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::InnerRight).ID: return 5123; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XP, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::OuterLeft).ID: return 5125; case NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XP, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::OuterRight).ID: return 5127; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::None, NetherBrickWall::South::None, true, NetherBrickWall::West::None).ID: return 12814; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::None, NetherBrickWall::South::None, true, NetherBrickWall::West::Low).ID: return 12815; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::None, NetherBrickWall::South::None, true, NetherBrickWall::West::Tall).ID: return 12816; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::None, NetherBrickWall::South::None, false, NetherBrickWall::West::None).ID: return 12820; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::None, NetherBrickWall::South::None, false, NetherBrickWall::West::Low).ID: return 12821; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::None, NetherBrickWall::South::None, false, NetherBrickWall::West::Tall).ID: return 12822; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::None, NetherBrickWall::South::Low, true, NetherBrickWall::West::None).ID: return 12826; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::None, NetherBrickWall::South::Low, true, NetherBrickWall::West::Low).ID: return 12827; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::None, NetherBrickWall::South::Low, true, NetherBrickWall::West::Tall).ID: return 12828; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::None, NetherBrickWall::South::Low, false, NetherBrickWall::West::None).ID: return 12832; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::None, NetherBrickWall::South::Low, false, NetherBrickWall::West::Low).ID: return 12833; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::None, NetherBrickWall::South::Low, false, NetherBrickWall::West::Tall).ID: return 12834; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::None, NetherBrickWall::South::Tall, true, NetherBrickWall::West::None).ID: return 12838; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::None, NetherBrickWall::South::Tall, true, NetherBrickWall::West::Low).ID: return 12839; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::None, NetherBrickWall::South::Tall, true, NetherBrickWall::West::Tall).ID: return 12840; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::None, NetherBrickWall::South::Tall, false, NetherBrickWall::West::None).ID: return 12844; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::None, NetherBrickWall::South::Tall, false, NetherBrickWall::West::Low).ID: return 12845; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::None, NetherBrickWall::South::Tall, false, NetherBrickWall::West::Tall).ID: return 12846; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::Low, NetherBrickWall::South::None, true, NetherBrickWall::West::None).ID: return 12850; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::Low, NetherBrickWall::South::None, true, NetherBrickWall::West::Low).ID: return 12851; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::Low, NetherBrickWall::South::None, true, NetherBrickWall::West::Tall).ID: return 12852; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::Low, NetherBrickWall::South::None, false, NetherBrickWall::West::None).ID: return 12856; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::Low, NetherBrickWall::South::None, false, NetherBrickWall::West::Low).ID: return 12857; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::Low, NetherBrickWall::South::None, false, NetherBrickWall::West::Tall).ID: return 12858; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::Low, NetherBrickWall::South::Low, true, NetherBrickWall::West::None).ID: return 12862; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::Low, NetherBrickWall::South::Low, true, NetherBrickWall::West::Low).ID: return 12863; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::Low, NetherBrickWall::South::Low, true, NetherBrickWall::West::Tall).ID: return 12864; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::Low, NetherBrickWall::South::Low, false, NetherBrickWall::West::None).ID: return 12868; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::Low, NetherBrickWall::South::Low, false, NetherBrickWall::West::Low).ID: return 12869; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::Low, NetherBrickWall::South::Low, false, NetherBrickWall::West::Tall).ID: return 12870; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::Low, NetherBrickWall::South::Tall, true, NetherBrickWall::West::None).ID: return 12874; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::Low, NetherBrickWall::South::Tall, true, NetherBrickWall::West::Low).ID: return 12875; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::Low, NetherBrickWall::South::Tall, true, NetherBrickWall::West::Tall).ID: return 12876; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::Low, NetherBrickWall::South::Tall, false, NetherBrickWall::West::None).ID: return 12880; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::Low, NetherBrickWall::South::Tall, false, NetherBrickWall::West::Low).ID: return 12881; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::Low, NetherBrickWall::South::Tall, false, NetherBrickWall::West::Tall).ID: return 12882; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::Tall, NetherBrickWall::South::None, true, NetherBrickWall::West::None).ID: return 12886; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::Tall, NetherBrickWall::South::None, true, NetherBrickWall::West::Low).ID: return 12887; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::Tall, NetherBrickWall::South::None, true, NetherBrickWall::West::Tall).ID: return 12888; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::Tall, NetherBrickWall::South::None, false, NetherBrickWall::West::None).ID: return 12892; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::Tall, NetherBrickWall::South::None, false, NetherBrickWall::West::Low).ID: return 12893; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::Tall, NetherBrickWall::South::None, false, NetherBrickWall::West::Tall).ID: return 12894; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::Tall, NetherBrickWall::South::Low, true, NetherBrickWall::West::None).ID: return 12898; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::Tall, NetherBrickWall::South::Low, true, NetherBrickWall::West::Low).ID: return 12899; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::Tall, NetherBrickWall::South::Low, true, NetherBrickWall::West::Tall).ID: return 12900; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::Tall, NetherBrickWall::South::Low, false, NetherBrickWall::West::None).ID: return 12904; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::Tall, NetherBrickWall::South::Low, false, NetherBrickWall::West::Low).ID: return 12905; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::Tall, NetherBrickWall::South::Low, false, NetherBrickWall::West::Tall).ID: return 12906; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::Tall, NetherBrickWall::South::Tall, true, NetherBrickWall::West::None).ID: return 12910; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::Tall, NetherBrickWall::South::Tall, true, NetherBrickWall::West::Low).ID: return 12911; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::Tall, NetherBrickWall::South::Tall, true, NetherBrickWall::West::Tall).ID: return 12912; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::Tall, NetherBrickWall::South::Tall, false, NetherBrickWall::West::None).ID: return 12916; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::Tall, NetherBrickWall::South::Tall, false, NetherBrickWall::West::Low).ID: return 12917; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::None, NetherBrickWall::North::Tall, NetherBrickWall::South::Tall, false, NetherBrickWall::West::Tall).ID: return 12918; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::None, NetherBrickWall::South::None, true, NetherBrickWall::West::None).ID: return 12922; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::None, NetherBrickWall::South::None, true, NetherBrickWall::West::Low).ID: return 12923; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::None, NetherBrickWall::South::None, true, NetherBrickWall::West::Tall).ID: return 12924; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::None, NetherBrickWall::South::None, false, NetherBrickWall::West::None).ID: return 12928; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::None, NetherBrickWall::South::None, false, NetherBrickWall::West::Low).ID: return 12929; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::None, NetherBrickWall::South::None, false, NetherBrickWall::West::Tall).ID: return 12930; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::None, NetherBrickWall::South::Low, true, NetherBrickWall::West::None).ID: return 12934; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::None, NetherBrickWall::South::Low, true, NetherBrickWall::West::Low).ID: return 12935; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::None, NetherBrickWall::South::Low, true, NetherBrickWall::West::Tall).ID: return 12936; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::None, NetherBrickWall::South::Low, false, NetherBrickWall::West::None).ID: return 12940; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::None, NetherBrickWall::South::Low, false, NetherBrickWall::West::Low).ID: return 12941; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::None, NetherBrickWall::South::Low, false, NetherBrickWall::West::Tall).ID: return 12942; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::None, NetherBrickWall::South::Tall, true, NetherBrickWall::West::None).ID: return 12946; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::None, NetherBrickWall::South::Tall, true, NetherBrickWall::West::Low).ID: return 12947; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::None, NetherBrickWall::South::Tall, true, NetherBrickWall::West::Tall).ID: return 12948; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::None, NetherBrickWall::South::Tall, false, NetherBrickWall::West::None).ID: return 12952; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::None, NetherBrickWall::South::Tall, false, NetherBrickWall::West::Low).ID: return 12953; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::None, NetherBrickWall::South::Tall, false, NetherBrickWall::West::Tall).ID: return 12954; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::Low, NetherBrickWall::South::None, true, NetherBrickWall::West::None).ID: return 12958; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::Low, NetherBrickWall::South::None, true, NetherBrickWall::West::Low).ID: return 12959; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::Low, NetherBrickWall::South::None, true, NetherBrickWall::West::Tall).ID: return 12960; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::Low, NetherBrickWall::South::None, false, NetherBrickWall::West::None).ID: return 12964; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::Low, NetherBrickWall::South::None, false, NetherBrickWall::West::Low).ID: return 12965; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::Low, NetherBrickWall::South::None, false, NetherBrickWall::West::Tall).ID: return 12966; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::Low, NetherBrickWall::South::Low, true, NetherBrickWall::West::None).ID: return 12970; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::Low, NetherBrickWall::South::Low, true, NetherBrickWall::West::Low).ID: return 12971; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::Low, NetherBrickWall::South::Low, true, NetherBrickWall::West::Tall).ID: return 12972; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::Low, NetherBrickWall::South::Low, false, NetherBrickWall::West::None).ID: return 12976; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::Low, NetherBrickWall::South::Low, false, NetherBrickWall::West::Low).ID: return 12977; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::Low, NetherBrickWall::South::Low, false, NetherBrickWall::West::Tall).ID: return 12978; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::Low, NetherBrickWall::South::Tall, true, NetherBrickWall::West::None).ID: return 12982; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::Low, NetherBrickWall::South::Tall, true, NetherBrickWall::West::Low).ID: return 12983; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::Low, NetherBrickWall::South::Tall, true, NetherBrickWall::West::Tall).ID: return 12984; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::Low, NetherBrickWall::South::Tall, false, NetherBrickWall::West::None).ID: return 12988; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::Low, NetherBrickWall::South::Tall, false, NetherBrickWall::West::Low).ID: return 12989; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::Low, NetherBrickWall::South::Tall, false, NetherBrickWall::West::Tall).ID: return 12990; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::Tall, NetherBrickWall::South::None, true, NetherBrickWall::West::None).ID: return 12994; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::Tall, NetherBrickWall::South::None, true, NetherBrickWall::West::Low).ID: return 12995; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::Tall, NetherBrickWall::South::None, true, NetherBrickWall::West::Tall).ID: return 12996; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::Tall, NetherBrickWall::South::None, false, NetherBrickWall::West::None).ID: return 13000; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::Tall, NetherBrickWall::South::None, false, NetherBrickWall::West::Low).ID: return 13001; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::Tall, NetherBrickWall::South::None, false, NetherBrickWall::West::Tall).ID: return 13002; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::Tall, NetherBrickWall::South::Low, true, NetherBrickWall::West::None).ID: return 13006; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::Tall, NetherBrickWall::South::Low, true, NetherBrickWall::West::Low).ID: return 13007; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::Tall, NetherBrickWall::South::Low, true, NetherBrickWall::West::Tall).ID: return 13008; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::Tall, NetherBrickWall::South::Low, false, NetherBrickWall::West::None).ID: return 13012; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::Tall, NetherBrickWall::South::Low, false, NetherBrickWall::West::Low).ID: return 13013; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::Tall, NetherBrickWall::South::Low, false, NetherBrickWall::West::Tall).ID: return 13014; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::Tall, NetherBrickWall::South::Tall, true, NetherBrickWall::West::None).ID: return 13018; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::Tall, NetherBrickWall::South::Tall, true, NetherBrickWall::West::Low).ID: return 13019; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::Tall, NetherBrickWall::South::Tall, true, NetherBrickWall::West::Tall).ID: return 13020; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::Tall, NetherBrickWall::South::Tall, false, NetherBrickWall::West::None).ID: return 13024; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::Tall, NetherBrickWall::South::Tall, false, NetherBrickWall::West::Low).ID: return 13025; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Low, NetherBrickWall::North::Tall, NetherBrickWall::South::Tall, false, NetherBrickWall::West::Tall).ID: return 13026; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Tall, NetherBrickWall::North::None, NetherBrickWall::South::None, true, NetherBrickWall::West::None).ID: return 13030; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Tall, NetherBrickWall::North::None, NetherBrickWall::South::None, true, NetherBrickWall::West::Low).ID: return 13031; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Tall, NetherBrickWall::North::None, NetherBrickWall::South::None, true, NetherBrickWall::West::Tall).ID: return 13032; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Tall, NetherBrickWall::North::None, NetherBrickWall::South::None, false, NetherBrickWall::West::None).ID: return 13036; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Tall, NetherBrickWall::North::None, NetherBrickWall::South::None, false, NetherBrickWall::West::Low).ID: return 13037; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Tall, NetherBrickWall::North::None, NetherBrickWall::South::None, false, NetherBrickWall::West::Tall).ID: return 13038; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Tall, NetherBrickWall::North::None, NetherBrickWall::South::Low, true, NetherBrickWall::West::None).ID: return 13042; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Tall, NetherBrickWall::North::None, NetherBrickWall::South::Low, true, NetherBrickWall::West::Low).ID: return 13043; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Tall, NetherBrickWall::North::None, NetherBrickWall::South::Low, true, NetherBrickWall::West::Tall).ID: return 13044; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Tall, NetherBrickWall::North::None, NetherBrickWall::South::Low, false, NetherBrickWall::West::None).ID: return 13048; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Tall, NetherBrickWall::North::None, NetherBrickWall::South::Low, false, NetherBrickWall::West::Low).ID: return 13049; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Tall, NetherBrickWall::North::None, NetherBrickWall::South::Low, false, NetherBrickWall::West::Tall).ID: return 13050; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Tall, NetherBrickWall::North::None, NetherBrickWall::South::Tall, true, NetherBrickWall::West::None).ID: return 13054; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Tall, NetherBrickWall::North::None, NetherBrickWall::South::Tall, true, NetherBrickWall::West::Low).ID: return 13055; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Tall, NetherBrickWall::North::None, NetherBrickWall::South::Tall, true, NetherBrickWall::West::Tall).ID: return 13056; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Tall, NetherBrickWall::North::None, NetherBrickWall::South::Tall, false, NetherBrickWall::West::None).ID: return 13060; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Tall, NetherBrickWall::North::None, NetherBrickWall::South::Tall, false, NetherBrickWall::West::Low).ID: return 13061; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Tall, NetherBrickWall::North::None, NetherBrickWall::South::Tall, false, NetherBrickWall::West::Tall).ID: return 13062; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Tall, NetherBrickWall::North::Low, NetherBrickWall::South::None, true, NetherBrickWall::West::None).ID: return 13066; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Tall, NetherBrickWall::North::Low, NetherBrickWall::South::None, true, NetherBrickWall::West::Low).ID: return 13067; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Tall, NetherBrickWall::North::Low, NetherBrickWall::South::None, true, NetherBrickWall::West::Tall).ID: return 13068; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Tall, NetherBrickWall::North::Low, NetherBrickWall::South::None, false, NetherBrickWall::West::None).ID: return 13072; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Tall, NetherBrickWall::North::Low, NetherBrickWall::South::None, false, NetherBrickWall::West::Low).ID: return 13073; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Tall, NetherBrickWall::North::Low, NetherBrickWall::South::None, false, NetherBrickWall::West::Tall).ID: return 13074; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Tall, NetherBrickWall::North::Low, NetherBrickWall::South::Low, true, NetherBrickWall::West::None).ID: return 13078; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Tall, NetherBrickWall::North::Low, NetherBrickWall::South::Low, true, NetherBrickWall::West::Low).ID: return 13079; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Tall, NetherBrickWall::North::Low, NetherBrickWall::South::Low, true, NetherBrickWall::West::Tall).ID: return 13080; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Tall, NetherBrickWall::North::Low, NetherBrickWall::South::Low, false, NetherBrickWall::West::None).ID: return 13084; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Tall, NetherBrickWall::North::Low, NetherBrickWall::South::Low, false, NetherBrickWall::West::Low).ID: return 13085; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Tall, NetherBrickWall::North::Low, NetherBrickWall::South::Low, false, NetherBrickWall::West::Tall).ID: return 13086; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Tall, NetherBrickWall::North::Low, NetherBrickWall::South::Tall, true, NetherBrickWall::West::None).ID: return 13090; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Tall, NetherBrickWall::North::Low, NetherBrickWall::South::Tall, true, NetherBrickWall::West::Low).ID: return 13091; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Tall, NetherBrickWall::North::Low, NetherBrickWall::South::Tall, true, NetherBrickWall::West::Tall).ID: return 13092; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Tall, NetherBrickWall::North::Low, NetherBrickWall::South::Tall, false, NetherBrickWall::West::None).ID: return 13096; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Tall, NetherBrickWall::North::Low, NetherBrickWall::South::Tall, false, NetherBrickWall::West::Low).ID: return 13097; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Tall, NetherBrickWall::North::Low, NetherBrickWall::South::Tall, false, NetherBrickWall::West::Tall).ID: return 13098; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Tall, NetherBrickWall::North::Tall, NetherBrickWall::South::None, true, NetherBrickWall::West::None).ID: return 13102; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Tall, NetherBrickWall::North::Tall, NetherBrickWall::South::None, true, NetherBrickWall::West::Low).ID: return 13103; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Tall, NetherBrickWall::North::Tall, NetherBrickWall::South::None, true, NetherBrickWall::West::Tall).ID: return 13104; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Tall, NetherBrickWall::North::Tall, NetherBrickWall::South::None, false, NetherBrickWall::West::None).ID: return 13108; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Tall, NetherBrickWall::North::Tall, NetherBrickWall::South::None, false, NetherBrickWall::West::Low).ID: return 13109; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Tall, NetherBrickWall::North::Tall, NetherBrickWall::South::None, false, NetherBrickWall::West::Tall).ID: return 13110; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Tall, NetherBrickWall::North::Tall, NetherBrickWall::South::Low, true, NetherBrickWall::West::None).ID: return 13114; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Tall, NetherBrickWall::North::Tall, NetherBrickWall::South::Low, true, NetherBrickWall::West::Low).ID: return 13115; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Tall, NetherBrickWall::North::Tall, NetherBrickWall::South::Low, true, NetherBrickWall::West::Tall).ID: return 13116; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Tall, NetherBrickWall::North::Tall, NetherBrickWall::South::Low, false, NetherBrickWall::West::None).ID: return 13120; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Tall, NetherBrickWall::North::Tall, NetherBrickWall::South::Low, false, NetherBrickWall::West::Low).ID: return 13121; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Tall, NetherBrickWall::North::Tall, NetherBrickWall::South::Low, false, NetherBrickWall::West::Tall).ID: return 13122; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Tall, NetherBrickWall::North::Tall, NetherBrickWall::South::Tall, true, NetherBrickWall::West::None).ID: return 13126; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Tall, NetherBrickWall::North::Tall, NetherBrickWall::South::Tall, true, NetherBrickWall::West::Low).ID: return 13127; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Tall, NetherBrickWall::North::Tall, NetherBrickWall::South::Tall, true, NetherBrickWall::West::Tall).ID: return 13128; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Tall, NetherBrickWall::North::Tall, NetherBrickWall::South::Tall, false, NetherBrickWall::West::None).ID: return 13132; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Tall, NetherBrickWall::North::Tall, NetherBrickWall::South::Tall, false, NetherBrickWall::West::Low).ID: return 13133; case NetherBrickWall::NetherBrickWall(NetherBrickWall::East::Tall, NetherBrickWall::North::Tall, NetherBrickWall::South::Tall, false, NetherBrickWall::West::Tall).ID: return 13134; case NetherBricks::NetherBricks().ID: return 5015; case NetherGoldOre::NetherGoldOre().ID: return 72; case NetherPortal::NetherPortal(NetherPortal::Axis::X).ID: return 4014; case NetherPortal::NetherPortal(NetherPortal::Axis::Z).ID: return 4015; case NetherQuartzOre::NetherQuartzOre().ID: return 6727; case NetherSprouts::NetherSprouts().ID: return 14974; case NetherWart::NetherWart(0).ID: return 5128; case NetherWart::NetherWart(1).ID: return 5129; case NetherWart::NetherWart(2).ID: return 5130; case NetherWart::NetherWart(3).ID: return 5131; case NetherWartBlock::NetherWartBlock().ID: return 9254; case NetheriteBlock::NetheriteBlock().ID: return 15826; case Netherrack::Netherrack().ID: return 3999; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 0, true).ID: return 249; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 0, false).ID: return 250; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 1, true).ID: return 251; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 1, false).ID: return 252; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 2, true).ID: return 253; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 2, false).ID: return 254; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 3, true).ID: return 255; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 3, false).ID: return 256; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 4, true).ID: return 257; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 4, false).ID: return 258; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 5, true).ID: return 259; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 5, false).ID: return 260; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 6, true).ID: return 261; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 6, false).ID: return 262; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 7, true).ID: return 263; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 7, false).ID: return 264; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 8, true).ID: return 265; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 8, false).ID: return 266; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 9, true).ID: return 267; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 9, false).ID: return 268; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 10, true).ID: return 269; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 10, false).ID: return 270; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 11, true).ID: return 271; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 11, false).ID: return 272; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 12, true).ID: return 273; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 12, false).ID: return 274; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 13, true).ID: return 275; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 13, false).ID: return 276; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 14, true).ID: return 277; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 14, false).ID: return 278; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 15, true).ID: return 279; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 15, false).ID: return 280; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 16, true).ID: return 281; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 16, false).ID: return 282; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 17, true).ID: return 283; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 17, false).ID: return 284; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 18, true).ID: return 285; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 18, false).ID: return 286; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 19, true).ID: return 287; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 19, false).ID: return 288; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 20, true).ID: return 289; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 20, false).ID: return 290; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 21, true).ID: return 291; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 21, false).ID: return 292; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 22, true).ID: return 293; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 22, false).ID: return 294; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 23, true).ID: return 295; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 23, false).ID: return 296; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 24, true).ID: return 297; case NoteBlock::NoteBlock(NoteBlock::Instrument::Harp, 24, false).ID: return 298; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 0, true).ID: return 299; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 0, false).ID: return 300; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 1, true).ID: return 301; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 1, false).ID: return 302; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 2, true).ID: return 303; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 2, false).ID: return 304; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 3, true).ID: return 305; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 3, false).ID: return 306; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 4, true).ID: return 307; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 4, false).ID: return 308; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 5, true).ID: return 309; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 5, false).ID: return 310; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 6, true).ID: return 311; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 6, false).ID: return 312; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 7, true).ID: return 313; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 7, false).ID: return 314; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 8, true).ID: return 315; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 8, false).ID: return 316; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 9, true).ID: return 317; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 9, false).ID: return 318; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 10, true).ID: return 319; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 10, false).ID: return 320; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 11, true).ID: return 321; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 11, false).ID: return 322; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 12, true).ID: return 323; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 12, false).ID: return 324; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 13, true).ID: return 325; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 13, false).ID: return 326; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 14, true).ID: return 327; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 14, false).ID: return 328; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 15, true).ID: return 329; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 15, false).ID: return 330; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 16, true).ID: return 331; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 16, false).ID: return 332; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 17, true).ID: return 333; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 17, false).ID: return 334; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 18, true).ID: return 335; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 18, false).ID: return 336; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 19, true).ID: return 337; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 19, false).ID: return 338; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 20, true).ID: return 339; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 20, false).ID: return 340; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 21, true).ID: return 341; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 21, false).ID: return 342; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 22, true).ID: return 343; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 22, false).ID: return 344; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 23, true).ID: return 345; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 23, false).ID: return 346; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 24, true).ID: return 347; case NoteBlock::NoteBlock(NoteBlock::Instrument::Basedrum, 24, false).ID: return 348; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 0, true).ID: return 349; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 0, false).ID: return 350; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 1, true).ID: return 351; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 1, false).ID: return 352; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 2, true).ID: return 353; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 2, false).ID: return 354; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 3, true).ID: return 355; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 3, false).ID: return 356; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 4, true).ID: return 357; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 4, false).ID: return 358; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 5, true).ID: return 359; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 5, false).ID: return 360; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 6, true).ID: return 361; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 6, false).ID: return 362; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 7, true).ID: return 363; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 7, false).ID: return 364; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 8, true).ID: return 365; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 8, false).ID: return 366; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 9, true).ID: return 367; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 9, false).ID: return 368; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 10, true).ID: return 369; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 10, false).ID: return 370; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 11, true).ID: return 371; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 11, false).ID: return 372; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 12, true).ID: return 373; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 12, false).ID: return 374; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 13, true).ID: return 375; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 13, false).ID: return 376; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 14, true).ID: return 377; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 14, false).ID: return 378; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 15, true).ID: return 379; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 15, false).ID: return 380; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 16, true).ID: return 381; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 16, false).ID: return 382; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 17, true).ID: return 383; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 17, false).ID: return 384; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 18, true).ID: return 385; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 18, false).ID: return 386; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 19, true).ID: return 387; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 19, false).ID: return 388; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 20, true).ID: return 389; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 20, false).ID: return 390; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 21, true).ID: return 391; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 21, false).ID: return 392; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 22, true).ID: return 393; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 22, false).ID: return 394; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 23, true).ID: return 395; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 23, false).ID: return 396; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 24, true).ID: return 397; case NoteBlock::NoteBlock(NoteBlock::Instrument::Snare, 24, false).ID: return 398; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 0, true).ID: return 399; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 0, false).ID: return 400; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 1, true).ID: return 401; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 1, false).ID: return 402; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 2, true).ID: return 403; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 2, false).ID: return 404; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 3, true).ID: return 405; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 3, false).ID: return 406; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 4, true).ID: return 407; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 4, false).ID: return 408; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 5, true).ID: return 409; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 5, false).ID: return 410; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 6, true).ID: return 411; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 6, false).ID: return 412; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 7, true).ID: return 413; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 7, false).ID: return 414; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 8, true).ID: return 415; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 8, false).ID: return 416; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 9, true).ID: return 417; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 9, false).ID: return 418; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 10, true).ID: return 419; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 10, false).ID: return 420; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 11, true).ID: return 421; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 11, false).ID: return 422; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 12, true).ID: return 423; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 12, false).ID: return 424; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 13, true).ID: return 425; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 13, false).ID: return 426; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 14, true).ID: return 427; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 14, false).ID: return 428; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 15, true).ID: return 429; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 15, false).ID: return 430; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 16, true).ID: return 431; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 16, false).ID: return 432; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 17, true).ID: return 433; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 17, false).ID: return 434; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 18, true).ID: return 435; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 18, false).ID: return 436; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 19, true).ID: return 437; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 19, false).ID: return 438; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 20, true).ID: return 439; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 20, false).ID: return 440; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 21, true).ID: return 441; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 21, false).ID: return 442; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 22, true).ID: return 443; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 22, false).ID: return 444; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 23, true).ID: return 445; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 23, false).ID: return 446; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 24, true).ID: return 447; case NoteBlock::NoteBlock(NoteBlock::Instrument::Hat, 24, false).ID: return 448; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 0, true).ID: return 449; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 0, false).ID: return 450; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 1, true).ID: return 451; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 1, false).ID: return 452; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 2, true).ID: return 453; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 2, false).ID: return 454; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 3, true).ID: return 455; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 3, false).ID: return 456; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 4, true).ID: return 457; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 4, false).ID: return 458; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 5, true).ID: return 459; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 5, false).ID: return 460; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 6, true).ID: return 461; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 6, false).ID: return 462; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 7, true).ID: return 463; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 7, false).ID: return 464; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 8, true).ID: return 465; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 8, false).ID: return 466; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 9, true).ID: return 467; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 9, false).ID: return 468; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 10, true).ID: return 469; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 10, false).ID: return 470; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 11, true).ID: return 471; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 11, false).ID: return 472; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 12, true).ID: return 473; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 12, false).ID: return 474; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 13, true).ID: return 475; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 13, false).ID: return 476; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 14, true).ID: return 477; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 14, false).ID: return 478; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 15, true).ID: return 479; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 15, false).ID: return 480; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 16, true).ID: return 481; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 16, false).ID: return 482; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 17, true).ID: return 483; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 17, false).ID: return 484; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 18, true).ID: return 485; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 18, false).ID: return 486; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 19, true).ID: return 487; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 19, false).ID: return 488; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 20, true).ID: return 489; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 20, false).ID: return 490; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 21, true).ID: return 491; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 21, false).ID: return 492; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 22, true).ID: return 493; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 22, false).ID: return 494; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 23, true).ID: return 495; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 23, false).ID: return 496; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 24, true).ID: return 497; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bass, 24, false).ID: return 498; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 0, true).ID: return 499; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 0, false).ID: return 500; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 1, true).ID: return 501; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 1, false).ID: return 502; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 2, true).ID: return 503; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 2, false).ID: return 504; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 3, true).ID: return 505; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 3, false).ID: return 506; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 4, true).ID: return 507; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 4, false).ID: return 508; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 5, true).ID: return 509; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 5, false).ID: return 510; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 6, true).ID: return 511; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 6, false).ID: return 512; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 7, true).ID: return 513; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 7, false).ID: return 514; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 8, true).ID: return 515; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 8, false).ID: return 516; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 9, true).ID: return 517; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 9, false).ID: return 518; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 10, true).ID: return 519; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 10, false).ID: return 520; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 11, true).ID: return 521; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 11, false).ID: return 522; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 12, true).ID: return 523; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 12, false).ID: return 524; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 13, true).ID: return 525; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 13, false).ID: return 526; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 14, true).ID: return 527; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 14, false).ID: return 528; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 15, true).ID: return 529; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 15, false).ID: return 530; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 16, true).ID: return 531; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 16, false).ID: return 532; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 17, true).ID: return 533; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 17, false).ID: return 534; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 18, true).ID: return 535; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 18, false).ID: return 536; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 19, true).ID: return 537; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 19, false).ID: return 538; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 20, true).ID: return 539; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 20, false).ID: return 540; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 21, true).ID: return 541; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 21, false).ID: return 542; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 22, true).ID: return 543; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 22, false).ID: return 544; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 23, true).ID: return 545; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 23, false).ID: return 546; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 24, true).ID: return 547; case NoteBlock::NoteBlock(NoteBlock::Instrument::Flute, 24, false).ID: return 548; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 0, true).ID: return 549; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 0, false).ID: return 550; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 1, true).ID: return 551; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 1, false).ID: return 552; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 2, true).ID: return 553; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 2, false).ID: return 554; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 3, true).ID: return 555; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 3, false).ID: return 556; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 4, true).ID: return 557; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 4, false).ID: return 558; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 5, true).ID: return 559; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 5, false).ID: return 560; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 6, true).ID: return 561; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 6, false).ID: return 562; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 7, true).ID: return 563; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 7, false).ID: return 564; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 8, true).ID: return 565; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 8, false).ID: return 566; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 9, true).ID: return 567; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 9, false).ID: return 568; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 10, true).ID: return 569; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 10, false).ID: return 570; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 11, true).ID: return 571; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 11, false).ID: return 572; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 12, true).ID: return 573; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 12, false).ID: return 574; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 13, true).ID: return 575; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 13, false).ID: return 576; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 14, true).ID: return 577; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 14, false).ID: return 578; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 15, true).ID: return 579; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 15, false).ID: return 580; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 16, true).ID: return 581; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 16, false).ID: return 582; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 17, true).ID: return 583; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 17, false).ID: return 584; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 18, true).ID: return 585; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 18, false).ID: return 586; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 19, true).ID: return 587; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 19, false).ID: return 588; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 20, true).ID: return 589; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 20, false).ID: return 590; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 21, true).ID: return 591; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 21, false).ID: return 592; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 22, true).ID: return 593; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 22, false).ID: return 594; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 23, true).ID: return 595; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 23, false).ID: return 596; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 24, true).ID: return 597; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bell, 24, false).ID: return 598; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 0, true).ID: return 599; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 0, false).ID: return 600; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 1, true).ID: return 601; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 1, false).ID: return 602; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 2, true).ID: return 603; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 2, false).ID: return 604; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 3, true).ID: return 605; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 3, false).ID: return 606; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 4, true).ID: return 607; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 4, false).ID: return 608; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 5, true).ID: return 609; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 5, false).ID: return 610; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 6, true).ID: return 611; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 6, false).ID: return 612; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 7, true).ID: return 613; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 7, false).ID: return 614; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 8, true).ID: return 615; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 8, false).ID: return 616; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 9, true).ID: return 617; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 9, false).ID: return 618; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 10, true).ID: return 619; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 10, false).ID: return 620; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 11, true).ID: return 621; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 11, false).ID: return 622; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 12, true).ID: return 623; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 12, false).ID: return 624; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 13, true).ID: return 625; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 13, false).ID: return 626; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 14, true).ID: return 627; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 14, false).ID: return 628; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 15, true).ID: return 629; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 15, false).ID: return 630; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 16, true).ID: return 631; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 16, false).ID: return 632; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 17, true).ID: return 633; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 17, false).ID: return 634; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 18, true).ID: return 635; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 18, false).ID: return 636; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 19, true).ID: return 637; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 19, false).ID: return 638; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 20, true).ID: return 639; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 20, false).ID: return 640; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 21, true).ID: return 641; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 21, false).ID: return 642; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 22, true).ID: return 643; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 22, false).ID: return 644; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 23, true).ID: return 645; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 23, false).ID: return 646; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 24, true).ID: return 647; case NoteBlock::NoteBlock(NoteBlock::Instrument::Guitar, 24, false).ID: return 648; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 0, true).ID: return 649; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 0, false).ID: return 650; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 1, true).ID: return 651; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 1, false).ID: return 652; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 2, true).ID: return 653; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 2, false).ID: return 654; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 3, true).ID: return 655; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 3, false).ID: return 656; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 4, true).ID: return 657; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 4, false).ID: return 658; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 5, true).ID: return 659; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 5, false).ID: return 660; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 6, true).ID: return 661; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 6, false).ID: return 662; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 7, true).ID: return 663; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 7, false).ID: return 664; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 8, true).ID: return 665; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 8, false).ID: return 666; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 9, true).ID: return 667; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 9, false).ID: return 668; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 10, true).ID: return 669; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 10, false).ID: return 670; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 11, true).ID: return 671; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 11, false).ID: return 672; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 12, true).ID: return 673; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 12, false).ID: return 674; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 13, true).ID: return 675; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 13, false).ID: return 676; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 14, true).ID: return 677; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 14, false).ID: return 678; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 15, true).ID: return 679; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 15, false).ID: return 680; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 16, true).ID: return 681; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 16, false).ID: return 682; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 17, true).ID: return 683; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 17, false).ID: return 684; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 18, true).ID: return 685; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 18, false).ID: return 686; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 19, true).ID: return 687; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 19, false).ID: return 688; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 20, true).ID: return 689; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 20, false).ID: return 690; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 21, true).ID: return 691; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 21, false).ID: return 692; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 22, true).ID: return 693; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 22, false).ID: return 694; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 23, true).ID: return 695; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 23, false).ID: return 696; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 24, true).ID: return 697; case NoteBlock::NoteBlock(NoteBlock::Instrument::Chime, 24, false).ID: return 698; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 0, true).ID: return 699; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 0, false).ID: return 700; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 1, true).ID: return 701; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 1, false).ID: return 702; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 2, true).ID: return 703; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 2, false).ID: return 704; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 3, true).ID: return 705; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 3, false).ID: return 706; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 4, true).ID: return 707; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 4, false).ID: return 708; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 5, true).ID: return 709; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 5, false).ID: return 710; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 6, true).ID: return 711; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 6, false).ID: return 712; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 7, true).ID: return 713; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 7, false).ID: return 714; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 8, true).ID: return 715; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 8, false).ID: return 716; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 9, true).ID: return 717; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 9, false).ID: return 718; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 10, true).ID: return 719; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 10, false).ID: return 720; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 11, true).ID: return 721; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 11, false).ID: return 722; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 12, true).ID: return 723; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 12, false).ID: return 724; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 13, true).ID: return 725; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 13, false).ID: return 726; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 14, true).ID: return 727; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 14, false).ID: return 728; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 15, true).ID: return 729; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 15, false).ID: return 730; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 16, true).ID: return 731; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 16, false).ID: return 732; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 17, true).ID: return 733; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 17, false).ID: return 734; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 18, true).ID: return 735; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 18, false).ID: return 736; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 19, true).ID: return 737; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 19, false).ID: return 738; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 20, true).ID: return 739; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 20, false).ID: return 740; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 21, true).ID: return 741; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 21, false).ID: return 742; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 22, true).ID: return 743; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 22, false).ID: return 744; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 23, true).ID: return 745; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 23, false).ID: return 746; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 24, true).ID: return 747; case NoteBlock::NoteBlock(NoteBlock::Instrument::Xylophone, 24, false).ID: return 748; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 0, true).ID: return 749; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 0, false).ID: return 750; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 1, true).ID: return 751; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 1, false).ID: return 752; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 2, true).ID: return 753; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 2, false).ID: return 754; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 3, true).ID: return 755; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 3, false).ID: return 756; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 4, true).ID: return 757; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 4, false).ID: return 758; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 5, true).ID: return 759; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 5, false).ID: return 760; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 6, true).ID: return 761; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 6, false).ID: return 762; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 7, true).ID: return 763; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 7, false).ID: return 764; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 8, true).ID: return 765; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 8, false).ID: return 766; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 9, true).ID: return 767; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 9, false).ID: return 768; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 10, true).ID: return 769; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 10, false).ID: return 770; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 11, true).ID: return 771; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 11, false).ID: return 772; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 12, true).ID: return 773; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 12, false).ID: return 774; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 13, true).ID: return 775; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 13, false).ID: return 776; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 14, true).ID: return 777; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 14, false).ID: return 778; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 15, true).ID: return 779; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 15, false).ID: return 780; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 16, true).ID: return 781; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 16, false).ID: return 782; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 17, true).ID: return 783; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 17, false).ID: return 784; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 18, true).ID: return 785; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 18, false).ID: return 786; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 19, true).ID: return 787; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 19, false).ID: return 788; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 20, true).ID: return 789; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 20, false).ID: return 790; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 21, true).ID: return 791; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 21, false).ID: return 792; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 22, true).ID: return 793; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 22, false).ID: return 794; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 23, true).ID: return 795; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 23, false).ID: return 796; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 24, true).ID: return 797; case NoteBlock::NoteBlock(NoteBlock::Instrument::IronXylophone, 24, false).ID: return 798; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 0, true).ID: return 799; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 0, false).ID: return 800; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 1, true).ID: return 801; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 1, false).ID: return 802; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 2, true).ID: return 803; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 2, false).ID: return 804; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 3, true).ID: return 805; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 3, false).ID: return 806; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 4, true).ID: return 807; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 4, false).ID: return 808; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 5, true).ID: return 809; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 5, false).ID: return 810; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 6, true).ID: return 811; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 6, false).ID: return 812; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 7, true).ID: return 813; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 7, false).ID: return 814; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 8, true).ID: return 815; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 8, false).ID: return 816; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 9, true).ID: return 817; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 9, false).ID: return 818; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 10, true).ID: return 819; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 10, false).ID: return 820; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 11, true).ID: return 821; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 11, false).ID: return 822; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 12, true).ID: return 823; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 12, false).ID: return 824; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 13, true).ID: return 825; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 13, false).ID: return 826; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 14, true).ID: return 827; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 14, false).ID: return 828; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 15, true).ID: return 829; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 15, false).ID: return 830; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 16, true).ID: return 831; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 16, false).ID: return 832; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 17, true).ID: return 833; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 17, false).ID: return 834; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 18, true).ID: return 835; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 18, false).ID: return 836; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 19, true).ID: return 837; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 19, false).ID: return 838; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 20, true).ID: return 839; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 20, false).ID: return 840; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 21, true).ID: return 841; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 21, false).ID: return 842; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 22, true).ID: return 843; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 22, false).ID: return 844; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 23, true).ID: return 845; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 23, false).ID: return 846; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 24, true).ID: return 847; case NoteBlock::NoteBlock(NoteBlock::Instrument::CowBell, 24, false).ID: return 848; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 0, true).ID: return 849; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 0, false).ID: return 850; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 1, true).ID: return 851; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 1, false).ID: return 852; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 2, true).ID: return 853; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 2, false).ID: return 854; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 3, true).ID: return 855; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 3, false).ID: return 856; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 4, true).ID: return 857; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 4, false).ID: return 858; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 5, true).ID: return 859; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 5, false).ID: return 860; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 6, true).ID: return 861; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 6, false).ID: return 862; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 7, true).ID: return 863; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 7, false).ID: return 864; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 8, true).ID: return 865; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 8, false).ID: return 866; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 9, true).ID: return 867; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 9, false).ID: return 868; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 10, true).ID: return 869; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 10, false).ID: return 870; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 11, true).ID: return 871; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 11, false).ID: return 872; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 12, true).ID: return 873; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 12, false).ID: return 874; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 13, true).ID: return 875; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 13, false).ID: return 876; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 14, true).ID: return 877; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 14, false).ID: return 878; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 15, true).ID: return 879; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 15, false).ID: return 880; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 16, true).ID: return 881; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 16, false).ID: return 882; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 17, true).ID: return 883; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 17, false).ID: return 884; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 18, true).ID: return 885; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 18, false).ID: return 886; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 19, true).ID: return 887; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 19, false).ID: return 888; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 20, true).ID: return 889; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 20, false).ID: return 890; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 21, true).ID: return 891; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 21, false).ID: return 892; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 22, true).ID: return 893; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 22, false).ID: return 894; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 23, true).ID: return 895; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 23, false).ID: return 896; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 24, true).ID: return 897; case NoteBlock::NoteBlock(NoteBlock::Instrument::Didgeridoo, 24, false).ID: return 898; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 0, true).ID: return 899; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 0, false).ID: return 900; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 1, true).ID: return 901; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 1, false).ID: return 902; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 2, true).ID: return 903; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 2, false).ID: return 904; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 3, true).ID: return 905; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 3, false).ID: return 906; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 4, true).ID: return 907; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 4, false).ID: return 908; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 5, true).ID: return 909; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 5, false).ID: return 910; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 6, true).ID: return 911; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 6, false).ID: return 912; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 7, true).ID: return 913; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 7, false).ID: return 914; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 8, true).ID: return 915; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 8, false).ID: return 916; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 9, true).ID: return 917; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 9, false).ID: return 918; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 10, true).ID: return 919; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 10, false).ID: return 920; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 11, true).ID: return 921; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 11, false).ID: return 922; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 12, true).ID: return 923; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 12, false).ID: return 924; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 13, true).ID: return 925; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 13, false).ID: return 926; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 14, true).ID: return 927; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 14, false).ID: return 928; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 15, true).ID: return 929; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 15, false).ID: return 930; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 16, true).ID: return 931; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 16, false).ID: return 932; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 17, true).ID: return 933; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 17, false).ID: return 934; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 18, true).ID: return 935; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 18, false).ID: return 936; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 19, true).ID: return 937; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 19, false).ID: return 938; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 20, true).ID: return 939; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 20, false).ID: return 940; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 21, true).ID: return 941; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 21, false).ID: return 942; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 22, true).ID: return 943; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 22, false).ID: return 944; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 23, true).ID: return 945; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 23, false).ID: return 946; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 24, true).ID: return 947; case NoteBlock::NoteBlock(NoteBlock::Instrument::Bit, 24, false).ID: return 948; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 0, true).ID: return 949; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 0, false).ID: return 950; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 1, true).ID: return 951; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 1, false).ID: return 952; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 2, true).ID: return 953; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 2, false).ID: return 954; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 3, true).ID: return 955; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 3, false).ID: return 956; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 4, true).ID: return 957; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 4, false).ID: return 958; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 5, true).ID: return 959; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 5, false).ID: return 960; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 6, true).ID: return 961; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 6, false).ID: return 962; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 7, true).ID: return 963; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 7, false).ID: return 964; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 8, true).ID: return 965; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 8, false).ID: return 966; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 9, true).ID: return 967; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 9, false).ID: return 968; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 10, true).ID: return 969; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 10, false).ID: return 970; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 11, true).ID: return 971; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 11, false).ID: return 972; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 12, true).ID: return 973; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 12, false).ID: return 974; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 13, true).ID: return 975; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 13, false).ID: return 976; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 14, true).ID: return 977; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 14, false).ID: return 978; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 15, true).ID: return 979; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 15, false).ID: return 980; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 16, true).ID: return 981; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 16, false).ID: return 982; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 17, true).ID: return 983; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 17, false).ID: return 984; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 18, true).ID: return 985; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 18, false).ID: return 986; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 19, true).ID: return 987; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 19, false).ID: return 988; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 20, true).ID: return 989; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 20, false).ID: return 990; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 21, true).ID: return 991; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 21, false).ID: return 992; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 22, true).ID: return 993; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 22, false).ID: return 994; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 23, true).ID: return 995; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 23, false).ID: return 996; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 24, true).ID: return 997; case NoteBlock::NoteBlock(NoteBlock::Instrument::Banjo, 24, false).ID: return 998; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 0, true).ID: return 999; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 0, false).ID: return 1000; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 1, true).ID: return 1001; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 1, false).ID: return 1002; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 2, true).ID: return 1003; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 2, false).ID: return 1004; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 3, true).ID: return 1005; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 3, false).ID: return 1006; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 4, true).ID: return 1007; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 4, false).ID: return 1008; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 5, true).ID: return 1009; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 5, false).ID: return 1010; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 6, true).ID: return 1011; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 6, false).ID: return 1012; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 7, true).ID: return 1013; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 7, false).ID: return 1014; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 8, true).ID: return 1015; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 8, false).ID: return 1016; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 9, true).ID: return 1017; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 9, false).ID: return 1018; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 10, true).ID: return 1019; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 10, false).ID: return 1020; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 11, true).ID: return 1021; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 11, false).ID: return 1022; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 12, true).ID: return 1023; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 12, false).ID: return 1024; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 13, true).ID: return 1025; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 13, false).ID: return 1026; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 14, true).ID: return 1027; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 14, false).ID: return 1028; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 15, true).ID: return 1029; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 15, false).ID: return 1030; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 16, true).ID: return 1031; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 16, false).ID: return 1032; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 17, true).ID: return 1033; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 17, false).ID: return 1034; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 18, true).ID: return 1035; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 18, false).ID: return 1036; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 19, true).ID: return 1037; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 19, false).ID: return 1038; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 20, true).ID: return 1039; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 20, false).ID: return 1040; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 21, true).ID: return 1041; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 21, false).ID: return 1042; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 22, true).ID: return 1043; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 22, false).ID: return 1044; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 23, true).ID: return 1045; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 23, false).ID: return 1046; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 24, true).ID: return 1047; case NoteBlock::NoteBlock(NoteBlock::Instrument::Pling, 24, false).ID: return 1048; case OakButton::OakButton(OakButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, true).ID: return 6346; case OakButton::OakButton(OakButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, false).ID: return 6347; case OakButton::OakButton(OakButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, true).ID: return 6348; case OakButton::OakButton(OakButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, false).ID: return 6349; case OakButton::OakButton(OakButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, true).ID: return 6350; case OakButton::OakButton(OakButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, false).ID: return 6351; case OakButton::OakButton(OakButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, true).ID: return 6352; case OakButton::OakButton(OakButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, false).ID: return 6353; case OakButton::OakButton(OakButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, true).ID: return 6354; case OakButton::OakButton(OakButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, false).ID: return 6355; case OakButton::OakButton(OakButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, true).ID: return 6356; case OakButton::OakButton(OakButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, false).ID: return 6357; case OakButton::OakButton(OakButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, true).ID: return 6358; case OakButton::OakButton(OakButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, false).ID: return 6359; case OakButton::OakButton(OakButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, true).ID: return 6360; case OakButton::OakButton(OakButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, false).ID: return 6361; case OakButton::OakButton(OakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, true).ID: return 6362; case OakButton::OakButton(OakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, false).ID: return 6363; case OakButton::OakButton(OakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, true).ID: return 6364; case OakButton::OakButton(OakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, false).ID: return 6365; case OakButton::OakButton(OakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, true).ID: return 6366; case OakButton::OakButton(OakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, false).ID: return 6367; case OakButton::OakButton(OakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, true).ID: return 6368; case OakButton::OakButton(OakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, false).ID: return 6369; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Upper, OakDoor::Hinge::Left, true, true).ID: return 3573; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Upper, OakDoor::Hinge::Left, true, false).ID: return 3574; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Upper, OakDoor::Hinge::Left, false, true).ID: return 3575; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Upper, OakDoor::Hinge::Left, false, false).ID: return 3576; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Upper, OakDoor::Hinge::Right, true, true).ID: return 3577; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Upper, OakDoor::Hinge::Right, true, false).ID: return 3578; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Upper, OakDoor::Hinge::Right, false, true).ID: return 3579; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Upper, OakDoor::Hinge::Right, false, false).ID: return 3580; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Lower, OakDoor::Hinge::Left, true, true).ID: return 3581; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Lower, OakDoor::Hinge::Left, true, false).ID: return 3582; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Lower, OakDoor::Hinge::Left, false, true).ID: return 3583; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Lower, OakDoor::Hinge::Left, false, false).ID: return 3584; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Lower, OakDoor::Hinge::Right, true, true).ID: return 3585; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Lower, OakDoor::Hinge::Right, true, false).ID: return 3586; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Lower, OakDoor::Hinge::Right, false, true).ID: return 3587; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Lower, OakDoor::Hinge::Right, false, false).ID: return 3588; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Upper, OakDoor::Hinge::Left, true, true).ID: return 3589; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Upper, OakDoor::Hinge::Left, true, false).ID: return 3590; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Upper, OakDoor::Hinge::Left, false, true).ID: return 3591; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Upper, OakDoor::Hinge::Left, false, false).ID: return 3592; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Upper, OakDoor::Hinge::Right, true, true).ID: return 3593; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Upper, OakDoor::Hinge::Right, true, false).ID: return 3594; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Upper, OakDoor::Hinge::Right, false, true).ID: return 3595; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Upper, OakDoor::Hinge::Right, false, false).ID: return 3596; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Lower, OakDoor::Hinge::Left, true, true).ID: return 3597; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Lower, OakDoor::Hinge::Left, true, false).ID: return 3598; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Lower, OakDoor::Hinge::Left, false, true).ID: return 3599; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Lower, OakDoor::Hinge::Left, false, false).ID: return 3600; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Lower, OakDoor::Hinge::Right, true, true).ID: return 3601; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Lower, OakDoor::Hinge::Right, true, false).ID: return 3602; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Lower, OakDoor::Hinge::Right, false, true).ID: return 3603; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Lower, OakDoor::Hinge::Right, false, false).ID: return 3604; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Upper, OakDoor::Hinge::Left, true, true).ID: return 3605; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Upper, OakDoor::Hinge::Left, true, false).ID: return 3606; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Upper, OakDoor::Hinge::Left, false, true).ID: return 3607; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Upper, OakDoor::Hinge::Left, false, false).ID: return 3608; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Upper, OakDoor::Hinge::Right, true, true).ID: return 3609; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Upper, OakDoor::Hinge::Right, true, false).ID: return 3610; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Upper, OakDoor::Hinge::Right, false, true).ID: return 3611; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Upper, OakDoor::Hinge::Right, false, false).ID: return 3612; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Lower, OakDoor::Hinge::Left, true, true).ID: return 3613; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Lower, OakDoor::Hinge::Left, true, false).ID: return 3614; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Lower, OakDoor::Hinge::Left, false, true).ID: return 3615; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Lower, OakDoor::Hinge::Left, false, false).ID: return 3616; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Lower, OakDoor::Hinge::Right, true, true).ID: return 3617; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Lower, OakDoor::Hinge::Right, true, false).ID: return 3618; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Lower, OakDoor::Hinge::Right, false, true).ID: return 3619; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Lower, OakDoor::Hinge::Right, false, false).ID: return 3620; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Upper, OakDoor::Hinge::Left, true, true).ID: return 3621; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Upper, OakDoor::Hinge::Left, true, false).ID: return 3622; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Upper, OakDoor::Hinge::Left, false, true).ID: return 3623; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Upper, OakDoor::Hinge::Left, false, false).ID: return 3624; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Upper, OakDoor::Hinge::Right, true, true).ID: return 3625; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Upper, OakDoor::Hinge::Right, true, false).ID: return 3626; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Upper, OakDoor::Hinge::Right, false, true).ID: return 3627; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Upper, OakDoor::Hinge::Right, false, false).ID: return 3628; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Lower, OakDoor::Hinge::Left, true, true).ID: return 3629; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Lower, OakDoor::Hinge::Left, true, false).ID: return 3630; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Lower, OakDoor::Hinge::Left, false, true).ID: return 3631; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Lower, OakDoor::Hinge::Left, false, false).ID: return 3632; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Lower, OakDoor::Hinge::Right, true, true).ID: return 3633; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Lower, OakDoor::Hinge::Right, true, false).ID: return 3634; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Lower, OakDoor::Hinge::Right, false, true).ID: return 3635; case OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Lower, OakDoor::Hinge::Right, false, false).ID: return 3636; case OakFence::OakFence(true, true, true, true).ID: return 3968; case OakFence::OakFence(true, true, true, false).ID: return 3969; case OakFence::OakFence(true, true, false, true).ID: return 3972; case OakFence::OakFence(true, true, false, false).ID: return 3973; case OakFence::OakFence(true, false, true, true).ID: return 3976; case OakFence::OakFence(true, false, true, false).ID: return 3977; case OakFence::OakFence(true, false, false, true).ID: return 3980; case OakFence::OakFence(true, false, false, false).ID: return 3981; case OakFence::OakFence(false, true, true, true).ID: return 3984; case OakFence::OakFence(false, true, true, false).ID: return 3985; case OakFence::OakFence(false, true, false, true).ID: return 3988; case OakFence::OakFence(false, true, false, false).ID: return 3989; case OakFence::OakFence(false, false, true, true).ID: return 3992; case OakFence::OakFence(false, false, true, false).ID: return 3993; case OakFence::OakFence(false, false, false, true).ID: return 3996; case OakFence::OakFence(false, false, false, false).ID: return 3997; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZM, true, true, true).ID: return 4820; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZM, true, true, false).ID: return 4821; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZM, true, false, true).ID: return 4822; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZM, true, false, false).ID: return 4823; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, true).ID: return 4824; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, false).ID: return 4825; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, true).ID: return 4826; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, false).ID: return 4827; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZP, true, true, true).ID: return 4828; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZP, true, true, false).ID: return 4829; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZP, true, false, true).ID: return 4830; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZP, true, false, false).ID: return 4831; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, true).ID: return 4832; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, false).ID: return 4833; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, true).ID: return 4834; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, false).ID: return 4835; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XM, true, true, true).ID: return 4836; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XM, true, true, false).ID: return 4837; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XM, true, false, true).ID: return 4838; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XM, true, false, false).ID: return 4839; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, true).ID: return 4840; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, false).ID: return 4841; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, true).ID: return 4842; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, false).ID: return 4843; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XP, true, true, true).ID: return 4844; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XP, true, true, false).ID: return 4845; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XP, true, false, true).ID: return 4846; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XP, true, false, false).ID: return 4847; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, true).ID: return 4848; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, false).ID: return 4849; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, true).ID: return 4850; case OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, false).ID: return 4851; case OakLeaves::OakLeaves(1, true).ID: return 145; case OakLeaves::OakLeaves(1, false).ID: return 146; case OakLeaves::OakLeaves(2, true).ID: return 147; case OakLeaves::OakLeaves(2, false).ID: return 148; case OakLeaves::OakLeaves(3, true).ID: return 149; case OakLeaves::OakLeaves(3, false).ID: return 150; case OakLeaves::OakLeaves(4, true).ID: return 151; case OakLeaves::OakLeaves(4, false).ID: return 152; case OakLeaves::OakLeaves(5, true).ID: return 153; case OakLeaves::OakLeaves(5, false).ID: return 154; case OakLeaves::OakLeaves(6, true).ID: return 155; case OakLeaves::OakLeaves(6, false).ID: return 156; case OakLeaves::OakLeaves(7, true).ID: return 157; case OakLeaves::OakLeaves(7, false).ID: return 158; case OakLog::OakLog(OakLog::Axis::X).ID: return 73; case OakLog::OakLog(OakLog::Axis::Y).ID: return 74; case OakLog::OakLog(OakLog::Axis::Z).ID: return 75; case OakPlanks::OakPlanks().ID: return 15; case OakPressurePlate::OakPressurePlate(true).ID: return 3873; case OakPressurePlate::OakPressurePlate(false).ID: return 3874; case OakSapling::OakSapling(0).ID: return 21; case OakSapling::OakSapling(1).ID: return 22; case OakSign::OakSign(0).ID: return 3382; case OakSign::OakSign(1).ID: return 3384; case OakSign::OakSign(2).ID: return 3386; case OakSign::OakSign(3).ID: return 3388; case OakSign::OakSign(4).ID: return 3390; case OakSign::OakSign(5).ID: return 3392; case OakSign::OakSign(6).ID: return 3394; case OakSign::OakSign(7).ID: return 3396; case OakSign::OakSign(8).ID: return 3398; case OakSign::OakSign(9).ID: return 3400; case OakSign::OakSign(10).ID: return 3402; case OakSign::OakSign(11).ID: return 3404; case OakSign::OakSign(12).ID: return 3406; case OakSign::OakSign(13).ID: return 3408; case OakSign::OakSign(14).ID: return 3410; case OakSign::OakSign(15).ID: return 3412; case OakSlab::OakSlab(OakSlab::Type::Top).ID: return 8301; case OakSlab::OakSlab(OakSlab::Type::Bottom).ID: return 8303; case OakSlab::OakSlab(OakSlab::Type::Double).ID: return 8305; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZM, OakStairs::Half::Top, OakStairs::Shape::Straight).ID: return 1955; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZM, OakStairs::Half::Top, OakStairs::Shape::InnerLeft).ID: return 1957; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZM, OakStairs::Half::Top, OakStairs::Shape::InnerRight).ID: return 1959; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZM, OakStairs::Half::Top, OakStairs::Shape::OuterLeft).ID: return 1961; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZM, OakStairs::Half::Top, OakStairs::Shape::OuterRight).ID: return 1963; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZM, OakStairs::Half::Bottom, OakStairs::Shape::Straight).ID: return 1965; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZM, OakStairs::Half::Bottom, OakStairs::Shape::InnerLeft).ID: return 1967; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZM, OakStairs::Half::Bottom, OakStairs::Shape::InnerRight).ID: return 1969; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZM, OakStairs::Half::Bottom, OakStairs::Shape::OuterLeft).ID: return 1971; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZM, OakStairs::Half::Bottom, OakStairs::Shape::OuterRight).ID: return 1973; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZP, OakStairs::Half::Top, OakStairs::Shape::Straight).ID: return 1975; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZP, OakStairs::Half::Top, OakStairs::Shape::InnerLeft).ID: return 1977; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZP, OakStairs::Half::Top, OakStairs::Shape::InnerRight).ID: return 1979; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZP, OakStairs::Half::Top, OakStairs::Shape::OuterLeft).ID: return 1981; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZP, OakStairs::Half::Top, OakStairs::Shape::OuterRight).ID: return 1983; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZP, OakStairs::Half::Bottom, OakStairs::Shape::Straight).ID: return 1985; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZP, OakStairs::Half::Bottom, OakStairs::Shape::InnerLeft).ID: return 1987; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZP, OakStairs::Half::Bottom, OakStairs::Shape::InnerRight).ID: return 1989; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZP, OakStairs::Half::Bottom, OakStairs::Shape::OuterLeft).ID: return 1991; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZP, OakStairs::Half::Bottom, OakStairs::Shape::OuterRight).ID: return 1993; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XM, OakStairs::Half::Top, OakStairs::Shape::Straight).ID: return 1995; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XM, OakStairs::Half::Top, OakStairs::Shape::InnerLeft).ID: return 1997; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XM, OakStairs::Half::Top, OakStairs::Shape::InnerRight).ID: return 1999; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XM, OakStairs::Half::Top, OakStairs::Shape::OuterLeft).ID: return 2001; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XM, OakStairs::Half::Top, OakStairs::Shape::OuterRight).ID: return 2003; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XM, OakStairs::Half::Bottom, OakStairs::Shape::Straight).ID: return 2005; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XM, OakStairs::Half::Bottom, OakStairs::Shape::InnerLeft).ID: return 2007; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XM, OakStairs::Half::Bottom, OakStairs::Shape::InnerRight).ID: return 2009; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XM, OakStairs::Half::Bottom, OakStairs::Shape::OuterLeft).ID: return 2011; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XM, OakStairs::Half::Bottom, OakStairs::Shape::OuterRight).ID: return 2013; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XP, OakStairs::Half::Top, OakStairs::Shape::Straight).ID: return 2015; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XP, OakStairs::Half::Top, OakStairs::Shape::InnerLeft).ID: return 2017; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XP, OakStairs::Half::Top, OakStairs::Shape::InnerRight).ID: return 2019; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XP, OakStairs::Half::Top, OakStairs::Shape::OuterLeft).ID: return 2021; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XP, OakStairs::Half::Top, OakStairs::Shape::OuterRight).ID: return 2023; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XP, OakStairs::Half::Bottom, OakStairs::Shape::Straight).ID: return 2025; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XP, OakStairs::Half::Bottom, OakStairs::Shape::InnerLeft).ID: return 2027; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XP, OakStairs::Half::Bottom, OakStairs::Shape::InnerRight).ID: return 2029; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XP, OakStairs::Half::Bottom, OakStairs::Shape::OuterLeft).ID: return 2031; case OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XP, OakStairs::Half::Bottom, OakStairs::Shape::OuterRight).ID: return 2033; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZM, OakTrapdoor::Half::Top, true, true).ID: return 4112; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZM, OakTrapdoor::Half::Top, true, false).ID: return 4114; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZM, OakTrapdoor::Half::Top, false, true).ID: return 4116; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZM, OakTrapdoor::Half::Top, false, false).ID: return 4118; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZM, OakTrapdoor::Half::Bottom, true, true).ID: return 4120; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZM, OakTrapdoor::Half::Bottom, true, false).ID: return 4122; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZM, OakTrapdoor::Half::Bottom, false, true).ID: return 4124; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZM, OakTrapdoor::Half::Bottom, false, false).ID: return 4126; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZP, OakTrapdoor::Half::Top, true, true).ID: return 4128; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZP, OakTrapdoor::Half::Top, true, false).ID: return 4130; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZP, OakTrapdoor::Half::Top, false, true).ID: return 4132; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZP, OakTrapdoor::Half::Top, false, false).ID: return 4134; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZP, OakTrapdoor::Half::Bottom, true, true).ID: return 4136; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZP, OakTrapdoor::Half::Bottom, true, false).ID: return 4138; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZP, OakTrapdoor::Half::Bottom, false, true).ID: return 4140; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZP, OakTrapdoor::Half::Bottom, false, false).ID: return 4142; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XM, OakTrapdoor::Half::Top, true, true).ID: return 4144; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XM, OakTrapdoor::Half::Top, true, false).ID: return 4146; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XM, OakTrapdoor::Half::Top, false, true).ID: return 4148; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XM, OakTrapdoor::Half::Top, false, false).ID: return 4150; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XM, OakTrapdoor::Half::Bottom, true, true).ID: return 4152; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XM, OakTrapdoor::Half::Bottom, true, false).ID: return 4154; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XM, OakTrapdoor::Half::Bottom, false, true).ID: return 4156; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XM, OakTrapdoor::Half::Bottom, false, false).ID: return 4158; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XP, OakTrapdoor::Half::Top, true, true).ID: return 4160; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XP, OakTrapdoor::Half::Top, true, false).ID: return 4162; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XP, OakTrapdoor::Half::Top, false, true).ID: return 4164; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XP, OakTrapdoor::Half::Top, false, false).ID: return 4166; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XP, OakTrapdoor::Half::Bottom, true, true).ID: return 4168; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XP, OakTrapdoor::Half::Bottom, true, false).ID: return 4170; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XP, OakTrapdoor::Half::Bottom, false, true).ID: return 4172; case OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XP, OakTrapdoor::Half::Bottom, false, false).ID: return 4174; case OakWallSign::OakWallSign(eBlockFace::BLOCK_FACE_ZM).ID: return 3736; case OakWallSign::OakWallSign(eBlockFace::BLOCK_FACE_ZP).ID: return 3738; case OakWallSign::OakWallSign(eBlockFace::BLOCK_FACE_XM).ID: return 3740; case OakWallSign::OakWallSign(eBlockFace::BLOCK_FACE_XP).ID: return 3742; case OakWood::OakWood(OakWood::Axis::X).ID: return 109; case OakWood::OakWood(OakWood::Axis::Y).ID: return 110; case OakWood::OakWood(OakWood::Axis::Z).ID: return 111; case Observer::Observer(eBlockFace::BLOCK_FACE_ZM, true).ID: return 9260; case Observer::Observer(eBlockFace::BLOCK_FACE_ZM, false).ID: return 9261; case Observer::Observer(eBlockFace::BLOCK_FACE_XP, true).ID: return 9262; case Observer::Observer(eBlockFace::BLOCK_FACE_XP, false).ID: return 9263; case Observer::Observer(eBlockFace::BLOCK_FACE_ZP, true).ID: return 9264; case Observer::Observer(eBlockFace::BLOCK_FACE_ZP, false).ID: return 9265; case Observer::Observer(eBlockFace::BLOCK_FACE_XM, true).ID: return 9266; case Observer::Observer(eBlockFace::BLOCK_FACE_XM, false).ID: return 9267; case Observer::Observer(eBlockFace::BLOCK_FACE_YP, true).ID: return 9268; case Observer::Observer(eBlockFace::BLOCK_FACE_YP, false).ID: return 9269; case Observer::Observer(eBlockFace::BLOCK_FACE_YM, true).ID: return 9270; case Observer::Observer(eBlockFace::BLOCK_FACE_YM, false).ID: return 9271; case Obsidian::Obsidian().ID: return 1434; case OrangeBanner::OrangeBanner(0).ID: return 7913; case OrangeBanner::OrangeBanner(1).ID: return 7914; case OrangeBanner::OrangeBanner(2).ID: return 7915; case OrangeBanner::OrangeBanner(3).ID: return 7916; case OrangeBanner::OrangeBanner(4).ID: return 7917; case OrangeBanner::OrangeBanner(5).ID: return 7918; case OrangeBanner::OrangeBanner(6).ID: return 7919; case OrangeBanner::OrangeBanner(7).ID: return 7920; case OrangeBanner::OrangeBanner(8).ID: return 7921; case OrangeBanner::OrangeBanner(9).ID: return 7922; case OrangeBanner::OrangeBanner(10).ID: return 7923; case OrangeBanner::OrangeBanner(11).ID: return 7924; case OrangeBanner::OrangeBanner(12).ID: return 7925; case OrangeBanner::OrangeBanner(13).ID: return 7926; case OrangeBanner::OrangeBanner(14).ID: return 7927; case OrangeBanner::OrangeBanner(15).ID: return 7928; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_ZM, true, OrangeBed::Part::Head).ID: return 1065; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_ZM, true, OrangeBed::Part::Foot).ID: return 1066; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_ZM, false, OrangeBed::Part::Head).ID: return 1067; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_ZM, false, OrangeBed::Part::Foot).ID: return 1068; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_ZP, true, OrangeBed::Part::Head).ID: return 1069; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_ZP, true, OrangeBed::Part::Foot).ID: return 1070; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_ZP, false, OrangeBed::Part::Head).ID: return 1071; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_ZP, false, OrangeBed::Part::Foot).ID: return 1072; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_XM, true, OrangeBed::Part::Head).ID: return 1073; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_XM, true, OrangeBed::Part::Foot).ID: return 1074; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_XM, false, OrangeBed::Part::Head).ID: return 1075; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_XM, false, OrangeBed::Part::Foot).ID: return 1076; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_XP, true, OrangeBed::Part::Head).ID: return 1077; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_XP, true, OrangeBed::Part::Foot).ID: return 1078; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_XP, false, OrangeBed::Part::Head).ID: return 1079; case OrangeBed::OrangeBed(eBlockFace::BLOCK_FACE_XP, false, OrangeBed::Part::Foot).ID: return 1080; case OrangeCarpet::OrangeCarpet().ID: return 7867; case OrangeConcrete::OrangeConcrete().ID: return 9439; case OrangeConcretePowder::OrangeConcretePowder().ID: return 9455; case OrangeGlazedTerracotta::OrangeGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 9378; case OrangeGlazedTerracotta::OrangeGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 9379; case OrangeGlazedTerracotta::OrangeGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 9380; case OrangeGlazedTerracotta::OrangeGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 9381; case OrangeShulkerBox::OrangeShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 9284; case OrangeShulkerBox::OrangeShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 9285; case OrangeShulkerBox::OrangeShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 9286; case OrangeShulkerBox::OrangeShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 9287; case OrangeShulkerBox::OrangeShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 9288; case OrangeShulkerBox::OrangeShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 9289; case OrangeStainedGlass::OrangeStainedGlass().ID: return 4096; case OrangeStainedGlassPane::OrangeStainedGlassPane(true, true, true, true).ID: return 6897; case OrangeStainedGlassPane::OrangeStainedGlassPane(true, true, true, false).ID: return 6898; case OrangeStainedGlassPane::OrangeStainedGlassPane(true, true, false, true).ID: return 6901; case OrangeStainedGlassPane::OrangeStainedGlassPane(true, true, false, false).ID: return 6902; case OrangeStainedGlassPane::OrangeStainedGlassPane(true, false, true, true).ID: return 6905; case OrangeStainedGlassPane::OrangeStainedGlassPane(true, false, true, false).ID: return 6906; case OrangeStainedGlassPane::OrangeStainedGlassPane(true, false, false, true).ID: return 6909; case OrangeStainedGlassPane::OrangeStainedGlassPane(true, false, false, false).ID: return 6910; case OrangeStainedGlassPane::OrangeStainedGlassPane(false, true, true, true).ID: return 6913; case OrangeStainedGlassPane::OrangeStainedGlassPane(false, true, true, false).ID: return 6914; case OrangeStainedGlassPane::OrangeStainedGlassPane(false, true, false, true).ID: return 6917; case OrangeStainedGlassPane::OrangeStainedGlassPane(false, true, false, false).ID: return 6918; case OrangeStainedGlassPane::OrangeStainedGlassPane(false, false, true, true).ID: return 6921; case OrangeStainedGlassPane::OrangeStainedGlassPane(false, false, true, false).ID: return 6922; case OrangeStainedGlassPane::OrangeStainedGlassPane(false, false, false, true).ID: return 6925; case OrangeStainedGlassPane::OrangeStainedGlassPane(false, false, false, false).ID: return 6926; case OrangeTerracotta::OrangeTerracotta().ID: return 6848; case OrangeTulip::OrangeTulip().ID: return 1418; case OrangeWallBanner::OrangeWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 8157; case OrangeWallBanner::OrangeWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 8158; case OrangeWallBanner::OrangeWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 8159; case OrangeWallBanner::OrangeWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 8160; case OrangeWool::OrangeWool().ID: return 1385; case OxeyeDaisy::OxeyeDaisy().ID: return 1421; case PackedIce::PackedIce().ID: return 7884; case Peony::Peony(Peony::Half::Upper).ID: return 7891; case Peony::Peony(Peony::Half::Lower).ID: return 7892; case PetrifiedOakSlab::PetrifiedOakSlab(PetrifiedOakSlab::Type::Top).ID: return 8361; case PetrifiedOakSlab::PetrifiedOakSlab(PetrifiedOakSlab::Type::Bottom).ID: return 8363; case PetrifiedOakSlab::PetrifiedOakSlab(PetrifiedOakSlab::Type::Double).ID: return 8365; case PinkBanner::PinkBanner(0).ID: return 7993; case PinkBanner::PinkBanner(1).ID: return 7994; case PinkBanner::PinkBanner(2).ID: return 7995; case PinkBanner::PinkBanner(3).ID: return 7996; case PinkBanner::PinkBanner(4).ID: return 7997; case PinkBanner::PinkBanner(5).ID: return 7998; case PinkBanner::PinkBanner(6).ID: return 7999; case PinkBanner::PinkBanner(7).ID: return 8000; case PinkBanner::PinkBanner(8).ID: return 8001; case PinkBanner::PinkBanner(9).ID: return 8002; case PinkBanner::PinkBanner(10).ID: return 8003; case PinkBanner::PinkBanner(11).ID: return 8004; case PinkBanner::PinkBanner(12).ID: return 8005; case PinkBanner::PinkBanner(13).ID: return 8006; case PinkBanner::PinkBanner(14).ID: return 8007; case PinkBanner::PinkBanner(15).ID: return 8008; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_ZM, true, PinkBed::Part::Head).ID: return 1145; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_ZM, true, PinkBed::Part::Foot).ID: return 1146; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_ZM, false, PinkBed::Part::Head).ID: return 1147; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_ZM, false, PinkBed::Part::Foot).ID: return 1148; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_ZP, true, PinkBed::Part::Head).ID: return 1149; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_ZP, true, PinkBed::Part::Foot).ID: return 1150; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_ZP, false, PinkBed::Part::Head).ID: return 1151; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_ZP, false, PinkBed::Part::Foot).ID: return 1152; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_XM, true, PinkBed::Part::Head).ID: return 1153; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_XM, true, PinkBed::Part::Foot).ID: return 1154; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_XM, false, PinkBed::Part::Head).ID: return 1155; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_XM, false, PinkBed::Part::Foot).ID: return 1156; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_XP, true, PinkBed::Part::Head).ID: return 1157; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_XP, true, PinkBed::Part::Foot).ID: return 1158; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_XP, false, PinkBed::Part::Head).ID: return 1159; case PinkBed::PinkBed(eBlockFace::BLOCK_FACE_XP, false, PinkBed::Part::Foot).ID: return 1160; case PinkCarpet::PinkCarpet().ID: return 7872; case PinkConcrete::PinkConcrete().ID: return 9444; case PinkConcretePowder::PinkConcretePowder().ID: return 9460; case PinkGlazedTerracotta::PinkGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 9398; case PinkGlazedTerracotta::PinkGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 9399; case PinkGlazedTerracotta::PinkGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 9400; case PinkGlazedTerracotta::PinkGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 9401; case PinkShulkerBox::PinkShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 9314; case PinkShulkerBox::PinkShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 9315; case PinkShulkerBox::PinkShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 9316; case PinkShulkerBox::PinkShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 9317; case PinkShulkerBox::PinkShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 9318; case PinkShulkerBox::PinkShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 9319; case PinkStainedGlass::PinkStainedGlass().ID: return 4101; case PinkStainedGlassPane::PinkStainedGlassPane(true, true, true, true).ID: return 7057; case PinkStainedGlassPane::PinkStainedGlassPane(true, true, true, false).ID: return 7058; case PinkStainedGlassPane::PinkStainedGlassPane(true, true, false, true).ID: return 7061; case PinkStainedGlassPane::PinkStainedGlassPane(true, true, false, false).ID: return 7062; case PinkStainedGlassPane::PinkStainedGlassPane(true, false, true, true).ID: return 7065; case PinkStainedGlassPane::PinkStainedGlassPane(true, false, true, false).ID: return 7066; case PinkStainedGlassPane::PinkStainedGlassPane(true, false, false, true).ID: return 7069; case PinkStainedGlassPane::PinkStainedGlassPane(true, false, false, false).ID: return 7070; case PinkStainedGlassPane::PinkStainedGlassPane(false, true, true, true).ID: return 7073; case PinkStainedGlassPane::PinkStainedGlassPane(false, true, true, false).ID: return 7074; case PinkStainedGlassPane::PinkStainedGlassPane(false, true, false, true).ID: return 7077; case PinkStainedGlassPane::PinkStainedGlassPane(false, true, false, false).ID: return 7078; case PinkStainedGlassPane::PinkStainedGlassPane(false, false, true, true).ID: return 7081; case PinkStainedGlassPane::PinkStainedGlassPane(false, false, true, false).ID: return 7082; case PinkStainedGlassPane::PinkStainedGlassPane(false, false, false, true).ID: return 7085; case PinkStainedGlassPane::PinkStainedGlassPane(false, false, false, false).ID: return 7086; case PinkTerracotta::PinkTerracotta().ID: return 6853; case PinkTulip::PinkTulip().ID: return 1420; case PinkWallBanner::PinkWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 8177; case PinkWallBanner::PinkWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 8178; case PinkWallBanner::PinkWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 8179; case PinkWallBanner::PinkWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 8180; case PinkWool::PinkWool().ID: return 1390; case Piston::Piston(true, eBlockFace::BLOCK_FACE_ZM).ID: return 1348; case Piston::Piston(true, eBlockFace::BLOCK_FACE_XP).ID: return 1349; case Piston::Piston(true, eBlockFace::BLOCK_FACE_ZP).ID: return 1350; case Piston::Piston(true, eBlockFace::BLOCK_FACE_XM).ID: return 1351; case Piston::Piston(true, eBlockFace::BLOCK_FACE_YP).ID: return 1352; case Piston::Piston(true, eBlockFace::BLOCK_FACE_YM).ID: return 1353; case Piston::Piston(false, eBlockFace::BLOCK_FACE_ZM).ID: return 1354; case Piston::Piston(false, eBlockFace::BLOCK_FACE_XP).ID: return 1355; case Piston::Piston(false, eBlockFace::BLOCK_FACE_ZP).ID: return 1356; case Piston::Piston(false, eBlockFace::BLOCK_FACE_XM).ID: return 1357; case Piston::Piston(false, eBlockFace::BLOCK_FACE_YP).ID: return 1358; case Piston::Piston(false, eBlockFace::BLOCK_FACE_YM).ID: return 1359; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_ZM, true, PistonHead::Type::Normal).ID: return 1360; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_ZM, true, PistonHead::Type::Sticky).ID: return 1361; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_ZM, false, PistonHead::Type::Normal).ID: return 1362; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_ZM, false, PistonHead::Type::Sticky).ID: return 1363; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_XP, true, PistonHead::Type::Normal).ID: return 1364; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_XP, true, PistonHead::Type::Sticky).ID: return 1365; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_XP, false, PistonHead::Type::Normal).ID: return 1366; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_XP, false, PistonHead::Type::Sticky).ID: return 1367; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_ZP, true, PistonHead::Type::Normal).ID: return 1368; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_ZP, true, PistonHead::Type::Sticky).ID: return 1369; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_ZP, false, PistonHead::Type::Normal).ID: return 1370; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_ZP, false, PistonHead::Type::Sticky).ID: return 1371; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_XM, true, PistonHead::Type::Normal).ID: return 1372; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_XM, true, PistonHead::Type::Sticky).ID: return 1373; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_XM, false, PistonHead::Type::Normal).ID: return 1374; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_XM, false, PistonHead::Type::Sticky).ID: return 1375; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_YP, true, PistonHead::Type::Normal).ID: return 1376; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_YP, true, PistonHead::Type::Sticky).ID: return 1377; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_YP, false, PistonHead::Type::Normal).ID: return 1378; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_YP, false, PistonHead::Type::Sticky).ID: return 1379; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_YM, true, PistonHead::Type::Normal).ID: return 1380; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_YM, true, PistonHead::Type::Sticky).ID: return 1381; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_YM, false, PistonHead::Type::Normal).ID: return 1382; case PistonHead::PistonHead(eBlockFace::BLOCK_FACE_YM, false, PistonHead::Type::Sticky).ID: return 1383; case PlayerHead::PlayerHead(0).ID: return 6550; case PlayerHead::PlayerHead(1).ID: return 6551; case PlayerHead::PlayerHead(2).ID: return 6552; case PlayerHead::PlayerHead(3).ID: return 6553; case PlayerHead::PlayerHead(4).ID: return 6554; case PlayerHead::PlayerHead(5).ID: return 6555; case PlayerHead::PlayerHead(6).ID: return 6556; case PlayerHead::PlayerHead(7).ID: return 6557; case PlayerHead::PlayerHead(8).ID: return 6558; case PlayerHead::PlayerHead(9).ID: return 6559; case PlayerHead::PlayerHead(10).ID: return 6560; case PlayerHead::PlayerHead(11).ID: return 6561; case PlayerHead::PlayerHead(12).ID: return 6562; case PlayerHead::PlayerHead(13).ID: return 6563; case PlayerHead::PlayerHead(14).ID: return 6564; case PlayerHead::PlayerHead(15).ID: return 6565; case PlayerWallHead::PlayerWallHead(eBlockFace::BLOCK_FACE_ZM).ID: return 6566; case PlayerWallHead::PlayerWallHead(eBlockFace::BLOCK_FACE_ZP).ID: return 6567; case PlayerWallHead::PlayerWallHead(eBlockFace::BLOCK_FACE_XM).ID: return 6568; case PlayerWallHead::PlayerWallHead(eBlockFace::BLOCK_FACE_XP).ID: return 6569; case Podzol::Podzol(true).ID: return 12; case Podzol::Podzol(false).ID: return 13; case PolishedAndesite::PolishedAndesite().ID: return 7; case PolishedAndesiteSlab::PolishedAndesiteSlab(PolishedAndesiteSlab::Type::Top).ID: return 10856; case PolishedAndesiteSlab::PolishedAndesiteSlab(PolishedAndesiteSlab::Type::Bottom).ID: return 10858; case PolishedAndesiteSlab::PolishedAndesiteSlab(PolishedAndesiteSlab::Type::Double).ID: return 10860; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedAndesiteStairs::Half::Top, PolishedAndesiteStairs::Shape::Straight).ID: return 10630; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedAndesiteStairs::Half::Top, PolishedAndesiteStairs::Shape::InnerLeft).ID: return 10632; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedAndesiteStairs::Half::Top, PolishedAndesiteStairs::Shape::InnerRight).ID: return 10634; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedAndesiteStairs::Half::Top, PolishedAndesiteStairs::Shape::OuterLeft).ID: return 10636; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedAndesiteStairs::Half::Top, PolishedAndesiteStairs::Shape::OuterRight).ID: return 10638; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedAndesiteStairs::Half::Bottom, PolishedAndesiteStairs::Shape::Straight).ID: return 10640; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedAndesiteStairs::Half::Bottom, PolishedAndesiteStairs::Shape::InnerLeft).ID: return 10642; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedAndesiteStairs::Half::Bottom, PolishedAndesiteStairs::Shape::InnerRight).ID: return 10644; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedAndesiteStairs::Half::Bottom, PolishedAndesiteStairs::Shape::OuterLeft).ID: return 10646; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedAndesiteStairs::Half::Bottom, PolishedAndesiteStairs::Shape::OuterRight).ID: return 10648; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedAndesiteStairs::Half::Top, PolishedAndesiteStairs::Shape::Straight).ID: return 10650; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedAndesiteStairs::Half::Top, PolishedAndesiteStairs::Shape::InnerLeft).ID: return 10652; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedAndesiteStairs::Half::Top, PolishedAndesiteStairs::Shape::InnerRight).ID: return 10654; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedAndesiteStairs::Half::Top, PolishedAndesiteStairs::Shape::OuterLeft).ID: return 10656; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedAndesiteStairs::Half::Top, PolishedAndesiteStairs::Shape::OuterRight).ID: return 10658; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedAndesiteStairs::Half::Bottom, PolishedAndesiteStairs::Shape::Straight).ID: return 10660; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedAndesiteStairs::Half::Bottom, PolishedAndesiteStairs::Shape::InnerLeft).ID: return 10662; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedAndesiteStairs::Half::Bottom, PolishedAndesiteStairs::Shape::InnerRight).ID: return 10664; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedAndesiteStairs::Half::Bottom, PolishedAndesiteStairs::Shape::OuterLeft).ID: return 10666; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedAndesiteStairs::Half::Bottom, PolishedAndesiteStairs::Shape::OuterRight).ID: return 10668; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_XM, PolishedAndesiteStairs::Half::Top, PolishedAndesiteStairs::Shape::Straight).ID: return 10670; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_XM, PolishedAndesiteStairs::Half::Top, PolishedAndesiteStairs::Shape::InnerLeft).ID: return 10672; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_XM, PolishedAndesiteStairs::Half::Top, PolishedAndesiteStairs::Shape::InnerRight).ID: return 10674; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_XM, PolishedAndesiteStairs::Half::Top, PolishedAndesiteStairs::Shape::OuterLeft).ID: return 10676; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_XM, PolishedAndesiteStairs::Half::Top, PolishedAndesiteStairs::Shape::OuterRight).ID: return 10678; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_XM, PolishedAndesiteStairs::Half::Bottom, PolishedAndesiteStairs::Shape::Straight).ID: return 10680; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_XM, PolishedAndesiteStairs::Half::Bottom, PolishedAndesiteStairs::Shape::InnerLeft).ID: return 10682; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_XM, PolishedAndesiteStairs::Half::Bottom, PolishedAndesiteStairs::Shape::InnerRight).ID: return 10684; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_XM, PolishedAndesiteStairs::Half::Bottom, PolishedAndesiteStairs::Shape::OuterLeft).ID: return 10686; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_XM, PolishedAndesiteStairs::Half::Bottom, PolishedAndesiteStairs::Shape::OuterRight).ID: return 10688; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_XP, PolishedAndesiteStairs::Half::Top, PolishedAndesiteStairs::Shape::Straight).ID: return 10690; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_XP, PolishedAndesiteStairs::Half::Top, PolishedAndesiteStairs::Shape::InnerLeft).ID: return 10692; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_XP, PolishedAndesiteStairs::Half::Top, PolishedAndesiteStairs::Shape::InnerRight).ID: return 10694; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_XP, PolishedAndesiteStairs::Half::Top, PolishedAndesiteStairs::Shape::OuterLeft).ID: return 10696; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_XP, PolishedAndesiteStairs::Half::Top, PolishedAndesiteStairs::Shape::OuterRight).ID: return 10698; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_XP, PolishedAndesiteStairs::Half::Bottom, PolishedAndesiteStairs::Shape::Straight).ID: return 10700; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_XP, PolishedAndesiteStairs::Half::Bottom, PolishedAndesiteStairs::Shape::InnerLeft).ID: return 10702; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_XP, PolishedAndesiteStairs::Half::Bottom, PolishedAndesiteStairs::Shape::InnerRight).ID: return 10704; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_XP, PolishedAndesiteStairs::Half::Bottom, PolishedAndesiteStairs::Shape::OuterLeft).ID: return 10706; case PolishedAndesiteStairs::PolishedAndesiteStairs(eBlockFace::BLOCK_FACE_XP, PolishedAndesiteStairs::Half::Bottom, PolishedAndesiteStairs::Shape::OuterRight).ID: return 10708; case PolishedBasalt::PolishedBasalt(PolishedBasalt::Axis::X).ID: return 4005; case PolishedBasalt::PolishedBasalt(PolishedBasalt::Axis::Y).ID: return 4006; case PolishedBasalt::PolishedBasalt(PolishedBasalt::Axis::Z).ID: return 4007; case PolishedBlackstone::PolishedBlackstone().ID: return 16250; case PolishedBlackstoneBrickSlab::PolishedBlackstoneBrickSlab(PolishedBlackstoneBrickSlab::Type::Top).ID: return 16255; case PolishedBlackstoneBrickSlab::PolishedBlackstoneBrickSlab(PolishedBlackstoneBrickSlab::Type::Bottom).ID: return 16257; case PolishedBlackstoneBrickSlab::PolishedBlackstoneBrickSlab(PolishedBlackstoneBrickSlab::Type::Double).ID: return 16259; case PolishedBlackstoneBrickStairs::PolishedBlackstoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, PolishedBlackstoneBrickStairs::Half::Top, PolishedBlackstoneBrickStairs::Shape::Straight).ID: return 16261; case PolishedBlackstoneBrickStairs::PolishedBlackstoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, PolishedBlackstoneBrickStairs::Half::Top, PolishedBlackstoneBrickStairs::Shape::InnerLeft).ID: return 16263; case PolishedBlackstoneBrickStairs::PolishedBlackstoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, PolishedBlackstoneBrickStairs::Half::Top, PolishedBlackstoneBrickStairs::Shape::InnerRight).ID: return 16265; case PolishedBlackstoneBrickStairs::PolishedBlackstoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, PolishedBlackstoneBrickStairs::Half::Top, PolishedBlackstoneBrickStairs::Shape::OuterLeft).ID: return 16267; case PolishedBlackstoneBrickStairs::PolishedBlackstoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, PolishedBlackstoneBrickStairs::Half::Top, PolishedBlackstoneBrickStairs::Shape::OuterRight).ID: return 16269; case PolishedBlackstoneBrickStairs::PolishedBlackstoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, PolishedBlackstoneBrickStairs::Half::Bottom, PolishedBlackstoneBrickStairs::Shape::Straight).ID: return 16271; case PolishedBlackstoneBrickStairs::PolishedBlackstoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, PolishedBlackstoneBrickStairs::Half::Bottom, PolishedBlackstoneBrickStairs::Shape::InnerLeft).ID: return 16273; case PolishedBlackstoneBrickStairs::PolishedBlackstoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, PolishedBlackstoneBrickStairs::Half::Bottom, PolishedBlackstoneBrickStairs::Shape::InnerRight).ID: return 16275; case PolishedBlackstoneBrickStairs::PolishedBlackstoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, PolishedBlackstoneBrickStairs::Half::Bottom, PolishedBlackstoneBrickStairs::Shape::OuterLeft).ID: return 16277; case PolishedBlackstoneBrickStairs::PolishedBlackstoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, PolishedBlackstoneBrickStairs::Half::Bottom, PolishedBlackstoneBrickStairs::Shape::OuterRight).ID: return 16279; case PolishedBlackstoneBrickStairs::PolishedBlackstoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, PolishedBlackstoneBrickStairs::Half::Top, PolishedBlackstoneBrickStairs::Shape::Straight).ID: return 16281; case PolishedBlackstoneBrickStairs::PolishedBlackstoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, PolishedBlackstoneBrickStairs::Half::Top, PolishedBlackstoneBrickStairs::Shape::InnerLeft).ID: return 16283; case PolishedBlackstoneBrickStairs::PolishedBlackstoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, PolishedBlackstoneBrickStairs::Half::Top, PolishedBlackstoneBrickStairs::Shape::InnerRight).ID: return 16285; case PolishedBlackstoneBrickStairs::PolishedBlackstoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, PolishedBlackstoneBrickStairs::Half::Top, PolishedBlackstoneBrickStairs::Shape::OuterLeft).ID: return 16287; case PolishedBlackstoneBrickStairs::PolishedBlackstoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, PolishedBlackstoneBrickStairs::Half::Top, PolishedBlackstoneBrickStairs::Shape::OuterRight).ID: return 16289; case PolishedBlackstoneBrickStairs::PolishedBlackstoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, PolishedBlackstoneBrickStairs::Half::Bottom, PolishedBlackstoneBrickStairs::Shape::Straight).ID: return 16291; case PolishedBlackstoneBrickStairs::PolishedBlackstoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, PolishedBlackstoneBrickStairs::Half::Bottom, PolishedBlackstoneBrickStairs::Shape::InnerLeft).ID: return 16293; case PolishedBlackstoneBrickStairs::PolishedBlackstoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, PolishedBlackstoneBrickStairs::Half::Bottom, PolishedBlackstoneBrickStairs::Shape::InnerRight).ID: return 16295; case PolishedBlackstoneBrickStairs::PolishedBlackstoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, PolishedBlackstoneBrickStairs::Half::Bottom, PolishedBlackstoneBrickStairs::Shape::OuterLeft).ID: return 16297; case PolishedBlackstoneBrickStairs::PolishedBlackstoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, PolishedBlackstoneBrickStairs::Half::Bottom, PolishedBlackstoneBrickStairs::Shape::OuterRight).ID: return 16299; case PolishedBlackstoneBrickStairs::PolishedBlackstoneBrickStairs(eBlockFace::BLOCK_FACE_XM, PolishedBlackstoneBrickStairs::Half::Top, PolishedBlackstoneBrickStairs::Shape::Straight).ID: return 16301; case PolishedBlackstoneBrickStairs::PolishedBlackstoneBrickStairs(eBlockFace::BLOCK_FACE_XM, PolishedBlackstoneBrickStairs::Half::Top, PolishedBlackstoneBrickStairs::Shape::InnerLeft).ID: return 16303; case PolishedBlackstoneBrickStairs::PolishedBlackstoneBrickStairs(eBlockFace::BLOCK_FACE_XM, PolishedBlackstoneBrickStairs::Half::Top, PolishedBlackstoneBrickStairs::Shape::InnerRight).ID: return 16305; case PolishedBlackstoneBrickStairs::PolishedBlackstoneBrickStairs(eBlockFace::BLOCK_FACE_XM, PolishedBlackstoneBrickStairs::Half::Top, PolishedBlackstoneBrickStairs::Shape::OuterLeft).ID: return 16307; case PolishedBlackstoneBrickStairs::PolishedBlackstoneBrickStairs(eBlockFace::BLOCK_FACE_XM, PolishedBlackstoneBrickStairs::Half::Top, PolishedBlackstoneBrickStairs::Shape::OuterRight).ID: return 16309; case PolishedBlackstoneBrickStairs::PolishedBlackstoneBrickStairs(eBlockFace::BLOCK_FACE_XM, PolishedBlackstoneBrickStairs::Half::Bottom, PolishedBlackstoneBrickStairs::Shape::Straight).ID: return 16311; case PolishedBlackstoneBrickStairs::PolishedBlackstoneBrickStairs(eBlockFace::BLOCK_FACE_XM, PolishedBlackstoneBrickStairs::Half::Bottom, PolishedBlackstoneBrickStairs::Shape::InnerLeft).ID: return 16313; case PolishedBlackstoneBrickStairs::PolishedBlackstoneBrickStairs(eBlockFace::BLOCK_FACE_XM, PolishedBlackstoneBrickStairs::Half::Bottom, PolishedBlackstoneBrickStairs::Shape::InnerRight).ID: return 16315; case PolishedBlackstoneBrickStairs::PolishedBlackstoneBrickStairs(eBlockFace::BLOCK_FACE_XM, PolishedBlackstoneBrickStairs::Half::Bottom, PolishedBlackstoneBrickStairs::Shape::OuterLeft).ID: return 16317; case PolishedBlackstoneBrickStairs::PolishedBlackstoneBrickStairs(eBlockFace::BLOCK_FACE_XM, PolishedBlackstoneBrickStairs::Half::Bottom, PolishedBlackstoneBrickStairs::Shape::OuterRight).ID: return 16319; case PolishedBlackstoneBrickStairs::PolishedBlackstoneBrickStairs(eBlockFace::BLOCK_FACE_XP, PolishedBlackstoneBrickStairs::Half::Top, PolishedBlackstoneBrickStairs::Shape::Straight).ID: return 16321; case PolishedBlackstoneBrickStairs::PolishedBlackstoneBrickStairs(eBlockFace::BLOCK_FACE_XP, PolishedBlackstoneBrickStairs::Half::Top, PolishedBlackstoneBrickStairs::Shape::InnerLeft).ID: return 16323; case PolishedBlackstoneBrickStairs::PolishedBlackstoneBrickStairs(eBlockFace::BLOCK_FACE_XP, PolishedBlackstoneBrickStairs::Half::Top, PolishedBlackstoneBrickStairs::Shape::InnerRight).ID: return 16325; case PolishedBlackstoneBrickStairs::PolishedBlackstoneBrickStairs(eBlockFace::BLOCK_FACE_XP, PolishedBlackstoneBrickStairs::Half::Top, PolishedBlackstoneBrickStairs::Shape::OuterLeft).ID: return 16327; case PolishedBlackstoneBrickStairs::PolishedBlackstoneBrickStairs(eBlockFace::BLOCK_FACE_XP, PolishedBlackstoneBrickStairs::Half::Top, PolishedBlackstoneBrickStairs::Shape::OuterRight).ID: return 16329; case PolishedBlackstoneBrickStairs::PolishedBlackstoneBrickStairs(eBlockFace::BLOCK_FACE_XP, PolishedBlackstoneBrickStairs::Half::Bottom, PolishedBlackstoneBrickStairs::Shape::Straight).ID: return 16331; case PolishedBlackstoneBrickStairs::PolishedBlackstoneBrickStairs(eBlockFace::BLOCK_FACE_XP, PolishedBlackstoneBrickStairs::Half::Bottom, PolishedBlackstoneBrickStairs::Shape::InnerLeft).ID: return 16333; case PolishedBlackstoneBrickStairs::PolishedBlackstoneBrickStairs(eBlockFace::BLOCK_FACE_XP, PolishedBlackstoneBrickStairs::Half::Bottom, PolishedBlackstoneBrickStairs::Shape::InnerRight).ID: return 16335; case PolishedBlackstoneBrickStairs::PolishedBlackstoneBrickStairs(eBlockFace::BLOCK_FACE_XP, PolishedBlackstoneBrickStairs::Half::Bottom, PolishedBlackstoneBrickStairs::Shape::OuterLeft).ID: return 16337; case PolishedBlackstoneBrickStairs::PolishedBlackstoneBrickStairs(eBlockFace::BLOCK_FACE_XP, PolishedBlackstoneBrickStairs::Half::Bottom, PolishedBlackstoneBrickStairs::Shape::OuterRight).ID: return 16339; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::None, PolishedBlackstoneBrickWall::North::None, PolishedBlackstoneBrickWall::South::None, true, PolishedBlackstoneBrickWall::West::None).ID: return 16343; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::None, PolishedBlackstoneBrickWall::North::None, PolishedBlackstoneBrickWall::South::None, true, PolishedBlackstoneBrickWall::West::Low).ID: return 16344; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::None, PolishedBlackstoneBrickWall::North::None, PolishedBlackstoneBrickWall::South::None, true, PolishedBlackstoneBrickWall::West::Tall).ID: return 16345; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::None, PolishedBlackstoneBrickWall::North::None, PolishedBlackstoneBrickWall::South::None, false, PolishedBlackstoneBrickWall::West::None).ID: return 16349; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::None, PolishedBlackstoneBrickWall::North::None, PolishedBlackstoneBrickWall::South::None, false, PolishedBlackstoneBrickWall::West::Low).ID: return 16350; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::None, PolishedBlackstoneBrickWall::North::None, PolishedBlackstoneBrickWall::South::None, false, PolishedBlackstoneBrickWall::West::Tall).ID: return 16351; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::None, PolishedBlackstoneBrickWall::North::None, PolishedBlackstoneBrickWall::South::Low, true, PolishedBlackstoneBrickWall::West::None).ID: return 16355; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::None, PolishedBlackstoneBrickWall::North::None, PolishedBlackstoneBrickWall::South::Low, true, PolishedBlackstoneBrickWall::West::Low).ID: return 16356; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::None, PolishedBlackstoneBrickWall::North::None, PolishedBlackstoneBrickWall::South::Low, true, PolishedBlackstoneBrickWall::West::Tall).ID: return 16357; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::None, PolishedBlackstoneBrickWall::North::None, PolishedBlackstoneBrickWall::South::Low, false, PolishedBlackstoneBrickWall::West::None).ID: return 16361; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::None, PolishedBlackstoneBrickWall::North::None, PolishedBlackstoneBrickWall::South::Low, false, PolishedBlackstoneBrickWall::West::Low).ID: return 16362; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::None, PolishedBlackstoneBrickWall::North::None, PolishedBlackstoneBrickWall::South::Low, false, PolishedBlackstoneBrickWall::West::Tall).ID: return 16363; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::None, PolishedBlackstoneBrickWall::North::None, PolishedBlackstoneBrickWall::South::Tall, true, PolishedBlackstoneBrickWall::West::None).ID: return 16367; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::None, PolishedBlackstoneBrickWall::North::None, PolishedBlackstoneBrickWall::South::Tall, true, PolishedBlackstoneBrickWall::West::Low).ID: return 16368; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::None, PolishedBlackstoneBrickWall::North::None, PolishedBlackstoneBrickWall::South::Tall, true, PolishedBlackstoneBrickWall::West::Tall).ID: return 16369; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::None, PolishedBlackstoneBrickWall::North::None, PolishedBlackstoneBrickWall::South::Tall, false, PolishedBlackstoneBrickWall::West::None).ID: return 16373; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::None, PolishedBlackstoneBrickWall::North::None, PolishedBlackstoneBrickWall::South::Tall, false, PolishedBlackstoneBrickWall::West::Low).ID: return 16374; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::None, PolishedBlackstoneBrickWall::North::None, PolishedBlackstoneBrickWall::South::Tall, false, PolishedBlackstoneBrickWall::West::Tall).ID: return 16375; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::None, PolishedBlackstoneBrickWall::North::Low, PolishedBlackstoneBrickWall::South::None, true, PolishedBlackstoneBrickWall::West::None).ID: return 16379; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::None, PolishedBlackstoneBrickWall::North::Low, PolishedBlackstoneBrickWall::South::None, true, PolishedBlackstoneBrickWall::West::Low).ID: return 16380; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::None, PolishedBlackstoneBrickWall::North::Low, PolishedBlackstoneBrickWall::South::None, true, PolishedBlackstoneBrickWall::West::Tall).ID: return 16381; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::None, PolishedBlackstoneBrickWall::North::Low, PolishedBlackstoneBrickWall::South::None, false, PolishedBlackstoneBrickWall::West::None).ID: return 16385; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::None, PolishedBlackstoneBrickWall::North::Low, PolishedBlackstoneBrickWall::South::None, false, PolishedBlackstoneBrickWall::West::Low).ID: return 16386; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::None, PolishedBlackstoneBrickWall::North::Low, PolishedBlackstoneBrickWall::South::None, false, PolishedBlackstoneBrickWall::West::Tall).ID: return 16387; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::None, PolishedBlackstoneBrickWall::North::Low, PolishedBlackstoneBrickWall::South::Low, true, PolishedBlackstoneBrickWall::West::None).ID: return 16391; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::None, PolishedBlackstoneBrickWall::North::Low, PolishedBlackstoneBrickWall::South::Low, true, PolishedBlackstoneBrickWall::West::Low).ID: return 16392; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::None, PolishedBlackstoneBrickWall::North::Low, PolishedBlackstoneBrickWall::South::Low, true, PolishedBlackstoneBrickWall::West::Tall).ID: return 16393; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::None, PolishedBlackstoneBrickWall::North::Low, PolishedBlackstoneBrickWall::South::Low, false, PolishedBlackstoneBrickWall::West::None).ID: return 16397; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::None, PolishedBlackstoneBrickWall::North::Low, PolishedBlackstoneBrickWall::South::Low, false, PolishedBlackstoneBrickWall::West::Low).ID: return 16398; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::None, PolishedBlackstoneBrickWall::North::Low, PolishedBlackstoneBrickWall::South::Low, false, PolishedBlackstoneBrickWall::West::Tall).ID: return 16399; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::None, PolishedBlackstoneBrickWall::North::Low, PolishedBlackstoneBrickWall::South::Tall, true, PolishedBlackstoneBrickWall::West::None).ID: return 16403; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::None, PolishedBlackstoneBrickWall::North::Low, PolishedBlackstoneBrickWall::South::Tall, true, PolishedBlackstoneBrickWall::West::Low).ID: return 16404; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::None, PolishedBlackstoneBrickWall::North::Low, PolishedBlackstoneBrickWall::South::Tall, true, PolishedBlackstoneBrickWall::West::Tall).ID: return 16405; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::None, PolishedBlackstoneBrickWall::North::Low, PolishedBlackstoneBrickWall::South::Tall, false, PolishedBlackstoneBrickWall::West::None).ID: return 16409; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::None, PolishedBlackstoneBrickWall::North::Low, PolishedBlackstoneBrickWall::South::Tall, false, PolishedBlackstoneBrickWall::West::Low).ID: return 16410; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::None, PolishedBlackstoneBrickWall::North::Low, PolishedBlackstoneBrickWall::South::Tall, false, PolishedBlackstoneBrickWall::West::Tall).ID: return 16411; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::None, PolishedBlackstoneBrickWall::North::Tall, PolishedBlackstoneBrickWall::South::None, true, PolishedBlackstoneBrickWall::West::None).ID: return 16415; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::None, PolishedBlackstoneBrickWall::North::Tall, PolishedBlackstoneBrickWall::South::None, true, PolishedBlackstoneBrickWall::West::Low).ID: return 16416; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::None, PolishedBlackstoneBrickWall::North::Tall, PolishedBlackstoneBrickWall::South::None, true, PolishedBlackstoneBrickWall::West::Tall).ID: return 16417; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::None, PolishedBlackstoneBrickWall::North::Tall, PolishedBlackstoneBrickWall::South::None, false, PolishedBlackstoneBrickWall::West::None).ID: return 16421; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::None, PolishedBlackstoneBrickWall::North::Tall, PolishedBlackstoneBrickWall::South::None, false, PolishedBlackstoneBrickWall::West::Low).ID: return 16422; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::None, PolishedBlackstoneBrickWall::North::Tall, PolishedBlackstoneBrickWall::South::None, false, PolishedBlackstoneBrickWall::West::Tall).ID: return 16423; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::None, PolishedBlackstoneBrickWall::North::Tall, PolishedBlackstoneBrickWall::South::Low, true, PolishedBlackstoneBrickWall::West::None).ID: return 16427; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::None, PolishedBlackstoneBrickWall::North::Tall, PolishedBlackstoneBrickWall::South::Low, true, PolishedBlackstoneBrickWall::West::Low).ID: return 16428; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::None, PolishedBlackstoneBrickWall::North::Tall, PolishedBlackstoneBrickWall::South::Low, true, PolishedBlackstoneBrickWall::West::Tall).ID: return 16429; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::None, PolishedBlackstoneBrickWall::North::Tall, PolishedBlackstoneBrickWall::South::Low, false, PolishedBlackstoneBrickWall::West::None).ID: return 16433; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::None, PolishedBlackstoneBrickWall::North::Tall, PolishedBlackstoneBrickWall::South::Low, false, PolishedBlackstoneBrickWall::West::Low).ID: return 16434; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::None, PolishedBlackstoneBrickWall::North::Tall, PolishedBlackstoneBrickWall::South::Low, false, PolishedBlackstoneBrickWall::West::Tall).ID: return 16435; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::None, PolishedBlackstoneBrickWall::North::Tall, PolishedBlackstoneBrickWall::South::Tall, true, PolishedBlackstoneBrickWall::West::None).ID: return 16439; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::None, PolishedBlackstoneBrickWall::North::Tall, PolishedBlackstoneBrickWall::South::Tall, true, PolishedBlackstoneBrickWall::West::Low).ID: return 16440; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::None, PolishedBlackstoneBrickWall::North::Tall, PolishedBlackstoneBrickWall::South::Tall, true, PolishedBlackstoneBrickWall::West::Tall).ID: return 16441; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::None, PolishedBlackstoneBrickWall::North::Tall, PolishedBlackstoneBrickWall::South::Tall, false, PolishedBlackstoneBrickWall::West::None).ID: return 16445; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::None, PolishedBlackstoneBrickWall::North::Tall, PolishedBlackstoneBrickWall::South::Tall, false, PolishedBlackstoneBrickWall::West::Low).ID: return 16446; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::None, PolishedBlackstoneBrickWall::North::Tall, PolishedBlackstoneBrickWall::South::Tall, false, PolishedBlackstoneBrickWall::West::Tall).ID: return 16447; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Low, PolishedBlackstoneBrickWall::North::None, PolishedBlackstoneBrickWall::South::None, true, PolishedBlackstoneBrickWall::West::None).ID: return 16451; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Low, PolishedBlackstoneBrickWall::North::None, PolishedBlackstoneBrickWall::South::None, true, PolishedBlackstoneBrickWall::West::Low).ID: return 16452; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Low, PolishedBlackstoneBrickWall::North::None, PolishedBlackstoneBrickWall::South::None, true, PolishedBlackstoneBrickWall::West::Tall).ID: return 16453; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Low, PolishedBlackstoneBrickWall::North::None, PolishedBlackstoneBrickWall::South::None, false, PolishedBlackstoneBrickWall::West::None).ID: return 16457; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Low, PolishedBlackstoneBrickWall::North::None, PolishedBlackstoneBrickWall::South::None, false, PolishedBlackstoneBrickWall::West::Low).ID: return 16458; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Low, PolishedBlackstoneBrickWall::North::None, PolishedBlackstoneBrickWall::South::None, false, PolishedBlackstoneBrickWall::West::Tall).ID: return 16459; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Low, PolishedBlackstoneBrickWall::North::None, PolishedBlackstoneBrickWall::South::Low, true, PolishedBlackstoneBrickWall::West::None).ID: return 16463; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Low, PolishedBlackstoneBrickWall::North::None, PolishedBlackstoneBrickWall::South::Low, true, PolishedBlackstoneBrickWall::West::Low).ID: return 16464; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Low, PolishedBlackstoneBrickWall::North::None, PolishedBlackstoneBrickWall::South::Low, true, PolishedBlackstoneBrickWall::West::Tall).ID: return 16465; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Low, PolishedBlackstoneBrickWall::North::None, PolishedBlackstoneBrickWall::South::Low, false, PolishedBlackstoneBrickWall::West::None).ID: return 16469; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Low, PolishedBlackstoneBrickWall::North::None, PolishedBlackstoneBrickWall::South::Low, false, PolishedBlackstoneBrickWall::West::Low).ID: return 16470; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Low, PolishedBlackstoneBrickWall::North::None, PolishedBlackstoneBrickWall::South::Low, false, PolishedBlackstoneBrickWall::West::Tall).ID: return 16471; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Low, PolishedBlackstoneBrickWall::North::None, PolishedBlackstoneBrickWall::South::Tall, true, PolishedBlackstoneBrickWall::West::None).ID: return 16475; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Low, PolishedBlackstoneBrickWall::North::None, PolishedBlackstoneBrickWall::South::Tall, true, PolishedBlackstoneBrickWall::West::Low).ID: return 16476; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Low, PolishedBlackstoneBrickWall::North::None, PolishedBlackstoneBrickWall::South::Tall, true, PolishedBlackstoneBrickWall::West::Tall).ID: return 16477; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Low, PolishedBlackstoneBrickWall::North::None, PolishedBlackstoneBrickWall::South::Tall, false, PolishedBlackstoneBrickWall::West::None).ID: return 16481; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Low, PolishedBlackstoneBrickWall::North::None, PolishedBlackstoneBrickWall::South::Tall, false, PolishedBlackstoneBrickWall::West::Low).ID: return 16482; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Low, PolishedBlackstoneBrickWall::North::None, PolishedBlackstoneBrickWall::South::Tall, false, PolishedBlackstoneBrickWall::West::Tall).ID: return 16483; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Low, PolishedBlackstoneBrickWall::North::Low, PolishedBlackstoneBrickWall::South::None, true, PolishedBlackstoneBrickWall::West::None).ID: return 16487; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Low, PolishedBlackstoneBrickWall::North::Low, PolishedBlackstoneBrickWall::South::None, true, PolishedBlackstoneBrickWall::West::Low).ID: return 16488; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Low, PolishedBlackstoneBrickWall::North::Low, PolishedBlackstoneBrickWall::South::None, true, PolishedBlackstoneBrickWall::West::Tall).ID: return 16489; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Low, PolishedBlackstoneBrickWall::North::Low, PolishedBlackstoneBrickWall::South::None, false, PolishedBlackstoneBrickWall::West::None).ID: return 16493; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Low, PolishedBlackstoneBrickWall::North::Low, PolishedBlackstoneBrickWall::South::None, false, PolishedBlackstoneBrickWall::West::Low).ID: return 16494; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Low, PolishedBlackstoneBrickWall::North::Low, PolishedBlackstoneBrickWall::South::None, false, PolishedBlackstoneBrickWall::West::Tall).ID: return 16495; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Low, PolishedBlackstoneBrickWall::North::Low, PolishedBlackstoneBrickWall::South::Low, true, PolishedBlackstoneBrickWall::West::None).ID: return 16499; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Low, PolishedBlackstoneBrickWall::North::Low, PolishedBlackstoneBrickWall::South::Low, true, PolishedBlackstoneBrickWall::West::Low).ID: return 16500; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Low, PolishedBlackstoneBrickWall::North::Low, PolishedBlackstoneBrickWall::South::Low, true, PolishedBlackstoneBrickWall::West::Tall).ID: return 16501; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Low, PolishedBlackstoneBrickWall::North::Low, PolishedBlackstoneBrickWall::South::Low, false, PolishedBlackstoneBrickWall::West::None).ID: return 16505; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Low, PolishedBlackstoneBrickWall::North::Low, PolishedBlackstoneBrickWall::South::Low, false, PolishedBlackstoneBrickWall::West::Low).ID: return 16506; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Low, PolishedBlackstoneBrickWall::North::Low, PolishedBlackstoneBrickWall::South::Low, false, PolishedBlackstoneBrickWall::West::Tall).ID: return 16507; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Low, PolishedBlackstoneBrickWall::North::Low, PolishedBlackstoneBrickWall::South::Tall, true, PolishedBlackstoneBrickWall::West::None).ID: return 16511; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Low, PolishedBlackstoneBrickWall::North::Low, PolishedBlackstoneBrickWall::South::Tall, true, PolishedBlackstoneBrickWall::West::Low).ID: return 16512; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Low, PolishedBlackstoneBrickWall::North::Low, PolishedBlackstoneBrickWall::South::Tall, true, PolishedBlackstoneBrickWall::West::Tall).ID: return 16513; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Low, PolishedBlackstoneBrickWall::North::Low, PolishedBlackstoneBrickWall::South::Tall, false, PolishedBlackstoneBrickWall::West::None).ID: return 16517; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Low, PolishedBlackstoneBrickWall::North::Low, PolishedBlackstoneBrickWall::South::Tall, false, PolishedBlackstoneBrickWall::West::Low).ID: return 16518; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Low, PolishedBlackstoneBrickWall::North::Low, PolishedBlackstoneBrickWall::South::Tall, false, PolishedBlackstoneBrickWall::West::Tall).ID: return 16519; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Low, PolishedBlackstoneBrickWall::North::Tall, PolishedBlackstoneBrickWall::South::None, true, PolishedBlackstoneBrickWall::West::None).ID: return 16523; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Low, PolishedBlackstoneBrickWall::North::Tall, PolishedBlackstoneBrickWall::South::None, true, PolishedBlackstoneBrickWall::West::Low).ID: return 16524; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Low, PolishedBlackstoneBrickWall::North::Tall, PolishedBlackstoneBrickWall::South::None, true, PolishedBlackstoneBrickWall::West::Tall).ID: return 16525; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Low, PolishedBlackstoneBrickWall::North::Tall, PolishedBlackstoneBrickWall::South::None, false, PolishedBlackstoneBrickWall::West::None).ID: return 16529; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Low, PolishedBlackstoneBrickWall::North::Tall, PolishedBlackstoneBrickWall::South::None, false, PolishedBlackstoneBrickWall::West::Low).ID: return 16530; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Low, PolishedBlackstoneBrickWall::North::Tall, PolishedBlackstoneBrickWall::South::None, false, PolishedBlackstoneBrickWall::West::Tall).ID: return 16531; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Low, PolishedBlackstoneBrickWall::North::Tall, PolishedBlackstoneBrickWall::South::Low, true, PolishedBlackstoneBrickWall::West::None).ID: return 16535; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Low, PolishedBlackstoneBrickWall::North::Tall, PolishedBlackstoneBrickWall::South::Low, true, PolishedBlackstoneBrickWall::West::Low).ID: return 16536; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Low, PolishedBlackstoneBrickWall::North::Tall, PolishedBlackstoneBrickWall::South::Low, true, PolishedBlackstoneBrickWall::West::Tall).ID: return 16537; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Low, PolishedBlackstoneBrickWall::North::Tall, PolishedBlackstoneBrickWall::South::Low, false, PolishedBlackstoneBrickWall::West::None).ID: return 16541; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Low, PolishedBlackstoneBrickWall::North::Tall, PolishedBlackstoneBrickWall::South::Low, false, PolishedBlackstoneBrickWall::West::Low).ID: return 16542; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Low, PolishedBlackstoneBrickWall::North::Tall, PolishedBlackstoneBrickWall::South::Low, false, PolishedBlackstoneBrickWall::West::Tall).ID: return 16543; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Low, PolishedBlackstoneBrickWall::North::Tall, PolishedBlackstoneBrickWall::South::Tall, true, PolishedBlackstoneBrickWall::West::None).ID: return 16547; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Low, PolishedBlackstoneBrickWall::North::Tall, PolishedBlackstoneBrickWall::South::Tall, true, PolishedBlackstoneBrickWall::West::Low).ID: return 16548; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Low, PolishedBlackstoneBrickWall::North::Tall, PolishedBlackstoneBrickWall::South::Tall, true, PolishedBlackstoneBrickWall::West::Tall).ID: return 16549; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Low, PolishedBlackstoneBrickWall::North::Tall, PolishedBlackstoneBrickWall::South::Tall, false, PolishedBlackstoneBrickWall::West::None).ID: return 16553; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Low, PolishedBlackstoneBrickWall::North::Tall, PolishedBlackstoneBrickWall::South::Tall, false, PolishedBlackstoneBrickWall::West::Low).ID: return 16554; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Low, PolishedBlackstoneBrickWall::North::Tall, PolishedBlackstoneBrickWall::South::Tall, false, PolishedBlackstoneBrickWall::West::Tall).ID: return 16555; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Tall, PolishedBlackstoneBrickWall::North::None, PolishedBlackstoneBrickWall::South::None, true, PolishedBlackstoneBrickWall::West::None).ID: return 16559; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Tall, PolishedBlackstoneBrickWall::North::None, PolishedBlackstoneBrickWall::South::None, true, PolishedBlackstoneBrickWall::West::Low).ID: return 16560; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Tall, PolishedBlackstoneBrickWall::North::None, PolishedBlackstoneBrickWall::South::None, true, PolishedBlackstoneBrickWall::West::Tall).ID: return 16561; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Tall, PolishedBlackstoneBrickWall::North::None, PolishedBlackstoneBrickWall::South::None, false, PolishedBlackstoneBrickWall::West::None).ID: return 16565; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Tall, PolishedBlackstoneBrickWall::North::None, PolishedBlackstoneBrickWall::South::None, false, PolishedBlackstoneBrickWall::West::Low).ID: return 16566; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Tall, PolishedBlackstoneBrickWall::North::None, PolishedBlackstoneBrickWall::South::None, false, PolishedBlackstoneBrickWall::West::Tall).ID: return 16567; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Tall, PolishedBlackstoneBrickWall::North::None, PolishedBlackstoneBrickWall::South::Low, true, PolishedBlackstoneBrickWall::West::None).ID: return 16571; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Tall, PolishedBlackstoneBrickWall::North::None, PolishedBlackstoneBrickWall::South::Low, true, PolishedBlackstoneBrickWall::West::Low).ID: return 16572; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Tall, PolishedBlackstoneBrickWall::North::None, PolishedBlackstoneBrickWall::South::Low, true, PolishedBlackstoneBrickWall::West::Tall).ID: return 16573; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Tall, PolishedBlackstoneBrickWall::North::None, PolishedBlackstoneBrickWall::South::Low, false, PolishedBlackstoneBrickWall::West::None).ID: return 16577; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Tall, PolishedBlackstoneBrickWall::North::None, PolishedBlackstoneBrickWall::South::Low, false, PolishedBlackstoneBrickWall::West::Low).ID: return 16578; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Tall, PolishedBlackstoneBrickWall::North::None, PolishedBlackstoneBrickWall::South::Low, false, PolishedBlackstoneBrickWall::West::Tall).ID: return 16579; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Tall, PolishedBlackstoneBrickWall::North::None, PolishedBlackstoneBrickWall::South::Tall, true, PolishedBlackstoneBrickWall::West::None).ID: return 16583; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Tall, PolishedBlackstoneBrickWall::North::None, PolishedBlackstoneBrickWall::South::Tall, true, PolishedBlackstoneBrickWall::West::Low).ID: return 16584; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Tall, PolishedBlackstoneBrickWall::North::None, PolishedBlackstoneBrickWall::South::Tall, true, PolishedBlackstoneBrickWall::West::Tall).ID: return 16585; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Tall, PolishedBlackstoneBrickWall::North::None, PolishedBlackstoneBrickWall::South::Tall, false, PolishedBlackstoneBrickWall::West::None).ID: return 16589; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Tall, PolishedBlackstoneBrickWall::North::None, PolishedBlackstoneBrickWall::South::Tall, false, PolishedBlackstoneBrickWall::West::Low).ID: return 16590; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Tall, PolishedBlackstoneBrickWall::North::None, PolishedBlackstoneBrickWall::South::Tall, false, PolishedBlackstoneBrickWall::West::Tall).ID: return 16591; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Tall, PolishedBlackstoneBrickWall::North::Low, PolishedBlackstoneBrickWall::South::None, true, PolishedBlackstoneBrickWall::West::None).ID: return 16595; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Tall, PolishedBlackstoneBrickWall::North::Low, PolishedBlackstoneBrickWall::South::None, true, PolishedBlackstoneBrickWall::West::Low).ID: return 16596; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Tall, PolishedBlackstoneBrickWall::North::Low, PolishedBlackstoneBrickWall::South::None, true, PolishedBlackstoneBrickWall::West::Tall).ID: return 16597; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Tall, PolishedBlackstoneBrickWall::North::Low, PolishedBlackstoneBrickWall::South::None, false, PolishedBlackstoneBrickWall::West::None).ID: return 16601; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Tall, PolishedBlackstoneBrickWall::North::Low, PolishedBlackstoneBrickWall::South::None, false, PolishedBlackstoneBrickWall::West::Low).ID: return 16602; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Tall, PolishedBlackstoneBrickWall::North::Low, PolishedBlackstoneBrickWall::South::None, false, PolishedBlackstoneBrickWall::West::Tall).ID: return 16603; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Tall, PolishedBlackstoneBrickWall::North::Low, PolishedBlackstoneBrickWall::South::Low, true, PolishedBlackstoneBrickWall::West::None).ID: return 16607; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Tall, PolishedBlackstoneBrickWall::North::Low, PolishedBlackstoneBrickWall::South::Low, true, PolishedBlackstoneBrickWall::West::Low).ID: return 16608; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Tall, PolishedBlackstoneBrickWall::North::Low, PolishedBlackstoneBrickWall::South::Low, true, PolishedBlackstoneBrickWall::West::Tall).ID: return 16609; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Tall, PolishedBlackstoneBrickWall::North::Low, PolishedBlackstoneBrickWall::South::Low, false, PolishedBlackstoneBrickWall::West::None).ID: return 16613; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Tall, PolishedBlackstoneBrickWall::North::Low, PolishedBlackstoneBrickWall::South::Low, false, PolishedBlackstoneBrickWall::West::Low).ID: return 16614; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Tall, PolishedBlackstoneBrickWall::North::Low, PolishedBlackstoneBrickWall::South::Low, false, PolishedBlackstoneBrickWall::West::Tall).ID: return 16615; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Tall, PolishedBlackstoneBrickWall::North::Low, PolishedBlackstoneBrickWall::South::Tall, true, PolishedBlackstoneBrickWall::West::None).ID: return 16619; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Tall, PolishedBlackstoneBrickWall::North::Low, PolishedBlackstoneBrickWall::South::Tall, true, PolishedBlackstoneBrickWall::West::Low).ID: return 16620; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Tall, PolishedBlackstoneBrickWall::North::Low, PolishedBlackstoneBrickWall::South::Tall, true, PolishedBlackstoneBrickWall::West::Tall).ID: return 16621; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Tall, PolishedBlackstoneBrickWall::North::Low, PolishedBlackstoneBrickWall::South::Tall, false, PolishedBlackstoneBrickWall::West::None).ID: return 16625; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Tall, PolishedBlackstoneBrickWall::North::Low, PolishedBlackstoneBrickWall::South::Tall, false, PolishedBlackstoneBrickWall::West::Low).ID: return 16626; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Tall, PolishedBlackstoneBrickWall::North::Low, PolishedBlackstoneBrickWall::South::Tall, false, PolishedBlackstoneBrickWall::West::Tall).ID: return 16627; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Tall, PolishedBlackstoneBrickWall::North::Tall, PolishedBlackstoneBrickWall::South::None, true, PolishedBlackstoneBrickWall::West::None).ID: return 16631; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Tall, PolishedBlackstoneBrickWall::North::Tall, PolishedBlackstoneBrickWall::South::None, true, PolishedBlackstoneBrickWall::West::Low).ID: return 16632; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Tall, PolishedBlackstoneBrickWall::North::Tall, PolishedBlackstoneBrickWall::South::None, true, PolishedBlackstoneBrickWall::West::Tall).ID: return 16633; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Tall, PolishedBlackstoneBrickWall::North::Tall, PolishedBlackstoneBrickWall::South::None, false, PolishedBlackstoneBrickWall::West::None).ID: return 16637; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Tall, PolishedBlackstoneBrickWall::North::Tall, PolishedBlackstoneBrickWall::South::None, false, PolishedBlackstoneBrickWall::West::Low).ID: return 16638; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Tall, PolishedBlackstoneBrickWall::North::Tall, PolishedBlackstoneBrickWall::South::None, false, PolishedBlackstoneBrickWall::West::Tall).ID: return 16639; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Tall, PolishedBlackstoneBrickWall::North::Tall, PolishedBlackstoneBrickWall::South::Low, true, PolishedBlackstoneBrickWall::West::None).ID: return 16643; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Tall, PolishedBlackstoneBrickWall::North::Tall, PolishedBlackstoneBrickWall::South::Low, true, PolishedBlackstoneBrickWall::West::Low).ID: return 16644; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Tall, PolishedBlackstoneBrickWall::North::Tall, PolishedBlackstoneBrickWall::South::Low, true, PolishedBlackstoneBrickWall::West::Tall).ID: return 16645; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Tall, PolishedBlackstoneBrickWall::North::Tall, PolishedBlackstoneBrickWall::South::Low, false, PolishedBlackstoneBrickWall::West::None).ID: return 16649; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Tall, PolishedBlackstoneBrickWall::North::Tall, PolishedBlackstoneBrickWall::South::Low, false, PolishedBlackstoneBrickWall::West::Low).ID: return 16650; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Tall, PolishedBlackstoneBrickWall::North::Tall, PolishedBlackstoneBrickWall::South::Low, false, PolishedBlackstoneBrickWall::West::Tall).ID: return 16651; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Tall, PolishedBlackstoneBrickWall::North::Tall, PolishedBlackstoneBrickWall::South::Tall, true, PolishedBlackstoneBrickWall::West::None).ID: return 16655; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Tall, PolishedBlackstoneBrickWall::North::Tall, PolishedBlackstoneBrickWall::South::Tall, true, PolishedBlackstoneBrickWall::West::Low).ID: return 16656; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Tall, PolishedBlackstoneBrickWall::North::Tall, PolishedBlackstoneBrickWall::South::Tall, true, PolishedBlackstoneBrickWall::West::Tall).ID: return 16657; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Tall, PolishedBlackstoneBrickWall::North::Tall, PolishedBlackstoneBrickWall::South::Tall, false, PolishedBlackstoneBrickWall::West::None).ID: return 16661; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Tall, PolishedBlackstoneBrickWall::North::Tall, PolishedBlackstoneBrickWall::South::Tall, false, PolishedBlackstoneBrickWall::West::Low).ID: return 16662; case PolishedBlackstoneBrickWall::PolishedBlackstoneBrickWall(PolishedBlackstoneBrickWall::East::Tall, PolishedBlackstoneBrickWall::North::Tall, PolishedBlackstoneBrickWall::South::Tall, false, PolishedBlackstoneBrickWall::West::Tall).ID: return 16663; case PolishedBlackstoneBricks::PolishedBlackstoneBricks().ID: return 16251; case PolishedBlackstoneButton::PolishedBlackstoneButton(PolishedBlackstoneButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, true).ID: return 16753; case PolishedBlackstoneButton::PolishedBlackstoneButton(PolishedBlackstoneButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, false).ID: return 16754; case PolishedBlackstoneButton::PolishedBlackstoneButton(PolishedBlackstoneButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, true).ID: return 16755; case PolishedBlackstoneButton::PolishedBlackstoneButton(PolishedBlackstoneButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, false).ID: return 16756; case PolishedBlackstoneButton::PolishedBlackstoneButton(PolishedBlackstoneButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, true).ID: return 16757; case PolishedBlackstoneButton::PolishedBlackstoneButton(PolishedBlackstoneButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, false).ID: return 16758; case PolishedBlackstoneButton::PolishedBlackstoneButton(PolishedBlackstoneButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, true).ID: return 16759; case PolishedBlackstoneButton::PolishedBlackstoneButton(PolishedBlackstoneButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, false).ID: return 16760; case PolishedBlackstoneButton::PolishedBlackstoneButton(PolishedBlackstoneButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, true).ID: return 16761; case PolishedBlackstoneButton::PolishedBlackstoneButton(PolishedBlackstoneButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, false).ID: return 16762; case PolishedBlackstoneButton::PolishedBlackstoneButton(PolishedBlackstoneButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, true).ID: return 16763; case PolishedBlackstoneButton::PolishedBlackstoneButton(PolishedBlackstoneButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, false).ID: return 16764; case PolishedBlackstoneButton::PolishedBlackstoneButton(PolishedBlackstoneButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, true).ID: return 16765; case PolishedBlackstoneButton::PolishedBlackstoneButton(PolishedBlackstoneButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, false).ID: return 16766; case PolishedBlackstoneButton::PolishedBlackstoneButton(PolishedBlackstoneButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, true).ID: return 16767; case PolishedBlackstoneButton::PolishedBlackstoneButton(PolishedBlackstoneButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, false).ID: return 16768; case PolishedBlackstoneButton::PolishedBlackstoneButton(PolishedBlackstoneButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, true).ID: return 16769; case PolishedBlackstoneButton::PolishedBlackstoneButton(PolishedBlackstoneButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, false).ID: return 16770; case PolishedBlackstoneButton::PolishedBlackstoneButton(PolishedBlackstoneButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, true).ID: return 16771; case PolishedBlackstoneButton::PolishedBlackstoneButton(PolishedBlackstoneButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, false).ID: return 16772; case PolishedBlackstoneButton::PolishedBlackstoneButton(PolishedBlackstoneButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, true).ID: return 16773; case PolishedBlackstoneButton::PolishedBlackstoneButton(PolishedBlackstoneButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, false).ID: return 16774; case PolishedBlackstoneButton::PolishedBlackstoneButton(PolishedBlackstoneButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, true).ID: return 16775; case PolishedBlackstoneButton::PolishedBlackstoneButton(PolishedBlackstoneButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, false).ID: return 16776; case PolishedBlackstonePressurePlate::PolishedBlackstonePressurePlate(true).ID: return 16751; case PolishedBlackstonePressurePlate::PolishedBlackstonePressurePlate(false).ID: return 16752; case PolishedBlackstoneSlab::PolishedBlackstoneSlab(PolishedBlackstoneSlab::Type::Top).ID: return 16746; case PolishedBlackstoneSlab::PolishedBlackstoneSlab(PolishedBlackstoneSlab::Type::Bottom).ID: return 16748; case PolishedBlackstoneSlab::PolishedBlackstoneSlab(PolishedBlackstoneSlab::Type::Double).ID: return 16750; case PolishedBlackstoneStairs::PolishedBlackstoneStairs(eBlockFace::BLOCK_FACE_ZM, PolishedBlackstoneStairs::Half::Top, PolishedBlackstoneStairs::Shape::Straight).ID: return 16666; case PolishedBlackstoneStairs::PolishedBlackstoneStairs(eBlockFace::BLOCK_FACE_ZM, PolishedBlackstoneStairs::Half::Top, PolishedBlackstoneStairs::Shape::InnerLeft).ID: return 16668; case PolishedBlackstoneStairs::PolishedBlackstoneStairs(eBlockFace::BLOCK_FACE_ZM, PolishedBlackstoneStairs::Half::Top, PolishedBlackstoneStairs::Shape::InnerRight).ID: return 16670; case PolishedBlackstoneStairs::PolishedBlackstoneStairs(eBlockFace::BLOCK_FACE_ZM, PolishedBlackstoneStairs::Half::Top, PolishedBlackstoneStairs::Shape::OuterLeft).ID: return 16672; case PolishedBlackstoneStairs::PolishedBlackstoneStairs(eBlockFace::BLOCK_FACE_ZM, PolishedBlackstoneStairs::Half::Top, PolishedBlackstoneStairs::Shape::OuterRight).ID: return 16674; case PolishedBlackstoneStairs::PolishedBlackstoneStairs(eBlockFace::BLOCK_FACE_ZM, PolishedBlackstoneStairs::Half::Bottom, PolishedBlackstoneStairs::Shape::Straight).ID: return 16676; case PolishedBlackstoneStairs::PolishedBlackstoneStairs(eBlockFace::BLOCK_FACE_ZM, PolishedBlackstoneStairs::Half::Bottom, PolishedBlackstoneStairs::Shape::InnerLeft).ID: return 16678; case PolishedBlackstoneStairs::PolishedBlackstoneStairs(eBlockFace::BLOCK_FACE_ZM, PolishedBlackstoneStairs::Half::Bottom, PolishedBlackstoneStairs::Shape::InnerRight).ID: return 16680; case PolishedBlackstoneStairs::PolishedBlackstoneStairs(eBlockFace::BLOCK_FACE_ZM, PolishedBlackstoneStairs::Half::Bottom, PolishedBlackstoneStairs::Shape::OuterLeft).ID: return 16682; case PolishedBlackstoneStairs::PolishedBlackstoneStairs(eBlockFace::BLOCK_FACE_ZM, PolishedBlackstoneStairs::Half::Bottom, PolishedBlackstoneStairs::Shape::OuterRight).ID: return 16684; case PolishedBlackstoneStairs::PolishedBlackstoneStairs(eBlockFace::BLOCK_FACE_ZP, PolishedBlackstoneStairs::Half::Top, PolishedBlackstoneStairs::Shape::Straight).ID: return 16686; case PolishedBlackstoneStairs::PolishedBlackstoneStairs(eBlockFace::BLOCK_FACE_ZP, PolishedBlackstoneStairs::Half::Top, PolishedBlackstoneStairs::Shape::InnerLeft).ID: return 16688; case PolishedBlackstoneStairs::PolishedBlackstoneStairs(eBlockFace::BLOCK_FACE_ZP, PolishedBlackstoneStairs::Half::Top, PolishedBlackstoneStairs::Shape::InnerRight).ID: return 16690; case PolishedBlackstoneStairs::PolishedBlackstoneStairs(eBlockFace::BLOCK_FACE_ZP, PolishedBlackstoneStairs::Half::Top, PolishedBlackstoneStairs::Shape::OuterLeft).ID: return 16692; case PolishedBlackstoneStairs::PolishedBlackstoneStairs(eBlockFace::BLOCK_FACE_ZP, PolishedBlackstoneStairs::Half::Top, PolishedBlackstoneStairs::Shape::OuterRight).ID: return 16694; case PolishedBlackstoneStairs::PolishedBlackstoneStairs(eBlockFace::BLOCK_FACE_ZP, PolishedBlackstoneStairs::Half::Bottom, PolishedBlackstoneStairs::Shape::Straight).ID: return 16696; case PolishedBlackstoneStairs::PolishedBlackstoneStairs(eBlockFace::BLOCK_FACE_ZP, PolishedBlackstoneStairs::Half::Bottom, PolishedBlackstoneStairs::Shape::InnerLeft).ID: return 16698; case PolishedBlackstoneStairs::PolishedBlackstoneStairs(eBlockFace::BLOCK_FACE_ZP, PolishedBlackstoneStairs::Half::Bottom, PolishedBlackstoneStairs::Shape::InnerRight).ID: return 16700; case PolishedBlackstoneStairs::PolishedBlackstoneStairs(eBlockFace::BLOCK_FACE_ZP, PolishedBlackstoneStairs::Half::Bottom, PolishedBlackstoneStairs::Shape::OuterLeft).ID: return 16702; case PolishedBlackstoneStairs::PolishedBlackstoneStairs(eBlockFace::BLOCK_FACE_ZP, PolishedBlackstoneStairs::Half::Bottom, PolishedBlackstoneStairs::Shape::OuterRight).ID: return 16704; case PolishedBlackstoneStairs::PolishedBlackstoneStairs(eBlockFace::BLOCK_FACE_XM, PolishedBlackstoneStairs::Half::Top, PolishedBlackstoneStairs::Shape::Straight).ID: return 16706; case PolishedBlackstoneStairs::PolishedBlackstoneStairs(eBlockFace::BLOCK_FACE_XM, PolishedBlackstoneStairs::Half::Top, PolishedBlackstoneStairs::Shape::InnerLeft).ID: return 16708; case PolishedBlackstoneStairs::PolishedBlackstoneStairs(eBlockFace::BLOCK_FACE_XM, PolishedBlackstoneStairs::Half::Top, PolishedBlackstoneStairs::Shape::InnerRight).ID: return 16710; case PolishedBlackstoneStairs::PolishedBlackstoneStairs(eBlockFace::BLOCK_FACE_XM, PolishedBlackstoneStairs::Half::Top, PolishedBlackstoneStairs::Shape::OuterLeft).ID: return 16712; case PolishedBlackstoneStairs::PolishedBlackstoneStairs(eBlockFace::BLOCK_FACE_XM, PolishedBlackstoneStairs::Half::Top, PolishedBlackstoneStairs::Shape::OuterRight).ID: return 16714; case PolishedBlackstoneStairs::PolishedBlackstoneStairs(eBlockFace::BLOCK_FACE_XM, PolishedBlackstoneStairs::Half::Bottom, PolishedBlackstoneStairs::Shape::Straight).ID: return 16716; case PolishedBlackstoneStairs::PolishedBlackstoneStairs(eBlockFace::BLOCK_FACE_XM, PolishedBlackstoneStairs::Half::Bottom, PolishedBlackstoneStairs::Shape::InnerLeft).ID: return 16718; case PolishedBlackstoneStairs::PolishedBlackstoneStairs(eBlockFace::BLOCK_FACE_XM, PolishedBlackstoneStairs::Half::Bottom, PolishedBlackstoneStairs::Shape::InnerRight).ID: return 16720; case PolishedBlackstoneStairs::PolishedBlackstoneStairs(eBlockFace::BLOCK_FACE_XM, PolishedBlackstoneStairs::Half::Bottom, PolishedBlackstoneStairs::Shape::OuterLeft).ID: return 16722; case PolishedBlackstoneStairs::PolishedBlackstoneStairs(eBlockFace::BLOCK_FACE_XM, PolishedBlackstoneStairs::Half::Bottom, PolishedBlackstoneStairs::Shape::OuterRight).ID: return 16724; case PolishedBlackstoneStairs::PolishedBlackstoneStairs(eBlockFace::BLOCK_FACE_XP, PolishedBlackstoneStairs::Half::Top, PolishedBlackstoneStairs::Shape::Straight).ID: return 16726; case PolishedBlackstoneStairs::PolishedBlackstoneStairs(eBlockFace::BLOCK_FACE_XP, PolishedBlackstoneStairs::Half::Top, PolishedBlackstoneStairs::Shape::InnerLeft).ID: return 16728; case PolishedBlackstoneStairs::PolishedBlackstoneStairs(eBlockFace::BLOCK_FACE_XP, PolishedBlackstoneStairs::Half::Top, PolishedBlackstoneStairs::Shape::InnerRight).ID: return 16730; case PolishedBlackstoneStairs::PolishedBlackstoneStairs(eBlockFace::BLOCK_FACE_XP, PolishedBlackstoneStairs::Half::Top, PolishedBlackstoneStairs::Shape::OuterLeft).ID: return 16732; case PolishedBlackstoneStairs::PolishedBlackstoneStairs(eBlockFace::BLOCK_FACE_XP, PolishedBlackstoneStairs::Half::Top, PolishedBlackstoneStairs::Shape::OuterRight).ID: return 16734; case PolishedBlackstoneStairs::PolishedBlackstoneStairs(eBlockFace::BLOCK_FACE_XP, PolishedBlackstoneStairs::Half::Bottom, PolishedBlackstoneStairs::Shape::Straight).ID: return 16736; case PolishedBlackstoneStairs::PolishedBlackstoneStairs(eBlockFace::BLOCK_FACE_XP, PolishedBlackstoneStairs::Half::Bottom, PolishedBlackstoneStairs::Shape::InnerLeft).ID: return 16738; case PolishedBlackstoneStairs::PolishedBlackstoneStairs(eBlockFace::BLOCK_FACE_XP, PolishedBlackstoneStairs::Half::Bottom, PolishedBlackstoneStairs::Shape::InnerRight).ID: return 16740; case PolishedBlackstoneStairs::PolishedBlackstoneStairs(eBlockFace::BLOCK_FACE_XP, PolishedBlackstoneStairs::Half::Bottom, PolishedBlackstoneStairs::Shape::OuterLeft).ID: return 16742; case PolishedBlackstoneStairs::PolishedBlackstoneStairs(eBlockFace::BLOCK_FACE_XP, PolishedBlackstoneStairs::Half::Bottom, PolishedBlackstoneStairs::Shape::OuterRight).ID: return 16744; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::None, PolishedBlackstoneWall::North::None, PolishedBlackstoneWall::South::None, true, PolishedBlackstoneWall::West::None).ID: return 16780; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::None, PolishedBlackstoneWall::North::None, PolishedBlackstoneWall::South::None, true, PolishedBlackstoneWall::West::Low).ID: return 16781; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::None, PolishedBlackstoneWall::North::None, PolishedBlackstoneWall::South::None, true, PolishedBlackstoneWall::West::Tall).ID: return 16782; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::None, PolishedBlackstoneWall::North::None, PolishedBlackstoneWall::South::None, false, PolishedBlackstoneWall::West::None).ID: return 16786; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::None, PolishedBlackstoneWall::North::None, PolishedBlackstoneWall::South::None, false, PolishedBlackstoneWall::West::Low).ID: return 16787; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::None, PolishedBlackstoneWall::North::None, PolishedBlackstoneWall::South::None, false, PolishedBlackstoneWall::West::Tall).ID: return 16788; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::None, PolishedBlackstoneWall::North::None, PolishedBlackstoneWall::South::Low, true, PolishedBlackstoneWall::West::None).ID: return 16792; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::None, PolishedBlackstoneWall::North::None, PolishedBlackstoneWall::South::Low, true, PolishedBlackstoneWall::West::Low).ID: return 16793; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::None, PolishedBlackstoneWall::North::None, PolishedBlackstoneWall::South::Low, true, PolishedBlackstoneWall::West::Tall).ID: return 16794; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::None, PolishedBlackstoneWall::North::None, PolishedBlackstoneWall::South::Low, false, PolishedBlackstoneWall::West::None).ID: return 16798; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::None, PolishedBlackstoneWall::North::None, PolishedBlackstoneWall::South::Low, false, PolishedBlackstoneWall::West::Low).ID: return 16799; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::None, PolishedBlackstoneWall::North::None, PolishedBlackstoneWall::South::Low, false, PolishedBlackstoneWall::West::Tall).ID: return 16800; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::None, PolishedBlackstoneWall::North::None, PolishedBlackstoneWall::South::Tall, true, PolishedBlackstoneWall::West::None).ID: return 16804; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::None, PolishedBlackstoneWall::North::None, PolishedBlackstoneWall::South::Tall, true, PolishedBlackstoneWall::West::Low).ID: return 16805; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::None, PolishedBlackstoneWall::North::None, PolishedBlackstoneWall::South::Tall, true, PolishedBlackstoneWall::West::Tall).ID: return 16806; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::None, PolishedBlackstoneWall::North::None, PolishedBlackstoneWall::South::Tall, false, PolishedBlackstoneWall::West::None).ID: return 16810; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::None, PolishedBlackstoneWall::North::None, PolishedBlackstoneWall::South::Tall, false, PolishedBlackstoneWall::West::Low).ID: return 16811; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::None, PolishedBlackstoneWall::North::None, PolishedBlackstoneWall::South::Tall, false, PolishedBlackstoneWall::West::Tall).ID: return 16812; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::None, PolishedBlackstoneWall::North::Low, PolishedBlackstoneWall::South::None, true, PolishedBlackstoneWall::West::None).ID: return 16816; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::None, PolishedBlackstoneWall::North::Low, PolishedBlackstoneWall::South::None, true, PolishedBlackstoneWall::West::Low).ID: return 16817; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::None, PolishedBlackstoneWall::North::Low, PolishedBlackstoneWall::South::None, true, PolishedBlackstoneWall::West::Tall).ID: return 16818; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::None, PolishedBlackstoneWall::North::Low, PolishedBlackstoneWall::South::None, false, PolishedBlackstoneWall::West::None).ID: return 16822; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::None, PolishedBlackstoneWall::North::Low, PolishedBlackstoneWall::South::None, false, PolishedBlackstoneWall::West::Low).ID: return 16823; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::None, PolishedBlackstoneWall::North::Low, PolishedBlackstoneWall::South::None, false, PolishedBlackstoneWall::West::Tall).ID: return 16824; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::None, PolishedBlackstoneWall::North::Low, PolishedBlackstoneWall::South::Low, true, PolishedBlackstoneWall::West::None).ID: return 16828; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::None, PolishedBlackstoneWall::North::Low, PolishedBlackstoneWall::South::Low, true, PolishedBlackstoneWall::West::Low).ID: return 16829; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::None, PolishedBlackstoneWall::North::Low, PolishedBlackstoneWall::South::Low, true, PolishedBlackstoneWall::West::Tall).ID: return 16830; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::None, PolishedBlackstoneWall::North::Low, PolishedBlackstoneWall::South::Low, false, PolishedBlackstoneWall::West::None).ID: return 16834; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::None, PolishedBlackstoneWall::North::Low, PolishedBlackstoneWall::South::Low, false, PolishedBlackstoneWall::West::Low).ID: return 16835; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::None, PolishedBlackstoneWall::North::Low, PolishedBlackstoneWall::South::Low, false, PolishedBlackstoneWall::West::Tall).ID: return 16836; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::None, PolishedBlackstoneWall::North::Low, PolishedBlackstoneWall::South::Tall, true, PolishedBlackstoneWall::West::None).ID: return 16840; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::None, PolishedBlackstoneWall::North::Low, PolishedBlackstoneWall::South::Tall, true, PolishedBlackstoneWall::West::Low).ID: return 16841; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::None, PolishedBlackstoneWall::North::Low, PolishedBlackstoneWall::South::Tall, true, PolishedBlackstoneWall::West::Tall).ID: return 16842; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::None, PolishedBlackstoneWall::North::Low, PolishedBlackstoneWall::South::Tall, false, PolishedBlackstoneWall::West::None).ID: return 16846; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::None, PolishedBlackstoneWall::North::Low, PolishedBlackstoneWall::South::Tall, false, PolishedBlackstoneWall::West::Low).ID: return 16847; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::None, PolishedBlackstoneWall::North::Low, PolishedBlackstoneWall::South::Tall, false, PolishedBlackstoneWall::West::Tall).ID: return 16848; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::None, PolishedBlackstoneWall::North::Tall, PolishedBlackstoneWall::South::None, true, PolishedBlackstoneWall::West::None).ID: return 16852; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::None, PolishedBlackstoneWall::North::Tall, PolishedBlackstoneWall::South::None, true, PolishedBlackstoneWall::West::Low).ID: return 16853; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::None, PolishedBlackstoneWall::North::Tall, PolishedBlackstoneWall::South::None, true, PolishedBlackstoneWall::West::Tall).ID: return 16854; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::None, PolishedBlackstoneWall::North::Tall, PolishedBlackstoneWall::South::None, false, PolishedBlackstoneWall::West::None).ID: return 16858; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::None, PolishedBlackstoneWall::North::Tall, PolishedBlackstoneWall::South::None, false, PolishedBlackstoneWall::West::Low).ID: return 16859; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::None, PolishedBlackstoneWall::North::Tall, PolishedBlackstoneWall::South::None, false, PolishedBlackstoneWall::West::Tall).ID: return 16860; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::None, PolishedBlackstoneWall::North::Tall, PolishedBlackstoneWall::South::Low, true, PolishedBlackstoneWall::West::None).ID: return 16864; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::None, PolishedBlackstoneWall::North::Tall, PolishedBlackstoneWall::South::Low, true, PolishedBlackstoneWall::West::Low).ID: return 16865; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::None, PolishedBlackstoneWall::North::Tall, PolishedBlackstoneWall::South::Low, true, PolishedBlackstoneWall::West::Tall).ID: return 16866; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::None, PolishedBlackstoneWall::North::Tall, PolishedBlackstoneWall::South::Low, false, PolishedBlackstoneWall::West::None).ID: return 16870; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::None, PolishedBlackstoneWall::North::Tall, PolishedBlackstoneWall::South::Low, false, PolishedBlackstoneWall::West::Low).ID: return 16871; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::None, PolishedBlackstoneWall::North::Tall, PolishedBlackstoneWall::South::Low, false, PolishedBlackstoneWall::West::Tall).ID: return 16872; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::None, PolishedBlackstoneWall::North::Tall, PolishedBlackstoneWall::South::Tall, true, PolishedBlackstoneWall::West::None).ID: return 16876; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::None, PolishedBlackstoneWall::North::Tall, PolishedBlackstoneWall::South::Tall, true, PolishedBlackstoneWall::West::Low).ID: return 16877; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::None, PolishedBlackstoneWall::North::Tall, PolishedBlackstoneWall::South::Tall, true, PolishedBlackstoneWall::West::Tall).ID: return 16878; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::None, PolishedBlackstoneWall::North::Tall, PolishedBlackstoneWall::South::Tall, false, PolishedBlackstoneWall::West::None).ID: return 16882; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::None, PolishedBlackstoneWall::North::Tall, PolishedBlackstoneWall::South::Tall, false, PolishedBlackstoneWall::West::Low).ID: return 16883; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::None, PolishedBlackstoneWall::North::Tall, PolishedBlackstoneWall::South::Tall, false, PolishedBlackstoneWall::West::Tall).ID: return 16884; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Low, PolishedBlackstoneWall::North::None, PolishedBlackstoneWall::South::None, true, PolishedBlackstoneWall::West::None).ID: return 16888; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Low, PolishedBlackstoneWall::North::None, PolishedBlackstoneWall::South::None, true, PolishedBlackstoneWall::West::Low).ID: return 16889; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Low, PolishedBlackstoneWall::North::None, PolishedBlackstoneWall::South::None, true, PolishedBlackstoneWall::West::Tall).ID: return 16890; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Low, PolishedBlackstoneWall::North::None, PolishedBlackstoneWall::South::None, false, PolishedBlackstoneWall::West::None).ID: return 16894; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Low, PolishedBlackstoneWall::North::None, PolishedBlackstoneWall::South::None, false, PolishedBlackstoneWall::West::Low).ID: return 16895; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Low, PolishedBlackstoneWall::North::None, PolishedBlackstoneWall::South::None, false, PolishedBlackstoneWall::West::Tall).ID: return 16896; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Low, PolishedBlackstoneWall::North::None, PolishedBlackstoneWall::South::Low, true, PolishedBlackstoneWall::West::None).ID: return 16900; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Low, PolishedBlackstoneWall::North::None, PolishedBlackstoneWall::South::Low, true, PolishedBlackstoneWall::West::Low).ID: return 16901; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Low, PolishedBlackstoneWall::North::None, PolishedBlackstoneWall::South::Low, true, PolishedBlackstoneWall::West::Tall).ID: return 16902; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Low, PolishedBlackstoneWall::North::None, PolishedBlackstoneWall::South::Low, false, PolishedBlackstoneWall::West::None).ID: return 16906; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Low, PolishedBlackstoneWall::North::None, PolishedBlackstoneWall::South::Low, false, PolishedBlackstoneWall::West::Low).ID: return 16907; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Low, PolishedBlackstoneWall::North::None, PolishedBlackstoneWall::South::Low, false, PolishedBlackstoneWall::West::Tall).ID: return 16908; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Low, PolishedBlackstoneWall::North::None, PolishedBlackstoneWall::South::Tall, true, PolishedBlackstoneWall::West::None).ID: return 16912; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Low, PolishedBlackstoneWall::North::None, PolishedBlackstoneWall::South::Tall, true, PolishedBlackstoneWall::West::Low).ID: return 16913; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Low, PolishedBlackstoneWall::North::None, PolishedBlackstoneWall::South::Tall, true, PolishedBlackstoneWall::West::Tall).ID: return 16914; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Low, PolishedBlackstoneWall::North::None, PolishedBlackstoneWall::South::Tall, false, PolishedBlackstoneWall::West::None).ID: return 16918; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Low, PolishedBlackstoneWall::North::None, PolishedBlackstoneWall::South::Tall, false, PolishedBlackstoneWall::West::Low).ID: return 16919; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Low, PolishedBlackstoneWall::North::None, PolishedBlackstoneWall::South::Tall, false, PolishedBlackstoneWall::West::Tall).ID: return 16920; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Low, PolishedBlackstoneWall::North::Low, PolishedBlackstoneWall::South::None, true, PolishedBlackstoneWall::West::None).ID: return 16924; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Low, PolishedBlackstoneWall::North::Low, PolishedBlackstoneWall::South::None, true, PolishedBlackstoneWall::West::Low).ID: return 16925; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Low, PolishedBlackstoneWall::North::Low, PolishedBlackstoneWall::South::None, true, PolishedBlackstoneWall::West::Tall).ID: return 16926; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Low, PolishedBlackstoneWall::North::Low, PolishedBlackstoneWall::South::None, false, PolishedBlackstoneWall::West::None).ID: return 16930; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Low, PolishedBlackstoneWall::North::Low, PolishedBlackstoneWall::South::None, false, PolishedBlackstoneWall::West::Low).ID: return 16931; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Low, PolishedBlackstoneWall::North::Low, PolishedBlackstoneWall::South::None, false, PolishedBlackstoneWall::West::Tall).ID: return 16932; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Low, PolishedBlackstoneWall::North::Low, PolishedBlackstoneWall::South::Low, true, PolishedBlackstoneWall::West::None).ID: return 16936; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Low, PolishedBlackstoneWall::North::Low, PolishedBlackstoneWall::South::Low, true, PolishedBlackstoneWall::West::Low).ID: return 16937; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Low, PolishedBlackstoneWall::North::Low, PolishedBlackstoneWall::South::Low, true, PolishedBlackstoneWall::West::Tall).ID: return 16938; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Low, PolishedBlackstoneWall::North::Low, PolishedBlackstoneWall::South::Low, false, PolishedBlackstoneWall::West::None).ID: return 16942; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Low, PolishedBlackstoneWall::North::Low, PolishedBlackstoneWall::South::Low, false, PolishedBlackstoneWall::West::Low).ID: return 16943; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Low, PolishedBlackstoneWall::North::Low, PolishedBlackstoneWall::South::Low, false, PolishedBlackstoneWall::West::Tall).ID: return 16944; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Low, PolishedBlackstoneWall::North::Low, PolishedBlackstoneWall::South::Tall, true, PolishedBlackstoneWall::West::None).ID: return 16948; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Low, PolishedBlackstoneWall::North::Low, PolishedBlackstoneWall::South::Tall, true, PolishedBlackstoneWall::West::Low).ID: return 16949; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Low, PolishedBlackstoneWall::North::Low, PolishedBlackstoneWall::South::Tall, true, PolishedBlackstoneWall::West::Tall).ID: return 16950; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Low, PolishedBlackstoneWall::North::Low, PolishedBlackstoneWall::South::Tall, false, PolishedBlackstoneWall::West::None).ID: return 16954; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Low, PolishedBlackstoneWall::North::Low, PolishedBlackstoneWall::South::Tall, false, PolishedBlackstoneWall::West::Low).ID: return 16955; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Low, PolishedBlackstoneWall::North::Low, PolishedBlackstoneWall::South::Tall, false, PolishedBlackstoneWall::West::Tall).ID: return 16956; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Low, PolishedBlackstoneWall::North::Tall, PolishedBlackstoneWall::South::None, true, PolishedBlackstoneWall::West::None).ID: return 16960; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Low, PolishedBlackstoneWall::North::Tall, PolishedBlackstoneWall::South::None, true, PolishedBlackstoneWall::West::Low).ID: return 16961; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Low, PolishedBlackstoneWall::North::Tall, PolishedBlackstoneWall::South::None, true, PolishedBlackstoneWall::West::Tall).ID: return 16962; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Low, PolishedBlackstoneWall::North::Tall, PolishedBlackstoneWall::South::None, false, PolishedBlackstoneWall::West::None).ID: return 16966; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Low, PolishedBlackstoneWall::North::Tall, PolishedBlackstoneWall::South::None, false, PolishedBlackstoneWall::West::Low).ID: return 16967; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Low, PolishedBlackstoneWall::North::Tall, PolishedBlackstoneWall::South::None, false, PolishedBlackstoneWall::West::Tall).ID: return 16968; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Low, PolishedBlackstoneWall::North::Tall, PolishedBlackstoneWall::South::Low, true, PolishedBlackstoneWall::West::None).ID: return 16972; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Low, PolishedBlackstoneWall::North::Tall, PolishedBlackstoneWall::South::Low, true, PolishedBlackstoneWall::West::Low).ID: return 16973; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Low, PolishedBlackstoneWall::North::Tall, PolishedBlackstoneWall::South::Low, true, PolishedBlackstoneWall::West::Tall).ID: return 16974; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Low, PolishedBlackstoneWall::North::Tall, PolishedBlackstoneWall::South::Low, false, PolishedBlackstoneWall::West::None).ID: return 16978; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Low, PolishedBlackstoneWall::North::Tall, PolishedBlackstoneWall::South::Low, false, PolishedBlackstoneWall::West::Low).ID: return 16979; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Low, PolishedBlackstoneWall::North::Tall, PolishedBlackstoneWall::South::Low, false, PolishedBlackstoneWall::West::Tall).ID: return 16980; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Low, PolishedBlackstoneWall::North::Tall, PolishedBlackstoneWall::South::Tall, true, PolishedBlackstoneWall::West::None).ID: return 16984; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Low, PolishedBlackstoneWall::North::Tall, PolishedBlackstoneWall::South::Tall, true, PolishedBlackstoneWall::West::Low).ID: return 16985; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Low, PolishedBlackstoneWall::North::Tall, PolishedBlackstoneWall::South::Tall, true, PolishedBlackstoneWall::West::Tall).ID: return 16986; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Low, PolishedBlackstoneWall::North::Tall, PolishedBlackstoneWall::South::Tall, false, PolishedBlackstoneWall::West::None).ID: return 16990; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Low, PolishedBlackstoneWall::North::Tall, PolishedBlackstoneWall::South::Tall, false, PolishedBlackstoneWall::West::Low).ID: return 16991; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Low, PolishedBlackstoneWall::North::Tall, PolishedBlackstoneWall::South::Tall, false, PolishedBlackstoneWall::West::Tall).ID: return 16992; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Tall, PolishedBlackstoneWall::North::None, PolishedBlackstoneWall::South::None, true, PolishedBlackstoneWall::West::None).ID: return 16996; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Tall, PolishedBlackstoneWall::North::None, PolishedBlackstoneWall::South::None, true, PolishedBlackstoneWall::West::Low).ID: return 16997; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Tall, PolishedBlackstoneWall::North::None, PolishedBlackstoneWall::South::None, true, PolishedBlackstoneWall::West::Tall).ID: return 16998; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Tall, PolishedBlackstoneWall::North::None, PolishedBlackstoneWall::South::None, false, PolishedBlackstoneWall::West::None).ID: return 17002; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Tall, PolishedBlackstoneWall::North::None, PolishedBlackstoneWall::South::None, false, PolishedBlackstoneWall::West::Low).ID: return 17003; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Tall, PolishedBlackstoneWall::North::None, PolishedBlackstoneWall::South::None, false, PolishedBlackstoneWall::West::Tall).ID: return 17004; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Tall, PolishedBlackstoneWall::North::None, PolishedBlackstoneWall::South::Low, true, PolishedBlackstoneWall::West::None).ID: return 17008; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Tall, PolishedBlackstoneWall::North::None, PolishedBlackstoneWall::South::Low, true, PolishedBlackstoneWall::West::Low).ID: return 17009; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Tall, PolishedBlackstoneWall::North::None, PolishedBlackstoneWall::South::Low, true, PolishedBlackstoneWall::West::Tall).ID: return 17010; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Tall, PolishedBlackstoneWall::North::None, PolishedBlackstoneWall::South::Low, false, PolishedBlackstoneWall::West::None).ID: return 17014; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Tall, PolishedBlackstoneWall::North::None, PolishedBlackstoneWall::South::Low, false, PolishedBlackstoneWall::West::Low).ID: return 17015; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Tall, PolishedBlackstoneWall::North::None, PolishedBlackstoneWall::South::Low, false, PolishedBlackstoneWall::West::Tall).ID: return 17016; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Tall, PolishedBlackstoneWall::North::None, PolishedBlackstoneWall::South::Tall, true, PolishedBlackstoneWall::West::None).ID: return 17020; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Tall, PolishedBlackstoneWall::North::None, PolishedBlackstoneWall::South::Tall, true, PolishedBlackstoneWall::West::Low).ID: return 17021; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Tall, PolishedBlackstoneWall::North::None, PolishedBlackstoneWall::South::Tall, true, PolishedBlackstoneWall::West::Tall).ID: return 17022; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Tall, PolishedBlackstoneWall::North::None, PolishedBlackstoneWall::South::Tall, false, PolishedBlackstoneWall::West::None).ID: return 17026; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Tall, PolishedBlackstoneWall::North::None, PolishedBlackstoneWall::South::Tall, false, PolishedBlackstoneWall::West::Low).ID: return 17027; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Tall, PolishedBlackstoneWall::North::None, PolishedBlackstoneWall::South::Tall, false, PolishedBlackstoneWall::West::Tall).ID: return 17028; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Tall, PolishedBlackstoneWall::North::Low, PolishedBlackstoneWall::South::None, true, PolishedBlackstoneWall::West::None).ID: return 17032; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Tall, PolishedBlackstoneWall::North::Low, PolishedBlackstoneWall::South::None, true, PolishedBlackstoneWall::West::Low).ID: return 17033; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Tall, PolishedBlackstoneWall::North::Low, PolishedBlackstoneWall::South::None, true, PolishedBlackstoneWall::West::Tall).ID: return 17034; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Tall, PolishedBlackstoneWall::North::Low, PolishedBlackstoneWall::South::None, false, PolishedBlackstoneWall::West::None).ID: return 17038; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Tall, PolishedBlackstoneWall::North::Low, PolishedBlackstoneWall::South::None, false, PolishedBlackstoneWall::West::Low).ID: return 17039; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Tall, PolishedBlackstoneWall::North::Low, PolishedBlackstoneWall::South::None, false, PolishedBlackstoneWall::West::Tall).ID: return 17040; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Tall, PolishedBlackstoneWall::North::Low, PolishedBlackstoneWall::South::Low, true, PolishedBlackstoneWall::West::None).ID: return 17044; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Tall, PolishedBlackstoneWall::North::Low, PolishedBlackstoneWall::South::Low, true, PolishedBlackstoneWall::West::Low).ID: return 17045; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Tall, PolishedBlackstoneWall::North::Low, PolishedBlackstoneWall::South::Low, true, PolishedBlackstoneWall::West::Tall).ID: return 17046; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Tall, PolishedBlackstoneWall::North::Low, PolishedBlackstoneWall::South::Low, false, PolishedBlackstoneWall::West::None).ID: return 17050; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Tall, PolishedBlackstoneWall::North::Low, PolishedBlackstoneWall::South::Low, false, PolishedBlackstoneWall::West::Low).ID: return 17051; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Tall, PolishedBlackstoneWall::North::Low, PolishedBlackstoneWall::South::Low, false, PolishedBlackstoneWall::West::Tall).ID: return 17052; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Tall, PolishedBlackstoneWall::North::Low, PolishedBlackstoneWall::South::Tall, true, PolishedBlackstoneWall::West::None).ID: return 17056; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Tall, PolishedBlackstoneWall::North::Low, PolishedBlackstoneWall::South::Tall, true, PolishedBlackstoneWall::West::Low).ID: return 17057; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Tall, PolishedBlackstoneWall::North::Low, PolishedBlackstoneWall::South::Tall, true, PolishedBlackstoneWall::West::Tall).ID: return 17058; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Tall, PolishedBlackstoneWall::North::Low, PolishedBlackstoneWall::South::Tall, false, PolishedBlackstoneWall::West::None).ID: return 17062; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Tall, PolishedBlackstoneWall::North::Low, PolishedBlackstoneWall::South::Tall, false, PolishedBlackstoneWall::West::Low).ID: return 17063; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Tall, PolishedBlackstoneWall::North::Low, PolishedBlackstoneWall::South::Tall, false, PolishedBlackstoneWall::West::Tall).ID: return 17064; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Tall, PolishedBlackstoneWall::North::Tall, PolishedBlackstoneWall::South::None, true, PolishedBlackstoneWall::West::None).ID: return 17068; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Tall, PolishedBlackstoneWall::North::Tall, PolishedBlackstoneWall::South::None, true, PolishedBlackstoneWall::West::Low).ID: return 17069; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Tall, PolishedBlackstoneWall::North::Tall, PolishedBlackstoneWall::South::None, true, PolishedBlackstoneWall::West::Tall).ID: return 17070; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Tall, PolishedBlackstoneWall::North::Tall, PolishedBlackstoneWall::South::None, false, PolishedBlackstoneWall::West::None).ID: return 17074; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Tall, PolishedBlackstoneWall::North::Tall, PolishedBlackstoneWall::South::None, false, PolishedBlackstoneWall::West::Low).ID: return 17075; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Tall, PolishedBlackstoneWall::North::Tall, PolishedBlackstoneWall::South::None, false, PolishedBlackstoneWall::West::Tall).ID: return 17076; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Tall, PolishedBlackstoneWall::North::Tall, PolishedBlackstoneWall::South::Low, true, PolishedBlackstoneWall::West::None).ID: return 17080; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Tall, PolishedBlackstoneWall::North::Tall, PolishedBlackstoneWall::South::Low, true, PolishedBlackstoneWall::West::Low).ID: return 17081; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Tall, PolishedBlackstoneWall::North::Tall, PolishedBlackstoneWall::South::Low, true, PolishedBlackstoneWall::West::Tall).ID: return 17082; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Tall, PolishedBlackstoneWall::North::Tall, PolishedBlackstoneWall::South::Low, false, PolishedBlackstoneWall::West::None).ID: return 17086; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Tall, PolishedBlackstoneWall::North::Tall, PolishedBlackstoneWall::South::Low, false, PolishedBlackstoneWall::West::Low).ID: return 17087; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Tall, PolishedBlackstoneWall::North::Tall, PolishedBlackstoneWall::South::Low, false, PolishedBlackstoneWall::West::Tall).ID: return 17088; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Tall, PolishedBlackstoneWall::North::Tall, PolishedBlackstoneWall::South::Tall, true, PolishedBlackstoneWall::West::None).ID: return 17092; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Tall, PolishedBlackstoneWall::North::Tall, PolishedBlackstoneWall::South::Tall, true, PolishedBlackstoneWall::West::Low).ID: return 17093; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Tall, PolishedBlackstoneWall::North::Tall, PolishedBlackstoneWall::South::Tall, true, PolishedBlackstoneWall::West::Tall).ID: return 17094; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Tall, PolishedBlackstoneWall::North::Tall, PolishedBlackstoneWall::South::Tall, false, PolishedBlackstoneWall::West::None).ID: return 17098; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Tall, PolishedBlackstoneWall::North::Tall, PolishedBlackstoneWall::South::Tall, false, PolishedBlackstoneWall::West::Low).ID: return 17099; case PolishedBlackstoneWall::PolishedBlackstoneWall(PolishedBlackstoneWall::East::Tall, PolishedBlackstoneWall::North::Tall, PolishedBlackstoneWall::South::Tall, false, PolishedBlackstoneWall::West::Tall).ID: return 17100; case PolishedDiorite::PolishedDiorite().ID: return 5; case PolishedDioriteSlab::PolishedDioriteSlab(PolishedDioriteSlab::Type::Top).ID: return 10808; case PolishedDioriteSlab::PolishedDioriteSlab(PolishedDioriteSlab::Type::Bottom).ID: return 10810; case PolishedDioriteSlab::PolishedDioriteSlab(PolishedDioriteSlab::Type::Double).ID: return 10812; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedDioriteStairs::Half::Top, PolishedDioriteStairs::Shape::Straight).ID: return 9910; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedDioriteStairs::Half::Top, PolishedDioriteStairs::Shape::InnerLeft).ID: return 9912; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedDioriteStairs::Half::Top, PolishedDioriteStairs::Shape::InnerRight).ID: return 9914; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedDioriteStairs::Half::Top, PolishedDioriteStairs::Shape::OuterLeft).ID: return 9916; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedDioriteStairs::Half::Top, PolishedDioriteStairs::Shape::OuterRight).ID: return 9918; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedDioriteStairs::Half::Bottom, PolishedDioriteStairs::Shape::Straight).ID: return 9920; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedDioriteStairs::Half::Bottom, PolishedDioriteStairs::Shape::InnerLeft).ID: return 9922; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedDioriteStairs::Half::Bottom, PolishedDioriteStairs::Shape::InnerRight).ID: return 9924; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedDioriteStairs::Half::Bottom, PolishedDioriteStairs::Shape::OuterLeft).ID: return 9926; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedDioriteStairs::Half::Bottom, PolishedDioriteStairs::Shape::OuterRight).ID: return 9928; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedDioriteStairs::Half::Top, PolishedDioriteStairs::Shape::Straight).ID: return 9930; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedDioriteStairs::Half::Top, PolishedDioriteStairs::Shape::InnerLeft).ID: return 9932; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedDioriteStairs::Half::Top, PolishedDioriteStairs::Shape::InnerRight).ID: return 9934; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedDioriteStairs::Half::Top, PolishedDioriteStairs::Shape::OuterLeft).ID: return 9936; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedDioriteStairs::Half::Top, PolishedDioriteStairs::Shape::OuterRight).ID: return 9938; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedDioriteStairs::Half::Bottom, PolishedDioriteStairs::Shape::Straight).ID: return 9940; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedDioriteStairs::Half::Bottom, PolishedDioriteStairs::Shape::InnerLeft).ID: return 9942; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedDioriteStairs::Half::Bottom, PolishedDioriteStairs::Shape::InnerRight).ID: return 9944; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedDioriteStairs::Half::Bottom, PolishedDioriteStairs::Shape::OuterLeft).ID: return 9946; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedDioriteStairs::Half::Bottom, PolishedDioriteStairs::Shape::OuterRight).ID: return 9948; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_XM, PolishedDioriteStairs::Half::Top, PolishedDioriteStairs::Shape::Straight).ID: return 9950; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_XM, PolishedDioriteStairs::Half::Top, PolishedDioriteStairs::Shape::InnerLeft).ID: return 9952; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_XM, PolishedDioriteStairs::Half::Top, PolishedDioriteStairs::Shape::InnerRight).ID: return 9954; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_XM, PolishedDioriteStairs::Half::Top, PolishedDioriteStairs::Shape::OuterLeft).ID: return 9956; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_XM, PolishedDioriteStairs::Half::Top, PolishedDioriteStairs::Shape::OuterRight).ID: return 9958; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_XM, PolishedDioriteStairs::Half::Bottom, PolishedDioriteStairs::Shape::Straight).ID: return 9960; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_XM, PolishedDioriteStairs::Half::Bottom, PolishedDioriteStairs::Shape::InnerLeft).ID: return 9962; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_XM, PolishedDioriteStairs::Half::Bottom, PolishedDioriteStairs::Shape::InnerRight).ID: return 9964; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_XM, PolishedDioriteStairs::Half::Bottom, PolishedDioriteStairs::Shape::OuterLeft).ID: return 9966; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_XM, PolishedDioriteStairs::Half::Bottom, PolishedDioriteStairs::Shape::OuterRight).ID: return 9968; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_XP, PolishedDioriteStairs::Half::Top, PolishedDioriteStairs::Shape::Straight).ID: return 9970; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_XP, PolishedDioriteStairs::Half::Top, PolishedDioriteStairs::Shape::InnerLeft).ID: return 9972; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_XP, PolishedDioriteStairs::Half::Top, PolishedDioriteStairs::Shape::InnerRight).ID: return 9974; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_XP, PolishedDioriteStairs::Half::Top, PolishedDioriteStairs::Shape::OuterLeft).ID: return 9976; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_XP, PolishedDioriteStairs::Half::Top, PolishedDioriteStairs::Shape::OuterRight).ID: return 9978; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_XP, PolishedDioriteStairs::Half::Bottom, PolishedDioriteStairs::Shape::Straight).ID: return 9980; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_XP, PolishedDioriteStairs::Half::Bottom, PolishedDioriteStairs::Shape::InnerLeft).ID: return 9982; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_XP, PolishedDioriteStairs::Half::Bottom, PolishedDioriteStairs::Shape::InnerRight).ID: return 9984; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_XP, PolishedDioriteStairs::Half::Bottom, PolishedDioriteStairs::Shape::OuterLeft).ID: return 9986; case PolishedDioriteStairs::PolishedDioriteStairs(eBlockFace::BLOCK_FACE_XP, PolishedDioriteStairs::Half::Bottom, PolishedDioriteStairs::Shape::OuterRight).ID: return 9988; case PolishedGranite::PolishedGranite().ID: return 3; case PolishedGraniteSlab::PolishedGraniteSlab(PolishedGraniteSlab::Type::Top).ID: return 10790; case PolishedGraniteSlab::PolishedGraniteSlab(PolishedGraniteSlab::Type::Bottom).ID: return 10792; case PolishedGraniteSlab::PolishedGraniteSlab(PolishedGraniteSlab::Type::Double).ID: return 10794; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedGraniteStairs::Half::Top, PolishedGraniteStairs::Shape::Straight).ID: return 9670; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedGraniteStairs::Half::Top, PolishedGraniteStairs::Shape::InnerLeft).ID: return 9672; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedGraniteStairs::Half::Top, PolishedGraniteStairs::Shape::InnerRight).ID: return 9674; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedGraniteStairs::Half::Top, PolishedGraniteStairs::Shape::OuterLeft).ID: return 9676; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedGraniteStairs::Half::Top, PolishedGraniteStairs::Shape::OuterRight).ID: return 9678; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedGraniteStairs::Half::Bottom, PolishedGraniteStairs::Shape::Straight).ID: return 9680; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedGraniteStairs::Half::Bottom, PolishedGraniteStairs::Shape::InnerLeft).ID: return 9682; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedGraniteStairs::Half::Bottom, PolishedGraniteStairs::Shape::InnerRight).ID: return 9684; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedGraniteStairs::Half::Bottom, PolishedGraniteStairs::Shape::OuterLeft).ID: return 9686; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_ZM, PolishedGraniteStairs::Half::Bottom, PolishedGraniteStairs::Shape::OuterRight).ID: return 9688; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedGraniteStairs::Half::Top, PolishedGraniteStairs::Shape::Straight).ID: return 9690; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedGraniteStairs::Half::Top, PolishedGraniteStairs::Shape::InnerLeft).ID: return 9692; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedGraniteStairs::Half::Top, PolishedGraniteStairs::Shape::InnerRight).ID: return 9694; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedGraniteStairs::Half::Top, PolishedGraniteStairs::Shape::OuterLeft).ID: return 9696; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedGraniteStairs::Half::Top, PolishedGraniteStairs::Shape::OuterRight).ID: return 9698; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedGraniteStairs::Half::Bottom, PolishedGraniteStairs::Shape::Straight).ID: return 9700; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedGraniteStairs::Half::Bottom, PolishedGraniteStairs::Shape::InnerLeft).ID: return 9702; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedGraniteStairs::Half::Bottom, PolishedGraniteStairs::Shape::InnerRight).ID: return 9704; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedGraniteStairs::Half::Bottom, PolishedGraniteStairs::Shape::OuterLeft).ID: return 9706; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_ZP, PolishedGraniteStairs::Half::Bottom, PolishedGraniteStairs::Shape::OuterRight).ID: return 9708; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_XM, PolishedGraniteStairs::Half::Top, PolishedGraniteStairs::Shape::Straight).ID: return 9710; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_XM, PolishedGraniteStairs::Half::Top, PolishedGraniteStairs::Shape::InnerLeft).ID: return 9712; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_XM, PolishedGraniteStairs::Half::Top, PolishedGraniteStairs::Shape::InnerRight).ID: return 9714; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_XM, PolishedGraniteStairs::Half::Top, PolishedGraniteStairs::Shape::OuterLeft).ID: return 9716; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_XM, PolishedGraniteStairs::Half::Top, PolishedGraniteStairs::Shape::OuterRight).ID: return 9718; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_XM, PolishedGraniteStairs::Half::Bottom, PolishedGraniteStairs::Shape::Straight).ID: return 9720; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_XM, PolishedGraniteStairs::Half::Bottom, PolishedGraniteStairs::Shape::InnerLeft).ID: return 9722; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_XM, PolishedGraniteStairs::Half::Bottom, PolishedGraniteStairs::Shape::InnerRight).ID: return 9724; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_XM, PolishedGraniteStairs::Half::Bottom, PolishedGraniteStairs::Shape::OuterLeft).ID: return 9726; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_XM, PolishedGraniteStairs::Half::Bottom, PolishedGraniteStairs::Shape::OuterRight).ID: return 9728; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_XP, PolishedGraniteStairs::Half::Top, PolishedGraniteStairs::Shape::Straight).ID: return 9730; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_XP, PolishedGraniteStairs::Half::Top, PolishedGraniteStairs::Shape::InnerLeft).ID: return 9732; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_XP, PolishedGraniteStairs::Half::Top, PolishedGraniteStairs::Shape::InnerRight).ID: return 9734; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_XP, PolishedGraniteStairs::Half::Top, PolishedGraniteStairs::Shape::OuterLeft).ID: return 9736; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_XP, PolishedGraniteStairs::Half::Top, PolishedGraniteStairs::Shape::OuterRight).ID: return 9738; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_XP, PolishedGraniteStairs::Half::Bottom, PolishedGraniteStairs::Shape::Straight).ID: return 9740; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_XP, PolishedGraniteStairs::Half::Bottom, PolishedGraniteStairs::Shape::InnerLeft).ID: return 9742; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_XP, PolishedGraniteStairs::Half::Bottom, PolishedGraniteStairs::Shape::InnerRight).ID: return 9744; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_XP, PolishedGraniteStairs::Half::Bottom, PolishedGraniteStairs::Shape::OuterLeft).ID: return 9746; case PolishedGraniteStairs::PolishedGraniteStairs(eBlockFace::BLOCK_FACE_XP, PolishedGraniteStairs::Half::Bottom, PolishedGraniteStairs::Shape::OuterRight).ID: return 9748; case Poppy::Poppy().ID: return 1413; case Potatoes::Potatoes(0).ID: return 6338; case Potatoes::Potatoes(1).ID: return 6339; case Potatoes::Potatoes(2).ID: return 6340; case Potatoes::Potatoes(3).ID: return 6341; case Potatoes::Potatoes(4).ID: return 6342; case Potatoes::Potatoes(5).ID: return 6343; case Potatoes::Potatoes(6).ID: return 6344; case Potatoes::Potatoes(7).ID: return 6345; case PottedAcaciaSapling::PottedAcaciaSapling().ID: return 6310; case PottedAllium::PottedAllium().ID: return 6316; case PottedAzureBluet::PottedAzureBluet().ID: return 6317; case PottedBamboo::PottedBamboo().ID: return 9664; case PottedBirchSapling::PottedBirchSapling().ID: return 6308; case PottedBlueOrchid::PottedBlueOrchid().ID: return 6315; case PottedBrownMushroom::PottedBrownMushroom().ID: return 6327; case PottedCactus::PottedCactus().ID: return 6329; case PottedCornflower::PottedCornflower().ID: return 6323; case PottedCrimsonFungus::PottedCrimsonFungus().ID: return 15834; case PottedCrimsonRoots::PottedCrimsonRoots().ID: return 15836; case PottedDandelion::PottedDandelion().ID: return 6313; case PottedDarkOakSapling::PottedDarkOakSapling().ID: return 6311; case PottedDeadBush::PottedDeadBush().ID: return 6328; case PottedFern::PottedFern().ID: return 6312; case PottedJungleSapling::PottedJungleSapling().ID: return 6309; case PottedLilyOfTheValley::PottedLilyOfTheValley().ID: return 6324; case PottedOakSapling::PottedOakSapling().ID: return 6306; case PottedOrangeTulip::PottedOrangeTulip().ID: return 6319; case PottedOxeyeDaisy::PottedOxeyeDaisy().ID: return 6322; case PottedPinkTulip::PottedPinkTulip().ID: return 6321; case PottedPoppy::PottedPoppy().ID: return 6314; case PottedRedMushroom::PottedRedMushroom().ID: return 6326; case PottedRedTulip::PottedRedTulip().ID: return 6318; case PottedSpruceSapling::PottedSpruceSapling().ID: return 6307; case PottedWarpedFungus::PottedWarpedFungus().ID: return 15835; case PottedWarpedRoots::PottedWarpedRoots().ID: return 15837; case PottedWhiteTulip::PottedWhiteTulip().ID: return 6320; case PottedWitherRose::PottedWitherRose().ID: return 6325; case PoweredRail::PoweredRail(true, PoweredRail::Shape::NorthSouth).ID: return 1305; case PoweredRail::PoweredRail(true, PoweredRail::Shape::EastWest).ID: return 1306; case PoweredRail::PoweredRail(true, PoweredRail::Shape::AscendingEast).ID: return 1307; case PoweredRail::PoweredRail(true, PoweredRail::Shape::AscendingWest).ID: return 1308; case PoweredRail::PoweredRail(true, PoweredRail::Shape::AscendingNorth).ID: return 1309; case PoweredRail::PoweredRail(true, PoweredRail::Shape::AscendingSouth).ID: return 1310; case PoweredRail::PoweredRail(false, PoweredRail::Shape::NorthSouth).ID: return 1311; case PoweredRail::PoweredRail(false, PoweredRail::Shape::EastWest).ID: return 1312; case PoweredRail::PoweredRail(false, PoweredRail::Shape::AscendingEast).ID: return 1313; case PoweredRail::PoweredRail(false, PoweredRail::Shape::AscendingWest).ID: return 1314; case PoweredRail::PoweredRail(false, PoweredRail::Shape::AscendingNorth).ID: return 1315; case PoweredRail::PoweredRail(false, PoweredRail::Shape::AscendingSouth).ID: return 1316; case Prismarine::Prismarine().ID: return 7601; case PrismarineBrickSlab::PrismarineBrickSlab(PrismarineBrickSlab::Type::Top).ID: return 7851; case PrismarineBrickSlab::PrismarineBrickSlab(PrismarineBrickSlab::Type::Bottom).ID: return 7853; case PrismarineBrickSlab::PrismarineBrickSlab(PrismarineBrickSlab::Type::Double).ID: return 7855; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::Straight).ID: return 7685; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::InnerLeft).ID: return 7687; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::InnerRight).ID: return 7689; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::OuterLeft).ID: return 7691; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::OuterRight).ID: return 7693; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::Straight).ID: return 7695; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::InnerLeft).ID: return 7697; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::InnerRight).ID: return 7699; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::OuterLeft).ID: return 7701; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::OuterRight).ID: return 7703; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::Straight).ID: return 7705; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::InnerLeft).ID: return 7707; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::InnerRight).ID: return 7709; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::OuterLeft).ID: return 7711; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::OuterRight).ID: return 7713; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::Straight).ID: return 7715; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::InnerLeft).ID: return 7717; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::InnerRight).ID: return 7719; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::OuterLeft).ID: return 7721; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::OuterRight).ID: return 7723; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XM, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::Straight).ID: return 7725; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XM, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::InnerLeft).ID: return 7727; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XM, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::InnerRight).ID: return 7729; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XM, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::OuterLeft).ID: return 7731; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XM, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::OuterRight).ID: return 7733; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XM, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::Straight).ID: return 7735; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XM, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::InnerLeft).ID: return 7737; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XM, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::InnerRight).ID: return 7739; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XM, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::OuterLeft).ID: return 7741; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XM, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::OuterRight).ID: return 7743; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XP, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::Straight).ID: return 7745; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XP, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::InnerLeft).ID: return 7747; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XP, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::InnerRight).ID: return 7749; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XP, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::OuterLeft).ID: return 7751; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XP, PrismarineBrickStairs::Half::Top, PrismarineBrickStairs::Shape::OuterRight).ID: return 7753; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XP, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::Straight).ID: return 7755; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XP, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::InnerLeft).ID: return 7757; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XP, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::InnerRight).ID: return 7759; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XP, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::OuterLeft).ID: return 7761; case PrismarineBrickStairs::PrismarineBrickStairs(eBlockFace::BLOCK_FACE_XP, PrismarineBrickStairs::Half::Bottom, PrismarineBrickStairs::Shape::OuterRight).ID: return 7763; case PrismarineBricks::PrismarineBricks().ID: return 7602; case PrismarineSlab::PrismarineSlab(PrismarineSlab::Type::Top).ID: return 7845; case PrismarineSlab::PrismarineSlab(PrismarineSlab::Type::Bottom).ID: return 7847; case PrismarineSlab::PrismarineSlab(PrismarineSlab::Type::Double).ID: return 7849; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineStairs::Half::Top, PrismarineStairs::Shape::Straight).ID: return 7605; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineStairs::Half::Top, PrismarineStairs::Shape::InnerLeft).ID: return 7607; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineStairs::Half::Top, PrismarineStairs::Shape::InnerRight).ID: return 7609; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineStairs::Half::Top, PrismarineStairs::Shape::OuterLeft).ID: return 7611; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineStairs::Half::Top, PrismarineStairs::Shape::OuterRight).ID: return 7613; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::Straight).ID: return 7615; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::InnerLeft).ID: return 7617; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::InnerRight).ID: return 7619; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::OuterLeft).ID: return 7621; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZM, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::OuterRight).ID: return 7623; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineStairs::Half::Top, PrismarineStairs::Shape::Straight).ID: return 7625; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineStairs::Half::Top, PrismarineStairs::Shape::InnerLeft).ID: return 7627; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineStairs::Half::Top, PrismarineStairs::Shape::InnerRight).ID: return 7629; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineStairs::Half::Top, PrismarineStairs::Shape::OuterLeft).ID: return 7631; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineStairs::Half::Top, PrismarineStairs::Shape::OuterRight).ID: return 7633; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::Straight).ID: return 7635; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::InnerLeft).ID: return 7637; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::InnerRight).ID: return 7639; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::OuterLeft).ID: return 7641; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_ZP, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::OuterRight).ID: return 7643; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XM, PrismarineStairs::Half::Top, PrismarineStairs::Shape::Straight).ID: return 7645; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XM, PrismarineStairs::Half::Top, PrismarineStairs::Shape::InnerLeft).ID: return 7647; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XM, PrismarineStairs::Half::Top, PrismarineStairs::Shape::InnerRight).ID: return 7649; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XM, PrismarineStairs::Half::Top, PrismarineStairs::Shape::OuterLeft).ID: return 7651; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XM, PrismarineStairs::Half::Top, PrismarineStairs::Shape::OuterRight).ID: return 7653; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XM, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::Straight).ID: return 7655; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XM, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::InnerLeft).ID: return 7657; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XM, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::InnerRight).ID: return 7659; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XM, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::OuterLeft).ID: return 7661; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XM, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::OuterRight).ID: return 7663; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XP, PrismarineStairs::Half::Top, PrismarineStairs::Shape::Straight).ID: return 7665; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XP, PrismarineStairs::Half::Top, PrismarineStairs::Shape::InnerLeft).ID: return 7667; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XP, PrismarineStairs::Half::Top, PrismarineStairs::Shape::InnerRight).ID: return 7669; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XP, PrismarineStairs::Half::Top, PrismarineStairs::Shape::OuterLeft).ID: return 7671; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XP, PrismarineStairs::Half::Top, PrismarineStairs::Shape::OuterRight).ID: return 7673; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XP, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::Straight).ID: return 7675; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XP, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::InnerLeft).ID: return 7677; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XP, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::InnerRight).ID: return 7679; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XP, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::OuterLeft).ID: return 7681; case PrismarineStairs::PrismarineStairs(eBlockFace::BLOCK_FACE_XP, PrismarineStairs::Half::Bottom, PrismarineStairs::Shape::OuterRight).ID: return 7683; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::None, PrismarineWall::South::None, true, PrismarineWall::West::None).ID: return 11194; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::None, PrismarineWall::South::None, true, PrismarineWall::West::Low).ID: return 11195; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::None, PrismarineWall::South::None, true, PrismarineWall::West::Tall).ID: return 11196; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::None, PrismarineWall::South::None, false, PrismarineWall::West::None).ID: return 11200; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::None, PrismarineWall::South::None, false, PrismarineWall::West::Low).ID: return 11201; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::None, PrismarineWall::South::None, false, PrismarineWall::West::Tall).ID: return 11202; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::None, PrismarineWall::South::Low, true, PrismarineWall::West::None).ID: return 11206; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::None, PrismarineWall::South::Low, true, PrismarineWall::West::Low).ID: return 11207; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::None, PrismarineWall::South::Low, true, PrismarineWall::West::Tall).ID: return 11208; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::None, PrismarineWall::South::Low, false, PrismarineWall::West::None).ID: return 11212; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::None, PrismarineWall::South::Low, false, PrismarineWall::West::Low).ID: return 11213; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::None, PrismarineWall::South::Low, false, PrismarineWall::West::Tall).ID: return 11214; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::None, PrismarineWall::South::Tall, true, PrismarineWall::West::None).ID: return 11218; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::None, PrismarineWall::South::Tall, true, PrismarineWall::West::Low).ID: return 11219; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::None, PrismarineWall::South::Tall, true, PrismarineWall::West::Tall).ID: return 11220; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::None, PrismarineWall::South::Tall, false, PrismarineWall::West::None).ID: return 11224; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::None, PrismarineWall::South::Tall, false, PrismarineWall::West::Low).ID: return 11225; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::None, PrismarineWall::South::Tall, false, PrismarineWall::West::Tall).ID: return 11226; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::Low, PrismarineWall::South::None, true, PrismarineWall::West::None).ID: return 11230; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::Low, PrismarineWall::South::None, true, PrismarineWall::West::Low).ID: return 11231; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::Low, PrismarineWall::South::None, true, PrismarineWall::West::Tall).ID: return 11232; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::Low, PrismarineWall::South::None, false, PrismarineWall::West::None).ID: return 11236; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::Low, PrismarineWall::South::None, false, PrismarineWall::West::Low).ID: return 11237; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::Low, PrismarineWall::South::None, false, PrismarineWall::West::Tall).ID: return 11238; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::Low, PrismarineWall::South::Low, true, PrismarineWall::West::None).ID: return 11242; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::Low, PrismarineWall::South::Low, true, PrismarineWall::West::Low).ID: return 11243; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::Low, PrismarineWall::South::Low, true, PrismarineWall::West::Tall).ID: return 11244; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::Low, PrismarineWall::South::Low, false, PrismarineWall::West::None).ID: return 11248; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::Low, PrismarineWall::South::Low, false, PrismarineWall::West::Low).ID: return 11249; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::Low, PrismarineWall::South::Low, false, PrismarineWall::West::Tall).ID: return 11250; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::Low, PrismarineWall::South::Tall, true, PrismarineWall::West::None).ID: return 11254; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::Low, PrismarineWall::South::Tall, true, PrismarineWall::West::Low).ID: return 11255; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::Low, PrismarineWall::South::Tall, true, PrismarineWall::West::Tall).ID: return 11256; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::Low, PrismarineWall::South::Tall, false, PrismarineWall::West::None).ID: return 11260; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::Low, PrismarineWall::South::Tall, false, PrismarineWall::West::Low).ID: return 11261; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::Low, PrismarineWall::South::Tall, false, PrismarineWall::West::Tall).ID: return 11262; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::Tall, PrismarineWall::South::None, true, PrismarineWall::West::None).ID: return 11266; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::Tall, PrismarineWall::South::None, true, PrismarineWall::West::Low).ID: return 11267; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::Tall, PrismarineWall::South::None, true, PrismarineWall::West::Tall).ID: return 11268; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::Tall, PrismarineWall::South::None, false, PrismarineWall::West::None).ID: return 11272; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::Tall, PrismarineWall::South::None, false, PrismarineWall::West::Low).ID: return 11273; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::Tall, PrismarineWall::South::None, false, PrismarineWall::West::Tall).ID: return 11274; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::Tall, PrismarineWall::South::Low, true, PrismarineWall::West::None).ID: return 11278; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::Tall, PrismarineWall::South::Low, true, PrismarineWall::West::Low).ID: return 11279; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::Tall, PrismarineWall::South::Low, true, PrismarineWall::West::Tall).ID: return 11280; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::Tall, PrismarineWall::South::Low, false, PrismarineWall::West::None).ID: return 11284; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::Tall, PrismarineWall::South::Low, false, PrismarineWall::West::Low).ID: return 11285; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::Tall, PrismarineWall::South::Low, false, PrismarineWall::West::Tall).ID: return 11286; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::Tall, PrismarineWall::South::Tall, true, PrismarineWall::West::None).ID: return 11290; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::Tall, PrismarineWall::South::Tall, true, PrismarineWall::West::Low).ID: return 11291; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::Tall, PrismarineWall::South::Tall, true, PrismarineWall::West::Tall).ID: return 11292; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::Tall, PrismarineWall::South::Tall, false, PrismarineWall::West::None).ID: return 11296; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::Tall, PrismarineWall::South::Tall, false, PrismarineWall::West::Low).ID: return 11297; case PrismarineWall::PrismarineWall(PrismarineWall::East::None, PrismarineWall::North::Tall, PrismarineWall::South::Tall, false, PrismarineWall::West::Tall).ID: return 11298; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::None, PrismarineWall::South::None, true, PrismarineWall::West::None).ID: return 11302; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::None, PrismarineWall::South::None, true, PrismarineWall::West::Low).ID: return 11303; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::None, PrismarineWall::South::None, true, PrismarineWall::West::Tall).ID: return 11304; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::None, PrismarineWall::South::None, false, PrismarineWall::West::None).ID: return 11308; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::None, PrismarineWall::South::None, false, PrismarineWall::West::Low).ID: return 11309; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::None, PrismarineWall::South::None, false, PrismarineWall::West::Tall).ID: return 11310; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::None, PrismarineWall::South::Low, true, PrismarineWall::West::None).ID: return 11314; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::None, PrismarineWall::South::Low, true, PrismarineWall::West::Low).ID: return 11315; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::None, PrismarineWall::South::Low, true, PrismarineWall::West::Tall).ID: return 11316; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::None, PrismarineWall::South::Low, false, PrismarineWall::West::None).ID: return 11320; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::None, PrismarineWall::South::Low, false, PrismarineWall::West::Low).ID: return 11321; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::None, PrismarineWall::South::Low, false, PrismarineWall::West::Tall).ID: return 11322; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::None, PrismarineWall::South::Tall, true, PrismarineWall::West::None).ID: return 11326; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::None, PrismarineWall::South::Tall, true, PrismarineWall::West::Low).ID: return 11327; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::None, PrismarineWall::South::Tall, true, PrismarineWall::West::Tall).ID: return 11328; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::None, PrismarineWall::South::Tall, false, PrismarineWall::West::None).ID: return 11332; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::None, PrismarineWall::South::Tall, false, PrismarineWall::West::Low).ID: return 11333; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::None, PrismarineWall::South::Tall, false, PrismarineWall::West::Tall).ID: return 11334; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::Low, PrismarineWall::South::None, true, PrismarineWall::West::None).ID: return 11338; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::Low, PrismarineWall::South::None, true, PrismarineWall::West::Low).ID: return 11339; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::Low, PrismarineWall::South::None, true, PrismarineWall::West::Tall).ID: return 11340; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::Low, PrismarineWall::South::None, false, PrismarineWall::West::None).ID: return 11344; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::Low, PrismarineWall::South::None, false, PrismarineWall::West::Low).ID: return 11345; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::Low, PrismarineWall::South::None, false, PrismarineWall::West::Tall).ID: return 11346; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::Low, PrismarineWall::South::Low, true, PrismarineWall::West::None).ID: return 11350; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::Low, PrismarineWall::South::Low, true, PrismarineWall::West::Low).ID: return 11351; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::Low, PrismarineWall::South::Low, true, PrismarineWall::West::Tall).ID: return 11352; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::Low, PrismarineWall::South::Low, false, PrismarineWall::West::None).ID: return 11356; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::Low, PrismarineWall::South::Low, false, PrismarineWall::West::Low).ID: return 11357; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::Low, PrismarineWall::South::Low, false, PrismarineWall::West::Tall).ID: return 11358; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::Low, PrismarineWall::South::Tall, true, PrismarineWall::West::None).ID: return 11362; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::Low, PrismarineWall::South::Tall, true, PrismarineWall::West::Low).ID: return 11363; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::Low, PrismarineWall::South::Tall, true, PrismarineWall::West::Tall).ID: return 11364; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::Low, PrismarineWall::South::Tall, false, PrismarineWall::West::None).ID: return 11368; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::Low, PrismarineWall::South::Tall, false, PrismarineWall::West::Low).ID: return 11369; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::Low, PrismarineWall::South::Tall, false, PrismarineWall::West::Tall).ID: return 11370; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::Tall, PrismarineWall::South::None, true, PrismarineWall::West::None).ID: return 11374; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::Tall, PrismarineWall::South::None, true, PrismarineWall::West::Low).ID: return 11375; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::Tall, PrismarineWall::South::None, true, PrismarineWall::West::Tall).ID: return 11376; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::Tall, PrismarineWall::South::None, false, PrismarineWall::West::None).ID: return 11380; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::Tall, PrismarineWall::South::None, false, PrismarineWall::West::Low).ID: return 11381; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::Tall, PrismarineWall::South::None, false, PrismarineWall::West::Tall).ID: return 11382; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::Tall, PrismarineWall::South::Low, true, PrismarineWall::West::None).ID: return 11386; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::Tall, PrismarineWall::South::Low, true, PrismarineWall::West::Low).ID: return 11387; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::Tall, PrismarineWall::South::Low, true, PrismarineWall::West::Tall).ID: return 11388; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::Tall, PrismarineWall::South::Low, false, PrismarineWall::West::None).ID: return 11392; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::Tall, PrismarineWall::South::Low, false, PrismarineWall::West::Low).ID: return 11393; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::Tall, PrismarineWall::South::Low, false, PrismarineWall::West::Tall).ID: return 11394; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::Tall, PrismarineWall::South::Tall, true, PrismarineWall::West::None).ID: return 11398; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::Tall, PrismarineWall::South::Tall, true, PrismarineWall::West::Low).ID: return 11399; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::Tall, PrismarineWall::South::Tall, true, PrismarineWall::West::Tall).ID: return 11400; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::Tall, PrismarineWall::South::Tall, false, PrismarineWall::West::None).ID: return 11404; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::Tall, PrismarineWall::South::Tall, false, PrismarineWall::West::Low).ID: return 11405; case PrismarineWall::PrismarineWall(PrismarineWall::East::Low, PrismarineWall::North::Tall, PrismarineWall::South::Tall, false, PrismarineWall::West::Tall).ID: return 11406; case PrismarineWall::PrismarineWall(PrismarineWall::East::Tall, PrismarineWall::North::None, PrismarineWall::South::None, true, PrismarineWall::West::None).ID: return 11410; case PrismarineWall::PrismarineWall(PrismarineWall::East::Tall, PrismarineWall::North::None, PrismarineWall::South::None, true, PrismarineWall::West::Low).ID: return 11411; case PrismarineWall::PrismarineWall(PrismarineWall::East::Tall, PrismarineWall::North::None, PrismarineWall::South::None, true, PrismarineWall::West::Tall).ID: return 11412; case PrismarineWall::PrismarineWall(PrismarineWall::East::Tall, PrismarineWall::North::None, PrismarineWall::South::None, false, PrismarineWall::West::None).ID: return 11416; case PrismarineWall::PrismarineWall(PrismarineWall::East::Tall, PrismarineWall::North::None, PrismarineWall::South::None, false, PrismarineWall::West::Low).ID: return 11417; case PrismarineWall::PrismarineWall(PrismarineWall::East::Tall, PrismarineWall::North::None, PrismarineWall::South::None, false, PrismarineWall::West::Tall).ID: return 11418; case PrismarineWall::PrismarineWall(PrismarineWall::East::Tall, PrismarineWall::North::None, PrismarineWall::South::Low, true, PrismarineWall::West::None).ID: return 11422; case PrismarineWall::PrismarineWall(PrismarineWall::East::Tall, PrismarineWall::North::None, PrismarineWall::South::Low, true, PrismarineWall::West::Low).ID: return 11423; case PrismarineWall::PrismarineWall(PrismarineWall::East::Tall, PrismarineWall::North::None, PrismarineWall::South::Low, true, PrismarineWall::West::Tall).ID: return 11424; case PrismarineWall::PrismarineWall(PrismarineWall::East::Tall, PrismarineWall::North::None, PrismarineWall::South::Low, false, PrismarineWall::West::None).ID: return 11428; case PrismarineWall::PrismarineWall(PrismarineWall::East::Tall, PrismarineWall::North::None, PrismarineWall::South::Low, false, PrismarineWall::West::Low).ID: return 11429; case PrismarineWall::PrismarineWall(PrismarineWall::East::Tall, PrismarineWall::North::None, PrismarineWall::South::Low, false, PrismarineWall::West::Tall).ID: return 11430; case PrismarineWall::PrismarineWall(PrismarineWall::East::Tall, PrismarineWall::North::None, PrismarineWall::South::Tall, true, PrismarineWall::West::None).ID: return 11434; case PrismarineWall::PrismarineWall(PrismarineWall::East::Tall, PrismarineWall::North::None, PrismarineWall::South::Tall, true, PrismarineWall::West::Low).ID: return 11435; case PrismarineWall::PrismarineWall(PrismarineWall::East::Tall, PrismarineWall::North::None, PrismarineWall::South::Tall, true, PrismarineWall::West::Tall).ID: return 11436; case PrismarineWall::PrismarineWall(PrismarineWall::East::Tall, PrismarineWall::North::None, PrismarineWall::South::Tall, false, PrismarineWall::West::None).ID: return 11440; case PrismarineWall::PrismarineWall(PrismarineWall::East::Tall, PrismarineWall::North::None, PrismarineWall::South::Tall, false, PrismarineWall::West::Low).ID: return 11441; case PrismarineWall::PrismarineWall(PrismarineWall::East::Tall, PrismarineWall::North::None, PrismarineWall::South::Tall, false, PrismarineWall::West::Tall).ID: return 11442; case PrismarineWall::PrismarineWall(PrismarineWall::East::Tall, PrismarineWall::North::Low, PrismarineWall::South::None, true, PrismarineWall::West::None).ID: return 11446; case PrismarineWall::PrismarineWall(PrismarineWall::East::Tall, PrismarineWall::North::Low, PrismarineWall::South::None, true, PrismarineWall::West::Low).ID: return 11447; case PrismarineWall::PrismarineWall(PrismarineWall::East::Tall, PrismarineWall::North::Low, PrismarineWall::South::None, true, PrismarineWall::West::Tall).ID: return 11448; case PrismarineWall::PrismarineWall(PrismarineWall::East::Tall, PrismarineWall::North::Low, PrismarineWall::South::None, false, PrismarineWall::West::None).ID: return 11452; case PrismarineWall::PrismarineWall(PrismarineWall::East::Tall, PrismarineWall::North::Low, PrismarineWall::South::None, false, PrismarineWall::West::Low).ID: return 11453; case PrismarineWall::PrismarineWall(PrismarineWall::East::Tall, PrismarineWall::North::Low, PrismarineWall::South::None, false, PrismarineWall::West::Tall).ID: return 11454; case PrismarineWall::PrismarineWall(PrismarineWall::East::Tall, PrismarineWall::North::Low, PrismarineWall::South::Low, true, PrismarineWall::West::None).ID: return 11458; case PrismarineWall::PrismarineWall(PrismarineWall::East::Tall, PrismarineWall::North::Low, PrismarineWall::South::Low, true, PrismarineWall::West::Low).ID: return 11459; case PrismarineWall::PrismarineWall(PrismarineWall::East::Tall, PrismarineWall::North::Low, PrismarineWall::South::Low, true, PrismarineWall::West::Tall).ID: return 11460; case PrismarineWall::PrismarineWall(PrismarineWall::East::Tall, PrismarineWall::North::Low, PrismarineWall::South::Low, false, PrismarineWall::West::None).ID: return 11464; case PrismarineWall::PrismarineWall(PrismarineWall::East::Tall, PrismarineWall::North::Low, PrismarineWall::South::Low, false, PrismarineWall::West::Low).ID: return 11465; case PrismarineWall::PrismarineWall(PrismarineWall::East::Tall, PrismarineWall::North::Low, PrismarineWall::South::Low, false, PrismarineWall::West::Tall).ID: return 11466; case PrismarineWall::PrismarineWall(PrismarineWall::East::Tall, PrismarineWall::North::Low, PrismarineWall::South::Tall, true, PrismarineWall::West::None).ID: return 11470; case PrismarineWall::PrismarineWall(PrismarineWall::East::Tall, PrismarineWall::North::Low, PrismarineWall::South::Tall, true, PrismarineWall::West::Low).ID: return 11471; case PrismarineWall::PrismarineWall(PrismarineWall::East::Tall, PrismarineWall::North::Low, PrismarineWall::South::Tall, true, PrismarineWall::West::Tall).ID: return 11472; case PrismarineWall::PrismarineWall(PrismarineWall::East::Tall, PrismarineWall::North::Low, PrismarineWall::South::Tall, false, PrismarineWall::West::None).ID: return 11476; case PrismarineWall::PrismarineWall(PrismarineWall::East::Tall, PrismarineWall::North::Low, PrismarineWall::South::Tall, false, PrismarineWall::West::Low).ID: return 11477; case PrismarineWall::PrismarineWall(PrismarineWall::East::Tall, PrismarineWall::North::Low, PrismarineWall::South::Tall, false, PrismarineWall::West::Tall).ID: return 11478; case PrismarineWall::PrismarineWall(PrismarineWall::East::Tall, PrismarineWall::North::Tall, PrismarineWall::South::None, true, PrismarineWall::West::None).ID: return 11482; case PrismarineWall::PrismarineWall(PrismarineWall::East::Tall, PrismarineWall::North::Tall, PrismarineWall::South::None, true, PrismarineWall::West::Low).ID: return 11483; case PrismarineWall::PrismarineWall(PrismarineWall::East::Tall, PrismarineWall::North::Tall, PrismarineWall::South::None, true, PrismarineWall::West::Tall).ID: return 11484; case PrismarineWall::PrismarineWall(PrismarineWall::East::Tall, PrismarineWall::North::Tall, PrismarineWall::South::None, false, PrismarineWall::West::None).ID: return 11488; case PrismarineWall::PrismarineWall(PrismarineWall::East::Tall, PrismarineWall::North::Tall, PrismarineWall::South::None, false, PrismarineWall::West::Low).ID: return 11489; case PrismarineWall::PrismarineWall(PrismarineWall::East::Tall, PrismarineWall::North::Tall, PrismarineWall::South::None, false, PrismarineWall::West::Tall).ID: return 11490; case PrismarineWall::PrismarineWall(PrismarineWall::East::Tall, PrismarineWall::North::Tall, PrismarineWall::South::Low, true, PrismarineWall::West::None).ID: return 11494; case PrismarineWall::PrismarineWall(PrismarineWall::East::Tall, PrismarineWall::North::Tall, PrismarineWall::South::Low, true, PrismarineWall::West::Low).ID: return 11495; case PrismarineWall::PrismarineWall(PrismarineWall::East::Tall, PrismarineWall::North::Tall, PrismarineWall::South::Low, true, PrismarineWall::West::Tall).ID: return 11496; case PrismarineWall::PrismarineWall(PrismarineWall::East::Tall, PrismarineWall::North::Tall, PrismarineWall::South::Low, false, PrismarineWall::West::None).ID: return 11500; case PrismarineWall::PrismarineWall(PrismarineWall::East::Tall, PrismarineWall::North::Tall, PrismarineWall::South::Low, false, PrismarineWall::West::Low).ID: return 11501; case PrismarineWall::PrismarineWall(PrismarineWall::East::Tall, PrismarineWall::North::Tall, PrismarineWall::South::Low, false, PrismarineWall::West::Tall).ID: return 11502; case PrismarineWall::PrismarineWall(PrismarineWall::East::Tall, PrismarineWall::North::Tall, PrismarineWall::South::Tall, true, PrismarineWall::West::None).ID: return 11506; case PrismarineWall::PrismarineWall(PrismarineWall::East::Tall, PrismarineWall::North::Tall, PrismarineWall::South::Tall, true, PrismarineWall::West::Low).ID: return 11507; case PrismarineWall::PrismarineWall(PrismarineWall::East::Tall, PrismarineWall::North::Tall, PrismarineWall::South::Tall, true, PrismarineWall::West::Tall).ID: return 11508; case PrismarineWall::PrismarineWall(PrismarineWall::East::Tall, PrismarineWall::North::Tall, PrismarineWall::South::Tall, false, PrismarineWall::West::None).ID: return 11512; case PrismarineWall::PrismarineWall(PrismarineWall::East::Tall, PrismarineWall::North::Tall, PrismarineWall::South::Tall, false, PrismarineWall::West::Low).ID: return 11513; case PrismarineWall::PrismarineWall(PrismarineWall::East::Tall, PrismarineWall::North::Tall, PrismarineWall::South::Tall, false, PrismarineWall::West::Tall).ID: return 11514; case Pumpkin::Pumpkin().ID: return 3998; case PumpkinStem::PumpkinStem(0).ID: return 4772; case PumpkinStem::PumpkinStem(1).ID: return 4773; case PumpkinStem::PumpkinStem(2).ID: return 4774; case PumpkinStem::PumpkinStem(3).ID: return 4775; case PumpkinStem::PumpkinStem(4).ID: return 4776; case PumpkinStem::PumpkinStem(5).ID: return 4777; case PumpkinStem::PumpkinStem(6).ID: return 4778; case PumpkinStem::PumpkinStem(7).ID: return 4779; case PurpleBanner::PurpleBanner(0).ID: return 8057; case PurpleBanner::PurpleBanner(1).ID: return 8058; case PurpleBanner::PurpleBanner(2).ID: return 8059; case PurpleBanner::PurpleBanner(3).ID: return 8060; case PurpleBanner::PurpleBanner(4).ID: return 8061; case PurpleBanner::PurpleBanner(5).ID: return 8062; case PurpleBanner::PurpleBanner(6).ID: return 8063; case PurpleBanner::PurpleBanner(7).ID: return 8064; case PurpleBanner::PurpleBanner(8).ID: return 8065; case PurpleBanner::PurpleBanner(9).ID: return 8066; case PurpleBanner::PurpleBanner(10).ID: return 8067; case PurpleBanner::PurpleBanner(11).ID: return 8068; case PurpleBanner::PurpleBanner(12).ID: return 8069; case PurpleBanner::PurpleBanner(13).ID: return 8070; case PurpleBanner::PurpleBanner(14).ID: return 8071; case PurpleBanner::PurpleBanner(15).ID: return 8072; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_ZM, true, PurpleBed::Part::Head).ID: return 1209; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_ZM, true, PurpleBed::Part::Foot).ID: return 1210; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_ZM, false, PurpleBed::Part::Head).ID: return 1211; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_ZM, false, PurpleBed::Part::Foot).ID: return 1212; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_ZP, true, PurpleBed::Part::Head).ID: return 1213; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_ZP, true, PurpleBed::Part::Foot).ID: return 1214; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_ZP, false, PurpleBed::Part::Head).ID: return 1215; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_ZP, false, PurpleBed::Part::Foot).ID: return 1216; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_XM, true, PurpleBed::Part::Head).ID: return 1217; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_XM, true, PurpleBed::Part::Foot).ID: return 1218; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_XM, false, PurpleBed::Part::Head).ID: return 1219; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_XM, false, PurpleBed::Part::Foot).ID: return 1220; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_XP, true, PurpleBed::Part::Head).ID: return 1221; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_XP, true, PurpleBed::Part::Foot).ID: return 1222; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_XP, false, PurpleBed::Part::Head).ID: return 1223; case PurpleBed::PurpleBed(eBlockFace::BLOCK_FACE_XP, false, PurpleBed::Part::Foot).ID: return 1224; case PurpleCarpet::PurpleCarpet().ID: return 7876; case PurpleConcrete::PurpleConcrete().ID: return 9448; case PurpleConcretePowder::PurpleConcretePowder().ID: return 9464; case PurpleGlazedTerracotta::PurpleGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 9414; case PurpleGlazedTerracotta::PurpleGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 9415; case PurpleGlazedTerracotta::PurpleGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 9416; case PurpleGlazedTerracotta::PurpleGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 9417; case PurpleShulkerBox::PurpleShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 9338; case PurpleShulkerBox::PurpleShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 9339; case PurpleShulkerBox::PurpleShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 9340; case PurpleShulkerBox::PurpleShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 9341; case PurpleShulkerBox::PurpleShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 9342; case PurpleShulkerBox::PurpleShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 9343; case PurpleStainedGlass::PurpleStainedGlass().ID: return 4105; case PurpleStainedGlassPane::PurpleStainedGlassPane(true, true, true, true).ID: return 7185; case PurpleStainedGlassPane::PurpleStainedGlassPane(true, true, true, false).ID: return 7186; case PurpleStainedGlassPane::PurpleStainedGlassPane(true, true, false, true).ID: return 7189; case PurpleStainedGlassPane::PurpleStainedGlassPane(true, true, false, false).ID: return 7190; case PurpleStainedGlassPane::PurpleStainedGlassPane(true, false, true, true).ID: return 7193; case PurpleStainedGlassPane::PurpleStainedGlassPane(true, false, true, false).ID: return 7194; case PurpleStainedGlassPane::PurpleStainedGlassPane(true, false, false, true).ID: return 7197; case PurpleStainedGlassPane::PurpleStainedGlassPane(true, false, false, false).ID: return 7198; case PurpleStainedGlassPane::PurpleStainedGlassPane(false, true, true, true).ID: return 7201; case PurpleStainedGlassPane::PurpleStainedGlassPane(false, true, true, false).ID: return 7202; case PurpleStainedGlassPane::PurpleStainedGlassPane(false, true, false, true).ID: return 7205; case PurpleStainedGlassPane::PurpleStainedGlassPane(false, true, false, false).ID: return 7206; case PurpleStainedGlassPane::PurpleStainedGlassPane(false, false, true, true).ID: return 7209; case PurpleStainedGlassPane::PurpleStainedGlassPane(false, false, true, false).ID: return 7210; case PurpleStainedGlassPane::PurpleStainedGlassPane(false, false, false, true).ID: return 7213; case PurpleStainedGlassPane::PurpleStainedGlassPane(false, false, false, false).ID: return 7214; case PurpleTerracotta::PurpleTerracotta().ID: return 6857; case PurpleWallBanner::PurpleWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 8193; case PurpleWallBanner::PurpleWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 8194; case PurpleWallBanner::PurpleWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 8195; case PurpleWallBanner::PurpleWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 8196; case PurpleWool::PurpleWool().ID: return 1394; case PurpurBlock::PurpurBlock().ID: return 9134; case PurpurPillar::PurpurPillar(PurpurPillar::Axis::X).ID: return 9135; case PurpurPillar::PurpurPillar(PurpurPillar::Axis::Y).ID: return 9136; case PurpurPillar::PurpurPillar(PurpurPillar::Axis::Z).ID: return 9137; case PurpurSlab::PurpurSlab(PurpurSlab::Type::Top).ID: return 8409; case PurpurSlab::PurpurSlab(PurpurSlab::Type::Bottom).ID: return 8411; case PurpurSlab::PurpurSlab(PurpurSlab::Type::Double).ID: return 8413; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZM, PurpurStairs::Half::Top, PurpurStairs::Shape::Straight).ID: return 9139; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZM, PurpurStairs::Half::Top, PurpurStairs::Shape::InnerLeft).ID: return 9141; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZM, PurpurStairs::Half::Top, PurpurStairs::Shape::InnerRight).ID: return 9143; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZM, PurpurStairs::Half::Top, PurpurStairs::Shape::OuterLeft).ID: return 9145; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZM, PurpurStairs::Half::Top, PurpurStairs::Shape::OuterRight).ID: return 9147; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZM, PurpurStairs::Half::Bottom, PurpurStairs::Shape::Straight).ID: return 9149; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZM, PurpurStairs::Half::Bottom, PurpurStairs::Shape::InnerLeft).ID: return 9151; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZM, PurpurStairs::Half::Bottom, PurpurStairs::Shape::InnerRight).ID: return 9153; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZM, PurpurStairs::Half::Bottom, PurpurStairs::Shape::OuterLeft).ID: return 9155; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZM, PurpurStairs::Half::Bottom, PurpurStairs::Shape::OuterRight).ID: return 9157; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZP, PurpurStairs::Half::Top, PurpurStairs::Shape::Straight).ID: return 9159; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZP, PurpurStairs::Half::Top, PurpurStairs::Shape::InnerLeft).ID: return 9161; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZP, PurpurStairs::Half::Top, PurpurStairs::Shape::InnerRight).ID: return 9163; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZP, PurpurStairs::Half::Top, PurpurStairs::Shape::OuterLeft).ID: return 9165; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZP, PurpurStairs::Half::Top, PurpurStairs::Shape::OuterRight).ID: return 9167; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZP, PurpurStairs::Half::Bottom, PurpurStairs::Shape::Straight).ID: return 9169; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZP, PurpurStairs::Half::Bottom, PurpurStairs::Shape::InnerLeft).ID: return 9171; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZP, PurpurStairs::Half::Bottom, PurpurStairs::Shape::InnerRight).ID: return 9173; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZP, PurpurStairs::Half::Bottom, PurpurStairs::Shape::OuterLeft).ID: return 9175; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZP, PurpurStairs::Half::Bottom, PurpurStairs::Shape::OuterRight).ID: return 9177; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XM, PurpurStairs::Half::Top, PurpurStairs::Shape::Straight).ID: return 9179; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XM, PurpurStairs::Half::Top, PurpurStairs::Shape::InnerLeft).ID: return 9181; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XM, PurpurStairs::Half::Top, PurpurStairs::Shape::InnerRight).ID: return 9183; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XM, PurpurStairs::Half::Top, PurpurStairs::Shape::OuterLeft).ID: return 9185; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XM, PurpurStairs::Half::Top, PurpurStairs::Shape::OuterRight).ID: return 9187; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XM, PurpurStairs::Half::Bottom, PurpurStairs::Shape::Straight).ID: return 9189; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XM, PurpurStairs::Half::Bottom, PurpurStairs::Shape::InnerLeft).ID: return 9191; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XM, PurpurStairs::Half::Bottom, PurpurStairs::Shape::InnerRight).ID: return 9193; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XM, PurpurStairs::Half::Bottom, PurpurStairs::Shape::OuterLeft).ID: return 9195; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XM, PurpurStairs::Half::Bottom, PurpurStairs::Shape::OuterRight).ID: return 9197; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XP, PurpurStairs::Half::Top, PurpurStairs::Shape::Straight).ID: return 9199; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XP, PurpurStairs::Half::Top, PurpurStairs::Shape::InnerLeft).ID: return 9201; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XP, PurpurStairs::Half::Top, PurpurStairs::Shape::InnerRight).ID: return 9203; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XP, PurpurStairs::Half::Top, PurpurStairs::Shape::OuterLeft).ID: return 9205; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XP, PurpurStairs::Half::Top, PurpurStairs::Shape::OuterRight).ID: return 9207; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XP, PurpurStairs::Half::Bottom, PurpurStairs::Shape::Straight).ID: return 9209; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XP, PurpurStairs::Half::Bottom, PurpurStairs::Shape::InnerLeft).ID: return 9211; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XP, PurpurStairs::Half::Bottom, PurpurStairs::Shape::InnerRight).ID: return 9213; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XP, PurpurStairs::Half::Bottom, PurpurStairs::Shape::OuterLeft).ID: return 9215; case PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XP, PurpurStairs::Half::Bottom, PurpurStairs::Shape::OuterRight).ID: return 9217; case QuartzBlock::QuartzBlock().ID: return 6738; case QuartzBricks::QuartzBricks().ID: return 17103; case QuartzPillar::QuartzPillar(QuartzPillar::Axis::X).ID: return 6740; case QuartzPillar::QuartzPillar(QuartzPillar::Axis::Y).ID: return 6741; case QuartzPillar::QuartzPillar(QuartzPillar::Axis::Z).ID: return 6742; case QuartzSlab::QuartzSlab(QuartzSlab::Type::Top).ID: return 8391; case QuartzSlab::QuartzSlab(QuartzSlab::Type::Bottom).ID: return 8393; case QuartzSlab::QuartzSlab(QuartzSlab::Type::Double).ID: return 8395; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZM, QuartzStairs::Half::Top, QuartzStairs::Shape::Straight).ID: return 6744; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZM, QuartzStairs::Half::Top, QuartzStairs::Shape::InnerLeft).ID: return 6746; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZM, QuartzStairs::Half::Top, QuartzStairs::Shape::InnerRight).ID: return 6748; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZM, QuartzStairs::Half::Top, QuartzStairs::Shape::OuterLeft).ID: return 6750; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZM, QuartzStairs::Half::Top, QuartzStairs::Shape::OuterRight).ID: return 6752; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZM, QuartzStairs::Half::Bottom, QuartzStairs::Shape::Straight).ID: return 6754; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZM, QuartzStairs::Half::Bottom, QuartzStairs::Shape::InnerLeft).ID: return 6756; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZM, QuartzStairs::Half::Bottom, QuartzStairs::Shape::InnerRight).ID: return 6758; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZM, QuartzStairs::Half::Bottom, QuartzStairs::Shape::OuterLeft).ID: return 6760; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZM, QuartzStairs::Half::Bottom, QuartzStairs::Shape::OuterRight).ID: return 6762; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZP, QuartzStairs::Half::Top, QuartzStairs::Shape::Straight).ID: return 6764; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZP, QuartzStairs::Half::Top, QuartzStairs::Shape::InnerLeft).ID: return 6766; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZP, QuartzStairs::Half::Top, QuartzStairs::Shape::InnerRight).ID: return 6768; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZP, QuartzStairs::Half::Top, QuartzStairs::Shape::OuterLeft).ID: return 6770; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZP, QuartzStairs::Half::Top, QuartzStairs::Shape::OuterRight).ID: return 6772; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZP, QuartzStairs::Half::Bottom, QuartzStairs::Shape::Straight).ID: return 6774; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZP, QuartzStairs::Half::Bottom, QuartzStairs::Shape::InnerLeft).ID: return 6776; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZP, QuartzStairs::Half::Bottom, QuartzStairs::Shape::InnerRight).ID: return 6778; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZP, QuartzStairs::Half::Bottom, QuartzStairs::Shape::OuterLeft).ID: return 6780; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZP, QuartzStairs::Half::Bottom, QuartzStairs::Shape::OuterRight).ID: return 6782; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XM, QuartzStairs::Half::Top, QuartzStairs::Shape::Straight).ID: return 6784; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XM, QuartzStairs::Half::Top, QuartzStairs::Shape::InnerLeft).ID: return 6786; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XM, QuartzStairs::Half::Top, QuartzStairs::Shape::InnerRight).ID: return 6788; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XM, QuartzStairs::Half::Top, QuartzStairs::Shape::OuterLeft).ID: return 6790; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XM, QuartzStairs::Half::Top, QuartzStairs::Shape::OuterRight).ID: return 6792; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XM, QuartzStairs::Half::Bottom, QuartzStairs::Shape::Straight).ID: return 6794; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XM, QuartzStairs::Half::Bottom, QuartzStairs::Shape::InnerLeft).ID: return 6796; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XM, QuartzStairs::Half::Bottom, QuartzStairs::Shape::InnerRight).ID: return 6798; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XM, QuartzStairs::Half::Bottom, QuartzStairs::Shape::OuterLeft).ID: return 6800; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XM, QuartzStairs::Half::Bottom, QuartzStairs::Shape::OuterRight).ID: return 6802; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XP, QuartzStairs::Half::Top, QuartzStairs::Shape::Straight).ID: return 6804; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XP, QuartzStairs::Half::Top, QuartzStairs::Shape::InnerLeft).ID: return 6806; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XP, QuartzStairs::Half::Top, QuartzStairs::Shape::InnerRight).ID: return 6808; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XP, QuartzStairs::Half::Top, QuartzStairs::Shape::OuterLeft).ID: return 6810; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XP, QuartzStairs::Half::Top, QuartzStairs::Shape::OuterRight).ID: return 6812; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XP, QuartzStairs::Half::Bottom, QuartzStairs::Shape::Straight).ID: return 6814; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XP, QuartzStairs::Half::Bottom, QuartzStairs::Shape::InnerLeft).ID: return 6816; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XP, QuartzStairs::Half::Bottom, QuartzStairs::Shape::InnerRight).ID: return 6818; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XP, QuartzStairs::Half::Bottom, QuartzStairs::Shape::OuterLeft).ID: return 6820; case QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XP, QuartzStairs::Half::Bottom, QuartzStairs::Shape::OuterRight).ID: return 6822; case Rail::Rail(Rail::Shape::NorthSouth).ID: return 3645; case Rail::Rail(Rail::Shape::EastWest).ID: return 3646; case Rail::Rail(Rail::Shape::AscendingEast).ID: return 3647; case Rail::Rail(Rail::Shape::AscendingWest).ID: return 3648; case Rail::Rail(Rail::Shape::AscendingNorth).ID: return 3649; case Rail::Rail(Rail::Shape::AscendingSouth).ID: return 3650; case Rail::Rail(Rail::Shape::SouthEast).ID: return 3651; case Rail::Rail(Rail::Shape::SouthWest).ID: return 3652; case Rail::Rail(Rail::Shape::NorthWest).ID: return 3653; case Rail::Rail(Rail::Shape::NorthEast).ID: return 3654; case RedBanner::RedBanner(0).ID: return 8121; case RedBanner::RedBanner(1).ID: return 8122; case RedBanner::RedBanner(2).ID: return 8123; case RedBanner::RedBanner(3).ID: return 8124; case RedBanner::RedBanner(4).ID: return 8125; case RedBanner::RedBanner(5).ID: return 8126; case RedBanner::RedBanner(6).ID: return 8127; case RedBanner::RedBanner(7).ID: return 8128; case RedBanner::RedBanner(8).ID: return 8129; case RedBanner::RedBanner(9).ID: return 8130; case RedBanner::RedBanner(10).ID: return 8131; case RedBanner::RedBanner(11).ID: return 8132; case RedBanner::RedBanner(12).ID: return 8133; case RedBanner::RedBanner(13).ID: return 8134; case RedBanner::RedBanner(14).ID: return 8135; case RedBanner::RedBanner(15).ID: return 8136; case RedBed::RedBed(eBlockFace::BLOCK_FACE_ZM, true, RedBed::Part::Head).ID: return 1273; case RedBed::RedBed(eBlockFace::BLOCK_FACE_ZM, true, RedBed::Part::Foot).ID: return 1274; case RedBed::RedBed(eBlockFace::BLOCK_FACE_ZM, false, RedBed::Part::Head).ID: return 1275; case RedBed::RedBed(eBlockFace::BLOCK_FACE_ZM, false, RedBed::Part::Foot).ID: return 1276; case RedBed::RedBed(eBlockFace::BLOCK_FACE_ZP, true, RedBed::Part::Head).ID: return 1277; case RedBed::RedBed(eBlockFace::BLOCK_FACE_ZP, true, RedBed::Part::Foot).ID: return 1278; case RedBed::RedBed(eBlockFace::BLOCK_FACE_ZP, false, RedBed::Part::Head).ID: return 1279; case RedBed::RedBed(eBlockFace::BLOCK_FACE_ZP, false, RedBed::Part::Foot).ID: return 1280; case RedBed::RedBed(eBlockFace::BLOCK_FACE_XM, true, RedBed::Part::Head).ID: return 1281; case RedBed::RedBed(eBlockFace::BLOCK_FACE_XM, true, RedBed::Part::Foot).ID: return 1282; case RedBed::RedBed(eBlockFace::BLOCK_FACE_XM, false, RedBed::Part::Head).ID: return 1283; case RedBed::RedBed(eBlockFace::BLOCK_FACE_XM, false, RedBed::Part::Foot).ID: return 1284; case RedBed::RedBed(eBlockFace::BLOCK_FACE_XP, true, RedBed::Part::Head).ID: return 1285; case RedBed::RedBed(eBlockFace::BLOCK_FACE_XP, true, RedBed::Part::Foot).ID: return 1286; case RedBed::RedBed(eBlockFace::BLOCK_FACE_XP, false, RedBed::Part::Head).ID: return 1287; case RedBed::RedBed(eBlockFace::BLOCK_FACE_XP, false, RedBed::Part::Foot).ID: return 1288; case RedCarpet::RedCarpet().ID: return 7880; case RedConcrete::RedConcrete().ID: return 9452; case RedConcretePowder::RedConcretePowder().ID: return 9468; case RedGlazedTerracotta::RedGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 9430; case RedGlazedTerracotta::RedGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 9431; case RedGlazedTerracotta::RedGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 9432; case RedGlazedTerracotta::RedGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 9433; case RedMushroom::RedMushroom().ID: return 1426; case RedMushroomBlock::RedMushroomBlock(true, true, true, true, true, true).ID: return 4569; case RedMushroomBlock::RedMushroomBlock(true, true, true, true, true, false).ID: return 4570; case RedMushroomBlock::RedMushroomBlock(true, true, true, true, false, true).ID: return 4571; case RedMushroomBlock::RedMushroomBlock(true, true, true, true, false, false).ID: return 4572; case RedMushroomBlock::RedMushroomBlock(true, true, true, false, true, true).ID: return 4573; case RedMushroomBlock::RedMushroomBlock(true, true, true, false, true, false).ID: return 4574; case RedMushroomBlock::RedMushroomBlock(true, true, true, false, false, true).ID: return 4575; case RedMushroomBlock::RedMushroomBlock(true, true, true, false, false, false).ID: return 4576; case RedMushroomBlock::RedMushroomBlock(true, true, false, true, true, true).ID: return 4577; case RedMushroomBlock::RedMushroomBlock(true, true, false, true, true, false).ID: return 4578; case RedMushroomBlock::RedMushroomBlock(true, true, false, true, false, true).ID: return 4579; case RedMushroomBlock::RedMushroomBlock(true, true, false, true, false, false).ID: return 4580; case RedMushroomBlock::RedMushroomBlock(true, true, false, false, true, true).ID: return 4581; case RedMushroomBlock::RedMushroomBlock(true, true, false, false, true, false).ID: return 4582; case RedMushroomBlock::RedMushroomBlock(true, true, false, false, false, true).ID: return 4583; case RedMushroomBlock::RedMushroomBlock(true, true, false, false, false, false).ID: return 4584; case RedMushroomBlock::RedMushroomBlock(true, false, true, true, true, true).ID: return 4585; case RedMushroomBlock::RedMushroomBlock(true, false, true, true, true, false).ID: return 4586; case RedMushroomBlock::RedMushroomBlock(true, false, true, true, false, true).ID: return 4587; case RedMushroomBlock::RedMushroomBlock(true, false, true, true, false, false).ID: return 4588; case RedMushroomBlock::RedMushroomBlock(true, false, true, false, true, true).ID: return 4589; case RedMushroomBlock::RedMushroomBlock(true, false, true, false, true, false).ID: return 4590; case RedMushroomBlock::RedMushroomBlock(true, false, true, false, false, true).ID: return 4591; case RedMushroomBlock::RedMushroomBlock(true, false, true, false, false, false).ID: return 4592; case RedMushroomBlock::RedMushroomBlock(true, false, false, true, true, true).ID: return 4593; case RedMushroomBlock::RedMushroomBlock(true, false, false, true, true, false).ID: return 4594; case RedMushroomBlock::RedMushroomBlock(true, false, false, true, false, true).ID: return 4595; case RedMushroomBlock::RedMushroomBlock(true, false, false, true, false, false).ID: return 4596; case RedMushroomBlock::RedMushroomBlock(true, false, false, false, true, true).ID: return 4597; case RedMushroomBlock::RedMushroomBlock(true, false, false, false, true, false).ID: return 4598; case RedMushroomBlock::RedMushroomBlock(true, false, false, false, false, true).ID: return 4599; case RedMushroomBlock::RedMushroomBlock(true, false, false, false, false, false).ID: return 4600; case RedMushroomBlock::RedMushroomBlock(false, true, true, true, true, true).ID: return 4601; case RedMushroomBlock::RedMushroomBlock(false, true, true, true, true, false).ID: return 4602; case RedMushroomBlock::RedMushroomBlock(false, true, true, true, false, true).ID: return 4603; case RedMushroomBlock::RedMushroomBlock(false, true, true, true, false, false).ID: return 4604; case RedMushroomBlock::RedMushroomBlock(false, true, true, false, true, true).ID: return 4605; case RedMushroomBlock::RedMushroomBlock(false, true, true, false, true, false).ID: return 4606; case RedMushroomBlock::RedMushroomBlock(false, true, true, false, false, true).ID: return 4607; case RedMushroomBlock::RedMushroomBlock(false, true, true, false, false, false).ID: return 4608; case RedMushroomBlock::RedMushroomBlock(false, true, false, true, true, true).ID: return 4609; case RedMushroomBlock::RedMushroomBlock(false, true, false, true, true, false).ID: return 4610; case RedMushroomBlock::RedMushroomBlock(false, true, false, true, false, true).ID: return 4611; case RedMushroomBlock::RedMushroomBlock(false, true, false, true, false, false).ID: return 4612; case RedMushroomBlock::RedMushroomBlock(false, true, false, false, true, true).ID: return 4613; case RedMushroomBlock::RedMushroomBlock(false, true, false, false, true, false).ID: return 4614; case RedMushroomBlock::RedMushroomBlock(false, true, false, false, false, true).ID: return 4615; case RedMushroomBlock::RedMushroomBlock(false, true, false, false, false, false).ID: return 4616; case RedMushroomBlock::RedMushroomBlock(false, false, true, true, true, true).ID: return 4617; case RedMushroomBlock::RedMushroomBlock(false, false, true, true, true, false).ID: return 4618; case RedMushroomBlock::RedMushroomBlock(false, false, true, true, false, true).ID: return 4619; case RedMushroomBlock::RedMushroomBlock(false, false, true, true, false, false).ID: return 4620; case RedMushroomBlock::RedMushroomBlock(false, false, true, false, true, true).ID: return 4621; case RedMushroomBlock::RedMushroomBlock(false, false, true, false, true, false).ID: return 4622; case RedMushroomBlock::RedMushroomBlock(false, false, true, false, false, true).ID: return 4623; case RedMushroomBlock::RedMushroomBlock(false, false, true, false, false, false).ID: return 4624; case RedMushroomBlock::RedMushroomBlock(false, false, false, true, true, true).ID: return 4625; case RedMushroomBlock::RedMushroomBlock(false, false, false, true, true, false).ID: return 4626; case RedMushroomBlock::RedMushroomBlock(false, false, false, true, false, true).ID: return 4627; case RedMushroomBlock::RedMushroomBlock(false, false, false, true, false, false).ID: return 4628; case RedMushroomBlock::RedMushroomBlock(false, false, false, false, true, true).ID: return 4629; case RedMushroomBlock::RedMushroomBlock(false, false, false, false, true, false).ID: return 4630; case RedMushroomBlock::RedMushroomBlock(false, false, false, false, false, true).ID: return 4631; case RedMushroomBlock::RedMushroomBlock(false, false, false, false, false, false).ID: return 4632; case RedNetherBrickSlab::RedNetherBrickSlab(RedNetherBrickSlab::Type::Top).ID: return 10850; case RedNetherBrickSlab::RedNetherBrickSlab(RedNetherBrickSlab::Type::Bottom).ID: return 10852; case RedNetherBrickSlab::RedNetherBrickSlab(RedNetherBrickSlab::Type::Double).ID: return 10854; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, RedNetherBrickStairs::Half::Top, RedNetherBrickStairs::Shape::Straight).ID: return 10550; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, RedNetherBrickStairs::Half::Top, RedNetherBrickStairs::Shape::InnerLeft).ID: return 10552; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, RedNetherBrickStairs::Half::Top, RedNetherBrickStairs::Shape::InnerRight).ID: return 10554; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, RedNetherBrickStairs::Half::Top, RedNetherBrickStairs::Shape::OuterLeft).ID: return 10556; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, RedNetherBrickStairs::Half::Top, RedNetherBrickStairs::Shape::OuterRight).ID: return 10558; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, RedNetherBrickStairs::Half::Bottom, RedNetherBrickStairs::Shape::Straight).ID: return 10560; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, RedNetherBrickStairs::Half::Bottom, RedNetherBrickStairs::Shape::InnerLeft).ID: return 10562; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, RedNetherBrickStairs::Half::Bottom, RedNetherBrickStairs::Shape::InnerRight).ID: return 10564; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, RedNetherBrickStairs::Half::Bottom, RedNetherBrickStairs::Shape::OuterLeft).ID: return 10566; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, RedNetherBrickStairs::Half::Bottom, RedNetherBrickStairs::Shape::OuterRight).ID: return 10568; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, RedNetherBrickStairs::Half::Top, RedNetherBrickStairs::Shape::Straight).ID: return 10570; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, RedNetherBrickStairs::Half::Top, RedNetherBrickStairs::Shape::InnerLeft).ID: return 10572; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, RedNetherBrickStairs::Half::Top, RedNetherBrickStairs::Shape::InnerRight).ID: return 10574; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, RedNetherBrickStairs::Half::Top, RedNetherBrickStairs::Shape::OuterLeft).ID: return 10576; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, RedNetherBrickStairs::Half::Top, RedNetherBrickStairs::Shape::OuterRight).ID: return 10578; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, RedNetherBrickStairs::Half::Bottom, RedNetherBrickStairs::Shape::Straight).ID: return 10580; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, RedNetherBrickStairs::Half::Bottom, RedNetherBrickStairs::Shape::InnerLeft).ID: return 10582; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, RedNetherBrickStairs::Half::Bottom, RedNetherBrickStairs::Shape::InnerRight).ID: return 10584; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, RedNetherBrickStairs::Half::Bottom, RedNetherBrickStairs::Shape::OuterLeft).ID: return 10586; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, RedNetherBrickStairs::Half::Bottom, RedNetherBrickStairs::Shape::OuterRight).ID: return 10588; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_XM, RedNetherBrickStairs::Half::Top, RedNetherBrickStairs::Shape::Straight).ID: return 10590; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_XM, RedNetherBrickStairs::Half::Top, RedNetherBrickStairs::Shape::InnerLeft).ID: return 10592; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_XM, RedNetherBrickStairs::Half::Top, RedNetherBrickStairs::Shape::InnerRight).ID: return 10594; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_XM, RedNetherBrickStairs::Half::Top, RedNetherBrickStairs::Shape::OuterLeft).ID: return 10596; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_XM, RedNetherBrickStairs::Half::Top, RedNetherBrickStairs::Shape::OuterRight).ID: return 10598; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_XM, RedNetherBrickStairs::Half::Bottom, RedNetherBrickStairs::Shape::Straight).ID: return 10600; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_XM, RedNetherBrickStairs::Half::Bottom, RedNetherBrickStairs::Shape::InnerLeft).ID: return 10602; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_XM, RedNetherBrickStairs::Half::Bottom, RedNetherBrickStairs::Shape::InnerRight).ID: return 10604; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_XM, RedNetherBrickStairs::Half::Bottom, RedNetherBrickStairs::Shape::OuterLeft).ID: return 10606; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_XM, RedNetherBrickStairs::Half::Bottom, RedNetherBrickStairs::Shape::OuterRight).ID: return 10608; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_XP, RedNetherBrickStairs::Half::Top, RedNetherBrickStairs::Shape::Straight).ID: return 10610; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_XP, RedNetherBrickStairs::Half::Top, RedNetherBrickStairs::Shape::InnerLeft).ID: return 10612; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_XP, RedNetherBrickStairs::Half::Top, RedNetherBrickStairs::Shape::InnerRight).ID: return 10614; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_XP, RedNetherBrickStairs::Half::Top, RedNetherBrickStairs::Shape::OuterLeft).ID: return 10616; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_XP, RedNetherBrickStairs::Half::Top, RedNetherBrickStairs::Shape::OuterRight).ID: return 10618; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_XP, RedNetherBrickStairs::Half::Bottom, RedNetherBrickStairs::Shape::Straight).ID: return 10620; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_XP, RedNetherBrickStairs::Half::Bottom, RedNetherBrickStairs::Shape::InnerLeft).ID: return 10622; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_XP, RedNetherBrickStairs::Half::Bottom, RedNetherBrickStairs::Shape::InnerRight).ID: return 10624; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_XP, RedNetherBrickStairs::Half::Bottom, RedNetherBrickStairs::Shape::OuterLeft).ID: return 10626; case RedNetherBrickStairs::RedNetherBrickStairs(eBlockFace::BLOCK_FACE_XP, RedNetherBrickStairs::Half::Bottom, RedNetherBrickStairs::Shape::OuterRight).ID: return 10628; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::None, RedNetherBrickWall::South::None, true, RedNetherBrickWall::West::None).ID: return 13462; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::None, RedNetherBrickWall::South::None, true, RedNetherBrickWall::West::Low).ID: return 13463; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::None, RedNetherBrickWall::South::None, true, RedNetherBrickWall::West::Tall).ID: return 13464; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::None, RedNetherBrickWall::South::None, false, RedNetherBrickWall::West::None).ID: return 13468; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::None, RedNetherBrickWall::South::None, false, RedNetherBrickWall::West::Low).ID: return 13469; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::None, RedNetherBrickWall::South::None, false, RedNetherBrickWall::West::Tall).ID: return 13470; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::None, RedNetherBrickWall::South::Low, true, RedNetherBrickWall::West::None).ID: return 13474; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::None, RedNetherBrickWall::South::Low, true, RedNetherBrickWall::West::Low).ID: return 13475; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::None, RedNetherBrickWall::South::Low, true, RedNetherBrickWall::West::Tall).ID: return 13476; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::None, RedNetherBrickWall::South::Low, false, RedNetherBrickWall::West::None).ID: return 13480; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::None, RedNetherBrickWall::South::Low, false, RedNetherBrickWall::West::Low).ID: return 13481; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::None, RedNetherBrickWall::South::Low, false, RedNetherBrickWall::West::Tall).ID: return 13482; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::None, RedNetherBrickWall::South::Tall, true, RedNetherBrickWall::West::None).ID: return 13486; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::None, RedNetherBrickWall::South::Tall, true, RedNetherBrickWall::West::Low).ID: return 13487; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::None, RedNetherBrickWall::South::Tall, true, RedNetherBrickWall::West::Tall).ID: return 13488; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::None, RedNetherBrickWall::South::Tall, false, RedNetherBrickWall::West::None).ID: return 13492; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::None, RedNetherBrickWall::South::Tall, false, RedNetherBrickWall::West::Low).ID: return 13493; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::None, RedNetherBrickWall::South::Tall, false, RedNetherBrickWall::West::Tall).ID: return 13494; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::None, true, RedNetherBrickWall::West::None).ID: return 13498; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::None, true, RedNetherBrickWall::West::Low).ID: return 13499; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::None, true, RedNetherBrickWall::West::Tall).ID: return 13500; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::None, false, RedNetherBrickWall::West::None).ID: return 13504; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::None, false, RedNetherBrickWall::West::Low).ID: return 13505; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::None, false, RedNetherBrickWall::West::Tall).ID: return 13506; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::Low, true, RedNetherBrickWall::West::None).ID: return 13510; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::Low, true, RedNetherBrickWall::West::Low).ID: return 13511; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::Low, true, RedNetherBrickWall::West::Tall).ID: return 13512; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::Low, false, RedNetherBrickWall::West::None).ID: return 13516; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::Low, false, RedNetherBrickWall::West::Low).ID: return 13517; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::Low, false, RedNetherBrickWall::West::Tall).ID: return 13518; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::Tall, true, RedNetherBrickWall::West::None).ID: return 13522; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::Tall, true, RedNetherBrickWall::West::Low).ID: return 13523; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::Tall, true, RedNetherBrickWall::West::Tall).ID: return 13524; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::Tall, false, RedNetherBrickWall::West::None).ID: return 13528; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::Tall, false, RedNetherBrickWall::West::Low).ID: return 13529; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::Tall, false, RedNetherBrickWall::West::Tall).ID: return 13530; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::Tall, RedNetherBrickWall::South::None, true, RedNetherBrickWall::West::None).ID: return 13534; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::Tall, RedNetherBrickWall::South::None, true, RedNetherBrickWall::West::Low).ID: return 13535; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::Tall, RedNetherBrickWall::South::None, true, RedNetherBrickWall::West::Tall).ID: return 13536; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::Tall, RedNetherBrickWall::South::None, false, RedNetherBrickWall::West::None).ID: return 13540; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::Tall, RedNetherBrickWall::South::None, false, RedNetherBrickWall::West::Low).ID: return 13541; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::Tall, RedNetherBrickWall::South::None, false, RedNetherBrickWall::West::Tall).ID: return 13542; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::Tall, RedNetherBrickWall::South::Low, true, RedNetherBrickWall::West::None).ID: return 13546; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::Tall, RedNetherBrickWall::South::Low, true, RedNetherBrickWall::West::Low).ID: return 13547; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::Tall, RedNetherBrickWall::South::Low, true, RedNetherBrickWall::West::Tall).ID: return 13548; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::Tall, RedNetherBrickWall::South::Low, false, RedNetherBrickWall::West::None).ID: return 13552; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::Tall, RedNetherBrickWall::South::Low, false, RedNetherBrickWall::West::Low).ID: return 13553; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::Tall, RedNetherBrickWall::South::Low, false, RedNetherBrickWall::West::Tall).ID: return 13554; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::Tall, RedNetherBrickWall::South::Tall, true, RedNetherBrickWall::West::None).ID: return 13558; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::Tall, RedNetherBrickWall::South::Tall, true, RedNetherBrickWall::West::Low).ID: return 13559; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::Tall, RedNetherBrickWall::South::Tall, true, RedNetherBrickWall::West::Tall).ID: return 13560; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::Tall, RedNetherBrickWall::South::Tall, false, RedNetherBrickWall::West::None).ID: return 13564; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::Tall, RedNetherBrickWall::South::Tall, false, RedNetherBrickWall::West::Low).ID: return 13565; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::None, RedNetherBrickWall::North::Tall, RedNetherBrickWall::South::Tall, false, RedNetherBrickWall::West::Tall).ID: return 13566; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::None, RedNetherBrickWall::South::None, true, RedNetherBrickWall::West::None).ID: return 13570; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::None, RedNetherBrickWall::South::None, true, RedNetherBrickWall::West::Low).ID: return 13571; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::None, RedNetherBrickWall::South::None, true, RedNetherBrickWall::West::Tall).ID: return 13572; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::None, RedNetherBrickWall::South::None, false, RedNetherBrickWall::West::None).ID: return 13576; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::None, RedNetherBrickWall::South::None, false, RedNetherBrickWall::West::Low).ID: return 13577; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::None, RedNetherBrickWall::South::None, false, RedNetherBrickWall::West::Tall).ID: return 13578; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::None, RedNetherBrickWall::South::Low, true, RedNetherBrickWall::West::None).ID: return 13582; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::None, RedNetherBrickWall::South::Low, true, RedNetherBrickWall::West::Low).ID: return 13583; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::None, RedNetherBrickWall::South::Low, true, RedNetherBrickWall::West::Tall).ID: return 13584; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::None, RedNetherBrickWall::South::Low, false, RedNetherBrickWall::West::None).ID: return 13588; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::None, RedNetherBrickWall::South::Low, false, RedNetherBrickWall::West::Low).ID: return 13589; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::None, RedNetherBrickWall::South::Low, false, RedNetherBrickWall::West::Tall).ID: return 13590; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::None, RedNetherBrickWall::South::Tall, true, RedNetherBrickWall::West::None).ID: return 13594; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::None, RedNetherBrickWall::South::Tall, true, RedNetherBrickWall::West::Low).ID: return 13595; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::None, RedNetherBrickWall::South::Tall, true, RedNetherBrickWall::West::Tall).ID: return 13596; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::None, RedNetherBrickWall::South::Tall, false, RedNetherBrickWall::West::None).ID: return 13600; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::None, RedNetherBrickWall::South::Tall, false, RedNetherBrickWall::West::Low).ID: return 13601; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::None, RedNetherBrickWall::South::Tall, false, RedNetherBrickWall::West::Tall).ID: return 13602; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::None, true, RedNetherBrickWall::West::None).ID: return 13606; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::None, true, RedNetherBrickWall::West::Low).ID: return 13607; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::None, true, RedNetherBrickWall::West::Tall).ID: return 13608; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::None, false, RedNetherBrickWall::West::None).ID: return 13612; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::None, false, RedNetherBrickWall::West::Low).ID: return 13613; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::None, false, RedNetherBrickWall::West::Tall).ID: return 13614; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::Low, true, RedNetherBrickWall::West::None).ID: return 13618; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::Low, true, RedNetherBrickWall::West::Low).ID: return 13619; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::Low, true, RedNetherBrickWall::West::Tall).ID: return 13620; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::Low, false, RedNetherBrickWall::West::None).ID: return 13624; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::Low, false, RedNetherBrickWall::West::Low).ID: return 13625; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::Low, false, RedNetherBrickWall::West::Tall).ID: return 13626; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::Tall, true, RedNetherBrickWall::West::None).ID: return 13630; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::Tall, true, RedNetherBrickWall::West::Low).ID: return 13631; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::Tall, true, RedNetherBrickWall::West::Tall).ID: return 13632; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::Tall, false, RedNetherBrickWall::West::None).ID: return 13636; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::Tall, false, RedNetherBrickWall::West::Low).ID: return 13637; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::Tall, false, RedNetherBrickWall::West::Tall).ID: return 13638; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::Tall, RedNetherBrickWall::South::None, true, RedNetherBrickWall::West::None).ID: return 13642; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::Tall, RedNetherBrickWall::South::None, true, RedNetherBrickWall::West::Low).ID: return 13643; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::Tall, RedNetherBrickWall::South::None, true, RedNetherBrickWall::West::Tall).ID: return 13644; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::Tall, RedNetherBrickWall::South::None, false, RedNetherBrickWall::West::None).ID: return 13648; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::Tall, RedNetherBrickWall::South::None, false, RedNetherBrickWall::West::Low).ID: return 13649; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::Tall, RedNetherBrickWall::South::None, false, RedNetherBrickWall::West::Tall).ID: return 13650; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::Tall, RedNetherBrickWall::South::Low, true, RedNetherBrickWall::West::None).ID: return 13654; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::Tall, RedNetherBrickWall::South::Low, true, RedNetherBrickWall::West::Low).ID: return 13655; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::Tall, RedNetherBrickWall::South::Low, true, RedNetherBrickWall::West::Tall).ID: return 13656; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::Tall, RedNetherBrickWall::South::Low, false, RedNetherBrickWall::West::None).ID: return 13660; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::Tall, RedNetherBrickWall::South::Low, false, RedNetherBrickWall::West::Low).ID: return 13661; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::Tall, RedNetherBrickWall::South::Low, false, RedNetherBrickWall::West::Tall).ID: return 13662; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::Tall, RedNetherBrickWall::South::Tall, true, RedNetherBrickWall::West::None).ID: return 13666; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::Tall, RedNetherBrickWall::South::Tall, true, RedNetherBrickWall::West::Low).ID: return 13667; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::Tall, RedNetherBrickWall::South::Tall, true, RedNetherBrickWall::West::Tall).ID: return 13668; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::Tall, RedNetherBrickWall::South::Tall, false, RedNetherBrickWall::West::None).ID: return 13672; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::Tall, RedNetherBrickWall::South::Tall, false, RedNetherBrickWall::West::Low).ID: return 13673; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Low, RedNetherBrickWall::North::Tall, RedNetherBrickWall::South::Tall, false, RedNetherBrickWall::West::Tall).ID: return 13674; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Tall, RedNetherBrickWall::North::None, RedNetherBrickWall::South::None, true, RedNetherBrickWall::West::None).ID: return 13678; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Tall, RedNetherBrickWall::North::None, RedNetherBrickWall::South::None, true, RedNetherBrickWall::West::Low).ID: return 13679; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Tall, RedNetherBrickWall::North::None, RedNetherBrickWall::South::None, true, RedNetherBrickWall::West::Tall).ID: return 13680; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Tall, RedNetherBrickWall::North::None, RedNetherBrickWall::South::None, false, RedNetherBrickWall::West::None).ID: return 13684; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Tall, RedNetherBrickWall::North::None, RedNetherBrickWall::South::None, false, RedNetherBrickWall::West::Low).ID: return 13685; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Tall, RedNetherBrickWall::North::None, RedNetherBrickWall::South::None, false, RedNetherBrickWall::West::Tall).ID: return 13686; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Tall, RedNetherBrickWall::North::None, RedNetherBrickWall::South::Low, true, RedNetherBrickWall::West::None).ID: return 13690; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Tall, RedNetherBrickWall::North::None, RedNetherBrickWall::South::Low, true, RedNetherBrickWall::West::Low).ID: return 13691; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Tall, RedNetherBrickWall::North::None, RedNetherBrickWall::South::Low, true, RedNetherBrickWall::West::Tall).ID: return 13692; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Tall, RedNetherBrickWall::North::None, RedNetherBrickWall::South::Low, false, RedNetherBrickWall::West::None).ID: return 13696; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Tall, RedNetherBrickWall::North::None, RedNetherBrickWall::South::Low, false, RedNetherBrickWall::West::Low).ID: return 13697; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Tall, RedNetherBrickWall::North::None, RedNetherBrickWall::South::Low, false, RedNetherBrickWall::West::Tall).ID: return 13698; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Tall, RedNetherBrickWall::North::None, RedNetherBrickWall::South::Tall, true, RedNetherBrickWall::West::None).ID: return 13702; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Tall, RedNetherBrickWall::North::None, RedNetherBrickWall::South::Tall, true, RedNetherBrickWall::West::Low).ID: return 13703; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Tall, RedNetherBrickWall::North::None, RedNetherBrickWall::South::Tall, true, RedNetherBrickWall::West::Tall).ID: return 13704; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Tall, RedNetherBrickWall::North::None, RedNetherBrickWall::South::Tall, false, RedNetherBrickWall::West::None).ID: return 13708; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Tall, RedNetherBrickWall::North::None, RedNetherBrickWall::South::Tall, false, RedNetherBrickWall::West::Low).ID: return 13709; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Tall, RedNetherBrickWall::North::None, RedNetherBrickWall::South::Tall, false, RedNetherBrickWall::West::Tall).ID: return 13710; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Tall, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::None, true, RedNetherBrickWall::West::None).ID: return 13714; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Tall, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::None, true, RedNetherBrickWall::West::Low).ID: return 13715; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Tall, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::None, true, RedNetherBrickWall::West::Tall).ID: return 13716; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Tall, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::None, false, RedNetherBrickWall::West::None).ID: return 13720; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Tall, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::None, false, RedNetherBrickWall::West::Low).ID: return 13721; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Tall, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::None, false, RedNetherBrickWall::West::Tall).ID: return 13722; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Tall, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::Low, true, RedNetherBrickWall::West::None).ID: return 13726; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Tall, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::Low, true, RedNetherBrickWall::West::Low).ID: return 13727; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Tall, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::Low, true, RedNetherBrickWall::West::Tall).ID: return 13728; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Tall, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::Low, false, RedNetherBrickWall::West::None).ID: return 13732; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Tall, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::Low, false, RedNetherBrickWall::West::Low).ID: return 13733; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Tall, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::Low, false, RedNetherBrickWall::West::Tall).ID: return 13734; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Tall, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::Tall, true, RedNetherBrickWall::West::None).ID: return 13738; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Tall, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::Tall, true, RedNetherBrickWall::West::Low).ID: return 13739; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Tall, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::Tall, true, RedNetherBrickWall::West::Tall).ID: return 13740; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Tall, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::Tall, false, RedNetherBrickWall::West::None).ID: return 13744; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Tall, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::Tall, false, RedNetherBrickWall::West::Low).ID: return 13745; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Tall, RedNetherBrickWall::North::Low, RedNetherBrickWall::South::Tall, false, RedNetherBrickWall::West::Tall).ID: return 13746; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Tall, RedNetherBrickWall::North::Tall, RedNetherBrickWall::South::None, true, RedNetherBrickWall::West::None).ID: return 13750; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Tall, RedNetherBrickWall::North::Tall, RedNetherBrickWall::South::None, true, RedNetherBrickWall::West::Low).ID: return 13751; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Tall, RedNetherBrickWall::North::Tall, RedNetherBrickWall::South::None, true, RedNetherBrickWall::West::Tall).ID: return 13752; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Tall, RedNetherBrickWall::North::Tall, RedNetherBrickWall::South::None, false, RedNetherBrickWall::West::None).ID: return 13756; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Tall, RedNetherBrickWall::North::Tall, RedNetherBrickWall::South::None, false, RedNetherBrickWall::West::Low).ID: return 13757; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Tall, RedNetherBrickWall::North::Tall, RedNetherBrickWall::South::None, false, RedNetherBrickWall::West::Tall).ID: return 13758; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Tall, RedNetherBrickWall::North::Tall, RedNetherBrickWall::South::Low, true, RedNetherBrickWall::West::None).ID: return 13762; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Tall, RedNetherBrickWall::North::Tall, RedNetherBrickWall::South::Low, true, RedNetherBrickWall::West::Low).ID: return 13763; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Tall, RedNetherBrickWall::North::Tall, RedNetherBrickWall::South::Low, true, RedNetherBrickWall::West::Tall).ID: return 13764; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Tall, RedNetherBrickWall::North::Tall, RedNetherBrickWall::South::Low, false, RedNetherBrickWall::West::None).ID: return 13768; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Tall, RedNetherBrickWall::North::Tall, RedNetherBrickWall::South::Low, false, RedNetherBrickWall::West::Low).ID: return 13769; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Tall, RedNetherBrickWall::North::Tall, RedNetherBrickWall::South::Low, false, RedNetherBrickWall::West::Tall).ID: return 13770; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Tall, RedNetherBrickWall::North::Tall, RedNetherBrickWall::South::Tall, true, RedNetherBrickWall::West::None).ID: return 13774; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Tall, RedNetherBrickWall::North::Tall, RedNetherBrickWall::South::Tall, true, RedNetherBrickWall::West::Low).ID: return 13775; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Tall, RedNetherBrickWall::North::Tall, RedNetherBrickWall::South::Tall, true, RedNetherBrickWall::West::Tall).ID: return 13776; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Tall, RedNetherBrickWall::North::Tall, RedNetherBrickWall::South::Tall, false, RedNetherBrickWall::West::None).ID: return 13780; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Tall, RedNetherBrickWall::North::Tall, RedNetherBrickWall::South::Tall, false, RedNetherBrickWall::West::Low).ID: return 13781; case RedNetherBrickWall::RedNetherBrickWall(RedNetherBrickWall::East::Tall, RedNetherBrickWall::North::Tall, RedNetherBrickWall::South::Tall, false, RedNetherBrickWall::West::Tall).ID: return 13782; case RedNetherBricks::RedNetherBricks().ID: return 9255; case RedSand::RedSand().ID: return 67; case RedSandstone::RedSandstone().ID: return 8217; case RedSandstoneSlab::RedSandstoneSlab(RedSandstoneSlab::Type::Top).ID: return 8397; case RedSandstoneSlab::RedSandstoneSlab(RedSandstoneSlab::Type::Bottom).ID: return 8399; case RedSandstoneSlab::RedSandstoneSlab(RedSandstoneSlab::Type::Double).ID: return 8401; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::Straight).ID: return 8221; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::InnerLeft).ID: return 8223; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::InnerRight).ID: return 8225; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::OuterLeft).ID: return 8227; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::OuterRight).ID: return 8229; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::Straight).ID: return 8231; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::InnerLeft).ID: return 8233; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::InnerRight).ID: return 8235; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::OuterLeft).ID: return 8237; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::OuterRight).ID: return 8239; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::Straight).ID: return 8241; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::InnerLeft).ID: return 8243; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::InnerRight).ID: return 8245; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::OuterLeft).ID: return 8247; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::OuterRight).ID: return 8249; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::Straight).ID: return 8251; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::InnerLeft).ID: return 8253; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::InnerRight).ID: return 8255; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::OuterLeft).ID: return 8257; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::OuterRight).ID: return 8259; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::Straight).ID: return 8261; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::InnerLeft).ID: return 8263; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::InnerRight).ID: return 8265; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::OuterLeft).ID: return 8267; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::OuterRight).ID: return 8269; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::Straight).ID: return 8271; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::InnerLeft).ID: return 8273; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::InnerRight).ID: return 8275; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::OuterLeft).ID: return 8277; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::OuterRight).ID: return 8279; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::Straight).ID: return 8281; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::InnerLeft).ID: return 8283; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::InnerRight).ID: return 8285; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::OuterLeft).ID: return 8287; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::OuterRight).ID: return 8289; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::Straight).ID: return 8291; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::InnerLeft).ID: return 8293; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::InnerRight).ID: return 8295; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::OuterLeft).ID: return 8297; case RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::OuterRight).ID: return 8299; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::None, RedSandstoneWall::South::None, true, RedSandstoneWall::West::None).ID: return 11518; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::None, RedSandstoneWall::South::None, true, RedSandstoneWall::West::Low).ID: return 11519; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::None, RedSandstoneWall::South::None, true, RedSandstoneWall::West::Tall).ID: return 11520; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::None, RedSandstoneWall::South::None, false, RedSandstoneWall::West::None).ID: return 11524; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::None, RedSandstoneWall::South::None, false, RedSandstoneWall::West::Low).ID: return 11525; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::None, RedSandstoneWall::South::None, false, RedSandstoneWall::West::Tall).ID: return 11526; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::None, RedSandstoneWall::South::Low, true, RedSandstoneWall::West::None).ID: return 11530; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::None, RedSandstoneWall::South::Low, true, RedSandstoneWall::West::Low).ID: return 11531; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::None, RedSandstoneWall::South::Low, true, RedSandstoneWall::West::Tall).ID: return 11532; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::None, RedSandstoneWall::South::Low, false, RedSandstoneWall::West::None).ID: return 11536; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::None, RedSandstoneWall::South::Low, false, RedSandstoneWall::West::Low).ID: return 11537; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::None, RedSandstoneWall::South::Low, false, RedSandstoneWall::West::Tall).ID: return 11538; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::None, RedSandstoneWall::South::Tall, true, RedSandstoneWall::West::None).ID: return 11542; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::None, RedSandstoneWall::South::Tall, true, RedSandstoneWall::West::Low).ID: return 11543; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::None, RedSandstoneWall::South::Tall, true, RedSandstoneWall::West::Tall).ID: return 11544; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::None, RedSandstoneWall::South::Tall, false, RedSandstoneWall::West::None).ID: return 11548; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::None, RedSandstoneWall::South::Tall, false, RedSandstoneWall::West::Low).ID: return 11549; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::None, RedSandstoneWall::South::Tall, false, RedSandstoneWall::West::Tall).ID: return 11550; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::Low, RedSandstoneWall::South::None, true, RedSandstoneWall::West::None).ID: return 11554; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::Low, RedSandstoneWall::South::None, true, RedSandstoneWall::West::Low).ID: return 11555; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::Low, RedSandstoneWall::South::None, true, RedSandstoneWall::West::Tall).ID: return 11556; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::Low, RedSandstoneWall::South::None, false, RedSandstoneWall::West::None).ID: return 11560; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::Low, RedSandstoneWall::South::None, false, RedSandstoneWall::West::Low).ID: return 11561; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::Low, RedSandstoneWall::South::None, false, RedSandstoneWall::West::Tall).ID: return 11562; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::Low, RedSandstoneWall::South::Low, true, RedSandstoneWall::West::None).ID: return 11566; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::Low, RedSandstoneWall::South::Low, true, RedSandstoneWall::West::Low).ID: return 11567; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::Low, RedSandstoneWall::South::Low, true, RedSandstoneWall::West::Tall).ID: return 11568; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::Low, RedSandstoneWall::South::Low, false, RedSandstoneWall::West::None).ID: return 11572; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::Low, RedSandstoneWall::South::Low, false, RedSandstoneWall::West::Low).ID: return 11573; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::Low, RedSandstoneWall::South::Low, false, RedSandstoneWall::West::Tall).ID: return 11574; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::Low, RedSandstoneWall::South::Tall, true, RedSandstoneWall::West::None).ID: return 11578; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::Low, RedSandstoneWall::South::Tall, true, RedSandstoneWall::West::Low).ID: return 11579; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::Low, RedSandstoneWall::South::Tall, true, RedSandstoneWall::West::Tall).ID: return 11580; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::Low, RedSandstoneWall::South::Tall, false, RedSandstoneWall::West::None).ID: return 11584; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::Low, RedSandstoneWall::South::Tall, false, RedSandstoneWall::West::Low).ID: return 11585; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::Low, RedSandstoneWall::South::Tall, false, RedSandstoneWall::West::Tall).ID: return 11586; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::Tall, RedSandstoneWall::South::None, true, RedSandstoneWall::West::None).ID: return 11590; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::Tall, RedSandstoneWall::South::None, true, RedSandstoneWall::West::Low).ID: return 11591; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::Tall, RedSandstoneWall::South::None, true, RedSandstoneWall::West::Tall).ID: return 11592; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::Tall, RedSandstoneWall::South::None, false, RedSandstoneWall::West::None).ID: return 11596; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::Tall, RedSandstoneWall::South::None, false, RedSandstoneWall::West::Low).ID: return 11597; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::Tall, RedSandstoneWall::South::None, false, RedSandstoneWall::West::Tall).ID: return 11598; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::Tall, RedSandstoneWall::South::Low, true, RedSandstoneWall::West::None).ID: return 11602; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::Tall, RedSandstoneWall::South::Low, true, RedSandstoneWall::West::Low).ID: return 11603; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::Tall, RedSandstoneWall::South::Low, true, RedSandstoneWall::West::Tall).ID: return 11604; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::Tall, RedSandstoneWall::South::Low, false, RedSandstoneWall::West::None).ID: return 11608; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::Tall, RedSandstoneWall::South::Low, false, RedSandstoneWall::West::Low).ID: return 11609; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::Tall, RedSandstoneWall::South::Low, false, RedSandstoneWall::West::Tall).ID: return 11610; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::Tall, RedSandstoneWall::South::Tall, true, RedSandstoneWall::West::None).ID: return 11614; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::Tall, RedSandstoneWall::South::Tall, true, RedSandstoneWall::West::Low).ID: return 11615; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::Tall, RedSandstoneWall::South::Tall, true, RedSandstoneWall::West::Tall).ID: return 11616; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::Tall, RedSandstoneWall::South::Tall, false, RedSandstoneWall::West::None).ID: return 11620; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::Tall, RedSandstoneWall::South::Tall, false, RedSandstoneWall::West::Low).ID: return 11621; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::None, RedSandstoneWall::North::Tall, RedSandstoneWall::South::Tall, false, RedSandstoneWall::West::Tall).ID: return 11622; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::None, RedSandstoneWall::South::None, true, RedSandstoneWall::West::None).ID: return 11626; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::None, RedSandstoneWall::South::None, true, RedSandstoneWall::West::Low).ID: return 11627; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::None, RedSandstoneWall::South::None, true, RedSandstoneWall::West::Tall).ID: return 11628; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::None, RedSandstoneWall::South::None, false, RedSandstoneWall::West::None).ID: return 11632; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::None, RedSandstoneWall::South::None, false, RedSandstoneWall::West::Low).ID: return 11633; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::None, RedSandstoneWall::South::None, false, RedSandstoneWall::West::Tall).ID: return 11634; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::None, RedSandstoneWall::South::Low, true, RedSandstoneWall::West::None).ID: return 11638; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::None, RedSandstoneWall::South::Low, true, RedSandstoneWall::West::Low).ID: return 11639; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::None, RedSandstoneWall::South::Low, true, RedSandstoneWall::West::Tall).ID: return 11640; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::None, RedSandstoneWall::South::Low, false, RedSandstoneWall::West::None).ID: return 11644; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::None, RedSandstoneWall::South::Low, false, RedSandstoneWall::West::Low).ID: return 11645; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::None, RedSandstoneWall::South::Low, false, RedSandstoneWall::West::Tall).ID: return 11646; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::None, RedSandstoneWall::South::Tall, true, RedSandstoneWall::West::None).ID: return 11650; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::None, RedSandstoneWall::South::Tall, true, RedSandstoneWall::West::Low).ID: return 11651; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::None, RedSandstoneWall::South::Tall, true, RedSandstoneWall::West::Tall).ID: return 11652; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::None, RedSandstoneWall::South::Tall, false, RedSandstoneWall::West::None).ID: return 11656; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::None, RedSandstoneWall::South::Tall, false, RedSandstoneWall::West::Low).ID: return 11657; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::None, RedSandstoneWall::South::Tall, false, RedSandstoneWall::West::Tall).ID: return 11658; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::Low, RedSandstoneWall::South::None, true, RedSandstoneWall::West::None).ID: return 11662; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::Low, RedSandstoneWall::South::None, true, RedSandstoneWall::West::Low).ID: return 11663; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::Low, RedSandstoneWall::South::None, true, RedSandstoneWall::West::Tall).ID: return 11664; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::Low, RedSandstoneWall::South::None, false, RedSandstoneWall::West::None).ID: return 11668; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::Low, RedSandstoneWall::South::None, false, RedSandstoneWall::West::Low).ID: return 11669; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::Low, RedSandstoneWall::South::None, false, RedSandstoneWall::West::Tall).ID: return 11670; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::Low, RedSandstoneWall::South::Low, true, RedSandstoneWall::West::None).ID: return 11674; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::Low, RedSandstoneWall::South::Low, true, RedSandstoneWall::West::Low).ID: return 11675; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::Low, RedSandstoneWall::South::Low, true, RedSandstoneWall::West::Tall).ID: return 11676; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::Low, RedSandstoneWall::South::Low, false, RedSandstoneWall::West::None).ID: return 11680; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::Low, RedSandstoneWall::South::Low, false, RedSandstoneWall::West::Low).ID: return 11681; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::Low, RedSandstoneWall::South::Low, false, RedSandstoneWall::West::Tall).ID: return 11682; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::Low, RedSandstoneWall::South::Tall, true, RedSandstoneWall::West::None).ID: return 11686; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::Low, RedSandstoneWall::South::Tall, true, RedSandstoneWall::West::Low).ID: return 11687; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::Low, RedSandstoneWall::South::Tall, true, RedSandstoneWall::West::Tall).ID: return 11688; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::Low, RedSandstoneWall::South::Tall, false, RedSandstoneWall::West::None).ID: return 11692; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::Low, RedSandstoneWall::South::Tall, false, RedSandstoneWall::West::Low).ID: return 11693; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::Low, RedSandstoneWall::South::Tall, false, RedSandstoneWall::West::Tall).ID: return 11694; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::Tall, RedSandstoneWall::South::None, true, RedSandstoneWall::West::None).ID: return 11698; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::Tall, RedSandstoneWall::South::None, true, RedSandstoneWall::West::Low).ID: return 11699; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::Tall, RedSandstoneWall::South::None, true, RedSandstoneWall::West::Tall).ID: return 11700; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::Tall, RedSandstoneWall::South::None, false, RedSandstoneWall::West::None).ID: return 11704; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::Tall, RedSandstoneWall::South::None, false, RedSandstoneWall::West::Low).ID: return 11705; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::Tall, RedSandstoneWall::South::None, false, RedSandstoneWall::West::Tall).ID: return 11706; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::Tall, RedSandstoneWall::South::Low, true, RedSandstoneWall::West::None).ID: return 11710; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::Tall, RedSandstoneWall::South::Low, true, RedSandstoneWall::West::Low).ID: return 11711; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::Tall, RedSandstoneWall::South::Low, true, RedSandstoneWall::West::Tall).ID: return 11712; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::Tall, RedSandstoneWall::South::Low, false, RedSandstoneWall::West::None).ID: return 11716; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::Tall, RedSandstoneWall::South::Low, false, RedSandstoneWall::West::Low).ID: return 11717; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::Tall, RedSandstoneWall::South::Low, false, RedSandstoneWall::West::Tall).ID: return 11718; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::Tall, RedSandstoneWall::South::Tall, true, RedSandstoneWall::West::None).ID: return 11722; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::Tall, RedSandstoneWall::South::Tall, true, RedSandstoneWall::West::Low).ID: return 11723; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::Tall, RedSandstoneWall::South::Tall, true, RedSandstoneWall::West::Tall).ID: return 11724; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::Tall, RedSandstoneWall::South::Tall, false, RedSandstoneWall::West::None).ID: return 11728; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::Tall, RedSandstoneWall::South::Tall, false, RedSandstoneWall::West::Low).ID: return 11729; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Low, RedSandstoneWall::North::Tall, RedSandstoneWall::South::Tall, false, RedSandstoneWall::West::Tall).ID: return 11730; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Tall, RedSandstoneWall::North::None, RedSandstoneWall::South::None, true, RedSandstoneWall::West::None).ID: return 11734; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Tall, RedSandstoneWall::North::None, RedSandstoneWall::South::None, true, RedSandstoneWall::West::Low).ID: return 11735; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Tall, RedSandstoneWall::North::None, RedSandstoneWall::South::None, true, RedSandstoneWall::West::Tall).ID: return 11736; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Tall, RedSandstoneWall::North::None, RedSandstoneWall::South::None, false, RedSandstoneWall::West::None).ID: return 11740; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Tall, RedSandstoneWall::North::None, RedSandstoneWall::South::None, false, RedSandstoneWall::West::Low).ID: return 11741; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Tall, RedSandstoneWall::North::None, RedSandstoneWall::South::None, false, RedSandstoneWall::West::Tall).ID: return 11742; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Tall, RedSandstoneWall::North::None, RedSandstoneWall::South::Low, true, RedSandstoneWall::West::None).ID: return 11746; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Tall, RedSandstoneWall::North::None, RedSandstoneWall::South::Low, true, RedSandstoneWall::West::Low).ID: return 11747; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Tall, RedSandstoneWall::North::None, RedSandstoneWall::South::Low, true, RedSandstoneWall::West::Tall).ID: return 11748; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Tall, RedSandstoneWall::North::None, RedSandstoneWall::South::Low, false, RedSandstoneWall::West::None).ID: return 11752; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Tall, RedSandstoneWall::North::None, RedSandstoneWall::South::Low, false, RedSandstoneWall::West::Low).ID: return 11753; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Tall, RedSandstoneWall::North::None, RedSandstoneWall::South::Low, false, RedSandstoneWall::West::Tall).ID: return 11754; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Tall, RedSandstoneWall::North::None, RedSandstoneWall::South::Tall, true, RedSandstoneWall::West::None).ID: return 11758; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Tall, RedSandstoneWall::North::None, RedSandstoneWall::South::Tall, true, RedSandstoneWall::West::Low).ID: return 11759; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Tall, RedSandstoneWall::North::None, RedSandstoneWall::South::Tall, true, RedSandstoneWall::West::Tall).ID: return 11760; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Tall, RedSandstoneWall::North::None, RedSandstoneWall::South::Tall, false, RedSandstoneWall::West::None).ID: return 11764; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Tall, RedSandstoneWall::North::None, RedSandstoneWall::South::Tall, false, RedSandstoneWall::West::Low).ID: return 11765; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Tall, RedSandstoneWall::North::None, RedSandstoneWall::South::Tall, false, RedSandstoneWall::West::Tall).ID: return 11766; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Tall, RedSandstoneWall::North::Low, RedSandstoneWall::South::None, true, RedSandstoneWall::West::None).ID: return 11770; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Tall, RedSandstoneWall::North::Low, RedSandstoneWall::South::None, true, RedSandstoneWall::West::Low).ID: return 11771; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Tall, RedSandstoneWall::North::Low, RedSandstoneWall::South::None, true, RedSandstoneWall::West::Tall).ID: return 11772; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Tall, RedSandstoneWall::North::Low, RedSandstoneWall::South::None, false, RedSandstoneWall::West::None).ID: return 11776; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Tall, RedSandstoneWall::North::Low, RedSandstoneWall::South::None, false, RedSandstoneWall::West::Low).ID: return 11777; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Tall, RedSandstoneWall::North::Low, RedSandstoneWall::South::None, false, RedSandstoneWall::West::Tall).ID: return 11778; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Tall, RedSandstoneWall::North::Low, RedSandstoneWall::South::Low, true, RedSandstoneWall::West::None).ID: return 11782; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Tall, RedSandstoneWall::North::Low, RedSandstoneWall::South::Low, true, RedSandstoneWall::West::Low).ID: return 11783; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Tall, RedSandstoneWall::North::Low, RedSandstoneWall::South::Low, true, RedSandstoneWall::West::Tall).ID: return 11784; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Tall, RedSandstoneWall::North::Low, RedSandstoneWall::South::Low, false, RedSandstoneWall::West::None).ID: return 11788; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Tall, RedSandstoneWall::North::Low, RedSandstoneWall::South::Low, false, RedSandstoneWall::West::Low).ID: return 11789; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Tall, RedSandstoneWall::North::Low, RedSandstoneWall::South::Low, false, RedSandstoneWall::West::Tall).ID: return 11790; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Tall, RedSandstoneWall::North::Low, RedSandstoneWall::South::Tall, true, RedSandstoneWall::West::None).ID: return 11794; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Tall, RedSandstoneWall::North::Low, RedSandstoneWall::South::Tall, true, RedSandstoneWall::West::Low).ID: return 11795; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Tall, RedSandstoneWall::North::Low, RedSandstoneWall::South::Tall, true, RedSandstoneWall::West::Tall).ID: return 11796; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Tall, RedSandstoneWall::North::Low, RedSandstoneWall::South::Tall, false, RedSandstoneWall::West::None).ID: return 11800; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Tall, RedSandstoneWall::North::Low, RedSandstoneWall::South::Tall, false, RedSandstoneWall::West::Low).ID: return 11801; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Tall, RedSandstoneWall::North::Low, RedSandstoneWall::South::Tall, false, RedSandstoneWall::West::Tall).ID: return 11802; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Tall, RedSandstoneWall::North::Tall, RedSandstoneWall::South::None, true, RedSandstoneWall::West::None).ID: return 11806; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Tall, RedSandstoneWall::North::Tall, RedSandstoneWall::South::None, true, RedSandstoneWall::West::Low).ID: return 11807; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Tall, RedSandstoneWall::North::Tall, RedSandstoneWall::South::None, true, RedSandstoneWall::West::Tall).ID: return 11808; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Tall, RedSandstoneWall::North::Tall, RedSandstoneWall::South::None, false, RedSandstoneWall::West::None).ID: return 11812; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Tall, RedSandstoneWall::North::Tall, RedSandstoneWall::South::None, false, RedSandstoneWall::West::Low).ID: return 11813; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Tall, RedSandstoneWall::North::Tall, RedSandstoneWall::South::None, false, RedSandstoneWall::West::Tall).ID: return 11814; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Tall, RedSandstoneWall::North::Tall, RedSandstoneWall::South::Low, true, RedSandstoneWall::West::None).ID: return 11818; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Tall, RedSandstoneWall::North::Tall, RedSandstoneWall::South::Low, true, RedSandstoneWall::West::Low).ID: return 11819; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Tall, RedSandstoneWall::North::Tall, RedSandstoneWall::South::Low, true, RedSandstoneWall::West::Tall).ID: return 11820; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Tall, RedSandstoneWall::North::Tall, RedSandstoneWall::South::Low, false, RedSandstoneWall::West::None).ID: return 11824; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Tall, RedSandstoneWall::North::Tall, RedSandstoneWall::South::Low, false, RedSandstoneWall::West::Low).ID: return 11825; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Tall, RedSandstoneWall::North::Tall, RedSandstoneWall::South::Low, false, RedSandstoneWall::West::Tall).ID: return 11826; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Tall, RedSandstoneWall::North::Tall, RedSandstoneWall::South::Tall, true, RedSandstoneWall::West::None).ID: return 11830; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Tall, RedSandstoneWall::North::Tall, RedSandstoneWall::South::Tall, true, RedSandstoneWall::West::Low).ID: return 11831; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Tall, RedSandstoneWall::North::Tall, RedSandstoneWall::South::Tall, true, RedSandstoneWall::West::Tall).ID: return 11832; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Tall, RedSandstoneWall::North::Tall, RedSandstoneWall::South::Tall, false, RedSandstoneWall::West::None).ID: return 11836; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Tall, RedSandstoneWall::North::Tall, RedSandstoneWall::South::Tall, false, RedSandstoneWall::West::Low).ID: return 11837; case RedSandstoneWall::RedSandstoneWall(RedSandstoneWall::East::Tall, RedSandstoneWall::North::Tall, RedSandstoneWall::South::Tall, false, RedSandstoneWall::West::Tall).ID: return 11838; case RedShulkerBox::RedShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 9362; case RedShulkerBox::RedShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 9363; case RedShulkerBox::RedShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 9364; case RedShulkerBox::RedShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 9365; case RedShulkerBox::RedShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 9366; case RedShulkerBox::RedShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 9367; case RedStainedGlass::RedStainedGlass().ID: return 4109; case RedStainedGlassPane::RedStainedGlassPane(true, true, true, true).ID: return 7313; case RedStainedGlassPane::RedStainedGlassPane(true, true, true, false).ID: return 7314; case RedStainedGlassPane::RedStainedGlassPane(true, true, false, true).ID: return 7317; case RedStainedGlassPane::RedStainedGlassPane(true, true, false, false).ID: return 7318; case RedStainedGlassPane::RedStainedGlassPane(true, false, true, true).ID: return 7321; case RedStainedGlassPane::RedStainedGlassPane(true, false, true, false).ID: return 7322; case RedStainedGlassPane::RedStainedGlassPane(true, false, false, true).ID: return 7325; case RedStainedGlassPane::RedStainedGlassPane(true, false, false, false).ID: return 7326; case RedStainedGlassPane::RedStainedGlassPane(false, true, true, true).ID: return 7329; case RedStainedGlassPane::RedStainedGlassPane(false, true, true, false).ID: return 7330; case RedStainedGlassPane::RedStainedGlassPane(false, true, false, true).ID: return 7333; case RedStainedGlassPane::RedStainedGlassPane(false, true, false, false).ID: return 7334; case RedStainedGlassPane::RedStainedGlassPane(false, false, true, true).ID: return 7337; case RedStainedGlassPane::RedStainedGlassPane(false, false, true, false).ID: return 7338; case RedStainedGlassPane::RedStainedGlassPane(false, false, false, true).ID: return 7341; case RedStainedGlassPane::RedStainedGlassPane(false, false, false, false).ID: return 7342; case RedTerracotta::RedTerracotta().ID: return 6861; case RedTulip::RedTulip().ID: return 1417; case RedWallBanner::RedWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 8209; case RedWallBanner::RedWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 8210; case RedWallBanner::RedWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 8211; case RedWallBanner::RedWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 8212; case RedWool::RedWool().ID: return 1398; case RedstoneBlock::RedstoneBlock().ID: return 6726; case RedstoneLamp::RedstoneLamp(true).ID: return 5156; case RedstoneLamp::RedstoneLamp(false).ID: return 5157; case RedstoneOre::RedstoneOre(true).ID: return 3885; case RedstoneOre::RedstoneOre(false).ID: return 3886; case RedstoneTorch::RedstoneTorch(true).ID: return 3887; case RedstoneTorch::RedstoneTorch(false).ID: return 3888; case RedstoneWallTorch::RedstoneWallTorch(eBlockFace::BLOCK_FACE_ZM, true).ID: return 3889; case RedstoneWallTorch::RedstoneWallTorch(eBlockFace::BLOCK_FACE_ZM, false).ID: return 3890; case RedstoneWallTorch::RedstoneWallTorch(eBlockFace::BLOCK_FACE_ZP, true).ID: return 3891; case RedstoneWallTorch::RedstoneWallTorch(eBlockFace::BLOCK_FACE_ZP, false).ID: return 3892; case RedstoneWallTorch::RedstoneWallTorch(eBlockFace::BLOCK_FACE_XM, true).ID: return 3893; case RedstoneWallTorch::RedstoneWallTorch(eBlockFace::BLOCK_FACE_XM, false).ID: return 3894; case RedstoneWallTorch::RedstoneWallTorch(eBlockFace::BLOCK_FACE_XP, true).ID: return 3895; case RedstoneWallTorch::RedstoneWallTorch(eBlockFace::BLOCK_FACE_XP, false).ID: return 3896; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 0, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2058; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 0, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2059; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 0, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2060; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 0, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2061; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 0, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2062; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 0, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2063; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 0, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2064; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 0, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2065; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 0, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2066; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 1, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2067; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 1, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2068; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 1, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2069; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 1, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2070; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 1, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2071; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 1, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2072; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 1, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2073; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 1, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2074; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 1, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2075; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 2, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2076; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 2, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2077; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 2, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2078; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 2, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2079; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 2, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2080; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 2, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2081; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 2, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2082; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 2, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2083; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 2, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2084; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 3, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2085; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 3, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2086; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 3, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2087; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 3, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2088; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 3, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2089; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 3, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2090; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 3, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2091; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 3, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2092; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 3, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2093; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 4, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2094; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 4, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2095; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 4, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2096; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 4, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2097; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 4, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2098; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 4, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2099; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 4, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2100; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 4, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2101; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 4, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2102; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 5, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2103; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 5, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2104; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 5, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2105; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 5, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2106; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 5, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2107; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 5, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2108; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 5, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2109; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 5, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2110; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 5, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2111; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 6, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2112; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 6, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2113; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 6, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2114; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 6, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2115; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 6, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2116; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 6, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2117; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 6, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2118; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 6, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2119; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 6, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2120; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 7, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2121; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 7, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2122; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 7, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2123; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 7, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2124; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 7, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2125; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 7, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2126; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 7, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2127; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 7, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2128; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 7, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2129; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 8, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2130; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 8, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2131; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 8, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2132; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 8, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2133; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 8, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2134; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 8, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2135; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 8, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2136; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 8, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2137; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 8, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2138; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 9, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2139; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 9, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2140; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 9, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2141; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 9, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2142; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 9, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2143; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 9, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2144; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 9, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2145; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 9, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2146; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 9, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2147; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 10, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2148; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 10, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2149; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 10, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2150; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 10, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2151; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 10, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2152; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 10, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2153; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 10, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2154; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 10, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2155; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 10, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2156; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 11, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2157; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 11, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2158; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 11, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2159; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 11, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2160; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 11, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2161; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 11, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2162; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 11, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2163; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 11, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2164; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 11, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2165; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 12, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2166; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 12, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2167; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 12, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2168; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 12, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2169; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 12, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2170; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 12, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2171; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 12, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2172; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 12, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2173; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 12, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2174; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 13, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2175; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 13, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2176; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 13, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2177; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 13, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2178; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 13, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2179; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 13, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2180; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 13, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2181; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 13, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2182; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 13, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2183; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 14, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2184; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 14, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2185; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 14, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2186; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 14, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2187; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 14, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2188; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 14, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2189; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 14, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2190; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 14, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2191; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 14, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2192; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 15, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2193; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 15, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2194; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 15, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2195; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 15, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2196; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 15, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2197; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 15, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2198; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 15, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2199; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 15, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2200; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Up, 15, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2201; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 0, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2202; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 0, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2203; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 0, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2204; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 0, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2205; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 0, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2206; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 0, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2207; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 0, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2208; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 0, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2209; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 0, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2210; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 1, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2211; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 1, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2212; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 1, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2213; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 1, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2214; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 1, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2215; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 1, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2216; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 1, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2217; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 1, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2218; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 1, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2219; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 2, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2220; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 2, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2221; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 2, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2222; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 2, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2223; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 2, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2224; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 2, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2225; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 2, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2226; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 2, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2227; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 2, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2228; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 3, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2229; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 3, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2230; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 3, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2231; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 3, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2232; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 3, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2233; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 3, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2234; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 3, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2235; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 3, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2236; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 3, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2237; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 4, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2238; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 4, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2239; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 4, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2240; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 4, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2241; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 4, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2242; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 4, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2243; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 4, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2244; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 4, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2245; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 4, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2246; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 5, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2247; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 5, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2248; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 5, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2249; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 5, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2250; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 5, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2251; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 5, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2252; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 5, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2253; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 5, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2254; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 5, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2255; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 6, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2256; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 6, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2257; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 6, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2258; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 6, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2259; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 6, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2260; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 6, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2261; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 6, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2262; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 6, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2263; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 6, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2264; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 7, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2265; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 7, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2266; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 7, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2267; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 7, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2268; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 7, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2269; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 7, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2270; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 7, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2271; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 7, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2272; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 7, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2273; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 8, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2274; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 8, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2275; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 8, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2276; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 8, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2277; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 8, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2278; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 8, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2279; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 8, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2280; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 8, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2281; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 8, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2282; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 9, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2283; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 9, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2284; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 9, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2285; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 9, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2286; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 9, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2287; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 9, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2288; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 9, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2289; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 9, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2290; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 9, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2291; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 10, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2292; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 10, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2293; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 10, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2294; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 10, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2295; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 10, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2296; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 10, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2297; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 10, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2298; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 10, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2299; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 10, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2300; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 11, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2301; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 11, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2302; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 11, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2303; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 11, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2304; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 11, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2305; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 11, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2306; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 11, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2307; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 11, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2308; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 11, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2309; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 12, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2310; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 12, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2311; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 12, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2312; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 12, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2313; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 12, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2314; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 12, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2315; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 12, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2316; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 12, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2317; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 12, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2318; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 13, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2319; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 13, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2320; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 13, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2321; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 13, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2322; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 13, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2323; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 13, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2324; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 13, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2325; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 13, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2326; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 13, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2327; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 14, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2328; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 14, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2329; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 14, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2330; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 14, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2331; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 14, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2332; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 14, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2333; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 14, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2334; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 14, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2335; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 14, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2336; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 15, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2337; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 15, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2338; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 15, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2339; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 15, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2340; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 15, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2341; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 15, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2342; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 15, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2343; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 15, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2344; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::Side, 15, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2345; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 0, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2346; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 0, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2347; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 0, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2348; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 0, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2349; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 0, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2350; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 0, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2351; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 0, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2352; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 0, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2353; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 0, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2354; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 1, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2355; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 1, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2356; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 1, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2357; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 1, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2358; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 1, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2359; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 1, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2360; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 1, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2361; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 1, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2362; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 1, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2363; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 2, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2364; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 2, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2365; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 2, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2366; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 2, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2367; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 2, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2368; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 2, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2369; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 2, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2370; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 2, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2371; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 2, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2372; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 3, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2373; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 3, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2374; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 3, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2375; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 3, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2376; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 3, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2377; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 3, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2378; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 3, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2379; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 3, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2380; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 3, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2381; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 4, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2382; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 4, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2383; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 4, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2384; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 4, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2385; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 4, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2386; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 4, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2387; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 4, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2388; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 4, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2389; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 4, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2390; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 5, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2391; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 5, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2392; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 5, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2393; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 5, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2394; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 5, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2395; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 5, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2396; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 5, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2397; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 5, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2398; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 5, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2399; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 6, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2400; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 6, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2401; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 6, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2402; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 6, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2403; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 6, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2404; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 6, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2405; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 6, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2406; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 6, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2407; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 6, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2408; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 7, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2409; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 7, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2410; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 7, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2411; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 7, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2412; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 7, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2413; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 7, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2414; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 7, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2415; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 7, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2416; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 7, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2417; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 8, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2418; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 8, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2419; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 8, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2420; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 8, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2421; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 8, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2422; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 8, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2423; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 8, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2424; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 8, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2425; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 8, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2426; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 9, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2427; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 9, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2428; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 9, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2429; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 9, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2430; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 9, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2431; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 9, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2432; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 9, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2433; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 9, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2434; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 9, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2435; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 10, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2436; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 10, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2437; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 10, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2438; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 10, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2439; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 10, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2440; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 10, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2441; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 10, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2442; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 10, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2443; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 10, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2444; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 11, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2445; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 11, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2446; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 11, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2447; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 11, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2448; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 11, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2449; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 11, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2450; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 11, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2451; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 11, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2452; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 11, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2453; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 12, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2454; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 12, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2455; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 12, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2456; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 12, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2457; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 12, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2458; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 12, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2459; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 12, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2460; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 12, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2461; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 12, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2462; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 13, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2463; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 13, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2464; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 13, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2465; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 13, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2466; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 13, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2467; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 13, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2468; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 13, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2469; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 13, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2470; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 13, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2471; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 14, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2472; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 14, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2473; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 14, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2474; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 14, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2475; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 14, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2476; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 14, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2477; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 14, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2478; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 14, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2479; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 14, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2480; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 15, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2481; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 15, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2482; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 15, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2483; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 15, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2484; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 15, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2485; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 15, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2486; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 15, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2487; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 15, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2488; case RedstoneWire::RedstoneWire(RedstoneWire::East::Up, RedstoneWire::North::None, 15, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2489; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 0, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2490; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 0, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2491; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 0, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2492; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 0, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2493; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 0, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2494; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 0, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2495; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 0, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2496; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 0, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2497; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 0, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2498; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 1, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2499; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 1, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2500; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 1, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2501; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 1, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2502; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 1, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2503; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 1, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2504; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 1, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2505; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 1, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2506; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 1, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2507; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 2, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2508; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 2, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2509; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 2, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2510; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 2, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2511; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 2, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2512; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 2, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2513; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 2, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2514; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 2, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2515; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 2, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2516; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 3, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2517; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 3, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2518; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 3, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2519; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 3, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2520; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 3, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2521; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 3, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2522; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 3, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2523; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 3, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2524; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 3, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2525; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 4, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2526; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 4, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2527; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 4, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2528; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 4, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2529; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 4, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2530; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 4, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2531; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 4, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2532; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 4, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2533; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 4, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2534; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 5, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2535; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 5, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2536; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 5, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2537; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 5, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2538; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 5, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2539; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 5, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2540; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 5, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2541; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 5, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2542; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 5, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2543; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 6, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2544; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 6, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2545; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 6, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2546; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 6, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2547; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 6, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2548; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 6, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2549; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 6, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2550; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 6, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2551; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 6, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2552; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 7, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2553; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 7, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2554; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 7, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2555; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 7, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2556; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 7, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2557; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 7, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2558; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 7, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2559; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 7, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2560; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 7, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2561; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 8, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2562; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 8, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2563; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 8, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2564; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 8, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2565; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 8, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2566; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 8, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2567; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 8, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2568; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 8, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2569; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 8, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2570; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 9, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2571; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 9, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2572; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 9, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2573; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 9, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2574; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 9, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2575; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 9, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2576; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 9, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2577; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 9, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2578; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 9, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2579; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 10, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2580; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 10, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2581; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 10, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2582; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 10, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2583; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 10, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2584; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 10, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2585; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 10, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2586; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 10, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2587; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 10, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2588; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 11, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2589; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 11, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2590; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 11, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2591; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 11, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2592; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 11, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2593; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 11, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2594; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 11, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2595; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 11, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2596; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 11, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2597; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 12, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2598; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 12, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2599; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 12, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2600; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 12, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2601; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 12, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2602; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 12, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2603; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 12, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2604; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 12, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2605; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 12, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2606; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 13, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2607; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 13, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2608; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 13, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2609; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 13, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2610; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 13, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2611; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 13, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2612; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 13, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2613; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 13, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2614; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 13, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2615; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 14, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2616; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 14, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2617; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 14, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2618; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 14, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2619; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 14, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2620; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 14, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2621; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 14, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2622; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 14, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2623; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 14, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2624; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 15, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2625; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 15, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2626; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 15, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2627; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 15, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2628; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 15, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2629; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 15, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2630; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 15, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2631; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 15, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2632; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Up, 15, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2633; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 0, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2634; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 0, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2635; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 0, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2636; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 0, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2637; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 0, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2638; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 0, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2639; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 0, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2640; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 0, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2641; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 0, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2642; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 1, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2643; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 1, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2644; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 1, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2645; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 1, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2646; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 1, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2647; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 1, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2648; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 1, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2649; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 1, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2650; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 1, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2651; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 2, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2652; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 2, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2653; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 2, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2654; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 2, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2655; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 2, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2656; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 2, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2657; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 2, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2658; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 2, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2659; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 2, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2660; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 3, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2661; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 3, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2662; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 3, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2663; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 3, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2664; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 3, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2665; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 3, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2666; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 3, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2667; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 3, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2668; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 3, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2669; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 4, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2670; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 4, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2671; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 4, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2672; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 4, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2673; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 4, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2674; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 4, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2675; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 4, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2676; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 4, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2677; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 4, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2678; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 5, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2679; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 5, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2680; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 5, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2681; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 5, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2682; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 5, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2683; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 5, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2684; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 5, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2685; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 5, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2686; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 5, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2687; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 6, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2688; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 6, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2689; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 6, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2690; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 6, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2691; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 6, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2692; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 6, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2693; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 6, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2694; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 6, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2695; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 6, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2696; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 7, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2697; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 7, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2698; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 7, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2699; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 7, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2700; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 7, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2701; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 7, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2702; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 7, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2703; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 7, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2704; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 7, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2705; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 8, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2706; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 8, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2707; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 8, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2708; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 8, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2709; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 8, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2710; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 8, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2711; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 8, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2712; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 8, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2713; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 8, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2714; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 9, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2715; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 9, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2716; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 9, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2717; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 9, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2718; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 9, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2719; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 9, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2720; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 9, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2721; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 9, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2722; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 9, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2723; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 10, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2724; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 10, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2725; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 10, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2726; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 10, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2727; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 10, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2728; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 10, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2729; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 10, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2730; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 10, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2731; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 10, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2732; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 11, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2733; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 11, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2734; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 11, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2735; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 11, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2736; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 11, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2737; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 11, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2738; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 11, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2739; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 11, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2740; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 11, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2741; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 12, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2742; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 12, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2743; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 12, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2744; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 12, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2745; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 12, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2746; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 12, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2747; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 12, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2748; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 12, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2749; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 12, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2750; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 13, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2751; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 13, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2752; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 13, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2753; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 13, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2754; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 13, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2755; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 13, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2756; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 13, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2757; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 13, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2758; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 13, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2759; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 14, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2760; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 14, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2761; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 14, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2762; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 14, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2763; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 14, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2764; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 14, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2765; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 14, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2766; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 14, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2767; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 14, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2768; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 15, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2769; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 15, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2770; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 15, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2771; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 15, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2772; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 15, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2773; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 15, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2774; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 15, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2775; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 15, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2776; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::Side, 15, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2777; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 0, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2778; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 0, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2779; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 0, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2780; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 0, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2781; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 0, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2782; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 0, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2783; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 0, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2784; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 0, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2785; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 0, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2786; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 1, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2787; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 1, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2788; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 1, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2789; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 1, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2790; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 1, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2791; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 1, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2792; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 1, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2793; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 1, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2794; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 1, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2795; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 2, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2796; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 2, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2797; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 2, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2798; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 2, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2799; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 2, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2800; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 2, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2801; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 2, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2802; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 2, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2803; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 2, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2804; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 3, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2805; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 3, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2806; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 3, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2807; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 3, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2808; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 3, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2809; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 3, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2810; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 3, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2811; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 3, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2812; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 3, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2813; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 4, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2814; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 4, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2815; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 4, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2816; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 4, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2817; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 4, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2818; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 4, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2819; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 4, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2820; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 4, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2821; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 4, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2822; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 5, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2823; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 5, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2824; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 5, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2825; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 5, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2826; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 5, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2827; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 5, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2828; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 5, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2829; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 5, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2830; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 5, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2831; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 6, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2832; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 6, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2833; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 6, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2834; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 6, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2835; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 6, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2836; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 6, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2837; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 6, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2838; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 6, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2839; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 6, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2840; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 7, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2841; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 7, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2842; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 7, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2843; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 7, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2844; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 7, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2845; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 7, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2846; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 7, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2847; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 7, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2848; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 7, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2849; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 8, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2850; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 8, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2851; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 8, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2852; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 8, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2853; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 8, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2854; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 8, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2855; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 8, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2856; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 8, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2857; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 8, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2858; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 9, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2859; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 9, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2860; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 9, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2861; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 9, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2862; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 9, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2863; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 9, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2864; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 9, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2865; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 9, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2866; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 9, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2867; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 10, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2868; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 10, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2869; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 10, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2870; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 10, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2871; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 10, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2872; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 10, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2873; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 10, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2874; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 10, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2875; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 10, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2876; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 11, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2877; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 11, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2878; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 11, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2879; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 11, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2880; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 11, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2881; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 11, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2882; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 11, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2883; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 11, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2884; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 11, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2885; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 12, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2886; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 12, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2887; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 12, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2888; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 12, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2889; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 12, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2890; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 12, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2891; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 12, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2892; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 12, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2893; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 12, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2894; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 13, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2895; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 13, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2896; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 13, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2897; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 13, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2898; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 13, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2899; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 13, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2900; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 13, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2901; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 13, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2902; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 13, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2903; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 14, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2904; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 14, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2905; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 14, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2906; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 14, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2907; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 14, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2908; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 14, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2909; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 14, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2910; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 14, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2911; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 14, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2912; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 15, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2913; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 15, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2914; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 15, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2915; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 15, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2916; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 15, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2917; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 15, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2918; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 15, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2919; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 15, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2920; case RedstoneWire::RedstoneWire(RedstoneWire::East::Side, RedstoneWire::North::None, 15, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2921; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 0, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2922; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 0, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2923; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 0, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2924; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 0, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2925; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 0, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2926; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 0, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2927; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 0, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2928; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 0, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2929; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 0, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2930; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 1, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2931; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 1, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2932; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 1, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2933; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 1, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2934; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 1, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2935; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 1, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2936; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 1, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2937; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 1, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2938; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 1, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2939; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 2, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2940; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 2, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2941; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 2, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2942; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 2, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2943; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 2, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2944; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 2, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2945; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 2, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2946; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 2, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2947; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 2, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2948; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 3, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2949; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 3, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2950; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 3, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2951; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 3, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2952; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 3, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2953; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 3, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2954; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 3, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2955; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 3, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2956; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 3, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2957; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 4, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2958; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 4, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2959; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 4, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2960; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 4, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2961; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 4, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2962; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 4, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2963; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 4, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2964; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 4, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2965; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 4, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2966; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 5, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2967; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 5, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2968; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 5, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2969; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 5, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2970; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 5, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2971; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 5, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2972; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 5, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2973; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 5, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2974; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 5, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2975; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 6, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2976; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 6, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2977; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 6, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2978; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 6, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2979; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 6, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2980; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 6, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2981; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 6, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2982; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 6, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2983; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 6, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2984; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 7, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2985; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 7, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2986; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 7, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2987; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 7, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2988; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 7, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2989; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 7, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2990; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 7, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 2991; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 7, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 2992; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 7, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 2993; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 8, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 2994; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 8, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 2995; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 8, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 2996; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 8, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 2997; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 8, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 2998; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 8, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 2999; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 8, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3000; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 8, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3001; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 8, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3002; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 9, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3003; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 9, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3004; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 9, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3005; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 9, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3006; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 9, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3007; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 9, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3008; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 9, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3009; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 9, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3010; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 9, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3011; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 10, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3012; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 10, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3013; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 10, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3014; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 10, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3015; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 10, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3016; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 10, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3017; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 10, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3018; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 10, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3019; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 10, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3020; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 11, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3021; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 11, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3022; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 11, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3023; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 11, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3024; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 11, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3025; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 11, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3026; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 11, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3027; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 11, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3028; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 11, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3029; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 12, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3030; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 12, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3031; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 12, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3032; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 12, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3033; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 12, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3034; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 12, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3035; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 12, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3036; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 12, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3037; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 12, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3038; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 13, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3039; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 13, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3040; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 13, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3041; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 13, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3042; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 13, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3043; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 13, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3044; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 13, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3045; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 13, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3046; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 13, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3047; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 14, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3048; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 14, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3049; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 14, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3050; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 14, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3051; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 14, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3052; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 14, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3053; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 14, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3054; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 14, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3055; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 14, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3056; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 15, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3057; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 15, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3058; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 15, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3059; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 15, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3060; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 15, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3061; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 15, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3062; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 15, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3063; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 15, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3064; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Up, 15, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3065; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 0, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3066; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 0, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3067; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 0, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3068; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 0, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3069; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 0, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3070; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 0, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3071; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 0, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3072; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 0, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3073; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 0, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3074; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 1, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3075; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 1, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3076; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 1, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3077; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 1, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3078; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 1, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3079; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 1, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3080; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 1, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3081; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 1, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3082; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 1, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3083; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 2, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3084; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 2, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3085; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 2, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3086; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 2, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3087; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 2, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3088; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 2, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3089; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 2, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3090; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 2, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3091; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 2, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3092; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 3, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3093; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 3, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3094; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 3, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3095; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 3, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3096; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 3, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3097; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 3, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3098; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 3, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3099; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 3, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3100; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 3, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3101; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 4, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3102; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 4, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3103; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 4, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3104; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 4, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3105; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 4, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3106; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 4, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3107; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 4, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3108; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 4, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3109; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 4, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3110; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 5, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3111; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 5, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3112; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 5, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3113; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 5, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3114; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 5, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3115; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 5, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3116; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 5, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3117; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 5, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3118; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 5, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3119; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 6, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3120; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 6, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3121; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 6, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3122; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 6, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3123; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 6, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3124; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 6, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3125; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 6, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3126; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 6, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3127; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 6, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3128; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 7, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3129; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 7, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3130; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 7, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3131; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 7, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3132; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 7, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3133; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 7, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3134; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 7, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3135; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 7, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3136; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 7, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3137; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 8, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3138; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 8, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3139; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 8, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3140; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 8, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3141; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 8, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3142; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 8, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3143; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 8, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3144; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 8, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3145; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 8, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3146; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 9, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3147; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 9, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3148; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 9, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3149; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 9, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3150; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 9, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3151; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 9, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3152; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 9, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3153; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 9, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3154; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 9, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3155; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 10, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3156; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 10, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3157; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 10, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3158; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 10, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3159; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 10, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3160; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 10, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3161; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 10, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3162; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 10, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3163; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 10, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3164; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 11, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3165; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 11, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3166; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 11, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3167; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 11, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3168; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 11, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3169; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 11, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3170; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 11, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3171; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 11, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3172; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 11, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3173; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 12, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3174; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 12, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3175; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 12, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3176; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 12, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3177; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 12, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3178; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 12, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3179; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 12, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3180; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 12, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3181; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 12, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3182; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 13, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3183; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 13, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3184; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 13, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3185; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 13, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3186; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 13, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3187; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 13, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3188; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 13, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3189; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 13, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3190; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 13, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3191; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 14, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3192; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 14, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3193; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 14, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3194; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 14, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3195; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 14, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3196; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 14, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3197; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 14, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3198; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 14, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3199; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 14, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3200; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 15, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3201; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 15, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3202; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 15, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3203; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 15, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3204; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 15, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3205; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 15, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3206; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 15, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3207; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 15, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3208; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::Side, 15, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3209; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 0, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3210; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 0, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3211; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 0, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3212; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 0, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3213; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 0, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3214; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 0, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3215; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 0, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3216; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 0, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3217; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 0, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3218; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 1, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3219; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 1, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3220; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 1, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3221; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 1, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3222; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 1, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3223; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 1, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3224; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 1, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3225; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 1, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3226; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 1, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3227; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 2, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3228; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 2, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3229; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 2, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3230; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 2, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3231; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 2, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3232; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 2, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3233; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 2, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3234; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 2, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3235; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 2, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3236; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 3, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3237; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 3, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3238; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 3, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3239; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 3, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3240; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 3, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3241; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 3, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3242; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 3, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3243; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 3, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3244; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 3, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3245; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 4, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3246; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 4, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3247; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 4, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3248; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 4, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3249; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 4, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3250; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 4, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3251; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 4, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3252; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 4, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3253; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 4, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3254; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 5, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3255; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 5, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3256; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 5, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3257; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 5, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3258; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 5, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3259; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 5, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3260; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 5, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3261; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 5, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3262; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 5, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3263; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 6, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3264; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 6, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3265; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 6, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3266; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 6, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3267; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 6, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3268; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 6, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3269; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 6, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3270; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 6, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3271; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 6, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3272; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 7, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3273; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 7, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3274; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 7, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3275; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 7, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3276; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 7, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3277; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 7, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3278; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 7, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3279; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 7, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3280; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 7, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3281; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 8, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3282; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 8, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3283; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 8, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3284; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 8, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3285; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 8, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3286; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 8, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3287; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 8, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3288; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 8, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3289; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 8, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3290; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 9, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3291; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 9, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3292; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 9, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3293; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 9, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3294; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 9, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3295; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 9, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3296; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 9, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3297; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 9, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3298; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 9, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3299; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 10, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3300; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 10, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3301; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 10, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3302; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 10, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3303; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 10, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3304; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 10, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3305; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 10, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3306; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 10, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3307; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 10, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3308; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 11, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3309; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 11, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3310; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 11, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3311; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 11, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3312; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 11, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3313; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 11, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3314; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 11, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3315; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 11, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3316; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 11, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3317; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 12, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3318; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 12, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3319; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 12, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3320; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 12, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3321; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 12, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3322; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 12, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3323; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 12, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3324; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 12, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3325; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 12, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3326; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 13, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3327; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 13, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3328; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 13, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3329; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 13, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3330; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 13, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3331; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 13, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3332; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 13, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3333; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 13, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3334; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 13, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3335; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 14, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3336; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 14, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3337; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 14, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3338; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 14, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3339; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 14, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3340; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 14, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3341; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 14, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3342; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 14, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3343; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 14, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3344; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 15, RedstoneWire::South::Up, RedstoneWire::West::Up).ID: return 3345; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 15, RedstoneWire::South::Up, RedstoneWire::West::Side).ID: return 3346; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 15, RedstoneWire::South::Up, RedstoneWire::West::None).ID: return 3347; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 15, RedstoneWire::South::Side, RedstoneWire::West::Up).ID: return 3348; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 15, RedstoneWire::South::Side, RedstoneWire::West::Side).ID: return 3349; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 15, RedstoneWire::South::Side, RedstoneWire::West::None).ID: return 3350; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 15, RedstoneWire::South::None, RedstoneWire::West::Up).ID: return 3351; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 15, RedstoneWire::South::None, RedstoneWire::West::Side).ID: return 3352; case RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 15, RedstoneWire::South::None, RedstoneWire::West::None).ID: return 3353; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_ZM, true, true).ID: return 4031; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_ZM, true, false).ID: return 4032; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_ZM, false, true).ID: return 4033; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_ZM, false, false).ID: return 4034; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_ZP, true, true).ID: return 4035; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_ZP, true, false).ID: return 4036; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_ZP, false, true).ID: return 4037; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_ZP, false, false).ID: return 4038; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_XM, true, true).ID: return 4039; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_XM, true, false).ID: return 4040; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_XM, false, true).ID: return 4041; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_XM, false, false).ID: return 4042; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_XP, true, true).ID: return 4043; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_XP, true, false).ID: return 4044; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_XP, false, true).ID: return 4045; case Repeater::Repeater(1, eBlockFace::BLOCK_FACE_XP, false, false).ID: return 4046; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_ZM, true, true).ID: return 4047; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_ZM, true, false).ID: return 4048; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_ZM, false, true).ID: return 4049; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_ZM, false, false).ID: return 4050; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_ZP, true, true).ID: return 4051; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_ZP, true, false).ID: return 4052; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_ZP, false, true).ID: return 4053; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_ZP, false, false).ID: return 4054; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_XM, true, true).ID: return 4055; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_XM, true, false).ID: return 4056; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_XM, false, true).ID: return 4057; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_XM, false, false).ID: return 4058; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_XP, true, true).ID: return 4059; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_XP, true, false).ID: return 4060; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_XP, false, true).ID: return 4061; case Repeater::Repeater(2, eBlockFace::BLOCK_FACE_XP, false, false).ID: return 4062; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_ZM, true, true).ID: return 4063; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_ZM, true, false).ID: return 4064; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_ZM, false, true).ID: return 4065; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_ZM, false, false).ID: return 4066; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_ZP, true, true).ID: return 4067; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_ZP, true, false).ID: return 4068; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_ZP, false, true).ID: return 4069; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_ZP, false, false).ID: return 4070; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_XM, true, true).ID: return 4071; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_XM, true, false).ID: return 4072; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_XM, false, true).ID: return 4073; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_XM, false, false).ID: return 4074; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_XP, true, true).ID: return 4075; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_XP, true, false).ID: return 4076; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_XP, false, true).ID: return 4077; case Repeater::Repeater(3, eBlockFace::BLOCK_FACE_XP, false, false).ID: return 4078; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_ZM, true, true).ID: return 4079; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_ZM, true, false).ID: return 4080; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_ZM, false, true).ID: return 4081; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_ZM, false, false).ID: return 4082; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_ZP, true, true).ID: return 4083; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_ZP, true, false).ID: return 4084; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_ZP, false, true).ID: return 4085; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_ZP, false, false).ID: return 4086; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_XM, true, true).ID: return 4087; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_XM, true, false).ID: return 4088; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_XM, false, true).ID: return 4089; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_XM, false, false).ID: return 4090; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_XP, true, true).ID: return 4091; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_XP, true, false).ID: return 4092; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_XP, false, true).ID: return 4093; case Repeater::Repeater(4, eBlockFace::BLOCK_FACE_XP, false, false).ID: return 4094; case RepeatingCommandBlock::RepeatingCommandBlock(true, eBlockFace::BLOCK_FACE_ZM).ID: return 9225; case RepeatingCommandBlock::RepeatingCommandBlock(true, eBlockFace::BLOCK_FACE_XP).ID: return 9226; case RepeatingCommandBlock::RepeatingCommandBlock(true, eBlockFace::BLOCK_FACE_ZP).ID: return 9227; case RepeatingCommandBlock::RepeatingCommandBlock(true, eBlockFace::BLOCK_FACE_XM).ID: return 9228; case RepeatingCommandBlock::RepeatingCommandBlock(true, eBlockFace::BLOCK_FACE_YP).ID: return 9229; case RepeatingCommandBlock::RepeatingCommandBlock(true, eBlockFace::BLOCK_FACE_YM).ID: return 9230; case RepeatingCommandBlock::RepeatingCommandBlock(false, eBlockFace::BLOCK_FACE_ZM).ID: return 9231; case RepeatingCommandBlock::RepeatingCommandBlock(false, eBlockFace::BLOCK_FACE_XP).ID: return 9232; case RepeatingCommandBlock::RepeatingCommandBlock(false, eBlockFace::BLOCK_FACE_ZP).ID: return 9233; case RepeatingCommandBlock::RepeatingCommandBlock(false, eBlockFace::BLOCK_FACE_XM).ID: return 9234; case RepeatingCommandBlock::RepeatingCommandBlock(false, eBlockFace::BLOCK_FACE_YP).ID: return 9235; case RepeatingCommandBlock::RepeatingCommandBlock(false, eBlockFace::BLOCK_FACE_YM).ID: return 9236; case RespawnAnchor::RespawnAnchor(0).ID: return 15829; case RespawnAnchor::RespawnAnchor(1).ID: return 15830; case RespawnAnchor::RespawnAnchor(2).ID: return 15831; case RespawnAnchor::RespawnAnchor(3).ID: return 15832; case RespawnAnchor::RespawnAnchor(4).ID: return 15833; case RoseBush::RoseBush(RoseBush::Half::Upper).ID: return 7889; case RoseBush::RoseBush(RoseBush::Half::Lower).ID: return 7890; case Sand::Sand().ID: return 66; case Sandstone::Sandstone().ID: return 246; case SandstoneSlab::SandstoneSlab(SandstoneSlab::Type::Top).ID: return 8349; case SandstoneSlab::SandstoneSlab(SandstoneSlab::Type::Bottom).ID: return 8351; case SandstoneSlab::SandstoneSlab(SandstoneSlab::Type::Double).ID: return 8353; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SandstoneStairs::Half::Top, SandstoneStairs::Shape::Straight).ID: return 5171; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SandstoneStairs::Half::Top, SandstoneStairs::Shape::InnerLeft).ID: return 5173; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SandstoneStairs::Half::Top, SandstoneStairs::Shape::InnerRight).ID: return 5175; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SandstoneStairs::Half::Top, SandstoneStairs::Shape::OuterLeft).ID: return 5177; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SandstoneStairs::Half::Top, SandstoneStairs::Shape::OuterRight).ID: return 5179; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::Straight).ID: return 5181; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::InnerLeft).ID: return 5183; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::InnerRight).ID: return 5185; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::OuterLeft).ID: return 5187; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::OuterRight).ID: return 5189; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SandstoneStairs::Half::Top, SandstoneStairs::Shape::Straight).ID: return 5191; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SandstoneStairs::Half::Top, SandstoneStairs::Shape::InnerLeft).ID: return 5193; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SandstoneStairs::Half::Top, SandstoneStairs::Shape::InnerRight).ID: return 5195; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SandstoneStairs::Half::Top, SandstoneStairs::Shape::OuterLeft).ID: return 5197; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SandstoneStairs::Half::Top, SandstoneStairs::Shape::OuterRight).ID: return 5199; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::Straight).ID: return 5201; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::InnerLeft).ID: return 5203; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::InnerRight).ID: return 5205; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::OuterLeft).ID: return 5207; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::OuterRight).ID: return 5209; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XM, SandstoneStairs::Half::Top, SandstoneStairs::Shape::Straight).ID: return 5211; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XM, SandstoneStairs::Half::Top, SandstoneStairs::Shape::InnerLeft).ID: return 5213; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XM, SandstoneStairs::Half::Top, SandstoneStairs::Shape::InnerRight).ID: return 5215; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XM, SandstoneStairs::Half::Top, SandstoneStairs::Shape::OuterLeft).ID: return 5217; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XM, SandstoneStairs::Half::Top, SandstoneStairs::Shape::OuterRight).ID: return 5219; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XM, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::Straight).ID: return 5221; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XM, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::InnerLeft).ID: return 5223; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XM, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::InnerRight).ID: return 5225; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XM, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::OuterLeft).ID: return 5227; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XM, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::OuterRight).ID: return 5229; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XP, SandstoneStairs::Half::Top, SandstoneStairs::Shape::Straight).ID: return 5231; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XP, SandstoneStairs::Half::Top, SandstoneStairs::Shape::InnerLeft).ID: return 5233; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XP, SandstoneStairs::Half::Top, SandstoneStairs::Shape::InnerRight).ID: return 5235; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XP, SandstoneStairs::Half::Top, SandstoneStairs::Shape::OuterLeft).ID: return 5237; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XP, SandstoneStairs::Half::Top, SandstoneStairs::Shape::OuterRight).ID: return 5239; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XP, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::Straight).ID: return 5241; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XP, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::InnerLeft).ID: return 5243; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XP, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::InnerRight).ID: return 5245; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XP, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::OuterLeft).ID: return 5247; case SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XP, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::OuterRight).ID: return 5249; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::None, SandstoneWall::South::None, true, SandstoneWall::West::None).ID: return 13786; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::None, SandstoneWall::South::None, true, SandstoneWall::West::Low).ID: return 13787; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::None, SandstoneWall::South::None, true, SandstoneWall::West::Tall).ID: return 13788; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::None, SandstoneWall::South::None, false, SandstoneWall::West::None).ID: return 13792; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::None, SandstoneWall::South::None, false, SandstoneWall::West::Low).ID: return 13793; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::None, SandstoneWall::South::None, false, SandstoneWall::West::Tall).ID: return 13794; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::None, SandstoneWall::South::Low, true, SandstoneWall::West::None).ID: return 13798; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::None, SandstoneWall::South::Low, true, SandstoneWall::West::Low).ID: return 13799; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::None, SandstoneWall::South::Low, true, SandstoneWall::West::Tall).ID: return 13800; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::None, SandstoneWall::South::Low, false, SandstoneWall::West::None).ID: return 13804; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::None, SandstoneWall::South::Low, false, SandstoneWall::West::Low).ID: return 13805; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::None, SandstoneWall::South::Low, false, SandstoneWall::West::Tall).ID: return 13806; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::None, SandstoneWall::South::Tall, true, SandstoneWall::West::None).ID: return 13810; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::None, SandstoneWall::South::Tall, true, SandstoneWall::West::Low).ID: return 13811; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::None, SandstoneWall::South::Tall, true, SandstoneWall::West::Tall).ID: return 13812; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::None, SandstoneWall::South::Tall, false, SandstoneWall::West::None).ID: return 13816; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::None, SandstoneWall::South::Tall, false, SandstoneWall::West::Low).ID: return 13817; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::None, SandstoneWall::South::Tall, false, SandstoneWall::West::Tall).ID: return 13818; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::Low, SandstoneWall::South::None, true, SandstoneWall::West::None).ID: return 13822; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::Low, SandstoneWall::South::None, true, SandstoneWall::West::Low).ID: return 13823; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::Low, SandstoneWall::South::None, true, SandstoneWall::West::Tall).ID: return 13824; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::Low, SandstoneWall::South::None, false, SandstoneWall::West::None).ID: return 13828; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::Low, SandstoneWall::South::None, false, SandstoneWall::West::Low).ID: return 13829; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::Low, SandstoneWall::South::None, false, SandstoneWall::West::Tall).ID: return 13830; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::Low, SandstoneWall::South::Low, true, SandstoneWall::West::None).ID: return 13834; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::Low, SandstoneWall::South::Low, true, SandstoneWall::West::Low).ID: return 13835; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::Low, SandstoneWall::South::Low, true, SandstoneWall::West::Tall).ID: return 13836; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::Low, SandstoneWall::South::Low, false, SandstoneWall::West::None).ID: return 13840; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::Low, SandstoneWall::South::Low, false, SandstoneWall::West::Low).ID: return 13841; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::Low, SandstoneWall::South::Low, false, SandstoneWall::West::Tall).ID: return 13842; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::Low, SandstoneWall::South::Tall, true, SandstoneWall::West::None).ID: return 13846; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::Low, SandstoneWall::South::Tall, true, SandstoneWall::West::Low).ID: return 13847; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::Low, SandstoneWall::South::Tall, true, SandstoneWall::West::Tall).ID: return 13848; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::Low, SandstoneWall::South::Tall, false, SandstoneWall::West::None).ID: return 13852; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::Low, SandstoneWall::South::Tall, false, SandstoneWall::West::Low).ID: return 13853; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::Low, SandstoneWall::South::Tall, false, SandstoneWall::West::Tall).ID: return 13854; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::Tall, SandstoneWall::South::None, true, SandstoneWall::West::None).ID: return 13858; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::Tall, SandstoneWall::South::None, true, SandstoneWall::West::Low).ID: return 13859; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::Tall, SandstoneWall::South::None, true, SandstoneWall::West::Tall).ID: return 13860; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::Tall, SandstoneWall::South::None, false, SandstoneWall::West::None).ID: return 13864; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::Tall, SandstoneWall::South::None, false, SandstoneWall::West::Low).ID: return 13865; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::Tall, SandstoneWall::South::None, false, SandstoneWall::West::Tall).ID: return 13866; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::Tall, SandstoneWall::South::Low, true, SandstoneWall::West::None).ID: return 13870; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::Tall, SandstoneWall::South::Low, true, SandstoneWall::West::Low).ID: return 13871; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::Tall, SandstoneWall::South::Low, true, SandstoneWall::West::Tall).ID: return 13872; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::Tall, SandstoneWall::South::Low, false, SandstoneWall::West::None).ID: return 13876; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::Tall, SandstoneWall::South::Low, false, SandstoneWall::West::Low).ID: return 13877; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::Tall, SandstoneWall::South::Low, false, SandstoneWall::West::Tall).ID: return 13878; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::Tall, SandstoneWall::South::Tall, true, SandstoneWall::West::None).ID: return 13882; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::Tall, SandstoneWall::South::Tall, true, SandstoneWall::West::Low).ID: return 13883; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::Tall, SandstoneWall::South::Tall, true, SandstoneWall::West::Tall).ID: return 13884; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::Tall, SandstoneWall::South::Tall, false, SandstoneWall::West::None).ID: return 13888; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::Tall, SandstoneWall::South::Tall, false, SandstoneWall::West::Low).ID: return 13889; case SandstoneWall::SandstoneWall(SandstoneWall::East::None, SandstoneWall::North::Tall, SandstoneWall::South::Tall, false, SandstoneWall::West::Tall).ID: return 13890; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::None, SandstoneWall::South::None, true, SandstoneWall::West::None).ID: return 13894; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::None, SandstoneWall::South::None, true, SandstoneWall::West::Low).ID: return 13895; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::None, SandstoneWall::South::None, true, SandstoneWall::West::Tall).ID: return 13896; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::None, SandstoneWall::South::None, false, SandstoneWall::West::None).ID: return 13900; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::None, SandstoneWall::South::None, false, SandstoneWall::West::Low).ID: return 13901; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::None, SandstoneWall::South::None, false, SandstoneWall::West::Tall).ID: return 13902; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::None, SandstoneWall::South::Low, true, SandstoneWall::West::None).ID: return 13906; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::None, SandstoneWall::South::Low, true, SandstoneWall::West::Low).ID: return 13907; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::None, SandstoneWall::South::Low, true, SandstoneWall::West::Tall).ID: return 13908; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::None, SandstoneWall::South::Low, false, SandstoneWall::West::None).ID: return 13912; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::None, SandstoneWall::South::Low, false, SandstoneWall::West::Low).ID: return 13913; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::None, SandstoneWall::South::Low, false, SandstoneWall::West::Tall).ID: return 13914; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::None, SandstoneWall::South::Tall, true, SandstoneWall::West::None).ID: return 13918; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::None, SandstoneWall::South::Tall, true, SandstoneWall::West::Low).ID: return 13919; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::None, SandstoneWall::South::Tall, true, SandstoneWall::West::Tall).ID: return 13920; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::None, SandstoneWall::South::Tall, false, SandstoneWall::West::None).ID: return 13924; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::None, SandstoneWall::South::Tall, false, SandstoneWall::West::Low).ID: return 13925; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::None, SandstoneWall::South::Tall, false, SandstoneWall::West::Tall).ID: return 13926; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::Low, SandstoneWall::South::None, true, SandstoneWall::West::None).ID: return 13930; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::Low, SandstoneWall::South::None, true, SandstoneWall::West::Low).ID: return 13931; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::Low, SandstoneWall::South::None, true, SandstoneWall::West::Tall).ID: return 13932; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::Low, SandstoneWall::South::None, false, SandstoneWall::West::None).ID: return 13936; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::Low, SandstoneWall::South::None, false, SandstoneWall::West::Low).ID: return 13937; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::Low, SandstoneWall::South::None, false, SandstoneWall::West::Tall).ID: return 13938; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::Low, SandstoneWall::South::Low, true, SandstoneWall::West::None).ID: return 13942; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::Low, SandstoneWall::South::Low, true, SandstoneWall::West::Low).ID: return 13943; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::Low, SandstoneWall::South::Low, true, SandstoneWall::West::Tall).ID: return 13944; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::Low, SandstoneWall::South::Low, false, SandstoneWall::West::None).ID: return 13948; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::Low, SandstoneWall::South::Low, false, SandstoneWall::West::Low).ID: return 13949; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::Low, SandstoneWall::South::Low, false, SandstoneWall::West::Tall).ID: return 13950; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::Low, SandstoneWall::South::Tall, true, SandstoneWall::West::None).ID: return 13954; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::Low, SandstoneWall::South::Tall, true, SandstoneWall::West::Low).ID: return 13955; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::Low, SandstoneWall::South::Tall, true, SandstoneWall::West::Tall).ID: return 13956; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::Low, SandstoneWall::South::Tall, false, SandstoneWall::West::None).ID: return 13960; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::Low, SandstoneWall::South::Tall, false, SandstoneWall::West::Low).ID: return 13961; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::Low, SandstoneWall::South::Tall, false, SandstoneWall::West::Tall).ID: return 13962; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::Tall, SandstoneWall::South::None, true, SandstoneWall::West::None).ID: return 13966; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::Tall, SandstoneWall::South::None, true, SandstoneWall::West::Low).ID: return 13967; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::Tall, SandstoneWall::South::None, true, SandstoneWall::West::Tall).ID: return 13968; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::Tall, SandstoneWall::South::None, false, SandstoneWall::West::None).ID: return 13972; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::Tall, SandstoneWall::South::None, false, SandstoneWall::West::Low).ID: return 13973; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::Tall, SandstoneWall::South::None, false, SandstoneWall::West::Tall).ID: return 13974; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::Tall, SandstoneWall::South::Low, true, SandstoneWall::West::None).ID: return 13978; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::Tall, SandstoneWall::South::Low, true, SandstoneWall::West::Low).ID: return 13979; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::Tall, SandstoneWall::South::Low, true, SandstoneWall::West::Tall).ID: return 13980; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::Tall, SandstoneWall::South::Low, false, SandstoneWall::West::None).ID: return 13984; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::Tall, SandstoneWall::South::Low, false, SandstoneWall::West::Low).ID: return 13985; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::Tall, SandstoneWall::South::Low, false, SandstoneWall::West::Tall).ID: return 13986; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::Tall, SandstoneWall::South::Tall, true, SandstoneWall::West::None).ID: return 13990; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::Tall, SandstoneWall::South::Tall, true, SandstoneWall::West::Low).ID: return 13991; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::Tall, SandstoneWall::South::Tall, true, SandstoneWall::West::Tall).ID: return 13992; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::Tall, SandstoneWall::South::Tall, false, SandstoneWall::West::None).ID: return 13996; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::Tall, SandstoneWall::South::Tall, false, SandstoneWall::West::Low).ID: return 13997; case SandstoneWall::SandstoneWall(SandstoneWall::East::Low, SandstoneWall::North::Tall, SandstoneWall::South::Tall, false, SandstoneWall::West::Tall).ID: return 13998; case SandstoneWall::SandstoneWall(SandstoneWall::East::Tall, SandstoneWall::North::None, SandstoneWall::South::None, true, SandstoneWall::West::None).ID: return 14002; case SandstoneWall::SandstoneWall(SandstoneWall::East::Tall, SandstoneWall::North::None, SandstoneWall::South::None, true, SandstoneWall::West::Low).ID: return 14003; case SandstoneWall::SandstoneWall(SandstoneWall::East::Tall, SandstoneWall::North::None, SandstoneWall::South::None, true, SandstoneWall::West::Tall).ID: return 14004; case SandstoneWall::SandstoneWall(SandstoneWall::East::Tall, SandstoneWall::North::None, SandstoneWall::South::None, false, SandstoneWall::West::None).ID: return 14008; case SandstoneWall::SandstoneWall(SandstoneWall::East::Tall, SandstoneWall::North::None, SandstoneWall::South::None, false, SandstoneWall::West::Low).ID: return 14009; case SandstoneWall::SandstoneWall(SandstoneWall::East::Tall, SandstoneWall::North::None, SandstoneWall::South::None, false, SandstoneWall::West::Tall).ID: return 14010; case SandstoneWall::SandstoneWall(SandstoneWall::East::Tall, SandstoneWall::North::None, SandstoneWall::South::Low, true, SandstoneWall::West::None).ID: return 14014; case SandstoneWall::SandstoneWall(SandstoneWall::East::Tall, SandstoneWall::North::None, SandstoneWall::South::Low, true, SandstoneWall::West::Low).ID: return 14015; case SandstoneWall::SandstoneWall(SandstoneWall::East::Tall, SandstoneWall::North::None, SandstoneWall::South::Low, true, SandstoneWall::West::Tall).ID: return 14016; case SandstoneWall::SandstoneWall(SandstoneWall::East::Tall, SandstoneWall::North::None, SandstoneWall::South::Low, false, SandstoneWall::West::None).ID: return 14020; case SandstoneWall::SandstoneWall(SandstoneWall::East::Tall, SandstoneWall::North::None, SandstoneWall::South::Low, false, SandstoneWall::West::Low).ID: return 14021; case SandstoneWall::SandstoneWall(SandstoneWall::East::Tall, SandstoneWall::North::None, SandstoneWall::South::Low, false, SandstoneWall::West::Tall).ID: return 14022; case SandstoneWall::SandstoneWall(SandstoneWall::East::Tall, SandstoneWall::North::None, SandstoneWall::South::Tall, true, SandstoneWall::West::None).ID: return 14026; case SandstoneWall::SandstoneWall(SandstoneWall::East::Tall, SandstoneWall::North::None, SandstoneWall::South::Tall, true, SandstoneWall::West::Low).ID: return 14027; case SandstoneWall::SandstoneWall(SandstoneWall::East::Tall, SandstoneWall::North::None, SandstoneWall::South::Tall, true, SandstoneWall::West::Tall).ID: return 14028; case SandstoneWall::SandstoneWall(SandstoneWall::East::Tall, SandstoneWall::North::None, SandstoneWall::South::Tall, false, SandstoneWall::West::None).ID: return 14032; case SandstoneWall::SandstoneWall(SandstoneWall::East::Tall, SandstoneWall::North::None, SandstoneWall::South::Tall, false, SandstoneWall::West::Low).ID: return 14033; case SandstoneWall::SandstoneWall(SandstoneWall::East::Tall, SandstoneWall::North::None, SandstoneWall::South::Tall, false, SandstoneWall::West::Tall).ID: return 14034; case SandstoneWall::SandstoneWall(SandstoneWall::East::Tall, SandstoneWall::North::Low, SandstoneWall::South::None, true, SandstoneWall::West::None).ID: return 14038; case SandstoneWall::SandstoneWall(SandstoneWall::East::Tall, SandstoneWall::North::Low, SandstoneWall::South::None, true, SandstoneWall::West::Low).ID: return 14039; case SandstoneWall::SandstoneWall(SandstoneWall::East::Tall, SandstoneWall::North::Low, SandstoneWall::South::None, true, SandstoneWall::West::Tall).ID: return 14040; case SandstoneWall::SandstoneWall(SandstoneWall::East::Tall, SandstoneWall::North::Low, SandstoneWall::South::None, false, SandstoneWall::West::None).ID: return 14044; case SandstoneWall::SandstoneWall(SandstoneWall::East::Tall, SandstoneWall::North::Low, SandstoneWall::South::None, false, SandstoneWall::West::Low).ID: return 14045; case SandstoneWall::SandstoneWall(SandstoneWall::East::Tall, SandstoneWall::North::Low, SandstoneWall::South::None, false, SandstoneWall::West::Tall).ID: return 14046; case SandstoneWall::SandstoneWall(SandstoneWall::East::Tall, SandstoneWall::North::Low, SandstoneWall::South::Low, true, SandstoneWall::West::None).ID: return 14050; case SandstoneWall::SandstoneWall(SandstoneWall::East::Tall, SandstoneWall::North::Low, SandstoneWall::South::Low, true, SandstoneWall::West::Low).ID: return 14051; case SandstoneWall::SandstoneWall(SandstoneWall::East::Tall, SandstoneWall::North::Low, SandstoneWall::South::Low, true, SandstoneWall::West::Tall).ID: return 14052; case SandstoneWall::SandstoneWall(SandstoneWall::East::Tall, SandstoneWall::North::Low, SandstoneWall::South::Low, false, SandstoneWall::West::None).ID: return 14056; case SandstoneWall::SandstoneWall(SandstoneWall::East::Tall, SandstoneWall::North::Low, SandstoneWall::South::Low, false, SandstoneWall::West::Low).ID: return 14057; case SandstoneWall::SandstoneWall(SandstoneWall::East::Tall, SandstoneWall::North::Low, SandstoneWall::South::Low, false, SandstoneWall::West::Tall).ID: return 14058; case SandstoneWall::SandstoneWall(SandstoneWall::East::Tall, SandstoneWall::North::Low, SandstoneWall::South::Tall, true, SandstoneWall::West::None).ID: return 14062; case SandstoneWall::SandstoneWall(SandstoneWall::East::Tall, SandstoneWall::North::Low, SandstoneWall::South::Tall, true, SandstoneWall::West::Low).ID: return 14063; case SandstoneWall::SandstoneWall(SandstoneWall::East::Tall, SandstoneWall::North::Low, SandstoneWall::South::Tall, true, SandstoneWall::West::Tall).ID: return 14064; case SandstoneWall::SandstoneWall(SandstoneWall::East::Tall, SandstoneWall::North::Low, SandstoneWall::South::Tall, false, SandstoneWall::West::None).ID: return 14068; case SandstoneWall::SandstoneWall(SandstoneWall::East::Tall, SandstoneWall::North::Low, SandstoneWall::South::Tall, false, SandstoneWall::West::Low).ID: return 14069; case SandstoneWall::SandstoneWall(SandstoneWall::East::Tall, SandstoneWall::North::Low, SandstoneWall::South::Tall, false, SandstoneWall::West::Tall).ID: return 14070; case SandstoneWall::SandstoneWall(SandstoneWall::East::Tall, SandstoneWall::North::Tall, SandstoneWall::South::None, true, SandstoneWall::West::None).ID: return 14074; case SandstoneWall::SandstoneWall(SandstoneWall::East::Tall, SandstoneWall::North::Tall, SandstoneWall::South::None, true, SandstoneWall::West::Low).ID: return 14075; case SandstoneWall::SandstoneWall(SandstoneWall::East::Tall, SandstoneWall::North::Tall, SandstoneWall::South::None, true, SandstoneWall::West::Tall).ID: return 14076; case SandstoneWall::SandstoneWall(SandstoneWall::East::Tall, SandstoneWall::North::Tall, SandstoneWall::South::None, false, SandstoneWall::West::None).ID: return 14080; case SandstoneWall::SandstoneWall(SandstoneWall::East::Tall, SandstoneWall::North::Tall, SandstoneWall::South::None, false, SandstoneWall::West::Low).ID: return 14081; case SandstoneWall::SandstoneWall(SandstoneWall::East::Tall, SandstoneWall::North::Tall, SandstoneWall::South::None, false, SandstoneWall::West::Tall).ID: return 14082; case SandstoneWall::SandstoneWall(SandstoneWall::East::Tall, SandstoneWall::North::Tall, SandstoneWall::South::Low, true, SandstoneWall::West::None).ID: return 14086; case SandstoneWall::SandstoneWall(SandstoneWall::East::Tall, SandstoneWall::North::Tall, SandstoneWall::South::Low, true, SandstoneWall::West::Low).ID: return 14087; case SandstoneWall::SandstoneWall(SandstoneWall::East::Tall, SandstoneWall::North::Tall, SandstoneWall::South::Low, true, SandstoneWall::West::Tall).ID: return 14088; case SandstoneWall::SandstoneWall(SandstoneWall::East::Tall, SandstoneWall::North::Tall, SandstoneWall::South::Low, false, SandstoneWall::West::None).ID: return 14092; case SandstoneWall::SandstoneWall(SandstoneWall::East::Tall, SandstoneWall::North::Tall, SandstoneWall::South::Low, false, SandstoneWall::West::Low).ID: return 14093; case SandstoneWall::SandstoneWall(SandstoneWall::East::Tall, SandstoneWall::North::Tall, SandstoneWall::South::Low, false, SandstoneWall::West::Tall).ID: return 14094; case SandstoneWall::SandstoneWall(SandstoneWall::East::Tall, SandstoneWall::North::Tall, SandstoneWall::South::Tall, true, SandstoneWall::West::None).ID: return 14098; case SandstoneWall::SandstoneWall(SandstoneWall::East::Tall, SandstoneWall::North::Tall, SandstoneWall::South::Tall, true, SandstoneWall::West::Low).ID: return 14099; case SandstoneWall::SandstoneWall(SandstoneWall::East::Tall, SandstoneWall::North::Tall, SandstoneWall::South::Tall, true, SandstoneWall::West::Tall).ID: return 14100; case SandstoneWall::SandstoneWall(SandstoneWall::East::Tall, SandstoneWall::North::Tall, SandstoneWall::South::Tall, false, SandstoneWall::West::None).ID: return 14104; case SandstoneWall::SandstoneWall(SandstoneWall::East::Tall, SandstoneWall::North::Tall, SandstoneWall::South::Tall, false, SandstoneWall::West::Low).ID: return 14105; case SandstoneWall::SandstoneWall(SandstoneWall::East::Tall, SandstoneWall::North::Tall, SandstoneWall::South::Tall, false, SandstoneWall::West::Tall).ID: return 14106; case Scaffolding::Scaffolding(true, 0).ID: return 14756; case Scaffolding::Scaffolding(true, 1).ID: return 14758; case Scaffolding::Scaffolding(true, 2).ID: return 14760; case Scaffolding::Scaffolding(true, 3).ID: return 14762; case Scaffolding::Scaffolding(true, 4).ID: return 14764; case Scaffolding::Scaffolding(true, 5).ID: return 14766; case Scaffolding::Scaffolding(true, 6).ID: return 14768; case Scaffolding::Scaffolding(true, 7).ID: return 14770; case Scaffolding::Scaffolding(false, 0).ID: return 14772; case Scaffolding::Scaffolding(false, 1).ID: return 14774; case Scaffolding::Scaffolding(false, 2).ID: return 14776; case Scaffolding::Scaffolding(false, 3).ID: return 14778; case Scaffolding::Scaffolding(false, 4).ID: return 14780; case Scaffolding::Scaffolding(false, 5).ID: return 14782; case Scaffolding::Scaffolding(false, 6).ID: return 14784; case Scaffolding::Scaffolding(false, 7).ID: return 14786; case SeaLantern::SeaLantern().ID: return 7862; case SeaPickle::SeaPickle(1).ID: return 9641; case SeaPickle::SeaPickle(2).ID: return 9643; case SeaPickle::SeaPickle(3).ID: return 9645; case SeaPickle::SeaPickle(4).ID: return 9647; case Seagrass::Seagrass().ID: return 1345; case Shroomlight::Shroomlight().ID: return 14989; case ShulkerBox::ShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 9272; case ShulkerBox::ShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 9273; case ShulkerBox::ShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 9274; case ShulkerBox::ShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 9275; case ShulkerBox::ShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 9276; case ShulkerBox::ShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 9277; case SkeletonSkull::SkeletonSkull(0).ID: return 6490; case SkeletonSkull::SkeletonSkull(1).ID: return 6491; case SkeletonSkull::SkeletonSkull(2).ID: return 6492; case SkeletonSkull::SkeletonSkull(3).ID: return 6493; case SkeletonSkull::SkeletonSkull(4).ID: return 6494; case SkeletonSkull::SkeletonSkull(5).ID: return 6495; case SkeletonSkull::SkeletonSkull(6).ID: return 6496; case SkeletonSkull::SkeletonSkull(7).ID: return 6497; case SkeletonSkull::SkeletonSkull(8).ID: return 6498; case SkeletonSkull::SkeletonSkull(9).ID: return 6499; case SkeletonSkull::SkeletonSkull(10).ID: return 6500; case SkeletonSkull::SkeletonSkull(11).ID: return 6501; case SkeletonSkull::SkeletonSkull(12).ID: return 6502; case SkeletonSkull::SkeletonSkull(13).ID: return 6503; case SkeletonSkull::SkeletonSkull(14).ID: return 6504; case SkeletonSkull::SkeletonSkull(15).ID: return 6505; case SkeletonWallSkull::SkeletonWallSkull(eBlockFace::BLOCK_FACE_ZM).ID: return 6506; case SkeletonWallSkull::SkeletonWallSkull(eBlockFace::BLOCK_FACE_ZP).ID: return 6507; case SkeletonWallSkull::SkeletonWallSkull(eBlockFace::BLOCK_FACE_XM).ID: return 6508; case SkeletonWallSkull::SkeletonWallSkull(eBlockFace::BLOCK_FACE_XP).ID: return 6509; case SlimeBlock::SlimeBlock().ID: return 7535; case SmithingTable::SmithingTable().ID: return 14849; case Smoker::Smoker(eBlockFace::BLOCK_FACE_ZM, true).ID: return 14803; case Smoker::Smoker(eBlockFace::BLOCK_FACE_ZM, false).ID: return 14804; case Smoker::Smoker(eBlockFace::BLOCK_FACE_ZP, true).ID: return 14805; case Smoker::Smoker(eBlockFace::BLOCK_FACE_ZP, false).ID: return 14806; case Smoker::Smoker(eBlockFace::BLOCK_FACE_XM, true).ID: return 14807; case Smoker::Smoker(eBlockFace::BLOCK_FACE_XM, false).ID: return 14808; case Smoker::Smoker(eBlockFace::BLOCK_FACE_XP, true).ID: return 14809; case Smoker::Smoker(eBlockFace::BLOCK_FACE_XP, false).ID: return 14810; case SmoothQuartz::SmoothQuartz().ID: return 8416; case SmoothQuartzSlab::SmoothQuartzSlab(SmoothQuartzSlab::Type::Top).ID: return 10832; case SmoothQuartzSlab::SmoothQuartzSlab(SmoothQuartzSlab::Type::Bottom).ID: return 10834; case SmoothQuartzSlab::SmoothQuartzSlab(SmoothQuartzSlab::Type::Double).ID: return 10836; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_ZM, SmoothQuartzStairs::Half::Top, SmoothQuartzStairs::Shape::Straight).ID: return 10310; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_ZM, SmoothQuartzStairs::Half::Top, SmoothQuartzStairs::Shape::InnerLeft).ID: return 10312; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_ZM, SmoothQuartzStairs::Half::Top, SmoothQuartzStairs::Shape::InnerRight).ID: return 10314; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_ZM, SmoothQuartzStairs::Half::Top, SmoothQuartzStairs::Shape::OuterLeft).ID: return 10316; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_ZM, SmoothQuartzStairs::Half::Top, SmoothQuartzStairs::Shape::OuterRight).ID: return 10318; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_ZM, SmoothQuartzStairs::Half::Bottom, SmoothQuartzStairs::Shape::Straight).ID: return 10320; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_ZM, SmoothQuartzStairs::Half::Bottom, SmoothQuartzStairs::Shape::InnerLeft).ID: return 10322; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_ZM, SmoothQuartzStairs::Half::Bottom, SmoothQuartzStairs::Shape::InnerRight).ID: return 10324; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_ZM, SmoothQuartzStairs::Half::Bottom, SmoothQuartzStairs::Shape::OuterLeft).ID: return 10326; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_ZM, SmoothQuartzStairs::Half::Bottom, SmoothQuartzStairs::Shape::OuterRight).ID: return 10328; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_ZP, SmoothQuartzStairs::Half::Top, SmoothQuartzStairs::Shape::Straight).ID: return 10330; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_ZP, SmoothQuartzStairs::Half::Top, SmoothQuartzStairs::Shape::InnerLeft).ID: return 10332; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_ZP, SmoothQuartzStairs::Half::Top, SmoothQuartzStairs::Shape::InnerRight).ID: return 10334; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_ZP, SmoothQuartzStairs::Half::Top, SmoothQuartzStairs::Shape::OuterLeft).ID: return 10336; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_ZP, SmoothQuartzStairs::Half::Top, SmoothQuartzStairs::Shape::OuterRight).ID: return 10338; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_ZP, SmoothQuartzStairs::Half::Bottom, SmoothQuartzStairs::Shape::Straight).ID: return 10340; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_ZP, SmoothQuartzStairs::Half::Bottom, SmoothQuartzStairs::Shape::InnerLeft).ID: return 10342; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_ZP, SmoothQuartzStairs::Half::Bottom, SmoothQuartzStairs::Shape::InnerRight).ID: return 10344; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_ZP, SmoothQuartzStairs::Half::Bottom, SmoothQuartzStairs::Shape::OuterLeft).ID: return 10346; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_ZP, SmoothQuartzStairs::Half::Bottom, SmoothQuartzStairs::Shape::OuterRight).ID: return 10348; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_XM, SmoothQuartzStairs::Half::Top, SmoothQuartzStairs::Shape::Straight).ID: return 10350; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_XM, SmoothQuartzStairs::Half::Top, SmoothQuartzStairs::Shape::InnerLeft).ID: return 10352; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_XM, SmoothQuartzStairs::Half::Top, SmoothQuartzStairs::Shape::InnerRight).ID: return 10354; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_XM, SmoothQuartzStairs::Half::Top, SmoothQuartzStairs::Shape::OuterLeft).ID: return 10356; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_XM, SmoothQuartzStairs::Half::Top, SmoothQuartzStairs::Shape::OuterRight).ID: return 10358; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_XM, SmoothQuartzStairs::Half::Bottom, SmoothQuartzStairs::Shape::Straight).ID: return 10360; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_XM, SmoothQuartzStairs::Half::Bottom, SmoothQuartzStairs::Shape::InnerLeft).ID: return 10362; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_XM, SmoothQuartzStairs::Half::Bottom, SmoothQuartzStairs::Shape::InnerRight).ID: return 10364; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_XM, SmoothQuartzStairs::Half::Bottom, SmoothQuartzStairs::Shape::OuterLeft).ID: return 10366; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_XM, SmoothQuartzStairs::Half::Bottom, SmoothQuartzStairs::Shape::OuterRight).ID: return 10368; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_XP, SmoothQuartzStairs::Half::Top, SmoothQuartzStairs::Shape::Straight).ID: return 10370; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_XP, SmoothQuartzStairs::Half::Top, SmoothQuartzStairs::Shape::InnerLeft).ID: return 10372; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_XP, SmoothQuartzStairs::Half::Top, SmoothQuartzStairs::Shape::InnerRight).ID: return 10374; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_XP, SmoothQuartzStairs::Half::Top, SmoothQuartzStairs::Shape::OuterLeft).ID: return 10376; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_XP, SmoothQuartzStairs::Half::Top, SmoothQuartzStairs::Shape::OuterRight).ID: return 10378; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_XP, SmoothQuartzStairs::Half::Bottom, SmoothQuartzStairs::Shape::Straight).ID: return 10380; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_XP, SmoothQuartzStairs::Half::Bottom, SmoothQuartzStairs::Shape::InnerLeft).ID: return 10382; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_XP, SmoothQuartzStairs::Half::Bottom, SmoothQuartzStairs::Shape::InnerRight).ID: return 10384; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_XP, SmoothQuartzStairs::Half::Bottom, SmoothQuartzStairs::Shape::OuterLeft).ID: return 10386; case SmoothQuartzStairs::SmoothQuartzStairs(eBlockFace::BLOCK_FACE_XP, SmoothQuartzStairs::Half::Bottom, SmoothQuartzStairs::Shape::OuterRight).ID: return 10388; case SmoothRedSandstone::SmoothRedSandstone().ID: return 8417; case SmoothRedSandstoneSlab::SmoothRedSandstoneSlab(SmoothRedSandstoneSlab::Type::Top).ID: return 10796; case SmoothRedSandstoneSlab::SmoothRedSandstoneSlab(SmoothRedSandstoneSlab::Type::Bottom).ID: return 10798; case SmoothRedSandstoneSlab::SmoothRedSandstoneSlab(SmoothRedSandstoneSlab::Type::Double).ID: return 10800; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SmoothRedSandstoneStairs::Half::Top, SmoothRedSandstoneStairs::Shape::Straight).ID: return 9750; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SmoothRedSandstoneStairs::Half::Top, SmoothRedSandstoneStairs::Shape::InnerLeft).ID: return 9752; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SmoothRedSandstoneStairs::Half::Top, SmoothRedSandstoneStairs::Shape::InnerRight).ID: return 9754; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SmoothRedSandstoneStairs::Half::Top, SmoothRedSandstoneStairs::Shape::OuterLeft).ID: return 9756; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SmoothRedSandstoneStairs::Half::Top, SmoothRedSandstoneStairs::Shape::OuterRight).ID: return 9758; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SmoothRedSandstoneStairs::Half::Bottom, SmoothRedSandstoneStairs::Shape::Straight).ID: return 9760; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SmoothRedSandstoneStairs::Half::Bottom, SmoothRedSandstoneStairs::Shape::InnerLeft).ID: return 9762; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SmoothRedSandstoneStairs::Half::Bottom, SmoothRedSandstoneStairs::Shape::InnerRight).ID: return 9764; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SmoothRedSandstoneStairs::Half::Bottom, SmoothRedSandstoneStairs::Shape::OuterLeft).ID: return 9766; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SmoothRedSandstoneStairs::Half::Bottom, SmoothRedSandstoneStairs::Shape::OuterRight).ID: return 9768; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SmoothRedSandstoneStairs::Half::Top, SmoothRedSandstoneStairs::Shape::Straight).ID: return 9770; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SmoothRedSandstoneStairs::Half::Top, SmoothRedSandstoneStairs::Shape::InnerLeft).ID: return 9772; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SmoothRedSandstoneStairs::Half::Top, SmoothRedSandstoneStairs::Shape::InnerRight).ID: return 9774; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SmoothRedSandstoneStairs::Half::Top, SmoothRedSandstoneStairs::Shape::OuterLeft).ID: return 9776; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SmoothRedSandstoneStairs::Half::Top, SmoothRedSandstoneStairs::Shape::OuterRight).ID: return 9778; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SmoothRedSandstoneStairs::Half::Bottom, SmoothRedSandstoneStairs::Shape::Straight).ID: return 9780; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SmoothRedSandstoneStairs::Half::Bottom, SmoothRedSandstoneStairs::Shape::InnerLeft).ID: return 9782; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SmoothRedSandstoneStairs::Half::Bottom, SmoothRedSandstoneStairs::Shape::InnerRight).ID: return 9784; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SmoothRedSandstoneStairs::Half::Bottom, SmoothRedSandstoneStairs::Shape::OuterLeft).ID: return 9786; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SmoothRedSandstoneStairs::Half::Bottom, SmoothRedSandstoneStairs::Shape::OuterRight).ID: return 9788; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, SmoothRedSandstoneStairs::Half::Top, SmoothRedSandstoneStairs::Shape::Straight).ID: return 9790; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, SmoothRedSandstoneStairs::Half::Top, SmoothRedSandstoneStairs::Shape::InnerLeft).ID: return 9792; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, SmoothRedSandstoneStairs::Half::Top, SmoothRedSandstoneStairs::Shape::InnerRight).ID: return 9794; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, SmoothRedSandstoneStairs::Half::Top, SmoothRedSandstoneStairs::Shape::OuterLeft).ID: return 9796; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, SmoothRedSandstoneStairs::Half::Top, SmoothRedSandstoneStairs::Shape::OuterRight).ID: return 9798; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, SmoothRedSandstoneStairs::Half::Bottom, SmoothRedSandstoneStairs::Shape::Straight).ID: return 9800; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, SmoothRedSandstoneStairs::Half::Bottom, SmoothRedSandstoneStairs::Shape::InnerLeft).ID: return 9802; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, SmoothRedSandstoneStairs::Half::Bottom, SmoothRedSandstoneStairs::Shape::InnerRight).ID: return 9804; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, SmoothRedSandstoneStairs::Half::Bottom, SmoothRedSandstoneStairs::Shape::OuterLeft).ID: return 9806; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, SmoothRedSandstoneStairs::Half::Bottom, SmoothRedSandstoneStairs::Shape::OuterRight).ID: return 9808; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, SmoothRedSandstoneStairs::Half::Top, SmoothRedSandstoneStairs::Shape::Straight).ID: return 9810; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, SmoothRedSandstoneStairs::Half::Top, SmoothRedSandstoneStairs::Shape::InnerLeft).ID: return 9812; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, SmoothRedSandstoneStairs::Half::Top, SmoothRedSandstoneStairs::Shape::InnerRight).ID: return 9814; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, SmoothRedSandstoneStairs::Half::Top, SmoothRedSandstoneStairs::Shape::OuterLeft).ID: return 9816; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, SmoothRedSandstoneStairs::Half::Top, SmoothRedSandstoneStairs::Shape::OuterRight).ID: return 9818; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, SmoothRedSandstoneStairs::Half::Bottom, SmoothRedSandstoneStairs::Shape::Straight).ID: return 9820; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, SmoothRedSandstoneStairs::Half::Bottom, SmoothRedSandstoneStairs::Shape::InnerLeft).ID: return 9822; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, SmoothRedSandstoneStairs::Half::Bottom, SmoothRedSandstoneStairs::Shape::InnerRight).ID: return 9824; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, SmoothRedSandstoneStairs::Half::Bottom, SmoothRedSandstoneStairs::Shape::OuterLeft).ID: return 9826; case SmoothRedSandstoneStairs::SmoothRedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, SmoothRedSandstoneStairs::Half::Bottom, SmoothRedSandstoneStairs::Shape::OuterRight).ID: return 9828; case SmoothSandstone::SmoothSandstone().ID: return 8415; case SmoothSandstoneSlab::SmoothSandstoneSlab(SmoothSandstoneSlab::Type::Top).ID: return 10826; case SmoothSandstoneSlab::SmoothSandstoneSlab(SmoothSandstoneSlab::Type::Bottom).ID: return 10828; case SmoothSandstoneSlab::SmoothSandstoneSlab(SmoothSandstoneSlab::Type::Double).ID: return 10830; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SmoothSandstoneStairs::Half::Top, SmoothSandstoneStairs::Shape::Straight).ID: return 10230; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SmoothSandstoneStairs::Half::Top, SmoothSandstoneStairs::Shape::InnerLeft).ID: return 10232; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SmoothSandstoneStairs::Half::Top, SmoothSandstoneStairs::Shape::InnerRight).ID: return 10234; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SmoothSandstoneStairs::Half::Top, SmoothSandstoneStairs::Shape::OuterLeft).ID: return 10236; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SmoothSandstoneStairs::Half::Top, SmoothSandstoneStairs::Shape::OuterRight).ID: return 10238; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SmoothSandstoneStairs::Half::Bottom, SmoothSandstoneStairs::Shape::Straight).ID: return 10240; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SmoothSandstoneStairs::Half::Bottom, SmoothSandstoneStairs::Shape::InnerLeft).ID: return 10242; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SmoothSandstoneStairs::Half::Bottom, SmoothSandstoneStairs::Shape::InnerRight).ID: return 10244; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SmoothSandstoneStairs::Half::Bottom, SmoothSandstoneStairs::Shape::OuterLeft).ID: return 10246; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SmoothSandstoneStairs::Half::Bottom, SmoothSandstoneStairs::Shape::OuterRight).ID: return 10248; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SmoothSandstoneStairs::Half::Top, SmoothSandstoneStairs::Shape::Straight).ID: return 10250; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SmoothSandstoneStairs::Half::Top, SmoothSandstoneStairs::Shape::InnerLeft).ID: return 10252; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SmoothSandstoneStairs::Half::Top, SmoothSandstoneStairs::Shape::InnerRight).ID: return 10254; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SmoothSandstoneStairs::Half::Top, SmoothSandstoneStairs::Shape::OuterLeft).ID: return 10256; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SmoothSandstoneStairs::Half::Top, SmoothSandstoneStairs::Shape::OuterRight).ID: return 10258; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SmoothSandstoneStairs::Half::Bottom, SmoothSandstoneStairs::Shape::Straight).ID: return 10260; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SmoothSandstoneStairs::Half::Bottom, SmoothSandstoneStairs::Shape::InnerLeft).ID: return 10262; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SmoothSandstoneStairs::Half::Bottom, SmoothSandstoneStairs::Shape::InnerRight).ID: return 10264; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SmoothSandstoneStairs::Half::Bottom, SmoothSandstoneStairs::Shape::OuterLeft).ID: return 10266; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SmoothSandstoneStairs::Half::Bottom, SmoothSandstoneStairs::Shape::OuterRight).ID: return 10268; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_XM, SmoothSandstoneStairs::Half::Top, SmoothSandstoneStairs::Shape::Straight).ID: return 10270; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_XM, SmoothSandstoneStairs::Half::Top, SmoothSandstoneStairs::Shape::InnerLeft).ID: return 10272; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_XM, SmoothSandstoneStairs::Half::Top, SmoothSandstoneStairs::Shape::InnerRight).ID: return 10274; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_XM, SmoothSandstoneStairs::Half::Top, SmoothSandstoneStairs::Shape::OuterLeft).ID: return 10276; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_XM, SmoothSandstoneStairs::Half::Top, SmoothSandstoneStairs::Shape::OuterRight).ID: return 10278; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_XM, SmoothSandstoneStairs::Half::Bottom, SmoothSandstoneStairs::Shape::Straight).ID: return 10280; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_XM, SmoothSandstoneStairs::Half::Bottom, SmoothSandstoneStairs::Shape::InnerLeft).ID: return 10282; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_XM, SmoothSandstoneStairs::Half::Bottom, SmoothSandstoneStairs::Shape::InnerRight).ID: return 10284; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_XM, SmoothSandstoneStairs::Half::Bottom, SmoothSandstoneStairs::Shape::OuterLeft).ID: return 10286; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_XM, SmoothSandstoneStairs::Half::Bottom, SmoothSandstoneStairs::Shape::OuterRight).ID: return 10288; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_XP, SmoothSandstoneStairs::Half::Top, SmoothSandstoneStairs::Shape::Straight).ID: return 10290; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_XP, SmoothSandstoneStairs::Half::Top, SmoothSandstoneStairs::Shape::InnerLeft).ID: return 10292; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_XP, SmoothSandstoneStairs::Half::Top, SmoothSandstoneStairs::Shape::InnerRight).ID: return 10294; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_XP, SmoothSandstoneStairs::Half::Top, SmoothSandstoneStairs::Shape::OuterLeft).ID: return 10296; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_XP, SmoothSandstoneStairs::Half::Top, SmoothSandstoneStairs::Shape::OuterRight).ID: return 10298; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_XP, SmoothSandstoneStairs::Half::Bottom, SmoothSandstoneStairs::Shape::Straight).ID: return 10300; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_XP, SmoothSandstoneStairs::Half::Bottom, SmoothSandstoneStairs::Shape::InnerLeft).ID: return 10302; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_XP, SmoothSandstoneStairs::Half::Bottom, SmoothSandstoneStairs::Shape::InnerRight).ID: return 10304; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_XP, SmoothSandstoneStairs::Half::Bottom, SmoothSandstoneStairs::Shape::OuterLeft).ID: return 10306; case SmoothSandstoneStairs::SmoothSandstoneStairs(eBlockFace::BLOCK_FACE_XP, SmoothSandstoneStairs::Half::Bottom, SmoothSandstoneStairs::Shape::OuterRight).ID: return 10308; case SmoothStone::SmoothStone().ID: return 8414; case SmoothStoneSlab::SmoothStoneSlab(SmoothStoneSlab::Type::Top).ID: return 8343; case SmoothStoneSlab::SmoothStoneSlab(SmoothStoneSlab::Type::Bottom).ID: return 8345; case SmoothStoneSlab::SmoothStoneSlab(SmoothStoneSlab::Type::Double).ID: return 8347; case Snow::Snow(1).ID: return 3921; case Snow::Snow(2).ID: return 3922; case Snow::Snow(3).ID: return 3923; case Snow::Snow(4).ID: return 3924; case Snow::Snow(5).ID: return 3925; case Snow::Snow(6).ID: return 3926; case Snow::Snow(7).ID: return 3927; case Snow::Snow(8).ID: return 3928; case SnowBlock::SnowBlock().ID: return 3930; case SoulCampfire::SoulCampfire(eBlockFace::BLOCK_FACE_ZM, true, true).ID: return 14923; case SoulCampfire::SoulCampfire(eBlockFace::BLOCK_FACE_ZM, true, false).ID: return 14925; case SoulCampfire::SoulCampfire(eBlockFace::BLOCK_FACE_ZM, false, true).ID: return 14927; case SoulCampfire::SoulCampfire(eBlockFace::BLOCK_FACE_ZM, false, false).ID: return 14929; case SoulCampfire::SoulCampfire(eBlockFace::BLOCK_FACE_ZP, true, true).ID: return 14931; case SoulCampfire::SoulCampfire(eBlockFace::BLOCK_FACE_ZP, true, false).ID: return 14933; case SoulCampfire::SoulCampfire(eBlockFace::BLOCK_FACE_ZP, false, true).ID: return 14935; case SoulCampfire::SoulCampfire(eBlockFace::BLOCK_FACE_ZP, false, false).ID: return 14937; case SoulCampfire::SoulCampfire(eBlockFace::BLOCK_FACE_XM, true, true).ID: return 14939; case SoulCampfire::SoulCampfire(eBlockFace::BLOCK_FACE_XM, true, false).ID: return 14941; case SoulCampfire::SoulCampfire(eBlockFace::BLOCK_FACE_XM, false, true).ID: return 14943; case SoulCampfire::SoulCampfire(eBlockFace::BLOCK_FACE_XM, false, false).ID: return 14945; case SoulCampfire::SoulCampfire(eBlockFace::BLOCK_FACE_XP, true, true).ID: return 14947; case SoulCampfire::SoulCampfire(eBlockFace::BLOCK_FACE_XP, true, false).ID: return 14949; case SoulCampfire::SoulCampfire(eBlockFace::BLOCK_FACE_XP, false, true).ID: return 14951; case SoulCampfire::SoulCampfire(eBlockFace::BLOCK_FACE_XP, false, false).ID: return 14953; case SoulFire::SoulFire().ID: return 1952; case SoulLantern::SoulLantern(true).ID: return 14888; case SoulLantern::SoulLantern(false).ID: return 14889; case SoulSand::SoulSand().ID: return 4000; case SoulSoil::SoulSoil().ID: return 4001; case SoulTorch::SoulTorch().ID: return 4008; case SoulWallTorch::SoulWallTorch(eBlockFace::BLOCK_FACE_ZM).ID: return 4009; case SoulWallTorch::SoulWallTorch(eBlockFace::BLOCK_FACE_ZP).ID: return 4010; case SoulWallTorch::SoulWallTorch(eBlockFace::BLOCK_FACE_XM).ID: return 4011; case SoulWallTorch::SoulWallTorch(eBlockFace::BLOCK_FACE_XP).ID: return 4012; case Spawner::Spawner().ID: return 1953; case Sponge::Sponge().ID: return 229; case SpruceButton::SpruceButton(SpruceButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, true).ID: return 6370; case SpruceButton::SpruceButton(SpruceButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, false).ID: return 6371; case SpruceButton::SpruceButton(SpruceButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, true).ID: return 6372; case SpruceButton::SpruceButton(SpruceButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, false).ID: return 6373; case SpruceButton::SpruceButton(SpruceButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, true).ID: return 6374; case SpruceButton::SpruceButton(SpruceButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, false).ID: return 6375; case SpruceButton::SpruceButton(SpruceButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, true).ID: return 6376; case SpruceButton::SpruceButton(SpruceButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, false).ID: return 6377; case SpruceButton::SpruceButton(SpruceButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, true).ID: return 6378; case SpruceButton::SpruceButton(SpruceButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, false).ID: return 6379; case SpruceButton::SpruceButton(SpruceButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, true).ID: return 6380; case SpruceButton::SpruceButton(SpruceButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, false).ID: return 6381; case SpruceButton::SpruceButton(SpruceButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, true).ID: return 6382; case SpruceButton::SpruceButton(SpruceButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, false).ID: return 6383; case SpruceButton::SpruceButton(SpruceButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, true).ID: return 6384; case SpruceButton::SpruceButton(SpruceButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, false).ID: return 6385; case SpruceButton::SpruceButton(SpruceButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, true).ID: return 6386; case SpruceButton::SpruceButton(SpruceButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, false).ID: return 6387; case SpruceButton::SpruceButton(SpruceButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, true).ID: return 6388; case SpruceButton::SpruceButton(SpruceButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, false).ID: return 6389; case SpruceButton::SpruceButton(SpruceButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, true).ID: return 6390; case SpruceButton::SpruceButton(SpruceButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, false).ID: return 6391; case SpruceButton::SpruceButton(SpruceButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, true).ID: return 6392; case SpruceButton::SpruceButton(SpruceButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, false).ID: return 6393; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, true, true).ID: return 8738; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, true, false).ID: return 8739; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, false, true).ID: return 8740; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, false, false).ID: return 8741; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, true, true).ID: return 8742; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, true, false).ID: return 8743; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, false, true).ID: return 8744; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, false, false).ID: return 8745; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, true, true).ID: return 8746; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, true, false).ID: return 8747; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, false, true).ID: return 8748; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, false, false).ID: return 8749; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, true, true).ID: return 8750; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, true, false).ID: return 8751; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, false, true).ID: return 8752; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, false, false).ID: return 8753; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, true, true).ID: return 8754; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, true, false).ID: return 8755; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, false, true).ID: return 8756; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, false, false).ID: return 8757; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, true, true).ID: return 8758; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, true, false).ID: return 8759; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, false, true).ID: return 8760; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, false, false).ID: return 8761; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, true, true).ID: return 8762; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, true, false).ID: return 8763; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, false, true).ID: return 8764; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, false, false).ID: return 8765; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, true, true).ID: return 8766; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, true, false).ID: return 8767; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, false, true).ID: return 8768; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, false, false).ID: return 8769; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, true, true).ID: return 8770; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, true, false).ID: return 8771; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, false, true).ID: return 8772; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, false, false).ID: return 8773; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, true, true).ID: return 8774; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, true, false).ID: return 8775; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, false, true).ID: return 8776; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, false, false).ID: return 8777; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, true, true).ID: return 8778; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, true, false).ID: return 8779; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, false, true).ID: return 8780; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, false, false).ID: return 8781; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, true, true).ID: return 8782; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, true, false).ID: return 8783; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, false, true).ID: return 8784; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, false, false).ID: return 8785; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, true, true).ID: return 8786; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, true, false).ID: return 8787; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, false, true).ID: return 8788; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, false, false).ID: return 8789; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, true, true).ID: return 8790; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, true, false).ID: return 8791; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, false, true).ID: return 8792; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, false, false).ID: return 8793; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, true, true).ID: return 8794; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, true, false).ID: return 8795; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, false, true).ID: return 8796; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Left, false, false).ID: return 8797; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, true, true).ID: return 8798; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, true, false).ID: return 8799; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, false, true).ID: return 8800; case SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, false, false).ID: return 8801; case SpruceFence::SpruceFence(true, true, true, true).ID: return 8580; case SpruceFence::SpruceFence(true, true, true, false).ID: return 8581; case SpruceFence::SpruceFence(true, true, false, true).ID: return 8584; case SpruceFence::SpruceFence(true, true, false, false).ID: return 8585; case SpruceFence::SpruceFence(true, false, true, true).ID: return 8588; case SpruceFence::SpruceFence(true, false, true, false).ID: return 8589; case SpruceFence::SpruceFence(true, false, false, true).ID: return 8592; case SpruceFence::SpruceFence(true, false, false, false).ID: return 8593; case SpruceFence::SpruceFence(false, true, true, true).ID: return 8596; case SpruceFence::SpruceFence(false, true, true, false).ID: return 8597; case SpruceFence::SpruceFence(false, true, false, true).ID: return 8600; case SpruceFence::SpruceFence(false, true, false, false).ID: return 8601; case SpruceFence::SpruceFence(false, false, true, true).ID: return 8604; case SpruceFence::SpruceFence(false, false, true, false).ID: return 8605; case SpruceFence::SpruceFence(false, false, false, true).ID: return 8608; case SpruceFence::SpruceFence(false, false, false, false).ID: return 8609; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZM, true, true, true).ID: return 8418; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZM, true, true, false).ID: return 8419; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZM, true, false, true).ID: return 8420; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZM, true, false, false).ID: return 8421; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, true).ID: return 8422; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, false).ID: return 8423; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, true).ID: return 8424; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, false).ID: return 8425; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZP, true, true, true).ID: return 8426; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZP, true, true, false).ID: return 8427; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZP, true, false, true).ID: return 8428; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZP, true, false, false).ID: return 8429; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, true).ID: return 8430; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, false).ID: return 8431; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, true).ID: return 8432; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, false).ID: return 8433; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XM, true, true, true).ID: return 8434; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XM, true, true, false).ID: return 8435; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XM, true, false, true).ID: return 8436; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XM, true, false, false).ID: return 8437; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, true).ID: return 8438; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, false).ID: return 8439; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, true).ID: return 8440; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, false).ID: return 8441; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XP, true, true, true).ID: return 8442; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XP, true, true, false).ID: return 8443; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XP, true, false, true).ID: return 8444; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XP, true, false, false).ID: return 8445; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, true).ID: return 8446; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, false).ID: return 8447; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, true).ID: return 8448; case SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, false).ID: return 8449; case SpruceLeaves::SpruceLeaves(1, true).ID: return 159; case SpruceLeaves::SpruceLeaves(1, false).ID: return 160; case SpruceLeaves::SpruceLeaves(2, true).ID: return 161; case SpruceLeaves::SpruceLeaves(2, false).ID: return 162; case SpruceLeaves::SpruceLeaves(3, true).ID: return 163; case SpruceLeaves::SpruceLeaves(3, false).ID: return 164; case SpruceLeaves::SpruceLeaves(4, true).ID: return 165; case SpruceLeaves::SpruceLeaves(4, false).ID: return 166; case SpruceLeaves::SpruceLeaves(5, true).ID: return 167; case SpruceLeaves::SpruceLeaves(5, false).ID: return 168; case SpruceLeaves::SpruceLeaves(6, true).ID: return 169; case SpruceLeaves::SpruceLeaves(6, false).ID: return 170; case SpruceLeaves::SpruceLeaves(7, true).ID: return 171; case SpruceLeaves::SpruceLeaves(7, false).ID: return 172; case SpruceLog::SpruceLog(SpruceLog::Axis::X).ID: return 76; case SpruceLog::SpruceLog(SpruceLog::Axis::Y).ID: return 77; case SpruceLog::SpruceLog(SpruceLog::Axis::Z).ID: return 78; case SprucePlanks::SprucePlanks().ID: return 16; case SprucePressurePlate::SprucePressurePlate(true).ID: return 3875; case SprucePressurePlate::SprucePressurePlate(false).ID: return 3876; case SpruceSapling::SpruceSapling(0).ID: return 23; case SpruceSapling::SpruceSapling(1).ID: return 24; case SpruceSign::SpruceSign(0).ID: return 3414; case SpruceSign::SpruceSign(1).ID: return 3416; case SpruceSign::SpruceSign(2).ID: return 3418; case SpruceSign::SpruceSign(3).ID: return 3420; case SpruceSign::SpruceSign(4).ID: return 3422; case SpruceSign::SpruceSign(5).ID: return 3424; case SpruceSign::SpruceSign(6).ID: return 3426; case SpruceSign::SpruceSign(7).ID: return 3428; case SpruceSign::SpruceSign(8).ID: return 3430; case SpruceSign::SpruceSign(9).ID: return 3432; case SpruceSign::SpruceSign(10).ID: return 3434; case SpruceSign::SpruceSign(11).ID: return 3436; case SpruceSign::SpruceSign(12).ID: return 3438; case SpruceSign::SpruceSign(13).ID: return 3440; case SpruceSign::SpruceSign(14).ID: return 3442; case SpruceSign::SpruceSign(15).ID: return 3444; case SpruceSlab::SpruceSlab(SpruceSlab::Type::Top).ID: return 8307; case SpruceSlab::SpruceSlab(SpruceSlab::Type::Bottom).ID: return 8309; case SpruceSlab::SpruceSlab(SpruceSlab::Type::Double).ID: return 8311; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZM, SpruceStairs::Half::Top, SpruceStairs::Shape::Straight).ID: return 5405; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZM, SpruceStairs::Half::Top, SpruceStairs::Shape::InnerLeft).ID: return 5407; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZM, SpruceStairs::Half::Top, SpruceStairs::Shape::InnerRight).ID: return 5409; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZM, SpruceStairs::Half::Top, SpruceStairs::Shape::OuterLeft).ID: return 5411; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZM, SpruceStairs::Half::Top, SpruceStairs::Shape::OuterRight).ID: return 5413; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZM, SpruceStairs::Half::Bottom, SpruceStairs::Shape::Straight).ID: return 5415; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZM, SpruceStairs::Half::Bottom, SpruceStairs::Shape::InnerLeft).ID: return 5417; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZM, SpruceStairs::Half::Bottom, SpruceStairs::Shape::InnerRight).ID: return 5419; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZM, SpruceStairs::Half::Bottom, SpruceStairs::Shape::OuterLeft).ID: return 5421; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZM, SpruceStairs::Half::Bottom, SpruceStairs::Shape::OuterRight).ID: return 5423; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZP, SpruceStairs::Half::Top, SpruceStairs::Shape::Straight).ID: return 5425; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZP, SpruceStairs::Half::Top, SpruceStairs::Shape::InnerLeft).ID: return 5427; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZP, SpruceStairs::Half::Top, SpruceStairs::Shape::InnerRight).ID: return 5429; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZP, SpruceStairs::Half::Top, SpruceStairs::Shape::OuterLeft).ID: return 5431; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZP, SpruceStairs::Half::Top, SpruceStairs::Shape::OuterRight).ID: return 5433; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZP, SpruceStairs::Half::Bottom, SpruceStairs::Shape::Straight).ID: return 5435; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZP, SpruceStairs::Half::Bottom, SpruceStairs::Shape::InnerLeft).ID: return 5437; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZP, SpruceStairs::Half::Bottom, SpruceStairs::Shape::InnerRight).ID: return 5439; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZP, SpruceStairs::Half::Bottom, SpruceStairs::Shape::OuterLeft).ID: return 5441; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZP, SpruceStairs::Half::Bottom, SpruceStairs::Shape::OuterRight).ID: return 5443; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XM, SpruceStairs::Half::Top, SpruceStairs::Shape::Straight).ID: return 5445; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XM, SpruceStairs::Half::Top, SpruceStairs::Shape::InnerLeft).ID: return 5447; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XM, SpruceStairs::Half::Top, SpruceStairs::Shape::InnerRight).ID: return 5449; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XM, SpruceStairs::Half::Top, SpruceStairs::Shape::OuterLeft).ID: return 5451; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XM, SpruceStairs::Half::Top, SpruceStairs::Shape::OuterRight).ID: return 5453; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XM, SpruceStairs::Half::Bottom, SpruceStairs::Shape::Straight).ID: return 5455; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XM, SpruceStairs::Half::Bottom, SpruceStairs::Shape::InnerLeft).ID: return 5457; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XM, SpruceStairs::Half::Bottom, SpruceStairs::Shape::InnerRight).ID: return 5459; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XM, SpruceStairs::Half::Bottom, SpruceStairs::Shape::OuterLeft).ID: return 5461; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XM, SpruceStairs::Half::Bottom, SpruceStairs::Shape::OuterRight).ID: return 5463; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XP, SpruceStairs::Half::Top, SpruceStairs::Shape::Straight).ID: return 5465; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XP, SpruceStairs::Half::Top, SpruceStairs::Shape::InnerLeft).ID: return 5467; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XP, SpruceStairs::Half::Top, SpruceStairs::Shape::InnerRight).ID: return 5469; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XP, SpruceStairs::Half::Top, SpruceStairs::Shape::OuterLeft).ID: return 5471; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XP, SpruceStairs::Half::Top, SpruceStairs::Shape::OuterRight).ID: return 5473; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XP, SpruceStairs::Half::Bottom, SpruceStairs::Shape::Straight).ID: return 5475; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XP, SpruceStairs::Half::Bottom, SpruceStairs::Shape::InnerLeft).ID: return 5477; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XP, SpruceStairs::Half::Bottom, SpruceStairs::Shape::InnerRight).ID: return 5479; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XP, SpruceStairs::Half::Bottom, SpruceStairs::Shape::OuterLeft).ID: return 5481; case SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XP, SpruceStairs::Half::Bottom, SpruceStairs::Shape::OuterRight).ID: return 5483; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZM, SpruceTrapdoor::Half::Top, true, true).ID: return 4176; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZM, SpruceTrapdoor::Half::Top, true, false).ID: return 4178; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZM, SpruceTrapdoor::Half::Top, false, true).ID: return 4180; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZM, SpruceTrapdoor::Half::Top, false, false).ID: return 4182; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZM, SpruceTrapdoor::Half::Bottom, true, true).ID: return 4184; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZM, SpruceTrapdoor::Half::Bottom, true, false).ID: return 4186; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZM, SpruceTrapdoor::Half::Bottom, false, true).ID: return 4188; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZM, SpruceTrapdoor::Half::Bottom, false, false).ID: return 4190; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZP, SpruceTrapdoor::Half::Top, true, true).ID: return 4192; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZP, SpruceTrapdoor::Half::Top, true, false).ID: return 4194; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZP, SpruceTrapdoor::Half::Top, false, true).ID: return 4196; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZP, SpruceTrapdoor::Half::Top, false, false).ID: return 4198; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZP, SpruceTrapdoor::Half::Bottom, true, true).ID: return 4200; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZP, SpruceTrapdoor::Half::Bottom, true, false).ID: return 4202; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZP, SpruceTrapdoor::Half::Bottom, false, true).ID: return 4204; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_ZP, SpruceTrapdoor::Half::Bottom, false, false).ID: return 4206; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XM, SpruceTrapdoor::Half::Top, true, true).ID: return 4208; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XM, SpruceTrapdoor::Half::Top, true, false).ID: return 4210; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XM, SpruceTrapdoor::Half::Top, false, true).ID: return 4212; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XM, SpruceTrapdoor::Half::Top, false, false).ID: return 4214; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XM, SpruceTrapdoor::Half::Bottom, true, true).ID: return 4216; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XM, SpruceTrapdoor::Half::Bottom, true, false).ID: return 4218; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XM, SpruceTrapdoor::Half::Bottom, false, true).ID: return 4220; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XM, SpruceTrapdoor::Half::Bottom, false, false).ID: return 4222; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XP, SpruceTrapdoor::Half::Top, true, true).ID: return 4224; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XP, SpruceTrapdoor::Half::Top, true, false).ID: return 4226; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XP, SpruceTrapdoor::Half::Top, false, true).ID: return 4228; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XP, SpruceTrapdoor::Half::Top, false, false).ID: return 4230; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XP, SpruceTrapdoor::Half::Bottom, true, true).ID: return 4232; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XP, SpruceTrapdoor::Half::Bottom, true, false).ID: return 4234; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XP, SpruceTrapdoor::Half::Bottom, false, true).ID: return 4236; case SpruceTrapdoor::SpruceTrapdoor(eBlockFace::BLOCK_FACE_XP, SpruceTrapdoor::Half::Bottom, false, false).ID: return 4238; case SpruceWallSign::SpruceWallSign(eBlockFace::BLOCK_FACE_ZM).ID: return 3744; case SpruceWallSign::SpruceWallSign(eBlockFace::BLOCK_FACE_ZP).ID: return 3746; case SpruceWallSign::SpruceWallSign(eBlockFace::BLOCK_FACE_XM).ID: return 3748; case SpruceWallSign::SpruceWallSign(eBlockFace::BLOCK_FACE_XP).ID: return 3750; case SpruceWood::SpruceWood(SpruceWood::Axis::X).ID: return 112; case SpruceWood::SpruceWood(SpruceWood::Axis::Y).ID: return 113; case SpruceWood::SpruceWood(SpruceWood::Axis::Z).ID: return 114; case StickyPiston::StickyPiston(true, eBlockFace::BLOCK_FACE_ZM).ID: return 1329; case StickyPiston::StickyPiston(true, eBlockFace::BLOCK_FACE_XP).ID: return 1330; case StickyPiston::StickyPiston(true, eBlockFace::BLOCK_FACE_ZP).ID: return 1331; case StickyPiston::StickyPiston(true, eBlockFace::BLOCK_FACE_XM).ID: return 1332; case StickyPiston::StickyPiston(true, eBlockFace::BLOCK_FACE_YP).ID: return 1333; case StickyPiston::StickyPiston(true, eBlockFace::BLOCK_FACE_YM).ID: return 1334; case StickyPiston::StickyPiston(false, eBlockFace::BLOCK_FACE_ZM).ID: return 1335; case StickyPiston::StickyPiston(false, eBlockFace::BLOCK_FACE_XP).ID: return 1336; case StickyPiston::StickyPiston(false, eBlockFace::BLOCK_FACE_ZP).ID: return 1337; case StickyPiston::StickyPiston(false, eBlockFace::BLOCK_FACE_XM).ID: return 1338; case StickyPiston::StickyPiston(false, eBlockFace::BLOCK_FACE_YP).ID: return 1339; case StickyPiston::StickyPiston(false, eBlockFace::BLOCK_FACE_YM).ID: return 1340; case Stone::Stone().ID: return 1; case StoneBrickSlab::StoneBrickSlab(StoneBrickSlab::Type::Top).ID: return 8379; case StoneBrickSlab::StoneBrickSlab(StoneBrickSlab::Type::Bottom).ID: return 8381; case StoneBrickSlab::StoneBrickSlab(StoneBrickSlab::Type::Double).ID: return 8383; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::Straight).ID: return 4933; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::InnerLeft).ID: return 4935; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::InnerRight).ID: return 4937; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::OuterLeft).ID: return 4939; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::OuterRight).ID: return 4941; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::Straight).ID: return 4943; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::InnerLeft).ID: return 4945; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::InnerRight).ID: return 4947; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::OuterLeft).ID: return 4949; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::OuterRight).ID: return 4951; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::Straight).ID: return 4953; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::InnerLeft).ID: return 4955; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::InnerRight).ID: return 4957; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::OuterLeft).ID: return 4959; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::OuterRight).ID: return 4961; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::Straight).ID: return 4963; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::InnerLeft).ID: return 4965; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::InnerRight).ID: return 4967; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::OuterLeft).ID: return 4969; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::OuterRight).ID: return 4971; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XM, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::Straight).ID: return 4973; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XM, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::InnerLeft).ID: return 4975; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XM, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::InnerRight).ID: return 4977; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XM, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::OuterLeft).ID: return 4979; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XM, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::OuterRight).ID: return 4981; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XM, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::Straight).ID: return 4983; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XM, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::InnerLeft).ID: return 4985; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XM, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::InnerRight).ID: return 4987; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XM, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::OuterLeft).ID: return 4989; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XM, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::OuterRight).ID: return 4991; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XP, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::Straight).ID: return 4993; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XP, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::InnerLeft).ID: return 4995; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XP, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::InnerRight).ID: return 4997; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XP, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::OuterLeft).ID: return 4999; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XP, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::OuterRight).ID: return 5001; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XP, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::Straight).ID: return 5003; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XP, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::InnerLeft).ID: return 5005; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XP, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::InnerRight).ID: return 5007; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XP, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::OuterLeft).ID: return 5009; case StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XP, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::OuterRight).ID: return 5011; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::None, StoneBrickWall::South::None, true, StoneBrickWall::West::None).ID: return 12490; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::None, StoneBrickWall::South::None, true, StoneBrickWall::West::Low).ID: return 12491; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::None, StoneBrickWall::South::None, true, StoneBrickWall::West::Tall).ID: return 12492; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::None, StoneBrickWall::South::None, false, StoneBrickWall::West::None).ID: return 12496; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::None, StoneBrickWall::South::None, false, StoneBrickWall::West::Low).ID: return 12497; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::None, StoneBrickWall::South::None, false, StoneBrickWall::West::Tall).ID: return 12498; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::None, StoneBrickWall::South::Low, true, StoneBrickWall::West::None).ID: return 12502; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::None, StoneBrickWall::South::Low, true, StoneBrickWall::West::Low).ID: return 12503; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::None, StoneBrickWall::South::Low, true, StoneBrickWall::West::Tall).ID: return 12504; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::None, StoneBrickWall::South::Low, false, StoneBrickWall::West::None).ID: return 12508; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::None, StoneBrickWall::South::Low, false, StoneBrickWall::West::Low).ID: return 12509; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::None, StoneBrickWall::South::Low, false, StoneBrickWall::West::Tall).ID: return 12510; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::None, StoneBrickWall::South::Tall, true, StoneBrickWall::West::None).ID: return 12514; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::None, StoneBrickWall::South::Tall, true, StoneBrickWall::West::Low).ID: return 12515; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::None, StoneBrickWall::South::Tall, true, StoneBrickWall::West::Tall).ID: return 12516; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::None, StoneBrickWall::South::Tall, false, StoneBrickWall::West::None).ID: return 12520; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::None, StoneBrickWall::South::Tall, false, StoneBrickWall::West::Low).ID: return 12521; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::None, StoneBrickWall::South::Tall, false, StoneBrickWall::West::Tall).ID: return 12522; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::Low, StoneBrickWall::South::None, true, StoneBrickWall::West::None).ID: return 12526; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::Low, StoneBrickWall::South::None, true, StoneBrickWall::West::Low).ID: return 12527; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::Low, StoneBrickWall::South::None, true, StoneBrickWall::West::Tall).ID: return 12528; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::Low, StoneBrickWall::South::None, false, StoneBrickWall::West::None).ID: return 12532; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::Low, StoneBrickWall::South::None, false, StoneBrickWall::West::Low).ID: return 12533; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::Low, StoneBrickWall::South::None, false, StoneBrickWall::West::Tall).ID: return 12534; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::Low, StoneBrickWall::South::Low, true, StoneBrickWall::West::None).ID: return 12538; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::Low, StoneBrickWall::South::Low, true, StoneBrickWall::West::Low).ID: return 12539; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::Low, StoneBrickWall::South::Low, true, StoneBrickWall::West::Tall).ID: return 12540; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::Low, StoneBrickWall::South::Low, false, StoneBrickWall::West::None).ID: return 12544; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::Low, StoneBrickWall::South::Low, false, StoneBrickWall::West::Low).ID: return 12545; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::Low, StoneBrickWall::South::Low, false, StoneBrickWall::West::Tall).ID: return 12546; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::Low, StoneBrickWall::South::Tall, true, StoneBrickWall::West::None).ID: return 12550; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::Low, StoneBrickWall::South::Tall, true, StoneBrickWall::West::Low).ID: return 12551; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::Low, StoneBrickWall::South::Tall, true, StoneBrickWall::West::Tall).ID: return 12552; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::Low, StoneBrickWall::South::Tall, false, StoneBrickWall::West::None).ID: return 12556; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::Low, StoneBrickWall::South::Tall, false, StoneBrickWall::West::Low).ID: return 12557; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::Low, StoneBrickWall::South::Tall, false, StoneBrickWall::West::Tall).ID: return 12558; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::Tall, StoneBrickWall::South::None, true, StoneBrickWall::West::None).ID: return 12562; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::Tall, StoneBrickWall::South::None, true, StoneBrickWall::West::Low).ID: return 12563; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::Tall, StoneBrickWall::South::None, true, StoneBrickWall::West::Tall).ID: return 12564; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::Tall, StoneBrickWall::South::None, false, StoneBrickWall::West::None).ID: return 12568; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::Tall, StoneBrickWall::South::None, false, StoneBrickWall::West::Low).ID: return 12569; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::Tall, StoneBrickWall::South::None, false, StoneBrickWall::West::Tall).ID: return 12570; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::Tall, StoneBrickWall::South::Low, true, StoneBrickWall::West::None).ID: return 12574; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::Tall, StoneBrickWall::South::Low, true, StoneBrickWall::West::Low).ID: return 12575; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::Tall, StoneBrickWall::South::Low, true, StoneBrickWall::West::Tall).ID: return 12576; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::Tall, StoneBrickWall::South::Low, false, StoneBrickWall::West::None).ID: return 12580; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::Tall, StoneBrickWall::South::Low, false, StoneBrickWall::West::Low).ID: return 12581; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::Tall, StoneBrickWall::South::Low, false, StoneBrickWall::West::Tall).ID: return 12582; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::Tall, StoneBrickWall::South::Tall, true, StoneBrickWall::West::None).ID: return 12586; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::Tall, StoneBrickWall::South::Tall, true, StoneBrickWall::West::Low).ID: return 12587; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::Tall, StoneBrickWall::South::Tall, true, StoneBrickWall::West::Tall).ID: return 12588; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::Tall, StoneBrickWall::South::Tall, false, StoneBrickWall::West::None).ID: return 12592; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::Tall, StoneBrickWall::South::Tall, false, StoneBrickWall::West::Low).ID: return 12593; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::None, StoneBrickWall::North::Tall, StoneBrickWall::South::Tall, false, StoneBrickWall::West::Tall).ID: return 12594; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::None, StoneBrickWall::South::None, true, StoneBrickWall::West::None).ID: return 12598; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::None, StoneBrickWall::South::None, true, StoneBrickWall::West::Low).ID: return 12599; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::None, StoneBrickWall::South::None, true, StoneBrickWall::West::Tall).ID: return 12600; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::None, StoneBrickWall::South::None, false, StoneBrickWall::West::None).ID: return 12604; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::None, StoneBrickWall::South::None, false, StoneBrickWall::West::Low).ID: return 12605; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::None, StoneBrickWall::South::None, false, StoneBrickWall::West::Tall).ID: return 12606; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::None, StoneBrickWall::South::Low, true, StoneBrickWall::West::None).ID: return 12610; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::None, StoneBrickWall::South::Low, true, StoneBrickWall::West::Low).ID: return 12611; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::None, StoneBrickWall::South::Low, true, StoneBrickWall::West::Tall).ID: return 12612; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::None, StoneBrickWall::South::Low, false, StoneBrickWall::West::None).ID: return 12616; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::None, StoneBrickWall::South::Low, false, StoneBrickWall::West::Low).ID: return 12617; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::None, StoneBrickWall::South::Low, false, StoneBrickWall::West::Tall).ID: return 12618; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::None, StoneBrickWall::South::Tall, true, StoneBrickWall::West::None).ID: return 12622; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::None, StoneBrickWall::South::Tall, true, StoneBrickWall::West::Low).ID: return 12623; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::None, StoneBrickWall::South::Tall, true, StoneBrickWall::West::Tall).ID: return 12624; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::None, StoneBrickWall::South::Tall, false, StoneBrickWall::West::None).ID: return 12628; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::None, StoneBrickWall::South::Tall, false, StoneBrickWall::West::Low).ID: return 12629; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::None, StoneBrickWall::South::Tall, false, StoneBrickWall::West::Tall).ID: return 12630; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::Low, StoneBrickWall::South::None, true, StoneBrickWall::West::None).ID: return 12634; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::Low, StoneBrickWall::South::None, true, StoneBrickWall::West::Low).ID: return 12635; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::Low, StoneBrickWall::South::None, true, StoneBrickWall::West::Tall).ID: return 12636; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::Low, StoneBrickWall::South::None, false, StoneBrickWall::West::None).ID: return 12640; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::Low, StoneBrickWall::South::None, false, StoneBrickWall::West::Low).ID: return 12641; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::Low, StoneBrickWall::South::None, false, StoneBrickWall::West::Tall).ID: return 12642; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::Low, StoneBrickWall::South::Low, true, StoneBrickWall::West::None).ID: return 12646; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::Low, StoneBrickWall::South::Low, true, StoneBrickWall::West::Low).ID: return 12647; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::Low, StoneBrickWall::South::Low, true, StoneBrickWall::West::Tall).ID: return 12648; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::Low, StoneBrickWall::South::Low, false, StoneBrickWall::West::None).ID: return 12652; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::Low, StoneBrickWall::South::Low, false, StoneBrickWall::West::Low).ID: return 12653; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::Low, StoneBrickWall::South::Low, false, StoneBrickWall::West::Tall).ID: return 12654; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::Low, StoneBrickWall::South::Tall, true, StoneBrickWall::West::None).ID: return 12658; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::Low, StoneBrickWall::South::Tall, true, StoneBrickWall::West::Low).ID: return 12659; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::Low, StoneBrickWall::South::Tall, true, StoneBrickWall::West::Tall).ID: return 12660; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::Low, StoneBrickWall::South::Tall, false, StoneBrickWall::West::None).ID: return 12664; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::Low, StoneBrickWall::South::Tall, false, StoneBrickWall::West::Low).ID: return 12665; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::Low, StoneBrickWall::South::Tall, false, StoneBrickWall::West::Tall).ID: return 12666; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::Tall, StoneBrickWall::South::None, true, StoneBrickWall::West::None).ID: return 12670; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::Tall, StoneBrickWall::South::None, true, StoneBrickWall::West::Low).ID: return 12671; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::Tall, StoneBrickWall::South::None, true, StoneBrickWall::West::Tall).ID: return 12672; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::Tall, StoneBrickWall::South::None, false, StoneBrickWall::West::None).ID: return 12676; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::Tall, StoneBrickWall::South::None, false, StoneBrickWall::West::Low).ID: return 12677; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::Tall, StoneBrickWall::South::None, false, StoneBrickWall::West::Tall).ID: return 12678; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::Tall, StoneBrickWall::South::Low, true, StoneBrickWall::West::None).ID: return 12682; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::Tall, StoneBrickWall::South::Low, true, StoneBrickWall::West::Low).ID: return 12683; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::Tall, StoneBrickWall::South::Low, true, StoneBrickWall::West::Tall).ID: return 12684; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::Tall, StoneBrickWall::South::Low, false, StoneBrickWall::West::None).ID: return 12688; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::Tall, StoneBrickWall::South::Low, false, StoneBrickWall::West::Low).ID: return 12689; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::Tall, StoneBrickWall::South::Low, false, StoneBrickWall::West::Tall).ID: return 12690; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::Tall, StoneBrickWall::South::Tall, true, StoneBrickWall::West::None).ID: return 12694; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::Tall, StoneBrickWall::South::Tall, true, StoneBrickWall::West::Low).ID: return 12695; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::Tall, StoneBrickWall::South::Tall, true, StoneBrickWall::West::Tall).ID: return 12696; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::Tall, StoneBrickWall::South::Tall, false, StoneBrickWall::West::None).ID: return 12700; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::Tall, StoneBrickWall::South::Tall, false, StoneBrickWall::West::Low).ID: return 12701; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Low, StoneBrickWall::North::Tall, StoneBrickWall::South::Tall, false, StoneBrickWall::West::Tall).ID: return 12702; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Tall, StoneBrickWall::North::None, StoneBrickWall::South::None, true, StoneBrickWall::West::None).ID: return 12706; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Tall, StoneBrickWall::North::None, StoneBrickWall::South::None, true, StoneBrickWall::West::Low).ID: return 12707; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Tall, StoneBrickWall::North::None, StoneBrickWall::South::None, true, StoneBrickWall::West::Tall).ID: return 12708; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Tall, StoneBrickWall::North::None, StoneBrickWall::South::None, false, StoneBrickWall::West::None).ID: return 12712; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Tall, StoneBrickWall::North::None, StoneBrickWall::South::None, false, StoneBrickWall::West::Low).ID: return 12713; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Tall, StoneBrickWall::North::None, StoneBrickWall::South::None, false, StoneBrickWall::West::Tall).ID: return 12714; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Tall, StoneBrickWall::North::None, StoneBrickWall::South::Low, true, StoneBrickWall::West::None).ID: return 12718; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Tall, StoneBrickWall::North::None, StoneBrickWall::South::Low, true, StoneBrickWall::West::Low).ID: return 12719; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Tall, StoneBrickWall::North::None, StoneBrickWall::South::Low, true, StoneBrickWall::West::Tall).ID: return 12720; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Tall, StoneBrickWall::North::None, StoneBrickWall::South::Low, false, StoneBrickWall::West::None).ID: return 12724; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Tall, StoneBrickWall::North::None, StoneBrickWall::South::Low, false, StoneBrickWall::West::Low).ID: return 12725; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Tall, StoneBrickWall::North::None, StoneBrickWall::South::Low, false, StoneBrickWall::West::Tall).ID: return 12726; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Tall, StoneBrickWall::North::None, StoneBrickWall::South::Tall, true, StoneBrickWall::West::None).ID: return 12730; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Tall, StoneBrickWall::North::None, StoneBrickWall::South::Tall, true, StoneBrickWall::West::Low).ID: return 12731; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Tall, StoneBrickWall::North::None, StoneBrickWall::South::Tall, true, StoneBrickWall::West::Tall).ID: return 12732; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Tall, StoneBrickWall::North::None, StoneBrickWall::South::Tall, false, StoneBrickWall::West::None).ID: return 12736; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Tall, StoneBrickWall::North::None, StoneBrickWall::South::Tall, false, StoneBrickWall::West::Low).ID: return 12737; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Tall, StoneBrickWall::North::None, StoneBrickWall::South::Tall, false, StoneBrickWall::West::Tall).ID: return 12738; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Tall, StoneBrickWall::North::Low, StoneBrickWall::South::None, true, StoneBrickWall::West::None).ID: return 12742; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Tall, StoneBrickWall::North::Low, StoneBrickWall::South::None, true, StoneBrickWall::West::Low).ID: return 12743; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Tall, StoneBrickWall::North::Low, StoneBrickWall::South::None, true, StoneBrickWall::West::Tall).ID: return 12744; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Tall, StoneBrickWall::North::Low, StoneBrickWall::South::None, false, StoneBrickWall::West::None).ID: return 12748; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Tall, StoneBrickWall::North::Low, StoneBrickWall::South::None, false, StoneBrickWall::West::Low).ID: return 12749; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Tall, StoneBrickWall::North::Low, StoneBrickWall::South::None, false, StoneBrickWall::West::Tall).ID: return 12750; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Tall, StoneBrickWall::North::Low, StoneBrickWall::South::Low, true, StoneBrickWall::West::None).ID: return 12754; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Tall, StoneBrickWall::North::Low, StoneBrickWall::South::Low, true, StoneBrickWall::West::Low).ID: return 12755; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Tall, StoneBrickWall::North::Low, StoneBrickWall::South::Low, true, StoneBrickWall::West::Tall).ID: return 12756; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Tall, StoneBrickWall::North::Low, StoneBrickWall::South::Low, false, StoneBrickWall::West::None).ID: return 12760; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Tall, StoneBrickWall::North::Low, StoneBrickWall::South::Low, false, StoneBrickWall::West::Low).ID: return 12761; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Tall, StoneBrickWall::North::Low, StoneBrickWall::South::Low, false, StoneBrickWall::West::Tall).ID: return 12762; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Tall, StoneBrickWall::North::Low, StoneBrickWall::South::Tall, true, StoneBrickWall::West::None).ID: return 12766; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Tall, StoneBrickWall::North::Low, StoneBrickWall::South::Tall, true, StoneBrickWall::West::Low).ID: return 12767; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Tall, StoneBrickWall::North::Low, StoneBrickWall::South::Tall, true, StoneBrickWall::West::Tall).ID: return 12768; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Tall, StoneBrickWall::North::Low, StoneBrickWall::South::Tall, false, StoneBrickWall::West::None).ID: return 12772; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Tall, StoneBrickWall::North::Low, StoneBrickWall::South::Tall, false, StoneBrickWall::West::Low).ID: return 12773; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Tall, StoneBrickWall::North::Low, StoneBrickWall::South::Tall, false, StoneBrickWall::West::Tall).ID: return 12774; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Tall, StoneBrickWall::North::Tall, StoneBrickWall::South::None, true, StoneBrickWall::West::None).ID: return 12778; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Tall, StoneBrickWall::North::Tall, StoneBrickWall::South::None, true, StoneBrickWall::West::Low).ID: return 12779; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Tall, StoneBrickWall::North::Tall, StoneBrickWall::South::None, true, StoneBrickWall::West::Tall).ID: return 12780; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Tall, StoneBrickWall::North::Tall, StoneBrickWall::South::None, false, StoneBrickWall::West::None).ID: return 12784; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Tall, StoneBrickWall::North::Tall, StoneBrickWall::South::None, false, StoneBrickWall::West::Low).ID: return 12785; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Tall, StoneBrickWall::North::Tall, StoneBrickWall::South::None, false, StoneBrickWall::West::Tall).ID: return 12786; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Tall, StoneBrickWall::North::Tall, StoneBrickWall::South::Low, true, StoneBrickWall::West::None).ID: return 12790; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Tall, StoneBrickWall::North::Tall, StoneBrickWall::South::Low, true, StoneBrickWall::West::Low).ID: return 12791; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Tall, StoneBrickWall::North::Tall, StoneBrickWall::South::Low, true, StoneBrickWall::West::Tall).ID: return 12792; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Tall, StoneBrickWall::North::Tall, StoneBrickWall::South::Low, false, StoneBrickWall::West::None).ID: return 12796; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Tall, StoneBrickWall::North::Tall, StoneBrickWall::South::Low, false, StoneBrickWall::West::Low).ID: return 12797; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Tall, StoneBrickWall::North::Tall, StoneBrickWall::South::Low, false, StoneBrickWall::West::Tall).ID: return 12798; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Tall, StoneBrickWall::North::Tall, StoneBrickWall::South::Tall, true, StoneBrickWall::West::None).ID: return 12802; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Tall, StoneBrickWall::North::Tall, StoneBrickWall::South::Tall, true, StoneBrickWall::West::Low).ID: return 12803; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Tall, StoneBrickWall::North::Tall, StoneBrickWall::South::Tall, true, StoneBrickWall::West::Tall).ID: return 12804; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Tall, StoneBrickWall::North::Tall, StoneBrickWall::South::Tall, false, StoneBrickWall::West::None).ID: return 12808; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Tall, StoneBrickWall::North::Tall, StoneBrickWall::South::Tall, false, StoneBrickWall::West::Low).ID: return 12809; case StoneBrickWall::StoneBrickWall(StoneBrickWall::East::Tall, StoneBrickWall::North::Tall, StoneBrickWall::South::Tall, false, StoneBrickWall::West::Tall).ID: return 12810; case StoneBricks::StoneBricks().ID: return 4495; case StoneButton::StoneButton(StoneButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, true).ID: return 3897; case StoneButton::StoneButton(StoneButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, false).ID: return 3898; case StoneButton::StoneButton(StoneButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, true).ID: return 3899; case StoneButton::StoneButton(StoneButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, false).ID: return 3900; case StoneButton::StoneButton(StoneButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, true).ID: return 3901; case StoneButton::StoneButton(StoneButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, false).ID: return 3902; case StoneButton::StoneButton(StoneButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, true).ID: return 3903; case StoneButton::StoneButton(StoneButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, false).ID: return 3904; case StoneButton::StoneButton(StoneButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, true).ID: return 3905; case StoneButton::StoneButton(StoneButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, false).ID: return 3906; case StoneButton::StoneButton(StoneButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, true).ID: return 3907; case StoneButton::StoneButton(StoneButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, false).ID: return 3908; case StoneButton::StoneButton(StoneButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, true).ID: return 3909; case StoneButton::StoneButton(StoneButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, false).ID: return 3910; case StoneButton::StoneButton(StoneButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, true).ID: return 3911; case StoneButton::StoneButton(StoneButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, false).ID: return 3912; case StoneButton::StoneButton(StoneButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, true).ID: return 3913; case StoneButton::StoneButton(StoneButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, false).ID: return 3914; case StoneButton::StoneButton(StoneButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, true).ID: return 3915; case StoneButton::StoneButton(StoneButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, false).ID: return 3916; case StoneButton::StoneButton(StoneButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, true).ID: return 3917; case StoneButton::StoneButton(StoneButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, false).ID: return 3918; case StoneButton::StoneButton(StoneButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, true).ID: return 3919; case StoneButton::StoneButton(StoneButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, false).ID: return 3920; case StonePressurePlate::StonePressurePlate(true).ID: return 3807; case StonePressurePlate::StonePressurePlate(false).ID: return 3808; case StoneSlab::StoneSlab(StoneSlab::Type::Top).ID: return 8337; case StoneSlab::StoneSlab(StoneSlab::Type::Bottom).ID: return 8339; case StoneSlab::StoneSlab(StoneSlab::Type::Double).ID: return 8341; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_ZM, StoneStairs::Half::Top, StoneStairs::Shape::Straight).ID: return 10150; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_ZM, StoneStairs::Half::Top, StoneStairs::Shape::InnerLeft).ID: return 10152; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_ZM, StoneStairs::Half::Top, StoneStairs::Shape::InnerRight).ID: return 10154; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_ZM, StoneStairs::Half::Top, StoneStairs::Shape::OuterLeft).ID: return 10156; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_ZM, StoneStairs::Half::Top, StoneStairs::Shape::OuterRight).ID: return 10158; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_ZM, StoneStairs::Half::Bottom, StoneStairs::Shape::Straight).ID: return 10160; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_ZM, StoneStairs::Half::Bottom, StoneStairs::Shape::InnerLeft).ID: return 10162; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_ZM, StoneStairs::Half::Bottom, StoneStairs::Shape::InnerRight).ID: return 10164; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_ZM, StoneStairs::Half::Bottom, StoneStairs::Shape::OuterLeft).ID: return 10166; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_ZM, StoneStairs::Half::Bottom, StoneStairs::Shape::OuterRight).ID: return 10168; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_ZP, StoneStairs::Half::Top, StoneStairs::Shape::Straight).ID: return 10170; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_ZP, StoneStairs::Half::Top, StoneStairs::Shape::InnerLeft).ID: return 10172; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_ZP, StoneStairs::Half::Top, StoneStairs::Shape::InnerRight).ID: return 10174; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_ZP, StoneStairs::Half::Top, StoneStairs::Shape::OuterLeft).ID: return 10176; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_ZP, StoneStairs::Half::Top, StoneStairs::Shape::OuterRight).ID: return 10178; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_ZP, StoneStairs::Half::Bottom, StoneStairs::Shape::Straight).ID: return 10180; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_ZP, StoneStairs::Half::Bottom, StoneStairs::Shape::InnerLeft).ID: return 10182; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_ZP, StoneStairs::Half::Bottom, StoneStairs::Shape::InnerRight).ID: return 10184; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_ZP, StoneStairs::Half::Bottom, StoneStairs::Shape::OuterLeft).ID: return 10186; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_ZP, StoneStairs::Half::Bottom, StoneStairs::Shape::OuterRight).ID: return 10188; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_XM, StoneStairs::Half::Top, StoneStairs::Shape::Straight).ID: return 10190; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_XM, StoneStairs::Half::Top, StoneStairs::Shape::InnerLeft).ID: return 10192; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_XM, StoneStairs::Half::Top, StoneStairs::Shape::InnerRight).ID: return 10194; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_XM, StoneStairs::Half::Top, StoneStairs::Shape::OuterLeft).ID: return 10196; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_XM, StoneStairs::Half::Top, StoneStairs::Shape::OuterRight).ID: return 10198; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_XM, StoneStairs::Half::Bottom, StoneStairs::Shape::Straight).ID: return 10200; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_XM, StoneStairs::Half::Bottom, StoneStairs::Shape::InnerLeft).ID: return 10202; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_XM, StoneStairs::Half::Bottom, StoneStairs::Shape::InnerRight).ID: return 10204; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_XM, StoneStairs::Half::Bottom, StoneStairs::Shape::OuterLeft).ID: return 10206; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_XM, StoneStairs::Half::Bottom, StoneStairs::Shape::OuterRight).ID: return 10208; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_XP, StoneStairs::Half::Top, StoneStairs::Shape::Straight).ID: return 10210; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_XP, StoneStairs::Half::Top, StoneStairs::Shape::InnerLeft).ID: return 10212; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_XP, StoneStairs::Half::Top, StoneStairs::Shape::InnerRight).ID: return 10214; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_XP, StoneStairs::Half::Top, StoneStairs::Shape::OuterLeft).ID: return 10216; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_XP, StoneStairs::Half::Top, StoneStairs::Shape::OuterRight).ID: return 10218; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_XP, StoneStairs::Half::Bottom, StoneStairs::Shape::Straight).ID: return 10220; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_XP, StoneStairs::Half::Bottom, StoneStairs::Shape::InnerLeft).ID: return 10222; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_XP, StoneStairs::Half::Bottom, StoneStairs::Shape::InnerRight).ID: return 10224; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_XP, StoneStairs::Half::Bottom, StoneStairs::Shape::OuterLeft).ID: return 10226; case StoneStairs::StoneStairs(eBlockFace::BLOCK_FACE_XP, StoneStairs::Half::Bottom, StoneStairs::Shape::OuterRight).ID: return 10228; case Stonecutter::Stonecutter(eBlockFace::BLOCK_FACE_ZM).ID: return 14850; case Stonecutter::Stonecutter(eBlockFace::BLOCK_FACE_ZP).ID: return 14851; case Stonecutter::Stonecutter(eBlockFace::BLOCK_FACE_XM).ID: return 14852; case Stonecutter::Stonecutter(eBlockFace::BLOCK_FACE_XP).ID: return 14853; case StrippedAcaciaLog::StrippedAcaciaLog(StrippedAcaciaLog::Axis::X).ID: return 100; case StrippedAcaciaLog::StrippedAcaciaLog(StrippedAcaciaLog::Axis::Y).ID: return 101; case StrippedAcaciaLog::StrippedAcaciaLog(StrippedAcaciaLog::Axis::Z).ID: return 102; case StrippedAcaciaWood::StrippedAcaciaWood(StrippedAcaciaWood::Axis::X).ID: return 139; case StrippedAcaciaWood::StrippedAcaciaWood(StrippedAcaciaWood::Axis::Y).ID: return 140; case StrippedAcaciaWood::StrippedAcaciaWood(StrippedAcaciaWood::Axis::Z).ID: return 141; case StrippedBirchLog::StrippedBirchLog(StrippedBirchLog::Axis::X).ID: return 94; case StrippedBirchLog::StrippedBirchLog(StrippedBirchLog::Axis::Y).ID: return 95; case StrippedBirchLog::StrippedBirchLog(StrippedBirchLog::Axis::Z).ID: return 96; case StrippedBirchWood::StrippedBirchWood(StrippedBirchWood::Axis::X).ID: return 133; case StrippedBirchWood::StrippedBirchWood(StrippedBirchWood::Axis::Y).ID: return 134; case StrippedBirchWood::StrippedBirchWood(StrippedBirchWood::Axis::Z).ID: return 135; case StrippedCrimsonHyphae::StrippedCrimsonHyphae(StrippedCrimsonHyphae::Axis::X).ID: return 14984; case StrippedCrimsonHyphae::StrippedCrimsonHyphae(StrippedCrimsonHyphae::Axis::Y).ID: return 14985; case StrippedCrimsonHyphae::StrippedCrimsonHyphae(StrippedCrimsonHyphae::Axis::Z).ID: return 14986; case StrippedCrimsonStem::StrippedCrimsonStem(StrippedCrimsonStem::Axis::X).ID: return 14978; case StrippedCrimsonStem::StrippedCrimsonStem(StrippedCrimsonStem::Axis::Y).ID: return 14979; case StrippedCrimsonStem::StrippedCrimsonStem(StrippedCrimsonStem::Axis::Z).ID: return 14980; case StrippedDarkOakLog::StrippedDarkOakLog(StrippedDarkOakLog::Axis::X).ID: return 103; case StrippedDarkOakLog::StrippedDarkOakLog(StrippedDarkOakLog::Axis::Y).ID: return 104; case StrippedDarkOakLog::StrippedDarkOakLog(StrippedDarkOakLog::Axis::Z).ID: return 105; case StrippedDarkOakWood::StrippedDarkOakWood(StrippedDarkOakWood::Axis::X).ID: return 142; case StrippedDarkOakWood::StrippedDarkOakWood(StrippedDarkOakWood::Axis::Y).ID: return 143; case StrippedDarkOakWood::StrippedDarkOakWood(StrippedDarkOakWood::Axis::Z).ID: return 144; case StrippedJungleLog::StrippedJungleLog(StrippedJungleLog::Axis::X).ID: return 97; case StrippedJungleLog::StrippedJungleLog(StrippedJungleLog::Axis::Y).ID: return 98; case StrippedJungleLog::StrippedJungleLog(StrippedJungleLog::Axis::Z).ID: return 99; case StrippedJungleWood::StrippedJungleWood(StrippedJungleWood::Axis::X).ID: return 136; case StrippedJungleWood::StrippedJungleWood(StrippedJungleWood::Axis::Y).ID: return 137; case StrippedJungleWood::StrippedJungleWood(StrippedJungleWood::Axis::Z).ID: return 138; case StrippedOakLog::StrippedOakLog(StrippedOakLog::Axis::X).ID: return 106; case StrippedOakLog::StrippedOakLog(StrippedOakLog::Axis::Y).ID: return 107; case StrippedOakLog::StrippedOakLog(StrippedOakLog::Axis::Z).ID: return 108; case StrippedOakWood::StrippedOakWood(StrippedOakWood::Axis::X).ID: return 127; case StrippedOakWood::StrippedOakWood(StrippedOakWood::Axis::Y).ID: return 128; case StrippedOakWood::StrippedOakWood(StrippedOakWood::Axis::Z).ID: return 129; case StrippedSpruceLog::StrippedSpruceLog(StrippedSpruceLog::Axis::X).ID: return 91; case StrippedSpruceLog::StrippedSpruceLog(StrippedSpruceLog::Axis::Y).ID: return 92; case StrippedSpruceLog::StrippedSpruceLog(StrippedSpruceLog::Axis::Z).ID: return 93; case StrippedSpruceWood::StrippedSpruceWood(StrippedSpruceWood::Axis::X).ID: return 130; case StrippedSpruceWood::StrippedSpruceWood(StrippedSpruceWood::Axis::Y).ID: return 131; case StrippedSpruceWood::StrippedSpruceWood(StrippedSpruceWood::Axis::Z).ID: return 132; case StrippedWarpedHyphae::StrippedWarpedHyphae(StrippedWarpedHyphae::Axis::X).ID: return 14967; case StrippedWarpedHyphae::StrippedWarpedHyphae(StrippedWarpedHyphae::Axis::Y).ID: return 14968; case StrippedWarpedHyphae::StrippedWarpedHyphae(StrippedWarpedHyphae::Axis::Z).ID: return 14969; case StrippedWarpedStem::StrippedWarpedStem(StrippedWarpedStem::Axis::X).ID: return 14961; case StrippedWarpedStem::StrippedWarpedStem(StrippedWarpedStem::Axis::Y).ID: return 14962; case StrippedWarpedStem::StrippedWarpedStem(StrippedWarpedStem::Axis::Z).ID: return 14963; case StructureBlock::StructureBlock(StructureBlock::Mode::Save).ID: return 15735; case StructureBlock::StructureBlock(StructureBlock::Mode::Load).ID: return 15736; case StructureBlock::StructureBlock(StructureBlock::Mode::Corner).ID: return 15737; case StructureBlock::StructureBlock(StructureBlock::Mode::Data).ID: return 15738; case StructureVoid::StructureVoid().ID: return 9259; case SugarCane::SugarCane(0).ID: return 3948; case SugarCane::SugarCane(1).ID: return 3949; case SugarCane::SugarCane(2).ID: return 3950; case SugarCane::SugarCane(3).ID: return 3951; case SugarCane::SugarCane(4).ID: return 3952; case SugarCane::SugarCane(5).ID: return 3953; case SugarCane::SugarCane(6).ID: return 3954; case SugarCane::SugarCane(7).ID: return 3955; case SugarCane::SugarCane(8).ID: return 3956; case SugarCane::SugarCane(9).ID: return 3957; case SugarCane::SugarCane(10).ID: return 3958; case SugarCane::SugarCane(11).ID: return 3959; case SugarCane::SugarCane(12).ID: return 3960; case SugarCane::SugarCane(13).ID: return 3961; case SugarCane::SugarCane(14).ID: return 3962; case SugarCane::SugarCane(15).ID: return 3963; case Sunflower::Sunflower(Sunflower::Half::Upper).ID: return 7885; case Sunflower::Sunflower(Sunflower::Half::Lower).ID: return 7886; case SweetBerryBush::SweetBerryBush(0).ID: return 14954; case SweetBerryBush::SweetBerryBush(1).ID: return 14955; case SweetBerryBush::SweetBerryBush(2).ID: return 14956; case SweetBerryBush::SweetBerryBush(3).ID: return 14957; case TNT::TNT(true).ID: return 1430; case TNT::TNT(false).ID: return 1431; case TallGrass::TallGrass(TallGrass::Half::Upper).ID: return 7893; case TallGrass::TallGrass(TallGrass::Half::Lower).ID: return 7894; case TallSeagrass::TallSeagrass(TallSeagrass::Half::Upper).ID: return 1346; case TallSeagrass::TallSeagrass(TallSeagrass::Half::Lower).ID: return 1347; case Target::Target(0).ID: return 15760; case Target::Target(1).ID: return 15761; case Target::Target(2).ID: return 15762; case Target::Target(3).ID: return 15763; case Target::Target(4).ID: return 15764; case Target::Target(5).ID: return 15765; case Target::Target(6).ID: return 15766; case Target::Target(7).ID: return 15767; case Target::Target(8).ID: return 15768; case Target::Target(9).ID: return 15769; case Target::Target(10).ID: return 15770; case Target::Target(11).ID: return 15771; case Target::Target(12).ID: return 15772; case Target::Target(13).ID: return 15773; case Target::Target(14).ID: return 15774; case Target::Target(15).ID: return 15775; case Terracotta::Terracotta().ID: return 7882; case Torch::Torch().ID: return 1435; case TrappedChest::TrappedChest(eBlockFace::BLOCK_FACE_ZM, TrappedChest::Type::Single).ID: return 6623; case TrappedChest::TrappedChest(eBlockFace::BLOCK_FACE_ZM, TrappedChest::Type::Left).ID: return 6625; case TrappedChest::TrappedChest(eBlockFace::BLOCK_FACE_ZM, TrappedChest::Type::Right).ID: return 6627; case TrappedChest::TrappedChest(eBlockFace::BLOCK_FACE_ZP, TrappedChest::Type::Single).ID: return 6629; case TrappedChest::TrappedChest(eBlockFace::BLOCK_FACE_ZP, TrappedChest::Type::Left).ID: return 6631; case TrappedChest::TrappedChest(eBlockFace::BLOCK_FACE_ZP, TrappedChest::Type::Right).ID: return 6633; case TrappedChest::TrappedChest(eBlockFace::BLOCK_FACE_XM, TrappedChest::Type::Single).ID: return 6635; case TrappedChest::TrappedChest(eBlockFace::BLOCK_FACE_XM, TrappedChest::Type::Left).ID: return 6637; case TrappedChest::TrappedChest(eBlockFace::BLOCK_FACE_XM, TrappedChest::Type::Right).ID: return 6639; case TrappedChest::TrappedChest(eBlockFace::BLOCK_FACE_XP, TrappedChest::Type::Single).ID: return 6641; case TrappedChest::TrappedChest(eBlockFace::BLOCK_FACE_XP, TrappedChest::Type::Left).ID: return 6643; case TrappedChest::TrappedChest(eBlockFace::BLOCK_FACE_XP, TrappedChest::Type::Right).ID: return 6645; case Tripwire::Tripwire(true, true, true, true, true, true, true).ID: return 5275; case Tripwire::Tripwire(true, true, true, true, true, true, false).ID: return 5276; case Tripwire::Tripwire(true, true, true, true, true, false, true).ID: return 5277; case Tripwire::Tripwire(true, true, true, true, true, false, false).ID: return 5278; case Tripwire::Tripwire(true, true, true, true, false, true, true).ID: return 5279; case Tripwire::Tripwire(true, true, true, true, false, true, false).ID: return 5280; case Tripwire::Tripwire(true, true, true, true, false, false, true).ID: return 5281; case Tripwire::Tripwire(true, true, true, true, false, false, false).ID: return 5282; case Tripwire::Tripwire(true, true, true, false, true, true, true).ID: return 5283; case Tripwire::Tripwire(true, true, true, false, true, true, false).ID: return 5284; case Tripwire::Tripwire(true, true, true, false, true, false, true).ID: return 5285; case Tripwire::Tripwire(true, true, true, false, true, false, false).ID: return 5286; case Tripwire::Tripwire(true, true, true, false, false, true, true).ID: return 5287; case Tripwire::Tripwire(true, true, true, false, false, true, false).ID: return 5288; case Tripwire::Tripwire(true, true, true, false, false, false, true).ID: return 5289; case Tripwire::Tripwire(true, true, true, false, false, false, false).ID: return 5290; case Tripwire::Tripwire(true, true, false, true, true, true, true).ID: return 5291; case Tripwire::Tripwire(true, true, false, true, true, true, false).ID: return 5292; case Tripwire::Tripwire(true, true, false, true, true, false, true).ID: return 5293; case Tripwire::Tripwire(true, true, false, true, true, false, false).ID: return 5294; case Tripwire::Tripwire(true, true, false, true, false, true, true).ID: return 5295; case Tripwire::Tripwire(true, true, false, true, false, true, false).ID: return 5296; case Tripwire::Tripwire(true, true, false, true, false, false, true).ID: return 5297; case Tripwire::Tripwire(true, true, false, true, false, false, false).ID: return 5298; case Tripwire::Tripwire(true, true, false, false, true, true, true).ID: return 5299; case Tripwire::Tripwire(true, true, false, false, true, true, false).ID: return 5300; case Tripwire::Tripwire(true, true, false, false, true, false, true).ID: return 5301; case Tripwire::Tripwire(true, true, false, false, true, false, false).ID: return 5302; case Tripwire::Tripwire(true, true, false, false, false, true, true).ID: return 5303; case Tripwire::Tripwire(true, true, false, false, false, true, false).ID: return 5304; case Tripwire::Tripwire(true, true, false, false, false, false, true).ID: return 5305; case Tripwire::Tripwire(true, true, false, false, false, false, false).ID: return 5306; case Tripwire::Tripwire(true, false, true, true, true, true, true).ID: return 5307; case Tripwire::Tripwire(true, false, true, true, true, true, false).ID: return 5308; case Tripwire::Tripwire(true, false, true, true, true, false, true).ID: return 5309; case Tripwire::Tripwire(true, false, true, true, true, false, false).ID: return 5310; case Tripwire::Tripwire(true, false, true, true, false, true, true).ID: return 5311; case Tripwire::Tripwire(true, false, true, true, false, true, false).ID: return 5312; case Tripwire::Tripwire(true, false, true, true, false, false, true).ID: return 5313; case Tripwire::Tripwire(true, false, true, true, false, false, false).ID: return 5314; case Tripwire::Tripwire(true, false, true, false, true, true, true).ID: return 5315; case Tripwire::Tripwire(true, false, true, false, true, true, false).ID: return 5316; case Tripwire::Tripwire(true, false, true, false, true, false, true).ID: return 5317; case Tripwire::Tripwire(true, false, true, false, true, false, false).ID: return 5318; case Tripwire::Tripwire(true, false, true, false, false, true, true).ID: return 5319; case Tripwire::Tripwire(true, false, true, false, false, true, false).ID: return 5320; case Tripwire::Tripwire(true, false, true, false, false, false, true).ID: return 5321; case Tripwire::Tripwire(true, false, true, false, false, false, false).ID: return 5322; case Tripwire::Tripwire(true, false, false, true, true, true, true).ID: return 5323; case Tripwire::Tripwire(true, false, false, true, true, true, false).ID: return 5324; case Tripwire::Tripwire(true, false, false, true, true, false, true).ID: return 5325; case Tripwire::Tripwire(true, false, false, true, true, false, false).ID: return 5326; case Tripwire::Tripwire(true, false, false, true, false, true, true).ID: return 5327; case Tripwire::Tripwire(true, false, false, true, false, true, false).ID: return 5328; case Tripwire::Tripwire(true, false, false, true, false, false, true).ID: return 5329; case Tripwire::Tripwire(true, false, false, true, false, false, false).ID: return 5330; case Tripwire::Tripwire(true, false, false, false, true, true, true).ID: return 5331; case Tripwire::Tripwire(true, false, false, false, true, true, false).ID: return 5332; case Tripwire::Tripwire(true, false, false, false, true, false, true).ID: return 5333; case Tripwire::Tripwire(true, false, false, false, true, false, false).ID: return 5334; case Tripwire::Tripwire(true, false, false, false, false, true, true).ID: return 5335; case Tripwire::Tripwire(true, false, false, false, false, true, false).ID: return 5336; case Tripwire::Tripwire(true, false, false, false, false, false, true).ID: return 5337; case Tripwire::Tripwire(true, false, false, false, false, false, false).ID: return 5338; case Tripwire::Tripwire(false, true, true, true, true, true, true).ID: return 5339; case Tripwire::Tripwire(false, true, true, true, true, true, false).ID: return 5340; case Tripwire::Tripwire(false, true, true, true, true, false, true).ID: return 5341; case Tripwire::Tripwire(false, true, true, true, true, false, false).ID: return 5342; case Tripwire::Tripwire(false, true, true, true, false, true, true).ID: return 5343; case Tripwire::Tripwire(false, true, true, true, false, true, false).ID: return 5344; case Tripwire::Tripwire(false, true, true, true, false, false, true).ID: return 5345; case Tripwire::Tripwire(false, true, true, true, false, false, false).ID: return 5346; case Tripwire::Tripwire(false, true, true, false, true, true, true).ID: return 5347; case Tripwire::Tripwire(false, true, true, false, true, true, false).ID: return 5348; case Tripwire::Tripwire(false, true, true, false, true, false, true).ID: return 5349; case Tripwire::Tripwire(false, true, true, false, true, false, false).ID: return 5350; case Tripwire::Tripwire(false, true, true, false, false, true, true).ID: return 5351; case Tripwire::Tripwire(false, true, true, false, false, true, false).ID: return 5352; case Tripwire::Tripwire(false, true, true, false, false, false, true).ID: return 5353; case Tripwire::Tripwire(false, true, true, false, false, false, false).ID: return 5354; case Tripwire::Tripwire(false, true, false, true, true, true, true).ID: return 5355; case Tripwire::Tripwire(false, true, false, true, true, true, false).ID: return 5356; case Tripwire::Tripwire(false, true, false, true, true, false, true).ID: return 5357; case Tripwire::Tripwire(false, true, false, true, true, false, false).ID: return 5358; case Tripwire::Tripwire(false, true, false, true, false, true, true).ID: return 5359; case Tripwire::Tripwire(false, true, false, true, false, true, false).ID: return 5360; case Tripwire::Tripwire(false, true, false, true, false, false, true).ID: return 5361; case Tripwire::Tripwire(false, true, false, true, false, false, false).ID: return 5362; case Tripwire::Tripwire(false, true, false, false, true, true, true).ID: return 5363; case Tripwire::Tripwire(false, true, false, false, true, true, false).ID: return 5364; case Tripwire::Tripwire(false, true, false, false, true, false, true).ID: return 5365; case Tripwire::Tripwire(false, true, false, false, true, false, false).ID: return 5366; case Tripwire::Tripwire(false, true, false, false, false, true, true).ID: return 5367; case Tripwire::Tripwire(false, true, false, false, false, true, false).ID: return 5368; case Tripwire::Tripwire(false, true, false, false, false, false, true).ID: return 5369; case Tripwire::Tripwire(false, true, false, false, false, false, false).ID: return 5370; case Tripwire::Tripwire(false, false, true, true, true, true, true).ID: return 5371; case Tripwire::Tripwire(false, false, true, true, true, true, false).ID: return 5372; case Tripwire::Tripwire(false, false, true, true, true, false, true).ID: return 5373; case Tripwire::Tripwire(false, false, true, true, true, false, false).ID: return 5374; case Tripwire::Tripwire(false, false, true, true, false, true, true).ID: return 5375; case Tripwire::Tripwire(false, false, true, true, false, true, false).ID: return 5376; case Tripwire::Tripwire(false, false, true, true, false, false, true).ID: return 5377; case Tripwire::Tripwire(false, false, true, true, false, false, false).ID: return 5378; case Tripwire::Tripwire(false, false, true, false, true, true, true).ID: return 5379; case Tripwire::Tripwire(false, false, true, false, true, true, false).ID: return 5380; case Tripwire::Tripwire(false, false, true, false, true, false, true).ID: return 5381; case Tripwire::Tripwire(false, false, true, false, true, false, false).ID: return 5382; case Tripwire::Tripwire(false, false, true, false, false, true, true).ID: return 5383; case Tripwire::Tripwire(false, false, true, false, false, true, false).ID: return 5384; case Tripwire::Tripwire(false, false, true, false, false, false, true).ID: return 5385; case Tripwire::Tripwire(false, false, true, false, false, false, false).ID: return 5386; case Tripwire::Tripwire(false, false, false, true, true, true, true).ID: return 5387; case Tripwire::Tripwire(false, false, false, true, true, true, false).ID: return 5388; case Tripwire::Tripwire(false, false, false, true, true, false, true).ID: return 5389; case Tripwire::Tripwire(false, false, false, true, true, false, false).ID: return 5390; case Tripwire::Tripwire(false, false, false, true, false, true, true).ID: return 5391; case Tripwire::Tripwire(false, false, false, true, false, true, false).ID: return 5392; case Tripwire::Tripwire(false, false, false, true, false, false, true).ID: return 5393; case Tripwire::Tripwire(false, false, false, true, false, false, false).ID: return 5394; case Tripwire::Tripwire(false, false, false, false, true, true, true).ID: return 5395; case Tripwire::Tripwire(false, false, false, false, true, true, false).ID: return 5396; case Tripwire::Tripwire(false, false, false, false, true, false, true).ID: return 5397; case Tripwire::Tripwire(false, false, false, false, true, false, false).ID: return 5398; case Tripwire::Tripwire(false, false, false, false, false, true, true).ID: return 5399; case Tripwire::Tripwire(false, false, false, false, false, true, false).ID: return 5400; case Tripwire::Tripwire(false, false, false, false, false, false, true).ID: return 5401; case Tripwire::Tripwire(false, false, false, false, false, false, false).ID: return 5402; case TripwireHook::TripwireHook(true, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5259; case TripwireHook::TripwireHook(true, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5260; case TripwireHook::TripwireHook(true, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5261; case TripwireHook::TripwireHook(true, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5262; case TripwireHook::TripwireHook(true, eBlockFace::BLOCK_FACE_XM, true).ID: return 5263; case TripwireHook::TripwireHook(true, eBlockFace::BLOCK_FACE_XM, false).ID: return 5264; case TripwireHook::TripwireHook(true, eBlockFace::BLOCK_FACE_XP, true).ID: return 5265; case TripwireHook::TripwireHook(true, eBlockFace::BLOCK_FACE_XP, false).ID: return 5266; case TripwireHook::TripwireHook(false, eBlockFace::BLOCK_FACE_ZM, true).ID: return 5267; case TripwireHook::TripwireHook(false, eBlockFace::BLOCK_FACE_ZM, false).ID: return 5268; case TripwireHook::TripwireHook(false, eBlockFace::BLOCK_FACE_ZP, true).ID: return 5269; case TripwireHook::TripwireHook(false, eBlockFace::BLOCK_FACE_ZP, false).ID: return 5270; case TripwireHook::TripwireHook(false, eBlockFace::BLOCK_FACE_XM, true).ID: return 5271; case TripwireHook::TripwireHook(false, eBlockFace::BLOCK_FACE_XM, false).ID: return 5272; case TripwireHook::TripwireHook(false, eBlockFace::BLOCK_FACE_XP, true).ID: return 5273; case TripwireHook::TripwireHook(false, eBlockFace::BLOCK_FACE_XP, false).ID: return 5274; case TubeCoral::TubeCoral().ID: return 9531; case TubeCoralBlock::TubeCoralBlock().ID: return 9515; case TubeCoralFan::TubeCoralFan().ID: return 9551; case TubeCoralWallFan::TubeCoralWallFan(eBlockFace::BLOCK_FACE_ZM).ID: return 9601; case TubeCoralWallFan::TubeCoralWallFan(eBlockFace::BLOCK_FACE_ZP).ID: return 9603; case TubeCoralWallFan::TubeCoralWallFan(eBlockFace::BLOCK_FACE_XM).ID: return 9605; case TubeCoralWallFan::TubeCoralWallFan(eBlockFace::BLOCK_FACE_XP).ID: return 9607; case TurtleEgg::TurtleEgg(1, 0).ID: return 9498; case TurtleEgg::TurtleEgg(1, 1).ID: return 9499; case TurtleEgg::TurtleEgg(1, 2).ID: return 9500; case TurtleEgg::TurtleEgg(2, 0).ID: return 9501; case TurtleEgg::TurtleEgg(2, 1).ID: return 9502; case TurtleEgg::TurtleEgg(2, 2).ID: return 9503; case TurtleEgg::TurtleEgg(3, 0).ID: return 9504; case TurtleEgg::TurtleEgg(3, 1).ID: return 9505; case TurtleEgg::TurtleEgg(3, 2).ID: return 9506; case TurtleEgg::TurtleEgg(4, 0).ID: return 9507; case TurtleEgg::TurtleEgg(4, 1).ID: return 9508; case TurtleEgg::TurtleEgg(4, 2).ID: return 9509; case TwistingVines::TwistingVines(0).ID: return 15017; case TwistingVines::TwistingVines(1).ID: return 15018; case TwistingVines::TwistingVines(2).ID: return 15019; case TwistingVines::TwistingVines(3).ID: return 15020; case TwistingVines::TwistingVines(4).ID: return 15021; case TwistingVines::TwistingVines(5).ID: return 15022; case TwistingVines::TwistingVines(6).ID: return 15023; case TwistingVines::TwistingVines(7).ID: return 15024; case TwistingVines::TwistingVines(8).ID: return 15025; case TwistingVines::TwistingVines(9).ID: return 15026; case TwistingVines::TwistingVines(10).ID: return 15027; case TwistingVines::TwistingVines(11).ID: return 15028; case TwistingVines::TwistingVines(12).ID: return 15029; case TwistingVines::TwistingVines(13).ID: return 15030; case TwistingVines::TwistingVines(14).ID: return 15031; case TwistingVines::TwistingVines(15).ID: return 15032; case TwistingVines::TwistingVines(16).ID: return 15033; case TwistingVines::TwistingVines(17).ID: return 15034; case TwistingVines::TwistingVines(18).ID: return 15035; case TwistingVines::TwistingVines(19).ID: return 15036; case TwistingVines::TwistingVines(20).ID: return 15037; case TwistingVines::TwistingVines(21).ID: return 15038; case TwistingVines::TwistingVines(22).ID: return 15039; case TwistingVines::TwistingVines(23).ID: return 15040; case TwistingVines::TwistingVines(24).ID: return 15041; case TwistingVines::TwistingVines(25).ID: return 15042; case TwistingVinesPlant::TwistingVinesPlant().ID: return 15043; case Vine::Vine(true, true, true, true, true).ID: return 4788; case Vine::Vine(true, true, true, true, false).ID: return 4789; case Vine::Vine(true, true, true, false, true).ID: return 4790; case Vine::Vine(true, true, true, false, false).ID: return 4791; case Vine::Vine(true, true, false, true, true).ID: return 4792; case Vine::Vine(true, true, false, true, false).ID: return 4793; case Vine::Vine(true, true, false, false, true).ID: return 4794; case Vine::Vine(true, true, false, false, false).ID: return 4795; case Vine::Vine(true, false, true, true, true).ID: return 4796; case Vine::Vine(true, false, true, true, false).ID: return 4797; case Vine::Vine(true, false, true, false, true).ID: return 4798; case Vine::Vine(true, false, true, false, false).ID: return 4799; case Vine::Vine(true, false, false, true, true).ID: return 4800; case Vine::Vine(true, false, false, true, false).ID: return 4801; case Vine::Vine(true, false, false, false, true).ID: return 4802; case Vine::Vine(true, false, false, false, false).ID: return 4803; case Vine::Vine(false, true, true, true, true).ID: return 4804; case Vine::Vine(false, true, true, true, false).ID: return 4805; case Vine::Vine(false, true, true, false, true).ID: return 4806; case Vine::Vine(false, true, true, false, false).ID: return 4807; case Vine::Vine(false, true, false, true, true).ID: return 4808; case Vine::Vine(false, true, false, true, false).ID: return 4809; case Vine::Vine(false, true, false, false, true).ID: return 4810; case Vine::Vine(false, true, false, false, false).ID: return 4811; case Vine::Vine(false, false, true, true, true).ID: return 4812; case Vine::Vine(false, false, true, true, false).ID: return 4813; case Vine::Vine(false, false, true, false, true).ID: return 4814; case Vine::Vine(false, false, true, false, false).ID: return 4815; case Vine::Vine(false, false, false, true, true).ID: return 4816; case Vine::Vine(false, false, false, true, false).ID: return 4817; case Vine::Vine(false, false, false, false, true).ID: return 4818; case Vine::Vine(false, false, false, false, false).ID: return 4819; case VoidAir::VoidAir().ID: return 9665; case WallTorch::WallTorch(eBlockFace::BLOCK_FACE_ZM).ID: return 1436; case WallTorch::WallTorch(eBlockFace::BLOCK_FACE_ZP).ID: return 1437; case WallTorch::WallTorch(eBlockFace::BLOCK_FACE_XM).ID: return 1438; case WallTorch::WallTorch(eBlockFace::BLOCK_FACE_XP).ID: return 1439; case WarpedButton::WarpedButton(WarpedButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, true).ID: return 15503; case WarpedButton::WarpedButton(WarpedButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, false).ID: return 15504; case WarpedButton::WarpedButton(WarpedButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, true).ID: return 15505; case WarpedButton::WarpedButton(WarpedButton::Face::Floor, eBlockFace::BLOCK_FACE_ZP, false).ID: return 15506; case WarpedButton::WarpedButton(WarpedButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, true).ID: return 15507; case WarpedButton::WarpedButton(WarpedButton::Face::Floor, eBlockFace::BLOCK_FACE_XM, false).ID: return 15508; case WarpedButton::WarpedButton(WarpedButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, true).ID: return 15509; case WarpedButton::WarpedButton(WarpedButton::Face::Floor, eBlockFace::BLOCK_FACE_XP, false).ID: return 15510; case WarpedButton::WarpedButton(WarpedButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, true).ID: return 15511; case WarpedButton::WarpedButton(WarpedButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, false).ID: return 15512; case WarpedButton::WarpedButton(WarpedButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, true).ID: return 15513; case WarpedButton::WarpedButton(WarpedButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, false).ID: return 15514; case WarpedButton::WarpedButton(WarpedButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, true).ID: return 15515; case WarpedButton::WarpedButton(WarpedButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, false).ID: return 15516; case WarpedButton::WarpedButton(WarpedButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, true).ID: return 15517; case WarpedButton::WarpedButton(WarpedButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, false).ID: return 15518; case WarpedButton::WarpedButton(WarpedButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, true).ID: return 15519; case WarpedButton::WarpedButton(WarpedButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, false).ID: return 15520; case WarpedButton::WarpedButton(WarpedButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, true).ID: return 15521; case WarpedButton::WarpedButton(WarpedButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZP, false).ID: return 15522; case WarpedButton::WarpedButton(WarpedButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, true).ID: return 15523; case WarpedButton::WarpedButton(WarpedButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, false).ID: return 15524; case WarpedButton::WarpedButton(WarpedButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, true).ID: return 15525; case WarpedButton::WarpedButton(WarpedButton::Face::Ceiling, eBlockFace::BLOCK_FACE_XP, false).ID: return 15526; case WarpedDoor::WarpedDoor(eBlockFace::BLOCK_FACE_ZM, WarpedDoor::Half::Upper, WarpedDoor::Hinge::Left, true, true).ID: return 15591; case WarpedDoor::WarpedDoor(eBlockFace::BLOCK_FACE_ZM, WarpedDoor::Half::Upper, WarpedDoor::Hinge::Left, true, false).ID: return 15592; case WarpedDoor::WarpedDoor(eBlockFace::BLOCK_FACE_ZM, WarpedDoor::Half::Upper, WarpedDoor::Hinge::Left, false, true).ID: return 15593; case WarpedDoor::WarpedDoor(eBlockFace::BLOCK_FACE_ZM, WarpedDoor::Half::Upper, WarpedDoor::Hinge::Left, false, false).ID: return 15594; case WarpedDoor::WarpedDoor(eBlockFace::BLOCK_FACE_ZM, WarpedDoor::Half::Upper, WarpedDoor::Hinge::Right, true, true).ID: return 15595; case WarpedDoor::WarpedDoor(eBlockFace::BLOCK_FACE_ZM, WarpedDoor::Half::Upper, WarpedDoor::Hinge::Right, true, false).ID: return 15596; case WarpedDoor::WarpedDoor(eBlockFace::BLOCK_FACE_ZM, WarpedDoor::Half::Upper, WarpedDoor::Hinge::Right, false, true).ID: return 15597; case WarpedDoor::WarpedDoor(eBlockFace::BLOCK_FACE_ZM, WarpedDoor::Half::Upper, WarpedDoor::Hinge::Right, false, false).ID: return 15598; case WarpedDoor::WarpedDoor(eBlockFace::BLOCK_FACE_ZM, WarpedDoor::Half::Lower, WarpedDoor::Hinge::Left, true, true).ID: return 15599; case WarpedDoor::WarpedDoor(eBlockFace::BLOCK_FACE_ZM, WarpedDoor::Half::Lower, WarpedDoor::Hinge::Left, true, false).ID: return 15600; case WarpedDoor::WarpedDoor(eBlockFace::BLOCK_FACE_ZM, WarpedDoor::Half::Lower, WarpedDoor::Hinge::Left, false, true).ID: return 15601; case WarpedDoor::WarpedDoor(eBlockFace::BLOCK_FACE_ZM, WarpedDoor::Half::Lower, WarpedDoor::Hinge::Left, false, false).ID: return 15602; case WarpedDoor::WarpedDoor(eBlockFace::BLOCK_FACE_ZM, WarpedDoor::Half::Lower, WarpedDoor::Hinge::Right, true, true).ID: return 15603; case WarpedDoor::WarpedDoor(eBlockFace::BLOCK_FACE_ZM, WarpedDoor::Half::Lower, WarpedDoor::Hinge::Right, true, false).ID: return 15604; case WarpedDoor::WarpedDoor(eBlockFace::BLOCK_FACE_ZM, WarpedDoor::Half::Lower, WarpedDoor::Hinge::Right, false, true).ID: return 15605; case WarpedDoor::WarpedDoor(eBlockFace::BLOCK_FACE_ZM, WarpedDoor::Half::Lower, WarpedDoor::Hinge::Right, false, false).ID: return 15606; case WarpedDoor::WarpedDoor(eBlockFace::BLOCK_FACE_ZP, WarpedDoor::Half::Upper, WarpedDoor::Hinge::Left, true, true).ID: return 15607; case WarpedDoor::WarpedDoor(eBlockFace::BLOCK_FACE_ZP, WarpedDoor::Half::Upper, WarpedDoor::Hinge::Left, true, false).ID: return 15608; case WarpedDoor::WarpedDoor(eBlockFace::BLOCK_FACE_ZP, WarpedDoor::Half::Upper, WarpedDoor::Hinge::Left, false, true).ID: return 15609; case WarpedDoor::WarpedDoor(eBlockFace::BLOCK_FACE_ZP, WarpedDoor::Half::Upper, WarpedDoor::Hinge::Left, false, false).ID: return 15610; case WarpedDoor::WarpedDoor(eBlockFace::BLOCK_FACE_ZP, WarpedDoor::Half::Upper, WarpedDoor::Hinge::Right, true, true).ID: return 15611; case WarpedDoor::WarpedDoor(eBlockFace::BLOCK_FACE_ZP, WarpedDoor::Half::Upper, WarpedDoor::Hinge::Right, true, false).ID: return 15612; case WarpedDoor::WarpedDoor(eBlockFace::BLOCK_FACE_ZP, WarpedDoor::Half::Upper, WarpedDoor::Hinge::Right, false, true).ID: return 15613; case WarpedDoor::WarpedDoor(eBlockFace::BLOCK_FACE_ZP, WarpedDoor::Half::Upper, WarpedDoor::Hinge::Right, false, false).ID: return 15614; case WarpedDoor::WarpedDoor(eBlockFace::BLOCK_FACE_ZP, WarpedDoor::Half::Lower, WarpedDoor::Hinge::Left, true, true).ID: return 15615; case WarpedDoor::WarpedDoor(eBlockFace::BLOCK_FACE_ZP, WarpedDoor::Half::Lower, WarpedDoor::Hinge::Left, true, false).ID: return 15616; case WarpedDoor::WarpedDoor(eBlockFace::BLOCK_FACE_ZP, WarpedDoor::Half::Lower, WarpedDoor::Hinge::Left, false, true).ID: return 15617; case WarpedDoor::WarpedDoor(eBlockFace::BLOCK_FACE_ZP, WarpedDoor::Half::Lower, WarpedDoor::Hinge::Left, false, false).ID: return 15618; case WarpedDoor::WarpedDoor(eBlockFace::BLOCK_FACE_ZP, WarpedDoor::Half::Lower, WarpedDoor::Hinge::Right, true, true).ID: return 15619; case WarpedDoor::WarpedDoor(eBlockFace::BLOCK_FACE_ZP, WarpedDoor::Half::Lower, WarpedDoor::Hinge::Right, true, false).ID: return 15620; case WarpedDoor::WarpedDoor(eBlockFace::BLOCK_FACE_ZP, WarpedDoor::Half::Lower, WarpedDoor::Hinge::Right, false, true).ID: return 15621; case WarpedDoor::WarpedDoor(eBlockFace::BLOCK_FACE_ZP, WarpedDoor::Half::Lower, WarpedDoor::Hinge::Right, false, false).ID: return 15622; case WarpedDoor::WarpedDoor(eBlockFace::BLOCK_FACE_XM, WarpedDoor::Half::Upper, WarpedDoor::Hinge::Left, true, true).ID: return 15623; case WarpedDoor::WarpedDoor(eBlockFace::BLOCK_FACE_XM, WarpedDoor::Half::Upper, WarpedDoor::Hinge::Left, true, false).ID: return 15624; case WarpedDoor::WarpedDoor(eBlockFace::BLOCK_FACE_XM, WarpedDoor::Half::Upper, WarpedDoor::Hinge::Left, false, true).ID: return 15625; case WarpedDoor::WarpedDoor(eBlockFace::BLOCK_FACE_XM, WarpedDoor::Half::Upper, WarpedDoor::Hinge::Left, false, false).ID: return 15626; case WarpedDoor::WarpedDoor(eBlockFace::BLOCK_FACE_XM, WarpedDoor::Half::Upper, WarpedDoor::Hinge::Right, true, true).ID: return 15627; case WarpedDoor::WarpedDoor(eBlockFace::BLOCK_FACE_XM, WarpedDoor::Half::Upper, WarpedDoor::Hinge::Right, true, false).ID: return 15628; case WarpedDoor::WarpedDoor(eBlockFace::BLOCK_FACE_XM, WarpedDoor::Half::Upper, WarpedDoor::Hinge::Right, false, true).ID: return 15629; case WarpedDoor::WarpedDoor(eBlockFace::BLOCK_FACE_XM, WarpedDoor::Half::Upper, WarpedDoor::Hinge::Right, false, false).ID: return 15630; case WarpedDoor::WarpedDoor(eBlockFace::BLOCK_FACE_XM, WarpedDoor::Half::Lower, WarpedDoor::Hinge::Left, true, true).ID: return 15631; case WarpedDoor::WarpedDoor(eBlockFace::BLOCK_FACE_XM, WarpedDoor::Half::Lower, WarpedDoor::Hinge::Left, true, false).ID: return 15632; case WarpedDoor::WarpedDoor(eBlockFace::BLOCK_FACE_XM, WarpedDoor::Half::Lower, WarpedDoor::Hinge::Left, false, true).ID: return 15633; case WarpedDoor::WarpedDoor(eBlockFace::BLOCK_FACE_XM, WarpedDoor::Half::Lower, WarpedDoor::Hinge::Left, false, false).ID: return 15634; case WarpedDoor::WarpedDoor(eBlockFace::BLOCK_FACE_XM, WarpedDoor::Half::Lower, WarpedDoor::Hinge::Right, true, true).ID: return 15635; case WarpedDoor::WarpedDoor(eBlockFace::BLOCK_FACE_XM, WarpedDoor::Half::Lower, WarpedDoor::Hinge::Right, true, false).ID: return 15636; case WarpedDoor::WarpedDoor(eBlockFace::BLOCK_FACE_XM, WarpedDoor::Half::Lower, WarpedDoor::Hinge::Right, false, true).ID: return 15637; case WarpedDoor::WarpedDoor(eBlockFace::BLOCK_FACE_XM, WarpedDoor::Half::Lower, WarpedDoor::Hinge::Right, false, false).ID: return 15638; case WarpedDoor::WarpedDoor(eBlockFace::BLOCK_FACE_XP, WarpedDoor::Half::Upper, WarpedDoor::Hinge::Left, true, true).ID: return 15639; case WarpedDoor::WarpedDoor(eBlockFace::BLOCK_FACE_XP, WarpedDoor::Half::Upper, WarpedDoor::Hinge::Left, true, false).ID: return 15640; case WarpedDoor::WarpedDoor(eBlockFace::BLOCK_FACE_XP, WarpedDoor::Half::Upper, WarpedDoor::Hinge::Left, false, true).ID: return 15641; case WarpedDoor::WarpedDoor(eBlockFace::BLOCK_FACE_XP, WarpedDoor::Half::Upper, WarpedDoor::Hinge::Left, false, false).ID: return 15642; case WarpedDoor::WarpedDoor(eBlockFace::BLOCK_FACE_XP, WarpedDoor::Half::Upper, WarpedDoor::Hinge::Right, true, true).ID: return 15643; case WarpedDoor::WarpedDoor(eBlockFace::BLOCK_FACE_XP, WarpedDoor::Half::Upper, WarpedDoor::Hinge::Right, true, false).ID: return 15644; case WarpedDoor::WarpedDoor(eBlockFace::BLOCK_FACE_XP, WarpedDoor::Half::Upper, WarpedDoor::Hinge::Right, false, true).ID: return 15645; case WarpedDoor::WarpedDoor(eBlockFace::BLOCK_FACE_XP, WarpedDoor::Half::Upper, WarpedDoor::Hinge::Right, false, false).ID: return 15646; case WarpedDoor::WarpedDoor(eBlockFace::BLOCK_FACE_XP, WarpedDoor::Half::Lower, WarpedDoor::Hinge::Left, true, true).ID: return 15647; case WarpedDoor::WarpedDoor(eBlockFace::BLOCK_FACE_XP, WarpedDoor::Half::Lower, WarpedDoor::Hinge::Left, true, false).ID: return 15648; case WarpedDoor::WarpedDoor(eBlockFace::BLOCK_FACE_XP, WarpedDoor::Half::Lower, WarpedDoor::Hinge::Left, false, true).ID: return 15649; case WarpedDoor::WarpedDoor(eBlockFace::BLOCK_FACE_XP, WarpedDoor::Half::Lower, WarpedDoor::Hinge::Left, false, false).ID: return 15650; case WarpedDoor::WarpedDoor(eBlockFace::BLOCK_FACE_XP, WarpedDoor::Half::Lower, WarpedDoor::Hinge::Right, true, true).ID: return 15651; case WarpedDoor::WarpedDoor(eBlockFace::BLOCK_FACE_XP, WarpedDoor::Half::Lower, WarpedDoor::Hinge::Right, true, false).ID: return 15652; case WarpedDoor::WarpedDoor(eBlockFace::BLOCK_FACE_XP, WarpedDoor::Half::Lower, WarpedDoor::Hinge::Right, false, true).ID: return 15653; case WarpedDoor::WarpedDoor(eBlockFace::BLOCK_FACE_XP, WarpedDoor::Half::Lower, WarpedDoor::Hinge::Right, false, false).ID: return 15654; case WarpedFence::WarpedFence(true, true, true, true).ID: return 15097; case WarpedFence::WarpedFence(true, true, true, false).ID: return 15098; case WarpedFence::WarpedFence(true, true, false, true).ID: return 15101; case WarpedFence::WarpedFence(true, true, false, false).ID: return 15102; case WarpedFence::WarpedFence(true, false, true, true).ID: return 15105; case WarpedFence::WarpedFence(true, false, true, false).ID: return 15106; case WarpedFence::WarpedFence(true, false, false, true).ID: return 15109; case WarpedFence::WarpedFence(true, false, false, false).ID: return 15110; case WarpedFence::WarpedFence(false, true, true, true).ID: return 15113; case WarpedFence::WarpedFence(false, true, true, false).ID: return 15114; case WarpedFence::WarpedFence(false, true, false, true).ID: return 15117; case WarpedFence::WarpedFence(false, true, false, false).ID: return 15118; case WarpedFence::WarpedFence(false, false, true, true).ID: return 15121; case WarpedFence::WarpedFence(false, false, true, false).ID: return 15122; case WarpedFence::WarpedFence(false, false, false, true).ID: return 15125; case WarpedFence::WarpedFence(false, false, false, false).ID: return 15126; case WarpedFenceGate::WarpedFenceGate(eBlockFace::BLOCK_FACE_ZM, true, true, true).ID: return 15287; case WarpedFenceGate::WarpedFenceGate(eBlockFace::BLOCK_FACE_ZM, true, true, false).ID: return 15288; case WarpedFenceGate::WarpedFenceGate(eBlockFace::BLOCK_FACE_ZM, true, false, true).ID: return 15289; case WarpedFenceGate::WarpedFenceGate(eBlockFace::BLOCK_FACE_ZM, true, false, false).ID: return 15290; case WarpedFenceGate::WarpedFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, true).ID: return 15291; case WarpedFenceGate::WarpedFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, false).ID: return 15292; case WarpedFenceGate::WarpedFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, true).ID: return 15293; case WarpedFenceGate::WarpedFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, false).ID: return 15294; case WarpedFenceGate::WarpedFenceGate(eBlockFace::BLOCK_FACE_ZP, true, true, true).ID: return 15295; case WarpedFenceGate::WarpedFenceGate(eBlockFace::BLOCK_FACE_ZP, true, true, false).ID: return 15296; case WarpedFenceGate::WarpedFenceGate(eBlockFace::BLOCK_FACE_ZP, true, false, true).ID: return 15297; case WarpedFenceGate::WarpedFenceGate(eBlockFace::BLOCK_FACE_ZP, true, false, false).ID: return 15298; case WarpedFenceGate::WarpedFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, true).ID: return 15299; case WarpedFenceGate::WarpedFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, false).ID: return 15300; case WarpedFenceGate::WarpedFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, true).ID: return 15301; case WarpedFenceGate::WarpedFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, false).ID: return 15302; case WarpedFenceGate::WarpedFenceGate(eBlockFace::BLOCK_FACE_XM, true, true, true).ID: return 15303; case WarpedFenceGate::WarpedFenceGate(eBlockFace::BLOCK_FACE_XM, true, true, false).ID: return 15304; case WarpedFenceGate::WarpedFenceGate(eBlockFace::BLOCK_FACE_XM, true, false, true).ID: return 15305; case WarpedFenceGate::WarpedFenceGate(eBlockFace::BLOCK_FACE_XM, true, false, false).ID: return 15306; case WarpedFenceGate::WarpedFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, true).ID: return 15307; case WarpedFenceGate::WarpedFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, false).ID: return 15308; case WarpedFenceGate::WarpedFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, true).ID: return 15309; case WarpedFenceGate::WarpedFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, false).ID: return 15310; case WarpedFenceGate::WarpedFenceGate(eBlockFace::BLOCK_FACE_XP, true, true, true).ID: return 15311; case WarpedFenceGate::WarpedFenceGate(eBlockFace::BLOCK_FACE_XP, true, true, false).ID: return 15312; case WarpedFenceGate::WarpedFenceGate(eBlockFace::BLOCK_FACE_XP, true, false, true).ID: return 15313; case WarpedFenceGate::WarpedFenceGate(eBlockFace::BLOCK_FACE_XP, true, false, false).ID: return 15314; case WarpedFenceGate::WarpedFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, true).ID: return 15315; case WarpedFenceGate::WarpedFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, false).ID: return 15316; case WarpedFenceGate::WarpedFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, true).ID: return 15317; case WarpedFenceGate::WarpedFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, false).ID: return 15318; case WarpedFungus::WarpedFungus().ID: return 14971; case WarpedHyphae::WarpedHyphae(WarpedHyphae::Axis::X).ID: return 14964; case WarpedHyphae::WarpedHyphae(WarpedHyphae::Axis::Y).ID: return 14965; case WarpedHyphae::WarpedHyphae(WarpedHyphae::Axis::Z).ID: return 14966; case WarpedNylium::WarpedNylium().ID: return 14970; case WarpedPlanks::WarpedPlanks().ID: return 15046; case WarpedPressurePlate::WarpedPressurePlate(true).ID: return 15061; case WarpedPressurePlate::WarpedPressurePlate(false).ID: return 15062; case WarpedRoots::WarpedRoots().ID: return 14973; case WarpedSign::WarpedSign(0).ID: return 15688; case WarpedSign::WarpedSign(1).ID: return 15690; case WarpedSign::WarpedSign(2).ID: return 15692; case WarpedSign::WarpedSign(3).ID: return 15694; case WarpedSign::WarpedSign(4).ID: return 15696; case WarpedSign::WarpedSign(5).ID: return 15698; case WarpedSign::WarpedSign(6).ID: return 15700; case WarpedSign::WarpedSign(7).ID: return 15702; case WarpedSign::WarpedSign(8).ID: return 15704; case WarpedSign::WarpedSign(9).ID: return 15706; case WarpedSign::WarpedSign(10).ID: return 15708; case WarpedSign::WarpedSign(11).ID: return 15710; case WarpedSign::WarpedSign(12).ID: return 15712; case WarpedSign::WarpedSign(13).ID: return 15714; case WarpedSign::WarpedSign(14).ID: return 15716; case WarpedSign::WarpedSign(15).ID: return 15718; case WarpedSlab::WarpedSlab(WarpedSlab::Type::Top).ID: return 15054; case WarpedSlab::WarpedSlab(WarpedSlab::Type::Bottom).ID: return 15056; case WarpedSlab::WarpedSlab(WarpedSlab::Type::Double).ID: return 15058; case WarpedStairs::WarpedStairs(eBlockFace::BLOCK_FACE_ZM, WarpedStairs::Half::Top, WarpedStairs::Shape::Straight).ID: return 15400; case WarpedStairs::WarpedStairs(eBlockFace::BLOCK_FACE_ZM, WarpedStairs::Half::Top, WarpedStairs::Shape::InnerLeft).ID: return 15402; case WarpedStairs::WarpedStairs(eBlockFace::BLOCK_FACE_ZM, WarpedStairs::Half::Top, WarpedStairs::Shape::InnerRight).ID: return 15404; case WarpedStairs::WarpedStairs(eBlockFace::BLOCK_FACE_ZM, WarpedStairs::Half::Top, WarpedStairs::Shape::OuterLeft).ID: return 15406; case WarpedStairs::WarpedStairs(eBlockFace::BLOCK_FACE_ZM, WarpedStairs::Half::Top, WarpedStairs::Shape::OuterRight).ID: return 15408; case WarpedStairs::WarpedStairs(eBlockFace::BLOCK_FACE_ZM, WarpedStairs::Half::Bottom, WarpedStairs::Shape::Straight).ID: return 15410; case WarpedStairs::WarpedStairs(eBlockFace::BLOCK_FACE_ZM, WarpedStairs::Half::Bottom, WarpedStairs::Shape::InnerLeft).ID: return 15412; case WarpedStairs::WarpedStairs(eBlockFace::BLOCK_FACE_ZM, WarpedStairs::Half::Bottom, WarpedStairs::Shape::InnerRight).ID: return 15414; case WarpedStairs::WarpedStairs(eBlockFace::BLOCK_FACE_ZM, WarpedStairs::Half::Bottom, WarpedStairs::Shape::OuterLeft).ID: return 15416; case WarpedStairs::WarpedStairs(eBlockFace::BLOCK_FACE_ZM, WarpedStairs::Half::Bottom, WarpedStairs::Shape::OuterRight).ID: return 15418; case WarpedStairs::WarpedStairs(eBlockFace::BLOCK_FACE_ZP, WarpedStairs::Half::Top, WarpedStairs::Shape::Straight).ID: return 15420; case WarpedStairs::WarpedStairs(eBlockFace::BLOCK_FACE_ZP, WarpedStairs::Half::Top, WarpedStairs::Shape::InnerLeft).ID: return 15422; case WarpedStairs::WarpedStairs(eBlockFace::BLOCK_FACE_ZP, WarpedStairs::Half::Top, WarpedStairs::Shape::InnerRight).ID: return 15424; case WarpedStairs::WarpedStairs(eBlockFace::BLOCK_FACE_ZP, WarpedStairs::Half::Top, WarpedStairs::Shape::OuterLeft).ID: return 15426; case WarpedStairs::WarpedStairs(eBlockFace::BLOCK_FACE_ZP, WarpedStairs::Half::Top, WarpedStairs::Shape::OuterRight).ID: return 15428; case WarpedStairs::WarpedStairs(eBlockFace::BLOCK_FACE_ZP, WarpedStairs::Half::Bottom, WarpedStairs::Shape::Straight).ID: return 15430; case WarpedStairs::WarpedStairs(eBlockFace::BLOCK_FACE_ZP, WarpedStairs::Half::Bottom, WarpedStairs::Shape::InnerLeft).ID: return 15432; case WarpedStairs::WarpedStairs(eBlockFace::BLOCK_FACE_ZP, WarpedStairs::Half::Bottom, WarpedStairs::Shape::InnerRight).ID: return 15434; case WarpedStairs::WarpedStairs(eBlockFace::BLOCK_FACE_ZP, WarpedStairs::Half::Bottom, WarpedStairs::Shape::OuterLeft).ID: return 15436; case WarpedStairs::WarpedStairs(eBlockFace::BLOCK_FACE_ZP, WarpedStairs::Half::Bottom, WarpedStairs::Shape::OuterRight).ID: return 15438; case WarpedStairs::WarpedStairs(eBlockFace::BLOCK_FACE_XM, WarpedStairs::Half::Top, WarpedStairs::Shape::Straight).ID: return 15440; case WarpedStairs::WarpedStairs(eBlockFace::BLOCK_FACE_XM, WarpedStairs::Half::Top, WarpedStairs::Shape::InnerLeft).ID: return 15442; case WarpedStairs::WarpedStairs(eBlockFace::BLOCK_FACE_XM, WarpedStairs::Half::Top, WarpedStairs::Shape::InnerRight).ID: return 15444; case WarpedStairs::WarpedStairs(eBlockFace::BLOCK_FACE_XM, WarpedStairs::Half::Top, WarpedStairs::Shape::OuterLeft).ID: return 15446; case WarpedStairs::WarpedStairs(eBlockFace::BLOCK_FACE_XM, WarpedStairs::Half::Top, WarpedStairs::Shape::OuterRight).ID: return 15448; case WarpedStairs::WarpedStairs(eBlockFace::BLOCK_FACE_XM, WarpedStairs::Half::Bottom, WarpedStairs::Shape::Straight).ID: return 15450; case WarpedStairs::WarpedStairs(eBlockFace::BLOCK_FACE_XM, WarpedStairs::Half::Bottom, WarpedStairs::Shape::InnerLeft).ID: return 15452; case WarpedStairs::WarpedStairs(eBlockFace::BLOCK_FACE_XM, WarpedStairs::Half::Bottom, WarpedStairs::Shape::InnerRight).ID: return 15454; case WarpedStairs::WarpedStairs(eBlockFace::BLOCK_FACE_XM, WarpedStairs::Half::Bottom, WarpedStairs::Shape::OuterLeft).ID: return 15456; case WarpedStairs::WarpedStairs(eBlockFace::BLOCK_FACE_XM, WarpedStairs::Half::Bottom, WarpedStairs::Shape::OuterRight).ID: return 15458; case WarpedStairs::WarpedStairs(eBlockFace::BLOCK_FACE_XP, WarpedStairs::Half::Top, WarpedStairs::Shape::Straight).ID: return 15460; case WarpedStairs::WarpedStairs(eBlockFace::BLOCK_FACE_XP, WarpedStairs::Half::Top, WarpedStairs::Shape::InnerLeft).ID: return 15462; case WarpedStairs::WarpedStairs(eBlockFace::BLOCK_FACE_XP, WarpedStairs::Half::Top, WarpedStairs::Shape::InnerRight).ID: return 15464; case WarpedStairs::WarpedStairs(eBlockFace::BLOCK_FACE_XP, WarpedStairs::Half::Top, WarpedStairs::Shape::OuterLeft).ID: return 15466; case WarpedStairs::WarpedStairs(eBlockFace::BLOCK_FACE_XP, WarpedStairs::Half::Top, WarpedStairs::Shape::OuterRight).ID: return 15468; case WarpedStairs::WarpedStairs(eBlockFace::BLOCK_FACE_XP, WarpedStairs::Half::Bottom, WarpedStairs::Shape::Straight).ID: return 15470; case WarpedStairs::WarpedStairs(eBlockFace::BLOCK_FACE_XP, WarpedStairs::Half::Bottom, WarpedStairs::Shape::InnerLeft).ID: return 15472; case WarpedStairs::WarpedStairs(eBlockFace::BLOCK_FACE_XP, WarpedStairs::Half::Bottom, WarpedStairs::Shape::InnerRight).ID: return 15474; case WarpedStairs::WarpedStairs(eBlockFace::BLOCK_FACE_XP, WarpedStairs::Half::Bottom, WarpedStairs::Shape::OuterLeft).ID: return 15476; case WarpedStairs::WarpedStairs(eBlockFace::BLOCK_FACE_XP, WarpedStairs::Half::Bottom, WarpedStairs::Shape::OuterRight).ID: return 15478; case WarpedStem::WarpedStem(WarpedStem::Axis::X).ID: return 14958; case WarpedStem::WarpedStem(WarpedStem::Axis::Y).ID: return 14959; case WarpedStem::WarpedStem(WarpedStem::Axis::Z).ID: return 14960; case WarpedTrapdoor::WarpedTrapdoor(eBlockFace::BLOCK_FACE_ZM, WarpedTrapdoor::Half::Top, true, true).ID: return 15192; case WarpedTrapdoor::WarpedTrapdoor(eBlockFace::BLOCK_FACE_ZM, WarpedTrapdoor::Half::Top, true, false).ID: return 15194; case WarpedTrapdoor::WarpedTrapdoor(eBlockFace::BLOCK_FACE_ZM, WarpedTrapdoor::Half::Top, false, true).ID: return 15196; case WarpedTrapdoor::WarpedTrapdoor(eBlockFace::BLOCK_FACE_ZM, WarpedTrapdoor::Half::Top, false, false).ID: return 15198; case WarpedTrapdoor::WarpedTrapdoor(eBlockFace::BLOCK_FACE_ZM, WarpedTrapdoor::Half::Bottom, true, true).ID: return 15200; case WarpedTrapdoor::WarpedTrapdoor(eBlockFace::BLOCK_FACE_ZM, WarpedTrapdoor::Half::Bottom, true, false).ID: return 15202; case WarpedTrapdoor::WarpedTrapdoor(eBlockFace::BLOCK_FACE_ZM, WarpedTrapdoor::Half::Bottom, false, true).ID: return 15204; case WarpedTrapdoor::WarpedTrapdoor(eBlockFace::BLOCK_FACE_ZM, WarpedTrapdoor::Half::Bottom, false, false).ID: return 15206; case WarpedTrapdoor::WarpedTrapdoor(eBlockFace::BLOCK_FACE_ZP, WarpedTrapdoor::Half::Top, true, true).ID: return 15208; case WarpedTrapdoor::WarpedTrapdoor(eBlockFace::BLOCK_FACE_ZP, WarpedTrapdoor::Half::Top, true, false).ID: return 15210; case WarpedTrapdoor::WarpedTrapdoor(eBlockFace::BLOCK_FACE_ZP, WarpedTrapdoor::Half::Top, false, true).ID: return 15212; case WarpedTrapdoor::WarpedTrapdoor(eBlockFace::BLOCK_FACE_ZP, WarpedTrapdoor::Half::Top, false, false).ID: return 15214; case WarpedTrapdoor::WarpedTrapdoor(eBlockFace::BLOCK_FACE_ZP, WarpedTrapdoor::Half::Bottom, true, true).ID: return 15216; case WarpedTrapdoor::WarpedTrapdoor(eBlockFace::BLOCK_FACE_ZP, WarpedTrapdoor::Half::Bottom, true, false).ID: return 15218; case WarpedTrapdoor::WarpedTrapdoor(eBlockFace::BLOCK_FACE_ZP, WarpedTrapdoor::Half::Bottom, false, true).ID: return 15220; case WarpedTrapdoor::WarpedTrapdoor(eBlockFace::BLOCK_FACE_ZP, WarpedTrapdoor::Half::Bottom, false, false).ID: return 15222; case WarpedTrapdoor::WarpedTrapdoor(eBlockFace::BLOCK_FACE_XM, WarpedTrapdoor::Half::Top, true, true).ID: return 15224; case WarpedTrapdoor::WarpedTrapdoor(eBlockFace::BLOCK_FACE_XM, WarpedTrapdoor::Half::Top, true, false).ID: return 15226; case WarpedTrapdoor::WarpedTrapdoor(eBlockFace::BLOCK_FACE_XM, WarpedTrapdoor::Half::Top, false, true).ID: return 15228; case WarpedTrapdoor::WarpedTrapdoor(eBlockFace::BLOCK_FACE_XM, WarpedTrapdoor::Half::Top, false, false).ID: return 15230; case WarpedTrapdoor::WarpedTrapdoor(eBlockFace::BLOCK_FACE_XM, WarpedTrapdoor::Half::Bottom, true, true).ID: return 15232; case WarpedTrapdoor::WarpedTrapdoor(eBlockFace::BLOCK_FACE_XM, WarpedTrapdoor::Half::Bottom, true, false).ID: return 15234; case WarpedTrapdoor::WarpedTrapdoor(eBlockFace::BLOCK_FACE_XM, WarpedTrapdoor::Half::Bottom, false, true).ID: return 15236; case WarpedTrapdoor::WarpedTrapdoor(eBlockFace::BLOCK_FACE_XM, WarpedTrapdoor::Half::Bottom, false, false).ID: return 15238; case WarpedTrapdoor::WarpedTrapdoor(eBlockFace::BLOCK_FACE_XP, WarpedTrapdoor::Half::Top, true, true).ID: return 15240; case WarpedTrapdoor::WarpedTrapdoor(eBlockFace::BLOCK_FACE_XP, WarpedTrapdoor::Half::Top, true, false).ID: return 15242; case WarpedTrapdoor::WarpedTrapdoor(eBlockFace::BLOCK_FACE_XP, WarpedTrapdoor::Half::Top, false, true).ID: return 15244; case WarpedTrapdoor::WarpedTrapdoor(eBlockFace::BLOCK_FACE_XP, WarpedTrapdoor::Half::Top, false, false).ID: return 15246; case WarpedTrapdoor::WarpedTrapdoor(eBlockFace::BLOCK_FACE_XP, WarpedTrapdoor::Half::Bottom, true, true).ID: return 15248; case WarpedTrapdoor::WarpedTrapdoor(eBlockFace::BLOCK_FACE_XP, WarpedTrapdoor::Half::Bottom, true, false).ID: return 15250; case WarpedTrapdoor::WarpedTrapdoor(eBlockFace::BLOCK_FACE_XP, WarpedTrapdoor::Half::Bottom, false, true).ID: return 15252; case WarpedTrapdoor::WarpedTrapdoor(eBlockFace::BLOCK_FACE_XP, WarpedTrapdoor::Half::Bottom, false, false).ID: return 15254; case WarpedWallSign::WarpedWallSign(eBlockFace::BLOCK_FACE_ZM).ID: return 15728; case WarpedWallSign::WarpedWallSign(eBlockFace::BLOCK_FACE_ZP).ID: return 15730; case WarpedWallSign::WarpedWallSign(eBlockFace::BLOCK_FACE_XM).ID: return 15732; case WarpedWallSign::WarpedWallSign(eBlockFace::BLOCK_FACE_XP).ID: return 15734; case WarpedWartBlock::WarpedWartBlock().ID: return 14972; case Water::Water(0).ID: return 34; case Water::Water(1).ID: return 35; case Water::Water(2).ID: return 36; case Water::Water(3).ID: return 37; case Water::Water(4).ID: return 38; case Water::Water(5).ID: return 39; case Water::Water(6).ID: return 40; case Water::Water(7).ID: return 41; case Water::Water(8).ID: return 42; case Water::Water(9).ID: return 43; case Water::Water(10).ID: return 44; case Water::Water(11).ID: return 45; case Water::Water(12).ID: return 46; case Water::Water(13).ID: return 47; case Water::Water(14).ID: return 48; case Water::Water(15).ID: return 49; case WeepingVines::WeepingVines(0).ID: return 14990; case WeepingVines::WeepingVines(1).ID: return 14991; case WeepingVines::WeepingVines(2).ID: return 14992; case WeepingVines::WeepingVines(3).ID: return 14993; case WeepingVines::WeepingVines(4).ID: return 14994; case WeepingVines::WeepingVines(5).ID: return 14995; case WeepingVines::WeepingVines(6).ID: return 14996; case WeepingVines::WeepingVines(7).ID: return 14997; case WeepingVines::WeepingVines(8).ID: return 14998; case WeepingVines::WeepingVines(9).ID: return 14999; case WeepingVines::WeepingVines(10).ID: return 15000; case WeepingVines::WeepingVines(11).ID: return 15001; case WeepingVines::WeepingVines(12).ID: return 15002; case WeepingVines::WeepingVines(13).ID: return 15003; case WeepingVines::WeepingVines(14).ID: return 15004; case WeepingVines::WeepingVines(15).ID: return 15005; case WeepingVines::WeepingVines(16).ID: return 15006; case WeepingVines::WeepingVines(17).ID: return 15007; case WeepingVines::WeepingVines(18).ID: return 15008; case WeepingVines::WeepingVines(19).ID: return 15009; case WeepingVines::WeepingVines(20).ID: return 15010; case WeepingVines::WeepingVines(21).ID: return 15011; case WeepingVines::WeepingVines(22).ID: return 15012; case WeepingVines::WeepingVines(23).ID: return 15013; case WeepingVines::WeepingVines(24).ID: return 15014; case WeepingVines::WeepingVines(25).ID: return 15015; case WeepingVinesPlant::WeepingVinesPlant().ID: return 15016; case WetSponge::WetSponge().ID: return 230; case Wheat::Wheat(0).ID: return 3357; case Wheat::Wheat(1).ID: return 3358; case Wheat::Wheat(2).ID: return 3359; case Wheat::Wheat(3).ID: return 3360; case Wheat::Wheat(4).ID: return 3361; case Wheat::Wheat(5).ID: return 3362; case Wheat::Wheat(6).ID: return 3363; case Wheat::Wheat(7).ID: return 3364; case WhiteBanner::WhiteBanner(0).ID: return 7897; case WhiteBanner::WhiteBanner(1).ID: return 7898; case WhiteBanner::WhiteBanner(2).ID: return 7899; case WhiteBanner::WhiteBanner(3).ID: return 7900; case WhiteBanner::WhiteBanner(4).ID: return 7901; case WhiteBanner::WhiteBanner(5).ID: return 7902; case WhiteBanner::WhiteBanner(6).ID: return 7903; case WhiteBanner::WhiteBanner(7).ID: return 7904; case WhiteBanner::WhiteBanner(8).ID: return 7905; case WhiteBanner::WhiteBanner(9).ID: return 7906; case WhiteBanner::WhiteBanner(10).ID: return 7907; case WhiteBanner::WhiteBanner(11).ID: return 7908; case WhiteBanner::WhiteBanner(12).ID: return 7909; case WhiteBanner::WhiteBanner(13).ID: return 7910; case WhiteBanner::WhiteBanner(14).ID: return 7911; case WhiteBanner::WhiteBanner(15).ID: return 7912; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_ZM, true, WhiteBed::Part::Head).ID: return 1049; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_ZM, true, WhiteBed::Part::Foot).ID: return 1050; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_ZM, false, WhiteBed::Part::Head).ID: return 1051; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_ZM, false, WhiteBed::Part::Foot).ID: return 1052; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_ZP, true, WhiteBed::Part::Head).ID: return 1053; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_ZP, true, WhiteBed::Part::Foot).ID: return 1054; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_ZP, false, WhiteBed::Part::Head).ID: return 1055; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_ZP, false, WhiteBed::Part::Foot).ID: return 1056; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_XM, true, WhiteBed::Part::Head).ID: return 1057; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_XM, true, WhiteBed::Part::Foot).ID: return 1058; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_XM, false, WhiteBed::Part::Head).ID: return 1059; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_XM, false, WhiteBed::Part::Foot).ID: return 1060; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_XP, true, WhiteBed::Part::Head).ID: return 1061; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_XP, true, WhiteBed::Part::Foot).ID: return 1062; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_XP, false, WhiteBed::Part::Head).ID: return 1063; case WhiteBed::WhiteBed(eBlockFace::BLOCK_FACE_XP, false, WhiteBed::Part::Foot).ID: return 1064; case WhiteCarpet::WhiteCarpet().ID: return 7866; case WhiteConcrete::WhiteConcrete().ID: return 9438; case WhiteConcretePowder::WhiteConcretePowder().ID: return 9454; case WhiteGlazedTerracotta::WhiteGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 9374; case WhiteGlazedTerracotta::WhiteGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 9375; case WhiteGlazedTerracotta::WhiteGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 9376; case WhiteGlazedTerracotta::WhiteGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 9377; case WhiteShulkerBox::WhiteShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 9278; case WhiteShulkerBox::WhiteShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 9279; case WhiteShulkerBox::WhiteShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 9280; case WhiteShulkerBox::WhiteShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 9281; case WhiteShulkerBox::WhiteShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 9282; case WhiteShulkerBox::WhiteShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 9283; case WhiteStainedGlass::WhiteStainedGlass().ID: return 4095; case WhiteStainedGlassPane::WhiteStainedGlassPane(true, true, true, true).ID: return 6865; case WhiteStainedGlassPane::WhiteStainedGlassPane(true, true, true, false).ID: return 6866; case WhiteStainedGlassPane::WhiteStainedGlassPane(true, true, false, true).ID: return 6869; case WhiteStainedGlassPane::WhiteStainedGlassPane(true, true, false, false).ID: return 6870; case WhiteStainedGlassPane::WhiteStainedGlassPane(true, false, true, true).ID: return 6873; case WhiteStainedGlassPane::WhiteStainedGlassPane(true, false, true, false).ID: return 6874; case WhiteStainedGlassPane::WhiteStainedGlassPane(true, false, false, true).ID: return 6877; case WhiteStainedGlassPane::WhiteStainedGlassPane(true, false, false, false).ID: return 6878; case WhiteStainedGlassPane::WhiteStainedGlassPane(false, true, true, true).ID: return 6881; case WhiteStainedGlassPane::WhiteStainedGlassPane(false, true, true, false).ID: return 6882; case WhiteStainedGlassPane::WhiteStainedGlassPane(false, true, false, true).ID: return 6885; case WhiteStainedGlassPane::WhiteStainedGlassPane(false, true, false, false).ID: return 6886; case WhiteStainedGlassPane::WhiteStainedGlassPane(false, false, true, true).ID: return 6889; case WhiteStainedGlassPane::WhiteStainedGlassPane(false, false, true, false).ID: return 6890; case WhiteStainedGlassPane::WhiteStainedGlassPane(false, false, false, true).ID: return 6893; case WhiteStainedGlassPane::WhiteStainedGlassPane(false, false, false, false).ID: return 6894; case WhiteTerracotta::WhiteTerracotta().ID: return 6847; case WhiteTulip::WhiteTulip().ID: return 1419; case WhiteWallBanner::WhiteWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 8153; case WhiteWallBanner::WhiteWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 8154; case WhiteWallBanner::WhiteWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 8155; case WhiteWallBanner::WhiteWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 8156; case WhiteWool::WhiteWool().ID: return 1384; case WitherRose::WitherRose().ID: return 1423; case WitherSkeletonSkull::WitherSkeletonSkull(0).ID: return 6510; case WitherSkeletonSkull::WitherSkeletonSkull(1).ID: return 6511; case WitherSkeletonSkull::WitherSkeletonSkull(2).ID: return 6512; case WitherSkeletonSkull::WitherSkeletonSkull(3).ID: return 6513; case WitherSkeletonSkull::WitherSkeletonSkull(4).ID: return 6514; case WitherSkeletonSkull::WitherSkeletonSkull(5).ID: return 6515; case WitherSkeletonSkull::WitherSkeletonSkull(6).ID: return 6516; case WitherSkeletonSkull::WitherSkeletonSkull(7).ID: return 6517; case WitherSkeletonSkull::WitherSkeletonSkull(8).ID: return 6518; case WitherSkeletonSkull::WitherSkeletonSkull(9).ID: return 6519; case WitherSkeletonSkull::WitherSkeletonSkull(10).ID: return 6520; case WitherSkeletonSkull::WitherSkeletonSkull(11).ID: return 6521; case WitherSkeletonSkull::WitherSkeletonSkull(12).ID: return 6522; case WitherSkeletonSkull::WitherSkeletonSkull(13).ID: return 6523; case WitherSkeletonSkull::WitherSkeletonSkull(14).ID: return 6524; case WitherSkeletonSkull::WitherSkeletonSkull(15).ID: return 6525; case WitherSkeletonWallSkull::WitherSkeletonWallSkull(eBlockFace::BLOCK_FACE_ZM).ID: return 6526; case WitherSkeletonWallSkull::WitherSkeletonWallSkull(eBlockFace::BLOCK_FACE_ZP).ID: return 6527; case WitherSkeletonWallSkull::WitherSkeletonWallSkull(eBlockFace::BLOCK_FACE_XM).ID: return 6528; case WitherSkeletonWallSkull::WitherSkeletonWallSkull(eBlockFace::BLOCK_FACE_XP).ID: return 6529; case YellowBanner::YellowBanner(0).ID: return 7961; case YellowBanner::YellowBanner(1).ID: return 7962; case YellowBanner::YellowBanner(2).ID: return 7963; case YellowBanner::YellowBanner(3).ID: return 7964; case YellowBanner::YellowBanner(4).ID: return 7965; case YellowBanner::YellowBanner(5).ID: return 7966; case YellowBanner::YellowBanner(6).ID: return 7967; case YellowBanner::YellowBanner(7).ID: return 7968; case YellowBanner::YellowBanner(8).ID: return 7969; case YellowBanner::YellowBanner(9).ID: return 7970; case YellowBanner::YellowBanner(10).ID: return 7971; case YellowBanner::YellowBanner(11).ID: return 7972; case YellowBanner::YellowBanner(12).ID: return 7973; case YellowBanner::YellowBanner(13).ID: return 7974; case YellowBanner::YellowBanner(14).ID: return 7975; case YellowBanner::YellowBanner(15).ID: return 7976; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_ZM, true, YellowBed::Part::Head).ID: return 1113; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_ZM, true, YellowBed::Part::Foot).ID: return 1114; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_ZM, false, YellowBed::Part::Head).ID: return 1115; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_ZM, false, YellowBed::Part::Foot).ID: return 1116; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_ZP, true, YellowBed::Part::Head).ID: return 1117; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_ZP, true, YellowBed::Part::Foot).ID: return 1118; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_ZP, false, YellowBed::Part::Head).ID: return 1119; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_ZP, false, YellowBed::Part::Foot).ID: return 1120; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_XM, true, YellowBed::Part::Head).ID: return 1121; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_XM, true, YellowBed::Part::Foot).ID: return 1122; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_XM, false, YellowBed::Part::Head).ID: return 1123; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_XM, false, YellowBed::Part::Foot).ID: return 1124; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_XP, true, YellowBed::Part::Head).ID: return 1125; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_XP, true, YellowBed::Part::Foot).ID: return 1126; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_XP, false, YellowBed::Part::Head).ID: return 1127; case YellowBed::YellowBed(eBlockFace::BLOCK_FACE_XP, false, YellowBed::Part::Foot).ID: return 1128; case YellowCarpet::YellowCarpet().ID: return 7870; case YellowConcrete::YellowConcrete().ID: return 9442; case YellowConcretePowder::YellowConcretePowder().ID: return 9458; case YellowGlazedTerracotta::YellowGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM).ID: return 9390; case YellowGlazedTerracotta::YellowGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP).ID: return 9391; case YellowGlazedTerracotta::YellowGlazedTerracotta(eBlockFace::BLOCK_FACE_XM).ID: return 9392; case YellowGlazedTerracotta::YellowGlazedTerracotta(eBlockFace::BLOCK_FACE_XP).ID: return 9393; case YellowShulkerBox::YellowShulkerBox(eBlockFace::BLOCK_FACE_ZM).ID: return 9302; case YellowShulkerBox::YellowShulkerBox(eBlockFace::BLOCK_FACE_XP).ID: return 9303; case YellowShulkerBox::YellowShulkerBox(eBlockFace::BLOCK_FACE_ZP).ID: return 9304; case YellowShulkerBox::YellowShulkerBox(eBlockFace::BLOCK_FACE_XM).ID: return 9305; case YellowShulkerBox::YellowShulkerBox(eBlockFace::BLOCK_FACE_YP).ID: return 9306; case YellowShulkerBox::YellowShulkerBox(eBlockFace::BLOCK_FACE_YM).ID: return 9307; case YellowStainedGlass::YellowStainedGlass().ID: return 4099; case YellowStainedGlassPane::YellowStainedGlassPane(true, true, true, true).ID: return 6993; case YellowStainedGlassPane::YellowStainedGlassPane(true, true, true, false).ID: return 6994; case YellowStainedGlassPane::YellowStainedGlassPane(true, true, false, true).ID: return 6997; case YellowStainedGlassPane::YellowStainedGlassPane(true, true, false, false).ID: return 6998; case YellowStainedGlassPane::YellowStainedGlassPane(true, false, true, true).ID: return 7001; case YellowStainedGlassPane::YellowStainedGlassPane(true, false, true, false).ID: return 7002; case YellowStainedGlassPane::YellowStainedGlassPane(true, false, false, true).ID: return 7005; case YellowStainedGlassPane::YellowStainedGlassPane(true, false, false, false).ID: return 7006; case YellowStainedGlassPane::YellowStainedGlassPane(false, true, true, true).ID: return 7009; case YellowStainedGlassPane::YellowStainedGlassPane(false, true, true, false).ID: return 7010; case YellowStainedGlassPane::YellowStainedGlassPane(false, true, false, true).ID: return 7013; case YellowStainedGlassPane::YellowStainedGlassPane(false, true, false, false).ID: return 7014; case YellowStainedGlassPane::YellowStainedGlassPane(false, false, true, true).ID: return 7017; case YellowStainedGlassPane::YellowStainedGlassPane(false, false, true, false).ID: return 7018; case YellowStainedGlassPane::YellowStainedGlassPane(false, false, false, true).ID: return 7021; case YellowStainedGlassPane::YellowStainedGlassPane(false, false, false, false).ID: return 7022; case YellowTerracotta::YellowTerracotta().ID: return 6851; case YellowWallBanner::YellowWallBanner(eBlockFace::BLOCK_FACE_ZM).ID: return 8169; case YellowWallBanner::YellowWallBanner(eBlockFace::BLOCK_FACE_ZP).ID: return 8170; case YellowWallBanner::YellowWallBanner(eBlockFace::BLOCK_FACE_XM).ID: return 8171; case YellowWallBanner::YellowWallBanner(eBlockFace::BLOCK_FACE_XP).ID: return 8172; case YellowWool::YellowWool().ID: return 1388; case ZombieHead::ZombieHead(0).ID: return 6530; case ZombieHead::ZombieHead(1).ID: return 6531; case ZombieHead::ZombieHead(2).ID: return 6532; case ZombieHead::ZombieHead(3).ID: return 6533; case ZombieHead::ZombieHead(4).ID: return 6534; case ZombieHead::ZombieHead(5).ID: return 6535; case ZombieHead::ZombieHead(6).ID: return 6536; case ZombieHead::ZombieHead(7).ID: return 6537; case ZombieHead::ZombieHead(8).ID: return 6538; case ZombieHead::ZombieHead(9).ID: return 6539; case ZombieHead::ZombieHead(10).ID: return 6540; case ZombieHead::ZombieHead(11).ID: return 6541; case ZombieHead::ZombieHead(12).ID: return 6542; case ZombieHead::ZombieHead(13).ID: return 6543; case ZombieHead::ZombieHead(14).ID: return 6544; case ZombieHead::ZombieHead(15).ID: return 6545; case ZombieWallHead::ZombieWallHead(eBlockFace::BLOCK_FACE_ZM).ID: return 6546; case ZombieWallHead::ZombieWallHead(eBlockFace::BLOCK_FACE_ZP).ID: return 6547; case ZombieWallHead::ZombieWallHead(eBlockFace::BLOCK_FACE_XM).ID: return 6548; case ZombieWallHead::ZombieWallHead(eBlockFace::BLOCK_FACE_XP).ID: return 6549; default: return 0; } } UInt32 From(const Item ID) { switch (ID) { case Item::AcaciaBoat: return 901; case Item::AcaciaButton: return 309; case Item::AcaciaDoor: return 562; case Item::AcaciaFence: return 212; case Item::AcaciaFenceGate: return 256; case Item::AcaciaLeaves: return 73; case Item::AcaciaLog: return 41; case Item::AcaciaPlanks: return 19; case Item::AcaciaPressurePlate: return 195; case Item::AcaciaSapling: return 27; case Item::AcaciaSign: return 656; case Item::AcaciaSlab: return 142; case Item::AcaciaStairs: return 369; case Item::AcaciaTrapdoor: return 230; case Item::AcaciaWood: return 65; case Item::ActivatorRail: return 329; case Item::Air: return -0; case Item::Allium: return 114; case Item::AncientDebris: return 959; case Item::Andesite: return 6; case Item::AndesiteSlab: return 552; case Item::AndesiteStairs: return 539; case Item::AndesiteWall: return 296; case Item::Anvil: return 314; case Item::Apple: return 576; case Item::ArmorStand: return 859; case Item::Arrow: return 578; case Item::AzureBluet: return 115; case Item::BakedPotato: return 831; case Item::Bamboo: return 135; case Item::Barrel: return 935; case Item::Barrier: return 347; case Item::Basalt: return 221; case Item::BatSpawnEgg: return 759; case Item::Beacon: return 286; case Item::Bedrock: return 29; case Item::BeeNest: return 952; case Item::BeeSpawnEgg: return 760; case Item::Beef: return 739; case Item::Beehive: return 953; case Item::Beetroot: return 888; case Item::BeetrootSeeds: return 889; case Item::BeetrootSoup: return 890; case Item::Bell: return 944; case Item::BirchBoat: return 899; case Item::BirchButton: return 307; case Item::BirchDoor: return 560; case Item::BirchFence: return 210; case Item::BirchFenceGate: return 254; case Item::BirchLeaves: return 71; case Item::BirchLog: return 39; case Item::BirchPlanks: return 17; case Item::BirchPressurePlate: return 193; case Item::BirchSapling: return 25; case Item::BirchSign: return 654; case Item::BirchSlab: return 140; case Item::BirchStairs: return 281; case Item::BirchTrapdoor: return 228; case Item::BirchWood: return 63; case Item::BlackBanner: return 884; case Item::BlackBed: return 731; case Item::BlackCarpet: return 365; case Item::BlackConcrete: return 479; case Item::BlackConcretePowder: return 495; case Item::BlackDye: return 711; case Item::BlackGlazedTerracotta: return 463; case Item::BlackShulkerBox: return 447; case Item::BlackStainedGlass: return 394; case Item::BlackStainedGlassPane: return 410; case Item::BlackTerracotta: return 346; case Item::BlackWool: return 110; case Item::Blackstone: return 962; case Item::BlackstoneSlab: return 963; case Item::BlackstoneStairs: return 964; case Item::BlackstoneWall: return 301; case Item::BlastFurnace: return 937; case Item::BlazePowder: return 753; case Item::BlazeRod: return 745; case Item::BlazeSpawnEgg: return 761; case Item::BlueBanner: return 880; case Item::BlueBed: return 727; case Item::BlueCarpet: return 361; case Item::BlueConcrete: return 475; case Item::BlueConcretePowder: return 491; case Item::BlueDye: return 709; case Item::BlueGlazedTerracotta: return 459; case Item::BlueIce: return 527; case Item::BlueOrchid: return 113; case Item::BlueShulkerBox: return 443; case Item::BlueStainedGlass: return 390; case Item::BlueStainedGlassPane: return 406; case Item::BlueTerracotta: return 342; case Item::BlueWool: return 106; case Item::Bone: return 713; case Item::BoneBlock: return 428; case Item::BoneMeal: return 708; case Item::Book: return 678; case Item::Bookshelf: return 168; case Item::Bow: return 577; case Item::Bowl: return 600; case Item::BrainCoral: return 508; case Item::BrainCoralBlock: return 503; case Item::BrainCoralFan: return 518; case Item::Bread: return 621; case Item::BrewingStand: return 755; case Item::Brick: return 674; case Item::BrickSlab: return 152; case Item::BrickStairs: return 260; case Item::BrickWall: return 289; case Item::Bricks: return 166; case Item::BrownBanner: return 881; case Item::BrownBed: return 728; case Item::BrownCarpet: return 362; case Item::BrownConcrete: return 476; case Item::BrownConcretePowder: return 492; case Item::BrownDye: return 710; case Item::BrownGlazedTerracotta: return 460; case Item::BrownMushroom: return 124; case Item::BrownMushroomBlock: return 244; case Item::BrownShulkerBox: return 444; case Item::BrownStainedGlass: return 391; case Item::BrownStainedGlassPane: return 407; case Item::BrownTerracotta: return 343; case Item::BrownWool: return 107; case Item::BubbleCoral: return 509; case Item::BubbleCoralBlock: return 504; case Item::BubbleCoralFan: return 519; case Item::Bucket: return 660; case Item::Cactus: return 205; case Item::Cake: return 715; case Item::Campfire: return 948; case Item::Carrot: return 829; case Item::CarrotOnAStick: return 841; case Item::CartographyTable: return 938; case Item::CarvedPumpkin: return 217; case Item::CatSpawnEgg: return 762; case Item::Cauldron: return 756; case Item::CaveSpiderSpawnEgg: return 763; case Item::Chain: return 248; case Item::ChainCommandBlock: return 423; case Item::ChainmailBoots: return 629; case Item::ChainmailChestplate: return 627; case Item::ChainmailHelmet: return 626; case Item::ChainmailLeggings: return 628; case Item::Charcoal: return 580; case Item::Chest: return 180; case Item::ChestMinecart: return 680; case Item::Chicken: return 741; case Item::ChickenSpawnEgg: return 764; case Item::ChippedAnvil: return 315; case Item::ChiseledNetherBricks: return 266; case Item::ChiseledPolishedBlackstone: return 969; case Item::ChiseledQuartzBlock: return 324; case Item::ChiseledRedSandstone: return 419; case Item::ChiseledSandstone: return 82; case Item::ChiseledStoneBricks: return 243; case Item::ChorusFlower: return 174; case Item::ChorusFruit: return 886; case Item::ChorusPlant: return 173; case Item::Clay: return 206; case Item::ClayBall: return 675; case Item::Clock: return 685; case Item::Coal: return 579; case Item::CoalBlock: return 367; case Item::CoalOre: return 35; case Item::CoarseDirt: return 10; case Item::Cobblestone: return 14; case Item::CobblestoneSlab: return 151; case Item::CobblestoneStairs: return 188; case Item::CobblestoneWall: return 287; case Item::Cobweb: return 88; case Item::CocoaBeans: return 696; case Item::Cod: return 687; case Item::CodBucket: return 672; case Item::CodSpawnEgg: return 765; case Item::CommandBlock: return 285; case Item::CommandBlockMinecart: return 866; case Item::Comparator: return 567; case Item::Compass: return 683; case Item::Composter: return 934; case Item::Conduit: return 528; case Item::CookedBeef: return 740; case Item::CookedChicken: return 742; case Item::CookedCod: return 691; case Item::CookedMutton: return 868; case Item::CookedPorkchop: return 648; case Item::CookedRabbit: return 855; case Item::CookedSalmon: return 692; case Item::Cookie: return 732; case Item::Cornflower: return 121; case Item::CowSpawnEgg: return 766; case Item::CrackedNetherBricks: return 265; case Item::CrackedPolishedBlackstoneBricks: return 973; case Item::CrackedStoneBricks: return 242; case Item::CraftingTable: return 183; case Item::CreeperBannerPattern: return 929; case Item::CreeperHead: return 839; case Item::CreeperSpawnEgg: return 767; case Item::CrimsonButton: return 311; case Item::CrimsonDoor: return 564; case Item::CrimsonFence: return 214; case Item::CrimsonFenceGate: return 258; case Item::CrimsonFungus: return 126; case Item::CrimsonHyphae: return 67; case Item::CrimsonNylium: return 12; case Item::CrimsonPlanks: return 21; case Item::CrimsonPressurePlate: return 197; case Item::CrimsonRoots: return 128; case Item::CrimsonSign: return 658; case Item::CrimsonSlab: return 144; case Item::CrimsonStairs: return 283; case Item::CrimsonStem: return 43; case Item::CrimsonTrapdoor: return 232; case Item::Crossbow: return 925; case Item::CryingObsidian: return 961; case Item::CutRedSandstone: return 420; case Item::CutRedSandstoneSlab: return 157; case Item::CutSandstone: return 83; case Item::CutSandstoneSlab: return 149; case Item::CyanBanner: return 878; case Item::CyanBed: return 725; case Item::CyanCarpet: return 359; case Item::CyanConcrete: return 473; case Item::CyanConcretePowder: return 489; case Item::CyanDye: return 699; case Item::CyanGlazedTerracotta: return 457; case Item::CyanShulkerBox: return 441; case Item::CyanStainedGlass: return 388; case Item::CyanStainedGlassPane: return 404; case Item::CyanTerracotta: return 340; case Item::CyanWool: return 104; case Item::DamagedAnvil: return 316; case Item::Dandelion: return 111; case Item::DarkOakBoat: return 902; case Item::DarkOakButton: return 310; case Item::DarkOakDoor: return 563; case Item::DarkOakFence: return 213; case Item::DarkOakFenceGate: return 257; case Item::DarkOakLeaves: return 74; case Item::DarkOakLog: return 42; case Item::DarkOakPlanks: return 20; case Item::DarkOakPressurePlate: return 196; case Item::DarkOakSapling: return 28; case Item::DarkOakSign: return 657; case Item::DarkOakSlab: return 143; case Item::DarkOakStairs: return 370; case Item::DarkOakTrapdoor: return 231; case Item::DarkOakWood: return 66; case Item::DarkPrismarine: return 413; case Item::DarkPrismarineSlab: return 161; case Item::DarkPrismarineStairs: return 416; case Item::DaylightDetector: return 320; case Item::DeadBrainCoral: return 512; case Item::DeadBrainCoralBlock: return 498; case Item::DeadBrainCoralFan: return 523; case Item::DeadBubbleCoral: return 513; case Item::DeadBubbleCoralBlock: return 499; case Item::DeadBubbleCoralFan: return 524; case Item::DeadBush: return 91; case Item::DeadFireCoral: return 514; case Item::DeadFireCoralBlock: return 500; case Item::DeadFireCoralFan: return 525; case Item::DeadHornCoral: return 515; case Item::DeadHornCoralBlock: return 501; case Item::DeadHornCoralFan: return 526; case Item::DeadTubeCoral: return 516; case Item::DeadTubeCoralBlock: return 497; case Item::DeadTubeCoralFan: return 522; case Item::DebugStick: return 907; case Item::DetectorRail: return 86; case Item::Diamond: return 581; case Item::DiamondAxe: return 598; case Item::DiamondBlock: return 182; case Item::DiamondBoots: return 637; case Item::DiamondChestplate: return 635; case Item::DiamondHelmet: return 634; case Item::DiamondHoe: return 616; case Item::DiamondHorseArmor: return 862; case Item::DiamondLeggings: return 636; case Item::DiamondOre: return 181; case Item::DiamondPickaxe: return 597; case Item::DiamondShovel: return 596; case Item::DiamondSword: return 595; case Item::Diorite: return 4; case Item::DioriteSlab: return 555; case Item::DioriteStairs: return 542; case Item::DioriteWall: return 300; case Item::Dirt: return 9; case Item::Dispenser: return 80; case Item::DolphinSpawnEgg: return 768; case Item::DonkeySpawnEgg: return 769; case Item::DragonBreath: return 891; case Item::DragonEgg: return 273; case Item::DragonHead: return 840; case Item::DriedKelp: return 736; case Item::DriedKelpBlock: return 676; case Item::Dropper: return 330; case Item::DrownedSpawnEgg: return 770; case Item::Egg: return 682; case Item::ElderGuardianSpawnEgg: return 771; case Item::Elytra: return 897; case Item::Emerald: return 826; case Item::EmeraldBlock: return 279; case Item::EmeraldOre: return 276; case Item::EnchantedBook: return 847; case Item::EnchantedGoldenApple: return 651; case Item::EnchantingTable: return 269; case Item::EndCrystal: return 885; case Item::EndPortalFrame: return 270; case Item::EndRod: return 172; case Item::EndStone: return 271; case Item::EndStoneBrickSlab: return 548; case Item::EndStoneBrickStairs: return 534; case Item::EndStoneBrickWall: return 299; case Item::EndStoneBricks: return 272; case Item::EnderChest: return 277; case Item::EnderEye: return 757; case Item::EnderPearl: return 744; case Item::EndermanSpawnEgg: return 772; case Item::EndermiteSpawnEgg: return 773; case Item::EvokerSpawnEgg: return 774; case Item::ExperienceBottle: return 822; case Item::Farmland: return 184; case Item::Feather: return 611; case Item::FermentedSpiderEye: return 752; case Item::Fern: return 90; case Item::FilledMap: return 733; case Item::FireCharge: return 823; case Item::FireCoral: return 510; case Item::FireCoralBlock: return 505; case Item::FireCoralFan: return 520; case Item::FireworkRocket: return 845; case Item::FireworkStar: return 846; case Item::FishingRod: return 684; case Item::FletchingTable: return 939; case Item::Flint: return 646; case Item::FlintAndSteel: return 575; case Item::FlowerBannerPattern: return 928; case Item::FlowerPot: return 828; case Item::FoxSpawnEgg: return 775; case Item::Furnace: return 185; case Item::FurnaceMinecart: return 681; case Item::GhastSpawnEgg: return 776; case Item::GhastTear: return 746; case Item::GildedBlackstone: return 965; case Item::Glass: return 77; case Item::GlassBottle: return 750; case Item::GlassPane: return 249; case Item::GlisteringMelonSlice: return 758; case Item::GlobeBannerPattern: return 932; case Item::Glowstone: return 224; case Item::GlowstoneDust: return 686; case Item::GoldBlock: return 136; case Item::GoldIngot: return 583; case Item::GoldNugget: return 747; case Item::GoldOre: return 33; case Item::GoldenApple: return 650; case Item::GoldenAxe: return 605; case Item::GoldenBoots: return 641; case Item::GoldenCarrot: return 834; case Item::GoldenChestplate: return 639; case Item::GoldenHelmet: return 638; case Item::GoldenHoe: return 617; case Item::GoldenHorseArmor: return 861; case Item::GoldenLeggings: return 640; case Item::GoldenPickaxe: return 604; case Item::GoldenShovel: return 603; case Item::GoldenSword: return 602; case Item::Granite: return 2; case Item::GraniteSlab: return 551; case Item::GraniteStairs: return 538; case Item::GraniteWall: return 293; case Item::Grass: return 89; case Item::GrassBlock: return 8; case Item::GrassPath: return 372; case Item::Gravel: return 32; case Item::GrayBanner: return 876; case Item::GrayBed: return 723; case Item::GrayCarpet: return 357; case Item::GrayConcrete: return 471; case Item::GrayConcretePowder: return 487; case Item::GrayDye: return 701; case Item::GrayGlazedTerracotta: return 455; case Item::GrayShulkerBox: return 439; case Item::GrayStainedGlass: return 386; case Item::GrayStainedGlassPane: return 402; case Item::GrayTerracotta: return 338; case Item::GrayWool: return 102; case Item::GreenBanner: return 882; case Item::GreenBed: return 729; case Item::GreenCarpet: return 363; case Item::GreenConcrete: return 477; case Item::GreenConcretePowder: return 493; case Item::GreenDye: return 695; case Item::GreenGlazedTerracotta: return 461; case Item::GreenShulkerBox: return 445; case Item::GreenStainedGlass: return 392; case Item::GreenStainedGlassPane: return 408; case Item::GreenTerracotta: return 344; case Item::GreenWool: return 108; case Item::Grindstone: return 940; case Item::GuardianSpawnEgg: return 777; case Item::Gunpowder: return 612; case Item::HayBale: return 349; case Item::HeartOfTheSea: return 924; case Item::HeavyWeightedPressurePlate: return 319; case Item::HoglinSpawnEgg: return 778; case Item::HoneyBlock: return 955; case Item::HoneyBottle: return 954; case Item::Honeycomb: return 951; case Item::HoneycombBlock: return 956; case Item::Hopper: return 323; case Item::HopperMinecart: return 851; case Item::HornCoral: return 511; case Item::HornCoralBlock: return 506; case Item::HornCoralFan: return 521; case Item::HorseSpawnEgg: return 779; case Item::HuskSpawnEgg: return 780; case Item::Ice: return 203; case Item::InfestedChiseledStoneBricks: return 239; case Item::InfestedCobblestone: return 235; case Item::InfestedCrackedStoneBricks: return 238; case Item::InfestedMossyStoneBricks: return 237; case Item::InfestedStone: return 234; case Item::InfestedStoneBricks: return 236; case Item::InkSac: return 693; case Item::IronAxe: return 574; case Item::IronBars: return 247; case Item::IronBlock: return 137; case Item::IronBoots: return 633; case Item::IronChestplate: return 631; case Item::IronDoor: return 557; case Item::IronHelmet: return 630; case Item::IronHoe: return 615; case Item::IronHorseArmor: return 860; case Item::IronIngot: return 582; case Item::IronLeggings: return 632; case Item::IronNugget: return 905; case Item::IronOre: return 34; case Item::IronPickaxe: return 573; case Item::IronShovel: return 572; case Item::IronSword: return 586; case Item::IronTrapdoor: return 348; case Item::ItemFrame: return 827; case Item::JackOLantern: return 225; case Item::Jigsaw: return 569; case Item::Jukebox: return 207; case Item::JungleBoat: return 900; case Item::JungleButton: return 308; case Item::JungleDoor: return 561; case Item::JungleFence: return 211; case Item::JungleFenceGate: return 255; case Item::JungleLeaves: return 72; case Item::JungleLog: return 40; case Item::JunglePlanks: return 18; case Item::JunglePressurePlate: return 194; case Item::JungleSapling: return 26; case Item::JungleSign: return 655; case Item::JungleSlab: return 141; case Item::JungleStairs: return 282; case Item::JungleTrapdoor: return 229; case Item::JungleWood: return 64; case Item::Kelp: return 134; case Item::KnowledgeBook: return 906; case Item::Ladder: return 186; case Item::Lantern: return 945; case Item::LapisBlock: return 79; case Item::LapisLazuli: return 697; case Item::LapisOre: return 78; case Item::LargeFern: return 378; case Item::LavaBucket: return 662; case Item::Lead: return 864; case Item::Leather: return 668; case Item::LeatherBoots: return 625; case Item::LeatherChestplate: return 623; case Item::LeatherHelmet: return 622; case Item::LeatherHorseArmor: return 863; case Item::LeatherLeggings: return 624; case Item::Lectern: return 941; case Item::Lever: return 189; case Item::LightBlueBanner: return 872; case Item::LightBlueBed: return 719; case Item::LightBlueCarpet: return 353; case Item::LightBlueConcrete: return 467; case Item::LightBlueConcretePowder: return 483; case Item::LightBlueDye: return 705; case Item::LightBlueGlazedTerracotta: return 451; case Item::LightBlueShulkerBox: return 435; case Item::LightBlueStainedGlass: return 382; case Item::LightBlueStainedGlassPane: return 398; case Item::LightBlueTerracotta: return 334; case Item::LightBlueWool: return 98; case Item::LightGrayBanner: return 877; case Item::LightGrayBed: return 724; case Item::LightGrayCarpet: return 358; case Item::LightGrayConcrete: return 472; case Item::LightGrayConcretePowder: return 488; case Item::LightGrayDye: return 700; case Item::LightGrayGlazedTerracotta: return 456; case Item::LightGrayShulkerBox: return 440; case Item::LightGrayStainedGlass: return 387; case Item::LightGrayStainedGlassPane: return 403; case Item::LightGrayTerracotta: return 339; case Item::LightGrayWool: return 103; case Item::LightWeightedPressurePlate: return 318; case Item::Lilac: return 374; case Item::LilyOfTheValley: return 122; case Item::LilyPad: return 263; case Item::LimeBanner: return 874; case Item::LimeBed: return 721; case Item::LimeCarpet: return 355; case Item::LimeConcrete: return 469; case Item::LimeConcretePowder: return 485; case Item::LimeDye: return 703; case Item::LimeGlazedTerracotta: return 453; case Item::LimeShulkerBox: return 437; case Item::LimeStainedGlass: return 384; case Item::LimeStainedGlassPane: return 400; case Item::LimeTerracotta: return 336; case Item::LimeWool: return 100; case Item::LingeringPotion: return 895; case Item::LlamaSpawnEgg: return 781; case Item::Lodestone: return 957; case Item::Loom: return 927; case Item::MagentaBanner: return 871; case Item::MagentaBed: return 718; case Item::MagentaCarpet: return 352; case Item::MagentaConcrete: return 466; case Item::MagentaConcretePowder: return 482; case Item::MagentaDye: return 706; case Item::MagentaGlazedTerracotta: return 450; case Item::MagentaShulkerBox: return 434; case Item::MagentaStainedGlass: return 381; case Item::MagentaStainedGlassPane: return 397; case Item::MagentaTerracotta: return 333; case Item::MagentaWool: return 97; case Item::MagmaBlock: return 424; case Item::MagmaCream: return 754; case Item::MagmaCubeSpawnEgg: return 782; case Item::Map: return 833; case Item::Melon: return 250; case Item::MelonSeeds: return 738; case Item::MelonSlice: return 735; case Item::MilkBucket: return 669; case Item::Minecart: return 663; case Item::MojangBannerPattern: return 931; case Item::MooshroomSpawnEgg: return 783; case Item::MossyCobblestone: return 169; case Item::MossyCobblestoneSlab: return 547; case Item::MossyCobblestoneStairs: return 533; case Item::MossyCobblestoneWall: return 288; case Item::MossyStoneBrickSlab: return 545; case Item::MossyStoneBrickStairs: return 531; case Item::MossyStoneBrickWall: return 292; case Item::MossyStoneBricks: return 241; case Item::MuleSpawnEgg: return 784; case Item::MushroomStem: return 246; case Item::MushroomStew: return 601; case Item::MusicDiscBlocks: return 910; case Item::MusicDiscCat: return 909; case Item::MusicDiscChirp: return 911; case Item::MusicDiscFar: return 912; case Item::MusicDiscMall: return 913; case Item::MusicDiscMellohi: return 914; case Item::MusicDiscPigstep: return 920; case Item::MusicDiscStal: return 915; case Item::MusicDiscStrad: return 916; case Item::MusicDiscWait: return 919; case Item::MusicDiscWard: return 917; case Item::MusicDisc11: return 918; case Item::MusicDisc13: return 908; case Item::Mutton: return 867; case Item::Mycelium: return 262; case Item::NameTag: return 865; case Item::NautilusShell: return 923; case Item::NetherBrick: return 848; case Item::NetherBrickFence: return 267; case Item::NetherBrickSlab: return 154; case Item::NetherBrickStairs: return 268; case Item::NetherBrickWall: return 295; case Item::NetherBricks: return 264; case Item::NetherGoldOre: return 36; case Item::NetherQuartzOre: return 322; case Item::NetherSprouts: return 130; case Item::NetherStar: return 843; case Item::NetherWart: return 748; case Item::NetherWartBlock: return 425; case Item::NetheriteAxe: return 609; case Item::NetheriteBlock: return 958; case Item::NetheriteBoots: return 645; case Item::NetheriteChestplate: return 643; case Item::NetheriteHelmet: return 642; case Item::NetheriteHoe: return 618; case Item::NetheriteIngot: return 584; case Item::NetheriteLeggings: return 644; case Item::NetheritePickaxe: return 608; case Item::NetheriteScrap: return 585; case Item::NetheriteShovel: return 607; case Item::NetheriteSword: return 606; case Item::Netherrack: return 218; case Item::NoteBlock: return 84; case Item::OakBoat: return 667; case Item::OakButton: return 305; case Item::OakDoor: return 558; case Item::OakFence: return 208; case Item::OakFenceGate: return 252; case Item::OakLeaves: return 69; case Item::OakLog: return 37; case Item::OakPlanks: return 15; case Item::OakPressurePlate: return 191; case Item::OakSapling: return 23; case Item::OakSign: return 652; case Item::OakSlab: return 138; case Item::OakStairs: return 179; case Item::OakTrapdoor: return 226; case Item::OakWood: return 61; case Item::Observer: return 430; case Item::Obsidian: return 170; case Item::OcelotSpawnEgg: return 785; case Item::OrangeBanner: return 870; case Item::OrangeBed: return 717; case Item::OrangeCarpet: return 351; case Item::OrangeConcrete: return 465; case Item::OrangeConcretePowder: return 481; case Item::OrangeDye: return 707; case Item::OrangeGlazedTerracotta: return 449; case Item::OrangeShulkerBox: return 433; case Item::OrangeStainedGlass: return 380; case Item::OrangeStainedGlassPane: return 396; case Item::OrangeTerracotta: return 332; case Item::OrangeTulip: return 117; case Item::OrangeWool: return 96; case Item::OxeyeDaisy: return 120; case Item::PackedIce: return 368; case Item::Painting: return 649; case Item::PandaSpawnEgg: return 786; case Item::Paper: return 677; case Item::ParrotSpawnEgg: return 787; case Item::Peony: return 376; case Item::PetrifiedOakSlab: return 150; case Item::PhantomMembrane: return 922; case Item::PhantomSpawnEgg: return 788; case Item::PigSpawnEgg: return 789; case Item::PiglinBannerPattern: return 933; case Item::PiglinSpawnEgg: return 790; case Item::PillagerSpawnEgg: return 791; case Item::PinkBanner: return 875; case Item::PinkBed: return 722; case Item::PinkCarpet: return 356; case Item::PinkConcrete: return 470; case Item::PinkConcretePowder: return 486; case Item::PinkDye: return 702; case Item::PinkGlazedTerracotta: return 454; case Item::PinkShulkerBox: return 438; case Item::PinkStainedGlass: return 385; case Item::PinkStainedGlassPane: return 401; case Item::PinkTerracotta: return 337; case Item::PinkTulip: return 119; case Item::PinkWool: return 101; case Item::Piston: return 94; case Item::PlayerHead: return 837; case Item::Podzol: return 11; case Item::PoisonousPotato: return 832; case Item::PolarBearSpawnEgg: return 792; case Item::PolishedAndesite: return 7; case Item::PolishedAndesiteSlab: return 554; case Item::PolishedAndesiteStairs: return 541; case Item::PolishedBasalt: return 222; case Item::PolishedBlackstone: return 966; case Item::PolishedBlackstoneBrickSlab: return 971; case Item::PolishedBlackstoneBrickStairs: return 972; case Item::PolishedBlackstoneBrickWall: return 303; case Item::PolishedBlackstoneBricks: return 970; case Item::PolishedBlackstoneButton: return 313; case Item::PolishedBlackstonePressurePlate: return 199; case Item::PolishedBlackstoneSlab: return 967; case Item::PolishedBlackstoneStairs: return 968; case Item::PolishedBlackstoneWall: return 302; case Item::PolishedDiorite: return 5; case Item::PolishedDioriteSlab: return 546; case Item::PolishedDioriteStairs: return 532; case Item::PolishedGranite: return 3; case Item::PolishedGraniteSlab: return 543; case Item::PolishedGraniteStairs: return 529; case Item::PoppedChorusFruit: return 887; case Item::Poppy: return 112; case Item::Porkchop: return 647; case Item::Potato: return 830; case Item::Potion: return 749; case Item::PoweredRail: return 85; case Item::Prismarine: return 411; case Item::PrismarineBrickSlab: return 160; case Item::PrismarineBrickStairs: return 415; case Item::PrismarineBricks: return 412; case Item::PrismarineCrystals: return 853; case Item::PrismarineShard: return 852; case Item::PrismarineSlab: return 159; case Item::PrismarineStairs: return 414; case Item::PrismarineWall: return 290; case Item::Pufferfish: return 690; case Item::PufferfishBucket: return 670; case Item::PufferfishSpawnEgg: return 793; case Item::Pumpkin: return 216; case Item::PumpkinPie: return 844; case Item::PumpkinSeeds: return 737; case Item::PurpleBanner: return 879; case Item::PurpleBed: return 726; case Item::PurpleCarpet: return 360; case Item::PurpleConcrete: return 474; case Item::PurpleConcretePowder: return 490; case Item::PurpleDye: return 698; case Item::PurpleGlazedTerracotta: return 458; case Item::PurpleShulkerBox: return 442; case Item::PurpleStainedGlass: return 389; case Item::PurpleStainedGlassPane: return 405; case Item::PurpleTerracotta: return 341; case Item::PurpleWool: return 105; case Item::PurpurBlock: return 175; case Item::PurpurPillar: return 176; case Item::PurpurSlab: return 158; case Item::PurpurStairs: return 177; case Item::Quartz: return 849; case Item::QuartzBlock: return 325; case Item::QuartzBricks: return 326; case Item::QuartzPillar: return 327; case Item::QuartzSlab: return 155; case Item::QuartzStairs: return 328; case Item::Rabbit: return 854; case Item::RabbitFoot: return 857; case Item::RabbitHide: return 858; case Item::RabbitSpawnEgg: return 794; case Item::RabbitStew: return 856; case Item::Rail: return 187; case Item::RavagerSpawnEgg: return 795; case Item::RedBanner: return 883; case Item::RedBed: return 730; case Item::RedCarpet: return 364; case Item::RedConcrete: return 478; case Item::RedConcretePowder: return 494; case Item::RedDye: return 694; case Item::RedGlazedTerracotta: return 462; case Item::RedMushroom: return 125; case Item::RedMushroomBlock: return 245; case Item::RedNetherBrickSlab: return 553; case Item::RedNetherBrickStairs: return 540; case Item::RedNetherBrickWall: return 297; case Item::RedNetherBricks: return 427; case Item::RedSand: return 31; case Item::RedSandstone: return 418; case Item::RedSandstoneSlab: return 156; case Item::RedSandstoneStairs: return 421; case Item::RedSandstoneWall: return 291; case Item::RedShulkerBox: return 446; case Item::RedStainedGlass: return 393; case Item::RedStainedGlassPane: return 409; case Item::RedTerracotta: return 345; case Item::RedTulip: return 116; case Item::RedWool: return 109; case Item::Redstone: return 665; case Item::RedstoneBlock: return 321; case Item::RedstoneLamp: return 274; case Item::RedstoneOre: return 200; case Item::RedstoneTorch: return 201; case Item::Repeater: return 566; case Item::RepeatingCommandBlock: return 422; case Item::RespawnAnchor: return 974; case Item::RoseBush: return 375; case Item::RottenFlesh: return 743; case Item::Saddle: return 664; case Item::Salmon: return 688; case Item::SalmonBucket: return 671; case Item::SalmonSpawnEgg: return 796; case Item::Sand: return 30; case Item::Sandstone: return 81; case Item::SandstoneSlab: return 148; case Item::SandstoneStairs: return 275; case Item::SandstoneWall: return 298; case Item::Scaffolding: return 556; case Item::Scute: return 571; case Item::SeaLantern: return 417; case Item::SeaPickle: return 93; case Item::Seagrass: return 92; case Item::Shears: return 734; case Item::SheepSpawnEgg: return 797; case Item::Shield: return 896; case Item::Shroomlight: return 950; case Item::ShulkerBox: return 431; case Item::ShulkerShell: return 904; case Item::ShulkerSpawnEgg: return 798; case Item::SilverfishSpawnEgg: return 799; case Item::SkeletonHorseSpawnEgg: return 801; case Item::SkeletonSkull: return 835; case Item::SkeletonSpawnEgg: return 800; case Item::SkullBannerPattern: return 930; case Item::SlimeBall: return 679; case Item::SlimeBlock: return 371; case Item::SlimeSpawnEgg: return 802; case Item::SmithingTable: return 942; case Item::Smoker: return 936; case Item::SmoothQuartz: return 162; case Item::SmoothQuartzSlab: return 550; case Item::SmoothQuartzStairs: return 537; case Item::SmoothRedSandstone: return 163; case Item::SmoothRedSandstoneSlab: return 544; case Item::SmoothRedSandstoneStairs: return 530; case Item::SmoothSandstone: return 164; case Item::SmoothSandstoneSlab: return 549; case Item::SmoothSandstoneStairs: return 536; case Item::SmoothStone: return 165; case Item::SmoothStoneSlab: return 147; case Item::Snow: return 202; case Item::SnowBlock: return 204; case Item::Snowball: return 666; case Item::SoulCampfire: return 949; case Item::SoulLantern: return 946; case Item::SoulSand: return 219; case Item::SoulSoil: return 220; case Item::SoulTorch: return 223; case Item::Spawner: return 178; case Item::SpectralArrow: return 893; case Item::SpiderEye: return 751; case Item::SpiderSpawnEgg: return 803; case Item::SplashPotion: return 892; case Item::Sponge: return 75; case Item::SpruceBoat: return 898; case Item::SpruceButton: return 306; case Item::SpruceDoor: return 559; case Item::SpruceFence: return 209; case Item::SpruceFenceGate: return 253; case Item::SpruceLeaves: return 70; case Item::SpruceLog: return 38; case Item::SprucePlanks: return 16; case Item::SprucePressurePlate: return 192; case Item::SpruceSapling: return 24; case Item::SpruceSign: return 653; case Item::SpruceSlab: return 139; case Item::SpruceStairs: return 280; case Item::SpruceTrapdoor: return 227; case Item::SpruceWood: return 62; case Item::SquidSpawnEgg: return 804; case Item::Stick: return 599; case Item::StickyPiston: return 87; case Item::Stone: return 1; case Item::StoneAxe: return 594; case Item::StoneBrickSlab: return 153; case Item::StoneBrickStairs: return 261; case Item::StoneBrickWall: return 294; case Item::StoneBricks: return 240; case Item::StoneButton: return 304; case Item::StoneHoe: return 614; case Item::StonePickaxe: return 593; case Item::StonePressurePlate: return 190; case Item::StoneShovel: return 592; case Item::StoneSlab: return 146; case Item::StoneStairs: return 535; case Item::StoneSword: return 591; case Item::Stonecutter: return 943; case Item::StraySpawnEgg: return 805; case Item::StriderSpawnEgg: return 806; case Item::String: return 610; case Item::StrippedAcaciaLog: return 49; case Item::StrippedAcaciaWood: return 57; case Item::StrippedBirchLog: return 47; case Item::StrippedBirchWood: return 55; case Item::StrippedCrimsonHyphae: return 59; case Item::StrippedCrimsonStem: return 51; case Item::StrippedDarkOakLog: return 50; case Item::StrippedDarkOakWood: return 58; case Item::StrippedJungleLog: return 48; case Item::StrippedJungleWood: return 56; case Item::StrippedOakLog: return 45; case Item::StrippedOakWood: return 53; case Item::StrippedSpruceLog: return 46; case Item::StrippedSpruceWood: return 54; case Item::StrippedWarpedHyphae: return 60; case Item::StrippedWarpedStem: return 52; case Item::StructureBlock: return 568; case Item::StructureVoid: return 429; case Item::Sugar: return 714; case Item::SugarCane: return 133; case Item::Sunflower: return 373; case Item::SuspiciousStew: return 926; case Item::SweetBerries: return 947; case Item::TallGrass: return 377; case Item::Target: return 960; case Item::Terracotta: return 366; case Item::TippedArrow: return 894; case Item::TNT: return 167; case Item::TNTMinecart: return 850; case Item::Torch: return 171; case Item::TotemOfUndying: return 903; case Item::TraderLlamaSpawnEgg: return 807; case Item::TrappedChest: return 317; case Item::Trident: return 921; case Item::TripwireHook: return 278; case Item::TropicalFish: return 689; case Item::TropicalFishBucket: return 673; case Item::TropicalFishSpawnEgg: return 808; case Item::TubeCoral: return 507; case Item::TubeCoralBlock: return 502; case Item::TubeCoralFan: return 517; case Item::TurtleEgg: return 496; case Item::TurtleHelmet: return 570; case Item::TurtleSpawnEgg: return 809; case Item::TwistingVines: return 132; case Item::VexSpawnEgg: return 810; case Item::VillagerSpawnEgg: return 811; case Item::VindicatorSpawnEgg: return 812; case Item::Vine: return 251; case Item::WanderingTraderSpawnEgg: return 813; case Item::WarpedButton: return 312; case Item::WarpedDoor: return 565; case Item::WarpedFence: return 215; case Item::WarpedFenceGate: return 259; case Item::WarpedFungus: return 127; case Item::WarpedFungusOnA_stick: return 842; case Item::WarpedHyphae: return 68; case Item::WarpedNylium: return 13; case Item::WarpedPlanks: return 22; case Item::WarpedPressurePlate: return 198; case Item::WarpedRoots: return 129; case Item::WarpedSign: return 659; case Item::WarpedSlab: return 145; case Item::WarpedStairs: return 284; case Item::WarpedStem: return 44; case Item::WarpedTrapdoor: return 233; case Item::WarpedWartBlock: return 426; case Item::WaterBucket: return 661; case Item::WeepingVines: return 131; case Item::WetSponge: return 76; case Item::Wheat: return 620; case Item::WheatSeeds: return 619; case Item::WhiteBanner: return 869; case Item::WhiteBed: return 716; case Item::WhiteCarpet: return 350; case Item::WhiteConcrete: return 464; case Item::WhiteConcretePowder: return 480; case Item::WhiteDye: return 712; case Item::WhiteGlazedTerracotta: return 448; case Item::WhiteShulkerBox: return 432; case Item::WhiteStainedGlass: return 379; case Item::WhiteStainedGlassPane: return 395; case Item::WhiteTerracotta: return 331; case Item::WhiteTulip: return 118; case Item::WhiteWool: return 95; case Item::WitchSpawnEgg: return 814; case Item::WitherRose: return 123; case Item::WitherSkeletonSkull: return 836; case Item::WitherSkeletonSpawnEgg: return 815; case Item::WolfSpawnEgg: return 816; case Item::WoodenAxe: return 590; case Item::WoodenHoe: return 613; case Item::WoodenPickaxe: return 589; case Item::WoodenShovel: return 588; case Item::WoodenSword: return 587; case Item::WritableBook: return 824; case Item::WrittenBook: return 825; case Item::YellowBanner: return 873; case Item::YellowBed: return 720; case Item::YellowCarpet: return 354; case Item::YellowConcrete: return 468; case Item::YellowConcretePowder: return 484; case Item::YellowDye: return 704; case Item::YellowGlazedTerracotta: return 452; case Item::YellowShulkerBox: return 436; case Item::YellowStainedGlass: return 383; case Item::YellowStainedGlassPane: return 399; case Item::YellowTerracotta: return 335; case Item::YellowWool: return 99; case Item::ZoglinSpawnEgg: return 817; case Item::ZombieHead: return 838; case Item::ZombieHorseSpawnEgg: return 819; case Item::ZombieSpawnEgg: return 818; case Item::ZombieVillagerSpawnEgg: return 820; case Item::ZombiePigmanSpawnEgg: return 821; } UNREACHABLE("Invalid item"); } UInt32 From(const CustomStatistic ID) { switch (ID) { case CustomStatistic::AnimalsBred: return 31; case CustomStatistic::AviateOneCm: return 17; case CustomStatistic::BellRing: return 67; case CustomStatistic::BoatOneCm: return 14; case CustomStatistic::CleanArmor: return 39; case CustomStatistic::CleanBanner: return 40; case CustomStatistic::CleanShulkerBox: return 41; case CustomStatistic::ClimbOneCm: return 10; case CustomStatistic::CrouchOneCm: return 6; case CustomStatistic::DamageAbsorbed: return 27; case CustomStatistic::DamageBlockedByShield: return 26; case CustomStatistic::DamageDealt: return 22; case CustomStatistic::DamageDealtAbsorbed: return 23; case CustomStatistic::DamageDealtResisted: return 24; case CustomStatistic::DamageResisted: return 28; case CustomStatistic::DamageTaken: return 25; case CustomStatistic::Deaths: return 29; case CustomStatistic::Drop: return 21; case CustomStatistic::EatCakeSlice: return 36; case CustomStatistic::EnchantItem: return 52; case CustomStatistic::FallOneCm: return 9; case CustomStatistic::FillCauldron: return 37; case CustomStatistic::FishCaught: return 33; case CustomStatistic::FlyOneCm: return 11; case CustomStatistic::HorseOneCm: return 16; case CustomStatistic::InspectDispenser: return 46; case CustomStatistic::InspectDropper: return 44; case CustomStatistic::InspectHopper: return 45; case CustomStatistic::InteractWithAnvil: return 70; case CustomStatistic::InteractWithBeacon: return 43; case CustomStatistic::InteractWithBlastFurnace: return 60; case CustomStatistic::InteractWithBrewingstand: return 42; case CustomStatistic::InteractWithCampfire: return 63; case CustomStatistic::InteractWithCartographyTable: return 64; case CustomStatistic::InteractWithCraftingTable: return 55; case CustomStatistic::InteractWithFurnace: return 54; case CustomStatistic::InteractWithGrindstone: return 71; case CustomStatistic::InteractWithLectern: return 62; case CustomStatistic::InteractWithLoom: return 65; case CustomStatistic::InteractWithSmithingTable: return 73; case CustomStatistic::InteractWithSmoker: return 61; case CustomStatistic::InteractWithStonecutter: return 66; case CustomStatistic::Jump: return 20; case CustomStatistic::LeaveGame: return -0; case CustomStatistic::MinecartOneCm: return 13; case CustomStatistic::MobKills: return 30; case CustomStatistic::OpenBarrel: return 59; case CustomStatistic::OpenChest: return 56; case CustomStatistic::OpenEnderchest: return 51; case CustomStatistic::OpenShulkerBox: return 58; case CustomStatistic::PigOneCm: return 15; case CustomStatistic::PlayNoteblock: return 47; case CustomStatistic::PlayOneMinute: return 1; case CustomStatistic::PlayRecord: return 53; case CustomStatistic::PlayerKills: return 32; case CustomStatistic::PotFlower: return 49; case CustomStatistic::RaidTrigger: return 68; case CustomStatistic::RaidWin: return 69; case CustomStatistic::SleepInBed: return 57; case CustomStatistic::SneakTime: return 4; case CustomStatistic::SprintOneCm: return 7; case CustomStatistic::StriderOneCm: return 19; case CustomStatistic::SwimOneCm: return 18; case CustomStatistic::TalkedToVillager: return 34; case CustomStatistic::TargetHit: return 72; case CustomStatistic::TimeSinceDeath: return 2; case CustomStatistic::TimeSinceRest: return 3; case CustomStatistic::TradedWithVillager: return 35; case CustomStatistic::TriggerTrappedChest: return 50; case CustomStatistic::TuneNoteblock: return 48; case CustomStatistic::UseCauldron: return 38; case CustomStatistic::WalkOnWaterOneCm: return 8; case CustomStatistic::WalkOneCm: return 5; case CustomStatistic::WalkUnderWaterOneCm: return 12; default: return UInt32(-1); } } Item ToItem(const UInt32 ID) { switch (ID) { case 901: return Item::AcaciaBoat; case 309: return Item::AcaciaButton; case 562: return Item::AcaciaDoor; case 212: return Item::AcaciaFence; case 256: return Item::AcaciaFenceGate; case 73: return Item::AcaciaLeaves; case 41: return Item::AcaciaLog; case 19: return Item::AcaciaPlanks; case 195: return Item::AcaciaPressurePlate; case 27: return Item::AcaciaSapling; case 656: return Item::AcaciaSign; case 142: return Item::AcaciaSlab; case 369: return Item::AcaciaStairs; case 230: return Item::AcaciaTrapdoor; case 65: return Item::AcaciaWood; case 329: return Item::ActivatorRail; case -0: return Item::Air; case 114: return Item::Allium; case 959: return Item::AncientDebris; case 6: return Item::Andesite; case 552: return Item::AndesiteSlab; case 539: return Item::AndesiteStairs; case 296: return Item::AndesiteWall; case 314: return Item::Anvil; case 576: return Item::Apple; case 859: return Item::ArmorStand; case 578: return Item::Arrow; case 115: return Item::AzureBluet; case 831: return Item::BakedPotato; case 135: return Item::Bamboo; case 935: return Item::Barrel; case 347: return Item::Barrier; case 221: return Item::Basalt; case 759: return Item::BatSpawnEgg; case 286: return Item::Beacon; case 29: return Item::Bedrock; case 952: return Item::BeeNest; case 760: return Item::BeeSpawnEgg; case 739: return Item::Beef; case 953: return Item::Beehive; case 888: return Item::Beetroot; case 889: return Item::BeetrootSeeds; case 890: return Item::BeetrootSoup; case 944: return Item::Bell; case 899: return Item::BirchBoat; case 307: return Item::BirchButton; case 560: return Item::BirchDoor; case 210: return Item::BirchFence; case 254: return Item::BirchFenceGate; case 71: return Item::BirchLeaves; case 39: return Item::BirchLog; case 17: return Item::BirchPlanks; case 193: return Item::BirchPressurePlate; case 25: return Item::BirchSapling; case 654: return Item::BirchSign; case 140: return Item::BirchSlab; case 281: return Item::BirchStairs; case 228: return Item::BirchTrapdoor; case 63: return Item::BirchWood; case 884: return Item::BlackBanner; case 731: return Item::BlackBed; case 365: return Item::BlackCarpet; case 479: return Item::BlackConcrete; case 495: return Item::BlackConcretePowder; case 711: return Item::BlackDye; case 463: return Item::BlackGlazedTerracotta; case 447: return Item::BlackShulkerBox; case 394: return Item::BlackStainedGlass; case 410: return Item::BlackStainedGlassPane; case 346: return Item::BlackTerracotta; case 110: return Item::BlackWool; case 962: return Item::Blackstone; case 963: return Item::BlackstoneSlab; case 964: return Item::BlackstoneStairs; case 301: return Item::BlackstoneWall; case 937: return Item::BlastFurnace; case 753: return Item::BlazePowder; case 745: return Item::BlazeRod; case 761: return Item::BlazeSpawnEgg; case 880: return Item::BlueBanner; case 727: return Item::BlueBed; case 361: return Item::BlueCarpet; case 475: return Item::BlueConcrete; case 491: return Item::BlueConcretePowder; case 709: return Item::BlueDye; case 459: return Item::BlueGlazedTerracotta; case 527: return Item::BlueIce; case 113: return Item::BlueOrchid; case 443: return Item::BlueShulkerBox; case 390: return Item::BlueStainedGlass; case 406: return Item::BlueStainedGlassPane; case 342: return Item::BlueTerracotta; case 106: return Item::BlueWool; case 713: return Item::Bone; case 428: return Item::BoneBlock; case 708: return Item::BoneMeal; case 678: return Item::Book; case 168: return Item::Bookshelf; case 577: return Item::Bow; case 600: return Item::Bowl; case 508: return Item::BrainCoral; case 503: return Item::BrainCoralBlock; case 518: return Item::BrainCoralFan; case 621: return Item::Bread; case 755: return Item::BrewingStand; case 674: return Item::Brick; case 152: return Item::BrickSlab; case 260: return Item::BrickStairs; case 289: return Item::BrickWall; case 166: return Item::Bricks; case 881: return Item::BrownBanner; case 728: return Item::BrownBed; case 362: return Item::BrownCarpet; case 476: return Item::BrownConcrete; case 492: return Item::BrownConcretePowder; case 710: return Item::BrownDye; case 460: return Item::BrownGlazedTerracotta; case 124: return Item::BrownMushroom; case 244: return Item::BrownMushroomBlock; case 444: return Item::BrownShulkerBox; case 391: return Item::BrownStainedGlass; case 407: return Item::BrownStainedGlassPane; case 343: return Item::BrownTerracotta; case 107: return Item::BrownWool; case 509: return Item::BubbleCoral; case 504: return Item::BubbleCoralBlock; case 519: return Item::BubbleCoralFan; case 660: return Item::Bucket; case 205: return Item::Cactus; case 715: return Item::Cake; case 948: return Item::Campfire; case 829: return Item::Carrot; case 841: return Item::CarrotOnAStick; case 938: return Item::CartographyTable; case 217: return Item::CarvedPumpkin; case 762: return Item::CatSpawnEgg; case 756: return Item::Cauldron; case 763: return Item::CaveSpiderSpawnEgg; case 248: return Item::Chain; case 423: return Item::ChainCommandBlock; case 629: return Item::ChainmailBoots; case 627: return Item::ChainmailChestplate; case 626: return Item::ChainmailHelmet; case 628: return Item::ChainmailLeggings; case 580: return Item::Charcoal; case 180: return Item::Chest; case 680: return Item::ChestMinecart; case 741: return Item::Chicken; case 764: return Item::ChickenSpawnEgg; case 315: return Item::ChippedAnvil; case 266: return Item::ChiseledNetherBricks; case 969: return Item::ChiseledPolishedBlackstone; case 324: return Item::ChiseledQuartzBlock; case 419: return Item::ChiseledRedSandstone; case 82: return Item::ChiseledSandstone; case 243: return Item::ChiseledStoneBricks; case 174: return Item::ChorusFlower; case 886: return Item::ChorusFruit; case 173: return Item::ChorusPlant; case 206: return Item::Clay; case 675: return Item::ClayBall; case 685: return Item::Clock; case 579: return Item::Coal; case 367: return Item::CoalBlock; case 35: return Item::CoalOre; case 10: return Item::CoarseDirt; case 14: return Item::Cobblestone; case 151: return Item::CobblestoneSlab; case 188: return Item::CobblestoneStairs; case 287: return Item::CobblestoneWall; case 88: return Item::Cobweb; case 696: return Item::CocoaBeans; case 687: return Item::Cod; case 672: return Item::CodBucket; case 765: return Item::CodSpawnEgg; case 285: return Item::CommandBlock; case 866: return Item::CommandBlockMinecart; case 567: return Item::Comparator; case 683: return Item::Compass; case 934: return Item::Composter; case 528: return Item::Conduit; case 740: return Item::CookedBeef; case 742: return Item::CookedChicken; case 691: return Item::CookedCod; case 868: return Item::CookedMutton; case 648: return Item::CookedPorkchop; case 855: return Item::CookedRabbit; case 692: return Item::CookedSalmon; case 732: return Item::Cookie; case 121: return Item::Cornflower; case 766: return Item::CowSpawnEgg; case 265: return Item::CrackedNetherBricks; case 973: return Item::CrackedPolishedBlackstoneBricks; case 242: return Item::CrackedStoneBricks; case 183: return Item::CraftingTable; case 929: return Item::CreeperBannerPattern; case 839: return Item::CreeperHead; case 767: return Item::CreeperSpawnEgg; case 311: return Item::CrimsonButton; case 564: return Item::CrimsonDoor; case 214: return Item::CrimsonFence; case 258: return Item::CrimsonFenceGate; case 126: return Item::CrimsonFungus; case 67: return Item::CrimsonHyphae; case 12: return Item::CrimsonNylium; case 21: return Item::CrimsonPlanks; case 197: return Item::CrimsonPressurePlate; case 128: return Item::CrimsonRoots; case 658: return Item::CrimsonSign; case 144: return Item::CrimsonSlab; case 283: return Item::CrimsonStairs; case 43: return Item::CrimsonStem; case 232: return Item::CrimsonTrapdoor; case 925: return Item::Crossbow; case 961: return Item::CryingObsidian; case 420: return Item::CutRedSandstone; case 157: return Item::CutRedSandstoneSlab; case 83: return Item::CutSandstone; case 149: return Item::CutSandstoneSlab; case 878: return Item::CyanBanner; case 725: return Item::CyanBed; case 359: return Item::CyanCarpet; case 473: return Item::CyanConcrete; case 489: return Item::CyanConcretePowder; case 699: return Item::CyanDye; case 457: return Item::CyanGlazedTerracotta; case 441: return Item::CyanShulkerBox; case 388: return Item::CyanStainedGlass; case 404: return Item::CyanStainedGlassPane; case 340: return Item::CyanTerracotta; case 104: return Item::CyanWool; case 316: return Item::DamagedAnvil; case 111: return Item::Dandelion; case 902: return Item::DarkOakBoat; case 310: return Item::DarkOakButton; case 563: return Item::DarkOakDoor; case 213: return Item::DarkOakFence; case 257: return Item::DarkOakFenceGate; case 74: return Item::DarkOakLeaves; case 42: return Item::DarkOakLog; case 20: return Item::DarkOakPlanks; case 196: return Item::DarkOakPressurePlate; case 28: return Item::DarkOakSapling; case 657: return Item::DarkOakSign; case 143: return Item::DarkOakSlab; case 370: return Item::DarkOakStairs; case 231: return Item::DarkOakTrapdoor; case 66: return Item::DarkOakWood; case 413: return Item::DarkPrismarine; case 161: return Item::DarkPrismarineSlab; case 416: return Item::DarkPrismarineStairs; case 320: return Item::DaylightDetector; case 512: return Item::DeadBrainCoral; case 498: return Item::DeadBrainCoralBlock; case 523: return Item::DeadBrainCoralFan; case 513: return Item::DeadBubbleCoral; case 499: return Item::DeadBubbleCoralBlock; case 524: return Item::DeadBubbleCoralFan; case 91: return Item::DeadBush; case 514: return Item::DeadFireCoral; case 500: return Item::DeadFireCoralBlock; case 525: return Item::DeadFireCoralFan; case 515: return Item::DeadHornCoral; case 501: return Item::DeadHornCoralBlock; case 526: return Item::DeadHornCoralFan; case 516: return Item::DeadTubeCoral; case 497: return Item::DeadTubeCoralBlock; case 522: return Item::DeadTubeCoralFan; case 907: return Item::DebugStick; case 86: return Item::DetectorRail; case 581: return Item::Diamond; case 598: return Item::DiamondAxe; case 182: return Item::DiamondBlock; case 637: return Item::DiamondBoots; case 635: return Item::DiamondChestplate; case 634: return Item::DiamondHelmet; case 616: return Item::DiamondHoe; case 862: return Item::DiamondHorseArmor; case 636: return Item::DiamondLeggings; case 181: return Item::DiamondOre; case 597: return Item::DiamondPickaxe; case 596: return Item::DiamondShovel; case 595: return Item::DiamondSword; case 4: return Item::Diorite; case 555: return Item::DioriteSlab; case 542: return Item::DioriteStairs; case 300: return Item::DioriteWall; case 9: return Item::Dirt; case 80: return Item::Dispenser; case 768: return Item::DolphinSpawnEgg; case 769: return Item::DonkeySpawnEgg; case 891: return Item::DragonBreath; case 273: return Item::DragonEgg; case 840: return Item::DragonHead; case 736: return Item::DriedKelp; case 676: return Item::DriedKelpBlock; case 330: return Item::Dropper; case 770: return Item::DrownedSpawnEgg; case 682: return Item::Egg; case 771: return Item::ElderGuardianSpawnEgg; case 897: return Item::Elytra; case 826: return Item::Emerald; case 279: return Item::EmeraldBlock; case 276: return Item::EmeraldOre; case 847: return Item::EnchantedBook; case 651: return Item::EnchantedGoldenApple; case 269: return Item::EnchantingTable; case 885: return Item::EndCrystal; case 270: return Item::EndPortalFrame; case 172: return Item::EndRod; case 271: return Item::EndStone; case 548: return Item::EndStoneBrickSlab; case 534: return Item::EndStoneBrickStairs; case 299: return Item::EndStoneBrickWall; case 272: return Item::EndStoneBricks; case 277: return Item::EnderChest; case 757: return Item::EnderEye; case 744: return Item::EnderPearl; case 772: return Item::EndermanSpawnEgg; case 773: return Item::EndermiteSpawnEgg; case 774: return Item::EvokerSpawnEgg; case 822: return Item::ExperienceBottle; case 184: return Item::Farmland; case 611: return Item::Feather; case 752: return Item::FermentedSpiderEye; case 90: return Item::Fern; case 733: return Item::FilledMap; case 823: return Item::FireCharge; case 510: return Item::FireCoral; case 505: return Item::FireCoralBlock; case 520: return Item::FireCoralFan; case 845: return Item::FireworkRocket; case 846: return Item::FireworkStar; case 684: return Item::FishingRod; case 939: return Item::FletchingTable; case 646: return Item::Flint; case 575: return Item::FlintAndSteel; case 928: return Item::FlowerBannerPattern; case 828: return Item::FlowerPot; case 775: return Item::FoxSpawnEgg; case 185: return Item::Furnace; case 681: return Item::FurnaceMinecart; case 776: return Item::GhastSpawnEgg; case 746: return Item::GhastTear; case 965: return Item::GildedBlackstone; case 77: return Item::Glass; case 750: return Item::GlassBottle; case 249: return Item::GlassPane; case 758: return Item::GlisteringMelonSlice; case 932: return Item::GlobeBannerPattern; case 224: return Item::Glowstone; case 686: return Item::GlowstoneDust; case 136: return Item::GoldBlock; case 583: return Item::GoldIngot; case 747: return Item::GoldNugget; case 33: return Item::GoldOre; case 650: return Item::GoldenApple; case 605: return Item::GoldenAxe; case 641: return Item::GoldenBoots; case 834: return Item::GoldenCarrot; case 639: return Item::GoldenChestplate; case 638: return Item::GoldenHelmet; case 617: return Item::GoldenHoe; case 861: return Item::GoldenHorseArmor; case 640: return Item::GoldenLeggings; case 604: return Item::GoldenPickaxe; case 603: return Item::GoldenShovel; case 602: return Item::GoldenSword; case 2: return Item::Granite; case 551: return Item::GraniteSlab; case 538: return Item::GraniteStairs; case 293: return Item::GraniteWall; case 89: return Item::Grass; case 8: return Item::GrassBlock; case 372: return Item::GrassPath; case 32: return Item::Gravel; case 876: return Item::GrayBanner; case 723: return Item::GrayBed; case 357: return Item::GrayCarpet; case 471: return Item::GrayConcrete; case 487: return Item::GrayConcretePowder; case 701: return Item::GrayDye; case 455: return Item::GrayGlazedTerracotta; case 439: return Item::GrayShulkerBox; case 386: return Item::GrayStainedGlass; case 402: return Item::GrayStainedGlassPane; case 338: return Item::GrayTerracotta; case 102: return Item::GrayWool; case 882: return Item::GreenBanner; case 729: return Item::GreenBed; case 363: return Item::GreenCarpet; case 477: return Item::GreenConcrete; case 493: return Item::GreenConcretePowder; case 695: return Item::GreenDye; case 461: return Item::GreenGlazedTerracotta; case 445: return Item::GreenShulkerBox; case 392: return Item::GreenStainedGlass; case 408: return Item::GreenStainedGlassPane; case 344: return Item::GreenTerracotta; case 108: return Item::GreenWool; case 940: return Item::Grindstone; case 777: return Item::GuardianSpawnEgg; case 612: return Item::Gunpowder; case 349: return Item::HayBale; case 924: return Item::HeartOfTheSea; case 319: return Item::HeavyWeightedPressurePlate; case 778: return Item::HoglinSpawnEgg; case 955: return Item::HoneyBlock; case 954: return Item::HoneyBottle; case 951: return Item::Honeycomb; case 956: return Item::HoneycombBlock; case 323: return Item::Hopper; case 851: return Item::HopperMinecart; case 511: return Item::HornCoral; case 506: return Item::HornCoralBlock; case 521: return Item::HornCoralFan; case 779: return Item::HorseSpawnEgg; case 780: return Item::HuskSpawnEgg; case 203: return Item::Ice; case 239: return Item::InfestedChiseledStoneBricks; case 235: return Item::InfestedCobblestone; case 238: return Item::InfestedCrackedStoneBricks; case 237: return Item::InfestedMossyStoneBricks; case 234: return Item::InfestedStone; case 236: return Item::InfestedStoneBricks; case 693: return Item::InkSac; case 574: return Item::IronAxe; case 247: return Item::IronBars; case 137: return Item::IronBlock; case 633: return Item::IronBoots; case 631: return Item::IronChestplate; case 557: return Item::IronDoor; case 630: return Item::IronHelmet; case 615: return Item::IronHoe; case 860: return Item::IronHorseArmor; case 582: return Item::IronIngot; case 632: return Item::IronLeggings; case 905: return Item::IronNugget; case 34: return Item::IronOre; case 573: return Item::IronPickaxe; case 572: return Item::IronShovel; case 586: return Item::IronSword; case 348: return Item::IronTrapdoor; case 827: return Item::ItemFrame; case 225: return Item::JackOLantern; case 569: return Item::Jigsaw; case 207: return Item::Jukebox; case 900: return Item::JungleBoat; case 308: return Item::JungleButton; case 561: return Item::JungleDoor; case 211: return Item::JungleFence; case 255: return Item::JungleFenceGate; case 72: return Item::JungleLeaves; case 40: return Item::JungleLog; case 18: return Item::JunglePlanks; case 194: return Item::JunglePressurePlate; case 26: return Item::JungleSapling; case 655: return Item::JungleSign; case 141: return Item::JungleSlab; case 282: return Item::JungleStairs; case 229: return Item::JungleTrapdoor; case 64: return Item::JungleWood; case 134: return Item::Kelp; case 906: return Item::KnowledgeBook; case 186: return Item::Ladder; case 945: return Item::Lantern; case 79: return Item::LapisBlock; case 697: return Item::LapisLazuli; case 78: return Item::LapisOre; case 378: return Item::LargeFern; case 662: return Item::LavaBucket; case 864: return Item::Lead; case 668: return Item::Leather; case 625: return Item::LeatherBoots; case 623: return Item::LeatherChestplate; case 622: return Item::LeatherHelmet; case 863: return Item::LeatherHorseArmor; case 624: return Item::LeatherLeggings; case 941: return Item::Lectern; case 189: return Item::Lever; case 872: return Item::LightBlueBanner; case 719: return Item::LightBlueBed; case 353: return Item::LightBlueCarpet; case 467: return Item::LightBlueConcrete; case 483: return Item::LightBlueConcretePowder; case 705: return Item::LightBlueDye; case 451: return Item::LightBlueGlazedTerracotta; case 435: return Item::LightBlueShulkerBox; case 382: return Item::LightBlueStainedGlass; case 398: return Item::LightBlueStainedGlassPane; case 334: return Item::LightBlueTerracotta; case 98: return Item::LightBlueWool; case 877: return Item::LightGrayBanner; case 724: return Item::LightGrayBed; case 358: return Item::LightGrayCarpet; case 472: return Item::LightGrayConcrete; case 488: return Item::LightGrayConcretePowder; case 700: return Item::LightGrayDye; case 456: return Item::LightGrayGlazedTerracotta; case 440: return Item::LightGrayShulkerBox; case 387: return Item::LightGrayStainedGlass; case 403: return Item::LightGrayStainedGlassPane; case 339: return Item::LightGrayTerracotta; case 103: return Item::LightGrayWool; case 318: return Item::LightWeightedPressurePlate; case 374: return Item::Lilac; case 122: return Item::LilyOfTheValley; case 263: return Item::LilyPad; case 874: return Item::LimeBanner; case 721: return Item::LimeBed; case 355: return Item::LimeCarpet; case 469: return Item::LimeConcrete; case 485: return Item::LimeConcretePowder; case 703: return Item::LimeDye; case 453: return Item::LimeGlazedTerracotta; case 437: return Item::LimeShulkerBox; case 384: return Item::LimeStainedGlass; case 400: return Item::LimeStainedGlassPane; case 336: return Item::LimeTerracotta; case 100: return Item::LimeWool; case 895: return Item::LingeringPotion; case 781: return Item::LlamaSpawnEgg; case 957: return Item::Lodestone; case 927: return Item::Loom; case 871: return Item::MagentaBanner; case 718: return Item::MagentaBed; case 352: return Item::MagentaCarpet; case 466: return Item::MagentaConcrete; case 482: return Item::MagentaConcretePowder; case 706: return Item::MagentaDye; case 450: return Item::MagentaGlazedTerracotta; case 434: return Item::MagentaShulkerBox; case 381: return Item::MagentaStainedGlass; case 397: return Item::MagentaStainedGlassPane; case 333: return Item::MagentaTerracotta; case 97: return Item::MagentaWool; case 424: return Item::MagmaBlock; case 754: return Item::MagmaCream; case 782: return Item::MagmaCubeSpawnEgg; case 833: return Item::Map; case 250: return Item::Melon; case 738: return Item::MelonSeeds; case 735: return Item::MelonSlice; case 669: return Item::MilkBucket; case 663: return Item::Minecart; case 931: return Item::MojangBannerPattern; case 783: return Item::MooshroomSpawnEgg; case 169: return Item::MossyCobblestone; case 547: return Item::MossyCobblestoneSlab; case 533: return Item::MossyCobblestoneStairs; case 288: return Item::MossyCobblestoneWall; case 545: return Item::MossyStoneBrickSlab; case 531: return Item::MossyStoneBrickStairs; case 292: return Item::MossyStoneBrickWall; case 241: return Item::MossyStoneBricks; case 784: return Item::MuleSpawnEgg; case 246: return Item::MushroomStem; case 601: return Item::MushroomStew; case 910: return Item::MusicDiscBlocks; case 909: return Item::MusicDiscCat; case 911: return Item::MusicDiscChirp; case 912: return Item::MusicDiscFar; case 913: return Item::MusicDiscMall; case 914: return Item::MusicDiscMellohi; case 920: return Item::MusicDiscPigstep; case 915: return Item::MusicDiscStal; case 916: return Item::MusicDiscStrad; case 919: return Item::MusicDiscWait; case 917: return Item::MusicDiscWard; case 918: return Item::MusicDisc11; case 908: return Item::MusicDisc13; case 867: return Item::Mutton; case 262: return Item::Mycelium; case 865: return Item::NameTag; case 923: return Item::NautilusShell; case 848: return Item::NetherBrick; case 267: return Item::NetherBrickFence; case 154: return Item::NetherBrickSlab; case 268: return Item::NetherBrickStairs; case 295: return Item::NetherBrickWall; case 264: return Item::NetherBricks; case 36: return Item::NetherGoldOre; case 322: return Item::NetherQuartzOre; case 130: return Item::NetherSprouts; case 843: return Item::NetherStar; case 748: return Item::NetherWart; case 425: return Item::NetherWartBlock; case 609: return Item::NetheriteAxe; case 958: return Item::NetheriteBlock; case 645: return Item::NetheriteBoots; case 643: return Item::NetheriteChestplate; case 642: return Item::NetheriteHelmet; case 618: return Item::NetheriteHoe; case 584: return Item::NetheriteIngot; case 644: return Item::NetheriteLeggings; case 608: return Item::NetheritePickaxe; case 585: return Item::NetheriteScrap; case 607: return Item::NetheriteShovel; case 606: return Item::NetheriteSword; case 218: return Item::Netherrack; case 84: return Item::NoteBlock; case 667: return Item::OakBoat; case 305: return Item::OakButton; case 558: return Item::OakDoor; case 208: return Item::OakFence; case 252: return Item::OakFenceGate; case 69: return Item::OakLeaves; case 37: return Item::OakLog; case 15: return Item::OakPlanks; case 191: return Item::OakPressurePlate; case 23: return Item::OakSapling; case 652: return Item::OakSign; case 138: return Item::OakSlab; case 179: return Item::OakStairs; case 226: return Item::OakTrapdoor; case 61: return Item::OakWood; case 430: return Item::Observer; case 170: return Item::Obsidian; case 785: return Item::OcelotSpawnEgg; case 870: return Item::OrangeBanner; case 717: return Item::OrangeBed; case 351: return Item::OrangeCarpet; case 465: return Item::OrangeConcrete; case 481: return Item::OrangeConcretePowder; case 707: return Item::OrangeDye; case 449: return Item::OrangeGlazedTerracotta; case 433: return Item::OrangeShulkerBox; case 380: return Item::OrangeStainedGlass; case 396: return Item::OrangeStainedGlassPane; case 332: return Item::OrangeTerracotta; case 117: return Item::OrangeTulip; case 96: return Item::OrangeWool; case 120: return Item::OxeyeDaisy; case 368: return Item::PackedIce; case 649: return Item::Painting; case 786: return Item::PandaSpawnEgg; case 677: return Item::Paper; case 787: return Item::ParrotSpawnEgg; case 376: return Item::Peony; case 150: return Item::PetrifiedOakSlab; case 922: return Item::PhantomMembrane; case 788: return Item::PhantomSpawnEgg; case 789: return Item::PigSpawnEgg; case 933: return Item::PiglinBannerPattern; case 790: return Item::PiglinSpawnEgg; case 791: return Item::PillagerSpawnEgg; case 875: return Item::PinkBanner; case 722: return Item::PinkBed; case 356: return Item::PinkCarpet; case 470: return Item::PinkConcrete; case 486: return Item::PinkConcretePowder; case 702: return Item::PinkDye; case 454: return Item::PinkGlazedTerracotta; case 438: return Item::PinkShulkerBox; case 385: return Item::PinkStainedGlass; case 401: return Item::PinkStainedGlassPane; case 337: return Item::PinkTerracotta; case 119: return Item::PinkTulip; case 101: return Item::PinkWool; case 94: return Item::Piston; case 837: return Item::PlayerHead; case 11: return Item::Podzol; case 832: return Item::PoisonousPotato; case 792: return Item::PolarBearSpawnEgg; case 7: return Item::PolishedAndesite; case 554: return Item::PolishedAndesiteSlab; case 541: return Item::PolishedAndesiteStairs; case 222: return Item::PolishedBasalt; case 966: return Item::PolishedBlackstone; case 971: return Item::PolishedBlackstoneBrickSlab; case 972: return Item::PolishedBlackstoneBrickStairs; case 303: return Item::PolishedBlackstoneBrickWall; case 970: return Item::PolishedBlackstoneBricks; case 313: return Item::PolishedBlackstoneButton; case 199: return Item::PolishedBlackstonePressurePlate; case 967: return Item::PolishedBlackstoneSlab; case 968: return Item::PolishedBlackstoneStairs; case 302: return Item::PolishedBlackstoneWall; case 5: return Item::PolishedDiorite; case 546: return Item::PolishedDioriteSlab; case 532: return Item::PolishedDioriteStairs; case 3: return Item::PolishedGranite; case 543: return Item::PolishedGraniteSlab; case 529: return Item::PolishedGraniteStairs; case 887: return Item::PoppedChorusFruit; case 112: return Item::Poppy; case 647: return Item::Porkchop; case 830: return Item::Potato; case 749: return Item::Potion; case 85: return Item::PoweredRail; case 411: return Item::Prismarine; case 160: return Item::PrismarineBrickSlab; case 415: return Item::PrismarineBrickStairs; case 412: return Item::PrismarineBricks; case 853: return Item::PrismarineCrystals; case 852: return Item::PrismarineShard; case 159: return Item::PrismarineSlab; case 414: return Item::PrismarineStairs; case 290: return Item::PrismarineWall; case 690: return Item::Pufferfish; case 670: return Item::PufferfishBucket; case 793: return Item::PufferfishSpawnEgg; case 216: return Item::Pumpkin; case 844: return Item::PumpkinPie; case 737: return Item::PumpkinSeeds; case 879: return Item::PurpleBanner; case 726: return Item::PurpleBed; case 360: return Item::PurpleCarpet; case 474: return Item::PurpleConcrete; case 490: return Item::PurpleConcretePowder; case 698: return Item::PurpleDye; case 458: return Item::PurpleGlazedTerracotta; case 442: return Item::PurpleShulkerBox; case 389: return Item::PurpleStainedGlass; case 405: return Item::PurpleStainedGlassPane; case 341: return Item::PurpleTerracotta; case 105: return Item::PurpleWool; case 175: return Item::PurpurBlock; case 176: return Item::PurpurPillar; case 158: return Item::PurpurSlab; case 177: return Item::PurpurStairs; case 849: return Item::Quartz; case 325: return Item::QuartzBlock; case 326: return Item::QuartzBricks; case 327: return Item::QuartzPillar; case 155: return Item::QuartzSlab; case 328: return Item::QuartzStairs; case 854: return Item::Rabbit; case 857: return Item::RabbitFoot; case 858: return Item::RabbitHide; case 794: return Item::RabbitSpawnEgg; case 856: return Item::RabbitStew; case 187: return Item::Rail; case 795: return Item::RavagerSpawnEgg; case 883: return Item::RedBanner; case 730: return Item::RedBed; case 364: return Item::RedCarpet; case 478: return Item::RedConcrete; case 494: return Item::RedConcretePowder; case 694: return Item::RedDye; case 462: return Item::RedGlazedTerracotta; case 125: return Item::RedMushroom; case 245: return Item::RedMushroomBlock; case 553: return Item::RedNetherBrickSlab; case 540: return Item::RedNetherBrickStairs; case 297: return Item::RedNetherBrickWall; case 427: return Item::RedNetherBricks; case 31: return Item::RedSand; case 418: return Item::RedSandstone; case 156: return Item::RedSandstoneSlab; case 421: return Item::RedSandstoneStairs; case 291: return Item::RedSandstoneWall; case 446: return Item::RedShulkerBox; case 393: return Item::RedStainedGlass; case 409: return Item::RedStainedGlassPane; case 345: return Item::RedTerracotta; case 116: return Item::RedTulip; case 109: return Item::RedWool; case 665: return Item::Redstone; case 321: return Item::RedstoneBlock; case 274: return Item::RedstoneLamp; case 200: return Item::RedstoneOre; case 201: return Item::RedstoneTorch; case 566: return Item::Repeater; case 422: return Item::RepeatingCommandBlock; case 974: return Item::RespawnAnchor; case 375: return Item::RoseBush; case 743: return Item::RottenFlesh; case 664: return Item::Saddle; case 688: return Item::Salmon; case 671: return Item::SalmonBucket; case 796: return Item::SalmonSpawnEgg; case 30: return Item::Sand; case 81: return Item::Sandstone; case 148: return Item::SandstoneSlab; case 275: return Item::SandstoneStairs; case 298: return Item::SandstoneWall; case 556: return Item::Scaffolding; case 571: return Item::Scute; case 417: return Item::SeaLantern; case 93: return Item::SeaPickle; case 92: return Item::Seagrass; case 734: return Item::Shears; case 797: return Item::SheepSpawnEgg; case 896: return Item::Shield; case 950: return Item::Shroomlight; case 431: return Item::ShulkerBox; case 904: return Item::ShulkerShell; case 798: return Item::ShulkerSpawnEgg; case 799: return Item::SilverfishSpawnEgg; case 801: return Item::SkeletonHorseSpawnEgg; case 835: return Item::SkeletonSkull; case 800: return Item::SkeletonSpawnEgg; case 930: return Item::SkullBannerPattern; case 679: return Item::SlimeBall; case 371: return Item::SlimeBlock; case 802: return Item::SlimeSpawnEgg; case 942: return Item::SmithingTable; case 936: return Item::Smoker; case 162: return Item::SmoothQuartz; case 550: return Item::SmoothQuartzSlab; case 537: return Item::SmoothQuartzStairs; case 163: return Item::SmoothRedSandstone; case 544: return Item::SmoothRedSandstoneSlab; case 530: return Item::SmoothRedSandstoneStairs; case 164: return Item::SmoothSandstone; case 549: return Item::SmoothSandstoneSlab; case 536: return Item::SmoothSandstoneStairs; case 165: return Item::SmoothStone; case 147: return Item::SmoothStoneSlab; case 202: return Item::Snow; case 204: return Item::SnowBlock; case 666: return Item::Snowball; case 949: return Item::SoulCampfire; case 946: return Item::SoulLantern; case 219: return Item::SoulSand; case 220: return Item::SoulSoil; case 223: return Item::SoulTorch; case 178: return Item::Spawner; case 893: return Item::SpectralArrow; case 751: return Item::SpiderEye; case 803: return Item::SpiderSpawnEgg; case 892: return Item::SplashPotion; case 75: return Item::Sponge; case 898: return Item::SpruceBoat; case 306: return Item::SpruceButton; case 559: return Item::SpruceDoor; case 209: return Item::SpruceFence; case 253: return Item::SpruceFenceGate; case 70: return Item::SpruceLeaves; case 38: return Item::SpruceLog; case 16: return Item::SprucePlanks; case 192: return Item::SprucePressurePlate; case 24: return Item::SpruceSapling; case 653: return Item::SpruceSign; case 139: return Item::SpruceSlab; case 280: return Item::SpruceStairs; case 227: return Item::SpruceTrapdoor; case 62: return Item::SpruceWood; case 804: return Item::SquidSpawnEgg; case 599: return Item::Stick; case 87: return Item::StickyPiston; case 1: return Item::Stone; case 594: return Item::StoneAxe; case 153: return Item::StoneBrickSlab; case 261: return Item::StoneBrickStairs; case 294: return Item::StoneBrickWall; case 240: return Item::StoneBricks; case 304: return Item::StoneButton; case 614: return Item::StoneHoe; case 593: return Item::StonePickaxe; case 190: return Item::StonePressurePlate; case 592: return Item::StoneShovel; case 146: return Item::StoneSlab; case 535: return Item::StoneStairs; case 591: return Item::StoneSword; case 943: return Item::Stonecutter; case 805: return Item::StraySpawnEgg; case 806: return Item::StriderSpawnEgg; case 610: return Item::String; case 49: return Item::StrippedAcaciaLog; case 57: return Item::StrippedAcaciaWood; case 47: return Item::StrippedBirchLog; case 55: return Item::StrippedBirchWood; case 59: return Item::StrippedCrimsonHyphae; case 51: return Item::StrippedCrimsonStem; case 50: return Item::StrippedDarkOakLog; case 58: return Item::StrippedDarkOakWood; case 48: return Item::StrippedJungleLog; case 56: return Item::StrippedJungleWood; case 45: return Item::StrippedOakLog; case 53: return Item::StrippedOakWood; case 46: return Item::StrippedSpruceLog; case 54: return Item::StrippedSpruceWood; case 60: return Item::StrippedWarpedHyphae; case 52: return Item::StrippedWarpedStem; case 568: return Item::StructureBlock; case 429: return Item::StructureVoid; case 714: return Item::Sugar; case 133: return Item::SugarCane; case 373: return Item::Sunflower; case 926: return Item::SuspiciousStew; case 947: return Item::SweetBerries; case 377: return Item::TallGrass; case 960: return Item::Target; case 366: return Item::Terracotta; case 894: return Item::TippedArrow; case 167: return Item::TNT; case 850: return Item::TNTMinecart; case 171: return Item::Torch; case 903: return Item::TotemOfUndying; case 807: return Item::TraderLlamaSpawnEgg; case 317: return Item::TrappedChest; case 921: return Item::Trident; case 278: return Item::TripwireHook; case 689: return Item::TropicalFish; case 673: return Item::TropicalFishBucket; case 808: return Item::TropicalFishSpawnEgg; case 507: return Item::TubeCoral; case 502: return Item::TubeCoralBlock; case 517: return Item::TubeCoralFan; case 496: return Item::TurtleEgg; case 570: return Item::TurtleHelmet; case 809: return Item::TurtleSpawnEgg; case 132: return Item::TwistingVines; case 810: return Item::VexSpawnEgg; case 811: return Item::VillagerSpawnEgg; case 812: return Item::VindicatorSpawnEgg; case 251: return Item::Vine; case 813: return Item::WanderingTraderSpawnEgg; case 312: return Item::WarpedButton; case 565: return Item::WarpedDoor; case 215: return Item::WarpedFence; case 259: return Item::WarpedFenceGate; case 127: return Item::WarpedFungus; case 842: return Item::WarpedFungusOnA_stick; case 68: return Item::WarpedHyphae; case 13: return Item::WarpedNylium; case 22: return Item::WarpedPlanks; case 198: return Item::WarpedPressurePlate; case 129: return Item::WarpedRoots; case 659: return Item::WarpedSign; case 145: return Item::WarpedSlab; case 284: return Item::WarpedStairs; case 44: return Item::WarpedStem; case 233: return Item::WarpedTrapdoor; case 426: return Item::WarpedWartBlock; case 661: return Item::WaterBucket; case 131: return Item::WeepingVines; case 76: return Item::WetSponge; case 620: return Item::Wheat; case 619: return Item::WheatSeeds; case 869: return Item::WhiteBanner; case 716: return Item::WhiteBed; case 350: return Item::WhiteCarpet; case 464: return Item::WhiteConcrete; case 480: return Item::WhiteConcretePowder; case 712: return Item::WhiteDye; case 448: return Item::WhiteGlazedTerracotta; case 432: return Item::WhiteShulkerBox; case 379: return Item::WhiteStainedGlass; case 395: return Item::WhiteStainedGlassPane; case 331: return Item::WhiteTerracotta; case 118: return Item::WhiteTulip; case 95: return Item::WhiteWool; case 814: return Item::WitchSpawnEgg; case 123: return Item::WitherRose; case 836: return Item::WitherSkeletonSkull; case 815: return Item::WitherSkeletonSpawnEgg; case 816: return Item::WolfSpawnEgg; case 590: return Item::WoodenAxe; case 613: return Item::WoodenHoe; case 589: return Item::WoodenPickaxe; case 588: return Item::WoodenShovel; case 587: return Item::WoodenSword; case 824: return Item::WritableBook; case 825: return Item::WrittenBook; case 873: return Item::YellowBanner; case 720: return Item::YellowBed; case 354: return Item::YellowCarpet; case 468: return Item::YellowConcrete; case 484: return Item::YellowConcretePowder; case 704: return Item::YellowDye; case 452: return Item::YellowGlazedTerracotta; case 436: return Item::YellowShulkerBox; case 383: return Item::YellowStainedGlass; case 399: return Item::YellowStainedGlassPane; case 335: return Item::YellowTerracotta; case 99: return Item::YellowWool; case 817: return Item::ZoglinSpawnEgg; case 838: return Item::ZombieHead; case 819: return Item::ZombieHorseSpawnEgg; case 818: return Item::ZombieSpawnEgg; case 820: return Item::ZombieVillagerSpawnEgg; case 821: return Item::ZombiePigmanSpawnEgg; default: return Item::Air; } } } ================================================ FILE: src/Protocol/Palettes/Palette_1_16.h ================================================ #pragma once #include "BlockState.h" #include "Registries/Items.h" #include "Registries/CustomStatistics.h" namespace Palette_1_16 { UInt32 From(BlockState Block); UInt32 From(Item ID); UInt32 From(CustomStatistic ID); Item ToItem(UInt32 ID); } ================================================ FILE: src/Protocol/Palettes/Upgrade.cpp ================================================ #include "Globals.h" #include "Upgrade.h" #include "Registries/BlockStates.h" namespace PaletteUpgrade { BlockState FromBlock(const BLOCKTYPE Block, const NIBBLETYPE Meta) { using namespace Block; switch ((Block << 4) | Meta) { case (0 << 4) | 0: return Air::Air(); case (1 << 4) | 0: return Stone::Stone(); case (1 << 4) | 1: return Granite::Granite(); case (1 << 4) | 2: return PolishedGranite::PolishedGranite(); case (1 << 4) | 3: return Diorite::Diorite(); case (1 << 4) | 4: return PolishedDiorite::PolishedDiorite(); case (1 << 4) | 5: return Andesite::Andesite(); case (1 << 4) | 6: return PolishedAndesite::PolishedAndesite(); case (2 << 4) | 0: return GrassBlock::GrassBlock(false); case (3 << 4) | 0: return Dirt::Dirt(); case (3 << 4) | 1: return CoarseDirt::CoarseDirt(); case (3 << 4) | 2: return Podzol::Podzol(false); case (4 << 4) | 0: return Cobblestone::Cobblestone(); case (5 << 4) | 0: return OakPlanks::OakPlanks(); case (5 << 4) | 1: return SprucePlanks::SprucePlanks(); case (5 << 4) | 2: return BirchPlanks::BirchPlanks(); case (5 << 4) | 3: return JunglePlanks::JunglePlanks(); case (5 << 4) | 4: return AcaciaPlanks::AcaciaPlanks(); case (5 << 4) | 5: return DarkOakPlanks::DarkOakPlanks(); case (6 << 4) | 0: return OakSapling::OakSapling(0); case (6 << 4) | 1: return SpruceSapling::SpruceSapling(0); case (6 << 4) | 2: return BirchSapling::BirchSapling(0); case (6 << 4) | 3: return JungleSapling::JungleSapling(0); case (6 << 4) | 4: return AcaciaSapling::AcaciaSapling(0); case (6 << 4) | 5: return DarkOakSapling::DarkOakSapling(0); case (6 << 4) | 8: return OakSapling::OakSapling(1); case (6 << 4) | 9: return SpruceSapling::SpruceSapling(1); case (6 << 4) | 10: return BirchSapling::BirchSapling(1); case (6 << 4) | 11: return JungleSapling::JungleSapling(1); case (6 << 4) | 12: return AcaciaSapling::AcaciaSapling(1); case (6 << 4) | 13: return DarkOakSapling::DarkOakSapling(1); case (7 << 4) | 0: return Bedrock::Bedrock(); case (8 << 4) | 0: return Water::Water(0); case (8 << 4) | 1: return Water::Water(1); case (8 << 4) | 2: return Water::Water(2); case (8 << 4) | 3: return Water::Water(3); case (8 << 4) | 4: return Water::Water(4); case (8 << 4) | 5: return Water::Water(5); case (8 << 4) | 6: return Water::Water(6); case (8 << 4) | 7: return Water::Water(7); case (8 << 4) | 8: return Water::Water(8); case (8 << 4) | 9: return Water::Water(9); case (8 << 4) | 10: return Water::Water(10); case (8 << 4) | 11: return Water::Water(11); case (8 << 4) | 12: return Water::Water(12); case (8 << 4) | 13: return Water::Water(13); case (8 << 4) | 14: return Water::Water(14); case (8 << 4) | 15: return Water::Water(15); case (9 << 4) | 0: return Water::Water(0); case (9 << 4) | 1: return Water::Water(1); case (9 << 4) | 2: return Water::Water(2); case (9 << 4) | 3: return Water::Water(3); case (9 << 4) | 4: return Water::Water(4); case (9 << 4) | 5: return Water::Water(5); case (9 << 4) | 6: return Water::Water(6); case (9 << 4) | 7: return Water::Water(7); case (9 << 4) | 8: return Water::Water(8); case (9 << 4) | 9: return Water::Water(9); case (9 << 4) | 10: return Water::Water(10); case (9 << 4) | 11: return Water::Water(11); case (9 << 4) | 12: return Water::Water(12); case (9 << 4) | 13: return Water::Water(13); case (9 << 4) | 14: return Water::Water(14); case (9 << 4) | 15: return Water::Water(15); case (10 << 4) | 0: return Lava::Lava(0); case (10 << 4) | 1: return Lava::Lava(1); case (10 << 4) | 2: return Lava::Lava(2); case (10 << 4) | 3: return Lava::Lava(3); case (10 << 4) | 4: return Lava::Lava(4); case (10 << 4) | 5: return Lava::Lava(5); case (10 << 4) | 6: return Lava::Lava(6); case (10 << 4) | 7: return Lava::Lava(7); case (10 << 4) | 8: return Lava::Lava(8); case (10 << 4) | 9: return Lava::Lava(9); case (10 << 4) | 10: return Lava::Lava(10); case (10 << 4) | 11: return Lava::Lava(11); case (10 << 4) | 12: return Lava::Lava(12); case (10 << 4) | 13: return Lava::Lava(13); case (10 << 4) | 14: return Lava::Lava(14); case (10 << 4) | 15: return Lava::Lava(15); case (11 << 4) | 0: return Lava::Lava(0); case (11 << 4) | 1: return Lava::Lava(1); case (11 << 4) | 2: return Lava::Lava(2); case (11 << 4) | 3: return Lava::Lava(3); case (11 << 4) | 4: return Lava::Lava(4); case (11 << 4) | 5: return Lava::Lava(5); case (11 << 4) | 6: return Lava::Lava(6); case (11 << 4) | 7: return Lava::Lava(7); case (11 << 4) | 8: return Lava::Lava(8); case (11 << 4) | 9: return Lava::Lava(9); case (11 << 4) | 10: return Lava::Lava(10); case (11 << 4) | 11: return Lava::Lava(11); case (11 << 4) | 12: return Lava::Lava(12); case (11 << 4) | 13: return Lava::Lava(13); case (11 << 4) | 14: return Lava::Lava(14); case (11 << 4) | 15: return Lava::Lava(15); case (12 << 4) | 0: return Sand::Sand(); case (12 << 4) | 1: return RedSand::RedSand(); case (13 << 4) | 0: return Gravel::Gravel(); case (14 << 4) | 0: return GoldOre::GoldOre(); case (15 << 4) | 0: return IronOre::IronOre(); case (16 << 4) | 0: return CoalOre::CoalOre(); case (17 << 4) | 0: return OakLog::OakLog(OakLog::Axis::Y); case (17 << 4) | 1: return SpruceLog::SpruceLog(SpruceLog::Axis::Y); case (17 << 4) | 2: return BirchLog::BirchLog(BirchLog::Axis::Y); case (17 << 4) | 3: return JungleLog::JungleLog(JungleLog::Axis::Y); case (17 << 4) | 4: return OakLog::OakLog(OakLog::Axis::X); case (17 << 4) | 5: return SpruceLog::SpruceLog(SpruceLog::Axis::X); case (17 << 4) | 6: return BirchLog::BirchLog(BirchLog::Axis::X); case (17 << 4) | 7: return JungleLog::JungleLog(JungleLog::Axis::X); case (17 << 4) | 8: return OakLog::OakLog(OakLog::Axis::Z); case (17 << 4) | 9: return SpruceLog::SpruceLog(SpruceLog::Axis::Z); case (17 << 4) | 10: return BirchLog::BirchLog(BirchLog::Axis::Z); case (17 << 4) | 11: return JungleLog::JungleLog(JungleLog::Axis::Z); case (17 << 4) | 12: return OakWood::OakWood(); case (17 << 4) | 13: return SpruceWood::SpruceWood(); case (17 << 4) | 14: return BirchWood::BirchWood(); case (17 << 4) | 15: return JungleWood::JungleWood(); case (18 << 4) | 0: return OakLeaves::OakLeaves(false, true); case (18 << 4) | 1: return SpruceLeaves::SpruceLeaves(false, true); case (18 << 4) | 2: return BirchLeaves::BirchLeaves(false, true); case (18 << 4) | 3: return JungleLeaves::JungleLeaves(false, true); case (18 << 4) | 4: return OakLeaves::OakLeaves(false, false); case (18 << 4) | 5: return SpruceLeaves::SpruceLeaves(false, false); case (18 << 4) | 6: return BirchLeaves::BirchLeaves(false, false); case (18 << 4) | 7: return JungleLeaves::JungleLeaves(false, false); case (18 << 4) | 8: return OakLeaves::OakLeaves(true, true); case (18 << 4) | 9: return SpruceLeaves::SpruceLeaves(true, true); case (18 << 4) | 10: return BirchLeaves::BirchLeaves(true, true); case (18 << 4) | 11: return JungleLeaves::JungleLeaves(true, true); case (18 << 4) | 12: return OakLeaves::OakLeaves(true, false); case (18 << 4) | 13: return SpruceLeaves::SpruceLeaves(true, false); case (18 << 4) | 14: return BirchLeaves::BirchLeaves(true, false); case (18 << 4) | 15: return JungleLeaves::JungleLeaves(true, false); case (19 << 4) | 0: return Sponge::Sponge(); case (19 << 4) | 1: return WetSponge::WetSponge(); case (20 << 4) | 0: return Glass::Glass(); case (21 << 4) | 0: return LapisOre::LapisOre(); case (22 << 4) | 0: return LapisBlock::LapisBlock(); case (23 << 4) | 0: return Dispenser::Dispenser(eBlockFace::BLOCK_FACE_YM, false); case (23 << 4) | 1: return Dispenser::Dispenser(eBlockFace::BLOCK_FACE_YP, false); case (23 << 4) | 2: return Dispenser::Dispenser(eBlockFace::BLOCK_FACE_ZM, false); case (23 << 4) | 3: return Dispenser::Dispenser(eBlockFace::BLOCK_FACE_ZP, false); case (23 << 4) | 4: return Dispenser::Dispenser(eBlockFace::BLOCK_FACE_XM, false); case (23 << 4) | 5: return Dispenser::Dispenser(eBlockFace::BLOCK_FACE_XP, false); case (23 << 4) | 8: return Dispenser::Dispenser(eBlockFace::BLOCK_FACE_YM, true); case (23 << 4) | 9: return Dispenser::Dispenser(eBlockFace::BLOCK_FACE_YP, true); case (23 << 4) | 10: return Dispenser::Dispenser(eBlockFace::BLOCK_FACE_ZM, true); case (23 << 4) | 11: return Dispenser::Dispenser(eBlockFace::BLOCK_FACE_ZP, true); case (23 << 4) | 12: return Dispenser::Dispenser(eBlockFace::BLOCK_FACE_XM, true); case (23 << 4) | 13: return Dispenser::Dispenser(eBlockFace::BLOCK_FACE_XP, true); case (24 << 4) | 0: return Sandstone::Sandstone(); case (24 << 4) | 1: return ChiseledSandstone::ChiseledSandstone(); case (24 << 4) | 2: return CutSandstone::CutSandstone(); case (25 << 4) | 0: return NoteBlock::NoteBlock(); case (26 << 4) | 0: return RedBed::RedBed(eBlockFace::BLOCK_FACE_ZP, false, RedBed::Part::Foot); case (26 << 4) | 1: return RedBed::RedBed(eBlockFace::BLOCK_FACE_XM, false, RedBed::Part::Foot); case (26 << 4) | 2: return RedBed::RedBed(eBlockFace::BLOCK_FACE_ZM, false, RedBed::Part::Foot); case (26 << 4) | 3: return RedBed::RedBed(eBlockFace::BLOCK_FACE_XP, false, RedBed::Part::Foot); case (26 << 4) | 8: return RedBed::RedBed(eBlockFace::BLOCK_FACE_ZP, false, RedBed::Part::Head); case (26 << 4) | 9: return RedBed::RedBed(eBlockFace::BLOCK_FACE_XM, false, RedBed::Part::Head); case (26 << 4) | 10: return RedBed::RedBed(eBlockFace::BLOCK_FACE_ZM, false, RedBed::Part::Head); case (26 << 4) | 11: return RedBed::RedBed(eBlockFace::BLOCK_FACE_XP, false, RedBed::Part::Head); case (26 << 4) | 12: return RedBed::RedBed(eBlockFace::BLOCK_FACE_ZP, true, RedBed::Part::Head); case (26 << 4) | 13: return RedBed::RedBed(eBlockFace::BLOCK_FACE_XM, true, RedBed::Part::Head); case (26 << 4) | 14: return RedBed::RedBed(eBlockFace::BLOCK_FACE_ZM, true, RedBed::Part::Head); case (26 << 4) | 15: return RedBed::RedBed(eBlockFace::BLOCK_FACE_XP, true, RedBed::Part::Head); case (27 << 4) | 0: return PoweredRail::PoweredRail(false, PoweredRail::Shape::NorthSouth); case (27 << 4) | 1: return PoweredRail::PoweredRail(false, PoweredRail::Shape::EastWest); case (27 << 4) | 2: return PoweredRail::PoweredRail(false, PoweredRail::Shape::AscendingEast); case (27 << 4) | 3: return PoweredRail::PoweredRail(false, PoweredRail::Shape::AscendingWest); case (27 << 4) | 4: return PoweredRail::PoweredRail(false, PoweredRail::Shape::AscendingNorth); case (27 << 4) | 5: return PoweredRail::PoweredRail(false, PoweredRail::Shape::AscendingSouth); case (27 << 4) | 8: return PoweredRail::PoweredRail(true, PoweredRail::Shape::NorthSouth); case (27 << 4) | 9: return PoweredRail::PoweredRail(true, PoweredRail::Shape::EastWest); case (27 << 4) | 10: return PoweredRail::PoweredRail(true, PoweredRail::Shape::AscendingEast); case (27 << 4) | 11: return PoweredRail::PoweredRail(true, PoweredRail::Shape::AscendingWest); case (27 << 4) | 12: return PoweredRail::PoweredRail(true, PoweredRail::Shape::AscendingNorth); case (27 << 4) | 13: return PoweredRail::PoweredRail(true, PoweredRail::Shape::AscendingSouth); case (28 << 4) | 0: return DetectorRail::DetectorRail(false, DetectorRail::Shape::NorthSouth); case (28 << 4) | 1: return DetectorRail::DetectorRail(false, DetectorRail::Shape::EastWest); case (28 << 4) | 2: return DetectorRail::DetectorRail(false, DetectorRail::Shape::AscendingEast); case (28 << 4) | 3: return DetectorRail::DetectorRail(false, DetectorRail::Shape::AscendingWest); case (28 << 4) | 4: return DetectorRail::DetectorRail(false, DetectorRail::Shape::AscendingNorth); case (28 << 4) | 5: return DetectorRail::DetectorRail(false, DetectorRail::Shape::AscendingSouth); case (28 << 4) | 8: return DetectorRail::DetectorRail(true, DetectorRail::Shape::NorthSouth); case (28 << 4) | 9: return DetectorRail::DetectorRail(true, DetectorRail::Shape::EastWest); case (28 << 4) | 10: return DetectorRail::DetectorRail(true, DetectorRail::Shape::AscendingEast); case (28 << 4) | 11: return DetectorRail::DetectorRail(true, DetectorRail::Shape::AscendingWest); case (28 << 4) | 12: return DetectorRail::DetectorRail(true, DetectorRail::Shape::AscendingNorth); case (28 << 4) | 13: return DetectorRail::DetectorRail(true, DetectorRail::Shape::AscendingSouth); case (29 << 4) | 0: return StickyPiston::StickyPiston(false, eBlockFace::BLOCK_FACE_YM); case (29 << 4) | 1: return StickyPiston::StickyPiston(false, eBlockFace::BLOCK_FACE_YP); case (29 << 4) | 2: return StickyPiston::StickyPiston(false, eBlockFace::BLOCK_FACE_ZM); case (29 << 4) | 3: return StickyPiston::StickyPiston(false, eBlockFace::BLOCK_FACE_ZP); case (29 << 4) | 4: return StickyPiston::StickyPiston(false, eBlockFace::BLOCK_FACE_XM); case (29 << 4) | 5: return StickyPiston::StickyPiston(false, eBlockFace::BLOCK_FACE_XP); case (29 << 4) | 8: return StickyPiston::StickyPiston(true, eBlockFace::BLOCK_FACE_YM); case (29 << 4) | 9: return StickyPiston::StickyPiston(true, eBlockFace::BLOCK_FACE_YP); case (29 << 4) | 10: return StickyPiston::StickyPiston(true, eBlockFace::BLOCK_FACE_ZM); case (29 << 4) | 11: return StickyPiston::StickyPiston(true, eBlockFace::BLOCK_FACE_ZP); case (29 << 4) | 12: return StickyPiston::StickyPiston(true, eBlockFace::BLOCK_FACE_XM); case (29 << 4) | 13: return StickyPiston::StickyPiston(true, eBlockFace::BLOCK_FACE_XP); case (30 << 4) | 0: return Cobweb::Cobweb(); case (31 << 4) | 0: return DeadBush::DeadBush(); case (31 << 4) | 1: return Grass::Grass(); case (31 << 4) | 2: return Fern::Fern(); case (32 << 4) | 0: return DeadBush::DeadBush(); case (33 << 4) | 0: return Piston::Piston(false, eBlockFace::BLOCK_FACE_YM); case (33 << 4) | 1: return Piston::Piston(false, eBlockFace::BLOCK_FACE_YP); case (33 << 4) | 2: return Piston::Piston(false, eBlockFace::BLOCK_FACE_ZM); case (33 << 4) | 3: return Piston::Piston(false, eBlockFace::BLOCK_FACE_ZP); case (33 << 4) | 4: return Piston::Piston(false, eBlockFace::BLOCK_FACE_XM); case (33 << 4) | 5: return Piston::Piston(false, eBlockFace::BLOCK_FACE_XP); case (33 << 4) | 8: return Piston::Piston(true, eBlockFace::BLOCK_FACE_YM); case (33 << 4) | 9: return Piston::Piston(true, eBlockFace::BLOCK_FACE_YP); case (33 << 4) | 10: return Piston::Piston(true, eBlockFace::BLOCK_FACE_ZM); case (33 << 4) | 11: return Piston::Piston(true, eBlockFace::BLOCK_FACE_ZP); case (33 << 4) | 12: return Piston::Piston(true, eBlockFace::BLOCK_FACE_XM); case (33 << 4) | 13: return Piston::Piston(true, eBlockFace::BLOCK_FACE_XP); case (34 << 4) | 0: return PistonHead::PistonHead(eBlockFace::BLOCK_FACE_YM, false, PistonHead::Type::Normal); case (34 << 4) | 1: return PistonHead::PistonHead(eBlockFace::BLOCK_FACE_YP, false, PistonHead::Type::Normal); case (34 << 4) | 2: return PistonHead::PistonHead(eBlockFace::BLOCK_FACE_ZM, false, PistonHead::Type::Normal); case (34 << 4) | 3: return PistonHead::PistonHead(eBlockFace::BLOCK_FACE_ZP, false, PistonHead::Type::Normal); case (34 << 4) | 4: return PistonHead::PistonHead(eBlockFace::BLOCK_FACE_XM, false, PistonHead::Type::Normal); case (34 << 4) | 5: return PistonHead::PistonHead(eBlockFace::BLOCK_FACE_XP, false, PistonHead::Type::Normal); case (34 << 4) | 8: return PistonHead::PistonHead(eBlockFace::BLOCK_FACE_YM, false, PistonHead::Type::Sticky); case (34 << 4) | 9: return PistonHead::PistonHead(eBlockFace::BLOCK_FACE_YP, false, PistonHead::Type::Sticky); case (34 << 4) | 10: return PistonHead::PistonHead(eBlockFace::BLOCK_FACE_ZM, false, PistonHead::Type::Sticky); case (34 << 4) | 11: return PistonHead::PistonHead(eBlockFace::BLOCK_FACE_ZP, false, PistonHead::Type::Sticky); case (34 << 4) | 12: return PistonHead::PistonHead(eBlockFace::BLOCK_FACE_XM, false, PistonHead::Type::Sticky); case (34 << 4) | 13: return PistonHead::PistonHead(eBlockFace::BLOCK_FACE_XP, false, PistonHead::Type::Sticky); case (35 << 4) | 0: return WhiteWool::WhiteWool(); case (35 << 4) | 1: return OrangeWool::OrangeWool(); case (35 << 4) | 2: return MagentaWool::MagentaWool(); case (35 << 4) | 3: return LightBlueWool::LightBlueWool(); case (35 << 4) | 4: return YellowWool::YellowWool(); case (35 << 4) | 5: return LimeWool::LimeWool(); case (35 << 4) | 6: return PinkWool::PinkWool(); case (35 << 4) | 7: return GrayWool::GrayWool(); case (35 << 4) | 8: return LightGrayWool::LightGrayWool(); case (35 << 4) | 9: return CyanWool::CyanWool(); case (35 << 4) | 10: return PurpleWool::PurpleWool(); case (35 << 4) | 11: return BlueWool::BlueWool(); case (35 << 4) | 12: return BrownWool::BrownWool(); case (35 << 4) | 13: return GreenWool::GreenWool(); case (35 << 4) | 14: return RedWool::RedWool(); case (35 << 4) | 15: return BlackWool::BlackWool(); case (36 << 4) | 0: return MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_YM, MovingPiston::Type::Normal); case (36 << 4) | 1: return MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_YP, MovingPiston::Type::Normal); case (36 << 4) | 2: return MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_ZM, MovingPiston::Type::Normal); case (36 << 4) | 3: return MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_ZP, MovingPiston::Type::Normal); case (36 << 4) | 4: return MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_XM, MovingPiston::Type::Normal); case (36 << 4) | 5: return MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_XP, MovingPiston::Type::Normal); case (36 << 4) | 8: return MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_YM, MovingPiston::Type::Sticky); case (36 << 4) | 9: return MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_YP, MovingPiston::Type::Sticky); case (36 << 4) | 10: return MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_ZM, MovingPiston::Type::Sticky); case (36 << 4) | 11: return MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_ZP, MovingPiston::Type::Sticky); case (36 << 4) | 12: return MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_XM, MovingPiston::Type::Sticky); case (36 << 4) | 13: return MovingPiston::MovingPiston(eBlockFace::BLOCK_FACE_XP, MovingPiston::Type::Sticky); case (37 << 4) | 0: return Dandelion::Dandelion(); case (38 << 4) | 0: return Poppy::Poppy(); case (38 << 4) | 1: return BlueOrchid::BlueOrchid(); case (38 << 4) | 2: return Allium::Allium(); case (38 << 4) | 3: return AzureBluet::AzureBluet(); case (38 << 4) | 4: return RedTulip::RedTulip(); case (38 << 4) | 5: return OrangeTulip::OrangeTulip(); case (38 << 4) | 6: return WhiteTulip::WhiteTulip(); case (38 << 4) | 7: return PinkTulip::PinkTulip(); case (38 << 4) | 8: return OxeyeDaisy::OxeyeDaisy(); case (39 << 4) | 0: return BrownMushroom::BrownMushroom(); case (40 << 4) | 0: return RedMushroom::RedMushroom(); case (41 << 4) | 0: return GoldBlock::GoldBlock(); case (42 << 4) | 0: return IronBlock::IronBlock(); case (43 << 4) | 0: return StoneSlab::StoneSlab(StoneSlab::Type::Double); case (43 << 4) | 1: return SandstoneSlab::SandstoneSlab(SandstoneSlab::Type::Double); case (43 << 4) | 2: return PetrifiedOakSlab::PetrifiedOakSlab(PetrifiedOakSlab::Type::Double); case (43 << 4) | 3: return CobblestoneSlab::CobblestoneSlab(CobblestoneSlab::Type::Double); case (43 << 4) | 4: return BrickSlab::BrickSlab(BrickSlab::Type::Double); case (43 << 4) | 5: return StoneBrickSlab::StoneBrickSlab(StoneBrickSlab::Type::Double); case (43 << 4) | 6: return NetherBrickSlab::NetherBrickSlab(NetherBrickSlab::Type::Double); case (43 << 4) | 7: return QuartzSlab::QuartzSlab(QuartzSlab::Type::Double); case (43 << 4) | 8: return SmoothStone::SmoothStone(); case (43 << 4) | 9: return SmoothSandstone::SmoothSandstone(); case (43 << 4) | 10: return PetrifiedOakSlab::PetrifiedOakSlab(PetrifiedOakSlab::Type::Double); case (43 << 4) | 11: return CobblestoneSlab::CobblestoneSlab(CobblestoneSlab::Type::Double); case (43 << 4) | 12: return BrickSlab::BrickSlab(BrickSlab::Type::Double); case (43 << 4) | 13: return StoneBrickSlab::StoneBrickSlab(StoneBrickSlab::Type::Double); case (43 << 4) | 14: return NetherBrickSlab::NetherBrickSlab(NetherBrickSlab::Type::Double); case (43 << 4) | 15: return SmoothQuartz::SmoothQuartz(); case (44 << 4) | 0: return StoneSlab::StoneSlab(StoneSlab::Type::Bottom); case (44 << 4) | 1: return SandstoneSlab::SandstoneSlab(SandstoneSlab::Type::Bottom); case (44 << 4) | 2: return PetrifiedOakSlab::PetrifiedOakSlab(PetrifiedOakSlab::Type::Bottom); case (44 << 4) | 3: return CobblestoneSlab::CobblestoneSlab(CobblestoneSlab::Type::Bottom); case (44 << 4) | 4: return BrickSlab::BrickSlab(BrickSlab::Type::Bottom); case (44 << 4) | 5: return StoneBrickSlab::StoneBrickSlab(StoneBrickSlab::Type::Bottom); case (44 << 4) | 6: return NetherBrickSlab::NetherBrickSlab(NetherBrickSlab::Type::Bottom); case (44 << 4) | 7: return QuartzSlab::QuartzSlab(QuartzSlab::Type::Bottom); case (44 << 4) | 8: return StoneSlab::StoneSlab(StoneSlab::Type::Top); case (44 << 4) | 9: return SandstoneSlab::SandstoneSlab(SandstoneSlab::Type::Top); case (44 << 4) | 10: return PetrifiedOakSlab::PetrifiedOakSlab(PetrifiedOakSlab::Type::Top); case (44 << 4) | 11: return CobblestoneSlab::CobblestoneSlab(CobblestoneSlab::Type::Top); case (44 << 4) | 12: return BrickSlab::BrickSlab(BrickSlab::Type::Top); case (44 << 4) | 13: return StoneBrickSlab::StoneBrickSlab(StoneBrickSlab::Type::Top); case (44 << 4) | 14: return NetherBrickSlab::NetherBrickSlab(NetherBrickSlab::Type::Top); case (44 << 4) | 15: return QuartzSlab::QuartzSlab(QuartzSlab::Type::Top); case (45 << 4) | 0: return Bricks::Bricks(); case (46 << 4) | 0: return TNT::TNT(false); case (46 << 4) | 1: return TNT::TNT(true); case (47 << 4) | 0: return Bookshelf::Bookshelf(); case (48 << 4) | 0: return MossyCobblestone::MossyCobblestone(); case (49 << 4) | 0: return Obsidian::Obsidian(); case (50 << 4) | 1: return WallTorch::WallTorch(eBlockFace::BLOCK_FACE_XP); case (50 << 4) | 2: return WallTorch::WallTorch(eBlockFace::BLOCK_FACE_XM); case (50 << 4) | 3: return WallTorch::WallTorch(eBlockFace::BLOCK_FACE_ZP); case (50 << 4) | 4: return WallTorch::WallTorch(eBlockFace::BLOCK_FACE_ZM); case (50 << 4) | 5: return Torch::Torch(); case (51 << 4) | 0: return Fire::Fire(0, false, false, false, false, false); case (51 << 4) | 1: return Fire::Fire(1, false, false, false, false, false); case (51 << 4) | 2: return Fire::Fire(2, false, false, false, false, false); case (51 << 4) | 3: return Fire::Fire(3, false, false, false, false, false); case (51 << 4) | 4: return Fire::Fire(4, false, false, false, false, false); case (51 << 4) | 5: return Fire::Fire(5, false, false, false, false, false); case (51 << 4) | 6: return Fire::Fire(6, false, false, false, false, false); case (51 << 4) | 7: return Fire::Fire(7, false, false, false, false, false); case (51 << 4) | 8: return Fire::Fire(8, false, false, false, false, false); case (51 << 4) | 9: return Fire::Fire(9, false, false, false, false, false); case (51 << 4) | 10: return Fire::Fire(10, false, false, false, false, false); case (51 << 4) | 11: return Fire::Fire(11, false, false, false, false, false); case (51 << 4) | 12: return Fire::Fire(12, false, false, false, false, false); case (51 << 4) | 13: return Fire::Fire(13, false, false, false, false, false); case (51 << 4) | 14: return Fire::Fire(14, false, false, false, false, false); case (51 << 4) | 15: return Fire::Fire(15, false, false, false, false, false); case (52 << 4) | 0: return Spawner::Spawner(); case (53 << 4) | 0: return OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XP, OakStairs::Half::Bottom, OakStairs::Shape::Straight); case (53 << 4) | 1: return OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XM, OakStairs::Half::Bottom, OakStairs::Shape::Straight); case (53 << 4) | 2: return OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZP, OakStairs::Half::Bottom, OakStairs::Shape::Straight); case (53 << 4) | 3: return OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZM, OakStairs::Half::Bottom, OakStairs::Shape::Straight); case (53 << 4) | 4: return OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XP, OakStairs::Half::Top, OakStairs::Shape::Straight); case (53 << 4) | 5: return OakStairs::OakStairs(eBlockFace::BLOCK_FACE_XM, OakStairs::Half::Top, OakStairs::Shape::Straight); case (53 << 4) | 6: return OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZP, OakStairs::Half::Top, OakStairs::Shape::Straight); case (53 << 4) | 7: return OakStairs::OakStairs(eBlockFace::BLOCK_FACE_ZM, OakStairs::Half::Top, OakStairs::Shape::Straight); case (54 << 4) | 2: return Chest::Chest(eBlockFace::BLOCK_FACE_ZM, Chest::Type::Single); case (54 << 4) | 3: return Chest::Chest(eBlockFace::BLOCK_FACE_ZP, Chest::Type::Single); case (54 << 4) | 4: return Chest::Chest(eBlockFace::BLOCK_FACE_XM, Chest::Type::Single); case (54 << 4) | 5: return Chest::Chest(eBlockFace::BLOCK_FACE_XP, Chest::Type::Single); case (55 << 4) | 0: return RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 0, RedstoneWire::South::None, RedstoneWire::West::None); case (55 << 4) | 1: return RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 1, RedstoneWire::South::None, RedstoneWire::West::None); case (55 << 4) | 2: return RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 2, RedstoneWire::South::None, RedstoneWire::West::None); case (55 << 4) | 3: return RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 3, RedstoneWire::South::None, RedstoneWire::West::None); case (55 << 4) | 4: return RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 4, RedstoneWire::South::None, RedstoneWire::West::None); case (55 << 4) | 5: return RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 5, RedstoneWire::South::None, RedstoneWire::West::None); case (55 << 4) | 6: return RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 6, RedstoneWire::South::None, RedstoneWire::West::None); case (55 << 4) | 7: return RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 7, RedstoneWire::South::None, RedstoneWire::West::None); case (55 << 4) | 8: return RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 8, RedstoneWire::South::None, RedstoneWire::West::None); case (55 << 4) | 9: return RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 9, RedstoneWire::South::None, RedstoneWire::West::None); case (55 << 4) | 10: return RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 10, RedstoneWire::South::None, RedstoneWire::West::None); case (55 << 4) | 11: return RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 11, RedstoneWire::South::None, RedstoneWire::West::None); case (55 << 4) | 12: return RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 12, RedstoneWire::South::None, RedstoneWire::West::None); case (55 << 4) | 13: return RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 13, RedstoneWire::South::None, RedstoneWire::West::None); case (55 << 4) | 14: return RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 14, RedstoneWire::South::None, RedstoneWire::West::None); case (55 << 4) | 15: return RedstoneWire::RedstoneWire(RedstoneWire::East::None, RedstoneWire::North::None, 15, RedstoneWire::South::None, RedstoneWire::West::None); case (56 << 4) | 0: return DiamondOre::DiamondOre(); case (57 << 4) | 0: return DiamondBlock::DiamondBlock(); case (58 << 4) | 0: return CraftingTable::CraftingTable(); case (59 << 4) | 0: return Wheat::Wheat(0); case (59 << 4) | 1: return Wheat::Wheat(1); case (59 << 4) | 2: return Wheat::Wheat(2); case (59 << 4) | 3: return Wheat::Wheat(3); case (59 << 4) | 4: return Wheat::Wheat(4); case (59 << 4) | 5: return Wheat::Wheat(5); case (59 << 4) | 6: return Wheat::Wheat(6); case (59 << 4) | 7: return Wheat::Wheat(7); case (60 << 4) | 0: return Farmland::Farmland(0); case (60 << 4) | 1: return Farmland::Farmland(1); case (60 << 4) | 2: return Farmland::Farmland(2); case (60 << 4) | 3: return Farmland::Farmland(3); case (60 << 4) | 4: return Farmland::Farmland(4); case (60 << 4) | 5: return Farmland::Farmland(5); case (60 << 4) | 6: return Farmland::Farmland(6); case (60 << 4) | 7: return Farmland::Farmland(7); case (61 << 4) | 2: return Furnace::Furnace(eBlockFace::BLOCK_FACE_ZM, false); case (61 << 4) | 3: return Furnace::Furnace(eBlockFace::BLOCK_FACE_ZP, false); case (61 << 4) | 4: return Furnace::Furnace(eBlockFace::BLOCK_FACE_XM, false); case (61 << 4) | 5: return Furnace::Furnace(eBlockFace::BLOCK_FACE_XP, false); case (62 << 4) | 2: return Furnace::Furnace(eBlockFace::BLOCK_FACE_ZM, true); case (62 << 4) | 3: return Furnace::Furnace(eBlockFace::BLOCK_FACE_ZP, true); case (62 << 4) | 4: return Furnace::Furnace(eBlockFace::BLOCK_FACE_XM, true); case (62 << 4) | 5: return Furnace::Furnace(eBlockFace::BLOCK_FACE_XP, true); case (63 << 4) | 0: return OakSign::OakSign(0); case (63 << 4) | 1: return OakSign::OakSign(1); case (63 << 4) | 2: return OakSign::OakSign(2); case (63 << 4) | 3: return OakSign::OakSign(3); case (63 << 4) | 4: return OakSign::OakSign(4); case (63 << 4) | 5: return OakSign::OakSign(5); case (63 << 4) | 6: return OakSign::OakSign(6); case (63 << 4) | 7: return OakSign::OakSign(7); case (63 << 4) | 8: return OakSign::OakSign(8); case (63 << 4) | 9: return OakSign::OakSign(9); case (63 << 4) | 10: return OakSign::OakSign(10); case (63 << 4) | 11: return OakSign::OakSign(11); case (63 << 4) | 12: return OakSign::OakSign(12); case (63 << 4) | 13: return OakSign::OakSign(13); case (63 << 4) | 14: return OakSign::OakSign(14); case (63 << 4) | 15: return OakSign::OakSign(15); case (64 << 4) | 0: return OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Lower, OakDoor::Hinge::Right, false, false); case (64 << 4) | 1: return OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Lower, OakDoor::Hinge::Right, false, false); case (64 << 4) | 2: return OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Lower, OakDoor::Hinge::Right, false, false); case (64 << 4) | 3: return OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Lower, OakDoor::Hinge::Right, false, false); case (64 << 4) | 4: return OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Lower, OakDoor::Hinge::Right, true, false); case (64 << 4) | 5: return OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Lower, OakDoor::Hinge::Right, true, false); case (64 << 4) | 6: return OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Lower, OakDoor::Hinge::Right, true, false); case (64 << 4) | 7: return OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Lower, OakDoor::Hinge::Right, true, false); case (64 << 4) | 8: return OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Upper, OakDoor::Hinge::Left, false, false); case (64 << 4) | 9: return OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Upper, OakDoor::Hinge::Right, false, false); case (64 << 4) | 10: return OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Upper, OakDoor::Hinge::Left, false, true); case (64 << 4) | 11: return OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Upper, OakDoor::Hinge::Right, false, true); case (64 << 4) | 12: return OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XP, OakDoor::Half::Upper, OakDoor::Hinge::Left, true, false); case (64 << 4) | 13: return OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZP, OakDoor::Half::Upper, OakDoor::Hinge::Left, true, false); case (64 << 4) | 14: return OakDoor::OakDoor(eBlockFace::BLOCK_FACE_XM, OakDoor::Half::Upper, OakDoor::Hinge::Left, true, false); case (64 << 4) | 15: return OakDoor::OakDoor(eBlockFace::BLOCK_FACE_ZM, OakDoor::Half::Upper, OakDoor::Hinge::Left, true, false); case (65 << 4) | 2: return Ladder::Ladder(eBlockFace::BLOCK_FACE_ZM); case (65 << 4) | 3: return Ladder::Ladder(eBlockFace::BLOCK_FACE_ZP); case (65 << 4) | 4: return Ladder::Ladder(eBlockFace::BLOCK_FACE_XM); case (65 << 4) | 5: return Ladder::Ladder(eBlockFace::BLOCK_FACE_XP); case (66 << 4) | 0: return Rail::Rail(Rail::Shape::NorthSouth); case (66 << 4) | 1: return Rail::Rail(Rail::Shape::EastWest); case (66 << 4) | 2: return Rail::Rail(Rail::Shape::AscendingEast); case (66 << 4) | 3: return Rail::Rail(Rail::Shape::AscendingWest); case (66 << 4) | 4: return Rail::Rail(Rail::Shape::AscendingNorth); case (66 << 4) | 5: return Rail::Rail(Rail::Shape::AscendingSouth); case (66 << 4) | 6: return Rail::Rail(Rail::Shape::SouthEast); case (66 << 4) | 7: return Rail::Rail(Rail::Shape::SouthWest); case (66 << 4) | 8: return Rail::Rail(Rail::Shape::NorthWest); case (66 << 4) | 9: return Rail::Rail(Rail::Shape::NorthEast); case (67 << 4) | 0: return CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XP, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::Straight); case (67 << 4) | 1: return CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XM, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::Straight); case (67 << 4) | 2: return CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::Straight); case (67 << 4) | 3: return CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, CobblestoneStairs::Half::Bottom, CobblestoneStairs::Shape::Straight); case (67 << 4) | 4: return CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XP, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::Straight); case (67 << 4) | 5: return CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_XM, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::Straight); case (67 << 4) | 6: return CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZP, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::Straight); case (67 << 4) | 7: return CobblestoneStairs::CobblestoneStairs(eBlockFace::BLOCK_FACE_ZM, CobblestoneStairs::Half::Top, CobblestoneStairs::Shape::Straight); case (68 << 4) | 2: return OakWallSign::OakWallSign(eBlockFace::BLOCK_FACE_ZM); case (68 << 4) | 3: return OakWallSign::OakWallSign(eBlockFace::BLOCK_FACE_ZP); case (68 << 4) | 4: return OakWallSign::OakWallSign(eBlockFace::BLOCK_FACE_XM); case (68 << 4) | 5: return OakWallSign::OakWallSign(eBlockFace::BLOCK_FACE_XP); case (69 << 4) | 0: return Lever::Lever(Lever::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, false); case (69 << 4) | 1: return Lever::Lever(Lever::Face::Wall, eBlockFace::BLOCK_FACE_XP, false); case (69 << 4) | 2: return Lever::Lever(Lever::Face::Wall, eBlockFace::BLOCK_FACE_XM, false); case (69 << 4) | 3: return Lever::Lever(Lever::Face::Wall, eBlockFace::BLOCK_FACE_ZP, false); case (69 << 4) | 4: return Lever::Lever(Lever::Face::Wall, eBlockFace::BLOCK_FACE_ZM, false); case (69 << 4) | 5: return Lever::Lever(Lever::Face::Floor, eBlockFace::BLOCK_FACE_ZM, false); case (69 << 4) | 6: return Lever::Lever(Lever::Face::Floor, eBlockFace::BLOCK_FACE_XM, false); case (69 << 4) | 7: return Lever::Lever(Lever::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, false); case (69 << 4) | 8: return Lever::Lever(Lever::Face::Ceiling, eBlockFace::BLOCK_FACE_XM, true); case (69 << 4) | 9: return Lever::Lever(Lever::Face::Wall, eBlockFace::BLOCK_FACE_XP, true); case (69 << 4) | 10: return Lever::Lever(Lever::Face::Wall, eBlockFace::BLOCK_FACE_XM, true); case (69 << 4) | 11: return Lever::Lever(Lever::Face::Wall, eBlockFace::BLOCK_FACE_ZP, true); case (69 << 4) | 12: return Lever::Lever(Lever::Face::Wall, eBlockFace::BLOCK_FACE_ZM, true); case (69 << 4) | 13: return Lever::Lever(Lever::Face::Floor, eBlockFace::BLOCK_FACE_ZM, true); case (69 << 4) | 14: return Lever::Lever(Lever::Face::Floor, eBlockFace::BLOCK_FACE_XM, true); case (69 << 4) | 15: return Lever::Lever(Lever::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, true); case (70 << 4) | 0: return StonePressurePlate::StonePressurePlate(false); case (70 << 4) | 1: return StonePressurePlate::StonePressurePlate(true); case (71 << 4) | 0: return IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Lower, IronDoor::Hinge::Right, false, false); case (71 << 4) | 1: return IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Lower, IronDoor::Hinge::Right, false, false); case (71 << 4) | 2: return IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Lower, IronDoor::Hinge::Right, false, false); case (71 << 4) | 3: return IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Lower, IronDoor::Hinge::Right, false, false); case (71 << 4) | 4: return IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Lower, IronDoor::Hinge::Right, true, false); case (71 << 4) | 5: return IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Lower, IronDoor::Hinge::Right, true, false); case (71 << 4) | 6: return IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Lower, IronDoor::Hinge::Right, true, false); case (71 << 4) | 7: return IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Lower, IronDoor::Hinge::Right, true, false); case (71 << 4) | 8: return IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Upper, IronDoor::Hinge::Left, false, false); case (71 << 4) | 9: return IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Upper, IronDoor::Hinge::Right, false, false); case (71 << 4) | 10: return IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Upper, IronDoor::Hinge::Left, false, true); case (71 << 4) | 11: return IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Upper, IronDoor::Hinge::Right, false, true); case (71 << 4) | 12: return IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XP, IronDoor::Half::Upper, IronDoor::Hinge::Left, true, false); case (71 << 4) | 13: return IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZP, IronDoor::Half::Upper, IronDoor::Hinge::Left, true, false); case (71 << 4) | 14: return IronDoor::IronDoor(eBlockFace::BLOCK_FACE_XM, IronDoor::Half::Upper, IronDoor::Hinge::Left, true, false); case (71 << 4) | 15: return IronDoor::IronDoor(eBlockFace::BLOCK_FACE_ZM, IronDoor::Half::Upper, IronDoor::Hinge::Left, true, false); case (72 << 4) | 0: return OakPressurePlate::OakPressurePlate(false); case (72 << 4) | 1: return OakPressurePlate::OakPressurePlate(true); case (73 << 4) | 0: return RedstoneOre::RedstoneOre(false); case (74 << 4) | 0: return RedstoneOre::RedstoneOre(true); case (75 << 4) | 1: return RedstoneWallTorch::RedstoneWallTorch(eBlockFace::BLOCK_FACE_XP, false); case (75 << 4) | 2: return RedstoneWallTorch::RedstoneWallTorch(eBlockFace::BLOCK_FACE_XM, false); case (75 << 4) | 3: return RedstoneWallTorch::RedstoneWallTorch(eBlockFace::BLOCK_FACE_ZP, false); case (75 << 4) | 4: return RedstoneWallTorch::RedstoneWallTorch(eBlockFace::BLOCK_FACE_ZM, false); case (75 << 4) | 5: return RedstoneTorch::RedstoneTorch(false); case (76 << 4) | 1: return RedstoneWallTorch::RedstoneWallTorch(eBlockFace::BLOCK_FACE_XP, true); case (76 << 4) | 2: return RedstoneWallTorch::RedstoneWallTorch(eBlockFace::BLOCK_FACE_XM, true); case (76 << 4) | 3: return RedstoneWallTorch::RedstoneWallTorch(eBlockFace::BLOCK_FACE_ZP, true); case (76 << 4) | 4: return RedstoneWallTorch::RedstoneWallTorch(eBlockFace::BLOCK_FACE_ZM, true); case (76 << 4) | 5: return RedstoneTorch::RedstoneTorch(true); case (77 << 4) | 0: return StoneButton::StoneButton(StoneButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, false); case (77 << 4) | 1: return StoneButton::StoneButton(StoneButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, false); case (77 << 4) | 2: return StoneButton::StoneButton(StoneButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, false); case (77 << 4) | 3: return StoneButton::StoneButton(StoneButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, false); case (77 << 4) | 4: return StoneButton::StoneButton(StoneButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, false); case (77 << 4) | 5: return StoneButton::StoneButton(StoneButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, false); case (77 << 4) | 8: return StoneButton::StoneButton(StoneButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, true); case (77 << 4) | 9: return StoneButton::StoneButton(StoneButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, true); case (77 << 4) | 10: return StoneButton::StoneButton(StoneButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, true); case (77 << 4) | 11: return StoneButton::StoneButton(StoneButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, true); case (77 << 4) | 12: return StoneButton::StoneButton(StoneButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, true); case (77 << 4) | 13: return StoneButton::StoneButton(StoneButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, true); case (78 << 4) | 0: return Snow::Snow(1); case (78 << 4) | 1: return Snow::Snow(2); case (78 << 4) | 2: return Snow::Snow(3); case (78 << 4) | 3: return Snow::Snow(4); case (78 << 4) | 4: return Snow::Snow(5); case (78 << 4) | 5: return Snow::Snow(6); case (78 << 4) | 6: return Snow::Snow(7); case (78 << 4) | 7: return Snow::Snow(8); case (79 << 4) | 0: return Ice::Ice(); case (80 << 4) | 0: return SnowBlock::SnowBlock(); case (81 << 4) | 0: return Cactus::Cactus(0); case (81 << 4) | 1: return Cactus::Cactus(1); case (81 << 4) | 2: return Cactus::Cactus(2); case (81 << 4) | 3: return Cactus::Cactus(3); case (81 << 4) | 4: return Cactus::Cactus(4); case (81 << 4) | 5: return Cactus::Cactus(5); case (81 << 4) | 6: return Cactus::Cactus(6); case (81 << 4) | 7: return Cactus::Cactus(7); case (81 << 4) | 8: return Cactus::Cactus(8); case (81 << 4) | 9: return Cactus::Cactus(9); case (81 << 4) | 10: return Cactus::Cactus(10); case (81 << 4) | 11: return Cactus::Cactus(11); case (81 << 4) | 12: return Cactus::Cactus(12); case (81 << 4) | 13: return Cactus::Cactus(13); case (81 << 4) | 14: return Cactus::Cactus(14); case (81 << 4) | 15: return Cactus::Cactus(15); case (82 << 4) | 0: return Clay::Clay(); case (83 << 4) | 0: return SugarCane::SugarCane(0); case (83 << 4) | 1: return SugarCane::SugarCane(1); case (83 << 4) | 2: return SugarCane::SugarCane(2); case (83 << 4) | 3: return SugarCane::SugarCane(3); case (83 << 4) | 4: return SugarCane::SugarCane(4); case (83 << 4) | 5: return SugarCane::SugarCane(5); case (83 << 4) | 6: return SugarCane::SugarCane(6); case (83 << 4) | 7: return SugarCane::SugarCane(7); case (83 << 4) | 8: return SugarCane::SugarCane(8); case (83 << 4) | 9: return SugarCane::SugarCane(9); case (83 << 4) | 10: return SugarCane::SugarCane(10); case (83 << 4) | 11: return SugarCane::SugarCane(11); case (83 << 4) | 12: return SugarCane::SugarCane(12); case (83 << 4) | 13: return SugarCane::SugarCane(13); case (83 << 4) | 14: return SugarCane::SugarCane(14); case (83 << 4) | 15: return SugarCane::SugarCane(15); case (84 << 4) | 0: return Jukebox::Jukebox(false); case (84 << 4) | 1: return Jukebox::Jukebox(true); case (85 << 4) | 0: return OakFence::OakFence(false, false, false, false); case (86 << 4) | 0: return CarvedPumpkin::CarvedPumpkin(eBlockFace::BLOCK_FACE_ZP); case (86 << 4) | 1: return CarvedPumpkin::CarvedPumpkin(eBlockFace::BLOCK_FACE_XM); case (86 << 4) | 2: return CarvedPumpkin::CarvedPumpkin(eBlockFace::BLOCK_FACE_ZM); case (86 << 4) | 3: return CarvedPumpkin::CarvedPumpkin(eBlockFace::BLOCK_FACE_XP); case (87 << 4) | 0: return Netherrack::Netherrack(); case (88 << 4) | 0: return SoulSand::SoulSand(); case (89 << 4) | 0: return Glowstone::Glowstone(); case (90 << 4) | 1: return NetherPortal::NetherPortal(NetherPortal::Axis::X); case (90 << 4) | 2: return NetherPortal::NetherPortal(NetherPortal::Axis::Z); case (91 << 4) | 0: return JackOLantern::JackOLantern(eBlockFace::BLOCK_FACE_ZP); case (91 << 4) | 1: return JackOLantern::JackOLantern(eBlockFace::BLOCK_FACE_XM); case (91 << 4) | 2: return JackOLantern::JackOLantern(eBlockFace::BLOCK_FACE_ZM); case (91 << 4) | 3: return JackOLantern::JackOLantern(eBlockFace::BLOCK_FACE_XP); case (92 << 4) | 0: return Cake::Cake(0); case (92 << 4) | 1: return Cake::Cake(1); case (92 << 4) | 2: return Cake::Cake(2); case (92 << 4) | 3: return Cake::Cake(3); case (92 << 4) | 4: return Cake::Cake(4); case (92 << 4) | 5: return Cake::Cake(5); case (92 << 4) | 6: return Cake::Cake(6); case (93 << 4) | 0: return Repeater::Repeater(1, eBlockFace::BLOCK_FACE_ZP, false, false); case (93 << 4) | 1: return Repeater::Repeater(1, eBlockFace::BLOCK_FACE_XM, false, false); case (93 << 4) | 2: return Repeater::Repeater(1, eBlockFace::BLOCK_FACE_ZM, false, false); case (93 << 4) | 3: return Repeater::Repeater(1, eBlockFace::BLOCK_FACE_XP, false, false); case (93 << 4) | 4: return Repeater::Repeater(2, eBlockFace::BLOCK_FACE_ZP, false, false); case (93 << 4) | 5: return Repeater::Repeater(2, eBlockFace::BLOCK_FACE_XM, false, false); case (93 << 4) | 6: return Repeater::Repeater(2, eBlockFace::BLOCK_FACE_ZM, false, false); case (93 << 4) | 7: return Repeater::Repeater(2, eBlockFace::BLOCK_FACE_XP, false, false); case (93 << 4) | 8: return Repeater::Repeater(3, eBlockFace::BLOCK_FACE_ZP, false, false); case (93 << 4) | 9: return Repeater::Repeater(3, eBlockFace::BLOCK_FACE_XM, false, false); case (93 << 4) | 10: return Repeater::Repeater(3, eBlockFace::BLOCK_FACE_ZM, false, false); case (93 << 4) | 11: return Repeater::Repeater(3, eBlockFace::BLOCK_FACE_XP, false, false); case (93 << 4) | 12: return Repeater::Repeater(4, eBlockFace::BLOCK_FACE_ZP, false, false); case (93 << 4) | 13: return Repeater::Repeater(4, eBlockFace::BLOCK_FACE_XM, false, false); case (93 << 4) | 14: return Repeater::Repeater(4, eBlockFace::BLOCK_FACE_ZM, false, false); case (93 << 4) | 15: return Repeater::Repeater(4, eBlockFace::BLOCK_FACE_XP, false, false); case (94 << 4) | 0: return Repeater::Repeater(1, eBlockFace::BLOCK_FACE_ZP, false, true); case (94 << 4) | 1: return Repeater::Repeater(1, eBlockFace::BLOCK_FACE_XM, false, true); case (94 << 4) | 2: return Repeater::Repeater(1, eBlockFace::BLOCK_FACE_ZM, false, true); case (94 << 4) | 3: return Repeater::Repeater(1, eBlockFace::BLOCK_FACE_XP, false, true); case (94 << 4) | 4: return Repeater::Repeater(2, eBlockFace::BLOCK_FACE_ZP, false, true); case (94 << 4) | 5: return Repeater::Repeater(2, eBlockFace::BLOCK_FACE_XM, false, true); case (94 << 4) | 6: return Repeater::Repeater(2, eBlockFace::BLOCK_FACE_ZM, false, true); case (94 << 4) | 7: return Repeater::Repeater(2, eBlockFace::BLOCK_FACE_XP, false, true); case (94 << 4) | 8: return Repeater::Repeater(3, eBlockFace::BLOCK_FACE_ZP, false, true); case (94 << 4) | 9: return Repeater::Repeater(3, eBlockFace::BLOCK_FACE_XM, false, true); case (94 << 4) | 10: return Repeater::Repeater(3, eBlockFace::BLOCK_FACE_ZM, false, true); case (94 << 4) | 11: return Repeater::Repeater(3, eBlockFace::BLOCK_FACE_XP, false, true); case (94 << 4) | 12: return Repeater::Repeater(4, eBlockFace::BLOCK_FACE_ZP, false, true); case (94 << 4) | 13: return Repeater::Repeater(4, eBlockFace::BLOCK_FACE_XM, false, true); case (94 << 4) | 14: return Repeater::Repeater(4, eBlockFace::BLOCK_FACE_ZM, false, true); case (94 << 4) | 15: return Repeater::Repeater(4, eBlockFace::BLOCK_FACE_XP, false, true); case (95 << 4) | 0: return WhiteStainedGlass::WhiteStainedGlass(); case (95 << 4) | 1: return OrangeStainedGlass::OrangeStainedGlass(); case (95 << 4) | 2: return MagentaStainedGlass::MagentaStainedGlass(); case (95 << 4) | 3: return LightBlueStainedGlass::LightBlueStainedGlass(); case (95 << 4) | 4: return YellowStainedGlass::YellowStainedGlass(); case (95 << 4) | 5: return LimeStainedGlass::LimeStainedGlass(); case (95 << 4) | 6: return PinkStainedGlass::PinkStainedGlass(); case (95 << 4) | 7: return GrayStainedGlass::GrayStainedGlass(); case (95 << 4) | 8: return LightGrayStainedGlass::LightGrayStainedGlass(); case (95 << 4) | 9: return CyanStainedGlass::CyanStainedGlass(); case (95 << 4) | 10: return PurpleStainedGlass::PurpleStainedGlass(); case (95 << 4) | 11: return BlueStainedGlass::BlueStainedGlass(); case (95 << 4) | 12: return BrownStainedGlass::BrownStainedGlass(); case (95 << 4) | 13: return GreenStainedGlass::GreenStainedGlass(); case (95 << 4) | 14: return RedStainedGlass::RedStainedGlass(); case (95 << 4) | 15: return BlackStainedGlass::BlackStainedGlass(); case (96 << 4) | 0: return OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZM, OakTrapdoor::Half::Bottom, false, false); case (96 << 4) | 1: return OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZP, OakTrapdoor::Half::Bottom, false, false); case (96 << 4) | 2: return OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XM, OakTrapdoor::Half::Bottom, false, false); case (96 << 4) | 3: return OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XP, OakTrapdoor::Half::Bottom, false, false); case (96 << 4) | 4: return OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZM, OakTrapdoor::Half::Bottom, true, false); case (96 << 4) | 5: return OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZP, OakTrapdoor::Half::Bottom, true, false); case (96 << 4) | 6: return OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XM, OakTrapdoor::Half::Bottom, true, false); case (96 << 4) | 7: return OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XP, OakTrapdoor::Half::Bottom, true, false); case (96 << 4) | 8: return OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZM, OakTrapdoor::Half::Top, false, false); case (96 << 4) | 9: return OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZP, OakTrapdoor::Half::Top, false, false); case (96 << 4) | 10: return OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XM, OakTrapdoor::Half::Top, false, false); case (96 << 4) | 11: return OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XP, OakTrapdoor::Half::Top, false, false); case (96 << 4) | 12: return OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZM, OakTrapdoor::Half::Top, true, false); case (96 << 4) | 13: return OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_ZP, OakTrapdoor::Half::Top, true, false); case (96 << 4) | 14: return OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XM, OakTrapdoor::Half::Top, true, false); case (96 << 4) | 15: return OakTrapdoor::OakTrapdoor(eBlockFace::BLOCK_FACE_XP, OakTrapdoor::Half::Top, true, false); case (97 << 4) | 0: return InfestedStone::InfestedStone(); case (97 << 4) | 1: return InfestedCobblestone::InfestedCobblestone(); case (97 << 4) | 2: return InfestedStoneBricks::InfestedStoneBricks(); case (97 << 4) | 3: return InfestedMossyStoneBricks::InfestedMossyStoneBricks(); case (97 << 4) | 4: return InfestedCrackedStoneBricks::InfestedCrackedStoneBricks(); case (97 << 4) | 5: return InfestedChiseledStoneBricks::InfestedChiseledStoneBricks(); case (98 << 4) | 0: return StoneBricks::StoneBricks(); case (98 << 4) | 1: return MossyStoneBricks::MossyStoneBricks(); case (98 << 4) | 2: return CrackedStoneBricks::CrackedStoneBricks(); case (98 << 4) | 3: return ChiseledStoneBricks::ChiseledStoneBricks(); case (99 << 4) | 0: return BrownMushroomBlock::BrownMushroomBlock(false, false, false, false, false, false); case (99 << 4) | 1: return BrownMushroomBlock::BrownMushroomBlock(false, false, true, false, true, true); case (99 << 4) | 2: return BrownMushroomBlock::BrownMushroomBlock(false, false, true, false, true, false); case (99 << 4) | 3: return BrownMushroomBlock::BrownMushroomBlock(false, true, true, false, true, false); case (99 << 4) | 4: return BrownMushroomBlock::BrownMushroomBlock(false, false, false, false, true, true); case (99 << 4) | 5: return BrownMushroomBlock::BrownMushroomBlock(false, false, false, false, true, false); case (99 << 4) | 6: return BrownMushroomBlock::BrownMushroomBlock(false, true, false, false, true, false); case (99 << 4) | 7: return BrownMushroomBlock::BrownMushroomBlock(false, false, false, true, true, true); case (99 << 4) | 8: return BrownMushroomBlock::BrownMushroomBlock(false, false, false, true, true, false); case (99 << 4) | 9: return BrownMushroomBlock::BrownMushroomBlock(false, true, false, true, true, false); case (99 << 4) | 10: return MushroomStem::MushroomStem(false, true, true, true, false, true); case (99 << 4) | 11: return BrownMushroomBlock::BrownMushroomBlock(false, false, false, false, false, false); case (99 << 4) | 12: return BrownMushroomBlock::BrownMushroomBlock(false, false, false, false, false, false); case (99 << 4) | 13: return BrownMushroomBlock::BrownMushroomBlock(false, false, false, false, false, false); case (99 << 4) | 14: return BrownMushroomBlock::BrownMushroomBlock(true, true, true, true, true, true); case (99 << 4) | 15: return MushroomStem::MushroomStem(true, true, true, true, true, true); case (100 << 4) | 0: return RedMushroomBlock::RedMushroomBlock(false, false, false, false, false, false); case (100 << 4) | 1: return RedMushroomBlock::RedMushroomBlock(false, false, true, false, true, true); case (100 << 4) | 2: return RedMushroomBlock::RedMushroomBlock(false, false, true, false, true, false); case (100 << 4) | 3: return RedMushroomBlock::RedMushroomBlock(false, true, true, false, true, false); case (100 << 4) | 4: return RedMushroomBlock::RedMushroomBlock(false, false, false, false, true, true); case (100 << 4) | 5: return RedMushroomBlock::RedMushroomBlock(false, false, false, false, true, false); case (100 << 4) | 6: return RedMushroomBlock::RedMushroomBlock(false, true, false, false, true, false); case (100 << 4) | 7: return RedMushroomBlock::RedMushroomBlock(false, false, false, true, true, true); case (100 << 4) | 8: return RedMushroomBlock::RedMushroomBlock(false, false, false, true, true, false); case (100 << 4) | 9: return RedMushroomBlock::RedMushroomBlock(false, true, false, true, true, false); case (100 << 4) | 10: return MushroomStem::MushroomStem(false, true, true, true, false, true); case (100 << 4) | 11: return RedMushroomBlock::RedMushroomBlock(false, false, false, false, false, false); case (100 << 4) | 12: return RedMushroomBlock::RedMushroomBlock(false, false, false, false, false, false); case (100 << 4) | 13: return RedMushroomBlock::RedMushroomBlock(false, false, false, false, false, false); case (100 << 4) | 14: return RedMushroomBlock::RedMushroomBlock(true, true, true, true, true, true); case (100 << 4) | 15: return MushroomStem::MushroomStem(true, true, true, true, true, true); case (101 << 4) | 0: return IronBars::IronBars(false, false, false, false); case (102 << 4) | 0: return GlassPane::GlassPane(false, false, false, false); case (103 << 4) | 0: return Melon::Melon(); case (104 << 4) | 0: return PumpkinStem::PumpkinStem(0); case (104 << 4) | 1: return PumpkinStem::PumpkinStem(1); case (104 << 4) | 2: return PumpkinStem::PumpkinStem(2); case (104 << 4) | 3: return PumpkinStem::PumpkinStem(3); case (104 << 4) | 4: return PumpkinStem::PumpkinStem(4); case (104 << 4) | 5: return PumpkinStem::PumpkinStem(5); case (104 << 4) | 6: return PumpkinStem::PumpkinStem(6); case (104 << 4) | 7: return PumpkinStem::PumpkinStem(7); case (105 << 4) | 0: return MelonStem::MelonStem(0); case (105 << 4) | 1: return MelonStem::MelonStem(1); case (105 << 4) | 2: return MelonStem::MelonStem(2); case (105 << 4) | 3: return MelonStem::MelonStem(3); case (105 << 4) | 4: return MelonStem::MelonStem(4); case (105 << 4) | 5: return MelonStem::MelonStem(5); case (105 << 4) | 6: return MelonStem::MelonStem(6); case (105 << 4) | 7: return MelonStem::MelonStem(7); case (106 << 4) | 0: return Vine::Vine(false, false, false, true, false); case (106 << 4) | 1: return Vine::Vine(false, false, true, true, false); case (106 << 4) | 2: return Vine::Vine(false, false, false, true, true); case (106 << 4) | 3: return Vine::Vine(false, false, true, true, true); case (106 << 4) | 4: return Vine::Vine(false, true, false, true, false); case (106 << 4) | 5: return Vine::Vine(false, true, true, true, false); case (106 << 4) | 6: return Vine::Vine(false, true, false, true, true); case (106 << 4) | 7: return Vine::Vine(false, true, true, true, true); case (106 << 4) | 8: return Vine::Vine(true, false, false, true, false); case (106 << 4) | 9: return Vine::Vine(true, false, true, true, false); case (106 << 4) | 10: return Vine::Vine(true, false, false, true, true); case (106 << 4) | 11: return Vine::Vine(true, false, true, true, true); case (106 << 4) | 12: return Vine::Vine(true, true, false, true, false); case (106 << 4) | 13: return Vine::Vine(true, true, true, true, false); case (106 << 4) | 14: return Vine::Vine(true, true, false, true, true); case (106 << 4) | 15: return Vine::Vine(true, true, true, true, true); case (107 << 4) | 0: return OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, false); case (107 << 4) | 1: return OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, false); case (107 << 4) | 2: return OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, false); case (107 << 4) | 3: return OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, false); case (107 << 4) | 4: return OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, false); case (107 << 4) | 5: return OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, false); case (107 << 4) | 6: return OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, false); case (107 << 4) | 7: return OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, false); case (107 << 4) | 8: return OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, true); case (107 << 4) | 9: return OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, true); case (107 << 4) | 10: return OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, true); case (107 << 4) | 11: return OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, true); case (107 << 4) | 12: return OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, true); case (107 << 4) | 13: return OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, true); case (107 << 4) | 14: return OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, true); case (107 << 4) | 15: return OakFenceGate::OakFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, true); case (108 << 4) | 0: return BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XP, BrickStairs::Half::Bottom, BrickStairs::Shape::Straight); case (108 << 4) | 1: return BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XM, BrickStairs::Half::Bottom, BrickStairs::Shape::Straight); case (108 << 4) | 2: return BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZP, BrickStairs::Half::Bottom, BrickStairs::Shape::Straight); case (108 << 4) | 3: return BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZM, BrickStairs::Half::Bottom, BrickStairs::Shape::Straight); case (108 << 4) | 4: return BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XP, BrickStairs::Half::Top, BrickStairs::Shape::Straight); case (108 << 4) | 5: return BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_XM, BrickStairs::Half::Top, BrickStairs::Shape::Straight); case (108 << 4) | 6: return BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZP, BrickStairs::Half::Top, BrickStairs::Shape::Straight); case (108 << 4) | 7: return BrickStairs::BrickStairs(eBlockFace::BLOCK_FACE_ZM, BrickStairs::Half::Top, BrickStairs::Shape::Straight); case (109 << 4) | 0: return StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XP, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::Straight); case (109 << 4) | 1: return StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XM, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::Straight); case (109 << 4) | 2: return StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::Straight); case (109 << 4) | 3: return StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, StoneBrickStairs::Half::Bottom, StoneBrickStairs::Shape::Straight); case (109 << 4) | 4: return StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XP, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::Straight); case (109 << 4) | 5: return StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_XM, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::Straight); case (109 << 4) | 6: return StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZP, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::Straight); case (109 << 4) | 7: return StoneBrickStairs::StoneBrickStairs(eBlockFace::BLOCK_FACE_ZM, StoneBrickStairs::Half::Top, StoneBrickStairs::Shape::Straight); case (110 << 4) | 0: return Mycelium::Mycelium(false); case (111 << 4) | 0: return LilyPad::LilyPad(); case (112 << 4) | 0: return NetherBricks::NetherBricks(); case (113 << 4) | 0: return NetherBrickFence::NetherBrickFence(false, false, false, false); case (114 << 4) | 0: return NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XP, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::Straight); case (114 << 4) | 1: return NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XM, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::Straight); case (114 << 4) | 2: return NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::Straight); case (114 << 4) | 3: return NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, NetherBrickStairs::Half::Bottom, NetherBrickStairs::Shape::Straight); case (114 << 4) | 4: return NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XP, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::Straight); case (114 << 4) | 5: return NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_XM, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::Straight); case (114 << 4) | 6: return NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZP, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::Straight); case (114 << 4) | 7: return NetherBrickStairs::NetherBrickStairs(eBlockFace::BLOCK_FACE_ZM, NetherBrickStairs::Half::Top, NetherBrickStairs::Shape::Straight); case (115 << 4) | 0: return NetherWart::NetherWart(0); case (115 << 4) | 1: return NetherWart::NetherWart(1); case (115 << 4) | 2: return NetherWart::NetherWart(2); case (115 << 4) | 3: return NetherWart::NetherWart(3); case (116 << 4) | 0: return EnchantingTable::EnchantingTable(); case (117 << 4) | 0: return BrewingStand::BrewingStand(false, false, false); case (117 << 4) | 1: return BrewingStand::BrewingStand(true, false, false); case (117 << 4) | 2: return BrewingStand::BrewingStand(false, true, false); case (117 << 4) | 3: return BrewingStand::BrewingStand(true, true, false); case (117 << 4) | 4: return BrewingStand::BrewingStand(false, false, true); case (117 << 4) | 5: return BrewingStand::BrewingStand(true, false, true); case (117 << 4) | 6: return BrewingStand::BrewingStand(false, true, true); case (117 << 4) | 7: return BrewingStand::BrewingStand(true, true, true); case (118 << 4) | 0: return Cauldron::Cauldron(0); case (118 << 4) | 1: return Cauldron::Cauldron(1); case (118 << 4) | 2: return Cauldron::Cauldron(2); case (118 << 4) | 3: return Cauldron::Cauldron(3); case (119 << 4) | 0: return EndPortal::EndPortal(); case (120 << 4) | 0: return EndPortalFrame::EndPortalFrame(false, eBlockFace::BLOCK_FACE_ZP); case (120 << 4) | 1: return EndPortalFrame::EndPortalFrame(false, eBlockFace::BLOCK_FACE_XM); case (120 << 4) | 2: return EndPortalFrame::EndPortalFrame(false, eBlockFace::BLOCK_FACE_ZM); case (120 << 4) | 3: return EndPortalFrame::EndPortalFrame(false, eBlockFace::BLOCK_FACE_XP); case (120 << 4) | 4: return EndPortalFrame::EndPortalFrame(true, eBlockFace::BLOCK_FACE_ZP); case (120 << 4) | 5: return EndPortalFrame::EndPortalFrame(true, eBlockFace::BLOCK_FACE_XM); case (120 << 4) | 6: return EndPortalFrame::EndPortalFrame(true, eBlockFace::BLOCK_FACE_ZM); case (120 << 4) | 7: return EndPortalFrame::EndPortalFrame(true, eBlockFace::BLOCK_FACE_XP); case (121 << 4) | 0: return EndStone::EndStone(); case (122 << 4) | 0: return DragonEgg::DragonEgg(); case (123 << 4) | 0: return RedstoneLamp::RedstoneLamp(false); case (124 << 4) | 0: return RedstoneLamp::RedstoneLamp(true); case (125 << 4) | 0: return OakSlab::OakSlab(OakSlab::Type::Double); case (125 << 4) | 1: return SpruceSlab::SpruceSlab(SpruceSlab::Type::Double); case (125 << 4) | 2: return BirchSlab::BirchSlab(BirchSlab::Type::Double); case (125 << 4) | 3: return JungleSlab::JungleSlab(JungleSlab::Type::Double); case (125 << 4) | 4: return AcaciaSlab::AcaciaSlab(AcaciaSlab::Type::Double); case (125 << 4) | 5: return DarkOakSlab::DarkOakSlab(DarkOakSlab::Type::Double); case (126 << 4) | 0: return OakSlab::OakSlab(OakSlab::Type::Bottom); case (126 << 4) | 1: return SpruceSlab::SpruceSlab(SpruceSlab::Type::Bottom); case (126 << 4) | 2: return BirchSlab::BirchSlab(BirchSlab::Type::Bottom); case (126 << 4) | 3: return JungleSlab::JungleSlab(JungleSlab::Type::Bottom); case (126 << 4) | 4: return AcaciaSlab::AcaciaSlab(AcaciaSlab::Type::Bottom); case (126 << 4) | 5: return DarkOakSlab::DarkOakSlab(DarkOakSlab::Type::Bottom); case (126 << 4) | 8: return OakSlab::OakSlab(OakSlab::Type::Top); case (126 << 4) | 9: return SpruceSlab::SpruceSlab(SpruceSlab::Type::Top); case (126 << 4) | 10: return BirchSlab::BirchSlab(BirchSlab::Type::Top); case (126 << 4) | 11: return JungleSlab::JungleSlab(JungleSlab::Type::Top); case (126 << 4) | 12: return AcaciaSlab::AcaciaSlab(AcaciaSlab::Type::Top); case (126 << 4) | 13: return DarkOakSlab::DarkOakSlab(DarkOakSlab::Type::Top); case (127 << 4) | 0: return Cocoa::Cocoa(0, eBlockFace::BLOCK_FACE_ZP); case (127 << 4) | 1: return Cocoa::Cocoa(0, eBlockFace::BLOCK_FACE_XM); case (127 << 4) | 2: return Cocoa::Cocoa(0, eBlockFace::BLOCK_FACE_ZM); case (127 << 4) | 3: return Cocoa::Cocoa(0, eBlockFace::BLOCK_FACE_XP); case (127 << 4) | 4: return Cocoa::Cocoa(1, eBlockFace::BLOCK_FACE_ZP); case (127 << 4) | 5: return Cocoa::Cocoa(1, eBlockFace::BLOCK_FACE_XM); case (127 << 4) | 6: return Cocoa::Cocoa(1, eBlockFace::BLOCK_FACE_ZM); case (127 << 4) | 7: return Cocoa::Cocoa(1, eBlockFace::BLOCK_FACE_XP); case (127 << 4) | 8: return Cocoa::Cocoa(2, eBlockFace::BLOCK_FACE_ZP); case (127 << 4) | 9: return Cocoa::Cocoa(2, eBlockFace::BLOCK_FACE_XM); case (127 << 4) | 10: return Cocoa::Cocoa(2, eBlockFace::BLOCK_FACE_ZM); case (127 << 4) | 11: return Cocoa::Cocoa(2, eBlockFace::BLOCK_FACE_XP); case (128 << 4) | 0: return SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XP, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::Straight); case (128 << 4) | 1: return SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XM, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::Straight); case (128 << 4) | 2: return SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::Straight); case (128 << 4) | 3: return SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SandstoneStairs::Half::Bottom, SandstoneStairs::Shape::Straight); case (128 << 4) | 4: return SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XP, SandstoneStairs::Half::Top, SandstoneStairs::Shape::Straight); case (128 << 4) | 5: return SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_XM, SandstoneStairs::Half::Top, SandstoneStairs::Shape::Straight); case (128 << 4) | 6: return SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZP, SandstoneStairs::Half::Top, SandstoneStairs::Shape::Straight); case (128 << 4) | 7: return SandstoneStairs::SandstoneStairs(eBlockFace::BLOCK_FACE_ZM, SandstoneStairs::Half::Top, SandstoneStairs::Shape::Straight); case (129 << 4) | 0: return EmeraldOre::EmeraldOre(); case (130 << 4) | 2: return EnderChest::EnderChest(eBlockFace::BLOCK_FACE_ZM); case (130 << 4) | 3: return EnderChest::EnderChest(eBlockFace::BLOCK_FACE_ZP); case (130 << 4) | 4: return EnderChest::EnderChest(eBlockFace::BLOCK_FACE_XM); case (130 << 4) | 5: return EnderChest::EnderChest(eBlockFace::BLOCK_FACE_XP); case (131 << 4) | 0: return TripwireHook::TripwireHook(false, eBlockFace::BLOCK_FACE_ZP, false); case (131 << 4) | 1: return TripwireHook::TripwireHook(false, eBlockFace::BLOCK_FACE_XM, false); case (131 << 4) | 2: return TripwireHook::TripwireHook(false, eBlockFace::BLOCK_FACE_ZM, false); case (131 << 4) | 3: return TripwireHook::TripwireHook(false, eBlockFace::BLOCK_FACE_XP, false); case (131 << 4) | 4: return TripwireHook::TripwireHook(true, eBlockFace::BLOCK_FACE_ZP, false); case (131 << 4) | 5: return TripwireHook::TripwireHook(true, eBlockFace::BLOCK_FACE_XM, false); case (131 << 4) | 6: return TripwireHook::TripwireHook(true, eBlockFace::BLOCK_FACE_ZM, false); case (131 << 4) | 7: return TripwireHook::TripwireHook(true, eBlockFace::BLOCK_FACE_XP, false); case (131 << 4) | 8: return TripwireHook::TripwireHook(false, eBlockFace::BLOCK_FACE_ZP, true); case (131 << 4) | 9: return TripwireHook::TripwireHook(false, eBlockFace::BLOCK_FACE_XM, true); case (131 << 4) | 10: return TripwireHook::TripwireHook(false, eBlockFace::BLOCK_FACE_ZM, true); case (131 << 4) | 11: return TripwireHook::TripwireHook(false, eBlockFace::BLOCK_FACE_XP, true); case (131 << 4) | 12: return TripwireHook::TripwireHook(true, eBlockFace::BLOCK_FACE_ZP, true); case (131 << 4) | 13: return TripwireHook::TripwireHook(true, eBlockFace::BLOCK_FACE_XM, true); case (131 << 4) | 14: return TripwireHook::TripwireHook(true, eBlockFace::BLOCK_FACE_ZM, true); case (131 << 4) | 15: return TripwireHook::TripwireHook(true, eBlockFace::BLOCK_FACE_XP, true); case (132 << 4) | 0: return Tripwire::Tripwire(false, false, false, false, false, false, false); case (132 << 4) | 1: return Tripwire::Tripwire(false, false, false, false, true, false, false); case (132 << 4) | 2: return Tripwire::Tripwire(false, false, false, false, false, false, false); case (132 << 4) | 3: return Tripwire::Tripwire(false, false, false, false, true, false, false); case (132 << 4) | 4: return Tripwire::Tripwire(true, false, false, false, false, false, false); case (132 << 4) | 5: return Tripwire::Tripwire(true, false, false, false, true, false, false); case (132 << 4) | 6: return Tripwire::Tripwire(true, false, false, false, false, false, false); case (132 << 4) | 7: return Tripwire::Tripwire(true, false, false, false, true, false, false); case (132 << 4) | 8: return Tripwire::Tripwire(false, true, false, false, false, false, false); case (132 << 4) | 9: return Tripwire::Tripwire(false, true, false, false, true, false, false); case (132 << 4) | 10: return Tripwire::Tripwire(false, true, false, false, false, false, false); case (132 << 4) | 11: return Tripwire::Tripwire(false, true, false, false, true, false, false); case (132 << 4) | 12: return Tripwire::Tripwire(true, true, false, false, false, false, false); case (132 << 4) | 13: return Tripwire::Tripwire(true, true, false, false, true, false, false); case (132 << 4) | 14: return Tripwire::Tripwire(true, true, false, false, false, false, false); case (133 << 4) | 0: return EmeraldBlock::EmeraldBlock(); case (134 << 4) | 0: return SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XP, SpruceStairs::Half::Bottom, SpruceStairs::Shape::Straight); case (134 << 4) | 1: return SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XM, SpruceStairs::Half::Bottom, SpruceStairs::Shape::Straight); case (134 << 4) | 2: return SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZP, SpruceStairs::Half::Bottom, SpruceStairs::Shape::Straight); case (134 << 4) | 3: return SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZM, SpruceStairs::Half::Bottom, SpruceStairs::Shape::Straight); case (134 << 4) | 4: return SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XP, SpruceStairs::Half::Top, SpruceStairs::Shape::Straight); case (134 << 4) | 5: return SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_XM, SpruceStairs::Half::Top, SpruceStairs::Shape::Straight); case (134 << 4) | 6: return SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZP, SpruceStairs::Half::Top, SpruceStairs::Shape::Straight); case (134 << 4) | 7: return SpruceStairs::SpruceStairs(eBlockFace::BLOCK_FACE_ZM, SpruceStairs::Half::Top, SpruceStairs::Shape::Straight); case (135 << 4) | 0: return BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XP, BirchStairs::Half::Bottom, BirchStairs::Shape::Straight); case (135 << 4) | 1: return BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XM, BirchStairs::Half::Bottom, BirchStairs::Shape::Straight); case (135 << 4) | 2: return BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZP, BirchStairs::Half::Bottom, BirchStairs::Shape::Straight); case (135 << 4) | 3: return BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZM, BirchStairs::Half::Bottom, BirchStairs::Shape::Straight); case (135 << 4) | 4: return BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XP, BirchStairs::Half::Top, BirchStairs::Shape::Straight); case (135 << 4) | 5: return BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_XM, BirchStairs::Half::Top, BirchStairs::Shape::Straight); case (135 << 4) | 6: return BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZP, BirchStairs::Half::Top, BirchStairs::Shape::Straight); case (135 << 4) | 7: return BirchStairs::BirchStairs(eBlockFace::BLOCK_FACE_ZM, BirchStairs::Half::Top, BirchStairs::Shape::Straight); case (136 << 4) | 0: return JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XP, JungleStairs::Half::Bottom, JungleStairs::Shape::Straight); case (136 << 4) | 1: return JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XM, JungleStairs::Half::Bottom, JungleStairs::Shape::Straight); case (136 << 4) | 2: return JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZP, JungleStairs::Half::Bottom, JungleStairs::Shape::Straight); case (136 << 4) | 3: return JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZM, JungleStairs::Half::Bottom, JungleStairs::Shape::Straight); case (136 << 4) | 4: return JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XP, JungleStairs::Half::Top, JungleStairs::Shape::Straight); case (136 << 4) | 5: return JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_XM, JungleStairs::Half::Top, JungleStairs::Shape::Straight); case (136 << 4) | 6: return JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZP, JungleStairs::Half::Top, JungleStairs::Shape::Straight); case (136 << 4) | 7: return JungleStairs::JungleStairs(eBlockFace::BLOCK_FACE_ZM, JungleStairs::Half::Top, JungleStairs::Shape::Straight); case (137 << 4) | 0: return CommandBlock::CommandBlock(false, eBlockFace::BLOCK_FACE_YM); case (137 << 4) | 1: return CommandBlock::CommandBlock(false, eBlockFace::BLOCK_FACE_YP); case (137 << 4) | 2: return CommandBlock::CommandBlock(false, eBlockFace::BLOCK_FACE_ZM); case (137 << 4) | 3: return CommandBlock::CommandBlock(false, eBlockFace::BLOCK_FACE_ZP); case (137 << 4) | 4: return CommandBlock::CommandBlock(false, eBlockFace::BLOCK_FACE_XM); case (137 << 4) | 5: return CommandBlock::CommandBlock(false, eBlockFace::BLOCK_FACE_XP); case (137 << 4) | 8: return CommandBlock::CommandBlock(true, eBlockFace::BLOCK_FACE_YM); case (137 << 4) | 9: return CommandBlock::CommandBlock(true, eBlockFace::BLOCK_FACE_YP); case (137 << 4) | 10: return CommandBlock::CommandBlock(true, eBlockFace::BLOCK_FACE_ZM); case (137 << 4) | 11: return CommandBlock::CommandBlock(true, eBlockFace::BLOCK_FACE_ZP); case (137 << 4) | 12: return CommandBlock::CommandBlock(true, eBlockFace::BLOCK_FACE_XM); case (137 << 4) | 13: return CommandBlock::CommandBlock(true, eBlockFace::BLOCK_FACE_XP); case (138 << 4) | 0: return Beacon::Beacon(); case (139 << 4) | 0: return CobblestoneWall::CobblestoneWall(CobblestoneWall::East::None, CobblestoneWall::North::None, CobblestoneWall::South::None, true, CobblestoneWall::West::None); case (139 << 4) | 1: return MossyCobblestoneWall::MossyCobblestoneWall(MossyCobblestoneWall::East::None, MossyCobblestoneWall::North::None, MossyCobblestoneWall::South::None, true, MossyCobblestoneWall::West::None); case (140 << 4) | 0: return PottedCactus::PottedCactus(); case (140 << 4) | 1: return PottedCactus::PottedCactus(); case (140 << 4) | 2: return PottedCactus::PottedCactus(); case (140 << 4) | 3: return PottedCactus::PottedCactus(); case (140 << 4) | 4: return PottedCactus::PottedCactus(); case (140 << 4) | 5: return PottedCactus::PottedCactus(); case (140 << 4) | 6: return PottedCactus::PottedCactus(); case (140 << 4) | 7: return PottedCactus::PottedCactus(); case (140 << 4) | 8: return PottedCactus::PottedCactus(); case (140 << 4) | 9: return PottedCactus::PottedCactus(); case (140 << 4) | 10: return PottedCactus::PottedCactus(); case (140 << 4) | 11: return PottedCactus::PottedCactus(); case (140 << 4) | 12: return PottedCactus::PottedCactus(); case (140 << 4) | 13: return PottedCactus::PottedCactus(); case (140 << 4) | 14: return PottedCactus::PottedCactus(); case (140 << 4) | 15: return PottedCactus::PottedCactus(); case (141 << 4) | 0: return Carrots::Carrots(0); case (141 << 4) | 1: return Carrots::Carrots(1); case (141 << 4) | 2: return Carrots::Carrots(2); case (141 << 4) | 3: return Carrots::Carrots(3); case (141 << 4) | 4: return Carrots::Carrots(4); case (141 << 4) | 5: return Carrots::Carrots(5); case (141 << 4) | 6: return Carrots::Carrots(6); case (141 << 4) | 7: return Carrots::Carrots(7); case (142 << 4) | 0: return Potatoes::Potatoes(0); case (142 << 4) | 1: return Potatoes::Potatoes(1); case (142 << 4) | 2: return Potatoes::Potatoes(2); case (142 << 4) | 3: return Potatoes::Potatoes(3); case (142 << 4) | 4: return Potatoes::Potatoes(4); case (142 << 4) | 5: return Potatoes::Potatoes(5); case (142 << 4) | 6: return Potatoes::Potatoes(6); case (142 << 4) | 7: return Potatoes::Potatoes(7); case (143 << 4) | 0: return OakButton::OakButton(OakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, false); case (143 << 4) | 1: return OakButton::OakButton(OakButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, false); case (143 << 4) | 2: return OakButton::OakButton(OakButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, false); case (143 << 4) | 3: return OakButton::OakButton(OakButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, false); case (143 << 4) | 4: return OakButton::OakButton(OakButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, false); case (143 << 4) | 5: return OakButton::OakButton(OakButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, false); case (143 << 4) | 8: return OakButton::OakButton(OakButton::Face::Ceiling, eBlockFace::BLOCK_FACE_ZM, true); case (143 << 4) | 9: return OakButton::OakButton(OakButton::Face::Wall, eBlockFace::BLOCK_FACE_XP, true); case (143 << 4) | 10: return OakButton::OakButton(OakButton::Face::Wall, eBlockFace::BLOCK_FACE_XM, true); case (143 << 4) | 11: return OakButton::OakButton(OakButton::Face::Wall, eBlockFace::BLOCK_FACE_ZP, true); case (143 << 4) | 12: return OakButton::OakButton(OakButton::Face::Wall, eBlockFace::BLOCK_FACE_ZM, true); case (143 << 4) | 13: return OakButton::OakButton(OakButton::Face::Floor, eBlockFace::BLOCK_FACE_ZM, true); case (144 << 4) | 1: return SkeletonSkull::SkeletonSkull(eBlockFace::BLOCK_FACE_YP); case (144 << 4) | 2: return SkeletonWallSkull::SkeletonWallSkull(eBlockFace::BLOCK_FACE_ZM); case (144 << 4) | 3: return SkeletonWallSkull::SkeletonWallSkull(eBlockFace::BLOCK_FACE_ZP); case (144 << 4) | 4: return SkeletonWallSkull::SkeletonWallSkull(eBlockFace::BLOCK_FACE_XM); case (144 << 4) | 5: return SkeletonWallSkull::SkeletonWallSkull(eBlockFace::BLOCK_FACE_XP); case (145 << 4) | 0: return Anvil::Anvil(eBlockFace::BLOCK_FACE_ZP); case (145 << 4) | 1: return Anvil::Anvil(eBlockFace::BLOCK_FACE_XM); case (145 << 4) | 2: return Anvil::Anvil(eBlockFace::BLOCK_FACE_ZM); case (145 << 4) | 3: return Anvil::Anvil(eBlockFace::BLOCK_FACE_XP); case (145 << 4) | 4: return ChippedAnvil::ChippedAnvil(eBlockFace::BLOCK_FACE_ZP); case (145 << 4) | 5: return ChippedAnvil::ChippedAnvil(eBlockFace::BLOCK_FACE_XM); case (145 << 4) | 6: return ChippedAnvil::ChippedAnvil(eBlockFace::BLOCK_FACE_ZM); case (145 << 4) | 7: return ChippedAnvil::ChippedAnvil(eBlockFace::BLOCK_FACE_XP); case (145 << 4) | 8: return DamagedAnvil::DamagedAnvil(eBlockFace::BLOCK_FACE_ZP); case (145 << 4) | 9: return DamagedAnvil::DamagedAnvil(eBlockFace::BLOCK_FACE_XM); case (145 << 4) | 10: return DamagedAnvil::DamagedAnvil(eBlockFace::BLOCK_FACE_ZM); case (145 << 4) | 11: return DamagedAnvil::DamagedAnvil(eBlockFace::BLOCK_FACE_XP); case (146 << 4) | 2: return TrappedChest::TrappedChest(eBlockFace::BLOCK_FACE_ZM, TrappedChest::Type::Single); case (146 << 4) | 3: return TrappedChest::TrappedChest(eBlockFace::BLOCK_FACE_ZP, TrappedChest::Type::Single); case (146 << 4) | 4: return TrappedChest::TrappedChest(eBlockFace::BLOCK_FACE_XM, TrappedChest::Type::Single); case (146 << 4) | 5: return TrappedChest::TrappedChest(eBlockFace::BLOCK_FACE_XP, TrappedChest::Type::Single); case (147 << 4) | 0: return LightWeightedPressurePlate::LightWeightedPressurePlate(0); case (147 << 4) | 1: return LightWeightedPressurePlate::LightWeightedPressurePlate(1); case (147 << 4) | 2: return LightWeightedPressurePlate::LightWeightedPressurePlate(2); case (147 << 4) | 3: return LightWeightedPressurePlate::LightWeightedPressurePlate(3); case (147 << 4) | 4: return LightWeightedPressurePlate::LightWeightedPressurePlate(4); case (147 << 4) | 5: return LightWeightedPressurePlate::LightWeightedPressurePlate(5); case (147 << 4) | 6: return LightWeightedPressurePlate::LightWeightedPressurePlate(6); case (147 << 4) | 7: return LightWeightedPressurePlate::LightWeightedPressurePlate(7); case (147 << 4) | 8: return LightWeightedPressurePlate::LightWeightedPressurePlate(8); case (147 << 4) | 9: return LightWeightedPressurePlate::LightWeightedPressurePlate(9); case (147 << 4) | 10: return LightWeightedPressurePlate::LightWeightedPressurePlate(10); case (147 << 4) | 11: return LightWeightedPressurePlate::LightWeightedPressurePlate(11); case (147 << 4) | 12: return LightWeightedPressurePlate::LightWeightedPressurePlate(12); case (147 << 4) | 13: return LightWeightedPressurePlate::LightWeightedPressurePlate(13); case (147 << 4) | 14: return LightWeightedPressurePlate::LightWeightedPressurePlate(14); case (147 << 4) | 15: return LightWeightedPressurePlate::LightWeightedPressurePlate(15); case (148 << 4) | 0: return HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(0); case (148 << 4) | 1: return HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(1); case (148 << 4) | 2: return HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(2); case (148 << 4) | 3: return HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(3); case (148 << 4) | 4: return HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(4); case (148 << 4) | 5: return HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(5); case (148 << 4) | 6: return HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(6); case (148 << 4) | 7: return HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(7); case (148 << 4) | 8: return HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(8); case (148 << 4) | 9: return HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(9); case (148 << 4) | 10: return HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(10); case (148 << 4) | 11: return HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(11); case (148 << 4) | 12: return HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(12); case (148 << 4) | 13: return HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(13); case (148 << 4) | 14: return HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(14); case (148 << 4) | 15: return HeavyWeightedPressurePlate::HeavyWeightedPressurePlate(15); case (149 << 4) | 0: return Comparator::Comparator(eBlockFace::BLOCK_FACE_ZP, Comparator::Mode::Compare, false); case (149 << 4) | 1: return Comparator::Comparator(eBlockFace::BLOCK_FACE_XM, Comparator::Mode::Compare, false); case (149 << 4) | 2: return Comparator::Comparator(eBlockFace::BLOCK_FACE_ZM, Comparator::Mode::Compare, false); case (149 << 4) | 3: return Comparator::Comparator(eBlockFace::BLOCK_FACE_XP, Comparator::Mode::Compare, false); case (149 << 4) | 4: return Comparator::Comparator(eBlockFace::BLOCK_FACE_ZP, Comparator::Mode::Subtract, false); case (149 << 4) | 5: return Comparator::Comparator(eBlockFace::BLOCK_FACE_XM, Comparator::Mode::Subtract, false); case (149 << 4) | 6: return Comparator::Comparator(eBlockFace::BLOCK_FACE_ZM, Comparator::Mode::Subtract, false); case (149 << 4) | 7: return Comparator::Comparator(eBlockFace::BLOCK_FACE_XP, Comparator::Mode::Subtract, false); case (149 << 4) | 8: return Comparator::Comparator(eBlockFace::BLOCK_FACE_ZP, Comparator::Mode::Compare, true); case (149 << 4) | 9: return Comparator::Comparator(eBlockFace::BLOCK_FACE_XM, Comparator::Mode::Compare, true); case (149 << 4) | 10: return Comparator::Comparator(eBlockFace::BLOCK_FACE_ZM, Comparator::Mode::Compare, true); case (149 << 4) | 11: return Comparator::Comparator(eBlockFace::BLOCK_FACE_XP, Comparator::Mode::Compare, true); case (149 << 4) | 12: return Comparator::Comparator(eBlockFace::BLOCK_FACE_ZP, Comparator::Mode::Subtract, true); case (149 << 4) | 13: return Comparator::Comparator(eBlockFace::BLOCK_FACE_XM, Comparator::Mode::Subtract, true); case (149 << 4) | 14: return Comparator::Comparator(eBlockFace::BLOCK_FACE_ZM, Comparator::Mode::Subtract, true); case (149 << 4) | 15: return Comparator::Comparator(eBlockFace::BLOCK_FACE_XP, Comparator::Mode::Subtract, true); case (150 << 4) | 0: return Comparator::Comparator(eBlockFace::BLOCK_FACE_ZP, Comparator::Mode::Compare, false); case (150 << 4) | 1: return Comparator::Comparator(eBlockFace::BLOCK_FACE_XM, Comparator::Mode::Compare, false); case (150 << 4) | 2: return Comparator::Comparator(eBlockFace::BLOCK_FACE_ZM, Comparator::Mode::Compare, false); case (150 << 4) | 3: return Comparator::Comparator(eBlockFace::BLOCK_FACE_XP, Comparator::Mode::Compare, false); case (150 << 4) | 4: return Comparator::Comparator(eBlockFace::BLOCK_FACE_ZP, Comparator::Mode::Subtract, false); case (150 << 4) | 5: return Comparator::Comparator(eBlockFace::BLOCK_FACE_XM, Comparator::Mode::Subtract, false); case (150 << 4) | 6: return Comparator::Comparator(eBlockFace::BLOCK_FACE_ZM, Comparator::Mode::Subtract, false); case (150 << 4) | 7: return Comparator::Comparator(eBlockFace::BLOCK_FACE_XP, Comparator::Mode::Subtract, false); case (150 << 4) | 8: return Comparator::Comparator(eBlockFace::BLOCK_FACE_ZP, Comparator::Mode::Compare, true); case (150 << 4) | 9: return Comparator::Comparator(eBlockFace::BLOCK_FACE_XM, Comparator::Mode::Compare, true); case (150 << 4) | 10: return Comparator::Comparator(eBlockFace::BLOCK_FACE_ZM, Comparator::Mode::Compare, true); case (150 << 4) | 11: return Comparator::Comparator(eBlockFace::BLOCK_FACE_XP, Comparator::Mode::Compare, true); case (150 << 4) | 12: return Comparator::Comparator(eBlockFace::BLOCK_FACE_ZP, Comparator::Mode::Subtract, true); case (150 << 4) | 13: return Comparator::Comparator(eBlockFace::BLOCK_FACE_XM, Comparator::Mode::Subtract, true); case (150 << 4) | 14: return Comparator::Comparator(eBlockFace::BLOCK_FACE_ZM, Comparator::Mode::Subtract, true); case (150 << 4) | 15: return Comparator::Comparator(eBlockFace::BLOCK_FACE_XP, Comparator::Mode::Subtract, true); case (151 << 4) | 0: return DaylightDetector::DaylightDetector(false, 0); case (151 << 4) | 1: return DaylightDetector::DaylightDetector(false, 1); case (151 << 4) | 2: return DaylightDetector::DaylightDetector(false, 2); case (151 << 4) | 3: return DaylightDetector::DaylightDetector(false, 3); case (151 << 4) | 4: return DaylightDetector::DaylightDetector(false, 4); case (151 << 4) | 5: return DaylightDetector::DaylightDetector(false, 5); case (151 << 4) | 6: return DaylightDetector::DaylightDetector(false, 6); case (151 << 4) | 7: return DaylightDetector::DaylightDetector(false, 7); case (151 << 4) | 8: return DaylightDetector::DaylightDetector(false, 8); case (151 << 4) | 9: return DaylightDetector::DaylightDetector(false, 9); case (151 << 4) | 10: return DaylightDetector::DaylightDetector(false, 10); case (151 << 4) | 11: return DaylightDetector::DaylightDetector(false, 11); case (151 << 4) | 12: return DaylightDetector::DaylightDetector(false, 12); case (151 << 4) | 13: return DaylightDetector::DaylightDetector(false, 13); case (151 << 4) | 14: return DaylightDetector::DaylightDetector(false, 14); case (151 << 4) | 15: return DaylightDetector::DaylightDetector(false, 15); case (152 << 4) | 0: return RedstoneBlock::RedstoneBlock(); case (153 << 4) | 0: return NetherQuartzOre::NetherQuartzOre(); case (154 << 4) | 0: return Hopper::Hopper(true, eBlockFace::BLOCK_FACE_YM); case (154 << 4) | 2: return Hopper::Hopper(true, eBlockFace::BLOCK_FACE_ZM); case (154 << 4) | 3: return Hopper::Hopper(true, eBlockFace::BLOCK_FACE_ZP); case (154 << 4) | 4: return Hopper::Hopper(true, eBlockFace::BLOCK_FACE_XM); case (154 << 4) | 5: return Hopper::Hopper(true, eBlockFace::BLOCK_FACE_XP); case (154 << 4) | 8: return Hopper::Hopper(false, eBlockFace::BLOCK_FACE_YM); case (154 << 4) | 10: return Hopper::Hopper(false, eBlockFace::BLOCK_FACE_ZM); case (154 << 4) | 11: return Hopper::Hopper(false, eBlockFace::BLOCK_FACE_ZP); case (154 << 4) | 12: return Hopper::Hopper(false, eBlockFace::BLOCK_FACE_XM); case (154 << 4) | 13: return Hopper::Hopper(false, eBlockFace::BLOCK_FACE_XP); case (155 << 4) | 0: return QuartzBlock::QuartzBlock(); case (155 << 4) | 1: return ChiseledQuartzBlock::ChiseledQuartzBlock(); case (155 << 4) | 2: return QuartzPillar::QuartzPillar(QuartzPillar::Axis::Y); case (155 << 4) | 3: return QuartzPillar::QuartzPillar(QuartzPillar::Axis::X); case (155 << 4) | 4: return QuartzPillar::QuartzPillar(QuartzPillar::Axis::Z); case (156 << 4) | 0: return QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XP, QuartzStairs::Half::Bottom, QuartzStairs::Shape::Straight); case (156 << 4) | 1: return QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XM, QuartzStairs::Half::Bottom, QuartzStairs::Shape::Straight); case (156 << 4) | 2: return QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZP, QuartzStairs::Half::Bottom, QuartzStairs::Shape::Straight); case (156 << 4) | 3: return QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZM, QuartzStairs::Half::Bottom, QuartzStairs::Shape::Straight); case (156 << 4) | 4: return QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XP, QuartzStairs::Half::Top, QuartzStairs::Shape::Straight); case (156 << 4) | 5: return QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_XM, QuartzStairs::Half::Top, QuartzStairs::Shape::Straight); case (156 << 4) | 6: return QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZP, QuartzStairs::Half::Top, QuartzStairs::Shape::Straight); case (156 << 4) | 7: return QuartzStairs::QuartzStairs(eBlockFace::BLOCK_FACE_ZM, QuartzStairs::Half::Top, QuartzStairs::Shape::Straight); case (157 << 4) | 0: return ActivatorRail::ActivatorRail(false, ActivatorRail::Shape::NorthSouth); case (157 << 4) | 1: return ActivatorRail::ActivatorRail(false, ActivatorRail::Shape::EastWest); case (157 << 4) | 2: return ActivatorRail::ActivatorRail(false, ActivatorRail::Shape::AscendingEast); case (157 << 4) | 3: return ActivatorRail::ActivatorRail(false, ActivatorRail::Shape::AscendingWest); case (157 << 4) | 4: return ActivatorRail::ActivatorRail(false, ActivatorRail::Shape::AscendingNorth); case (157 << 4) | 5: return ActivatorRail::ActivatorRail(false, ActivatorRail::Shape::AscendingSouth); case (157 << 4) | 8: return ActivatorRail::ActivatorRail(true, ActivatorRail::Shape::NorthSouth); case (157 << 4) | 9: return ActivatorRail::ActivatorRail(true, ActivatorRail::Shape::EastWest); case (157 << 4) | 10: return ActivatorRail::ActivatorRail(true, ActivatorRail::Shape::AscendingEast); case (157 << 4) | 11: return ActivatorRail::ActivatorRail(true, ActivatorRail::Shape::AscendingWest); case (157 << 4) | 12: return ActivatorRail::ActivatorRail(true, ActivatorRail::Shape::AscendingNorth); case (157 << 4) | 13: return ActivatorRail::ActivatorRail(true, ActivatorRail::Shape::AscendingSouth); case (158 << 4) | 0: return Dropper::Dropper(eBlockFace::BLOCK_FACE_YM, false); case (158 << 4) | 1: return Dropper::Dropper(eBlockFace::BLOCK_FACE_YP, false); case (158 << 4) | 2: return Dropper::Dropper(eBlockFace::BLOCK_FACE_ZM, false); case (158 << 4) | 3: return Dropper::Dropper(eBlockFace::BLOCK_FACE_ZP, false); case (158 << 4) | 4: return Dropper::Dropper(eBlockFace::BLOCK_FACE_XM, false); case (158 << 4) | 5: return Dropper::Dropper(eBlockFace::BLOCK_FACE_XP, false); case (158 << 4) | 8: return Dropper::Dropper(eBlockFace::BLOCK_FACE_YM, true); case (158 << 4) | 9: return Dropper::Dropper(eBlockFace::BLOCK_FACE_YP, true); case (158 << 4) | 10: return Dropper::Dropper(eBlockFace::BLOCK_FACE_ZM, true); case (158 << 4) | 11: return Dropper::Dropper(eBlockFace::BLOCK_FACE_ZP, true); case (158 << 4) | 12: return Dropper::Dropper(eBlockFace::BLOCK_FACE_XM, true); case (158 << 4) | 13: return Dropper::Dropper(eBlockFace::BLOCK_FACE_XP, true); case (159 << 4) | 0: return WhiteTerracotta::WhiteTerracotta(); case (159 << 4) | 1: return OrangeTerracotta::OrangeTerracotta(); case (159 << 4) | 2: return MagentaTerracotta::MagentaTerracotta(); case (159 << 4) | 3: return LightBlueTerracotta::LightBlueTerracotta(); case (159 << 4) | 4: return YellowTerracotta::YellowTerracotta(); case (159 << 4) | 5: return LimeTerracotta::LimeTerracotta(); case (159 << 4) | 6: return PinkTerracotta::PinkTerracotta(); case (159 << 4) | 7: return GrayTerracotta::GrayTerracotta(); case (159 << 4) | 8: return LightGrayTerracotta::LightGrayTerracotta(); case (159 << 4) | 9: return CyanTerracotta::CyanTerracotta(); case (159 << 4) | 10: return PurpleTerracotta::PurpleTerracotta(); case (159 << 4) | 11: return BlueTerracotta::BlueTerracotta(); case (159 << 4) | 12: return BrownTerracotta::BrownTerracotta(); case (159 << 4) | 13: return GreenTerracotta::GreenTerracotta(); case (159 << 4) | 14: return RedTerracotta::RedTerracotta(); case (159 << 4) | 15: return BlackTerracotta::BlackTerracotta(); case (160 << 4) | 0: return WhiteStainedGlassPane::WhiteStainedGlassPane(false, false, false, false); case (160 << 4) | 1: return OrangeStainedGlassPane::OrangeStainedGlassPane(false, false, false, false); case (160 << 4) | 2: return MagentaStainedGlassPane::MagentaStainedGlassPane(false, false, false, false); case (160 << 4) | 3: return LightBlueStainedGlassPane::LightBlueStainedGlassPane(false, false, false, false); case (160 << 4) | 4: return YellowStainedGlassPane::YellowStainedGlassPane(false, false, false, false); case (160 << 4) | 5: return LimeStainedGlassPane::LimeStainedGlassPane(false, false, false, false); case (160 << 4) | 6: return PinkStainedGlassPane::PinkStainedGlassPane(false, false, false, false); case (160 << 4) | 7: return GrayStainedGlassPane::GrayStainedGlassPane(false, false, false, false); case (160 << 4) | 8: return LightGrayStainedGlassPane::LightGrayStainedGlassPane(false, false, false, false); case (160 << 4) | 9: return CyanStainedGlassPane::CyanStainedGlassPane(false, false, false, false); case (160 << 4) | 10: return PurpleStainedGlassPane::PurpleStainedGlassPane(false, false, false, false); case (160 << 4) | 11: return BlueStainedGlassPane::BlueStainedGlassPane(false, false, false, false); case (160 << 4) | 12: return BrownStainedGlassPane::BrownStainedGlassPane(false, false, false, false); case (160 << 4) | 13: return GreenStainedGlassPane::GreenStainedGlassPane(false, false, false, false); case (160 << 4) | 14: return RedStainedGlassPane::RedStainedGlassPane(false, false, false, false); case (160 << 4) | 15: return BlackStainedGlassPane::BlackStainedGlassPane(false, false, false, false); case (161 << 4) | 0: return AcaciaLeaves::AcaciaLeaves(false, true); case (161 << 4) | 1: return DarkOakLeaves::DarkOakLeaves(false, true); case (161 << 4) | 4: return AcaciaLeaves::AcaciaLeaves(false, false); case (161 << 4) | 5: return DarkOakLeaves::DarkOakLeaves(false, false); case (161 << 4) | 8: return AcaciaLeaves::AcaciaLeaves(true, true); case (161 << 4) | 9: return DarkOakLeaves::DarkOakLeaves(true, true); case (161 << 4) | 12: return AcaciaLeaves::AcaciaLeaves(true, false); case (161 << 4) | 13: return DarkOakLeaves::DarkOakLeaves(true, false); case (162 << 4) | 0: return AcaciaLog::AcaciaLog(AcaciaLog::Axis::Y); case (162 << 4) | 1: return DarkOakLog::DarkOakLog(DarkOakLog::Axis::Y); case (162 << 4) | 4: return AcaciaLog::AcaciaLog(AcaciaLog::Axis::X); case (162 << 4) | 5: return DarkOakLog::DarkOakLog(DarkOakLog::Axis::X); case (162 << 4) | 8: return AcaciaLog::AcaciaLog(AcaciaLog::Axis::Z); case (162 << 4) | 9: return DarkOakLog::DarkOakLog(DarkOakLog::Axis::Z); case (162 << 4) | 12: return AcaciaWood::AcaciaWood(); case (162 << 4) | 13: return DarkOakWood::DarkOakWood(); case (163 << 4) | 0: return AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XP, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::Straight); case (163 << 4) | 1: return AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XM, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::Straight); case (163 << 4) | 2: return AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZP, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::Straight); case (163 << 4) | 3: return AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZM, AcaciaStairs::Half::Bottom, AcaciaStairs::Shape::Straight); case (163 << 4) | 4: return AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XP, AcaciaStairs::Half::Top, AcaciaStairs::Shape::Straight); case (163 << 4) | 5: return AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_XM, AcaciaStairs::Half::Top, AcaciaStairs::Shape::Straight); case (163 << 4) | 6: return AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZP, AcaciaStairs::Half::Top, AcaciaStairs::Shape::Straight); case (163 << 4) | 7: return AcaciaStairs::AcaciaStairs(eBlockFace::BLOCK_FACE_ZM, AcaciaStairs::Half::Top, AcaciaStairs::Shape::Straight); case (164 << 4) | 0: return DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XP, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::Straight); case (164 << 4) | 1: return DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XM, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::Straight); case (164 << 4) | 2: return DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZP, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::Straight); case (164 << 4) | 3: return DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZM, DarkOakStairs::Half::Bottom, DarkOakStairs::Shape::Straight); case (164 << 4) | 4: return DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XP, DarkOakStairs::Half::Top, DarkOakStairs::Shape::Straight); case (164 << 4) | 5: return DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_XM, DarkOakStairs::Half::Top, DarkOakStairs::Shape::Straight); case (164 << 4) | 6: return DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZP, DarkOakStairs::Half::Top, DarkOakStairs::Shape::Straight); case (164 << 4) | 7: return DarkOakStairs::DarkOakStairs(eBlockFace::BLOCK_FACE_ZM, DarkOakStairs::Half::Top, DarkOakStairs::Shape::Straight); case (165 << 4) | 0: return SlimeBlock::SlimeBlock(); case (166 << 4) | 0: return Barrier::Barrier(); case (167 << 4) | 0: return IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZM, IronTrapdoor::Half::Bottom, false, false); case (167 << 4) | 1: return IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZP, IronTrapdoor::Half::Bottom, false, false); case (167 << 4) | 2: return IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XM, IronTrapdoor::Half::Bottom, false, false); case (167 << 4) | 3: return IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XP, IronTrapdoor::Half::Bottom, false, false); case (167 << 4) | 4: return IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZM, IronTrapdoor::Half::Bottom, true, false); case (167 << 4) | 5: return IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZP, IronTrapdoor::Half::Bottom, true, false); case (167 << 4) | 6: return IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XM, IronTrapdoor::Half::Bottom, true, false); case (167 << 4) | 7: return IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XP, IronTrapdoor::Half::Bottom, true, false); case (167 << 4) | 8: return IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZM, IronTrapdoor::Half::Top, false, false); case (167 << 4) | 9: return IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZP, IronTrapdoor::Half::Top, false, false); case (167 << 4) | 10: return IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XM, IronTrapdoor::Half::Top, false, false); case (167 << 4) | 11: return IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XP, IronTrapdoor::Half::Top, false, false); case (167 << 4) | 12: return IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZM, IronTrapdoor::Half::Top, true, false); case (167 << 4) | 13: return IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_ZP, IronTrapdoor::Half::Top, true, false); case (167 << 4) | 14: return IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XM, IronTrapdoor::Half::Top, true, false); case (167 << 4) | 15: return IronTrapdoor::IronTrapdoor(eBlockFace::BLOCK_FACE_XP, IronTrapdoor::Half::Top, true, false); case (168 << 4) | 0: return Prismarine::Prismarine(); case (168 << 4) | 1: return PrismarineBricks::PrismarineBricks(); case (168 << 4) | 2: return DarkPrismarine::DarkPrismarine(); case (169 << 4) | 0: return SeaLantern::SeaLantern(); case (170 << 4) | 0: return HayBale::HayBale(HayBale::Axis::Y); case (170 << 4) | 4: return HayBale::HayBale(HayBale::Axis::X); case (170 << 4) | 8: return HayBale::HayBale(HayBale::Axis::Z); case (171 << 4) | 0: return WhiteCarpet::WhiteCarpet(); case (171 << 4) | 1: return OrangeCarpet::OrangeCarpet(); case (171 << 4) | 2: return MagentaCarpet::MagentaCarpet(); case (171 << 4) | 3: return LightBlueCarpet::LightBlueCarpet(); case (171 << 4) | 4: return YellowCarpet::YellowCarpet(); case (171 << 4) | 5: return LimeCarpet::LimeCarpet(); case (171 << 4) | 6: return PinkCarpet::PinkCarpet(); case (171 << 4) | 7: return GrayCarpet::GrayCarpet(); case (171 << 4) | 8: return LightGrayCarpet::LightGrayCarpet(); case (171 << 4) | 9: return CyanCarpet::CyanCarpet(); case (171 << 4) | 10: return PurpleCarpet::PurpleCarpet(); case (171 << 4) | 11: return BlueCarpet::BlueCarpet(); case (171 << 4) | 12: return BrownCarpet::BrownCarpet(); case (171 << 4) | 13: return GreenCarpet::GreenCarpet(); case (171 << 4) | 14: return RedCarpet::RedCarpet(); case (171 << 4) | 15: return BlackCarpet::BlackCarpet(); case (172 << 4) | 0: return Terracotta::Terracotta(); case (173 << 4) | 0: return CoalBlock::CoalBlock(); case (174 << 4) | 0: return PackedIce::PackedIce(); case (175 << 4) | 0: return Sunflower::Sunflower(Sunflower::Half::Lower); case (175 << 4) | 1: return Lilac::Lilac(Lilac::Half::Lower); case (175 << 4) | 2: return TallGrass::TallGrass(TallGrass::Half::Lower); case (175 << 4) | 3: return LargeFern::LargeFern(LargeFern::Half::Lower); case (175 << 4) | 4: return RoseBush::RoseBush(RoseBush::Half::Lower); case (175 << 4) | 5: return Peony::Peony(Peony::Half::Lower); case (175 << 4) | 8: return Sunflower::Sunflower(Sunflower::Half::Upper); case (175 << 4) | 9: return Lilac::Lilac(Lilac::Half::Upper); case (175 << 4) | 10: return TallGrass::TallGrass(TallGrass::Half::Upper); case (175 << 4) | 11: return LargeFern::LargeFern(LargeFern::Half::Upper); case (175 << 4) | 12: return RoseBush::RoseBush(RoseBush::Half::Upper); case (175 << 4) | 13: return Peony::Peony(Peony::Half::Upper); case (176 << 4) | 0: return WhiteBanner::WhiteBanner(0); case (176 << 4) | 1: return WhiteBanner::WhiteBanner(1); case (176 << 4) | 2: return WhiteBanner::WhiteBanner(2); case (176 << 4) | 3: return WhiteBanner::WhiteBanner(3); case (176 << 4) | 4: return WhiteBanner::WhiteBanner(4); case (176 << 4) | 5: return WhiteBanner::WhiteBanner(5); case (176 << 4) | 6: return WhiteBanner::WhiteBanner(6); case (176 << 4) | 7: return WhiteBanner::WhiteBanner(7); case (176 << 4) | 8: return WhiteBanner::WhiteBanner(8); case (176 << 4) | 9: return WhiteBanner::WhiteBanner(9); case (176 << 4) | 10: return WhiteBanner::WhiteBanner(10); case (176 << 4) | 11: return WhiteBanner::WhiteBanner(11); case (176 << 4) | 12: return WhiteBanner::WhiteBanner(12); case (176 << 4) | 13: return WhiteBanner::WhiteBanner(13); case (176 << 4) | 14: return WhiteBanner::WhiteBanner(14); case (176 << 4) | 15: return WhiteBanner::WhiteBanner(15); case (177 << 4) | 2: return WhiteWallBanner::WhiteWallBanner(eBlockFace::BLOCK_FACE_ZM); case (177 << 4) | 3: return WhiteWallBanner::WhiteWallBanner(eBlockFace::BLOCK_FACE_ZP); case (177 << 4) | 4: return WhiteWallBanner::WhiteWallBanner(eBlockFace::BLOCK_FACE_XM); case (177 << 4) | 5: return WhiteWallBanner::WhiteWallBanner(eBlockFace::BLOCK_FACE_XP); case (178 << 4) | 0: return DaylightDetector::DaylightDetector(true, 0); case (178 << 4) | 1: return DaylightDetector::DaylightDetector(true, 1); case (178 << 4) | 2: return DaylightDetector::DaylightDetector(true, 2); case (178 << 4) | 3: return DaylightDetector::DaylightDetector(true, 3); case (178 << 4) | 4: return DaylightDetector::DaylightDetector(true, 4); case (178 << 4) | 5: return DaylightDetector::DaylightDetector(true, 5); case (178 << 4) | 6: return DaylightDetector::DaylightDetector(true, 6); case (178 << 4) | 7: return DaylightDetector::DaylightDetector(true, 7); case (178 << 4) | 8: return DaylightDetector::DaylightDetector(true, 8); case (178 << 4) | 9: return DaylightDetector::DaylightDetector(true, 9); case (178 << 4) | 10: return DaylightDetector::DaylightDetector(true, 10); case (178 << 4) | 11: return DaylightDetector::DaylightDetector(true, 11); case (178 << 4) | 12: return DaylightDetector::DaylightDetector(true, 12); case (178 << 4) | 13: return DaylightDetector::DaylightDetector(true, 13); case (178 << 4) | 14: return DaylightDetector::DaylightDetector(true, 14); case (178 << 4) | 15: return DaylightDetector::DaylightDetector(true, 15); case (179 << 4) | 0: return RedSandstone::RedSandstone(); case (179 << 4) | 1: return ChiseledRedSandstone::ChiseledRedSandstone(); case (179 << 4) | 2: return CutRedSandstone::CutRedSandstone(); case (180 << 4) | 0: return RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::Straight); case (180 << 4) | 1: return RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::Straight); case (180 << 4) | 2: return RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::Straight); case (180 << 4) | 3: return RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, RedSandstoneStairs::Half::Bottom, RedSandstoneStairs::Shape::Straight); case (180 << 4) | 4: return RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XP, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::Straight); case (180 << 4) | 5: return RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_XM, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::Straight); case (180 << 4) | 6: return RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZP, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::Straight); case (180 << 4) | 7: return RedSandstoneStairs::RedSandstoneStairs(eBlockFace::BLOCK_FACE_ZM, RedSandstoneStairs::Half::Top, RedSandstoneStairs::Shape::Straight); case (181 << 4) | 0: return RedSandstoneSlab::RedSandstoneSlab(RedSandstoneSlab::Type::Double); case (181 << 4) | 8: return SmoothRedSandstone::SmoothRedSandstone(); case (182 << 4) | 0: return RedSandstoneSlab::RedSandstoneSlab(RedSandstoneSlab::Type::Bottom); case (182 << 4) | 8: return RedSandstoneSlab::RedSandstoneSlab(RedSandstoneSlab::Type::Top); case (183 << 4) | 0: return SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, false); case (183 << 4) | 1: return SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, false); case (183 << 4) | 2: return SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, false); case (183 << 4) | 3: return SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, false); case (183 << 4) | 4: return SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, false); case (183 << 4) | 5: return SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, false); case (183 << 4) | 6: return SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, false); case (183 << 4) | 7: return SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, false); case (183 << 4) | 8: return SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, true); case (183 << 4) | 9: return SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, true); case (183 << 4) | 10: return SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, true); case (183 << 4) | 11: return SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, true); case (183 << 4) | 12: return SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, true); case (183 << 4) | 13: return SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, true); case (183 << 4) | 14: return SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, true); case (183 << 4) | 15: return SpruceFenceGate::SpruceFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, true); case (184 << 4) | 0: return BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, false); case (184 << 4) | 1: return BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, false); case (184 << 4) | 2: return BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, false); case (184 << 4) | 3: return BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, false); case (184 << 4) | 4: return BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, false); case (184 << 4) | 5: return BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, false); case (184 << 4) | 6: return BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, false); case (184 << 4) | 7: return BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, false); case (184 << 4) | 8: return BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, true); case (184 << 4) | 9: return BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, true); case (184 << 4) | 10: return BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, true); case (184 << 4) | 11: return BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, true); case (184 << 4) | 12: return BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, true); case (184 << 4) | 13: return BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, true); case (184 << 4) | 14: return BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, true); case (184 << 4) | 15: return BirchFenceGate::BirchFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, true); case (185 << 4) | 0: return JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, false); case (185 << 4) | 1: return JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, false); case (185 << 4) | 2: return JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, false); case (185 << 4) | 3: return JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, false); case (185 << 4) | 4: return JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, false); case (185 << 4) | 5: return JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, false); case (185 << 4) | 6: return JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, false); case (185 << 4) | 7: return JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, false); case (185 << 4) | 8: return JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, true); case (185 << 4) | 9: return JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, true); case (185 << 4) | 10: return JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, true); case (185 << 4) | 11: return JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, true); case (185 << 4) | 12: return JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, true); case (185 << 4) | 13: return JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, true); case (185 << 4) | 14: return JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, true); case (185 << 4) | 15: return JungleFenceGate::JungleFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, true); case (186 << 4) | 0: return DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, false); case (186 << 4) | 1: return DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, false); case (186 << 4) | 2: return DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, false); case (186 << 4) | 3: return DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, false); case (186 << 4) | 4: return DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, false); case (186 << 4) | 5: return DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, false); case (186 << 4) | 6: return DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, false); case (186 << 4) | 7: return DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, false); case (186 << 4) | 8: return DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, true); case (186 << 4) | 9: return DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, true); case (186 << 4) | 10: return DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, true); case (186 << 4) | 11: return DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, true); case (186 << 4) | 12: return DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, true); case (186 << 4) | 13: return DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, true); case (186 << 4) | 14: return DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, true); case (186 << 4) | 15: return DarkOakFenceGate::DarkOakFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, true); case (187 << 4) | 0: return AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, false); case (187 << 4) | 1: return AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, false); case (187 << 4) | 2: return AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, false); case (187 << 4) | 3: return AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, false); case (187 << 4) | 4: return AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, false); case (187 << 4) | 5: return AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, false); case (187 << 4) | 6: return AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, false); case (187 << 4) | 7: return AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, false); case (187 << 4) | 8: return AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZP, false, false, true); case (187 << 4) | 9: return AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XM, false, false, true); case (187 << 4) | 10: return AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZM, false, false, true); case (187 << 4) | 11: return AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XP, false, false, true); case (187 << 4) | 12: return AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZP, false, true, true); case (187 << 4) | 13: return AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XM, false, true, true); case (187 << 4) | 14: return AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_ZM, false, true, true); case (187 << 4) | 15: return AcaciaFenceGate::AcaciaFenceGate(eBlockFace::BLOCK_FACE_XP, false, true, true); case (188 << 4) | 0: return SpruceFence::SpruceFence(false, false, false, false); case (189 << 4) | 0: return BirchFence::BirchFence(false, false, false, false); case (190 << 4) | 0: return JungleFence::JungleFence(false, false, false, false); case (191 << 4) | 0: return DarkOakFence::DarkOakFence(false, false, false, false); case (192 << 4) | 0: return AcaciaFence::AcaciaFence(false, false, false, false); case (193 << 4) | 0: return SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, false, false); case (193 << 4) | 1: return SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, false, false); case (193 << 4) | 2: return SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, false, false); case (193 << 4) | 3: return SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, false, false); case (193 << 4) | 4: return SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, true, false); case (193 << 4) | 5: return SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZP, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, true, false); case (193 << 4) | 6: return SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, true, false); case (193 << 4) | 7: return SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_ZM, SpruceDoor::Half::Lower, SpruceDoor::Hinge::Right, true, false); case (193 << 4) | 8: return SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, false, false); case (193 << 4) | 9: return SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, false, false); case (193 << 4) | 10: return SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Left, false, true); case (193 << 4) | 11: return SpruceDoor::SpruceDoor(eBlockFace::BLOCK_FACE_XP, SpruceDoor::Half::Upper, SpruceDoor::Hinge::Right, false, true); case (194 << 4) | 0: return BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, false, false); case (194 << 4) | 1: return BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, false, false); case (194 << 4) | 2: return BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, false, false); case (194 << 4) | 3: return BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, false, false); case (194 << 4) | 4: return BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, true, false); case (194 << 4) | 5: return BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZP, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, true, false); case (194 << 4) | 6: return BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XM, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, true, false); case (194 << 4) | 7: return BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_ZM, BirchDoor::Half::Lower, BirchDoor::Hinge::Right, true, false); case (194 << 4) | 8: return BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, false, false); case (194 << 4) | 9: return BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, false, false); case (194 << 4) | 10: return BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Upper, BirchDoor::Hinge::Left, false, true); case (194 << 4) | 11: return BirchDoor::BirchDoor(eBlockFace::BLOCK_FACE_XP, BirchDoor::Half::Upper, BirchDoor::Hinge::Right, false, true); case (195 << 4) | 0: return JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, false, false); case (195 << 4) | 1: return JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, false, false); case (195 << 4) | 2: return JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, false, false); case (195 << 4) | 3: return JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, false, false); case (195 << 4) | 4: return JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, true, false); case (195 << 4) | 5: return JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZP, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, true, false); case (195 << 4) | 6: return JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XM, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, true, false); case (195 << 4) | 7: return JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_ZM, JungleDoor::Half::Lower, JungleDoor::Hinge::Right, true, false); case (195 << 4) | 8: return JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, false, false); case (195 << 4) | 9: return JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, false, false); case (195 << 4) | 10: return JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Upper, JungleDoor::Hinge::Left, false, true); case (195 << 4) | 11: return JungleDoor::JungleDoor(eBlockFace::BLOCK_FACE_XP, JungleDoor::Half::Upper, JungleDoor::Hinge::Right, false, true); case (196 << 4) | 0: return AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, false, false); case (196 << 4) | 1: return AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, false, false); case (196 << 4) | 2: return AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, false, false); case (196 << 4) | 3: return AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, false, false); case (196 << 4) | 4: return AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, true, false); case (196 << 4) | 5: return AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZP, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, true, false); case (196 << 4) | 6: return AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, true, false); case (196 << 4) | 7: return AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_ZM, AcaciaDoor::Half::Lower, AcaciaDoor::Hinge::Right, true, false); case (196 << 4) | 8: return AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, false, false); case (196 << 4) | 9: return AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, false, false); case (196 << 4) | 10: return AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Left, false, true); case (196 << 4) | 11: return AcaciaDoor::AcaciaDoor(eBlockFace::BLOCK_FACE_XP, AcaciaDoor::Half::Upper, AcaciaDoor::Hinge::Right, false, true); case (197 << 4) | 0: return DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, false, false); case (197 << 4) | 1: return DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, false, false); case (197 << 4) | 2: return DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, false, false); case (197 << 4) | 3: return DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, false, false); case (197 << 4) | 4: return DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, true, false); case (197 << 4) | 5: return DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZP, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, true, false); case (197 << 4) | 6: return DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, true, false); case (197 << 4) | 7: return DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_ZM, DarkOakDoor::Half::Lower, DarkOakDoor::Hinge::Right, true, false); case (197 << 4) | 8: return DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, false, false); case (197 << 4) | 9: return DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, false, false); case (197 << 4) | 10: return DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Left, false, true); case (197 << 4) | 11: return DarkOakDoor::DarkOakDoor(eBlockFace::BLOCK_FACE_XP, DarkOakDoor::Half::Upper, DarkOakDoor::Hinge::Right, false, true); case (198 << 4) | 0: return EndRod::EndRod(eBlockFace::BLOCK_FACE_YM); case (198 << 4) | 1: return EndRod::EndRod(eBlockFace::BLOCK_FACE_YP); case (198 << 4) | 2: return EndRod::EndRod(eBlockFace::BLOCK_FACE_ZM); case (198 << 4) | 3: return EndRod::EndRod(eBlockFace::BLOCK_FACE_ZP); case (198 << 4) | 4: return EndRod::EndRod(eBlockFace::BLOCK_FACE_XM); case (198 << 4) | 5: return EndRod::EndRod(eBlockFace::BLOCK_FACE_XP); case (199 << 4) | 0: return ChorusPlant::ChorusPlant(false, false, false, false, false, false); case (200 << 4) | 0: return ChorusFlower::ChorusFlower(0); case (200 << 4) | 1: return ChorusFlower::ChorusFlower(1); case (200 << 4) | 2: return ChorusFlower::ChorusFlower(2); case (200 << 4) | 3: return ChorusFlower::ChorusFlower(3); case (200 << 4) | 4: return ChorusFlower::ChorusFlower(4); case (200 << 4) | 5: return ChorusFlower::ChorusFlower(5); case (201 << 4) | 0: return PurpurBlock::PurpurBlock(); case (202 << 4) | 0: return PurpurPillar::PurpurPillar(PurpurPillar::Axis::Y); case (202 << 4) | 4: return PurpurPillar::PurpurPillar(PurpurPillar::Axis::X); case (202 << 4) | 8: return PurpurPillar::PurpurPillar(PurpurPillar::Axis::Z); case (203 << 4) | 0: return PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XP, PurpurStairs::Half::Bottom, PurpurStairs::Shape::Straight); case (203 << 4) | 1: return PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XM, PurpurStairs::Half::Bottom, PurpurStairs::Shape::Straight); case (203 << 4) | 2: return PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZP, PurpurStairs::Half::Bottom, PurpurStairs::Shape::Straight); case (203 << 4) | 3: return PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZM, PurpurStairs::Half::Bottom, PurpurStairs::Shape::Straight); case (203 << 4) | 4: return PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XP, PurpurStairs::Half::Top, PurpurStairs::Shape::Straight); case (203 << 4) | 5: return PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_XM, PurpurStairs::Half::Top, PurpurStairs::Shape::Straight); case (203 << 4) | 6: return PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZP, PurpurStairs::Half::Top, PurpurStairs::Shape::Straight); case (203 << 4) | 7: return PurpurStairs::PurpurStairs(eBlockFace::BLOCK_FACE_ZM, PurpurStairs::Half::Top, PurpurStairs::Shape::Straight); case (204 << 4) | 0: return PurpurSlab::PurpurSlab(PurpurSlab::Type::Double); case (205 << 4) | 0: return PurpurSlab::PurpurSlab(PurpurSlab::Type::Bottom); case (205 << 4) | 8: return PurpurSlab::PurpurSlab(PurpurSlab::Type::Top); case (206 << 4) | 0: return EndStoneBricks::EndStoneBricks(); case (207 << 4) | 0: return Beetroots::Beetroots(0); case (207 << 4) | 1: return Beetroots::Beetroots(1); case (207 << 4) | 2: return Beetroots::Beetroots(2); case (207 << 4) | 3: return Beetroots::Beetroots(3); case (208 << 4) | 0: return GrassPath::GrassPath(); case (209 << 4) | 0: return EndGateway::EndGateway(); case (210 << 4) | 0: return RepeatingCommandBlock::RepeatingCommandBlock(false, eBlockFace::BLOCK_FACE_YM); case (210 << 4) | 1: return RepeatingCommandBlock::RepeatingCommandBlock(false, eBlockFace::BLOCK_FACE_YP); case (210 << 4) | 2: return RepeatingCommandBlock::RepeatingCommandBlock(false, eBlockFace::BLOCK_FACE_ZM); case (210 << 4) | 3: return RepeatingCommandBlock::RepeatingCommandBlock(false, eBlockFace::BLOCK_FACE_ZP); case (210 << 4) | 4: return RepeatingCommandBlock::RepeatingCommandBlock(false, eBlockFace::BLOCK_FACE_XM); case (210 << 4) | 5: return RepeatingCommandBlock::RepeatingCommandBlock(false, eBlockFace::BLOCK_FACE_XP); case (210 << 4) | 8: return RepeatingCommandBlock::RepeatingCommandBlock(true, eBlockFace::BLOCK_FACE_YM); case (210 << 4) | 9: return RepeatingCommandBlock::RepeatingCommandBlock(true, eBlockFace::BLOCK_FACE_YP); case (210 << 4) | 10: return RepeatingCommandBlock::RepeatingCommandBlock(true, eBlockFace::BLOCK_FACE_ZM); case (210 << 4) | 11: return RepeatingCommandBlock::RepeatingCommandBlock(true, eBlockFace::BLOCK_FACE_ZP); case (210 << 4) | 12: return RepeatingCommandBlock::RepeatingCommandBlock(true, eBlockFace::BLOCK_FACE_XM); case (210 << 4) | 13: return RepeatingCommandBlock::RepeatingCommandBlock(true, eBlockFace::BLOCK_FACE_XP); case (211 << 4) | 0: return ChainCommandBlock::ChainCommandBlock(false, eBlockFace::BLOCK_FACE_YM); case (211 << 4) | 1: return ChainCommandBlock::ChainCommandBlock(false, eBlockFace::BLOCK_FACE_YP); case (211 << 4) | 2: return ChainCommandBlock::ChainCommandBlock(false, eBlockFace::BLOCK_FACE_ZM); case (211 << 4) | 3: return ChainCommandBlock::ChainCommandBlock(false, eBlockFace::BLOCK_FACE_ZP); case (211 << 4) | 4: return ChainCommandBlock::ChainCommandBlock(false, eBlockFace::BLOCK_FACE_XM); case (211 << 4) | 5: return ChainCommandBlock::ChainCommandBlock(false, eBlockFace::BLOCK_FACE_XP); case (211 << 4) | 8: return ChainCommandBlock::ChainCommandBlock(true, eBlockFace::BLOCK_FACE_YM); case (211 << 4) | 9: return ChainCommandBlock::ChainCommandBlock(true, eBlockFace::BLOCK_FACE_YP); case (211 << 4) | 10: return ChainCommandBlock::ChainCommandBlock(true, eBlockFace::BLOCK_FACE_ZM); case (211 << 4) | 11: return ChainCommandBlock::ChainCommandBlock(true, eBlockFace::BLOCK_FACE_ZP); case (211 << 4) | 12: return ChainCommandBlock::ChainCommandBlock(true, eBlockFace::BLOCK_FACE_XM); case (211 << 4) | 13: return ChainCommandBlock::ChainCommandBlock(true, eBlockFace::BLOCK_FACE_XP); case (212 << 4) | 0: return FrostedIce::FrostedIce(0); case (212 << 4) | 1: return FrostedIce::FrostedIce(1); case (212 << 4) | 2: return FrostedIce::FrostedIce(2); case (212 << 4) | 3: return FrostedIce::FrostedIce(3); case (213 << 4) | 0: return MagmaBlock::MagmaBlock(); case (214 << 4) | 0: return NetherWartBlock::NetherWartBlock(); case (215 << 4) | 0: return RedNetherBricks::RedNetherBricks(); case (216 << 4) | 0: return BoneBlock::BoneBlock(BoneBlock::Axis::Y); case (216 << 4) | 4: return BoneBlock::BoneBlock(BoneBlock::Axis::X); case (216 << 4) | 8: return BoneBlock::BoneBlock(BoneBlock::Axis::Z); case (217 << 4) | 0: return StructureVoid::StructureVoid(); case (218 << 4) | 0: return Observer::Observer(eBlockFace::BLOCK_FACE_YM, false); case (218 << 4) | 1: return Observer::Observer(eBlockFace::BLOCK_FACE_YP, false); case (218 << 4) | 2: return Observer::Observer(eBlockFace::BLOCK_FACE_ZM, false); case (218 << 4) | 3: return Observer::Observer(eBlockFace::BLOCK_FACE_ZP, false); case (218 << 4) | 4: return Observer::Observer(eBlockFace::BLOCK_FACE_XM, false); case (218 << 4) | 5: return Observer::Observer(eBlockFace::BLOCK_FACE_XP, false); case (218 << 4) | 8: return Observer::Observer(eBlockFace::BLOCK_FACE_YM, true); case (218 << 4) | 9: return Observer::Observer(eBlockFace::BLOCK_FACE_YP, true); case (218 << 4) | 10: return Observer::Observer(eBlockFace::BLOCK_FACE_ZM, true); case (218 << 4) | 11: return Observer::Observer(eBlockFace::BLOCK_FACE_ZP, true); case (218 << 4) | 12: return Observer::Observer(eBlockFace::BLOCK_FACE_XM, true); case (218 << 4) | 13: return Observer::Observer(eBlockFace::BLOCK_FACE_XP, true); case (219 << 4) | 0: return WhiteShulkerBox::WhiteShulkerBox(eBlockFace::BLOCK_FACE_YM); case (219 << 4) | 1: return WhiteShulkerBox::WhiteShulkerBox(eBlockFace::BLOCK_FACE_YP); case (219 << 4) | 2: return WhiteShulkerBox::WhiteShulkerBox(eBlockFace::BLOCK_FACE_ZM); case (219 << 4) | 3: return WhiteShulkerBox::WhiteShulkerBox(eBlockFace::BLOCK_FACE_ZP); case (219 << 4) | 4: return WhiteShulkerBox::WhiteShulkerBox(eBlockFace::BLOCK_FACE_XM); case (219 << 4) | 5: return WhiteShulkerBox::WhiteShulkerBox(eBlockFace::BLOCK_FACE_XP); case (220 << 4) | 0: return OrangeShulkerBox::OrangeShulkerBox(eBlockFace::BLOCK_FACE_YM); case (220 << 4) | 1: return OrangeShulkerBox::OrangeShulkerBox(eBlockFace::BLOCK_FACE_YP); case (220 << 4) | 2: return OrangeShulkerBox::OrangeShulkerBox(eBlockFace::BLOCK_FACE_ZM); case (220 << 4) | 3: return OrangeShulkerBox::OrangeShulkerBox(eBlockFace::BLOCK_FACE_ZP); case (220 << 4) | 4: return OrangeShulkerBox::OrangeShulkerBox(eBlockFace::BLOCK_FACE_XM); case (220 << 4) | 5: return OrangeShulkerBox::OrangeShulkerBox(eBlockFace::BLOCK_FACE_XP); case (221 << 4) | 0: return MagentaShulkerBox::MagentaShulkerBox(eBlockFace::BLOCK_FACE_YM); case (221 << 4) | 1: return MagentaShulkerBox::MagentaShulkerBox(eBlockFace::BLOCK_FACE_YP); case (221 << 4) | 2: return MagentaShulkerBox::MagentaShulkerBox(eBlockFace::BLOCK_FACE_ZM); case (221 << 4) | 3: return MagentaShulkerBox::MagentaShulkerBox(eBlockFace::BLOCK_FACE_ZP); case (221 << 4) | 4: return MagentaShulkerBox::MagentaShulkerBox(eBlockFace::BLOCK_FACE_XM); case (221 << 4) | 5: return MagentaShulkerBox::MagentaShulkerBox(eBlockFace::BLOCK_FACE_XP); case (222 << 4) | 0: return LightBlueShulkerBox::LightBlueShulkerBox(eBlockFace::BLOCK_FACE_YM); case (222 << 4) | 1: return LightBlueShulkerBox::LightBlueShulkerBox(eBlockFace::BLOCK_FACE_YP); case (222 << 4) | 2: return LightBlueShulkerBox::LightBlueShulkerBox(eBlockFace::BLOCK_FACE_ZM); case (222 << 4) | 3: return LightBlueShulkerBox::LightBlueShulkerBox(eBlockFace::BLOCK_FACE_ZP); case (222 << 4) | 4: return LightBlueShulkerBox::LightBlueShulkerBox(eBlockFace::BLOCK_FACE_XM); case (222 << 4) | 5: return LightBlueShulkerBox::LightBlueShulkerBox(eBlockFace::BLOCK_FACE_XP); case (223 << 4) | 0: return YellowShulkerBox::YellowShulkerBox(eBlockFace::BLOCK_FACE_YM); case (223 << 4) | 1: return YellowShulkerBox::YellowShulkerBox(eBlockFace::BLOCK_FACE_YP); case (223 << 4) | 2: return YellowShulkerBox::YellowShulkerBox(eBlockFace::BLOCK_FACE_ZM); case (223 << 4) | 3: return YellowShulkerBox::YellowShulkerBox(eBlockFace::BLOCK_FACE_ZP); case (223 << 4) | 4: return YellowShulkerBox::YellowShulkerBox(eBlockFace::BLOCK_FACE_XM); case (223 << 4) | 5: return YellowShulkerBox::YellowShulkerBox(eBlockFace::BLOCK_FACE_XP); case (224 << 4) | 0: return LimeShulkerBox::LimeShulkerBox(eBlockFace::BLOCK_FACE_YM); case (224 << 4) | 1: return LimeShulkerBox::LimeShulkerBox(eBlockFace::BLOCK_FACE_YP); case (224 << 4) | 2: return LimeShulkerBox::LimeShulkerBox(eBlockFace::BLOCK_FACE_ZM); case (224 << 4) | 3: return LimeShulkerBox::LimeShulkerBox(eBlockFace::BLOCK_FACE_ZP); case (224 << 4) | 4: return LimeShulkerBox::LimeShulkerBox(eBlockFace::BLOCK_FACE_XM); case (224 << 4) | 5: return LimeShulkerBox::LimeShulkerBox(eBlockFace::BLOCK_FACE_XP); case (225 << 4) | 0: return PinkShulkerBox::PinkShulkerBox(eBlockFace::BLOCK_FACE_YM); case (225 << 4) | 1: return PinkShulkerBox::PinkShulkerBox(eBlockFace::BLOCK_FACE_YP); case (225 << 4) | 2: return PinkShulkerBox::PinkShulkerBox(eBlockFace::BLOCK_FACE_ZM); case (225 << 4) | 3: return PinkShulkerBox::PinkShulkerBox(eBlockFace::BLOCK_FACE_ZP); case (225 << 4) | 4: return PinkShulkerBox::PinkShulkerBox(eBlockFace::BLOCK_FACE_XM); case (225 << 4) | 5: return PinkShulkerBox::PinkShulkerBox(eBlockFace::BLOCK_FACE_XP); case (226 << 4) | 0: return GrayShulkerBox::GrayShulkerBox(eBlockFace::BLOCK_FACE_YM); case (226 << 4) | 1: return GrayShulkerBox::GrayShulkerBox(eBlockFace::BLOCK_FACE_YP); case (226 << 4) | 2: return GrayShulkerBox::GrayShulkerBox(eBlockFace::BLOCK_FACE_ZM); case (226 << 4) | 3: return GrayShulkerBox::GrayShulkerBox(eBlockFace::BLOCK_FACE_ZP); case (226 << 4) | 4: return GrayShulkerBox::GrayShulkerBox(eBlockFace::BLOCK_FACE_XM); case (226 << 4) | 5: return GrayShulkerBox::GrayShulkerBox(eBlockFace::BLOCK_FACE_XP); case (227 << 4) | 0: return LightGrayShulkerBox::LightGrayShulkerBox(eBlockFace::BLOCK_FACE_YM); case (227 << 4) | 1: return LightGrayShulkerBox::LightGrayShulkerBox(eBlockFace::BLOCK_FACE_YP); case (227 << 4) | 2: return LightGrayShulkerBox::LightGrayShulkerBox(eBlockFace::BLOCK_FACE_ZM); case (227 << 4) | 3: return LightGrayShulkerBox::LightGrayShulkerBox(eBlockFace::BLOCK_FACE_ZP); case (227 << 4) | 4: return LightGrayShulkerBox::LightGrayShulkerBox(eBlockFace::BLOCK_FACE_XM); case (227 << 4) | 5: return LightGrayShulkerBox::LightGrayShulkerBox(eBlockFace::BLOCK_FACE_XP); case (228 << 4) | 0: return CyanShulkerBox::CyanShulkerBox(eBlockFace::BLOCK_FACE_YM); case (228 << 4) | 1: return CyanShulkerBox::CyanShulkerBox(eBlockFace::BLOCK_FACE_YP); case (228 << 4) | 2: return CyanShulkerBox::CyanShulkerBox(eBlockFace::BLOCK_FACE_ZM); case (228 << 4) | 3: return CyanShulkerBox::CyanShulkerBox(eBlockFace::BLOCK_FACE_ZP); case (228 << 4) | 4: return CyanShulkerBox::CyanShulkerBox(eBlockFace::BLOCK_FACE_XM); case (228 << 4) | 5: return CyanShulkerBox::CyanShulkerBox(eBlockFace::BLOCK_FACE_XP); case (229 << 4) | 0: return PurpleShulkerBox::PurpleShulkerBox(eBlockFace::BLOCK_FACE_YM); case (229 << 4) | 1: return PurpleShulkerBox::PurpleShulkerBox(eBlockFace::BLOCK_FACE_YP); case (229 << 4) | 2: return PurpleShulkerBox::PurpleShulkerBox(eBlockFace::BLOCK_FACE_ZM); case (229 << 4) | 3: return PurpleShulkerBox::PurpleShulkerBox(eBlockFace::BLOCK_FACE_ZP); case (229 << 4) | 4: return PurpleShulkerBox::PurpleShulkerBox(eBlockFace::BLOCK_FACE_XM); case (229 << 4) | 5: return PurpleShulkerBox::PurpleShulkerBox(eBlockFace::BLOCK_FACE_XP); case (230 << 4) | 0: return BlueShulkerBox::BlueShulkerBox(eBlockFace::BLOCK_FACE_YM); case (230 << 4) | 1: return BlueShulkerBox::BlueShulkerBox(eBlockFace::BLOCK_FACE_YP); case (230 << 4) | 2: return BlueShulkerBox::BlueShulkerBox(eBlockFace::BLOCK_FACE_ZM); case (230 << 4) | 3: return BlueShulkerBox::BlueShulkerBox(eBlockFace::BLOCK_FACE_ZP); case (230 << 4) | 4: return BlueShulkerBox::BlueShulkerBox(eBlockFace::BLOCK_FACE_XM); case (230 << 4) | 5: return BlueShulkerBox::BlueShulkerBox(eBlockFace::BLOCK_FACE_XP); case (231 << 4) | 0: return BrownShulkerBox::BrownShulkerBox(eBlockFace::BLOCK_FACE_YM); case (231 << 4) | 1: return BrownShulkerBox::BrownShulkerBox(eBlockFace::BLOCK_FACE_YP); case (231 << 4) | 2: return BrownShulkerBox::BrownShulkerBox(eBlockFace::BLOCK_FACE_ZM); case (231 << 4) | 3: return BrownShulkerBox::BrownShulkerBox(eBlockFace::BLOCK_FACE_ZP); case (231 << 4) | 4: return BrownShulkerBox::BrownShulkerBox(eBlockFace::BLOCK_FACE_XM); case (231 << 4) | 5: return BrownShulkerBox::BrownShulkerBox(eBlockFace::BLOCK_FACE_XP); case (232 << 4) | 0: return GreenShulkerBox::GreenShulkerBox(eBlockFace::BLOCK_FACE_YM); case (232 << 4) | 1: return GreenShulkerBox::GreenShulkerBox(eBlockFace::BLOCK_FACE_YP); case (232 << 4) | 2: return GreenShulkerBox::GreenShulkerBox(eBlockFace::BLOCK_FACE_ZM); case (232 << 4) | 3: return GreenShulkerBox::GreenShulkerBox(eBlockFace::BLOCK_FACE_ZP); case (232 << 4) | 4: return GreenShulkerBox::GreenShulkerBox(eBlockFace::BLOCK_FACE_XM); case (232 << 4) | 5: return GreenShulkerBox::GreenShulkerBox(eBlockFace::BLOCK_FACE_XP); case (233 << 4) | 0: return RedShulkerBox::RedShulkerBox(eBlockFace::BLOCK_FACE_YM); case (233 << 4) | 1: return RedShulkerBox::RedShulkerBox(eBlockFace::BLOCK_FACE_YP); case (233 << 4) | 2: return RedShulkerBox::RedShulkerBox(eBlockFace::BLOCK_FACE_ZM); case (233 << 4) | 3: return RedShulkerBox::RedShulkerBox(eBlockFace::BLOCK_FACE_ZP); case (233 << 4) | 4: return RedShulkerBox::RedShulkerBox(eBlockFace::BLOCK_FACE_XM); case (233 << 4) | 5: return RedShulkerBox::RedShulkerBox(eBlockFace::BLOCK_FACE_XP); case (234 << 4) | 0: return BlackShulkerBox::BlackShulkerBox(eBlockFace::BLOCK_FACE_YM); case (234 << 4) | 1: return BlackShulkerBox::BlackShulkerBox(eBlockFace::BLOCK_FACE_YP); case (234 << 4) | 2: return BlackShulkerBox::BlackShulkerBox(eBlockFace::BLOCK_FACE_ZM); case (234 << 4) | 3: return BlackShulkerBox::BlackShulkerBox(eBlockFace::BLOCK_FACE_ZP); case (234 << 4) | 4: return BlackShulkerBox::BlackShulkerBox(eBlockFace::BLOCK_FACE_XM); case (234 << 4) | 5: return BlackShulkerBox::BlackShulkerBox(eBlockFace::BLOCK_FACE_XP); case (235 << 4) | 0: return WhiteGlazedTerracotta::WhiteGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP); case (235 << 4) | 1: return WhiteGlazedTerracotta::WhiteGlazedTerracotta(eBlockFace::BLOCK_FACE_XM); case (235 << 4) | 2: return WhiteGlazedTerracotta::WhiteGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM); case (235 << 4) | 3: return WhiteGlazedTerracotta::WhiteGlazedTerracotta(eBlockFace::BLOCK_FACE_XP); case (236 << 4) | 0: return OrangeGlazedTerracotta::OrangeGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP); case (236 << 4) | 1: return OrangeGlazedTerracotta::OrangeGlazedTerracotta(eBlockFace::BLOCK_FACE_XM); case (236 << 4) | 2: return OrangeGlazedTerracotta::OrangeGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM); case (236 << 4) | 3: return OrangeGlazedTerracotta::OrangeGlazedTerracotta(eBlockFace::BLOCK_FACE_XP); case (237 << 4) | 0: return MagentaGlazedTerracotta::MagentaGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP); case (237 << 4) | 1: return MagentaGlazedTerracotta::MagentaGlazedTerracotta(eBlockFace::BLOCK_FACE_XM); case (237 << 4) | 2: return MagentaGlazedTerracotta::MagentaGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM); case (237 << 4) | 3: return MagentaGlazedTerracotta::MagentaGlazedTerracotta(eBlockFace::BLOCK_FACE_XP); case (238 << 4) | 0: return LightBlueGlazedTerracotta::LightBlueGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP); case (238 << 4) | 1: return LightBlueGlazedTerracotta::LightBlueGlazedTerracotta(eBlockFace::BLOCK_FACE_XM); case (238 << 4) | 2: return LightBlueGlazedTerracotta::LightBlueGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM); case (238 << 4) | 3: return LightBlueGlazedTerracotta::LightBlueGlazedTerracotta(eBlockFace::BLOCK_FACE_XP); case (239 << 4) | 0: return YellowGlazedTerracotta::YellowGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP); case (239 << 4) | 1: return YellowGlazedTerracotta::YellowGlazedTerracotta(eBlockFace::BLOCK_FACE_XM); case (239 << 4) | 2: return YellowGlazedTerracotta::YellowGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM); case (239 << 4) | 3: return YellowGlazedTerracotta::YellowGlazedTerracotta(eBlockFace::BLOCK_FACE_XP); case (240 << 4) | 0: return LimeGlazedTerracotta::LimeGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP); case (240 << 4) | 1: return LimeGlazedTerracotta::LimeGlazedTerracotta(eBlockFace::BLOCK_FACE_XM); case (240 << 4) | 2: return LimeGlazedTerracotta::LimeGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM); case (240 << 4) | 3: return LimeGlazedTerracotta::LimeGlazedTerracotta(eBlockFace::BLOCK_FACE_XP); case (241 << 4) | 0: return PinkGlazedTerracotta::PinkGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP); case (241 << 4) | 1: return PinkGlazedTerracotta::PinkGlazedTerracotta(eBlockFace::BLOCK_FACE_XM); case (241 << 4) | 2: return PinkGlazedTerracotta::PinkGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM); case (241 << 4) | 3: return PinkGlazedTerracotta::PinkGlazedTerracotta(eBlockFace::BLOCK_FACE_XP); case (242 << 4) | 0: return GrayGlazedTerracotta::GrayGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP); case (242 << 4) | 1: return GrayGlazedTerracotta::GrayGlazedTerracotta(eBlockFace::BLOCK_FACE_XM); case (242 << 4) | 2: return GrayGlazedTerracotta::GrayGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM); case (242 << 4) | 3: return GrayGlazedTerracotta::GrayGlazedTerracotta(eBlockFace::BLOCK_FACE_XP); case (243 << 4) | 0: return LightGrayGlazedTerracotta::LightGrayGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP); case (243 << 4) | 1: return LightGrayGlazedTerracotta::LightGrayGlazedTerracotta(eBlockFace::BLOCK_FACE_XM); case (243 << 4) | 2: return LightGrayGlazedTerracotta::LightGrayGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM); case (243 << 4) | 3: return LightGrayGlazedTerracotta::LightGrayGlazedTerracotta(eBlockFace::BLOCK_FACE_XP); case (244 << 4) | 0: return CyanGlazedTerracotta::CyanGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP); case (244 << 4) | 1: return CyanGlazedTerracotta::CyanGlazedTerracotta(eBlockFace::BLOCK_FACE_XM); case (244 << 4) | 2: return CyanGlazedTerracotta::CyanGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM); case (244 << 4) | 3: return CyanGlazedTerracotta::CyanGlazedTerracotta(eBlockFace::BLOCK_FACE_XP); case (245 << 4) | 0: return PurpleGlazedTerracotta::PurpleGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP); case (245 << 4) | 1: return PurpleGlazedTerracotta::PurpleGlazedTerracotta(eBlockFace::BLOCK_FACE_XM); case (245 << 4) | 2: return PurpleGlazedTerracotta::PurpleGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM); case (245 << 4) | 3: return PurpleGlazedTerracotta::PurpleGlazedTerracotta(eBlockFace::BLOCK_FACE_XP); case (246 << 4) | 0: return BlueGlazedTerracotta::BlueGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP); case (246 << 4) | 1: return BlueGlazedTerracotta::BlueGlazedTerracotta(eBlockFace::BLOCK_FACE_XM); case (246 << 4) | 2: return BlueGlazedTerracotta::BlueGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM); case (246 << 4) | 3: return BlueGlazedTerracotta::BlueGlazedTerracotta(eBlockFace::BLOCK_FACE_XP); case (247 << 4) | 0: return BrownGlazedTerracotta::BrownGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP); case (247 << 4) | 1: return BrownGlazedTerracotta::BrownGlazedTerracotta(eBlockFace::BLOCK_FACE_XM); case (247 << 4) | 2: return BrownGlazedTerracotta::BrownGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM); case (247 << 4) | 3: return BrownGlazedTerracotta::BrownGlazedTerracotta(eBlockFace::BLOCK_FACE_XP); case (248 << 4) | 0: return GreenGlazedTerracotta::GreenGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP); case (248 << 4) | 1: return GreenGlazedTerracotta::GreenGlazedTerracotta(eBlockFace::BLOCK_FACE_XM); case (248 << 4) | 2: return GreenGlazedTerracotta::GreenGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM); case (248 << 4) | 3: return GreenGlazedTerracotta::GreenGlazedTerracotta(eBlockFace::BLOCK_FACE_XP); case (249 << 4) | 0: return RedGlazedTerracotta::RedGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP); case (249 << 4) | 1: return RedGlazedTerracotta::RedGlazedTerracotta(eBlockFace::BLOCK_FACE_XM); case (249 << 4) | 2: return RedGlazedTerracotta::RedGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM); case (249 << 4) | 3: return RedGlazedTerracotta::RedGlazedTerracotta(eBlockFace::BLOCK_FACE_XP); case (250 << 4) | 0: return BlackGlazedTerracotta::BlackGlazedTerracotta(eBlockFace::BLOCK_FACE_ZP); case (250 << 4) | 1: return BlackGlazedTerracotta::BlackGlazedTerracotta(eBlockFace::BLOCK_FACE_XM); case (250 << 4) | 2: return BlackGlazedTerracotta::BlackGlazedTerracotta(eBlockFace::BLOCK_FACE_ZM); case (250 << 4) | 3: return BlackGlazedTerracotta::BlackGlazedTerracotta(eBlockFace::BLOCK_FACE_XP); case (251 << 4) | 0: return WhiteConcrete::WhiteConcrete(); case (251 << 4) | 1: return OrangeConcrete::OrangeConcrete(); case (251 << 4) | 2: return MagentaConcrete::MagentaConcrete(); case (251 << 4) | 3: return LightBlueConcrete::LightBlueConcrete(); case (251 << 4) | 4: return YellowConcrete::YellowConcrete(); case (251 << 4) | 5: return LimeConcrete::LimeConcrete(); case (251 << 4) | 6: return PinkConcrete::PinkConcrete(); case (251 << 4) | 7: return GrayConcrete::GrayConcrete(); case (251 << 4) | 8: return LightGrayConcrete::LightGrayConcrete(); case (251 << 4) | 9: return CyanConcrete::CyanConcrete(); case (251 << 4) | 10: return PurpleConcrete::PurpleConcrete(); case (251 << 4) | 11: return BlueConcrete::BlueConcrete(); case (251 << 4) | 12: return BrownConcrete::BrownConcrete(); case (251 << 4) | 13: return GreenConcrete::GreenConcrete(); case (251 << 4) | 14: return RedConcrete::RedConcrete(); case (251 << 4) | 15: return BlackConcrete::BlackConcrete(); case (252 << 4) | 0: return WhiteConcretePowder::WhiteConcretePowder(); case (252 << 4) | 1: return OrangeConcretePowder::OrangeConcretePowder(); case (252 << 4) | 2: return MagentaConcretePowder::MagentaConcretePowder(); case (252 << 4) | 3: return LightBlueConcretePowder::LightBlueConcretePowder(); case (252 << 4) | 4: return YellowConcretePowder::YellowConcretePowder(); case (252 << 4) | 5: return LimeConcretePowder::LimeConcretePowder(); case (252 << 4) | 6: return PinkConcretePowder::PinkConcretePowder(); case (252 << 4) | 7: return GrayConcretePowder::GrayConcretePowder(); case (252 << 4) | 8: return LightGrayConcretePowder::LightGrayConcretePowder(); case (252 << 4) | 9: return CyanConcretePowder::CyanConcretePowder(); case (252 << 4) | 10: return PurpleConcretePowder::PurpleConcretePowder(); case (252 << 4) | 11: return BlueConcretePowder::BlueConcretePowder(); case (252 << 4) | 12: return BrownConcretePowder::BrownConcretePowder(); case (252 << 4) | 13: return GreenConcretePowder::GreenConcretePowder(); case (252 << 4) | 14: return RedConcretePowder::RedConcretePowder(); case (252 << 4) | 15: return BlackConcretePowder::BlackConcretePowder(); case (255 << 4) | 0: return StructureBlock::StructureBlock(StructureBlock::Mode::Save); case (255 << 4) | 1: return StructureBlock::StructureBlock(StructureBlock::Mode::Load); case (255 << 4) | 2: return StructureBlock::StructureBlock(StructureBlock::Mode::Corner); case (255 << 4) | 3: return StructureBlock::StructureBlock(StructureBlock::Mode::Data); default: return Air::Air(); } } Item FromItem(const short Item, const short Damage) { switch ((Item << 16) | Damage) { case (1 << 16) | 0: return Item::Stone; case (1 << 16) | 1: return Item::Granite; case (1 << 16) | 2: return Item::PolishedGranite; case (1 << 16) | 3: return Item::Diorite; case (1 << 16) | 4: return Item::PolishedDiorite; case (1 << 16) | 5: return Item::Andesite; case (1 << 16) | 6: return Item::PolishedAndesite; case (2 << 16) | 0: return Item::GrassBlock; case (3 << 16) | 0: return Item::Dirt; case (3 << 16) | 1: return Item::CoarseDirt; case (3 << 16) | 2: return Item::Podzol; case (4 << 16) | 0: return Item::Cobblestone; case (5 << 16) | 0: return Item::OakPlanks; case (5 << 16) | 1: return Item::SprucePlanks; case (5 << 16) | 2: return Item::BirchPlanks; case (5 << 16) | 3: return Item::JunglePlanks; case (5 << 16) | 4: return Item::AcaciaPlanks; case (5 << 16) | 5: return Item::DarkOakPlanks; case (6 << 16) | 0: return Item::OakSapling; case (6 << 16) | 1: return Item::SpruceSapling; case (6 << 16) | 2: return Item::BirchSapling; case (6 << 16) | 3: return Item::JungleSapling; case (6 << 16) | 4: return Item::AcaciaSapling; case (6 << 16) | 5: return Item::DarkOakSapling; case (7 << 16) | 0: return Item::Bedrock; case (12 << 16) | 0: return Item::Sand; case (12 << 16) | 1: return Item::RedSand; case (13 << 16) | 0: return Item::Gravel; case (14 << 16) | 0: return Item::GoldOre; case (15 << 16) | 0: return Item::IronOre; case (16 << 16) | 0: return Item::CoalOre; case (17 << 16) | 0: return Item::OakLog; case (17 << 16) | 1: return Item::SpruceLog; case (17 << 16) | 2: return Item::BirchLog; case (17 << 16) | 3: return Item::JungleLog; case (162 << 16) | 0: return Item::AcaciaLog; case (162 << 16) | 1: return Item::DarkOakLog; case (18 << 16) | 0: return Item::OakLeaves; case (18 << 16) | 1: return Item::SpruceLeaves; case (18 << 16) | 2: return Item::BirchLeaves; case (18 << 16) | 3: return Item::JungleLeaves; case (161 << 16) | 0: return Item::AcaciaLeaves; case (161 << 16) | 1: return Item::DarkOakLeaves; case (19 << 16) | 0: return Item::Sponge; case (19 << 16) | 1: return Item::WetSponge; case (20 << 16) | 0: return Item::Glass; case (21 << 16) | 0: return Item::LapisOre; case (22 << 16) | 0: return Item::LapisBlock; case (23 << 16) | 0: return Item::Dispenser; case (24 << 16) | 0: return Item::Sandstone; case (24 << 16) | 1: return Item::ChiseledSandstone; case (24 << 16) | 2: return Item::CutSandstone; case (25 << 16) | 0: return Item::NoteBlock; case (27 << 16) | 0: return Item::PoweredRail; case (28 << 16) | 0: return Item::DetectorRail; case (29 << 16) | 0: return Item::StickyPiston; case (30 << 16) | 0: return Item::Cobweb; case (31 << 16) | 2: return Item::Fern; case (32 << 16) | 0: return Item::DeadBush; case (33 << 16) | 0: return Item::Piston; case (35 << 16) | 0: return Item::WhiteWool; case (35 << 16) | 1: return Item::OrangeWool; case (35 << 16) | 2: return Item::MagentaWool; case (35 << 16) | 3: return Item::LightBlueWool; case (35 << 16) | 4: return Item::YellowWool; case (35 << 16) | 5: return Item::LimeWool; case (35 << 16) | 6: return Item::PinkWool; case (35 << 16) | 7: return Item::GrayWool; case (35 << 16) | 8: return Item::LightGrayWool; case (35 << 16) | 9: return Item::CyanWool; case (35 << 16) | 10: return Item::PurpleWool; case (35 << 16) | 11: return Item::BlueWool; case (35 << 16) | 12: return Item::BrownWool; case (35 << 16) | 13: return Item::GreenWool; case (35 << 16) | 14: return Item::RedWool; case (35 << 16) | 15: return Item::BlackWool; case (37 << 16) | 0: return Item::Dandelion; case (38 << 16) | 0: return Item::Poppy; case (38 << 16) | 1: return Item::BlueOrchid; case (38 << 16) | 2: return Item::Allium; case (38 << 16) | 3: return Item::AzureBluet; case (38 << 16) | 4: return Item::RedTulip; case (38 << 16) | 5: return Item::OrangeTulip; case (38 << 16) | 6: return Item::WhiteTulip; case (38 << 16) | 7: return Item::PinkTulip; case (38 << 16) | 8: return Item::OxeyeDaisy; case (39 << 16) | 0: return Item::BrownMushroom; case (40 << 16) | 0: return Item::RedMushroom; case (41 << 16) | 0: return Item::GoldBlock; case (42 << 16) | 0: return Item::IronBlock; case (126 << 16) | 0: return Item::OakSlab; case (126 << 16) | 1: return Item::SpruceSlab; case (126 << 16) | 2: return Item::BirchSlab; case (126 << 16) | 3: return Item::JungleSlab; case (126 << 16) | 4: return Item::AcaciaSlab; case (126 << 16) | 5: return Item::DarkOakSlab; case (44 << 16) | 2: return Item::StoneSlab; case (44 << 16) | 1: return Item::SandstoneSlab; case (44 << 16) | 3: return Item::CobblestoneSlab; case (44 << 16) | 4: return Item::BrickSlab; case (44 << 16) | 5: return Item::StoneBrickSlab; case (44 << 16) | 6: return Item::NetherBrickSlab; case (44 << 16) | 7: return Item::QuartzSlab; case (182 << 16) | 0: return Item::RedSandstoneSlab; case (205 << 16) | 0: return Item::PurpurSlab; case (43 << 16) | 7: return Item::SmoothQuartz; case (43 << 16) | 8: return Item::SmoothStone; case (45 << 16) | 0: return Item::Bricks; case (46 << 16) | 0: return Item::TNT; case (47 << 16) | 0: return Item::Bookshelf; case (48 << 16) | 0: return Item::MossyCobblestone; case (49 << 16) | 0: return Item::Obsidian; case (50 << 16) | 0: return Item::Torch; case (198 << 16) | 0: return Item::EndRod; case (199 << 16) | 0: return Item::ChorusPlant; case (200 << 16) | 0: return Item::ChorusFlower; case (201 << 16) | 0: return Item::PurpurBlock; case (202 << 16) | 0: return Item::PurpurPillar; case (203 << 16) | 0: return Item::PurpurStairs; case (52 << 16) | 0: return Item::Spawner; case (53 << 16) | 0: return Item::OakStairs; case (54 << 16) | 0: return Item::Chest; case (56 << 16) | 0: return Item::DiamondOre; case (57 << 16) | 0: return Item::DiamondBlock; case (58 << 16) | 0: return Item::CraftingTable; case (60 << 16) | 0: return Item::Farmland; case (61 << 16) | 0: return Item::Furnace; case (65 << 16) | 0: return Item::Ladder; case (66 << 16) | 0: return Item::Rail; case (67 << 16) | 0: return Item::CobblestoneStairs; case (69 << 16) | 0: return Item::Lever; case (70 << 16) | 0: return Item::StonePressurePlate; case (72 << 16) | 0: return Item::OakPressurePlate; case (73 << 16) | 0: return Item::RedstoneOre; case (76 << 16) | 0: return Item::RedstoneTorch; case (77 << 16) | 0: return Item::StoneButton; case (78 << 16) | 0: return Item::Snow; case (79 << 16) | 0: return Item::Ice; case (80 << 16) | 0: return Item::SnowBlock; case (81 << 16) | 0: return Item::Cactus; case (82 << 16) | 0: return Item::Clay; case (84 << 16) | 0: return Item::Jukebox; case (85 << 16) | 0: return Item::OakFence; case (188 << 16) | 0: return Item::SpruceFence; case (189 << 16) | 0: return Item::BirchFence; case (190 << 16) | 0: return Item::JungleFence; case (192 << 16) | 0: return Item::AcaciaFence; case (191 << 16) | 0: return Item::DarkOakFence; case (86 << 16) | 0: return Item::Pumpkin; case (87 << 16) | 0: return Item::Netherrack; case (88 << 16) | 0: return Item::SoulSand; case (89 << 16) | 0: return Item::Glowstone; case (91 << 16) | 0: return Item::JackOLantern; case (96 << 16) | 0: return Item::OakTrapdoor; case (97 << 16) | 0: return Item::InfestedStone; case (97 << 16) | 1: return Item::InfestedCobblestone; case (97 << 16) | 2: return Item::InfestedStoneBricks; case (97 << 16) | 3: return Item::InfestedMossyStoneBricks; case (97 << 16) | 4: return Item::InfestedCrackedStoneBricks; case (97 << 16) | 5: return Item::InfestedChiseledStoneBricks; case (98 << 16) | 0: return Item::StoneBricks; case (98 << 16) | 1: return Item::MossyStoneBricks; case (98 << 16) | 2: return Item::CrackedStoneBricks; case (98 << 16) | 3: return Item::ChiseledStoneBricks; case (99 << 16) | 0: return Item::BrownMushroomBlock; case (100 << 16) | 0: return Item::RedMushroomBlock; case (101 << 16) | 0: return Item::IronBars; case (102 << 16) | 0: return Item::GlassPane; case (103 << 16) | 0: return Item::Melon; case (106 << 16) | 0: return Item::Vine; case (107 << 16) | 0: return Item::OakFenceGate; case (183 << 16) | 0: return Item::SpruceFenceGate; case (184 << 16) | 0: return Item::BirchFenceGate; case (185 << 16) | 0: return Item::JungleFenceGate; case (187 << 16) | 0: return Item::AcaciaFenceGate; case (186 << 16) | 0: return Item::DarkOakFenceGate; case (108 << 16) | 0: return Item::BrickStairs; case (109 << 16) | 0: return Item::StoneBrickStairs; case (110 << 16) | 0: return Item::Mycelium; case (111 << 16) | 0: return Item::LilyPad; case (112 << 16) | 0: return Item::NetherBricks; case (113 << 16) | 0: return Item::NetherBrickFence; case (114 << 16) | 0: return Item::NetherBrickStairs; case (116 << 16) | 0: return Item::EnchantingTable; case (120 << 16) | 0: return Item::EndPortalFrame; case (121 << 16) | 0: return Item::EndStone; case (206 << 16) | 0: return Item::EndStoneBricks; case (122 << 16) | 0: return Item::DragonEgg; case (123 << 16) | 0: return Item::RedstoneLamp; case (128 << 16) | 0: return Item::SandstoneStairs; case (129 << 16) | 0: return Item::EmeraldOre; case (130 << 16) | 0: return Item::EnderChest; case (131 << 16) | 0: return Item::TripwireHook; case (133 << 16) | 0: return Item::EmeraldBlock; case (134 << 16) | 0: return Item::SpruceStairs; case (135 << 16) | 0: return Item::BirchStairs; case (136 << 16) | 0: return Item::JungleStairs; case (137 << 16) | 0: return Item::CommandBlock; case (138 << 16) | 0: return Item::Beacon; case (139 << 16) | 0: return Item::CobblestoneWall; case (139 << 16) | 1: return Item::MossyCobblestoneWall; case (143 << 16) | 0: return Item::OakButton; case (145 << 16) | 0: return Item::Anvil; case (145 << 16) | 1: return Item::ChippedAnvil; case (145 << 16) | 2: return Item::DamagedAnvil; case (146 << 16) | 0: return Item::TrappedChest; case (147 << 16) | 0: return Item::LightWeightedPressurePlate; case (148 << 16) | 0: return Item::HeavyWeightedPressurePlate; case (151 << 16) | 0: return Item::DaylightDetector; case (152 << 16) | 0: return Item::RedstoneBlock; case (153 << 16) | 0: return Item::NetherQuartzOre; case (154 << 16) | 0: return Item::Hopper; case (155 << 16) | 1: return Item::ChiseledQuartzBlock; case (155 << 16) | 0: return Item::QuartzBlock; case (155 << 16) | 2: return Item::QuartzPillar; case (156 << 16) | 0: return Item::QuartzStairs; case (157 << 16) | 0: return Item::ActivatorRail; case (158 << 16) | 0: return Item::Dropper; case (159 << 16) | 0: return Item::WhiteTerracotta; case (159 << 16) | 1: return Item::OrangeTerracotta; case (159 << 16) | 2: return Item::MagentaTerracotta; case (159 << 16) | 3: return Item::LightBlueTerracotta; case (159 << 16) | 4: return Item::YellowTerracotta; case (159 << 16) | 5: return Item::LimeTerracotta; case (159 << 16) | 6: return Item::PinkTerracotta; case (159 << 16) | 7: return Item::GrayTerracotta; case (159 << 16) | 8: return Item::LightGrayTerracotta; case (159 << 16) | 9: return Item::CyanTerracotta; case (159 << 16) | 10: return Item::PurpleTerracotta; case (159 << 16) | 11: return Item::BlueTerracotta; case (159 << 16) | 12: return Item::BrownTerracotta; case (159 << 16) | 13: return Item::GreenTerracotta; case (159 << 16) | 14: return Item::RedTerracotta; case (159 << 16) | 15: return Item::BlackTerracotta; case (166 << 16) | 0: return Item::Barrier; case (167 << 16) | 0: return Item::IronTrapdoor; case (170 << 16) | 0: return Item::HayBale; case (171 << 16) | 0: return Item::WhiteCarpet; case (171 << 16) | 1: return Item::OrangeCarpet; case (171 << 16) | 2: return Item::MagentaCarpet; case (171 << 16) | 3: return Item::LightBlueCarpet; case (171 << 16) | 4: return Item::YellowCarpet; case (171 << 16) | 5: return Item::LimeCarpet; case (171 << 16) | 6: return Item::PinkCarpet; case (171 << 16) | 7: return Item::GrayCarpet; case (171 << 16) | 8: return Item::LightGrayCarpet; case (171 << 16) | 9: return Item::CyanCarpet; case (171 << 16) | 10: return Item::PurpleCarpet; case (171 << 16) | 11: return Item::BlueCarpet; case (171 << 16) | 12: return Item::BrownCarpet; case (171 << 16) | 13: return Item::GreenCarpet; case (171 << 16) | 14: return Item::RedCarpet; case (171 << 16) | 15: return Item::BlackCarpet; case (172 << 16) | 0: return Item::Terracotta; case (173 << 16) | 0: return Item::CoalBlock; case (174 << 16) | 0: return Item::PackedIce; case (163 << 16) | 0: return Item::AcaciaStairs; case (164 << 16) | 0: return Item::DarkOakStairs; case (165 << 16) | 0: return Item::SlimeBlock; case (208 << 16) | 0: return Item::GrassPath; case (175 << 16) | 0: return Item::Sunflower; case (175 << 16) | 1: return Item::Lilac; case (175 << 16) | 4: return Item::RoseBush; case (175 << 16) | 5: return Item::Peony; case (175 << 16) | 2: return Item::TallGrass; case (175 << 16) | 3: return Item::LargeFern; case (95 << 16) | 0: return Item::WhiteStainedGlass; case (95 << 16) | 1: return Item::OrangeStainedGlass; case (95 << 16) | 2: return Item::MagentaStainedGlass; case (95 << 16) | 3: return Item::LightBlueStainedGlass; case (95 << 16) | 4: return Item::YellowStainedGlass; case (95 << 16) | 5: return Item::LimeStainedGlass; case (95 << 16) | 6: return Item::PinkStainedGlass; case (95 << 16) | 7: return Item::GrayStainedGlass; case (95 << 16) | 8: return Item::LightGrayStainedGlass; case (95 << 16) | 9: return Item::CyanStainedGlass; case (95 << 16) | 10: return Item::PurpleStainedGlass; case (95 << 16) | 11: return Item::BlueStainedGlass; case (95 << 16) | 12: return Item::BrownStainedGlass; case (95 << 16) | 13: return Item::GreenStainedGlass; case (95 << 16) | 14: return Item::RedStainedGlass; case (95 << 16) | 15: return Item::BlackStainedGlass; case (160 << 16) | 0: return Item::WhiteStainedGlassPane; case (160 << 16) | 1: return Item::OrangeStainedGlassPane; case (160 << 16) | 2: return Item::MagentaStainedGlassPane; case (160 << 16) | 3: return Item::LightBlueStainedGlassPane; case (160 << 16) | 4: return Item::YellowStainedGlassPane; case (160 << 16) | 5: return Item::LimeStainedGlassPane; case (160 << 16) | 6: return Item::PinkStainedGlassPane; case (160 << 16) | 7: return Item::GrayStainedGlassPane; case (160 << 16) | 8: return Item::LightGrayStainedGlassPane; case (160 << 16) | 9: return Item::CyanStainedGlassPane; case (160 << 16) | 10: return Item::PurpleStainedGlassPane; case (160 << 16) | 11: return Item::BlueStainedGlassPane; case (160 << 16) | 12: return Item::BrownStainedGlassPane; case (160 << 16) | 13: return Item::GreenStainedGlassPane; case (160 << 16) | 14: return Item::RedStainedGlassPane; case (160 << 16) | 15: return Item::BlackStainedGlassPane; case (168 << 16) | 0: return Item::Prismarine; case (168 << 16) | 1: return Item::PrismarineBricks; case (168 << 16) | 2: return Item::DarkPrismarine; case (169 << 16) | 0: return Item::SeaLantern; case (179 << 16) | 0: return Item::RedSandstone; case (179 << 16) | 1: return Item::ChiseledRedSandstone; case (179 << 16) | 2: return Item::CutRedSandstone; case (180 << 16) | 0: return Item::RedSandstoneStairs; case (210 << 16) | 0: return Item::RepeatingCommandBlock; case (211 << 16) | 0: return Item::ChainCommandBlock; case (213 << 16) | 0: return Item::MagmaBlock; case (214 << 16) | 0: return Item::NetherWartBlock; case (215 << 16) | 0: return Item::RedNetherBricks; case (216 << 16) | 0: return Item::BoneBlock; case (217 << 16) | 0: return Item::StructureVoid; case (218 << 16) | 0: return Item::Observer; case (219 << 16) | 0: return Item::WhiteShulkerBox; case (220 << 16) | 0: return Item::OrangeShulkerBox; case (221 << 16) | 0: return Item::MagentaShulkerBox; case (222 << 16) | 0: return Item::LightBlueShulkerBox; case (223 << 16) | 0: return Item::YellowShulkerBox; case (224 << 16) | 0: return Item::LimeShulkerBox; case (225 << 16) | 0: return Item::PinkShulkerBox; case (226 << 16) | 0: return Item::GrayShulkerBox; case (227 << 16) | 0: return Item::LightGrayShulkerBox; case (228 << 16) | 0: return Item::CyanShulkerBox; case (229 << 16) | 0: return Item::PurpleShulkerBox; case (230 << 16) | 0: return Item::BlueShulkerBox; case (231 << 16) | 0: return Item::BrownShulkerBox; case (232 << 16) | 0: return Item::GreenShulkerBox; case (233 << 16) | 0: return Item::RedShulkerBox; case (234 << 16) | 0: return Item::BlackShulkerBox; case (235 << 16) | 0: return Item::WhiteGlazedTerracotta; case (236 << 16) | 0: return Item::OrangeGlazedTerracotta; case (237 << 16) | 0: return Item::MagentaGlazedTerracotta; case (238 << 16) | 0: return Item::LightBlueGlazedTerracotta; case (239 << 16) | 0: return Item::YellowGlazedTerracotta; case (240 << 16) | 0: return Item::LimeGlazedTerracotta; case (241 << 16) | 0: return Item::PinkGlazedTerracotta; case (242 << 16) | 0: return Item::GrayGlazedTerracotta; case (243 << 16) | 0: return Item::LightGrayGlazedTerracotta; case (244 << 16) | 0: return Item::CyanGlazedTerracotta; case (245 << 16) | 0: return Item::PurpleGlazedTerracotta; case (246 << 16) | 0: return Item::BlueGlazedTerracotta; case (247 << 16) | 0: return Item::BrownGlazedTerracotta; case (248 << 16) | 0: return Item::GreenGlazedTerracotta; case (249 << 16) | 0: return Item::RedGlazedTerracotta; case (250 << 16) | 0: return Item::BlackGlazedTerracotta; case (251 << 16) | 0: return Item::WhiteConcrete; case (251 << 16) | 1: return Item::OrangeConcrete; case (251 << 16) | 2: return Item::MagentaConcrete; case (251 << 16) | 3: return Item::LightBlueConcrete; case (251 << 16) | 4: return Item::YellowConcrete; case (251 << 16) | 5: return Item::LimeConcrete; case (251 << 16) | 6: return Item::PinkConcrete; case (251 << 16) | 7: return Item::GrayConcrete; case (251 << 16) | 8: return Item::LightGrayConcrete; case (251 << 16) | 9: return Item::CyanConcrete; case (251 << 16) | 10: return Item::PurpleConcrete; case (251 << 16) | 11: return Item::BlueConcrete; case (251 << 16) | 12: return Item::BrownConcrete; case (251 << 16) | 13: return Item::GreenConcrete; case (251 << 16) | 14: return Item::RedConcrete; case (251 << 16) | 15: return Item::BlackConcrete; case (252 << 16) | 0: return Item::WhiteConcretePowder; case (252 << 16) | 1: return Item::OrangeConcretePowder; case (252 << 16) | 2: return Item::MagentaConcretePowder; case (252 << 16) | 3: return Item::LightBlueConcretePowder; case (252 << 16) | 4: return Item::YellowConcretePowder; case (252 << 16) | 5: return Item::LimeConcretePowder; case (252 << 16) | 6: return Item::PinkConcretePowder; case (252 << 16) | 7: return Item::GrayConcretePowder; case (252 << 16) | 8: return Item::LightGrayConcretePowder; case (252 << 16) | 9: return Item::CyanConcretePowder; case (252 << 16) | 10: return Item::PurpleConcretePowder; case (252 << 16) | 11: return Item::BlueConcretePowder; case (252 << 16) | 12: return Item::BrownConcretePowder; case (252 << 16) | 13: return Item::GreenConcretePowder; case (252 << 16) | 14: return Item::RedConcretePowder; case (252 << 16) | 15: return Item::BlackConcretePowder; case (330 << 16) | 0: return Item::IronDoor; case (324 << 16) | 0: return Item::OakDoor; case (427 << 16) | 0: return Item::SpruceDoor; case (428 << 16) | 0: return Item::BirchDoor; case (429 << 16) | 0: return Item::JungleDoor; case (430 << 16) | 0: return Item::AcaciaDoor; case (431 << 16) | 0: return Item::DarkOakDoor; case (356 << 16) | 0: return Item::Repeater; case (404 << 16) | 0: return Item::Comparator; case (255 << 16) | 0: return Item::StructureBlock; case (256 << 16) | 0: return Item::IronShovel; case (257 << 16) | 0: return Item::IronPickaxe; case (258 << 16) | 0: return Item::IronAxe; case (259 << 16) | 0: return Item::FlintAndSteel; case (260 << 16) | 0: return Item::Apple; case (261 << 16) | 0: return Item::Bow; case (262 << 16) | 0: return Item::Arrow; case (263 << 16) | 0: return Item::Coal; case (263 << 16) | 1: return Item::Charcoal; case (264 << 16) | 0: return Item::Diamond; case (265 << 16) | 0: return Item::IronIngot; case (266 << 16) | 0: return Item::GoldIngot; case (267 << 16) | 0: return Item::IronSword; case (268 << 16) | 0: return Item::WoodenSword; case (269 << 16) | 0: return Item::WoodenShovel; case (270 << 16) | 0: return Item::WoodenPickaxe; case (271 << 16) | 0: return Item::WoodenAxe; case (272 << 16) | 0: return Item::StoneSword; case (273 << 16) | 0: return Item::StoneShovel; case (274 << 16) | 0: return Item::StonePickaxe; case (275 << 16) | 0: return Item::StoneAxe; case (276 << 16) | 0: return Item::DiamondSword; case (277 << 16) | 0: return Item::DiamondShovel; case (278 << 16) | 0: return Item::DiamondPickaxe; case (279 << 16) | 0: return Item::DiamondAxe; case (280 << 16) | 0: return Item::Stick; case (281 << 16) | 0: return Item::Bowl; case (282 << 16) | 0: return Item::MushroomStew; case (283 << 16) | 0: return Item::GoldenSword; case (284 << 16) | 0: return Item::GoldenShovel; case (285 << 16) | 0: return Item::GoldenPickaxe; case (286 << 16) | 0: return Item::GoldenAxe; case (287 << 16) | 0: return Item::String; case (288 << 16) | 0: return Item::Feather; case (289 << 16) | 0: return Item::Gunpowder; case (290 << 16) | 0: return Item::WoodenHoe; case (291 << 16) | 0: return Item::StoneHoe; case (292 << 16) | 0: return Item::IronHoe; case (293 << 16) | 0: return Item::DiamondHoe; case (294 << 16) | 0: return Item::GoldenHoe; case (295 << 16) | 0: return Item::WheatSeeds; case (296 << 16) | 0: return Item::Wheat; case (297 << 16) | 0: return Item::Bread; case (298 << 16) | 0: return Item::LeatherHelmet; case (299 << 16) | 0: return Item::LeatherChestplate; case (300 << 16) | 0: return Item::LeatherLeggings; case (301 << 16) | 0: return Item::LeatherBoots; case (302 << 16) | 0: return Item::ChainmailHelmet; case (303 << 16) | 0: return Item::ChainmailChestplate; case (304 << 16) | 0: return Item::ChainmailLeggings; case (305 << 16) | 0: return Item::ChainmailBoots; case (306 << 16) | 0: return Item::IronHelmet; case (307 << 16) | 0: return Item::IronChestplate; case (308 << 16) | 0: return Item::IronLeggings; case (309 << 16) | 0: return Item::IronBoots; case (310 << 16) | 0: return Item::DiamondHelmet; case (311 << 16) | 0: return Item::DiamondChestplate; case (312 << 16) | 0: return Item::DiamondLeggings; case (313 << 16) | 0: return Item::DiamondBoots; case (314 << 16) | 0: return Item::GoldenHelmet; case (315 << 16) | 0: return Item::GoldenChestplate; case (316 << 16) | 0: return Item::GoldenLeggings; case (317 << 16) | 0: return Item::GoldenBoots; case (318 << 16) | 0: return Item::Flint; case (319 << 16) | 0: return Item::Porkchop; case (320 << 16) | 0: return Item::CookedPorkchop; case (321 << 16) | 0: return Item::Painting; case (322 << 16) | 0: return Item::GoldenApple; case (322 << 16) | 1: return Item::EnchantedGoldenApple; case (323 << 16) | 0: return Item::OakSign; case (325 << 16) | 0: return Item::Bucket; case (326 << 16) | 0: return Item::WaterBucket; case (327 << 16) | 0: return Item::LavaBucket; case (328 << 16) | 0: return Item::Minecart; case (329 << 16) | 0: return Item::Saddle; case (331 << 16) | 0: return Item::Redstone; case (332 << 16) | 0: return Item::Snowball; case (333 << 16) | 0: return Item::OakBoat; case (334 << 16) | 0: return Item::Leather; case (335 << 16) | 0: return Item::MilkBucket; case (336 << 16) | 0: return Item::Brick; case (337 << 16) | 0: return Item::ClayBall; case (338 << 16) | 0: return Item::SugarCane; case (339 << 16) | 0: return Item::Paper; case (340 << 16) | 0: return Item::Book; case (341 << 16) | 0: return Item::SlimeBall; case (342 << 16) | 0: return Item::ChestMinecart; case (343 << 16) | 0: return Item::FurnaceMinecart; case (344 << 16) | 0: return Item::Egg; case (345 << 16) | 0: return Item::Compass; case (346 << 16) | 0: return Item::FishingRod; case (347 << 16) | 0: return Item::Clock; case (348 << 16) | 0: return Item::GlowstoneDust; case (349 << 16) | 0: return Item::Cod; case (349 << 16) | 1: return Item::Salmon; case (349 << 16) | 2: return Item::TropicalFish; case (349 << 16) | 3: return Item::Pufferfish; case (350 << 16) | 0: return Item::CookedCod; case (350 << 16) | 1: return Item::CookedSalmon; case (351 << 16) | 0: return Item::InkSac; case (351 << 16) | 1: return Item::RedDye; case (351 << 16) | 2: return Item::GreenDye; case (351 << 16) | 3: return Item::CocoaBeans; case (351 << 16) | 4: return Item::LapisLazuli; case (351 << 16) | 5: return Item::PurpleDye; case (351 << 16) | 6: return Item::CyanDye; case (351 << 16) | 7: return Item::LightGrayDye; case (351 << 16) | 8: return Item::GrayDye; case (351 << 16) | 9: return Item::PinkDye; case (351 << 16) | 10: return Item::LimeDye; case (351 << 16) | 11: return Item::YellowDye; case (351 << 16) | 12: return Item::LightBlueDye; case (351 << 16) | 13: return Item::MagentaDye; case (351 << 16) | 14: return Item::OrangeDye; case (351 << 16) | 15: return Item::BoneMeal; case (352 << 16) | 0: return Item::Bone; case (353 << 16) | 0: return Item::Sugar; case (354 << 16) | 0: return Item::Cake; case (355 << 16) | 0: return Item::WhiteBed; case (355 << 16) | 1: return Item::OrangeBed; case (355 << 16) | 2: return Item::MagentaBed; case (355 << 16) | 3: return Item::LightBlueBed; case (355 << 16) | 4: return Item::YellowBed; case (355 << 16) | 5: return Item::LimeBed; case (355 << 16) | 6: return Item::PinkBed; case (355 << 16) | 7: return Item::GrayBed; case (355 << 16) | 8: return Item::LightGrayBed; case (355 << 16) | 9: return Item::CyanBed; case (355 << 16) | 10: return Item::PurpleBed; case (355 << 16) | 11: return Item::BlueBed; case (355 << 16) | 12: return Item::BrownBed; case (355 << 16) | 13: return Item::GreenBed; case (355 << 16) | 14: return Item::RedBed; case (355 << 16) | 15: return Item::BlackBed; case (357 << 16) | 0: return Item::Cookie; case (358 << 16) | 0: return Item::FilledMap; case (359 << 16) | 0: return Item::Shears; case (360 << 16) | 0: return Item::MelonSlice; case (361 << 16) | 0: return Item::PumpkinSeeds; case (362 << 16) | 0: return Item::MelonSeeds; case (363 << 16) | 0: return Item::Beef; case (364 << 16) | 0: return Item::CookedBeef; case (365 << 16) | 0: return Item::Chicken; case (366 << 16) | 0: return Item::CookedChicken; case (367 << 16) | 0: return Item::RottenFlesh; case (368 << 16) | 0: return Item::EnderPearl; case (369 << 16) | 0: return Item::BlazeRod; case (370 << 16) | 0: return Item::GhastTear; case (371 << 16) | 0: return Item::GoldNugget; case (372 << 16) | 0: return Item::NetherWart; case (373 << 16) | 0: return Item::Potion; case (438 << 16) | 0: return Item::SplashPotion; case (441 << 16) | 0: return Item::LingeringPotion; // Potion type encoded in Item NBT: case (373 << 16) | 16: case (373 << 16) | 32: case (373 << 16) | 64: case (373 << 16) | 8193: case (373 << 16) | 8194: case (373 << 16) | 8195: case (373 << 16) | 8196: case (373 << 16) | 8197: case (373 << 16) | 8198: case (373 << 16) | 8200: case (373 << 16) | 8201: case (373 << 16) | 8202: case (373 << 16) | 8204: case (373 << 16) | 8205: case (373 << 16) | 8206: case (373 << 16) | 8225: case (373 << 16) | 8226: case (373 << 16) | 8228: case (373 << 16) | 8229: case (373 << 16) | 8233: case (373 << 16) | 8235: case (373 << 16) | 8236: case (373 << 16) | 8257: case (373 << 16) | 8258: case (373 << 16) | 8259: case (373 << 16) | 8260: case (373 << 16) | 8262: case (373 << 16) | 8264: case (373 << 16) | 8265: case (373 << 16) | 8266: case (373 << 16) | 8267: case (373 << 16) | 8269: case (373 << 16) | 8270: case (373 << 16) | 8289: case (373 << 16) | 8290: case (373 << 16) | 8292: case (373 << 16) | 8297: return Item::Potion; // Potion type encoded in Item NBT: case (373 << 16) | 16385: case (373 << 16) | 16386: case (373 << 16) | 16387: case (373 << 16) | 16388: case (373 << 16) | 16389: case (373 << 16) | 16390: case (373 << 16) | 16392: case (373 << 16) | 16393: case (373 << 16) | 16394: case (373 << 16) | 16396: case (373 << 16) | 16397: case (373 << 16) | 16398: case (373 << 16) | 16417: case (373 << 16) | 16418: case (373 << 16) | 16420: case (373 << 16) | 16421: case (373 << 16) | 16425: case (373 << 16) | 16427: case (373 << 16) | 16428: case (373 << 16) | 16449: case (373 << 16) | 16450: case (373 << 16) | 16451: case (373 << 16) | 16452: case (373 << 16) | 16454: case (373 << 16) | 16456: case (373 << 16) | 16457: case (373 << 16) | 16458: case (373 << 16) | 16459: case (373 << 16) | 16461: case (373 << 16) | 16462: case (373 << 16) | 16481: case (373 << 16) | 16482: case (373 << 16) | 16484: case (373 << 16) | 16489: return Item::SplashPotion; case (374 << 16) | 0: return Item::GlassBottle; case (375 << 16) | 0: return Item::SpiderEye; case (376 << 16) | 0: return Item::FermentedSpiderEye; case (377 << 16) | 0: return Item::BlazePowder; case (378 << 16) | 0: return Item::MagmaCream; case (379 << 16) | 0: return Item::BrewingStand; case (380 << 16) | 0: return Item::Cauldron; case (381 << 16) | 0: return Item::EnderEye; case (382 << 16) | 0: return Item::GlisteringMelonSlice; case (383 << 16) | 65: return Item::BatSpawnEgg; case (383 << 16) | 61: return Item::BlazeSpawnEgg; case (383 << 16) | 59: return Item::CaveSpiderSpawnEgg; case (383 << 16) | 93: return Item::ChickenSpawnEgg; case (383 << 16) | 92: return Item::CowSpawnEgg; case (383 << 16) | 50: return Item::CreeperSpawnEgg; case (383 << 16) | 31: return Item::DonkeySpawnEgg; case (383 << 16) | 4: return Item::ElderGuardianSpawnEgg; case (383 << 16) | 58: return Item::EndermanSpawnEgg; case (383 << 16) | 67: return Item::EndermiteSpawnEgg; case (383 << 16) | 34: return Item::EvokerSpawnEgg; case (383 << 16) | 56: return Item::GhastSpawnEgg; case (383 << 16) | 68: return Item::GuardianSpawnEgg; case (383 << 16) | 100: return Item::HorseSpawnEgg; case (383 << 16) | 23: return Item::HuskSpawnEgg; case (383 << 16) | 103: return Item::LlamaSpawnEgg; case (383 << 16) | 62: return Item::MagmaCubeSpawnEgg; case (383 << 16) | 96: return Item::MooshroomSpawnEgg; case (383 << 16) | 32: return Item::MuleSpawnEgg; case (383 << 16) | 98: return Item::OcelotSpawnEgg; case (383 << 16) | 90: return Item::PigSpawnEgg; case (383 << 16) | 102: return Item::PolarBearSpawnEgg; case (383 << 16) | 101: return Item::RabbitSpawnEgg; case (383 << 16) | 91: return Item::SheepSpawnEgg; case (383 << 16) | 69: return Item::ShulkerSpawnEgg; case (383 << 16) | 51: return Item::SkeletonSpawnEgg; case (383 << 16) | 28: return Item::SkeletonHorseSpawnEgg; case (383 << 16) | 55: return Item::SlimeSpawnEgg; case (383 << 16) | 52: return Item::SpiderSpawnEgg; case (383 << 16) | 94: return Item::SquidSpawnEgg; case (383 << 16) | 6: return Item::StraySpawnEgg; case (383 << 16) | 35: return Item::VexSpawnEgg; case (383 << 16) | 120: return Item::VillagerSpawnEgg; case (383 << 16) | 36: return Item::VindicatorSpawnEgg; case (383 << 16) | 66: return Item::WitchSpawnEgg; case (383 << 16) | 5: return Item::WitherSkeletonSpawnEgg; case (383 << 16) | 95: return Item::WolfSpawnEgg; case (383 << 16) | 54: return Item::ZombieSpawnEgg; case (383 << 16) | 29: return Item::ZombieHorseSpawnEgg; case (383 << 16) | 57: return Item::ZombiePigmanSpawnEgg; case (383 << 16) | 27: return Item::ZombieVillagerSpawnEgg; case (384 << 16) | 0: return Item::ExperienceBottle; case (385 << 16) | 0: return Item::FireCharge; case (386 << 16) | 0: return Item::WritableBook; case (387 << 16) | 0: return Item::WrittenBook; case (388 << 16) | 0: return Item::Emerald; case (389 << 16) | 0: return Item::ItemFrame; case (390 << 16) | 0: return Item::FlowerPot; case (391 << 16) | 0: return Item::Carrot; case (392 << 16) | 0: return Item::Potato; case (393 << 16) | 0: return Item::BakedPotato; case (394 << 16) | 0: return Item::PoisonousPotato; case (395 << 16) | 0: return Item::Map; case (396 << 16) | 0: return Item::GoldenCarrot; case (397 << 16) | 0: return Item::SkeletonSkull; case (397 << 16) | 1: return Item::WitherSkeletonSkull; case (397 << 16) | 3: return Item::PlayerHead; case (397 << 16) | 2: return Item::ZombieHead; case (397 << 16) | 4: return Item::CreeperHead; case (397 << 16) | 5: return Item::DragonHead; case (398 << 16) | 0: return Item::CarrotOnAStick; case (399 << 16) | 0: return Item::NetherStar; case (400 << 16) | 0: return Item::PumpkinPie; case (401 << 16) | 0: return Item::FireworkRocket; case (402 << 16) | 0: return Item::FireworkStar; case (403 << 16) | 0: return Item::EnchantedBook; case (405 << 16) | 0: return Item::NetherBrick; case (406 << 16) | 0: return Item::Quartz; case (407 << 16) | 0: return Item::TNTMinecart; case (408 << 16) | 0: return Item::HopperMinecart; case (409 << 16) | 0: return Item::PrismarineShard; case (410 << 16) | 0: return Item::PrismarineCrystals; case (411 << 16) | 0: return Item::Rabbit; case (412 << 16) | 0: return Item::CookedRabbit; case (413 << 16) | 0: return Item::RabbitStew; case (414 << 16) | 0: return Item::RabbitFoot; case (415 << 16) | 0: return Item::RabbitHide; case (416 << 16) | 0: return Item::ArmorStand; case (417 << 16) | 0: return Item::IronHorseArmor; case (418 << 16) | 0: return Item::GoldenHorseArmor; case (419 << 16) | 0: return Item::DiamondHorseArmor; case (420 << 16) | 0: return Item::Lead; case (421 << 16) | 0: return Item::NameTag; case (422 << 16) | 0: return Item::CommandBlockMinecart; case (423 << 16) | 0: return Item::Mutton; case (424 << 16) | 0: return Item::CookedMutton; case (425 << 16) | 15: return Item::WhiteBanner; case (425 << 16) | 14: return Item::OrangeBanner; case (425 << 16) | 13: return Item::MagentaBanner; case (425 << 16) | 12: return Item::LightBlueBanner; case (425 << 16) | 11: return Item::YellowBanner; case (425 << 16) | 10: return Item::LimeBanner; case (425 << 16) | 9: return Item::PinkBanner; case (425 << 16) | 8: return Item::GrayBanner; case (425 << 16) | 7: return Item::LightGrayBanner; case (425 << 16) | 6: return Item::CyanBanner; case (425 << 16) | 5: return Item::PurpleBanner; case (425 << 16) | 4: return Item::BlueBanner; case (425 << 16) | 3: return Item::BrownBanner; case (425 << 16) | 2: return Item::GreenBanner; case (425 << 16) | 1: return Item::RedBanner; case (425 << 16) | 0: return Item::BlackBanner; case (426 << 16) | 0: return Item::EndCrystal; case (432 << 16) | 0: return Item::ChorusFruit; case (433 << 16) | 0: return Item::PoppedChorusFruit; case (434 << 16) | 0: return Item::Beetroot; case (435 << 16) | 0: return Item::BeetrootSeeds; case (436 << 16) | 0: return Item::BeetrootSoup; case (437 << 16) | 0: return Item::DragonBreath; case (439 << 16) | 0: return Item::SpectralArrow; case (440 << 16) | 0: return Item::TippedArrow; case (442 << 16) | 0: return Item::Shield; case (443 << 16) | 0: return Item::Elytra; case (444 << 16) | 0: return Item::SpruceBoat; case (445 << 16) | 0: return Item::BirchBoat; case (446 << 16) | 0: return Item::JungleBoat; case (447 << 16) | 0: return Item::AcaciaBoat; case (448 << 16) | 0: return Item::DarkOakBoat; case (449 << 16) | 0: return Item::TotemOfUndying; case (450 << 16) | 0: return Item::ShulkerShell; case (452 << 16) | 0: return Item::IronNugget; case (2256 << 16) | 0: return Item::MusicDisc13; case (2257 << 16) | 0: return Item::MusicDiscCat; case (2258 << 16) | 0: return Item::MusicDiscBlocks; case (2259 << 16) | 0: return Item::MusicDiscChirp; case (2260 << 16) | 0: return Item::MusicDiscFar; case (2261 << 16) | 0: return Item::MusicDiscMall; case (2262 << 16) | 0: return Item::MusicDiscMellohi; case (2263 << 16) | 0: return Item::MusicDiscStal; case (2264 << 16) | 0: return Item::MusicDiscStrad; case (2265 << 16) | 0: return Item::MusicDiscWard; case (2266 << 16) | 0: return Item::MusicDisc11; case (2267 << 16) | 0: return Item::MusicDiscWait; // Technical blocks that used to be able to appear // in the inventory. e.g. Water, Lava, Piston Head, Fire // Redstone Wire, Wall Sign, Stem, Portal, Cocoa, Tripwire, etc. // Some technical blocks have been manually mapped to item analogues. case (55 << 16) | 0: return Item::Redstone; case (68 << 16) | 0: return Item::OakSign; case (83 << 16) | 0: return Item::SugarCane; case (127 << 16) | 0: return Item::CocoaBeans; case (132 << 16) | 0: return Item::String; case (141 << 16) | 0: return Item::Carrot; case (142 << 16) | 0: return Item::Potato; case (207 << 16) | 0: return Item::Beetroot; // Monster Spawner type encoded in Item NBT case (52 << 16) | 50: case (52 << 16) | 51: case (52 << 16) | 52: case (52 << 16) | 53: case (52 << 16) | 54: case (52 << 16) | 55: case (52 << 16) | 56: case (52 << 16) | 57: case (52 << 16) | 58: case (52 << 16) | 59: case (52 << 16) | 60: case (52 << 16) | 61: case (52 << 16) | 62: case (52 << 16) | 63: case (52 << 16) | 64: case (52 << 16) | 65: case (52 << 16) | 66: case (52 << 16) | 90: case (52 << 16) | 91: case (52 << 16) | 92: case (52 << 16) | 93: case (52 << 16) | 94: case (52 << 16) | 95: case (52 << 16) | 96: case (52 << 16) | 97: case (52 << 16) | 98: case (52 << 16) | 99: case (52 << 16) | 100: return Item::Spawner; default: return Item::Air; } } std::pair ToItem(const Item ID) { switch (ID) { case Item::Stone: return { 1, 0 }; case Item::Granite: return { 1, 1 }; case Item::PolishedGranite: return { 1, 2 }; case Item::Diorite: return { 1, 3 }; case Item::PolishedDiorite: return { 1, 4 }; case Item::Andesite: return { 1, 5 }; case Item::PolishedAndesite: return { 1, 6 }; case Item::GrassBlock: return { 2, 0 }; case Item::Dirt: return { 3, 0 }; case Item::CoarseDirt: return { 3, 1 }; case Item::Podzol: return { 3, 2 }; case Item::Cobblestone: return { 4, 0 }; case Item::OakPlanks: return { 5, 0 }; case Item::SprucePlanks: return { 5, 1 }; case Item::BirchPlanks: return { 5, 2 }; case Item::JunglePlanks: return { 5, 3 }; case Item::AcaciaPlanks: return { 5, 4 }; case Item::DarkOakPlanks: return { 5, 5 }; case Item::OakSapling: return { 6, 0 }; case Item::SpruceSapling: return { 6, 1 }; case Item::BirchSapling: return { 6, 2 }; case Item::JungleSapling: return { 6, 3 }; case Item::AcaciaSapling: return { 6, 4 }; case Item::DarkOakSapling: return { 6, 5 }; case Item::Bedrock: return { 7, 0 }; case Item::Sand: return { 12, 0 }; case Item::RedSand: return { 12, 1 }; case Item::Gravel: return { 13, 0 }; case Item::GoldOre: return { 14, 0 }; case Item::IronOre: return { 15, 0 }; case Item::CoalOre: return { 16, 0 }; case Item::OakLog: return { 17, 0 }; case Item::SpruceLog: return { 17, 1 }; case Item::BirchLog: return { 17, 2 }; case Item::JungleLog: return { 17, 3 }; case Item::AcaciaLog: return { 162, 0 }; case Item::DarkOakLog: return { 162, 1 }; case Item::OakLeaves: return { 18, 0 }; case Item::SpruceLeaves: return { 18, 1 }; case Item::BirchLeaves: return { 18, 2 }; case Item::JungleLeaves: return { 18, 3 }; case Item::AcaciaLeaves: return { 161, 0 }; case Item::DarkOakLeaves: return { 161, 1 }; case Item::Sponge: return { 19, 0 }; case Item::WetSponge: return { 19, 1 }; case Item::Glass: return { 20, 0 }; case Item::LapisOre: return { 21, 0 }; case Item::LapisBlock: return { 22, 0 }; case Item::Dispenser: return { 23, 0 }; case Item::Sandstone: return { 24, 0 }; case Item::ChiseledSandstone: return { 24, 1 }; case Item::CutSandstone: return { 24, 2 }; case Item::NoteBlock: return { 25, 0 }; case Item::PoweredRail: return { 27, 0 }; case Item::DetectorRail: return { 28, 0 }; case Item::StickyPiston: return { 29, 0 }; case Item::Cobweb: return { 30, 0 }; case Item::Fern: return { 31, 2 }; case Item::DeadBush: return { 32, 0 }; case Item::Piston: return { 33, 0 }; case Item::WhiteWool: return { 35, 0 }; case Item::OrangeWool: return { 35, 1 }; case Item::MagentaWool: return { 35, 2 }; case Item::LightBlueWool: return { 35, 3 }; case Item::YellowWool: return { 35, 4 }; case Item::LimeWool: return { 35, 5 }; case Item::PinkWool: return { 35, 6 }; case Item::GrayWool: return { 35, 7 }; case Item::LightGrayWool: return { 35, 8 }; case Item::CyanWool: return { 35, 9 }; case Item::PurpleWool: return { 35, 10 }; case Item::BlueWool: return { 35, 11 }; case Item::BrownWool: return { 35, 12 }; case Item::GreenWool: return { 35, 13 }; case Item::RedWool: return { 35, 14 }; case Item::BlackWool: return { 35, 15 }; case Item::Dandelion: return { 37, 0 }; case Item::Poppy: return { 38, 0 }; case Item::BlueOrchid: return { 38, 1 }; case Item::Allium: return { 38, 2 }; case Item::AzureBluet: return { 38, 3 }; case Item::RedTulip: return { 38, 4 }; case Item::OrangeTulip: return { 38, 5 }; case Item::WhiteTulip: return { 38, 6 }; case Item::PinkTulip: return { 38, 7 }; case Item::OxeyeDaisy: return { 38, 8 }; case Item::BrownMushroom: return { 39, 0 }; case Item::RedMushroom: return { 40, 0 }; case Item::GoldBlock: return { 41, 0 }; case Item::IronBlock: return { 42, 0 }; case Item::OakSlab: return { 126, 0 }; case Item::SpruceSlab: return { 126, 1 }; case Item::BirchSlab: return { 126, 2 }; case Item::JungleSlab: return { 126, 3 }; case Item::AcaciaSlab: return { 126, 4 }; case Item::DarkOakSlab: return { 126, 5 }; case Item::StoneSlab: return { 44, 2 }; case Item::SandstoneSlab: return { 44, 1 }; case Item::CobblestoneSlab: return { 44, 3 }; case Item::BrickSlab: return { 44, 4 }; case Item::StoneBrickSlab: return { 44, 5 }; case Item::NetherBrickSlab: return { 44, 6 }; case Item::QuartzSlab: return { 44, 7 }; case Item::RedSandstoneSlab: return { 182, 0 }; case Item::PurpurSlab: return { 205, 0 }; case Item::SmoothQuartz: return { 43, 7 }; case Item::SmoothStone: return { 43, 8 }; case Item::Bricks: return { 45, 0 }; case Item::TNT: return { 46, 0 }; case Item::Bookshelf: return { 47, 0 }; case Item::MossyCobblestone: return { 48, 0 }; case Item::Obsidian: return { 49, 0 }; case Item::Torch: return { 50, 0 }; case Item::EndRod: return { 198, 0 }; case Item::ChorusPlant: return { 199, 0 }; case Item::ChorusFlower: return { 200, 0 }; case Item::PurpurBlock: return { 201, 0 }; case Item::PurpurPillar: return { 202, 0 }; case Item::PurpurStairs: return { 203, 0 }; case Item::Spawner: return { 52, 0 }; case Item::OakStairs: return { 53, 0 }; case Item::Chest: return { 54, 0 }; case Item::DiamondOre: return { 56, 0 }; case Item::DiamondBlock: return { 57, 0 }; case Item::CraftingTable: return { 58, 0 }; case Item::Farmland: return { 60, 0 }; case Item::Furnace: return { 61, 0 }; case Item::Ladder: return { 65, 0 }; case Item::Rail: return { 66, 0 }; case Item::CobblestoneStairs: return { 67, 0 }; case Item::Lever: return { 69, 0 }; case Item::StonePressurePlate: return { 70, 0 }; case Item::OakPressurePlate: return { 72, 0 }; case Item::RedstoneOre: return { 73, 0 }; case Item::RedstoneTorch: return { 76, 0 }; case Item::StoneButton: return { 77, 0 }; case Item::Snow: return { 78, 0 }; case Item::Ice: return { 79, 0 }; case Item::SnowBlock: return { 80, 0 }; case Item::Cactus: return { 81, 0 }; case Item::Clay: return { 82, 0 }; case Item::Jukebox: return { 84, 0 }; case Item::OakFence: return { 85, 0 }; case Item::SpruceFence: return { 188, 0 }; case Item::BirchFence: return { 189, 0 }; case Item::JungleFence: return { 190, 0 }; case Item::AcaciaFence: return { 192, 0 }; case Item::DarkOakFence: return { 191, 0 }; case Item::Pumpkin: return { 86, 0 }; case Item::Netherrack: return { 87, 0 }; case Item::SoulSand: return { 88, 0 }; case Item::Glowstone: return { 89, 0 }; case Item::JackOLantern: return { 91, 0 }; case Item::OakTrapdoor: return { 96, 0 }; case Item::InfestedStone: return { 97, 0 }; case Item::InfestedCobblestone: return { 97, 1 }; case Item::InfestedStoneBricks: return { 97, 2 }; case Item::InfestedMossyStoneBricks: return { 97, 3 }; case Item::InfestedCrackedStoneBricks: return { 97, 4 }; case Item::InfestedChiseledStoneBricks: return { 97, 5 }; case Item::StoneBricks: return { 98, 0 }; case Item::MossyStoneBricks: return { 98, 1 }; case Item::CrackedStoneBricks: return { 98, 2 }; case Item::ChiseledStoneBricks: return { 98, 3 }; case Item::BrownMushroomBlock: return { 99, 0 }; case Item::RedMushroomBlock: return { 100, 0 }; case Item::IronBars: return { 101, 0 }; case Item::GlassPane: return { 102, 0 }; case Item::Melon: return { 103, 0 }; case Item::Vine: return { 106, 0 }; case Item::OakFenceGate: return { 107, 0 }; case Item::SpruceFenceGate: return { 183, 0 }; case Item::BirchFenceGate: return { 184, 0 }; case Item::JungleFenceGate: return { 185, 0 }; case Item::AcaciaFenceGate: return { 187, 0 }; case Item::DarkOakFenceGate: return { 186, 0 }; case Item::BrickStairs: return { 108, 0 }; case Item::StoneBrickStairs: return { 109, 0 }; case Item::Mycelium: return { 110, 0 }; case Item::LilyPad: return { 111, 0 }; case Item::NetherBricks: return { 112, 0 }; case Item::NetherBrickFence: return { 113, 0 }; case Item::NetherBrickStairs: return { 114, 0 }; case Item::EnchantingTable: return { 116, 0 }; case Item::EndPortalFrame: return { 120, 0 }; case Item::EndStone: return { 121, 0 }; case Item::EndStoneBricks: return { 206, 0 }; case Item::DragonEgg: return { 122, 0 }; case Item::RedstoneLamp: return { 123, 0 }; case Item::SandstoneStairs: return { 128, 0 }; case Item::EmeraldOre: return { 129, 0 }; case Item::EnderChest: return { 130, 0 }; case Item::TripwireHook: return { 131, 0 }; case Item::EmeraldBlock: return { 133, 0 }; case Item::SpruceStairs: return { 134, 0 }; case Item::BirchStairs: return { 135, 0 }; case Item::JungleStairs: return { 136, 0 }; case Item::CommandBlock: return { 137, 0 }; case Item::Beacon: return { 138, 0 }; case Item::CobblestoneWall: return { 139, 0 }; case Item::MossyCobblestoneWall: return { 139, 1 }; case Item::OakButton: return { 143, 0 }; case Item::Anvil: return { 145, 0 }; case Item::ChippedAnvil: return { 145, 1 }; case Item::DamagedAnvil: return { 145, 2 }; case Item::TrappedChest: return { 146, 0 }; case Item::LightWeightedPressurePlate: return { 147, 0 }; case Item::HeavyWeightedPressurePlate: return { 148, 0 }; case Item::DaylightDetector: return { 151, 0 }; case Item::RedstoneBlock: return { 152, 0 }; case Item::NetherQuartzOre: return { 153, 0 }; case Item::Hopper: return { 154, 0 }; case Item::ChiseledQuartzBlock: return { 155, 1 }; case Item::QuartzBlock: return { 155, 0 }; case Item::QuartzPillar: return { 155, 2 }; case Item::QuartzStairs: return { 156, 0 }; case Item::ActivatorRail: return { 157, 0 }; case Item::Dropper: return { 158, 0 }; case Item::WhiteTerracotta: return { 159, 0 }; case Item::OrangeTerracotta: return { 159, 1 }; case Item::MagentaTerracotta: return { 159, 2 }; case Item::LightBlueTerracotta: return { 159, 3 }; case Item::YellowTerracotta: return { 159, 4 }; case Item::LimeTerracotta: return { 159, 5 }; case Item::PinkTerracotta: return { 159, 6 }; case Item::GrayTerracotta: return { 159, 7 }; case Item::LightGrayTerracotta: return { 159, 8 }; case Item::CyanTerracotta: return { 159, 9 }; case Item::PurpleTerracotta: return { 159, 10 }; case Item::BlueTerracotta: return { 159, 11 }; case Item::BrownTerracotta: return { 159, 12 }; case Item::GreenTerracotta: return { 159, 13 }; case Item::RedTerracotta: return { 159, 14 }; case Item::BlackTerracotta: return { 159, 15 }; case Item::Barrier: return { 166, 0 }; case Item::IronTrapdoor: return { 167, 0 }; case Item::HayBale: return { 170, 0 }; case Item::WhiteCarpet: return { 171, 0 }; case Item::OrangeCarpet: return { 171, 1 }; case Item::MagentaCarpet: return { 171, 2 }; case Item::LightBlueCarpet: return { 171, 3 }; case Item::YellowCarpet: return { 171, 4 }; case Item::LimeCarpet: return { 171, 5 }; case Item::PinkCarpet: return { 171, 6 }; case Item::GrayCarpet: return { 171, 7 }; case Item::LightGrayCarpet: return { 171, 8 }; case Item::CyanCarpet: return { 171, 9 }; case Item::PurpleCarpet: return { 171, 10 }; case Item::BlueCarpet: return { 171, 11 }; case Item::BrownCarpet: return { 171, 12 }; case Item::GreenCarpet: return { 171, 13 }; case Item::RedCarpet: return { 171, 14 }; case Item::BlackCarpet: return { 171, 15 }; case Item::Terracotta: return { 172, 0 }; case Item::CoalBlock: return { 173, 0 }; case Item::PackedIce: return { 174, 0 }; case Item::AcaciaStairs: return { 163, 0 }; case Item::DarkOakStairs: return { 164, 0 }; case Item::SlimeBlock: return { 165, 0 }; case Item::GrassPath: return { 208, 0 }; case Item::Sunflower: return { 175, 0 }; case Item::Lilac: return { 175, 1 }; case Item::RoseBush: return { 175, 4 }; case Item::Peony: return { 175, 5 }; case Item::TallGrass: return { 175, 2 }; case Item::LargeFern: return { 175, 3 }; case Item::WhiteStainedGlass: return { 95, 0 }; case Item::OrangeStainedGlass: return { 95, 1 }; case Item::MagentaStainedGlass: return { 95, 2 }; case Item::LightBlueStainedGlass: return { 95, 3 }; case Item::YellowStainedGlass: return { 95, 4 }; case Item::LimeStainedGlass: return { 95, 5 }; case Item::PinkStainedGlass: return { 95, 6 }; case Item::GrayStainedGlass: return { 95, 7 }; case Item::LightGrayStainedGlass: return { 95, 8 }; case Item::CyanStainedGlass: return { 95, 9 }; case Item::PurpleStainedGlass: return { 95, 10 }; case Item::BlueStainedGlass: return { 95, 11 }; case Item::BrownStainedGlass: return { 95, 12 }; case Item::GreenStainedGlass: return { 95, 13 }; case Item::RedStainedGlass: return { 95, 14 }; case Item::BlackStainedGlass: return { 95, 15 }; case Item::WhiteStainedGlassPane: return { 160, 0 }; case Item::OrangeStainedGlassPane: return { 160, 1 }; case Item::MagentaStainedGlassPane: return { 160, 2 }; case Item::LightBlueStainedGlassPane: return { 160, 3 }; case Item::YellowStainedGlassPane: return { 160, 4 }; case Item::LimeStainedGlassPane: return { 160, 5 }; case Item::PinkStainedGlassPane: return { 160, 6 }; case Item::GrayStainedGlassPane: return { 160, 7 }; case Item::LightGrayStainedGlassPane: return { 160, 8 }; case Item::CyanStainedGlassPane: return { 160, 9 }; case Item::PurpleStainedGlassPane: return { 160, 10 }; case Item::BlueStainedGlassPane: return { 160, 11 }; case Item::BrownStainedGlassPane: return { 160, 12 }; case Item::GreenStainedGlassPane: return { 160, 13 }; case Item::RedStainedGlassPane: return { 160, 14 }; case Item::BlackStainedGlassPane: return { 160, 15 }; case Item::Prismarine: return { 168, 0 }; case Item::PrismarineBricks: return { 168, 1 }; case Item::DarkPrismarine: return { 168, 2 }; case Item::SeaLantern: return { 169, 0 }; case Item::RedSandstone: return { 179, 0 }; case Item::ChiseledRedSandstone: return { 179, 1 }; case Item::CutRedSandstone: return { 179, 2 }; case Item::RedSandstoneStairs: return { 180, 0 }; case Item::RepeatingCommandBlock: return { 210, 0 }; case Item::ChainCommandBlock: return { 211, 0 }; case Item::MagmaBlock: return { 213, 0 }; case Item::NetherWartBlock: return { 214, 0 }; case Item::RedNetherBricks: return { 215, 0 }; case Item::BoneBlock: return { 216, 0 }; case Item::StructureVoid: return { 217, 0 }; case Item::Observer: return { 218, 0 }; case Item::WhiteShulkerBox: return { 219, 0 }; case Item::OrangeShulkerBox: return { 220, 0 }; case Item::MagentaShulkerBox: return { 221, 0 }; case Item::LightBlueShulkerBox: return { 222, 0 }; case Item::YellowShulkerBox: return { 223, 0 }; case Item::LimeShulkerBox: return { 224, 0 }; case Item::PinkShulkerBox: return { 225, 0 }; case Item::GrayShulkerBox: return { 226, 0 }; case Item::LightGrayShulkerBox: return { 227, 0 }; case Item::CyanShulkerBox: return { 228, 0 }; case Item::PurpleShulkerBox: return { 229, 0 }; case Item::BlueShulkerBox: return { 230, 0 }; case Item::BrownShulkerBox: return { 231, 0 }; case Item::GreenShulkerBox: return { 232, 0 }; case Item::RedShulkerBox: return { 233, 0 }; case Item::BlackShulkerBox: return { 234, 0 }; case Item::WhiteGlazedTerracotta: return { 235, 0 }; case Item::OrangeGlazedTerracotta: return { 236, 0 }; case Item::MagentaGlazedTerracotta: return { 237, 0 }; case Item::LightBlueGlazedTerracotta: return { 238, 0 }; case Item::YellowGlazedTerracotta: return { 239, 0 }; case Item::LimeGlazedTerracotta: return { 240, 0 }; case Item::PinkGlazedTerracotta: return { 241, 0 }; case Item::GrayGlazedTerracotta: return { 242, 0 }; case Item::LightGrayGlazedTerracotta: return { 243, 0 }; case Item::CyanGlazedTerracotta: return { 244, 0 }; case Item::PurpleGlazedTerracotta: return { 245, 0 }; case Item::BlueGlazedTerracotta: return { 246, 0 }; case Item::BrownGlazedTerracotta: return { 247, 0 }; case Item::GreenGlazedTerracotta: return { 248, 0 }; case Item::RedGlazedTerracotta: return { 249, 0 }; case Item::BlackGlazedTerracotta: return { 250, 0 }; case Item::WhiteConcrete: return { 251, 0 }; case Item::OrangeConcrete: return { 251, 1 }; case Item::MagentaConcrete: return { 251, 2 }; case Item::LightBlueConcrete: return { 251, 3 }; case Item::YellowConcrete: return { 251, 4 }; case Item::LimeConcrete: return { 251, 5 }; case Item::PinkConcrete: return { 251, 6 }; case Item::GrayConcrete: return { 251, 7 }; case Item::LightGrayConcrete: return { 251, 8 }; case Item::CyanConcrete: return { 251, 9 }; case Item::PurpleConcrete: return { 251, 10 }; case Item::BlueConcrete: return { 251, 11 }; case Item::BrownConcrete: return { 251, 12 }; case Item::GreenConcrete: return { 251, 13 }; case Item::RedConcrete: return { 251, 14 }; case Item::BlackConcrete: return { 251, 15 }; case Item::WhiteConcretePowder: return { 252, 0 }; case Item::OrangeConcretePowder: return { 252, 1 }; case Item::MagentaConcretePowder: return { 252, 2 }; case Item::LightBlueConcretePowder: return { 252, 3 }; case Item::YellowConcretePowder: return { 252, 4 }; case Item::LimeConcretePowder: return { 252, 5 }; case Item::PinkConcretePowder: return { 252, 6 }; case Item::GrayConcretePowder: return { 252, 7 }; case Item::LightGrayConcretePowder: return { 252, 8 }; case Item::CyanConcretePowder: return { 252, 9 }; case Item::PurpleConcretePowder: return { 252, 10 }; case Item::BlueConcretePowder: return { 252, 11 }; case Item::BrownConcretePowder: return { 252, 12 }; case Item::GreenConcretePowder: return { 252, 13 }; case Item::RedConcretePowder: return { 252, 14 }; case Item::BlackConcretePowder: return { 252, 15 }; case Item::IronDoor: return { 330, 0 }; case Item::OakDoor: return { 324, 0 }; case Item::SpruceDoor: return { 427, 0 }; case Item::BirchDoor: return { 428, 0 }; case Item::JungleDoor: return { 429, 0 }; case Item::AcaciaDoor: return { 430, 0 }; case Item::DarkOakDoor: return { 431, 0 }; case Item::Repeater: return { 356, 0 }; case Item::Comparator: return { 404, 0 }; case Item::StructureBlock: return { 255, 0 }; case Item::IronShovel: return { 256, 0 }; case Item::IronPickaxe: return { 257, 0 }; case Item::IronAxe: return { 258, 0 }; case Item::FlintAndSteel: return { 259, 0 }; case Item::Apple: return { 260, 0 }; case Item::Bow: return { 261, 0 }; case Item::Arrow: return { 262, 0 }; case Item::Coal: return { 263, 0 }; case Item::Charcoal: return { 263, 1 }; case Item::Diamond: return { 264, 0 }; case Item::IronIngot: return { 265, 0 }; case Item::GoldIngot: return { 266, 0 }; case Item::IronSword: return { 267, 0 }; case Item::WoodenSword: return { 268, 0 }; case Item::WoodenShovel: return { 269, 0 }; case Item::WoodenPickaxe: return { 270, 0 }; case Item::WoodenAxe: return { 271, 0 }; case Item::StoneSword: return { 272, 0 }; case Item::StoneShovel: return { 273, 0 }; case Item::StonePickaxe: return { 274, 0 }; case Item::StoneAxe: return { 275, 0 }; case Item::DiamondSword: return { 276, 0 }; case Item::DiamondShovel: return { 277, 0 }; case Item::DiamondPickaxe: return { 278, 0 }; case Item::DiamondAxe: return { 279, 0 }; case Item::Stick: return { 280, 0 }; case Item::Bowl: return { 281, 0 }; case Item::MushroomStew: return { 282, 0 }; case Item::GoldenSword: return { 283, 0 }; case Item::GoldenShovel: return { 284, 0 }; case Item::GoldenPickaxe: return { 285, 0 }; case Item::GoldenAxe: return { 286, 0 }; case Item::String: return { 287, 0 }; case Item::Feather: return { 288, 0 }; case Item::Gunpowder: return { 289, 0 }; case Item::WoodenHoe: return { 290, 0 }; case Item::StoneHoe: return { 291, 0 }; case Item::IronHoe: return { 292, 0 }; case Item::DiamondHoe: return { 293, 0 }; case Item::GoldenHoe: return { 294, 0 }; case Item::WheatSeeds: return { 295, 0 }; case Item::Wheat: return { 296, 0 }; case Item::Bread: return { 297, 0 }; case Item::LeatherHelmet: return { 298, 0 }; case Item::LeatherChestplate: return { 299, 0 }; case Item::LeatherLeggings: return { 300, 0 }; case Item::LeatherBoots: return { 301, 0 }; case Item::ChainmailHelmet: return { 302, 0 }; case Item::ChainmailChestplate: return { 303, 0 }; case Item::ChainmailLeggings: return { 304, 0 }; case Item::ChainmailBoots: return { 305, 0 }; case Item::IronHelmet: return { 306, 0 }; case Item::IronChestplate: return { 307, 0 }; case Item::IronLeggings: return { 308, 0 }; case Item::IronBoots: return { 309, 0 }; case Item::DiamondHelmet: return { 310, 0 }; case Item::DiamondChestplate: return { 311, 0 }; case Item::DiamondLeggings: return { 312, 0 }; case Item::DiamondBoots: return { 313, 0 }; case Item::GoldenHelmet: return { 314, 0 }; case Item::GoldenChestplate: return { 315, 0 }; case Item::GoldenLeggings: return { 316, 0 }; case Item::GoldenBoots: return { 317, 0 }; case Item::Flint: return { 318, 0 }; case Item::Porkchop: return { 319, 0 }; case Item::CookedPorkchop: return { 320, 0 }; case Item::Painting: return { 321, 0 }; case Item::GoldenApple: return { 322, 0 }; case Item::EnchantedGoldenApple: return { 322, 1 }; case Item::OakSign: return { 323, 0 }; case Item::Bucket: return { 325, 0 }; case Item::WaterBucket: return { 326, 0 }; case Item::LavaBucket: return { 327, 0 }; case Item::Minecart: return { 328, 0 }; case Item::Saddle: return { 329, 0 }; case Item::Redstone: return { 331, 0 }; case Item::Snowball: return { 332, 0 }; case Item::OakBoat: return { 333, 0 }; case Item::Leather: return { 334, 0 }; case Item::MilkBucket: return { 335, 0 }; case Item::Brick: return { 336, 0 }; case Item::ClayBall: return { 337, 0 }; case Item::SugarCane: return { 338, 0 }; case Item::Paper: return { 339, 0 }; case Item::Book: return { 340, 0 }; case Item::SlimeBall: return { 341, 0 }; case Item::ChestMinecart: return { 342, 0 }; case Item::FurnaceMinecart: return { 343, 0 }; case Item::Egg: return { 344, 0 }; case Item::Compass: return { 345, 0 }; case Item::FishingRod: return { 346, 0 }; case Item::Clock: return { 347, 0 }; case Item::GlowstoneDust: return { 348, 0 }; case Item::Cod: return { 349, 0 }; case Item::Salmon: return { 349, 1 }; case Item::TropicalFish: return { 349, 2 }; case Item::Pufferfish: return { 349, 3 }; case Item::CookedCod: return { 350, 0 }; case Item::CookedSalmon: return { 350, 1 }; case Item::InkSac: return { 351, 0 }; case Item::RedDye: return { 351, 1 }; case Item::GreenDye: return { 351, 2 }; case Item::CocoaBeans: return { 351, 3 }; case Item::LapisLazuli: return { 351, 4 }; case Item::PurpleDye: return { 351, 5 }; case Item::CyanDye: return { 351, 6 }; case Item::LightGrayDye: return { 351, 7 }; case Item::GrayDye: return { 351, 8 }; case Item::PinkDye: return { 351, 9 }; case Item::LimeDye: return { 351, 10 }; case Item::YellowDye: return { 351, 11 }; case Item::LightBlueDye: return { 351, 12 }; case Item::MagentaDye: return { 351, 13 }; case Item::OrangeDye: return { 351, 14 }; case Item::BoneMeal: return { 351, 15 }; case Item::Bone: return { 352, 0 }; case Item::Sugar: return { 353, 0 }; case Item::Cake: return { 354, 0 }; case Item::WhiteBed: return { 355, 0 }; case Item::OrangeBed: return { 355, 1 }; case Item::MagentaBed: return { 355, 2 }; case Item::LightBlueBed: return { 355, 3 }; case Item::YellowBed: return { 355, 4 }; case Item::LimeBed: return { 355, 5 }; case Item::PinkBed: return { 355, 6 }; case Item::GrayBed: return { 355, 7 }; case Item::LightGrayBed: return { 355, 8 }; case Item::CyanBed: return { 355, 9 }; case Item::PurpleBed: return { 355, 10 }; case Item::BlueBed: return { 355, 11 }; case Item::BrownBed: return { 355, 12 }; case Item::GreenBed: return { 355, 13 }; case Item::RedBed: return { 355, 14 }; case Item::BlackBed: return { 355, 15 }; case Item::Cookie: return { 357, 0 }; case Item::FilledMap: return { 358, 0 }; case Item::Shears: return { 359, 0 }; case Item::MelonSlice: return { 360, 0 }; case Item::PumpkinSeeds: return { 361, 0 }; case Item::MelonSeeds: return { 362, 0 }; case Item::Beef: return { 363, 0 }; case Item::CookedBeef: return { 364, 0 }; case Item::Chicken: return { 365, 0 }; case Item::CookedChicken: return { 366, 0 }; case Item::RottenFlesh: return { 367, 0 }; case Item::EnderPearl: return { 368, 0 }; case Item::BlazeRod: return { 369, 0 }; case Item::GhastTear: return { 370, 0 }; case Item::GoldNugget: return { 371, 0 }; case Item::NetherWart: return { 372, 0 }; case Item::Potion: return { 373, 0 }; case Item::SplashPotion: return { 438, 0 }; case Item::LingeringPotion: return { 441, 0 }; case Item::GlassBottle: return { 374, 0 }; case Item::SpiderEye: return { 375, 0 }; case Item::FermentedSpiderEye: return { 376, 0 }; case Item::BlazePowder: return { 377, 0 }; case Item::MagmaCream: return { 378, 0 }; case Item::BrewingStand: return { 379, 0 }; case Item::Cauldron: return { 380, 0 }; case Item::EnderEye: return { 381, 0 }; case Item::GlisteringMelonSlice: return { 382, 0 }; case Item::BatSpawnEgg: return { 383, 65 }; case Item::BlazeSpawnEgg: return { 383, 61 }; case Item::CaveSpiderSpawnEgg: return { 383, 59 }; case Item::ChickenSpawnEgg: return { 383, 93 }; case Item::CowSpawnEgg: return { 383, 92 }; case Item::CreeperSpawnEgg: return { 383, 50 }; case Item::DonkeySpawnEgg: return { 383, 31 }; case Item::ElderGuardianSpawnEgg: return { 383, 4 }; case Item::EndermanSpawnEgg: return { 383, 58 }; case Item::EndermiteSpawnEgg: return { 383, 67 }; case Item::EvokerSpawnEgg: return { 383, 34 }; case Item::GhastSpawnEgg: return { 383, 56 }; case Item::GuardianSpawnEgg: return { 383, 68 }; case Item::HorseSpawnEgg: return { 383, 100 }; case Item::HuskSpawnEgg: return { 383, 23 }; case Item::LlamaSpawnEgg: return { 383, 103 }; case Item::MagmaCubeSpawnEgg: return { 383, 62 }; case Item::MooshroomSpawnEgg: return { 383, 96 }; case Item::MuleSpawnEgg: return { 383, 32 }; case Item::OcelotSpawnEgg: return { 383, 98 }; case Item::PigSpawnEgg: return { 383, 90 }; case Item::PolarBearSpawnEgg: return { 383, 102 }; case Item::RabbitSpawnEgg: return { 383, 101 }; case Item::SheepSpawnEgg: return { 383, 91 }; case Item::ShulkerSpawnEgg: return { 383, 69 }; case Item::SkeletonSpawnEgg: return { 383, 51 }; case Item::SkeletonHorseSpawnEgg: return { 383, 28 }; case Item::SlimeSpawnEgg: return { 383, 55 }; case Item::SpiderSpawnEgg: return { 383, 52 }; case Item::SquidSpawnEgg: return { 383, 94 }; case Item::StraySpawnEgg: return { 383, 6 }; case Item::VexSpawnEgg: return { 383, 35 }; case Item::VillagerSpawnEgg: return { 383, 120 }; case Item::VindicatorSpawnEgg: return { 383, 36 }; case Item::WitchSpawnEgg: return { 383, 66 }; case Item::WitherSkeletonSpawnEgg: return { 383, 5 }; case Item::WolfSpawnEgg: return { 383, 95 }; case Item::ZombieSpawnEgg: return { 383, 54 }; case Item::ZombieHorseSpawnEgg: return { 383, 29 }; case Item::ZombiePigmanSpawnEgg: return { 383, 57 }; case Item::ZombieVillagerSpawnEgg: return { 383, 27 }; case Item::ExperienceBottle: return { 384, 0 }; case Item::FireCharge: return { 385, 0 }; case Item::WritableBook: return { 386, 0 }; case Item::WrittenBook: return { 387, 0 }; case Item::Emerald: return { 388, 0 }; case Item::ItemFrame: return { 389, 0 }; case Item::FlowerPot: return { 390, 0 }; case Item::Carrot: return { 391, 0 }; case Item::Potato: return { 392, 0 }; case Item::BakedPotato: return { 393, 0 }; case Item::PoisonousPotato: return { 394, 0 }; case Item::Map: return { 395, 0 }; case Item::GoldenCarrot: return { 396, 0 }; case Item::SkeletonSkull: return { 397, 0 }; case Item::WitherSkeletonSkull: return { 397, 1 }; case Item::PlayerHead: return { 397, 3 }; case Item::ZombieHead: return { 397, 2 }; case Item::CreeperHead: return { 397, 4 }; case Item::DragonHead: return { 397, 5 }; case Item::CarrotOnAStick: return { 398, 0 }; case Item::NetherStar: return { 399, 0 }; case Item::PumpkinPie: return { 400, 0 }; case Item::FireworkRocket: return { 401, 0 }; case Item::FireworkStar: return { 402, 0 }; case Item::EnchantedBook: return { 403, 0 }; case Item::NetherBrick: return { 405, 0 }; case Item::Quartz: return { 406, 0 }; case Item::TNTMinecart: return { 407, 0 }; case Item::HopperMinecart: return { 408, 0 }; case Item::PrismarineShard: return { 409, 0 }; case Item::PrismarineCrystals: return { 410, 0 }; case Item::Rabbit: return { 411, 0 }; case Item::CookedRabbit: return { 412, 0 }; case Item::RabbitStew: return { 413, 0 }; case Item::RabbitFoot: return { 414, 0 }; case Item::RabbitHide: return { 415, 0 }; case Item::ArmorStand: return { 416, 0 }; case Item::IronHorseArmor: return { 417, 0 }; case Item::GoldenHorseArmor: return { 418, 0 }; case Item::DiamondHorseArmor: return { 419, 0 }; case Item::Lead: return { 420, 0 }; case Item::NameTag: return { 421, 0 }; case Item::CommandBlockMinecart: return { 422, 0 }; case Item::Mutton: return { 423, 0 }; case Item::CookedMutton: return { 424, 0 }; case Item::WhiteBanner: return { 425, 15 }; case Item::OrangeBanner: return { 425, 14 }; case Item::MagentaBanner: return { 425, 13 }; case Item::LightBlueBanner: return { 425, 12 }; case Item::YellowBanner: return { 425, 11 }; case Item::LimeBanner: return { 425, 10 }; case Item::PinkBanner: return { 425, 9 }; case Item::GrayBanner: return { 425, 8 }; case Item::LightGrayBanner: return { 425, 7 }; case Item::CyanBanner: return { 425, 6 }; case Item::PurpleBanner: return { 425, 5 }; case Item::BlueBanner: return { 425, 4 }; case Item::BrownBanner: return { 425, 3 }; case Item::GreenBanner: return { 425, 2 }; case Item::RedBanner: return { 425, 1 }; case Item::BlackBanner: return { 425, 0 }; case Item::EndCrystal: return { 426, 0 }; case Item::ChorusFruit: return { 432, 0 }; case Item::PoppedChorusFruit: return { 433, 0 }; case Item::Beetroot: return { 434, 0 }; case Item::BeetrootSeeds: return { 435, 0 }; case Item::BeetrootSoup: return { 436, 0 }; case Item::DragonBreath: return { 437, 0 }; case Item::SpectralArrow: return { 439, 0 }; case Item::TippedArrow: return { 440, 0 }; case Item::Shield: return { 442, 0 }; case Item::Elytra: return { 443, 0 }; case Item::SpruceBoat: return { 444, 0 }; case Item::BirchBoat: return { 445, 0 }; case Item::JungleBoat: return { 446, 0 }; case Item::AcaciaBoat: return { 447, 0 }; case Item::DarkOakBoat: return { 448, 0 }; case Item::TotemOfUndying: return { 449, 0 }; case Item::ShulkerShell: return { 450, 0 }; case Item::IronNugget: return { 452, 0 }; case Item::MusicDisc13: return { 2256, 0 }; case Item::MusicDiscCat: return { 2257, 0 }; case Item::MusicDiscBlocks: return { 2258, 0 }; case Item::MusicDiscChirp: return { 2259, 0 }; case Item::MusicDiscFar: return { 2260, 0 }; case Item::MusicDiscMall: return { 2261, 0 }; case Item::MusicDiscMellohi: return { 2262, 0 }; case Item::MusicDiscStal: return { 2263, 0 }; case Item::MusicDiscStrad: return { 2264, 0 }; case Item::MusicDiscWard: return { 2265, 0 }; case Item::MusicDisc11: return { 2266, 0 }; case Item::MusicDiscWait: return { 2267, 0 }; default: return { 0, 0 }; } } } ================================================ FILE: src/Protocol/Palettes/Upgrade.h ================================================ #pragma once #include "ChunkDef.h" #include "BlockState.h" #include "Registries/Items.h" namespace PaletteUpgrade { BlockState FromBlock(BLOCKTYPE Block, NIBBLETYPE Meta); Item FromItem(short Item, short Damage); std::pair ToItem(Item ID); } ================================================ FILE: src/Protocol/Protocol.h ================================================ // Protocol.h // Interfaces to the cProtocol class representing the generic interface that a protocol // parser and serializer must implement #pragma once #include "../Defines.h" #include "../Scoreboard.h" #include "../ByteBuffer.h" #include "../EffectID.h" #include "../World.h" class cMap; class cExpOrb; class cPlayer; class cEntity; class cWindow; class cPainting; class cWorld; class cMonster; class cCompositeChat; class cPacketizer; struct StatisticsManager; class cProtocol { public: cProtocol(cClientHandle * a_Client) : m_Client(a_Client), m_OutPacketBuffer(64 KiB), m_OutPacketLenBuffer(20) // 20 bytes is more than enough for one VarInt { } virtual ~cProtocol() {} /** Logical types of outgoing packets. These values get translated to on-wire packet IDs in GetPacketID(), specific for each protocol. This is mainly useful for protocol sub-versions that re-number the packets while using mostly the same packet layout. */ enum ePacketType { pktAttachEntity = 0, pktBlockAction, pktBlockBreakAnim, pktBlockChange, pktBlockChanges, pktBossBar, pktCameraSetTo, pktChatRaw, pktCollectEntity, pktDestroyEntity, pktDifficulty, pktDisconnectDuringLogin, pktDisconnectDuringGame, pktDisplayObjective, pktEditSign, pktEncryptionRequest, pktEntityAnimation, pktEntityEffect, pktEntityEquipment, pktEntityHeadLook, pktEntityLook, pktEntityMeta, pktEntityProperties, pktEntityRelMove, pktEntityRelMoveLook, pktEntityStatus, pktEntityVelocity, pktExperience, pktExplosion, pktGameMode, pktHeldItemChange, pktHorseWindowOpen, pktInventorySlot, pktJoinGame, pktKeepAlive, pktLeashEntity, pktLoginSuccess, pktMapData, pktParticleEffect, pktPingResponse, pktPlayerAbilities, pktPlayerList, pktPlayerListHeaderFooter, pktPlayerMoveLook, pktPluginMessage, pktRemoveEntityEffect, pktResourcePack, pktRespawn, pktScoreboardObjective, pktSpawnObject, pktSoundEffect, pktSoundParticleEffect, pktSpawnExperienceOrb, pktSpawnGlobalEntity, pktSpawnMob, pktSpawnOtherPlayer, pktSpawnPainting, pktSpawnPosition, pktStartCompression, pktStatistics, pktStatusResponse, pktTabCompletionResults, pktTeleportEntity, pktTimeUpdate, pktTitle, pktUnloadChunk, pktUnlockRecipe, pktUpdateBlockEntity, pktUpdateHealth, pktUpdateScore, pktUpdateSign, pktUseBed, pktWeather, pktWindowItems, pktWindowClose, pktWindowOpen, pktWindowProperty }; enum class EntityMetadata { EntityFlags, EntityAir, EntityCustomName, EntityCustomNameVisible, EntitySilent, EntityNoGravity, EntityPose, PotionThrown, FallingBlockPosition, AreaEffectCloudRadius, AreaEffectCloudColor, AreaEffectCloudSinglePointEffect, AreaEffectCloudParticleId, AreaEffectCloudParticleParameter1, AreaEffectCloudParticleParameter2, ArrowFlags, TippedArrowColor, PiercingLevel, BoatLastHitTime, BoatForwardDirection, BoatDamageTaken, BoatType, BoatLeftPaddleTurning, BoatRightPaddleTurning, BoatSplashTimer, EnderCrystalBeamTarget, EnderCrystalShowBottom, WitherSkullInvulnerable, FireworkInfo, FireworkBoostedEntityId, FireworkFromCrossbow, ItemFrameItem, ItemFrameRotation, ItemItem, LivingActiveHand, LivingHealth, LivingPotionEffectColor, LivingPotionEffectAmbient, LivingNumberOfArrows, PlayerAdditionalHearts, PlayerScore, PlayerDisplayedSkinParts, PlayerMainHand, ArmorStandStatus, ArmorStandHeadRotation, ArmorStandBodyRotation, ArmorStandLeftArmRotation, ArmorStandRightArmRotation, ArmorStandLeftLegRotation, ArmorStandRightLegRotation, InsentientFlags, BatHanging, AgeableIsBaby, AbstractHorseFlags, AbstractHorseOwner, HorseVariant, HorseArmour, ChestedHorseChested, LlamaStrength, LlamaCarpetColor, LlamaVariant, PigHasSaddle, PigTotalCarrotOnAStickBoost, RabbitType, PolarBearStanding, SheepFlags, TameableAnimalFlags, TameableAnimalOwner, ThrowableItem, TridentLoyaltyLevel, OcelotType, WolfDamageTaken, WolfBegging, WolfCollarColour, VillagerProfession, IronGolemPlayerCreated, ShulkerFacingDirection, ShulkerAttachmentFallingBlockPosition, ShulkerShieldHeight, BlazeOnFire, CreeperState, CreeperPowered, CreeperIgnited, GuardianStatus, GuardianTarget, IllagerFlags, SpeIlagerSpell, VexFlags, AbstractSkeletonArmsSwinging, SpiderClimbing, WitchAggresive, WitchDrinking, WitherFirstHeadTarget, WitherSecondHeadTarget, WitherThirdHeadTarget, WitherInvulnerableTimer, ZombieIsBaby, ZombieUnusedWasType, ZombieHandsRisedUp, ZombieVillagerConverting, ZombieVillagerProfession, EndermanCarriedBlock, EndermanScreaming, EnderDragonDragonPhase, GhastAttacking, SlimeSize, MinecartShakingPower, MinecartShakingDirection, MinecartShakingMultiplier, MinecartBlockIDMeta, MinecartBlockY, MinecartShowBlock, MinecartCommandBlockCommand, MinecartCommandBlockLastOutput, MinecartFurnacePowered, MooshroomType, TNTPrimedFuseTime }; enum class EntityMetadataType { Byte, VarInt, Float, String, Chat, OptChat, Item, Boolean, Rotation, Position, OptPosition, Direction, OptUUID, OptBlockID, NBT, Particle, VillagerData, OptVarInt, Pose }; /** The protocol version number, received from the client in the Handshake packet. */ enum class Version { v1_8_0 = 47, v1_9_0 = 107, v1_9_1 = 108, v1_9_2 = 109, v1_9_4 = 110, v1_10_0 = 210, v1_11_0 = 315, v1_11_1 = 316, v1_12 = 335, v1_12_1 = 338, v1_12_2 = 340, v1_13 = 393, v1_13_1 = 401, v1_13_2 = 404, v1_14 = 477, v1_14_1 = 480, v1_14_2 = 485, v1_14_3 = 490, v1_14_4 = 498 }; enum State { Status = 1, Login = 2, Game = 3, }; /** Called by cClientHandle to process data, when the client sends some. The protocol uses the provided buffers for storage and processing, and must have exclusive access to them. */ virtual void DataReceived(cByteBuffer & a_Buffer, ContiguousByteBuffer & a_Data) = 0; /** Called by cClientHandle to finalise a buffer of prepared data before they are sent to the client. Descendants may for example, encrypt the data if needed. The protocol modifies the provided buffer in-place. */ virtual void DataPrepared(ContiguousByteBuffer & a_Data) = 0; // Sending stuff to clients (alphabetically sorted): virtual void SendAttachEntity (const cEntity & a_Entity, const cEntity & a_Vehicle) = 0; virtual void SendBlockAction (Vector3i a_BlockPos, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType) = 0; virtual void SendBlockBreakAnim (UInt32 a_EntityID, Vector3i a_BlockPos, char a_Stage) = 0; virtual void SendBlockChange (Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) = 0; virtual void SendBlockChanges (int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes) = 0; virtual void SendBossBarAdd (UInt32 a_UniqueID, const cCompositeChat & a_Title, float a_FractionFilled, BossBarColor a_Color, BossBarDivisionType a_DivisionType, bool a_DarkenSky, bool a_PlayEndMusic, bool a_CreateFog) = 0; virtual void SendBossBarRemove (UInt32 a_UniqueID) = 0; virtual void SendBossBarUpdateHealth (UInt32 a_UniqueID, float a_FractionFilled) = 0; virtual void SendBossBarUpdateFlags (UInt32 a_UniqueID, bool a_DarkenSky, bool a_PlayEndMusic, bool a_CreateFog) = 0; virtual void SendBossBarUpdateStyle (UInt32 a_UniqueID, BossBarColor a_Color, BossBarDivisionType a_DivisionType) = 0; virtual void SendBossBarUpdateTitle (UInt32 a_UniqueID, const cCompositeChat & a_Title) = 0; virtual void SendCameraSetTo (const cEntity & a_Entity) = 0; virtual void SendChat (const AString & a_Message, eChatType a_Type) = 0; virtual void SendChat (const cCompositeChat & a_Message, eChatType a_Type, bool a_ShouldUseChatPrefixes) = 0; virtual void SendChatRaw (const AString & a_MessageRaw, eChatType a_Type) = 0; virtual void SendChunkData (ContiguousByteBufferView a_ChunkData) = 0; virtual void SendCollectEntity (const cEntity & a_Collected, const cEntity & a_Collector, unsigned a_Count) = 0; virtual void SendDestroyEntity (const cEntity & a_Entity) = 0; virtual void SendDetachEntity (const cEntity & a_Entity, const cEntity & a_PreviousVehicle) = 0; virtual void SendDisconnect (const AString & a_Reason) = 0; virtual void SendEditSign (Vector3i a_BlockPos) = 0; ///< Request the client to open up the sign editor for the sign (1.6+) virtual void SendEntityEffect (const cEntity & a_Entity, int a_EffectID, int a_Amplifier, int a_Duration) = 0; virtual void SendEntityAnimation (const cEntity & a_Entity, EntityAnimation a_Animation) = 0; virtual void SendEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item) = 0; virtual void SendEntityHeadLook (const cEntity & a_Entity) = 0; virtual void SendEntityLook (const cEntity & a_Entity) = 0; virtual void SendEntityMetadata (const cEntity & a_Entity) = 0; virtual void SendEntityPosition (const cEntity & a_Entity) = 0; virtual void SendEntityProperties (const cEntity & a_Entity) = 0; virtual void SendEntityVelocity (const cEntity & a_Entity) = 0; virtual void SendExplosion (Vector3f a_Position, float a_Power) = 0; virtual void SendGameMode (eGameMode a_GameMode) = 0; virtual void SendHealth (void) = 0; virtual void SendHeldItemChange (int a_ItemIndex) = 0; virtual void SendHideTitle (void) = 0; virtual void SendInventorySlot (char a_WindowID, short a_SlotNum, const cItem & a_Item) = 0; virtual void SendKeepAlive (UInt32 a_PingID) = 0; virtual void SendLeashEntity (const cEntity & a_Entity, const cEntity & a_EntityLeashedTo) = 0; virtual void SendLogin (const cPlayer & a_Player, const cWorld & a_World) = 0; virtual void SendLoginSuccess (void) = 0; virtual void SendMapData (const cMap & a_Map, int a_DataStartX, int a_DataStartY) = 0; virtual void SendPaintingSpawn (const cPainting & a_Painting) = 0; virtual void SendPlayerAbilities (void) = 0; virtual void SendParticleEffect (const AString & a_SoundName, Vector3f a_Src, Vector3f a_Offset, float a_ParticleData, int a_ParticleAmount) = 0; virtual void SendParticleEffect (const AString & a_SoundName, Vector3f a_Src, Vector3f a_Offset, float a_ParticleData, int a_ParticleAmount, std::array a_Data) = 0; virtual void SendPlayerListAddPlayer (const cPlayer & a_Player) = 0; virtual void SendPlayerListHeaderFooter (const cCompositeChat & a_Header, const cCompositeChat & a_Footer) = 0; virtual void SendPlayerListRemovePlayer (const cPlayer & a_Player) = 0; virtual void SendPlayerListUpdateGameMode (const cPlayer & a_Player) = 0; virtual void SendPlayerListUpdatePing () = 0; virtual void SendPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_CustomName) = 0; virtual void SendPlayerMoveLook (Vector3d a_Pos, float a_Yaw, float a_Pitch, bool a_IsRelative) = 0; virtual void SendPlayerMoveLook (void) = 0; virtual void SendPlayerPermissionLevel (void) = 0; virtual void SendPlayerPosition (void) = 0; virtual void SendPlayerSpawn (const cPlayer & a_Player) = 0; virtual void SendPluginMessage (const AString & a_Channel, ContiguousByteBufferView a_Message) = 0; virtual void SendRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID) = 0; virtual void SendResetTitle (void) = 0; virtual void SendResourcePack (const AString & a_ResourcePackUrl) = 0; virtual void SendRespawn (eDimension a_Dimension) = 0; virtual void SendExperience (void) = 0; virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) = 0; virtual void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) = 0; virtual void SendScoreUpdate (const AString & a_Objective, const AString & a_Player, cObjective::Score a_Score, Byte a_Mode) = 0; virtual void SendDisplayObjective (const AString & a_Objective, cScoreboard::eDisplaySlot a_Display) = 0; virtual void SendSetSubTitle (const cCompositeChat & a_SubTitle) = 0; virtual void SendSetRawSubTitle (const AString & a_SubTitle) = 0; virtual void SendSetTitle (const cCompositeChat & a_Title) = 0; virtual void SendSetRawTitle (const AString & a_Title) = 0; virtual void SendSoundEffect (const AString & a_SoundName, Vector3d a_Origin, float a_Volume, float a_Pitch) = 0; virtual void SendSoundParticleEffect (const EffectID a_EffectID, Vector3i a_Origin, int a_Data) = 0; virtual void SendSpawnEntity (const cEntity & a_Entity) = 0; virtual void SendSpawnMob (const cMonster & a_Mob) = 0; virtual void SendStatistics (const StatisticsManager & a_Manager) = 0; virtual void SendTabCompletionResults (const AStringVector & a_Results) = 0; virtual void SendThunderbolt (Vector3i a_Origin) = 0; virtual void SendTitleTimes (int a_FadeInTicks, int a_DisplayTicks, int a_FadeOutTicks) = 0; virtual void SendTimeUpdate (cTickTimeLong a_WorldAge, cTickTimeLong a_WorldDate, bool a_DoDaylightCycle) = 0; virtual void SendUnleashEntity (const cEntity & a_Entity) = 0; virtual void SendUnloadChunk (int a_ChunkX, int a_ChunkZ) = 0; virtual void SendUpdateBlockEntity (cBlockEntity & a_BlockEntity) = 0; virtual void SendUpdateSign (Vector3i a_BlockPos, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4) = 0; virtual void SendUnlockRecipe (UInt32 a_RecipeID) = 0; virtual void SendInitRecipes (UInt32 a_RecipeID) = 0; virtual void SendWeather (eWeather a_Weather) = 0; virtual void SendWholeInventory (const cWindow & a_Window) = 0; virtual void SendWindowClose (const cWindow & a_Window) = 0; virtual void SendWindowOpen (const cWindow & a_Window) = 0; virtual void SendWindowProperty (const cWindow & a_Window, size_t a_Property, short a_Value) = 0; /** Returns the ServerID used for authentication through session.minecraft.net */ virtual AString GetAuthServerID(void) = 0; protected: friend class cPacketizer; cClientHandle * m_Client; /** Provides synchronization for sending the entire packet at once. Each SendXYZ() function must acquire this CS in order to send the whole packet at once. Automated via cPacketizer class. */ cCriticalSection m_CSPacket; /** Buffer for composing the outgoing packets, through cPacketizer */ cByteBuffer m_OutPacketBuffer; /** Buffer for composing packet length (so that each cPacketizer instance doesn't allocate a new cPacketBuffer) */ cByteBuffer m_OutPacketLenBuffer; /** Returns the protocol-specific packet ID given the protocol-agnostic packet enum. */ virtual UInt32 GetPacketID(ePacketType a_Packet) const = 0; /** Returns the current protocol's version, for handling status requests. */ virtual Version GetProtocolVersion() const = 0; /** Sends a single packet contained within the cPacketizer class. The cPacketizer's destructor calls this to send the contained packet; protocol may transform the data (compression in 1.8 etc). */ virtual void SendPacket(cPacketizer & a_Packet) = 0; } ; ================================================ FILE: src/Protocol/ProtocolRecognizer.cpp ================================================ // ProtocolRecognizer.cpp // Implements the cProtocolRecognizer class representing the meta-protocol that recognizes possibly multiple // protocol versions and redirects everything to them #include "Globals.h" #include "ProtocolRecognizer.h" #include "Protocol_1_8.h" #include "Protocol_1_9.h" #include "Protocol_1_10.h" #include "Protocol_1_11.h" #include "Protocol_1_12.h" #include "Protocol_1_13.h" #include "Protocol_1_14.h" #include "../ClientHandle.h" #include "../Root.h" #include "../Server.h" #include "../World.h" #include "../JsonUtils.h" #include "../Bindings/PluginManager.h" struct TriedToJoinWithUnsupportedProtocolException : public std::runtime_error { explicit TriedToJoinWithUnsupportedProtocolException(const std::string & a_Message) : std::runtime_error(a_Message) { } }; cMultiVersionProtocol::cMultiVersionProtocol() : m_Buffer(32 KiB), m_WaitingForData(true) { } AString cMultiVersionProtocol::GetVersionTextFromInt(cProtocol::Version a_ProtocolVersion) { switch (a_ProtocolVersion) { case cProtocol::Version::v1_8_0: return "1.8"; case cProtocol::Version::v1_9_0: return "1.9"; case cProtocol::Version::v1_9_1: return "1.9.1"; case cProtocol::Version::v1_9_2: return "1.9.2"; case cProtocol::Version::v1_9_4: return "1.9.4"; case cProtocol::Version::v1_10_0: return "1.10"; case cProtocol::Version::v1_11_0: return "1.11"; case cProtocol::Version::v1_11_1: return "1.11.1"; case cProtocol::Version::v1_12: return "1.12"; case cProtocol::Version::v1_12_1: return "1.12.1"; case cProtocol::Version::v1_12_2: return "1.12.2"; case cProtocol::Version::v1_13: return "1.13"; case cProtocol::Version::v1_13_1: return "1.13.1"; case cProtocol::Version::v1_13_2: return "1.13.2"; case cProtocol::Version::v1_14: return "1.14"; case cProtocol::Version::v1_14_1: return "1.14.1"; case cProtocol::Version::v1_14_2: return "1.14.2"; case cProtocol::Version::v1_14_3: return "1.14.3"; case cProtocol::Version::v1_14_4: return "1.14.4"; } ASSERT(!"Unknown protocol version"); return fmt::format(FMT_STRING("Unknown protocol ({})"), a_ProtocolVersion); } void cMultiVersionProtocol::HandleIncomingDataInRecognitionStage(cClientHandle & a_Client, ContiguousByteBuffer & a_Data) { // NOTE: If a new protocol is added or an old one is removed, adjust MCS_CLIENT_VERSIONS and MCS_PROTOCOL_VERSIONS macros in the header file /* Write all incoming data unmodified into m_Buffer. Writing everything is always okay to do: 1. We can be sure protocol encryption hasn't started yet since m_Protocol hasn't been called, hence no decryption needs to take place 2. The extra data are processed at the end of this function */ if (!m_Buffer.Write(a_Data.data(), a_Data.size())) { a_Client.PacketBufferFull(); return; } if (TryHandleHTTPRequest(a_Client, a_Data)) { return; } // TODO: recover from git history // Unlengthed protocol, ... // Lengthed protocol, try if it has the entire initial handshake packet: if ( UInt32 PacketLen; // If not enough bytes for the packet length, keep waiting !m_Buffer.ReadVarInt(PacketLen) || // If not enough bytes for the packet, keep waiting // (More of a sanity check to make sure no one tries anything funny, since ReadXXX can wait for data themselves) !m_Buffer.CanReadBytes(PacketLen) ) { m_Buffer.ResetRead(); return; } /* Figure out the client's version. 1. m_Protocol != nullptr: the protocol is supported and we have a handler 2. m_Protocol == nullptr: the protocol is unsupported, handling is a special case done by ourselves 3. Exception: the data sent were garbage, the client handle deals with it by disconnecting */ m_Protocol = TryRecognizeLengthedProtocol(a_Client); // Version recognised. Cause HandleIncomingData to stop calling us to handle data: m_WaitingForData = false; // Explicitly process any remaining data (already written to m_Buffer) with the new handler: { ContiguousByteBuffer Empty; HandleIncomingData(a_Client, Empty); } } void cMultiVersionProtocol::HandleIncomingDataInOldPingResponseStage(cClientHandle & a_Client, const ContiguousByteBufferView a_Data) { if (!m_Buffer.Write(a_Data.data(), a_Data.size())) { a_Client.PacketBufferFull(); return; } // Handle server list ping packets for (;;) { UInt32 PacketLen; UInt32 PacketID; if ( !m_Buffer.ReadVarInt32(PacketLen) || !m_Buffer.CanReadBytes(PacketLen) || !m_Buffer.ReadVarInt32(PacketID) ) { // Not enough data m_Buffer.ResetRead(); break; } if ((PacketID == 0x00) && (PacketLen == 1)) // Request packet { HandlePacketStatusRequest(a_Client); } else if ((PacketID == 0x01) && (PacketLen == 9)) // Ping packet { HandlePacketStatusPing(a_Client); } else { a_Client.PacketUnknown(PacketID); return; } m_Buffer.CommitRead(); } } void cMultiVersionProtocol::HandleIncomingData(cClientHandle & a_Client, ContiguousByteBuffer & a_Data) { if (m_WaitingForData) { HandleIncomingDataInRecognitionStage(a_Client, a_Data); } else if (m_Protocol == nullptr) { // Got a Handshake for an unrecognised version, process future data accordingly: HandleIncomingDataInOldPingResponseStage(a_Client, a_Data); } else { // The protocol recogniser succesfully identified a supported version, direct data to that protocol: m_Protocol->DataReceived(m_Buffer, a_Data); } } void cMultiVersionProtocol::HandleOutgoingData(ContiguousByteBuffer & a_Data) { // Normally only the protocol sends data, so outgoing data are only present when m_Protocol != nullptr. // However, for unrecognised protocols we send data too, and that's when m_Protocol == nullptr. Check to avoid crashing (GH #5260). if (m_Protocol != nullptr) { m_Protocol->DataPrepared(a_Data); } } void cMultiVersionProtocol::SendDisconnect(cClientHandle & a_Client, const AString & a_Reason) { if (m_Protocol != nullptr) { m_Protocol->SendDisconnect(a_Reason); return; } const AString Message = JsonUtils::SerializeSingleValueJsonObject("text", a_Reason); const auto PacketID = GetPacketID(cProtocol::ePacketType::pktDisconnectDuringLogin); cByteBuffer Out( cByteBuffer::GetVarIntSize(PacketID) + cByteBuffer::GetVarIntSize(static_cast(Message.size())) + Message.size() ); VERIFY(Out.WriteVarInt32(PacketID)); VERIFY(Out.WriteVarUTF8String(Message)); SendPacket(a_Client, Out); } bool cMultiVersionProtocol::TryHandleHTTPRequest(cClientHandle & a_Client, ContiguousByteBuffer & a_Data) { const auto RedirectUrl = cRoot::Get()->GetServer()->GetCustomRedirectUrl(); if (RedirectUrl.empty()) { return false; } ContiguousByteBuffer Buffer; m_Buffer.ReadSome(Buffer, 10U); m_Buffer.ResetRead(); // The request line, hastily decoded with the hope that it's encoded in US-ASCII. const std::string_view Value(reinterpret_cast(Buffer.data()), Buffer.size()); if (Value == u8"GET / HTTP") { const auto Response = fmt::format(u8"HTTP/1.0 303 See Other\r\nLocation: {}\r\n\r\n", cRoot::Get()->GetServer()->GetCustomRedirectUrl()); a_Client.SendData({ reinterpret_cast(Response.data()), Response.size() }); a_Client.Destroy(); return true; } return false; } std::unique_ptr cMultiVersionProtocol::TryRecognizeLengthedProtocol(cClientHandle & a_Client) { UInt32 PacketType; UInt32 ProtocolVersion; AString ServerAddress; UInt16 ServerPort; UInt32 NextStateValue; if (!m_Buffer.ReadVarInt(PacketType) || (PacketType != 0x00)) { // Not an initial handshake packet, we don't know how to talk to them: LOGD("Client \"%s\" uses an unsupported protocol (lengthed, initial packet %u)", a_Client.GetIPString().c_str(), PacketType ); throw TriedToJoinWithUnsupportedProtocolException("Your client isn't supported.\nTry connecting with Minecraft " MCS_CLIENT_VERSIONS); } if ( !m_Buffer.ReadVarInt(ProtocolVersion) || !m_Buffer.ReadVarUTF8String(ServerAddress) || !m_Buffer.ReadBEUInt16(ServerPort) || !m_Buffer.ReadVarInt(NextStateValue) ) { // TryRecognizeProtocol guarantees that we will have as much // data to read as the client claims in the protocol length field: throw TriedToJoinWithUnsupportedProtocolException("Incorrect amount of data received - hacked client?"); } const auto NextState = [NextStateValue] { switch (NextStateValue) { case 1: return cProtocol::State::Status; case 2: return cProtocol::State::Login; case 3: return cProtocol::State::Game; default: throw TriedToJoinWithUnsupportedProtocolException("Your client isn't supported.\nTry connecting with Minecraft " MCS_CLIENT_VERSIONS); } }(); // TODO: this should be a protocol property, not ClientHandle: a_Client.SetProtocolVersion(ProtocolVersion); // All good, eat up the data: m_Buffer.CommitRead(); switch (ProtocolVersion) { case static_cast(cProtocol::Version::v1_8_0): return std::make_unique (&a_Client, ServerAddress, NextState); case static_cast(cProtocol::Version::v1_9_0): return std::make_unique (&a_Client, ServerAddress, NextState); case static_cast(cProtocol::Version::v1_9_1): return std::make_unique (&a_Client, ServerAddress, NextState); case static_cast(cProtocol::Version::v1_9_2): return std::make_unique (&a_Client, ServerAddress, NextState); case static_cast(cProtocol::Version::v1_9_4): return std::make_unique (&a_Client, ServerAddress, NextState); case static_cast(cProtocol::Version::v1_10_0): return std::make_unique(&a_Client, ServerAddress, NextState); case static_cast(cProtocol::Version::v1_11_0): return std::make_unique(&a_Client, ServerAddress, NextState); case static_cast(cProtocol::Version::v1_11_1): return std::make_unique(&a_Client, ServerAddress, NextState); case static_cast(cProtocol::Version::v1_12): return std::make_unique (&a_Client, ServerAddress, NextState); case static_cast(cProtocol::Version::v1_12_1): return std::make_unique(&a_Client, ServerAddress, NextState); case static_cast(cProtocol::Version::v1_12_2): return std::make_unique(&a_Client, ServerAddress, NextState); case static_cast(cProtocol::Version::v1_13): return std::make_unique (&a_Client, ServerAddress, NextState); case static_cast(cProtocol::Version::v1_13_1): return std::make_unique(&a_Client, ServerAddress, NextState); case static_cast(cProtocol::Version::v1_13_2): return std::make_unique(&a_Client, ServerAddress, NextState); case static_cast(cProtocol::Version::v1_14): return std::make_unique (&a_Client, ServerAddress, NextState); case static_cast(cProtocol::Version::v1_14_1): return std::make_unique(&a_Client, ServerAddress, NextState); case static_cast(cProtocol::Version::v1_14_2): return std::make_unique(&a_Client, ServerAddress, NextState); case static_cast(cProtocol::Version::v1_14_3): return std::make_unique(&a_Client, ServerAddress, NextState); case static_cast(cProtocol::Version::v1_14_4): return std::make_unique(&a_Client, ServerAddress, NextState); default: { LOGD("Client \"%s\" uses an unsupported protocol (lengthed, version %u (0x%x))", a_Client.GetIPString(), ProtocolVersion, ProtocolVersion ); if (NextState != cProtocol::State::Status) { throw TriedToJoinWithUnsupportedProtocolException( fmt::format(FMT_STRING("Unsupported protocol version {}.\nTry connecting with Minecraft {}"), ProtocolVersion, MCS_CLIENT_VERSIONS) ); } // No cProtocol can handle the client: return nullptr; } } } void cMultiVersionProtocol::SendPacket(cClientHandle & a_Client, cByteBuffer & a_OutPacketBuffer) { // Writes out the packet normally. UInt32 PacketLen = static_cast(a_OutPacketBuffer.GetUsedSpace()); cByteBuffer OutPacketLenBuffer(cByteBuffer::GetVarIntSize(PacketLen)); // Compression doesn't apply to this state, send raw data: VERIFY(OutPacketLenBuffer.WriteVarInt32(PacketLen)); ContiguousByteBuffer LengthData; OutPacketLenBuffer.ReadAll(LengthData); a_Client.SendData(LengthData); // Send the packet's payload: ContiguousByteBuffer PacketData; a_OutPacketBuffer.ReadAll(PacketData); a_OutPacketBuffer.CommitRead(); a_Client.SendData(PacketData); } UInt32 cMultiVersionProtocol::GetPacketID(cProtocol::ePacketType a_PacketType) { switch (a_PacketType) { case cProtocol::ePacketType::pktDisconnectDuringLogin: return 0x00; case cProtocol::ePacketType::pktStatusResponse: return 0x00; case cProtocol::ePacketType::pktPingResponse: return 0x01; default: { ASSERT(!"GetPacketID() called for an unhandled packet"); return 0; } } } void cMultiVersionProtocol::HandlePacketStatusRequest(cClientHandle & a_Client) { cServer * Server = cRoot::Get()->GetServer(); AString ServerDescription = Server->GetDescription(); auto NumPlayers = static_cast(Server->GetNumPlayers()); auto MaxPlayers = static_cast(Server->GetMaxPlayers()); AString Favicon = Server->GetFaviconData(); cRoot::Get()->GetPluginManager()->CallHookServerPing(a_Client, ServerDescription, NumPlayers, MaxPlayers, Favicon); // Version: Json::Value Version; Version["name"] = "Cuberite " MCS_CLIENT_VERSIONS; Version["protocol"] = MCS_LATEST_PROTOCOL_VERSION; // Players: Json::Value Players; Players["online"] = NumPlayers; Players["max"] = MaxPlayers; // TODO: Add "sample" // Description: Json::Value Description; Description["text"] = ServerDescription.c_str(); // Create the response: Json::Value ResponseValue; ResponseValue["version"] = Version; ResponseValue["players"] = Players; ResponseValue["description"] = Description; if (!Favicon.empty()) { ResponseValue["favicon"] = "data:image/png;base64," + Favicon; } AString Response = JsonUtils::WriteFastString(ResponseValue); // Send the response in a packet: cByteBuffer out(Response.size() + 12); // String + 2x VarInt + extra space for safety VERIFY(out.WriteVarInt32(GetPacketID(cProtocol::ePacketType::pktStatusResponse))); VERIFY(out.WriteVarUTF8String(Response)); SendPacket(a_Client, out); } void cMultiVersionProtocol::HandlePacketStatusPing(cClientHandle & a_Client) { Int64 Timestamp; if (!m_Buffer.ReadBEInt64(Timestamp)) { return; } // Send the ping response packet: cByteBuffer out(16); // VarInt + Int64 + extra space for safety VERIFY(out.WriteVarInt32(GetPacketID(cProtocol::ePacketType::pktPingResponse))); VERIFY(out.WriteBEInt64(Timestamp)); SendPacket(a_Client, out); } ================================================ FILE: src/Protocol/ProtocolRecognizer.h ================================================ #pragma once #include "Protocol.h" // Adjust these if a new protocol is added or an old one is removed: #define MCS_CLIENT_VERSIONS "1.8.x-1.14.4" #define MCS_PROTOCOL_VERSIONS "47, 107, 108, 109, 110, 210, 315, 316, 335, 338, 340, 393, 401, 477, 480, 485, 490, 498" #define MCS_LATEST_PROTOCOL_VERSION 498 /** Meta-protocol that recognizes multiple protocol versions, creates the specific protocol version instance and redirects everything to it. */ class cMultiVersionProtocol { public: cMultiVersionProtocol(); /** Translates protocol version number into protocol version text: 49 -> "1.4.4" */ static AString GetVersionTextFromInt(cProtocol::Version a_ProtocolVersion); /** Returns if we contain a concrete protocol corresponding to the client's protocol version. */ bool VersionRecognitionSuccessful() { return m_Protocol != nullptr; } /** Convenience overload to enable redirecting sends to the underlying implementation. */ auto & operator->() { return m_Protocol; } /** Directs incoming protocol data along the correct pathway, depending on the state of the version recognition process. The protocol modifies the provided buffer in-place. */ void HandleIncomingData(cClientHandle & a_Client, ContiguousByteBuffer & a_Data); /** Allows the protocol (if any) to do a final pass on outgiong data, possibly modifying the provided buffer in-place. */ void HandleOutgoingData(ContiguousByteBuffer & a_Data); /** Sends a disconnect to the client as a result of a recognition error. This function can be used to disconnect before any protocol has been recognised. */ void SendDisconnect(cClientHandle & a_Client, const AString & a_Reason); private: /** Handles data reception in a newly-created client handle that doesn't yet have a known protocol. a_Data contains a view of data that were just received. Tries to recognize a protocol, populate m_Protocol, and transitions to another mode depending on success. */ void HandleIncomingDataInRecognitionStage(cClientHandle & a_Client, ContiguousByteBuffer & a_Data); /** Handles and responds to unsupported clients sending pings. */ void HandleIncomingDataInOldPingResponseStage(cClientHandle & a_Client, ContiguousByteBufferView a_Data); /* Checks if incoming data is an HTTP request and handles it if it is. */ bool TryHandleHTTPRequest(cClientHandle & a_Client, ContiguousByteBuffer & a_Data); /** Tries to recognize a protocol in the lengthed family (1.7+), based on m_Buffer. Returns a cProtocol_XXX instance if recognized. */ std::unique_ptr TryRecognizeLengthedProtocol(cClientHandle & a_Client); /** Sends one packet inside a cByteBuffer. This is used only when handling an outdated server ping. */ static void SendPacket(cClientHandle & a_Client, cByteBuffer & a_OutPacketBuffer); /** Returns the protocol-specific packet ID given the protocol-agnostic packet enum. */ static UInt32 GetPacketID(cProtocol::ePacketType a_PacketType); /* Status handler for unrecognised versions. */ void HandlePacketStatusRequest(cClientHandle & a_Client); /* Ping handler for unrecognised versions. */ void HandlePacketStatusPing(cClientHandle & a_Client); /** Buffer for received protocol data. */ cByteBuffer m_Buffer; /** The actual protocol implementation. Created when recognition of the client version succeeds with a version we support. */ std::unique_ptr m_Protocol; /** If we're still waiting for data required for version recognition to arrive. */ bool m_WaitingForData; } ; ================================================ FILE: src/Protocol/Protocol_1_10.cpp ================================================ // Protocol_1_10.cpp /* Implements the 1.10 protocol classes: - cProtocol_1_10_0 - release 1.10 protocol (#210), also used by 1.10.1 and 1.10.2 */ #include "Globals.h" #include "Protocol_1_10.h" #include "Packetizer.h" #include "json/json.h" #include "../Root.h" #include "../Server.h" #include "../ClientHandle.h" #include "../JsonUtils.h" #include "../WorldStorage/FastNBT.h" #include "../Entities/Boat.h" #include "../Entities/EnderCrystal.h" #include "../Entities/ExpOrb.h" #include "../Entities/Minecart.h" #include "../Entities/FallingBlock.h" #include "../Entities/Painting.h" #include "../Entities/Pickup.h" #include "../Entities/Player.h" #include "../Entities/ItemFrame.h" #include "../Entities/ArrowEntity.h" #include "../Entities/FireworkEntity.h" #include "../Entities/SplashPotionEntity.h" #include "../Mobs/IncludeAllMonsters.h" #include "../BlockEntities/BannerEntity.h" #include "../BlockEntities/BeaconEntity.h" #include "../BlockEntities/CommandBlockEntity.h" #include "../BlockEntities/MobHeadEntity.h" #include "../BlockEntities/MobSpawnerEntity.h" #include "../BlockEntities/FlowerPotEntity.h" #include "../Bindings/PluginManager.h" // The disabled error is intended, since the Metadata have overlapping indexes // based on the type of the Entity. // // IMPORTANT: The enum is used to automate the sequential counting of the // Metadata indexes. Adding a new enum value causes the following values to // increase their index. Therefore the ordering of the enum values is VERY important! #ifdef __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wduplicate-enum" #endif namespace Metadata { enum Metadata_Index { // Entity ENTITY_FLAGS, ENTITY_AIR, ENTITY_CUSTOM_NAME, ENTITY_CUSTOM_NAME_VISIBLE, ENTITY_SILENT, ENTITY_NO_GRAVITY, _ENTITY_NEXT, // Used by descendants // Potion POTION_THROWN = _ENTITY_NEXT, // FallingBlock FALLING_BLOCK_POSITION = _ENTITY_NEXT, // AreaEffectCloud AREA_EFFECT_CLOUD_RADIUS = _ENTITY_NEXT, AREA_EFFECT_CLOUD_COLOR, AREA_EFFECT_CLOUD_SINGLE_POINT_EFFECT, AREA_EFFECT_CLOUD_PARTICLE_ID, AREA_EFFECT_CLOUD_PARTICLE_PARAMETER1, AREA_EFFECT_CLOUD_PARTICLE_PARAMETER2, // Arrow ARROW_CRITICAL = _ENTITY_NEXT, _ARROW_NEXT, // TippedArrow TIPPED_ARROW_COLOR = _ARROW_NEXT, // Boat BOAT_LAST_HIT_TIME = _ENTITY_NEXT, BOAT_FORWARD_DIRECTION, BOAT_DAMAGE_TAKEN, BOAT_TYPE, BOAT_RIGHT_PADDLE_TURNING, BOAT_LEFT_PADDLE_TURNING, // EnderCrystal ENDER_CRYSTAL_BEAM_TARGET = _ENTITY_NEXT, ENDER_CRYSTAL_SHOW_BOTTOM, // Fireball _FIREBALL_NEXT = _ENTITY_NEXT, // WitherSkull WITHER_SKULL_INVULNERABLE = _FIREBALL_NEXT, // Fireworks FIREWORK_INFO = _ENTITY_NEXT, // Hanging _HANGING_NEXT = _ENTITY_NEXT, // ItemFrame ITEM_FRAME_ITEM = _HANGING_NEXT, ITEM_FRAME_ROTATION, // Item ITEM_ITEM = _ENTITY_NEXT, // Living LIVING_ACTIVE_HAND = _ENTITY_NEXT, LIVING_HEALTH, LIVING_POTION_EFFECT_COLOR, LIVING_POTION_EFFECT_AMBIENT, LIVING_NUMBER_OF_ARROWS, _LIVING_NEXT, // Player PLAYER_ADDITIONAL_HEARTHS = _LIVING_NEXT, PLAYER_SCORE, PLAYER_DISPLAYED_SKIN_PARTS, PLAYER_MAIN_HAND, // ArmorStand ARMOR_STAND_STATUS = _LIVING_NEXT, ARMOR_STAND_HEAD_ROTATION, ARMOR_STAND_BODY_ROTATION, ARMOR_STAND_LEFT_ARM_ROTATION, ARMOR_STAND_RIGHT_ARM_ROTATION, ARMOR_STAND_LEFT_LEG_ROTATION, ARMOR_STAND_RIGHT_LEG_ROTATION, // Insentient INSENTIENT_STATUS = _LIVING_NEXT, _INSENTIENT_NEXT, // Ambient _AMBIENT_NEXT = _INSENTIENT_NEXT, // Bat BAT_HANGING = _AMBIENT_NEXT, // Creature _CREATURE_NEXT = _INSENTIENT_NEXT, // Ageable AGEABLE_BABY = _CREATURE_NEXT, _AGEABLE_NEXT, // PolarBear POLAR_BEAR_STANDING = _AGEABLE_NEXT, // Animal _ANIMAL_NEXT = _AGEABLE_NEXT, // Horse HORSE_STATUS = _ANIMAL_NEXT, HORSE_TYPE, HORSE_VARIANT, HORSE_OWNER, HORSE_ARMOR, // Pig PIG_HAS_SADDLE = _ANIMAL_NEXT, // Rabbit RABBIT_TYPE = _ANIMAL_NEXT, // Sheep SHEEP_STATUS = _ANIMAL_NEXT, // TameableAnimal TAMEABLE_ANIMAL_STATUS = _ANIMAL_NEXT, TAMEABLE_ANIMAL_OWNER, _TAMEABLE_NEXT, // Ocelot OCELOT_TYPE = _TAMEABLE_NEXT, // Wolf WOLF_DAMAGE_TAKEN = _TAMEABLE_NEXT, WOLF_BEGGING, WOLF_COLLAR_COLOR, // Villager VILLAGER_PROFESSION = _AGEABLE_NEXT, // Golem _GOLEM_NEXT = _CREATURE_NEXT, // IronGolem IRON_GOLEM_PLAYER_CREATED = _GOLEM_NEXT, // Shulker SHULKER_FACING_DIRECTION = _GOLEM_NEXT, SHULKER_ATTACHMENT_FALLING_BLOCK_POSITION, SHULKER_SHIELD_HEIGHT, // Monster _MONSTER_NEXT = _CREATURE_NEXT, // Blaze BLAZE_ON_FIRE = _MONSTER_NEXT, // Creeper CREEPER_STATE = _MONSTER_NEXT, CREEPER_POWERED, CREEPER_IGNITED, // Guardian GUARDIAN_STATUS = _MONSTER_NEXT, GUARDIAN_TARGET, // Skeleton SKELETON_TYPE = _MONSTER_NEXT, SKELETON_ARMS_SWINGING, // Spider SPIDER_CLIMBING = _MONSTER_NEXT, // Witch WITCH_AGGRESIVE = _MONSTER_NEXT, // Wither WITHER_FIRST_HEAD_TARGET = _MONSTER_NEXT, WITHER_SECOND_HEAD_TARGET, WITHER_THIRD_HEAD_TARGET, WITHER_INVULNERABLE_TIMER, // Zombie ZOMBIE_IS_BABY = _MONSTER_NEXT, ZOMBIE_TYPE, ZOMBIE_CONVERTING, ZOMBIE_HANDS_RISED_UP, // Enderman ENDERMAN_CARRIED_BLOCK = _MONSTER_NEXT, ENDERMAN_SCREAMING, // EnderDragon ENDER_DRAGON_DRAGON_PHASE = _INSENTIENT_NEXT, // Flying _FLYING_NEXT = _INSENTIENT_NEXT, // Ghast GHAST_ATTACKING = _FLYING_NEXT, // Slime SLIME_SIZE = _INSENTIENT_NEXT, // Minecart MINECART_SHAKING_POWER = _ENTITY_NEXT, MINECART_SHAKING_DIRECTION, MINECART_SHAKING_MULTIPLIER, MINECART_BLOCK_ID_META, MINECART_BLOCK_Y, MINECART_SHOW_BLOCK, _MINECART_NEXT, // MinecartCommandBlock MINECART_COMMAND_BLOCK_COMMAND = _MINECART_NEXT, MINECART_COMMAND_BLOCK_LAST_OUTPUT, // MinecartFurnace MINECART_FURNACE_POWERED = _MINECART_NEXT, // TNTPrimed TNT_PRIMED_FUSE_TIME = _ENTITY_NEXT, }; } #ifdef __clang__ #pragma clang diagnostic pop // Restore ignored clang errors #endif //////////////////////////////////////////////////////////////////////////////// // cProtocol_1_10_0: void cProtocol_1_10_0::SendSoundEffect(const AString & a_SoundName, Vector3d a_Origin, float a_Volume, float a_Pitch) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktSoundEffect); Pkt.WriteString(a_SoundName); Pkt.WriteVarInt32(0); // Master sound category (may want to be changed to a parameter later) Pkt.WriteBEInt32(FloorC(a_Origin.x * 8.0)); Pkt.WriteBEInt32(FloorC(a_Origin.y * 8.0)); Pkt.WriteBEInt32(FloorC(a_Origin.z * 8.0)); Pkt.WriteBEFloat(a_Volume); Pkt.WriteBEFloat(a_Pitch); } UInt32 cProtocol_1_10_0::GetProtocolMobType(const eMonsterType a_MobType) const { switch (a_MobType) { case mtPolarBear: return 102; default: return Super::GetProtocolMobType(a_MobType); } } cProtocol::Version cProtocol_1_10_0::GetProtocolVersion() const { return Version::v1_10_0; } void cProtocol_1_10_0::HandlePacketResourcePackStatus(cByteBuffer & a_ByteBuffer) { HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, Status); m_Client->HandleResourcePack(Status); } void cProtocol_1_10_0::WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_Entity) const { using namespace Metadata; // Common metadata: Int8 Flags = 0; if (a_Entity.IsOnFire()) { Flags |= 0x01; } if (a_Entity.IsCrouched()) { Flags |= 0x02; } if (a_Entity.IsSprinting()) { Flags |= 0x08; } if (a_Entity.IsRclking()) { Flags |= 0x10; } if (a_Entity.IsInvisible()) { Flags |= 0x20; } a_Pkt.WriteBEUInt8(ENTITY_FLAGS); // Index a_Pkt.WriteBEUInt8(METADATA_TYPE_BYTE); // Type a_Pkt.WriteBEInt8(Flags); switch (a_Entity.GetEntityType()) { case cEntity::etPlayer: { auto & Player = static_cast(a_Entity); // TODO Set player custom name to their name. // Then it's possible to move the custom name of mobs to the entities // and to remove the "special" player custom name. a_Pkt.WriteBEUInt8(ENTITY_CUSTOM_NAME); a_Pkt.WriteBEUInt8(METADATA_TYPE_STRING); a_Pkt.WriteString(Player.GetName()); a_Pkt.WriteBEUInt8(LIVING_HEALTH); a_Pkt.WriteBEUInt8(METADATA_TYPE_FLOAT); a_Pkt.WriteBEFloat(static_cast(Player.GetHealth())); a_Pkt.WriteBEUInt8(PLAYER_DISPLAYED_SKIN_PARTS); a_Pkt.WriteBEUInt8(METADATA_TYPE_BYTE); a_Pkt.WriteBEUInt8(static_cast(Player.GetSkinParts())); a_Pkt.WriteBEUInt8(PLAYER_MAIN_HAND); a_Pkt.WriteBEUInt8(METADATA_TYPE_BYTE); a_Pkt.WriteBEUInt8(Player.IsLeftHanded() ? 0 : 1); break; } case cEntity::etPickup: { a_Pkt.WriteBEUInt8(ITEM_ITEM); a_Pkt.WriteBEUInt8(METADATA_TYPE_ITEM); WriteItem(a_Pkt, static_cast(a_Entity).GetItem()); break; } case cEntity::etMinecart: { a_Pkt.WriteBEUInt8(MINECART_SHAKING_POWER); a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); // The following expression makes Minecarts shake more with less health or higher damage taken auto & Minecart = static_cast(a_Entity); auto maxHealth = a_Entity.GetMaxHealth(); auto curHealth = a_Entity.GetHealth(); a_Pkt.WriteVarInt32(static_cast((maxHealth - curHealth) * Minecart.LastDamage() * 4)); a_Pkt.WriteBEUInt8(MINECART_SHAKING_DIRECTION); // (doesn't seem to effect anything) a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(1); a_Pkt.WriteBEUInt8(MINECART_SHAKING_MULTIPLIER); // or damage taken a_Pkt.WriteBEUInt8(METADATA_TYPE_FLOAT); a_Pkt.WriteBEFloat(static_cast(Minecart.LastDamage() + 10)); if (Minecart.GetPayload() == cMinecart::mpNone) { auto & RideableMinecart = static_cast(Minecart); const cItem & MinecartContent = RideableMinecart.GetContent(); if (!MinecartContent.IsEmpty()) { a_Pkt.WriteBEUInt8(MINECART_BLOCK_ID_META); a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); int Content = MinecartContent.m_ItemType; Content |= MinecartContent.m_ItemDamage << 8; a_Pkt.WriteVarInt32(static_cast(Content)); a_Pkt.WriteBEUInt8(MINECART_BLOCK_Y); a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(static_cast(RideableMinecart.GetBlockHeight())); a_Pkt.WriteBEUInt8(MINECART_SHOW_BLOCK); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(true); } } else if (Minecart.GetPayload() == cMinecart::mpFurnace) { a_Pkt.WriteBEUInt8(MINECART_FURNACE_POWERED); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(static_cast(Minecart).IsFueled()); } break; } // case etMinecart case cEntity::etProjectile: { auto & Projectile = static_cast(a_Entity); switch (Projectile.GetProjectileKind()) { case cProjectileEntity::pkArrow: { a_Pkt.WriteBEUInt8(ARROW_CRITICAL); a_Pkt.WriteBEUInt8(METADATA_TYPE_BYTE); a_Pkt.WriteBEInt8(static_cast(Projectile).IsCritical() ? 1 : 0); break; } case cProjectileEntity::pkFirework: { a_Pkt.WriteBEUInt8(FIREWORK_INFO); // Firework item used for this firework a_Pkt.WriteBEUInt8(METADATA_TYPE_ITEM); WriteItem(a_Pkt, static_cast(Projectile).GetItem()); break; } case cProjectileEntity::pkSplashPotion: { a_Pkt.WriteBEUInt8(POTION_THROWN); // Potion item which was thrown a_Pkt.WriteBEUInt8(METADATA_TYPE_ITEM); WriteItem(a_Pkt, static_cast(Projectile).GetItem()); } default: { break; } } break; } // case etProjectile case cEntity::etMonster: { WriteMobMetadata(a_Pkt, static_cast(a_Entity)); break; } case cEntity::etBoat: { auto & Boat = static_cast(a_Entity); a_Pkt.WriteBEInt8(BOAT_LAST_HIT_TIME); a_Pkt.WriteBEInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(static_cast(Boat.GetLastDamage())); a_Pkt.WriteBEInt8(BOAT_FORWARD_DIRECTION); a_Pkt.WriteBEInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(static_cast(Boat.GetForwardDirection())); a_Pkt.WriteBEInt8(BOAT_DAMAGE_TAKEN); a_Pkt.WriteBEInt8(METADATA_TYPE_FLOAT); a_Pkt.WriteBEFloat(Boat.GetDamageTaken()); a_Pkt.WriteBEInt8(BOAT_TYPE); a_Pkt.WriteBEInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(static_cast(Boat.GetMaterial())); a_Pkt.WriteBEInt8(BOAT_RIGHT_PADDLE_TURNING); a_Pkt.WriteBEInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Boat.IsRightPaddleUsed()); a_Pkt.WriteBEInt8(BOAT_LEFT_PADDLE_TURNING); a_Pkt.WriteBEInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Boat.IsLeftPaddleUsed()); break; } // case etBoat case cEntity::etItemFrame: { auto & Frame = static_cast(a_Entity); a_Pkt.WriteBEUInt8(ITEM_FRAME_ITEM); a_Pkt.WriteBEUInt8(METADATA_TYPE_ITEM); WriteItem(a_Pkt, Frame.GetItem()); a_Pkt.WriteBEUInt8(ITEM_FRAME_ROTATION); a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(Frame.GetItemRotation()); break; } // case etItemFrame case cEntity::etEnderCrystal: { const auto & EnderCrystal = static_cast(a_Entity); a_Pkt.WriteBEUInt8(ENDER_CRYSTAL_BEAM_TARGET); a_Pkt.WriteBEUInt8(METADATA_TYPE_OPTIONAL_POSITION); a_Pkt.WriteBool(EnderCrystal.DisplaysBeam()); if (EnderCrystal.DisplaysBeam()) { a_Pkt.WriteXYZPosition64(EnderCrystal.GetBeamTarget()); } a_Pkt.WriteBEUInt8(ENDER_CRYSTAL_SHOW_BOTTOM); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(EnderCrystal.ShowsBottom()); break; } // case etEnderCrystal default: { break; } } } void cProtocol_1_10_0::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mob) const { using namespace Metadata; // Living entity metadata if (a_Mob.HasCustomName()) { // TODO: As of 1.9 _all_ entities can have custom names; should this be moved up? a_Pkt.WriteBEUInt8(ENTITY_CUSTOM_NAME); a_Pkt.WriteBEUInt8(METADATA_TYPE_STRING); a_Pkt.WriteString(a_Mob.GetCustomName()); a_Pkt.WriteBEUInt8(ENTITY_CUSTOM_NAME_VISIBLE); // Custom name always visible a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(a_Mob.IsCustomNameAlwaysVisible()); } a_Pkt.WriteBEUInt8(LIVING_HEALTH); a_Pkt.WriteBEUInt8(METADATA_TYPE_FLOAT); a_Pkt.WriteBEFloat(static_cast(a_Mob.GetHealth())); switch (a_Mob.GetMobType()) { case mtBat: { auto & Bat = static_cast(a_Mob); a_Pkt.WriteBEUInt8(BAT_HANGING); a_Pkt.WriteBEUInt8(METADATA_TYPE_BYTE); a_Pkt.WriteBEInt8(Bat.IsHanging() ? 1 : 0); break; } // case mtBat case mtChicken: { auto & Chicken = static_cast(a_Mob); a_Pkt.WriteBEUInt8(AGEABLE_BABY); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Chicken.IsBaby()); break; } // case mtChicken case mtCow: { auto & Cow = static_cast(a_Mob); a_Pkt.WriteBEUInt8(AGEABLE_BABY); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Cow.IsBaby()); break; } // case mtCow case mtCreeper: { auto & Creeper = static_cast(a_Mob); a_Pkt.WriteBEUInt8(CREEPER_STATE); // (idle or "blowing") a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(Creeper.IsBlowing() ? 1 : static_cast(-1)); a_Pkt.WriteBEUInt8(CREEPER_POWERED); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Creeper.IsCharged()); a_Pkt.WriteBEUInt8(CREEPER_IGNITED); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Creeper.IsBurnedWithFlintAndSteel()); break; } // case mtCreeper case mtEnderman: { auto & Enderman = static_cast(a_Mob); a_Pkt.WriteBEUInt8(ENDERMAN_CARRIED_BLOCK); a_Pkt.WriteBEUInt8(METADATA_TYPE_BLOCKID); UInt32 Carried = 0; Carried |= static_cast(Enderman.GetCarriedBlock() << 4); Carried |= Enderman.GetCarriedMeta(); a_Pkt.WriteVarInt32(Carried); a_Pkt.WriteBEUInt8(ENDERMAN_SCREAMING); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Enderman.IsScreaming()); break; } // case mtEnderman case mtGhast: { auto & Ghast = static_cast(a_Mob); a_Pkt.WriteBEUInt8(GHAST_ATTACKING); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Ghast.IsCharging()); break; } // case mtGhast case mtHorse: { auto & Horse = static_cast(a_Mob); Int8 Flags = 0; if (Horse.IsTame()) { Flags |= 0x02; } if (Horse.IsSaddled()) { Flags |= 0x04; } if (Horse.IsChested()) { Flags |= 0x08; } if (Horse.IsEating()) { Flags |= 0x20; } if (Horse.IsRearing()) { Flags |= 0x40; } if (Horse.IsMthOpen()) { Flags |= 0x80; } a_Pkt.WriteBEUInt8(HORSE_STATUS); a_Pkt.WriteBEUInt8(METADATA_TYPE_BYTE); a_Pkt.WriteBEInt8(Flags); a_Pkt.WriteBEUInt8(HORSE_TYPE); a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(static_cast(Horse.GetHorseType())); a_Pkt.WriteBEUInt8(HORSE_VARIANT); // Color / style a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); int Appearance = 0; Appearance = Horse.GetHorseColor(); Appearance |= Horse.GetHorseStyle() << 8; a_Pkt.WriteVarInt32(static_cast(Appearance)); a_Pkt.WriteBEUInt8(HORSE_ARMOR); a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(static_cast(Horse.GetHorseArmour())); a_Pkt.WriteBEUInt8(AGEABLE_BABY); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Horse.IsBaby()); break; } // case mtHorse case mtMagmaCube: { auto & MagmaCube = static_cast(a_Mob); a_Pkt.WriteBEUInt8(SLIME_SIZE); a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(static_cast(MagmaCube.GetSize())); break; } // case mtMagmaCube case mtOcelot: { auto & Ocelot = static_cast(a_Mob); a_Pkt.WriteBEUInt8(AGEABLE_BABY); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Ocelot.IsBaby()); break; } // case mtOcelot case mtPig: { auto & Pig = static_cast(a_Mob); a_Pkt.WriteBEUInt8(AGEABLE_BABY); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Pig.IsBaby()); a_Pkt.WriteBEUInt8(PIG_HAS_SADDLE); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Pig.IsSaddled()); break; } // case mtPig case mtRabbit: { auto & Rabbit = static_cast(a_Mob); a_Pkt.WriteBEUInt8(AGEABLE_BABY); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Rabbit.IsBaby()); a_Pkt.WriteBEUInt8(RABBIT_TYPE); a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(static_cast(Rabbit.GetRabbitType())); break; } // case mtRabbit case mtSheep: { auto & Sheep = static_cast(a_Mob); a_Pkt.WriteBEUInt8(AGEABLE_BABY); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Sheep.IsBaby()); a_Pkt.WriteBEUInt8(SHEEP_STATUS); a_Pkt.WriteBEUInt8(METADATA_TYPE_BYTE); Int8 SheepMetadata = 0; SheepMetadata = static_cast(Sheep.GetFurColor()); if (Sheep.IsSheared()) { SheepMetadata |= 0x10; } a_Pkt.WriteBEInt8(SheepMetadata); break; } // case mtSheep case mtSkeleton: { auto & Skeleton = static_cast(a_Mob); a_Pkt.WriteBEUInt8(LIVING_ACTIVE_HAND); a_Pkt.WriteBEUInt8(METADATA_TYPE_BYTE); a_Pkt.WriteBEUInt8(Skeleton.IsChargingBow() ? 0x01 : 0x00); a_Pkt.WriteBEUInt8(SKELETON_ARMS_SWINGING); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Skeleton.IsChargingBow()); break; } // case mtSkeleton case mtSlime: { auto & Slime = static_cast(a_Mob); a_Pkt.WriteBEUInt8(SLIME_SIZE); a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(static_cast(Slime.GetSize())); break; } // case mtSlime case mtVillager: { auto & Villager = static_cast(a_Mob); a_Pkt.WriteBEUInt8(AGEABLE_BABY); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Villager.IsBaby()); a_Pkt.WriteBEUInt8(VILLAGER_PROFESSION); a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(static_cast(Villager.GetVilType())); break; } // case mtVillager case mtWitch: { auto & Witch = static_cast(a_Mob); a_Pkt.WriteBEUInt8(WITCH_AGGRESIVE); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Witch.IsAngry()); break; } // case mtWitch case mtWither: { auto & Wither = static_cast(a_Mob); a_Pkt.WriteBEUInt8(WITHER_INVULNERABLE_TIMER); a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(Wither.GetWitherInvulnerableTicks()); // TODO: Use boss bar packet for health break; } // case mtWither case mtWitherSkeleton: { a_Pkt.WriteBEUInt8(SKELETON_TYPE); a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(1); // Is wither skeleton break; } // case mtWitherSkeleton case mtWolf: { auto & Wolf = static_cast(a_Mob); a_Pkt.WriteBEUInt8(AGEABLE_BABY); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Wolf.IsBaby()); Int8 WolfStatus = 0; if (Wolf.IsSitting()) { WolfStatus |= 0x1; } if (Wolf.IsAngry()) { WolfStatus |= 0x2; } if (Wolf.IsTame()) { WolfStatus |= 0x4; } a_Pkt.WriteBEUInt8(TAMEABLE_ANIMAL_STATUS); a_Pkt.WriteBEUInt8(METADATA_TYPE_BYTE); a_Pkt.WriteBEInt8(WolfStatus); a_Pkt.WriteBEUInt8(WOLF_DAMAGE_TAKEN); a_Pkt.WriteBEUInt8(METADATA_TYPE_FLOAT); a_Pkt.WriteBEFloat(static_cast(a_Mob.GetHealth())); // TODO Not use the current health a_Pkt.WriteBEUInt8(WOLF_BEGGING); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Wolf.IsBegging()); a_Pkt.WriteBEUInt8(WOLF_COLLAR_COLOR); a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(static_cast(Wolf.GetCollarColor())); break; } // case mtWolf case mtHusk: case mtZombie: { auto & Zombie = static_cast(a_Mob); a_Pkt.WriteBEUInt8(ZOMBIE_IS_BABY); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Zombie.IsBaby()); a_Pkt.WriteBEUInt8(ZOMBIE_TYPE); a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(0); a_Pkt.WriteBEUInt8(ZOMBIE_CONVERTING); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(false); break; } // case mtZombie case mtZombiePigman: { auto & ZombiePigman = static_cast(a_Mob); a_Pkt.WriteBEUInt8(AGEABLE_BABY); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(ZombiePigman.IsBaby()); break; } // case mtZombiePigman case mtZombieVillager: { auto & ZombieVillager = reinterpret_cast(a_Mob); a_Pkt.WriteBEUInt8(ZOMBIE_IS_BABY); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(ZombieVillager.IsBaby()); a_Pkt.WriteBEUInt8(ZOMBIE_TYPE); a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(ZombieVillager.GetProfession()); a_Pkt.WriteBEUInt8(ZOMBIE_CONVERTING); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(ZombieVillager.ConversionTime() != -1); break; } // case mtZombieVillager case mtBlaze: case mtElderGuardian: case mtGuardian: { // TODO: Mobs with extra fields that aren't implemented break; } case mtCat: case mtPolarBear: case mtShulker: case mtDonkey: case mtMule: case mtSkeletonHorse: case mtZombieHorse: { // Todo: Mobs not added yet. Grouped ones have the same metadata ASSERT(!"cProtocol_1_10::WriteMobMetadata: received unimplemented type"); break; } case mtCaveSpider: case mtEnderDragon: case mtEndermite: case mtGiant: case mtIronGolem: case mtMooshroom: case mtSilverfish: case mtSnowGolem: case mtStray: case mtSpider: case mtSquid: { // Entities without additional metadata break; } default: UNREACHABLE("cProtocol_1_10::WriteMobMetadata: received mob of invalid type"); } // switch (a_Mob.GetType()) } ================================================ FILE: src/Protocol/Protocol_1_10.h ================================================ // Protocol_1_10.h /* Declares the 1.10 protocol classes: - cProtocol_1_10 - release 1.10 protocol (#210), also used by 1.10.1 and 1.10.2 */ #pragma once #include "Protocol_1_9.h" class cProtocol_1_10_0: public cProtocol_1_9_4 { using Super = cProtocol_1_9_4; public: using Super::Super; protected: virtual void SendSoundEffect(const AString & a_SoundName, Vector3d a_Origin, float a_Volume, float a_Pitch) override; virtual UInt32 GetProtocolMobType(eMonsterType a_MobType) const override; virtual Version GetProtocolVersion() const override; virtual void HandlePacketResourcePackStatus(cByteBuffer & a_ByteBuffer) override; virtual void WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_Entity) const override; virtual void WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mob) const override; }; ================================================ FILE: src/Protocol/Protocol_1_11.cpp ================================================ // Protocol_1_11.cpp /* Implements the 1.11 protocol classes: - cProtocol_1_11_0 - release 1.11 protocol (#315) - cProtocol_1_11_1 - release 1.11.1 protocol (#316) */ #include "Globals.h" #include "Protocol_1_11.h" #include "Packetizer.h" #include "../WorldStorage/FastNBT.h" #include "../Entities/Boat.h" #include "../Entities/EnderCrystal.h" #include "../Entities/ExpOrb.h" #include "../Entities/Minecart.h" #include "../Entities/FallingBlock.h" #include "../Entities/Painting.h" #include "../Entities/Pickup.h" #include "../Entities/Player.h" #include "../Entities/ItemFrame.h" #include "../Entities/ArrowEntity.h" #include "../Entities/FireworkEntity.h" #include "../Entities/SplashPotionEntity.h" #include "../Mobs/IncludeAllMonsters.h" #include "../BlockEntities/BedEntity.h" #include "../BlockEntities/MobSpawnerEntity.h" #include "../Root.h" #include "../Server.h" #include "../ClientHandle.h" #include "../CompositeChat.h" #include "../JsonUtils.h" #include "../Bindings/PluginManager.h" // The disabled error is intended, since the Metadata have overlapping indexes // based on the type of the Entity. // // IMPORTANT: The enum is used to automate the sequential counting of the // Metadata indexes. Adding a new enum value causes the following values to // increase their index. Therefore the ordering of the enum values is VERY important! #ifdef __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wduplicate-enum" #endif namespace Metadata_1_11 { enum MetadataIndex { // Entity ENTITY_FLAGS, ENTITY_AIR, ENTITY_CUSTOM_NAME, ENTITY_CUSTOM_NAME_VISIBLE, ENTITY_SILENT, ENTITY_NO_GRAVITY, _ENTITY_NEXT, // Used by descendants // Potion POTION_THROWN = _ENTITY_NEXT, // FallingBlock FALLING_BLOCK_POSITION = _ENTITY_NEXT, // AreaEffectCloud AREA_EFFECT_CLOUD_RADIUS = _ENTITY_NEXT, AREA_EFFECT_CLOUD_COLOR, AREA_EFFECT_CLOUD_SINGLE_POINT_EFFECT, AREA_EFFECT_CLOUD_PARTICLE_ID, AREA_EFFECT_CLOUD_PARTICLE_PARAMETER1, AREA_EFFECT_CLOUD_PARTICLE_PARAMETER2, // Arrow ARROW_CRITICAL = _ENTITY_NEXT, _ARROW_NEXT, // TippedArrow TIPPED_ARROW_COLOR = _ARROW_NEXT, // Boat BOAT_LAST_HIT_TIME = _ENTITY_NEXT, BOAT_FORWARD_DIRECTION, BOAT_DAMAGE_TAKEN, BOAT_TYPE, BOAT_RIGHT_PADDLE_TURNING, BOAT_LEFT_PADDLE_TURNING, // EnderCrystal ENDER_CRYSTAL_BEAM_TARGET = _ENTITY_NEXT, ENDER_CRYSTAL_SHOW_BOTTOM, // Fireball _FIREBALL_NEXT = _ENTITY_NEXT, // WitherSkull WITHER_SKULL_INVULNERABLE = _FIREBALL_NEXT, // Fireworks FIREWORK_INFO = _ENTITY_NEXT, FIREWORK_BOOSTED_ENTITY_ID, // 1.11.1 only // Hanging _HANGING_NEXT = _ENTITY_NEXT, // ItemFrame ITEM_FRAME_ITEM = _HANGING_NEXT, ITEM_FRAME_ROTATION, // Item ITEM_ITEM = _ENTITY_NEXT, // Living LIVING_ACTIVE_HAND = _ENTITY_NEXT, LIVING_HEALTH, LIVING_POTION_EFFECT_COLOR, LIVING_POTION_EFFECT_AMBIENT, LIVING_NUMBER_OF_ARROWS, _LIVING_NEXT, // Player PLAYER_ADDITIONAL_HEARTHS = _LIVING_NEXT, PLAYER_SCORE, PLAYER_DISPLAYED_SKIN_PARTS, PLAYER_MAIN_HAND, // ArmorStand ARMOR_STAND_STATUS = _LIVING_NEXT, ARMOR_STAND_HEAD_ROTATION, ARMOR_STAND_BODY_ROTATION, ARMOR_STAND_LEFT_ARM_ROTATION, ARMOR_STAND_RIGHT_ARM_ROTATION, ARMOR_STAND_LEFT_LEG_ROTATION, ARMOR_STAND_RIGHT_LEG_ROTATION, // Insentient INSENTIENT_STATUS = _LIVING_NEXT, _INSENTIENT_NEXT, // Ambient _AMBIENT_NEXT = _INSENTIENT_NEXT, // Bat BAT_HANGING = _AMBIENT_NEXT, // Creature _CREATURE_NEXT = _INSENTIENT_NEXT, // Ageable AGEABLE_BABY = _CREATURE_NEXT, _AGEABLE_NEXT, // PolarBear POLAR_BEAR_STANDING = _AGEABLE_NEXT, // Animal _ANIMAL_NEXT = _AGEABLE_NEXT, // Abstract horse ABSTRACT_HORSE_STATUS = _ANIMAL_NEXT, ABSTRACT_HORSE_OWNER, _ABSTRACT_HORSE_NEXT, // Horse HORSE_VARIANT = _ABSTRACT_HORSE_NEXT, HORSE_ARMOR, // Chested horse CHESTED_HORSE_CHESTED = _ABSTRACT_HORSE_NEXT, _CHESTED_HORSE_NEXT, // Llama LLAMA_STRENGTH = _CHESTED_HORSE_NEXT, LLAMA_CARPET_COLOR, LLAMA_VARIANT, // Pig PIG_HAS_SADDLE = _ANIMAL_NEXT, PIG_TOTAL_CARROT_ON_A_STICK_BOOST, // 1.11.1 only // Rabbit RABBIT_TYPE = _ANIMAL_NEXT, // Sheep SHEEP_STATUS = _ANIMAL_NEXT, // TameableAnimal TAMEABLE_ANIMAL_STATUS = _ANIMAL_NEXT, TAMEABLE_ANIMAL_OWNER, _TAMEABLE_NEXT, // Ocelot OCELOT_TYPE = _TAMEABLE_NEXT, // Wolf WOLF_DAMAGE_TAKEN = _TAMEABLE_NEXT, WOLF_BEGGING, WOLF_COLLAR_COLOR, // Villager VILLAGER_PROFESSION = _AGEABLE_NEXT, // Golem _GOLEM_NEXT = _CREATURE_NEXT, // IronGolem IRON_GOLEM_PLAYER_CREATED = _GOLEM_NEXT, // Shulker SHULKER_FACING_DIRECTION = _GOLEM_NEXT, SHULKER_ATTACHMENT_FALLING_BLOCK_POSITION, SHULKER_SHIELD_HEIGHT, // Monster _MONSTER_NEXT = _CREATURE_NEXT, // Blaze BLAZE_ON_FIRE = _MONSTER_NEXT, // Creeper CREEPER_STATE = _MONSTER_NEXT, CREEPER_POWERED, CREEPER_IGNITED, // Guardian GUARDIAN_STATUS = _MONSTER_NEXT, GUARDIAN_TARGET, // Abstract Skeleton ABSTRACT_SKELETON_ARMS_SWINGING = _MONSTER_NEXT, // Spider SPIDER_CLIMBING = _MONSTER_NEXT, // Witch WITCH_AGGRESIVE = _MONSTER_NEXT, // Wither WITHER_FIRST_HEAD_TARGET = _MONSTER_NEXT, WITHER_SECOND_HEAD_TARGET, WITHER_THIRD_HEAD_TARGET, WITHER_INVULNERABLE_TIMER, // Zombie ZOMBIE_IS_BABY = _MONSTER_NEXT, ZOMBIE_UNUSED, // Was type ZOMBIE_HANDS_RISED_UP, _ZOMBIE_NEXT, // Zombie villager ZOMBIE_VILLAGER_CONVERTING = _ZOMBIE_NEXT, ZOMBIE_VILLAGER_PROFESSION, // Enderman ENDERMAN_CARRIED_BLOCK = _MONSTER_NEXT, ENDERMAN_SCREAMING, // Evocation illager EVOKER_SPELL = _MONSTER_NEXT, // Vex VEX_FLAGS = _MONSTER_NEXT, // Vindication illager VINDICATOR_FLAGS = _MONSTER_NEXT, // EnderDragon ENDER_DRAGON_DRAGON_PHASE = _INSENTIENT_NEXT, // Flying _FLYING_NEXT = _INSENTIENT_NEXT, // Ghast GHAST_ATTACKING = _FLYING_NEXT, // Slime SLIME_SIZE = _INSENTIENT_NEXT, // Minecart MINECART_SHAKING_POWER = _ENTITY_NEXT, MINECART_SHAKING_DIRECTION, MINECART_SHAKING_MULTIPLIER, MINECART_BLOCK_ID_META, MINECART_BLOCK_Y, MINECART_SHOW_BLOCK, _MINECART_NEXT, // MinecartCommandBlock MINECART_COMMAND_BLOCK_COMMAND = _MINECART_NEXT, MINECART_COMMAND_BLOCK_LAST_OUTPUT, // MinecartFurnace MINECART_FURNACE_POWERED = _MINECART_NEXT, // TNTPrimed TNT_PRIMED_FUSE_TIME = _ENTITY_NEXT, }; } #ifdef __clang__ #pragma clang diagnostic pop // Restore ignored clang errors #endif //////////////////////////////////////////////////////////////////////////////// // cProtocol_1_11_0: void cProtocol_1_11_0::SendCollectEntity(const cEntity & a_Collected, const cEntity & a_Collector, unsigned a_Count) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktCollectEntity); Pkt.WriteVarInt32(a_Collected.GetUniqueID()); Pkt.WriteVarInt32(a_Collector.GetUniqueID()); Pkt.WriteVarInt32(static_cast(a_Count)); } void cProtocol_1_11_0::SendEntityAnimation(const cEntity & a_Entity, const EntityAnimation a_Animation) { switch (a_Animation) { case EntityAnimation::EggCracks: case EntityAnimation::SnowballPoofs: { // Vanilla stopped doing clientside prediction for thrown projectile particle effects (for some reason). // But they're still doing motion prediction, and latency exists, hence re-send the server position to avoid particle effects happening inside a block: SendEntityPosition(a_Entity); break; } case EntityAnimation::PawnChestEquipmentBreaks: case EntityAnimation::PawnFeetEquipmentBreaks: case EntityAnimation::PawnHeadEquipmentBreaks: case EntityAnimation::PawnLegsEquipmentBreaks: case EntityAnimation::PawnMainHandEquipmentBreaks: case EntityAnimation::PawnOffHandEquipmentBreaks: { const auto Position = a_Entity.GetPosition(); // 1.11 dropped the automatic particle effect + sound on item break. Emulate at least some of it: SendSoundEffect("entity.item.break", Position, 1, 0.75f + ((a_Entity.GetUniqueID() * 23) % 32) / 64.f); break; } default: break; } Super::SendEntityAnimation(a_Entity, a_Animation); } void cProtocol_1_11_0::SendHideTitle(void) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktTitle); Pkt.WriteVarInt32(4); // Hide title } void cProtocol_1_11_0::SendResetTitle(void) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktTitle); Pkt.WriteVarInt32(5); // Reset title } void cProtocol_1_11_0::SendSpawnMob(const cMonster & a_Mob) { ASSERT(m_State == 3); // In game mode? const auto MobType = GetProtocolMobType(a_Mob.GetMobType()); // If the type is not valid in this protocol bail out: if (MobType == 0) { return; } cPacketizer Pkt(*this, pktSpawnMob); Pkt.WriteVarInt32(a_Mob.GetUniqueID()); // TODO: Bad way to write a UUID, and it's not a true UUID, but this is functional for now. Pkt.WriteBEUInt64(0); Pkt.WriteBEUInt64(a_Mob.GetUniqueID()); Pkt.WriteVarInt32(MobType); Vector3d LastSentPos = a_Mob.GetLastSentPosition(); Pkt.WriteBEDouble(LastSentPos.x); Pkt.WriteBEDouble(LastSentPos.y); Pkt.WriteBEDouble(LastSentPos.z); Pkt.WriteByteAngle(a_Mob.GetHeadYaw()); // Doesn't seem to be used Pkt.WriteByteAngle(a_Mob.GetPitch()); Pkt.WriteByteAngle(a_Mob.GetYaw()); Pkt.WriteBEInt16(static_cast(a_Mob.GetSpeedX() * 400)); Pkt.WriteBEInt16(static_cast(a_Mob.GetSpeedY() * 400)); Pkt.WriteBEInt16(static_cast(a_Mob.GetSpeedZ() * 400)); WriteEntityMetadata(Pkt, a_Mob); Pkt.WriteBEUInt8(0xff); // Metadata terminator } void cProtocol_1_11_0::SendTitleTimes(int a_FadeInTicks, int a_DisplayTicks, int a_FadeOutTicks) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktTitle); Pkt.WriteVarInt32(3); // Set title display times Pkt.WriteBEInt32(a_FadeInTicks); Pkt.WriteBEInt32(a_DisplayTicks); Pkt.WriteBEInt32(a_FadeOutTicks); } void cProtocol_1_11_0::SendUpdateBlockEntity(cBlockEntity & a_BlockEntity) { ASSERT(m_State == 3); // In game mode? Byte Action; switch (a_BlockEntity.GetBlockType()) { case E_BLOCK_CHEST: case E_BLOCK_ENCHANTMENT_TABLE: case E_BLOCK_END_PORTAL: case E_BLOCK_TRAPPED_CHEST: { // The ones with a action of 0 is just a workaround to send the block entities to a client. // Todo: 18.09.2020 - remove this when block entities are transmitted in the ChunkData packet - 12xx12 Action = 0; break; } case E_BLOCK_MOB_SPAWNER: Action = 1; break; // Update mob spawner spinny mob thing case E_BLOCK_COMMAND_BLOCK: Action = 2; break; // Update command block text case E_BLOCK_BEACON: Action = 3; break; // Update beacon entity case E_BLOCK_HEAD: Action = 4; break; // Update mobhead entity case E_BLOCK_FLOWER_POT: Action = 5; break; // Update flower pot case E_BLOCK_WALL_BANNER: case E_BLOCK_STANDING_BANNER: Action = 6; break; // Update banner case E_BLOCK_BED: Action = 11; break; // Update bed color (new!) default: return; // Block entities change between versions } cPacketizer Pkt(*this, pktUpdateBlockEntity); Pkt.WriteXYZPosition64(a_BlockEntity.GetPosX(), a_BlockEntity.GetPosY(), a_BlockEntity.GetPosZ()); Pkt.WriteBEUInt8(Action); cFastNBTWriter Writer; WriteBlockEntity(Writer, a_BlockEntity); Writer.Finish(); Pkt.WriteBuf(Writer.GetResult()); } signed char cProtocol_1_11_0::GetProtocolEntityStatus(const EntityAnimation a_Animation) const { switch (a_Animation) { case EntityAnimation::EggCracks: return 3; case EntityAnimation::EvokerFangsAttacks: return 4; case EntityAnimation::IronGolemStashesGift: return 34; case EntityAnimation::PawnTotemActivates: return 35; case EntityAnimation::SnowballPoofs: return 3; default: return Super::GetProtocolEntityStatus(a_Animation); } } UInt32 cProtocol_1_11_0::GetProtocolMobType(const eMonsterType a_MobType) const { switch (a_MobType) { // Map invalid type to Giant for easy debugging (if this ever spawns, something has gone very wrong) case mtInvalidType: return 53; case mtBat: return 65; case mtBlaze: return 61; case mtCaveSpider: return 59; case mtChicken: return 93; case mtCow: return 92; case mtCreeper: return 50; case mtDonkey: return 31; case mtEnderDragon: return 63; case mtEnderman: return 58; case mtEndermite: return 67; case mtEvoker: return 34; case mtGhast: return 56; case mtGiant: return 53; case mtGuardian: return 68; case mtHorse: return 100; case mtHusk: return 23; case mtIronGolem: return 99; case mtLlama: return 103; case mtMagmaCube: return 62; case mtMooshroom: return 96; case mtMule: return 32; case mtOcelot: return 98; case mtPig: return 90; case mtPolarBear: return 102; case mtRabbit: return 101; case mtSheep: return 91; case mtShulker: return 69; case mtSilverfish: return 60; case mtSkeleton: return 51; case mtSlime: return 55; case mtSnowGolem: return 97; case mtSpider: return 52; case mtStray: return 6; case mtTraderLlama: return 103; case mtSquid: return 94; case mtVex: return 35; case mtVillager: return 120; case mtVindicator: return 36; case mtWitch: return 66; case mtWither: return 64; case mtWitherSkeleton: return 5; case mtWolf: return 95; case mtZombie: return 54; case mtZombiePigman: return 57; case mtZombieVillager: return 27; default: return 0; } } cProtocol::Version cProtocol_1_11_0::GetProtocolVersion() const { return Version::v1_11_0; } void cProtocol_1_11_0::HandlePacketBlockPlace(cByteBuffer & a_ByteBuffer) { Vector3i Position; if (!a_ByteBuffer.ReadXYZPosition64(Position)) { return; } HANDLE_READ(a_ByteBuffer, ReadVarInt, Int32, Face); HANDLE_READ(a_ByteBuffer, ReadVarInt, Int32, Hand); HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, CursorX); HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, CursorY); HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, CursorZ); m_Client->HandleRightClick(Position, FaceIntToBlockFace(Face), {FloorC(CursorX * 16), FloorC(CursorY * 16), FloorC(CursorZ * 16)}, Hand == 0); } void cProtocol_1_11_0::WriteBlockEntity(cFastNBTWriter & a_Writer, const cBlockEntity & a_BlockEntity) const { switch (a_BlockEntity.GetBlockType()) { case E_BLOCK_BED: { auto & BedEntity = static_cast(a_BlockEntity); a_Writer.AddInt("color", BedEntity.GetColor()); // New: multicoloured beds break; } case E_BLOCK_MOB_SPAWNER: { auto & MobSpawnerEntity = static_cast(a_BlockEntity); a_Writer.BeginCompound("SpawnData"); a_Writer.AddString("id", cMonster::MobTypeToVanillaNBT(MobSpawnerEntity.GetEntity())); // New: uses namespaced ID a_Writer.EndCompound(); a_Writer.AddShort("Delay", MobSpawnerEntity.GetSpawnDelay()); break; } default: return Super::WriteBlockEntity(a_Writer, a_BlockEntity); } a_Writer.AddInt("x", a_BlockEntity.GetPosX()); a_Writer.AddInt("y", a_BlockEntity.GetPosY()); a_Writer.AddInt("z", a_BlockEntity.GetPosZ()); } void cProtocol_1_11_0::WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_Entity) const { using namespace Metadata_1_11; // Common metadata: Int8 Flags = 0; if (a_Entity.IsOnFire()) { Flags |= 0x01; } if (a_Entity.IsCrouched()) { Flags |= 0x02; } if (a_Entity.IsSprinting()) { Flags |= 0x08; } if (a_Entity.IsRclking()) { Flags |= 0x10; } if (a_Entity.IsInvisible()) { Flags |= 0x20; } a_Pkt.WriteBEUInt8(ENTITY_FLAGS); // Index a_Pkt.WriteBEUInt8(METADATA_TYPE_BYTE); // Type a_Pkt.WriteBEInt8(Flags); switch (a_Entity.GetEntityType()) { case cEntity::etPlayer: { auto & Player = static_cast(a_Entity); // TODO Set player custom name to their name. // Then it's possible to move the custom name of mobs to the entities // and to remove the "special" player custom name. a_Pkt.WriteBEUInt8(ENTITY_CUSTOM_NAME); a_Pkt.WriteBEUInt8(METADATA_TYPE_STRING); a_Pkt.WriteString(Player.GetName()); a_Pkt.WriteBEUInt8(LIVING_HEALTH); a_Pkt.WriteBEUInt8(METADATA_TYPE_FLOAT); a_Pkt.WriteBEFloat(static_cast(Player.GetHealth())); a_Pkt.WriteBEUInt8(PLAYER_DISPLAYED_SKIN_PARTS); a_Pkt.WriteBEUInt8(METADATA_TYPE_BYTE); a_Pkt.WriteBEUInt8(static_cast(Player.GetSkinParts())); a_Pkt.WriteBEUInt8(PLAYER_MAIN_HAND); a_Pkt.WriteBEUInt8(METADATA_TYPE_BYTE); a_Pkt.WriteBEUInt8(Player.IsLeftHanded() ? 0 : 1); break; } case cEntity::etPickup: { a_Pkt.WriteBEUInt8(ITEM_ITEM); a_Pkt.WriteBEUInt8(METADATA_TYPE_ITEM); WriteItem(a_Pkt, static_cast(a_Entity).GetItem()); break; } case cEntity::etMinecart: { a_Pkt.WriteBEUInt8(MINECART_SHAKING_POWER); a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); // The following expression makes Minecarts shake more with less health or higher damage taken auto & Minecart = static_cast(a_Entity); auto maxHealth = a_Entity.GetMaxHealth(); auto curHealth = a_Entity.GetHealth(); a_Pkt.WriteVarInt32(static_cast((maxHealth - curHealth) * Minecart.LastDamage() * 4)); a_Pkt.WriteBEUInt8(MINECART_SHAKING_DIRECTION); // (doesn't seem to effect anything) a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(1); a_Pkt.WriteBEUInt8(MINECART_SHAKING_MULTIPLIER); // or damage taken a_Pkt.WriteBEUInt8(METADATA_TYPE_FLOAT); a_Pkt.WriteBEFloat(static_cast(Minecart.LastDamage() + 10)); if (Minecart.GetPayload() == cMinecart::mpNone) { auto & RideableMinecart = static_cast(Minecart); const cItem & MinecartContent = RideableMinecart.GetContent(); if (!MinecartContent.IsEmpty()) { a_Pkt.WriteBEUInt8(MINECART_BLOCK_ID_META); a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); int Content = MinecartContent.m_ItemType; Content |= MinecartContent.m_ItemDamage << 8; a_Pkt.WriteVarInt32(static_cast(Content)); a_Pkt.WriteBEUInt8(MINECART_BLOCK_Y); a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(static_cast(RideableMinecart.GetBlockHeight())); a_Pkt.WriteBEUInt8(MINECART_SHOW_BLOCK); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(true); } } else if (Minecart.GetPayload() == cMinecart::mpFurnace) { a_Pkt.WriteBEUInt8(MINECART_FURNACE_POWERED); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(static_cast(Minecart).IsFueled()); } break; } // case etMinecart case cEntity::etProjectile: { auto & Projectile = static_cast(a_Entity); switch (Projectile.GetProjectileKind()) { case cProjectileEntity::pkArrow: { a_Pkt.WriteBEUInt8(ARROW_CRITICAL); a_Pkt.WriteBEUInt8(METADATA_TYPE_BYTE); a_Pkt.WriteBEInt8(static_cast(Projectile).IsCritical() ? 1 : 0); break; } case cProjectileEntity::pkFirework: { a_Pkt.WriteBEUInt8(FIREWORK_INFO); // Firework item used for this firework a_Pkt.WriteBEUInt8(METADATA_TYPE_ITEM); WriteItem(a_Pkt, static_cast(Projectile).GetItem()); // FIREWORK_BOOSTED_ENTITY_ID, in 1.11.1 only break; } case cProjectileEntity::pkSplashPotion: { a_Pkt.WriteBEUInt8(POTION_THROWN); // Potion item which was thrown a_Pkt.WriteBEUInt8(METADATA_TYPE_ITEM); WriteItem(a_Pkt, static_cast(Projectile).GetItem()); } default: { break; } } break; } // case etProjectile case cEntity::etMonster: { WriteMobMetadata(a_Pkt, static_cast(a_Entity)); break; } case cEntity::etBoat: { auto & Boat = static_cast(a_Entity); a_Pkt.WriteBEInt8(BOAT_LAST_HIT_TIME); a_Pkt.WriteBEInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(static_cast(Boat.GetLastDamage())); a_Pkt.WriteBEInt8(BOAT_FORWARD_DIRECTION); a_Pkt.WriteBEInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(static_cast(Boat.GetForwardDirection())); a_Pkt.WriteBEInt8(BOAT_DAMAGE_TAKEN); a_Pkt.WriteBEInt8(METADATA_TYPE_FLOAT); a_Pkt.WriteBEFloat(Boat.GetDamageTaken()); a_Pkt.WriteBEInt8(BOAT_TYPE); a_Pkt.WriteBEInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(static_cast(Boat.GetMaterial())); a_Pkt.WriteBEInt8(BOAT_RIGHT_PADDLE_TURNING); a_Pkt.WriteBEInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Boat.IsRightPaddleUsed()); a_Pkt.WriteBEInt8(BOAT_LEFT_PADDLE_TURNING); a_Pkt.WriteBEInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Boat.IsLeftPaddleUsed()); break; } // case etBoat case cEntity::etItemFrame: { auto & Frame = static_cast(a_Entity); a_Pkt.WriteBEUInt8(ITEM_FRAME_ITEM); a_Pkt.WriteBEUInt8(METADATA_TYPE_ITEM); WriteItem(a_Pkt, Frame.GetItem()); a_Pkt.WriteBEUInt8(ITEM_FRAME_ROTATION); a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(Frame.GetItemRotation()); break; } // case etItemFrame case cEntity::etEnderCrystal: { const auto & EnderCrystal = static_cast(a_Entity); if (EnderCrystal.DisplaysBeam()) { a_Pkt.WriteBEUInt8(ENDER_CRYSTAL_BEAM_TARGET); a_Pkt.WriteBEUInt8(METADATA_TYPE_OPTIONAL_POSITION); a_Pkt.WriteBool(true); // Dont do a second check if it should display the beam a_Pkt.WriteXYZPosition64(EnderCrystal.GetBeamTarget()); } a_Pkt.WriteBEUInt8(ENDER_CRYSTAL_SHOW_BOTTOM); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(EnderCrystal.ShowsBottom()); break; } // case etEnderCrystal default: { break; } } } void cProtocol_1_11_0::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mob) const { using namespace Metadata_1_11; // Living entity Metadata if (a_Mob.HasCustomName()) { // TODO: As of 1.9 _all_ entities can have custom names; should this be moved up? a_Pkt.WriteBEUInt8(ENTITY_CUSTOM_NAME); a_Pkt.WriteBEUInt8(METADATA_TYPE_STRING); a_Pkt.WriteString(a_Mob.GetCustomName()); a_Pkt.WriteBEUInt8(ENTITY_CUSTOM_NAME_VISIBLE); // Custom name always visible a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(a_Mob.IsCustomNameAlwaysVisible()); } a_Pkt.WriteBEUInt8(LIVING_HEALTH); a_Pkt.WriteBEUInt8(METADATA_TYPE_FLOAT); a_Pkt.WriteBEFloat(static_cast(a_Mob.GetHealth())); switch (a_Mob.GetMobType()) { case mtBat: { auto & Bat = static_cast(a_Mob); a_Pkt.WriteBEUInt8(BAT_HANGING); a_Pkt.WriteBEUInt8(METADATA_TYPE_BYTE); a_Pkt.WriteBEInt8(Bat.IsHanging() ? 1 : 0); break; } // case mtBat case mtChicken: { auto & Chicken = static_cast(a_Mob); a_Pkt.WriteBEUInt8(AGEABLE_BABY); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Chicken.IsBaby()); break; } // case mtChicken case mtCow: { auto & Cow = static_cast(a_Mob); a_Pkt.WriteBEUInt8(AGEABLE_BABY); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Cow.IsBaby()); break; } // case mtCow case mtCreeper: { auto & Creeper = static_cast(a_Mob); a_Pkt.WriteBEUInt8(CREEPER_STATE); // (idle or "blowing") a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(Creeper.IsBlowing() ? 1 : static_cast(-1)); a_Pkt.WriteBEUInt8(CREEPER_POWERED); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Creeper.IsCharged()); a_Pkt.WriteBEUInt8(CREEPER_IGNITED); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Creeper.IsBurnedWithFlintAndSteel()); break; } // case mtCreeper case mtEnderman: { auto & Enderman = static_cast(a_Mob); a_Pkt.WriteBEUInt8(ENDERMAN_CARRIED_BLOCK); a_Pkt.WriteBEUInt8(METADATA_TYPE_BLOCKID); UInt32 Carried = 0; Carried |= static_cast(Enderman.GetCarriedBlock() << 4); Carried |= Enderman.GetCarriedMeta(); a_Pkt.WriteVarInt32(Carried); a_Pkt.WriteBEUInt8(ENDERMAN_SCREAMING); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Enderman.IsScreaming()); break; } // case mtEnderman case mtGhast: { auto & Ghast = static_cast(a_Mob); a_Pkt.WriteBEUInt8(GHAST_ATTACKING); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Ghast.IsCharging()); break; } // case mtGhast case mtHorse: { // XXX This behaves incorrectly with different variants; horses have different entity IDs now // Abstract horse auto & Horse = static_cast(a_Mob); Int8 Flags = 0; if (Horse.IsTame()) { Flags |= 0x02; } if (Horse.IsSaddled()) { Flags |= 0x04; } if (Horse.IsChested()) { Flags |= 0x08; } if (Horse.IsEating()) { Flags |= 0x20; } if (Horse.IsRearing()) { Flags |= 0x40; } if (Horse.IsMthOpen()) { Flags |= 0x80; } a_Pkt.WriteBEUInt8(ABSTRACT_HORSE_STATUS); a_Pkt.WriteBEUInt8(METADATA_TYPE_BYTE); a_Pkt.WriteBEInt8(Flags); // This doesn't exist any more; it'll cause horses to all be the normal type // a_Pkt.WriteBEUInt8(HORSE_TYPE); // a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); // a_Pkt.WriteVarInt32(static_cast(Horse.GetHorseType())); // Regular horses a_Pkt.WriteBEUInt8(HORSE_VARIANT); // Color / style a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); int Appearance = 0; Appearance = Horse.GetHorseColor(); Appearance |= Horse.GetHorseStyle() << 8; a_Pkt.WriteVarInt32(static_cast(Appearance)); a_Pkt.WriteBEUInt8(HORSE_ARMOR); a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(static_cast(Horse.GetHorseArmour())); a_Pkt.WriteBEUInt8(AGEABLE_BABY); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Horse.IsBaby()); break; } // case mtHorse case mtMagmaCube: { auto & MagmaCube = static_cast(a_Mob); a_Pkt.WriteBEUInt8(SLIME_SIZE); a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(static_cast(MagmaCube.GetSize())); break; } // case mtMagmaCube case mtOcelot: { // Todo: move unnecessary to cat auto & Ocelot = static_cast(a_Mob); a_Pkt.WriteBEUInt8(AGEABLE_BABY); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Ocelot.IsBaby()); Int8 OcelotStatus = 0; if (Ocelot.IsSitting()) { OcelotStatus |= 0x1; } if (Ocelot.IsTame()) { OcelotStatus |= 0x4; } a_Pkt.WriteBEUInt8(TAMEABLE_ANIMAL_STATUS); a_Pkt.WriteBEUInt8(METADATA_TYPE_BYTE); a_Pkt.WriteBEInt8(OcelotStatus); a_Pkt.WriteBEUInt8(OCELOT_TYPE); a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(static_cast(Ocelot.GetOcelotType())); break; } // case mtOcelot case mtPig: { auto & Pig = static_cast(a_Mob); a_Pkt.WriteBEUInt8(AGEABLE_BABY); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Pig.IsBaby()); a_Pkt.WriteBEUInt8(PIG_HAS_SADDLE); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Pig.IsSaddled()); // PIG_TOTAL_CARROT_ON_A_STICK_BOOST in 1.11.1 only break; } // case mtPig case mtRabbit: { auto & Rabbit = static_cast(a_Mob); a_Pkt.WriteBEUInt8(AGEABLE_BABY); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Rabbit.IsBaby()); a_Pkt.WriteBEUInt8(RABBIT_TYPE); a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(static_cast(Rabbit.GetRabbitType())); break; } // case mtRabbit case mtSheep: { auto & Sheep = static_cast(a_Mob); a_Pkt.WriteBEUInt8(AGEABLE_BABY); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Sheep.IsBaby()); a_Pkt.WriteBEUInt8(SHEEP_STATUS); a_Pkt.WriteBEUInt8(METADATA_TYPE_BYTE); Int8 SheepMetadata = 0; SheepMetadata = static_cast(Sheep.GetFurColor()); if (Sheep.IsSheared()) { SheepMetadata |= 0x10; } a_Pkt.WriteBEInt8(SheepMetadata); break; } // case mtSheep case mtSkeleton: { auto & Skeleton = static_cast(a_Mob); a_Pkt.WriteBEUInt8(LIVING_ACTIVE_HAND); a_Pkt.WriteBEUInt8(METADATA_TYPE_BYTE); a_Pkt.WriteBEUInt8(Skeleton.IsChargingBow() ? 0x01 : 0x00); a_Pkt.WriteBEUInt8(ABSTRACT_SKELETON_ARMS_SWINGING); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Skeleton.IsChargingBow()); break; } // case mtSkeleton case mtSlime: { auto & Slime = static_cast(a_Mob); a_Pkt.WriteBEUInt8(SLIME_SIZE); a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(static_cast(Slime.GetSize())); break; } // case mtSlime case mtVillager: { auto & Villager = static_cast(a_Mob); a_Pkt.WriteBEUInt8(AGEABLE_BABY); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Villager.IsBaby()); a_Pkt.WriteBEUInt8(VILLAGER_PROFESSION); a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(static_cast(Villager.GetVilType())); break; } // case mtVillager case mtWitch: { auto & Witch = static_cast(a_Mob); a_Pkt.WriteBEUInt8(WITCH_AGGRESIVE); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Witch.IsAngry()); break; } // case mtWitch case mtWither: { auto & Wither = static_cast(a_Mob); a_Pkt.WriteBEUInt8(WITHER_INVULNERABLE_TIMER); a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(Wither.GetWitherInvulnerableTicks()); // TODO: Use boss bar packet for health break; } // case mtWither case mtWolf: { auto & Wolf = static_cast(a_Mob); a_Pkt.WriteBEUInt8(AGEABLE_BABY); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Wolf.IsBaby()); Int8 WolfStatus = 0; if (Wolf.IsSitting()) { WolfStatus |= 0x1; } if (Wolf.IsAngry()) { WolfStatus |= 0x2; } if (Wolf.IsTame()) { WolfStatus |= 0x4; } a_Pkt.WriteBEUInt8(TAMEABLE_ANIMAL_STATUS); a_Pkt.WriteBEUInt8(METADATA_TYPE_BYTE); a_Pkt.WriteBEInt8(WolfStatus); a_Pkt.WriteBEUInt8(WOLF_DAMAGE_TAKEN); a_Pkt.WriteBEUInt8(METADATA_TYPE_FLOAT); a_Pkt.WriteBEFloat(static_cast(a_Mob.GetHealth())); // TODO Not use the current health a_Pkt.WriteBEUInt8(WOLF_BEGGING); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Wolf.IsBegging()); a_Pkt.WriteBEUInt8(WOLF_COLLAR_COLOR); a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(static_cast(Wolf.GetCollarColor())); break; } // case mtWolf case mtZombie: { // XXX Zombies were also split into new subclasses; this doesn't handle that. auto & Zombie = static_cast(a_Mob); a_Pkt.WriteBEUInt8(ZOMBIE_IS_BABY); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Zombie.IsBaby()); break; } // case mtZombie case mtZombiePigman: { auto & ZombiePigman = static_cast(a_Mob); a_Pkt.WriteBEUInt8(AGEABLE_BABY); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(ZombiePigman.IsBaby()); break; } // case mtZombiePigman case mtZombieVillager: { auto & ZombieVillager = reinterpret_cast(a_Mob); a_Pkt.WriteBEUInt8(ZOMBIE_IS_BABY); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(ZombieVillager.IsBaby()); a_Pkt.WriteBEUInt8(ZOMBIE_VILLAGER_CONVERTING); a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(static_cast(ZombieVillager.ConversionTime())); a_Pkt.WriteBEUInt8(ZOMBIE_VILLAGER_PROFESSION); a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(static_cast(ZombieVillager.GetProfession())); break; } // case mtZombieVillager case mtBlaze: case mtElderGuardian: case mtGuardian: case mtSnowGolem: { // TODO: Mobs with extra fields that aren't implemented break; } case mtCat: case mtDonkey: case mtMule: case mtEvoker: case mtLlama: case mtPolarBear: case mtShulker: case mtSkeletonHorse: case mtZombieHorse: case mtVex: case mtVindicator: { // Todo: Mobs not added yet. Grouped ones have the same metadata ASSERT(!"cProtocol_1_11::WriteMobMetadata: received unimplemented type"); break; } case mtCaveSpider: case mtEnderDragon: case mtEndermite: case mtGiant: case mtIronGolem: case mtMooshroom: case mtSilverfish: case mtStray: case mtSpider: case mtSquid: case mtWitherSkeleton: { // Mobs without additional metadata break; } default: UNREACHABLE("cProtocol_1_11::WriteMobMetadata: received mob of invalid type"); } // switch (a_Mob.GetType()) } //////////////////////////////////////////////////////////////////////////////// // cProtocol_1_11_1: cProtocol::Version cProtocol_1_11_1::GetProtocolVersion() const { return Version::v1_11_1; } ================================================ FILE: src/Protocol/Protocol_1_11.h ================================================ // Protocol_1_11.h /* Declares the 1.11 protocol classes: - cProtocol_1_11_0 - release 1.11 protocol (#315) - cProtocol_1_11_1 - release 1.11.1 protocol (#316) */ #pragma once #include "Protocol_1_10.h" class cProtocol_1_11_0: public cProtocol_1_10_0 { using Super = cProtocol_1_10_0; public: using Super::Super; protected: virtual void SendCollectEntity (const cEntity & a_Collected, const cEntity & a_Collector, unsigned a_Count) override; virtual void SendEntityAnimation (const cEntity & a_Entity, EntityAnimation a_Animation) override; virtual void SendHideTitle (void) override; virtual void SendResetTitle (void) override; virtual void SendSpawnMob (const cMonster & a_Mob) override; virtual void SendTitleTimes (int a_FadeInTicks, int a_DisplayTicks, int a_FadeOutTicks) override; virtual void SendUpdateBlockEntity(cBlockEntity & a_BlockEntity) override; virtual signed char GetProtocolEntityStatus(EntityAnimation a_Animation) const override; virtual UInt32 GetProtocolMobType(eMonsterType a_MobType) const override; virtual Version GetProtocolVersion() const override; virtual void HandlePacketBlockPlace(cByteBuffer & a_ByteBuffer) override; virtual void WriteBlockEntity(cFastNBTWriter & a_Writer, const cBlockEntity & a_BlockEntity) const override; virtual void WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_Entity) const override; virtual void WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mob) const override; }; class cProtocol_1_11_1: public cProtocol_1_11_0 { using Super = cProtocol_1_11_0; public: using Super::Super; protected: virtual Version GetProtocolVersion() const override; }; ================================================ FILE: src/Protocol/Protocol_1_12.cpp ================================================ // Protocol_1_12.cpp /* Implements the 1.12 protocol classes: - release 1.12 protocol (#335) - release 1.12.1 protocol (#338) - release 1.12.2 protocol (#340) */ #include "Globals.h" #include "Protocol_1_12.h" #include "Packetizer.h" #include "../Entities/Boat.h" #include "../Entities/EnderCrystal.h" #include "../Entities/Minecart.h" #include "../Entities/Pickup.h" #include "../Entities/Player.h" #include "../Entities/ItemFrame.h" #include "../Entities/ArrowEntity.h" #include "../Entities/FireworkEntity.h" #include "../Entities/SplashPotionEntity.h" #include "../Mobs/IncludeAllMonsters.h" #include "../Root.h" #include "../Server.h" #include "../ClientHandle.h" #include "../CraftingRecipes.h" #include "../Bindings/PluginManager.h" #include "../JsonUtils.h" // The disabled error is intended, since the Metadata have overlapping indexes // based on the type of the Entity. // // IMPORTANT: The enum is used to automate the sequential counting of the // Metadata indexes. Adding a new enum value causes the following values to // increase their index. Therefore the ordering of the enum values is VERY important! #ifdef __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wduplicate-enum" #endif namespace Metadata_1_12 { enum MetadataIndex { // Entity ENTITY_FLAGS, ENTITY_AIR, ENTITY_CUSTOM_NAME, ENTITY_CUSTOM_NAME_VISIBLE, ENTITY_SILENT, ENTITY_NO_GRAVITY, _ENTITY_NEXT, // Used by descendants // Potion POTION_THROWN = _ENTITY_NEXT, // FallingBlock FALLING_BLOCK_POSITION = _ENTITY_NEXT, // AreaEffectCloud AREA_EFFECT_CLOUD_RADIUS = _ENTITY_NEXT, AREA_EFFECT_CLOUD_COLOR, AREA_EFFECT_CLOUD_SINGLE_POINT_EFFECT, AREA_EFFECT_CLOUD_PARTICLE_ID, AREA_EFFECT_CLOUD_PARTICLE_PARAMETER1, AREA_EFFECT_CLOUD_PARTICLE_PARAMETER2, // Arrow ARROW_CRITICAL = _ENTITY_NEXT, _ARROW_NEXT, // TippedArrow TIPPED_ARROW_COLOR = _ARROW_NEXT, // Boat BOAT_LAST_HIT_TIME = _ENTITY_NEXT, BOAT_FORWARD_DIRECTION, BOAT_DAMAGE_TAKEN, BOAT_TYPE, BOAT_RIGHT_PADDLE_TURNING, BOAT_LEFT_PADDLE_TURNING, // EnderCrystal ENDER_CRYSTAL_BEAM_TARGET = _ENTITY_NEXT, ENDER_CRYSTAL_SHOW_BOTTOM, // Fireball _FIREBALL_NEXT = _ENTITY_NEXT, // WitherSkull WITHER_SKULL_INVULNERABLE = _FIREBALL_NEXT, // Fireworks FIREWORK_INFO = _ENTITY_NEXT, FIREWORK_BOOSTED_ENTITY_ID, // 1.11.1 only // Hanging _HANGING_NEXT = _ENTITY_NEXT, // ItemFrame ITEM_FRAME_ITEM = _HANGING_NEXT, ITEM_FRAME_ROTATION, // Item ITEM_ITEM = _ENTITY_NEXT, // Living LIVING_ACTIVE_HAND = _ENTITY_NEXT, LIVING_HEALTH, LIVING_POTION_EFFECT_COLOR, LIVING_POTION_EFFECT_AMBIENT, LIVING_NUMBER_OF_ARROWS, _LIVING_NEXT, // Player PLAYER_ADDITIONAL_HEARTHS = _LIVING_NEXT, PLAYER_SCORE, PLAYER_DISPLAYED_SKIN_PARTS, PLAYER_MAIN_HAND, // ArmorStand ARMOR_STAND_STATUS = _LIVING_NEXT, ARMOR_STAND_HEAD_ROTATION, ARMOR_STAND_BODY_ROTATION, ARMOR_STAND_LEFT_ARM_ROTATION, ARMOR_STAND_RIGHT_ARM_ROTATION, ARMOR_STAND_LEFT_LEG_ROTATION, ARMOR_STAND_RIGHT_LEG_ROTATION, // Insentient INSENTIENT_STATUS = _LIVING_NEXT, _INSENTIENT_NEXT, // Ambient _AMBIENT_NEXT = _INSENTIENT_NEXT, // Bat BAT_HANGING = _AMBIENT_NEXT, // Creature _CREATURE_NEXT = _INSENTIENT_NEXT, // Ageable AGEABLE_BABY = _CREATURE_NEXT, _AGEABLE_NEXT, // PolarBear POLAR_BEAR_STANDING = _AGEABLE_NEXT, // Animal _ANIMAL_NEXT = _AGEABLE_NEXT, // Abstract horse ABSTRACT_HORSE_STATUS = _ANIMAL_NEXT, ABSTRACT_HORSE_OWNER, _ABSTRACT_HORSE_NEXT, // Horse HORSE_VARIANT = _ABSTRACT_HORSE_NEXT, HORSE_ARMOR, // Chested horse CHESTED_HORSE_CHESTED = _ABSTRACT_HORSE_NEXT, _CHESTED_HORSE_NEXT, // Llama LLAMA_STRENGTH = _CHESTED_HORSE_NEXT, LLAMA_CARPET_COLOR, LLAMA_VARIANT, // Pig PIG_HAS_SADDLE = _ANIMAL_NEXT, PIG_TOTAL_CARROT_ON_A_STICK_BOOST, // 1.11.1 only // Rabbit RABBIT_TYPE = _ANIMAL_NEXT, // Sheep SHEEP_STATUS = _ANIMAL_NEXT, // TameableAnimal TAMEABLE_ANIMAL_STATUS = _ANIMAL_NEXT, TAMEABLE_ANIMAL_OWNER, _TAMEABLE_NEXT, // Ocelot OCELOT_TYPE = _TAMEABLE_NEXT, // Wolf WOLF_DAMAGE_TAKEN = _TAMEABLE_NEXT, WOLF_BEGGING, WOLF_COLLAR_COLOR, // Villager VILLAGER_PROFESSION = _AGEABLE_NEXT, // Golem _GOLEM_NEXT = _CREATURE_NEXT, // IronGolem IRON_GOLEM_PLAYER_CREATED = _GOLEM_NEXT, // Shulker SHULKER_FACING_DIRECTION = _GOLEM_NEXT, SHULKER_ATTACHMENT_FALLING_BLOCK_POSITION, SHULKER_SHIELD_HEIGHT, // Monster _MONSTER_NEXT = _CREATURE_NEXT, // Blaze BLAZE_ON_FIRE = _MONSTER_NEXT, // Creeper CREEPER_STATE = _MONSTER_NEXT, CREEPER_POWERED, CREEPER_IGNITED, // Guardian GUARDIAN_STATUS = _MONSTER_NEXT, GUARDIAN_TARGET, // Abstract Skeleton ABSTRACT_SKELETON_ARMS_SWINGING = _MONSTER_NEXT, // Spider SPIDER_CLIMBING = _MONSTER_NEXT, // Witch WITCH_AGGRESIVE = _MONSTER_NEXT, // Wither WITHER_FIRST_HEAD_TARGET = _MONSTER_NEXT, WITHER_SECOND_HEAD_TARGET, WITHER_THIRD_HEAD_TARGET, WITHER_INVULNERABLE_TIMER, // Zombie ZOMBIE_IS_BABY = _MONSTER_NEXT, ZOMBIE_UNUSED, // Was type ZOMBIE_HANDS_RISED_UP, _ZOMBIE_NEXT, // Zombie villager ZOMBIE_VILLAGER_CONVERTING = _ZOMBIE_NEXT, ZOMBIE_VILLAGER_PROFESSION, // Enderman ENDERMAN_CARRIED_BLOCK = _MONSTER_NEXT, ENDERMAN_SCREAMING, // Evocation illager EVOKER_SPELL = _MONSTER_NEXT, // Vex VEX_FLAGS = _MONSTER_NEXT, // Vindication illager VINDICATOR_FLAGS = _MONSTER_NEXT, // EnderDragon ENDER_DRAGON_DRAGON_PHASE = _INSENTIENT_NEXT, // Flying _FLYING_NEXT = _INSENTIENT_NEXT, // Ghast GHAST_ATTACKING = _FLYING_NEXT, // Slime SLIME_SIZE = _INSENTIENT_NEXT, // Minecart MINECART_SHAKING_POWER = _ENTITY_NEXT, MINECART_SHAKING_DIRECTION, MINECART_SHAKING_MULTIPLIER, MINECART_BLOCK_ID_META, MINECART_BLOCK_Y, MINECART_SHOW_BLOCK, _MINECART_NEXT, // MinecartCommandBlock MINECART_COMMAND_BLOCK_COMMAND = _MINECART_NEXT, MINECART_COMMAND_BLOCK_LAST_OUTPUT, // MinecartFurnace MINECART_FURNACE_POWERED = _MINECART_NEXT, // TNTPrimed TNT_PRIMED_FUSE_TIME = _ENTITY_NEXT, }; } #ifdef __clang__ #pragma clang diagnostic pop // Restore ignored clang errors #endif //////////////////////////////////////////////////////////////////////////////// // cProtocol_1_12: void cProtocol_1_12::WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_Entity) const { using namespace Metadata_1_12; // Common metadata: Int8 Flags = 0; if (a_Entity.IsOnFire()) { Flags |= 0x01; } if (a_Entity.IsCrouched()) { Flags |= 0x02; } if (a_Entity.IsSprinting()) { Flags |= 0x08; } if (a_Entity.IsRclking()) { Flags |= 0x10; } if (a_Entity.IsInvisible()) { Flags |= 0x20; } if (a_Entity.IsElytraFlying()) { Flags |= 0x80; } a_Pkt.WriteBEUInt8(ENTITY_FLAGS); // Index a_Pkt.WriteBEUInt8(METADATA_TYPE_BYTE); // Type a_Pkt.WriteBEInt8(Flags); switch (a_Entity.GetEntityType()) { case cEntity::etPlayer: { auto & Player = static_cast(a_Entity); // TODO Set player custom name to their name. // Then it's possible to move the custom name of mobs to the entities // and to remove the "special" player custom name. a_Pkt.WriteBEUInt8(ENTITY_CUSTOM_NAME); a_Pkt.WriteBEUInt8(METADATA_TYPE_STRING); a_Pkt.WriteString(Player.GetName()); a_Pkt.WriteBEUInt8(LIVING_HEALTH); a_Pkt.WriteBEUInt8(METADATA_TYPE_FLOAT); a_Pkt.WriteBEFloat(static_cast(Player.GetHealth())); a_Pkt.WriteBEUInt8(PLAYER_DISPLAYED_SKIN_PARTS); a_Pkt.WriteBEUInt8(METADATA_TYPE_BYTE); a_Pkt.WriteBEUInt8(static_cast(Player.GetSkinParts())); a_Pkt.WriteBEUInt8(PLAYER_MAIN_HAND); a_Pkt.WriteBEUInt8(METADATA_TYPE_BYTE); a_Pkt.WriteBEUInt8(Player.IsLeftHanded() ? 0 : 1); break; } case cEntity::etPickup: { a_Pkt.WriteBEUInt8(ITEM_ITEM); a_Pkt.WriteBEUInt8(METADATA_TYPE_ITEM); WriteItem(a_Pkt, static_cast(a_Entity).GetItem()); break; } case cEntity::etMinecart: { a_Pkt.WriteBEUInt8(MINECART_SHAKING_POWER); a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); // The following expression makes Minecarts shake more with less health or higher damage taken auto & Minecart = static_cast(a_Entity); auto maxHealth = a_Entity.GetMaxHealth(); auto curHealth = a_Entity.GetHealth(); a_Pkt.WriteVarInt32(static_cast((maxHealth - curHealth) * Minecart.LastDamage() * 4)); a_Pkt.WriteBEUInt8(MINECART_SHAKING_DIRECTION); // (doesn't seem to effect anything) a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(1); a_Pkt.WriteBEUInt8(MINECART_SHAKING_MULTIPLIER); // or damage taken a_Pkt.WriteBEUInt8(METADATA_TYPE_FLOAT); a_Pkt.WriteBEFloat(static_cast(Minecart.LastDamage() + 10)); if (Minecart.GetPayload() == cMinecart::mpNone) { auto & RideableMinecart = static_cast(Minecart); const cItem & MinecartContent = RideableMinecart.GetContent(); if (!MinecartContent.IsEmpty()) { a_Pkt.WriteBEUInt8(MINECART_BLOCK_ID_META); a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); int Content = MinecartContent.m_ItemType; Content |= MinecartContent.m_ItemDamage << 8; a_Pkt.WriteVarInt32(static_cast(Content)); a_Pkt.WriteBEUInt8(MINECART_BLOCK_Y); a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(static_cast(RideableMinecart.GetBlockHeight())); a_Pkt.WriteBEUInt8(MINECART_SHOW_BLOCK); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(true); } } else if (Minecart.GetPayload() == cMinecart::mpFurnace) { a_Pkt.WriteBEUInt8(MINECART_FURNACE_POWERED); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(static_cast(Minecart).IsFueled()); } break; } // case etMinecart case cEntity::etProjectile: { auto & Projectile = static_cast(a_Entity); switch (Projectile.GetProjectileKind()) { case cProjectileEntity::pkArrow: { a_Pkt.WriteBEUInt8(ARROW_CRITICAL); a_Pkt.WriteBEUInt8(METADATA_TYPE_BYTE); a_Pkt.WriteBEInt8(static_cast(Projectile).IsCritical() ? 1 : 0); break; } case cProjectileEntity::pkFirework: { a_Pkt.WriteBEUInt8(FIREWORK_INFO); // Firework item used for this firework a_Pkt.WriteBEUInt8(METADATA_TYPE_ITEM); WriteItem(a_Pkt, static_cast(Projectile).GetItem()); // FIREWORK_BOOSTED_ENTITY_ID, in 1.11.1 only break; } case cProjectileEntity::pkSplashPotion: { a_Pkt.WriteBEUInt8(POTION_THROWN); // Potion item which was thrown a_Pkt.WriteBEUInt8(METADATA_TYPE_ITEM); WriteItem(a_Pkt, static_cast(Projectile).GetItem()); } default: { break; } } break; } // case etProjectile case cEntity::etMonster: { WriteMobMetadata(a_Pkt, static_cast(a_Entity)); break; } case cEntity::etBoat: { auto & Boat = static_cast(a_Entity); a_Pkt.WriteBEInt8(BOAT_LAST_HIT_TIME); a_Pkt.WriteBEInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(static_cast(Boat.GetLastDamage())); a_Pkt.WriteBEInt8(BOAT_FORWARD_DIRECTION); a_Pkt.WriteBEInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(static_cast(Boat.GetForwardDirection())); a_Pkt.WriteBEInt8(BOAT_DAMAGE_TAKEN); a_Pkt.WriteBEInt8(METADATA_TYPE_FLOAT); a_Pkt.WriteBEFloat(Boat.GetDamageTaken()); a_Pkt.WriteBEInt8(BOAT_TYPE); a_Pkt.WriteBEInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(static_cast(Boat.GetMaterial())); a_Pkt.WriteBEInt8(BOAT_RIGHT_PADDLE_TURNING); a_Pkt.WriteBEInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Boat.IsRightPaddleUsed()); a_Pkt.WriteBEInt8(BOAT_LEFT_PADDLE_TURNING); a_Pkt.WriteBEInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Boat.IsLeftPaddleUsed()); break; } // case etBoat case cEntity::etItemFrame: { auto & Frame = static_cast(a_Entity); a_Pkt.WriteBEUInt8(ITEM_FRAME_ITEM); a_Pkt.WriteBEUInt8(METADATA_TYPE_ITEM); WriteItem(a_Pkt, Frame.GetItem()); a_Pkt.WriteBEUInt8(ITEM_FRAME_ROTATION); a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(Frame.GetItemRotation()); break; } // case etItemFrame case cEntity::etEnderCrystal: { const auto & EnderCrystal = static_cast(a_Entity); if (EnderCrystal.DisplaysBeam()) { a_Pkt.WriteBEUInt8(ENDER_CRYSTAL_BEAM_TARGET); a_Pkt.WriteBEUInt8(METADATA_TYPE_OPTIONAL_POSITION); a_Pkt.WriteBool(true); // Dont do a second check if it should display the beam a_Pkt.WriteXYZPosition64(EnderCrystal.GetBeamTarget()); } a_Pkt.WriteBEUInt8(ENDER_CRYSTAL_SHOW_BOTTOM); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(EnderCrystal.ShowsBottom()); break; } // case etEnderCrystal default: { break; } } } void cProtocol_1_12::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mob) const { using namespace Metadata_1_12; // Living entity metadata if (a_Mob.HasCustomName()) { // TODO: As of 1.9 _all_ entities can have custom names; should this be moved up? a_Pkt.WriteBEUInt8(ENTITY_CUSTOM_NAME); a_Pkt.WriteBEUInt8(METADATA_TYPE_STRING); a_Pkt.WriteString(a_Mob.GetCustomName()); a_Pkt.WriteBEUInt8(ENTITY_CUSTOM_NAME_VISIBLE); // Custom name always visible a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(a_Mob.IsCustomNameAlwaysVisible()); } a_Pkt.WriteBEUInt8(LIVING_HEALTH); a_Pkt.WriteBEUInt8(METADATA_TYPE_FLOAT); a_Pkt.WriteBEFloat(static_cast(a_Mob.GetHealth())); switch (a_Mob.GetMobType()) { case mtBat: { auto & Bat = static_cast(a_Mob); a_Pkt.WriteBEUInt8(BAT_HANGING); a_Pkt.WriteBEUInt8(METADATA_TYPE_BYTE); a_Pkt.WriteBEInt8(Bat.IsHanging() ? 1 : 0); break; } // case mtBat case mtChicken: { auto & Chicken = static_cast(a_Mob); a_Pkt.WriteBEUInt8(AGEABLE_BABY); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Chicken.IsBaby()); break; } // case mtChicken case mtCow: { auto & Cow = static_cast(a_Mob); a_Pkt.WriteBEUInt8(AGEABLE_BABY); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Cow.IsBaby()); break; } // case mtCow case mtCreeper: { auto & Creeper = static_cast(a_Mob); a_Pkt.WriteBEUInt8(CREEPER_STATE); // (idle or "blowing") a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(Creeper.IsBlowing() ? 1 : static_cast(-1)); a_Pkt.WriteBEUInt8(CREEPER_POWERED); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Creeper.IsCharged()); a_Pkt.WriteBEUInt8(CREEPER_IGNITED); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Creeper.IsBurnedWithFlintAndSteel()); break; } // case mtCreeper case mtEnderman: { auto & Enderman = static_cast(a_Mob); a_Pkt.WriteBEUInt8(ENDERMAN_CARRIED_BLOCK); a_Pkt.WriteBEUInt8(METADATA_TYPE_BLOCKID); UInt32 Carried = 0; Carried |= static_cast(Enderman.GetCarriedBlock() << 4); Carried |= Enderman.GetCarriedMeta(); a_Pkt.WriteVarInt32(Carried); a_Pkt.WriteBEUInt8(ENDERMAN_SCREAMING); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Enderman.IsScreaming()); break; } // case mtEnderman case mtGhast: { auto & Ghast = static_cast(a_Mob); a_Pkt.WriteBEUInt8(GHAST_ATTACKING); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Ghast.IsCharging()); break; } // case mtGhast case mtHorse: { // XXX This behaves incorrectly with different variants; horses have different entity IDs now // Abstract horse auto & Horse = static_cast(a_Mob); Int8 Flags = 0; if (Horse.IsTame()) { Flags |= 0x02; } if (Horse.IsSaddled()) { Flags |= 0x04; } if (Horse.IsChested()) { Flags |= 0x08; } if (Horse.IsEating()) { Flags |= 0x20; } if (Horse.IsRearing()) { Flags |= 0x40; } if (Horse.IsMthOpen()) { Flags |= 0x80; } a_Pkt.WriteBEUInt8(ABSTRACT_HORSE_STATUS); a_Pkt.WriteBEUInt8(METADATA_TYPE_BYTE); a_Pkt.WriteBEInt8(Flags); // This doesn't exist any more; it'll cause horses to all be the normal type // a_Pkt.WriteBEUInt8(HORSE_TYPE); // a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); // a_Pkt.WriteVarInt32(static_cast(Horse.GetHorseType())); // Regular horses a_Pkt.WriteBEUInt8(HORSE_VARIANT); // Color / style a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); int Appearance = 0; Appearance = Horse.GetHorseColor(); Appearance |= Horse.GetHorseStyle() << 8; a_Pkt.WriteVarInt32(static_cast(Appearance)); a_Pkt.WriteBEUInt8(HORSE_ARMOR); a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(static_cast(Horse.GetHorseArmour())); a_Pkt.WriteBEUInt8(AGEABLE_BABY); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Horse.IsBaby()); break; } // case mtHorse case mtMagmaCube: { auto & MagmaCube = static_cast(a_Mob); a_Pkt.WriteBEUInt8(SLIME_SIZE); a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(static_cast(MagmaCube.GetSize())); break; } // case mtMagmaCube case mtOcelot: { auto & Ocelot = static_cast(a_Mob); a_Pkt.WriteBEUInt8(AGEABLE_BABY); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Ocelot.IsBaby()); Int8 OcelotStatus = 0; if (Ocelot.IsSitting()) { OcelotStatus |= 0x1; } if (Ocelot.IsTame()) { OcelotStatus |= 0x4; } a_Pkt.WriteBEUInt8(TAMEABLE_ANIMAL_STATUS); a_Pkt.WriteBEUInt8(METADATA_TYPE_BYTE); a_Pkt.WriteBEInt8(OcelotStatus); a_Pkt.WriteBEUInt8(OCELOT_TYPE); a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(static_cast(Ocelot.GetOcelotType())); break; } // case mtOcelot case mtPig: { auto & Pig = static_cast(a_Mob); a_Pkt.WriteBEUInt8(AGEABLE_BABY); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Pig.IsBaby()); a_Pkt.WriteBEUInt8(PIG_HAS_SADDLE); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Pig.IsSaddled()); // PIG_TOTAL_CARROT_ON_A_STICK_BOOST in 1.11.1 only break; } // case mtPig case mtRabbit: { auto & Rabbit = static_cast(a_Mob); a_Pkt.WriteBEUInt8(AGEABLE_BABY); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Rabbit.IsBaby()); a_Pkt.WriteBEUInt8(RABBIT_TYPE); a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(static_cast(Rabbit.GetRabbitType())); break; } // case mtRabbit case mtSheep: { auto & Sheep = static_cast(a_Mob); a_Pkt.WriteBEUInt8(AGEABLE_BABY); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Sheep.IsBaby()); a_Pkt.WriteBEUInt8(SHEEP_STATUS); a_Pkt.WriteBEUInt8(METADATA_TYPE_BYTE); Int8 SheepMetadata = 0; SheepMetadata = static_cast(Sheep.GetFurColor()); if (Sheep.IsSheared()) { SheepMetadata |= 0x10; } a_Pkt.WriteBEInt8(SheepMetadata); break; } // case mtSheep case mtSkeleton: { auto & Skeleton = static_cast(a_Mob); a_Pkt.WriteBEUInt8(LIVING_ACTIVE_HAND); a_Pkt.WriteBEUInt8(METADATA_TYPE_BYTE); a_Pkt.WriteBEUInt8(Skeleton.IsChargingBow() ? 0x01 : 0x00); a_Pkt.WriteBEUInt8(ABSTRACT_SKELETON_ARMS_SWINGING); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Skeleton.IsChargingBow()); break; } // case mtSkeleton case mtSlime: { auto & Slime = static_cast(a_Mob); a_Pkt.WriteBEUInt8(SLIME_SIZE); a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(static_cast(Slime.GetSize())); break; } // case mtSlime case mtVillager: { auto & Villager = static_cast(a_Mob); a_Pkt.WriteBEUInt8(AGEABLE_BABY); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Villager.IsBaby()); a_Pkt.WriteBEUInt8(VILLAGER_PROFESSION); a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(static_cast(Villager.GetVilType())); break; } // case mtVillager case mtWitch: { auto & Witch = static_cast(a_Mob); a_Pkt.WriteBEUInt8(WITCH_AGGRESIVE); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Witch.IsAngry()); break; } // case mtWitch case mtWither: { auto & Wither = static_cast(a_Mob); a_Pkt.WriteBEUInt8(WITHER_INVULNERABLE_TIMER); a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(Wither.GetWitherInvulnerableTicks()); // TODO: Use boss bar packet for health break; } // case mtWither case mtWolf: { auto & Wolf = static_cast(a_Mob); a_Pkt.WriteBEUInt8(AGEABLE_BABY); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Wolf.IsBaby()); Int8 WolfStatus = 0; if (Wolf.IsSitting()) { WolfStatus |= 0x1; } if (Wolf.IsAngry()) { WolfStatus |= 0x2; } if (Wolf.IsTame()) { WolfStatus |= 0x4; } a_Pkt.WriteBEUInt8(TAMEABLE_ANIMAL_STATUS); a_Pkt.WriteBEUInt8(METADATA_TYPE_BYTE); a_Pkt.WriteBEInt8(WolfStatus); a_Pkt.WriteBEUInt8(WOLF_DAMAGE_TAKEN); a_Pkt.WriteBEUInt8(METADATA_TYPE_FLOAT); a_Pkt.WriteBEFloat(static_cast(a_Mob.GetHealth())); // TODO Not use the current health a_Pkt.WriteBEUInt8(WOLF_BEGGING); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Wolf.IsBegging()); a_Pkt.WriteBEUInt8(WOLF_COLLAR_COLOR); a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(static_cast(Wolf.GetCollarColor())); break; } // case mtWolf case mtZombie: { // XXX Zombies were also split into new subclasses; this doesn't handle that. auto & Zombie = static_cast(a_Mob); a_Pkt.WriteBEUInt8(ZOMBIE_IS_BABY); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Zombie.IsBaby()); // These don't exist // a_Pkt.WriteBEUInt8(ZOMBIE_TYPE); // a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); // a_Pkt.WriteVarInt32(Zombie.IsVillagerZombie() ? 1 : 0); break; } // case mtZombie case mtZombiePigman: { auto & ZombiePigman = static_cast(a_Mob); a_Pkt.WriteBEUInt8(AGEABLE_BABY); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(ZombiePigman.IsBaby()); break; } // case mtZombiePigman case mtZombieVillager: { auto & ZombieVillager = reinterpret_cast(a_Mob); a_Pkt.WriteBEUInt8(ZOMBIE_IS_BABY); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(ZombieVillager.IsBaby()); a_Pkt.WriteBEUInt8(ZOMBIE_VILLAGER_CONVERTING); a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(static_cast(ZombieVillager.ConversionTime())); a_Pkt.WriteBEUInt8(ZOMBIE_VILLAGER_PROFESSION); a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(static_cast(ZombieVillager.GetProfession())); break; } // case mtZombieVillager case mtBlaze: case mtCaveSpider: case mtElderGuardian: case mtEnderDragon: case mtGuardian: case mtIronGolem: case mtSnowGolem: case mtSpider: case mtWitherSkeleton: { // TODO: Mobs with extra fields that aren't implemented break; } case mtMooshroom: { // Not mentioned on http://wiki.vg/Entities break; } case mtCat: case mtDonkey: case mtMule: case mtEvoker: case mtHusk: case mtIllusioner: case mtLlama: case mtParrot: case mtPolarBear: case mtShulker: case mtSkeletonHorse: case mtZombieHorse: case mtStray: case mtVex: case mtVindicator: { // Todo: Mobs not added yet. Grouped ones have the same metadata ASSERT(!"cProtocol_1_12::WriteMobMetadata: received unimplemented type"); break; } case mtEndermite: case mtGiant: case mtSilverfish: case mtSquid: { // Mobs with no extra fields break; } default: UNREACHABLE("cProtocol_1_12::WriteMobMetadata: received mob of invalid type"); } // switch (a_Mob.GetType()) } UInt32 cProtocol_1_12::GetPacketID(cProtocol::ePacketType a_Packet) const { switch (a_Packet) { case pktAttachEntity: return 0x42; case pktCameraSetTo: return 0x38; case pktCollectEntity: return 0x4a; case pktDestroyEntity: return 0x31; case pktDisplayObjective: return 0x3a; case pktEntityEffect: return 0x4e; case pktEntityEquipment: return 0x3e; case pktEntityHeadLook: return 0x35; case pktEntityLook: return 0x28; case pktEntityMeta: return 0x3b; case pktEntityProperties: return 0x4d; case pktEntityRelMove: return 0x26; case pktEntityRelMoveLook: return 0x27; case pktEntityVelocity: return 0x3d; case pktExperience: return 0x3f; case pktHeldItemChange: return 0x39; case pktLeashEntity: return 0x3c; case pktRemoveEntityEffect: return 0x32; case pktResourcePack: return 0x33; case pktRespawn: return 0x34; case pktScoreboardObjective: return 0x41; case pktSpawnPosition: return 0x45; case pktTeleportEntity: return 0x4b; case pktTimeUpdate: return 0x46; case pktTitle: return 0x47; case pktUnlockRecipe: return 0x30; case pktUpdateBlockEntity: return 0x09; case pktUpdateHealth: return 0x40; case pktUpdateScore: return 0x44; default: return Super::GetPacketID(a_Packet); } } void cProtocol_1_12::HandleCraftRecipe(cByteBuffer & a_ByteBuffer) { HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, WindowID); HANDLE_READ(a_ByteBuffer, ReadVarInt, UInt32, RecipeID); HANDLE_READ(a_ByteBuffer, ReadBool, bool, MakeAll); auto CuberiteRecipeId = cRoot::Get()->GetRecipeMapper()->GetCuberiteRecipeId(RecipeID, m_Client->GetProtocolVersion()); if (CuberiteRecipeId.has_value()) { m_Client->HandleCraftRecipe(CuberiteRecipeId.value()); } } void cProtocol_1_12::HandlePacketCraftingBookData(cByteBuffer & a_ByteBuffer) { // TODO not yet used, not sure if it is needed // https://wiki.vg/index.php?title=Protocol&oldid=14204#Crafting_Book_Data a_ByteBuffer.SkipRead(a_ByteBuffer.GetReadableSpace()); } void cProtocol_1_12::HandlePacketAdvancementTab(cByteBuffer & a_ByteBuffer) { a_ByteBuffer.SkipRead(a_ByteBuffer.GetReadableSpace()); m_Client->GetPlayer()->SendMessageInfo("The new advancements are not implemented."); } signed char cProtocol_1_12::GetProtocolEntityStatus(EntityAnimation a_Animation) const { switch (a_Animation) { case EntityAnimation::PawnBurns: return 37; case EntityAnimation::PawnDrowns: return 36; default: return Super::GetProtocolEntityStatus(a_Animation); } } UInt32 cProtocol_1_12::GetProtocolMobType(const eMonsterType a_MobType) const { switch (a_MobType) { case mtIllusioner: return 37; case mtParrot: return 105; default: return Super::GetProtocolMobType(a_MobType); } } cProtocol::Version cProtocol_1_12::GetProtocolVersion() const { return Version::v1_12; } bool cProtocol_1_12::HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType) { switch (m_State) { case State::Status: { switch (a_PacketType) { case 0x00: HandlePacketStatusRequest(a_ByteBuffer); return true; case 0x01: HandlePacketStatusPing(a_ByteBuffer); return true; } break; } case State::Login: { switch (a_PacketType) { case 0x00: HandlePacketLoginStart(a_ByteBuffer); return true; case 0x01: HandlePacketLoginEncryptionResponse(a_ByteBuffer); return true; } break; } case State::Game: { switch (a_PacketType) { case 0x00: HandleConfirmTeleport(a_ByteBuffer); return true; case 0x01: break; // Prepare Crafting Grid, not yet implemented case 0x02: HandlePacketTabComplete(a_ByteBuffer); return true; case 0x03: HandlePacketChatMessage(a_ByteBuffer); return true; case 0x04: HandlePacketClientStatus(a_ByteBuffer); return true; case 0x05: HandlePacketClientSettings(a_ByteBuffer); return true; case 0x06: break; // Confirm transaction - not used in Cuberite case 0x07: HandlePacketEnchantItem(a_ByteBuffer); return true; case 0x08: HandlePacketWindowClick(a_ByteBuffer); return true; case 0x09: HandlePacketWindowClose(a_ByteBuffer); return true; case 0x0a: HandlePacketPluginMessage(a_ByteBuffer); return true; case 0x0b: HandlePacketUseEntity(a_ByteBuffer); return true; case 0x0c: HandlePacketKeepAlive(a_ByteBuffer); return true; case 0x0d: HandlePacketPlayer(a_ByteBuffer); return true; case 0x0e: HandlePacketPlayerPos(a_ByteBuffer); return true; case 0x0f: HandlePacketPlayerPosLook(a_ByteBuffer); return true; case 0x10: HandlePacketPlayerLook(a_ByteBuffer); return true; case 0x11: HandlePacketVehicleMove(a_ByteBuffer); return true; case 0x12: HandlePacketBoatSteer(a_ByteBuffer); return true; case 0x13: HandlePacketPlayerAbilities(a_ByteBuffer); return true; case 0x14: HandlePacketBlockDig(a_ByteBuffer); return true; case 0x15: HandlePacketEntityAction(a_ByteBuffer); return true; case 0x16: HandlePacketSteerVehicle(a_ByteBuffer); return true; case 0x17: HandlePacketCraftingBookData(a_ByteBuffer); return true; case 0x18: HandlePacketResourcePackStatus(a_ByteBuffer); return true; case 0x19: HandlePacketAdvancementTab(a_ByteBuffer); return true; case 0x1a: HandlePacketSlotSelect(a_ByteBuffer); return true; case 0x1b: HandlePacketCreativeInventoryAction(a_ByteBuffer); return true; case 0x1c: HandlePacketUpdateSign(a_ByteBuffer); return true; case 0x1d: HandlePacketAnimation(a_ByteBuffer); return true; case 0x1e: HandlePacketSpectate(a_ByteBuffer); return true; case 0x1f: HandlePacketBlockPlace(a_ByteBuffer); return true; case 0x20: HandlePacketUseItem(a_ByteBuffer); return true; } break; } } // switch (m_State) // Unknown packet type, report to the ClientHandle: m_Client->PacketUnknown(a_PacketType); return false; } //////////////////////////////////////////////////////////////////////////////// // cProtocol_1_12_1: UInt32 cProtocol_1_12_1::GetPacketID(ePacketType a_Packet) const { switch (a_Packet) { case pktAttachEntity: return 0x43; case pktCameraSetTo: return 0x39; case pktCollectEntity: return 0x4b; case pktDestroyEntity: return 0x32; case pktDisplayObjective: return 0x3b; case pktEntityEffect: return 0x4f; case pktEntityEquipment: return 0x3f; case pktEntityHeadLook: return 0x36; case pktEntityMeta: return 0x3c; case pktEntityProperties: return 0x4e; case pktEntityVelocity: return 0x3e; case pktExperience: return 0x40; case pktHeldItemChange: return 0x3a; case pktLeashEntity: return 0x3d; case pktPlayerList: return 0x2e; case pktPlayerListHeaderFooter: return 0x4a; case pktPlayerAbilities: return 0x2c; case pktPlayerMoveLook: return 0x2f; case pktRemoveEntityEffect: return 0x33; case pktResourcePack: return 0x34; case pktRespawn: return 0x35; case pktScoreboardObjective: return 0x42; case pktSpawnPosition: return 0x46; case pktUnlockRecipe: return 0x31; case pktUpdateHealth: return 0x41; case pktUpdateScore: return 0x45; case pktUseBed: return 0x30; case pktTeleportEntity: return 0x4c; case pktTimeUpdate: return 0x47; case pktTitle: return 0x48; default: return Super::GetPacketID(a_Packet); } } cProtocol::Version cProtocol_1_12_1::GetProtocolVersion() const { return Version::v1_12_1; } bool cProtocol_1_12_1::HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType) { switch (m_State) { case State::Status: { switch (a_PacketType) { case 0x00: HandlePacketStatusRequest(a_ByteBuffer); return true; case 0x01: HandlePacketStatusPing(a_ByteBuffer); return true; } break; } case State::Login: { switch (a_PacketType) { case 0x00: HandlePacketLoginStart(a_ByteBuffer); return true; case 0x01: HandlePacketLoginEncryptionResponse(a_ByteBuffer); return true; } break; } case State::Game: { switch (a_PacketType) { case 0x00: HandleConfirmTeleport(a_ByteBuffer); return true; case 0x01: HandlePacketTabComplete(a_ByteBuffer); return true; case 0x02: HandlePacketChatMessage(a_ByteBuffer); return true; case 0x03: HandlePacketClientStatus(a_ByteBuffer); return true; case 0x04: HandlePacketClientSettings(a_ByteBuffer); return true; case 0x05: break; // Confirm transaction - not used in Cuberite case 0x06: HandlePacketEnchantItem(a_ByteBuffer); return true; case 0x07: HandlePacketWindowClick(a_ByteBuffer); return true; case 0x08: HandlePacketWindowClose(a_ByteBuffer); return true; case 0x09: HandlePacketPluginMessage(a_ByteBuffer); return true; case 0x0a: HandlePacketUseEntity(a_ByteBuffer); return true; case 0x0b: HandlePacketKeepAlive(a_ByteBuffer); return true; case 0x0c: HandlePacketPlayer(a_ByteBuffer); return true; case 0x0d: HandlePacketPlayerPos(a_ByteBuffer); return true; case 0x0e: HandlePacketPlayerPosLook(a_ByteBuffer); return true; case 0x0f: HandlePacketPlayerLook(a_ByteBuffer); return true; case 0x10: HandlePacketVehicleMove(a_ByteBuffer); return true; case 0x11: HandlePacketBoatSteer(a_ByteBuffer); return true; case 0x12: HandleCraftRecipe(a_ByteBuffer); return true; case 0x13: HandlePacketPlayerAbilities(a_ByteBuffer); return true; case 0x14: HandlePacketBlockDig(a_ByteBuffer); return true; case 0x15: HandlePacketEntityAction(a_ByteBuffer); return true; case 0x16: HandlePacketSteerVehicle(a_ByteBuffer); return true; case 0x17: HandlePacketCraftingBookData(a_ByteBuffer); return true; case 0x18: HandlePacketResourcePackStatus(a_ByteBuffer); return true; case 0x19: HandlePacketAdvancementTab(a_ByteBuffer); return true; case 0x1a: HandlePacketSlotSelect(a_ByteBuffer); return true; case 0x1b: HandlePacketCreativeInventoryAction(a_ByteBuffer); return true; case 0x1c: HandlePacketUpdateSign(a_ByteBuffer); return true; case 0x1d: HandlePacketAnimation(a_ByteBuffer); return true; case 0x1e: HandlePacketSpectate(a_ByteBuffer); return true; case 0x1f: HandlePacketBlockPlace(a_ByteBuffer); return true; case 0x20: HandlePacketUseItem(a_ByteBuffer); return true; } break; } } // switch (m_State) // Unknown packet type, report to the ClientHandle: m_Client->PacketUnknown(a_PacketType); return false; } //////////////////////////////////////////////////////////////////////////////// // cProtocol_1_12_2:: cProtocol::Version cProtocol_1_12_2::GetProtocolVersion() const { return Version::v1_12_2; } void cProtocol_1_12_2::HandlePacketKeepAlive(cByteBuffer & a_ByteBuffer) { HANDLE_READ(a_ByteBuffer, ReadBEInt64, Int64, KeepAliveID); if ( (KeepAliveID <= std::numeric_limits::max()) && (KeepAliveID >= 0) ) { // The server will only send a UInt32 so any value out of that range shouldn't keep the client alive. m_Client->HandleKeepAlive(static_cast(KeepAliveID)); } } void cProtocol_1_12_2::SendKeepAlive(UInt32 a_PingID) { // Drop the packet if the protocol is not in the Game state yet (caused a client crash): if (m_State != 3) { LOGWARNING("Trying to send a KeepAlive packet to a player who's not yet fully logged in (%d). The protocol class prevented the packet.", m_State); return; } cPacketizer Pkt(*this, pktKeepAlive); Pkt.WriteBEInt64(a_PingID); } void cProtocol_1_12_2::SendUnlockRecipe(UInt32 a_RecipeID) { ASSERT(m_State == 3); // In game mode? auto ProtocolRecipeId = cRoot::Get()->GetRecipeMapper()->GetProtocolRecipeId(a_RecipeID, m_Client->GetProtocolVersion()); if (ProtocolRecipeId.has_value()) { cPacketizer Pkt(*this, pktUnlockRecipe); Pkt.WriteVarInt32(1); Pkt.WriteBool(true); Pkt.WriteBool(false); Pkt.WriteVarInt32(1); Pkt.WriteVarInt32(ProtocolRecipeId.value()); } } void cProtocol_1_12_2::SendInitRecipes(UInt32 a_RecipeID) { ASSERT(m_State == 3); // In game mode? auto ProtocolRecipeId = cRoot::Get()->GetRecipeMapper()->GetProtocolRecipeId(a_RecipeID, m_Client->GetProtocolVersion()); if (!ProtocolRecipeId.has_value()) { return; } cPacketizer Pkt(*this, pktUnlockRecipe); Pkt.WriteVarInt32(0); Pkt.WriteBool(true); Pkt.WriteBool(false); if (a_RecipeID == 0) { Pkt.WriteVarInt32(0); Pkt.WriteVarInt32(0); } else { Pkt.WriteVarInt32(1); Pkt.WriteVarInt32(ProtocolRecipeId.value()); Pkt.WriteVarInt32(1); Pkt.WriteVarInt32(ProtocolRecipeId.value()); } } ================================================ FILE: src/Protocol/Protocol_1_12.h ================================================ // Protocol_1_12.h /* Declares the 1.12 protocol classes: - cProtocol_1_12 - release 1.12 protocol (#335) - cProtocol_1_12_1 - release 1.12.1 protocol (#338) - cProtocol_1_12_2 - release 1.12.2 protocol (#340) */ #pragma once #include "Protocol_1_11.h" #include "RecipeMapper.h" class cProtocol_1_12: public cProtocol_1_11_1 { using Super = cProtocol_1_11_1; public: using Super::Super; protected: virtual UInt32 GetPacketID(ePacketType a_Packet) const override; virtual signed char GetProtocolEntityStatus(EntityAnimation a_Animation) const override; virtual UInt32 GetProtocolMobType(eMonsterType a_MobType) const override; virtual Version GetProtocolVersion() const override; virtual bool HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType) override; virtual void HandlePacketAdvancementTab(cByteBuffer & a_ByteBuffer); virtual void HandleCraftRecipe(cByteBuffer & a_ByteBuffer); virtual void HandlePacketCraftingBookData(cByteBuffer & a_ByteBuffer); virtual void WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_Entity) const override; virtual void WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mob) const override; }; class cProtocol_1_12_1: public cProtocol_1_12 { using Super = cProtocol_1_12; public: using Super::Super; protected: virtual UInt32 GetPacketID(ePacketType a_Packet) const override; virtual Version GetProtocolVersion() const override; virtual bool HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType) override; }; class cProtocol_1_12_2: public cProtocol_1_12_1 { using Super = cProtocol_1_12_1; public: using Super::Super; protected: virtual Version GetProtocolVersion() const override; virtual void HandlePacketKeepAlive(cByteBuffer & a_ByteBuffer) override; virtual void SendKeepAlive(UInt32 a_PingID) override; virtual void SendUnlockRecipe(UInt32 a_RecipeID) override; virtual void SendInitRecipes(UInt32 a_RecipeID) override; }; ================================================ FILE: src/Protocol/Protocol_1_13.cpp ================================================ // Protocol_1_13.cpp /* Implements the 1.13 protocol classes: - release 1.13 protocol (#393) - release 1.13.1 protocol (#401) - release 1.13.2 protocol (#404) */ #include "Globals.h" #include "Protocol_1_13.h" #include "../Entities/Boat.h" #include "../Entities/EnderCrystal.h" #include "../Entities/Minecart.h" #include "../Entities/Pickup.h" #include "../Entities/Player.h" #include "../Entities/ItemFrame.h" #include "../Entities/ArrowEntity.h" #include "../Entities/FireworkEntity.h" #include "../Entities/SplashPotionEntity.h" #include "../Mobs/IncludeAllMonsters.h" #include "../CompositeChat.h" #include "../ClientHandle.h" #include "../Root.h" #include "../Server.h" #include "../World.h" #include "../JsonUtils.h" #include "../WorldStorage/FastNBT.h" #include "WorldStorage/NamespaceSerializer.h" #include "../Bindings/PluginManager.h" #include "Palettes/Palette_1_13.h" #include "Palettes/Palette_1_13_1.h" //////////////////////////////////////////////////////////////////////////////// // cProtocol_1_13: void cProtocol_1_13::SendBlockChange(Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) { cPacketizer Pkt(*this, pktBlockChange); Pkt.WriteXYZPosition64(a_BlockPos); Pkt.WriteVarInt32(GetProtocolBlockType(a_BlockType, a_BlockMeta)); } void cProtocol_1_13::SendBlockChanges(int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktBlockChanges); Pkt.WriteBEInt32(a_ChunkX); Pkt.WriteBEInt32(a_ChunkZ); Pkt.WriteVarInt32(static_cast(a_Changes.size())); for (const auto & Change : a_Changes) { Int16 Coords = static_cast(Change.m_RelY | (Change.m_RelZ << 8) | (Change.m_RelX << 12)); Pkt.WriteBEInt16(Coords); Pkt.WriteVarInt32(GetProtocolBlockType(Change.m_BlockType, Change.m_BlockMeta)); } } void cProtocol_1_13::SendMapData(const cMap & a_Map, int a_DataStartX, int a_DataStartY) { // TODO } void cProtocol_1_13::SendPaintingSpawn(const cPainting & a_Painting) { // TODO } void cProtocol_1_13::SendParticleEffect(const AString & a_ParticleName, Vector3f a_Src, Vector3f a_Offset, float a_ParticleData, int a_ParticleAmount, std::array a_Data) { // This packet is unchanged since 1.8 // However we are hardcoding a string-to-id mapping inside there // TODO: make a virtual enum-to-id mapping } void cProtocol_1_13::SendScoreboardObjective(const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) { // TODO } void cProtocol_1_13::SendStatistics(const StatisticsManager & a_Manager) { ASSERT(m_State == 3); // In game mode? UInt32 Size = 0; for (const auto & [Statistic, Value] : a_Manager.Custom) { // Client balks at out-of-range values so there is no good default value. // We're forced to not send the statistics this protocol version doesn't support. if (GetProtocolStatisticType(Statistic) != static_cast(-1)) { Size++; } } // No need to check Size != 0 // Assume that the vast majority of the time there's at least one statistic to send cPacketizer Pkt(*this, pktStatistics); Pkt.WriteVarInt32(Size); for (const auto & [Statistic, Value] : a_Manager.Custom) { const auto ID = GetProtocolStatisticType(Statistic); if (ID == static_cast(-1)) { // Unsupported, don't send: continue; } Pkt.WriteVarInt32(8); // "Custom" category. Pkt.WriteVarInt32(ID); Pkt.WriteVarInt32(static_cast(Value)); } } void cProtocol_1_13::SendTabCompletionResults(const AStringVector & a_Results) { // TODO } void cProtocol_1_13::SendUpdateBlockEntity(cBlockEntity & a_BlockEntity) { ASSERT(m_State == 3); // In game mode? Byte Action; switch (a_BlockEntity.GetBlockType()) { case E_BLOCK_CHEST: case E_BLOCK_ENCHANTMENT_TABLE: case E_BLOCK_END_PORTAL: case E_BLOCK_TRAPPED_CHEST: { // The ones with a action of 0 is just a workaround to send the block entities to a client. // Todo: 18.09.2020 - remove this when block entities are transmitted in the ChunkData packet - 12xx12 Action = 0; break; } case E_BLOCK_MOB_SPAWNER: Action = 1; break; // Update mob spawner spinny mob thing case E_BLOCK_COMMAND_BLOCK: Action = 2; break; // Update command block text case E_BLOCK_BEACON: Action = 3; break; // Update beacon entity case E_BLOCK_HEAD: Action = 4; break; // Update Mobhead entity // case E_BLOCK_CONDUIT: Action = 5; break; // Update Conduit entity case E_BLOCK_STANDING_BANNER: case E_BLOCK_WALL_BANNER: Action = 6; break; // Update banner entity // case Structure Block: Action = 7; break; // Update Structure tile entity case E_BLOCK_END_GATEWAY: Action = 8; break; // Update destination for a end gateway entity case E_BLOCK_SIGN_POST: Action = 9; break; // Update sign entity // case E_BLOCK_SHULKER_BOX: Action = 10; break; // sets shulker box - not used just here if anyone is confused from reading the protocol wiki case E_BLOCK_BED: Action = 11; break; // Update bed color default: return; // Block entities change between versions } cPacketizer Pkt(*this, pktUpdateBlockEntity); Pkt.WriteXYZPosition64(a_BlockEntity.GetPosX(), a_BlockEntity.GetPosY(), a_BlockEntity.GetPosZ()); Pkt.WriteBEUInt8(Action); cFastNBTWriter Writer; WriteBlockEntity(Writer, a_BlockEntity); Writer.Finish(); Pkt.WriteBuf(Writer.GetResult()); } UInt8 cProtocol_1_13::GetEntityMetadataID(EntityMetadata a_Metadata) const { const UInt8 Entity = 6; const UInt8 Living = Entity + 5; const UInt8 Insentient = Living + 1; const UInt8 Ageable = Insentient + 1; const UInt8 AbstractHorse = Ageable + 2; const UInt8 ChestedHorse = AbstractHorse + 1; const UInt8 TameableAnimal = Ageable + 2; const UInt8 Minecart = Entity + 6; switch (a_Metadata) { case EntityMetadata::EntityFlags: return 0; case EntityMetadata::EntityAir: return 1; case EntityMetadata::EntityCustomName: return 2; case EntityMetadata::EntityCustomNameVisible: return 3; case EntityMetadata::EntitySilent: return 4; case EntityMetadata::EntityNoGravity: return 5; case EntityMetadata::PotionThrown: return Entity; case EntityMetadata::FallingBlockPosition: return Entity; case EntityMetadata::AreaEffectCloudRadius: return Entity; case EntityMetadata::AreaEffectCloudColor: return Entity + 1; case EntityMetadata::AreaEffectCloudSinglePointEffect: return Entity + 2; case EntityMetadata::AreaEffectCloudParticleId: return Entity + 3; case EntityMetadata::ArrowFlags: return Entity; case EntityMetadata::TippedArrowColor: return Entity + 1; case EntityMetadata::BoatLastHitTime: return Entity; case EntityMetadata::BoatForwardDirection: return Entity + 1; case EntityMetadata::BoatDamageTaken: return Entity + 2; case EntityMetadata::BoatType: return Entity + 3; case EntityMetadata::BoatLeftPaddleTurning: return Entity + 4; case EntityMetadata::BoatRightPaddleTurning: return Entity + 5; case EntityMetadata::BoatSplashTimer: return Entity + 6; case EntityMetadata::EnderCrystalBeamTarget: return Entity; case EntityMetadata::EnderCrystalShowBottom: return Entity + 1; case EntityMetadata::WitherSkullInvulnerable: return Entity; case EntityMetadata::FireworkInfo: return Entity; case EntityMetadata::FireworkBoostedEntityId: return Entity + 1; case EntityMetadata::ItemFrameItem: return Entity; case EntityMetadata::ItemFrameRotation: return Entity + 1; case EntityMetadata::ItemItem: return Entity; case EntityMetadata::LivingActiveHand: return Entity; case EntityMetadata::LivingHealth: return Entity + 1; case EntityMetadata::LivingPotionEffectColor: return Entity + 2; case EntityMetadata::LivingPotionEffectAmbient: return Entity + 3; case EntityMetadata::LivingNumberOfArrows: return Entity + 4; case EntityMetadata::PlayerAdditionalHearts: return Living; case EntityMetadata::PlayerScore: return Living + 1; case EntityMetadata::PlayerDisplayedSkinParts: return Living + 2; case EntityMetadata::PlayerMainHand: return Living + 3; case EntityMetadata::ArmorStandStatus: return Living; case EntityMetadata::ArmorStandHeadRotation: return Living + 1; case EntityMetadata::ArmorStandBodyRotation: return Living + 2; case EntityMetadata::ArmorStandLeftArmRotation: return Living + 3; case EntityMetadata::ArmorStandRightArmRotation: return Living + 4; case EntityMetadata::ArmorStandLeftLegRotation: return Living + 5; case EntityMetadata::ArmorStandRightLegRotation: return Living + 6; case EntityMetadata::InsentientFlags: return Living; case EntityMetadata::BatHanging: return Insentient; case EntityMetadata::AgeableIsBaby: return Insentient; case EntityMetadata::AbstractHorseFlags: return Ageable; case EntityMetadata::AbstractHorseOwner: return Ageable + 1; case EntityMetadata::HorseVariant: return AbstractHorse; case EntityMetadata::HorseArmour: return AbstractHorse + 1; case EntityMetadata::ChestedHorseChested: return AbstractHorse; case EntityMetadata::LlamaStrength: return ChestedHorse; case EntityMetadata::LlamaCarpetColor: return ChestedHorse + 1; case EntityMetadata::LlamaVariant: return ChestedHorse + 2; case EntityMetadata::PigHasSaddle: return Ageable; case EntityMetadata::PigTotalCarrotOnAStickBoost: return Ageable + 1; case EntityMetadata::RabbitType: return Ageable; case EntityMetadata::PolarBearStanding: return Ageable; case EntityMetadata::SheepFlags: return Ageable; case EntityMetadata::TameableAnimalFlags: return Ageable; case EntityMetadata::TameableAnimalOwner: return Ageable + 1; case EntityMetadata::OcelotType: return TameableAnimal; case EntityMetadata::WolfDamageTaken: return TameableAnimal; case EntityMetadata::WolfBegging: return TameableAnimal + 1; case EntityMetadata::WolfCollarColour: return TameableAnimal + 2; case EntityMetadata::VillagerProfession: return Ageable; case EntityMetadata::IronGolemPlayerCreated: return Insentient; case EntityMetadata::ShulkerFacingDirection: return Insentient; case EntityMetadata::ShulkerAttachmentFallingBlockPosition: return Insentient + 1; case EntityMetadata::ShulkerShieldHeight: return Insentient + 2; case EntityMetadata::BlazeOnFire: return Insentient; case EntityMetadata::CreeperState: return Insentient; case EntityMetadata::CreeperPowered: return Insentient + 1; case EntityMetadata::CreeperIgnited: return Insentient + 2; case EntityMetadata::GuardianStatus: return Insentient; case EntityMetadata::GuardianTarget: return Insentient + 1; case EntityMetadata::IllagerFlags: return Insentient; case EntityMetadata::SpeIlagerSpell: return Insentient + 1; case EntityMetadata::VexFlags: return Insentient; case EntityMetadata::AbstractSkeletonArmsSwinging: return Insentient; case EntityMetadata::SpiderClimbing: return Insentient; case EntityMetadata::WitchAggresive: return Insentient; case EntityMetadata::WitherFirstHeadTarget: return Insentient; case EntityMetadata::WitherSecondHeadTarget: return Insentient + 1; case EntityMetadata::WitherThirdHeadTarget: return Insentient + 2; case EntityMetadata::WitherInvulnerableTimer: return Insentient + 3; case EntityMetadata::ZombieIsBaby: return Insentient; case EntityMetadata::ZombieHandsRisedUp: return Insentient + 2; case EntityMetadata::ZombieVillagerConverting: return Insentient + 4; case EntityMetadata::ZombieVillagerProfession: return Insentient + 5; case EntityMetadata::EndermanCarriedBlock: return Insentient; case EntityMetadata::EndermanScreaming: return Insentient + 1; case EntityMetadata::EnderDragonDragonPhase: return Insentient; case EntityMetadata::GhastAttacking: return Insentient; case EntityMetadata::SlimeSize: return Insentient; case EntityMetadata::MinecartShakingPower: return Entity; case EntityMetadata::MinecartShakingDirection: return Entity + 1; case EntityMetadata::MinecartShakingMultiplier: return Entity + 2; case EntityMetadata::MinecartBlockIDMeta: return Entity + 3; case EntityMetadata::MinecartBlockY: return Entity + 4; case EntityMetadata::MinecartShowBlock: return Entity + 5; case EntityMetadata::MinecartCommandBlockCommand: return Minecart; case EntityMetadata::MinecartCommandBlockLastOutput: return Minecart + 1; case EntityMetadata::MinecartFurnacePowered: return Minecart; case EntityMetadata::TNTPrimedFuseTime: return Entity; case EntityMetadata::EntityPose: case EntityMetadata::AreaEffectCloudParticleParameter1: case EntityMetadata::AreaEffectCloudParticleParameter2: case EntityMetadata::ZombieUnusedWasType: break; default: break; } UNREACHABLE("Retrieved invalid metadata for protocol"); } UInt8 cProtocol_1_13::GetEntityMetadataID(EntityMetadataType a_FieldType) const { switch (a_FieldType) { case EntityMetadataType::Byte: return 0; case EntityMetadataType::VarInt: return 1; case EntityMetadataType::Float: return 2; case EntityMetadataType::String: return 3; case EntityMetadataType::Chat: return 4; case EntityMetadataType::OptChat: return 5; case EntityMetadataType::Item: return 6; case EntityMetadataType::Boolean: return 7; case EntityMetadataType::Rotation: return 8; case EntityMetadataType::Position: return 9; case EntityMetadataType::OptPosition: return 10; case EntityMetadataType::Direction: return 11; case EntityMetadataType::OptUUID: return 12; case EntityMetadataType::OptBlockID: return 13; case EntityMetadataType::NBT: return 14; case EntityMetadataType::Particle: return 15; case EntityMetadataType::VillagerData: return 16; case EntityMetadataType::OptVarInt: return 17; case EntityMetadataType::Pose: return 18; } UNREACHABLE("Translated invalid metadata type for protocol"); } std::pair cProtocol_1_13::GetItemFromProtocolID(UInt32 a_ProtocolID) const { return PaletteUpgrade::ToItem(Palette_1_13::ToItem(a_ProtocolID)); } UInt32 cProtocol_1_13::GetPacketID(ePacketType a_PacketType) const { switch (a_PacketType) { case pktAttachEntity: return 0x46; case pktBlockChanges: return 0x0f; case pktCameraSetTo: return 0x3c; case pktChatRaw: return 0x0e; case pktCollectEntity: return 0x4f; case pktDestroyEntity: return 0x35; case pktDisconnectDuringGame: return 0x1b; case pktEditSign: return 0x2c; case pktEntityEffect: return 0x53; case pktEntityEquipment: return 0x42; case pktEntityHeadLook: return 0x39; case pktEntityLook: return 0x2a; case pktEntityMeta: return 0x3f; case pktEntityProperties: return 0x52; case pktEntityRelMove: return 0x28; case pktEntityRelMoveLook: return 0x29; case pktEntityStatus: return 0x1c; case pktEntityVelocity: return 0x41; case pktExperience: return 0x43; case pktExplosion: return 0x1e; case pktGameMode: return 0x20; case pktHeldItemChange: return 0x3d; case pktInventorySlot: return 0x17; case pktJoinGame: return 0x25; case pktKeepAlive: return 0x21; case pktLeashEntity: return 0x40; case pktMapData: return 0x26; case pktParticleEffect: return 0x24; case pktPlayerAbilities: return 0x2e; case pktPlayerList: return 0x30; case pktPlayerListHeaderFooter: return 0x4e; case pktPlayerMoveLook: return 0x32; case pktPluginMessage: return 0x19; case pktRemoveEntityEffect: return 0x36; case pktRespawn: return 0x38; case pktScoreboardObjective: return 0x45; case pktSoundEffect: return 0x1a; case pktSoundParticleEffect: return 0x23; case pktSpawnPosition: return 0x49; case pktTabCompletionResults: return 0x10; case pktTeleportEntity: return 0x50; case pktTimeUpdate: return 0x4a; case pktTitle: return 0x4b; case pktUnloadChunk: return 0x1f; case pktUnlockRecipe: return 0x32; case pktUpdateHealth: return 0x44; case pktUpdateScore: return 0x48; case pktUpdateSign: return GetPacketID(pktUpdateBlockEntity); case pktUseBed: return 0x33; case pktWeather: return 0x20; case pktWindowClose: return 0x13; case pktWindowItems: return 0x15; case pktWindowOpen: return 0x14; case pktWindowProperty: return 0x16; default: return Super::GetPacketID(a_PacketType); } } UInt32 cProtocol_1_13::GetProtocolBlockType(BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const { return Palette_1_13::From(PaletteUpgrade::FromBlock(a_BlockType, a_Meta)); } signed char cProtocol_1_13::GetProtocolEntityStatus(const EntityAnimation a_Animation) const { switch (a_Animation) { case EntityAnimation::DolphinShowsHappiness: return 38; default: return Super::GetProtocolEntityStatus(a_Animation); } } UInt32 cProtocol_1_13::GetProtocolItemType(short a_ItemID, short a_ItemDamage) const { return Palette_1_13::From(PaletteUpgrade::FromItem(a_ItemID, a_ItemDamage)); } UInt32 cProtocol_1_13::GetProtocolMobType(eMonsterType a_MobType) const { switch (a_MobType) { // Map invalid type to Giant for easy debugging (if this ever spawns, something has gone very wrong) case mtInvalidType: return 27; case mtBat: return 3; case mtCat: return 48; case mtBlaze: return 4; case mtCaveSpider: return 6; case mtChicken: return 7; case mtCod: return 8; case mtCow: return 9; case mtCreeper: return 10; case mtDonkey: return 11; case mtDolphin: return 12; case mtDrowned: return 14; case mtElderGuardian: return 15; case mtEnderDragon: return 17; case mtEnderman: return 18; case mtEndermite: return 19; case mtEvoker: return 21; case mtGhast: return 26; case mtGiant: return 27; case mtGuardian: return 28; case mtHorse: return 29; case mtHusk: return 30; case mtIllusioner: return 31; case mtIronGolem: return 80; case mtLlama: return 36; case mtMagmaCube: return 38; case mtMule: return 46; case mtMooshroom: return 47; case mtOcelot: return 48; case mtParrot: return 50; case mtPhantom: return 90; case mtPig: return 51; case mtPufferfish: return 52; case mtPolarBear: return 54; case mtRabbit: return 56; case mtSalmon: return 57; case mtSheep: return 58; case mtShulker: return 59; case mtSilverfish: return 61; case mtSkeleton: return 62; case mtSkeletonHorse: return 63; case mtSlime: return 64; case mtSnowGolem: return 66; case mtSpider: return 69; case mtSquid: return 70; case mtStray: return 71; case mtTropicalFish: return 72; case mtTurtle: return 73; case mtVex: return 78; case mtVillager: return 79; case mtVindicator: return 81; case mtWitch: return 82; case mtWither: return 83; case mtWitherSkeleton: return 84; case mtWolf: return 86; case mtZombie: return 87; case mtZombiePigman: return 53; case mtZombieHorse: return 88; case mtZombieVillager: return 89; default: return 0; } } UInt32 cProtocol_1_13::GetProtocolStatisticType(const CustomStatistic a_Statistic) const { return Palette_1_13::From(a_Statistic); } cProtocol::Version cProtocol_1_13::GetProtocolVersion() const { return Version::v1_13; } bool cProtocol_1_13::HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType) { if (m_State != 3) { return Super::HandlePacket(a_ByteBuffer, a_PacketType); } // Game switch (a_PacketType) { case 0x00: HandleConfirmTeleport(a_ByteBuffer); return true; case 0x05: HandlePacketTabComplete(a_ByteBuffer); return true; case 0x02: HandlePacketChatMessage(a_ByteBuffer); return true; case 0x03: HandlePacketClientStatus(a_ByteBuffer); return true; case 0x04: HandlePacketClientSettings(a_ByteBuffer); return true; case 0x06: break; // Confirm transaction - not used in Cuberite case 0x07: HandlePacketEnchantItem(a_ByteBuffer); return true; case 0x08: HandlePacketWindowClick(a_ByteBuffer); return true; case 0x09: HandlePacketWindowClose(a_ByteBuffer); return true; case 0x0a: HandlePacketPluginMessage(a_ByteBuffer); return true; case 0x0d: HandlePacketUseEntity(a_ByteBuffer); return true; case 0x0e: HandlePacketKeepAlive(a_ByteBuffer); return true; case 0x0f: HandlePacketPlayer(a_ByteBuffer); return true; case 0x10: HandlePacketPlayerPos(a_ByteBuffer); return true; case 0x11: HandlePacketPlayerPosLook(a_ByteBuffer); return true; case 0x12: HandlePacketPlayerLook(a_ByteBuffer); return true; case 0x13: HandlePacketVehicleMove(a_ByteBuffer); return true; case 0x14: HandlePacketBoatSteer(a_ByteBuffer); return true; case 0x15: break; // Pick item - not yet implemented case 0x16: break; // Craft Recipe Request - not yet implemented case 0x17: HandlePacketPlayerAbilities(a_ByteBuffer); return true; case 0x18: HandlePacketBlockDig(a_ByteBuffer); return true; case 0x19: HandlePacketEntityAction(a_ByteBuffer); return true; case 0x1a: HandlePacketSteerVehicle(a_ByteBuffer); return true; case 0x1b: HandlePacketCraftingBookData(a_ByteBuffer); return true; case 0x1c: HandlePacketNameItem(a_ByteBuffer); return true; case 0x1d: break; // Resource pack status - not yet implemented case 0x1e: HandlePacketAdvancementTab(a_ByteBuffer); return true; case 0x20: HandlePacketSetBeaconEffect(a_ByteBuffer); return true; case 0x21: HandlePacketSlotSelect(a_ByteBuffer); return true; case 0x24: HandlePacketCreativeInventoryAction(a_ByteBuffer); return true; case 0x26: HandlePacketUpdateSign(a_ByteBuffer); return true; case 0x27: HandlePacketAnimation(a_ByteBuffer); return true; case 0x28: HandlePacketSpectate(a_ByteBuffer); return true; case 0x29: HandlePacketBlockPlace(a_ByteBuffer); return true; case 0x2a: HandlePacketUseItem(a_ByteBuffer); return true; } return Super::HandlePacket(a_ByteBuffer, a_PacketType); } void cProtocol_1_13::HandlePacketNameItem(cByteBuffer & a_ByteBuffer) { HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, NewItemName); LOGD("New item name : %s", NewItemName); } void cProtocol_1_13::HandlePacketPluginMessage(cByteBuffer & a_ByteBuffer) { HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, NamespacedChannel); const auto & [Namespace, Channel] = NamespaceSerializer::SplitNamespacedID(NamespacedChannel); // If the plugin channel is recognized vanilla, handle it directly: if (Namespace == NamespaceSerializer::Namespace::Minecraft) { HandleVanillaPluginMessage(a_ByteBuffer, Channel); return; } ContiguousByteBuffer Data; // Read the plugin message and relay to clienthandle: a_ByteBuffer.ReadSome(Data, a_ByteBuffer.GetReadableSpace()); m_Client->HandlePluginMessage(NamespacedChannel, Data); } void cProtocol_1_13::HandlePacketSetBeaconEffect(cByteBuffer & a_ByteBuffer) { HANDLE_READ(a_ByteBuffer, ReadVarInt32, UInt32, Effect1); HANDLE_READ(a_ByteBuffer, ReadVarInt32, UInt32, Effect2); m_Client->HandleBeaconSelection(Effect1, Effect2); } void cProtocol_1_13::HandleVanillaPluginMessage(cByteBuffer & a_ByteBuffer, const std::string_view a_Channel) { if (a_Channel == "brand") { HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Brand); m_Client->SetClientBrand(Brand); m_Client->SendPluginMessage("brand", "\x08""Cuberite"); // Send back our brand, including the length. } } bool cProtocol_1_13::ReadItem(cByteBuffer & a_ByteBuffer, cItem & a_Item, size_t a_KeepRemainingBytes) const { HANDLE_PACKET_READ(a_ByteBuffer, ReadBEInt16, Int16, ItemID); if (ItemID == -1) { // The item is empty, no more data follows a_Item.Empty(); return true; } const auto Translated = GetItemFromProtocolID(ToUnsigned(ItemID)); a_Item.m_ItemType = Translated.first; a_Item.m_ItemDamage = Translated.second; HANDLE_PACKET_READ(a_ByteBuffer, ReadBEInt8, Int8, ItemCount); a_Item.m_ItemCount = ItemCount; if (ItemCount <= 0) { a_Item.Empty(); } ContiguousByteBuffer Metadata; if (!a_ByteBuffer.ReadSome(Metadata, a_ByteBuffer.GetReadableSpace() - a_KeepRemainingBytes) || Metadata.empty() || (Metadata[0] == std::byte(0))) { // No metadata return true; } ParseItemMetadata(a_Item, Metadata); return true; } void cProtocol_1_13::WriteEntityMetadata(cPacketizer & a_Pkt, const EntityMetadata a_Metadata, const EntityMetadataType a_FieldType) const { a_Pkt.WriteBEUInt8(GetEntityMetadataID(a_Metadata)); // Index a_Pkt.WriteBEUInt8(GetEntityMetadataID(a_FieldType)); // Type } void cProtocol_1_13::WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_Entity) const { // Common metadata: Int8 Flags = 0; if (a_Entity.IsOnFire()) { Flags |= 0x01; } if (a_Entity.IsCrouched()) { Flags |= 0x02; } if (a_Entity.IsSprinting()) { Flags |= 0x08; } if (a_Entity.IsRclking()) { Flags |= 0x10; } if (a_Entity.IsInvisible()) { Flags |= 0x20; } WriteEntityMetadata(a_Pkt, EntityMetadata::EntityFlags, EntityMetadataType::Byte); a_Pkt.WriteBEInt8(Flags); switch (a_Entity.GetEntityType()) { case cEntity::etPlayer: { auto & Player = static_cast(a_Entity); // TODO Set player custom name to their name. // Then it's possible to move the custom name of mobs to the entities // and to remove the "special" player custom name. WriteEntityMetadata(a_Pkt, EntityMetadata::EntityCustomName, EntityMetadataType::String); a_Pkt.WriteString(Player.GetName()); WriteEntityMetadata(a_Pkt, EntityMetadata::LivingHealth, EntityMetadataType::Float); a_Pkt.WriteBEFloat(static_cast(Player.GetHealth())); WriteEntityMetadata(a_Pkt, EntityMetadata::PlayerDisplayedSkinParts, EntityMetadataType::Byte); a_Pkt.WriteBEUInt8(static_cast(Player.GetSkinParts())); WriteEntityMetadata(a_Pkt, EntityMetadata::PlayerMainHand, EntityMetadataType::Byte); a_Pkt.WriteBEUInt8(Player.IsLeftHanded() ? 0 : 1); break; } case cEntity::etPickup: { WriteEntityMetadata(a_Pkt, EntityMetadata::ItemItem, EntityMetadataType::Item); WriteItem(a_Pkt, static_cast(a_Entity).GetItem()); break; } case cEntity::etMinecart: { WriteEntityMetadata(a_Pkt, EntityMetadata::MinecartShakingPower, EntityMetadataType::VarInt); // The following expression makes Minecarts shake more with less health or higher damage taken auto & Minecart = static_cast(a_Entity); auto maxHealth = a_Entity.GetMaxHealth(); auto curHealth = a_Entity.GetHealth(); a_Pkt.WriteVarInt32(static_cast((maxHealth - curHealth) * Minecart.LastDamage() * 4)); WriteEntityMetadata(a_Pkt, EntityMetadata::MinecartShakingDirection, EntityMetadataType::VarInt); a_Pkt.WriteVarInt32(1); // (doesn't seem to effect anything) WriteEntityMetadata(a_Pkt, EntityMetadata::MinecartShakingMultiplier, EntityMetadataType::Float); a_Pkt.WriteBEFloat(static_cast(Minecart.LastDamage() + 10)); // or damage taken if (Minecart.GetPayload() == cMinecart::mpNone) { auto & RideableMinecart = static_cast(Minecart); const cItem & MinecartContent = RideableMinecart.GetContent(); if (!MinecartContent.IsEmpty()) { WriteEntityMetadata(a_Pkt, EntityMetadata::MinecartBlockIDMeta, EntityMetadataType::VarInt); int Content = MinecartContent.m_ItemType; Content |= MinecartContent.m_ItemDamage << 8; a_Pkt.WriteVarInt32(static_cast(Content)); WriteEntityMetadata(a_Pkt, EntityMetadata::MinecartBlockY, EntityMetadataType::VarInt); a_Pkt.WriteVarInt32(static_cast(RideableMinecart.GetBlockHeight())); WriteEntityMetadata(a_Pkt, EntityMetadata::MinecartShowBlock, EntityMetadataType::Boolean); a_Pkt.WriteBool(true); } } else if (Minecart.GetPayload() == cMinecart::mpFurnace) { WriteEntityMetadata(a_Pkt, EntityMetadata::MinecartFurnacePowered, EntityMetadataType::Boolean); a_Pkt.WriteBool(static_cast(Minecart).IsFueled()); } break; } // case etMinecart case cEntity::etProjectile: { auto & Projectile = static_cast(a_Entity); switch (Projectile.GetProjectileKind()) { case cProjectileEntity::pkArrow: { WriteEntityMetadata(a_Pkt, EntityMetadata::ArrowFlags, EntityMetadataType::Byte); a_Pkt.WriteBEInt8(static_cast(Projectile).IsCritical() ? 1 : 0); break; } case cProjectileEntity::pkFirework: { // TODO break; } case cProjectileEntity::pkSplashPotion: { // TODO } default: { break; } } break; } // case etProjectile case cEntity::etMonster: { WriteMobMetadata(a_Pkt, static_cast(a_Entity)); break; } case cEntity::etBoat: { auto & Boat = static_cast(a_Entity); WriteEntityMetadata(a_Pkt, EntityMetadata::BoatLastHitTime, EntityMetadataType::VarInt); a_Pkt.WriteVarInt32(static_cast(Boat.GetLastDamage())); WriteEntityMetadata(a_Pkt, EntityMetadata::BoatForwardDirection, EntityMetadataType::VarInt); a_Pkt.WriteVarInt32(static_cast(Boat.GetForwardDirection())); WriteEntityMetadata(a_Pkt, EntityMetadata::BoatDamageTaken, EntityMetadataType::Float); a_Pkt.WriteBEFloat(Boat.GetDamageTaken()); WriteEntityMetadata(a_Pkt, EntityMetadata::BoatType, EntityMetadataType::VarInt); a_Pkt.WriteVarInt32(static_cast(Boat.GetMaterial())); WriteEntityMetadata(a_Pkt, EntityMetadata::BoatRightPaddleTurning, EntityMetadataType::Boolean); a_Pkt.WriteBool(Boat.IsRightPaddleUsed()); WriteEntityMetadata(a_Pkt, EntityMetadata::BoatLeftPaddleTurning, EntityMetadataType::Boolean); a_Pkt.WriteBool(static_cast(Boat.IsLeftPaddleUsed())); WriteEntityMetadata(a_Pkt, EntityMetadata::BoatSplashTimer, EntityMetadataType::VarInt); a_Pkt.WriteVarInt32(0); break; } // case etBoat case cEntity::etItemFrame: { const auto & Frame = static_cast(a_Entity); WriteEntityMetadata(a_Pkt, EntityMetadata::ItemFrameItem, EntityMetadataType::Item); WriteItem(a_Pkt, Frame.GetItem()); WriteEntityMetadata(a_Pkt, EntityMetadata::ItemFrameRotation, EntityMetadataType::VarInt); a_Pkt.WriteVarInt32(Frame.GetItemRotation()); break; } // case etItemFrame case cEntity::etEnderCrystal: { const auto & EnderCrystal = static_cast(a_Entity); if (EnderCrystal.DisplaysBeam()) { WriteEntityMetadata(a_Pkt, EntityMetadata::EnderCrystalBeamTarget, EntityMetadataType::OptPosition); a_Pkt.WriteBool(true); // Dont do a second check if it should display the beam a_Pkt.WriteXYZPosition64(EnderCrystal.GetBeamTarget()); } WriteEntityMetadata(a_Pkt, EntityMetadata::EnderCrystalShowBottom, EntityMetadataType::Boolean); a_Pkt.WriteBool(EnderCrystal.ShowsBottom()); break; } // case etEnderCrystal default: { break; } } } void cProtocol_1_13::WriteItem(cPacketizer & a_Pkt, const cItem & a_Item) const { short ItemType = a_Item.m_ItemType; ASSERT(ItemType >= -1); // Check validity of packets in debug runtime if (ItemType <= 0) { // Fix, to make sure no invalid values are sent. ItemType = -1; } if (a_Item.IsEmpty()) { a_Pkt.WriteBEInt16(-1); return; } // Normal item a_Pkt.WriteBEInt16(static_cast(GetProtocolItemType(a_Item.m_ItemType, a_Item.m_ItemDamage))); a_Pkt.WriteBEInt8(a_Item.m_ItemCount); // TODO: NBT a_Pkt.WriteBEInt8(0); } void cProtocol_1_13::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mob) const { // Living Enitiy Metadata if (a_Mob.HasCustomName()) { // TODO: As of 1.9 _all_ entities can have custom names; should this be moved up? WriteEntityMetadata(a_Pkt, EntityMetadata::EntityCustomName, EntityMetadataType::OptChat); a_Pkt.WriteBool(true); a_Pkt.WriteString(a_Mob.GetCustomName()); WriteEntityMetadata(a_Pkt, EntityMetadata::EntityCustomNameVisible, EntityMetadataType::Boolean); a_Pkt.WriteBool(a_Mob.IsCustomNameAlwaysVisible()); } WriteEntityMetadata(a_Pkt, EntityMetadata::LivingHealth, EntityMetadataType::Float); a_Pkt.WriteBEFloat(static_cast(a_Mob.GetHealth())); switch (a_Mob.GetMobType()) { case mtBat: { auto & Bat = static_cast(a_Mob); WriteEntityMetadata(a_Pkt, EntityMetadata::BatHanging, EntityMetadataType::Byte); a_Pkt.WriteBEInt8(Bat.IsHanging() ? 1 : 0); break; } // case mtBat case mtChicken: { auto & Chicken = static_cast(a_Mob); WriteEntityMetadata(a_Pkt, EntityMetadata::AgeableIsBaby, EntityMetadataType::Boolean); a_Pkt.WriteBool(Chicken.IsBaby()); break; } // case mtChicken case mtCow: { auto & Cow = static_cast(a_Mob); WriteEntityMetadata(a_Pkt, EntityMetadata::AgeableIsBaby, EntityMetadataType::Boolean); a_Pkt.WriteBool(Cow.IsBaby()); break; } // case mtCow case mtCreeper: { auto & Creeper = static_cast(a_Mob); WriteEntityMetadata(a_Pkt, EntityMetadata::CreeperState, EntityMetadataType::VarInt); a_Pkt.WriteVarInt32(Creeper.IsBlowing() ? 1 : static_cast(-1)); // (idle or "blowing") WriteEntityMetadata(a_Pkt, EntityMetadata::CreeperPowered, EntityMetadataType::Boolean); a_Pkt.WriteBool(Creeper.IsCharged()); WriteEntityMetadata(a_Pkt, EntityMetadata::CreeperIgnited, EntityMetadataType::Boolean); a_Pkt.WriteBool(Creeper.IsBurnedWithFlintAndSteel()); break; } // case mtCreeper case mtEnderman: { auto & Enderman = static_cast(a_Mob); WriteEntityMetadata(a_Pkt, EntityMetadata::EndermanCarriedBlock, EntityMetadataType::OptBlockID); UInt32 Carried = 0; Carried |= static_cast(Enderman.GetCarriedBlock() << 4); Carried |= Enderman.GetCarriedMeta(); a_Pkt.WriteVarInt32(Carried); WriteEntityMetadata(a_Pkt, EntityMetadata::EndermanScreaming, EntityMetadataType::Boolean); a_Pkt.WriteBool(Enderman.IsScreaming()); break; } // case mtEnderman case mtGhast: { auto & Ghast = static_cast(a_Mob); WriteEntityMetadata(a_Pkt, EntityMetadata::GhastAttacking, EntityMetadataType::Boolean); a_Pkt.WriteBool(Ghast.IsCharging()); break; } // case mtGhast case mtHorse: { // XXX This behaves incorrectly with different varients; horses have different entity IDs now // Abstract horse auto & Horse = static_cast(a_Mob); Int8 Flags = 0; if (Horse.IsTame()) { Flags |= 0x02; } if (Horse.IsSaddled()) { Flags |= 0x04; } if (Horse.IsInLoveCooldown()) { Flags |= 0x08; } if (Horse.IsEating()) { Flags |= 0x10; } if (Horse.IsRearing()) { Flags |= 0x20; } if (Horse.IsMthOpen()) { Flags |= 0x40; } WriteEntityMetadata(a_Pkt, EntityMetadata::AbstractHorseFlags, EntityMetadataType::Byte); a_Pkt.WriteBEInt8(Flags); // Regular horses int Appearance = 0; Appearance = Horse.GetHorseColor(); Appearance |= Horse.GetHorseStyle() << 8; WriteEntityMetadata(a_Pkt, EntityMetadata::HorseVariant, EntityMetadataType::VarInt); a_Pkt.WriteVarInt32(static_cast(Appearance)); // Color / style WriteEntityMetadata(a_Pkt, EntityMetadata::HorseArmour, EntityMetadataType::VarInt); a_Pkt.WriteVarInt32(static_cast(Horse.GetHorseArmour())); WriteEntityMetadata(a_Pkt, EntityMetadata::AgeableIsBaby, EntityMetadataType::Boolean); a_Pkt.WriteBool(Horse.IsBaby()); break; } // case mtHorse case mtMagmaCube: { auto & MagmaCube = static_cast(a_Mob); WriteEntityMetadata(a_Pkt, EntityMetadata::SlimeSize, EntityMetadataType::VarInt); a_Pkt.WriteVarInt32(static_cast(MagmaCube.GetSize())); break; } // case mtMagmaCube case mtOcelot: { auto & Ocelot = static_cast(a_Mob); WriteEntityMetadata(a_Pkt, EntityMetadata::AgeableIsBaby, EntityMetadataType::Boolean); a_Pkt.WriteBool(Ocelot.IsBaby()); Int8 OcelotStatus = 0; if (Ocelot.IsSitting()) { OcelotStatus |= 0x1; } if (Ocelot.IsTame()) { OcelotStatus |= 0x4; } WriteEntityMetadata(a_Pkt, EntityMetadata::TameableAnimalFlags, EntityMetadataType::Byte); a_Pkt.WriteBEInt8(OcelotStatus); WriteEntityMetadata(a_Pkt, EntityMetadata::OcelotType, EntityMetadataType::Byte); a_Pkt.WriteVarInt32(static_cast(Ocelot.GetOcelotType())); break; } // case mtOcelot case mtPig: { auto & Pig = static_cast(a_Mob); WriteEntityMetadata(a_Pkt, EntityMetadata::AgeableIsBaby, EntityMetadataType::Boolean); a_Pkt.WriteBool(Pig.IsBaby()); WriteEntityMetadata(a_Pkt, EntityMetadata::PigHasSaddle, EntityMetadataType::Boolean); a_Pkt.WriteBool(Pig.IsSaddled()); // PIG_TOTAL_CARROT_ON_A_STICK_BOOST in 1.11.1 only break; } // case mtPig case mtRabbit: { auto & Rabbit = static_cast(a_Mob); WriteEntityMetadata(a_Pkt, EntityMetadata::AgeableIsBaby, EntityMetadataType::Boolean); a_Pkt.WriteBool(Rabbit.IsBaby()); WriteEntityMetadata(a_Pkt, EntityMetadata::RabbitType, EntityMetadataType::VarInt); a_Pkt.WriteVarInt32(static_cast(Rabbit.GetRabbitType())); break; } // case mtRabbit case mtSheep: { auto & Sheep = static_cast(a_Mob); WriteEntityMetadata(a_Pkt, EntityMetadata::AgeableIsBaby, EntityMetadataType::Boolean); a_Pkt.WriteBool(Sheep.IsBaby()); Int8 SheepMetadata = 0; SheepMetadata = static_cast(Sheep.GetFurColor()); if (Sheep.IsSheared()) { SheepMetadata |= 0x10; } WriteEntityMetadata(a_Pkt, EntityMetadata::SheepFlags, EntityMetadataType::Byte); a_Pkt.WriteBEInt8(SheepMetadata); break; } // case mtSheep case mtSkeleton: { auto & Skeleton = static_cast(a_Mob); WriteEntityMetadata(a_Pkt, EntityMetadata::LivingActiveHand, EntityMetadataType::Byte); a_Pkt.WriteBEUInt8(Skeleton.IsChargingBow() ? 0x01 : 0x00); WriteEntityMetadata(a_Pkt, EntityMetadata::AbstractSkeletonArmsSwinging, EntityMetadataType::Boolean); a_Pkt.WriteBool(Skeleton.IsChargingBow()); break; } // case mtSkeleton case mtSlime: { auto & Slime = static_cast(a_Mob); WriteEntityMetadata(a_Pkt, EntityMetadata::SlimeSize, EntityMetadataType::VarInt); a_Pkt.WriteVarInt32(static_cast(Slime.GetSize())); break; } // case mtSlime case mtVillager: { auto & Villager = static_cast(a_Mob); WriteEntityMetadata(a_Pkt, EntityMetadata::AgeableIsBaby, EntityMetadataType::Boolean); a_Pkt.WriteBool(Villager.IsBaby()); WriteEntityMetadata(a_Pkt, EntityMetadata::VillagerProfession, EntityMetadataType::VarInt); a_Pkt.WriteVarInt32(static_cast(Villager.GetVilType())); break; } // case mtVillager case mtWitch: { auto & Witch = static_cast(a_Mob); WriteEntityMetadata(a_Pkt, EntityMetadata::WitchAggresive, EntityMetadataType::Boolean); a_Pkt.WriteBool(Witch.IsAngry()); break; } // case mtWitch case mtWither: { auto & Wither = static_cast(a_Mob); WriteEntityMetadata(a_Pkt, EntityMetadata::WitherInvulnerableTimer, EntityMetadataType::VarInt); a_Pkt.WriteVarInt32(Wither.GetWitherInvulnerableTicks()); // TODO: Use boss bar packet for health break; } // case mtWither case mtWolf: { auto & Wolf = static_cast(a_Mob); WriteEntityMetadata(a_Pkt, EntityMetadata::AgeableIsBaby, EntityMetadataType::Boolean); a_Pkt.WriteBool(Wolf.IsBaby()); Int8 WolfStatus = 0; if (Wolf.IsSitting()) { WolfStatus |= 0x1; } if (Wolf.IsAngry()) { WolfStatus |= 0x2; } if (Wolf.IsTame()) { WolfStatus |= 0x4; } WriteEntityMetadata(a_Pkt, EntityMetadata::TameableAnimalFlags, EntityMetadataType::Byte); a_Pkt.WriteBEInt8(WolfStatus); WriteEntityMetadata(a_Pkt, EntityMetadata::WolfDamageTaken, EntityMetadataType::Float); a_Pkt.WriteBEFloat(static_cast(a_Mob.GetHealth())); // TODO Not use the current health WriteEntityMetadata(a_Pkt, EntityMetadata::WolfBegging, EntityMetadataType::Boolean); a_Pkt.WriteBool(Wolf.IsBegging()); WriteEntityMetadata(a_Pkt, EntityMetadata::WolfCollarColour, EntityMetadataType::VarInt); a_Pkt.WriteVarInt32(static_cast(Wolf.GetCollarColor())); break; } // case mtWolf case mtZombie: { // XXX Zombies were also split into new sublcasses; this doesn't handle that. auto & Zombie = static_cast(a_Mob); WriteEntityMetadata(a_Pkt, EntityMetadata::ZombieIsBaby, EntityMetadataType::Boolean); a_Pkt.WriteBool(Zombie.IsBaby()); break; } // case mtZombie case mtZombiePigman: { auto & ZombiePigman = static_cast(a_Mob); WriteEntityMetadata(a_Pkt, EntityMetadata::AgeableIsBaby, EntityMetadataType::Boolean); a_Pkt.WriteBool(ZombiePigman.IsBaby()); break; } // case mtZombiePigman case mtBlaze: case mtEnderDragon: case mtIronGolem: case mtSnowGolem: case mtSpider: case mtZombieVillager: case mtElderGuardian: case mtGuardian: { // TODO: Mobs with extra fields that aren't implemented break; } case mtCat: case mtCod: case mtDolphin: case mtDonkey: case mtDrowned: case mtEvoker: case mtIllusioner: case mtLlama: case mtMule: case mtParrot: case mtPhantom: case mtPolarBear: case mtPufferfish: case mtSalmon: case mtShulker: case mtStray: case mtSkeletonHorse: case mtZombieHorse: case mtTropicalFish: case mtTurtle: case mtVex: case mtVindicator: case mtHusk: { // Todo: Mobs not added yet. Grouped ones have the same metadata ASSERT(!"cProtocol_1_13::WriteMobMetadata: received unimplemented type"); break; } case mtMooshroom: case mtCaveSpider: { // Not mentioned on http://wiki.vg/Entities break; } case mtEndermite: case mtGiant: case mtSilverfish: case mtSquid: case mtWitherSkeleton: { // Mobs with no extra fields break; } default: UNREACHABLE("cProtocol_1_13::WriteMobMetadata: received mob of invalid type"); } // switch (a_Mob.GetType()) } //////////////////////////////////////////////////////////////////////////////// // cProtocol_1_13_1: void cProtocol_1_13_1::SendBossBarAdd(UInt32 a_UniqueID, const cCompositeChat & a_Title, float a_FractionFilled, BossBarColor a_Color, BossBarDivisionType a_DivisionType, bool a_DarkenSky, bool a_PlayEndMusic, bool a_CreateFog) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktBossBar); // TODO: Bad way to write a UUID, and it's not a true UUID, but this is functional for now. Pkt.WriteBEUInt64(0); Pkt.WriteBEUInt64(a_UniqueID); Pkt.WriteVarInt32(0); // Add Pkt.WriteString(a_Title.CreateJsonString()); Pkt.WriteBEFloat(a_FractionFilled); Pkt.WriteVarInt32([a_Color] { switch (a_Color) { case BossBarColor::Pink: return 0U; case BossBarColor::Blue: return 1U; case BossBarColor::Red: return 2U; case BossBarColor::Green: return 3U; case BossBarColor::Yellow: return 4U; case BossBarColor::Purple: return 5U; case BossBarColor::White: return 6U; } UNREACHABLE("Unsupported boss bar property"); }()); Pkt.WriteVarInt32([a_DivisionType] { switch (a_DivisionType) { case BossBarDivisionType::None: return 0U; case BossBarDivisionType::SixNotches: return 1U; case BossBarDivisionType::TenNotches: return 2U; case BossBarDivisionType::TwelveNotches: return 3U; case BossBarDivisionType::TwentyNotches: return 4U; } UNREACHABLE("Unsupported boss bar property"); }()); { UInt8 Flags = 0x00; if (a_DarkenSky) { Flags |= 0x01; } if (a_PlayEndMusic) { Flags |= 0x02; } if (a_CreateFog) { Flags |= 0x04; // Only difference to 1.9 is fog now a separate flag } Pkt.WriteBEUInt8(Flags); } } void cProtocol_1_13_1::SendBossBarUpdateFlags(UInt32 a_UniqueID, bool a_DarkenSky, bool a_PlayEndMusic, bool a_CreateFog) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktBossBar); // TODO: Bad way to write a UUID, and it's not a true UUID, but this is functional for now. Pkt.WriteBEUInt64(0); Pkt.WriteBEUInt64(a_UniqueID); Pkt.WriteVarInt32(5); // Update Flags { UInt8 Flags = 0x00; if (a_DarkenSky) { Flags |= 0x01; } if (a_PlayEndMusic) { Flags |= 0x02; } if (a_CreateFog) { Flags |= 0x04; // Only difference to 1.9 is fog now a separate flag } Pkt.WriteBEUInt8(Flags); } } std::pair cProtocol_1_13_1::GetItemFromProtocolID(UInt32 a_ProtocolID) const { return PaletteUpgrade::ToItem(Palette_1_13_1::ToItem(a_ProtocolID)); } UInt32 cProtocol_1_13_1::GetProtocolBlockType(BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const { return Palette_1_13_1::From(PaletteUpgrade::FromBlock(a_BlockType, a_Meta)); } UInt32 cProtocol_1_13_1::GetProtocolItemType(short a_ItemID, short a_ItemDamage) const { return Palette_1_13_1::From(PaletteUpgrade::FromItem(a_ItemID, a_ItemDamage)); } UInt32 cProtocol_1_13_1::GetProtocolStatisticType(const CustomStatistic a_Statistic) const { return Palette_1_13_1::From(a_Statistic); } cProtocol::Version cProtocol_1_13_1::GetProtocolVersion() const { return Version::v1_13_1; } //////////////////////////////////////////////////////////////////////////////// // cProtocol_1_13_2: cProtocol::Version cProtocol_1_13_2::GetProtocolVersion() const { return Version::v1_13_2; } bool cProtocol_1_13_2::ReadItem(cByteBuffer & a_ByteBuffer, cItem & a_Item, size_t a_KeepRemainingBytes) const { HANDLE_PACKET_READ(a_ByteBuffer, ReadBool, bool, Present); if (!Present) { // The item is empty, no more data follows a_Item.Empty(); return true; } HANDLE_PACKET_READ(a_ByteBuffer, ReadVarInt32, UInt32, ItemID); const auto Translated = GetItemFromProtocolID(ItemID); a_Item.m_ItemType = Translated.first; a_Item.m_ItemDamage = Translated.second; HANDLE_PACKET_READ(a_ByteBuffer, ReadBEInt8, Int8, ItemCount); a_Item.m_ItemCount = ItemCount; if (ItemCount <= 0) { a_Item.Empty(); } ContiguousByteBuffer Metadata; if (!a_ByteBuffer.ReadSome(Metadata, a_ByteBuffer.GetReadableSpace() - a_KeepRemainingBytes) || Metadata.empty() || (Metadata[0] == std::byte(0))) { // No metadata return true; } ParseItemMetadata(a_Item, Metadata); return true; } void cProtocol_1_13_2::WriteItem(cPacketizer & a_Pkt, const cItem & a_Item) const { short ItemType = a_Item.m_ItemType; ASSERT(ItemType >= -1); // Check validity of packets in debug runtime if (ItemType <= 0) { // Fix, to make sure no invalid values are sent. ItemType = -1; } if (a_Item.IsEmpty()) { a_Pkt.WriteBool(false); return; } // Item present a_Pkt.WriteBool(true); // Normal item a_Pkt.WriteVarInt32(GetProtocolItemType(a_Item.m_ItemType, a_Item.m_ItemDamage)); a_Pkt.WriteBEInt8(a_Item.m_ItemCount); // TODO: NBT a_Pkt.WriteBEInt8(0); } ================================================ FILE: src/Protocol/Protocol_1_13.h ================================================ // Protocol_1_13.h /* Declares the 1.13 protocol classes: - cProtocol_1_13 - release 1.13 protocol (#393) - cProtocol_1_13_1 - release 1.13.1 protocol (#401) - cProtocol_1_13_2 - release 1.13.2 protocol (#404) */ #pragma once #include "Protocol_1_12.h" #include "Packetizer.h" #include "Palettes/Upgrade.h" class cProtocol_1_13: public cProtocol_1_12_2 { using Super = cProtocol_1_12_2; public: using Super::Super; protected: virtual void SendBlockChange (Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override; virtual void SendBlockChanges (int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes) override; virtual void SendMapData (const cMap & a_Map, int a_DataStartX, int a_DataStartY) override; virtual void SendPaintingSpawn (const cPainting & a_Painting) override; virtual void SendParticleEffect (const AString & a_ParticleName, Vector3f a_Src, Vector3f a_Offset, float a_ParticleData, int a_ParticleAmount, std::array a_Data) override; virtual void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) override; virtual void SendStatistics (const StatisticsManager & a_Manager) override; virtual void SendTabCompletionResults (const AStringVector & a_Results) override; virtual void SendUpdateBlockEntity (cBlockEntity & a_BlockEntity) override; virtual UInt8 GetEntityMetadataID(EntityMetadata a_Metadata) const; virtual UInt8 GetEntityMetadataID(EntityMetadataType a_FieldType) const; virtual std::pair GetItemFromProtocolID(UInt32 a_ProtocolID) const; virtual UInt32 GetPacketID(ePacketType a_PacketType) const override; virtual UInt32 GetProtocolBlockType(BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const; virtual signed char GetProtocolEntityStatus(EntityAnimation a_Animation) const override; virtual UInt32 GetProtocolItemType(short a_ItemID, short a_ItemDamage) const; virtual UInt32 GetProtocolMobType(eMonsterType a_MobType) const override; virtual UInt32 GetProtocolStatisticType(CustomStatistic a_Statistic) const; virtual Version GetProtocolVersion() const override; virtual bool HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType) override; virtual void HandlePacketNameItem(cByteBuffer & a_ByteBuffer); virtual void HandlePacketPluginMessage(cByteBuffer & a_ByteBuffer) override; virtual void HandlePacketSetBeaconEffect(cByteBuffer & a_ByteBuffer); virtual void HandleVanillaPluginMessage(cByteBuffer & a_ByteBuffer, std::string_view a_Channel) override; virtual bool ReadItem(cByteBuffer & a_ByteBuffer, cItem & a_Item, size_t a_KeepRemainingBytes) const override; virtual void WriteEntityMetadata(cPacketizer & a_Pkt, EntityMetadata a_Metadata, EntityMetadataType a_FieldType) const; virtual void WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_Entity) const override; virtual void WriteItem(cPacketizer & a_Pkt, const cItem & a_Item) const override; virtual void WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mob) const override; }; class cProtocol_1_13_1 : public cProtocol_1_13 { using Super = cProtocol_1_13; public: using Super::Super; protected: virtual void SendBossBarAdd(UInt32 a_UniqueID, const cCompositeChat & a_Title, float a_FractionFilled, BossBarColor a_Color, BossBarDivisionType a_DivisionType, bool a_DarkenSky, bool a_PlayEndMusic, bool a_CreateFog) override; virtual void SendBossBarUpdateFlags(UInt32 a_UniqueID, bool a_DarkenSky, bool a_PlayEndMusic, bool a_CreateFog) override; virtual std::pair GetItemFromProtocolID(UInt32 a_ProtocolID) const override; virtual UInt32 GetProtocolBlockType(BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override; virtual UInt32 GetProtocolItemType(short a_ItemID, short a_ItemDamage) const override; virtual UInt32 GetProtocolStatisticType(CustomStatistic a_Statistic) const override; virtual Version GetProtocolVersion() const override; }; class cProtocol_1_13_2 : public cProtocol_1_13_1 { using Super = cProtocol_1_13_1; public: using Super::Super; protected: virtual Version GetProtocolVersion() const override; virtual bool ReadItem(cByteBuffer & a_ByteBuffer, cItem & a_Item, size_t a_KeepRemainingBytes) const override; virtual void WriteItem(cPacketizer & a_Pkt, const cItem & a_Item) const override; }; ================================================ FILE: src/Protocol/Protocol_1_14.cpp ================================================ // Protocol_1_14.cpp /* Implements the 1.14 protocol classes: - release 1.14 protocol (#477) */ #include "Globals.h" #include "Protocol_1_14.h" #include "Packetizer.h" #include "JsonUtils.h" #include "../Root.h" #include "../Server.h" #include "../World.h" #include "../UI/HorseWindow.h" #include "../ClientHandle.h" #include "../WorldStorage/FastNBT.h" #include "../BlockEntities/BlockEntity.h" #include "../Entities/ArrowEntity.h" #include "../Entities/ItemFrame.h" #include "../Mobs/Bat.h" #include "../Entities/Boat.h" #include "../Mobs/Chicken.h" #include "../Mobs/Cow.h" #include "../Mobs/Creeper.h" #include "../Entities/EnderCrystal.h" #include "../Mobs/Enderman.h" #include "../Mobs/Ghast.h" #include "../Mobs/Horse.h" #include "../Mobs/MagmaCube.h" #include "../Entities/Minecart.h" #include "../Mobs/Ocelot.h" #include "../Entities/Pickup.h" #include "../Mobs/Pig.h" #include "../Entities/Player.h" #include "../Mobs/Rabbit.h" #include "../Mobs/Sheep.h" #include "../Mobs/Skeleton.h" #include "../Mobs/Slime.h" #include "../Mobs/Villager.h" #include "../Mobs/Wolf.h" #include "../Mobs/Wither.h" #include "../Mobs/Zombie.h" #include "../Mobs/ZombiePigman.h" #include "Palettes/Upgrade.h" #include "Palettes/Palette_1_14.h" //////////////////////////////////////////////////////////////////////////////// // cProtocol_1_14: void cProtocol_1_14::SendBlockAction(Vector3i a_BlockPos, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktBlockAction); Pkt.WriteXZYPosition64(a_BlockPos); Pkt.WriteBEInt8(a_Byte1); Pkt.WriteBEInt8(a_Byte2); Pkt.WriteVarInt32(a_BlockType); } void cProtocol_1_14::SendBlockBreakAnim(UInt32 a_EntityID, Vector3i a_BlockPos, char a_Stage) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktBlockBreakAnim); Pkt.WriteVarInt32(a_EntityID); Pkt.WriteXZYPosition64(a_BlockPos); Pkt.WriteBEInt8(a_Stage); } void cProtocol_1_14::SendBlockChange(Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) { cPacketizer Pkt(*this, pktBlockChange); Pkt.WriteXZYPosition64(a_BlockPos); Pkt.WriteVarInt32(GetProtocolBlockType(a_BlockType, a_BlockMeta)); } void cProtocol_1_14::SendEditSign(Vector3i a_BlockPos) { } void cProtocol_1_14::SendEntityAnimation(const cEntity & a_Entity, EntityAnimation a_Animation) { if (a_Animation == EntityAnimation::PlayerEntersBed) { // Use Bed packet removed, through metadata instead: SendEntityMetadata(a_Entity); return; } Super::SendEntityAnimation(a_Entity, a_Animation); } void cProtocol_1_14::SendEntitySpawn(const cEntity & a_Entity, const UInt8 a_ObjectType, const Int32 a_ObjectData) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktSpawnObject); Pkt.WriteVarInt32(a_Entity.GetUniqueID()); // TODO: Bad way to write a UUID, and it's not a true UUID, but this is functional for now. Pkt.WriteBEUInt64(0); Pkt.WriteBEUInt64(a_Entity.GetUniqueID()); Pkt.WriteVarInt32(a_ObjectType); Pkt.WriteBEDouble(a_Entity.GetPosX()); Pkt.WriteBEDouble(a_Entity.GetPosY()); Pkt.WriteBEDouble(a_Entity.GetPosZ()); Pkt.WriteByteAngle(a_Entity.GetPitch()); Pkt.WriteByteAngle(a_Entity.GetYaw()); Pkt.WriteBEInt32(a_ObjectData); Pkt.WriteBEInt16(static_cast(a_Entity.GetSpeedX() * 400)); Pkt.WriteBEInt16(static_cast(a_Entity.GetSpeedY() * 400)); Pkt.WriteBEInt16(static_cast(a_Entity.GetSpeedZ() * 400)); } void cProtocol_1_14::SendLogin(const cPlayer & a_Player, const cWorld & a_World) { // Send the Join Game packet: { cServer * Server = cRoot::Get()->GetServer(); cPacketizer Pkt(*this, pktJoinGame); Pkt.WriteBEUInt32(a_Player.GetUniqueID()); Pkt.WriteBEUInt8(static_cast(a_Player.GetEffectiveGameMode()) | (Server->IsHardcore() ? 0x08 : 0)); Pkt.WriteBEInt32(static_cast(a_World.GetDimension())); Pkt.WriteBEUInt8(static_cast(Clamp(Server->GetMaxPlayers(), 0, 255))); Pkt.WriteString("default"); Pkt.WriteVarInt32(ToUnsigned(a_World.GetMaxViewDistance())); Pkt.WriteBool(false); } // Send the spawn position: { cPacketizer Pkt(*this, pktSpawnPosition); Pkt.WriteXZYPosition64(a_World.GetSpawnX(), a_World.GetSpawnY(), a_World.GetSpawnZ()); } // Send the server difficulty: { cPacketizer Pkt(*this, pktDifficulty); Pkt.WriteBEInt8(1); Pkt.WriteBool(false); // Difficulty locked? } } void cProtocol_1_14::SendMapData(const cMap & a_Map, int a_DataStartX, int a_DataStartY) { } void cProtocol_1_14::SendPaintingSpawn(const cPainting & a_Painting) { } void cProtocol_1_14::SendParticleEffect(const AString & a_ParticleName, Vector3f a_Src, Vector3f a_Offset, float a_ParticleData, int a_ParticleAmount, std::array a_Data) { ASSERT(m_State == 3); // In game mode? const auto ParticleID = GetProtocolParticleID(a_ParticleName); cPacketizer Pkt(*this, pktParticleEffect); Pkt.WriteBEInt32(ParticleID); Pkt.WriteBool(false); Pkt.WriteBEFloat(a_Src.x); Pkt.WriteBEFloat(a_Src.y); Pkt.WriteBEFloat(a_Src.z); Pkt.WriteBEFloat(a_Offset.x); Pkt.WriteBEFloat(a_Offset.y); Pkt.WriteBEFloat(a_Offset.z); Pkt.WriteBEFloat(a_ParticleData); Pkt.WriteBEInt32(a_ParticleAmount); switch (ParticleID) { // blockdust case 3: { Pkt.WriteVarInt32(static_cast(a_Data[0])); break; } } } void cProtocol_1_14::SendRespawn(eDimension a_Dimension) { cPacketizer Pkt(*this, pktRespawn); cPlayer * Player = m_Client->GetPlayer(); Pkt.WriteBEInt32(static_cast(a_Dimension)); Pkt.WriteBEUInt8(static_cast(Player->GetEffectiveGameMode())); Pkt.WriteString("default"); } void cProtocol_1_14::SendSoundParticleEffect(const EffectID a_EffectID, Vector3i a_Origin, int a_Data) { ASSERT(m_State == 3); // In game mode? // Note: Particles from block break missing cPacketizer Pkt(*this, pktSoundParticleEffect); Pkt.WriteBEInt32(static_cast(a_EffectID)); Pkt.WriteXYZPosition64(a_Origin); Pkt.WriteBEInt32(a_Data); Pkt.WriteBool(false); } void cProtocol_1_14::SendUpdateBlockEntity(cBlockEntity & a_BlockEntity) { ASSERT(m_State == 3); // In game mode? Byte Action; switch (a_BlockEntity.GetBlockType()) { case E_BLOCK_CHEST: case E_BLOCK_ENCHANTMENT_TABLE: case E_BLOCK_END_PORTAL: case E_BLOCK_TRAPPED_CHEST: { // The ones with a action of 0 is just a workaround to send the block entities to a client. // Todo: 18.09.2020 - remove this when block entities are transmitted in the ChunkData packet - 12xx12 Action = 0; break; } case E_BLOCK_MOB_SPAWNER: Action = 1; break; // Update mob spawner spinny mob thing case E_BLOCK_COMMAND_BLOCK: Action = 2; break; // Update command block text case E_BLOCK_BEACON: Action = 3; break; // Update beacon entity case E_BLOCK_HEAD: Action = 4; break; // Update Mobhead entity // case E_BLOCK_CONDUIT: Action = 5; break; // Update Conduit entity case E_BLOCK_STANDING_BANNER: case E_BLOCK_WALL_BANNER: Action = 6; break; // Update banner entity // case Structure Block: Action = 7; break; // Update Structure tile entity case E_BLOCK_END_GATEWAY: Action = 8; break; // Update destination for a end gateway entity case E_BLOCK_SIGN_POST: Action = 9; break; // Update sign entity // case E_BLOCK_SHULKER_BOX: Action = 10; break; // sets shulker box - not used just here if anyone is confused from reading the protocol wiki case E_BLOCK_BED: Action = 11; break; // Update bed color // case E_BLOCK_JIGSAW: Action = 12; break; // case E_BLOCK_CAMPFIRE: Action = 13; break; default: return; // Block entities change between versions } cPacketizer Pkt(*this, pktUpdateBlockEntity); Pkt.WriteXZYPosition64(a_BlockEntity.GetPosX(), a_BlockEntity.GetPosY(), a_BlockEntity.GetPosZ()); Pkt.WriteBEUInt8(Action); cFastNBTWriter Writer; WriteBlockEntity(Writer, a_BlockEntity); Writer.Finish(); Pkt.WriteBuf(Writer.GetResult()); } void cProtocol_1_14::SendUpdateSign(Vector3i a_BlockPos, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4) { } void cProtocol_1_14::SendWindowOpen(const cWindow & a_Window) { ASSERT(m_State == 3); // In game mode? if (a_Window.GetWindowType() < 0) { // Do not send this packet for player inventory windows return; } if (a_Window.GetWindowType() == cWindow::wtAnimalChest) { cPacketizer Pkt(*this, pktHorseWindowOpen); Pkt.WriteBEUInt8(static_cast(a_Window.GetWindowID())); Pkt.WriteVarInt32(static_cast(a_Window.GetNumSlots())); UInt32 HorseID = static_cast(a_Window).GetHorseID(); Pkt.WriteBEInt32(static_cast(HorseID)); } else { cPacketizer Pkt(*this, pktWindowOpen); Pkt.WriteVarInt32(static_cast(a_Window.GetWindowID())); switch (a_Window.GetWindowType()) { case cWindow::wtChest: { // Chests can have multiple size Pkt.WriteVarInt32(static_cast(a_Window.GetNumNonInventorySlots() / 9 - 1)); break; } case cWindow::wtDropper: case cWindow::wtDropSpenser: { Pkt.WriteVarInt32(6); break; } case cWindow::wtAnvil: { Pkt.WriteVarInt32(7); break; } case cWindow::wtBeacon: { Pkt.WriteVarInt32(8); break; } case cWindow::wtBrewery: { Pkt.WriteVarInt32(10); break; } case cWindow::wtWorkbench: { Pkt.WriteVarInt32(11); break; } case cWindow::wtEnchantment: { Pkt.WriteVarInt32(12); break; } case cWindow::wtFurnace: { Pkt.WriteVarInt32(13); break; } /* case cWindow::wtGrindstone: { Pkt.WriteVarInt32(14); break; } */ case cWindow::wtHopper: { Pkt.WriteVarInt32(15); break; } /* case cWindow::wtLectern: { Pkt.WriteVarInt32(16); break; } case cWindow::wtLoom: { Pkt.WriteVarInt32(17); break; } */ case cWindow::wtNPCTrade: { Pkt.WriteVarInt32(18); break; } /* case cWindow::wtShulker: { Pkt.WriteVarInt32(19); break; } case cWindow::wtSmoker: { Pkt.WriteVarInt32(20); break; } case cWindow::wtCartography: { Pkt.WriteVarInt32(21); break; } case cWindow::wtStonecutter: { Pkt.WriteVarInt32(22); break; } */ default: { Pkt.WriteBEUInt8(static_cast(a_Window.GetNumNonInventorySlots())); break; } } Pkt.WriteString(JsonUtils::SerializeSingleValueJsonObject("text", a_Window.GetWindowTitle())); } } UInt32 cProtocol_1_14::GetPacketID(ePacketType a_PacketType) const { switch (a_PacketType) { case cProtocol::pktAttachEntity: return 0x4A; case cProtocol::pktCameraSetTo: return 0x3E; case cProtocol::pktCollectEntity: return 0x55; case cProtocol::pktDestroyEntity: return 0x37; case cProtocol::pktDisconnectDuringGame: return 0x1A; case cProtocol::pktEntityEffect: return 0x59; case cProtocol::pktEntityEquipment: return 0x46; case cProtocol::pktEntityHeadLook: return 0x3B; case cProtocol::pktEntityMeta: return 0x43; case cProtocol::pktEntityProperties: return 0x58; case cProtocol::pktEntityStatus: return 0x1B; case cProtocol::pktEntityVelocity: return 0x45; case cProtocol::pktExperience: return 0x47; case cProtocol::pktExplosion: return 0x1C; case cProtocol::pktGameMode: return 0x1E; case cProtocol::pktHeldItemChange: return 0x3F; case cProtocol::pktHorseWindowOpen: return 0x1F; case cProtocol::pktInventorySlot: return 0x16; case cProtocol::pktKeepAlive: return 0x20; case cProtocol::pktParticleEffect: return 0x23; case cProtocol::pktPlayerAbilities: return 0x31; case cProtocol::pktPlayerList: return 0x33; case cProtocol::pktPlayerMoveLook: return 0x35; case cProtocol::pktPluginMessage: return 0x18; case cProtocol::pktRemoveEntityEffect: return 0x38; case cProtocol::pktResourcePack: return 0x39; case cProtocol::pktRespawn: return 0x3A; case cProtocol::pktScoreboardObjective: return 0x49; case cProtocol::pktSoundEffect: return 0x19; case cProtocol::pktSoundParticleEffect: return 0x22; case cProtocol::pktSpawnPosition: return 0x4D; case cProtocol::pktTeleportEntity: return 0x56; case cProtocol::pktTimeUpdate: return 0x4E; case cProtocol::pktTitle: return 0x4F; case cProtocol::pktUnloadChunk: return 0x1D; case cProtocol::pktUnlockRecipe: return 0x36; case cProtocol::pktUpdateHealth: return 0x48; case cProtocol::pktUpdateScore: return 0x4C; case cProtocol::pktUpdateSign: return 0x2F; case cProtocol::pktWeather: return 0x1E; case cProtocol::pktWindowItems: return 0x14; case cProtocol::pktWindowOpen: return 0x2E; case cProtocol::pktWindowProperty: return 0x15; default: return Super::GetPacketID(a_PacketType); } } UInt8 cProtocol_1_14::GetEntityMetadataID(EntityMetadata a_Metadata) const { const UInt8 Entity = 7; const UInt8 Living = Entity + 6; const UInt8 Insentient = Living + 1; const UInt8 Ageable = Insentient + 1; const UInt8 AbstractHorse = Ageable + 2; const UInt8 ChestedHorse = AbstractHorse + 1; const UInt8 TameableAnimal = Ageable + 2; const UInt8 Minecart = Entity + 6; const UInt8 RaidParticipent = Insentient + 1; switch (a_Metadata) { case EntityMetadata::EntityFlags: return 0; case EntityMetadata::EntityAir: return 1; case EntityMetadata::EntityCustomName: return 2; case EntityMetadata::EntityCustomNameVisible: return 3; case EntityMetadata::EntitySilent: return 4; case EntityMetadata::EntityNoGravity: return 5; case EntityMetadata::EntityPose: return 6; case EntityMetadata::ThrowableItem: return Entity; case EntityMetadata::PotionThrown: return Entity; case EntityMetadata::FallingBlockPosition: return Entity; case EntityMetadata::AreaEffectCloudRadius: return Entity; case EntityMetadata::AreaEffectCloudColor: return Entity + 1; case EntityMetadata::AreaEffectCloudSinglePointEffect: return Entity + 2; case EntityMetadata::AreaEffectCloudParticleId: return Entity + 3; case EntityMetadata::ArrowFlags: return Entity; case EntityMetadata::PiercingLevel: return Entity + 2; case EntityMetadata::TippedArrowColor: return Entity + 3; case EntityMetadata::BoatLastHitTime: return Entity; case EntityMetadata::BoatForwardDirection: return Entity + 1; case EntityMetadata::BoatDamageTaken: return Entity + 2; case EntityMetadata::BoatType: return Entity + 3; case EntityMetadata::BoatLeftPaddleTurning: return Entity + 4; case EntityMetadata::BoatRightPaddleTurning: return Entity + 5; case EntityMetadata::BoatSplashTimer: return Entity + 6; case EntityMetadata::EnderCrystalBeamTarget: return Entity; case EntityMetadata::EnderCrystalShowBottom: return Entity + 1; case EntityMetadata::WitherSkullInvulnerable: return Entity; case EntityMetadata::FireworkInfo: return Entity; case EntityMetadata::FireworkBoostedEntityId: return Entity + 1; case EntityMetadata::FireworkFromCrossbow: return Entity + 2; case EntityMetadata::ItemFrameItem: return Entity; case EntityMetadata::ItemFrameRotation: return Entity + 1; case EntityMetadata::ItemItem: return Entity; case EntityMetadata::LivingActiveHand: return Entity; case EntityMetadata::LivingHealth: return Entity + 1; case EntityMetadata::LivingPotionEffectColor: return Entity + 2; case EntityMetadata::LivingPotionEffectAmbient: return Entity + 3; case EntityMetadata::LivingNumberOfArrows: return Entity + 4; case EntityMetadata::PlayerAdditionalHearts: return Living; case EntityMetadata::PlayerScore: return Living + 1; case EntityMetadata::PlayerDisplayedSkinParts: return Living + 2; case EntityMetadata::PlayerMainHand: return Living + 3; case EntityMetadata::ArmorStandStatus: return Living; case EntityMetadata::ArmorStandHeadRotation: return Living + 1; case EntityMetadata::ArmorStandBodyRotation: return Living + 2; case EntityMetadata::ArmorStandLeftArmRotation: return Living + 3; case EntityMetadata::ArmorStandRightArmRotation: return Living + 4; case EntityMetadata::ArmorStandLeftLegRotation: return Living + 5; case EntityMetadata::ArmorStandRightLegRotation: return Living + 6; case EntityMetadata::InsentientFlags: return Living; case EntityMetadata::BatHanging: return Insentient; case EntityMetadata::AgeableIsBaby: return Insentient; case EntityMetadata::AbstractHorseFlags: return Ageable; case EntityMetadata::AbstractHorseOwner: return Ageable + 1; case EntityMetadata::HorseVariant: return AbstractHorse; case EntityMetadata::ChestedHorseChested: return AbstractHorse; case EntityMetadata::LlamaStrength: return ChestedHorse; case EntityMetadata::LlamaCarpetColor: return ChestedHorse + 1; case EntityMetadata::LlamaVariant: return ChestedHorse + 2; case EntityMetadata::PigHasSaddle: return Ageable; case EntityMetadata::PigTotalCarrotOnAStickBoost: return Ageable + 1; case EntityMetadata::RabbitType: return Ageable; case EntityMetadata::PolarBearStanding: return Ageable; case EntityMetadata::SheepFlags: return Ageable; case EntityMetadata::TameableAnimalFlags: return Ageable; case EntityMetadata::TameableAnimalOwner: return Ageable + 1; case EntityMetadata::OcelotType: return TameableAnimal; case EntityMetadata::WolfDamageTaken: return TameableAnimal; case EntityMetadata::WolfBegging: return TameableAnimal + 1; case EntityMetadata::WolfCollarColour: return TameableAnimal + 2; case EntityMetadata::VillagerProfession: return Ageable; case EntityMetadata::IronGolemPlayerCreated: return Insentient; case EntityMetadata::ShulkerFacingDirection: return Insentient; case EntityMetadata::ShulkerAttachmentFallingBlockPosition: return Insentient + 1; case EntityMetadata::ShulkerShieldHeight: return Insentient + 2; case EntityMetadata::BlazeOnFire: return Insentient; case EntityMetadata::CreeperState: return Insentient; case EntityMetadata::CreeperPowered: return Insentient + 1; case EntityMetadata::CreeperIgnited: return Insentient + 2; case EntityMetadata::GuardianStatus: return Insentient; case EntityMetadata::GuardianTarget: return Insentient + 1; case EntityMetadata::IllagerFlags: return Insentient; case EntityMetadata::SpeIlagerSpell: return Insentient + 1; case EntityMetadata::VexFlags: return Insentient; case EntityMetadata::AbstractSkeletonArmsSwinging: return Insentient; case EntityMetadata::SpiderClimbing: return Insentient; case EntityMetadata::WitchAggresive: return Insentient; case EntityMetadata::WitherFirstHeadTarget: return Insentient; case EntityMetadata::WitherSecondHeadTarget: return Insentient + 1; case EntityMetadata::WitherThirdHeadTarget: return Insentient + 2; case EntityMetadata::WitherInvulnerableTimer: return Insentient + 3; case EntityMetadata::ZombieIsBaby: return Insentient; case EntityMetadata::ZombieHandsRisedUp: return Insentient + 2; case EntityMetadata::ZombieVillagerConverting: return Insentient + 4; case EntityMetadata::ZombieVillagerProfession: return Insentient + 5; case EntityMetadata::EndermanCarriedBlock: return Insentient; case EntityMetadata::EndermanScreaming: return Insentient + 1; case EntityMetadata::EnderDragonDragonPhase: return Insentient; case EntityMetadata::GhastAttacking: return Insentient; case EntityMetadata::SlimeSize: return Insentient; case EntityMetadata::MinecartShakingPower: return Entity; case EntityMetadata::MinecartShakingDirection: return Entity + 1; case EntityMetadata::MinecartShakingMultiplier: return Entity + 2; case EntityMetadata::MinecartBlockIDMeta: return Entity + 3; case EntityMetadata::MinecartBlockY: return Entity + 4; case EntityMetadata::MinecartShowBlock: return Entity + 5; case EntityMetadata::MinecartCommandBlockCommand: return Minecart; case EntityMetadata::MinecartCommandBlockLastOutput: return Minecart + 1; case EntityMetadata::MinecartFurnacePowered: return Minecart; case EntityMetadata::TNTPrimedFuseTime: return Entity; case EntityMetadata::TridentLoyaltyLevel: return Entity + 3; case EntityMetadata::MooshroomType: return Ageable; case EntityMetadata::WitchDrinking: return RaidParticipent; case EntityMetadata::AreaEffectCloudParticleParameter1: case EntityMetadata::AreaEffectCloudParticleParameter2: case EntityMetadata::ZombieUnusedWasType: break; default: break; } UNREACHABLE("Retrieved invalid metadata for protocol"); } std::pair cProtocol_1_14::GetItemFromProtocolID(UInt32 a_ProtocolID) const { return PaletteUpgrade::ToItem(Palette_1_14::ToItem(a_ProtocolID)); } UInt32 cProtocol_1_14::GetProtocolBlockType(BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const { return Palette_1_14::From(PaletteUpgrade::FromBlock(a_BlockType, a_Meta)); } signed char cProtocol_1_14::GetProtocolEntityStatus(EntityAnimation a_Animation) const { switch (a_Animation) { case EntityAnimation::FoxChews: return 45; case EntityAnimation::OcelotTrusts: return 40; case EntityAnimation::OcelotDistrusts: return 41; case EntityAnimation::PawnBerryBushPricks: return 44; case EntityAnimation::PawnChestEquipmentBreaks: return 50; case EntityAnimation::PawnFeetEquipmentBreaks: return 52; case EntityAnimation::PawnHeadEquipmentBreaks: return 49; case EntityAnimation::PawnLegsEquipmentBreaks: return 51; case EntityAnimation::PawnMainHandEquipmentBreaks: return 47; case EntityAnimation::PawnOffHandEquipmentBreaks: return 48; case EntityAnimation::PawnTeleports: return 46; case EntityAnimation::PlayerBadOmenActivates: return 43; case EntityAnimation::RavagerAttacks: return 4; case EntityAnimation::RavagerBecomesStunned: return 39; case EntityAnimation::VillagerSweats: return 42; default: return Super::GetProtocolEntityStatus(a_Animation); } } UInt8 cProtocol_1_14::GetProtocolEntityType(const cEntity & a_Entity) const { using Type = cEntity::eEntityType; switch (a_Entity.GetEntityType()) { case Type::etEnderCrystal: return 17; case Type::etPickup: return 34; case Type::etFallingBlock: return 25; case Type::etMinecart: return 41; case Type::etBoat: return 5; case Type::etTNT: return 58; case Type::etProjectile: { using PType = cProjectileEntity::eKind; const auto & Projectile = static_cast(a_Entity); switch (Projectile.GetProjectileKind()) { case PType::pkArrow: return 2; case PType::pkSnowball: return 70; case PType::pkEgg: return 78; case PType::pkGhastFireball: return 36; case PType::pkFireCharge: return 68; case PType::pkEnderPearl: return 79; case PType::pkExpBottle: return 80; case PType::pkSplashPotion: return 81; case PType::pkFirework: return 26; case PType::pkWitherSkull: return 92; } break; } case Type::etFloater: return 101; case Type::etItemFrame: return 35; case Type::etLeashKnot: return 37; // Non-objects must not be sent case Type::etEntity: case Type::etPlayer: case Type::etMonster: case Type::etExpOrb: case Type::etPainting: break; } UNREACHABLE("Unhandled entity kind"); } UInt32 cProtocol_1_14::GetProtocolItemType(short a_ItemID, short a_ItemDamage) const { return Palette_1_14::From(PaletteUpgrade::FromItem(a_ItemID, a_ItemDamage)); } UInt32 cProtocol_1_14::GetProtocolMobType(eMonsterType a_MobType) const { switch (a_MobType) { // Map invalid type to Giant for easy debugging (if this ever spawns, something has gone very wrong) case mtInvalidType: return 29; case mtBat: return 3; case mtBlaze: return 4; case mtCat: return 6; case mtCaveSpider: return 7; case mtChicken: return 8; case mtCod: return 9; case mtCow: return 10; case mtCreeper: return 11; case mtDonkey: return 12; case mtDolphin: return 13; case mtDrowned: return 15; case mtElderGuardian: return 16; case mtEnderDragon: return 18; case mtEnderman: return 19; case mtEndermite: return 20; case mtEvoker: return 22; case mtFox: return 27; case mtGhast: return 28; case mtGiant: return 29; case mtGuardian: return 30; case mtHorse: return 31; case mtHusk: return 32; case mtIllusioner: return 33; case mtIronGolem: return 85; case mtLlama: return 38; case mtMagmaCube: return 40; case mtMule: return 48; case mtMooshroom: return 49; case mtOcelot: return 50; case mtPanda: return 52; case mtParrot: return 53; case mtPig: return 54; case mtPufferfish: return 55; case mtPolarBear: return 57; case mtRabbit: return 59; case mtSalmon: return 60; case mtSheep: return 61; case mtShulker: return 62; case mtSilverfish: return 64; case mtSkeleton: return 65; case mtSkeletonHorse: return 66; case mtSlime: return 67; case mtSnowGolem: return 69; case mtSpider: return 72; case mtSquid: return 73; case mtStray: return 74; case mtTraderLlama: return 75; case mtTropicalFish: return 76; case mtTurtle: return 77; case mtVex: return 83; case mtVillager: return 84; case mtVindicator: return 86; case mtPillager: return 87; case mtWanderingTrader: return 88; case mtWitch: return 89; case mtWither: return 90; case mtWitherSkeleton: return 91; case mtWolf: return 93; case mtZombie: return 94; case mtZombieHorse: return 95; case mtZombiePigman: return 56; case mtZombieVillager: return 96; case mtPhantom: return 97; case mtRavager: return 98; default: return 0; } } int cProtocol_1_14::GetProtocolParticleID(const AString & a_ParticleName) const { static const std::unordered_map ParticleMap { // Initialize the ParticleMap: { "ambiantentity", 0 }, { "angryvillager", 1 }, { "barrier", 2 }, { "blockdust", 3 }, { "bubble", 4 }, { "cloud", 5 }, { "crit", 6 }, { "damageindicator", 7 }, { "dragonbreath", 8 }, { "driplava", 9 }, { "fallinglava", 10 }, { "landinglava", 11 }, { "dripwater", 12 }, { "fallingwater", 13 }, { "dust", 14 }, { "effect", 15 }, { "elderguardian", 16 }, { "enchantedhit", 17 }, { "enchant", 18 }, { "endrod", 19 }, { "entityeffect", 20 }, { "explosionemitter", 21 }, { "explode", 22 }, { "fallingdust", 23 }, { "firework", 24 }, { "fishing", 25 }, { "flame", 26 }, { "flash", 27 }, { "happyvillager", 28 }, { "composter", 29 }, { "heart", 30 }, { "instanteffect", 31 }, { "item", 32 }, { "slime", 33 }, { "snowball", 34 }, { "largesmoke", 35 }, { "lava", 36 }, { "mycelium", 37 }, { "note", 38 }, { "poof", 39 }, { "portal", 40 }, { "rain", 41 }, { "smoke", 42 }, { "sneeze", 43 }, { "spit", 44 }, { "squidink", 45 }, { "sweepattack", 46 }, { "totem", 47 }, { "underwater", 48 }, { "splash", 49 }, { "witch", 50 }, { "bubblepop", 51 }, { "currentdown", 52 }, { "bubblecolumnup", 53 }, { "nautilus", 54 }, { "dolphin", 55 }, { "campfirecosysmoke", 56 }, { "campfiresignalsmoke", 57 }, }; const auto ParticleName = StrToLower(a_ParticleName); const auto FindResult = ParticleMap.find(ParticleName); if (FindResult == ParticleMap.end()) { LOGWARNING("Unknown particle: %s", a_ParticleName.c_str()); ASSERT(!"Unknown particle"); return 0; } return FindResult->second; } UInt32 cProtocol_1_14::GetProtocolStatisticType(const CustomStatistic a_Statistic) const { return Palette_1_14::From(a_Statistic); } cProtocol::Version cProtocol_1_14::GetProtocolVersion() const { return Version::v1_14; } bool cProtocol_1_14::HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType) { if (m_State != State::Game) { return Super::HandlePacket(a_ByteBuffer, a_PacketType); } // Game switch (a_PacketType) { case 0x03: HandlePacketChatMessage(a_ByteBuffer); return true; case 0x04: HandlePacketClientStatus(a_ByteBuffer); return true; case 0x05: HandlePacketClientSettings(a_ByteBuffer); return true; case 0x06: HandlePacketTabComplete(a_ByteBuffer); return true; case 0x07: break; // Confirm transaction - not used in Cuberite case 0x08: HandlePacketEnchantItem(a_ByteBuffer); return true; case 0x09: HandlePacketWindowClick(a_ByteBuffer); return true; case 0x0A: HandlePacketWindowClose(a_ByteBuffer); return true; case 0x0B: HandlePacketPluginMessage(a_ByteBuffer); return true; case 0x0E: HandlePacketUseEntity(a_ByteBuffer); return true; case 0x0F: HandlePacketKeepAlive(a_ByteBuffer); return true; case 0x11: HandlePacketPlayerPos(a_ByteBuffer); return true; case 0x12: HandlePacketPlayerPosLook(a_ByteBuffer); return true; case 0x13: HandlePacketPlayerLook(a_ByteBuffer); return true; case 0x14: HandlePacketPlayer(a_ByteBuffer); return true; case 0x15: HandlePacketVehicleMove(a_ByteBuffer); return true; case 0x16: HandlePacketBoatSteer(a_ByteBuffer); return true; case 0x18: HandleCraftRecipe(a_ByteBuffer); return true; case 0x19: HandlePacketPlayerAbilities(a_ByteBuffer); return true; case 0x1A: HandlePacketBlockDig(a_ByteBuffer); return true; case 0x1C: HandlePacketSteerVehicle(a_ByteBuffer); return true; case 0x1D: HandlePacketCraftingBookData(a_ByteBuffer); return true; case 0x1E: HandlePacketNameItem(a_ByteBuffer); return true; case 0x1F: HandlePacketResourcePackStatus(a_ByteBuffer); return true; case 0x20: HandlePacketAdvancementTab(a_ByteBuffer); return true; case 0x22: HandlePacketSetBeaconEffect(a_ByteBuffer); return true; case 0x23: HandlePacketSlotSelect(a_ByteBuffer); return true; case 0x26: HandlePacketCreativeInventoryAction(a_ByteBuffer); return true; case 0x2C: HandlePacketBlockPlace(a_ByteBuffer); return true; case 0x2D: HandlePacketUseItem(a_ByteBuffer); return true; default: break; } return Super::HandlePacket(a_ByteBuffer, a_PacketType); } void cProtocol_1_14::HandlePacketBlockDig(cByteBuffer & a_ByteBuffer) { HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, Status); int BlockX, BlockY, BlockZ; if (!a_ByteBuffer.ReadXZYPosition64(BlockX, BlockY, BlockZ)) { return; } HANDLE_READ(a_ByteBuffer, ReadVarInt, Int32, Face); m_Client->HandleLeftClick({BlockX, BlockY, BlockZ}, FaceIntToBlockFace(Face), Status); } void cProtocol_1_14::HandlePacketBlockPlace(cByteBuffer & a_ByteBuffer) { HANDLE_READ(a_ByteBuffer, ReadVarInt, Int32, Hand); int BlockX, BlockY, BlockZ; if (!a_ByteBuffer.ReadXZYPosition64(BlockX, BlockY, BlockZ)) { return; } HANDLE_READ(a_ByteBuffer, ReadVarInt, Int32, Face); HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, CursorX); HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, CursorY); HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, CursorZ); HANDLE_READ(a_ByteBuffer, ReadBool, bool, InsideBlock); m_Client->HandleRightClick({BlockX, BlockY, BlockZ}, FaceIntToBlockFace(Face), {FloorC(CursorX * 16), FloorC(CursorY * 16), FloorC(CursorZ * 16)}, Hand == 0); } void cProtocol_1_14::HandlePacketUpdateSign(cByteBuffer & a_ByteBuffer) { } void cProtocol_1_14::WriteEntityMetadata(cPacketizer & a_Pkt, const EntityMetadata a_Metadata, const EntityMetadataType a_FieldType) const { a_Pkt.WriteBEUInt8(GetEntityMetadataID(a_Metadata)); // Index a_Pkt.WriteBEUInt8(Super::GetEntityMetadataID(a_FieldType)); // Type } void cProtocol_1_14::WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_Entity) const { // Common metadata: Int8 Flags = 0; if (a_Entity.IsOnFire()) { Flags |= 0x01; } if (a_Entity.IsCrouched()) { Flags |= 0x02; } if (a_Entity.IsSprinting()) { Flags |= 0x08; } if (a_Entity.IsRclking()) { Flags |= 0x10; } if (a_Entity.IsInvisible()) { Flags |= 0x20; } /* if (a_Entity.IsGlowing()) { Flags |= 0x40; } */ if (a_Entity.IsElytraFlying()) { Flags |= 0x80; } WriteEntityMetadata(a_Pkt, EntityMetadata::EntityFlags, EntityMetadataType::Byte); a_Pkt.WriteBEInt8(Flags); switch (a_Entity.GetEntityType()) { case cEntity::etPlayer: { auto & Player = static_cast(a_Entity); // TODO Set player custom name to their name. // Then it's possible to move the custom name of mobs to the entities // and to remove the "special" player custom name. WriteEntityMetadata(a_Pkt, EntityMetadata::EntityCustomName, EntityMetadataType::String); a_Pkt.WriteString(Player.GetName()); WriteEntityMetadata(a_Pkt, EntityMetadata::LivingHealth, EntityMetadataType::Float); a_Pkt.WriteBEFloat(static_cast(Player.GetHealth())); WriteEntityMetadata(a_Pkt, EntityMetadata::PlayerDisplayedSkinParts, EntityMetadataType::Byte); a_Pkt.WriteBEUInt8(static_cast(Player.GetSkinParts())); WriteEntityMetadata(a_Pkt, EntityMetadata::PlayerMainHand, EntityMetadataType::Byte); a_Pkt.WriteBEUInt8(Player.IsLeftHanded() ? 0 : 1); break; } case cEntity::etPickup: { WriteEntityMetadata(a_Pkt, EntityMetadata::ItemItem, EntityMetadataType::Item); WriteItem(a_Pkt, static_cast(a_Entity).GetItem()); break; } case cEntity::etMinecart: { WriteEntityMetadata(a_Pkt, EntityMetadata::MinecartShakingPower, EntityMetadataType::VarInt); // The following expression makes Minecarts shake more with less health or higher damage taken auto & Minecart = static_cast(a_Entity); auto maxHealth = a_Entity.GetMaxHealth(); auto curHealth = a_Entity.GetHealth(); a_Pkt.WriteVarInt32(static_cast((maxHealth - curHealth) * Minecart.LastDamage() * 4)); WriteEntityMetadata(a_Pkt, EntityMetadata::MinecartShakingDirection, EntityMetadataType::VarInt); a_Pkt.WriteVarInt32(1); // (doesn't seem to effect anything) WriteEntityMetadata(a_Pkt, EntityMetadata::MinecartShakingMultiplier, EntityMetadataType::Float); a_Pkt.WriteBEFloat(static_cast(Minecart.LastDamage() + 10)); // or damage taken if (Minecart.GetPayload() == cMinecart::mpNone) { auto & RideableMinecart = static_cast(Minecart); const cItem & MinecartContent = RideableMinecart.GetContent(); if (!MinecartContent.IsEmpty()) { WriteEntityMetadata(a_Pkt, EntityMetadata::MinecartBlockIDMeta, EntityMetadataType::VarInt); int Content = MinecartContent.m_ItemType; Content |= MinecartContent.m_ItemDamage << 8; a_Pkt.WriteVarInt32(static_cast(Content)); WriteEntityMetadata(a_Pkt, EntityMetadata::MinecartBlockY, EntityMetadataType::VarInt); a_Pkt.WriteVarInt32(static_cast(RideableMinecart.GetBlockHeight())); WriteEntityMetadata(a_Pkt, EntityMetadata::MinecartShowBlock, EntityMetadataType::Boolean); a_Pkt.WriteBool(true); } } else if (Minecart.GetPayload() == cMinecart::mpFurnace) { WriteEntityMetadata(a_Pkt, EntityMetadata::MinecartFurnacePowered, EntityMetadataType::Boolean); a_Pkt.WriteBool(static_cast(Minecart).IsFueled()); } break; } // case etMinecart case cEntity::etProjectile: { auto & Projectile = static_cast(a_Entity); switch (Projectile.GetProjectileKind()) { case cProjectileEntity::pkArrow: { WriteEntityMetadata(a_Pkt, EntityMetadata::ArrowFlags, EntityMetadataType::Byte); a_Pkt.WriteBEInt8(static_cast(Projectile).IsCritical() ? 1 : 0); // TODO: Piercing level break; } case cProjectileEntity::pkFirework: { // TODO break; } case cProjectileEntity::pkSplashPotion: { // TODO } default: { break; } } break; } // case etProjectile case cEntity::etMonster: { WriteMobMetadata(a_Pkt, static_cast(a_Entity)); break; } case cEntity::etBoat: { auto & Boat = static_cast(a_Entity); WriteEntityMetadata(a_Pkt, EntityMetadata::BoatLastHitTime, EntityMetadataType::VarInt); a_Pkt.WriteVarInt32(static_cast(Boat.GetLastDamage())); WriteEntityMetadata(a_Pkt, EntityMetadata::BoatForwardDirection, EntityMetadataType::VarInt); a_Pkt.WriteVarInt32(static_cast(Boat.GetForwardDirection())); WriteEntityMetadata(a_Pkt, EntityMetadata::BoatDamageTaken, EntityMetadataType::Float); a_Pkt.WriteBEFloat(Boat.GetDamageTaken()); WriteEntityMetadata(a_Pkt, EntityMetadata::BoatType, EntityMetadataType::VarInt); a_Pkt.WriteVarInt32(static_cast(Boat.GetMaterial())); WriteEntityMetadata(a_Pkt, EntityMetadata::BoatRightPaddleTurning, EntityMetadataType::Boolean); a_Pkt.WriteBool(Boat.IsRightPaddleUsed()); WriteEntityMetadata(a_Pkt, EntityMetadata::BoatLeftPaddleTurning, EntityMetadataType::Boolean); a_Pkt.WriteBool(static_cast(Boat.IsLeftPaddleUsed())); WriteEntityMetadata(a_Pkt, EntityMetadata::BoatSplashTimer, EntityMetadataType::VarInt); a_Pkt.WriteVarInt32(0); break; } // case etBoat case cEntity::etItemFrame: { const auto & Frame = static_cast(a_Entity); WriteEntityMetadata(a_Pkt, EntityMetadata::ItemFrameItem, EntityMetadataType::Item); WriteItem(a_Pkt, Frame.GetItem()); WriteEntityMetadata(a_Pkt, EntityMetadata::ItemFrameRotation, EntityMetadataType::VarInt); a_Pkt.WriteVarInt32(Frame.GetItemRotation()); break; } // case etItemFrame case cEntity::etEnderCrystal: { const auto & EnderCrystal = static_cast(a_Entity); if (EnderCrystal.DisplaysBeam()) { WriteEntityMetadata(a_Pkt, EntityMetadata::EnderCrystalBeamTarget, EntityMetadataType::OptPosition); a_Pkt.WriteBool(true); // Dont do a second check if it should display the beam a_Pkt.WriteXYZPosition64(EnderCrystal.GetBeamTarget()); } WriteEntityMetadata(a_Pkt, EntityMetadata::EnderCrystalShowBottom, EntityMetadataType::Boolean); a_Pkt.WriteBool(EnderCrystal.ShowsBottom()); break; } // case etEnderCrystal default: { break; } } } void cProtocol_1_14::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mob) const { // Living Enitiy Metadata if (a_Mob.HasCustomName()) { // TODO: As of 1.9 _all_ entities can have custom names; should this be moved up? WriteEntityMetadata(a_Pkt, EntityMetadata::EntityCustomName, EntityMetadataType::OptChat); a_Pkt.WriteBool(true); a_Pkt.WriteString(a_Mob.GetCustomName()); WriteEntityMetadata(a_Pkt, EntityMetadata::EntityCustomNameVisible, EntityMetadataType::Boolean); a_Pkt.WriteBool(a_Mob.IsCustomNameAlwaysVisible()); } WriteEntityMetadata(a_Pkt, EntityMetadata::LivingHealth, EntityMetadataType::Float); a_Pkt.WriteBEFloat(static_cast(a_Mob.GetHealth())); // TODO: pose switch (a_Mob.GetMobType()) { case mtBat: { auto & Bat = static_cast(a_Mob); WriteEntityMetadata(a_Pkt, EntityMetadata::BatHanging, EntityMetadataType::Byte); a_Pkt.WriteBEInt8(Bat.IsHanging() ? 1 : 0); break; } // case mtBat case mtChicken: { auto & Chicken = static_cast(a_Mob); WriteEntityMetadata(a_Pkt, EntityMetadata::AgeableIsBaby, EntityMetadataType::Boolean); a_Pkt.WriteBool(Chicken.IsBaby()); break; } // case mtChicken case mtCow: { auto & Cow = static_cast(a_Mob); WriteEntityMetadata(a_Pkt, EntityMetadata::AgeableIsBaby, EntityMetadataType::Boolean); a_Pkt.WriteBool(Cow.IsBaby()); break; } // case mtCow case mtCreeper: { auto & Creeper = static_cast(a_Mob); WriteEntityMetadata(a_Pkt, EntityMetadata::CreeperState, EntityMetadataType::VarInt); a_Pkt.WriteVarInt32(Creeper.IsBlowing() ? 1 : static_cast(-1)); // (idle or "blowing") WriteEntityMetadata(a_Pkt, EntityMetadata::CreeperPowered, EntityMetadataType::Boolean); a_Pkt.WriteBool(Creeper.IsCharged()); WriteEntityMetadata(a_Pkt, EntityMetadata::CreeperIgnited, EntityMetadataType::Boolean); a_Pkt.WriteBool(Creeper.IsBurnedWithFlintAndSteel()); break; } // case mtCreeper case mtEnderman: { auto & Enderman = static_cast(a_Mob); WriteEntityMetadata(a_Pkt, EntityMetadata::EndermanCarriedBlock, EntityMetadataType::OptBlockID); UInt32 Carried = 0; Carried |= static_cast(Enderman.GetCarriedBlock() << 4); Carried |= Enderman.GetCarriedMeta(); a_Pkt.WriteVarInt32(Carried); WriteEntityMetadata(a_Pkt, EntityMetadata::EndermanScreaming, EntityMetadataType::Boolean); a_Pkt.WriteBool(Enderman.IsScreaming()); break; } // case mtEnderman case mtGhast: { auto & Ghast = static_cast(a_Mob); WriteEntityMetadata(a_Pkt, EntityMetadata::GhastAttacking, EntityMetadataType::Boolean); a_Pkt.WriteBool(Ghast.IsCharging()); break; } // case mtGhast case mtHorse: { // XXX This behaves incorrectly with different varients; horses have different entity IDs now // Abstract horse auto & Horse = static_cast(a_Mob); Int8 Flags = 0; if (Horse.IsTame()) { Flags |= 0x02; } if (Horse.IsSaddled()) { Flags |= 0x04; } if (Horse.IsInLoveCooldown()) { Flags |= 0x08; } if (Horse.IsEating()) { Flags |= 0x10; } if (Horse.IsRearing()) { Flags |= 0x20; } if (Horse.IsMthOpen()) { Flags |= 0x40; } WriteEntityMetadata(a_Pkt, EntityMetadata::AbstractHorseFlags, EntityMetadataType::Byte); a_Pkt.WriteBEInt8(Flags); // Regular horses int Appearance = 0; Appearance = Horse.GetHorseColor(); Appearance |= Horse.GetHorseStyle() << 8; WriteEntityMetadata(a_Pkt, EntityMetadata::HorseVariant, EntityMetadataType::VarInt); a_Pkt.WriteVarInt32(static_cast(Appearance)); // Color / style WriteEntityMetadata(a_Pkt, EntityMetadata::AgeableIsBaby, EntityMetadataType::Boolean); a_Pkt.WriteBool(Horse.IsBaby()); break; } // case mtHorse case mtMagmaCube: { auto & MagmaCube = static_cast(a_Mob); WriteEntityMetadata(a_Pkt, EntityMetadata::SlimeSize, EntityMetadataType::VarInt); a_Pkt.WriteVarInt32(static_cast(MagmaCube.GetSize())); break; } // case mtMagmaCube case mtOcelot: { auto & Ocelot = static_cast(a_Mob); WriteEntityMetadata(a_Pkt, EntityMetadata::AgeableIsBaby, EntityMetadataType::Boolean); a_Pkt.WriteBool(Ocelot.IsBaby()); // TODO: Ocelot trusting break; } // case mtOcelot case mtPig: { auto & Pig = static_cast(a_Mob); WriteEntityMetadata(a_Pkt, EntityMetadata::AgeableIsBaby, EntityMetadataType::Boolean); a_Pkt.WriteBool(Pig.IsBaby()); WriteEntityMetadata(a_Pkt, EntityMetadata::PigHasSaddle, EntityMetadataType::Boolean); a_Pkt.WriteBool(Pig.IsSaddled()); // PIG_TOTAL_CARROT_ON_A_STICK_BOOST in 1.11.1 only break; } // case mtPig case mtRabbit: { auto & Rabbit = static_cast(a_Mob); WriteEntityMetadata(a_Pkt, EntityMetadata::AgeableIsBaby, EntityMetadataType::Boolean); a_Pkt.WriteBool(Rabbit.IsBaby()); WriteEntityMetadata(a_Pkt, EntityMetadata::RabbitType, EntityMetadataType::VarInt); a_Pkt.WriteVarInt32(static_cast(Rabbit.GetRabbitType())); break; } // case mtRabbit case mtSheep: { auto & Sheep = static_cast(a_Mob); WriteEntityMetadata(a_Pkt, EntityMetadata::AgeableIsBaby, EntityMetadataType::Boolean); a_Pkt.WriteBool(Sheep.IsBaby()); Int8 SheepMetadata = 0; SheepMetadata = static_cast(Sheep.GetFurColor()); if (Sheep.IsSheared()) { SheepMetadata |= 0x10; } WriteEntityMetadata(a_Pkt, EntityMetadata::SheepFlags, EntityMetadataType::Byte); a_Pkt.WriteBEInt8(SheepMetadata); break; } // case mtSheep case mtSkeleton: { auto & Skeleton = static_cast(a_Mob); WriteEntityMetadata(a_Pkt, EntityMetadata::LivingActiveHand, EntityMetadataType::Byte); a_Pkt.WriteBEUInt8(Skeleton.IsChargingBow() ? 0x01 : 0x00); // TODO: Skeleton animation break; } // case mtSkeleton case mtSlime: { auto & Slime = static_cast(a_Mob); WriteEntityMetadata(a_Pkt, EntityMetadata::SlimeSize, EntityMetadataType::VarInt); a_Pkt.WriteVarInt32(static_cast(Slime.GetSize())); break; } // case mtSlime case mtVillager: { auto & Villager = static_cast(a_Mob); WriteEntityMetadata(a_Pkt, EntityMetadata::AgeableIsBaby, EntityMetadataType::Boolean); a_Pkt.WriteBool(Villager.IsBaby()); WriteEntityMetadata(a_Pkt, EntityMetadata::VillagerProfession, EntityMetadataType::VillagerData); a_Pkt.WriteVarInt32(2); // Villager from plains switch (Villager.GetVilType()) { case cVillager::vtFarmer: { a_Pkt.WriteVarInt32(5); break; } case cVillager::vtLibrarian: { a_Pkt.WriteVarInt32(9); break; } case cVillager::vtPriest: { a_Pkt.WriteVarInt32(4); break; } case cVillager::vtBlacksmith: { a_Pkt.WriteVarInt32(13); break; } case cVillager::vtButcher: { a_Pkt.WriteVarInt32(2); break; } case cVillager::vtGeneric: { a_Pkt.WriteVarInt32(0); break; } } a_Pkt.WriteVarInt32(1); // Level 1 villager break; } // case mtVillager case mtWitch: { // auto & Witch = static_cast(a_Mob); // TODO: Witch drinking potion break; } // case mtWitch case mtWither: { auto & Wither = static_cast(a_Mob); WriteEntityMetadata(a_Pkt, EntityMetadata::WitherInvulnerableTimer, EntityMetadataType::VarInt); a_Pkt.WriteVarInt32(Wither.GetWitherInvulnerableTicks()); // TODO: Use boss bar packet for health break; } // case mtWither case mtWolf: { auto & Wolf = static_cast(a_Mob); WriteEntityMetadata(a_Pkt, EntityMetadata::AgeableIsBaby, EntityMetadataType::Boolean); a_Pkt.WriteBool(Wolf.IsBaby()); Int8 WolfStatus = 0; if (Wolf.IsSitting()) { WolfStatus |= 0x1; } if (Wolf.IsAngry()) { WolfStatus |= 0x2; } if (Wolf.IsTame()) { WolfStatus |= 0x4; } WriteEntityMetadata(a_Pkt, EntityMetadata::TameableAnimalFlags, EntityMetadataType::Byte); a_Pkt.WriteBEInt8(WolfStatus); WriteEntityMetadata(a_Pkt, EntityMetadata::WolfDamageTaken, EntityMetadataType::Float); a_Pkt.WriteBEFloat(static_cast(a_Mob.GetHealth())); // TODO Not use the current health WriteEntityMetadata(a_Pkt, EntityMetadata::WolfBegging, EntityMetadataType::Boolean); a_Pkt.WriteBool(Wolf.IsBegging()); WriteEntityMetadata(a_Pkt, EntityMetadata::WolfCollarColour, EntityMetadataType::VarInt); a_Pkt.WriteVarInt32(static_cast(Wolf.GetCollarColor())); break; } // case mtWolf case mtZombie: { // XXX Zombies were also split into new sublcasses; this doesn't handle that. auto & Zombie = static_cast(a_Mob); WriteEntityMetadata(a_Pkt, EntityMetadata::ZombieIsBaby, EntityMetadataType::Boolean); a_Pkt.WriteBool(Zombie.IsBaby()); break; } // case mtZombie case mtZombiePigman: { auto & ZombiePigman = static_cast(a_Mob); WriteEntityMetadata(a_Pkt, EntityMetadata::AgeableIsBaby, EntityMetadataType::Boolean); a_Pkt.WriteBool(ZombiePigman.IsBaby()); break; } // case mtZombiePigman case mtBlaze: case mtEnderDragon: case mtIronGolem: case mtSnowGolem: case mtSpider: case mtZombieVillager: case mtElderGuardian: case mtGuardian: { // TODO: Mobs with extra fields that aren't implemented break; } case mtCat: case mtCod: case mtDolphin: case mtDonkey: case mtDrowned: case mtEvoker: case mtIllusioner: case mtLlama: case mtMule: case mtParrot: case mtPhantom: case mtPolarBear: case mtPufferfish: case mtSalmon: case mtShulker: case mtStray: case mtSkeletonHorse: case mtZombieHorse: case mtTropicalFish: case mtTurtle: case mtVex: case mtVindicator: case mtHusk: { // Todo: Mobs not added yet. Grouped ones have the same metadata ASSERT(!"cProtocol_1_14::WriteMobMetadata: received unimplemented type"); break; } case mtMooshroom: case mtCaveSpider: { // Not mentioned on http://wiki.vg/Entities break; } case mtEndermite: case mtGiant: case mtSilverfish: case mtSquid: case mtWitherSkeleton: { // Mobs with no extra fields break; } default: UNREACHABLE("cProtocol_1_14::WriteMobMetadata: received mob of invalid type"); } // switch (a_Mob.GetType()) } //////////////////////////////////////////////////////////////////////////////// // cProtocol_1_14_1: cProtocol::Version cProtocol_1_14_1::GetProtocolVersion() const { return Version::v1_14_1; } //////////////////////////////////////////////////////////////////////////////// // cProtocol_1_14_2: cProtocol::Version cProtocol_1_14_2::GetProtocolVersion() const { return Version::v1_14_2; } //////////////////////////////////////////////////////////////////////////////// // cProtocol_1_14_3: cProtocol::Version cProtocol_1_14_3::GetProtocolVersion() const { return Version::v1_14_3; } //////////////////////////////////////////////////////////////////////////////// // cProtocol_1_14_4: cProtocol::Version cProtocol_1_14_4::GetProtocolVersion() const { return Version::v1_14_4; } ================================================ FILE: src/Protocol/Protocol_1_14.h ================================================ // Protocol_1_14.h /* Declares the 1.14 protocol classes: - cProtocol_1_14 - release 1.14 protocol (#477) */ #pragma once #include "Protocol_1_13.h" class cProtocol_1_14: public cProtocol_1_13_2 { using Super = cProtocol_1_13_2; public: using Super::Super; protected: virtual void SendBlockAction (Vector3i a_BlockPos, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType) override; virtual void SendBlockBreakAnim (UInt32 a_EntityID, Vector3i a_BlockPos, char a_Stage) override; virtual void SendBlockChange (Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override; virtual void SendEditSign (Vector3i a_BlockPos) override; ///< Request the client to open up the sign editor for the sign (1.6+) virtual void SendEntityAnimation (const cEntity & a_Entity, EntityAnimation a_Animation) override; virtual void SendEntitySpawn (const cEntity & a_Entity, const UInt8 a_ObjectType, const Int32 a_ObjectData) override; virtual void SendLogin (const cPlayer & a_Player, const cWorld & a_World) override; virtual void SendMapData (const cMap & a_Map, int a_DataStartX, int a_DataStartY) override; virtual void SendPaintingSpawn (const cPainting & a_Painting) override; virtual void SendParticleEffect (const AString & a_ParticleName, Vector3f a_Src, Vector3f a_Offset, float a_ParticleData, int a_ParticleAmount, std::array a_Data) override; virtual void SendRespawn (eDimension a_Dimension) override; virtual void SendSoundParticleEffect (const EffectID a_EffectID, Vector3i a_Origin, int a_Data) override; virtual void SendUpdateBlockEntity (cBlockEntity & a_BlockEntity) override; virtual void SendUpdateSign (Vector3i a_BlockPos, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4) override; virtual void SendWindowOpen (const cWindow & a_Window) override; virtual UInt8 GetEntityMetadataID(EntityMetadata a_Metadata) const override; virtual UInt32 GetPacketID(ePacketType a_PacketType) const override; virtual std::pair GetItemFromProtocolID(UInt32 a_ProtocolID) const override; virtual UInt32 GetProtocolBlockType(BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override; virtual signed char GetProtocolEntityStatus(EntityAnimation a_Animation) const override; virtual UInt8 GetProtocolEntityType(const cEntity & a_Entity) const override; virtual UInt32 GetProtocolItemType(short a_ItemID, short a_ItemDamage) const override; virtual UInt32 GetProtocolMobType(eMonsterType a_MobType) const override; virtual int GetProtocolParticleID(const AString & a_ParticleName) const override; virtual UInt32 GetProtocolStatisticType(CustomStatistic a_Statistic) const override; virtual Version GetProtocolVersion() const override; virtual bool HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType) override; virtual void HandlePacketBlockDig(cByteBuffer & a_ByteBuffer) override; virtual void HandlePacketBlockPlace(cByteBuffer & a_ByteBuffer) override; virtual void HandlePacketUpdateSign(cByteBuffer & a_ByteBuffer) override; virtual void WriteEntityMetadata(cPacketizer & a_Pkt, EntityMetadata a_Metadata, EntityMetadataType a_FieldType) const override; virtual void WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_Entity) const override; virtual void WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mob) const override; }; class cProtocol_1_14_1: public cProtocol_1_14 { using Super = cProtocol_1_14; public: using Super::Super; protected: virtual Version GetProtocolVersion() const override; }; class cProtocol_1_14_2: public cProtocol_1_14_1 { using Super = cProtocol_1_14_1; public: using Super::Super; protected: virtual Version GetProtocolVersion() const override; }; class cProtocol_1_14_3: public cProtocol_1_14_2 { using Super = cProtocol_1_14_2; public: using Super::Super; protected: virtual Version GetProtocolVersion() const override; }; class cProtocol_1_14_4: public cProtocol_1_14_3 { using Super = cProtocol_1_14_3; public: using Super::Super; protected: virtual Version GetProtocolVersion() const override; }; ================================================ FILE: src/Protocol/Protocol_1_8.cpp ================================================ // Protocol_1_8.cpp /* Implements the 1.8 protocol classes: - cProtocol_1_8_0 - release 1.8 protocol (#47) */ #include "Globals.h" #include "Protocol_1_8.h" #include "main.h" #include "../mbedTLS++/Sha1Checksum.h" #include "Packetizer.h" #include "../ClientHandle.h" #include "../Root.h" #include "../Server.h" #include "../World.h" #include "../EffectID.h" #include "../StringCompression.h" #include "../CompositeChat.h" #include "../UUID.h" #include "../World.h" #include "../JsonUtils.h" #include "../WorldStorage/FastNBT.h" #include "../WorldStorage/EnchantmentSerializer.h" #include "../Entities/ExpOrb.h" #include "../Entities/Minecart.h" #include "../Entities/FallingBlock.h" #include "../Entities/Floater.h" #include "../Entities/Painting.h" #include "../Entities/Pickup.h" #include "../Entities/Player.h" #include "../Entities/ItemFrame.h" #include "../Entities/ArrowEntity.h" #include "../Entities/FireworkEntity.h" #include "../Mobs/IncludeAllMonsters.h" #include "../UI/Window.h" #include "../UI/HorseWindow.h" #include "../BlockEntities/BannerEntity.h" #include "../BlockEntities/BeaconEntity.h" #include "../BlockEntities/CommandBlockEntity.h" #include "../BlockEntities/EnchantingTableEntity.h" #include "../BlockEntities/MobHeadEntity.h" #include "../BlockEntities/MobSpawnerEntity.h" #include "../BlockEntities/FlowerPotEntity.h" #include "../Bindings/PluginManager.h" const int MAX_ENC_LEN = 512; // Maximum size of the encrypted message; should be 128, but who knows... static const UInt32 CompressionThreshold = 256; // After how large a packet should we compress it. //////////////////////////////////////////////////////////////////////////////// // cProtocol_1_8_0: cProtocol_1_8_0::cProtocol_1_8_0(cClientHandle * a_Client, const AString & a_ServerAddress, State a_State) : Super(a_Client), m_State(a_State), m_ServerAddress(a_ServerAddress), m_IsEncrypted(false) { AStringVector Params; SplitZeroTerminatedStrings(a_ServerAddress, Params); if (Params.size() >= 2) { m_ServerAddress = Params[0]; if (Params[1] == "FML") { LOGD("Forge client connected!"); m_Client->SetIsForgeClient(); } else if (Params.size() == 4) { if (cRoot::Get()->GetServer()->ShouldAllowBungeeCord()) { // BungeeCord handling: // If BC is setup with ip_forward == true, it sends additional data in the login packet's ServerAddress field: // hostname\00ip-address\00uuid\00profile-properties-as-json LOGD("Player at %s connected via BungeeCord", Params[1].c_str()); cUUID UUID; UUID.FromString(Params[2]); Json::Value root; if (!JsonUtils::ParseString(Params[3], root)) { LOGERROR("Unable to parse player properties: '%s'", Params[3]); m_Client->ProxyInit(Params[1], UUID); } else { m_Client->ProxyInit(Params[1], UUID, root); } } else { LOG("BungeeCord is disabled, but client sent additional data, set AllowBungeeCord=1 if you want to allow it"); } } else { LOG("Unknown additional data sent in server address (BungeeCord/FML?): %zu parameters", Params.size()); // TODO: support FML + BungeeCord? (what parameters does it send in that case?) https://github.com/SpigotMC/BungeeCord/issues/899 } } // Create the comm log file, if so requested: if (g_ShouldLogCommIn || g_ShouldLogCommOut) { static int sCounter = 0; cFile::CreateFolder("CommLogs"); AString IP(a_Client->GetIPString()); ReplaceString(IP, ":", "_"); auto FileName = fmt::format(FMT_STRING("CommLogs/{:x}_{}__{}.log"), static_cast(time(nullptr)), sCounter++, IP.c_str() ); if (!m_CommLogFile.Open(FileName, cFile::fmWrite)) { LOG("Cannot log communication to file, the log file \"%s\" cannot be opened for writing.", FileName.c_str()); } } } void cProtocol_1_8_0::DataReceived(cByteBuffer & a_Buffer, ContiguousByteBuffer & a_Data) { if (m_IsEncrypted) { m_Decryptor.ProcessData(a_Data.data(), a_Data.size()); } AddReceivedData(a_Buffer, a_Data); } void cProtocol_1_8_0::DataPrepared(ContiguousByteBuffer & a_Data) { if (m_IsEncrypted) { m_Encryptor.ProcessData(a_Data.data(), a_Data.size()); } } void cProtocol_1_8_0::SendAttachEntity(const cEntity & a_Entity, const cEntity & a_Vehicle) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktAttachEntity); Pkt.WriteBEUInt32(a_Entity.GetUniqueID()); Pkt.WriteBEUInt32(a_Vehicle.GetUniqueID()); Pkt.WriteBool(false); } void cProtocol_1_8_0::SendBlockAction(Vector3i a_BlockPos, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktBlockAction); Pkt.WriteXYZPosition64(a_BlockPos); Pkt.WriteBEInt8(a_Byte1); Pkt.WriteBEInt8(a_Byte2); Pkt.WriteVarInt32(a_BlockType); } void cProtocol_1_8_0::SendBlockBreakAnim(UInt32 a_EntityID, Vector3i a_BlockPos, char a_Stage) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktBlockBreakAnim); Pkt.WriteVarInt32(a_EntityID); Pkt.WriteXYZPosition64(a_BlockPos); Pkt.WriteBEInt8(a_Stage); } void cProtocol_1_8_0::SendBlockChange(Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktBlockChange); Pkt.WriteXYZPosition64(a_BlockPos); Pkt.WriteVarInt32((static_cast(a_BlockType) << 4) | (static_cast(a_BlockMeta) & 15)); } void cProtocol_1_8_0::SendBlockChanges(int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktBlockChanges); Pkt.WriteBEInt32(a_ChunkX); Pkt.WriteBEInt32(a_ChunkZ); Pkt.WriteVarInt32(static_cast(a_Changes.size())); for (const auto & Change : a_Changes) { Int16 Coords = static_cast(Change.m_RelY | (Change.m_RelZ << 8) | (Change.m_RelX << 12)); Pkt.WriteBEInt16(Coords); Pkt.WriteVarInt32(static_cast(Change.m_BlockType & 0xFFF) << 4 | (Change.m_BlockMeta & 0xF)); } } void cProtocol_1_8_0::SendBossBarAdd(UInt32 a_UniqueID, const cCompositeChat & a_Title, float a_FractionFilled, BossBarColor a_Color, BossBarDivisionType a_DivisionType, bool a_DarkenSky, bool a_PlayEndMusic, bool a_CreateFog) { // No such packet here } void cProtocol_1_8_0::SendBossBarRemove(UInt32 a_UniqueID) { // No such packet here } void cProtocol_1_8_0::SendBossBarUpdateFlags(UInt32 a_UniqueID, bool a_DarkenSky, bool a_PlayEndMusic, bool a_CreateFog) { // No such packet here } void cProtocol_1_8_0::SendBossBarUpdateHealth(UInt32 a_UniqueID, float a_FractionFilled) { // No such packet here } void cProtocol_1_8_0::SendBossBarUpdateStyle(UInt32 a_UniqueID, BossBarColor a_Color, BossBarDivisionType a_DivisionType) { // No such packet here } void cProtocol_1_8_0::SendBossBarUpdateTitle(UInt32 a_UniqueID, const cCompositeChat & a_Title) { // No such packet here } void cProtocol_1_8_0::SendCameraSetTo(const cEntity & a_Entity) { cPacketizer Pkt(*this, pktCameraSetTo); Pkt.WriteVarInt32(a_Entity.GetUniqueID()); } void cProtocol_1_8_0::SendChat(const AString & a_Message, eChatType a_Type) { ASSERT(m_State == 3); // In game mode? SendChatRaw(JsonUtils::SerializeSingleValueJsonObject("text", a_Message), a_Type); } void cProtocol_1_8_0::SendChat(const cCompositeChat & a_Message, eChatType a_Type, bool a_ShouldUseChatPrefixes) { ASSERT(m_State == 3); // In game mode? SendChatRaw(a_Message.CreateJsonString(a_ShouldUseChatPrefixes), a_Type); } void cProtocol_1_8_0::SendChatRaw(const AString & a_MessageRaw, eChatType a_Type) { ASSERT(m_State == 3); // In game mode? // Prevent chat messages that might trigger CVE-2021-44228 if (a_MessageRaw.find("${") != std::string::npos) { return; } // Send the json string to the client: cPacketizer Pkt(*this, pktChatRaw); Pkt.WriteString(a_MessageRaw); Pkt.WriteBEInt8([a_Type]() -> signed char { switch (a_Type) { case eChatType::ctChatBox: return 0; case eChatType::ctSystem: return 1; case eChatType::ctAboveActionBar: return 2; } UNREACHABLE("Unsupported chat type"); }()); } void cProtocol_1_8_0::SendChunkData(const ContiguousByteBufferView a_ChunkData) { ASSERT(m_State == 3); // In game mode? cCSLock Lock(m_CSPacket); m_Client->SendData(a_ChunkData); } void cProtocol_1_8_0::SendCollectEntity(const cEntity & a_Collected, const cEntity & a_Collector, unsigned a_Count) { UNUSED(a_Count); ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktCollectEntity); Pkt.WriteVarInt32(a_Collected.GetUniqueID()); Pkt.WriteVarInt32(a_Collector.GetUniqueID()); } void cProtocol_1_8_0::SendDestroyEntity(const cEntity & a_Entity) { ASSERT(m_State == 3); // In game mode? { cPacketizer Pkt(*this, pktDestroyEntity); Pkt.WriteVarInt32(1); Pkt.WriteVarInt32(a_Entity.GetUniqueID()); } if (!a_Entity.IsMob()) { return; } const auto & Mob = static_cast(a_Entity); if ((Mob.GetMobType() == mtEnderDragon) || (Mob.GetMobType() == mtWither)) { SendBossBarRemove(Mob.GetUniqueID()); } } void cProtocol_1_8_0::SendDetachEntity(const cEntity & a_Entity, const cEntity & a_PreviousVehicle) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktAttachEntity); Pkt.WriteBEUInt32(a_Entity.GetUniqueID()); Pkt.WriteBEUInt32(0); Pkt.WriteBool(false); } void cProtocol_1_8_0::SendDisconnect(const AString & a_Reason) { switch (m_State) { case State::Login: { cPacketizer Pkt(*this, pktDisconnectDuringLogin); Pkt.WriteString(JsonUtils::SerializeSingleValueJsonObject("text", a_Reason)); break; } case State::Game: { cPacketizer Pkt(*this, pktDisconnectDuringGame); Pkt.WriteString(JsonUtils::SerializeSingleValueJsonObject("text", a_Reason)); break; } default: { FLOGERROR( "Tried to send disconnect in invalid game state {0}", static_cast(m_State) ); } } } void cProtocol_1_8_0::SendEditSign(Vector3i a_BlockPos) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktEditSign); Pkt.WriteXYZPosition64(a_BlockPos); } void cProtocol_1_8_0::SendEntityAnimation(const cEntity & a_Entity, const EntityAnimation a_Animation) { ASSERT(m_State == 3); // In game mode? if (a_Animation == EntityAnimation::PlayerEntersBed) { ASSERT(a_Entity.IsPlayer()); const auto BedPosition = static_cast(a_Entity).GetLastBedPos(); cPacketizer Pkt(*this, pktUseBed); Pkt.WriteVarInt32(a_Entity.GetUniqueID()); Pkt.WriteXYZPosition64(BedPosition.x, BedPosition.y, BedPosition.z); return; } if (const auto AnimationID = GetProtocolEntityAnimation(a_Animation); AnimationID != static_cast(-1)) { cPacketizer Pkt(*this, pktEntityAnimation); Pkt.WriteVarInt32(a_Entity.GetUniqueID()); Pkt.WriteBEUInt8(AnimationID); return; } if (const auto StatusID = GetProtocolEntityStatus(a_Animation); StatusID != -1) { cPacketizer Pkt(*this, pktEntityStatus); Pkt.WriteBEUInt32(a_Entity.GetUniqueID()); Pkt.WriteBEInt8(StatusID); } } void cProtocol_1_8_0::SendEntityEffect(const cEntity & a_Entity, int a_EffectID, int a_Amplifier, int a_Duration) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktEntityEffect); Pkt.WriteVarInt32(a_Entity.GetUniqueID()); Pkt.WriteBEUInt8(static_cast(a_EffectID)); Pkt.WriteBEUInt8(static_cast(a_Amplifier)); Pkt.WriteVarInt32(static_cast(a_Duration)); Pkt.WriteBool(false); // Hide particles } void cProtocol_1_8_0::SendEntityEquipment(const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktEntityEquipment); Pkt.WriteVarInt32(a_Entity.GetUniqueID()); Pkt.WriteBEInt16(a_SlotNum); WriteItem(Pkt, a_Item); } void cProtocol_1_8_0::SendEntityHeadLook(const cEntity & a_Entity) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktEntityHeadLook); Pkt.WriteVarInt32(a_Entity.GetUniqueID()); Pkt.WriteByteAngle(a_Entity.GetHeadYaw()); } void cProtocol_1_8_0::SendEntityLook(const cEntity & a_Entity) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktEntityLook); Pkt.WriteVarInt32(a_Entity.GetUniqueID()); Pkt.WriteByteAngle(a_Entity.GetYaw()); Pkt.WriteByteAngle(a_Entity.GetPitch()); Pkt.WriteBool(a_Entity.IsOnGround()); } void cProtocol_1_8_0::SendEntityMetadata(const cEntity & a_Entity) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktEntityMeta); Pkt.WriteVarInt32(a_Entity.GetUniqueID()); WriteEntityMetadata(Pkt, a_Entity); Pkt.WriteBEUInt8(0x7f); // The termination byte } void cProtocol_1_8_0::SendEntityPosition(const cEntity & a_Entity) { ASSERT(m_State == 3); // In game mode? const auto Delta = (a_Entity.GetPosition() * 32).Floor() - (a_Entity.GetLastSentPosition() * 32).Floor(); // Ensure that the delta has enough precision and is within range of a BEInt8: if ( Delta.HasNonZeroLength() && cByteBuffer::CanBEInt8Represent(Delta.x) && cByteBuffer::CanBEInt8Represent(Delta.y) && cByteBuffer::CanBEInt8Represent(Delta.z) ) { const auto Move = static_cast>(Delta); // Difference within limitations, use a relative move packet if (a_Entity.IsOrientationDirty()) { cPacketizer Pkt(*this, pktEntityRelMoveLook); Pkt.WriteVarInt32(a_Entity.GetUniqueID()); Pkt.WriteBEInt8(Move.x); Pkt.WriteBEInt8(Move.y); Pkt.WriteBEInt8(Move.z); Pkt.WriteByteAngle(a_Entity.GetYaw()); Pkt.WriteByteAngle(a_Entity.GetPitch()); Pkt.WriteBool(a_Entity.IsOnGround()); } else { cPacketizer Pkt(*this, pktEntityRelMove); Pkt.WriteVarInt32(a_Entity.GetUniqueID()); Pkt.WriteBEInt8(Move.x); Pkt.WriteBEInt8(Move.y); Pkt.WriteBEInt8(Move.z); Pkt.WriteBool(a_Entity.IsOnGround()); } return; } // Too big or small a movement, do a teleport. cPacketizer Pkt(*this, pktTeleportEntity); Pkt.WriteVarInt32(a_Entity.GetUniqueID()); Pkt.WriteFPInt(a_Entity.GetPosX()); Pkt.WriteFPInt(a_Entity.GetPosY()); Pkt.WriteFPInt(a_Entity.GetPosZ()); Pkt.WriteByteAngle(a_Entity.GetYaw()); Pkt.WriteByteAngle(a_Entity.GetPitch()); Pkt.WriteBool(a_Entity.IsOnGround()); } void cProtocol_1_8_0::SendEntityProperties(const cEntity & a_Entity) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktEntityProperties); Pkt.WriteVarInt32(a_Entity.GetUniqueID()); WriteEntityProperties(Pkt, a_Entity); } void cProtocol_1_8_0::SendEntityVelocity(const cEntity & a_Entity) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktEntityVelocity); Pkt.WriteVarInt32(a_Entity.GetUniqueID()); // 400 = 8000 / 20 ... Conversion from our speed in m / s to 8000 m / tick Pkt.WriteBEInt16(static_cast(a_Entity.GetSpeedX() * 400)); Pkt.WriteBEInt16(static_cast(a_Entity.GetSpeedY() * 400)); Pkt.WriteBEInt16(static_cast(a_Entity.GetSpeedZ() * 400)); } void cProtocol_1_8_0::SendExperience(void) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktExperience); cPlayer * Player = m_Client->GetPlayer(); Pkt.WriteBEFloat(Player->GetXpPercentage()); Pkt.WriteVarInt32(static_cast(Player->GetXpLevel())); Pkt.WriteVarInt32(static_cast(Player->GetCurrentXp())); } void cProtocol_1_8_0::SendExperienceOrb(const cExpOrb & a_ExpOrb) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktSpawnExperienceOrb); Pkt.WriteVarInt32(a_ExpOrb.GetUniqueID()); Pkt.WriteFPInt(a_ExpOrb.GetPosX()); Pkt.WriteFPInt(a_ExpOrb.GetPosY()); Pkt.WriteFPInt(a_ExpOrb.GetPosZ()); Pkt.WriteBEInt16(static_cast(a_ExpOrb.GetReward())); } void cProtocol_1_8_0::SendExplosion(const Vector3f a_Position, const float a_Power) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktExplosion); Pkt.WriteBEFloat(a_Position.x); Pkt.WriteBEFloat(a_Position.y); Pkt.WriteBEFloat(a_Position.z); Pkt.WriteBEFloat(a_Power); Pkt.WriteBEUInt32(0); Pkt.WriteBEFloat(0); Pkt.WriteBEFloat(0); Pkt.WriteBEFloat(0); } void cProtocol_1_8_0::SendGameMode(eGameMode a_GameMode) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktGameMode); Pkt.WriteBEUInt8(3); // Reason: Change game mode Pkt.WriteBEFloat(static_cast(a_GameMode)); // The protocol really represents the value with a float! } void cProtocol_1_8_0::SendHealth(void) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktUpdateHealth); cPlayer * Player = m_Client->GetPlayer(); Pkt.WriteBEFloat(static_cast(Player->GetHealth())); Pkt.WriteVarInt32(static_cast(Player->GetFoodLevel())); Pkt.WriteBEFloat(static_cast(Player->GetFoodSaturationLevel())); } void cProtocol_1_8_0::SendHeldItemChange(int a_ItemIndex) { ASSERT((a_ItemIndex >= 0) && (a_ItemIndex <= 8)); // Valid check cPacketizer Pkt(*this, pktHeldItemChange); Pkt.WriteBEInt8(static_cast(a_ItemIndex)); } void cProtocol_1_8_0::SendHideTitle(void) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktTitle); Pkt.WriteVarInt32(3); // Hide title } void cProtocol_1_8_0::SendInventorySlot(char a_WindowID, short a_SlotNum, const cItem & a_Item) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktInventorySlot); Pkt.WriteBEInt8(a_WindowID); Pkt.WriteBEInt16(a_SlotNum); WriteItem(Pkt, a_Item); } void cProtocol_1_8_0::SendKeepAlive(UInt32 a_PingID) { // Drop the packet if the protocol is not in the Game state yet (caused a client crash): if (m_State != 3) { LOGWARNING("Trying to send a KeepAlive packet to a player who's not yet fully logged in (%d). The protocol class prevented the packet.", m_State); return; } cPacketizer Pkt(*this, pktKeepAlive); Pkt.WriteVarInt32(a_PingID); } void cProtocol_1_8_0::SendLeashEntity(const cEntity & a_Entity, const cEntity & a_EntityLeashedTo) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktLeashEntity); Pkt.WriteBEUInt32(a_Entity.GetUniqueID()); Pkt.WriteBEUInt32(a_EntityLeashedTo.GetUniqueID()); Pkt.WriteBool(true); } void cProtocol_1_8_0::SendUnleashEntity(const cEntity & a_Entity) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktLeashEntity); Pkt.WriteBEUInt32(a_Entity.GetUniqueID()); Pkt.WriteBEInt32(-1); Pkt.WriteBool(true); } void cProtocol_1_8_0::SendLogin(const cPlayer & a_Player, const cWorld & a_World) { // Send the Join Game packet: { cServer * Server = cRoot::Get()->GetServer(); cPacketizer Pkt(*this, pktJoinGame); Pkt.WriteBEUInt32(a_Player.GetUniqueID()); Pkt.WriteBEUInt8(static_cast(a_Player.GetEffectiveGameMode()) | (Server->IsHardcore() ? 0x08 : 0)); // Hardcore flag bit 4 Pkt.WriteBEInt8(static_cast(a_World.GetDimension())); Pkt.WriteBEUInt8(2); // TODO: Difficulty (set to Normal) Pkt.WriteBEUInt8(static_cast(Clamp(Server->GetMaxPlayers(), 0, 255))); Pkt.WriteString("default"); // Level type - wtf? Pkt.WriteBool(false); // Reduced Debug Info - wtf? } // Send the spawn position: { cPacketizer Pkt(*this, pktSpawnPosition); Pkt.WriteXYZPosition64(a_World.GetSpawnX(), a_World.GetSpawnY(), a_World.GetSpawnZ()); } // Send the server difficulty: { cPacketizer Pkt(*this, pktDifficulty); Pkt.WriteBEInt8(1); } } void cProtocol_1_8_0::SendLoginSuccess(void) { ASSERT(m_State == 2); // State: login? // Enable compression: { cPacketizer Pkt(*this, pktStartCompression); Pkt.WriteVarInt32(CompressionThreshold); } m_State = State::Game; { cPacketizer Pkt(*this, pktLoginSuccess); Pkt.WriteString(m_Client->GetUUID().ToLongString()); Pkt.WriteString(m_Client->GetUsername()); } } void cProtocol_1_8_0::SendPaintingSpawn(const cPainting & a_Painting) { ASSERT(m_State == 3); // In game mode? double PosX = a_Painting.GetPosX(); double PosY = a_Painting.GetPosY(); double PosZ = a_Painting.GetPosZ(); cPacketizer Pkt(*this, pktSpawnPainting); Pkt.WriteVarInt32(a_Painting.GetUniqueID()); Pkt.WriteString(a_Painting.GetName()); Pkt.WriteXYZPosition64(static_cast(PosX), static_cast(PosY), static_cast(PosZ)); Pkt.WriteBEInt8(static_cast(a_Painting.GetProtocolFacing())); } void cProtocol_1_8_0::SendMapData(const cMap & a_Map, int a_DataStartX, int a_DataStartY) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktMapData); Pkt.WriteVarInt32(a_Map.GetID()); Pkt.WriteBEUInt8(static_cast(a_Map.GetScale())); Pkt.WriteVarInt32(static_cast(a_Map.GetDecorators().size())); for (const auto & Decorator : a_Map.GetDecorators()) { Pkt.WriteBEUInt8(static_cast((static_cast(Decorator.GetType()) << 4) | (Decorator.GetRot() & 0xF))); Pkt.WriteBEUInt8(static_cast(Decorator.GetPixelX())); Pkt.WriteBEUInt8(static_cast(Decorator.GetPixelZ())); } Pkt.WriteBEUInt8(128); Pkt.WriteBEUInt8(128); Pkt.WriteBEUInt8(static_cast(a_DataStartX)); Pkt.WriteBEUInt8(static_cast(a_DataStartY)); Pkt.WriteVarInt32(static_cast(a_Map.GetData().size())); for (auto itr = a_Map.GetData().cbegin(); itr != a_Map.GetData().cend(); ++itr) { Pkt.WriteBEUInt8(*itr); } } void cProtocol_1_8_0::SendPlayerAbilities(void) { ASSERT(m_State == 3); // In game mode? Byte Flags = 0; const cPlayer * Player = m_Client->GetPlayer(); if (Player->IsGameModeCreative() || Player->IsGameModeSpectator()) { Flags |= 0x01; // Invulnerability. } if (Player->IsFlying()) { Flags |= 0x02; } if (Player->CanFly()) { Flags |= 0x04; } if (Player->IsGameModeCreative()) { Flags |= 0x08; // Godmode: creative instant break. } cPacketizer Pkt(*this, pktPlayerAbilities); Pkt.WriteBEUInt8(Flags); Pkt.WriteBEFloat(static_cast(0.05 * Player->GetFlyingMaxSpeed())); Pkt.WriteBEFloat(static_cast(0.1 * Player->GetNormalMaxSpeed())); } void cProtocol_1_8_0::SendParticleEffect(const AString & a_ParticleName, Vector3f a_Src, Vector3f a_Offset, float a_ParticleData, int a_ParticleAmount) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktParticleEffect); Pkt.WriteBEInt32(GetProtocolParticleID(a_ParticleName)); Pkt.WriteBool(false); Pkt.WriteBEFloat(a_Src.x); Pkt.WriteBEFloat(a_Src.y); Pkt.WriteBEFloat(a_Src.z); Pkt.WriteBEFloat(a_Offset.x); Pkt.WriteBEFloat(a_Offset.y); Pkt.WriteBEFloat(a_Offset.z); Pkt.WriteBEFloat(a_ParticleData); Pkt.WriteBEInt32(a_ParticleAmount); } void cProtocol_1_8_0::SendParticleEffect(const AString & a_ParticleName, Vector3f a_Src, Vector3f a_Offset, float a_ParticleData, int a_ParticleAmount, std::array a_Data) { ASSERT(m_State == 3); // In game mode? const auto ParticleID = GetProtocolParticleID(a_ParticleName); cPacketizer Pkt(*this, pktParticleEffect); Pkt.WriteBEInt32(ParticleID); Pkt.WriteBool(false); Pkt.WriteBEFloat(a_Src.x); Pkt.WriteBEFloat(a_Src.y); Pkt.WriteBEFloat(a_Src.z); Pkt.WriteBEFloat(a_Offset.x); Pkt.WriteBEFloat(a_Offset.y); Pkt.WriteBEFloat(a_Offset.z); Pkt.WriteBEFloat(a_ParticleData); Pkt.WriteBEInt32(a_ParticleAmount); switch (ParticleID) { // iconcrack case 36: { Pkt.WriteVarInt32(static_cast(a_Data[0])); Pkt.WriteVarInt32(static_cast(a_Data[1])); break; } // blockcrack // blockdust case 37: case 38: { Pkt.WriteVarInt32(static_cast(a_Data[0])); break; } } } void cProtocol_1_8_0::SendPlayerListAddPlayer(const cPlayer & a_Player) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktPlayerList); Pkt.WriteVarInt32(0); Pkt.WriteVarInt32(1); Pkt.WriteUUID(a_Player.GetUUID()); Pkt.WriteString(a_Player.GetPlayerListName()); const Json::Value & Properties = a_Player.GetClientHandle()->GetProperties(); Pkt.WriteVarInt32(Properties.size()); for (auto & Node : Properties) { Pkt.WriteString(Node.get("name", "").asString()); Pkt.WriteString(Node.get("value", "").asString()); AString Signature = Node.get("signature", "").asString(); if (Signature.empty()) { Pkt.WriteBool(false); } else { Pkt.WriteBool(true); Pkt.WriteString(Signature); } } Pkt.WriteVarInt32(static_cast(a_Player.GetEffectiveGameMode())); Pkt.WriteVarInt32(static_cast(a_Player.GetClientHandle()->GetPing())); Pkt.WriteBool(false); } void cProtocol_1_8_0::SendPlayerListHeaderFooter(const cCompositeChat & a_Header, const cCompositeChat & a_Footer) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktPlayerListHeaderFooter); Pkt.WriteString(a_Header.CreateJsonString(false)); Pkt.WriteString(a_Footer.CreateJsonString(false)); } void cProtocol_1_8_0::SendPlayerListRemovePlayer(const cPlayer & a_Player) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktPlayerList); Pkt.WriteVarInt32(4); Pkt.WriteVarInt32(1); Pkt.WriteUUID(a_Player.GetUUID()); } void cProtocol_1_8_0::SendPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_CustomName) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktPlayerList); Pkt.WriteVarInt32(3); Pkt.WriteVarInt32(1); Pkt.WriteUUID(a_Player.GetUUID()); if (a_CustomName.empty()) { Pkt.WriteBool(false); } else { Pkt.WriteBool(true); Pkt.WriteString(JsonUtils::SerializeSingleValueJsonObject("text", a_CustomName)); } } void cProtocol_1_8_0::SendPlayerListUpdateGameMode(const cPlayer & a_Player) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktPlayerList); Pkt.WriteVarInt32(1); Pkt.WriteVarInt32(1); Pkt.WriteUUID(a_Player.GetUUID()); Pkt.WriteVarInt32(static_cast(a_Player.GetEffectiveGameMode())); } void cProtocol_1_8_0::SendPlayerListUpdatePing() { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktPlayerList); Pkt.WriteVarInt32(2); const auto World = m_Client->GetPlayer()->GetWorld(); Pkt.WriteVarInt32(static_cast(World->GetPlayerCount())); World->ForEachPlayer([&Pkt](cPlayer & a_Player) { Pkt.WriteUUID(a_Player.GetUUID()); Pkt.WriteVarInt32(static_cast(a_Player.GetClientHandle()->GetPing())); return false; }); } void cProtocol_1_8_0::SendPlayerMoveLook (const Vector3d a_Pos, const float a_Yaw, const float a_Pitch, const bool a_IsRelative) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktPlayerMoveLook); Pkt.WriteBEDouble(a_Pos.x); Pkt.WriteBEDouble(a_Pos.y); Pkt.WriteBEDouble(a_Pos.z); Pkt.WriteBEFloat(a_Yaw); Pkt.WriteBEFloat(a_Pitch); if (a_IsRelative) { // Set all bits to 1 - makes everything relative Pkt.WriteBEUInt8(static_cast(-1)); } else { // Set all bits to 0 - make everything absolute Pkt.WriteBEUInt8(0); } } void cProtocol_1_8_0::SendPlayerMoveLook(void) { cPlayer * Player = m_Client->GetPlayer(); SendPlayerMoveLook(Player->GetPosition(), static_cast(Player->GetYaw()), static_cast(Player->GetPitch()), false); } void cProtocol_1_8_0::SendPlayerPermissionLevel() { // 1.8 has no concept of a permission level. } void cProtocol_1_8_0::SendPlayerPosition(void) { // There is no dedicated packet for this, send the whole thing: SendPlayerMoveLook(); } void cProtocol_1_8_0::SendPlayerSpawn(const cPlayer & a_Player) { // Called to spawn another player for the client cPacketizer Pkt(*this, pktSpawnOtherPlayer); Pkt.WriteVarInt32(a_Player.GetUniqueID()); Pkt.WriteUUID(a_Player.GetUUID()); Vector3d LastSentPos = a_Player.GetLastSentPosition(); Pkt.WriteFPInt(LastSentPos.x); Pkt.WriteFPInt(LastSentPos.y + 0.001); // The "+ 0.001" is there because otherwise the player falls through the block they were standing on. Pkt.WriteFPInt(LastSentPos.z); Pkt.WriteByteAngle(a_Player.GetYaw()); Pkt.WriteByteAngle(a_Player.GetPitch()); Pkt.WriteBEInt16(a_Player.GetEquippedItem().IsEmpty() ? 0 : a_Player.GetEquippedItem().m_ItemType); WriteEntityMetadata(Pkt, a_Player); Pkt.WriteBEUInt8(0x7f); // Metadata: end } void cProtocol_1_8_0::SendPluginMessage(const AString & a_Channel, const ContiguousByteBufferView a_Message) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktPluginMessage); Pkt.WriteString(a_Channel); Pkt.WriteBuf(a_Message); } void cProtocol_1_8_0::SendRemoveEntityEffect(const cEntity & a_Entity, int a_EffectID) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktRemoveEntityEffect); Pkt.WriteVarInt32(a_Entity.GetUniqueID()); Pkt.WriteBEUInt8(static_cast(a_EffectID)); } void cProtocol_1_8_0::SendResetTitle(void) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktTitle); Pkt.WriteVarInt32(4); // Reset title } void cProtocol_1_8_0::SendResourcePack(const AString & a_ResourcePackUrl) { cPacketizer Pkt(*this, pktResourcePack); cSha1Checksum Checksum; Checksum.Update(reinterpret_cast(a_ResourcePackUrl.c_str()), a_ResourcePackUrl.size()); Byte Digest[20]; Checksum.Finalize(Digest); AString Sha1Output; cSha1Checksum::DigestToHex(Digest, Sha1Output); Pkt.WriteString(a_ResourcePackUrl); Pkt.WriteString(Sha1Output); } void cProtocol_1_8_0::SendRespawn(eDimension a_Dimension) { cPacketizer Pkt(*this, pktRespawn); cPlayer * Player = m_Client->GetPlayer(); Pkt.WriteBEInt32(static_cast(a_Dimension)); Pkt.WriteBEUInt8(2); // TODO: Difficulty (set to Normal) Pkt.WriteBEUInt8(static_cast(Player->GetEffectiveGameMode())); Pkt.WriteString("default"); } void cProtocol_1_8_0::SendScoreboardObjective(const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktScoreboardObjective); Pkt.WriteString(a_Name); Pkt.WriteBEUInt8(a_Mode); if ((a_Mode == 0) || (a_Mode == 2)) { Pkt.WriteString(a_DisplayName); Pkt.WriteString("integer"); } } void cProtocol_1_8_0::SendScoreUpdate(const AString & a_Objective, const AString & a_Player, cObjective::Score a_Score, Byte a_Mode) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktUpdateScore); Pkt.WriteString(a_Player); Pkt.WriteBEUInt8(a_Mode); Pkt.WriteString(a_Objective); if (a_Mode != 1) { Pkt.WriteVarInt32(static_cast(a_Score)); } } void cProtocol_1_8_0::SendDisplayObjective(const AString & a_Objective, cScoreboard::eDisplaySlot a_Display) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktDisplayObjective); Pkt.WriteBEUInt8(static_cast(a_Display)); Pkt.WriteString(a_Objective); } void cProtocol_1_8_0::SendSetSubTitle(const cCompositeChat & a_SubTitle) { SendSetRawSubTitle(a_SubTitle.CreateJsonString(false)); } void cProtocol_1_8_0::SendSetRawSubTitle(const AString & a_SubTitle) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktTitle); Pkt.WriteVarInt32(1); // Set subtitle Pkt.WriteString(a_SubTitle); } void cProtocol_1_8_0::SendSetTitle(const cCompositeChat & a_Title) { SendSetRawTitle(a_Title.CreateJsonString(false)); } void cProtocol_1_8_0::SendSetRawTitle(const AString & a_Title) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktTitle); Pkt.WriteVarInt32(0); // Set title Pkt.WriteString(a_Title); } void cProtocol_1_8_0::SendSoundEffect(const AString & a_SoundName, Vector3d a_Origin, float a_Volume, float a_Pitch) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktSoundEffect); Pkt.WriteString(a_SoundName); Pkt.WriteBEInt32(static_cast(a_Origin.x * 8.0)); Pkt.WriteBEInt32(static_cast(a_Origin.y * 8.0)); Pkt.WriteBEInt32(static_cast(a_Origin.z * 8.0)); Pkt.WriteBEFloat(a_Volume); Pkt.WriteBEUInt8(static_cast(a_Pitch * 63)); } void cProtocol_1_8_0::SendSoundParticleEffect(const EffectID a_EffectID, Vector3i a_Origin, int a_Data) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktSoundParticleEffect); Pkt.WriteBEInt32(static_cast(a_EffectID)); Pkt.WriteXYZPosition64(a_Origin); Pkt.WriteBEInt32(a_Data); Pkt.WriteBool(false); } void cProtocol_1_8_0::SendSpawnEntity(const cEntity & a_Entity) { Int32 EntityData = /* Default: velocity present flag */ 1; const auto EntityType = GetProtocolEntityType(a_Entity); if (a_Entity.IsMinecart()) { const auto & Cart = static_cast(a_Entity); EntityData = static_cast(Cart.GetPayload()); } else if (a_Entity.IsItemFrame()) { const auto & Frame = static_cast(a_Entity); EntityData = static_cast(Frame.GetProtocolFacing()); } else if (a_Entity.IsFallingBlock()) { const auto & Block = static_cast(a_Entity); EntityData = Block.GetBlockType() | (static_cast(Block.GetBlockMeta()) << 12); } else if (a_Entity.IsFloater()) { const auto & Floater = static_cast(a_Entity); EntityData = static_cast(Floater.GetOwnerID()); } else if (a_Entity.IsProjectile()) { using PType = cProjectileEntity::eKind; const auto & Projectile = static_cast(a_Entity); if (Projectile.GetProjectileKind() == PType::pkArrow) { const auto & Arrow = static_cast(Projectile); EntityData = static_cast(Arrow.GetCreatorUniqueID() + 1); } } SendEntitySpawn(a_Entity, EntityType, EntityData); } void cProtocol_1_8_0::SendSpawnMob(const cMonster & a_Mob) { ASSERT(m_State == 3); // In game mode? const auto MobType = GetProtocolMobType(a_Mob.GetMobType()); // If the type is not valid in this protocol bail out: if (MobType == 0) { return; } cPacketizer Pkt(*this, pktSpawnMob); Pkt.WriteVarInt32(a_Mob.GetUniqueID()); Pkt.WriteBEUInt8(static_cast(MobType)); Vector3d LastSentPos = a_Mob.GetLastSentPosition(); Pkt.WriteFPInt(LastSentPos.x); Pkt.WriteFPInt(LastSentPos.y); Pkt.WriteFPInt(LastSentPos.z); Pkt.WriteByteAngle(a_Mob.GetHeadYaw()); // Doesn't seem to be used Pkt.WriteByteAngle(a_Mob.GetPitch()); Pkt.WriteByteAngle(a_Mob.GetYaw()); Pkt.WriteBEInt16(static_cast(a_Mob.GetSpeedX() * 400)); Pkt.WriteBEInt16(static_cast(a_Mob.GetSpeedY() * 400)); Pkt.WriteBEInt16(static_cast(a_Mob.GetSpeedZ() * 400)); WriteEntityMetadata(Pkt, a_Mob); Pkt.WriteBEUInt8(0x7f); // Metadata terminator } void cProtocol_1_8_0::SendStatistics(const StatisticsManager & a_Manager) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktStatistics); // No need to check Size != 0. // Assume that the vast majority of the time there's at least one statistic to send: Pkt.WriteVarInt32(static_cast(a_Manager.Custom.size())); for (const auto & [Statistic, Value] : a_Manager.Custom) { Pkt.WriteString(GetProtocolStatisticName(Statistic)); Pkt.WriteVarInt32(static_cast(Value)); } } void cProtocol_1_8_0::SendTabCompletionResults(const AStringVector & a_Results) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktTabCompletionResults); Pkt.WriteVarInt32(static_cast(a_Results.size())); for (AStringVector::const_iterator itr = a_Results.begin(), end = a_Results.end(); itr != end; ++itr) { Pkt.WriteString(*itr); } } void cProtocol_1_8_0::SendThunderbolt(Vector3i a_Origin) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktSpawnGlobalEntity); Pkt.WriteVarInt32(0); // EntityID = 0, always Pkt.WriteBEUInt8(1); // Type = Thunderbolt Pkt.WriteFPInt(a_Origin.x); Pkt.WriteFPInt(a_Origin.y); Pkt.WriteFPInt(a_Origin.z); } void cProtocol_1_8_0::SendTitleTimes(int a_FadeInTicks, int a_DisplayTicks, int a_FadeOutTicks) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktTitle); Pkt.WriteVarInt32(2); // Set title display times Pkt.WriteBEInt32(a_FadeInTicks); Pkt.WriteBEInt32(a_DisplayTicks); Pkt.WriteBEInt32(a_FadeOutTicks); } void cProtocol_1_8_0::SendTimeUpdate(const cTickTimeLong a_WorldAge, const cTickTimeLong a_WorldDate, const bool a_DoDaylightCycle) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktTimeUpdate); Pkt.WriteBEInt64(a_WorldAge.count()); if (a_DoDaylightCycle) { Pkt.WriteBEInt64(a_WorldDate.count()); } else { // Negating the date stops time from advancing on the client // (the std::min construction is to handle the case where the date is exactly zero): Pkt.WriteBEInt64(std::min(-a_WorldDate.count(), -1LL)); } } void cProtocol_1_8_0::SendUnloadChunk(int a_ChunkX, int a_ChunkZ) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktUnloadChunk); Pkt.WriteBEInt32(a_ChunkX); Pkt.WriteBEInt32(a_ChunkZ); Pkt.WriteBool(true); Pkt.WriteBEInt16(0); // Primary bitmap Pkt.WriteVarInt32(0); // Data size } void cProtocol_1_8_0::SendUpdateBlockEntity(cBlockEntity & a_BlockEntity) { ASSERT(m_State == 3); // In game mode? Byte Action; switch (a_BlockEntity.GetBlockType()) { case E_BLOCK_CHEST: case E_BLOCK_ENCHANTMENT_TABLE: case E_BLOCK_END_PORTAL: case E_BLOCK_TRAPPED_CHEST: { // The ones with a action of 0 is just a workaround to send the block entities to a client. // Todo: 18.09.2020 - remove this when block entities are transmitted in the ChunkData packet - 12xx12 Action = 0; break; } case E_BLOCK_MOB_SPAWNER: Action = 1; break; // Update mob spawner spinny mob thing case E_BLOCK_COMMAND_BLOCK: Action = 2; break; // Update command block text case E_BLOCK_BEACON: Action = 3; break; // Update beacon entity case E_BLOCK_HEAD: Action = 4; break; // Update mobhead entity case E_BLOCK_FLOWER_POT: Action = 5; break; // Update flower pot case E_BLOCK_WALL_BANNER: case E_BLOCK_STANDING_BANNER: Action = 6; break; // Update banner default: return; // Block entities change between versions } cPacketizer Pkt(*this, pktUpdateBlockEntity); Pkt.WriteXYZPosition64(a_BlockEntity.GetPosX(), a_BlockEntity.GetPosY(), a_BlockEntity.GetPosZ()); Pkt.WriteBEUInt8(Action); cFastNBTWriter Writer; WriteBlockEntity(Writer, a_BlockEntity); Writer.Finish(); Pkt.WriteBuf(Writer.GetResult()); } void cProtocol_1_8_0::SendUpdateSign(Vector3i a_BlockPos, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktUpdateSign); Pkt.WriteXYZPosition64(a_BlockPos); AString Lines[] = { a_Line1, a_Line2, a_Line3, a_Line4 }; for (size_t i = 0; i < ARRAYCOUNT(Lines); i++) { Pkt.WriteString(JsonUtils::SerializeSingleValueJsonObject("text", Lines[i])); } } void cProtocol_1_8_0::SendUnlockRecipe(UInt32 a_RecipeID) { // Client doesn't support this feature return; } void cProtocol_1_8_0::SendInitRecipes(UInt32 a_RecipeID) { // Client doesn't support this feature return; } void cProtocol_1_8_0::SendWeather(eWeather a_Weather) { ASSERT(m_State == 3); // In game mode? { cPacketizer Pkt(*this, pktWeather); Pkt.WriteBEUInt8((a_Weather == wSunny) ? 1 : 2); // End rain / begin rain Pkt.WriteBEFloat(0); // Unused for weather } // TODO: Fade effect, somehow } void cProtocol_1_8_0::SendWholeInventory(const cWindow & a_Window) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktWindowItems); Pkt.WriteBEUInt8(static_cast(a_Window.GetWindowID())); Pkt.WriteBEInt16(static_cast(a_Window.GetNumSlots())); cItems Slots; a_Window.GetSlots(*(m_Client->GetPlayer()), Slots); for (cItems::const_iterator itr = Slots.begin(), end = Slots.end(); itr != end; ++itr) { WriteItem(Pkt, *itr); } // for itr - Slots[] } void cProtocol_1_8_0::SendWindowClose(const cWindow & a_Window) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktWindowClose); Pkt.WriteBEUInt8(static_cast(a_Window.GetWindowID())); } void cProtocol_1_8_0::SendWindowOpen(const cWindow & a_Window) { ASSERT(m_State == 3); // In game mode? if (a_Window.GetWindowType() < 0) { // Do not send this packet for player inventory windows return; } cPacketizer Pkt(*this, pktWindowOpen); Pkt.WriteBEUInt8(static_cast(a_Window.GetWindowID())); Pkt.WriteString(a_Window.GetWindowTypeName()); Pkt.WriteString(JsonUtils::SerializeSingleValueJsonObject("text", a_Window.GetWindowTitle())); switch (a_Window.GetWindowType()) { case cWindow::wtWorkbench: case cWindow::wtEnchantment: case cWindow::wtAnvil: { Pkt.WriteBEUInt8(0); break; } default: { Pkt.WriteBEUInt8(static_cast(a_Window.GetNumNonInventorySlots())); break; } } if (a_Window.GetWindowType() == cWindow::wtAnimalChest) { UInt32 HorseID = static_cast(a_Window).GetHorseID(); Pkt.WriteBEInt32(static_cast(HorseID)); } } void cProtocol_1_8_0::SendWindowProperty(const cWindow & a_Window, size_t a_Property, short a_Value) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktWindowProperty); Pkt.WriteBEUInt8(static_cast(a_Window.GetWindowID())); Pkt.WriteBEInt16(static_cast(a_Property)); Pkt.WriteBEInt16(a_Value); } void cProtocol_1_8_0::CompressPacket(CircularBufferCompressor & a_Packet, ContiguousByteBuffer & a_CompressedData) { const auto Uncompressed = a_Packet.GetView(); if (Uncompressed.size() < CompressionThreshold) { /* Size doesn't reach threshold, not worth compressing. --------------- Packet format ---------------- |--- Header ---------------------------------| | PacketSize: Size of all fields below | | DataSize: Zero, means below not compressed | |--- Body -----------------------------------| | a_Packet: copy of uncompressed data | ---------------------------------------------- */ const UInt32 DataSize = 0; const auto PacketSize = static_cast(cByteBuffer::GetVarIntSize(DataSize) + Uncompressed.size()); cByteBuffer LengthHeaderBuffer( cByteBuffer::GetVarIntSize(PacketSize) + cByteBuffer::GetVarIntSize(DataSize) ); LengthHeaderBuffer.WriteVarInt32(PacketSize); LengthHeaderBuffer.WriteVarInt32(DataSize); ContiguousByteBuffer LengthData; LengthHeaderBuffer.ReadAll(LengthData); a_CompressedData.reserve(LengthData.size() + Uncompressed.size()); a_CompressedData = LengthData; a_CompressedData += Uncompressed; return; } /* Definitely worth compressing. --------------- Packet format ---------------- |--- Header ---------------------------------| | PacketSize: Size of all fields below | | DataSize: Size of uncompressed a_Packet | |--- Body -----------------------------------| | CompressedData: compressed a_Packet | ---------------------------------------------- */ const auto CompressedData = a_Packet.Compress(); const auto Compressed = CompressedData.GetView(); const UInt32 DataSize = static_cast(Uncompressed.size()); const auto PacketSize = static_cast(cByteBuffer::GetVarIntSize(DataSize) + Compressed.size()); cByteBuffer LengthHeaderBuffer( cByteBuffer::GetVarIntSize(PacketSize) + cByteBuffer::GetVarIntSize(DataSize) ); LengthHeaderBuffer.WriteVarInt32(PacketSize); LengthHeaderBuffer.WriteVarInt32(DataSize); ContiguousByteBuffer LengthData; LengthHeaderBuffer.ReadAll(LengthData); a_CompressedData.reserve(LengthData.size() + Compressed.size()); a_CompressedData = LengthData; a_CompressedData += Compressed; } eBlockFace cProtocol_1_8_0::FaceIntToBlockFace(const Int32 a_BlockFace) { // Normalize the blockface values returned from the protocol // Anything known gets mapped 1:1, everything else returns BLOCK_FACE_NONE switch (a_BlockFace) { case BLOCK_FACE_XM: return BLOCK_FACE_XM; case BLOCK_FACE_XP: return BLOCK_FACE_XP; case BLOCK_FACE_YM: return BLOCK_FACE_YM; case BLOCK_FACE_YP: return BLOCK_FACE_YP; case BLOCK_FACE_ZM: return BLOCK_FACE_ZM; case BLOCK_FACE_ZP: return BLOCK_FACE_ZP; default: return BLOCK_FACE_NONE; } } UInt32 cProtocol_1_8_0::GetPacketID(ePacketType a_PacketType) const { switch (a_PacketType) { case pktAttachEntity: return 0x1b; case pktBlockAction: return 0x24; case pktBlockBreakAnim: return 0x25; case pktBlockChange: return 0x23; case pktBlockChanges: return 0x22; case pktCameraSetTo: return 0x43; case pktChatRaw: return 0x02; case pktCollectEntity: return 0x0d; case pktDestroyEntity: return 0x13; case pktDifficulty: return 0x41; case pktDisconnectDuringGame: return 0x40; case pktDisconnectDuringLogin: return 0x00; case pktDisplayObjective: return 0x3d; case pktEditSign: return 0x36; case pktEncryptionRequest: return 0x01; case pktEntityAnimation: return 0x0b; case pktEntityEffect: return 0x1d; case pktEntityEquipment: return 0x04; case pktEntityHeadLook: return 0x19; case pktEntityLook: return 0x16; case pktEntityMeta: return 0x1c; case pktEntityProperties: return 0x20; case pktEntityRelMove: return 0x15; case pktEntityRelMoveLook: return 0x17; case pktEntityStatus: return 0x1a; case pktEntityVelocity: return 0x12; case pktExperience: return 0x1f; case pktExplosion: return 0x27; case pktGameMode: return 0x2b; case pktHeldItemChange: return 0x09; case pktInventorySlot: return 0x2f; case pktJoinGame: return 0x01; case pktKeepAlive: return 0x00; case pktLeashEntity: return 0x1b; case pktLoginSuccess: return 0x02; case pktMapData: return 0x34; case pktParticleEffect: return 0x2a; case pktPingResponse: return 0x01; case pktPlayerAbilities: return 0x39; case pktPlayerList: return 0x38; case pktPlayerListHeaderFooter: return 0x47; case pktPlayerMoveLook: return 0x08; case pktPluginMessage: return 0x3f; case pktRemoveEntityEffect: return 0x1e; case pktResourcePack: return 0x48; case pktRespawn: return 0x07; case pktScoreboardObjective: return 0x3b; case pktSoundEffect: return 0x29; case pktSoundParticleEffect: return 0x28; case pktSpawnExperienceOrb: return 0x11; case pktSpawnGlobalEntity: return 0x2c; case pktSpawnMob: return 0x0f; case pktSpawnObject: return 0x0e; case pktSpawnOtherPlayer: return 0x0c; case pktSpawnPainting: return 0x10; case pktSpawnPosition: return 0x05; case pktStartCompression: return 0x03; case pktStatistics: return 0x37; case pktStatusResponse: return 0x00; case pktTabCompletionResults: return 0x3a; case pktTeleportEntity: return 0x18; case pktTimeUpdate: return 0x03; case pktTitle: return 0x45; case pktUnloadChunk: return 0x21; case pktUpdateBlockEntity: return 0x35; case pktUpdateHealth: return 0x06; case pktUpdateScore: return 0x3c; case pktUpdateSign: return 0x33; case pktUseBed: return 0x0a; case pktWeather: return 0x2b; case pktWindowClose: return 0x2e; case pktWindowItems: return 0x30; case pktWindowOpen: return 0x2d; case pktWindowProperty: return 0x31; default: { LOG("Unhandled outgoing packet type: %s (0x%02x)", cPacketizer::PacketTypeToStr(a_PacketType), a_PacketType); ASSERT(!"Unhandled outgoing packet type"); return 0; } } } unsigned char cProtocol_1_8_0::GetProtocolEntityAnimation(const EntityAnimation a_Animation) const { switch (a_Animation) { case EntityAnimation::EntityGetsCriticalHit: return 4; case EntityAnimation::EntityGetsMagicalCriticalHit: return 5; case EntityAnimation::PlayerLeavesBed: return 2; case EntityAnimation::PlayerMainHandSwings: return 0; case EntityAnimation::PlayerOffHandSwings: return 0; default: return static_cast(-1); } } signed char cProtocol_1_8_0::GetProtocolEntityStatus(const EntityAnimation a_Animation) const { switch (a_Animation) { case EntityAnimation::AnimalFallsInLove: return 18; case EntityAnimation::FireworkRocketExplodes: return 17; case EntityAnimation::GuardianAttacks: return 21; case EntityAnimation::HorseTamingFails: return 6; case EntityAnimation::HorseTamingSucceeds: return 7; case EntityAnimation::IronGolemAttacks: return 4; case EntityAnimation::IronGolemOffersGift: return 11; case EntityAnimation::MinecartSpawnerDelayResets: return 1; case EntityAnimation::MinecartTNTIgnites: return 10; case EntityAnimation::MobSpawns: return 20; case EntityAnimation::OcelotTrusts: return 6; case EntityAnimation::OcelotDistrusts: return 7; case EntityAnimation::PawnBerryBushPricks: return 2; case EntityAnimation::PawnBurns: return 2; case EntityAnimation::PawnDies: return 3; case EntityAnimation::PawnDrowns: return 2; case EntityAnimation::PawnHurts: return 2; case EntityAnimation::PawnThornsPricks: return 2; case EntityAnimation::PlayerFinishesEating: return 9; case EntityAnimation::RabbitJumps: return 1; case EntityAnimation::SheepEatsGrass: return 10; case EntityAnimation::VillagerKisses: return 12; case EntityAnimation::VillagerShowsAnger: return 13; case EntityAnimation::VillagerShowsHappiness: return 14; case EntityAnimation::WitchMagicks: return 15; case EntityAnimation::WolfShakesWater: return 8; case EntityAnimation::WolfTamingFails: return 6; case EntityAnimation::WolfTamingSucceeds: return 7; case EntityAnimation::ZombieVillagerCureFinishes: return 16; default: return -1; } } UInt32 cProtocol_1_8_0::GetProtocolMobType(const eMonsterType a_MobType) const { switch (a_MobType) { // Map invalid type to Giant for easy debugging (if this ever spawns, something has gone very wrong) case mtInvalidType: return 53; case mtBat: return 65; case mtBlaze: return 61; case mtCaveSpider: return 59; case mtChicken: return 93; case mtCow: return 92; case mtCreeper: return 50; case mtEnderDragon: return 63; case mtEnderman: return 58; case mtEndermite: return 67; case mtGhast: return 56; case mtGiant: return 53; case mtGuardian: return 68; case mtHorse: return 100; case mtIronGolem: return 99; case mtMagmaCube: return 62; case mtMooshroom: return 96; case mtOcelot: return 98; case mtPig: return 90; case mtRabbit: return 101; case mtSheep: return 91; case mtSilverfish: return 60; case mtSkeleton: return 51; case mtSlime: return 55; case mtSnowGolem: return 97; case mtSpider: return 52; case mtSquid: return 94; case mtVillager: return 120; case mtWitch: return 66; case mtWither: return 64; case mtWitherSkeleton: return 51; case mtWolf: return 95; case mtZombie: return 54; case mtZombiePigman: return 57; case mtZombieVillager: return 27; // Mobs that get replaced with another because they were added later case mtCat: return GetProtocolMobType(mtOcelot); case mtDonkey: return GetProtocolMobType(mtHorse); case mtMule: return GetProtocolMobType(mtHorse); case mtSkeletonHorse: return GetProtocolMobType(mtHorse); case mtZombieHorse: return GetProtocolMobType(mtHorse); case mtStray: return GetProtocolMobType(mtSkeleton); case mtHusk: return GetProtocolMobType(mtZombie); default: return 0; } } cProtocol::Version cProtocol_1_8_0::GetProtocolVersion() const { return Version::v1_8_0; } bool cProtocol_1_8_0::HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType) { switch (m_State) { case State::Status: { switch (a_PacketType) { case 0x00: HandlePacketStatusRequest(a_ByteBuffer); return true; case 0x01: HandlePacketStatusPing (a_ByteBuffer); return true; } break; } case State::Login: { switch (a_PacketType) { case 0x00: HandlePacketLoginStart (a_ByteBuffer); return true; case 0x01: HandlePacketLoginEncryptionResponse(a_ByteBuffer); return true; } break; } case State::Game: { switch (a_PacketType) { case 0x00: HandlePacketKeepAlive (a_ByteBuffer); return true; case 0x01: HandlePacketChatMessage (a_ByteBuffer); return true; case 0x02: HandlePacketUseEntity (a_ByteBuffer); return true; case 0x03: HandlePacketPlayer (a_ByteBuffer); return true; case 0x04: HandlePacketPlayerPos (a_ByteBuffer); return true; case 0x05: HandlePacketPlayerLook (a_ByteBuffer); return true; case 0x06: HandlePacketPlayerPosLook (a_ByteBuffer); return true; case 0x07: HandlePacketBlockDig (a_ByteBuffer); return true; case 0x08: HandlePacketBlockPlace (a_ByteBuffer); return true; case 0x09: HandlePacketSlotSelect (a_ByteBuffer); return true; case 0x0a: HandlePacketAnimation (a_ByteBuffer); return true; case 0x0b: HandlePacketEntityAction (a_ByteBuffer); return true; case 0x0c: HandlePacketSteerVehicle (a_ByteBuffer); return true; case 0x0d: HandlePacketWindowClose (a_ByteBuffer); return true; case 0x0e: HandlePacketWindowClick (a_ByteBuffer); return true; case 0x0f: // Confirm transaction - not used in MCS case 0x10: HandlePacketCreativeInventoryAction(a_ByteBuffer); return true; case 0x11: HandlePacketEnchantItem (a_ByteBuffer); return true; case 0x12: HandlePacketUpdateSign (a_ByteBuffer); return true; case 0x13: HandlePacketPlayerAbilities (a_ByteBuffer); return true; case 0x14: HandlePacketTabComplete (a_ByteBuffer); return true; case 0x15: HandlePacketClientSettings (a_ByteBuffer); return true; case 0x16: HandlePacketClientStatus (a_ByteBuffer); return true; case 0x17: HandlePacketPluginMessage (a_ByteBuffer); return true; case 0x18: HandlePacketSpectate (a_ByteBuffer); return true; case 0x19: HandlePacketResourcePackStatus (a_ByteBuffer); return true; } break; } } // switch (m_State) // Unknown packet type, report to the ClientHandle: m_Client->PacketUnknown(a_PacketType); return false; } void cProtocol_1_8_0::HandlePacketStatusPing(cByteBuffer & a_ByteBuffer) { HANDLE_READ(a_ByteBuffer, ReadBEInt64, Int64, Timestamp); cPacketizer Pkt(*this, pktPingResponse); Pkt.WriteBEInt64(Timestamp); } void cProtocol_1_8_0::HandlePacketStatusRequest(cByteBuffer & a_ByteBuffer) { cServer * Server = cRoot::Get()->GetServer(); AString ServerDescription = Server->GetDescription(); auto NumPlayers = static_cast(Server->GetNumPlayers()); auto MaxPlayers = static_cast(Server->GetMaxPlayers()); AString Favicon = Server->GetFaviconData(); cRoot::Get()->GetPluginManager()->CallHookServerPing(*m_Client, ServerDescription, NumPlayers, MaxPlayers, Favicon); // Version: Json::Value Version; const auto ProtocolVersion = GetProtocolVersion(); Version["name"] = "Cuberite " + cMultiVersionProtocol::GetVersionTextFromInt(ProtocolVersion); Version["protocol"] = static_cast>(ProtocolVersion); // Players: Json::Value Players; Players["online"] = NumPlayers; Players["max"] = MaxPlayers; // TODO: Add "sample" // Description: Json::Value Description; Description["text"] = std::move(ServerDescription); // Create the response: Json::Value ResponseValue; ResponseValue["version"] = Version; ResponseValue["players"] = Players; ResponseValue["description"] = Description; m_Client->ForgeAugmentServerListPing(ResponseValue); if (!Favicon.empty()) { ResponseValue["favicon"] = "data:image/png;base64," + Favicon; } // Serialize the response into a packet: cPacketizer Pkt(*this, pktStatusResponse); Pkt.WriteString(JsonUtils::WriteFastString(ResponseValue)); } void cProtocol_1_8_0::HandlePacketLoginEncryptionResponse(cByteBuffer & a_ByteBuffer) { UInt32 EncKeyLength, EncNonceLength; if (!a_ByteBuffer.ReadVarInt(EncKeyLength)) { return; } ContiguousByteBuffer EncKey; if (!a_ByteBuffer.ReadSome(EncKey, EncKeyLength)) { return; } if (!a_ByteBuffer.ReadVarInt(EncNonceLength)) { return; } ContiguousByteBuffer EncNonce; if (!a_ByteBuffer.ReadSome(EncNonce, EncNonceLength)) { return; } if ((EncKeyLength > MAX_ENC_LEN) || (EncNonceLength > MAX_ENC_LEN)) { LOGD("Too long encryption"); m_Client->Kick("Hacked client"); return; } // Decrypt EncNonce using privkey cRsaPrivateKey & rsaDecryptor = cRoot::Get()->GetServer()->GetPrivateKey(); UInt32 DecryptedNonce[MAX_ENC_LEN / sizeof(Int32)]; int res = rsaDecryptor.Decrypt(EncNonce, reinterpret_cast(DecryptedNonce), sizeof(DecryptedNonce)); if (res != 4) { LOGD("Bad nonce length: got %d, exp %d", res, 4); m_Client->Kick("Hacked client"); return; } if (ntohl(DecryptedNonce[0]) != static_cast(reinterpret_cast(this))) { LOGD("Bad nonce value"); m_Client->Kick("Hacked client"); return; } // Decrypt the symmetric encryption key using privkey: Byte DecryptedKey[MAX_ENC_LEN]; res = rsaDecryptor.Decrypt(EncKey, DecryptedKey, sizeof(DecryptedKey)); if (res != 16) { LOGD("Bad key length"); m_Client->Kick("Hacked client"); return; } StartEncryption(DecryptedKey); m_Client->HandleLogin(); } void cProtocol_1_8_0::HandlePacketLoginStart(cByteBuffer & a_ByteBuffer) { AString Username; if (!a_ByteBuffer.ReadVarUTF8String(Username)) { m_Client->Kick("Bad username"); return; } if (!m_Client->HandleHandshake(Username)) { // The client is not welcome here, they have been sent a Kick packet already return; } m_Client->SetUsername(std::move(Username)); // If auth is required, then send the encryption request: if (const auto Server = cRoot::Get()->GetServer(); Server->ShouldAuthenticate()) { cPacketizer Pkt(*this, pktEncryptionRequest); Pkt.WriteString(Server->GetServerID()); const auto PubKeyDer = Server->GetPublicKeyDER(); Pkt.WriteVarInt32(static_cast(PubKeyDer.size())); Pkt.WriteBuf(PubKeyDer); Pkt.WriteVarInt32(4); Pkt.WriteBEInt32(static_cast(reinterpret_cast(this))); // Using 'this' as the cryptographic nonce, so that we don't have to generate one each time :) return; } m_Client->HandleLogin(); } void cProtocol_1_8_0::HandlePacketAnimation(cByteBuffer & a_ByteBuffer) { m_Client->HandleAnimation(true); // Packet exists solely for arm-swing notification (main hand). } void cProtocol_1_8_0::HandlePacketBlockDig(cByteBuffer & a_ByteBuffer) { HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, Status); Vector3i Position; if (!a_ByteBuffer.ReadXYZPosition64(Position)) { return; } HANDLE_READ(a_ByteBuffer, ReadBEInt8, Int8, Face); m_Client->HandleLeftClick(Position, FaceIntToBlockFace(Face), Status); } void cProtocol_1_8_0::HandlePacketBlockPlace(cByteBuffer & a_ByteBuffer) { Vector3i BlockPos; if (!a_ByteBuffer.ReadXYZPosition64(BlockPos)) { return; } HANDLE_READ(a_ByteBuffer, ReadBEInt8, Int8, Face); cItem Item; // Ignored ReadItem(a_ByteBuffer, Item, 3); HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, CursorX); HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, CursorY); HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, CursorZ); eBlockFace blockFace = FaceIntToBlockFace(Face); if (blockFace == eBlockFace::BLOCK_FACE_NONE) { m_Client->HandleUseItem(true); } else { m_Client->HandleRightClick(BlockPos, blockFace, {CursorX, CursorY, CursorZ}, true); } } void cProtocol_1_8_0::HandlePacketChatMessage(cByteBuffer & a_ByteBuffer) { HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Message); m_Client->HandleChat(Message); } void cProtocol_1_8_0::HandlePacketClientSettings(cByteBuffer & a_ByteBuffer) { HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Locale); HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, ViewDistance); HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, ChatFlags); HANDLE_READ(a_ByteBuffer, ReadBool, bool, ChatColors); HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, SkinParts); m_Client->SetLocale(Locale); m_Client->SetViewDistance(ViewDistance); m_Client->GetPlayer()->SetSkinParts(SkinParts); // TODO: Handle chat flags and chat colors } void cProtocol_1_8_0::HandlePacketClientStatus(cByteBuffer & a_ByteBuffer) { HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, ActionID); switch (ActionID) { case 0: { // Respawn m_Client->HandleRespawn(); break; } case 1: { // Request stats SendStatistics(m_Client->GetPlayer()->GetStatistics()); break; } case 2: { // Open Inventory achievement m_Client->GetPlayer()->AwardAchievement(CustomStatistic::AchOpenInventory); break; } } } void cProtocol_1_8_0::HandlePacketCreativeInventoryAction(cByteBuffer & a_ByteBuffer) { HANDLE_READ(a_ByteBuffer, ReadBEInt16, Int16, SlotNum); cItem Item; if (!ReadItem(a_ByteBuffer, Item)) { return; } m_Client->HandleCreativeInventory(SlotNum, Item, (SlotNum == -1) ? caLeftClickOutside : caLeftClick); } void cProtocol_1_8_0::HandlePacketEntityAction(cByteBuffer & a_ByteBuffer) { HANDLE_READ(a_ByteBuffer, ReadVarInt, UInt32, PlayerID); HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, Action); HANDLE_READ(a_ByteBuffer, ReadVarInt, UInt32, JumpBoost); if (PlayerID != m_Client->GetPlayer()->GetUniqueID()) { LOGD("Player \"%s\" attempted to action another entity - hacked client?", m_Client->GetUsername().c_str()); return; } switch (Action) { case 0: return m_Client->HandleCrouch(true); case 1: return m_Client->HandleCrouch(false); case 2: return m_Client->HandleLeaveBed(); case 3: return m_Client->HandleSprint(true); case 4: return m_Client->HandleSprint(false); case 6: return m_Client->HandleOpenHorseInventory(); } } void cProtocol_1_8_0::HandlePacketKeepAlive(cByteBuffer & a_ByteBuffer) { HANDLE_READ(a_ByteBuffer, ReadVarInt, UInt32, KeepAliveID); m_Client->HandleKeepAlive(KeepAliveID); } void cProtocol_1_8_0::HandlePacketPlayer(cByteBuffer & a_ByteBuffer) { HANDLE_READ(a_ByteBuffer, ReadBool, bool, IsOnGround); // TODO: m_Client->HandlePlayerOnGround(IsOnGround); } void cProtocol_1_8_0::HandlePacketPlayerAbilities(cByteBuffer & a_ByteBuffer) { HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, Flags); HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, FlyingSpeed); HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, WalkingSpeed); // COnvert the bitfield into individual boolean flags: bool IsFlying = false; if ((Flags & 2) != 0) { IsFlying = true; } m_Client->HandlePlayerAbilities(IsFlying, FlyingSpeed, WalkingSpeed); } void cProtocol_1_8_0::HandlePacketPlayerLook(cByteBuffer & a_ByteBuffer) { HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, Yaw); HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, Pitch); HANDLE_READ(a_ByteBuffer, ReadBool, bool, IsOnGround); m_Client->HandlePlayerLook(Yaw, Pitch, IsOnGround); } void cProtocol_1_8_0::HandlePacketPlayerPos(cByteBuffer & a_ByteBuffer) { HANDLE_READ(a_ByteBuffer, ReadBEDouble, double, PosX); HANDLE_READ(a_ByteBuffer, ReadBEDouble, double, PosY); HANDLE_READ(a_ByteBuffer, ReadBEDouble, double, PosZ); HANDLE_READ(a_ByteBuffer, ReadBool, bool, IsOnGround); m_Client->HandlePlayerMove({PosX, PosY, PosZ}, IsOnGround); } void cProtocol_1_8_0::HandlePacketPlayerPosLook(cByteBuffer & a_ByteBuffer) { HANDLE_READ(a_ByteBuffer, ReadBEDouble, double, PosX); HANDLE_READ(a_ByteBuffer, ReadBEDouble, double, PosY); HANDLE_READ(a_ByteBuffer, ReadBEDouble, double, PosZ); HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, Yaw); HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, Pitch); HANDLE_READ(a_ByteBuffer, ReadBool, bool, IsOnGround); m_Client->HandlePlayerMoveLook({PosX, PosY, PosZ}, Yaw, Pitch, IsOnGround); } void cProtocol_1_8_0::HandlePacketPluginMessage(cByteBuffer & a_ByteBuffer) { // https://wiki.vg/index.php?title=Plugin_channels&oldid=14089#MC.7CAdvCmd HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Channel); const std::string_view ChannelView = Channel; // If the plugin channel is recognized vanilla, handle it directly: if (ChannelView.substr(0, 3) == "MC|") { HandleVanillaPluginMessage(a_ByteBuffer, ChannelView.substr(3)); return; } ContiguousByteBuffer Data; // Read the plugin message and relay to clienthandle: a_ByteBuffer.ReadSome(Data, a_ByteBuffer.GetReadableSpace()); m_Client->HandlePluginMessage(Channel, Data); } void cProtocol_1_8_0::HandlePacketResourcePackStatus(cByteBuffer & a_ByteBuffer) { HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Hash); HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, Status); m_Client->HandleResourcePack(Status); } void cProtocol_1_8_0::HandlePacketSlotSelect(cByteBuffer & a_ByteBuffer) { HANDLE_READ(a_ByteBuffer, ReadBEInt16, Int16, SlotNum); m_Client->HandleSlotSelected(SlotNum); } void cProtocol_1_8_0::HandlePacketSpectate(cByteBuffer &a_ByteBuffer) { cUUID playerUUID; if (!a_ByteBuffer.ReadUUID(playerUUID)) { return; } m_Client->HandleSpectate(playerUUID); } void cProtocol_1_8_0::HandlePacketSteerVehicle(cByteBuffer & a_ByteBuffer) { HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, Sideways); HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, Forward); HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, Flags); if ((Flags & 0x2) != 0) { m_Client->HandleUnmount(); } else if ((Flags & 0x1) != 0) { // jump } else { m_Client->HandleSteerVehicle(Forward, Sideways); } } void cProtocol_1_8_0::HandlePacketTabComplete(cByteBuffer & a_ByteBuffer) { HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Text); HANDLE_READ(a_ByteBuffer, ReadBool, bool, HasPosition); if (HasPosition) { HANDLE_READ(a_ByteBuffer, ReadBEInt64, Int64, Position); } m_Client->HandleTabCompletion(Text); } void cProtocol_1_8_0::HandlePacketUpdateSign(cByteBuffer & a_ByteBuffer) { Vector3i Position; if (!a_ByteBuffer.ReadXYZPosition64(Position)) { return; } AString Lines[4]; Json::Value root; for (int i = 0; i < 4; i++) { HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Line); if (JsonUtils::ParseString(Line, root) && root.isString()) { Lines[i] = root.asString(); } } m_Client->HandleUpdateSign(Position, Lines[0], Lines[1], Lines[2], Lines[3]); } void cProtocol_1_8_0::HandlePacketUseEntity(cByteBuffer & a_ByteBuffer) { HANDLE_READ(a_ByteBuffer, ReadVarInt, UInt32, EntityID); HANDLE_READ(a_ByteBuffer, ReadVarInt, UInt32, Type); switch (Type) { case 0: { m_Client->HandleUseEntity(EntityID, false); break; } case 1: { m_Client->HandleUseEntity(EntityID, true); break; } case 2: { HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, TargetX); HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, TargetY); HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, TargetZ); // TODO: Do anything break; } default: { ASSERT(!"Unhandled use entity type!"); return; } } } void cProtocol_1_8_0::HandlePacketEnchantItem(cByteBuffer & a_ByteBuffer) { HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, WindowID); HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, Enchantment); m_Client->HandleEnchantItem(WindowID, Enchantment); } void cProtocol_1_8_0::HandlePacketWindowClick(cByteBuffer & a_ByteBuffer) { HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, WindowID); HANDLE_READ(a_ByteBuffer, ReadBEInt16, Int16, SlotNum); HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, Button); HANDLE_READ(a_ByteBuffer, ReadBEUInt16, UInt16, TransactionID); HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, Mode); cItem Item; ReadItem(a_ByteBuffer, Item); /** The slot number that the client uses to indicate "outside the window". */ static const Int16 SLOT_NUM_OUTSIDE = -999; // Convert Button, Mode, SlotNum and HeldItem into eClickAction: eClickAction Action; switch ((Mode << 8) | Button) { case 0x0000: Action = (SlotNum != SLOT_NUM_OUTSIDE) ? caLeftClick : caLeftClickOutside; break; case 0x0001: Action = (SlotNum != SLOT_NUM_OUTSIDE) ? caRightClick : caRightClickOutside; break; case 0x0100: Action = caShiftLeftClick; break; case 0x0101: Action = caShiftRightClick; break; case 0x0200: Action = caNumber1; break; case 0x0201: Action = caNumber2; break; case 0x0202: Action = caNumber3; break; case 0x0203: Action = caNumber4; break; case 0x0204: Action = caNumber5; break; case 0x0205: Action = caNumber6; break; case 0x0206: Action = caNumber7; break; case 0x0207: Action = caNumber8; break; case 0x0208: Action = caNumber9; break; case 0x0302: Action = caMiddleClick; break; case 0x0400: Action = (SlotNum == SLOT_NUM_OUTSIDE) ? caLeftClickOutsideHoldNothing : caDropKey; break; case 0x0401: Action = (SlotNum == SLOT_NUM_OUTSIDE) ? caRightClickOutsideHoldNothing : caCtrlDropKey; break; case 0x0500: Action = (SlotNum == SLOT_NUM_OUTSIDE) ? caLeftPaintBegin : caUnknown; break; case 0x0501: Action = (SlotNum != SLOT_NUM_OUTSIDE) ? caLeftPaintProgress : caUnknown; break; case 0x0502: Action = (SlotNum == SLOT_NUM_OUTSIDE) ? caLeftPaintEnd : caUnknown; break; case 0x0504: Action = (SlotNum == SLOT_NUM_OUTSIDE) ? caRightPaintBegin : caUnknown; break; case 0x0505: Action = (SlotNum != SLOT_NUM_OUTSIDE) ? caRightPaintProgress : caUnknown; break; case 0x0506: Action = (SlotNum == SLOT_NUM_OUTSIDE) ? caRightPaintEnd : caUnknown; break; case 0x0508: Action = (SlotNum == SLOT_NUM_OUTSIDE) ? caMiddlePaintBegin : caUnknown; break; case 0x0509: Action = (SlotNum != SLOT_NUM_OUTSIDE) ? caMiddlePaintProgress : caUnknown; break; case 0x050a: Action = (SlotNum == SLOT_NUM_OUTSIDE) ? caMiddlePaintEnd : caUnknown; break; case 0x0600: Action = caDblClick; break; default: { LOGWARNING("Unhandled window click mode / button combination: %d (0x%x)", (Mode << 8) | Button, (Mode << 8) | Button); Action = caUnknown; break; } } m_Client->HandleWindowClick(WindowID, SlotNum, Action, Item); } void cProtocol_1_8_0::HandlePacketWindowClose(cByteBuffer & a_ByteBuffer) { HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, WindowID); m_Client->HandleWindowClose(WindowID); } void cProtocol_1_8_0::HandleVanillaPluginMessage(cByteBuffer & a_ByteBuffer, const std::string_view a_Channel) { if ((a_Channel == "AdvCdm") || (a_Channel == "AdvCmd")) // Spelling was fixed in 15w34. { HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, Type); switch (Type) { case 0x00: { HANDLE_READ(a_ByteBuffer, ReadBEInt32, Int32, BlockX); HANDLE_READ(a_ByteBuffer, ReadBEInt32, Int32, BlockY); HANDLE_READ(a_ByteBuffer, ReadBEInt32, Int32, BlockZ); HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Command); HANDLE_READ(a_ByteBuffer, ReadBool, bool, TrackOutput); // Editing a command-block: m_Client->HandleCommandBlockBlockChange({BlockX, BlockY, BlockZ}, Command); return; } case 0x01: { HANDLE_READ(a_ByteBuffer, ReadBEUInt32, UInt32, EntityID); HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Command); HANDLE_READ(a_ByteBuffer, ReadBool, bool, TrackOutput); // Editing a command-block-minecart: m_Client->HandleCommandBlockEntityChange(EntityID, Command); return; } default: { LOGD("Player \"%s\" sent an invalid command block edit type - hacked client?", m_Client->GetUsername().c_str()); return; } } } else if (a_Channel == "Beacon") { HANDLE_READ(a_ByteBuffer, ReadBEUInt32, UInt32, Effect1); HANDLE_READ(a_ByteBuffer, ReadBEUInt32, UInt32, Effect2); m_Client->HandleBeaconSelection(Effect1, Effect2); } else if (a_Channel == "BEdit") { if (cItem UnsignedBook; ReadItem(a_ByteBuffer, UnsignedBook)) { // TODO: m_Client->HandleBookEdit } } else if (a_Channel == "BSign") { if (cItem WrittenBook; ReadItem(a_ByteBuffer, WrittenBook)) { // TODO: m_Client->HandleBookSign } } else if (a_Channel == "Brand") { HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Brand); m_Client->SetClientBrand(Brand); m_Client->SendPluginMessage("MC|Brand", "\x08""Cuberite"); // Send back our brand, including the length. } else if (a_Channel == "ItemName") { HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, ItemName); m_Client->HandleAnvilItemName(ItemName); } else if (a_Channel == "TrSel") { HANDLE_READ(a_ByteBuffer, ReadBEInt32, Int32, SlotNum); m_Client->HandleNPCTrade(SlotNum); } } void cProtocol_1_8_0::ParseItemMetadata(cItem & a_Item, const ContiguousByteBufferView a_Metadata) const { // Parse into NBT: cParsedNBT NBT(a_Metadata); if (!NBT.IsValid()) { AString HexDump; CreateHexDump(HexDump, a_Metadata.data(), std::max(a_Metadata.size(), 1024), 16); LOGWARNING("Cannot parse NBT item metadata: %s at (%zu / %zu bytes)\n%s", NBT.GetErrorCode().message().c_str(), NBT.GetErrorPos(), a_Metadata.size(), HexDump.c_str() ); return; } // Load enchantments and custom display names from the NBT data: for (int tag = NBT.GetFirstChild(NBT.GetRoot()); tag >= 0; tag = NBT.GetNextSibling(tag)) { AString TagName = NBT.GetName(tag); switch (NBT.GetType(tag)) { case TAG_List: { if ((TagName == "ench") || (TagName == "StoredEnchantments")) // Enchantments tags { EnchantmentSerializer::ParseFromNBT(a_Item.m_Enchantments, NBT, tag); } break; } case TAG_Compound: { if (TagName == "display") // Custom name and lore tag { for (int displaytag = NBT.GetFirstChild(tag); displaytag >= 0; displaytag = NBT.GetNextSibling(displaytag)) { if ((NBT.GetType(displaytag) == TAG_String) && (NBT.GetName(displaytag) == "Name")) // Custon name tag { a_Item.m_CustomName = NBT.GetString(displaytag); } else if ((NBT.GetType(displaytag) == TAG_List) && (NBT.GetName(displaytag) == "Lore")) // Lore tag { for (int loretag = NBT.GetFirstChild(displaytag); loretag >= 0; loretag = NBT.GetNextSibling(loretag)) // Loop through array of strings { a_Item.m_LoreTable.push_back(NBT.GetString(loretag)); } } else if ((NBT.GetType(displaytag) == TAG_Int) && (NBT.GetName(displaytag) == "color")) { a_Item.m_ItemColor.m_Color = static_cast(NBT.GetInt(displaytag)); } } } else if ((TagName == "Fireworks") || (TagName == "Explosion")) { cFireworkItem::ParseFromNBT(a_Item.m_FireworkItem, NBT, tag, static_cast(a_Item.m_ItemType)); } break; } case TAG_Int: { if (TagName == "RepairCost") { a_Item.m_RepairCost = NBT.GetInt(tag); } break; } default: LOGD("Unimplemented NBT data when parsing!"); break; } } } bool cProtocol_1_8_0::ReadItem(cByteBuffer & a_ByteBuffer, cItem & a_Item, size_t a_KeepRemainingBytes) const { HANDLE_PACKET_READ(a_ByteBuffer, ReadBEInt16, Int16, ItemType); if (ItemType == -1) { // The item is empty, no more data follows a_Item.Empty(); return true; } a_Item.m_ItemType = ItemType; HANDLE_PACKET_READ(a_ByteBuffer, ReadBEInt8, Int8, ItemCount); HANDLE_PACKET_READ(a_ByteBuffer, ReadBEInt16, Int16, ItemDamage); a_Item.m_ItemCount = ItemCount; a_Item.m_ItemDamage = ItemDamage; if (ItemCount <= 0) { a_Item.Empty(); } ContiguousByteBuffer Metadata; if (!a_ByteBuffer.ReadSome(Metadata, a_ByteBuffer.GetReadableSpace() - a_KeepRemainingBytes) || Metadata.empty() || (Metadata[0] == std::byte(0))) { // No metadata return true; } ParseItemMetadata(a_Item, Metadata); return true; } void cProtocol_1_8_0::SendEntitySpawn(const cEntity & a_Entity, const UInt8 a_ObjectType, const Int32 a_ObjectData) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktSpawnObject); Pkt.WriteVarInt32(a_Entity.GetUniqueID()); Pkt.WriteBEUInt8(a_ObjectType); Pkt.WriteFPInt(a_Entity.GetPosX()); Pkt.WriteFPInt(a_Entity.GetPosY()); Pkt.WriteFPInt(a_Entity.GetPosZ()); Pkt.WriteByteAngle(a_Entity.GetPitch()); Pkt.WriteByteAngle(a_Entity.GetYaw()); Pkt.WriteBEInt32(a_ObjectData); if (a_ObjectData != 0) { Pkt.WriteBEInt16(static_cast(a_Entity.GetSpeedX() * 400)); Pkt.WriteBEInt16(static_cast(a_Entity.GetSpeedY() * 400)); Pkt.WriteBEInt16(static_cast(a_Entity.GetSpeedZ() * 400)); } } void cProtocol_1_8_0::SendPacket(cPacketizer & a_Pkt) { ASSERT(m_OutPacketBuffer.GetReadableSpace() == m_OutPacketBuffer.GetUsedSpace()); m_Compressor.ReadFrom(m_OutPacketBuffer); m_OutPacketBuffer.CommitRead(); const auto PacketData = m_Compressor.GetView(); if (m_State == 3) { ContiguousByteBuffer CompressedPacket; // Compress the packet payload: cProtocol_1_8_0::CompressPacket(m_Compressor, CompressedPacket); // Send the packet's payload compressed: m_Client->SendData(CompressedPacket); } else { // Compression doesn't apply to this state, send raw data: m_OutPacketLenBuffer.WriteVarInt32(static_cast(PacketData.size())); ContiguousByteBuffer LengthData; m_OutPacketLenBuffer.ReadAll(LengthData); m_OutPacketLenBuffer.CommitRead(); m_Client->SendData(LengthData); // Send the packet's payload directly: m_Client->SendData(PacketData); } // Log the comm into logfile: if (g_ShouldLogCommOut && m_CommLogFile.IsOpen()) { AString Hex; ASSERT(PacketData.size() > 0); CreateHexDump(Hex, PacketData.data(), PacketData.size(), 16); m_CommLogFile.Write(fmt::format( FMT_STRING("Outgoing packet: type {} (translated to 0x{:02x}), length {} (0x{:04x}), state {}. Payload (incl. type):\n{}\n"), cPacketizer::PacketTypeToStr(a_Pkt.GetPacketType()), GetPacketID(a_Pkt.GetPacketType()), PacketData.size(), PacketData.size(), m_State, Hex )); /* // Useful for debugging a new protocol: LOGD("Outgoing packet: type %s (translated to 0x%02x), length %u (0x%04x), state %d. Payload (incl. type):\n%s\n", cPacketizer::PacketTypeToStr(a_Pkt.GetPacketType()), GetPacketID(a_Pkt.GetPacketType()), PacketLen, PacketLen, m_State, Hex ); //*/ } /* // Useful for debugging a new protocol: std::this_thread::sleep_for(std::chrono::milliseconds(100)); */ } void cProtocol_1_8_0::WriteBlockEntity(cFastNBTWriter & a_Writer, const cBlockEntity & a_BlockEntity) const { switch (a_BlockEntity.GetBlockType()) { case E_BLOCK_WALL_BANNER: case E_BLOCK_STANDING_BANNER: { auto & BannerEntity = static_cast(a_BlockEntity); a_Writer.AddInt("Base", static_cast(BannerEntity.GetBaseColor())); break; } case E_BLOCK_BEACON: case E_BLOCK_CHEST: { // Nothing! break; } case E_BLOCK_COMMAND_BLOCK: { auto & CommandBlockEntity = static_cast(a_BlockEntity); a_Writer.AddByte("TrackOutput", 1); // Neither I nor the MC wiki has any idea about this a_Writer.AddInt("SuccessCount", CommandBlockEntity.GetResult()); a_Writer.AddString("Command", CommandBlockEntity.GetCommand()); // You can set custom names for windows in Vanilla // For a command block, this would be the 'name' prepended to anything it outputs into global chat // MCS doesn't have this, so just leave it @ '@'. (geddit?) a_Writer.AddString("CustomName", "@"); if (!CommandBlockEntity.GetLastOutput().empty()) { a_Writer.AddString("LastOutput", JsonUtils::SerializeSingleValueJsonObject("text", CommandBlockEntity.GetLastOutput())); } break; } case E_BLOCK_ENCHANTMENT_TABLE: case E_BLOCK_END_PORTAL: { // Nothing! break; } case E_BLOCK_HEAD: { auto & MobHeadEntity = static_cast(a_BlockEntity); a_Writer.AddByte("SkullType", MobHeadEntity.GetType() & 0xFF); a_Writer.AddByte("Rot", MobHeadEntity.GetRotation() & 0xFF); // The new Block Entity format for a Mob Head. See: https://minecraft.wiki/w/Head#Block_entity a_Writer.BeginCompound("Owner"); a_Writer.AddString("Id", MobHeadEntity.GetOwnerUUID().ToShortString()); a_Writer.AddString("Name", MobHeadEntity.GetOwnerName()); a_Writer.BeginCompound("Properties"); a_Writer.BeginList("textures", TAG_Compound); a_Writer.BeginCompound(""); a_Writer.AddString("Signature", MobHeadEntity.GetOwnerTextureSignature()); a_Writer.AddString("Value", MobHeadEntity.GetOwnerTexture()); a_Writer.EndCompound(); a_Writer.EndList(); a_Writer.EndCompound(); a_Writer.EndCompound(); break; } case E_BLOCK_FLOWER_POT: { auto & FlowerPotEntity = static_cast(a_BlockEntity); a_Writer.AddInt("Item", static_cast(FlowerPotEntity.GetItem().m_ItemType)); a_Writer.AddInt("Data", static_cast(FlowerPotEntity.GetItem().m_ItemDamage)); break; } case E_BLOCK_MOB_SPAWNER: { auto & MobSpawnerEntity = static_cast(a_BlockEntity); a_Writer.AddString("EntityId", cMonster::MobTypeToVanillaName(MobSpawnerEntity.GetEntity())); a_Writer.AddShort("Delay", MobSpawnerEntity.GetSpawnDelay()); break; } default: { return; } } a_Writer.AddInt("x", a_BlockEntity.GetPosX()); a_Writer.AddInt("y", a_BlockEntity.GetPosY()); a_Writer.AddInt("z", a_BlockEntity.GetPosZ()); } void cProtocol_1_8_0::WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_Entity) const { // Common metadata: Byte Flags = 0; if (a_Entity.IsOnFire()) { Flags |= 0x01; } if (a_Entity.IsCrouched()) { Flags |= 0x02; } if (a_Entity.IsSprinting()) { Flags |= 0x08; } if (a_Entity.IsRclking()) { Flags |= 0x10; } if (a_Entity.IsInvisible()) { Flags |= 0x20; } if (a_Entity.IsElytraFlying()) { Flags |= 0x80; } a_Pkt.WriteBEUInt8(0); // Byte(0) + index 0 a_Pkt.WriteBEUInt8(Flags); switch (a_Entity.GetEntityType()) { case cEntity::etPlayer: { auto & Player = static_cast(a_Entity); // Player name: a_Pkt.WriteBEUInt8(0x82); a_Pkt.WriteString(Player.GetName()); // Player health: a_Pkt.WriteBEUInt8(0x66); a_Pkt.WriteBEFloat(static_cast(Player.GetHealth())); // Skin flags: a_Pkt.WriteBEUInt8(0x0A); a_Pkt.WriteBEUInt8(static_cast(Player.GetSkinParts())); break; } case cEntity::etPickup: { a_Pkt.WriteBEUInt8((5 << 5) | 10); // Slot(5) + index 10 WriteItem(a_Pkt, static_cast(a_Entity).GetItem()); break; } case cEntity::etMinecart: { a_Pkt.WriteBEUInt8(0x51); // The following expression makes Minecarts shake more with less health or higher damage taken // It gets half the maximum health, and takes it away from the current health minus the half health: /* Health: 5 | 3 - (5 - 3) = 1 (shake power) Health: 3 | 3 - (3 - 3) = 3 Health: 1 | 3 - (1 - 3) = 5 */ auto & Minecart = static_cast(a_Entity); a_Pkt.WriteBEInt32(static_cast((((a_Entity.GetMaxHealth() / 2) - (a_Entity.GetHealth() - (a_Entity.GetMaxHealth() / 2))) * Minecart.LastDamage()) * 4)); a_Pkt.WriteBEUInt8(0x52); a_Pkt.WriteBEInt32(1); // Shaking direction, doesn't seem to affect anything a_Pkt.WriteBEUInt8(0x73); a_Pkt.WriteBEFloat(static_cast(Minecart.LastDamage() + 10)); // Damage taken / shake effect multiplyer if (Minecart.GetPayload() == cMinecart::mpNone) { auto & RideableMinecart = static_cast(Minecart); const cItem & MinecartContent = RideableMinecart.GetContent(); if (!MinecartContent.IsEmpty()) { a_Pkt.WriteBEUInt8(0x54); int Content = MinecartContent.m_ItemType; Content |= MinecartContent.m_ItemDamage << 8; a_Pkt.WriteBEInt32(Content); a_Pkt.WriteBEUInt8(0x55); a_Pkt.WriteBEInt32(RideableMinecart.GetBlockHeight()); a_Pkt.WriteBEUInt8(0x56); a_Pkt.WriteBEUInt8(1); } } else if (Minecart.GetPayload() == cMinecart::mpFurnace) { a_Pkt.WriteBEUInt8(0x10); a_Pkt.WriteBEUInt8(static_cast(Minecart).IsFueled() ? 1 : 0); } break; } // case etMinecart case cEntity::etProjectile: { auto & Projectile = static_cast(a_Entity); switch (Projectile.GetProjectileKind()) { case cProjectileEntity::pkArrow: { a_Pkt.WriteBEUInt8(0x10); a_Pkt.WriteBEUInt8(static_cast(Projectile).IsCritical() ? 1 : 0); break; } case cProjectileEntity::pkFirework: { a_Pkt.WriteBEUInt8(0xa8); WriteItem(a_Pkt, static_cast(Projectile).GetItem()); break; } default: { break; } } break; } // case etProjectile case cEntity::etMonster: { WriteMobMetadata(a_Pkt, static_cast(a_Entity)); break; } case cEntity::etItemFrame: { auto & Frame = static_cast(a_Entity); a_Pkt.WriteBEUInt8(0xa8); WriteItem(a_Pkt, Frame.GetItem()); a_Pkt.WriteBEUInt8(0x09); a_Pkt.WriteBEUInt8(Frame.GetItemRotation()); break; } // case etItemFrame default: { break; } } } void cProtocol_1_8_0::WriteEntityProperties(cPacketizer & a_Pkt, const cEntity & a_Entity) const { if (a_Entity.IsPlayer()) { const auto & Player = static_cast(a_Entity); a_Pkt.WriteBEInt32(1); // Count. a_Pkt.WriteString("generic.movementSpeed"); a_Pkt.WriteBEDouble(0.1 * Player.GetNormalMaxSpeed()); // The default game speed is 0.1, multiply that value by the relative speed. // It seems the modifiers aren't conditionally activated; their effects are applied immediately! // We have to keep on re-sending this packet when the client notifies us of sprint start and end, and so on. Strange. if (Player.IsSprinting()) { a_Pkt.WriteVarInt32(1); // Modifier count. a_Pkt.WriteBEUInt64(0x662a6b8dda3e4c1c); a_Pkt.WriteBEUInt64(0x881396ea6097278d); // UUID of the modifier (sprinting speed boost). a_Pkt.WriteBEDouble(Player.GetSprintingMaxSpeed() - Player.GetNormalMaxSpeed()); a_Pkt.WriteBEUInt8(2); } else { a_Pkt.WriteVarInt32(0); } } else { // const cMonster & Mob = (const cMonster &)a_Entity; // TODO: Send properties and modifiers based on the mob type a_Pkt.WriteBEInt32(0); } } void cProtocol_1_8_0::WriteItem(cPacketizer & a_Pkt, const cItem & a_Item) const { short ItemType = a_Item.m_ItemType; ASSERT(ItemType >= -1); // Check validity of packets in debug runtime if (ItemType <= 0) { // Fix, to make sure no invalid values are sent. ItemType = -1; } if (a_Item.IsEmpty()) { a_Pkt.WriteBEInt16(-1); return; } a_Pkt.WriteBEInt16(ItemType); a_Pkt.WriteBEInt8(a_Item.m_ItemCount); a_Pkt.WriteBEInt16(a_Item.m_ItemDamage); if (a_Item.m_Enchantments.IsEmpty() && a_Item.IsBothNameAndLoreEmpty() && (a_Item.m_ItemType != E_ITEM_FIREWORK_ROCKET) && (a_Item.m_ItemType != E_ITEM_FIREWORK_STAR) && !a_Item.m_ItemColor.IsValid()) { a_Pkt.WriteBEInt8(0); return; } // Send the enchantments and custom names: cFastNBTWriter Writer; if (a_Item.m_RepairCost != 0) { Writer.AddInt("RepairCost", a_Item.m_RepairCost); } if (!a_Item.m_Enchantments.IsEmpty()) { const char * TagName = (a_Item.m_ItemType == E_ITEM_BOOK) ? "StoredEnchantments" : "ench"; EnchantmentSerializer::WriteToNBTCompound(a_Item.m_Enchantments, Writer, TagName); } if (!a_Item.IsBothNameAndLoreEmpty() || a_Item.m_ItemColor.IsValid()) { Writer.BeginCompound("display"); if (a_Item.m_ItemColor.IsValid()) { Writer.AddInt("color", static_cast(a_Item.m_ItemColor.m_Color)); } if (!a_Item.IsCustomNameEmpty()) { Writer.AddString("Name", a_Item.m_CustomName); } if (!a_Item.IsLoreEmpty()) { Writer.BeginList("Lore", TAG_String); for (const auto & Line : a_Item.m_LoreTable) { Writer.AddString("", Line); } Writer.EndList(); } Writer.EndCompound(); } if ((a_Item.m_ItemType == E_ITEM_FIREWORK_ROCKET) || (a_Item.m_ItemType == E_ITEM_FIREWORK_STAR)) { cFireworkItem::WriteToNBTCompound(a_Item.m_FireworkItem, Writer, static_cast(a_Item.m_ItemType)); } Writer.Finish(); const auto Result = Writer.GetResult(); if (Result.empty()) { a_Pkt.WriteBEInt8(0); return; } a_Pkt.WriteBuf(Result); } void cProtocol_1_8_0::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mob) const { // Living Enitiy Metadata if (a_Mob.HasCustomName()) { a_Pkt.WriteBEUInt8(0x82); a_Pkt.WriteString(a_Mob.GetCustomName()); a_Pkt.WriteBEUInt8(0x03); a_Pkt.WriteBool(a_Mob.IsCustomNameAlwaysVisible()); } a_Pkt.WriteBEUInt8(0x66); a_Pkt.WriteBEFloat(static_cast(a_Mob.GetHealth())); switch (a_Mob.GetMobType()) { case mtBat: { auto & Bat = static_cast(a_Mob); a_Pkt.WriteBEUInt8(0x10); a_Pkt.WriteBEUInt8(Bat.IsHanging() ? 1 : 0); break; } // case mtBat case mtChicken: { auto & Chicken = static_cast(a_Mob); a_Pkt.WriteBEUInt8(0x0c); a_Pkt.WriteBEInt8(Chicken.IsBaby() ? -1 : (Chicken.IsInLoveCooldown() ? 1 : 0)); break; } // case mtChicken case mtCow: { auto & Cow = static_cast(a_Mob); a_Pkt.WriteBEUInt8(0x0c); a_Pkt.WriteBEInt8(Cow.IsBaby() ? -1 : (Cow.IsInLoveCooldown() ? 1 : 0)); break; } // case mtCow case mtCreeper: { auto & Creeper = static_cast(a_Mob); a_Pkt.WriteBEUInt8(0x10); a_Pkt.WriteBEUInt8(Creeper.IsBlowing() ? 1 : 255); a_Pkt.WriteBEUInt8(0x11); a_Pkt.WriteBEUInt8(Creeper.IsCharged() ? 1 : 0); break; } // case mtCreeper case mtEnderman: { auto & Enderman = static_cast(a_Mob); a_Pkt.WriteBEUInt8(0x30); a_Pkt.WriteBEInt16(static_cast(Enderman.GetCarriedBlock())); a_Pkt.WriteBEUInt8(0x11); a_Pkt.WriteBEUInt8(static_cast(Enderman.GetCarriedMeta())); a_Pkt.WriteBEUInt8(0x12); a_Pkt.WriteBEUInt8(Enderman.IsScreaming() ? 1 : 0); break; } // case mtEnderman case mtGhast: { auto & Ghast = static_cast(a_Mob); a_Pkt.WriteBEUInt8(0x10); a_Pkt.WriteBEUInt8(Ghast.IsCharging()); break; } // case mtGhast case mtHorse: { auto & Horse = static_cast(a_Mob); int Flags = 0; if (Horse.IsTame()) { Flags |= 0x02; } if (Horse.IsSaddled()) { Flags |= 0x04; } if (Horse.IsChested()) { Flags |= 0x08; } if (Horse.IsEating()) { Flags |= 0x20; } if (Horse.IsRearing()) { Flags |= 0x40; } if (Horse.IsMthOpen()) { Flags |= 0x80; } a_Pkt.WriteBEUInt8(0x50); // Int at index 16 a_Pkt.WriteBEInt32(Flags); a_Pkt.WriteBEUInt8(0x13); // Byte at index 19 a_Pkt.WriteBEUInt8(static_cast(Horse.GetHorseType())); a_Pkt.WriteBEUInt8(0x54); // Int at index 20 int Appearance = 0; Appearance = Horse.GetHorseColor(); Appearance |= Horse.GetHorseStyle() << 8; a_Pkt.WriteBEInt32(Appearance); a_Pkt.WriteBEUInt8(0x56); // Int at index 22 a_Pkt.WriteBEInt32(Horse.GetHorseArmour()); a_Pkt.WriteBEUInt8(0x0c); a_Pkt.WriteBEInt8(Horse.IsBaby() ? -1 : (Horse.IsInLoveCooldown() ? 1 : 0)); break; } // case mtHorse case mtMagmaCube: { auto & MagmaCube = static_cast(a_Mob); a_Pkt.WriteBEUInt8(0x10); a_Pkt.WriteBEUInt8(static_cast(MagmaCube.GetSize())); break; } // case mtMagmaCube case mtOcelot: { auto & Ocelot = static_cast(a_Mob); a_Pkt.WriteBEUInt8(0x0c); a_Pkt.WriteBEInt8(Ocelot.IsBaby() ? -1 : (Ocelot.IsInLoveCooldown() ? 1 : 0)); break; } // case mtOcelot case mtPig: { auto & Pig = static_cast(a_Mob); a_Pkt.WriteBEUInt8(0x0c); a_Pkt.WriteBEInt8(Pig.IsBaby() ? -1 : (Pig.IsInLoveCooldown() ? 1 : 0)); a_Pkt.WriteBEUInt8(0x10); a_Pkt.WriteBEUInt8(Pig.IsSaddled() ? 1 : 0); break; } // case mtPig case mtSheep: { auto & Sheep = static_cast(a_Mob); a_Pkt.WriteBEUInt8(0x0c); a_Pkt.WriteBEInt8(Sheep.IsBaby() ? -1 : (Sheep.IsInLoveCooldown() ? 1 : 0)); a_Pkt.WriteBEUInt8(0x10); Byte SheepMetadata = 0; SheepMetadata = static_cast(Sheep.GetFurColor()); if (Sheep.IsSheared()) { SheepMetadata |= 0x10; } a_Pkt.WriteBEUInt8(SheepMetadata); break; } // case mtSheep case mtRabbit: { auto & Rabbit = static_cast(a_Mob); a_Pkt.WriteBEUInt8(0x12); a_Pkt.WriteBEUInt8(static_cast(Rabbit.GetRabbitType())); a_Pkt.WriteBEUInt8(0x0c); a_Pkt.WriteBEInt8(Rabbit.IsBaby() ? -1 : (Rabbit.IsInLoveCooldown() ? 1 : 0)); break; } // case mtRabbit case mtSlime: { auto & Slime = static_cast(a_Mob); a_Pkt.WriteBEUInt8(0x10); a_Pkt.WriteBEUInt8(static_cast(Slime.GetSize())); break; } // case mtSlime case mtSkeleton: case mtStray: { a_Pkt.WriteBEUInt8(0x0d); a_Pkt.WriteBEUInt8(0); // Is normal skeleton break; } case mtVillager: { auto & Villager = static_cast(a_Mob); a_Pkt.WriteBEUInt8(0x50); a_Pkt.WriteBEInt32(Villager.GetVilType()); a_Pkt.WriteBEUInt8(0x0c); a_Pkt.WriteBEInt8(Villager.IsBaby() ? -1 : 0); break; } // case mtVillager case mtWitch: { auto & Witch = static_cast(a_Mob); a_Pkt.WriteBEUInt8(0x15); a_Pkt.WriteBEUInt8(Witch.IsAngry() ? 1 : 0); break; } // case mtWitch case mtWither: { auto & Wither = static_cast(a_Mob); a_Pkt.WriteBEUInt8(0x54); // Int at index 20 a_Pkt.WriteBEInt32(static_cast(Wither.GetWitherInvulnerableTicks())); a_Pkt.WriteBEUInt8(0x66); // Float at index 6 a_Pkt.WriteBEFloat(static_cast(a_Mob.GetHealth())); break; } // case mtWither case mtWitherSkeleton: { a_Pkt.WriteBEUInt8(0x0d); a_Pkt.WriteBEUInt8(1); // Is wither skeleton break; } // case mtWitherSkeleton case mtWolf: { auto & Wolf = static_cast(a_Mob); Byte WolfStatus = 0; if (Wolf.IsSitting()) { WolfStatus |= 0x1; } if (Wolf.IsAngry()) { WolfStatus |= 0x2; } if (Wolf.IsTame()) { WolfStatus |= 0x4; } a_Pkt.WriteBEUInt8(0x10); a_Pkt.WriteBEUInt8(WolfStatus); a_Pkt.WriteBEUInt8(0x72); a_Pkt.WriteBEFloat(static_cast(a_Mob.GetHealth())); a_Pkt.WriteBEUInt8(0x13); a_Pkt.WriteBEUInt8(Wolf.IsBegging() ? 1 : 0); a_Pkt.WriteBEUInt8(0x14); a_Pkt.WriteBEUInt8(static_cast(Wolf.GetCollarColor())); a_Pkt.WriteBEUInt8(0x0c); a_Pkt.WriteBEInt8(Wolf.IsBaby() ? -1 : 0); break; } // case mtWolf case mtHusk: case mtZombie: { auto & Zombie = static_cast(a_Mob); a_Pkt.WriteBEUInt8(0x0c); a_Pkt.WriteBEInt8(Zombie.IsBaby() ? 1 : -1); a_Pkt.WriteBEUInt8(0x0d); a_Pkt.WriteBEUInt8(0); a_Pkt.WriteBEUInt8(0x0e); a_Pkt.WriteBEUInt8(0); break; } // case mtZombie case mtZombiePigman: { auto & ZombiePigman = static_cast(a_Mob); a_Pkt.WriteBEUInt8(0x0c); a_Pkt.WriteBEInt8(ZombiePigman.IsBaby() ? 1 : -1); break; } // case mtZombiePigman case mtZombieVillager: { auto & ZombieVillager = reinterpret_cast(a_Mob); a_Pkt.WriteBEUInt8(0x0c); a_Pkt.WriteBEInt8(ZombieVillager.IsBaby() ? 1 : -1); a_Pkt.WriteBEUInt8(0x0d); a_Pkt.WriteBEUInt8(1); a_Pkt.WriteBEUInt8(0x0e); a_Pkt.WriteBEUInt8((ZombieVillager.ConversionTime() == -1) ? 0 : 1); break; } // case mtZombieVillager case mtBlaze: case mtElderGuardian: case mtGuardian: { // TODO: Mobs with extra fields that aren't implemented break; } case mtCat: case mtDonkey: case mtMule: case mtSkeletonHorse: case mtZombieHorse: { // Todo: Mobs not added yet. Grouped ones have the same metadata ASSERT(!"cProtocol_1_8::WriteMobMetadata: received unimplemented type"); break; } case mtCaveSpider: case mtEnderDragon: case mtGiant: case mtIronGolem: case mtMooshroom: case mtSilverfish: case mtEndermite: case mtSnowGolem: case mtSpider: case mtSquid: { // Allowed mobs without additional metadata break; } default: UNREACHABLE("cProtocol_1_8::WriteMobMetadata: received mob of invalid type"); } // switch (a_Mob.GetType()) } void cProtocol_1_8_0::AddReceivedData(cByteBuffer & a_Buffer, const ContiguousByteBufferView a_Data) { // Write the incoming data into the comm log file: if (g_ShouldLogCommIn && m_CommLogFile.IsOpen()) { if (a_Buffer.GetReadableSpace() > 0) { ContiguousByteBuffer AllData; size_t OldReadableSpace = a_Buffer.GetReadableSpace(); a_Buffer.ReadAll(AllData); a_Buffer.ResetRead(); a_Buffer.SkipRead(a_Buffer.GetReadableSpace() - OldReadableSpace); ASSERT(a_Buffer.GetReadableSpace() == OldReadableSpace); AString Hex; CreateHexDump(Hex, AllData.data(), AllData.size(), 16); m_CommLogFile.Write(fmt::format( FMT_STRING("Incoming data, {0} (0x{0:x}) unparsed bytes already present in buffer:\n{1}\n"), AllData.size(), Hex )); } AString Hex; CreateHexDump(Hex, a_Data.data(), a_Data.size(), 16); m_CommLogFile.Write(fmt::format( FMT_STRING("Incoming data: {0} (0x{0:x}) bytes: \n{1}\n"), a_Data.size(), Hex )); m_CommLogFile.Flush(); } if (!a_Buffer.Write(a_Data.data(), a_Data.size())) { // Too much data in the incoming queue, report to caller: m_Client->PacketBufferFull(); return; } // Handle all complete packets: for (;;) { UInt32 PacketLen; if (!a_Buffer.ReadVarInt(PacketLen)) { // Not enough data a_Buffer.ResetRead(); break; } if (!a_Buffer.CanReadBytes(PacketLen)) { // The full packet hasn't been received yet a_Buffer.ResetRead(); break; } // Check packet for compression: if (m_State == 3) { UInt32 NumBytesRead = static_cast(a_Buffer.GetReadableSpace()); UInt32 UncompressedSize; if (!a_Buffer.ReadVarInt(UncompressedSize)) { m_Client->Kick("Compression packet incomplete"); return; } NumBytesRead -= static_cast(a_Buffer.GetReadableSpace()); // How many bytes has the UncompressedSize taken up? ASSERT(PacketLen > NumBytesRead); PacketLen -= NumBytesRead; if (UncompressedSize > 0) { // Decompress the data: m_Extractor.ReadFrom(a_Buffer, PacketLen); a_Buffer.CommitRead(); const auto UncompressedData = m_Extractor.Extract(UncompressedSize); const auto Uncompressed = UncompressedData.GetView(); cByteBuffer bb(Uncompressed.size()); // Compression was used, move the uncompressed data: VERIFY(bb.Write(Uncompressed.data(), Uncompressed.size())); HandlePacket(bb); continue; } } // Move the packet payload to a separate cByteBuffer, bb: cByteBuffer bb(PacketLen); // No compression was used, move directly: VERIFY(a_Buffer.ReadToByteBuffer(bb, static_cast(PacketLen))); a_Buffer.CommitRead(); HandlePacket(bb); } // for (ever) // Log any leftover bytes into the logfile: if (g_ShouldLogCommIn && (a_Buffer.GetReadableSpace() > 0) && m_CommLogFile.IsOpen()) { ContiguousByteBuffer AllData; size_t OldReadableSpace = a_Buffer.GetReadableSpace(); a_Buffer.ReadAll(AllData); a_Buffer.ResetRead(); a_Buffer.SkipRead(a_Buffer.GetReadableSpace() - OldReadableSpace); ASSERT(a_Buffer.GetReadableSpace() == OldReadableSpace); AString Hex; CreateHexDump(Hex, AllData.data(), AllData.size(), 16); m_CommLogFile.Write(fmt::format( FMT_STRING("There are {0} (0x{0:x}) bytes of non-parse-able data left in the buffer:\n{1}"), a_Buffer.GetReadableSpace(), Hex )); m_CommLogFile.Flush(); } } UInt8 cProtocol_1_8_0::GetProtocolEntityType(const cEntity & a_Entity) const { using Type = cEntity::eEntityType; switch (a_Entity.GetEntityType()) { case Type::etEnderCrystal: return 51; case Type::etPickup: return 2; case Type::etFallingBlock: return 70; case Type::etMinecart: return 10; case Type::etBoat: return 1; case Type::etTNT: return 50; case Type::etProjectile: { using PType = cProjectileEntity::eKind; const auto & Projectile = static_cast(a_Entity); switch (Projectile.GetProjectileKind()) { case PType::pkArrow: return 60; case PType::pkSnowball: return 61; case PType::pkEgg: return 62; case PType::pkGhastFireball: return 63; case PType::pkFireCharge: return 64; case PType::pkEnderPearl: return 65; case PType::pkExpBottle: return 75; case PType::pkSplashPotion: return 73; case PType::pkFirework: return 76; case PType::pkWitherSkull: return 66; } break; } case Type::etFloater: return 90; case Type::etItemFrame: return 71; case Type::etLeashKnot: return 77; // Non-objects must not be sent case Type::etEntity: case Type::etPlayer: case Type::etMonster: case Type::etExpOrb: case Type::etPainting: break; } UNREACHABLE("Unhandled entity kind"); } int cProtocol_1_8_0::GetProtocolParticleID(const AString & a_ParticleName) const { static const std::unordered_map ParticleMap { // Initialize the ParticleMap: { "explode", 0 }, { "largeexplode", 1 }, { "hugeexplosion", 2 }, { "fireworksspark", 3 }, { "bubble", 4 }, { "splash", 5 }, { "wake", 6 }, { "suspended", 7 }, { "depthsuspend", 8 }, { "crit", 9 }, { "magiccrit", 10 }, { "smoke", 11 }, { "largesmoke", 12 }, { "spell", 13 }, { "instantspell", 14 }, { "mobspell", 15 }, { "mobspellambient", 16 }, { "witchmagic", 17 }, { "dripwater", 18 }, { "driplava", 19 }, { "angryvillager", 20 }, { "happyvillager", 21 }, { "townaura", 22 }, { "note", 23 }, { "portal", 24 }, { "enchantmenttable", 25 }, { "flame", 26 }, { "lava", 27 }, { "footstep", 28 }, { "cloud", 29 }, { "reddust", 30 }, { "snowballpoof", 31 }, { "snowshovel", 32 }, { "slime", 33 }, { "heart", 34 }, { "barrier", 35 }, { "iconcrack", 36 }, { "blockcrack", 37 }, { "blockdust", 38 }, { "droplet", 39 }, { "take", 40 }, { "mobappearance", 41 }, { "dragonbreath", 42 }, { "endrod", 43 }, { "damageindicator", 44 }, { "sweepattack", 45 }, { "fallingdust", 46 }, { "totem", 47 }, { "spit", 48 } }; const auto ParticleName = StrToLower(a_ParticleName); const auto FindResult = ParticleMap.find(ParticleName); if (FindResult == ParticleMap.end()) { LOGWARNING("Unknown particle: %s", a_ParticleName.c_str()); ASSERT(!"Unknown particle"); return 0; } return FindResult->second; } const char * cProtocol_1_8_0::GetProtocolStatisticName(const CustomStatistic a_Statistic) { switch (a_Statistic) { // V1.8 Achievements case CustomStatistic::AchOpenInventory: return "achievement.openInventory"; case CustomStatistic::AchMineWood: return "achievement.mineWood"; case CustomStatistic::AchBuildWorkBench: return "achievement.buildWorkBench"; case CustomStatistic::AchBuildPickaxe: return "achievement.buildPickaxe"; case CustomStatistic::AchBuildFurnace: return "achievement.buildFurnace"; case CustomStatistic::AchAcquireIron: return "achievement.acquireIron"; case CustomStatistic::AchBuildHoe: return "achievement.buildHoe"; case CustomStatistic::AchMakeBread: return "achievement.makeBread"; case CustomStatistic::AchBakeCake: return "achievement.bakeCake"; case CustomStatistic::AchBuildBetterPickaxe: return "achievement.buildBetterPickaxe"; case CustomStatistic::AchCookFish: return "achievement.cookFish"; case CustomStatistic::AchOnARail: return "achievement.onARail"; case CustomStatistic::AchBuildSword: return "achievement.buildSword"; case CustomStatistic::AchKillEnemy: return "achievement.killEnemy"; case CustomStatistic::AchKillCow: return "achievement.killCow"; case CustomStatistic::AchFlyPig: return "achievement.flyPig"; case CustomStatistic::AchSnipeSkeleton: return "achievement.snipeSkeleton"; case CustomStatistic::AchDiamonds: return "achievement.diamonds"; case CustomStatistic::AchPortal: return "achievement.portal"; case CustomStatistic::AchGhast: return "achievement.ghast"; case CustomStatistic::AchBlazeRod: return "achievement.blazeRod"; case CustomStatistic::AchPotion: return "achievement.potion"; case CustomStatistic::AchTheEnd: return "achievement.theEnd"; case CustomStatistic::AchTheEnd2: return "achievement.theEnd2"; case CustomStatistic::AchEnchantments: return "achievement.enchantments"; case CustomStatistic::AchOverkill: return "achievement.overkill"; case CustomStatistic::AchBookcase: return "achievement.bookcase"; case CustomStatistic::AchExploreAllBiomes: return "achievement.exploreAllBiomes"; case CustomStatistic::AchSpawnWither: return "achievement.spawnWither"; case CustomStatistic::AchKillWither: return "achievement.killWither"; case CustomStatistic::AchFullBeacon: return "achievement.fullBeacon"; case CustomStatistic::AchBreedCow: return "achievement.breedCow"; case CustomStatistic::AchDiamondsToYou: return "achievement.diamondsToYou"; // V1.8 stats case CustomStatistic::AnimalsBred: return "stat.animalsBred"; case CustomStatistic::BoatOneCm: return "stat.boatOneCm"; case CustomStatistic::ClimbOneCm: return "stat.climbOneCm"; case CustomStatistic::CrouchOneCm: return "stat.crouchOneCm"; case CustomStatistic::DamageDealt: return "stat.damageDealt"; case CustomStatistic::DamageTaken: return "stat.damageTaken"; case CustomStatistic::Deaths: return "stat.deaths"; case CustomStatistic::Drop: return "stat.drop"; case CustomStatistic::FallOneCm: return "stat.fallOneCm"; case CustomStatistic::FishCaught: return "stat.fishCaught"; case CustomStatistic::FlyOneCm: return "stat.flyOneCm"; case CustomStatistic::HorseOneCm: return "stat.horseOneCm"; case CustomStatistic::Jump: return "stat.jump"; case CustomStatistic::LeaveGame: return "stat.leaveGame"; case CustomStatistic::MinecartOneCm: return "stat.minecartOneCm"; case CustomStatistic::MobKills: return "stat.mobKills"; case CustomStatistic::PigOneCm: return "stat.pigOneCm"; case CustomStatistic::PlayerKills: return "stat.playerKills"; case CustomStatistic::PlayOneMinute: return "stat.playOneMinute"; case CustomStatistic::SprintOneCm: return "stat.sprintOneCm"; case CustomStatistic::SwimOneCm: return "stat.swimOneCm"; case CustomStatistic::TalkedToVillager: return "stat.talkedToVillager"; case CustomStatistic::TimeSinceDeath: return "stat.timeSinceDeath"; case CustomStatistic::TradedWithVillager: return "stat.tradedWithVillager"; case CustomStatistic::WalkOneCm: return "stat.walkOneCm"; case CustomStatistic::WalkUnderWaterOneCm: return "stat.diveOneCm"; // V1.8.2 stats case CustomStatistic::CleanArmor: return "stat.armorCleaned"; case CustomStatistic::CleanBanner: return "stat.bannerCleaned"; case CustomStatistic::EatCakeSlice: return "stat.cakeSlicesEaten"; case CustomStatistic::EnchantItem: return "stat.itemEnchanted"; case CustomStatistic::FillCauldron: return "stat.cauldronFilled"; case CustomStatistic::InspectDispenser: return "stat.dispenserInspected"; case CustomStatistic::InspectDropper: return "stat.dropperInspected"; case CustomStatistic::InspectHopper: return "stat.hopperInspected"; case CustomStatistic::InteractWithBeacon: return "stat.beaconInteraction"; case CustomStatistic::InteractWithBrewingstand: return "stat.brewingstandInteraction"; case CustomStatistic::InteractWithCraftingTable: return "stat.craftingTableInteraction"; case CustomStatistic::InteractWithFurnace: return "stat.furnaceInteraction"; case CustomStatistic::OpenChest: return "stat.chestOpened"; case CustomStatistic::OpenEnderchest: return "stat.enderchestOpened"; case CustomStatistic::PlayNoteblock: return "stat.noteblockPlayed"; case CustomStatistic::PlayRecord: return "stat.recordPlayed"; case CustomStatistic::PotFlower: return "stat.flowerPotted"; case CustomStatistic::TriggerTrappedChest: return "stat.trappedChestTriggered"; case CustomStatistic::TuneNoteblock: return "stat.noteblockTuned"; case CustomStatistic::UseCauldron: return "stat.cauldronUsed"; // V1.9 stats case CustomStatistic::AviateOneCm: return "stat.aviateOneCm"; case CustomStatistic::SleepInBed: return "stat.sleepInBed"; case CustomStatistic::SneakTime: return "stat.sneakTime"; default: return ""; } } void cProtocol_1_8_0::HandlePacket(cByteBuffer & a_Buffer) { UInt32 PacketType; if (!a_Buffer.ReadVarInt(PacketType)) { // Not enough data return; } // Log the packet info into the comm log file: if (g_ShouldLogCommIn && m_CommLogFile.IsOpen()) { ContiguousByteBuffer PacketData; a_Buffer.ReadAll(PacketData); a_Buffer.ResetRead(); a_Buffer.ReadVarInt(PacketType); // We have already read the packet type once, it will be there again ASSERT(PacketData.size() > 0); // We have written an extra NUL, so there had to be at least one byte read PacketData.resize(PacketData.size() - 1); AString PacketDataHex; CreateHexDump(PacketDataHex, PacketData.data(), PacketData.size(), 16); m_CommLogFile.Write(fmt::format( FMT_STRING("Next incoming packet is type {0} (0x{0:x}), length {1} (0x{1:x}) at state {2}. Payload:\n{3}\n"), PacketType, a_Buffer.GetUsedSpace(), m_State, PacketDataHex )); } if (!HandlePacket(a_Buffer, PacketType)) { // Unknown packet, already been reported, but without the length. Log the length here: LOGWARNING("Unhandled packet: type 0x%x, state %d, length %u", PacketType, m_State, a_Buffer.GetUsedSpace()); #ifndef NDEBUG // Dump the packet contents into the log: a_Buffer.ResetRead(); ContiguousByteBuffer Packet; a_Buffer.ReadAll(Packet); Packet.resize(Packet.size() - 1); // Drop the final NUL pushed there for over-read detection AString Out; CreateHexDump(Out, Packet.data(), Packet.size(), 24); LOGD("Packet contents:\n%s", Out.c_str()); #endif // !NDEBUG // Put a message in the comm log: if (g_ShouldLogCommIn && m_CommLogFile.IsOpen()) { m_CommLogFile.Write("^^^^^^ Unhandled packet ^^^^^^\n\n\n"); } return; } // The packet should have nothing left in the buffer: if (a_Buffer.GetReadableSpace() != 0) { // Read more or less than packet length, report as error LOGWARNING("Protocol 1.8: Wrong number of bytes read for packet 0x%x, state %d. Read %zu bytes, packet contained %u bytes", PacketType, m_State, a_Buffer.GetUsedSpace() - a_Buffer.GetReadableSpace(), a_Buffer.GetUsedSpace() ); // Put a message in the comm log: if (g_ShouldLogCommIn && m_CommLogFile.IsOpen()) { m_CommLogFile.Write(fmt::format( FMT_STRING("^^^^^^ Wrong number of bytes read for this packet (exp 1 left, got {} left) ^^^^^^\n\n\n"), a_Buffer.GetReadableSpace() )); m_CommLogFile.Flush(); } ASSERT(!"Read wrong number of bytes!"); m_Client->PacketError(PacketType); } } void cProtocol_1_8_0::StartEncryption(const Byte * a_Key) { m_Encryptor.Init(a_Key, a_Key); m_Decryptor.Init(a_Key, a_Key); m_IsEncrypted = true; // Prepare the m_AuthServerID: cSha1Checksum Checksum; cServer * Server = cRoot::Get()->GetServer(); const AString & ServerID = Server->GetServerID(); Checksum.Update(reinterpret_cast(ServerID.c_str()), ServerID.length()); Checksum.Update(a_Key, 16); Checksum.Update(reinterpret_cast(Server->GetPublicKeyDER().data()), Server->GetPublicKeyDER().size()); Byte Digest[20]; Checksum.Finalize(Digest); cSha1Checksum::DigestToJava(Digest, m_AuthServerID); } ================================================ FILE: src/Protocol/Protocol_1_8.h ================================================ // Protocol_1_8.h /* Declares the 1.8 protocol classes: - cProtocol_1_8_0 - release 1.8 protocol (#47), also used by 1.8.1 to 1.8.9 */ #pragma once #include "Protocol.h" #include "../ByteBuffer.h" #include "../Registries/CustomStatistics.h" #include "../mbedTLS++/AesCfb128Decryptor.h" #include "../mbedTLS++/AesCfb128Encryptor.h" #include "CircularBufferCompressor.h" #include "StringCompression.h" class cProtocol_1_8_0: public cProtocol { using Super = cProtocol; public: cProtocol_1_8_0(cClientHandle * a_Client, const AString & a_ServerAddress, State a_State); virtual void DataReceived(cByteBuffer & a_Buffer, ContiguousByteBuffer & a_Data) override; virtual void DataPrepared(ContiguousByteBuffer & a_Data) override; // Sending stuff to clients (alphabetically sorted): virtual void SendAttachEntity (const cEntity & a_Entity, const cEntity & a_Vehicle) override; virtual void SendBlockAction (Vector3i a_BlockPos, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType) override; virtual void SendBlockBreakAnim (UInt32 a_EntityID, Vector3i a_BlockPos, char a_Stage) override; virtual void SendBlockChange (Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override; virtual void SendBlockChanges (int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes) override; virtual void SendBossBarAdd (UInt32 a_UniqueID, const cCompositeChat & a_Title, float a_FractionFilled, BossBarColor a_Color, BossBarDivisionType a_DivisionType, bool a_DarkenSky, bool a_PlayEndMusic, bool a_CreateFog) override; virtual void SendBossBarRemove (UInt32 a_UniqueID) override; virtual void SendBossBarUpdateFlags (UInt32 a_UniqueID, bool a_DarkenSky, bool a_PlayEndMusic, bool a_CreateFog) override; virtual void SendBossBarUpdateHealth (UInt32 a_UniqueID, float a_FractionFilled) override; virtual void SendBossBarUpdateStyle (UInt32 a_UniqueID, BossBarColor a_Color, BossBarDivisionType a_DivisionType) override; virtual void SendBossBarUpdateTitle (UInt32 a_UniqueID, const cCompositeChat & a_Title) override; virtual void SendCameraSetTo (const cEntity & a_Entity) override; virtual void SendChat (const AString & a_Message, eChatType a_Type) override; virtual void SendChat (const cCompositeChat & a_Message, eChatType a_Type, bool a_ShouldUseChatPrefixes) override; virtual void SendChatRaw (const AString & a_MessageRaw, eChatType a_Type) override; virtual void SendChunkData (ContiguousByteBufferView a_ChunkData) override; virtual void SendCollectEntity (const cEntity & a_Collected, const cEntity & a_Collector, unsigned a_Count) override; virtual void SendDestroyEntity (const cEntity & a_Entity) override; virtual void SendDetachEntity (const cEntity & a_Entity, const cEntity & a_PreviousVehicle) override; virtual void SendDisconnect (const AString & a_Reason) override; virtual void SendEditSign (Vector3i a_BlockPos) override; ///< Request the client to open up the sign editor for the sign (1.6+) virtual void SendEntityAnimation (const cEntity & a_Entity, EntityAnimation a_Animation) override; virtual void SendEntityEffect (const cEntity & a_Entity, int a_EffectID, int a_Amplifier, int a_Duration) override; virtual void SendEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item) override; virtual void SendEntityHeadLook (const cEntity & a_Entity) override; virtual void SendEntityLook (const cEntity & a_Entity) override; virtual void SendEntityMetadata (const cEntity & a_Entity) override; virtual void SendEntityPosition (const cEntity & a_Entity) override; virtual void SendEntityProperties (const cEntity & a_Entity) override; virtual void SendEntityVelocity (const cEntity & a_Entity) override; virtual void SendExperience (void) override; virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) override; virtual void SendExplosion (Vector3f a_Position, float a_Power) override; virtual void SendGameMode (eGameMode a_GameMode) override; virtual void SendHealth (void) override; virtual void SendHeldItemChange (int a_ItemIndex) override; virtual void SendHideTitle (void) override; virtual void SendInventorySlot (char a_WindowID, short a_SlotNum, const cItem & a_Item) override; virtual void SendKeepAlive (UInt32 a_PingID) override; virtual void SendLeashEntity (const cEntity & a_Entity, const cEntity & a_EntityLeashedTo) override; virtual void SendLogin (const cPlayer & a_Player, const cWorld & a_World) override; virtual void SendLoginSuccess (void) override; virtual void SendMapData (const cMap & a_Map, int a_DataStartX, int a_DataStartY) override; virtual void SendPaintingSpawn (const cPainting & a_Painting) override; virtual void SendPlayerAbilities (void) override; virtual void SendParticleEffect (const AString & a_ParticleName, Vector3f a_Src, Vector3f a_Offset, float a_ParticleData, int a_ParticleAmount) override; virtual void SendParticleEffect (const AString & a_ParticleName, Vector3f a_Src, Vector3f a_Offset, float a_ParticleData, int a_ParticleAmount, std::array a_Data) override; virtual void SendPlayerListAddPlayer (const cPlayer & a_Player) override; virtual void SendPlayerListHeaderFooter (const cCompositeChat & a_Header, const cCompositeChat & a_Footer) override; virtual void SendPlayerListRemovePlayer (const cPlayer & a_Player) override; virtual void SendPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_CustomName) override; virtual void SendPlayerListUpdateGameMode (const cPlayer & a_Player) override; virtual void SendPlayerListUpdatePing () override; virtual void SendPlayerMoveLook (Vector3d a_Pos, float a_Yaw, float a_Pitch, bool a_IsRelative) override; virtual void SendPlayerMoveLook (void) override; virtual void SendPlayerPermissionLevel (void) override; virtual void SendPlayerPosition (void) override; virtual void SendPlayerSpawn (const cPlayer & a_Player) override; virtual void SendPluginMessage (const AString & a_Channel, ContiguousByteBufferView a_Message) override; virtual void SendRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID) override; virtual void SendResetTitle (void) override; virtual void SendResourcePack (const AString & a_ResourcePackUrl) override; virtual void SendRespawn (eDimension a_Dimension) override; virtual void SendSoundEffect (const AString & a_SoundName, Vector3d a_Origin, float a_Volume, float a_Pitch) override; virtual void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) override; virtual void SendScoreUpdate (const AString & a_Objective, const AString & a_Player, cObjective::Score a_Score, Byte a_Mode) override; virtual void SendDisplayObjective (const AString & a_Objective, cScoreboard::eDisplaySlot a_Display) override; virtual void SendSetSubTitle (const cCompositeChat & a_SubTitle) override; virtual void SendSetRawSubTitle (const AString & a_SubTitle) override; virtual void SendSetTitle (const cCompositeChat & a_Title) override; virtual void SendSetRawTitle (const AString & a_Title) override; virtual void SendSoundParticleEffect (const EffectID a_EffectID, Vector3i a_Origin, int a_Data) override; virtual void SendSpawnEntity (const cEntity & a_Entity) override; virtual void SendSpawnMob (const cMonster & a_Mob) override; virtual void SendStatistics (const StatisticsManager & a_Manager) override; virtual void SendTabCompletionResults (const AStringVector & a_Results) override; virtual void SendThunderbolt (Vector3i a_BlockPos) override; virtual void SendTitleTimes (int a_FadeInTicks, int a_DisplayTicks, int a_FadeOutTicks) override; virtual void SendTimeUpdate (cTickTimeLong a_WorldAge, cTickTimeLong a_WorldDate, bool a_DoDaylightCycle) override; virtual void SendUnleashEntity (const cEntity & a_Entity) override; virtual void SendUnloadChunk (int a_ChunkX, int a_ChunkZ) override; virtual void SendUpdateBlockEntity (cBlockEntity & a_BlockEntity) override; virtual void SendUpdateSign (Vector3i a_BlockPos, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4) override; virtual void SendUnlockRecipe (UInt32 a_RecipeID) override; virtual void SendInitRecipes (UInt32 a_RecipeID) override; virtual void SendWeather (eWeather a_Weather) override; virtual void SendWholeInventory (const cWindow & a_Window) override; virtual void SendWindowClose (const cWindow & a_Window) override; virtual void SendWindowOpen (const cWindow & a_Window) override; virtual void SendWindowProperty (const cWindow & a_Window, size_t a_Property, short a_Value) override; virtual AString GetAuthServerID(void) override { return m_AuthServerID; } /** Compress the packet. a_Packet must be without packet length. a_Compressed will be set to the compressed packet includes packet length and data length. */ static void CompressPacket(CircularBufferCompressor & a_Packet, ContiguousByteBuffer & a_Compressed); protected: /** State of the protocol. */ State m_State; /** Converts the BlockFace received by the protocol into eBlockFace constants. If the received value doesn't match any of our eBlockFace constants, BLOCK_FACE_NONE is returned. */ static eBlockFace FaceIntToBlockFace(Int32 a_FaceInt); /** Get the packet ID for a given packet. */ virtual UInt32 GetPacketID(ePacketType a_Packet) const override; /** Converts an animation into an ID suitable for use with the Entity Animation packet. Returns (uchar)-1 if the protocol version doesn't support this animation. */ virtual unsigned char GetProtocolEntityAnimation(EntityAnimation a_Animation) const; /** Converts an animation into an ID suitable for use with the Entity Status packet. Returns -1 if the protocol version doesn't support this animation. */ virtual signed char GetProtocolEntityStatus(EntityAnimation a_Animation) const; /** Converts an entity to a protocol-specific entity type. Only entities that the Send Spawn Entity packet supports are valid inputs to this method */ virtual UInt8 GetProtocolEntityType(const cEntity & a_Entity) const; /** Converts eMonsterType to protocol-specific mob types */ virtual UInt32 GetProtocolMobType(eMonsterType a_MobType) const; /** The 1.8 protocol use a particle id instead of a string. This function converts the name to the id. If the name is incorrect, it returns 0. */ virtual int GetProtocolParticleID(const AString & a_ParticleName) const; /** Returns the protocol version. */ virtual Version GetProtocolVersion() const override; /** Reads and handles the packet. The packet length and type have already been read. Returns true if the packet was understood, false if it was an unknown packet. */ virtual bool HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType); // Packet handlers while in the Status state (m_State == 1): virtual void HandlePacketStatusPing(cByteBuffer & a_ByteBuffer); virtual void HandlePacketStatusRequest(cByteBuffer & a_ByteBuffer); // Packet handlers while in the Login state (m_State == 2): virtual void HandlePacketLoginEncryptionResponse(cByteBuffer & a_ByteBuffer); virtual void HandlePacketLoginStart(cByteBuffer & a_ByteBuffer); // Packet handlers while in the Game state (m_State == 3): virtual void HandlePacketAnimation (cByteBuffer & a_ByteBuffer); virtual void HandlePacketBlockDig (cByteBuffer & a_ByteBuffer); virtual void HandlePacketBlockPlace (cByteBuffer & a_ByteBuffer); virtual void HandlePacketChatMessage (cByteBuffer & a_ByteBuffer); virtual void HandlePacketClientSettings (cByteBuffer & a_ByteBuffer); virtual void HandlePacketClientStatus (cByteBuffer & a_ByteBuffer); virtual void HandlePacketCreativeInventoryAction(cByteBuffer & a_ByteBuffer); virtual void HandlePacketEntityAction (cByteBuffer & a_ByteBuffer); virtual void HandlePacketKeepAlive (cByteBuffer & a_ByteBuffer); virtual void HandlePacketPlayer (cByteBuffer & a_ByteBuffer); virtual void HandlePacketPlayerAbilities (cByteBuffer & a_ByteBuffer); virtual void HandlePacketPlayerLook (cByteBuffer & a_ByteBuffer); virtual void HandlePacketPlayerPos (cByteBuffer & a_ByteBuffer); virtual void HandlePacketPlayerPosLook (cByteBuffer & a_ByteBuffer); virtual void HandlePacketPluginMessage (cByteBuffer & a_ByteBuffer); virtual void HandlePacketResourcePackStatus (cByteBuffer & a_ByteBuffer); virtual void HandlePacketSlotSelect (cByteBuffer & a_ByteBuffer); virtual void HandlePacketSpectate (cByteBuffer & a_ByteBuffer); virtual void HandlePacketSteerVehicle (cByteBuffer & a_ByteBuffer); virtual void HandlePacketTabComplete (cByteBuffer & a_ByteBuffer); virtual void HandlePacketUpdateSign (cByteBuffer & a_ByteBuffer); virtual void HandlePacketUseEntity (cByteBuffer & a_ByteBuffer); virtual void HandlePacketEnchantItem (cByteBuffer & a_ByteBuffer); virtual void HandlePacketWindowClick (cByteBuffer & a_ByteBuffer); virtual void HandlePacketWindowClose (cByteBuffer & a_ByteBuffer); /** Parses Vanilla plugin messages into specific ClientHandle calls. The message payload is still in the bytebuffer, the handler reads it specifically for each handled channel. */ virtual void HandleVanillaPluginMessage(cByteBuffer & a_ByteBuffer, std::string_view a_Channel); /** Parses item metadata as read by ReadItem(), into the item enchantments. */ virtual void ParseItemMetadata(cItem & a_Item, ContiguousByteBufferView a_Metadata) const; /** Reads an item out of the received data, sets a_Item to the values read. Returns false if not enough received data. a_KeepRemainingBytes tells the function to keep that many bytes at the end of the buffer. */ virtual bool ReadItem(cByteBuffer & a_ByteBuffer, cItem & a_Item, size_t a_KeepRemainingBytes = 0) const; /** Sends the entity type and entity-dependent data required for the entity to initially spawn. */ virtual void SendEntitySpawn(const cEntity & a_Entity, const UInt8 a_ObjectType, const Int32 a_ObjectData); /** Sends the packet to the client. Called by the cPacketizer's destructor. */ virtual void SendPacket(cPacketizer & a_Packet) override; /** Writes the block entity data for the specified block entity into the packet. */ virtual void WriteBlockEntity(cFastNBTWriter & a_Writer, const cBlockEntity & a_BlockEntity) const; /** Writes the metadata for the specified entity, not including the terminating 0x7f. */ virtual void WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_Entity) const; /** Writes the entity properties for the specified entity, including the Count field. */ virtual void WriteEntityProperties(cPacketizer & a_Pkt, const cEntity & a_Entity) const; /** Writes the item data into a packet. */ virtual void WriteItem(cPacketizer & a_Pkt, const cItem & a_Item) const; /** Writes the mob-specific metadata for the specified mob */ virtual void WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mob) const; private: AString m_ServerAddress; AString m_AuthServerID; bool m_IsEncrypted; cAesCfb128Decryptor m_Decryptor; cAesCfb128Encryptor m_Encryptor; CircularBufferCompressor m_Compressor; CircularBufferExtractor m_Extractor; /** The logfile where the comm is logged, when g_ShouldLogComm is true */ cFile m_CommLogFile; /** Adds the received (unencrypted) data to m_ReceivedData, parses complete packets */ void AddReceivedData(cByteBuffer & a_Buffer, ContiguousByteBufferView a_Data); /** Converts a statistic to a protocol-specific string. Protocols <= 1.12 use strings, hence this is a static as the string-mapping was append-only for the versions that used it. Returns an empty string, handled correctly by the client, for newer, unsupported statistics. */ static const char * GetProtocolStatisticName(CustomStatistic a_Statistic); /** Handle a complete packet stored in the given buffer. */ void HandlePacket(cByteBuffer & a_Buffer); void StartEncryption(const Byte * a_Key); } ; ================================================ FILE: src/Protocol/Protocol_1_9.cpp ================================================ // Protocol_1_9.cpp /* Implements the 1.9 protocol classes: - cProtocol_1_9_0 - release 1.9 protocol (#107) - cProtocol_1_9_1 - release 1.9.1 protocol (#108) - cProtocol_1_9_2 - release 1.9.2 protocol (#109) - cProtocol_1_9_4 - release 1.9.4 protocol (#110) */ #include "Globals.h" #include "Protocol_1_9.h" #include "../mbedTLS++/Sha1Checksum.h" #include "Packetizer.h" #include "../ClientHandle.h" #include "../Root.h" #include "../Server.h" #include "../World.h" #include "../StringCompression.h" #include "../CompositeChat.h" #include "../JsonUtils.h" #include "../WorldStorage/FastNBT.h" #include "../Entities/EnderCrystal.h" #include "../Entities/ExpOrb.h" #include "../Entities/Minecart.h" #include "../Entities/FallingBlock.h" #include "../Entities/Painting.h" #include "../Entities/Pickup.h" #include "../Entities/Player.h" #include "../Entities/ItemFrame.h" #include "../Entities/ArrowEntity.h" #include "../Entities/FireworkEntity.h" #include "../Entities/SplashPotionEntity.h" #include "../Items/ItemSpawnEgg.h" #include "../Mobs/IncludeAllMonsters.h" #include "../UI/HorseWindow.h" #include "../BlockEntities/MobSpawnerEntity.h" // Value for main hand in Hand parameter for Protocol 1.9. #define MAIN_HAND 0 // Value for left hand in MainHand parameter for Protocol 1.9. #define LEFT_HAND 0 //////////////////////////////////////////////////////////////////////////////// // cProtocol_1_9_0: cProtocol_1_9_0::cProtocol_1_9_0(cClientHandle * a_Client, const AString & a_ServerAddress, State a_State) : Super(a_Client, a_ServerAddress, a_State), m_IsTeleportIdConfirmed(true), m_OutstandingTeleportId(0) { } void cProtocol_1_9_0::SendAttachEntity(const cEntity & a_Entity, const cEntity & a_Vehicle) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktAttachEntity); Pkt.WriteVarInt32(a_Vehicle.GetUniqueID()); Pkt.WriteVarInt32(1); // 1 passenger Pkt.WriteVarInt32(a_Entity.GetUniqueID()); } void cProtocol_1_9_0::SendBossBarAdd(UInt32 a_UniqueID, const cCompositeChat & a_Title, float a_FractionFilled, BossBarColor a_Color, BossBarDivisionType a_DivisionType, bool a_DarkenSky, bool a_PlayEndMusic, bool a_CreateFog) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktBossBar); // TODO: Bad way to write a UUID, and it's not a true UUID, but this is functional for now. Pkt.WriteBEUInt64(0); Pkt.WriteBEUInt64(a_UniqueID); Pkt.WriteVarInt32(0); // Add Pkt.WriteString(a_Title.CreateJsonString()); Pkt.WriteBEFloat(a_FractionFilled); Pkt.WriteVarInt32([a_Color] { switch (a_Color) { case BossBarColor::Pink: return 0U; case BossBarColor::Blue: return 1U; case BossBarColor::Red: return 2U; case BossBarColor::Green: return 3U; case BossBarColor::Yellow: return 4U; case BossBarColor::Purple: return 5U; case BossBarColor::White: return 6U; } UNREACHABLE("Unsupported boss bar property"); }()); Pkt.WriteVarInt32([a_DivisionType] { switch (a_DivisionType) { case BossBarDivisionType::None: return 0U; case BossBarDivisionType::SixNotches: return 1U; case BossBarDivisionType::TenNotches: return 2U; case BossBarDivisionType::TwelveNotches: return 3U; case BossBarDivisionType::TwentyNotches: return 4U; } UNREACHABLE("Unsupported boss bar property"); }()); { UInt8 Flags = 0x00; if (a_DarkenSky) { Flags |= 0x01; } if (a_PlayEndMusic || a_CreateFog) { Flags |= 0x02; } Pkt.WriteBEUInt8(Flags); } } void cProtocol_1_9_0::SendBossBarRemove(UInt32 a_UniqueID) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktBossBar); // TODO: Bad way to write a UUID, and it's not a true UUID, but this is functional for now. Pkt.WriteBEUInt64(0); Pkt.WriteBEUInt64(a_UniqueID); Pkt.WriteVarInt32(1); // Remove } void cProtocol_1_9_0::SendBossBarUpdateFlags(UInt32 a_UniqueID, bool a_DarkenSky, bool a_PlayEndMusic, bool a_CreateFog) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktBossBar); // TODO: Bad way to write a UUID, and it's not a true UUID, but this is functional for now. Pkt.WriteBEUInt64(0); Pkt.WriteBEUInt64(a_UniqueID); Pkt.WriteVarInt32(5); // Update Flags { UInt8 Flags = 0x00; if (a_DarkenSky) { Flags |= 0x01; } if (a_PlayEndMusic || a_CreateFog) { Flags |= 0x02; } Pkt.WriteBEUInt8(Flags); } } void cProtocol_1_9_0::SendBossBarUpdateHealth(UInt32 a_UniqueID, float a_FractionFilled) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktBossBar); // TODO: Bad way to write a UUID, and it's not a true UUID, but this is functional for now. Pkt.WriteBEUInt64(0); Pkt.WriteBEUInt64(a_UniqueID); Pkt.WriteVarInt32(2); // Update health Pkt.WriteBEFloat(a_FractionFilled); } void cProtocol_1_9_0::SendBossBarUpdateStyle(UInt32 a_UniqueID, BossBarColor a_Color, BossBarDivisionType a_DivisionType) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktBossBar); // TODO: Bad way to write a UUID, and it's not a true UUID, but this is functional for now. Pkt.WriteBEUInt64(0); Pkt.WriteBEUInt64(a_UniqueID); Pkt.WriteVarInt32(4); // Update health Pkt.WriteVarInt32([a_Color] { switch (a_Color) { case BossBarColor::Pink: return 0U; case BossBarColor::Blue: return 1U; case BossBarColor::Red: return 2U; case BossBarColor::Green: return 3U; case BossBarColor::Yellow: return 4U; case BossBarColor::Purple: return 5U; case BossBarColor::White: return 6U; } UNREACHABLE("Unsupported boss bar property"); }()); Pkt.WriteVarInt32([a_DivisionType] { switch (a_DivisionType) { case BossBarDivisionType::None: return 0U; case BossBarDivisionType::SixNotches: return 1U; case BossBarDivisionType::TenNotches: return 2U; case BossBarDivisionType::TwelveNotches: return 3U; case BossBarDivisionType::TwentyNotches: return 4U; } UNREACHABLE("Unsupported boss bar property"); }()); } void cProtocol_1_9_0::SendBossBarUpdateTitle(UInt32 a_UniqueID, const cCompositeChat & a_Title) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktBossBar); // TODO: Bad way to write a UUID, and it's not a true UUID, but this is functional for now. Pkt.WriteBEUInt64(0); Pkt.WriteBEUInt64(a_UniqueID); Pkt.WriteVarInt32(3); // Update title Pkt.WriteString(a_Title.CreateJsonString()); } void cProtocol_1_9_0::SendDetachEntity(const cEntity & a_Entity, const cEntity & a_PreviousVehicle) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktAttachEntity); Pkt.WriteVarInt32(a_PreviousVehicle.GetUniqueID()); Pkt.WriteVarInt32(0); // No passangers } void cProtocol_1_9_0::SendEntityEquipment(const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktEntityEquipment); Pkt.WriteVarInt32(a_Entity.GetUniqueID()); // Needs to be adjusted due to the insertion of offhand at slot 1 if (a_SlotNum > 0) { a_SlotNum++; } Pkt.WriteVarInt32(static_cast(a_SlotNum)); WriteItem(Pkt, a_Item); } void cProtocol_1_9_0::SendEntityMetadata(const cEntity & a_Entity) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktEntityMeta); Pkt.WriteVarInt32(a_Entity.GetUniqueID()); WriteEntityMetadata(Pkt, a_Entity); Pkt.WriteBEUInt8(0xff); // The termination byte } void cProtocol_1_9_0::SendEntityPosition(const cEntity & a_Entity) { ASSERT(m_State == 3); // In game mode? const auto Delta = (a_Entity.GetPosition() * 32 * 128).Floor() - (a_Entity.GetLastSentPosition() * 32 * 128).Floor(); // Ensure that the delta has enough precision and is within range of a BEInt16: if ( Delta.HasNonZeroLength() && cByteBuffer::CanBEInt16Represent(Delta.x) && cByteBuffer::CanBEInt16Represent(Delta.y) && cByteBuffer::CanBEInt16Represent(Delta.z) ) { const auto Move = static_cast>(Delta); // Difference within limitations, use a relative move packet if (a_Entity.IsOrientationDirty()) { cPacketizer Pkt(*this, pktEntityRelMoveLook); Pkt.WriteVarInt32(a_Entity.GetUniqueID()); Pkt.WriteBEInt16(Move.x); Pkt.WriteBEInt16(Move.y); Pkt.WriteBEInt16(Move.z); Pkt.WriteByteAngle(a_Entity.GetYaw()); Pkt.WriteByteAngle(a_Entity.GetPitch()); Pkt.WriteBool(a_Entity.IsOnGround()); } else { cPacketizer Pkt(*this, pktEntityRelMove); Pkt.WriteVarInt32(a_Entity.GetUniqueID()); Pkt.WriteBEInt16(Move.x); Pkt.WriteBEInt16(Move.y); Pkt.WriteBEInt16(Move.z); Pkt.WriteBool(a_Entity.IsOnGround()); } return; } // Too big or small a movement, do a teleport. cPacketizer Pkt(*this, pktTeleportEntity); Pkt.WriteVarInt32(a_Entity.GetUniqueID()); Pkt.WriteBEDouble(a_Entity.GetPosX()); Pkt.WriteBEDouble(a_Entity.GetPosY()); Pkt.WriteBEDouble(a_Entity.GetPosZ()); Pkt.WriteByteAngle(a_Entity.GetYaw()); Pkt.WriteByteAngle(a_Entity.GetPitch()); Pkt.WriteBool(a_Entity.IsOnGround()); } void cProtocol_1_9_0::SendExperienceOrb(const cExpOrb & a_ExpOrb) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktSpawnExperienceOrb); Pkt.WriteVarInt32(a_ExpOrb.GetUniqueID()); Pkt.WriteBEDouble(a_ExpOrb.GetPosX()); Pkt.WriteBEDouble(a_ExpOrb.GetPosY()); Pkt.WriteBEDouble(a_ExpOrb.GetPosZ()); Pkt.WriteBEInt16(static_cast(a_ExpOrb.GetReward())); } void cProtocol_1_9_0::SendKeepAlive(UInt32 a_PingID) { // Drop the packet if the protocol is not in the Game state yet (caused a client crash): if (m_State != 3) { LOG("Trying to send a KeepAlive packet to a player who's not yet fully logged in (%d). The protocol class prevented the packet.", m_State); return; } cPacketizer Pkt(*this, pktKeepAlive); Pkt.WriteVarInt32(a_PingID); } void cProtocol_1_9_0::SendLeashEntity(const cEntity & a_Entity, const cEntity & a_EntityLeashedTo) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktLeashEntity); Pkt.WriteBEUInt32(a_Entity.GetUniqueID()); Pkt.WriteBEUInt32(a_EntityLeashedTo.GetUniqueID()); } void cProtocol_1_9_0::SendUnleashEntity(const cEntity & a_Entity) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktLeashEntity); Pkt.WriteBEUInt32(a_Entity.GetUniqueID()); Pkt.WriteBEInt32(-1); // Unleash a_Entity } void cProtocol_1_9_0::SendPaintingSpawn(const cPainting & a_Painting) { ASSERT(m_State == 3); // In game mode? double PosX = a_Painting.GetPosX(); double PosY = a_Painting.GetPosY(); double PosZ = a_Painting.GetPosZ(); cPacketizer Pkt(*this, pktSpawnPainting); Pkt.WriteVarInt32(a_Painting.GetUniqueID()); // TODO: Bad way to write a UUID, and it's not a true UUID, but this is functional for now. Pkt.WriteBEUInt64(0); Pkt.WriteBEUInt64(a_Painting.GetUniqueID()); Pkt.WriteString(a_Painting.GetName()); Pkt.WriteXYZPosition64(static_cast(PosX), static_cast(PosY), static_cast(PosZ)); Pkt.WriteBEInt8(static_cast(a_Painting.GetProtocolFacing())); } void cProtocol_1_9_0::SendMapData(const cMap & a_Map, int a_DataStartX, int a_DataStartY) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktMapData); Pkt.WriteVarInt32(a_Map.GetID()); Pkt.WriteBEUInt8(static_cast(a_Map.GetScale())); Pkt.WriteBool(true); Pkt.WriteVarInt32(static_cast(a_Map.GetDecorators().size())); for (const auto & Decorator : a_Map.GetDecorators()) { Pkt.WriteBEUInt8(static_cast((static_cast(Decorator.GetType()) << 4) | (Decorator.GetRot() & 0xF))); Pkt.WriteBEUInt8(static_cast(Decorator.GetPixelX())); Pkt.WriteBEUInt8(static_cast(Decorator.GetPixelZ())); } Pkt.WriteBEUInt8(128); Pkt.WriteBEUInt8(128); Pkt.WriteBEUInt8(static_cast(a_DataStartX)); Pkt.WriteBEUInt8(static_cast(a_DataStartY)); Pkt.WriteVarInt32(static_cast(a_Map.GetData().size())); for (auto itr = a_Map.GetData().cbegin(); itr != a_Map.GetData().cend(); ++itr) { Pkt.WriteBEUInt8(*itr); } } void cProtocol_1_9_0::SendPlayerMoveLook (const Vector3d a_Pos, const float a_Yaw, const float a_Pitch, const bool a_IsRelative) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktPlayerMoveLook); Pkt.WriteBEDouble(a_Pos.x); Pkt.WriteBEDouble(a_Pos.y); Pkt.WriteBEDouble(a_Pos.z); Pkt.WriteBEFloat(a_Yaw); Pkt.WriteBEFloat(a_Pitch); if (a_IsRelative) { // Set all bits to 1 - makes everything relative Pkt.WriteBEUInt8(static_cast(-1)); } else { // Set all bits to 0 - make everything absolute Pkt.WriteBEUInt8(0); } Pkt.WriteVarInt32(++m_OutstandingTeleportId); // This teleport ID hasn't been confirmed yet m_IsTeleportIdConfirmed = false; } void cProtocol_1_9_0::SendPlayerMoveLook(void) { cPlayer * Player = m_Client->GetPlayer(); SendPlayerMoveLook(Player->GetPosition(), static_cast(Player->GetYaw()), static_cast(Player->GetPitch()), false); } void cProtocol_1_9_0::SendPlayerPermissionLevel() { const cPlayer & Player = *m_Client->GetPlayer(); cPacketizer Pkt(*this, pktEntityStatus); Pkt.WriteBEUInt32(Player.GetUniqueID()); Pkt.WriteBEInt8([&Player]() -> signed char { if (Player.HasPermission("core.stop") || Player.HasPermission("core.reload") || Player.HasPermission("core.save-all")) { return 28; } if (Player.HasPermission("core.ban") || Player.HasPermission("core.deop") || Player.HasPermission("core.kick") || Player.HasPermission("core.op")) { return 27; } if (Player.HasPermission("cuberite.comandblock.set") || Player.HasPermission("core.clear") || Player.HasPermission("core.difficulty") || Player.HasPermission("core.effect") || Player.HasPermission("core.gamemode") || Player.HasPermission("core.tp") || Player.HasPermission("core.give")) { return 26; } if (Player.HasPermission("core.spawnprotect.bypass")) { return 25; } return 24; }()); } void cProtocol_1_9_0::SendPlayerSpawn(const cPlayer & a_Player) { // Called to spawn another player for the client cPacketizer Pkt(*this, pktSpawnOtherPlayer); Pkt.WriteVarInt32(a_Player.GetUniqueID()); Pkt.WriteUUID(a_Player.GetUUID()); Vector3d LastSentPos = a_Player.GetLastSentPosition(); Pkt.WriteBEDouble(LastSentPos.x); Pkt.WriteBEDouble(LastSentPos.y + 0.001); // The "+ 0.001" is there because otherwise the player falls through the block they were standing on. Pkt.WriteBEDouble(LastSentPos.z); Pkt.WriteByteAngle(a_Player.GetYaw()); Pkt.WriteByteAngle(a_Player.GetPitch()); WriteEntityMetadata(Pkt, a_Player); Pkt.WriteBEUInt8(0xff); // Metadata: end } void cProtocol_1_9_0::SendSoundEffect(const AString & a_SoundName, Vector3d a_Origin, float a_Volume, float a_Pitch) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktSoundEffect); Pkt.WriteString(a_SoundName); Pkt.WriteVarInt32(0); // Master sound category (may want to be changed to a parameter later) Pkt.WriteBEInt32(static_cast(a_Origin.x * 8.0)); Pkt.WriteBEInt32(static_cast(a_Origin.y * 8.0)); Pkt.WriteBEInt32(static_cast(a_Origin.z * 8.0)); Pkt.WriteBEFloat(a_Volume); Pkt.WriteBEUInt8(static_cast(a_Pitch * 63)); } void cProtocol_1_9_0::SendSpawnMob(const cMonster & a_Mob) { ASSERT(m_State == 3); // In game mode? const auto MobType = GetProtocolMobType(a_Mob.GetMobType()); // If the type is not valid in this protocol bail out: if (MobType == 0) { return; } cPacketizer Pkt(*this, pktSpawnMob); Pkt.WriteVarInt32(a_Mob.GetUniqueID()); // TODO: Bad way to write a UUID, and it's not a true UUID, but this is functional for now. Pkt.WriteBEUInt64(0); Pkt.WriteBEUInt64(a_Mob.GetUniqueID()); Pkt.WriteBEUInt8(static_cast(MobType)); Vector3d LastSentPos = a_Mob.GetLastSentPosition(); Pkt.WriteBEDouble(LastSentPos.x); Pkt.WriteBEDouble(LastSentPos.y); Pkt.WriteBEDouble(LastSentPos.z); Pkt.WriteByteAngle(a_Mob.GetHeadYaw()); // Doesn't seem to be used Pkt.WriteByteAngle(a_Mob.GetPitch()); Pkt.WriteByteAngle(a_Mob.GetYaw()); Pkt.WriteBEInt16(static_cast(a_Mob.GetSpeedX() * 400)); Pkt.WriteBEInt16(static_cast(a_Mob.GetSpeedY() * 400)); Pkt.WriteBEInt16(static_cast(a_Mob.GetSpeedZ() * 400)); WriteEntityMetadata(Pkt, a_Mob); Pkt.WriteBEUInt8(0xff); // Metadata terminator } void cProtocol_1_9_0::SendThunderbolt(Vector3i a_Origin) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktSpawnGlobalEntity); Pkt.WriteVarInt32(0); // EntityID = 0, always Pkt.WriteBEUInt8(1); // Type = Thunderbolt Pkt.WriteBEDouble(a_Origin.x); Pkt.WriteBEDouble(a_Origin.y); Pkt.WriteBEDouble(a_Origin.z); } void cProtocol_1_9_0::SendUnloadChunk(int a_ChunkX, int a_ChunkZ) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktUnloadChunk); Pkt.WriteBEInt32(a_ChunkX); Pkt.WriteBEInt32(a_ChunkZ); } UInt32 cProtocol_1_9_0::GetPacketID(cProtocol::ePacketType a_Packet) const { switch (a_Packet) { case pktAttachEntity: return 0x40; case pktBlockAction: return 0x0a; case pktBlockBreakAnim: return 0x08; case pktBlockChange: return 0x0b; case pktBlockChanges: return 0x10; case pktBossBar: return 0x0c; case pktCameraSetTo: return 0x36; case pktChatRaw: return 0x0f; case pktCollectEntity: return 0x49; case pktDestroyEntity: return 0x30; case pktDifficulty: return 0x0d; case pktDisconnectDuringGame: return 0x1a; case pktDisconnectDuringLogin: return 0x0; case pktDisplayObjective: return 0x38; case pktEditSign: return 0x2a; case pktEncryptionRequest: return 0x01; case pktEntityAnimation: return 0x06; case pktEntityEffect: return 0x4c; case pktEntityEquipment: return 0x3c; case pktEntityHeadLook: return 0x34; case pktEntityLook: return 0x27; case pktEntityMeta: return 0x39; case pktEntityProperties: return 0x4b; case pktEntityRelMove: return 0x25; case pktEntityRelMoveLook: return 0x26; case pktEntityStatus: return 0x1b; case pktEntityVelocity: return 0x3b; case pktExperience: return 0x3d; case pktExplosion: return 0x1c; case pktGameMode: return 0x1e; case pktHeldItemChange: return 0x37; case pktInventorySlot: return 0x16; case pktJoinGame: return 0x23; case pktKeepAlive: return 0x1f; case pktLeashEntity: return 0x3a; case pktLoginSuccess: return 0x02; case pktMapData: return 0x24; case pktParticleEffect: return 0x22; case pktPingResponse: return 0x01; case pktPlayerAbilities: return 0x2b; case pktPlayerList: return 0x2d; case pktPlayerListHeaderFooter: return 0x48; case pktPlayerMoveLook: return 0x2e; case pktPluginMessage: return 0x18; case pktRemoveEntityEffect: return 0x31; case pktResourcePack: return 0x32; case pktRespawn: return 0x33; case pktScoreboardObjective: return 0x3f; case pktSpawnExperienceOrb: return 0x01; case pktSpawnGlobalEntity: return 0x02; case pktSpawnObject: return 0x00; case pktSpawnOtherPlayer: return 0x05; case pktSpawnPainting: return 0x04; case pktSpawnPosition: return 0x43; case pktSoundEffect: return 0x19; case pktSoundParticleEffect: return 0x21; case pktSpawnMob: return 0x03; case pktStartCompression: return 0x03; case pktStatistics: return 0x07; case pktStatusResponse: return 0x00; case pktTabCompletionResults: return 0x0e; case pktTeleportEntity: return 0x4a; case pktTimeUpdate: return 0x44; case pktTitle: return 0x45; case pktUnloadChunk: return 0x1d; case pktUpdateBlockEntity: return 0x09; case pktUpdateHealth: return 0x3e; case pktUpdateScore: return 0x42; case pktUpdateSign: return 0x46; case pktUseBed: return 0x2f; case pktWeather: return 0x1e; case pktWindowClose: return 0x12; case pktWindowItems: return 0x14; case pktWindowOpen: return 0x13; case pktWindowProperty: return 0x15; // Unsupported packets case pktUnlockRecipe: { break; } default: break; } UNREACHABLE("Unsupported outgoing packet type"); } unsigned char cProtocol_1_9_0::GetProtocolEntityAnimation(const EntityAnimation a_Animation) const { if (a_Animation == EntityAnimation::PlayerOffHandSwings) { return 3; } return Super::GetProtocolEntityAnimation(a_Animation); } signed char cProtocol_1_9_0::GetProtocolEntityStatus(const EntityAnimation a_Animation) const { switch (a_Animation) { case EntityAnimation::ArmorStandGetsHit: return 32; case EntityAnimation::ArrowTipSparkles: return 0; case EntityAnimation::PawnShieldBlocks: return 29; case EntityAnimation::PawnShieldBreaks: return 30; case EntityAnimation::PawnThornsPricks: return 33; default: return Super::GetProtocolEntityStatus(a_Animation); } } UInt32 cProtocol_1_9_0::GetProtocolMobType(const eMonsterType a_MobType) const { switch (a_MobType) { case mtShulker: return 69; default: return Super::GetProtocolMobType(a_MobType); } } cProtocol::Version cProtocol_1_9_0::GetProtocolVersion() const { return Version::v1_9_0; } bool cProtocol_1_9_0::HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType) { switch (m_State) { case State::Status: { switch (a_PacketType) { case 0x00: HandlePacketStatusRequest(a_ByteBuffer); return true; case 0x01: HandlePacketStatusPing (a_ByteBuffer); return true; } break; } case State::Login: { switch (a_PacketType) { case 0x00: HandlePacketLoginStart (a_ByteBuffer); return true; case 0x01: HandlePacketLoginEncryptionResponse(a_ByteBuffer); return true; } break; } case State::Game: { switch (a_PacketType) { case 0x00: HandleConfirmTeleport (a_ByteBuffer); return true; case 0x01: HandlePacketTabComplete (a_ByteBuffer); return true; case 0x02: HandlePacketChatMessage (a_ByteBuffer); return true; case 0x03: HandlePacketClientStatus (a_ByteBuffer); return true; case 0x04: HandlePacketClientSettings (a_ByteBuffer); return true; case 0x05: break; // Confirm transaction - not used in MCS case 0x06: HandlePacketEnchantItem (a_ByteBuffer); return true; case 0x07: HandlePacketWindowClick (a_ByteBuffer); return true; case 0x08: HandlePacketWindowClose (a_ByteBuffer); return true; case 0x09: HandlePacketPluginMessage (a_ByteBuffer); return true; case 0x0a: HandlePacketUseEntity (a_ByteBuffer); return true; case 0x0b: HandlePacketKeepAlive (a_ByteBuffer); return true; case 0x0c: HandlePacketPlayerPos (a_ByteBuffer); return true; case 0x0d: HandlePacketPlayerPosLook (a_ByteBuffer); return true; case 0x0e: HandlePacketPlayerLook (a_ByteBuffer); return true; case 0x0f: HandlePacketPlayer (a_ByteBuffer); return true; case 0x10: HandlePacketVehicleMove (a_ByteBuffer); return true; case 0x11: HandlePacketBoatSteer (a_ByteBuffer); return true; case 0x12: HandlePacketPlayerAbilities (a_ByteBuffer); return true; case 0x13: HandlePacketBlockDig (a_ByteBuffer); return true; case 0x14: HandlePacketEntityAction (a_ByteBuffer); return true; case 0x15: HandlePacketSteerVehicle (a_ByteBuffer); return true; case 0x16: HandlePacketResourcePackStatus (a_ByteBuffer); return true; case 0x17: HandlePacketSlotSelect (a_ByteBuffer); return true; case 0x18: HandlePacketCreativeInventoryAction(a_ByteBuffer); return true; case 0x19: HandlePacketUpdateSign (a_ByteBuffer); return true; case 0x1a: HandlePacketAnimation (a_ByteBuffer); return true; case 0x1b: HandlePacketSpectate (a_ByteBuffer); return true; case 0x1c: HandlePacketBlockPlace (a_ByteBuffer); return true; case 0x1d: HandlePacketUseItem (a_ByteBuffer); return true; } break; } } // switch (m_State) // Unknown packet type, report to the ClientHandle: m_Client->PacketUnknown(a_PacketType); return false; } void cProtocol_1_9_0::HandlePacketAnimation(cByteBuffer & a_ByteBuffer) { HANDLE_READ(a_ByteBuffer, ReadVarInt, Int32, Hand); m_Client->HandleAnimation(Hand == MAIN_HAND); // Packet exists solely for arm-swing notification (main and off-hand). } void cProtocol_1_9_0::HandlePacketBlockDig(cByteBuffer & a_ByteBuffer) { HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, Status); Vector3i Position; if (!a_ByteBuffer.ReadXYZPosition64(Position)) { return; } HANDLE_READ(a_ByteBuffer, ReadVarInt, Int32, Face); m_Client->HandleLeftClick(Position, FaceIntToBlockFace(Face), Status); } void cProtocol_1_9_0::HandlePacketBlockPlace(cByteBuffer & a_ByteBuffer) { Vector3i Position; if (!a_ByteBuffer.ReadXYZPosition64(Position)) { return; } HANDLE_READ(a_ByteBuffer, ReadVarInt, Int32, Face); HANDLE_READ(a_ByteBuffer, ReadVarInt, Int32, Hand); HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, CursorX); HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, CursorY); HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, CursorZ); m_Client->HandleRightClick(Position, FaceIntToBlockFace(Face), {CursorX, CursorY, CursorZ}, Hand == MAIN_HAND); } void cProtocol_1_9_0::HandlePacketBoatSteer(cByteBuffer & a_ByteBuffer) { HANDLE_READ(a_ByteBuffer, ReadBool, bool, RightPaddle); HANDLE_READ(a_ByteBuffer, ReadBool, bool, LeftPaddle); // Get the players vehicle cPlayer * Player = m_Client->GetPlayer(); cEntity * Vehicle = Player->GetAttached(); if (Vehicle) { if (Vehicle->GetEntityType() == cEntity::etBoat) { auto * Boat = static_cast(Vehicle); Boat->UpdatePaddles(RightPaddle, LeftPaddle); } } } void cProtocol_1_9_0::HandlePacketClientSettings(cByteBuffer & a_ByteBuffer) { HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Locale); HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, ViewDistance); HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, ChatFlags); HANDLE_READ(a_ByteBuffer, ReadBool, bool, ChatColors); HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, SkinParts); HANDLE_READ(a_ByteBuffer, ReadVarInt, UInt32, MainHand); m_Client->SetLocale(Locale); m_Client->SetViewDistance(ViewDistance); m_Client->GetPlayer()->SetSkinParts(SkinParts); m_Client->GetPlayer()->SetLeftHanded(MainHand == LEFT_HAND); // TODO: Handle chat flags and chat colors } void cProtocol_1_9_0::HandleConfirmTeleport(cByteBuffer & a_ByteBuffer) { HANDLE_READ(a_ByteBuffer, ReadVarInt32, UInt32, TeleportID); // Can we stop throwing away incoming player position packets? if (TeleportID == m_OutstandingTeleportId) { m_IsTeleportIdConfirmed = true; } } void cProtocol_1_9_0::HandlePacketEntityAction(cByteBuffer & a_ByteBuffer) { HANDLE_READ(a_ByteBuffer, ReadVarInt, UInt32, PlayerID); HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, Action); HANDLE_READ(a_ByteBuffer, ReadVarInt, UInt32, JumpBoost); if (PlayerID != m_Client->GetPlayer()->GetUniqueID()) { LOGD("Player \"%s\" attempted to action another entity - hacked client?", m_Client->GetUsername().c_str()); return; } switch (Action) { case 0: return m_Client->HandleCrouch(true); case 1: return m_Client->HandleCrouch(false); case 2: return m_Client->HandleLeaveBed(); case 3: return m_Client->HandleSprint(true); case 4: return m_Client->HandleSprint(false); case 7: return m_Client->HandleOpenHorseInventory(); case 8: return m_Client->HandleStartElytraFlight(); } } void cProtocol_1_9_0::HandlePacketPlayerPos(cByteBuffer & a_ByteBuffer) { HANDLE_READ(a_ByteBuffer, ReadBEDouble, double, PosX); HANDLE_READ(a_ByteBuffer, ReadBEDouble, double, PosY); HANDLE_READ(a_ByteBuffer, ReadBEDouble, double, PosZ); HANDLE_READ(a_ByteBuffer, ReadBool, bool, IsOnGround); if (m_IsTeleportIdConfirmed) { m_Client->HandlePlayerMove({PosX, PosY, PosZ}, IsOnGround); } } void cProtocol_1_9_0::HandlePacketPlayerPosLook(cByteBuffer & a_ByteBuffer) { HANDLE_READ(a_ByteBuffer, ReadBEDouble, double, PosX); HANDLE_READ(a_ByteBuffer, ReadBEDouble, double, PosY); HANDLE_READ(a_ByteBuffer, ReadBEDouble, double, PosZ); HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, Yaw); HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, Pitch); HANDLE_READ(a_ByteBuffer, ReadBool, bool, IsOnGround); if (m_IsTeleportIdConfirmed) { m_Client->HandlePlayerMoveLook({PosX, PosY, PosZ}, Yaw, Pitch, IsOnGround); } } void cProtocol_1_9_0::HandlePacketSteerVehicle(cByteBuffer & a_ByteBuffer) { HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, Sideways); HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, Forward); HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, Flags); if ((Flags & 0x2) != 0) { m_Client->HandleUnmount(); } else if ((Flags & 0x1) != 0) { // TODO: Handle vehicle jump (for animals) } else { m_Client->HandleSteerVehicle(Forward, Sideways); } } void cProtocol_1_9_0::HandlePacketTabComplete(cByteBuffer & a_ByteBuffer) { HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Text); HANDLE_READ(a_ByteBuffer, ReadBool, bool, AssumeCommand); HANDLE_READ(a_ByteBuffer, ReadBool, bool, HasPosition); if (HasPosition) { HANDLE_READ(a_ByteBuffer, ReadBEInt64, Int64, Position); } m_Client->HandleTabCompletion(Text); } void cProtocol_1_9_0::HandlePacketUpdateSign(cByteBuffer & a_ByteBuffer) { Vector3i Position; if (!a_ByteBuffer.ReadXYZPosition64(Position)) { return; } AString Lines[4]; for (int i = 0; i < 4; i++) { HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Line); Lines[i] = Line; } m_Client->HandleUpdateSign(Position, Lines[0], Lines[1], Lines[2], Lines[3]); } void cProtocol_1_9_0::HandlePacketUseEntity(cByteBuffer & a_ByteBuffer) { HANDLE_READ(a_ByteBuffer, ReadVarInt, UInt32, EntityID); HANDLE_READ(a_ByteBuffer, ReadVarInt, UInt32, Type); switch (Type) { case 0: { HANDLE_READ(a_ByteBuffer, ReadVarInt, UInt32, Hand); if (Hand == MAIN_HAND) // TODO: implement handling of off-hand actions; ignore them for now to avoid processing actions twice { m_Client->HandleUseEntity(EntityID, false); } break; } case 1: { m_Client->HandleUseEntity(EntityID, true); break; } case 2: { HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, TargetX); HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, TargetY); HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, TargetZ); HANDLE_READ(a_ByteBuffer, ReadVarInt, UInt32, Hand); // TODO: Do anything break; } default: { ASSERT(!"Unhandled use entity type!"); return; } } } void cProtocol_1_9_0::HandlePacketUseItem(cByteBuffer & a_ByteBuffer) { HANDLE_READ(a_ByteBuffer, ReadVarInt, Int32, Hand); m_Client->HandleUseItem(Hand == MAIN_HAND); } void cProtocol_1_9_0::HandlePacketVehicleMove(cByteBuffer & a_ByteBuffer) { // This handles updating the vehicles location server side HANDLE_READ(a_ByteBuffer, ReadBEDouble, double, xPos); HANDLE_READ(a_ByteBuffer, ReadBEDouble, double, yPos); HANDLE_READ(a_ByteBuffer, ReadBEDouble, double, zPos); HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, yaw); HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, pitch); // Get the players vehicle cEntity * Vehicle = m_Client->GetPlayer()->GetAttached(); if (Vehicle) { Vehicle->SetPosX(xPos); Vehicle->SetPosY(yPos); Vehicle->SetPosZ(zPos); Vehicle->SetYaw(yaw); Vehicle->SetPitch(pitch); } } void cProtocol_1_9_0::HandlePacketWindowClick(cByteBuffer & a_ByteBuffer) { HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, WindowID); HANDLE_READ(a_ByteBuffer, ReadBEInt16, Int16, SlotNum); HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, Button); HANDLE_READ(a_ByteBuffer, ReadBEUInt16, UInt16, TransactionID); HANDLE_READ(a_ByteBuffer, ReadVarInt32, UInt32, Mode); cItem Item; ReadItem(a_ByteBuffer, Item); /** The slot number that the client uses to indicate "outside the window". */ static const Int16 SLOT_NUM_OUTSIDE = -999; // Convert Button, Mode, SlotNum and HeldItem into eClickAction: eClickAction Action; switch ((Mode << 8) | Button) { case 0x0000: Action = (SlotNum != SLOT_NUM_OUTSIDE) ? caLeftClick : caLeftClickOutside; break; case 0x0001: Action = (SlotNum != SLOT_NUM_OUTSIDE) ? caRightClick : caRightClickOutside; break; case 0x0100: Action = caShiftLeftClick; break; case 0x0101: Action = caShiftRightClick; break; case 0x0200: Action = caNumber1; break; case 0x0201: Action = caNumber2; break; case 0x0202: Action = caNumber3; break; case 0x0203: Action = caNumber4; break; case 0x0204: Action = caNumber5; break; case 0x0205: Action = caNumber6; break; case 0x0206: Action = caNumber7; break; case 0x0207: Action = caNumber8; break; case 0x0208: Action = caNumber9; break; case 0x0302: Action = caMiddleClick; break; case 0x0400: Action = (SlotNum == SLOT_NUM_OUTSIDE) ? caLeftClickOutsideHoldNothing : caDropKey; break; case 0x0401: Action = (SlotNum == SLOT_NUM_OUTSIDE) ? caRightClickOutsideHoldNothing : caCtrlDropKey; break; case 0x0500: Action = (SlotNum == SLOT_NUM_OUTSIDE) ? caLeftPaintBegin : caUnknown; break; case 0x0501: Action = (SlotNum != SLOT_NUM_OUTSIDE) ? caLeftPaintProgress : caUnknown; break; case 0x0502: Action = (SlotNum == SLOT_NUM_OUTSIDE) ? caLeftPaintEnd : caUnknown; break; case 0x0504: Action = (SlotNum == SLOT_NUM_OUTSIDE) ? caRightPaintBegin : caUnknown; break; case 0x0505: Action = (SlotNum != SLOT_NUM_OUTSIDE) ? caRightPaintProgress : caUnknown; break; case 0x0506: Action = (SlotNum == SLOT_NUM_OUTSIDE) ? caRightPaintEnd : caUnknown; break; case 0x0508: Action = (SlotNum == SLOT_NUM_OUTSIDE) ? caMiddlePaintBegin : caUnknown; break; case 0x0509: Action = (SlotNum != SLOT_NUM_OUTSIDE) ? caMiddlePaintProgress : caUnknown; break; case 0x050a: Action = (SlotNum == SLOT_NUM_OUTSIDE) ? caMiddlePaintEnd : caUnknown; break; case 0x0600: Action = caDblClick; break; default: { LOGWARNING("Unhandled window click mode / button combination: %d (0x%x)", (Mode << 8) | Button, (Mode << 8) | Button); Action = caUnknown; break; } } m_Client->HandleWindowClick(WindowID, SlotNum, Action, Item); } void cProtocol_1_9_0::HandleVanillaPluginMessage(cByteBuffer & a_ByteBuffer, std::string_view a_Channel) { if (a_Channel == "AutoCmd") { HANDLE_READ(a_ByteBuffer, ReadBEInt32, Int32, BlockX); HANDLE_READ(a_ByteBuffer, ReadBEInt32, Int32, BlockY); HANDLE_READ(a_ByteBuffer, ReadBEInt32, Int32, BlockZ); HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Command); HANDLE_READ(a_ByteBuffer, ReadBool, bool, TrackOutput); HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Mode); HANDLE_READ(a_ByteBuffer, ReadBool, bool, Conditional); HANDLE_READ(a_ByteBuffer, ReadBool, bool, Automatic); m_Client->HandleCommandBlockBlockChange({BlockX, BlockY, BlockZ}, Command); } else if (a_Channel == "PickItem") { HANDLE_READ(a_ByteBuffer, ReadVarInt32, UInt32, InventorySlotIndex); } else if (a_Channel == "Struct") { HANDLE_READ(a_ByteBuffer, ReadBEInt32, Int32, BlockX); HANDLE_READ(a_ByteBuffer, ReadBEInt32, Int32, BlockY); HANDLE_READ(a_ByteBuffer, ReadBEInt32, Int32, BlockZ); HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, Action); HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Mode); HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Name); HANDLE_READ(a_ByteBuffer, ReadBEInt32, Int32, OffsetX); HANDLE_READ(a_ByteBuffer, ReadBEInt32, Int32, OffsetY); HANDLE_READ(a_ByteBuffer, ReadBEInt32, Int32, OffsetZ); HANDLE_READ(a_ByteBuffer, ReadBEUInt32, UInt32, SizeX); HANDLE_READ(a_ByteBuffer, ReadBEUInt32, UInt32, SizeY); HANDLE_READ(a_ByteBuffer, ReadBEUInt32, UInt32, SizeZ); HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Mirror); HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Rotation); HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Metadata); HANDLE_READ(a_ByteBuffer, ReadBool, bool, IgnoreEntities); HANDLE_READ(a_ByteBuffer, ReadBool, bool, ShowAir); HANDLE_READ(a_ByteBuffer, ReadBool, bool, ShowBoundingBox); HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, Integrity); HANDLE_READ(a_ByteBuffer, ReadVarInt64, UInt64, Seed); } else { Super::HandleVanillaPluginMessage(a_ByteBuffer, a_Channel); } } void cProtocol_1_9_0::ParseItemMetadata(cItem & a_Item, const ContiguousByteBufferView a_Metadata) const { // Parse into NBT: cParsedNBT NBT(a_Metadata); if (!NBT.IsValid()) { AString HexDump; CreateHexDump(HexDump, a_Metadata.data(), std::max(a_Metadata.size(), 1024), 16); LOGWARNING("Cannot parse NBT item metadata: %s at (%zu / %zu bytes)\n%s", NBT.GetErrorCode().message().c_str(), NBT.GetErrorPos(), a_Metadata.size(), HexDump.c_str() ); return; } // Load enchantments and custom display names from the NBT data: for (int tag = NBT.GetFirstChild(NBT.GetRoot()); tag >= 0; tag = NBT.GetNextSibling(tag)) { AString TagName = NBT.GetName(tag); switch (NBT.GetType(tag)) { case TAG_List: { if ((TagName == "ench") || (TagName == "StoredEnchantments")) // Enchantments tags { EnchantmentSerializer::ParseFromNBT(a_Item.m_Enchantments, NBT, tag); } break; } case TAG_Compound: { if (TagName == "display") // Custom name and lore tag { for (int displaytag = NBT.GetFirstChild(tag); displaytag >= 0; displaytag = NBT.GetNextSibling(displaytag)) { if ((NBT.GetType(displaytag) == TAG_String) && (NBT.GetName(displaytag) == "Name")) // Custon name tag { a_Item.m_CustomName = NBT.GetString(displaytag); } else if ((NBT.GetType(displaytag) == TAG_List) && (NBT.GetName(displaytag) == "Lore")) // Lore tag { a_Item.m_LoreTable.clear(); for (int loretag = NBT.GetFirstChild(displaytag); loretag >= 0; loretag = NBT.GetNextSibling(loretag)) // Loop through array of strings { a_Item.m_LoreTable.push_back(NBT.GetString(loretag)); } } else if ((NBT.GetType(displaytag) == TAG_Int) && (NBT.GetName(displaytag) == "color")) { a_Item.m_ItemColor.m_Color = static_cast(NBT.GetInt(displaytag)); } } } else if ((TagName == "Fireworks") || (TagName == "Explosion")) { cFireworkItem::ParseFromNBT(a_Item.m_FireworkItem, NBT, tag, static_cast(a_Item.m_ItemType)); } else if (TagName == "EntityTag") { for (int entitytag = NBT.GetFirstChild(tag); entitytag >= 0; entitytag = NBT.GetNextSibling(entitytag)) { if ((NBT.GetType(entitytag) == TAG_String) && (NBT.GetName(entitytag) == "id")) { AString NBTName = NBT.GetString(entitytag); ReplaceString(NBTName, "minecraft:", ""); eMonsterType MonsterType = cMonster::StringToMobType(NBTName); a_Item.m_ItemDamage = static_cast(GetProtocolMobType(MonsterType)); } } } break; } case TAG_Int: { if (TagName == "RepairCost") { a_Item.m_RepairCost = NBT.GetInt(tag); } break; } case TAG_String: { if (TagName == "Potion") { AString PotionEffect = NBT.GetString(tag); if (PotionEffect.find("minecraft:") == AString::npos) { LOGD("Unknown or missing domain on potion effect name %s!", PotionEffect.c_str()); continue; } if (PotionEffect.find("empty") != AString::npos) { a_Item.m_ItemDamage = 0; } else if (PotionEffect.find("mundane") != AString::npos) { a_Item.m_ItemDamage = 64; } else if (PotionEffect.find("thick") != AString::npos) { a_Item.m_ItemDamage = 32; } else if (PotionEffect.find("awkward") != AString::npos) { a_Item.m_ItemDamage = 16; } else if (PotionEffect.find("regeneration") != AString::npos) { a_Item.m_ItemDamage = 1; } else if (PotionEffect.find("swiftness") != AString::npos) { a_Item.m_ItemDamage = 2; } else if (PotionEffect.find("fire_resistance") != AString::npos) { a_Item.m_ItemDamage = 3; } else if (PotionEffect.find("poison") != AString::npos) { a_Item.m_ItemDamage = 4; } else if (PotionEffect.find("healing") != AString::npos) { a_Item.m_ItemDamage = 5; } else if (PotionEffect.find("night_vision") != AString::npos) { a_Item.m_ItemDamage = 6; } else if (PotionEffect.find("weakness") != AString::npos) { a_Item.m_ItemDamage = 8; } else if (PotionEffect.find("strength") != AString::npos) { a_Item.m_ItemDamage = 9; } else if (PotionEffect.find("slowness") != AString::npos) { a_Item.m_ItemDamage = 10; } else if (PotionEffect.find("leaping") != AString::npos) { a_Item.m_ItemDamage = 11; } else if (PotionEffect.find("harming") != AString::npos) { a_Item.m_ItemDamage = 12; } else if (PotionEffect.find("water_breathing") != AString::npos) { a_Item.m_ItemDamage = 13; } else if (PotionEffect.find("invisibility") != AString::npos) { a_Item.m_ItemDamage = 14; } else if (PotionEffect.find("water") != AString::npos) { a_Item.m_ItemDamage = 0; // Water bottles shouldn't have other bits set on them; exit early. continue; } else { // Note: luck potions are not handled and will reach this location LOGD("Unknown potion type for effect name %s!", PotionEffect.c_str()); continue; } if (PotionEffect.find("strong") != AString::npos) { a_Item.m_ItemDamage |= 0x20; } if (PotionEffect.find("long") != AString::npos) { a_Item.m_ItemDamage |= 0x40; } // Ugly special case with the changed splash potion ID in 1.9 if ((a_Item.m_ItemType == 438) || (a_Item.m_ItemType == 441)) { // Splash or lingering potions - change the ID to the normal one and mark as splash potions a_Item.m_ItemType = E_ITEM_POTION; a_Item.m_ItemDamage |= 0x4000; // Is splash potion } else { a_Item.m_ItemDamage |= 0x2000; // Is drinkable } } break; } default: LOGD("Unimplemented NBT data when parsing!"); break; } } } void cProtocol_1_9_0::SendEntitySpawn(const cEntity & a_Entity, const UInt8 a_ObjectType, const Int32 a_ObjectData) { ASSERT(m_State == 3); // In game mode? cPacketizer Pkt(*this, pktSpawnObject); Pkt.WriteVarInt32(a_Entity.GetUniqueID()); // TODO: Bad way to write a UUID, and it's not a true UUID, but this is functional for now. Pkt.WriteBEUInt64(0); Pkt.WriteBEUInt64(a_Entity.GetUniqueID()); Pkt.WriteBEUInt8(a_ObjectType); Pkt.WriteBEDouble(a_Entity.GetPosX()); Pkt.WriteBEDouble(a_Entity.GetPosY()); Pkt.WriteBEDouble(a_Entity.GetPosZ()); Pkt.WriteByteAngle(a_Entity.GetPitch()); Pkt.WriteByteAngle(a_Entity.GetYaw()); Pkt.WriteBEInt32(a_ObjectData); Pkt.WriteBEInt16(static_cast(a_Entity.GetSpeedX() * 400)); Pkt.WriteBEInt16(static_cast(a_Entity.GetSpeedY() * 400)); Pkt.WriteBEInt16(static_cast(a_Entity.GetSpeedZ() * 400)); } void cProtocol_1_9_0::WriteBlockEntity(cFastNBTWriter & a_Writer, const cBlockEntity & a_BlockEntity) const { if (a_BlockEntity.GetBlockType() == E_BLOCK_MOB_SPAWNER) { auto & MobSpawnerEntity = static_cast(a_BlockEntity); a_Writer.AddInt("x", a_BlockEntity.GetPosX()); a_Writer.AddInt("y", a_BlockEntity.GetPosY()); a_Writer.AddInt("z", a_BlockEntity.GetPosZ()); a_Writer.BeginCompound("SpawnData"); // New: SpawnData compound a_Writer.AddString("id", cMonster::MobTypeToVanillaName(MobSpawnerEntity.GetEntity())); a_Writer.EndCompound(); a_Writer.AddShort("Delay", MobSpawnerEntity.GetSpawnDelay()); } else { Super::WriteBlockEntity(a_Writer, a_BlockEntity); } } void cProtocol_1_9_0::WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_Entity) const { // Common metadata: Int8 Flags = 0; if (a_Entity.IsOnFire()) { Flags |= 0x01; } if (a_Entity.IsCrouched()) { Flags |= 0x02; } if (a_Entity.IsSprinting()) { Flags |= 0x08; } if (a_Entity.IsRclking()) { Flags |= 0x10; } if (a_Entity.IsInvisible()) { Flags |= 0x20; } if (a_Entity.IsElytraFlying()) { Flags |= 0x80; } a_Pkt.WriteBEUInt8(0); // Index 0 a_Pkt.WriteBEUInt8(METADATA_TYPE_BYTE); // Type a_Pkt.WriteBEInt8(Flags); switch (a_Entity.GetEntityType()) { case cEntity::etPlayer: { auto & Player = static_cast(a_Entity); // TODO Set player custom name to their name. // Then it's possible to move the custom name of mobs to the entities // and to remove the "special" player custom name. a_Pkt.WriteBEUInt8(2); // Index 2: Custom name a_Pkt.WriteBEUInt8(METADATA_TYPE_STRING); a_Pkt.WriteString(Player.GetName()); a_Pkt.WriteBEUInt8(6); // Index 6: Health a_Pkt.WriteBEUInt8(METADATA_TYPE_FLOAT); a_Pkt.WriteBEFloat(static_cast(Player.GetHealth())); a_Pkt.WriteBEUInt8(12); a_Pkt.WriteBEUInt8(METADATA_TYPE_BYTE); a_Pkt.WriteBEUInt8(static_cast(Player.GetSkinParts())); a_Pkt.WriteBEUInt8(13); a_Pkt.WriteBEUInt8(METADATA_TYPE_BYTE); a_Pkt.WriteBEUInt8(Player.IsLeftHanded() ? 0 : 1); break; } case cEntity::etPickup: { a_Pkt.WriteBEUInt8(5); // Index 5: Item a_Pkt.WriteBEUInt8(METADATA_TYPE_ITEM); WriteItem(a_Pkt, static_cast(a_Entity).GetItem()); break; } case cEntity::etMinecart: { a_Pkt.WriteBEUInt8(5); // Index 5: Shaking power a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); // The following expression makes Minecarts shake more with less health or higher damage taken auto & Minecart = static_cast(a_Entity); auto maxHealth = a_Entity.GetMaxHealth(); auto curHealth = a_Entity.GetHealth(); a_Pkt.WriteVarInt32(static_cast((maxHealth - curHealth) * Minecart.LastDamage() * 4)); a_Pkt.WriteBEUInt8(6); // Index 6: Shaking direction (doesn't seem to effect anything) a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(1); a_Pkt.WriteBEUInt8(7); // Index 7: Shake multiplier / damage taken a_Pkt.WriteBEUInt8(METADATA_TYPE_FLOAT); a_Pkt.WriteBEFloat(static_cast(Minecart.LastDamage() + 10)); if (Minecart.GetPayload() == cMinecart::mpNone) { auto & RideableMinecart = static_cast(Minecart); const cItem & MinecartContent = RideableMinecart.GetContent(); if (!MinecartContent.IsEmpty()) { a_Pkt.WriteBEUInt8(8); // Index 8: Block ID and damage a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); int Content = MinecartContent.m_ItemType; Content |= MinecartContent.m_ItemDamage << 8; a_Pkt.WriteVarInt32(static_cast(Content)); a_Pkt.WriteBEUInt8(9); // Index 9: Block ID and damage a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(static_cast(RideableMinecart.GetBlockHeight())); a_Pkt.WriteBEUInt8(10); // Index 10: Show block a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(true); } } else if (Minecart.GetPayload() == cMinecart::mpFurnace) { a_Pkt.WriteBEUInt8(11); // Index 11: Is powered a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(static_cast(Minecart).IsFueled()); } break; } // case etMinecart case cEntity::etProjectile: { auto & Projectile = static_cast(a_Entity); switch (Projectile.GetProjectileKind()) { case cProjectileEntity::pkArrow: { a_Pkt.WriteBEUInt8(5); // Index 5: Is critical a_Pkt.WriteBEUInt8(METADATA_TYPE_BYTE); a_Pkt.WriteBEInt8(static_cast(Projectile).IsCritical() ? 1 : 0); break; } case cProjectileEntity::pkFirework: { a_Pkt.WriteBEUInt8(5); // Index 5: Firework item used for this firework a_Pkt.WriteBEUInt8(METADATA_TYPE_ITEM); WriteItem(a_Pkt, static_cast(Projectile).GetItem()); break; } case cProjectileEntity::pkSplashPotion: { a_Pkt.WriteBEUInt8(5); // Index 5: Potion item which was thrown a_Pkt.WriteBEUInt8(METADATA_TYPE_ITEM); WriteItem(a_Pkt, static_cast(Projectile).GetItem()); } default: { break; } } break; } // case etProjectile case cEntity::etMonster: { WriteMobMetadata(a_Pkt, static_cast(a_Entity)); break; } case cEntity::etBoat: { auto & Boat = static_cast(a_Entity); a_Pkt.WriteBEInt8(5); // Index 6: Time since last hit a_Pkt.WriteBEInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(static_cast(Boat.GetLastDamage())); a_Pkt.WriteBEInt8(6); // Index 7: Forward direction a_Pkt.WriteBEInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(static_cast(Boat.GetForwardDirection())); a_Pkt.WriteBEInt8(7); // Index 8: Damage taken a_Pkt.WriteBEInt8(METADATA_TYPE_FLOAT); a_Pkt.WriteBEFloat(Boat.GetDamageTaken()); a_Pkt.WriteBEInt8(8); // Index 9: Type a_Pkt.WriteBEInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(static_cast(Boat.GetMaterial())); a_Pkt.WriteBEInt8(9); // Index 10: Right paddle turning a_Pkt.WriteBEInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Boat.IsRightPaddleUsed()); a_Pkt.WriteBEInt8(10); // Index 11: Left paddle turning a_Pkt.WriteBEInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Boat.IsLeftPaddleUsed()); break; } // case etBoat case cEntity::etItemFrame: { auto & Frame = static_cast(a_Entity); a_Pkt.WriteBEUInt8(5); // Index 5: Item a_Pkt.WriteBEUInt8(METADATA_TYPE_ITEM); WriteItem(a_Pkt, Frame.GetItem()); a_Pkt.WriteBEUInt8(6); // Index 6: Rotation a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(Frame.GetItemRotation()); break; } // case etItemFrame case cEntity::etEnderCrystal: { const auto & EnderCrystal = static_cast(a_Entity); a_Pkt.WriteBEUInt8(5); a_Pkt.WriteBEUInt8(METADATA_TYPE_OPTIONAL_POSITION); a_Pkt.WriteBool(EnderCrystal.DisplaysBeam()); if (EnderCrystal.DisplaysBeam()) { a_Pkt.WriteXYZPosition64(EnderCrystal.GetBeamTarget()); } a_Pkt.WriteBEUInt8(6); a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(EnderCrystal.ShowsBottom()); break; } // case etEnderCrystal default: { break; } } } void cProtocol_1_9_0::WriteItem(cPacketizer & a_Pkt, const cItem & a_Item) const { short ItemType = a_Item.m_ItemType; ASSERT(ItemType >= -1); // Check validity of packets in debug runtime if (ItemType <= 0) { // Fix, to make sure no invalid values are sent. ItemType = -1; } if (a_Item.IsEmpty()) { a_Pkt.WriteBEInt16(-1); return; } if ((ItemType == E_ITEM_POTION) && ((a_Item.m_ItemDamage & 0x4000) != 0)) { // Ugly special case for splash potion ids which changed in 1.9; this can be removed when the new 1.9 ids are implemented a_Pkt.WriteBEInt16(438); // minecraft:splash_potion } else { // Normal item a_Pkt.WriteBEInt16(ItemType); } a_Pkt.WriteBEInt8(a_Item.m_ItemCount); if ((ItemType == E_ITEM_POTION) || (ItemType == E_ITEM_SPAWN_EGG)) { // These items lost their metadata; if it is sent they don't render correctly. a_Pkt.WriteBEInt16(0); } else { a_Pkt.WriteBEInt16(a_Item.m_ItemDamage); } if (a_Item.m_Enchantments.IsEmpty() && a_Item.IsBothNameAndLoreEmpty() && (ItemType != E_ITEM_FIREWORK_ROCKET) && (ItemType != E_ITEM_FIREWORK_STAR) && !a_Item.m_ItemColor.IsValid() && (ItemType != E_ITEM_POTION) && (ItemType != E_ITEM_SPAWN_EGG)) { a_Pkt.WriteBEInt8(0); return; } // Send the enchantments and custom names: cFastNBTWriter Writer; if (a_Item.m_RepairCost != 0) { Writer.AddInt("RepairCost", a_Item.m_RepairCost); } if (!a_Item.m_Enchantments.IsEmpty()) { const char * TagName = (a_Item.m_ItemType == E_ITEM_BOOK) ? "StoredEnchantments" : "ench"; EnchantmentSerializer::WriteToNBTCompound(a_Item.m_Enchantments, Writer, TagName); } if (!a_Item.IsBothNameAndLoreEmpty() || a_Item.m_ItemColor.IsValid()) { Writer.BeginCompound("display"); if (a_Item.m_ItemColor.IsValid()) { Writer.AddInt("color", static_cast(a_Item.m_ItemColor.m_Color)); } if (!a_Item.IsCustomNameEmpty()) { Writer.AddString("Name", a_Item.m_CustomName); } if (!a_Item.IsLoreEmpty()) { Writer.BeginList("Lore", TAG_String); for (const auto & Line : a_Item.m_LoreTable) { Writer.AddString("", Line); } Writer.EndList(); } Writer.EndCompound(); } if ((a_Item.m_ItemType == E_ITEM_FIREWORK_ROCKET) || (a_Item.m_ItemType == E_ITEM_FIREWORK_STAR)) { cFireworkItem::WriteToNBTCompound(a_Item.m_FireworkItem, Writer, static_cast(a_Item.m_ItemType)); } if (a_Item.m_ItemType == E_ITEM_POTION) { // 1.9 potions use a different format. In the future (when only 1.9+ is supported) this should be its own class AString PotionID = "empty"; // Fallback of "Uncraftable potion" for unhandled cases cEntityEffect::eType Type = cEntityEffect::GetPotionEffectType(a_Item.m_ItemDamage); if (Type != cEntityEffect::effNoEffect) { switch (Type) { case cEntityEffect::effRegeneration: PotionID = "regeneration"; break; case cEntityEffect::effSpeed: PotionID = "swiftness"; break; case cEntityEffect::effFireResistance: PotionID = "fire_resistance"; break; case cEntityEffect::effPoison: PotionID = "poison"; break; case cEntityEffect::effInstantHealth: PotionID = "healing"; break; case cEntityEffect::effNightVision: PotionID = "night_vision"; break; case cEntityEffect::effWeakness: PotionID = "weakness"; break; case cEntityEffect::effStrength: PotionID = "strength"; break; case cEntityEffect::effSlowness: PotionID = "slowness"; break; case cEntityEffect::effJumpBoost: PotionID = "leaping"; break; case cEntityEffect::effInstantDamage: PotionID = "harming"; break; case cEntityEffect::effWaterBreathing: PotionID = "water_breathing"; break; case cEntityEffect::effInvisibility: PotionID = "invisibility"; break; default: ASSERT(!"Unknown potion effect"); break; } if (cEntityEffect::GetPotionEffectIntensity(a_Item.m_ItemDamage) == 1) { PotionID = "strong_" + PotionID; } else if (a_Item.m_ItemDamage & 0x40) { // Extended potion bit PotionID = "long_" + PotionID; } } else { // Empty potions: Water bottles and other base ones if (a_Item.m_ItemDamage == 0) { // No other bits set; thus it's a water bottle PotionID = "water"; } else { switch (a_Item.m_ItemDamage & 0x3f) { case 0x00: PotionID = "mundane"; break; case 0x10: PotionID = "awkward"; break; case 0x20: PotionID = "thick"; break; } // Default cases will use "empty" from before. } } PotionID = "minecraft:" + PotionID; Writer.AddString("Potion", PotionID); } if (a_Item.m_ItemType == E_ITEM_SPAWN_EGG) { // Convert entity ID to the name. eMonsterType MonsterType = cItemSpawnEggHandler::ItemDamageToMonsterType(a_Item.m_ItemDamage); if (MonsterType != eMonsterType::mtInvalidType) { Writer.BeginCompound("EntityTag"); Writer.AddString("id", "minecraft:" + cMonster::MobTypeToVanillaNBT(MonsterType)); Writer.EndCompound(); } } Writer.Finish(); const auto Result = Writer.GetResult(); if (Result.empty()) { a_Pkt.WriteBEInt8(0); return; } a_Pkt.WriteBuf(Result); } void cProtocol_1_9_0::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mob) const { // Living entity metadata if (a_Mob.HasCustomName()) { // TODO: As of 1.9 _all_ entities can have custom names; should this be moved up? a_Pkt.WriteBEUInt8(2); // Index 2: Custom name a_Pkt.WriteBEUInt8(METADATA_TYPE_STRING); a_Pkt.WriteString(a_Mob.GetCustomName()); a_Pkt.WriteBEUInt8(3); // Index 3: Custom name always visible a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(a_Mob.IsCustomNameAlwaysVisible()); } a_Pkt.WriteBEUInt8(6); // Index 6: Health a_Pkt.WriteBEUInt8(METADATA_TYPE_FLOAT); a_Pkt.WriteBEFloat(static_cast(a_Mob.GetHealth())); switch (a_Mob.GetMobType()) { case mtBat: { auto & Bat = static_cast(a_Mob); a_Pkt.WriteBEUInt8(11); // Index 11: Bat flags - currently only hanging a_Pkt.WriteBEUInt8(METADATA_TYPE_BYTE); a_Pkt.WriteBEInt8(Bat.IsHanging() ? 1 : 0); break; } // case mtBat case mtChicken: { auto & Chicken = static_cast(a_Mob); a_Pkt.WriteBEUInt8(11); // Index 11: Is baby a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Chicken.IsBaby()); break; } // case mtChicken case mtCow: { auto & Cow = static_cast(a_Mob); a_Pkt.WriteBEUInt8(11); // Index 11: Is baby a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Cow.IsBaby()); break; } // case mtCow case mtCreeper: { auto & Creeper = static_cast(a_Mob); a_Pkt.WriteBEUInt8(11); // Index 11: State (idle or "blowing") a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(Creeper.IsBlowing() ? 1 : 0xffffffff); a_Pkt.WriteBEUInt8(12); // Index 12: Is charged a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Creeper.IsCharged()); a_Pkt.WriteBEUInt8(13); // Index 13: Is ignited a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Creeper.IsBurnedWithFlintAndSteel()); break; } // case mtCreeper case mtEnderman: { auto & Enderman = static_cast(a_Mob); a_Pkt.WriteBEUInt8(11); // Index 11: Carried block a_Pkt.WriteBEUInt8(METADATA_TYPE_BLOCKID); UInt32 Carried = 0; Carried |= static_cast(Enderman.GetCarriedBlock() << 4); Carried |= Enderman.GetCarriedMeta(); a_Pkt.WriteVarInt32(Carried); a_Pkt.WriteBEUInt8(12); // Index 12: Is screaming a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Enderman.IsScreaming()); break; } // case mtEnderman case mtGhast: { auto & Ghast = static_cast(a_Mob); a_Pkt.WriteBEUInt8(11); // Is attacking a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Ghast.IsCharging()); break; } // case mtGhast case mtHorse: { auto & Horse = static_cast(a_Mob); Int8 Flags = 0; if (Horse.IsTame()) { Flags |= 0x02; } if (Horse.IsSaddled()) { Flags |= 0x04; } if (Horse.IsChested()) { Flags |= 0x08; } if (Horse.IsEating()) { Flags |= 0x20; } if (Horse.IsRearing()) { Flags |= 0x40; } if (Horse.IsMthOpen()) { Flags |= 0x80; } a_Pkt.WriteBEUInt8(12); // Index 12: flags a_Pkt.WriteBEUInt8(METADATA_TYPE_BYTE); a_Pkt.WriteBEInt8(Flags); a_Pkt.WriteBEUInt8(13); // Index 13: Variant / type a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(static_cast(Horse.GetHorseType())); a_Pkt.WriteBEUInt8(14); // Index 14: Color / style a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); int Appearance = 0; Appearance = Horse.GetHorseColor(); Appearance |= Horse.GetHorseStyle() << 8; a_Pkt.WriteVarInt32(static_cast(Appearance)); a_Pkt.WriteBEUInt8(16); // Index 16: Armor a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(static_cast(Horse.GetHorseArmour())); a_Pkt.WriteBEUInt8(11); // Index 11: Is baby a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Horse.IsBaby()); break; } // case mtHorse case mtMagmaCube: { auto & MagmaCube = static_cast(a_Mob); a_Pkt.WriteBEUInt8(11); // Index 11: Size a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(static_cast(MagmaCube.GetSize())); break; } // case mtMagmaCube case mtOcelot: { auto & Ocelot = static_cast(a_Mob); a_Pkt.WriteBEUInt8(11); // Index 11: Is baby a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Ocelot.IsBaby()); break; } // case mtOcelot case mtPig: { auto & Pig = static_cast(a_Mob); a_Pkt.WriteBEUInt8(11); // Index 11: Is baby a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Pig.IsBaby()); a_Pkt.WriteBEUInt8(12); // Index 12: Is saddled a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Pig.IsSaddled()); break; } // case mtPig case mtRabbit: { auto & Rabbit = static_cast(a_Mob); a_Pkt.WriteBEUInt8(11); // Index 11: Is baby a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Rabbit.IsBaby()); a_Pkt.WriteBEUInt8(12); // Index 12: Type a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(static_cast(Rabbit.GetRabbitType())); break; } // case mtRabbit case mtSheep: { auto & Sheep = static_cast(a_Mob); a_Pkt.WriteBEUInt8(11); // Index 11: Is baby a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Sheep.IsBaby()); a_Pkt.WriteBEUInt8(12); // Index 12: sheared, color a_Pkt.WriteBEUInt8(METADATA_TYPE_BYTE); Int8 SheepMetadata = 0; SheepMetadata = static_cast(Sheep.GetFurColor()); if (Sheep.IsSheared()) { SheepMetadata |= 0x10; } a_Pkt.WriteBEInt8(SheepMetadata); break; } // case mtSheep case mtSkeleton: { auto & Skeleton = static_cast(a_Mob); a_Pkt.WriteBEUInt8(11); a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(0); // Index 5 and 12 used for charging bow client animation. a_Pkt.WriteBEUInt8(5); a_Pkt.WriteBEUInt8(METADATA_TYPE_BYTE); a_Pkt.WriteBEInt8(0x02 | (Skeleton.IsChargingBow() ? 0x01 : 0x00)); a_Pkt.WriteBEUInt8(12); a_Pkt.WriteBEUInt8(METADATA_TYPE_BYTE); a_Pkt.WriteBool(Skeleton.IsChargingBow()); break; } case mtSlime: { auto & Slime = static_cast(a_Mob); a_Pkt.WriteBEUInt8(11); // Index 11: Size a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(static_cast(Slime.GetSize())); break; } // case mtSlime case mtVillager: { auto & Villager = static_cast(a_Mob); a_Pkt.WriteBEUInt8(11); // Index 11: Is baby a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Villager.IsBaby()); a_Pkt.WriteBEUInt8(12); // Index 12: Type a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(static_cast(Villager.GetVilType())); break; } // case mtVillager case mtWitch: { auto & Witch = static_cast(a_Mob); a_Pkt.WriteBEUInt8(11); // Index 11: Is angry a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Witch.IsAngry()); break; } // case mtWitch case mtWither: { auto & Wither = static_cast(a_Mob); a_Pkt.WriteBEUInt8(14); // Index 14: Invulnerable ticks a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(Wither.GetWitherInvulnerableTicks()); // TODO: Use boss bar packet for health break; } // case mtWither case mtWitherSkeleton: { a_Pkt.WriteBEUInt8(11); // Index 11: Type a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(1); // Is wither skeleton break; } // case mtWitherSkeleton case mtWolf: { auto & Wolf = static_cast(a_Mob); a_Pkt.WriteBEUInt8(11); // Index 11: Is baby a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Wolf.IsBaby()); Int8 WolfStatus = 0; if (Wolf.IsSitting()) { WolfStatus |= 0x1; } if (Wolf.IsAngry()) { WolfStatus |= 0x2; } if (Wolf.IsTame()) { WolfStatus |= 0x4; } a_Pkt.WriteBEUInt8(12); // Index 12: status a_Pkt.WriteBEUInt8(METADATA_TYPE_BYTE); a_Pkt.WriteBEInt8(WolfStatus); a_Pkt.WriteBEUInt8(14); // Index 14: Health a_Pkt.WriteBEUInt8(METADATA_TYPE_FLOAT); a_Pkt.WriteBEFloat(static_cast(a_Mob.GetHealth())); a_Pkt.WriteBEUInt8(15); // Index 15: Is begging a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Wolf.IsBegging()); a_Pkt.WriteBEUInt8(16); // Index 16: Collar color a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(static_cast(Wolf.GetCollarColor())); break; } // case mtWolf case mtZombie: { auto & Zombie = static_cast(a_Mob); a_Pkt.WriteBEUInt8(11); // Index 11: Is baby a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Zombie.IsBaby()); a_Pkt.WriteBEUInt8(12); // Index 12: Is a villager a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(0); a_Pkt.WriteBEUInt8(13); // Index 13: Is converting a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(false); break; } // case mtZombie case mtZombiePigman: { auto & ZombiePigman = static_cast(a_Mob); a_Pkt.WriteBEUInt8(11); // Index 11: Is baby a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(ZombiePigman.IsBaby()); break; } // case mtZombiePigman case mtZombieVillager: { auto & ZombieVillager = reinterpret_cast(a_Mob); a_Pkt.WriteBEUInt8(11); // Index 11: Is baby a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(ZombieVillager.IsBaby()); a_Pkt.WriteBEUInt8(12); // Index 12: Is a villager a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(ZombieVillager.GetProfession()); a_Pkt.WriteBEUInt8(13); // Index 13: Is converting a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(ZombieVillager.ConversionTime() != -1); break; } // case mtZombieVillager case mtBlaze: case mtElderGuardian: case mtGuardian: { // TODO: Mobs with extra fields that aren't implemented break; } case mtCat: case mtDonkey: case mtMule: case mtStray: case mtSkeletonHorse: case mtZombieHorse: case mtShulker: { // Todo: Mobs not added yet. Grouped ones have the same metadata ASSERT(!"cProtocol_1_9::WriteMobMetadata: received unimplemented type"); break; } case mtCaveSpider: case mtEnderDragon: case mtEndermite: case mtGiant: case mtIronGolem: case mtMooshroom: case mtSilverfish: case mtSnowGolem: case mtSpider: case mtSquid: { // Entities without additional metadata break; } default: UNREACHABLE("cProtocol_1_9::WriteMobMetadata: received mob of invalid type"); } // switch (a_Mob.GetType()) } //////////////////////////////////////////////////////////////////////////////// // cProtocol_1_9_1: void cProtocol_1_9_1::SendLogin(const cPlayer & a_Player, const cWorld & a_World) { // Send the Join Game packet: { cServer * Server = cRoot::Get()->GetServer(); cPacketizer Pkt(*this, pktJoinGame); Pkt.WriteBEUInt32(a_Player.GetUniqueID()); Pkt.WriteBEUInt8(static_cast(a_Player.GetEffectiveGameMode()) | (Server->IsHardcore() ? 0x08 : 0)); // Hardcore flag bit 4 Pkt.WriteBEInt32(static_cast(a_World.GetDimension())); // This is the change from 1.9.0 (Int8 to Int32) Pkt.WriteBEUInt8(2); // TODO: Difficulty (set to Normal) Pkt.WriteBEUInt8(static_cast(Clamp(Server->GetMaxPlayers(), 0, 255))); Pkt.WriteString("default"); // Level type - wtf? Pkt.WriteBool(false); // Reduced Debug Info - wtf? } // Send the spawn position: { cPacketizer Pkt(*this, pktSpawnPosition); Pkt.WriteXYZPosition64(a_World.GetSpawnX(), a_World.GetSpawnY(), a_World.GetSpawnZ()); } // Send the server difficulty: { cPacketizer Pkt(*this, pktDifficulty); Pkt.WriteBEInt8(1); } } cProtocol::Version cProtocol_1_9_1::GetProtocolVersion() const { return Version::v1_9_1; } //////////////////////////////////////////////////////////////////////////////// // cProtocol_1_9_2: cProtocol::Version cProtocol_1_9_2::GetProtocolVersion() const { return Version::v1_9_2; } //////////////////////////////////////////////////////////////////////////////// // cProtocol_1_9_4: void cProtocol_1_9_4::SendUpdateSign(Vector3i a_BlockPos, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4) { ASSERT(m_State == 3); // In game mode? // 1.9.4 removed the update sign packet and now uses Update Block Entity cPacketizer Pkt(*this, pktUpdateBlockEntity); Pkt.WriteXYZPosition64(a_BlockPos); Pkt.WriteBEUInt8(9); // Action 9 - update sign cFastNBTWriter Writer; Writer.AddInt("x", a_BlockPos.x); Writer.AddInt("y", a_BlockPos.y); Writer.AddInt("z", a_BlockPos.z); Writer.AddString("id", "Sign"); Json::Value Line1; Line1["text"] = a_Line1; Writer.AddString("Text1", JsonUtils::WriteFastString(Line1)); Json::Value Line2; Line2["text"] = a_Line2; Writer.AddString("Text2", JsonUtils::WriteFastString(Line2)); Json::Value Line3; Line3["text"] = a_Line3; Writer.AddString("Text3", JsonUtils::WriteFastString(Line3)); Json::Value Line4; Line4["text"] = a_Line4; Writer.AddString("Text4", JsonUtils::WriteFastString(Line4)); Writer.Finish(); Pkt.WriteBuf(Writer.GetResult()); } UInt32 cProtocol_1_9_4::GetPacketID(cProtocol::ePacketType a_Packet) const { switch (a_Packet) { case pktCollectEntity: return 0x48; case pktEntityEffect: return 0x4b; case pktEntityProperties: return 0x4a; case pktPlayerListHeaderFooter: return 0x47; case pktTeleportEntity: return 0x49; default: return Super::GetPacketID(a_Packet); } } cProtocol::Version cProtocol_1_9_4::GetProtocolVersion() const { return Version::v1_9_4; } ================================================ FILE: src/Protocol/Protocol_1_9.h ================================================ // Protocol_1_9.h /* Declares the 1.9 protocol classes: - cProtocol_1_9_0 - release 1.9 protocol (#107) - cProtocol_1_9_1 - release 1.9.1 protocol (#108) - cProtocol_1_9_2 - release 1.9.2 protocol (#109) - cProtocol_1_9_4 - release 1.9.4 protocol (#110) */ #pragma once #include "Protocol.h" #include "Protocol_1_8.h" class cProtocol_1_9_0: public cProtocol_1_8_0 { using Super = cProtocol_1_8_0; public: cProtocol_1_9_0(cClientHandle * a_Client, const AString & a_ServerAddress, State a_State); virtual void SendAttachEntity (const cEntity & a_Entity, const cEntity & a_Vehicle) override; virtual void SendBossBarAdd (UInt32 a_UniqueID, const cCompositeChat & a_Title, float a_FractionFilled, BossBarColor a_Color, BossBarDivisionType a_DivisionType, bool a_DarkenSky, bool a_PlayEndMusic, bool a_CreateFog) override; virtual void SendBossBarRemove (UInt32 a_UniqueID) override; virtual void SendBossBarUpdateFlags (UInt32 a_UniqueID, bool a_DarkenSky, bool a_PlayEndMusic, bool a_CreateFog) override; virtual void SendBossBarUpdateHealth (UInt32 a_UniqueID, float a_FractionFilled) override; virtual void SendBossBarUpdateStyle (UInt32 a_UniqueID, BossBarColor a_Color, BossBarDivisionType a_DivisionType) override; virtual void SendBossBarUpdateTitle (UInt32 a_UniqueID, const cCompositeChat & a_Title) override; virtual void SendDetachEntity (const cEntity & a_Entity, const cEntity & a_PreviousVehicle) override; virtual void SendEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item) override; virtual void SendEntityMetadata (const cEntity & a_Entity) override; virtual void SendEntityPosition (const cEntity & a_Entity) override; virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) override; virtual void SendKeepAlive (UInt32 a_PingID) override; virtual void SendLeashEntity (const cEntity & a_Entity, const cEntity & a_EntityLeashedTo) override; virtual void SendMapData (const cMap & a_Map, int a_DataStartX, int a_DataStartY) override; virtual void SendPaintingSpawn (const cPainting & a_Painting) override; virtual void SendPlayerMoveLook (Vector3d a_Pos, float a_Yaw, float a_Pitch, bool a_IsRelative) override; virtual void SendPlayerMoveLook (void) override; virtual void SendPlayerPermissionLevel() override; virtual void SendPlayerSpawn (const cPlayer & a_Player) override; virtual void SendSoundEffect (const AString & a_SoundName, Vector3d a_Origin, float a_Volume, float a_Pitch) override; virtual void SendSpawnMob (const cMonster & a_Mob) override; virtual void SendThunderbolt (Vector3i a_Origin) override; virtual void SendUnleashEntity (const cEntity & a_Entity) override; virtual void SendUnloadChunk (int a_ChunkX, int a_ChunkZ) override; protected: /** The current teleport ID. */ bool m_IsTeleportIdConfirmed; /** Whether the current teleport ID has been confirmed by the client. */ UInt32 m_OutstandingTeleportId; virtual UInt32 GetPacketID(ePacketType a_Packet) const override; virtual unsigned char GetProtocolEntityAnimation(EntityAnimation a_Animation) const override; virtual signed char GetProtocolEntityStatus(EntityAnimation a_Animation) const override; virtual UInt32 GetProtocolMobType(eMonsterType a_MobType) const override; virtual Version GetProtocolVersion() const override; virtual bool HandlePacket (cByteBuffer & a_ByteBuffer, UInt32 a_PacketType) override; virtual void HandlePacketAnimation (cByteBuffer & a_ByteBuffer) override; virtual void HandlePacketBlockDig (cByteBuffer & a_ByteBuffer) override; virtual void HandlePacketBlockPlace (cByteBuffer & a_ByteBuffer) override; virtual void HandlePacketBoatSteer (cByteBuffer & a_ByteBuffer); virtual void HandlePacketClientSettings (cByteBuffer & a_ByteBuffer) override; virtual void HandleConfirmTeleport (cByteBuffer & a_ByteBuffer); virtual void HandlePacketEntityAction (cByteBuffer & a_ByteBuffer) override; virtual void HandlePacketPlayerPos (cByteBuffer & a_ByteBuffer) override; virtual void HandlePacketPlayerPosLook (cByteBuffer & a_ByteBuffer) override; virtual void HandlePacketSteerVehicle (cByteBuffer & a_ByteBuffer) override; virtual void HandlePacketTabComplete (cByteBuffer & a_ByteBuffer) override; virtual void HandlePacketUpdateSign (cByteBuffer & a_ByteBuffer) override; virtual void HandlePacketUseEntity (cByteBuffer & a_ByteBuffer) override; virtual void HandlePacketUseItem (cByteBuffer & a_ByteBuffer); virtual void HandlePacketVehicleMove (cByteBuffer & a_ByteBuffer); virtual void HandlePacketWindowClick (cByteBuffer & a_ByteBuffer) override; virtual void HandleVanillaPluginMessage (cByteBuffer & a_ByteBuffer, std::string_view a_Channel) override; virtual void ParseItemMetadata(cItem & a_Item, ContiguousByteBufferView a_Metadata) const override; virtual void SendEntitySpawn(const cEntity & a_Entity, const UInt8 a_ObjectType, const Int32 a_ObjectData) override; virtual void WriteBlockEntity(cFastNBTWriter & a_Writer, const cBlockEntity & a_BlockEntity) const override; virtual void WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_Entity) const override; virtual void WriteItem(cPacketizer & a_Pkt, const cItem & a_Item) const override; virtual void WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mob) const override; /** Types used within metadata */ enum eMetadataType { METADATA_TYPE_BYTE = 0, METADATA_TYPE_VARINT = 1, METADATA_TYPE_FLOAT = 2, METADATA_TYPE_STRING = 3, METADATA_TYPE_CHAT = 4, METADATA_TYPE_ITEM = 5, METADATA_TYPE_BOOL = 6, METADATA_TYPE_ROTATION = 7, METADATA_TYPE_POSITION = 8, METADATA_TYPE_OPTIONAL_POSITION = 9, METADATA_TYPE_DIRECTION = 10, METADATA_TYPE_OPTIONAL_UUID = 11, METADATA_TYPE_BLOCKID = 12 } ; } ; /** The version 108 protocol, used by 1.9.1. Uses an int rather than a byte for dimension in join game. */ class cProtocol_1_9_1: public cProtocol_1_9_0 { using Super = cProtocol_1_9_0; public: using Super::Super; protected: virtual void SendLogin(const cPlayer & a_Player, const cWorld & a_World) override; virtual Version GetProtocolVersion() const override; } ; /** The version 109 protocol, used by 1.9.2. Same as 1.9.1, except the server list ping version number changed with the protocol number. */ class cProtocol_1_9_2: public cProtocol_1_9_1 { using Super = cProtocol_1_9_1; public: using Super::Super; protected: virtual Version GetProtocolVersion() const override; } ; /** The version 110 protocol, used by 1.9.3 and 1.9.4. */ class cProtocol_1_9_4: public cProtocol_1_9_2 { using Super = cProtocol_1_9_2; public: using Super::Super; protected: virtual void SendUpdateSign(Vector3i a_BlockPos, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4) override; virtual UInt32 GetPacketID(ePacketType a_Packet) const override; virtual Version GetProtocolVersion() const override; } ; ================================================ FILE: src/Protocol/RecipeMapper.cpp ================================================ #include "Globals.h" #include "RecipeMapper.h" #include "../Root.h" cRecipeMapper::cRecipeMapper(void) { AString path = "Protocol"; auto contents = cFile::GetFolderContents(path); for (const auto & content: contents) { auto fullName = path + cFile::PathSeparator() + content; if (cFile::IsFolder(fullName)) { loadRecipes(content); } } } void cRecipeMapper::loadRecipes(const AString & a_ProtocolVersion) { cFile f; if (!f.Open("Protocol/" + a_ProtocolVersion + "/base.recipes.txt", cFile::fmRead)) { LOGWARNING("Cannot open file \"Protocol/%s/base.recipes.txt\", no recipe book recipes will be available!", a_ProtocolVersion); return; } AString Everything; if (!f.ReadRestOfFile(Everything)) { LOGWARNING("Cannot read file \"Protocol/%s/base.recipes.txt\", no recipe book recipes will be available!", a_ProtocolVersion); return; } f.Close(); // Split it into lines, then process each line as a single recipe: AStringVector Split = StringSplit(Everything, "\n"); m_ProtocolVersionMap[a_ProtocolVersion] = {}; const auto & RecipeNameMap = cRoot::Get()->GetCraftingRecipes()->GetRecipeNameMap(); int LineNum = 1; for (AStringVector::const_iterator itr = Split.begin(); itr != Split.end(); ++itr, ++LineNum) { // Remove anything after a '#' sign and trim away the whitespace: AString Recipe = TrimString(itr->substr(0, itr->find('#'))); if (Recipe.empty()) { // Empty recipe continue; } AddRecipeLine(a_ProtocolVersion, LineNum, Recipe, RecipeNameMap); } LOG("Loaded %s %zu recipe book", a_ProtocolVersion, m_ProtocolVersionMap[a_ProtocolVersion].size()); } cRecipeMapper::~cRecipeMapper() { } void cRecipeMapper::AddRecipeLine(const AString & a_ProtocolVersion, int a_LineNum, const AString & a_RecipeLine, const std::map & a_RecipeNameMap) { AStringVector Sides = StringSplit(a_RecipeLine, " "); UInt32 Id; if (Sides.size() != 2) { LOGINFO("Recipe incompletely configured %s", a_RecipeLine); return; } StringToInteger(Sides[0], Id); auto RecipeIndex = a_RecipeNameMap.find(Sides[1]); if (RecipeIndex == a_RecipeNameMap.end()) { return; } m_ProtocolVersionMap[a_ProtocolVersion].emplace(Id, RecipeIndex->second); } std::optional cRecipeMapper::GetProtocolRecipeId(UInt32 a_RecipeId, UInt32 a_ProtocolVersion) { auto ProtocolMap = m_ProtocolVersionMap.find(cRoot::Get()->GetProtocolVersionTextFromInt(static_cast(a_ProtocolVersion))); if (ProtocolMap == m_ProtocolVersionMap.end()) { return {}; } for (const auto & item: ProtocolMap->second) { if (item.second == a_RecipeId) { return item.first; } } return {}; } std::optional cRecipeMapper::GetCuberiteRecipeId(UInt32 a_ProtocolRecipeId, UInt32 a_ProtocolVersion) { auto ProtocolMap = m_ProtocolVersionMap.find(cRoot::Get()->GetProtocolVersionTextFromInt(static_cast(a_ProtocolVersion))); if (ProtocolMap == m_ProtocolVersionMap.end()) { return {}; } auto Element = ProtocolMap->second.find(a_ProtocolRecipeId); if (Element != ProtocolMap->second.end()) { return Element->second; } return {}; } ================================================ FILE: src/Protocol/RecipeMapper.h ================================================ #pragma once #include "../CraftingRecipes.h" #include /** The RecipeMapper handles the translation of crafting recipes into protocol specific recipe Ids. The crafting recipes are identified by the RecipeId. The actual configuration is stored in the protocol specific configuration directory, e.g. `Server/Protocol/1.12.2/base.recipes.txt` */ class cRecipeMapper { public: cRecipeMapper(void); ~cRecipeMapper(); /** Translates the cuberite RecipeId to the protocol specific RecipeId */ std::optional GetProtocolRecipeId(UInt32 a_RecipeId, UInt32 a_ProtocolVersion); /** Translates the protocol specific RecipeId to the cuberite RecipeId */ std::optional GetCuberiteRecipeId(UInt32 a_ProtocolRecipeId, UInt32 a_ProtocolVersion); private: /** A mapping for each protocol from the protocol specific RecipeId and the cuberite RecipeId */ std::map> m_ProtocolVersionMap; /** Load Recipes from the protocol specific mapping file */ void loadRecipes(const AString & a_ProtocolVersion); /** Handles a single line of the protocol specific mapping file */ void AddRecipeLine(const AString & a_ProtocolVersion, int a_LineNum, const AString & a_RecipeLine, const std::map & a_RecipeNameMap); }; ================================================ FILE: src/RCONServer.cpp ================================================ // RCONServer.cpp // Implements the cRCONServer class representing the RCON server #include "Globals.h" #include "IniFile.h" #include "RCONServer.h" #include "Server.h" #include "Root.h" #include "CommandOutput.h" // Disable MSVC warnings: #if defined(_MSC_VER) #pragma warning(push) #pragma warning(disable:4355) // 'this' : used in base member initializer list #endif enum { // Client -> Server: RCON_PACKET_COMMAND = 2, RCON_PACKET_LOGIN = 3, // Server -> Client: RCON_PACKET_RESPONSE = 2, } ; //////////////////////////////////////////////////////////////////////////////// // cRCONListenCallbacks: class cRCONListenCallbacks: public cNetwork::cListenCallbacks { public: cRCONListenCallbacks(cRCONServer & a_RCONServer, UInt16 a_Port): m_RCONServer(a_RCONServer), m_Port(a_Port) { } protected: /** The RCON server instance that we're attached to. */ cRCONServer & m_RCONServer; /** The port for which this instance is responsible. */ UInt16 m_Port; // cNetwork::cListenCallbacks overrides: virtual cTCPLink::cCallbacksPtr OnIncomingConnection(const AString & a_RemoteIPAddress, UInt16 a_RemotePort) override { LOG("RCON Client \"%s\" connected!", a_RemoteIPAddress.c_str()); return std::make_shared(m_RCONServer, a_RemoteIPAddress); } virtual void OnAccepted(cTCPLink & a_Link) override {} virtual void OnError(int a_ErrorCode, const AString & a_ErrorMsg) override { LOGWARNING("RCON server error on port %d: %d (%s)", m_Port, a_ErrorCode, a_ErrorMsg.c_str()); } }; //////////////////////////////////////////////////////////////////////////////// // cRCONCommandOutput: class cRCONCommandOutput : public cCommandOutputCallback { public: cRCONCommandOutput(cRCONServer::cConnection & a_Connection, UInt32 a_RequestID) : m_Connection(a_Connection), m_RequestID(a_RequestID) { } // cCommandOutputCallback overrides: virtual void Out(const AString & a_Text) override { m_Buffer.append(a_Text); } virtual void Finished(void) override { m_Connection.SendResponse(m_RequestID, RCON_PACKET_RESPONSE, static_cast(m_Buffer.size()), m_Buffer.c_str()); delete this; } protected: cRCONServer::cConnection & m_Connection; UInt32 m_RequestID; AString m_Buffer; } ; //////////////////////////////////////////////////////////////////////////////// // cRCONServer: cRCONServer::cRCONServer(cServer & a_Server) : m_Server(a_Server) { } cRCONServer::~cRCONServer() { for (const auto & srv: m_ListenServers) { srv->Close(); } } void cRCONServer::Initialize(cSettingsRepositoryInterface & a_Settings) { if (!a_Settings.GetValueSetB("RCON", "Enabled", false)) { return; } // Read the password, don't allow an empty one: m_Password = a_Settings.GetValueSet("RCON", "Password", ""); if (m_Password.empty()) { LOGWARNING("RCON is requested, but the password is not set. RCON is now disabled."); return; } // Read the listening ports for RCON from config: AStringVector Ports = ReadUpgradeIniPorts(a_Settings, "RCON", "Ports", "PortsIPv4", "PortsIPv6", "25575"); // Start listening on each specified port: for (const auto & port: Ports) { UInt16 PortNum; if (!StringToInteger(port, PortNum)) { LOGINFO("Invalid RCON port value: \"%s\". Ignoring.", port.c_str()); continue; } auto Handle = cNetwork::Listen(PortNum, std::make_shared(*this, PortNum)); if (Handle->IsListening()) { m_ListenServers.push_back(Handle); } } if (m_ListenServers.empty()) { LOGWARNING("RCON is enabled but no valid ports were found. RCON is not accessible."); } } //////////////////////////////////////////////////////////////////////////////// // cRCONServer::cConnection: cRCONServer::cConnection::cConnection(cRCONServer & a_RCONServer, const AString & a_IPAddress) : m_IsAuthenticated(false), m_RCONServer(a_RCONServer), m_IPAddress(a_IPAddress) { } void cRCONServer::cConnection::OnLinkCreated(cTCPLinkPtr a_Link) { m_Link = a_Link; } void cRCONServer::cConnection::OnReceivedData(const char * a_Data, size_t a_Size) { ASSERT(m_Link != nullptr); // Append data to the buffer: m_Buffer.append(a_Data, a_Size); // Process the packets in the buffer: while (m_Buffer.size() >= 14) { UInt32 Length = UIntFromBuffer(m_Buffer.data()); if ((Length > 1500) || (Length < 10)) { // Too long or too short, drop the connection LOGWARNING("Received an invalid RCON packet length (%d), dropping RCON connection to %s.", Length, m_IPAddress.c_str() ); m_Link->Close(); m_Link.reset(); return; } if (Length > static_cast(m_Buffer.size() + 4)) { // Incomplete packet yet, wait for more data to come return; } UInt32 RequestID = UIntFromBuffer(m_Buffer.data() + 4); UInt32 PacketType = UIntFromBuffer(m_Buffer.data() + 8); if (!ProcessPacket(RequestID, PacketType, Length - 10, m_Buffer.data() + 12)) { m_Link->Close(); m_Link.reset(); return; } m_Buffer.erase(0, Length + 4); } // while (m_Buffer.size() >= 14) } void cRCONServer::cConnection::OnRemoteClosed(void) { m_Link.reset(); } void cRCONServer::cConnection::OnError(int a_ErrorCode, const AString & a_ErrorMsg) { LOGD("Error in RCON connection %s: %d (%s)", m_IPAddress.c_str(), a_ErrorCode, a_ErrorMsg.c_str()); m_Link.reset(); } bool cRCONServer::cConnection::ProcessPacket(UInt32 a_RequestID, UInt32 a_PacketType, UInt32 a_PayloadLength, const char * a_Payload) { switch (a_PacketType) { case RCON_PACKET_LOGIN: { if ((a_PayloadLength == 0) || (strncmp(a_Payload, m_RCONServer.m_Password.c_str(), a_PayloadLength) != 0)) { LOGINFO("RCON: Invalid password from client %s, dropping connection.", m_IPAddress.c_str()); SendResponse(0xffffffffU, RCON_PACKET_RESPONSE, 0, nullptr); return false; } m_IsAuthenticated = true; LOGD("RCON: Client at %s has successfully authenticated", m_IPAddress.c_str()); // Send OK response: SendResponse(a_RequestID, RCON_PACKET_RESPONSE, 0, nullptr); return true; } case RCON_PACKET_COMMAND: { if (!m_IsAuthenticated) { char AuthNeeded[] = "You need to authenticate first!"; SendResponse(a_RequestID, RCON_PACKET_RESPONSE, sizeof(AuthNeeded), AuthNeeded); return false; } AString cmd(a_Payload, a_PayloadLength); LOGD("RCON command from %s: \"%s\"", m_IPAddress.c_str(), cmd.c_str()); cRoot::Get()->QueueExecuteConsoleCommand(cmd, *(new cRCONCommandOutput(*this, a_RequestID))); // Send an empty response: SendResponse(a_RequestID, RCON_PACKET_RESPONSE, 0, nullptr); return true; } } // Unknown packet type, drop the connection: LOGWARNING("RCON: Client at %s has sent an unknown packet type %d, dropping connection.", m_IPAddress.c_str(), a_PacketType ); return false; } UInt32 cRCONServer::cConnection::UIntFromBuffer(const char * a_Buffer) { const Byte * Buffer = reinterpret_cast(a_Buffer); return static_cast((Buffer[3] << 24) | (Buffer[2] << 16) | (Buffer[1] << 8) | Buffer[0]); } void cRCONServer::cConnection::UIntToBuffer(UInt32 a_Value, char * a_Buffer) { a_Buffer[0] = static_cast(a_Value & 0xff); a_Buffer[1] = static_cast((a_Value >> 8) & 0xff); a_Buffer[2] = static_cast((a_Value >> 16) & 0xff); a_Buffer[3] = static_cast((a_Value >> 24) & 0xff); } void cRCONServer::cConnection::SendResponse(UInt32 a_RequestID, UInt32 a_PacketType, UInt32 a_PayloadLength, const char * a_Payload) { ASSERT((a_PayloadLength == 0) || (a_Payload != nullptr)); // Either zero data to send, or a valid payload ptr ASSERT(m_Link != nullptr); char Buffer[12]; UInt32 Length = a_PayloadLength + 10; UIntToBuffer(Length, Buffer); UIntToBuffer(a_RequestID, Buffer + 4); UIntToBuffer(a_PacketType, Buffer + 8); m_Link->Send(Buffer, 12); if (a_PayloadLength > 0) { m_Link->Send(a_Payload, a_PayloadLength); } m_Link->Send("\0", 2); // Send two zero chars as the padding } ================================================ FILE: src/RCONServer.h ================================================ // RCONServer.h // Declares the cRCONServer class representing the RCON server #pragma once #include "OSSupport/Network.h" // fwd: class cServer; class cSettingsRepositoryInterface; class cRCONServer { public: cRCONServer(cServer & a_Server); virtual ~cRCONServer(); void Initialize(cSettingsRepositoryInterface & a_Settings); protected: friend class cRCONCommandOutput; friend class cRCONListenCallbacks; class cConnection : public cTCPLink::cCallbacks { public: cConnection(cRCONServer & a_RCONServer, const AString & a_IPAddress); protected: friend class cRCONCommandOutput; /** Set to true if the client has successfully authenticated */ bool m_IsAuthenticated; /** Buffer for the incoming data */ AString m_Buffer; /** Server that owns this connection and processes requests */ cRCONServer & m_RCONServer; /** The TCP link to the client */ cTCPLinkPtr m_Link; /** Address of the client */ AString m_IPAddress; // cTCPLink::cCallbacks overrides: virtual void OnLinkCreated(cTCPLinkPtr a_Link) override; virtual void OnReceivedData(const char * a_Data, size_t a_Length) override; virtual void OnRemoteClosed(void) override; virtual void OnError(int a_ErrorCode, const AString & a_ErrorMsg) override; /** Processes the given packet and sends the response; returns true if successful, false if the connection is to be dropped */ bool ProcessPacket(UInt32 a_RequestID, UInt32 a_PacketType, UInt32 a_PayloadLength, const char * a_Payload); /** Reads 4 bytes from a_Buffer and returns the LE UInt32 they represent */ UInt32 UIntFromBuffer(const char * a_Buffer); /** Puts 4 bytes representing the int into the buffer */ void UIntToBuffer(UInt32 a_Value, char * a_Buffer); /** Sends a RCON packet back to the client */ void SendResponse(UInt32 a_RequestID, UInt32 a_PacketType, UInt32 a_PayloadLength, const char * a_Payload); } ; /** The server object that will process the commands received */ cServer & m_Server; /** The sockets for accepting RCON connections (one socket per port). */ cServerHandlePtrs m_ListenServers; /** Password for authentication */ AString m_Password; } ; ================================================ FILE: src/RankManager.cpp ================================================ // RankManager.cpp // Implements the cRankManager class that represents the rank manager responsible for assigning permissions and message visuals to players #include "Globals.h" #include "RankManager.h" #include "Protocol/MojangAPI.h" #include "ClientHandle.h" //////////////////////////////////////////////////////////////////////////////// // cRankManager: cRankManager::cRankManager(void) : m_DB("Ranks.sqlite", SQLite::OPEN_READWRITE | SQLite::OPEN_CREATE), m_IsInitialized(false) { } cRankManager::~cRankManager() { } void cRankManager::Initialize(cMojangAPI & a_MojangAPI) { ASSERT(!m_IsInitialized); // Calling Initialize for the second time? // Create the DB tables, if they don't exist: m_DB.exec("CREATE TABLE IF NOT EXISTS Rank (RankID INTEGER PRIMARY KEY, Name, MsgPrefix, MsgSuffix, MsgNameColorCode)"); m_DB.exec("CREATE TABLE IF NOT EXISTS PlayerRank (PlayerUUID, PlayerName, RankID INTEGER)"); m_DB.exec("CREATE TABLE IF NOT EXISTS PermGroup (PermGroupID INTEGER PRIMARY KEY, Name)"); m_DB.exec("CREATE TABLE IF NOT EXISTS RankPermGroup (RankID INTEGER, PermGroupID INTEGER)"); m_DB.exec("CREATE TABLE IF NOT EXISTS PermissionItem (PermGroupID INTEGER, Permission)"); m_DB.exec("CREATE TABLE IF NOT EXISTS RestrictionItem (PermGroupID INTEGER, Permission)"); m_DB.exec("CREATE TABLE IF NOT EXISTS DefaultRank (RankID INTEGER)"); m_IsInitialized = true; a_MojangAPI.SetRankManager(this); // If tables are empty, create default ranks if (AreDBTablesEmpty()) { LOGINFO("Creating default ranks..."); CreateDefaults(); LOGINFO("Default ranks created."); } // Load the default rank: try { SQLite::Statement stmt(m_DB, "SELECT Rank.Name FROM Rank " "LEFT JOIN DefaultRank ON Rank.RankID = DefaultRank.RankID" ); if (stmt.executeStep()) { m_DefaultRank = stmt.getColumn(0).getText(); } } catch (const SQLite::Exception & ex) { LOGWARNING("%s: Cannot load default rank: %s", __FUNCTION__, ex.what()); return; } // If the default rank cannot be loaded, use the first rank: if (m_DefaultRank.empty()) { SetDefaultRank(GetAllRanks()[0]); } } AString cRankManager::GetPlayerRankName(const cUUID & a_PlayerUUID) { ASSERT(m_IsInitialized); cCSLock Lock(m_CS); try { SQLite::Statement stmt(m_DB, "SELECT Rank.Name FROM Rank LEFT JOIN PlayerRank ON Rank.RankID = PlayerRank.RankID WHERE PlayerRank.PlayerUUID = ?"); stmt.bind(1, a_PlayerUUID.ToShortString()); // executeStep returns false on no data if (!stmt.executeStep()) { // No data returned from the DB return AString(); } return stmt.getColumn(0).getText(); } catch (const SQLite::Exception & ex) { LOGWARNING("%s: Cannot get player rank name: %s", __FUNCTION__, ex.what()); } return AString(); } AString cRankManager::GetPlayerName(const cUUID & a_PlayerUUID) { ASSERT(m_IsInitialized); cCSLock Lock(m_CS); try { // Prepare the DB statement: SQLite::Statement stmt(m_DB, "SELECT PlayerName FROM PlayerRank WHERE PlayerUUID = ?"); stmt.bind(1, a_PlayerUUID.ToShortString()); if (stmt.executeStep()) { return stmt.getColumn(0).getText(); } } catch (SQLite::Exception & ex) { LOGWARNING("%s: Cannot get player name: %s", __FUNCTION__, ex.what()); } return AString(); } AStringVector cRankManager::GetPlayerGroups(const cUUID & a_PlayerUUID) { ASSERT(m_IsInitialized); cCSLock Lock(m_CS); AStringVector res; try { // Prepare the DB statement: SQLite::Statement stmt(m_DB, "SELECT PermGroup.Name FROM PermGroup " "LEFT JOIN RankPermGroup ON PermGroup.PermGroupID = RankPermGroup.PermGroupID " "LEFT JOIN PlayerRank ON PlayerRank.RankID = RankPermGroup.RankID " "WHERE PlayerRank.PlayerUUID = ?" ); stmt.bind(1, a_PlayerUUID.ToShortString()); // Execute and get results: while (stmt.executeStep()) { res.push_back(stmt.getColumn(0).getText()); } } catch (const SQLite::Exception & ex) { LOGWARNING("%s: Cannot get player groups: %s", __FUNCTION__, ex.what()); } return res; } AStringVector cRankManager::GetPlayerPermissions(const cUUID & a_PlayerUUID) { AString Rank = GetPlayerRankName(a_PlayerUUID); if (Rank.empty()) { Rank = m_DefaultRank; } return GetRankPermissions(Rank); } AStringVector cRankManager::GetPlayerRestrictions(const cUUID & a_PlayerUUID) { AString Rank = GetPlayerRankName(a_PlayerUUID); if (Rank.empty()) { Rank = m_DefaultRank; } return GetRankRestrictions(Rank); } AStringVector cRankManager::GetRankGroups(const AString & a_RankName) { ASSERT(m_IsInitialized); cCSLock Lock(m_CS); AStringVector res; try { SQLite::Statement stmt(m_DB, "SELECT PermGroup.Name FROM PermGroup " "LEFT JOIN RankPermGroup ON RankPermGroup.PermGroupID = PermGroup.PermGroupID " "LEFT JOIN Rank ON Rank.RankID = RankPermGroup.RankID " "WHERE Rank.Name = ?" ); stmt.bind(1, a_RankName); while (stmt.executeStep()) { res.push_back(stmt.getColumn(0).getText()); } } catch (const SQLite::Exception & ex) { LOGWARNING("%s: Failed to get rank groups from DB: %s", __FUNCTION__, ex.what()); } return res; } AStringVector cRankManager::GetGroupPermissions(const AString & a_GroupName) { ASSERT(m_IsInitialized); cCSLock Lock(m_CS); AStringVector res; try { SQLite::Statement stmt(m_DB, "SELECT PermissionItem.Permission FROM PermissionItem " "LEFT JOIN PermGroup ON PermGroup.PermGroupID = PermissionItem.PermGroupID " "WHERE PermGroup.Name = ?" ); stmt.bind(1, a_GroupName); while (stmt.executeStep()) { res.push_back(stmt.getColumn(0).getText()); } } catch (const SQLite::Exception & ex) { LOGWARNING("%s: Failed to get group permissions from DB: %s", __FUNCTION__, ex.what()); } return res; } AStringVector cRankManager::GetGroupRestrictions(const AString & a_GroupName) { ASSERT(m_IsInitialized); cCSLock Lock(m_CS); AStringVector res; try { SQLite::Statement stmt(m_DB, "SELECT RestrictionItem.Permission FROM RestrictionItem " "LEFT JOIN PermGroup ON PermGroup.PermGroupID = RestrictionItem.PermGroupID " "WHERE PermGroup.Name = ?" ); stmt.bind(1, a_GroupName); while (stmt.executeStep()) { res.push_back(stmt.getColumn(0).getText()); } } catch (const SQLite::Exception & ex) { LOGWARNING("%s: Failed to get group restrictions from DB: %s", __FUNCTION__, ex.what()); } return res; } AStringVector cRankManager::GetRankPermissions(const AString & a_RankName) { ASSERT(m_IsInitialized); cCSLock Lock(m_CS); AStringVector res; try { SQLite::Statement stmt(m_DB, "SELECT PermissionItem.Permission FROM PermissionItem " "LEFT JOIN RankPermGroup ON RankPermGroup.PermGroupID = PermissionItem.PermGroupID " "LEFT JOIN Rank ON Rank.RankID = RankPermGroup.RankID " "WHERE Rank.Name = ?" ); stmt.bind(1, a_RankName); while (stmt.executeStep()) { res.push_back(stmt.getColumn(0).getText()); } } catch (const SQLite::Exception & ex) { LOGWARNING("%s: Failed to get rank permissions from DB: %s", __FUNCTION__, ex.what()); } return res; } AStringVector cRankManager::GetRankRestrictions(const AString & a_RankName) { ASSERT(m_IsInitialized); cCSLock Lock(m_CS); AStringVector res; try { SQLite::Statement stmt(m_DB, "SELECT RestrictionItem.Permission FROM RestrictionItem " "LEFT JOIN RankPermGroup ON RankPermGroup.PermGroupID = RestrictionItem.PermGroupID " "LEFT JOIN Rank ON Rank.RankID = RankPermGroup.RankID " "WHERE Rank.Name = ?" ); stmt.bind(1, a_RankName); while (stmt.executeStep()) { res.push_back(stmt.getColumn(0).getText()); } } catch (const SQLite::Exception & ex) { LOGWARNING("%s: Failed to get rank restrictions from DB: %s", __FUNCTION__, ex.what()); } return res; } std::vector cRankManager::GetAllPlayerUUIDs(void) { ASSERT(m_IsInitialized); cCSLock Lock(m_CS); cUUID tempUUID; std::vector res; try { SQLite::Statement stmt(m_DB, "SELECT PlayerUUID FROM PlayerRank ORDER BY PlayerName COLLATE NOCASE"); while (stmt.executeStep()) { if (!tempUUID.FromString(stmt.getColumn(0).getText())) { // Invalid UUID, ignore continue; } res.push_back(tempUUID); } } catch (const SQLite::Exception & ex) { LOGWARNING("%s: Failed to get players from DB: %s", __FUNCTION__, ex.what()); } return res; } AStringVector cRankManager::GetAllRanks(void) { ASSERT(m_IsInitialized); cCSLock Lock(m_CS); AStringVector res; try { SQLite::Statement stmt(m_DB, "SELECT Name FROM Rank"); while (stmt.executeStep()) { res.push_back(stmt.getColumn(0).getText()); } } catch (const SQLite::Exception & ex) { LOGWARNING("%s: Failed to get ranks from DB: %s", __FUNCTION__, ex.what()); } return res; } AStringVector cRankManager::GetAllGroups(void) { ASSERT(m_IsInitialized); cCSLock Lock(m_CS); AStringVector res; try { SQLite::Statement stmt(m_DB, "SELECT Name FROM PermGroup"); while (stmt.executeStep()) { res.push_back(stmt.getColumn(0).getText()); } } catch (const SQLite::Exception & ex) { LOGWARNING("%s: Failed to get groups from DB: %s", __FUNCTION__, ex.what()); } return res; } AStringVector cRankManager::GetAllPermissions(void) { ASSERT(m_IsInitialized); cCSLock Lock(m_CS); AStringVector res; try { SQLite::Statement stmt(m_DB, "SELECT DISTINCT(Permission) FROM PermissionItem"); while (stmt.executeStep()) { res.push_back(stmt.getColumn(0).getText()); } } catch (const SQLite::Exception & ex) { LOGWARNING("%s: Failed to get permissions from DB: %s", __FUNCTION__, ex.what()); } return res; } AStringVector cRankManager::GetAllRestrictions(void) { ASSERT(m_IsInitialized); cCSLock Lock(m_CS); AStringVector res; try { SQLite::Statement stmt(m_DB, "SELECT DISTINCT(Permission) FROM RestrictionItem"); while (stmt.executeStep()) { res.push_back(stmt.getColumn(0).getText()); } } catch (const SQLite::Exception & ex) { LOGWARNING("%s: Failed to get restrictions from DB: %s", __FUNCTION__, ex.what()); } return res; } AStringVector cRankManager::GetAllPermissionsRestrictions(void) { AStringVector Permissions = GetAllPermissions(); AStringVector Restrictions = GetAllRestrictions(); for (auto & restriction: Restrictions) { Permissions.push_back(restriction); } return Permissions; } bool cRankManager::GetPlayerMsgVisuals( const cUUID & a_PlayerUUID, AString & a_MsgPrefix, AString & a_MsgSuffix, AString & a_MsgNameColorCode ) { AString Rank = GetPlayerRankName(a_PlayerUUID); if (Rank.empty()) { // Rank not found, return failure: a_MsgPrefix.clear(); a_MsgSuffix.clear(); a_MsgNameColorCode.clear(); return false; } return GetRankVisuals(Rank, a_MsgPrefix, a_MsgSuffix, a_MsgNameColorCode); } void cRankManager::AddRank( const AString & a_RankName, const AString & a_MsgPrefix, const AString & a_MsgSuffix, const AString & a_MsgNameColorCode ) { ASSERT(m_IsInitialized); cCSLock Lock(m_CS); try { // Check if such a rank name is already used: { SQLite::Statement stmt(m_DB, "SELECT COUNT(*) FROM Rank WHERE Name = ?"); stmt.bind(1, a_RankName); if (stmt.executeStep()) { if (stmt.getColumn(0).getInt() > 0) { // Rank already exists, do nothing: return; } } } // Insert a new rank: SQLite::Statement stmt(m_DB, "INSERT INTO Rank (Name, MsgPrefix, MsgSuffix, MsgNameColorCode) VALUES (?, ?, ?, ?)"); stmt.bind(1, a_RankName); stmt.bind(2, a_MsgPrefix); stmt.bind(3, a_MsgSuffix); stmt.bind(4, a_MsgNameColorCode); if (stmt.exec() <= 0) { LOGWARNING("%s: Failed to add a new rank \"%s\".", __FUNCTION__, a_RankName.c_str()); return; } } catch (const SQLite::Exception & ex) { LOGWARNING("%s: Failed to add a new rank \"%s\": %s", __FUNCTION__, a_RankName.c_str(), ex.what()); } } void cRankManager::AddGroup(const AString & a_GroupName) { ASSERT(m_IsInitialized); cCSLock Lock(m_CS); try { // Check if such a group name is already used: { SQLite::Statement stmt(m_DB, "SELECT COUNT(*) FROM PermGroup WHERE Name = ?"); stmt.bind(1, a_GroupName); if (stmt.executeStep()) { if (stmt.getColumn(0).getInt() > 0) { // Group already exists, do nothing: return; } } } // Insert a new group: SQLite::Statement stmt(m_DB, "INSERT INTO PermGroup (Name) VALUES (?)"); stmt.bind(1, a_GroupName); if (stmt.exec() <= 0) { LOGWARNING("%s: Failed to add a new group \"%s\".", __FUNCTION__, a_GroupName.c_str()); return; } } catch (const SQLite::Exception & ex) { LOGWARNING("%s: Failed to add a new group \"%s\": %s", __FUNCTION__, a_GroupName.c_str(), ex.what()); } } void cRankManager::AddGroups(const AStringVector & a_GroupNames) { ASSERT(m_IsInitialized); cCSLock Lock(m_CS); try { for (AStringVector::const_iterator itr = a_GroupNames.begin(), end = a_GroupNames.end(); itr != end; ++itr) { // Check if such the group name is already used: { SQLite::Statement stmt(m_DB, "SELECT COUNT(*) FROM PermGroup WHERE Name = ?"); stmt.bind(1, *itr); if (stmt.executeStep()) { if (stmt.getColumn(0).getInt() > 0) { // Group already exists, do nothing: return; } } } // Insert a new group: SQLite::Statement stmt(m_DB, "INSERT INTO PermGroup (Name) VALUES (?)"); stmt.bind(1, *itr); if (stmt.exec() <= 0) { LOGWARNING("%s: Failed to add a new group \"%s\".", __FUNCTION__, itr->c_str()); return; } } // for itr - a_GroupNames[] } catch (const SQLite::Exception & ex) { LOGWARNING("%s: Failed to add new groups: %s", __FUNCTION__, ex.what()); } } bool cRankManager::AddGroupToRank(const AString & a_GroupName, const AString & a_RankName) { ASSERT(m_IsInitialized); cCSLock Lock(m_CS); try { // Get the group's ID: int GroupID; { SQLite::Statement stmt(m_DB, "SELECT PermGroupID FROM PermGroup WHERE Name = ?"); stmt.bind(1, a_GroupName); if (!stmt.executeStep()) { LOGWARNING("%s: No such group (%s), aborting.", __FUNCTION__, a_GroupName.c_str()); return false; } GroupID = stmt.getColumn(0); } // Get the rank's ID: int RankID; { SQLite::Statement stmt(m_DB, "SELECT RankID FROM Rank WHERE Name = ?"); stmt.bind(1, a_RankName); if (!stmt.executeStep()) { LOGWARNING("%s: No such rank (%s), aborting.", __FUNCTION__, a_RankName.c_str()); return false; } RankID = stmt.getColumn(0); } // Check if the group is already there: { SQLite::Statement stmt(m_DB, "SELECT COUNT(*) FROM RankPermGroup WHERE RankID = ? AND PermGroupID = ?"); stmt.bind(1, RankID); stmt.bind(2, GroupID); if (!stmt.executeStep()) { LOGWARNING("%s: Failed to check binding between rank %s and group %s, aborting.", __FUNCTION__, a_RankName.c_str(), a_GroupName.c_str()); return false; } if (stmt.getColumn(0).getInt() > 0) { LOGD("%s: Group %s already present in rank %s, skipping and returning success.", __FUNCTION__, a_GroupName.c_str(), a_RankName.c_str() ); return true; } } // Add the group: { SQLite::Statement stmt(m_DB, "INSERT INTO RankPermGroup (RankID, PermGroupID) VALUES (?, ?)"); stmt.bind(1, RankID); stmt.bind(2, GroupID); if (stmt.exec() <= 0) { LOGWARNING("%s: Failed to add group %s to rank %s, aborting.", __FUNCTION__, a_GroupName.c_str(), a_RankName.c_str()); return false; } } // Adding succeeded: return true; } catch (const SQLite::Exception & ex) { LOGWARNING("%s: Failed to add group %s to rank %s: %s", __FUNCTION__, a_GroupName.c_str(), a_RankName.c_str(), ex.what()); } return false; } bool cRankManager::AddPermissionToGroup(const AString & a_Permission, const AString & a_GroupName) { ASSERT(m_IsInitialized); cCSLock Lock(m_CS); try { // Get the group's ID: int GroupID; { SQLite::Statement stmt(m_DB, "SELECT PermGroupID FROM PermGroup WHERE Name = ?"); stmt.bind(1, a_GroupName); if (!stmt.executeStep()) { LOGWARNING("%s: No such group (%s), aborting.", __FUNCTION__, a_GroupName.c_str()); return false; } GroupID = stmt.getColumn(0).getInt(); } // Check if the permission is already present: { SQLite::Statement stmt(m_DB, "SELECT COUNT(*) FROM PermissionItem WHERE PermGroupID = ? AND Permission = ?"); stmt.bind(1, GroupID); stmt.bind(2, a_Permission); if (!stmt.executeStep()) { LOGWARNING("%s: Failed to check binding between permission %s and group %s, aborting.", __FUNCTION__, a_Permission.c_str(), a_GroupName.c_str()); return false; } if (stmt.getColumn(0).getInt() > 0) { LOGD("%s: Permission %s is already present in group %s, skipping and returning success.", __FUNCTION__, a_Permission.c_str(), a_GroupName.c_str() ); return true; } } // Add the permission: { SQLite::Statement stmt(m_DB, "INSERT INTO PermissionItem (Permission, PermGroupID) VALUES (?, ?)"); stmt.bind(1, a_Permission); stmt.bind(2, GroupID); if (stmt.exec() <= 0) { LOGWARNING("%s: Failed to add permission %s to group %s, aborting.", __FUNCTION__, a_Permission.c_str(), a_GroupName.c_str()); return false; } } // Adding succeeded: return true; } catch (const SQLite::Exception & ex) { LOGWARNING("%s: Failed to add permission %s to group %s: %s", __FUNCTION__, a_Permission.c_str(), a_GroupName.c_str(), ex.what() ); } return false; } bool cRankManager::AddRestrictionToGroup(const AString & a_Restriction, const AString & a_GroupName) { ASSERT(m_IsInitialized); cCSLock Lock(m_CS); try { // Get the group's ID: int GroupID; { SQLite::Statement stmt(m_DB, "SELECT PermGroupID FROM PermGroup WHERE Name = ?"); stmt.bind(1, a_GroupName); if (!stmt.executeStep()) { LOGWARNING("%s: No such group (%s), aborting.", __FUNCTION__, a_GroupName.c_str()); return false; } GroupID = stmt.getColumn(0).getInt(); } // Check if the restriction is already present: { SQLite::Statement stmt(m_DB, "SELECT COUNT(*) FROM RestrictionItem WHERE PermGroupID = ? AND Permission = ?"); stmt.bind(1, GroupID); stmt.bind(2, a_Restriction); if (!stmt.executeStep()) { LOGWARNING("%s: Failed to check binding between restriction %s and group %s, aborting.", __FUNCTION__, a_Restriction.c_str(), a_GroupName.c_str()); return false; } if (stmt.getColumn(0).getInt() > 0) { LOGD("%s: Restriction %s is already present in group %s, skipping and returning success.", __FUNCTION__, a_Restriction.c_str(), a_GroupName.c_str() ); return true; } } // Add the restriction: { SQLite::Statement stmt(m_DB, "INSERT INTO RestrictionItem (Permission, PermGroupID) VALUES (?, ?)"); stmt.bind(1, a_Restriction); stmt.bind(2, GroupID); if (stmt.exec() <= 0) { LOGWARNING("%s: Failed to add restriction %s to group %s, aborting.", __FUNCTION__, a_Restriction.c_str(), a_GroupName.c_str()); return false; } } // Adding succeeded: return true; } catch (const SQLite::Exception & ex) { LOGWARNING("%s: Failed to add restriction %s to group %s: %s", __FUNCTION__, a_Restriction.c_str(), a_GroupName.c_str(), ex.what() ); } return false; } bool cRankManager::AddPermissionsToGroup(const AStringVector & a_Permissions, const AString & a_GroupName) { ASSERT(m_IsInitialized); cCSLock Lock(m_CS); try { // Get the group's ID: int GroupID; { SQLite::Statement stmt(m_DB, "SELECT PermGroupID FROM PermGroup WHERE Name = ?"); stmt.bind(1, a_GroupName); if (!stmt.executeStep()) { LOGWARNING("%s: No such group (%s), aborting.", __FUNCTION__, a_GroupName.c_str()); return false; } GroupID = stmt.getColumn(0).getInt(); } for (AStringVector::const_iterator itr = a_Permissions.begin(), end = a_Permissions.end(); itr != end; ++itr) { // Check if the permission is already present: { SQLite::Statement stmt(m_DB, "SELECT COUNT(*) FROM PermissionItem WHERE PermGroupID = ? AND Permission = ?"); stmt.bind(1, GroupID); stmt.bind(2, *itr); if (!stmt.executeStep()) { LOGWARNING("%s: Failed to check binding between permission %s and group %s, aborting.", __FUNCTION__, itr->c_str(), a_GroupName.c_str()); return false; } if (stmt.getColumn(0).getInt() > 0) { LOGD("%s: Permission %s is already present in group %s, skipping and returning success.", __FUNCTION__, itr->c_str(), a_GroupName.c_str() ); continue; } } // Add the permission: { SQLite::Statement stmt(m_DB, "INSERT INTO PermissionItem (Permission, PermGroupID) VALUES (?, ?)"); stmt.bind(1, *itr); stmt.bind(2, GroupID); if (stmt.exec() <= 0) { LOGWARNING("%s: Failed to add permission %s to group %s, skipping.", __FUNCTION__, itr->c_str(), a_GroupName.c_str()); continue; } } } // for itr - a_Permissions[] // Adding succeeded: return true; } catch (const SQLite::Exception & ex) { LOGWARNING("%s: Failed to add permissions to group %s: %s", __FUNCTION__, a_GroupName.c_str(), ex.what() ); } return false; } bool cRankManager::AddRestrictionsToGroup(const AStringVector & a_Restrictions, const AString & a_GroupName) { ASSERT(m_IsInitialized); cCSLock Lock(m_CS); try { // Get the group's ID: int GroupID; { SQLite::Statement stmt(m_DB, "SELECT PermGroupID FROM PermGroup WHERE Name = ?"); stmt.bind(1, a_GroupName); if (!stmt.executeStep()) { LOGWARNING("%s: No such group (%s), aborting.", __FUNCTION__, a_GroupName.c_str()); return false; } GroupID = stmt.getColumn(0).getInt(); } for (auto itr = a_Restrictions.cbegin(), end = a_Restrictions.cend(); itr != end; ++itr) { // Check if the restriction is already present: { SQLite::Statement stmt(m_DB, "SELECT COUNT(*) FROM RestrictionItem WHERE PermGroupID = ? AND Permission = ?"); stmt.bind(1, GroupID); stmt.bind(2, *itr); if (!stmt.executeStep()) { LOGWARNING("%s: Failed to check binding between restriction %s and group %s, aborting.", __FUNCTION__, itr->c_str(), a_GroupName.c_str()); return false; } if (stmt.getColumn(0).getInt() > 0) { LOGD("%s: Restriction %s is already present in group %s, skipping and returning success.", __FUNCTION__, itr->c_str(), a_GroupName.c_str() ); continue; } } // Add the permission: { SQLite::Statement stmt(m_DB, "INSERT INTO RestrictionItem (Permission, PermGroupID) VALUES (?, ?)"); stmt.bind(1, *itr); stmt.bind(2, GroupID); if (stmt.exec() <= 0) { LOGWARNING("%s: Failed to add restriction %s to group %s, skipping.", __FUNCTION__, itr->c_str(), a_GroupName.c_str()); continue; } } } // for itr - a_Restrictions[] // Adding succeeded: return true; } catch (const SQLite::Exception & ex) { LOGWARNING("%s: Failed to add restrictions to group %s: %s", __FUNCTION__, a_GroupName.c_str(), ex.what() ); } return false; } void cRankManager::RemoveRank(const AString & a_RankName, const AString & a_ReplacementRankName) { ASSERT(m_IsInitialized); cCSLock Lock(m_CS); // Check if the default rank is being removed with a proper replacement: if ((a_RankName == m_DefaultRank) && !RankExists(a_ReplacementRankName)) { LOGWARNING("%s: Cannot remove rank %s, it is the default rank and the replacement rank doesn't exist.", __FUNCTION__, a_RankName.c_str()); return; } AStringVector res; try { // Get the RankID for the rank being removed: int RemoveRankID; { SQLite::Statement stmt(m_DB, "SELECT RankID FROM Rank WHERE Name = ?"); stmt.bind(1, a_RankName); if (!stmt.executeStep()) { LOGINFO("%s: Rank %s was not found. Skipping.", __FUNCTION__, a_RankName.c_str()); return; } RemoveRankID = stmt.getColumn(0).getInt(); } // Get the RankID for the replacement rank: int ReplacementRankID = -1; { SQLite::Statement stmt(m_DB, "SELECT RankID FROM Rank WHERE Name = ?"); stmt.bind(1, a_ReplacementRankName); if (stmt.executeStep()) { ReplacementRankID = stmt.getColumn(0).getInt(); } } // Remove the rank's bindings to groups: { SQLite::Statement stmt(m_DB, "DELETE FROM RankPermGroup WHERE RankID = ?"); stmt.bind(1, RemoveRankID); stmt.exec(); } // Adjust players: if (ReplacementRankID == -1) { // No replacement, just delete all the players that have the rank: SQLite::Statement stmt(m_DB, "DELETE FROM PlayerRank WHERE RankID = ?"); stmt.bind(1, RemoveRankID); stmt.exec(); } else { // Replacement available, change all the player records: SQLite::Statement stmt(m_DB, "UPDATE PlayerRank SET RankID = ? WHERE RankID = ?"); stmt.bind(1, ReplacementRankID); stmt.bind(2, RemoveRankID); stmt.exec(); } // Remove the rank from the DB: { SQLite::Statement stmt(m_DB, "DELETE FROM Rank WHERE RankID = ?"); stmt.bind(1, RemoveRankID); stmt.exec(); } // Update the default rank, if it was the one being removed: if (a_RankName == m_DefaultRank) { m_DefaultRank = a_RankName; } } catch (const SQLite::Exception & ex) { LOGWARNING("%s: Failed to remove rank from DB: %s", __FUNCTION__, ex.what()); } } void cRankManager::RemoveGroup(const AString & a_GroupName) { ASSERT(m_IsInitialized); cCSLock Lock(m_CS); try { // Get the ID of the group: int GroupID; { SQLite::Statement stmt(m_DB, "SELECT PermGroupID FROM PermGroup WHERE Name = ?"); stmt.bind(1, a_GroupName); if (!stmt.executeStep()) { LOGINFO("%s: Group %s was not found, skipping.", __FUNCTION__, a_GroupName.c_str()); return; } GroupID = stmt.getColumn(0).getInt(); } // Remove all permissions from the group: { SQLite::Statement stmt(m_DB, "DELETE FROM PermissionItem WHERE PermGroupID = ?"); stmt.bind(1, GroupID); stmt.exec(); } // Remove the group from all ranks that contain it: { SQLite::Statement stmt(m_DB, "DELETE FROM RankPermGroup WHERE PermGroupID = ?"); stmt.bind(1, GroupID); stmt.exec(); } // Remove the group itself: { SQLite::Statement stmt(m_DB, "DELETE FROM PermGroup WHERE PermGroupID = ?"); stmt.bind(1, GroupID); stmt.exec(); } } catch (const SQLite::Exception & ex) { LOGWARNING("%s: Failed to remove group %s from DB: %s", __FUNCTION__, a_GroupName.c_str(), ex.what()); } } void cRankManager::RemoveGroupFromRank(const AString & a_GroupName, const AString & a_RankName) { ASSERT(m_IsInitialized); cCSLock Lock(m_CS); try { // Get the IDs of the group and the rank: int GroupID, RankID; { SQLite::Statement stmt(m_DB, "SELECT PermGroup.PermGroupID, Rank.RankID FROM PermGroup " "LEFT JOIN RankPermGroup ON RankPermGroup.PermGroupID = PermGroup.PermGroupID " "LEFT JOIN Rank ON Rank.RankID = RankPermGroup.RankID " "WHERE PermGroup.Name = ? AND Rank.Name = ?" ); stmt.bind(1, a_GroupName); stmt.bind(2, a_RankName); if (!stmt.executeStep()) { LOGINFO("%s: Group %s was not found in rank %s, skipping.", __FUNCTION__, a_GroupName.c_str(), a_RankName.c_str()); return; } GroupID = stmt.getColumn(0).getInt(); RankID = stmt.getColumn(1).getInt(); } // Remove the group from all ranks that contain it: { SQLite::Statement stmt(m_DB, "DELETE FROM RankPermGroup WHERE PermGroupID = ?"); stmt.bind(1, GroupID); stmt.exec(); } // Remove the group-to-rank binding: { SQLite::Statement stmt(m_DB, "DELETE FROM RankPermGroup WHERE PermGroupID = ? AND RankID = ?"); stmt.bind(1, GroupID); stmt.bind(1, RankID); stmt.exec(); } } catch (const SQLite::Exception & ex) { LOGWARNING("%s: Failed to remove group %s from rank %s in the DB: %s", __FUNCTION__, a_GroupName.c_str(), a_RankName.c_str(), ex.what()); } } void cRankManager::RemovePermissionFromGroup(const AString & a_Permission, const AString & a_GroupName) { ASSERT(m_IsInitialized); cCSLock Lock(m_CS); try { // Get the ID of the group: int GroupID; { SQLite::Statement stmt(m_DB, "SELECT PermGroupID FROM PermGroup WHERE Name = ?"); stmt.bind(1, a_GroupName); if (!stmt.executeStep()) { LOGINFO("%s: Group %s was not found, skipping.", __FUNCTION__, a_GroupName.c_str()); return; } GroupID = stmt.getColumn(0).getInt(); } // Remove the permission from the group: { SQLite::Statement stmt(m_DB, "DELETE FROM PermissionItem WHERE PermGroupID = ? AND Permission = ?"); stmt.bind(1, GroupID); stmt.bind(2, a_Permission); stmt.exec(); } } catch (const SQLite::Exception & ex) { LOGWARNING("%s: Failed to remove permission %s from group %s in DB: %s", __FUNCTION__, a_Permission.c_str(), a_GroupName.c_str(), ex.what() ); } } void cRankManager::RemoveRestrictionFromGroup(const AString & a_Restriction, const AString & a_GroupName) { ASSERT(m_IsInitialized); cCSLock Lock(m_CS); try { // Get the ID of the group: int GroupID; { SQLite::Statement stmt(m_DB, "SELECT PermGroupID FROM PermGroup WHERE Name = ?"); stmt.bind(1, a_GroupName); if (!stmt.executeStep()) { LOGINFO("%s: Group %s was not found, skipping.", __FUNCTION__, a_GroupName.c_str()); return; } GroupID = stmt.getColumn(0).getInt(); } // Remove the permission from the group: { SQLite::Statement stmt(m_DB, "DELETE FROM RestrictionItem WHERE PermGroupID = ? AND Permission = ?"); stmt.bind(1, GroupID); stmt.bind(2, a_Restriction); stmt.exec(); } } catch (const SQLite::Exception & ex) { LOGWARNING("%s: Failed to remove restriction %s from group %s in DB: %s", __FUNCTION__, a_Restriction.c_str(), a_GroupName.c_str(), ex.what() ); } } bool cRankManager::RenameRank(const AString & a_OldName, const AString & a_NewName) { ASSERT(m_IsInitialized); cCSLock Lock(m_CS); try { // Check that NewName doesn't exist: { SQLite::Statement stmt(m_DB, "SELECT RankID FROM Rank WHERE Name = ?"); stmt.bind(1, a_NewName); if (stmt.executeStep()) { LOGINFO("%s: Rank %s is already present, cannot rename %s", __FUNCTION__, a_NewName.c_str(), a_OldName.c_str()); return false; } } // Rename: { SQLite::Statement stmt(m_DB, "UPDATE Rank SET Name = ? WHERE Name = ?"); stmt.bind(1, a_NewName); stmt.bind(2, a_OldName); if (stmt.exec() <= 0) { LOGINFO("%s: There is no rank %s, cannot rename to %s.", __FUNCTION__, a_OldName.c_str(), a_NewName.c_str()); return false; } } // Update the default rank, if it was the one being renamed: if (a_OldName == m_DefaultRank) { m_DefaultRank = a_NewName; } return true; } catch (const SQLite::Exception & ex) { LOGWARNING("%s: Failed to rename rank %s to %s in DB: %s", __FUNCTION__, a_OldName.c_str(), a_NewName.c_str(), ex.what()); } return false; } bool cRankManager::RenameGroup(const AString & a_OldName, const AString & a_NewName) { ASSERT(m_IsInitialized); cCSLock Lock(m_CS); try { // Check that NewName doesn't exist: { SQLite::Statement stmt(m_DB, "SELECT PermGroupID FROM PermGroup WHERE Name = ?"); stmt.bind(1, a_NewName); if (stmt.executeStep()) { LOGD("%s: Group %s is already present, cannot rename %s", __FUNCTION__, a_NewName.c_str(), a_OldName.c_str()); return false; } } // Rename: bool res; { SQLite::Statement stmt(m_DB, "UPDATE PermGroup SET Name = ? WHERE Name = ?"); stmt.bind(1, a_NewName); stmt.bind(2, a_OldName); res = (stmt.exec() > 0); } return res; } catch (const SQLite::Exception & ex) { LOGWARNING("%s: Failed to rename group %s to %s in DB: %s", __FUNCTION__, a_OldName.c_str(), a_NewName.c_str(), ex.what()); } return false; } void cRankManager::SetPlayerRank(const cUUID & a_PlayerUUID, const AString & a_PlayerName, const AString & a_RankName) { ASSERT(m_IsInitialized); cCSLock Lock(m_CS); AString StrUUID = a_PlayerUUID.ToShortString(); try { // Get the rank ID: int RankID; { SQLite::Statement stmt(m_DB, "SELECT RankID FROM Rank WHERE Name = ?"); stmt.bind(1, a_RankName); if (!stmt.executeStep()) { LOGWARNING("%s: There is no rank %s, aborting.", __FUNCTION__, a_RankName.c_str()); return; } RankID = stmt.getColumn(0).getInt(); } // Update the player's rank, if already in DB: { SQLite::Statement stmt(m_DB, "UPDATE PlayerRank SET RankID = ?, PlayerName = ? WHERE PlayerUUID = ?"); stmt.bind(1, RankID); stmt.bind(2, a_PlayerName); stmt.bind(3, StrUUID); if (stmt.exec() > 0) { // Successfully updated the player's rank return; } } // The player is not yet in the DB, add them: SQLite::Statement stmt(m_DB, "INSERT INTO PlayerRank (RankID, PlayerUUID, PlayerName) VALUES (?, ?, ?)"); stmt.bind(1, RankID); stmt.bind(2, StrUUID); stmt.bind(3, a_PlayerName); if (stmt.exec() > 0) { // Successfully added the player return; } LOGWARNING("%s: Failed to set player UUID %s to rank %s.", __FUNCTION__, StrUUID.c_str(), a_RankName.c_str() ); } catch (const SQLite::Exception & ex) { LOGWARNING("%s: Failed to set player UUID %s to rank %s: %s", __FUNCTION__, StrUUID.c_str(), a_RankName.c_str(), ex.what() ); } } void cRankManager::RemovePlayerRank(const cUUID & a_PlayerUUID) { ASSERT(m_IsInitialized); cCSLock Lock(m_CS); AString StrUUID = a_PlayerUUID.ToShortString(); try { SQLite::Statement stmt(m_DB, "DELETE FROM PlayerRank WHERE PlayerUUID = ?"); stmt.bind(1, StrUUID); stmt.exec(); } catch (const SQLite::Exception & ex) { LOGWARNING("%s: Failed to remove rank from player UUID %s: %s", __FUNCTION__, StrUUID.c_str(), ex.what() ); } } void cRankManager::SetRankVisuals( const AString & a_RankName, const AString & a_MsgPrefix, const AString & a_MsgSuffix, const AString & a_MsgNameColorCode ) { ASSERT(m_IsInitialized); cCSLock Lock(m_CS); try { SQLite::Statement stmt(m_DB, "UPDATE Rank SET MsgPrefix = ?, MsgSuffix = ?, MsgNameColorCode = ? WHERE Name = ?"); stmt.bind(1, a_MsgPrefix); stmt.bind(2, a_MsgSuffix); stmt.bind(3, a_MsgNameColorCode); stmt.bind(4, a_RankName); if (stmt.exec() < 1) { LOGINFO("%s: Rank %s not found, visuals not set.", __FUNCTION__, a_RankName.c_str()); } } catch (const SQLite::Exception & ex) { LOGWARNING("%s: Failed to get ranks from DB: %s", __FUNCTION__, ex.what()); } } bool cRankManager::GetRankVisuals( const AString & a_RankName, AString & a_MsgPrefix, AString & a_MsgSuffix, AString & a_MsgNameColorCode ) { ASSERT(m_IsInitialized); cCSLock Lock(m_CS); try { SQLite::Statement stmt(m_DB, "SELECT MsgPrefix, MsgSuffix, MsgNameColorCode FROM Rank WHERE Name = ?"); stmt.bind(1, a_RankName); if (!stmt.executeStep()) { // Rank not found return false; } a_MsgPrefix = stmt.getColumn(0).getText(); a_MsgSuffix = stmt.getColumn(1).getText(); a_MsgNameColorCode = stmt.getColumn(2).getText(); return true; } catch (const SQLite::Exception & ex) { LOGWARNING("%s: Failed to get ranks from DB: %s", __FUNCTION__, ex.what()); } return false; } bool cRankManager::RankExists(const AString & a_RankName) { ASSERT(m_IsInitialized); cCSLock Lock(m_CS); try { SQLite::Statement stmt(m_DB, "SELECT * FROM Rank WHERE Name = ?"); stmt.bind(1, a_RankName); if (stmt.executeStep()) { // The rank was found return true; } } catch (const SQLite::Exception & ex) { LOGWARNING("%s: Failed to query DB for rank %s: %s", __FUNCTION__, a_RankName.c_str(), ex.what()); } return false; } bool cRankManager::GroupExists(const AString & a_GroupName) { ASSERT(m_IsInitialized); cCSLock Lock(m_CS); try { SQLite::Statement stmt(m_DB, "SELECT * FROM PermGroup WHERE Name = ?"); stmt.bind(1, a_GroupName); if (stmt.executeStep()) { // The group was found return true; } } catch (const SQLite::Exception & ex) { LOGWARNING("%s: Failed to query DB for group %s: %s", __FUNCTION__, a_GroupName.c_str(), ex.what()); } return false; } bool cRankManager::IsPlayerRankSet(const cUUID & a_PlayerUUID) { ASSERT(m_IsInitialized); cCSLock Lock(m_CS); AString StrUUID = a_PlayerUUID.ToShortString(); try { SQLite::Statement stmt(m_DB, "SELECT * FROM PlayerRank WHERE PlayerUUID = ?"); stmt.bind(1, StrUUID); if (stmt.executeStep()) { // The player UUID was found, they have a rank return true; } } catch (const SQLite::Exception & ex) { LOGWARNING("%s: Failed to query DB for player UUID %s: %s", __FUNCTION__, StrUUID.c_str(), ex.what()); } return false; } bool cRankManager::IsGroupInRank(const AString & a_GroupName, const AString & a_RankName) { ASSERT(m_IsInitialized); cCSLock Lock(m_CS); try { SQLite::Statement stmt(m_DB, "SELECT * FROM Rank " "LEFT JOIN RankPermGroup ON Rank.RankID = RankPermGroup.RankID " "LEFT JOIN PermGroup ON PermGroup.PermGroupID = RankPermGroup.PermGroupID " "WHERE Rank.Name = ? AND PermGroup.Name = ?" ); stmt.bind(1, a_RankName); stmt.bind(2, a_GroupName); if (stmt.executeStep()) { // The group is in the rank return true; } } catch (const SQLite::Exception & ex) { LOGWARNING("%s: Failed to query DB: %s", __FUNCTION__, ex.what()); } return false; } bool cRankManager::IsPermissionInGroup(const AString & a_Permission, const AString & a_GroupName) { ASSERT(m_IsInitialized); cCSLock Lock(m_CS); try { SQLite::Statement stmt(m_DB, "SELECT * FROM PermissionItem " "LEFT JOIN PermGroup ON PermGroup.PermGroupID = PermissionItem.PermGroupID " "WHERE PermissionItem.Permission = ? AND PermGroup.Name = ?" ); stmt.bind(1, a_Permission); stmt.bind(2, a_GroupName); if (stmt.executeStep()) { // The permission is in the group return true; } } catch (const SQLite::Exception & ex) { LOGWARNING("%s: Failed to query DB: %s", __FUNCTION__, ex.what()); } return false; } bool cRankManager::IsRestrictionInGroup(const AString & a_Restriction, const AString & a_GroupName) { ASSERT(m_IsInitialized); cCSLock Lock(m_CS); try { SQLite::Statement stmt(m_DB, "SELECT * FROM RestrictionItem " "LEFT JOIN PermGroup ON PermGroup.PermGroupID = RestrictionItem.PermGroupID " "WHERE RestrictionItem.Permission = ? AND PermGroup.Name = ?" ); stmt.bind(1, a_Restriction); stmt.bind(2, a_GroupName); if (stmt.executeStep()) { // The restriction is in the group return true; } } catch (const SQLite::Exception & ex) { LOGWARNING("%s: Failed to query DB: %s", __FUNCTION__, ex.what()); } return false; } void cRankManager::NotifyNameUUID(const AString & a_PlayerName, const cUUID & a_UUID) { ASSERT(m_IsInitialized); cCSLock Lock(m_CS); try { SQLite::Statement stmt(m_DB, "UPDATE PlayerRank SET PlayerName = ? WHERE PlayerUUID = ?"); stmt.bind(1, a_PlayerName); stmt.bind(2, a_UUID.ToShortString()); stmt.exec(); } catch (const SQLite::Exception & ex) { LOGWARNING("%s: Failed to update DB: %s", __FUNCTION__, ex.what()); } } bool cRankManager::SetDefaultRank(const AString & a_RankName) { ASSERT(m_IsInitialized); cCSLock Lock(m_CS); try { // Find the rank's ID: int RankID = 0; { SQLite::Statement stmt(m_DB, "SELECT RankID FROM Rank WHERE Name = ?"); stmt.bind(1, a_RankName); if (!stmt.executeStep()) { LOGINFO("%s: Cannot set rank %s as the default, it does not exist.", __FUNCTION__, a_RankName.c_str()); return false; } } // Set the rank as the default: { SQLite::Statement stmt(m_DB, "UPDATE DefaultRank SET RankID = ?"); stmt.bind(1, RankID); if (stmt.exec() < 1) { // Failed to update, there might be none in the DB, try inserting: SQLite::Statement stmt2(m_DB, "INSERT INTO DefaultRank (RankID) VALUES (?)"); stmt2.bind(1, RankID); if (stmt2.exec() < 1) { LOGINFO("%s: Cannot update the default rank in the DB to %s.", __FUNCTION__, a_RankName.c_str()); return false; } } } // Set the internal cache: m_DefaultRank = a_RankName; return true; } catch (const SQLite::Exception & ex) { LOGWARNING("%s: Failed to update DB: %s", __FUNCTION__, ex.what()); return false; } } void cRankManager::ClearPlayerRanks(void) { ASSERT(m_IsInitialized); cCSLock Lock(m_CS); try { SQLite::Statement stmt(m_DB, "DELETE FROM PlayerRank"); stmt.exec(); } catch (SQLite::Exception & ex) { LOGWARNING("%s: Failed to remove / clear all players: %s", __FUNCTION__, ex.what()); } } bool cRankManager::UpdatePlayerName(const cUUID & a_PlayerUUID, const AString & a_NewPlayerName) { ASSERT(m_IsInitialized); cCSLock Lock(m_CS); AString StrUUID = a_PlayerUUID.ToShortString(); try { SQLite::Statement stmt(m_DB, "UPDATE PlayerRank SET PlayerName = ? WHERE PlayerUUID = ?"); stmt.bind(1, a_NewPlayerName); stmt.bind(2, StrUUID); if (stmt.exec() > 0) { // The player name was changed, returns true return true; } } catch (const SQLite::Exception & ex) { LOGWARNING("%s: Failed to update player name from UUID %s: %s", __FUNCTION__, StrUUID.c_str(), ex.what()); } return false; } bool cRankManager::AreDBTablesEmpty(void) { return ( IsDBTableEmpty("Rank") && IsDBTableEmpty("PlayerRank") && IsDBTableEmpty("PermGroup") && IsDBTableEmpty("RankPermGroup") && IsDBTableEmpty("PermissionItem") && IsDBTableEmpty("DefaultRank") ); } bool cRankManager::IsDBTableEmpty(const AString & a_TableName) { try { SQLite::Statement stmt(m_DB, "SELECT COUNT(*) FROM " + a_TableName); return (stmt.executeStep() && (stmt.getColumn(0).getInt() == 0)); } catch (const SQLite::Exception & ex) { LOGWARNING("%s: Failed to query DB: %s", __FUNCTION__, ex.what()); } return false; } void cRankManager::CreateDefaults(void) { // Wrap everything in a big transaction to speed things up: cMassChangeLock Lock(*this); // Create ranks: AddRank("Default", "", "", ""); AddRank("VIP", "", "", ""); AddRank("Operator", "", "", ""); AddRank("Admin", "", "", ""); // Create groups: AddGroup("Default"); AddGroup("Kick"); AddGroup("Teleport"); AddGroup("Everything"); // Add groups to ranks: AddGroupToRank("Default", "Default"); AddGroupToRank("Teleport", "VIP"); AddGroupToRank("Teleport", "Operator"); AddGroupToRank("Kick", "Operator"); AddGroupToRank("Everything", "Admin"); // Add permissions to groups: AddPermissionToGroup("core.help", "Default"); AddPermissionToGroup("core.build", "Default"); AddPermissionToGroup("core.teleport", "Teleport"); AddPermissionToGroup("core.kick", "Kick"); AddPermissionToGroup("*", "Everything"); // Set the default rank: SetDefaultRank("Default"); } bool cRankManager::DoesColumnExist(const char * a_TableName, const char * a_ColumnName) { try { SQLite::Statement stmt(m_DB, fmt::format(FMT_STRING("PRAGMA table_info({})"), a_TableName)); while (stmt.executeStep()) // Iterate over all table's columns { int NumColumns = stmt.getColumnCount(); for (int i = 0; i < NumColumns; i++) // Iterate over all reply's columns (table column's metadata) { auto column = stmt.getColumn(i); if (strcmp(column.getName(), "name") == 0) { if (NoCaseCompare(column.getText(), a_ColumnName) == 0) { // Colun found return true; } } } // for i - stmt.getColumns() } // while (stmt.executeStep()) } catch (const SQLite::Exception & ex) { LOGWARNING("%s: Failed to query DB: %s", __FUNCTION__, ex.what()); } return false; } void cRankManager::CreateColumnIfNotExists(const char * a_TableName, const char * a_ColumnName, const char * a_ColumnType) { // If the column already exists, bail out: if (DoesColumnExist(a_TableName, a_ColumnName)) { return; } // Add the column: try { m_DB.exec(fmt::format(FMT_STRING("ALTER TABLE {} ADD COLUMN {} {}"), a_TableName, a_ColumnName, a_ColumnType)); } catch (const SQLite::Exception & exc) { LOGWARNING("%s: Failed to query DB: %s", __FUNCTION__, exc.what()); } } ================================================ FILE: src/RankManager.h ================================================ // RankManager.h // Declares the cRankManager class that represents the rank manager responsible for assigning permissions and message visuals to players #pragma once #include "SQLiteCpp/Database.h" #include "SQLiteCpp/Transaction.h" class cUUID; class cMojangAPI; class cRankManager { public: /** Acquire this lock to perform mass changes. Improves performance by wrapping everything into a transaction. Makes sure that no other thread is accessing the DB. */ class cMassChangeLock { public: cMassChangeLock(cRankManager & a_RankManager) : m_Lock(a_RankManager.m_CS), m_Transaction(a_RankManager.m_DB) { } ~cMassChangeLock() { m_Transaction.commit(); } protected: cCSLock m_Lock; SQLite::Transaction m_Transaction; }; /** Creates the rank manager. Needs to be initialized before other use. */ cRankManager(void); ~cRankManager(); /** Initializes the rank manager. Performs migration and default-setting if no data is found in the DB. The a_MojangAPI param is used to keep player names in sync with UUIDs, since Mojang allows username changes. */ void Initialize(cMojangAPI & a_MojangAPI); /** Returns the name of the rank that the specified player has assigned to them. If the player has no rank assigned, returns an empty string (NOT the default rank). */ AString GetPlayerRankName(const cUUID & a_PlayerUUID); /** Returns the last name that the specified player has. An empty string is returned if the player isn't in the database. */ AString GetPlayerName(const cUUID & a_PlayerUUID); /** Returns the names of Groups that the specified player has assigned to them. */ AStringVector GetPlayerGroups(const cUUID & a_PlayerUUID); /** Returns the permissions that the specified player has assigned to them. If the player has no rank assigned to them, returns the default rank's permissions. */ AStringVector GetPlayerPermissions(const cUUID & a_PlayerUUID); /** Returns the restrictions that the specified player has assigned to them. If the player has no rank assigned to them, returns the default rank's restrictions. */ AStringVector GetPlayerRestrictions(const cUUID & a_PlayerUUID); /** Returns the names of groups that the specified rank has assigned to it. Returns an empty vector if the rank doesn't exist. */ AStringVector GetRankGroups(const AString & a_RankName); /** Returns the permissions that the specified group has assigned to it. Returns an empty vector if the group doesn't exist. */ AStringVector GetGroupPermissions(const AString & a_GroupName); /** Returns the restrictions that the specified group has assigned to it. Returns an empty vector if the group doesn't exist. */ AStringVector GetGroupRestrictions(const AString & a_GroupName); /** Returns all permissions that the specified rank has assigned to it, through all its groups. Returns an empty vector if the rank doesn't exist. Any non-existent groups are ignored. */ AStringVector GetRankPermissions(const AString & a_RankName); /** Returns all restrictions that the specified rank has assigned to it, through all its groups. Returns an empty vector if the rank doesn't exist. Any non-existent groups are ignored. */ AStringVector GetRankRestrictions(const AString & a_RankName); /** Returns the uuids of all defined players. The returned players are ordered by their name (NOT their UUIDs). */ std::vector GetAllPlayerUUIDs(void); /** Returns the names of all defined ranks. */ AStringVector GetAllRanks(void); /** Returns the names of all permission groups. */ AStringVector GetAllGroups(void); /** Returns all the distinct permissions that are stored in the DB. */ AStringVector GetAllPermissions(void); /** Returns all the distinct restrictions that are stored in the DB. */ AStringVector GetAllRestrictions(void); /** Returns all the distinct permissions and restrictions that are stored in the DB. */ AStringVector GetAllPermissionsRestrictions(void); /** Returns the message visuals (prefix, postfix, color) for the specified player. Returns true if the visuals were read from the DB, false if not (player not found etc). */ bool GetPlayerMsgVisuals( const cUUID & a_PlayerUUID, AString & a_MsgPrefix, AString & a_MsgSuffix, AString & a_MsgNameColorCode ); /** Adds a new rank. No action if the rank already exists. */ void AddRank( const AString & a_RankName, const AString & a_MsgPrefix, const AString & a_MsgSuffix, const AString & a_MsgNameColorCode ); /** Adds a new permission group. No action if such a group already exists. */ void AddGroup(const AString & a_GroupName); /** Bulk-adds groups. Group names that already exist are silently skipped. */ void AddGroups(const AStringVector & a_GroupNames); /** Adds the specified permission group to the specified rank. Fails if the rank or group names are not found. Returns true if successful, false on error. */ bool AddGroupToRank(const AString & a_GroupName, const AString & a_RankName); /** Adds the specified permission to the specified permission group. Fails if the permission group name is not found. Returns true if successful, false on error. */ bool AddPermissionToGroup(const AString & a_Permission, const AString & a_GroupName); /** Adds the specified restriction to the specified group. Fails if the group name is not found. Returns true if successful, false on error. */ bool AddRestrictionToGroup(const AString & a_Restriction, const AString & a_GroupName); /** Adds the specified permissions to the specified permission group. Fails if the permission group name is not found. Returns true if successful, false on error. */ bool AddPermissionsToGroup(const AStringVector & a_Permissions, const AString & a_GroupName); /** Adds the specified restrictions to the specified group. Fails if the group name is not found. Returns true if successful, false on error. */ bool AddRestrictionsToGroup(const AStringVector & a_Restrictions, const AString & a_GroupName); /** Removes the specified rank. All players assigned to that rank will be re-assigned to a_ReplacementRankName. If a_ReplacementRankName is empty or not a valid rank, the player will be removed from the DB, which means they will receive the default rank the next time they are queried. If the rank being removed is the default rank, the default will be changed to the replacement rank; the operation fails silently if there's no replacement. */ void RemoveRank(const AString & a_RankName, const AString & a_ReplacementRankName); /** Removes the specified group completely. The group will first be removed from all ranks using it, and then removed itself. */ void RemoveGroup(const AString & a_GroupName); /** Removes the specified group from the specified rank. The group will stay defined, even if no rank is using it. */ void RemoveGroupFromRank(const AString & a_GroupName, const AString & a_RankName); /** Removes the specified permission from the specified group. */ void RemovePermissionFromGroup(const AString & a_Permission, const AString & a_GroupName); /** Removes the specified restriction from the specified group. */ void RemoveRestrictionFromGroup(const AString & a_Restriction, const AString & a_GroupName); /** Renames the specified rank. No action if the rank name is not found. Fails if the new name is already used. Updates the cached m_DefaultRank if the default rank is being renamed. Returns true on success, false on failure. */ bool RenameRank(const AString & a_OldName, const AString & a_NewName); /** Renames the specified group. No action if the rank name is not found. Fails if the new name is already used. Returns true on success, false on failure. */ bool RenameGroup(const AString & a_OldName, const AString & a_NewName); /** Sets the specified player's rank. If the player already had rank assigned to them, it is overwritten with the new rank and name. Note that this doesn't change the cPlayer if the player is already connected, you need to update all the cPlayer instances manually. The PlayerName is provided for reference, so that GetRankPlayerNames() can work. */ void SetPlayerRank(const cUUID & a_PlayerUUID, const AString & a_PlayerName, const AString & a_RankName); /** Removes the player's rank assignment. The player is left without a rank. Note that this doesn't change the cPlayer instances for the already connected players, you need to update all the instances manually. No action if the player has no rank assigned to them already. */ void RemovePlayerRank(const cUUID & a_PlayerUUID); /** Sets the message visuals of an existing rank. No action if the rank name is not found. */ void SetRankVisuals( const AString & a_RankName, const AString & a_MsgPrefix, const AString & a_MsgSuffix, const AString & a_MsgNameColorCode ); /** Returns the message visuals of an existing rank. Returns true if successful, false on error (rank doesn't exist). */ bool GetRankVisuals( const AString & a_RankName, AString & a_MsgPrefix, AString & a_MsgSuffix, AString & a_MsgNameColorCode ); /** Returns true iff the specified rank exists in the DB. */ bool RankExists(const AString & a_RankName); /** Returns true iff the specified group exists in the DB. */ bool GroupExists(const AString & a_GroupName); /** Returns true iff the specified player has a rank assigned to them in the DB. */ bool IsPlayerRankSet(const cUUID & a_PlayerUUID); /** Returns true iff the specified rank contains the specified group. */ bool IsGroupInRank(const AString & a_GroupName, const AString & a_RankName); /** Returns true iff the specified group contains the specified permission. */ bool IsPermissionInGroup(const AString & a_Permission, const AString & a_GroupName); /** Returns true iff the specified group contains the specified restriction. */ bool IsRestrictionInGroup(const AString & a_Restriction, const AString & a_GroupName); /** Called by cMojangAPI whenever the playername-uuid pairing is discovered. Updates the DB. */ void NotifyNameUUID(const AString & a_PlayerName, const cUUID & a_UUID); /** Sets the specified rank as the default rank. Returns true on success, false on failure (rank not found). */ bool SetDefaultRank(const AString & a_RankName); /** Returns the name of the default rank. */ const AString & GetDefaultRank(void) const { return m_DefaultRank; } /** Removes all player ranks from the database. Note that this doesn't change the cPlayer instances for the already connected players, you need to update all the instances manually. */ void ClearPlayerRanks(void); /** Updates the playername that is saved with this uuid. Returns false if a error occurred */ bool UpdatePlayerName(const cUUID & a_PlayerUUID, const AString & a_NewPlayerName); protected: /** The database storage for all the data. Protected by m_CS. */ SQLite::Database m_DB; /** The name of the default rank. Kept as a cache so that queries for it don't need to go through the DB. */ AString m_DefaultRank; /** The mutex protecting m_DB and m_DefaultRank against multi-threaded access. */ cCriticalSection m_CS; /** Set to true once the manager is initialized. */ bool m_IsInitialized; /** Returns true if all the DB tables are empty, indicating a fresh new install. */ bool AreDBTablesEmpty(void); /** Returns true iff the specified DB table is empty. If there's an error while querying, returns false. */ bool IsDBTableEmpty(const AString & a_TableName); /** Creates a default set of ranks / groups / permissions. */ void CreateDefaults(void); /** Returns true if the specified column exists in the specified table. */ bool DoesColumnExist(const char * a_TableName, const char * a_ColumnName); /** If the specified table doesn't contain the specified column, it is added to the table. The column type is used only when creating the column, it is not used when checking for existence. */ void CreateColumnIfNotExists(const char * a_TableName, const char * a_ColumnName, const char * a_ColumnType = ""); } ; ================================================ FILE: src/Registries/BlockStates.cpp ================================================ #include "BlockStates.h" namespace Block { namespace AcaciaButton { BlockState AcaciaButton() { return 6451; } enum Face Face(const BlockState Block) { switch (Block.ID) { case 6458: case 6459: case 6460: case 6461: case 6462: case 6463: case 6464: case 6465: return Face::Ceiling; case 6442: case 6443: case 6444: case 6445: case 6446: case 6447: case 6448: case 6449: return Face::Floor; default: return Face::Wall; } } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 6446: case 6447: case 6454: case 6455: case 6462: case 6463: return eBlockFace::BLOCK_FACE_XM; case 6448: case 6449: case 6456: case 6457: case 6464: case 6465: return eBlockFace::BLOCK_FACE_XP; case 6442: case 6443: case 6450: case 6451: case 6458: case 6459: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } bool Powered(const BlockState Block) { switch (Block.ID) { case 6443: case 6445: case 6447: case 6449: case 6451: case 6453: case 6455: case 6457: case 6459: case 6461: case 6463: case 6465: return false; default: return true; } } } namespace AcaciaDoor { BlockState AcaciaDoor() { return 8941; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 8962: case 8963: case 8964: case 8965: case 8966: case 8967: case 8968: case 8969: case 8970: case 8971: case 8972: case 8973: case 8974: case 8975: case 8976: case 8977: return eBlockFace::BLOCK_FACE_XM; case 8978: case 8979: case 8980: case 8981: case 8982: case 8983: case 8984: case 8985: case 8986: case 8987: case 8988: case 8989: case 8990: case 8991: case 8992: case 8993: return eBlockFace::BLOCK_FACE_XP; case 8930: case 8931: case 8932: case 8933: case 8934: case 8935: case 8936: case 8937: case 8938: case 8939: case 8940: case 8941: case 8942: case 8943: case 8944: case 8945: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } enum Half Half(const BlockState Block) { switch (Block.ID) { case 8938: case 8939: case 8940: case 8941: case 8942: case 8943: case 8944: case 8945: case 8954: case 8955: case 8956: case 8957: case 8958: case 8959: case 8960: case 8961: case 8970: case 8971: case 8972: case 8973: case 8974: case 8975: case 8976: case 8977: case 8986: case 8987: case 8988: case 8989: case 8990: case 8991: case 8992: case 8993: return Half::Lower; default: return Half::Upper; } } enum Hinge Hinge(const BlockState Block) { switch (Block.ID) { case 8930: case 8931: case 8932: case 8933: case 8938: case 8939: case 8940: case 8941: case 8946: case 8947: case 8948: case 8949: case 8954: case 8955: case 8956: case 8957: case 8962: case 8963: case 8964: case 8965: case 8970: case 8971: case 8972: case 8973: case 8978: case 8979: case 8980: case 8981: case 8986: case 8987: case 8988: case 8989: return Hinge::Left; default: return Hinge::Right; } } bool Open(const BlockState Block) { switch (Block.ID) { case 8932: case 8933: case 8936: case 8937: case 8940: case 8941: case 8944: case 8945: case 8948: case 8949: case 8952: case 8953: case 8956: case 8957: case 8960: case 8961: case 8964: case 8965: case 8968: case 8969: case 8972: case 8973: case 8976: case 8977: case 8980: case 8981: case 8984: case 8985: case 8988: case 8989: case 8992: case 8993: return false; default: return true; } } bool Powered(const BlockState Block) { switch (Block.ID) { case 8931: case 8933: case 8935: case 8937: case 8939: case 8941: case 8943: case 8945: case 8947: case 8949: case 8951: case 8953: case 8955: case 8957: case 8959: case 8961: case 8963: case 8965: case 8967: case 8969: case 8971: case 8973: case 8975: case 8977: case 8979: case 8981: case 8983: case 8985: case 8987: case 8989: case 8991: case 8993: return false; default: return true; } } } namespace AcaciaFence { BlockState AcaciaFence() { return 8705; } bool East(const BlockState Block) { switch (Block.ID) { case 8692: case 8693: case 8696: case 8697: case 8700: case 8701: case 8704: case 8705: return false; default: return true; } } bool North(const BlockState Block) { switch (Block.ID) { case 8684: case 8685: case 8688: case 8689: case 8700: case 8701: case 8704: case 8705: return false; default: return true; } } bool South(const BlockState Block) { switch (Block.ID) { case 8680: case 8681: case 8688: case 8689: case 8696: case 8697: case 8704: case 8705: return false; default: return true; } } bool West(const BlockState Block) { switch (Block.ID) { case 8677: case 8681: case 8685: case 8689: case 8693: case 8697: case 8701: case 8705: return false; default: return true; } } } namespace AcaciaFenceGate { BlockState AcaciaFenceGate() { return 8521; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 8530: case 8531: case 8532: case 8533: case 8534: case 8535: case 8536: case 8537: return eBlockFace::BLOCK_FACE_XM; case 8538: case 8539: case 8540: case 8541: case 8542: case 8543: case 8544: case 8545: return eBlockFace::BLOCK_FACE_XP; case 8514: case 8515: case 8516: case 8517: case 8518: case 8519: case 8520: case 8521: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } bool InWall(const BlockState Block) { switch (Block.ID) { case 8518: case 8519: case 8520: case 8521: case 8526: case 8527: case 8528: case 8529: case 8534: case 8535: case 8536: case 8537: case 8542: case 8543: case 8544: case 8545: return false; default: return true; } } bool Open(const BlockState Block) { switch (Block.ID) { case 8516: case 8517: case 8520: case 8521: case 8524: case 8525: case 8528: case 8529: case 8532: case 8533: case 8536: case 8537: case 8540: case 8541: case 8544: case 8545: return false; default: return true; } } bool Powered(const BlockState Block) { switch (Block.ID) { case 8515: case 8517: case 8519: case 8521: case 8523: case 8525: case 8527: case 8529: case 8531: case 8533: case 8535: case 8537: case 8539: case 8541: case 8543: case 8545: return false; default: return true; } } } namespace AcaciaLeaves { BlockState AcaciaLeaves() { return 214; } unsigned char Distance(const BlockState Block) { switch (Block.ID) { case 201: case 202: return 1; case 203: case 204: return 2; case 205: case 206: return 3; case 207: case 208: return 4; case 209: case 210: return 5; case 211: case 212: return 6; default: return 7; } } bool Persistent(const BlockState Block) { switch (Block.ID) { case 202: case 204: case 206: case 208: case 210: case 212: case 214: return false; default: return true; } } } namespace AcaciaLog { BlockState AcaciaLog() { return 86; } enum Axis Axis(const BlockState Block) { switch (Block.ID) { case 85: return Axis::X; case 86: return Axis::Y; default: return Axis::Z; } } } namespace AcaciaPlanks { } namespace AcaciaPressurePlate { BlockState AcaciaPressurePlate() { return 3882; } bool Powered(const BlockState Block) { switch (Block.ID) { case 3882: return false; default: return true; } } } namespace AcaciaSapling { BlockState AcaciaSapling() { return 29; } unsigned char Stage(const BlockState Block) { switch (Block.ID) { case 29: return 0; default: return 1; } } } namespace AcaciaSign { BlockState AcaciaSign() { return 3478; } unsigned char Rotation(const BlockState Block) { switch (Block.ID) { case 3478: return 0; case 3480: return 1; case 3498: return 10; case 3500: return 11; case 3502: return 12; case 3504: return 13; case 3506: return 14; case 3508: return 15; case 3482: return 2; case 3484: return 3; case 3486: return 4; case 3488: return 5; case 3490: return 6; case 3492: return 7; case 3494: return 8; default: return 9; } } } namespace AcaciaSlab { BlockState AcaciaSlab() { return 8327; } enum Type Type(const BlockState Block) { switch (Block.ID) { case 8327: return Type::Bottom; case 8329: return Type::Double; default: return Type::Top; } } } namespace AcaciaStairs { BlockState AcaciaStairs() { return 7386; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 7416: case 7418: case 7420: case 7422: case 7424: case 7426: case 7428: case 7430: case 7432: case 7434: return eBlockFace::BLOCK_FACE_XM; case 7436: case 7438: case 7440: case 7442: case 7444: case 7446: case 7448: case 7450: case 7452: case 7454: return eBlockFace::BLOCK_FACE_XP; case 7376: case 7378: case 7380: case 7382: case 7384: case 7386: case 7388: case 7390: case 7392: case 7394: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } enum Half Half(const BlockState Block) { switch (Block.ID) { case 7386: case 7388: case 7390: case 7392: case 7394: case 7406: case 7408: case 7410: case 7412: case 7414: case 7426: case 7428: case 7430: case 7432: case 7434: case 7446: case 7448: case 7450: case 7452: case 7454: return Half::Bottom; default: return Half::Top; } } enum Shape Shape(const BlockState Block) { switch (Block.ID) { case 7378: case 7388: case 7398: case 7408: case 7418: case 7428: case 7438: case 7448: return Shape::InnerLeft; case 7380: case 7390: case 7400: case 7410: case 7420: case 7430: case 7440: case 7450: return Shape::InnerRight; case 7382: case 7392: case 7402: case 7412: case 7422: case 7432: case 7442: case 7452: return Shape::OuterLeft; case 7384: case 7394: case 7404: case 7414: case 7424: case 7434: case 7444: case 7454: return Shape::OuterRight; default: return Shape::Straight; } } } namespace AcaciaTrapdoor { BlockState AcaciaTrapdoor() { return 4382; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 4400: case 4402: case 4404: case 4406: case 4408: case 4410: case 4412: case 4414: return eBlockFace::BLOCK_FACE_XM; case 4416: case 4418: case 4420: case 4422: case 4424: case 4426: case 4428: case 4430: return eBlockFace::BLOCK_FACE_XP; case 4368: case 4370: case 4372: case 4374: case 4376: case 4378: case 4380: case 4382: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } enum Half Half(const BlockState Block) { switch (Block.ID) { case 4376: case 4378: case 4380: case 4382: case 4392: case 4394: case 4396: case 4398: case 4408: case 4410: case 4412: case 4414: case 4424: case 4426: case 4428: case 4430: return Half::Bottom; default: return Half::Top; } } bool Open(const BlockState Block) { switch (Block.ID) { case 4372: case 4374: case 4380: case 4382: case 4388: case 4390: case 4396: case 4398: case 4404: case 4406: case 4412: case 4414: case 4420: case 4422: case 4428: case 4430: return false; default: return true; } } bool Powered(const BlockState Block) { switch (Block.ID) { case 4370: case 4374: case 4378: case 4382: case 4386: case 4390: case 4394: case 4398: case 4402: case 4406: case 4410: case 4414: case 4418: case 4422: case 4426: case 4430: return false; default: return true; } } } namespace AcaciaWallSign { BlockState AcaciaWallSign() { return 3760; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 3764: return eBlockFace::BLOCK_FACE_XM; case 3766: return eBlockFace::BLOCK_FACE_XP; case 3760: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace AcaciaWood { BlockState AcaciaWood() { return 122; } enum Axis Axis(const BlockState Block) { switch (Block.ID) { case 121: return Axis::X; case 122: return Axis::Y; default: return Axis::Z; } } } namespace ActivatorRail { BlockState ActivatorRail() { return 6829; } bool Powered(const BlockState Block) { switch (Block.ID) { case 6829: case 6830: case 6831: case 6832: case 6833: case 6834: return false; default: return true; } } enum Shape Shape(const BlockState Block) { switch (Block.ID) { case 6825: case 6831: return Shape::AscendingEast; case 6827: case 6833: return Shape::AscendingNorth; case 6828: case 6834: return Shape::AscendingSouth; case 6826: case 6832: return Shape::AscendingWest; case 6824: case 6830: return Shape::EastWest; default: return Shape::NorthSouth; } } } namespace Air { } namespace Allium { } namespace AncientDebris { } namespace Andesite { } namespace AndesiteSlab { BlockState AndesiteSlab() { return 10846; } enum Type Type(const BlockState Block) { switch (Block.ID) { case 10846: return Type::Bottom; case 10848: return Type::Double; default: return Type::Top; } } } namespace AndesiteStairs { BlockState AndesiteStairs() { return 10480; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 10510: case 10512: case 10514: case 10516: case 10518: case 10520: case 10522: case 10524: case 10526: case 10528: return eBlockFace::BLOCK_FACE_XM; case 10530: case 10532: case 10534: case 10536: case 10538: case 10540: case 10542: case 10544: case 10546: case 10548: return eBlockFace::BLOCK_FACE_XP; case 10470: case 10472: case 10474: case 10476: case 10478: case 10480: case 10482: case 10484: case 10486: case 10488: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } enum Half Half(const BlockState Block) { switch (Block.ID) { case 10480: case 10482: case 10484: case 10486: case 10488: case 10500: case 10502: case 10504: case 10506: case 10508: case 10520: case 10522: case 10524: case 10526: case 10528: case 10540: case 10542: case 10544: case 10546: case 10548: return Half::Bottom; default: return Half::Top; } } enum Shape Shape(const BlockState Block) { switch (Block.ID) { case 10472: case 10482: case 10492: case 10502: case 10512: case 10522: case 10532: case 10542: return Shape::InnerLeft; case 10474: case 10484: case 10494: case 10504: case 10514: case 10524: case 10534: case 10544: return Shape::InnerRight; case 10476: case 10486: case 10496: case 10506: case 10516: case 10526: case 10536: case 10546: return Shape::OuterLeft; case 10478: case 10488: case 10498: case 10508: case 10518: case 10528: case 10538: case 10548: return Shape::OuterRight; default: return Shape::Straight; } } } namespace AndesiteWall { BlockState AndesiteWall() { return 13138; } enum East East(const BlockState Block) { switch (Block.ID) { case 13246: case 13247: case 13248: case 13252: case 13253: case 13254: case 13258: case 13259: case 13260: case 13264: case 13265: case 13266: case 13270: case 13271: case 13272: case 13276: case 13277: case 13278: case 13282: case 13283: case 13284: case 13288: case 13289: case 13290: case 13294: case 13295: case 13296: case 13300: case 13301: case 13302: case 13306: case 13307: case 13308: case 13312: case 13313: case 13314: case 13318: case 13319: case 13320: case 13324: case 13325: case 13326: case 13330: case 13331: case 13332: case 13336: case 13337: case 13338: case 13342: case 13343: case 13344: case 13348: case 13349: case 13350: return East::Low; case 13138: case 13139: case 13140: case 13144: case 13145: case 13146: case 13150: case 13151: case 13152: case 13156: case 13157: case 13158: case 13162: case 13163: case 13164: case 13168: case 13169: case 13170: case 13174: case 13175: case 13176: case 13180: case 13181: case 13182: case 13186: case 13187: case 13188: case 13192: case 13193: case 13194: case 13198: case 13199: case 13200: case 13204: case 13205: case 13206: case 13210: case 13211: case 13212: case 13216: case 13217: case 13218: case 13222: case 13223: case 13224: case 13228: case 13229: case 13230: case 13234: case 13235: case 13236: case 13240: case 13241: case 13242: return East::None; default: return East::Tall; } } enum North North(const BlockState Block) { switch (Block.ID) { case 13174: case 13175: case 13176: case 13180: case 13181: case 13182: case 13186: case 13187: case 13188: case 13192: case 13193: case 13194: case 13198: case 13199: case 13200: case 13204: case 13205: case 13206: case 13282: case 13283: case 13284: case 13288: case 13289: case 13290: case 13294: case 13295: case 13296: case 13300: case 13301: case 13302: case 13306: case 13307: case 13308: case 13312: case 13313: case 13314: case 13390: case 13391: case 13392: case 13396: case 13397: case 13398: case 13402: case 13403: case 13404: case 13408: case 13409: case 13410: case 13414: case 13415: case 13416: case 13420: case 13421: case 13422: return North::Low; case 13138: case 13139: case 13140: case 13144: case 13145: case 13146: case 13150: case 13151: case 13152: case 13156: case 13157: case 13158: case 13162: case 13163: case 13164: case 13168: case 13169: case 13170: case 13246: case 13247: case 13248: case 13252: case 13253: case 13254: case 13258: case 13259: case 13260: case 13264: case 13265: case 13266: case 13270: case 13271: case 13272: case 13276: case 13277: case 13278: case 13354: case 13355: case 13356: case 13360: case 13361: case 13362: case 13366: case 13367: case 13368: case 13372: case 13373: case 13374: case 13378: case 13379: case 13380: case 13384: case 13385: case 13386: return North::None; default: return North::Tall; } } enum South South(const BlockState Block) { switch (Block.ID) { case 13150: case 13151: case 13152: case 13156: case 13157: case 13158: case 13186: case 13187: case 13188: case 13192: case 13193: case 13194: case 13222: case 13223: case 13224: case 13228: case 13229: case 13230: case 13258: case 13259: case 13260: case 13264: case 13265: case 13266: case 13294: case 13295: case 13296: case 13300: case 13301: case 13302: case 13330: case 13331: case 13332: case 13336: case 13337: case 13338: case 13366: case 13367: case 13368: case 13372: case 13373: case 13374: case 13402: case 13403: case 13404: case 13408: case 13409: case 13410: case 13438: case 13439: case 13440: case 13444: case 13445: case 13446: return South::Low; case 13138: case 13139: case 13140: case 13144: case 13145: case 13146: case 13174: case 13175: case 13176: case 13180: case 13181: case 13182: case 13210: case 13211: case 13212: case 13216: case 13217: case 13218: case 13246: case 13247: case 13248: case 13252: case 13253: case 13254: case 13282: case 13283: case 13284: case 13288: case 13289: case 13290: case 13318: case 13319: case 13320: case 13324: case 13325: case 13326: case 13354: case 13355: case 13356: case 13360: case 13361: case 13362: case 13390: case 13391: case 13392: case 13396: case 13397: case 13398: case 13426: case 13427: case 13428: case 13432: case 13433: case 13434: return South::None; default: return South::Tall; } } bool Up(const BlockState Block) { switch (Block.ID) { case 13144: case 13145: case 13146: case 13156: case 13157: case 13158: case 13168: case 13169: case 13170: case 13180: case 13181: case 13182: case 13192: case 13193: case 13194: case 13204: case 13205: case 13206: case 13216: case 13217: case 13218: case 13228: case 13229: case 13230: case 13240: case 13241: case 13242: case 13252: case 13253: case 13254: case 13264: case 13265: case 13266: case 13276: case 13277: case 13278: case 13288: case 13289: case 13290: case 13300: case 13301: case 13302: case 13312: case 13313: case 13314: case 13324: case 13325: case 13326: case 13336: case 13337: case 13338: case 13348: case 13349: case 13350: case 13360: case 13361: case 13362: case 13372: case 13373: case 13374: case 13384: case 13385: case 13386: case 13396: case 13397: case 13398: case 13408: case 13409: case 13410: case 13420: case 13421: case 13422: case 13432: case 13433: case 13434: case 13444: case 13445: case 13446: case 13456: case 13457: case 13458: return false; default: return true; } } enum West West(const BlockState Block) { switch (Block.ID) { case 13139: case 13145: case 13151: case 13157: case 13163: case 13169: case 13175: case 13181: case 13187: case 13193: case 13199: case 13205: case 13211: case 13217: case 13223: case 13229: case 13235: case 13241: case 13247: case 13253: case 13259: case 13265: case 13271: case 13277: case 13283: case 13289: case 13295: case 13301: case 13307: case 13313: case 13319: case 13325: case 13331: case 13337: case 13343: case 13349: case 13355: case 13361: case 13367: case 13373: case 13379: case 13385: case 13391: case 13397: case 13403: case 13409: case 13415: case 13421: case 13427: case 13433: case 13439: case 13445: case 13451: case 13457: return West::Low; case 13138: case 13144: case 13150: case 13156: case 13162: case 13168: case 13174: case 13180: case 13186: case 13192: case 13198: case 13204: case 13210: case 13216: case 13222: case 13228: case 13234: case 13240: case 13246: case 13252: case 13258: case 13264: case 13270: case 13276: case 13282: case 13288: case 13294: case 13300: case 13306: case 13312: case 13318: case 13324: case 13330: case 13336: case 13342: case 13348: case 13354: case 13360: case 13366: case 13372: case 13378: case 13384: case 13390: case 13396: case 13402: case 13408: case 13414: case 13420: case 13426: case 13432: case 13438: case 13444: case 13450: case 13456: return West::None; default: return West::Tall; } } } namespace Anvil { BlockState Anvil() { return 6610; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 6612: return eBlockFace::BLOCK_FACE_XM; case 6613: return eBlockFace::BLOCK_FACE_XP; case 6610: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace AttachedMelonStem { BlockState AttachedMelonStem() { return 4768; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 4770: return eBlockFace::BLOCK_FACE_XM; case 4771: return eBlockFace::BLOCK_FACE_XP; case 4768: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace AttachedPumpkinStem { BlockState AttachedPumpkinStem() { return 4764; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 4766: return eBlockFace::BLOCK_FACE_XM; case 4767: return eBlockFace::BLOCK_FACE_XP; case 4764: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace AzureBluet { } namespace Bamboo { BlockState Bamboo() { return 9652; } unsigned char Age(const BlockState Block) { switch (Block.ID) { case 9652: case 9653: case 9654: case 9655: case 9656: case 9657: return 0; default: return 1; } } enum Leaves Leaves(const BlockState Block) { switch (Block.ID) { case 9656: case 9657: case 9662: case 9663: return Leaves::Large; case 9652: case 9653: case 9658: case 9659: return Leaves::None; default: return Leaves::Small; } } unsigned char Stage(const BlockState Block) { switch (Block.ID) { case 9652: case 9654: case 9656: case 9658: case 9660: case 9662: return 0; default: return 1; } } } namespace BambooSapling { } namespace Barrel { BlockState Barrel() { return 14792; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 14797: case 14798: return eBlockFace::BLOCK_FACE_XM; case 14793: case 14794: return eBlockFace::BLOCK_FACE_XP; case 14801: case 14802: return eBlockFace::BLOCK_FACE_YM; case 14799: case 14800: return eBlockFace::BLOCK_FACE_YP; case 14791: case 14792: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } bool Open(const BlockState Block) { switch (Block.ID) { case 14792: case 14794: case 14796: case 14798: case 14800: case 14802: return false; default: return true; } } } namespace Barrier { } namespace Basalt { BlockState Basalt() { return 4003; } enum Axis Axis(const BlockState Block) { switch (Block.ID) { case 4002: return Axis::X; case 4003: return Axis::Y; default: return Axis::Z; } } } namespace Beacon { } namespace Bedrock { } namespace BeeNest { BlockState BeeNest() { return 15776; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 15788: case 15789: case 15790: case 15791: case 15792: case 15793: return eBlockFace::BLOCK_FACE_XM; case 15794: case 15795: case 15796: case 15797: case 15798: case 15799: return eBlockFace::BLOCK_FACE_XP; case 15776: case 15777: case 15778: case 15779: case 15780: case 15781: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } unsigned char HoneyLevel(const BlockState Block) { switch (Block.ID) { case 15776: case 15782: case 15788: case 15794: return 0; case 15777: case 15783: case 15789: case 15795: return 1; case 15778: case 15784: case 15790: case 15796: return 2; case 15779: case 15785: case 15791: case 15797: return 3; case 15780: case 15786: case 15792: case 15798: return 4; default: return 5; } } } namespace Beehive { BlockState Beehive() { return 15800; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 15812: case 15813: case 15814: case 15815: case 15816: case 15817: return eBlockFace::BLOCK_FACE_XM; case 15818: case 15819: case 15820: case 15821: case 15822: case 15823: return eBlockFace::BLOCK_FACE_XP; case 15800: case 15801: case 15802: case 15803: case 15804: case 15805: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } unsigned char HoneyLevel(const BlockState Block) { switch (Block.ID) { case 15800: case 15806: case 15812: case 15818: return 0; case 15801: case 15807: case 15813: case 15819: return 1; case 15802: case 15808: case 15814: case 15820: return 2; case 15803: case 15809: case 15815: case 15821: return 3; case 15804: case 15810: case 15816: case 15822: return 4; default: return 5; } } } namespace Beetroots { BlockState Beetroots() { return 9219; } unsigned char Age(const BlockState Block) { switch (Block.ID) { case 9219: return 0; case 9220: return 1; case 9221: return 2; default: return 3; } } } namespace Bell { BlockState Bell() { return 14855; } enum Attachment Attachment(const BlockState Block) { switch (Block.ID) { case 14862: case 14863: case 14864: case 14865: case 14866: case 14867: case 14868: case 14869: return Attachment::Ceiling; case 14878: case 14879: case 14880: case 14881: case 14882: case 14883: case 14884: case 14885: return Attachment::DoubleWall; case 14854: case 14855: case 14856: case 14857: case 14858: case 14859: case 14860: case 14861: return Attachment::Floor; default: return Attachment::SingleWall; } } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 14858: case 14859: case 14866: case 14867: case 14874: case 14875: case 14882: case 14883: return eBlockFace::BLOCK_FACE_XM; case 14860: case 14861: case 14868: case 14869: case 14876: case 14877: case 14884: case 14885: return eBlockFace::BLOCK_FACE_XP; case 14854: case 14855: case 14862: case 14863: case 14870: case 14871: case 14878: case 14879: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } bool Powered(const BlockState Block) { switch (Block.ID) { case 14855: case 14857: case 14859: case 14861: case 14863: case 14865: case 14867: case 14869: case 14871: case 14873: case 14875: case 14877: case 14879: case 14881: case 14883: case 14885: return false; default: return true; } } } namespace BirchButton { BlockState BirchButton() { return 6403; } enum Face Face(const BlockState Block) { switch (Block.ID) { case 6410: case 6411: case 6412: case 6413: case 6414: case 6415: case 6416: case 6417: return Face::Ceiling; case 6394: case 6395: case 6396: case 6397: case 6398: case 6399: case 6400: case 6401: return Face::Floor; default: return Face::Wall; } } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 6398: case 6399: case 6406: case 6407: case 6414: case 6415: return eBlockFace::BLOCK_FACE_XM; case 6400: case 6401: case 6408: case 6409: case 6416: case 6417: return eBlockFace::BLOCK_FACE_XP; case 6394: case 6395: case 6402: case 6403: case 6410: case 6411: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } bool Powered(const BlockState Block) { switch (Block.ID) { case 6395: case 6397: case 6399: case 6401: case 6403: case 6405: case 6407: case 6409: case 6411: case 6413: case 6415: case 6417: return false; default: return true; } } } namespace BirchDoor { BlockState BirchDoor() { return 8813; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 8834: case 8835: case 8836: case 8837: case 8838: case 8839: case 8840: case 8841: case 8842: case 8843: case 8844: case 8845: case 8846: case 8847: case 8848: case 8849: return eBlockFace::BLOCK_FACE_XM; case 8850: case 8851: case 8852: case 8853: case 8854: case 8855: case 8856: case 8857: case 8858: case 8859: case 8860: case 8861: case 8862: case 8863: case 8864: case 8865: return eBlockFace::BLOCK_FACE_XP; case 8802: case 8803: case 8804: case 8805: case 8806: case 8807: case 8808: case 8809: case 8810: case 8811: case 8812: case 8813: case 8814: case 8815: case 8816: case 8817: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } enum Half Half(const BlockState Block) { switch (Block.ID) { case 8810: case 8811: case 8812: case 8813: case 8814: case 8815: case 8816: case 8817: case 8826: case 8827: case 8828: case 8829: case 8830: case 8831: case 8832: case 8833: case 8842: case 8843: case 8844: case 8845: case 8846: case 8847: case 8848: case 8849: case 8858: case 8859: case 8860: case 8861: case 8862: case 8863: case 8864: case 8865: return Half::Lower; default: return Half::Upper; } } enum Hinge Hinge(const BlockState Block) { switch (Block.ID) { case 8802: case 8803: case 8804: case 8805: case 8810: case 8811: case 8812: case 8813: case 8818: case 8819: case 8820: case 8821: case 8826: case 8827: case 8828: case 8829: case 8834: case 8835: case 8836: case 8837: case 8842: case 8843: case 8844: case 8845: case 8850: case 8851: case 8852: case 8853: case 8858: case 8859: case 8860: case 8861: return Hinge::Left; default: return Hinge::Right; } } bool Open(const BlockState Block) { switch (Block.ID) { case 8804: case 8805: case 8808: case 8809: case 8812: case 8813: case 8816: case 8817: case 8820: case 8821: case 8824: case 8825: case 8828: case 8829: case 8832: case 8833: case 8836: case 8837: case 8840: case 8841: case 8844: case 8845: case 8848: case 8849: case 8852: case 8853: case 8856: case 8857: case 8860: case 8861: case 8864: case 8865: return false; default: return true; } } bool Powered(const BlockState Block) { switch (Block.ID) { case 8803: case 8805: case 8807: case 8809: case 8811: case 8813: case 8815: case 8817: case 8819: case 8821: case 8823: case 8825: case 8827: case 8829: case 8831: case 8833: case 8835: case 8837: case 8839: case 8841: case 8843: case 8845: case 8847: case 8849: case 8851: case 8853: case 8855: case 8857: case 8859: case 8861: case 8863: case 8865: return false; default: return true; } } } namespace BirchFence { BlockState BirchFence() { return 8641; } bool East(const BlockState Block) { switch (Block.ID) { case 8628: case 8629: case 8632: case 8633: case 8636: case 8637: case 8640: case 8641: return false; default: return true; } } bool North(const BlockState Block) { switch (Block.ID) { case 8620: case 8621: case 8624: case 8625: case 8636: case 8637: case 8640: case 8641: return false; default: return true; } } bool South(const BlockState Block) { switch (Block.ID) { case 8616: case 8617: case 8624: case 8625: case 8632: case 8633: case 8640: case 8641: return false; default: return true; } } bool West(const BlockState Block) { switch (Block.ID) { case 8613: case 8617: case 8621: case 8625: case 8629: case 8633: case 8637: case 8641: return false; default: return true; } } } namespace BirchFenceGate { BlockState BirchFenceGate() { return 8457; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 8466: case 8467: case 8468: case 8469: case 8470: case 8471: case 8472: case 8473: return eBlockFace::BLOCK_FACE_XM; case 8474: case 8475: case 8476: case 8477: case 8478: case 8479: case 8480: case 8481: return eBlockFace::BLOCK_FACE_XP; case 8450: case 8451: case 8452: case 8453: case 8454: case 8455: case 8456: case 8457: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } bool InWall(const BlockState Block) { switch (Block.ID) { case 8454: case 8455: case 8456: case 8457: case 8462: case 8463: case 8464: case 8465: case 8470: case 8471: case 8472: case 8473: case 8478: case 8479: case 8480: case 8481: return false; default: return true; } } bool Open(const BlockState Block) { switch (Block.ID) { case 8452: case 8453: case 8456: case 8457: case 8460: case 8461: case 8464: case 8465: case 8468: case 8469: case 8472: case 8473: case 8476: case 8477: case 8480: case 8481: return false; default: return true; } } bool Powered(const BlockState Block) { switch (Block.ID) { case 8451: case 8453: case 8455: case 8457: case 8459: case 8461: case 8463: case 8465: case 8467: case 8469: case 8471: case 8473: case 8475: case 8477: case 8479: case 8481: return false; default: return true; } } } namespace BirchLeaves { BlockState BirchLeaves() { return 186; } unsigned char Distance(const BlockState Block) { switch (Block.ID) { case 173: case 174: return 1; case 175: case 176: return 2; case 177: case 178: return 3; case 179: case 180: return 4; case 181: case 182: return 5; case 183: case 184: return 6; default: return 7; } } bool Persistent(const BlockState Block) { switch (Block.ID) { case 174: case 176: case 178: case 180: case 182: case 184: case 186: return false; default: return true; } } } namespace BirchLog { BlockState BirchLog() { return 80; } enum Axis Axis(const BlockState Block) { switch (Block.ID) { case 79: return Axis::X; case 80: return Axis::Y; default: return Axis::Z; } } } namespace BirchPlanks { } namespace BirchPressurePlate { BlockState BirchPressurePlate() { return 3878; } bool Powered(const BlockState Block) { switch (Block.ID) { case 3878: return false; default: return true; } } } namespace BirchSapling { BlockState BirchSapling() { return 25; } unsigned char Stage(const BlockState Block) { switch (Block.ID) { case 25: return 0; default: return 1; } } } namespace BirchSign { BlockState BirchSign() { return 3446; } unsigned char Rotation(const BlockState Block) { switch (Block.ID) { case 3446: return 0; case 3448: return 1; case 3466: return 10; case 3468: return 11; case 3470: return 12; case 3472: return 13; case 3474: return 14; case 3476: return 15; case 3450: return 2; case 3452: return 3; case 3454: return 4; case 3456: return 5; case 3458: return 6; case 3460: return 7; case 3462: return 8; default: return 9; } } } namespace BirchSlab { BlockState BirchSlab() { return 8315; } enum Type Type(const BlockState Block) { switch (Block.ID) { case 8315: return Type::Bottom; case 8317: return Type::Double; default: return Type::Top; } } } namespace BirchStairs { BlockState BirchStairs() { return 5495; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 5525: case 5527: case 5529: case 5531: case 5533: case 5535: case 5537: case 5539: case 5541: case 5543: return eBlockFace::BLOCK_FACE_XM; case 5545: case 5547: case 5549: case 5551: case 5553: case 5555: case 5557: case 5559: case 5561: case 5563: return eBlockFace::BLOCK_FACE_XP; case 5485: case 5487: case 5489: case 5491: case 5493: case 5495: case 5497: case 5499: case 5501: case 5503: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } enum Half Half(const BlockState Block) { switch (Block.ID) { case 5495: case 5497: case 5499: case 5501: case 5503: case 5515: case 5517: case 5519: case 5521: case 5523: case 5535: case 5537: case 5539: case 5541: case 5543: case 5555: case 5557: case 5559: case 5561: case 5563: return Half::Bottom; default: return Half::Top; } } enum Shape Shape(const BlockState Block) { switch (Block.ID) { case 5487: case 5497: case 5507: case 5517: case 5527: case 5537: case 5547: case 5557: return Shape::InnerLeft; case 5489: case 5499: case 5509: case 5519: case 5529: case 5539: case 5549: case 5559: return Shape::InnerRight; case 5491: case 5501: case 5511: case 5521: case 5531: case 5541: case 5551: case 5561: return Shape::OuterLeft; case 5493: case 5503: case 5513: case 5523: case 5533: case 5543: case 5553: case 5563: return Shape::OuterRight; default: return Shape::Straight; } } } namespace BirchTrapdoor { BlockState BirchTrapdoor() { return 4254; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 4272: case 4274: case 4276: case 4278: case 4280: case 4282: case 4284: case 4286: return eBlockFace::BLOCK_FACE_XM; case 4288: case 4290: case 4292: case 4294: case 4296: case 4298: case 4300: case 4302: return eBlockFace::BLOCK_FACE_XP; case 4240: case 4242: case 4244: case 4246: case 4248: case 4250: case 4252: case 4254: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } enum Half Half(const BlockState Block) { switch (Block.ID) { case 4248: case 4250: case 4252: case 4254: case 4264: case 4266: case 4268: case 4270: case 4280: case 4282: case 4284: case 4286: case 4296: case 4298: case 4300: case 4302: return Half::Bottom; default: return Half::Top; } } bool Open(const BlockState Block) { switch (Block.ID) { case 4244: case 4246: case 4252: case 4254: case 4260: case 4262: case 4268: case 4270: case 4276: case 4278: case 4284: case 4286: case 4292: case 4294: case 4300: case 4302: return false; default: return true; } } bool Powered(const BlockState Block) { switch (Block.ID) { case 4242: case 4246: case 4250: case 4254: case 4258: case 4262: case 4266: case 4270: case 4274: case 4278: case 4282: case 4286: case 4290: case 4294: case 4298: case 4302: return false; default: return true; } } } namespace BirchWallSign { BlockState BirchWallSign() { return 3752; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 3756: return eBlockFace::BLOCK_FACE_XM; case 3758: return eBlockFace::BLOCK_FACE_XP; case 3752: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace BirchWood { BlockState BirchWood() { return 116; } enum Axis Axis(const BlockState Block) { switch (Block.ID) { case 115: return Axis::X; case 116: return Axis::Y; default: return Axis::Z; } } } namespace BlackBanner { BlockState BlackBanner() { return 8137; } unsigned char Rotation(const BlockState Block) { switch (Block.ID) { case 8137: return 0; case 8138: return 1; case 8147: return 10; case 8148: return 11; case 8149: return 12; case 8150: return 13; case 8151: return 14; case 8152: return 15; case 8139: return 2; case 8140: return 3; case 8141: return 4; case 8142: return 5; case 8143: return 6; case 8144: return 7; case 8145: return 8; default: return 9; } } } namespace BlackBed { BlockState BlackBed() { return 1292; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 1297: case 1298: case 1299: case 1300: return eBlockFace::BLOCK_FACE_XM; case 1301: case 1302: case 1303: case 1304: return eBlockFace::BLOCK_FACE_XP; case 1289: case 1290: case 1291: case 1292: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } bool Occupied(const BlockState Block) { switch (Block.ID) { case 1291: case 1292: case 1295: case 1296: case 1299: case 1300: case 1303: case 1304: return false; default: return true; } } enum Part Part(const BlockState Block) { switch (Block.ID) { case 1290: case 1292: case 1294: case 1296: case 1298: case 1300: case 1302: case 1304: return Part::Foot; default: return Part::Head; } } } namespace BlackCarpet { } namespace BlackConcrete { } namespace BlackConcretePowder { } namespace BlackGlazedTerracotta { BlockState BlackGlazedTerracotta() { return 9434; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 9436: return eBlockFace::BLOCK_FACE_XM; case 9437: return eBlockFace::BLOCK_FACE_XP; case 9434: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace BlackShulkerBox { BlockState BlackShulkerBox() { return 9372; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 9371: return eBlockFace::BLOCK_FACE_XM; case 9369: return eBlockFace::BLOCK_FACE_XP; case 9373: return eBlockFace::BLOCK_FACE_YM; case 9372: return eBlockFace::BLOCK_FACE_YP; case 9368: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace BlackStainedGlass { } namespace BlackStainedGlassPane { BlockState BlackStainedGlassPane() { return 7374; } bool East(const BlockState Block) { switch (Block.ID) { case 7361: case 7362: case 7365: case 7366: case 7369: case 7370: case 7373: case 7374: return false; default: return true; } } bool North(const BlockState Block) { switch (Block.ID) { case 7353: case 7354: case 7357: case 7358: case 7369: case 7370: case 7373: case 7374: return false; default: return true; } } bool South(const BlockState Block) { switch (Block.ID) { case 7349: case 7350: case 7357: case 7358: case 7365: case 7366: case 7373: case 7374: return false; default: return true; } } bool West(const BlockState Block) { switch (Block.ID) { case 7346: case 7350: case 7354: case 7358: case 7362: case 7366: case 7370: case 7374: return false; default: return true; } } } namespace BlackTerracotta { } namespace BlackWallBanner { BlockState BlackWallBanner() { return 8213; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 8215: return eBlockFace::BLOCK_FACE_XM; case 8216: return eBlockFace::BLOCK_FACE_XP; case 8213: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace BlackWool { } namespace Blackstone { } namespace BlackstoneSlab { BlockState BlackstoneSlab() { return 16247; } enum Type Type(const BlockState Block) { switch (Block.ID) { case 16247: return Type::Bottom; case 16249: return Type::Double; default: return Type::Top; } } } namespace BlackstoneStairs { BlockState BlackstoneStairs() { return 15851; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 15881: case 15883: case 15885: case 15887: case 15889: case 15891: case 15893: case 15895: case 15897: case 15899: return eBlockFace::BLOCK_FACE_XM; case 15901: case 15903: case 15905: case 15907: case 15909: case 15911: case 15913: case 15915: case 15917: case 15919: return eBlockFace::BLOCK_FACE_XP; case 15841: case 15843: case 15845: case 15847: case 15849: case 15851: case 15853: case 15855: case 15857: case 15859: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } enum Half Half(const BlockState Block) { switch (Block.ID) { case 15851: case 15853: case 15855: case 15857: case 15859: case 15871: case 15873: case 15875: case 15877: case 15879: case 15891: case 15893: case 15895: case 15897: case 15899: case 15911: case 15913: case 15915: case 15917: case 15919: return Half::Bottom; default: return Half::Top; } } enum Shape Shape(const BlockState Block) { switch (Block.ID) { case 15843: case 15853: case 15863: case 15873: case 15883: case 15893: case 15903: case 15913: return Shape::InnerLeft; case 15845: case 15855: case 15865: case 15875: case 15885: case 15895: case 15905: case 15915: return Shape::InnerRight; case 15847: case 15857: case 15867: case 15877: case 15887: case 15897: case 15907: case 15917: return Shape::OuterLeft; case 15849: case 15859: case 15869: case 15879: case 15889: case 15899: case 15909: case 15919: return Shape::OuterRight; default: return Shape::Straight; } } } namespace BlackstoneWall { BlockState BlackstoneWall() { return 15923; } enum East East(const BlockState Block) { switch (Block.ID) { case 16031: case 16032: case 16033: case 16037: case 16038: case 16039: case 16043: case 16044: case 16045: case 16049: case 16050: case 16051: case 16055: case 16056: case 16057: case 16061: case 16062: case 16063: case 16067: case 16068: case 16069: case 16073: case 16074: case 16075: case 16079: case 16080: case 16081: case 16085: case 16086: case 16087: case 16091: case 16092: case 16093: case 16097: case 16098: case 16099: case 16103: case 16104: case 16105: case 16109: case 16110: case 16111: case 16115: case 16116: case 16117: case 16121: case 16122: case 16123: case 16127: case 16128: case 16129: case 16133: case 16134: case 16135: return East::Low; case 15923: case 15924: case 15925: case 15929: case 15930: case 15931: case 15935: case 15936: case 15937: case 15941: case 15942: case 15943: case 15947: case 15948: case 15949: case 15953: case 15954: case 15955: case 15959: case 15960: case 15961: case 15965: case 15966: case 15967: case 15971: case 15972: case 15973: case 15977: case 15978: case 15979: case 15983: case 15984: case 15985: case 15989: case 15990: case 15991: case 15995: case 15996: case 15997: case 16001: case 16002: case 16003: case 16007: case 16008: case 16009: case 16013: case 16014: case 16015: case 16019: case 16020: case 16021: case 16025: case 16026: case 16027: return East::None; default: return East::Tall; } } enum North North(const BlockState Block) { switch (Block.ID) { case 15959: case 15960: case 15961: case 15965: case 15966: case 15967: case 15971: case 15972: case 15973: case 15977: case 15978: case 15979: case 15983: case 15984: case 15985: case 15989: case 15990: case 15991: case 16067: case 16068: case 16069: case 16073: case 16074: case 16075: case 16079: case 16080: case 16081: case 16085: case 16086: case 16087: case 16091: case 16092: case 16093: case 16097: case 16098: case 16099: case 16175: case 16176: case 16177: case 16181: case 16182: case 16183: case 16187: case 16188: case 16189: case 16193: case 16194: case 16195: case 16199: case 16200: case 16201: case 16205: case 16206: case 16207: return North::Low; case 15923: case 15924: case 15925: case 15929: case 15930: case 15931: case 15935: case 15936: case 15937: case 15941: case 15942: case 15943: case 15947: case 15948: case 15949: case 15953: case 15954: case 15955: case 16031: case 16032: case 16033: case 16037: case 16038: case 16039: case 16043: case 16044: case 16045: case 16049: case 16050: case 16051: case 16055: case 16056: case 16057: case 16061: case 16062: case 16063: case 16139: case 16140: case 16141: case 16145: case 16146: case 16147: case 16151: case 16152: case 16153: case 16157: case 16158: case 16159: case 16163: case 16164: case 16165: case 16169: case 16170: case 16171: return North::None; default: return North::Tall; } } enum South South(const BlockState Block) { switch (Block.ID) { case 15935: case 15936: case 15937: case 15941: case 15942: case 15943: case 15971: case 15972: case 15973: case 15977: case 15978: case 15979: case 16007: case 16008: case 16009: case 16013: case 16014: case 16015: case 16043: case 16044: case 16045: case 16049: case 16050: case 16051: case 16079: case 16080: case 16081: case 16085: case 16086: case 16087: case 16115: case 16116: case 16117: case 16121: case 16122: case 16123: case 16151: case 16152: case 16153: case 16157: case 16158: case 16159: case 16187: case 16188: case 16189: case 16193: case 16194: case 16195: case 16223: case 16224: case 16225: case 16229: case 16230: case 16231: return South::Low; case 15923: case 15924: case 15925: case 15929: case 15930: case 15931: case 15959: case 15960: case 15961: case 15965: case 15966: case 15967: case 15995: case 15996: case 15997: case 16001: case 16002: case 16003: case 16031: case 16032: case 16033: case 16037: case 16038: case 16039: case 16067: case 16068: case 16069: case 16073: case 16074: case 16075: case 16103: case 16104: case 16105: case 16109: case 16110: case 16111: case 16139: case 16140: case 16141: case 16145: case 16146: case 16147: case 16175: case 16176: case 16177: case 16181: case 16182: case 16183: case 16211: case 16212: case 16213: case 16217: case 16218: case 16219: return South::None; default: return South::Tall; } } bool Up(const BlockState Block) { switch (Block.ID) { case 15929: case 15930: case 15931: case 15941: case 15942: case 15943: case 15953: case 15954: case 15955: case 15965: case 15966: case 15967: case 15977: case 15978: case 15979: case 15989: case 15990: case 15991: case 16001: case 16002: case 16003: case 16013: case 16014: case 16015: case 16025: case 16026: case 16027: case 16037: case 16038: case 16039: case 16049: case 16050: case 16051: case 16061: case 16062: case 16063: case 16073: case 16074: case 16075: case 16085: case 16086: case 16087: case 16097: case 16098: case 16099: case 16109: case 16110: case 16111: case 16121: case 16122: case 16123: case 16133: case 16134: case 16135: case 16145: case 16146: case 16147: case 16157: case 16158: case 16159: case 16169: case 16170: case 16171: case 16181: case 16182: case 16183: case 16193: case 16194: case 16195: case 16205: case 16206: case 16207: case 16217: case 16218: case 16219: case 16229: case 16230: case 16231: case 16241: case 16242: case 16243: return false; default: return true; } } enum West West(const BlockState Block) { switch (Block.ID) { case 15924: case 15930: case 15936: case 15942: case 15948: case 15954: case 15960: case 15966: case 15972: case 15978: case 15984: case 15990: case 15996: case 16002: case 16008: case 16014: case 16020: case 16026: case 16032: case 16038: case 16044: case 16050: case 16056: case 16062: case 16068: case 16074: case 16080: case 16086: case 16092: case 16098: case 16104: case 16110: case 16116: case 16122: case 16128: case 16134: case 16140: case 16146: case 16152: case 16158: case 16164: case 16170: case 16176: case 16182: case 16188: case 16194: case 16200: case 16206: case 16212: case 16218: case 16224: case 16230: case 16236: case 16242: return West::Low; case 15923: case 15929: case 15935: case 15941: case 15947: case 15953: case 15959: case 15965: case 15971: case 15977: case 15983: case 15989: case 15995: case 16001: case 16007: case 16013: case 16019: case 16025: case 16031: case 16037: case 16043: case 16049: case 16055: case 16061: case 16067: case 16073: case 16079: case 16085: case 16091: case 16097: case 16103: case 16109: case 16115: case 16121: case 16127: case 16133: case 16139: case 16145: case 16151: case 16157: case 16163: case 16169: case 16175: case 16181: case 16187: case 16193: case 16199: case 16205: case 16211: case 16217: case 16223: case 16229: case 16235: case 16241: return West::None; default: return West::Tall; } } } namespace BlastFurnace { BlockState BlastFurnace() { return 14812; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 14815: case 14816: return eBlockFace::BLOCK_FACE_XM; case 14817: case 14818: return eBlockFace::BLOCK_FACE_XP; case 14811: case 14812: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } bool Lit(const BlockState Block) { switch (Block.ID) { case 14812: case 14814: case 14816: case 14818: return false; default: return true; } } } namespace BlueBanner { BlockState BlueBanner() { return 8073; } unsigned char Rotation(const BlockState Block) { switch (Block.ID) { case 8073: return 0; case 8074: return 1; case 8083: return 10; case 8084: return 11; case 8085: return 12; case 8086: return 13; case 8087: return 14; case 8088: return 15; case 8075: return 2; case 8076: return 3; case 8077: return 4; case 8078: return 5; case 8079: return 6; case 8080: return 7; case 8081: return 8; default: return 9; } } } namespace BlueBed { BlockState BlueBed() { return 1228; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 1233: case 1234: case 1235: case 1236: return eBlockFace::BLOCK_FACE_XM; case 1237: case 1238: case 1239: case 1240: return eBlockFace::BLOCK_FACE_XP; case 1225: case 1226: case 1227: case 1228: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } bool Occupied(const BlockState Block) { switch (Block.ID) { case 1227: case 1228: case 1231: case 1232: case 1235: case 1236: case 1239: case 1240: return false; default: return true; } } enum Part Part(const BlockState Block) { switch (Block.ID) { case 1226: case 1228: case 1230: case 1232: case 1234: case 1236: case 1238: case 1240: return Part::Foot; default: return Part::Head; } } } namespace BlueCarpet { } namespace BlueConcrete { } namespace BlueConcretePowder { } namespace BlueGlazedTerracotta { BlockState BlueGlazedTerracotta() { return 9418; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 9420: return eBlockFace::BLOCK_FACE_XM; case 9421: return eBlockFace::BLOCK_FACE_XP; case 9418: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace BlueIce { } namespace BlueOrchid { } namespace BlueShulkerBox { BlockState BlueShulkerBox() { return 9348; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 9347: return eBlockFace::BLOCK_FACE_XM; case 9345: return eBlockFace::BLOCK_FACE_XP; case 9349: return eBlockFace::BLOCK_FACE_YM; case 9348: return eBlockFace::BLOCK_FACE_YP; case 9344: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace BlueStainedGlass { } namespace BlueStainedGlassPane { BlockState BlueStainedGlassPane() { return 7246; } bool East(const BlockState Block) { switch (Block.ID) { case 7233: case 7234: case 7237: case 7238: case 7241: case 7242: case 7245: case 7246: return false; default: return true; } } bool North(const BlockState Block) { switch (Block.ID) { case 7225: case 7226: case 7229: case 7230: case 7241: case 7242: case 7245: case 7246: return false; default: return true; } } bool South(const BlockState Block) { switch (Block.ID) { case 7221: case 7222: case 7229: case 7230: case 7237: case 7238: case 7245: case 7246: return false; default: return true; } } bool West(const BlockState Block) { switch (Block.ID) { case 7218: case 7222: case 7226: case 7230: case 7234: case 7238: case 7242: case 7246: return false; default: return true; } } } namespace BlueTerracotta { } namespace BlueWallBanner { BlockState BlueWallBanner() { return 8197; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 8199: return eBlockFace::BLOCK_FACE_XM; case 8200: return eBlockFace::BLOCK_FACE_XP; case 8197: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace BlueWool { } namespace BoneBlock { BlockState BoneBlock() { return 9257; } enum Axis Axis(const BlockState Block) { switch (Block.ID) { case 9256: return Axis::X; case 9257: return Axis::Y; default: return Axis::Z; } } } namespace Bookshelf { } namespace BrainCoral { } namespace BrainCoralBlock { } namespace BrainCoralFan { } namespace BrainCoralWallFan { BlockState BrainCoralWallFan() { return 9608; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 9613: return eBlockFace::BLOCK_FACE_XM; case 9615: return eBlockFace::BLOCK_FACE_XP; case 9609: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace BrewingStand { BlockState BrewingStand() { return 5140; } bool HasBottle_0(const BlockState Block) { switch (Block.ID) { case 5137: case 5138: case 5139: case 5140: return false; default: return true; } } bool HasBottle_1(const BlockState Block) { switch (Block.ID) { case 5135: case 5136: case 5139: case 5140: return false; default: return true; } } bool HasBottle_2(const BlockState Block) { switch (Block.ID) { case 5134: case 5136: case 5138: case 5140: return false; default: return true; } } } namespace BrickSlab { BlockState BrickSlab() { return 8375; } enum Type Type(const BlockState Block) { switch (Block.ID) { case 8375: return Type::Bottom; case 8377: return Type::Double; default: return Type::Top; } } } namespace BrickStairs { BlockState BrickStairs() { return 4863; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 4893: case 4895: case 4897: case 4899: case 4901: case 4903: case 4905: case 4907: case 4909: case 4911: return eBlockFace::BLOCK_FACE_XM; case 4913: case 4915: case 4917: case 4919: case 4921: case 4923: case 4925: case 4927: case 4929: case 4931: return eBlockFace::BLOCK_FACE_XP; case 4853: case 4855: case 4857: case 4859: case 4861: case 4863: case 4865: case 4867: case 4869: case 4871: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } enum Half Half(const BlockState Block) { switch (Block.ID) { case 4863: case 4865: case 4867: case 4869: case 4871: case 4883: case 4885: case 4887: case 4889: case 4891: case 4903: case 4905: case 4907: case 4909: case 4911: case 4923: case 4925: case 4927: case 4929: case 4931: return Half::Bottom; default: return Half::Top; } } enum Shape Shape(const BlockState Block) { switch (Block.ID) { case 4855: case 4865: case 4875: case 4885: case 4895: case 4905: case 4915: case 4925: return Shape::InnerLeft; case 4857: case 4867: case 4877: case 4887: case 4897: case 4907: case 4917: case 4927: return Shape::InnerRight; case 4859: case 4869: case 4879: case 4889: case 4899: case 4909: case 4919: case 4929: return Shape::OuterLeft; case 4861: case 4871: case 4881: case 4891: case 4901: case 4911: case 4921: case 4931: return Shape::OuterRight; default: return Shape::Straight; } } } namespace BrickWall { BlockState BrickWall() { return 10870; } enum East East(const BlockState Block) { switch (Block.ID) { case 10978: case 10979: case 10980: case 10984: case 10985: case 10986: case 10990: case 10991: case 10992: case 10996: case 10997: case 10998: case 11002: case 11003: case 11004: case 11008: case 11009: case 11010: case 11014: case 11015: case 11016: case 11020: case 11021: case 11022: case 11026: case 11027: case 11028: case 11032: case 11033: case 11034: case 11038: case 11039: case 11040: case 11044: case 11045: case 11046: case 11050: case 11051: case 11052: case 11056: case 11057: case 11058: case 11062: case 11063: case 11064: case 11068: case 11069: case 11070: case 11074: case 11075: case 11076: case 11080: case 11081: case 11082: return East::Low; case 10870: case 10871: case 10872: case 10876: case 10877: case 10878: case 10882: case 10883: case 10884: case 10888: case 10889: case 10890: case 10894: case 10895: case 10896: case 10900: case 10901: case 10902: case 10906: case 10907: case 10908: case 10912: case 10913: case 10914: case 10918: case 10919: case 10920: case 10924: case 10925: case 10926: case 10930: case 10931: case 10932: case 10936: case 10937: case 10938: case 10942: case 10943: case 10944: case 10948: case 10949: case 10950: case 10954: case 10955: case 10956: case 10960: case 10961: case 10962: case 10966: case 10967: case 10968: case 10972: case 10973: case 10974: return East::None; default: return East::Tall; } } enum North North(const BlockState Block) { switch (Block.ID) { case 10906: case 10907: case 10908: case 10912: case 10913: case 10914: case 10918: case 10919: case 10920: case 10924: case 10925: case 10926: case 10930: case 10931: case 10932: case 10936: case 10937: case 10938: case 11014: case 11015: case 11016: case 11020: case 11021: case 11022: case 11026: case 11027: case 11028: case 11032: case 11033: case 11034: case 11038: case 11039: case 11040: case 11044: case 11045: case 11046: case 11122: case 11123: case 11124: case 11128: case 11129: case 11130: case 11134: case 11135: case 11136: case 11140: case 11141: case 11142: case 11146: case 11147: case 11148: case 11152: case 11153: case 11154: return North::Low; case 10870: case 10871: case 10872: case 10876: case 10877: case 10878: case 10882: case 10883: case 10884: case 10888: case 10889: case 10890: case 10894: case 10895: case 10896: case 10900: case 10901: case 10902: case 10978: case 10979: case 10980: case 10984: case 10985: case 10986: case 10990: case 10991: case 10992: case 10996: case 10997: case 10998: case 11002: case 11003: case 11004: case 11008: case 11009: case 11010: case 11086: case 11087: case 11088: case 11092: case 11093: case 11094: case 11098: case 11099: case 11100: case 11104: case 11105: case 11106: case 11110: case 11111: case 11112: case 11116: case 11117: case 11118: return North::None; default: return North::Tall; } } enum South South(const BlockState Block) { switch (Block.ID) { case 10882: case 10883: case 10884: case 10888: case 10889: case 10890: case 10918: case 10919: case 10920: case 10924: case 10925: case 10926: case 10954: case 10955: case 10956: case 10960: case 10961: case 10962: case 10990: case 10991: case 10992: case 10996: case 10997: case 10998: case 11026: case 11027: case 11028: case 11032: case 11033: case 11034: case 11062: case 11063: case 11064: case 11068: case 11069: case 11070: case 11098: case 11099: case 11100: case 11104: case 11105: case 11106: case 11134: case 11135: case 11136: case 11140: case 11141: case 11142: case 11170: case 11171: case 11172: case 11176: case 11177: case 11178: return South::Low; case 10870: case 10871: case 10872: case 10876: case 10877: case 10878: case 10906: case 10907: case 10908: case 10912: case 10913: case 10914: case 10942: case 10943: case 10944: case 10948: case 10949: case 10950: case 10978: case 10979: case 10980: case 10984: case 10985: case 10986: case 11014: case 11015: case 11016: case 11020: case 11021: case 11022: case 11050: case 11051: case 11052: case 11056: case 11057: case 11058: case 11086: case 11087: case 11088: case 11092: case 11093: case 11094: case 11122: case 11123: case 11124: case 11128: case 11129: case 11130: case 11158: case 11159: case 11160: case 11164: case 11165: case 11166: return South::None; default: return South::Tall; } } bool Up(const BlockState Block) { switch (Block.ID) { case 10876: case 10877: case 10878: case 10888: case 10889: case 10890: case 10900: case 10901: case 10902: case 10912: case 10913: case 10914: case 10924: case 10925: case 10926: case 10936: case 10937: case 10938: case 10948: case 10949: case 10950: case 10960: case 10961: case 10962: case 10972: case 10973: case 10974: case 10984: case 10985: case 10986: case 10996: case 10997: case 10998: case 11008: case 11009: case 11010: case 11020: case 11021: case 11022: case 11032: case 11033: case 11034: case 11044: case 11045: case 11046: case 11056: case 11057: case 11058: case 11068: case 11069: case 11070: case 11080: case 11081: case 11082: case 11092: case 11093: case 11094: case 11104: case 11105: case 11106: case 11116: case 11117: case 11118: case 11128: case 11129: case 11130: case 11140: case 11141: case 11142: case 11152: case 11153: case 11154: case 11164: case 11165: case 11166: case 11176: case 11177: case 11178: case 11188: case 11189: case 11190: return false; default: return true; } } enum West West(const BlockState Block) { switch (Block.ID) { case 10871: case 10877: case 10883: case 10889: case 10895: case 10901: case 10907: case 10913: case 10919: case 10925: case 10931: case 10937: case 10943: case 10949: case 10955: case 10961: case 10967: case 10973: case 10979: case 10985: case 10991: case 10997: case 11003: case 11009: case 11015: case 11021: case 11027: case 11033: case 11039: case 11045: case 11051: case 11057: case 11063: case 11069: case 11075: case 11081: case 11087: case 11093: case 11099: case 11105: case 11111: case 11117: case 11123: case 11129: case 11135: case 11141: case 11147: case 11153: case 11159: case 11165: case 11171: case 11177: case 11183: case 11189: return West::Low; case 10870: case 10876: case 10882: case 10888: case 10894: case 10900: case 10906: case 10912: case 10918: case 10924: case 10930: case 10936: case 10942: case 10948: case 10954: case 10960: case 10966: case 10972: case 10978: case 10984: case 10990: case 10996: case 11002: case 11008: case 11014: case 11020: case 11026: case 11032: case 11038: case 11044: case 11050: case 11056: case 11062: case 11068: case 11074: case 11080: case 11086: case 11092: case 11098: case 11104: case 11110: case 11116: case 11122: case 11128: case 11134: case 11140: case 11146: case 11152: case 11158: case 11164: case 11170: case 11176: case 11182: case 11188: return West::None; default: return West::Tall; } } } namespace Bricks { } namespace BrownBanner { BlockState BrownBanner() { return 8089; } unsigned char Rotation(const BlockState Block) { switch (Block.ID) { case 8089: return 0; case 8090: return 1; case 8099: return 10; case 8100: return 11; case 8101: return 12; case 8102: return 13; case 8103: return 14; case 8104: return 15; case 8091: return 2; case 8092: return 3; case 8093: return 4; case 8094: return 5; case 8095: return 6; case 8096: return 7; case 8097: return 8; default: return 9; } } } namespace BrownBed { BlockState BrownBed() { return 1244; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 1249: case 1250: case 1251: case 1252: return eBlockFace::BLOCK_FACE_XM; case 1253: case 1254: case 1255: case 1256: return eBlockFace::BLOCK_FACE_XP; case 1241: case 1242: case 1243: case 1244: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } bool Occupied(const BlockState Block) { switch (Block.ID) { case 1243: case 1244: case 1247: case 1248: case 1251: case 1252: case 1255: case 1256: return false; default: return true; } } enum Part Part(const BlockState Block) { switch (Block.ID) { case 1242: case 1244: case 1246: case 1248: case 1250: case 1252: case 1254: case 1256: return Part::Foot; default: return Part::Head; } } } namespace BrownCarpet { } namespace BrownConcrete { } namespace BrownConcretePowder { } namespace BrownGlazedTerracotta { BlockState BrownGlazedTerracotta() { return 9422; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 9424: return eBlockFace::BLOCK_FACE_XM; case 9425: return eBlockFace::BLOCK_FACE_XP; case 9422: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace BrownMushroom { } namespace BrownMushroomBlock { BlockState BrownMushroomBlock() { return 4505; } bool Down(const BlockState Block) { switch (Block.ID) { case 4537: case 4538: case 4539: case 4540: case 4541: case 4542: case 4543: case 4544: case 4545: case 4546: case 4547: case 4548: case 4549: case 4550: case 4551: case 4552: case 4553: case 4554: case 4555: case 4556: case 4557: case 4558: case 4559: case 4560: case 4561: case 4562: case 4563: case 4564: case 4565: case 4566: case 4567: case 4568: return false; default: return true; } } bool East(const BlockState Block) { switch (Block.ID) { case 4521: case 4522: case 4523: case 4524: case 4525: case 4526: case 4527: case 4528: case 4529: case 4530: case 4531: case 4532: case 4533: case 4534: case 4535: case 4536: case 4553: case 4554: case 4555: case 4556: case 4557: case 4558: case 4559: case 4560: case 4561: case 4562: case 4563: case 4564: case 4565: case 4566: case 4567: case 4568: return false; default: return true; } } bool North(const BlockState Block) { switch (Block.ID) { case 4513: case 4514: case 4515: case 4516: case 4517: case 4518: case 4519: case 4520: case 4529: case 4530: case 4531: case 4532: case 4533: case 4534: case 4535: case 4536: case 4545: case 4546: case 4547: case 4548: case 4549: case 4550: case 4551: case 4552: case 4561: case 4562: case 4563: case 4564: case 4565: case 4566: case 4567: case 4568: return false; default: return true; } } bool South(const BlockState Block) { switch (Block.ID) { case 4509: case 4510: case 4511: case 4512: case 4517: case 4518: case 4519: case 4520: case 4525: case 4526: case 4527: case 4528: case 4533: case 4534: case 4535: case 4536: case 4541: case 4542: case 4543: case 4544: case 4549: case 4550: case 4551: case 4552: case 4557: case 4558: case 4559: case 4560: case 4565: case 4566: case 4567: case 4568: return false; default: return true; } } bool Up(const BlockState Block) { switch (Block.ID) { case 4507: case 4508: case 4511: case 4512: case 4515: case 4516: case 4519: case 4520: case 4523: case 4524: case 4527: case 4528: case 4531: case 4532: case 4535: case 4536: case 4539: case 4540: case 4543: case 4544: case 4547: case 4548: case 4551: case 4552: case 4555: case 4556: case 4559: case 4560: case 4563: case 4564: case 4567: case 4568: return false; default: return true; } } bool West(const BlockState Block) { switch (Block.ID) { case 4506: case 4508: case 4510: case 4512: case 4514: case 4516: case 4518: case 4520: case 4522: case 4524: case 4526: case 4528: case 4530: case 4532: case 4534: case 4536: case 4538: case 4540: case 4542: case 4544: case 4546: case 4548: case 4550: case 4552: case 4554: case 4556: case 4558: case 4560: case 4562: case 4564: case 4566: case 4568: return false; default: return true; } } } namespace BrownShulkerBox { BlockState BrownShulkerBox() { return 9354; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 9353: return eBlockFace::BLOCK_FACE_XM; case 9351: return eBlockFace::BLOCK_FACE_XP; case 9355: return eBlockFace::BLOCK_FACE_YM; case 9354: return eBlockFace::BLOCK_FACE_YP; case 9350: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace BrownStainedGlass { } namespace BrownStainedGlassPane { BlockState BrownStainedGlassPane() { return 7278; } bool East(const BlockState Block) { switch (Block.ID) { case 7265: case 7266: case 7269: case 7270: case 7273: case 7274: case 7277: case 7278: return false; default: return true; } } bool North(const BlockState Block) { switch (Block.ID) { case 7257: case 7258: case 7261: case 7262: case 7273: case 7274: case 7277: case 7278: return false; default: return true; } } bool South(const BlockState Block) { switch (Block.ID) { case 7253: case 7254: case 7261: case 7262: case 7269: case 7270: case 7277: case 7278: return false; default: return true; } } bool West(const BlockState Block) { switch (Block.ID) { case 7250: case 7254: case 7258: case 7262: case 7266: case 7270: case 7274: case 7278: return false; default: return true; } } } namespace BrownTerracotta { } namespace BrownWallBanner { BlockState BrownWallBanner() { return 8201; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 8203: return eBlockFace::BLOCK_FACE_XM; case 8204: return eBlockFace::BLOCK_FACE_XP; case 8201: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace BrownWool { } namespace BubbleColumn { BlockState BubbleColumn() { return 9667; } bool Drag(const BlockState Block) { switch (Block.ID) { case 9668: return false; default: return true; } } } namespace BubbleCoral { } namespace BubbleCoralBlock { } namespace BubbleCoralFan { } namespace BubbleCoralWallFan { BlockState BubbleCoralWallFan() { return 9616; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 9621: return eBlockFace::BLOCK_FACE_XM; case 9623: return eBlockFace::BLOCK_FACE_XP; case 9617: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace Cactus { BlockState Cactus() { return 3931; } unsigned char Age(const BlockState Block) { switch (Block.ID) { case 3931: return 0; case 3932: return 1; case 3941: return 10; case 3942: return 11; case 3943: return 12; case 3944: return 13; case 3945: return 14; case 3946: return 15; case 3933: return 2; case 3934: return 3; case 3935: return 4; case 3936: return 5; case 3937: return 6; case 3938: return 7; case 3939: return 8; default: return 9; } } } namespace Cake { BlockState Cake() { return 4024; } unsigned char Bites(const BlockState Block) { switch (Block.ID) { case 4024: return 0; case 4025: return 1; case 4026: return 2; case 4027: return 3; case 4028: return 4; case 4029: return 5; default: return 6; } } } namespace Campfire { BlockState Campfire() { return 14893; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 14907: case 14909: case 14911: case 14913: return eBlockFace::BLOCK_FACE_XM; case 14915: case 14917: case 14919: case 14921: return eBlockFace::BLOCK_FACE_XP; case 14891: case 14893: case 14895: case 14897: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } bool Lit(const BlockState Block) { switch (Block.ID) { case 14895: case 14897: case 14903: case 14905: case 14911: case 14913: case 14919: case 14921: return false; default: return true; } } bool SignalFire(const BlockState Block) { switch (Block.ID) { case 14893: case 14897: case 14901: case 14905: case 14909: case 14913: case 14917: case 14921: return false; default: return true; } } } namespace Carrots { BlockState Carrots() { return 6330; } unsigned char Age(const BlockState Block) { switch (Block.ID) { case 6330: return 0; case 6331: return 1; case 6332: return 2; case 6333: return 3; case 6334: return 4; case 6335: return 5; case 6336: return 6; default: return 7; } } } namespace CartographyTable { } namespace CarvedPumpkin { BlockState CarvedPumpkin() { return 4016; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 4018: return eBlockFace::BLOCK_FACE_XM; case 4019: return eBlockFace::BLOCK_FACE_XP; case 4016: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace Cauldron { BlockState Cauldron() { return 5141; } unsigned char Level(const BlockState Block) { switch (Block.ID) { case 5141: return 0; case 5142: return 1; case 5143: return 2; default: return 3; } } } namespace CaveAir { } namespace Chain { } namespace ChainCommandBlock { BlockState ChainCommandBlock() { return 9243; } bool Conditional(const BlockState Block) { switch (Block.ID) { case 9243: case 9244: case 9245: case 9246: case 9247: case 9248: return false; default: return true; } } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 9240: case 9246: return eBlockFace::BLOCK_FACE_XM; case 9238: case 9244: return eBlockFace::BLOCK_FACE_XP; case 9242: case 9248: return eBlockFace::BLOCK_FACE_YM; case 9241: case 9247: return eBlockFace::BLOCK_FACE_YP; case 9237: case 9243: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace Chest { BlockState Chest() { return 2035; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 2047: case 2049: case 2051: return eBlockFace::BLOCK_FACE_XM; case 2053: case 2055: case 2057: return eBlockFace::BLOCK_FACE_XP; case 2035: case 2037: case 2039: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } enum Type Type(const BlockState Block) { switch (Block.ID) { case 2037: case 2043: case 2049: case 2055: return Type::Left; case 2039: case 2045: case 2051: case 2057: return Type::Right; default: return Type::Single; } } } namespace ChippedAnvil { BlockState ChippedAnvil() { return 6614; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 6616: return eBlockFace::BLOCK_FACE_XM; case 6617: return eBlockFace::BLOCK_FACE_XP; case 6614: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace ChiseledNetherBricks { } namespace ChiseledPolishedBlackstone { } namespace ChiseledQuartzBlock { } namespace ChiseledRedSandstone { } namespace ChiseledSandstone { } namespace ChiseledStoneBricks { } namespace ChorusFlower { BlockState ChorusFlower() { return 9128; } unsigned char Age(const BlockState Block) { switch (Block.ID) { case 9128: return 0; case 9129: return 1; case 9130: return 2; case 9131: return 3; case 9132: return 4; default: return 5; } } } namespace ChorusPlant { BlockState ChorusPlant() { return 9127; } bool Down(const BlockState Block) { switch (Block.ID) { case 9096: case 9097: case 9098: case 9099: case 9100: case 9101: case 9102: case 9103: case 9104: case 9105: case 9106: case 9107: case 9108: case 9109: case 9110: case 9111: case 9112: case 9113: case 9114: case 9115: case 9116: case 9117: case 9118: case 9119: case 9120: case 9121: case 9122: case 9123: case 9124: case 9125: case 9126: case 9127: return false; default: return true; } } bool East(const BlockState Block) { switch (Block.ID) { case 9080: case 9081: case 9082: case 9083: case 9084: case 9085: case 9086: case 9087: case 9088: case 9089: case 9090: case 9091: case 9092: case 9093: case 9094: case 9095: case 9112: case 9113: case 9114: case 9115: case 9116: case 9117: case 9118: case 9119: case 9120: case 9121: case 9122: case 9123: case 9124: case 9125: case 9126: case 9127: return false; default: return true; } } bool North(const BlockState Block) { switch (Block.ID) { case 9072: case 9073: case 9074: case 9075: case 9076: case 9077: case 9078: case 9079: case 9088: case 9089: case 9090: case 9091: case 9092: case 9093: case 9094: case 9095: case 9104: case 9105: case 9106: case 9107: case 9108: case 9109: case 9110: case 9111: case 9120: case 9121: case 9122: case 9123: case 9124: case 9125: case 9126: case 9127: return false; default: return true; } } bool South(const BlockState Block) { switch (Block.ID) { case 9068: case 9069: case 9070: case 9071: case 9076: case 9077: case 9078: case 9079: case 9084: case 9085: case 9086: case 9087: case 9092: case 9093: case 9094: case 9095: case 9100: case 9101: case 9102: case 9103: case 9108: case 9109: case 9110: case 9111: case 9116: case 9117: case 9118: case 9119: case 9124: case 9125: case 9126: case 9127: return false; default: return true; } } bool Up(const BlockState Block) { switch (Block.ID) { case 9066: case 9067: case 9070: case 9071: case 9074: case 9075: case 9078: case 9079: case 9082: case 9083: case 9086: case 9087: case 9090: case 9091: case 9094: case 9095: case 9098: case 9099: case 9102: case 9103: case 9106: case 9107: case 9110: case 9111: case 9114: case 9115: case 9118: case 9119: case 9122: case 9123: case 9126: case 9127: return false; default: return true; } } bool West(const BlockState Block) { switch (Block.ID) { case 9065: case 9067: case 9069: case 9071: case 9073: case 9075: case 9077: case 9079: case 9081: case 9083: case 9085: case 9087: case 9089: case 9091: case 9093: case 9095: case 9097: case 9099: case 9101: case 9103: case 9105: case 9107: case 9109: case 9111: case 9113: case 9115: case 9117: case 9119: case 9121: case 9123: case 9125: case 9127: return false; default: return true; } } } namespace Clay { } namespace CoalBlock { } namespace CoalOre { } namespace CoarseDirt { } namespace Cobblestone { } namespace CobblestoneSlab { BlockState CobblestoneSlab() { return 8369; } enum Type Type(const BlockState Block) { switch (Block.ID) { case 8369: return Type::Bottom; case 8371: return Type::Double; default: return Type::Top; } } } namespace CobblestoneStairs { BlockState CobblestoneStairs() { return 3666; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 3696: case 3698: case 3700: case 3702: case 3704: case 3706: case 3708: case 3710: case 3712: case 3714: return eBlockFace::BLOCK_FACE_XM; case 3716: case 3718: case 3720: case 3722: case 3724: case 3726: case 3728: case 3730: case 3732: case 3734: return eBlockFace::BLOCK_FACE_XP; case 3656: case 3658: case 3660: case 3662: case 3664: case 3666: case 3668: case 3670: case 3672: case 3674: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } enum Half Half(const BlockState Block) { switch (Block.ID) { case 3666: case 3668: case 3670: case 3672: case 3674: case 3686: case 3688: case 3690: case 3692: case 3694: case 3706: case 3708: case 3710: case 3712: case 3714: case 3726: case 3728: case 3730: case 3732: case 3734: return Half::Bottom; default: return Half::Top; } } enum Shape Shape(const BlockState Block) { switch (Block.ID) { case 3658: case 3668: case 3678: case 3688: case 3698: case 3708: case 3718: case 3728: return Shape::InnerLeft; case 3660: case 3670: case 3680: case 3690: case 3700: case 3710: case 3720: case 3730: return Shape::InnerRight; case 3662: case 3672: case 3682: case 3692: case 3702: case 3712: case 3722: case 3732: return Shape::OuterLeft; case 3664: case 3674: case 3684: case 3694: case 3704: case 3714: case 3724: case 3734: return Shape::OuterRight; default: return Shape::Straight; } } } namespace CobblestoneWall { BlockState CobblestoneWall() { return 5660; } enum East East(const BlockState Block) { switch (Block.ID) { case 5768: case 5769: case 5770: case 5774: case 5775: case 5776: case 5780: case 5781: case 5782: case 5786: case 5787: case 5788: case 5792: case 5793: case 5794: case 5798: case 5799: case 5800: case 5804: case 5805: case 5806: case 5810: case 5811: case 5812: case 5816: case 5817: case 5818: case 5822: case 5823: case 5824: case 5828: case 5829: case 5830: case 5834: case 5835: case 5836: case 5840: case 5841: case 5842: case 5846: case 5847: case 5848: case 5852: case 5853: case 5854: case 5858: case 5859: case 5860: case 5864: case 5865: case 5866: case 5870: case 5871: case 5872: return East::Low; case 5660: case 5661: case 5662: case 5666: case 5667: case 5668: case 5672: case 5673: case 5674: case 5678: case 5679: case 5680: case 5684: case 5685: case 5686: case 5690: case 5691: case 5692: case 5696: case 5697: case 5698: case 5702: case 5703: case 5704: case 5708: case 5709: case 5710: case 5714: case 5715: case 5716: case 5720: case 5721: case 5722: case 5726: case 5727: case 5728: case 5732: case 5733: case 5734: case 5738: case 5739: case 5740: case 5744: case 5745: case 5746: case 5750: case 5751: case 5752: case 5756: case 5757: case 5758: case 5762: case 5763: case 5764: return East::None; default: return East::Tall; } } enum North North(const BlockState Block) { switch (Block.ID) { case 5696: case 5697: case 5698: case 5702: case 5703: case 5704: case 5708: case 5709: case 5710: case 5714: case 5715: case 5716: case 5720: case 5721: case 5722: case 5726: case 5727: case 5728: case 5804: case 5805: case 5806: case 5810: case 5811: case 5812: case 5816: case 5817: case 5818: case 5822: case 5823: case 5824: case 5828: case 5829: case 5830: case 5834: case 5835: case 5836: case 5912: case 5913: case 5914: case 5918: case 5919: case 5920: case 5924: case 5925: case 5926: case 5930: case 5931: case 5932: case 5936: case 5937: case 5938: case 5942: case 5943: case 5944: return North::Low; case 5660: case 5661: case 5662: case 5666: case 5667: case 5668: case 5672: case 5673: case 5674: case 5678: case 5679: case 5680: case 5684: case 5685: case 5686: case 5690: case 5691: case 5692: case 5768: case 5769: case 5770: case 5774: case 5775: case 5776: case 5780: case 5781: case 5782: case 5786: case 5787: case 5788: case 5792: case 5793: case 5794: case 5798: case 5799: case 5800: case 5876: case 5877: case 5878: case 5882: case 5883: case 5884: case 5888: case 5889: case 5890: case 5894: case 5895: case 5896: case 5900: case 5901: case 5902: case 5906: case 5907: case 5908: return North::None; default: return North::Tall; } } enum South South(const BlockState Block) { switch (Block.ID) { case 5672: case 5673: case 5674: case 5678: case 5679: case 5680: case 5708: case 5709: case 5710: case 5714: case 5715: case 5716: case 5744: case 5745: case 5746: case 5750: case 5751: case 5752: case 5780: case 5781: case 5782: case 5786: case 5787: case 5788: case 5816: case 5817: case 5818: case 5822: case 5823: case 5824: case 5852: case 5853: case 5854: case 5858: case 5859: case 5860: case 5888: case 5889: case 5890: case 5894: case 5895: case 5896: case 5924: case 5925: case 5926: case 5930: case 5931: case 5932: case 5960: case 5961: case 5962: case 5966: case 5967: case 5968: return South::Low; case 5660: case 5661: case 5662: case 5666: case 5667: case 5668: case 5696: case 5697: case 5698: case 5702: case 5703: case 5704: case 5732: case 5733: case 5734: case 5738: case 5739: case 5740: case 5768: case 5769: case 5770: case 5774: case 5775: case 5776: case 5804: case 5805: case 5806: case 5810: case 5811: case 5812: case 5840: case 5841: case 5842: case 5846: case 5847: case 5848: case 5876: case 5877: case 5878: case 5882: case 5883: case 5884: case 5912: case 5913: case 5914: case 5918: case 5919: case 5920: case 5948: case 5949: case 5950: case 5954: case 5955: case 5956: return South::None; default: return South::Tall; } } bool Up(const BlockState Block) { switch (Block.ID) { case 5666: case 5667: case 5668: case 5678: case 5679: case 5680: case 5690: case 5691: case 5692: case 5702: case 5703: case 5704: case 5714: case 5715: case 5716: case 5726: case 5727: case 5728: case 5738: case 5739: case 5740: case 5750: case 5751: case 5752: case 5762: case 5763: case 5764: case 5774: case 5775: case 5776: case 5786: case 5787: case 5788: case 5798: case 5799: case 5800: case 5810: case 5811: case 5812: case 5822: case 5823: case 5824: case 5834: case 5835: case 5836: case 5846: case 5847: case 5848: case 5858: case 5859: case 5860: case 5870: case 5871: case 5872: case 5882: case 5883: case 5884: case 5894: case 5895: case 5896: case 5906: case 5907: case 5908: case 5918: case 5919: case 5920: case 5930: case 5931: case 5932: case 5942: case 5943: case 5944: case 5954: case 5955: case 5956: case 5966: case 5967: case 5968: case 5978: case 5979: case 5980: return false; default: return true; } } enum West West(const BlockState Block) { switch (Block.ID) { case 5661: case 5667: case 5673: case 5679: case 5685: case 5691: case 5697: case 5703: case 5709: case 5715: case 5721: case 5727: case 5733: case 5739: case 5745: case 5751: case 5757: case 5763: case 5769: case 5775: case 5781: case 5787: case 5793: case 5799: case 5805: case 5811: case 5817: case 5823: case 5829: case 5835: case 5841: case 5847: case 5853: case 5859: case 5865: case 5871: case 5877: case 5883: case 5889: case 5895: case 5901: case 5907: case 5913: case 5919: case 5925: case 5931: case 5937: case 5943: case 5949: case 5955: case 5961: case 5967: case 5973: case 5979: return West::Low; case 5660: case 5666: case 5672: case 5678: case 5684: case 5690: case 5696: case 5702: case 5708: case 5714: case 5720: case 5726: case 5732: case 5738: case 5744: case 5750: case 5756: case 5762: case 5768: case 5774: case 5780: case 5786: case 5792: case 5798: case 5804: case 5810: case 5816: case 5822: case 5828: case 5834: case 5840: case 5846: case 5852: case 5858: case 5864: case 5870: case 5876: case 5882: case 5888: case 5894: case 5900: case 5906: case 5912: case 5918: case 5924: case 5930: case 5936: case 5942: case 5948: case 5954: case 5960: case 5966: case 5972: case 5978: return West::None; default: return West::Tall; } } } namespace Cobweb { } namespace Cocoa { BlockState Cocoa() { return 5158; } unsigned char Age(const BlockState Block) { switch (Block.ID) { case 5158: case 5159: case 5160: case 5161: return 0; case 5162: case 5163: case 5164: case 5165: return 1; default: return 2; } } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 5160: case 5164: case 5168: return eBlockFace::BLOCK_FACE_XM; case 5161: case 5165: case 5169: return eBlockFace::BLOCK_FACE_XP; case 5158: case 5162: case 5166: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace CommandBlock { BlockState CommandBlock() { return 5650; } bool Conditional(const BlockState Block) { switch (Block.ID) { case 5650: case 5651: case 5652: case 5653: case 5654: case 5655: return false; default: return true; } } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 5647: case 5653: return eBlockFace::BLOCK_FACE_XM; case 5645: case 5651: return eBlockFace::BLOCK_FACE_XP; case 5649: case 5655: return eBlockFace::BLOCK_FACE_YM; case 5648: case 5654: return eBlockFace::BLOCK_FACE_YP; case 5644: case 5650: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace Comparator { BlockState Comparator() { return 6679; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 6686: case 6687: case 6688: case 6689: return eBlockFace::BLOCK_FACE_XM; case 6690: case 6691: case 6692: case 6693: return eBlockFace::BLOCK_FACE_XP; case 6678: case 6679: case 6680: case 6681: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } enum Mode Mode(const BlockState Block) { switch (Block.ID) { case 6678: case 6679: case 6682: case 6683: case 6686: case 6687: case 6690: case 6691: return Mode::Compare; default: return Mode::Subtract; } } bool Powered(const BlockState Block) { switch (Block.ID) { case 6679: case 6681: case 6683: case 6685: case 6687: case 6689: case 6691: case 6693: return false; default: return true; } } } namespace Composter { BlockState Composter() { return 15751; } unsigned char Level(const BlockState Block) { switch (Block.ID) { case 15751: return 0; case 15752: return 1; case 15753: return 2; case 15754: return 3; case 15755: return 4; case 15756: return 5; case 15757: return 6; case 15758: return 7; default: return 8; } } } namespace Conduit { } namespace Cornflower { } namespace CrackedNetherBricks { } namespace CrackedPolishedBlackstoneBricks { } namespace CrackedStoneBricks { } namespace CraftingTable { } namespace CreeperHead { BlockState CreeperHead() { return 6570; } unsigned char Rotation(const BlockState Block) { switch (Block.ID) { case 6570: return 0; case 6571: return 1; case 6580: return 10; case 6581: return 11; case 6582: return 12; case 6583: return 13; case 6584: return 14; case 6585: return 15; case 6572: return 2; case 6573: return 3; case 6574: return 4; case 6575: return 5; case 6576: return 6; case 6577: return 7; case 6578: return 8; default: return 9; } } } namespace CreeperWallHead { BlockState CreeperWallHead() { return 6586; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 6588: return eBlockFace::BLOCK_FACE_XM; case 6589: return eBlockFace::BLOCK_FACE_XP; case 6586: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace CrimsonButton { BlockState CrimsonButton() { return 15488; } enum Face Face(const BlockState Block) { switch (Block.ID) { case 15495: case 15496: case 15497: case 15498: case 15499: case 15500: case 15501: case 15502: return Face::Ceiling; case 15479: case 15480: case 15481: case 15482: case 15483: case 15484: case 15485: case 15486: return Face::Floor; default: return Face::Wall; } } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 15483: case 15484: case 15491: case 15492: case 15499: case 15500: return eBlockFace::BLOCK_FACE_XM; case 15485: case 15486: case 15493: case 15494: case 15501: case 15502: return eBlockFace::BLOCK_FACE_XP; case 15479: case 15480: case 15487: case 15488: case 15495: case 15496: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } bool Powered(const BlockState Block) { switch (Block.ID) { case 15480: case 15482: case 15484: case 15486: case 15488: case 15490: case 15492: case 15494: case 15496: case 15498: case 15500: case 15502: return false; default: return true; } } } namespace CrimsonDoor { BlockState CrimsonDoor() { return 15538; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 15559: case 15560: case 15561: case 15562: case 15563: case 15564: case 15565: case 15566: case 15567: case 15568: case 15569: case 15570: case 15571: case 15572: case 15573: case 15574: return eBlockFace::BLOCK_FACE_XM; case 15575: case 15576: case 15577: case 15578: case 15579: case 15580: case 15581: case 15582: case 15583: case 15584: case 15585: case 15586: case 15587: case 15588: case 15589: case 15590: return eBlockFace::BLOCK_FACE_XP; case 15527: case 15528: case 15529: case 15530: case 15531: case 15532: case 15533: case 15534: case 15535: case 15536: case 15537: case 15538: case 15539: case 15540: case 15541: case 15542: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } enum Half Half(const BlockState Block) { switch (Block.ID) { case 15535: case 15536: case 15537: case 15538: case 15539: case 15540: case 15541: case 15542: case 15551: case 15552: case 15553: case 15554: case 15555: case 15556: case 15557: case 15558: case 15567: case 15568: case 15569: case 15570: case 15571: case 15572: case 15573: case 15574: case 15583: case 15584: case 15585: case 15586: case 15587: case 15588: case 15589: case 15590: return Half::Lower; default: return Half::Upper; } } enum Hinge Hinge(const BlockState Block) { switch (Block.ID) { case 15527: case 15528: case 15529: case 15530: case 15535: case 15536: case 15537: case 15538: case 15543: case 15544: case 15545: case 15546: case 15551: case 15552: case 15553: case 15554: case 15559: case 15560: case 15561: case 15562: case 15567: case 15568: case 15569: case 15570: case 15575: case 15576: case 15577: case 15578: case 15583: case 15584: case 15585: case 15586: return Hinge::Left; default: return Hinge::Right; } } bool Open(const BlockState Block) { switch (Block.ID) { case 15529: case 15530: case 15533: case 15534: case 15537: case 15538: case 15541: case 15542: case 15545: case 15546: case 15549: case 15550: case 15553: case 15554: case 15557: case 15558: case 15561: case 15562: case 15565: case 15566: case 15569: case 15570: case 15573: case 15574: case 15577: case 15578: case 15581: case 15582: case 15585: case 15586: case 15589: case 15590: return false; default: return true; } } bool Powered(const BlockState Block) { switch (Block.ID) { case 15528: case 15530: case 15532: case 15534: case 15536: case 15538: case 15540: case 15542: case 15544: case 15546: case 15548: case 15550: case 15552: case 15554: case 15556: case 15558: case 15560: case 15562: case 15564: case 15566: case 15568: case 15570: case 15572: case 15574: case 15576: case 15578: case 15580: case 15582: case 15584: case 15586: case 15588: case 15590: return false; default: return true; } } } namespace CrimsonFence { BlockState CrimsonFence() { return 15094; } bool East(const BlockState Block) { switch (Block.ID) { case 15081: case 15082: case 15085: case 15086: case 15089: case 15090: case 15093: case 15094: return false; default: return true; } } bool North(const BlockState Block) { switch (Block.ID) { case 15073: case 15074: case 15077: case 15078: case 15089: case 15090: case 15093: case 15094: return false; default: return true; } } bool South(const BlockState Block) { switch (Block.ID) { case 15069: case 15070: case 15077: case 15078: case 15085: case 15086: case 15093: case 15094: return false; default: return true; } } bool West(const BlockState Block) { switch (Block.ID) { case 15066: case 15070: case 15074: case 15078: case 15082: case 15086: case 15090: case 15094: return false; default: return true; } } } namespace CrimsonFenceGate { BlockState CrimsonFenceGate() { return 15262; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 15271: case 15272: case 15273: case 15274: case 15275: case 15276: case 15277: case 15278: return eBlockFace::BLOCK_FACE_XM; case 15279: case 15280: case 15281: case 15282: case 15283: case 15284: case 15285: case 15286: return eBlockFace::BLOCK_FACE_XP; case 15255: case 15256: case 15257: case 15258: case 15259: case 15260: case 15261: case 15262: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } bool InWall(const BlockState Block) { switch (Block.ID) { case 15259: case 15260: case 15261: case 15262: case 15267: case 15268: case 15269: case 15270: case 15275: case 15276: case 15277: case 15278: case 15283: case 15284: case 15285: case 15286: return false; default: return true; } } bool Open(const BlockState Block) { switch (Block.ID) { case 15257: case 15258: case 15261: case 15262: case 15265: case 15266: case 15269: case 15270: case 15273: case 15274: case 15277: case 15278: case 15281: case 15282: case 15285: case 15286: return false; default: return true; } } bool Powered(const BlockState Block) { switch (Block.ID) { case 15256: case 15258: case 15260: case 15262: case 15264: case 15266: case 15268: case 15270: case 15272: case 15274: case 15276: case 15278: case 15280: case 15282: case 15284: case 15286: return false; default: return true; } } } namespace CrimsonFungus { } namespace CrimsonHyphae { BlockState CrimsonHyphae() { return 14982; } enum Axis Axis(const BlockState Block) { switch (Block.ID) { case 14981: return Axis::X; case 14982: return Axis::Y; default: return Axis::Z; } } } namespace CrimsonNylium { } namespace CrimsonPlanks { } namespace CrimsonPressurePlate { BlockState CrimsonPressurePlate() { return 15060; } bool Powered(const BlockState Block) { switch (Block.ID) { case 15060: return false; default: return true; } } } namespace CrimsonRoots { } namespace CrimsonSign { BlockState CrimsonSign() { return 15656; } unsigned char Rotation(const BlockState Block) { switch (Block.ID) { case 15656: return 0; case 15658: return 1; case 15676: return 10; case 15678: return 11; case 15680: return 12; case 15682: return 13; case 15684: return 14; case 15686: return 15; case 15660: return 2; case 15662: return 3; case 15664: return 4; case 15666: return 5; case 15668: return 6; case 15670: return 7; case 15672: return 8; default: return 9; } } } namespace CrimsonSlab { BlockState CrimsonSlab() { return 15050; } enum Type Type(const BlockState Block) { switch (Block.ID) { case 15050: return Type::Bottom; case 15052: return Type::Double; default: return Type::Top; } } } namespace CrimsonStairs { BlockState CrimsonStairs() { return 15330; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 15360: case 15362: case 15364: case 15366: case 15368: case 15370: case 15372: case 15374: case 15376: case 15378: return eBlockFace::BLOCK_FACE_XM; case 15380: case 15382: case 15384: case 15386: case 15388: case 15390: case 15392: case 15394: case 15396: case 15398: return eBlockFace::BLOCK_FACE_XP; case 15320: case 15322: case 15324: case 15326: case 15328: case 15330: case 15332: case 15334: case 15336: case 15338: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } enum Half Half(const BlockState Block) { switch (Block.ID) { case 15330: case 15332: case 15334: case 15336: case 15338: case 15350: case 15352: case 15354: case 15356: case 15358: case 15370: case 15372: case 15374: case 15376: case 15378: case 15390: case 15392: case 15394: case 15396: case 15398: return Half::Bottom; default: return Half::Top; } } enum Shape Shape(const BlockState Block) { switch (Block.ID) { case 15322: case 15332: case 15342: case 15352: case 15362: case 15372: case 15382: case 15392: return Shape::InnerLeft; case 15324: case 15334: case 15344: case 15354: case 15364: case 15374: case 15384: case 15394: return Shape::InnerRight; case 15326: case 15336: case 15346: case 15356: case 15366: case 15376: case 15386: case 15396: return Shape::OuterLeft; case 15328: case 15338: case 15348: case 15358: case 15368: case 15378: case 15388: case 15398: return Shape::OuterRight; default: return Shape::Straight; } } } namespace CrimsonStem { BlockState CrimsonStem() { return 14976; } enum Axis Axis(const BlockState Block) { switch (Block.ID) { case 14975: return Axis::X; case 14976: return Axis::Y; default: return Axis::Z; } } } namespace CrimsonTrapdoor { BlockState CrimsonTrapdoor() { return 15142; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 15160: case 15162: case 15164: case 15166: case 15168: case 15170: case 15172: case 15174: return eBlockFace::BLOCK_FACE_XM; case 15176: case 15178: case 15180: case 15182: case 15184: case 15186: case 15188: case 15190: return eBlockFace::BLOCK_FACE_XP; case 15128: case 15130: case 15132: case 15134: case 15136: case 15138: case 15140: case 15142: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } enum Half Half(const BlockState Block) { switch (Block.ID) { case 15136: case 15138: case 15140: case 15142: case 15152: case 15154: case 15156: case 15158: case 15168: case 15170: case 15172: case 15174: case 15184: case 15186: case 15188: case 15190: return Half::Bottom; default: return Half::Top; } } bool Open(const BlockState Block) { switch (Block.ID) { case 15132: case 15134: case 15140: case 15142: case 15148: case 15150: case 15156: case 15158: case 15164: case 15166: case 15172: case 15174: case 15180: case 15182: case 15188: case 15190: return false; default: return true; } } bool Powered(const BlockState Block) { switch (Block.ID) { case 15130: case 15134: case 15138: case 15142: case 15146: case 15150: case 15154: case 15158: case 15162: case 15166: case 15170: case 15174: case 15178: case 15182: case 15186: case 15190: return false; default: return true; } } } namespace CrimsonWallSign { BlockState CrimsonWallSign() { return 15720; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 15724: return eBlockFace::BLOCK_FACE_XM; case 15726: return eBlockFace::BLOCK_FACE_XP; case 15720: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace CryingObsidian { } namespace CutRedSandstone { } namespace CutRedSandstoneSlab { BlockState CutRedSandstoneSlab() { return 8405; } enum Type Type(const BlockState Block) { switch (Block.ID) { case 8405: return Type::Bottom; case 8407: return Type::Double; default: return Type::Top; } } } namespace CutSandstone { } namespace CutSandstoneSlab { BlockState CutSandstoneSlab() { return 8357; } enum Type Type(const BlockState Block) { switch (Block.ID) { case 8357: return Type::Bottom; case 8359: return Type::Double; default: return Type::Top; } } } namespace CyanBanner { BlockState CyanBanner() { return 8041; } unsigned char Rotation(const BlockState Block) { switch (Block.ID) { case 8041: return 0; case 8042: return 1; case 8051: return 10; case 8052: return 11; case 8053: return 12; case 8054: return 13; case 8055: return 14; case 8056: return 15; case 8043: return 2; case 8044: return 3; case 8045: return 4; case 8046: return 5; case 8047: return 6; case 8048: return 7; case 8049: return 8; default: return 9; } } } namespace CyanBed { BlockState CyanBed() { return 1196; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 1201: case 1202: case 1203: case 1204: return eBlockFace::BLOCK_FACE_XM; case 1205: case 1206: case 1207: case 1208: return eBlockFace::BLOCK_FACE_XP; case 1193: case 1194: case 1195: case 1196: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } bool Occupied(const BlockState Block) { switch (Block.ID) { case 1195: case 1196: case 1199: case 1200: case 1203: case 1204: case 1207: case 1208: return false; default: return true; } } enum Part Part(const BlockState Block) { switch (Block.ID) { case 1194: case 1196: case 1198: case 1200: case 1202: case 1204: case 1206: case 1208: return Part::Foot; default: return Part::Head; } } } namespace CyanCarpet { } namespace CyanConcrete { } namespace CyanConcretePowder { } namespace CyanGlazedTerracotta { BlockState CyanGlazedTerracotta() { return 9410; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 9412: return eBlockFace::BLOCK_FACE_XM; case 9413: return eBlockFace::BLOCK_FACE_XP; case 9410: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace CyanShulkerBox { BlockState CyanShulkerBox() { return 9336; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 9335: return eBlockFace::BLOCK_FACE_XM; case 9333: return eBlockFace::BLOCK_FACE_XP; case 9337: return eBlockFace::BLOCK_FACE_YM; case 9336: return eBlockFace::BLOCK_FACE_YP; case 9332: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace CyanStainedGlass { } namespace CyanStainedGlassPane { BlockState CyanStainedGlassPane() { return 7182; } bool East(const BlockState Block) { switch (Block.ID) { case 7169: case 7170: case 7173: case 7174: case 7177: case 7178: case 7181: case 7182: return false; default: return true; } } bool North(const BlockState Block) { switch (Block.ID) { case 7161: case 7162: case 7165: case 7166: case 7177: case 7178: case 7181: case 7182: return false; default: return true; } } bool South(const BlockState Block) { switch (Block.ID) { case 7157: case 7158: case 7165: case 7166: case 7173: case 7174: case 7181: case 7182: return false; default: return true; } } bool West(const BlockState Block) { switch (Block.ID) { case 7154: case 7158: case 7162: case 7166: case 7170: case 7174: case 7178: case 7182: return false; default: return true; } } } namespace CyanTerracotta { } namespace CyanWallBanner { BlockState CyanWallBanner() { return 8189; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 8191: return eBlockFace::BLOCK_FACE_XM; case 8192: return eBlockFace::BLOCK_FACE_XP; case 8189: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace CyanWool { } namespace DamagedAnvil { BlockState DamagedAnvil() { return 6618; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 6620: return eBlockFace::BLOCK_FACE_XM; case 6621: return eBlockFace::BLOCK_FACE_XP; case 6618: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace Dandelion { } namespace DarkOakButton { BlockState DarkOakButton() { return 6475; } enum Face Face(const BlockState Block) { switch (Block.ID) { case 6482: case 6483: case 6484: case 6485: case 6486: case 6487: case 6488: case 6489: return Face::Ceiling; case 6466: case 6467: case 6468: case 6469: case 6470: case 6471: case 6472: case 6473: return Face::Floor; default: return Face::Wall; } } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 6470: case 6471: case 6478: case 6479: case 6486: case 6487: return eBlockFace::BLOCK_FACE_XM; case 6472: case 6473: case 6480: case 6481: case 6488: case 6489: return eBlockFace::BLOCK_FACE_XP; case 6466: case 6467: case 6474: case 6475: case 6482: case 6483: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } bool Powered(const BlockState Block) { switch (Block.ID) { case 6467: case 6469: case 6471: case 6473: case 6475: case 6477: case 6479: case 6481: case 6483: case 6485: case 6487: case 6489: return false; default: return true; } } } namespace DarkOakDoor { BlockState DarkOakDoor() { return 9005; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 9026: case 9027: case 9028: case 9029: case 9030: case 9031: case 9032: case 9033: case 9034: case 9035: case 9036: case 9037: case 9038: case 9039: case 9040: case 9041: return eBlockFace::BLOCK_FACE_XM; case 9042: case 9043: case 9044: case 9045: case 9046: case 9047: case 9048: case 9049: case 9050: case 9051: case 9052: case 9053: case 9054: case 9055: case 9056: case 9057: return eBlockFace::BLOCK_FACE_XP; case 8994: case 8995: case 8996: case 8997: case 8998: case 8999: case 9000: case 9001: case 9002: case 9003: case 9004: case 9005: case 9006: case 9007: case 9008: case 9009: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } enum Half Half(const BlockState Block) { switch (Block.ID) { case 9002: case 9003: case 9004: case 9005: case 9006: case 9007: case 9008: case 9009: case 9018: case 9019: case 9020: case 9021: case 9022: case 9023: case 9024: case 9025: case 9034: case 9035: case 9036: case 9037: case 9038: case 9039: case 9040: case 9041: case 9050: case 9051: case 9052: case 9053: case 9054: case 9055: case 9056: case 9057: return Half::Lower; default: return Half::Upper; } } enum Hinge Hinge(const BlockState Block) { switch (Block.ID) { case 8994: case 8995: case 8996: case 8997: case 9002: case 9003: case 9004: case 9005: case 9010: case 9011: case 9012: case 9013: case 9018: case 9019: case 9020: case 9021: case 9026: case 9027: case 9028: case 9029: case 9034: case 9035: case 9036: case 9037: case 9042: case 9043: case 9044: case 9045: case 9050: case 9051: case 9052: case 9053: return Hinge::Left; default: return Hinge::Right; } } bool Open(const BlockState Block) { switch (Block.ID) { case 8996: case 8997: case 9000: case 9001: case 9004: case 9005: case 9008: case 9009: case 9012: case 9013: case 9016: case 9017: case 9020: case 9021: case 9024: case 9025: case 9028: case 9029: case 9032: case 9033: case 9036: case 9037: case 9040: case 9041: case 9044: case 9045: case 9048: case 9049: case 9052: case 9053: case 9056: case 9057: return false; default: return true; } } bool Powered(const BlockState Block) { switch (Block.ID) { case 8995: case 8997: case 8999: case 9001: case 9003: case 9005: case 9007: case 9009: case 9011: case 9013: case 9015: case 9017: case 9019: case 9021: case 9023: case 9025: case 9027: case 9029: case 9031: case 9033: case 9035: case 9037: case 9039: case 9041: case 9043: case 9045: case 9047: case 9049: case 9051: case 9053: case 9055: case 9057: return false; default: return true; } } } namespace DarkOakFence { BlockState DarkOakFence() { return 8737; } bool East(const BlockState Block) { switch (Block.ID) { case 8724: case 8725: case 8728: case 8729: case 8732: case 8733: case 8736: case 8737: return false; default: return true; } } bool North(const BlockState Block) { switch (Block.ID) { case 8716: case 8717: case 8720: case 8721: case 8732: case 8733: case 8736: case 8737: return false; default: return true; } } bool South(const BlockState Block) { switch (Block.ID) { case 8712: case 8713: case 8720: case 8721: case 8728: case 8729: case 8736: case 8737: return false; default: return true; } } bool West(const BlockState Block) { switch (Block.ID) { case 8709: case 8713: case 8717: case 8721: case 8725: case 8729: case 8733: case 8737: return false; default: return true; } } } namespace DarkOakFenceGate { BlockState DarkOakFenceGate() { return 8553; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 8562: case 8563: case 8564: case 8565: case 8566: case 8567: case 8568: case 8569: return eBlockFace::BLOCK_FACE_XM; case 8570: case 8571: case 8572: case 8573: case 8574: case 8575: case 8576: case 8577: return eBlockFace::BLOCK_FACE_XP; case 8546: case 8547: case 8548: case 8549: case 8550: case 8551: case 8552: case 8553: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } bool InWall(const BlockState Block) { switch (Block.ID) { case 8550: case 8551: case 8552: case 8553: case 8558: case 8559: case 8560: case 8561: case 8566: case 8567: case 8568: case 8569: case 8574: case 8575: case 8576: case 8577: return false; default: return true; } } bool Open(const BlockState Block) { switch (Block.ID) { case 8548: case 8549: case 8552: case 8553: case 8556: case 8557: case 8560: case 8561: case 8564: case 8565: case 8568: case 8569: case 8572: case 8573: case 8576: case 8577: return false; default: return true; } } bool Powered(const BlockState Block) { switch (Block.ID) { case 8547: case 8549: case 8551: case 8553: case 8555: case 8557: case 8559: case 8561: case 8563: case 8565: case 8567: case 8569: case 8571: case 8573: case 8575: case 8577: return false; default: return true; } } } namespace DarkOakLeaves { BlockState DarkOakLeaves() { return 228; } unsigned char Distance(const BlockState Block) { switch (Block.ID) { case 215: case 216: return 1; case 217: case 218: return 2; case 219: case 220: return 3; case 221: case 222: return 4; case 223: case 224: return 5; case 225: case 226: return 6; default: return 7; } } bool Persistent(const BlockState Block) { switch (Block.ID) { case 216: case 218: case 220: case 222: case 224: case 226: case 228: return false; default: return true; } } } namespace DarkOakLog { BlockState DarkOakLog() { return 89; } enum Axis Axis(const BlockState Block) { switch (Block.ID) { case 88: return Axis::X; case 89: return Axis::Y; default: return Axis::Z; } } } namespace DarkOakPlanks { } namespace DarkOakPressurePlate { BlockState DarkOakPressurePlate() { return 3884; } bool Powered(const BlockState Block) { switch (Block.ID) { case 3884: return false; default: return true; } } } namespace DarkOakSapling { BlockState DarkOakSapling() { return 31; } unsigned char Stage(const BlockState Block) { switch (Block.ID) { case 31: return 0; default: return 1; } } } namespace DarkOakSign { BlockState DarkOakSign() { return 3542; } unsigned char Rotation(const BlockState Block) { switch (Block.ID) { case 3542: return 0; case 3544: return 1; case 3562: return 10; case 3564: return 11; case 3566: return 12; case 3568: return 13; case 3570: return 14; case 3572: return 15; case 3546: return 2; case 3548: return 3; case 3550: return 4; case 3552: return 5; case 3554: return 6; case 3556: return 7; case 3558: return 8; default: return 9; } } } namespace DarkOakSlab { BlockState DarkOakSlab() { return 8333; } enum Type Type(const BlockState Block) { switch (Block.ID) { case 8333: return Type::Bottom; case 8335: return Type::Double; default: return Type::Top; } } } namespace DarkOakStairs { BlockState DarkOakStairs() { return 7466; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 7496: case 7498: case 7500: case 7502: case 7504: case 7506: case 7508: case 7510: case 7512: case 7514: return eBlockFace::BLOCK_FACE_XM; case 7516: case 7518: case 7520: case 7522: case 7524: case 7526: case 7528: case 7530: case 7532: case 7534: return eBlockFace::BLOCK_FACE_XP; case 7456: case 7458: case 7460: case 7462: case 7464: case 7466: case 7468: case 7470: case 7472: case 7474: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } enum Half Half(const BlockState Block) { switch (Block.ID) { case 7466: case 7468: case 7470: case 7472: case 7474: case 7486: case 7488: case 7490: case 7492: case 7494: case 7506: case 7508: case 7510: case 7512: case 7514: case 7526: case 7528: case 7530: case 7532: case 7534: return Half::Bottom; default: return Half::Top; } } enum Shape Shape(const BlockState Block) { switch (Block.ID) { case 7458: case 7468: case 7478: case 7488: case 7498: case 7508: case 7518: case 7528: return Shape::InnerLeft; case 7460: case 7470: case 7480: case 7490: case 7500: case 7510: case 7520: case 7530: return Shape::InnerRight; case 7462: case 7472: case 7482: case 7492: case 7502: case 7512: case 7522: case 7532: return Shape::OuterLeft; case 7464: case 7474: case 7484: case 7494: case 7504: case 7514: case 7524: case 7534: return Shape::OuterRight; default: return Shape::Straight; } } } namespace DarkOakTrapdoor { BlockState DarkOakTrapdoor() { return 4446; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 4464: case 4466: case 4468: case 4470: case 4472: case 4474: case 4476: case 4478: return eBlockFace::BLOCK_FACE_XM; case 4480: case 4482: case 4484: case 4486: case 4488: case 4490: case 4492: case 4494: return eBlockFace::BLOCK_FACE_XP; case 4432: case 4434: case 4436: case 4438: case 4440: case 4442: case 4444: case 4446: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } enum Half Half(const BlockState Block) { switch (Block.ID) { case 4440: case 4442: case 4444: case 4446: case 4456: case 4458: case 4460: case 4462: case 4472: case 4474: case 4476: case 4478: case 4488: case 4490: case 4492: case 4494: return Half::Bottom; default: return Half::Top; } } bool Open(const BlockState Block) { switch (Block.ID) { case 4436: case 4438: case 4444: case 4446: case 4452: case 4454: case 4460: case 4462: case 4468: case 4470: case 4476: case 4478: case 4484: case 4486: case 4492: case 4494: return false; default: return true; } } bool Powered(const BlockState Block) { switch (Block.ID) { case 4434: case 4438: case 4442: case 4446: case 4450: case 4454: case 4458: case 4462: case 4466: case 4470: case 4474: case 4478: case 4482: case 4486: case 4490: case 4494: return false; default: return true; } } } namespace DarkOakWallSign { BlockState DarkOakWallSign() { return 3776; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 3780: return eBlockFace::BLOCK_FACE_XM; case 3782: return eBlockFace::BLOCK_FACE_XP; case 3776: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace DarkOakWood { BlockState DarkOakWood() { return 125; } enum Axis Axis(const BlockState Block) { switch (Block.ID) { case 124: return Axis::X; case 125: return Axis::Y; default: return Axis::Z; } } } namespace DarkPrismarine { } namespace DarkPrismarineSlab { BlockState DarkPrismarineSlab() { return 7859; } enum Type Type(const BlockState Block) { switch (Block.ID) { case 7859: return Type::Bottom; case 7861: return Type::Double; default: return Type::Top; } } } namespace DarkPrismarineStairs { BlockState DarkPrismarineStairs() { return 7775; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 7805: case 7807: case 7809: case 7811: case 7813: case 7815: case 7817: case 7819: case 7821: case 7823: return eBlockFace::BLOCK_FACE_XM; case 7825: case 7827: case 7829: case 7831: case 7833: case 7835: case 7837: case 7839: case 7841: case 7843: return eBlockFace::BLOCK_FACE_XP; case 7765: case 7767: case 7769: case 7771: case 7773: case 7775: case 7777: case 7779: case 7781: case 7783: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } enum Half Half(const BlockState Block) { switch (Block.ID) { case 7775: case 7777: case 7779: case 7781: case 7783: case 7795: case 7797: case 7799: case 7801: case 7803: case 7815: case 7817: case 7819: case 7821: case 7823: case 7835: case 7837: case 7839: case 7841: case 7843: return Half::Bottom; default: return Half::Top; } } enum Shape Shape(const BlockState Block) { switch (Block.ID) { case 7767: case 7777: case 7787: case 7797: case 7807: case 7817: case 7827: case 7837: return Shape::InnerLeft; case 7769: case 7779: case 7789: case 7799: case 7809: case 7819: case 7829: case 7839: return Shape::InnerRight; case 7771: case 7781: case 7791: case 7801: case 7811: case 7821: case 7831: case 7841: return Shape::OuterLeft; case 7773: case 7783: case 7793: case 7803: case 7813: case 7823: case 7833: case 7843: return Shape::OuterRight; default: return Shape::Straight; } } } namespace DaylightDetector { BlockState DaylightDetector() { return 6710; } bool Inverted(const BlockState Block) { switch (Block.ID) { case 6710: case 6711: case 6712: case 6713: case 6714: case 6715: case 6716: case 6717: case 6718: case 6719: case 6720: case 6721: case 6722: case 6723: case 6724: case 6725: return false; default: return true; } } unsigned char Power(const BlockState Block) { switch (Block.ID) { case 6694: case 6710: return 0; case 6695: case 6711: return 1; case 6704: case 6720: return 10; case 6705: case 6721: return 11; case 6706: case 6722: return 12; case 6707: case 6723: return 13; case 6708: case 6724: return 14; case 6709: case 6725: return 15; case 6696: case 6712: return 2; case 6697: case 6713: return 3; case 6698: case 6714: return 4; case 6699: case 6715: return 5; case 6700: case 6716: return 6; case 6701: case 6717: return 7; case 6702: case 6718: return 8; default: return 9; } } } namespace DeadBrainCoral { } namespace DeadBrainCoralBlock { } namespace DeadBrainCoralFan { } namespace DeadBrainCoralWallFan { BlockState DeadBrainCoralWallFan() { return 9568; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 9573: return eBlockFace::BLOCK_FACE_XM; case 9575: return eBlockFace::BLOCK_FACE_XP; case 9569: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace DeadBubbleCoral { } namespace DeadBubbleCoralBlock { } namespace DeadBubbleCoralFan { } namespace DeadBubbleCoralWallFan { BlockState DeadBubbleCoralWallFan() { return 9576; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 9581: return eBlockFace::BLOCK_FACE_XM; case 9583: return eBlockFace::BLOCK_FACE_XP; case 9577: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace DeadBush { } namespace DeadFireCoral { } namespace DeadFireCoralBlock { } namespace DeadFireCoralFan { } namespace DeadFireCoralWallFan { BlockState DeadFireCoralWallFan() { return 9584; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 9589: return eBlockFace::BLOCK_FACE_XM; case 9591: return eBlockFace::BLOCK_FACE_XP; case 9585: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace DeadHornCoral { } namespace DeadHornCoralBlock { } namespace DeadHornCoralFan { } namespace DeadHornCoralWallFan { BlockState DeadHornCoralWallFan() { return 9592; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 9597: return eBlockFace::BLOCK_FACE_XM; case 9599: return eBlockFace::BLOCK_FACE_XP; case 9593: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace DeadTubeCoral { } namespace DeadTubeCoralBlock { } namespace DeadTubeCoralFan { } namespace DeadTubeCoralWallFan { BlockState DeadTubeCoralWallFan() { return 9560; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 9565: return eBlockFace::BLOCK_FACE_XM; case 9567: return eBlockFace::BLOCK_FACE_XP; case 9561: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace DetectorRail { BlockState DetectorRail() { return 1323; } bool Powered(const BlockState Block) { switch (Block.ID) { case 1323: case 1324: case 1325: case 1326: case 1327: case 1328: return false; default: return true; } } enum Shape Shape(const BlockState Block) { switch (Block.ID) { case 1319: case 1325: return Shape::AscendingEast; case 1321: case 1327: return Shape::AscendingNorth; case 1322: case 1328: return Shape::AscendingSouth; case 1320: case 1326: return Shape::AscendingWest; case 1318: case 1324: return Shape::EastWest; default: return Shape::NorthSouth; } } } namespace DiamondBlock { } namespace DiamondOre { } namespace Diorite { } namespace DioriteSlab { BlockState DioriteSlab() { return 10864; } enum Type Type(const BlockState Block) { switch (Block.ID) { case 10864: return Type::Bottom; case 10866: return Type::Double; default: return Type::Top; } } } namespace DioriteStairs { BlockState DioriteStairs() { return 10720; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 10750: case 10752: case 10754: case 10756: case 10758: case 10760: case 10762: case 10764: case 10766: case 10768: return eBlockFace::BLOCK_FACE_XM; case 10770: case 10772: case 10774: case 10776: case 10778: case 10780: case 10782: case 10784: case 10786: case 10788: return eBlockFace::BLOCK_FACE_XP; case 10710: case 10712: case 10714: case 10716: case 10718: case 10720: case 10722: case 10724: case 10726: case 10728: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } enum Half Half(const BlockState Block) { switch (Block.ID) { case 10720: case 10722: case 10724: case 10726: case 10728: case 10740: case 10742: case 10744: case 10746: case 10748: case 10760: case 10762: case 10764: case 10766: case 10768: case 10780: case 10782: case 10784: case 10786: case 10788: return Half::Bottom; default: return Half::Top; } } enum Shape Shape(const BlockState Block) { switch (Block.ID) { case 10712: case 10722: case 10732: case 10742: case 10752: case 10762: case 10772: case 10782: return Shape::InnerLeft; case 10714: case 10724: case 10734: case 10744: case 10754: case 10764: case 10774: case 10784: return Shape::InnerRight; case 10716: case 10726: case 10736: case 10746: case 10756: case 10766: case 10776: case 10786: return Shape::OuterLeft; case 10718: case 10728: case 10738: case 10748: case 10758: case 10768: case 10778: case 10788: return Shape::OuterRight; default: return Shape::Straight; } } } namespace DioriteWall { BlockState DioriteWall() { return 14434; } enum East East(const BlockState Block) { switch (Block.ID) { case 14542: case 14543: case 14544: case 14548: case 14549: case 14550: case 14554: case 14555: case 14556: case 14560: case 14561: case 14562: case 14566: case 14567: case 14568: case 14572: case 14573: case 14574: case 14578: case 14579: case 14580: case 14584: case 14585: case 14586: case 14590: case 14591: case 14592: case 14596: case 14597: case 14598: case 14602: case 14603: case 14604: case 14608: case 14609: case 14610: case 14614: case 14615: case 14616: case 14620: case 14621: case 14622: case 14626: case 14627: case 14628: case 14632: case 14633: case 14634: case 14638: case 14639: case 14640: case 14644: case 14645: case 14646: return East::Low; case 14434: case 14435: case 14436: case 14440: case 14441: case 14442: case 14446: case 14447: case 14448: case 14452: case 14453: case 14454: case 14458: case 14459: case 14460: case 14464: case 14465: case 14466: case 14470: case 14471: case 14472: case 14476: case 14477: case 14478: case 14482: case 14483: case 14484: case 14488: case 14489: case 14490: case 14494: case 14495: case 14496: case 14500: case 14501: case 14502: case 14506: case 14507: case 14508: case 14512: case 14513: case 14514: case 14518: case 14519: case 14520: case 14524: case 14525: case 14526: case 14530: case 14531: case 14532: case 14536: case 14537: case 14538: return East::None; default: return East::Tall; } } enum North North(const BlockState Block) { switch (Block.ID) { case 14470: case 14471: case 14472: case 14476: case 14477: case 14478: case 14482: case 14483: case 14484: case 14488: case 14489: case 14490: case 14494: case 14495: case 14496: case 14500: case 14501: case 14502: case 14578: case 14579: case 14580: case 14584: case 14585: case 14586: case 14590: case 14591: case 14592: case 14596: case 14597: case 14598: case 14602: case 14603: case 14604: case 14608: case 14609: case 14610: case 14686: case 14687: case 14688: case 14692: case 14693: case 14694: case 14698: case 14699: case 14700: case 14704: case 14705: case 14706: case 14710: case 14711: case 14712: case 14716: case 14717: case 14718: return North::Low; case 14434: case 14435: case 14436: case 14440: case 14441: case 14442: case 14446: case 14447: case 14448: case 14452: case 14453: case 14454: case 14458: case 14459: case 14460: case 14464: case 14465: case 14466: case 14542: case 14543: case 14544: case 14548: case 14549: case 14550: case 14554: case 14555: case 14556: case 14560: case 14561: case 14562: case 14566: case 14567: case 14568: case 14572: case 14573: case 14574: case 14650: case 14651: case 14652: case 14656: case 14657: case 14658: case 14662: case 14663: case 14664: case 14668: case 14669: case 14670: case 14674: case 14675: case 14676: case 14680: case 14681: case 14682: return North::None; default: return North::Tall; } } enum South South(const BlockState Block) { switch (Block.ID) { case 14446: case 14447: case 14448: case 14452: case 14453: case 14454: case 14482: case 14483: case 14484: case 14488: case 14489: case 14490: case 14518: case 14519: case 14520: case 14524: case 14525: case 14526: case 14554: case 14555: case 14556: case 14560: case 14561: case 14562: case 14590: case 14591: case 14592: case 14596: case 14597: case 14598: case 14626: case 14627: case 14628: case 14632: case 14633: case 14634: case 14662: case 14663: case 14664: case 14668: case 14669: case 14670: case 14698: case 14699: case 14700: case 14704: case 14705: case 14706: case 14734: case 14735: case 14736: case 14740: case 14741: case 14742: return South::Low; case 14434: case 14435: case 14436: case 14440: case 14441: case 14442: case 14470: case 14471: case 14472: case 14476: case 14477: case 14478: case 14506: case 14507: case 14508: case 14512: case 14513: case 14514: case 14542: case 14543: case 14544: case 14548: case 14549: case 14550: case 14578: case 14579: case 14580: case 14584: case 14585: case 14586: case 14614: case 14615: case 14616: case 14620: case 14621: case 14622: case 14650: case 14651: case 14652: case 14656: case 14657: case 14658: case 14686: case 14687: case 14688: case 14692: case 14693: case 14694: case 14722: case 14723: case 14724: case 14728: case 14729: case 14730: return South::None; default: return South::Tall; } } bool Up(const BlockState Block) { switch (Block.ID) { case 14440: case 14441: case 14442: case 14452: case 14453: case 14454: case 14464: case 14465: case 14466: case 14476: case 14477: case 14478: case 14488: case 14489: case 14490: case 14500: case 14501: case 14502: case 14512: case 14513: case 14514: case 14524: case 14525: case 14526: case 14536: case 14537: case 14538: case 14548: case 14549: case 14550: case 14560: case 14561: case 14562: case 14572: case 14573: case 14574: case 14584: case 14585: case 14586: case 14596: case 14597: case 14598: case 14608: case 14609: case 14610: case 14620: case 14621: case 14622: case 14632: case 14633: case 14634: case 14644: case 14645: case 14646: case 14656: case 14657: case 14658: case 14668: case 14669: case 14670: case 14680: case 14681: case 14682: case 14692: case 14693: case 14694: case 14704: case 14705: case 14706: case 14716: case 14717: case 14718: case 14728: case 14729: case 14730: case 14740: case 14741: case 14742: case 14752: case 14753: case 14754: return false; default: return true; } } enum West West(const BlockState Block) { switch (Block.ID) { case 14435: case 14441: case 14447: case 14453: case 14459: case 14465: case 14471: case 14477: case 14483: case 14489: case 14495: case 14501: case 14507: case 14513: case 14519: case 14525: case 14531: case 14537: case 14543: case 14549: case 14555: case 14561: case 14567: case 14573: case 14579: case 14585: case 14591: case 14597: case 14603: case 14609: case 14615: case 14621: case 14627: case 14633: case 14639: case 14645: case 14651: case 14657: case 14663: case 14669: case 14675: case 14681: case 14687: case 14693: case 14699: case 14705: case 14711: case 14717: case 14723: case 14729: case 14735: case 14741: case 14747: case 14753: return West::Low; case 14434: case 14440: case 14446: case 14452: case 14458: case 14464: case 14470: case 14476: case 14482: case 14488: case 14494: case 14500: case 14506: case 14512: case 14518: case 14524: case 14530: case 14536: case 14542: case 14548: case 14554: case 14560: case 14566: case 14572: case 14578: case 14584: case 14590: case 14596: case 14602: case 14608: case 14614: case 14620: case 14626: case 14632: case 14638: case 14644: case 14650: case 14656: case 14662: case 14668: case 14674: case 14680: case 14686: case 14692: case 14698: case 14704: case 14710: case 14716: case 14722: case 14728: case 14734: case 14740: case 14746: case 14752: return West::None; default: return West::Tall; } } } namespace Dirt { } namespace Dispenser { BlockState Dispenser() { return 235; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 240: case 241: return eBlockFace::BLOCK_FACE_XM; case 236: case 237: return eBlockFace::BLOCK_FACE_XP; case 244: case 245: return eBlockFace::BLOCK_FACE_YM; case 242: case 243: return eBlockFace::BLOCK_FACE_YP; case 234: case 235: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } bool Triggered(const BlockState Block) { switch (Block.ID) { case 235: case 237: case 239: case 241: case 243: case 245: return false; default: return true; } } } namespace DragonEgg { } namespace DragonHead { BlockState DragonHead() { return 6590; } unsigned char Rotation(const BlockState Block) { switch (Block.ID) { case 6590: return 0; case 6591: return 1; case 6600: return 10; case 6601: return 11; case 6602: return 12; case 6603: return 13; case 6604: return 14; case 6605: return 15; case 6592: return 2; case 6593: return 3; case 6594: return 4; case 6595: return 5; case 6596: return 6; case 6597: return 7; case 6598: return 8; default: return 9; } } } namespace DragonWallHead { BlockState DragonWallHead() { return 6606; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 6608: return eBlockFace::BLOCK_FACE_XM; case 6609: return eBlockFace::BLOCK_FACE_XP; case 6606: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace DriedKelpBlock { } namespace Dropper { BlockState Dropper() { return 6836; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 6841: case 6842: return eBlockFace::BLOCK_FACE_XM; case 6837: case 6838: return eBlockFace::BLOCK_FACE_XP; case 6845: case 6846: return eBlockFace::BLOCK_FACE_YM; case 6843: case 6844: return eBlockFace::BLOCK_FACE_YP; case 6835: case 6836: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } bool Triggered(const BlockState Block) { switch (Block.ID) { case 6836: case 6838: case 6840: case 6842: case 6844: case 6846: return false; default: return true; } } } namespace EmeraldBlock { } namespace EmeraldOre { } namespace EnchantingTable { } namespace EndGateway { } namespace EndPortal { } namespace EndPortalFrame { BlockState EndPortalFrame() { return 5150; } bool Eye(const BlockState Block) { switch (Block.ID) { case 5150: case 5151: case 5152: case 5153: return false; default: return true; } } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 5148: case 5152: return eBlockFace::BLOCK_FACE_XM; case 5149: case 5153: return eBlockFace::BLOCK_FACE_XP; case 5146: case 5150: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace EndRod { BlockState EndRod() { return 9062; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 9061: return eBlockFace::BLOCK_FACE_XM; case 9059: return eBlockFace::BLOCK_FACE_XP; case 9063: return eBlockFace::BLOCK_FACE_YM; case 9062: return eBlockFace::BLOCK_FACE_YP; case 9058: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace EndStone { } namespace EndStoneBrickSlab { BlockState EndStoneBrickSlab() { return 10822; } enum Type Type(const BlockState Block) { switch (Block.ID) { case 10822: return Type::Bottom; case 10824: return Type::Double; default: return Type::Top; } } } namespace EndStoneBrickStairs { BlockState EndStoneBrickStairs() { return 10080; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 10110: case 10112: case 10114: case 10116: case 10118: case 10120: case 10122: case 10124: case 10126: case 10128: return eBlockFace::BLOCK_FACE_XM; case 10130: case 10132: case 10134: case 10136: case 10138: case 10140: case 10142: case 10144: case 10146: case 10148: return eBlockFace::BLOCK_FACE_XP; case 10070: case 10072: case 10074: case 10076: case 10078: case 10080: case 10082: case 10084: case 10086: case 10088: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } enum Half Half(const BlockState Block) { switch (Block.ID) { case 10080: case 10082: case 10084: case 10086: case 10088: case 10100: case 10102: case 10104: case 10106: case 10108: case 10120: case 10122: case 10124: case 10126: case 10128: case 10140: case 10142: case 10144: case 10146: case 10148: return Half::Bottom; default: return Half::Top; } } enum Shape Shape(const BlockState Block) { switch (Block.ID) { case 10072: case 10082: case 10092: case 10102: case 10112: case 10122: case 10132: case 10142: return Shape::InnerLeft; case 10074: case 10084: case 10094: case 10104: case 10114: case 10124: case 10134: case 10144: return Shape::InnerRight; case 10076: case 10086: case 10096: case 10106: case 10116: case 10126: case 10136: case 10146: return Shape::OuterLeft; case 10078: case 10088: case 10098: case 10108: case 10118: case 10128: case 10138: case 10148: return Shape::OuterRight; default: return Shape::Straight; } } } namespace EndStoneBrickWall { BlockState EndStoneBrickWall() { return 14110; } enum East East(const BlockState Block) { switch (Block.ID) { case 14218: case 14219: case 14220: case 14224: case 14225: case 14226: case 14230: case 14231: case 14232: case 14236: case 14237: case 14238: case 14242: case 14243: case 14244: case 14248: case 14249: case 14250: case 14254: case 14255: case 14256: case 14260: case 14261: case 14262: case 14266: case 14267: case 14268: case 14272: case 14273: case 14274: case 14278: case 14279: case 14280: case 14284: case 14285: case 14286: case 14290: case 14291: case 14292: case 14296: case 14297: case 14298: case 14302: case 14303: case 14304: case 14308: case 14309: case 14310: case 14314: case 14315: case 14316: case 14320: case 14321: case 14322: return East::Low; case 14110: case 14111: case 14112: case 14116: case 14117: case 14118: case 14122: case 14123: case 14124: case 14128: case 14129: case 14130: case 14134: case 14135: case 14136: case 14140: case 14141: case 14142: case 14146: case 14147: case 14148: case 14152: case 14153: case 14154: case 14158: case 14159: case 14160: case 14164: case 14165: case 14166: case 14170: case 14171: case 14172: case 14176: case 14177: case 14178: case 14182: case 14183: case 14184: case 14188: case 14189: case 14190: case 14194: case 14195: case 14196: case 14200: case 14201: case 14202: case 14206: case 14207: case 14208: case 14212: case 14213: case 14214: return East::None; default: return East::Tall; } } enum North North(const BlockState Block) { switch (Block.ID) { case 14146: case 14147: case 14148: case 14152: case 14153: case 14154: case 14158: case 14159: case 14160: case 14164: case 14165: case 14166: case 14170: case 14171: case 14172: case 14176: case 14177: case 14178: case 14254: case 14255: case 14256: case 14260: case 14261: case 14262: case 14266: case 14267: case 14268: case 14272: case 14273: case 14274: case 14278: case 14279: case 14280: case 14284: case 14285: case 14286: case 14362: case 14363: case 14364: case 14368: case 14369: case 14370: case 14374: case 14375: case 14376: case 14380: case 14381: case 14382: case 14386: case 14387: case 14388: case 14392: case 14393: case 14394: return North::Low; case 14110: case 14111: case 14112: case 14116: case 14117: case 14118: case 14122: case 14123: case 14124: case 14128: case 14129: case 14130: case 14134: case 14135: case 14136: case 14140: case 14141: case 14142: case 14218: case 14219: case 14220: case 14224: case 14225: case 14226: case 14230: case 14231: case 14232: case 14236: case 14237: case 14238: case 14242: case 14243: case 14244: case 14248: case 14249: case 14250: case 14326: case 14327: case 14328: case 14332: case 14333: case 14334: case 14338: case 14339: case 14340: case 14344: case 14345: case 14346: case 14350: case 14351: case 14352: case 14356: case 14357: case 14358: return North::None; default: return North::Tall; } } enum South South(const BlockState Block) { switch (Block.ID) { case 14122: case 14123: case 14124: case 14128: case 14129: case 14130: case 14158: case 14159: case 14160: case 14164: case 14165: case 14166: case 14194: case 14195: case 14196: case 14200: case 14201: case 14202: case 14230: case 14231: case 14232: case 14236: case 14237: case 14238: case 14266: case 14267: case 14268: case 14272: case 14273: case 14274: case 14302: case 14303: case 14304: case 14308: case 14309: case 14310: case 14338: case 14339: case 14340: case 14344: case 14345: case 14346: case 14374: case 14375: case 14376: case 14380: case 14381: case 14382: case 14410: case 14411: case 14412: case 14416: case 14417: case 14418: return South::Low; case 14110: case 14111: case 14112: case 14116: case 14117: case 14118: case 14146: case 14147: case 14148: case 14152: case 14153: case 14154: case 14182: case 14183: case 14184: case 14188: case 14189: case 14190: case 14218: case 14219: case 14220: case 14224: case 14225: case 14226: case 14254: case 14255: case 14256: case 14260: case 14261: case 14262: case 14290: case 14291: case 14292: case 14296: case 14297: case 14298: case 14326: case 14327: case 14328: case 14332: case 14333: case 14334: case 14362: case 14363: case 14364: case 14368: case 14369: case 14370: case 14398: case 14399: case 14400: case 14404: case 14405: case 14406: return South::None; default: return South::Tall; } } bool Up(const BlockState Block) { switch (Block.ID) { case 14116: case 14117: case 14118: case 14128: case 14129: case 14130: case 14140: case 14141: case 14142: case 14152: case 14153: case 14154: case 14164: case 14165: case 14166: case 14176: case 14177: case 14178: case 14188: case 14189: case 14190: case 14200: case 14201: case 14202: case 14212: case 14213: case 14214: case 14224: case 14225: case 14226: case 14236: case 14237: case 14238: case 14248: case 14249: case 14250: case 14260: case 14261: case 14262: case 14272: case 14273: case 14274: case 14284: case 14285: case 14286: case 14296: case 14297: case 14298: case 14308: case 14309: case 14310: case 14320: case 14321: case 14322: case 14332: case 14333: case 14334: case 14344: case 14345: case 14346: case 14356: case 14357: case 14358: case 14368: case 14369: case 14370: case 14380: case 14381: case 14382: case 14392: case 14393: case 14394: case 14404: case 14405: case 14406: case 14416: case 14417: case 14418: case 14428: case 14429: case 14430: return false; default: return true; } } enum West West(const BlockState Block) { switch (Block.ID) { case 14111: case 14117: case 14123: case 14129: case 14135: case 14141: case 14147: case 14153: case 14159: case 14165: case 14171: case 14177: case 14183: case 14189: case 14195: case 14201: case 14207: case 14213: case 14219: case 14225: case 14231: case 14237: case 14243: case 14249: case 14255: case 14261: case 14267: case 14273: case 14279: case 14285: case 14291: case 14297: case 14303: case 14309: case 14315: case 14321: case 14327: case 14333: case 14339: case 14345: case 14351: case 14357: case 14363: case 14369: case 14375: case 14381: case 14387: case 14393: case 14399: case 14405: case 14411: case 14417: case 14423: case 14429: return West::Low; case 14110: case 14116: case 14122: case 14128: case 14134: case 14140: case 14146: case 14152: case 14158: case 14164: case 14170: case 14176: case 14182: case 14188: case 14194: case 14200: case 14206: case 14212: case 14218: case 14224: case 14230: case 14236: case 14242: case 14248: case 14254: case 14260: case 14266: case 14272: case 14278: case 14284: case 14290: case 14296: case 14302: case 14308: case 14314: case 14320: case 14326: case 14332: case 14338: case 14344: case 14350: case 14356: case 14362: case 14368: case 14374: case 14380: case 14386: case 14392: case 14398: case 14404: case 14410: case 14416: case 14422: case 14428: return West::None; default: return West::Tall; } } } namespace EndStoneBricks { } namespace EnderChest { BlockState EnderChest() { return 5252; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 5256: return eBlockFace::BLOCK_FACE_XM; case 5258: return eBlockFace::BLOCK_FACE_XP; case 5252: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace Farmland { BlockState Farmland() { return 3365; } unsigned char Moisture(const BlockState Block) { switch (Block.ID) { case 3365: return 0; case 3366: return 1; case 3367: return 2; case 3368: return 3; case 3369: return 4; case 3370: return 5; case 3371: return 6; default: return 7; } } } namespace Fern { } namespace Fire { BlockState Fire() { return 1471; } unsigned char Age(const BlockState Block) { switch (Block.ID) { case 1440: case 1441: case 1442: case 1443: case 1444: case 1445: case 1446: case 1447: case 1448: case 1449: case 1450: case 1451: case 1452: case 1453: case 1454: case 1455: case 1456: case 1457: case 1458: case 1459: case 1460: case 1461: case 1462: case 1463: case 1464: case 1465: case 1466: case 1467: case 1468: case 1469: case 1470: case 1471: return 0; case 1472: case 1473: case 1474: case 1475: case 1476: case 1477: case 1478: case 1479: case 1480: case 1481: case 1482: case 1483: case 1484: case 1485: case 1486: case 1487: case 1488: case 1489: case 1490: case 1491: case 1492: case 1493: case 1494: case 1495: case 1496: case 1497: case 1498: case 1499: case 1500: case 1501: case 1502: case 1503: return 1; case 1760: case 1761: case 1762: case 1763: case 1764: case 1765: case 1766: case 1767: case 1768: case 1769: case 1770: case 1771: case 1772: case 1773: case 1774: case 1775: case 1776: case 1777: case 1778: case 1779: case 1780: case 1781: case 1782: case 1783: case 1784: case 1785: case 1786: case 1787: case 1788: case 1789: case 1790: case 1791: return 10; case 1792: case 1793: case 1794: case 1795: case 1796: case 1797: case 1798: case 1799: case 1800: case 1801: case 1802: case 1803: case 1804: case 1805: case 1806: case 1807: case 1808: case 1809: case 1810: case 1811: case 1812: case 1813: case 1814: case 1815: case 1816: case 1817: case 1818: case 1819: case 1820: case 1821: case 1822: case 1823: return 11; case 1824: case 1825: case 1826: case 1827: case 1828: case 1829: case 1830: case 1831: case 1832: case 1833: case 1834: case 1835: case 1836: case 1837: case 1838: case 1839: case 1840: case 1841: case 1842: case 1843: case 1844: case 1845: case 1846: case 1847: case 1848: case 1849: case 1850: case 1851: case 1852: case 1853: case 1854: case 1855: return 12; case 1856: case 1857: case 1858: case 1859: case 1860: case 1861: case 1862: case 1863: case 1864: case 1865: case 1866: case 1867: case 1868: case 1869: case 1870: case 1871: case 1872: case 1873: case 1874: case 1875: case 1876: case 1877: case 1878: case 1879: case 1880: case 1881: case 1882: case 1883: case 1884: case 1885: case 1886: case 1887: return 13; case 1888: case 1889: case 1890: case 1891: case 1892: case 1893: case 1894: case 1895: case 1896: case 1897: case 1898: case 1899: case 1900: case 1901: case 1902: case 1903: case 1904: case 1905: case 1906: case 1907: case 1908: case 1909: case 1910: case 1911: case 1912: case 1913: case 1914: case 1915: case 1916: case 1917: case 1918: case 1919: return 14; case 1920: case 1921: case 1922: case 1923: case 1924: case 1925: case 1926: case 1927: case 1928: case 1929: case 1930: case 1931: case 1932: case 1933: case 1934: case 1935: case 1936: case 1937: case 1938: case 1939: case 1940: case 1941: case 1942: case 1943: case 1944: case 1945: case 1946: case 1947: case 1948: case 1949: case 1950: case 1951: return 15; case 1504: case 1505: case 1506: case 1507: case 1508: case 1509: case 1510: case 1511: case 1512: case 1513: case 1514: case 1515: case 1516: case 1517: case 1518: case 1519: case 1520: case 1521: case 1522: case 1523: case 1524: case 1525: case 1526: case 1527: case 1528: case 1529: case 1530: case 1531: case 1532: case 1533: case 1534: case 1535: return 2; case 1536: case 1537: case 1538: case 1539: case 1540: case 1541: case 1542: case 1543: case 1544: case 1545: case 1546: case 1547: case 1548: case 1549: case 1550: case 1551: case 1552: case 1553: case 1554: case 1555: case 1556: case 1557: case 1558: case 1559: case 1560: case 1561: case 1562: case 1563: case 1564: case 1565: case 1566: case 1567: return 3; case 1568: case 1569: case 1570: case 1571: case 1572: case 1573: case 1574: case 1575: case 1576: case 1577: case 1578: case 1579: case 1580: case 1581: case 1582: case 1583: case 1584: case 1585: case 1586: case 1587: case 1588: case 1589: case 1590: case 1591: case 1592: case 1593: case 1594: case 1595: case 1596: case 1597: case 1598: case 1599: return 4; case 1600: case 1601: case 1602: case 1603: case 1604: case 1605: case 1606: case 1607: case 1608: case 1609: case 1610: case 1611: case 1612: case 1613: case 1614: case 1615: case 1616: case 1617: case 1618: case 1619: case 1620: case 1621: case 1622: case 1623: case 1624: case 1625: case 1626: case 1627: case 1628: case 1629: case 1630: case 1631: return 5; case 1632: case 1633: case 1634: case 1635: case 1636: case 1637: case 1638: case 1639: case 1640: case 1641: case 1642: case 1643: case 1644: case 1645: case 1646: case 1647: case 1648: case 1649: case 1650: case 1651: case 1652: case 1653: case 1654: case 1655: case 1656: case 1657: case 1658: case 1659: case 1660: case 1661: case 1662: case 1663: return 6; case 1664: case 1665: case 1666: case 1667: case 1668: case 1669: case 1670: case 1671: case 1672: case 1673: case 1674: case 1675: case 1676: case 1677: case 1678: case 1679: case 1680: case 1681: case 1682: case 1683: case 1684: case 1685: case 1686: case 1687: case 1688: case 1689: case 1690: case 1691: case 1692: case 1693: case 1694: case 1695: return 7; case 1696: case 1697: case 1698: case 1699: case 1700: case 1701: case 1702: case 1703: case 1704: case 1705: case 1706: case 1707: case 1708: case 1709: case 1710: case 1711: case 1712: case 1713: case 1714: case 1715: case 1716: case 1717: case 1718: case 1719: case 1720: case 1721: case 1722: case 1723: case 1724: case 1725: case 1726: case 1727: return 8; default: return 9; } } bool East(const BlockState Block) { switch (Block.ID) { case 1456: case 1457: case 1458: case 1459: case 1460: case 1461: case 1462: case 1463: case 1464: case 1465: case 1466: case 1467: case 1468: case 1469: case 1470: case 1471: case 1488: case 1489: case 1490: case 1491: case 1492: case 1493: case 1494: case 1495: case 1496: case 1497: case 1498: case 1499: case 1500: case 1501: case 1502: case 1503: case 1520: case 1521: case 1522: case 1523: case 1524: case 1525: case 1526: case 1527: case 1528: case 1529: case 1530: case 1531: case 1532: case 1533: case 1534: case 1535: case 1552: case 1553: case 1554: case 1555: case 1556: case 1557: case 1558: case 1559: case 1560: case 1561: case 1562: case 1563: case 1564: case 1565: case 1566: case 1567: case 1584: case 1585: case 1586: case 1587: case 1588: case 1589: case 1590: case 1591: case 1592: case 1593: case 1594: case 1595: case 1596: case 1597: case 1598: case 1599: case 1616: case 1617: case 1618: case 1619: case 1620: case 1621: case 1622: case 1623: case 1624: case 1625: case 1626: case 1627: case 1628: case 1629: case 1630: case 1631: case 1648: case 1649: case 1650: case 1651: case 1652: case 1653: case 1654: case 1655: case 1656: case 1657: case 1658: case 1659: case 1660: case 1661: case 1662: case 1663: case 1680: case 1681: case 1682: case 1683: case 1684: case 1685: case 1686: case 1687: case 1688: case 1689: case 1690: case 1691: case 1692: case 1693: case 1694: case 1695: case 1712: case 1713: case 1714: case 1715: case 1716: case 1717: case 1718: case 1719: case 1720: case 1721: case 1722: case 1723: case 1724: case 1725: case 1726: case 1727: case 1744: case 1745: case 1746: case 1747: case 1748: case 1749: case 1750: case 1751: case 1752: case 1753: case 1754: case 1755: case 1756: case 1757: case 1758: case 1759: case 1776: case 1777: case 1778: case 1779: case 1780: case 1781: case 1782: case 1783: case 1784: case 1785: case 1786: case 1787: case 1788: case 1789: case 1790: case 1791: case 1808: case 1809: case 1810: case 1811: case 1812: case 1813: case 1814: case 1815: case 1816: case 1817: case 1818: case 1819: case 1820: case 1821: case 1822: case 1823: case 1840: case 1841: case 1842: case 1843: case 1844: case 1845: case 1846: case 1847: case 1848: case 1849: case 1850: case 1851: case 1852: case 1853: case 1854: case 1855: case 1872: case 1873: case 1874: case 1875: case 1876: case 1877: case 1878: case 1879: case 1880: case 1881: case 1882: case 1883: case 1884: case 1885: case 1886: case 1887: case 1904: case 1905: case 1906: case 1907: case 1908: case 1909: case 1910: case 1911: case 1912: case 1913: case 1914: case 1915: case 1916: case 1917: case 1918: case 1919: case 1936: case 1937: case 1938: case 1939: case 1940: case 1941: case 1942: case 1943: case 1944: case 1945: case 1946: case 1947: case 1948: case 1949: case 1950: case 1951: return false; default: return true; } } bool North(const BlockState Block) { switch (Block.ID) { case 1448: case 1449: case 1450: case 1451: case 1452: case 1453: case 1454: case 1455: case 1464: case 1465: case 1466: case 1467: case 1468: case 1469: case 1470: case 1471: case 1480: case 1481: case 1482: case 1483: case 1484: case 1485: case 1486: case 1487: case 1496: case 1497: case 1498: case 1499: case 1500: case 1501: case 1502: case 1503: case 1512: case 1513: case 1514: case 1515: case 1516: case 1517: case 1518: case 1519: case 1528: case 1529: case 1530: case 1531: case 1532: case 1533: case 1534: case 1535: case 1544: case 1545: case 1546: case 1547: case 1548: case 1549: case 1550: case 1551: case 1560: case 1561: case 1562: case 1563: case 1564: case 1565: case 1566: case 1567: case 1576: case 1577: case 1578: case 1579: case 1580: case 1581: case 1582: case 1583: case 1592: case 1593: case 1594: case 1595: case 1596: case 1597: case 1598: case 1599: case 1608: case 1609: case 1610: case 1611: case 1612: case 1613: case 1614: case 1615: case 1624: case 1625: case 1626: case 1627: case 1628: case 1629: case 1630: case 1631: case 1640: case 1641: case 1642: case 1643: case 1644: case 1645: case 1646: case 1647: case 1656: case 1657: case 1658: case 1659: case 1660: case 1661: case 1662: case 1663: case 1672: case 1673: case 1674: case 1675: case 1676: case 1677: case 1678: case 1679: case 1688: case 1689: case 1690: case 1691: case 1692: case 1693: case 1694: case 1695: case 1704: case 1705: case 1706: case 1707: case 1708: case 1709: case 1710: case 1711: case 1720: case 1721: case 1722: case 1723: case 1724: case 1725: case 1726: case 1727: case 1736: case 1737: case 1738: case 1739: case 1740: case 1741: case 1742: case 1743: case 1752: case 1753: case 1754: case 1755: case 1756: case 1757: case 1758: case 1759: case 1768: case 1769: case 1770: case 1771: case 1772: case 1773: case 1774: case 1775: case 1784: case 1785: case 1786: case 1787: case 1788: case 1789: case 1790: case 1791: case 1800: case 1801: case 1802: case 1803: case 1804: case 1805: case 1806: case 1807: case 1816: case 1817: case 1818: case 1819: case 1820: case 1821: case 1822: case 1823: case 1832: case 1833: case 1834: case 1835: case 1836: case 1837: case 1838: case 1839: case 1848: case 1849: case 1850: case 1851: case 1852: case 1853: case 1854: case 1855: case 1864: case 1865: case 1866: case 1867: case 1868: case 1869: case 1870: case 1871: case 1880: case 1881: case 1882: case 1883: case 1884: case 1885: case 1886: case 1887: case 1896: case 1897: case 1898: case 1899: case 1900: case 1901: case 1902: case 1903: case 1912: case 1913: case 1914: case 1915: case 1916: case 1917: case 1918: case 1919: case 1928: case 1929: case 1930: case 1931: case 1932: case 1933: case 1934: case 1935: case 1944: case 1945: case 1946: case 1947: case 1948: case 1949: case 1950: case 1951: return false; default: return true; } } bool South(const BlockState Block) { switch (Block.ID) { case 1444: case 1445: case 1446: case 1447: case 1452: case 1453: case 1454: case 1455: case 1460: case 1461: case 1462: case 1463: case 1468: case 1469: case 1470: case 1471: case 1476: case 1477: case 1478: case 1479: case 1484: case 1485: case 1486: case 1487: case 1492: case 1493: case 1494: case 1495: case 1500: case 1501: case 1502: case 1503: case 1508: case 1509: case 1510: case 1511: case 1516: case 1517: case 1518: case 1519: case 1524: case 1525: case 1526: case 1527: case 1532: case 1533: case 1534: case 1535: case 1540: case 1541: case 1542: case 1543: case 1548: case 1549: case 1550: case 1551: case 1556: case 1557: case 1558: case 1559: case 1564: case 1565: case 1566: case 1567: case 1572: case 1573: case 1574: case 1575: case 1580: case 1581: case 1582: case 1583: case 1588: case 1589: case 1590: case 1591: case 1596: case 1597: case 1598: case 1599: case 1604: case 1605: case 1606: case 1607: case 1612: case 1613: case 1614: case 1615: case 1620: case 1621: case 1622: case 1623: case 1628: case 1629: case 1630: case 1631: case 1636: case 1637: case 1638: case 1639: case 1644: case 1645: case 1646: case 1647: case 1652: case 1653: case 1654: case 1655: case 1660: case 1661: case 1662: case 1663: case 1668: case 1669: case 1670: case 1671: case 1676: case 1677: case 1678: case 1679: case 1684: case 1685: case 1686: case 1687: case 1692: case 1693: case 1694: case 1695: case 1700: case 1701: case 1702: case 1703: case 1708: case 1709: case 1710: case 1711: case 1716: case 1717: case 1718: case 1719: case 1724: case 1725: case 1726: case 1727: case 1732: case 1733: case 1734: case 1735: case 1740: case 1741: case 1742: case 1743: case 1748: case 1749: case 1750: case 1751: case 1756: case 1757: case 1758: case 1759: case 1764: case 1765: case 1766: case 1767: case 1772: case 1773: case 1774: case 1775: case 1780: case 1781: case 1782: case 1783: case 1788: case 1789: case 1790: case 1791: case 1796: case 1797: case 1798: case 1799: case 1804: case 1805: case 1806: case 1807: case 1812: case 1813: case 1814: case 1815: case 1820: case 1821: case 1822: case 1823: case 1828: case 1829: case 1830: case 1831: case 1836: case 1837: case 1838: case 1839: case 1844: case 1845: case 1846: case 1847: case 1852: case 1853: case 1854: case 1855: case 1860: case 1861: case 1862: case 1863: case 1868: case 1869: case 1870: case 1871: case 1876: case 1877: case 1878: case 1879: case 1884: case 1885: case 1886: case 1887: case 1892: case 1893: case 1894: case 1895: case 1900: case 1901: case 1902: case 1903: case 1908: case 1909: case 1910: case 1911: case 1916: case 1917: case 1918: case 1919: case 1924: case 1925: case 1926: case 1927: case 1932: case 1933: case 1934: case 1935: case 1940: case 1941: case 1942: case 1943: case 1948: case 1949: case 1950: case 1951: return false; default: return true; } } bool Up(const BlockState Block) { switch (Block.ID) { case 1442: case 1443: case 1446: case 1447: case 1450: case 1451: case 1454: case 1455: case 1458: case 1459: case 1462: case 1463: case 1466: case 1467: case 1470: case 1471: case 1474: case 1475: case 1478: case 1479: case 1482: case 1483: case 1486: case 1487: case 1490: case 1491: case 1494: case 1495: case 1498: case 1499: case 1502: case 1503: case 1506: case 1507: case 1510: case 1511: case 1514: case 1515: case 1518: case 1519: case 1522: case 1523: case 1526: case 1527: case 1530: case 1531: case 1534: case 1535: case 1538: case 1539: case 1542: case 1543: case 1546: case 1547: case 1550: case 1551: case 1554: case 1555: case 1558: case 1559: case 1562: case 1563: case 1566: case 1567: case 1570: case 1571: case 1574: case 1575: case 1578: case 1579: case 1582: case 1583: case 1586: case 1587: case 1590: case 1591: case 1594: case 1595: case 1598: case 1599: case 1602: case 1603: case 1606: case 1607: case 1610: case 1611: case 1614: case 1615: case 1618: case 1619: case 1622: case 1623: case 1626: case 1627: case 1630: case 1631: case 1634: case 1635: case 1638: case 1639: case 1642: case 1643: case 1646: case 1647: case 1650: case 1651: case 1654: case 1655: case 1658: case 1659: case 1662: case 1663: case 1666: case 1667: case 1670: case 1671: case 1674: case 1675: case 1678: case 1679: case 1682: case 1683: case 1686: case 1687: case 1690: case 1691: case 1694: case 1695: case 1698: case 1699: case 1702: case 1703: case 1706: case 1707: case 1710: case 1711: case 1714: case 1715: case 1718: case 1719: case 1722: case 1723: case 1726: case 1727: case 1730: case 1731: case 1734: case 1735: case 1738: case 1739: case 1742: case 1743: case 1746: case 1747: case 1750: case 1751: case 1754: case 1755: case 1758: case 1759: case 1762: case 1763: case 1766: case 1767: case 1770: case 1771: case 1774: case 1775: case 1778: case 1779: case 1782: case 1783: case 1786: case 1787: case 1790: case 1791: case 1794: case 1795: case 1798: case 1799: case 1802: case 1803: case 1806: case 1807: case 1810: case 1811: case 1814: case 1815: case 1818: case 1819: case 1822: case 1823: case 1826: case 1827: case 1830: case 1831: case 1834: case 1835: case 1838: case 1839: case 1842: case 1843: case 1846: case 1847: case 1850: case 1851: case 1854: case 1855: case 1858: case 1859: case 1862: case 1863: case 1866: case 1867: case 1870: case 1871: case 1874: case 1875: case 1878: case 1879: case 1882: case 1883: case 1886: case 1887: case 1890: case 1891: case 1894: case 1895: case 1898: case 1899: case 1902: case 1903: case 1906: case 1907: case 1910: case 1911: case 1914: case 1915: case 1918: case 1919: case 1922: case 1923: case 1926: case 1927: case 1930: case 1931: case 1934: case 1935: case 1938: case 1939: case 1942: case 1943: case 1946: case 1947: case 1950: case 1951: return false; default: return true; } } bool West(const BlockState Block) { switch (Block.ID) { case 1441: case 1443: case 1445: case 1447: case 1449: case 1451: case 1453: case 1455: case 1457: case 1459: case 1461: case 1463: case 1465: case 1467: case 1469: case 1471: case 1473: case 1475: case 1477: case 1479: case 1481: case 1483: case 1485: case 1487: case 1489: case 1491: case 1493: case 1495: case 1497: case 1499: case 1501: case 1503: case 1505: case 1507: case 1509: case 1511: case 1513: case 1515: case 1517: case 1519: case 1521: case 1523: case 1525: case 1527: case 1529: case 1531: case 1533: case 1535: case 1537: case 1539: case 1541: case 1543: case 1545: case 1547: case 1549: case 1551: case 1553: case 1555: case 1557: case 1559: case 1561: case 1563: case 1565: case 1567: case 1569: case 1571: case 1573: case 1575: case 1577: case 1579: case 1581: case 1583: case 1585: case 1587: case 1589: case 1591: case 1593: case 1595: case 1597: case 1599: case 1601: case 1603: case 1605: case 1607: case 1609: case 1611: case 1613: case 1615: case 1617: case 1619: case 1621: case 1623: case 1625: case 1627: case 1629: case 1631: case 1633: case 1635: case 1637: case 1639: case 1641: case 1643: case 1645: case 1647: case 1649: case 1651: case 1653: case 1655: case 1657: case 1659: case 1661: case 1663: case 1665: case 1667: case 1669: case 1671: case 1673: case 1675: case 1677: case 1679: case 1681: case 1683: case 1685: case 1687: case 1689: case 1691: case 1693: case 1695: case 1697: case 1699: case 1701: case 1703: case 1705: case 1707: case 1709: case 1711: case 1713: case 1715: case 1717: case 1719: case 1721: case 1723: case 1725: case 1727: case 1729: case 1731: case 1733: case 1735: case 1737: case 1739: case 1741: case 1743: case 1745: case 1747: case 1749: case 1751: case 1753: case 1755: case 1757: case 1759: case 1761: case 1763: case 1765: case 1767: case 1769: case 1771: case 1773: case 1775: case 1777: case 1779: case 1781: case 1783: case 1785: case 1787: case 1789: case 1791: case 1793: case 1795: case 1797: case 1799: case 1801: case 1803: case 1805: case 1807: case 1809: case 1811: case 1813: case 1815: case 1817: case 1819: case 1821: case 1823: case 1825: case 1827: case 1829: case 1831: case 1833: case 1835: case 1837: case 1839: case 1841: case 1843: case 1845: case 1847: case 1849: case 1851: case 1853: case 1855: case 1857: case 1859: case 1861: case 1863: case 1865: case 1867: case 1869: case 1871: case 1873: case 1875: case 1877: case 1879: case 1881: case 1883: case 1885: case 1887: case 1889: case 1891: case 1893: case 1895: case 1897: case 1899: case 1901: case 1903: case 1905: case 1907: case 1909: case 1911: case 1913: case 1915: case 1917: case 1919: case 1921: case 1923: case 1925: case 1927: case 1929: case 1931: case 1933: case 1935: case 1937: case 1939: case 1941: case 1943: case 1945: case 1947: case 1949: case 1951: return false; default: return true; } } } namespace FireCoral { } namespace FireCoralBlock { } namespace FireCoralFan { } namespace FireCoralWallFan { BlockState FireCoralWallFan() { return 9624; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 9629: return eBlockFace::BLOCK_FACE_XM; case 9631: return eBlockFace::BLOCK_FACE_XP; case 9625: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace FletchingTable { } namespace FlowerPot { } namespace FrostedIce { BlockState FrostedIce() { return 9249; } unsigned char Age(const BlockState Block) { switch (Block.ID) { case 9249: return 0; case 9250: return 1; case 9251: return 2; default: return 3; } } } namespace Furnace { BlockState Furnace() { return 3374; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 3377: case 3378: return eBlockFace::BLOCK_FACE_XM; case 3379: case 3380: return eBlockFace::BLOCK_FACE_XP; case 3373: case 3374: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } bool Lit(const BlockState Block) { switch (Block.ID) { case 3374: case 3376: case 3378: case 3380: return false; default: return true; } } } namespace GildedBlackstone { } namespace Glass { } namespace GlassPane { BlockState GlassPane() { return 4762; } bool East(const BlockState Block) { switch (Block.ID) { case 4749: case 4750: case 4753: case 4754: case 4757: case 4758: case 4761: case 4762: return false; default: return true; } } bool North(const BlockState Block) { switch (Block.ID) { case 4741: case 4742: case 4745: case 4746: case 4757: case 4758: case 4761: case 4762: return false; default: return true; } } bool South(const BlockState Block) { switch (Block.ID) { case 4737: case 4738: case 4745: case 4746: case 4753: case 4754: case 4761: case 4762: return false; default: return true; } } bool West(const BlockState Block) { switch (Block.ID) { case 4734: case 4738: case 4742: case 4746: case 4750: case 4754: case 4758: case 4762: return false; default: return true; } } } namespace Glowstone { } namespace GoldBlock { } namespace GoldOre { } namespace Granite { } namespace GraniteSlab { BlockState GraniteSlab() { return 10840; } enum Type Type(const BlockState Block) { switch (Block.ID) { case 10840: return Type::Bottom; case 10842: return Type::Double; default: return Type::Top; } } } namespace GraniteStairs { BlockState GraniteStairs() { return 10400; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 10430: case 10432: case 10434: case 10436: case 10438: case 10440: case 10442: case 10444: case 10446: case 10448: return eBlockFace::BLOCK_FACE_XM; case 10450: case 10452: case 10454: case 10456: case 10458: case 10460: case 10462: case 10464: case 10466: case 10468: return eBlockFace::BLOCK_FACE_XP; case 10390: case 10392: case 10394: case 10396: case 10398: case 10400: case 10402: case 10404: case 10406: case 10408: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } enum Half Half(const BlockState Block) { switch (Block.ID) { case 10400: case 10402: case 10404: case 10406: case 10408: case 10420: case 10422: case 10424: case 10426: case 10428: case 10440: case 10442: case 10444: case 10446: case 10448: case 10460: case 10462: case 10464: case 10466: case 10468: return Half::Bottom; default: return Half::Top; } } enum Shape Shape(const BlockState Block) { switch (Block.ID) { case 10392: case 10402: case 10412: case 10422: case 10432: case 10442: case 10452: case 10462: return Shape::InnerLeft; case 10394: case 10404: case 10414: case 10424: case 10434: case 10444: case 10454: case 10464: return Shape::InnerRight; case 10396: case 10406: case 10416: case 10426: case 10436: case 10446: case 10456: case 10466: return Shape::OuterLeft; case 10398: case 10408: case 10418: case 10428: case 10438: case 10448: case 10458: case 10468: return Shape::OuterRight; default: return Shape::Straight; } } } namespace GraniteWall { BlockState GraniteWall() { return 12166; } enum East East(const BlockState Block) { switch (Block.ID) { case 12274: case 12275: case 12276: case 12280: case 12281: case 12282: case 12286: case 12287: case 12288: case 12292: case 12293: case 12294: case 12298: case 12299: case 12300: case 12304: case 12305: case 12306: case 12310: case 12311: case 12312: case 12316: case 12317: case 12318: case 12322: case 12323: case 12324: case 12328: case 12329: case 12330: case 12334: case 12335: case 12336: case 12340: case 12341: case 12342: case 12346: case 12347: case 12348: case 12352: case 12353: case 12354: case 12358: case 12359: case 12360: case 12364: case 12365: case 12366: case 12370: case 12371: case 12372: case 12376: case 12377: case 12378: return East::Low; case 12166: case 12167: case 12168: case 12172: case 12173: case 12174: case 12178: case 12179: case 12180: case 12184: case 12185: case 12186: case 12190: case 12191: case 12192: case 12196: case 12197: case 12198: case 12202: case 12203: case 12204: case 12208: case 12209: case 12210: case 12214: case 12215: case 12216: case 12220: case 12221: case 12222: case 12226: case 12227: case 12228: case 12232: case 12233: case 12234: case 12238: case 12239: case 12240: case 12244: case 12245: case 12246: case 12250: case 12251: case 12252: case 12256: case 12257: case 12258: case 12262: case 12263: case 12264: case 12268: case 12269: case 12270: return East::None; default: return East::Tall; } } enum North North(const BlockState Block) { switch (Block.ID) { case 12202: case 12203: case 12204: case 12208: case 12209: case 12210: case 12214: case 12215: case 12216: case 12220: case 12221: case 12222: case 12226: case 12227: case 12228: case 12232: case 12233: case 12234: case 12310: case 12311: case 12312: case 12316: case 12317: case 12318: case 12322: case 12323: case 12324: case 12328: case 12329: case 12330: case 12334: case 12335: case 12336: case 12340: case 12341: case 12342: case 12418: case 12419: case 12420: case 12424: case 12425: case 12426: case 12430: case 12431: case 12432: case 12436: case 12437: case 12438: case 12442: case 12443: case 12444: case 12448: case 12449: case 12450: return North::Low; case 12166: case 12167: case 12168: case 12172: case 12173: case 12174: case 12178: case 12179: case 12180: case 12184: case 12185: case 12186: case 12190: case 12191: case 12192: case 12196: case 12197: case 12198: case 12274: case 12275: case 12276: case 12280: case 12281: case 12282: case 12286: case 12287: case 12288: case 12292: case 12293: case 12294: case 12298: case 12299: case 12300: case 12304: case 12305: case 12306: case 12382: case 12383: case 12384: case 12388: case 12389: case 12390: case 12394: case 12395: case 12396: case 12400: case 12401: case 12402: case 12406: case 12407: case 12408: case 12412: case 12413: case 12414: return North::None; default: return North::Tall; } } enum South South(const BlockState Block) { switch (Block.ID) { case 12178: case 12179: case 12180: case 12184: case 12185: case 12186: case 12214: case 12215: case 12216: case 12220: case 12221: case 12222: case 12250: case 12251: case 12252: case 12256: case 12257: case 12258: case 12286: case 12287: case 12288: case 12292: case 12293: case 12294: case 12322: case 12323: case 12324: case 12328: case 12329: case 12330: case 12358: case 12359: case 12360: case 12364: case 12365: case 12366: case 12394: case 12395: case 12396: case 12400: case 12401: case 12402: case 12430: case 12431: case 12432: case 12436: case 12437: case 12438: case 12466: case 12467: case 12468: case 12472: case 12473: case 12474: return South::Low; case 12166: case 12167: case 12168: case 12172: case 12173: case 12174: case 12202: case 12203: case 12204: case 12208: case 12209: case 12210: case 12238: case 12239: case 12240: case 12244: case 12245: case 12246: case 12274: case 12275: case 12276: case 12280: case 12281: case 12282: case 12310: case 12311: case 12312: case 12316: case 12317: case 12318: case 12346: case 12347: case 12348: case 12352: case 12353: case 12354: case 12382: case 12383: case 12384: case 12388: case 12389: case 12390: case 12418: case 12419: case 12420: case 12424: case 12425: case 12426: case 12454: case 12455: case 12456: case 12460: case 12461: case 12462: return South::None; default: return South::Tall; } } bool Up(const BlockState Block) { switch (Block.ID) { case 12172: case 12173: case 12174: case 12184: case 12185: case 12186: case 12196: case 12197: case 12198: case 12208: case 12209: case 12210: case 12220: case 12221: case 12222: case 12232: case 12233: case 12234: case 12244: case 12245: case 12246: case 12256: case 12257: case 12258: case 12268: case 12269: case 12270: case 12280: case 12281: case 12282: case 12292: case 12293: case 12294: case 12304: case 12305: case 12306: case 12316: case 12317: case 12318: case 12328: case 12329: case 12330: case 12340: case 12341: case 12342: case 12352: case 12353: case 12354: case 12364: case 12365: case 12366: case 12376: case 12377: case 12378: case 12388: case 12389: case 12390: case 12400: case 12401: case 12402: case 12412: case 12413: case 12414: case 12424: case 12425: case 12426: case 12436: case 12437: case 12438: case 12448: case 12449: case 12450: case 12460: case 12461: case 12462: case 12472: case 12473: case 12474: case 12484: case 12485: case 12486: return false; default: return true; } } enum West West(const BlockState Block) { switch (Block.ID) { case 12167: case 12173: case 12179: case 12185: case 12191: case 12197: case 12203: case 12209: case 12215: case 12221: case 12227: case 12233: case 12239: case 12245: case 12251: case 12257: case 12263: case 12269: case 12275: case 12281: case 12287: case 12293: case 12299: case 12305: case 12311: case 12317: case 12323: case 12329: case 12335: case 12341: case 12347: case 12353: case 12359: case 12365: case 12371: case 12377: case 12383: case 12389: case 12395: case 12401: case 12407: case 12413: case 12419: case 12425: case 12431: case 12437: case 12443: case 12449: case 12455: case 12461: case 12467: case 12473: case 12479: case 12485: return West::Low; case 12166: case 12172: case 12178: case 12184: case 12190: case 12196: case 12202: case 12208: case 12214: case 12220: case 12226: case 12232: case 12238: case 12244: case 12250: case 12256: case 12262: case 12268: case 12274: case 12280: case 12286: case 12292: case 12298: case 12304: case 12310: case 12316: case 12322: case 12328: case 12334: case 12340: case 12346: case 12352: case 12358: case 12364: case 12370: case 12376: case 12382: case 12388: case 12394: case 12400: case 12406: case 12412: case 12418: case 12424: case 12430: case 12436: case 12442: case 12448: case 12454: case 12460: case 12466: case 12472: case 12478: case 12484: return West::None; default: return West::Tall; } } } namespace Grass { } namespace GrassBlock { BlockState GrassBlock() { return 9; } bool Snowy(const BlockState Block) { switch (Block.ID) { case 9: return false; default: return true; } } } namespace GrassPath { } namespace Gravel { } namespace GrayBanner { BlockState GrayBanner() { return 8009; } unsigned char Rotation(const BlockState Block) { switch (Block.ID) { case 8009: return 0; case 8010: return 1; case 8019: return 10; case 8020: return 11; case 8021: return 12; case 8022: return 13; case 8023: return 14; case 8024: return 15; case 8011: return 2; case 8012: return 3; case 8013: return 4; case 8014: return 5; case 8015: return 6; case 8016: return 7; case 8017: return 8; default: return 9; } } } namespace GrayBed { BlockState GrayBed() { return 1164; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 1169: case 1170: case 1171: case 1172: return eBlockFace::BLOCK_FACE_XM; case 1173: case 1174: case 1175: case 1176: return eBlockFace::BLOCK_FACE_XP; case 1161: case 1162: case 1163: case 1164: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } bool Occupied(const BlockState Block) { switch (Block.ID) { case 1163: case 1164: case 1167: case 1168: case 1171: case 1172: case 1175: case 1176: return false; default: return true; } } enum Part Part(const BlockState Block) { switch (Block.ID) { case 1162: case 1164: case 1166: case 1168: case 1170: case 1172: case 1174: case 1176: return Part::Foot; default: return Part::Head; } } } namespace GrayCarpet { } namespace GrayConcrete { } namespace GrayConcretePowder { } namespace GrayGlazedTerracotta { BlockState GrayGlazedTerracotta() { return 9402; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 9404: return eBlockFace::BLOCK_FACE_XM; case 9405: return eBlockFace::BLOCK_FACE_XP; case 9402: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace GrayShulkerBox { BlockState GrayShulkerBox() { return 9324; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 9323: return eBlockFace::BLOCK_FACE_XM; case 9321: return eBlockFace::BLOCK_FACE_XP; case 9325: return eBlockFace::BLOCK_FACE_YM; case 9324: return eBlockFace::BLOCK_FACE_YP; case 9320: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace GrayStainedGlass { } namespace GrayStainedGlassPane { BlockState GrayStainedGlassPane() { return 7118; } bool East(const BlockState Block) { switch (Block.ID) { case 7105: case 7106: case 7109: case 7110: case 7113: case 7114: case 7117: case 7118: return false; default: return true; } } bool North(const BlockState Block) { switch (Block.ID) { case 7097: case 7098: case 7101: case 7102: case 7113: case 7114: case 7117: case 7118: return false; default: return true; } } bool South(const BlockState Block) { switch (Block.ID) { case 7093: case 7094: case 7101: case 7102: case 7109: case 7110: case 7117: case 7118: return false; default: return true; } } bool West(const BlockState Block) { switch (Block.ID) { case 7090: case 7094: case 7098: case 7102: case 7106: case 7110: case 7114: case 7118: return false; default: return true; } } } namespace GrayTerracotta { } namespace GrayWallBanner { BlockState GrayWallBanner() { return 8181; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 8183: return eBlockFace::BLOCK_FACE_XM; case 8184: return eBlockFace::BLOCK_FACE_XP; case 8181: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace GrayWool { } namespace GreenBanner { BlockState GreenBanner() { return 8105; } unsigned char Rotation(const BlockState Block) { switch (Block.ID) { case 8105: return 0; case 8106: return 1; case 8115: return 10; case 8116: return 11; case 8117: return 12; case 8118: return 13; case 8119: return 14; case 8120: return 15; case 8107: return 2; case 8108: return 3; case 8109: return 4; case 8110: return 5; case 8111: return 6; case 8112: return 7; case 8113: return 8; default: return 9; } } } namespace GreenBed { BlockState GreenBed() { return 1260; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 1265: case 1266: case 1267: case 1268: return eBlockFace::BLOCK_FACE_XM; case 1269: case 1270: case 1271: case 1272: return eBlockFace::BLOCK_FACE_XP; case 1257: case 1258: case 1259: case 1260: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } bool Occupied(const BlockState Block) { switch (Block.ID) { case 1259: case 1260: case 1263: case 1264: case 1267: case 1268: case 1271: case 1272: return false; default: return true; } } enum Part Part(const BlockState Block) { switch (Block.ID) { case 1258: case 1260: case 1262: case 1264: case 1266: case 1268: case 1270: case 1272: return Part::Foot; default: return Part::Head; } } } namespace GreenCarpet { } namespace GreenConcrete { } namespace GreenConcretePowder { } namespace GreenGlazedTerracotta { BlockState GreenGlazedTerracotta() { return 9426; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 9428: return eBlockFace::BLOCK_FACE_XM; case 9429: return eBlockFace::BLOCK_FACE_XP; case 9426: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace GreenShulkerBox { BlockState GreenShulkerBox() { return 9360; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 9359: return eBlockFace::BLOCK_FACE_XM; case 9357: return eBlockFace::BLOCK_FACE_XP; case 9361: return eBlockFace::BLOCK_FACE_YM; case 9360: return eBlockFace::BLOCK_FACE_YP; case 9356: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace GreenStainedGlass { } namespace GreenStainedGlassPane { BlockState GreenStainedGlassPane() { return 7310; } bool East(const BlockState Block) { switch (Block.ID) { case 7297: case 7298: case 7301: case 7302: case 7305: case 7306: case 7309: case 7310: return false; default: return true; } } bool North(const BlockState Block) { switch (Block.ID) { case 7289: case 7290: case 7293: case 7294: case 7305: case 7306: case 7309: case 7310: return false; default: return true; } } bool South(const BlockState Block) { switch (Block.ID) { case 7285: case 7286: case 7293: case 7294: case 7301: case 7302: case 7309: case 7310: return false; default: return true; } } bool West(const BlockState Block) { switch (Block.ID) { case 7282: case 7286: case 7290: case 7294: case 7298: case 7302: case 7306: case 7310: return false; default: return true; } } } namespace GreenTerracotta { } namespace GreenWallBanner { BlockState GreenWallBanner() { return 8205; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 8207: return eBlockFace::BLOCK_FACE_XM; case 8208: return eBlockFace::BLOCK_FACE_XP; case 8205: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace GreenWool { } namespace Grindstone { BlockState Grindstone() { return 14825; } enum Face Face(const BlockState Block) { switch (Block.ID) { case 14829: case 14830: case 14831: case 14832: return Face::Ceiling; case 14821: case 14822: case 14823: case 14824: return Face::Floor; default: return Face::Wall; } } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 14823: case 14827: case 14831: return eBlockFace::BLOCK_FACE_XM; case 14824: case 14828: case 14832: return eBlockFace::BLOCK_FACE_XP; case 14821: case 14825: case 14829: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace HayBale { BlockState HayBale() { return 7864; } enum Axis Axis(const BlockState Block) { switch (Block.ID) { case 7863: return Axis::X; case 7864: return Axis::Y; default: return Axis::Z; } } } namespace HeavyWeightedPressurePlate { BlockState HeavyWeightedPressurePlate() { return 6662; } unsigned char Power(const BlockState Block) { switch (Block.ID) { case 6662: return 0; case 6663: return 1; case 6672: return 10; case 6673: return 11; case 6674: return 12; case 6675: return 13; case 6676: return 14; case 6677: return 15; case 6664: return 2; case 6665: return 3; case 6666: return 4; case 6667: return 5; case 6668: return 6; case 6669: return 7; case 6670: return 8; default: return 9; } } } namespace HoneyBlock { } namespace HoneycombBlock { } namespace Hopper { BlockState Hopper() { return 6728; } bool Enabled(const BlockState Block) { switch (Block.ID) { case 6733: case 6734: case 6735: case 6736: case 6737: return false; default: return true; } } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 6731: case 6736: return eBlockFace::BLOCK_FACE_XM; case 6732: case 6737: return eBlockFace::BLOCK_FACE_XP; case 6728: case 6733: return eBlockFace::BLOCK_FACE_YM; case 6729: case 6734: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace HornCoral { } namespace HornCoralBlock { } namespace HornCoralFan { } namespace HornCoralWallFan { BlockState HornCoralWallFan() { return 9632; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 9637: return eBlockFace::BLOCK_FACE_XM; case 9639: return eBlockFace::BLOCK_FACE_XP; case 9633: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace Ice { } namespace InfestedChiseledStoneBricks { } namespace InfestedCobblestone { } namespace InfestedCrackedStoneBricks { } namespace InfestedMossyStoneBricks { } namespace InfestedStone { } namespace InfestedStoneBricks { } namespace IronBars { BlockState IronBars() { return 4728; } bool East(const BlockState Block) { switch (Block.ID) { case 4715: case 4716: case 4719: case 4720: case 4723: case 4724: case 4727: case 4728: return false; default: return true; } } bool North(const BlockState Block) { switch (Block.ID) { case 4707: case 4708: case 4711: case 4712: case 4723: case 4724: case 4727: case 4728: return false; default: return true; } } bool South(const BlockState Block) { switch (Block.ID) { case 4703: case 4704: case 4711: case 4712: case 4719: case 4720: case 4727: case 4728: return false; default: return true; } } bool West(const BlockState Block) { switch (Block.ID) { case 4700: case 4704: case 4708: case 4712: case 4716: case 4720: case 4724: case 4728: return false; default: return true; } } } namespace IronBlock { } namespace IronDoor { BlockState IronDoor() { return 3820; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 3841: case 3842: case 3843: case 3844: case 3845: case 3846: case 3847: case 3848: case 3849: case 3850: case 3851: case 3852: case 3853: case 3854: case 3855: case 3856: return eBlockFace::BLOCK_FACE_XM; case 3857: case 3858: case 3859: case 3860: case 3861: case 3862: case 3863: case 3864: case 3865: case 3866: case 3867: case 3868: case 3869: case 3870: case 3871: case 3872: return eBlockFace::BLOCK_FACE_XP; case 3809: case 3810: case 3811: case 3812: case 3813: case 3814: case 3815: case 3816: case 3817: case 3818: case 3819: case 3820: case 3821: case 3822: case 3823: case 3824: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } enum Half Half(const BlockState Block) { switch (Block.ID) { case 3817: case 3818: case 3819: case 3820: case 3821: case 3822: case 3823: case 3824: case 3833: case 3834: case 3835: case 3836: case 3837: case 3838: case 3839: case 3840: case 3849: case 3850: case 3851: case 3852: case 3853: case 3854: case 3855: case 3856: case 3865: case 3866: case 3867: case 3868: case 3869: case 3870: case 3871: case 3872: return Half::Lower; default: return Half::Upper; } } enum Hinge Hinge(const BlockState Block) { switch (Block.ID) { case 3809: case 3810: case 3811: case 3812: case 3817: case 3818: case 3819: case 3820: case 3825: case 3826: case 3827: case 3828: case 3833: case 3834: case 3835: case 3836: case 3841: case 3842: case 3843: case 3844: case 3849: case 3850: case 3851: case 3852: case 3857: case 3858: case 3859: case 3860: case 3865: case 3866: case 3867: case 3868: return Hinge::Left; default: return Hinge::Right; } } bool Open(const BlockState Block) { switch (Block.ID) { case 3811: case 3812: case 3815: case 3816: case 3819: case 3820: case 3823: case 3824: case 3827: case 3828: case 3831: case 3832: case 3835: case 3836: case 3839: case 3840: case 3843: case 3844: case 3847: case 3848: case 3851: case 3852: case 3855: case 3856: case 3859: case 3860: case 3863: case 3864: case 3867: case 3868: case 3871: case 3872: return false; default: return true; } } bool Powered(const BlockState Block) { switch (Block.ID) { case 3810: case 3812: case 3814: case 3816: case 3818: case 3820: case 3822: case 3824: case 3826: case 3828: case 3830: case 3832: case 3834: case 3836: case 3838: case 3840: case 3842: case 3844: case 3846: case 3848: case 3850: case 3852: case 3854: case 3856: case 3858: case 3860: case 3862: case 3864: case 3866: case 3868: case 3870: case 3872: return false; default: return true; } } } namespace IronOre { } namespace IronTrapdoor { BlockState IronTrapdoor() { return 7552; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 7570: case 7572: case 7574: case 7576: case 7578: case 7580: case 7582: case 7584: return eBlockFace::BLOCK_FACE_XM; case 7586: case 7588: case 7590: case 7592: case 7594: case 7596: case 7598: case 7600: return eBlockFace::BLOCK_FACE_XP; case 7538: case 7540: case 7542: case 7544: case 7546: case 7548: case 7550: case 7552: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } enum Half Half(const BlockState Block) { switch (Block.ID) { case 7546: case 7548: case 7550: case 7552: case 7562: case 7564: case 7566: case 7568: case 7578: case 7580: case 7582: case 7584: case 7594: case 7596: case 7598: case 7600: return Half::Bottom; default: return Half::Top; } } bool Open(const BlockState Block) { switch (Block.ID) { case 7542: case 7544: case 7550: case 7552: case 7558: case 7560: case 7566: case 7568: case 7574: case 7576: case 7582: case 7584: case 7590: case 7592: case 7598: case 7600: return false; default: return true; } } bool Powered(const BlockState Block) { switch (Block.ID) { case 7540: case 7544: case 7548: case 7552: case 7556: case 7560: case 7564: case 7568: case 7572: case 7576: case 7580: case 7584: case 7588: case 7592: case 7596: case 7600: return false; default: return true; } } } namespace JackOLantern { BlockState JackOLantern() { return 4020; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 4022: return eBlockFace::BLOCK_FACE_XM; case 4023: return eBlockFace::BLOCK_FACE_XP; case 4020: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace Jigsaw { BlockState Jigsaw() { return 15749; } enum Orientation Orientation(const BlockState Block) { switch (Block.ID) { case 15739: return Orientation::DownEast; case 15740: return Orientation::DownNorth; case 15741: return Orientation::DownSouth; case 15742: return Orientation::DownWest; case 15748: return Orientation::EastUp; case 15749: return Orientation::NorthUp; case 15750: return Orientation::SouthUp; case 15743: return Orientation::UpEast; case 15744: return Orientation::UpNorth; case 15745: return Orientation::UpSouth; case 15746: return Orientation::UpWest; default: return Orientation::WestUp; } } } namespace Jukebox { BlockState Jukebox() { return 3965; } bool HasRecord(const BlockState Block) { switch (Block.ID) { case 3965: return false; default: return true; } } } namespace JungleButton { BlockState JungleButton() { return 6427; } enum Face Face(const BlockState Block) { switch (Block.ID) { case 6434: case 6435: case 6436: case 6437: case 6438: case 6439: case 6440: case 6441: return Face::Ceiling; case 6418: case 6419: case 6420: case 6421: case 6422: case 6423: case 6424: case 6425: return Face::Floor; default: return Face::Wall; } } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 6422: case 6423: case 6430: case 6431: case 6438: case 6439: return eBlockFace::BLOCK_FACE_XM; case 6424: case 6425: case 6432: case 6433: case 6440: case 6441: return eBlockFace::BLOCK_FACE_XP; case 6418: case 6419: case 6426: case 6427: case 6434: case 6435: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } bool Powered(const BlockState Block) { switch (Block.ID) { case 6419: case 6421: case 6423: case 6425: case 6427: case 6429: case 6431: case 6433: case 6435: case 6437: case 6439: case 6441: return false; default: return true; } } } namespace JungleDoor { BlockState JungleDoor() { return 8877; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 8898: case 8899: case 8900: case 8901: case 8902: case 8903: case 8904: case 8905: case 8906: case 8907: case 8908: case 8909: case 8910: case 8911: case 8912: case 8913: return eBlockFace::BLOCK_FACE_XM; case 8914: case 8915: case 8916: case 8917: case 8918: case 8919: case 8920: case 8921: case 8922: case 8923: case 8924: case 8925: case 8926: case 8927: case 8928: case 8929: return eBlockFace::BLOCK_FACE_XP; case 8866: case 8867: case 8868: case 8869: case 8870: case 8871: case 8872: case 8873: case 8874: case 8875: case 8876: case 8877: case 8878: case 8879: case 8880: case 8881: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } enum Half Half(const BlockState Block) { switch (Block.ID) { case 8874: case 8875: case 8876: case 8877: case 8878: case 8879: case 8880: case 8881: case 8890: case 8891: case 8892: case 8893: case 8894: case 8895: case 8896: case 8897: case 8906: case 8907: case 8908: case 8909: case 8910: case 8911: case 8912: case 8913: case 8922: case 8923: case 8924: case 8925: case 8926: case 8927: case 8928: case 8929: return Half::Lower; default: return Half::Upper; } } enum Hinge Hinge(const BlockState Block) { switch (Block.ID) { case 8866: case 8867: case 8868: case 8869: case 8874: case 8875: case 8876: case 8877: case 8882: case 8883: case 8884: case 8885: case 8890: case 8891: case 8892: case 8893: case 8898: case 8899: case 8900: case 8901: case 8906: case 8907: case 8908: case 8909: case 8914: case 8915: case 8916: case 8917: case 8922: case 8923: case 8924: case 8925: return Hinge::Left; default: return Hinge::Right; } } bool Open(const BlockState Block) { switch (Block.ID) { case 8868: case 8869: case 8872: case 8873: case 8876: case 8877: case 8880: case 8881: case 8884: case 8885: case 8888: case 8889: case 8892: case 8893: case 8896: case 8897: case 8900: case 8901: case 8904: case 8905: case 8908: case 8909: case 8912: case 8913: case 8916: case 8917: case 8920: case 8921: case 8924: case 8925: case 8928: case 8929: return false; default: return true; } } bool Powered(const BlockState Block) { switch (Block.ID) { case 8867: case 8869: case 8871: case 8873: case 8875: case 8877: case 8879: case 8881: case 8883: case 8885: case 8887: case 8889: case 8891: case 8893: case 8895: case 8897: case 8899: case 8901: case 8903: case 8905: case 8907: case 8909: case 8911: case 8913: case 8915: case 8917: case 8919: case 8921: case 8923: case 8925: case 8927: case 8929: return false; default: return true; } } } namespace JungleFence { BlockState JungleFence() { return 8673; } bool East(const BlockState Block) { switch (Block.ID) { case 8660: case 8661: case 8664: case 8665: case 8668: case 8669: case 8672: case 8673: return false; default: return true; } } bool North(const BlockState Block) { switch (Block.ID) { case 8652: case 8653: case 8656: case 8657: case 8668: case 8669: case 8672: case 8673: return false; default: return true; } } bool South(const BlockState Block) { switch (Block.ID) { case 8648: case 8649: case 8656: case 8657: case 8664: case 8665: case 8672: case 8673: return false; default: return true; } } bool West(const BlockState Block) { switch (Block.ID) { case 8645: case 8649: case 8653: case 8657: case 8661: case 8665: case 8669: case 8673: return false; default: return true; } } } namespace JungleFenceGate { BlockState JungleFenceGate() { return 8489; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 8498: case 8499: case 8500: case 8501: case 8502: case 8503: case 8504: case 8505: return eBlockFace::BLOCK_FACE_XM; case 8506: case 8507: case 8508: case 8509: case 8510: case 8511: case 8512: case 8513: return eBlockFace::BLOCK_FACE_XP; case 8482: case 8483: case 8484: case 8485: case 8486: case 8487: case 8488: case 8489: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } bool InWall(const BlockState Block) { switch (Block.ID) { case 8486: case 8487: case 8488: case 8489: case 8494: case 8495: case 8496: case 8497: case 8502: case 8503: case 8504: case 8505: case 8510: case 8511: case 8512: case 8513: return false; default: return true; } } bool Open(const BlockState Block) { switch (Block.ID) { case 8484: case 8485: case 8488: case 8489: case 8492: case 8493: case 8496: case 8497: case 8500: case 8501: case 8504: case 8505: case 8508: case 8509: case 8512: case 8513: return false; default: return true; } } bool Powered(const BlockState Block) { switch (Block.ID) { case 8483: case 8485: case 8487: case 8489: case 8491: case 8493: case 8495: case 8497: case 8499: case 8501: case 8503: case 8505: case 8507: case 8509: case 8511: case 8513: return false; default: return true; } } } namespace JungleLeaves { BlockState JungleLeaves() { return 200; } unsigned char Distance(const BlockState Block) { switch (Block.ID) { case 187: case 188: return 1; case 189: case 190: return 2; case 191: case 192: return 3; case 193: case 194: return 4; case 195: case 196: return 5; case 197: case 198: return 6; default: return 7; } } bool Persistent(const BlockState Block) { switch (Block.ID) { case 188: case 190: case 192: case 194: case 196: case 198: case 200: return false; default: return true; } } } namespace JungleLog { BlockState JungleLog() { return 83; } enum Axis Axis(const BlockState Block) { switch (Block.ID) { case 82: return Axis::X; case 83: return Axis::Y; default: return Axis::Z; } } } namespace JunglePlanks { } namespace JunglePressurePlate { BlockState JunglePressurePlate() { return 3880; } bool Powered(const BlockState Block) { switch (Block.ID) { case 3880: return false; default: return true; } } } namespace JungleSapling { BlockState JungleSapling() { return 27; } unsigned char Stage(const BlockState Block) { switch (Block.ID) { case 27: return 0; default: return 1; } } } namespace JungleSign { BlockState JungleSign() { return 3510; } unsigned char Rotation(const BlockState Block) { switch (Block.ID) { case 3510: return 0; case 3512: return 1; case 3530: return 10; case 3532: return 11; case 3534: return 12; case 3536: return 13; case 3538: return 14; case 3540: return 15; case 3514: return 2; case 3516: return 3; case 3518: return 4; case 3520: return 5; case 3522: return 6; case 3524: return 7; case 3526: return 8; default: return 9; } } } namespace JungleSlab { BlockState JungleSlab() { return 8321; } enum Type Type(const BlockState Block) { switch (Block.ID) { case 8321: return Type::Bottom; case 8323: return Type::Double; default: return Type::Top; } } } namespace JungleStairs { BlockState JungleStairs() { return 5575; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 5605: case 5607: case 5609: case 5611: case 5613: case 5615: case 5617: case 5619: case 5621: case 5623: return eBlockFace::BLOCK_FACE_XM; case 5625: case 5627: case 5629: case 5631: case 5633: case 5635: case 5637: case 5639: case 5641: case 5643: return eBlockFace::BLOCK_FACE_XP; case 5565: case 5567: case 5569: case 5571: case 5573: case 5575: case 5577: case 5579: case 5581: case 5583: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } enum Half Half(const BlockState Block) { switch (Block.ID) { case 5575: case 5577: case 5579: case 5581: case 5583: case 5595: case 5597: case 5599: case 5601: case 5603: case 5615: case 5617: case 5619: case 5621: case 5623: case 5635: case 5637: case 5639: case 5641: case 5643: return Half::Bottom; default: return Half::Top; } } enum Shape Shape(const BlockState Block) { switch (Block.ID) { case 5567: case 5577: case 5587: case 5597: case 5607: case 5617: case 5627: case 5637: return Shape::InnerLeft; case 5569: case 5579: case 5589: case 5599: case 5609: case 5619: case 5629: case 5639: return Shape::InnerRight; case 5571: case 5581: case 5591: case 5601: case 5611: case 5621: case 5631: case 5641: return Shape::OuterLeft; case 5573: case 5583: case 5593: case 5603: case 5613: case 5623: case 5633: case 5643: return Shape::OuterRight; default: return Shape::Straight; } } } namespace JungleTrapdoor { BlockState JungleTrapdoor() { return 4318; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 4336: case 4338: case 4340: case 4342: case 4344: case 4346: case 4348: case 4350: return eBlockFace::BLOCK_FACE_XM; case 4352: case 4354: case 4356: case 4358: case 4360: case 4362: case 4364: case 4366: return eBlockFace::BLOCK_FACE_XP; case 4304: case 4306: case 4308: case 4310: case 4312: case 4314: case 4316: case 4318: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } enum Half Half(const BlockState Block) { switch (Block.ID) { case 4312: case 4314: case 4316: case 4318: case 4328: case 4330: case 4332: case 4334: case 4344: case 4346: case 4348: case 4350: case 4360: case 4362: case 4364: case 4366: return Half::Bottom; default: return Half::Top; } } bool Open(const BlockState Block) { switch (Block.ID) { case 4308: case 4310: case 4316: case 4318: case 4324: case 4326: case 4332: case 4334: case 4340: case 4342: case 4348: case 4350: case 4356: case 4358: case 4364: case 4366: return false; default: return true; } } bool Powered(const BlockState Block) { switch (Block.ID) { case 4306: case 4310: case 4314: case 4318: case 4322: case 4326: case 4330: case 4334: case 4338: case 4342: case 4346: case 4350: case 4354: case 4358: case 4362: case 4366: return false; default: return true; } } } namespace JungleWallSign { BlockState JungleWallSign() { return 3768; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 3772: return eBlockFace::BLOCK_FACE_XM; case 3774: return eBlockFace::BLOCK_FACE_XP; case 3768: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace JungleWood { BlockState JungleWood() { return 119; } enum Axis Axis(const BlockState Block) { switch (Block.ID) { case 118: return Axis::X; case 119: return Axis::Y; default: return Axis::Z; } } } namespace Kelp { BlockState Kelp() { return 9470; } unsigned char Age(const BlockState Block) { switch (Block.ID) { case 9470: return 0; case 9471: return 1; case 9480: return 10; case 9481: return 11; case 9482: return 12; case 9483: return 13; case 9484: return 14; case 9485: return 15; case 9486: return 16; case 9487: return 17; case 9488: return 18; case 9489: return 19; case 9472: return 2; case 9490: return 20; case 9491: return 21; case 9492: return 22; case 9493: return 23; case 9494: return 24; case 9495: return 25; case 9473: return 3; case 9474: return 4; case 9475: return 5; case 9476: return 6; case 9477: return 7; case 9478: return 8; default: return 9; } } } namespace KelpPlant { } namespace Ladder { BlockState Ladder() { return 3638; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 3642: return eBlockFace::BLOCK_FACE_XM; case 3644: return eBlockFace::BLOCK_FACE_XP; case 3638: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace Lantern { BlockState Lantern() { return 14887; } bool Hanging(const BlockState Block) { switch (Block.ID) { case 14887: return false; default: return true; } } } namespace LapisBlock { } namespace LapisOre { } namespace LargeFern { BlockState LargeFern() { return 7896; } enum Half Half(const BlockState Block) { switch (Block.ID) { case 7896: return Half::Lower; default: return Half::Upper; } } } namespace Lava { BlockState Lava() { return 50; } unsigned char Level(const BlockState Block) { switch (Block.ID) { case 50: return 0; case 51: return 1; case 60: return 10; case 61: return 11; case 62: return 12; case 63: return 13; case 64: return 14; case 65: return 15; case 52: return 2; case 53: return 3; case 54: return 4; case 55: return 5; case 56: return 6; case 57: return 7; case 58: return 8; default: return 9; } } } namespace Lectern { BlockState Lectern() { return 14836; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 14841: case 14842: case 14843: case 14844: return eBlockFace::BLOCK_FACE_XM; case 14845: case 14846: case 14847: case 14848: return eBlockFace::BLOCK_FACE_XP; case 14833: case 14834: case 14835: case 14836: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } bool HasBook(const BlockState Block) { switch (Block.ID) { case 14835: case 14836: case 14839: case 14840: case 14843: case 14844: case 14847: case 14848: return false; default: return true; } } bool Powered(const BlockState Block) { switch (Block.ID) { case 14834: case 14836: case 14838: case 14840: case 14842: case 14844: case 14846: case 14848: return false; default: return true; } } } namespace Lever { BlockState Lever() { return 3792; } enum Face Face(const BlockState Block) { switch (Block.ID) { case 3799: case 3800: case 3801: case 3802: case 3803: case 3804: case 3805: case 3806: return Face::Ceiling; case 3783: case 3784: case 3785: case 3786: case 3787: case 3788: case 3789: case 3790: return Face::Floor; default: return Face::Wall; } } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 3787: case 3788: case 3795: case 3796: case 3803: case 3804: return eBlockFace::BLOCK_FACE_XM; case 3789: case 3790: case 3797: case 3798: case 3805: case 3806: return eBlockFace::BLOCK_FACE_XP; case 3783: case 3784: case 3791: case 3792: case 3799: case 3800: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } bool Powered(const BlockState Block) { switch (Block.ID) { case 3784: case 3786: case 3788: case 3790: case 3792: case 3794: case 3796: case 3798: case 3800: case 3802: case 3804: case 3806: return false; default: return true; } } } namespace LightBlueBanner { BlockState LightBlueBanner() { return 7945; } unsigned char Rotation(const BlockState Block) { switch (Block.ID) { case 7945: return 0; case 7946: return 1; case 7955: return 10; case 7956: return 11; case 7957: return 12; case 7958: return 13; case 7959: return 14; case 7960: return 15; case 7947: return 2; case 7948: return 3; case 7949: return 4; case 7950: return 5; case 7951: return 6; case 7952: return 7; case 7953: return 8; default: return 9; } } } namespace LightBlueBed { BlockState LightBlueBed() { return 1100; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 1105: case 1106: case 1107: case 1108: return eBlockFace::BLOCK_FACE_XM; case 1109: case 1110: case 1111: case 1112: return eBlockFace::BLOCK_FACE_XP; case 1097: case 1098: case 1099: case 1100: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } bool Occupied(const BlockState Block) { switch (Block.ID) { case 1099: case 1100: case 1103: case 1104: case 1107: case 1108: case 1111: case 1112: return false; default: return true; } } enum Part Part(const BlockState Block) { switch (Block.ID) { case 1098: case 1100: case 1102: case 1104: case 1106: case 1108: case 1110: case 1112: return Part::Foot; default: return Part::Head; } } } namespace LightBlueCarpet { } namespace LightBlueConcrete { } namespace LightBlueConcretePowder { } namespace LightBlueGlazedTerracotta { BlockState LightBlueGlazedTerracotta() { return 9386; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 9388: return eBlockFace::BLOCK_FACE_XM; case 9389: return eBlockFace::BLOCK_FACE_XP; case 9386: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace LightBlueShulkerBox { BlockState LightBlueShulkerBox() { return 9300; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 9299: return eBlockFace::BLOCK_FACE_XM; case 9297: return eBlockFace::BLOCK_FACE_XP; case 9301: return eBlockFace::BLOCK_FACE_YM; case 9300: return eBlockFace::BLOCK_FACE_YP; case 9296: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace LightBlueStainedGlass { } namespace LightBlueStainedGlassPane { BlockState LightBlueStainedGlassPane() { return 6990; } bool East(const BlockState Block) { switch (Block.ID) { case 6977: case 6978: case 6981: case 6982: case 6985: case 6986: case 6989: case 6990: return false; default: return true; } } bool North(const BlockState Block) { switch (Block.ID) { case 6969: case 6970: case 6973: case 6974: case 6985: case 6986: case 6989: case 6990: return false; default: return true; } } bool South(const BlockState Block) { switch (Block.ID) { case 6965: case 6966: case 6973: case 6974: case 6981: case 6982: case 6989: case 6990: return false; default: return true; } } bool West(const BlockState Block) { switch (Block.ID) { case 6962: case 6966: case 6970: case 6974: case 6978: case 6982: case 6986: case 6990: return false; default: return true; } } } namespace LightBlueTerracotta { } namespace LightBlueWallBanner { BlockState LightBlueWallBanner() { return 8165; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 8167: return eBlockFace::BLOCK_FACE_XM; case 8168: return eBlockFace::BLOCK_FACE_XP; case 8165: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace LightBlueWool { } namespace LightGrayBanner { BlockState LightGrayBanner() { return 8025; } unsigned char Rotation(const BlockState Block) { switch (Block.ID) { case 8025: return 0; case 8026: return 1; case 8035: return 10; case 8036: return 11; case 8037: return 12; case 8038: return 13; case 8039: return 14; case 8040: return 15; case 8027: return 2; case 8028: return 3; case 8029: return 4; case 8030: return 5; case 8031: return 6; case 8032: return 7; case 8033: return 8; default: return 9; } } } namespace LightGrayBed { BlockState LightGrayBed() { return 1180; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 1185: case 1186: case 1187: case 1188: return eBlockFace::BLOCK_FACE_XM; case 1189: case 1190: case 1191: case 1192: return eBlockFace::BLOCK_FACE_XP; case 1177: case 1178: case 1179: case 1180: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } bool Occupied(const BlockState Block) { switch (Block.ID) { case 1179: case 1180: case 1183: case 1184: case 1187: case 1188: case 1191: case 1192: return false; default: return true; } } enum Part Part(const BlockState Block) { switch (Block.ID) { case 1178: case 1180: case 1182: case 1184: case 1186: case 1188: case 1190: case 1192: return Part::Foot; default: return Part::Head; } } } namespace LightGrayCarpet { } namespace LightGrayConcrete { } namespace LightGrayConcretePowder { } namespace LightGrayGlazedTerracotta { BlockState LightGrayGlazedTerracotta() { return 9406; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 9408: return eBlockFace::BLOCK_FACE_XM; case 9409: return eBlockFace::BLOCK_FACE_XP; case 9406: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace LightGrayShulkerBox { BlockState LightGrayShulkerBox() { return 9330; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 9329: return eBlockFace::BLOCK_FACE_XM; case 9327: return eBlockFace::BLOCK_FACE_XP; case 9331: return eBlockFace::BLOCK_FACE_YM; case 9330: return eBlockFace::BLOCK_FACE_YP; case 9326: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace LightGrayStainedGlass { } namespace LightGrayStainedGlassPane { BlockState LightGrayStainedGlassPane() { return 7150; } bool East(const BlockState Block) { switch (Block.ID) { case 7137: case 7138: case 7141: case 7142: case 7145: case 7146: case 7149: case 7150: return false; default: return true; } } bool North(const BlockState Block) { switch (Block.ID) { case 7129: case 7130: case 7133: case 7134: case 7145: case 7146: case 7149: case 7150: return false; default: return true; } } bool South(const BlockState Block) { switch (Block.ID) { case 7125: case 7126: case 7133: case 7134: case 7141: case 7142: case 7149: case 7150: return false; default: return true; } } bool West(const BlockState Block) { switch (Block.ID) { case 7122: case 7126: case 7130: case 7134: case 7138: case 7142: case 7146: case 7150: return false; default: return true; } } } namespace LightGrayTerracotta { } namespace LightGrayWallBanner { BlockState LightGrayWallBanner() { return 8185; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 8187: return eBlockFace::BLOCK_FACE_XM; case 8188: return eBlockFace::BLOCK_FACE_XP; case 8185: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace LightGrayWool { } namespace LightWeightedPressurePlate { BlockState LightWeightedPressurePlate() { return 6646; } unsigned char Power(const BlockState Block) { switch (Block.ID) { case 6646: return 0; case 6647: return 1; case 6656: return 10; case 6657: return 11; case 6658: return 12; case 6659: return 13; case 6660: return 14; case 6661: return 15; case 6648: return 2; case 6649: return 3; case 6650: return 4; case 6651: return 5; case 6652: return 6; case 6653: return 7; case 6654: return 8; default: return 9; } } } namespace Lilac { BlockState Lilac() { return 7888; } enum Half Half(const BlockState Block) { switch (Block.ID) { case 7888: return Half::Lower; default: return Half::Upper; } } } namespace LilyOfTheValley { } namespace LilyPad { } namespace LimeBanner { BlockState LimeBanner() { return 7977; } unsigned char Rotation(const BlockState Block) { switch (Block.ID) { case 7977: return 0; case 7978: return 1; case 7987: return 10; case 7988: return 11; case 7989: return 12; case 7990: return 13; case 7991: return 14; case 7992: return 15; case 7979: return 2; case 7980: return 3; case 7981: return 4; case 7982: return 5; case 7983: return 6; case 7984: return 7; case 7985: return 8; default: return 9; } } } namespace LimeBed { BlockState LimeBed() { return 1132; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 1137: case 1138: case 1139: case 1140: return eBlockFace::BLOCK_FACE_XM; case 1141: case 1142: case 1143: case 1144: return eBlockFace::BLOCK_FACE_XP; case 1129: case 1130: case 1131: case 1132: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } bool Occupied(const BlockState Block) { switch (Block.ID) { case 1131: case 1132: case 1135: case 1136: case 1139: case 1140: case 1143: case 1144: return false; default: return true; } } enum Part Part(const BlockState Block) { switch (Block.ID) { case 1130: case 1132: case 1134: case 1136: case 1138: case 1140: case 1142: case 1144: return Part::Foot; default: return Part::Head; } } } namespace LimeCarpet { } namespace LimeConcrete { } namespace LimeConcretePowder { } namespace LimeGlazedTerracotta { BlockState LimeGlazedTerracotta() { return 9394; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 9396: return eBlockFace::BLOCK_FACE_XM; case 9397: return eBlockFace::BLOCK_FACE_XP; case 9394: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace LimeShulkerBox { BlockState LimeShulkerBox() { return 9312; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 9311: return eBlockFace::BLOCK_FACE_XM; case 9309: return eBlockFace::BLOCK_FACE_XP; case 9313: return eBlockFace::BLOCK_FACE_YM; case 9312: return eBlockFace::BLOCK_FACE_YP; case 9308: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace LimeStainedGlass { } namespace LimeStainedGlassPane { BlockState LimeStainedGlassPane() { return 7054; } bool East(const BlockState Block) { switch (Block.ID) { case 7041: case 7042: case 7045: case 7046: case 7049: case 7050: case 7053: case 7054: return false; default: return true; } } bool North(const BlockState Block) { switch (Block.ID) { case 7033: case 7034: case 7037: case 7038: case 7049: case 7050: case 7053: case 7054: return false; default: return true; } } bool South(const BlockState Block) { switch (Block.ID) { case 7029: case 7030: case 7037: case 7038: case 7045: case 7046: case 7053: case 7054: return false; default: return true; } } bool West(const BlockState Block) { switch (Block.ID) { case 7026: case 7030: case 7034: case 7038: case 7042: case 7046: case 7050: case 7054: return false; default: return true; } } } namespace LimeTerracotta { } namespace LimeWallBanner { BlockState LimeWallBanner() { return 8173; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 8175: return eBlockFace::BLOCK_FACE_XM; case 8176: return eBlockFace::BLOCK_FACE_XP; case 8173: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace LimeWool { } namespace Lodestone { } namespace Loom { BlockState Loom() { return 14787; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 14789: return eBlockFace::BLOCK_FACE_XM; case 14790: return eBlockFace::BLOCK_FACE_XP; case 14787: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace MagentaBanner { BlockState MagentaBanner() { return 7929; } unsigned char Rotation(const BlockState Block) { switch (Block.ID) { case 7929: return 0; case 7930: return 1; case 7939: return 10; case 7940: return 11; case 7941: return 12; case 7942: return 13; case 7943: return 14; case 7944: return 15; case 7931: return 2; case 7932: return 3; case 7933: return 4; case 7934: return 5; case 7935: return 6; case 7936: return 7; case 7937: return 8; default: return 9; } } } namespace MagentaBed { BlockState MagentaBed() { return 1084; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 1089: case 1090: case 1091: case 1092: return eBlockFace::BLOCK_FACE_XM; case 1093: case 1094: case 1095: case 1096: return eBlockFace::BLOCK_FACE_XP; case 1081: case 1082: case 1083: case 1084: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } bool Occupied(const BlockState Block) { switch (Block.ID) { case 1083: case 1084: case 1087: case 1088: case 1091: case 1092: case 1095: case 1096: return false; default: return true; } } enum Part Part(const BlockState Block) { switch (Block.ID) { case 1082: case 1084: case 1086: case 1088: case 1090: case 1092: case 1094: case 1096: return Part::Foot; default: return Part::Head; } } } namespace MagentaCarpet { } namespace MagentaConcrete { } namespace MagentaConcretePowder { } namespace MagentaGlazedTerracotta { BlockState MagentaGlazedTerracotta() { return 9382; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 9384: return eBlockFace::BLOCK_FACE_XM; case 9385: return eBlockFace::BLOCK_FACE_XP; case 9382: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace MagentaShulkerBox { BlockState MagentaShulkerBox() { return 9294; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 9293: return eBlockFace::BLOCK_FACE_XM; case 9291: return eBlockFace::BLOCK_FACE_XP; case 9295: return eBlockFace::BLOCK_FACE_YM; case 9294: return eBlockFace::BLOCK_FACE_YP; case 9290: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace MagentaStainedGlass { } namespace MagentaStainedGlassPane { BlockState MagentaStainedGlassPane() { return 6958; } bool East(const BlockState Block) { switch (Block.ID) { case 6945: case 6946: case 6949: case 6950: case 6953: case 6954: case 6957: case 6958: return false; default: return true; } } bool North(const BlockState Block) { switch (Block.ID) { case 6937: case 6938: case 6941: case 6942: case 6953: case 6954: case 6957: case 6958: return false; default: return true; } } bool South(const BlockState Block) { switch (Block.ID) { case 6933: case 6934: case 6941: case 6942: case 6949: case 6950: case 6957: case 6958: return false; default: return true; } } bool West(const BlockState Block) { switch (Block.ID) { case 6930: case 6934: case 6938: case 6942: case 6946: case 6950: case 6954: case 6958: return false; default: return true; } } } namespace MagentaTerracotta { } namespace MagentaWallBanner { BlockState MagentaWallBanner() { return 8161; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 8163: return eBlockFace::BLOCK_FACE_XM; case 8164: return eBlockFace::BLOCK_FACE_XP; case 8161: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace MagentaWool { } namespace MagmaBlock { } namespace Melon { } namespace MelonStem { BlockState MelonStem() { return 4780; } unsigned char Age(const BlockState Block) { switch (Block.ID) { case 4780: return 0; case 4781: return 1; case 4782: return 2; case 4783: return 3; case 4784: return 4; case 4785: return 5; case 4786: return 6; default: return 7; } } } namespace MossyCobblestone { } namespace MossyCobblestoneSlab { BlockState MossyCobblestoneSlab() { return 10816; } enum Type Type(const BlockState Block) { switch (Block.ID) { case 10816: return Type::Bottom; case 10818: return Type::Double; default: return Type::Top; } } } namespace MossyCobblestoneStairs { BlockState MossyCobblestoneStairs() { return 10000; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 10030: case 10032: case 10034: case 10036: case 10038: case 10040: case 10042: case 10044: case 10046: case 10048: return eBlockFace::BLOCK_FACE_XM; case 10050: case 10052: case 10054: case 10056: case 10058: case 10060: case 10062: case 10064: case 10066: case 10068: return eBlockFace::BLOCK_FACE_XP; case 9990: case 9992: case 9994: case 9996: case 9998: case 10000: case 10002: case 10004: case 10006: case 10008: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } enum Half Half(const BlockState Block) { switch (Block.ID) { case 10000: case 10002: case 10004: case 10006: case 10008: case 10020: case 10022: case 10024: case 10026: case 10028: case 10040: case 10042: case 10044: case 10046: case 10048: case 10060: case 10062: case 10064: case 10066: case 10068: return Half::Bottom; default: return Half::Top; } } enum Shape Shape(const BlockState Block) { switch (Block.ID) { case 9992: case 10002: case 10012: case 10022: case 10032: case 10042: case 10052: case 10062: return Shape::InnerLeft; case 9994: case 10004: case 10014: case 10024: case 10034: case 10044: case 10054: case 10064: return Shape::InnerRight; case 9996: case 10006: case 10016: case 10026: case 10036: case 10046: case 10056: case 10066: return Shape::OuterLeft; case 9998: case 10008: case 10018: case 10028: case 10038: case 10048: case 10058: case 10068: return Shape::OuterRight; default: return Shape::Straight; } } } namespace MossyCobblestoneWall { BlockState MossyCobblestoneWall() { return 5984; } enum East East(const BlockState Block) { switch (Block.ID) { case 6092: case 6093: case 6094: case 6098: case 6099: case 6100: case 6104: case 6105: case 6106: case 6110: case 6111: case 6112: case 6116: case 6117: case 6118: case 6122: case 6123: case 6124: case 6128: case 6129: case 6130: case 6134: case 6135: case 6136: case 6140: case 6141: case 6142: case 6146: case 6147: case 6148: case 6152: case 6153: case 6154: case 6158: case 6159: case 6160: case 6164: case 6165: case 6166: case 6170: case 6171: case 6172: case 6176: case 6177: case 6178: case 6182: case 6183: case 6184: case 6188: case 6189: case 6190: case 6194: case 6195: case 6196: return East::Low; case 5984: case 5985: case 5986: case 5990: case 5991: case 5992: case 5996: case 5997: case 5998: case 6002: case 6003: case 6004: case 6008: case 6009: case 6010: case 6014: case 6015: case 6016: case 6020: case 6021: case 6022: case 6026: case 6027: case 6028: case 6032: case 6033: case 6034: case 6038: case 6039: case 6040: case 6044: case 6045: case 6046: case 6050: case 6051: case 6052: case 6056: case 6057: case 6058: case 6062: case 6063: case 6064: case 6068: case 6069: case 6070: case 6074: case 6075: case 6076: case 6080: case 6081: case 6082: case 6086: case 6087: case 6088: return East::None; default: return East::Tall; } } enum North North(const BlockState Block) { switch (Block.ID) { case 6020: case 6021: case 6022: case 6026: case 6027: case 6028: case 6032: case 6033: case 6034: case 6038: case 6039: case 6040: case 6044: case 6045: case 6046: case 6050: case 6051: case 6052: case 6128: case 6129: case 6130: case 6134: case 6135: case 6136: case 6140: case 6141: case 6142: case 6146: case 6147: case 6148: case 6152: case 6153: case 6154: case 6158: case 6159: case 6160: case 6236: case 6237: case 6238: case 6242: case 6243: case 6244: case 6248: case 6249: case 6250: case 6254: case 6255: case 6256: case 6260: case 6261: case 6262: case 6266: case 6267: case 6268: return North::Low; case 5984: case 5985: case 5986: case 5990: case 5991: case 5992: case 5996: case 5997: case 5998: case 6002: case 6003: case 6004: case 6008: case 6009: case 6010: case 6014: case 6015: case 6016: case 6092: case 6093: case 6094: case 6098: case 6099: case 6100: case 6104: case 6105: case 6106: case 6110: case 6111: case 6112: case 6116: case 6117: case 6118: case 6122: case 6123: case 6124: case 6200: case 6201: case 6202: case 6206: case 6207: case 6208: case 6212: case 6213: case 6214: case 6218: case 6219: case 6220: case 6224: case 6225: case 6226: case 6230: case 6231: case 6232: return North::None; default: return North::Tall; } } enum South South(const BlockState Block) { switch (Block.ID) { case 5996: case 5997: case 5998: case 6002: case 6003: case 6004: case 6032: case 6033: case 6034: case 6038: case 6039: case 6040: case 6068: case 6069: case 6070: case 6074: case 6075: case 6076: case 6104: case 6105: case 6106: case 6110: case 6111: case 6112: case 6140: case 6141: case 6142: case 6146: case 6147: case 6148: case 6176: case 6177: case 6178: case 6182: case 6183: case 6184: case 6212: case 6213: case 6214: case 6218: case 6219: case 6220: case 6248: case 6249: case 6250: case 6254: case 6255: case 6256: case 6284: case 6285: case 6286: case 6290: case 6291: case 6292: return South::Low; case 5984: case 5985: case 5986: case 5990: case 5991: case 5992: case 6020: case 6021: case 6022: case 6026: case 6027: case 6028: case 6056: case 6057: case 6058: case 6062: case 6063: case 6064: case 6092: case 6093: case 6094: case 6098: case 6099: case 6100: case 6128: case 6129: case 6130: case 6134: case 6135: case 6136: case 6164: case 6165: case 6166: case 6170: case 6171: case 6172: case 6200: case 6201: case 6202: case 6206: case 6207: case 6208: case 6236: case 6237: case 6238: case 6242: case 6243: case 6244: case 6272: case 6273: case 6274: case 6278: case 6279: case 6280: return South::None; default: return South::Tall; } } bool Up(const BlockState Block) { switch (Block.ID) { case 5990: case 5991: case 5992: case 6002: case 6003: case 6004: case 6014: case 6015: case 6016: case 6026: case 6027: case 6028: case 6038: case 6039: case 6040: case 6050: case 6051: case 6052: case 6062: case 6063: case 6064: case 6074: case 6075: case 6076: case 6086: case 6087: case 6088: case 6098: case 6099: case 6100: case 6110: case 6111: case 6112: case 6122: case 6123: case 6124: case 6134: case 6135: case 6136: case 6146: case 6147: case 6148: case 6158: case 6159: case 6160: case 6170: case 6171: case 6172: case 6182: case 6183: case 6184: case 6194: case 6195: case 6196: case 6206: case 6207: case 6208: case 6218: case 6219: case 6220: case 6230: case 6231: case 6232: case 6242: case 6243: case 6244: case 6254: case 6255: case 6256: case 6266: case 6267: case 6268: case 6278: case 6279: case 6280: case 6290: case 6291: case 6292: case 6302: case 6303: case 6304: return false; default: return true; } } enum West West(const BlockState Block) { switch (Block.ID) { case 5985: case 5991: case 5997: case 6003: case 6009: case 6015: case 6021: case 6027: case 6033: case 6039: case 6045: case 6051: case 6057: case 6063: case 6069: case 6075: case 6081: case 6087: case 6093: case 6099: case 6105: case 6111: case 6117: case 6123: case 6129: case 6135: case 6141: case 6147: case 6153: case 6159: case 6165: case 6171: case 6177: case 6183: case 6189: case 6195: case 6201: case 6207: case 6213: case 6219: case 6225: case 6231: case 6237: case 6243: case 6249: case 6255: case 6261: case 6267: case 6273: case 6279: case 6285: case 6291: case 6297: case 6303: return West::Low; case 5984: case 5990: case 5996: case 6002: case 6008: case 6014: case 6020: case 6026: case 6032: case 6038: case 6044: case 6050: case 6056: case 6062: case 6068: case 6074: case 6080: case 6086: case 6092: case 6098: case 6104: case 6110: case 6116: case 6122: case 6128: case 6134: case 6140: case 6146: case 6152: case 6158: case 6164: case 6170: case 6176: case 6182: case 6188: case 6194: case 6200: case 6206: case 6212: case 6218: case 6224: case 6230: case 6236: case 6242: case 6248: case 6254: case 6260: case 6266: case 6272: case 6278: case 6284: case 6290: case 6296: case 6302: return West::None; default: return West::Tall; } } } namespace MossyStoneBrickSlab { BlockState MossyStoneBrickSlab() { return 10804; } enum Type Type(const BlockState Block) { switch (Block.ID) { case 10804: return Type::Bottom; case 10806: return Type::Double; default: return Type::Top; } } } namespace MossyStoneBrickStairs { BlockState MossyStoneBrickStairs() { return 9840; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 9870: case 9872: case 9874: case 9876: case 9878: case 9880: case 9882: case 9884: case 9886: case 9888: return eBlockFace::BLOCK_FACE_XM; case 9890: case 9892: case 9894: case 9896: case 9898: case 9900: case 9902: case 9904: case 9906: case 9908: return eBlockFace::BLOCK_FACE_XP; case 9830: case 9832: case 9834: case 9836: case 9838: case 9840: case 9842: case 9844: case 9846: case 9848: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } enum Half Half(const BlockState Block) { switch (Block.ID) { case 9840: case 9842: case 9844: case 9846: case 9848: case 9860: case 9862: case 9864: case 9866: case 9868: case 9880: case 9882: case 9884: case 9886: case 9888: case 9900: case 9902: case 9904: case 9906: case 9908: return Half::Bottom; default: return Half::Top; } } enum Shape Shape(const BlockState Block) { switch (Block.ID) { case 9832: case 9842: case 9852: case 9862: case 9872: case 9882: case 9892: case 9902: return Shape::InnerLeft; case 9834: case 9844: case 9854: case 9864: case 9874: case 9884: case 9894: case 9904: return Shape::InnerRight; case 9836: case 9846: case 9856: case 9866: case 9876: case 9886: case 9896: case 9906: return Shape::OuterLeft; case 9838: case 9848: case 9858: case 9868: case 9878: case 9888: case 9898: case 9908: return Shape::OuterRight; default: return Shape::Straight; } } } namespace MossyStoneBrickWall { BlockState MossyStoneBrickWall() { return 11842; } enum East East(const BlockState Block) { switch (Block.ID) { case 11950: case 11951: case 11952: case 11956: case 11957: case 11958: case 11962: case 11963: case 11964: case 11968: case 11969: case 11970: case 11974: case 11975: case 11976: case 11980: case 11981: case 11982: case 11986: case 11987: case 11988: case 11992: case 11993: case 11994: case 11998: case 11999: case 12000: case 12004: case 12005: case 12006: case 12010: case 12011: case 12012: case 12016: case 12017: case 12018: case 12022: case 12023: case 12024: case 12028: case 12029: case 12030: case 12034: case 12035: case 12036: case 12040: case 12041: case 12042: case 12046: case 12047: case 12048: case 12052: case 12053: case 12054: return East::Low; case 11842: case 11843: case 11844: case 11848: case 11849: case 11850: case 11854: case 11855: case 11856: case 11860: case 11861: case 11862: case 11866: case 11867: case 11868: case 11872: case 11873: case 11874: case 11878: case 11879: case 11880: case 11884: case 11885: case 11886: case 11890: case 11891: case 11892: case 11896: case 11897: case 11898: case 11902: case 11903: case 11904: case 11908: case 11909: case 11910: case 11914: case 11915: case 11916: case 11920: case 11921: case 11922: case 11926: case 11927: case 11928: case 11932: case 11933: case 11934: case 11938: case 11939: case 11940: case 11944: case 11945: case 11946: return East::None; default: return East::Tall; } } enum North North(const BlockState Block) { switch (Block.ID) { case 11878: case 11879: case 11880: case 11884: case 11885: case 11886: case 11890: case 11891: case 11892: case 11896: case 11897: case 11898: case 11902: case 11903: case 11904: case 11908: case 11909: case 11910: case 11986: case 11987: case 11988: case 11992: case 11993: case 11994: case 11998: case 11999: case 12000: case 12004: case 12005: case 12006: case 12010: case 12011: case 12012: case 12016: case 12017: case 12018: case 12094: case 12095: case 12096: case 12100: case 12101: case 12102: case 12106: case 12107: case 12108: case 12112: case 12113: case 12114: case 12118: case 12119: case 12120: case 12124: case 12125: case 12126: return North::Low; case 11842: case 11843: case 11844: case 11848: case 11849: case 11850: case 11854: case 11855: case 11856: case 11860: case 11861: case 11862: case 11866: case 11867: case 11868: case 11872: case 11873: case 11874: case 11950: case 11951: case 11952: case 11956: case 11957: case 11958: case 11962: case 11963: case 11964: case 11968: case 11969: case 11970: case 11974: case 11975: case 11976: case 11980: case 11981: case 11982: case 12058: case 12059: case 12060: case 12064: case 12065: case 12066: case 12070: case 12071: case 12072: case 12076: case 12077: case 12078: case 12082: case 12083: case 12084: case 12088: case 12089: case 12090: return North::None; default: return North::Tall; } } enum South South(const BlockState Block) { switch (Block.ID) { case 11854: case 11855: case 11856: case 11860: case 11861: case 11862: case 11890: case 11891: case 11892: case 11896: case 11897: case 11898: case 11926: case 11927: case 11928: case 11932: case 11933: case 11934: case 11962: case 11963: case 11964: case 11968: case 11969: case 11970: case 11998: case 11999: case 12000: case 12004: case 12005: case 12006: case 12034: case 12035: case 12036: case 12040: case 12041: case 12042: case 12070: case 12071: case 12072: case 12076: case 12077: case 12078: case 12106: case 12107: case 12108: case 12112: case 12113: case 12114: case 12142: case 12143: case 12144: case 12148: case 12149: case 12150: return South::Low; case 11842: case 11843: case 11844: case 11848: case 11849: case 11850: case 11878: case 11879: case 11880: case 11884: case 11885: case 11886: case 11914: case 11915: case 11916: case 11920: case 11921: case 11922: case 11950: case 11951: case 11952: case 11956: case 11957: case 11958: case 11986: case 11987: case 11988: case 11992: case 11993: case 11994: case 12022: case 12023: case 12024: case 12028: case 12029: case 12030: case 12058: case 12059: case 12060: case 12064: case 12065: case 12066: case 12094: case 12095: case 12096: case 12100: case 12101: case 12102: case 12130: case 12131: case 12132: case 12136: case 12137: case 12138: return South::None; default: return South::Tall; } } bool Up(const BlockState Block) { switch (Block.ID) { case 11848: case 11849: case 11850: case 11860: case 11861: case 11862: case 11872: case 11873: case 11874: case 11884: case 11885: case 11886: case 11896: case 11897: case 11898: case 11908: case 11909: case 11910: case 11920: case 11921: case 11922: case 11932: case 11933: case 11934: case 11944: case 11945: case 11946: case 11956: case 11957: case 11958: case 11968: case 11969: case 11970: case 11980: case 11981: case 11982: case 11992: case 11993: case 11994: case 12004: case 12005: case 12006: case 12016: case 12017: case 12018: case 12028: case 12029: case 12030: case 12040: case 12041: case 12042: case 12052: case 12053: case 12054: case 12064: case 12065: case 12066: case 12076: case 12077: case 12078: case 12088: case 12089: case 12090: case 12100: case 12101: case 12102: case 12112: case 12113: case 12114: case 12124: case 12125: case 12126: case 12136: case 12137: case 12138: case 12148: case 12149: case 12150: case 12160: case 12161: case 12162: return false; default: return true; } } enum West West(const BlockState Block) { switch (Block.ID) { case 11843: case 11849: case 11855: case 11861: case 11867: case 11873: case 11879: case 11885: case 11891: case 11897: case 11903: case 11909: case 11915: case 11921: case 11927: case 11933: case 11939: case 11945: case 11951: case 11957: case 11963: case 11969: case 11975: case 11981: case 11987: case 11993: case 11999: case 12005: case 12011: case 12017: case 12023: case 12029: case 12035: case 12041: case 12047: case 12053: case 12059: case 12065: case 12071: case 12077: case 12083: case 12089: case 12095: case 12101: case 12107: case 12113: case 12119: case 12125: case 12131: case 12137: case 12143: case 12149: case 12155: case 12161: return West::Low; case 11842: case 11848: case 11854: case 11860: case 11866: case 11872: case 11878: case 11884: case 11890: case 11896: case 11902: case 11908: case 11914: case 11920: case 11926: case 11932: case 11938: case 11944: case 11950: case 11956: case 11962: case 11968: case 11974: case 11980: case 11986: case 11992: case 11998: case 12004: case 12010: case 12016: case 12022: case 12028: case 12034: case 12040: case 12046: case 12052: case 12058: case 12064: case 12070: case 12076: case 12082: case 12088: case 12094: case 12100: case 12106: case 12112: case 12118: case 12124: case 12130: case 12136: case 12142: case 12148: case 12154: case 12160: return West::None; default: return West::Tall; } } } namespace MossyStoneBricks { } namespace MovingPiston { BlockState MovingPiston() { return 1400; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 1406: case 1407: return eBlockFace::BLOCK_FACE_XM; case 1402: case 1403: return eBlockFace::BLOCK_FACE_XP; case 1410: case 1411: return eBlockFace::BLOCK_FACE_YM; case 1408: case 1409: return eBlockFace::BLOCK_FACE_YP; case 1400: case 1401: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } enum Type Type(const BlockState Block) { switch (Block.ID) { case 1400: case 1402: case 1404: case 1406: case 1408: case 1410: return Type::Normal; default: return Type::Sticky; } } } namespace MushroomStem { BlockState MushroomStem() { return 4633; } bool Down(const BlockState Block) { switch (Block.ID) { case 4665: case 4666: case 4667: case 4668: case 4669: case 4670: case 4671: case 4672: case 4673: case 4674: case 4675: case 4676: case 4677: case 4678: case 4679: case 4680: case 4681: case 4682: case 4683: case 4684: case 4685: case 4686: case 4687: case 4688: case 4689: case 4690: case 4691: case 4692: case 4693: case 4694: case 4695: case 4696: return false; default: return true; } } bool East(const BlockState Block) { switch (Block.ID) { case 4649: case 4650: case 4651: case 4652: case 4653: case 4654: case 4655: case 4656: case 4657: case 4658: case 4659: case 4660: case 4661: case 4662: case 4663: case 4664: case 4681: case 4682: case 4683: case 4684: case 4685: case 4686: case 4687: case 4688: case 4689: case 4690: case 4691: case 4692: case 4693: case 4694: case 4695: case 4696: return false; default: return true; } } bool North(const BlockState Block) { switch (Block.ID) { case 4641: case 4642: case 4643: case 4644: case 4645: case 4646: case 4647: case 4648: case 4657: case 4658: case 4659: case 4660: case 4661: case 4662: case 4663: case 4664: case 4673: case 4674: case 4675: case 4676: case 4677: case 4678: case 4679: case 4680: case 4689: case 4690: case 4691: case 4692: case 4693: case 4694: case 4695: case 4696: return false; default: return true; } } bool South(const BlockState Block) { switch (Block.ID) { case 4637: case 4638: case 4639: case 4640: case 4645: case 4646: case 4647: case 4648: case 4653: case 4654: case 4655: case 4656: case 4661: case 4662: case 4663: case 4664: case 4669: case 4670: case 4671: case 4672: case 4677: case 4678: case 4679: case 4680: case 4685: case 4686: case 4687: case 4688: case 4693: case 4694: case 4695: case 4696: return false; default: return true; } } bool Up(const BlockState Block) { switch (Block.ID) { case 4635: case 4636: case 4639: case 4640: case 4643: case 4644: case 4647: case 4648: case 4651: case 4652: case 4655: case 4656: case 4659: case 4660: case 4663: case 4664: case 4667: case 4668: case 4671: case 4672: case 4675: case 4676: case 4679: case 4680: case 4683: case 4684: case 4687: case 4688: case 4691: case 4692: case 4695: case 4696: return false; default: return true; } } bool West(const BlockState Block) { switch (Block.ID) { case 4634: case 4636: case 4638: case 4640: case 4642: case 4644: case 4646: case 4648: case 4650: case 4652: case 4654: case 4656: case 4658: case 4660: case 4662: case 4664: case 4666: case 4668: case 4670: case 4672: case 4674: case 4676: case 4678: case 4680: case 4682: case 4684: case 4686: case 4688: case 4690: case 4692: case 4694: case 4696: return false; default: return true; } } } namespace Mycelium { BlockState Mycelium() { return 5013; } bool Snowy(const BlockState Block) { switch (Block.ID) { case 5013: return false; default: return true; } } } namespace NetherBrickFence { BlockState NetherBrickFence() { return 5047; } bool East(const BlockState Block) { switch (Block.ID) { case 5034: case 5035: case 5038: case 5039: case 5042: case 5043: case 5046: case 5047: return false; default: return true; } } bool North(const BlockState Block) { switch (Block.ID) { case 5026: case 5027: case 5030: case 5031: case 5042: case 5043: case 5046: case 5047: return false; default: return true; } } bool South(const BlockState Block) { switch (Block.ID) { case 5022: case 5023: case 5030: case 5031: case 5038: case 5039: case 5046: case 5047: return false; default: return true; } } bool West(const BlockState Block) { switch (Block.ID) { case 5019: case 5023: case 5027: case 5031: case 5035: case 5039: case 5043: case 5047: return false; default: return true; } } } namespace NetherBrickSlab { BlockState NetherBrickSlab() { return 8387; } enum Type Type(const BlockState Block) { switch (Block.ID) { case 8387: return Type::Bottom; case 8389: return Type::Double; default: return Type::Top; } } } namespace NetherBrickStairs { BlockState NetherBrickStairs() { return 5059; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 5089: case 5091: case 5093: case 5095: case 5097: case 5099: case 5101: case 5103: case 5105: case 5107: return eBlockFace::BLOCK_FACE_XM; case 5109: case 5111: case 5113: case 5115: case 5117: case 5119: case 5121: case 5123: case 5125: case 5127: return eBlockFace::BLOCK_FACE_XP; case 5049: case 5051: case 5053: case 5055: case 5057: case 5059: case 5061: case 5063: case 5065: case 5067: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } enum Half Half(const BlockState Block) { switch (Block.ID) { case 5059: case 5061: case 5063: case 5065: case 5067: case 5079: case 5081: case 5083: case 5085: case 5087: case 5099: case 5101: case 5103: case 5105: case 5107: case 5119: case 5121: case 5123: case 5125: case 5127: return Half::Bottom; default: return Half::Top; } } enum Shape Shape(const BlockState Block) { switch (Block.ID) { case 5051: case 5061: case 5071: case 5081: case 5091: case 5101: case 5111: case 5121: return Shape::InnerLeft; case 5053: case 5063: case 5073: case 5083: case 5093: case 5103: case 5113: case 5123: return Shape::InnerRight; case 5055: case 5065: case 5075: case 5085: case 5095: case 5105: case 5115: case 5125: return Shape::OuterLeft; case 5057: case 5067: case 5077: case 5087: case 5097: case 5107: case 5117: case 5127: return Shape::OuterRight; default: return Shape::Straight; } } } namespace NetherBrickWall { BlockState NetherBrickWall() { return 12814; } enum East East(const BlockState Block) { switch (Block.ID) { case 12922: case 12923: case 12924: case 12928: case 12929: case 12930: case 12934: case 12935: case 12936: case 12940: case 12941: case 12942: case 12946: case 12947: case 12948: case 12952: case 12953: case 12954: case 12958: case 12959: case 12960: case 12964: case 12965: case 12966: case 12970: case 12971: case 12972: case 12976: case 12977: case 12978: case 12982: case 12983: case 12984: case 12988: case 12989: case 12990: case 12994: case 12995: case 12996: case 13000: case 13001: case 13002: case 13006: case 13007: case 13008: case 13012: case 13013: case 13014: case 13018: case 13019: case 13020: case 13024: case 13025: case 13026: return East::Low; case 12814: case 12815: case 12816: case 12820: case 12821: case 12822: case 12826: case 12827: case 12828: case 12832: case 12833: case 12834: case 12838: case 12839: case 12840: case 12844: case 12845: case 12846: case 12850: case 12851: case 12852: case 12856: case 12857: case 12858: case 12862: case 12863: case 12864: case 12868: case 12869: case 12870: case 12874: case 12875: case 12876: case 12880: case 12881: case 12882: case 12886: case 12887: case 12888: case 12892: case 12893: case 12894: case 12898: case 12899: case 12900: case 12904: case 12905: case 12906: case 12910: case 12911: case 12912: case 12916: case 12917: case 12918: return East::None; default: return East::Tall; } } enum North North(const BlockState Block) { switch (Block.ID) { case 12850: case 12851: case 12852: case 12856: case 12857: case 12858: case 12862: case 12863: case 12864: case 12868: case 12869: case 12870: case 12874: case 12875: case 12876: case 12880: case 12881: case 12882: case 12958: case 12959: case 12960: case 12964: case 12965: case 12966: case 12970: case 12971: case 12972: case 12976: case 12977: case 12978: case 12982: case 12983: case 12984: case 12988: case 12989: case 12990: case 13066: case 13067: case 13068: case 13072: case 13073: case 13074: case 13078: case 13079: case 13080: case 13084: case 13085: case 13086: case 13090: case 13091: case 13092: case 13096: case 13097: case 13098: return North::Low; case 12814: case 12815: case 12816: case 12820: case 12821: case 12822: case 12826: case 12827: case 12828: case 12832: case 12833: case 12834: case 12838: case 12839: case 12840: case 12844: case 12845: case 12846: case 12922: case 12923: case 12924: case 12928: case 12929: case 12930: case 12934: case 12935: case 12936: case 12940: case 12941: case 12942: case 12946: case 12947: case 12948: case 12952: case 12953: case 12954: case 13030: case 13031: case 13032: case 13036: case 13037: case 13038: case 13042: case 13043: case 13044: case 13048: case 13049: case 13050: case 13054: case 13055: case 13056: case 13060: case 13061: case 13062: return North::None; default: return North::Tall; } } enum South South(const BlockState Block) { switch (Block.ID) { case 12826: case 12827: case 12828: case 12832: case 12833: case 12834: case 12862: case 12863: case 12864: case 12868: case 12869: case 12870: case 12898: case 12899: case 12900: case 12904: case 12905: case 12906: case 12934: case 12935: case 12936: case 12940: case 12941: case 12942: case 12970: case 12971: case 12972: case 12976: case 12977: case 12978: case 13006: case 13007: case 13008: case 13012: case 13013: case 13014: case 13042: case 13043: case 13044: case 13048: case 13049: case 13050: case 13078: case 13079: case 13080: case 13084: case 13085: case 13086: case 13114: case 13115: case 13116: case 13120: case 13121: case 13122: return South::Low; case 12814: case 12815: case 12816: case 12820: case 12821: case 12822: case 12850: case 12851: case 12852: case 12856: case 12857: case 12858: case 12886: case 12887: case 12888: case 12892: case 12893: case 12894: case 12922: case 12923: case 12924: case 12928: case 12929: case 12930: case 12958: case 12959: case 12960: case 12964: case 12965: case 12966: case 12994: case 12995: case 12996: case 13000: case 13001: case 13002: case 13030: case 13031: case 13032: case 13036: case 13037: case 13038: case 13066: case 13067: case 13068: case 13072: case 13073: case 13074: case 13102: case 13103: case 13104: case 13108: case 13109: case 13110: return South::None; default: return South::Tall; } } bool Up(const BlockState Block) { switch (Block.ID) { case 12820: case 12821: case 12822: case 12832: case 12833: case 12834: case 12844: case 12845: case 12846: case 12856: case 12857: case 12858: case 12868: case 12869: case 12870: case 12880: case 12881: case 12882: case 12892: case 12893: case 12894: case 12904: case 12905: case 12906: case 12916: case 12917: case 12918: case 12928: case 12929: case 12930: case 12940: case 12941: case 12942: case 12952: case 12953: case 12954: case 12964: case 12965: case 12966: case 12976: case 12977: case 12978: case 12988: case 12989: case 12990: case 13000: case 13001: case 13002: case 13012: case 13013: case 13014: case 13024: case 13025: case 13026: case 13036: case 13037: case 13038: case 13048: case 13049: case 13050: case 13060: case 13061: case 13062: case 13072: case 13073: case 13074: case 13084: case 13085: case 13086: case 13096: case 13097: case 13098: case 13108: case 13109: case 13110: case 13120: case 13121: case 13122: case 13132: case 13133: case 13134: return false; default: return true; } } enum West West(const BlockState Block) { switch (Block.ID) { case 12815: case 12821: case 12827: case 12833: case 12839: case 12845: case 12851: case 12857: case 12863: case 12869: case 12875: case 12881: case 12887: case 12893: case 12899: case 12905: case 12911: case 12917: case 12923: case 12929: case 12935: case 12941: case 12947: case 12953: case 12959: case 12965: case 12971: case 12977: case 12983: case 12989: case 12995: case 13001: case 13007: case 13013: case 13019: case 13025: case 13031: case 13037: case 13043: case 13049: case 13055: case 13061: case 13067: case 13073: case 13079: case 13085: case 13091: case 13097: case 13103: case 13109: case 13115: case 13121: case 13127: case 13133: return West::Low; case 12814: case 12820: case 12826: case 12832: case 12838: case 12844: case 12850: case 12856: case 12862: case 12868: case 12874: case 12880: case 12886: case 12892: case 12898: case 12904: case 12910: case 12916: case 12922: case 12928: case 12934: case 12940: case 12946: case 12952: case 12958: case 12964: case 12970: case 12976: case 12982: case 12988: case 12994: case 13000: case 13006: case 13012: case 13018: case 13024: case 13030: case 13036: case 13042: case 13048: case 13054: case 13060: case 13066: case 13072: case 13078: case 13084: case 13090: case 13096: case 13102: case 13108: case 13114: case 13120: case 13126: case 13132: return West::None; default: return West::Tall; } } } namespace NetherBricks { } namespace NetherGoldOre { } namespace NetherPortal { BlockState NetherPortal() { return 4014; } enum Axis Axis(const BlockState Block) { switch (Block.ID) { case 4014: return Axis::X; default: return Axis::Z; } } } namespace NetherQuartzOre { } namespace NetherSprouts { } namespace NetherWart { BlockState NetherWart() { return 5128; } unsigned char Age(const BlockState Block) { switch (Block.ID) { case 5128: return 0; case 5129: return 1; case 5130: return 2; default: return 3; } } } namespace NetherWartBlock { } namespace NetheriteBlock { } namespace Netherrack { } namespace NoteBlock { BlockState NoteBlock() { return 250; } enum Instrument Instrument(const BlockState Block) { switch (Block.ID) { case 949: case 950: case 951: case 952: case 953: case 954: case 955: case 956: case 957: case 958: case 959: case 960: case 961: case 962: case 963: case 964: case 965: case 966: case 967: case 968: case 969: case 970: case 971: case 972: case 973: case 974: case 975: case 976: case 977: case 978: case 979: case 980: case 981: case 982: case 983: case 984: case 985: case 986: case 987: case 988: case 989: case 990: case 991: case 992: case 993: case 994: case 995: case 996: case 997: case 998: return Instrument::Banjo; case 299: case 300: case 301: case 302: case 303: case 304: case 305: case 306: case 307: case 308: case 309: case 310: case 311: case 312: case 313: case 314: case 315: case 316: case 317: case 318: case 319: case 320: case 321: case 322: case 323: case 324: case 325: case 326: case 327: case 328: case 329: case 330: case 331: case 332: case 333: case 334: case 335: case 336: case 337: case 338: case 339: case 340: case 341: case 342: case 343: case 344: case 345: case 346: case 347: case 348: return Instrument::Basedrum; case 449: case 450: case 451: case 452: case 453: case 454: case 455: case 456: case 457: case 458: case 459: case 460: case 461: case 462: case 463: case 464: case 465: case 466: case 467: case 468: case 469: case 470: case 471: case 472: case 473: case 474: case 475: case 476: case 477: case 478: case 479: case 480: case 481: case 482: case 483: case 484: case 485: case 486: case 487: case 488: case 489: case 490: case 491: case 492: case 493: case 494: case 495: case 496: case 497: case 498: return Instrument::Bass; case 549: case 550: case 551: case 552: case 553: case 554: case 555: case 556: case 557: case 558: case 559: case 560: case 561: case 562: case 563: case 564: case 565: case 566: case 567: case 568: case 569: case 570: case 571: case 572: case 573: case 574: case 575: case 576: case 577: case 578: case 579: case 580: case 581: case 582: case 583: case 584: case 585: case 586: case 587: case 588: case 589: case 590: case 591: case 592: case 593: case 594: case 595: case 596: case 597: case 598: return Instrument::Bell; case 899: case 900: case 901: case 902: case 903: case 904: case 905: case 906: case 907: case 908: case 909: case 910: case 911: case 912: case 913: case 914: case 915: case 916: case 917: case 918: case 919: case 920: case 921: case 922: case 923: case 924: case 925: case 926: case 927: case 928: case 929: case 930: case 931: case 932: case 933: case 934: case 935: case 936: case 937: case 938: case 939: case 940: case 941: case 942: case 943: case 944: case 945: case 946: case 947: case 948: return Instrument::Bit; case 649: case 650: case 651: case 652: case 653: case 654: case 655: case 656: case 657: case 658: case 659: case 660: case 661: case 662: case 663: case 664: case 665: case 666: case 667: case 668: case 669: case 670: case 671: case 672: case 673: case 674: case 675: case 676: case 677: case 678: case 679: case 680: case 681: case 682: case 683: case 684: case 685: case 686: case 687: case 688: case 689: case 690: case 691: case 692: case 693: case 694: case 695: case 696: case 697: case 698: return Instrument::Chime; case 799: case 800: case 801: case 802: case 803: case 804: case 805: case 806: case 807: case 808: case 809: case 810: case 811: case 812: case 813: case 814: case 815: case 816: case 817: case 818: case 819: case 820: case 821: case 822: case 823: case 824: case 825: case 826: case 827: case 828: case 829: case 830: case 831: case 832: case 833: case 834: case 835: case 836: case 837: case 838: case 839: case 840: case 841: case 842: case 843: case 844: case 845: case 846: case 847: case 848: return Instrument::CowBell; case 849: case 850: case 851: case 852: case 853: case 854: case 855: case 856: case 857: case 858: case 859: case 860: case 861: case 862: case 863: case 864: case 865: case 866: case 867: case 868: case 869: case 870: case 871: case 872: case 873: case 874: case 875: case 876: case 877: case 878: case 879: case 880: case 881: case 882: case 883: case 884: case 885: case 886: case 887: case 888: case 889: case 890: case 891: case 892: case 893: case 894: case 895: case 896: case 897: case 898: return Instrument::Didgeridoo; case 499: case 500: case 501: case 502: case 503: case 504: case 505: case 506: case 507: case 508: case 509: case 510: case 511: case 512: case 513: case 514: case 515: case 516: case 517: case 518: case 519: case 520: case 521: case 522: case 523: case 524: case 525: case 526: case 527: case 528: case 529: case 530: case 531: case 532: case 533: case 534: case 535: case 536: case 537: case 538: case 539: case 540: case 541: case 542: case 543: case 544: case 545: case 546: case 547: case 548: return Instrument::Flute; case 599: case 600: case 601: case 602: case 603: case 604: case 605: case 606: case 607: case 608: case 609: case 610: case 611: case 612: case 613: case 614: case 615: case 616: case 617: case 618: case 619: case 620: case 621: case 622: case 623: case 624: case 625: case 626: case 627: case 628: case 629: case 630: case 631: case 632: case 633: case 634: case 635: case 636: case 637: case 638: case 639: case 640: case 641: case 642: case 643: case 644: case 645: case 646: case 647: case 648: return Instrument::Guitar; case 249: case 250: case 251: case 252: case 253: case 254: case 255: case 256: case 257: case 258: case 259: case 260: case 261: case 262: case 263: case 264: case 265: case 266: case 267: case 268: case 269: case 270: case 271: case 272: case 273: case 274: case 275: case 276: case 277: case 278: case 279: case 280: case 281: case 282: case 283: case 284: case 285: case 286: case 287: case 288: case 289: case 290: case 291: case 292: case 293: case 294: case 295: case 296: case 297: case 298: return Instrument::Harp; case 399: case 400: case 401: case 402: case 403: case 404: case 405: case 406: case 407: case 408: case 409: case 410: case 411: case 412: case 413: case 414: case 415: case 416: case 417: case 418: case 419: case 420: case 421: case 422: case 423: case 424: case 425: case 426: case 427: case 428: case 429: case 430: case 431: case 432: case 433: case 434: case 435: case 436: case 437: case 438: case 439: case 440: case 441: case 442: case 443: case 444: case 445: case 446: case 447: case 448: return Instrument::Hat; case 749: case 750: case 751: case 752: case 753: case 754: case 755: case 756: case 757: case 758: case 759: case 760: case 761: case 762: case 763: case 764: case 765: case 766: case 767: case 768: case 769: case 770: case 771: case 772: case 773: case 774: case 775: case 776: case 777: case 778: case 779: case 780: case 781: case 782: case 783: case 784: case 785: case 786: case 787: case 788: case 789: case 790: case 791: case 792: case 793: case 794: case 795: case 796: case 797: case 798: return Instrument::IronXylophone; case 999: case 1000: case 1001: case 1002: case 1003: case 1004: case 1005: case 1006: case 1007: case 1008: case 1009: case 1010: case 1011: case 1012: case 1013: case 1014: case 1015: case 1016: case 1017: case 1018: case 1019: case 1020: case 1021: case 1022: case 1023: case 1024: case 1025: case 1026: case 1027: case 1028: case 1029: case 1030: case 1031: case 1032: case 1033: case 1034: case 1035: case 1036: case 1037: case 1038: case 1039: case 1040: case 1041: case 1042: case 1043: case 1044: case 1045: case 1046: case 1047: case 1048: return Instrument::Pling; case 349: case 350: case 351: case 352: case 353: case 354: case 355: case 356: case 357: case 358: case 359: case 360: case 361: case 362: case 363: case 364: case 365: case 366: case 367: case 368: case 369: case 370: case 371: case 372: case 373: case 374: case 375: case 376: case 377: case 378: case 379: case 380: case 381: case 382: case 383: case 384: case 385: case 386: case 387: case 388: case 389: case 390: case 391: case 392: case 393: case 394: case 395: case 396: case 397: case 398: return Instrument::Snare; default: return Instrument::Xylophone; } } unsigned char Note(const BlockState Block) { switch (Block.ID) { case 249: case 250: case 299: case 300: case 349: case 350: case 399: case 400: case 449: case 450: case 499: case 500: case 549: case 550: case 599: case 600: case 649: case 650: case 699: case 700: case 749: case 750: case 799: case 800: case 849: case 850: case 899: case 900: case 949: case 950: case 999: case 1000: return 0; case 251: case 252: case 301: case 302: case 351: case 352: case 401: case 402: case 451: case 452: case 501: case 502: case 551: case 552: case 601: case 602: case 651: case 652: case 701: case 702: case 751: case 752: case 801: case 802: case 851: case 852: case 901: case 902: case 951: case 952: case 1001: case 1002: return 1; case 269: case 270: case 319: case 320: case 369: case 370: case 419: case 420: case 469: case 470: case 519: case 520: case 569: case 570: case 619: case 620: case 669: case 670: case 719: case 720: case 769: case 770: case 819: case 820: case 869: case 870: case 919: case 920: case 969: case 970: case 1019: case 1020: return 10; case 271: case 272: case 321: case 322: case 371: case 372: case 421: case 422: case 471: case 472: case 521: case 522: case 571: case 572: case 621: case 622: case 671: case 672: case 721: case 722: case 771: case 772: case 821: case 822: case 871: case 872: case 921: case 922: case 971: case 972: case 1021: case 1022: return 11; case 273: case 274: case 323: case 324: case 373: case 374: case 423: case 424: case 473: case 474: case 523: case 524: case 573: case 574: case 623: case 624: case 673: case 674: case 723: case 724: case 773: case 774: case 823: case 824: case 873: case 874: case 923: case 924: case 973: case 974: case 1023: case 1024: return 12; case 275: case 276: case 325: case 326: case 375: case 376: case 425: case 426: case 475: case 476: case 525: case 526: case 575: case 576: case 625: case 626: case 675: case 676: case 725: case 726: case 775: case 776: case 825: case 826: case 875: case 876: case 925: case 926: case 975: case 976: case 1025: case 1026: return 13; case 277: case 278: case 327: case 328: case 377: case 378: case 427: case 428: case 477: case 478: case 527: case 528: case 577: case 578: case 627: case 628: case 677: case 678: case 727: case 728: case 777: case 778: case 827: case 828: case 877: case 878: case 927: case 928: case 977: case 978: case 1027: case 1028: return 14; case 279: case 280: case 329: case 330: case 379: case 380: case 429: case 430: case 479: case 480: case 529: case 530: case 579: case 580: case 629: case 630: case 679: case 680: case 729: case 730: case 779: case 780: case 829: case 830: case 879: case 880: case 929: case 930: case 979: case 980: case 1029: case 1030: return 15; case 281: case 282: case 331: case 332: case 381: case 382: case 431: case 432: case 481: case 482: case 531: case 532: case 581: case 582: case 631: case 632: case 681: case 682: case 731: case 732: case 781: case 782: case 831: case 832: case 881: case 882: case 931: case 932: case 981: case 982: case 1031: case 1032: return 16; case 283: case 284: case 333: case 334: case 383: case 384: case 433: case 434: case 483: case 484: case 533: case 534: case 583: case 584: case 633: case 634: case 683: case 684: case 733: case 734: case 783: case 784: case 833: case 834: case 883: case 884: case 933: case 934: case 983: case 984: case 1033: case 1034: return 17; case 285: case 286: case 335: case 336: case 385: case 386: case 435: case 436: case 485: case 486: case 535: case 536: case 585: case 586: case 635: case 636: case 685: case 686: case 735: case 736: case 785: case 786: case 835: case 836: case 885: case 886: case 935: case 936: case 985: case 986: case 1035: case 1036: return 18; case 287: case 288: case 337: case 338: case 387: case 388: case 437: case 438: case 487: case 488: case 537: case 538: case 587: case 588: case 637: case 638: case 687: case 688: case 737: case 738: case 787: case 788: case 837: case 838: case 887: case 888: case 937: case 938: case 987: case 988: case 1037: case 1038: return 19; case 253: case 254: case 303: case 304: case 353: case 354: case 403: case 404: case 453: case 454: case 503: case 504: case 553: case 554: case 603: case 604: case 653: case 654: case 703: case 704: case 753: case 754: case 803: case 804: case 853: case 854: case 903: case 904: case 953: case 954: case 1003: case 1004: return 2; case 289: case 290: case 339: case 340: case 389: case 390: case 439: case 440: case 489: case 490: case 539: case 540: case 589: case 590: case 639: case 640: case 689: case 690: case 739: case 740: case 789: case 790: case 839: case 840: case 889: case 890: case 939: case 940: case 989: case 990: case 1039: case 1040: return 20; case 291: case 292: case 341: case 342: case 391: case 392: case 441: case 442: case 491: case 492: case 541: case 542: case 591: case 592: case 641: case 642: case 691: case 692: case 741: case 742: case 791: case 792: case 841: case 842: case 891: case 892: case 941: case 942: case 991: case 992: case 1041: case 1042: return 21; case 293: case 294: case 343: case 344: case 393: case 394: case 443: case 444: case 493: case 494: case 543: case 544: case 593: case 594: case 643: case 644: case 693: case 694: case 743: case 744: case 793: case 794: case 843: case 844: case 893: case 894: case 943: case 944: case 993: case 994: case 1043: case 1044: return 22; case 295: case 296: case 345: case 346: case 395: case 396: case 445: case 446: case 495: case 496: case 545: case 546: case 595: case 596: case 645: case 646: case 695: case 696: case 745: case 746: case 795: case 796: case 845: case 846: case 895: case 896: case 945: case 946: case 995: case 996: case 1045: case 1046: return 23; case 297: case 298: case 347: case 348: case 397: case 398: case 447: case 448: case 497: case 498: case 547: case 548: case 597: case 598: case 647: case 648: case 697: case 698: case 747: case 748: case 797: case 798: case 847: case 848: case 897: case 898: case 947: case 948: case 997: case 998: case 1047: case 1048: return 24; case 255: case 256: case 305: case 306: case 355: case 356: case 405: case 406: case 455: case 456: case 505: case 506: case 555: case 556: case 605: case 606: case 655: case 656: case 705: case 706: case 755: case 756: case 805: case 806: case 855: case 856: case 905: case 906: case 955: case 956: case 1005: case 1006: return 3; case 257: case 258: case 307: case 308: case 357: case 358: case 407: case 408: case 457: case 458: case 507: case 508: case 557: case 558: case 607: case 608: case 657: case 658: case 707: case 708: case 757: case 758: case 807: case 808: case 857: case 858: case 907: case 908: case 957: case 958: case 1007: case 1008: return 4; case 259: case 260: case 309: case 310: case 359: case 360: case 409: case 410: case 459: case 460: case 509: case 510: case 559: case 560: case 609: case 610: case 659: case 660: case 709: case 710: case 759: case 760: case 809: case 810: case 859: case 860: case 909: case 910: case 959: case 960: case 1009: case 1010: return 5; case 261: case 262: case 311: case 312: case 361: case 362: case 411: case 412: case 461: case 462: case 511: case 512: case 561: case 562: case 611: case 612: case 661: case 662: case 711: case 712: case 761: case 762: case 811: case 812: case 861: case 862: case 911: case 912: case 961: case 962: case 1011: case 1012: return 6; case 263: case 264: case 313: case 314: case 363: case 364: case 413: case 414: case 463: case 464: case 513: case 514: case 563: case 564: case 613: case 614: case 663: case 664: case 713: case 714: case 763: case 764: case 813: case 814: case 863: case 864: case 913: case 914: case 963: case 964: case 1013: case 1014: return 7; case 265: case 266: case 315: case 316: case 365: case 366: case 415: case 416: case 465: case 466: case 515: case 516: case 565: case 566: case 615: case 616: case 665: case 666: case 715: case 716: case 765: case 766: case 815: case 816: case 865: case 866: case 915: case 916: case 965: case 966: case 1015: case 1016: return 8; default: return 9; } } bool Powered(const BlockState Block) { switch (Block.ID) { case 250: case 252: case 254: case 256: case 258: case 260: case 262: case 264: case 266: case 268: case 270: case 272: case 274: case 276: case 278: case 280: case 282: case 284: case 286: case 288: case 290: case 292: case 294: case 296: case 298: case 300: case 302: case 304: case 306: case 308: case 310: case 312: case 314: case 316: case 318: case 320: case 322: case 324: case 326: case 328: case 330: case 332: case 334: case 336: case 338: case 340: case 342: case 344: case 346: case 348: case 350: case 352: case 354: case 356: case 358: case 360: case 362: case 364: case 366: case 368: case 370: case 372: case 374: case 376: case 378: case 380: case 382: case 384: case 386: case 388: case 390: case 392: case 394: case 396: case 398: case 400: case 402: case 404: case 406: case 408: case 410: case 412: case 414: case 416: case 418: case 420: case 422: case 424: case 426: case 428: case 430: case 432: case 434: case 436: case 438: case 440: case 442: case 444: case 446: case 448: case 450: case 452: case 454: case 456: case 458: case 460: case 462: case 464: case 466: case 468: case 470: case 472: case 474: case 476: case 478: case 480: case 482: case 484: case 486: case 488: case 490: case 492: case 494: case 496: case 498: case 500: case 502: case 504: case 506: case 508: case 510: case 512: case 514: case 516: case 518: case 520: case 522: case 524: case 526: case 528: case 530: case 532: case 534: case 536: case 538: case 540: case 542: case 544: case 546: case 548: case 550: case 552: case 554: case 556: case 558: case 560: case 562: case 564: case 566: case 568: case 570: case 572: case 574: case 576: case 578: case 580: case 582: case 584: case 586: case 588: case 590: case 592: case 594: case 596: case 598: case 600: case 602: case 604: case 606: case 608: case 610: case 612: case 614: case 616: case 618: case 620: case 622: case 624: case 626: case 628: case 630: case 632: case 634: case 636: case 638: case 640: case 642: case 644: case 646: case 648: case 650: case 652: case 654: case 656: case 658: case 660: case 662: case 664: case 666: case 668: case 670: case 672: case 674: case 676: case 678: case 680: case 682: case 684: case 686: case 688: case 690: case 692: case 694: case 696: case 698: case 700: case 702: case 704: case 706: case 708: case 710: case 712: case 714: case 716: case 718: case 720: case 722: case 724: case 726: case 728: case 730: case 732: case 734: case 736: case 738: case 740: case 742: case 744: case 746: case 748: case 750: case 752: case 754: case 756: case 758: case 760: case 762: case 764: case 766: case 768: case 770: case 772: case 774: case 776: case 778: case 780: case 782: case 784: case 786: case 788: case 790: case 792: case 794: case 796: case 798: case 800: case 802: case 804: case 806: case 808: case 810: case 812: case 814: case 816: case 818: case 820: case 822: case 824: case 826: case 828: case 830: case 832: case 834: case 836: case 838: case 840: case 842: case 844: case 846: case 848: case 850: case 852: case 854: case 856: case 858: case 860: case 862: case 864: case 866: case 868: case 870: case 872: case 874: case 876: case 878: case 880: case 882: case 884: case 886: case 888: case 890: case 892: case 894: case 896: case 898: case 900: case 902: case 904: case 906: case 908: case 910: case 912: case 914: case 916: case 918: case 920: case 922: case 924: case 926: case 928: case 930: case 932: case 934: case 936: case 938: case 940: case 942: case 944: case 946: case 948: case 950: case 952: case 954: case 956: case 958: case 960: case 962: case 964: case 966: case 968: case 970: case 972: case 974: case 976: case 978: case 980: case 982: case 984: case 986: case 988: case 990: case 992: case 994: case 996: case 998: case 1000: case 1002: case 1004: case 1006: case 1008: case 1010: case 1012: case 1014: case 1016: case 1018: case 1020: case 1022: case 1024: case 1026: case 1028: case 1030: case 1032: case 1034: case 1036: case 1038: case 1040: case 1042: case 1044: case 1046: case 1048: return false; default: return true; } } } namespace OakButton { BlockState OakButton() { return 6355; } enum Face Face(const BlockState Block) { switch (Block.ID) { case 6362: case 6363: case 6364: case 6365: case 6366: case 6367: case 6368: case 6369: return Face::Ceiling; case 6346: case 6347: case 6348: case 6349: case 6350: case 6351: case 6352: case 6353: return Face::Floor; default: return Face::Wall; } } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 6350: case 6351: case 6358: case 6359: case 6366: case 6367: return eBlockFace::BLOCK_FACE_XM; case 6352: case 6353: case 6360: case 6361: case 6368: case 6369: return eBlockFace::BLOCK_FACE_XP; case 6346: case 6347: case 6354: case 6355: case 6362: case 6363: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } bool Powered(const BlockState Block) { switch (Block.ID) { case 6347: case 6349: case 6351: case 6353: case 6355: case 6357: case 6359: case 6361: case 6363: case 6365: case 6367: case 6369: return false; default: return true; } } } namespace OakDoor { BlockState OakDoor() { return 3584; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 3605: case 3606: case 3607: case 3608: case 3609: case 3610: case 3611: case 3612: case 3613: case 3614: case 3615: case 3616: case 3617: case 3618: case 3619: case 3620: return eBlockFace::BLOCK_FACE_XM; case 3621: case 3622: case 3623: case 3624: case 3625: case 3626: case 3627: case 3628: case 3629: case 3630: case 3631: case 3632: case 3633: case 3634: case 3635: case 3636: return eBlockFace::BLOCK_FACE_XP; case 3573: case 3574: case 3575: case 3576: case 3577: case 3578: case 3579: case 3580: case 3581: case 3582: case 3583: case 3584: case 3585: case 3586: case 3587: case 3588: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } enum Half Half(const BlockState Block) { switch (Block.ID) { case 3581: case 3582: case 3583: case 3584: case 3585: case 3586: case 3587: case 3588: case 3597: case 3598: case 3599: case 3600: case 3601: case 3602: case 3603: case 3604: case 3613: case 3614: case 3615: case 3616: case 3617: case 3618: case 3619: case 3620: case 3629: case 3630: case 3631: case 3632: case 3633: case 3634: case 3635: case 3636: return Half::Lower; default: return Half::Upper; } } enum Hinge Hinge(const BlockState Block) { switch (Block.ID) { case 3573: case 3574: case 3575: case 3576: case 3581: case 3582: case 3583: case 3584: case 3589: case 3590: case 3591: case 3592: case 3597: case 3598: case 3599: case 3600: case 3605: case 3606: case 3607: case 3608: case 3613: case 3614: case 3615: case 3616: case 3621: case 3622: case 3623: case 3624: case 3629: case 3630: case 3631: case 3632: return Hinge::Left; default: return Hinge::Right; } } bool Open(const BlockState Block) { switch (Block.ID) { case 3575: case 3576: case 3579: case 3580: case 3583: case 3584: case 3587: case 3588: case 3591: case 3592: case 3595: case 3596: case 3599: case 3600: case 3603: case 3604: case 3607: case 3608: case 3611: case 3612: case 3615: case 3616: case 3619: case 3620: case 3623: case 3624: case 3627: case 3628: case 3631: case 3632: case 3635: case 3636: return false; default: return true; } } bool Powered(const BlockState Block) { switch (Block.ID) { case 3574: case 3576: case 3578: case 3580: case 3582: case 3584: case 3586: case 3588: case 3590: case 3592: case 3594: case 3596: case 3598: case 3600: case 3602: case 3604: case 3606: case 3608: case 3610: case 3612: case 3614: case 3616: case 3618: case 3620: case 3622: case 3624: case 3626: case 3628: case 3630: case 3632: case 3634: case 3636: return false; default: return true; } } } namespace OakFence { BlockState OakFence() { return 3997; } bool East(const BlockState Block) { switch (Block.ID) { case 3984: case 3985: case 3988: case 3989: case 3992: case 3993: case 3996: case 3997: return false; default: return true; } } bool North(const BlockState Block) { switch (Block.ID) { case 3976: case 3977: case 3980: case 3981: case 3992: case 3993: case 3996: case 3997: return false; default: return true; } } bool South(const BlockState Block) { switch (Block.ID) { case 3972: case 3973: case 3980: case 3981: case 3988: case 3989: case 3996: case 3997: return false; default: return true; } } bool West(const BlockState Block) { switch (Block.ID) { case 3969: case 3973: case 3977: case 3981: case 3985: case 3989: case 3993: case 3997: return false; default: return true; } } } namespace OakFenceGate { BlockState OakFenceGate() { return 4827; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 4836: case 4837: case 4838: case 4839: case 4840: case 4841: case 4842: case 4843: return eBlockFace::BLOCK_FACE_XM; case 4844: case 4845: case 4846: case 4847: case 4848: case 4849: case 4850: case 4851: return eBlockFace::BLOCK_FACE_XP; case 4820: case 4821: case 4822: case 4823: case 4824: case 4825: case 4826: case 4827: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } bool InWall(const BlockState Block) { switch (Block.ID) { case 4824: case 4825: case 4826: case 4827: case 4832: case 4833: case 4834: case 4835: case 4840: case 4841: case 4842: case 4843: case 4848: case 4849: case 4850: case 4851: return false; default: return true; } } bool Open(const BlockState Block) { switch (Block.ID) { case 4822: case 4823: case 4826: case 4827: case 4830: case 4831: case 4834: case 4835: case 4838: case 4839: case 4842: case 4843: case 4846: case 4847: case 4850: case 4851: return false; default: return true; } } bool Powered(const BlockState Block) { switch (Block.ID) { case 4821: case 4823: case 4825: case 4827: case 4829: case 4831: case 4833: case 4835: case 4837: case 4839: case 4841: case 4843: case 4845: case 4847: case 4849: case 4851: return false; default: return true; } } } namespace OakLeaves { BlockState OakLeaves() { return 158; } unsigned char Distance(const BlockState Block) { switch (Block.ID) { case 145: case 146: return 1; case 147: case 148: return 2; case 149: case 150: return 3; case 151: case 152: return 4; case 153: case 154: return 5; case 155: case 156: return 6; default: return 7; } } bool Persistent(const BlockState Block) { switch (Block.ID) { case 146: case 148: case 150: case 152: case 154: case 156: case 158: return false; default: return true; } } } namespace OakLog { BlockState OakLog() { return 74; } enum Axis Axis(const BlockState Block) { switch (Block.ID) { case 73: return Axis::X; case 74: return Axis::Y; default: return Axis::Z; } } } namespace OakPlanks { } namespace OakPressurePlate { BlockState OakPressurePlate() { return 3874; } bool Powered(const BlockState Block) { switch (Block.ID) { case 3874: return false; default: return true; } } } namespace OakSapling { BlockState OakSapling() { return 21; } unsigned char Stage(const BlockState Block) { switch (Block.ID) { case 21: return 0; default: return 1; } } } namespace OakSign { BlockState OakSign() { return 3382; } unsigned char Rotation(const BlockState Block) { switch (Block.ID) { case 3382: return 0; case 3384: return 1; case 3402: return 10; case 3404: return 11; case 3406: return 12; case 3408: return 13; case 3410: return 14; case 3412: return 15; case 3386: return 2; case 3388: return 3; case 3390: return 4; case 3392: return 5; case 3394: return 6; case 3396: return 7; case 3398: return 8; default: return 9; } } } namespace OakSlab { BlockState OakSlab() { return 8303; } enum Type Type(const BlockState Block) { switch (Block.ID) { case 8303: return Type::Bottom; case 8305: return Type::Double; default: return Type::Top; } } } namespace OakStairs { BlockState OakStairs() { return 1965; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 1995: case 1997: case 1999: case 2001: case 2003: case 2005: case 2007: case 2009: case 2011: case 2013: return eBlockFace::BLOCK_FACE_XM; case 2015: case 2017: case 2019: case 2021: case 2023: case 2025: case 2027: case 2029: case 2031: case 2033: return eBlockFace::BLOCK_FACE_XP; case 1955: case 1957: case 1959: case 1961: case 1963: case 1965: case 1967: case 1969: case 1971: case 1973: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } enum Half Half(const BlockState Block) { switch (Block.ID) { case 1965: case 1967: case 1969: case 1971: case 1973: case 1985: case 1987: case 1989: case 1991: case 1993: case 2005: case 2007: case 2009: case 2011: case 2013: case 2025: case 2027: case 2029: case 2031: case 2033: return Half::Bottom; default: return Half::Top; } } enum Shape Shape(const BlockState Block) { switch (Block.ID) { case 1957: case 1967: case 1977: case 1987: case 1997: case 2007: case 2017: case 2027: return Shape::InnerLeft; case 1959: case 1969: case 1979: case 1989: case 1999: case 2009: case 2019: case 2029: return Shape::InnerRight; case 1961: case 1971: case 1981: case 1991: case 2001: case 2011: case 2021: case 2031: return Shape::OuterLeft; case 1963: case 1973: case 1983: case 1993: case 2003: case 2013: case 2023: case 2033: return Shape::OuterRight; default: return Shape::Straight; } } } namespace OakTrapdoor { BlockState OakTrapdoor() { return 4126; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 4144: case 4146: case 4148: case 4150: case 4152: case 4154: case 4156: case 4158: return eBlockFace::BLOCK_FACE_XM; case 4160: case 4162: case 4164: case 4166: case 4168: case 4170: case 4172: case 4174: return eBlockFace::BLOCK_FACE_XP; case 4112: case 4114: case 4116: case 4118: case 4120: case 4122: case 4124: case 4126: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } enum Half Half(const BlockState Block) { switch (Block.ID) { case 4120: case 4122: case 4124: case 4126: case 4136: case 4138: case 4140: case 4142: case 4152: case 4154: case 4156: case 4158: case 4168: case 4170: case 4172: case 4174: return Half::Bottom; default: return Half::Top; } } bool Open(const BlockState Block) { switch (Block.ID) { case 4116: case 4118: case 4124: case 4126: case 4132: case 4134: case 4140: case 4142: case 4148: case 4150: case 4156: case 4158: case 4164: case 4166: case 4172: case 4174: return false; default: return true; } } bool Powered(const BlockState Block) { switch (Block.ID) { case 4114: case 4118: case 4122: case 4126: case 4130: case 4134: case 4138: case 4142: case 4146: case 4150: case 4154: case 4158: case 4162: case 4166: case 4170: case 4174: return false; default: return true; } } } namespace OakWallSign { BlockState OakWallSign() { return 3736; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 3740: return eBlockFace::BLOCK_FACE_XM; case 3742: return eBlockFace::BLOCK_FACE_XP; case 3736: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace OakWood { BlockState OakWood() { return 110; } enum Axis Axis(const BlockState Block) { switch (Block.ID) { case 109: return Axis::X; case 110: return Axis::Y; default: return Axis::Z; } } } namespace Observer { BlockState Observer() { return 9265; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 9266: case 9267: return eBlockFace::BLOCK_FACE_XM; case 9262: case 9263: return eBlockFace::BLOCK_FACE_XP; case 9270: case 9271: return eBlockFace::BLOCK_FACE_YM; case 9268: case 9269: return eBlockFace::BLOCK_FACE_YP; case 9260: case 9261: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } bool Powered(const BlockState Block) { switch (Block.ID) { case 9261: case 9263: case 9265: case 9267: case 9269: case 9271: return false; default: return true; } } } namespace Obsidian { } namespace OrangeBanner { BlockState OrangeBanner() { return 7913; } unsigned char Rotation(const BlockState Block) { switch (Block.ID) { case 7913: return 0; case 7914: return 1; case 7923: return 10; case 7924: return 11; case 7925: return 12; case 7926: return 13; case 7927: return 14; case 7928: return 15; case 7915: return 2; case 7916: return 3; case 7917: return 4; case 7918: return 5; case 7919: return 6; case 7920: return 7; case 7921: return 8; default: return 9; } } } namespace OrangeBed { BlockState OrangeBed() { return 1068; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 1073: case 1074: case 1075: case 1076: return eBlockFace::BLOCK_FACE_XM; case 1077: case 1078: case 1079: case 1080: return eBlockFace::BLOCK_FACE_XP; case 1065: case 1066: case 1067: case 1068: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } bool Occupied(const BlockState Block) { switch (Block.ID) { case 1067: case 1068: case 1071: case 1072: case 1075: case 1076: case 1079: case 1080: return false; default: return true; } } enum Part Part(const BlockState Block) { switch (Block.ID) { case 1066: case 1068: case 1070: case 1072: case 1074: case 1076: case 1078: case 1080: return Part::Foot; default: return Part::Head; } } } namespace OrangeCarpet { } namespace OrangeConcrete { } namespace OrangeConcretePowder { } namespace OrangeGlazedTerracotta { BlockState OrangeGlazedTerracotta() { return 9378; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 9380: return eBlockFace::BLOCK_FACE_XM; case 9381: return eBlockFace::BLOCK_FACE_XP; case 9378: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace OrangeShulkerBox { BlockState OrangeShulkerBox() { return 9288; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 9287: return eBlockFace::BLOCK_FACE_XM; case 9285: return eBlockFace::BLOCK_FACE_XP; case 9289: return eBlockFace::BLOCK_FACE_YM; case 9288: return eBlockFace::BLOCK_FACE_YP; case 9284: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace OrangeStainedGlass { } namespace OrangeStainedGlassPane { BlockState OrangeStainedGlassPane() { return 6926; } bool East(const BlockState Block) { switch (Block.ID) { case 6913: case 6914: case 6917: case 6918: case 6921: case 6922: case 6925: case 6926: return false; default: return true; } } bool North(const BlockState Block) { switch (Block.ID) { case 6905: case 6906: case 6909: case 6910: case 6921: case 6922: case 6925: case 6926: return false; default: return true; } } bool South(const BlockState Block) { switch (Block.ID) { case 6901: case 6902: case 6909: case 6910: case 6917: case 6918: case 6925: case 6926: return false; default: return true; } } bool West(const BlockState Block) { switch (Block.ID) { case 6898: case 6902: case 6906: case 6910: case 6914: case 6918: case 6922: case 6926: return false; default: return true; } } } namespace OrangeTerracotta { } namespace OrangeTulip { } namespace OrangeWallBanner { BlockState OrangeWallBanner() { return 8157; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 8159: return eBlockFace::BLOCK_FACE_XM; case 8160: return eBlockFace::BLOCK_FACE_XP; case 8157: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace OrangeWool { } namespace OxeyeDaisy { } namespace PackedIce { } namespace Peony { BlockState Peony() { return 7892; } enum Half Half(const BlockState Block) { switch (Block.ID) { case 7892: return Half::Lower; default: return Half::Upper; } } } namespace PetrifiedOakSlab { BlockState PetrifiedOakSlab() { return 8363; } enum Type Type(const BlockState Block) { switch (Block.ID) { case 8363: return Type::Bottom; case 8365: return Type::Double; default: return Type::Top; } } } namespace PinkBanner { BlockState PinkBanner() { return 7993; } unsigned char Rotation(const BlockState Block) { switch (Block.ID) { case 7993: return 0; case 7994: return 1; case 8003: return 10; case 8004: return 11; case 8005: return 12; case 8006: return 13; case 8007: return 14; case 8008: return 15; case 7995: return 2; case 7996: return 3; case 7997: return 4; case 7998: return 5; case 7999: return 6; case 8000: return 7; case 8001: return 8; default: return 9; } } } namespace PinkBed { BlockState PinkBed() { return 1148; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 1153: case 1154: case 1155: case 1156: return eBlockFace::BLOCK_FACE_XM; case 1157: case 1158: case 1159: case 1160: return eBlockFace::BLOCK_FACE_XP; case 1145: case 1146: case 1147: case 1148: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } bool Occupied(const BlockState Block) { switch (Block.ID) { case 1147: case 1148: case 1151: case 1152: case 1155: case 1156: case 1159: case 1160: return false; default: return true; } } enum Part Part(const BlockState Block) { switch (Block.ID) { case 1146: case 1148: case 1150: case 1152: case 1154: case 1156: case 1158: case 1160: return Part::Foot; default: return Part::Head; } } } namespace PinkCarpet { } namespace PinkConcrete { } namespace PinkConcretePowder { } namespace PinkGlazedTerracotta { BlockState PinkGlazedTerracotta() { return 9398; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 9400: return eBlockFace::BLOCK_FACE_XM; case 9401: return eBlockFace::BLOCK_FACE_XP; case 9398: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace PinkShulkerBox { BlockState PinkShulkerBox() { return 9318; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 9317: return eBlockFace::BLOCK_FACE_XM; case 9315: return eBlockFace::BLOCK_FACE_XP; case 9319: return eBlockFace::BLOCK_FACE_YM; case 9318: return eBlockFace::BLOCK_FACE_YP; case 9314: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace PinkStainedGlass { } namespace PinkStainedGlassPane { BlockState PinkStainedGlassPane() { return 7086; } bool East(const BlockState Block) { switch (Block.ID) { case 7073: case 7074: case 7077: case 7078: case 7081: case 7082: case 7085: case 7086: return false; default: return true; } } bool North(const BlockState Block) { switch (Block.ID) { case 7065: case 7066: case 7069: case 7070: case 7081: case 7082: case 7085: case 7086: return false; default: return true; } } bool South(const BlockState Block) { switch (Block.ID) { case 7061: case 7062: case 7069: case 7070: case 7077: case 7078: case 7085: case 7086: return false; default: return true; } } bool West(const BlockState Block) { switch (Block.ID) { case 7058: case 7062: case 7066: case 7070: case 7074: case 7078: case 7082: case 7086: return false; default: return true; } } } namespace PinkTerracotta { } namespace PinkTulip { } namespace PinkWallBanner { BlockState PinkWallBanner() { return 8177; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 8179: return eBlockFace::BLOCK_FACE_XM; case 8180: return eBlockFace::BLOCK_FACE_XP; case 8177: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace PinkWool { } namespace Piston { BlockState Piston() { return 1354; } bool Extended(const BlockState Block) { switch (Block.ID) { case 1354: case 1355: case 1356: case 1357: case 1358: case 1359: return false; default: return true; } } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 1351: case 1357: return eBlockFace::BLOCK_FACE_XM; case 1349: case 1355: return eBlockFace::BLOCK_FACE_XP; case 1353: case 1359: return eBlockFace::BLOCK_FACE_YM; case 1352: case 1358: return eBlockFace::BLOCK_FACE_YP; case 1348: case 1354: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace PistonHead { BlockState PistonHead() { return 1362; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 1372: case 1373: case 1374: case 1375: return eBlockFace::BLOCK_FACE_XM; case 1364: case 1365: case 1366: case 1367: return eBlockFace::BLOCK_FACE_XP; case 1380: case 1381: case 1382: case 1383: return eBlockFace::BLOCK_FACE_YM; case 1376: case 1377: case 1378: case 1379: return eBlockFace::BLOCK_FACE_YP; case 1360: case 1361: case 1362: case 1363: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } bool Short(const BlockState Block) { switch (Block.ID) { case 1362: case 1363: case 1366: case 1367: case 1370: case 1371: case 1374: case 1375: case 1378: case 1379: case 1382: case 1383: return false; default: return true; } } enum Type Type(const BlockState Block) { switch (Block.ID) { case 1360: case 1362: case 1364: case 1366: case 1368: case 1370: case 1372: case 1374: case 1376: case 1378: case 1380: case 1382: return Type::Normal; default: return Type::Sticky; } } } namespace PlayerHead { BlockState PlayerHead() { return 6550; } unsigned char Rotation(const BlockState Block) { switch (Block.ID) { case 6550: return 0; case 6551: return 1; case 6560: return 10; case 6561: return 11; case 6562: return 12; case 6563: return 13; case 6564: return 14; case 6565: return 15; case 6552: return 2; case 6553: return 3; case 6554: return 4; case 6555: return 5; case 6556: return 6; case 6557: return 7; case 6558: return 8; default: return 9; } } } namespace PlayerWallHead { BlockState PlayerWallHead() { return 6566; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 6568: return eBlockFace::BLOCK_FACE_XM; case 6569: return eBlockFace::BLOCK_FACE_XP; case 6566: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace Podzol { BlockState Podzol() { return 13; } bool Snowy(const BlockState Block) { switch (Block.ID) { case 13: return false; default: return true; } } } namespace PolishedAndesite { } namespace PolishedAndesiteSlab { BlockState PolishedAndesiteSlab() { return 10858; } enum Type Type(const BlockState Block) { switch (Block.ID) { case 10858: return Type::Bottom; case 10860: return Type::Double; default: return Type::Top; } } } namespace PolishedAndesiteStairs { BlockState PolishedAndesiteStairs() { return 10640; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 10670: case 10672: case 10674: case 10676: case 10678: case 10680: case 10682: case 10684: case 10686: case 10688: return eBlockFace::BLOCK_FACE_XM; case 10690: case 10692: case 10694: case 10696: case 10698: case 10700: case 10702: case 10704: case 10706: case 10708: return eBlockFace::BLOCK_FACE_XP; case 10630: case 10632: case 10634: case 10636: case 10638: case 10640: case 10642: case 10644: case 10646: case 10648: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } enum Half Half(const BlockState Block) { switch (Block.ID) { case 10640: case 10642: case 10644: case 10646: case 10648: case 10660: case 10662: case 10664: case 10666: case 10668: case 10680: case 10682: case 10684: case 10686: case 10688: case 10700: case 10702: case 10704: case 10706: case 10708: return Half::Bottom; default: return Half::Top; } } enum Shape Shape(const BlockState Block) { switch (Block.ID) { case 10632: case 10642: case 10652: case 10662: case 10672: case 10682: case 10692: case 10702: return Shape::InnerLeft; case 10634: case 10644: case 10654: case 10664: case 10674: case 10684: case 10694: case 10704: return Shape::InnerRight; case 10636: case 10646: case 10656: case 10666: case 10676: case 10686: case 10696: case 10706: return Shape::OuterLeft; case 10638: case 10648: case 10658: case 10668: case 10678: case 10688: case 10698: case 10708: return Shape::OuterRight; default: return Shape::Straight; } } } namespace PolishedBasalt { BlockState PolishedBasalt() { return 4006; } enum Axis Axis(const BlockState Block) { switch (Block.ID) { case 4005: return Axis::X; case 4006: return Axis::Y; default: return Axis::Z; } } } namespace PolishedBlackstone { } namespace PolishedBlackstoneBrickSlab { BlockState PolishedBlackstoneBrickSlab() { return 16257; } enum Type Type(const BlockState Block) { switch (Block.ID) { case 16257: return Type::Bottom; case 16259: return Type::Double; default: return Type::Top; } } } namespace PolishedBlackstoneBrickStairs { BlockState PolishedBlackstoneBrickStairs() { return 16271; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 16301: case 16303: case 16305: case 16307: case 16309: case 16311: case 16313: case 16315: case 16317: case 16319: return eBlockFace::BLOCK_FACE_XM; case 16321: case 16323: case 16325: case 16327: case 16329: case 16331: case 16333: case 16335: case 16337: case 16339: return eBlockFace::BLOCK_FACE_XP; case 16261: case 16263: case 16265: case 16267: case 16269: case 16271: case 16273: case 16275: case 16277: case 16279: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } enum Half Half(const BlockState Block) { switch (Block.ID) { case 16271: case 16273: case 16275: case 16277: case 16279: case 16291: case 16293: case 16295: case 16297: case 16299: case 16311: case 16313: case 16315: case 16317: case 16319: case 16331: case 16333: case 16335: case 16337: case 16339: return Half::Bottom; default: return Half::Top; } } enum Shape Shape(const BlockState Block) { switch (Block.ID) { case 16263: case 16273: case 16283: case 16293: case 16303: case 16313: case 16323: case 16333: return Shape::InnerLeft; case 16265: case 16275: case 16285: case 16295: case 16305: case 16315: case 16325: case 16335: return Shape::InnerRight; case 16267: case 16277: case 16287: case 16297: case 16307: case 16317: case 16327: case 16337: return Shape::OuterLeft; case 16269: case 16279: case 16289: case 16299: case 16309: case 16319: case 16329: case 16339: return Shape::OuterRight; default: return Shape::Straight; } } } namespace PolishedBlackstoneBrickWall { BlockState PolishedBlackstoneBrickWall() { return 16343; } enum East East(const BlockState Block) { switch (Block.ID) { case 16451: case 16452: case 16453: case 16457: case 16458: case 16459: case 16463: case 16464: case 16465: case 16469: case 16470: case 16471: case 16475: case 16476: case 16477: case 16481: case 16482: case 16483: case 16487: case 16488: case 16489: case 16493: case 16494: case 16495: case 16499: case 16500: case 16501: case 16505: case 16506: case 16507: case 16511: case 16512: case 16513: case 16517: case 16518: case 16519: case 16523: case 16524: case 16525: case 16529: case 16530: case 16531: case 16535: case 16536: case 16537: case 16541: case 16542: case 16543: case 16547: case 16548: case 16549: case 16553: case 16554: case 16555: return East::Low; case 16343: case 16344: case 16345: case 16349: case 16350: case 16351: case 16355: case 16356: case 16357: case 16361: case 16362: case 16363: case 16367: case 16368: case 16369: case 16373: case 16374: case 16375: case 16379: case 16380: case 16381: case 16385: case 16386: case 16387: case 16391: case 16392: case 16393: case 16397: case 16398: case 16399: case 16403: case 16404: case 16405: case 16409: case 16410: case 16411: case 16415: case 16416: case 16417: case 16421: case 16422: case 16423: case 16427: case 16428: case 16429: case 16433: case 16434: case 16435: case 16439: case 16440: case 16441: case 16445: case 16446: case 16447: return East::None; default: return East::Tall; } } enum North North(const BlockState Block) { switch (Block.ID) { case 16379: case 16380: case 16381: case 16385: case 16386: case 16387: case 16391: case 16392: case 16393: case 16397: case 16398: case 16399: case 16403: case 16404: case 16405: case 16409: case 16410: case 16411: case 16487: case 16488: case 16489: case 16493: case 16494: case 16495: case 16499: case 16500: case 16501: case 16505: case 16506: case 16507: case 16511: case 16512: case 16513: case 16517: case 16518: case 16519: case 16595: case 16596: case 16597: case 16601: case 16602: case 16603: case 16607: case 16608: case 16609: case 16613: case 16614: case 16615: case 16619: case 16620: case 16621: case 16625: case 16626: case 16627: return North::Low; case 16343: case 16344: case 16345: case 16349: case 16350: case 16351: case 16355: case 16356: case 16357: case 16361: case 16362: case 16363: case 16367: case 16368: case 16369: case 16373: case 16374: case 16375: case 16451: case 16452: case 16453: case 16457: case 16458: case 16459: case 16463: case 16464: case 16465: case 16469: case 16470: case 16471: case 16475: case 16476: case 16477: case 16481: case 16482: case 16483: case 16559: case 16560: case 16561: case 16565: case 16566: case 16567: case 16571: case 16572: case 16573: case 16577: case 16578: case 16579: case 16583: case 16584: case 16585: case 16589: case 16590: case 16591: return North::None; default: return North::Tall; } } enum South South(const BlockState Block) { switch (Block.ID) { case 16355: case 16356: case 16357: case 16361: case 16362: case 16363: case 16391: case 16392: case 16393: case 16397: case 16398: case 16399: case 16427: case 16428: case 16429: case 16433: case 16434: case 16435: case 16463: case 16464: case 16465: case 16469: case 16470: case 16471: case 16499: case 16500: case 16501: case 16505: case 16506: case 16507: case 16535: case 16536: case 16537: case 16541: case 16542: case 16543: case 16571: case 16572: case 16573: case 16577: case 16578: case 16579: case 16607: case 16608: case 16609: case 16613: case 16614: case 16615: case 16643: case 16644: case 16645: case 16649: case 16650: case 16651: return South::Low; case 16343: case 16344: case 16345: case 16349: case 16350: case 16351: case 16379: case 16380: case 16381: case 16385: case 16386: case 16387: case 16415: case 16416: case 16417: case 16421: case 16422: case 16423: case 16451: case 16452: case 16453: case 16457: case 16458: case 16459: case 16487: case 16488: case 16489: case 16493: case 16494: case 16495: case 16523: case 16524: case 16525: case 16529: case 16530: case 16531: case 16559: case 16560: case 16561: case 16565: case 16566: case 16567: case 16595: case 16596: case 16597: case 16601: case 16602: case 16603: case 16631: case 16632: case 16633: case 16637: case 16638: case 16639: return South::None; default: return South::Tall; } } bool Up(const BlockState Block) { switch (Block.ID) { case 16349: case 16350: case 16351: case 16361: case 16362: case 16363: case 16373: case 16374: case 16375: case 16385: case 16386: case 16387: case 16397: case 16398: case 16399: case 16409: case 16410: case 16411: case 16421: case 16422: case 16423: case 16433: case 16434: case 16435: case 16445: case 16446: case 16447: case 16457: case 16458: case 16459: case 16469: case 16470: case 16471: case 16481: case 16482: case 16483: case 16493: case 16494: case 16495: case 16505: case 16506: case 16507: case 16517: case 16518: case 16519: case 16529: case 16530: case 16531: case 16541: case 16542: case 16543: case 16553: case 16554: case 16555: case 16565: case 16566: case 16567: case 16577: case 16578: case 16579: case 16589: case 16590: case 16591: case 16601: case 16602: case 16603: case 16613: case 16614: case 16615: case 16625: case 16626: case 16627: case 16637: case 16638: case 16639: case 16649: case 16650: case 16651: case 16661: case 16662: case 16663: return false; default: return true; } } enum West West(const BlockState Block) { switch (Block.ID) { case 16344: case 16350: case 16356: case 16362: case 16368: case 16374: case 16380: case 16386: case 16392: case 16398: case 16404: case 16410: case 16416: case 16422: case 16428: case 16434: case 16440: case 16446: case 16452: case 16458: case 16464: case 16470: case 16476: case 16482: case 16488: case 16494: case 16500: case 16506: case 16512: case 16518: case 16524: case 16530: case 16536: case 16542: case 16548: case 16554: case 16560: case 16566: case 16572: case 16578: case 16584: case 16590: case 16596: case 16602: case 16608: case 16614: case 16620: case 16626: case 16632: case 16638: case 16644: case 16650: case 16656: case 16662: return West::Low; case 16343: case 16349: case 16355: case 16361: case 16367: case 16373: case 16379: case 16385: case 16391: case 16397: case 16403: case 16409: case 16415: case 16421: case 16427: case 16433: case 16439: case 16445: case 16451: case 16457: case 16463: case 16469: case 16475: case 16481: case 16487: case 16493: case 16499: case 16505: case 16511: case 16517: case 16523: case 16529: case 16535: case 16541: case 16547: case 16553: case 16559: case 16565: case 16571: case 16577: case 16583: case 16589: case 16595: case 16601: case 16607: case 16613: case 16619: case 16625: case 16631: case 16637: case 16643: case 16649: case 16655: case 16661: return West::None; default: return West::Tall; } } } namespace PolishedBlackstoneBricks { } namespace PolishedBlackstoneButton { BlockState PolishedBlackstoneButton() { return 16762; } enum Face Face(const BlockState Block) { switch (Block.ID) { case 16769: case 16770: case 16771: case 16772: case 16773: case 16774: case 16775: case 16776: return Face::Ceiling; case 16753: case 16754: case 16755: case 16756: case 16757: case 16758: case 16759: case 16760: return Face::Floor; default: return Face::Wall; } } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 16757: case 16758: case 16765: case 16766: case 16773: case 16774: return eBlockFace::BLOCK_FACE_XM; case 16759: case 16760: case 16767: case 16768: case 16775: case 16776: return eBlockFace::BLOCK_FACE_XP; case 16753: case 16754: case 16761: case 16762: case 16769: case 16770: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } bool Powered(const BlockState Block) { switch (Block.ID) { case 16754: case 16756: case 16758: case 16760: case 16762: case 16764: case 16766: case 16768: case 16770: case 16772: case 16774: case 16776: return false; default: return true; } } } namespace PolishedBlackstonePressurePlate { BlockState PolishedBlackstonePressurePlate() { return 16752; } bool Powered(const BlockState Block) { switch (Block.ID) { case 16752: return false; default: return true; } } } namespace PolishedBlackstoneSlab { BlockState PolishedBlackstoneSlab() { return 16748; } enum Type Type(const BlockState Block) { switch (Block.ID) { case 16748: return Type::Bottom; case 16750: return Type::Double; default: return Type::Top; } } } namespace PolishedBlackstoneStairs { BlockState PolishedBlackstoneStairs() { return 16676; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 16706: case 16708: case 16710: case 16712: case 16714: case 16716: case 16718: case 16720: case 16722: case 16724: return eBlockFace::BLOCK_FACE_XM; case 16726: case 16728: case 16730: case 16732: case 16734: case 16736: case 16738: case 16740: case 16742: case 16744: return eBlockFace::BLOCK_FACE_XP; case 16666: case 16668: case 16670: case 16672: case 16674: case 16676: case 16678: case 16680: case 16682: case 16684: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } enum Half Half(const BlockState Block) { switch (Block.ID) { case 16676: case 16678: case 16680: case 16682: case 16684: case 16696: case 16698: case 16700: case 16702: case 16704: case 16716: case 16718: case 16720: case 16722: case 16724: case 16736: case 16738: case 16740: case 16742: case 16744: return Half::Bottom; default: return Half::Top; } } enum Shape Shape(const BlockState Block) { switch (Block.ID) { case 16668: case 16678: case 16688: case 16698: case 16708: case 16718: case 16728: case 16738: return Shape::InnerLeft; case 16670: case 16680: case 16690: case 16700: case 16710: case 16720: case 16730: case 16740: return Shape::InnerRight; case 16672: case 16682: case 16692: case 16702: case 16712: case 16722: case 16732: case 16742: return Shape::OuterLeft; case 16674: case 16684: case 16694: case 16704: case 16714: case 16724: case 16734: case 16744: return Shape::OuterRight; default: return Shape::Straight; } } } namespace PolishedBlackstoneWall { BlockState PolishedBlackstoneWall() { return 16780; } enum East East(const BlockState Block) { switch (Block.ID) { case 16888: case 16889: case 16890: case 16894: case 16895: case 16896: case 16900: case 16901: case 16902: case 16906: case 16907: case 16908: case 16912: case 16913: case 16914: case 16918: case 16919: case 16920: case 16924: case 16925: case 16926: case 16930: case 16931: case 16932: case 16936: case 16937: case 16938: case 16942: case 16943: case 16944: case 16948: case 16949: case 16950: case 16954: case 16955: case 16956: case 16960: case 16961: case 16962: case 16966: case 16967: case 16968: case 16972: case 16973: case 16974: case 16978: case 16979: case 16980: case 16984: case 16985: case 16986: case 16990: case 16991: case 16992: return East::Low; case 16780: case 16781: case 16782: case 16786: case 16787: case 16788: case 16792: case 16793: case 16794: case 16798: case 16799: case 16800: case 16804: case 16805: case 16806: case 16810: case 16811: case 16812: case 16816: case 16817: case 16818: case 16822: case 16823: case 16824: case 16828: case 16829: case 16830: case 16834: case 16835: case 16836: case 16840: case 16841: case 16842: case 16846: case 16847: case 16848: case 16852: case 16853: case 16854: case 16858: case 16859: case 16860: case 16864: case 16865: case 16866: case 16870: case 16871: case 16872: case 16876: case 16877: case 16878: case 16882: case 16883: case 16884: return East::None; default: return East::Tall; } } enum North North(const BlockState Block) { switch (Block.ID) { case 16816: case 16817: case 16818: case 16822: case 16823: case 16824: case 16828: case 16829: case 16830: case 16834: case 16835: case 16836: case 16840: case 16841: case 16842: case 16846: case 16847: case 16848: case 16924: case 16925: case 16926: case 16930: case 16931: case 16932: case 16936: case 16937: case 16938: case 16942: case 16943: case 16944: case 16948: case 16949: case 16950: case 16954: case 16955: case 16956: case 17032: case 17033: case 17034: case 17038: case 17039: case 17040: case 17044: case 17045: case 17046: case 17050: case 17051: case 17052: case 17056: case 17057: case 17058: case 17062: case 17063: case 17064: return North::Low; case 16780: case 16781: case 16782: case 16786: case 16787: case 16788: case 16792: case 16793: case 16794: case 16798: case 16799: case 16800: case 16804: case 16805: case 16806: case 16810: case 16811: case 16812: case 16888: case 16889: case 16890: case 16894: case 16895: case 16896: case 16900: case 16901: case 16902: case 16906: case 16907: case 16908: case 16912: case 16913: case 16914: case 16918: case 16919: case 16920: case 16996: case 16997: case 16998: case 17002: case 17003: case 17004: case 17008: case 17009: case 17010: case 17014: case 17015: case 17016: case 17020: case 17021: case 17022: case 17026: case 17027: case 17028: return North::None; default: return North::Tall; } } enum South South(const BlockState Block) { switch (Block.ID) { case 16792: case 16793: case 16794: case 16798: case 16799: case 16800: case 16828: case 16829: case 16830: case 16834: case 16835: case 16836: case 16864: case 16865: case 16866: case 16870: case 16871: case 16872: case 16900: case 16901: case 16902: case 16906: case 16907: case 16908: case 16936: case 16937: case 16938: case 16942: case 16943: case 16944: case 16972: case 16973: case 16974: case 16978: case 16979: case 16980: case 17008: case 17009: case 17010: case 17014: case 17015: case 17016: case 17044: case 17045: case 17046: case 17050: case 17051: case 17052: case 17080: case 17081: case 17082: case 17086: case 17087: case 17088: return South::Low; case 16780: case 16781: case 16782: case 16786: case 16787: case 16788: case 16816: case 16817: case 16818: case 16822: case 16823: case 16824: case 16852: case 16853: case 16854: case 16858: case 16859: case 16860: case 16888: case 16889: case 16890: case 16894: case 16895: case 16896: case 16924: case 16925: case 16926: case 16930: case 16931: case 16932: case 16960: case 16961: case 16962: case 16966: case 16967: case 16968: case 16996: case 16997: case 16998: case 17002: case 17003: case 17004: case 17032: case 17033: case 17034: case 17038: case 17039: case 17040: case 17068: case 17069: case 17070: case 17074: case 17075: case 17076: return South::None; default: return South::Tall; } } bool Up(const BlockState Block) { switch (Block.ID) { case 16786: case 16787: case 16788: case 16798: case 16799: case 16800: case 16810: case 16811: case 16812: case 16822: case 16823: case 16824: case 16834: case 16835: case 16836: case 16846: case 16847: case 16848: case 16858: case 16859: case 16860: case 16870: case 16871: case 16872: case 16882: case 16883: case 16884: case 16894: case 16895: case 16896: case 16906: case 16907: case 16908: case 16918: case 16919: case 16920: case 16930: case 16931: case 16932: case 16942: case 16943: case 16944: case 16954: case 16955: case 16956: case 16966: case 16967: case 16968: case 16978: case 16979: case 16980: case 16990: case 16991: case 16992: case 17002: case 17003: case 17004: case 17014: case 17015: case 17016: case 17026: case 17027: case 17028: case 17038: case 17039: case 17040: case 17050: case 17051: case 17052: case 17062: case 17063: case 17064: case 17074: case 17075: case 17076: case 17086: case 17087: case 17088: case 17098: case 17099: case 17100: return false; default: return true; } } enum West West(const BlockState Block) { switch (Block.ID) { case 16781: case 16787: case 16793: case 16799: case 16805: case 16811: case 16817: case 16823: case 16829: case 16835: case 16841: case 16847: case 16853: case 16859: case 16865: case 16871: case 16877: case 16883: case 16889: case 16895: case 16901: case 16907: case 16913: case 16919: case 16925: case 16931: case 16937: case 16943: case 16949: case 16955: case 16961: case 16967: case 16973: case 16979: case 16985: case 16991: case 16997: case 17003: case 17009: case 17015: case 17021: case 17027: case 17033: case 17039: case 17045: case 17051: case 17057: case 17063: case 17069: case 17075: case 17081: case 17087: case 17093: case 17099: return West::Low; case 16780: case 16786: case 16792: case 16798: case 16804: case 16810: case 16816: case 16822: case 16828: case 16834: case 16840: case 16846: case 16852: case 16858: case 16864: case 16870: case 16876: case 16882: case 16888: case 16894: case 16900: case 16906: case 16912: case 16918: case 16924: case 16930: case 16936: case 16942: case 16948: case 16954: case 16960: case 16966: case 16972: case 16978: case 16984: case 16990: case 16996: case 17002: case 17008: case 17014: case 17020: case 17026: case 17032: case 17038: case 17044: case 17050: case 17056: case 17062: case 17068: case 17074: case 17080: case 17086: case 17092: case 17098: return West::None; default: return West::Tall; } } } namespace PolishedDiorite { } namespace PolishedDioriteSlab { BlockState PolishedDioriteSlab() { return 10810; } enum Type Type(const BlockState Block) { switch (Block.ID) { case 10810: return Type::Bottom; case 10812: return Type::Double; default: return Type::Top; } } } namespace PolishedDioriteStairs { BlockState PolishedDioriteStairs() { return 9920; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 9950: case 9952: case 9954: case 9956: case 9958: case 9960: case 9962: case 9964: case 9966: case 9968: return eBlockFace::BLOCK_FACE_XM; case 9970: case 9972: case 9974: case 9976: case 9978: case 9980: case 9982: case 9984: case 9986: case 9988: return eBlockFace::BLOCK_FACE_XP; case 9910: case 9912: case 9914: case 9916: case 9918: case 9920: case 9922: case 9924: case 9926: case 9928: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } enum Half Half(const BlockState Block) { switch (Block.ID) { case 9920: case 9922: case 9924: case 9926: case 9928: case 9940: case 9942: case 9944: case 9946: case 9948: case 9960: case 9962: case 9964: case 9966: case 9968: case 9980: case 9982: case 9984: case 9986: case 9988: return Half::Bottom; default: return Half::Top; } } enum Shape Shape(const BlockState Block) { switch (Block.ID) { case 9912: case 9922: case 9932: case 9942: case 9952: case 9962: case 9972: case 9982: return Shape::InnerLeft; case 9914: case 9924: case 9934: case 9944: case 9954: case 9964: case 9974: case 9984: return Shape::InnerRight; case 9916: case 9926: case 9936: case 9946: case 9956: case 9966: case 9976: case 9986: return Shape::OuterLeft; case 9918: case 9928: case 9938: case 9948: case 9958: case 9968: case 9978: case 9988: return Shape::OuterRight; default: return Shape::Straight; } } } namespace PolishedGranite { } namespace PolishedGraniteSlab { BlockState PolishedGraniteSlab() { return 10792; } enum Type Type(const BlockState Block) { switch (Block.ID) { case 10792: return Type::Bottom; case 10794: return Type::Double; default: return Type::Top; } } } namespace PolishedGraniteStairs { BlockState PolishedGraniteStairs() { return 9680; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 9710: case 9712: case 9714: case 9716: case 9718: case 9720: case 9722: case 9724: case 9726: case 9728: return eBlockFace::BLOCK_FACE_XM; case 9730: case 9732: case 9734: case 9736: case 9738: case 9740: case 9742: case 9744: case 9746: case 9748: return eBlockFace::BLOCK_FACE_XP; case 9670: case 9672: case 9674: case 9676: case 9678: case 9680: case 9682: case 9684: case 9686: case 9688: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } enum Half Half(const BlockState Block) { switch (Block.ID) { case 9680: case 9682: case 9684: case 9686: case 9688: case 9700: case 9702: case 9704: case 9706: case 9708: case 9720: case 9722: case 9724: case 9726: case 9728: case 9740: case 9742: case 9744: case 9746: case 9748: return Half::Bottom; default: return Half::Top; } } enum Shape Shape(const BlockState Block) { switch (Block.ID) { case 9672: case 9682: case 9692: case 9702: case 9712: case 9722: case 9732: case 9742: return Shape::InnerLeft; case 9674: case 9684: case 9694: case 9704: case 9714: case 9724: case 9734: case 9744: return Shape::InnerRight; case 9676: case 9686: case 9696: case 9706: case 9716: case 9726: case 9736: case 9746: return Shape::OuterLeft; case 9678: case 9688: case 9698: case 9708: case 9718: case 9728: case 9738: case 9748: return Shape::OuterRight; default: return Shape::Straight; } } } namespace Poppy { } namespace Potatoes { BlockState Potatoes() { return 6338; } unsigned char Age(const BlockState Block) { switch (Block.ID) { case 6338: return 0; case 6339: return 1; case 6340: return 2; case 6341: return 3; case 6342: return 4; case 6343: return 5; case 6344: return 6; default: return 7; } } } namespace PottedAcaciaSapling { } namespace PottedAllium { } namespace PottedAzureBluet { } namespace PottedBamboo { } namespace PottedBirchSapling { } namespace PottedBlueOrchid { } namespace PottedBrownMushroom { } namespace PottedCactus { } namespace PottedCornflower { } namespace PottedCrimsonFungus { } namespace PottedCrimsonRoots { } namespace PottedDandelion { } namespace PottedDarkOakSapling { } namespace PottedDeadBush { } namespace PottedFern { } namespace PottedJungleSapling { } namespace PottedLilyOfTheValley { } namespace PottedOakSapling { } namespace PottedOrangeTulip { } namespace PottedOxeyeDaisy { } namespace PottedPinkTulip { } namespace PottedPoppy { } namespace PottedRedMushroom { } namespace PottedRedTulip { } namespace PottedSpruceSapling { } namespace PottedWarpedFungus { } namespace PottedWarpedRoots { } namespace PottedWhiteTulip { } namespace PottedWitherRose { } namespace PoweredRail { BlockState PoweredRail() { return 1311; } bool Powered(const BlockState Block) { switch (Block.ID) { case 1311: case 1312: case 1313: case 1314: case 1315: case 1316: return false; default: return true; } } enum Shape Shape(const BlockState Block) { switch (Block.ID) { case 1307: case 1313: return Shape::AscendingEast; case 1309: case 1315: return Shape::AscendingNorth; case 1310: case 1316: return Shape::AscendingSouth; case 1308: case 1314: return Shape::AscendingWest; case 1306: case 1312: return Shape::EastWest; default: return Shape::NorthSouth; } } } namespace Prismarine { } namespace PrismarineBrickSlab { BlockState PrismarineBrickSlab() { return 7853; } enum Type Type(const BlockState Block) { switch (Block.ID) { case 7853: return Type::Bottom; case 7855: return Type::Double; default: return Type::Top; } } } namespace PrismarineBrickStairs { BlockState PrismarineBrickStairs() { return 7695; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 7725: case 7727: case 7729: case 7731: case 7733: case 7735: case 7737: case 7739: case 7741: case 7743: return eBlockFace::BLOCK_FACE_XM; case 7745: case 7747: case 7749: case 7751: case 7753: case 7755: case 7757: case 7759: case 7761: case 7763: return eBlockFace::BLOCK_FACE_XP; case 7685: case 7687: case 7689: case 7691: case 7693: case 7695: case 7697: case 7699: case 7701: case 7703: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } enum Half Half(const BlockState Block) { switch (Block.ID) { case 7695: case 7697: case 7699: case 7701: case 7703: case 7715: case 7717: case 7719: case 7721: case 7723: case 7735: case 7737: case 7739: case 7741: case 7743: case 7755: case 7757: case 7759: case 7761: case 7763: return Half::Bottom; default: return Half::Top; } } enum Shape Shape(const BlockState Block) { switch (Block.ID) { case 7687: case 7697: case 7707: case 7717: case 7727: case 7737: case 7747: case 7757: return Shape::InnerLeft; case 7689: case 7699: case 7709: case 7719: case 7729: case 7739: case 7749: case 7759: return Shape::InnerRight; case 7691: case 7701: case 7711: case 7721: case 7731: case 7741: case 7751: case 7761: return Shape::OuterLeft; case 7693: case 7703: case 7713: case 7723: case 7733: case 7743: case 7753: case 7763: return Shape::OuterRight; default: return Shape::Straight; } } } namespace PrismarineBricks { } namespace PrismarineSlab { BlockState PrismarineSlab() { return 7847; } enum Type Type(const BlockState Block) { switch (Block.ID) { case 7847: return Type::Bottom; case 7849: return Type::Double; default: return Type::Top; } } } namespace PrismarineStairs { BlockState PrismarineStairs() { return 7615; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 7645: case 7647: case 7649: case 7651: case 7653: case 7655: case 7657: case 7659: case 7661: case 7663: return eBlockFace::BLOCK_FACE_XM; case 7665: case 7667: case 7669: case 7671: case 7673: case 7675: case 7677: case 7679: case 7681: case 7683: return eBlockFace::BLOCK_FACE_XP; case 7605: case 7607: case 7609: case 7611: case 7613: case 7615: case 7617: case 7619: case 7621: case 7623: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } enum Half Half(const BlockState Block) { switch (Block.ID) { case 7615: case 7617: case 7619: case 7621: case 7623: case 7635: case 7637: case 7639: case 7641: case 7643: case 7655: case 7657: case 7659: case 7661: case 7663: case 7675: case 7677: case 7679: case 7681: case 7683: return Half::Bottom; default: return Half::Top; } } enum Shape Shape(const BlockState Block) { switch (Block.ID) { case 7607: case 7617: case 7627: case 7637: case 7647: case 7657: case 7667: case 7677: return Shape::InnerLeft; case 7609: case 7619: case 7629: case 7639: case 7649: case 7659: case 7669: case 7679: return Shape::InnerRight; case 7611: case 7621: case 7631: case 7641: case 7651: case 7661: case 7671: case 7681: return Shape::OuterLeft; case 7613: case 7623: case 7633: case 7643: case 7653: case 7663: case 7673: case 7683: return Shape::OuterRight; default: return Shape::Straight; } } } namespace PrismarineWall { BlockState PrismarineWall() { return 11194; } enum East East(const BlockState Block) { switch (Block.ID) { case 11302: case 11303: case 11304: case 11308: case 11309: case 11310: case 11314: case 11315: case 11316: case 11320: case 11321: case 11322: case 11326: case 11327: case 11328: case 11332: case 11333: case 11334: case 11338: case 11339: case 11340: case 11344: case 11345: case 11346: case 11350: case 11351: case 11352: case 11356: case 11357: case 11358: case 11362: case 11363: case 11364: case 11368: case 11369: case 11370: case 11374: case 11375: case 11376: case 11380: case 11381: case 11382: case 11386: case 11387: case 11388: case 11392: case 11393: case 11394: case 11398: case 11399: case 11400: case 11404: case 11405: case 11406: return East::Low; case 11194: case 11195: case 11196: case 11200: case 11201: case 11202: case 11206: case 11207: case 11208: case 11212: case 11213: case 11214: case 11218: case 11219: case 11220: case 11224: case 11225: case 11226: case 11230: case 11231: case 11232: case 11236: case 11237: case 11238: case 11242: case 11243: case 11244: case 11248: case 11249: case 11250: case 11254: case 11255: case 11256: case 11260: case 11261: case 11262: case 11266: case 11267: case 11268: case 11272: case 11273: case 11274: case 11278: case 11279: case 11280: case 11284: case 11285: case 11286: case 11290: case 11291: case 11292: case 11296: case 11297: case 11298: return East::None; default: return East::Tall; } } enum North North(const BlockState Block) { switch (Block.ID) { case 11230: case 11231: case 11232: case 11236: case 11237: case 11238: case 11242: case 11243: case 11244: case 11248: case 11249: case 11250: case 11254: case 11255: case 11256: case 11260: case 11261: case 11262: case 11338: case 11339: case 11340: case 11344: case 11345: case 11346: case 11350: case 11351: case 11352: case 11356: case 11357: case 11358: case 11362: case 11363: case 11364: case 11368: case 11369: case 11370: case 11446: case 11447: case 11448: case 11452: case 11453: case 11454: case 11458: case 11459: case 11460: case 11464: case 11465: case 11466: case 11470: case 11471: case 11472: case 11476: case 11477: case 11478: return North::Low; case 11194: case 11195: case 11196: case 11200: case 11201: case 11202: case 11206: case 11207: case 11208: case 11212: case 11213: case 11214: case 11218: case 11219: case 11220: case 11224: case 11225: case 11226: case 11302: case 11303: case 11304: case 11308: case 11309: case 11310: case 11314: case 11315: case 11316: case 11320: case 11321: case 11322: case 11326: case 11327: case 11328: case 11332: case 11333: case 11334: case 11410: case 11411: case 11412: case 11416: case 11417: case 11418: case 11422: case 11423: case 11424: case 11428: case 11429: case 11430: case 11434: case 11435: case 11436: case 11440: case 11441: case 11442: return North::None; default: return North::Tall; } } enum South South(const BlockState Block) { switch (Block.ID) { case 11206: case 11207: case 11208: case 11212: case 11213: case 11214: case 11242: case 11243: case 11244: case 11248: case 11249: case 11250: case 11278: case 11279: case 11280: case 11284: case 11285: case 11286: case 11314: case 11315: case 11316: case 11320: case 11321: case 11322: case 11350: case 11351: case 11352: case 11356: case 11357: case 11358: case 11386: case 11387: case 11388: case 11392: case 11393: case 11394: case 11422: case 11423: case 11424: case 11428: case 11429: case 11430: case 11458: case 11459: case 11460: case 11464: case 11465: case 11466: case 11494: case 11495: case 11496: case 11500: case 11501: case 11502: return South::Low; case 11194: case 11195: case 11196: case 11200: case 11201: case 11202: case 11230: case 11231: case 11232: case 11236: case 11237: case 11238: case 11266: case 11267: case 11268: case 11272: case 11273: case 11274: case 11302: case 11303: case 11304: case 11308: case 11309: case 11310: case 11338: case 11339: case 11340: case 11344: case 11345: case 11346: case 11374: case 11375: case 11376: case 11380: case 11381: case 11382: case 11410: case 11411: case 11412: case 11416: case 11417: case 11418: case 11446: case 11447: case 11448: case 11452: case 11453: case 11454: case 11482: case 11483: case 11484: case 11488: case 11489: case 11490: return South::None; default: return South::Tall; } } bool Up(const BlockState Block) { switch (Block.ID) { case 11200: case 11201: case 11202: case 11212: case 11213: case 11214: case 11224: case 11225: case 11226: case 11236: case 11237: case 11238: case 11248: case 11249: case 11250: case 11260: case 11261: case 11262: case 11272: case 11273: case 11274: case 11284: case 11285: case 11286: case 11296: case 11297: case 11298: case 11308: case 11309: case 11310: case 11320: case 11321: case 11322: case 11332: case 11333: case 11334: case 11344: case 11345: case 11346: case 11356: case 11357: case 11358: case 11368: case 11369: case 11370: case 11380: case 11381: case 11382: case 11392: case 11393: case 11394: case 11404: case 11405: case 11406: case 11416: case 11417: case 11418: case 11428: case 11429: case 11430: case 11440: case 11441: case 11442: case 11452: case 11453: case 11454: case 11464: case 11465: case 11466: case 11476: case 11477: case 11478: case 11488: case 11489: case 11490: case 11500: case 11501: case 11502: case 11512: case 11513: case 11514: return false; default: return true; } } enum West West(const BlockState Block) { switch (Block.ID) { case 11195: case 11201: case 11207: case 11213: case 11219: case 11225: case 11231: case 11237: case 11243: case 11249: case 11255: case 11261: case 11267: case 11273: case 11279: case 11285: case 11291: case 11297: case 11303: case 11309: case 11315: case 11321: case 11327: case 11333: case 11339: case 11345: case 11351: case 11357: case 11363: case 11369: case 11375: case 11381: case 11387: case 11393: case 11399: case 11405: case 11411: case 11417: case 11423: case 11429: case 11435: case 11441: case 11447: case 11453: case 11459: case 11465: case 11471: case 11477: case 11483: case 11489: case 11495: case 11501: case 11507: case 11513: return West::Low; case 11194: case 11200: case 11206: case 11212: case 11218: case 11224: case 11230: case 11236: case 11242: case 11248: case 11254: case 11260: case 11266: case 11272: case 11278: case 11284: case 11290: case 11296: case 11302: case 11308: case 11314: case 11320: case 11326: case 11332: case 11338: case 11344: case 11350: case 11356: case 11362: case 11368: case 11374: case 11380: case 11386: case 11392: case 11398: case 11404: case 11410: case 11416: case 11422: case 11428: case 11434: case 11440: case 11446: case 11452: case 11458: case 11464: case 11470: case 11476: case 11482: case 11488: case 11494: case 11500: case 11506: case 11512: return West::None; default: return West::Tall; } } } namespace Pumpkin { } namespace PumpkinStem { BlockState PumpkinStem() { return 4772; } unsigned char Age(const BlockState Block) { switch (Block.ID) { case 4772: return 0; case 4773: return 1; case 4774: return 2; case 4775: return 3; case 4776: return 4; case 4777: return 5; case 4778: return 6; default: return 7; } } } namespace PurpleBanner { BlockState PurpleBanner() { return 8057; } unsigned char Rotation(const BlockState Block) { switch (Block.ID) { case 8057: return 0; case 8058: return 1; case 8067: return 10; case 8068: return 11; case 8069: return 12; case 8070: return 13; case 8071: return 14; case 8072: return 15; case 8059: return 2; case 8060: return 3; case 8061: return 4; case 8062: return 5; case 8063: return 6; case 8064: return 7; case 8065: return 8; default: return 9; } } } namespace PurpleBed { BlockState PurpleBed() { return 1212; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 1217: case 1218: case 1219: case 1220: return eBlockFace::BLOCK_FACE_XM; case 1221: case 1222: case 1223: case 1224: return eBlockFace::BLOCK_FACE_XP; case 1209: case 1210: case 1211: case 1212: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } bool Occupied(const BlockState Block) { switch (Block.ID) { case 1211: case 1212: case 1215: case 1216: case 1219: case 1220: case 1223: case 1224: return false; default: return true; } } enum Part Part(const BlockState Block) { switch (Block.ID) { case 1210: case 1212: case 1214: case 1216: case 1218: case 1220: case 1222: case 1224: return Part::Foot; default: return Part::Head; } } } namespace PurpleCarpet { } namespace PurpleConcrete { } namespace PurpleConcretePowder { } namespace PurpleGlazedTerracotta { BlockState PurpleGlazedTerracotta() { return 9414; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 9416: return eBlockFace::BLOCK_FACE_XM; case 9417: return eBlockFace::BLOCK_FACE_XP; case 9414: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace PurpleShulkerBox { BlockState PurpleShulkerBox() { return 9342; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 9341: return eBlockFace::BLOCK_FACE_XM; case 9339: return eBlockFace::BLOCK_FACE_XP; case 9343: return eBlockFace::BLOCK_FACE_YM; case 9342: return eBlockFace::BLOCK_FACE_YP; case 9338: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace PurpleStainedGlass { } namespace PurpleStainedGlassPane { BlockState PurpleStainedGlassPane() { return 7214; } bool East(const BlockState Block) { switch (Block.ID) { case 7201: case 7202: case 7205: case 7206: case 7209: case 7210: case 7213: case 7214: return false; default: return true; } } bool North(const BlockState Block) { switch (Block.ID) { case 7193: case 7194: case 7197: case 7198: case 7209: case 7210: case 7213: case 7214: return false; default: return true; } } bool South(const BlockState Block) { switch (Block.ID) { case 7189: case 7190: case 7197: case 7198: case 7205: case 7206: case 7213: case 7214: return false; default: return true; } } bool West(const BlockState Block) { switch (Block.ID) { case 7186: case 7190: case 7194: case 7198: case 7202: case 7206: case 7210: case 7214: return false; default: return true; } } } namespace PurpleTerracotta { } namespace PurpleWallBanner { BlockState PurpleWallBanner() { return 8193; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 8195: return eBlockFace::BLOCK_FACE_XM; case 8196: return eBlockFace::BLOCK_FACE_XP; case 8193: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace PurpleWool { } namespace PurpurBlock { } namespace PurpurPillar { BlockState PurpurPillar() { return 9136; } enum Axis Axis(const BlockState Block) { switch (Block.ID) { case 9135: return Axis::X; case 9136: return Axis::Y; default: return Axis::Z; } } } namespace PurpurSlab { BlockState PurpurSlab() { return 8411; } enum Type Type(const BlockState Block) { switch (Block.ID) { case 8411: return Type::Bottom; case 8413: return Type::Double; default: return Type::Top; } } } namespace PurpurStairs { BlockState PurpurStairs() { return 9149; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 9179: case 9181: case 9183: case 9185: case 9187: case 9189: case 9191: case 9193: case 9195: case 9197: return eBlockFace::BLOCK_FACE_XM; case 9199: case 9201: case 9203: case 9205: case 9207: case 9209: case 9211: case 9213: case 9215: case 9217: return eBlockFace::BLOCK_FACE_XP; case 9139: case 9141: case 9143: case 9145: case 9147: case 9149: case 9151: case 9153: case 9155: case 9157: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } enum Half Half(const BlockState Block) { switch (Block.ID) { case 9149: case 9151: case 9153: case 9155: case 9157: case 9169: case 9171: case 9173: case 9175: case 9177: case 9189: case 9191: case 9193: case 9195: case 9197: case 9209: case 9211: case 9213: case 9215: case 9217: return Half::Bottom; default: return Half::Top; } } enum Shape Shape(const BlockState Block) { switch (Block.ID) { case 9141: case 9151: case 9161: case 9171: case 9181: case 9191: case 9201: case 9211: return Shape::InnerLeft; case 9143: case 9153: case 9163: case 9173: case 9183: case 9193: case 9203: case 9213: return Shape::InnerRight; case 9145: case 9155: case 9165: case 9175: case 9185: case 9195: case 9205: case 9215: return Shape::OuterLeft; case 9147: case 9157: case 9167: case 9177: case 9187: case 9197: case 9207: case 9217: return Shape::OuterRight; default: return Shape::Straight; } } } namespace QuartzBlock { } namespace QuartzBricks { } namespace QuartzPillar { BlockState QuartzPillar() { return 6741; } enum Axis Axis(const BlockState Block) { switch (Block.ID) { case 6740: return Axis::X; case 6741: return Axis::Y; default: return Axis::Z; } } } namespace QuartzSlab { BlockState QuartzSlab() { return 8393; } enum Type Type(const BlockState Block) { switch (Block.ID) { case 8393: return Type::Bottom; case 8395: return Type::Double; default: return Type::Top; } } } namespace QuartzStairs { BlockState QuartzStairs() { return 6754; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 6784: case 6786: case 6788: case 6790: case 6792: case 6794: case 6796: case 6798: case 6800: case 6802: return eBlockFace::BLOCK_FACE_XM; case 6804: case 6806: case 6808: case 6810: case 6812: case 6814: case 6816: case 6818: case 6820: case 6822: return eBlockFace::BLOCK_FACE_XP; case 6744: case 6746: case 6748: case 6750: case 6752: case 6754: case 6756: case 6758: case 6760: case 6762: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } enum Half Half(const BlockState Block) { switch (Block.ID) { case 6754: case 6756: case 6758: case 6760: case 6762: case 6774: case 6776: case 6778: case 6780: case 6782: case 6794: case 6796: case 6798: case 6800: case 6802: case 6814: case 6816: case 6818: case 6820: case 6822: return Half::Bottom; default: return Half::Top; } } enum Shape Shape(const BlockState Block) { switch (Block.ID) { case 6746: case 6756: case 6766: case 6776: case 6786: case 6796: case 6806: case 6816: return Shape::InnerLeft; case 6748: case 6758: case 6768: case 6778: case 6788: case 6798: case 6808: case 6818: return Shape::InnerRight; case 6750: case 6760: case 6770: case 6780: case 6790: case 6800: case 6810: case 6820: return Shape::OuterLeft; case 6752: case 6762: case 6772: case 6782: case 6792: case 6802: case 6812: case 6822: return Shape::OuterRight; default: return Shape::Straight; } } } namespace Rail { BlockState Rail() { return 3645; } enum Shape Shape(const BlockState Block) { switch (Block.ID) { case 3647: return Shape::AscendingEast; case 3649: return Shape::AscendingNorth; case 3650: return Shape::AscendingSouth; case 3648: return Shape::AscendingWest; case 3646: return Shape::EastWest; case 3654: return Shape::NorthEast; case 3645: return Shape::NorthSouth; case 3653: return Shape::NorthWest; case 3651: return Shape::SouthEast; default: return Shape::SouthWest; } } } namespace RedBanner { BlockState RedBanner() { return 8121; } unsigned char Rotation(const BlockState Block) { switch (Block.ID) { case 8121: return 0; case 8122: return 1; case 8131: return 10; case 8132: return 11; case 8133: return 12; case 8134: return 13; case 8135: return 14; case 8136: return 15; case 8123: return 2; case 8124: return 3; case 8125: return 4; case 8126: return 5; case 8127: return 6; case 8128: return 7; case 8129: return 8; default: return 9; } } } namespace RedBed { BlockState RedBed() { return 1276; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 1281: case 1282: case 1283: case 1284: return eBlockFace::BLOCK_FACE_XM; case 1285: case 1286: case 1287: case 1288: return eBlockFace::BLOCK_FACE_XP; case 1273: case 1274: case 1275: case 1276: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } bool Occupied(const BlockState Block) { switch (Block.ID) { case 1275: case 1276: case 1279: case 1280: case 1283: case 1284: case 1287: case 1288: return false; default: return true; } } enum Part Part(const BlockState Block) { switch (Block.ID) { case 1274: case 1276: case 1278: case 1280: case 1282: case 1284: case 1286: case 1288: return Part::Foot; default: return Part::Head; } } } namespace RedCarpet { } namespace RedConcrete { } namespace RedConcretePowder { } namespace RedGlazedTerracotta { BlockState RedGlazedTerracotta() { return 9430; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 9432: return eBlockFace::BLOCK_FACE_XM; case 9433: return eBlockFace::BLOCK_FACE_XP; case 9430: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace RedMushroom { } namespace RedMushroomBlock { BlockState RedMushroomBlock() { return 4569; } bool Down(const BlockState Block) { switch (Block.ID) { case 4601: case 4602: case 4603: case 4604: case 4605: case 4606: case 4607: case 4608: case 4609: case 4610: case 4611: case 4612: case 4613: case 4614: case 4615: case 4616: case 4617: case 4618: case 4619: case 4620: case 4621: case 4622: case 4623: case 4624: case 4625: case 4626: case 4627: case 4628: case 4629: case 4630: case 4631: case 4632: return false; default: return true; } } bool East(const BlockState Block) { switch (Block.ID) { case 4585: case 4586: case 4587: case 4588: case 4589: case 4590: case 4591: case 4592: case 4593: case 4594: case 4595: case 4596: case 4597: case 4598: case 4599: case 4600: case 4617: case 4618: case 4619: case 4620: case 4621: case 4622: case 4623: case 4624: case 4625: case 4626: case 4627: case 4628: case 4629: case 4630: case 4631: case 4632: return false; default: return true; } } bool North(const BlockState Block) { switch (Block.ID) { case 4577: case 4578: case 4579: case 4580: case 4581: case 4582: case 4583: case 4584: case 4593: case 4594: case 4595: case 4596: case 4597: case 4598: case 4599: case 4600: case 4609: case 4610: case 4611: case 4612: case 4613: case 4614: case 4615: case 4616: case 4625: case 4626: case 4627: case 4628: case 4629: case 4630: case 4631: case 4632: return false; default: return true; } } bool South(const BlockState Block) { switch (Block.ID) { case 4573: case 4574: case 4575: case 4576: case 4581: case 4582: case 4583: case 4584: case 4589: case 4590: case 4591: case 4592: case 4597: case 4598: case 4599: case 4600: case 4605: case 4606: case 4607: case 4608: case 4613: case 4614: case 4615: case 4616: case 4621: case 4622: case 4623: case 4624: case 4629: case 4630: case 4631: case 4632: return false; default: return true; } } bool Up(const BlockState Block) { switch (Block.ID) { case 4571: case 4572: case 4575: case 4576: case 4579: case 4580: case 4583: case 4584: case 4587: case 4588: case 4591: case 4592: case 4595: case 4596: case 4599: case 4600: case 4603: case 4604: case 4607: case 4608: case 4611: case 4612: case 4615: case 4616: case 4619: case 4620: case 4623: case 4624: case 4627: case 4628: case 4631: case 4632: return false; default: return true; } } bool West(const BlockState Block) { switch (Block.ID) { case 4570: case 4572: case 4574: case 4576: case 4578: case 4580: case 4582: case 4584: case 4586: case 4588: case 4590: case 4592: case 4594: case 4596: case 4598: case 4600: case 4602: case 4604: case 4606: case 4608: case 4610: case 4612: case 4614: case 4616: case 4618: case 4620: case 4622: case 4624: case 4626: case 4628: case 4630: case 4632: return false; default: return true; } } } namespace RedNetherBrickSlab { BlockState RedNetherBrickSlab() { return 10852; } enum Type Type(const BlockState Block) { switch (Block.ID) { case 10852: return Type::Bottom; case 10854: return Type::Double; default: return Type::Top; } } } namespace RedNetherBrickStairs { BlockState RedNetherBrickStairs() { return 10560; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 10590: case 10592: case 10594: case 10596: case 10598: case 10600: case 10602: case 10604: case 10606: case 10608: return eBlockFace::BLOCK_FACE_XM; case 10610: case 10612: case 10614: case 10616: case 10618: case 10620: case 10622: case 10624: case 10626: case 10628: return eBlockFace::BLOCK_FACE_XP; case 10550: case 10552: case 10554: case 10556: case 10558: case 10560: case 10562: case 10564: case 10566: case 10568: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } enum Half Half(const BlockState Block) { switch (Block.ID) { case 10560: case 10562: case 10564: case 10566: case 10568: case 10580: case 10582: case 10584: case 10586: case 10588: case 10600: case 10602: case 10604: case 10606: case 10608: case 10620: case 10622: case 10624: case 10626: case 10628: return Half::Bottom; default: return Half::Top; } } enum Shape Shape(const BlockState Block) { switch (Block.ID) { case 10552: case 10562: case 10572: case 10582: case 10592: case 10602: case 10612: case 10622: return Shape::InnerLeft; case 10554: case 10564: case 10574: case 10584: case 10594: case 10604: case 10614: case 10624: return Shape::InnerRight; case 10556: case 10566: case 10576: case 10586: case 10596: case 10606: case 10616: case 10626: return Shape::OuterLeft; case 10558: case 10568: case 10578: case 10588: case 10598: case 10608: case 10618: case 10628: return Shape::OuterRight; default: return Shape::Straight; } } } namespace RedNetherBrickWall { BlockState RedNetherBrickWall() { return 13462; } enum East East(const BlockState Block) { switch (Block.ID) { case 13570: case 13571: case 13572: case 13576: case 13577: case 13578: case 13582: case 13583: case 13584: case 13588: case 13589: case 13590: case 13594: case 13595: case 13596: case 13600: case 13601: case 13602: case 13606: case 13607: case 13608: case 13612: case 13613: case 13614: case 13618: case 13619: case 13620: case 13624: case 13625: case 13626: case 13630: case 13631: case 13632: case 13636: case 13637: case 13638: case 13642: case 13643: case 13644: case 13648: case 13649: case 13650: case 13654: case 13655: case 13656: case 13660: case 13661: case 13662: case 13666: case 13667: case 13668: case 13672: case 13673: case 13674: return East::Low; case 13462: case 13463: case 13464: case 13468: case 13469: case 13470: case 13474: case 13475: case 13476: case 13480: case 13481: case 13482: case 13486: case 13487: case 13488: case 13492: case 13493: case 13494: case 13498: case 13499: case 13500: case 13504: case 13505: case 13506: case 13510: case 13511: case 13512: case 13516: case 13517: case 13518: case 13522: case 13523: case 13524: case 13528: case 13529: case 13530: case 13534: case 13535: case 13536: case 13540: case 13541: case 13542: case 13546: case 13547: case 13548: case 13552: case 13553: case 13554: case 13558: case 13559: case 13560: case 13564: case 13565: case 13566: return East::None; default: return East::Tall; } } enum North North(const BlockState Block) { switch (Block.ID) { case 13498: case 13499: case 13500: case 13504: case 13505: case 13506: case 13510: case 13511: case 13512: case 13516: case 13517: case 13518: case 13522: case 13523: case 13524: case 13528: case 13529: case 13530: case 13606: case 13607: case 13608: case 13612: case 13613: case 13614: case 13618: case 13619: case 13620: case 13624: case 13625: case 13626: case 13630: case 13631: case 13632: case 13636: case 13637: case 13638: case 13714: case 13715: case 13716: case 13720: case 13721: case 13722: case 13726: case 13727: case 13728: case 13732: case 13733: case 13734: case 13738: case 13739: case 13740: case 13744: case 13745: case 13746: return North::Low; case 13462: case 13463: case 13464: case 13468: case 13469: case 13470: case 13474: case 13475: case 13476: case 13480: case 13481: case 13482: case 13486: case 13487: case 13488: case 13492: case 13493: case 13494: case 13570: case 13571: case 13572: case 13576: case 13577: case 13578: case 13582: case 13583: case 13584: case 13588: case 13589: case 13590: case 13594: case 13595: case 13596: case 13600: case 13601: case 13602: case 13678: case 13679: case 13680: case 13684: case 13685: case 13686: case 13690: case 13691: case 13692: case 13696: case 13697: case 13698: case 13702: case 13703: case 13704: case 13708: case 13709: case 13710: return North::None; default: return North::Tall; } } enum South South(const BlockState Block) { switch (Block.ID) { case 13474: case 13475: case 13476: case 13480: case 13481: case 13482: case 13510: case 13511: case 13512: case 13516: case 13517: case 13518: case 13546: case 13547: case 13548: case 13552: case 13553: case 13554: case 13582: case 13583: case 13584: case 13588: case 13589: case 13590: case 13618: case 13619: case 13620: case 13624: case 13625: case 13626: case 13654: case 13655: case 13656: case 13660: case 13661: case 13662: case 13690: case 13691: case 13692: case 13696: case 13697: case 13698: case 13726: case 13727: case 13728: case 13732: case 13733: case 13734: case 13762: case 13763: case 13764: case 13768: case 13769: case 13770: return South::Low; case 13462: case 13463: case 13464: case 13468: case 13469: case 13470: case 13498: case 13499: case 13500: case 13504: case 13505: case 13506: case 13534: case 13535: case 13536: case 13540: case 13541: case 13542: case 13570: case 13571: case 13572: case 13576: case 13577: case 13578: case 13606: case 13607: case 13608: case 13612: case 13613: case 13614: case 13642: case 13643: case 13644: case 13648: case 13649: case 13650: case 13678: case 13679: case 13680: case 13684: case 13685: case 13686: case 13714: case 13715: case 13716: case 13720: case 13721: case 13722: case 13750: case 13751: case 13752: case 13756: case 13757: case 13758: return South::None; default: return South::Tall; } } bool Up(const BlockState Block) { switch (Block.ID) { case 13468: case 13469: case 13470: case 13480: case 13481: case 13482: case 13492: case 13493: case 13494: case 13504: case 13505: case 13506: case 13516: case 13517: case 13518: case 13528: case 13529: case 13530: case 13540: case 13541: case 13542: case 13552: case 13553: case 13554: case 13564: case 13565: case 13566: case 13576: case 13577: case 13578: case 13588: case 13589: case 13590: case 13600: case 13601: case 13602: case 13612: case 13613: case 13614: case 13624: case 13625: case 13626: case 13636: case 13637: case 13638: case 13648: case 13649: case 13650: case 13660: case 13661: case 13662: case 13672: case 13673: case 13674: case 13684: case 13685: case 13686: case 13696: case 13697: case 13698: case 13708: case 13709: case 13710: case 13720: case 13721: case 13722: case 13732: case 13733: case 13734: case 13744: case 13745: case 13746: case 13756: case 13757: case 13758: case 13768: case 13769: case 13770: case 13780: case 13781: case 13782: return false; default: return true; } } enum West West(const BlockState Block) { switch (Block.ID) { case 13463: case 13469: case 13475: case 13481: case 13487: case 13493: case 13499: case 13505: case 13511: case 13517: case 13523: case 13529: case 13535: case 13541: case 13547: case 13553: case 13559: case 13565: case 13571: case 13577: case 13583: case 13589: case 13595: case 13601: case 13607: case 13613: case 13619: case 13625: case 13631: case 13637: case 13643: case 13649: case 13655: case 13661: case 13667: case 13673: case 13679: case 13685: case 13691: case 13697: case 13703: case 13709: case 13715: case 13721: case 13727: case 13733: case 13739: case 13745: case 13751: case 13757: case 13763: case 13769: case 13775: case 13781: return West::Low; case 13462: case 13468: case 13474: case 13480: case 13486: case 13492: case 13498: case 13504: case 13510: case 13516: case 13522: case 13528: case 13534: case 13540: case 13546: case 13552: case 13558: case 13564: case 13570: case 13576: case 13582: case 13588: case 13594: case 13600: case 13606: case 13612: case 13618: case 13624: case 13630: case 13636: case 13642: case 13648: case 13654: case 13660: case 13666: case 13672: case 13678: case 13684: case 13690: case 13696: case 13702: case 13708: case 13714: case 13720: case 13726: case 13732: case 13738: case 13744: case 13750: case 13756: case 13762: case 13768: case 13774: case 13780: return West::None; default: return West::Tall; } } } namespace RedNetherBricks { } namespace RedSand { } namespace RedSandstone { } namespace RedSandstoneSlab { BlockState RedSandstoneSlab() { return 8399; } enum Type Type(const BlockState Block) { switch (Block.ID) { case 8399: return Type::Bottom; case 8401: return Type::Double; default: return Type::Top; } } } namespace RedSandstoneStairs { BlockState RedSandstoneStairs() { return 8231; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 8261: case 8263: case 8265: case 8267: case 8269: case 8271: case 8273: case 8275: case 8277: case 8279: return eBlockFace::BLOCK_FACE_XM; case 8281: case 8283: case 8285: case 8287: case 8289: case 8291: case 8293: case 8295: case 8297: case 8299: return eBlockFace::BLOCK_FACE_XP; case 8221: case 8223: case 8225: case 8227: case 8229: case 8231: case 8233: case 8235: case 8237: case 8239: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } enum Half Half(const BlockState Block) { switch (Block.ID) { case 8231: case 8233: case 8235: case 8237: case 8239: case 8251: case 8253: case 8255: case 8257: case 8259: case 8271: case 8273: case 8275: case 8277: case 8279: case 8291: case 8293: case 8295: case 8297: case 8299: return Half::Bottom; default: return Half::Top; } } enum Shape Shape(const BlockState Block) { switch (Block.ID) { case 8223: case 8233: case 8243: case 8253: case 8263: case 8273: case 8283: case 8293: return Shape::InnerLeft; case 8225: case 8235: case 8245: case 8255: case 8265: case 8275: case 8285: case 8295: return Shape::InnerRight; case 8227: case 8237: case 8247: case 8257: case 8267: case 8277: case 8287: case 8297: return Shape::OuterLeft; case 8229: case 8239: case 8249: case 8259: case 8269: case 8279: case 8289: case 8299: return Shape::OuterRight; default: return Shape::Straight; } } } namespace RedSandstoneWall { BlockState RedSandstoneWall() { return 11518; } enum East East(const BlockState Block) { switch (Block.ID) { case 11626: case 11627: case 11628: case 11632: case 11633: case 11634: case 11638: case 11639: case 11640: case 11644: case 11645: case 11646: case 11650: case 11651: case 11652: case 11656: case 11657: case 11658: case 11662: case 11663: case 11664: case 11668: case 11669: case 11670: case 11674: case 11675: case 11676: case 11680: case 11681: case 11682: case 11686: case 11687: case 11688: case 11692: case 11693: case 11694: case 11698: case 11699: case 11700: case 11704: case 11705: case 11706: case 11710: case 11711: case 11712: case 11716: case 11717: case 11718: case 11722: case 11723: case 11724: case 11728: case 11729: case 11730: return East::Low; case 11518: case 11519: case 11520: case 11524: case 11525: case 11526: case 11530: case 11531: case 11532: case 11536: case 11537: case 11538: case 11542: case 11543: case 11544: case 11548: case 11549: case 11550: case 11554: case 11555: case 11556: case 11560: case 11561: case 11562: case 11566: case 11567: case 11568: case 11572: case 11573: case 11574: case 11578: case 11579: case 11580: case 11584: case 11585: case 11586: case 11590: case 11591: case 11592: case 11596: case 11597: case 11598: case 11602: case 11603: case 11604: case 11608: case 11609: case 11610: case 11614: case 11615: case 11616: case 11620: case 11621: case 11622: return East::None; default: return East::Tall; } } enum North North(const BlockState Block) { switch (Block.ID) { case 11554: case 11555: case 11556: case 11560: case 11561: case 11562: case 11566: case 11567: case 11568: case 11572: case 11573: case 11574: case 11578: case 11579: case 11580: case 11584: case 11585: case 11586: case 11662: case 11663: case 11664: case 11668: case 11669: case 11670: case 11674: case 11675: case 11676: case 11680: case 11681: case 11682: case 11686: case 11687: case 11688: case 11692: case 11693: case 11694: case 11770: case 11771: case 11772: case 11776: case 11777: case 11778: case 11782: case 11783: case 11784: case 11788: case 11789: case 11790: case 11794: case 11795: case 11796: case 11800: case 11801: case 11802: return North::Low; case 11518: case 11519: case 11520: case 11524: case 11525: case 11526: case 11530: case 11531: case 11532: case 11536: case 11537: case 11538: case 11542: case 11543: case 11544: case 11548: case 11549: case 11550: case 11626: case 11627: case 11628: case 11632: case 11633: case 11634: case 11638: case 11639: case 11640: case 11644: case 11645: case 11646: case 11650: case 11651: case 11652: case 11656: case 11657: case 11658: case 11734: case 11735: case 11736: case 11740: case 11741: case 11742: case 11746: case 11747: case 11748: case 11752: case 11753: case 11754: case 11758: case 11759: case 11760: case 11764: case 11765: case 11766: return North::None; default: return North::Tall; } } enum South South(const BlockState Block) { switch (Block.ID) { case 11530: case 11531: case 11532: case 11536: case 11537: case 11538: case 11566: case 11567: case 11568: case 11572: case 11573: case 11574: case 11602: case 11603: case 11604: case 11608: case 11609: case 11610: case 11638: case 11639: case 11640: case 11644: case 11645: case 11646: case 11674: case 11675: case 11676: case 11680: case 11681: case 11682: case 11710: case 11711: case 11712: case 11716: case 11717: case 11718: case 11746: case 11747: case 11748: case 11752: case 11753: case 11754: case 11782: case 11783: case 11784: case 11788: case 11789: case 11790: case 11818: case 11819: case 11820: case 11824: case 11825: case 11826: return South::Low; case 11518: case 11519: case 11520: case 11524: case 11525: case 11526: case 11554: case 11555: case 11556: case 11560: case 11561: case 11562: case 11590: case 11591: case 11592: case 11596: case 11597: case 11598: case 11626: case 11627: case 11628: case 11632: case 11633: case 11634: case 11662: case 11663: case 11664: case 11668: case 11669: case 11670: case 11698: case 11699: case 11700: case 11704: case 11705: case 11706: case 11734: case 11735: case 11736: case 11740: case 11741: case 11742: case 11770: case 11771: case 11772: case 11776: case 11777: case 11778: case 11806: case 11807: case 11808: case 11812: case 11813: case 11814: return South::None; default: return South::Tall; } } bool Up(const BlockState Block) { switch (Block.ID) { case 11524: case 11525: case 11526: case 11536: case 11537: case 11538: case 11548: case 11549: case 11550: case 11560: case 11561: case 11562: case 11572: case 11573: case 11574: case 11584: case 11585: case 11586: case 11596: case 11597: case 11598: case 11608: case 11609: case 11610: case 11620: case 11621: case 11622: case 11632: case 11633: case 11634: case 11644: case 11645: case 11646: case 11656: case 11657: case 11658: case 11668: case 11669: case 11670: case 11680: case 11681: case 11682: case 11692: case 11693: case 11694: case 11704: case 11705: case 11706: case 11716: case 11717: case 11718: case 11728: case 11729: case 11730: case 11740: case 11741: case 11742: case 11752: case 11753: case 11754: case 11764: case 11765: case 11766: case 11776: case 11777: case 11778: case 11788: case 11789: case 11790: case 11800: case 11801: case 11802: case 11812: case 11813: case 11814: case 11824: case 11825: case 11826: case 11836: case 11837: case 11838: return false; default: return true; } } enum West West(const BlockState Block) { switch (Block.ID) { case 11519: case 11525: case 11531: case 11537: case 11543: case 11549: case 11555: case 11561: case 11567: case 11573: case 11579: case 11585: case 11591: case 11597: case 11603: case 11609: case 11615: case 11621: case 11627: case 11633: case 11639: case 11645: case 11651: case 11657: case 11663: case 11669: case 11675: case 11681: case 11687: case 11693: case 11699: case 11705: case 11711: case 11717: case 11723: case 11729: case 11735: case 11741: case 11747: case 11753: case 11759: case 11765: case 11771: case 11777: case 11783: case 11789: case 11795: case 11801: case 11807: case 11813: case 11819: case 11825: case 11831: case 11837: return West::Low; case 11518: case 11524: case 11530: case 11536: case 11542: case 11548: case 11554: case 11560: case 11566: case 11572: case 11578: case 11584: case 11590: case 11596: case 11602: case 11608: case 11614: case 11620: case 11626: case 11632: case 11638: case 11644: case 11650: case 11656: case 11662: case 11668: case 11674: case 11680: case 11686: case 11692: case 11698: case 11704: case 11710: case 11716: case 11722: case 11728: case 11734: case 11740: case 11746: case 11752: case 11758: case 11764: case 11770: case 11776: case 11782: case 11788: case 11794: case 11800: case 11806: case 11812: case 11818: case 11824: case 11830: case 11836: return West::None; default: return West::Tall; } } } namespace RedShulkerBox { BlockState RedShulkerBox() { return 9366; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 9365: return eBlockFace::BLOCK_FACE_XM; case 9363: return eBlockFace::BLOCK_FACE_XP; case 9367: return eBlockFace::BLOCK_FACE_YM; case 9366: return eBlockFace::BLOCK_FACE_YP; case 9362: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace RedStainedGlass { } namespace RedStainedGlassPane { BlockState RedStainedGlassPane() { return 7342; } bool East(const BlockState Block) { switch (Block.ID) { case 7329: case 7330: case 7333: case 7334: case 7337: case 7338: case 7341: case 7342: return false; default: return true; } } bool North(const BlockState Block) { switch (Block.ID) { case 7321: case 7322: case 7325: case 7326: case 7337: case 7338: case 7341: case 7342: return false; default: return true; } } bool South(const BlockState Block) { switch (Block.ID) { case 7317: case 7318: case 7325: case 7326: case 7333: case 7334: case 7341: case 7342: return false; default: return true; } } bool West(const BlockState Block) { switch (Block.ID) { case 7314: case 7318: case 7322: case 7326: case 7330: case 7334: case 7338: case 7342: return false; default: return true; } } } namespace RedTerracotta { } namespace RedTulip { } namespace RedWallBanner { BlockState RedWallBanner() { return 8209; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 8211: return eBlockFace::BLOCK_FACE_XM; case 8212: return eBlockFace::BLOCK_FACE_XP; case 8209: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace RedWool { } namespace RedstoneBlock { } namespace RedstoneLamp { BlockState RedstoneLamp() { return 5157; } bool Lit(const BlockState Block) { switch (Block.ID) { case 5157: return false; default: return true; } } } namespace RedstoneOre { BlockState RedstoneOre() { return 3886; } bool Lit(const BlockState Block) { switch (Block.ID) { case 3886: return false; default: return true; } } } namespace RedstoneTorch { BlockState RedstoneTorch() { return 3887; } bool Lit(const BlockState Block) { switch (Block.ID) { case 3888: return false; default: return true; } } } namespace RedstoneWallTorch { BlockState RedstoneWallTorch() { return 3889; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 3893: case 3894: return eBlockFace::BLOCK_FACE_XM; case 3895: case 3896: return eBlockFace::BLOCK_FACE_XP; case 3889: case 3890: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } bool Lit(const BlockState Block) { switch (Block.ID) { case 3890: case 3892: case 3894: case 3896: return false; default: return true; } } } namespace RedstoneWire { BlockState RedstoneWire() { return 3218; } enum East East(const BlockState Block) { switch (Block.ID) { case 2922: case 2923: case 2924: case 2925: case 2926: case 2927: case 2928: case 2929: case 2930: case 2931: case 2932: case 2933: case 2934: case 2935: case 2936: case 2937: case 2938: case 2939: case 2940: case 2941: case 2942: case 2943: case 2944: case 2945: case 2946: case 2947: case 2948: case 2949: case 2950: case 2951: case 2952: case 2953: case 2954: case 2955: case 2956: case 2957: case 2958: case 2959: case 2960: case 2961: case 2962: case 2963: case 2964: case 2965: case 2966: case 2967: case 2968: case 2969: case 2970: case 2971: case 2972: case 2973: case 2974: case 2975: case 2976: case 2977: case 2978: case 2979: case 2980: case 2981: case 2982: case 2983: case 2984: case 2985: case 2986: case 2987: case 2988: case 2989: case 2990: case 2991: case 2992: case 2993: case 2994: case 2995: case 2996: case 2997: case 2998: case 2999: case 3000: case 3001: case 3002: case 3003: case 3004: case 3005: case 3006: case 3007: case 3008: case 3009: case 3010: case 3011: case 3012: case 3013: case 3014: case 3015: case 3016: case 3017: case 3018: case 3019: case 3020: case 3021: case 3022: case 3023: case 3024: case 3025: case 3026: case 3027: case 3028: case 3029: case 3030: case 3031: case 3032: case 3033: case 3034: case 3035: case 3036: case 3037: case 3038: case 3039: case 3040: case 3041: case 3042: case 3043: case 3044: case 3045: case 3046: case 3047: case 3048: case 3049: case 3050: case 3051: case 3052: case 3053: case 3054: case 3055: case 3056: case 3057: case 3058: case 3059: case 3060: case 3061: case 3062: case 3063: case 3064: case 3065: case 3066: case 3067: case 3068: case 3069: case 3070: case 3071: case 3072: case 3073: case 3074: case 3075: case 3076: case 3077: case 3078: case 3079: case 3080: case 3081: case 3082: case 3083: case 3084: case 3085: case 3086: case 3087: case 3088: case 3089: case 3090: case 3091: case 3092: case 3093: case 3094: case 3095: case 3096: case 3097: case 3098: case 3099: case 3100: case 3101: case 3102: case 3103: case 3104: case 3105: case 3106: case 3107: case 3108: case 3109: case 3110: case 3111: case 3112: case 3113: case 3114: case 3115: case 3116: case 3117: case 3118: case 3119: case 3120: case 3121: case 3122: case 3123: case 3124: case 3125: case 3126: case 3127: case 3128: case 3129: case 3130: case 3131: case 3132: case 3133: case 3134: case 3135: case 3136: case 3137: case 3138: case 3139: case 3140: case 3141: case 3142: case 3143: case 3144: case 3145: case 3146: case 3147: case 3148: case 3149: case 3150: case 3151: case 3152: case 3153: case 3154: case 3155: case 3156: case 3157: case 3158: case 3159: case 3160: case 3161: case 3162: case 3163: case 3164: case 3165: case 3166: case 3167: case 3168: case 3169: case 3170: case 3171: case 3172: case 3173: case 3174: case 3175: case 3176: case 3177: case 3178: case 3179: case 3180: case 3181: case 3182: case 3183: case 3184: case 3185: case 3186: case 3187: case 3188: case 3189: case 3190: case 3191: case 3192: case 3193: case 3194: case 3195: case 3196: case 3197: case 3198: case 3199: case 3200: case 3201: case 3202: case 3203: case 3204: case 3205: case 3206: case 3207: case 3208: case 3209: case 3210: case 3211: case 3212: case 3213: case 3214: case 3215: case 3216: case 3217: case 3218: case 3219: case 3220: case 3221: case 3222: case 3223: case 3224: case 3225: case 3226: case 3227: case 3228: case 3229: case 3230: case 3231: case 3232: case 3233: case 3234: case 3235: case 3236: case 3237: case 3238: case 3239: case 3240: case 3241: case 3242: case 3243: case 3244: case 3245: case 3246: case 3247: case 3248: case 3249: case 3250: case 3251: case 3252: case 3253: case 3254: case 3255: case 3256: case 3257: case 3258: case 3259: case 3260: case 3261: case 3262: case 3263: case 3264: case 3265: case 3266: case 3267: case 3268: case 3269: case 3270: case 3271: case 3272: case 3273: case 3274: case 3275: case 3276: case 3277: case 3278: case 3279: case 3280: case 3281: case 3282: case 3283: case 3284: case 3285: case 3286: case 3287: case 3288: case 3289: case 3290: case 3291: case 3292: case 3293: case 3294: case 3295: case 3296: case 3297: case 3298: case 3299: case 3300: case 3301: case 3302: case 3303: case 3304: case 3305: case 3306: case 3307: case 3308: case 3309: case 3310: case 3311: case 3312: case 3313: case 3314: case 3315: case 3316: case 3317: case 3318: case 3319: case 3320: case 3321: case 3322: case 3323: case 3324: case 3325: case 3326: case 3327: case 3328: case 3329: case 3330: case 3331: case 3332: case 3333: case 3334: case 3335: case 3336: case 3337: case 3338: case 3339: case 3340: case 3341: case 3342: case 3343: case 3344: case 3345: case 3346: case 3347: case 3348: case 3349: case 3350: case 3351: case 3352: case 3353: return East::None; case 2490: case 2491: case 2492: case 2493: case 2494: case 2495: case 2496: case 2497: case 2498: case 2499: case 2500: case 2501: case 2502: case 2503: case 2504: case 2505: case 2506: case 2507: case 2508: case 2509: case 2510: case 2511: case 2512: case 2513: case 2514: case 2515: case 2516: case 2517: case 2518: case 2519: case 2520: case 2521: case 2522: case 2523: case 2524: case 2525: case 2526: case 2527: case 2528: case 2529: case 2530: case 2531: case 2532: case 2533: case 2534: case 2535: case 2536: case 2537: case 2538: case 2539: case 2540: case 2541: case 2542: case 2543: case 2544: case 2545: case 2546: case 2547: case 2548: case 2549: case 2550: case 2551: case 2552: case 2553: case 2554: case 2555: case 2556: case 2557: case 2558: case 2559: case 2560: case 2561: case 2562: case 2563: case 2564: case 2565: case 2566: case 2567: case 2568: case 2569: case 2570: case 2571: case 2572: case 2573: case 2574: case 2575: case 2576: case 2577: case 2578: case 2579: case 2580: case 2581: case 2582: case 2583: case 2584: case 2585: case 2586: case 2587: case 2588: case 2589: case 2590: case 2591: case 2592: case 2593: case 2594: case 2595: case 2596: case 2597: case 2598: case 2599: case 2600: case 2601: case 2602: case 2603: case 2604: case 2605: case 2606: case 2607: case 2608: case 2609: case 2610: case 2611: case 2612: case 2613: case 2614: case 2615: case 2616: case 2617: case 2618: case 2619: case 2620: case 2621: case 2622: case 2623: case 2624: case 2625: case 2626: case 2627: case 2628: case 2629: case 2630: case 2631: case 2632: case 2633: case 2634: case 2635: case 2636: case 2637: case 2638: case 2639: case 2640: case 2641: case 2642: case 2643: case 2644: case 2645: case 2646: case 2647: case 2648: case 2649: case 2650: case 2651: case 2652: case 2653: case 2654: case 2655: case 2656: case 2657: case 2658: case 2659: case 2660: case 2661: case 2662: case 2663: case 2664: case 2665: case 2666: case 2667: case 2668: case 2669: case 2670: case 2671: case 2672: case 2673: case 2674: case 2675: case 2676: case 2677: case 2678: case 2679: case 2680: case 2681: case 2682: case 2683: case 2684: case 2685: case 2686: case 2687: case 2688: case 2689: case 2690: case 2691: case 2692: case 2693: case 2694: case 2695: case 2696: case 2697: case 2698: case 2699: case 2700: case 2701: case 2702: case 2703: case 2704: case 2705: case 2706: case 2707: case 2708: case 2709: case 2710: case 2711: case 2712: case 2713: case 2714: case 2715: case 2716: case 2717: case 2718: case 2719: case 2720: case 2721: case 2722: case 2723: case 2724: case 2725: case 2726: case 2727: case 2728: case 2729: case 2730: case 2731: case 2732: case 2733: case 2734: case 2735: case 2736: case 2737: case 2738: case 2739: case 2740: case 2741: case 2742: case 2743: case 2744: case 2745: case 2746: case 2747: case 2748: case 2749: case 2750: case 2751: case 2752: case 2753: case 2754: case 2755: case 2756: case 2757: case 2758: case 2759: case 2760: case 2761: case 2762: case 2763: case 2764: case 2765: case 2766: case 2767: case 2768: case 2769: case 2770: case 2771: case 2772: case 2773: case 2774: case 2775: case 2776: case 2777: case 2778: case 2779: case 2780: case 2781: case 2782: case 2783: case 2784: case 2785: case 2786: case 2787: case 2788: case 2789: case 2790: case 2791: case 2792: case 2793: case 2794: case 2795: case 2796: case 2797: case 2798: case 2799: case 2800: case 2801: case 2802: case 2803: case 2804: case 2805: case 2806: case 2807: case 2808: case 2809: case 2810: case 2811: case 2812: case 2813: case 2814: case 2815: case 2816: case 2817: case 2818: case 2819: case 2820: case 2821: case 2822: case 2823: case 2824: case 2825: case 2826: case 2827: case 2828: case 2829: case 2830: case 2831: case 2832: case 2833: case 2834: case 2835: case 2836: case 2837: case 2838: case 2839: case 2840: case 2841: case 2842: case 2843: case 2844: case 2845: case 2846: case 2847: case 2848: case 2849: case 2850: case 2851: case 2852: case 2853: case 2854: case 2855: case 2856: case 2857: case 2858: case 2859: case 2860: case 2861: case 2862: case 2863: case 2864: case 2865: case 2866: case 2867: case 2868: case 2869: case 2870: case 2871: case 2872: case 2873: case 2874: case 2875: case 2876: case 2877: case 2878: case 2879: case 2880: case 2881: case 2882: case 2883: case 2884: case 2885: case 2886: case 2887: case 2888: case 2889: case 2890: case 2891: case 2892: case 2893: case 2894: case 2895: case 2896: case 2897: case 2898: case 2899: case 2900: case 2901: case 2902: case 2903: case 2904: case 2905: case 2906: case 2907: case 2908: case 2909: case 2910: case 2911: case 2912: case 2913: case 2914: case 2915: case 2916: case 2917: case 2918: case 2919: case 2920: case 2921: return East::Side; default: return East::Up; } } enum North North(const BlockState Block) { switch (Block.ID) { case 2346: case 2347: case 2348: case 2349: case 2350: case 2351: case 2352: case 2353: case 2354: case 2355: case 2356: case 2357: case 2358: case 2359: case 2360: case 2361: case 2362: case 2363: case 2364: case 2365: case 2366: case 2367: case 2368: case 2369: case 2370: case 2371: case 2372: case 2373: case 2374: case 2375: case 2376: case 2377: case 2378: case 2379: case 2380: case 2381: case 2382: case 2383: case 2384: case 2385: case 2386: case 2387: case 2388: case 2389: case 2390: case 2391: case 2392: case 2393: case 2394: case 2395: case 2396: case 2397: case 2398: case 2399: case 2400: case 2401: case 2402: case 2403: case 2404: case 2405: case 2406: case 2407: case 2408: case 2409: case 2410: case 2411: case 2412: case 2413: case 2414: case 2415: case 2416: case 2417: case 2418: case 2419: case 2420: case 2421: case 2422: case 2423: case 2424: case 2425: case 2426: case 2427: case 2428: case 2429: case 2430: case 2431: case 2432: case 2433: case 2434: case 2435: case 2436: case 2437: case 2438: case 2439: case 2440: case 2441: case 2442: case 2443: case 2444: case 2445: case 2446: case 2447: case 2448: case 2449: case 2450: case 2451: case 2452: case 2453: case 2454: case 2455: case 2456: case 2457: case 2458: case 2459: case 2460: case 2461: case 2462: case 2463: case 2464: case 2465: case 2466: case 2467: case 2468: case 2469: case 2470: case 2471: case 2472: case 2473: case 2474: case 2475: case 2476: case 2477: case 2478: case 2479: case 2480: case 2481: case 2482: case 2483: case 2484: case 2485: case 2486: case 2487: case 2488: case 2489: case 2778: case 2779: case 2780: case 2781: case 2782: case 2783: case 2784: case 2785: case 2786: case 2787: case 2788: case 2789: case 2790: case 2791: case 2792: case 2793: case 2794: case 2795: case 2796: case 2797: case 2798: case 2799: case 2800: case 2801: case 2802: case 2803: case 2804: case 2805: case 2806: case 2807: case 2808: case 2809: case 2810: case 2811: case 2812: case 2813: case 2814: case 2815: case 2816: case 2817: case 2818: case 2819: case 2820: case 2821: case 2822: case 2823: case 2824: case 2825: case 2826: case 2827: case 2828: case 2829: case 2830: case 2831: case 2832: case 2833: case 2834: case 2835: case 2836: case 2837: case 2838: case 2839: case 2840: case 2841: case 2842: case 2843: case 2844: case 2845: case 2846: case 2847: case 2848: case 2849: case 2850: case 2851: case 2852: case 2853: case 2854: case 2855: case 2856: case 2857: case 2858: case 2859: case 2860: case 2861: case 2862: case 2863: case 2864: case 2865: case 2866: case 2867: case 2868: case 2869: case 2870: case 2871: case 2872: case 2873: case 2874: case 2875: case 2876: case 2877: case 2878: case 2879: case 2880: case 2881: case 2882: case 2883: case 2884: case 2885: case 2886: case 2887: case 2888: case 2889: case 2890: case 2891: case 2892: case 2893: case 2894: case 2895: case 2896: case 2897: case 2898: case 2899: case 2900: case 2901: case 2902: case 2903: case 2904: case 2905: case 2906: case 2907: case 2908: case 2909: case 2910: case 2911: case 2912: case 2913: case 2914: case 2915: case 2916: case 2917: case 2918: case 2919: case 2920: case 2921: case 3210: case 3211: case 3212: case 3213: case 3214: case 3215: case 3216: case 3217: case 3218: case 3219: case 3220: case 3221: case 3222: case 3223: case 3224: case 3225: case 3226: case 3227: case 3228: case 3229: case 3230: case 3231: case 3232: case 3233: case 3234: case 3235: case 3236: case 3237: case 3238: case 3239: case 3240: case 3241: case 3242: case 3243: case 3244: case 3245: case 3246: case 3247: case 3248: case 3249: case 3250: case 3251: case 3252: case 3253: case 3254: case 3255: case 3256: case 3257: case 3258: case 3259: case 3260: case 3261: case 3262: case 3263: case 3264: case 3265: case 3266: case 3267: case 3268: case 3269: case 3270: case 3271: case 3272: case 3273: case 3274: case 3275: case 3276: case 3277: case 3278: case 3279: case 3280: case 3281: case 3282: case 3283: case 3284: case 3285: case 3286: case 3287: case 3288: case 3289: case 3290: case 3291: case 3292: case 3293: case 3294: case 3295: case 3296: case 3297: case 3298: case 3299: case 3300: case 3301: case 3302: case 3303: case 3304: case 3305: case 3306: case 3307: case 3308: case 3309: case 3310: case 3311: case 3312: case 3313: case 3314: case 3315: case 3316: case 3317: case 3318: case 3319: case 3320: case 3321: case 3322: case 3323: case 3324: case 3325: case 3326: case 3327: case 3328: case 3329: case 3330: case 3331: case 3332: case 3333: case 3334: case 3335: case 3336: case 3337: case 3338: case 3339: case 3340: case 3341: case 3342: case 3343: case 3344: case 3345: case 3346: case 3347: case 3348: case 3349: case 3350: case 3351: case 3352: case 3353: return North::None; case 2202: case 2203: case 2204: case 2205: case 2206: case 2207: case 2208: case 2209: case 2210: case 2211: case 2212: case 2213: case 2214: case 2215: case 2216: case 2217: case 2218: case 2219: case 2220: case 2221: case 2222: case 2223: case 2224: case 2225: case 2226: case 2227: case 2228: case 2229: case 2230: case 2231: case 2232: case 2233: case 2234: case 2235: case 2236: case 2237: case 2238: case 2239: case 2240: case 2241: case 2242: case 2243: case 2244: case 2245: case 2246: case 2247: case 2248: case 2249: case 2250: case 2251: case 2252: case 2253: case 2254: case 2255: case 2256: case 2257: case 2258: case 2259: case 2260: case 2261: case 2262: case 2263: case 2264: case 2265: case 2266: case 2267: case 2268: case 2269: case 2270: case 2271: case 2272: case 2273: case 2274: case 2275: case 2276: case 2277: case 2278: case 2279: case 2280: case 2281: case 2282: case 2283: case 2284: case 2285: case 2286: case 2287: case 2288: case 2289: case 2290: case 2291: case 2292: case 2293: case 2294: case 2295: case 2296: case 2297: case 2298: case 2299: case 2300: case 2301: case 2302: case 2303: case 2304: case 2305: case 2306: case 2307: case 2308: case 2309: case 2310: case 2311: case 2312: case 2313: case 2314: case 2315: case 2316: case 2317: case 2318: case 2319: case 2320: case 2321: case 2322: case 2323: case 2324: case 2325: case 2326: case 2327: case 2328: case 2329: case 2330: case 2331: case 2332: case 2333: case 2334: case 2335: case 2336: case 2337: case 2338: case 2339: case 2340: case 2341: case 2342: case 2343: case 2344: case 2345: case 2634: case 2635: case 2636: case 2637: case 2638: case 2639: case 2640: case 2641: case 2642: case 2643: case 2644: case 2645: case 2646: case 2647: case 2648: case 2649: case 2650: case 2651: case 2652: case 2653: case 2654: case 2655: case 2656: case 2657: case 2658: case 2659: case 2660: case 2661: case 2662: case 2663: case 2664: case 2665: case 2666: case 2667: case 2668: case 2669: case 2670: case 2671: case 2672: case 2673: case 2674: case 2675: case 2676: case 2677: case 2678: case 2679: case 2680: case 2681: case 2682: case 2683: case 2684: case 2685: case 2686: case 2687: case 2688: case 2689: case 2690: case 2691: case 2692: case 2693: case 2694: case 2695: case 2696: case 2697: case 2698: case 2699: case 2700: case 2701: case 2702: case 2703: case 2704: case 2705: case 2706: case 2707: case 2708: case 2709: case 2710: case 2711: case 2712: case 2713: case 2714: case 2715: case 2716: case 2717: case 2718: case 2719: case 2720: case 2721: case 2722: case 2723: case 2724: case 2725: case 2726: case 2727: case 2728: case 2729: case 2730: case 2731: case 2732: case 2733: case 2734: case 2735: case 2736: case 2737: case 2738: case 2739: case 2740: case 2741: case 2742: case 2743: case 2744: case 2745: case 2746: case 2747: case 2748: case 2749: case 2750: case 2751: case 2752: case 2753: case 2754: case 2755: case 2756: case 2757: case 2758: case 2759: case 2760: case 2761: case 2762: case 2763: case 2764: case 2765: case 2766: case 2767: case 2768: case 2769: case 2770: case 2771: case 2772: case 2773: case 2774: case 2775: case 2776: case 2777: case 3066: case 3067: case 3068: case 3069: case 3070: case 3071: case 3072: case 3073: case 3074: case 3075: case 3076: case 3077: case 3078: case 3079: case 3080: case 3081: case 3082: case 3083: case 3084: case 3085: case 3086: case 3087: case 3088: case 3089: case 3090: case 3091: case 3092: case 3093: case 3094: case 3095: case 3096: case 3097: case 3098: case 3099: case 3100: case 3101: case 3102: case 3103: case 3104: case 3105: case 3106: case 3107: case 3108: case 3109: case 3110: case 3111: case 3112: case 3113: case 3114: case 3115: case 3116: case 3117: case 3118: case 3119: case 3120: case 3121: case 3122: case 3123: case 3124: case 3125: case 3126: case 3127: case 3128: case 3129: case 3130: case 3131: case 3132: case 3133: case 3134: case 3135: case 3136: case 3137: case 3138: case 3139: case 3140: case 3141: case 3142: case 3143: case 3144: case 3145: case 3146: case 3147: case 3148: case 3149: case 3150: case 3151: case 3152: case 3153: case 3154: case 3155: case 3156: case 3157: case 3158: case 3159: case 3160: case 3161: case 3162: case 3163: case 3164: case 3165: case 3166: case 3167: case 3168: case 3169: case 3170: case 3171: case 3172: case 3173: case 3174: case 3175: case 3176: case 3177: case 3178: case 3179: case 3180: case 3181: case 3182: case 3183: case 3184: case 3185: case 3186: case 3187: case 3188: case 3189: case 3190: case 3191: case 3192: case 3193: case 3194: case 3195: case 3196: case 3197: case 3198: case 3199: case 3200: case 3201: case 3202: case 3203: case 3204: case 3205: case 3206: case 3207: case 3208: case 3209: return North::Side; default: return North::Up; } } unsigned char Power(const BlockState Block) { switch (Block.ID) { case 2058: case 2059: case 2060: case 2061: case 2062: case 2063: case 2064: case 2065: case 2066: case 2202: case 2203: case 2204: case 2205: case 2206: case 2207: case 2208: case 2209: case 2210: case 2346: case 2347: case 2348: case 2349: case 2350: case 2351: case 2352: case 2353: case 2354: case 2490: case 2491: case 2492: case 2493: case 2494: case 2495: case 2496: case 2497: case 2498: case 2634: case 2635: case 2636: case 2637: case 2638: case 2639: case 2640: case 2641: case 2642: case 2778: case 2779: case 2780: case 2781: case 2782: case 2783: case 2784: case 2785: case 2786: case 2922: case 2923: case 2924: case 2925: case 2926: case 2927: case 2928: case 2929: case 2930: case 3066: case 3067: case 3068: case 3069: case 3070: case 3071: case 3072: case 3073: case 3074: case 3210: case 3211: case 3212: case 3213: case 3214: case 3215: case 3216: case 3217: case 3218: return 0; case 2067: case 2068: case 2069: case 2070: case 2071: case 2072: case 2073: case 2074: case 2075: case 2211: case 2212: case 2213: case 2214: case 2215: case 2216: case 2217: case 2218: case 2219: case 2355: case 2356: case 2357: case 2358: case 2359: case 2360: case 2361: case 2362: case 2363: case 2499: case 2500: case 2501: case 2502: case 2503: case 2504: case 2505: case 2506: case 2507: case 2643: case 2644: case 2645: case 2646: case 2647: case 2648: case 2649: case 2650: case 2651: case 2787: case 2788: case 2789: case 2790: case 2791: case 2792: case 2793: case 2794: case 2795: case 2931: case 2932: case 2933: case 2934: case 2935: case 2936: case 2937: case 2938: case 2939: case 3075: case 3076: case 3077: case 3078: case 3079: case 3080: case 3081: case 3082: case 3083: case 3219: case 3220: case 3221: case 3222: case 3223: case 3224: case 3225: case 3226: case 3227: return 1; case 2148: case 2149: case 2150: case 2151: case 2152: case 2153: case 2154: case 2155: case 2156: case 2292: case 2293: case 2294: case 2295: case 2296: case 2297: case 2298: case 2299: case 2300: case 2436: case 2437: case 2438: case 2439: case 2440: case 2441: case 2442: case 2443: case 2444: case 2580: case 2581: case 2582: case 2583: case 2584: case 2585: case 2586: case 2587: case 2588: case 2724: case 2725: case 2726: case 2727: case 2728: case 2729: case 2730: case 2731: case 2732: case 2868: case 2869: case 2870: case 2871: case 2872: case 2873: case 2874: case 2875: case 2876: case 3012: case 3013: case 3014: case 3015: case 3016: case 3017: case 3018: case 3019: case 3020: case 3156: case 3157: case 3158: case 3159: case 3160: case 3161: case 3162: case 3163: case 3164: case 3300: case 3301: case 3302: case 3303: case 3304: case 3305: case 3306: case 3307: case 3308: return 10; case 2157: case 2158: case 2159: case 2160: case 2161: case 2162: case 2163: case 2164: case 2165: case 2301: case 2302: case 2303: case 2304: case 2305: case 2306: case 2307: case 2308: case 2309: case 2445: case 2446: case 2447: case 2448: case 2449: case 2450: case 2451: case 2452: case 2453: case 2589: case 2590: case 2591: case 2592: case 2593: case 2594: case 2595: case 2596: case 2597: case 2733: case 2734: case 2735: case 2736: case 2737: case 2738: case 2739: case 2740: case 2741: case 2877: case 2878: case 2879: case 2880: case 2881: case 2882: case 2883: case 2884: case 2885: case 3021: case 3022: case 3023: case 3024: case 3025: case 3026: case 3027: case 3028: case 3029: case 3165: case 3166: case 3167: case 3168: case 3169: case 3170: case 3171: case 3172: case 3173: case 3309: case 3310: case 3311: case 3312: case 3313: case 3314: case 3315: case 3316: case 3317: return 11; case 2166: case 2167: case 2168: case 2169: case 2170: case 2171: case 2172: case 2173: case 2174: case 2310: case 2311: case 2312: case 2313: case 2314: case 2315: case 2316: case 2317: case 2318: case 2454: case 2455: case 2456: case 2457: case 2458: case 2459: case 2460: case 2461: case 2462: case 2598: case 2599: case 2600: case 2601: case 2602: case 2603: case 2604: case 2605: case 2606: case 2742: case 2743: case 2744: case 2745: case 2746: case 2747: case 2748: case 2749: case 2750: case 2886: case 2887: case 2888: case 2889: case 2890: case 2891: case 2892: case 2893: case 2894: case 3030: case 3031: case 3032: case 3033: case 3034: case 3035: case 3036: case 3037: case 3038: case 3174: case 3175: case 3176: case 3177: case 3178: case 3179: case 3180: case 3181: case 3182: case 3318: case 3319: case 3320: case 3321: case 3322: case 3323: case 3324: case 3325: case 3326: return 12; case 2175: case 2176: case 2177: case 2178: case 2179: case 2180: case 2181: case 2182: case 2183: case 2319: case 2320: case 2321: case 2322: case 2323: case 2324: case 2325: case 2326: case 2327: case 2463: case 2464: case 2465: case 2466: case 2467: case 2468: case 2469: case 2470: case 2471: case 2607: case 2608: case 2609: case 2610: case 2611: case 2612: case 2613: case 2614: case 2615: case 2751: case 2752: case 2753: case 2754: case 2755: case 2756: case 2757: case 2758: case 2759: case 2895: case 2896: case 2897: case 2898: case 2899: case 2900: case 2901: case 2902: case 2903: case 3039: case 3040: case 3041: case 3042: case 3043: case 3044: case 3045: case 3046: case 3047: case 3183: case 3184: case 3185: case 3186: case 3187: case 3188: case 3189: case 3190: case 3191: case 3327: case 3328: case 3329: case 3330: case 3331: case 3332: case 3333: case 3334: case 3335: return 13; case 2184: case 2185: case 2186: case 2187: case 2188: case 2189: case 2190: case 2191: case 2192: case 2328: case 2329: case 2330: case 2331: case 2332: case 2333: case 2334: case 2335: case 2336: case 2472: case 2473: case 2474: case 2475: case 2476: case 2477: case 2478: case 2479: case 2480: case 2616: case 2617: case 2618: case 2619: case 2620: case 2621: case 2622: case 2623: case 2624: case 2760: case 2761: case 2762: case 2763: case 2764: case 2765: case 2766: case 2767: case 2768: case 2904: case 2905: case 2906: case 2907: case 2908: case 2909: case 2910: case 2911: case 2912: case 3048: case 3049: case 3050: case 3051: case 3052: case 3053: case 3054: case 3055: case 3056: case 3192: case 3193: case 3194: case 3195: case 3196: case 3197: case 3198: case 3199: case 3200: case 3336: case 3337: case 3338: case 3339: case 3340: case 3341: case 3342: case 3343: case 3344: return 14; case 2193: case 2194: case 2195: case 2196: case 2197: case 2198: case 2199: case 2200: case 2201: case 2337: case 2338: case 2339: case 2340: case 2341: case 2342: case 2343: case 2344: case 2345: case 2481: case 2482: case 2483: case 2484: case 2485: case 2486: case 2487: case 2488: case 2489: case 2625: case 2626: case 2627: case 2628: case 2629: case 2630: case 2631: case 2632: case 2633: case 2769: case 2770: case 2771: case 2772: case 2773: case 2774: case 2775: case 2776: case 2777: case 2913: case 2914: case 2915: case 2916: case 2917: case 2918: case 2919: case 2920: case 2921: case 3057: case 3058: case 3059: case 3060: case 3061: case 3062: case 3063: case 3064: case 3065: case 3201: case 3202: case 3203: case 3204: case 3205: case 3206: case 3207: case 3208: case 3209: case 3345: case 3346: case 3347: case 3348: case 3349: case 3350: case 3351: case 3352: case 3353: return 15; case 2076: case 2077: case 2078: case 2079: case 2080: case 2081: case 2082: case 2083: case 2084: case 2220: case 2221: case 2222: case 2223: case 2224: case 2225: case 2226: case 2227: case 2228: case 2364: case 2365: case 2366: case 2367: case 2368: case 2369: case 2370: case 2371: case 2372: case 2508: case 2509: case 2510: case 2511: case 2512: case 2513: case 2514: case 2515: case 2516: case 2652: case 2653: case 2654: case 2655: case 2656: case 2657: case 2658: case 2659: case 2660: case 2796: case 2797: case 2798: case 2799: case 2800: case 2801: case 2802: case 2803: case 2804: case 2940: case 2941: case 2942: case 2943: case 2944: case 2945: case 2946: case 2947: case 2948: case 3084: case 3085: case 3086: case 3087: case 3088: case 3089: case 3090: case 3091: case 3092: case 3228: case 3229: case 3230: case 3231: case 3232: case 3233: case 3234: case 3235: case 3236: return 2; case 2085: case 2086: case 2087: case 2088: case 2089: case 2090: case 2091: case 2092: case 2093: case 2229: case 2230: case 2231: case 2232: case 2233: case 2234: case 2235: case 2236: case 2237: case 2373: case 2374: case 2375: case 2376: case 2377: case 2378: case 2379: case 2380: case 2381: case 2517: case 2518: case 2519: case 2520: case 2521: case 2522: case 2523: case 2524: case 2525: case 2661: case 2662: case 2663: case 2664: case 2665: case 2666: case 2667: case 2668: case 2669: case 2805: case 2806: case 2807: case 2808: case 2809: case 2810: case 2811: case 2812: case 2813: case 2949: case 2950: case 2951: case 2952: case 2953: case 2954: case 2955: case 2956: case 2957: case 3093: case 3094: case 3095: case 3096: case 3097: case 3098: case 3099: case 3100: case 3101: case 3237: case 3238: case 3239: case 3240: case 3241: case 3242: case 3243: case 3244: case 3245: return 3; case 2094: case 2095: case 2096: case 2097: case 2098: case 2099: case 2100: case 2101: case 2102: case 2238: case 2239: case 2240: case 2241: case 2242: case 2243: case 2244: case 2245: case 2246: case 2382: case 2383: case 2384: case 2385: case 2386: case 2387: case 2388: case 2389: case 2390: case 2526: case 2527: case 2528: case 2529: case 2530: case 2531: case 2532: case 2533: case 2534: case 2670: case 2671: case 2672: case 2673: case 2674: case 2675: case 2676: case 2677: case 2678: case 2814: case 2815: case 2816: case 2817: case 2818: case 2819: case 2820: case 2821: case 2822: case 2958: case 2959: case 2960: case 2961: case 2962: case 2963: case 2964: case 2965: case 2966: case 3102: case 3103: case 3104: case 3105: case 3106: case 3107: case 3108: case 3109: case 3110: case 3246: case 3247: case 3248: case 3249: case 3250: case 3251: case 3252: case 3253: case 3254: return 4; case 2103: case 2104: case 2105: case 2106: case 2107: case 2108: case 2109: case 2110: case 2111: case 2247: case 2248: case 2249: case 2250: case 2251: case 2252: case 2253: case 2254: case 2255: case 2391: case 2392: case 2393: case 2394: case 2395: case 2396: case 2397: case 2398: case 2399: case 2535: case 2536: case 2537: case 2538: case 2539: case 2540: case 2541: case 2542: case 2543: case 2679: case 2680: case 2681: case 2682: case 2683: case 2684: case 2685: case 2686: case 2687: case 2823: case 2824: case 2825: case 2826: case 2827: case 2828: case 2829: case 2830: case 2831: case 2967: case 2968: case 2969: case 2970: case 2971: case 2972: case 2973: case 2974: case 2975: case 3111: case 3112: case 3113: case 3114: case 3115: case 3116: case 3117: case 3118: case 3119: case 3255: case 3256: case 3257: case 3258: case 3259: case 3260: case 3261: case 3262: case 3263: return 5; case 2112: case 2113: case 2114: case 2115: case 2116: case 2117: case 2118: case 2119: case 2120: case 2256: case 2257: case 2258: case 2259: case 2260: case 2261: case 2262: case 2263: case 2264: case 2400: case 2401: case 2402: case 2403: case 2404: case 2405: case 2406: case 2407: case 2408: case 2544: case 2545: case 2546: case 2547: case 2548: case 2549: case 2550: case 2551: case 2552: case 2688: case 2689: case 2690: case 2691: case 2692: case 2693: case 2694: case 2695: case 2696: case 2832: case 2833: case 2834: case 2835: case 2836: case 2837: case 2838: case 2839: case 2840: case 2976: case 2977: case 2978: case 2979: case 2980: case 2981: case 2982: case 2983: case 2984: case 3120: case 3121: case 3122: case 3123: case 3124: case 3125: case 3126: case 3127: case 3128: case 3264: case 3265: case 3266: case 3267: case 3268: case 3269: case 3270: case 3271: case 3272: return 6; case 2121: case 2122: case 2123: case 2124: case 2125: case 2126: case 2127: case 2128: case 2129: case 2265: case 2266: case 2267: case 2268: case 2269: case 2270: case 2271: case 2272: case 2273: case 2409: case 2410: case 2411: case 2412: case 2413: case 2414: case 2415: case 2416: case 2417: case 2553: case 2554: case 2555: case 2556: case 2557: case 2558: case 2559: case 2560: case 2561: case 2697: case 2698: case 2699: case 2700: case 2701: case 2702: case 2703: case 2704: case 2705: case 2841: case 2842: case 2843: case 2844: case 2845: case 2846: case 2847: case 2848: case 2849: case 2985: case 2986: case 2987: case 2988: case 2989: case 2990: case 2991: case 2992: case 2993: case 3129: case 3130: case 3131: case 3132: case 3133: case 3134: case 3135: case 3136: case 3137: case 3273: case 3274: case 3275: case 3276: case 3277: case 3278: case 3279: case 3280: case 3281: return 7; case 2130: case 2131: case 2132: case 2133: case 2134: case 2135: case 2136: case 2137: case 2138: case 2274: case 2275: case 2276: case 2277: case 2278: case 2279: case 2280: case 2281: case 2282: case 2418: case 2419: case 2420: case 2421: case 2422: case 2423: case 2424: case 2425: case 2426: case 2562: case 2563: case 2564: case 2565: case 2566: case 2567: case 2568: case 2569: case 2570: case 2706: case 2707: case 2708: case 2709: case 2710: case 2711: case 2712: case 2713: case 2714: case 2850: case 2851: case 2852: case 2853: case 2854: case 2855: case 2856: case 2857: case 2858: case 2994: case 2995: case 2996: case 2997: case 2998: case 2999: case 3000: case 3001: case 3002: case 3138: case 3139: case 3140: case 3141: case 3142: case 3143: case 3144: case 3145: case 3146: case 3282: case 3283: case 3284: case 3285: case 3286: case 3287: case 3288: case 3289: case 3290: return 8; default: return 9; } } enum South South(const BlockState Block) { switch (Block.ID) { case 2064: case 2065: case 2066: case 2073: case 2074: case 2075: case 2082: case 2083: case 2084: case 2091: case 2092: case 2093: case 2100: case 2101: case 2102: case 2109: case 2110: case 2111: case 2118: case 2119: case 2120: case 2127: case 2128: case 2129: case 2136: case 2137: case 2138: case 2145: case 2146: case 2147: case 2154: case 2155: case 2156: case 2163: case 2164: case 2165: case 2172: case 2173: case 2174: case 2181: case 2182: case 2183: case 2190: case 2191: case 2192: case 2199: case 2200: case 2201: case 2208: case 2209: case 2210: case 2217: case 2218: case 2219: case 2226: case 2227: case 2228: case 2235: case 2236: case 2237: case 2244: case 2245: case 2246: case 2253: case 2254: case 2255: case 2262: case 2263: case 2264: case 2271: case 2272: case 2273: case 2280: case 2281: case 2282: case 2289: case 2290: case 2291: case 2298: case 2299: case 2300: case 2307: case 2308: case 2309: case 2316: case 2317: case 2318: case 2325: case 2326: case 2327: case 2334: case 2335: case 2336: case 2343: case 2344: case 2345: case 2352: case 2353: case 2354: case 2361: case 2362: case 2363: case 2370: case 2371: case 2372: case 2379: case 2380: case 2381: case 2388: case 2389: case 2390: case 2397: case 2398: case 2399: case 2406: case 2407: case 2408: case 2415: case 2416: case 2417: case 2424: case 2425: case 2426: case 2433: case 2434: case 2435: case 2442: case 2443: case 2444: case 2451: case 2452: case 2453: case 2460: case 2461: case 2462: case 2469: case 2470: case 2471: case 2478: case 2479: case 2480: case 2487: case 2488: case 2489: case 2496: case 2497: case 2498: case 2505: case 2506: case 2507: case 2514: case 2515: case 2516: case 2523: case 2524: case 2525: case 2532: case 2533: case 2534: case 2541: case 2542: case 2543: case 2550: case 2551: case 2552: case 2559: case 2560: case 2561: case 2568: case 2569: case 2570: case 2577: case 2578: case 2579: case 2586: case 2587: case 2588: case 2595: case 2596: case 2597: case 2604: case 2605: case 2606: case 2613: case 2614: case 2615: case 2622: case 2623: case 2624: case 2631: case 2632: case 2633: case 2640: case 2641: case 2642: case 2649: case 2650: case 2651: case 2658: case 2659: case 2660: case 2667: case 2668: case 2669: case 2676: case 2677: case 2678: case 2685: case 2686: case 2687: case 2694: case 2695: case 2696: case 2703: case 2704: case 2705: case 2712: case 2713: case 2714: case 2721: case 2722: case 2723: case 2730: case 2731: case 2732: case 2739: case 2740: case 2741: case 2748: case 2749: case 2750: case 2757: case 2758: case 2759: case 2766: case 2767: case 2768: case 2775: case 2776: case 2777: case 2784: case 2785: case 2786: case 2793: case 2794: case 2795: case 2802: case 2803: case 2804: case 2811: case 2812: case 2813: case 2820: case 2821: case 2822: case 2829: case 2830: case 2831: case 2838: case 2839: case 2840: case 2847: case 2848: case 2849: case 2856: case 2857: case 2858: case 2865: case 2866: case 2867: case 2874: case 2875: case 2876: case 2883: case 2884: case 2885: case 2892: case 2893: case 2894: case 2901: case 2902: case 2903: case 2910: case 2911: case 2912: case 2919: case 2920: case 2921: case 2928: case 2929: case 2930: case 2937: case 2938: case 2939: case 2946: case 2947: case 2948: case 2955: case 2956: case 2957: case 2964: case 2965: case 2966: case 2973: case 2974: case 2975: case 2982: case 2983: case 2984: case 2991: case 2992: case 2993: case 3000: case 3001: case 3002: case 3009: case 3010: case 3011: case 3018: case 3019: case 3020: case 3027: case 3028: case 3029: case 3036: case 3037: case 3038: case 3045: case 3046: case 3047: case 3054: case 3055: case 3056: case 3063: case 3064: case 3065: case 3072: case 3073: case 3074: case 3081: case 3082: case 3083: case 3090: case 3091: case 3092: case 3099: case 3100: case 3101: case 3108: case 3109: case 3110: case 3117: case 3118: case 3119: case 3126: case 3127: case 3128: case 3135: case 3136: case 3137: case 3144: case 3145: case 3146: case 3153: case 3154: case 3155: case 3162: case 3163: case 3164: case 3171: case 3172: case 3173: case 3180: case 3181: case 3182: case 3189: case 3190: case 3191: case 3198: case 3199: case 3200: case 3207: case 3208: case 3209: case 3216: case 3217: case 3218: case 3225: case 3226: case 3227: case 3234: case 3235: case 3236: case 3243: case 3244: case 3245: case 3252: case 3253: case 3254: case 3261: case 3262: case 3263: case 3270: case 3271: case 3272: case 3279: case 3280: case 3281: case 3288: case 3289: case 3290: case 3297: case 3298: case 3299: case 3306: case 3307: case 3308: case 3315: case 3316: case 3317: case 3324: case 3325: case 3326: case 3333: case 3334: case 3335: case 3342: case 3343: case 3344: case 3351: case 3352: case 3353: return South::None; case 2061: case 2062: case 2063: case 2070: case 2071: case 2072: case 2079: case 2080: case 2081: case 2088: case 2089: case 2090: case 2097: case 2098: case 2099: case 2106: case 2107: case 2108: case 2115: case 2116: case 2117: case 2124: case 2125: case 2126: case 2133: case 2134: case 2135: case 2142: case 2143: case 2144: case 2151: case 2152: case 2153: case 2160: case 2161: case 2162: case 2169: case 2170: case 2171: case 2178: case 2179: case 2180: case 2187: case 2188: case 2189: case 2196: case 2197: case 2198: case 2205: case 2206: case 2207: case 2214: case 2215: case 2216: case 2223: case 2224: case 2225: case 2232: case 2233: case 2234: case 2241: case 2242: case 2243: case 2250: case 2251: case 2252: case 2259: case 2260: case 2261: case 2268: case 2269: case 2270: case 2277: case 2278: case 2279: case 2286: case 2287: case 2288: case 2295: case 2296: case 2297: case 2304: case 2305: case 2306: case 2313: case 2314: case 2315: case 2322: case 2323: case 2324: case 2331: case 2332: case 2333: case 2340: case 2341: case 2342: case 2349: case 2350: case 2351: case 2358: case 2359: case 2360: case 2367: case 2368: case 2369: case 2376: case 2377: case 2378: case 2385: case 2386: case 2387: case 2394: case 2395: case 2396: case 2403: case 2404: case 2405: case 2412: case 2413: case 2414: case 2421: case 2422: case 2423: case 2430: case 2431: case 2432: case 2439: case 2440: case 2441: case 2448: case 2449: case 2450: case 2457: case 2458: case 2459: case 2466: case 2467: case 2468: case 2475: case 2476: case 2477: case 2484: case 2485: case 2486: case 2493: case 2494: case 2495: case 2502: case 2503: case 2504: case 2511: case 2512: case 2513: case 2520: case 2521: case 2522: case 2529: case 2530: case 2531: case 2538: case 2539: case 2540: case 2547: case 2548: case 2549: case 2556: case 2557: case 2558: case 2565: case 2566: case 2567: case 2574: case 2575: case 2576: case 2583: case 2584: case 2585: case 2592: case 2593: case 2594: case 2601: case 2602: case 2603: case 2610: case 2611: case 2612: case 2619: case 2620: case 2621: case 2628: case 2629: case 2630: case 2637: case 2638: case 2639: case 2646: case 2647: case 2648: case 2655: case 2656: case 2657: case 2664: case 2665: case 2666: case 2673: case 2674: case 2675: case 2682: case 2683: case 2684: case 2691: case 2692: case 2693: case 2700: case 2701: case 2702: case 2709: case 2710: case 2711: case 2718: case 2719: case 2720: case 2727: case 2728: case 2729: case 2736: case 2737: case 2738: case 2745: case 2746: case 2747: case 2754: case 2755: case 2756: case 2763: case 2764: case 2765: case 2772: case 2773: case 2774: case 2781: case 2782: case 2783: case 2790: case 2791: case 2792: case 2799: case 2800: case 2801: case 2808: case 2809: case 2810: case 2817: case 2818: case 2819: case 2826: case 2827: case 2828: case 2835: case 2836: case 2837: case 2844: case 2845: case 2846: case 2853: case 2854: case 2855: case 2862: case 2863: case 2864: case 2871: case 2872: case 2873: case 2880: case 2881: case 2882: case 2889: case 2890: case 2891: case 2898: case 2899: case 2900: case 2907: case 2908: case 2909: case 2916: case 2917: case 2918: case 2925: case 2926: case 2927: case 2934: case 2935: case 2936: case 2943: case 2944: case 2945: case 2952: case 2953: case 2954: case 2961: case 2962: case 2963: case 2970: case 2971: case 2972: case 2979: case 2980: case 2981: case 2988: case 2989: case 2990: case 2997: case 2998: case 2999: case 3006: case 3007: case 3008: case 3015: case 3016: case 3017: case 3024: case 3025: case 3026: case 3033: case 3034: case 3035: case 3042: case 3043: case 3044: case 3051: case 3052: case 3053: case 3060: case 3061: case 3062: case 3069: case 3070: case 3071: case 3078: case 3079: case 3080: case 3087: case 3088: case 3089: case 3096: case 3097: case 3098: case 3105: case 3106: case 3107: case 3114: case 3115: case 3116: case 3123: case 3124: case 3125: case 3132: case 3133: case 3134: case 3141: case 3142: case 3143: case 3150: case 3151: case 3152: case 3159: case 3160: case 3161: case 3168: case 3169: case 3170: case 3177: case 3178: case 3179: case 3186: case 3187: case 3188: case 3195: case 3196: case 3197: case 3204: case 3205: case 3206: case 3213: case 3214: case 3215: case 3222: case 3223: case 3224: case 3231: case 3232: case 3233: case 3240: case 3241: case 3242: case 3249: case 3250: case 3251: case 3258: case 3259: case 3260: case 3267: case 3268: case 3269: case 3276: case 3277: case 3278: case 3285: case 3286: case 3287: case 3294: case 3295: case 3296: case 3303: case 3304: case 3305: case 3312: case 3313: case 3314: case 3321: case 3322: case 3323: case 3330: case 3331: case 3332: case 3339: case 3340: case 3341: case 3348: case 3349: case 3350: return South::Side; default: return South::Up; } } enum West West(const BlockState Block) { switch (Block.ID) { case 2060: case 2063: case 2066: case 2069: case 2072: case 2075: case 2078: case 2081: case 2084: case 2087: case 2090: case 2093: case 2096: case 2099: case 2102: case 2105: case 2108: case 2111: case 2114: case 2117: case 2120: case 2123: case 2126: case 2129: case 2132: case 2135: case 2138: case 2141: case 2144: case 2147: case 2150: case 2153: case 2156: case 2159: case 2162: case 2165: case 2168: case 2171: case 2174: case 2177: case 2180: case 2183: case 2186: case 2189: case 2192: case 2195: case 2198: case 2201: case 2204: case 2207: case 2210: case 2213: case 2216: case 2219: case 2222: case 2225: case 2228: case 2231: case 2234: case 2237: case 2240: case 2243: case 2246: case 2249: case 2252: case 2255: case 2258: case 2261: case 2264: case 2267: case 2270: case 2273: case 2276: case 2279: case 2282: case 2285: case 2288: case 2291: case 2294: case 2297: case 2300: case 2303: case 2306: case 2309: case 2312: case 2315: case 2318: case 2321: case 2324: case 2327: case 2330: case 2333: case 2336: case 2339: case 2342: case 2345: case 2348: case 2351: case 2354: case 2357: case 2360: case 2363: case 2366: case 2369: case 2372: case 2375: case 2378: case 2381: case 2384: case 2387: case 2390: case 2393: case 2396: case 2399: case 2402: case 2405: case 2408: case 2411: case 2414: case 2417: case 2420: case 2423: case 2426: case 2429: case 2432: case 2435: case 2438: case 2441: case 2444: case 2447: case 2450: case 2453: case 2456: case 2459: case 2462: case 2465: case 2468: case 2471: case 2474: case 2477: case 2480: case 2483: case 2486: case 2489: case 2492: case 2495: case 2498: case 2501: case 2504: case 2507: case 2510: case 2513: case 2516: case 2519: case 2522: case 2525: case 2528: case 2531: case 2534: case 2537: case 2540: case 2543: case 2546: case 2549: case 2552: case 2555: case 2558: case 2561: case 2564: case 2567: case 2570: case 2573: case 2576: case 2579: case 2582: case 2585: case 2588: case 2591: case 2594: case 2597: case 2600: case 2603: case 2606: case 2609: case 2612: case 2615: case 2618: case 2621: case 2624: case 2627: case 2630: case 2633: case 2636: case 2639: case 2642: case 2645: case 2648: case 2651: case 2654: case 2657: case 2660: case 2663: case 2666: case 2669: case 2672: case 2675: case 2678: case 2681: case 2684: case 2687: case 2690: case 2693: case 2696: case 2699: case 2702: case 2705: case 2708: case 2711: case 2714: case 2717: case 2720: case 2723: case 2726: case 2729: case 2732: case 2735: case 2738: case 2741: case 2744: case 2747: case 2750: case 2753: case 2756: case 2759: case 2762: case 2765: case 2768: case 2771: case 2774: case 2777: case 2780: case 2783: case 2786: case 2789: case 2792: case 2795: case 2798: case 2801: case 2804: case 2807: case 2810: case 2813: case 2816: case 2819: case 2822: case 2825: case 2828: case 2831: case 2834: case 2837: case 2840: case 2843: case 2846: case 2849: case 2852: case 2855: case 2858: case 2861: case 2864: case 2867: case 2870: case 2873: case 2876: case 2879: case 2882: case 2885: case 2888: case 2891: case 2894: case 2897: case 2900: case 2903: case 2906: case 2909: case 2912: case 2915: case 2918: case 2921: case 2924: case 2927: case 2930: case 2933: case 2936: case 2939: case 2942: case 2945: case 2948: case 2951: case 2954: case 2957: case 2960: case 2963: case 2966: case 2969: case 2972: case 2975: case 2978: case 2981: case 2984: case 2987: case 2990: case 2993: case 2996: case 2999: case 3002: case 3005: case 3008: case 3011: case 3014: case 3017: case 3020: case 3023: case 3026: case 3029: case 3032: case 3035: case 3038: case 3041: case 3044: case 3047: case 3050: case 3053: case 3056: case 3059: case 3062: case 3065: case 3068: case 3071: case 3074: case 3077: case 3080: case 3083: case 3086: case 3089: case 3092: case 3095: case 3098: case 3101: case 3104: case 3107: case 3110: case 3113: case 3116: case 3119: case 3122: case 3125: case 3128: case 3131: case 3134: case 3137: case 3140: case 3143: case 3146: case 3149: case 3152: case 3155: case 3158: case 3161: case 3164: case 3167: case 3170: case 3173: case 3176: case 3179: case 3182: case 3185: case 3188: case 3191: case 3194: case 3197: case 3200: case 3203: case 3206: case 3209: case 3212: case 3215: case 3218: case 3221: case 3224: case 3227: case 3230: case 3233: case 3236: case 3239: case 3242: case 3245: case 3248: case 3251: case 3254: case 3257: case 3260: case 3263: case 3266: case 3269: case 3272: case 3275: case 3278: case 3281: case 3284: case 3287: case 3290: case 3293: case 3296: case 3299: case 3302: case 3305: case 3308: case 3311: case 3314: case 3317: case 3320: case 3323: case 3326: case 3329: case 3332: case 3335: case 3338: case 3341: case 3344: case 3347: case 3350: case 3353: return West::None; case 2059: case 2062: case 2065: case 2068: case 2071: case 2074: case 2077: case 2080: case 2083: case 2086: case 2089: case 2092: case 2095: case 2098: case 2101: case 2104: case 2107: case 2110: case 2113: case 2116: case 2119: case 2122: case 2125: case 2128: case 2131: case 2134: case 2137: case 2140: case 2143: case 2146: case 2149: case 2152: case 2155: case 2158: case 2161: case 2164: case 2167: case 2170: case 2173: case 2176: case 2179: case 2182: case 2185: case 2188: case 2191: case 2194: case 2197: case 2200: case 2203: case 2206: case 2209: case 2212: case 2215: case 2218: case 2221: case 2224: case 2227: case 2230: case 2233: case 2236: case 2239: case 2242: case 2245: case 2248: case 2251: case 2254: case 2257: case 2260: case 2263: case 2266: case 2269: case 2272: case 2275: case 2278: case 2281: case 2284: case 2287: case 2290: case 2293: case 2296: case 2299: case 2302: case 2305: case 2308: case 2311: case 2314: case 2317: case 2320: case 2323: case 2326: case 2329: case 2332: case 2335: case 2338: case 2341: case 2344: case 2347: case 2350: case 2353: case 2356: case 2359: case 2362: case 2365: case 2368: case 2371: case 2374: case 2377: case 2380: case 2383: case 2386: case 2389: case 2392: case 2395: case 2398: case 2401: case 2404: case 2407: case 2410: case 2413: case 2416: case 2419: case 2422: case 2425: case 2428: case 2431: case 2434: case 2437: case 2440: case 2443: case 2446: case 2449: case 2452: case 2455: case 2458: case 2461: case 2464: case 2467: case 2470: case 2473: case 2476: case 2479: case 2482: case 2485: case 2488: case 2491: case 2494: case 2497: case 2500: case 2503: case 2506: case 2509: case 2512: case 2515: case 2518: case 2521: case 2524: case 2527: case 2530: case 2533: case 2536: case 2539: case 2542: case 2545: case 2548: case 2551: case 2554: case 2557: case 2560: case 2563: case 2566: case 2569: case 2572: case 2575: case 2578: case 2581: case 2584: case 2587: case 2590: case 2593: case 2596: case 2599: case 2602: case 2605: case 2608: case 2611: case 2614: case 2617: case 2620: case 2623: case 2626: case 2629: case 2632: case 2635: case 2638: case 2641: case 2644: case 2647: case 2650: case 2653: case 2656: case 2659: case 2662: case 2665: case 2668: case 2671: case 2674: case 2677: case 2680: case 2683: case 2686: case 2689: case 2692: case 2695: case 2698: case 2701: case 2704: case 2707: case 2710: case 2713: case 2716: case 2719: case 2722: case 2725: case 2728: case 2731: case 2734: case 2737: case 2740: case 2743: case 2746: case 2749: case 2752: case 2755: case 2758: case 2761: case 2764: case 2767: case 2770: case 2773: case 2776: case 2779: case 2782: case 2785: case 2788: case 2791: case 2794: case 2797: case 2800: case 2803: case 2806: case 2809: case 2812: case 2815: case 2818: case 2821: case 2824: case 2827: case 2830: case 2833: case 2836: case 2839: case 2842: case 2845: case 2848: case 2851: case 2854: case 2857: case 2860: case 2863: case 2866: case 2869: case 2872: case 2875: case 2878: case 2881: case 2884: case 2887: case 2890: case 2893: case 2896: case 2899: case 2902: case 2905: case 2908: case 2911: case 2914: case 2917: case 2920: case 2923: case 2926: case 2929: case 2932: case 2935: case 2938: case 2941: case 2944: case 2947: case 2950: case 2953: case 2956: case 2959: case 2962: case 2965: case 2968: case 2971: case 2974: case 2977: case 2980: case 2983: case 2986: case 2989: case 2992: case 2995: case 2998: case 3001: case 3004: case 3007: case 3010: case 3013: case 3016: case 3019: case 3022: case 3025: case 3028: case 3031: case 3034: case 3037: case 3040: case 3043: case 3046: case 3049: case 3052: case 3055: case 3058: case 3061: case 3064: case 3067: case 3070: case 3073: case 3076: case 3079: case 3082: case 3085: case 3088: case 3091: case 3094: case 3097: case 3100: case 3103: case 3106: case 3109: case 3112: case 3115: case 3118: case 3121: case 3124: case 3127: case 3130: case 3133: case 3136: case 3139: case 3142: case 3145: case 3148: case 3151: case 3154: case 3157: case 3160: case 3163: case 3166: case 3169: case 3172: case 3175: case 3178: case 3181: case 3184: case 3187: case 3190: case 3193: case 3196: case 3199: case 3202: case 3205: case 3208: case 3211: case 3214: case 3217: case 3220: case 3223: case 3226: case 3229: case 3232: case 3235: case 3238: case 3241: case 3244: case 3247: case 3250: case 3253: case 3256: case 3259: case 3262: case 3265: case 3268: case 3271: case 3274: case 3277: case 3280: case 3283: case 3286: case 3289: case 3292: case 3295: case 3298: case 3301: case 3304: case 3307: case 3310: case 3313: case 3316: case 3319: case 3322: case 3325: case 3328: case 3331: case 3334: case 3337: case 3340: case 3343: case 3346: case 3349: case 3352: return West::Side; default: return West::Up; } } } namespace Repeater { BlockState Repeater() { return 4034; } unsigned char Delay(const BlockState Block) { switch (Block.ID) { case 4031: case 4032: case 4033: case 4034: case 4035: case 4036: case 4037: case 4038: case 4039: case 4040: case 4041: case 4042: case 4043: case 4044: case 4045: case 4046: return 1; case 4047: case 4048: case 4049: case 4050: case 4051: case 4052: case 4053: case 4054: case 4055: case 4056: case 4057: case 4058: case 4059: case 4060: case 4061: case 4062: return 2; case 4063: case 4064: case 4065: case 4066: case 4067: case 4068: case 4069: case 4070: case 4071: case 4072: case 4073: case 4074: case 4075: case 4076: case 4077: case 4078: return 3; default: return 4; } } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 4039: case 4040: case 4041: case 4042: case 4055: case 4056: case 4057: case 4058: case 4071: case 4072: case 4073: case 4074: case 4087: case 4088: case 4089: case 4090: return eBlockFace::BLOCK_FACE_XM; case 4043: case 4044: case 4045: case 4046: case 4059: case 4060: case 4061: case 4062: case 4075: case 4076: case 4077: case 4078: case 4091: case 4092: case 4093: case 4094: return eBlockFace::BLOCK_FACE_XP; case 4031: case 4032: case 4033: case 4034: case 4047: case 4048: case 4049: case 4050: case 4063: case 4064: case 4065: case 4066: case 4079: case 4080: case 4081: case 4082: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } bool Locked(const BlockState Block) { switch (Block.ID) { case 4033: case 4034: case 4037: case 4038: case 4041: case 4042: case 4045: case 4046: case 4049: case 4050: case 4053: case 4054: case 4057: case 4058: case 4061: case 4062: case 4065: case 4066: case 4069: case 4070: case 4073: case 4074: case 4077: case 4078: case 4081: case 4082: case 4085: case 4086: case 4089: case 4090: case 4093: case 4094: return false; default: return true; } } bool Powered(const BlockState Block) { switch (Block.ID) { case 4032: case 4034: case 4036: case 4038: case 4040: case 4042: case 4044: case 4046: case 4048: case 4050: case 4052: case 4054: case 4056: case 4058: case 4060: case 4062: case 4064: case 4066: case 4068: case 4070: case 4072: case 4074: case 4076: case 4078: case 4080: case 4082: case 4084: case 4086: case 4088: case 4090: case 4092: case 4094: return false; default: return true; } } } namespace RepeatingCommandBlock { BlockState RepeatingCommandBlock() { return 9231; } bool Conditional(const BlockState Block) { switch (Block.ID) { case 9231: case 9232: case 9233: case 9234: case 9235: case 9236: return false; default: return true; } } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 9228: case 9234: return eBlockFace::BLOCK_FACE_XM; case 9226: case 9232: return eBlockFace::BLOCK_FACE_XP; case 9230: case 9236: return eBlockFace::BLOCK_FACE_YM; case 9229: case 9235: return eBlockFace::BLOCK_FACE_YP; case 9225: case 9231: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace RespawnAnchor { BlockState RespawnAnchor() { return 15829; } unsigned char Charges(const BlockState Block) { switch (Block.ID) { case 15829: return 0; case 15830: return 1; case 15831: return 2; case 15832: return 3; default: return 4; } } } namespace RoseBush { BlockState RoseBush() { return 7890; } enum Half Half(const BlockState Block) { switch (Block.ID) { case 7890: return Half::Lower; default: return Half::Upper; } } } namespace Sand { } namespace Sandstone { } namespace SandstoneSlab { BlockState SandstoneSlab() { return 8351; } enum Type Type(const BlockState Block) { switch (Block.ID) { case 8351: return Type::Bottom; case 8353: return Type::Double; default: return Type::Top; } } } namespace SandstoneStairs { BlockState SandstoneStairs() { return 5181; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 5211: case 5213: case 5215: case 5217: case 5219: case 5221: case 5223: case 5225: case 5227: case 5229: return eBlockFace::BLOCK_FACE_XM; case 5231: case 5233: case 5235: case 5237: case 5239: case 5241: case 5243: case 5245: case 5247: case 5249: return eBlockFace::BLOCK_FACE_XP; case 5171: case 5173: case 5175: case 5177: case 5179: case 5181: case 5183: case 5185: case 5187: case 5189: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } enum Half Half(const BlockState Block) { switch (Block.ID) { case 5181: case 5183: case 5185: case 5187: case 5189: case 5201: case 5203: case 5205: case 5207: case 5209: case 5221: case 5223: case 5225: case 5227: case 5229: case 5241: case 5243: case 5245: case 5247: case 5249: return Half::Bottom; default: return Half::Top; } } enum Shape Shape(const BlockState Block) { switch (Block.ID) { case 5173: case 5183: case 5193: case 5203: case 5213: case 5223: case 5233: case 5243: return Shape::InnerLeft; case 5175: case 5185: case 5195: case 5205: case 5215: case 5225: case 5235: case 5245: return Shape::InnerRight; case 5177: case 5187: case 5197: case 5207: case 5217: case 5227: case 5237: case 5247: return Shape::OuterLeft; case 5179: case 5189: case 5199: case 5209: case 5219: case 5229: case 5239: case 5249: return Shape::OuterRight; default: return Shape::Straight; } } } namespace SandstoneWall { BlockState SandstoneWall() { return 13786; } enum East East(const BlockState Block) { switch (Block.ID) { case 13894: case 13895: case 13896: case 13900: case 13901: case 13902: case 13906: case 13907: case 13908: case 13912: case 13913: case 13914: case 13918: case 13919: case 13920: case 13924: case 13925: case 13926: case 13930: case 13931: case 13932: case 13936: case 13937: case 13938: case 13942: case 13943: case 13944: case 13948: case 13949: case 13950: case 13954: case 13955: case 13956: case 13960: case 13961: case 13962: case 13966: case 13967: case 13968: case 13972: case 13973: case 13974: case 13978: case 13979: case 13980: case 13984: case 13985: case 13986: case 13990: case 13991: case 13992: case 13996: case 13997: case 13998: return East::Low; case 13786: case 13787: case 13788: case 13792: case 13793: case 13794: case 13798: case 13799: case 13800: case 13804: case 13805: case 13806: case 13810: case 13811: case 13812: case 13816: case 13817: case 13818: case 13822: case 13823: case 13824: case 13828: case 13829: case 13830: case 13834: case 13835: case 13836: case 13840: case 13841: case 13842: case 13846: case 13847: case 13848: case 13852: case 13853: case 13854: case 13858: case 13859: case 13860: case 13864: case 13865: case 13866: case 13870: case 13871: case 13872: case 13876: case 13877: case 13878: case 13882: case 13883: case 13884: case 13888: case 13889: case 13890: return East::None; default: return East::Tall; } } enum North North(const BlockState Block) { switch (Block.ID) { case 13822: case 13823: case 13824: case 13828: case 13829: case 13830: case 13834: case 13835: case 13836: case 13840: case 13841: case 13842: case 13846: case 13847: case 13848: case 13852: case 13853: case 13854: case 13930: case 13931: case 13932: case 13936: case 13937: case 13938: case 13942: case 13943: case 13944: case 13948: case 13949: case 13950: case 13954: case 13955: case 13956: case 13960: case 13961: case 13962: case 14038: case 14039: case 14040: case 14044: case 14045: case 14046: case 14050: case 14051: case 14052: case 14056: case 14057: case 14058: case 14062: case 14063: case 14064: case 14068: case 14069: case 14070: return North::Low; case 13786: case 13787: case 13788: case 13792: case 13793: case 13794: case 13798: case 13799: case 13800: case 13804: case 13805: case 13806: case 13810: case 13811: case 13812: case 13816: case 13817: case 13818: case 13894: case 13895: case 13896: case 13900: case 13901: case 13902: case 13906: case 13907: case 13908: case 13912: case 13913: case 13914: case 13918: case 13919: case 13920: case 13924: case 13925: case 13926: case 14002: case 14003: case 14004: case 14008: case 14009: case 14010: case 14014: case 14015: case 14016: case 14020: case 14021: case 14022: case 14026: case 14027: case 14028: case 14032: case 14033: case 14034: return North::None; default: return North::Tall; } } enum South South(const BlockState Block) { switch (Block.ID) { case 13798: case 13799: case 13800: case 13804: case 13805: case 13806: case 13834: case 13835: case 13836: case 13840: case 13841: case 13842: case 13870: case 13871: case 13872: case 13876: case 13877: case 13878: case 13906: case 13907: case 13908: case 13912: case 13913: case 13914: case 13942: case 13943: case 13944: case 13948: case 13949: case 13950: case 13978: case 13979: case 13980: case 13984: case 13985: case 13986: case 14014: case 14015: case 14016: case 14020: case 14021: case 14022: case 14050: case 14051: case 14052: case 14056: case 14057: case 14058: case 14086: case 14087: case 14088: case 14092: case 14093: case 14094: return South::Low; case 13786: case 13787: case 13788: case 13792: case 13793: case 13794: case 13822: case 13823: case 13824: case 13828: case 13829: case 13830: case 13858: case 13859: case 13860: case 13864: case 13865: case 13866: case 13894: case 13895: case 13896: case 13900: case 13901: case 13902: case 13930: case 13931: case 13932: case 13936: case 13937: case 13938: case 13966: case 13967: case 13968: case 13972: case 13973: case 13974: case 14002: case 14003: case 14004: case 14008: case 14009: case 14010: case 14038: case 14039: case 14040: case 14044: case 14045: case 14046: case 14074: case 14075: case 14076: case 14080: case 14081: case 14082: return South::None; default: return South::Tall; } } bool Up(const BlockState Block) { switch (Block.ID) { case 13792: case 13793: case 13794: case 13804: case 13805: case 13806: case 13816: case 13817: case 13818: case 13828: case 13829: case 13830: case 13840: case 13841: case 13842: case 13852: case 13853: case 13854: case 13864: case 13865: case 13866: case 13876: case 13877: case 13878: case 13888: case 13889: case 13890: case 13900: case 13901: case 13902: case 13912: case 13913: case 13914: case 13924: case 13925: case 13926: case 13936: case 13937: case 13938: case 13948: case 13949: case 13950: case 13960: case 13961: case 13962: case 13972: case 13973: case 13974: case 13984: case 13985: case 13986: case 13996: case 13997: case 13998: case 14008: case 14009: case 14010: case 14020: case 14021: case 14022: case 14032: case 14033: case 14034: case 14044: case 14045: case 14046: case 14056: case 14057: case 14058: case 14068: case 14069: case 14070: case 14080: case 14081: case 14082: case 14092: case 14093: case 14094: case 14104: case 14105: case 14106: return false; default: return true; } } enum West West(const BlockState Block) { switch (Block.ID) { case 13787: case 13793: case 13799: case 13805: case 13811: case 13817: case 13823: case 13829: case 13835: case 13841: case 13847: case 13853: case 13859: case 13865: case 13871: case 13877: case 13883: case 13889: case 13895: case 13901: case 13907: case 13913: case 13919: case 13925: case 13931: case 13937: case 13943: case 13949: case 13955: case 13961: case 13967: case 13973: case 13979: case 13985: case 13991: case 13997: case 14003: case 14009: case 14015: case 14021: case 14027: case 14033: case 14039: case 14045: case 14051: case 14057: case 14063: case 14069: case 14075: case 14081: case 14087: case 14093: case 14099: case 14105: return West::Low; case 13786: case 13792: case 13798: case 13804: case 13810: case 13816: case 13822: case 13828: case 13834: case 13840: case 13846: case 13852: case 13858: case 13864: case 13870: case 13876: case 13882: case 13888: case 13894: case 13900: case 13906: case 13912: case 13918: case 13924: case 13930: case 13936: case 13942: case 13948: case 13954: case 13960: case 13966: case 13972: case 13978: case 13984: case 13990: case 13996: case 14002: case 14008: case 14014: case 14020: case 14026: case 14032: case 14038: case 14044: case 14050: case 14056: case 14062: case 14068: case 14074: case 14080: case 14086: case 14092: case 14098: case 14104: return West::None; default: return West::Tall; } } } namespace Scaffolding { BlockState Scaffolding() { return 14786; } bool Bottom(const BlockState Block) { switch (Block.ID) { case 14772: case 14774: case 14776: case 14778: case 14780: case 14782: case 14784: case 14786: return false; default: return true; } } unsigned char Distance(const BlockState Block) { switch (Block.ID) { case 14756: case 14772: return 0; case 14758: case 14774: return 1; case 14760: case 14776: return 2; case 14762: case 14778: return 3; case 14764: case 14780: return 4; case 14766: case 14782: return 5; case 14768: case 14784: return 6; default: return 7; } } } namespace SeaLantern { } namespace SeaPickle { BlockState SeaPickle() { return 9640; } unsigned char Pickles(const BlockState Block) { switch (Block.ID) { case 9641: return 1; case 9643: return 2; case 9645: return 3; default: return 4; } } } namespace Seagrass { } namespace Shroomlight { } namespace ShulkerBox { BlockState ShulkerBox() { return 9276; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 9275: return eBlockFace::BLOCK_FACE_XM; case 9273: return eBlockFace::BLOCK_FACE_XP; case 9277: return eBlockFace::BLOCK_FACE_YM; case 9276: return eBlockFace::BLOCK_FACE_YP; case 9272: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace SkeletonSkull { BlockState SkeletonSkull() { return 6490; } unsigned char Rotation(const BlockState Block) { switch (Block.ID) { case 6490: return 0; case 6491: return 1; case 6500: return 10; case 6501: return 11; case 6502: return 12; case 6503: return 13; case 6504: return 14; case 6505: return 15; case 6492: return 2; case 6493: return 3; case 6494: return 4; case 6495: return 5; case 6496: return 6; case 6497: return 7; case 6498: return 8; default: return 9; } } } namespace SkeletonWallSkull { BlockState SkeletonWallSkull() { return 6506; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 6508: return eBlockFace::BLOCK_FACE_XM; case 6509: return eBlockFace::BLOCK_FACE_XP; case 6506: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace SlimeBlock { } namespace SmithingTable { } namespace Smoker { BlockState Smoker() { return 14804; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 14807: case 14808: return eBlockFace::BLOCK_FACE_XM; case 14809: case 14810: return eBlockFace::BLOCK_FACE_XP; case 14803: case 14804: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } bool Lit(const BlockState Block) { switch (Block.ID) { case 14804: case 14806: case 14808: case 14810: return false; default: return true; } } } namespace SmoothQuartz { } namespace SmoothQuartzSlab { BlockState SmoothQuartzSlab() { return 10834; } enum Type Type(const BlockState Block) { switch (Block.ID) { case 10834: return Type::Bottom; case 10836: return Type::Double; default: return Type::Top; } } } namespace SmoothQuartzStairs { BlockState SmoothQuartzStairs() { return 10320; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 10350: case 10352: case 10354: case 10356: case 10358: case 10360: case 10362: case 10364: case 10366: case 10368: return eBlockFace::BLOCK_FACE_XM; case 10370: case 10372: case 10374: case 10376: case 10378: case 10380: case 10382: case 10384: case 10386: case 10388: return eBlockFace::BLOCK_FACE_XP; case 10310: case 10312: case 10314: case 10316: case 10318: case 10320: case 10322: case 10324: case 10326: case 10328: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } enum Half Half(const BlockState Block) { switch (Block.ID) { case 10320: case 10322: case 10324: case 10326: case 10328: case 10340: case 10342: case 10344: case 10346: case 10348: case 10360: case 10362: case 10364: case 10366: case 10368: case 10380: case 10382: case 10384: case 10386: case 10388: return Half::Bottom; default: return Half::Top; } } enum Shape Shape(const BlockState Block) { switch (Block.ID) { case 10312: case 10322: case 10332: case 10342: case 10352: case 10362: case 10372: case 10382: return Shape::InnerLeft; case 10314: case 10324: case 10334: case 10344: case 10354: case 10364: case 10374: case 10384: return Shape::InnerRight; case 10316: case 10326: case 10336: case 10346: case 10356: case 10366: case 10376: case 10386: return Shape::OuterLeft; case 10318: case 10328: case 10338: case 10348: case 10358: case 10368: case 10378: case 10388: return Shape::OuterRight; default: return Shape::Straight; } } } namespace SmoothRedSandstone { } namespace SmoothRedSandstoneSlab { BlockState SmoothRedSandstoneSlab() { return 10798; } enum Type Type(const BlockState Block) { switch (Block.ID) { case 10798: return Type::Bottom; case 10800: return Type::Double; default: return Type::Top; } } } namespace SmoothRedSandstoneStairs { BlockState SmoothRedSandstoneStairs() { return 9760; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 9790: case 9792: case 9794: case 9796: case 9798: case 9800: case 9802: case 9804: case 9806: case 9808: return eBlockFace::BLOCK_FACE_XM; case 9810: case 9812: case 9814: case 9816: case 9818: case 9820: case 9822: case 9824: case 9826: case 9828: return eBlockFace::BLOCK_FACE_XP; case 9750: case 9752: case 9754: case 9756: case 9758: case 9760: case 9762: case 9764: case 9766: case 9768: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } enum Half Half(const BlockState Block) { switch (Block.ID) { case 9760: case 9762: case 9764: case 9766: case 9768: case 9780: case 9782: case 9784: case 9786: case 9788: case 9800: case 9802: case 9804: case 9806: case 9808: case 9820: case 9822: case 9824: case 9826: case 9828: return Half::Bottom; default: return Half::Top; } } enum Shape Shape(const BlockState Block) { switch (Block.ID) { case 9752: case 9762: case 9772: case 9782: case 9792: case 9802: case 9812: case 9822: return Shape::InnerLeft; case 9754: case 9764: case 9774: case 9784: case 9794: case 9804: case 9814: case 9824: return Shape::InnerRight; case 9756: case 9766: case 9776: case 9786: case 9796: case 9806: case 9816: case 9826: return Shape::OuterLeft; case 9758: case 9768: case 9778: case 9788: case 9798: case 9808: case 9818: case 9828: return Shape::OuterRight; default: return Shape::Straight; } } } namespace SmoothSandstone { } namespace SmoothSandstoneSlab { BlockState SmoothSandstoneSlab() { return 10828; } enum Type Type(const BlockState Block) { switch (Block.ID) { case 10828: return Type::Bottom; case 10830: return Type::Double; default: return Type::Top; } } } namespace SmoothSandstoneStairs { BlockState SmoothSandstoneStairs() { return 10240; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 10270: case 10272: case 10274: case 10276: case 10278: case 10280: case 10282: case 10284: case 10286: case 10288: return eBlockFace::BLOCK_FACE_XM; case 10290: case 10292: case 10294: case 10296: case 10298: case 10300: case 10302: case 10304: case 10306: case 10308: return eBlockFace::BLOCK_FACE_XP; case 10230: case 10232: case 10234: case 10236: case 10238: case 10240: case 10242: case 10244: case 10246: case 10248: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } enum Half Half(const BlockState Block) { switch (Block.ID) { case 10240: case 10242: case 10244: case 10246: case 10248: case 10260: case 10262: case 10264: case 10266: case 10268: case 10280: case 10282: case 10284: case 10286: case 10288: case 10300: case 10302: case 10304: case 10306: case 10308: return Half::Bottom; default: return Half::Top; } } enum Shape Shape(const BlockState Block) { switch (Block.ID) { case 10232: case 10242: case 10252: case 10262: case 10272: case 10282: case 10292: case 10302: return Shape::InnerLeft; case 10234: case 10244: case 10254: case 10264: case 10274: case 10284: case 10294: case 10304: return Shape::InnerRight; case 10236: case 10246: case 10256: case 10266: case 10276: case 10286: case 10296: case 10306: return Shape::OuterLeft; case 10238: case 10248: case 10258: case 10268: case 10278: case 10288: case 10298: case 10308: return Shape::OuterRight; default: return Shape::Straight; } } } namespace SmoothStone { } namespace SmoothStoneSlab { BlockState SmoothStoneSlab() { return 8345; } enum Type Type(const BlockState Block) { switch (Block.ID) { case 8345: return Type::Bottom; case 8347: return Type::Double; default: return Type::Top; } } } namespace Snow { BlockState Snow() { return 3921; } unsigned char Layers(const BlockState Block) { switch (Block.ID) { case 3921: return 1; case 3922: return 2; case 3923: return 3; case 3924: return 4; case 3925: return 5; case 3926: return 6; case 3927: return 7; default: return 8; } } } namespace SnowBlock { } namespace SoulCampfire { BlockState SoulCampfire() { return 14925; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 14939: case 14941: case 14943: case 14945: return eBlockFace::BLOCK_FACE_XM; case 14947: case 14949: case 14951: case 14953: return eBlockFace::BLOCK_FACE_XP; case 14923: case 14925: case 14927: case 14929: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } bool Lit(const BlockState Block) { switch (Block.ID) { case 14927: case 14929: case 14935: case 14937: case 14943: case 14945: case 14951: case 14953: return false; default: return true; } } bool SignalFire(const BlockState Block) { switch (Block.ID) { case 14925: case 14929: case 14933: case 14937: case 14941: case 14945: case 14949: case 14953: return false; default: return true; } } } namespace SoulFire { } namespace SoulLantern { BlockState SoulLantern() { return 14889; } bool Hanging(const BlockState Block) { switch (Block.ID) { case 14889: return false; default: return true; } } } namespace SoulSand { } namespace SoulSoil { } namespace SoulTorch { } namespace SoulWallTorch { BlockState SoulWallTorch() { return 4009; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 4011: return eBlockFace::BLOCK_FACE_XM; case 4012: return eBlockFace::BLOCK_FACE_XP; case 4009: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace Spawner { } namespace Sponge { } namespace SpruceButton { BlockState SpruceButton() { return 6379; } enum Face Face(const BlockState Block) { switch (Block.ID) { case 6386: case 6387: case 6388: case 6389: case 6390: case 6391: case 6392: case 6393: return Face::Ceiling; case 6370: case 6371: case 6372: case 6373: case 6374: case 6375: case 6376: case 6377: return Face::Floor; default: return Face::Wall; } } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 6374: case 6375: case 6382: case 6383: case 6390: case 6391: return eBlockFace::BLOCK_FACE_XM; case 6376: case 6377: case 6384: case 6385: case 6392: case 6393: return eBlockFace::BLOCK_FACE_XP; case 6370: case 6371: case 6378: case 6379: case 6386: case 6387: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } bool Powered(const BlockState Block) { switch (Block.ID) { case 6371: case 6373: case 6375: case 6377: case 6379: case 6381: case 6383: case 6385: case 6387: case 6389: case 6391: case 6393: return false; default: return true; } } } namespace SpruceDoor { BlockState SpruceDoor() { return 8749; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 8770: case 8771: case 8772: case 8773: case 8774: case 8775: case 8776: case 8777: case 8778: case 8779: case 8780: case 8781: case 8782: case 8783: case 8784: case 8785: return eBlockFace::BLOCK_FACE_XM; case 8786: case 8787: case 8788: case 8789: case 8790: case 8791: case 8792: case 8793: case 8794: case 8795: case 8796: case 8797: case 8798: case 8799: case 8800: case 8801: return eBlockFace::BLOCK_FACE_XP; case 8738: case 8739: case 8740: case 8741: case 8742: case 8743: case 8744: case 8745: case 8746: case 8747: case 8748: case 8749: case 8750: case 8751: case 8752: case 8753: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } enum Half Half(const BlockState Block) { switch (Block.ID) { case 8746: case 8747: case 8748: case 8749: case 8750: case 8751: case 8752: case 8753: case 8762: case 8763: case 8764: case 8765: case 8766: case 8767: case 8768: case 8769: case 8778: case 8779: case 8780: case 8781: case 8782: case 8783: case 8784: case 8785: case 8794: case 8795: case 8796: case 8797: case 8798: case 8799: case 8800: case 8801: return Half::Lower; default: return Half::Upper; } } enum Hinge Hinge(const BlockState Block) { switch (Block.ID) { case 8738: case 8739: case 8740: case 8741: case 8746: case 8747: case 8748: case 8749: case 8754: case 8755: case 8756: case 8757: case 8762: case 8763: case 8764: case 8765: case 8770: case 8771: case 8772: case 8773: case 8778: case 8779: case 8780: case 8781: case 8786: case 8787: case 8788: case 8789: case 8794: case 8795: case 8796: case 8797: return Hinge::Left; default: return Hinge::Right; } } bool Open(const BlockState Block) { switch (Block.ID) { case 8740: case 8741: case 8744: case 8745: case 8748: case 8749: case 8752: case 8753: case 8756: case 8757: case 8760: case 8761: case 8764: case 8765: case 8768: case 8769: case 8772: case 8773: case 8776: case 8777: case 8780: case 8781: case 8784: case 8785: case 8788: case 8789: case 8792: case 8793: case 8796: case 8797: case 8800: case 8801: return false; default: return true; } } bool Powered(const BlockState Block) { switch (Block.ID) { case 8739: case 8741: case 8743: case 8745: case 8747: case 8749: case 8751: case 8753: case 8755: case 8757: case 8759: case 8761: case 8763: case 8765: case 8767: case 8769: case 8771: case 8773: case 8775: case 8777: case 8779: case 8781: case 8783: case 8785: case 8787: case 8789: case 8791: case 8793: case 8795: case 8797: case 8799: case 8801: return false; default: return true; } } } namespace SpruceFence { BlockState SpruceFence() { return 8609; } bool East(const BlockState Block) { switch (Block.ID) { case 8596: case 8597: case 8600: case 8601: case 8604: case 8605: case 8608: case 8609: return false; default: return true; } } bool North(const BlockState Block) { switch (Block.ID) { case 8588: case 8589: case 8592: case 8593: case 8604: case 8605: case 8608: case 8609: return false; default: return true; } } bool South(const BlockState Block) { switch (Block.ID) { case 8584: case 8585: case 8592: case 8593: case 8600: case 8601: case 8608: case 8609: return false; default: return true; } } bool West(const BlockState Block) { switch (Block.ID) { case 8581: case 8585: case 8589: case 8593: case 8597: case 8601: case 8605: case 8609: return false; default: return true; } } } namespace SpruceFenceGate { BlockState SpruceFenceGate() { return 8425; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 8434: case 8435: case 8436: case 8437: case 8438: case 8439: case 8440: case 8441: return eBlockFace::BLOCK_FACE_XM; case 8442: case 8443: case 8444: case 8445: case 8446: case 8447: case 8448: case 8449: return eBlockFace::BLOCK_FACE_XP; case 8418: case 8419: case 8420: case 8421: case 8422: case 8423: case 8424: case 8425: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } bool InWall(const BlockState Block) { switch (Block.ID) { case 8422: case 8423: case 8424: case 8425: case 8430: case 8431: case 8432: case 8433: case 8438: case 8439: case 8440: case 8441: case 8446: case 8447: case 8448: case 8449: return false; default: return true; } } bool Open(const BlockState Block) { switch (Block.ID) { case 8420: case 8421: case 8424: case 8425: case 8428: case 8429: case 8432: case 8433: case 8436: case 8437: case 8440: case 8441: case 8444: case 8445: case 8448: case 8449: return false; default: return true; } } bool Powered(const BlockState Block) { switch (Block.ID) { case 8419: case 8421: case 8423: case 8425: case 8427: case 8429: case 8431: case 8433: case 8435: case 8437: case 8439: case 8441: case 8443: case 8445: case 8447: case 8449: return false; default: return true; } } } namespace SpruceLeaves { BlockState SpruceLeaves() { return 172; } unsigned char Distance(const BlockState Block) { switch (Block.ID) { case 159: case 160: return 1; case 161: case 162: return 2; case 163: case 164: return 3; case 165: case 166: return 4; case 167: case 168: return 5; case 169: case 170: return 6; default: return 7; } } bool Persistent(const BlockState Block) { switch (Block.ID) { case 160: case 162: case 164: case 166: case 168: case 170: case 172: return false; default: return true; } } } namespace SpruceLog { BlockState SpruceLog() { return 77; } enum Axis Axis(const BlockState Block) { switch (Block.ID) { case 76: return Axis::X; case 77: return Axis::Y; default: return Axis::Z; } } } namespace SprucePlanks { } namespace SprucePressurePlate { BlockState SprucePressurePlate() { return 3876; } bool Powered(const BlockState Block) { switch (Block.ID) { case 3876: return false; default: return true; } } } namespace SpruceSapling { BlockState SpruceSapling() { return 23; } unsigned char Stage(const BlockState Block) { switch (Block.ID) { case 23: return 0; default: return 1; } } } namespace SpruceSign { BlockState SpruceSign() { return 3414; } unsigned char Rotation(const BlockState Block) { switch (Block.ID) { case 3414: return 0; case 3416: return 1; case 3434: return 10; case 3436: return 11; case 3438: return 12; case 3440: return 13; case 3442: return 14; case 3444: return 15; case 3418: return 2; case 3420: return 3; case 3422: return 4; case 3424: return 5; case 3426: return 6; case 3428: return 7; case 3430: return 8; default: return 9; } } } namespace SpruceSlab { BlockState SpruceSlab() { return 8309; } enum Type Type(const BlockState Block) { switch (Block.ID) { case 8309: return Type::Bottom; case 8311: return Type::Double; default: return Type::Top; } } } namespace SpruceStairs { BlockState SpruceStairs() { return 5415; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 5445: case 5447: case 5449: case 5451: case 5453: case 5455: case 5457: case 5459: case 5461: case 5463: return eBlockFace::BLOCK_FACE_XM; case 5465: case 5467: case 5469: case 5471: case 5473: case 5475: case 5477: case 5479: case 5481: case 5483: return eBlockFace::BLOCK_FACE_XP; case 5405: case 5407: case 5409: case 5411: case 5413: case 5415: case 5417: case 5419: case 5421: case 5423: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } enum Half Half(const BlockState Block) { switch (Block.ID) { case 5415: case 5417: case 5419: case 5421: case 5423: case 5435: case 5437: case 5439: case 5441: case 5443: case 5455: case 5457: case 5459: case 5461: case 5463: case 5475: case 5477: case 5479: case 5481: case 5483: return Half::Bottom; default: return Half::Top; } } enum Shape Shape(const BlockState Block) { switch (Block.ID) { case 5407: case 5417: case 5427: case 5437: case 5447: case 5457: case 5467: case 5477: return Shape::InnerLeft; case 5409: case 5419: case 5429: case 5439: case 5449: case 5459: case 5469: case 5479: return Shape::InnerRight; case 5411: case 5421: case 5431: case 5441: case 5451: case 5461: case 5471: case 5481: return Shape::OuterLeft; case 5413: case 5423: case 5433: case 5443: case 5453: case 5463: case 5473: case 5483: return Shape::OuterRight; default: return Shape::Straight; } } } namespace SpruceTrapdoor { BlockState SpruceTrapdoor() { return 4190; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 4208: case 4210: case 4212: case 4214: case 4216: case 4218: case 4220: case 4222: return eBlockFace::BLOCK_FACE_XM; case 4224: case 4226: case 4228: case 4230: case 4232: case 4234: case 4236: case 4238: return eBlockFace::BLOCK_FACE_XP; case 4176: case 4178: case 4180: case 4182: case 4184: case 4186: case 4188: case 4190: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } enum Half Half(const BlockState Block) { switch (Block.ID) { case 4184: case 4186: case 4188: case 4190: case 4200: case 4202: case 4204: case 4206: case 4216: case 4218: case 4220: case 4222: case 4232: case 4234: case 4236: case 4238: return Half::Bottom; default: return Half::Top; } } bool Open(const BlockState Block) { switch (Block.ID) { case 4180: case 4182: case 4188: case 4190: case 4196: case 4198: case 4204: case 4206: case 4212: case 4214: case 4220: case 4222: case 4228: case 4230: case 4236: case 4238: return false; default: return true; } } bool Powered(const BlockState Block) { switch (Block.ID) { case 4178: case 4182: case 4186: case 4190: case 4194: case 4198: case 4202: case 4206: case 4210: case 4214: case 4218: case 4222: case 4226: case 4230: case 4234: case 4238: return false; default: return true; } } } namespace SpruceWallSign { BlockState SpruceWallSign() { return 3744; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 3748: return eBlockFace::BLOCK_FACE_XM; case 3750: return eBlockFace::BLOCK_FACE_XP; case 3744: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace SpruceWood { BlockState SpruceWood() { return 113; } enum Axis Axis(const BlockState Block) { switch (Block.ID) { case 112: return Axis::X; case 113: return Axis::Y; default: return Axis::Z; } } } namespace StickyPiston { BlockState StickyPiston() { return 1335; } bool Extended(const BlockState Block) { switch (Block.ID) { case 1335: case 1336: case 1337: case 1338: case 1339: case 1340: return false; default: return true; } } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 1332: case 1338: return eBlockFace::BLOCK_FACE_XM; case 1330: case 1336: return eBlockFace::BLOCK_FACE_XP; case 1334: case 1340: return eBlockFace::BLOCK_FACE_YM; case 1333: case 1339: return eBlockFace::BLOCK_FACE_YP; case 1329: case 1335: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace Stone { } namespace StoneBrickSlab { BlockState StoneBrickSlab() { return 8381; } enum Type Type(const BlockState Block) { switch (Block.ID) { case 8381: return Type::Bottom; case 8383: return Type::Double; default: return Type::Top; } } } namespace StoneBrickStairs { BlockState StoneBrickStairs() { return 4943; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 4973: case 4975: case 4977: case 4979: case 4981: case 4983: case 4985: case 4987: case 4989: case 4991: return eBlockFace::BLOCK_FACE_XM; case 4993: case 4995: case 4997: case 4999: case 5001: case 5003: case 5005: case 5007: case 5009: case 5011: return eBlockFace::BLOCK_FACE_XP; case 4933: case 4935: case 4937: case 4939: case 4941: case 4943: case 4945: case 4947: case 4949: case 4951: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } enum Half Half(const BlockState Block) { switch (Block.ID) { case 4943: case 4945: case 4947: case 4949: case 4951: case 4963: case 4965: case 4967: case 4969: case 4971: case 4983: case 4985: case 4987: case 4989: case 4991: case 5003: case 5005: case 5007: case 5009: case 5011: return Half::Bottom; default: return Half::Top; } } enum Shape Shape(const BlockState Block) { switch (Block.ID) { case 4935: case 4945: case 4955: case 4965: case 4975: case 4985: case 4995: case 5005: return Shape::InnerLeft; case 4937: case 4947: case 4957: case 4967: case 4977: case 4987: case 4997: case 5007: return Shape::InnerRight; case 4939: case 4949: case 4959: case 4969: case 4979: case 4989: case 4999: case 5009: return Shape::OuterLeft; case 4941: case 4951: case 4961: case 4971: case 4981: case 4991: case 5001: case 5011: return Shape::OuterRight; default: return Shape::Straight; } } } namespace StoneBrickWall { BlockState StoneBrickWall() { return 12490; } enum East East(const BlockState Block) { switch (Block.ID) { case 12598: case 12599: case 12600: case 12604: case 12605: case 12606: case 12610: case 12611: case 12612: case 12616: case 12617: case 12618: case 12622: case 12623: case 12624: case 12628: case 12629: case 12630: case 12634: case 12635: case 12636: case 12640: case 12641: case 12642: case 12646: case 12647: case 12648: case 12652: case 12653: case 12654: case 12658: case 12659: case 12660: case 12664: case 12665: case 12666: case 12670: case 12671: case 12672: case 12676: case 12677: case 12678: case 12682: case 12683: case 12684: case 12688: case 12689: case 12690: case 12694: case 12695: case 12696: case 12700: case 12701: case 12702: return East::Low; case 12490: case 12491: case 12492: case 12496: case 12497: case 12498: case 12502: case 12503: case 12504: case 12508: case 12509: case 12510: case 12514: case 12515: case 12516: case 12520: case 12521: case 12522: case 12526: case 12527: case 12528: case 12532: case 12533: case 12534: case 12538: case 12539: case 12540: case 12544: case 12545: case 12546: case 12550: case 12551: case 12552: case 12556: case 12557: case 12558: case 12562: case 12563: case 12564: case 12568: case 12569: case 12570: case 12574: case 12575: case 12576: case 12580: case 12581: case 12582: case 12586: case 12587: case 12588: case 12592: case 12593: case 12594: return East::None; default: return East::Tall; } } enum North North(const BlockState Block) { switch (Block.ID) { case 12526: case 12527: case 12528: case 12532: case 12533: case 12534: case 12538: case 12539: case 12540: case 12544: case 12545: case 12546: case 12550: case 12551: case 12552: case 12556: case 12557: case 12558: case 12634: case 12635: case 12636: case 12640: case 12641: case 12642: case 12646: case 12647: case 12648: case 12652: case 12653: case 12654: case 12658: case 12659: case 12660: case 12664: case 12665: case 12666: case 12742: case 12743: case 12744: case 12748: case 12749: case 12750: case 12754: case 12755: case 12756: case 12760: case 12761: case 12762: case 12766: case 12767: case 12768: case 12772: case 12773: case 12774: return North::Low; case 12490: case 12491: case 12492: case 12496: case 12497: case 12498: case 12502: case 12503: case 12504: case 12508: case 12509: case 12510: case 12514: case 12515: case 12516: case 12520: case 12521: case 12522: case 12598: case 12599: case 12600: case 12604: case 12605: case 12606: case 12610: case 12611: case 12612: case 12616: case 12617: case 12618: case 12622: case 12623: case 12624: case 12628: case 12629: case 12630: case 12706: case 12707: case 12708: case 12712: case 12713: case 12714: case 12718: case 12719: case 12720: case 12724: case 12725: case 12726: case 12730: case 12731: case 12732: case 12736: case 12737: case 12738: return North::None; default: return North::Tall; } } enum South South(const BlockState Block) { switch (Block.ID) { case 12502: case 12503: case 12504: case 12508: case 12509: case 12510: case 12538: case 12539: case 12540: case 12544: case 12545: case 12546: case 12574: case 12575: case 12576: case 12580: case 12581: case 12582: case 12610: case 12611: case 12612: case 12616: case 12617: case 12618: case 12646: case 12647: case 12648: case 12652: case 12653: case 12654: case 12682: case 12683: case 12684: case 12688: case 12689: case 12690: case 12718: case 12719: case 12720: case 12724: case 12725: case 12726: case 12754: case 12755: case 12756: case 12760: case 12761: case 12762: case 12790: case 12791: case 12792: case 12796: case 12797: case 12798: return South::Low; case 12490: case 12491: case 12492: case 12496: case 12497: case 12498: case 12526: case 12527: case 12528: case 12532: case 12533: case 12534: case 12562: case 12563: case 12564: case 12568: case 12569: case 12570: case 12598: case 12599: case 12600: case 12604: case 12605: case 12606: case 12634: case 12635: case 12636: case 12640: case 12641: case 12642: case 12670: case 12671: case 12672: case 12676: case 12677: case 12678: case 12706: case 12707: case 12708: case 12712: case 12713: case 12714: case 12742: case 12743: case 12744: case 12748: case 12749: case 12750: case 12778: case 12779: case 12780: case 12784: case 12785: case 12786: return South::None; default: return South::Tall; } } bool Up(const BlockState Block) { switch (Block.ID) { case 12496: case 12497: case 12498: case 12508: case 12509: case 12510: case 12520: case 12521: case 12522: case 12532: case 12533: case 12534: case 12544: case 12545: case 12546: case 12556: case 12557: case 12558: case 12568: case 12569: case 12570: case 12580: case 12581: case 12582: case 12592: case 12593: case 12594: case 12604: case 12605: case 12606: case 12616: case 12617: case 12618: case 12628: case 12629: case 12630: case 12640: case 12641: case 12642: case 12652: case 12653: case 12654: case 12664: case 12665: case 12666: case 12676: case 12677: case 12678: case 12688: case 12689: case 12690: case 12700: case 12701: case 12702: case 12712: case 12713: case 12714: case 12724: case 12725: case 12726: case 12736: case 12737: case 12738: case 12748: case 12749: case 12750: case 12760: case 12761: case 12762: case 12772: case 12773: case 12774: case 12784: case 12785: case 12786: case 12796: case 12797: case 12798: case 12808: case 12809: case 12810: return false; default: return true; } } enum West West(const BlockState Block) { switch (Block.ID) { case 12491: case 12497: case 12503: case 12509: case 12515: case 12521: case 12527: case 12533: case 12539: case 12545: case 12551: case 12557: case 12563: case 12569: case 12575: case 12581: case 12587: case 12593: case 12599: case 12605: case 12611: case 12617: case 12623: case 12629: case 12635: case 12641: case 12647: case 12653: case 12659: case 12665: case 12671: case 12677: case 12683: case 12689: case 12695: case 12701: case 12707: case 12713: case 12719: case 12725: case 12731: case 12737: case 12743: case 12749: case 12755: case 12761: case 12767: case 12773: case 12779: case 12785: case 12791: case 12797: case 12803: case 12809: return West::Low; case 12490: case 12496: case 12502: case 12508: case 12514: case 12520: case 12526: case 12532: case 12538: case 12544: case 12550: case 12556: case 12562: case 12568: case 12574: case 12580: case 12586: case 12592: case 12598: case 12604: case 12610: case 12616: case 12622: case 12628: case 12634: case 12640: case 12646: case 12652: case 12658: case 12664: case 12670: case 12676: case 12682: case 12688: case 12694: case 12700: case 12706: case 12712: case 12718: case 12724: case 12730: case 12736: case 12742: case 12748: case 12754: case 12760: case 12766: case 12772: case 12778: case 12784: case 12790: case 12796: case 12802: case 12808: return West::None; default: return West::Tall; } } } namespace StoneBricks { } namespace StoneButton { BlockState StoneButton() { return 3906; } enum Face Face(const BlockState Block) { switch (Block.ID) { case 3913: case 3914: case 3915: case 3916: case 3917: case 3918: case 3919: case 3920: return Face::Ceiling; case 3897: case 3898: case 3899: case 3900: case 3901: case 3902: case 3903: case 3904: return Face::Floor; default: return Face::Wall; } } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 3901: case 3902: case 3909: case 3910: case 3917: case 3918: return eBlockFace::BLOCK_FACE_XM; case 3903: case 3904: case 3911: case 3912: case 3919: case 3920: return eBlockFace::BLOCK_FACE_XP; case 3897: case 3898: case 3905: case 3906: case 3913: case 3914: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } bool Powered(const BlockState Block) { switch (Block.ID) { case 3898: case 3900: case 3902: case 3904: case 3906: case 3908: case 3910: case 3912: case 3914: case 3916: case 3918: case 3920: return false; default: return true; } } } namespace StonePressurePlate { BlockState StonePressurePlate() { return 3808; } bool Powered(const BlockState Block) { switch (Block.ID) { case 3808: return false; default: return true; } } } namespace StoneSlab { BlockState StoneSlab() { return 8339; } enum Type Type(const BlockState Block) { switch (Block.ID) { case 8339: return Type::Bottom; case 8341: return Type::Double; default: return Type::Top; } } } namespace StoneStairs { BlockState StoneStairs() { return 10160; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 10190: case 10192: case 10194: case 10196: case 10198: case 10200: case 10202: case 10204: case 10206: case 10208: return eBlockFace::BLOCK_FACE_XM; case 10210: case 10212: case 10214: case 10216: case 10218: case 10220: case 10222: case 10224: case 10226: case 10228: return eBlockFace::BLOCK_FACE_XP; case 10150: case 10152: case 10154: case 10156: case 10158: case 10160: case 10162: case 10164: case 10166: case 10168: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } enum Half Half(const BlockState Block) { switch (Block.ID) { case 10160: case 10162: case 10164: case 10166: case 10168: case 10180: case 10182: case 10184: case 10186: case 10188: case 10200: case 10202: case 10204: case 10206: case 10208: case 10220: case 10222: case 10224: case 10226: case 10228: return Half::Bottom; default: return Half::Top; } } enum Shape Shape(const BlockState Block) { switch (Block.ID) { case 10152: case 10162: case 10172: case 10182: case 10192: case 10202: case 10212: case 10222: return Shape::InnerLeft; case 10154: case 10164: case 10174: case 10184: case 10194: case 10204: case 10214: case 10224: return Shape::InnerRight; case 10156: case 10166: case 10176: case 10186: case 10196: case 10206: case 10216: case 10226: return Shape::OuterLeft; case 10158: case 10168: case 10178: case 10188: case 10198: case 10208: case 10218: case 10228: return Shape::OuterRight; default: return Shape::Straight; } } } namespace Stonecutter { BlockState Stonecutter() { return 14850; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 14852: return eBlockFace::BLOCK_FACE_XM; case 14853: return eBlockFace::BLOCK_FACE_XP; case 14850: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace StrippedAcaciaLog { BlockState StrippedAcaciaLog() { return 101; } enum Axis Axis(const BlockState Block) { switch (Block.ID) { case 100: return Axis::X; case 101: return Axis::Y; default: return Axis::Z; } } } namespace StrippedAcaciaWood { BlockState StrippedAcaciaWood() { return 140; } enum Axis Axis(const BlockState Block) { switch (Block.ID) { case 139: return Axis::X; case 140: return Axis::Y; default: return Axis::Z; } } } namespace StrippedBirchLog { BlockState StrippedBirchLog() { return 95; } enum Axis Axis(const BlockState Block) { switch (Block.ID) { case 94: return Axis::X; case 95: return Axis::Y; default: return Axis::Z; } } } namespace StrippedBirchWood { BlockState StrippedBirchWood() { return 134; } enum Axis Axis(const BlockState Block) { switch (Block.ID) { case 133: return Axis::X; case 134: return Axis::Y; default: return Axis::Z; } } } namespace StrippedCrimsonHyphae { BlockState StrippedCrimsonHyphae() { return 14985; } enum Axis Axis(const BlockState Block) { switch (Block.ID) { case 14984: return Axis::X; case 14985: return Axis::Y; default: return Axis::Z; } } } namespace StrippedCrimsonStem { BlockState StrippedCrimsonStem() { return 14979; } enum Axis Axis(const BlockState Block) { switch (Block.ID) { case 14978: return Axis::X; case 14979: return Axis::Y; default: return Axis::Z; } } } namespace StrippedDarkOakLog { BlockState StrippedDarkOakLog() { return 104; } enum Axis Axis(const BlockState Block) { switch (Block.ID) { case 103: return Axis::X; case 104: return Axis::Y; default: return Axis::Z; } } } namespace StrippedDarkOakWood { BlockState StrippedDarkOakWood() { return 143; } enum Axis Axis(const BlockState Block) { switch (Block.ID) { case 142: return Axis::X; case 143: return Axis::Y; default: return Axis::Z; } } } namespace StrippedJungleLog { BlockState StrippedJungleLog() { return 98; } enum Axis Axis(const BlockState Block) { switch (Block.ID) { case 97: return Axis::X; case 98: return Axis::Y; default: return Axis::Z; } } } namespace StrippedJungleWood { BlockState StrippedJungleWood() { return 137; } enum Axis Axis(const BlockState Block) { switch (Block.ID) { case 136: return Axis::X; case 137: return Axis::Y; default: return Axis::Z; } } } namespace StrippedOakLog { BlockState StrippedOakLog() { return 107; } enum Axis Axis(const BlockState Block) { switch (Block.ID) { case 106: return Axis::X; case 107: return Axis::Y; default: return Axis::Z; } } } namespace StrippedOakWood { BlockState StrippedOakWood() { return 128; } enum Axis Axis(const BlockState Block) { switch (Block.ID) { case 127: return Axis::X; case 128: return Axis::Y; default: return Axis::Z; } } } namespace StrippedSpruceLog { BlockState StrippedSpruceLog() { return 92; } enum Axis Axis(const BlockState Block) { switch (Block.ID) { case 91: return Axis::X; case 92: return Axis::Y; default: return Axis::Z; } } } namespace StrippedSpruceWood { BlockState StrippedSpruceWood() { return 131; } enum Axis Axis(const BlockState Block) { switch (Block.ID) { case 130: return Axis::X; case 131: return Axis::Y; default: return Axis::Z; } } } namespace StrippedWarpedHyphae { BlockState StrippedWarpedHyphae() { return 14968; } enum Axis Axis(const BlockState Block) { switch (Block.ID) { case 14967: return Axis::X; case 14968: return Axis::Y; default: return Axis::Z; } } } namespace StrippedWarpedStem { BlockState StrippedWarpedStem() { return 14962; } enum Axis Axis(const BlockState Block) { switch (Block.ID) { case 14961: return Axis::X; case 14962: return Axis::Y; default: return Axis::Z; } } } namespace StructureBlock { BlockState StructureBlock() { return 15735; } enum Mode Mode(const BlockState Block) { switch (Block.ID) { case 15737: return Mode::Corner; case 15738: return Mode::Data; case 15736: return Mode::Load; default: return Mode::Save; } } } namespace StructureVoid { } namespace SugarCane { BlockState SugarCane() { return 3948; } unsigned char Age(const BlockState Block) { switch (Block.ID) { case 3948: return 0; case 3949: return 1; case 3958: return 10; case 3959: return 11; case 3960: return 12; case 3961: return 13; case 3962: return 14; case 3963: return 15; case 3950: return 2; case 3951: return 3; case 3952: return 4; case 3953: return 5; case 3954: return 6; case 3955: return 7; case 3956: return 8; default: return 9; } } } namespace Sunflower { BlockState Sunflower() { return 7886; } enum Half Half(const BlockState Block) { switch (Block.ID) { case 7886: return Half::Lower; default: return Half::Upper; } } } namespace SweetBerryBush { BlockState SweetBerryBush() { return 14954; } unsigned char Age(const BlockState Block) { switch (Block.ID) { case 14954: return 0; case 14955: return 1; case 14956: return 2; default: return 3; } } } namespace TNT { BlockState TNT() { return 1431; } bool Unstable(const BlockState Block) { switch (Block.ID) { case 1431: return false; default: return true; } } } namespace TallGrass { BlockState TallGrass() { return 7894; } enum Half Half(const BlockState Block) { switch (Block.ID) { case 7894: return Half::Lower; default: return Half::Upper; } } } namespace TallSeagrass { BlockState TallSeagrass() { return 1347; } enum Half Half(const BlockState Block) { switch (Block.ID) { case 1347: return Half::Lower; default: return Half::Upper; } } } namespace Target { BlockState Target() { return 15760; } unsigned char Power(const BlockState Block) { switch (Block.ID) { case 15760: return 0; case 15761: return 1; case 15770: return 10; case 15771: return 11; case 15772: return 12; case 15773: return 13; case 15774: return 14; case 15775: return 15; case 15762: return 2; case 15763: return 3; case 15764: return 4; case 15765: return 5; case 15766: return 6; case 15767: return 7; case 15768: return 8; default: return 9; } } } namespace Terracotta { } namespace Torch { } namespace TrappedChest { BlockState TrappedChest() { return 6623; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 6635: case 6637: case 6639: return eBlockFace::BLOCK_FACE_XM; case 6641: case 6643: case 6645: return eBlockFace::BLOCK_FACE_XP; case 6623: case 6625: case 6627: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } enum Type Type(const BlockState Block) { switch (Block.ID) { case 6625: case 6631: case 6637: case 6643: return Type::Left; case 6627: case 6633: case 6639: case 6645: return Type::Right; default: return Type::Single; } } } namespace Tripwire { BlockState Tripwire() { return 5402; } bool Attached(const BlockState Block) { switch (Block.ID) { case 5339: case 5340: case 5341: case 5342: case 5343: case 5344: case 5345: case 5346: case 5347: case 5348: case 5349: case 5350: case 5351: case 5352: case 5353: case 5354: case 5355: case 5356: case 5357: case 5358: case 5359: case 5360: case 5361: case 5362: case 5363: case 5364: case 5365: case 5366: case 5367: case 5368: case 5369: case 5370: case 5371: case 5372: case 5373: case 5374: case 5375: case 5376: case 5377: case 5378: case 5379: case 5380: case 5381: case 5382: case 5383: case 5384: case 5385: case 5386: case 5387: case 5388: case 5389: case 5390: case 5391: case 5392: case 5393: case 5394: case 5395: case 5396: case 5397: case 5398: case 5399: case 5400: case 5401: case 5402: return false; default: return true; } } bool Disarmed(const BlockState Block) { switch (Block.ID) { case 5307: case 5308: case 5309: case 5310: case 5311: case 5312: case 5313: case 5314: case 5315: case 5316: case 5317: case 5318: case 5319: case 5320: case 5321: case 5322: case 5323: case 5324: case 5325: case 5326: case 5327: case 5328: case 5329: case 5330: case 5331: case 5332: case 5333: case 5334: case 5335: case 5336: case 5337: case 5338: case 5371: case 5372: case 5373: case 5374: case 5375: case 5376: case 5377: case 5378: case 5379: case 5380: case 5381: case 5382: case 5383: case 5384: case 5385: case 5386: case 5387: case 5388: case 5389: case 5390: case 5391: case 5392: case 5393: case 5394: case 5395: case 5396: case 5397: case 5398: case 5399: case 5400: case 5401: case 5402: return false; default: return true; } } bool East(const BlockState Block) { switch (Block.ID) { case 5291: case 5292: case 5293: case 5294: case 5295: case 5296: case 5297: case 5298: case 5299: case 5300: case 5301: case 5302: case 5303: case 5304: case 5305: case 5306: case 5323: case 5324: case 5325: case 5326: case 5327: case 5328: case 5329: case 5330: case 5331: case 5332: case 5333: case 5334: case 5335: case 5336: case 5337: case 5338: case 5355: case 5356: case 5357: case 5358: case 5359: case 5360: case 5361: case 5362: case 5363: case 5364: case 5365: case 5366: case 5367: case 5368: case 5369: case 5370: case 5387: case 5388: case 5389: case 5390: case 5391: case 5392: case 5393: case 5394: case 5395: case 5396: case 5397: case 5398: case 5399: case 5400: case 5401: case 5402: return false; default: return true; } } bool North(const BlockState Block) { switch (Block.ID) { case 5283: case 5284: case 5285: case 5286: case 5287: case 5288: case 5289: case 5290: case 5299: case 5300: case 5301: case 5302: case 5303: case 5304: case 5305: case 5306: case 5315: case 5316: case 5317: case 5318: case 5319: case 5320: case 5321: case 5322: case 5331: case 5332: case 5333: case 5334: case 5335: case 5336: case 5337: case 5338: case 5347: case 5348: case 5349: case 5350: case 5351: case 5352: case 5353: case 5354: case 5363: case 5364: case 5365: case 5366: case 5367: case 5368: case 5369: case 5370: case 5379: case 5380: case 5381: case 5382: case 5383: case 5384: case 5385: case 5386: case 5395: case 5396: case 5397: case 5398: case 5399: case 5400: case 5401: case 5402: return false; default: return true; } } bool Powered(const BlockState Block) { switch (Block.ID) { case 5279: case 5280: case 5281: case 5282: case 5287: case 5288: case 5289: case 5290: case 5295: case 5296: case 5297: case 5298: case 5303: case 5304: case 5305: case 5306: case 5311: case 5312: case 5313: case 5314: case 5319: case 5320: case 5321: case 5322: case 5327: case 5328: case 5329: case 5330: case 5335: case 5336: case 5337: case 5338: case 5343: case 5344: case 5345: case 5346: case 5351: case 5352: case 5353: case 5354: case 5359: case 5360: case 5361: case 5362: case 5367: case 5368: case 5369: case 5370: case 5375: case 5376: case 5377: case 5378: case 5383: case 5384: case 5385: case 5386: case 5391: case 5392: case 5393: case 5394: case 5399: case 5400: case 5401: case 5402: return false; default: return true; } } bool South(const BlockState Block) { switch (Block.ID) { case 5277: case 5278: case 5281: case 5282: case 5285: case 5286: case 5289: case 5290: case 5293: case 5294: case 5297: case 5298: case 5301: case 5302: case 5305: case 5306: case 5309: case 5310: case 5313: case 5314: case 5317: case 5318: case 5321: case 5322: case 5325: case 5326: case 5329: case 5330: case 5333: case 5334: case 5337: case 5338: case 5341: case 5342: case 5345: case 5346: case 5349: case 5350: case 5353: case 5354: case 5357: case 5358: case 5361: case 5362: case 5365: case 5366: case 5369: case 5370: case 5373: case 5374: case 5377: case 5378: case 5381: case 5382: case 5385: case 5386: case 5389: case 5390: case 5393: case 5394: case 5397: case 5398: case 5401: case 5402: return false; default: return true; } } bool West(const BlockState Block) { switch (Block.ID) { case 5276: case 5278: case 5280: case 5282: case 5284: case 5286: case 5288: case 5290: case 5292: case 5294: case 5296: case 5298: case 5300: case 5302: case 5304: case 5306: case 5308: case 5310: case 5312: case 5314: case 5316: case 5318: case 5320: case 5322: case 5324: case 5326: case 5328: case 5330: case 5332: case 5334: case 5336: case 5338: case 5340: case 5342: case 5344: case 5346: case 5348: case 5350: case 5352: case 5354: case 5356: case 5358: case 5360: case 5362: case 5364: case 5366: case 5368: case 5370: case 5372: case 5374: case 5376: case 5378: case 5380: case 5382: case 5384: case 5386: case 5388: case 5390: case 5392: case 5394: case 5396: case 5398: case 5400: case 5402: return false; default: return true; } } } namespace TripwireHook { BlockState TripwireHook() { return 5268; } bool Attached(const BlockState Block) { switch (Block.ID) { case 5267: case 5268: case 5269: case 5270: case 5271: case 5272: case 5273: case 5274: return false; default: return true; } } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 5263: case 5264: case 5271: case 5272: return eBlockFace::BLOCK_FACE_XM; case 5265: case 5266: case 5273: case 5274: return eBlockFace::BLOCK_FACE_XP; case 5259: case 5260: case 5267: case 5268: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } bool Powered(const BlockState Block) { switch (Block.ID) { case 5260: case 5262: case 5264: case 5266: case 5268: case 5270: case 5272: case 5274: return false; default: return true; } } } namespace TubeCoral { } namespace TubeCoralBlock { } namespace TubeCoralFan { } namespace TubeCoralWallFan { BlockState TubeCoralWallFan() { return 9600; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 9605: return eBlockFace::BLOCK_FACE_XM; case 9607: return eBlockFace::BLOCK_FACE_XP; case 9601: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace TurtleEgg { BlockState TurtleEgg() { return 9498; } unsigned char Eggs(const BlockState Block) { switch (Block.ID) { case 9498: case 9499: case 9500: return 1; case 9501: case 9502: case 9503: return 2; case 9504: case 9505: case 9506: return 3; default: return 4; } } unsigned char Hatch(const BlockState Block) { switch (Block.ID) { case 9498: case 9501: case 9504: case 9507: return 0; case 9499: case 9502: case 9505: case 9508: return 1; default: return 2; } } } namespace TwistingVines { BlockState TwistingVines() { return 15017; } unsigned char Age(const BlockState Block) { switch (Block.ID) { case 15017: return 0; case 15018: return 1; case 15027: return 10; case 15028: return 11; case 15029: return 12; case 15030: return 13; case 15031: return 14; case 15032: return 15; case 15033: return 16; case 15034: return 17; case 15035: return 18; case 15036: return 19; case 15019: return 2; case 15037: return 20; case 15038: return 21; case 15039: return 22; case 15040: return 23; case 15041: return 24; case 15042: return 25; case 15020: return 3; case 15021: return 4; case 15022: return 5; case 15023: return 6; case 15024: return 7; case 15025: return 8; default: return 9; } } } namespace TwistingVinesPlant { } namespace Vine { BlockState Vine() { return 4819; } bool East(const BlockState Block) { switch (Block.ID) { case 4804: case 4805: case 4806: case 4807: case 4808: case 4809: case 4810: case 4811: case 4812: case 4813: case 4814: case 4815: case 4816: case 4817: case 4818: case 4819: return false; default: return true; } } bool North(const BlockState Block) { switch (Block.ID) { case 4796: case 4797: case 4798: case 4799: case 4800: case 4801: case 4802: case 4803: case 4812: case 4813: case 4814: case 4815: case 4816: case 4817: case 4818: case 4819: return false; default: return true; } } bool South(const BlockState Block) { switch (Block.ID) { case 4792: case 4793: case 4794: case 4795: case 4800: case 4801: case 4802: case 4803: case 4808: case 4809: case 4810: case 4811: case 4816: case 4817: case 4818: case 4819: return false; default: return true; } } bool Up(const BlockState Block) { switch (Block.ID) { case 4790: case 4791: case 4794: case 4795: case 4798: case 4799: case 4802: case 4803: case 4806: case 4807: case 4810: case 4811: case 4814: case 4815: case 4818: case 4819: return false; default: return true; } } bool West(const BlockState Block) { switch (Block.ID) { case 4789: case 4791: case 4793: case 4795: case 4797: case 4799: case 4801: case 4803: case 4805: case 4807: case 4809: case 4811: case 4813: case 4815: case 4817: case 4819: return false; default: return true; } } } namespace VoidAir { } namespace WallTorch { BlockState WallTorch() { return 1436; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 1438: return eBlockFace::BLOCK_FACE_XM; case 1439: return eBlockFace::BLOCK_FACE_XP; case 1436: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace WarpedButton { BlockState WarpedButton() { return 15512; } enum Face Face(const BlockState Block) { switch (Block.ID) { case 15519: case 15520: case 15521: case 15522: case 15523: case 15524: case 15525: case 15526: return Face::Ceiling; case 15503: case 15504: case 15505: case 15506: case 15507: case 15508: case 15509: case 15510: return Face::Floor; default: return Face::Wall; } } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 15507: case 15508: case 15515: case 15516: case 15523: case 15524: return eBlockFace::BLOCK_FACE_XM; case 15509: case 15510: case 15517: case 15518: case 15525: case 15526: return eBlockFace::BLOCK_FACE_XP; case 15503: case 15504: case 15511: case 15512: case 15519: case 15520: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } bool Powered(const BlockState Block) { switch (Block.ID) { case 15504: case 15506: case 15508: case 15510: case 15512: case 15514: case 15516: case 15518: case 15520: case 15522: case 15524: case 15526: return false; default: return true; } } } namespace WarpedDoor { BlockState WarpedDoor() { return 15602; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 15623: case 15624: case 15625: case 15626: case 15627: case 15628: case 15629: case 15630: case 15631: case 15632: case 15633: case 15634: case 15635: case 15636: case 15637: case 15638: return eBlockFace::BLOCK_FACE_XM; case 15639: case 15640: case 15641: case 15642: case 15643: case 15644: case 15645: case 15646: case 15647: case 15648: case 15649: case 15650: case 15651: case 15652: case 15653: case 15654: return eBlockFace::BLOCK_FACE_XP; case 15591: case 15592: case 15593: case 15594: case 15595: case 15596: case 15597: case 15598: case 15599: case 15600: case 15601: case 15602: case 15603: case 15604: case 15605: case 15606: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } enum Half Half(const BlockState Block) { switch (Block.ID) { case 15599: case 15600: case 15601: case 15602: case 15603: case 15604: case 15605: case 15606: case 15615: case 15616: case 15617: case 15618: case 15619: case 15620: case 15621: case 15622: case 15631: case 15632: case 15633: case 15634: case 15635: case 15636: case 15637: case 15638: case 15647: case 15648: case 15649: case 15650: case 15651: case 15652: case 15653: case 15654: return Half::Lower; default: return Half::Upper; } } enum Hinge Hinge(const BlockState Block) { switch (Block.ID) { case 15591: case 15592: case 15593: case 15594: case 15599: case 15600: case 15601: case 15602: case 15607: case 15608: case 15609: case 15610: case 15615: case 15616: case 15617: case 15618: case 15623: case 15624: case 15625: case 15626: case 15631: case 15632: case 15633: case 15634: case 15639: case 15640: case 15641: case 15642: case 15647: case 15648: case 15649: case 15650: return Hinge::Left; default: return Hinge::Right; } } bool Open(const BlockState Block) { switch (Block.ID) { case 15593: case 15594: case 15597: case 15598: case 15601: case 15602: case 15605: case 15606: case 15609: case 15610: case 15613: case 15614: case 15617: case 15618: case 15621: case 15622: case 15625: case 15626: case 15629: case 15630: case 15633: case 15634: case 15637: case 15638: case 15641: case 15642: case 15645: case 15646: case 15649: case 15650: case 15653: case 15654: return false; default: return true; } } bool Powered(const BlockState Block) { switch (Block.ID) { case 15592: case 15594: case 15596: case 15598: case 15600: case 15602: case 15604: case 15606: case 15608: case 15610: case 15612: case 15614: case 15616: case 15618: case 15620: case 15622: case 15624: case 15626: case 15628: case 15630: case 15632: case 15634: case 15636: case 15638: case 15640: case 15642: case 15644: case 15646: case 15648: case 15650: case 15652: case 15654: return false; default: return true; } } } namespace WarpedFence { BlockState WarpedFence() { return 15126; } bool East(const BlockState Block) { switch (Block.ID) { case 15113: case 15114: case 15117: case 15118: case 15121: case 15122: case 15125: case 15126: return false; default: return true; } } bool North(const BlockState Block) { switch (Block.ID) { case 15105: case 15106: case 15109: case 15110: case 15121: case 15122: case 15125: case 15126: return false; default: return true; } } bool South(const BlockState Block) { switch (Block.ID) { case 15101: case 15102: case 15109: case 15110: case 15117: case 15118: case 15125: case 15126: return false; default: return true; } } bool West(const BlockState Block) { switch (Block.ID) { case 15098: case 15102: case 15106: case 15110: case 15114: case 15118: case 15122: case 15126: return false; default: return true; } } } namespace WarpedFenceGate { BlockState WarpedFenceGate() { return 15294; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 15303: case 15304: case 15305: case 15306: case 15307: case 15308: case 15309: case 15310: return eBlockFace::BLOCK_FACE_XM; case 15311: case 15312: case 15313: case 15314: case 15315: case 15316: case 15317: case 15318: return eBlockFace::BLOCK_FACE_XP; case 15287: case 15288: case 15289: case 15290: case 15291: case 15292: case 15293: case 15294: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } bool InWall(const BlockState Block) { switch (Block.ID) { case 15291: case 15292: case 15293: case 15294: case 15299: case 15300: case 15301: case 15302: case 15307: case 15308: case 15309: case 15310: case 15315: case 15316: case 15317: case 15318: return false; default: return true; } } bool Open(const BlockState Block) { switch (Block.ID) { case 15289: case 15290: case 15293: case 15294: case 15297: case 15298: case 15301: case 15302: case 15305: case 15306: case 15309: case 15310: case 15313: case 15314: case 15317: case 15318: return false; default: return true; } } bool Powered(const BlockState Block) { switch (Block.ID) { case 15288: case 15290: case 15292: case 15294: case 15296: case 15298: case 15300: case 15302: case 15304: case 15306: case 15308: case 15310: case 15312: case 15314: case 15316: case 15318: return false; default: return true; } } } namespace WarpedFungus { } namespace WarpedHyphae { BlockState WarpedHyphae() { return 14965; } enum Axis Axis(const BlockState Block) { switch (Block.ID) { case 14964: return Axis::X; case 14965: return Axis::Y; default: return Axis::Z; } } } namespace WarpedNylium { } namespace WarpedPlanks { } namespace WarpedPressurePlate { BlockState WarpedPressurePlate() { return 15062; } bool Powered(const BlockState Block) { switch (Block.ID) { case 15062: return false; default: return true; } } } namespace WarpedRoots { } namespace WarpedSign { BlockState WarpedSign() { return 15688; } unsigned char Rotation(const BlockState Block) { switch (Block.ID) { case 15688: return 0; case 15690: return 1; case 15708: return 10; case 15710: return 11; case 15712: return 12; case 15714: return 13; case 15716: return 14; case 15718: return 15; case 15692: return 2; case 15694: return 3; case 15696: return 4; case 15698: return 5; case 15700: return 6; case 15702: return 7; case 15704: return 8; default: return 9; } } } namespace WarpedSlab { BlockState WarpedSlab() { return 15056; } enum Type Type(const BlockState Block) { switch (Block.ID) { case 15056: return Type::Bottom; case 15058: return Type::Double; default: return Type::Top; } } } namespace WarpedStairs { BlockState WarpedStairs() { return 15410; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 15440: case 15442: case 15444: case 15446: case 15448: case 15450: case 15452: case 15454: case 15456: case 15458: return eBlockFace::BLOCK_FACE_XM; case 15460: case 15462: case 15464: case 15466: case 15468: case 15470: case 15472: case 15474: case 15476: case 15478: return eBlockFace::BLOCK_FACE_XP; case 15400: case 15402: case 15404: case 15406: case 15408: case 15410: case 15412: case 15414: case 15416: case 15418: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } enum Half Half(const BlockState Block) { switch (Block.ID) { case 15410: case 15412: case 15414: case 15416: case 15418: case 15430: case 15432: case 15434: case 15436: case 15438: case 15450: case 15452: case 15454: case 15456: case 15458: case 15470: case 15472: case 15474: case 15476: case 15478: return Half::Bottom; default: return Half::Top; } } enum Shape Shape(const BlockState Block) { switch (Block.ID) { case 15402: case 15412: case 15422: case 15432: case 15442: case 15452: case 15462: case 15472: return Shape::InnerLeft; case 15404: case 15414: case 15424: case 15434: case 15444: case 15454: case 15464: case 15474: return Shape::InnerRight; case 15406: case 15416: case 15426: case 15436: case 15446: case 15456: case 15466: case 15476: return Shape::OuterLeft; case 15408: case 15418: case 15428: case 15438: case 15448: case 15458: case 15468: case 15478: return Shape::OuterRight; default: return Shape::Straight; } } } namespace WarpedStem { BlockState WarpedStem() { return 14959; } enum Axis Axis(const BlockState Block) { switch (Block.ID) { case 14958: return Axis::X; case 14959: return Axis::Y; default: return Axis::Z; } } } namespace WarpedTrapdoor { BlockState WarpedTrapdoor() { return 15206; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 15224: case 15226: case 15228: case 15230: case 15232: case 15234: case 15236: case 15238: return eBlockFace::BLOCK_FACE_XM; case 15240: case 15242: case 15244: case 15246: case 15248: case 15250: case 15252: case 15254: return eBlockFace::BLOCK_FACE_XP; case 15192: case 15194: case 15196: case 15198: case 15200: case 15202: case 15204: case 15206: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } enum Half Half(const BlockState Block) { switch (Block.ID) { case 15200: case 15202: case 15204: case 15206: case 15216: case 15218: case 15220: case 15222: case 15232: case 15234: case 15236: case 15238: case 15248: case 15250: case 15252: case 15254: return Half::Bottom; default: return Half::Top; } } bool Open(const BlockState Block) { switch (Block.ID) { case 15196: case 15198: case 15204: case 15206: case 15212: case 15214: case 15220: case 15222: case 15228: case 15230: case 15236: case 15238: case 15244: case 15246: case 15252: case 15254: return false; default: return true; } } bool Powered(const BlockState Block) { switch (Block.ID) { case 15194: case 15198: case 15202: case 15206: case 15210: case 15214: case 15218: case 15222: case 15226: case 15230: case 15234: case 15238: case 15242: case 15246: case 15250: case 15254: return false; default: return true; } } } namespace WarpedWallSign { BlockState WarpedWallSign() { return 15728; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 15732: return eBlockFace::BLOCK_FACE_XM; case 15734: return eBlockFace::BLOCK_FACE_XP; case 15728: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace WarpedWartBlock { } namespace Water { BlockState Water() { return 34; } unsigned char Level(const BlockState Block) { switch (Block.ID) { case 34: return 0; case 35: return 1; case 44: return 10; case 45: return 11; case 46: return 12; case 47: return 13; case 48: return 14; case 49: return 15; case 36: return 2; case 37: return 3; case 38: return 4; case 39: return 5; case 40: return 6; case 41: return 7; case 42: return 8; default: return 9; } } } namespace WeepingVines { BlockState WeepingVines() { return 14990; } unsigned char Age(const BlockState Block) { switch (Block.ID) { case 14990: return 0; case 14991: return 1; case 15000: return 10; case 15001: return 11; case 15002: return 12; case 15003: return 13; case 15004: return 14; case 15005: return 15; case 15006: return 16; case 15007: return 17; case 15008: return 18; case 15009: return 19; case 14992: return 2; case 15010: return 20; case 15011: return 21; case 15012: return 22; case 15013: return 23; case 15014: return 24; case 15015: return 25; case 14993: return 3; case 14994: return 4; case 14995: return 5; case 14996: return 6; case 14997: return 7; case 14998: return 8; default: return 9; } } } namespace WeepingVinesPlant { } namespace WetSponge { } namespace Wheat { BlockState Wheat() { return 3357; } unsigned char Age(const BlockState Block) { switch (Block.ID) { case 3357: return 0; case 3358: return 1; case 3359: return 2; case 3360: return 3; case 3361: return 4; case 3362: return 5; case 3363: return 6; default: return 7; } } } namespace WhiteBanner { BlockState WhiteBanner() { return 7897; } unsigned char Rotation(const BlockState Block) { switch (Block.ID) { case 7897: return 0; case 7898: return 1; case 7907: return 10; case 7908: return 11; case 7909: return 12; case 7910: return 13; case 7911: return 14; case 7912: return 15; case 7899: return 2; case 7900: return 3; case 7901: return 4; case 7902: return 5; case 7903: return 6; case 7904: return 7; case 7905: return 8; default: return 9; } } } namespace WhiteBed { BlockState WhiteBed() { return 1052; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 1057: case 1058: case 1059: case 1060: return eBlockFace::BLOCK_FACE_XM; case 1061: case 1062: case 1063: case 1064: return eBlockFace::BLOCK_FACE_XP; case 1049: case 1050: case 1051: case 1052: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } bool Occupied(const BlockState Block) { switch (Block.ID) { case 1051: case 1052: case 1055: case 1056: case 1059: case 1060: case 1063: case 1064: return false; default: return true; } } enum Part Part(const BlockState Block) { switch (Block.ID) { case 1050: case 1052: case 1054: case 1056: case 1058: case 1060: case 1062: case 1064: return Part::Foot; default: return Part::Head; } } } namespace WhiteCarpet { } namespace WhiteConcrete { } namespace WhiteConcretePowder { } namespace WhiteGlazedTerracotta { BlockState WhiteGlazedTerracotta() { return 9374; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 9376: return eBlockFace::BLOCK_FACE_XM; case 9377: return eBlockFace::BLOCK_FACE_XP; case 9374: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace WhiteShulkerBox { BlockState WhiteShulkerBox() { return 9282; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 9281: return eBlockFace::BLOCK_FACE_XM; case 9279: return eBlockFace::BLOCK_FACE_XP; case 9283: return eBlockFace::BLOCK_FACE_YM; case 9282: return eBlockFace::BLOCK_FACE_YP; case 9278: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace WhiteStainedGlass { } namespace WhiteStainedGlassPane { BlockState WhiteStainedGlassPane() { return 6894; } bool East(const BlockState Block) { switch (Block.ID) { case 6881: case 6882: case 6885: case 6886: case 6889: case 6890: case 6893: case 6894: return false; default: return true; } } bool North(const BlockState Block) { switch (Block.ID) { case 6873: case 6874: case 6877: case 6878: case 6889: case 6890: case 6893: case 6894: return false; default: return true; } } bool South(const BlockState Block) { switch (Block.ID) { case 6869: case 6870: case 6877: case 6878: case 6885: case 6886: case 6893: case 6894: return false; default: return true; } } bool West(const BlockState Block) { switch (Block.ID) { case 6866: case 6870: case 6874: case 6878: case 6882: case 6886: case 6890: case 6894: return false; default: return true; } } } namespace WhiteTerracotta { } namespace WhiteTulip { } namespace WhiteWallBanner { BlockState WhiteWallBanner() { return 8153; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 8155: return eBlockFace::BLOCK_FACE_XM; case 8156: return eBlockFace::BLOCK_FACE_XP; case 8153: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace WhiteWool { } namespace WitherRose { } namespace WitherSkeletonSkull { BlockState WitherSkeletonSkull() { return 6510; } unsigned char Rotation(const BlockState Block) { switch (Block.ID) { case 6510: return 0; case 6511: return 1; case 6520: return 10; case 6521: return 11; case 6522: return 12; case 6523: return 13; case 6524: return 14; case 6525: return 15; case 6512: return 2; case 6513: return 3; case 6514: return 4; case 6515: return 5; case 6516: return 6; case 6517: return 7; case 6518: return 8; default: return 9; } } } namespace WitherSkeletonWallSkull { BlockState WitherSkeletonWallSkull() { return 6526; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 6528: return eBlockFace::BLOCK_FACE_XM; case 6529: return eBlockFace::BLOCK_FACE_XP; case 6526: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace YellowBanner { BlockState YellowBanner() { return 7961; } unsigned char Rotation(const BlockState Block) { switch (Block.ID) { case 7961: return 0; case 7962: return 1; case 7971: return 10; case 7972: return 11; case 7973: return 12; case 7974: return 13; case 7975: return 14; case 7976: return 15; case 7963: return 2; case 7964: return 3; case 7965: return 4; case 7966: return 5; case 7967: return 6; case 7968: return 7; case 7969: return 8; default: return 9; } } } namespace YellowBed { BlockState YellowBed() { return 1116; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 1121: case 1122: case 1123: case 1124: return eBlockFace::BLOCK_FACE_XM; case 1125: case 1126: case 1127: case 1128: return eBlockFace::BLOCK_FACE_XP; case 1113: case 1114: case 1115: case 1116: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } bool Occupied(const BlockState Block) { switch (Block.ID) { case 1115: case 1116: case 1119: case 1120: case 1123: case 1124: case 1127: case 1128: return false; default: return true; } } enum Part Part(const BlockState Block) { switch (Block.ID) { case 1114: case 1116: case 1118: case 1120: case 1122: case 1124: case 1126: case 1128: return Part::Foot; default: return Part::Head; } } } namespace YellowCarpet { } namespace YellowConcrete { } namespace YellowConcretePowder { } namespace YellowGlazedTerracotta { BlockState YellowGlazedTerracotta() { return 9390; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 9392: return eBlockFace::BLOCK_FACE_XM; case 9393: return eBlockFace::BLOCK_FACE_XP; case 9390: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace YellowShulkerBox { BlockState YellowShulkerBox() { return 9306; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 9305: return eBlockFace::BLOCK_FACE_XM; case 9303: return eBlockFace::BLOCK_FACE_XP; case 9307: return eBlockFace::BLOCK_FACE_YM; case 9306: return eBlockFace::BLOCK_FACE_YP; case 9302: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace YellowStainedGlass { } namespace YellowStainedGlassPane { BlockState YellowStainedGlassPane() { return 7022; } bool East(const BlockState Block) { switch (Block.ID) { case 7009: case 7010: case 7013: case 7014: case 7017: case 7018: case 7021: case 7022: return false; default: return true; } } bool North(const BlockState Block) { switch (Block.ID) { case 7001: case 7002: case 7005: case 7006: case 7017: case 7018: case 7021: case 7022: return false; default: return true; } } bool South(const BlockState Block) { switch (Block.ID) { case 6997: case 6998: case 7005: case 7006: case 7013: case 7014: case 7021: case 7022: return false; default: return true; } } bool West(const BlockState Block) { switch (Block.ID) { case 6994: case 6998: case 7002: case 7006: case 7010: case 7014: case 7018: case 7022: return false; default: return true; } } } namespace YellowTerracotta { } namespace YellowWallBanner { BlockState YellowWallBanner() { return 8169; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 8171: return eBlockFace::BLOCK_FACE_XM; case 8172: return eBlockFace::BLOCK_FACE_XP; case 8169: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } namespace YellowWool { } namespace ZombieHead { BlockState ZombieHead() { return 6530; } unsigned char Rotation(const BlockState Block) { switch (Block.ID) { case 6530: return 0; case 6531: return 1; case 6540: return 10; case 6541: return 11; case 6542: return 12; case 6543: return 13; case 6544: return 14; case 6545: return 15; case 6532: return 2; case 6533: return 3; case 6534: return 4; case 6535: return 5; case 6536: return 6; case 6537: return 7; case 6538: return 8; default: return 9; } } } namespace ZombieWallHead { BlockState ZombieWallHead() { return 6546; } eBlockFace Facing(const BlockState Block) { switch (Block.ID) { case 6548: return eBlockFace::BLOCK_FACE_XM; case 6549: return eBlockFace::BLOCK_FACE_XP; case 6546: return eBlockFace::BLOCK_FACE_ZM; default: return eBlockFace::BLOCK_FACE_ZP; } } } } BlockType BlockState::Type() const { switch (ID) { case 6442: case 6443: case 6444: case 6445: case 6446: case 6447: case 6448: case 6449: case 6450: case 6451: case 6452: case 6453: case 6454: case 6455: case 6456: case 6457: case 6458: case 6459: case 6460: case 6461: case 6462: case 6463: case 6464: case 6465: return BlockType::AcaciaButton; case 8930: case 8931: case 8932: case 8933: case 8934: case 8935: case 8936: case 8937: case 8938: case 8939: case 8940: case 8941: case 8942: case 8943: case 8944: case 8945: case 8946: case 8947: case 8948: case 8949: case 8950: case 8951: case 8952: case 8953: case 8954: case 8955: case 8956: case 8957: case 8958: case 8959: case 8960: case 8961: case 8962: case 8963: case 8964: case 8965: case 8966: case 8967: case 8968: case 8969: case 8970: case 8971: case 8972: case 8973: case 8974: case 8975: case 8976: case 8977: case 8978: case 8979: case 8980: case 8981: case 8982: case 8983: case 8984: case 8985: case 8986: case 8987: case 8988: case 8989: case 8990: case 8991: case 8992: case 8993: return BlockType::AcaciaDoor; case 8676: case 8677: case 8680: case 8681: case 8684: case 8685: case 8688: case 8689: case 8692: case 8693: case 8696: case 8697: case 8700: case 8701: case 8704: case 8705: return BlockType::AcaciaFence; case 8514: case 8515: case 8516: case 8517: case 8518: case 8519: case 8520: case 8521: case 8522: case 8523: case 8524: case 8525: case 8526: case 8527: case 8528: case 8529: case 8530: case 8531: case 8532: case 8533: case 8534: case 8535: case 8536: case 8537: case 8538: case 8539: case 8540: case 8541: case 8542: case 8543: case 8544: case 8545: return BlockType::AcaciaFenceGate; case 201: case 202: case 203: case 204: case 205: case 206: case 207: case 208: case 209: case 210: case 211: case 212: case 213: case 214: return BlockType::AcaciaLeaves; case 85: case 86: case 87: return BlockType::AcaciaLog; case 19: return BlockType::AcaciaPlanks; case 3881: case 3882: return BlockType::AcaciaPressurePlate; case 29: case 30: return BlockType::AcaciaSapling; case 3478: case 3480: case 3482: case 3484: case 3486: case 3488: case 3490: case 3492: case 3494: case 3496: case 3498: case 3500: case 3502: case 3504: case 3506: case 3508: return BlockType::AcaciaSign; case 8325: case 8327: case 8329: return BlockType::AcaciaSlab; case 7376: case 7378: case 7380: case 7382: case 7384: case 7386: case 7388: case 7390: case 7392: case 7394: case 7396: case 7398: case 7400: case 7402: case 7404: case 7406: case 7408: case 7410: case 7412: case 7414: case 7416: case 7418: case 7420: case 7422: case 7424: case 7426: case 7428: case 7430: case 7432: case 7434: case 7436: case 7438: case 7440: case 7442: case 7444: case 7446: case 7448: case 7450: case 7452: case 7454: return BlockType::AcaciaStairs; case 4368: case 4370: case 4372: case 4374: case 4376: case 4378: case 4380: case 4382: case 4384: case 4386: case 4388: case 4390: case 4392: case 4394: case 4396: case 4398: case 4400: case 4402: case 4404: case 4406: case 4408: case 4410: case 4412: case 4414: case 4416: case 4418: case 4420: case 4422: case 4424: case 4426: case 4428: case 4430: return BlockType::AcaciaTrapdoor; case 3760: case 3762: case 3764: case 3766: return BlockType::AcaciaWallSign; case 121: case 122: case 123: return BlockType::AcaciaWood; case 6823: case 6824: case 6825: case 6826: case 6827: case 6828: case 6829: case 6830: case 6831: case 6832: case 6833: case 6834: return BlockType::ActivatorRail; case -0: return BlockType::Air; case 1415: return BlockType::Allium; case 15827: return BlockType::AncientDebris; case 6: return BlockType::Andesite; case 10844: case 10846: case 10848: return BlockType::AndesiteSlab; case 10470: case 10472: case 10474: case 10476: case 10478: case 10480: case 10482: case 10484: case 10486: case 10488: case 10490: case 10492: case 10494: case 10496: case 10498: case 10500: case 10502: case 10504: case 10506: case 10508: case 10510: case 10512: case 10514: case 10516: case 10518: case 10520: case 10522: case 10524: case 10526: case 10528: case 10530: case 10532: case 10534: case 10536: case 10538: case 10540: case 10542: case 10544: case 10546: case 10548: return BlockType::AndesiteStairs; case 13138: case 13139: case 13140: case 13144: case 13145: case 13146: case 13150: case 13151: case 13152: case 13156: case 13157: case 13158: case 13162: case 13163: case 13164: case 13168: case 13169: case 13170: case 13174: case 13175: case 13176: case 13180: case 13181: case 13182: case 13186: case 13187: case 13188: case 13192: case 13193: case 13194: case 13198: case 13199: case 13200: case 13204: case 13205: case 13206: case 13210: case 13211: case 13212: case 13216: case 13217: case 13218: case 13222: case 13223: case 13224: case 13228: case 13229: case 13230: case 13234: case 13235: case 13236: case 13240: case 13241: case 13242: case 13246: case 13247: case 13248: case 13252: case 13253: case 13254: case 13258: case 13259: case 13260: case 13264: case 13265: case 13266: case 13270: case 13271: case 13272: case 13276: case 13277: case 13278: case 13282: case 13283: case 13284: case 13288: case 13289: case 13290: case 13294: case 13295: case 13296: case 13300: case 13301: case 13302: case 13306: case 13307: case 13308: case 13312: case 13313: case 13314: case 13318: case 13319: case 13320: case 13324: case 13325: case 13326: case 13330: case 13331: case 13332: case 13336: case 13337: case 13338: case 13342: case 13343: case 13344: case 13348: case 13349: case 13350: case 13354: case 13355: case 13356: case 13360: case 13361: case 13362: case 13366: case 13367: case 13368: case 13372: case 13373: case 13374: case 13378: case 13379: case 13380: case 13384: case 13385: case 13386: case 13390: case 13391: case 13392: case 13396: case 13397: case 13398: case 13402: case 13403: case 13404: case 13408: case 13409: case 13410: case 13414: case 13415: case 13416: case 13420: case 13421: case 13422: case 13426: case 13427: case 13428: case 13432: case 13433: case 13434: case 13438: case 13439: case 13440: case 13444: case 13445: case 13446: case 13450: case 13451: case 13452: case 13456: case 13457: case 13458: return BlockType::AndesiteWall; case 6610: case 6611: case 6612: case 6613: return BlockType::Anvil; case 4768: case 4769: case 4770: case 4771: return BlockType::AttachedMelonStem; case 4764: case 4765: case 4766: case 4767: return BlockType::AttachedPumpkinStem; case 1416: return BlockType::AzureBluet; case 9652: case 9653: case 9654: case 9655: case 9656: case 9657: case 9658: case 9659: case 9660: case 9661: case 9662: case 9663: return BlockType::Bamboo; case 9651: return BlockType::BambooSapling; case 14791: case 14792: case 14793: case 14794: case 14795: case 14796: case 14797: case 14798: case 14799: case 14800: case 14801: case 14802: return BlockType::Barrel; case 7536: return BlockType::Barrier; case 4002: case 4003: case 4004: return BlockType::Basalt; case 5656: return BlockType::Beacon; case 33: return BlockType::Bedrock; case 15776: case 15777: case 15778: case 15779: case 15780: case 15781: case 15782: case 15783: case 15784: case 15785: case 15786: case 15787: case 15788: case 15789: case 15790: case 15791: case 15792: case 15793: case 15794: case 15795: case 15796: case 15797: case 15798: case 15799: return BlockType::BeeNest; case 15800: case 15801: case 15802: case 15803: case 15804: case 15805: case 15806: case 15807: case 15808: case 15809: case 15810: case 15811: case 15812: case 15813: case 15814: case 15815: case 15816: case 15817: case 15818: case 15819: case 15820: case 15821: case 15822: case 15823: return BlockType::Beehive; case 9219: case 9220: case 9221: case 9222: return BlockType::Beetroots; case 14854: case 14855: case 14856: case 14857: case 14858: case 14859: case 14860: case 14861: case 14862: case 14863: case 14864: case 14865: case 14866: case 14867: case 14868: case 14869: case 14870: case 14871: case 14872: case 14873: case 14874: case 14875: case 14876: case 14877: case 14878: case 14879: case 14880: case 14881: case 14882: case 14883: case 14884: case 14885: return BlockType::Bell; case 6394: case 6395: case 6396: case 6397: case 6398: case 6399: case 6400: case 6401: case 6402: case 6403: case 6404: case 6405: case 6406: case 6407: case 6408: case 6409: case 6410: case 6411: case 6412: case 6413: case 6414: case 6415: case 6416: case 6417: return BlockType::BirchButton; case 8802: case 8803: case 8804: case 8805: case 8806: case 8807: case 8808: case 8809: case 8810: case 8811: case 8812: case 8813: case 8814: case 8815: case 8816: case 8817: case 8818: case 8819: case 8820: case 8821: case 8822: case 8823: case 8824: case 8825: case 8826: case 8827: case 8828: case 8829: case 8830: case 8831: case 8832: case 8833: case 8834: case 8835: case 8836: case 8837: case 8838: case 8839: case 8840: case 8841: case 8842: case 8843: case 8844: case 8845: case 8846: case 8847: case 8848: case 8849: case 8850: case 8851: case 8852: case 8853: case 8854: case 8855: case 8856: case 8857: case 8858: case 8859: case 8860: case 8861: case 8862: case 8863: case 8864: case 8865: return BlockType::BirchDoor; case 8612: case 8613: case 8616: case 8617: case 8620: case 8621: case 8624: case 8625: case 8628: case 8629: case 8632: case 8633: case 8636: case 8637: case 8640: case 8641: return BlockType::BirchFence; case 8450: case 8451: case 8452: case 8453: case 8454: case 8455: case 8456: case 8457: case 8458: case 8459: case 8460: case 8461: case 8462: case 8463: case 8464: case 8465: case 8466: case 8467: case 8468: case 8469: case 8470: case 8471: case 8472: case 8473: case 8474: case 8475: case 8476: case 8477: case 8478: case 8479: case 8480: case 8481: return BlockType::BirchFenceGate; case 173: case 174: case 175: case 176: case 177: case 178: case 179: case 180: case 181: case 182: case 183: case 184: case 185: case 186: return BlockType::BirchLeaves; case 79: case 80: case 81: return BlockType::BirchLog; case 17: return BlockType::BirchPlanks; case 3877: case 3878: return BlockType::BirchPressurePlate; case 25: case 26: return BlockType::BirchSapling; case 3446: case 3448: case 3450: case 3452: case 3454: case 3456: case 3458: case 3460: case 3462: case 3464: case 3466: case 3468: case 3470: case 3472: case 3474: case 3476: return BlockType::BirchSign; case 8313: case 8315: case 8317: return BlockType::BirchSlab; case 5485: case 5487: case 5489: case 5491: case 5493: case 5495: case 5497: case 5499: case 5501: case 5503: case 5505: case 5507: case 5509: case 5511: case 5513: case 5515: case 5517: case 5519: case 5521: case 5523: case 5525: case 5527: case 5529: case 5531: case 5533: case 5535: case 5537: case 5539: case 5541: case 5543: case 5545: case 5547: case 5549: case 5551: case 5553: case 5555: case 5557: case 5559: case 5561: case 5563: return BlockType::BirchStairs; case 4240: case 4242: case 4244: case 4246: case 4248: case 4250: case 4252: case 4254: case 4256: case 4258: case 4260: case 4262: case 4264: case 4266: case 4268: case 4270: case 4272: case 4274: case 4276: case 4278: case 4280: case 4282: case 4284: case 4286: case 4288: case 4290: case 4292: case 4294: case 4296: case 4298: case 4300: case 4302: return BlockType::BirchTrapdoor; case 3752: case 3754: case 3756: case 3758: return BlockType::BirchWallSign; case 115: case 116: case 117: return BlockType::BirchWood; case 8137: case 8138: case 8139: case 8140: case 8141: case 8142: case 8143: case 8144: case 8145: case 8146: case 8147: case 8148: case 8149: case 8150: case 8151: case 8152: return BlockType::BlackBanner; case 1289: case 1290: case 1291: case 1292: case 1293: case 1294: case 1295: case 1296: case 1297: case 1298: case 1299: case 1300: case 1301: case 1302: case 1303: case 1304: return BlockType::BlackBed; case 7881: return BlockType::BlackCarpet; case 9453: return BlockType::BlackConcrete; case 9469: return BlockType::BlackConcretePowder; case 9434: case 9435: case 9436: case 9437: return BlockType::BlackGlazedTerracotta; case 9368: case 9369: case 9370: case 9371: case 9372: case 9373: return BlockType::BlackShulkerBox; case 4110: return BlockType::BlackStainedGlass; case 7345: case 7346: case 7349: case 7350: case 7353: case 7354: case 7357: case 7358: case 7361: case 7362: case 7365: case 7366: case 7369: case 7370: case 7373: case 7374: return BlockType::BlackStainedGlassPane; case 6862: return BlockType::BlackTerracotta; case 8213: case 8214: case 8215: case 8216: return BlockType::BlackWallBanner; case 1399: return BlockType::BlackWool; case 15839: return BlockType::Blackstone; case 16245: case 16247: case 16249: return BlockType::BlackstoneSlab; case 15841: case 15843: case 15845: case 15847: case 15849: case 15851: case 15853: case 15855: case 15857: case 15859: case 15861: case 15863: case 15865: case 15867: case 15869: case 15871: case 15873: case 15875: case 15877: case 15879: case 15881: case 15883: case 15885: case 15887: case 15889: case 15891: case 15893: case 15895: case 15897: case 15899: case 15901: case 15903: case 15905: case 15907: case 15909: case 15911: case 15913: case 15915: case 15917: case 15919: return BlockType::BlackstoneStairs; case 15923: case 15924: case 15925: case 15929: case 15930: case 15931: case 15935: case 15936: case 15937: case 15941: case 15942: case 15943: case 15947: case 15948: case 15949: case 15953: case 15954: case 15955: case 15959: case 15960: case 15961: case 15965: case 15966: case 15967: case 15971: case 15972: case 15973: case 15977: case 15978: case 15979: case 15983: case 15984: case 15985: case 15989: case 15990: case 15991: case 15995: case 15996: case 15997: case 16001: case 16002: case 16003: case 16007: case 16008: case 16009: case 16013: case 16014: case 16015: case 16019: case 16020: case 16021: case 16025: case 16026: case 16027: case 16031: case 16032: case 16033: case 16037: case 16038: case 16039: case 16043: case 16044: case 16045: case 16049: case 16050: case 16051: case 16055: case 16056: case 16057: case 16061: case 16062: case 16063: case 16067: case 16068: case 16069: case 16073: case 16074: case 16075: case 16079: case 16080: case 16081: case 16085: case 16086: case 16087: case 16091: case 16092: case 16093: case 16097: case 16098: case 16099: case 16103: case 16104: case 16105: case 16109: case 16110: case 16111: case 16115: case 16116: case 16117: case 16121: case 16122: case 16123: case 16127: case 16128: case 16129: case 16133: case 16134: case 16135: case 16139: case 16140: case 16141: case 16145: case 16146: case 16147: case 16151: case 16152: case 16153: case 16157: case 16158: case 16159: case 16163: case 16164: case 16165: case 16169: case 16170: case 16171: case 16175: case 16176: case 16177: case 16181: case 16182: case 16183: case 16187: case 16188: case 16189: case 16193: case 16194: case 16195: case 16199: case 16200: case 16201: case 16205: case 16206: case 16207: case 16211: case 16212: case 16213: case 16217: case 16218: case 16219: case 16223: case 16224: case 16225: case 16229: case 16230: case 16231: case 16235: case 16236: case 16237: case 16241: case 16242: case 16243: return BlockType::BlackstoneWall; case 14811: case 14812: case 14813: case 14814: case 14815: case 14816: case 14817: case 14818: return BlockType::BlastFurnace; case 8073: case 8074: case 8075: case 8076: case 8077: case 8078: case 8079: case 8080: case 8081: case 8082: case 8083: case 8084: case 8085: case 8086: case 8087: case 8088: return BlockType::BlueBanner; case 1225: case 1226: case 1227: case 1228: case 1229: case 1230: case 1231: case 1232: case 1233: case 1234: case 1235: case 1236: case 1237: case 1238: case 1239: case 1240: return BlockType::BlueBed; case 7877: return BlockType::BlueCarpet; case 9449: return BlockType::BlueConcrete; case 9465: return BlockType::BlueConcretePowder; case 9418: case 9419: case 9420: case 9421: return BlockType::BlueGlazedTerracotta; case 9648: return BlockType::BlueIce; case 1414: return BlockType::BlueOrchid; case 9344: case 9345: case 9346: case 9347: case 9348: case 9349: return BlockType::BlueShulkerBox; case 4106: return BlockType::BlueStainedGlass; case 7217: case 7218: case 7221: case 7222: case 7225: case 7226: case 7229: case 7230: case 7233: case 7234: case 7237: case 7238: case 7241: case 7242: case 7245: case 7246: return BlockType::BlueStainedGlassPane; case 6858: return BlockType::BlueTerracotta; case 8197: case 8198: case 8199: case 8200: return BlockType::BlueWallBanner; case 1395: return BlockType::BlueWool; case 9256: case 9257: case 9258: return BlockType::BoneBlock; case 1432: return BlockType::Bookshelf; case 9533: return BlockType::BrainCoral; case 9516: return BlockType::BrainCoralBlock; case 9553: return BlockType::BrainCoralFan; case 9609: case 9611: case 9613: case 9615: return BlockType::BrainCoralWallFan; case 5133: case 5134: case 5135: case 5136: case 5137: case 5138: case 5139: case 5140: return BlockType::BrewingStand; case 8373: case 8375: case 8377: return BlockType::BrickSlab; case 4853: case 4855: case 4857: case 4859: case 4861: case 4863: case 4865: case 4867: case 4869: case 4871: case 4873: case 4875: case 4877: case 4879: case 4881: case 4883: case 4885: case 4887: case 4889: case 4891: case 4893: case 4895: case 4897: case 4899: case 4901: case 4903: case 4905: case 4907: case 4909: case 4911: case 4913: case 4915: case 4917: case 4919: case 4921: case 4923: case 4925: case 4927: case 4929: case 4931: return BlockType::BrickStairs; case 10870: case 10871: case 10872: case 10876: case 10877: case 10878: case 10882: case 10883: case 10884: case 10888: case 10889: case 10890: case 10894: case 10895: case 10896: case 10900: case 10901: case 10902: case 10906: case 10907: case 10908: case 10912: case 10913: case 10914: case 10918: case 10919: case 10920: case 10924: case 10925: case 10926: case 10930: case 10931: case 10932: case 10936: case 10937: case 10938: case 10942: case 10943: case 10944: case 10948: case 10949: case 10950: case 10954: case 10955: case 10956: case 10960: case 10961: case 10962: case 10966: case 10967: case 10968: case 10972: case 10973: case 10974: case 10978: case 10979: case 10980: case 10984: case 10985: case 10986: case 10990: case 10991: case 10992: case 10996: case 10997: case 10998: case 11002: case 11003: case 11004: case 11008: case 11009: case 11010: case 11014: case 11015: case 11016: case 11020: case 11021: case 11022: case 11026: case 11027: case 11028: case 11032: case 11033: case 11034: case 11038: case 11039: case 11040: case 11044: case 11045: case 11046: case 11050: case 11051: case 11052: case 11056: case 11057: case 11058: case 11062: case 11063: case 11064: case 11068: case 11069: case 11070: case 11074: case 11075: case 11076: case 11080: case 11081: case 11082: case 11086: case 11087: case 11088: case 11092: case 11093: case 11094: case 11098: case 11099: case 11100: case 11104: case 11105: case 11106: case 11110: case 11111: case 11112: case 11116: case 11117: case 11118: case 11122: case 11123: case 11124: case 11128: case 11129: case 11130: case 11134: case 11135: case 11136: case 11140: case 11141: case 11142: case 11146: case 11147: case 11148: case 11152: case 11153: case 11154: case 11158: case 11159: case 11160: case 11164: case 11165: case 11166: case 11170: case 11171: case 11172: case 11176: case 11177: case 11178: case 11182: case 11183: case 11184: case 11188: case 11189: case 11190: return BlockType::BrickWall; case 1429: return BlockType::Bricks; case 8089: case 8090: case 8091: case 8092: case 8093: case 8094: case 8095: case 8096: case 8097: case 8098: case 8099: case 8100: case 8101: case 8102: case 8103: case 8104: return BlockType::BrownBanner; case 1241: case 1242: case 1243: case 1244: case 1245: case 1246: case 1247: case 1248: case 1249: case 1250: case 1251: case 1252: case 1253: case 1254: case 1255: case 1256: return BlockType::BrownBed; case 7878: return BlockType::BrownCarpet; case 9450: return BlockType::BrownConcrete; case 9466: return BlockType::BrownConcretePowder; case 9422: case 9423: case 9424: case 9425: return BlockType::BrownGlazedTerracotta; case 1425: return BlockType::BrownMushroom; case 4505: case 4506: case 4507: case 4508: case 4509: case 4510: case 4511: case 4512: case 4513: case 4514: case 4515: case 4516: case 4517: case 4518: case 4519: case 4520: case 4521: case 4522: case 4523: case 4524: case 4525: case 4526: case 4527: case 4528: case 4529: case 4530: case 4531: case 4532: case 4533: case 4534: case 4535: case 4536: case 4537: case 4538: case 4539: case 4540: case 4541: case 4542: case 4543: case 4544: case 4545: case 4546: case 4547: case 4548: case 4549: case 4550: case 4551: case 4552: case 4553: case 4554: case 4555: case 4556: case 4557: case 4558: case 4559: case 4560: case 4561: case 4562: case 4563: case 4564: case 4565: case 4566: case 4567: case 4568: return BlockType::BrownMushroomBlock; case 9350: case 9351: case 9352: case 9353: case 9354: case 9355: return BlockType::BrownShulkerBox; case 4107: return BlockType::BrownStainedGlass; case 7249: case 7250: case 7253: case 7254: case 7257: case 7258: case 7261: case 7262: case 7265: case 7266: case 7269: case 7270: case 7273: case 7274: case 7277: case 7278: return BlockType::BrownStainedGlassPane; case 6859: return BlockType::BrownTerracotta; case 8201: case 8202: case 8203: case 8204: return BlockType::BrownWallBanner; case 1396: return BlockType::BrownWool; case 9667: case 9668: return BlockType::BubbleColumn; case 9535: return BlockType::BubbleCoral; case 9517: return BlockType::BubbleCoralBlock; case 9555: return BlockType::BubbleCoralFan; case 9617: case 9619: case 9621: case 9623: return BlockType::BubbleCoralWallFan; case 3931: case 3932: case 3933: case 3934: case 3935: case 3936: case 3937: case 3938: case 3939: case 3940: case 3941: case 3942: case 3943: case 3944: case 3945: case 3946: return BlockType::Cactus; case 4024: case 4025: case 4026: case 4027: case 4028: case 4029: case 4030: return BlockType::Cake; case 14891: case 14893: case 14895: case 14897: case 14899: case 14901: case 14903: case 14905: case 14907: case 14909: case 14911: case 14913: case 14915: case 14917: case 14919: case 14921: return BlockType::Campfire; case 6330: case 6331: case 6332: case 6333: case 6334: case 6335: case 6336: case 6337: return BlockType::Carrots; case 14819: return BlockType::CartographyTable; case 4016: case 4017: case 4018: case 4019: return BlockType::CarvedPumpkin; case 5141: case 5142: case 5143: case 5144: return BlockType::Cauldron; case 9666: return BlockType::CaveAir; case 4730: return BlockType::Chain; case 9237: case 9238: case 9239: case 9240: case 9241: case 9242: case 9243: case 9244: case 9245: case 9246: case 9247: case 9248: return BlockType::ChainCommandBlock; case 2035: case 2037: case 2039: case 2041: case 2043: case 2045: case 2047: case 2049: case 2051: case 2053: case 2055: case 2057: return BlockType::Chest; case 6614: case 6615: case 6616: case 6617: return BlockType::ChippedAnvil; case 17101: return BlockType::ChiseledNetherBricks; case 16253: return BlockType::ChiseledPolishedBlackstone; case 6739: return BlockType::ChiseledQuartzBlock; case 8218: return BlockType::ChiseledRedSandstone; case 247: return BlockType::ChiseledSandstone; case 4498: return BlockType::ChiseledStoneBricks; case 9128: case 9129: case 9130: case 9131: case 9132: case 9133: return BlockType::ChorusFlower; case 9064: case 9065: case 9066: case 9067: case 9068: case 9069: case 9070: case 9071: case 9072: case 9073: case 9074: case 9075: case 9076: case 9077: case 9078: case 9079: case 9080: case 9081: case 9082: case 9083: case 9084: case 9085: case 9086: case 9087: case 9088: case 9089: case 9090: case 9091: case 9092: case 9093: case 9094: case 9095: case 9096: case 9097: case 9098: case 9099: case 9100: case 9101: case 9102: case 9103: case 9104: case 9105: case 9106: case 9107: case 9108: case 9109: case 9110: case 9111: case 9112: case 9113: case 9114: case 9115: case 9116: case 9117: case 9118: case 9119: case 9120: case 9121: case 9122: case 9123: case 9124: case 9125: case 9126: case 9127: return BlockType::ChorusPlant; case 3947: return BlockType::Clay; case 7883: return BlockType::CoalBlock; case 71: return BlockType::CoalOre; case 11: return BlockType::CoarseDirt; case 14: return BlockType::Cobblestone; case 8367: case 8369: case 8371: return BlockType::CobblestoneSlab; case 3656: case 3658: case 3660: case 3662: case 3664: case 3666: case 3668: case 3670: case 3672: case 3674: case 3676: case 3678: case 3680: case 3682: case 3684: case 3686: case 3688: case 3690: case 3692: case 3694: case 3696: case 3698: case 3700: case 3702: case 3704: case 3706: case 3708: case 3710: case 3712: case 3714: case 3716: case 3718: case 3720: case 3722: case 3724: case 3726: case 3728: case 3730: case 3732: case 3734: return BlockType::CobblestoneStairs; case 5660: case 5661: case 5662: case 5666: case 5667: case 5668: case 5672: case 5673: case 5674: case 5678: case 5679: case 5680: case 5684: case 5685: case 5686: case 5690: case 5691: case 5692: case 5696: case 5697: case 5698: case 5702: case 5703: case 5704: case 5708: case 5709: case 5710: case 5714: case 5715: case 5716: case 5720: case 5721: case 5722: case 5726: case 5727: case 5728: case 5732: case 5733: case 5734: case 5738: case 5739: case 5740: case 5744: case 5745: case 5746: case 5750: case 5751: case 5752: case 5756: case 5757: case 5758: case 5762: case 5763: case 5764: case 5768: case 5769: case 5770: case 5774: case 5775: case 5776: case 5780: case 5781: case 5782: case 5786: case 5787: case 5788: case 5792: case 5793: case 5794: case 5798: case 5799: case 5800: case 5804: case 5805: case 5806: case 5810: case 5811: case 5812: case 5816: case 5817: case 5818: case 5822: case 5823: case 5824: case 5828: case 5829: case 5830: case 5834: case 5835: case 5836: case 5840: case 5841: case 5842: case 5846: case 5847: case 5848: case 5852: case 5853: case 5854: case 5858: case 5859: case 5860: case 5864: case 5865: case 5866: case 5870: case 5871: case 5872: case 5876: case 5877: case 5878: case 5882: case 5883: case 5884: case 5888: case 5889: case 5890: case 5894: case 5895: case 5896: case 5900: case 5901: case 5902: case 5906: case 5907: case 5908: case 5912: case 5913: case 5914: case 5918: case 5919: case 5920: case 5924: case 5925: case 5926: case 5930: case 5931: case 5932: case 5936: case 5937: case 5938: case 5942: case 5943: case 5944: case 5948: case 5949: case 5950: case 5954: case 5955: case 5956: case 5960: case 5961: case 5962: case 5966: case 5967: case 5968: case 5972: case 5973: case 5974: case 5978: case 5979: case 5980: return BlockType::CobblestoneWall; case 1341: return BlockType::Cobweb; case 5158: case 5159: case 5160: case 5161: case 5162: case 5163: case 5164: case 5165: case 5166: case 5167: case 5168: case 5169: return BlockType::Cocoa; case 5644: case 5645: case 5646: case 5647: case 5648: case 5649: case 5650: case 5651: case 5652: case 5653: case 5654: case 5655: return BlockType::CommandBlock; case 6678: case 6679: case 6680: case 6681: case 6682: case 6683: case 6684: case 6685: case 6686: case 6687: case 6688: case 6689: case 6690: case 6691: case 6692: case 6693: return BlockType::Comparator; case 15751: case 15752: case 15753: case 15754: case 15755: case 15756: case 15757: case 15758: case 15759: return BlockType::Composter; case 9650: return BlockType::Conduit; case 1422: return BlockType::Cornflower; case 17102: return BlockType::CrackedNetherBricks; case 16252: return BlockType::CrackedPolishedBlackstoneBricks; case 4497: return BlockType::CrackedStoneBricks; case 3356: return BlockType::CraftingTable; case 6570: case 6571: case 6572: case 6573: case 6574: case 6575: case 6576: case 6577: case 6578: case 6579: case 6580: case 6581: case 6582: case 6583: case 6584: case 6585: return BlockType::CreeperHead; case 6586: case 6587: case 6588: case 6589: return BlockType::CreeperWallHead; case 15479: case 15480: case 15481: case 15482: case 15483: case 15484: case 15485: case 15486: case 15487: case 15488: case 15489: case 15490: case 15491: case 15492: case 15493: case 15494: case 15495: case 15496: case 15497: case 15498: case 15499: case 15500: case 15501: case 15502: return BlockType::CrimsonButton; case 15527: case 15528: case 15529: case 15530: case 15531: case 15532: case 15533: case 15534: case 15535: case 15536: case 15537: case 15538: case 15539: case 15540: case 15541: case 15542: case 15543: case 15544: case 15545: case 15546: case 15547: case 15548: case 15549: case 15550: case 15551: case 15552: case 15553: case 15554: case 15555: case 15556: case 15557: case 15558: case 15559: case 15560: case 15561: case 15562: case 15563: case 15564: case 15565: case 15566: case 15567: case 15568: case 15569: case 15570: case 15571: case 15572: case 15573: case 15574: case 15575: case 15576: case 15577: case 15578: case 15579: case 15580: case 15581: case 15582: case 15583: case 15584: case 15585: case 15586: case 15587: case 15588: case 15589: case 15590: return BlockType::CrimsonDoor; case 15065: case 15066: case 15069: case 15070: case 15073: case 15074: case 15077: case 15078: case 15081: case 15082: case 15085: case 15086: case 15089: case 15090: case 15093: case 15094: return BlockType::CrimsonFence; case 15255: case 15256: case 15257: case 15258: case 15259: case 15260: case 15261: case 15262: case 15263: case 15264: case 15265: case 15266: case 15267: case 15268: case 15269: case 15270: case 15271: case 15272: case 15273: case 15274: case 15275: case 15276: case 15277: case 15278: case 15279: case 15280: case 15281: case 15282: case 15283: case 15284: case 15285: case 15286: return BlockType::CrimsonFenceGate; case 14988: return BlockType::CrimsonFungus; case 14981: case 14982: case 14983: return BlockType::CrimsonHyphae; case 14987: return BlockType::CrimsonNylium; case 15045: return BlockType::CrimsonPlanks; case 15059: case 15060: return BlockType::CrimsonPressurePlate; case 15044: return BlockType::CrimsonRoots; case 15656: case 15658: case 15660: case 15662: case 15664: case 15666: case 15668: case 15670: case 15672: case 15674: case 15676: case 15678: case 15680: case 15682: case 15684: case 15686: return BlockType::CrimsonSign; case 15048: case 15050: case 15052: return BlockType::CrimsonSlab; case 15320: case 15322: case 15324: case 15326: case 15328: case 15330: case 15332: case 15334: case 15336: case 15338: case 15340: case 15342: case 15344: case 15346: case 15348: case 15350: case 15352: case 15354: case 15356: case 15358: case 15360: case 15362: case 15364: case 15366: case 15368: case 15370: case 15372: case 15374: case 15376: case 15378: case 15380: case 15382: case 15384: case 15386: case 15388: case 15390: case 15392: case 15394: case 15396: case 15398: return BlockType::CrimsonStairs; case 14975: case 14976: case 14977: return BlockType::CrimsonStem; case 15128: case 15130: case 15132: case 15134: case 15136: case 15138: case 15140: case 15142: case 15144: case 15146: case 15148: case 15150: case 15152: case 15154: case 15156: case 15158: case 15160: case 15162: case 15164: case 15166: case 15168: case 15170: case 15172: case 15174: case 15176: case 15178: case 15180: case 15182: case 15184: case 15186: case 15188: case 15190: return BlockType::CrimsonTrapdoor; case 15720: case 15722: case 15724: case 15726: return BlockType::CrimsonWallSign; case 15828: return BlockType::CryingObsidian; case 8219: return BlockType::CutRedSandstone; case 8403: case 8405: case 8407: return BlockType::CutRedSandstoneSlab; case 248: return BlockType::CutSandstone; case 8355: case 8357: case 8359: return BlockType::CutSandstoneSlab; case 8041: case 8042: case 8043: case 8044: case 8045: case 8046: case 8047: case 8048: case 8049: case 8050: case 8051: case 8052: case 8053: case 8054: case 8055: case 8056: return BlockType::CyanBanner; case 1193: case 1194: case 1195: case 1196: case 1197: case 1198: case 1199: case 1200: case 1201: case 1202: case 1203: case 1204: case 1205: case 1206: case 1207: case 1208: return BlockType::CyanBed; case 7875: return BlockType::CyanCarpet; case 9447: return BlockType::CyanConcrete; case 9463: return BlockType::CyanConcretePowder; case 9410: case 9411: case 9412: case 9413: return BlockType::CyanGlazedTerracotta; case 9332: case 9333: case 9334: case 9335: case 9336: case 9337: return BlockType::CyanShulkerBox; case 4104: return BlockType::CyanStainedGlass; case 7153: case 7154: case 7157: case 7158: case 7161: case 7162: case 7165: case 7166: case 7169: case 7170: case 7173: case 7174: case 7177: case 7178: case 7181: case 7182: return BlockType::CyanStainedGlassPane; case 6856: return BlockType::CyanTerracotta; case 8189: case 8190: case 8191: case 8192: return BlockType::CyanWallBanner; case 1393: return BlockType::CyanWool; case 6618: case 6619: case 6620: case 6621: return BlockType::DamagedAnvil; case 1412: return BlockType::Dandelion; case 6466: case 6467: case 6468: case 6469: case 6470: case 6471: case 6472: case 6473: case 6474: case 6475: case 6476: case 6477: case 6478: case 6479: case 6480: case 6481: case 6482: case 6483: case 6484: case 6485: case 6486: case 6487: case 6488: case 6489: return BlockType::DarkOakButton; case 8994: case 8995: case 8996: case 8997: case 8998: case 8999: case 9000: case 9001: case 9002: case 9003: case 9004: case 9005: case 9006: case 9007: case 9008: case 9009: case 9010: case 9011: case 9012: case 9013: case 9014: case 9015: case 9016: case 9017: case 9018: case 9019: case 9020: case 9021: case 9022: case 9023: case 9024: case 9025: case 9026: case 9027: case 9028: case 9029: case 9030: case 9031: case 9032: case 9033: case 9034: case 9035: case 9036: case 9037: case 9038: case 9039: case 9040: case 9041: case 9042: case 9043: case 9044: case 9045: case 9046: case 9047: case 9048: case 9049: case 9050: case 9051: case 9052: case 9053: case 9054: case 9055: case 9056: case 9057: return BlockType::DarkOakDoor; case 8708: case 8709: case 8712: case 8713: case 8716: case 8717: case 8720: case 8721: case 8724: case 8725: case 8728: case 8729: case 8732: case 8733: case 8736: case 8737: return BlockType::DarkOakFence; case 8546: case 8547: case 8548: case 8549: case 8550: case 8551: case 8552: case 8553: case 8554: case 8555: case 8556: case 8557: case 8558: case 8559: case 8560: case 8561: case 8562: case 8563: case 8564: case 8565: case 8566: case 8567: case 8568: case 8569: case 8570: case 8571: case 8572: case 8573: case 8574: case 8575: case 8576: case 8577: return BlockType::DarkOakFenceGate; case 215: case 216: case 217: case 218: case 219: case 220: case 221: case 222: case 223: case 224: case 225: case 226: case 227: case 228: return BlockType::DarkOakLeaves; case 88: case 89: case 90: return BlockType::DarkOakLog; case 20: return BlockType::DarkOakPlanks; case 3883: case 3884: return BlockType::DarkOakPressurePlate; case 31: case 32: return BlockType::DarkOakSapling; case 3542: case 3544: case 3546: case 3548: case 3550: case 3552: case 3554: case 3556: case 3558: case 3560: case 3562: case 3564: case 3566: case 3568: case 3570: case 3572: return BlockType::DarkOakSign; case 8331: case 8333: case 8335: return BlockType::DarkOakSlab; case 7456: case 7458: case 7460: case 7462: case 7464: case 7466: case 7468: case 7470: case 7472: case 7474: case 7476: case 7478: case 7480: case 7482: case 7484: case 7486: case 7488: case 7490: case 7492: case 7494: case 7496: case 7498: case 7500: case 7502: case 7504: case 7506: case 7508: case 7510: case 7512: case 7514: case 7516: case 7518: case 7520: case 7522: case 7524: case 7526: case 7528: case 7530: case 7532: case 7534: return BlockType::DarkOakStairs; case 4432: case 4434: case 4436: case 4438: case 4440: case 4442: case 4444: case 4446: case 4448: case 4450: case 4452: case 4454: case 4456: case 4458: case 4460: case 4462: case 4464: case 4466: case 4468: case 4470: case 4472: case 4474: case 4476: case 4478: case 4480: case 4482: case 4484: case 4486: case 4488: case 4490: case 4492: case 4494: return BlockType::DarkOakTrapdoor; case 3776: case 3778: case 3780: case 3782: return BlockType::DarkOakWallSign; case 124: case 125: case 126: return BlockType::DarkOakWood; case 7603: return BlockType::DarkPrismarine; case 7857: case 7859: case 7861: return BlockType::DarkPrismarineSlab; case 7765: case 7767: case 7769: case 7771: case 7773: case 7775: case 7777: case 7779: case 7781: case 7783: case 7785: case 7787: case 7789: case 7791: case 7793: case 7795: case 7797: case 7799: case 7801: case 7803: case 7805: case 7807: case 7809: case 7811: case 7813: case 7815: case 7817: case 7819: case 7821: case 7823: case 7825: case 7827: case 7829: case 7831: case 7833: case 7835: case 7837: case 7839: case 7841: case 7843: return BlockType::DarkPrismarineStairs; case 6694: case 6695: case 6696: case 6697: case 6698: case 6699: case 6700: case 6701: case 6702: case 6703: case 6704: case 6705: case 6706: case 6707: case 6708: case 6709: case 6710: case 6711: case 6712: case 6713: case 6714: case 6715: case 6716: case 6717: case 6718: case 6719: case 6720: case 6721: case 6722: case 6723: case 6724: case 6725: return BlockType::DaylightDetector; case 9523: return BlockType::DeadBrainCoral; case 9511: return BlockType::DeadBrainCoralBlock; case 9543: return BlockType::DeadBrainCoralFan; case 9569: case 9571: case 9573: case 9575: return BlockType::DeadBrainCoralWallFan; case 9525: return BlockType::DeadBubbleCoral; case 9512: return BlockType::DeadBubbleCoralBlock; case 9545: return BlockType::DeadBubbleCoralFan; case 9577: case 9579: case 9581: case 9583: return BlockType::DeadBubbleCoralWallFan; case 1344: return BlockType::DeadBush; case 9527: return BlockType::DeadFireCoral; case 9513: return BlockType::DeadFireCoralBlock; case 9547: return BlockType::DeadFireCoralFan; case 9585: case 9587: case 9589: case 9591: return BlockType::DeadFireCoralWallFan; case 9529: return BlockType::DeadHornCoral; case 9514: return BlockType::DeadHornCoralBlock; case 9549: return BlockType::DeadHornCoralFan; case 9593: case 9595: case 9597: case 9599: return BlockType::DeadHornCoralWallFan; case 9521: return BlockType::DeadTubeCoral; case 9510: return BlockType::DeadTubeCoralBlock; case 9541: return BlockType::DeadTubeCoralFan; case 9561: case 9563: case 9565: case 9567: return BlockType::DeadTubeCoralWallFan; case 1317: case 1318: case 1319: case 1320: case 1321: case 1322: case 1323: case 1324: case 1325: case 1326: case 1327: case 1328: return BlockType::DetectorRail; case 3355: return BlockType::DiamondBlock; case 3354: return BlockType::DiamondOre; case 4: return BlockType::Diorite; case 10862: case 10864: case 10866: return BlockType::DioriteSlab; case 10710: case 10712: case 10714: case 10716: case 10718: case 10720: case 10722: case 10724: case 10726: case 10728: case 10730: case 10732: case 10734: case 10736: case 10738: case 10740: case 10742: case 10744: case 10746: case 10748: case 10750: case 10752: case 10754: case 10756: case 10758: case 10760: case 10762: case 10764: case 10766: case 10768: case 10770: case 10772: case 10774: case 10776: case 10778: case 10780: case 10782: case 10784: case 10786: case 10788: return BlockType::DioriteStairs; case 14434: case 14435: case 14436: case 14440: case 14441: case 14442: case 14446: case 14447: case 14448: case 14452: case 14453: case 14454: case 14458: case 14459: case 14460: case 14464: case 14465: case 14466: case 14470: case 14471: case 14472: case 14476: case 14477: case 14478: case 14482: case 14483: case 14484: case 14488: case 14489: case 14490: case 14494: case 14495: case 14496: case 14500: case 14501: case 14502: case 14506: case 14507: case 14508: case 14512: case 14513: case 14514: case 14518: case 14519: case 14520: case 14524: case 14525: case 14526: case 14530: case 14531: case 14532: case 14536: case 14537: case 14538: case 14542: case 14543: case 14544: case 14548: case 14549: case 14550: case 14554: case 14555: case 14556: case 14560: case 14561: case 14562: case 14566: case 14567: case 14568: case 14572: case 14573: case 14574: case 14578: case 14579: case 14580: case 14584: case 14585: case 14586: case 14590: case 14591: case 14592: case 14596: case 14597: case 14598: case 14602: case 14603: case 14604: case 14608: case 14609: case 14610: case 14614: case 14615: case 14616: case 14620: case 14621: case 14622: case 14626: case 14627: case 14628: case 14632: case 14633: case 14634: case 14638: case 14639: case 14640: case 14644: case 14645: case 14646: case 14650: case 14651: case 14652: case 14656: case 14657: case 14658: case 14662: case 14663: case 14664: case 14668: case 14669: case 14670: case 14674: case 14675: case 14676: case 14680: case 14681: case 14682: case 14686: case 14687: case 14688: case 14692: case 14693: case 14694: case 14698: case 14699: case 14700: case 14704: case 14705: case 14706: case 14710: case 14711: case 14712: case 14716: case 14717: case 14718: case 14722: case 14723: case 14724: case 14728: case 14729: case 14730: case 14734: case 14735: case 14736: case 14740: case 14741: case 14742: case 14746: case 14747: case 14748: case 14752: case 14753: case 14754: return BlockType::DioriteWall; case 10: return BlockType::Dirt; case 234: case 235: case 236: case 237: case 238: case 239: case 240: case 241: case 242: case 243: case 244: case 245: return BlockType::Dispenser; case 5155: return BlockType::DragonEgg; case 6590: case 6591: case 6592: case 6593: case 6594: case 6595: case 6596: case 6597: case 6598: case 6599: case 6600: case 6601: case 6602: case 6603: case 6604: case 6605: return BlockType::DragonHead; case 6606: case 6607: case 6608: case 6609: return BlockType::DragonWallHead; case 9497: return BlockType::DriedKelpBlock; case 6835: case 6836: case 6837: case 6838: case 6839: case 6840: case 6841: case 6842: case 6843: case 6844: case 6845: case 6846: return BlockType::Dropper; case 5403: return BlockType::EmeraldBlock; case 5250: return BlockType::EmeraldOre; case 5132: return BlockType::EnchantingTable; case 9224: return BlockType::EndGateway; case 5145: return BlockType::EndPortal; case 5146: case 5147: case 5148: case 5149: case 5150: case 5151: case 5152: case 5153: return BlockType::EndPortalFrame; case 9058: case 9059: case 9060: case 9061: case 9062: case 9063: return BlockType::EndRod; case 5154: return BlockType::EndStone; case 10820: case 10822: case 10824: return BlockType::EndStoneBrickSlab; case 10070: case 10072: case 10074: case 10076: case 10078: case 10080: case 10082: case 10084: case 10086: case 10088: case 10090: case 10092: case 10094: case 10096: case 10098: case 10100: case 10102: case 10104: case 10106: case 10108: case 10110: case 10112: case 10114: case 10116: case 10118: case 10120: case 10122: case 10124: case 10126: case 10128: case 10130: case 10132: case 10134: case 10136: case 10138: case 10140: case 10142: case 10144: case 10146: case 10148: return BlockType::EndStoneBrickStairs; case 14110: case 14111: case 14112: case 14116: case 14117: case 14118: case 14122: case 14123: case 14124: case 14128: case 14129: case 14130: case 14134: case 14135: case 14136: case 14140: case 14141: case 14142: case 14146: case 14147: case 14148: case 14152: case 14153: case 14154: case 14158: case 14159: case 14160: case 14164: case 14165: case 14166: case 14170: case 14171: case 14172: case 14176: case 14177: case 14178: case 14182: case 14183: case 14184: case 14188: case 14189: case 14190: case 14194: case 14195: case 14196: case 14200: case 14201: case 14202: case 14206: case 14207: case 14208: case 14212: case 14213: case 14214: case 14218: case 14219: case 14220: case 14224: case 14225: case 14226: case 14230: case 14231: case 14232: case 14236: case 14237: case 14238: case 14242: case 14243: case 14244: case 14248: case 14249: case 14250: case 14254: case 14255: case 14256: case 14260: case 14261: case 14262: case 14266: case 14267: case 14268: case 14272: case 14273: case 14274: case 14278: case 14279: case 14280: case 14284: case 14285: case 14286: case 14290: case 14291: case 14292: case 14296: case 14297: case 14298: case 14302: case 14303: case 14304: case 14308: case 14309: case 14310: case 14314: case 14315: case 14316: case 14320: case 14321: case 14322: case 14326: case 14327: case 14328: case 14332: case 14333: case 14334: case 14338: case 14339: case 14340: case 14344: case 14345: case 14346: case 14350: case 14351: case 14352: case 14356: case 14357: case 14358: case 14362: case 14363: case 14364: case 14368: case 14369: case 14370: case 14374: case 14375: case 14376: case 14380: case 14381: case 14382: case 14386: case 14387: case 14388: case 14392: case 14393: case 14394: case 14398: case 14399: case 14400: case 14404: case 14405: case 14406: case 14410: case 14411: case 14412: case 14416: case 14417: case 14418: case 14422: case 14423: case 14424: case 14428: case 14429: case 14430: return BlockType::EndStoneBrickWall; case 9218: return BlockType::EndStoneBricks; case 5252: case 5254: case 5256: case 5258: return BlockType::EnderChest; case 3365: case 3366: case 3367: case 3368: case 3369: case 3370: case 3371: case 3372: return BlockType::Farmland; case 1343: return BlockType::Fern; case 1440: case 1441: case 1442: case 1443: case 1444: case 1445: case 1446: case 1447: case 1448: case 1449: case 1450: case 1451: case 1452: case 1453: case 1454: case 1455: case 1456: case 1457: case 1458: case 1459: case 1460: case 1461: case 1462: case 1463: case 1464: case 1465: case 1466: case 1467: case 1468: case 1469: case 1470: case 1471: case 1472: case 1473: case 1474: case 1475: case 1476: case 1477: case 1478: case 1479: case 1480: case 1481: case 1482: case 1483: case 1484: case 1485: case 1486: case 1487: case 1488: case 1489: case 1490: case 1491: case 1492: case 1493: case 1494: case 1495: case 1496: case 1497: case 1498: case 1499: case 1500: case 1501: case 1502: case 1503: case 1504: case 1505: case 1506: case 1507: case 1508: case 1509: case 1510: case 1511: case 1512: case 1513: case 1514: case 1515: case 1516: case 1517: case 1518: case 1519: case 1520: case 1521: case 1522: case 1523: case 1524: case 1525: case 1526: case 1527: case 1528: case 1529: case 1530: case 1531: case 1532: case 1533: case 1534: case 1535: case 1536: case 1537: case 1538: case 1539: case 1540: case 1541: case 1542: case 1543: case 1544: case 1545: case 1546: case 1547: case 1548: case 1549: case 1550: case 1551: case 1552: case 1553: case 1554: case 1555: case 1556: case 1557: case 1558: case 1559: case 1560: case 1561: case 1562: case 1563: case 1564: case 1565: case 1566: case 1567: case 1568: case 1569: case 1570: case 1571: case 1572: case 1573: case 1574: case 1575: case 1576: case 1577: case 1578: case 1579: case 1580: case 1581: case 1582: case 1583: case 1584: case 1585: case 1586: case 1587: case 1588: case 1589: case 1590: case 1591: case 1592: case 1593: case 1594: case 1595: case 1596: case 1597: case 1598: case 1599: case 1600: case 1601: case 1602: case 1603: case 1604: case 1605: case 1606: case 1607: case 1608: case 1609: case 1610: case 1611: case 1612: case 1613: case 1614: case 1615: case 1616: case 1617: case 1618: case 1619: case 1620: case 1621: case 1622: case 1623: case 1624: case 1625: case 1626: case 1627: case 1628: case 1629: case 1630: case 1631: case 1632: case 1633: case 1634: case 1635: case 1636: case 1637: case 1638: case 1639: case 1640: case 1641: case 1642: case 1643: case 1644: case 1645: case 1646: case 1647: case 1648: case 1649: case 1650: case 1651: case 1652: case 1653: case 1654: case 1655: case 1656: case 1657: case 1658: case 1659: case 1660: case 1661: case 1662: case 1663: case 1664: case 1665: case 1666: case 1667: case 1668: case 1669: case 1670: case 1671: case 1672: case 1673: case 1674: case 1675: case 1676: case 1677: case 1678: case 1679: case 1680: case 1681: case 1682: case 1683: case 1684: case 1685: case 1686: case 1687: case 1688: case 1689: case 1690: case 1691: case 1692: case 1693: case 1694: case 1695: case 1696: case 1697: case 1698: case 1699: case 1700: case 1701: case 1702: case 1703: case 1704: case 1705: case 1706: case 1707: case 1708: case 1709: case 1710: case 1711: case 1712: case 1713: case 1714: case 1715: case 1716: case 1717: case 1718: case 1719: case 1720: case 1721: case 1722: case 1723: case 1724: case 1725: case 1726: case 1727: case 1728: case 1729: case 1730: case 1731: case 1732: case 1733: case 1734: case 1735: case 1736: case 1737: case 1738: case 1739: case 1740: case 1741: case 1742: case 1743: case 1744: case 1745: case 1746: case 1747: case 1748: case 1749: case 1750: case 1751: case 1752: case 1753: case 1754: case 1755: case 1756: case 1757: case 1758: case 1759: case 1760: case 1761: case 1762: case 1763: case 1764: case 1765: case 1766: case 1767: case 1768: case 1769: case 1770: case 1771: case 1772: case 1773: case 1774: case 1775: case 1776: case 1777: case 1778: case 1779: case 1780: case 1781: case 1782: case 1783: case 1784: case 1785: case 1786: case 1787: case 1788: case 1789: case 1790: case 1791: case 1792: case 1793: case 1794: case 1795: case 1796: case 1797: case 1798: case 1799: case 1800: case 1801: case 1802: case 1803: case 1804: case 1805: case 1806: case 1807: case 1808: case 1809: case 1810: case 1811: case 1812: case 1813: case 1814: case 1815: case 1816: case 1817: case 1818: case 1819: case 1820: case 1821: case 1822: case 1823: case 1824: case 1825: case 1826: case 1827: case 1828: case 1829: case 1830: case 1831: case 1832: case 1833: case 1834: case 1835: case 1836: case 1837: case 1838: case 1839: case 1840: case 1841: case 1842: case 1843: case 1844: case 1845: case 1846: case 1847: case 1848: case 1849: case 1850: case 1851: case 1852: case 1853: case 1854: case 1855: case 1856: case 1857: case 1858: case 1859: case 1860: case 1861: case 1862: case 1863: case 1864: case 1865: case 1866: case 1867: case 1868: case 1869: case 1870: case 1871: case 1872: case 1873: case 1874: case 1875: case 1876: case 1877: case 1878: case 1879: case 1880: case 1881: case 1882: case 1883: case 1884: case 1885: case 1886: case 1887: case 1888: case 1889: case 1890: case 1891: case 1892: case 1893: case 1894: case 1895: case 1896: case 1897: case 1898: case 1899: case 1900: case 1901: case 1902: case 1903: case 1904: case 1905: case 1906: case 1907: case 1908: case 1909: case 1910: case 1911: case 1912: case 1913: case 1914: case 1915: case 1916: case 1917: case 1918: case 1919: case 1920: case 1921: case 1922: case 1923: case 1924: case 1925: case 1926: case 1927: case 1928: case 1929: case 1930: case 1931: case 1932: case 1933: case 1934: case 1935: case 1936: case 1937: case 1938: case 1939: case 1940: case 1941: case 1942: case 1943: case 1944: case 1945: case 1946: case 1947: case 1948: case 1949: case 1950: case 1951: return BlockType::Fire; case 9537: return BlockType::FireCoral; case 9518: return BlockType::FireCoralBlock; case 9557: return BlockType::FireCoralFan; case 9625: case 9627: case 9629: case 9631: return BlockType::FireCoralWallFan; case 14820: return BlockType::FletchingTable; case 6305: return BlockType::FlowerPot; case 9249: case 9250: case 9251: case 9252: return BlockType::FrostedIce; case 3373: case 3374: case 3375: case 3376: case 3377: case 3378: case 3379: case 3380: return BlockType::Furnace; case 16664: return BlockType::GildedBlackstone; case 231: return BlockType::Glass; case 4733: case 4734: case 4737: case 4738: case 4741: case 4742: case 4745: case 4746: case 4749: case 4750: case 4753: case 4754: case 4757: case 4758: case 4761: case 4762: return BlockType::GlassPane; case 4013: return BlockType::Glowstone; case 1427: return BlockType::GoldBlock; case 69: return BlockType::GoldOre; case 2: return BlockType::Granite; case 10838: case 10840: case 10842: return BlockType::GraniteSlab; case 10390: case 10392: case 10394: case 10396: case 10398: case 10400: case 10402: case 10404: case 10406: case 10408: case 10410: case 10412: case 10414: case 10416: case 10418: case 10420: case 10422: case 10424: case 10426: case 10428: case 10430: case 10432: case 10434: case 10436: case 10438: case 10440: case 10442: case 10444: case 10446: case 10448: case 10450: case 10452: case 10454: case 10456: case 10458: case 10460: case 10462: case 10464: case 10466: case 10468: return BlockType::GraniteStairs; case 12166: case 12167: case 12168: case 12172: case 12173: case 12174: case 12178: case 12179: case 12180: case 12184: case 12185: case 12186: case 12190: case 12191: case 12192: case 12196: case 12197: case 12198: case 12202: case 12203: case 12204: case 12208: case 12209: case 12210: case 12214: case 12215: case 12216: case 12220: case 12221: case 12222: case 12226: case 12227: case 12228: case 12232: case 12233: case 12234: case 12238: case 12239: case 12240: case 12244: case 12245: case 12246: case 12250: case 12251: case 12252: case 12256: case 12257: case 12258: case 12262: case 12263: case 12264: case 12268: case 12269: case 12270: case 12274: case 12275: case 12276: case 12280: case 12281: case 12282: case 12286: case 12287: case 12288: case 12292: case 12293: case 12294: case 12298: case 12299: case 12300: case 12304: case 12305: case 12306: case 12310: case 12311: case 12312: case 12316: case 12317: case 12318: case 12322: case 12323: case 12324: case 12328: case 12329: case 12330: case 12334: case 12335: case 12336: case 12340: case 12341: case 12342: case 12346: case 12347: case 12348: case 12352: case 12353: case 12354: case 12358: case 12359: case 12360: case 12364: case 12365: case 12366: case 12370: case 12371: case 12372: case 12376: case 12377: case 12378: case 12382: case 12383: case 12384: case 12388: case 12389: case 12390: case 12394: case 12395: case 12396: case 12400: case 12401: case 12402: case 12406: case 12407: case 12408: case 12412: case 12413: case 12414: case 12418: case 12419: case 12420: case 12424: case 12425: case 12426: case 12430: case 12431: case 12432: case 12436: case 12437: case 12438: case 12442: case 12443: case 12444: case 12448: case 12449: case 12450: case 12454: case 12455: case 12456: case 12460: case 12461: case 12462: case 12466: case 12467: case 12468: case 12472: case 12473: case 12474: case 12478: case 12479: case 12480: case 12484: case 12485: case 12486: return BlockType::GraniteWall; case 1342: return BlockType::Grass; case 8: case 9: return BlockType::GrassBlock; case 9223: return BlockType::GrassPath; case 68: return BlockType::Gravel; case 8009: case 8010: case 8011: case 8012: case 8013: case 8014: case 8015: case 8016: case 8017: case 8018: case 8019: case 8020: case 8021: case 8022: case 8023: case 8024: return BlockType::GrayBanner; case 1161: case 1162: case 1163: case 1164: case 1165: case 1166: case 1167: case 1168: case 1169: case 1170: case 1171: case 1172: case 1173: case 1174: case 1175: case 1176: return BlockType::GrayBed; case 7873: return BlockType::GrayCarpet; case 9445: return BlockType::GrayConcrete; case 9461: return BlockType::GrayConcretePowder; case 9402: case 9403: case 9404: case 9405: return BlockType::GrayGlazedTerracotta; case 9320: case 9321: case 9322: case 9323: case 9324: case 9325: return BlockType::GrayShulkerBox; case 4102: return BlockType::GrayStainedGlass; case 7089: case 7090: case 7093: case 7094: case 7097: case 7098: case 7101: case 7102: case 7105: case 7106: case 7109: case 7110: case 7113: case 7114: case 7117: case 7118: return BlockType::GrayStainedGlassPane; case 6854: return BlockType::GrayTerracotta; case 8181: case 8182: case 8183: case 8184: return BlockType::GrayWallBanner; case 1391: return BlockType::GrayWool; case 8105: case 8106: case 8107: case 8108: case 8109: case 8110: case 8111: case 8112: case 8113: case 8114: case 8115: case 8116: case 8117: case 8118: case 8119: case 8120: return BlockType::GreenBanner; case 1257: case 1258: case 1259: case 1260: case 1261: case 1262: case 1263: case 1264: case 1265: case 1266: case 1267: case 1268: case 1269: case 1270: case 1271: case 1272: return BlockType::GreenBed; case 7879: return BlockType::GreenCarpet; case 9451: return BlockType::GreenConcrete; case 9467: return BlockType::GreenConcretePowder; case 9426: case 9427: case 9428: case 9429: return BlockType::GreenGlazedTerracotta; case 9356: case 9357: case 9358: case 9359: case 9360: case 9361: return BlockType::GreenShulkerBox; case 4108: return BlockType::GreenStainedGlass; case 7281: case 7282: case 7285: case 7286: case 7289: case 7290: case 7293: case 7294: case 7297: case 7298: case 7301: case 7302: case 7305: case 7306: case 7309: case 7310: return BlockType::GreenStainedGlassPane; case 6860: return BlockType::GreenTerracotta; case 8205: case 8206: case 8207: case 8208: return BlockType::GreenWallBanner; case 1397: return BlockType::GreenWool; case 14821: case 14822: case 14823: case 14824: case 14825: case 14826: case 14827: case 14828: case 14829: case 14830: case 14831: case 14832: return BlockType::Grindstone; case 7863: case 7864: case 7865: return BlockType::HayBale; case 6662: case 6663: case 6664: case 6665: case 6666: case 6667: case 6668: case 6669: case 6670: case 6671: case 6672: case 6673: case 6674: case 6675: case 6676: case 6677: return BlockType::HeavyWeightedPressurePlate; case 15824: return BlockType::HoneyBlock; case 15825: return BlockType::HoneycombBlock; case 6728: case 6729: case 6730: case 6731: case 6732: case 6733: case 6734: case 6735: case 6736: case 6737: return BlockType::Hopper; case 9539: return BlockType::HornCoral; case 9519: return BlockType::HornCoralBlock; case 9559: return BlockType::HornCoralFan; case 9633: case 9635: case 9637: case 9639: return BlockType::HornCoralWallFan; case 3929: return BlockType::Ice; case 4504: return BlockType::InfestedChiseledStoneBricks; case 4500: return BlockType::InfestedCobblestone; case 4503: return BlockType::InfestedCrackedStoneBricks; case 4502: return BlockType::InfestedMossyStoneBricks; case 4499: return BlockType::InfestedStone; case 4501: return BlockType::InfestedStoneBricks; case 4699: case 4700: case 4703: case 4704: case 4707: case 4708: case 4711: case 4712: case 4715: case 4716: case 4719: case 4720: case 4723: case 4724: case 4727: case 4728: return BlockType::IronBars; case 1428: return BlockType::IronBlock; case 3809: case 3810: case 3811: case 3812: case 3813: case 3814: case 3815: case 3816: case 3817: case 3818: case 3819: case 3820: case 3821: case 3822: case 3823: case 3824: case 3825: case 3826: case 3827: case 3828: case 3829: case 3830: case 3831: case 3832: case 3833: case 3834: case 3835: case 3836: case 3837: case 3838: case 3839: case 3840: case 3841: case 3842: case 3843: case 3844: case 3845: case 3846: case 3847: case 3848: case 3849: case 3850: case 3851: case 3852: case 3853: case 3854: case 3855: case 3856: case 3857: case 3858: case 3859: case 3860: case 3861: case 3862: case 3863: case 3864: case 3865: case 3866: case 3867: case 3868: case 3869: case 3870: case 3871: case 3872: return BlockType::IronDoor; case 70: return BlockType::IronOre; case 7538: case 7540: case 7542: case 7544: case 7546: case 7548: case 7550: case 7552: case 7554: case 7556: case 7558: case 7560: case 7562: case 7564: case 7566: case 7568: case 7570: case 7572: case 7574: case 7576: case 7578: case 7580: case 7582: case 7584: case 7586: case 7588: case 7590: case 7592: case 7594: case 7596: case 7598: case 7600: return BlockType::IronTrapdoor; case 4020: case 4021: case 4022: case 4023: return BlockType::JackOLantern; case 15739: case 15740: case 15741: case 15742: case 15743: case 15744: case 15745: case 15746: case 15747: case 15748: case 15749: case 15750: return BlockType::Jigsaw; case 3964: case 3965: return BlockType::Jukebox; case 6418: case 6419: case 6420: case 6421: case 6422: case 6423: case 6424: case 6425: case 6426: case 6427: case 6428: case 6429: case 6430: case 6431: case 6432: case 6433: case 6434: case 6435: case 6436: case 6437: case 6438: case 6439: case 6440: case 6441: return BlockType::JungleButton; case 8866: case 8867: case 8868: case 8869: case 8870: case 8871: case 8872: case 8873: case 8874: case 8875: case 8876: case 8877: case 8878: case 8879: case 8880: case 8881: case 8882: case 8883: case 8884: case 8885: case 8886: case 8887: case 8888: case 8889: case 8890: case 8891: case 8892: case 8893: case 8894: case 8895: case 8896: case 8897: case 8898: case 8899: case 8900: case 8901: case 8902: case 8903: case 8904: case 8905: case 8906: case 8907: case 8908: case 8909: case 8910: case 8911: case 8912: case 8913: case 8914: case 8915: case 8916: case 8917: case 8918: case 8919: case 8920: case 8921: case 8922: case 8923: case 8924: case 8925: case 8926: case 8927: case 8928: case 8929: return BlockType::JungleDoor; case 8644: case 8645: case 8648: case 8649: case 8652: case 8653: case 8656: case 8657: case 8660: case 8661: case 8664: case 8665: case 8668: case 8669: case 8672: case 8673: return BlockType::JungleFence; case 8482: case 8483: case 8484: case 8485: case 8486: case 8487: case 8488: case 8489: case 8490: case 8491: case 8492: case 8493: case 8494: case 8495: case 8496: case 8497: case 8498: case 8499: case 8500: case 8501: case 8502: case 8503: case 8504: case 8505: case 8506: case 8507: case 8508: case 8509: case 8510: case 8511: case 8512: case 8513: return BlockType::JungleFenceGate; case 187: case 188: case 189: case 190: case 191: case 192: case 193: case 194: case 195: case 196: case 197: case 198: case 199: case 200: return BlockType::JungleLeaves; case 82: case 83: case 84: return BlockType::JungleLog; case 18: return BlockType::JunglePlanks; case 3879: case 3880: return BlockType::JunglePressurePlate; case 27: case 28: return BlockType::JungleSapling; case 3510: case 3512: case 3514: case 3516: case 3518: case 3520: case 3522: case 3524: case 3526: case 3528: case 3530: case 3532: case 3534: case 3536: case 3538: case 3540: return BlockType::JungleSign; case 8319: case 8321: case 8323: return BlockType::JungleSlab; case 5565: case 5567: case 5569: case 5571: case 5573: case 5575: case 5577: case 5579: case 5581: case 5583: case 5585: case 5587: case 5589: case 5591: case 5593: case 5595: case 5597: case 5599: case 5601: case 5603: case 5605: case 5607: case 5609: case 5611: case 5613: case 5615: case 5617: case 5619: case 5621: case 5623: case 5625: case 5627: case 5629: case 5631: case 5633: case 5635: case 5637: case 5639: case 5641: case 5643: return BlockType::JungleStairs; case 4304: case 4306: case 4308: case 4310: case 4312: case 4314: case 4316: case 4318: case 4320: case 4322: case 4324: case 4326: case 4328: case 4330: case 4332: case 4334: case 4336: case 4338: case 4340: case 4342: case 4344: case 4346: case 4348: case 4350: case 4352: case 4354: case 4356: case 4358: case 4360: case 4362: case 4364: case 4366: return BlockType::JungleTrapdoor; case 3768: case 3770: case 3772: case 3774: return BlockType::JungleWallSign; case 118: case 119: case 120: return BlockType::JungleWood; case 9470: case 9471: case 9472: case 9473: case 9474: case 9475: case 9476: case 9477: case 9478: case 9479: case 9480: case 9481: case 9482: case 9483: case 9484: case 9485: case 9486: case 9487: case 9488: case 9489: case 9490: case 9491: case 9492: case 9493: case 9494: case 9495: return BlockType::Kelp; case 9496: return BlockType::KelpPlant; case 3638: case 3640: case 3642: case 3644: return BlockType::Ladder; case 14886: case 14887: return BlockType::Lantern; case 233: return BlockType::LapisBlock; case 232: return BlockType::LapisOre; case 7895: case 7896: return BlockType::LargeFern; case 50: case 51: case 52: case 53: case 54: case 55: case 56: case 57: case 58: case 59: case 60: case 61: case 62: case 63: case 64: case 65: return BlockType::Lava; case 14833: case 14834: case 14835: case 14836: case 14837: case 14838: case 14839: case 14840: case 14841: case 14842: case 14843: case 14844: case 14845: case 14846: case 14847: case 14848: return BlockType::Lectern; case 3783: case 3784: case 3785: case 3786: case 3787: case 3788: case 3789: case 3790: case 3791: case 3792: case 3793: case 3794: case 3795: case 3796: case 3797: case 3798: case 3799: case 3800: case 3801: case 3802: case 3803: case 3804: case 3805: case 3806: return BlockType::Lever; case 7945: case 7946: case 7947: case 7948: case 7949: case 7950: case 7951: case 7952: case 7953: case 7954: case 7955: case 7956: case 7957: case 7958: case 7959: case 7960: return BlockType::LightBlueBanner; case 1097: case 1098: case 1099: case 1100: case 1101: case 1102: case 1103: case 1104: case 1105: case 1106: case 1107: case 1108: case 1109: case 1110: case 1111: case 1112: return BlockType::LightBlueBed; case 7869: return BlockType::LightBlueCarpet; case 9441: return BlockType::LightBlueConcrete; case 9457: return BlockType::LightBlueConcretePowder; case 9386: case 9387: case 9388: case 9389: return BlockType::LightBlueGlazedTerracotta; case 9296: case 9297: case 9298: case 9299: case 9300: case 9301: return BlockType::LightBlueShulkerBox; case 4098: return BlockType::LightBlueStainedGlass; case 6961: case 6962: case 6965: case 6966: case 6969: case 6970: case 6973: case 6974: case 6977: case 6978: case 6981: case 6982: case 6985: case 6986: case 6989: case 6990: return BlockType::LightBlueStainedGlassPane; case 6850: return BlockType::LightBlueTerracotta; case 8165: case 8166: case 8167: case 8168: return BlockType::LightBlueWallBanner; case 1387: return BlockType::LightBlueWool; case 8025: case 8026: case 8027: case 8028: case 8029: case 8030: case 8031: case 8032: case 8033: case 8034: case 8035: case 8036: case 8037: case 8038: case 8039: case 8040: return BlockType::LightGrayBanner; case 1177: case 1178: case 1179: case 1180: case 1181: case 1182: case 1183: case 1184: case 1185: case 1186: case 1187: case 1188: case 1189: case 1190: case 1191: case 1192: return BlockType::LightGrayBed; case 7874: return BlockType::LightGrayCarpet; case 9446: return BlockType::LightGrayConcrete; case 9462: return BlockType::LightGrayConcretePowder; case 9406: case 9407: case 9408: case 9409: return BlockType::LightGrayGlazedTerracotta; case 9326: case 9327: case 9328: case 9329: case 9330: case 9331: return BlockType::LightGrayShulkerBox; case 4103: return BlockType::LightGrayStainedGlass; case 7121: case 7122: case 7125: case 7126: case 7129: case 7130: case 7133: case 7134: case 7137: case 7138: case 7141: case 7142: case 7145: case 7146: case 7149: case 7150: return BlockType::LightGrayStainedGlassPane; case 6855: return BlockType::LightGrayTerracotta; case 8185: case 8186: case 8187: case 8188: return BlockType::LightGrayWallBanner; case 1392: return BlockType::LightGrayWool; case 6646: case 6647: case 6648: case 6649: case 6650: case 6651: case 6652: case 6653: case 6654: case 6655: case 6656: case 6657: case 6658: case 6659: case 6660: case 6661: return BlockType::LightWeightedPressurePlate; case 7887: case 7888: return BlockType::Lilac; case 1424: return BlockType::LilyOfTheValley; case 5014: return BlockType::LilyPad; case 7977: case 7978: case 7979: case 7980: case 7981: case 7982: case 7983: case 7984: case 7985: case 7986: case 7987: case 7988: case 7989: case 7990: case 7991: case 7992: return BlockType::LimeBanner; case 1129: case 1130: case 1131: case 1132: case 1133: case 1134: case 1135: case 1136: case 1137: case 1138: case 1139: case 1140: case 1141: case 1142: case 1143: case 1144: return BlockType::LimeBed; case 7871: return BlockType::LimeCarpet; case 9443: return BlockType::LimeConcrete; case 9459: return BlockType::LimeConcretePowder; case 9394: case 9395: case 9396: case 9397: return BlockType::LimeGlazedTerracotta; case 9308: case 9309: case 9310: case 9311: case 9312: case 9313: return BlockType::LimeShulkerBox; case 4100: return BlockType::LimeStainedGlass; case 7025: case 7026: case 7029: case 7030: case 7033: case 7034: case 7037: case 7038: case 7041: case 7042: case 7045: case 7046: case 7049: case 7050: case 7053: case 7054: return BlockType::LimeStainedGlassPane; case 6852: return BlockType::LimeTerracotta; case 8173: case 8174: case 8175: case 8176: return BlockType::LimeWallBanner; case 1389: return BlockType::LimeWool; case 15838: return BlockType::Lodestone; case 14787: case 14788: case 14789: case 14790: return BlockType::Loom; case 7929: case 7930: case 7931: case 7932: case 7933: case 7934: case 7935: case 7936: case 7937: case 7938: case 7939: case 7940: case 7941: case 7942: case 7943: case 7944: return BlockType::MagentaBanner; case 1081: case 1082: case 1083: case 1084: case 1085: case 1086: case 1087: case 1088: case 1089: case 1090: case 1091: case 1092: case 1093: case 1094: case 1095: case 1096: return BlockType::MagentaBed; case 7868: return BlockType::MagentaCarpet; case 9440: return BlockType::MagentaConcrete; case 9456: return BlockType::MagentaConcretePowder; case 9382: case 9383: case 9384: case 9385: return BlockType::MagentaGlazedTerracotta; case 9290: case 9291: case 9292: case 9293: case 9294: case 9295: return BlockType::MagentaShulkerBox; case 4097: return BlockType::MagentaStainedGlass; case 6929: case 6930: case 6933: case 6934: case 6937: case 6938: case 6941: case 6942: case 6945: case 6946: case 6949: case 6950: case 6953: case 6954: case 6957: case 6958: return BlockType::MagentaStainedGlassPane; case 6849: return BlockType::MagentaTerracotta; case 8161: case 8162: case 8163: case 8164: return BlockType::MagentaWallBanner; case 1386: return BlockType::MagentaWool; case 9253: return BlockType::MagmaBlock; case 4763: return BlockType::Melon; case 4780: case 4781: case 4782: case 4783: case 4784: case 4785: case 4786: case 4787: return BlockType::MelonStem; case 1433: return BlockType::MossyCobblestone; case 10814: case 10816: case 10818: return BlockType::MossyCobblestoneSlab; case 9990: case 9992: case 9994: case 9996: case 9998: case 10000: case 10002: case 10004: case 10006: case 10008: case 10010: case 10012: case 10014: case 10016: case 10018: case 10020: case 10022: case 10024: case 10026: case 10028: case 10030: case 10032: case 10034: case 10036: case 10038: case 10040: case 10042: case 10044: case 10046: case 10048: case 10050: case 10052: case 10054: case 10056: case 10058: case 10060: case 10062: case 10064: case 10066: case 10068: return BlockType::MossyCobblestoneStairs; case 5984: case 5985: case 5986: case 5990: case 5991: case 5992: case 5996: case 5997: case 5998: case 6002: case 6003: case 6004: case 6008: case 6009: case 6010: case 6014: case 6015: case 6016: case 6020: case 6021: case 6022: case 6026: case 6027: case 6028: case 6032: case 6033: case 6034: case 6038: case 6039: case 6040: case 6044: case 6045: case 6046: case 6050: case 6051: case 6052: case 6056: case 6057: case 6058: case 6062: case 6063: case 6064: case 6068: case 6069: case 6070: case 6074: case 6075: case 6076: case 6080: case 6081: case 6082: case 6086: case 6087: case 6088: case 6092: case 6093: case 6094: case 6098: case 6099: case 6100: case 6104: case 6105: case 6106: case 6110: case 6111: case 6112: case 6116: case 6117: case 6118: case 6122: case 6123: case 6124: case 6128: case 6129: case 6130: case 6134: case 6135: case 6136: case 6140: case 6141: case 6142: case 6146: case 6147: case 6148: case 6152: case 6153: case 6154: case 6158: case 6159: case 6160: case 6164: case 6165: case 6166: case 6170: case 6171: case 6172: case 6176: case 6177: case 6178: case 6182: case 6183: case 6184: case 6188: case 6189: case 6190: case 6194: case 6195: case 6196: case 6200: case 6201: case 6202: case 6206: case 6207: case 6208: case 6212: case 6213: case 6214: case 6218: case 6219: case 6220: case 6224: case 6225: case 6226: case 6230: case 6231: case 6232: case 6236: case 6237: case 6238: case 6242: case 6243: case 6244: case 6248: case 6249: case 6250: case 6254: case 6255: case 6256: case 6260: case 6261: case 6262: case 6266: case 6267: case 6268: case 6272: case 6273: case 6274: case 6278: case 6279: case 6280: case 6284: case 6285: case 6286: case 6290: case 6291: case 6292: case 6296: case 6297: case 6298: case 6302: case 6303: case 6304: return BlockType::MossyCobblestoneWall; case 10802: case 10804: case 10806: return BlockType::MossyStoneBrickSlab; case 9830: case 9832: case 9834: case 9836: case 9838: case 9840: case 9842: case 9844: case 9846: case 9848: case 9850: case 9852: case 9854: case 9856: case 9858: case 9860: case 9862: case 9864: case 9866: case 9868: case 9870: case 9872: case 9874: case 9876: case 9878: case 9880: case 9882: case 9884: case 9886: case 9888: case 9890: case 9892: case 9894: case 9896: case 9898: case 9900: case 9902: case 9904: case 9906: case 9908: return BlockType::MossyStoneBrickStairs; case 11842: case 11843: case 11844: case 11848: case 11849: case 11850: case 11854: case 11855: case 11856: case 11860: case 11861: case 11862: case 11866: case 11867: case 11868: case 11872: case 11873: case 11874: case 11878: case 11879: case 11880: case 11884: case 11885: case 11886: case 11890: case 11891: case 11892: case 11896: case 11897: case 11898: case 11902: case 11903: case 11904: case 11908: case 11909: case 11910: case 11914: case 11915: case 11916: case 11920: case 11921: case 11922: case 11926: case 11927: case 11928: case 11932: case 11933: case 11934: case 11938: case 11939: case 11940: case 11944: case 11945: case 11946: case 11950: case 11951: case 11952: case 11956: case 11957: case 11958: case 11962: case 11963: case 11964: case 11968: case 11969: case 11970: case 11974: case 11975: case 11976: case 11980: case 11981: case 11982: case 11986: case 11987: case 11988: case 11992: case 11993: case 11994: case 11998: case 11999: case 12000: case 12004: case 12005: case 12006: case 12010: case 12011: case 12012: case 12016: case 12017: case 12018: case 12022: case 12023: case 12024: case 12028: case 12029: case 12030: case 12034: case 12035: case 12036: case 12040: case 12041: case 12042: case 12046: case 12047: case 12048: case 12052: case 12053: case 12054: case 12058: case 12059: case 12060: case 12064: case 12065: case 12066: case 12070: case 12071: case 12072: case 12076: case 12077: case 12078: case 12082: case 12083: case 12084: case 12088: case 12089: case 12090: case 12094: case 12095: case 12096: case 12100: case 12101: case 12102: case 12106: case 12107: case 12108: case 12112: case 12113: case 12114: case 12118: case 12119: case 12120: case 12124: case 12125: case 12126: case 12130: case 12131: case 12132: case 12136: case 12137: case 12138: case 12142: case 12143: case 12144: case 12148: case 12149: case 12150: case 12154: case 12155: case 12156: case 12160: case 12161: case 12162: return BlockType::MossyStoneBrickWall; case 4496: return BlockType::MossyStoneBricks; case 1400: case 1401: case 1402: case 1403: case 1404: case 1405: case 1406: case 1407: case 1408: case 1409: case 1410: case 1411: return BlockType::MovingPiston; case 4633: case 4634: case 4635: case 4636: case 4637: case 4638: case 4639: case 4640: case 4641: case 4642: case 4643: case 4644: case 4645: case 4646: case 4647: case 4648: case 4649: case 4650: case 4651: case 4652: case 4653: case 4654: case 4655: case 4656: case 4657: case 4658: case 4659: case 4660: case 4661: case 4662: case 4663: case 4664: case 4665: case 4666: case 4667: case 4668: case 4669: case 4670: case 4671: case 4672: case 4673: case 4674: case 4675: case 4676: case 4677: case 4678: case 4679: case 4680: case 4681: case 4682: case 4683: case 4684: case 4685: case 4686: case 4687: case 4688: case 4689: case 4690: case 4691: case 4692: case 4693: case 4694: case 4695: case 4696: return BlockType::MushroomStem; case 5012: case 5013: return BlockType::Mycelium; case 5018: case 5019: case 5022: case 5023: case 5026: case 5027: case 5030: case 5031: case 5034: case 5035: case 5038: case 5039: case 5042: case 5043: case 5046: case 5047: return BlockType::NetherBrickFence; case 8385: case 8387: case 8389: return BlockType::NetherBrickSlab; case 5049: case 5051: case 5053: case 5055: case 5057: case 5059: case 5061: case 5063: case 5065: case 5067: case 5069: case 5071: case 5073: case 5075: case 5077: case 5079: case 5081: case 5083: case 5085: case 5087: case 5089: case 5091: case 5093: case 5095: case 5097: case 5099: case 5101: case 5103: case 5105: case 5107: case 5109: case 5111: case 5113: case 5115: case 5117: case 5119: case 5121: case 5123: case 5125: case 5127: return BlockType::NetherBrickStairs; case 12814: case 12815: case 12816: case 12820: case 12821: case 12822: case 12826: case 12827: case 12828: case 12832: case 12833: case 12834: case 12838: case 12839: case 12840: case 12844: case 12845: case 12846: case 12850: case 12851: case 12852: case 12856: case 12857: case 12858: case 12862: case 12863: case 12864: case 12868: case 12869: case 12870: case 12874: case 12875: case 12876: case 12880: case 12881: case 12882: case 12886: case 12887: case 12888: case 12892: case 12893: case 12894: case 12898: case 12899: case 12900: case 12904: case 12905: case 12906: case 12910: case 12911: case 12912: case 12916: case 12917: case 12918: case 12922: case 12923: case 12924: case 12928: case 12929: case 12930: case 12934: case 12935: case 12936: case 12940: case 12941: case 12942: case 12946: case 12947: case 12948: case 12952: case 12953: case 12954: case 12958: case 12959: case 12960: case 12964: case 12965: case 12966: case 12970: case 12971: case 12972: case 12976: case 12977: case 12978: case 12982: case 12983: case 12984: case 12988: case 12989: case 12990: case 12994: case 12995: case 12996: case 13000: case 13001: case 13002: case 13006: case 13007: case 13008: case 13012: case 13013: case 13014: case 13018: case 13019: case 13020: case 13024: case 13025: case 13026: case 13030: case 13031: case 13032: case 13036: case 13037: case 13038: case 13042: case 13043: case 13044: case 13048: case 13049: case 13050: case 13054: case 13055: case 13056: case 13060: case 13061: case 13062: case 13066: case 13067: case 13068: case 13072: case 13073: case 13074: case 13078: case 13079: case 13080: case 13084: case 13085: case 13086: case 13090: case 13091: case 13092: case 13096: case 13097: case 13098: case 13102: case 13103: case 13104: case 13108: case 13109: case 13110: case 13114: case 13115: case 13116: case 13120: case 13121: case 13122: case 13126: case 13127: case 13128: case 13132: case 13133: case 13134: return BlockType::NetherBrickWall; case 5015: return BlockType::NetherBricks; case 72: return BlockType::NetherGoldOre; case 4014: case 4015: return BlockType::NetherPortal; case 6727: return BlockType::NetherQuartzOre; case 14974: return BlockType::NetherSprouts; case 5128: case 5129: case 5130: case 5131: return BlockType::NetherWart; case 9254: return BlockType::NetherWartBlock; case 15826: return BlockType::NetheriteBlock; case 3999: return BlockType::Netherrack; case 249: case 250: case 251: case 252: case 253: case 254: case 255: case 256: case 257: case 258: case 259: case 260: case 261: case 262: case 263: case 264: case 265: case 266: case 267: case 268: case 269: case 270: case 271: case 272: case 273: case 274: case 275: case 276: case 277: case 278: case 279: case 280: case 281: case 282: case 283: case 284: case 285: case 286: case 287: case 288: case 289: case 290: case 291: case 292: case 293: case 294: case 295: case 296: case 297: case 298: case 299: case 300: case 301: case 302: case 303: case 304: case 305: case 306: case 307: case 308: case 309: case 310: case 311: case 312: case 313: case 314: case 315: case 316: case 317: case 318: case 319: case 320: case 321: case 322: case 323: case 324: case 325: case 326: case 327: case 328: case 329: case 330: case 331: case 332: case 333: case 334: case 335: case 336: case 337: case 338: case 339: case 340: case 341: case 342: case 343: case 344: case 345: case 346: case 347: case 348: case 349: case 350: case 351: case 352: case 353: case 354: case 355: case 356: case 357: case 358: case 359: case 360: case 361: case 362: case 363: case 364: case 365: case 366: case 367: case 368: case 369: case 370: case 371: case 372: case 373: case 374: case 375: case 376: case 377: case 378: case 379: case 380: case 381: case 382: case 383: case 384: case 385: case 386: case 387: case 388: case 389: case 390: case 391: case 392: case 393: case 394: case 395: case 396: case 397: case 398: case 399: case 400: case 401: case 402: case 403: case 404: case 405: case 406: case 407: case 408: case 409: case 410: case 411: case 412: case 413: case 414: case 415: case 416: case 417: case 418: case 419: case 420: case 421: case 422: case 423: case 424: case 425: case 426: case 427: case 428: case 429: case 430: case 431: case 432: case 433: case 434: case 435: case 436: case 437: case 438: case 439: case 440: case 441: case 442: case 443: case 444: case 445: case 446: case 447: case 448: case 449: case 450: case 451: case 452: case 453: case 454: case 455: case 456: case 457: case 458: case 459: case 460: case 461: case 462: case 463: case 464: case 465: case 466: case 467: case 468: case 469: case 470: case 471: case 472: case 473: case 474: case 475: case 476: case 477: case 478: case 479: case 480: case 481: case 482: case 483: case 484: case 485: case 486: case 487: case 488: case 489: case 490: case 491: case 492: case 493: case 494: case 495: case 496: case 497: case 498: case 499: case 500: case 501: case 502: case 503: case 504: case 505: case 506: case 507: case 508: case 509: case 510: case 511: case 512: case 513: case 514: case 515: case 516: case 517: case 518: case 519: case 520: case 521: case 522: case 523: case 524: case 525: case 526: case 527: case 528: case 529: case 530: case 531: case 532: case 533: case 534: case 535: case 536: case 537: case 538: case 539: case 540: case 541: case 542: case 543: case 544: case 545: case 546: case 547: case 548: case 549: case 550: case 551: case 552: case 553: case 554: case 555: case 556: case 557: case 558: case 559: case 560: case 561: case 562: case 563: case 564: case 565: case 566: case 567: case 568: case 569: case 570: case 571: case 572: case 573: case 574: case 575: case 576: case 577: case 578: case 579: case 580: case 581: case 582: case 583: case 584: case 585: case 586: case 587: case 588: case 589: case 590: case 591: case 592: case 593: case 594: case 595: case 596: case 597: case 598: case 599: case 600: case 601: case 602: case 603: case 604: case 605: case 606: case 607: case 608: case 609: case 610: case 611: case 612: case 613: case 614: case 615: case 616: case 617: case 618: case 619: case 620: case 621: case 622: case 623: case 624: case 625: case 626: case 627: case 628: case 629: case 630: case 631: case 632: case 633: case 634: case 635: case 636: case 637: case 638: case 639: case 640: case 641: case 642: case 643: case 644: case 645: case 646: case 647: case 648: case 649: case 650: case 651: case 652: case 653: case 654: case 655: case 656: case 657: case 658: case 659: case 660: case 661: case 662: case 663: case 664: case 665: case 666: case 667: case 668: case 669: case 670: case 671: case 672: case 673: case 674: case 675: case 676: case 677: case 678: case 679: case 680: case 681: case 682: case 683: case 684: case 685: case 686: case 687: case 688: case 689: case 690: case 691: case 692: case 693: case 694: case 695: case 696: case 697: case 698: case 699: case 700: case 701: case 702: case 703: case 704: case 705: case 706: case 707: case 708: case 709: case 710: case 711: case 712: case 713: case 714: case 715: case 716: case 717: case 718: case 719: case 720: case 721: case 722: case 723: case 724: case 725: case 726: case 727: case 728: case 729: case 730: case 731: case 732: case 733: case 734: case 735: case 736: case 737: case 738: case 739: case 740: case 741: case 742: case 743: case 744: case 745: case 746: case 747: case 748: case 749: case 750: case 751: case 752: case 753: case 754: case 755: case 756: case 757: case 758: case 759: case 760: case 761: case 762: case 763: case 764: case 765: case 766: case 767: case 768: case 769: case 770: case 771: case 772: case 773: case 774: case 775: case 776: case 777: case 778: case 779: case 780: case 781: case 782: case 783: case 784: case 785: case 786: case 787: case 788: case 789: case 790: case 791: case 792: case 793: case 794: case 795: case 796: case 797: case 798: case 799: case 800: case 801: case 802: case 803: case 804: case 805: case 806: case 807: case 808: case 809: case 810: case 811: case 812: case 813: case 814: case 815: case 816: case 817: case 818: case 819: case 820: case 821: case 822: case 823: case 824: case 825: case 826: case 827: case 828: case 829: case 830: case 831: case 832: case 833: case 834: case 835: case 836: case 837: case 838: case 839: case 840: case 841: case 842: case 843: case 844: case 845: case 846: case 847: case 848: case 849: case 850: case 851: case 852: case 853: case 854: case 855: case 856: case 857: case 858: case 859: case 860: case 861: case 862: case 863: case 864: case 865: case 866: case 867: case 868: case 869: case 870: case 871: case 872: case 873: case 874: case 875: case 876: case 877: case 878: case 879: case 880: case 881: case 882: case 883: case 884: case 885: case 886: case 887: case 888: case 889: case 890: case 891: case 892: case 893: case 894: case 895: case 896: case 897: case 898: case 899: case 900: case 901: case 902: case 903: case 904: case 905: case 906: case 907: case 908: case 909: case 910: case 911: case 912: case 913: case 914: case 915: case 916: case 917: case 918: case 919: case 920: case 921: case 922: case 923: case 924: case 925: case 926: case 927: case 928: case 929: case 930: case 931: case 932: case 933: case 934: case 935: case 936: case 937: case 938: case 939: case 940: case 941: case 942: case 943: case 944: case 945: case 946: case 947: case 948: case 949: case 950: case 951: case 952: case 953: case 954: case 955: case 956: case 957: case 958: case 959: case 960: case 961: case 962: case 963: case 964: case 965: case 966: case 967: case 968: case 969: case 970: case 971: case 972: case 973: case 974: case 975: case 976: case 977: case 978: case 979: case 980: case 981: case 982: case 983: case 984: case 985: case 986: case 987: case 988: case 989: case 990: case 991: case 992: case 993: case 994: case 995: case 996: case 997: case 998: case 999: case 1000: case 1001: case 1002: case 1003: case 1004: case 1005: case 1006: case 1007: case 1008: case 1009: case 1010: case 1011: case 1012: case 1013: case 1014: case 1015: case 1016: case 1017: case 1018: case 1019: case 1020: case 1021: case 1022: case 1023: case 1024: case 1025: case 1026: case 1027: case 1028: case 1029: case 1030: case 1031: case 1032: case 1033: case 1034: case 1035: case 1036: case 1037: case 1038: case 1039: case 1040: case 1041: case 1042: case 1043: case 1044: case 1045: case 1046: case 1047: case 1048: return BlockType::NoteBlock; case 6346: case 6347: case 6348: case 6349: case 6350: case 6351: case 6352: case 6353: case 6354: case 6355: case 6356: case 6357: case 6358: case 6359: case 6360: case 6361: case 6362: case 6363: case 6364: case 6365: case 6366: case 6367: case 6368: case 6369: return BlockType::OakButton; case 3573: case 3574: case 3575: case 3576: case 3577: case 3578: case 3579: case 3580: case 3581: case 3582: case 3583: case 3584: case 3585: case 3586: case 3587: case 3588: case 3589: case 3590: case 3591: case 3592: case 3593: case 3594: case 3595: case 3596: case 3597: case 3598: case 3599: case 3600: case 3601: case 3602: case 3603: case 3604: case 3605: case 3606: case 3607: case 3608: case 3609: case 3610: case 3611: case 3612: case 3613: case 3614: case 3615: case 3616: case 3617: case 3618: case 3619: case 3620: case 3621: case 3622: case 3623: case 3624: case 3625: case 3626: case 3627: case 3628: case 3629: case 3630: case 3631: case 3632: case 3633: case 3634: case 3635: case 3636: return BlockType::OakDoor; case 3968: case 3969: case 3972: case 3973: case 3976: case 3977: case 3980: case 3981: case 3984: case 3985: case 3988: case 3989: case 3992: case 3993: case 3996: case 3997: return BlockType::OakFence; case 4820: case 4821: case 4822: case 4823: case 4824: case 4825: case 4826: case 4827: case 4828: case 4829: case 4830: case 4831: case 4832: case 4833: case 4834: case 4835: case 4836: case 4837: case 4838: case 4839: case 4840: case 4841: case 4842: case 4843: case 4844: case 4845: case 4846: case 4847: case 4848: case 4849: case 4850: case 4851: return BlockType::OakFenceGate; case 145: case 146: case 147: case 148: case 149: case 150: case 151: case 152: case 153: case 154: case 155: case 156: case 157: case 158: return BlockType::OakLeaves; case 73: case 74: case 75: return BlockType::OakLog; case 15: return BlockType::OakPlanks; case 3873: case 3874: return BlockType::OakPressurePlate; case 21: case 22: return BlockType::OakSapling; case 3382: case 3384: case 3386: case 3388: case 3390: case 3392: case 3394: case 3396: case 3398: case 3400: case 3402: case 3404: case 3406: case 3408: case 3410: case 3412: return BlockType::OakSign; case 8301: case 8303: case 8305: return BlockType::OakSlab; case 1955: case 1957: case 1959: case 1961: case 1963: case 1965: case 1967: case 1969: case 1971: case 1973: case 1975: case 1977: case 1979: case 1981: case 1983: case 1985: case 1987: case 1989: case 1991: case 1993: case 1995: case 1997: case 1999: case 2001: case 2003: case 2005: case 2007: case 2009: case 2011: case 2013: case 2015: case 2017: case 2019: case 2021: case 2023: case 2025: case 2027: case 2029: case 2031: case 2033: return BlockType::OakStairs; case 4112: case 4114: case 4116: case 4118: case 4120: case 4122: case 4124: case 4126: case 4128: case 4130: case 4132: case 4134: case 4136: case 4138: case 4140: case 4142: case 4144: case 4146: case 4148: case 4150: case 4152: case 4154: case 4156: case 4158: case 4160: case 4162: case 4164: case 4166: case 4168: case 4170: case 4172: case 4174: return BlockType::OakTrapdoor; case 3736: case 3738: case 3740: case 3742: return BlockType::OakWallSign; case 109: case 110: case 111: return BlockType::OakWood; case 9260: case 9261: case 9262: case 9263: case 9264: case 9265: case 9266: case 9267: case 9268: case 9269: case 9270: case 9271: return BlockType::Observer; case 1434: return BlockType::Obsidian; case 7913: case 7914: case 7915: case 7916: case 7917: case 7918: case 7919: case 7920: case 7921: case 7922: case 7923: case 7924: case 7925: case 7926: case 7927: case 7928: return BlockType::OrangeBanner; case 1065: case 1066: case 1067: case 1068: case 1069: case 1070: case 1071: case 1072: case 1073: case 1074: case 1075: case 1076: case 1077: case 1078: case 1079: case 1080: return BlockType::OrangeBed; case 7867: return BlockType::OrangeCarpet; case 9439: return BlockType::OrangeConcrete; case 9455: return BlockType::OrangeConcretePowder; case 9378: case 9379: case 9380: case 9381: return BlockType::OrangeGlazedTerracotta; case 9284: case 9285: case 9286: case 9287: case 9288: case 9289: return BlockType::OrangeShulkerBox; case 4096: return BlockType::OrangeStainedGlass; case 6897: case 6898: case 6901: case 6902: case 6905: case 6906: case 6909: case 6910: case 6913: case 6914: case 6917: case 6918: case 6921: case 6922: case 6925: case 6926: return BlockType::OrangeStainedGlassPane; case 6848: return BlockType::OrangeTerracotta; case 1418: return BlockType::OrangeTulip; case 8157: case 8158: case 8159: case 8160: return BlockType::OrangeWallBanner; case 1385: return BlockType::OrangeWool; case 1421: return BlockType::OxeyeDaisy; case 7884: return BlockType::PackedIce; case 7891: case 7892: return BlockType::Peony; case 8361: case 8363: case 8365: return BlockType::PetrifiedOakSlab; case 7993: case 7994: case 7995: case 7996: case 7997: case 7998: case 7999: case 8000: case 8001: case 8002: case 8003: case 8004: case 8005: case 8006: case 8007: case 8008: return BlockType::PinkBanner; case 1145: case 1146: case 1147: case 1148: case 1149: case 1150: case 1151: case 1152: case 1153: case 1154: case 1155: case 1156: case 1157: case 1158: case 1159: case 1160: return BlockType::PinkBed; case 7872: return BlockType::PinkCarpet; case 9444: return BlockType::PinkConcrete; case 9460: return BlockType::PinkConcretePowder; case 9398: case 9399: case 9400: case 9401: return BlockType::PinkGlazedTerracotta; case 9314: case 9315: case 9316: case 9317: case 9318: case 9319: return BlockType::PinkShulkerBox; case 4101: return BlockType::PinkStainedGlass; case 7057: case 7058: case 7061: case 7062: case 7065: case 7066: case 7069: case 7070: case 7073: case 7074: case 7077: case 7078: case 7081: case 7082: case 7085: case 7086: return BlockType::PinkStainedGlassPane; case 6853: return BlockType::PinkTerracotta; case 1420: return BlockType::PinkTulip; case 8177: case 8178: case 8179: case 8180: return BlockType::PinkWallBanner; case 1390: return BlockType::PinkWool; case 1348: case 1349: case 1350: case 1351: case 1352: case 1353: case 1354: case 1355: case 1356: case 1357: case 1358: case 1359: return BlockType::Piston; case 1360: case 1361: case 1362: case 1363: case 1364: case 1365: case 1366: case 1367: case 1368: case 1369: case 1370: case 1371: case 1372: case 1373: case 1374: case 1375: case 1376: case 1377: case 1378: case 1379: case 1380: case 1381: case 1382: case 1383: return BlockType::PistonHead; case 6550: case 6551: case 6552: case 6553: case 6554: case 6555: case 6556: case 6557: case 6558: case 6559: case 6560: case 6561: case 6562: case 6563: case 6564: case 6565: return BlockType::PlayerHead; case 6566: case 6567: case 6568: case 6569: return BlockType::PlayerWallHead; case 12: case 13: return BlockType::Podzol; case 7: return BlockType::PolishedAndesite; case 10856: case 10858: case 10860: return BlockType::PolishedAndesiteSlab; case 10630: case 10632: case 10634: case 10636: case 10638: case 10640: case 10642: case 10644: case 10646: case 10648: case 10650: case 10652: case 10654: case 10656: case 10658: case 10660: case 10662: case 10664: case 10666: case 10668: case 10670: case 10672: case 10674: case 10676: case 10678: case 10680: case 10682: case 10684: case 10686: case 10688: case 10690: case 10692: case 10694: case 10696: case 10698: case 10700: case 10702: case 10704: case 10706: case 10708: return BlockType::PolishedAndesiteStairs; case 4005: case 4006: case 4007: return BlockType::PolishedBasalt; case 16250: return BlockType::PolishedBlackstone; case 16255: case 16257: case 16259: return BlockType::PolishedBlackstoneBrickSlab; case 16261: case 16263: case 16265: case 16267: case 16269: case 16271: case 16273: case 16275: case 16277: case 16279: case 16281: case 16283: case 16285: case 16287: case 16289: case 16291: case 16293: case 16295: case 16297: case 16299: case 16301: case 16303: case 16305: case 16307: case 16309: case 16311: case 16313: case 16315: case 16317: case 16319: case 16321: case 16323: case 16325: case 16327: case 16329: case 16331: case 16333: case 16335: case 16337: case 16339: return BlockType::PolishedBlackstoneBrickStairs; case 16343: case 16344: case 16345: case 16349: case 16350: case 16351: case 16355: case 16356: case 16357: case 16361: case 16362: case 16363: case 16367: case 16368: case 16369: case 16373: case 16374: case 16375: case 16379: case 16380: case 16381: case 16385: case 16386: case 16387: case 16391: case 16392: case 16393: case 16397: case 16398: case 16399: case 16403: case 16404: case 16405: case 16409: case 16410: case 16411: case 16415: case 16416: case 16417: case 16421: case 16422: case 16423: case 16427: case 16428: case 16429: case 16433: case 16434: case 16435: case 16439: case 16440: case 16441: case 16445: case 16446: case 16447: case 16451: case 16452: case 16453: case 16457: case 16458: case 16459: case 16463: case 16464: case 16465: case 16469: case 16470: case 16471: case 16475: case 16476: case 16477: case 16481: case 16482: case 16483: case 16487: case 16488: case 16489: case 16493: case 16494: case 16495: case 16499: case 16500: case 16501: case 16505: case 16506: case 16507: case 16511: case 16512: case 16513: case 16517: case 16518: case 16519: case 16523: case 16524: case 16525: case 16529: case 16530: case 16531: case 16535: case 16536: case 16537: case 16541: case 16542: case 16543: case 16547: case 16548: case 16549: case 16553: case 16554: case 16555: case 16559: case 16560: case 16561: case 16565: case 16566: case 16567: case 16571: case 16572: case 16573: case 16577: case 16578: case 16579: case 16583: case 16584: case 16585: case 16589: case 16590: case 16591: case 16595: case 16596: case 16597: case 16601: case 16602: case 16603: case 16607: case 16608: case 16609: case 16613: case 16614: case 16615: case 16619: case 16620: case 16621: case 16625: case 16626: case 16627: case 16631: case 16632: case 16633: case 16637: case 16638: case 16639: case 16643: case 16644: case 16645: case 16649: case 16650: case 16651: case 16655: case 16656: case 16657: case 16661: case 16662: case 16663: return BlockType::PolishedBlackstoneBrickWall; case 16251: return BlockType::PolishedBlackstoneBricks; case 16753: case 16754: case 16755: case 16756: case 16757: case 16758: case 16759: case 16760: case 16761: case 16762: case 16763: case 16764: case 16765: case 16766: case 16767: case 16768: case 16769: case 16770: case 16771: case 16772: case 16773: case 16774: case 16775: case 16776: return BlockType::PolishedBlackstoneButton; case 16751: case 16752: return BlockType::PolishedBlackstonePressurePlate; case 16746: case 16748: case 16750: return BlockType::PolishedBlackstoneSlab; case 16666: case 16668: case 16670: case 16672: case 16674: case 16676: case 16678: case 16680: case 16682: case 16684: case 16686: case 16688: case 16690: case 16692: case 16694: case 16696: case 16698: case 16700: case 16702: case 16704: case 16706: case 16708: case 16710: case 16712: case 16714: case 16716: case 16718: case 16720: case 16722: case 16724: case 16726: case 16728: case 16730: case 16732: case 16734: case 16736: case 16738: case 16740: case 16742: case 16744: return BlockType::PolishedBlackstoneStairs; case 16780: case 16781: case 16782: case 16786: case 16787: case 16788: case 16792: case 16793: case 16794: case 16798: case 16799: case 16800: case 16804: case 16805: case 16806: case 16810: case 16811: case 16812: case 16816: case 16817: case 16818: case 16822: case 16823: case 16824: case 16828: case 16829: case 16830: case 16834: case 16835: case 16836: case 16840: case 16841: case 16842: case 16846: case 16847: case 16848: case 16852: case 16853: case 16854: case 16858: case 16859: case 16860: case 16864: case 16865: case 16866: case 16870: case 16871: case 16872: case 16876: case 16877: case 16878: case 16882: case 16883: case 16884: case 16888: case 16889: case 16890: case 16894: case 16895: case 16896: case 16900: case 16901: case 16902: case 16906: case 16907: case 16908: case 16912: case 16913: case 16914: case 16918: case 16919: case 16920: case 16924: case 16925: case 16926: case 16930: case 16931: case 16932: case 16936: case 16937: case 16938: case 16942: case 16943: case 16944: case 16948: case 16949: case 16950: case 16954: case 16955: case 16956: case 16960: case 16961: case 16962: case 16966: case 16967: case 16968: case 16972: case 16973: case 16974: case 16978: case 16979: case 16980: case 16984: case 16985: case 16986: case 16990: case 16991: case 16992: case 16996: case 16997: case 16998: case 17002: case 17003: case 17004: case 17008: case 17009: case 17010: case 17014: case 17015: case 17016: case 17020: case 17021: case 17022: case 17026: case 17027: case 17028: case 17032: case 17033: case 17034: case 17038: case 17039: case 17040: case 17044: case 17045: case 17046: case 17050: case 17051: case 17052: case 17056: case 17057: case 17058: case 17062: case 17063: case 17064: case 17068: case 17069: case 17070: case 17074: case 17075: case 17076: case 17080: case 17081: case 17082: case 17086: case 17087: case 17088: case 17092: case 17093: case 17094: case 17098: case 17099: case 17100: return BlockType::PolishedBlackstoneWall; case 5: return BlockType::PolishedDiorite; case 10808: case 10810: case 10812: return BlockType::PolishedDioriteSlab; case 9910: case 9912: case 9914: case 9916: case 9918: case 9920: case 9922: case 9924: case 9926: case 9928: case 9930: case 9932: case 9934: case 9936: case 9938: case 9940: case 9942: case 9944: case 9946: case 9948: case 9950: case 9952: case 9954: case 9956: case 9958: case 9960: case 9962: case 9964: case 9966: case 9968: case 9970: case 9972: case 9974: case 9976: case 9978: case 9980: case 9982: case 9984: case 9986: case 9988: return BlockType::PolishedDioriteStairs; case 3: return BlockType::PolishedGranite; case 10790: case 10792: case 10794: return BlockType::PolishedGraniteSlab; case 9670: case 9672: case 9674: case 9676: case 9678: case 9680: case 9682: case 9684: case 9686: case 9688: case 9690: case 9692: case 9694: case 9696: case 9698: case 9700: case 9702: case 9704: case 9706: case 9708: case 9710: case 9712: case 9714: case 9716: case 9718: case 9720: case 9722: case 9724: case 9726: case 9728: case 9730: case 9732: case 9734: case 9736: case 9738: case 9740: case 9742: case 9744: case 9746: case 9748: return BlockType::PolishedGraniteStairs; case 1413: return BlockType::Poppy; case 6338: case 6339: case 6340: case 6341: case 6342: case 6343: case 6344: case 6345: return BlockType::Potatoes; case 6310: return BlockType::PottedAcaciaSapling; case 6316: return BlockType::PottedAllium; case 6317: return BlockType::PottedAzureBluet; case 9664: return BlockType::PottedBamboo; case 6308: return BlockType::PottedBirchSapling; case 6315: return BlockType::PottedBlueOrchid; case 6327: return BlockType::PottedBrownMushroom; case 6329: return BlockType::PottedCactus; case 6323: return BlockType::PottedCornflower; case 15834: return BlockType::PottedCrimsonFungus; case 15836: return BlockType::PottedCrimsonRoots; case 6313: return BlockType::PottedDandelion; case 6311: return BlockType::PottedDarkOakSapling; case 6328: return BlockType::PottedDeadBush; case 6312: return BlockType::PottedFern; case 6309: return BlockType::PottedJungleSapling; case 6324: return BlockType::PottedLilyOfTheValley; case 6306: return BlockType::PottedOakSapling; case 6319: return BlockType::PottedOrangeTulip; case 6322: return BlockType::PottedOxeyeDaisy; case 6321: return BlockType::PottedPinkTulip; case 6314: return BlockType::PottedPoppy; case 6326: return BlockType::PottedRedMushroom; case 6318: return BlockType::PottedRedTulip; case 6307: return BlockType::PottedSpruceSapling; case 15835: return BlockType::PottedWarpedFungus; case 15837: return BlockType::PottedWarpedRoots; case 6320: return BlockType::PottedWhiteTulip; case 6325: return BlockType::PottedWitherRose; case 1305: case 1306: case 1307: case 1308: case 1309: case 1310: case 1311: case 1312: case 1313: case 1314: case 1315: case 1316: return BlockType::PoweredRail; case 7601: return BlockType::Prismarine; case 7851: case 7853: case 7855: return BlockType::PrismarineBrickSlab; case 7685: case 7687: case 7689: case 7691: case 7693: case 7695: case 7697: case 7699: case 7701: case 7703: case 7705: case 7707: case 7709: case 7711: case 7713: case 7715: case 7717: case 7719: case 7721: case 7723: case 7725: case 7727: case 7729: case 7731: case 7733: case 7735: case 7737: case 7739: case 7741: case 7743: case 7745: case 7747: case 7749: case 7751: case 7753: case 7755: case 7757: case 7759: case 7761: case 7763: return BlockType::PrismarineBrickStairs; case 7602: return BlockType::PrismarineBricks; case 7845: case 7847: case 7849: return BlockType::PrismarineSlab; case 7605: case 7607: case 7609: case 7611: case 7613: case 7615: case 7617: case 7619: case 7621: case 7623: case 7625: case 7627: case 7629: case 7631: case 7633: case 7635: case 7637: case 7639: case 7641: case 7643: case 7645: case 7647: case 7649: case 7651: case 7653: case 7655: case 7657: case 7659: case 7661: case 7663: case 7665: case 7667: case 7669: case 7671: case 7673: case 7675: case 7677: case 7679: case 7681: case 7683: return BlockType::PrismarineStairs; case 11194: case 11195: case 11196: case 11200: case 11201: case 11202: case 11206: case 11207: case 11208: case 11212: case 11213: case 11214: case 11218: case 11219: case 11220: case 11224: case 11225: case 11226: case 11230: case 11231: case 11232: case 11236: case 11237: case 11238: case 11242: case 11243: case 11244: case 11248: case 11249: case 11250: case 11254: case 11255: case 11256: case 11260: case 11261: case 11262: case 11266: case 11267: case 11268: case 11272: case 11273: case 11274: case 11278: case 11279: case 11280: case 11284: case 11285: case 11286: case 11290: case 11291: case 11292: case 11296: case 11297: case 11298: case 11302: case 11303: case 11304: case 11308: case 11309: case 11310: case 11314: case 11315: case 11316: case 11320: case 11321: case 11322: case 11326: case 11327: case 11328: case 11332: case 11333: case 11334: case 11338: case 11339: case 11340: case 11344: case 11345: case 11346: case 11350: case 11351: case 11352: case 11356: case 11357: case 11358: case 11362: case 11363: case 11364: case 11368: case 11369: case 11370: case 11374: case 11375: case 11376: case 11380: case 11381: case 11382: case 11386: case 11387: case 11388: case 11392: case 11393: case 11394: case 11398: case 11399: case 11400: case 11404: case 11405: case 11406: case 11410: case 11411: case 11412: case 11416: case 11417: case 11418: case 11422: case 11423: case 11424: case 11428: case 11429: case 11430: case 11434: case 11435: case 11436: case 11440: case 11441: case 11442: case 11446: case 11447: case 11448: case 11452: case 11453: case 11454: case 11458: case 11459: case 11460: case 11464: case 11465: case 11466: case 11470: case 11471: case 11472: case 11476: case 11477: case 11478: case 11482: case 11483: case 11484: case 11488: case 11489: case 11490: case 11494: case 11495: case 11496: case 11500: case 11501: case 11502: case 11506: case 11507: case 11508: case 11512: case 11513: case 11514: return BlockType::PrismarineWall; case 3998: return BlockType::Pumpkin; case 4772: case 4773: case 4774: case 4775: case 4776: case 4777: case 4778: case 4779: return BlockType::PumpkinStem; case 8057: case 8058: case 8059: case 8060: case 8061: case 8062: case 8063: case 8064: case 8065: case 8066: case 8067: case 8068: case 8069: case 8070: case 8071: case 8072: return BlockType::PurpleBanner; case 1209: case 1210: case 1211: case 1212: case 1213: case 1214: case 1215: case 1216: case 1217: case 1218: case 1219: case 1220: case 1221: case 1222: case 1223: case 1224: return BlockType::PurpleBed; case 7876: return BlockType::PurpleCarpet; case 9448: return BlockType::PurpleConcrete; case 9464: return BlockType::PurpleConcretePowder; case 9414: case 9415: case 9416: case 9417: return BlockType::PurpleGlazedTerracotta; case 9338: case 9339: case 9340: case 9341: case 9342: case 9343: return BlockType::PurpleShulkerBox; case 4105: return BlockType::PurpleStainedGlass; case 7185: case 7186: case 7189: case 7190: case 7193: case 7194: case 7197: case 7198: case 7201: case 7202: case 7205: case 7206: case 7209: case 7210: case 7213: case 7214: return BlockType::PurpleStainedGlassPane; case 6857: return BlockType::PurpleTerracotta; case 8193: case 8194: case 8195: case 8196: return BlockType::PurpleWallBanner; case 1394: return BlockType::PurpleWool; case 9134: return BlockType::PurpurBlock; case 9135: case 9136: case 9137: return BlockType::PurpurPillar; case 8409: case 8411: case 8413: return BlockType::PurpurSlab; case 9139: case 9141: case 9143: case 9145: case 9147: case 9149: case 9151: case 9153: case 9155: case 9157: case 9159: case 9161: case 9163: case 9165: case 9167: case 9169: case 9171: case 9173: case 9175: case 9177: case 9179: case 9181: case 9183: case 9185: case 9187: case 9189: case 9191: case 9193: case 9195: case 9197: case 9199: case 9201: case 9203: case 9205: case 9207: case 9209: case 9211: case 9213: case 9215: case 9217: return BlockType::PurpurStairs; case 6738: return BlockType::QuartzBlock; case 17103: return BlockType::QuartzBricks; case 6740: case 6741: case 6742: return BlockType::QuartzPillar; case 8391: case 8393: case 8395: return BlockType::QuartzSlab; case 6744: case 6746: case 6748: case 6750: case 6752: case 6754: case 6756: case 6758: case 6760: case 6762: case 6764: case 6766: case 6768: case 6770: case 6772: case 6774: case 6776: case 6778: case 6780: case 6782: case 6784: case 6786: case 6788: case 6790: case 6792: case 6794: case 6796: case 6798: case 6800: case 6802: case 6804: case 6806: case 6808: case 6810: case 6812: case 6814: case 6816: case 6818: case 6820: case 6822: return BlockType::QuartzStairs; case 3645: case 3646: case 3647: case 3648: case 3649: case 3650: case 3651: case 3652: case 3653: case 3654: return BlockType::Rail; case 8121: case 8122: case 8123: case 8124: case 8125: case 8126: case 8127: case 8128: case 8129: case 8130: case 8131: case 8132: case 8133: case 8134: case 8135: case 8136: return BlockType::RedBanner; case 1273: case 1274: case 1275: case 1276: case 1277: case 1278: case 1279: case 1280: case 1281: case 1282: case 1283: case 1284: case 1285: case 1286: case 1287: case 1288: return BlockType::RedBed; case 7880: return BlockType::RedCarpet; case 9452: return BlockType::RedConcrete; case 9468: return BlockType::RedConcretePowder; case 9430: case 9431: case 9432: case 9433: return BlockType::RedGlazedTerracotta; case 1426: return BlockType::RedMushroom; case 4569: case 4570: case 4571: case 4572: case 4573: case 4574: case 4575: case 4576: case 4577: case 4578: case 4579: case 4580: case 4581: case 4582: case 4583: case 4584: case 4585: case 4586: case 4587: case 4588: case 4589: case 4590: case 4591: case 4592: case 4593: case 4594: case 4595: case 4596: case 4597: case 4598: case 4599: case 4600: case 4601: case 4602: case 4603: case 4604: case 4605: case 4606: case 4607: case 4608: case 4609: case 4610: case 4611: case 4612: case 4613: case 4614: case 4615: case 4616: case 4617: case 4618: case 4619: case 4620: case 4621: case 4622: case 4623: case 4624: case 4625: case 4626: case 4627: case 4628: case 4629: case 4630: case 4631: case 4632: return BlockType::RedMushroomBlock; case 10850: case 10852: case 10854: return BlockType::RedNetherBrickSlab; case 10550: case 10552: case 10554: case 10556: case 10558: case 10560: case 10562: case 10564: case 10566: case 10568: case 10570: case 10572: case 10574: case 10576: case 10578: case 10580: case 10582: case 10584: case 10586: case 10588: case 10590: case 10592: case 10594: case 10596: case 10598: case 10600: case 10602: case 10604: case 10606: case 10608: case 10610: case 10612: case 10614: case 10616: case 10618: case 10620: case 10622: case 10624: case 10626: case 10628: return BlockType::RedNetherBrickStairs; case 13462: case 13463: case 13464: case 13468: case 13469: case 13470: case 13474: case 13475: case 13476: case 13480: case 13481: case 13482: case 13486: case 13487: case 13488: case 13492: case 13493: case 13494: case 13498: case 13499: case 13500: case 13504: case 13505: case 13506: case 13510: case 13511: case 13512: case 13516: case 13517: case 13518: case 13522: case 13523: case 13524: case 13528: case 13529: case 13530: case 13534: case 13535: case 13536: case 13540: case 13541: case 13542: case 13546: case 13547: case 13548: case 13552: case 13553: case 13554: case 13558: case 13559: case 13560: case 13564: case 13565: case 13566: case 13570: case 13571: case 13572: case 13576: case 13577: case 13578: case 13582: case 13583: case 13584: case 13588: case 13589: case 13590: case 13594: case 13595: case 13596: case 13600: case 13601: case 13602: case 13606: case 13607: case 13608: case 13612: case 13613: case 13614: case 13618: case 13619: case 13620: case 13624: case 13625: case 13626: case 13630: case 13631: case 13632: case 13636: case 13637: case 13638: case 13642: case 13643: case 13644: case 13648: case 13649: case 13650: case 13654: case 13655: case 13656: case 13660: case 13661: case 13662: case 13666: case 13667: case 13668: case 13672: case 13673: case 13674: case 13678: case 13679: case 13680: case 13684: case 13685: case 13686: case 13690: case 13691: case 13692: case 13696: case 13697: case 13698: case 13702: case 13703: case 13704: case 13708: case 13709: case 13710: case 13714: case 13715: case 13716: case 13720: case 13721: case 13722: case 13726: case 13727: case 13728: case 13732: case 13733: case 13734: case 13738: case 13739: case 13740: case 13744: case 13745: case 13746: case 13750: case 13751: case 13752: case 13756: case 13757: case 13758: case 13762: case 13763: case 13764: case 13768: case 13769: case 13770: case 13774: case 13775: case 13776: case 13780: case 13781: case 13782: return BlockType::RedNetherBrickWall; case 9255: return BlockType::RedNetherBricks; case 67: return BlockType::RedSand; case 8217: return BlockType::RedSandstone; case 8397: case 8399: case 8401: return BlockType::RedSandstoneSlab; case 8221: case 8223: case 8225: case 8227: case 8229: case 8231: case 8233: case 8235: case 8237: case 8239: case 8241: case 8243: case 8245: case 8247: case 8249: case 8251: case 8253: case 8255: case 8257: case 8259: case 8261: case 8263: case 8265: case 8267: case 8269: case 8271: case 8273: case 8275: case 8277: case 8279: case 8281: case 8283: case 8285: case 8287: case 8289: case 8291: case 8293: case 8295: case 8297: case 8299: return BlockType::RedSandstoneStairs; case 11518: case 11519: case 11520: case 11524: case 11525: case 11526: case 11530: case 11531: case 11532: case 11536: case 11537: case 11538: case 11542: case 11543: case 11544: case 11548: case 11549: case 11550: case 11554: case 11555: case 11556: case 11560: case 11561: case 11562: case 11566: case 11567: case 11568: case 11572: case 11573: case 11574: case 11578: case 11579: case 11580: case 11584: case 11585: case 11586: case 11590: case 11591: case 11592: case 11596: case 11597: case 11598: case 11602: case 11603: case 11604: case 11608: case 11609: case 11610: case 11614: case 11615: case 11616: case 11620: case 11621: case 11622: case 11626: case 11627: case 11628: case 11632: case 11633: case 11634: case 11638: case 11639: case 11640: case 11644: case 11645: case 11646: case 11650: case 11651: case 11652: case 11656: case 11657: case 11658: case 11662: case 11663: case 11664: case 11668: case 11669: case 11670: case 11674: case 11675: case 11676: case 11680: case 11681: case 11682: case 11686: case 11687: case 11688: case 11692: case 11693: case 11694: case 11698: case 11699: case 11700: case 11704: case 11705: case 11706: case 11710: case 11711: case 11712: case 11716: case 11717: case 11718: case 11722: case 11723: case 11724: case 11728: case 11729: case 11730: case 11734: case 11735: case 11736: case 11740: case 11741: case 11742: case 11746: case 11747: case 11748: case 11752: case 11753: case 11754: case 11758: case 11759: case 11760: case 11764: case 11765: case 11766: case 11770: case 11771: case 11772: case 11776: case 11777: case 11778: case 11782: case 11783: case 11784: case 11788: case 11789: case 11790: case 11794: case 11795: case 11796: case 11800: case 11801: case 11802: case 11806: case 11807: case 11808: case 11812: case 11813: case 11814: case 11818: case 11819: case 11820: case 11824: case 11825: case 11826: case 11830: case 11831: case 11832: case 11836: case 11837: case 11838: return BlockType::RedSandstoneWall; case 9362: case 9363: case 9364: case 9365: case 9366: case 9367: return BlockType::RedShulkerBox; case 4109: return BlockType::RedStainedGlass; case 7313: case 7314: case 7317: case 7318: case 7321: case 7322: case 7325: case 7326: case 7329: case 7330: case 7333: case 7334: case 7337: case 7338: case 7341: case 7342: return BlockType::RedStainedGlassPane; case 6861: return BlockType::RedTerracotta; case 1417: return BlockType::RedTulip; case 8209: case 8210: case 8211: case 8212: return BlockType::RedWallBanner; case 1398: return BlockType::RedWool; case 6726: return BlockType::RedstoneBlock; case 5156: case 5157: return BlockType::RedstoneLamp; case 3885: case 3886: return BlockType::RedstoneOre; case 3887: case 3888: return BlockType::RedstoneTorch; case 3889: case 3890: case 3891: case 3892: case 3893: case 3894: case 3895: case 3896: return BlockType::RedstoneWallTorch; case 2058: case 2059: case 2060: case 2061: case 2062: case 2063: case 2064: case 2065: case 2066: case 2067: case 2068: case 2069: case 2070: case 2071: case 2072: case 2073: case 2074: case 2075: case 2076: case 2077: case 2078: case 2079: case 2080: case 2081: case 2082: case 2083: case 2084: case 2085: case 2086: case 2087: case 2088: case 2089: case 2090: case 2091: case 2092: case 2093: case 2094: case 2095: case 2096: case 2097: case 2098: case 2099: case 2100: case 2101: case 2102: case 2103: case 2104: case 2105: case 2106: case 2107: case 2108: case 2109: case 2110: case 2111: case 2112: case 2113: case 2114: case 2115: case 2116: case 2117: case 2118: case 2119: case 2120: case 2121: case 2122: case 2123: case 2124: case 2125: case 2126: case 2127: case 2128: case 2129: case 2130: case 2131: case 2132: case 2133: case 2134: case 2135: case 2136: case 2137: case 2138: case 2139: case 2140: case 2141: case 2142: case 2143: case 2144: case 2145: case 2146: case 2147: case 2148: case 2149: case 2150: case 2151: case 2152: case 2153: case 2154: case 2155: case 2156: case 2157: case 2158: case 2159: case 2160: case 2161: case 2162: case 2163: case 2164: case 2165: case 2166: case 2167: case 2168: case 2169: case 2170: case 2171: case 2172: case 2173: case 2174: case 2175: case 2176: case 2177: case 2178: case 2179: case 2180: case 2181: case 2182: case 2183: case 2184: case 2185: case 2186: case 2187: case 2188: case 2189: case 2190: case 2191: case 2192: case 2193: case 2194: case 2195: case 2196: case 2197: case 2198: case 2199: case 2200: case 2201: case 2202: case 2203: case 2204: case 2205: case 2206: case 2207: case 2208: case 2209: case 2210: case 2211: case 2212: case 2213: case 2214: case 2215: case 2216: case 2217: case 2218: case 2219: case 2220: case 2221: case 2222: case 2223: case 2224: case 2225: case 2226: case 2227: case 2228: case 2229: case 2230: case 2231: case 2232: case 2233: case 2234: case 2235: case 2236: case 2237: case 2238: case 2239: case 2240: case 2241: case 2242: case 2243: case 2244: case 2245: case 2246: case 2247: case 2248: case 2249: case 2250: case 2251: case 2252: case 2253: case 2254: case 2255: case 2256: case 2257: case 2258: case 2259: case 2260: case 2261: case 2262: case 2263: case 2264: case 2265: case 2266: case 2267: case 2268: case 2269: case 2270: case 2271: case 2272: case 2273: case 2274: case 2275: case 2276: case 2277: case 2278: case 2279: case 2280: case 2281: case 2282: case 2283: case 2284: case 2285: case 2286: case 2287: case 2288: case 2289: case 2290: case 2291: case 2292: case 2293: case 2294: case 2295: case 2296: case 2297: case 2298: case 2299: case 2300: case 2301: case 2302: case 2303: case 2304: case 2305: case 2306: case 2307: case 2308: case 2309: case 2310: case 2311: case 2312: case 2313: case 2314: case 2315: case 2316: case 2317: case 2318: case 2319: case 2320: case 2321: case 2322: case 2323: case 2324: case 2325: case 2326: case 2327: case 2328: case 2329: case 2330: case 2331: case 2332: case 2333: case 2334: case 2335: case 2336: case 2337: case 2338: case 2339: case 2340: case 2341: case 2342: case 2343: case 2344: case 2345: case 2346: case 2347: case 2348: case 2349: case 2350: case 2351: case 2352: case 2353: case 2354: case 2355: case 2356: case 2357: case 2358: case 2359: case 2360: case 2361: case 2362: case 2363: case 2364: case 2365: case 2366: case 2367: case 2368: case 2369: case 2370: case 2371: case 2372: case 2373: case 2374: case 2375: case 2376: case 2377: case 2378: case 2379: case 2380: case 2381: case 2382: case 2383: case 2384: case 2385: case 2386: case 2387: case 2388: case 2389: case 2390: case 2391: case 2392: case 2393: case 2394: case 2395: case 2396: case 2397: case 2398: case 2399: case 2400: case 2401: case 2402: case 2403: case 2404: case 2405: case 2406: case 2407: case 2408: case 2409: case 2410: case 2411: case 2412: case 2413: case 2414: case 2415: case 2416: case 2417: case 2418: case 2419: case 2420: case 2421: case 2422: case 2423: case 2424: case 2425: case 2426: case 2427: case 2428: case 2429: case 2430: case 2431: case 2432: case 2433: case 2434: case 2435: case 2436: case 2437: case 2438: case 2439: case 2440: case 2441: case 2442: case 2443: case 2444: case 2445: case 2446: case 2447: case 2448: case 2449: case 2450: case 2451: case 2452: case 2453: case 2454: case 2455: case 2456: case 2457: case 2458: case 2459: case 2460: case 2461: case 2462: case 2463: case 2464: case 2465: case 2466: case 2467: case 2468: case 2469: case 2470: case 2471: case 2472: case 2473: case 2474: case 2475: case 2476: case 2477: case 2478: case 2479: case 2480: case 2481: case 2482: case 2483: case 2484: case 2485: case 2486: case 2487: case 2488: case 2489: case 2490: case 2491: case 2492: case 2493: case 2494: case 2495: case 2496: case 2497: case 2498: case 2499: case 2500: case 2501: case 2502: case 2503: case 2504: case 2505: case 2506: case 2507: case 2508: case 2509: case 2510: case 2511: case 2512: case 2513: case 2514: case 2515: case 2516: case 2517: case 2518: case 2519: case 2520: case 2521: case 2522: case 2523: case 2524: case 2525: case 2526: case 2527: case 2528: case 2529: case 2530: case 2531: case 2532: case 2533: case 2534: case 2535: case 2536: case 2537: case 2538: case 2539: case 2540: case 2541: case 2542: case 2543: case 2544: case 2545: case 2546: case 2547: case 2548: case 2549: case 2550: case 2551: case 2552: case 2553: case 2554: case 2555: case 2556: case 2557: case 2558: case 2559: case 2560: case 2561: case 2562: case 2563: case 2564: case 2565: case 2566: case 2567: case 2568: case 2569: case 2570: case 2571: case 2572: case 2573: case 2574: case 2575: case 2576: case 2577: case 2578: case 2579: case 2580: case 2581: case 2582: case 2583: case 2584: case 2585: case 2586: case 2587: case 2588: case 2589: case 2590: case 2591: case 2592: case 2593: case 2594: case 2595: case 2596: case 2597: case 2598: case 2599: case 2600: case 2601: case 2602: case 2603: case 2604: case 2605: case 2606: case 2607: case 2608: case 2609: case 2610: case 2611: case 2612: case 2613: case 2614: case 2615: case 2616: case 2617: case 2618: case 2619: case 2620: case 2621: case 2622: case 2623: case 2624: case 2625: case 2626: case 2627: case 2628: case 2629: case 2630: case 2631: case 2632: case 2633: case 2634: case 2635: case 2636: case 2637: case 2638: case 2639: case 2640: case 2641: case 2642: case 2643: case 2644: case 2645: case 2646: case 2647: case 2648: case 2649: case 2650: case 2651: case 2652: case 2653: case 2654: case 2655: case 2656: case 2657: case 2658: case 2659: case 2660: case 2661: case 2662: case 2663: case 2664: case 2665: case 2666: case 2667: case 2668: case 2669: case 2670: case 2671: case 2672: case 2673: case 2674: case 2675: case 2676: case 2677: case 2678: case 2679: case 2680: case 2681: case 2682: case 2683: case 2684: case 2685: case 2686: case 2687: case 2688: case 2689: case 2690: case 2691: case 2692: case 2693: case 2694: case 2695: case 2696: case 2697: case 2698: case 2699: case 2700: case 2701: case 2702: case 2703: case 2704: case 2705: case 2706: case 2707: case 2708: case 2709: case 2710: case 2711: case 2712: case 2713: case 2714: case 2715: case 2716: case 2717: case 2718: case 2719: case 2720: case 2721: case 2722: case 2723: case 2724: case 2725: case 2726: case 2727: case 2728: case 2729: case 2730: case 2731: case 2732: case 2733: case 2734: case 2735: case 2736: case 2737: case 2738: case 2739: case 2740: case 2741: case 2742: case 2743: case 2744: case 2745: case 2746: case 2747: case 2748: case 2749: case 2750: case 2751: case 2752: case 2753: case 2754: case 2755: case 2756: case 2757: case 2758: case 2759: case 2760: case 2761: case 2762: case 2763: case 2764: case 2765: case 2766: case 2767: case 2768: case 2769: case 2770: case 2771: case 2772: case 2773: case 2774: case 2775: case 2776: case 2777: case 2778: case 2779: case 2780: case 2781: case 2782: case 2783: case 2784: case 2785: case 2786: case 2787: case 2788: case 2789: case 2790: case 2791: case 2792: case 2793: case 2794: case 2795: case 2796: case 2797: case 2798: case 2799: case 2800: case 2801: case 2802: case 2803: case 2804: case 2805: case 2806: case 2807: case 2808: case 2809: case 2810: case 2811: case 2812: case 2813: case 2814: case 2815: case 2816: case 2817: case 2818: case 2819: case 2820: case 2821: case 2822: case 2823: case 2824: case 2825: case 2826: case 2827: case 2828: case 2829: case 2830: case 2831: case 2832: case 2833: case 2834: case 2835: case 2836: case 2837: case 2838: case 2839: case 2840: case 2841: case 2842: case 2843: case 2844: case 2845: case 2846: case 2847: case 2848: case 2849: case 2850: case 2851: case 2852: case 2853: case 2854: case 2855: case 2856: case 2857: case 2858: case 2859: case 2860: case 2861: case 2862: case 2863: case 2864: case 2865: case 2866: case 2867: case 2868: case 2869: case 2870: case 2871: case 2872: case 2873: case 2874: case 2875: case 2876: case 2877: case 2878: case 2879: case 2880: case 2881: case 2882: case 2883: case 2884: case 2885: case 2886: case 2887: case 2888: case 2889: case 2890: case 2891: case 2892: case 2893: case 2894: case 2895: case 2896: case 2897: case 2898: case 2899: case 2900: case 2901: case 2902: case 2903: case 2904: case 2905: case 2906: case 2907: case 2908: case 2909: case 2910: case 2911: case 2912: case 2913: case 2914: case 2915: case 2916: case 2917: case 2918: case 2919: case 2920: case 2921: case 2922: case 2923: case 2924: case 2925: case 2926: case 2927: case 2928: case 2929: case 2930: case 2931: case 2932: case 2933: case 2934: case 2935: case 2936: case 2937: case 2938: case 2939: case 2940: case 2941: case 2942: case 2943: case 2944: case 2945: case 2946: case 2947: case 2948: case 2949: case 2950: case 2951: case 2952: case 2953: case 2954: case 2955: case 2956: case 2957: case 2958: case 2959: case 2960: case 2961: case 2962: case 2963: case 2964: case 2965: case 2966: case 2967: case 2968: case 2969: case 2970: case 2971: case 2972: case 2973: case 2974: case 2975: case 2976: case 2977: case 2978: case 2979: case 2980: case 2981: case 2982: case 2983: case 2984: case 2985: case 2986: case 2987: case 2988: case 2989: case 2990: case 2991: case 2992: case 2993: case 2994: case 2995: case 2996: case 2997: case 2998: case 2999: case 3000: case 3001: case 3002: case 3003: case 3004: case 3005: case 3006: case 3007: case 3008: case 3009: case 3010: case 3011: case 3012: case 3013: case 3014: case 3015: case 3016: case 3017: case 3018: case 3019: case 3020: case 3021: case 3022: case 3023: case 3024: case 3025: case 3026: case 3027: case 3028: case 3029: case 3030: case 3031: case 3032: case 3033: case 3034: case 3035: case 3036: case 3037: case 3038: case 3039: case 3040: case 3041: case 3042: case 3043: case 3044: case 3045: case 3046: case 3047: case 3048: case 3049: case 3050: case 3051: case 3052: case 3053: case 3054: case 3055: case 3056: case 3057: case 3058: case 3059: case 3060: case 3061: case 3062: case 3063: case 3064: case 3065: case 3066: case 3067: case 3068: case 3069: case 3070: case 3071: case 3072: case 3073: case 3074: case 3075: case 3076: case 3077: case 3078: case 3079: case 3080: case 3081: case 3082: case 3083: case 3084: case 3085: case 3086: case 3087: case 3088: case 3089: case 3090: case 3091: case 3092: case 3093: case 3094: case 3095: case 3096: case 3097: case 3098: case 3099: case 3100: case 3101: case 3102: case 3103: case 3104: case 3105: case 3106: case 3107: case 3108: case 3109: case 3110: case 3111: case 3112: case 3113: case 3114: case 3115: case 3116: case 3117: case 3118: case 3119: case 3120: case 3121: case 3122: case 3123: case 3124: case 3125: case 3126: case 3127: case 3128: case 3129: case 3130: case 3131: case 3132: case 3133: case 3134: case 3135: case 3136: case 3137: case 3138: case 3139: case 3140: case 3141: case 3142: case 3143: case 3144: case 3145: case 3146: case 3147: case 3148: case 3149: case 3150: case 3151: case 3152: case 3153: case 3154: case 3155: case 3156: case 3157: case 3158: case 3159: case 3160: case 3161: case 3162: case 3163: case 3164: case 3165: case 3166: case 3167: case 3168: case 3169: case 3170: case 3171: case 3172: case 3173: case 3174: case 3175: case 3176: case 3177: case 3178: case 3179: case 3180: case 3181: case 3182: case 3183: case 3184: case 3185: case 3186: case 3187: case 3188: case 3189: case 3190: case 3191: case 3192: case 3193: case 3194: case 3195: case 3196: case 3197: case 3198: case 3199: case 3200: case 3201: case 3202: case 3203: case 3204: case 3205: case 3206: case 3207: case 3208: case 3209: case 3210: case 3211: case 3212: case 3213: case 3214: case 3215: case 3216: case 3217: case 3218: case 3219: case 3220: case 3221: case 3222: case 3223: case 3224: case 3225: case 3226: case 3227: case 3228: case 3229: case 3230: case 3231: case 3232: case 3233: case 3234: case 3235: case 3236: case 3237: case 3238: case 3239: case 3240: case 3241: case 3242: case 3243: case 3244: case 3245: case 3246: case 3247: case 3248: case 3249: case 3250: case 3251: case 3252: case 3253: case 3254: case 3255: case 3256: case 3257: case 3258: case 3259: case 3260: case 3261: case 3262: case 3263: case 3264: case 3265: case 3266: case 3267: case 3268: case 3269: case 3270: case 3271: case 3272: case 3273: case 3274: case 3275: case 3276: case 3277: case 3278: case 3279: case 3280: case 3281: case 3282: case 3283: case 3284: case 3285: case 3286: case 3287: case 3288: case 3289: case 3290: case 3291: case 3292: case 3293: case 3294: case 3295: case 3296: case 3297: case 3298: case 3299: case 3300: case 3301: case 3302: case 3303: case 3304: case 3305: case 3306: case 3307: case 3308: case 3309: case 3310: case 3311: case 3312: case 3313: case 3314: case 3315: case 3316: case 3317: case 3318: case 3319: case 3320: case 3321: case 3322: case 3323: case 3324: case 3325: case 3326: case 3327: case 3328: case 3329: case 3330: case 3331: case 3332: case 3333: case 3334: case 3335: case 3336: case 3337: case 3338: case 3339: case 3340: case 3341: case 3342: case 3343: case 3344: case 3345: case 3346: case 3347: case 3348: case 3349: case 3350: case 3351: case 3352: case 3353: return BlockType::RedstoneWire; case 4031: case 4032: case 4033: case 4034: case 4035: case 4036: case 4037: case 4038: case 4039: case 4040: case 4041: case 4042: case 4043: case 4044: case 4045: case 4046: case 4047: case 4048: case 4049: case 4050: case 4051: case 4052: case 4053: case 4054: case 4055: case 4056: case 4057: case 4058: case 4059: case 4060: case 4061: case 4062: case 4063: case 4064: case 4065: case 4066: case 4067: case 4068: case 4069: case 4070: case 4071: case 4072: case 4073: case 4074: case 4075: case 4076: case 4077: case 4078: case 4079: case 4080: case 4081: case 4082: case 4083: case 4084: case 4085: case 4086: case 4087: case 4088: case 4089: case 4090: case 4091: case 4092: case 4093: case 4094: return BlockType::Repeater; case 9225: case 9226: case 9227: case 9228: case 9229: case 9230: case 9231: case 9232: case 9233: case 9234: case 9235: case 9236: return BlockType::RepeatingCommandBlock; case 15829: case 15830: case 15831: case 15832: case 15833: return BlockType::RespawnAnchor; case 7889: case 7890: return BlockType::RoseBush; case 66: return BlockType::Sand; case 246: return BlockType::Sandstone; case 8349: case 8351: case 8353: return BlockType::SandstoneSlab; case 5171: case 5173: case 5175: case 5177: case 5179: case 5181: case 5183: case 5185: case 5187: case 5189: case 5191: case 5193: case 5195: case 5197: case 5199: case 5201: case 5203: case 5205: case 5207: case 5209: case 5211: case 5213: case 5215: case 5217: case 5219: case 5221: case 5223: case 5225: case 5227: case 5229: case 5231: case 5233: case 5235: case 5237: case 5239: case 5241: case 5243: case 5245: case 5247: case 5249: return BlockType::SandstoneStairs; case 13786: case 13787: case 13788: case 13792: case 13793: case 13794: case 13798: case 13799: case 13800: case 13804: case 13805: case 13806: case 13810: case 13811: case 13812: case 13816: case 13817: case 13818: case 13822: case 13823: case 13824: case 13828: case 13829: case 13830: case 13834: case 13835: case 13836: case 13840: case 13841: case 13842: case 13846: case 13847: case 13848: case 13852: case 13853: case 13854: case 13858: case 13859: case 13860: case 13864: case 13865: case 13866: case 13870: case 13871: case 13872: case 13876: case 13877: case 13878: case 13882: case 13883: case 13884: case 13888: case 13889: case 13890: case 13894: case 13895: case 13896: case 13900: case 13901: case 13902: case 13906: case 13907: case 13908: case 13912: case 13913: case 13914: case 13918: case 13919: case 13920: case 13924: case 13925: case 13926: case 13930: case 13931: case 13932: case 13936: case 13937: case 13938: case 13942: case 13943: case 13944: case 13948: case 13949: case 13950: case 13954: case 13955: case 13956: case 13960: case 13961: case 13962: case 13966: case 13967: case 13968: case 13972: case 13973: case 13974: case 13978: case 13979: case 13980: case 13984: case 13985: case 13986: case 13990: case 13991: case 13992: case 13996: case 13997: case 13998: case 14002: case 14003: case 14004: case 14008: case 14009: case 14010: case 14014: case 14015: case 14016: case 14020: case 14021: case 14022: case 14026: case 14027: case 14028: case 14032: case 14033: case 14034: case 14038: case 14039: case 14040: case 14044: case 14045: case 14046: case 14050: case 14051: case 14052: case 14056: case 14057: case 14058: case 14062: case 14063: case 14064: case 14068: case 14069: case 14070: case 14074: case 14075: case 14076: case 14080: case 14081: case 14082: case 14086: case 14087: case 14088: case 14092: case 14093: case 14094: case 14098: case 14099: case 14100: case 14104: case 14105: case 14106: return BlockType::SandstoneWall; case 14756: case 14758: case 14760: case 14762: case 14764: case 14766: case 14768: case 14770: case 14772: case 14774: case 14776: case 14778: case 14780: case 14782: case 14784: case 14786: return BlockType::Scaffolding; case 7862: return BlockType::SeaLantern; case 9641: case 9643: case 9645: case 9647: return BlockType::SeaPickle; case 1345: return BlockType::Seagrass; case 14989: return BlockType::Shroomlight; case 9272: case 9273: case 9274: case 9275: case 9276: case 9277: return BlockType::ShulkerBox; case 6490: case 6491: case 6492: case 6493: case 6494: case 6495: case 6496: case 6497: case 6498: case 6499: case 6500: case 6501: case 6502: case 6503: case 6504: case 6505: return BlockType::SkeletonSkull; case 6506: case 6507: case 6508: case 6509: return BlockType::SkeletonWallSkull; case 7535: return BlockType::SlimeBlock; case 14849: return BlockType::SmithingTable; case 14803: case 14804: case 14805: case 14806: case 14807: case 14808: case 14809: case 14810: return BlockType::Smoker; case 8416: return BlockType::SmoothQuartz; case 10832: case 10834: case 10836: return BlockType::SmoothQuartzSlab; case 10310: case 10312: case 10314: case 10316: case 10318: case 10320: case 10322: case 10324: case 10326: case 10328: case 10330: case 10332: case 10334: case 10336: case 10338: case 10340: case 10342: case 10344: case 10346: case 10348: case 10350: case 10352: case 10354: case 10356: case 10358: case 10360: case 10362: case 10364: case 10366: case 10368: case 10370: case 10372: case 10374: case 10376: case 10378: case 10380: case 10382: case 10384: case 10386: case 10388: return BlockType::SmoothQuartzStairs; case 8417: return BlockType::SmoothRedSandstone; case 10796: case 10798: case 10800: return BlockType::SmoothRedSandstoneSlab; case 9750: case 9752: case 9754: case 9756: case 9758: case 9760: case 9762: case 9764: case 9766: case 9768: case 9770: case 9772: case 9774: case 9776: case 9778: case 9780: case 9782: case 9784: case 9786: case 9788: case 9790: case 9792: case 9794: case 9796: case 9798: case 9800: case 9802: case 9804: case 9806: case 9808: case 9810: case 9812: case 9814: case 9816: case 9818: case 9820: case 9822: case 9824: case 9826: case 9828: return BlockType::SmoothRedSandstoneStairs; case 8415: return BlockType::SmoothSandstone; case 10826: case 10828: case 10830: return BlockType::SmoothSandstoneSlab; case 10230: case 10232: case 10234: case 10236: case 10238: case 10240: case 10242: case 10244: case 10246: case 10248: case 10250: case 10252: case 10254: case 10256: case 10258: case 10260: case 10262: case 10264: case 10266: case 10268: case 10270: case 10272: case 10274: case 10276: case 10278: case 10280: case 10282: case 10284: case 10286: case 10288: case 10290: case 10292: case 10294: case 10296: case 10298: case 10300: case 10302: case 10304: case 10306: case 10308: return BlockType::SmoothSandstoneStairs; case 8414: return BlockType::SmoothStone; case 8343: case 8345: case 8347: return BlockType::SmoothStoneSlab; case 3921: case 3922: case 3923: case 3924: case 3925: case 3926: case 3927: case 3928: return BlockType::Snow; case 3930: return BlockType::SnowBlock; case 14923: case 14925: case 14927: case 14929: case 14931: case 14933: case 14935: case 14937: case 14939: case 14941: case 14943: case 14945: case 14947: case 14949: case 14951: case 14953: return BlockType::SoulCampfire; case 1952: return BlockType::SoulFire; case 14888: case 14889: return BlockType::SoulLantern; case 4000: return BlockType::SoulSand; case 4001: return BlockType::SoulSoil; case 4008: return BlockType::SoulTorch; case 4009: case 4010: case 4011: case 4012: return BlockType::SoulWallTorch; case 1953: return BlockType::Spawner; case 229: return BlockType::Sponge; case 6370: case 6371: case 6372: case 6373: case 6374: case 6375: case 6376: case 6377: case 6378: case 6379: case 6380: case 6381: case 6382: case 6383: case 6384: case 6385: case 6386: case 6387: case 6388: case 6389: case 6390: case 6391: case 6392: case 6393: return BlockType::SpruceButton; case 8738: case 8739: case 8740: case 8741: case 8742: case 8743: case 8744: case 8745: case 8746: case 8747: case 8748: case 8749: case 8750: case 8751: case 8752: case 8753: case 8754: case 8755: case 8756: case 8757: case 8758: case 8759: case 8760: case 8761: case 8762: case 8763: case 8764: case 8765: case 8766: case 8767: case 8768: case 8769: case 8770: case 8771: case 8772: case 8773: case 8774: case 8775: case 8776: case 8777: case 8778: case 8779: case 8780: case 8781: case 8782: case 8783: case 8784: case 8785: case 8786: case 8787: case 8788: case 8789: case 8790: case 8791: case 8792: case 8793: case 8794: case 8795: case 8796: case 8797: case 8798: case 8799: case 8800: case 8801: return BlockType::SpruceDoor; case 8580: case 8581: case 8584: case 8585: case 8588: case 8589: case 8592: case 8593: case 8596: case 8597: case 8600: case 8601: case 8604: case 8605: case 8608: case 8609: return BlockType::SpruceFence; case 8418: case 8419: case 8420: case 8421: case 8422: case 8423: case 8424: case 8425: case 8426: case 8427: case 8428: case 8429: case 8430: case 8431: case 8432: case 8433: case 8434: case 8435: case 8436: case 8437: case 8438: case 8439: case 8440: case 8441: case 8442: case 8443: case 8444: case 8445: case 8446: case 8447: case 8448: case 8449: return BlockType::SpruceFenceGate; case 159: case 160: case 161: case 162: case 163: case 164: case 165: case 166: case 167: case 168: case 169: case 170: case 171: case 172: return BlockType::SpruceLeaves; case 76: case 77: case 78: return BlockType::SpruceLog; case 16: return BlockType::SprucePlanks; case 3875: case 3876: return BlockType::SprucePressurePlate; case 23: case 24: return BlockType::SpruceSapling; case 3414: case 3416: case 3418: case 3420: case 3422: case 3424: case 3426: case 3428: case 3430: case 3432: case 3434: case 3436: case 3438: case 3440: case 3442: case 3444: return BlockType::SpruceSign; case 8307: case 8309: case 8311: return BlockType::SpruceSlab; case 5405: case 5407: case 5409: case 5411: case 5413: case 5415: case 5417: case 5419: case 5421: case 5423: case 5425: case 5427: case 5429: case 5431: case 5433: case 5435: case 5437: case 5439: case 5441: case 5443: case 5445: case 5447: case 5449: case 5451: case 5453: case 5455: case 5457: case 5459: case 5461: case 5463: case 5465: case 5467: case 5469: case 5471: case 5473: case 5475: case 5477: case 5479: case 5481: case 5483: return BlockType::SpruceStairs; case 4176: case 4178: case 4180: case 4182: case 4184: case 4186: case 4188: case 4190: case 4192: case 4194: case 4196: case 4198: case 4200: case 4202: case 4204: case 4206: case 4208: case 4210: case 4212: case 4214: case 4216: case 4218: case 4220: case 4222: case 4224: case 4226: case 4228: case 4230: case 4232: case 4234: case 4236: case 4238: return BlockType::SpruceTrapdoor; case 3744: case 3746: case 3748: case 3750: return BlockType::SpruceWallSign; case 112: case 113: case 114: return BlockType::SpruceWood; case 1329: case 1330: case 1331: case 1332: case 1333: case 1334: case 1335: case 1336: case 1337: case 1338: case 1339: case 1340: return BlockType::StickyPiston; case 1: return BlockType::Stone; case 8379: case 8381: case 8383: return BlockType::StoneBrickSlab; case 4933: case 4935: case 4937: case 4939: case 4941: case 4943: case 4945: case 4947: case 4949: case 4951: case 4953: case 4955: case 4957: case 4959: case 4961: case 4963: case 4965: case 4967: case 4969: case 4971: case 4973: case 4975: case 4977: case 4979: case 4981: case 4983: case 4985: case 4987: case 4989: case 4991: case 4993: case 4995: case 4997: case 4999: case 5001: case 5003: case 5005: case 5007: case 5009: case 5011: return BlockType::StoneBrickStairs; case 12490: case 12491: case 12492: case 12496: case 12497: case 12498: case 12502: case 12503: case 12504: case 12508: case 12509: case 12510: case 12514: case 12515: case 12516: case 12520: case 12521: case 12522: case 12526: case 12527: case 12528: case 12532: case 12533: case 12534: case 12538: case 12539: case 12540: case 12544: case 12545: case 12546: case 12550: case 12551: case 12552: case 12556: case 12557: case 12558: case 12562: case 12563: case 12564: case 12568: case 12569: case 12570: case 12574: case 12575: case 12576: case 12580: case 12581: case 12582: case 12586: case 12587: case 12588: case 12592: case 12593: case 12594: case 12598: case 12599: case 12600: case 12604: case 12605: case 12606: case 12610: case 12611: case 12612: case 12616: case 12617: case 12618: case 12622: case 12623: case 12624: case 12628: case 12629: case 12630: case 12634: case 12635: case 12636: case 12640: case 12641: case 12642: case 12646: case 12647: case 12648: case 12652: case 12653: case 12654: case 12658: case 12659: case 12660: case 12664: case 12665: case 12666: case 12670: case 12671: case 12672: case 12676: case 12677: case 12678: case 12682: case 12683: case 12684: case 12688: case 12689: case 12690: case 12694: case 12695: case 12696: case 12700: case 12701: case 12702: case 12706: case 12707: case 12708: case 12712: case 12713: case 12714: case 12718: case 12719: case 12720: case 12724: case 12725: case 12726: case 12730: case 12731: case 12732: case 12736: case 12737: case 12738: case 12742: case 12743: case 12744: case 12748: case 12749: case 12750: case 12754: case 12755: case 12756: case 12760: case 12761: case 12762: case 12766: case 12767: case 12768: case 12772: case 12773: case 12774: case 12778: case 12779: case 12780: case 12784: case 12785: case 12786: case 12790: case 12791: case 12792: case 12796: case 12797: case 12798: case 12802: case 12803: case 12804: case 12808: case 12809: case 12810: return BlockType::StoneBrickWall; case 4495: return BlockType::StoneBricks; case 3897: case 3898: case 3899: case 3900: case 3901: case 3902: case 3903: case 3904: case 3905: case 3906: case 3907: case 3908: case 3909: case 3910: case 3911: case 3912: case 3913: case 3914: case 3915: case 3916: case 3917: case 3918: case 3919: case 3920: return BlockType::StoneButton; case 3807: case 3808: return BlockType::StonePressurePlate; case 8337: case 8339: case 8341: return BlockType::StoneSlab; case 10150: case 10152: case 10154: case 10156: case 10158: case 10160: case 10162: case 10164: case 10166: case 10168: case 10170: case 10172: case 10174: case 10176: case 10178: case 10180: case 10182: case 10184: case 10186: case 10188: case 10190: case 10192: case 10194: case 10196: case 10198: case 10200: case 10202: case 10204: case 10206: case 10208: case 10210: case 10212: case 10214: case 10216: case 10218: case 10220: case 10222: case 10224: case 10226: case 10228: return BlockType::StoneStairs; case 14850: case 14851: case 14852: case 14853: return BlockType::Stonecutter; case 100: case 101: case 102: return BlockType::StrippedAcaciaLog; case 139: case 140: case 141: return BlockType::StrippedAcaciaWood; case 94: case 95: case 96: return BlockType::StrippedBirchLog; case 133: case 134: case 135: return BlockType::StrippedBirchWood; case 14984: case 14985: case 14986: return BlockType::StrippedCrimsonHyphae; case 14978: case 14979: case 14980: return BlockType::StrippedCrimsonStem; case 103: case 104: case 105: return BlockType::StrippedDarkOakLog; case 142: case 143: case 144: return BlockType::StrippedDarkOakWood; case 97: case 98: case 99: return BlockType::StrippedJungleLog; case 136: case 137: case 138: return BlockType::StrippedJungleWood; case 106: case 107: case 108: return BlockType::StrippedOakLog; case 127: case 128: case 129: return BlockType::StrippedOakWood; case 91: case 92: case 93: return BlockType::StrippedSpruceLog; case 130: case 131: case 132: return BlockType::StrippedSpruceWood; case 14967: case 14968: case 14969: return BlockType::StrippedWarpedHyphae; case 14961: case 14962: case 14963: return BlockType::StrippedWarpedStem; case 15735: case 15736: case 15737: case 15738: return BlockType::StructureBlock; case 9259: return BlockType::StructureVoid; case 3948: case 3949: case 3950: case 3951: case 3952: case 3953: case 3954: case 3955: case 3956: case 3957: case 3958: case 3959: case 3960: case 3961: case 3962: case 3963: return BlockType::SugarCane; case 7885: case 7886: return BlockType::Sunflower; case 14954: case 14955: case 14956: case 14957: return BlockType::SweetBerryBush; case 1430: case 1431: return BlockType::TNT; case 7893: case 7894: return BlockType::TallGrass; case 1346: case 1347: return BlockType::TallSeagrass; case 15760: case 15761: case 15762: case 15763: case 15764: case 15765: case 15766: case 15767: case 15768: case 15769: case 15770: case 15771: case 15772: case 15773: case 15774: case 15775: return BlockType::Target; case 7882: return BlockType::Terracotta; case 1435: return BlockType::Torch; case 6623: case 6625: case 6627: case 6629: case 6631: case 6633: case 6635: case 6637: case 6639: case 6641: case 6643: case 6645: return BlockType::TrappedChest; case 5275: case 5276: case 5277: case 5278: case 5279: case 5280: case 5281: case 5282: case 5283: case 5284: case 5285: case 5286: case 5287: case 5288: case 5289: case 5290: case 5291: case 5292: case 5293: case 5294: case 5295: case 5296: case 5297: case 5298: case 5299: case 5300: case 5301: case 5302: case 5303: case 5304: case 5305: case 5306: case 5307: case 5308: case 5309: case 5310: case 5311: case 5312: case 5313: case 5314: case 5315: case 5316: case 5317: case 5318: case 5319: case 5320: case 5321: case 5322: case 5323: case 5324: case 5325: case 5326: case 5327: case 5328: case 5329: case 5330: case 5331: case 5332: case 5333: case 5334: case 5335: case 5336: case 5337: case 5338: case 5339: case 5340: case 5341: case 5342: case 5343: case 5344: case 5345: case 5346: case 5347: case 5348: case 5349: case 5350: case 5351: case 5352: case 5353: case 5354: case 5355: case 5356: case 5357: case 5358: case 5359: case 5360: case 5361: case 5362: case 5363: case 5364: case 5365: case 5366: case 5367: case 5368: case 5369: case 5370: case 5371: case 5372: case 5373: case 5374: case 5375: case 5376: case 5377: case 5378: case 5379: case 5380: case 5381: case 5382: case 5383: case 5384: case 5385: case 5386: case 5387: case 5388: case 5389: case 5390: case 5391: case 5392: case 5393: case 5394: case 5395: case 5396: case 5397: case 5398: case 5399: case 5400: case 5401: case 5402: return BlockType::Tripwire; case 5259: case 5260: case 5261: case 5262: case 5263: case 5264: case 5265: case 5266: case 5267: case 5268: case 5269: case 5270: case 5271: case 5272: case 5273: case 5274: return BlockType::TripwireHook; case 9531: return BlockType::TubeCoral; case 9515: return BlockType::TubeCoralBlock; case 9551: return BlockType::TubeCoralFan; case 9601: case 9603: case 9605: case 9607: return BlockType::TubeCoralWallFan; case 9498: case 9499: case 9500: case 9501: case 9502: case 9503: case 9504: case 9505: case 9506: case 9507: case 9508: case 9509: return BlockType::TurtleEgg; case 15017: case 15018: case 15019: case 15020: case 15021: case 15022: case 15023: case 15024: case 15025: case 15026: case 15027: case 15028: case 15029: case 15030: case 15031: case 15032: case 15033: case 15034: case 15035: case 15036: case 15037: case 15038: case 15039: case 15040: case 15041: case 15042: return BlockType::TwistingVines; case 15043: return BlockType::TwistingVinesPlant; case 4788: case 4789: case 4790: case 4791: case 4792: case 4793: case 4794: case 4795: case 4796: case 4797: case 4798: case 4799: case 4800: case 4801: case 4802: case 4803: case 4804: case 4805: case 4806: case 4807: case 4808: case 4809: case 4810: case 4811: case 4812: case 4813: case 4814: case 4815: case 4816: case 4817: case 4818: case 4819: return BlockType::Vine; case 9665: return BlockType::VoidAir; case 1436: case 1437: case 1438: case 1439: return BlockType::WallTorch; case 15503: case 15504: case 15505: case 15506: case 15507: case 15508: case 15509: case 15510: case 15511: case 15512: case 15513: case 15514: case 15515: case 15516: case 15517: case 15518: case 15519: case 15520: case 15521: case 15522: case 15523: case 15524: case 15525: case 15526: return BlockType::WarpedButton; case 15591: case 15592: case 15593: case 15594: case 15595: case 15596: case 15597: case 15598: case 15599: case 15600: case 15601: case 15602: case 15603: case 15604: case 15605: case 15606: case 15607: case 15608: case 15609: case 15610: case 15611: case 15612: case 15613: case 15614: case 15615: case 15616: case 15617: case 15618: case 15619: case 15620: case 15621: case 15622: case 15623: case 15624: case 15625: case 15626: case 15627: case 15628: case 15629: case 15630: case 15631: case 15632: case 15633: case 15634: case 15635: case 15636: case 15637: case 15638: case 15639: case 15640: case 15641: case 15642: case 15643: case 15644: case 15645: case 15646: case 15647: case 15648: case 15649: case 15650: case 15651: case 15652: case 15653: case 15654: return BlockType::WarpedDoor; case 15097: case 15098: case 15101: case 15102: case 15105: case 15106: case 15109: case 15110: case 15113: case 15114: case 15117: case 15118: case 15121: case 15122: case 15125: case 15126: return BlockType::WarpedFence; case 15287: case 15288: case 15289: case 15290: case 15291: case 15292: case 15293: case 15294: case 15295: case 15296: case 15297: case 15298: case 15299: case 15300: case 15301: case 15302: case 15303: case 15304: case 15305: case 15306: case 15307: case 15308: case 15309: case 15310: case 15311: case 15312: case 15313: case 15314: case 15315: case 15316: case 15317: case 15318: return BlockType::WarpedFenceGate; case 14971: return BlockType::WarpedFungus; case 14964: case 14965: case 14966: return BlockType::WarpedHyphae; case 14970: return BlockType::WarpedNylium; case 15046: return BlockType::WarpedPlanks; case 15061: case 15062: return BlockType::WarpedPressurePlate; case 14973: return BlockType::WarpedRoots; case 15688: case 15690: case 15692: case 15694: case 15696: case 15698: case 15700: case 15702: case 15704: case 15706: case 15708: case 15710: case 15712: case 15714: case 15716: case 15718: return BlockType::WarpedSign; case 15054: case 15056: case 15058: return BlockType::WarpedSlab; case 15400: case 15402: case 15404: case 15406: case 15408: case 15410: case 15412: case 15414: case 15416: case 15418: case 15420: case 15422: case 15424: case 15426: case 15428: case 15430: case 15432: case 15434: case 15436: case 15438: case 15440: case 15442: case 15444: case 15446: case 15448: case 15450: case 15452: case 15454: case 15456: case 15458: case 15460: case 15462: case 15464: case 15466: case 15468: case 15470: case 15472: case 15474: case 15476: case 15478: return BlockType::WarpedStairs; case 14958: case 14959: case 14960: return BlockType::WarpedStem; case 15192: case 15194: case 15196: case 15198: case 15200: case 15202: case 15204: case 15206: case 15208: case 15210: case 15212: case 15214: case 15216: case 15218: case 15220: case 15222: case 15224: case 15226: case 15228: case 15230: case 15232: case 15234: case 15236: case 15238: case 15240: case 15242: case 15244: case 15246: case 15248: case 15250: case 15252: case 15254: return BlockType::WarpedTrapdoor; case 15728: case 15730: case 15732: case 15734: return BlockType::WarpedWallSign; case 14972: return BlockType::WarpedWartBlock; case 34: case 35: case 36: case 37: case 38: case 39: case 40: case 41: case 42: case 43: case 44: case 45: case 46: case 47: case 48: case 49: return BlockType::Water; case 14990: case 14991: case 14992: case 14993: case 14994: case 14995: case 14996: case 14997: case 14998: case 14999: case 15000: case 15001: case 15002: case 15003: case 15004: case 15005: case 15006: case 15007: case 15008: case 15009: case 15010: case 15011: case 15012: case 15013: case 15014: case 15015: return BlockType::WeepingVines; case 15016: return BlockType::WeepingVinesPlant; case 230: return BlockType::WetSponge; case 3357: case 3358: case 3359: case 3360: case 3361: case 3362: case 3363: case 3364: return BlockType::Wheat; case 7897: case 7898: case 7899: case 7900: case 7901: case 7902: case 7903: case 7904: case 7905: case 7906: case 7907: case 7908: case 7909: case 7910: case 7911: case 7912: return BlockType::WhiteBanner; case 1049: case 1050: case 1051: case 1052: case 1053: case 1054: case 1055: case 1056: case 1057: case 1058: case 1059: case 1060: case 1061: case 1062: case 1063: case 1064: return BlockType::WhiteBed; case 7866: return BlockType::WhiteCarpet; case 9438: return BlockType::WhiteConcrete; case 9454: return BlockType::WhiteConcretePowder; case 9374: case 9375: case 9376: case 9377: return BlockType::WhiteGlazedTerracotta; case 9278: case 9279: case 9280: case 9281: case 9282: case 9283: return BlockType::WhiteShulkerBox; case 4095: return BlockType::WhiteStainedGlass; case 6865: case 6866: case 6869: case 6870: case 6873: case 6874: case 6877: case 6878: case 6881: case 6882: case 6885: case 6886: case 6889: case 6890: case 6893: case 6894: return BlockType::WhiteStainedGlassPane; case 6847: return BlockType::WhiteTerracotta; case 1419: return BlockType::WhiteTulip; case 8153: case 8154: case 8155: case 8156: return BlockType::WhiteWallBanner; case 1384: return BlockType::WhiteWool; case 1423: return BlockType::WitherRose; case 6510: case 6511: case 6512: case 6513: case 6514: case 6515: case 6516: case 6517: case 6518: case 6519: case 6520: case 6521: case 6522: case 6523: case 6524: case 6525: return BlockType::WitherSkeletonSkull; case 6526: case 6527: case 6528: case 6529: return BlockType::WitherSkeletonWallSkull; case 7961: case 7962: case 7963: case 7964: case 7965: case 7966: case 7967: case 7968: case 7969: case 7970: case 7971: case 7972: case 7973: case 7974: case 7975: case 7976: return BlockType::YellowBanner; case 1113: case 1114: case 1115: case 1116: case 1117: case 1118: case 1119: case 1120: case 1121: case 1122: case 1123: case 1124: case 1125: case 1126: case 1127: case 1128: return BlockType::YellowBed; case 7870: return BlockType::YellowCarpet; case 9442: return BlockType::YellowConcrete; case 9458: return BlockType::YellowConcretePowder; case 9390: case 9391: case 9392: case 9393: return BlockType::YellowGlazedTerracotta; case 9302: case 9303: case 9304: case 9305: case 9306: case 9307: return BlockType::YellowShulkerBox; case 4099: return BlockType::YellowStainedGlass; case 6993: case 6994: case 6997: case 6998: case 7001: case 7002: case 7005: case 7006: case 7009: case 7010: case 7013: case 7014: case 7017: case 7018: case 7021: case 7022: return BlockType::YellowStainedGlassPane; case 6851: return BlockType::YellowTerracotta; case 8169: case 8170: case 8171: case 8172: return BlockType::YellowWallBanner; case 1388: return BlockType::YellowWool; case 6530: case 6531: case 6532: case 6533: case 6534: case 6535: case 6536: case 6537: case 6538: case 6539: case 6540: case 6541: case 6542: case 6543: case 6544: case 6545: return BlockType::ZombieHead; default: return BlockType::ZombieWallHead; } } ================================================ FILE: src/Registries/BlockStates.h ================================================ #pragma once #include "Globals.h" #include "BlockState.h" #include "Defines.h" namespace Block { namespace AcaciaButton { enum class Face { Floor, Wall, Ceiling }; constexpr BlockState AcaciaButton(const enum Face Face, const eBlockFace Facing, const bool Powered) { if (Face == Face::Floor) if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Powered) return 6442; else return 6443; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Powered) return 6444; else return 6445; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Powered) return 6446; else return 6447; else if (Powered) return 6448; else return 6449; else if (Face == Face::Wall) if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Powered) return 6450; else return 6451; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Powered) return 6452; else return 6453; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Powered) return 6454; else return 6455; else if (Powered) return 6456; else return 6457; else if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Powered) return 6458; else return 6459; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Powered) return 6460; else return 6461; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Powered) return 6462; else return 6463; else if (Powered) return 6464; else return 6465; } BlockState AcaciaButton(); enum Face Face(BlockState Block); eBlockFace Facing(BlockState Block); bool Powered(BlockState Block); } namespace AcaciaDoor { enum class Half { Upper, Lower }; enum class Hinge { Left, Right }; constexpr BlockState AcaciaDoor(const eBlockFace Facing, const enum Half Half, const enum Hinge Hinge, const bool Open, const bool Powered) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Half == Half::Upper) if (Hinge == Hinge::Left) if (Open) if (Powered) return 8930; else return 8931; else if (Powered) return 8932; else return 8933; else if (Open) if (Powered) return 8934; else return 8935; else if (Powered) return 8936; else return 8937; else if (Hinge == Hinge::Left) if (Open) if (Powered) return 8938; else return 8939; else if (Powered) return 8940; else return 8941; else if (Open) if (Powered) return 8942; else return 8943; else if (Powered) return 8944; else return 8945; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Half == Half::Upper) if (Hinge == Hinge::Left) if (Open) if (Powered) return 8946; else return 8947; else if (Powered) return 8948; else return 8949; else if (Open) if (Powered) return 8950; else return 8951; else if (Powered) return 8952; else return 8953; else if (Hinge == Hinge::Left) if (Open) if (Powered) return 8954; else return 8955; else if (Powered) return 8956; else return 8957; else if (Open) if (Powered) return 8958; else return 8959; else if (Powered) return 8960; else return 8961; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Half == Half::Upper) if (Hinge == Hinge::Left) if (Open) if (Powered) return 8962; else return 8963; else if (Powered) return 8964; else return 8965; else if (Open) if (Powered) return 8966; else return 8967; else if (Powered) return 8968; else return 8969; else if (Hinge == Hinge::Left) if (Open) if (Powered) return 8970; else return 8971; else if (Powered) return 8972; else return 8973; else if (Open) if (Powered) return 8974; else return 8975; else if (Powered) return 8976; else return 8977; else if (Half == Half::Upper) if (Hinge == Hinge::Left) if (Open) if (Powered) return 8978; else return 8979; else if (Powered) return 8980; else return 8981; else if (Open) if (Powered) return 8982; else return 8983; else if (Powered) return 8984; else return 8985; else if (Hinge == Hinge::Left) if (Open) if (Powered) return 8986; else return 8987; else if (Powered) return 8988; else return 8989; else if (Open) if (Powered) return 8990; else return 8991; else if (Powered) return 8992; else return 8993; } BlockState AcaciaDoor(); eBlockFace Facing(BlockState Block); enum Half Half(BlockState Block); enum Hinge Hinge(BlockState Block); bool Open(BlockState Block); bool Powered(BlockState Block); } namespace AcaciaFence { constexpr BlockState AcaciaFence(const bool East, const bool North, const bool South, const bool West) { if (East) if (North) if (South) if (West) return 8676; else return 8677; else if (West) return 8680; else return 8681; else if (South) if (West) return 8684; else return 8685; else if (West) return 8688; else return 8689; else if (North) if (South) if (West) return 8692; else return 8693; else if (West) return 8696; else return 8697; else if (South) if (West) return 8700; else return 8701; else if (West) return 8704; else return 8705; } BlockState AcaciaFence(); bool East(BlockState Block); bool North(BlockState Block); bool South(BlockState Block); bool West(BlockState Block); } namespace AcaciaFenceGate { constexpr BlockState AcaciaFenceGate(const eBlockFace Facing, const bool InWall, const bool Open, const bool Powered) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (InWall) if (Open) if (Powered) return 8514; else return 8515; else if (Powered) return 8516; else return 8517; else if (Open) if (Powered) return 8518; else return 8519; else if (Powered) return 8520; else return 8521; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (InWall) if (Open) if (Powered) return 8522; else return 8523; else if (Powered) return 8524; else return 8525; else if (Open) if (Powered) return 8526; else return 8527; else if (Powered) return 8528; else return 8529; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (InWall) if (Open) if (Powered) return 8530; else return 8531; else if (Powered) return 8532; else return 8533; else if (Open) if (Powered) return 8534; else return 8535; else if (Powered) return 8536; else return 8537; else if (InWall) if (Open) if (Powered) return 8538; else return 8539; else if (Powered) return 8540; else return 8541; else if (Open) if (Powered) return 8542; else return 8543; else if (Powered) return 8544; else return 8545; } BlockState AcaciaFenceGate(); eBlockFace Facing(BlockState Block); bool InWall(BlockState Block); bool Open(BlockState Block); bool Powered(BlockState Block); } namespace AcaciaLeaves { constexpr BlockState AcaciaLeaves(const unsigned char Distance, const bool Persistent) { if (Distance == 1) if (Persistent) return 201; else return 202; else if (Distance == 2) if (Persistent) return 203; else return 204; else if (Distance == 3) if (Persistent) return 205; else return 206; else if (Distance == 4) if (Persistent) return 207; else return 208; else if (Distance == 5) if (Persistent) return 209; else return 210; else if (Distance == 6) if (Persistent) return 211; else return 212; else if (Persistent) return 213; else return 214; } BlockState AcaciaLeaves(); unsigned char Distance(BlockState Block); bool Persistent(BlockState Block); } namespace AcaciaLog { enum class Axis { X, Y, Z }; constexpr BlockState AcaciaLog(const enum Axis Axis) { if (Axis == Axis::X) return 85; else if (Axis == Axis::Y) return 86; else return 87; } BlockState AcaciaLog(); enum Axis Axis(BlockState Block); } namespace AcaciaPlanks { constexpr BlockState AcaciaPlanks() { return 19; } } namespace AcaciaPressurePlate { constexpr BlockState AcaciaPressurePlate(const bool Powered) { if (Powered) return 3881; else return 3882; } BlockState AcaciaPressurePlate(); bool Powered(BlockState Block); } namespace AcaciaSapling { constexpr BlockState AcaciaSapling(const unsigned char Stage) { if (Stage == 0) return 29; else return 30; } BlockState AcaciaSapling(); unsigned char Stage(BlockState Block); } namespace AcaciaSign { constexpr BlockState AcaciaSign(const unsigned char Rotation) { if (Rotation == 0) return 3478; else if (Rotation == 1) return 3480; else if (Rotation == 2) return 3482; else if (Rotation == 3) return 3484; else if (Rotation == 4) return 3486; else if (Rotation == 5) return 3488; else if (Rotation == 6) return 3490; else if (Rotation == 7) return 3492; else if (Rotation == 8) return 3494; else if (Rotation == 9) return 3496; else if (Rotation == 10) return 3498; else if (Rotation == 11) return 3500; else if (Rotation == 12) return 3502; else if (Rotation == 13) return 3504; else if (Rotation == 14) return 3506; else return 3508; } BlockState AcaciaSign(); unsigned char Rotation(BlockState Block); } namespace AcaciaSlab { enum class Type { Top, Bottom, Double }; constexpr BlockState AcaciaSlab(const enum Type Type) { if (Type == Type::Top) return 8325; else if (Type == Type::Bottom) return 8327; else return 8329; } BlockState AcaciaSlab(); enum Type Type(BlockState Block); } namespace AcaciaStairs { enum class Half { Top, Bottom }; enum class Shape { Straight, InnerLeft, InnerRight, OuterLeft, OuterRight }; constexpr BlockState AcaciaStairs(const eBlockFace Facing, const enum Half Half, const enum Shape Shape) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Half == Half::Top) if (Shape == Shape::Straight) return 7376; else if (Shape == Shape::InnerLeft) return 7378; else if (Shape == Shape::InnerRight) return 7380; else if (Shape == Shape::OuterLeft) return 7382; else return 7384; else if (Shape == Shape::Straight) return 7386; else if (Shape == Shape::InnerLeft) return 7388; else if (Shape == Shape::InnerRight) return 7390; else if (Shape == Shape::OuterLeft) return 7392; else return 7394; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Half == Half::Top) if (Shape == Shape::Straight) return 7396; else if (Shape == Shape::InnerLeft) return 7398; else if (Shape == Shape::InnerRight) return 7400; else if (Shape == Shape::OuterLeft) return 7402; else return 7404; else if (Shape == Shape::Straight) return 7406; else if (Shape == Shape::InnerLeft) return 7408; else if (Shape == Shape::InnerRight) return 7410; else if (Shape == Shape::OuterLeft) return 7412; else return 7414; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Half == Half::Top) if (Shape == Shape::Straight) return 7416; else if (Shape == Shape::InnerLeft) return 7418; else if (Shape == Shape::InnerRight) return 7420; else if (Shape == Shape::OuterLeft) return 7422; else return 7424; else if (Shape == Shape::Straight) return 7426; else if (Shape == Shape::InnerLeft) return 7428; else if (Shape == Shape::InnerRight) return 7430; else if (Shape == Shape::OuterLeft) return 7432; else return 7434; else if (Half == Half::Top) if (Shape == Shape::Straight) return 7436; else if (Shape == Shape::InnerLeft) return 7438; else if (Shape == Shape::InnerRight) return 7440; else if (Shape == Shape::OuterLeft) return 7442; else return 7444; else if (Shape == Shape::Straight) return 7446; else if (Shape == Shape::InnerLeft) return 7448; else if (Shape == Shape::InnerRight) return 7450; else if (Shape == Shape::OuterLeft) return 7452; else return 7454; } BlockState AcaciaStairs(); eBlockFace Facing(BlockState Block); enum Half Half(BlockState Block); enum Shape Shape(BlockState Block); } namespace AcaciaTrapdoor { enum class Half { Top, Bottom }; constexpr BlockState AcaciaTrapdoor(const eBlockFace Facing, const enum Half Half, const bool Open, const bool Powered) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Half == Half::Top) if (Open) if (Powered) return 4368; else return 4370; else if (Powered) return 4372; else return 4374; else if (Open) if (Powered) return 4376; else return 4378; else if (Powered) return 4380; else return 4382; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Half == Half::Top) if (Open) if (Powered) return 4384; else return 4386; else if (Powered) return 4388; else return 4390; else if (Open) if (Powered) return 4392; else return 4394; else if (Powered) return 4396; else return 4398; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Half == Half::Top) if (Open) if (Powered) return 4400; else return 4402; else if (Powered) return 4404; else return 4406; else if (Open) if (Powered) return 4408; else return 4410; else if (Powered) return 4412; else return 4414; else if (Half == Half::Top) if (Open) if (Powered) return 4416; else return 4418; else if (Powered) return 4420; else return 4422; else if (Open) if (Powered) return 4424; else return 4426; else if (Powered) return 4428; else return 4430; } BlockState AcaciaTrapdoor(); eBlockFace Facing(BlockState Block); enum Half Half(BlockState Block); bool Open(BlockState Block); bool Powered(BlockState Block); } namespace AcaciaWallSign { constexpr BlockState AcaciaWallSign(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 3760; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 3762; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 3764; else return 3766; } BlockState AcaciaWallSign(); eBlockFace Facing(BlockState Block); } namespace AcaciaWood { enum class Axis { X, Y, Z }; constexpr BlockState AcaciaWood(const enum Axis Axis) { if (Axis == Axis::X) return 121; else if (Axis == Axis::Y) return 122; else return 123; } BlockState AcaciaWood(); enum Axis Axis(BlockState Block); } namespace ActivatorRail { enum class Shape { NorthSouth, EastWest, AscendingEast, AscendingWest, AscendingNorth, AscendingSouth }; constexpr BlockState ActivatorRail(const bool Powered, const enum Shape Shape) { if (Powered) if (Shape == Shape::NorthSouth) return 6823; else if (Shape == Shape::EastWest) return 6824; else if (Shape == Shape::AscendingEast) return 6825; else if (Shape == Shape::AscendingWest) return 6826; else if (Shape == Shape::AscendingNorth) return 6827; else return 6828; else if (Shape == Shape::NorthSouth) return 6829; else if (Shape == Shape::EastWest) return 6830; else if (Shape == Shape::AscendingEast) return 6831; else if (Shape == Shape::AscendingWest) return 6832; else if (Shape == Shape::AscendingNorth) return 6833; else return 6834; } BlockState ActivatorRail(); bool Powered(BlockState Block); enum Shape Shape(BlockState Block); } namespace Air { constexpr BlockState Air() { return -0; } } namespace Allium { constexpr BlockState Allium() { return 1415; } } namespace AncientDebris { constexpr BlockState AncientDebris() { return 15827; } } namespace Andesite { constexpr BlockState Andesite() { return 6; } } namespace AndesiteSlab { enum class Type { Top, Bottom, Double }; constexpr BlockState AndesiteSlab(const enum Type Type) { if (Type == Type::Top) return 10844; else if (Type == Type::Bottom) return 10846; else return 10848; } BlockState AndesiteSlab(); enum Type Type(BlockState Block); } namespace AndesiteStairs { enum class Half { Top, Bottom }; enum class Shape { Straight, InnerLeft, InnerRight, OuterLeft, OuterRight }; constexpr BlockState AndesiteStairs(const eBlockFace Facing, const enum Half Half, const enum Shape Shape) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Half == Half::Top) if (Shape == Shape::Straight) return 10470; else if (Shape == Shape::InnerLeft) return 10472; else if (Shape == Shape::InnerRight) return 10474; else if (Shape == Shape::OuterLeft) return 10476; else return 10478; else if (Shape == Shape::Straight) return 10480; else if (Shape == Shape::InnerLeft) return 10482; else if (Shape == Shape::InnerRight) return 10484; else if (Shape == Shape::OuterLeft) return 10486; else return 10488; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Half == Half::Top) if (Shape == Shape::Straight) return 10490; else if (Shape == Shape::InnerLeft) return 10492; else if (Shape == Shape::InnerRight) return 10494; else if (Shape == Shape::OuterLeft) return 10496; else return 10498; else if (Shape == Shape::Straight) return 10500; else if (Shape == Shape::InnerLeft) return 10502; else if (Shape == Shape::InnerRight) return 10504; else if (Shape == Shape::OuterLeft) return 10506; else return 10508; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Half == Half::Top) if (Shape == Shape::Straight) return 10510; else if (Shape == Shape::InnerLeft) return 10512; else if (Shape == Shape::InnerRight) return 10514; else if (Shape == Shape::OuterLeft) return 10516; else return 10518; else if (Shape == Shape::Straight) return 10520; else if (Shape == Shape::InnerLeft) return 10522; else if (Shape == Shape::InnerRight) return 10524; else if (Shape == Shape::OuterLeft) return 10526; else return 10528; else if (Half == Half::Top) if (Shape == Shape::Straight) return 10530; else if (Shape == Shape::InnerLeft) return 10532; else if (Shape == Shape::InnerRight) return 10534; else if (Shape == Shape::OuterLeft) return 10536; else return 10538; else if (Shape == Shape::Straight) return 10540; else if (Shape == Shape::InnerLeft) return 10542; else if (Shape == Shape::InnerRight) return 10544; else if (Shape == Shape::OuterLeft) return 10546; else return 10548; } BlockState AndesiteStairs(); eBlockFace Facing(BlockState Block); enum Half Half(BlockState Block); enum Shape Shape(BlockState Block); } namespace AndesiteWall { enum class East { None, Low, Tall }; enum class North { None, Low, Tall }; enum class South { None, Low, Tall }; enum class West { None, Low, Tall }; constexpr BlockState AndesiteWall(const enum East East, const enum North North, const enum South South, const bool Up, const enum West West) { if (East == East::None) if (North == North::None) if (South == South::None) if (Up) if (West == West::None) return 13138; else if (West == West::Low) return 13139; else return 13140; else if (West == West::None) return 13144; else if (West == West::Low) return 13145; else return 13146; else if (South == South::Low) if (Up) if (West == West::None) return 13150; else if (West == West::Low) return 13151; else return 13152; else if (West == West::None) return 13156; else if (West == West::Low) return 13157; else return 13158; else if (Up) if (West == West::None) return 13162; else if (West == West::Low) return 13163; else return 13164; else if (West == West::None) return 13168; else if (West == West::Low) return 13169; else return 13170; else if (North == North::Low) if (South == South::None) if (Up) if (West == West::None) return 13174; else if (West == West::Low) return 13175; else return 13176; else if (West == West::None) return 13180; else if (West == West::Low) return 13181; else return 13182; else if (South == South::Low) if (Up) if (West == West::None) return 13186; else if (West == West::Low) return 13187; else return 13188; else if (West == West::None) return 13192; else if (West == West::Low) return 13193; else return 13194; else if (Up) if (West == West::None) return 13198; else if (West == West::Low) return 13199; else return 13200; else if (West == West::None) return 13204; else if (West == West::Low) return 13205; else return 13206; else if (South == South::None) if (Up) if (West == West::None) return 13210; else if (West == West::Low) return 13211; else return 13212; else if (West == West::None) return 13216; else if (West == West::Low) return 13217; else return 13218; else if (South == South::Low) if (Up) if (West == West::None) return 13222; else if (West == West::Low) return 13223; else return 13224; else if (West == West::None) return 13228; else if (West == West::Low) return 13229; else return 13230; else if (Up) if (West == West::None) return 13234; else if (West == West::Low) return 13235; else return 13236; else if (West == West::None) return 13240; else if (West == West::Low) return 13241; else return 13242; else if (East == East::Low) if (North == North::None) if (South == South::None) if (Up) if (West == West::None) return 13246; else if (West == West::Low) return 13247; else return 13248; else if (West == West::None) return 13252; else if (West == West::Low) return 13253; else return 13254; else if (South == South::Low) if (Up) if (West == West::None) return 13258; else if (West == West::Low) return 13259; else return 13260; else if (West == West::None) return 13264; else if (West == West::Low) return 13265; else return 13266; else if (Up) if (West == West::None) return 13270; else if (West == West::Low) return 13271; else return 13272; else if (West == West::None) return 13276; else if (West == West::Low) return 13277; else return 13278; else if (North == North::Low) if (South == South::None) if (Up) if (West == West::None) return 13282; else if (West == West::Low) return 13283; else return 13284; else if (West == West::None) return 13288; else if (West == West::Low) return 13289; else return 13290; else if (South == South::Low) if (Up) if (West == West::None) return 13294; else if (West == West::Low) return 13295; else return 13296; else if (West == West::None) return 13300; else if (West == West::Low) return 13301; else return 13302; else if (Up) if (West == West::None) return 13306; else if (West == West::Low) return 13307; else return 13308; else if (West == West::None) return 13312; else if (West == West::Low) return 13313; else return 13314; else if (South == South::None) if (Up) if (West == West::None) return 13318; else if (West == West::Low) return 13319; else return 13320; else if (West == West::None) return 13324; else if (West == West::Low) return 13325; else return 13326; else if (South == South::Low) if (Up) if (West == West::None) return 13330; else if (West == West::Low) return 13331; else return 13332; else if (West == West::None) return 13336; else if (West == West::Low) return 13337; else return 13338; else if (Up) if (West == West::None) return 13342; else if (West == West::Low) return 13343; else return 13344; else if (West == West::None) return 13348; else if (West == West::Low) return 13349; else return 13350; else if (North == North::None) if (South == South::None) if (Up) if (West == West::None) return 13354; else if (West == West::Low) return 13355; else return 13356; else if (West == West::None) return 13360; else if (West == West::Low) return 13361; else return 13362; else if (South == South::Low) if (Up) if (West == West::None) return 13366; else if (West == West::Low) return 13367; else return 13368; else if (West == West::None) return 13372; else if (West == West::Low) return 13373; else return 13374; else if (Up) if (West == West::None) return 13378; else if (West == West::Low) return 13379; else return 13380; else if (West == West::None) return 13384; else if (West == West::Low) return 13385; else return 13386; else if (North == North::Low) if (South == South::None) if (Up) if (West == West::None) return 13390; else if (West == West::Low) return 13391; else return 13392; else if (West == West::None) return 13396; else if (West == West::Low) return 13397; else return 13398; else if (South == South::Low) if (Up) if (West == West::None) return 13402; else if (West == West::Low) return 13403; else return 13404; else if (West == West::None) return 13408; else if (West == West::Low) return 13409; else return 13410; else if (Up) if (West == West::None) return 13414; else if (West == West::Low) return 13415; else return 13416; else if (West == West::None) return 13420; else if (West == West::Low) return 13421; else return 13422; else if (South == South::None) if (Up) if (West == West::None) return 13426; else if (West == West::Low) return 13427; else return 13428; else if (West == West::None) return 13432; else if (West == West::Low) return 13433; else return 13434; else if (South == South::Low) if (Up) if (West == West::None) return 13438; else if (West == West::Low) return 13439; else return 13440; else if (West == West::None) return 13444; else if (West == West::Low) return 13445; else return 13446; else if (Up) if (West == West::None) return 13450; else if (West == West::Low) return 13451; else return 13452; else if (West == West::None) return 13456; else if (West == West::Low) return 13457; else return 13458; } BlockState AndesiteWall(); enum East East(BlockState Block); enum North North(BlockState Block); enum South South(BlockState Block); bool Up(BlockState Block); enum West West(BlockState Block); } namespace Anvil { constexpr BlockState Anvil(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 6610; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 6611; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 6612; else return 6613; } BlockState Anvil(); eBlockFace Facing(BlockState Block); } namespace AttachedMelonStem { constexpr BlockState AttachedMelonStem(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 4768; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 4769; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 4770; else return 4771; } BlockState AttachedMelonStem(); eBlockFace Facing(BlockState Block); } namespace AttachedPumpkinStem { constexpr BlockState AttachedPumpkinStem(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 4764; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 4765; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 4766; else return 4767; } BlockState AttachedPumpkinStem(); eBlockFace Facing(BlockState Block); } namespace AzureBluet { constexpr BlockState AzureBluet() { return 1416; } } namespace Bamboo { enum class Leaves { None, Small, Large }; constexpr BlockState Bamboo(const unsigned char Age, const enum Leaves Leaves, const unsigned char Stage) { if (Age == 0) if (Leaves == Leaves::None) if (Stage == 0) return 9652; else return 9653; else if (Leaves == Leaves::Small) if (Stage == 0) return 9654; else return 9655; else if (Stage == 0) return 9656; else return 9657; else if (Leaves == Leaves::None) if (Stage == 0) return 9658; else return 9659; else if (Leaves == Leaves::Small) if (Stage == 0) return 9660; else return 9661; else if (Stage == 0) return 9662; else return 9663; } BlockState Bamboo(); unsigned char Age(BlockState Block); enum Leaves Leaves(BlockState Block); unsigned char Stage(BlockState Block); } namespace BambooSapling { constexpr BlockState BambooSapling() { return 9651; } } namespace Barrel { constexpr BlockState Barrel(const eBlockFace Facing, const bool Open) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Open) return 14791; else return 14792; else if (Facing == eBlockFace::BLOCK_FACE_XP) if (Open) return 14793; else return 14794; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Open) return 14795; else return 14796; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Open) return 14797; else return 14798; else if (Facing == eBlockFace::BLOCK_FACE_YP) if (Open) return 14799; else return 14800; else if (Open) return 14801; else return 14802; } BlockState Barrel(); eBlockFace Facing(BlockState Block); bool Open(BlockState Block); } namespace Barrier { constexpr BlockState Barrier() { return 7536; } } namespace Basalt { enum class Axis { X, Y, Z }; constexpr BlockState Basalt(const enum Axis Axis) { if (Axis == Axis::X) return 4002; else if (Axis == Axis::Y) return 4003; else return 4004; } BlockState Basalt(); enum Axis Axis(BlockState Block); } namespace Beacon { constexpr BlockState Beacon() { return 5656; } } namespace Bedrock { constexpr BlockState Bedrock() { return 33; } } namespace BeeNest { constexpr BlockState BeeNest(const eBlockFace Facing, const unsigned char HoneyLevel) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (HoneyLevel == 0) return 15776; else if (HoneyLevel == 1) return 15777; else if (HoneyLevel == 2) return 15778; else if (HoneyLevel == 3) return 15779; else if (HoneyLevel == 4) return 15780; else return 15781; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (HoneyLevel == 0) return 15782; else if (HoneyLevel == 1) return 15783; else if (HoneyLevel == 2) return 15784; else if (HoneyLevel == 3) return 15785; else if (HoneyLevel == 4) return 15786; else return 15787; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (HoneyLevel == 0) return 15788; else if (HoneyLevel == 1) return 15789; else if (HoneyLevel == 2) return 15790; else if (HoneyLevel == 3) return 15791; else if (HoneyLevel == 4) return 15792; else return 15793; else if (HoneyLevel == 0) return 15794; else if (HoneyLevel == 1) return 15795; else if (HoneyLevel == 2) return 15796; else if (HoneyLevel == 3) return 15797; else if (HoneyLevel == 4) return 15798; else return 15799; } BlockState BeeNest(); eBlockFace Facing(BlockState Block); unsigned char HoneyLevel(BlockState Block); } namespace Beehive { constexpr BlockState Beehive(const eBlockFace Facing, const unsigned char HoneyLevel) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (HoneyLevel == 0) return 15800; else if (HoneyLevel == 1) return 15801; else if (HoneyLevel == 2) return 15802; else if (HoneyLevel == 3) return 15803; else if (HoneyLevel == 4) return 15804; else return 15805; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (HoneyLevel == 0) return 15806; else if (HoneyLevel == 1) return 15807; else if (HoneyLevel == 2) return 15808; else if (HoneyLevel == 3) return 15809; else if (HoneyLevel == 4) return 15810; else return 15811; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (HoneyLevel == 0) return 15812; else if (HoneyLevel == 1) return 15813; else if (HoneyLevel == 2) return 15814; else if (HoneyLevel == 3) return 15815; else if (HoneyLevel == 4) return 15816; else return 15817; else if (HoneyLevel == 0) return 15818; else if (HoneyLevel == 1) return 15819; else if (HoneyLevel == 2) return 15820; else if (HoneyLevel == 3) return 15821; else if (HoneyLevel == 4) return 15822; else return 15823; } BlockState Beehive(); eBlockFace Facing(BlockState Block); unsigned char HoneyLevel(BlockState Block); } namespace Beetroots { constexpr BlockState Beetroots(const unsigned char Age) { if (Age == 0) return 9219; else if (Age == 1) return 9220; else if (Age == 2) return 9221; else return 9222; } BlockState Beetroots(); unsigned char Age(BlockState Block); } namespace Bell { enum class Attachment { Floor, Ceiling, SingleWall, DoubleWall }; constexpr BlockState Bell(const enum Attachment Attachment, const eBlockFace Facing, const bool Powered) { if (Attachment == Attachment::Floor) if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Powered) return 14854; else return 14855; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Powered) return 14856; else return 14857; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Powered) return 14858; else return 14859; else if (Powered) return 14860; else return 14861; else if (Attachment == Attachment::Ceiling) if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Powered) return 14862; else return 14863; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Powered) return 14864; else return 14865; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Powered) return 14866; else return 14867; else if (Powered) return 14868; else return 14869; else if (Attachment == Attachment::SingleWall) if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Powered) return 14870; else return 14871; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Powered) return 14872; else return 14873; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Powered) return 14874; else return 14875; else if (Powered) return 14876; else return 14877; else if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Powered) return 14878; else return 14879; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Powered) return 14880; else return 14881; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Powered) return 14882; else return 14883; else if (Powered) return 14884; else return 14885; } BlockState Bell(); enum Attachment Attachment(BlockState Block); eBlockFace Facing(BlockState Block); bool Powered(BlockState Block); } namespace BirchButton { enum class Face { Floor, Wall, Ceiling }; constexpr BlockState BirchButton(const enum Face Face, const eBlockFace Facing, const bool Powered) { if (Face == Face::Floor) if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Powered) return 6394; else return 6395; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Powered) return 6396; else return 6397; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Powered) return 6398; else return 6399; else if (Powered) return 6400; else return 6401; else if (Face == Face::Wall) if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Powered) return 6402; else return 6403; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Powered) return 6404; else return 6405; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Powered) return 6406; else return 6407; else if (Powered) return 6408; else return 6409; else if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Powered) return 6410; else return 6411; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Powered) return 6412; else return 6413; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Powered) return 6414; else return 6415; else if (Powered) return 6416; else return 6417; } BlockState BirchButton(); enum Face Face(BlockState Block); eBlockFace Facing(BlockState Block); bool Powered(BlockState Block); } namespace BirchDoor { enum class Half { Upper, Lower }; enum class Hinge { Left, Right }; constexpr BlockState BirchDoor(const eBlockFace Facing, const enum Half Half, const enum Hinge Hinge, const bool Open, const bool Powered) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Half == Half::Upper) if (Hinge == Hinge::Left) if (Open) if (Powered) return 8802; else return 8803; else if (Powered) return 8804; else return 8805; else if (Open) if (Powered) return 8806; else return 8807; else if (Powered) return 8808; else return 8809; else if (Hinge == Hinge::Left) if (Open) if (Powered) return 8810; else return 8811; else if (Powered) return 8812; else return 8813; else if (Open) if (Powered) return 8814; else return 8815; else if (Powered) return 8816; else return 8817; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Half == Half::Upper) if (Hinge == Hinge::Left) if (Open) if (Powered) return 8818; else return 8819; else if (Powered) return 8820; else return 8821; else if (Open) if (Powered) return 8822; else return 8823; else if (Powered) return 8824; else return 8825; else if (Hinge == Hinge::Left) if (Open) if (Powered) return 8826; else return 8827; else if (Powered) return 8828; else return 8829; else if (Open) if (Powered) return 8830; else return 8831; else if (Powered) return 8832; else return 8833; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Half == Half::Upper) if (Hinge == Hinge::Left) if (Open) if (Powered) return 8834; else return 8835; else if (Powered) return 8836; else return 8837; else if (Open) if (Powered) return 8838; else return 8839; else if (Powered) return 8840; else return 8841; else if (Hinge == Hinge::Left) if (Open) if (Powered) return 8842; else return 8843; else if (Powered) return 8844; else return 8845; else if (Open) if (Powered) return 8846; else return 8847; else if (Powered) return 8848; else return 8849; else if (Half == Half::Upper) if (Hinge == Hinge::Left) if (Open) if (Powered) return 8850; else return 8851; else if (Powered) return 8852; else return 8853; else if (Open) if (Powered) return 8854; else return 8855; else if (Powered) return 8856; else return 8857; else if (Hinge == Hinge::Left) if (Open) if (Powered) return 8858; else return 8859; else if (Powered) return 8860; else return 8861; else if (Open) if (Powered) return 8862; else return 8863; else if (Powered) return 8864; else return 8865; } BlockState BirchDoor(); eBlockFace Facing(BlockState Block); enum Half Half(BlockState Block); enum Hinge Hinge(BlockState Block); bool Open(BlockState Block); bool Powered(BlockState Block); } namespace BirchFence { constexpr BlockState BirchFence(const bool East, const bool North, const bool South, const bool West) { if (East) if (North) if (South) if (West) return 8612; else return 8613; else if (West) return 8616; else return 8617; else if (South) if (West) return 8620; else return 8621; else if (West) return 8624; else return 8625; else if (North) if (South) if (West) return 8628; else return 8629; else if (West) return 8632; else return 8633; else if (South) if (West) return 8636; else return 8637; else if (West) return 8640; else return 8641; } BlockState BirchFence(); bool East(BlockState Block); bool North(BlockState Block); bool South(BlockState Block); bool West(BlockState Block); } namespace BirchFenceGate { constexpr BlockState BirchFenceGate(const eBlockFace Facing, const bool InWall, const bool Open, const bool Powered) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (InWall) if (Open) if (Powered) return 8450; else return 8451; else if (Powered) return 8452; else return 8453; else if (Open) if (Powered) return 8454; else return 8455; else if (Powered) return 8456; else return 8457; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (InWall) if (Open) if (Powered) return 8458; else return 8459; else if (Powered) return 8460; else return 8461; else if (Open) if (Powered) return 8462; else return 8463; else if (Powered) return 8464; else return 8465; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (InWall) if (Open) if (Powered) return 8466; else return 8467; else if (Powered) return 8468; else return 8469; else if (Open) if (Powered) return 8470; else return 8471; else if (Powered) return 8472; else return 8473; else if (InWall) if (Open) if (Powered) return 8474; else return 8475; else if (Powered) return 8476; else return 8477; else if (Open) if (Powered) return 8478; else return 8479; else if (Powered) return 8480; else return 8481; } BlockState BirchFenceGate(); eBlockFace Facing(BlockState Block); bool InWall(BlockState Block); bool Open(BlockState Block); bool Powered(BlockState Block); } namespace BirchLeaves { constexpr BlockState BirchLeaves(const unsigned char Distance, const bool Persistent) { if (Distance == 1) if (Persistent) return 173; else return 174; else if (Distance == 2) if (Persistent) return 175; else return 176; else if (Distance == 3) if (Persistent) return 177; else return 178; else if (Distance == 4) if (Persistent) return 179; else return 180; else if (Distance == 5) if (Persistent) return 181; else return 182; else if (Distance == 6) if (Persistent) return 183; else return 184; else if (Persistent) return 185; else return 186; } BlockState BirchLeaves(); unsigned char Distance(BlockState Block); bool Persistent(BlockState Block); } namespace BirchLog { enum class Axis { X, Y, Z }; constexpr BlockState BirchLog(const enum Axis Axis) { if (Axis == Axis::X) return 79; else if (Axis == Axis::Y) return 80; else return 81; } BlockState BirchLog(); enum Axis Axis(BlockState Block); } namespace BirchPlanks { constexpr BlockState BirchPlanks() { return 17; } } namespace BirchPressurePlate { constexpr BlockState BirchPressurePlate(const bool Powered) { if (Powered) return 3877; else return 3878; } BlockState BirchPressurePlate(); bool Powered(BlockState Block); } namespace BirchSapling { constexpr BlockState BirchSapling(const unsigned char Stage) { if (Stage == 0) return 25; else return 26; } BlockState BirchSapling(); unsigned char Stage(BlockState Block); } namespace BirchSign { constexpr BlockState BirchSign(const unsigned char Rotation) { if (Rotation == 0) return 3446; else if (Rotation == 1) return 3448; else if (Rotation == 2) return 3450; else if (Rotation == 3) return 3452; else if (Rotation == 4) return 3454; else if (Rotation == 5) return 3456; else if (Rotation == 6) return 3458; else if (Rotation == 7) return 3460; else if (Rotation == 8) return 3462; else if (Rotation == 9) return 3464; else if (Rotation == 10) return 3466; else if (Rotation == 11) return 3468; else if (Rotation == 12) return 3470; else if (Rotation == 13) return 3472; else if (Rotation == 14) return 3474; else return 3476; } BlockState BirchSign(); unsigned char Rotation(BlockState Block); } namespace BirchSlab { enum class Type { Top, Bottom, Double }; constexpr BlockState BirchSlab(const enum Type Type) { if (Type == Type::Top) return 8313; else if (Type == Type::Bottom) return 8315; else return 8317; } BlockState BirchSlab(); enum Type Type(BlockState Block); } namespace BirchStairs { enum class Half { Top, Bottom }; enum class Shape { Straight, InnerLeft, InnerRight, OuterLeft, OuterRight }; constexpr BlockState BirchStairs(const eBlockFace Facing, const enum Half Half, const enum Shape Shape) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Half == Half::Top) if (Shape == Shape::Straight) return 5485; else if (Shape == Shape::InnerLeft) return 5487; else if (Shape == Shape::InnerRight) return 5489; else if (Shape == Shape::OuterLeft) return 5491; else return 5493; else if (Shape == Shape::Straight) return 5495; else if (Shape == Shape::InnerLeft) return 5497; else if (Shape == Shape::InnerRight) return 5499; else if (Shape == Shape::OuterLeft) return 5501; else return 5503; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Half == Half::Top) if (Shape == Shape::Straight) return 5505; else if (Shape == Shape::InnerLeft) return 5507; else if (Shape == Shape::InnerRight) return 5509; else if (Shape == Shape::OuterLeft) return 5511; else return 5513; else if (Shape == Shape::Straight) return 5515; else if (Shape == Shape::InnerLeft) return 5517; else if (Shape == Shape::InnerRight) return 5519; else if (Shape == Shape::OuterLeft) return 5521; else return 5523; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Half == Half::Top) if (Shape == Shape::Straight) return 5525; else if (Shape == Shape::InnerLeft) return 5527; else if (Shape == Shape::InnerRight) return 5529; else if (Shape == Shape::OuterLeft) return 5531; else return 5533; else if (Shape == Shape::Straight) return 5535; else if (Shape == Shape::InnerLeft) return 5537; else if (Shape == Shape::InnerRight) return 5539; else if (Shape == Shape::OuterLeft) return 5541; else return 5543; else if (Half == Half::Top) if (Shape == Shape::Straight) return 5545; else if (Shape == Shape::InnerLeft) return 5547; else if (Shape == Shape::InnerRight) return 5549; else if (Shape == Shape::OuterLeft) return 5551; else return 5553; else if (Shape == Shape::Straight) return 5555; else if (Shape == Shape::InnerLeft) return 5557; else if (Shape == Shape::InnerRight) return 5559; else if (Shape == Shape::OuterLeft) return 5561; else return 5563; } BlockState BirchStairs(); eBlockFace Facing(BlockState Block); enum Half Half(BlockState Block); enum Shape Shape(BlockState Block); } namespace BirchTrapdoor { enum class Half { Top, Bottom }; constexpr BlockState BirchTrapdoor(const eBlockFace Facing, const enum Half Half, const bool Open, const bool Powered) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Half == Half::Top) if (Open) if (Powered) return 4240; else return 4242; else if (Powered) return 4244; else return 4246; else if (Open) if (Powered) return 4248; else return 4250; else if (Powered) return 4252; else return 4254; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Half == Half::Top) if (Open) if (Powered) return 4256; else return 4258; else if (Powered) return 4260; else return 4262; else if (Open) if (Powered) return 4264; else return 4266; else if (Powered) return 4268; else return 4270; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Half == Half::Top) if (Open) if (Powered) return 4272; else return 4274; else if (Powered) return 4276; else return 4278; else if (Open) if (Powered) return 4280; else return 4282; else if (Powered) return 4284; else return 4286; else if (Half == Half::Top) if (Open) if (Powered) return 4288; else return 4290; else if (Powered) return 4292; else return 4294; else if (Open) if (Powered) return 4296; else return 4298; else if (Powered) return 4300; else return 4302; } BlockState BirchTrapdoor(); eBlockFace Facing(BlockState Block); enum Half Half(BlockState Block); bool Open(BlockState Block); bool Powered(BlockState Block); } namespace BirchWallSign { constexpr BlockState BirchWallSign(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 3752; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 3754; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 3756; else return 3758; } BlockState BirchWallSign(); eBlockFace Facing(BlockState Block); } namespace BirchWood { enum class Axis { X, Y, Z }; constexpr BlockState BirchWood(const enum Axis Axis) { if (Axis == Axis::X) return 115; else if (Axis == Axis::Y) return 116; else return 117; } BlockState BirchWood(); enum Axis Axis(BlockState Block); } namespace BlackBanner { constexpr BlockState BlackBanner(const unsigned char Rotation) { if (Rotation == 0) return 8137; else if (Rotation == 1) return 8138; else if (Rotation == 2) return 8139; else if (Rotation == 3) return 8140; else if (Rotation == 4) return 8141; else if (Rotation == 5) return 8142; else if (Rotation == 6) return 8143; else if (Rotation == 7) return 8144; else if (Rotation == 8) return 8145; else if (Rotation == 9) return 8146; else if (Rotation == 10) return 8147; else if (Rotation == 11) return 8148; else if (Rotation == 12) return 8149; else if (Rotation == 13) return 8150; else if (Rotation == 14) return 8151; else return 8152; } BlockState BlackBanner(); unsigned char Rotation(BlockState Block); } namespace BlackBed { enum class Part { Head, Foot }; constexpr BlockState BlackBed(const eBlockFace Facing, const bool Occupied, const enum Part Part) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Occupied) if (Part == Part::Head) return 1289; else return 1290; else if (Part == Part::Head) return 1291; else return 1292; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Occupied) if (Part == Part::Head) return 1293; else return 1294; else if (Part == Part::Head) return 1295; else return 1296; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Occupied) if (Part == Part::Head) return 1297; else return 1298; else if (Part == Part::Head) return 1299; else return 1300; else if (Occupied) if (Part == Part::Head) return 1301; else return 1302; else if (Part == Part::Head) return 1303; else return 1304; } BlockState BlackBed(); eBlockFace Facing(BlockState Block); bool Occupied(BlockState Block); enum Part Part(BlockState Block); } namespace BlackCarpet { constexpr BlockState BlackCarpet() { return 7881; } } namespace BlackConcrete { constexpr BlockState BlackConcrete() { return 9453; } } namespace BlackConcretePowder { constexpr BlockState BlackConcretePowder() { return 9469; } } namespace BlackGlazedTerracotta { constexpr BlockState BlackGlazedTerracotta(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 9434; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 9435; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 9436; else return 9437; } BlockState BlackGlazedTerracotta(); eBlockFace Facing(BlockState Block); } namespace BlackShulkerBox { constexpr BlockState BlackShulkerBox(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 9368; else if (Facing == eBlockFace::BLOCK_FACE_XP) return 9369; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 9370; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 9371; else if (Facing == eBlockFace::BLOCK_FACE_YP) return 9372; else return 9373; } BlockState BlackShulkerBox(); eBlockFace Facing(BlockState Block); } namespace BlackStainedGlass { constexpr BlockState BlackStainedGlass() { return 4110; } } namespace BlackStainedGlassPane { constexpr BlockState BlackStainedGlassPane(const bool East, const bool North, const bool South, const bool West) { if (East) if (North) if (South) if (West) return 7345; else return 7346; else if (West) return 7349; else return 7350; else if (South) if (West) return 7353; else return 7354; else if (West) return 7357; else return 7358; else if (North) if (South) if (West) return 7361; else return 7362; else if (West) return 7365; else return 7366; else if (South) if (West) return 7369; else return 7370; else if (West) return 7373; else return 7374; } BlockState BlackStainedGlassPane(); bool East(BlockState Block); bool North(BlockState Block); bool South(BlockState Block); bool West(BlockState Block); } namespace BlackTerracotta { constexpr BlockState BlackTerracotta() { return 6862; } } namespace BlackWallBanner { constexpr BlockState BlackWallBanner(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 8213; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 8214; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 8215; else return 8216; } BlockState BlackWallBanner(); eBlockFace Facing(BlockState Block); } namespace BlackWool { constexpr BlockState BlackWool() { return 1399; } } namespace Blackstone { constexpr BlockState Blackstone() { return 15839; } } namespace BlackstoneSlab { enum class Type { Top, Bottom, Double }; constexpr BlockState BlackstoneSlab(const enum Type Type) { if (Type == Type::Top) return 16245; else if (Type == Type::Bottom) return 16247; else return 16249; } BlockState BlackstoneSlab(); enum Type Type(BlockState Block); } namespace BlackstoneStairs { enum class Half { Top, Bottom }; enum class Shape { Straight, InnerLeft, InnerRight, OuterLeft, OuterRight }; constexpr BlockState BlackstoneStairs(const eBlockFace Facing, const enum Half Half, const enum Shape Shape) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Half == Half::Top) if (Shape == Shape::Straight) return 15841; else if (Shape == Shape::InnerLeft) return 15843; else if (Shape == Shape::InnerRight) return 15845; else if (Shape == Shape::OuterLeft) return 15847; else return 15849; else if (Shape == Shape::Straight) return 15851; else if (Shape == Shape::InnerLeft) return 15853; else if (Shape == Shape::InnerRight) return 15855; else if (Shape == Shape::OuterLeft) return 15857; else return 15859; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Half == Half::Top) if (Shape == Shape::Straight) return 15861; else if (Shape == Shape::InnerLeft) return 15863; else if (Shape == Shape::InnerRight) return 15865; else if (Shape == Shape::OuterLeft) return 15867; else return 15869; else if (Shape == Shape::Straight) return 15871; else if (Shape == Shape::InnerLeft) return 15873; else if (Shape == Shape::InnerRight) return 15875; else if (Shape == Shape::OuterLeft) return 15877; else return 15879; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Half == Half::Top) if (Shape == Shape::Straight) return 15881; else if (Shape == Shape::InnerLeft) return 15883; else if (Shape == Shape::InnerRight) return 15885; else if (Shape == Shape::OuterLeft) return 15887; else return 15889; else if (Shape == Shape::Straight) return 15891; else if (Shape == Shape::InnerLeft) return 15893; else if (Shape == Shape::InnerRight) return 15895; else if (Shape == Shape::OuterLeft) return 15897; else return 15899; else if (Half == Half::Top) if (Shape == Shape::Straight) return 15901; else if (Shape == Shape::InnerLeft) return 15903; else if (Shape == Shape::InnerRight) return 15905; else if (Shape == Shape::OuterLeft) return 15907; else return 15909; else if (Shape == Shape::Straight) return 15911; else if (Shape == Shape::InnerLeft) return 15913; else if (Shape == Shape::InnerRight) return 15915; else if (Shape == Shape::OuterLeft) return 15917; else return 15919; } BlockState BlackstoneStairs(); eBlockFace Facing(BlockState Block); enum Half Half(BlockState Block); enum Shape Shape(BlockState Block); } namespace BlackstoneWall { enum class East { None, Low, Tall }; enum class North { None, Low, Tall }; enum class South { None, Low, Tall }; enum class West { None, Low, Tall }; constexpr BlockState BlackstoneWall(const enum East East, const enum North North, const enum South South, const bool Up, const enum West West) { if (East == East::None) if (North == North::None) if (South == South::None) if (Up) if (West == West::None) return 15923; else if (West == West::Low) return 15924; else return 15925; else if (West == West::None) return 15929; else if (West == West::Low) return 15930; else return 15931; else if (South == South::Low) if (Up) if (West == West::None) return 15935; else if (West == West::Low) return 15936; else return 15937; else if (West == West::None) return 15941; else if (West == West::Low) return 15942; else return 15943; else if (Up) if (West == West::None) return 15947; else if (West == West::Low) return 15948; else return 15949; else if (West == West::None) return 15953; else if (West == West::Low) return 15954; else return 15955; else if (North == North::Low) if (South == South::None) if (Up) if (West == West::None) return 15959; else if (West == West::Low) return 15960; else return 15961; else if (West == West::None) return 15965; else if (West == West::Low) return 15966; else return 15967; else if (South == South::Low) if (Up) if (West == West::None) return 15971; else if (West == West::Low) return 15972; else return 15973; else if (West == West::None) return 15977; else if (West == West::Low) return 15978; else return 15979; else if (Up) if (West == West::None) return 15983; else if (West == West::Low) return 15984; else return 15985; else if (West == West::None) return 15989; else if (West == West::Low) return 15990; else return 15991; else if (South == South::None) if (Up) if (West == West::None) return 15995; else if (West == West::Low) return 15996; else return 15997; else if (West == West::None) return 16001; else if (West == West::Low) return 16002; else return 16003; else if (South == South::Low) if (Up) if (West == West::None) return 16007; else if (West == West::Low) return 16008; else return 16009; else if (West == West::None) return 16013; else if (West == West::Low) return 16014; else return 16015; else if (Up) if (West == West::None) return 16019; else if (West == West::Low) return 16020; else return 16021; else if (West == West::None) return 16025; else if (West == West::Low) return 16026; else return 16027; else if (East == East::Low) if (North == North::None) if (South == South::None) if (Up) if (West == West::None) return 16031; else if (West == West::Low) return 16032; else return 16033; else if (West == West::None) return 16037; else if (West == West::Low) return 16038; else return 16039; else if (South == South::Low) if (Up) if (West == West::None) return 16043; else if (West == West::Low) return 16044; else return 16045; else if (West == West::None) return 16049; else if (West == West::Low) return 16050; else return 16051; else if (Up) if (West == West::None) return 16055; else if (West == West::Low) return 16056; else return 16057; else if (West == West::None) return 16061; else if (West == West::Low) return 16062; else return 16063; else if (North == North::Low) if (South == South::None) if (Up) if (West == West::None) return 16067; else if (West == West::Low) return 16068; else return 16069; else if (West == West::None) return 16073; else if (West == West::Low) return 16074; else return 16075; else if (South == South::Low) if (Up) if (West == West::None) return 16079; else if (West == West::Low) return 16080; else return 16081; else if (West == West::None) return 16085; else if (West == West::Low) return 16086; else return 16087; else if (Up) if (West == West::None) return 16091; else if (West == West::Low) return 16092; else return 16093; else if (West == West::None) return 16097; else if (West == West::Low) return 16098; else return 16099; else if (South == South::None) if (Up) if (West == West::None) return 16103; else if (West == West::Low) return 16104; else return 16105; else if (West == West::None) return 16109; else if (West == West::Low) return 16110; else return 16111; else if (South == South::Low) if (Up) if (West == West::None) return 16115; else if (West == West::Low) return 16116; else return 16117; else if (West == West::None) return 16121; else if (West == West::Low) return 16122; else return 16123; else if (Up) if (West == West::None) return 16127; else if (West == West::Low) return 16128; else return 16129; else if (West == West::None) return 16133; else if (West == West::Low) return 16134; else return 16135; else if (North == North::None) if (South == South::None) if (Up) if (West == West::None) return 16139; else if (West == West::Low) return 16140; else return 16141; else if (West == West::None) return 16145; else if (West == West::Low) return 16146; else return 16147; else if (South == South::Low) if (Up) if (West == West::None) return 16151; else if (West == West::Low) return 16152; else return 16153; else if (West == West::None) return 16157; else if (West == West::Low) return 16158; else return 16159; else if (Up) if (West == West::None) return 16163; else if (West == West::Low) return 16164; else return 16165; else if (West == West::None) return 16169; else if (West == West::Low) return 16170; else return 16171; else if (North == North::Low) if (South == South::None) if (Up) if (West == West::None) return 16175; else if (West == West::Low) return 16176; else return 16177; else if (West == West::None) return 16181; else if (West == West::Low) return 16182; else return 16183; else if (South == South::Low) if (Up) if (West == West::None) return 16187; else if (West == West::Low) return 16188; else return 16189; else if (West == West::None) return 16193; else if (West == West::Low) return 16194; else return 16195; else if (Up) if (West == West::None) return 16199; else if (West == West::Low) return 16200; else return 16201; else if (West == West::None) return 16205; else if (West == West::Low) return 16206; else return 16207; else if (South == South::None) if (Up) if (West == West::None) return 16211; else if (West == West::Low) return 16212; else return 16213; else if (West == West::None) return 16217; else if (West == West::Low) return 16218; else return 16219; else if (South == South::Low) if (Up) if (West == West::None) return 16223; else if (West == West::Low) return 16224; else return 16225; else if (West == West::None) return 16229; else if (West == West::Low) return 16230; else return 16231; else if (Up) if (West == West::None) return 16235; else if (West == West::Low) return 16236; else return 16237; else if (West == West::None) return 16241; else if (West == West::Low) return 16242; else return 16243; } BlockState BlackstoneWall(); enum East East(BlockState Block); enum North North(BlockState Block); enum South South(BlockState Block); bool Up(BlockState Block); enum West West(BlockState Block); } namespace BlastFurnace { constexpr BlockState BlastFurnace(const eBlockFace Facing, const bool Lit) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Lit) return 14811; else return 14812; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Lit) return 14813; else return 14814; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Lit) return 14815; else return 14816; else if (Lit) return 14817; else return 14818; } BlockState BlastFurnace(); eBlockFace Facing(BlockState Block); bool Lit(BlockState Block); } namespace BlueBanner { constexpr BlockState BlueBanner(const unsigned char Rotation) { if (Rotation == 0) return 8073; else if (Rotation == 1) return 8074; else if (Rotation == 2) return 8075; else if (Rotation == 3) return 8076; else if (Rotation == 4) return 8077; else if (Rotation == 5) return 8078; else if (Rotation == 6) return 8079; else if (Rotation == 7) return 8080; else if (Rotation == 8) return 8081; else if (Rotation == 9) return 8082; else if (Rotation == 10) return 8083; else if (Rotation == 11) return 8084; else if (Rotation == 12) return 8085; else if (Rotation == 13) return 8086; else if (Rotation == 14) return 8087; else return 8088; } BlockState BlueBanner(); unsigned char Rotation(BlockState Block); } namespace BlueBed { enum class Part { Head, Foot }; constexpr BlockState BlueBed(const eBlockFace Facing, const bool Occupied, const enum Part Part) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Occupied) if (Part == Part::Head) return 1225; else return 1226; else if (Part == Part::Head) return 1227; else return 1228; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Occupied) if (Part == Part::Head) return 1229; else return 1230; else if (Part == Part::Head) return 1231; else return 1232; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Occupied) if (Part == Part::Head) return 1233; else return 1234; else if (Part == Part::Head) return 1235; else return 1236; else if (Occupied) if (Part == Part::Head) return 1237; else return 1238; else if (Part == Part::Head) return 1239; else return 1240; } BlockState BlueBed(); eBlockFace Facing(BlockState Block); bool Occupied(BlockState Block); enum Part Part(BlockState Block); } namespace BlueCarpet { constexpr BlockState BlueCarpet() { return 7877; } } namespace BlueConcrete { constexpr BlockState BlueConcrete() { return 9449; } } namespace BlueConcretePowder { constexpr BlockState BlueConcretePowder() { return 9465; } } namespace BlueGlazedTerracotta { constexpr BlockState BlueGlazedTerracotta(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 9418; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 9419; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 9420; else return 9421; } BlockState BlueGlazedTerracotta(); eBlockFace Facing(BlockState Block); } namespace BlueIce { constexpr BlockState BlueIce() { return 9648; } } namespace BlueOrchid { constexpr BlockState BlueOrchid() { return 1414; } } namespace BlueShulkerBox { constexpr BlockState BlueShulkerBox(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 9344; else if (Facing == eBlockFace::BLOCK_FACE_XP) return 9345; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 9346; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 9347; else if (Facing == eBlockFace::BLOCK_FACE_YP) return 9348; else return 9349; } BlockState BlueShulkerBox(); eBlockFace Facing(BlockState Block); } namespace BlueStainedGlass { constexpr BlockState BlueStainedGlass() { return 4106; } } namespace BlueStainedGlassPane { constexpr BlockState BlueStainedGlassPane(const bool East, const bool North, const bool South, const bool West) { if (East) if (North) if (South) if (West) return 7217; else return 7218; else if (West) return 7221; else return 7222; else if (South) if (West) return 7225; else return 7226; else if (West) return 7229; else return 7230; else if (North) if (South) if (West) return 7233; else return 7234; else if (West) return 7237; else return 7238; else if (South) if (West) return 7241; else return 7242; else if (West) return 7245; else return 7246; } BlockState BlueStainedGlassPane(); bool East(BlockState Block); bool North(BlockState Block); bool South(BlockState Block); bool West(BlockState Block); } namespace BlueTerracotta { constexpr BlockState BlueTerracotta() { return 6858; } } namespace BlueWallBanner { constexpr BlockState BlueWallBanner(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 8197; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 8198; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 8199; else return 8200; } BlockState BlueWallBanner(); eBlockFace Facing(BlockState Block); } namespace BlueWool { constexpr BlockState BlueWool() { return 1395; } } namespace BoneBlock { enum class Axis { X, Y, Z }; constexpr BlockState BoneBlock(const enum Axis Axis) { if (Axis == Axis::X) return 9256; else if (Axis == Axis::Y) return 9257; else return 9258; } BlockState BoneBlock(); enum Axis Axis(BlockState Block); } namespace Bookshelf { constexpr BlockState Bookshelf() { return 1432; } } namespace BrainCoral { constexpr BlockState BrainCoral() { return 9533; } } namespace BrainCoralBlock { constexpr BlockState BrainCoralBlock() { return 9516; } } namespace BrainCoralFan { constexpr BlockState BrainCoralFan() { return 9553; } } namespace BrainCoralWallFan { constexpr BlockState BrainCoralWallFan(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 9609; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 9611; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 9613; else return 9615; } BlockState BrainCoralWallFan(); eBlockFace Facing(BlockState Block); } namespace BrewingStand { constexpr BlockState BrewingStand(const bool HasBottle_0, const bool HasBottle_1, const bool HasBottle_2) { if (HasBottle_0) if (HasBottle_1) if (HasBottle_2) return 5133; else return 5134; else if (HasBottle_2) return 5135; else return 5136; else if (HasBottle_1) if (HasBottle_2) return 5137; else return 5138; else if (HasBottle_2) return 5139; else return 5140; } BlockState BrewingStand(); bool HasBottle_0(BlockState Block); bool HasBottle_1(BlockState Block); bool HasBottle_2(BlockState Block); } namespace BrickSlab { enum class Type { Top, Bottom, Double }; constexpr BlockState BrickSlab(const enum Type Type) { if (Type == Type::Top) return 8373; else if (Type == Type::Bottom) return 8375; else return 8377; } BlockState BrickSlab(); enum Type Type(BlockState Block); } namespace BrickStairs { enum class Half { Top, Bottom }; enum class Shape { Straight, InnerLeft, InnerRight, OuterLeft, OuterRight }; constexpr BlockState BrickStairs(const eBlockFace Facing, const enum Half Half, const enum Shape Shape) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Half == Half::Top) if (Shape == Shape::Straight) return 4853; else if (Shape == Shape::InnerLeft) return 4855; else if (Shape == Shape::InnerRight) return 4857; else if (Shape == Shape::OuterLeft) return 4859; else return 4861; else if (Shape == Shape::Straight) return 4863; else if (Shape == Shape::InnerLeft) return 4865; else if (Shape == Shape::InnerRight) return 4867; else if (Shape == Shape::OuterLeft) return 4869; else return 4871; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Half == Half::Top) if (Shape == Shape::Straight) return 4873; else if (Shape == Shape::InnerLeft) return 4875; else if (Shape == Shape::InnerRight) return 4877; else if (Shape == Shape::OuterLeft) return 4879; else return 4881; else if (Shape == Shape::Straight) return 4883; else if (Shape == Shape::InnerLeft) return 4885; else if (Shape == Shape::InnerRight) return 4887; else if (Shape == Shape::OuterLeft) return 4889; else return 4891; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Half == Half::Top) if (Shape == Shape::Straight) return 4893; else if (Shape == Shape::InnerLeft) return 4895; else if (Shape == Shape::InnerRight) return 4897; else if (Shape == Shape::OuterLeft) return 4899; else return 4901; else if (Shape == Shape::Straight) return 4903; else if (Shape == Shape::InnerLeft) return 4905; else if (Shape == Shape::InnerRight) return 4907; else if (Shape == Shape::OuterLeft) return 4909; else return 4911; else if (Half == Half::Top) if (Shape == Shape::Straight) return 4913; else if (Shape == Shape::InnerLeft) return 4915; else if (Shape == Shape::InnerRight) return 4917; else if (Shape == Shape::OuterLeft) return 4919; else return 4921; else if (Shape == Shape::Straight) return 4923; else if (Shape == Shape::InnerLeft) return 4925; else if (Shape == Shape::InnerRight) return 4927; else if (Shape == Shape::OuterLeft) return 4929; else return 4931; } BlockState BrickStairs(); eBlockFace Facing(BlockState Block); enum Half Half(BlockState Block); enum Shape Shape(BlockState Block); } namespace BrickWall { enum class East { None, Low, Tall }; enum class North { None, Low, Tall }; enum class South { None, Low, Tall }; enum class West { None, Low, Tall }; constexpr BlockState BrickWall(const enum East East, const enum North North, const enum South South, const bool Up, const enum West West) { if (East == East::None) if (North == North::None) if (South == South::None) if (Up) if (West == West::None) return 10870; else if (West == West::Low) return 10871; else return 10872; else if (West == West::None) return 10876; else if (West == West::Low) return 10877; else return 10878; else if (South == South::Low) if (Up) if (West == West::None) return 10882; else if (West == West::Low) return 10883; else return 10884; else if (West == West::None) return 10888; else if (West == West::Low) return 10889; else return 10890; else if (Up) if (West == West::None) return 10894; else if (West == West::Low) return 10895; else return 10896; else if (West == West::None) return 10900; else if (West == West::Low) return 10901; else return 10902; else if (North == North::Low) if (South == South::None) if (Up) if (West == West::None) return 10906; else if (West == West::Low) return 10907; else return 10908; else if (West == West::None) return 10912; else if (West == West::Low) return 10913; else return 10914; else if (South == South::Low) if (Up) if (West == West::None) return 10918; else if (West == West::Low) return 10919; else return 10920; else if (West == West::None) return 10924; else if (West == West::Low) return 10925; else return 10926; else if (Up) if (West == West::None) return 10930; else if (West == West::Low) return 10931; else return 10932; else if (West == West::None) return 10936; else if (West == West::Low) return 10937; else return 10938; else if (South == South::None) if (Up) if (West == West::None) return 10942; else if (West == West::Low) return 10943; else return 10944; else if (West == West::None) return 10948; else if (West == West::Low) return 10949; else return 10950; else if (South == South::Low) if (Up) if (West == West::None) return 10954; else if (West == West::Low) return 10955; else return 10956; else if (West == West::None) return 10960; else if (West == West::Low) return 10961; else return 10962; else if (Up) if (West == West::None) return 10966; else if (West == West::Low) return 10967; else return 10968; else if (West == West::None) return 10972; else if (West == West::Low) return 10973; else return 10974; else if (East == East::Low) if (North == North::None) if (South == South::None) if (Up) if (West == West::None) return 10978; else if (West == West::Low) return 10979; else return 10980; else if (West == West::None) return 10984; else if (West == West::Low) return 10985; else return 10986; else if (South == South::Low) if (Up) if (West == West::None) return 10990; else if (West == West::Low) return 10991; else return 10992; else if (West == West::None) return 10996; else if (West == West::Low) return 10997; else return 10998; else if (Up) if (West == West::None) return 11002; else if (West == West::Low) return 11003; else return 11004; else if (West == West::None) return 11008; else if (West == West::Low) return 11009; else return 11010; else if (North == North::Low) if (South == South::None) if (Up) if (West == West::None) return 11014; else if (West == West::Low) return 11015; else return 11016; else if (West == West::None) return 11020; else if (West == West::Low) return 11021; else return 11022; else if (South == South::Low) if (Up) if (West == West::None) return 11026; else if (West == West::Low) return 11027; else return 11028; else if (West == West::None) return 11032; else if (West == West::Low) return 11033; else return 11034; else if (Up) if (West == West::None) return 11038; else if (West == West::Low) return 11039; else return 11040; else if (West == West::None) return 11044; else if (West == West::Low) return 11045; else return 11046; else if (South == South::None) if (Up) if (West == West::None) return 11050; else if (West == West::Low) return 11051; else return 11052; else if (West == West::None) return 11056; else if (West == West::Low) return 11057; else return 11058; else if (South == South::Low) if (Up) if (West == West::None) return 11062; else if (West == West::Low) return 11063; else return 11064; else if (West == West::None) return 11068; else if (West == West::Low) return 11069; else return 11070; else if (Up) if (West == West::None) return 11074; else if (West == West::Low) return 11075; else return 11076; else if (West == West::None) return 11080; else if (West == West::Low) return 11081; else return 11082; else if (North == North::None) if (South == South::None) if (Up) if (West == West::None) return 11086; else if (West == West::Low) return 11087; else return 11088; else if (West == West::None) return 11092; else if (West == West::Low) return 11093; else return 11094; else if (South == South::Low) if (Up) if (West == West::None) return 11098; else if (West == West::Low) return 11099; else return 11100; else if (West == West::None) return 11104; else if (West == West::Low) return 11105; else return 11106; else if (Up) if (West == West::None) return 11110; else if (West == West::Low) return 11111; else return 11112; else if (West == West::None) return 11116; else if (West == West::Low) return 11117; else return 11118; else if (North == North::Low) if (South == South::None) if (Up) if (West == West::None) return 11122; else if (West == West::Low) return 11123; else return 11124; else if (West == West::None) return 11128; else if (West == West::Low) return 11129; else return 11130; else if (South == South::Low) if (Up) if (West == West::None) return 11134; else if (West == West::Low) return 11135; else return 11136; else if (West == West::None) return 11140; else if (West == West::Low) return 11141; else return 11142; else if (Up) if (West == West::None) return 11146; else if (West == West::Low) return 11147; else return 11148; else if (West == West::None) return 11152; else if (West == West::Low) return 11153; else return 11154; else if (South == South::None) if (Up) if (West == West::None) return 11158; else if (West == West::Low) return 11159; else return 11160; else if (West == West::None) return 11164; else if (West == West::Low) return 11165; else return 11166; else if (South == South::Low) if (Up) if (West == West::None) return 11170; else if (West == West::Low) return 11171; else return 11172; else if (West == West::None) return 11176; else if (West == West::Low) return 11177; else return 11178; else if (Up) if (West == West::None) return 11182; else if (West == West::Low) return 11183; else return 11184; else if (West == West::None) return 11188; else if (West == West::Low) return 11189; else return 11190; } BlockState BrickWall(); enum East East(BlockState Block); enum North North(BlockState Block); enum South South(BlockState Block); bool Up(BlockState Block); enum West West(BlockState Block); } namespace Bricks { constexpr BlockState Bricks() { return 1429; } } namespace BrownBanner { constexpr BlockState BrownBanner(const unsigned char Rotation) { if (Rotation == 0) return 8089; else if (Rotation == 1) return 8090; else if (Rotation == 2) return 8091; else if (Rotation == 3) return 8092; else if (Rotation == 4) return 8093; else if (Rotation == 5) return 8094; else if (Rotation == 6) return 8095; else if (Rotation == 7) return 8096; else if (Rotation == 8) return 8097; else if (Rotation == 9) return 8098; else if (Rotation == 10) return 8099; else if (Rotation == 11) return 8100; else if (Rotation == 12) return 8101; else if (Rotation == 13) return 8102; else if (Rotation == 14) return 8103; else return 8104; } BlockState BrownBanner(); unsigned char Rotation(BlockState Block); } namespace BrownBed { enum class Part { Head, Foot }; constexpr BlockState BrownBed(const eBlockFace Facing, const bool Occupied, const enum Part Part) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Occupied) if (Part == Part::Head) return 1241; else return 1242; else if (Part == Part::Head) return 1243; else return 1244; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Occupied) if (Part == Part::Head) return 1245; else return 1246; else if (Part == Part::Head) return 1247; else return 1248; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Occupied) if (Part == Part::Head) return 1249; else return 1250; else if (Part == Part::Head) return 1251; else return 1252; else if (Occupied) if (Part == Part::Head) return 1253; else return 1254; else if (Part == Part::Head) return 1255; else return 1256; } BlockState BrownBed(); eBlockFace Facing(BlockState Block); bool Occupied(BlockState Block); enum Part Part(BlockState Block); } namespace BrownCarpet { constexpr BlockState BrownCarpet() { return 7878; } } namespace BrownConcrete { constexpr BlockState BrownConcrete() { return 9450; } } namespace BrownConcretePowder { constexpr BlockState BrownConcretePowder() { return 9466; } } namespace BrownGlazedTerracotta { constexpr BlockState BrownGlazedTerracotta(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 9422; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 9423; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 9424; else return 9425; } BlockState BrownGlazedTerracotta(); eBlockFace Facing(BlockState Block); } namespace BrownMushroom { constexpr BlockState BrownMushroom() { return 1425; } } namespace BrownMushroomBlock { constexpr BlockState BrownMushroomBlock(const bool Down, const bool East, const bool North, const bool South, const bool Up, const bool West) { if (Down) if (East) if (North) if (South) if (Up) if (West) return 4505; else return 4506; else if (West) return 4507; else return 4508; else if (Up) if (West) return 4509; else return 4510; else if (West) return 4511; else return 4512; else if (South) if (Up) if (West) return 4513; else return 4514; else if (West) return 4515; else return 4516; else if (Up) if (West) return 4517; else return 4518; else if (West) return 4519; else return 4520; else if (North) if (South) if (Up) if (West) return 4521; else return 4522; else if (West) return 4523; else return 4524; else if (Up) if (West) return 4525; else return 4526; else if (West) return 4527; else return 4528; else if (South) if (Up) if (West) return 4529; else return 4530; else if (West) return 4531; else return 4532; else if (Up) if (West) return 4533; else return 4534; else if (West) return 4535; else return 4536; else if (East) if (North) if (South) if (Up) if (West) return 4537; else return 4538; else if (West) return 4539; else return 4540; else if (Up) if (West) return 4541; else return 4542; else if (West) return 4543; else return 4544; else if (South) if (Up) if (West) return 4545; else return 4546; else if (West) return 4547; else return 4548; else if (Up) if (West) return 4549; else return 4550; else if (West) return 4551; else return 4552; else if (North) if (South) if (Up) if (West) return 4553; else return 4554; else if (West) return 4555; else return 4556; else if (Up) if (West) return 4557; else return 4558; else if (West) return 4559; else return 4560; else if (South) if (Up) if (West) return 4561; else return 4562; else if (West) return 4563; else return 4564; else if (Up) if (West) return 4565; else return 4566; else if (West) return 4567; else return 4568; } BlockState BrownMushroomBlock(); bool Down(BlockState Block); bool East(BlockState Block); bool North(BlockState Block); bool South(BlockState Block); bool Up(BlockState Block); bool West(BlockState Block); } namespace BrownShulkerBox { constexpr BlockState BrownShulkerBox(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 9350; else if (Facing == eBlockFace::BLOCK_FACE_XP) return 9351; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 9352; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 9353; else if (Facing == eBlockFace::BLOCK_FACE_YP) return 9354; else return 9355; } BlockState BrownShulkerBox(); eBlockFace Facing(BlockState Block); } namespace BrownStainedGlass { constexpr BlockState BrownStainedGlass() { return 4107; } } namespace BrownStainedGlassPane { constexpr BlockState BrownStainedGlassPane(const bool East, const bool North, const bool South, const bool West) { if (East) if (North) if (South) if (West) return 7249; else return 7250; else if (West) return 7253; else return 7254; else if (South) if (West) return 7257; else return 7258; else if (West) return 7261; else return 7262; else if (North) if (South) if (West) return 7265; else return 7266; else if (West) return 7269; else return 7270; else if (South) if (West) return 7273; else return 7274; else if (West) return 7277; else return 7278; } BlockState BrownStainedGlassPane(); bool East(BlockState Block); bool North(BlockState Block); bool South(BlockState Block); bool West(BlockState Block); } namespace BrownTerracotta { constexpr BlockState BrownTerracotta() { return 6859; } } namespace BrownWallBanner { constexpr BlockState BrownWallBanner(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 8201; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 8202; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 8203; else return 8204; } BlockState BrownWallBanner(); eBlockFace Facing(BlockState Block); } namespace BrownWool { constexpr BlockState BrownWool() { return 1396; } } namespace BubbleColumn { constexpr BlockState BubbleColumn(const bool Drag) { if (Drag) return 9667; else return 9668; } BlockState BubbleColumn(); bool Drag(BlockState Block); } namespace BubbleCoral { constexpr BlockState BubbleCoral() { return 9535; } } namespace BubbleCoralBlock { constexpr BlockState BubbleCoralBlock() { return 9517; } } namespace BubbleCoralFan { constexpr BlockState BubbleCoralFan() { return 9555; } } namespace BubbleCoralWallFan { constexpr BlockState BubbleCoralWallFan(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 9617; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 9619; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 9621; else return 9623; } BlockState BubbleCoralWallFan(); eBlockFace Facing(BlockState Block); } namespace Cactus { constexpr BlockState Cactus(const unsigned char Age) { if (Age == 0) return 3931; else if (Age == 1) return 3932; else if (Age == 2) return 3933; else if (Age == 3) return 3934; else if (Age == 4) return 3935; else if (Age == 5) return 3936; else if (Age == 6) return 3937; else if (Age == 7) return 3938; else if (Age == 8) return 3939; else if (Age == 9) return 3940; else if (Age == 10) return 3941; else if (Age == 11) return 3942; else if (Age == 12) return 3943; else if (Age == 13) return 3944; else if (Age == 14) return 3945; else return 3946; } BlockState Cactus(); unsigned char Age(BlockState Block); } namespace Cake { constexpr BlockState Cake(const unsigned char Bites) { if (Bites == 0) return 4024; else if (Bites == 1) return 4025; else if (Bites == 2) return 4026; else if (Bites == 3) return 4027; else if (Bites == 4) return 4028; else if (Bites == 5) return 4029; else return 4030; } BlockState Cake(); unsigned char Bites(BlockState Block); } namespace Campfire { constexpr BlockState Campfire(const eBlockFace Facing, const bool Lit, const bool SignalFire) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Lit) if (SignalFire) return 14891; else return 14893; else if (SignalFire) return 14895; else return 14897; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Lit) if (SignalFire) return 14899; else return 14901; else if (SignalFire) return 14903; else return 14905; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Lit) if (SignalFire) return 14907; else return 14909; else if (SignalFire) return 14911; else return 14913; else if (Lit) if (SignalFire) return 14915; else return 14917; else if (SignalFire) return 14919; else return 14921; } BlockState Campfire(); eBlockFace Facing(BlockState Block); bool Lit(BlockState Block); bool SignalFire(BlockState Block); } namespace Carrots { constexpr BlockState Carrots(const unsigned char Age) { if (Age == 0) return 6330; else if (Age == 1) return 6331; else if (Age == 2) return 6332; else if (Age == 3) return 6333; else if (Age == 4) return 6334; else if (Age == 5) return 6335; else if (Age == 6) return 6336; else return 6337; } BlockState Carrots(); unsigned char Age(BlockState Block); } namespace CartographyTable { constexpr BlockState CartographyTable() { return 14819; } } namespace CarvedPumpkin { constexpr BlockState CarvedPumpkin(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 4016; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 4017; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 4018; else return 4019; } BlockState CarvedPumpkin(); eBlockFace Facing(BlockState Block); } namespace Cauldron { constexpr BlockState Cauldron(const unsigned char Level) { if (Level == 0) return 5141; else if (Level == 1) return 5142; else if (Level == 2) return 5143; else return 5144; } BlockState Cauldron(); unsigned char Level(BlockState Block); } namespace CaveAir { constexpr BlockState CaveAir() { return 9666; } } namespace Chain { constexpr BlockState Chain() { return 4730; } } namespace ChainCommandBlock { constexpr BlockState ChainCommandBlock(const bool Conditional, const eBlockFace Facing) { if (Conditional) if (Facing == eBlockFace::BLOCK_FACE_ZM) return 9237; else if (Facing == eBlockFace::BLOCK_FACE_XP) return 9238; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 9239; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 9240; else if (Facing == eBlockFace::BLOCK_FACE_YP) return 9241; else return 9242; else if (Facing == eBlockFace::BLOCK_FACE_ZM) return 9243; else if (Facing == eBlockFace::BLOCK_FACE_XP) return 9244; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 9245; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 9246; else if (Facing == eBlockFace::BLOCK_FACE_YP) return 9247; else return 9248; } BlockState ChainCommandBlock(); bool Conditional(BlockState Block); eBlockFace Facing(BlockState Block); } namespace Chest { enum class Type { Single, Left, Right }; constexpr BlockState Chest(const eBlockFace Facing, const enum Type Type) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Type == Type::Single) return 2035; else if (Type == Type::Left) return 2037; else return 2039; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Type == Type::Single) return 2041; else if (Type == Type::Left) return 2043; else return 2045; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Type == Type::Single) return 2047; else if (Type == Type::Left) return 2049; else return 2051; else if (Type == Type::Single) return 2053; else if (Type == Type::Left) return 2055; else return 2057; } BlockState Chest(); eBlockFace Facing(BlockState Block); enum Type Type(BlockState Block); } namespace ChippedAnvil { constexpr BlockState ChippedAnvil(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 6614; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 6615; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 6616; else return 6617; } BlockState ChippedAnvil(); eBlockFace Facing(BlockState Block); } namespace ChiseledNetherBricks { constexpr BlockState ChiseledNetherBricks() { return 17101; } } namespace ChiseledPolishedBlackstone { constexpr BlockState ChiseledPolishedBlackstone() { return 16253; } } namespace ChiseledQuartzBlock { constexpr BlockState ChiseledQuartzBlock() { return 6739; } } namespace ChiseledRedSandstone { constexpr BlockState ChiseledRedSandstone() { return 8218; } } namespace ChiseledSandstone { constexpr BlockState ChiseledSandstone() { return 247; } } namespace ChiseledStoneBricks { constexpr BlockState ChiseledStoneBricks() { return 4498; } } namespace ChorusFlower { constexpr BlockState ChorusFlower(const unsigned char Age) { if (Age == 0) return 9128; else if (Age == 1) return 9129; else if (Age == 2) return 9130; else if (Age == 3) return 9131; else if (Age == 4) return 9132; else return 9133; } BlockState ChorusFlower(); unsigned char Age(BlockState Block); } namespace ChorusPlant { constexpr BlockState ChorusPlant(const bool Down, const bool East, const bool North, const bool South, const bool Up, const bool West) { if (Down) if (East) if (North) if (South) if (Up) if (West) return 9064; else return 9065; else if (West) return 9066; else return 9067; else if (Up) if (West) return 9068; else return 9069; else if (West) return 9070; else return 9071; else if (South) if (Up) if (West) return 9072; else return 9073; else if (West) return 9074; else return 9075; else if (Up) if (West) return 9076; else return 9077; else if (West) return 9078; else return 9079; else if (North) if (South) if (Up) if (West) return 9080; else return 9081; else if (West) return 9082; else return 9083; else if (Up) if (West) return 9084; else return 9085; else if (West) return 9086; else return 9087; else if (South) if (Up) if (West) return 9088; else return 9089; else if (West) return 9090; else return 9091; else if (Up) if (West) return 9092; else return 9093; else if (West) return 9094; else return 9095; else if (East) if (North) if (South) if (Up) if (West) return 9096; else return 9097; else if (West) return 9098; else return 9099; else if (Up) if (West) return 9100; else return 9101; else if (West) return 9102; else return 9103; else if (South) if (Up) if (West) return 9104; else return 9105; else if (West) return 9106; else return 9107; else if (Up) if (West) return 9108; else return 9109; else if (West) return 9110; else return 9111; else if (North) if (South) if (Up) if (West) return 9112; else return 9113; else if (West) return 9114; else return 9115; else if (Up) if (West) return 9116; else return 9117; else if (West) return 9118; else return 9119; else if (South) if (Up) if (West) return 9120; else return 9121; else if (West) return 9122; else return 9123; else if (Up) if (West) return 9124; else return 9125; else if (West) return 9126; else return 9127; } BlockState ChorusPlant(); bool Down(BlockState Block); bool East(BlockState Block); bool North(BlockState Block); bool South(BlockState Block); bool Up(BlockState Block); bool West(BlockState Block); } namespace Clay { constexpr BlockState Clay() { return 3947; } } namespace CoalBlock { constexpr BlockState CoalBlock() { return 7883; } } namespace CoalOre { constexpr BlockState CoalOre() { return 71; } } namespace CoarseDirt { constexpr BlockState CoarseDirt() { return 11; } } namespace Cobblestone { constexpr BlockState Cobblestone() { return 14; } } namespace CobblestoneSlab { enum class Type { Top, Bottom, Double }; constexpr BlockState CobblestoneSlab(const enum Type Type) { if (Type == Type::Top) return 8367; else if (Type == Type::Bottom) return 8369; else return 8371; } BlockState CobblestoneSlab(); enum Type Type(BlockState Block); } namespace CobblestoneStairs { enum class Half { Top, Bottom }; enum class Shape { Straight, InnerLeft, InnerRight, OuterLeft, OuterRight }; constexpr BlockState CobblestoneStairs(const eBlockFace Facing, const enum Half Half, const enum Shape Shape) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Half == Half::Top) if (Shape == Shape::Straight) return 3656; else if (Shape == Shape::InnerLeft) return 3658; else if (Shape == Shape::InnerRight) return 3660; else if (Shape == Shape::OuterLeft) return 3662; else return 3664; else if (Shape == Shape::Straight) return 3666; else if (Shape == Shape::InnerLeft) return 3668; else if (Shape == Shape::InnerRight) return 3670; else if (Shape == Shape::OuterLeft) return 3672; else return 3674; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Half == Half::Top) if (Shape == Shape::Straight) return 3676; else if (Shape == Shape::InnerLeft) return 3678; else if (Shape == Shape::InnerRight) return 3680; else if (Shape == Shape::OuterLeft) return 3682; else return 3684; else if (Shape == Shape::Straight) return 3686; else if (Shape == Shape::InnerLeft) return 3688; else if (Shape == Shape::InnerRight) return 3690; else if (Shape == Shape::OuterLeft) return 3692; else return 3694; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Half == Half::Top) if (Shape == Shape::Straight) return 3696; else if (Shape == Shape::InnerLeft) return 3698; else if (Shape == Shape::InnerRight) return 3700; else if (Shape == Shape::OuterLeft) return 3702; else return 3704; else if (Shape == Shape::Straight) return 3706; else if (Shape == Shape::InnerLeft) return 3708; else if (Shape == Shape::InnerRight) return 3710; else if (Shape == Shape::OuterLeft) return 3712; else return 3714; else if (Half == Half::Top) if (Shape == Shape::Straight) return 3716; else if (Shape == Shape::InnerLeft) return 3718; else if (Shape == Shape::InnerRight) return 3720; else if (Shape == Shape::OuterLeft) return 3722; else return 3724; else if (Shape == Shape::Straight) return 3726; else if (Shape == Shape::InnerLeft) return 3728; else if (Shape == Shape::InnerRight) return 3730; else if (Shape == Shape::OuterLeft) return 3732; else return 3734; } BlockState CobblestoneStairs(); eBlockFace Facing(BlockState Block); enum Half Half(BlockState Block); enum Shape Shape(BlockState Block); } namespace CobblestoneWall { enum class East { None, Low, Tall }; enum class North { None, Low, Tall }; enum class South { None, Low, Tall }; enum class West { None, Low, Tall }; constexpr BlockState CobblestoneWall(const enum East East, const enum North North, const enum South South, const bool Up, const enum West West) { if (East == East::None) if (North == North::None) if (South == South::None) if (Up) if (West == West::None) return 5660; else if (West == West::Low) return 5661; else return 5662; else if (West == West::None) return 5666; else if (West == West::Low) return 5667; else return 5668; else if (South == South::Low) if (Up) if (West == West::None) return 5672; else if (West == West::Low) return 5673; else return 5674; else if (West == West::None) return 5678; else if (West == West::Low) return 5679; else return 5680; else if (Up) if (West == West::None) return 5684; else if (West == West::Low) return 5685; else return 5686; else if (West == West::None) return 5690; else if (West == West::Low) return 5691; else return 5692; else if (North == North::Low) if (South == South::None) if (Up) if (West == West::None) return 5696; else if (West == West::Low) return 5697; else return 5698; else if (West == West::None) return 5702; else if (West == West::Low) return 5703; else return 5704; else if (South == South::Low) if (Up) if (West == West::None) return 5708; else if (West == West::Low) return 5709; else return 5710; else if (West == West::None) return 5714; else if (West == West::Low) return 5715; else return 5716; else if (Up) if (West == West::None) return 5720; else if (West == West::Low) return 5721; else return 5722; else if (West == West::None) return 5726; else if (West == West::Low) return 5727; else return 5728; else if (South == South::None) if (Up) if (West == West::None) return 5732; else if (West == West::Low) return 5733; else return 5734; else if (West == West::None) return 5738; else if (West == West::Low) return 5739; else return 5740; else if (South == South::Low) if (Up) if (West == West::None) return 5744; else if (West == West::Low) return 5745; else return 5746; else if (West == West::None) return 5750; else if (West == West::Low) return 5751; else return 5752; else if (Up) if (West == West::None) return 5756; else if (West == West::Low) return 5757; else return 5758; else if (West == West::None) return 5762; else if (West == West::Low) return 5763; else return 5764; else if (East == East::Low) if (North == North::None) if (South == South::None) if (Up) if (West == West::None) return 5768; else if (West == West::Low) return 5769; else return 5770; else if (West == West::None) return 5774; else if (West == West::Low) return 5775; else return 5776; else if (South == South::Low) if (Up) if (West == West::None) return 5780; else if (West == West::Low) return 5781; else return 5782; else if (West == West::None) return 5786; else if (West == West::Low) return 5787; else return 5788; else if (Up) if (West == West::None) return 5792; else if (West == West::Low) return 5793; else return 5794; else if (West == West::None) return 5798; else if (West == West::Low) return 5799; else return 5800; else if (North == North::Low) if (South == South::None) if (Up) if (West == West::None) return 5804; else if (West == West::Low) return 5805; else return 5806; else if (West == West::None) return 5810; else if (West == West::Low) return 5811; else return 5812; else if (South == South::Low) if (Up) if (West == West::None) return 5816; else if (West == West::Low) return 5817; else return 5818; else if (West == West::None) return 5822; else if (West == West::Low) return 5823; else return 5824; else if (Up) if (West == West::None) return 5828; else if (West == West::Low) return 5829; else return 5830; else if (West == West::None) return 5834; else if (West == West::Low) return 5835; else return 5836; else if (South == South::None) if (Up) if (West == West::None) return 5840; else if (West == West::Low) return 5841; else return 5842; else if (West == West::None) return 5846; else if (West == West::Low) return 5847; else return 5848; else if (South == South::Low) if (Up) if (West == West::None) return 5852; else if (West == West::Low) return 5853; else return 5854; else if (West == West::None) return 5858; else if (West == West::Low) return 5859; else return 5860; else if (Up) if (West == West::None) return 5864; else if (West == West::Low) return 5865; else return 5866; else if (West == West::None) return 5870; else if (West == West::Low) return 5871; else return 5872; else if (North == North::None) if (South == South::None) if (Up) if (West == West::None) return 5876; else if (West == West::Low) return 5877; else return 5878; else if (West == West::None) return 5882; else if (West == West::Low) return 5883; else return 5884; else if (South == South::Low) if (Up) if (West == West::None) return 5888; else if (West == West::Low) return 5889; else return 5890; else if (West == West::None) return 5894; else if (West == West::Low) return 5895; else return 5896; else if (Up) if (West == West::None) return 5900; else if (West == West::Low) return 5901; else return 5902; else if (West == West::None) return 5906; else if (West == West::Low) return 5907; else return 5908; else if (North == North::Low) if (South == South::None) if (Up) if (West == West::None) return 5912; else if (West == West::Low) return 5913; else return 5914; else if (West == West::None) return 5918; else if (West == West::Low) return 5919; else return 5920; else if (South == South::Low) if (Up) if (West == West::None) return 5924; else if (West == West::Low) return 5925; else return 5926; else if (West == West::None) return 5930; else if (West == West::Low) return 5931; else return 5932; else if (Up) if (West == West::None) return 5936; else if (West == West::Low) return 5937; else return 5938; else if (West == West::None) return 5942; else if (West == West::Low) return 5943; else return 5944; else if (South == South::None) if (Up) if (West == West::None) return 5948; else if (West == West::Low) return 5949; else return 5950; else if (West == West::None) return 5954; else if (West == West::Low) return 5955; else return 5956; else if (South == South::Low) if (Up) if (West == West::None) return 5960; else if (West == West::Low) return 5961; else return 5962; else if (West == West::None) return 5966; else if (West == West::Low) return 5967; else return 5968; else if (Up) if (West == West::None) return 5972; else if (West == West::Low) return 5973; else return 5974; else if (West == West::None) return 5978; else if (West == West::Low) return 5979; else return 5980; } BlockState CobblestoneWall(); enum East East(BlockState Block); enum North North(BlockState Block); enum South South(BlockState Block); bool Up(BlockState Block); enum West West(BlockState Block); } namespace Cobweb { constexpr BlockState Cobweb() { return 1341; } } namespace Cocoa { constexpr BlockState Cocoa(const unsigned char Age, const eBlockFace Facing) { if (Age == 0) if (Facing == eBlockFace::BLOCK_FACE_ZM) return 5158; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 5159; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 5160; else return 5161; else if (Age == 1) if (Facing == eBlockFace::BLOCK_FACE_ZM) return 5162; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 5163; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 5164; else return 5165; else if (Facing == eBlockFace::BLOCK_FACE_ZM) return 5166; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 5167; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 5168; else return 5169; } BlockState Cocoa(); unsigned char Age(BlockState Block); eBlockFace Facing(BlockState Block); } namespace CommandBlock { constexpr BlockState CommandBlock(const bool Conditional, const eBlockFace Facing) { if (Conditional) if (Facing == eBlockFace::BLOCK_FACE_ZM) return 5644; else if (Facing == eBlockFace::BLOCK_FACE_XP) return 5645; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 5646; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 5647; else if (Facing == eBlockFace::BLOCK_FACE_YP) return 5648; else return 5649; else if (Facing == eBlockFace::BLOCK_FACE_ZM) return 5650; else if (Facing == eBlockFace::BLOCK_FACE_XP) return 5651; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 5652; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 5653; else if (Facing == eBlockFace::BLOCK_FACE_YP) return 5654; else return 5655; } BlockState CommandBlock(); bool Conditional(BlockState Block); eBlockFace Facing(BlockState Block); } namespace Comparator { enum class Mode { Compare, Subtract }; constexpr BlockState Comparator(const eBlockFace Facing, const enum Mode Mode, const bool Powered) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Mode == Mode::Compare) if (Powered) return 6678; else return 6679; else if (Powered) return 6680; else return 6681; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Mode == Mode::Compare) if (Powered) return 6682; else return 6683; else if (Powered) return 6684; else return 6685; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Mode == Mode::Compare) if (Powered) return 6686; else return 6687; else if (Powered) return 6688; else return 6689; else if (Mode == Mode::Compare) if (Powered) return 6690; else return 6691; else if (Powered) return 6692; else return 6693; } BlockState Comparator(); eBlockFace Facing(BlockState Block); enum Mode Mode(BlockState Block); bool Powered(BlockState Block); } namespace Composter { constexpr BlockState Composter(const unsigned char Level) { if (Level == 0) return 15751; else if (Level == 1) return 15752; else if (Level == 2) return 15753; else if (Level == 3) return 15754; else if (Level == 4) return 15755; else if (Level == 5) return 15756; else if (Level == 6) return 15757; else if (Level == 7) return 15758; else return 15759; } BlockState Composter(); unsigned char Level(BlockState Block); } namespace Conduit { constexpr BlockState Conduit() { return 9650; } } namespace Cornflower { constexpr BlockState Cornflower() { return 1422; } } namespace CrackedNetherBricks { constexpr BlockState CrackedNetherBricks() { return 17102; } } namespace CrackedPolishedBlackstoneBricks { constexpr BlockState CrackedPolishedBlackstoneBricks() { return 16252; } } namespace CrackedStoneBricks { constexpr BlockState CrackedStoneBricks() { return 4497; } } namespace CraftingTable { constexpr BlockState CraftingTable() { return 3356; } } namespace CreeperHead { constexpr BlockState CreeperHead(const unsigned char Rotation) { if (Rotation == 0) return 6570; else if (Rotation == 1) return 6571; else if (Rotation == 2) return 6572; else if (Rotation == 3) return 6573; else if (Rotation == 4) return 6574; else if (Rotation == 5) return 6575; else if (Rotation == 6) return 6576; else if (Rotation == 7) return 6577; else if (Rotation == 8) return 6578; else if (Rotation == 9) return 6579; else if (Rotation == 10) return 6580; else if (Rotation == 11) return 6581; else if (Rotation == 12) return 6582; else if (Rotation == 13) return 6583; else if (Rotation == 14) return 6584; else return 6585; } BlockState CreeperHead(); unsigned char Rotation(BlockState Block); } namespace CreeperWallHead { constexpr BlockState CreeperWallHead(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 6586; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 6587; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 6588; else return 6589; } BlockState CreeperWallHead(); eBlockFace Facing(BlockState Block); } namespace CrimsonButton { enum class Face { Floor, Wall, Ceiling }; constexpr BlockState CrimsonButton(const enum Face Face, const eBlockFace Facing, const bool Powered) { if (Face == Face::Floor) if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Powered) return 15479; else return 15480; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Powered) return 15481; else return 15482; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Powered) return 15483; else return 15484; else if (Powered) return 15485; else return 15486; else if (Face == Face::Wall) if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Powered) return 15487; else return 15488; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Powered) return 15489; else return 15490; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Powered) return 15491; else return 15492; else if (Powered) return 15493; else return 15494; else if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Powered) return 15495; else return 15496; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Powered) return 15497; else return 15498; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Powered) return 15499; else return 15500; else if (Powered) return 15501; else return 15502; } BlockState CrimsonButton(); enum Face Face(BlockState Block); eBlockFace Facing(BlockState Block); bool Powered(BlockState Block); } namespace CrimsonDoor { enum class Half { Upper, Lower }; enum class Hinge { Left, Right }; constexpr BlockState CrimsonDoor(const eBlockFace Facing, const enum Half Half, const enum Hinge Hinge, const bool Open, const bool Powered) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Half == Half::Upper) if (Hinge == Hinge::Left) if (Open) if (Powered) return 15527; else return 15528; else if (Powered) return 15529; else return 15530; else if (Open) if (Powered) return 15531; else return 15532; else if (Powered) return 15533; else return 15534; else if (Hinge == Hinge::Left) if (Open) if (Powered) return 15535; else return 15536; else if (Powered) return 15537; else return 15538; else if (Open) if (Powered) return 15539; else return 15540; else if (Powered) return 15541; else return 15542; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Half == Half::Upper) if (Hinge == Hinge::Left) if (Open) if (Powered) return 15543; else return 15544; else if (Powered) return 15545; else return 15546; else if (Open) if (Powered) return 15547; else return 15548; else if (Powered) return 15549; else return 15550; else if (Hinge == Hinge::Left) if (Open) if (Powered) return 15551; else return 15552; else if (Powered) return 15553; else return 15554; else if (Open) if (Powered) return 15555; else return 15556; else if (Powered) return 15557; else return 15558; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Half == Half::Upper) if (Hinge == Hinge::Left) if (Open) if (Powered) return 15559; else return 15560; else if (Powered) return 15561; else return 15562; else if (Open) if (Powered) return 15563; else return 15564; else if (Powered) return 15565; else return 15566; else if (Hinge == Hinge::Left) if (Open) if (Powered) return 15567; else return 15568; else if (Powered) return 15569; else return 15570; else if (Open) if (Powered) return 15571; else return 15572; else if (Powered) return 15573; else return 15574; else if (Half == Half::Upper) if (Hinge == Hinge::Left) if (Open) if (Powered) return 15575; else return 15576; else if (Powered) return 15577; else return 15578; else if (Open) if (Powered) return 15579; else return 15580; else if (Powered) return 15581; else return 15582; else if (Hinge == Hinge::Left) if (Open) if (Powered) return 15583; else return 15584; else if (Powered) return 15585; else return 15586; else if (Open) if (Powered) return 15587; else return 15588; else if (Powered) return 15589; else return 15590; } BlockState CrimsonDoor(); eBlockFace Facing(BlockState Block); enum Half Half(BlockState Block); enum Hinge Hinge(BlockState Block); bool Open(BlockState Block); bool Powered(BlockState Block); } namespace CrimsonFence { constexpr BlockState CrimsonFence(const bool East, const bool North, const bool South, const bool West) { if (East) if (North) if (South) if (West) return 15065; else return 15066; else if (West) return 15069; else return 15070; else if (South) if (West) return 15073; else return 15074; else if (West) return 15077; else return 15078; else if (North) if (South) if (West) return 15081; else return 15082; else if (West) return 15085; else return 15086; else if (South) if (West) return 15089; else return 15090; else if (West) return 15093; else return 15094; } BlockState CrimsonFence(); bool East(BlockState Block); bool North(BlockState Block); bool South(BlockState Block); bool West(BlockState Block); } namespace CrimsonFenceGate { constexpr BlockState CrimsonFenceGate(const eBlockFace Facing, const bool InWall, const bool Open, const bool Powered) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (InWall) if (Open) if (Powered) return 15255; else return 15256; else if (Powered) return 15257; else return 15258; else if (Open) if (Powered) return 15259; else return 15260; else if (Powered) return 15261; else return 15262; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (InWall) if (Open) if (Powered) return 15263; else return 15264; else if (Powered) return 15265; else return 15266; else if (Open) if (Powered) return 15267; else return 15268; else if (Powered) return 15269; else return 15270; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (InWall) if (Open) if (Powered) return 15271; else return 15272; else if (Powered) return 15273; else return 15274; else if (Open) if (Powered) return 15275; else return 15276; else if (Powered) return 15277; else return 15278; else if (InWall) if (Open) if (Powered) return 15279; else return 15280; else if (Powered) return 15281; else return 15282; else if (Open) if (Powered) return 15283; else return 15284; else if (Powered) return 15285; else return 15286; } BlockState CrimsonFenceGate(); eBlockFace Facing(BlockState Block); bool InWall(BlockState Block); bool Open(BlockState Block); bool Powered(BlockState Block); } namespace CrimsonFungus { constexpr BlockState CrimsonFungus() { return 14988; } } namespace CrimsonHyphae { enum class Axis { X, Y, Z }; constexpr BlockState CrimsonHyphae(const enum Axis Axis) { if (Axis == Axis::X) return 14981; else if (Axis == Axis::Y) return 14982; else return 14983; } BlockState CrimsonHyphae(); enum Axis Axis(BlockState Block); } namespace CrimsonNylium { constexpr BlockState CrimsonNylium() { return 14987; } } namespace CrimsonPlanks { constexpr BlockState CrimsonPlanks() { return 15045; } } namespace CrimsonPressurePlate { constexpr BlockState CrimsonPressurePlate(const bool Powered) { if (Powered) return 15059; else return 15060; } BlockState CrimsonPressurePlate(); bool Powered(BlockState Block); } namespace CrimsonRoots { constexpr BlockState CrimsonRoots() { return 15044; } } namespace CrimsonSign { constexpr BlockState CrimsonSign(const unsigned char Rotation) { if (Rotation == 0) return 15656; else if (Rotation == 1) return 15658; else if (Rotation == 2) return 15660; else if (Rotation == 3) return 15662; else if (Rotation == 4) return 15664; else if (Rotation == 5) return 15666; else if (Rotation == 6) return 15668; else if (Rotation == 7) return 15670; else if (Rotation == 8) return 15672; else if (Rotation == 9) return 15674; else if (Rotation == 10) return 15676; else if (Rotation == 11) return 15678; else if (Rotation == 12) return 15680; else if (Rotation == 13) return 15682; else if (Rotation == 14) return 15684; else return 15686; } BlockState CrimsonSign(); unsigned char Rotation(BlockState Block); } namespace CrimsonSlab { enum class Type { Top, Bottom, Double }; constexpr BlockState CrimsonSlab(const enum Type Type) { if (Type == Type::Top) return 15048; else if (Type == Type::Bottom) return 15050; else return 15052; } BlockState CrimsonSlab(); enum Type Type(BlockState Block); } namespace CrimsonStairs { enum class Half { Top, Bottom }; enum class Shape { Straight, InnerLeft, InnerRight, OuterLeft, OuterRight }; constexpr BlockState CrimsonStairs(const eBlockFace Facing, const enum Half Half, const enum Shape Shape) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Half == Half::Top) if (Shape == Shape::Straight) return 15320; else if (Shape == Shape::InnerLeft) return 15322; else if (Shape == Shape::InnerRight) return 15324; else if (Shape == Shape::OuterLeft) return 15326; else return 15328; else if (Shape == Shape::Straight) return 15330; else if (Shape == Shape::InnerLeft) return 15332; else if (Shape == Shape::InnerRight) return 15334; else if (Shape == Shape::OuterLeft) return 15336; else return 15338; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Half == Half::Top) if (Shape == Shape::Straight) return 15340; else if (Shape == Shape::InnerLeft) return 15342; else if (Shape == Shape::InnerRight) return 15344; else if (Shape == Shape::OuterLeft) return 15346; else return 15348; else if (Shape == Shape::Straight) return 15350; else if (Shape == Shape::InnerLeft) return 15352; else if (Shape == Shape::InnerRight) return 15354; else if (Shape == Shape::OuterLeft) return 15356; else return 15358; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Half == Half::Top) if (Shape == Shape::Straight) return 15360; else if (Shape == Shape::InnerLeft) return 15362; else if (Shape == Shape::InnerRight) return 15364; else if (Shape == Shape::OuterLeft) return 15366; else return 15368; else if (Shape == Shape::Straight) return 15370; else if (Shape == Shape::InnerLeft) return 15372; else if (Shape == Shape::InnerRight) return 15374; else if (Shape == Shape::OuterLeft) return 15376; else return 15378; else if (Half == Half::Top) if (Shape == Shape::Straight) return 15380; else if (Shape == Shape::InnerLeft) return 15382; else if (Shape == Shape::InnerRight) return 15384; else if (Shape == Shape::OuterLeft) return 15386; else return 15388; else if (Shape == Shape::Straight) return 15390; else if (Shape == Shape::InnerLeft) return 15392; else if (Shape == Shape::InnerRight) return 15394; else if (Shape == Shape::OuterLeft) return 15396; else return 15398; } BlockState CrimsonStairs(); eBlockFace Facing(BlockState Block); enum Half Half(BlockState Block); enum Shape Shape(BlockState Block); } namespace CrimsonStem { enum class Axis { X, Y, Z }; constexpr BlockState CrimsonStem(const enum Axis Axis) { if (Axis == Axis::X) return 14975; else if (Axis == Axis::Y) return 14976; else return 14977; } BlockState CrimsonStem(); enum Axis Axis(BlockState Block); } namespace CrimsonTrapdoor { enum class Half { Top, Bottom }; constexpr BlockState CrimsonTrapdoor(const eBlockFace Facing, const enum Half Half, const bool Open, const bool Powered) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Half == Half::Top) if (Open) if (Powered) return 15128; else return 15130; else if (Powered) return 15132; else return 15134; else if (Open) if (Powered) return 15136; else return 15138; else if (Powered) return 15140; else return 15142; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Half == Half::Top) if (Open) if (Powered) return 15144; else return 15146; else if (Powered) return 15148; else return 15150; else if (Open) if (Powered) return 15152; else return 15154; else if (Powered) return 15156; else return 15158; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Half == Half::Top) if (Open) if (Powered) return 15160; else return 15162; else if (Powered) return 15164; else return 15166; else if (Open) if (Powered) return 15168; else return 15170; else if (Powered) return 15172; else return 15174; else if (Half == Half::Top) if (Open) if (Powered) return 15176; else return 15178; else if (Powered) return 15180; else return 15182; else if (Open) if (Powered) return 15184; else return 15186; else if (Powered) return 15188; else return 15190; } BlockState CrimsonTrapdoor(); eBlockFace Facing(BlockState Block); enum Half Half(BlockState Block); bool Open(BlockState Block); bool Powered(BlockState Block); } namespace CrimsonWallSign { constexpr BlockState CrimsonWallSign(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 15720; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 15722; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 15724; else return 15726; } BlockState CrimsonWallSign(); eBlockFace Facing(BlockState Block); } namespace CryingObsidian { constexpr BlockState CryingObsidian() { return 15828; } } namespace CutRedSandstone { constexpr BlockState CutRedSandstone() { return 8219; } } namespace CutRedSandstoneSlab { enum class Type { Top, Bottom, Double }; constexpr BlockState CutRedSandstoneSlab(const enum Type Type) { if (Type == Type::Top) return 8403; else if (Type == Type::Bottom) return 8405; else return 8407; } BlockState CutRedSandstoneSlab(); enum Type Type(BlockState Block); } namespace CutSandstone { constexpr BlockState CutSandstone() { return 248; } } namespace CutSandstoneSlab { enum class Type { Top, Bottom, Double }; constexpr BlockState CutSandstoneSlab(const enum Type Type) { if (Type == Type::Top) return 8355; else if (Type == Type::Bottom) return 8357; else return 8359; } BlockState CutSandstoneSlab(); enum Type Type(BlockState Block); } namespace CyanBanner { constexpr BlockState CyanBanner(const unsigned char Rotation) { if (Rotation == 0) return 8041; else if (Rotation == 1) return 8042; else if (Rotation == 2) return 8043; else if (Rotation == 3) return 8044; else if (Rotation == 4) return 8045; else if (Rotation == 5) return 8046; else if (Rotation == 6) return 8047; else if (Rotation == 7) return 8048; else if (Rotation == 8) return 8049; else if (Rotation == 9) return 8050; else if (Rotation == 10) return 8051; else if (Rotation == 11) return 8052; else if (Rotation == 12) return 8053; else if (Rotation == 13) return 8054; else if (Rotation == 14) return 8055; else return 8056; } BlockState CyanBanner(); unsigned char Rotation(BlockState Block); } namespace CyanBed { enum class Part { Head, Foot }; constexpr BlockState CyanBed(const eBlockFace Facing, const bool Occupied, const enum Part Part) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Occupied) if (Part == Part::Head) return 1193; else return 1194; else if (Part == Part::Head) return 1195; else return 1196; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Occupied) if (Part == Part::Head) return 1197; else return 1198; else if (Part == Part::Head) return 1199; else return 1200; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Occupied) if (Part == Part::Head) return 1201; else return 1202; else if (Part == Part::Head) return 1203; else return 1204; else if (Occupied) if (Part == Part::Head) return 1205; else return 1206; else if (Part == Part::Head) return 1207; else return 1208; } BlockState CyanBed(); eBlockFace Facing(BlockState Block); bool Occupied(BlockState Block); enum Part Part(BlockState Block); } namespace CyanCarpet { constexpr BlockState CyanCarpet() { return 7875; } } namespace CyanConcrete { constexpr BlockState CyanConcrete() { return 9447; } } namespace CyanConcretePowder { constexpr BlockState CyanConcretePowder() { return 9463; } } namespace CyanGlazedTerracotta { constexpr BlockState CyanGlazedTerracotta(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 9410; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 9411; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 9412; else return 9413; } BlockState CyanGlazedTerracotta(); eBlockFace Facing(BlockState Block); } namespace CyanShulkerBox { constexpr BlockState CyanShulkerBox(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 9332; else if (Facing == eBlockFace::BLOCK_FACE_XP) return 9333; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 9334; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 9335; else if (Facing == eBlockFace::BLOCK_FACE_YP) return 9336; else return 9337; } BlockState CyanShulkerBox(); eBlockFace Facing(BlockState Block); } namespace CyanStainedGlass { constexpr BlockState CyanStainedGlass() { return 4104; } } namespace CyanStainedGlassPane { constexpr BlockState CyanStainedGlassPane(const bool East, const bool North, const bool South, const bool West) { if (East) if (North) if (South) if (West) return 7153; else return 7154; else if (West) return 7157; else return 7158; else if (South) if (West) return 7161; else return 7162; else if (West) return 7165; else return 7166; else if (North) if (South) if (West) return 7169; else return 7170; else if (West) return 7173; else return 7174; else if (South) if (West) return 7177; else return 7178; else if (West) return 7181; else return 7182; } BlockState CyanStainedGlassPane(); bool East(BlockState Block); bool North(BlockState Block); bool South(BlockState Block); bool West(BlockState Block); } namespace CyanTerracotta { constexpr BlockState CyanTerracotta() { return 6856; } } namespace CyanWallBanner { constexpr BlockState CyanWallBanner(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 8189; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 8190; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 8191; else return 8192; } BlockState CyanWallBanner(); eBlockFace Facing(BlockState Block); } namespace CyanWool { constexpr BlockState CyanWool() { return 1393; } } namespace DamagedAnvil { constexpr BlockState DamagedAnvil(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 6618; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 6619; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 6620; else return 6621; } BlockState DamagedAnvil(); eBlockFace Facing(BlockState Block); } namespace Dandelion { constexpr BlockState Dandelion() { return 1412; } } namespace DarkOakButton { enum class Face { Floor, Wall, Ceiling }; constexpr BlockState DarkOakButton(const enum Face Face, const eBlockFace Facing, const bool Powered) { if (Face == Face::Floor) if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Powered) return 6466; else return 6467; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Powered) return 6468; else return 6469; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Powered) return 6470; else return 6471; else if (Powered) return 6472; else return 6473; else if (Face == Face::Wall) if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Powered) return 6474; else return 6475; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Powered) return 6476; else return 6477; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Powered) return 6478; else return 6479; else if (Powered) return 6480; else return 6481; else if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Powered) return 6482; else return 6483; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Powered) return 6484; else return 6485; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Powered) return 6486; else return 6487; else if (Powered) return 6488; else return 6489; } BlockState DarkOakButton(); enum Face Face(BlockState Block); eBlockFace Facing(BlockState Block); bool Powered(BlockState Block); } namespace DarkOakDoor { enum class Half { Upper, Lower }; enum class Hinge { Left, Right }; constexpr BlockState DarkOakDoor(const eBlockFace Facing, const enum Half Half, const enum Hinge Hinge, const bool Open, const bool Powered) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Half == Half::Upper) if (Hinge == Hinge::Left) if (Open) if (Powered) return 8994; else return 8995; else if (Powered) return 8996; else return 8997; else if (Open) if (Powered) return 8998; else return 8999; else if (Powered) return 9000; else return 9001; else if (Hinge == Hinge::Left) if (Open) if (Powered) return 9002; else return 9003; else if (Powered) return 9004; else return 9005; else if (Open) if (Powered) return 9006; else return 9007; else if (Powered) return 9008; else return 9009; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Half == Half::Upper) if (Hinge == Hinge::Left) if (Open) if (Powered) return 9010; else return 9011; else if (Powered) return 9012; else return 9013; else if (Open) if (Powered) return 9014; else return 9015; else if (Powered) return 9016; else return 9017; else if (Hinge == Hinge::Left) if (Open) if (Powered) return 9018; else return 9019; else if (Powered) return 9020; else return 9021; else if (Open) if (Powered) return 9022; else return 9023; else if (Powered) return 9024; else return 9025; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Half == Half::Upper) if (Hinge == Hinge::Left) if (Open) if (Powered) return 9026; else return 9027; else if (Powered) return 9028; else return 9029; else if (Open) if (Powered) return 9030; else return 9031; else if (Powered) return 9032; else return 9033; else if (Hinge == Hinge::Left) if (Open) if (Powered) return 9034; else return 9035; else if (Powered) return 9036; else return 9037; else if (Open) if (Powered) return 9038; else return 9039; else if (Powered) return 9040; else return 9041; else if (Half == Half::Upper) if (Hinge == Hinge::Left) if (Open) if (Powered) return 9042; else return 9043; else if (Powered) return 9044; else return 9045; else if (Open) if (Powered) return 9046; else return 9047; else if (Powered) return 9048; else return 9049; else if (Hinge == Hinge::Left) if (Open) if (Powered) return 9050; else return 9051; else if (Powered) return 9052; else return 9053; else if (Open) if (Powered) return 9054; else return 9055; else if (Powered) return 9056; else return 9057; } BlockState DarkOakDoor(); eBlockFace Facing(BlockState Block); enum Half Half(BlockState Block); enum Hinge Hinge(BlockState Block); bool Open(BlockState Block); bool Powered(BlockState Block); } namespace DarkOakFence { constexpr BlockState DarkOakFence(const bool East, const bool North, const bool South, const bool West) { if (East) if (North) if (South) if (West) return 8708; else return 8709; else if (West) return 8712; else return 8713; else if (South) if (West) return 8716; else return 8717; else if (West) return 8720; else return 8721; else if (North) if (South) if (West) return 8724; else return 8725; else if (West) return 8728; else return 8729; else if (South) if (West) return 8732; else return 8733; else if (West) return 8736; else return 8737; } BlockState DarkOakFence(); bool East(BlockState Block); bool North(BlockState Block); bool South(BlockState Block); bool West(BlockState Block); } namespace DarkOakFenceGate { constexpr BlockState DarkOakFenceGate(const eBlockFace Facing, const bool InWall, const bool Open, const bool Powered) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (InWall) if (Open) if (Powered) return 8546; else return 8547; else if (Powered) return 8548; else return 8549; else if (Open) if (Powered) return 8550; else return 8551; else if (Powered) return 8552; else return 8553; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (InWall) if (Open) if (Powered) return 8554; else return 8555; else if (Powered) return 8556; else return 8557; else if (Open) if (Powered) return 8558; else return 8559; else if (Powered) return 8560; else return 8561; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (InWall) if (Open) if (Powered) return 8562; else return 8563; else if (Powered) return 8564; else return 8565; else if (Open) if (Powered) return 8566; else return 8567; else if (Powered) return 8568; else return 8569; else if (InWall) if (Open) if (Powered) return 8570; else return 8571; else if (Powered) return 8572; else return 8573; else if (Open) if (Powered) return 8574; else return 8575; else if (Powered) return 8576; else return 8577; } BlockState DarkOakFenceGate(); eBlockFace Facing(BlockState Block); bool InWall(BlockState Block); bool Open(BlockState Block); bool Powered(BlockState Block); } namespace DarkOakLeaves { constexpr BlockState DarkOakLeaves(const unsigned char Distance, const bool Persistent) { if (Distance == 1) if (Persistent) return 215; else return 216; else if (Distance == 2) if (Persistent) return 217; else return 218; else if (Distance == 3) if (Persistent) return 219; else return 220; else if (Distance == 4) if (Persistent) return 221; else return 222; else if (Distance == 5) if (Persistent) return 223; else return 224; else if (Distance == 6) if (Persistent) return 225; else return 226; else if (Persistent) return 227; else return 228; } BlockState DarkOakLeaves(); unsigned char Distance(BlockState Block); bool Persistent(BlockState Block); } namespace DarkOakLog { enum class Axis { X, Y, Z }; constexpr BlockState DarkOakLog(const enum Axis Axis) { if (Axis == Axis::X) return 88; else if (Axis == Axis::Y) return 89; else return 90; } BlockState DarkOakLog(); enum Axis Axis(BlockState Block); } namespace DarkOakPlanks { constexpr BlockState DarkOakPlanks() { return 20; } } namespace DarkOakPressurePlate { constexpr BlockState DarkOakPressurePlate(const bool Powered) { if (Powered) return 3883; else return 3884; } BlockState DarkOakPressurePlate(); bool Powered(BlockState Block); } namespace DarkOakSapling { constexpr BlockState DarkOakSapling(const unsigned char Stage) { if (Stage == 0) return 31; else return 32; } BlockState DarkOakSapling(); unsigned char Stage(BlockState Block); } namespace DarkOakSign { constexpr BlockState DarkOakSign(const unsigned char Rotation) { if (Rotation == 0) return 3542; else if (Rotation == 1) return 3544; else if (Rotation == 2) return 3546; else if (Rotation == 3) return 3548; else if (Rotation == 4) return 3550; else if (Rotation == 5) return 3552; else if (Rotation == 6) return 3554; else if (Rotation == 7) return 3556; else if (Rotation == 8) return 3558; else if (Rotation == 9) return 3560; else if (Rotation == 10) return 3562; else if (Rotation == 11) return 3564; else if (Rotation == 12) return 3566; else if (Rotation == 13) return 3568; else if (Rotation == 14) return 3570; else return 3572; } BlockState DarkOakSign(); unsigned char Rotation(BlockState Block); } namespace DarkOakSlab { enum class Type { Top, Bottom, Double }; constexpr BlockState DarkOakSlab(const enum Type Type) { if (Type == Type::Top) return 8331; else if (Type == Type::Bottom) return 8333; else return 8335; } BlockState DarkOakSlab(); enum Type Type(BlockState Block); } namespace DarkOakStairs { enum class Half { Top, Bottom }; enum class Shape { Straight, InnerLeft, InnerRight, OuterLeft, OuterRight }; constexpr BlockState DarkOakStairs(const eBlockFace Facing, const enum Half Half, const enum Shape Shape) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Half == Half::Top) if (Shape == Shape::Straight) return 7456; else if (Shape == Shape::InnerLeft) return 7458; else if (Shape == Shape::InnerRight) return 7460; else if (Shape == Shape::OuterLeft) return 7462; else return 7464; else if (Shape == Shape::Straight) return 7466; else if (Shape == Shape::InnerLeft) return 7468; else if (Shape == Shape::InnerRight) return 7470; else if (Shape == Shape::OuterLeft) return 7472; else return 7474; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Half == Half::Top) if (Shape == Shape::Straight) return 7476; else if (Shape == Shape::InnerLeft) return 7478; else if (Shape == Shape::InnerRight) return 7480; else if (Shape == Shape::OuterLeft) return 7482; else return 7484; else if (Shape == Shape::Straight) return 7486; else if (Shape == Shape::InnerLeft) return 7488; else if (Shape == Shape::InnerRight) return 7490; else if (Shape == Shape::OuterLeft) return 7492; else return 7494; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Half == Half::Top) if (Shape == Shape::Straight) return 7496; else if (Shape == Shape::InnerLeft) return 7498; else if (Shape == Shape::InnerRight) return 7500; else if (Shape == Shape::OuterLeft) return 7502; else return 7504; else if (Shape == Shape::Straight) return 7506; else if (Shape == Shape::InnerLeft) return 7508; else if (Shape == Shape::InnerRight) return 7510; else if (Shape == Shape::OuterLeft) return 7512; else return 7514; else if (Half == Half::Top) if (Shape == Shape::Straight) return 7516; else if (Shape == Shape::InnerLeft) return 7518; else if (Shape == Shape::InnerRight) return 7520; else if (Shape == Shape::OuterLeft) return 7522; else return 7524; else if (Shape == Shape::Straight) return 7526; else if (Shape == Shape::InnerLeft) return 7528; else if (Shape == Shape::InnerRight) return 7530; else if (Shape == Shape::OuterLeft) return 7532; else return 7534; } BlockState DarkOakStairs(); eBlockFace Facing(BlockState Block); enum Half Half(BlockState Block); enum Shape Shape(BlockState Block); } namespace DarkOakTrapdoor { enum class Half { Top, Bottom }; constexpr BlockState DarkOakTrapdoor(const eBlockFace Facing, const enum Half Half, const bool Open, const bool Powered) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Half == Half::Top) if (Open) if (Powered) return 4432; else return 4434; else if (Powered) return 4436; else return 4438; else if (Open) if (Powered) return 4440; else return 4442; else if (Powered) return 4444; else return 4446; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Half == Half::Top) if (Open) if (Powered) return 4448; else return 4450; else if (Powered) return 4452; else return 4454; else if (Open) if (Powered) return 4456; else return 4458; else if (Powered) return 4460; else return 4462; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Half == Half::Top) if (Open) if (Powered) return 4464; else return 4466; else if (Powered) return 4468; else return 4470; else if (Open) if (Powered) return 4472; else return 4474; else if (Powered) return 4476; else return 4478; else if (Half == Half::Top) if (Open) if (Powered) return 4480; else return 4482; else if (Powered) return 4484; else return 4486; else if (Open) if (Powered) return 4488; else return 4490; else if (Powered) return 4492; else return 4494; } BlockState DarkOakTrapdoor(); eBlockFace Facing(BlockState Block); enum Half Half(BlockState Block); bool Open(BlockState Block); bool Powered(BlockState Block); } namespace DarkOakWallSign { constexpr BlockState DarkOakWallSign(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 3776; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 3778; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 3780; else return 3782; } BlockState DarkOakWallSign(); eBlockFace Facing(BlockState Block); } namespace DarkOakWood { enum class Axis { X, Y, Z }; constexpr BlockState DarkOakWood(const enum Axis Axis) { if (Axis == Axis::X) return 124; else if (Axis == Axis::Y) return 125; else return 126; } BlockState DarkOakWood(); enum Axis Axis(BlockState Block); } namespace DarkPrismarine { constexpr BlockState DarkPrismarine() { return 7603; } } namespace DarkPrismarineSlab { enum class Type { Top, Bottom, Double }; constexpr BlockState DarkPrismarineSlab(const enum Type Type) { if (Type == Type::Top) return 7857; else if (Type == Type::Bottom) return 7859; else return 7861; } BlockState DarkPrismarineSlab(); enum Type Type(BlockState Block); } namespace DarkPrismarineStairs { enum class Half { Top, Bottom }; enum class Shape { Straight, InnerLeft, InnerRight, OuterLeft, OuterRight }; constexpr BlockState DarkPrismarineStairs(const eBlockFace Facing, const enum Half Half, const enum Shape Shape) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Half == Half::Top) if (Shape == Shape::Straight) return 7765; else if (Shape == Shape::InnerLeft) return 7767; else if (Shape == Shape::InnerRight) return 7769; else if (Shape == Shape::OuterLeft) return 7771; else return 7773; else if (Shape == Shape::Straight) return 7775; else if (Shape == Shape::InnerLeft) return 7777; else if (Shape == Shape::InnerRight) return 7779; else if (Shape == Shape::OuterLeft) return 7781; else return 7783; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Half == Half::Top) if (Shape == Shape::Straight) return 7785; else if (Shape == Shape::InnerLeft) return 7787; else if (Shape == Shape::InnerRight) return 7789; else if (Shape == Shape::OuterLeft) return 7791; else return 7793; else if (Shape == Shape::Straight) return 7795; else if (Shape == Shape::InnerLeft) return 7797; else if (Shape == Shape::InnerRight) return 7799; else if (Shape == Shape::OuterLeft) return 7801; else return 7803; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Half == Half::Top) if (Shape == Shape::Straight) return 7805; else if (Shape == Shape::InnerLeft) return 7807; else if (Shape == Shape::InnerRight) return 7809; else if (Shape == Shape::OuterLeft) return 7811; else return 7813; else if (Shape == Shape::Straight) return 7815; else if (Shape == Shape::InnerLeft) return 7817; else if (Shape == Shape::InnerRight) return 7819; else if (Shape == Shape::OuterLeft) return 7821; else return 7823; else if (Half == Half::Top) if (Shape == Shape::Straight) return 7825; else if (Shape == Shape::InnerLeft) return 7827; else if (Shape == Shape::InnerRight) return 7829; else if (Shape == Shape::OuterLeft) return 7831; else return 7833; else if (Shape == Shape::Straight) return 7835; else if (Shape == Shape::InnerLeft) return 7837; else if (Shape == Shape::InnerRight) return 7839; else if (Shape == Shape::OuterLeft) return 7841; else return 7843; } BlockState DarkPrismarineStairs(); eBlockFace Facing(BlockState Block); enum Half Half(BlockState Block); enum Shape Shape(BlockState Block); } namespace DaylightDetector { constexpr BlockState DaylightDetector(const bool Inverted, const unsigned char Power) { if (Inverted) if (Power == 0) return 6694; else if (Power == 1) return 6695; else if (Power == 2) return 6696; else if (Power == 3) return 6697; else if (Power == 4) return 6698; else if (Power == 5) return 6699; else if (Power == 6) return 6700; else if (Power == 7) return 6701; else if (Power == 8) return 6702; else if (Power == 9) return 6703; else if (Power == 10) return 6704; else if (Power == 11) return 6705; else if (Power == 12) return 6706; else if (Power == 13) return 6707; else if (Power == 14) return 6708; else return 6709; else if (Power == 0) return 6710; else if (Power == 1) return 6711; else if (Power == 2) return 6712; else if (Power == 3) return 6713; else if (Power == 4) return 6714; else if (Power == 5) return 6715; else if (Power == 6) return 6716; else if (Power == 7) return 6717; else if (Power == 8) return 6718; else if (Power == 9) return 6719; else if (Power == 10) return 6720; else if (Power == 11) return 6721; else if (Power == 12) return 6722; else if (Power == 13) return 6723; else if (Power == 14) return 6724; else return 6725; } BlockState DaylightDetector(); bool Inverted(BlockState Block); unsigned char Power(BlockState Block); } namespace DeadBrainCoral { constexpr BlockState DeadBrainCoral() { return 9523; } } namespace DeadBrainCoralBlock { constexpr BlockState DeadBrainCoralBlock() { return 9511; } } namespace DeadBrainCoralFan { constexpr BlockState DeadBrainCoralFan() { return 9543; } } namespace DeadBrainCoralWallFan { constexpr BlockState DeadBrainCoralWallFan(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 9569; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 9571; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 9573; else return 9575; } BlockState DeadBrainCoralWallFan(); eBlockFace Facing(BlockState Block); } namespace DeadBubbleCoral { constexpr BlockState DeadBubbleCoral() { return 9525; } } namespace DeadBubbleCoralBlock { constexpr BlockState DeadBubbleCoralBlock() { return 9512; } } namespace DeadBubbleCoralFan { constexpr BlockState DeadBubbleCoralFan() { return 9545; } } namespace DeadBubbleCoralWallFan { constexpr BlockState DeadBubbleCoralWallFan(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 9577; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 9579; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 9581; else return 9583; } BlockState DeadBubbleCoralWallFan(); eBlockFace Facing(BlockState Block); } namespace DeadBush { constexpr BlockState DeadBush() { return 1344; } } namespace DeadFireCoral { constexpr BlockState DeadFireCoral() { return 9527; } } namespace DeadFireCoralBlock { constexpr BlockState DeadFireCoralBlock() { return 9513; } } namespace DeadFireCoralFan { constexpr BlockState DeadFireCoralFan() { return 9547; } } namespace DeadFireCoralWallFan { constexpr BlockState DeadFireCoralWallFan(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 9585; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 9587; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 9589; else return 9591; } BlockState DeadFireCoralWallFan(); eBlockFace Facing(BlockState Block); } namespace DeadHornCoral { constexpr BlockState DeadHornCoral() { return 9529; } } namespace DeadHornCoralBlock { constexpr BlockState DeadHornCoralBlock() { return 9514; } } namespace DeadHornCoralFan { constexpr BlockState DeadHornCoralFan() { return 9549; } } namespace DeadHornCoralWallFan { constexpr BlockState DeadHornCoralWallFan(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 9593; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 9595; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 9597; else return 9599; } BlockState DeadHornCoralWallFan(); eBlockFace Facing(BlockState Block); } namespace DeadTubeCoral { constexpr BlockState DeadTubeCoral() { return 9521; } } namespace DeadTubeCoralBlock { constexpr BlockState DeadTubeCoralBlock() { return 9510; } } namespace DeadTubeCoralFan { constexpr BlockState DeadTubeCoralFan() { return 9541; } } namespace DeadTubeCoralWallFan { constexpr BlockState DeadTubeCoralWallFan(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 9561; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 9563; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 9565; else return 9567; } BlockState DeadTubeCoralWallFan(); eBlockFace Facing(BlockState Block); } namespace DetectorRail { enum class Shape { NorthSouth, EastWest, AscendingEast, AscendingWest, AscendingNorth, AscendingSouth }; constexpr BlockState DetectorRail(const bool Powered, const enum Shape Shape) { if (Powered) if (Shape == Shape::NorthSouth) return 1317; else if (Shape == Shape::EastWest) return 1318; else if (Shape == Shape::AscendingEast) return 1319; else if (Shape == Shape::AscendingWest) return 1320; else if (Shape == Shape::AscendingNorth) return 1321; else return 1322; else if (Shape == Shape::NorthSouth) return 1323; else if (Shape == Shape::EastWest) return 1324; else if (Shape == Shape::AscendingEast) return 1325; else if (Shape == Shape::AscendingWest) return 1326; else if (Shape == Shape::AscendingNorth) return 1327; else return 1328; } BlockState DetectorRail(); bool Powered(BlockState Block); enum Shape Shape(BlockState Block); } namespace DiamondBlock { constexpr BlockState DiamondBlock() { return 3355; } } namespace DiamondOre { constexpr BlockState DiamondOre() { return 3354; } } namespace Diorite { constexpr BlockState Diorite() { return 4; } } namespace DioriteSlab { enum class Type { Top, Bottom, Double }; constexpr BlockState DioriteSlab(const enum Type Type) { if (Type == Type::Top) return 10862; else if (Type == Type::Bottom) return 10864; else return 10866; } BlockState DioriteSlab(); enum Type Type(BlockState Block); } namespace DioriteStairs { enum class Half { Top, Bottom }; enum class Shape { Straight, InnerLeft, InnerRight, OuterLeft, OuterRight }; constexpr BlockState DioriteStairs(const eBlockFace Facing, const enum Half Half, const enum Shape Shape) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Half == Half::Top) if (Shape == Shape::Straight) return 10710; else if (Shape == Shape::InnerLeft) return 10712; else if (Shape == Shape::InnerRight) return 10714; else if (Shape == Shape::OuterLeft) return 10716; else return 10718; else if (Shape == Shape::Straight) return 10720; else if (Shape == Shape::InnerLeft) return 10722; else if (Shape == Shape::InnerRight) return 10724; else if (Shape == Shape::OuterLeft) return 10726; else return 10728; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Half == Half::Top) if (Shape == Shape::Straight) return 10730; else if (Shape == Shape::InnerLeft) return 10732; else if (Shape == Shape::InnerRight) return 10734; else if (Shape == Shape::OuterLeft) return 10736; else return 10738; else if (Shape == Shape::Straight) return 10740; else if (Shape == Shape::InnerLeft) return 10742; else if (Shape == Shape::InnerRight) return 10744; else if (Shape == Shape::OuterLeft) return 10746; else return 10748; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Half == Half::Top) if (Shape == Shape::Straight) return 10750; else if (Shape == Shape::InnerLeft) return 10752; else if (Shape == Shape::InnerRight) return 10754; else if (Shape == Shape::OuterLeft) return 10756; else return 10758; else if (Shape == Shape::Straight) return 10760; else if (Shape == Shape::InnerLeft) return 10762; else if (Shape == Shape::InnerRight) return 10764; else if (Shape == Shape::OuterLeft) return 10766; else return 10768; else if (Half == Half::Top) if (Shape == Shape::Straight) return 10770; else if (Shape == Shape::InnerLeft) return 10772; else if (Shape == Shape::InnerRight) return 10774; else if (Shape == Shape::OuterLeft) return 10776; else return 10778; else if (Shape == Shape::Straight) return 10780; else if (Shape == Shape::InnerLeft) return 10782; else if (Shape == Shape::InnerRight) return 10784; else if (Shape == Shape::OuterLeft) return 10786; else return 10788; } BlockState DioriteStairs(); eBlockFace Facing(BlockState Block); enum Half Half(BlockState Block); enum Shape Shape(BlockState Block); } namespace DioriteWall { enum class East { None, Low, Tall }; enum class North { None, Low, Tall }; enum class South { None, Low, Tall }; enum class West { None, Low, Tall }; constexpr BlockState DioriteWall(const enum East East, const enum North North, const enum South South, const bool Up, const enum West West) { if (East == East::None) if (North == North::None) if (South == South::None) if (Up) if (West == West::None) return 14434; else if (West == West::Low) return 14435; else return 14436; else if (West == West::None) return 14440; else if (West == West::Low) return 14441; else return 14442; else if (South == South::Low) if (Up) if (West == West::None) return 14446; else if (West == West::Low) return 14447; else return 14448; else if (West == West::None) return 14452; else if (West == West::Low) return 14453; else return 14454; else if (Up) if (West == West::None) return 14458; else if (West == West::Low) return 14459; else return 14460; else if (West == West::None) return 14464; else if (West == West::Low) return 14465; else return 14466; else if (North == North::Low) if (South == South::None) if (Up) if (West == West::None) return 14470; else if (West == West::Low) return 14471; else return 14472; else if (West == West::None) return 14476; else if (West == West::Low) return 14477; else return 14478; else if (South == South::Low) if (Up) if (West == West::None) return 14482; else if (West == West::Low) return 14483; else return 14484; else if (West == West::None) return 14488; else if (West == West::Low) return 14489; else return 14490; else if (Up) if (West == West::None) return 14494; else if (West == West::Low) return 14495; else return 14496; else if (West == West::None) return 14500; else if (West == West::Low) return 14501; else return 14502; else if (South == South::None) if (Up) if (West == West::None) return 14506; else if (West == West::Low) return 14507; else return 14508; else if (West == West::None) return 14512; else if (West == West::Low) return 14513; else return 14514; else if (South == South::Low) if (Up) if (West == West::None) return 14518; else if (West == West::Low) return 14519; else return 14520; else if (West == West::None) return 14524; else if (West == West::Low) return 14525; else return 14526; else if (Up) if (West == West::None) return 14530; else if (West == West::Low) return 14531; else return 14532; else if (West == West::None) return 14536; else if (West == West::Low) return 14537; else return 14538; else if (East == East::Low) if (North == North::None) if (South == South::None) if (Up) if (West == West::None) return 14542; else if (West == West::Low) return 14543; else return 14544; else if (West == West::None) return 14548; else if (West == West::Low) return 14549; else return 14550; else if (South == South::Low) if (Up) if (West == West::None) return 14554; else if (West == West::Low) return 14555; else return 14556; else if (West == West::None) return 14560; else if (West == West::Low) return 14561; else return 14562; else if (Up) if (West == West::None) return 14566; else if (West == West::Low) return 14567; else return 14568; else if (West == West::None) return 14572; else if (West == West::Low) return 14573; else return 14574; else if (North == North::Low) if (South == South::None) if (Up) if (West == West::None) return 14578; else if (West == West::Low) return 14579; else return 14580; else if (West == West::None) return 14584; else if (West == West::Low) return 14585; else return 14586; else if (South == South::Low) if (Up) if (West == West::None) return 14590; else if (West == West::Low) return 14591; else return 14592; else if (West == West::None) return 14596; else if (West == West::Low) return 14597; else return 14598; else if (Up) if (West == West::None) return 14602; else if (West == West::Low) return 14603; else return 14604; else if (West == West::None) return 14608; else if (West == West::Low) return 14609; else return 14610; else if (South == South::None) if (Up) if (West == West::None) return 14614; else if (West == West::Low) return 14615; else return 14616; else if (West == West::None) return 14620; else if (West == West::Low) return 14621; else return 14622; else if (South == South::Low) if (Up) if (West == West::None) return 14626; else if (West == West::Low) return 14627; else return 14628; else if (West == West::None) return 14632; else if (West == West::Low) return 14633; else return 14634; else if (Up) if (West == West::None) return 14638; else if (West == West::Low) return 14639; else return 14640; else if (West == West::None) return 14644; else if (West == West::Low) return 14645; else return 14646; else if (North == North::None) if (South == South::None) if (Up) if (West == West::None) return 14650; else if (West == West::Low) return 14651; else return 14652; else if (West == West::None) return 14656; else if (West == West::Low) return 14657; else return 14658; else if (South == South::Low) if (Up) if (West == West::None) return 14662; else if (West == West::Low) return 14663; else return 14664; else if (West == West::None) return 14668; else if (West == West::Low) return 14669; else return 14670; else if (Up) if (West == West::None) return 14674; else if (West == West::Low) return 14675; else return 14676; else if (West == West::None) return 14680; else if (West == West::Low) return 14681; else return 14682; else if (North == North::Low) if (South == South::None) if (Up) if (West == West::None) return 14686; else if (West == West::Low) return 14687; else return 14688; else if (West == West::None) return 14692; else if (West == West::Low) return 14693; else return 14694; else if (South == South::Low) if (Up) if (West == West::None) return 14698; else if (West == West::Low) return 14699; else return 14700; else if (West == West::None) return 14704; else if (West == West::Low) return 14705; else return 14706; else if (Up) if (West == West::None) return 14710; else if (West == West::Low) return 14711; else return 14712; else if (West == West::None) return 14716; else if (West == West::Low) return 14717; else return 14718; else if (South == South::None) if (Up) if (West == West::None) return 14722; else if (West == West::Low) return 14723; else return 14724; else if (West == West::None) return 14728; else if (West == West::Low) return 14729; else return 14730; else if (South == South::Low) if (Up) if (West == West::None) return 14734; else if (West == West::Low) return 14735; else return 14736; else if (West == West::None) return 14740; else if (West == West::Low) return 14741; else return 14742; else if (Up) if (West == West::None) return 14746; else if (West == West::Low) return 14747; else return 14748; else if (West == West::None) return 14752; else if (West == West::Low) return 14753; else return 14754; } BlockState DioriteWall(); enum East East(BlockState Block); enum North North(BlockState Block); enum South South(BlockState Block); bool Up(BlockState Block); enum West West(BlockState Block); } namespace Dirt { constexpr BlockState Dirt() { return 10; } } namespace Dispenser { constexpr BlockState Dispenser(const eBlockFace Facing, const bool Triggered) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Triggered) return 234; else return 235; else if (Facing == eBlockFace::BLOCK_FACE_XP) if (Triggered) return 236; else return 237; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Triggered) return 238; else return 239; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Triggered) return 240; else return 241; else if (Facing == eBlockFace::BLOCK_FACE_YP) if (Triggered) return 242; else return 243; else if (Triggered) return 244; else return 245; } BlockState Dispenser(); eBlockFace Facing(BlockState Block); bool Triggered(BlockState Block); } namespace DragonEgg { constexpr BlockState DragonEgg() { return 5155; } } namespace DragonHead { constexpr BlockState DragonHead(const unsigned char Rotation) { if (Rotation == 0) return 6590; else if (Rotation == 1) return 6591; else if (Rotation == 2) return 6592; else if (Rotation == 3) return 6593; else if (Rotation == 4) return 6594; else if (Rotation == 5) return 6595; else if (Rotation == 6) return 6596; else if (Rotation == 7) return 6597; else if (Rotation == 8) return 6598; else if (Rotation == 9) return 6599; else if (Rotation == 10) return 6600; else if (Rotation == 11) return 6601; else if (Rotation == 12) return 6602; else if (Rotation == 13) return 6603; else if (Rotation == 14) return 6604; else return 6605; } BlockState DragonHead(); unsigned char Rotation(BlockState Block); } namespace DragonWallHead { constexpr BlockState DragonWallHead(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 6606; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 6607; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 6608; else return 6609; } BlockState DragonWallHead(); eBlockFace Facing(BlockState Block); } namespace DriedKelpBlock { constexpr BlockState DriedKelpBlock() { return 9497; } } namespace Dropper { constexpr BlockState Dropper(const eBlockFace Facing, const bool Triggered) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Triggered) return 6835; else return 6836; else if (Facing == eBlockFace::BLOCK_FACE_XP) if (Triggered) return 6837; else return 6838; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Triggered) return 6839; else return 6840; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Triggered) return 6841; else return 6842; else if (Facing == eBlockFace::BLOCK_FACE_YP) if (Triggered) return 6843; else return 6844; else if (Triggered) return 6845; else return 6846; } BlockState Dropper(); eBlockFace Facing(BlockState Block); bool Triggered(BlockState Block); } namespace EmeraldBlock { constexpr BlockState EmeraldBlock() { return 5403; } } namespace EmeraldOre { constexpr BlockState EmeraldOre() { return 5250; } } namespace EnchantingTable { constexpr BlockState EnchantingTable() { return 5132; } } namespace EndGateway { constexpr BlockState EndGateway() { return 9224; } } namespace EndPortal { constexpr BlockState EndPortal() { return 5145; } } namespace EndPortalFrame { constexpr BlockState EndPortalFrame(const bool Eye, const eBlockFace Facing) { if (Eye) if (Facing == eBlockFace::BLOCK_FACE_ZM) return 5146; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 5147; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 5148; else return 5149; else if (Facing == eBlockFace::BLOCK_FACE_ZM) return 5150; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 5151; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 5152; else return 5153; } BlockState EndPortalFrame(); bool Eye(BlockState Block); eBlockFace Facing(BlockState Block); } namespace EndRod { constexpr BlockState EndRod(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 9058; else if (Facing == eBlockFace::BLOCK_FACE_XP) return 9059; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 9060; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 9061; else if (Facing == eBlockFace::BLOCK_FACE_YP) return 9062; else return 9063; } BlockState EndRod(); eBlockFace Facing(BlockState Block); } namespace EndStone { constexpr BlockState EndStone() { return 5154; } } namespace EndStoneBrickSlab { enum class Type { Top, Bottom, Double }; constexpr BlockState EndStoneBrickSlab(const enum Type Type) { if (Type == Type::Top) return 10820; else if (Type == Type::Bottom) return 10822; else return 10824; } BlockState EndStoneBrickSlab(); enum Type Type(BlockState Block); } namespace EndStoneBrickStairs { enum class Half { Top, Bottom }; enum class Shape { Straight, InnerLeft, InnerRight, OuterLeft, OuterRight }; constexpr BlockState EndStoneBrickStairs(const eBlockFace Facing, const enum Half Half, const enum Shape Shape) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Half == Half::Top) if (Shape == Shape::Straight) return 10070; else if (Shape == Shape::InnerLeft) return 10072; else if (Shape == Shape::InnerRight) return 10074; else if (Shape == Shape::OuterLeft) return 10076; else return 10078; else if (Shape == Shape::Straight) return 10080; else if (Shape == Shape::InnerLeft) return 10082; else if (Shape == Shape::InnerRight) return 10084; else if (Shape == Shape::OuterLeft) return 10086; else return 10088; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Half == Half::Top) if (Shape == Shape::Straight) return 10090; else if (Shape == Shape::InnerLeft) return 10092; else if (Shape == Shape::InnerRight) return 10094; else if (Shape == Shape::OuterLeft) return 10096; else return 10098; else if (Shape == Shape::Straight) return 10100; else if (Shape == Shape::InnerLeft) return 10102; else if (Shape == Shape::InnerRight) return 10104; else if (Shape == Shape::OuterLeft) return 10106; else return 10108; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Half == Half::Top) if (Shape == Shape::Straight) return 10110; else if (Shape == Shape::InnerLeft) return 10112; else if (Shape == Shape::InnerRight) return 10114; else if (Shape == Shape::OuterLeft) return 10116; else return 10118; else if (Shape == Shape::Straight) return 10120; else if (Shape == Shape::InnerLeft) return 10122; else if (Shape == Shape::InnerRight) return 10124; else if (Shape == Shape::OuterLeft) return 10126; else return 10128; else if (Half == Half::Top) if (Shape == Shape::Straight) return 10130; else if (Shape == Shape::InnerLeft) return 10132; else if (Shape == Shape::InnerRight) return 10134; else if (Shape == Shape::OuterLeft) return 10136; else return 10138; else if (Shape == Shape::Straight) return 10140; else if (Shape == Shape::InnerLeft) return 10142; else if (Shape == Shape::InnerRight) return 10144; else if (Shape == Shape::OuterLeft) return 10146; else return 10148; } BlockState EndStoneBrickStairs(); eBlockFace Facing(BlockState Block); enum Half Half(BlockState Block); enum Shape Shape(BlockState Block); } namespace EndStoneBrickWall { enum class East { None, Low, Tall }; enum class North { None, Low, Tall }; enum class South { None, Low, Tall }; enum class West { None, Low, Tall }; constexpr BlockState EndStoneBrickWall(const enum East East, const enum North North, const enum South South, const bool Up, const enum West West) { if (East == East::None) if (North == North::None) if (South == South::None) if (Up) if (West == West::None) return 14110; else if (West == West::Low) return 14111; else return 14112; else if (West == West::None) return 14116; else if (West == West::Low) return 14117; else return 14118; else if (South == South::Low) if (Up) if (West == West::None) return 14122; else if (West == West::Low) return 14123; else return 14124; else if (West == West::None) return 14128; else if (West == West::Low) return 14129; else return 14130; else if (Up) if (West == West::None) return 14134; else if (West == West::Low) return 14135; else return 14136; else if (West == West::None) return 14140; else if (West == West::Low) return 14141; else return 14142; else if (North == North::Low) if (South == South::None) if (Up) if (West == West::None) return 14146; else if (West == West::Low) return 14147; else return 14148; else if (West == West::None) return 14152; else if (West == West::Low) return 14153; else return 14154; else if (South == South::Low) if (Up) if (West == West::None) return 14158; else if (West == West::Low) return 14159; else return 14160; else if (West == West::None) return 14164; else if (West == West::Low) return 14165; else return 14166; else if (Up) if (West == West::None) return 14170; else if (West == West::Low) return 14171; else return 14172; else if (West == West::None) return 14176; else if (West == West::Low) return 14177; else return 14178; else if (South == South::None) if (Up) if (West == West::None) return 14182; else if (West == West::Low) return 14183; else return 14184; else if (West == West::None) return 14188; else if (West == West::Low) return 14189; else return 14190; else if (South == South::Low) if (Up) if (West == West::None) return 14194; else if (West == West::Low) return 14195; else return 14196; else if (West == West::None) return 14200; else if (West == West::Low) return 14201; else return 14202; else if (Up) if (West == West::None) return 14206; else if (West == West::Low) return 14207; else return 14208; else if (West == West::None) return 14212; else if (West == West::Low) return 14213; else return 14214; else if (East == East::Low) if (North == North::None) if (South == South::None) if (Up) if (West == West::None) return 14218; else if (West == West::Low) return 14219; else return 14220; else if (West == West::None) return 14224; else if (West == West::Low) return 14225; else return 14226; else if (South == South::Low) if (Up) if (West == West::None) return 14230; else if (West == West::Low) return 14231; else return 14232; else if (West == West::None) return 14236; else if (West == West::Low) return 14237; else return 14238; else if (Up) if (West == West::None) return 14242; else if (West == West::Low) return 14243; else return 14244; else if (West == West::None) return 14248; else if (West == West::Low) return 14249; else return 14250; else if (North == North::Low) if (South == South::None) if (Up) if (West == West::None) return 14254; else if (West == West::Low) return 14255; else return 14256; else if (West == West::None) return 14260; else if (West == West::Low) return 14261; else return 14262; else if (South == South::Low) if (Up) if (West == West::None) return 14266; else if (West == West::Low) return 14267; else return 14268; else if (West == West::None) return 14272; else if (West == West::Low) return 14273; else return 14274; else if (Up) if (West == West::None) return 14278; else if (West == West::Low) return 14279; else return 14280; else if (West == West::None) return 14284; else if (West == West::Low) return 14285; else return 14286; else if (South == South::None) if (Up) if (West == West::None) return 14290; else if (West == West::Low) return 14291; else return 14292; else if (West == West::None) return 14296; else if (West == West::Low) return 14297; else return 14298; else if (South == South::Low) if (Up) if (West == West::None) return 14302; else if (West == West::Low) return 14303; else return 14304; else if (West == West::None) return 14308; else if (West == West::Low) return 14309; else return 14310; else if (Up) if (West == West::None) return 14314; else if (West == West::Low) return 14315; else return 14316; else if (West == West::None) return 14320; else if (West == West::Low) return 14321; else return 14322; else if (North == North::None) if (South == South::None) if (Up) if (West == West::None) return 14326; else if (West == West::Low) return 14327; else return 14328; else if (West == West::None) return 14332; else if (West == West::Low) return 14333; else return 14334; else if (South == South::Low) if (Up) if (West == West::None) return 14338; else if (West == West::Low) return 14339; else return 14340; else if (West == West::None) return 14344; else if (West == West::Low) return 14345; else return 14346; else if (Up) if (West == West::None) return 14350; else if (West == West::Low) return 14351; else return 14352; else if (West == West::None) return 14356; else if (West == West::Low) return 14357; else return 14358; else if (North == North::Low) if (South == South::None) if (Up) if (West == West::None) return 14362; else if (West == West::Low) return 14363; else return 14364; else if (West == West::None) return 14368; else if (West == West::Low) return 14369; else return 14370; else if (South == South::Low) if (Up) if (West == West::None) return 14374; else if (West == West::Low) return 14375; else return 14376; else if (West == West::None) return 14380; else if (West == West::Low) return 14381; else return 14382; else if (Up) if (West == West::None) return 14386; else if (West == West::Low) return 14387; else return 14388; else if (West == West::None) return 14392; else if (West == West::Low) return 14393; else return 14394; else if (South == South::None) if (Up) if (West == West::None) return 14398; else if (West == West::Low) return 14399; else return 14400; else if (West == West::None) return 14404; else if (West == West::Low) return 14405; else return 14406; else if (South == South::Low) if (Up) if (West == West::None) return 14410; else if (West == West::Low) return 14411; else return 14412; else if (West == West::None) return 14416; else if (West == West::Low) return 14417; else return 14418; else if (Up) if (West == West::None) return 14422; else if (West == West::Low) return 14423; else return 14424; else if (West == West::None) return 14428; else if (West == West::Low) return 14429; else return 14430; } BlockState EndStoneBrickWall(); enum East East(BlockState Block); enum North North(BlockState Block); enum South South(BlockState Block); bool Up(BlockState Block); enum West West(BlockState Block); } namespace EndStoneBricks { constexpr BlockState EndStoneBricks() { return 9218; } } namespace EnderChest { constexpr BlockState EnderChest(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 5252; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 5254; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 5256; else return 5258; } BlockState EnderChest(); eBlockFace Facing(BlockState Block); } namespace Farmland { constexpr BlockState Farmland(const unsigned char Moisture) { if (Moisture == 0) return 3365; else if (Moisture == 1) return 3366; else if (Moisture == 2) return 3367; else if (Moisture == 3) return 3368; else if (Moisture == 4) return 3369; else if (Moisture == 5) return 3370; else if (Moisture == 6) return 3371; else return 3372; } BlockState Farmland(); unsigned char Moisture(BlockState Block); } namespace Fern { constexpr BlockState Fern() { return 1343; } } namespace Fire { constexpr BlockState Fire(const unsigned char Age, const bool East, const bool North, const bool South, const bool Up, const bool West) { if (Age == 0) if (East) if (North) if (South) if (Up) if (West) return 1440; else return 1441; else if (West) return 1442; else return 1443; else if (Up) if (West) return 1444; else return 1445; else if (West) return 1446; else return 1447; else if (South) if (Up) if (West) return 1448; else return 1449; else if (West) return 1450; else return 1451; else if (Up) if (West) return 1452; else return 1453; else if (West) return 1454; else return 1455; else if (North) if (South) if (Up) if (West) return 1456; else return 1457; else if (West) return 1458; else return 1459; else if (Up) if (West) return 1460; else return 1461; else if (West) return 1462; else return 1463; else if (South) if (Up) if (West) return 1464; else return 1465; else if (West) return 1466; else return 1467; else if (Up) if (West) return 1468; else return 1469; else if (West) return 1470; else return 1471; else if (Age == 1) if (East) if (North) if (South) if (Up) if (West) return 1472; else return 1473; else if (West) return 1474; else return 1475; else if (Up) if (West) return 1476; else return 1477; else if (West) return 1478; else return 1479; else if (South) if (Up) if (West) return 1480; else return 1481; else if (West) return 1482; else return 1483; else if (Up) if (West) return 1484; else return 1485; else if (West) return 1486; else return 1487; else if (North) if (South) if (Up) if (West) return 1488; else return 1489; else if (West) return 1490; else return 1491; else if (Up) if (West) return 1492; else return 1493; else if (West) return 1494; else return 1495; else if (South) if (Up) if (West) return 1496; else return 1497; else if (West) return 1498; else return 1499; else if (Up) if (West) return 1500; else return 1501; else if (West) return 1502; else return 1503; else if (Age == 2) if (East) if (North) if (South) if (Up) if (West) return 1504; else return 1505; else if (West) return 1506; else return 1507; else if (Up) if (West) return 1508; else return 1509; else if (West) return 1510; else return 1511; else if (South) if (Up) if (West) return 1512; else return 1513; else if (West) return 1514; else return 1515; else if (Up) if (West) return 1516; else return 1517; else if (West) return 1518; else return 1519; else if (North) if (South) if (Up) if (West) return 1520; else return 1521; else if (West) return 1522; else return 1523; else if (Up) if (West) return 1524; else return 1525; else if (West) return 1526; else return 1527; else if (South) if (Up) if (West) return 1528; else return 1529; else if (West) return 1530; else return 1531; else if (Up) if (West) return 1532; else return 1533; else if (West) return 1534; else return 1535; else if (Age == 3) if (East) if (North) if (South) if (Up) if (West) return 1536; else return 1537; else if (West) return 1538; else return 1539; else if (Up) if (West) return 1540; else return 1541; else if (West) return 1542; else return 1543; else if (South) if (Up) if (West) return 1544; else return 1545; else if (West) return 1546; else return 1547; else if (Up) if (West) return 1548; else return 1549; else if (West) return 1550; else return 1551; else if (North) if (South) if (Up) if (West) return 1552; else return 1553; else if (West) return 1554; else return 1555; else if (Up) if (West) return 1556; else return 1557; else if (West) return 1558; else return 1559; else if (South) if (Up) if (West) return 1560; else return 1561; else if (West) return 1562; else return 1563; else if (Up) if (West) return 1564; else return 1565; else if (West) return 1566; else return 1567; else if (Age == 4) if (East) if (North) if (South) if (Up) if (West) return 1568; else return 1569; else if (West) return 1570; else return 1571; else if (Up) if (West) return 1572; else return 1573; else if (West) return 1574; else return 1575; else if (South) if (Up) if (West) return 1576; else return 1577; else if (West) return 1578; else return 1579; else if (Up) if (West) return 1580; else return 1581; else if (West) return 1582; else return 1583; else if (North) if (South) if (Up) if (West) return 1584; else return 1585; else if (West) return 1586; else return 1587; else if (Up) if (West) return 1588; else return 1589; else if (West) return 1590; else return 1591; else if (South) if (Up) if (West) return 1592; else return 1593; else if (West) return 1594; else return 1595; else if (Up) if (West) return 1596; else return 1597; else if (West) return 1598; else return 1599; else if (Age == 5) if (East) if (North) if (South) if (Up) if (West) return 1600; else return 1601; else if (West) return 1602; else return 1603; else if (Up) if (West) return 1604; else return 1605; else if (West) return 1606; else return 1607; else if (South) if (Up) if (West) return 1608; else return 1609; else if (West) return 1610; else return 1611; else if (Up) if (West) return 1612; else return 1613; else if (West) return 1614; else return 1615; else if (North) if (South) if (Up) if (West) return 1616; else return 1617; else if (West) return 1618; else return 1619; else if (Up) if (West) return 1620; else return 1621; else if (West) return 1622; else return 1623; else if (South) if (Up) if (West) return 1624; else return 1625; else if (West) return 1626; else return 1627; else if (Up) if (West) return 1628; else return 1629; else if (West) return 1630; else return 1631; else if (Age == 6) if (East) if (North) if (South) if (Up) if (West) return 1632; else return 1633; else if (West) return 1634; else return 1635; else if (Up) if (West) return 1636; else return 1637; else if (West) return 1638; else return 1639; else if (South) if (Up) if (West) return 1640; else return 1641; else if (West) return 1642; else return 1643; else if (Up) if (West) return 1644; else return 1645; else if (West) return 1646; else return 1647; else if (North) if (South) if (Up) if (West) return 1648; else return 1649; else if (West) return 1650; else return 1651; else if (Up) if (West) return 1652; else return 1653; else if (West) return 1654; else return 1655; else if (South) if (Up) if (West) return 1656; else return 1657; else if (West) return 1658; else return 1659; else if (Up) if (West) return 1660; else return 1661; else if (West) return 1662; else return 1663; else if (Age == 7) if (East) if (North) if (South) if (Up) if (West) return 1664; else return 1665; else if (West) return 1666; else return 1667; else if (Up) if (West) return 1668; else return 1669; else if (West) return 1670; else return 1671; else if (South) if (Up) if (West) return 1672; else return 1673; else if (West) return 1674; else return 1675; else if (Up) if (West) return 1676; else return 1677; else if (West) return 1678; else return 1679; else if (North) if (South) if (Up) if (West) return 1680; else return 1681; else if (West) return 1682; else return 1683; else if (Up) if (West) return 1684; else return 1685; else if (West) return 1686; else return 1687; else if (South) if (Up) if (West) return 1688; else return 1689; else if (West) return 1690; else return 1691; else if (Up) if (West) return 1692; else return 1693; else if (West) return 1694; else return 1695; else if (Age == 8) if (East) if (North) if (South) if (Up) if (West) return 1696; else return 1697; else if (West) return 1698; else return 1699; else if (Up) if (West) return 1700; else return 1701; else if (West) return 1702; else return 1703; else if (South) if (Up) if (West) return 1704; else return 1705; else if (West) return 1706; else return 1707; else if (Up) if (West) return 1708; else return 1709; else if (West) return 1710; else return 1711; else if (North) if (South) if (Up) if (West) return 1712; else return 1713; else if (West) return 1714; else return 1715; else if (Up) if (West) return 1716; else return 1717; else if (West) return 1718; else return 1719; else if (South) if (Up) if (West) return 1720; else return 1721; else if (West) return 1722; else return 1723; else if (Up) if (West) return 1724; else return 1725; else if (West) return 1726; else return 1727; else if (Age == 9) if (East) if (North) if (South) if (Up) if (West) return 1728; else return 1729; else if (West) return 1730; else return 1731; else if (Up) if (West) return 1732; else return 1733; else if (West) return 1734; else return 1735; else if (South) if (Up) if (West) return 1736; else return 1737; else if (West) return 1738; else return 1739; else if (Up) if (West) return 1740; else return 1741; else if (West) return 1742; else return 1743; else if (North) if (South) if (Up) if (West) return 1744; else return 1745; else if (West) return 1746; else return 1747; else if (Up) if (West) return 1748; else return 1749; else if (West) return 1750; else return 1751; else if (South) if (Up) if (West) return 1752; else return 1753; else if (West) return 1754; else return 1755; else if (Up) if (West) return 1756; else return 1757; else if (West) return 1758; else return 1759; else if (Age == 10) if (East) if (North) if (South) if (Up) if (West) return 1760; else return 1761; else if (West) return 1762; else return 1763; else if (Up) if (West) return 1764; else return 1765; else if (West) return 1766; else return 1767; else if (South) if (Up) if (West) return 1768; else return 1769; else if (West) return 1770; else return 1771; else if (Up) if (West) return 1772; else return 1773; else if (West) return 1774; else return 1775; else if (North) if (South) if (Up) if (West) return 1776; else return 1777; else if (West) return 1778; else return 1779; else if (Up) if (West) return 1780; else return 1781; else if (West) return 1782; else return 1783; else if (South) if (Up) if (West) return 1784; else return 1785; else if (West) return 1786; else return 1787; else if (Up) if (West) return 1788; else return 1789; else if (West) return 1790; else return 1791; else if (Age == 11) if (East) if (North) if (South) if (Up) if (West) return 1792; else return 1793; else if (West) return 1794; else return 1795; else if (Up) if (West) return 1796; else return 1797; else if (West) return 1798; else return 1799; else if (South) if (Up) if (West) return 1800; else return 1801; else if (West) return 1802; else return 1803; else if (Up) if (West) return 1804; else return 1805; else if (West) return 1806; else return 1807; else if (North) if (South) if (Up) if (West) return 1808; else return 1809; else if (West) return 1810; else return 1811; else if (Up) if (West) return 1812; else return 1813; else if (West) return 1814; else return 1815; else if (South) if (Up) if (West) return 1816; else return 1817; else if (West) return 1818; else return 1819; else if (Up) if (West) return 1820; else return 1821; else if (West) return 1822; else return 1823; else if (Age == 12) if (East) if (North) if (South) if (Up) if (West) return 1824; else return 1825; else if (West) return 1826; else return 1827; else if (Up) if (West) return 1828; else return 1829; else if (West) return 1830; else return 1831; else if (South) if (Up) if (West) return 1832; else return 1833; else if (West) return 1834; else return 1835; else if (Up) if (West) return 1836; else return 1837; else if (West) return 1838; else return 1839; else if (North) if (South) if (Up) if (West) return 1840; else return 1841; else if (West) return 1842; else return 1843; else if (Up) if (West) return 1844; else return 1845; else if (West) return 1846; else return 1847; else if (South) if (Up) if (West) return 1848; else return 1849; else if (West) return 1850; else return 1851; else if (Up) if (West) return 1852; else return 1853; else if (West) return 1854; else return 1855; else if (Age == 13) if (East) if (North) if (South) if (Up) if (West) return 1856; else return 1857; else if (West) return 1858; else return 1859; else if (Up) if (West) return 1860; else return 1861; else if (West) return 1862; else return 1863; else if (South) if (Up) if (West) return 1864; else return 1865; else if (West) return 1866; else return 1867; else if (Up) if (West) return 1868; else return 1869; else if (West) return 1870; else return 1871; else if (North) if (South) if (Up) if (West) return 1872; else return 1873; else if (West) return 1874; else return 1875; else if (Up) if (West) return 1876; else return 1877; else if (West) return 1878; else return 1879; else if (South) if (Up) if (West) return 1880; else return 1881; else if (West) return 1882; else return 1883; else if (Up) if (West) return 1884; else return 1885; else if (West) return 1886; else return 1887; else if (Age == 14) if (East) if (North) if (South) if (Up) if (West) return 1888; else return 1889; else if (West) return 1890; else return 1891; else if (Up) if (West) return 1892; else return 1893; else if (West) return 1894; else return 1895; else if (South) if (Up) if (West) return 1896; else return 1897; else if (West) return 1898; else return 1899; else if (Up) if (West) return 1900; else return 1901; else if (West) return 1902; else return 1903; else if (North) if (South) if (Up) if (West) return 1904; else return 1905; else if (West) return 1906; else return 1907; else if (Up) if (West) return 1908; else return 1909; else if (West) return 1910; else return 1911; else if (South) if (Up) if (West) return 1912; else return 1913; else if (West) return 1914; else return 1915; else if (Up) if (West) return 1916; else return 1917; else if (West) return 1918; else return 1919; else if (East) if (North) if (South) if (Up) if (West) return 1920; else return 1921; else if (West) return 1922; else return 1923; else if (Up) if (West) return 1924; else return 1925; else if (West) return 1926; else return 1927; else if (South) if (Up) if (West) return 1928; else return 1929; else if (West) return 1930; else return 1931; else if (Up) if (West) return 1932; else return 1933; else if (West) return 1934; else return 1935; else if (North) if (South) if (Up) if (West) return 1936; else return 1937; else if (West) return 1938; else return 1939; else if (Up) if (West) return 1940; else return 1941; else if (West) return 1942; else return 1943; else if (South) if (Up) if (West) return 1944; else return 1945; else if (West) return 1946; else return 1947; else if (Up) if (West) return 1948; else return 1949; else if (West) return 1950; else return 1951; } BlockState Fire(); unsigned char Age(BlockState Block); bool East(BlockState Block); bool North(BlockState Block); bool South(BlockState Block); bool Up(BlockState Block); bool West(BlockState Block); } namespace FireCoral { constexpr BlockState FireCoral() { return 9537; } } namespace FireCoralBlock { constexpr BlockState FireCoralBlock() { return 9518; } } namespace FireCoralFan { constexpr BlockState FireCoralFan() { return 9557; } } namespace FireCoralWallFan { constexpr BlockState FireCoralWallFan(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 9625; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 9627; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 9629; else return 9631; } BlockState FireCoralWallFan(); eBlockFace Facing(BlockState Block); } namespace FletchingTable { constexpr BlockState FletchingTable() { return 14820; } } namespace FlowerPot { constexpr BlockState FlowerPot() { return 6305; } } namespace FrostedIce { constexpr BlockState FrostedIce(const unsigned char Age) { if (Age == 0) return 9249; else if (Age == 1) return 9250; else if (Age == 2) return 9251; else return 9252; } BlockState FrostedIce(); unsigned char Age(BlockState Block); } namespace Furnace { constexpr BlockState Furnace(const eBlockFace Facing, const bool Lit) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Lit) return 3373; else return 3374; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Lit) return 3375; else return 3376; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Lit) return 3377; else return 3378; else if (Lit) return 3379; else return 3380; } BlockState Furnace(); eBlockFace Facing(BlockState Block); bool Lit(BlockState Block); } namespace GildedBlackstone { constexpr BlockState GildedBlackstone() { return 16664; } } namespace Glass { constexpr BlockState Glass() { return 231; } } namespace GlassPane { constexpr BlockState GlassPane(const bool East, const bool North, const bool South, const bool West) { if (East) if (North) if (South) if (West) return 4733; else return 4734; else if (West) return 4737; else return 4738; else if (South) if (West) return 4741; else return 4742; else if (West) return 4745; else return 4746; else if (North) if (South) if (West) return 4749; else return 4750; else if (West) return 4753; else return 4754; else if (South) if (West) return 4757; else return 4758; else if (West) return 4761; else return 4762; } BlockState GlassPane(); bool East(BlockState Block); bool North(BlockState Block); bool South(BlockState Block); bool West(BlockState Block); } namespace Glowstone { constexpr BlockState Glowstone() { return 4013; } } namespace GoldBlock { constexpr BlockState GoldBlock() { return 1427; } } namespace GoldOre { constexpr BlockState GoldOre() { return 69; } } namespace Granite { constexpr BlockState Granite() { return 2; } } namespace GraniteSlab { enum class Type { Top, Bottom, Double }; constexpr BlockState GraniteSlab(const enum Type Type) { if (Type == Type::Top) return 10838; else if (Type == Type::Bottom) return 10840; else return 10842; } BlockState GraniteSlab(); enum Type Type(BlockState Block); } namespace GraniteStairs { enum class Half { Top, Bottom }; enum class Shape { Straight, InnerLeft, InnerRight, OuterLeft, OuterRight }; constexpr BlockState GraniteStairs(const eBlockFace Facing, const enum Half Half, const enum Shape Shape) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Half == Half::Top) if (Shape == Shape::Straight) return 10390; else if (Shape == Shape::InnerLeft) return 10392; else if (Shape == Shape::InnerRight) return 10394; else if (Shape == Shape::OuterLeft) return 10396; else return 10398; else if (Shape == Shape::Straight) return 10400; else if (Shape == Shape::InnerLeft) return 10402; else if (Shape == Shape::InnerRight) return 10404; else if (Shape == Shape::OuterLeft) return 10406; else return 10408; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Half == Half::Top) if (Shape == Shape::Straight) return 10410; else if (Shape == Shape::InnerLeft) return 10412; else if (Shape == Shape::InnerRight) return 10414; else if (Shape == Shape::OuterLeft) return 10416; else return 10418; else if (Shape == Shape::Straight) return 10420; else if (Shape == Shape::InnerLeft) return 10422; else if (Shape == Shape::InnerRight) return 10424; else if (Shape == Shape::OuterLeft) return 10426; else return 10428; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Half == Half::Top) if (Shape == Shape::Straight) return 10430; else if (Shape == Shape::InnerLeft) return 10432; else if (Shape == Shape::InnerRight) return 10434; else if (Shape == Shape::OuterLeft) return 10436; else return 10438; else if (Shape == Shape::Straight) return 10440; else if (Shape == Shape::InnerLeft) return 10442; else if (Shape == Shape::InnerRight) return 10444; else if (Shape == Shape::OuterLeft) return 10446; else return 10448; else if (Half == Half::Top) if (Shape == Shape::Straight) return 10450; else if (Shape == Shape::InnerLeft) return 10452; else if (Shape == Shape::InnerRight) return 10454; else if (Shape == Shape::OuterLeft) return 10456; else return 10458; else if (Shape == Shape::Straight) return 10460; else if (Shape == Shape::InnerLeft) return 10462; else if (Shape == Shape::InnerRight) return 10464; else if (Shape == Shape::OuterLeft) return 10466; else return 10468; } BlockState GraniteStairs(); eBlockFace Facing(BlockState Block); enum Half Half(BlockState Block); enum Shape Shape(BlockState Block); } namespace GraniteWall { enum class East { None, Low, Tall }; enum class North { None, Low, Tall }; enum class South { None, Low, Tall }; enum class West { None, Low, Tall }; constexpr BlockState GraniteWall(const enum East East, const enum North North, const enum South South, const bool Up, const enum West West) { if (East == East::None) if (North == North::None) if (South == South::None) if (Up) if (West == West::None) return 12166; else if (West == West::Low) return 12167; else return 12168; else if (West == West::None) return 12172; else if (West == West::Low) return 12173; else return 12174; else if (South == South::Low) if (Up) if (West == West::None) return 12178; else if (West == West::Low) return 12179; else return 12180; else if (West == West::None) return 12184; else if (West == West::Low) return 12185; else return 12186; else if (Up) if (West == West::None) return 12190; else if (West == West::Low) return 12191; else return 12192; else if (West == West::None) return 12196; else if (West == West::Low) return 12197; else return 12198; else if (North == North::Low) if (South == South::None) if (Up) if (West == West::None) return 12202; else if (West == West::Low) return 12203; else return 12204; else if (West == West::None) return 12208; else if (West == West::Low) return 12209; else return 12210; else if (South == South::Low) if (Up) if (West == West::None) return 12214; else if (West == West::Low) return 12215; else return 12216; else if (West == West::None) return 12220; else if (West == West::Low) return 12221; else return 12222; else if (Up) if (West == West::None) return 12226; else if (West == West::Low) return 12227; else return 12228; else if (West == West::None) return 12232; else if (West == West::Low) return 12233; else return 12234; else if (South == South::None) if (Up) if (West == West::None) return 12238; else if (West == West::Low) return 12239; else return 12240; else if (West == West::None) return 12244; else if (West == West::Low) return 12245; else return 12246; else if (South == South::Low) if (Up) if (West == West::None) return 12250; else if (West == West::Low) return 12251; else return 12252; else if (West == West::None) return 12256; else if (West == West::Low) return 12257; else return 12258; else if (Up) if (West == West::None) return 12262; else if (West == West::Low) return 12263; else return 12264; else if (West == West::None) return 12268; else if (West == West::Low) return 12269; else return 12270; else if (East == East::Low) if (North == North::None) if (South == South::None) if (Up) if (West == West::None) return 12274; else if (West == West::Low) return 12275; else return 12276; else if (West == West::None) return 12280; else if (West == West::Low) return 12281; else return 12282; else if (South == South::Low) if (Up) if (West == West::None) return 12286; else if (West == West::Low) return 12287; else return 12288; else if (West == West::None) return 12292; else if (West == West::Low) return 12293; else return 12294; else if (Up) if (West == West::None) return 12298; else if (West == West::Low) return 12299; else return 12300; else if (West == West::None) return 12304; else if (West == West::Low) return 12305; else return 12306; else if (North == North::Low) if (South == South::None) if (Up) if (West == West::None) return 12310; else if (West == West::Low) return 12311; else return 12312; else if (West == West::None) return 12316; else if (West == West::Low) return 12317; else return 12318; else if (South == South::Low) if (Up) if (West == West::None) return 12322; else if (West == West::Low) return 12323; else return 12324; else if (West == West::None) return 12328; else if (West == West::Low) return 12329; else return 12330; else if (Up) if (West == West::None) return 12334; else if (West == West::Low) return 12335; else return 12336; else if (West == West::None) return 12340; else if (West == West::Low) return 12341; else return 12342; else if (South == South::None) if (Up) if (West == West::None) return 12346; else if (West == West::Low) return 12347; else return 12348; else if (West == West::None) return 12352; else if (West == West::Low) return 12353; else return 12354; else if (South == South::Low) if (Up) if (West == West::None) return 12358; else if (West == West::Low) return 12359; else return 12360; else if (West == West::None) return 12364; else if (West == West::Low) return 12365; else return 12366; else if (Up) if (West == West::None) return 12370; else if (West == West::Low) return 12371; else return 12372; else if (West == West::None) return 12376; else if (West == West::Low) return 12377; else return 12378; else if (North == North::None) if (South == South::None) if (Up) if (West == West::None) return 12382; else if (West == West::Low) return 12383; else return 12384; else if (West == West::None) return 12388; else if (West == West::Low) return 12389; else return 12390; else if (South == South::Low) if (Up) if (West == West::None) return 12394; else if (West == West::Low) return 12395; else return 12396; else if (West == West::None) return 12400; else if (West == West::Low) return 12401; else return 12402; else if (Up) if (West == West::None) return 12406; else if (West == West::Low) return 12407; else return 12408; else if (West == West::None) return 12412; else if (West == West::Low) return 12413; else return 12414; else if (North == North::Low) if (South == South::None) if (Up) if (West == West::None) return 12418; else if (West == West::Low) return 12419; else return 12420; else if (West == West::None) return 12424; else if (West == West::Low) return 12425; else return 12426; else if (South == South::Low) if (Up) if (West == West::None) return 12430; else if (West == West::Low) return 12431; else return 12432; else if (West == West::None) return 12436; else if (West == West::Low) return 12437; else return 12438; else if (Up) if (West == West::None) return 12442; else if (West == West::Low) return 12443; else return 12444; else if (West == West::None) return 12448; else if (West == West::Low) return 12449; else return 12450; else if (South == South::None) if (Up) if (West == West::None) return 12454; else if (West == West::Low) return 12455; else return 12456; else if (West == West::None) return 12460; else if (West == West::Low) return 12461; else return 12462; else if (South == South::Low) if (Up) if (West == West::None) return 12466; else if (West == West::Low) return 12467; else return 12468; else if (West == West::None) return 12472; else if (West == West::Low) return 12473; else return 12474; else if (Up) if (West == West::None) return 12478; else if (West == West::Low) return 12479; else return 12480; else if (West == West::None) return 12484; else if (West == West::Low) return 12485; else return 12486; } BlockState GraniteWall(); enum East East(BlockState Block); enum North North(BlockState Block); enum South South(BlockState Block); bool Up(BlockState Block); enum West West(BlockState Block); } namespace Grass { constexpr BlockState Grass() { return 1342; } } namespace GrassBlock { constexpr BlockState GrassBlock(const bool Snowy) { if (Snowy) return 8; else return 9; } BlockState GrassBlock(); bool Snowy(BlockState Block); } namespace GrassPath { constexpr BlockState GrassPath() { return 9223; } } namespace Gravel { constexpr BlockState Gravel() { return 68; } } namespace GrayBanner { constexpr BlockState GrayBanner(const unsigned char Rotation) { if (Rotation == 0) return 8009; else if (Rotation == 1) return 8010; else if (Rotation == 2) return 8011; else if (Rotation == 3) return 8012; else if (Rotation == 4) return 8013; else if (Rotation == 5) return 8014; else if (Rotation == 6) return 8015; else if (Rotation == 7) return 8016; else if (Rotation == 8) return 8017; else if (Rotation == 9) return 8018; else if (Rotation == 10) return 8019; else if (Rotation == 11) return 8020; else if (Rotation == 12) return 8021; else if (Rotation == 13) return 8022; else if (Rotation == 14) return 8023; else return 8024; } BlockState GrayBanner(); unsigned char Rotation(BlockState Block); } namespace GrayBed { enum class Part { Head, Foot }; constexpr BlockState GrayBed(const eBlockFace Facing, const bool Occupied, const enum Part Part) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Occupied) if (Part == Part::Head) return 1161; else return 1162; else if (Part == Part::Head) return 1163; else return 1164; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Occupied) if (Part == Part::Head) return 1165; else return 1166; else if (Part == Part::Head) return 1167; else return 1168; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Occupied) if (Part == Part::Head) return 1169; else return 1170; else if (Part == Part::Head) return 1171; else return 1172; else if (Occupied) if (Part == Part::Head) return 1173; else return 1174; else if (Part == Part::Head) return 1175; else return 1176; } BlockState GrayBed(); eBlockFace Facing(BlockState Block); bool Occupied(BlockState Block); enum Part Part(BlockState Block); } namespace GrayCarpet { constexpr BlockState GrayCarpet() { return 7873; } } namespace GrayConcrete { constexpr BlockState GrayConcrete() { return 9445; } } namespace GrayConcretePowder { constexpr BlockState GrayConcretePowder() { return 9461; } } namespace GrayGlazedTerracotta { constexpr BlockState GrayGlazedTerracotta(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 9402; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 9403; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 9404; else return 9405; } BlockState GrayGlazedTerracotta(); eBlockFace Facing(BlockState Block); } namespace GrayShulkerBox { constexpr BlockState GrayShulkerBox(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 9320; else if (Facing == eBlockFace::BLOCK_FACE_XP) return 9321; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 9322; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 9323; else if (Facing == eBlockFace::BLOCK_FACE_YP) return 9324; else return 9325; } BlockState GrayShulkerBox(); eBlockFace Facing(BlockState Block); } namespace GrayStainedGlass { constexpr BlockState GrayStainedGlass() { return 4102; } } namespace GrayStainedGlassPane { constexpr BlockState GrayStainedGlassPane(const bool East, const bool North, const bool South, const bool West) { if (East) if (North) if (South) if (West) return 7089; else return 7090; else if (West) return 7093; else return 7094; else if (South) if (West) return 7097; else return 7098; else if (West) return 7101; else return 7102; else if (North) if (South) if (West) return 7105; else return 7106; else if (West) return 7109; else return 7110; else if (South) if (West) return 7113; else return 7114; else if (West) return 7117; else return 7118; } BlockState GrayStainedGlassPane(); bool East(BlockState Block); bool North(BlockState Block); bool South(BlockState Block); bool West(BlockState Block); } namespace GrayTerracotta { constexpr BlockState GrayTerracotta() { return 6854; } } namespace GrayWallBanner { constexpr BlockState GrayWallBanner(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 8181; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 8182; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 8183; else return 8184; } BlockState GrayWallBanner(); eBlockFace Facing(BlockState Block); } namespace GrayWool { constexpr BlockState GrayWool() { return 1391; } } namespace GreenBanner { constexpr BlockState GreenBanner(const unsigned char Rotation) { if (Rotation == 0) return 8105; else if (Rotation == 1) return 8106; else if (Rotation == 2) return 8107; else if (Rotation == 3) return 8108; else if (Rotation == 4) return 8109; else if (Rotation == 5) return 8110; else if (Rotation == 6) return 8111; else if (Rotation == 7) return 8112; else if (Rotation == 8) return 8113; else if (Rotation == 9) return 8114; else if (Rotation == 10) return 8115; else if (Rotation == 11) return 8116; else if (Rotation == 12) return 8117; else if (Rotation == 13) return 8118; else if (Rotation == 14) return 8119; else return 8120; } BlockState GreenBanner(); unsigned char Rotation(BlockState Block); } namespace GreenBed { enum class Part { Head, Foot }; constexpr BlockState GreenBed(const eBlockFace Facing, const bool Occupied, const enum Part Part) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Occupied) if (Part == Part::Head) return 1257; else return 1258; else if (Part == Part::Head) return 1259; else return 1260; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Occupied) if (Part == Part::Head) return 1261; else return 1262; else if (Part == Part::Head) return 1263; else return 1264; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Occupied) if (Part == Part::Head) return 1265; else return 1266; else if (Part == Part::Head) return 1267; else return 1268; else if (Occupied) if (Part == Part::Head) return 1269; else return 1270; else if (Part == Part::Head) return 1271; else return 1272; } BlockState GreenBed(); eBlockFace Facing(BlockState Block); bool Occupied(BlockState Block); enum Part Part(BlockState Block); } namespace GreenCarpet { constexpr BlockState GreenCarpet() { return 7879; } } namespace GreenConcrete { constexpr BlockState GreenConcrete() { return 9451; } } namespace GreenConcretePowder { constexpr BlockState GreenConcretePowder() { return 9467; } } namespace GreenGlazedTerracotta { constexpr BlockState GreenGlazedTerracotta(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 9426; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 9427; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 9428; else return 9429; } BlockState GreenGlazedTerracotta(); eBlockFace Facing(BlockState Block); } namespace GreenShulkerBox { constexpr BlockState GreenShulkerBox(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 9356; else if (Facing == eBlockFace::BLOCK_FACE_XP) return 9357; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 9358; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 9359; else if (Facing == eBlockFace::BLOCK_FACE_YP) return 9360; else return 9361; } BlockState GreenShulkerBox(); eBlockFace Facing(BlockState Block); } namespace GreenStainedGlass { constexpr BlockState GreenStainedGlass() { return 4108; } } namespace GreenStainedGlassPane { constexpr BlockState GreenStainedGlassPane(const bool East, const bool North, const bool South, const bool West) { if (East) if (North) if (South) if (West) return 7281; else return 7282; else if (West) return 7285; else return 7286; else if (South) if (West) return 7289; else return 7290; else if (West) return 7293; else return 7294; else if (North) if (South) if (West) return 7297; else return 7298; else if (West) return 7301; else return 7302; else if (South) if (West) return 7305; else return 7306; else if (West) return 7309; else return 7310; } BlockState GreenStainedGlassPane(); bool East(BlockState Block); bool North(BlockState Block); bool South(BlockState Block); bool West(BlockState Block); } namespace GreenTerracotta { constexpr BlockState GreenTerracotta() { return 6860; } } namespace GreenWallBanner { constexpr BlockState GreenWallBanner(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 8205; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 8206; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 8207; else return 8208; } BlockState GreenWallBanner(); eBlockFace Facing(BlockState Block); } namespace GreenWool { constexpr BlockState GreenWool() { return 1397; } } namespace Grindstone { enum class Face { Floor, Wall, Ceiling }; constexpr BlockState Grindstone(const enum Face Face, const eBlockFace Facing) { if (Face == Face::Floor) if (Facing == eBlockFace::BLOCK_FACE_ZM) return 14821; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 14822; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 14823; else return 14824; else if (Face == Face::Wall) if (Facing == eBlockFace::BLOCK_FACE_ZM) return 14825; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 14826; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 14827; else return 14828; else if (Facing == eBlockFace::BLOCK_FACE_ZM) return 14829; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 14830; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 14831; else return 14832; } BlockState Grindstone(); enum Face Face(BlockState Block); eBlockFace Facing(BlockState Block); } namespace HayBale { enum class Axis { X, Y, Z }; constexpr BlockState HayBale(const enum Axis Axis) { if (Axis == Axis::X) return 7863; else if (Axis == Axis::Y) return 7864; else return 7865; } BlockState HayBale(); enum Axis Axis(BlockState Block); } namespace HeavyWeightedPressurePlate { constexpr BlockState HeavyWeightedPressurePlate(const unsigned char Power) { if (Power == 0) return 6662; else if (Power == 1) return 6663; else if (Power == 2) return 6664; else if (Power == 3) return 6665; else if (Power == 4) return 6666; else if (Power == 5) return 6667; else if (Power == 6) return 6668; else if (Power == 7) return 6669; else if (Power == 8) return 6670; else if (Power == 9) return 6671; else if (Power == 10) return 6672; else if (Power == 11) return 6673; else if (Power == 12) return 6674; else if (Power == 13) return 6675; else if (Power == 14) return 6676; else return 6677; } BlockState HeavyWeightedPressurePlate(); unsigned char Power(BlockState Block); } namespace HoneyBlock { constexpr BlockState HoneyBlock() { return 15824; } } namespace HoneycombBlock { constexpr BlockState HoneycombBlock() { return 15825; } } namespace Hopper { constexpr BlockState Hopper(const bool Enabled, const eBlockFace Facing) { if (Enabled) if (Facing == eBlockFace::BLOCK_FACE_YM) return 6728; else if (Facing == eBlockFace::BLOCK_FACE_ZM) return 6729; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 6730; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 6731; else return 6732; else if (Facing == eBlockFace::BLOCK_FACE_YM) return 6733; else if (Facing == eBlockFace::BLOCK_FACE_ZM) return 6734; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 6735; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 6736; else return 6737; } BlockState Hopper(); bool Enabled(BlockState Block); eBlockFace Facing(BlockState Block); } namespace HornCoral { constexpr BlockState HornCoral() { return 9539; } } namespace HornCoralBlock { constexpr BlockState HornCoralBlock() { return 9519; } } namespace HornCoralFan { constexpr BlockState HornCoralFan() { return 9559; } } namespace HornCoralWallFan { constexpr BlockState HornCoralWallFan(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 9633; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 9635; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 9637; else return 9639; } BlockState HornCoralWallFan(); eBlockFace Facing(BlockState Block); } namespace Ice { constexpr BlockState Ice() { return 3929; } } namespace InfestedChiseledStoneBricks { constexpr BlockState InfestedChiseledStoneBricks() { return 4504; } } namespace InfestedCobblestone { constexpr BlockState InfestedCobblestone() { return 4500; } } namespace InfestedCrackedStoneBricks { constexpr BlockState InfestedCrackedStoneBricks() { return 4503; } } namespace InfestedMossyStoneBricks { constexpr BlockState InfestedMossyStoneBricks() { return 4502; } } namespace InfestedStone { constexpr BlockState InfestedStone() { return 4499; } } namespace InfestedStoneBricks { constexpr BlockState InfestedStoneBricks() { return 4501; } } namespace IronBars { constexpr BlockState IronBars(const bool East, const bool North, const bool South, const bool West) { if (East) if (North) if (South) if (West) return 4699; else return 4700; else if (West) return 4703; else return 4704; else if (South) if (West) return 4707; else return 4708; else if (West) return 4711; else return 4712; else if (North) if (South) if (West) return 4715; else return 4716; else if (West) return 4719; else return 4720; else if (South) if (West) return 4723; else return 4724; else if (West) return 4727; else return 4728; } BlockState IronBars(); bool East(BlockState Block); bool North(BlockState Block); bool South(BlockState Block); bool West(BlockState Block); } namespace IronBlock { constexpr BlockState IronBlock() { return 1428; } } namespace IronDoor { enum class Half { Upper, Lower }; enum class Hinge { Left, Right }; constexpr BlockState IronDoor(const eBlockFace Facing, const enum Half Half, const enum Hinge Hinge, const bool Open, const bool Powered) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Half == Half::Upper) if (Hinge == Hinge::Left) if (Open) if (Powered) return 3809; else return 3810; else if (Powered) return 3811; else return 3812; else if (Open) if (Powered) return 3813; else return 3814; else if (Powered) return 3815; else return 3816; else if (Hinge == Hinge::Left) if (Open) if (Powered) return 3817; else return 3818; else if (Powered) return 3819; else return 3820; else if (Open) if (Powered) return 3821; else return 3822; else if (Powered) return 3823; else return 3824; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Half == Half::Upper) if (Hinge == Hinge::Left) if (Open) if (Powered) return 3825; else return 3826; else if (Powered) return 3827; else return 3828; else if (Open) if (Powered) return 3829; else return 3830; else if (Powered) return 3831; else return 3832; else if (Hinge == Hinge::Left) if (Open) if (Powered) return 3833; else return 3834; else if (Powered) return 3835; else return 3836; else if (Open) if (Powered) return 3837; else return 3838; else if (Powered) return 3839; else return 3840; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Half == Half::Upper) if (Hinge == Hinge::Left) if (Open) if (Powered) return 3841; else return 3842; else if (Powered) return 3843; else return 3844; else if (Open) if (Powered) return 3845; else return 3846; else if (Powered) return 3847; else return 3848; else if (Hinge == Hinge::Left) if (Open) if (Powered) return 3849; else return 3850; else if (Powered) return 3851; else return 3852; else if (Open) if (Powered) return 3853; else return 3854; else if (Powered) return 3855; else return 3856; else if (Half == Half::Upper) if (Hinge == Hinge::Left) if (Open) if (Powered) return 3857; else return 3858; else if (Powered) return 3859; else return 3860; else if (Open) if (Powered) return 3861; else return 3862; else if (Powered) return 3863; else return 3864; else if (Hinge == Hinge::Left) if (Open) if (Powered) return 3865; else return 3866; else if (Powered) return 3867; else return 3868; else if (Open) if (Powered) return 3869; else return 3870; else if (Powered) return 3871; else return 3872; } BlockState IronDoor(); eBlockFace Facing(BlockState Block); enum Half Half(BlockState Block); enum Hinge Hinge(BlockState Block); bool Open(BlockState Block); bool Powered(BlockState Block); } namespace IronOre { constexpr BlockState IronOre() { return 70; } } namespace IronTrapdoor { enum class Half { Top, Bottom }; constexpr BlockState IronTrapdoor(const eBlockFace Facing, const enum Half Half, const bool Open, const bool Powered) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Half == Half::Top) if (Open) if (Powered) return 7538; else return 7540; else if (Powered) return 7542; else return 7544; else if (Open) if (Powered) return 7546; else return 7548; else if (Powered) return 7550; else return 7552; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Half == Half::Top) if (Open) if (Powered) return 7554; else return 7556; else if (Powered) return 7558; else return 7560; else if (Open) if (Powered) return 7562; else return 7564; else if (Powered) return 7566; else return 7568; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Half == Half::Top) if (Open) if (Powered) return 7570; else return 7572; else if (Powered) return 7574; else return 7576; else if (Open) if (Powered) return 7578; else return 7580; else if (Powered) return 7582; else return 7584; else if (Half == Half::Top) if (Open) if (Powered) return 7586; else return 7588; else if (Powered) return 7590; else return 7592; else if (Open) if (Powered) return 7594; else return 7596; else if (Powered) return 7598; else return 7600; } BlockState IronTrapdoor(); eBlockFace Facing(BlockState Block); enum Half Half(BlockState Block); bool Open(BlockState Block); bool Powered(BlockState Block); } namespace JackOLantern { constexpr BlockState JackOLantern(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 4020; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 4021; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 4022; else return 4023; } BlockState JackOLantern(); eBlockFace Facing(BlockState Block); } namespace Jigsaw { enum class Orientation { DownEast, DownNorth, DownSouth, DownWest, UpEast, UpNorth, UpSouth, UpWest, WestUp, EastUp, NorthUp, SouthUp }; constexpr BlockState Jigsaw(const enum Orientation Orientation) { if (Orientation == Orientation::DownEast) return 15739; else if (Orientation == Orientation::DownNorth) return 15740; else if (Orientation == Orientation::DownSouth) return 15741; else if (Orientation == Orientation::DownWest) return 15742; else if (Orientation == Orientation::UpEast) return 15743; else if (Orientation == Orientation::UpNorth) return 15744; else if (Orientation == Orientation::UpSouth) return 15745; else if (Orientation == Orientation::UpWest) return 15746; else if (Orientation == Orientation::WestUp) return 15747; else if (Orientation == Orientation::EastUp) return 15748; else if (Orientation == Orientation::NorthUp) return 15749; else return 15750; } BlockState Jigsaw(); enum Orientation Orientation(BlockState Block); } namespace Jukebox { constexpr BlockState Jukebox(const bool HasRecord) { if (HasRecord) return 3964; else return 3965; } BlockState Jukebox(); bool HasRecord(BlockState Block); } namespace JungleButton { enum class Face { Floor, Wall, Ceiling }; constexpr BlockState JungleButton(const enum Face Face, const eBlockFace Facing, const bool Powered) { if (Face == Face::Floor) if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Powered) return 6418; else return 6419; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Powered) return 6420; else return 6421; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Powered) return 6422; else return 6423; else if (Powered) return 6424; else return 6425; else if (Face == Face::Wall) if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Powered) return 6426; else return 6427; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Powered) return 6428; else return 6429; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Powered) return 6430; else return 6431; else if (Powered) return 6432; else return 6433; else if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Powered) return 6434; else return 6435; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Powered) return 6436; else return 6437; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Powered) return 6438; else return 6439; else if (Powered) return 6440; else return 6441; } BlockState JungleButton(); enum Face Face(BlockState Block); eBlockFace Facing(BlockState Block); bool Powered(BlockState Block); } namespace JungleDoor { enum class Half { Upper, Lower }; enum class Hinge { Left, Right }; constexpr BlockState JungleDoor(const eBlockFace Facing, const enum Half Half, const enum Hinge Hinge, const bool Open, const bool Powered) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Half == Half::Upper) if (Hinge == Hinge::Left) if (Open) if (Powered) return 8866; else return 8867; else if (Powered) return 8868; else return 8869; else if (Open) if (Powered) return 8870; else return 8871; else if (Powered) return 8872; else return 8873; else if (Hinge == Hinge::Left) if (Open) if (Powered) return 8874; else return 8875; else if (Powered) return 8876; else return 8877; else if (Open) if (Powered) return 8878; else return 8879; else if (Powered) return 8880; else return 8881; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Half == Half::Upper) if (Hinge == Hinge::Left) if (Open) if (Powered) return 8882; else return 8883; else if (Powered) return 8884; else return 8885; else if (Open) if (Powered) return 8886; else return 8887; else if (Powered) return 8888; else return 8889; else if (Hinge == Hinge::Left) if (Open) if (Powered) return 8890; else return 8891; else if (Powered) return 8892; else return 8893; else if (Open) if (Powered) return 8894; else return 8895; else if (Powered) return 8896; else return 8897; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Half == Half::Upper) if (Hinge == Hinge::Left) if (Open) if (Powered) return 8898; else return 8899; else if (Powered) return 8900; else return 8901; else if (Open) if (Powered) return 8902; else return 8903; else if (Powered) return 8904; else return 8905; else if (Hinge == Hinge::Left) if (Open) if (Powered) return 8906; else return 8907; else if (Powered) return 8908; else return 8909; else if (Open) if (Powered) return 8910; else return 8911; else if (Powered) return 8912; else return 8913; else if (Half == Half::Upper) if (Hinge == Hinge::Left) if (Open) if (Powered) return 8914; else return 8915; else if (Powered) return 8916; else return 8917; else if (Open) if (Powered) return 8918; else return 8919; else if (Powered) return 8920; else return 8921; else if (Hinge == Hinge::Left) if (Open) if (Powered) return 8922; else return 8923; else if (Powered) return 8924; else return 8925; else if (Open) if (Powered) return 8926; else return 8927; else if (Powered) return 8928; else return 8929; } BlockState JungleDoor(); eBlockFace Facing(BlockState Block); enum Half Half(BlockState Block); enum Hinge Hinge(BlockState Block); bool Open(BlockState Block); bool Powered(BlockState Block); } namespace JungleFence { constexpr BlockState JungleFence(const bool East, const bool North, const bool South, const bool West) { if (East) if (North) if (South) if (West) return 8644; else return 8645; else if (West) return 8648; else return 8649; else if (South) if (West) return 8652; else return 8653; else if (West) return 8656; else return 8657; else if (North) if (South) if (West) return 8660; else return 8661; else if (West) return 8664; else return 8665; else if (South) if (West) return 8668; else return 8669; else if (West) return 8672; else return 8673; } BlockState JungleFence(); bool East(BlockState Block); bool North(BlockState Block); bool South(BlockState Block); bool West(BlockState Block); } namespace JungleFenceGate { constexpr BlockState JungleFenceGate(const eBlockFace Facing, const bool InWall, const bool Open, const bool Powered) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (InWall) if (Open) if (Powered) return 8482; else return 8483; else if (Powered) return 8484; else return 8485; else if (Open) if (Powered) return 8486; else return 8487; else if (Powered) return 8488; else return 8489; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (InWall) if (Open) if (Powered) return 8490; else return 8491; else if (Powered) return 8492; else return 8493; else if (Open) if (Powered) return 8494; else return 8495; else if (Powered) return 8496; else return 8497; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (InWall) if (Open) if (Powered) return 8498; else return 8499; else if (Powered) return 8500; else return 8501; else if (Open) if (Powered) return 8502; else return 8503; else if (Powered) return 8504; else return 8505; else if (InWall) if (Open) if (Powered) return 8506; else return 8507; else if (Powered) return 8508; else return 8509; else if (Open) if (Powered) return 8510; else return 8511; else if (Powered) return 8512; else return 8513; } BlockState JungleFenceGate(); eBlockFace Facing(BlockState Block); bool InWall(BlockState Block); bool Open(BlockState Block); bool Powered(BlockState Block); } namespace JungleLeaves { constexpr BlockState JungleLeaves(const unsigned char Distance, const bool Persistent) { if (Distance == 1) if (Persistent) return 187; else return 188; else if (Distance == 2) if (Persistent) return 189; else return 190; else if (Distance == 3) if (Persistent) return 191; else return 192; else if (Distance == 4) if (Persistent) return 193; else return 194; else if (Distance == 5) if (Persistent) return 195; else return 196; else if (Distance == 6) if (Persistent) return 197; else return 198; else if (Persistent) return 199; else return 200; } BlockState JungleLeaves(); unsigned char Distance(BlockState Block); bool Persistent(BlockState Block); } namespace JungleLog { enum class Axis { X, Y, Z }; constexpr BlockState JungleLog(const enum Axis Axis) { if (Axis == Axis::X) return 82; else if (Axis == Axis::Y) return 83; else return 84; } BlockState JungleLog(); enum Axis Axis(BlockState Block); } namespace JunglePlanks { constexpr BlockState JunglePlanks() { return 18; } } namespace JunglePressurePlate { constexpr BlockState JunglePressurePlate(const bool Powered) { if (Powered) return 3879; else return 3880; } BlockState JunglePressurePlate(); bool Powered(BlockState Block); } namespace JungleSapling { constexpr BlockState JungleSapling(const unsigned char Stage) { if (Stage == 0) return 27; else return 28; } BlockState JungleSapling(); unsigned char Stage(BlockState Block); } namespace JungleSign { constexpr BlockState JungleSign(const unsigned char Rotation) { if (Rotation == 0) return 3510; else if (Rotation == 1) return 3512; else if (Rotation == 2) return 3514; else if (Rotation == 3) return 3516; else if (Rotation == 4) return 3518; else if (Rotation == 5) return 3520; else if (Rotation == 6) return 3522; else if (Rotation == 7) return 3524; else if (Rotation == 8) return 3526; else if (Rotation == 9) return 3528; else if (Rotation == 10) return 3530; else if (Rotation == 11) return 3532; else if (Rotation == 12) return 3534; else if (Rotation == 13) return 3536; else if (Rotation == 14) return 3538; else return 3540; } BlockState JungleSign(); unsigned char Rotation(BlockState Block); } namespace JungleSlab { enum class Type { Top, Bottom, Double }; constexpr BlockState JungleSlab(const enum Type Type) { if (Type == Type::Top) return 8319; else if (Type == Type::Bottom) return 8321; else return 8323; } BlockState JungleSlab(); enum Type Type(BlockState Block); } namespace JungleStairs { enum class Half { Top, Bottom }; enum class Shape { Straight, InnerLeft, InnerRight, OuterLeft, OuterRight }; constexpr BlockState JungleStairs(const eBlockFace Facing, const enum Half Half, const enum Shape Shape) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Half == Half::Top) if (Shape == Shape::Straight) return 5565; else if (Shape == Shape::InnerLeft) return 5567; else if (Shape == Shape::InnerRight) return 5569; else if (Shape == Shape::OuterLeft) return 5571; else return 5573; else if (Shape == Shape::Straight) return 5575; else if (Shape == Shape::InnerLeft) return 5577; else if (Shape == Shape::InnerRight) return 5579; else if (Shape == Shape::OuterLeft) return 5581; else return 5583; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Half == Half::Top) if (Shape == Shape::Straight) return 5585; else if (Shape == Shape::InnerLeft) return 5587; else if (Shape == Shape::InnerRight) return 5589; else if (Shape == Shape::OuterLeft) return 5591; else return 5593; else if (Shape == Shape::Straight) return 5595; else if (Shape == Shape::InnerLeft) return 5597; else if (Shape == Shape::InnerRight) return 5599; else if (Shape == Shape::OuterLeft) return 5601; else return 5603; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Half == Half::Top) if (Shape == Shape::Straight) return 5605; else if (Shape == Shape::InnerLeft) return 5607; else if (Shape == Shape::InnerRight) return 5609; else if (Shape == Shape::OuterLeft) return 5611; else return 5613; else if (Shape == Shape::Straight) return 5615; else if (Shape == Shape::InnerLeft) return 5617; else if (Shape == Shape::InnerRight) return 5619; else if (Shape == Shape::OuterLeft) return 5621; else return 5623; else if (Half == Half::Top) if (Shape == Shape::Straight) return 5625; else if (Shape == Shape::InnerLeft) return 5627; else if (Shape == Shape::InnerRight) return 5629; else if (Shape == Shape::OuterLeft) return 5631; else return 5633; else if (Shape == Shape::Straight) return 5635; else if (Shape == Shape::InnerLeft) return 5637; else if (Shape == Shape::InnerRight) return 5639; else if (Shape == Shape::OuterLeft) return 5641; else return 5643; } BlockState JungleStairs(); eBlockFace Facing(BlockState Block); enum Half Half(BlockState Block); enum Shape Shape(BlockState Block); } namespace JungleTrapdoor { enum class Half { Top, Bottom }; constexpr BlockState JungleTrapdoor(const eBlockFace Facing, const enum Half Half, const bool Open, const bool Powered) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Half == Half::Top) if (Open) if (Powered) return 4304; else return 4306; else if (Powered) return 4308; else return 4310; else if (Open) if (Powered) return 4312; else return 4314; else if (Powered) return 4316; else return 4318; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Half == Half::Top) if (Open) if (Powered) return 4320; else return 4322; else if (Powered) return 4324; else return 4326; else if (Open) if (Powered) return 4328; else return 4330; else if (Powered) return 4332; else return 4334; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Half == Half::Top) if (Open) if (Powered) return 4336; else return 4338; else if (Powered) return 4340; else return 4342; else if (Open) if (Powered) return 4344; else return 4346; else if (Powered) return 4348; else return 4350; else if (Half == Half::Top) if (Open) if (Powered) return 4352; else return 4354; else if (Powered) return 4356; else return 4358; else if (Open) if (Powered) return 4360; else return 4362; else if (Powered) return 4364; else return 4366; } BlockState JungleTrapdoor(); eBlockFace Facing(BlockState Block); enum Half Half(BlockState Block); bool Open(BlockState Block); bool Powered(BlockState Block); } namespace JungleWallSign { constexpr BlockState JungleWallSign(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 3768; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 3770; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 3772; else return 3774; } BlockState JungleWallSign(); eBlockFace Facing(BlockState Block); } namespace JungleWood { enum class Axis { X, Y, Z }; constexpr BlockState JungleWood(const enum Axis Axis) { if (Axis == Axis::X) return 118; else if (Axis == Axis::Y) return 119; else return 120; } BlockState JungleWood(); enum Axis Axis(BlockState Block); } namespace Kelp { constexpr BlockState Kelp(const unsigned char Age) { if (Age == 0) return 9470; else if (Age == 1) return 9471; else if (Age == 2) return 9472; else if (Age == 3) return 9473; else if (Age == 4) return 9474; else if (Age == 5) return 9475; else if (Age == 6) return 9476; else if (Age == 7) return 9477; else if (Age == 8) return 9478; else if (Age == 9) return 9479; else if (Age == 10) return 9480; else if (Age == 11) return 9481; else if (Age == 12) return 9482; else if (Age == 13) return 9483; else if (Age == 14) return 9484; else if (Age == 15) return 9485; else if (Age == 16) return 9486; else if (Age == 17) return 9487; else if (Age == 18) return 9488; else if (Age == 19) return 9489; else if (Age == 20) return 9490; else if (Age == 21) return 9491; else if (Age == 22) return 9492; else if (Age == 23) return 9493; else if (Age == 24) return 9494; else return 9495; } BlockState Kelp(); unsigned char Age(BlockState Block); } namespace KelpPlant { constexpr BlockState KelpPlant() { return 9496; } } namespace Ladder { constexpr BlockState Ladder(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 3638; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 3640; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 3642; else return 3644; } BlockState Ladder(); eBlockFace Facing(BlockState Block); } namespace Lantern { constexpr BlockState Lantern(const bool Hanging) { if (Hanging) return 14886; else return 14887; } BlockState Lantern(); bool Hanging(BlockState Block); } namespace LapisBlock { constexpr BlockState LapisBlock() { return 233; } } namespace LapisOre { constexpr BlockState LapisOre() { return 232; } } namespace LargeFern { enum class Half { Upper, Lower }; constexpr BlockState LargeFern(const enum Half Half) { if (Half == Half::Upper) return 7895; else return 7896; } BlockState LargeFern(); enum Half Half(BlockState Block); } namespace Lava { constexpr BlockState Lava(const unsigned char Level) { if (Level == 0) return 50; else if (Level == 1) return 51; else if (Level == 2) return 52; else if (Level == 3) return 53; else if (Level == 4) return 54; else if (Level == 5) return 55; else if (Level == 6) return 56; else if (Level == 7) return 57; else if (Level == 8) return 58; else if (Level == 9) return 59; else if (Level == 10) return 60; else if (Level == 11) return 61; else if (Level == 12) return 62; else if (Level == 13) return 63; else if (Level == 14) return 64; else return 65; } BlockState Lava(); unsigned char Level(BlockState Block); } namespace Lectern { constexpr BlockState Lectern(const eBlockFace Facing, const bool HasBook, const bool Powered) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (HasBook) if (Powered) return 14833; else return 14834; else if (Powered) return 14835; else return 14836; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (HasBook) if (Powered) return 14837; else return 14838; else if (Powered) return 14839; else return 14840; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (HasBook) if (Powered) return 14841; else return 14842; else if (Powered) return 14843; else return 14844; else if (HasBook) if (Powered) return 14845; else return 14846; else if (Powered) return 14847; else return 14848; } BlockState Lectern(); eBlockFace Facing(BlockState Block); bool HasBook(BlockState Block); bool Powered(BlockState Block); } namespace Lever { enum class Face { Floor, Wall, Ceiling }; constexpr BlockState Lever(const enum Face Face, const eBlockFace Facing, const bool Powered) { if (Face == Face::Floor) if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Powered) return 3783; else return 3784; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Powered) return 3785; else return 3786; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Powered) return 3787; else return 3788; else if (Powered) return 3789; else return 3790; else if (Face == Face::Wall) if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Powered) return 3791; else return 3792; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Powered) return 3793; else return 3794; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Powered) return 3795; else return 3796; else if (Powered) return 3797; else return 3798; else if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Powered) return 3799; else return 3800; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Powered) return 3801; else return 3802; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Powered) return 3803; else return 3804; else if (Powered) return 3805; else return 3806; } BlockState Lever(); enum Face Face(BlockState Block); eBlockFace Facing(BlockState Block); bool Powered(BlockState Block); } namespace LightBlueBanner { constexpr BlockState LightBlueBanner(const unsigned char Rotation) { if (Rotation == 0) return 7945; else if (Rotation == 1) return 7946; else if (Rotation == 2) return 7947; else if (Rotation == 3) return 7948; else if (Rotation == 4) return 7949; else if (Rotation == 5) return 7950; else if (Rotation == 6) return 7951; else if (Rotation == 7) return 7952; else if (Rotation == 8) return 7953; else if (Rotation == 9) return 7954; else if (Rotation == 10) return 7955; else if (Rotation == 11) return 7956; else if (Rotation == 12) return 7957; else if (Rotation == 13) return 7958; else if (Rotation == 14) return 7959; else return 7960; } BlockState LightBlueBanner(); unsigned char Rotation(BlockState Block); } namespace LightBlueBed { enum class Part { Head, Foot }; constexpr BlockState LightBlueBed(const eBlockFace Facing, const bool Occupied, const enum Part Part) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Occupied) if (Part == Part::Head) return 1097; else return 1098; else if (Part == Part::Head) return 1099; else return 1100; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Occupied) if (Part == Part::Head) return 1101; else return 1102; else if (Part == Part::Head) return 1103; else return 1104; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Occupied) if (Part == Part::Head) return 1105; else return 1106; else if (Part == Part::Head) return 1107; else return 1108; else if (Occupied) if (Part == Part::Head) return 1109; else return 1110; else if (Part == Part::Head) return 1111; else return 1112; } BlockState LightBlueBed(); eBlockFace Facing(BlockState Block); bool Occupied(BlockState Block); enum Part Part(BlockState Block); } namespace LightBlueCarpet { constexpr BlockState LightBlueCarpet() { return 7869; } } namespace LightBlueConcrete { constexpr BlockState LightBlueConcrete() { return 9441; } } namespace LightBlueConcretePowder { constexpr BlockState LightBlueConcretePowder() { return 9457; } } namespace LightBlueGlazedTerracotta { constexpr BlockState LightBlueGlazedTerracotta(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 9386; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 9387; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 9388; else return 9389; } BlockState LightBlueGlazedTerracotta(); eBlockFace Facing(BlockState Block); } namespace LightBlueShulkerBox { constexpr BlockState LightBlueShulkerBox(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 9296; else if (Facing == eBlockFace::BLOCK_FACE_XP) return 9297; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 9298; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 9299; else if (Facing == eBlockFace::BLOCK_FACE_YP) return 9300; else return 9301; } BlockState LightBlueShulkerBox(); eBlockFace Facing(BlockState Block); } namespace LightBlueStainedGlass { constexpr BlockState LightBlueStainedGlass() { return 4098; } } namespace LightBlueStainedGlassPane { constexpr BlockState LightBlueStainedGlassPane(const bool East, const bool North, const bool South, const bool West) { if (East) if (North) if (South) if (West) return 6961; else return 6962; else if (West) return 6965; else return 6966; else if (South) if (West) return 6969; else return 6970; else if (West) return 6973; else return 6974; else if (North) if (South) if (West) return 6977; else return 6978; else if (West) return 6981; else return 6982; else if (South) if (West) return 6985; else return 6986; else if (West) return 6989; else return 6990; } BlockState LightBlueStainedGlassPane(); bool East(BlockState Block); bool North(BlockState Block); bool South(BlockState Block); bool West(BlockState Block); } namespace LightBlueTerracotta { constexpr BlockState LightBlueTerracotta() { return 6850; } } namespace LightBlueWallBanner { constexpr BlockState LightBlueWallBanner(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 8165; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 8166; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 8167; else return 8168; } BlockState LightBlueWallBanner(); eBlockFace Facing(BlockState Block); } namespace LightBlueWool { constexpr BlockState LightBlueWool() { return 1387; } } namespace LightGrayBanner { constexpr BlockState LightGrayBanner(const unsigned char Rotation) { if (Rotation == 0) return 8025; else if (Rotation == 1) return 8026; else if (Rotation == 2) return 8027; else if (Rotation == 3) return 8028; else if (Rotation == 4) return 8029; else if (Rotation == 5) return 8030; else if (Rotation == 6) return 8031; else if (Rotation == 7) return 8032; else if (Rotation == 8) return 8033; else if (Rotation == 9) return 8034; else if (Rotation == 10) return 8035; else if (Rotation == 11) return 8036; else if (Rotation == 12) return 8037; else if (Rotation == 13) return 8038; else if (Rotation == 14) return 8039; else return 8040; } BlockState LightGrayBanner(); unsigned char Rotation(BlockState Block); } namespace LightGrayBed { enum class Part { Head, Foot }; constexpr BlockState LightGrayBed(const eBlockFace Facing, const bool Occupied, const enum Part Part) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Occupied) if (Part == Part::Head) return 1177; else return 1178; else if (Part == Part::Head) return 1179; else return 1180; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Occupied) if (Part == Part::Head) return 1181; else return 1182; else if (Part == Part::Head) return 1183; else return 1184; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Occupied) if (Part == Part::Head) return 1185; else return 1186; else if (Part == Part::Head) return 1187; else return 1188; else if (Occupied) if (Part == Part::Head) return 1189; else return 1190; else if (Part == Part::Head) return 1191; else return 1192; } BlockState LightGrayBed(); eBlockFace Facing(BlockState Block); bool Occupied(BlockState Block); enum Part Part(BlockState Block); } namespace LightGrayCarpet { constexpr BlockState LightGrayCarpet() { return 7874; } } namespace LightGrayConcrete { constexpr BlockState LightGrayConcrete() { return 9446; } } namespace LightGrayConcretePowder { constexpr BlockState LightGrayConcretePowder() { return 9462; } } namespace LightGrayGlazedTerracotta { constexpr BlockState LightGrayGlazedTerracotta(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 9406; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 9407; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 9408; else return 9409; } BlockState LightGrayGlazedTerracotta(); eBlockFace Facing(BlockState Block); } namespace LightGrayShulkerBox { constexpr BlockState LightGrayShulkerBox(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 9326; else if (Facing == eBlockFace::BLOCK_FACE_XP) return 9327; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 9328; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 9329; else if (Facing == eBlockFace::BLOCK_FACE_YP) return 9330; else return 9331; } BlockState LightGrayShulkerBox(); eBlockFace Facing(BlockState Block); } namespace LightGrayStainedGlass { constexpr BlockState LightGrayStainedGlass() { return 4103; } } namespace LightGrayStainedGlassPane { constexpr BlockState LightGrayStainedGlassPane(const bool East, const bool North, const bool South, const bool West) { if (East) if (North) if (South) if (West) return 7121; else return 7122; else if (West) return 7125; else return 7126; else if (South) if (West) return 7129; else return 7130; else if (West) return 7133; else return 7134; else if (North) if (South) if (West) return 7137; else return 7138; else if (West) return 7141; else return 7142; else if (South) if (West) return 7145; else return 7146; else if (West) return 7149; else return 7150; } BlockState LightGrayStainedGlassPane(); bool East(BlockState Block); bool North(BlockState Block); bool South(BlockState Block); bool West(BlockState Block); } namespace LightGrayTerracotta { constexpr BlockState LightGrayTerracotta() { return 6855; } } namespace LightGrayWallBanner { constexpr BlockState LightGrayWallBanner(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 8185; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 8186; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 8187; else return 8188; } BlockState LightGrayWallBanner(); eBlockFace Facing(BlockState Block); } namespace LightGrayWool { constexpr BlockState LightGrayWool() { return 1392; } } namespace LightWeightedPressurePlate { constexpr BlockState LightWeightedPressurePlate(const unsigned char Power) { if (Power == 0) return 6646; else if (Power == 1) return 6647; else if (Power == 2) return 6648; else if (Power == 3) return 6649; else if (Power == 4) return 6650; else if (Power == 5) return 6651; else if (Power == 6) return 6652; else if (Power == 7) return 6653; else if (Power == 8) return 6654; else if (Power == 9) return 6655; else if (Power == 10) return 6656; else if (Power == 11) return 6657; else if (Power == 12) return 6658; else if (Power == 13) return 6659; else if (Power == 14) return 6660; else return 6661; } BlockState LightWeightedPressurePlate(); unsigned char Power(BlockState Block); } namespace Lilac { enum class Half { Upper, Lower }; constexpr BlockState Lilac(const enum Half Half) { if (Half == Half::Upper) return 7887; else return 7888; } BlockState Lilac(); enum Half Half(BlockState Block); } namespace LilyOfTheValley { constexpr BlockState LilyOfTheValley() { return 1424; } } namespace LilyPad { constexpr BlockState LilyPad() { return 5014; } } namespace LimeBanner { constexpr BlockState LimeBanner(const unsigned char Rotation) { if (Rotation == 0) return 7977; else if (Rotation == 1) return 7978; else if (Rotation == 2) return 7979; else if (Rotation == 3) return 7980; else if (Rotation == 4) return 7981; else if (Rotation == 5) return 7982; else if (Rotation == 6) return 7983; else if (Rotation == 7) return 7984; else if (Rotation == 8) return 7985; else if (Rotation == 9) return 7986; else if (Rotation == 10) return 7987; else if (Rotation == 11) return 7988; else if (Rotation == 12) return 7989; else if (Rotation == 13) return 7990; else if (Rotation == 14) return 7991; else return 7992; } BlockState LimeBanner(); unsigned char Rotation(BlockState Block); } namespace LimeBed { enum class Part { Head, Foot }; constexpr BlockState LimeBed(const eBlockFace Facing, const bool Occupied, const enum Part Part) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Occupied) if (Part == Part::Head) return 1129; else return 1130; else if (Part == Part::Head) return 1131; else return 1132; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Occupied) if (Part == Part::Head) return 1133; else return 1134; else if (Part == Part::Head) return 1135; else return 1136; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Occupied) if (Part == Part::Head) return 1137; else return 1138; else if (Part == Part::Head) return 1139; else return 1140; else if (Occupied) if (Part == Part::Head) return 1141; else return 1142; else if (Part == Part::Head) return 1143; else return 1144; } BlockState LimeBed(); eBlockFace Facing(BlockState Block); bool Occupied(BlockState Block); enum Part Part(BlockState Block); } namespace LimeCarpet { constexpr BlockState LimeCarpet() { return 7871; } } namespace LimeConcrete { constexpr BlockState LimeConcrete() { return 9443; } } namespace LimeConcretePowder { constexpr BlockState LimeConcretePowder() { return 9459; } } namespace LimeGlazedTerracotta { constexpr BlockState LimeGlazedTerracotta(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 9394; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 9395; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 9396; else return 9397; } BlockState LimeGlazedTerracotta(); eBlockFace Facing(BlockState Block); } namespace LimeShulkerBox { constexpr BlockState LimeShulkerBox(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 9308; else if (Facing == eBlockFace::BLOCK_FACE_XP) return 9309; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 9310; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 9311; else if (Facing == eBlockFace::BLOCK_FACE_YP) return 9312; else return 9313; } BlockState LimeShulkerBox(); eBlockFace Facing(BlockState Block); } namespace LimeStainedGlass { constexpr BlockState LimeStainedGlass() { return 4100; } } namespace LimeStainedGlassPane { constexpr BlockState LimeStainedGlassPane(const bool East, const bool North, const bool South, const bool West) { if (East) if (North) if (South) if (West) return 7025; else return 7026; else if (West) return 7029; else return 7030; else if (South) if (West) return 7033; else return 7034; else if (West) return 7037; else return 7038; else if (North) if (South) if (West) return 7041; else return 7042; else if (West) return 7045; else return 7046; else if (South) if (West) return 7049; else return 7050; else if (West) return 7053; else return 7054; } BlockState LimeStainedGlassPane(); bool East(BlockState Block); bool North(BlockState Block); bool South(BlockState Block); bool West(BlockState Block); } namespace LimeTerracotta { constexpr BlockState LimeTerracotta() { return 6852; } } namespace LimeWallBanner { constexpr BlockState LimeWallBanner(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 8173; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 8174; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 8175; else return 8176; } BlockState LimeWallBanner(); eBlockFace Facing(BlockState Block); } namespace LimeWool { constexpr BlockState LimeWool() { return 1389; } } namespace Lodestone { constexpr BlockState Lodestone() { return 15838; } } namespace Loom { constexpr BlockState Loom(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 14787; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 14788; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 14789; else return 14790; } BlockState Loom(); eBlockFace Facing(BlockState Block); } namespace MagentaBanner { constexpr BlockState MagentaBanner(const unsigned char Rotation) { if (Rotation == 0) return 7929; else if (Rotation == 1) return 7930; else if (Rotation == 2) return 7931; else if (Rotation == 3) return 7932; else if (Rotation == 4) return 7933; else if (Rotation == 5) return 7934; else if (Rotation == 6) return 7935; else if (Rotation == 7) return 7936; else if (Rotation == 8) return 7937; else if (Rotation == 9) return 7938; else if (Rotation == 10) return 7939; else if (Rotation == 11) return 7940; else if (Rotation == 12) return 7941; else if (Rotation == 13) return 7942; else if (Rotation == 14) return 7943; else return 7944; } BlockState MagentaBanner(); unsigned char Rotation(BlockState Block); } namespace MagentaBed { enum class Part { Head, Foot }; constexpr BlockState MagentaBed(const eBlockFace Facing, const bool Occupied, const enum Part Part) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Occupied) if (Part == Part::Head) return 1081; else return 1082; else if (Part == Part::Head) return 1083; else return 1084; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Occupied) if (Part == Part::Head) return 1085; else return 1086; else if (Part == Part::Head) return 1087; else return 1088; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Occupied) if (Part == Part::Head) return 1089; else return 1090; else if (Part == Part::Head) return 1091; else return 1092; else if (Occupied) if (Part == Part::Head) return 1093; else return 1094; else if (Part == Part::Head) return 1095; else return 1096; } BlockState MagentaBed(); eBlockFace Facing(BlockState Block); bool Occupied(BlockState Block); enum Part Part(BlockState Block); } namespace MagentaCarpet { constexpr BlockState MagentaCarpet() { return 7868; } } namespace MagentaConcrete { constexpr BlockState MagentaConcrete() { return 9440; } } namespace MagentaConcretePowder { constexpr BlockState MagentaConcretePowder() { return 9456; } } namespace MagentaGlazedTerracotta { constexpr BlockState MagentaGlazedTerracotta(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 9382; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 9383; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 9384; else return 9385; } BlockState MagentaGlazedTerracotta(); eBlockFace Facing(BlockState Block); } namespace MagentaShulkerBox { constexpr BlockState MagentaShulkerBox(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 9290; else if (Facing == eBlockFace::BLOCK_FACE_XP) return 9291; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 9292; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 9293; else if (Facing == eBlockFace::BLOCK_FACE_YP) return 9294; else return 9295; } BlockState MagentaShulkerBox(); eBlockFace Facing(BlockState Block); } namespace MagentaStainedGlass { constexpr BlockState MagentaStainedGlass() { return 4097; } } namespace MagentaStainedGlassPane { constexpr BlockState MagentaStainedGlassPane(const bool East, const bool North, const bool South, const bool West) { if (East) if (North) if (South) if (West) return 6929; else return 6930; else if (West) return 6933; else return 6934; else if (South) if (West) return 6937; else return 6938; else if (West) return 6941; else return 6942; else if (North) if (South) if (West) return 6945; else return 6946; else if (West) return 6949; else return 6950; else if (South) if (West) return 6953; else return 6954; else if (West) return 6957; else return 6958; } BlockState MagentaStainedGlassPane(); bool East(BlockState Block); bool North(BlockState Block); bool South(BlockState Block); bool West(BlockState Block); } namespace MagentaTerracotta { constexpr BlockState MagentaTerracotta() { return 6849; } } namespace MagentaWallBanner { constexpr BlockState MagentaWallBanner(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 8161; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 8162; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 8163; else return 8164; } BlockState MagentaWallBanner(); eBlockFace Facing(BlockState Block); } namespace MagentaWool { constexpr BlockState MagentaWool() { return 1386; } } namespace MagmaBlock { constexpr BlockState MagmaBlock() { return 9253; } } namespace Melon { constexpr BlockState Melon() { return 4763; } } namespace MelonStem { constexpr BlockState MelonStem(const unsigned char Age) { if (Age == 0) return 4780; else if (Age == 1) return 4781; else if (Age == 2) return 4782; else if (Age == 3) return 4783; else if (Age == 4) return 4784; else if (Age == 5) return 4785; else if (Age == 6) return 4786; else return 4787; } BlockState MelonStem(); unsigned char Age(BlockState Block); } namespace MossyCobblestone { constexpr BlockState MossyCobblestone() { return 1433; } } namespace MossyCobblestoneSlab { enum class Type { Top, Bottom, Double }; constexpr BlockState MossyCobblestoneSlab(const enum Type Type) { if (Type == Type::Top) return 10814; else if (Type == Type::Bottom) return 10816; else return 10818; } BlockState MossyCobblestoneSlab(); enum Type Type(BlockState Block); } namespace MossyCobblestoneStairs { enum class Half { Top, Bottom }; enum class Shape { Straight, InnerLeft, InnerRight, OuterLeft, OuterRight }; constexpr BlockState MossyCobblestoneStairs(const eBlockFace Facing, const enum Half Half, const enum Shape Shape) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Half == Half::Top) if (Shape == Shape::Straight) return 9990; else if (Shape == Shape::InnerLeft) return 9992; else if (Shape == Shape::InnerRight) return 9994; else if (Shape == Shape::OuterLeft) return 9996; else return 9998; else if (Shape == Shape::Straight) return 10000; else if (Shape == Shape::InnerLeft) return 10002; else if (Shape == Shape::InnerRight) return 10004; else if (Shape == Shape::OuterLeft) return 10006; else return 10008; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Half == Half::Top) if (Shape == Shape::Straight) return 10010; else if (Shape == Shape::InnerLeft) return 10012; else if (Shape == Shape::InnerRight) return 10014; else if (Shape == Shape::OuterLeft) return 10016; else return 10018; else if (Shape == Shape::Straight) return 10020; else if (Shape == Shape::InnerLeft) return 10022; else if (Shape == Shape::InnerRight) return 10024; else if (Shape == Shape::OuterLeft) return 10026; else return 10028; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Half == Half::Top) if (Shape == Shape::Straight) return 10030; else if (Shape == Shape::InnerLeft) return 10032; else if (Shape == Shape::InnerRight) return 10034; else if (Shape == Shape::OuterLeft) return 10036; else return 10038; else if (Shape == Shape::Straight) return 10040; else if (Shape == Shape::InnerLeft) return 10042; else if (Shape == Shape::InnerRight) return 10044; else if (Shape == Shape::OuterLeft) return 10046; else return 10048; else if (Half == Half::Top) if (Shape == Shape::Straight) return 10050; else if (Shape == Shape::InnerLeft) return 10052; else if (Shape == Shape::InnerRight) return 10054; else if (Shape == Shape::OuterLeft) return 10056; else return 10058; else if (Shape == Shape::Straight) return 10060; else if (Shape == Shape::InnerLeft) return 10062; else if (Shape == Shape::InnerRight) return 10064; else if (Shape == Shape::OuterLeft) return 10066; else return 10068; } BlockState MossyCobblestoneStairs(); eBlockFace Facing(BlockState Block); enum Half Half(BlockState Block); enum Shape Shape(BlockState Block); } namespace MossyCobblestoneWall { enum class East { None, Low, Tall }; enum class North { None, Low, Tall }; enum class South { None, Low, Tall }; enum class West { None, Low, Tall }; constexpr BlockState MossyCobblestoneWall(const enum East East, const enum North North, const enum South South, const bool Up, const enum West West) { if (East == East::None) if (North == North::None) if (South == South::None) if (Up) if (West == West::None) return 5984; else if (West == West::Low) return 5985; else return 5986; else if (West == West::None) return 5990; else if (West == West::Low) return 5991; else return 5992; else if (South == South::Low) if (Up) if (West == West::None) return 5996; else if (West == West::Low) return 5997; else return 5998; else if (West == West::None) return 6002; else if (West == West::Low) return 6003; else return 6004; else if (Up) if (West == West::None) return 6008; else if (West == West::Low) return 6009; else return 6010; else if (West == West::None) return 6014; else if (West == West::Low) return 6015; else return 6016; else if (North == North::Low) if (South == South::None) if (Up) if (West == West::None) return 6020; else if (West == West::Low) return 6021; else return 6022; else if (West == West::None) return 6026; else if (West == West::Low) return 6027; else return 6028; else if (South == South::Low) if (Up) if (West == West::None) return 6032; else if (West == West::Low) return 6033; else return 6034; else if (West == West::None) return 6038; else if (West == West::Low) return 6039; else return 6040; else if (Up) if (West == West::None) return 6044; else if (West == West::Low) return 6045; else return 6046; else if (West == West::None) return 6050; else if (West == West::Low) return 6051; else return 6052; else if (South == South::None) if (Up) if (West == West::None) return 6056; else if (West == West::Low) return 6057; else return 6058; else if (West == West::None) return 6062; else if (West == West::Low) return 6063; else return 6064; else if (South == South::Low) if (Up) if (West == West::None) return 6068; else if (West == West::Low) return 6069; else return 6070; else if (West == West::None) return 6074; else if (West == West::Low) return 6075; else return 6076; else if (Up) if (West == West::None) return 6080; else if (West == West::Low) return 6081; else return 6082; else if (West == West::None) return 6086; else if (West == West::Low) return 6087; else return 6088; else if (East == East::Low) if (North == North::None) if (South == South::None) if (Up) if (West == West::None) return 6092; else if (West == West::Low) return 6093; else return 6094; else if (West == West::None) return 6098; else if (West == West::Low) return 6099; else return 6100; else if (South == South::Low) if (Up) if (West == West::None) return 6104; else if (West == West::Low) return 6105; else return 6106; else if (West == West::None) return 6110; else if (West == West::Low) return 6111; else return 6112; else if (Up) if (West == West::None) return 6116; else if (West == West::Low) return 6117; else return 6118; else if (West == West::None) return 6122; else if (West == West::Low) return 6123; else return 6124; else if (North == North::Low) if (South == South::None) if (Up) if (West == West::None) return 6128; else if (West == West::Low) return 6129; else return 6130; else if (West == West::None) return 6134; else if (West == West::Low) return 6135; else return 6136; else if (South == South::Low) if (Up) if (West == West::None) return 6140; else if (West == West::Low) return 6141; else return 6142; else if (West == West::None) return 6146; else if (West == West::Low) return 6147; else return 6148; else if (Up) if (West == West::None) return 6152; else if (West == West::Low) return 6153; else return 6154; else if (West == West::None) return 6158; else if (West == West::Low) return 6159; else return 6160; else if (South == South::None) if (Up) if (West == West::None) return 6164; else if (West == West::Low) return 6165; else return 6166; else if (West == West::None) return 6170; else if (West == West::Low) return 6171; else return 6172; else if (South == South::Low) if (Up) if (West == West::None) return 6176; else if (West == West::Low) return 6177; else return 6178; else if (West == West::None) return 6182; else if (West == West::Low) return 6183; else return 6184; else if (Up) if (West == West::None) return 6188; else if (West == West::Low) return 6189; else return 6190; else if (West == West::None) return 6194; else if (West == West::Low) return 6195; else return 6196; else if (North == North::None) if (South == South::None) if (Up) if (West == West::None) return 6200; else if (West == West::Low) return 6201; else return 6202; else if (West == West::None) return 6206; else if (West == West::Low) return 6207; else return 6208; else if (South == South::Low) if (Up) if (West == West::None) return 6212; else if (West == West::Low) return 6213; else return 6214; else if (West == West::None) return 6218; else if (West == West::Low) return 6219; else return 6220; else if (Up) if (West == West::None) return 6224; else if (West == West::Low) return 6225; else return 6226; else if (West == West::None) return 6230; else if (West == West::Low) return 6231; else return 6232; else if (North == North::Low) if (South == South::None) if (Up) if (West == West::None) return 6236; else if (West == West::Low) return 6237; else return 6238; else if (West == West::None) return 6242; else if (West == West::Low) return 6243; else return 6244; else if (South == South::Low) if (Up) if (West == West::None) return 6248; else if (West == West::Low) return 6249; else return 6250; else if (West == West::None) return 6254; else if (West == West::Low) return 6255; else return 6256; else if (Up) if (West == West::None) return 6260; else if (West == West::Low) return 6261; else return 6262; else if (West == West::None) return 6266; else if (West == West::Low) return 6267; else return 6268; else if (South == South::None) if (Up) if (West == West::None) return 6272; else if (West == West::Low) return 6273; else return 6274; else if (West == West::None) return 6278; else if (West == West::Low) return 6279; else return 6280; else if (South == South::Low) if (Up) if (West == West::None) return 6284; else if (West == West::Low) return 6285; else return 6286; else if (West == West::None) return 6290; else if (West == West::Low) return 6291; else return 6292; else if (Up) if (West == West::None) return 6296; else if (West == West::Low) return 6297; else return 6298; else if (West == West::None) return 6302; else if (West == West::Low) return 6303; else return 6304; } BlockState MossyCobblestoneWall(); enum East East(BlockState Block); enum North North(BlockState Block); enum South South(BlockState Block); bool Up(BlockState Block); enum West West(BlockState Block); } namespace MossyStoneBrickSlab { enum class Type { Top, Bottom, Double }; constexpr BlockState MossyStoneBrickSlab(const enum Type Type) { if (Type == Type::Top) return 10802; else if (Type == Type::Bottom) return 10804; else return 10806; } BlockState MossyStoneBrickSlab(); enum Type Type(BlockState Block); } namespace MossyStoneBrickStairs { enum class Half { Top, Bottom }; enum class Shape { Straight, InnerLeft, InnerRight, OuterLeft, OuterRight }; constexpr BlockState MossyStoneBrickStairs(const eBlockFace Facing, const enum Half Half, const enum Shape Shape) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Half == Half::Top) if (Shape == Shape::Straight) return 9830; else if (Shape == Shape::InnerLeft) return 9832; else if (Shape == Shape::InnerRight) return 9834; else if (Shape == Shape::OuterLeft) return 9836; else return 9838; else if (Shape == Shape::Straight) return 9840; else if (Shape == Shape::InnerLeft) return 9842; else if (Shape == Shape::InnerRight) return 9844; else if (Shape == Shape::OuterLeft) return 9846; else return 9848; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Half == Half::Top) if (Shape == Shape::Straight) return 9850; else if (Shape == Shape::InnerLeft) return 9852; else if (Shape == Shape::InnerRight) return 9854; else if (Shape == Shape::OuterLeft) return 9856; else return 9858; else if (Shape == Shape::Straight) return 9860; else if (Shape == Shape::InnerLeft) return 9862; else if (Shape == Shape::InnerRight) return 9864; else if (Shape == Shape::OuterLeft) return 9866; else return 9868; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Half == Half::Top) if (Shape == Shape::Straight) return 9870; else if (Shape == Shape::InnerLeft) return 9872; else if (Shape == Shape::InnerRight) return 9874; else if (Shape == Shape::OuterLeft) return 9876; else return 9878; else if (Shape == Shape::Straight) return 9880; else if (Shape == Shape::InnerLeft) return 9882; else if (Shape == Shape::InnerRight) return 9884; else if (Shape == Shape::OuterLeft) return 9886; else return 9888; else if (Half == Half::Top) if (Shape == Shape::Straight) return 9890; else if (Shape == Shape::InnerLeft) return 9892; else if (Shape == Shape::InnerRight) return 9894; else if (Shape == Shape::OuterLeft) return 9896; else return 9898; else if (Shape == Shape::Straight) return 9900; else if (Shape == Shape::InnerLeft) return 9902; else if (Shape == Shape::InnerRight) return 9904; else if (Shape == Shape::OuterLeft) return 9906; else return 9908; } BlockState MossyStoneBrickStairs(); eBlockFace Facing(BlockState Block); enum Half Half(BlockState Block); enum Shape Shape(BlockState Block); } namespace MossyStoneBrickWall { enum class East { None, Low, Tall }; enum class North { None, Low, Tall }; enum class South { None, Low, Tall }; enum class West { None, Low, Tall }; constexpr BlockState MossyStoneBrickWall(const enum East East, const enum North North, const enum South South, const bool Up, const enum West West) { if (East == East::None) if (North == North::None) if (South == South::None) if (Up) if (West == West::None) return 11842; else if (West == West::Low) return 11843; else return 11844; else if (West == West::None) return 11848; else if (West == West::Low) return 11849; else return 11850; else if (South == South::Low) if (Up) if (West == West::None) return 11854; else if (West == West::Low) return 11855; else return 11856; else if (West == West::None) return 11860; else if (West == West::Low) return 11861; else return 11862; else if (Up) if (West == West::None) return 11866; else if (West == West::Low) return 11867; else return 11868; else if (West == West::None) return 11872; else if (West == West::Low) return 11873; else return 11874; else if (North == North::Low) if (South == South::None) if (Up) if (West == West::None) return 11878; else if (West == West::Low) return 11879; else return 11880; else if (West == West::None) return 11884; else if (West == West::Low) return 11885; else return 11886; else if (South == South::Low) if (Up) if (West == West::None) return 11890; else if (West == West::Low) return 11891; else return 11892; else if (West == West::None) return 11896; else if (West == West::Low) return 11897; else return 11898; else if (Up) if (West == West::None) return 11902; else if (West == West::Low) return 11903; else return 11904; else if (West == West::None) return 11908; else if (West == West::Low) return 11909; else return 11910; else if (South == South::None) if (Up) if (West == West::None) return 11914; else if (West == West::Low) return 11915; else return 11916; else if (West == West::None) return 11920; else if (West == West::Low) return 11921; else return 11922; else if (South == South::Low) if (Up) if (West == West::None) return 11926; else if (West == West::Low) return 11927; else return 11928; else if (West == West::None) return 11932; else if (West == West::Low) return 11933; else return 11934; else if (Up) if (West == West::None) return 11938; else if (West == West::Low) return 11939; else return 11940; else if (West == West::None) return 11944; else if (West == West::Low) return 11945; else return 11946; else if (East == East::Low) if (North == North::None) if (South == South::None) if (Up) if (West == West::None) return 11950; else if (West == West::Low) return 11951; else return 11952; else if (West == West::None) return 11956; else if (West == West::Low) return 11957; else return 11958; else if (South == South::Low) if (Up) if (West == West::None) return 11962; else if (West == West::Low) return 11963; else return 11964; else if (West == West::None) return 11968; else if (West == West::Low) return 11969; else return 11970; else if (Up) if (West == West::None) return 11974; else if (West == West::Low) return 11975; else return 11976; else if (West == West::None) return 11980; else if (West == West::Low) return 11981; else return 11982; else if (North == North::Low) if (South == South::None) if (Up) if (West == West::None) return 11986; else if (West == West::Low) return 11987; else return 11988; else if (West == West::None) return 11992; else if (West == West::Low) return 11993; else return 11994; else if (South == South::Low) if (Up) if (West == West::None) return 11998; else if (West == West::Low) return 11999; else return 12000; else if (West == West::None) return 12004; else if (West == West::Low) return 12005; else return 12006; else if (Up) if (West == West::None) return 12010; else if (West == West::Low) return 12011; else return 12012; else if (West == West::None) return 12016; else if (West == West::Low) return 12017; else return 12018; else if (South == South::None) if (Up) if (West == West::None) return 12022; else if (West == West::Low) return 12023; else return 12024; else if (West == West::None) return 12028; else if (West == West::Low) return 12029; else return 12030; else if (South == South::Low) if (Up) if (West == West::None) return 12034; else if (West == West::Low) return 12035; else return 12036; else if (West == West::None) return 12040; else if (West == West::Low) return 12041; else return 12042; else if (Up) if (West == West::None) return 12046; else if (West == West::Low) return 12047; else return 12048; else if (West == West::None) return 12052; else if (West == West::Low) return 12053; else return 12054; else if (North == North::None) if (South == South::None) if (Up) if (West == West::None) return 12058; else if (West == West::Low) return 12059; else return 12060; else if (West == West::None) return 12064; else if (West == West::Low) return 12065; else return 12066; else if (South == South::Low) if (Up) if (West == West::None) return 12070; else if (West == West::Low) return 12071; else return 12072; else if (West == West::None) return 12076; else if (West == West::Low) return 12077; else return 12078; else if (Up) if (West == West::None) return 12082; else if (West == West::Low) return 12083; else return 12084; else if (West == West::None) return 12088; else if (West == West::Low) return 12089; else return 12090; else if (North == North::Low) if (South == South::None) if (Up) if (West == West::None) return 12094; else if (West == West::Low) return 12095; else return 12096; else if (West == West::None) return 12100; else if (West == West::Low) return 12101; else return 12102; else if (South == South::Low) if (Up) if (West == West::None) return 12106; else if (West == West::Low) return 12107; else return 12108; else if (West == West::None) return 12112; else if (West == West::Low) return 12113; else return 12114; else if (Up) if (West == West::None) return 12118; else if (West == West::Low) return 12119; else return 12120; else if (West == West::None) return 12124; else if (West == West::Low) return 12125; else return 12126; else if (South == South::None) if (Up) if (West == West::None) return 12130; else if (West == West::Low) return 12131; else return 12132; else if (West == West::None) return 12136; else if (West == West::Low) return 12137; else return 12138; else if (South == South::Low) if (Up) if (West == West::None) return 12142; else if (West == West::Low) return 12143; else return 12144; else if (West == West::None) return 12148; else if (West == West::Low) return 12149; else return 12150; else if (Up) if (West == West::None) return 12154; else if (West == West::Low) return 12155; else return 12156; else if (West == West::None) return 12160; else if (West == West::Low) return 12161; else return 12162; } BlockState MossyStoneBrickWall(); enum East East(BlockState Block); enum North North(BlockState Block); enum South South(BlockState Block); bool Up(BlockState Block); enum West West(BlockState Block); } namespace MossyStoneBricks { constexpr BlockState MossyStoneBricks() { return 4496; } } namespace MovingPiston { enum class Type { Normal, Sticky }; constexpr BlockState MovingPiston(const eBlockFace Facing, const enum Type Type) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Type == Type::Normal) return 1400; else return 1401; else if (Facing == eBlockFace::BLOCK_FACE_XP) if (Type == Type::Normal) return 1402; else return 1403; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Type == Type::Normal) return 1404; else return 1405; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Type == Type::Normal) return 1406; else return 1407; else if (Facing == eBlockFace::BLOCK_FACE_YP) if (Type == Type::Normal) return 1408; else return 1409; else if (Type == Type::Normal) return 1410; else return 1411; } BlockState MovingPiston(); eBlockFace Facing(BlockState Block); enum Type Type(BlockState Block); } namespace MushroomStem { constexpr BlockState MushroomStem(const bool Down, const bool East, const bool North, const bool South, const bool Up, const bool West) { if (Down) if (East) if (North) if (South) if (Up) if (West) return 4633; else return 4634; else if (West) return 4635; else return 4636; else if (Up) if (West) return 4637; else return 4638; else if (West) return 4639; else return 4640; else if (South) if (Up) if (West) return 4641; else return 4642; else if (West) return 4643; else return 4644; else if (Up) if (West) return 4645; else return 4646; else if (West) return 4647; else return 4648; else if (North) if (South) if (Up) if (West) return 4649; else return 4650; else if (West) return 4651; else return 4652; else if (Up) if (West) return 4653; else return 4654; else if (West) return 4655; else return 4656; else if (South) if (Up) if (West) return 4657; else return 4658; else if (West) return 4659; else return 4660; else if (Up) if (West) return 4661; else return 4662; else if (West) return 4663; else return 4664; else if (East) if (North) if (South) if (Up) if (West) return 4665; else return 4666; else if (West) return 4667; else return 4668; else if (Up) if (West) return 4669; else return 4670; else if (West) return 4671; else return 4672; else if (South) if (Up) if (West) return 4673; else return 4674; else if (West) return 4675; else return 4676; else if (Up) if (West) return 4677; else return 4678; else if (West) return 4679; else return 4680; else if (North) if (South) if (Up) if (West) return 4681; else return 4682; else if (West) return 4683; else return 4684; else if (Up) if (West) return 4685; else return 4686; else if (West) return 4687; else return 4688; else if (South) if (Up) if (West) return 4689; else return 4690; else if (West) return 4691; else return 4692; else if (Up) if (West) return 4693; else return 4694; else if (West) return 4695; else return 4696; } BlockState MushroomStem(); bool Down(BlockState Block); bool East(BlockState Block); bool North(BlockState Block); bool South(BlockState Block); bool Up(BlockState Block); bool West(BlockState Block); } namespace Mycelium { constexpr BlockState Mycelium(const bool Snowy) { if (Snowy) return 5012; else return 5013; } BlockState Mycelium(); bool Snowy(BlockState Block); } namespace NetherBrickFence { constexpr BlockState NetherBrickFence(const bool East, const bool North, const bool South, const bool West) { if (East) if (North) if (South) if (West) return 5018; else return 5019; else if (West) return 5022; else return 5023; else if (South) if (West) return 5026; else return 5027; else if (West) return 5030; else return 5031; else if (North) if (South) if (West) return 5034; else return 5035; else if (West) return 5038; else return 5039; else if (South) if (West) return 5042; else return 5043; else if (West) return 5046; else return 5047; } BlockState NetherBrickFence(); bool East(BlockState Block); bool North(BlockState Block); bool South(BlockState Block); bool West(BlockState Block); } namespace NetherBrickSlab { enum class Type { Top, Bottom, Double }; constexpr BlockState NetherBrickSlab(const enum Type Type) { if (Type == Type::Top) return 8385; else if (Type == Type::Bottom) return 8387; else return 8389; } BlockState NetherBrickSlab(); enum Type Type(BlockState Block); } namespace NetherBrickStairs { enum class Half { Top, Bottom }; enum class Shape { Straight, InnerLeft, InnerRight, OuterLeft, OuterRight }; constexpr BlockState NetherBrickStairs(const eBlockFace Facing, const enum Half Half, const enum Shape Shape) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Half == Half::Top) if (Shape == Shape::Straight) return 5049; else if (Shape == Shape::InnerLeft) return 5051; else if (Shape == Shape::InnerRight) return 5053; else if (Shape == Shape::OuterLeft) return 5055; else return 5057; else if (Shape == Shape::Straight) return 5059; else if (Shape == Shape::InnerLeft) return 5061; else if (Shape == Shape::InnerRight) return 5063; else if (Shape == Shape::OuterLeft) return 5065; else return 5067; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Half == Half::Top) if (Shape == Shape::Straight) return 5069; else if (Shape == Shape::InnerLeft) return 5071; else if (Shape == Shape::InnerRight) return 5073; else if (Shape == Shape::OuterLeft) return 5075; else return 5077; else if (Shape == Shape::Straight) return 5079; else if (Shape == Shape::InnerLeft) return 5081; else if (Shape == Shape::InnerRight) return 5083; else if (Shape == Shape::OuterLeft) return 5085; else return 5087; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Half == Half::Top) if (Shape == Shape::Straight) return 5089; else if (Shape == Shape::InnerLeft) return 5091; else if (Shape == Shape::InnerRight) return 5093; else if (Shape == Shape::OuterLeft) return 5095; else return 5097; else if (Shape == Shape::Straight) return 5099; else if (Shape == Shape::InnerLeft) return 5101; else if (Shape == Shape::InnerRight) return 5103; else if (Shape == Shape::OuterLeft) return 5105; else return 5107; else if (Half == Half::Top) if (Shape == Shape::Straight) return 5109; else if (Shape == Shape::InnerLeft) return 5111; else if (Shape == Shape::InnerRight) return 5113; else if (Shape == Shape::OuterLeft) return 5115; else return 5117; else if (Shape == Shape::Straight) return 5119; else if (Shape == Shape::InnerLeft) return 5121; else if (Shape == Shape::InnerRight) return 5123; else if (Shape == Shape::OuterLeft) return 5125; else return 5127; } BlockState NetherBrickStairs(); eBlockFace Facing(BlockState Block); enum Half Half(BlockState Block); enum Shape Shape(BlockState Block); } namespace NetherBrickWall { enum class East { None, Low, Tall }; enum class North { None, Low, Tall }; enum class South { None, Low, Tall }; enum class West { None, Low, Tall }; constexpr BlockState NetherBrickWall(const enum East East, const enum North North, const enum South South, const bool Up, const enum West West) { if (East == East::None) if (North == North::None) if (South == South::None) if (Up) if (West == West::None) return 12814; else if (West == West::Low) return 12815; else return 12816; else if (West == West::None) return 12820; else if (West == West::Low) return 12821; else return 12822; else if (South == South::Low) if (Up) if (West == West::None) return 12826; else if (West == West::Low) return 12827; else return 12828; else if (West == West::None) return 12832; else if (West == West::Low) return 12833; else return 12834; else if (Up) if (West == West::None) return 12838; else if (West == West::Low) return 12839; else return 12840; else if (West == West::None) return 12844; else if (West == West::Low) return 12845; else return 12846; else if (North == North::Low) if (South == South::None) if (Up) if (West == West::None) return 12850; else if (West == West::Low) return 12851; else return 12852; else if (West == West::None) return 12856; else if (West == West::Low) return 12857; else return 12858; else if (South == South::Low) if (Up) if (West == West::None) return 12862; else if (West == West::Low) return 12863; else return 12864; else if (West == West::None) return 12868; else if (West == West::Low) return 12869; else return 12870; else if (Up) if (West == West::None) return 12874; else if (West == West::Low) return 12875; else return 12876; else if (West == West::None) return 12880; else if (West == West::Low) return 12881; else return 12882; else if (South == South::None) if (Up) if (West == West::None) return 12886; else if (West == West::Low) return 12887; else return 12888; else if (West == West::None) return 12892; else if (West == West::Low) return 12893; else return 12894; else if (South == South::Low) if (Up) if (West == West::None) return 12898; else if (West == West::Low) return 12899; else return 12900; else if (West == West::None) return 12904; else if (West == West::Low) return 12905; else return 12906; else if (Up) if (West == West::None) return 12910; else if (West == West::Low) return 12911; else return 12912; else if (West == West::None) return 12916; else if (West == West::Low) return 12917; else return 12918; else if (East == East::Low) if (North == North::None) if (South == South::None) if (Up) if (West == West::None) return 12922; else if (West == West::Low) return 12923; else return 12924; else if (West == West::None) return 12928; else if (West == West::Low) return 12929; else return 12930; else if (South == South::Low) if (Up) if (West == West::None) return 12934; else if (West == West::Low) return 12935; else return 12936; else if (West == West::None) return 12940; else if (West == West::Low) return 12941; else return 12942; else if (Up) if (West == West::None) return 12946; else if (West == West::Low) return 12947; else return 12948; else if (West == West::None) return 12952; else if (West == West::Low) return 12953; else return 12954; else if (North == North::Low) if (South == South::None) if (Up) if (West == West::None) return 12958; else if (West == West::Low) return 12959; else return 12960; else if (West == West::None) return 12964; else if (West == West::Low) return 12965; else return 12966; else if (South == South::Low) if (Up) if (West == West::None) return 12970; else if (West == West::Low) return 12971; else return 12972; else if (West == West::None) return 12976; else if (West == West::Low) return 12977; else return 12978; else if (Up) if (West == West::None) return 12982; else if (West == West::Low) return 12983; else return 12984; else if (West == West::None) return 12988; else if (West == West::Low) return 12989; else return 12990; else if (South == South::None) if (Up) if (West == West::None) return 12994; else if (West == West::Low) return 12995; else return 12996; else if (West == West::None) return 13000; else if (West == West::Low) return 13001; else return 13002; else if (South == South::Low) if (Up) if (West == West::None) return 13006; else if (West == West::Low) return 13007; else return 13008; else if (West == West::None) return 13012; else if (West == West::Low) return 13013; else return 13014; else if (Up) if (West == West::None) return 13018; else if (West == West::Low) return 13019; else return 13020; else if (West == West::None) return 13024; else if (West == West::Low) return 13025; else return 13026; else if (North == North::None) if (South == South::None) if (Up) if (West == West::None) return 13030; else if (West == West::Low) return 13031; else return 13032; else if (West == West::None) return 13036; else if (West == West::Low) return 13037; else return 13038; else if (South == South::Low) if (Up) if (West == West::None) return 13042; else if (West == West::Low) return 13043; else return 13044; else if (West == West::None) return 13048; else if (West == West::Low) return 13049; else return 13050; else if (Up) if (West == West::None) return 13054; else if (West == West::Low) return 13055; else return 13056; else if (West == West::None) return 13060; else if (West == West::Low) return 13061; else return 13062; else if (North == North::Low) if (South == South::None) if (Up) if (West == West::None) return 13066; else if (West == West::Low) return 13067; else return 13068; else if (West == West::None) return 13072; else if (West == West::Low) return 13073; else return 13074; else if (South == South::Low) if (Up) if (West == West::None) return 13078; else if (West == West::Low) return 13079; else return 13080; else if (West == West::None) return 13084; else if (West == West::Low) return 13085; else return 13086; else if (Up) if (West == West::None) return 13090; else if (West == West::Low) return 13091; else return 13092; else if (West == West::None) return 13096; else if (West == West::Low) return 13097; else return 13098; else if (South == South::None) if (Up) if (West == West::None) return 13102; else if (West == West::Low) return 13103; else return 13104; else if (West == West::None) return 13108; else if (West == West::Low) return 13109; else return 13110; else if (South == South::Low) if (Up) if (West == West::None) return 13114; else if (West == West::Low) return 13115; else return 13116; else if (West == West::None) return 13120; else if (West == West::Low) return 13121; else return 13122; else if (Up) if (West == West::None) return 13126; else if (West == West::Low) return 13127; else return 13128; else if (West == West::None) return 13132; else if (West == West::Low) return 13133; else return 13134; } BlockState NetherBrickWall(); enum East East(BlockState Block); enum North North(BlockState Block); enum South South(BlockState Block); bool Up(BlockState Block); enum West West(BlockState Block); } namespace NetherBricks { constexpr BlockState NetherBricks() { return 5015; } } namespace NetherGoldOre { constexpr BlockState NetherGoldOre() { return 72; } } namespace NetherPortal { enum class Axis { X, Z }; constexpr BlockState NetherPortal(const enum Axis Axis) { if (Axis == Axis::X) return 4014; else return 4015; } BlockState NetherPortal(); enum Axis Axis(BlockState Block); } namespace NetherQuartzOre { constexpr BlockState NetherQuartzOre() { return 6727; } } namespace NetherSprouts { constexpr BlockState NetherSprouts() { return 14974; } } namespace NetherWart { constexpr BlockState NetherWart(const unsigned char Age) { if (Age == 0) return 5128; else if (Age == 1) return 5129; else if (Age == 2) return 5130; else return 5131; } BlockState NetherWart(); unsigned char Age(BlockState Block); } namespace NetherWartBlock { constexpr BlockState NetherWartBlock() { return 9254; } } namespace NetheriteBlock { constexpr BlockState NetheriteBlock() { return 15826; } } namespace Netherrack { constexpr BlockState Netherrack() { return 3999; } } namespace NoteBlock { enum class Instrument { Harp, Basedrum, Snare, Hat, Bass, Flute, Bell, Guitar, Chime, Xylophone, IronXylophone, CowBell, Didgeridoo, Bit, Banjo, Pling }; constexpr BlockState NoteBlock(const enum Instrument Instrument, const unsigned char Note, const bool Powered) { if (Instrument == Instrument::Harp) if (Note == 0) if (Powered) return 249; else return 250; else if (Note == 1) if (Powered) return 251; else return 252; else if (Note == 2) if (Powered) return 253; else return 254; else if (Note == 3) if (Powered) return 255; else return 256; else if (Note == 4) if (Powered) return 257; else return 258; else if (Note == 5) if (Powered) return 259; else return 260; else if (Note == 6) if (Powered) return 261; else return 262; else if (Note == 7) if (Powered) return 263; else return 264; else if (Note == 8) if (Powered) return 265; else return 266; else if (Note == 9) if (Powered) return 267; else return 268; else if (Note == 10) if (Powered) return 269; else return 270; else if (Note == 11) if (Powered) return 271; else return 272; else if (Note == 12) if (Powered) return 273; else return 274; else if (Note == 13) if (Powered) return 275; else return 276; else if (Note == 14) if (Powered) return 277; else return 278; else if (Note == 15) if (Powered) return 279; else return 280; else if (Note == 16) if (Powered) return 281; else return 282; else if (Note == 17) if (Powered) return 283; else return 284; else if (Note == 18) if (Powered) return 285; else return 286; else if (Note == 19) if (Powered) return 287; else return 288; else if (Note == 20) if (Powered) return 289; else return 290; else if (Note == 21) if (Powered) return 291; else return 292; else if (Note == 22) if (Powered) return 293; else return 294; else if (Note == 23) if (Powered) return 295; else return 296; else if (Powered) return 297; else return 298; else if (Instrument == Instrument::Basedrum) if (Note == 0) if (Powered) return 299; else return 300; else if (Note == 1) if (Powered) return 301; else return 302; else if (Note == 2) if (Powered) return 303; else return 304; else if (Note == 3) if (Powered) return 305; else return 306; else if (Note == 4) if (Powered) return 307; else return 308; else if (Note == 5) if (Powered) return 309; else return 310; else if (Note == 6) if (Powered) return 311; else return 312; else if (Note == 7) if (Powered) return 313; else return 314; else if (Note == 8) if (Powered) return 315; else return 316; else if (Note == 9) if (Powered) return 317; else return 318; else if (Note == 10) if (Powered) return 319; else return 320; else if (Note == 11) if (Powered) return 321; else return 322; else if (Note == 12) if (Powered) return 323; else return 324; else if (Note == 13) if (Powered) return 325; else return 326; else if (Note == 14) if (Powered) return 327; else return 328; else if (Note == 15) if (Powered) return 329; else return 330; else if (Note == 16) if (Powered) return 331; else return 332; else if (Note == 17) if (Powered) return 333; else return 334; else if (Note == 18) if (Powered) return 335; else return 336; else if (Note == 19) if (Powered) return 337; else return 338; else if (Note == 20) if (Powered) return 339; else return 340; else if (Note == 21) if (Powered) return 341; else return 342; else if (Note == 22) if (Powered) return 343; else return 344; else if (Note == 23) if (Powered) return 345; else return 346; else if (Powered) return 347; else return 348; else if (Instrument == Instrument::Snare) if (Note == 0) if (Powered) return 349; else return 350; else if (Note == 1) if (Powered) return 351; else return 352; else if (Note == 2) if (Powered) return 353; else return 354; else if (Note == 3) if (Powered) return 355; else return 356; else if (Note == 4) if (Powered) return 357; else return 358; else if (Note == 5) if (Powered) return 359; else return 360; else if (Note == 6) if (Powered) return 361; else return 362; else if (Note == 7) if (Powered) return 363; else return 364; else if (Note == 8) if (Powered) return 365; else return 366; else if (Note == 9) if (Powered) return 367; else return 368; else if (Note == 10) if (Powered) return 369; else return 370; else if (Note == 11) if (Powered) return 371; else return 372; else if (Note == 12) if (Powered) return 373; else return 374; else if (Note == 13) if (Powered) return 375; else return 376; else if (Note == 14) if (Powered) return 377; else return 378; else if (Note == 15) if (Powered) return 379; else return 380; else if (Note == 16) if (Powered) return 381; else return 382; else if (Note == 17) if (Powered) return 383; else return 384; else if (Note == 18) if (Powered) return 385; else return 386; else if (Note == 19) if (Powered) return 387; else return 388; else if (Note == 20) if (Powered) return 389; else return 390; else if (Note == 21) if (Powered) return 391; else return 392; else if (Note == 22) if (Powered) return 393; else return 394; else if (Note == 23) if (Powered) return 395; else return 396; else if (Powered) return 397; else return 398; else if (Instrument == Instrument::Hat) if (Note == 0) if (Powered) return 399; else return 400; else if (Note == 1) if (Powered) return 401; else return 402; else if (Note == 2) if (Powered) return 403; else return 404; else if (Note == 3) if (Powered) return 405; else return 406; else if (Note == 4) if (Powered) return 407; else return 408; else if (Note == 5) if (Powered) return 409; else return 410; else if (Note == 6) if (Powered) return 411; else return 412; else if (Note == 7) if (Powered) return 413; else return 414; else if (Note == 8) if (Powered) return 415; else return 416; else if (Note == 9) if (Powered) return 417; else return 418; else if (Note == 10) if (Powered) return 419; else return 420; else if (Note == 11) if (Powered) return 421; else return 422; else if (Note == 12) if (Powered) return 423; else return 424; else if (Note == 13) if (Powered) return 425; else return 426; else if (Note == 14) if (Powered) return 427; else return 428; else if (Note == 15) if (Powered) return 429; else return 430; else if (Note == 16) if (Powered) return 431; else return 432; else if (Note == 17) if (Powered) return 433; else return 434; else if (Note == 18) if (Powered) return 435; else return 436; else if (Note == 19) if (Powered) return 437; else return 438; else if (Note == 20) if (Powered) return 439; else return 440; else if (Note == 21) if (Powered) return 441; else return 442; else if (Note == 22) if (Powered) return 443; else return 444; else if (Note == 23) if (Powered) return 445; else return 446; else if (Powered) return 447; else return 448; else if (Instrument == Instrument::Bass) if (Note == 0) if (Powered) return 449; else return 450; else if (Note == 1) if (Powered) return 451; else return 452; else if (Note == 2) if (Powered) return 453; else return 454; else if (Note == 3) if (Powered) return 455; else return 456; else if (Note == 4) if (Powered) return 457; else return 458; else if (Note == 5) if (Powered) return 459; else return 460; else if (Note == 6) if (Powered) return 461; else return 462; else if (Note == 7) if (Powered) return 463; else return 464; else if (Note == 8) if (Powered) return 465; else return 466; else if (Note == 9) if (Powered) return 467; else return 468; else if (Note == 10) if (Powered) return 469; else return 470; else if (Note == 11) if (Powered) return 471; else return 472; else if (Note == 12) if (Powered) return 473; else return 474; else if (Note == 13) if (Powered) return 475; else return 476; else if (Note == 14) if (Powered) return 477; else return 478; else if (Note == 15) if (Powered) return 479; else return 480; else if (Note == 16) if (Powered) return 481; else return 482; else if (Note == 17) if (Powered) return 483; else return 484; else if (Note == 18) if (Powered) return 485; else return 486; else if (Note == 19) if (Powered) return 487; else return 488; else if (Note == 20) if (Powered) return 489; else return 490; else if (Note == 21) if (Powered) return 491; else return 492; else if (Note == 22) if (Powered) return 493; else return 494; else if (Note == 23) if (Powered) return 495; else return 496; else if (Powered) return 497; else return 498; else if (Instrument == Instrument::Flute) if (Note == 0) if (Powered) return 499; else return 500; else if (Note == 1) if (Powered) return 501; else return 502; else if (Note == 2) if (Powered) return 503; else return 504; else if (Note == 3) if (Powered) return 505; else return 506; else if (Note == 4) if (Powered) return 507; else return 508; else if (Note == 5) if (Powered) return 509; else return 510; else if (Note == 6) if (Powered) return 511; else return 512; else if (Note == 7) if (Powered) return 513; else return 514; else if (Note == 8) if (Powered) return 515; else return 516; else if (Note == 9) if (Powered) return 517; else return 518; else if (Note == 10) if (Powered) return 519; else return 520; else if (Note == 11) if (Powered) return 521; else return 522; else if (Note == 12) if (Powered) return 523; else return 524; else if (Note == 13) if (Powered) return 525; else return 526; else if (Note == 14) if (Powered) return 527; else return 528; else if (Note == 15) if (Powered) return 529; else return 530; else if (Note == 16) if (Powered) return 531; else return 532; else if (Note == 17) if (Powered) return 533; else return 534; else if (Note == 18) if (Powered) return 535; else return 536; else if (Note == 19) if (Powered) return 537; else return 538; else if (Note == 20) if (Powered) return 539; else return 540; else if (Note == 21) if (Powered) return 541; else return 542; else if (Note == 22) if (Powered) return 543; else return 544; else if (Note == 23) if (Powered) return 545; else return 546; else if (Powered) return 547; else return 548; else if (Instrument == Instrument::Bell) if (Note == 0) if (Powered) return 549; else return 550; else if (Note == 1) if (Powered) return 551; else return 552; else if (Note == 2) if (Powered) return 553; else return 554; else if (Note == 3) if (Powered) return 555; else return 556; else if (Note == 4) if (Powered) return 557; else return 558; else if (Note == 5) if (Powered) return 559; else return 560; else if (Note == 6) if (Powered) return 561; else return 562; else if (Note == 7) if (Powered) return 563; else return 564; else if (Note == 8) if (Powered) return 565; else return 566; else if (Note == 9) if (Powered) return 567; else return 568; else if (Note == 10) if (Powered) return 569; else return 570; else if (Note == 11) if (Powered) return 571; else return 572; else if (Note == 12) if (Powered) return 573; else return 574; else if (Note == 13) if (Powered) return 575; else return 576; else if (Note == 14) if (Powered) return 577; else return 578; else if (Note == 15) if (Powered) return 579; else return 580; else if (Note == 16) if (Powered) return 581; else return 582; else if (Note == 17) if (Powered) return 583; else return 584; else if (Note == 18) if (Powered) return 585; else return 586; else if (Note == 19) if (Powered) return 587; else return 588; else if (Note == 20) if (Powered) return 589; else return 590; else if (Note == 21) if (Powered) return 591; else return 592; else if (Note == 22) if (Powered) return 593; else return 594; else if (Note == 23) if (Powered) return 595; else return 596; else if (Powered) return 597; else return 598; else if (Instrument == Instrument::Guitar) if (Note == 0) if (Powered) return 599; else return 600; else if (Note == 1) if (Powered) return 601; else return 602; else if (Note == 2) if (Powered) return 603; else return 604; else if (Note == 3) if (Powered) return 605; else return 606; else if (Note == 4) if (Powered) return 607; else return 608; else if (Note == 5) if (Powered) return 609; else return 610; else if (Note == 6) if (Powered) return 611; else return 612; else if (Note == 7) if (Powered) return 613; else return 614; else if (Note == 8) if (Powered) return 615; else return 616; else if (Note == 9) if (Powered) return 617; else return 618; else if (Note == 10) if (Powered) return 619; else return 620; else if (Note == 11) if (Powered) return 621; else return 622; else if (Note == 12) if (Powered) return 623; else return 624; else if (Note == 13) if (Powered) return 625; else return 626; else if (Note == 14) if (Powered) return 627; else return 628; else if (Note == 15) if (Powered) return 629; else return 630; else if (Note == 16) if (Powered) return 631; else return 632; else if (Note == 17) if (Powered) return 633; else return 634; else if (Note == 18) if (Powered) return 635; else return 636; else if (Note == 19) if (Powered) return 637; else return 638; else if (Note == 20) if (Powered) return 639; else return 640; else if (Note == 21) if (Powered) return 641; else return 642; else if (Note == 22) if (Powered) return 643; else return 644; else if (Note == 23) if (Powered) return 645; else return 646; else if (Powered) return 647; else return 648; else if (Instrument == Instrument::Chime) if (Note == 0) if (Powered) return 649; else return 650; else if (Note == 1) if (Powered) return 651; else return 652; else if (Note == 2) if (Powered) return 653; else return 654; else if (Note == 3) if (Powered) return 655; else return 656; else if (Note == 4) if (Powered) return 657; else return 658; else if (Note == 5) if (Powered) return 659; else return 660; else if (Note == 6) if (Powered) return 661; else return 662; else if (Note == 7) if (Powered) return 663; else return 664; else if (Note == 8) if (Powered) return 665; else return 666; else if (Note == 9) if (Powered) return 667; else return 668; else if (Note == 10) if (Powered) return 669; else return 670; else if (Note == 11) if (Powered) return 671; else return 672; else if (Note == 12) if (Powered) return 673; else return 674; else if (Note == 13) if (Powered) return 675; else return 676; else if (Note == 14) if (Powered) return 677; else return 678; else if (Note == 15) if (Powered) return 679; else return 680; else if (Note == 16) if (Powered) return 681; else return 682; else if (Note == 17) if (Powered) return 683; else return 684; else if (Note == 18) if (Powered) return 685; else return 686; else if (Note == 19) if (Powered) return 687; else return 688; else if (Note == 20) if (Powered) return 689; else return 690; else if (Note == 21) if (Powered) return 691; else return 692; else if (Note == 22) if (Powered) return 693; else return 694; else if (Note == 23) if (Powered) return 695; else return 696; else if (Powered) return 697; else return 698; else if (Instrument == Instrument::Xylophone) if (Note == 0) if (Powered) return 699; else return 700; else if (Note == 1) if (Powered) return 701; else return 702; else if (Note == 2) if (Powered) return 703; else return 704; else if (Note == 3) if (Powered) return 705; else return 706; else if (Note == 4) if (Powered) return 707; else return 708; else if (Note == 5) if (Powered) return 709; else return 710; else if (Note == 6) if (Powered) return 711; else return 712; else if (Note == 7) if (Powered) return 713; else return 714; else if (Note == 8) if (Powered) return 715; else return 716; else if (Note == 9) if (Powered) return 717; else return 718; else if (Note == 10) if (Powered) return 719; else return 720; else if (Note == 11) if (Powered) return 721; else return 722; else if (Note == 12) if (Powered) return 723; else return 724; else if (Note == 13) if (Powered) return 725; else return 726; else if (Note == 14) if (Powered) return 727; else return 728; else if (Note == 15) if (Powered) return 729; else return 730; else if (Note == 16) if (Powered) return 731; else return 732; else if (Note == 17) if (Powered) return 733; else return 734; else if (Note == 18) if (Powered) return 735; else return 736; else if (Note == 19) if (Powered) return 737; else return 738; else if (Note == 20) if (Powered) return 739; else return 740; else if (Note == 21) if (Powered) return 741; else return 742; else if (Note == 22) if (Powered) return 743; else return 744; else if (Note == 23) if (Powered) return 745; else return 746; else if (Powered) return 747; else return 748; else if (Instrument == Instrument::IronXylophone) if (Note == 0) if (Powered) return 749; else return 750; else if (Note == 1) if (Powered) return 751; else return 752; else if (Note == 2) if (Powered) return 753; else return 754; else if (Note == 3) if (Powered) return 755; else return 756; else if (Note == 4) if (Powered) return 757; else return 758; else if (Note == 5) if (Powered) return 759; else return 760; else if (Note == 6) if (Powered) return 761; else return 762; else if (Note == 7) if (Powered) return 763; else return 764; else if (Note == 8) if (Powered) return 765; else return 766; else if (Note == 9) if (Powered) return 767; else return 768; else if (Note == 10) if (Powered) return 769; else return 770; else if (Note == 11) if (Powered) return 771; else return 772; else if (Note == 12) if (Powered) return 773; else return 774; else if (Note == 13) if (Powered) return 775; else return 776; else if (Note == 14) if (Powered) return 777; else return 778; else if (Note == 15) if (Powered) return 779; else return 780; else if (Note == 16) if (Powered) return 781; else return 782; else if (Note == 17) if (Powered) return 783; else return 784; else if (Note == 18) if (Powered) return 785; else return 786; else if (Note == 19) if (Powered) return 787; else return 788; else if (Note == 20) if (Powered) return 789; else return 790; else if (Note == 21) if (Powered) return 791; else return 792; else if (Note == 22) if (Powered) return 793; else return 794; else if (Note == 23) if (Powered) return 795; else return 796; else if (Powered) return 797; else return 798; else if (Instrument == Instrument::CowBell) if (Note == 0) if (Powered) return 799; else return 800; else if (Note == 1) if (Powered) return 801; else return 802; else if (Note == 2) if (Powered) return 803; else return 804; else if (Note == 3) if (Powered) return 805; else return 806; else if (Note == 4) if (Powered) return 807; else return 808; else if (Note == 5) if (Powered) return 809; else return 810; else if (Note == 6) if (Powered) return 811; else return 812; else if (Note == 7) if (Powered) return 813; else return 814; else if (Note == 8) if (Powered) return 815; else return 816; else if (Note == 9) if (Powered) return 817; else return 818; else if (Note == 10) if (Powered) return 819; else return 820; else if (Note == 11) if (Powered) return 821; else return 822; else if (Note == 12) if (Powered) return 823; else return 824; else if (Note == 13) if (Powered) return 825; else return 826; else if (Note == 14) if (Powered) return 827; else return 828; else if (Note == 15) if (Powered) return 829; else return 830; else if (Note == 16) if (Powered) return 831; else return 832; else if (Note == 17) if (Powered) return 833; else return 834; else if (Note == 18) if (Powered) return 835; else return 836; else if (Note == 19) if (Powered) return 837; else return 838; else if (Note == 20) if (Powered) return 839; else return 840; else if (Note == 21) if (Powered) return 841; else return 842; else if (Note == 22) if (Powered) return 843; else return 844; else if (Note == 23) if (Powered) return 845; else return 846; else if (Powered) return 847; else return 848; else if (Instrument == Instrument::Didgeridoo) if (Note == 0) if (Powered) return 849; else return 850; else if (Note == 1) if (Powered) return 851; else return 852; else if (Note == 2) if (Powered) return 853; else return 854; else if (Note == 3) if (Powered) return 855; else return 856; else if (Note == 4) if (Powered) return 857; else return 858; else if (Note == 5) if (Powered) return 859; else return 860; else if (Note == 6) if (Powered) return 861; else return 862; else if (Note == 7) if (Powered) return 863; else return 864; else if (Note == 8) if (Powered) return 865; else return 866; else if (Note == 9) if (Powered) return 867; else return 868; else if (Note == 10) if (Powered) return 869; else return 870; else if (Note == 11) if (Powered) return 871; else return 872; else if (Note == 12) if (Powered) return 873; else return 874; else if (Note == 13) if (Powered) return 875; else return 876; else if (Note == 14) if (Powered) return 877; else return 878; else if (Note == 15) if (Powered) return 879; else return 880; else if (Note == 16) if (Powered) return 881; else return 882; else if (Note == 17) if (Powered) return 883; else return 884; else if (Note == 18) if (Powered) return 885; else return 886; else if (Note == 19) if (Powered) return 887; else return 888; else if (Note == 20) if (Powered) return 889; else return 890; else if (Note == 21) if (Powered) return 891; else return 892; else if (Note == 22) if (Powered) return 893; else return 894; else if (Note == 23) if (Powered) return 895; else return 896; else if (Powered) return 897; else return 898; else if (Instrument == Instrument::Bit) if (Note == 0) if (Powered) return 899; else return 900; else if (Note == 1) if (Powered) return 901; else return 902; else if (Note == 2) if (Powered) return 903; else return 904; else if (Note == 3) if (Powered) return 905; else return 906; else if (Note == 4) if (Powered) return 907; else return 908; else if (Note == 5) if (Powered) return 909; else return 910; else if (Note == 6) if (Powered) return 911; else return 912; else if (Note == 7) if (Powered) return 913; else return 914; else if (Note == 8) if (Powered) return 915; else return 916; else if (Note == 9) if (Powered) return 917; else return 918; else if (Note == 10) if (Powered) return 919; else return 920; else if (Note == 11) if (Powered) return 921; else return 922; else if (Note == 12) if (Powered) return 923; else return 924; else if (Note == 13) if (Powered) return 925; else return 926; else if (Note == 14) if (Powered) return 927; else return 928; else if (Note == 15) if (Powered) return 929; else return 930; else if (Note == 16) if (Powered) return 931; else return 932; else if (Note == 17) if (Powered) return 933; else return 934; else if (Note == 18) if (Powered) return 935; else return 936; else if (Note == 19) if (Powered) return 937; else return 938; else if (Note == 20) if (Powered) return 939; else return 940; else if (Note == 21) if (Powered) return 941; else return 942; else if (Note == 22) if (Powered) return 943; else return 944; else if (Note == 23) if (Powered) return 945; else return 946; else if (Powered) return 947; else return 948; else if (Instrument == Instrument::Banjo) if (Note == 0) if (Powered) return 949; else return 950; else if (Note == 1) if (Powered) return 951; else return 952; else if (Note == 2) if (Powered) return 953; else return 954; else if (Note == 3) if (Powered) return 955; else return 956; else if (Note == 4) if (Powered) return 957; else return 958; else if (Note == 5) if (Powered) return 959; else return 960; else if (Note == 6) if (Powered) return 961; else return 962; else if (Note == 7) if (Powered) return 963; else return 964; else if (Note == 8) if (Powered) return 965; else return 966; else if (Note == 9) if (Powered) return 967; else return 968; else if (Note == 10) if (Powered) return 969; else return 970; else if (Note == 11) if (Powered) return 971; else return 972; else if (Note == 12) if (Powered) return 973; else return 974; else if (Note == 13) if (Powered) return 975; else return 976; else if (Note == 14) if (Powered) return 977; else return 978; else if (Note == 15) if (Powered) return 979; else return 980; else if (Note == 16) if (Powered) return 981; else return 982; else if (Note == 17) if (Powered) return 983; else return 984; else if (Note == 18) if (Powered) return 985; else return 986; else if (Note == 19) if (Powered) return 987; else return 988; else if (Note == 20) if (Powered) return 989; else return 990; else if (Note == 21) if (Powered) return 991; else return 992; else if (Note == 22) if (Powered) return 993; else return 994; else if (Note == 23) if (Powered) return 995; else return 996; else if (Powered) return 997; else return 998; else if (Note == 0) if (Powered) return 999; else return 1000; else if (Note == 1) if (Powered) return 1001; else return 1002; else if (Note == 2) if (Powered) return 1003; else return 1004; else if (Note == 3) if (Powered) return 1005; else return 1006; else if (Note == 4) if (Powered) return 1007; else return 1008; else if (Note == 5) if (Powered) return 1009; else return 1010; else if (Note == 6) if (Powered) return 1011; else return 1012; else if (Note == 7) if (Powered) return 1013; else return 1014; else if (Note == 8) if (Powered) return 1015; else return 1016; else if (Note == 9) if (Powered) return 1017; else return 1018; else if (Note == 10) if (Powered) return 1019; else return 1020; else if (Note == 11) if (Powered) return 1021; else return 1022; else if (Note == 12) if (Powered) return 1023; else return 1024; else if (Note == 13) if (Powered) return 1025; else return 1026; else if (Note == 14) if (Powered) return 1027; else return 1028; else if (Note == 15) if (Powered) return 1029; else return 1030; else if (Note == 16) if (Powered) return 1031; else return 1032; else if (Note == 17) if (Powered) return 1033; else return 1034; else if (Note == 18) if (Powered) return 1035; else return 1036; else if (Note == 19) if (Powered) return 1037; else return 1038; else if (Note == 20) if (Powered) return 1039; else return 1040; else if (Note == 21) if (Powered) return 1041; else return 1042; else if (Note == 22) if (Powered) return 1043; else return 1044; else if (Note == 23) if (Powered) return 1045; else return 1046; else if (Powered) return 1047; else return 1048; } BlockState NoteBlock(); enum Instrument Instrument(BlockState Block); unsigned char Note(BlockState Block); bool Powered(BlockState Block); } namespace OakButton { enum class Face { Floor, Wall, Ceiling }; constexpr BlockState OakButton(const enum Face Face, const eBlockFace Facing, const bool Powered) { if (Face == Face::Floor) if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Powered) return 6346; else return 6347; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Powered) return 6348; else return 6349; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Powered) return 6350; else return 6351; else if (Powered) return 6352; else return 6353; else if (Face == Face::Wall) if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Powered) return 6354; else return 6355; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Powered) return 6356; else return 6357; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Powered) return 6358; else return 6359; else if (Powered) return 6360; else return 6361; else if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Powered) return 6362; else return 6363; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Powered) return 6364; else return 6365; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Powered) return 6366; else return 6367; else if (Powered) return 6368; else return 6369; } BlockState OakButton(); enum Face Face(BlockState Block); eBlockFace Facing(BlockState Block); bool Powered(BlockState Block); } namespace OakDoor { enum class Half { Upper, Lower }; enum class Hinge { Left, Right }; constexpr BlockState OakDoor(const eBlockFace Facing, const enum Half Half, const enum Hinge Hinge, const bool Open, const bool Powered) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Half == Half::Upper) if (Hinge == Hinge::Left) if (Open) if (Powered) return 3573; else return 3574; else if (Powered) return 3575; else return 3576; else if (Open) if (Powered) return 3577; else return 3578; else if (Powered) return 3579; else return 3580; else if (Hinge == Hinge::Left) if (Open) if (Powered) return 3581; else return 3582; else if (Powered) return 3583; else return 3584; else if (Open) if (Powered) return 3585; else return 3586; else if (Powered) return 3587; else return 3588; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Half == Half::Upper) if (Hinge == Hinge::Left) if (Open) if (Powered) return 3589; else return 3590; else if (Powered) return 3591; else return 3592; else if (Open) if (Powered) return 3593; else return 3594; else if (Powered) return 3595; else return 3596; else if (Hinge == Hinge::Left) if (Open) if (Powered) return 3597; else return 3598; else if (Powered) return 3599; else return 3600; else if (Open) if (Powered) return 3601; else return 3602; else if (Powered) return 3603; else return 3604; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Half == Half::Upper) if (Hinge == Hinge::Left) if (Open) if (Powered) return 3605; else return 3606; else if (Powered) return 3607; else return 3608; else if (Open) if (Powered) return 3609; else return 3610; else if (Powered) return 3611; else return 3612; else if (Hinge == Hinge::Left) if (Open) if (Powered) return 3613; else return 3614; else if (Powered) return 3615; else return 3616; else if (Open) if (Powered) return 3617; else return 3618; else if (Powered) return 3619; else return 3620; else if (Half == Half::Upper) if (Hinge == Hinge::Left) if (Open) if (Powered) return 3621; else return 3622; else if (Powered) return 3623; else return 3624; else if (Open) if (Powered) return 3625; else return 3626; else if (Powered) return 3627; else return 3628; else if (Hinge == Hinge::Left) if (Open) if (Powered) return 3629; else return 3630; else if (Powered) return 3631; else return 3632; else if (Open) if (Powered) return 3633; else return 3634; else if (Powered) return 3635; else return 3636; } BlockState OakDoor(); eBlockFace Facing(BlockState Block); enum Half Half(BlockState Block); enum Hinge Hinge(BlockState Block); bool Open(BlockState Block); bool Powered(BlockState Block); } namespace OakFence { constexpr BlockState OakFence(const bool East, const bool North, const bool South, const bool West) { if (East) if (North) if (South) if (West) return 3968; else return 3969; else if (West) return 3972; else return 3973; else if (South) if (West) return 3976; else return 3977; else if (West) return 3980; else return 3981; else if (North) if (South) if (West) return 3984; else return 3985; else if (West) return 3988; else return 3989; else if (South) if (West) return 3992; else return 3993; else if (West) return 3996; else return 3997; } BlockState OakFence(); bool East(BlockState Block); bool North(BlockState Block); bool South(BlockState Block); bool West(BlockState Block); } namespace OakFenceGate { constexpr BlockState OakFenceGate(const eBlockFace Facing, const bool InWall, const bool Open, const bool Powered) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (InWall) if (Open) if (Powered) return 4820; else return 4821; else if (Powered) return 4822; else return 4823; else if (Open) if (Powered) return 4824; else return 4825; else if (Powered) return 4826; else return 4827; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (InWall) if (Open) if (Powered) return 4828; else return 4829; else if (Powered) return 4830; else return 4831; else if (Open) if (Powered) return 4832; else return 4833; else if (Powered) return 4834; else return 4835; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (InWall) if (Open) if (Powered) return 4836; else return 4837; else if (Powered) return 4838; else return 4839; else if (Open) if (Powered) return 4840; else return 4841; else if (Powered) return 4842; else return 4843; else if (InWall) if (Open) if (Powered) return 4844; else return 4845; else if (Powered) return 4846; else return 4847; else if (Open) if (Powered) return 4848; else return 4849; else if (Powered) return 4850; else return 4851; } BlockState OakFenceGate(); eBlockFace Facing(BlockState Block); bool InWall(BlockState Block); bool Open(BlockState Block); bool Powered(BlockState Block); } namespace OakLeaves { constexpr BlockState OakLeaves(const unsigned char Distance, const bool Persistent) { if (Distance == 1) if (Persistent) return 145; else return 146; else if (Distance == 2) if (Persistent) return 147; else return 148; else if (Distance == 3) if (Persistent) return 149; else return 150; else if (Distance == 4) if (Persistent) return 151; else return 152; else if (Distance == 5) if (Persistent) return 153; else return 154; else if (Distance == 6) if (Persistent) return 155; else return 156; else if (Persistent) return 157; else return 158; } BlockState OakLeaves(); unsigned char Distance(BlockState Block); bool Persistent(BlockState Block); } namespace OakLog { enum class Axis { X, Y, Z }; constexpr BlockState OakLog(const enum Axis Axis) { if (Axis == Axis::X) return 73; else if (Axis == Axis::Y) return 74; else return 75; } BlockState OakLog(); enum Axis Axis(BlockState Block); } namespace OakPlanks { constexpr BlockState OakPlanks() { return 15; } } namespace OakPressurePlate { constexpr BlockState OakPressurePlate(const bool Powered) { if (Powered) return 3873; else return 3874; } BlockState OakPressurePlate(); bool Powered(BlockState Block); } namespace OakSapling { constexpr BlockState OakSapling(const unsigned char Stage) { if (Stage == 0) return 21; else return 22; } BlockState OakSapling(); unsigned char Stage(BlockState Block); } namespace OakSign { constexpr BlockState OakSign(const unsigned char Rotation) { if (Rotation == 0) return 3382; else if (Rotation == 1) return 3384; else if (Rotation == 2) return 3386; else if (Rotation == 3) return 3388; else if (Rotation == 4) return 3390; else if (Rotation == 5) return 3392; else if (Rotation == 6) return 3394; else if (Rotation == 7) return 3396; else if (Rotation == 8) return 3398; else if (Rotation == 9) return 3400; else if (Rotation == 10) return 3402; else if (Rotation == 11) return 3404; else if (Rotation == 12) return 3406; else if (Rotation == 13) return 3408; else if (Rotation == 14) return 3410; else return 3412; } BlockState OakSign(); unsigned char Rotation(BlockState Block); } namespace OakSlab { enum class Type { Top, Bottom, Double }; constexpr BlockState OakSlab(const enum Type Type) { if (Type == Type::Top) return 8301; else if (Type == Type::Bottom) return 8303; else return 8305; } BlockState OakSlab(); enum Type Type(BlockState Block); } namespace OakStairs { enum class Half { Top, Bottom }; enum class Shape { Straight, InnerLeft, InnerRight, OuterLeft, OuterRight }; constexpr BlockState OakStairs(const eBlockFace Facing, const enum Half Half, const enum Shape Shape) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Half == Half::Top) if (Shape == Shape::Straight) return 1955; else if (Shape == Shape::InnerLeft) return 1957; else if (Shape == Shape::InnerRight) return 1959; else if (Shape == Shape::OuterLeft) return 1961; else return 1963; else if (Shape == Shape::Straight) return 1965; else if (Shape == Shape::InnerLeft) return 1967; else if (Shape == Shape::InnerRight) return 1969; else if (Shape == Shape::OuterLeft) return 1971; else return 1973; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Half == Half::Top) if (Shape == Shape::Straight) return 1975; else if (Shape == Shape::InnerLeft) return 1977; else if (Shape == Shape::InnerRight) return 1979; else if (Shape == Shape::OuterLeft) return 1981; else return 1983; else if (Shape == Shape::Straight) return 1985; else if (Shape == Shape::InnerLeft) return 1987; else if (Shape == Shape::InnerRight) return 1989; else if (Shape == Shape::OuterLeft) return 1991; else return 1993; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Half == Half::Top) if (Shape == Shape::Straight) return 1995; else if (Shape == Shape::InnerLeft) return 1997; else if (Shape == Shape::InnerRight) return 1999; else if (Shape == Shape::OuterLeft) return 2001; else return 2003; else if (Shape == Shape::Straight) return 2005; else if (Shape == Shape::InnerLeft) return 2007; else if (Shape == Shape::InnerRight) return 2009; else if (Shape == Shape::OuterLeft) return 2011; else return 2013; else if (Half == Half::Top) if (Shape == Shape::Straight) return 2015; else if (Shape == Shape::InnerLeft) return 2017; else if (Shape == Shape::InnerRight) return 2019; else if (Shape == Shape::OuterLeft) return 2021; else return 2023; else if (Shape == Shape::Straight) return 2025; else if (Shape == Shape::InnerLeft) return 2027; else if (Shape == Shape::InnerRight) return 2029; else if (Shape == Shape::OuterLeft) return 2031; else return 2033; } BlockState OakStairs(); eBlockFace Facing(BlockState Block); enum Half Half(BlockState Block); enum Shape Shape(BlockState Block); } namespace OakTrapdoor { enum class Half { Top, Bottom }; constexpr BlockState OakTrapdoor(const eBlockFace Facing, const enum Half Half, const bool Open, const bool Powered) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Half == Half::Top) if (Open) if (Powered) return 4112; else return 4114; else if (Powered) return 4116; else return 4118; else if (Open) if (Powered) return 4120; else return 4122; else if (Powered) return 4124; else return 4126; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Half == Half::Top) if (Open) if (Powered) return 4128; else return 4130; else if (Powered) return 4132; else return 4134; else if (Open) if (Powered) return 4136; else return 4138; else if (Powered) return 4140; else return 4142; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Half == Half::Top) if (Open) if (Powered) return 4144; else return 4146; else if (Powered) return 4148; else return 4150; else if (Open) if (Powered) return 4152; else return 4154; else if (Powered) return 4156; else return 4158; else if (Half == Half::Top) if (Open) if (Powered) return 4160; else return 4162; else if (Powered) return 4164; else return 4166; else if (Open) if (Powered) return 4168; else return 4170; else if (Powered) return 4172; else return 4174; } BlockState OakTrapdoor(); eBlockFace Facing(BlockState Block); enum Half Half(BlockState Block); bool Open(BlockState Block); bool Powered(BlockState Block); } namespace OakWallSign { constexpr BlockState OakWallSign(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 3736; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 3738; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 3740; else return 3742; } BlockState OakWallSign(); eBlockFace Facing(BlockState Block); } namespace OakWood { enum class Axis { X, Y, Z }; constexpr BlockState OakWood(const enum Axis Axis) { if (Axis == Axis::X) return 109; else if (Axis == Axis::Y) return 110; else return 111; } BlockState OakWood(); enum Axis Axis(BlockState Block); } namespace Observer { constexpr BlockState Observer(const eBlockFace Facing, const bool Powered) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Powered) return 9260; else return 9261; else if (Facing == eBlockFace::BLOCK_FACE_XP) if (Powered) return 9262; else return 9263; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Powered) return 9264; else return 9265; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Powered) return 9266; else return 9267; else if (Facing == eBlockFace::BLOCK_FACE_YP) if (Powered) return 9268; else return 9269; else if (Powered) return 9270; else return 9271; } BlockState Observer(); eBlockFace Facing(BlockState Block); bool Powered(BlockState Block); } namespace Obsidian { constexpr BlockState Obsidian() { return 1434; } } namespace OrangeBanner { constexpr BlockState OrangeBanner(const unsigned char Rotation) { if (Rotation == 0) return 7913; else if (Rotation == 1) return 7914; else if (Rotation == 2) return 7915; else if (Rotation == 3) return 7916; else if (Rotation == 4) return 7917; else if (Rotation == 5) return 7918; else if (Rotation == 6) return 7919; else if (Rotation == 7) return 7920; else if (Rotation == 8) return 7921; else if (Rotation == 9) return 7922; else if (Rotation == 10) return 7923; else if (Rotation == 11) return 7924; else if (Rotation == 12) return 7925; else if (Rotation == 13) return 7926; else if (Rotation == 14) return 7927; else return 7928; } BlockState OrangeBanner(); unsigned char Rotation(BlockState Block); } namespace OrangeBed { enum class Part { Head, Foot }; constexpr BlockState OrangeBed(const eBlockFace Facing, const bool Occupied, const enum Part Part) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Occupied) if (Part == Part::Head) return 1065; else return 1066; else if (Part == Part::Head) return 1067; else return 1068; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Occupied) if (Part == Part::Head) return 1069; else return 1070; else if (Part == Part::Head) return 1071; else return 1072; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Occupied) if (Part == Part::Head) return 1073; else return 1074; else if (Part == Part::Head) return 1075; else return 1076; else if (Occupied) if (Part == Part::Head) return 1077; else return 1078; else if (Part == Part::Head) return 1079; else return 1080; } BlockState OrangeBed(); eBlockFace Facing(BlockState Block); bool Occupied(BlockState Block); enum Part Part(BlockState Block); } namespace OrangeCarpet { constexpr BlockState OrangeCarpet() { return 7867; } } namespace OrangeConcrete { constexpr BlockState OrangeConcrete() { return 9439; } } namespace OrangeConcretePowder { constexpr BlockState OrangeConcretePowder() { return 9455; } } namespace OrangeGlazedTerracotta { constexpr BlockState OrangeGlazedTerracotta(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 9378; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 9379; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 9380; else return 9381; } BlockState OrangeGlazedTerracotta(); eBlockFace Facing(BlockState Block); } namespace OrangeShulkerBox { constexpr BlockState OrangeShulkerBox(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 9284; else if (Facing == eBlockFace::BLOCK_FACE_XP) return 9285; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 9286; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 9287; else if (Facing == eBlockFace::BLOCK_FACE_YP) return 9288; else return 9289; } BlockState OrangeShulkerBox(); eBlockFace Facing(BlockState Block); } namespace OrangeStainedGlass { constexpr BlockState OrangeStainedGlass() { return 4096; } } namespace OrangeStainedGlassPane { constexpr BlockState OrangeStainedGlassPane(const bool East, const bool North, const bool South, const bool West) { if (East) if (North) if (South) if (West) return 6897; else return 6898; else if (West) return 6901; else return 6902; else if (South) if (West) return 6905; else return 6906; else if (West) return 6909; else return 6910; else if (North) if (South) if (West) return 6913; else return 6914; else if (West) return 6917; else return 6918; else if (South) if (West) return 6921; else return 6922; else if (West) return 6925; else return 6926; } BlockState OrangeStainedGlassPane(); bool East(BlockState Block); bool North(BlockState Block); bool South(BlockState Block); bool West(BlockState Block); } namespace OrangeTerracotta { constexpr BlockState OrangeTerracotta() { return 6848; } } namespace OrangeTulip { constexpr BlockState OrangeTulip() { return 1418; } } namespace OrangeWallBanner { constexpr BlockState OrangeWallBanner(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 8157; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 8158; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 8159; else return 8160; } BlockState OrangeWallBanner(); eBlockFace Facing(BlockState Block); } namespace OrangeWool { constexpr BlockState OrangeWool() { return 1385; } } namespace OxeyeDaisy { constexpr BlockState OxeyeDaisy() { return 1421; } } namespace PackedIce { constexpr BlockState PackedIce() { return 7884; } } namespace Peony { enum class Half { Upper, Lower }; constexpr BlockState Peony(const enum Half Half) { if (Half == Half::Upper) return 7891; else return 7892; } BlockState Peony(); enum Half Half(BlockState Block); } namespace PetrifiedOakSlab { enum class Type { Top, Bottom, Double }; constexpr BlockState PetrifiedOakSlab(const enum Type Type) { if (Type == Type::Top) return 8361; else if (Type == Type::Bottom) return 8363; else return 8365; } BlockState PetrifiedOakSlab(); enum Type Type(BlockState Block); } namespace PinkBanner { constexpr BlockState PinkBanner(const unsigned char Rotation) { if (Rotation == 0) return 7993; else if (Rotation == 1) return 7994; else if (Rotation == 2) return 7995; else if (Rotation == 3) return 7996; else if (Rotation == 4) return 7997; else if (Rotation == 5) return 7998; else if (Rotation == 6) return 7999; else if (Rotation == 7) return 8000; else if (Rotation == 8) return 8001; else if (Rotation == 9) return 8002; else if (Rotation == 10) return 8003; else if (Rotation == 11) return 8004; else if (Rotation == 12) return 8005; else if (Rotation == 13) return 8006; else if (Rotation == 14) return 8007; else return 8008; } BlockState PinkBanner(); unsigned char Rotation(BlockState Block); } namespace PinkBed { enum class Part { Head, Foot }; constexpr BlockState PinkBed(const eBlockFace Facing, const bool Occupied, const enum Part Part) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Occupied) if (Part == Part::Head) return 1145; else return 1146; else if (Part == Part::Head) return 1147; else return 1148; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Occupied) if (Part == Part::Head) return 1149; else return 1150; else if (Part == Part::Head) return 1151; else return 1152; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Occupied) if (Part == Part::Head) return 1153; else return 1154; else if (Part == Part::Head) return 1155; else return 1156; else if (Occupied) if (Part == Part::Head) return 1157; else return 1158; else if (Part == Part::Head) return 1159; else return 1160; } BlockState PinkBed(); eBlockFace Facing(BlockState Block); bool Occupied(BlockState Block); enum Part Part(BlockState Block); } namespace PinkCarpet { constexpr BlockState PinkCarpet() { return 7872; } } namespace PinkConcrete { constexpr BlockState PinkConcrete() { return 9444; } } namespace PinkConcretePowder { constexpr BlockState PinkConcretePowder() { return 9460; } } namespace PinkGlazedTerracotta { constexpr BlockState PinkGlazedTerracotta(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 9398; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 9399; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 9400; else return 9401; } BlockState PinkGlazedTerracotta(); eBlockFace Facing(BlockState Block); } namespace PinkShulkerBox { constexpr BlockState PinkShulkerBox(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 9314; else if (Facing == eBlockFace::BLOCK_FACE_XP) return 9315; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 9316; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 9317; else if (Facing == eBlockFace::BLOCK_FACE_YP) return 9318; else return 9319; } BlockState PinkShulkerBox(); eBlockFace Facing(BlockState Block); } namespace PinkStainedGlass { constexpr BlockState PinkStainedGlass() { return 4101; } } namespace PinkStainedGlassPane { constexpr BlockState PinkStainedGlassPane(const bool East, const bool North, const bool South, const bool West) { if (East) if (North) if (South) if (West) return 7057; else return 7058; else if (West) return 7061; else return 7062; else if (South) if (West) return 7065; else return 7066; else if (West) return 7069; else return 7070; else if (North) if (South) if (West) return 7073; else return 7074; else if (West) return 7077; else return 7078; else if (South) if (West) return 7081; else return 7082; else if (West) return 7085; else return 7086; } BlockState PinkStainedGlassPane(); bool East(BlockState Block); bool North(BlockState Block); bool South(BlockState Block); bool West(BlockState Block); } namespace PinkTerracotta { constexpr BlockState PinkTerracotta() { return 6853; } } namespace PinkTulip { constexpr BlockState PinkTulip() { return 1420; } } namespace PinkWallBanner { constexpr BlockState PinkWallBanner(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 8177; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 8178; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 8179; else return 8180; } BlockState PinkWallBanner(); eBlockFace Facing(BlockState Block); } namespace PinkWool { constexpr BlockState PinkWool() { return 1390; } } namespace Piston { constexpr BlockState Piston(const bool Extended, const eBlockFace Facing) { if (Extended) if (Facing == eBlockFace::BLOCK_FACE_ZM) return 1348; else if (Facing == eBlockFace::BLOCK_FACE_XP) return 1349; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 1350; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 1351; else if (Facing == eBlockFace::BLOCK_FACE_YP) return 1352; else return 1353; else if (Facing == eBlockFace::BLOCK_FACE_ZM) return 1354; else if (Facing == eBlockFace::BLOCK_FACE_XP) return 1355; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 1356; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 1357; else if (Facing == eBlockFace::BLOCK_FACE_YP) return 1358; else return 1359; } BlockState Piston(); bool Extended(BlockState Block); eBlockFace Facing(BlockState Block); } namespace PistonHead { enum class Type { Normal, Sticky }; constexpr BlockState PistonHead(const eBlockFace Facing, const bool Short, const enum Type Type) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Short) if (Type == Type::Normal) return 1360; else return 1361; else if (Type == Type::Normal) return 1362; else return 1363; else if (Facing == eBlockFace::BLOCK_FACE_XP) if (Short) if (Type == Type::Normal) return 1364; else return 1365; else if (Type == Type::Normal) return 1366; else return 1367; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Short) if (Type == Type::Normal) return 1368; else return 1369; else if (Type == Type::Normal) return 1370; else return 1371; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Short) if (Type == Type::Normal) return 1372; else return 1373; else if (Type == Type::Normal) return 1374; else return 1375; else if (Facing == eBlockFace::BLOCK_FACE_YP) if (Short) if (Type == Type::Normal) return 1376; else return 1377; else if (Type == Type::Normal) return 1378; else return 1379; else if (Short) if (Type == Type::Normal) return 1380; else return 1381; else if (Type == Type::Normal) return 1382; else return 1383; } BlockState PistonHead(); eBlockFace Facing(BlockState Block); bool Short(BlockState Block); enum Type Type(BlockState Block); } namespace PlayerHead { constexpr BlockState PlayerHead(const unsigned char Rotation) { if (Rotation == 0) return 6550; else if (Rotation == 1) return 6551; else if (Rotation == 2) return 6552; else if (Rotation == 3) return 6553; else if (Rotation == 4) return 6554; else if (Rotation == 5) return 6555; else if (Rotation == 6) return 6556; else if (Rotation == 7) return 6557; else if (Rotation == 8) return 6558; else if (Rotation == 9) return 6559; else if (Rotation == 10) return 6560; else if (Rotation == 11) return 6561; else if (Rotation == 12) return 6562; else if (Rotation == 13) return 6563; else if (Rotation == 14) return 6564; else return 6565; } BlockState PlayerHead(); unsigned char Rotation(BlockState Block); } namespace PlayerWallHead { constexpr BlockState PlayerWallHead(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 6566; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 6567; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 6568; else return 6569; } BlockState PlayerWallHead(); eBlockFace Facing(BlockState Block); } namespace Podzol { constexpr BlockState Podzol(const bool Snowy) { if (Snowy) return 12; else return 13; } BlockState Podzol(); bool Snowy(BlockState Block); } namespace PolishedAndesite { constexpr BlockState PolishedAndesite() { return 7; } } namespace PolishedAndesiteSlab { enum class Type { Top, Bottom, Double }; constexpr BlockState PolishedAndesiteSlab(const enum Type Type) { if (Type == Type::Top) return 10856; else if (Type == Type::Bottom) return 10858; else return 10860; } BlockState PolishedAndesiteSlab(); enum Type Type(BlockState Block); } namespace PolishedAndesiteStairs { enum class Half { Top, Bottom }; enum class Shape { Straight, InnerLeft, InnerRight, OuterLeft, OuterRight }; constexpr BlockState PolishedAndesiteStairs(const eBlockFace Facing, const enum Half Half, const enum Shape Shape) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Half == Half::Top) if (Shape == Shape::Straight) return 10630; else if (Shape == Shape::InnerLeft) return 10632; else if (Shape == Shape::InnerRight) return 10634; else if (Shape == Shape::OuterLeft) return 10636; else return 10638; else if (Shape == Shape::Straight) return 10640; else if (Shape == Shape::InnerLeft) return 10642; else if (Shape == Shape::InnerRight) return 10644; else if (Shape == Shape::OuterLeft) return 10646; else return 10648; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Half == Half::Top) if (Shape == Shape::Straight) return 10650; else if (Shape == Shape::InnerLeft) return 10652; else if (Shape == Shape::InnerRight) return 10654; else if (Shape == Shape::OuterLeft) return 10656; else return 10658; else if (Shape == Shape::Straight) return 10660; else if (Shape == Shape::InnerLeft) return 10662; else if (Shape == Shape::InnerRight) return 10664; else if (Shape == Shape::OuterLeft) return 10666; else return 10668; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Half == Half::Top) if (Shape == Shape::Straight) return 10670; else if (Shape == Shape::InnerLeft) return 10672; else if (Shape == Shape::InnerRight) return 10674; else if (Shape == Shape::OuterLeft) return 10676; else return 10678; else if (Shape == Shape::Straight) return 10680; else if (Shape == Shape::InnerLeft) return 10682; else if (Shape == Shape::InnerRight) return 10684; else if (Shape == Shape::OuterLeft) return 10686; else return 10688; else if (Half == Half::Top) if (Shape == Shape::Straight) return 10690; else if (Shape == Shape::InnerLeft) return 10692; else if (Shape == Shape::InnerRight) return 10694; else if (Shape == Shape::OuterLeft) return 10696; else return 10698; else if (Shape == Shape::Straight) return 10700; else if (Shape == Shape::InnerLeft) return 10702; else if (Shape == Shape::InnerRight) return 10704; else if (Shape == Shape::OuterLeft) return 10706; else return 10708; } BlockState PolishedAndesiteStairs(); eBlockFace Facing(BlockState Block); enum Half Half(BlockState Block); enum Shape Shape(BlockState Block); } namespace PolishedBasalt { enum class Axis { X, Y, Z }; constexpr BlockState PolishedBasalt(const enum Axis Axis) { if (Axis == Axis::X) return 4005; else if (Axis == Axis::Y) return 4006; else return 4007; } BlockState PolishedBasalt(); enum Axis Axis(BlockState Block); } namespace PolishedBlackstone { constexpr BlockState PolishedBlackstone() { return 16250; } } namespace PolishedBlackstoneBrickSlab { enum class Type { Top, Bottom, Double }; constexpr BlockState PolishedBlackstoneBrickSlab(const enum Type Type) { if (Type == Type::Top) return 16255; else if (Type == Type::Bottom) return 16257; else return 16259; } BlockState PolishedBlackstoneBrickSlab(); enum Type Type(BlockState Block); } namespace PolishedBlackstoneBrickStairs { enum class Half { Top, Bottom }; enum class Shape { Straight, InnerLeft, InnerRight, OuterLeft, OuterRight }; constexpr BlockState PolishedBlackstoneBrickStairs(const eBlockFace Facing, const enum Half Half, const enum Shape Shape) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Half == Half::Top) if (Shape == Shape::Straight) return 16261; else if (Shape == Shape::InnerLeft) return 16263; else if (Shape == Shape::InnerRight) return 16265; else if (Shape == Shape::OuterLeft) return 16267; else return 16269; else if (Shape == Shape::Straight) return 16271; else if (Shape == Shape::InnerLeft) return 16273; else if (Shape == Shape::InnerRight) return 16275; else if (Shape == Shape::OuterLeft) return 16277; else return 16279; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Half == Half::Top) if (Shape == Shape::Straight) return 16281; else if (Shape == Shape::InnerLeft) return 16283; else if (Shape == Shape::InnerRight) return 16285; else if (Shape == Shape::OuterLeft) return 16287; else return 16289; else if (Shape == Shape::Straight) return 16291; else if (Shape == Shape::InnerLeft) return 16293; else if (Shape == Shape::InnerRight) return 16295; else if (Shape == Shape::OuterLeft) return 16297; else return 16299; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Half == Half::Top) if (Shape == Shape::Straight) return 16301; else if (Shape == Shape::InnerLeft) return 16303; else if (Shape == Shape::InnerRight) return 16305; else if (Shape == Shape::OuterLeft) return 16307; else return 16309; else if (Shape == Shape::Straight) return 16311; else if (Shape == Shape::InnerLeft) return 16313; else if (Shape == Shape::InnerRight) return 16315; else if (Shape == Shape::OuterLeft) return 16317; else return 16319; else if (Half == Half::Top) if (Shape == Shape::Straight) return 16321; else if (Shape == Shape::InnerLeft) return 16323; else if (Shape == Shape::InnerRight) return 16325; else if (Shape == Shape::OuterLeft) return 16327; else return 16329; else if (Shape == Shape::Straight) return 16331; else if (Shape == Shape::InnerLeft) return 16333; else if (Shape == Shape::InnerRight) return 16335; else if (Shape == Shape::OuterLeft) return 16337; else return 16339; } BlockState PolishedBlackstoneBrickStairs(); eBlockFace Facing(BlockState Block); enum Half Half(BlockState Block); enum Shape Shape(BlockState Block); } namespace PolishedBlackstoneBrickWall { enum class East { None, Low, Tall }; enum class North { None, Low, Tall }; enum class South { None, Low, Tall }; enum class West { None, Low, Tall }; constexpr BlockState PolishedBlackstoneBrickWall(const enum East East, const enum North North, const enum South South, const bool Up, const enum West West) { if (East == East::None) if (North == North::None) if (South == South::None) if (Up) if (West == West::None) return 16343; else if (West == West::Low) return 16344; else return 16345; else if (West == West::None) return 16349; else if (West == West::Low) return 16350; else return 16351; else if (South == South::Low) if (Up) if (West == West::None) return 16355; else if (West == West::Low) return 16356; else return 16357; else if (West == West::None) return 16361; else if (West == West::Low) return 16362; else return 16363; else if (Up) if (West == West::None) return 16367; else if (West == West::Low) return 16368; else return 16369; else if (West == West::None) return 16373; else if (West == West::Low) return 16374; else return 16375; else if (North == North::Low) if (South == South::None) if (Up) if (West == West::None) return 16379; else if (West == West::Low) return 16380; else return 16381; else if (West == West::None) return 16385; else if (West == West::Low) return 16386; else return 16387; else if (South == South::Low) if (Up) if (West == West::None) return 16391; else if (West == West::Low) return 16392; else return 16393; else if (West == West::None) return 16397; else if (West == West::Low) return 16398; else return 16399; else if (Up) if (West == West::None) return 16403; else if (West == West::Low) return 16404; else return 16405; else if (West == West::None) return 16409; else if (West == West::Low) return 16410; else return 16411; else if (South == South::None) if (Up) if (West == West::None) return 16415; else if (West == West::Low) return 16416; else return 16417; else if (West == West::None) return 16421; else if (West == West::Low) return 16422; else return 16423; else if (South == South::Low) if (Up) if (West == West::None) return 16427; else if (West == West::Low) return 16428; else return 16429; else if (West == West::None) return 16433; else if (West == West::Low) return 16434; else return 16435; else if (Up) if (West == West::None) return 16439; else if (West == West::Low) return 16440; else return 16441; else if (West == West::None) return 16445; else if (West == West::Low) return 16446; else return 16447; else if (East == East::Low) if (North == North::None) if (South == South::None) if (Up) if (West == West::None) return 16451; else if (West == West::Low) return 16452; else return 16453; else if (West == West::None) return 16457; else if (West == West::Low) return 16458; else return 16459; else if (South == South::Low) if (Up) if (West == West::None) return 16463; else if (West == West::Low) return 16464; else return 16465; else if (West == West::None) return 16469; else if (West == West::Low) return 16470; else return 16471; else if (Up) if (West == West::None) return 16475; else if (West == West::Low) return 16476; else return 16477; else if (West == West::None) return 16481; else if (West == West::Low) return 16482; else return 16483; else if (North == North::Low) if (South == South::None) if (Up) if (West == West::None) return 16487; else if (West == West::Low) return 16488; else return 16489; else if (West == West::None) return 16493; else if (West == West::Low) return 16494; else return 16495; else if (South == South::Low) if (Up) if (West == West::None) return 16499; else if (West == West::Low) return 16500; else return 16501; else if (West == West::None) return 16505; else if (West == West::Low) return 16506; else return 16507; else if (Up) if (West == West::None) return 16511; else if (West == West::Low) return 16512; else return 16513; else if (West == West::None) return 16517; else if (West == West::Low) return 16518; else return 16519; else if (South == South::None) if (Up) if (West == West::None) return 16523; else if (West == West::Low) return 16524; else return 16525; else if (West == West::None) return 16529; else if (West == West::Low) return 16530; else return 16531; else if (South == South::Low) if (Up) if (West == West::None) return 16535; else if (West == West::Low) return 16536; else return 16537; else if (West == West::None) return 16541; else if (West == West::Low) return 16542; else return 16543; else if (Up) if (West == West::None) return 16547; else if (West == West::Low) return 16548; else return 16549; else if (West == West::None) return 16553; else if (West == West::Low) return 16554; else return 16555; else if (North == North::None) if (South == South::None) if (Up) if (West == West::None) return 16559; else if (West == West::Low) return 16560; else return 16561; else if (West == West::None) return 16565; else if (West == West::Low) return 16566; else return 16567; else if (South == South::Low) if (Up) if (West == West::None) return 16571; else if (West == West::Low) return 16572; else return 16573; else if (West == West::None) return 16577; else if (West == West::Low) return 16578; else return 16579; else if (Up) if (West == West::None) return 16583; else if (West == West::Low) return 16584; else return 16585; else if (West == West::None) return 16589; else if (West == West::Low) return 16590; else return 16591; else if (North == North::Low) if (South == South::None) if (Up) if (West == West::None) return 16595; else if (West == West::Low) return 16596; else return 16597; else if (West == West::None) return 16601; else if (West == West::Low) return 16602; else return 16603; else if (South == South::Low) if (Up) if (West == West::None) return 16607; else if (West == West::Low) return 16608; else return 16609; else if (West == West::None) return 16613; else if (West == West::Low) return 16614; else return 16615; else if (Up) if (West == West::None) return 16619; else if (West == West::Low) return 16620; else return 16621; else if (West == West::None) return 16625; else if (West == West::Low) return 16626; else return 16627; else if (South == South::None) if (Up) if (West == West::None) return 16631; else if (West == West::Low) return 16632; else return 16633; else if (West == West::None) return 16637; else if (West == West::Low) return 16638; else return 16639; else if (South == South::Low) if (Up) if (West == West::None) return 16643; else if (West == West::Low) return 16644; else return 16645; else if (West == West::None) return 16649; else if (West == West::Low) return 16650; else return 16651; else if (Up) if (West == West::None) return 16655; else if (West == West::Low) return 16656; else return 16657; else if (West == West::None) return 16661; else if (West == West::Low) return 16662; else return 16663; } BlockState PolishedBlackstoneBrickWall(); enum East East(BlockState Block); enum North North(BlockState Block); enum South South(BlockState Block); bool Up(BlockState Block); enum West West(BlockState Block); } namespace PolishedBlackstoneBricks { constexpr BlockState PolishedBlackstoneBricks() { return 16251; } } namespace PolishedBlackstoneButton { enum class Face { Floor, Wall, Ceiling }; constexpr BlockState PolishedBlackstoneButton(const enum Face Face, const eBlockFace Facing, const bool Powered) { if (Face == Face::Floor) if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Powered) return 16753; else return 16754; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Powered) return 16755; else return 16756; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Powered) return 16757; else return 16758; else if (Powered) return 16759; else return 16760; else if (Face == Face::Wall) if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Powered) return 16761; else return 16762; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Powered) return 16763; else return 16764; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Powered) return 16765; else return 16766; else if (Powered) return 16767; else return 16768; else if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Powered) return 16769; else return 16770; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Powered) return 16771; else return 16772; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Powered) return 16773; else return 16774; else if (Powered) return 16775; else return 16776; } BlockState PolishedBlackstoneButton(); enum Face Face(BlockState Block); eBlockFace Facing(BlockState Block); bool Powered(BlockState Block); } namespace PolishedBlackstonePressurePlate { constexpr BlockState PolishedBlackstonePressurePlate(const bool Powered) { if (Powered) return 16751; else return 16752; } BlockState PolishedBlackstonePressurePlate(); bool Powered(BlockState Block); } namespace PolishedBlackstoneSlab { enum class Type { Top, Bottom, Double }; constexpr BlockState PolishedBlackstoneSlab(const enum Type Type) { if (Type == Type::Top) return 16746; else if (Type == Type::Bottom) return 16748; else return 16750; } BlockState PolishedBlackstoneSlab(); enum Type Type(BlockState Block); } namespace PolishedBlackstoneStairs { enum class Half { Top, Bottom }; enum class Shape { Straight, InnerLeft, InnerRight, OuterLeft, OuterRight }; constexpr BlockState PolishedBlackstoneStairs(const eBlockFace Facing, const enum Half Half, const enum Shape Shape) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Half == Half::Top) if (Shape == Shape::Straight) return 16666; else if (Shape == Shape::InnerLeft) return 16668; else if (Shape == Shape::InnerRight) return 16670; else if (Shape == Shape::OuterLeft) return 16672; else return 16674; else if (Shape == Shape::Straight) return 16676; else if (Shape == Shape::InnerLeft) return 16678; else if (Shape == Shape::InnerRight) return 16680; else if (Shape == Shape::OuterLeft) return 16682; else return 16684; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Half == Half::Top) if (Shape == Shape::Straight) return 16686; else if (Shape == Shape::InnerLeft) return 16688; else if (Shape == Shape::InnerRight) return 16690; else if (Shape == Shape::OuterLeft) return 16692; else return 16694; else if (Shape == Shape::Straight) return 16696; else if (Shape == Shape::InnerLeft) return 16698; else if (Shape == Shape::InnerRight) return 16700; else if (Shape == Shape::OuterLeft) return 16702; else return 16704; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Half == Half::Top) if (Shape == Shape::Straight) return 16706; else if (Shape == Shape::InnerLeft) return 16708; else if (Shape == Shape::InnerRight) return 16710; else if (Shape == Shape::OuterLeft) return 16712; else return 16714; else if (Shape == Shape::Straight) return 16716; else if (Shape == Shape::InnerLeft) return 16718; else if (Shape == Shape::InnerRight) return 16720; else if (Shape == Shape::OuterLeft) return 16722; else return 16724; else if (Half == Half::Top) if (Shape == Shape::Straight) return 16726; else if (Shape == Shape::InnerLeft) return 16728; else if (Shape == Shape::InnerRight) return 16730; else if (Shape == Shape::OuterLeft) return 16732; else return 16734; else if (Shape == Shape::Straight) return 16736; else if (Shape == Shape::InnerLeft) return 16738; else if (Shape == Shape::InnerRight) return 16740; else if (Shape == Shape::OuterLeft) return 16742; else return 16744; } BlockState PolishedBlackstoneStairs(); eBlockFace Facing(BlockState Block); enum Half Half(BlockState Block); enum Shape Shape(BlockState Block); } namespace PolishedBlackstoneWall { enum class East { None, Low, Tall }; enum class North { None, Low, Tall }; enum class South { None, Low, Tall }; enum class West { None, Low, Tall }; constexpr BlockState PolishedBlackstoneWall(const enum East East, const enum North North, const enum South South, const bool Up, const enum West West) { if (East == East::None) if (North == North::None) if (South == South::None) if (Up) if (West == West::None) return 16780; else if (West == West::Low) return 16781; else return 16782; else if (West == West::None) return 16786; else if (West == West::Low) return 16787; else return 16788; else if (South == South::Low) if (Up) if (West == West::None) return 16792; else if (West == West::Low) return 16793; else return 16794; else if (West == West::None) return 16798; else if (West == West::Low) return 16799; else return 16800; else if (Up) if (West == West::None) return 16804; else if (West == West::Low) return 16805; else return 16806; else if (West == West::None) return 16810; else if (West == West::Low) return 16811; else return 16812; else if (North == North::Low) if (South == South::None) if (Up) if (West == West::None) return 16816; else if (West == West::Low) return 16817; else return 16818; else if (West == West::None) return 16822; else if (West == West::Low) return 16823; else return 16824; else if (South == South::Low) if (Up) if (West == West::None) return 16828; else if (West == West::Low) return 16829; else return 16830; else if (West == West::None) return 16834; else if (West == West::Low) return 16835; else return 16836; else if (Up) if (West == West::None) return 16840; else if (West == West::Low) return 16841; else return 16842; else if (West == West::None) return 16846; else if (West == West::Low) return 16847; else return 16848; else if (South == South::None) if (Up) if (West == West::None) return 16852; else if (West == West::Low) return 16853; else return 16854; else if (West == West::None) return 16858; else if (West == West::Low) return 16859; else return 16860; else if (South == South::Low) if (Up) if (West == West::None) return 16864; else if (West == West::Low) return 16865; else return 16866; else if (West == West::None) return 16870; else if (West == West::Low) return 16871; else return 16872; else if (Up) if (West == West::None) return 16876; else if (West == West::Low) return 16877; else return 16878; else if (West == West::None) return 16882; else if (West == West::Low) return 16883; else return 16884; else if (East == East::Low) if (North == North::None) if (South == South::None) if (Up) if (West == West::None) return 16888; else if (West == West::Low) return 16889; else return 16890; else if (West == West::None) return 16894; else if (West == West::Low) return 16895; else return 16896; else if (South == South::Low) if (Up) if (West == West::None) return 16900; else if (West == West::Low) return 16901; else return 16902; else if (West == West::None) return 16906; else if (West == West::Low) return 16907; else return 16908; else if (Up) if (West == West::None) return 16912; else if (West == West::Low) return 16913; else return 16914; else if (West == West::None) return 16918; else if (West == West::Low) return 16919; else return 16920; else if (North == North::Low) if (South == South::None) if (Up) if (West == West::None) return 16924; else if (West == West::Low) return 16925; else return 16926; else if (West == West::None) return 16930; else if (West == West::Low) return 16931; else return 16932; else if (South == South::Low) if (Up) if (West == West::None) return 16936; else if (West == West::Low) return 16937; else return 16938; else if (West == West::None) return 16942; else if (West == West::Low) return 16943; else return 16944; else if (Up) if (West == West::None) return 16948; else if (West == West::Low) return 16949; else return 16950; else if (West == West::None) return 16954; else if (West == West::Low) return 16955; else return 16956; else if (South == South::None) if (Up) if (West == West::None) return 16960; else if (West == West::Low) return 16961; else return 16962; else if (West == West::None) return 16966; else if (West == West::Low) return 16967; else return 16968; else if (South == South::Low) if (Up) if (West == West::None) return 16972; else if (West == West::Low) return 16973; else return 16974; else if (West == West::None) return 16978; else if (West == West::Low) return 16979; else return 16980; else if (Up) if (West == West::None) return 16984; else if (West == West::Low) return 16985; else return 16986; else if (West == West::None) return 16990; else if (West == West::Low) return 16991; else return 16992; else if (North == North::None) if (South == South::None) if (Up) if (West == West::None) return 16996; else if (West == West::Low) return 16997; else return 16998; else if (West == West::None) return 17002; else if (West == West::Low) return 17003; else return 17004; else if (South == South::Low) if (Up) if (West == West::None) return 17008; else if (West == West::Low) return 17009; else return 17010; else if (West == West::None) return 17014; else if (West == West::Low) return 17015; else return 17016; else if (Up) if (West == West::None) return 17020; else if (West == West::Low) return 17021; else return 17022; else if (West == West::None) return 17026; else if (West == West::Low) return 17027; else return 17028; else if (North == North::Low) if (South == South::None) if (Up) if (West == West::None) return 17032; else if (West == West::Low) return 17033; else return 17034; else if (West == West::None) return 17038; else if (West == West::Low) return 17039; else return 17040; else if (South == South::Low) if (Up) if (West == West::None) return 17044; else if (West == West::Low) return 17045; else return 17046; else if (West == West::None) return 17050; else if (West == West::Low) return 17051; else return 17052; else if (Up) if (West == West::None) return 17056; else if (West == West::Low) return 17057; else return 17058; else if (West == West::None) return 17062; else if (West == West::Low) return 17063; else return 17064; else if (South == South::None) if (Up) if (West == West::None) return 17068; else if (West == West::Low) return 17069; else return 17070; else if (West == West::None) return 17074; else if (West == West::Low) return 17075; else return 17076; else if (South == South::Low) if (Up) if (West == West::None) return 17080; else if (West == West::Low) return 17081; else return 17082; else if (West == West::None) return 17086; else if (West == West::Low) return 17087; else return 17088; else if (Up) if (West == West::None) return 17092; else if (West == West::Low) return 17093; else return 17094; else if (West == West::None) return 17098; else if (West == West::Low) return 17099; else return 17100; } BlockState PolishedBlackstoneWall(); enum East East(BlockState Block); enum North North(BlockState Block); enum South South(BlockState Block); bool Up(BlockState Block); enum West West(BlockState Block); } namespace PolishedDiorite { constexpr BlockState PolishedDiorite() { return 5; } } namespace PolishedDioriteSlab { enum class Type { Top, Bottom, Double }; constexpr BlockState PolishedDioriteSlab(const enum Type Type) { if (Type == Type::Top) return 10808; else if (Type == Type::Bottom) return 10810; else return 10812; } BlockState PolishedDioriteSlab(); enum Type Type(BlockState Block); } namespace PolishedDioriteStairs { enum class Half { Top, Bottom }; enum class Shape { Straight, InnerLeft, InnerRight, OuterLeft, OuterRight }; constexpr BlockState PolishedDioriteStairs(const eBlockFace Facing, const enum Half Half, const enum Shape Shape) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Half == Half::Top) if (Shape == Shape::Straight) return 9910; else if (Shape == Shape::InnerLeft) return 9912; else if (Shape == Shape::InnerRight) return 9914; else if (Shape == Shape::OuterLeft) return 9916; else return 9918; else if (Shape == Shape::Straight) return 9920; else if (Shape == Shape::InnerLeft) return 9922; else if (Shape == Shape::InnerRight) return 9924; else if (Shape == Shape::OuterLeft) return 9926; else return 9928; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Half == Half::Top) if (Shape == Shape::Straight) return 9930; else if (Shape == Shape::InnerLeft) return 9932; else if (Shape == Shape::InnerRight) return 9934; else if (Shape == Shape::OuterLeft) return 9936; else return 9938; else if (Shape == Shape::Straight) return 9940; else if (Shape == Shape::InnerLeft) return 9942; else if (Shape == Shape::InnerRight) return 9944; else if (Shape == Shape::OuterLeft) return 9946; else return 9948; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Half == Half::Top) if (Shape == Shape::Straight) return 9950; else if (Shape == Shape::InnerLeft) return 9952; else if (Shape == Shape::InnerRight) return 9954; else if (Shape == Shape::OuterLeft) return 9956; else return 9958; else if (Shape == Shape::Straight) return 9960; else if (Shape == Shape::InnerLeft) return 9962; else if (Shape == Shape::InnerRight) return 9964; else if (Shape == Shape::OuterLeft) return 9966; else return 9968; else if (Half == Half::Top) if (Shape == Shape::Straight) return 9970; else if (Shape == Shape::InnerLeft) return 9972; else if (Shape == Shape::InnerRight) return 9974; else if (Shape == Shape::OuterLeft) return 9976; else return 9978; else if (Shape == Shape::Straight) return 9980; else if (Shape == Shape::InnerLeft) return 9982; else if (Shape == Shape::InnerRight) return 9984; else if (Shape == Shape::OuterLeft) return 9986; else return 9988; } BlockState PolishedDioriteStairs(); eBlockFace Facing(BlockState Block); enum Half Half(BlockState Block); enum Shape Shape(BlockState Block); } namespace PolishedGranite { constexpr BlockState PolishedGranite() { return 3; } } namespace PolishedGraniteSlab { enum class Type { Top, Bottom, Double }; constexpr BlockState PolishedGraniteSlab(const enum Type Type) { if (Type == Type::Top) return 10790; else if (Type == Type::Bottom) return 10792; else return 10794; } BlockState PolishedGraniteSlab(); enum Type Type(BlockState Block); } namespace PolishedGraniteStairs { enum class Half { Top, Bottom }; enum class Shape { Straight, InnerLeft, InnerRight, OuterLeft, OuterRight }; constexpr BlockState PolishedGraniteStairs(const eBlockFace Facing, const enum Half Half, const enum Shape Shape) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Half == Half::Top) if (Shape == Shape::Straight) return 9670; else if (Shape == Shape::InnerLeft) return 9672; else if (Shape == Shape::InnerRight) return 9674; else if (Shape == Shape::OuterLeft) return 9676; else return 9678; else if (Shape == Shape::Straight) return 9680; else if (Shape == Shape::InnerLeft) return 9682; else if (Shape == Shape::InnerRight) return 9684; else if (Shape == Shape::OuterLeft) return 9686; else return 9688; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Half == Half::Top) if (Shape == Shape::Straight) return 9690; else if (Shape == Shape::InnerLeft) return 9692; else if (Shape == Shape::InnerRight) return 9694; else if (Shape == Shape::OuterLeft) return 9696; else return 9698; else if (Shape == Shape::Straight) return 9700; else if (Shape == Shape::InnerLeft) return 9702; else if (Shape == Shape::InnerRight) return 9704; else if (Shape == Shape::OuterLeft) return 9706; else return 9708; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Half == Half::Top) if (Shape == Shape::Straight) return 9710; else if (Shape == Shape::InnerLeft) return 9712; else if (Shape == Shape::InnerRight) return 9714; else if (Shape == Shape::OuterLeft) return 9716; else return 9718; else if (Shape == Shape::Straight) return 9720; else if (Shape == Shape::InnerLeft) return 9722; else if (Shape == Shape::InnerRight) return 9724; else if (Shape == Shape::OuterLeft) return 9726; else return 9728; else if (Half == Half::Top) if (Shape == Shape::Straight) return 9730; else if (Shape == Shape::InnerLeft) return 9732; else if (Shape == Shape::InnerRight) return 9734; else if (Shape == Shape::OuterLeft) return 9736; else return 9738; else if (Shape == Shape::Straight) return 9740; else if (Shape == Shape::InnerLeft) return 9742; else if (Shape == Shape::InnerRight) return 9744; else if (Shape == Shape::OuterLeft) return 9746; else return 9748; } BlockState PolishedGraniteStairs(); eBlockFace Facing(BlockState Block); enum Half Half(BlockState Block); enum Shape Shape(BlockState Block); } namespace Poppy { constexpr BlockState Poppy() { return 1413; } } namespace Potatoes { constexpr BlockState Potatoes(const unsigned char Age) { if (Age == 0) return 6338; else if (Age == 1) return 6339; else if (Age == 2) return 6340; else if (Age == 3) return 6341; else if (Age == 4) return 6342; else if (Age == 5) return 6343; else if (Age == 6) return 6344; else return 6345; } BlockState Potatoes(); unsigned char Age(BlockState Block); } namespace PottedAcaciaSapling { constexpr BlockState PottedAcaciaSapling() { return 6310; } } namespace PottedAllium { constexpr BlockState PottedAllium() { return 6316; } } namespace PottedAzureBluet { constexpr BlockState PottedAzureBluet() { return 6317; } } namespace PottedBamboo { constexpr BlockState PottedBamboo() { return 9664; } } namespace PottedBirchSapling { constexpr BlockState PottedBirchSapling() { return 6308; } } namespace PottedBlueOrchid { constexpr BlockState PottedBlueOrchid() { return 6315; } } namespace PottedBrownMushroom { constexpr BlockState PottedBrownMushroom() { return 6327; } } namespace PottedCactus { constexpr BlockState PottedCactus() { return 6329; } } namespace PottedCornflower { constexpr BlockState PottedCornflower() { return 6323; } } namespace PottedCrimsonFungus { constexpr BlockState PottedCrimsonFungus() { return 15834; } } namespace PottedCrimsonRoots { constexpr BlockState PottedCrimsonRoots() { return 15836; } } namespace PottedDandelion { constexpr BlockState PottedDandelion() { return 6313; } } namespace PottedDarkOakSapling { constexpr BlockState PottedDarkOakSapling() { return 6311; } } namespace PottedDeadBush { constexpr BlockState PottedDeadBush() { return 6328; } } namespace PottedFern { constexpr BlockState PottedFern() { return 6312; } } namespace PottedJungleSapling { constexpr BlockState PottedJungleSapling() { return 6309; } } namespace PottedLilyOfTheValley { constexpr BlockState PottedLilyOfTheValley() { return 6324; } } namespace PottedOakSapling { constexpr BlockState PottedOakSapling() { return 6306; } } namespace PottedOrangeTulip { constexpr BlockState PottedOrangeTulip() { return 6319; } } namespace PottedOxeyeDaisy { constexpr BlockState PottedOxeyeDaisy() { return 6322; } } namespace PottedPinkTulip { constexpr BlockState PottedPinkTulip() { return 6321; } } namespace PottedPoppy { constexpr BlockState PottedPoppy() { return 6314; } } namespace PottedRedMushroom { constexpr BlockState PottedRedMushroom() { return 6326; } } namespace PottedRedTulip { constexpr BlockState PottedRedTulip() { return 6318; } } namespace PottedSpruceSapling { constexpr BlockState PottedSpruceSapling() { return 6307; } } namespace PottedWarpedFungus { constexpr BlockState PottedWarpedFungus() { return 15835; } } namespace PottedWarpedRoots { constexpr BlockState PottedWarpedRoots() { return 15837; } } namespace PottedWhiteTulip { constexpr BlockState PottedWhiteTulip() { return 6320; } } namespace PottedWitherRose { constexpr BlockState PottedWitherRose() { return 6325; } } namespace PoweredRail { enum class Shape { NorthSouth, EastWest, AscendingEast, AscendingWest, AscendingNorth, AscendingSouth }; constexpr BlockState PoweredRail(const bool Powered, const enum Shape Shape) { if (Powered) if (Shape == Shape::NorthSouth) return 1305; else if (Shape == Shape::EastWest) return 1306; else if (Shape == Shape::AscendingEast) return 1307; else if (Shape == Shape::AscendingWest) return 1308; else if (Shape == Shape::AscendingNorth) return 1309; else return 1310; else if (Shape == Shape::NorthSouth) return 1311; else if (Shape == Shape::EastWest) return 1312; else if (Shape == Shape::AscendingEast) return 1313; else if (Shape == Shape::AscendingWest) return 1314; else if (Shape == Shape::AscendingNorth) return 1315; else return 1316; } BlockState PoweredRail(); bool Powered(BlockState Block); enum Shape Shape(BlockState Block); } namespace Prismarine { constexpr BlockState Prismarine() { return 7601; } } namespace PrismarineBrickSlab { enum class Type { Top, Bottom, Double }; constexpr BlockState PrismarineBrickSlab(const enum Type Type) { if (Type == Type::Top) return 7851; else if (Type == Type::Bottom) return 7853; else return 7855; } BlockState PrismarineBrickSlab(); enum Type Type(BlockState Block); } namespace PrismarineBrickStairs { enum class Half { Top, Bottom }; enum class Shape { Straight, InnerLeft, InnerRight, OuterLeft, OuterRight }; constexpr BlockState PrismarineBrickStairs(const eBlockFace Facing, const enum Half Half, const enum Shape Shape) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Half == Half::Top) if (Shape == Shape::Straight) return 7685; else if (Shape == Shape::InnerLeft) return 7687; else if (Shape == Shape::InnerRight) return 7689; else if (Shape == Shape::OuterLeft) return 7691; else return 7693; else if (Shape == Shape::Straight) return 7695; else if (Shape == Shape::InnerLeft) return 7697; else if (Shape == Shape::InnerRight) return 7699; else if (Shape == Shape::OuterLeft) return 7701; else return 7703; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Half == Half::Top) if (Shape == Shape::Straight) return 7705; else if (Shape == Shape::InnerLeft) return 7707; else if (Shape == Shape::InnerRight) return 7709; else if (Shape == Shape::OuterLeft) return 7711; else return 7713; else if (Shape == Shape::Straight) return 7715; else if (Shape == Shape::InnerLeft) return 7717; else if (Shape == Shape::InnerRight) return 7719; else if (Shape == Shape::OuterLeft) return 7721; else return 7723; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Half == Half::Top) if (Shape == Shape::Straight) return 7725; else if (Shape == Shape::InnerLeft) return 7727; else if (Shape == Shape::InnerRight) return 7729; else if (Shape == Shape::OuterLeft) return 7731; else return 7733; else if (Shape == Shape::Straight) return 7735; else if (Shape == Shape::InnerLeft) return 7737; else if (Shape == Shape::InnerRight) return 7739; else if (Shape == Shape::OuterLeft) return 7741; else return 7743; else if (Half == Half::Top) if (Shape == Shape::Straight) return 7745; else if (Shape == Shape::InnerLeft) return 7747; else if (Shape == Shape::InnerRight) return 7749; else if (Shape == Shape::OuterLeft) return 7751; else return 7753; else if (Shape == Shape::Straight) return 7755; else if (Shape == Shape::InnerLeft) return 7757; else if (Shape == Shape::InnerRight) return 7759; else if (Shape == Shape::OuterLeft) return 7761; else return 7763; } BlockState PrismarineBrickStairs(); eBlockFace Facing(BlockState Block); enum Half Half(BlockState Block); enum Shape Shape(BlockState Block); } namespace PrismarineBricks { constexpr BlockState PrismarineBricks() { return 7602; } } namespace PrismarineSlab { enum class Type { Top, Bottom, Double }; constexpr BlockState PrismarineSlab(const enum Type Type) { if (Type == Type::Top) return 7845; else if (Type == Type::Bottom) return 7847; else return 7849; } BlockState PrismarineSlab(); enum Type Type(BlockState Block); } namespace PrismarineStairs { enum class Half { Top, Bottom }; enum class Shape { Straight, InnerLeft, InnerRight, OuterLeft, OuterRight }; constexpr BlockState PrismarineStairs(const eBlockFace Facing, const enum Half Half, const enum Shape Shape) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Half == Half::Top) if (Shape == Shape::Straight) return 7605; else if (Shape == Shape::InnerLeft) return 7607; else if (Shape == Shape::InnerRight) return 7609; else if (Shape == Shape::OuterLeft) return 7611; else return 7613; else if (Shape == Shape::Straight) return 7615; else if (Shape == Shape::InnerLeft) return 7617; else if (Shape == Shape::InnerRight) return 7619; else if (Shape == Shape::OuterLeft) return 7621; else return 7623; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Half == Half::Top) if (Shape == Shape::Straight) return 7625; else if (Shape == Shape::InnerLeft) return 7627; else if (Shape == Shape::InnerRight) return 7629; else if (Shape == Shape::OuterLeft) return 7631; else return 7633; else if (Shape == Shape::Straight) return 7635; else if (Shape == Shape::InnerLeft) return 7637; else if (Shape == Shape::InnerRight) return 7639; else if (Shape == Shape::OuterLeft) return 7641; else return 7643; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Half == Half::Top) if (Shape == Shape::Straight) return 7645; else if (Shape == Shape::InnerLeft) return 7647; else if (Shape == Shape::InnerRight) return 7649; else if (Shape == Shape::OuterLeft) return 7651; else return 7653; else if (Shape == Shape::Straight) return 7655; else if (Shape == Shape::InnerLeft) return 7657; else if (Shape == Shape::InnerRight) return 7659; else if (Shape == Shape::OuterLeft) return 7661; else return 7663; else if (Half == Half::Top) if (Shape == Shape::Straight) return 7665; else if (Shape == Shape::InnerLeft) return 7667; else if (Shape == Shape::InnerRight) return 7669; else if (Shape == Shape::OuterLeft) return 7671; else return 7673; else if (Shape == Shape::Straight) return 7675; else if (Shape == Shape::InnerLeft) return 7677; else if (Shape == Shape::InnerRight) return 7679; else if (Shape == Shape::OuterLeft) return 7681; else return 7683; } BlockState PrismarineStairs(); eBlockFace Facing(BlockState Block); enum Half Half(BlockState Block); enum Shape Shape(BlockState Block); } namespace PrismarineWall { enum class East { None, Low, Tall }; enum class North { None, Low, Tall }; enum class South { None, Low, Tall }; enum class West { None, Low, Tall }; constexpr BlockState PrismarineWall(const enum East East, const enum North North, const enum South South, const bool Up, const enum West West) { if (East == East::None) if (North == North::None) if (South == South::None) if (Up) if (West == West::None) return 11194; else if (West == West::Low) return 11195; else return 11196; else if (West == West::None) return 11200; else if (West == West::Low) return 11201; else return 11202; else if (South == South::Low) if (Up) if (West == West::None) return 11206; else if (West == West::Low) return 11207; else return 11208; else if (West == West::None) return 11212; else if (West == West::Low) return 11213; else return 11214; else if (Up) if (West == West::None) return 11218; else if (West == West::Low) return 11219; else return 11220; else if (West == West::None) return 11224; else if (West == West::Low) return 11225; else return 11226; else if (North == North::Low) if (South == South::None) if (Up) if (West == West::None) return 11230; else if (West == West::Low) return 11231; else return 11232; else if (West == West::None) return 11236; else if (West == West::Low) return 11237; else return 11238; else if (South == South::Low) if (Up) if (West == West::None) return 11242; else if (West == West::Low) return 11243; else return 11244; else if (West == West::None) return 11248; else if (West == West::Low) return 11249; else return 11250; else if (Up) if (West == West::None) return 11254; else if (West == West::Low) return 11255; else return 11256; else if (West == West::None) return 11260; else if (West == West::Low) return 11261; else return 11262; else if (South == South::None) if (Up) if (West == West::None) return 11266; else if (West == West::Low) return 11267; else return 11268; else if (West == West::None) return 11272; else if (West == West::Low) return 11273; else return 11274; else if (South == South::Low) if (Up) if (West == West::None) return 11278; else if (West == West::Low) return 11279; else return 11280; else if (West == West::None) return 11284; else if (West == West::Low) return 11285; else return 11286; else if (Up) if (West == West::None) return 11290; else if (West == West::Low) return 11291; else return 11292; else if (West == West::None) return 11296; else if (West == West::Low) return 11297; else return 11298; else if (East == East::Low) if (North == North::None) if (South == South::None) if (Up) if (West == West::None) return 11302; else if (West == West::Low) return 11303; else return 11304; else if (West == West::None) return 11308; else if (West == West::Low) return 11309; else return 11310; else if (South == South::Low) if (Up) if (West == West::None) return 11314; else if (West == West::Low) return 11315; else return 11316; else if (West == West::None) return 11320; else if (West == West::Low) return 11321; else return 11322; else if (Up) if (West == West::None) return 11326; else if (West == West::Low) return 11327; else return 11328; else if (West == West::None) return 11332; else if (West == West::Low) return 11333; else return 11334; else if (North == North::Low) if (South == South::None) if (Up) if (West == West::None) return 11338; else if (West == West::Low) return 11339; else return 11340; else if (West == West::None) return 11344; else if (West == West::Low) return 11345; else return 11346; else if (South == South::Low) if (Up) if (West == West::None) return 11350; else if (West == West::Low) return 11351; else return 11352; else if (West == West::None) return 11356; else if (West == West::Low) return 11357; else return 11358; else if (Up) if (West == West::None) return 11362; else if (West == West::Low) return 11363; else return 11364; else if (West == West::None) return 11368; else if (West == West::Low) return 11369; else return 11370; else if (South == South::None) if (Up) if (West == West::None) return 11374; else if (West == West::Low) return 11375; else return 11376; else if (West == West::None) return 11380; else if (West == West::Low) return 11381; else return 11382; else if (South == South::Low) if (Up) if (West == West::None) return 11386; else if (West == West::Low) return 11387; else return 11388; else if (West == West::None) return 11392; else if (West == West::Low) return 11393; else return 11394; else if (Up) if (West == West::None) return 11398; else if (West == West::Low) return 11399; else return 11400; else if (West == West::None) return 11404; else if (West == West::Low) return 11405; else return 11406; else if (North == North::None) if (South == South::None) if (Up) if (West == West::None) return 11410; else if (West == West::Low) return 11411; else return 11412; else if (West == West::None) return 11416; else if (West == West::Low) return 11417; else return 11418; else if (South == South::Low) if (Up) if (West == West::None) return 11422; else if (West == West::Low) return 11423; else return 11424; else if (West == West::None) return 11428; else if (West == West::Low) return 11429; else return 11430; else if (Up) if (West == West::None) return 11434; else if (West == West::Low) return 11435; else return 11436; else if (West == West::None) return 11440; else if (West == West::Low) return 11441; else return 11442; else if (North == North::Low) if (South == South::None) if (Up) if (West == West::None) return 11446; else if (West == West::Low) return 11447; else return 11448; else if (West == West::None) return 11452; else if (West == West::Low) return 11453; else return 11454; else if (South == South::Low) if (Up) if (West == West::None) return 11458; else if (West == West::Low) return 11459; else return 11460; else if (West == West::None) return 11464; else if (West == West::Low) return 11465; else return 11466; else if (Up) if (West == West::None) return 11470; else if (West == West::Low) return 11471; else return 11472; else if (West == West::None) return 11476; else if (West == West::Low) return 11477; else return 11478; else if (South == South::None) if (Up) if (West == West::None) return 11482; else if (West == West::Low) return 11483; else return 11484; else if (West == West::None) return 11488; else if (West == West::Low) return 11489; else return 11490; else if (South == South::Low) if (Up) if (West == West::None) return 11494; else if (West == West::Low) return 11495; else return 11496; else if (West == West::None) return 11500; else if (West == West::Low) return 11501; else return 11502; else if (Up) if (West == West::None) return 11506; else if (West == West::Low) return 11507; else return 11508; else if (West == West::None) return 11512; else if (West == West::Low) return 11513; else return 11514; } BlockState PrismarineWall(); enum East East(BlockState Block); enum North North(BlockState Block); enum South South(BlockState Block); bool Up(BlockState Block); enum West West(BlockState Block); } namespace Pumpkin { constexpr BlockState Pumpkin() { return 3998; } } namespace PumpkinStem { constexpr BlockState PumpkinStem(const unsigned char Age) { if (Age == 0) return 4772; else if (Age == 1) return 4773; else if (Age == 2) return 4774; else if (Age == 3) return 4775; else if (Age == 4) return 4776; else if (Age == 5) return 4777; else if (Age == 6) return 4778; else return 4779; } BlockState PumpkinStem(); unsigned char Age(BlockState Block); } namespace PurpleBanner { constexpr BlockState PurpleBanner(const unsigned char Rotation) { if (Rotation == 0) return 8057; else if (Rotation == 1) return 8058; else if (Rotation == 2) return 8059; else if (Rotation == 3) return 8060; else if (Rotation == 4) return 8061; else if (Rotation == 5) return 8062; else if (Rotation == 6) return 8063; else if (Rotation == 7) return 8064; else if (Rotation == 8) return 8065; else if (Rotation == 9) return 8066; else if (Rotation == 10) return 8067; else if (Rotation == 11) return 8068; else if (Rotation == 12) return 8069; else if (Rotation == 13) return 8070; else if (Rotation == 14) return 8071; else return 8072; } BlockState PurpleBanner(); unsigned char Rotation(BlockState Block); } namespace PurpleBed { enum class Part { Head, Foot }; constexpr BlockState PurpleBed(const eBlockFace Facing, const bool Occupied, const enum Part Part) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Occupied) if (Part == Part::Head) return 1209; else return 1210; else if (Part == Part::Head) return 1211; else return 1212; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Occupied) if (Part == Part::Head) return 1213; else return 1214; else if (Part == Part::Head) return 1215; else return 1216; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Occupied) if (Part == Part::Head) return 1217; else return 1218; else if (Part == Part::Head) return 1219; else return 1220; else if (Occupied) if (Part == Part::Head) return 1221; else return 1222; else if (Part == Part::Head) return 1223; else return 1224; } BlockState PurpleBed(); eBlockFace Facing(BlockState Block); bool Occupied(BlockState Block); enum Part Part(BlockState Block); } namespace PurpleCarpet { constexpr BlockState PurpleCarpet() { return 7876; } } namespace PurpleConcrete { constexpr BlockState PurpleConcrete() { return 9448; } } namespace PurpleConcretePowder { constexpr BlockState PurpleConcretePowder() { return 9464; } } namespace PurpleGlazedTerracotta { constexpr BlockState PurpleGlazedTerracotta(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 9414; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 9415; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 9416; else return 9417; } BlockState PurpleGlazedTerracotta(); eBlockFace Facing(BlockState Block); } namespace PurpleShulkerBox { constexpr BlockState PurpleShulkerBox(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 9338; else if (Facing == eBlockFace::BLOCK_FACE_XP) return 9339; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 9340; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 9341; else if (Facing == eBlockFace::BLOCK_FACE_YP) return 9342; else return 9343; } BlockState PurpleShulkerBox(); eBlockFace Facing(BlockState Block); } namespace PurpleStainedGlass { constexpr BlockState PurpleStainedGlass() { return 4105; } } namespace PurpleStainedGlassPane { constexpr BlockState PurpleStainedGlassPane(const bool East, const bool North, const bool South, const bool West) { if (East) if (North) if (South) if (West) return 7185; else return 7186; else if (West) return 7189; else return 7190; else if (South) if (West) return 7193; else return 7194; else if (West) return 7197; else return 7198; else if (North) if (South) if (West) return 7201; else return 7202; else if (West) return 7205; else return 7206; else if (South) if (West) return 7209; else return 7210; else if (West) return 7213; else return 7214; } BlockState PurpleStainedGlassPane(); bool East(BlockState Block); bool North(BlockState Block); bool South(BlockState Block); bool West(BlockState Block); } namespace PurpleTerracotta { constexpr BlockState PurpleTerracotta() { return 6857; } } namespace PurpleWallBanner { constexpr BlockState PurpleWallBanner(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 8193; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 8194; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 8195; else return 8196; } BlockState PurpleWallBanner(); eBlockFace Facing(BlockState Block); } namespace PurpleWool { constexpr BlockState PurpleWool() { return 1394; } } namespace PurpurBlock { constexpr BlockState PurpurBlock() { return 9134; } } namespace PurpurPillar { enum class Axis { X, Y, Z }; constexpr BlockState PurpurPillar(const enum Axis Axis) { if (Axis == Axis::X) return 9135; else if (Axis == Axis::Y) return 9136; else return 9137; } BlockState PurpurPillar(); enum Axis Axis(BlockState Block); } namespace PurpurSlab { enum class Type { Top, Bottom, Double }; constexpr BlockState PurpurSlab(const enum Type Type) { if (Type == Type::Top) return 8409; else if (Type == Type::Bottom) return 8411; else return 8413; } BlockState PurpurSlab(); enum Type Type(BlockState Block); } namespace PurpurStairs { enum class Half { Top, Bottom }; enum class Shape { Straight, InnerLeft, InnerRight, OuterLeft, OuterRight }; constexpr BlockState PurpurStairs(const eBlockFace Facing, const enum Half Half, const enum Shape Shape) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Half == Half::Top) if (Shape == Shape::Straight) return 9139; else if (Shape == Shape::InnerLeft) return 9141; else if (Shape == Shape::InnerRight) return 9143; else if (Shape == Shape::OuterLeft) return 9145; else return 9147; else if (Shape == Shape::Straight) return 9149; else if (Shape == Shape::InnerLeft) return 9151; else if (Shape == Shape::InnerRight) return 9153; else if (Shape == Shape::OuterLeft) return 9155; else return 9157; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Half == Half::Top) if (Shape == Shape::Straight) return 9159; else if (Shape == Shape::InnerLeft) return 9161; else if (Shape == Shape::InnerRight) return 9163; else if (Shape == Shape::OuterLeft) return 9165; else return 9167; else if (Shape == Shape::Straight) return 9169; else if (Shape == Shape::InnerLeft) return 9171; else if (Shape == Shape::InnerRight) return 9173; else if (Shape == Shape::OuterLeft) return 9175; else return 9177; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Half == Half::Top) if (Shape == Shape::Straight) return 9179; else if (Shape == Shape::InnerLeft) return 9181; else if (Shape == Shape::InnerRight) return 9183; else if (Shape == Shape::OuterLeft) return 9185; else return 9187; else if (Shape == Shape::Straight) return 9189; else if (Shape == Shape::InnerLeft) return 9191; else if (Shape == Shape::InnerRight) return 9193; else if (Shape == Shape::OuterLeft) return 9195; else return 9197; else if (Half == Half::Top) if (Shape == Shape::Straight) return 9199; else if (Shape == Shape::InnerLeft) return 9201; else if (Shape == Shape::InnerRight) return 9203; else if (Shape == Shape::OuterLeft) return 9205; else return 9207; else if (Shape == Shape::Straight) return 9209; else if (Shape == Shape::InnerLeft) return 9211; else if (Shape == Shape::InnerRight) return 9213; else if (Shape == Shape::OuterLeft) return 9215; else return 9217; } BlockState PurpurStairs(); eBlockFace Facing(BlockState Block); enum Half Half(BlockState Block); enum Shape Shape(BlockState Block); } namespace QuartzBlock { constexpr BlockState QuartzBlock() { return 6738; } } namespace QuartzBricks { constexpr BlockState QuartzBricks() { return 17103; } } namespace QuartzPillar { enum class Axis { X, Y, Z }; constexpr BlockState QuartzPillar(const enum Axis Axis) { if (Axis == Axis::X) return 6740; else if (Axis == Axis::Y) return 6741; else return 6742; } BlockState QuartzPillar(); enum Axis Axis(BlockState Block); } namespace QuartzSlab { enum class Type { Top, Bottom, Double }; constexpr BlockState QuartzSlab(const enum Type Type) { if (Type == Type::Top) return 8391; else if (Type == Type::Bottom) return 8393; else return 8395; } BlockState QuartzSlab(); enum Type Type(BlockState Block); } namespace QuartzStairs { enum class Half { Top, Bottom }; enum class Shape { Straight, InnerLeft, InnerRight, OuterLeft, OuterRight }; constexpr BlockState QuartzStairs(const eBlockFace Facing, const enum Half Half, const enum Shape Shape) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Half == Half::Top) if (Shape == Shape::Straight) return 6744; else if (Shape == Shape::InnerLeft) return 6746; else if (Shape == Shape::InnerRight) return 6748; else if (Shape == Shape::OuterLeft) return 6750; else return 6752; else if (Shape == Shape::Straight) return 6754; else if (Shape == Shape::InnerLeft) return 6756; else if (Shape == Shape::InnerRight) return 6758; else if (Shape == Shape::OuterLeft) return 6760; else return 6762; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Half == Half::Top) if (Shape == Shape::Straight) return 6764; else if (Shape == Shape::InnerLeft) return 6766; else if (Shape == Shape::InnerRight) return 6768; else if (Shape == Shape::OuterLeft) return 6770; else return 6772; else if (Shape == Shape::Straight) return 6774; else if (Shape == Shape::InnerLeft) return 6776; else if (Shape == Shape::InnerRight) return 6778; else if (Shape == Shape::OuterLeft) return 6780; else return 6782; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Half == Half::Top) if (Shape == Shape::Straight) return 6784; else if (Shape == Shape::InnerLeft) return 6786; else if (Shape == Shape::InnerRight) return 6788; else if (Shape == Shape::OuterLeft) return 6790; else return 6792; else if (Shape == Shape::Straight) return 6794; else if (Shape == Shape::InnerLeft) return 6796; else if (Shape == Shape::InnerRight) return 6798; else if (Shape == Shape::OuterLeft) return 6800; else return 6802; else if (Half == Half::Top) if (Shape == Shape::Straight) return 6804; else if (Shape == Shape::InnerLeft) return 6806; else if (Shape == Shape::InnerRight) return 6808; else if (Shape == Shape::OuterLeft) return 6810; else return 6812; else if (Shape == Shape::Straight) return 6814; else if (Shape == Shape::InnerLeft) return 6816; else if (Shape == Shape::InnerRight) return 6818; else if (Shape == Shape::OuterLeft) return 6820; else return 6822; } BlockState QuartzStairs(); eBlockFace Facing(BlockState Block); enum Half Half(BlockState Block); enum Shape Shape(BlockState Block); } namespace Rail { enum class Shape { NorthSouth, EastWest, AscendingEast, AscendingWest, AscendingNorth, AscendingSouth, SouthEast, SouthWest, NorthWest, NorthEast }; constexpr BlockState Rail(const enum Shape Shape) { if (Shape == Shape::NorthSouth) return 3645; else if (Shape == Shape::EastWest) return 3646; else if (Shape == Shape::AscendingEast) return 3647; else if (Shape == Shape::AscendingWest) return 3648; else if (Shape == Shape::AscendingNorth) return 3649; else if (Shape == Shape::AscendingSouth) return 3650; else if (Shape == Shape::SouthEast) return 3651; else if (Shape == Shape::SouthWest) return 3652; else if (Shape == Shape::NorthWest) return 3653; else return 3654; } BlockState Rail(); enum Shape Shape(BlockState Block); } namespace RedBanner { constexpr BlockState RedBanner(const unsigned char Rotation) { if (Rotation == 0) return 8121; else if (Rotation == 1) return 8122; else if (Rotation == 2) return 8123; else if (Rotation == 3) return 8124; else if (Rotation == 4) return 8125; else if (Rotation == 5) return 8126; else if (Rotation == 6) return 8127; else if (Rotation == 7) return 8128; else if (Rotation == 8) return 8129; else if (Rotation == 9) return 8130; else if (Rotation == 10) return 8131; else if (Rotation == 11) return 8132; else if (Rotation == 12) return 8133; else if (Rotation == 13) return 8134; else if (Rotation == 14) return 8135; else return 8136; } BlockState RedBanner(); unsigned char Rotation(BlockState Block); } namespace RedBed { enum class Part { Head, Foot }; constexpr BlockState RedBed(const eBlockFace Facing, const bool Occupied, const enum Part Part) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Occupied) if (Part == Part::Head) return 1273; else return 1274; else if (Part == Part::Head) return 1275; else return 1276; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Occupied) if (Part == Part::Head) return 1277; else return 1278; else if (Part == Part::Head) return 1279; else return 1280; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Occupied) if (Part == Part::Head) return 1281; else return 1282; else if (Part == Part::Head) return 1283; else return 1284; else if (Occupied) if (Part == Part::Head) return 1285; else return 1286; else if (Part == Part::Head) return 1287; else return 1288; } BlockState RedBed(); eBlockFace Facing(BlockState Block); bool Occupied(BlockState Block); enum Part Part(BlockState Block); } namespace RedCarpet { constexpr BlockState RedCarpet() { return 7880; } } namespace RedConcrete { constexpr BlockState RedConcrete() { return 9452; } } namespace RedConcretePowder { constexpr BlockState RedConcretePowder() { return 9468; } } namespace RedGlazedTerracotta { constexpr BlockState RedGlazedTerracotta(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 9430; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 9431; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 9432; else return 9433; } BlockState RedGlazedTerracotta(); eBlockFace Facing(BlockState Block); } namespace RedMushroom { constexpr BlockState RedMushroom() { return 1426; } } namespace RedMushroomBlock { constexpr BlockState RedMushroomBlock(const bool Down, const bool East, const bool North, const bool South, const bool Up, const bool West) { if (Down) if (East) if (North) if (South) if (Up) if (West) return 4569; else return 4570; else if (West) return 4571; else return 4572; else if (Up) if (West) return 4573; else return 4574; else if (West) return 4575; else return 4576; else if (South) if (Up) if (West) return 4577; else return 4578; else if (West) return 4579; else return 4580; else if (Up) if (West) return 4581; else return 4582; else if (West) return 4583; else return 4584; else if (North) if (South) if (Up) if (West) return 4585; else return 4586; else if (West) return 4587; else return 4588; else if (Up) if (West) return 4589; else return 4590; else if (West) return 4591; else return 4592; else if (South) if (Up) if (West) return 4593; else return 4594; else if (West) return 4595; else return 4596; else if (Up) if (West) return 4597; else return 4598; else if (West) return 4599; else return 4600; else if (East) if (North) if (South) if (Up) if (West) return 4601; else return 4602; else if (West) return 4603; else return 4604; else if (Up) if (West) return 4605; else return 4606; else if (West) return 4607; else return 4608; else if (South) if (Up) if (West) return 4609; else return 4610; else if (West) return 4611; else return 4612; else if (Up) if (West) return 4613; else return 4614; else if (West) return 4615; else return 4616; else if (North) if (South) if (Up) if (West) return 4617; else return 4618; else if (West) return 4619; else return 4620; else if (Up) if (West) return 4621; else return 4622; else if (West) return 4623; else return 4624; else if (South) if (Up) if (West) return 4625; else return 4626; else if (West) return 4627; else return 4628; else if (Up) if (West) return 4629; else return 4630; else if (West) return 4631; else return 4632; } BlockState RedMushroomBlock(); bool Down(BlockState Block); bool East(BlockState Block); bool North(BlockState Block); bool South(BlockState Block); bool Up(BlockState Block); bool West(BlockState Block); } namespace RedNetherBrickSlab { enum class Type { Top, Bottom, Double }; constexpr BlockState RedNetherBrickSlab(const enum Type Type) { if (Type == Type::Top) return 10850; else if (Type == Type::Bottom) return 10852; else return 10854; } BlockState RedNetherBrickSlab(); enum Type Type(BlockState Block); } namespace RedNetherBrickStairs { enum class Half { Top, Bottom }; enum class Shape { Straight, InnerLeft, InnerRight, OuterLeft, OuterRight }; constexpr BlockState RedNetherBrickStairs(const eBlockFace Facing, const enum Half Half, const enum Shape Shape) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Half == Half::Top) if (Shape == Shape::Straight) return 10550; else if (Shape == Shape::InnerLeft) return 10552; else if (Shape == Shape::InnerRight) return 10554; else if (Shape == Shape::OuterLeft) return 10556; else return 10558; else if (Shape == Shape::Straight) return 10560; else if (Shape == Shape::InnerLeft) return 10562; else if (Shape == Shape::InnerRight) return 10564; else if (Shape == Shape::OuterLeft) return 10566; else return 10568; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Half == Half::Top) if (Shape == Shape::Straight) return 10570; else if (Shape == Shape::InnerLeft) return 10572; else if (Shape == Shape::InnerRight) return 10574; else if (Shape == Shape::OuterLeft) return 10576; else return 10578; else if (Shape == Shape::Straight) return 10580; else if (Shape == Shape::InnerLeft) return 10582; else if (Shape == Shape::InnerRight) return 10584; else if (Shape == Shape::OuterLeft) return 10586; else return 10588; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Half == Half::Top) if (Shape == Shape::Straight) return 10590; else if (Shape == Shape::InnerLeft) return 10592; else if (Shape == Shape::InnerRight) return 10594; else if (Shape == Shape::OuterLeft) return 10596; else return 10598; else if (Shape == Shape::Straight) return 10600; else if (Shape == Shape::InnerLeft) return 10602; else if (Shape == Shape::InnerRight) return 10604; else if (Shape == Shape::OuterLeft) return 10606; else return 10608; else if (Half == Half::Top) if (Shape == Shape::Straight) return 10610; else if (Shape == Shape::InnerLeft) return 10612; else if (Shape == Shape::InnerRight) return 10614; else if (Shape == Shape::OuterLeft) return 10616; else return 10618; else if (Shape == Shape::Straight) return 10620; else if (Shape == Shape::InnerLeft) return 10622; else if (Shape == Shape::InnerRight) return 10624; else if (Shape == Shape::OuterLeft) return 10626; else return 10628; } BlockState RedNetherBrickStairs(); eBlockFace Facing(BlockState Block); enum Half Half(BlockState Block); enum Shape Shape(BlockState Block); } namespace RedNetherBrickWall { enum class East { None, Low, Tall }; enum class North { None, Low, Tall }; enum class South { None, Low, Tall }; enum class West { None, Low, Tall }; constexpr BlockState RedNetherBrickWall(const enum East East, const enum North North, const enum South South, const bool Up, const enum West West) { if (East == East::None) if (North == North::None) if (South == South::None) if (Up) if (West == West::None) return 13462; else if (West == West::Low) return 13463; else return 13464; else if (West == West::None) return 13468; else if (West == West::Low) return 13469; else return 13470; else if (South == South::Low) if (Up) if (West == West::None) return 13474; else if (West == West::Low) return 13475; else return 13476; else if (West == West::None) return 13480; else if (West == West::Low) return 13481; else return 13482; else if (Up) if (West == West::None) return 13486; else if (West == West::Low) return 13487; else return 13488; else if (West == West::None) return 13492; else if (West == West::Low) return 13493; else return 13494; else if (North == North::Low) if (South == South::None) if (Up) if (West == West::None) return 13498; else if (West == West::Low) return 13499; else return 13500; else if (West == West::None) return 13504; else if (West == West::Low) return 13505; else return 13506; else if (South == South::Low) if (Up) if (West == West::None) return 13510; else if (West == West::Low) return 13511; else return 13512; else if (West == West::None) return 13516; else if (West == West::Low) return 13517; else return 13518; else if (Up) if (West == West::None) return 13522; else if (West == West::Low) return 13523; else return 13524; else if (West == West::None) return 13528; else if (West == West::Low) return 13529; else return 13530; else if (South == South::None) if (Up) if (West == West::None) return 13534; else if (West == West::Low) return 13535; else return 13536; else if (West == West::None) return 13540; else if (West == West::Low) return 13541; else return 13542; else if (South == South::Low) if (Up) if (West == West::None) return 13546; else if (West == West::Low) return 13547; else return 13548; else if (West == West::None) return 13552; else if (West == West::Low) return 13553; else return 13554; else if (Up) if (West == West::None) return 13558; else if (West == West::Low) return 13559; else return 13560; else if (West == West::None) return 13564; else if (West == West::Low) return 13565; else return 13566; else if (East == East::Low) if (North == North::None) if (South == South::None) if (Up) if (West == West::None) return 13570; else if (West == West::Low) return 13571; else return 13572; else if (West == West::None) return 13576; else if (West == West::Low) return 13577; else return 13578; else if (South == South::Low) if (Up) if (West == West::None) return 13582; else if (West == West::Low) return 13583; else return 13584; else if (West == West::None) return 13588; else if (West == West::Low) return 13589; else return 13590; else if (Up) if (West == West::None) return 13594; else if (West == West::Low) return 13595; else return 13596; else if (West == West::None) return 13600; else if (West == West::Low) return 13601; else return 13602; else if (North == North::Low) if (South == South::None) if (Up) if (West == West::None) return 13606; else if (West == West::Low) return 13607; else return 13608; else if (West == West::None) return 13612; else if (West == West::Low) return 13613; else return 13614; else if (South == South::Low) if (Up) if (West == West::None) return 13618; else if (West == West::Low) return 13619; else return 13620; else if (West == West::None) return 13624; else if (West == West::Low) return 13625; else return 13626; else if (Up) if (West == West::None) return 13630; else if (West == West::Low) return 13631; else return 13632; else if (West == West::None) return 13636; else if (West == West::Low) return 13637; else return 13638; else if (South == South::None) if (Up) if (West == West::None) return 13642; else if (West == West::Low) return 13643; else return 13644; else if (West == West::None) return 13648; else if (West == West::Low) return 13649; else return 13650; else if (South == South::Low) if (Up) if (West == West::None) return 13654; else if (West == West::Low) return 13655; else return 13656; else if (West == West::None) return 13660; else if (West == West::Low) return 13661; else return 13662; else if (Up) if (West == West::None) return 13666; else if (West == West::Low) return 13667; else return 13668; else if (West == West::None) return 13672; else if (West == West::Low) return 13673; else return 13674; else if (North == North::None) if (South == South::None) if (Up) if (West == West::None) return 13678; else if (West == West::Low) return 13679; else return 13680; else if (West == West::None) return 13684; else if (West == West::Low) return 13685; else return 13686; else if (South == South::Low) if (Up) if (West == West::None) return 13690; else if (West == West::Low) return 13691; else return 13692; else if (West == West::None) return 13696; else if (West == West::Low) return 13697; else return 13698; else if (Up) if (West == West::None) return 13702; else if (West == West::Low) return 13703; else return 13704; else if (West == West::None) return 13708; else if (West == West::Low) return 13709; else return 13710; else if (North == North::Low) if (South == South::None) if (Up) if (West == West::None) return 13714; else if (West == West::Low) return 13715; else return 13716; else if (West == West::None) return 13720; else if (West == West::Low) return 13721; else return 13722; else if (South == South::Low) if (Up) if (West == West::None) return 13726; else if (West == West::Low) return 13727; else return 13728; else if (West == West::None) return 13732; else if (West == West::Low) return 13733; else return 13734; else if (Up) if (West == West::None) return 13738; else if (West == West::Low) return 13739; else return 13740; else if (West == West::None) return 13744; else if (West == West::Low) return 13745; else return 13746; else if (South == South::None) if (Up) if (West == West::None) return 13750; else if (West == West::Low) return 13751; else return 13752; else if (West == West::None) return 13756; else if (West == West::Low) return 13757; else return 13758; else if (South == South::Low) if (Up) if (West == West::None) return 13762; else if (West == West::Low) return 13763; else return 13764; else if (West == West::None) return 13768; else if (West == West::Low) return 13769; else return 13770; else if (Up) if (West == West::None) return 13774; else if (West == West::Low) return 13775; else return 13776; else if (West == West::None) return 13780; else if (West == West::Low) return 13781; else return 13782; } BlockState RedNetherBrickWall(); enum East East(BlockState Block); enum North North(BlockState Block); enum South South(BlockState Block); bool Up(BlockState Block); enum West West(BlockState Block); } namespace RedNetherBricks { constexpr BlockState RedNetherBricks() { return 9255; } } namespace RedSand { constexpr BlockState RedSand() { return 67; } } namespace RedSandstone { constexpr BlockState RedSandstone() { return 8217; } } namespace RedSandstoneSlab { enum class Type { Top, Bottom, Double }; constexpr BlockState RedSandstoneSlab(const enum Type Type) { if (Type == Type::Top) return 8397; else if (Type == Type::Bottom) return 8399; else return 8401; } BlockState RedSandstoneSlab(); enum Type Type(BlockState Block); } namespace RedSandstoneStairs { enum class Half { Top, Bottom }; enum class Shape { Straight, InnerLeft, InnerRight, OuterLeft, OuterRight }; constexpr BlockState RedSandstoneStairs(const eBlockFace Facing, const enum Half Half, const enum Shape Shape) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Half == Half::Top) if (Shape == Shape::Straight) return 8221; else if (Shape == Shape::InnerLeft) return 8223; else if (Shape == Shape::InnerRight) return 8225; else if (Shape == Shape::OuterLeft) return 8227; else return 8229; else if (Shape == Shape::Straight) return 8231; else if (Shape == Shape::InnerLeft) return 8233; else if (Shape == Shape::InnerRight) return 8235; else if (Shape == Shape::OuterLeft) return 8237; else return 8239; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Half == Half::Top) if (Shape == Shape::Straight) return 8241; else if (Shape == Shape::InnerLeft) return 8243; else if (Shape == Shape::InnerRight) return 8245; else if (Shape == Shape::OuterLeft) return 8247; else return 8249; else if (Shape == Shape::Straight) return 8251; else if (Shape == Shape::InnerLeft) return 8253; else if (Shape == Shape::InnerRight) return 8255; else if (Shape == Shape::OuterLeft) return 8257; else return 8259; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Half == Half::Top) if (Shape == Shape::Straight) return 8261; else if (Shape == Shape::InnerLeft) return 8263; else if (Shape == Shape::InnerRight) return 8265; else if (Shape == Shape::OuterLeft) return 8267; else return 8269; else if (Shape == Shape::Straight) return 8271; else if (Shape == Shape::InnerLeft) return 8273; else if (Shape == Shape::InnerRight) return 8275; else if (Shape == Shape::OuterLeft) return 8277; else return 8279; else if (Half == Half::Top) if (Shape == Shape::Straight) return 8281; else if (Shape == Shape::InnerLeft) return 8283; else if (Shape == Shape::InnerRight) return 8285; else if (Shape == Shape::OuterLeft) return 8287; else return 8289; else if (Shape == Shape::Straight) return 8291; else if (Shape == Shape::InnerLeft) return 8293; else if (Shape == Shape::InnerRight) return 8295; else if (Shape == Shape::OuterLeft) return 8297; else return 8299; } BlockState RedSandstoneStairs(); eBlockFace Facing(BlockState Block); enum Half Half(BlockState Block); enum Shape Shape(BlockState Block); } namespace RedSandstoneWall { enum class East { None, Low, Tall }; enum class North { None, Low, Tall }; enum class South { None, Low, Tall }; enum class West { None, Low, Tall }; constexpr BlockState RedSandstoneWall(const enum East East, const enum North North, const enum South South, const bool Up, const enum West West) { if (East == East::None) if (North == North::None) if (South == South::None) if (Up) if (West == West::None) return 11518; else if (West == West::Low) return 11519; else return 11520; else if (West == West::None) return 11524; else if (West == West::Low) return 11525; else return 11526; else if (South == South::Low) if (Up) if (West == West::None) return 11530; else if (West == West::Low) return 11531; else return 11532; else if (West == West::None) return 11536; else if (West == West::Low) return 11537; else return 11538; else if (Up) if (West == West::None) return 11542; else if (West == West::Low) return 11543; else return 11544; else if (West == West::None) return 11548; else if (West == West::Low) return 11549; else return 11550; else if (North == North::Low) if (South == South::None) if (Up) if (West == West::None) return 11554; else if (West == West::Low) return 11555; else return 11556; else if (West == West::None) return 11560; else if (West == West::Low) return 11561; else return 11562; else if (South == South::Low) if (Up) if (West == West::None) return 11566; else if (West == West::Low) return 11567; else return 11568; else if (West == West::None) return 11572; else if (West == West::Low) return 11573; else return 11574; else if (Up) if (West == West::None) return 11578; else if (West == West::Low) return 11579; else return 11580; else if (West == West::None) return 11584; else if (West == West::Low) return 11585; else return 11586; else if (South == South::None) if (Up) if (West == West::None) return 11590; else if (West == West::Low) return 11591; else return 11592; else if (West == West::None) return 11596; else if (West == West::Low) return 11597; else return 11598; else if (South == South::Low) if (Up) if (West == West::None) return 11602; else if (West == West::Low) return 11603; else return 11604; else if (West == West::None) return 11608; else if (West == West::Low) return 11609; else return 11610; else if (Up) if (West == West::None) return 11614; else if (West == West::Low) return 11615; else return 11616; else if (West == West::None) return 11620; else if (West == West::Low) return 11621; else return 11622; else if (East == East::Low) if (North == North::None) if (South == South::None) if (Up) if (West == West::None) return 11626; else if (West == West::Low) return 11627; else return 11628; else if (West == West::None) return 11632; else if (West == West::Low) return 11633; else return 11634; else if (South == South::Low) if (Up) if (West == West::None) return 11638; else if (West == West::Low) return 11639; else return 11640; else if (West == West::None) return 11644; else if (West == West::Low) return 11645; else return 11646; else if (Up) if (West == West::None) return 11650; else if (West == West::Low) return 11651; else return 11652; else if (West == West::None) return 11656; else if (West == West::Low) return 11657; else return 11658; else if (North == North::Low) if (South == South::None) if (Up) if (West == West::None) return 11662; else if (West == West::Low) return 11663; else return 11664; else if (West == West::None) return 11668; else if (West == West::Low) return 11669; else return 11670; else if (South == South::Low) if (Up) if (West == West::None) return 11674; else if (West == West::Low) return 11675; else return 11676; else if (West == West::None) return 11680; else if (West == West::Low) return 11681; else return 11682; else if (Up) if (West == West::None) return 11686; else if (West == West::Low) return 11687; else return 11688; else if (West == West::None) return 11692; else if (West == West::Low) return 11693; else return 11694; else if (South == South::None) if (Up) if (West == West::None) return 11698; else if (West == West::Low) return 11699; else return 11700; else if (West == West::None) return 11704; else if (West == West::Low) return 11705; else return 11706; else if (South == South::Low) if (Up) if (West == West::None) return 11710; else if (West == West::Low) return 11711; else return 11712; else if (West == West::None) return 11716; else if (West == West::Low) return 11717; else return 11718; else if (Up) if (West == West::None) return 11722; else if (West == West::Low) return 11723; else return 11724; else if (West == West::None) return 11728; else if (West == West::Low) return 11729; else return 11730; else if (North == North::None) if (South == South::None) if (Up) if (West == West::None) return 11734; else if (West == West::Low) return 11735; else return 11736; else if (West == West::None) return 11740; else if (West == West::Low) return 11741; else return 11742; else if (South == South::Low) if (Up) if (West == West::None) return 11746; else if (West == West::Low) return 11747; else return 11748; else if (West == West::None) return 11752; else if (West == West::Low) return 11753; else return 11754; else if (Up) if (West == West::None) return 11758; else if (West == West::Low) return 11759; else return 11760; else if (West == West::None) return 11764; else if (West == West::Low) return 11765; else return 11766; else if (North == North::Low) if (South == South::None) if (Up) if (West == West::None) return 11770; else if (West == West::Low) return 11771; else return 11772; else if (West == West::None) return 11776; else if (West == West::Low) return 11777; else return 11778; else if (South == South::Low) if (Up) if (West == West::None) return 11782; else if (West == West::Low) return 11783; else return 11784; else if (West == West::None) return 11788; else if (West == West::Low) return 11789; else return 11790; else if (Up) if (West == West::None) return 11794; else if (West == West::Low) return 11795; else return 11796; else if (West == West::None) return 11800; else if (West == West::Low) return 11801; else return 11802; else if (South == South::None) if (Up) if (West == West::None) return 11806; else if (West == West::Low) return 11807; else return 11808; else if (West == West::None) return 11812; else if (West == West::Low) return 11813; else return 11814; else if (South == South::Low) if (Up) if (West == West::None) return 11818; else if (West == West::Low) return 11819; else return 11820; else if (West == West::None) return 11824; else if (West == West::Low) return 11825; else return 11826; else if (Up) if (West == West::None) return 11830; else if (West == West::Low) return 11831; else return 11832; else if (West == West::None) return 11836; else if (West == West::Low) return 11837; else return 11838; } BlockState RedSandstoneWall(); enum East East(BlockState Block); enum North North(BlockState Block); enum South South(BlockState Block); bool Up(BlockState Block); enum West West(BlockState Block); } namespace RedShulkerBox { constexpr BlockState RedShulkerBox(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 9362; else if (Facing == eBlockFace::BLOCK_FACE_XP) return 9363; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 9364; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 9365; else if (Facing == eBlockFace::BLOCK_FACE_YP) return 9366; else return 9367; } BlockState RedShulkerBox(); eBlockFace Facing(BlockState Block); } namespace RedStainedGlass { constexpr BlockState RedStainedGlass() { return 4109; } } namespace RedStainedGlassPane { constexpr BlockState RedStainedGlassPane(const bool East, const bool North, const bool South, const bool West) { if (East) if (North) if (South) if (West) return 7313; else return 7314; else if (West) return 7317; else return 7318; else if (South) if (West) return 7321; else return 7322; else if (West) return 7325; else return 7326; else if (North) if (South) if (West) return 7329; else return 7330; else if (West) return 7333; else return 7334; else if (South) if (West) return 7337; else return 7338; else if (West) return 7341; else return 7342; } BlockState RedStainedGlassPane(); bool East(BlockState Block); bool North(BlockState Block); bool South(BlockState Block); bool West(BlockState Block); } namespace RedTerracotta { constexpr BlockState RedTerracotta() { return 6861; } } namespace RedTulip { constexpr BlockState RedTulip() { return 1417; } } namespace RedWallBanner { constexpr BlockState RedWallBanner(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 8209; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 8210; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 8211; else return 8212; } BlockState RedWallBanner(); eBlockFace Facing(BlockState Block); } namespace RedWool { constexpr BlockState RedWool() { return 1398; } } namespace RedstoneBlock { constexpr BlockState RedstoneBlock() { return 6726; } } namespace RedstoneLamp { constexpr BlockState RedstoneLamp(const bool Lit) { if (Lit) return 5156; else return 5157; } BlockState RedstoneLamp(); bool Lit(BlockState Block); } namespace RedstoneOre { constexpr BlockState RedstoneOre(const bool Lit) { if (Lit) return 3885; else return 3886; } BlockState RedstoneOre(); bool Lit(BlockState Block); } namespace RedstoneTorch { constexpr BlockState RedstoneTorch(const bool Lit) { if (Lit) return 3887; else return 3888; } BlockState RedstoneTorch(); bool Lit(BlockState Block); } namespace RedstoneWallTorch { constexpr BlockState RedstoneWallTorch(const eBlockFace Facing, const bool Lit) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Lit) return 3889; else return 3890; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Lit) return 3891; else return 3892; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Lit) return 3893; else return 3894; else if (Lit) return 3895; else return 3896; } BlockState RedstoneWallTorch(); eBlockFace Facing(BlockState Block); bool Lit(BlockState Block); } namespace RedstoneWire { enum class East { Up, Side, None }; enum class North { Up, Side, None }; enum class South { Up, Side, None }; enum class West { Up, Side, None }; constexpr BlockState RedstoneWire(const enum East East, const enum North North, const unsigned char Power, const enum South South, const enum West West) { if (East == East::Up) if (North == North::Up) if (Power == 0) if (South == South::Up) if (West == West::Up) return 2058; else if (West == West::Side) return 2059; else return 2060; else if (South == South::Side) if (West == West::Up) return 2061; else if (West == West::Side) return 2062; else return 2063; else if (West == West::Up) return 2064; else if (West == West::Side) return 2065; else return 2066; else if (Power == 1) if (South == South::Up) if (West == West::Up) return 2067; else if (West == West::Side) return 2068; else return 2069; else if (South == South::Side) if (West == West::Up) return 2070; else if (West == West::Side) return 2071; else return 2072; else if (West == West::Up) return 2073; else if (West == West::Side) return 2074; else return 2075; else if (Power == 2) if (South == South::Up) if (West == West::Up) return 2076; else if (West == West::Side) return 2077; else return 2078; else if (South == South::Side) if (West == West::Up) return 2079; else if (West == West::Side) return 2080; else return 2081; else if (West == West::Up) return 2082; else if (West == West::Side) return 2083; else return 2084; else if (Power == 3) if (South == South::Up) if (West == West::Up) return 2085; else if (West == West::Side) return 2086; else return 2087; else if (South == South::Side) if (West == West::Up) return 2088; else if (West == West::Side) return 2089; else return 2090; else if (West == West::Up) return 2091; else if (West == West::Side) return 2092; else return 2093; else if (Power == 4) if (South == South::Up) if (West == West::Up) return 2094; else if (West == West::Side) return 2095; else return 2096; else if (South == South::Side) if (West == West::Up) return 2097; else if (West == West::Side) return 2098; else return 2099; else if (West == West::Up) return 2100; else if (West == West::Side) return 2101; else return 2102; else if (Power == 5) if (South == South::Up) if (West == West::Up) return 2103; else if (West == West::Side) return 2104; else return 2105; else if (South == South::Side) if (West == West::Up) return 2106; else if (West == West::Side) return 2107; else return 2108; else if (West == West::Up) return 2109; else if (West == West::Side) return 2110; else return 2111; else if (Power == 6) if (South == South::Up) if (West == West::Up) return 2112; else if (West == West::Side) return 2113; else return 2114; else if (South == South::Side) if (West == West::Up) return 2115; else if (West == West::Side) return 2116; else return 2117; else if (West == West::Up) return 2118; else if (West == West::Side) return 2119; else return 2120; else if (Power == 7) if (South == South::Up) if (West == West::Up) return 2121; else if (West == West::Side) return 2122; else return 2123; else if (South == South::Side) if (West == West::Up) return 2124; else if (West == West::Side) return 2125; else return 2126; else if (West == West::Up) return 2127; else if (West == West::Side) return 2128; else return 2129; else if (Power == 8) if (South == South::Up) if (West == West::Up) return 2130; else if (West == West::Side) return 2131; else return 2132; else if (South == South::Side) if (West == West::Up) return 2133; else if (West == West::Side) return 2134; else return 2135; else if (West == West::Up) return 2136; else if (West == West::Side) return 2137; else return 2138; else if (Power == 9) if (South == South::Up) if (West == West::Up) return 2139; else if (West == West::Side) return 2140; else return 2141; else if (South == South::Side) if (West == West::Up) return 2142; else if (West == West::Side) return 2143; else return 2144; else if (West == West::Up) return 2145; else if (West == West::Side) return 2146; else return 2147; else if (Power == 10) if (South == South::Up) if (West == West::Up) return 2148; else if (West == West::Side) return 2149; else return 2150; else if (South == South::Side) if (West == West::Up) return 2151; else if (West == West::Side) return 2152; else return 2153; else if (West == West::Up) return 2154; else if (West == West::Side) return 2155; else return 2156; else if (Power == 11) if (South == South::Up) if (West == West::Up) return 2157; else if (West == West::Side) return 2158; else return 2159; else if (South == South::Side) if (West == West::Up) return 2160; else if (West == West::Side) return 2161; else return 2162; else if (West == West::Up) return 2163; else if (West == West::Side) return 2164; else return 2165; else if (Power == 12) if (South == South::Up) if (West == West::Up) return 2166; else if (West == West::Side) return 2167; else return 2168; else if (South == South::Side) if (West == West::Up) return 2169; else if (West == West::Side) return 2170; else return 2171; else if (West == West::Up) return 2172; else if (West == West::Side) return 2173; else return 2174; else if (Power == 13) if (South == South::Up) if (West == West::Up) return 2175; else if (West == West::Side) return 2176; else return 2177; else if (South == South::Side) if (West == West::Up) return 2178; else if (West == West::Side) return 2179; else return 2180; else if (West == West::Up) return 2181; else if (West == West::Side) return 2182; else return 2183; else if (Power == 14) if (South == South::Up) if (West == West::Up) return 2184; else if (West == West::Side) return 2185; else return 2186; else if (South == South::Side) if (West == West::Up) return 2187; else if (West == West::Side) return 2188; else return 2189; else if (West == West::Up) return 2190; else if (West == West::Side) return 2191; else return 2192; else if (South == South::Up) if (West == West::Up) return 2193; else if (West == West::Side) return 2194; else return 2195; else if (South == South::Side) if (West == West::Up) return 2196; else if (West == West::Side) return 2197; else return 2198; else if (West == West::Up) return 2199; else if (West == West::Side) return 2200; else return 2201; else if (North == North::Side) if (Power == 0) if (South == South::Up) if (West == West::Up) return 2202; else if (West == West::Side) return 2203; else return 2204; else if (South == South::Side) if (West == West::Up) return 2205; else if (West == West::Side) return 2206; else return 2207; else if (West == West::Up) return 2208; else if (West == West::Side) return 2209; else return 2210; else if (Power == 1) if (South == South::Up) if (West == West::Up) return 2211; else if (West == West::Side) return 2212; else return 2213; else if (South == South::Side) if (West == West::Up) return 2214; else if (West == West::Side) return 2215; else return 2216; else if (West == West::Up) return 2217; else if (West == West::Side) return 2218; else return 2219; else if (Power == 2) if (South == South::Up) if (West == West::Up) return 2220; else if (West == West::Side) return 2221; else return 2222; else if (South == South::Side) if (West == West::Up) return 2223; else if (West == West::Side) return 2224; else return 2225; else if (West == West::Up) return 2226; else if (West == West::Side) return 2227; else return 2228; else if (Power == 3) if (South == South::Up) if (West == West::Up) return 2229; else if (West == West::Side) return 2230; else return 2231; else if (South == South::Side) if (West == West::Up) return 2232; else if (West == West::Side) return 2233; else return 2234; else if (West == West::Up) return 2235; else if (West == West::Side) return 2236; else return 2237; else if (Power == 4) if (South == South::Up) if (West == West::Up) return 2238; else if (West == West::Side) return 2239; else return 2240; else if (South == South::Side) if (West == West::Up) return 2241; else if (West == West::Side) return 2242; else return 2243; else if (West == West::Up) return 2244; else if (West == West::Side) return 2245; else return 2246; else if (Power == 5) if (South == South::Up) if (West == West::Up) return 2247; else if (West == West::Side) return 2248; else return 2249; else if (South == South::Side) if (West == West::Up) return 2250; else if (West == West::Side) return 2251; else return 2252; else if (West == West::Up) return 2253; else if (West == West::Side) return 2254; else return 2255; else if (Power == 6) if (South == South::Up) if (West == West::Up) return 2256; else if (West == West::Side) return 2257; else return 2258; else if (South == South::Side) if (West == West::Up) return 2259; else if (West == West::Side) return 2260; else return 2261; else if (West == West::Up) return 2262; else if (West == West::Side) return 2263; else return 2264; else if (Power == 7) if (South == South::Up) if (West == West::Up) return 2265; else if (West == West::Side) return 2266; else return 2267; else if (South == South::Side) if (West == West::Up) return 2268; else if (West == West::Side) return 2269; else return 2270; else if (West == West::Up) return 2271; else if (West == West::Side) return 2272; else return 2273; else if (Power == 8) if (South == South::Up) if (West == West::Up) return 2274; else if (West == West::Side) return 2275; else return 2276; else if (South == South::Side) if (West == West::Up) return 2277; else if (West == West::Side) return 2278; else return 2279; else if (West == West::Up) return 2280; else if (West == West::Side) return 2281; else return 2282; else if (Power == 9) if (South == South::Up) if (West == West::Up) return 2283; else if (West == West::Side) return 2284; else return 2285; else if (South == South::Side) if (West == West::Up) return 2286; else if (West == West::Side) return 2287; else return 2288; else if (West == West::Up) return 2289; else if (West == West::Side) return 2290; else return 2291; else if (Power == 10) if (South == South::Up) if (West == West::Up) return 2292; else if (West == West::Side) return 2293; else return 2294; else if (South == South::Side) if (West == West::Up) return 2295; else if (West == West::Side) return 2296; else return 2297; else if (West == West::Up) return 2298; else if (West == West::Side) return 2299; else return 2300; else if (Power == 11) if (South == South::Up) if (West == West::Up) return 2301; else if (West == West::Side) return 2302; else return 2303; else if (South == South::Side) if (West == West::Up) return 2304; else if (West == West::Side) return 2305; else return 2306; else if (West == West::Up) return 2307; else if (West == West::Side) return 2308; else return 2309; else if (Power == 12) if (South == South::Up) if (West == West::Up) return 2310; else if (West == West::Side) return 2311; else return 2312; else if (South == South::Side) if (West == West::Up) return 2313; else if (West == West::Side) return 2314; else return 2315; else if (West == West::Up) return 2316; else if (West == West::Side) return 2317; else return 2318; else if (Power == 13) if (South == South::Up) if (West == West::Up) return 2319; else if (West == West::Side) return 2320; else return 2321; else if (South == South::Side) if (West == West::Up) return 2322; else if (West == West::Side) return 2323; else return 2324; else if (West == West::Up) return 2325; else if (West == West::Side) return 2326; else return 2327; else if (Power == 14) if (South == South::Up) if (West == West::Up) return 2328; else if (West == West::Side) return 2329; else return 2330; else if (South == South::Side) if (West == West::Up) return 2331; else if (West == West::Side) return 2332; else return 2333; else if (West == West::Up) return 2334; else if (West == West::Side) return 2335; else return 2336; else if (South == South::Up) if (West == West::Up) return 2337; else if (West == West::Side) return 2338; else return 2339; else if (South == South::Side) if (West == West::Up) return 2340; else if (West == West::Side) return 2341; else return 2342; else if (West == West::Up) return 2343; else if (West == West::Side) return 2344; else return 2345; else if (Power == 0) if (South == South::Up) if (West == West::Up) return 2346; else if (West == West::Side) return 2347; else return 2348; else if (South == South::Side) if (West == West::Up) return 2349; else if (West == West::Side) return 2350; else return 2351; else if (West == West::Up) return 2352; else if (West == West::Side) return 2353; else return 2354; else if (Power == 1) if (South == South::Up) if (West == West::Up) return 2355; else if (West == West::Side) return 2356; else return 2357; else if (South == South::Side) if (West == West::Up) return 2358; else if (West == West::Side) return 2359; else return 2360; else if (West == West::Up) return 2361; else if (West == West::Side) return 2362; else return 2363; else if (Power == 2) if (South == South::Up) if (West == West::Up) return 2364; else if (West == West::Side) return 2365; else return 2366; else if (South == South::Side) if (West == West::Up) return 2367; else if (West == West::Side) return 2368; else return 2369; else if (West == West::Up) return 2370; else if (West == West::Side) return 2371; else return 2372; else if (Power == 3) if (South == South::Up) if (West == West::Up) return 2373; else if (West == West::Side) return 2374; else return 2375; else if (South == South::Side) if (West == West::Up) return 2376; else if (West == West::Side) return 2377; else return 2378; else if (West == West::Up) return 2379; else if (West == West::Side) return 2380; else return 2381; else if (Power == 4) if (South == South::Up) if (West == West::Up) return 2382; else if (West == West::Side) return 2383; else return 2384; else if (South == South::Side) if (West == West::Up) return 2385; else if (West == West::Side) return 2386; else return 2387; else if (West == West::Up) return 2388; else if (West == West::Side) return 2389; else return 2390; else if (Power == 5) if (South == South::Up) if (West == West::Up) return 2391; else if (West == West::Side) return 2392; else return 2393; else if (South == South::Side) if (West == West::Up) return 2394; else if (West == West::Side) return 2395; else return 2396; else if (West == West::Up) return 2397; else if (West == West::Side) return 2398; else return 2399; else if (Power == 6) if (South == South::Up) if (West == West::Up) return 2400; else if (West == West::Side) return 2401; else return 2402; else if (South == South::Side) if (West == West::Up) return 2403; else if (West == West::Side) return 2404; else return 2405; else if (West == West::Up) return 2406; else if (West == West::Side) return 2407; else return 2408; else if (Power == 7) if (South == South::Up) if (West == West::Up) return 2409; else if (West == West::Side) return 2410; else return 2411; else if (South == South::Side) if (West == West::Up) return 2412; else if (West == West::Side) return 2413; else return 2414; else if (West == West::Up) return 2415; else if (West == West::Side) return 2416; else return 2417; else if (Power == 8) if (South == South::Up) if (West == West::Up) return 2418; else if (West == West::Side) return 2419; else return 2420; else if (South == South::Side) if (West == West::Up) return 2421; else if (West == West::Side) return 2422; else return 2423; else if (West == West::Up) return 2424; else if (West == West::Side) return 2425; else return 2426; else if (Power == 9) if (South == South::Up) if (West == West::Up) return 2427; else if (West == West::Side) return 2428; else return 2429; else if (South == South::Side) if (West == West::Up) return 2430; else if (West == West::Side) return 2431; else return 2432; else if (West == West::Up) return 2433; else if (West == West::Side) return 2434; else return 2435; else if (Power == 10) if (South == South::Up) if (West == West::Up) return 2436; else if (West == West::Side) return 2437; else return 2438; else if (South == South::Side) if (West == West::Up) return 2439; else if (West == West::Side) return 2440; else return 2441; else if (West == West::Up) return 2442; else if (West == West::Side) return 2443; else return 2444; else if (Power == 11) if (South == South::Up) if (West == West::Up) return 2445; else if (West == West::Side) return 2446; else return 2447; else if (South == South::Side) if (West == West::Up) return 2448; else if (West == West::Side) return 2449; else return 2450; else if (West == West::Up) return 2451; else if (West == West::Side) return 2452; else return 2453; else if (Power == 12) if (South == South::Up) if (West == West::Up) return 2454; else if (West == West::Side) return 2455; else return 2456; else if (South == South::Side) if (West == West::Up) return 2457; else if (West == West::Side) return 2458; else return 2459; else if (West == West::Up) return 2460; else if (West == West::Side) return 2461; else return 2462; else if (Power == 13) if (South == South::Up) if (West == West::Up) return 2463; else if (West == West::Side) return 2464; else return 2465; else if (South == South::Side) if (West == West::Up) return 2466; else if (West == West::Side) return 2467; else return 2468; else if (West == West::Up) return 2469; else if (West == West::Side) return 2470; else return 2471; else if (Power == 14) if (South == South::Up) if (West == West::Up) return 2472; else if (West == West::Side) return 2473; else return 2474; else if (South == South::Side) if (West == West::Up) return 2475; else if (West == West::Side) return 2476; else return 2477; else if (West == West::Up) return 2478; else if (West == West::Side) return 2479; else return 2480; else if (South == South::Up) if (West == West::Up) return 2481; else if (West == West::Side) return 2482; else return 2483; else if (South == South::Side) if (West == West::Up) return 2484; else if (West == West::Side) return 2485; else return 2486; else if (West == West::Up) return 2487; else if (West == West::Side) return 2488; else return 2489; else if (East == East::Side) if (North == North::Up) if (Power == 0) if (South == South::Up) if (West == West::Up) return 2490; else if (West == West::Side) return 2491; else return 2492; else if (South == South::Side) if (West == West::Up) return 2493; else if (West == West::Side) return 2494; else return 2495; else if (West == West::Up) return 2496; else if (West == West::Side) return 2497; else return 2498; else if (Power == 1) if (South == South::Up) if (West == West::Up) return 2499; else if (West == West::Side) return 2500; else return 2501; else if (South == South::Side) if (West == West::Up) return 2502; else if (West == West::Side) return 2503; else return 2504; else if (West == West::Up) return 2505; else if (West == West::Side) return 2506; else return 2507; else if (Power == 2) if (South == South::Up) if (West == West::Up) return 2508; else if (West == West::Side) return 2509; else return 2510; else if (South == South::Side) if (West == West::Up) return 2511; else if (West == West::Side) return 2512; else return 2513; else if (West == West::Up) return 2514; else if (West == West::Side) return 2515; else return 2516; else if (Power == 3) if (South == South::Up) if (West == West::Up) return 2517; else if (West == West::Side) return 2518; else return 2519; else if (South == South::Side) if (West == West::Up) return 2520; else if (West == West::Side) return 2521; else return 2522; else if (West == West::Up) return 2523; else if (West == West::Side) return 2524; else return 2525; else if (Power == 4) if (South == South::Up) if (West == West::Up) return 2526; else if (West == West::Side) return 2527; else return 2528; else if (South == South::Side) if (West == West::Up) return 2529; else if (West == West::Side) return 2530; else return 2531; else if (West == West::Up) return 2532; else if (West == West::Side) return 2533; else return 2534; else if (Power == 5) if (South == South::Up) if (West == West::Up) return 2535; else if (West == West::Side) return 2536; else return 2537; else if (South == South::Side) if (West == West::Up) return 2538; else if (West == West::Side) return 2539; else return 2540; else if (West == West::Up) return 2541; else if (West == West::Side) return 2542; else return 2543; else if (Power == 6) if (South == South::Up) if (West == West::Up) return 2544; else if (West == West::Side) return 2545; else return 2546; else if (South == South::Side) if (West == West::Up) return 2547; else if (West == West::Side) return 2548; else return 2549; else if (West == West::Up) return 2550; else if (West == West::Side) return 2551; else return 2552; else if (Power == 7) if (South == South::Up) if (West == West::Up) return 2553; else if (West == West::Side) return 2554; else return 2555; else if (South == South::Side) if (West == West::Up) return 2556; else if (West == West::Side) return 2557; else return 2558; else if (West == West::Up) return 2559; else if (West == West::Side) return 2560; else return 2561; else if (Power == 8) if (South == South::Up) if (West == West::Up) return 2562; else if (West == West::Side) return 2563; else return 2564; else if (South == South::Side) if (West == West::Up) return 2565; else if (West == West::Side) return 2566; else return 2567; else if (West == West::Up) return 2568; else if (West == West::Side) return 2569; else return 2570; else if (Power == 9) if (South == South::Up) if (West == West::Up) return 2571; else if (West == West::Side) return 2572; else return 2573; else if (South == South::Side) if (West == West::Up) return 2574; else if (West == West::Side) return 2575; else return 2576; else if (West == West::Up) return 2577; else if (West == West::Side) return 2578; else return 2579; else if (Power == 10) if (South == South::Up) if (West == West::Up) return 2580; else if (West == West::Side) return 2581; else return 2582; else if (South == South::Side) if (West == West::Up) return 2583; else if (West == West::Side) return 2584; else return 2585; else if (West == West::Up) return 2586; else if (West == West::Side) return 2587; else return 2588; else if (Power == 11) if (South == South::Up) if (West == West::Up) return 2589; else if (West == West::Side) return 2590; else return 2591; else if (South == South::Side) if (West == West::Up) return 2592; else if (West == West::Side) return 2593; else return 2594; else if (West == West::Up) return 2595; else if (West == West::Side) return 2596; else return 2597; else if (Power == 12) if (South == South::Up) if (West == West::Up) return 2598; else if (West == West::Side) return 2599; else return 2600; else if (South == South::Side) if (West == West::Up) return 2601; else if (West == West::Side) return 2602; else return 2603; else if (West == West::Up) return 2604; else if (West == West::Side) return 2605; else return 2606; else if (Power == 13) if (South == South::Up) if (West == West::Up) return 2607; else if (West == West::Side) return 2608; else return 2609; else if (South == South::Side) if (West == West::Up) return 2610; else if (West == West::Side) return 2611; else return 2612; else if (West == West::Up) return 2613; else if (West == West::Side) return 2614; else return 2615; else if (Power == 14) if (South == South::Up) if (West == West::Up) return 2616; else if (West == West::Side) return 2617; else return 2618; else if (South == South::Side) if (West == West::Up) return 2619; else if (West == West::Side) return 2620; else return 2621; else if (West == West::Up) return 2622; else if (West == West::Side) return 2623; else return 2624; else if (South == South::Up) if (West == West::Up) return 2625; else if (West == West::Side) return 2626; else return 2627; else if (South == South::Side) if (West == West::Up) return 2628; else if (West == West::Side) return 2629; else return 2630; else if (West == West::Up) return 2631; else if (West == West::Side) return 2632; else return 2633; else if (North == North::Side) if (Power == 0) if (South == South::Up) if (West == West::Up) return 2634; else if (West == West::Side) return 2635; else return 2636; else if (South == South::Side) if (West == West::Up) return 2637; else if (West == West::Side) return 2638; else return 2639; else if (West == West::Up) return 2640; else if (West == West::Side) return 2641; else return 2642; else if (Power == 1) if (South == South::Up) if (West == West::Up) return 2643; else if (West == West::Side) return 2644; else return 2645; else if (South == South::Side) if (West == West::Up) return 2646; else if (West == West::Side) return 2647; else return 2648; else if (West == West::Up) return 2649; else if (West == West::Side) return 2650; else return 2651; else if (Power == 2) if (South == South::Up) if (West == West::Up) return 2652; else if (West == West::Side) return 2653; else return 2654; else if (South == South::Side) if (West == West::Up) return 2655; else if (West == West::Side) return 2656; else return 2657; else if (West == West::Up) return 2658; else if (West == West::Side) return 2659; else return 2660; else if (Power == 3) if (South == South::Up) if (West == West::Up) return 2661; else if (West == West::Side) return 2662; else return 2663; else if (South == South::Side) if (West == West::Up) return 2664; else if (West == West::Side) return 2665; else return 2666; else if (West == West::Up) return 2667; else if (West == West::Side) return 2668; else return 2669; else if (Power == 4) if (South == South::Up) if (West == West::Up) return 2670; else if (West == West::Side) return 2671; else return 2672; else if (South == South::Side) if (West == West::Up) return 2673; else if (West == West::Side) return 2674; else return 2675; else if (West == West::Up) return 2676; else if (West == West::Side) return 2677; else return 2678; else if (Power == 5) if (South == South::Up) if (West == West::Up) return 2679; else if (West == West::Side) return 2680; else return 2681; else if (South == South::Side) if (West == West::Up) return 2682; else if (West == West::Side) return 2683; else return 2684; else if (West == West::Up) return 2685; else if (West == West::Side) return 2686; else return 2687; else if (Power == 6) if (South == South::Up) if (West == West::Up) return 2688; else if (West == West::Side) return 2689; else return 2690; else if (South == South::Side) if (West == West::Up) return 2691; else if (West == West::Side) return 2692; else return 2693; else if (West == West::Up) return 2694; else if (West == West::Side) return 2695; else return 2696; else if (Power == 7) if (South == South::Up) if (West == West::Up) return 2697; else if (West == West::Side) return 2698; else return 2699; else if (South == South::Side) if (West == West::Up) return 2700; else if (West == West::Side) return 2701; else return 2702; else if (West == West::Up) return 2703; else if (West == West::Side) return 2704; else return 2705; else if (Power == 8) if (South == South::Up) if (West == West::Up) return 2706; else if (West == West::Side) return 2707; else return 2708; else if (South == South::Side) if (West == West::Up) return 2709; else if (West == West::Side) return 2710; else return 2711; else if (West == West::Up) return 2712; else if (West == West::Side) return 2713; else return 2714; else if (Power == 9) if (South == South::Up) if (West == West::Up) return 2715; else if (West == West::Side) return 2716; else return 2717; else if (South == South::Side) if (West == West::Up) return 2718; else if (West == West::Side) return 2719; else return 2720; else if (West == West::Up) return 2721; else if (West == West::Side) return 2722; else return 2723; else if (Power == 10) if (South == South::Up) if (West == West::Up) return 2724; else if (West == West::Side) return 2725; else return 2726; else if (South == South::Side) if (West == West::Up) return 2727; else if (West == West::Side) return 2728; else return 2729; else if (West == West::Up) return 2730; else if (West == West::Side) return 2731; else return 2732; else if (Power == 11) if (South == South::Up) if (West == West::Up) return 2733; else if (West == West::Side) return 2734; else return 2735; else if (South == South::Side) if (West == West::Up) return 2736; else if (West == West::Side) return 2737; else return 2738; else if (West == West::Up) return 2739; else if (West == West::Side) return 2740; else return 2741; else if (Power == 12) if (South == South::Up) if (West == West::Up) return 2742; else if (West == West::Side) return 2743; else return 2744; else if (South == South::Side) if (West == West::Up) return 2745; else if (West == West::Side) return 2746; else return 2747; else if (West == West::Up) return 2748; else if (West == West::Side) return 2749; else return 2750; else if (Power == 13) if (South == South::Up) if (West == West::Up) return 2751; else if (West == West::Side) return 2752; else return 2753; else if (South == South::Side) if (West == West::Up) return 2754; else if (West == West::Side) return 2755; else return 2756; else if (West == West::Up) return 2757; else if (West == West::Side) return 2758; else return 2759; else if (Power == 14) if (South == South::Up) if (West == West::Up) return 2760; else if (West == West::Side) return 2761; else return 2762; else if (South == South::Side) if (West == West::Up) return 2763; else if (West == West::Side) return 2764; else return 2765; else if (West == West::Up) return 2766; else if (West == West::Side) return 2767; else return 2768; else if (South == South::Up) if (West == West::Up) return 2769; else if (West == West::Side) return 2770; else return 2771; else if (South == South::Side) if (West == West::Up) return 2772; else if (West == West::Side) return 2773; else return 2774; else if (West == West::Up) return 2775; else if (West == West::Side) return 2776; else return 2777; else if (Power == 0) if (South == South::Up) if (West == West::Up) return 2778; else if (West == West::Side) return 2779; else return 2780; else if (South == South::Side) if (West == West::Up) return 2781; else if (West == West::Side) return 2782; else return 2783; else if (West == West::Up) return 2784; else if (West == West::Side) return 2785; else return 2786; else if (Power == 1) if (South == South::Up) if (West == West::Up) return 2787; else if (West == West::Side) return 2788; else return 2789; else if (South == South::Side) if (West == West::Up) return 2790; else if (West == West::Side) return 2791; else return 2792; else if (West == West::Up) return 2793; else if (West == West::Side) return 2794; else return 2795; else if (Power == 2) if (South == South::Up) if (West == West::Up) return 2796; else if (West == West::Side) return 2797; else return 2798; else if (South == South::Side) if (West == West::Up) return 2799; else if (West == West::Side) return 2800; else return 2801; else if (West == West::Up) return 2802; else if (West == West::Side) return 2803; else return 2804; else if (Power == 3) if (South == South::Up) if (West == West::Up) return 2805; else if (West == West::Side) return 2806; else return 2807; else if (South == South::Side) if (West == West::Up) return 2808; else if (West == West::Side) return 2809; else return 2810; else if (West == West::Up) return 2811; else if (West == West::Side) return 2812; else return 2813; else if (Power == 4) if (South == South::Up) if (West == West::Up) return 2814; else if (West == West::Side) return 2815; else return 2816; else if (South == South::Side) if (West == West::Up) return 2817; else if (West == West::Side) return 2818; else return 2819; else if (West == West::Up) return 2820; else if (West == West::Side) return 2821; else return 2822; else if (Power == 5) if (South == South::Up) if (West == West::Up) return 2823; else if (West == West::Side) return 2824; else return 2825; else if (South == South::Side) if (West == West::Up) return 2826; else if (West == West::Side) return 2827; else return 2828; else if (West == West::Up) return 2829; else if (West == West::Side) return 2830; else return 2831; else if (Power == 6) if (South == South::Up) if (West == West::Up) return 2832; else if (West == West::Side) return 2833; else return 2834; else if (South == South::Side) if (West == West::Up) return 2835; else if (West == West::Side) return 2836; else return 2837; else if (West == West::Up) return 2838; else if (West == West::Side) return 2839; else return 2840; else if (Power == 7) if (South == South::Up) if (West == West::Up) return 2841; else if (West == West::Side) return 2842; else return 2843; else if (South == South::Side) if (West == West::Up) return 2844; else if (West == West::Side) return 2845; else return 2846; else if (West == West::Up) return 2847; else if (West == West::Side) return 2848; else return 2849; else if (Power == 8) if (South == South::Up) if (West == West::Up) return 2850; else if (West == West::Side) return 2851; else return 2852; else if (South == South::Side) if (West == West::Up) return 2853; else if (West == West::Side) return 2854; else return 2855; else if (West == West::Up) return 2856; else if (West == West::Side) return 2857; else return 2858; else if (Power == 9) if (South == South::Up) if (West == West::Up) return 2859; else if (West == West::Side) return 2860; else return 2861; else if (South == South::Side) if (West == West::Up) return 2862; else if (West == West::Side) return 2863; else return 2864; else if (West == West::Up) return 2865; else if (West == West::Side) return 2866; else return 2867; else if (Power == 10) if (South == South::Up) if (West == West::Up) return 2868; else if (West == West::Side) return 2869; else return 2870; else if (South == South::Side) if (West == West::Up) return 2871; else if (West == West::Side) return 2872; else return 2873; else if (West == West::Up) return 2874; else if (West == West::Side) return 2875; else return 2876; else if (Power == 11) if (South == South::Up) if (West == West::Up) return 2877; else if (West == West::Side) return 2878; else return 2879; else if (South == South::Side) if (West == West::Up) return 2880; else if (West == West::Side) return 2881; else return 2882; else if (West == West::Up) return 2883; else if (West == West::Side) return 2884; else return 2885; else if (Power == 12) if (South == South::Up) if (West == West::Up) return 2886; else if (West == West::Side) return 2887; else return 2888; else if (South == South::Side) if (West == West::Up) return 2889; else if (West == West::Side) return 2890; else return 2891; else if (West == West::Up) return 2892; else if (West == West::Side) return 2893; else return 2894; else if (Power == 13) if (South == South::Up) if (West == West::Up) return 2895; else if (West == West::Side) return 2896; else return 2897; else if (South == South::Side) if (West == West::Up) return 2898; else if (West == West::Side) return 2899; else return 2900; else if (West == West::Up) return 2901; else if (West == West::Side) return 2902; else return 2903; else if (Power == 14) if (South == South::Up) if (West == West::Up) return 2904; else if (West == West::Side) return 2905; else return 2906; else if (South == South::Side) if (West == West::Up) return 2907; else if (West == West::Side) return 2908; else return 2909; else if (West == West::Up) return 2910; else if (West == West::Side) return 2911; else return 2912; else if (South == South::Up) if (West == West::Up) return 2913; else if (West == West::Side) return 2914; else return 2915; else if (South == South::Side) if (West == West::Up) return 2916; else if (West == West::Side) return 2917; else return 2918; else if (West == West::Up) return 2919; else if (West == West::Side) return 2920; else return 2921; else if (North == North::Up) if (Power == 0) if (South == South::Up) if (West == West::Up) return 2922; else if (West == West::Side) return 2923; else return 2924; else if (South == South::Side) if (West == West::Up) return 2925; else if (West == West::Side) return 2926; else return 2927; else if (West == West::Up) return 2928; else if (West == West::Side) return 2929; else return 2930; else if (Power == 1) if (South == South::Up) if (West == West::Up) return 2931; else if (West == West::Side) return 2932; else return 2933; else if (South == South::Side) if (West == West::Up) return 2934; else if (West == West::Side) return 2935; else return 2936; else if (West == West::Up) return 2937; else if (West == West::Side) return 2938; else return 2939; else if (Power == 2) if (South == South::Up) if (West == West::Up) return 2940; else if (West == West::Side) return 2941; else return 2942; else if (South == South::Side) if (West == West::Up) return 2943; else if (West == West::Side) return 2944; else return 2945; else if (West == West::Up) return 2946; else if (West == West::Side) return 2947; else return 2948; else if (Power == 3) if (South == South::Up) if (West == West::Up) return 2949; else if (West == West::Side) return 2950; else return 2951; else if (South == South::Side) if (West == West::Up) return 2952; else if (West == West::Side) return 2953; else return 2954; else if (West == West::Up) return 2955; else if (West == West::Side) return 2956; else return 2957; else if (Power == 4) if (South == South::Up) if (West == West::Up) return 2958; else if (West == West::Side) return 2959; else return 2960; else if (South == South::Side) if (West == West::Up) return 2961; else if (West == West::Side) return 2962; else return 2963; else if (West == West::Up) return 2964; else if (West == West::Side) return 2965; else return 2966; else if (Power == 5) if (South == South::Up) if (West == West::Up) return 2967; else if (West == West::Side) return 2968; else return 2969; else if (South == South::Side) if (West == West::Up) return 2970; else if (West == West::Side) return 2971; else return 2972; else if (West == West::Up) return 2973; else if (West == West::Side) return 2974; else return 2975; else if (Power == 6) if (South == South::Up) if (West == West::Up) return 2976; else if (West == West::Side) return 2977; else return 2978; else if (South == South::Side) if (West == West::Up) return 2979; else if (West == West::Side) return 2980; else return 2981; else if (West == West::Up) return 2982; else if (West == West::Side) return 2983; else return 2984; else if (Power == 7) if (South == South::Up) if (West == West::Up) return 2985; else if (West == West::Side) return 2986; else return 2987; else if (South == South::Side) if (West == West::Up) return 2988; else if (West == West::Side) return 2989; else return 2990; else if (West == West::Up) return 2991; else if (West == West::Side) return 2992; else return 2993; else if (Power == 8) if (South == South::Up) if (West == West::Up) return 2994; else if (West == West::Side) return 2995; else return 2996; else if (South == South::Side) if (West == West::Up) return 2997; else if (West == West::Side) return 2998; else return 2999; else if (West == West::Up) return 3000; else if (West == West::Side) return 3001; else return 3002; else if (Power == 9) if (South == South::Up) if (West == West::Up) return 3003; else if (West == West::Side) return 3004; else return 3005; else if (South == South::Side) if (West == West::Up) return 3006; else if (West == West::Side) return 3007; else return 3008; else if (West == West::Up) return 3009; else if (West == West::Side) return 3010; else return 3011; else if (Power == 10) if (South == South::Up) if (West == West::Up) return 3012; else if (West == West::Side) return 3013; else return 3014; else if (South == South::Side) if (West == West::Up) return 3015; else if (West == West::Side) return 3016; else return 3017; else if (West == West::Up) return 3018; else if (West == West::Side) return 3019; else return 3020; else if (Power == 11) if (South == South::Up) if (West == West::Up) return 3021; else if (West == West::Side) return 3022; else return 3023; else if (South == South::Side) if (West == West::Up) return 3024; else if (West == West::Side) return 3025; else return 3026; else if (West == West::Up) return 3027; else if (West == West::Side) return 3028; else return 3029; else if (Power == 12) if (South == South::Up) if (West == West::Up) return 3030; else if (West == West::Side) return 3031; else return 3032; else if (South == South::Side) if (West == West::Up) return 3033; else if (West == West::Side) return 3034; else return 3035; else if (West == West::Up) return 3036; else if (West == West::Side) return 3037; else return 3038; else if (Power == 13) if (South == South::Up) if (West == West::Up) return 3039; else if (West == West::Side) return 3040; else return 3041; else if (South == South::Side) if (West == West::Up) return 3042; else if (West == West::Side) return 3043; else return 3044; else if (West == West::Up) return 3045; else if (West == West::Side) return 3046; else return 3047; else if (Power == 14) if (South == South::Up) if (West == West::Up) return 3048; else if (West == West::Side) return 3049; else return 3050; else if (South == South::Side) if (West == West::Up) return 3051; else if (West == West::Side) return 3052; else return 3053; else if (West == West::Up) return 3054; else if (West == West::Side) return 3055; else return 3056; else if (South == South::Up) if (West == West::Up) return 3057; else if (West == West::Side) return 3058; else return 3059; else if (South == South::Side) if (West == West::Up) return 3060; else if (West == West::Side) return 3061; else return 3062; else if (West == West::Up) return 3063; else if (West == West::Side) return 3064; else return 3065; else if (North == North::Side) if (Power == 0) if (South == South::Up) if (West == West::Up) return 3066; else if (West == West::Side) return 3067; else return 3068; else if (South == South::Side) if (West == West::Up) return 3069; else if (West == West::Side) return 3070; else return 3071; else if (West == West::Up) return 3072; else if (West == West::Side) return 3073; else return 3074; else if (Power == 1) if (South == South::Up) if (West == West::Up) return 3075; else if (West == West::Side) return 3076; else return 3077; else if (South == South::Side) if (West == West::Up) return 3078; else if (West == West::Side) return 3079; else return 3080; else if (West == West::Up) return 3081; else if (West == West::Side) return 3082; else return 3083; else if (Power == 2) if (South == South::Up) if (West == West::Up) return 3084; else if (West == West::Side) return 3085; else return 3086; else if (South == South::Side) if (West == West::Up) return 3087; else if (West == West::Side) return 3088; else return 3089; else if (West == West::Up) return 3090; else if (West == West::Side) return 3091; else return 3092; else if (Power == 3) if (South == South::Up) if (West == West::Up) return 3093; else if (West == West::Side) return 3094; else return 3095; else if (South == South::Side) if (West == West::Up) return 3096; else if (West == West::Side) return 3097; else return 3098; else if (West == West::Up) return 3099; else if (West == West::Side) return 3100; else return 3101; else if (Power == 4) if (South == South::Up) if (West == West::Up) return 3102; else if (West == West::Side) return 3103; else return 3104; else if (South == South::Side) if (West == West::Up) return 3105; else if (West == West::Side) return 3106; else return 3107; else if (West == West::Up) return 3108; else if (West == West::Side) return 3109; else return 3110; else if (Power == 5) if (South == South::Up) if (West == West::Up) return 3111; else if (West == West::Side) return 3112; else return 3113; else if (South == South::Side) if (West == West::Up) return 3114; else if (West == West::Side) return 3115; else return 3116; else if (West == West::Up) return 3117; else if (West == West::Side) return 3118; else return 3119; else if (Power == 6) if (South == South::Up) if (West == West::Up) return 3120; else if (West == West::Side) return 3121; else return 3122; else if (South == South::Side) if (West == West::Up) return 3123; else if (West == West::Side) return 3124; else return 3125; else if (West == West::Up) return 3126; else if (West == West::Side) return 3127; else return 3128; else if (Power == 7) if (South == South::Up) if (West == West::Up) return 3129; else if (West == West::Side) return 3130; else return 3131; else if (South == South::Side) if (West == West::Up) return 3132; else if (West == West::Side) return 3133; else return 3134; else if (West == West::Up) return 3135; else if (West == West::Side) return 3136; else return 3137; else if (Power == 8) if (South == South::Up) if (West == West::Up) return 3138; else if (West == West::Side) return 3139; else return 3140; else if (South == South::Side) if (West == West::Up) return 3141; else if (West == West::Side) return 3142; else return 3143; else if (West == West::Up) return 3144; else if (West == West::Side) return 3145; else return 3146; else if (Power == 9) if (South == South::Up) if (West == West::Up) return 3147; else if (West == West::Side) return 3148; else return 3149; else if (South == South::Side) if (West == West::Up) return 3150; else if (West == West::Side) return 3151; else return 3152; else if (West == West::Up) return 3153; else if (West == West::Side) return 3154; else return 3155; else if (Power == 10) if (South == South::Up) if (West == West::Up) return 3156; else if (West == West::Side) return 3157; else return 3158; else if (South == South::Side) if (West == West::Up) return 3159; else if (West == West::Side) return 3160; else return 3161; else if (West == West::Up) return 3162; else if (West == West::Side) return 3163; else return 3164; else if (Power == 11) if (South == South::Up) if (West == West::Up) return 3165; else if (West == West::Side) return 3166; else return 3167; else if (South == South::Side) if (West == West::Up) return 3168; else if (West == West::Side) return 3169; else return 3170; else if (West == West::Up) return 3171; else if (West == West::Side) return 3172; else return 3173; else if (Power == 12) if (South == South::Up) if (West == West::Up) return 3174; else if (West == West::Side) return 3175; else return 3176; else if (South == South::Side) if (West == West::Up) return 3177; else if (West == West::Side) return 3178; else return 3179; else if (West == West::Up) return 3180; else if (West == West::Side) return 3181; else return 3182; else if (Power == 13) if (South == South::Up) if (West == West::Up) return 3183; else if (West == West::Side) return 3184; else return 3185; else if (South == South::Side) if (West == West::Up) return 3186; else if (West == West::Side) return 3187; else return 3188; else if (West == West::Up) return 3189; else if (West == West::Side) return 3190; else return 3191; else if (Power == 14) if (South == South::Up) if (West == West::Up) return 3192; else if (West == West::Side) return 3193; else return 3194; else if (South == South::Side) if (West == West::Up) return 3195; else if (West == West::Side) return 3196; else return 3197; else if (West == West::Up) return 3198; else if (West == West::Side) return 3199; else return 3200; else if (South == South::Up) if (West == West::Up) return 3201; else if (West == West::Side) return 3202; else return 3203; else if (South == South::Side) if (West == West::Up) return 3204; else if (West == West::Side) return 3205; else return 3206; else if (West == West::Up) return 3207; else if (West == West::Side) return 3208; else return 3209; else if (Power == 0) if (South == South::Up) if (West == West::Up) return 3210; else if (West == West::Side) return 3211; else return 3212; else if (South == South::Side) if (West == West::Up) return 3213; else if (West == West::Side) return 3214; else return 3215; else if (West == West::Up) return 3216; else if (West == West::Side) return 3217; else return 3218; else if (Power == 1) if (South == South::Up) if (West == West::Up) return 3219; else if (West == West::Side) return 3220; else return 3221; else if (South == South::Side) if (West == West::Up) return 3222; else if (West == West::Side) return 3223; else return 3224; else if (West == West::Up) return 3225; else if (West == West::Side) return 3226; else return 3227; else if (Power == 2) if (South == South::Up) if (West == West::Up) return 3228; else if (West == West::Side) return 3229; else return 3230; else if (South == South::Side) if (West == West::Up) return 3231; else if (West == West::Side) return 3232; else return 3233; else if (West == West::Up) return 3234; else if (West == West::Side) return 3235; else return 3236; else if (Power == 3) if (South == South::Up) if (West == West::Up) return 3237; else if (West == West::Side) return 3238; else return 3239; else if (South == South::Side) if (West == West::Up) return 3240; else if (West == West::Side) return 3241; else return 3242; else if (West == West::Up) return 3243; else if (West == West::Side) return 3244; else return 3245; else if (Power == 4) if (South == South::Up) if (West == West::Up) return 3246; else if (West == West::Side) return 3247; else return 3248; else if (South == South::Side) if (West == West::Up) return 3249; else if (West == West::Side) return 3250; else return 3251; else if (West == West::Up) return 3252; else if (West == West::Side) return 3253; else return 3254; else if (Power == 5) if (South == South::Up) if (West == West::Up) return 3255; else if (West == West::Side) return 3256; else return 3257; else if (South == South::Side) if (West == West::Up) return 3258; else if (West == West::Side) return 3259; else return 3260; else if (West == West::Up) return 3261; else if (West == West::Side) return 3262; else return 3263; else if (Power == 6) if (South == South::Up) if (West == West::Up) return 3264; else if (West == West::Side) return 3265; else return 3266; else if (South == South::Side) if (West == West::Up) return 3267; else if (West == West::Side) return 3268; else return 3269; else if (West == West::Up) return 3270; else if (West == West::Side) return 3271; else return 3272; else if (Power == 7) if (South == South::Up) if (West == West::Up) return 3273; else if (West == West::Side) return 3274; else return 3275; else if (South == South::Side) if (West == West::Up) return 3276; else if (West == West::Side) return 3277; else return 3278; else if (West == West::Up) return 3279; else if (West == West::Side) return 3280; else return 3281; else if (Power == 8) if (South == South::Up) if (West == West::Up) return 3282; else if (West == West::Side) return 3283; else return 3284; else if (South == South::Side) if (West == West::Up) return 3285; else if (West == West::Side) return 3286; else return 3287; else if (West == West::Up) return 3288; else if (West == West::Side) return 3289; else return 3290; else if (Power == 9) if (South == South::Up) if (West == West::Up) return 3291; else if (West == West::Side) return 3292; else return 3293; else if (South == South::Side) if (West == West::Up) return 3294; else if (West == West::Side) return 3295; else return 3296; else if (West == West::Up) return 3297; else if (West == West::Side) return 3298; else return 3299; else if (Power == 10) if (South == South::Up) if (West == West::Up) return 3300; else if (West == West::Side) return 3301; else return 3302; else if (South == South::Side) if (West == West::Up) return 3303; else if (West == West::Side) return 3304; else return 3305; else if (West == West::Up) return 3306; else if (West == West::Side) return 3307; else return 3308; else if (Power == 11) if (South == South::Up) if (West == West::Up) return 3309; else if (West == West::Side) return 3310; else return 3311; else if (South == South::Side) if (West == West::Up) return 3312; else if (West == West::Side) return 3313; else return 3314; else if (West == West::Up) return 3315; else if (West == West::Side) return 3316; else return 3317; else if (Power == 12) if (South == South::Up) if (West == West::Up) return 3318; else if (West == West::Side) return 3319; else return 3320; else if (South == South::Side) if (West == West::Up) return 3321; else if (West == West::Side) return 3322; else return 3323; else if (West == West::Up) return 3324; else if (West == West::Side) return 3325; else return 3326; else if (Power == 13) if (South == South::Up) if (West == West::Up) return 3327; else if (West == West::Side) return 3328; else return 3329; else if (South == South::Side) if (West == West::Up) return 3330; else if (West == West::Side) return 3331; else return 3332; else if (West == West::Up) return 3333; else if (West == West::Side) return 3334; else return 3335; else if (Power == 14) if (South == South::Up) if (West == West::Up) return 3336; else if (West == West::Side) return 3337; else return 3338; else if (South == South::Side) if (West == West::Up) return 3339; else if (West == West::Side) return 3340; else return 3341; else if (West == West::Up) return 3342; else if (West == West::Side) return 3343; else return 3344; else if (South == South::Up) if (West == West::Up) return 3345; else if (West == West::Side) return 3346; else return 3347; else if (South == South::Side) if (West == West::Up) return 3348; else if (West == West::Side) return 3349; else return 3350; else if (West == West::Up) return 3351; else if (West == West::Side) return 3352; else return 3353; } BlockState RedstoneWire(); enum East East(BlockState Block); enum North North(BlockState Block); unsigned char Power(BlockState Block); enum South South(BlockState Block); enum West West(BlockState Block); } namespace Repeater { constexpr BlockState Repeater(const unsigned char Delay, const eBlockFace Facing, const bool Locked, const bool Powered) { if (Delay == 1) if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Locked) if (Powered) return 4031; else return 4032; else if (Powered) return 4033; else return 4034; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Locked) if (Powered) return 4035; else return 4036; else if (Powered) return 4037; else return 4038; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Locked) if (Powered) return 4039; else return 4040; else if (Powered) return 4041; else return 4042; else if (Locked) if (Powered) return 4043; else return 4044; else if (Powered) return 4045; else return 4046; else if (Delay == 2) if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Locked) if (Powered) return 4047; else return 4048; else if (Powered) return 4049; else return 4050; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Locked) if (Powered) return 4051; else return 4052; else if (Powered) return 4053; else return 4054; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Locked) if (Powered) return 4055; else return 4056; else if (Powered) return 4057; else return 4058; else if (Locked) if (Powered) return 4059; else return 4060; else if (Powered) return 4061; else return 4062; else if (Delay == 3) if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Locked) if (Powered) return 4063; else return 4064; else if (Powered) return 4065; else return 4066; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Locked) if (Powered) return 4067; else return 4068; else if (Powered) return 4069; else return 4070; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Locked) if (Powered) return 4071; else return 4072; else if (Powered) return 4073; else return 4074; else if (Locked) if (Powered) return 4075; else return 4076; else if (Powered) return 4077; else return 4078; else if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Locked) if (Powered) return 4079; else return 4080; else if (Powered) return 4081; else return 4082; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Locked) if (Powered) return 4083; else return 4084; else if (Powered) return 4085; else return 4086; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Locked) if (Powered) return 4087; else return 4088; else if (Powered) return 4089; else return 4090; else if (Locked) if (Powered) return 4091; else return 4092; else if (Powered) return 4093; else return 4094; } BlockState Repeater(); unsigned char Delay(BlockState Block); eBlockFace Facing(BlockState Block); bool Locked(BlockState Block); bool Powered(BlockState Block); } namespace RepeatingCommandBlock { constexpr BlockState RepeatingCommandBlock(const bool Conditional, const eBlockFace Facing) { if (Conditional) if (Facing == eBlockFace::BLOCK_FACE_ZM) return 9225; else if (Facing == eBlockFace::BLOCK_FACE_XP) return 9226; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 9227; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 9228; else if (Facing == eBlockFace::BLOCK_FACE_YP) return 9229; else return 9230; else if (Facing == eBlockFace::BLOCK_FACE_ZM) return 9231; else if (Facing == eBlockFace::BLOCK_FACE_XP) return 9232; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 9233; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 9234; else if (Facing == eBlockFace::BLOCK_FACE_YP) return 9235; else return 9236; } BlockState RepeatingCommandBlock(); bool Conditional(BlockState Block); eBlockFace Facing(BlockState Block); } namespace RespawnAnchor { constexpr BlockState RespawnAnchor(const unsigned char Charges) { if (Charges == 0) return 15829; else if (Charges == 1) return 15830; else if (Charges == 2) return 15831; else if (Charges == 3) return 15832; else return 15833; } BlockState RespawnAnchor(); unsigned char Charges(BlockState Block); } namespace RoseBush { enum class Half { Upper, Lower }; constexpr BlockState RoseBush(const enum Half Half) { if (Half == Half::Upper) return 7889; else return 7890; } BlockState RoseBush(); enum Half Half(BlockState Block); } namespace Sand { constexpr BlockState Sand() { return 66; } } namespace Sandstone { constexpr BlockState Sandstone() { return 246; } } namespace SandstoneSlab { enum class Type { Top, Bottom, Double }; constexpr BlockState SandstoneSlab(const enum Type Type) { if (Type == Type::Top) return 8349; else if (Type == Type::Bottom) return 8351; else return 8353; } BlockState SandstoneSlab(); enum Type Type(BlockState Block); } namespace SandstoneStairs { enum class Half { Top, Bottom }; enum class Shape { Straight, InnerLeft, InnerRight, OuterLeft, OuterRight }; constexpr BlockState SandstoneStairs(const eBlockFace Facing, const enum Half Half, const enum Shape Shape) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Half == Half::Top) if (Shape == Shape::Straight) return 5171; else if (Shape == Shape::InnerLeft) return 5173; else if (Shape == Shape::InnerRight) return 5175; else if (Shape == Shape::OuterLeft) return 5177; else return 5179; else if (Shape == Shape::Straight) return 5181; else if (Shape == Shape::InnerLeft) return 5183; else if (Shape == Shape::InnerRight) return 5185; else if (Shape == Shape::OuterLeft) return 5187; else return 5189; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Half == Half::Top) if (Shape == Shape::Straight) return 5191; else if (Shape == Shape::InnerLeft) return 5193; else if (Shape == Shape::InnerRight) return 5195; else if (Shape == Shape::OuterLeft) return 5197; else return 5199; else if (Shape == Shape::Straight) return 5201; else if (Shape == Shape::InnerLeft) return 5203; else if (Shape == Shape::InnerRight) return 5205; else if (Shape == Shape::OuterLeft) return 5207; else return 5209; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Half == Half::Top) if (Shape == Shape::Straight) return 5211; else if (Shape == Shape::InnerLeft) return 5213; else if (Shape == Shape::InnerRight) return 5215; else if (Shape == Shape::OuterLeft) return 5217; else return 5219; else if (Shape == Shape::Straight) return 5221; else if (Shape == Shape::InnerLeft) return 5223; else if (Shape == Shape::InnerRight) return 5225; else if (Shape == Shape::OuterLeft) return 5227; else return 5229; else if (Half == Half::Top) if (Shape == Shape::Straight) return 5231; else if (Shape == Shape::InnerLeft) return 5233; else if (Shape == Shape::InnerRight) return 5235; else if (Shape == Shape::OuterLeft) return 5237; else return 5239; else if (Shape == Shape::Straight) return 5241; else if (Shape == Shape::InnerLeft) return 5243; else if (Shape == Shape::InnerRight) return 5245; else if (Shape == Shape::OuterLeft) return 5247; else return 5249; } BlockState SandstoneStairs(); eBlockFace Facing(BlockState Block); enum Half Half(BlockState Block); enum Shape Shape(BlockState Block); } namespace SandstoneWall { enum class East { None, Low, Tall }; enum class North { None, Low, Tall }; enum class South { None, Low, Tall }; enum class West { None, Low, Tall }; constexpr BlockState SandstoneWall(const enum East East, const enum North North, const enum South South, const bool Up, const enum West West) { if (East == East::None) if (North == North::None) if (South == South::None) if (Up) if (West == West::None) return 13786; else if (West == West::Low) return 13787; else return 13788; else if (West == West::None) return 13792; else if (West == West::Low) return 13793; else return 13794; else if (South == South::Low) if (Up) if (West == West::None) return 13798; else if (West == West::Low) return 13799; else return 13800; else if (West == West::None) return 13804; else if (West == West::Low) return 13805; else return 13806; else if (Up) if (West == West::None) return 13810; else if (West == West::Low) return 13811; else return 13812; else if (West == West::None) return 13816; else if (West == West::Low) return 13817; else return 13818; else if (North == North::Low) if (South == South::None) if (Up) if (West == West::None) return 13822; else if (West == West::Low) return 13823; else return 13824; else if (West == West::None) return 13828; else if (West == West::Low) return 13829; else return 13830; else if (South == South::Low) if (Up) if (West == West::None) return 13834; else if (West == West::Low) return 13835; else return 13836; else if (West == West::None) return 13840; else if (West == West::Low) return 13841; else return 13842; else if (Up) if (West == West::None) return 13846; else if (West == West::Low) return 13847; else return 13848; else if (West == West::None) return 13852; else if (West == West::Low) return 13853; else return 13854; else if (South == South::None) if (Up) if (West == West::None) return 13858; else if (West == West::Low) return 13859; else return 13860; else if (West == West::None) return 13864; else if (West == West::Low) return 13865; else return 13866; else if (South == South::Low) if (Up) if (West == West::None) return 13870; else if (West == West::Low) return 13871; else return 13872; else if (West == West::None) return 13876; else if (West == West::Low) return 13877; else return 13878; else if (Up) if (West == West::None) return 13882; else if (West == West::Low) return 13883; else return 13884; else if (West == West::None) return 13888; else if (West == West::Low) return 13889; else return 13890; else if (East == East::Low) if (North == North::None) if (South == South::None) if (Up) if (West == West::None) return 13894; else if (West == West::Low) return 13895; else return 13896; else if (West == West::None) return 13900; else if (West == West::Low) return 13901; else return 13902; else if (South == South::Low) if (Up) if (West == West::None) return 13906; else if (West == West::Low) return 13907; else return 13908; else if (West == West::None) return 13912; else if (West == West::Low) return 13913; else return 13914; else if (Up) if (West == West::None) return 13918; else if (West == West::Low) return 13919; else return 13920; else if (West == West::None) return 13924; else if (West == West::Low) return 13925; else return 13926; else if (North == North::Low) if (South == South::None) if (Up) if (West == West::None) return 13930; else if (West == West::Low) return 13931; else return 13932; else if (West == West::None) return 13936; else if (West == West::Low) return 13937; else return 13938; else if (South == South::Low) if (Up) if (West == West::None) return 13942; else if (West == West::Low) return 13943; else return 13944; else if (West == West::None) return 13948; else if (West == West::Low) return 13949; else return 13950; else if (Up) if (West == West::None) return 13954; else if (West == West::Low) return 13955; else return 13956; else if (West == West::None) return 13960; else if (West == West::Low) return 13961; else return 13962; else if (South == South::None) if (Up) if (West == West::None) return 13966; else if (West == West::Low) return 13967; else return 13968; else if (West == West::None) return 13972; else if (West == West::Low) return 13973; else return 13974; else if (South == South::Low) if (Up) if (West == West::None) return 13978; else if (West == West::Low) return 13979; else return 13980; else if (West == West::None) return 13984; else if (West == West::Low) return 13985; else return 13986; else if (Up) if (West == West::None) return 13990; else if (West == West::Low) return 13991; else return 13992; else if (West == West::None) return 13996; else if (West == West::Low) return 13997; else return 13998; else if (North == North::None) if (South == South::None) if (Up) if (West == West::None) return 14002; else if (West == West::Low) return 14003; else return 14004; else if (West == West::None) return 14008; else if (West == West::Low) return 14009; else return 14010; else if (South == South::Low) if (Up) if (West == West::None) return 14014; else if (West == West::Low) return 14015; else return 14016; else if (West == West::None) return 14020; else if (West == West::Low) return 14021; else return 14022; else if (Up) if (West == West::None) return 14026; else if (West == West::Low) return 14027; else return 14028; else if (West == West::None) return 14032; else if (West == West::Low) return 14033; else return 14034; else if (North == North::Low) if (South == South::None) if (Up) if (West == West::None) return 14038; else if (West == West::Low) return 14039; else return 14040; else if (West == West::None) return 14044; else if (West == West::Low) return 14045; else return 14046; else if (South == South::Low) if (Up) if (West == West::None) return 14050; else if (West == West::Low) return 14051; else return 14052; else if (West == West::None) return 14056; else if (West == West::Low) return 14057; else return 14058; else if (Up) if (West == West::None) return 14062; else if (West == West::Low) return 14063; else return 14064; else if (West == West::None) return 14068; else if (West == West::Low) return 14069; else return 14070; else if (South == South::None) if (Up) if (West == West::None) return 14074; else if (West == West::Low) return 14075; else return 14076; else if (West == West::None) return 14080; else if (West == West::Low) return 14081; else return 14082; else if (South == South::Low) if (Up) if (West == West::None) return 14086; else if (West == West::Low) return 14087; else return 14088; else if (West == West::None) return 14092; else if (West == West::Low) return 14093; else return 14094; else if (Up) if (West == West::None) return 14098; else if (West == West::Low) return 14099; else return 14100; else if (West == West::None) return 14104; else if (West == West::Low) return 14105; else return 14106; } BlockState SandstoneWall(); enum East East(BlockState Block); enum North North(BlockState Block); enum South South(BlockState Block); bool Up(BlockState Block); enum West West(BlockState Block); } namespace Scaffolding { constexpr BlockState Scaffolding(const bool Bottom, const unsigned char Distance) { if (Bottom) if (Distance == 0) return 14756; else if (Distance == 1) return 14758; else if (Distance == 2) return 14760; else if (Distance == 3) return 14762; else if (Distance == 4) return 14764; else if (Distance == 5) return 14766; else if (Distance == 6) return 14768; else return 14770; else if (Distance == 0) return 14772; else if (Distance == 1) return 14774; else if (Distance == 2) return 14776; else if (Distance == 3) return 14778; else if (Distance == 4) return 14780; else if (Distance == 5) return 14782; else if (Distance == 6) return 14784; else return 14786; } BlockState Scaffolding(); bool Bottom(BlockState Block); unsigned char Distance(BlockState Block); } namespace SeaLantern { constexpr BlockState SeaLantern() { return 7862; } } namespace SeaPickle { constexpr BlockState SeaPickle(const unsigned char Pickles) { if (Pickles == 1) return 9641; else if (Pickles == 2) return 9643; else if (Pickles == 3) return 9645; else return 9647; } BlockState SeaPickle(); unsigned char Pickles(BlockState Block); } namespace Seagrass { constexpr BlockState Seagrass() { return 1345; } } namespace Shroomlight { constexpr BlockState Shroomlight() { return 14989; } } namespace ShulkerBox { constexpr BlockState ShulkerBox(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 9272; else if (Facing == eBlockFace::BLOCK_FACE_XP) return 9273; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 9274; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 9275; else if (Facing == eBlockFace::BLOCK_FACE_YP) return 9276; else return 9277; } BlockState ShulkerBox(); eBlockFace Facing(BlockState Block); } namespace SkeletonSkull { constexpr BlockState SkeletonSkull(const unsigned char Rotation) { if (Rotation == 0) return 6490; else if (Rotation == 1) return 6491; else if (Rotation == 2) return 6492; else if (Rotation == 3) return 6493; else if (Rotation == 4) return 6494; else if (Rotation == 5) return 6495; else if (Rotation == 6) return 6496; else if (Rotation == 7) return 6497; else if (Rotation == 8) return 6498; else if (Rotation == 9) return 6499; else if (Rotation == 10) return 6500; else if (Rotation == 11) return 6501; else if (Rotation == 12) return 6502; else if (Rotation == 13) return 6503; else if (Rotation == 14) return 6504; else return 6505; } BlockState SkeletonSkull(); unsigned char Rotation(BlockState Block); } namespace SkeletonWallSkull { constexpr BlockState SkeletonWallSkull(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 6506; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 6507; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 6508; else return 6509; } BlockState SkeletonWallSkull(); eBlockFace Facing(BlockState Block); } namespace SlimeBlock { constexpr BlockState SlimeBlock() { return 7535; } } namespace SmithingTable { constexpr BlockState SmithingTable() { return 14849; } } namespace Smoker { constexpr BlockState Smoker(const eBlockFace Facing, const bool Lit) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Lit) return 14803; else return 14804; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Lit) return 14805; else return 14806; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Lit) return 14807; else return 14808; else if (Lit) return 14809; else return 14810; } BlockState Smoker(); eBlockFace Facing(BlockState Block); bool Lit(BlockState Block); } namespace SmoothQuartz { constexpr BlockState SmoothQuartz() { return 8416; } } namespace SmoothQuartzSlab { enum class Type { Top, Bottom, Double }; constexpr BlockState SmoothQuartzSlab(const enum Type Type) { if (Type == Type::Top) return 10832; else if (Type == Type::Bottom) return 10834; else return 10836; } BlockState SmoothQuartzSlab(); enum Type Type(BlockState Block); } namespace SmoothQuartzStairs { enum class Half { Top, Bottom }; enum class Shape { Straight, InnerLeft, InnerRight, OuterLeft, OuterRight }; constexpr BlockState SmoothQuartzStairs(const eBlockFace Facing, const enum Half Half, const enum Shape Shape) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Half == Half::Top) if (Shape == Shape::Straight) return 10310; else if (Shape == Shape::InnerLeft) return 10312; else if (Shape == Shape::InnerRight) return 10314; else if (Shape == Shape::OuterLeft) return 10316; else return 10318; else if (Shape == Shape::Straight) return 10320; else if (Shape == Shape::InnerLeft) return 10322; else if (Shape == Shape::InnerRight) return 10324; else if (Shape == Shape::OuterLeft) return 10326; else return 10328; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Half == Half::Top) if (Shape == Shape::Straight) return 10330; else if (Shape == Shape::InnerLeft) return 10332; else if (Shape == Shape::InnerRight) return 10334; else if (Shape == Shape::OuterLeft) return 10336; else return 10338; else if (Shape == Shape::Straight) return 10340; else if (Shape == Shape::InnerLeft) return 10342; else if (Shape == Shape::InnerRight) return 10344; else if (Shape == Shape::OuterLeft) return 10346; else return 10348; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Half == Half::Top) if (Shape == Shape::Straight) return 10350; else if (Shape == Shape::InnerLeft) return 10352; else if (Shape == Shape::InnerRight) return 10354; else if (Shape == Shape::OuterLeft) return 10356; else return 10358; else if (Shape == Shape::Straight) return 10360; else if (Shape == Shape::InnerLeft) return 10362; else if (Shape == Shape::InnerRight) return 10364; else if (Shape == Shape::OuterLeft) return 10366; else return 10368; else if (Half == Half::Top) if (Shape == Shape::Straight) return 10370; else if (Shape == Shape::InnerLeft) return 10372; else if (Shape == Shape::InnerRight) return 10374; else if (Shape == Shape::OuterLeft) return 10376; else return 10378; else if (Shape == Shape::Straight) return 10380; else if (Shape == Shape::InnerLeft) return 10382; else if (Shape == Shape::InnerRight) return 10384; else if (Shape == Shape::OuterLeft) return 10386; else return 10388; } BlockState SmoothQuartzStairs(); eBlockFace Facing(BlockState Block); enum Half Half(BlockState Block); enum Shape Shape(BlockState Block); } namespace SmoothRedSandstone { constexpr BlockState SmoothRedSandstone() { return 8417; } } namespace SmoothRedSandstoneSlab { enum class Type { Top, Bottom, Double }; constexpr BlockState SmoothRedSandstoneSlab(const enum Type Type) { if (Type == Type::Top) return 10796; else if (Type == Type::Bottom) return 10798; else return 10800; } BlockState SmoothRedSandstoneSlab(); enum Type Type(BlockState Block); } namespace SmoothRedSandstoneStairs { enum class Half { Top, Bottom }; enum class Shape { Straight, InnerLeft, InnerRight, OuterLeft, OuterRight }; constexpr BlockState SmoothRedSandstoneStairs(const eBlockFace Facing, const enum Half Half, const enum Shape Shape) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Half == Half::Top) if (Shape == Shape::Straight) return 9750; else if (Shape == Shape::InnerLeft) return 9752; else if (Shape == Shape::InnerRight) return 9754; else if (Shape == Shape::OuterLeft) return 9756; else return 9758; else if (Shape == Shape::Straight) return 9760; else if (Shape == Shape::InnerLeft) return 9762; else if (Shape == Shape::InnerRight) return 9764; else if (Shape == Shape::OuterLeft) return 9766; else return 9768; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Half == Half::Top) if (Shape == Shape::Straight) return 9770; else if (Shape == Shape::InnerLeft) return 9772; else if (Shape == Shape::InnerRight) return 9774; else if (Shape == Shape::OuterLeft) return 9776; else return 9778; else if (Shape == Shape::Straight) return 9780; else if (Shape == Shape::InnerLeft) return 9782; else if (Shape == Shape::InnerRight) return 9784; else if (Shape == Shape::OuterLeft) return 9786; else return 9788; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Half == Half::Top) if (Shape == Shape::Straight) return 9790; else if (Shape == Shape::InnerLeft) return 9792; else if (Shape == Shape::InnerRight) return 9794; else if (Shape == Shape::OuterLeft) return 9796; else return 9798; else if (Shape == Shape::Straight) return 9800; else if (Shape == Shape::InnerLeft) return 9802; else if (Shape == Shape::InnerRight) return 9804; else if (Shape == Shape::OuterLeft) return 9806; else return 9808; else if (Half == Half::Top) if (Shape == Shape::Straight) return 9810; else if (Shape == Shape::InnerLeft) return 9812; else if (Shape == Shape::InnerRight) return 9814; else if (Shape == Shape::OuterLeft) return 9816; else return 9818; else if (Shape == Shape::Straight) return 9820; else if (Shape == Shape::InnerLeft) return 9822; else if (Shape == Shape::InnerRight) return 9824; else if (Shape == Shape::OuterLeft) return 9826; else return 9828; } BlockState SmoothRedSandstoneStairs(); eBlockFace Facing(BlockState Block); enum Half Half(BlockState Block); enum Shape Shape(BlockState Block); } namespace SmoothSandstone { constexpr BlockState SmoothSandstone() { return 8415; } } namespace SmoothSandstoneSlab { enum class Type { Top, Bottom, Double }; constexpr BlockState SmoothSandstoneSlab(const enum Type Type) { if (Type == Type::Top) return 10826; else if (Type == Type::Bottom) return 10828; else return 10830; } BlockState SmoothSandstoneSlab(); enum Type Type(BlockState Block); } namespace SmoothSandstoneStairs { enum class Half { Top, Bottom }; enum class Shape { Straight, InnerLeft, InnerRight, OuterLeft, OuterRight }; constexpr BlockState SmoothSandstoneStairs(const eBlockFace Facing, const enum Half Half, const enum Shape Shape) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Half == Half::Top) if (Shape == Shape::Straight) return 10230; else if (Shape == Shape::InnerLeft) return 10232; else if (Shape == Shape::InnerRight) return 10234; else if (Shape == Shape::OuterLeft) return 10236; else return 10238; else if (Shape == Shape::Straight) return 10240; else if (Shape == Shape::InnerLeft) return 10242; else if (Shape == Shape::InnerRight) return 10244; else if (Shape == Shape::OuterLeft) return 10246; else return 10248; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Half == Half::Top) if (Shape == Shape::Straight) return 10250; else if (Shape == Shape::InnerLeft) return 10252; else if (Shape == Shape::InnerRight) return 10254; else if (Shape == Shape::OuterLeft) return 10256; else return 10258; else if (Shape == Shape::Straight) return 10260; else if (Shape == Shape::InnerLeft) return 10262; else if (Shape == Shape::InnerRight) return 10264; else if (Shape == Shape::OuterLeft) return 10266; else return 10268; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Half == Half::Top) if (Shape == Shape::Straight) return 10270; else if (Shape == Shape::InnerLeft) return 10272; else if (Shape == Shape::InnerRight) return 10274; else if (Shape == Shape::OuterLeft) return 10276; else return 10278; else if (Shape == Shape::Straight) return 10280; else if (Shape == Shape::InnerLeft) return 10282; else if (Shape == Shape::InnerRight) return 10284; else if (Shape == Shape::OuterLeft) return 10286; else return 10288; else if (Half == Half::Top) if (Shape == Shape::Straight) return 10290; else if (Shape == Shape::InnerLeft) return 10292; else if (Shape == Shape::InnerRight) return 10294; else if (Shape == Shape::OuterLeft) return 10296; else return 10298; else if (Shape == Shape::Straight) return 10300; else if (Shape == Shape::InnerLeft) return 10302; else if (Shape == Shape::InnerRight) return 10304; else if (Shape == Shape::OuterLeft) return 10306; else return 10308; } BlockState SmoothSandstoneStairs(); eBlockFace Facing(BlockState Block); enum Half Half(BlockState Block); enum Shape Shape(BlockState Block); } namespace SmoothStone { constexpr BlockState SmoothStone() { return 8414; } } namespace SmoothStoneSlab { enum class Type { Top, Bottom, Double }; constexpr BlockState SmoothStoneSlab(const enum Type Type) { if (Type == Type::Top) return 8343; else if (Type == Type::Bottom) return 8345; else return 8347; } BlockState SmoothStoneSlab(); enum Type Type(BlockState Block); } namespace Snow { constexpr BlockState Snow(const unsigned char Layers) { if (Layers == 1) return 3921; else if (Layers == 2) return 3922; else if (Layers == 3) return 3923; else if (Layers == 4) return 3924; else if (Layers == 5) return 3925; else if (Layers == 6) return 3926; else if (Layers == 7) return 3927; else return 3928; } BlockState Snow(); unsigned char Layers(BlockState Block); } namespace SnowBlock { constexpr BlockState SnowBlock() { return 3930; } } namespace SoulCampfire { constexpr BlockState SoulCampfire(const eBlockFace Facing, const bool Lit, const bool SignalFire) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Lit) if (SignalFire) return 14923; else return 14925; else if (SignalFire) return 14927; else return 14929; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Lit) if (SignalFire) return 14931; else return 14933; else if (SignalFire) return 14935; else return 14937; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Lit) if (SignalFire) return 14939; else return 14941; else if (SignalFire) return 14943; else return 14945; else if (Lit) if (SignalFire) return 14947; else return 14949; else if (SignalFire) return 14951; else return 14953; } BlockState SoulCampfire(); eBlockFace Facing(BlockState Block); bool Lit(BlockState Block); bool SignalFire(BlockState Block); } namespace SoulFire { constexpr BlockState SoulFire() { return 1952; } } namespace SoulLantern { constexpr BlockState SoulLantern(const bool Hanging) { if (Hanging) return 14888; else return 14889; } BlockState SoulLantern(); bool Hanging(BlockState Block); } namespace SoulSand { constexpr BlockState SoulSand() { return 4000; } } namespace SoulSoil { constexpr BlockState SoulSoil() { return 4001; } } namespace SoulTorch { constexpr BlockState SoulTorch() { return 4008; } } namespace SoulWallTorch { constexpr BlockState SoulWallTorch(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 4009; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 4010; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 4011; else return 4012; } BlockState SoulWallTorch(); eBlockFace Facing(BlockState Block); } namespace Spawner { constexpr BlockState Spawner() { return 1953; } } namespace Sponge { constexpr BlockState Sponge() { return 229; } } namespace SpruceButton { enum class Face { Floor, Wall, Ceiling }; constexpr BlockState SpruceButton(const enum Face Face, const eBlockFace Facing, const bool Powered) { if (Face == Face::Floor) if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Powered) return 6370; else return 6371; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Powered) return 6372; else return 6373; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Powered) return 6374; else return 6375; else if (Powered) return 6376; else return 6377; else if (Face == Face::Wall) if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Powered) return 6378; else return 6379; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Powered) return 6380; else return 6381; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Powered) return 6382; else return 6383; else if (Powered) return 6384; else return 6385; else if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Powered) return 6386; else return 6387; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Powered) return 6388; else return 6389; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Powered) return 6390; else return 6391; else if (Powered) return 6392; else return 6393; } BlockState SpruceButton(); enum Face Face(BlockState Block); eBlockFace Facing(BlockState Block); bool Powered(BlockState Block); } namespace SpruceDoor { enum class Half { Upper, Lower }; enum class Hinge { Left, Right }; constexpr BlockState SpruceDoor(const eBlockFace Facing, const enum Half Half, const enum Hinge Hinge, const bool Open, const bool Powered) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Half == Half::Upper) if (Hinge == Hinge::Left) if (Open) if (Powered) return 8738; else return 8739; else if (Powered) return 8740; else return 8741; else if (Open) if (Powered) return 8742; else return 8743; else if (Powered) return 8744; else return 8745; else if (Hinge == Hinge::Left) if (Open) if (Powered) return 8746; else return 8747; else if (Powered) return 8748; else return 8749; else if (Open) if (Powered) return 8750; else return 8751; else if (Powered) return 8752; else return 8753; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Half == Half::Upper) if (Hinge == Hinge::Left) if (Open) if (Powered) return 8754; else return 8755; else if (Powered) return 8756; else return 8757; else if (Open) if (Powered) return 8758; else return 8759; else if (Powered) return 8760; else return 8761; else if (Hinge == Hinge::Left) if (Open) if (Powered) return 8762; else return 8763; else if (Powered) return 8764; else return 8765; else if (Open) if (Powered) return 8766; else return 8767; else if (Powered) return 8768; else return 8769; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Half == Half::Upper) if (Hinge == Hinge::Left) if (Open) if (Powered) return 8770; else return 8771; else if (Powered) return 8772; else return 8773; else if (Open) if (Powered) return 8774; else return 8775; else if (Powered) return 8776; else return 8777; else if (Hinge == Hinge::Left) if (Open) if (Powered) return 8778; else return 8779; else if (Powered) return 8780; else return 8781; else if (Open) if (Powered) return 8782; else return 8783; else if (Powered) return 8784; else return 8785; else if (Half == Half::Upper) if (Hinge == Hinge::Left) if (Open) if (Powered) return 8786; else return 8787; else if (Powered) return 8788; else return 8789; else if (Open) if (Powered) return 8790; else return 8791; else if (Powered) return 8792; else return 8793; else if (Hinge == Hinge::Left) if (Open) if (Powered) return 8794; else return 8795; else if (Powered) return 8796; else return 8797; else if (Open) if (Powered) return 8798; else return 8799; else if (Powered) return 8800; else return 8801; } BlockState SpruceDoor(); eBlockFace Facing(BlockState Block); enum Half Half(BlockState Block); enum Hinge Hinge(BlockState Block); bool Open(BlockState Block); bool Powered(BlockState Block); } namespace SpruceFence { constexpr BlockState SpruceFence(const bool East, const bool North, const bool South, const bool West) { if (East) if (North) if (South) if (West) return 8580; else return 8581; else if (West) return 8584; else return 8585; else if (South) if (West) return 8588; else return 8589; else if (West) return 8592; else return 8593; else if (North) if (South) if (West) return 8596; else return 8597; else if (West) return 8600; else return 8601; else if (South) if (West) return 8604; else return 8605; else if (West) return 8608; else return 8609; } BlockState SpruceFence(); bool East(BlockState Block); bool North(BlockState Block); bool South(BlockState Block); bool West(BlockState Block); } namespace SpruceFenceGate { constexpr BlockState SpruceFenceGate(const eBlockFace Facing, const bool InWall, const bool Open, const bool Powered) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (InWall) if (Open) if (Powered) return 8418; else return 8419; else if (Powered) return 8420; else return 8421; else if (Open) if (Powered) return 8422; else return 8423; else if (Powered) return 8424; else return 8425; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (InWall) if (Open) if (Powered) return 8426; else return 8427; else if (Powered) return 8428; else return 8429; else if (Open) if (Powered) return 8430; else return 8431; else if (Powered) return 8432; else return 8433; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (InWall) if (Open) if (Powered) return 8434; else return 8435; else if (Powered) return 8436; else return 8437; else if (Open) if (Powered) return 8438; else return 8439; else if (Powered) return 8440; else return 8441; else if (InWall) if (Open) if (Powered) return 8442; else return 8443; else if (Powered) return 8444; else return 8445; else if (Open) if (Powered) return 8446; else return 8447; else if (Powered) return 8448; else return 8449; } BlockState SpruceFenceGate(); eBlockFace Facing(BlockState Block); bool InWall(BlockState Block); bool Open(BlockState Block); bool Powered(BlockState Block); } namespace SpruceLeaves { constexpr BlockState SpruceLeaves(const unsigned char Distance, const bool Persistent) { if (Distance == 1) if (Persistent) return 159; else return 160; else if (Distance == 2) if (Persistent) return 161; else return 162; else if (Distance == 3) if (Persistent) return 163; else return 164; else if (Distance == 4) if (Persistent) return 165; else return 166; else if (Distance == 5) if (Persistent) return 167; else return 168; else if (Distance == 6) if (Persistent) return 169; else return 170; else if (Persistent) return 171; else return 172; } BlockState SpruceLeaves(); unsigned char Distance(BlockState Block); bool Persistent(BlockState Block); } namespace SpruceLog { enum class Axis { X, Y, Z }; constexpr BlockState SpruceLog(const enum Axis Axis) { if (Axis == Axis::X) return 76; else if (Axis == Axis::Y) return 77; else return 78; } BlockState SpruceLog(); enum Axis Axis(BlockState Block); } namespace SprucePlanks { constexpr BlockState SprucePlanks() { return 16; } } namespace SprucePressurePlate { constexpr BlockState SprucePressurePlate(const bool Powered) { if (Powered) return 3875; else return 3876; } BlockState SprucePressurePlate(); bool Powered(BlockState Block); } namespace SpruceSapling { constexpr BlockState SpruceSapling(const unsigned char Stage) { if (Stage == 0) return 23; else return 24; } BlockState SpruceSapling(); unsigned char Stage(BlockState Block); } namespace SpruceSign { constexpr BlockState SpruceSign(const unsigned char Rotation) { if (Rotation == 0) return 3414; else if (Rotation == 1) return 3416; else if (Rotation == 2) return 3418; else if (Rotation == 3) return 3420; else if (Rotation == 4) return 3422; else if (Rotation == 5) return 3424; else if (Rotation == 6) return 3426; else if (Rotation == 7) return 3428; else if (Rotation == 8) return 3430; else if (Rotation == 9) return 3432; else if (Rotation == 10) return 3434; else if (Rotation == 11) return 3436; else if (Rotation == 12) return 3438; else if (Rotation == 13) return 3440; else if (Rotation == 14) return 3442; else return 3444; } BlockState SpruceSign(); unsigned char Rotation(BlockState Block); } namespace SpruceSlab { enum class Type { Top, Bottom, Double }; constexpr BlockState SpruceSlab(const enum Type Type) { if (Type == Type::Top) return 8307; else if (Type == Type::Bottom) return 8309; else return 8311; } BlockState SpruceSlab(); enum Type Type(BlockState Block); } namespace SpruceStairs { enum class Half { Top, Bottom }; enum class Shape { Straight, InnerLeft, InnerRight, OuterLeft, OuterRight }; constexpr BlockState SpruceStairs(const eBlockFace Facing, const enum Half Half, const enum Shape Shape) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Half == Half::Top) if (Shape == Shape::Straight) return 5405; else if (Shape == Shape::InnerLeft) return 5407; else if (Shape == Shape::InnerRight) return 5409; else if (Shape == Shape::OuterLeft) return 5411; else return 5413; else if (Shape == Shape::Straight) return 5415; else if (Shape == Shape::InnerLeft) return 5417; else if (Shape == Shape::InnerRight) return 5419; else if (Shape == Shape::OuterLeft) return 5421; else return 5423; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Half == Half::Top) if (Shape == Shape::Straight) return 5425; else if (Shape == Shape::InnerLeft) return 5427; else if (Shape == Shape::InnerRight) return 5429; else if (Shape == Shape::OuterLeft) return 5431; else return 5433; else if (Shape == Shape::Straight) return 5435; else if (Shape == Shape::InnerLeft) return 5437; else if (Shape == Shape::InnerRight) return 5439; else if (Shape == Shape::OuterLeft) return 5441; else return 5443; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Half == Half::Top) if (Shape == Shape::Straight) return 5445; else if (Shape == Shape::InnerLeft) return 5447; else if (Shape == Shape::InnerRight) return 5449; else if (Shape == Shape::OuterLeft) return 5451; else return 5453; else if (Shape == Shape::Straight) return 5455; else if (Shape == Shape::InnerLeft) return 5457; else if (Shape == Shape::InnerRight) return 5459; else if (Shape == Shape::OuterLeft) return 5461; else return 5463; else if (Half == Half::Top) if (Shape == Shape::Straight) return 5465; else if (Shape == Shape::InnerLeft) return 5467; else if (Shape == Shape::InnerRight) return 5469; else if (Shape == Shape::OuterLeft) return 5471; else return 5473; else if (Shape == Shape::Straight) return 5475; else if (Shape == Shape::InnerLeft) return 5477; else if (Shape == Shape::InnerRight) return 5479; else if (Shape == Shape::OuterLeft) return 5481; else return 5483; } BlockState SpruceStairs(); eBlockFace Facing(BlockState Block); enum Half Half(BlockState Block); enum Shape Shape(BlockState Block); } namespace SpruceTrapdoor { enum class Half { Top, Bottom }; constexpr BlockState SpruceTrapdoor(const eBlockFace Facing, const enum Half Half, const bool Open, const bool Powered) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Half == Half::Top) if (Open) if (Powered) return 4176; else return 4178; else if (Powered) return 4180; else return 4182; else if (Open) if (Powered) return 4184; else return 4186; else if (Powered) return 4188; else return 4190; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Half == Half::Top) if (Open) if (Powered) return 4192; else return 4194; else if (Powered) return 4196; else return 4198; else if (Open) if (Powered) return 4200; else return 4202; else if (Powered) return 4204; else return 4206; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Half == Half::Top) if (Open) if (Powered) return 4208; else return 4210; else if (Powered) return 4212; else return 4214; else if (Open) if (Powered) return 4216; else return 4218; else if (Powered) return 4220; else return 4222; else if (Half == Half::Top) if (Open) if (Powered) return 4224; else return 4226; else if (Powered) return 4228; else return 4230; else if (Open) if (Powered) return 4232; else return 4234; else if (Powered) return 4236; else return 4238; } BlockState SpruceTrapdoor(); eBlockFace Facing(BlockState Block); enum Half Half(BlockState Block); bool Open(BlockState Block); bool Powered(BlockState Block); } namespace SpruceWallSign { constexpr BlockState SpruceWallSign(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 3744; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 3746; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 3748; else return 3750; } BlockState SpruceWallSign(); eBlockFace Facing(BlockState Block); } namespace SpruceWood { enum class Axis { X, Y, Z }; constexpr BlockState SpruceWood(const enum Axis Axis) { if (Axis == Axis::X) return 112; else if (Axis == Axis::Y) return 113; else return 114; } BlockState SpruceWood(); enum Axis Axis(BlockState Block); } namespace StickyPiston { constexpr BlockState StickyPiston(const bool Extended, const eBlockFace Facing) { if (Extended) if (Facing == eBlockFace::BLOCK_FACE_ZM) return 1329; else if (Facing == eBlockFace::BLOCK_FACE_XP) return 1330; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 1331; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 1332; else if (Facing == eBlockFace::BLOCK_FACE_YP) return 1333; else return 1334; else if (Facing == eBlockFace::BLOCK_FACE_ZM) return 1335; else if (Facing == eBlockFace::BLOCK_FACE_XP) return 1336; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 1337; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 1338; else if (Facing == eBlockFace::BLOCK_FACE_YP) return 1339; else return 1340; } BlockState StickyPiston(); bool Extended(BlockState Block); eBlockFace Facing(BlockState Block); } namespace Stone { constexpr BlockState Stone() { return 1; } } namespace StoneBrickSlab { enum class Type { Top, Bottom, Double }; constexpr BlockState StoneBrickSlab(const enum Type Type) { if (Type == Type::Top) return 8379; else if (Type == Type::Bottom) return 8381; else return 8383; } BlockState StoneBrickSlab(); enum Type Type(BlockState Block); } namespace StoneBrickStairs { enum class Half { Top, Bottom }; enum class Shape { Straight, InnerLeft, InnerRight, OuterLeft, OuterRight }; constexpr BlockState StoneBrickStairs(const eBlockFace Facing, const enum Half Half, const enum Shape Shape) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Half == Half::Top) if (Shape == Shape::Straight) return 4933; else if (Shape == Shape::InnerLeft) return 4935; else if (Shape == Shape::InnerRight) return 4937; else if (Shape == Shape::OuterLeft) return 4939; else return 4941; else if (Shape == Shape::Straight) return 4943; else if (Shape == Shape::InnerLeft) return 4945; else if (Shape == Shape::InnerRight) return 4947; else if (Shape == Shape::OuterLeft) return 4949; else return 4951; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Half == Half::Top) if (Shape == Shape::Straight) return 4953; else if (Shape == Shape::InnerLeft) return 4955; else if (Shape == Shape::InnerRight) return 4957; else if (Shape == Shape::OuterLeft) return 4959; else return 4961; else if (Shape == Shape::Straight) return 4963; else if (Shape == Shape::InnerLeft) return 4965; else if (Shape == Shape::InnerRight) return 4967; else if (Shape == Shape::OuterLeft) return 4969; else return 4971; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Half == Half::Top) if (Shape == Shape::Straight) return 4973; else if (Shape == Shape::InnerLeft) return 4975; else if (Shape == Shape::InnerRight) return 4977; else if (Shape == Shape::OuterLeft) return 4979; else return 4981; else if (Shape == Shape::Straight) return 4983; else if (Shape == Shape::InnerLeft) return 4985; else if (Shape == Shape::InnerRight) return 4987; else if (Shape == Shape::OuterLeft) return 4989; else return 4991; else if (Half == Half::Top) if (Shape == Shape::Straight) return 4993; else if (Shape == Shape::InnerLeft) return 4995; else if (Shape == Shape::InnerRight) return 4997; else if (Shape == Shape::OuterLeft) return 4999; else return 5001; else if (Shape == Shape::Straight) return 5003; else if (Shape == Shape::InnerLeft) return 5005; else if (Shape == Shape::InnerRight) return 5007; else if (Shape == Shape::OuterLeft) return 5009; else return 5011; } BlockState StoneBrickStairs(); eBlockFace Facing(BlockState Block); enum Half Half(BlockState Block); enum Shape Shape(BlockState Block); } namespace StoneBrickWall { enum class East { None, Low, Tall }; enum class North { None, Low, Tall }; enum class South { None, Low, Tall }; enum class West { None, Low, Tall }; constexpr BlockState StoneBrickWall(const enum East East, const enum North North, const enum South South, const bool Up, const enum West West) { if (East == East::None) if (North == North::None) if (South == South::None) if (Up) if (West == West::None) return 12490; else if (West == West::Low) return 12491; else return 12492; else if (West == West::None) return 12496; else if (West == West::Low) return 12497; else return 12498; else if (South == South::Low) if (Up) if (West == West::None) return 12502; else if (West == West::Low) return 12503; else return 12504; else if (West == West::None) return 12508; else if (West == West::Low) return 12509; else return 12510; else if (Up) if (West == West::None) return 12514; else if (West == West::Low) return 12515; else return 12516; else if (West == West::None) return 12520; else if (West == West::Low) return 12521; else return 12522; else if (North == North::Low) if (South == South::None) if (Up) if (West == West::None) return 12526; else if (West == West::Low) return 12527; else return 12528; else if (West == West::None) return 12532; else if (West == West::Low) return 12533; else return 12534; else if (South == South::Low) if (Up) if (West == West::None) return 12538; else if (West == West::Low) return 12539; else return 12540; else if (West == West::None) return 12544; else if (West == West::Low) return 12545; else return 12546; else if (Up) if (West == West::None) return 12550; else if (West == West::Low) return 12551; else return 12552; else if (West == West::None) return 12556; else if (West == West::Low) return 12557; else return 12558; else if (South == South::None) if (Up) if (West == West::None) return 12562; else if (West == West::Low) return 12563; else return 12564; else if (West == West::None) return 12568; else if (West == West::Low) return 12569; else return 12570; else if (South == South::Low) if (Up) if (West == West::None) return 12574; else if (West == West::Low) return 12575; else return 12576; else if (West == West::None) return 12580; else if (West == West::Low) return 12581; else return 12582; else if (Up) if (West == West::None) return 12586; else if (West == West::Low) return 12587; else return 12588; else if (West == West::None) return 12592; else if (West == West::Low) return 12593; else return 12594; else if (East == East::Low) if (North == North::None) if (South == South::None) if (Up) if (West == West::None) return 12598; else if (West == West::Low) return 12599; else return 12600; else if (West == West::None) return 12604; else if (West == West::Low) return 12605; else return 12606; else if (South == South::Low) if (Up) if (West == West::None) return 12610; else if (West == West::Low) return 12611; else return 12612; else if (West == West::None) return 12616; else if (West == West::Low) return 12617; else return 12618; else if (Up) if (West == West::None) return 12622; else if (West == West::Low) return 12623; else return 12624; else if (West == West::None) return 12628; else if (West == West::Low) return 12629; else return 12630; else if (North == North::Low) if (South == South::None) if (Up) if (West == West::None) return 12634; else if (West == West::Low) return 12635; else return 12636; else if (West == West::None) return 12640; else if (West == West::Low) return 12641; else return 12642; else if (South == South::Low) if (Up) if (West == West::None) return 12646; else if (West == West::Low) return 12647; else return 12648; else if (West == West::None) return 12652; else if (West == West::Low) return 12653; else return 12654; else if (Up) if (West == West::None) return 12658; else if (West == West::Low) return 12659; else return 12660; else if (West == West::None) return 12664; else if (West == West::Low) return 12665; else return 12666; else if (South == South::None) if (Up) if (West == West::None) return 12670; else if (West == West::Low) return 12671; else return 12672; else if (West == West::None) return 12676; else if (West == West::Low) return 12677; else return 12678; else if (South == South::Low) if (Up) if (West == West::None) return 12682; else if (West == West::Low) return 12683; else return 12684; else if (West == West::None) return 12688; else if (West == West::Low) return 12689; else return 12690; else if (Up) if (West == West::None) return 12694; else if (West == West::Low) return 12695; else return 12696; else if (West == West::None) return 12700; else if (West == West::Low) return 12701; else return 12702; else if (North == North::None) if (South == South::None) if (Up) if (West == West::None) return 12706; else if (West == West::Low) return 12707; else return 12708; else if (West == West::None) return 12712; else if (West == West::Low) return 12713; else return 12714; else if (South == South::Low) if (Up) if (West == West::None) return 12718; else if (West == West::Low) return 12719; else return 12720; else if (West == West::None) return 12724; else if (West == West::Low) return 12725; else return 12726; else if (Up) if (West == West::None) return 12730; else if (West == West::Low) return 12731; else return 12732; else if (West == West::None) return 12736; else if (West == West::Low) return 12737; else return 12738; else if (North == North::Low) if (South == South::None) if (Up) if (West == West::None) return 12742; else if (West == West::Low) return 12743; else return 12744; else if (West == West::None) return 12748; else if (West == West::Low) return 12749; else return 12750; else if (South == South::Low) if (Up) if (West == West::None) return 12754; else if (West == West::Low) return 12755; else return 12756; else if (West == West::None) return 12760; else if (West == West::Low) return 12761; else return 12762; else if (Up) if (West == West::None) return 12766; else if (West == West::Low) return 12767; else return 12768; else if (West == West::None) return 12772; else if (West == West::Low) return 12773; else return 12774; else if (South == South::None) if (Up) if (West == West::None) return 12778; else if (West == West::Low) return 12779; else return 12780; else if (West == West::None) return 12784; else if (West == West::Low) return 12785; else return 12786; else if (South == South::Low) if (Up) if (West == West::None) return 12790; else if (West == West::Low) return 12791; else return 12792; else if (West == West::None) return 12796; else if (West == West::Low) return 12797; else return 12798; else if (Up) if (West == West::None) return 12802; else if (West == West::Low) return 12803; else return 12804; else if (West == West::None) return 12808; else if (West == West::Low) return 12809; else return 12810; } BlockState StoneBrickWall(); enum East East(BlockState Block); enum North North(BlockState Block); enum South South(BlockState Block); bool Up(BlockState Block); enum West West(BlockState Block); } namespace StoneBricks { constexpr BlockState StoneBricks() { return 4495; } } namespace StoneButton { enum class Face { Floor, Wall, Ceiling }; constexpr BlockState StoneButton(const enum Face Face, const eBlockFace Facing, const bool Powered) { if (Face == Face::Floor) if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Powered) return 3897; else return 3898; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Powered) return 3899; else return 3900; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Powered) return 3901; else return 3902; else if (Powered) return 3903; else return 3904; else if (Face == Face::Wall) if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Powered) return 3905; else return 3906; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Powered) return 3907; else return 3908; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Powered) return 3909; else return 3910; else if (Powered) return 3911; else return 3912; else if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Powered) return 3913; else return 3914; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Powered) return 3915; else return 3916; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Powered) return 3917; else return 3918; else if (Powered) return 3919; else return 3920; } BlockState StoneButton(); enum Face Face(BlockState Block); eBlockFace Facing(BlockState Block); bool Powered(BlockState Block); } namespace StonePressurePlate { constexpr BlockState StonePressurePlate(const bool Powered) { if (Powered) return 3807; else return 3808; } BlockState StonePressurePlate(); bool Powered(BlockState Block); } namespace StoneSlab { enum class Type { Top, Bottom, Double }; constexpr BlockState StoneSlab(const enum Type Type) { if (Type == Type::Top) return 8337; else if (Type == Type::Bottom) return 8339; else return 8341; } BlockState StoneSlab(); enum Type Type(BlockState Block); } namespace StoneStairs { enum class Half { Top, Bottom }; enum class Shape { Straight, InnerLeft, InnerRight, OuterLeft, OuterRight }; constexpr BlockState StoneStairs(const eBlockFace Facing, const enum Half Half, const enum Shape Shape) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Half == Half::Top) if (Shape == Shape::Straight) return 10150; else if (Shape == Shape::InnerLeft) return 10152; else if (Shape == Shape::InnerRight) return 10154; else if (Shape == Shape::OuterLeft) return 10156; else return 10158; else if (Shape == Shape::Straight) return 10160; else if (Shape == Shape::InnerLeft) return 10162; else if (Shape == Shape::InnerRight) return 10164; else if (Shape == Shape::OuterLeft) return 10166; else return 10168; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Half == Half::Top) if (Shape == Shape::Straight) return 10170; else if (Shape == Shape::InnerLeft) return 10172; else if (Shape == Shape::InnerRight) return 10174; else if (Shape == Shape::OuterLeft) return 10176; else return 10178; else if (Shape == Shape::Straight) return 10180; else if (Shape == Shape::InnerLeft) return 10182; else if (Shape == Shape::InnerRight) return 10184; else if (Shape == Shape::OuterLeft) return 10186; else return 10188; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Half == Half::Top) if (Shape == Shape::Straight) return 10190; else if (Shape == Shape::InnerLeft) return 10192; else if (Shape == Shape::InnerRight) return 10194; else if (Shape == Shape::OuterLeft) return 10196; else return 10198; else if (Shape == Shape::Straight) return 10200; else if (Shape == Shape::InnerLeft) return 10202; else if (Shape == Shape::InnerRight) return 10204; else if (Shape == Shape::OuterLeft) return 10206; else return 10208; else if (Half == Half::Top) if (Shape == Shape::Straight) return 10210; else if (Shape == Shape::InnerLeft) return 10212; else if (Shape == Shape::InnerRight) return 10214; else if (Shape == Shape::OuterLeft) return 10216; else return 10218; else if (Shape == Shape::Straight) return 10220; else if (Shape == Shape::InnerLeft) return 10222; else if (Shape == Shape::InnerRight) return 10224; else if (Shape == Shape::OuterLeft) return 10226; else return 10228; } BlockState StoneStairs(); eBlockFace Facing(BlockState Block); enum Half Half(BlockState Block); enum Shape Shape(BlockState Block); } namespace Stonecutter { constexpr BlockState Stonecutter(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 14850; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 14851; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 14852; else return 14853; } BlockState Stonecutter(); eBlockFace Facing(BlockState Block); } namespace StrippedAcaciaLog { enum class Axis { X, Y, Z }; constexpr BlockState StrippedAcaciaLog(const enum Axis Axis) { if (Axis == Axis::X) return 100; else if (Axis == Axis::Y) return 101; else return 102; } BlockState StrippedAcaciaLog(); enum Axis Axis(BlockState Block); } namespace StrippedAcaciaWood { enum class Axis { X, Y, Z }; constexpr BlockState StrippedAcaciaWood(const enum Axis Axis) { if (Axis == Axis::X) return 139; else if (Axis == Axis::Y) return 140; else return 141; } BlockState StrippedAcaciaWood(); enum Axis Axis(BlockState Block); } namespace StrippedBirchLog { enum class Axis { X, Y, Z }; constexpr BlockState StrippedBirchLog(const enum Axis Axis) { if (Axis == Axis::X) return 94; else if (Axis == Axis::Y) return 95; else return 96; } BlockState StrippedBirchLog(); enum Axis Axis(BlockState Block); } namespace StrippedBirchWood { enum class Axis { X, Y, Z }; constexpr BlockState StrippedBirchWood(const enum Axis Axis) { if (Axis == Axis::X) return 133; else if (Axis == Axis::Y) return 134; else return 135; } BlockState StrippedBirchWood(); enum Axis Axis(BlockState Block); } namespace StrippedCrimsonHyphae { enum class Axis { X, Y, Z }; constexpr BlockState StrippedCrimsonHyphae(const enum Axis Axis) { if (Axis == Axis::X) return 14984; else if (Axis == Axis::Y) return 14985; else return 14986; } BlockState StrippedCrimsonHyphae(); enum Axis Axis(BlockState Block); } namespace StrippedCrimsonStem { enum class Axis { X, Y, Z }; constexpr BlockState StrippedCrimsonStem(const enum Axis Axis) { if (Axis == Axis::X) return 14978; else if (Axis == Axis::Y) return 14979; else return 14980; } BlockState StrippedCrimsonStem(); enum Axis Axis(BlockState Block); } namespace StrippedDarkOakLog { enum class Axis { X, Y, Z }; constexpr BlockState StrippedDarkOakLog(const enum Axis Axis) { if (Axis == Axis::X) return 103; else if (Axis == Axis::Y) return 104; else return 105; } BlockState StrippedDarkOakLog(); enum Axis Axis(BlockState Block); } namespace StrippedDarkOakWood { enum class Axis { X, Y, Z }; constexpr BlockState StrippedDarkOakWood(const enum Axis Axis) { if (Axis == Axis::X) return 142; else if (Axis == Axis::Y) return 143; else return 144; } BlockState StrippedDarkOakWood(); enum Axis Axis(BlockState Block); } namespace StrippedJungleLog { enum class Axis { X, Y, Z }; constexpr BlockState StrippedJungleLog(const enum Axis Axis) { if (Axis == Axis::X) return 97; else if (Axis == Axis::Y) return 98; else return 99; } BlockState StrippedJungleLog(); enum Axis Axis(BlockState Block); } namespace StrippedJungleWood { enum class Axis { X, Y, Z }; constexpr BlockState StrippedJungleWood(const enum Axis Axis) { if (Axis == Axis::X) return 136; else if (Axis == Axis::Y) return 137; else return 138; } BlockState StrippedJungleWood(); enum Axis Axis(BlockState Block); } namespace StrippedOakLog { enum class Axis { X, Y, Z }; constexpr BlockState StrippedOakLog(const enum Axis Axis) { if (Axis == Axis::X) return 106; else if (Axis == Axis::Y) return 107; else return 108; } BlockState StrippedOakLog(); enum Axis Axis(BlockState Block); } namespace StrippedOakWood { enum class Axis { X, Y, Z }; constexpr BlockState StrippedOakWood(const enum Axis Axis) { if (Axis == Axis::X) return 127; else if (Axis == Axis::Y) return 128; else return 129; } BlockState StrippedOakWood(); enum Axis Axis(BlockState Block); } namespace StrippedSpruceLog { enum class Axis { X, Y, Z }; constexpr BlockState StrippedSpruceLog(const enum Axis Axis) { if (Axis == Axis::X) return 91; else if (Axis == Axis::Y) return 92; else return 93; } BlockState StrippedSpruceLog(); enum Axis Axis(BlockState Block); } namespace StrippedSpruceWood { enum class Axis { X, Y, Z }; constexpr BlockState StrippedSpruceWood(const enum Axis Axis) { if (Axis == Axis::X) return 130; else if (Axis == Axis::Y) return 131; else return 132; } BlockState StrippedSpruceWood(); enum Axis Axis(BlockState Block); } namespace StrippedWarpedHyphae { enum class Axis { X, Y, Z }; constexpr BlockState StrippedWarpedHyphae(const enum Axis Axis) { if (Axis == Axis::X) return 14967; else if (Axis == Axis::Y) return 14968; else return 14969; } BlockState StrippedWarpedHyphae(); enum Axis Axis(BlockState Block); } namespace StrippedWarpedStem { enum class Axis { X, Y, Z }; constexpr BlockState StrippedWarpedStem(const enum Axis Axis) { if (Axis == Axis::X) return 14961; else if (Axis == Axis::Y) return 14962; else return 14963; } BlockState StrippedWarpedStem(); enum Axis Axis(BlockState Block); } namespace StructureBlock { enum class Mode { Save, Load, Corner, Data }; constexpr BlockState StructureBlock(const enum Mode Mode) { if (Mode == Mode::Save) return 15735; else if (Mode == Mode::Load) return 15736; else if (Mode == Mode::Corner) return 15737; else return 15738; } BlockState StructureBlock(); enum Mode Mode(BlockState Block); } namespace StructureVoid { constexpr BlockState StructureVoid() { return 9259; } } namespace SugarCane { constexpr BlockState SugarCane(const unsigned char Age) { if (Age == 0) return 3948; else if (Age == 1) return 3949; else if (Age == 2) return 3950; else if (Age == 3) return 3951; else if (Age == 4) return 3952; else if (Age == 5) return 3953; else if (Age == 6) return 3954; else if (Age == 7) return 3955; else if (Age == 8) return 3956; else if (Age == 9) return 3957; else if (Age == 10) return 3958; else if (Age == 11) return 3959; else if (Age == 12) return 3960; else if (Age == 13) return 3961; else if (Age == 14) return 3962; else return 3963; } BlockState SugarCane(); unsigned char Age(BlockState Block); } namespace Sunflower { enum class Half { Upper, Lower }; constexpr BlockState Sunflower(const enum Half Half) { if (Half == Half::Upper) return 7885; else return 7886; } BlockState Sunflower(); enum Half Half(BlockState Block); } namespace SweetBerryBush { constexpr BlockState SweetBerryBush(const unsigned char Age) { if (Age == 0) return 14954; else if (Age == 1) return 14955; else if (Age == 2) return 14956; else return 14957; } BlockState SweetBerryBush(); unsigned char Age(BlockState Block); } namespace TNT { constexpr BlockState TNT(const bool Unstable) { if (Unstable) return 1430; else return 1431; } BlockState TNT(); bool Unstable(BlockState Block); } namespace TallGrass { enum class Half { Upper, Lower }; constexpr BlockState TallGrass(const enum Half Half) { if (Half == Half::Upper) return 7893; else return 7894; } BlockState TallGrass(); enum Half Half(BlockState Block); } namespace TallSeagrass { enum class Half { Upper, Lower }; constexpr BlockState TallSeagrass(const enum Half Half) { if (Half == Half::Upper) return 1346; else return 1347; } BlockState TallSeagrass(); enum Half Half(BlockState Block); } namespace Target { constexpr BlockState Target(const unsigned char Power) { if (Power == 0) return 15760; else if (Power == 1) return 15761; else if (Power == 2) return 15762; else if (Power == 3) return 15763; else if (Power == 4) return 15764; else if (Power == 5) return 15765; else if (Power == 6) return 15766; else if (Power == 7) return 15767; else if (Power == 8) return 15768; else if (Power == 9) return 15769; else if (Power == 10) return 15770; else if (Power == 11) return 15771; else if (Power == 12) return 15772; else if (Power == 13) return 15773; else if (Power == 14) return 15774; else return 15775; } BlockState Target(); unsigned char Power(BlockState Block); } namespace Terracotta { constexpr BlockState Terracotta() { return 7882; } } namespace Torch { constexpr BlockState Torch() { return 1435; } } namespace TrappedChest { enum class Type { Single, Left, Right }; constexpr BlockState TrappedChest(const eBlockFace Facing, const enum Type Type) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Type == Type::Single) return 6623; else if (Type == Type::Left) return 6625; else return 6627; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Type == Type::Single) return 6629; else if (Type == Type::Left) return 6631; else return 6633; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Type == Type::Single) return 6635; else if (Type == Type::Left) return 6637; else return 6639; else if (Type == Type::Single) return 6641; else if (Type == Type::Left) return 6643; else return 6645; } BlockState TrappedChest(); eBlockFace Facing(BlockState Block); enum Type Type(BlockState Block); } namespace Tripwire { constexpr BlockState Tripwire(const bool Attached, const bool Disarmed, const bool East, const bool North, const bool Powered, const bool South, const bool West) { if (Attached) if (Disarmed) if (East) if (North) if (Powered) if (South) if (West) return 5275; else return 5276; else if (West) return 5277; else return 5278; else if (South) if (West) return 5279; else return 5280; else if (West) return 5281; else return 5282; else if (Powered) if (South) if (West) return 5283; else return 5284; else if (West) return 5285; else return 5286; else if (South) if (West) return 5287; else return 5288; else if (West) return 5289; else return 5290; else if (North) if (Powered) if (South) if (West) return 5291; else return 5292; else if (West) return 5293; else return 5294; else if (South) if (West) return 5295; else return 5296; else if (West) return 5297; else return 5298; else if (Powered) if (South) if (West) return 5299; else return 5300; else if (West) return 5301; else return 5302; else if (South) if (West) return 5303; else return 5304; else if (West) return 5305; else return 5306; else if (East) if (North) if (Powered) if (South) if (West) return 5307; else return 5308; else if (West) return 5309; else return 5310; else if (South) if (West) return 5311; else return 5312; else if (West) return 5313; else return 5314; else if (Powered) if (South) if (West) return 5315; else return 5316; else if (West) return 5317; else return 5318; else if (South) if (West) return 5319; else return 5320; else if (West) return 5321; else return 5322; else if (North) if (Powered) if (South) if (West) return 5323; else return 5324; else if (West) return 5325; else return 5326; else if (South) if (West) return 5327; else return 5328; else if (West) return 5329; else return 5330; else if (Powered) if (South) if (West) return 5331; else return 5332; else if (West) return 5333; else return 5334; else if (South) if (West) return 5335; else return 5336; else if (West) return 5337; else return 5338; else if (Disarmed) if (East) if (North) if (Powered) if (South) if (West) return 5339; else return 5340; else if (West) return 5341; else return 5342; else if (South) if (West) return 5343; else return 5344; else if (West) return 5345; else return 5346; else if (Powered) if (South) if (West) return 5347; else return 5348; else if (West) return 5349; else return 5350; else if (South) if (West) return 5351; else return 5352; else if (West) return 5353; else return 5354; else if (North) if (Powered) if (South) if (West) return 5355; else return 5356; else if (West) return 5357; else return 5358; else if (South) if (West) return 5359; else return 5360; else if (West) return 5361; else return 5362; else if (Powered) if (South) if (West) return 5363; else return 5364; else if (West) return 5365; else return 5366; else if (South) if (West) return 5367; else return 5368; else if (West) return 5369; else return 5370; else if (East) if (North) if (Powered) if (South) if (West) return 5371; else return 5372; else if (West) return 5373; else return 5374; else if (South) if (West) return 5375; else return 5376; else if (West) return 5377; else return 5378; else if (Powered) if (South) if (West) return 5379; else return 5380; else if (West) return 5381; else return 5382; else if (South) if (West) return 5383; else return 5384; else if (West) return 5385; else return 5386; else if (North) if (Powered) if (South) if (West) return 5387; else return 5388; else if (West) return 5389; else return 5390; else if (South) if (West) return 5391; else return 5392; else if (West) return 5393; else return 5394; else if (Powered) if (South) if (West) return 5395; else return 5396; else if (West) return 5397; else return 5398; else if (South) if (West) return 5399; else return 5400; else if (West) return 5401; else return 5402; } BlockState Tripwire(); bool Attached(BlockState Block); bool Disarmed(BlockState Block); bool East(BlockState Block); bool North(BlockState Block); bool Powered(BlockState Block); bool South(BlockState Block); bool West(BlockState Block); } namespace TripwireHook { constexpr BlockState TripwireHook(const bool Attached, const eBlockFace Facing, const bool Powered) { if (Attached) if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Powered) return 5259; else return 5260; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Powered) return 5261; else return 5262; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Powered) return 5263; else return 5264; else if (Powered) return 5265; else return 5266; else if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Powered) return 5267; else return 5268; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Powered) return 5269; else return 5270; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Powered) return 5271; else return 5272; else if (Powered) return 5273; else return 5274; } BlockState TripwireHook(); bool Attached(BlockState Block); eBlockFace Facing(BlockState Block); bool Powered(BlockState Block); } namespace TubeCoral { constexpr BlockState TubeCoral() { return 9531; } } namespace TubeCoralBlock { constexpr BlockState TubeCoralBlock() { return 9515; } } namespace TubeCoralFan { constexpr BlockState TubeCoralFan() { return 9551; } } namespace TubeCoralWallFan { constexpr BlockState TubeCoralWallFan(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 9601; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 9603; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 9605; else return 9607; } BlockState TubeCoralWallFan(); eBlockFace Facing(BlockState Block); } namespace TurtleEgg { constexpr BlockState TurtleEgg(const unsigned char Eggs, const unsigned char Hatch) { if (Eggs == 1) if (Hatch == 0) return 9498; else if (Hatch == 1) return 9499; else return 9500; else if (Eggs == 2) if (Hatch == 0) return 9501; else if (Hatch == 1) return 9502; else return 9503; else if (Eggs == 3) if (Hatch == 0) return 9504; else if (Hatch == 1) return 9505; else return 9506; else if (Hatch == 0) return 9507; else if (Hatch == 1) return 9508; else return 9509; } BlockState TurtleEgg(); unsigned char Eggs(BlockState Block); unsigned char Hatch(BlockState Block); } namespace TwistingVines { constexpr BlockState TwistingVines(const unsigned char Age) { if (Age == 0) return 15017; else if (Age == 1) return 15018; else if (Age == 2) return 15019; else if (Age == 3) return 15020; else if (Age == 4) return 15021; else if (Age == 5) return 15022; else if (Age == 6) return 15023; else if (Age == 7) return 15024; else if (Age == 8) return 15025; else if (Age == 9) return 15026; else if (Age == 10) return 15027; else if (Age == 11) return 15028; else if (Age == 12) return 15029; else if (Age == 13) return 15030; else if (Age == 14) return 15031; else if (Age == 15) return 15032; else if (Age == 16) return 15033; else if (Age == 17) return 15034; else if (Age == 18) return 15035; else if (Age == 19) return 15036; else if (Age == 20) return 15037; else if (Age == 21) return 15038; else if (Age == 22) return 15039; else if (Age == 23) return 15040; else if (Age == 24) return 15041; else return 15042; } BlockState TwistingVines(); unsigned char Age(BlockState Block); } namespace TwistingVinesPlant { constexpr BlockState TwistingVinesPlant() { return 15043; } } namespace Vine { constexpr BlockState Vine(const bool East, const bool North, const bool South, const bool Up, const bool West) { if (East) if (North) if (South) if (Up) if (West) return 4788; else return 4789; else if (West) return 4790; else return 4791; else if (Up) if (West) return 4792; else return 4793; else if (West) return 4794; else return 4795; else if (South) if (Up) if (West) return 4796; else return 4797; else if (West) return 4798; else return 4799; else if (Up) if (West) return 4800; else return 4801; else if (West) return 4802; else return 4803; else if (North) if (South) if (Up) if (West) return 4804; else return 4805; else if (West) return 4806; else return 4807; else if (Up) if (West) return 4808; else return 4809; else if (West) return 4810; else return 4811; else if (South) if (Up) if (West) return 4812; else return 4813; else if (West) return 4814; else return 4815; else if (Up) if (West) return 4816; else return 4817; else if (West) return 4818; else return 4819; } BlockState Vine(); bool East(BlockState Block); bool North(BlockState Block); bool South(BlockState Block); bool Up(BlockState Block); bool West(BlockState Block); } namespace VoidAir { constexpr BlockState VoidAir() { return 9665; } } namespace WallTorch { constexpr BlockState WallTorch(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 1436; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 1437; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 1438; else return 1439; } BlockState WallTorch(); eBlockFace Facing(BlockState Block); } namespace WarpedButton { enum class Face { Floor, Wall, Ceiling }; constexpr BlockState WarpedButton(const enum Face Face, const eBlockFace Facing, const bool Powered) { if (Face == Face::Floor) if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Powered) return 15503; else return 15504; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Powered) return 15505; else return 15506; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Powered) return 15507; else return 15508; else if (Powered) return 15509; else return 15510; else if (Face == Face::Wall) if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Powered) return 15511; else return 15512; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Powered) return 15513; else return 15514; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Powered) return 15515; else return 15516; else if (Powered) return 15517; else return 15518; else if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Powered) return 15519; else return 15520; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Powered) return 15521; else return 15522; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Powered) return 15523; else return 15524; else if (Powered) return 15525; else return 15526; } BlockState WarpedButton(); enum Face Face(BlockState Block); eBlockFace Facing(BlockState Block); bool Powered(BlockState Block); } namespace WarpedDoor { enum class Half { Upper, Lower }; enum class Hinge { Left, Right }; constexpr BlockState WarpedDoor(const eBlockFace Facing, const enum Half Half, const enum Hinge Hinge, const bool Open, const bool Powered) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Half == Half::Upper) if (Hinge == Hinge::Left) if (Open) if (Powered) return 15591; else return 15592; else if (Powered) return 15593; else return 15594; else if (Open) if (Powered) return 15595; else return 15596; else if (Powered) return 15597; else return 15598; else if (Hinge == Hinge::Left) if (Open) if (Powered) return 15599; else return 15600; else if (Powered) return 15601; else return 15602; else if (Open) if (Powered) return 15603; else return 15604; else if (Powered) return 15605; else return 15606; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Half == Half::Upper) if (Hinge == Hinge::Left) if (Open) if (Powered) return 15607; else return 15608; else if (Powered) return 15609; else return 15610; else if (Open) if (Powered) return 15611; else return 15612; else if (Powered) return 15613; else return 15614; else if (Hinge == Hinge::Left) if (Open) if (Powered) return 15615; else return 15616; else if (Powered) return 15617; else return 15618; else if (Open) if (Powered) return 15619; else return 15620; else if (Powered) return 15621; else return 15622; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Half == Half::Upper) if (Hinge == Hinge::Left) if (Open) if (Powered) return 15623; else return 15624; else if (Powered) return 15625; else return 15626; else if (Open) if (Powered) return 15627; else return 15628; else if (Powered) return 15629; else return 15630; else if (Hinge == Hinge::Left) if (Open) if (Powered) return 15631; else return 15632; else if (Powered) return 15633; else return 15634; else if (Open) if (Powered) return 15635; else return 15636; else if (Powered) return 15637; else return 15638; else if (Half == Half::Upper) if (Hinge == Hinge::Left) if (Open) if (Powered) return 15639; else return 15640; else if (Powered) return 15641; else return 15642; else if (Open) if (Powered) return 15643; else return 15644; else if (Powered) return 15645; else return 15646; else if (Hinge == Hinge::Left) if (Open) if (Powered) return 15647; else return 15648; else if (Powered) return 15649; else return 15650; else if (Open) if (Powered) return 15651; else return 15652; else if (Powered) return 15653; else return 15654; } BlockState WarpedDoor(); eBlockFace Facing(BlockState Block); enum Half Half(BlockState Block); enum Hinge Hinge(BlockState Block); bool Open(BlockState Block); bool Powered(BlockState Block); } namespace WarpedFence { constexpr BlockState WarpedFence(const bool East, const bool North, const bool South, const bool West) { if (East) if (North) if (South) if (West) return 15097; else return 15098; else if (West) return 15101; else return 15102; else if (South) if (West) return 15105; else return 15106; else if (West) return 15109; else return 15110; else if (North) if (South) if (West) return 15113; else return 15114; else if (West) return 15117; else return 15118; else if (South) if (West) return 15121; else return 15122; else if (West) return 15125; else return 15126; } BlockState WarpedFence(); bool East(BlockState Block); bool North(BlockState Block); bool South(BlockState Block); bool West(BlockState Block); } namespace WarpedFenceGate { constexpr BlockState WarpedFenceGate(const eBlockFace Facing, const bool InWall, const bool Open, const bool Powered) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (InWall) if (Open) if (Powered) return 15287; else return 15288; else if (Powered) return 15289; else return 15290; else if (Open) if (Powered) return 15291; else return 15292; else if (Powered) return 15293; else return 15294; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (InWall) if (Open) if (Powered) return 15295; else return 15296; else if (Powered) return 15297; else return 15298; else if (Open) if (Powered) return 15299; else return 15300; else if (Powered) return 15301; else return 15302; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (InWall) if (Open) if (Powered) return 15303; else return 15304; else if (Powered) return 15305; else return 15306; else if (Open) if (Powered) return 15307; else return 15308; else if (Powered) return 15309; else return 15310; else if (InWall) if (Open) if (Powered) return 15311; else return 15312; else if (Powered) return 15313; else return 15314; else if (Open) if (Powered) return 15315; else return 15316; else if (Powered) return 15317; else return 15318; } BlockState WarpedFenceGate(); eBlockFace Facing(BlockState Block); bool InWall(BlockState Block); bool Open(BlockState Block); bool Powered(BlockState Block); } namespace WarpedFungus { constexpr BlockState WarpedFungus() { return 14971; } } namespace WarpedHyphae { enum class Axis { X, Y, Z }; constexpr BlockState WarpedHyphae(const enum Axis Axis) { if (Axis == Axis::X) return 14964; else if (Axis == Axis::Y) return 14965; else return 14966; } BlockState WarpedHyphae(); enum Axis Axis(BlockState Block); } namespace WarpedNylium { constexpr BlockState WarpedNylium() { return 14970; } } namespace WarpedPlanks { constexpr BlockState WarpedPlanks() { return 15046; } } namespace WarpedPressurePlate { constexpr BlockState WarpedPressurePlate(const bool Powered) { if (Powered) return 15061; else return 15062; } BlockState WarpedPressurePlate(); bool Powered(BlockState Block); } namespace WarpedRoots { constexpr BlockState WarpedRoots() { return 14973; } } namespace WarpedSign { constexpr BlockState WarpedSign(const unsigned char Rotation) { if (Rotation == 0) return 15688; else if (Rotation == 1) return 15690; else if (Rotation == 2) return 15692; else if (Rotation == 3) return 15694; else if (Rotation == 4) return 15696; else if (Rotation == 5) return 15698; else if (Rotation == 6) return 15700; else if (Rotation == 7) return 15702; else if (Rotation == 8) return 15704; else if (Rotation == 9) return 15706; else if (Rotation == 10) return 15708; else if (Rotation == 11) return 15710; else if (Rotation == 12) return 15712; else if (Rotation == 13) return 15714; else if (Rotation == 14) return 15716; else return 15718; } BlockState WarpedSign(); unsigned char Rotation(BlockState Block); } namespace WarpedSlab { enum class Type { Top, Bottom, Double }; constexpr BlockState WarpedSlab(const enum Type Type) { if (Type == Type::Top) return 15054; else if (Type == Type::Bottom) return 15056; else return 15058; } BlockState WarpedSlab(); enum Type Type(BlockState Block); } namespace WarpedStairs { enum class Half { Top, Bottom }; enum class Shape { Straight, InnerLeft, InnerRight, OuterLeft, OuterRight }; constexpr BlockState WarpedStairs(const eBlockFace Facing, const enum Half Half, const enum Shape Shape) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Half == Half::Top) if (Shape == Shape::Straight) return 15400; else if (Shape == Shape::InnerLeft) return 15402; else if (Shape == Shape::InnerRight) return 15404; else if (Shape == Shape::OuterLeft) return 15406; else return 15408; else if (Shape == Shape::Straight) return 15410; else if (Shape == Shape::InnerLeft) return 15412; else if (Shape == Shape::InnerRight) return 15414; else if (Shape == Shape::OuterLeft) return 15416; else return 15418; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Half == Half::Top) if (Shape == Shape::Straight) return 15420; else if (Shape == Shape::InnerLeft) return 15422; else if (Shape == Shape::InnerRight) return 15424; else if (Shape == Shape::OuterLeft) return 15426; else return 15428; else if (Shape == Shape::Straight) return 15430; else if (Shape == Shape::InnerLeft) return 15432; else if (Shape == Shape::InnerRight) return 15434; else if (Shape == Shape::OuterLeft) return 15436; else return 15438; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Half == Half::Top) if (Shape == Shape::Straight) return 15440; else if (Shape == Shape::InnerLeft) return 15442; else if (Shape == Shape::InnerRight) return 15444; else if (Shape == Shape::OuterLeft) return 15446; else return 15448; else if (Shape == Shape::Straight) return 15450; else if (Shape == Shape::InnerLeft) return 15452; else if (Shape == Shape::InnerRight) return 15454; else if (Shape == Shape::OuterLeft) return 15456; else return 15458; else if (Half == Half::Top) if (Shape == Shape::Straight) return 15460; else if (Shape == Shape::InnerLeft) return 15462; else if (Shape == Shape::InnerRight) return 15464; else if (Shape == Shape::OuterLeft) return 15466; else return 15468; else if (Shape == Shape::Straight) return 15470; else if (Shape == Shape::InnerLeft) return 15472; else if (Shape == Shape::InnerRight) return 15474; else if (Shape == Shape::OuterLeft) return 15476; else return 15478; } BlockState WarpedStairs(); eBlockFace Facing(BlockState Block); enum Half Half(BlockState Block); enum Shape Shape(BlockState Block); } namespace WarpedStem { enum class Axis { X, Y, Z }; constexpr BlockState WarpedStem(const enum Axis Axis) { if (Axis == Axis::X) return 14958; else if (Axis == Axis::Y) return 14959; else return 14960; } BlockState WarpedStem(); enum Axis Axis(BlockState Block); } namespace WarpedTrapdoor { enum class Half { Top, Bottom }; constexpr BlockState WarpedTrapdoor(const eBlockFace Facing, const enum Half Half, const bool Open, const bool Powered) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Half == Half::Top) if (Open) if (Powered) return 15192; else return 15194; else if (Powered) return 15196; else return 15198; else if (Open) if (Powered) return 15200; else return 15202; else if (Powered) return 15204; else return 15206; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Half == Half::Top) if (Open) if (Powered) return 15208; else return 15210; else if (Powered) return 15212; else return 15214; else if (Open) if (Powered) return 15216; else return 15218; else if (Powered) return 15220; else return 15222; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Half == Half::Top) if (Open) if (Powered) return 15224; else return 15226; else if (Powered) return 15228; else return 15230; else if (Open) if (Powered) return 15232; else return 15234; else if (Powered) return 15236; else return 15238; else if (Half == Half::Top) if (Open) if (Powered) return 15240; else return 15242; else if (Powered) return 15244; else return 15246; else if (Open) if (Powered) return 15248; else return 15250; else if (Powered) return 15252; else return 15254; } BlockState WarpedTrapdoor(); eBlockFace Facing(BlockState Block); enum Half Half(BlockState Block); bool Open(BlockState Block); bool Powered(BlockState Block); } namespace WarpedWallSign { constexpr BlockState WarpedWallSign(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 15728; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 15730; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 15732; else return 15734; } BlockState WarpedWallSign(); eBlockFace Facing(BlockState Block); } namespace WarpedWartBlock { constexpr BlockState WarpedWartBlock() { return 14972; } } namespace Water { constexpr BlockState Water(const unsigned char Level) { if (Level == 0) return 34; else if (Level == 1) return 35; else if (Level == 2) return 36; else if (Level == 3) return 37; else if (Level == 4) return 38; else if (Level == 5) return 39; else if (Level == 6) return 40; else if (Level == 7) return 41; else if (Level == 8) return 42; else if (Level == 9) return 43; else if (Level == 10) return 44; else if (Level == 11) return 45; else if (Level == 12) return 46; else if (Level == 13) return 47; else if (Level == 14) return 48; else return 49; } BlockState Water(); unsigned char Level(BlockState Block); } namespace WeepingVines { constexpr BlockState WeepingVines(const unsigned char Age) { if (Age == 0) return 14990; else if (Age == 1) return 14991; else if (Age == 2) return 14992; else if (Age == 3) return 14993; else if (Age == 4) return 14994; else if (Age == 5) return 14995; else if (Age == 6) return 14996; else if (Age == 7) return 14997; else if (Age == 8) return 14998; else if (Age == 9) return 14999; else if (Age == 10) return 15000; else if (Age == 11) return 15001; else if (Age == 12) return 15002; else if (Age == 13) return 15003; else if (Age == 14) return 15004; else if (Age == 15) return 15005; else if (Age == 16) return 15006; else if (Age == 17) return 15007; else if (Age == 18) return 15008; else if (Age == 19) return 15009; else if (Age == 20) return 15010; else if (Age == 21) return 15011; else if (Age == 22) return 15012; else if (Age == 23) return 15013; else if (Age == 24) return 15014; else return 15015; } BlockState WeepingVines(); unsigned char Age(BlockState Block); } namespace WeepingVinesPlant { constexpr BlockState WeepingVinesPlant() { return 15016; } } namespace WetSponge { constexpr BlockState WetSponge() { return 230; } } namespace Wheat { constexpr BlockState Wheat(const unsigned char Age) { if (Age == 0) return 3357; else if (Age == 1) return 3358; else if (Age == 2) return 3359; else if (Age == 3) return 3360; else if (Age == 4) return 3361; else if (Age == 5) return 3362; else if (Age == 6) return 3363; else return 3364; } BlockState Wheat(); unsigned char Age(BlockState Block); } namespace WhiteBanner { constexpr BlockState WhiteBanner(const unsigned char Rotation) { if (Rotation == 0) return 7897; else if (Rotation == 1) return 7898; else if (Rotation == 2) return 7899; else if (Rotation == 3) return 7900; else if (Rotation == 4) return 7901; else if (Rotation == 5) return 7902; else if (Rotation == 6) return 7903; else if (Rotation == 7) return 7904; else if (Rotation == 8) return 7905; else if (Rotation == 9) return 7906; else if (Rotation == 10) return 7907; else if (Rotation == 11) return 7908; else if (Rotation == 12) return 7909; else if (Rotation == 13) return 7910; else if (Rotation == 14) return 7911; else return 7912; } BlockState WhiteBanner(); unsigned char Rotation(BlockState Block); } namespace WhiteBed { enum class Part { Head, Foot }; constexpr BlockState WhiteBed(const eBlockFace Facing, const bool Occupied, const enum Part Part) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Occupied) if (Part == Part::Head) return 1049; else return 1050; else if (Part == Part::Head) return 1051; else return 1052; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Occupied) if (Part == Part::Head) return 1053; else return 1054; else if (Part == Part::Head) return 1055; else return 1056; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Occupied) if (Part == Part::Head) return 1057; else return 1058; else if (Part == Part::Head) return 1059; else return 1060; else if (Occupied) if (Part == Part::Head) return 1061; else return 1062; else if (Part == Part::Head) return 1063; else return 1064; } BlockState WhiteBed(); eBlockFace Facing(BlockState Block); bool Occupied(BlockState Block); enum Part Part(BlockState Block); } namespace WhiteCarpet { constexpr BlockState WhiteCarpet() { return 7866; } } namespace WhiteConcrete { constexpr BlockState WhiteConcrete() { return 9438; } } namespace WhiteConcretePowder { constexpr BlockState WhiteConcretePowder() { return 9454; } } namespace WhiteGlazedTerracotta { constexpr BlockState WhiteGlazedTerracotta(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 9374; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 9375; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 9376; else return 9377; } BlockState WhiteGlazedTerracotta(); eBlockFace Facing(BlockState Block); } namespace WhiteShulkerBox { constexpr BlockState WhiteShulkerBox(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 9278; else if (Facing == eBlockFace::BLOCK_FACE_XP) return 9279; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 9280; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 9281; else if (Facing == eBlockFace::BLOCK_FACE_YP) return 9282; else return 9283; } BlockState WhiteShulkerBox(); eBlockFace Facing(BlockState Block); } namespace WhiteStainedGlass { constexpr BlockState WhiteStainedGlass() { return 4095; } } namespace WhiteStainedGlassPane { constexpr BlockState WhiteStainedGlassPane(const bool East, const bool North, const bool South, const bool West) { if (East) if (North) if (South) if (West) return 6865; else return 6866; else if (West) return 6869; else return 6870; else if (South) if (West) return 6873; else return 6874; else if (West) return 6877; else return 6878; else if (North) if (South) if (West) return 6881; else return 6882; else if (West) return 6885; else return 6886; else if (South) if (West) return 6889; else return 6890; else if (West) return 6893; else return 6894; } BlockState WhiteStainedGlassPane(); bool East(BlockState Block); bool North(BlockState Block); bool South(BlockState Block); bool West(BlockState Block); } namespace WhiteTerracotta { constexpr BlockState WhiteTerracotta() { return 6847; } } namespace WhiteTulip { constexpr BlockState WhiteTulip() { return 1419; } } namespace WhiteWallBanner { constexpr BlockState WhiteWallBanner(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 8153; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 8154; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 8155; else return 8156; } BlockState WhiteWallBanner(); eBlockFace Facing(BlockState Block); } namespace WhiteWool { constexpr BlockState WhiteWool() { return 1384; } } namespace WitherRose { constexpr BlockState WitherRose() { return 1423; } } namespace WitherSkeletonSkull { constexpr BlockState WitherSkeletonSkull(const unsigned char Rotation) { if (Rotation == 0) return 6510; else if (Rotation == 1) return 6511; else if (Rotation == 2) return 6512; else if (Rotation == 3) return 6513; else if (Rotation == 4) return 6514; else if (Rotation == 5) return 6515; else if (Rotation == 6) return 6516; else if (Rotation == 7) return 6517; else if (Rotation == 8) return 6518; else if (Rotation == 9) return 6519; else if (Rotation == 10) return 6520; else if (Rotation == 11) return 6521; else if (Rotation == 12) return 6522; else if (Rotation == 13) return 6523; else if (Rotation == 14) return 6524; else return 6525; } BlockState WitherSkeletonSkull(); unsigned char Rotation(BlockState Block); } namespace WitherSkeletonWallSkull { constexpr BlockState WitherSkeletonWallSkull(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 6526; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 6527; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 6528; else return 6529; } BlockState WitherSkeletonWallSkull(); eBlockFace Facing(BlockState Block); } namespace YellowBanner { constexpr BlockState YellowBanner(const unsigned char Rotation) { if (Rotation == 0) return 7961; else if (Rotation == 1) return 7962; else if (Rotation == 2) return 7963; else if (Rotation == 3) return 7964; else if (Rotation == 4) return 7965; else if (Rotation == 5) return 7966; else if (Rotation == 6) return 7967; else if (Rotation == 7) return 7968; else if (Rotation == 8) return 7969; else if (Rotation == 9) return 7970; else if (Rotation == 10) return 7971; else if (Rotation == 11) return 7972; else if (Rotation == 12) return 7973; else if (Rotation == 13) return 7974; else if (Rotation == 14) return 7975; else return 7976; } BlockState YellowBanner(); unsigned char Rotation(BlockState Block); } namespace YellowBed { enum class Part { Head, Foot }; constexpr BlockState YellowBed(const eBlockFace Facing, const bool Occupied, const enum Part Part) { if (Facing == eBlockFace::BLOCK_FACE_ZM) if (Occupied) if (Part == Part::Head) return 1113; else return 1114; else if (Part == Part::Head) return 1115; else return 1116; else if (Facing == eBlockFace::BLOCK_FACE_ZP) if (Occupied) if (Part == Part::Head) return 1117; else return 1118; else if (Part == Part::Head) return 1119; else return 1120; else if (Facing == eBlockFace::BLOCK_FACE_XM) if (Occupied) if (Part == Part::Head) return 1121; else return 1122; else if (Part == Part::Head) return 1123; else return 1124; else if (Occupied) if (Part == Part::Head) return 1125; else return 1126; else if (Part == Part::Head) return 1127; else return 1128; } BlockState YellowBed(); eBlockFace Facing(BlockState Block); bool Occupied(BlockState Block); enum Part Part(BlockState Block); } namespace YellowCarpet { constexpr BlockState YellowCarpet() { return 7870; } } namespace YellowConcrete { constexpr BlockState YellowConcrete() { return 9442; } } namespace YellowConcretePowder { constexpr BlockState YellowConcretePowder() { return 9458; } } namespace YellowGlazedTerracotta { constexpr BlockState YellowGlazedTerracotta(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 9390; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 9391; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 9392; else return 9393; } BlockState YellowGlazedTerracotta(); eBlockFace Facing(BlockState Block); } namespace YellowShulkerBox { constexpr BlockState YellowShulkerBox(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 9302; else if (Facing == eBlockFace::BLOCK_FACE_XP) return 9303; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 9304; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 9305; else if (Facing == eBlockFace::BLOCK_FACE_YP) return 9306; else return 9307; } BlockState YellowShulkerBox(); eBlockFace Facing(BlockState Block); } namespace YellowStainedGlass { constexpr BlockState YellowStainedGlass() { return 4099; } } namespace YellowStainedGlassPane { constexpr BlockState YellowStainedGlassPane(const bool East, const bool North, const bool South, const bool West) { if (East) if (North) if (South) if (West) return 6993; else return 6994; else if (West) return 6997; else return 6998; else if (South) if (West) return 7001; else return 7002; else if (West) return 7005; else return 7006; else if (North) if (South) if (West) return 7009; else return 7010; else if (West) return 7013; else return 7014; else if (South) if (West) return 7017; else return 7018; else if (West) return 7021; else return 7022; } BlockState YellowStainedGlassPane(); bool East(BlockState Block); bool North(BlockState Block); bool South(BlockState Block); bool West(BlockState Block); } namespace YellowTerracotta { constexpr BlockState YellowTerracotta() { return 6851; } } namespace YellowWallBanner { constexpr BlockState YellowWallBanner(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 8169; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 8170; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 8171; else return 8172; } BlockState YellowWallBanner(); eBlockFace Facing(BlockState Block); } namespace YellowWool { constexpr BlockState YellowWool() { return 1388; } } namespace ZombieHead { constexpr BlockState ZombieHead(const unsigned char Rotation) { if (Rotation == 0) return 6530; else if (Rotation == 1) return 6531; else if (Rotation == 2) return 6532; else if (Rotation == 3) return 6533; else if (Rotation == 4) return 6534; else if (Rotation == 5) return 6535; else if (Rotation == 6) return 6536; else if (Rotation == 7) return 6537; else if (Rotation == 8) return 6538; else if (Rotation == 9) return 6539; else if (Rotation == 10) return 6540; else if (Rotation == 11) return 6541; else if (Rotation == 12) return 6542; else if (Rotation == 13) return 6543; else if (Rotation == 14) return 6544; else return 6545; } BlockState ZombieHead(); unsigned char Rotation(BlockState Block); } namespace ZombieWallHead { constexpr BlockState ZombieWallHead(const eBlockFace Facing) { if (Facing == eBlockFace::BLOCK_FACE_ZM) return 6546; else if (Facing == eBlockFace::BLOCK_FACE_ZP) return 6547; else if (Facing == eBlockFace::BLOCK_FACE_XM) return 6548; else return 6549; } BlockState ZombieWallHead(); eBlockFace Facing(BlockState Block); } } ================================================ FILE: src/Registries/BlockTypes.h ================================================ #pragma once enum class BlockType { AcaciaButton, AcaciaDoor, AcaciaFence, AcaciaFenceGate, AcaciaLeaves, AcaciaLog, AcaciaPlanks, AcaciaPressurePlate, AcaciaSapling, AcaciaSign, AcaciaSlab, AcaciaStairs, AcaciaTrapdoor, AcaciaWallSign, AcaciaWood, ActivatorRail, Air, Allium, AncientDebris, Andesite, AndesiteSlab, AndesiteStairs, AndesiteWall, Anvil, AttachedMelonStem, AttachedPumpkinStem, AzureBluet, Bamboo, BambooSapling, Barrel, Barrier, Basalt, Beacon, Bedrock, BeeNest, Beehive, Beetroots, Bell, BirchButton, BirchDoor, BirchFence, BirchFenceGate, BirchLeaves, BirchLog, BirchPlanks, BirchPressurePlate, BirchSapling, BirchSign, BirchSlab, BirchStairs, BirchTrapdoor, BirchWallSign, BirchWood, BlackBanner, BlackBed, BlackCarpet, BlackConcrete, BlackConcretePowder, BlackGlazedTerracotta, BlackShulkerBox, BlackStainedGlass, BlackStainedGlassPane, BlackTerracotta, BlackWallBanner, BlackWool, Blackstone, BlackstoneSlab, BlackstoneStairs, BlackstoneWall, BlastFurnace, BlueBanner, BlueBed, BlueCarpet, BlueConcrete, BlueConcretePowder, BlueGlazedTerracotta, BlueIce, BlueOrchid, BlueShulkerBox, BlueStainedGlass, BlueStainedGlassPane, BlueTerracotta, BlueWallBanner, BlueWool, BoneBlock, Bookshelf, BrainCoral, BrainCoralBlock, BrainCoralFan, BrainCoralWallFan, BrewingStand, BrickSlab, BrickStairs, BrickWall, Bricks, BrownBanner, BrownBed, BrownCarpet, BrownConcrete, BrownConcretePowder, BrownGlazedTerracotta, BrownMushroom, BrownMushroomBlock, BrownShulkerBox, BrownStainedGlass, BrownStainedGlassPane, BrownTerracotta, BrownWallBanner, BrownWool, BubbleColumn, BubbleCoral, BubbleCoralBlock, BubbleCoralFan, BubbleCoralWallFan, Cactus, Cake, Campfire, Carrots, CartographyTable, CarvedPumpkin, Cauldron, CaveAir, Chain, ChainCommandBlock, Chest, ChippedAnvil, ChiseledNetherBricks, ChiseledPolishedBlackstone, ChiseledQuartzBlock, ChiseledRedSandstone, ChiseledSandstone, ChiseledStoneBricks, ChorusFlower, ChorusPlant, Clay, CoalBlock, CoalOre, CoarseDirt, Cobblestone, CobblestoneSlab, CobblestoneStairs, CobblestoneWall, Cobweb, Cocoa, CommandBlock, Comparator, Composter, Conduit, Cornflower, CrackedNetherBricks, CrackedPolishedBlackstoneBricks, CrackedStoneBricks, CraftingTable, CreeperHead, CreeperWallHead, CrimsonButton, CrimsonDoor, CrimsonFence, CrimsonFenceGate, CrimsonFungus, CrimsonHyphae, CrimsonNylium, CrimsonPlanks, CrimsonPressurePlate, CrimsonRoots, CrimsonSign, CrimsonSlab, CrimsonStairs, CrimsonStem, CrimsonTrapdoor, CrimsonWallSign, CryingObsidian, CutRedSandstone, CutRedSandstoneSlab, CutSandstone, CutSandstoneSlab, CyanBanner, CyanBed, CyanCarpet, CyanConcrete, CyanConcretePowder, CyanGlazedTerracotta, CyanShulkerBox, CyanStainedGlass, CyanStainedGlassPane, CyanTerracotta, CyanWallBanner, CyanWool, DamagedAnvil, Dandelion, DarkOakButton, DarkOakDoor, DarkOakFence, DarkOakFenceGate, DarkOakLeaves, DarkOakLog, DarkOakPlanks, DarkOakPressurePlate, DarkOakSapling, DarkOakSign, DarkOakSlab, DarkOakStairs, DarkOakTrapdoor, DarkOakWallSign, DarkOakWood, DarkPrismarine, DarkPrismarineSlab, DarkPrismarineStairs, DaylightDetector, DeadBrainCoral, DeadBrainCoralBlock, DeadBrainCoralFan, DeadBrainCoralWallFan, DeadBubbleCoral, DeadBubbleCoralBlock, DeadBubbleCoralFan, DeadBubbleCoralWallFan, DeadBush, DeadFireCoral, DeadFireCoralBlock, DeadFireCoralFan, DeadFireCoralWallFan, DeadHornCoral, DeadHornCoralBlock, DeadHornCoralFan, DeadHornCoralWallFan, DeadTubeCoral, DeadTubeCoralBlock, DeadTubeCoralFan, DeadTubeCoralWallFan, DetectorRail, DiamondBlock, DiamondOre, Diorite, DioriteSlab, DioriteStairs, DioriteWall, Dirt, Dispenser, DragonEgg, DragonHead, DragonWallHead, DriedKelpBlock, Dropper, EmeraldBlock, EmeraldOre, EnchantingTable, EndGateway, EndPortal, EndPortalFrame, EndRod, EndStone, EndStoneBrickSlab, EndStoneBrickStairs, EndStoneBrickWall, EndStoneBricks, EnderChest, Farmland, Fern, Fire, FireCoral, FireCoralBlock, FireCoralFan, FireCoralWallFan, FletchingTable, FlowerPot, FrostedIce, Furnace, GildedBlackstone, Glass, GlassPane, Glowstone, GoldBlock, GoldOre, Granite, GraniteSlab, GraniteStairs, GraniteWall, Grass, GrassBlock, GrassPath, Gravel, GrayBanner, GrayBed, GrayCarpet, GrayConcrete, GrayConcretePowder, GrayGlazedTerracotta, GrayShulkerBox, GrayStainedGlass, GrayStainedGlassPane, GrayTerracotta, GrayWallBanner, GrayWool, GreenBanner, GreenBed, GreenCarpet, GreenConcrete, GreenConcretePowder, GreenGlazedTerracotta, GreenShulkerBox, GreenStainedGlass, GreenStainedGlassPane, GreenTerracotta, GreenWallBanner, GreenWool, Grindstone, HayBale, HeavyWeightedPressurePlate, HoneyBlock, HoneycombBlock, Hopper, HornCoral, HornCoralBlock, HornCoralFan, HornCoralWallFan, Ice, InfestedChiseledStoneBricks, InfestedCobblestone, InfestedCrackedStoneBricks, InfestedMossyStoneBricks, InfestedStone, InfestedStoneBricks, IronBars, IronBlock, IronDoor, IronOre, IronTrapdoor, JackOLantern, Jigsaw, Jukebox, JungleButton, JungleDoor, JungleFence, JungleFenceGate, JungleLeaves, JungleLog, JunglePlanks, JunglePressurePlate, JungleSapling, JungleSign, JungleSlab, JungleStairs, JungleTrapdoor, JungleWallSign, JungleWood, Kelp, KelpPlant, Ladder, Lantern, LapisBlock, LapisOre, LargeFern, Lava, Lectern, Lever, LightBlueBanner, LightBlueBed, LightBlueCarpet, LightBlueConcrete, LightBlueConcretePowder, LightBlueGlazedTerracotta, LightBlueShulkerBox, LightBlueStainedGlass, LightBlueStainedGlassPane, LightBlueTerracotta, LightBlueWallBanner, LightBlueWool, LightGrayBanner, LightGrayBed, LightGrayCarpet, LightGrayConcrete, LightGrayConcretePowder, LightGrayGlazedTerracotta, LightGrayShulkerBox, LightGrayStainedGlass, LightGrayStainedGlassPane, LightGrayTerracotta, LightGrayWallBanner, LightGrayWool, LightWeightedPressurePlate, Lilac, LilyOfTheValley, LilyPad, LimeBanner, LimeBed, LimeCarpet, LimeConcrete, LimeConcretePowder, LimeGlazedTerracotta, LimeShulkerBox, LimeStainedGlass, LimeStainedGlassPane, LimeTerracotta, LimeWallBanner, LimeWool, Lodestone, Loom, MagentaBanner, MagentaBed, MagentaCarpet, MagentaConcrete, MagentaConcretePowder, MagentaGlazedTerracotta, MagentaShulkerBox, MagentaStainedGlass, MagentaStainedGlassPane, MagentaTerracotta, MagentaWallBanner, MagentaWool, MagmaBlock, Melon, MelonStem, MossyCobblestone, MossyCobblestoneSlab, MossyCobblestoneStairs, MossyCobblestoneWall, MossyStoneBrickSlab, MossyStoneBrickStairs, MossyStoneBrickWall, MossyStoneBricks, MovingPiston, MushroomStem, Mycelium, NetherBrickFence, NetherBrickSlab, NetherBrickStairs, NetherBrickWall, NetherBricks, NetherGoldOre, NetherPortal, NetherQuartzOre, NetherSprouts, NetherWart, NetherWartBlock, NetheriteBlock, Netherrack, NoteBlock, OakButton, OakDoor, OakFence, OakFenceGate, OakLeaves, OakLog, OakPlanks, OakPressurePlate, OakSapling, OakSign, OakSlab, OakStairs, OakTrapdoor, OakWallSign, OakWood, Observer, Obsidian, OrangeBanner, OrangeBed, OrangeCarpet, OrangeConcrete, OrangeConcretePowder, OrangeGlazedTerracotta, OrangeShulkerBox, OrangeStainedGlass, OrangeStainedGlassPane, OrangeTerracotta, OrangeTulip, OrangeWallBanner, OrangeWool, OxeyeDaisy, PackedIce, Peony, PetrifiedOakSlab, PinkBanner, PinkBed, PinkCarpet, PinkConcrete, PinkConcretePowder, PinkGlazedTerracotta, PinkShulkerBox, PinkStainedGlass, PinkStainedGlassPane, PinkTerracotta, PinkTulip, PinkWallBanner, PinkWool, Piston, PistonHead, PlayerHead, PlayerWallHead, Podzol, PolishedAndesite, PolishedAndesiteSlab, PolishedAndesiteStairs, PolishedBasalt, PolishedBlackstone, PolishedBlackstoneBrickSlab, PolishedBlackstoneBrickStairs, PolishedBlackstoneBrickWall, PolishedBlackstoneBricks, PolishedBlackstoneButton, PolishedBlackstonePressurePlate, PolishedBlackstoneSlab, PolishedBlackstoneStairs, PolishedBlackstoneWall, PolishedDiorite, PolishedDioriteSlab, PolishedDioriteStairs, PolishedGranite, PolishedGraniteSlab, PolishedGraniteStairs, Poppy, Potatoes, PottedAcaciaSapling, PottedAllium, PottedAzureBluet, PottedBamboo, PottedBirchSapling, PottedBlueOrchid, PottedBrownMushroom, PottedCactus, PottedCornflower, PottedCrimsonFungus, PottedCrimsonRoots, PottedDandelion, PottedDarkOakSapling, PottedDeadBush, PottedFern, PottedJungleSapling, PottedLilyOfTheValley, PottedOakSapling, PottedOrangeTulip, PottedOxeyeDaisy, PottedPinkTulip, PottedPoppy, PottedRedMushroom, PottedRedTulip, PottedSpruceSapling, PottedWarpedFungus, PottedWarpedRoots, PottedWhiteTulip, PottedWitherRose, PoweredRail, Prismarine, PrismarineBrickSlab, PrismarineBrickStairs, PrismarineBricks, PrismarineSlab, PrismarineStairs, PrismarineWall, Pumpkin, PumpkinStem, PurpleBanner, PurpleBed, PurpleCarpet, PurpleConcrete, PurpleConcretePowder, PurpleGlazedTerracotta, PurpleShulkerBox, PurpleStainedGlass, PurpleStainedGlassPane, PurpleTerracotta, PurpleWallBanner, PurpleWool, PurpurBlock, PurpurPillar, PurpurSlab, PurpurStairs, QuartzBlock, QuartzBricks, QuartzPillar, QuartzSlab, QuartzStairs, Rail, RedBanner, RedBed, RedCarpet, RedConcrete, RedConcretePowder, RedGlazedTerracotta, RedMushroom, RedMushroomBlock, RedNetherBrickSlab, RedNetherBrickStairs, RedNetherBrickWall, RedNetherBricks, RedSand, RedSandstone, RedSandstoneSlab, RedSandstoneStairs, RedSandstoneWall, RedShulkerBox, RedStainedGlass, RedStainedGlassPane, RedTerracotta, RedTulip, RedWallBanner, RedWool, RedstoneBlock, RedstoneLamp, RedstoneOre, RedstoneTorch, RedstoneWallTorch, RedstoneWire, Repeater, RepeatingCommandBlock, RespawnAnchor, RoseBush, Sand, Sandstone, SandstoneSlab, SandstoneStairs, SandstoneWall, Scaffolding, SeaLantern, SeaPickle, Seagrass, Shroomlight, ShulkerBox, SkeletonSkull, SkeletonWallSkull, SlimeBlock, SmithingTable, Smoker, SmoothQuartz, SmoothQuartzSlab, SmoothQuartzStairs, SmoothRedSandstone, SmoothRedSandstoneSlab, SmoothRedSandstoneStairs, SmoothSandstone, SmoothSandstoneSlab, SmoothSandstoneStairs, SmoothStone, SmoothStoneSlab, Snow, SnowBlock, SoulCampfire, SoulFire, SoulLantern, SoulSand, SoulSoil, SoulTorch, SoulWallTorch, Spawner, Sponge, SpruceButton, SpruceDoor, SpruceFence, SpruceFenceGate, SpruceLeaves, SpruceLog, SprucePlanks, SprucePressurePlate, SpruceSapling, SpruceSign, SpruceSlab, SpruceStairs, SpruceTrapdoor, SpruceWallSign, SpruceWood, StickyPiston, Stone, StoneBrickSlab, StoneBrickStairs, StoneBrickWall, StoneBricks, StoneButton, StonePressurePlate, StoneSlab, StoneStairs, Stonecutter, StrippedAcaciaLog, StrippedAcaciaWood, StrippedBirchLog, StrippedBirchWood, StrippedCrimsonHyphae, StrippedCrimsonStem, StrippedDarkOakLog, StrippedDarkOakWood, StrippedJungleLog, StrippedJungleWood, StrippedOakLog, StrippedOakWood, StrippedSpruceLog, StrippedSpruceWood, StrippedWarpedHyphae, StrippedWarpedStem, StructureBlock, StructureVoid, SugarCane, Sunflower, SweetBerryBush, TNT, TallGrass, TallSeagrass, Target, Terracotta, Torch, TrappedChest, Tripwire, TripwireHook, TubeCoral, TubeCoralBlock, TubeCoralFan, TubeCoralWallFan, TurtleEgg, TwistingVines, TwistingVinesPlant, Vine, VoidAir, WallTorch, WarpedButton, WarpedDoor, WarpedFence, WarpedFenceGate, WarpedFungus, WarpedHyphae, WarpedNylium, WarpedPlanks, WarpedPressurePlate, WarpedRoots, WarpedSign, WarpedSlab, WarpedStairs, WarpedStem, WarpedTrapdoor, WarpedWallSign, WarpedWartBlock, Water, WeepingVines, WeepingVinesPlant, WetSponge, Wheat, WhiteBanner, WhiteBed, WhiteCarpet, WhiteConcrete, WhiteConcretePowder, WhiteGlazedTerracotta, WhiteShulkerBox, WhiteStainedGlass, WhiteStainedGlassPane, WhiteTerracotta, WhiteTulip, WhiteWallBanner, WhiteWool, WitherRose, WitherSkeletonSkull, WitherSkeletonWallSkull, YellowBanner, YellowBed, YellowCarpet, YellowConcrete, YellowConcretePowder, YellowGlazedTerracotta, YellowShulkerBox, YellowStainedGlass, YellowStainedGlassPane, YellowTerracotta, YellowWallBanner, YellowWool, ZombieHead, ZombieWallHead }; ================================================ FILE: src/Registries/CMakeLists.txt ================================================ target_sources( ${CMAKE_PROJECT_NAME} PRIVATE BlockStates.cpp BlockStates.h BlockTypes.h CustomStatistics.h Items.h ) ================================================ FILE: src/Registries/CustomStatistics.h ================================================ #pragma once // tolua_begin enum class CustomStatistic { // tolua_end /* Achievements */ AchOpenInventory, /* Taking Inventory */ AchMineWood, /* Getting Wood */ AchBuildWorkBench, /* Benchmarking */ AchBuildPickaxe, /* Time to Mine! */ AchBuildFurnace, /* Hot Topic */ AchAcquireIron, /* Acquire Hardware */ AchBuildHoe, /* Time to Farm! */ AchMakeBread, /* Bake Bread */ AchBakeCake, /* The Lie */ AchBuildBetterPickaxe, /* Getting an Upgrade */ AchCookFish, /* Delicious Fish */ AchOnARail, /* On A Rail */ AchBuildSword, /* Time to Strike! */ AchKillEnemy, /* Monster Hunter */ AchKillCow, /* Cow Tipper */ AchFlyPig, /* When Pigs Fly */ AchSnipeSkeleton, /* Sniper Duel */ AchDiamonds, /* DIAMONDS! */ AchPortal, /* We Need to Go Deeper */ AchGhast, /* Return to Sender */ AchBlazeRod, /* Into Fire */ AchPotion, /* Local Brewery */ AchTheEnd, /* The End? */ AchTheEnd2, /* The End. */ AchEnchantments, /* Enchanter */ AchOverkill, /* Overkill */ AchBookcase, /* Librarian */ AchExploreAllBiomes, /* Adventuring Time */ AchSpawnWither, /* The Beginning? */ AchKillWither, /* The Beginning. */ AchFullBeacon, /* Beaconator */ AchBreedCow, /* Repopulation */ AchDiamondsToYou, /* Diamonds to you! */ // tolua_begin /* Statistics */ AnimalsBred, AviateOneCm, BellRing, BoatOneCm, CleanArmor, CleanBanner, CleanShulkerBox, ClimbOneCm, CrouchOneCm, DamageAbsorbed, DamageBlockedByShield, DamageDealt, DamageDealtAbsorbed, DamageDealtResisted, DamageResisted, DamageTaken, Deaths, Drop, EatCakeSlice, EnchantItem, FallOneCm, FillCauldron, FishCaught, FlyOneCm, HorseOneCm, InspectDispenser, InspectDropper, InspectHopper, InteractWithAnvil, InteractWithBeacon, InteractWithBlastFurnace, InteractWithBrewingstand, InteractWithCampfire, InteractWithCartographyTable, InteractWithCraftingTable, InteractWithFurnace, InteractWithGrindstone, InteractWithLectern, InteractWithLoom, InteractWithSmithingTable, InteractWithSmoker, InteractWithStonecutter, Jump, LeaveGame, MinecartOneCm, MobKills, OpenBarrel, OpenChest, OpenEnderchest, OpenShulkerBox, PigOneCm, PlayNoteblock, PlayOneMinute, PlayRecord, PlayerKills, PotFlower, RaidTrigger, RaidWin, SleepInBed, SneakTime, SprintOneCm, StriderOneCm, SwimOneCm, TalkedToVillager, TargetHit, TimeSinceDeath, TimeSinceRest, TradedWithVillager, TriggerTrappedChest, TuneNoteblock, UseCauldron, WalkOnWaterOneCm, WalkOneCm, WalkUnderWaterOneCm, // Old ones just for compatibility JunkFished, TreasureFished, }; // tolua_end ================================================ FILE: src/Registries/Items.h ================================================ #pragma once enum class Item { AcaciaBoat, AcaciaButton, AcaciaDoor, AcaciaFence, AcaciaFenceGate, AcaciaLeaves, AcaciaLog, AcaciaPlanks, AcaciaPressurePlate, AcaciaSapling, AcaciaSign, AcaciaSlab, AcaciaStairs, AcaciaTrapdoor, AcaciaWood, ActivatorRail, Air, Allium, AncientDebris, Andesite, AndesiteSlab, AndesiteStairs, AndesiteWall, Anvil, Apple, ArmorStand, Arrow, AzureBluet, BakedPotato, Bamboo, Barrel, Barrier, Basalt, BatSpawnEgg, Beacon, Bedrock, BeeNest, BeeSpawnEgg, Beef, Beehive, Beetroot, BeetrootSeeds, BeetrootSoup, Bell, BirchBoat, BirchButton, BirchDoor, BirchFence, BirchFenceGate, BirchLeaves, BirchLog, BirchPlanks, BirchPressurePlate, BirchSapling, BirchSign, BirchSlab, BirchStairs, BirchTrapdoor, BirchWood, BlackBanner, BlackBed, BlackCarpet, BlackConcrete, BlackConcretePowder, BlackDye, BlackGlazedTerracotta, BlackShulkerBox, BlackStainedGlass, BlackStainedGlassPane, BlackTerracotta, BlackWool, Blackstone, BlackstoneSlab, BlackstoneStairs, BlackstoneWall, BlastFurnace, BlazePowder, BlazeRod, BlazeSpawnEgg, BlueBanner, BlueBed, BlueCarpet, BlueConcrete, BlueConcretePowder, BlueDye, BlueGlazedTerracotta, BlueIce, BlueOrchid, BlueShulkerBox, BlueStainedGlass, BlueStainedGlassPane, BlueTerracotta, BlueWool, Bone, BoneBlock, BoneMeal, Book, Bookshelf, Bow, Bowl, BrainCoral, BrainCoralBlock, BrainCoralFan, Bread, BrewingStand, Brick, BrickSlab, BrickStairs, BrickWall, Bricks, BrownBanner, BrownBed, BrownCarpet, BrownConcrete, BrownConcretePowder, BrownDye, BrownGlazedTerracotta, BrownMushroom, BrownMushroomBlock, BrownShulkerBox, BrownStainedGlass, BrownStainedGlassPane, BrownTerracotta, BrownWool, BubbleCoral, BubbleCoralBlock, BubbleCoralFan, Bucket, Cactus, Cake, Campfire, Carrot, CarrotOnAStick, CartographyTable, CarvedPumpkin, CatSpawnEgg, Cauldron, CaveSpiderSpawnEgg, Chain, ChainCommandBlock, ChainmailBoots, ChainmailChestplate, ChainmailHelmet, ChainmailLeggings, Charcoal, Chest, ChestMinecart, Chicken, ChickenSpawnEgg, ChippedAnvil, ChiseledNetherBricks, ChiseledPolishedBlackstone, ChiseledQuartzBlock, ChiseledRedSandstone, ChiseledSandstone, ChiseledStoneBricks, ChorusFlower, ChorusFruit, ChorusPlant, Clay, ClayBall, Clock, Coal, CoalBlock, CoalOre, CoarseDirt, Cobblestone, CobblestoneSlab, CobblestoneStairs, CobblestoneWall, Cobweb, CocoaBeans, Cod, CodBucket, CodSpawnEgg, CommandBlock, CommandBlockMinecart, Comparator, Compass, Composter, Conduit, CookedBeef, CookedChicken, CookedCod, CookedMutton, CookedPorkchop, CookedRabbit, CookedSalmon, Cookie, Cornflower, CowSpawnEgg, CrackedNetherBricks, CrackedPolishedBlackstoneBricks, CrackedStoneBricks, CraftingTable, CreeperBannerPattern, CreeperHead, CreeperSpawnEgg, CrimsonButton, CrimsonDoor, CrimsonFence, CrimsonFenceGate, CrimsonFungus, CrimsonHyphae, CrimsonNylium, CrimsonPlanks, CrimsonPressurePlate, CrimsonRoots, CrimsonSign, CrimsonSlab, CrimsonStairs, CrimsonStem, CrimsonTrapdoor, Crossbow, CryingObsidian, CutRedSandstone, CutRedSandstoneSlab, CutSandstone, CutSandstoneSlab, CyanBanner, CyanBed, CyanCarpet, CyanConcrete, CyanConcretePowder, CyanDye, CyanGlazedTerracotta, CyanShulkerBox, CyanStainedGlass, CyanStainedGlassPane, CyanTerracotta, CyanWool, DamagedAnvil, Dandelion, DarkOakBoat, DarkOakButton, DarkOakDoor, DarkOakFence, DarkOakFenceGate, DarkOakLeaves, DarkOakLog, DarkOakPlanks, DarkOakPressurePlate, DarkOakSapling, DarkOakSign, DarkOakSlab, DarkOakStairs, DarkOakTrapdoor, DarkOakWood, DarkPrismarine, DarkPrismarineSlab, DarkPrismarineStairs, DaylightDetector, DeadBrainCoral, DeadBrainCoralBlock, DeadBrainCoralFan, DeadBubbleCoral, DeadBubbleCoralBlock, DeadBubbleCoralFan, DeadBush, DeadFireCoral, DeadFireCoralBlock, DeadFireCoralFan, DeadHornCoral, DeadHornCoralBlock, DeadHornCoralFan, DeadTubeCoral, DeadTubeCoralBlock, DeadTubeCoralFan, DebugStick, DetectorRail, Diamond, DiamondAxe, DiamondBlock, DiamondBoots, DiamondChestplate, DiamondHelmet, DiamondHoe, DiamondHorseArmor, DiamondLeggings, DiamondOre, DiamondPickaxe, DiamondShovel, DiamondSword, Diorite, DioriteSlab, DioriteStairs, DioriteWall, Dirt, Dispenser, DolphinSpawnEgg, DonkeySpawnEgg, DragonBreath, DragonEgg, DragonHead, DriedKelp, DriedKelpBlock, Dropper, DrownedSpawnEgg, Egg, ElderGuardianSpawnEgg, Elytra, Emerald, EmeraldBlock, EmeraldOre, EnchantedBook, EnchantedGoldenApple, EnchantingTable, EndCrystal, EndPortalFrame, EndRod, EndStone, EndStoneBrickSlab, EndStoneBrickStairs, EndStoneBrickWall, EndStoneBricks, EnderChest, EnderEye, EnderPearl, EndermanSpawnEgg, EndermiteSpawnEgg, EvokerSpawnEgg, ExperienceBottle, Farmland, Feather, FermentedSpiderEye, Fern, FilledMap, FireCharge, FireCoral, FireCoralBlock, FireCoralFan, FireworkRocket, FireworkStar, FishingRod, FletchingTable, Flint, FlintAndSteel, FlowerBannerPattern, FlowerPot, FoxSpawnEgg, Furnace, FurnaceMinecart, GhastSpawnEgg, GhastTear, GildedBlackstone, Glass, GlassBottle, GlassPane, GlisteringMelonSlice, GlobeBannerPattern, Glowstone, GlowstoneDust, GoldBlock, GoldIngot, GoldNugget, GoldOre, GoldenApple, GoldenAxe, GoldenBoots, GoldenCarrot, GoldenChestplate, GoldenHelmet, GoldenHoe, GoldenHorseArmor, GoldenLeggings, GoldenPickaxe, GoldenShovel, GoldenSword, Granite, GraniteSlab, GraniteStairs, GraniteWall, Grass, GrassBlock, GrassPath, Gravel, GrayBanner, GrayBed, GrayCarpet, GrayConcrete, GrayConcretePowder, GrayDye, GrayGlazedTerracotta, GrayShulkerBox, GrayStainedGlass, GrayStainedGlassPane, GrayTerracotta, GrayWool, GreenBanner, GreenBed, GreenCarpet, GreenConcrete, GreenConcretePowder, GreenDye, GreenGlazedTerracotta, GreenShulkerBox, GreenStainedGlass, GreenStainedGlassPane, GreenTerracotta, GreenWool, Grindstone, GuardianSpawnEgg, Gunpowder, HayBale, HeartOfTheSea, HeavyWeightedPressurePlate, HoglinSpawnEgg, HoneyBlock, HoneyBottle, Honeycomb, HoneycombBlock, Hopper, HopperMinecart, HornCoral, HornCoralBlock, HornCoralFan, HorseSpawnEgg, HuskSpawnEgg, Ice, InfestedChiseledStoneBricks, InfestedCobblestone, InfestedCrackedStoneBricks, InfestedMossyStoneBricks, InfestedStone, InfestedStoneBricks, InkSac, IronAxe, IronBars, IronBlock, IronBoots, IronChestplate, IronDoor, IronHelmet, IronHoe, IronHorseArmor, IronIngot, IronLeggings, IronNugget, IronOre, IronPickaxe, IronShovel, IronSword, IronTrapdoor, ItemFrame, JackOLantern, Jigsaw, Jukebox, JungleBoat, JungleButton, JungleDoor, JungleFence, JungleFenceGate, JungleLeaves, JungleLog, JunglePlanks, JunglePressurePlate, JungleSapling, JungleSign, JungleSlab, JungleStairs, JungleTrapdoor, JungleWood, Kelp, KnowledgeBook, Ladder, Lantern, LapisBlock, LapisLazuli, LapisOre, LargeFern, LavaBucket, Lead, Leather, LeatherBoots, LeatherChestplate, LeatherHelmet, LeatherHorseArmor, LeatherLeggings, Lectern, Lever, LightBlueBanner, LightBlueBed, LightBlueCarpet, LightBlueConcrete, LightBlueConcretePowder, LightBlueDye, LightBlueGlazedTerracotta, LightBlueShulkerBox, LightBlueStainedGlass, LightBlueStainedGlassPane, LightBlueTerracotta, LightBlueWool, LightGrayBanner, LightGrayBed, LightGrayCarpet, LightGrayConcrete, LightGrayConcretePowder, LightGrayDye, LightGrayGlazedTerracotta, LightGrayShulkerBox, LightGrayStainedGlass, LightGrayStainedGlassPane, LightGrayTerracotta, LightGrayWool, LightWeightedPressurePlate, Lilac, LilyOfTheValley, LilyPad, LimeBanner, LimeBed, LimeCarpet, LimeConcrete, LimeConcretePowder, LimeDye, LimeGlazedTerracotta, LimeShulkerBox, LimeStainedGlass, LimeStainedGlassPane, LimeTerracotta, LimeWool, LingeringPotion, LlamaSpawnEgg, Lodestone, Loom, MagentaBanner, MagentaBed, MagentaCarpet, MagentaConcrete, MagentaConcretePowder, MagentaDye, MagentaGlazedTerracotta, MagentaShulkerBox, MagentaStainedGlass, MagentaStainedGlassPane, MagentaTerracotta, MagentaWool, MagmaBlock, MagmaCream, MagmaCubeSpawnEgg, Map, Melon, MelonSeeds, MelonSlice, MilkBucket, Minecart, MojangBannerPattern, MooshroomSpawnEgg, MossyCobblestone, MossyCobblestoneSlab, MossyCobblestoneStairs, MossyCobblestoneWall, MossyStoneBrickSlab, MossyStoneBrickStairs, MossyStoneBrickWall, MossyStoneBricks, MuleSpawnEgg, MushroomStem, MushroomStew, MusicDiscBlocks, MusicDiscCat, MusicDiscChirp, MusicDiscFar, MusicDiscMall, MusicDiscMellohi, MusicDiscPigstep, MusicDiscStal, MusicDiscStrad, MusicDiscWait, MusicDiscWard, MusicDisc11, MusicDisc13, Mutton, Mycelium, NameTag, NautilusShell, NetherBrick, NetherBrickFence, NetherBrickSlab, NetherBrickStairs, NetherBrickWall, NetherBricks, NetherGoldOre, NetherQuartzOre, NetherSprouts, NetherStar, NetherWart, NetherWartBlock, NetheriteAxe, NetheriteBlock, NetheriteBoots, NetheriteChestplate, NetheriteHelmet, NetheriteHoe, NetheriteIngot, NetheriteLeggings, NetheritePickaxe, NetheriteScrap, NetheriteShovel, NetheriteSword, Netherrack, NoteBlock, OakBoat, OakButton, OakDoor, OakFence, OakFenceGate, OakLeaves, OakLog, OakPlanks, OakPressurePlate, OakSapling, OakSign, OakSlab, OakStairs, OakTrapdoor, OakWood, Observer, Obsidian, OcelotSpawnEgg, OrangeBanner, OrangeBed, OrangeCarpet, OrangeConcrete, OrangeConcretePowder, OrangeDye, OrangeGlazedTerracotta, OrangeShulkerBox, OrangeStainedGlass, OrangeStainedGlassPane, OrangeTerracotta, OrangeTulip, OrangeWool, OxeyeDaisy, PackedIce, Painting, PandaSpawnEgg, Paper, ParrotSpawnEgg, Peony, PetrifiedOakSlab, PhantomMembrane, PhantomSpawnEgg, PigSpawnEgg, PiglinBannerPattern, PiglinSpawnEgg, PillagerSpawnEgg, PinkBanner, PinkBed, PinkCarpet, PinkConcrete, PinkConcretePowder, PinkDye, PinkGlazedTerracotta, PinkShulkerBox, PinkStainedGlass, PinkStainedGlassPane, PinkTerracotta, PinkTulip, PinkWool, Piston, PlayerHead, Podzol, PoisonousPotato, PolarBearSpawnEgg, PolishedAndesite, PolishedAndesiteSlab, PolishedAndesiteStairs, PolishedBasalt, PolishedBlackstone, PolishedBlackstoneBrickSlab, PolishedBlackstoneBrickStairs, PolishedBlackstoneBrickWall, PolishedBlackstoneBricks, PolishedBlackstoneButton, PolishedBlackstonePressurePlate, PolishedBlackstoneSlab, PolishedBlackstoneStairs, PolishedBlackstoneWall, PolishedDiorite, PolishedDioriteSlab, PolishedDioriteStairs, PolishedGranite, PolishedGraniteSlab, PolishedGraniteStairs, PoppedChorusFruit, Poppy, Porkchop, Potato, Potion, PoweredRail, Prismarine, PrismarineBrickSlab, PrismarineBrickStairs, PrismarineBricks, PrismarineCrystals, PrismarineShard, PrismarineSlab, PrismarineStairs, PrismarineWall, Pufferfish, PufferfishBucket, PufferfishSpawnEgg, Pumpkin, PumpkinPie, PumpkinSeeds, PurpleBanner, PurpleBed, PurpleCarpet, PurpleConcrete, PurpleConcretePowder, PurpleDye, PurpleGlazedTerracotta, PurpleShulkerBox, PurpleStainedGlass, PurpleStainedGlassPane, PurpleTerracotta, PurpleWool, PurpurBlock, PurpurPillar, PurpurSlab, PurpurStairs, Quartz, QuartzBlock, QuartzBricks, QuartzPillar, QuartzSlab, QuartzStairs, Rabbit, RabbitFoot, RabbitHide, RabbitSpawnEgg, RabbitStew, Rail, RavagerSpawnEgg, RedBanner, RedBed, RedCarpet, RedConcrete, RedConcretePowder, RedDye, RedGlazedTerracotta, RedMushroom, RedMushroomBlock, RedNetherBrickSlab, RedNetherBrickStairs, RedNetherBrickWall, RedNetherBricks, RedSand, RedSandstone, RedSandstoneSlab, RedSandstoneStairs, RedSandstoneWall, RedShulkerBox, RedStainedGlass, RedStainedGlassPane, RedTerracotta, RedTulip, RedWool, Redstone, RedstoneBlock, RedstoneLamp, RedstoneOre, RedstoneTorch, Repeater, RepeatingCommandBlock, RespawnAnchor, RoseBush, RottenFlesh, Saddle, Salmon, SalmonBucket, SalmonSpawnEgg, Sand, Sandstone, SandstoneSlab, SandstoneStairs, SandstoneWall, Scaffolding, Scute, SeaLantern, SeaPickle, Seagrass, Shears, SheepSpawnEgg, Shield, Shroomlight, ShulkerBox, ShulkerShell, ShulkerSpawnEgg, SilverfishSpawnEgg, SkeletonHorseSpawnEgg, SkeletonSkull, SkeletonSpawnEgg, SkullBannerPattern, SlimeBall, SlimeBlock, SlimeSpawnEgg, SmithingTable, Smoker, SmoothQuartz, SmoothQuartzSlab, SmoothQuartzStairs, SmoothRedSandstone, SmoothRedSandstoneSlab, SmoothRedSandstoneStairs, SmoothSandstone, SmoothSandstoneSlab, SmoothSandstoneStairs, SmoothStone, SmoothStoneSlab, Snow, SnowBlock, Snowball, SoulCampfire, SoulLantern, SoulSand, SoulSoil, SoulTorch, Spawner, SpectralArrow, SpiderEye, SpiderSpawnEgg, SplashPotion, Sponge, SpruceBoat, SpruceButton, SpruceDoor, SpruceFence, SpruceFenceGate, SpruceLeaves, SpruceLog, SprucePlanks, SprucePressurePlate, SpruceSapling, SpruceSign, SpruceSlab, SpruceStairs, SpruceTrapdoor, SpruceWood, SquidSpawnEgg, Stick, StickyPiston, Stone, StoneAxe, StoneBrickSlab, StoneBrickStairs, StoneBrickWall, StoneBricks, StoneButton, StoneHoe, StonePickaxe, StonePressurePlate, StoneShovel, StoneSlab, StoneStairs, StoneSword, Stonecutter, StraySpawnEgg, StriderSpawnEgg, String, StrippedAcaciaLog, StrippedAcaciaWood, StrippedBirchLog, StrippedBirchWood, StrippedCrimsonHyphae, StrippedCrimsonStem, StrippedDarkOakLog, StrippedDarkOakWood, StrippedJungleLog, StrippedJungleWood, StrippedOakLog, StrippedOakWood, StrippedSpruceLog, StrippedSpruceWood, StrippedWarpedHyphae, StrippedWarpedStem, StructureBlock, StructureVoid, Sugar, SugarCane, Sunflower, SuspiciousStew, SweetBerries, TallGrass, Target, Terracotta, TippedArrow, TNT, TNTMinecart, Torch, TotemOfUndying, TraderLlamaSpawnEgg, TrappedChest, Trident, TripwireHook, TropicalFish, TropicalFishBucket, TropicalFishSpawnEgg, TubeCoral, TubeCoralBlock, TubeCoralFan, TurtleEgg, TurtleHelmet, TurtleSpawnEgg, TwistingVines, VexSpawnEgg, VillagerSpawnEgg, VindicatorSpawnEgg, Vine, WanderingTraderSpawnEgg, WarpedButton, WarpedDoor, WarpedFence, WarpedFenceGate, WarpedFungus, WarpedFungusOnA_stick, WarpedHyphae, WarpedNylium, WarpedPlanks, WarpedPressurePlate, WarpedRoots, WarpedSign, WarpedSlab, WarpedStairs, WarpedStem, WarpedTrapdoor, WarpedWartBlock, WaterBucket, WeepingVines, WetSponge, Wheat, WheatSeeds, WhiteBanner, WhiteBed, WhiteCarpet, WhiteConcrete, WhiteConcretePowder, WhiteDye, WhiteGlazedTerracotta, WhiteShulkerBox, WhiteStainedGlass, WhiteStainedGlassPane, WhiteTerracotta, WhiteTulip, WhiteWool, WitchSpawnEgg, WitherRose, WitherSkeletonSkull, WitherSkeletonSpawnEgg, WolfSpawnEgg, WoodenAxe, WoodenHoe, WoodenPickaxe, WoodenShovel, WoodenSword, WritableBook, WrittenBook, YellowBanner, YellowBed, YellowCarpet, YellowConcrete, YellowConcretePowder, YellowDye, YellowGlazedTerracotta, YellowShulkerBox, YellowStainedGlass, YellowStainedGlassPane, YellowTerracotta, YellowWool, ZoglinSpawnEgg, ZombieHead, ZombieHorseSpawnEgg, ZombieSpawnEgg, ZombieVillagerSpawnEgg, ZombiePigmanSpawnEgg }; ================================================ FILE: src/Resources/Cuberite.rc ================================================ #pragma code_page(65001) // UTF-8 #include "winres.h" Favicon ICON "icon.ico" STRINGTABLE LANGUAGE LANG_CHINESE_SIMPLIFIED, SUBLANG_CHINESE_SIMPLIFIED BEGIN 1 "Cuberite" 2 "一个轻巧、快速、可扩展的Minecraftf游戏服务器" END STRINGTABLE LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK BEGIN 1 "Cuberite" 2 "A lightweight, fast and extensible game server for Minecraft" END #define VERSION 1,3,3,7 #define VERSION_STRING "1.3.3.7" #define INTERNAL_NAME "MCServer" #define ORIGINAL_FILENAME "Cuberite.exe" #ifdef NDEBUG #define FILE_FLAGS 0 #else #define FILE_FLAGS VS_FF_DEBUG #endif LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK VS_VERSION_INFO VERSIONINFO FILEVERSION VERSION PRODUCTVERSION VERSION FILEFLAGSMASK 0x3fL FILEFLAGS FILE_FLAGS FILEOS 0x40004L FILETYPE VFT_APP FILESUBTYPE 0 BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "080904B0" BEGIN VALUE "CompanyName", "Cuberite Contributors" VALUE "FileDescription", "Cuberite" VALUE "FileVersion", VERSION_STRING VALUE "InternalName", INTERNAL_NAME VALUE "OriginalFilename", ORIGINAL_FILENAME VALUE "ProductName", "Cuberite" VALUE "ProductVersion", VERSION_STRING END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x0809,1200, 0x0804,1200 END END LANGUAGE LANG_CHINESE_SIMPLIFIED, SUBLANG_CHINESE_SIMPLIFIED VS_VERSION_INFO VERSIONINFO FILEVERSION VERSION PRODUCTVERSION VERSION FILEFLAGSMASK 0x3fL FILEFLAGS FILE_FLAGS FILEOS 0x40004L FILETYPE VFT_APP FILESUBTYPE 0 BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "080404B0" BEGIN VALUE "CompanyName", "Cuberite 作者" VALUE "FileDescription", "Cuberite" VALUE "FileVersion", VERSION_STRING VALUE "InternalName", INTERNAL_NAME VALUE "OriginalFilename", ORIGINAL_FILENAME VALUE "ProductName", "Cuberite" VALUE "ProductVersion", VERSION_STRING END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x0804,1200, 0x0809,1200 END END ================================================ FILE: src/Root.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "Root.h" #include "main.h" // STD lib hreaders: #include // OS-specific headers: #if defined(_WIN32) #include #elif defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) #include #if defined(__linux__) #include #if !defined(__GLIBC__) #include #endif #elif defined(__APPLE__) #include #elif defined(__FreeBSD__) #include #include #include #include #endif #endif #include "Server.h" #include "World.h" #include "WebAdmin.h" #include "BrewingRecipes.h" #include "FurnaceRecipe.h" #include "CraftingRecipes.h" #include "Protocol/RecipeMapper.h" #include "Bindings/PluginManager.h" #include "MonsterConfig.h" #include "Entities/Player.h" #include "Blocks/BlockHandler.h" #include "Items/ItemHandler.h" #include "Chunk.h" #include "Protocol/ProtocolRecognizer.h" // for protocol version constants #include "CommandOutput.h" #include "DeadlockDetect.h" #include "LoggerListeners.h" #include "BuildInfo.h" #include "IniFile.h" #include "OverridesSettingsRepository.h" #include "Logger.h" #include "ClientHandle.h" #ifdef __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wglobal-constructors" #endif decltype(cRoot::s_Root) cRoot::s_Root; decltype(cRoot::s_NextState) cRoot::s_NextState; decltype(cRoot::s_StopEvent) cRoot::s_StopEvent; #ifdef __clang__ #pragma clang diagnostic pop #endif cRoot::cRoot(void) : m_pDefaultWorld(nullptr), m_Server(nullptr), m_MonsterConfig(nullptr), m_CraftingRecipes(nullptr), m_FurnaceRecipe(nullptr), m_BrewingRecipes(nullptr), m_WebAdmin(nullptr), m_PluginManager(nullptr), m_MojangAPI(nullptr) { s_Root = this; TransitionNextState(NextState::Run); } cRoot::~cRoot() { s_Root = nullptr; } bool cRoot::Run(cSettingsRepositoryInterface & a_OverridesRepo) { auto consoleLogListener = MakeConsoleListener(g_RunAsService); auto consoleAttachment = cLogger::GetInstance().AttachListener(std::move(consoleLogListener)); cLogger::cAttachment fileAttachment; if (!a_OverridesRepo.HasValue("Server","DisableLogFile")) { auto fileLogListenerRet = MakeFileListener(); if (!fileLogListenerRet.first) { throw std::runtime_error("failed to open log file"); } fileAttachment = cLogger::GetInstance().AttachListener(std::move(fileLogListenerRet.second)); } LOG("--- Started Log ---"); #ifdef BUILD_ID LOG("Cuberite " BUILD_SERIES_NAME " (id: " BUILD_ID ")"); LOG("from commit " BUILD_COMMIT_ID " built at: " BUILD_DATETIME); #endif cDeadlockDetect dd; auto BeginTime = std::chrono::steady_clock::now(); LoadGlobalSettings(); LOG("Creating new server instance..."); m_Server = new cServer(); LOG("Reading server config..."); m_SettingsFilename = "settings.ini"; if (a_OverridesRepo.HasValue("Server","ConfigFile")) { m_SettingsFilename = a_OverridesRepo.GetValue("Server","ConfigFile"); } auto IniFile = std::make_unique(); bool IsNewIniFile = !IniFile->ReadFile(m_SettingsFilename); if (IsNewIniFile) { LOGWARN("Regenerating settings.ini, all settings will be reset"); IniFile->AddHeaderComment(" This is the main server configuration"); IniFile->AddHeaderComment(" Most of the settings here can be configured using the webadmin interface, if enabled in webadmin.ini"); } auto settingsRepo = std::make_unique(std::move(IniFile), a_OverridesRepo); LOG("Starting server..."); // cClientHandle::FASTBREAK_PERCENTAGE = settingsRepo->GetValueSetI("AntiCheat", "FastBreakPercentage", 97) / 100.0f; cClientHandle::FASTBREAK_PERCENTAGE = 0; // AntiCheat disabled due to bugs. We will enabled it once they are fixed. See #3506. m_MojangAPI = new cMojangAPI; bool ShouldAuthenticate = settingsRepo->GetValueSetB("Authentication", "Authenticate", true); m_MojangAPI->Start(*settingsRepo, ShouldAuthenticate); // Mojang API needs to be started before plugins, so that plugins may use it for DB upgrades on server init if (!m_Server->InitServer(*settingsRepo, ShouldAuthenticate)) { settingsRepo->Flush(); throw std::runtime_error("failure starting server"); } m_WebAdmin = new cWebAdmin(); m_WebAdmin->Init(); LOGD("Loading settings..."); m_RankManager.reset(new cRankManager()); m_RankManager->Initialize(*m_MojangAPI); m_CraftingRecipes = new cCraftingRecipes(); m_RecipeMapper.reset(new cRecipeMapper()); m_FurnaceRecipe = new cFurnaceRecipe(); m_BrewingRecipes.reset(new cBrewingRecipes()); LOGD("Loading worlds..."); LoadWorlds(dd, *settingsRepo, IsNewIniFile); LOGD("Loading plugin manager..."); m_PluginManager = new cPluginManager(dd); m_PluginManager->ReloadPluginsNow(*settingsRepo); LOGD("Loading MonsterConfig..."); m_MonsterConfig = new cMonsterConfig; // This sets stuff in motion LOGD("Starting Authenticator..."); m_Authenticator.Start(*settingsRepo); LOGD("Starting worlds..."); StartWorlds(dd); if (settingsRepo->GetValueSetB("DeadlockDetect", "Enabled", true)) { LOGD("Starting deadlock detector..."); dd.Start(settingsRepo->GetValueSetI("DeadlockDetect", "IntervalSec", 20)); } settingsRepo->Flush(); LOGD("Finalising startup..."); if (m_Server->Start()) { m_WebAdmin->Start(); LOG("Startup complete, took %ldms!", static_cast(std::chrono::duration_cast(std::chrono::steady_clock::now() - BeginTime).count())); // Save the current time m_StartTime = std::chrono::steady_clock::now(); HandleInput(); s_StopEvent.Wait(); // Stop the server: m_WebAdmin->Stop(); LOG("Shutting down server..."); m_Server->Shutdown(); } // if (m_Server->Start() delete m_MojangAPI; m_MojangAPI = nullptr; LOGD("Shutting down deadlock detector..."); dd.Stop(); LOGD("Stopping world threads..."); StopWorlds(dd); LOGD("Stopping authenticator..."); m_Authenticator.Stop(); LOGD("Freeing MonsterConfig..."); delete m_MonsterConfig; m_MonsterConfig = nullptr; delete m_WebAdmin; m_WebAdmin = nullptr; LOGD("Unloading recipes..."); delete m_FurnaceRecipe; m_FurnaceRecipe = nullptr; delete m_CraftingRecipes; m_CraftingRecipes = nullptr; LOGD("Stopping plugin manager..."); delete m_PluginManager; m_PluginManager = nullptr; LOG("Cleaning up..."); delete m_Server; m_Server = nullptr; LOG("Shutdown successful!"); LOG("--- Stopped Log ---"); return s_NextState == NextState::Restart; } void cRoot::Stop() { TransitionNextState(NextState::Stop); } void cRoot::Restart() { TransitionNextState(NextState::Restart); } void cRoot::LoadGlobalSettings() { // Nothing needed yet } void cRoot::LoadWorlds(cDeadlockDetect & a_dd, cSettingsRepositoryInterface & a_Settings, bool a_IsNewIniFile) { if (a_IsNewIniFile) { a_Settings.AddValue("Worlds", "DefaultWorld", "world"); a_Settings.AddValue("Worlds", "World", "world_nether"); a_Settings.AddValue("Worlds", "World", "world_the_end"); a_Settings.AddValue("WorldPaths", "world", "world"); a_Settings.AddValue("WorldPaths", "world_nether", "world_nether"); a_Settings.AddValue("WorldPaths", "world_the_end", "world_the_end"); const AStringVector WorldNames{ "world", "world_nether", "world_the_end" }; m_pDefaultWorld = &m_WorldsByName.try_emplace("world", "world", "world", a_dd, WorldNames).first->second; m_WorldsByName.try_emplace("world_nether", "world_nether", "world_nether", a_dd, WorldNames, dimNether, "world"); m_WorldsByName.try_emplace("world_the_end", "world_the_end", "world_the_end", a_dd, WorldNames, dimEnd, "world"); return; } // Build a list of all world names auto Worlds = a_Settings.GetValues("Worlds"); AStringVector WorldNames(Worlds.size()); for (const auto & World : Worlds) { WorldNames.push_back(World.second); } // Get the default world AString DefaultWorldName = a_Settings.GetValueSet("Worlds", "DefaultWorld", "world"); AString DefaultWorldPath = a_Settings.GetValueSet("WorldPaths", DefaultWorldName, DefaultWorldName); m_pDefaultWorld = &m_WorldsByName.try_emplace(DefaultWorldName, DefaultWorldName, DefaultWorldPath, a_dd, WorldNames).first->second; // Then load the other worlds if (Worlds.size() <= 0) { return; } /* Here are the world creation rules. Note that these only apply for a world which is in settings.ini but has no world.ini file. If an ini file is present, it overrides the world linkages and the dimension type in cWorld::start() The creation rules are as follows: - If a world exists in settings.ini but has no world.ini, then: - If the world name is x_nether, create a world.ini with the dimension type "nether". - If a world called x exists, set it as x_nether's overworld. - Otherwise set the default world as x_nether's overworld. - If the world name is x_the_end or x_end, create a world.ini with the dimension type "end". - If a world called x exists, set it as x_the_end's overworld. - Otherwise set the default world as x_the_end's overworld. - If the world name is x (and doesn't end with _the_end, _end or _nether) - Create a world.ini with a dimension type of "overworld". - If a world called x_nether exists, set it as x's nether world. - Otherwise set x's nether world to blank.h - If a world called x_the_end or x_end exists, set it as x's end world. - Otherwise set x's nether world to blank. */ bool FoundAdditionalWorlds = false; for (const auto & WorldNameValue : Worlds) { AString ValueName = WorldNameValue.first; if (ValueName.compare("World") != 0) { continue; } AString WorldName = WorldNameValue.second; if (WorldName.empty()) { continue; } FoundAdditionalWorlds = true; AString LowercaseName = StrToLower(WorldName); AString WorldPath = a_Settings.GetValueSet("WorldPaths", WorldName, WorldName); AString NetherAppend = "_nether"; AString EndAppend1 = "_the_end"; AString EndAppend2 = "_end"; // The default world is an overworld with no links eDimension Dimension = dimOverworld; AString LinkTo; // if the world is called x_nether if ((LowercaseName.size() > NetherAppend.size()) && (LowercaseName.substr(LowercaseName.size() - NetherAppend.size()) == NetherAppend)) { // The world is called x_nether, see if a world called x exists. If yes, choose it as the linked world, // otherwise, choose the default world as the linked world. // As before, any ini settings will completely override this if an ini is already present. LinkTo = WorldName.substr(0, WorldName.size() - NetherAppend.size()); if (GetWorld(LinkTo) == nullptr) { LinkTo = DefaultWorldName; } Dimension = dimNether; } // if the world is called x_the_end else if ((LowercaseName.size() > EndAppend1.size()) && (LowercaseName.substr(LowercaseName.size() - EndAppend1.size()) == EndAppend1)) { // The world is called x_the_end, see if a world called x exists. If yes, choose it as the linked world, // otherwise, choose the default world as the linked world. // As before, any ini settings will completely override this if an ini is already present. LinkTo = WorldName.substr(0, WorldName.size() - EndAppend1.size()); if (GetWorld(LinkTo) == nullptr) { LinkTo = DefaultWorldName; } Dimension = dimEnd; } // if the world is called x_end else if ((LowercaseName.size() > EndAppend2.size()) && (LowercaseName.substr(LowercaseName.size() - EndAppend2.size()) == EndAppend2)) { // The world is called x_end, see if a world called x exists. If yes, choose it as the linked world, // otherwise, choose the default world as the linked world. // As before, any ini settings will completely override this if an ini is already present. LinkTo = WorldName.substr(0, WorldName.size() - EndAppend2.size()); if (GetWorld(LinkTo) == nullptr) { LinkTo = DefaultWorldName; } Dimension = dimEnd; } m_WorldsByName.try_emplace(WorldName, WorldName, WorldPath, a_dd, WorldNames, Dimension, LinkTo); } // for i - Worlds if (!FoundAdditionalWorlds) { if (a_Settings.GetKeyComment("Worlds", 0) != " World=secondworld") { a_Settings.DeleteKeyComment("Worlds", 0); a_Settings.AddKeyComment("Worlds", " World=secondworld"); } } } void cRoot::StartWorlds(cDeadlockDetect & a_DeadlockDetect) { for (auto & Entry : m_WorldsByName) { auto & World = Entry.second; World.Start(); World.InitializeSpawn(); m_PluginManager->CallHookWorldStarted(World); } } void cRoot::StopWorlds(cDeadlockDetect & a_DeadlockDetect) { for (auto & Entry : m_WorldsByName) { Entry.second.Stop(a_DeadlockDetect); } } cWorld * cRoot::GetDefaultWorld() { ASSERT(m_pDefaultWorld != nullptr); return m_pDefaultWorld; } cWorld * cRoot::GetWorld(const AString & a_WorldName) { const auto FindResult = m_WorldsByName.find(a_WorldName); if (FindResult != m_WorldsByName.cend()) { return &FindResult->second; } return nullptr; } bool cRoot::ForEachWorld(cWorldListCallback a_Callback) { for (auto & World : m_WorldsByName) { if (a_Callback(World.second)) { return false; } } return true; } void cRoot::QueueExecuteConsoleCommand(const AString & a_Cmd, cCommandOutputCallback & a_Output) { const auto KickPlayers = [this] { // Kick all players from the server with custom disconnect message bool SentDisconnect = false; cRoot::Get()->ForEachPlayer( [&](cPlayer & a_Player) { a_Player.GetClientHandle()->Kick(m_Server->GetShutdownMessage()); SentDisconnect = true; return false; } ); if (SentDisconnect) { std::this_thread::sleep_for(std::chrono::seconds(1)); } }; // Some commands are built-in: if (a_Cmd == "stop") { KickPlayers(); cRoot::Stop(); return; } else if (a_Cmd == "restart") { KickPlayers(); cRoot::Restart(); return; } LOG("Executing console command: \"%s\"", a_Cmd.c_str()); m_Server->ExecuteConsoleCommand(a_Cmd, a_Output); } void cRoot::QueueExecuteConsoleCommand(const AString & a_Cmd) { // Put the command into a queue (Alleviates FS #363): QueueExecuteConsoleCommand(a_Cmd, *new cLogCommandDeleteSelfOutputCallback); } void cRoot::KickUser(int a_ClientID, const AString & a_Reason) { m_Server->KickUser(a_ClientID, a_Reason); } size_t cRoot::GetTotalChunkCount(void) { size_t Count = 0; for (const auto & Entry : m_WorldsByName) { Count += Entry.second.GetNumChunks(); } return Count; } void cRoot::SaveAllChunks(void) { for (auto & Entry : m_WorldsByName) { Entry.second.QueueSaveAllChunks(); } } void cRoot::SaveAllChunksNow(void) { for (auto & Entry : m_WorldsByName) { Entry.second.SaveAllChunks(); } } void cRoot::SetSavingEnabled(bool a_SavingEnabled) { for (auto & Entry : m_WorldsByName) { Entry.second.SetSavingEnabled(a_SavingEnabled); } } void cRoot::SendPlayerLists(cPlayer * a_DestPlayer) { for (auto & Entry : m_WorldsByName) { Entry.second.SendPlayerList(a_DestPlayer); } } void cRoot::BroadcastPlayerListsAddPlayer(const cPlayer & a_Player, const cClientHandle * a_Exclude) { for (auto & Entry : m_WorldsByName) { Entry.second.BroadcastPlayerListAddPlayer(a_Player); } } void cRoot::BroadcastPlayerListsRemovePlayer(const cPlayer & a_Player, const cClientHandle * a_Exclude) { for (auto & Entry : m_WorldsByName) { Entry.second.BroadcastPlayerListRemovePlayer(a_Player); } } void cRoot::BroadcastPlayerListsHeaderFooter(const cCompositeChat & a_Header, const cCompositeChat & a_Footer) { for (auto & Entry : m_WorldsByName) { Entry.second.BroadcastPlayerListHeaderFooter(a_Header, a_Footer); } } void cRoot::BroadcastChat(const AString & a_Message, eMessageType a_ChatPrefix) { for (auto & Entry : m_WorldsByName) { Entry.second.BroadcastChat(a_Message, nullptr, a_ChatPrefix); } } void cRoot::BroadcastChat(const cCompositeChat & a_Message) { for (auto & Entry : m_WorldsByName) { Entry.second.BroadcastChat(a_Message); } } bool cRoot::ForEachPlayer(cPlayerListCallback a_Callback) { for (auto & Entry : m_WorldsByName) { if (!Entry.second.ForEachPlayer(a_Callback)) { return false; } } return true; } bool cRoot::FindAndDoWithPlayer(const AString & a_PlayerName, cPlayerListCallback a_Callback) { class cCallback { size_t m_BestRating; size_t m_NameLength; const AString m_PlayerName; public: bool operator () (cPlayer & a_Player) { size_t Rating = RateCompareString (m_PlayerName, a_Player.GetName()); if ((Rating > 0) && (Rating >= m_BestRating)) { m_BestMatch = a_Player.GetName(); if (Rating > m_BestRating) { m_NumMatches = 0; } m_BestRating = Rating; ++m_NumMatches; } return (Rating == m_NameLength); // Perfect match } cCallback (const AString & a_CBPlayerName) : m_BestRating(0), m_NameLength(a_CBPlayerName.length()), m_PlayerName(a_CBPlayerName), m_BestMatch(), m_NumMatches(0) {} AString m_BestMatch; unsigned m_NumMatches; } Callback (a_PlayerName); ForEachPlayer(Callback); if (Callback.m_NumMatches == 1) { return DoWithPlayer(Callback.m_BestMatch, a_Callback); } return false; } bool cRoot::DoWithPlayerByUUID(const cUUID & a_PlayerUUID, cPlayerListCallback a_Callback) { for (auto & Entry : m_WorldsByName) { if (Entry.second.DoWithPlayerByUUID(a_PlayerUUID, a_Callback)) { return true; } } return false; } bool cRoot::DoWithPlayer(const AString & a_PlayerName, cPlayerListCallback a_Callback) { for (auto & Entry : m_WorldsByName) { if (Entry.second.DoWithPlayer(a_PlayerName, a_Callback)) { return true; } } return false; } AString cRoot::GetProtocolVersionTextFromInt(int a_ProtocolVersion) { return cMultiVersionProtocol::GetVersionTextFromInt(static_cast(a_ProtocolVersion)); } int cRoot::GetVirtualRAMUsage(void) { #ifdef _WIN32 PROCESS_MEMORY_COUNTERS_EX pmc; if (GetProcessMemoryInfo(GetCurrentProcess(), (PROCESS_MEMORY_COUNTERS *)&pmc, sizeof(pmc))) { return (int)(pmc.PrivateUsage / 1024); } return -1; #elif defined(__linux__) // Code adapted from https://stackoverflow.com/questions/63166/how-to-determine-cpu-and-memory-consumption-from-inside-a-process std::ifstream StatFile("/proc/self/status"); if (!StatFile.good()) { return -1; } while (StatFile.good()) { AString Line; std::getline(StatFile, Line); if (strncmp(Line.c_str(), "VmSize:", 7) == 0) { int res = atoi(Line.c_str() + 8); return (res == 0) ? -1 : res; // If parsing failed, return -1 } } return -1; #elif defined (__APPLE__) // Code adapted from https://stackoverflow.com/questions/63166/how-to-determine-cpu-and-memory-consumption-from-inside-a-process struct task_basic_info t_info; mach_msg_type_number_t t_info_count = TASK_BASIC_INFO_COUNT; if (KERN_SUCCESS == task_info( mach_task_self(), TASK_BASIC_INFO, reinterpret_cast(&t_info), &t_info_count )) { return static_cast(t_info.virtual_size / 1024); } return -1; #else LOGINFO("%s: Unknown platform, cannot query memory usage", __FUNCTION__); return -1; #endif } int cRoot::GetPhysicalRAMUsage(void) { #ifdef _WIN32 PROCESS_MEMORY_COUNTERS pmc; if (GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc))) { return (int)(pmc.WorkingSetSize / 1024); } return -1; #elif defined(__linux__) // Code adapted from https://stackoverflow.com/questions/63166/how-to-determine-cpu-and-memory-consumption-from-inside-a-process std::ifstream StatFile("/proc/self/status"); if (!StatFile.good()) { return -1; } while (StatFile.good()) { AString Line; std::getline(StatFile, Line); if (strncmp(Line.c_str(), "VmRSS:", 6) == 0) { int res = atoi(Line.c_str() + 7); return (res == 0) ? -1 : res; // If parsing failed, return -1 } } return -1; #elif defined (__APPLE__) // Code adapted from https://stackoverflow.com/questions/63166/how-to-determine-cpu-and-memory-consumption-from-inside-a-process struct task_basic_info t_info; mach_msg_type_number_t t_info_count = TASK_BASIC_INFO_COUNT; if (KERN_SUCCESS == task_info( mach_task_self(), TASK_BASIC_INFO, reinterpret_cast(&t_info), &t_info_count )) { return static_cast(t_info.resident_size / 1024); } return -1; #elif defined (__FreeBSD__) /* struct rusage self_usage; int status = getrusage(RUSAGE_SELF, &self_usage); if (!status) { return static_cast(self_usage.ru_maxrss); } return -1; */ // Good to watch: https://www.youtube.com/watch?v=Os5cK0H8EOA - getrusage. // Unfortunately, it only gives peak memory usage a.k.a max resident set size // So it is better to use FreeBSD kvm function to get the size of resident pages. static kvm_t* kd = NULL; if (kd == NULL) { kd = kvm_open(NULL, "/dev/null", NULL, O_RDONLY, "kvm_open"); // returns a descriptor used to access kernel virtual memory } if (kd != NULL) { int pc = 0; // number of processes found struct kinfo_proc* kp; kp = kvm_getprocs(kd, KERN_PROC_PID, getpid(), &pc); if ((kp != NULL) && (pc >= 1)) { return static_cast(kp->ki_rssize * getpagesize() / 1024); } } return -1; #else LOGINFO("%s: Unknown platform, cannot query memory usage", __FUNCTION__); return -1; #endif } void cRoot::LogChunkStats(cCommandOutputCallback & a_Output) { int SumNumValid = 0; int SumNumDirty = 0; int SumNumInLighting = 0; size_t SumNumInGenerator = 0; int SumMem = 0; for (auto & Entry : m_WorldsByName) { auto & World = Entry.second; const auto NumInGenerator = World.GetGeneratorQueueLength(); const auto NumInSaveQueue = World.GetStorageSaveQueueLength(); const auto NumInLoadQueue = World.GetStorageLoadQueueLength(); int NumValid = 0; int NumDirty = 0; int NumInLighting = 0; World.GetChunkStats(NumValid, NumDirty, NumInLighting); a_Output.OutLn(fmt::format(FMT_STRING("World {}:"), World.GetName())); a_Output.OutLn(fmt::format(FMT_STRING(" Num loaded chunks: {}"), NumValid)); a_Output.OutLn(fmt::format(FMT_STRING(" Num dirty chunks: {}"), NumDirty)); a_Output.OutLn(fmt::format(FMT_STRING(" Num chunks in lighting queue: {}"), NumInLighting)); a_Output.OutLn(fmt::format(FMT_STRING(" Num chunks in generator queue: {}"), NumInGenerator)); a_Output.OutLn(fmt::format(FMT_STRING(" Num chunks in storage load queue: {}"), NumInLoadQueue)); a_Output.OutLn(fmt::format(FMT_STRING(" Num chunks in storage save queue: {}"), NumInSaveQueue)); int Mem = NumValid * static_cast(sizeof(cChunk)); a_Output.OutLn(fmt::format(FMT_STRING(" Memory used by chunks: {} KiB ({} MiB)"), (Mem + 1023) / 1024, (Mem + 1024 * 1024 - 1) / (1024 * 1024))); SumNumValid += NumValid; SumNumDirty += NumDirty; SumNumInLighting += NumInLighting; SumNumInGenerator += NumInGenerator; SumMem += Mem; } a_Output.OutLn("Totals:"); a_Output.OutLn(fmt::format(FMT_STRING(" Num loaded chunks: {}"), SumNumValid)); a_Output.OutLn(fmt::format(FMT_STRING(" Num dirty chunks: {}"), SumNumDirty)); a_Output.OutLn(fmt::format(FMT_STRING(" Num chunks in lighting queue: {}"), SumNumInLighting)); a_Output.OutLn(fmt::format(FMT_STRING(" Num chunks in generator queue: {}"), SumNumInGenerator)); a_Output.OutLn(fmt::format(FMT_STRING(" Memory used by chunks: {} KiB ({} MiB)"), (SumMem + 1023) / 1024, (SumMem + 1024 * 1024 - 1) / (1024 * 1024))); a_Output.OutLn("Per-chunk memory size breakdown:"); a_Output.OutLn(fmt::format(FMT_STRING(" block types: {:06} bytes ({:3} KiB)"), sizeof(cChunkDef::BlockTypes), (sizeof(cChunkDef::BlockTypes) + 1023) / 1024)); a_Output.OutLn(fmt::format(FMT_STRING(" block metadata: {:06} bytes ({:3} KiB)"), sizeof(cChunkDef::BlockNibbles), (sizeof(cChunkDef::BlockNibbles) + 1023) / 1024)); a_Output.OutLn(fmt::format(FMT_STRING(" block lighting: {:06} bytes ({:3} KiB)"), 2 * sizeof(cChunkDef::BlockNibbles), (2 * sizeof(cChunkDef::BlockNibbles) + 1023) / 1024)); a_Output.OutLn(fmt::format(FMT_STRING(" heightmap: {:06} bytes ({:3} KiB)"), sizeof(cChunkDef::HeightMap), (sizeof(cChunkDef::HeightMap) + 1023) / 1024)); a_Output.OutLn(fmt::format(FMT_STRING(" biomemap: {:06} bytes ({:3} KiB)"), sizeof(cChunkDef::BiomeMap), (sizeof(cChunkDef::BiomeMap) + 1023) / 1024)); } int cRoot::GetFurnaceFuelBurnTime(const cItem & a_Fuel) { cFurnaceRecipe * FR = Get()->GetFurnaceRecipe(); return FR->GetBurnTime(a_Fuel); } AStringVector cRoot::GetPlayerTabCompletionMultiWorld(const AString & a_Text) { AStringVector Results; ForEachWorld([&](cWorld & a_World) { a_World.TabCompleteUserName(a_Text, Results); return false; } ); return Results; } void cRoot::HandleInput() { if (g_RunAsService || g_DetachedStdin) { // Ignore input when running as a service, cin was never opened in that case: return; } cLogCommandOutputCallback Output; AString Command; while (s_NextState == NextState::Run) { #ifndef _WIN32 timeval Timeout{ 0, 0 }; Timeout.tv_usec = 100 * 1000; // 100 msec fd_set ReadSet; FD_ZERO(&ReadSet); FD_SET(STDIN_FILENO, &ReadSet); if (select(STDIN_FILENO + 1, &ReadSet, nullptr, nullptr, &Timeout) <= 0) { // Don't call getline because there's nothing to read continue; } #endif if (!std::getline(std::cin, Command)) { cRoot::Stop(); return; } if (s_NextState != NextState::Run) { // Already shutting down, can't execute commands break; } if (!Command.empty()) { // Execute and clear command string when submitted QueueExecuteConsoleCommand(TrimString(Command), Output); } } } void cRoot::TransitionNextState(NextState a_NextState) { { auto Current = s_NextState.load(); do { // Stopping is final, so stops override restarts: if (Current == NextState::Stop) { return; } } while (!s_NextState.compare_exchange_strong(Current, a_NextState)); } if (s_NextState == NextState::Run) { return; } s_StopEvent.Set(); #ifdef WIN32 DWORD Length; INPUT_RECORD Record { KEY_EVENT, { { TRUE, 1, VK_RETURN, static_cast(MapVirtualKey(VK_RETURN, MAPVK_VK_TO_VSC)), { { VK_RETURN } }, 0 } } }; // Can't kill the input thread since it breaks cin (getline doesn't block / receive input on restart) // Apparently no way to unblock getline apart from CancelIoEx, but xoft wants Windows XP support // Only thing I can think of for now. Also, ignore the retval since sometimes there's no cin. WriteConsoleInput(GetStdHandle(STD_INPUT_HANDLE), &Record, 1, &Length); #endif } ================================================ FILE: src/Root.h ================================================ #pragma once #include "Defines.h" #include "FunctionRef.h" #include "HTTP/HTTPServer.h" #include "Protocol/Authenticator.h" #include "Protocol/MojangAPI.h" #include "RankManager.h" #include "ChunkDef.h" // fwd: class cItem; class cMonsterConfig; class cBrewingRecipes; class cCraftingRecipes; class cRecipeMapper; class cFurnaceRecipe; class cWebAdmin; class cPluginManager; class cServer; class cWorld; class cPlayer; class cCommandOutputCallback; class cCompositeChat; class cSettingsRepositoryInterface; class cDeadlockDetect; class cUUID; class BlockTypePalette; class ProtocolPalettes; using cPlayerListCallback = cFunctionRef; using cWorldListCallback = cFunctionRef; namespace Json { class Value; } /** The root of the object hierarchy */ // tolua_begin class cRoot { public: static cRoot * Get() { return s_Root; } // tolua_end /** which ini file to load settings from, default is settings.ini */ AString m_SettingsFilename; cRoot(void); ~cRoot(); /** Run the server. Returns true if we should restart, false to quit. */ bool Run(cSettingsRepositoryInterface & a_OverridesRepo); /** Interrupts the server and stops it, as if "/stop" typed in the console. */ static void Stop(); /** Interrupts the server and restarts it, as if "/restart" was typed in the console. */ static void Restart(); // tolua_begin cServer * GetServer(void) { return m_Server; } cWorld * GetDefaultWorld(void); /** Returns a pointer to the world specified. If no world of that name exists, returns a nullptr. */ cWorld * GetWorld(const AString & a_WorldName); /** Returns the up time of the server in seconds */ int GetServerUpTime(void) { return static_cast(std::chrono::duration_cast(std::chrono::steady_clock::now() - m_StartTime).count()); } // tolua_end /** Calls the callback for each world; returns true if the callback didn't abort (return true) */ bool ForEachWorld(cWorldListCallback a_Callback); // >> Exported in ManualBindings << /** Writes chunkstats, for each world and totals, to the output callback */ void LogChunkStats(cCommandOutputCallback & a_Output); cMonsterConfig * GetMonsterConfig(void) { return m_MonsterConfig; } cCraftingRecipes * GetCraftingRecipes(void) { return m_CraftingRecipes; } // tolua_export cRecipeMapper * GetRecipeMapper(void) { return m_RecipeMapper.get(); } cFurnaceRecipe * GetFurnaceRecipe (void) { return m_FurnaceRecipe; } // Exported in ManualBindings.cpp with quite a different signature cBrewingRecipes * GetBrewingRecipes (void) { return m_BrewingRecipes.get(); } // Exported in ManualBindings.cpp /** Returns the (read-write) storage for registered block types. */ // BlockTypeRegistry & GetBlockTypeRegistry() { return m_BlockTypeRegistry; } /** Returns the number of ticks for how long the item would fuel a furnace. Returns zero if not a fuel */ static int GetFurnaceFuelBurnTime(const cItem & a_Fuel); // tolua_export /** Returns the completions for a player name across all worlds. Returns an empty vector if none are found. */ AStringVector GetPlayerTabCompletionMultiWorld(const AString & a_Text); /** The current time where the startup of the server has been completed */ std::chrono::steady_clock::time_point m_StartTime; cWebAdmin * GetWebAdmin (void) { return m_WebAdmin; } // tolua_export cPluginManager * GetPluginManager (void) { return m_PluginManager; } // tolua_export cAuthenticator & GetAuthenticator (void) { return m_Authenticator; } cMojangAPI & GetMojangAPI (void) { return *m_MojangAPI; } cRankManager * GetRankManager (void) { return m_RankManager.get(); } /** Queues a console command for execution through the cServer class. The command will be executed in the tick thread The command's output will be written to the a_Output callback "stop" and "restart" commands have special handling. */ void QueueExecuteConsoleCommand(const AString & a_Cmd, cCommandOutputCallback & a_Output); /** Queues a console command for execution through the cServer class. The command will be executed in the tick thread The command's output will be sent to console "stop" and "restart" commands have special handling. */ void QueueExecuteConsoleCommand(const AString & a_Cmd); // tolua_export /** Kicks the user, no matter in what world they are. Used from cAuthenticator */ void KickUser(int a_ClientID, const AString & a_Reason); /** Returns the number of chunks loaded */ size_t GetTotalChunkCount(void); // tolua_export /** Saves all chunks in all worlds */ void SaveAllChunks(void); // tolua_export /** Saves all chunks in all worlds synchronously (waits until dirty chunks have been sent to the ChunkStorage queue before returning) */ void SaveAllChunksNow(void); /** Sets whether saving chunks is enabled in all worlds (overrides however the worlds were already set) */ void SetSavingEnabled(bool a_SavingEnabled); // tolua_export /** Calls the callback for each player in all worlds */ bool ForEachPlayer(cPlayerListCallback a_Callback); // >> EXPORTED IN MANUALBINDINGS << /** Finds a player from a partial or complete player name and calls the callback - case-insensitive */ bool FindAndDoWithPlayer(const AString & a_PlayerName, cPlayerListCallback a_Callback); // >> EXPORTED IN MANUALBINDINGS << /** Finds the player over his uuid and calls the callback */ bool DoWithPlayerByUUID(const cUUID & a_PlayerUUID, cPlayerListCallback a_Callback); // >> EXPORTED IN MANUALBINDINGS << /** Finds the player using it's complete username and calls the callback */ bool DoWithPlayer(const AString & a_PlayerName, cPlayerListCallback a_Callback); /** Send playerlist of all worlds to player */ void SendPlayerLists(cPlayer * a_DestPlayer); /** Broadcast playerlist addition through all worlds */ void BroadcastPlayerListsAddPlayer(const cPlayer & a_Player, const cClientHandle * a_Exclude = nullptr); /** Broadcast playerlist removal through all worlds */ void BroadcastPlayerListsRemovePlayer(const cPlayer & a_Player, const cClientHandle * a_Exclude = nullptr); /** Broadcast playerlist header and footer through all worlds */ void BroadcastPlayerListsHeaderFooter(const cCompositeChat & a_Header, const cCompositeChat & a_Footer); // tolua_export // tolua_begin /** Sends a chat message to all connected clients (in all worlds) */ void BroadcastChat (const AString & a_Message, eMessageType a_ChatPrefix = mtCustom); void BroadcastChat (const cCompositeChat & a_Message); void BroadcastChatDeath (const AString & a_Message) { BroadcastChat(a_Message, mtDeath); } void BroadcastChatFailure(const AString & a_Message) { BroadcastChat(a_Message, mtFailure); } void BroadcastChatFatal (const AString & a_Message) { BroadcastChat(a_Message, mtFailure); } void BroadcastChatInfo (const AString & a_Message) { BroadcastChat(a_Message, mtInformation); } void BroadcastChatJoin (const AString & a_Message) { BroadcastChat(a_Message, mtJoin); } void BroadcastChatLeave (const AString & a_Message) { BroadcastChat(a_Message, mtLeave); } void BroadcastChatSuccess(const AString & a_Message) { BroadcastChat(a_Message, mtSuccess); } void BroadcastChatWarning(const AString & a_Message) { BroadcastChat(a_Message, mtWarning); } /** Returns the textual description of the protocol version: 49 -> "1.4.4". Provided specifically for Lua API */ static AString GetProtocolVersionTextFromInt(int a_ProtocolVersionNum); /** Returns the amount of virtual RAM used, in KiB. Returns a negative number on error */ static int GetVirtualRAMUsage(void); /** Returns the amount of virtual RAM used, in KiB. Returns a negative number on error */ static int GetPhysicalRAMUsage(void); // tolua_end private: /** States that the global cRoot can be in. You can transition freely between Run and Restart, but the server unconditionally terminates in Stop. */ enum class NextState { Run, Restart, Stop }; typedef std::map WorldMap; /** Blocking reads and processes console input. */ void HandleInput(); /** Performs run state transition, enforcing guarantees about state transitions. */ static void TransitionNextState(NextState a_NextState); cWorld * m_pDefaultWorld; WorldMap m_WorldsByName; static cEvent s_StopEvent; cServer * m_Server; cMonsterConfig * m_MonsterConfig; cCraftingRecipes * m_CraftingRecipes; std::unique_ptr m_RecipeMapper; cFurnaceRecipe * m_FurnaceRecipe; std::unique_ptr m_BrewingRecipes; cWebAdmin * m_WebAdmin; cPluginManager * m_PluginManager; cAuthenticator m_Authenticator; cMojangAPI * m_MojangAPI; std::unique_ptr m_RankManager; cHTTPServer m_HTTPServer; /** The storage for all registered block types. */ // BlockTypeRegistry m_BlockTypeRegistry; void LoadGlobalSettings(); /** Loads the worlds from settings.ini, creates the worldmap */ void LoadWorlds(cDeadlockDetect & a_dd, cSettingsRepositoryInterface & a_Settings, bool a_IsNewIniFile); /** Starts each world's life */ void StartWorlds(cDeadlockDetect & a_DeadlockDetect); /** Stops each world's threads, so that it's safe to unload them */ void StopWorlds(cDeadlockDetect & a_DeadlockDetect); static cRoot * s_Root; /** Indicates the next action of cRoot, whether to run, stop or restart. */ static std::atomic s_NextState; }; // tolua_export ================================================ FILE: src/Scoreboard.cpp ================================================ // Scoreboard.cpp // Implementation of a scoreboard that keeps track of specified objectives #include "Globals.h" #include "Scoreboard.h" #include "World.h" #include "ClientHandle.h" AString cObjective::TypeToString(eType a_Type) { switch (a_Type) { case otDummy: return "dummy"; case otDeathCount: return "deathCount"; case otPlayerKillCount: return "playerKillCount"; case otTotalKillCount: return "totalKillCount"; case otHealth: return "health"; case otAchievement: return "achievement"; case otStat: return "stat"; case otStatItemCraft: return "stat.craftItem"; case otStatItemUse: return "stat.useItem"; case otStatItemBreak: return "stat.breakItem"; case otStatBlockMine: return "stat.mineBlock"; case otStatEntityKill: return "stat.killEntity"; case otStatEntityKilledBy: return "stat.entityKilledBy"; } UNREACHABLE("Unsupported objective type"); } cObjective::eType cObjective::StringToType(const AString & a_Name) { static struct { eType m_Type; const char * m_String; } TypeMap [] = { {otDummy, "dummy" }, {otDeathCount, "deathCount" }, {otPlayerKillCount, "playerKillCount" }, {otTotalKillCount, "totalKillCount" }, {otHealth, "health" }, {otAchievement, "achievement" }, {otStat, "stat" }, {otStatItemCraft, "stat.craftItem" }, {otStatItemUse, "stat.useItem" }, {otStatItemBreak, "stat.breakItem" }, {otStatBlockMine, "stat.mineBlock" }, {otStatEntityKill, "stat.killEntity" }, {otStatEntityKilledBy, "stat.entityKilledBy"} }; for (size_t i = 0; i < ARRAYCOUNT(TypeMap); i++) { if (NoCaseCompare(TypeMap[i].m_String, a_Name) == 0) { return TypeMap[i].m_Type; } } // for i - TypeMap[] return otDummy; } cObjective::cObjective(const AString & a_Name, const AString & a_DisplayName, cObjective::eType a_Type, cWorld * a_World) : m_DisplayName(a_DisplayName) , m_Name(a_Name) , m_Type(a_Type) , m_World(a_World) { } void cObjective::Reset(void) { for (cScoreMap::iterator it = m_Scores.begin(); it != m_Scores.end(); ++it) { m_World->BroadcastScoreUpdate(m_Name, it->first, 0, 1); } m_Scores.clear(); } cObjective::Score cObjective::GetScore(const AString & a_Name) const { cScoreMap::const_iterator it = m_Scores.find(a_Name); if (it == m_Scores.end()) { return 0; } else { return it->second; } } void cObjective::SetScore(const AString & a_Name, cObjective::Score a_Score) { m_Scores[a_Name] = a_Score; m_World->BroadcastScoreUpdate(m_Name, a_Name, a_Score, 0); } void cObjective::ResetScore(const AString & a_Name) { m_Scores.erase(a_Name); m_World->BroadcastScoreUpdate(m_Name, a_Name, 0, 1); } cObjective::Score cObjective::AddScore(const AString & a_Name, cObjective::Score a_Delta) { // TODO 2014-01-19 xdot: Potential optimization - Reuse iterator Score NewScore = m_Scores[a_Name] + a_Delta; SetScore(a_Name, NewScore); return NewScore; } cObjective::Score cObjective::SubScore(const AString & a_Name, cObjective::Score a_Delta) { // TODO 2014-01-19 xdot: Potential optimization - Reuse iterator Score NewScore = m_Scores[a_Name] - a_Delta; SetScore(a_Name, NewScore); return NewScore; } void cObjective::SetDisplayName(const AString & a_Name) { m_DisplayName = a_Name; m_World->BroadcastScoreboardObjective(m_Name, m_DisplayName, 2); } void cObjective::SendTo(cClientHandle & a_Client) { a_Client.SendScoreboardObjective(m_Name, m_DisplayName, 0); for (cScoreMap::const_iterator it = m_Scores.begin(); it != m_Scores.end(); ++it) { a_Client.SendScoreUpdate(m_Name, it->first, it->second, 0); } } cTeam::cTeam( const AString & a_Name, const AString & a_DisplayName, const AString & a_Prefix, const AString & a_Suffix ) : m_AllowsFriendlyFire(true) , m_CanSeeFriendlyInvisible(false) , m_DisplayName(a_DisplayName) , m_Name(a_Name) , m_Prefix(a_Prefix) , m_Suffix(a_Suffix) { } bool cTeam::AddPlayer(const AString & a_Name) { return m_Players.insert(a_Name).second; } bool cTeam::RemovePlayer(const AString & a_Name) { return m_Players.erase(a_Name) > 0; } bool cTeam::HasPlayer(const AString & a_Name) const { cPlayerNameSet::const_iterator it = m_Players.find(a_Name); return it != m_Players.end(); } void cTeam::Reset(void) { // TODO 2014-01-22 xdot: Inform online players m_Players.clear(); } void cTeam::SetDisplayName(const AString & a_Name) { m_DisplayName = a_Name; // TODO 2014-03-01 xdot: Update clients } size_t cTeam::GetNumPlayers(void) const { return m_Players.size(); } cScoreboard::cScoreboard(cWorld * a_World) : m_World(a_World) { for (int i = 0; i < static_cast(dsCount); ++i) { m_Display[i] = nullptr; } } cObjective * cScoreboard::RegisterObjective(const AString & a_Name, const AString & a_DisplayName, cObjective::eType a_Type) { cObjective Objective(a_Name, a_DisplayName, a_Type, m_World); std::pair Status = m_Objectives.insert(cNamedObjective(a_Name, Objective)); if (Status.second) { ASSERT(m_World != nullptr); m_World->BroadcastScoreboardObjective(a_Name, a_DisplayName, 0); return &Status.first->second; } else { return nullptr; } } bool cScoreboard::RemoveObjective(const AString & a_Name) { cCSLock Lock(m_CSObjectives); cObjectiveMap::iterator it = m_Objectives.find(a_Name); if (it == m_Objectives.end()) { return false; } ASSERT(m_World != nullptr); m_World->BroadcastScoreboardObjective(it->second.GetName(), it->second.GetDisplayName(), 1); for (unsigned int i = 0; i < static_cast(dsCount); ++i) { if (m_Display[i] == &it->second) { SetDisplay(nullptr, static_cast(i)); } } m_Objectives.erase(it); return true; } cObjective * cScoreboard::GetObjective(const AString & a_Name) { cCSLock Lock(m_CSObjectives); cObjectiveMap::iterator it = m_Objectives.find(a_Name); if (it == m_Objectives.end()) { return nullptr; } else { return &it->second; } } cTeam * cScoreboard::RegisterTeam( const AString & a_Name, const AString & a_DisplayName, const AString & a_Prefix, const AString & a_Suffix ) { auto [TeamIterator, TeamExists] = m_Teams.try_emplace(a_Name, a_Name, a_DisplayName, a_Prefix, a_Suffix); if (!TeamExists && GetTeam(a_Name)) { LOGWARNING("Tried to register a team that already exists: %s", a_Name.c_str()); return nullptr; } return &TeamIterator->second; } bool cScoreboard::RemoveTeam(const AString & a_Name) { cCSLock Lock(m_CSTeams); cTeamMap::iterator it = m_Teams.find(a_Name); if (it == m_Teams.end()) { return false; } m_Teams.erase(it); return true; } cTeam * cScoreboard::GetTeam(const AString & a_Name) { cCSLock Lock(m_CSTeams); cTeamMap::iterator it = m_Teams.find(a_Name); if (it == m_Teams.end()) { return nullptr; } else { return &it->second; } } AStringVector cScoreboard::GetTeamNames() { AStringVector TeamNames; for (const auto & Team: m_Teams) { TeamNames.push_back(Team.first); } return TeamNames; } cTeam * cScoreboard::QueryPlayerTeam(const AString & a_Name) { cCSLock Lock(m_CSTeams); for (cTeamMap::iterator it = m_Teams.begin(); it != m_Teams.end(); ++it) { if (it->second.HasPlayer(a_Name)) { return &it->second; } } return nullptr; } void cScoreboard::SetDisplay(const AString & a_Objective, eDisplaySlot a_Slot) { ASSERT(a_Slot < dsCount); cObjective * Objective = GetObjective(a_Objective); SetDisplay(Objective, a_Slot); } void cScoreboard::SetDisplay(cObjective * a_Objective, eDisplaySlot a_Slot) { m_Display[a_Slot] = a_Objective; ASSERT(m_World != nullptr); m_World->BroadcastDisplayObjective(a_Objective ? a_Objective->GetName() : "", a_Slot); } cObjective * cScoreboard::GetObjectiveIn(eDisplaySlot a_Slot) { ASSERT(a_Slot < dsCount); return m_Display[a_Slot]; } bool cScoreboard::ForEachObjectiveWith(cObjective::eType a_Type, cObjectiveCallback a_Callback) { cCSLock Lock(m_CSObjectives); for (cObjectiveMap::iterator it = m_Objectives.begin(); it != m_Objectives.end(); ++it) { if (it->second.GetType() == a_Type) { // Call callback if (a_Callback(it->second)) { return false; } } } return true; } bool cScoreboard::ForEachObjective(cObjectiveCallback a_Callback) { cCSLock Lock(m_CSObjectives); for (cObjectiveMap::iterator it = m_Objectives.begin(); it != m_Objectives.end(); ++it) { // Call callback if (a_Callback(it->second)) { return false; } } return true; } bool cScoreboard::ForEachTeam(cTeamCallback a_Callback) { cCSLock Lock(m_CSTeams); for (cTeamMap::iterator it = m_Teams.begin(); it != m_Teams.end(); ++it) { // Call callback if (a_Callback(it->second)) { return false; } } return true; } void cScoreboard::AddPlayerScore(const AString & a_Name, cObjective::eType a_Type, cObjective::Score a_Value) { cCSLock Lock(m_CSObjectives); for (cObjectiveMap::iterator it = m_Objectives.begin(); it != m_Objectives.end(); ++it) { if (it->second.GetType() == a_Type) { it->second.AddScore(a_Name, a_Value); } } } void cScoreboard::SendTo(cClientHandle & a_Client) { cCSLock Lock(m_CSObjectives); for (cObjectiveMap::iterator it = m_Objectives.begin(); it != m_Objectives.end(); ++it) { it->second.SendTo(a_Client); } for (int i = 0; i < static_cast(dsCount); ++i) { // Avoid race conditions cObjective * Objective = m_Display[i]; if (Objective) { a_Client.SendDisplayObjective(Objective->GetName(), static_cast(i)); } } } size_t cScoreboard::GetNumObjectives(void) const { return m_Objectives.size(); } size_t cScoreboard::GetNumTeams(void) const { return m_Teams.size(); } ================================================ FILE: src/Scoreboard.h ================================================ // Scoreboard.h // Implementation of a scoreboard that keeps track of specified objectives #pragma once #include "FunctionRef.h" class cClientHandle; class cObjective; class cTeam; class cWorld; using cObjectiveCallback = cFunctionRef; using cTeamCallback = cFunctionRef; // tolua_begin class cObjective { public: typedef int Score; enum eType { otDummy, otDeathCount, otPlayerKillCount, otTotalKillCount, otHealth, otAchievement, otStat, otStatItemCraft, otStatItemUse, otStatItemBreak, otStatBlockMine, otStatEntityKill, otStatEntityKilledBy }; // tolua_end static AString TypeToString(eType a_Type); static eType StringToType(const AString & a_Name); public: cObjective(const AString & a_Name, const AString & a_DisplayName, eType a_Type, cWorld * a_World); // tolua_begin eType GetType(void) const { return m_Type; } const AString & GetName(void) const { return m_Name; } const AString & GetDisplayName(void) const { return m_DisplayName; } /** Resets the objective */ void Reset(void); /** Returns the score of the specified player */ Score GetScore(const AString & a_Name) const; /** Sets the score of the specified player */ void SetScore(const AString & a_Name, Score a_Score); /** Resets the score of the specified player */ void ResetScore(const AString & a_Name); /** Adds a_Delta and returns the new score */ Score AddScore(const AString & a_Name, Score a_Delta); /** Subtracts a_Delta and returns the new score */ Score SubScore(const AString & a_Name, Score a_Delta); void SetDisplayName(const AString & a_Name); // tolua_end /** Send this objective to the specified client */ void SendTo(cClientHandle & a_Client); private: typedef std::pair cTrackedPlayer; typedef std::map cScoreMap; cScoreMap m_Scores; AString m_DisplayName; AString m_Name; eType m_Type; cWorld * m_World; friend class cScoreboardSerializer; }; // tolua_export // tolua_begin class cTeam { public: // tolua_end cTeam( const AString & a_Name, const AString & a_DisplayName, const AString & a_Prefix, const AString & a_Suffix ); // tolua_begin /** Adds a new player to the team */ bool AddPlayer(const AString & a_Name); /** Removes a player from the team */ bool RemovePlayer(const AString & a_Name); /** Returns whether the specified player is in this team */ bool HasPlayer(const AString & a_Name) const; /** Removes all registered players */ void Reset(void); // tolua_begin /** Returns the number of registered players */ size_t GetNumPlayers(void) const; bool AllowsFriendlyFire(void) const { return m_AllowsFriendlyFire; } bool CanSeeFriendlyInvisible(void) const { return m_CanSeeFriendlyInvisible; } const AString & GetDisplayName(void) const { return m_DisplayName; } const AString & GetName(void) const { return m_Name; } const AString & GetPrefix(void) const { return m_Prefix; } const AString & GetSuffix(void) const { return m_Suffix; } void SetFriendlyFire(bool a_Flag) { m_AllowsFriendlyFire = a_Flag; } void SetCanSeeFriendlyInvisible(bool a_Flag) { m_CanSeeFriendlyInvisible = a_Flag; } void SetDisplayName(const AString & a_Name); void SetPrefix(const AString & a_Prefix) { m_Prefix = a_Prefix; } void SetSuffix(const AString & a_Suffix) { m_Suffix = a_Suffix; } // tolua_end private: typedef std::set cPlayerNameSet; bool m_AllowsFriendlyFire; bool m_CanSeeFriendlyInvisible; AString m_DisplayName; AString m_Name; AString m_Prefix; AString m_Suffix; cPlayerNameSet m_Players; friend class cScoreboardSerializer; }; // tolua_export // tolua_begin class cScoreboard { public: enum eDisplaySlot { dsList = 0, dsSidebar, dsName, dsCount }; // tolua_end public: cScoreboard(cWorld * a_World); // tolua_begin /** Registers a new scoreboard objective, returns the cObjective instance, nullptr on name collision */ cObjective * RegisterObjective(const AString & a_Name, const AString & a_DisplayName, cObjective::eType a_Type); /** Removes a registered objective, returns true if operation was successful */ bool RemoveObjective(const AString & a_Name); /** Retrieves the objective with the specified name, nullptr if not found */ cObjective * GetObjective(const AString & a_Name); /** Registers a new team, returns the cTeam instance, nullptr on name collision */ cTeam * RegisterTeam(const AString & a_Name, const AString & a_DisplayName, const AString & a_Prefix, const AString & a_Suffix); /** Removes a registered team, returns true if operation was successful */ bool RemoveTeam(const AString & a_Name); /** Retrieves the team with the specified name, nullptr if not found */ cTeam * GetTeam(const AString & a_Name); void SetDisplay(const AString & a_Objective, eDisplaySlot a_Slot); cObjective * GetObjectiveIn(eDisplaySlot a_Slot); size_t GetNumObjectives(void) const; size_t GetNumTeams(void) const; void AddPlayerScore(const AString & a_Name, cObjective::eType a_Type, cObjective::Score a_Value = 1); // tolua_end /** Retrieves the list of team names */ AStringVector GetTeamNames(); /** Send this scoreboard to the specified client */ void SendTo(cClientHandle & a_Client); cTeam * QueryPlayerTeam(const AString & a_Name); // WARNING: O(n logn) /** Execute callback for each objective with the specified type Returns true if all objectives processed, false if the callback aborted by returning true. */ bool ForEachObjectiveWith(cObjective::eType a_Type, cObjectiveCallback a_Callback); /** Execute callback for each objective. Returns true if all objectives have been processed, false if the callback aborted by returning true. */ bool ForEachObjective(cObjectiveCallback a_Callback); // Exported in ManualBindings.cpp /** Execute callback for each team. Returns true if all teams have been processed, false if the callback aborted by returning true. */ bool ForEachTeam(cTeamCallback a_Callback); // Exported in ManualBindings.cpp void SetDisplay(cObjective * a_Objective, eDisplaySlot a_Slot); private: typedef std::pair cNamedObjective; typedef std::pair cNamedTeam; typedef std::map cObjectiveMap; typedef std::map cTeamMap; // TODO 2014-01-19 xdot: Potential optimization - Sort objectives based on type cCriticalSection m_CSObjectives; cObjectiveMap m_Objectives; cCriticalSection m_CSTeams; cTeamMap m_Teams; cWorld * m_World; cObjective * m_Display[dsCount]; friend class cScoreboardSerializer; }; // tolua_export ================================================ FILE: src/Server.cpp ================================================ // ReDucTor is an awesome guy who helped me a lot #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "Server.h" #include "ClientHandle.h" #include "LoggerSimple.h" #include "Mobs/Monster.h" #include "Root.h" #include "World.h" #include "Bindings/PluginManager.h" #include "ChatColor.h" #include "Entities/Player.h" #include "Inventory.h" #include "Item.h" #include "FurnaceRecipe.h" #include "WebAdmin.h" #include "Protocol/ProtocolRecognizer.h" #include "CommandOutput.h" #include "FastRandom.h" #include "IniFile.h" #include #include #include //////////////////////////////////////////////////////////////////////////////// // cServerListenCallbacks: class cServerListenCallbacks: public cNetwork::cListenCallbacks { cServer & m_Server; UInt16 m_Port; virtual cTCPLink::cCallbacksPtr OnIncomingConnection(const AString & a_RemoteIPAddress, UInt16 a_RemotePort) override { return m_Server.OnConnectionAccepted(a_RemoteIPAddress); } virtual void OnAccepted(cTCPLink & a_Link) override {} virtual void OnError(int a_ErrorCode, const AString & a_ErrorMsg) override { LOGWARNING("Cannot listen on port %d: %d (%s).", m_Port, a_ErrorCode, a_ErrorMsg.c_str()); } public: cServerListenCallbacks(cServer & a_Server, UInt16 a_Port): m_Server(a_Server), m_Port(a_Port) { } }; //////////////////////////////////////////////////////////////////////////////// // cServer::cTickThread: cServer::cTickThread::cTickThread(cServer & a_Server) : Super("Server Ticker"), m_Server(a_Server) { } void cServer::cTickThread::Execute(void) { auto LastTime = std::chrono::steady_clock::now(); static const auto msPerTick = std::chrono::milliseconds(50); while (!m_ShouldTerminate) { auto NowTime = std::chrono::steady_clock::now(); auto msec = std::chrono::duration_cast(NowTime - LastTime).count(); m_Server.Tick(static_cast(msec)); auto TickTime = std::chrono::steady_clock::now() - NowTime; if (TickTime < msPerTick) { // Stretch tick time until it's at least msPerTick std::this_thread::sleep_for(msPerTick - TickTime); } LastTime = NowTime; } } //////////////////////////////////////////////////////////////////////////////// // cServer: cServer::cServer(void) : m_PlayerCount(0), m_ClientViewDistance(0), m_bIsConnected(false), m_RCONServer(*this), m_MaxPlayers(0), m_bIsHardcore(false), m_TickThread(*this), m_ShouldAuthenticate(false), m_UpTime(0) { // Initialize the LuaStateTracker singleton before the app goes multithreaded: cLuaStateTracker::GetStats(); } void cServer::ClientMovedToWorld(const cClientHandle * a_Client) { cCSLock Lock(m_CSClients); m_ClientsToRemove.push_back(const_cast(a_Client)); } void cServer::PlayerCreated() { m_PlayerCount++; } void cServer::PlayerDestroyed() { m_PlayerCount--; } bool cServer::InitServer(cSettingsRepositoryInterface & a_Settings, bool a_ShouldAuth) { m_Description = a_Settings.GetValueSet("Server", "Description", "Cuberite - in C++!"); m_ShutdownMessage = a_Settings.GetValueSet("Server", "ShutdownMessage", "Server shutdown"); m_MaxPlayers = static_cast(a_Settings.GetValueSetI("Server", "MaxPlayers", 100)); m_bIsHardcore = a_Settings.GetValueSetB("Server", "HardcoreEnabled", false); m_bAllowMultiLogin = a_Settings.GetValueSetB("Server", "AllowMultiLogin", false); m_RequireResourcePack = a_Settings.GetValueSetB("Server", "RequireResourcePack", false); m_ResourcePackUrl = a_Settings.GetValueSet("Server", "ResourcePackUrl", ""); m_CustomRedirectUrl = a_Settings.GetValueSet("Server", "CustomRedirectUrl", "https://youtu.be/dQw4w9WgXcQ"); m_FaviconData = Base64Encode(cFile::ReadWholeFile(AString("favicon.png"))); // Will return empty string if file nonexistant; client doesn't mind if (m_bIsConnected) { LOGERROR("ERROR: Trying to initialize server while server is already running!"); return false; } LOGINFO("Compatible clients: %s", MCS_CLIENT_VERSIONS); LOGD("Compatible protocol versions %s", MCS_PROTOCOL_VERSIONS); m_Ports = ReadUpgradeIniPorts(a_Settings, "Server", "Ports", "Port", "PortsIPv6", "25565"); m_RCONServer.Initialize(a_Settings); m_bIsConnected = true; m_ServerID = "-"; m_ShouldAuthenticate = a_ShouldAuth; if (m_ShouldAuthenticate) { auto & rand = GetRandomProvider(); unsigned int r1 = rand.RandInt(1000000000U, 0x7fffffffU); unsigned int r2 = rand.RandInt(1000000000U, 0x7fffffffU); std::ostringstream sid; sid << std::hex << r1; sid << std::hex << r2; m_ServerID = sid.str(); m_ServerID.resize(16, '0'); } // Check if both BungeeCord and online mode are on, if so, warn the admin: m_ShouldAllowBungeeCord = a_Settings.GetValueSetB("Authentication", "AllowBungeeCord", false); m_OnlyAllowBungeeCord = a_Settings.GetValueSetB("Authentication", "OnlyAllowBungeeCord", false); m_ProxySharedSecret = a_Settings.GetValueSet("Authentication", "ProxySharedSecret", ""); if (m_ShouldAllowBungeeCord && m_ShouldAuthenticate) { LOGWARNING("WARNING: BungeeCord is allowed and server set to online mode. This is unsafe and will not work properly. Disable either authentication or BungeeCord in settings.ini."); } if (m_ShouldAllowBungeeCord && m_ProxySharedSecret.empty()) { LOGWARNING("WARNING: There is not a Proxy Forward Secret set up, and any proxy server can forward a player to this server unless closed from the internet."); } m_ShouldAllowMultiWorldTabCompletion = a_Settings.GetValueSetB("Server", "AllowMultiWorldTabCompletion", true); m_ShouldLimitPlayerBlockChanges = a_Settings.GetValueSetB("AntiCheat", "LimitPlayerBlockChanges", true); const auto ClientViewDistance = a_Settings.GetValueSetI("Server", "DefaultViewDistance", cClientHandle::DEFAULT_VIEW_DISTANCE); if (ClientViewDistance < cClientHandle::MIN_VIEW_DISTANCE) { m_ClientViewDistance = cClientHandle::MIN_VIEW_DISTANCE; LOGINFO("Setting default view distance to the minimum of %d", m_ClientViewDistance); } else if (ClientViewDistance > cClientHandle::MAX_VIEW_DISTANCE) { m_ClientViewDistance = cClientHandle::MAX_VIEW_DISTANCE; LOGINFO("Setting default view distance to the maximum of %d", m_ClientViewDistance); } else { m_ClientViewDistance = ClientViewDistance; } PrepareKeys(); return true; } bool cServer::RegisterForgeMod(const AString & a_ModName, const AString & a_ModVersion, UInt32 a_ProtocolVersionNumber) { auto & Mods = RegisteredForgeMods(a_ProtocolVersionNumber); return Mods.insert({a_ModName, a_ModVersion}).second; } void cServer::UnregisterForgeMod(const AString & a_ModName, UInt32 a_ProtocolVersionNumber) { auto & Mods = RegisteredForgeMods(a_ProtocolVersionNumber); auto it = Mods.find(a_ModName); if (it != Mods.end()) { Mods.erase(it); } } AStringMap & cServer::RegisteredForgeMods(const UInt32 a_Protocol) { auto it = m_ForgeModsByVersion.find(a_Protocol); if (it == m_ForgeModsByVersion.end()) { AStringMap mods; m_ForgeModsByVersion.insert({a_Protocol, mods}); return m_ForgeModsByVersion.find(a_Protocol)->second; } return it->second; } const AStringMap & cServer::GetRegisteredForgeMods(const UInt32 a_Protocol) { return RegisteredForgeMods(a_Protocol); } bool cServer::IsPlayerInQueue(const AString & a_Username) { cCSLock Lock(m_CSClients); for (const auto & client : m_Clients) { if ((client->GetUsername()).compare(a_Username) == 0) { return true; } } return false; } void cServer::PrepareKeys(void) { LOGD("Generating protocol encryption keypair..."); VERIFY(m_PrivateKey.Generate(1024)); m_PublicKeyDER = m_PrivateKey.GetPubKeyDER(); } cTCPLink::cCallbacksPtr cServer::OnConnectionAccepted(const AString & a_RemoteIPAddress) { LOGD("Client \"%s\" connected!", a_RemoteIPAddress.c_str()); cClientHandlePtr NewHandle = std::make_shared(a_RemoteIPAddress, m_ClientViewDistance); cCSLock Lock(m_CSClients); m_Clients.push_back(NewHandle); return NewHandle; } void cServer::Tick(float a_Dt) { // Update server uptime m_UpTime++; // Send the tick to the plugins, as well as let the plugin manager reload, if asked to (issue #102): cPluginManager::Get()->Tick(a_Dt); // Process all the queued commands: TickCommands(); // Tick all clients not yet assigned to a world: TickClients(a_Dt); // Process all queued tasks TickQueuedTasks(); } void cServer::TickClients(float a_Dt) { cClientHandlePtrs RemoveClients; { cCSLock Lock(m_CSClients); // Remove clients that have moved to a world (the world will be ticking them from now on) for (auto itr = m_ClientsToRemove.begin(), end = m_ClientsToRemove.end(); itr != end; ++itr) { for (auto itrC = m_Clients.begin(), endC = m_Clients.end(); itrC != endC; ++itrC) { if (itrC->get() == *itr) { m_Clients.erase(itrC); break; } } } // for itr - m_ClientsToRemove[] m_ClientsToRemove.clear(); // Tick the remaining clients, take out those that have been destroyed into RemoveClients for (auto itr = m_Clients.begin(); itr != m_Clients.end();) { auto & Client = *itr; Client->ServerTick(a_Dt); if (Client->IsDestroyed()) { // Delete the client later, when CS is not held, to avoid deadlock: https://forum.cuberite.org/thread-374.html RemoveClients.push_back(std::move(Client)); itr = m_Clients.erase(itr); continue; } ++itr; } // for itr - m_Clients[] } // Delete the clients that have been destroyed RemoveClients.clear(); } bool cServer::Start(void) { for (const auto & port: m_Ports) { UInt16 PortNum; if (!StringToInteger(port, PortNum)) { LOGWARNING("Invalid port specified for server: \"%s\". Ignoring.", port.c_str()); continue; } auto Handle = cNetwork::Listen(PortNum, std::make_shared(*this, PortNum)); if (Handle->IsListening()) { LOGINFO("Server Running On Port: %s", port.c_str()); m_ServerHandles.push_back(Handle); } } // for port - Ports[] if (m_ServerHandles.empty()) { LOGERROR("Couldn't open any ports. Aborting the server"); return false; } m_TickThread.Start(); return true; } bool cServer::Command(cClientHandle & a_Client, AString & a_Cmd) { bool Res = cRoot::Get()->DoWithPlayerByUUID( a_Client.GetUUID(), [&](cPlayer & a_Player) { return cRoot::Get()->GetPluginManager()->CallHookChat(a_Player, a_Cmd); } ); return Res; } void cServer::QueueExecuteConsoleCommand(const AString & a_Cmd, cCommandOutputCallback & a_Output) { // Put the command into a queue (Alleviates FS #363): cCSLock Lock(m_CSPendingCommands); m_PendingCommands.emplace_back(a_Cmd, &a_Output); } void cServer::ScheduleTask(cTickTime a_DelayTicks, std::function a_Task) { const auto TargetTick = a_DelayTicks + m_UpTime; // Insert the task into the list of scheduled tasks { cCSLock Lock(m_CSTasks); m_Tasks.emplace_back(TargetTick, std::move(a_Task)); } } void cServer::ExecuteConsoleCommand(const AString & a_Cmd, cCommandOutputCallback & a_Output) { AStringVector split = StringSplit(a_Cmd, " "); if (split.empty()) { return; } // "stop" and "restart" are handled in cRoot::ExecuteConsoleCommand, our caller, due to its access to controlling variables // "help" and "reload" are to be handled by Cuberite, so that they work no matter what if (split[0] == "help") { PrintHelp(split, a_Output); a_Output.Finished(); return; } else if (split[0] == "reload") { if (split.size() > 1) { cPluginManager::Get()->ReloadPlugin(split[1]); a_Output.OutLn("Plugin reload scheduled"); } else { cPluginManager::Get()->ReloadPlugins(); } a_Output.Finished(); return; } else if (split[0] == "reloadplugins") { cPluginManager::Get()->ReloadPlugins(); a_Output.OutLn("Plugins reloaded"); a_Output.Finished(); return; } else if (split[0] == "reloadweb") { cRoot::Get()->GetWebAdmin()->Reload(); a_Output.OutLn("WebAdmin configuration reloaded"); a_Output.Finished(); return; } else if (split[0] == "load") { if (split.size() > 1) { cPluginManager::Get()->RefreshPluginList(); // Refresh the plugin list, so that if the plugin was added just now, it is loadable a_Output.OutLn(cPluginManager::Get()->LoadPlugin(split[1]) ? "Plugin loaded" : "Error occurred loading plugin"); } else { a_Output.OutLn("Usage: load "); } a_Output.Finished(); return; } else if (split[0] == "unload") { if (split.size() > 1) { cPluginManager::Get()->UnloadPlugin(split[1]); a_Output.OutLn("Plugin unload scheduled"); } else { a_Output.OutLn("Usage: unload "); } a_Output.Finished(); return; } if (split[0] == "destroyentities") { cRoot::Get()->ForEachWorld([](cWorld & a_World) { a_World.ForEachEntity([](cEntity & a_Entity) { if (!a_Entity.IsPlayer()) { a_Entity.Destroy(); } return false; } ); return false; } ); a_Output.OutLn("Destroyed all entities"); a_Output.Finished(); return; } // There is currently no way a plugin can do these (and probably won't ever be): else if (split[0].compare("chunkstats") == 0) { cRoot::Get()->LogChunkStats(a_Output); a_Output.Finished(); return; } else if (split[0].compare("luastats") == 0) { a_Output.OutLn(cLuaStateTracker::GetStats()); a_Output.Finished(); return; } else if (cPluginManager::Get()->ExecuteConsoleCommand(split, a_Output, a_Cmd)) { a_Output.Finished(); return; } a_Output.OutLn("Unknown command, type 'help' for all commands."); a_Output.Finished(); } void cServer::PrintHelp(const AStringVector & a_Split, cCommandOutputCallback & a_Output) { UNUSED(a_Split); typedef std::pair AStringPair; typedef std::vector AStringPairs; class cCallback : public cPluginManager::cCommandEnumCallback { public: cCallback(void) : m_MaxLen(0) {} virtual bool Command(const AString & a_Command, const cPlugin * a_Plugin, const AString & a_Permission, const AString & a_HelpString) override { UNUSED(a_Plugin); UNUSED(a_Permission); if (!a_HelpString.empty()) { m_Commands.push_back(AStringPair(a_Command, a_HelpString)); if (m_MaxLen < a_Command.length()) { m_MaxLen = a_Command.length(); } } return false; } AStringPairs m_Commands; size_t m_MaxLen; } Callback; cPluginManager::Get()->ForEachConsoleCommand(Callback); std::sort(Callback.m_Commands.begin(), Callback.m_Commands.end()); for (AStringPairs::const_iterator itr = Callback.m_Commands.begin(), end = Callback.m_Commands.end(); itr != end; ++itr) { const AStringPair & cmd = *itr; // Output the commands and their help strings, with all the commands aligned to the same width a_Output.OutLn(fmt::format(FMT_STRING("{1:{0}s} - {2}"), Callback.m_MaxLen, cmd.first, cmd.second)); } // for itr - Callback.m_Commands[] } void cServer::BindBuiltInConsoleCommands(void) { // Create an empty handler - the actual handling for the commands is performed before they are handed off to cPluginManager class cEmptyHandler: public cPluginManager::cCommandHandler { virtual bool ExecuteCommand( const AStringVector & a_Split, cPlayer * a_Player, const AString & a_Command, cCommandOutputCallback * a_Output = nullptr ) override { return false; } }; auto handler = std::make_shared(); // Register internal commands: cPluginManager * PlgMgr = cPluginManager::Get(); PlgMgr->BindConsoleCommand("help", nullptr, handler, "Shows the available commands"); PlgMgr->BindConsoleCommand("reload", nullptr, handler, "Reloads all plugins"); PlgMgr->BindConsoleCommand("reloadweb", nullptr, handler, "Reloads the webadmin configuration"); PlgMgr->BindConsoleCommand("restart", nullptr, handler, "Restarts the server cleanly"); PlgMgr->BindConsoleCommand("stop", nullptr, handler, "Stops the server cleanly"); PlgMgr->BindConsoleCommand("chunkstats", nullptr, handler, "Displays detailed chunk memory statistics"); PlgMgr->BindConsoleCommand("load", nullptr, handler, "Adds and enables the specified plugin"); PlgMgr->BindConsoleCommand("unload", nullptr, handler, "Disables the specified plugin"); PlgMgr->BindConsoleCommand("destroyentities", nullptr, handler, "Destroys all entities in all worlds"); } void cServer::Shutdown(void) { // Stop listening on all sockets: for (const auto & srv: m_ServerHandles) { srv->Close(); } m_ServerHandles.clear(); // Notify the tick thread and wait for it to terminate: m_TickThread.Stop(); // Save all chunks in all worlds, wait for chunks to be sent to the ChunkStorage queue for each world: cRoot::Get()->SaveAllChunksNow(); // Remove all clients: cCSLock Lock(m_CSClients); for (auto itr = m_Clients.begin(); itr != m_Clients.end(); ++itr) { (*itr)->Destroy(); } m_Clients.clear(); } void cServer::KickUser(int a_ClientID, const AString & a_Reason) { cCSLock Lock(m_CSClients); for (auto itr = m_Clients.begin(); itr != m_Clients.end(); ++itr) { if ((*itr)->GetUniqueID() == a_ClientID) { (*itr)->Kick(a_Reason); } } // for itr - m_Clients[] } void cServer::AuthenticateUser(int a_ClientID, AString && a_Username, const cUUID & a_UUID, Json::Value && a_Properties) { cCSLock Lock(m_CSClients); // Check max players condition within lock (expect server and authenticator thread to both call here) if (GetNumPlayers() >= GetMaxPlayers()) { KickUser(a_ClientID, "The server is currently full :(" "\n" "Try again later?"); return; } for (const auto & Client : m_Clients) { if (Client->GetUniqueID() == a_ClientID) { Client->Authenticate(std::move(a_Username), a_UUID, std::move(a_Properties)); return; } } } void cServer::TickCommands(void) { decltype(m_PendingCommands) PendingCommands; { cCSLock Lock(m_CSPendingCommands); std::swap(PendingCommands, m_PendingCommands); } // Execute any pending commands: for (const auto & Command : PendingCommands) { ExecuteConsoleCommand(Command.first, *Command.second); } } void cServer::TickQueuedTasks(void) { // Move the tasks to be executed to a seperate vector to avoid deadlocks on // accessing m_Tasks decltype(m_Tasks) Tasks; { cCSLock Lock(m_CSTasks); if (m_Tasks.empty()) { return; } // Partition everything to be executed by returning false to move to end // of list if time reached auto MoveBeginIterator = std::partition( m_Tasks.begin(), m_Tasks.end(), [this](const decltype(m_Tasks)::value_type & a_Task) { return a_Task.first >= m_UpTime; }); // Cut all the due tasks from m_Tasks into Tasks: Tasks.insert( Tasks.end(), std::make_move_iterator(MoveBeginIterator), std::make_move_iterator(m_Tasks.end())); m_Tasks.erase(MoveBeginIterator, m_Tasks.end()); } // Execute each task: for (const auto & Task : Tasks) { Task.second(*this); } // for itr - m_Tasks[] } ================================================ FILE: src/Server.h ================================================ // cServer.h // Interfaces to the cServer object representing the network server #pragma once #include "RCONServer.h" #include "OSSupport/IsThread.h" #include "OSSupport/Network.h" #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable:4127) #pragma warning(disable:4244) #pragma warning(disable:4231) #pragma warning(disable:4189) #pragma warning(disable:4702) #endif #include "mbedTLS++/RsaPrivateKey.h" #ifdef _MSC_VER #pragma warning(pop) #endif // fwd: class cClientHandle; typedef std::shared_ptr cClientHandlePtr; typedef std::list cClientHandlePtrs; typedef std::list cClientHandles; class cCommandOutputCallback; class cSettingsRepositoryInterface; class cUUID; namespace Json { class Value; } // tolua_begin class cServer { public: // tolua_end virtual ~cServer() {} bool InitServer(cSettingsRepositoryInterface & a_Settings, bool a_ShouldAuth); // tolua_begin const AString & GetDescription(void) const {return m_Description; } const AString & GetShutdownMessage(void) const { return m_ShutdownMessage; } // Player counts: size_t GetMaxPlayers(void) const { return m_MaxPlayers; } size_t GetNumPlayers(void) const { return m_PlayerCount; } void SetMaxPlayers(size_t a_MaxPlayers) { m_MaxPlayers = a_MaxPlayers; } // tolua_end /** Add a Forge mod to the server ping list. */ bool RegisterForgeMod(const AString & a_ModName, const AString & a_ModVersion, UInt32 a_ProtocolVersionNumber); // tolua_begin /** Remove a Forge mod to the server ping list. */ void UnregisterForgeMod(const AString & a_ModName, UInt32 a_ProtocolVersionNumber); /** Check if the player is queued to be transferred to a World. Returns true is Player is found in queue. */ bool IsPlayerInQueue(const AString & a_Username); /** Can login more than once with same username. Returns false if it is not allowed, true otherwise. */ bool DoesAllowMultiLogin(void) { return m_bAllowMultiLogin; } // Hardcore mode or not: bool IsHardcore(void) const { return m_bIsHardcore; } // tolua_end /** Returns true if clients must accept resource pack. This is read from the settings. */ bool ShouldRequireResourcePack(void) { return m_RequireResourcePack; } const AString & GetResourcePackUrl(void) { return m_ResourcePackUrl; } std::string_view GetCustomRedirectUrl(void) { return m_CustomRedirectUrl; } bool Start(void); bool Command(cClientHandle & a_Client, AString & a_Cmd); /** Queues a console command for execution through the cServer class. The command will be executed in the server tick thread. The command's output will be written to the a_Output callback. */ void QueueExecuteConsoleCommand(const AString & a_Cmd, cCommandOutputCallback & a_Output); /** Queues a lambda task onto the server tick thread, with the specified delay in ticks. */ void ScheduleTask(cTickTime a_DelayTicks, std::function a_Task); /** Lists all available console commands and their helpstrings */ void PrintHelp(const AStringVector & a_Split, cCommandOutputCallback & a_Output); /** Binds the built-in console commands with the plugin manager */ static void BindBuiltInConsoleCommands(void); void Shutdown(void); void KickUser(int a_ClientID, const AString & a_Reason); /** Authenticates the specified user, called by cAuthenticator supplying player details from Mojang. */ void AuthenticateUser(int a_ClientID, AString && a_Username, const cUUID & a_UUID, Json::Value && a_Properties); const AString & GetServerID(void) const { return m_ServerID; } // tolua_export /** Don't tick a_Client anymore, it will be ticked from its cPlayer instead */ void ClientMovedToWorld(const cClientHandle * a_Client); /** Notifies the server that a player was created; the server uses this to adjust the number of players */ void PlayerCreated(); /** Notifies the server that a player is being destroyed; the server uses this to adjust the number of players */ void PlayerDestroyed(); /** Returns base64 encoded favicon data (obtained from favicon.png) */ const AString & GetFaviconData(void) const { return m_FaviconData; } cRsaPrivateKey & GetPrivateKey(void) { return m_PrivateKey; } ContiguousByteBufferView GetPublicKeyDER(void) const { return m_PublicKeyDER; } /** Returns true if authentication has been turned on in server settings. */ bool ShouldAuthenticate(void) const { return m_ShouldAuthenticate; } // tolua_export /** Returns true if limit for number of block changes per tick by a player has been turned on in server settings. */ bool ShouldLimitPlayerBlockChanges(void) const { return m_ShouldLimitPlayerBlockChanges; } /** Returns true if BungeeCord logins (that specify the player's UUID) are allowed. Read from settings, admins should set this to true only when they chain to BungeeCord, it makes the server vulnerable to identity theft through direct connections. */ bool ShouldAllowBungeeCord(void) const { return m_ShouldAllowBungeeCord; } bool OnlyAllowBungeeCord(void) const { return m_OnlyAllowBungeeCord; } const AString & GetProxySharedSecret(void) const { return m_ProxySharedSecret; } /** Returns true if usernames should be completed across worlds. This is read from the settings. */ bool ShouldAllowMultiWorldTabCompletion(void) const { return m_ShouldAllowMultiWorldTabCompletion; } /** Get the Forge mods (map of ModName -> ModVersionString) registered for a given protocol. */ const AStringMap & GetRegisteredForgeMods(const UInt32 a_Protocol); private: friend class cRoot; // so cRoot can create and destroy cServer friend class cServerListenCallbacks; // Accessing OnConnectionAccepted() /** The server tick thread takes care of the players who aren't yet spawned in a world */ class cTickThread: public cIsThread { using Super = cIsThread; public: cTickThread(cServer & a_Server); protected: cServer & m_Server; // cIsThread overrides: virtual void Execute(void) override; } ; /** The network sockets listening for client connections. */ cServerHandlePtrs m_ServerHandles; /** Protects m_Clients and m_ClientsToRemove against multithreaded access. */ cCriticalSection m_CSClients; /** Clients that are connected to the server and not yet assigned to a cWorld. */ cClientHandlePtrs m_Clients; /** Clients that have just been moved into a world and are to be removed from m_Clients in the next Tick(). */ cClientHandles m_ClientsToRemove; /** Number of players currently playing in the server. */ std::atomic_size_t m_PlayerCount; cCriticalSection m_CSPendingCommands; std::vector> m_PendingCommands; int m_ClientViewDistance; // The default view distance for clients; settable in Settings.ini bool m_bIsConnected; // true - connected false - not connected /** The private key used for the assymetric encryption start in the protocols */ cRsaPrivateKey m_PrivateKey; /** Public key for m_PrivateKey, ASN1-DER-encoded */ ContiguousByteBuffer m_PublicKeyDER; cRCONServer m_RCONServer; AString m_Description; AString m_ShutdownMessage; AString m_FaviconData; size_t m_MaxPlayers; bool m_bIsHardcore; bool m_RequireResourcePack; AString m_ResourcePackUrl; AString m_CustomRedirectUrl; /** Map of protocol version to Forge mods (map of ModName -> ModVersionString) */ std::map m_ForgeModsByVersion; /** True - allow same username to login more than once False - only once */ bool m_bAllowMultiLogin; cTickThread m_TickThread; /** The server ID used for client authentication */ AString m_ServerID; /** If true, players will be online-authenticated agains Mojang servers. This setting is the same as the "online-mode" setting in Vanilla. */ bool m_ShouldAuthenticate; /** True if limit for number of block changes per tick by a player should be enabled. */ bool m_ShouldLimitPlayerBlockChanges; /** True if BungeeCord handshake packets (with player UUID) should be accepted. */ bool m_ShouldAllowBungeeCord; /** True if BungeeCord handshake packets should be the only ones accepted. */ bool m_OnlyAllowBungeeCord; /** Security string that the proxy server should send, compatible with BungeeGuard */ AString m_ProxySharedSecret; /** True if usernames should be completed across worlds. */ bool m_ShouldAllowMultiWorldTabCompletion; /** The list of ports on which the server should listen for connections. Initialized in InitServer(), used in Start(). */ AStringVector m_Ports; /** Time, in ticks, since the server started Not persistent across server restarts */ cTickTimeLong m_UpTime; /** Guards the m_Tasks */ cCriticalSection m_CSTasks; /** Tasks that have been queued onto the tick thread, possibly to be executed at target tick in the future; guarded by m_CSTasks */ std::vector>> m_Tasks; cServer(void); /** Executes the console command, sends output through the specified callback. */ void ExecuteConsoleCommand(const AString & a_Cmd, cCommandOutputCallback & a_Output); /** Get the Forge mods registered for a given protocol, for modification */ AStringMap & RegisteredForgeMods(const UInt32 a_Protocol); /** Loads, or generates, if missing, RSA keys for protocol encryption */ void PrepareKeys(void); /** Creates a new cClientHandle instance and adds it to the list of clients. Returns the cClientHandle reinterpreted as cTCPLink callbacks. */ cTCPLink::cCallbacksPtr OnConnectionAccepted(const AString & a_RemoteIPAddress); void Tick(float a_Dt); /** Ticks the clients in m_Clients, manages the list in respect to removing clients */ void TickClients(float a_Dt); /** Executes commands queued in the command queue. */ void TickCommands(void); /** Executes all tasks queued onto the tick thread */ void TickQueuedTasks(void); }; // tolua_export ================================================ FILE: src/SetChunkData.cpp ================================================ #include "Globals.h" #include "SetChunkData.h" #include "BlockType.h" #include "Entities/Entity.h" void SetChunkData::UpdateHeightMap() { for (int x = 0; x < cChunkDef::Width; x++) { for (int z = 0; z < cChunkDef::Width; z++) { HEIGHTTYPE Height = 0; for (HEIGHTTYPE y = cChunkDef::Height - 1; y > 0; y--) { BLOCKTYPE BlockType = BlockData.GetBlock({x, y, z}); if (BlockType != E_BLOCK_AIR) { Height = y; break; } } // for y auto idx = x + cChunkDef::Width * z; HeightMap[idx] = Height; } // for z } // for x } ================================================ FILE: src/SetChunkData.h ================================================ #pragma once #include "ChunkData.h" #include "BlockEntities/BlockEntity.h" /** Contains the data for a loaded / generated chunk, ready to be set into a cWorld. */ struct SetChunkData { /** Initialise the structure with chunk coordinates. The caller is responsible for initialising the remaining members. */ SetChunkData(const cChunkCoords a_Chunk) : Chunk(a_Chunk) { } cChunkCoords Chunk; ChunkBlockData BlockData; ChunkLightData LightData; cChunkDef::BiomeMap BiomeMap; cChunkDef::HeightMap HeightMap; cEntityList Entities; cBlockEntities BlockEntities; bool IsLightValid; /** Recalculates the HeightMap based on BlockData contents. */ void UpdateHeightMap(); }; ================================================ FILE: src/SettingsRepositoryInterface.h ================================================ #pragma once class cSettingsRepositoryInterface { public: enum errors { noID = -1, }; cSettingsRepositoryInterface() = default; virtual ~cSettingsRepositoryInterface() = default; DISALLOW_COPY_AND_ASSIGN(cSettingsRepositoryInterface); /** Returns true iff the specified key exists */ virtual bool KeyExists(const AString keyname) const = 0; /** Returns true iff the specified value exists. */ virtual bool HasValue(const AString & a_KeyName, const AString & a_ValueName) const = 0; /** Add a key name. Return value is not required to mean anything */ virtual int AddKeyName(const AString & keyname) = 0; /** Add a key comment, will always fail if the repository does not support comments */ virtual bool AddKeyComment(const AString & keyname, const AString & comment) = 0; /** Return a key comment, returns "" for repositories that do not return comments */ virtual AString GetKeyComment(const AString & keyname, const int commentID) const = 0; /** Delete a key comment, will always fail if the repository does not support comments */ virtual bool DeleteKeyComment(const AString & keyname, const int commentID) = 0; /** Adds a new value to the specified key. If a value of the same name already exists, creates another one */ virtual void AddValue (const AString & a_KeyName, const AString & a_ValueName, const AString & a_Value) = 0; /** returns a vector containing a name, value pair for each value under the key */ virtual std::vector> GetValues(AString a_keyName) = 0; /** Get the value at the specified key and value, returns defValue on failure */ virtual AString GetValue (const AString & keyname, const AString & valuename, const AString & defValue = "") const = 0; /** Gets the value; if not found, write the default to the repository */ virtual AString GetValueSet (const AString & keyname, const AString & valuename, const AString & defValue = "") = 0; virtual int GetValueSetI(const AString & keyname, const AString & valuename, const int defValue = 0) = 0; virtual Int64 GetValueSetI(const AString & keyname, const AString & valuename, const Int64 defValue = 0) = 0; virtual bool GetValueSetB(const AString & keyname, const AString & valuename, const bool defValue = false) = 0; /** Overwrites the value of the key, value pair Specify the optional parameter as false if you do not want the value created if it doesn't exist. Returns true if value set, false otherwise. */ virtual bool SetValue (const AString & a_KeyName, const AString & a_ValueName, const AString & a_Value, const bool a_CreateIfNotExists = true) = 0; virtual bool SetValueI(const AString & a_KeyName, const AString & a_ValueName, const int a_Value, const bool a_CreateIfNotExists = true) = 0; /** Deletes the specified key, value pair */ virtual bool DeleteValue(const AString & keyname, const AString & valuename) = 0; /** Writes the changes to the backing store, if the repository has one */ virtual bool Flush() = 0; }; ================================================ FILE: src/Simulator/CMakeLists.txt ================================================ target_sources( ${CMAKE_PROJECT_NAME} PRIVATE DelayedFluidSimulator.cpp FireSimulator.cpp FloodyFluidSimulator.cpp FluidSimulator.cpp SandSimulator.cpp Simulator.cpp SimulatorManager.cpp VanillaFluidSimulator.cpp VaporizeFluidSimulator.cpp DelayedFluidSimulator.h FireSimulator.h FloodyFluidSimulator.h FluidSimulator.h NoopFluidSimulator.h NoopRedstoneSimulator.h RedstoneSimulator.h SandSimulator.h Simulator.h SimulatorManager.h VanillaFluidSimulator.h VaporizeFluidSimulator.h ) ================================================ FILE: src/Simulator/DelayedFluidSimulator.cpp ================================================ // DelayedFluidSimulator.cpp // Interfaces to the cDelayedFluidSimulator class representing a fluid simulator that has a configurable delay // before simulating a block. Each tick it takes a consecutive delay "slot" and simulates only blocks in that slot. #include "Globals.h" #include "DelayedFluidSimulator.h" #include "../World.h" #include "../Chunk.h" //////////////////////////////////////////////////////////////////////////////// // cDelayedFluidSimulatorChunkData::cSlot bool cDelayedFluidSimulatorChunkData::cSlot::Add(int a_RelX, int a_RelY, int a_RelZ) { ASSERT(a_RelZ >= 0); ASSERT(a_RelZ < static_cast(ARRAYCOUNT(m_Blocks))); auto & Blocks = m_Blocks[a_RelZ]; const auto Index = cChunkDef::MakeIndex(a_RelX, a_RelY, a_RelZ); for (const auto & Block : Blocks) { if (Block.Data == Index) { // Already present return false; } } // for itr - Blocks[] Blocks.emplace_back(a_RelX, a_RelY, a_RelZ, Index); return true; } //////////////////////////////////////////////////////////////////////////////// // cDelayedFluidSimulatorChunkData: cDelayedFluidSimulatorChunkData::cDelayedFluidSimulatorChunkData(int a_TickDelay) : m_Slots(new cSlot[ToUnsigned(a_TickDelay)]) { } cDelayedFluidSimulatorChunkData::~cDelayedFluidSimulatorChunkData() { delete[] m_Slots; m_Slots = nullptr; } //////////////////////////////////////////////////////////////////////////////// // cDelayedFluidSimulator: cDelayedFluidSimulator::cDelayedFluidSimulator(cWorld & a_World, BLOCKTYPE a_Fluid, BLOCKTYPE a_StationaryFluid, int a_TickDelay) : Super(a_World, a_Fluid, a_StationaryFluid), m_TickDelay(a_TickDelay), m_AddSlotNum(a_TickDelay - 1), m_SimSlotNum(0), m_TotalBlocks(0) { } void cDelayedFluidSimulator::Simulate(float a_Dt) { m_AddSlotNum = m_SimSlotNum; m_SimSlotNum += 1; if (m_SimSlotNum >= m_TickDelay) { m_SimSlotNum = 0; } } void cDelayedFluidSimulator::SimulateChunk(std::chrono::milliseconds a_Dt, int a_ChunkX, int a_ChunkZ, cChunk * a_Chunk) { auto ChunkDataRaw = (m_FluidBlock == E_BLOCK_WATER) ? a_Chunk->GetWaterSimulatorData() : a_Chunk->GetLavaSimulatorData(); cDelayedFluidSimulatorChunkData * ChunkData = static_cast(ChunkDataRaw); cDelayedFluidSimulatorChunkData::cSlot & Slot = ChunkData->m_Slots[m_SimSlotNum]; // Simulate all the blocks in the scheduled slot: for (size_t i = 0; i < ARRAYCOUNT(Slot.m_Blocks); i++) { auto & Blocks = Slot.m_Blocks[i]; if (Blocks.empty()) { continue; } for (const auto & Block : Blocks) { SimulateBlock(a_Chunk, Block.x, Block.y, Block.z); } m_TotalBlocks -= static_cast(Blocks.size()); Blocks.clear(); } } void cDelayedFluidSimulator::AddBlock(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_Block) { if ((a_Block != m_FluidBlock) && (a_Block != m_StationaryFluidBlock)) { return; } auto ChunkDataRaw = (m_FluidBlock == E_BLOCK_WATER) ? a_Chunk.GetWaterSimulatorData() : a_Chunk.GetLavaSimulatorData(); cDelayedFluidSimulatorChunkData * ChunkData = static_cast(ChunkDataRaw); cDelayedFluidSimulatorChunkData::cSlot & Slot = ChunkData->m_Slots[m_AddSlotNum]; // Add, if not already present: if (!Slot.Add(a_Position.x, a_Position.y, a_Position.z)) { return; } ++m_TotalBlocks; } ================================================ FILE: src/Simulator/DelayedFluidSimulator.h ================================================ // DelayedFluidSimulator.h // Interfaces to the cDelayedFluidSimulator class representing a fluid simulator that has a configurable delay // before simulating a block. Each tick it takes a consecutive delay "slot" and simulates only blocks in that slot. #pragma once #include "FluidSimulator.h" class cDelayedFluidSimulatorChunkData : public cFluidSimulatorData { public: class cSlot { public: /** Returns true if the specified block is stored */ bool HasBlock(int a_RelX, int a_RelY, int a_RelZ); /** Adds the specified block unless already present; returns true if added, false if the block was already present */ bool Add(int a_RelX, int a_RelY, int a_RelZ); /** Array of block containers, each item stores blocks for one Z coord size_t param is the block index (for faster duplicate comparison in Add()) */ std::vector> m_Blocks[16]; } ; cDelayedFluidSimulatorChunkData(int a_TickDelay); virtual ~cDelayedFluidSimulatorChunkData() override; /** Slots, one for each delay tick, each containing the blocks to simulate */ cSlot * m_Slots; } ; class cDelayedFluidSimulator: public cFluidSimulator { using Super = cFluidSimulator; public: cDelayedFluidSimulator(cWorld & a_World, BLOCKTYPE a_Fluid, BLOCKTYPE a_StationaryFluid, int a_TickDelay); protected: virtual void Simulate(float a_Dt) override; virtual void SimulateChunk(std::chrono::milliseconds a_Dt, int a_ChunkX, int a_ChunkZ, cChunk * a_Chunk) override; virtual void AddBlock(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_Block) override; virtual cFluidSimulatorData * CreateChunkData(void) override { return new cDelayedFluidSimulatorChunkData(m_TickDelay); } int m_TickDelay; // Count of the m_Slots array in each ChunkData int m_AddSlotNum; // Index into m_Slots[] where to add new blocks in each ChunkData int m_SimSlotNum; // Index into m_Slots[] where to simulate blocks in each ChunkData int m_TotalBlocks; // Statistics only: the total number of blocks currently queued /* Slots: | 0 | 1 | ... | m_AddSlotNum | m_SimSlotNum | ... | m_TickDelay - 1 | | adding blocks here ^ | ^ simulating here */ /** Called from SimulateChunk() to simulate each block in one slot of blocks. Descendants override this method to provide custom simulation. */ virtual void SimulateBlock(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ) = 0; } ; ================================================ FILE: src/Simulator/FireSimulator.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "FireSimulator.h" #include "../BlockInfo.h" #include "../World.h" #include "../Defines.h" #include "../Chunk.h" #include "../Root.h" #include "../Bindings/PluginManager.h" // Easy switch for turning on debugging logging: #if 0 #define FIRE_FLOG FLOGD #else #define FIRE_FLOG(...) #endif #define MAX_CHANCE_REPLACE_FUEL 100000 #define MAX_CHANCE_FLAMMABILITY 100000 // The base chance that in a tick, rain will extinguish a fire block. #define CHANCE_BASE_RAIN_EXTINGUISH 0.2 // The additional chance, multiplied by the meta of the fire block, that rain // will extinguish a fire block in a tick. #define CHANCE_AGE_M_RAIN_EXTINGUISH 0.03 static constexpr Vector3i gCrossCoords[] = { { 1, 0, 0}, {-1, 0, 0}, { 0, 0, 1}, { 0, 0, -1}, } ; static constexpr Vector3i gNeighborCoords[] = { { 1, 0, 0}, {-1, 0, 0}, { 0, 1, 0}, { 0, -1, 0}, { 0, 0, 1}, { 0, 0, -1}, }; //////////////////////////////////////////////////////////////////////////////// // cFireSimulator: cFireSimulator::cFireSimulator(cWorld & a_World, cIniFile & a_IniFile) : cSimulator(a_World) { // Read params from the ini file: m_BurnStepTimeFuel = static_cast(a_IniFile.GetValueSetI("FireSimulator", "BurnStepTimeFuel", 500)); m_BurnStepTimeNonfuel = static_cast(a_IniFile.GetValueSetI("FireSimulator", "BurnStepTimeNonfuel", 100)); m_Flammability = a_IniFile.GetValueSetI("FireSimulator", "Flammability", 50); m_ReplaceFuelChance = a_IniFile.GetValueSetI("FireSimulator", "ReplaceFuelChance", 50000); } void cFireSimulator::SimulateChunk(std::chrono::milliseconds a_Dt, int a_ChunkX, int a_ChunkZ, cChunk * a_Chunk) { cCoordWithIntList & Data = a_Chunk->GetFireSimulatorData(); int NumMSecs = static_cast(a_Dt.count()); for (cCoordWithIntList::iterator itr = Data.begin(); itr != Data.end();) { Vector3i relPos(itr->x, itr->y, itr->z); auto blockType = a_Chunk->GetBlock(relPos); if (!IsAllowedBlock(blockType)) { // The block is no longer eligible (not a fire block anymore; a player probably placed a block over the fire) FIRE_FLOG("FS: Removing block {0}", absPos); itr = Data.erase(itr); continue; } auto BurnsForever = ((relPos.y > 0) && DoesBurnForever(a_Chunk->GetBlock(relPos.addedY(-1)))); auto BlockMeta = a_Chunk->GetMeta(relPos); auto Raining = std::any_of(std::begin(gCrossCoords), std::end(gCrossCoords), [a_Chunk, relPos](Vector3i cc) { auto Adjusted = relPos + cc; const auto Chunk = a_Chunk->GetRelNeighborChunkAdjustCoords(Adjusted); if ((Chunk != nullptr) && Chunk->IsValid()) { return Chunk->IsWeatherWetAt(Adjusted); } return false; }); // Randomly burn out the fire if it is raining: if (!BurnsForever && Raining && GetRandomProvider().RandBool(CHANCE_BASE_RAIN_EXTINGUISH + (BlockMeta * CHANCE_AGE_M_RAIN_EXTINGUISH))) { a_Chunk->SetBlock(relPos, E_BLOCK_AIR, 0); itr = Data.erase(itr); continue; } // Try to spread the fire: TrySpreadFire(a_Chunk, relPos); itr->Data -= NumMSecs; if (itr->Data >= 0) { // Not yet, wait for it longer ++itr; continue; } // FIRE_FLOG("FS: Fire at {0} is stepping", absPos); // TODO: Add some randomness into this const auto BurnStep = GetBurnStepTime(a_Chunk, relPos); if (BurnStep == 0) { // Fire has no fuel or ground block, extinguish flame a_Chunk->SetBlock(relPos, E_BLOCK_AIR, 0); itr = Data.erase(itr); continue; } // Has the fire burnt out? if (BlockMeta == 0x0f) { // The fire burnt out completely FIRE_FLOG("FS: Fire at {0} burnt out, removing the fire block", absPos); a_Chunk->SetBlock(relPos, E_BLOCK_AIR, 0); RemoveFuelNeighbors(a_Chunk, relPos); itr = Data.erase(itr); continue; } // Burn out the fire one step by increasing the meta: if (!BurnsForever) { a_Chunk->SetMeta(relPos, BlockMeta + 1); } itr->Data = BurnStep; ++itr; } // for itr - Data[] } bool cFireSimulator::IsAllowedBlock(BLOCKTYPE a_BlockType) { return (a_BlockType == E_BLOCK_FIRE); } bool cFireSimulator::IsFuel(BLOCKTYPE a_BlockType) { switch (a_BlockType) { case E_BLOCK_PLANKS: case E_BLOCK_DOUBLE_WOODEN_SLAB: case E_BLOCK_WOODEN_SLAB: case E_BLOCK_OAK_WOOD_STAIRS: case E_BLOCK_SPRUCE_WOOD_STAIRS: case E_BLOCK_BIRCH_WOOD_STAIRS: case E_BLOCK_JUNGLE_WOOD_STAIRS: case E_BLOCK_LEAVES: case E_BLOCK_NEW_LEAVES: case E_BLOCK_LOG: case E_BLOCK_NEW_LOG: case E_BLOCK_WOOL: case E_BLOCK_BOOKCASE: case E_BLOCK_FENCE: case E_BLOCK_SPRUCE_FENCE: case E_BLOCK_BIRCH_FENCE: case E_BLOCK_JUNGLE_FENCE: case E_BLOCK_DARK_OAK_FENCE: case E_BLOCK_ACACIA_FENCE: case E_BLOCK_OAK_FENCE_GATE: case E_BLOCK_SPRUCE_FENCE_GATE: case E_BLOCK_BIRCH_FENCE_GATE: case E_BLOCK_JUNGLE_FENCE_GATE: case E_BLOCK_DARK_OAK_FENCE_GATE: case E_BLOCK_ACACIA_FENCE_GATE: case E_BLOCK_TNT: case E_BLOCK_VINES: case E_BLOCK_HAY_BALE: case E_BLOCK_TALL_GRASS: case E_BLOCK_BIG_FLOWER: case E_BLOCK_DANDELION: case E_BLOCK_FLOWER: case E_BLOCK_CARPET: { return true; } } return false; } bool cFireSimulator::DoesBurnForever(BLOCKTYPE a_BlockType) { return (a_BlockType == E_BLOCK_NETHERRACK); } void cFireSimulator::AddBlock(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_Block) { if (!IsAllowedBlock(a_Block)) { return; } // Check for duplicates: cFireSimulatorChunkData & ChunkData = a_Chunk.GetFireSimulatorData(); for (cCoordWithIntList::iterator itr = ChunkData.begin(), end = ChunkData.end(); itr != end; ++itr) { const Vector3i ItrPos{itr->x, itr->y, itr->z}; if (ItrPos == a_Position) { // Block already present, check if burn step should decrease // This means if fuel is removed, then the fire burns out sooner const auto NewBurnStep = GetBurnStepTime(&a_Chunk, a_Position); if (itr->Data > NewBurnStep) { FIRE_FLOG("FS: Block lost its fuel at {0}", a_Block); itr->Data = NewBurnStep; } return; } } // for itr - ChunkData[] FIRE_FLOG("FS: Adding block {0}", a_Block); ChunkData.emplace_back(a_Position.x, a_Position.y, a_Position.z, 100); } int cFireSimulator::GetBurnStepTime(cChunk * a_Chunk, Vector3i a_RelPos) { bool IsBlockBelowSolid = false; if (a_RelPos.y > 0) { BLOCKTYPE BlockBelow = a_Chunk->GetBlock(a_RelPos.addedY(-1)); if (DoesBurnForever(BlockBelow)) { // Is burning atop of netherrack, burn forever (re-check in 10 sec) return 10000; } if (IsFuel(BlockBelow)) { return static_cast(m_BurnStepTimeFuel); } IsBlockBelowSolid = cBlockInfo::IsSolid(BlockBelow); } for (const auto & cross: gCrossCoords) { BLOCKTYPE BlockType; NIBBLETYPE BlockMeta; if (a_Chunk->UnboundedRelGetBlock(a_RelPos + cross, BlockType, BlockMeta)) { if (IsFuel(BlockType)) { return static_cast(m_BurnStepTimeFuel); } } } // for i - gCrossCoords[] if (!IsBlockBelowSolid) { // Checked through everything, nothing was flammable // If block below isn't solid, we can't have fire, it would be a non-fueled fire return 0; } return static_cast(m_BurnStepTimeNonfuel); } void cFireSimulator::TrySpreadFire(cChunk * a_Chunk, Vector3i a_RelPos) { /* if (GetRandomProvider().RandBool(0.99)) { // Make the chance to spread 100x smaller return; } */ for (int x = -1; x <= 1; x++) { for (int z = -1; z <= 1; z++) { for (int y = 1; y <= 2; y++) // flames spread up one more block than around { // No need to check the coords for equality with the parent block, // it cannot catch fire anyway (because it's not an air block) if (!GetRandomProvider().RandBool(m_Flammability * (1.0 / MAX_CHANCE_FLAMMABILITY))) { continue; } // Start the fire in the neighbor a_RelPos + {x, y, z} auto dstRelPos = a_RelPos + Vector3i{x, y, z}; if (CanStartFireInBlock(a_Chunk, dstRelPos)) { auto dstAbsPos = a_Chunk->RelativeToAbsolute(dstRelPos); if (cRoot::Get()->GetPluginManager()->CallHookBlockSpread(m_World, dstAbsPos, ssFireSpread)) { return; } FIRE_FLOG("FS: Starting new fire at {0}.", dstAbsPos); a_Chunk->UnboundedRelSetBlock(dstRelPos, E_BLOCK_FIRE, 0); } } // for y } // for z } // for x } void cFireSimulator::RemoveFuelNeighbors(cChunk * a_Chunk, Vector3i a_RelPos) { for (auto & coord : gNeighborCoords) { auto relPos = a_RelPos + coord; if (!cChunkDef::IsValidHeight(relPos)) { continue; } const auto neighbor = a_Chunk->GetRelNeighborChunkAdjustCoords(relPos); if ((neighbor == nullptr) || !neighbor->IsValid()) { continue; } BLOCKTYPE BlockType = neighbor->GetBlock(relPos); if (!IsFuel(BlockType)) { continue; } auto absPos = neighbor->RelativeToAbsolute(relPos); if (BlockType == E_BLOCK_TNT) { neighbor->SetBlock(relPos, E_BLOCK_AIR, 0); m_World.SpawnPrimedTNT(Vector3d(absPos) + Vector3d(0.5, 0.5, 0.5)); // 80 ticks to boom return; } bool ShouldReplaceFuel = (GetRandomProvider().RandBool(m_ReplaceFuelChance * (1.0 / MAX_CHANCE_REPLACE_FUEL))); if (ShouldReplaceFuel && !cRoot::Get()->GetPluginManager()->CallHookBlockSpread(m_World, absPos, ssFireSpread)) { neighbor->SetBlock(relPos, E_BLOCK_FIRE, 0); } else { neighbor->SetBlock(relPos, E_BLOCK_AIR, 0); } } // for i - Coords[] } bool cFireSimulator::CanStartFireInBlock(cChunk * a_NearChunk, Vector3i a_RelPos) { BLOCKTYPE BlockType; NIBBLETYPE BlockMeta; if (!a_NearChunk->UnboundedRelGetBlock(a_RelPos, BlockType, BlockMeta)) { // The chunk is not accessible return false; } if (BlockType != E_BLOCK_AIR) { // Only an air block can be replaced by a fire block return false; } for (const auto & neighbor: gNeighborCoords) { if (!a_NearChunk->UnboundedRelGetBlock(a_RelPos + neighbor, BlockType, BlockMeta)) { // Neighbor inaccessible, skip it while evaluating continue; } if (IsFuel(BlockType)) { return true; } } // for i - Coords[] return false; } ================================================ FILE: src/Simulator/FireSimulator.h ================================================ #pragma once #include "Simulator.h" #include "../IniFile.h" /** The fire simulator takes care of the fire blocks. It periodically increases their meta ("steps") until they "burn out"; it also supports the forever burning netherrack. Each individual fire block gets stored in per-chunk data; that list is then used for fast retrieval. The data value associated with each coord is used as the number of msec that the fire takes until it progresses to the next step (blockmeta++). This value is updated if a neighbor is changed. The simulator reads its parameters from the ini file given to the constructor. */ class cFireSimulator : public cSimulator { public: cFireSimulator(cWorld & a_World, cIniFile & a_IniFile); static bool IsFuel (BLOCKTYPE a_BlockType); static bool DoesBurnForever(BLOCKTYPE a_BlockType); private: virtual void SimulateChunk(std::chrono::milliseconds a_Dt, int a_ChunkX, int a_ChunkZ, cChunk * a_Chunk) override; static bool IsAllowedBlock(BLOCKTYPE a_BlockType); /** Time (in msec) that a fire block takes to burn with a fuel block into the next step */ unsigned m_BurnStepTimeFuel; /** Time (in msec) that a fire block takes to burn without a fuel block into the next step */ unsigned m_BurnStepTimeNonfuel; /** Chance [0..100000] of an adjacent fuel to catch fire on each tick */ int m_Flammability; /** Chance [0..100000] of a fuel burning out being replaced by a new fire block instead of an air block */ int m_ReplaceFuelChance; virtual void AddBlock(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_Block) override; /** Returns the time [msec] after which the specified fire block is stepped again; based on surrounding fuels */ int GetBurnStepTime(cChunk * a_Chunk, Vector3i a_RelPos); /** Tries to spread fire to a neighborhood of the specified block */ void TrySpreadFire(cChunk * a_Chunk, Vector3i a_RelPos); /** Removes all burnable blocks neighboring the specified block */ void RemoveFuelNeighbors(cChunk * a_Chunk, Vector3i a_RelPos); /** Returns true if a fire can be started in the specified block, that is, it is an air block and has fuel next to it. Note that a_NearChunk may be a chunk neighbor to the block specified! The coords are relative to a_NearChunk but not necessarily in it. */ bool CanStartFireInBlock(cChunk * a_NearChunk, Vector3i a_RelPos); } ; /** Stores individual fire blocks in the chunk; the int data is used as the time [msec] the fire takes to step to another stage (blockmeta++) */ typedef cCoordWithIntList cFireSimulatorChunkData; ================================================ FILE: src/Simulator/FloodyFluidSimulator.cpp ================================================ // FloodyFluidSimulator.cpp // Interfaces to the cFloodyFluidSimulator that represents a fluid simulator that tries to flood everything :) // https://forum.cuberite.org/thread-565.html #include "Globals.h" #include "FloodyFluidSimulator.h" #include "../BlockInfo.h" #include "../World.h" #include "../Chunk.h" #include "../BlockArea.h" #include "../Blocks/BlockHandler.h" #include "../BlockInServerPluginInterface.h" #include "../Blocks/ChunkInterface.h" // Enable or disable detailed logging #if 0 #define FLUID_FLOG FLOGD #else #define FLUID_FLOG(...) #endif cFloodyFluidSimulator::cFloodyFluidSimulator( cWorld & a_World, BLOCKTYPE a_Fluid, BLOCKTYPE a_StationaryFluid, NIBBLETYPE a_Falloff, int a_TickDelay, int a_NumNeighborsForSource ) : Super(a_World, a_Fluid, a_StationaryFluid, a_TickDelay), m_Falloff(a_Falloff), m_NumNeighborsForSource(a_NumNeighborsForSource) { } void cFloodyFluidSimulator::SimulateBlock(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ) { FLUID_FLOG("Simulating block {0}: block {1}, meta {2}", a_Chunk->PositionToWorldPosition(a_RelX, a_RelY, a_RelZ), a_Chunk->GetBlock(a_RelX, a_RelY, a_RelZ), a_Chunk->GetMeta(a_RelX, a_RelY, a_RelZ) ); BLOCKTYPE MyBlock; NIBBLETYPE MyMeta; a_Chunk->GetBlockTypeMeta(a_RelX, a_RelY, a_RelZ, MyBlock, MyMeta); if (!IsAnyFluidBlock(MyBlock)) { // Can happen - if a block is scheduled for simulating and gets replaced in the meantime. FLUID_FLOG(" BadBlockType exit"); return; } // When in contact with water, lava should harden if (HardenBlock(a_Chunk, {a_RelX, a_RelY, a_RelZ}, MyBlock, MyMeta)) { // Block was changed, bail out return; } if (MyMeta != 0) { // Source blocks aren't checked for tributaries, others are. if (CheckTributaries(a_Chunk, a_RelX, a_RelY, a_RelZ, MyMeta)) { // Has no tributary, has been decreased (in CheckTributaries()), // no more processing needed (neighbors have been scheduled by the decrease) FLUID_FLOG(" CheckTributaries exit"); return; } } // New meta for the spreading to neighbors: // If this is a source block or was falling, the new meta is just the falloff // Otherwise it is the current meta plus falloff (may be larger than max height, will be checked later) NIBBLETYPE NewMeta = ((MyMeta == 0) || ((MyMeta & 0x08) != 0)) ? m_Falloff : (MyMeta + m_Falloff); if (a_RelY > 0) { bool SpreadFurther = true; BLOCKTYPE Below = a_Chunk->GetBlock(a_RelX, a_RelY - 1, a_RelZ); if (IsPassableForFluid(Below) || IsBlockLava(Below) || IsBlockWater(Below)) { // Spread only down, possibly washing away what's there or turning lava to stone / cobble / obsidian: SpreadToNeighbor(a_Chunk, a_RelX, a_RelY - 1, a_RelZ, 8); // Source blocks spread both downwards and sideways if (MyMeta != 0) { SpreadFurther = false; } } // Spread to the neighbors: if (SpreadFurther && (NewMeta < 8)) { SpreadXZ(a_Chunk, a_RelX, a_RelY, a_RelZ, NewMeta); } // If source creation is on, check for it here: if ( (m_NumNeighborsForSource > 0) && // Source creation is on (MyMeta == m_Falloff) && // Only exactly one block away from a source (fast bail-out) ( !IsPassableForFluid(Below) || // Only exactly 1 block deep (Below == m_StationaryFluidBlock) // Or a source block underneath ) && CheckNeighborsForSource(a_Chunk, a_RelX, a_RelY, a_RelZ) // Did we create a source? ) { // We created a source, no more spreading is to be done now // Also has been re-scheduled for ticking in the next wave, so no marking is needed return; } } // Mark as processed: a_Chunk->FastSetBlock(a_RelX, a_RelY, a_RelZ, m_StationaryFluidBlock, MyMeta); } void cFloodyFluidSimulator::SpreadXZ(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_NewMeta) { SpreadToNeighbor(a_Chunk, a_RelX - 1, a_RelY, a_RelZ, a_NewMeta); SpreadToNeighbor(a_Chunk, a_RelX + 1, a_RelY, a_RelZ, a_NewMeta); SpreadToNeighbor(a_Chunk, a_RelX, a_RelY, a_RelZ - 1, a_NewMeta); SpreadToNeighbor(a_Chunk, a_RelX, a_RelY, a_RelZ + 1, a_NewMeta); } bool cFloodyFluidSimulator::CheckTributaries(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_MyMeta) { // If we have a section above, check if there's fluid above this block that would feed it: if (a_RelY < cChunkDef::Height - 1) { if (IsAnyFluidBlock(a_Chunk->GetBlock(a_RelX, a_RelY + 1, a_RelZ))) { // This block is fed from above, no more processing needed FLUID_FLOG(" Fed from above"); return false; } } // Not fed from above, check if there's a feed from the side (but not if it's a downward-flowing block): if (a_MyMeta != 8) { BLOCKTYPE BlockType; NIBBLETYPE BlockMeta; static const Vector3i Coords[] = { Vector3i( 1, 0, 0), Vector3i(-1, 0, 0), Vector3i( 0, 0, 1), Vector3i( 0, 0, -1), } ; for (size_t i = 0; i < ARRAYCOUNT(Coords); i++) { if (!a_Chunk->UnboundedRelGetBlock(a_RelX + Coords[i].x, a_RelY, a_RelZ + Coords[i].z, BlockType, BlockMeta)) { continue; } if (IsAllowedBlock(BlockType) && IsHigherMeta(BlockMeta, a_MyMeta)) { // This block is fed, no more processing needed FLUID_FLOG(" Fed from {0}, type {1}, meta {2}", a_Chunk->PositionToWorldPosition(a_RelX+ Coords[i].x, a_RelY, a_RelZ + Coords[i].z), BlockType, BlockMeta ); return false; } } // for i - Coords[] } // if not fed from above // Block is not fed, decrease by m_Falloff levels: if (a_MyMeta >= 8) { FLUID_FLOG(" Not fed and downwards, turning into non-downwards meta {0}", m_Falloff); a_Chunk->SetBlock({a_RelX, a_RelY, a_RelZ}, m_StationaryFluidBlock, m_Falloff); } else { a_MyMeta += m_Falloff; if (a_MyMeta < 8) { FLUID_FLOG(" Not fed, decreasing from {0} to {1}", a_MyMeta - m_Falloff, a_MyMeta); a_Chunk->SetBlock({a_RelX, a_RelY, a_RelZ}, m_StationaryFluidBlock, a_MyMeta); } else { FLUID_FLOG(" Not fed, meta {0}, erasing altogether", a_MyMeta); a_Chunk->SetBlock({a_RelX, a_RelY, a_RelZ}, E_BLOCK_AIR, 0); } } return true; } void cFloodyFluidSimulator::SpreadToNeighbor(cChunk * a_NearChunk, int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_NewMeta) { ASSERT(a_NewMeta <= 8); // Invalid meta values ASSERT(a_NewMeta > 0); // Source blocks aren't spread Vector3i relPos(a_RelX, a_RelY, a_RelZ); a_NearChunk = a_NearChunk->GetRelNeighborChunkAdjustCoords(relPos); if ((a_NearChunk == nullptr) || (!a_NearChunk->IsValid())) { // Chunk not available return; } const auto absPos = a_NearChunk->RelativeToAbsolute(relPos); BLOCKTYPE BlockType; NIBBLETYPE BlockMeta; a_NearChunk->GetBlockTypeMeta(relPos, BlockType, BlockMeta); if (IsAllowedBlock(BlockType)) { if ((BlockMeta == a_NewMeta) || IsHigherMeta(BlockMeta, a_NewMeta)) { // Don't spread there, there's already a higher or same level there return; } } // Check water - lava interaction: if (m_FluidBlock == E_BLOCK_LAVA) { if (IsBlockWater(BlockType)) { // Lava flowing into water, change to stone / cobblestone based on direction: BLOCKTYPE NewBlock = (a_NewMeta == 8) ? E_BLOCK_STONE : E_BLOCK_COBBLESTONE; FLUID_FLOG(" Lava flowing into water, turning water at rel {0} into {1}", relPos, ItemTypeToString(NewBlock) ); a_NearChunk->SetBlock(relPos, NewBlock, 0); m_World.BroadcastSoundEffect( "block.lava.extinguish", absPos, 0.5f, 1.5f ); return; } } else if (m_FluidBlock == E_BLOCK_WATER) { if (IsBlockLava(BlockType)) { // Water flowing into lava, change to cobblestone / obsidian based on dest block: BLOCKTYPE NewBlock = (BlockMeta == 0) ? E_BLOCK_OBSIDIAN : E_BLOCK_COBBLESTONE; FLUID_FLOG(" Water flowing into lava, turning lava at rel {0} into {1}", relPos, ItemTypeToString(NewBlock) ); a_NearChunk->SetBlock(relPos, NewBlock, 0); m_World.BroadcastSoundEffect( "block.lava.extinguish", absPos, 0.5f, 1.5f ); return; } } else { ASSERT(!"Unknown fluid!"); } if (!IsPassableForFluid(BlockType)) { // Can't spread there return; } // Wash away the block there, if possible: if (CanWashAway(BlockType)) { m_World.DropBlockAsPickups(absPos, nullptr, nullptr); } // if (CanWashAway) // Spread: FLUID_FLOG(" Spreading to {0} with meta {1}", absPos, a_NewMeta); a_NearChunk->SetBlock(relPos, m_FluidBlock, a_NewMeta); m_World.GetSimulatorManager()->WakeUp(*a_NearChunk, relPos); HardenBlock(a_NearChunk, relPos, m_FluidBlock, a_NewMeta); } bool cFloodyFluidSimulator::CheckNeighborsForSource(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ) { FLUID_FLOG(" Checking neighbors for source creation"); static const Vector3i NeighborCoords[] = { Vector3i(-1, 0, 0), Vector3i( 1, 0, 0), Vector3i( 0, 0, -1), Vector3i( 0, 0, 1), } ; int NumNeeded = m_NumNeighborsForSource; for (size_t i = 0; i < ARRAYCOUNT(NeighborCoords); i++) { int x = a_RelX + NeighborCoords[i].x; int y = a_RelY + NeighborCoords[i].y; int z = a_RelZ + NeighborCoords[i].z; BLOCKTYPE BlockType; NIBBLETYPE BlockMeta; if (!a_Chunk->UnboundedRelGetBlock(x, y, z, BlockType, BlockMeta)) { // Neighbor not available, skip it continue; } // FLUID_FLOG(" Neighbor at {0}: {1}", Vector3i{x, y, z}, ItemToFullString(cItem(BlockType, 1, BlockMeta))); if ((BlockMeta == 0) && IsAnyFluidBlock(BlockType)) { NumNeeded--; // FLUID_FLOG(" Found a neighbor source at {0}, NumNeeded := {1}", Vector3i{x, y, z}, NumNeeded); if (NumNeeded == 0) { // Found enough, turn into a source and bail out // FLUID_FLOG(" Found enough neighbor sources, turning into a source"); a_Chunk->SetBlock({a_RelX, a_RelY, a_RelZ}, m_FluidBlock, 0); return true; } } } // FLUID_FLOG(" Not enough neighbors for turning into a source, NumNeeded = {0}", NumNeeded); return false; } bool cFloodyFluidSimulator::HardenBlock(cChunk * a_Chunk, Vector3i a_RelPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) { ASSERT(cChunkDef::IsValidRelPos(a_RelPos)); // Only lava blocks can harden if (!IsBlockLava(a_BlockType)) { return false; } bool ShouldHarden = false; BLOCKTYPE BlockType; NIBBLETYPE BlockMeta; static const Vector3i neighborOffsets[] = { Vector3i( 1, 0, 0), Vector3i(-1, 0, 0), Vector3i( 0, 0, 1), Vector3i( 0, 0, -1), }; for (const auto & ofs: neighborOffsets) { if (!a_Chunk->UnboundedRelGetBlock(a_RelPos + ofs, BlockType, BlockMeta)) { continue; } if (IsBlockWater(BlockType)) { ShouldHarden = true; } } // for i - Coords[] if (ShouldHarden) { if (a_Meta == 0) { // Source lava block a_Chunk->SetBlock(a_RelPos, E_BLOCK_OBSIDIAN, 0); return true; } // Ignore last lava level else if (a_Meta <= 4) { a_Chunk->SetBlock(a_RelPos, E_BLOCK_COBBLESTONE, 0); return true; } } return false; } ================================================ FILE: src/Simulator/FloodyFluidSimulator.h ================================================ // FloodyFluidSimulator.h // Interfaces to the cFloodyFluidSimulator that represents a fluid simulator that tries to flood everything :) // https://forum.cuberite.org/thread-565.html #pragma once #include "DelayedFluidSimulator.h" class cFloodyFluidSimulator: public cDelayedFluidSimulator { using Super = cDelayedFluidSimulator; public: cFloodyFluidSimulator(cWorld & a_World, BLOCKTYPE a_Fluid, BLOCKTYPE a_StationaryFluid, NIBBLETYPE a_Falloff, int a_TickDelay, int a_NumNeighborsForSource); protected: NIBBLETYPE m_Falloff; int m_NumNeighborsForSource; // cDelayedFluidSimulator overrides: virtual void SimulateBlock(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ) override; /** Checks tributaries, if not fed, decreases the block's level and returns true. */ bool CheckTributaries(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_MyMeta); /** Spreads into the specified block, if the blocktype there allows. a_Area is for checking. */ void SpreadToNeighbor(cChunk * a_NearChunk, int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_NewMeta); /** Checks if there are enough neighbors to create a source at the coords specified; turns into source and returns true if so. */ bool CheckNeighborsForSource(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ); /** Checks if the specified block should harden (Water / Lava interaction) and if so, converts it to a suitable block. Returns whether the block was changed or not. */ bool HardenBlock(cChunk * a_Chunk, Vector3i a_RelPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta); /** Spread fluid to XZ neighbors. The coords are of the block currently being processed; a_NewMeta is the new meta for the new fluid block. Descendants may overridde to provide more sophisticated algorithms. */ virtual void SpreadXZ(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_NewMeta); } ; ================================================ FILE: src/Simulator/FluidSimulator.cpp ================================================ #include "Globals.h" #include "FluidSimulator.h" #include "../World.h" cFluidSimulator::cFluidSimulator(cWorld & a_World, BLOCKTYPE a_Fluid, BLOCKTYPE a_StationaryFluid) : Super(a_World), m_FluidBlock(a_Fluid), m_StationaryFluidBlock(a_StationaryFluid) { } bool cFluidSimulator::IsAllowedBlock(BLOCKTYPE a_BlockType) { return ((a_BlockType == m_FluidBlock) || (a_BlockType == m_StationaryFluidBlock)); } bool cFluidSimulator::CanWashAway(BLOCKTYPE a_BlockType) { switch (a_BlockType) { case E_BLOCK_ACTIVATOR_RAIL: case E_BLOCK_ACTIVE_COMPARATOR: case E_BLOCK_BEETROOTS: case E_BLOCK_BIG_FLOWER: case E_BLOCK_BROWN_MUSHROOM: case E_BLOCK_CACTUS: case E_BLOCK_CARROTS: case E_BLOCK_COBWEB: case E_BLOCK_CROPS: case E_BLOCK_DEAD_BUSH: case E_BLOCK_DETECTOR_RAIL: case E_BLOCK_INACTIVE_COMPARATOR: case E_BLOCK_LILY_PAD: case E_BLOCK_POTATOES: case E_BLOCK_POWERED_RAIL: case E_BLOCK_RAIL: case E_BLOCK_REDSTONE_REPEATER_OFF: case E_BLOCK_REDSTONE_REPEATER_ON: case E_BLOCK_REDSTONE_TORCH_OFF: case E_BLOCK_REDSTONE_TORCH_ON: case E_BLOCK_REDSTONE_WIRE: case E_BLOCK_RED_MUSHROOM: case E_BLOCK_RED_ROSE: case E_BLOCK_SNOW: case E_BLOCK_SUGARCANE: case E_BLOCK_TALL_GRASS: case E_BLOCK_TORCH: case E_BLOCK_TRIPWIRE: case E_BLOCK_TRIPWIRE_HOOK: case E_BLOCK_YELLOW_FLOWER: { return true; } default: { return false; } } } bool cFluidSimulator::IsSolidBlock(BLOCKTYPE a_BlockType) { return !IsPassableForFluid(a_BlockType); } bool cFluidSimulator::IsPassableForFluid(BLOCKTYPE a_BlockType) { return ( (a_BlockType == E_BLOCK_AIR) || (a_BlockType == E_BLOCK_FIRE) || IsAllowedBlock(a_BlockType) || CanWashAway(a_BlockType) ); } bool cFluidSimulator::IsHigherMeta(NIBBLETYPE a_Meta1, NIBBLETYPE a_Meta2) { if (a_Meta1 == 0) { // Source block is higher than anything, even itself. return true; } if ((a_Meta1 & 0x08) != 0) { // Falling fluid is higher than anything, including self return true; } if (a_Meta2 == 0) { // Second block is a source and first block isn't return false; } if ((a_Meta2 & 0x08) != 0) { // Second block is falling and the first one is neither a source nor falling return false; } // All special cases have been handled, now it's just a raw comparison: return (a_Meta1 < a_Meta2); } Vector3f cFluidSimulator::GetFlowingDirection(Vector3i a_Pos) { if (!cChunkDef::IsValidHeight(a_Pos)) { return {}; } if (!IsAllowedBlock(m_World.GetBlock(a_Pos))) // No Fluid -> No Flowing direction :D { return {}; } const auto HeightFromMeta = [](NIBBLETYPE a_BlockMeta) -> NIBBLETYPE { // Falling water blocks are always full height (0) return ((a_BlockMeta & 0x08) != 0) ? 0 : a_BlockMeta; }; auto BlockMeta = m_World.GetBlockMeta(a_Pos); NIBBLETYPE CentralPoint = HeightFromMeta(BlockMeta); NIBBLETYPE LevelPoint[4]; // blocks around the checking pos std::array Offsets { { { 1, 0, 0 }, { 0, 0, 1 }, { 1, 0, 0 }, { 0, 0, 1 } } }; for (size_t i = 0; i < Offsets.size(); i++) { if (IsAllowedBlock(m_World.GetBlock(a_Pos + Offsets[i]))) { LevelPoint[i] = HeightFromMeta(m_World.GetBlockMeta(Offsets[i])); } else { LevelPoint[i] = CentralPoint; } } Vector3f Direction; // Calculate the flow direction Direction.x = (LevelPoint[0] - LevelPoint[2]) / 2.0f; Direction.z = (LevelPoint[1] - LevelPoint[3]) / 2.0f; if ((BlockMeta & 0x08) != 0) // Test falling bit { Direction.y = -1.0f; } return Direction; } ================================================ FILE: src/Simulator/FluidSimulator.h ================================================ #pragma once #include "Simulator.h" class cWorld; enum Direction { X_PLUS, X_MINUS, Y_PLUS, Y_MINUS, Z_PLUS, Z_MINUS, NONE }; /** This is a base class for all fluid simulator data classes. Needed so that cChunk can properly delete instances of fluid simulator data, no matter what simulator it's using. */ class cFluidSimulatorData { public: virtual ~cFluidSimulatorData() {} }; class cFluidSimulator: public cSimulator { using Super = cSimulator; public: cFluidSimulator(cWorld & a_World, BLOCKTYPE a_Fluid, BLOCKTYPE a_StationaryFluid); /** Returns a unit vector in the direction the fluid is flowing or a zero-vector if not flowing. */ virtual Vector3f GetFlowingDirection(Vector3i a_Pos); /** Creates a ChunkData object for the simulator to use. The simulator returns the correct object type. */ virtual cFluidSimulatorData * CreateChunkData(void) = 0; bool IsFluidBlock (BLOCKTYPE a_BlockType) const { return (a_BlockType == m_FluidBlock); } bool IsStationaryFluidBlock(BLOCKTYPE a_BlockType) const { return (a_BlockType == m_StationaryFluidBlock); } bool IsAnyFluidBlock (BLOCKTYPE a_BlockType) const { return ((a_BlockType == m_FluidBlock) || (a_BlockType == m_StationaryFluidBlock)); } static bool CanWashAway(BLOCKTYPE a_BlockType); bool IsSolidBlock (BLOCKTYPE a_BlockType); bool IsPassableForFluid(BLOCKTYPE a_BlockType); /** Returns true if a_Meta1 is a higher fluid than a_Meta2. Takes source blocks into account. */ bool IsHigherMeta(NIBBLETYPE a_Meta1, NIBBLETYPE a_Meta2); protected: bool IsAllowedBlock(BLOCKTYPE a_BlockType); BLOCKTYPE m_FluidBlock; // The fluid block type that needs simulating BLOCKTYPE m_StationaryFluidBlock; // The fluid block type that indicates no simulation is needed }; ================================================ FILE: src/Simulator/IncrementalRedstoneSimulator/CMakeLists.txt ================================================ target_sources( ${CMAKE_PROJECT_NAME} PRIVATE ForEachSourceCallback.cpp IncrementalRedstoneSimulator.cpp RedstoneHandler.cpp CommandBlockHandler.h DaylightSensorHandler.h DoorHandler.h DropSpenserHandler.h ForEachSourceCallback.h HopperHandler.h IncrementalRedstoneSimulator.h RedstoneHandler.h RedstoneSimulatorChunkData.h RedstoneComparatorHandler.h RedstoneDataHelper.h RedstoneRepeaterHandler.h RedstoneBlockHandler.h RedstoneTorchHandler.h RedstoneWireHandler.h RedstoneLampHandler.h RedstoneToggleHandler.h PistonHandler.h SmallGateHandler.h NoteBlockHandler.h ObserverHandler.h TNTHandler.h TrappedChestHandler.h TripwireHookHandler.h PoweredRailHandler.h PressurePlateHandler.h ) ================================================ FILE: src/Simulator/IncrementalRedstoneSimulator/CommandBlockHandler.h ================================================ #pragma once #include "../../BlockEntities/CommandBlockEntity.h" namespace CommandBlockHandler { static PowerLevel GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) { UNUSED(a_Chunk); UNUSED(a_Position); UNUSED(a_BlockType); UNUSED(a_QueryPosition); UNUSED(a_QueryBlockType); UNUSED(IsLinked); return 0; } static void Update(cChunk & a_Chunk, cChunk &, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, const PowerLevel Power) { // LOGD("Evaluating commander the cmdblck (%d %d %d)", a_Position.x, a_Position.y, a_Position.z); const auto Previous = DataForChunk(a_Chunk).ExchangeUpdateOncePowerData(a_Position, Power); if ((Previous != 0) || (Power == 0)) { // If we're already powered or received an update of no power, don't activate return; } a_Chunk.DoWithBlockEntityAt(a_Position, [](cBlockEntity & a_BlockEntity) { ASSERT(a_BlockEntity.GetBlockType() == E_BLOCK_COMMAND_BLOCK); static_cast(a_BlockEntity).Activate(); return false; }); } static void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, ForEachSourceCallback & Callback) { UNUSED(a_Chunk); UNUSED(a_BlockType); UNUSED(a_Meta); InvokeForAdjustedRelatives(Callback, a_Position, RelativeAdjacents); } }; ================================================ FILE: src/Simulator/IncrementalRedstoneSimulator/DaylightSensorHandler.h ================================================ #pragma once #include "World.h" namespace DaylightSensorHandler { static PowerLevel GetPowerLevel(const cChunk & a_Chunk, const Vector3i a_Position) { if (a_Chunk.GetBlock(a_Position) == E_BLOCK_INVERTED_DAYLIGHT_SENSOR) { // Inverted sensor directly returns darkened skylight, no fancy tricks: return 15 - a_Chunk.GetSkyLightAltered(a_Position); } // The [0, 1) proportion of the current day that has elapsed. const auto ProportionOfDay = a_Chunk.GetWorld()->GetTimeOfDay().count() * (static_cast(M_PI) / 12000.f); // The curved value of darkened skylight, with outputs somewhat similar to Vanilla. const auto RawOutput = a_Chunk.GetSkyLightAltered(a_Position) * (0.6f * std::sin(ProportionOfDay) + 0.5f); // Saturate the amplified sine curve at 0 and 15: return static_cast(std::clamp(RawOutput, 0.f, 15.f)); } static PowerLevel GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) { UNUSED(a_Chunk); UNUSED(a_BlockType); UNUSED(a_QueryPosition); // Daylight sensors only output to immediately surrounding blocks: return IsLinked ? 0 : a_Chunk.GetMeta(a_Position); } static void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, const PowerLevel Power) { // LOGD("Evaluating Darryl the daylight sensor (%d %d %d)", a_Position.x, a_Position.y, a_Position.z); // What the sensor should output according to the time-power function. const auto PowerLevel = GetPowerLevel(a_Chunk, a_Position); // Only update the output if the power level has changed: if (PowerLevel != a_Meta) { a_Chunk.SetMeta(a_Position, PowerLevel); UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, a_Position, RelativeAdjacents); } } static void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, ForEachSourceCallback & Callback) { UNUSED(a_Chunk); UNUSED(a_Position); UNUSED(a_BlockType); UNUSED(a_Meta); UNUSED(Callback); } }; ================================================ FILE: src/Simulator/IncrementalRedstoneSimulator/DoorHandler.h ================================================ #pragma once #include "../../Blocks/BlockDoor.h" namespace DoorHandler { // "Doormammu, I've come to bargain" static PowerLevel GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) { UNUSED(a_Chunk); UNUSED(a_Position); UNUSED(a_BlockType); UNUSED(a_QueryPosition); UNUSED(a_QueryBlockType); UNUSED(IsLinked); return 0; } static void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, ForEachSourceCallback & Callback) { UNUSED(a_Chunk); UNUSED(a_BlockType); UNUSED(a_Meta); InvokeForAdjustedRelatives(Callback, a_Position, RelativeAdjacents); } static void Update(cChunk & a_Chunk, cChunk &, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PowerLevel Power) { // LOGD("Evaluating dori the door (%d %d %d)", a_Position.x, a_Position.y, a_Position.z); NIBBLETYPE TopMeta; const bool IsTop = (a_Meta & 0x8) == 0x8; const auto TopPosition = IsTop ? a_Position : a_Position.addedY(1); // Figure out the metadata of the top half, which stores the previous redstone power state: if (IsTop) { TopMeta = a_Meta; } else { if (TopPosition.y == cChunkDef::Height) { return; } BLOCKTYPE AboveType; a_Chunk.GetBlockTypeMeta(TopPosition, AboveType, TopMeta); if (!cBlockDoorHandler::IsDoorBlockType(AboveType)) { return; } } const auto OppositeHalfPosition = a_Position + (IsTop ? OffsetYM : OffsetYP); ForEachSourceCallback Callback(a_Chunk, OppositeHalfPosition, a_BlockType); ForValidSourcePositions(a_Chunk, OppositeHalfPosition, a_BlockType, a_Meta, Callback); // Factor in what the other half is getting: Power = std::max(Power, Callback.Power); const bool ShouldBeOpen = Power != 0; const bool PreviouslyPowered = (TopMeta & 0x2) == 0x2; // Allow players to override redstone control // don't update if redstone power hasn't changed since we last saw it: if (ShouldBeOpen == PreviouslyPowered) { return; } // Update the previous redstone power: if (ShouldBeOpen) { a_Chunk.SetMeta(TopPosition, TopMeta | 0x2); } else { a_Chunk.SetMeta(TopPosition, TopMeta & ~0x2); } cChunkInterface ChunkInterface(a_Chunk.GetWorld()->GetChunkMap()); const auto AbsolutePosition = cChunkDef::RelativeToAbsolute(a_Position, a_Chunk.GetPos()); // Toggle the door, if it needs to be changed: if (ShouldBeOpen != cBlockDoorHandler::IsOpen(ChunkInterface, AbsolutePosition)) { cBlockDoorHandler::SetOpen(ChunkInterface, AbsolutePosition, ShouldBeOpen); a_Chunk.GetWorld()->BroadcastSoundParticleEffect(EffectID::SFX_RANDOM_WOODEN_DOOR_OPEN, AbsolutePosition, 0); } } }; ================================================ FILE: src/Simulator/IncrementalRedstoneSimulator/DropSpenserHandler.h ================================================ #pragma once #include "../../BlockEntities/DropSpenserEntity.h" namespace DropSpenserHandler { static bool IsActivated(NIBBLETYPE a_Meta) { return (a_Meta & E_META_DROPSPENSER_ACTIVATED) != 0; } static NIBBLETYPE SetActivationState(NIBBLETYPE a_Meta, bool IsOn) { if (IsOn) { return a_Meta | E_META_DROPSPENSER_ACTIVATED; // set the bit } else { return a_Meta & ~E_META_DROPSPENSER_ACTIVATED; // clear the bit } } static PowerLevel GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) { UNUSED(a_Chunk); UNUSED(a_Position); UNUSED(a_BlockType); UNUSED(a_QueryPosition); UNUSED(a_QueryBlockType); UNUSED(IsLinked); return 0; } static void Update(cChunk & a_Chunk, cChunk &, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, const PowerLevel Power) { // LOGD("Evaluating spencer the dropspenser (%d %d %d)", a_Position.x, a_Position.y, a_Position.z); const bool IsPoweredNow = (Power > 0); const bool WasPoweredPreviously = IsActivated(a_Meta); if (IsPoweredNow && !WasPoweredPreviously) { a_Chunk.DoWithBlockEntityAt(a_Position, [](cBlockEntity & a_BlockEntity) { ASSERT((a_BlockEntity.GetBlockType() == E_BLOCK_DISPENSER) || (a_BlockEntity.GetBlockType() == E_BLOCK_DROPPER)); static_cast(a_BlockEntity).Activate(); return false; }); } // Update the internal dropspenser state if necessary if (IsPoweredNow != WasPoweredPreviously) { a_Chunk.SetMeta(a_Position, SetActivationState(a_Meta, IsPoweredNow)); } } static void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, ForEachSourceCallback & Callback) { UNUSED(a_Chunk); UNUSED(a_BlockType); UNUSED(a_Meta); // Consider indirect power: Callback.CheckIndirectPower(); // Consider normal adjacents: InvokeForAdjustedRelatives(Callback, a_Position, RelativeAdjacents); } }; ================================================ FILE: src/Simulator/IncrementalRedstoneSimulator/ForEachSourceCallback.cpp ================================================ #include "Globals.h" #include "ForEachSourceCallback.h" #include "BlockType.h" #include "../../BlockInfo.h" #include "../../Chunk.h" #include "IncrementalRedstoneSimulator.h" #include "RedstoneHandler.h" ForEachSourceCallback::ForEachSourceCallback(const cChunk & Chunk, const Vector3i Position, const BLOCKTYPE CurrentBlock) : Power(0), m_Chunk(Chunk), m_Position(Position), m_CurrentBlock(CurrentBlock) { } void ForEachSourceCallback::operator()(Vector3i Location) { if (!cChunkDef::IsValidHeight(Location)) { return; } const auto NeighbourChunk = m_Chunk.GetRelNeighborChunkAdjustCoords(Location); if ((NeighbourChunk == nullptr) || !NeighbourChunk->IsValid()) { return; } const auto PotentialSourceBlock = NeighbourChunk->GetBlock(Location); const auto NeighbourRelativeQueryPosition = cIncrementalRedstoneSimulatorChunkData::RebaseRelativePosition(m_Chunk, *NeighbourChunk, m_Position); if (!cBlockInfo::IsTransparent(PotentialSourceBlock)) { Power = std::max(Power, QueryLinkedPower(*NeighbourChunk, NeighbourRelativeQueryPosition, m_CurrentBlock, Location)); } else { Power = std::max( Power, RedstoneHandler::GetPowerDeliveredToPosition( *NeighbourChunk, Location, PotentialSourceBlock, NeighbourRelativeQueryPosition, m_CurrentBlock, false ) ); } } void ForEachSourceCallback::CheckIndirectPower() { const Vector3i OffsetYP(0, 1, 0); const auto Above = m_Position + OffsetYP; if (Above.y == cChunkDef::Height) { return; } // Object representing restarted power calculation where the // block above this piston, dropspenser is requesting a power level. ForEachSourceCallback QuasiQueryCallback(m_Chunk, Above, m_Chunk.GetBlock(Above)); // Manually feed the callback object all positions that may deliver power to Above: for (const auto & QuasiPowerOffset : cSimulator::GetLinkedOffsets(OffsetYP)) { QuasiQueryCallback(m_Position + QuasiPowerOffset); } // Get the results: Power = std::max(Power, QuasiQueryCallback.Power); } PowerLevel ForEachSourceCallback::QueryLinkedPower(const cChunk & Chunk, const Vector3i QueryPosition, const BLOCKTYPE QueryBlock, const Vector3i SolidBlockPosition) { PowerLevel Power = 0; // Loop through all linked powerable offsets in the direction requested: for (const auto & Offset : cSimulator::GetLinkedOffsets(SolidBlockPosition - QueryPosition)) { auto SourcePosition = QueryPosition + Offset; if (!cChunkDef::IsValidHeight(SourcePosition)) { continue; } const auto NeighbourChunk = Chunk.GetRelNeighborChunkAdjustCoords(SourcePosition); if ((NeighbourChunk == nullptr) || !NeighbourChunk->IsValid()) { continue; } // Conduit block's position, relative to NeighbourChunk. const auto NeighbourRelativeSolidBlockPosition = cIncrementalRedstoneSimulatorChunkData::RebaseRelativePosition(Chunk, *NeighbourChunk, SolidBlockPosition); // Do a standard power query, but the requester's position is actually the solid block that will conduct power: Power = std::max( Power, RedstoneHandler::GetPowerDeliveredToPosition( *NeighbourChunk, SourcePosition, NeighbourChunk->GetBlock(SourcePosition), NeighbourRelativeSolidBlockPosition, QueryBlock, true ) ); } return Power; } ================================================ FILE: src/Simulator/IncrementalRedstoneSimulator/ForEachSourceCallback.h ================================================ #pragma once #include "RedstoneSimulatorChunkData.h" class ForEachSourceCallback { public: ForEachSourceCallback(const cChunk & Chunk, Vector3i Position, BLOCKTYPE CurrentBlock); /** Callback invoked for each potential source position of the redstone component. */ void operator()(Vector3i Location); /** Callback invoked for blocks supporting quasiconnectivity. */ void CheckIndirectPower(); // The maximum power level of all source locations. PowerLevel Power; private: /** Asks redstone handlers adjacent to a solid block how much power they will deliver to the querying position, via the solid block. Both QueryPosition and SolidBlockPosition are relative to Chunk. */ static PowerLevel QueryLinkedPower(const cChunk & Chunk, Vector3i QueryPosition, BLOCKTYPE QueryBlock, Vector3i SolidBlockPosition); const cChunk & m_Chunk; const Vector3i m_Position; const BLOCKTYPE m_CurrentBlock; }; ================================================ FILE: src/Simulator/IncrementalRedstoneSimulator/HopperHandler.h ================================================ #pragma once #include "../../BlockEntities/HopperEntity.h" namespace HopperHandler { static PowerLevel GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) { UNUSED(a_Chunk); UNUSED(a_Position); UNUSED(a_BlockType); UNUSED(a_QueryPosition); UNUSED(a_QueryBlockType); UNUSED(IsLinked); return 0; } static void Update(cChunk & a_Chunk, cChunk &, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, const PowerLevel Power) { // LOGD("Evaluating holey the hopper (%d %d %d)", a_Position.x, a_Position.y, a_Position.z); const bool ShouldBeLocked = Power != 0; const bool PreviouslyLocked = (a_Meta & 0x8) == 0x8; if (ShouldBeLocked == PreviouslyLocked) { return; } if (ShouldBeLocked) { a_Chunk.SetMeta(a_Position, a_Meta | 0x8); } else { a_Chunk.SetMeta(a_Position, a_Meta & ~0x8); } a_Chunk.DoWithBlockEntityAt(a_Position, [ShouldBeLocked](cBlockEntity & a_BlockEntity) { ASSERT(a_BlockEntity.GetBlockType() == E_BLOCK_HOPPER); static_cast(a_BlockEntity).SetLocked(ShouldBeLocked); return false; }); } static void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, ForEachSourceCallback & Callback) { UNUSED(a_Chunk); UNUSED(a_BlockType); UNUSED(a_Meta); InvokeForAdjustedRelatives(Callback, a_Position, RelativeAdjacents); } }; ================================================ FILE: src/Simulator/IncrementalRedstoneSimulator/IncrementalRedstoneSimulator.cpp ================================================ #include "Globals.h" #include "IncrementalRedstoneSimulator.h" #include "BlockType.h" #include "RedstoneHandler.h" #include "RedstoneSimulatorChunkData.h" #include "ForEachSourceCallback.h" bool cIncrementalRedstoneSimulator::IsAlwaysTicked(BLOCKTYPE a_Block) { switch (a_Block) // Call the appropriate simulator for the entry's block type { case E_BLOCK_DAYLIGHT_SENSOR: case E_BLOCK_INVERTED_DAYLIGHT_SENSOR: case E_BLOCK_TRIPWIRE_HOOK: case E_BLOCK_WOODEN_PRESSURE_PLATE: case E_BLOCK_STONE_PRESSURE_PLATE: case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE: case E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE: return true; default: return false; } } bool cIncrementalRedstoneSimulator::IsRedstone(BLOCKTYPE a_Block) { switch (a_Block) { // All redstone devices, please alpha sort case E_BLOCK_ACACIA_DOOR: case E_BLOCK_ACACIA_FENCE_GATE: case E_BLOCK_ACTIVATOR_RAIL: case E_BLOCK_ACTIVE_COMPARATOR: case E_BLOCK_BIRCH_DOOR: case E_BLOCK_BIRCH_FENCE_GATE: case E_BLOCK_BLOCK_OF_REDSTONE: case E_BLOCK_COMMAND_BLOCK: case E_BLOCK_DARK_OAK_DOOR: case E_BLOCK_DARK_OAK_FENCE_GATE: case E_BLOCK_DAYLIGHT_SENSOR: case E_BLOCK_DETECTOR_RAIL: case E_BLOCK_DISPENSER: case E_BLOCK_DROPPER: case E_BLOCK_FENCE_GATE: case E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE: case E_BLOCK_HOPPER: case E_BLOCK_INACTIVE_COMPARATOR: case E_BLOCK_INVERTED_DAYLIGHT_SENSOR: case E_BLOCK_IRON_DOOR: case E_BLOCK_IRON_TRAPDOOR: case E_BLOCK_JUNGLE_DOOR: case E_BLOCK_JUNGLE_FENCE_GATE: case E_BLOCK_LEVER: case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE: case E_BLOCK_NOTE_BLOCK: case E_BLOCK_OBSERVER: case E_BLOCK_POWERED_RAIL: case E_BLOCK_REDSTONE_LAMP_OFF: case E_BLOCK_REDSTONE_LAMP_ON: case E_BLOCK_REDSTONE_REPEATER_OFF: case E_BLOCK_REDSTONE_REPEATER_ON: case E_BLOCK_REDSTONE_TORCH_OFF: case E_BLOCK_REDSTONE_TORCH_ON: case E_BLOCK_REDSTONE_WIRE: case E_BLOCK_SPRUCE_DOOR: case E_BLOCK_SPRUCE_FENCE_GATE: case E_BLOCK_STICKY_PISTON: case E_BLOCK_STONE_BUTTON: case E_BLOCK_STONE_PRESSURE_PLATE: case E_BLOCK_TNT: case E_BLOCK_TRAPDOOR: case E_BLOCK_TRAPPED_CHEST: case E_BLOCK_TRIPWIRE_HOOK: case E_BLOCK_WOODEN_BUTTON: case E_BLOCK_WOODEN_DOOR: case E_BLOCK_WOODEN_PRESSURE_PLATE: case E_BLOCK_PISTON: { return true; } default: return false; } } void cIncrementalRedstoneSimulator::ProcessWorkItem(cChunk & Chunk, cChunk & TickingSource, const Vector3i Position) { BLOCKTYPE CurrentBlock; NIBBLETYPE CurrentMeta; Chunk.GetBlockTypeMeta(Position, CurrentBlock, CurrentMeta); ForEachSourceCallback Callback(Chunk, Position, CurrentBlock); RedstoneHandler::ForValidSourcePositions(Chunk, Position, CurrentBlock, CurrentMeta, Callback); // Inform the handler to update RedstoneHandler::Update(Chunk, TickingSource, Position, CurrentBlock, CurrentMeta, Callback.Power); } void cIncrementalRedstoneSimulator::SimulateChunk(std::chrono::milliseconds a_Dt, int a_ChunkX, int a_ChunkZ, cChunk * a_Chunk) { auto & ChunkData = *static_cast(a_Chunk->GetRedstoneSimulatorData()); for (auto & DelayInfo : ChunkData.m_MechanismDelays) { if ((--DelayInfo.second.first) == 0) { ChunkData.WakeUp(DelayInfo.first); } } // Build our work queue auto & WorkQueue = ChunkData.GetActiveBlocks(); // Process the work queue while (!WorkQueue.empty()) { // Grab the first element and remove it from the list Vector3i CurrentLocation = WorkQueue.top(); WorkQueue.pop(); const auto NeighbourChunk = a_Chunk->GetRelNeighborChunkAdjustCoords(CurrentLocation); if ((NeighbourChunk == nullptr) || !NeighbourChunk->IsValid()) { continue; } ProcessWorkItem(*NeighbourChunk, *a_Chunk, CurrentLocation); } for (const auto & Position : ChunkData.AlwaysTickedPositions) { ChunkData.WakeUp(Position); } } void cIncrementalRedstoneSimulator::AddBlock(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_Block) { // Never update blocks without a handler: if (!IsRedstone(a_Block)) { return; } auto & ChunkData = *static_cast(a_Chunk.GetRedstoneSimulatorData()); if (IsAlwaysTicked(a_Block)) { ChunkData.AlwaysTickedPositions.emplace(a_Position); } // Temporary: in the absence of block state support calculate our own: if (a_Block == E_BLOCK_REDSTONE_WIRE) { RedstoneHandler::SetWireState(a_Chunk, a_Position); } // Always update redstone devices: ChunkData.WakeUp(a_Position); } cRedstoneSimulatorChunkData * cIncrementalRedstoneSimulator::CreateChunkData() { return new cIncrementalRedstoneSimulatorChunkData; } void cIncrementalRedstoneSimulator::WakeUp(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_Block) { // Having WakeUp called on us directly means someone called SetBlock (or WakeUp) // Since the simulator never does this, something external changed. Clear cached data: static_cast(a_Chunk.GetRedstoneSimulatorData())->ErasePowerData(a_Position); // Queue the block, in case the set block was redstone: AddBlock(a_Chunk, a_Position, a_Block); } void cIncrementalRedstoneSimulator::WakeUp(cChunk & a_Chunk, Vector3i a_Position, Vector3i a_Offset, BLOCKTYPE a_Block) { // This is an automatic cross-coords wakeup by cSimulatorManager // There is no need to erase power data; if a component was destroyed the 3-arg WakeUp will handle it AddBlock(a_Chunk, a_Position, a_Block); // The only thing to do go one block farther than this cross-coord, in the direction of Offset // in order to notify linked-powered positions that there was a change for (const auto & Offset : cSimulator::GetLinkedOffsets(a_Offset)) { auto Relative = a_Position - a_Offset + Offset; if (!cChunkDef::IsValidHeight(Relative)) { continue; } const auto Chunk = a_Chunk.GetRelNeighborChunkAdjustCoords(Relative); if ((Chunk == nullptr) || !Chunk->IsValid()) { continue; } const auto Block = Chunk->GetBlock(Relative); AddBlock(*Chunk, Relative, Block); } } ================================================ FILE: src/Simulator/IncrementalRedstoneSimulator/IncrementalRedstoneSimulator.h ================================================ #pragma once #include "../RedstoneSimulator.h" class cIncrementalRedstoneSimulator final : public cRedstoneSimulator { using Super = cRedstoneSimulator; public: using Super::Super; private: /** Returns if a redstone device is always ticked due to influence by its environment */ static bool IsAlwaysTicked(BLOCKTYPE a_Block); /** Returns if a block is any sort of redstone device */ static bool IsRedstone(BLOCKTYPE a_Block); void ProcessWorkItem(cChunk & Chunk, cChunk & TickingSource, const Vector3i Position); virtual void SimulateChunk(std::chrono::milliseconds Dt, int ChunkX, int ChunkZ, cChunk * Chunk) override; virtual void AddBlock(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_Block) override; virtual cRedstoneSimulatorChunkData * CreateChunkData() override; virtual void WakeUp(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_Block) override; virtual void WakeUp(cChunk & a_Chunk, Vector3i a_Position, Vector3i a_Offset, BLOCKTYPE a_Block) override; } ; ================================================ FILE: src/Simulator/IncrementalRedstoneSimulator/NoteBlockHandler.h ================================================ #pragma once #include "../../BlockEntities/NoteEntity.h" namespace NoteBlockHandler { static PowerLevel GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) { UNUSED(a_Chunk); UNUSED(a_Position); UNUSED(a_BlockType); UNUSED(a_QueryPosition); UNUSED(a_QueryBlockType); UNUSED(IsLinked); return 0; } static void Update(cChunk & a_Chunk, cChunk &, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, const PowerLevel Power) { // LOGD("Evaluating sparky the magical note block (%d %d %d) %i", a_Position.x, a_Position.y, a_Position.z, Power); const auto Previous = DataForChunk(a_Chunk).ExchangeUpdateOncePowerData(a_Position, Power); if ((Previous != 0) || (Power == 0)) { // If we're already powered or received an update of no power, don't make a sound return; } a_Chunk.DoWithBlockEntityAt(a_Position, [](cBlockEntity & a_BlockEntity) { ASSERT(a_BlockEntity.GetBlockType() == E_BLOCK_NOTE_BLOCK); static_cast(a_BlockEntity).MakeSound(); return false; }); } static void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, ForEachSourceCallback & Callback) { UNUSED(a_Chunk); UNUSED(a_BlockType); UNUSED(a_Meta); InvokeForAdjustedRelatives(Callback, a_Position, RelativeAdjacents); } }; ================================================ FILE: src/Simulator/IncrementalRedstoneSimulator/ObserverHandler.h ================================================ #pragma once #include "../../Blocks/BlockObserver.h" namespace ObserverHandler { static bool IsOn(NIBBLETYPE a_Meta) { return (a_Meta & 0x8) == 0x8; } static bool ShouldPowerOn(cChunk & Chunk, const Vector3i a_Position, NIBBLETYPE a_Meta, cIncrementalRedstoneSimulatorChunkData & a_Data) { BLOCKTYPE BlockType; NIBBLETYPE BlockMeta; if (!Chunk.UnboundedRelGetBlock(a_Position + cBlockObserverHandler::GetObservingFaceOffset(a_Meta), BlockType, BlockMeta)) { return false; } auto & ObserverCache = a_Data.ObserverCache; const auto FindResult = ObserverCache.find(a_Position); const auto Observed = std::make_pair(BlockType, BlockMeta); if (FindResult == ObserverCache.end()) { // Cache the last seen block for this position: ObserverCache.emplace(a_Position, Observed); // Definitely should signal update: return true; } // The block this observer previously saw. const auto Previous = FindResult->second; // Update the last seen block: FindResult->second = Observed; // Determine if to signal an update based on the block previously observed changed return Previous != Observed; } static PowerLevel GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) { const auto Meta = a_Chunk.GetMeta(a_Position); return (IsOn(Meta) && (a_QueryPosition == (a_Position + cBlockObserverHandler::GetSignalOutputOffset(Meta)))) ? 15 : 0; } static void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, const PowerLevel Power) { // LOGD("Evaluating Lenny the observer (%i %i %i)", a_Position.x, a_Position.y, a_Position.z); auto & Data = DataForChunk(a_Chunk); auto DelayInfo = Data.GetMechanismDelayInfo(a_Position); if (DelayInfo == nullptr) { if (!ShouldPowerOn(a_Chunk, a_Position, a_Meta, Data)) { return; } // From rest, we've determined there was a block update // Schedule power-on 1 tick in the future Data.m_MechanismDelays[a_Position] = std::make_pair(1, true); return; } int DelayTicks; bool ShouldPowerOn; std::tie(DelayTicks, ShouldPowerOn) = *DelayInfo; if (DelayTicks != 0) { return; } if (ShouldPowerOn) { // Remain on for 1 tick before resetting *DelayInfo = std::make_pair(1, false); a_Chunk.SetMeta(a_Position, a_Meta | 0x8); } else { // We've reset. Erase delay data in preparation for detecting further updates Data.m_MechanismDelays.erase(a_Position); a_Chunk.SetMeta(a_Position, a_Meta & ~0x8); } UpdateAdjustedRelative(a_Chunk, CurrentlyTicking, a_Position, cBlockObserverHandler::GetSignalOutputOffset(a_Meta)); } static void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, ForEachSourceCallback & Callback) { UNUSED(a_Chunk); UNUSED(a_Position); UNUSED(a_BlockType); UNUSED(a_BlockType); } }; ================================================ FILE: src/Simulator/IncrementalRedstoneSimulator/PistonHandler.h ================================================ #pragma once #include "../../Blocks/BlockPiston.h" namespace PistonHandler { static PowerLevel GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) { UNUSED(a_Chunk); UNUSED(a_Position); UNUSED(a_BlockType); UNUSED(a_QueryPosition); UNUSED(a_QueryBlockType); UNUSED(IsLinked); return 0; } static void Update(cChunk & a_Chunk, cChunk &, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, const PowerLevel Power) { // LOGD("Evaluating pisty the piston (%d %d %d)", a_Position.x, a_Position.y, a_Position.z); const bool ShouldBeExtended = Power != 0; if (ShouldBeExtended == cBlockPistonHandler::IsExtended(a_Meta)) { return; } a_Position = cChunkDef::RelativeToAbsolute(a_Position, a_Chunk.GetPos()); if (ShouldBeExtended) { cBlockPistonHandler::ExtendPiston(a_Position, *a_Chunk.GetWorld()); } else { cBlockPistonHandler::RetractPiston(a_Position, *a_Chunk.GetWorld()); } // It is necessary to delay after a signal to prevent an infinite loop (#3168) // However, this delay is already present: as a side effect of the implementation of piston animation in Blocks\BlockPiston.cpp } static void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, ForEachSourceCallback & Callback) { UNUSED(a_Chunk); UNUSED(a_BlockType); const auto Face = cBlockPistonHandler::MetaDataToDirection(a_Meta); const auto FrontOffset = AddFaceDirection(Vector3i(), Face); for (const auto & Offset : RelativeAdjacents) { if (Offset != FrontOffset) { Callback(a_Position + Offset); } } // Consider indirect power: Callback.CheckIndirectPower(); } }; ================================================ FILE: src/Simulator/IncrementalRedstoneSimulator/PoweredRailHandler.h ================================================ #pragma once namespace PoweredRailHandler { /** Get the offset along which the rail faces. Not in cBlockRailHandler since specific to powered rails. */ static Vector3i GetPoweredRailAdjacentXZCoordinateOffset(NIBBLETYPE a_Meta) { switch (a_Meta & 0x7) { case E_META_RAIL_ZM_ZP: return { 0, 0, 1 }; case E_META_RAIL_XM_XP: return { 1, 0, 0 }; case E_META_RAIL_ASCEND_XP: return { 1, 1, 0 }; case E_META_RAIL_ASCEND_XM: return { 1, 1, 0 }; case E_META_RAIL_ASCEND_ZM: return { 0, 1, 1 }; case E_META_RAIL_ASCEND_ZP: return { 0, 1, 1 }; default: { ASSERT(!"Impossible rail meta! wat wat wat"); return { 0, 0, 0 }; } } } static PowerLevel GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) { UNUSED(a_QueryBlockType); const auto Meta = a_Chunk.GetMeta(a_Position); const auto Offset = GetPoweredRailAdjacentXZCoordinateOffset(Meta); if (((Offset + a_Position) == a_QueryPosition) || ((-Offset + a_Position) == a_QueryPosition)) { const auto Power = DataForChunk(a_Chunk).GetCachedPowerData(a_Position); return (Power <= 7) ? 0 : (Power - 1); } return 0; } static void Update(cChunk & a_Chunk, cChunk & CurrentlyTickingChunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, const PowerLevel Power) { // LOGD("Evaluating tracky the rail (%d %d %d)", a_Position.x, a_Position.y, a_Position.z); switch (a_BlockType) { case E_BLOCK_DETECTOR_RAIL: { /* if ((m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ) & 0x08) == 0x08) { SetAllDirsAsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, a_MyType); } */ return; } case E_BLOCK_ACTIVATOR_RAIL: case E_BLOCK_POWERED_RAIL: { const auto Offset = GetPoweredRailAdjacentXZCoordinateOffset(a_Meta); if (Power != DataForChunk(a_Chunk).ExchangeUpdateOncePowerData(a_Position, Power)) { a_Chunk.SetMeta(a_Position, (Power == 0) ? (a_Meta & 0x07) : (a_Meta | 0x08)); UpdateAdjustedRelative(a_Chunk, CurrentlyTickingChunk, a_Position, Offset); UpdateAdjustedRelative(a_Chunk, CurrentlyTickingChunk, a_Position, -Offset); } return; } default: { ASSERT(!"Unhandled type of rail in passed to rail handler!"); } } } static void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, ForEachSourceCallback & Callback) { UNUSED(a_Chunk); UNUSED(a_Meta); if ((a_BlockType == E_BLOCK_POWERED_RAIL) || (a_BlockType == E_BLOCK_ACTIVATOR_RAIL)) { InvokeForAdjustedRelatives(Callback, a_Position, RelativeAdjacents); } } }; ================================================ FILE: src/Simulator/IncrementalRedstoneSimulator/PressurePlateHandler.h ================================================ #pragma once #include "../../BoundingBox.h" #include "../../Entities/Pickup.h" namespace PressurePlateHandler { static unsigned char GetPowerLevel(const cChunk & Chunk, const Vector3i Position, const BLOCKTYPE BlockType) { size_t NumberOfEntities = 0; bool FoundPlayer = false; Chunk.ForEachEntityInBox(cBoundingBox(Vector3d(0.5, 0, 0.5) + Position, 0.5, 0.5), [&](cEntity & Entity) { if (Entity.GetHealth() <= 0) { return false; } if (Entity.IsPlayer()) { const auto & Player = static_cast(Entity); if (Player.IsGameModeSpectator()) { return false; } FoundPlayer = true; } else if (Entity.IsPickup()) { const auto & Pickup = static_cast(Entity); NumberOfEntities += static_cast(Pickup.GetItem().m_ItemCount); return false; } NumberOfEntities++; return false; }); switch (BlockType) { case E_BLOCK_STONE_PRESSURE_PLATE: { return FoundPlayer ? 15 : 0; } case E_BLOCK_WOODEN_PRESSURE_PLATE: { return (NumberOfEntities != 0) ? 15 : 0; } case E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE: { return std::min(static_cast(CeilC(NumberOfEntities / 10.f)), static_cast(15)); } case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE: { return std::min(static_cast(NumberOfEntities), static_cast(15)); } default: { ASSERT(!"Unhandled/unimplemented block in pressure plate handler!"); return 0; } } } static const char * GetClickOnSound(BLOCKTYPE a_BlockType) { // manage on-sound switch (a_BlockType) { case E_BLOCK_STONE_PRESSURE_PLATE: return "block.stone_pressureplate.click_on"; case E_BLOCK_WOODEN_PRESSURE_PLATE: return "block.wood_pressureplate.click_on"; case E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE: case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE: return "block.metal_pressureplate.click_on"; default: { ASSERT(!"No on sound for this one!"); return ""; } } } static const char * GetClickOffSound(BLOCKTYPE a_BlockType) { // manage off-sound switch (a_BlockType) { case E_BLOCK_STONE_PRESSURE_PLATE: return "block.stone_pressureplate.click_off"; case E_BLOCK_WOODEN_PRESSURE_PLATE: return "block.wood_pressureplate.click_off"; case E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE: case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE: return "block.metal_pressureplate.click_off"; default: { ASSERT(!"No off sound for this one!"); return ""; } } } static PowerLevel GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) { UNUSED(a_BlockType); UNUSED(a_QueryPosition); UNUSED(a_QueryBlockType); // Plates only link power blocks below // Retrieve and return the cached power calculated by Update for performance: return (IsLinked && (a_QueryPosition != (a_Position + OffsetYM))) ? 0 : DataForChunk(a_Chunk).GetCachedPowerData(a_Position); } static void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, const PowerLevel Power) { // LOGD("Evaluating clicky the pressure plate (%d %d %d)", a_Position.x, a_Position.y, a_Position.z); auto & ChunkData = DataForChunk(a_Chunk); const auto PreviousPower = ChunkData.GetCachedPowerData(a_Position); const auto Absolute = cChunkDef::RelativeToAbsolute(a_Position, a_Chunk.GetPos()); const auto PowerLevel = GetPowerLevel(a_Chunk, Absolute, a_BlockType); // Get the current power of the platey const auto DelayInfo = ChunkData.GetMechanismDelayInfo(a_Position); // Resting state? if (DelayInfo == nullptr) { if (PowerLevel == 0) { // Nothing happened, back to rest return; } // From rest, a player stepped on us // Schedule a minimum 0.5 second delay before even thinking about releasing ChunkData.m_MechanismDelays[a_Position] = std::make_pair(5, true); a_Chunk.GetWorld()->BroadcastSoundEffect(GetClickOnSound(a_BlockType), Absolute, 0.5f, 0.6f); // Update power ChunkData.SetCachedPowerData(a_Position, PowerLevel); // Immediately depress plate a_Chunk.SetMeta(a_Position, E_META_PRESSURE_PLATE_DEPRESSED); UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, a_Position, RelativeAdjacents); return; } // Not a resting state int DelayTicks; bool HasExitedMinimumOnDelayPhase; std::tie(DelayTicks, HasExitedMinimumOnDelayPhase) = *DelayInfo; // Are we waiting for the initial delay or subsequent release delay? if (DelayTicks > 0) { // Nothing changes, if there is nothing on it anymore, because the state is locked. if (PowerLevel == 0) { return; } // Yes. Are we waiting to release, and found that the player stepped on it again? if (!HasExitedMinimumOnDelayPhase) { // Reset delay *DelayInfo = std::make_pair(0, true); } // Did the power level change and is still above zero? if (PowerLevel != PreviousPower) { // Yes. Update power ChunkData.SetCachedPowerData(a_Position, PowerLevel); UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, a_Position, RelativeAdjacents); } return; } // Not waiting for anything. Has the initial delay elapsed? if (HasExitedMinimumOnDelayPhase) { // Yep, initial delay elapsed. Has the player gotten off? if (PowerLevel == 0) { // Yes. Go into subsequent release delay, for a further 0.5 seconds *DelayInfo = std::make_pair(5, false); return; } // Did the power level change and is still above zero? if (PowerLevel != PreviousPower) { // Yes. Update power ChunkData.SetCachedPowerData(a_Position, PowerLevel); UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, a_Position, RelativeAdjacents); } // Yes, but player's still on the plate, do nothing return; } // Just got out of the subsequent release phase, reset everything and raise the plate ChunkData.m_MechanismDelays.erase(a_Position); a_Chunk.GetWorld()->BroadcastSoundEffect(GetClickOffSound(a_BlockType), Absolute, 0.5f, 0.5f); ChunkData.SetCachedPowerData(a_Position, PowerLevel); a_Chunk.SetMeta(a_Position, E_META_PRESSURE_PLATE_RAISED); UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, a_Position, RelativeAdjacents); } static void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, ForEachSourceCallback & Callback) { UNUSED(a_Chunk); UNUSED(a_Position); UNUSED(a_BlockType); UNUSED(a_Meta); UNUSED(Callback); } }; ================================================ FILE: src/Simulator/IncrementalRedstoneSimulator/RedstoneBlockHandler.h ================================================ #pragma once namespace RedstoneBlockHandler { static PowerLevel GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) { UNUSED(a_Chunk); UNUSED(a_Position); UNUSED(a_BlockType); UNUSED(a_QueryPosition); UNUSED(IsLinked); return IsLinked ? 0 : 15; } static void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, const PowerLevel Power) { // LOGD("Evaluating crimson the redstone block (%d %d %d)", a_Position.x, a_Position.y, a_Position.z); } static void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, ForEachSourceCallback & Callback) { UNUSED(a_Chunk); UNUSED(a_Position); UNUSED(a_BlockType); UNUSED(a_Meta); UNUSED(Callback); } }; ================================================ FILE: src/Simulator/IncrementalRedstoneSimulator/RedstoneComparatorHandler.h ================================================ #pragma once #include "../../Blocks/BlockComparator.h" namespace RedstoneComparatorHandler { static unsigned char GetFrontPowerLevel(NIBBLETYPE a_Meta, unsigned char a_HighestSidePowerLevel, unsigned char a_HighestRearPowerLevel) { if (cBlockComparatorHandler::IsInSubtractionMode(a_Meta)) { // Subtraction mode return static_cast(std::max(static_cast(a_HighestRearPowerLevel) - a_HighestSidePowerLevel, 0)); } else { // Comparison mode return (a_HighestRearPowerLevel < a_HighestSidePowerLevel) ? 0 : a_HighestRearPowerLevel; } } static PowerLevel GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) { UNUSED(a_QueryPosition); UNUSED(a_QueryBlockType); const auto Meta = a_Chunk.GetMeta(a_Position); return ( (cBlockComparatorHandler::GetFrontCoordinate(a_Position, Meta & 0x3) == a_QueryPosition) ? DataForChunk(a_Chunk).GetCachedPowerData(a_Position) : 0 ); } static unsigned char GetPowerLevel(cChunk & a_Chunk, Vector3i Position, BLOCKTYPE BlockType, NIBBLETYPE Meta) { UInt8 SignalStrength = 0; auto RearCoordinate = cBlockComparatorHandler::GetRearCoordinate(Position, Meta & 0x3); auto RearChunk = a_Chunk.GetRelNeighborChunkAdjustCoords(RearCoordinate); if ((RearChunk == nullptr) || !RearChunk->IsValid()) { return SignalStrength; } RearChunk->DoWithBlockEntityAt(RearCoordinate, [&](cBlockEntity & a_BlockEntity) { // Skip BlockEntities that don't have slots auto BlockEntityWithItems = dynamic_cast(&a_BlockEntity); if (BlockEntityWithItems == nullptr) { return false; } // TODO: handle double chests auto & Contents = BlockEntityWithItems->GetContents(); float Fullness = 0; // Is a floating-point type to allow later calculation to produce a non-truncated value for (int Slot = 0; Slot != Contents.GetNumSlots(); ++Slot) { Fullness += static_cast(Contents.GetSlot(Slot).m_ItemCount) / Contents.GetSlot(Slot).GetMaxStackSize(); } SignalStrength = (Fullness < 0.001 /* container empty? */) ? 0 : static_cast(1 + (Fullness / Contents.GetNumSlots()) * 14); return false; }); const auto RearType = RearChunk->GetBlock(RearCoordinate); return std::max( SignalStrength, RedstoneHandler::GetPowerDeliveredToPosition( *RearChunk, RearCoordinate, RearType, cIncrementalRedstoneSimulatorChunkData::RebaseRelativePosition(a_Chunk, *RearChunk, Position), BlockType, false ) ); } static void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, const PowerLevel Power) { // Note that Power here contains the maximum * side * power level, as specified by GetValidSourcePositions // LOGD("Evaluating ALU the comparator (%d %d %d)", a_Position.x, a_Position.y, a_Position.z); auto & Data = DataForChunk(a_Chunk); auto DelayInfo = Data.GetMechanismDelayInfo(a_Position); // Delay is used here to prevent an infinite loop (#3168) if (DelayInfo == nullptr) { const auto RearPower = GetPowerLevel(a_Chunk, a_Position, a_BlockType, a_Meta); const auto FrontPower = GetFrontPowerLevel(a_Meta, Power, RearPower); const auto PreviousFrontPower = Data.GetCachedPowerData(a_Position); const bool ShouldUpdate = (FrontPower != PreviousFrontPower); // "Business logic" (:P) - determined by side and rear power levels if (ShouldUpdate) { Data.m_MechanismDelays[a_Position] = std::make_pair(1, bool()); } return; } int DelayTicks; std::tie(DelayTicks, std::ignore) = *DelayInfo; if (DelayTicks != 0) { return; } const auto RearPower = GetPowerLevel(a_Chunk, a_Position, a_BlockType, a_Meta); const auto FrontPower = GetFrontPowerLevel(a_Meta, Power, RearPower); const NIBBLETYPE NewMeta = (FrontPower > 0) ? (a_Meta | 0x08u) : (a_Meta & 0x07u); // Don't care about the previous power level so return value ignored Data.ExchangeUpdateOncePowerData(a_Position, FrontPower); a_Chunk.SetMeta(a_Position, NewMeta); Data.m_MechanismDelays.erase(a_Position); // Assume that an update (to front power) is needed: UpdateAdjustedRelative(a_Chunk, CurrentlyTicking, a_Position, cBlockComparatorHandler::GetFrontCoordinate(a_Position, a_Meta & 0x3) - a_Position); } static void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, ForEachSourceCallback & Callback) { UNUSED(a_Chunk); UNUSED(a_BlockType); Callback(cBlockComparatorHandler::GetSideCoordinate(a_Position, a_Meta & 0x3, false)); Callback(cBlockComparatorHandler::GetSideCoordinate(a_Position, a_Meta & 0x3, true)); } }; ================================================ FILE: src/Simulator/IncrementalRedstoneSimulator/RedstoneDataHelper.h ================================================ #pragma once #include "../../Chunk.h" inline auto & DataForChunk(const cChunk & a_Chunk) { return *static_cast(a_Chunk.GetRedstoneSimulatorData()); } inline void UpdateAdjustedRelative(const cChunk & a_Chunk, const cChunk & a_TickingChunk, const Vector3i a_Position, const Vector3i a_Offset) { const auto PositionToWake = a_Position + a_Offset; if (!cChunkDef::IsValidHeight(PositionToWake)) { // If an offset position is not a valid height, its linked offset positions won't be either. return; } auto & ChunkData = DataForChunk(a_TickingChunk); // Schedule the block in the requested direction to update: ChunkData.WakeUp(cIncrementalRedstoneSimulatorChunkData::RebaseRelativePosition(a_Chunk, a_TickingChunk, PositionToWake)); // To follow Vanilla behaviour, update all linked positions: for (const auto & LinkedOffset : cSimulator::GetLinkedOffsets(a_Offset)) { if (const auto LinkedPositionToWake = a_Position + LinkedOffset; cChunkDef::IsValidHeight(LinkedPositionToWake)) { ChunkData.WakeUp(cIncrementalRedstoneSimulatorChunkData::RebaseRelativePosition(a_Chunk, a_TickingChunk, LinkedPositionToWake)); } } } template inline void UpdateAdjustedRelatives(const cChunk & a_Chunk, const cChunk & a_TickingChunk, const Vector3i a_Position, const ArrayType & a_Relative) { for (const auto & Offset : a_Relative) { UpdateAdjustedRelative(a_Chunk, a_TickingChunk, a_Position, Offset); } } template inline void InvokeForAdjustedRelatives(ForEachSourceCallback & Callback, const Vector3i Position, const ArrayType & Relative) { for (const auto & Offset : Relative) { Callback(Position + Offset); } } inline constexpr Vector3i OffsetYP{ 0, 1, 0 }; inline constexpr Vector3i OffsetYM{ 0, -1, 0 }; inline constexpr std::array RelativeAdjacents { { { 1, 0, 0 }, { -1, 0, 0 }, { 0, 1, 0 }, { 0, -1, 0 }, { 0, 0, 1 }, { 0, 0, -1 }, } }; inline constexpr std::array RelativeLaterals { { { 1, 0, 0 }, { -1, 0, 0 }, { 0, 0, 1 }, { 0, 0, -1 }, } }; ================================================ FILE: src/Simulator/IncrementalRedstoneSimulator/RedstoneHandler.cpp ================================================ #include "Globals.h" #include "RedstoneHandler.h" #include "RedstoneDataHelper.h" #include "ForEachSourceCallback.h" #include "BlockType.h" #include "CommandBlockHandler.h" #include "DaylightSensorHandler.h" #include "DoorHandler.h" #include "RedstoneTorchHandler.h" #include "RedstoneWireHandler.h" #include "RedstoneRepeaterHandler.h" #include "RedstoneToggleHandler.h" #include "RedstoneLampHandler.h" #include "RedstoneBlockHandler.h" #include "PistonHandler.h" #include "SmallGateHandler.h" #include "NoteBlockHandler.h" #include "ObserverHandler.h" #include "TNTHandler.h" #include "PoweredRailHandler.h" #include "PressurePlateHandler.h" #include "TripwireHookHandler.h" #include "DropSpenserHandler.h" #include "RedstoneComparatorHandler.h" #include "TrappedChestHandler.h" #include "HopperHandler.h" #define INVOKE_FOR_HANDLERS(Callback) \ do \ { \ switch (BlockType) \ { \ case E_BLOCK_ACTIVATOR_RAIL: \ case E_BLOCK_DETECTOR_RAIL: \ case E_BLOCK_POWERED_RAIL: return PoweredRailHandler::Callback; \ case E_BLOCK_ACTIVE_COMPARATOR: \ case E_BLOCK_INACTIVE_COMPARATOR: return RedstoneComparatorHandler::Callback; \ case E_BLOCK_DISPENSER: \ case E_BLOCK_DROPPER: return DropSpenserHandler::Callback; \ case E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE: \ case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE: \ case E_BLOCK_STONE_PRESSURE_PLATE: \ case E_BLOCK_WOODEN_PRESSURE_PLATE: return PressurePlateHandler::Callback; \ case E_BLOCK_ACACIA_FENCE_GATE: \ case E_BLOCK_BIRCH_FENCE_GATE: \ case E_BLOCK_DARK_OAK_FENCE_GATE: \ case E_BLOCK_FENCE_GATE: \ case E_BLOCK_IRON_TRAPDOOR: \ case E_BLOCK_JUNGLE_FENCE_GATE: \ case E_BLOCK_SPRUCE_FENCE_GATE: \ case E_BLOCK_TRAPDOOR: return SmallGateHandler::Callback; \ case E_BLOCK_REDSTONE_LAMP_OFF: \ case E_BLOCK_REDSTONE_LAMP_ON: return RedstoneLampHandler::Callback; \ case E_BLOCK_REDSTONE_REPEATER_OFF: \ case E_BLOCK_REDSTONE_REPEATER_ON: return RedstoneRepeaterHandler::Callback; \ case E_BLOCK_REDSTONE_TORCH_OFF: \ case E_BLOCK_REDSTONE_TORCH_ON: return RedstoneTorchHandler::Callback; \ case E_BLOCK_OBSERVER: return ObserverHandler::Callback; \ case E_BLOCK_PISTON: \ case E_BLOCK_STICKY_PISTON: return PistonHandler::Callback; \ case E_BLOCK_DAYLIGHT_SENSOR: \ case E_BLOCK_INVERTED_DAYLIGHT_SENSOR: return DaylightSensorHandler::Callback; \ case E_BLOCK_LEVER: \ case E_BLOCK_STONE_BUTTON: \ case E_BLOCK_WOODEN_BUTTON: return RedstoneToggleHandler::Callback; \ case E_BLOCK_BLOCK_OF_REDSTONE: return RedstoneBlockHandler::Callback; \ case E_BLOCK_COMMAND_BLOCK: return CommandBlockHandler::Callback; \ case E_BLOCK_HOPPER: return HopperHandler::Callback; \ case E_BLOCK_NOTE_BLOCK: return NoteBlockHandler::Callback; \ case E_BLOCK_REDSTONE_WIRE: return RedstoneWireHandler::Callback; \ case E_BLOCK_TNT: return TNTHandler::Callback; \ case E_BLOCK_TRAPPED_CHEST: return TrappedChestHandler::Callback; \ case E_BLOCK_TRIPWIRE_HOOK: return TripwireHookHandler::Callback; \ default: \ { \ if (cBlockDoorHandler::IsDoorBlockType(BlockType)) \ { \ return DoorHandler::Callback; \ } \ } \ } \ } while (false) namespace RedstoneHandler { PowerLevel GetPowerDeliveredToPosition(const cChunk & Chunk, const Vector3i Position, const BLOCKTYPE BlockType, const Vector3i QueryPosition, const BLOCKTYPE QueryBlockType, const bool IsLinked) { INVOKE_FOR_HANDLERS(GetPowerDeliveredToPosition(Chunk, Position, BlockType, QueryPosition, QueryBlockType, IsLinked)); // Fell through the switch statement // Block at Position doesn't have a corresponding redstone handler // ErasePowerData will have been called in AddBlock // Default: return 0; } void Update(cChunk & Chunk, cChunk & CurrentlyTicking, const Vector3i Position, const BLOCKTYPE BlockType, const NIBBLETYPE Meta, const PowerLevel PowerLevel) { INVOKE_FOR_HANDLERS(Update(Chunk, CurrentlyTicking, Position, BlockType, Meta, PowerLevel)); } void ForValidSourcePositions(const cChunk & Chunk, const Vector3i Position, const BLOCKTYPE BlockType, const NIBBLETYPE Meta, ForEachSourceCallback & Callback) { INVOKE_FOR_HANDLERS(ForValidSourcePositions(Chunk, Position, BlockType, Meta, Callback)); } void SetWireState(const cChunk & Chunk, const Vector3i Position) { RedstoneWireHandler::SetWireState(Chunk, Position); } } ================================================ FILE: src/Simulator/IncrementalRedstoneSimulator/RedstoneHandler.h ================================================ #pragma once #include "RedstoneSimulatorChunkData.h" class cChunk; class ForEachSourceCallback; namespace RedstoneHandler { /** Asks a redstone component at the source position how much power it will deliver to the querying position. If IsLinked is true, QueryPosition should point to the intermediate conduit block. The Position and QueryPosition are both relative to Chunk. */ PowerLevel GetPowerDeliveredToPosition(const cChunk & Chunk, Vector3i Position, BLOCKTYPE BlockType, Vector3i QueryPosition, BLOCKTYPE QueryBlockType, bool IsLinked); /** Tells a redstone component at this position to update itself. PowerLevel represents the maximum power level all of its source positions gave to it. Position is relative to Chunk, but if the component needs to queue neighbour updates, they are queued to CurrentlyTicking. */ void Update(cChunk & Chunk, cChunk & CurrentlyTicking, Vector3i Position, BLOCKTYPE BlockType, NIBBLETYPE Meta, PowerLevel PowerLevel); /** Invokes Callback for each position this component can accept power from. */ void ForValidSourcePositions(const cChunk & Chunk, Vector3i Position, BLOCKTYPE BlockType, NIBBLETYPE Meta, ForEachSourceCallback & Callback); /** Temporary: compute and set the block state of a redstone wire. */ void SetWireState(const cChunk & Chunk, Vector3i Position); } ================================================ FILE: src/Simulator/IncrementalRedstoneSimulator/RedstoneLampHandler.h ================================================ #pragma once namespace RedstoneLampHandler { static bool IsOn(BLOCKTYPE a_BlockType) { return (a_BlockType == E_BLOCK_REDSTONE_LAMP_ON); } static PowerLevel GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) { return 0; } static void Update(cChunk & a_Chunk, cChunk &, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, const PowerLevel Power) { // LOGD("Evaluating lamp (%i %i %i)", a_Position.x, a_Position.y, a_Position.z); if (Power > 0) { if (!IsOn(a_BlockType)) { a_Chunk.FastSetBlock(a_Position, E_BLOCK_REDSTONE_LAMP_ON, 0); } } else { if (IsOn(a_BlockType)) { a_Chunk.FastSetBlock(a_Position, E_BLOCK_REDSTONE_LAMP_OFF, 0); } } } static void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, ForEachSourceCallback & Callback) { UNUSED(a_Chunk); UNUSED(a_Meta); UNUSED(a_BlockType); InvokeForAdjustedRelatives(Callback, a_Position, RelativeAdjacents); } }; ================================================ FILE: src/Simulator/IncrementalRedstoneSimulator/RedstoneRepeaterHandler.h ================================================ #pragma once #include "../../Blocks/BlockRedstoneRepeater.h" namespace RedstoneRepeaterHandler { static bool IsOn(BLOCKTYPE a_Block) { return (a_Block == E_BLOCK_REDSTONE_REPEATER_ON); } /** Returns a pair with first element indicating if the block at the given position is an activated repeater. If it is activated, the second element is the repeater metadata. */ static std::pair IsOnRepeater(cChunk & Chunk, const Vector3i a_Position) { BLOCKTYPE Type; NIBBLETYPE Meta; if (!Chunk.UnboundedRelGetBlock(a_Position, Type, Meta)) { return std::make_pair(false, static_cast(0)); } return std::make_pair(IsOn(Type), Meta); } /** Determine, from the metadata of a repeater on our left side, if they lock us. To test a repeater on our right, simply invert the order of arguments provided. "Left" is relative to the direction the repeater output faces, naturally. */ static bool DoesLhsLockMe(NIBBLETYPE a_MetaLhs, NIBBLETYPE a_MyMeta) { // Get the direction bits a_MetaLhs &= E_META_REDSTONE_REPEATER_FACING_MASK; a_MyMeta &= E_META_REDSTONE_REPEATER_FACING_MASK; /* Check for a valid locking configuration, where they are perpendicular and one snuggles into the other. Order of comparisons: XP >^ ZM ZP |_ XP XM <| ZP ZP ^< xM Key: ^ Facing up _ Facing right | Facing down < Facing left */ return ((a_MetaLhs == E_META_REDSTONE_REPEATER_FACING_XP) && (a_MyMeta == E_META_REDSTONE_REPEATER_FACING_ZM)) || ((a_MetaLhs == E_META_REDSTONE_REPEATER_FACING_ZP) && (a_MyMeta == E_META_REDSTONE_REPEATER_FACING_XP)) || ((a_MetaLhs == E_META_REDSTONE_REPEATER_FACING_XM) && (a_MyMeta == E_META_REDSTONE_REPEATER_FACING_ZP)) || ((a_MetaLhs == E_META_REDSTONE_REPEATER_FACING_ZM) && (a_MyMeta == E_META_REDSTONE_REPEATER_FACING_XM)) ; } /** Determine if a repeater is locked. A locked repeater is one with another powered repeater facing them, to their immediate left or right sides. "Left" is relative to the direction the repeater output faces, naturally. */ static bool IsLocked(cChunk & Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) { // The left hand side offset. Will be negated to get the rhs offset const auto LhsOffset = cBlockRedstoneRepeaterHandler::GetLeftCoordinateOffset(a_Meta); // Test the block to the left of us const auto Lhs = IsOnRepeater(Chunk, LhsOffset + a_Position); if (Lhs.first && DoesLhsLockMe(Lhs.second, a_Meta)) { return true; } // Test the right side, flipping the argument order to DoesLhsLockMe const auto Rhs = IsOnRepeater(Chunk, -LhsOffset + a_Position); return Rhs.first && DoesLhsLockMe(a_Meta, Rhs.second); } static PowerLevel GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) { if (!IsOn(a_BlockType)) { return 0; } const auto FrontOffset = cBlockRedstoneRepeaterHandler::GetFrontCoordinateOffset(a_Chunk.GetMeta(a_Position)); const auto FrontPosition = a_Position + FrontOffset; if (a_QueryPosition == FrontPosition) { return 15; } return 0; } static void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, const PowerLevel Power) { // LOGD("Evaluating loopy the repeater (%d %d %d)", a_Position.x, a_Position.y, a_Position.z); auto & Data = DataForChunk(a_Chunk); const auto DelayInfo = Data.GetMechanismDelayInfo(a_Position); // If the repeater is locked by another, ignore and forget all power changes: if (IsLocked(a_Chunk, a_Position, a_Meta)) { if (DelayInfo != nullptr) { Data.m_MechanismDelays.erase(a_Position); } return; } if (DelayInfo == nullptr) { bool ShouldBeOn = (Power != 0); if (ShouldBeOn != IsOn(a_BlockType)) { Data.m_MechanismDelays[a_Position] = std::make_pair((((a_Meta & 0xC) >> 0x2) + 1), ShouldBeOn); } return; } int DelayTicks; bool ShouldPowerOn; std::tie(DelayTicks, ShouldPowerOn) = *DelayInfo; if (DelayTicks != 0) { return; } const auto NewType = ShouldPowerOn ? E_BLOCK_REDSTONE_REPEATER_ON : E_BLOCK_REDSTONE_REPEATER_OFF; a_Chunk.FastSetBlock(a_Position, NewType, a_Meta); Data.m_MechanismDelays.erase(a_Position); // While sleeping, we ignore any power changes and apply our saved ShouldBeOn when sleep expires // Now, we need to recalculate to be aware of any new changes that may e.g. cause a new output change // FastSetBlock doesn't wake simulators, so manually update ourselves: Update(a_Chunk, CurrentlyTicking, a_Position, NewType, a_Meta, Power); UpdateAdjustedRelative(a_Chunk, CurrentlyTicking, a_Position, cBlockRedstoneRepeaterHandler::GetFrontCoordinateOffset(a_Meta)); } static void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, ForEachSourceCallback & Callback) { Callback(cBlockRedstoneRepeaterHandler::GetRearCoordinateOffset(a_Meta) + a_Position); } }; ================================================ FILE: src/Simulator/IncrementalRedstoneSimulator/RedstoneSimulatorChunkData.h ================================================ #pragma once #include #include "Chunk.h" #include "BlockState.h" #include "Simulator/RedstoneSimulator.h" using PowerLevel = unsigned char; class cIncrementalRedstoneSimulatorChunkData final : public cRedstoneSimulatorChunkData { public: void WakeUp(const Vector3i & a_Position) { m_ActiveBlocks.push(a_Position); } auto & GetActiveBlocks() { return m_ActiveBlocks; } PowerLevel GetCachedPowerData(const Vector3i Position) const { auto Result = m_CachedPowerLevels.find(Position); return (Result == m_CachedPowerLevels.end()) ? 0 : Result->second; } void SetCachedPowerData(const Vector3i Position, const PowerLevel PowerLevel) { m_CachedPowerLevels[Position] = PowerLevel; } std::pair * GetMechanismDelayInfo(const Vector3i Position) { auto Result = m_MechanismDelays.find(Position); return (Result == m_MechanismDelays.end()) ? nullptr : &Result->second; } /** Erase all cached redstone data for position. */ void ErasePowerData(const Vector3i Position) { m_CachedPowerLevels.erase(Position); m_MechanismDelays.erase(Position); AlwaysTickedPositions.erase(Position); WireStates.erase(Position); ObserverCache.erase(Position); } PowerLevel ExchangeUpdateOncePowerData(const Vector3i & a_Position, PowerLevel Power) { auto Result = m_CachedPowerLevels.find(a_Position); if (Result == m_CachedPowerLevels.end()) { m_CachedPowerLevels[a_Position] = Power; return 0; } return std::exchange(Result->second, Power); } /** Adjust From-relative coordinates into To-relative coordinates. */ inline static Vector3i RebaseRelativePosition(const cChunk & From, const cChunk & To, const Vector3i Position) { return { Position.x + (From.GetPosX() - To.GetPosX()) * cChunkDef::Width, Position.y, Position.z + (From.GetPosZ() - To.GetPosZ()) * cChunkDef::Width }; } /** Temporary, should be chunk data: wire block store, to avoid recomputing states every time. */ std::unordered_map> WireStates; std::unordered_set> AlwaysTickedPositions; /** Structure storing an observer's last seen block. */ std::unordered_map, VectorHasher> ObserverCache; /** Structure storing position of mechanism + it's delay ticks (countdown) & if to power on. */ std::unordered_map, VectorHasher> m_MechanismDelays; private: std::stack> m_ActiveBlocks; // TODO: map -> Position of torch + it's heat level std::unordered_map> m_CachedPowerLevels; friend class cRedstoneHandlerFactory; }; ================================================ FILE: src/Simulator/IncrementalRedstoneSimulator/RedstoneToggleHandler.h ================================================ #pragma once #include "../../Blocks/BlockButton.h" #include "../../Blocks/BlockLever.h" namespace RedstoneToggleHandler { static Vector3i GetOffsetAttachedTo(Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) { switch (a_BlockType) { case E_BLOCK_LEVER: { switch (a_Meta & 0x7) { case 0x0: case 0x7: return { 0, 1, 0 }; case 0x1: return { -1, 0, 0 }; case 0x2: return { 1, 0, 0 }; case 0x3: return { 0, 0, -1 }; case 0x4: return { 0, 0, 1 }; case 0x5: case 0x6: return { 0, -1, 0 }; default: { ASSERT(!"Unhandled lever metadata!"); return { 0, 0, 0 }; } } } case E_BLOCK_STONE_BUTTON: case E_BLOCK_WOODEN_BUTTON: { switch (a_Meta & 0x7) { case 0x0: return { 0, 1, 0 }; case 0x1: return { -1, 0, 0 }; case 0x2: return { 1, 0, 0 }; case 0x3: return { 0, 0, -1 }; case 0x4: return { 0, 0, 1 }; case 0x5: return { 0, -1, 0 }; default: { ASSERT(!"Unhandled button metadata!"); return { 0, 0, 0 }; } } } default: { ASSERT(!"Unexpected block passed to button/lever handler"); return { 0, 0, 0 }; } } } static unsigned char GetPowerLevel(BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) { switch (a_BlockType) { case E_BLOCK_LEVER: return cBlockLeverHandler::IsLeverOn(a_Meta) ? 15 : 0; case E_BLOCK_STONE_BUTTON: case E_BLOCK_WOODEN_BUTTON: return cBlockButtonHandler::IsButtonOn(a_Meta) ? 15 : 0; default: { ASSERT(!"Unexpected block passed to button/lever handler"); return 0; } } } static PowerLevel GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) { UNUSED(a_QueryBlockType); const auto Meta = a_Chunk.GetMeta(a_Position); const auto QueryOffset = a_QueryPosition - a_Position; if (IsLinked && (QueryOffset != GetOffsetAttachedTo(a_Position, a_BlockType, Meta))) { return 0; } return GetPowerLevel(a_BlockType, Meta); } static void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, const PowerLevel Power) { // LOGD("Evaluating templatio<> the lever/button (%d %d %d)", a_Position.x, a_Position.y, a_Position.z); } static void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, ForEachSourceCallback & Callback) { UNUSED(a_Chunk); UNUSED(a_Position); UNUSED(a_BlockType); UNUSED(a_Meta); UNUSED(Callback); } }; ================================================ FILE: src/Simulator/IncrementalRedstoneSimulator/RedstoneTorchHandler.h ================================================ #pragma once namespace RedstoneTorchHandler { static bool IsOn(BLOCKTYPE a_Block) { return (a_Block == E_BLOCK_REDSTONE_TORCH_ON); } static Vector3i GetOffsetAttachedTo(const NIBBLETYPE a_Meta) { switch (a_Meta) { case E_META_TORCH_FLOOR: return { 0, -1, 0 }; case E_META_TORCH_EAST: return { -1, 0, 0 }; case E_META_TORCH_WEST: return { 1, 0, 0 }; case E_META_TORCH_NORTH: return { 0, 0, 1 }; case E_META_TORCH_SOUTH: return { 0, 0, -1 }; default: { ASSERT(!"Unhandled torch metadata"); return { 0, 0, 0 }; } } } static PowerLevel GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) { const auto QueryOffset = a_QueryPosition - a_Position; if ( !IsOn(a_BlockType) || (QueryOffset == GetOffsetAttachedTo(a_Chunk.GetMeta(a_Position))) || (IsLinked && (QueryOffset != OffsetYP)) ) { return 0; } return 15; } static void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, const PowerLevel Power) { // LOGD("Evaluating torchy the redstone torch (%i %i %i)", a_Position.x, a_Position.y, a_Position.z); auto & Data = DataForChunk(a_Chunk); auto DelayInfo = Data.GetMechanismDelayInfo(a_Position); if (DelayInfo == nullptr) { const bool ShouldBeOn = (Power == 0); if (ShouldBeOn != IsOn(a_BlockType)) { Data.m_MechanismDelays[a_Position] = std::make_pair(1, ShouldBeOn); } return; } int DelayTicks; bool ShouldPowerOn; std::tie(DelayTicks, ShouldPowerOn) = *DelayInfo; if (DelayTicks != 0) { return; } a_Chunk.FastSetBlock(a_Position, ShouldPowerOn ? E_BLOCK_REDSTONE_TORCH_ON : E_BLOCK_REDSTONE_TORCH_OFF, a_Meta); Data.m_MechanismDelays.erase(a_Position); for (const auto & Adjacent : RelativeAdjacents) { // Update all adjacents (including linked power positions) // apart from our attachment, which can't possibly need an update: if (Adjacent != GetOffsetAttachedTo(a_Meta)) { UpdateAdjustedRelative(a_Chunk, CurrentlyTicking, a_Position, Adjacent); } } } static void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, ForEachSourceCallback & Callback) { UNUSED(a_Chunk); UNUSED(a_BlockType); Callback(a_Position + GetOffsetAttachedTo(a_Meta)); } }; ================================================ FILE: src/Simulator/IncrementalRedstoneSimulator/RedstoneWireHandler.h ================================================ #pragma once #include "RedstoneHandler.h" #include "Registries/BlockStates.h" namespace RedstoneWireHandler { /** A unified representation of wire direction. */ enum class TemporaryDirection { Up, Side }; /** Invokes Callback with the wire's left, front, and right direction state corresponding to Offset. Returns a new block constructed from the directions that the callback may have modified. */ template static BlockState DoWithDirectionState(const Vector3i Offset, BlockState Block, OffsetCallback Callback) { auto North = Block::RedstoneWire::North(Block); auto South = Block::RedstoneWire::South(Block); auto West = Block::RedstoneWire::West(Block); auto East = Block::RedstoneWire::East(Block); if (Offset.x == -1) { Callback(South, West, North); } else if (Offset.x == 1) { Callback(North, East, South); } if (Offset.z == -1) { Callback(West, North, East); } else if (Offset.z == 1) { Callback(East, South, West); } return Block::RedstoneWire::RedstoneWire(East, North, 0, South, West); } /** Adjusts a given wire block so that the direction represented by Offset has state Direction. */ static void SetDirectionState(const Vector3i Offset, BlockState & Block, TemporaryDirection Direction) { Block = DoWithDirectionState(Offset, Block, [Direction](auto, auto & Front, auto) { using FrontState = std::remove_reference_t; switch (Direction) { case TemporaryDirection::Up: { Front = FrontState::Up; return; } case TemporaryDirection::Side: { Front = FrontState::Side; return; } } }); } static bool IsDirectlyConnectingMechanism(BLOCKTYPE a_Block, NIBBLETYPE a_BlockMeta, const Vector3i a_Offset) { switch (a_Block) { case E_BLOCK_REDSTONE_REPEATER_ON: case E_BLOCK_REDSTONE_REPEATER_OFF: { a_BlockMeta &= E_META_REDSTONE_REPEATER_FACING_MASK; if ((a_BlockMeta == E_META_REDSTONE_REPEATER_FACING_XP) || (a_BlockMeta == E_META_REDSTONE_REPEATER_FACING_XM)) { // Wire connects to repeater if repeater is aligned along X // and wire is in front or behind it (#4639) return a_Offset.x != 0; } return a_Offset.z != 0; } case E_BLOCK_ACTIVE_COMPARATOR: case E_BLOCK_BLOCK_OF_REDSTONE: case E_BLOCK_INACTIVE_COMPARATOR: case E_BLOCK_LEVER: case E_BLOCK_REDSTONE_TORCH_OFF: case E_BLOCK_REDSTONE_TORCH_ON: case E_BLOCK_REDSTONE_WIRE: case E_BLOCK_STONE_BUTTON: case E_BLOCK_WOODEN_BUTTON: return true; default: return false; } } static bool IsYPTerracingBlocked(const cChunk & a_Chunk, const Vector3i a_Position) { const auto Position = a_Position + OffsetYP; if (!cChunkDef::IsValidHeight(Position)) { // Certainly cannot terrace at the top of the world: return true; } const auto YPTerraceBlock = a_Chunk.GetBlock(Position); return cBlockInfo::IsSolid(YPTerraceBlock) && !cBlockInfo::IsTransparent(YPTerraceBlock); } /** Temporary. Discovers a wire's connection state, including terracing, storing the block inside redstone chunk data. TODO: once the server supports block states this should go in the block handler, with data saved in the world. */ static void SetWireState(const cChunk & a_Chunk, const Vector3i a_Position) { auto Block = Block::RedstoneWire::RedstoneWire(); const bool IsYPTerracingBlocked = RedstoneWireHandler::IsYPTerracingBlocked(a_Chunk, a_Position); // Loop through laterals, discovering terracing connections: for (const auto & Offset : RelativeLaterals) { auto Adjacent = a_Position + Offset; auto NeighbourChunk = a_Chunk.GetRelNeighborChunkAdjustCoords(Adjacent); if ((NeighbourChunk == nullptr) || !NeighbourChunk->IsValid()) { continue; } BLOCKTYPE LateralBlock; NIBBLETYPE LateralMeta; NeighbourChunk->GetBlockTypeMeta(Adjacent, LateralBlock, LateralMeta); if (IsDirectlyConnectingMechanism(LateralBlock, LateralMeta, Offset)) { // Any direct connections on a lateral means the wire has side connection in that direction: SetDirectionState(Offset, Block, TemporaryDirection::Side); // Temporary: this case will eventually be handled when wires are placed, with the state saved as blocks // When a neighbour wire was loaded into its chunk, its neighbour chunks may not have loaded yet // This function is called during chunk load (through AddBlock). Attempt to tell it its new state: if ((NeighbourChunk != &a_Chunk) && (LateralBlock == E_BLOCK_REDSTONE_WIRE)) { auto & NeighbourBlock = DataForChunk(*NeighbourChunk).WireStates.find(Adjacent)->second; SetDirectionState(-Offset, NeighbourBlock, TemporaryDirection::Side); } continue; } if ( !IsYPTerracingBlocked && // A block above us blocks all YP terracing, so the check is static in the loop (Adjacent.y < (cChunkDef::Height - 1)) && (NeighbourChunk->GetBlock(Adjacent + OffsetYP) == E_BLOCK_REDSTONE_WIRE) // Only terrace YP with another wire ) { SetDirectionState(Offset, Block, cBlockInfo::IsTransparent(LateralBlock) ? TemporaryDirection::Side : TemporaryDirection::Up); if (NeighbourChunk != &a_Chunk) { auto & NeighbourBlock = DataForChunk(*NeighbourChunk).WireStates.find(Adjacent + OffsetYP)->second; SetDirectionState(-Offset, NeighbourBlock, TemporaryDirection::Side); } continue; } if ( // IsYMTerracingBlocked (i.e. check block above lower terracing position, a.k.a. just the plain adjacent) (!cBlockInfo::IsSolid(LateralBlock) || cBlockInfo::IsTransparent(LateralBlock)) && (Adjacent.y > 0) && (NeighbourChunk->GetBlock(Adjacent + OffsetYM) == E_BLOCK_REDSTONE_WIRE) // Only terrace YM with another wire ) { SetDirectionState(Offset, Block, TemporaryDirection::Side); if (NeighbourChunk != &a_Chunk) { auto & NeighbourBlock = DataForChunk(*NeighbourChunk).WireStates.find(Adjacent + OffsetYM)->second; SetDirectionState(-Offset, NeighbourBlock, TemporaryDirection::Up); } } } auto & States = DataForChunk(a_Chunk).WireStates; const auto FindResult = States.find(a_Position); if (FindResult != States.end()) { if (Block != FindResult->second) { FindResult->second = Block; // TODO: when state is stored as the block, the block handler updating via SetBlock will do this automatically // When a wire changes connection state, it needs to update its neighbours: a_Chunk.GetWorld()->WakeUpSimulators(cChunkDef::RelativeToAbsolute(a_Position, a_Chunk.GetPos())); } return; } DataForChunk(a_Chunk).WireStates.emplace(a_Position, Block); } static PowerLevel GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) { // Starts off as the wire's meta value, modified appropriately and returned auto Power = a_Chunk.GetMeta(a_Position); const auto QueryOffset = a_QueryPosition - a_Position; if ( (QueryOffset == OffsetYP) || // Wires do not power things above them (IsLinked && (a_QueryBlockType == E_BLOCK_REDSTONE_WIRE)) // Nor do they link power other wires ) { return 0; } if (QueryOffset == OffsetYM) { // Wires always deliver power to the block underneath return Power; } const auto & Data = DataForChunk(a_Chunk); const auto Block = Data.WireStates.find(a_Position)->second; DoWithDirectionState(QueryOffset, Block, [a_QueryBlockType, &Power](const auto Left, const auto Front, const auto Right) { using LeftState = std::remove_reference_t; using FrontState = std::remove_reference_t; using RightState = std::remove_reference_t; // Wires always deliver power to any directly connecting mechanisms: if (Front != FrontState::None) { if ((a_QueryBlockType == E_BLOCK_REDSTONE_WIRE) && (Power != 0)) { // For mechanisms, wire of power one will still power them // But for wire-to-wire connections, power level decreases by 1: Power--; } return; } /* Okay, we do not directly connect to the wire. 1. If there are no DC mechanisms at all, the wire powers all laterals. Great, left and right are both None. 2. If there is one DC mechanism, the wire "goes straight" along the axis of the wire and mechanism. The only possible way for us to be powered is for us to be on the opposite end, with the wire pointing towards us. Check that left and right are both None. 3. If there is more than one DC, no non-DCs are powered. Left, right, cannot both be None. */ if ((Left == LeftState::None) && (Right == RightState::None)) { // Case 1 // Case 2 return; } // Case 3 Power = 0; }); return Power; } static void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, const PowerLevel Power) { // LOGD("Evaluating dusty the wire (%d %d %d) %i", a_Position.x, a_Position.y, a_Position.z, Power); if (a_Meta == Power) { return; } a_Chunk.SetMeta(a_Position, Power); // Notify all positions, sans YP, to update: UpdateAdjustedRelative(a_Chunk, CurrentlyTicking, a_Position, OffsetYM); UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, a_Position, RelativeLaterals); } static void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, ForEachSourceCallback & Callback) { UNUSED(a_BlockType); UNUSED(a_Meta); Callback(a_Position + OffsetYP); Callback(a_Position + OffsetYM); const auto & Data = DataForChunk(a_Chunk); const auto Block = Data.WireStates.find(a_Position)->second; // Figure out, based on our pre-computed block, where we connect to: for (const auto & Offset : RelativeLaterals) { const auto Relative = a_Position + Offset; Callback(Relative); DoWithDirectionState(Offset, Block, [&a_Chunk, &Callback, Relative](auto, const auto Front, auto) { using FrontState = std::remove_reference_t; if (Front == FrontState::Up) { Callback(Relative + OffsetYP); } else if (Front == FrontState::Side) { // Alas, no way to distinguish side lateral and side diagonal // Have to do a manual check to only accept power from YM diagonal if there's a wire there const auto YMDiagonalPosition = Relative + OffsetYM; if ( BLOCKTYPE QueryBlock; cChunkDef::IsValidHeight(YMDiagonalPosition) && a_Chunk.UnboundedRelGetBlockType(YMDiagonalPosition, QueryBlock) && (QueryBlock == E_BLOCK_REDSTONE_WIRE) ) { Callback(YMDiagonalPosition); } } }); } } }; ================================================ FILE: src/Simulator/IncrementalRedstoneSimulator/SmallGateHandler.h ================================================ #pragma once namespace SmallGateHandler { static PowerLevel GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) { UNUSED(a_Chunk); UNUSED(a_Position); UNUSED(a_BlockType); UNUSED(a_QueryPosition); UNUSED(a_QueryBlockType); UNUSED(IsLinked); return 0; } static void Update(cChunk & a_Chunk, cChunk &, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, const PowerLevel Power) { // LOGD("Evaluating gateydory the fence gate/trapdoor (%d %d %d)", a_Position.x, a_Position.y, a_Position.z); // Use redstone data rather than block state so players can override redstone control const auto Previous = DataForChunk(a_Chunk).ExchangeUpdateOncePowerData(a_Position, Power); const bool IsOpen = (Previous != 0); const bool ShouldBeOpen = Power != 0; if (ShouldBeOpen != IsOpen) { a_Chunk.SetMeta(a_Position, ShouldBeOpen ? (a_Meta | 0x4) : (a_Meta & ~0x04)); } } static void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, ForEachSourceCallback & Callback) { UNUSED(a_Chunk); UNUSED(a_BlockType); UNUSED(a_Meta); InvokeForAdjustedRelatives(Callback, a_Position, RelativeAdjacents); } }; ================================================ FILE: src/Simulator/IncrementalRedstoneSimulator/TNTHandler.h ================================================ #pragma once namespace TNTHandler { static PowerLevel GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) { UNUSED(a_Chunk); UNUSED(a_Position); UNUSED(a_BlockType); UNUSED(a_QueryPosition); UNUSED(a_QueryBlockType); UNUSED(IsLinked); return 0; } static void Update(cChunk & a_Chunk, cChunk &, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, const PowerLevel Power) { // LOGD("Evaluating explodinator the trinitrotoluene (%d %d %d)", a_Position.x, a_Position.y, a_Position.z); if (Power != 0) { a_Chunk.SetBlock(a_Position, E_BLOCK_AIR, 0); a_Chunk.GetWorld()->SpawnPrimedTNT(Vector3d(0.5, 0.5, 0.5) + cChunkDef::RelativeToAbsolute(a_Position, a_Chunk.GetPos())); // 80 ticks to boom } } static void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, ForEachSourceCallback & Callback) { UNUSED(a_Chunk); UNUSED(a_BlockType); UNUSED(a_Meta); InvokeForAdjustedRelatives(Callback, a_Position, RelativeAdjacents); } }; ================================================ FILE: src/Simulator/IncrementalRedstoneSimulator/TrappedChestHandler.h ================================================ #pragma once #include "../../BlockEntities/ChestEntity.h" namespace TrappedChestHandler { static PowerLevel GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) { UNUSED(a_BlockType); UNUSED(a_QueryPosition); UNUSED(a_QueryBlockType); UNUSED(IsLinked); return DataForChunk(a_Chunk).GetCachedPowerData(a_Position); } static unsigned char GetPowerLevel(cChunk & a_Chunk, Vector3i a_Position) { int NumberOfPlayers = 0; a_Chunk.DoWithBlockEntityAt(a_Position, [&NumberOfPlayers](cBlockEntity & a_BlockEntity) { ASSERT(a_BlockEntity.GetBlockType() == E_BLOCK_TRAPPED_CHEST); NumberOfPlayers = static_cast(a_BlockEntity).GetNumberOfPlayers(); return false; }); return static_cast(std::min(NumberOfPlayers, 15)); } static void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, const PowerLevel Power) { // LOGD("Evaluating tricky the trapped chest (%d %d %d)", a_Position.x, a_Position.y, a_Position.z); const auto PowerLevel = GetPowerLevel(a_Chunk, a_Position); const auto PreviousPower = DataForChunk(a_Chunk).ExchangeUpdateOncePowerData(a_Position, PowerLevel); if (PowerLevel != PreviousPower) { UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, a_Position, RelativeAdjacents); } } static void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, ForEachSourceCallback & Callback) { UNUSED(a_Chunk); UNUSED(a_Position); UNUSED(a_BlockType); UNUSED(a_Meta); UNUSED(Callback); } }; ================================================ FILE: src/Simulator/IncrementalRedstoneSimulator/TripwireHookHandler.h ================================================ #pragma once #include "../../Blocks/BlockTripwireHook.h" namespace TripwireHookHandler { static unsigned char GetPowerLevel(const cChunk & a_Chunk, Vector3i a_Position, NIBBLETYPE a_Meta) { bool FoundActivated = false; const auto FaceToGoTowards = cBlockTripwireHookHandler::MetadataToDirection(a_Meta); for (int i = 0; i < 40; ++i) // Tripwires can be connected up to 40 blocks { BLOCKTYPE Type; NIBBLETYPE Meta; a_Position = AddFaceDirection(a_Position, FaceToGoTowards); if (!a_Chunk.UnboundedRelGetBlock(a_Position, Type, Meta)) { return 0; } if (Type == E_BLOCK_TRIPWIRE) { if (FoundActivated) { continue; } if ( !a_Chunk.ForEachEntityInBox( cBoundingBox(Vector3d(0.5, 0, 0.5) + cChunkDef::RelativeToAbsolute(a_Position, a_Chunk.GetPos()), 0.5, 0.5), [](cEntity &) { return true; } ) ) { FoundActivated = true; } continue; } else if (Type == E_BLOCK_TRIPWIRE_HOOK) { if (ReverseBlockFace(cBlockTripwireHookHandler::MetadataToDirection(Meta)) == FaceToGoTowards) { // Other hook facing in opposite direction - circuit completed! return FoundActivated ? 15 : 1; } } // Tripwire hook not connected at all return 0; } return 0; } static PowerLevel GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) { UNUSED(a_BlockType); UNUSED(a_QueryBlockType); UNUSED(a_QueryPosition); return (GetPowerLevel(a_Chunk, a_Position, a_Chunk.GetMeta(a_Position)) == 15) ? 15 : 0; } static void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, const PowerLevel Power) { // LOGD("Evaluating hooky the tripwire hook (%d %d %d)", a_Position.x, a_Position.y, a_Position.z); const auto PowerLevel = GetPowerLevel(a_Chunk, a_Position, a_Meta); NIBBLETYPE Meta; if (PowerLevel == 0) { Meta = (a_Meta & 0x3); } else if (PowerLevel == 1) { // Connected but not activated, AND away the highest bit Meta = (a_Meta & 0x7) | 0x4; } else if (PowerLevel == 15) { // Connected and activated, set the 3rd and 4th highest bits Meta = (a_Meta | 0xC); } else { UNREACHABLE("Unexpected tripwire hook power level!"); } if (Meta != a_Meta) { a_Chunk.SetMeta(a_Position, Meta); UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, a_Position, RelativeAdjacents); } } static void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, ForEachSourceCallback & Callback) { UNUSED(a_Chunk); UNUSED(a_BlockType); UNUSED(a_Meta); UNUSED(a_Position); UNUSED(Callback); } }; ================================================ FILE: src/Simulator/NoopFluidSimulator.h ================================================ // NoopFluidSimulator.h // Declares the cNoopFluidSimulator class representing a fluid simulator that performs nothing, it ignores all blocks #pragma once #include "FluidSimulator.h" class cNoopFluidSimulator final : public cFluidSimulator { using Super = cFluidSimulator; public: using Super::Super; private: virtual void SimulateChunk(std::chrono::milliseconds a_Dt, int a_ChunkX, int a_ChunkZ, cChunk * a_Chunk) override { UNUSED(a_Dt); UNUSED(a_ChunkX); UNUSED(a_ChunkZ); UNUSED(a_Chunk); } virtual void AddBlock(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_Block) override { UNUSED(a_Block); UNUSED(a_Chunk); } virtual cFluidSimulatorData * CreateChunkData(void) override { return nullptr; } } ; ================================================ FILE: src/Simulator/NoopRedstoneSimulator.h ================================================ #pragma once #include "RedstoneSimulator.h" class cRedstoneNoopSimulator final : public cRedstoneSimulator { using Super = cRedstoneSimulator; public: cRedstoneNoopSimulator(cWorld & a_World): Super(a_World) { } virtual void SimulateChunk(std::chrono::milliseconds a_Dt, int a_ChunkX, int a_ChunkZ, cChunk * a_Chunk) override { UNUSED(a_Dt); UNUSED(a_ChunkX); UNUSED(a_ChunkZ); UNUSED(a_Chunk); } virtual void AddBlock(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_Block) override { UNUSED(a_Block); UNUSED(a_Chunk); } virtual cRedstoneSimulatorChunkData * CreateChunkData() override { return nullptr; } } ; ================================================ FILE: src/Simulator/RedstoneSimulator.h ================================================ #pragma once #include "Simulator.h" class cRedstoneSimulatorChunkData { public: virtual ~cRedstoneSimulatorChunkData() { } }; class cRedstoneSimulator: public cSimulator { using Super = cSimulator; public: using Super::Super; virtual cRedstoneSimulatorChunkData * CreateChunkData() = 0; }; ================================================ FILE: src/Simulator/SandSimulator.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "SandSimulator.h" #include "../BlockInfo.h" #include "../World.h" #include "../Defines.h" #include "../Entities/FallingBlock.h" #include "../Chunk.h" #include "../IniFile.h" #include "../EffectID.h" cSandSimulator::cSandSimulator(cWorld & a_World, cIniFile & a_IniFile) : cSimulator(a_World), m_TotalBlocks(0) { m_IsInstantFall = a_IniFile.GetValueSetB("Physics", "SandInstantFall", false); } void cSandSimulator::SimulateChunk(std::chrono::milliseconds a_Dt, int a_ChunkX, int a_ChunkZ, cChunk * a_Chunk) { cSandSimulatorChunkData & ChunkData = a_Chunk->GetSandSimulatorData(); if (ChunkData.empty()) { return; } int BaseX = a_Chunk->GetPosX() * cChunkDef::Width; int BaseZ = a_Chunk->GetPosZ() * cChunkDef::Width; for (cSandSimulatorChunkData::const_iterator itr = ChunkData.begin(), end = ChunkData.end(); itr != end; ++itr) { BLOCKTYPE BlockType = a_Chunk->GetBlock(itr->x, itr->y, itr->z); if (!IsAllowedBlock(BlockType) || (itr->y <= 0)) { continue; } BLOCKTYPE BlockBelow = (itr->y > 0) ? a_Chunk->GetBlock(itr->x, itr->y - 1, itr->z) : static_cast(E_BLOCK_AIR); if (CanStartFallingThrough(BlockBelow)) { if (m_IsInstantFall) { DoInstantFall(a_Chunk, itr->x, itr->y, itr->z); continue; } Vector3i Pos; Pos.x = itr->x + BaseX; Pos.y = itr->y; Pos.z = itr->z + BaseZ; /* FLOGD( "Creating a falling block at {0} of type {1}, block below: {2}", Pos, ItemTypeToString(BlockType), ItemTypeToString(BlockBelow) ); */ m_World.SpawnFallingBlock(Pos, BlockType, a_Chunk->GetMeta(itr->x, itr->y, itr->z)); a_Chunk->SetBlock({itr->x, itr->y, itr->z}, E_BLOCK_AIR, 0); } } m_TotalBlocks -= static_cast(ChunkData.size()); ChunkData.clear(); } void cSandSimulator::AddBlock(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_Block) { if (!IsAllowedBlock(a_Block)) { return; } // Check for duplicates: cSandSimulatorChunkData & ChunkData = a_Chunk.GetSandSimulatorData(); for (cSandSimulatorChunkData::iterator itr = ChunkData.begin(); itr != ChunkData.end(); ++itr) { if ((itr->x == a_Position.x) && (itr->y == a_Position.y) && (itr->z == a_Position.z)) { return; } } m_TotalBlocks += 1; ChunkData.emplace_back(a_Position.x, a_Position.y, a_Position.z); } bool cSandSimulator::CanStartFallingThrough(BLOCKTYPE a_BlockType) { // Please keep the list alpha-sorted switch (a_BlockType) { case E_BLOCK_AIR: case E_BLOCK_FIRE: case E_BLOCK_LAVA: case E_BLOCK_SNOW: case E_BLOCK_STATIONARY_LAVA: case E_BLOCK_STATIONARY_WATER: case E_BLOCK_WATER: { return true; } } return false; } bool cSandSimulator::CanContinueFallThrough(BLOCKTYPE a_BlockType) { // Please keep the list alpha-sorted switch (a_BlockType) { case E_BLOCK_AIR: case E_BLOCK_BEETROOTS: case E_BLOCK_BROWN_MUSHROOM: case E_BLOCK_CARROTS: case E_BLOCK_COBWEB: case E_BLOCK_CROPS: case E_BLOCK_DEAD_BUSH: case E_BLOCK_DETECTOR_RAIL: case E_BLOCK_FIRE: case E_BLOCK_FLOWER_POT: case E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE: case E_BLOCK_IRON_TRAPDOOR: case E_BLOCK_LAVA: case E_BLOCK_LEVER: case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE: case E_BLOCK_MINECART_TRACKS: case E_BLOCK_MELON_STEM: case E_BLOCK_POWERED_RAIL: case E_BLOCK_PUMPKIN_STEM: case E_BLOCK_REDSTONE_REPEATER_OFF: case E_BLOCK_REDSTONE_REPEATER_ON: case E_BLOCK_REDSTONE_TORCH_OFF: case E_BLOCK_REDSTONE_TORCH_ON: case E_BLOCK_REDSTONE_WIRE: case E_BLOCK_RED_MUSHROOM: case E_BLOCK_RED_ROSE: case E_BLOCK_SIGN_POST: case E_BLOCK_SNOW: case E_BLOCK_STANDING_BANNER: case E_BLOCK_STATIONARY_LAVA: case E_BLOCK_STATIONARY_WATER: case E_BLOCK_STONE_BUTTON: case E_BLOCK_STONE_PRESSURE_PLATE: case E_BLOCK_TALL_GRASS: case E_BLOCK_TORCH: case E_BLOCK_TRAPDOOR: case E_BLOCK_TRIPWIRE: case E_BLOCK_TRIPWIRE_HOOK: case E_BLOCK_WALL_BANNER: case E_BLOCK_WALLSIGN: case E_BLOCK_WATER: case E_BLOCK_WOODEN_BUTTON: case E_BLOCK_WOODEN_PRESSURE_PLATE: case E_BLOCK_YELLOW_FLOWER: { return true; } } return false; } bool cSandSimulator::IsReplacedOnRematerialization(BLOCKTYPE a_BlockType) { // Please keep the list alpha-sorted switch (a_BlockType) { case E_BLOCK_AIR: case E_BLOCK_CHORUS_FLOWER: case E_BLOCK_CHORUS_PLANT: case E_BLOCK_DEAD_BUSH: case E_BLOCK_FIRE: case E_BLOCK_LAVA: case E_BLOCK_SNOW: case E_BLOCK_STATIONARY_LAVA: case E_BLOCK_STATIONARY_WATER: case E_BLOCK_STRUCTURE_VOID: case E_BLOCK_TALL_GRASS: case E_BLOCK_WATER: { return true; } } return false; } bool cSandSimulator::DoesBreakFallingThrough(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) { switch (a_BlockType) { case E_BLOCK_PURPUR_SLAB: case E_BLOCK_RED_SANDSTONE_SLAB: case E_BLOCK_STONE_SLAB: case E_BLOCK_WOODEN_SLAB: { return ((a_BlockMeta & 0x08) == 0); // Only a bottom-slab breaks the block } } return false; } void cSandSimulator::FinishFalling( cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_FallingBlockType, NIBBLETYPE a_FallingBlockMeta ) { ASSERT(a_BlockY < cChunkDef::Height); BLOCKTYPE CurrentBlockType = a_World->GetBlock({ a_BlockX, a_BlockY, a_BlockZ }); if ((a_FallingBlockType == E_BLOCK_ANVIL) || IsReplacedOnRematerialization(CurrentBlockType)) { // Rematerialize the material here: a_World->SetBlock({ a_BlockX, a_BlockY, a_BlockZ }, a_FallingBlockType, a_FallingBlockMeta); if (a_FallingBlockType == E_BLOCK_ANVIL) { a_World->BroadcastSoundParticleEffect(EffectID::SFX_RANDOM_ANVIL_LAND, {a_BlockX, a_BlockY, a_BlockZ}, 0); } return; } // Create a pickup instead: cItems Pickups; Pickups.Add(static_cast(a_FallingBlockType), 1, a_FallingBlockMeta); a_World->SpawnItemPickups( Pickups, static_cast(a_BlockX) + 0.5, static_cast(a_BlockY) + 0.5, static_cast(a_BlockZ) + 0.5 ); } bool cSandSimulator::IsAllowedBlock(BLOCKTYPE a_BlockType) { switch (a_BlockType) { case E_BLOCK_ANVIL: case E_BLOCK_CONCRETE_POWDER: case E_BLOCK_DRAGON_EGG: case E_BLOCK_GRAVEL: case E_BLOCK_SAND: { return true; } default: { return false; } } } void cSandSimulator::DoInstantFall(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ) { // Remove the original block: BLOCKTYPE FallingBlockType; NIBBLETYPE FallingBlockMeta; a_Chunk->GetBlockTypeMeta(a_RelX, a_RelY, a_RelZ, FallingBlockType, FallingBlockMeta); a_Chunk->SetBlock({a_RelX, a_RelY, a_RelZ}, E_BLOCK_AIR, 0); // Search for a place to put it: for (int y = a_RelY - 1; y >= 0; y--) { BLOCKTYPE BlockType; NIBBLETYPE BlockMeta; a_Chunk->GetBlockTypeMeta(a_RelX, y, a_RelZ, BlockType, BlockMeta); int BlockY; if (DoesBreakFallingThrough(BlockType, BlockMeta)) { BlockY = y; } else if (!CanContinueFallThrough(BlockType)) { BlockY = y + 1; } else if ((FallingBlockType == E_BLOCK_CONCRETE_POWDER) && IsBlockWater(BlockType)) { FallingBlockType = E_BLOCK_CONCRETE; BlockY = y; } else { // Can fall further down continue; } // Finish the fall at the found bottom: int BlockX = a_RelX + a_Chunk->GetPosX() * cChunkDef::Width; int BlockZ = a_RelZ + a_Chunk->GetPosZ() * cChunkDef::Width; FinishFalling(&m_World, BlockX, BlockY, BlockZ, FallingBlockType, FallingBlockMeta); return; } // The block just "fell off the world" without leaving a trace } ================================================ FILE: src/Simulator/SandSimulator.h ================================================ #pragma once #include "Simulator.h" #include "../IniFile.h" // fwd: class cChunk; /** Per-chunk data for the simulator, specified individual chunks to simulate; Data is not used */ typedef cCoordWithIntList cSandSimulatorChunkData; /** Despite the class name, this simulator takes care of all blocks that fall when suspended in the air. */ class cSandSimulator : public cSimulator { public: cSandSimulator(cWorld & a_World, cIniFile & a_IniFile); /** Returns true if a falling-able block can start falling through the specified block type */ static bool CanStartFallingThrough(BLOCKTYPE a_BlockType); /** Returns true if an already-falling block can pass through the specified block type (e. g. torch) */ static bool CanContinueFallThrough(BLOCKTYPE a_BlockType); /** Returns true if the falling block rematerializing will replace the specified block type (e. g. tall grass) */ static bool IsReplacedOnRematerialization(BLOCKTYPE a_BlockType); /** Returns true if the specified block breaks falling blocks while they fall through it (e. g. halfslabs) */ static bool DoesBreakFallingThrough(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta); /** Called when a block finishes falling at the specified coords, either by insta-fall, or through cFallingBlock entity. It either rematerializes the block (a_FallingBlockType) at the specified coords, or creates a pickup, based on the block currently present in the world at the dest specified coords. */ static void FinishFalling( cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_FallingBlockType, NIBBLETYPE a_FallingBlockMeta ); static bool IsAllowedBlock(BLOCKTYPE a_BlockType); private: virtual void SimulateChunk(std::chrono::milliseconds a_Dt, int a_ChunkX, int a_ChunkZ, cChunk * a_Chunk) override; bool m_IsInstantFall; // If set to true, blocks don't fall using cFallingBlock entity, but instantly instead int m_TotalBlocks; // Total number of blocks currently in the queue for simulating virtual void AddBlock(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_Block) override; /** Performs the instant fall of the block - removes it from top, Finishes it at the bottom */ void DoInstantFall(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ); }; ================================================ FILE: src/Simulator/Simulator.cpp ================================================ #include "Globals.h" #include "Simulator.h" #include "../Chunk.h" #include "../World.h" std::array cSimulator::GetLinkedOffsets(const Vector3i Offset) { if (Offset.x == -1) { return { { { -2, 0, 0 }, { -1, -1, 0 }, { -1, 1, 0 }, { -1, 0, -1 }, { -1, 0, 1 } } }; } else if (Offset.x == 1) { return { { { 2, 0, 0 }, { 1, -1, 0 }, { 1, 1, 0 }, { 1, 0, -1 }, { 1, 0, 1 } } }; } else if (Offset.y == -1) { return { { { 0, -2, 0 }, { -1, -1, 0 }, { 1, -1, 0 }, { 0, -1, -1 }, { 0, -1, 1 } } }; } else if (Offset.y == 1) { return { { { 0, 2, 0 }, { -1, 1, 0 }, { 1, 1, 0 }, { 0, 1, -1 }, { 0, 1, 1 } } }; } else if (Offset.z == -1) { return { { { 0, 0, -2 }, { -1, 0, -1 }, { 1, 0, -1 }, { 0, -1, -1 }, { 0, 1, -1 } } }; } return { { { 0, 0, 2 }, { -1, 0, 1 }, { 1, 0, 1 }, { 0, -1, 1 }, { 0, 1, 1 } } }; } void cSimulator::Simulate(float a_Dt) { UNUSED(a_Dt); } void cSimulator::WakeUp(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_Block) { ASSERT(a_Chunk.IsValid()); AddBlock(a_Chunk, a_Position, a_Block); } void cSimulator::WakeUp(cChunk & a_Chunk, Vector3i a_Position, Vector3i a_Offset, BLOCKTYPE a_Block) { ASSERT(a_Chunk.IsValid()); WakeUp(a_Chunk, a_Position, a_Block); } ================================================ FILE: src/Simulator/Simulator.h ================================================ #pragma once #include "ChunkDef.h" class cWorld; class cChunk; class cCuboid; /** Base class for all block-based physics simulators (such as fluid, fire, falling blocks etc.). Each descendant provides an implementation of what needs to be done on each world tick. The descendant may choose to do all processing in a single call for the entire world (Simulate()) or do per-chunk calculations (SimulateChunk()). Whenever a block is changed, the WakeUp() functions are called to notify all simulators by the simulator manager. The functions are invoked to add all affected blocks and their direct neighbors using the AddBlock() function. The simulator may update its internal state based on this call. */ class cSimulator { public: cSimulator(cWorld & a_World) : m_World(a_World) { } virtual ~cSimulator() {} /** Contains offsets for direct adjacents of any position. */ static constexpr std::array AdjacentOffsets { { { 1, 0, 0 }, { -1, 0, 0 }, { 0, 1, 0 }, { 0, -1, 0 }, { 0, 0, 1 }, { 0, 0, -1 }, } }; /** For a given offset from a position, return the offsets that represent the adjacents of the newly offset position, excluding the old position. */ static std::array GetLinkedOffsets(Vector3i Offset); protected: friend class cChunk; // Calls AddBlock() in its WakeUpSimulators() function, to speed things up friend class cSimulatorManager; // Class reponsible for dispatching calls to the various slave Simulators virtual void Simulate(float a_Dt); virtual void SimulateChunk(std::chrono::milliseconds a_Dt, int a_ChunkX, int a_ChunkZ, cChunk * a_Chunk) = 0; /** Called to simulate a new block. Unlike WakeUp this function will perform minimal checking. It queues the block to be simulated as fast as possible, suitable for area wakeups. */ virtual void AddBlock(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_Block) = 0; /** Called to simulate a single new block, typically as a result of a single block break or change. The simulator implementation may decide to perform additional checks or maintain consistency of internal state before the block is added to the simulate queue. */ virtual void WakeUp(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_Block); /** Called to simulate a single block, synthesised by the simulator manager. The position represents the adjacents of the block that was actually changed, with the offset used given. Simulators may use this information to update additional blocks that were affected by the change, or queue farther, extra-adjacents blocks to be updated. The simulator manager calls this overload after the 3-argument WakeUp. */ virtual void WakeUp(cChunk & a_Chunk, Vector3i a_Position, Vector3i a_Offset, BLOCKTYPE a_Block); cWorld & m_World; } ; ================================================ FILE: src/Simulator/SimulatorManager.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "SimulatorManager.h" #include "../Chunk.h" #include "../Cuboid.h" #include "../World.h" cSimulatorManager::cSimulatorManager(cWorld & a_World) : m_World(a_World), m_Ticks(0) { } cSimulatorManager::~cSimulatorManager() { } void cSimulatorManager::Simulate(float a_Dt) { m_Ticks++; for (cSimulators::iterator itr = m_Simulators.begin(); itr != m_Simulators.end(); ++itr) { if ((m_Ticks % itr->second) == 0) { itr->first->Simulate(a_Dt); } } } void cSimulatorManager::SimulateChunk(std::chrono::milliseconds a_Dt, int a_ChunkX, int a_ChunkZ, cChunk * a_Chunk) { // m_Ticks has already been increased in Simulate() for (cSimulators::iterator itr = m_Simulators.begin(); itr != m_Simulators.end(); ++itr) { if ((m_Ticks % itr->second) == 0) { itr->first->SimulateChunk(a_Dt, a_ChunkX, a_ChunkZ, a_Chunk); } } } void cSimulatorManager::WakeUp(cChunk & a_Chunk, Vector3i a_Position) { ASSERT(a_Chunk.IsValid()); for (const auto & Item : m_Simulators) { Item.first->WakeUp(a_Chunk, a_Position, a_Chunk.GetBlock(a_Position)); } for (const auto & Offset : cSimulator::AdjacentOffsets) { auto Relative = a_Position + Offset; if (!cChunkDef::IsValidHeight(Relative)) { continue; } const auto Chunk = a_Chunk.GetRelNeighborChunkAdjustCoords(Relative); if ((Chunk == nullptr) || !Chunk->IsValid()) { continue; } // Stored block to give to simulators for performance // Since they all need this we save them querying it themselves const auto Block = Chunk->GetBlock(Relative); for (const auto & Item : m_Simulators) { Item.first->WakeUp(*Chunk, Relative, Offset, Block); } } } void cSimulatorManager::WakeUp(const cCuboid & a_Area) { cCuboid area(a_Area); area.Sort(); area.Expand(1, 1, 1, 1, 1, 1); // Expand the area to contain the neighbors, too. area.ClampY(0, cChunkDef::Height - 1); cChunkCoords ChunkStart = cChunkDef::BlockToChunk(area.p1); cChunkCoords ChunkEnd = cChunkDef::BlockToChunk(area.p2); // Add all blocks, in a per-chunk manner: for (int cz = ChunkStart.m_ChunkZ; cz <= ChunkEnd.m_ChunkZ; ++cz) { for (int cx = ChunkStart.m_ChunkX; cx <= ChunkEnd.m_ChunkX; ++cx) { m_World.DoWithChunk(cx, cz, [this, &area](cChunk & a_CBChunk) { int startX = std::max(area.p1.x, a_CBChunk.GetPosX() * cChunkDef::Width); int startZ = std::max(area.p1.z, a_CBChunk.GetPosZ() * cChunkDef::Width); int endX = std::min(area.p2.x, a_CBChunk.GetPosX() * cChunkDef::Width + cChunkDef::Width - 1); int endZ = std::min(area.p2.z, a_CBChunk.GetPosZ() * cChunkDef::Width + cChunkDef::Width - 1); for (const auto & Item : m_Simulators) { const auto Simulator = Item.first; for (int y = area.p1.y; y <= area.p2.y; ++y) { for (int z = startZ; z <= endZ; ++z) { for (int x = startX; x <= endX; ++x) { const auto Position = cChunkDef::AbsoluteToRelative({ x, y, z }); Simulator->WakeUp(a_CBChunk, Position, a_CBChunk.GetBlock(Position)); } // for x } // for z } // for y } return true; }); } // for cx } // for cz } void cSimulatorManager::RegisterSimulator(cSimulator * a_Simulator, int a_Rate) { m_Simulators.push_back(std::make_pair(a_Simulator, a_Rate)); } ================================================ FILE: src/Simulator/SimulatorManager.h ================================================ // cSimulatorManager.h #pragma once #include "Simulator.h" // fwd: Chunk.h class cChunk; // fwd: World.h class cWorld; class cSimulatorManager { public: cSimulatorManager(cWorld & a_World); ~cSimulatorManager(); /** Called in each tick, a_Dt is the time passed since the last tick, in msec. */ void Simulate(float a_Dt); /** Called in each tick for each chunk, a_Dt is the time passed since the last tick, in msec; direct access to chunk data available. */ void SimulateChunk(std::chrono::milliseconds a_DT, int a_ChunkX, int a_ChunkZ, cChunk * a_Chunk); /* Called when a single block changes, wakes all simulators up for the block and its face-neighbors. The simulator implementation may also decide to wake blocks farther away. */ void WakeUp(cChunk & a_Chunk, Vector3i a_Position); /** Does the same processing as WakeUp, but for all blocks within the specified area. Has better performance than calling WakeUp for each block individually, due to neighbor-checking. All chunks intersected by the area should be valid (outputs a warning if not). Note that, unlike WakeUp(), this call adds blocks not only face-neighboring, but also edge-neighboring and corner-neighboring the specified area. */ void WakeUp(const cCuboid & a_Area); void RegisterSimulator(cSimulator * a_Simulator, int a_Rate); // Takes ownership of the simulator object! protected: typedef std::vector > cSimulators; cWorld & m_World; cSimulators m_Simulators; long long m_Ticks; }; ================================================ FILE: src/Simulator/VanillaFluidSimulator.cpp ================================================ // VanillaFluidSimulator.cpp #include "Globals.h" #include "VanillaFluidSimulator.h" #include "../BlockInfo.h" #include "../World.h" #include "../Chunk.h" #include "../BlockArea.h" #include "../Blocks/BlockHandler.h" #include "../BlockInServerPluginInterface.h" static const int InfiniteCost = 100; cVanillaFluidSimulator::cVanillaFluidSimulator( cWorld & a_World, BLOCKTYPE a_Fluid, BLOCKTYPE a_StationaryFluid, NIBBLETYPE a_Falloff, int a_TickDelay, int a_NumNeighborsForSource ): Super(a_World, a_Fluid, a_StationaryFluid, a_Falloff, a_TickDelay, a_NumNeighborsForSource) { } void cVanillaFluidSimulator::SpreadXZ(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_NewMeta) { // Calculate the distance to the nearest "hole" in each direction: int Cost[4]; Cost[0] = CalculateFlowCost(a_Chunk, a_RelX + 1, a_RelY, a_RelZ, X_PLUS); Cost[1] = CalculateFlowCost(a_Chunk, a_RelX - 1, a_RelY, a_RelZ, X_MINUS); Cost[2] = CalculateFlowCost(a_Chunk, a_RelX, a_RelY, a_RelZ + 1, Z_PLUS); Cost[3] = CalculateFlowCost(a_Chunk, a_RelX, a_RelY, a_RelZ - 1, Z_MINUS); // Find the minimum distance: int MinCost = InfiniteCost; for (unsigned int i = 0; i < ARRAYCOUNT(Cost); ++i) { if (Cost[i] < MinCost) { MinCost = Cost[i]; } } // Spread in all directions where the distance matches the minimum: if (Cost[0] == MinCost) { SpreadToNeighbor(a_Chunk, a_RelX + 1, a_RelY, a_RelZ, a_NewMeta); } if (Cost[1] == MinCost) { SpreadToNeighbor(a_Chunk, a_RelX - 1, a_RelY, a_RelZ, a_NewMeta); } if (Cost[2] == MinCost) { SpreadToNeighbor(a_Chunk, a_RelX, a_RelY, a_RelZ + 1, a_NewMeta); } if (Cost[3] == MinCost) { SpreadToNeighbor(a_Chunk, a_RelX, a_RelY, a_RelZ - 1, a_NewMeta); } } int cVanillaFluidSimulator::CalculateFlowCost(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ, Direction a_Dir, unsigned a_Iteration) { int Cost = InfiniteCost; BLOCKTYPE BlockType; NIBBLETYPE BlockMeta; // Check if block is passable if (!a_Chunk->UnboundedRelGetBlock(a_RelX, a_RelY, a_RelZ, BlockType, BlockMeta)) { return Cost; } if ( !IsPassableForFluid(BlockType) || // The block cannot be passed by the liquid ... (IsAllowedBlock(BlockType) && (BlockMeta == 0)) // ... or if it is liquid, it is a source block ) { return Cost; } // Check if block below is passable if ((a_RelY > 0) && !a_Chunk->UnboundedRelGetBlock(a_RelX, a_RelY - 1, a_RelZ, BlockType, BlockMeta)) { return Cost; } if (IsPassableForFluid(BlockType) || IsBlockLiquid(BlockType)) { // Path found, exit return static_cast(a_Iteration); } // 5 blocks away, bail out if (a_Iteration > 3) { return Cost; } // Recurse if (a_Dir != X_MINUS) { int NextCost = CalculateFlowCost(a_Chunk, a_RelX + 1, a_RelY, a_RelZ, X_PLUS, a_Iteration + 1); if (NextCost < Cost) { Cost = NextCost; } } if (a_Dir != X_PLUS) { int NextCost = CalculateFlowCost(a_Chunk, a_RelX - 1, a_RelY, a_RelZ, X_MINUS, a_Iteration + 1); if (NextCost < Cost) { Cost = NextCost; } } if (a_Dir != Z_MINUS) { int NextCost = CalculateFlowCost(a_Chunk, a_RelX, a_RelY, a_RelZ + 1, Z_PLUS, a_Iteration + 1); if (NextCost < Cost) { Cost = NextCost; } } if (a_Dir != Z_PLUS) { int NextCost = CalculateFlowCost(a_Chunk, a_RelX, a_RelY, a_RelZ - 1, Z_MINUS, a_Iteration + 1); if (NextCost < Cost) { Cost = NextCost; } } return Cost; } ================================================ FILE: src/Simulator/VanillaFluidSimulator.h ================================================ // VanillaFluidSimulator.h #pragma once #include "FloodyFluidSimulator.h" class cVanillaFluidSimulator: public cFloodyFluidSimulator { using Super = cFloodyFluidSimulator; public: cVanillaFluidSimulator( cWorld & a_World, BLOCKTYPE a_Fluid, BLOCKTYPE a_StationaryFluid, NIBBLETYPE a_Falloff, int a_TickDelay, int a_NumNeighborsForSource ); protected: // cFloodyFluidSimulator overrides: virtual void SpreadXZ(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_NewMeta) override; /** Recursively calculates the minimum number of blocks needed to descend a level. */ int CalculateFlowCost(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ, Direction a_Dir, unsigned a_Iteration = 0); } ; ================================================ FILE: src/Simulator/VaporizeFluidSimulator.cpp ================================================ // VaporizeFluidSimulator.cpp // Implements the cVaporizeFluidSimulator class representing a fluid simulator that replaces all fluid blocks with air #include "Globals.h" #include "VaporizeFluidSimulator.h" #include "BlockType.h" #include "../OpaqueWorld.h" #include "../Chunk.h" #include "../Blocks/BroadcastInterface.h" void cVaporizeFluidSimulator::SimulateChunk(std::chrono::milliseconds a_Dt, int a_ChunkX, int a_ChunkZ, cChunk * a_Chunk) { // Nothing needed UNUSED(a_Dt); UNUSED(a_ChunkX); UNUSED(a_ChunkZ); UNUSED(a_Chunk); } void cVaporizeFluidSimulator::AddBlock(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_Block) { if ((a_Block == m_FluidBlock) || (a_Block == m_StationaryFluidBlock)) { a_Chunk.FastSetBlock(a_Position, E_BLOCK_AIR, 0); World::GetBroadcastInterface(m_World).BroadcastSoundEffect( "block.fire.extinguish", Vector3d(a_Position), 1.0f, 0.6f ); } } ================================================ FILE: src/Simulator/VaporizeFluidSimulator.h ================================================ // VaporizeFluidSimulator.h // Declares the cVaporizeFluidSimulator class representing a fluid simulator that replaces all fluid blocks with air // Useful for water simulation in the Nether #pragma once #include "FluidSimulator.h" class cVaporizeFluidSimulator: public cFluidSimulator { using Super = cFluidSimulator; public: using Super::Super; private: virtual void SimulateChunk(std::chrono::milliseconds a_Dt, int a_ChunkX, int a_ChunkZ, cChunk * a_Chunk) override; virtual void AddBlock(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_Block) override; virtual cFluidSimulatorData * CreateChunkData(void) override { return nullptr; } } ; ================================================ FILE: src/SpawnPrepare.cpp ================================================ #include "Globals.h" #include "SpawnPrepare.h" #include "World.h" class cSpawnPrepareCallback : public cChunkCoordCallback { public: cSpawnPrepareCallback(std::shared_ptr a_SpawnPrepare) : m_SpawnPrepare(std::move(a_SpawnPrepare)) { ASSERT(m_SpawnPrepare != nullptr); } protected: std::shared_ptr m_SpawnPrepare; virtual void Call(cChunkCoords a_Coords, bool a_IsSuccess) override { m_SpawnPrepare->PreparedChunkCallback(a_Coords.m_ChunkX, a_Coords.m_ChunkZ); } }; cSpawnPrepare::cSpawnPrepare(cWorld & a_World, int a_SpawnChunkX, int a_SpawnChunkZ, int a_PrepareDistance, int a_FirstIdx, sMakeSharedTag): m_World(a_World), m_SpawnChunkX(a_SpawnChunkX), m_SpawnChunkZ(a_SpawnChunkZ), m_PrepareDistance(a_PrepareDistance), m_NextIdx(a_FirstIdx), m_MaxIdx(a_PrepareDistance * a_PrepareDistance), m_NumPrepared(0), m_LastReportTime(std::chrono::steady_clock::now()), m_LastReportChunkCount(0) { } void cSpawnPrepare::PrepareChunks(cWorld & a_World, int a_SpawnChunkX, int a_SpawnChunkZ, int a_PrepareDistance) { // Queue the initial chunks: int MaxIdx = a_PrepareDistance * a_PrepareDistance; int maxQueue = std::min(MaxIdx - 1, 100); // Number of chunks to queue at once auto prep = std::make_shared(a_World, a_SpawnChunkX, a_SpawnChunkZ, a_PrepareDistance, maxQueue, sMakeSharedTag{}); for (int i = 0; i < maxQueue; i++) { int chunkX, chunkZ; prep->DecodeChunkCoords(i, chunkX, chunkZ); a_World.PrepareChunk(chunkX, chunkZ, std::make_unique(prep)); } // for i // Wait for the lighting thread to prepare everything. Event is set in the Call() callback: if (MaxIdx > 0) { prep->m_EvtFinished.Wait(); } } void cSpawnPrepare::DecodeChunkCoords(int a_Idx, int & a_ChunkX, int & a_ChunkZ) { // A zigzag pattern from the top to bottom, each row alternating between forward-x and backward-x: int z = a_Idx / m_PrepareDistance; int x = a_Idx % m_PrepareDistance; if ((z & 1) == 0) { // Reverse every second row: x = m_PrepareDistance - 1 - x; } a_ChunkZ = m_SpawnChunkZ + z - m_PrepareDistance / 2; a_ChunkX = m_SpawnChunkX + x - m_PrepareDistance / 2; } void cSpawnPrepare::PreparedChunkCallback(int a_ChunkX, int a_ChunkZ) { // Check if this was the last chunk: m_NumPrepared += 1; if (m_NumPrepared >= m_MaxIdx) { m_EvtFinished.Set(); // Must return here, because "this" may have gotten deleted by the previous line return; } // Queue another chunk, if appropriate: if (m_NextIdx < m_MaxIdx) { int chunkX, chunkZ; DecodeChunkCoords(m_NextIdx, chunkX, chunkZ); m_World.GetLightingThread().QueueChunk(chunkX, chunkZ, std::make_unique(shared_from_this())); m_NextIdx += 1; } // Report progress every 1 second: auto Now = std::chrono::steady_clock::now(); if (Now - m_LastReportTime > std::chrono::seconds(1)) { float PercentDone = static_cast(m_NumPrepared * 100) / m_MaxIdx; float ChunkSpeed = static_cast((m_NumPrepared - m_LastReportChunkCount) * 1000) / std::chrono::duration_cast(Now - m_LastReportTime).count(); LOG("Preparing spawn (%s): %.02f%% (%d/%d; %.02f chunks / sec)", m_World.GetName().c_str(), PercentDone, m_NumPrepared.load(std::memory_order_seq_cst), m_MaxIdx, ChunkSpeed ); m_LastReportTime = Now; m_LastReportChunkCount = m_NumPrepared; } } ================================================ FILE: src/SpawnPrepare.h ================================================ #pragma once #include "ChunkDef.h" class cWorld; /** Generates and lights the spawn area of the world. Runs as a separate thread. */ class cSpawnPrepare: public std::enable_shared_from_this { /** Private tag allows public constructors that can only be used with private access. */ struct sMakeSharedTag {}; public: cSpawnPrepare(cWorld & a_World, int a_SpawnChunkX, int a_SpawnChunkZ, int a_PrepareDistance, int a_FirstIdx, sMakeSharedTag); static void PrepareChunks(cWorld & a_World, int a_SpawnChunkX, int a_SpawnChunkZ, int a_PrepareDistance); static void PrepareChunks(cWorld & a_World, cChunkCoords a_SpawnChunk, int a_PrepareDistance) { PrepareChunks(a_World, a_SpawnChunk.m_ChunkX, a_SpawnChunk.m_ChunkZ, a_PrepareDistance); } protected: cWorld & m_World; int m_SpawnChunkX; int m_SpawnChunkZ; int m_PrepareDistance; /** The index of the next chunk to be queued in the lighting thread. */ int m_NextIdx; /** The maximum index of the prepared chunks. Queueing stops when m_NextIdx reaches this number. */ int m_MaxIdx; /** Total number of chunks already finished preparing. Preparation finishes when this number reaches m_MaxIdx. */ std::atomic m_NumPrepared; /** Event used to signal that the preparation is finished. */ cEvent m_EvtFinished; /** The timestamp of the last progress report emitted. */ std::chrono::steady_clock::time_point m_LastReportTime; /** Number of chunks prepared when the last progress report was emitted. */ int m_LastReportChunkCount; void PreparedChunkCallback(int a_ChunkX, int a_ChunkZ); /** Decodes the index into chunk coords. Provides the specific chunk ordering. */ void DecodeChunkCoords(int a_Idx, int & a_ChunkX, int & a_ChunkZ); friend class cSpawnPrepareCallback; }; ================================================ FILE: src/StatisticsManager.cpp ================================================ // Statistics.cpp #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "StatisticsManager.h" bool StatisticsManager::SatisfiesPrerequisite(const CustomStatistic a_Stat) const { switch (a_Stat) { case CustomStatistic::AchOpenInventory: return true; case CustomStatistic::AchMineWood: return IsStatisticPresent(CustomStatistic::AchOpenInventory); case CustomStatistic::AchBuildWorkBench: return IsStatisticPresent(CustomStatistic::AchMineWood); case CustomStatistic::AchBuildHoe: return IsStatisticPresent(CustomStatistic::AchBuildWorkBench); case CustomStatistic::AchBakeCake: return IsStatisticPresent(CustomStatistic::AchBuildHoe); case CustomStatistic::AchMakeBread: return IsStatisticPresent(CustomStatistic::AchBuildHoe); case CustomStatistic::AchBuildSword: return IsStatisticPresent(CustomStatistic::AchBuildWorkBench); case CustomStatistic::AchKillCow: return IsStatisticPresent(CustomStatistic::AchBuildSword); case CustomStatistic::AchFlyPig: return IsStatisticPresent(CustomStatistic::AchKillCow); case CustomStatistic::AchBreedCow: return IsStatisticPresent(CustomStatistic::AchKillCow); case CustomStatistic::AchKillEnemy: return IsStatisticPresent(CustomStatistic::AchBuildSword); case CustomStatistic::AchSnipeSkeleton: return IsStatisticPresent(CustomStatistic::AchKillEnemy); case CustomStatistic::AchBuildPickaxe: return IsStatisticPresent(CustomStatistic::AchBuildWorkBench); case CustomStatistic::AchBuildBetterPickaxe: return IsStatisticPresent(CustomStatistic::AchBuildPickaxe); case CustomStatistic::AchBuildFurnace: return IsStatisticPresent(CustomStatistic::AchBuildWorkBench); case CustomStatistic::AchCookFish: return IsStatisticPresent(CustomStatistic::AchBuildFurnace); case CustomStatistic::AchAcquireIron: return IsStatisticPresent(CustomStatistic::AchBuildFurnace); case CustomStatistic::AchOnARail: return IsStatisticPresent(CustomStatistic::AchAcquireIron); case CustomStatistic::AchDiamonds: return IsStatisticPresent(CustomStatistic::AchAcquireIron); case CustomStatistic::AchPortal: return IsStatisticPresent(CustomStatistic::AchDiamonds); case CustomStatistic::AchGhast: return IsStatisticPresent(CustomStatistic::AchPortal); case CustomStatistic::AchBlazeRod: return IsStatisticPresent(CustomStatistic::AchPortal); case CustomStatistic::AchPotion: return IsStatisticPresent(CustomStatistic::AchBlazeRod); case CustomStatistic::AchTheEnd: return IsStatisticPresent(CustomStatistic::AchBlazeRod); case CustomStatistic::AchTheEnd2: return IsStatisticPresent(CustomStatistic::AchTheEnd); case CustomStatistic::AchEnchantments: return IsStatisticPresent(CustomStatistic::AchDiamonds); case CustomStatistic::AchOverkill: return IsStatisticPresent(CustomStatistic::AchEnchantments); case CustomStatistic::AchBookcase: return IsStatisticPresent(CustomStatistic::AchEnchantments); case CustomStatistic::AchExploreAllBiomes: return IsStatisticPresent(CustomStatistic::AchTheEnd); case CustomStatistic::AchSpawnWither: return IsStatisticPresent(CustomStatistic::AchTheEnd2); case CustomStatistic::AchKillWither: return IsStatisticPresent(CustomStatistic::AchSpawnWither); case CustomStatistic::AchFullBeacon: return IsStatisticPresent(CustomStatistic::AchKillWither); case CustomStatistic::AchDiamondsToYou: return IsStatisticPresent(CustomStatistic::AchDiamonds); default: UNREACHABLE("Unsupported achievement type"); } } bool StatisticsManager::IsStatisticPresent(const CustomStatistic a_Stat) const { const auto Result = Custom.find(a_Stat); if (Result != Custom.end()) { return Result->second > 0; } return false; } ================================================ FILE: src/StatisticsManager.h ================================================ // Statistics.h /* Hello fellow developer ! In case you are trying to add new statistics to Cuberite you need to do a few things: --------------------------------------------------------------------------- 1. add a new entry to the enum class Statistic in Registries\Statistics.h file 2. add this to serialization functions in WorldStorage\NamespaceSerializer.cpp The String in the above is used for saving on disk! so use the same string! In case you want to add a mapping of network IDs to the used stats you will find a lua script in ../Tools/BlockTypePaletteGenerator/ExportStatMapping.lua it will provide you with information how to use it. you need a registries.json exported from the server https://wiki.vg/Data_Generators Greetings 12xx12 */ #pragma once #include "Registries/CustomStatistics.h" /** Class that manages the statistics and achievements of a single player. */ struct StatisticsManager { typedef unsigned StatValue; // TODO: Block tallies, entities killed, all the others std::unordered_map Custom; /** Returns whether the prerequisite for awarding an achievement are satisfied. */ bool SatisfiesPrerequisite(CustomStatistic a_Stat) const; private: /** Returns if a statistic is both present and has nonzero value. */ bool IsStatisticPresent(CustomStatistic a_Stat) const; }; ================================================ FILE: src/StringCompression.cpp ================================================ // StringCompression.cpp // Implements the wrapping functions for compression and decompression #include "Globals.h" #include "ByteBuffer.h" #include "StringCompression.h" #include std::string_view Compression::Result::GetStringView() const { const auto View = GetView(); return { reinterpret_cast(View.data()), View.size() }; } ContiguousByteBufferView Compression::Result::GetView() const { // Get a generic std::byte * to what the variant is currently storing: return { std::visit([](const auto & Buffer) -> const std::byte * { using Variant = std::decay_t; if constexpr (std::is_same_v) { return Buffer.data(); } else { return Buffer.get(); } }, Storage), Size }; } Compression::Compressor::Compressor(int CompressionFactor) { m_Handle = libdeflate_alloc_compressor(CompressionFactor); if (m_Handle == nullptr) { throw std::bad_alloc(); } } Compression::Compressor::~Compressor() { libdeflate_free_compressor(m_Handle); } template Compression::Result Compression::Compressor::Compress(const void * const Input, const size_t Size) { // First see if the stack buffer has enough space: { Result::Static Buffer; const auto BytesWrittenOut = Algorithm(m_Handle, Input, Size, Buffer.data(), Buffer.size()); if (BytesWrittenOut != 0) { return { Buffer, BytesWrittenOut }; } } // No it doesn't. Allocate space on the heap to write the compression result, increasing in powers of 2. // This will either succeed, or except with bad_alloc. auto DynamicCapacity = Result::StaticCapacity * 2; while (true) { auto Dynamic = cpp20::make_unique_for_overwrite(DynamicCapacity); const auto BytesWrittenOut = Algorithm(m_Handle, Input, Size, Dynamic.get(), DynamicCapacity); if (BytesWrittenOut != 0) { return { std::move(Dynamic), BytesWrittenOut }; } DynamicCapacity *= 2; } } Compression::Result Compression::Compressor::CompressGZip(const ContiguousByteBufferView Input) { return Compress<&libdeflate_gzip_compress>(Input.data(), Input.size()); } Compression::Result Compression::Compressor::CompressZLib(const ContiguousByteBufferView Input) { return Compress<&libdeflate_zlib_compress>(Input.data(), Input.size()); } Compression::Result Compression::Compressor::CompressZLib(const void * const Input, const size_t Size) { return Compress<&libdeflate_zlib_compress>(Input, Size); } Compression::Extractor::Extractor() { m_Handle = libdeflate_alloc_decompressor(); if (m_Handle == nullptr) { throw std::bad_alloc(); } } Compression::Extractor::~Extractor() { libdeflate_free_decompressor(m_Handle); } Compression::Result Compression::Extractor::ExtractGZip(ContiguousByteBufferView Input) { return Extract<&libdeflate_gzip_decompress>(Input); } Compression::Result Compression::Extractor::ExtractZLib(ContiguousByteBufferView Input) { return Extract<&libdeflate_zlib_decompress>(Input); } Compression::Result Compression::Extractor::ExtractZLib(ContiguousByteBufferView Input, size_t UncompressedSize) { return Extract<&libdeflate_zlib_decompress>(Input, UncompressedSize); } template Compression::Result Compression::Extractor::Extract(const ContiguousByteBufferView Input) { // First see if the stack buffer has enough space: { Result::Static Buffer; size_t BytesWrittenOut; switch (Algorithm(m_Handle, Input.data(), Input.size(), Buffer.data(), Buffer.size(), &BytesWrittenOut)) { case LIBDEFLATE_SUCCESS: return { Buffer, BytesWrittenOut }; case LIBDEFLATE_INSUFFICIENT_SPACE: break; default: throw std::runtime_error("Data extraction failed."); } } // No it doesn't. Allocate space on the heap to write the compression result, increasing in powers of 2. auto DynamicCapacity = Result::StaticCapacity * 2; while (true) { size_t BytesWrittenOut; auto Dynamic = cpp20::make_unique_for_overwrite(DynamicCapacity); switch (Algorithm(m_Handle, Input.data(), Input.size(), Dynamic.get(), DynamicCapacity, &BytesWrittenOut)) { case libdeflate_result::LIBDEFLATE_SUCCESS: return { std::move(Dynamic), BytesWrittenOut }; case libdeflate_result::LIBDEFLATE_INSUFFICIENT_SPACE: { DynamicCapacity *= 2; continue; } default: throw std::runtime_error("Data extraction failed."); } } } template Compression::Result Compression::Extractor::Extract(const ContiguousByteBufferView Input, size_t UncompressedSize) { // Here we have the expected size after extraction, so directly use a suitable buffer size: if (UncompressedSize <= Result::StaticCapacity) { if ( Result::Static Buffer; Algorithm(m_Handle, Input.data(), Input.size(), Buffer.data(), UncompressedSize, nullptr) == libdeflate_result::LIBDEFLATE_SUCCESS ) { return { Buffer, UncompressedSize }; } } else if ( auto Dynamic = cpp20::make_unique_for_overwrite(UncompressedSize); Algorithm(m_Handle, Input.data(), Input.size(), Dynamic.get(), UncompressedSize, nullptr) == libdeflate_result::LIBDEFLATE_SUCCESS ) { return { std::move(Dynamic), UncompressedSize }; } throw std::runtime_error("Data extraction failed."); } ================================================ FILE: src/StringCompression.h ================================================ // StringCompression.h // Interfaces to the wrapping functions for compression and decompression #pragma once struct libdeflate_compressor; struct libdeflate_decompressor; namespace Compression { /** Contains the result of a compression or extraction operation. */ struct Result { using Static = std::array; using Dynamic = std::unique_ptr; static constexpr size_t StaticCapacity = sizeof(Compression::Result::Static) / sizeof(Compression::Result::Static::value_type); /** Returns a view (of type char) of the internal store. */ std::string_view GetStringView() const; /** Returns a view (of type std::byte) of the internal store. */ ContiguousByteBufferView GetView() const; /** A store allocated on either the stack or heap. */ std::variant Storage; /** The length of valid data in the store. */ size_t Size; }; /** Contains routines for data compression. */ class Compressor { public: /** Creates a new compressor instance with a compression factor [0-12]. */ Compressor(int CompressionFactor = 6); ~Compressor(); Result CompressGZip(ContiguousByteBufferView Input); Result CompressZLib(ContiguousByteBufferView Input); Result CompressZLib(const void * Input, size_t Size); private: template Result Compress(const void * Input, size_t Size); libdeflate_compressor * m_Handle; }; /** Contains routines for data extraction. */ class Extractor { public: /** Creates a new extractor instance. */ Extractor(); ~Extractor(); Result ExtractGZip(ContiguousByteBufferView Input); Result ExtractZLib(ContiguousByteBufferView Input); Result ExtractZLib(ContiguousByteBufferView Input, size_t UncompressedSize); private: template Result Extract(ContiguousByteBufferView Input); template Result Extract(ContiguousByteBufferView Input, size_t UncompressedSize); libdeflate_decompressor * m_Handle; }; } ================================================ FILE: src/StringUtils.cpp ================================================ // StringUtils.cpp // Implements the various string helper functions: #include "Globals.h" #include "Endianness.h" #include "fmt/printf.h" /** Returns the value of the single hex digit. Returns 0xff on failure. */ static unsigned char HexToDec(char a_HexChar) { switch (a_HexChar) { case '0': return 0; case '1': return 1; case '2': return 2; case '3': return 3; case '4': return 4; case '5': return 5; case '6': return 6; case '7': return 7; case '8': return 8; case '9': return 9; case 'a': return 10; case 'b': return 11; case 'c': return 12; case 'd': return 13; case 'e': return 14; case 'f': return 15; case 'A': return 10; case 'B': return 11; case 'C': return 12; case 'D': return 13; case 'E': return 14; case 'F': return 15; } return 0xff; } AStringVector StringSplit(const AString & str, const AString & delim) { AStringVector results; size_t cutAt = 0; size_t Prev = 0; while ((cutAt = str.find_first_of(delim, Prev)) != str.npos) { results.push_back(str.substr(Prev, cutAt - Prev)); Prev = cutAt + 1; } if (Prev < str.length()) { results.push_back(str.substr(Prev)); } return results; } AStringVector StringSplitWithQuotes(const AString & str, const AString & delim) { AStringVector results; size_t cutAt = 0; size_t Prev = 0; size_t cutAtQuote = 0; while ((cutAt = str.find_first_of(delim, Prev)) != str.npos) { if (cutAt == Prev) { // Empty string due to multiple whitespace / whitespace at the beginning of the input // Just skip it Prev = Prev + 1; continue; } AString current = str.substr(Prev, cutAt - Prev); if ((current.front() == '"') || (current.front() == '\'')) { Prev += 1; cutAtQuote = str.find_first_of(current.front(), Prev); if (cutAtQuote != str.npos) { current = str.substr(Prev, cutAtQuote - Prev); cutAt = cutAtQuote + 1; } } results.push_back(std::move(current)); Prev = cutAt + 1; } if (Prev < str.length()) { AString current = str.substr(Prev); // If the remant is wrapped in matching quotes, remove them: if ( (current.length() >= 2) && ((current.front() == '"') || (current.front() == '\'')) && (current.front() == current.back()) ) { current = current.substr(1, current.length() - 2); } results.push_back(current); } return results; } AString StringJoin(const AStringVector & a_Strings, const AString & a_Delimeter) { if (a_Strings.empty()) { return {}; } // Do a dry run to gather the size const auto DelimSize = a_Delimeter.size(); size_t ResultSize = a_Strings[0].size(); std::for_each(a_Strings.begin() + 1, a_Strings.end(), [&](const AString & a_String) { ResultSize += DelimSize; ResultSize += a_String.size(); } ); // Now do the actual join AString Result; Result.reserve(ResultSize); Result.append(a_Strings[0]); std::for_each(a_Strings.begin() + 1, a_Strings.end(), [&](const AString & a_String) { Result += a_Delimeter; Result += a_String; } ); return Result; } AStringVector StringSplitAndTrim(const AString & str, const AString & delim) { AStringVector results; size_t cutAt = 0; size_t Prev = 0; while ((cutAt = str.find_first_of(delim, Prev)) != str.npos) { results.push_back(TrimString(str.substr(Prev, cutAt - Prev))); Prev = cutAt + 1; } if (Prev < str.length()) { results.push_back(TrimString(str.substr(Prev))); } return results; } AString TrimString(const AString & str) { size_t len = str.length(); size_t start = 0; while (start < len) { if (static_cast(str[start]) > 32) { break; } ++start; } if (start == len) { return ""; } size_t end = len; while (end >= start) { if (static_cast(str[end]) > 32) { break; } --end; } return str.substr(start, end - start + 1); } AString & InPlaceLowercase(AString & s) { std::transform(s.begin(), s.end(), s.begin(), ::tolower); return s; } AString & InPlaceUppercase(AString & s) { std::transform(s.begin(), s.end(), s.begin(), ::toupper); return s; } AString StrToLower(const AString & s) { AString res; res.resize(s.size()); std::transform(s.begin(), s.end(), res.begin(), ::tolower); return res; } AString StrToUpper(const AString & s) { AString res; res.resize(s.size()); std::transform(s.begin(), s.end(), res.begin(), ::toupper); return res; } int NoCaseCompare(const AString & s1, const AString & s2) { #ifdef _MSC_VER return _stricmp(s1.c_str(), s2.c_str()); #else return strcasecmp(s1.c_str(), s2.c_str()); #endif // else _MSC_VER } size_t RateCompareString(const AString & s1, const AString & s2) { size_t MatchedLetters = 0; size_t s1Length = s1.length(); if (s1Length > s2.length()) { // Definitely not a match return 0; } for (size_t i = 0; i < s1Length; i++) { char c1 = static_cast(toupper(s1[i])); char c2 = static_cast(toupper(s2[i])); if (c1 == c2) { ++MatchedLetters; } else { break; } } return MatchedLetters; } void ReplaceString(AString & iHayStack, const AString & iNeedle, const AString & iReplaceWith) { // find always returns the current position for an empty needle; prevent endless loop if (iNeedle.empty()) { return; } size_t pos1 = iHayStack.find(iNeedle); while (pos1 != AString::npos) { iHayStack.replace( pos1, iNeedle.size(), iReplaceWith); pos1 = iHayStack.find(iNeedle, pos1 + iReplaceWith.size()); } } void ReplaceURL(AString & iHayStack, const AString & iNeedle, const AString & iReplaceWith) { auto ReplaceWith = URLEncode(iReplaceWith); ReplaceString(iHayStack, iNeedle, ReplaceWith); } AString & RawBEUTF16ToUTF8(const char * a_RawData, size_t a_NumShorts, AString & a_UTF8) { a_UTF8.clear(); a_UTF8.reserve(3 * a_NumShorts / 2); // a quick guess of the resulting size for (size_t i = 0; i < a_NumShorts; i++) { auto UTF16 = NetworkBufToHost(reinterpret_cast(&a_RawData[i * 2])); a_UTF8.append(UnicodeCharToUtf8(UTF16)); } return a_UTF8; } AString UnicodeCharToUtf8(unsigned a_UnicodeChar) { if (a_UnicodeChar < 0x80) { return AString{static_cast(a_UnicodeChar)}; } else if (a_UnicodeChar < 0x800) { return AString { static_cast(192 + a_UnicodeChar / 64), static_cast(128 + a_UnicodeChar % 64), }; } else if (a_UnicodeChar - 0xd800 < 0x800) { // Error return AString(); } else if (a_UnicodeChar < 0x10000) { return AString { static_cast(224 + a_UnicodeChar / 4096), static_cast(128 + (a_UnicodeChar / 64) % 64), static_cast(128 + a_UnicodeChar % 64) }; } else if (a_UnicodeChar < 0x110000) { return AString { static_cast(240 + a_UnicodeChar / 262144), static_cast(128 + (a_UnicodeChar / 4096) % 64), static_cast(128 + (a_UnicodeChar / 64) % 64), static_cast(128 + a_UnicodeChar % 64), }; } else { // Error return AString(); } } #ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wimplicit-fallthrough" #endif // UTF-8 conversion code adapted from: // https://stackoverflow.com/questions/2867123/convert-utf-16-to-utf-8-under-windows-and-linux-in-c //////////////////////////////////////////////////////////////////////////////// // Begin of Unicode, Inc.'s code / information //////////////////////////////////////////////////////////////////////////////// /* Notice from the original file: * Copyright 2001-2004 Unicode, Inc. * * Disclaimer * * This source code is provided as is by Unicode, Inc. No claims are * made as to fitness for any particular purpose. No warranties of any * kind are expressed or implied. The recipient agrees to determine * applicability of information provided. If this file has been * purchased on magnetic or optical media from Unicode, Inc., the * sole remedy for any claim will be exchange of defective media * within 90 days of receipt. * * Limitations on Rights to Redistribute This Code * * Unicode, Inc. hereby grants the right to freely use the information * supplied in this file in the creation of products supporting the * Unicode Standard, and to make copies of this file in any form * for internal or external distribution as long as this notice * remains attached. */ #define UNI_MAX_BMP 0x0000FFFF #define UNI_MAX_UTF16 0x0010FFFF #define UNI_SUR_HIGH_START 0xD800 #define UNI_SUR_LOW_START 0xDC00 #define UNI_SUR_LOW_END 0xDFFF static const Byte trailingBytesForUTF8[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5 }; static const unsigned int offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL, 0x03C82080UL, 0xFA082080UL, 0x82082080UL }; static bool isLegalUTF8(const unsigned char * source, int length) { unsigned char a; const unsigned char * srcptr = source + length; switch (length) { default: return false; // Everything else falls through when "true"... case 4: if (((a = (*--srcptr)) < 0x80) || (a > 0xbf)) return false; case 3: if (((a = (*--srcptr)) < 0x80) || (a > 0xbf)) return false; case 2: { if ((a = (*--srcptr)) > 0xbf) { return false; } switch (*source) { // no fall-through in this inner switch case 0xe0: if (a < 0xa0) return false; break; case 0xed: if (a > 0x9f) return false; break; case 0xf0: if (a < 0x90) return false; break; case 0xf4: if (a > 0x8f) return false; break; default: if (a < 0x80) return false; } } case 1: if ((*source >= 0x80) && (*source < 0xc2)) return false; } return (*source <= 0xf4); } std::u16string UTF8ToRawBEUTF16(const AString & a_UTF8) { std::u16string UTF16; UTF16.reserve(a_UTF8.size() * 2); const unsigned char * source = reinterpret_cast(a_UTF8.data()); const unsigned char * sourceEnd = source + a_UTF8.size(); const int halfShift = 10; // used for shifting by 10 bits const unsigned int halfBase = 0x0010000UL; const unsigned int halfMask = 0x3ffUL; while (source < sourceEnd) { unsigned int ch = 0; unsigned short extraBytesToRead = trailingBytesForUTF8[*source]; if (source + extraBytesToRead >= sourceEnd) { return UTF16; } // Do this check whether lenient or strict if (!isLegalUTF8(source, extraBytesToRead + 1)) { return UTF16; } // The cases all fall through. See "Note A" below. switch (extraBytesToRead) { case 5: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */ case 4: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */ case 3: ch += *source++; ch <<= 6; case 2: ch += *source++; ch <<= 6; case 1: ch += *source++; ch <<= 6; case 0: ch += *source++; } ch -= offsetsFromUTF8[extraBytesToRead]; if (ch <= UNI_MAX_BMP) { // Target is a character <= 0xFFFF if ((ch >= UNI_SUR_HIGH_START) && (ch <= UNI_SUR_LOW_END)) { // UTF-16 surrogate values are illegal in UTF-32 ch = ' '; } unsigned short v = htons(static_cast(ch)); UTF16.push_back(static_cast(v)); } else if (ch > UNI_MAX_UTF16) { // Invalid value, replace with a space unsigned short v = htons(' '); UTF16.push_back(static_cast(v)); } else { // target is a character in range 0xFFFF - 0x10FFFF. ch -= halfBase; auto v1 = htons(static_cast((ch >> halfShift) + UNI_SUR_HIGH_START)); auto v2 = htons(static_cast((ch & halfMask) + UNI_SUR_LOW_START)); UTF16.push_back(static_cast(v1)); UTF16.push_back(static_cast(v2)); } } return UTF16; } /* --------------------------------------------------------------------- Note A. The fall-through switches in UTF-8 reading code save a temp variable, some decrements & conditionals. The switches are equivalent to the following loop: { int tmpBytesToRead = extraBytesToRead + 1; do { ch += *source++; --tmpBytesToRead; if (tmpBytesToRead) { ch <<= 6; } } while (tmpBytesToRead > 0); } --------------------------------------------------------------------- */ //////////////////////////////////////////////////////////////////////////////// // End of Unicode, Inc.'s code / information //////////////////////////////////////////////////////////////////////////////// #ifdef __GNUC__ #pragma GCC diagnostic pop #endif #define HEX(x) static_cast((x) > 9 ? (x) + 'A' - 10 : (x) + '0') /** format binary data this way: 00001234: 31 32 33 34 35 36 37 38 39 30 61 62 63 64 65 66 1234567890abcdef */ AString & CreateHexDump(AString & a_Out, const void * a_Data, size_t a_Size, size_t a_BytesPerLine) { fmt::memory_buffer Output; /* If formatting the data from the comment above: Hex holds: "31 32 33 34 35 36 37 38 39 30 61 62 63 64 65 66 " Chars holds: "1234567890abcdef" */ fmt::memory_buffer Hex, Chars; if (a_Size > 0) { // Same as std::ceil(static_cast(a_Size) / a_BytesPerLine); const size_t NumLines = a_Size / a_BytesPerLine + (a_Size % a_BytesPerLine != 0); const size_t CharsPerLine = 14 + 4 * a_BytesPerLine; Output.reserve(NumLines * CharsPerLine); } for (size_t i = 0; i < a_Size; i += a_BytesPerLine) { size_t k = std::min(a_Size - i, a_BytesPerLine); for (size_t j = 0; j < k; j++) { Byte c = (static_cast(a_Data))[i + j]; Hex.push_back(HEX(c >> 4)); Hex.push_back(HEX(c & 0xf)); Hex.push_back(' '); Chars.push_back((c >= ' ') ? static_cast(c) : '.'); } // for j // Write Hex with a dynamic fixed width auto HexStr = fmt::string_view(Hex.data(), Hex.size()); auto CharsStr = fmt::string_view(Chars.data(), Chars.size()); fmt::format_to( Output, "{0:08x}: {1:{2}} {3}\n", i, HexStr, a_BytesPerLine * 3, CharsStr ); Hex.clear(); Chars.clear(); } // for i a_Out.append(Output.data(), Output.size()); return a_Out; } AString EscapeString(const AString & a_Message) { AString EscapedMsg; size_t len = a_Message.size(); size_t last = 0; EscapedMsg.reserve(len); for (size_t i = 0; i < len; i++) { char ch = a_Message[i]; switch (ch) { case '\'': case '\"': case '\\': { if (i > last) { EscapedMsg.append(a_Message, last, i - last); } EscapedMsg.push_back('\\'); EscapedMsg.push_back(ch); last = i + 1; break; } } // switch (ch) } // for i - a_Message[] if (len > last) { EscapedMsg.append(a_Message, last, len - last); } return EscapedMsg; } AString StripColorCodes(const AString & a_Message) { AString res(a_Message); size_t idx = 0; for (;;) { idx = res.find("\xc2\xa7", idx); if (idx == AString::npos) { return res; } res.erase(idx, 3); } } std::pair URLDecode(const AString & a_Text) { AString res; auto len = a_Text.size(); res.reserve(len); for (size_t i = 0; i < len; i++) { if (a_Text[i] == '+') { res.push_back(' '); continue; } if (a_Text[i] != '%') { res.push_back(a_Text[i]); continue; } if (i + 1 >= len) { // String too short for an encoded value return std::make_pair(false, AString()); } if ((a_Text[i + 1] == 'u') || (a_Text[i + 1] == 'U')) { // Unicode char "%u0xxxx" if (i + 6 >= len) { return std::make_pair(false, AString()); } if (a_Text[i + 2] != '0') { return std::make_pair(false, AString()); } unsigned v1 = HexToDec(a_Text[i + 3]); unsigned v2 = HexToDec(a_Text[i + 4]); unsigned v3 = HexToDec(a_Text[i + 5]); unsigned v4 = HexToDec(a_Text[i + 6]); if ((v1 == 0xff) || (v2 == 0xff) || (v4 == 0xff) || (v3 == 0xff)) { // Invalid hex numbers return std::make_pair(false, AString()); } res.append(UnicodeCharToUtf8((v1 << 12) | (v2 << 8) | (v3 << 4) | v4)); i = i + 6; } else { // Regular char "%xx": if (i + 2 >= len) { return std::make_pair(false, AString()); } auto v1 = HexToDec(a_Text[i + 1]); auto v2 = HexToDec(a_Text[i + 2]); if ((v1 == 0xff) || (v2 == 0xff)) { // Invalid hex numbers return std::make_pair(false, AString()); } res.push_back(static_cast((v1 << 4) | v2)); i = i + 2; } } // for i - a_Text[i] return std::make_pair(true, res); } AString URLEncode(const AString & a_Text) { AString res; auto len = a_Text.size(); res.reserve(len); static const char HEX[] = "0123456789ABCDEF"; for (size_t i = 0; i < len; ++i) { if (isalnum(a_Text[i])) { res.push_back(a_Text[i]); } else if (a_Text[i] == ' ') { res.push_back('+'); } else { res.push_back('%'); res.push_back(HEX[static_cast(a_Text[i]) >> 4]); res.push_back(HEX[static_cast(a_Text[i]) & 0x0f]); } } return res; } AString ReplaceAllCharOccurrences(const AString & a_String, char a_From, char a_To) { AString res(a_String); std::replace(res.begin(), res.end(), a_From, a_To); return res; } /** Converts one Hex character in a Base64 encoding into the data value */ static inline int UnBase64(char c) { if ((c >='A') && (c <= 'Z')) { return c - 'A'; } if ((c >='a') && (c <= 'z')) { return c - 'a' + 26; } if ((c >= '0') && (c <= '9')) { return c - '0' + 52; } if (c == '+') { return 62; } if (c == '/') { return 63; } if (c == '=') { return -1; } return -2; } AString Base64Decode(const AString & a_Base64String) { AString res; size_t i, len = a_Base64String.size(); size_t o; int c; res.resize((len * 4) / 3 + 5, 0); // Approximate the upper bound on the result length for (o = 0, i = 0; i < len; i++) { c = UnBase64(a_Base64String[i]); if (c >= 0) { switch (o & 7) { case 0: res[o >> 3] |= (c << 2); break; case 6: res[o >> 3] |= (c >> 4); res[(o >> 3) + 1] |= (c << 4); break; case 4: res[o >> 3] |= (c >> 2); res[(o >> 3) + 1] |= (c << 6); break; case 2: res[o >> 3] |= c; break; } o += 6; } if (c == -1) { // Error while decoding, invalid input. Return as much as we've decoded: res.resize(o >> 3); return res; } } res.resize(o >> 3); return res; } AString Base64Encode(const AString & a_Input) { static const char BASE64[64] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' }; AString output; output.resize(((a_Input.size() + 2) / 3) * 4); size_t output_index = 0; size_t size_full24 = (a_Input.size() / 3) * 3; for (size_t i = 0; i < size_full24; i += 3) { output[output_index++] = BASE64[static_cast(a_Input[i]) >> 2]; output[output_index++] = BASE64[(static_cast(a_Input[i]) << 4 | static_cast(a_Input[i + 1]) >> 4) & 63]; output[output_index++] = BASE64[(static_cast(a_Input[i + 1]) << 2 | static_cast(a_Input[i + 2]) >> 6) & 63]; output[output_index++] = BASE64[static_cast(a_Input[i + 2]) & 63]; } if (size_full24 < a_Input.size()) { output[output_index++] = BASE64[static_cast(a_Input[size_full24]) >> 2]; if (size_full24 + 1 == a_Input.size()) { output[output_index++] = BASE64[(static_cast(a_Input[size_full24]) << 4) & 63]; output[output_index++] = '='; } else { output[output_index++] = BASE64[(static_cast(a_Input[size_full24]) << 4 | static_cast(a_Input[size_full24 + 1]) >> 4) & 63]; output[output_index++] = BASE64[(static_cast(a_Input[size_full24 + 1]) << 2) & 63]; } output[output_index++] = '='; } ASSERT(output_index == output.size()); return output; } bool SplitZeroTerminatedStrings(const AString & a_Strings, AStringVector & a_Output) { a_Output.clear(); size_t size = a_Strings.size(); size_t start = 0; bool res = false; for (size_t i = 0; i < size; i++) { if (a_Strings[i] == 0) { a_Output.push_back(a_Strings.substr(start, i - start)); start = i + 1; res = true; } } if (start < size) { a_Output.push_back(a_Strings.substr(start, size - start)); res = true; } return res; } AStringVector MergeStringVectors(const AStringVector & a_Strings1, const AStringVector & a_Strings2) { // Initialize the resulting vector by the first vector: AStringVector res = a_Strings1; // Add each item from strings2 that is not already present: for (const auto & item : a_Strings2) { if (std::find(res.begin(), res.end(), item) == res.end()) { res.push_back(item); } } // for item - a_Strings2[] return res; } AString StringsConcat(const AStringVector & a_Strings, char a_Separator) { // If the vector is empty, return an empty string: if (a_Strings.empty()) { return ""; } // Concatenate the strings in the vector: AString res; res.append(a_Strings[0]); for (auto itr = a_Strings.cbegin() + 1, end = a_Strings.cend(); itr != end; ++itr) { res.push_back(a_Separator); res.append(*itr); } return res; } bool StringToFloat(const AString & a_String, float & a_Num) { char *err; a_Num = strtof(a_String.c_str(), &err); return (*err == 0); } bool IsOnlyWhitespace(const AString & a_String) { return std::all_of(a_String.cbegin(), a_String.cend(), isspace); } ================================================ FILE: src/StringUtils.h ================================================ // StringUtils.h // Interfaces to various string helper functions #pragma once typedef std::string AString; typedef std::vector AStringVector; typedef std::list AStringList; /** A string dictionary, used for key-value pairs. */ typedef std::map AStringMap; /** Split the string at any of the listed delimiters. Return the splitted strings as a stringvector. */ extern AStringVector StringSplit(const AString & str, const AString & delim); /** Split the string at any of the listed delimiters. Keeps quoted content together Resolves issue #490 Return the splitted strings as a stringvector. */ extern AStringVector StringSplitWithQuotes(const AString & str, const AString & delim); /** Join a list of strings with the given delimiter between entries. */ AString StringJoin(const AStringVector & a_Strings, const AString & a_Delimiter); /** Split the string at any of the listed delimiters and trim each value. Returns the splitted strings as a stringvector. */ extern AStringVector StringSplitAndTrim(const AString & str, const AString & delim); /** Trims whitespace at both ends of the string. Returns a trimmed copy of the original string. */ extern AString TrimString(const AString & str); // tolua_export /** In-place string conversion to uppercase. Returns the same string object. */ extern AString & InPlaceUppercase(AString & s); /** In-place string conversion to lowercase. Returns the same string object. */ extern AString & InPlaceLowercase(AString & s); /** Returns an upper-cased copy of the string */ extern AString StrToUpper(const AString & s); /** Returns a lower-cased copy of the string */ extern AString StrToLower(const AString & s); /** Case-insensitive string comparison. Returns 0 if the strings are the same, <0 if s1 < s2 and >0 if s1 > s2. */ extern int NoCaseCompare(const AString & s1, const AString & s2); // tolua_export /** Case-insensitive string comparison that returns a rating of equal-ness between [0 - s1.length()]. */ extern size_t RateCompareString(const AString & s1, const AString & s2); /** Replaces each occurence of iNeedle in iHayStack with iReplaceWith */ extern void ReplaceString(AString & iHayStack, const AString & iNeedle, const AString & iReplaceWith); // tolua_export /** Replaces each occurence of iNeedle in iHayStack with iReplaceWith, after URL-encoding iReplaceWith */ extern void ReplaceURL(AString & iHayStack, const AString & iNeedle, const AString & iReplaceWith); /** Converts a stream of BE shorts into UTF-8 string; returns a_UTF8. */ extern AString & RawBEUTF16ToUTF8(const char * a_RawData, size_t a_NumShorts, AString & a_UTF8); /** Converts a unicode character to its UTF8 representation. */ extern AString UnicodeCharToUtf8(unsigned a_UnicodeChar); /** Converts a UTF-8 string into a UTF-16 BE string. */ extern std::u16string UTF8ToRawBEUTF16(const AString & a_String); /** Creates a nicely formatted HEX dump of the given memory block. */ extern AString & CreateHexDump(AString & a_Out, const void * a_Data, size_t a_Size, size_t a_BytesPerLine); /** Returns a copy of a_Message with all quotes and backslashes escaped by a backslash. */ extern AString EscapeString(const AString & a_Message); // tolua_export /** Removes all control codes used by MC for colors and styles. */ extern AString StripColorCodes(const AString & a_Message); // tolua_export /** URL-Decodes the given string. The first value specifies whether the decoding was successful. The second value is the decoded string, if successful. */ extern std::pair URLDecode(const AString & a_String); // Exported to Lua as cUrlParser::UrlDecode() /** URL-encodes the given string. */ extern AString URLEncode(const AString & a_Text); /** Replaces all occurrences of char a_From inside a_String with char a_To. */ extern AString ReplaceAllCharOccurrences(const AString & a_String, char a_From, char a_To); // Needn't export to Lua, since Lua doesn't have chars anyway /** Decodes a Base64-encoded string into the raw data */ extern AString Base64Decode(const AString & a_Base64String); // Exported manually due to embedded NULs and extra parameter /** Encodes a string into Base64 */ extern AString Base64Encode(const AString & a_Input); // Exported manually due to embedded NULs and extra parameter /** Splits a string that has embedded \0 characters, on those characters. a_Output is first cleared and then each separate string is pushed back into a_Output. Returns true if there are at least two strings in a_Output (there was at least one \0 separator). */ extern bool SplitZeroTerminatedStrings(const AString & a_Strings, AStringVector & a_Output); /** Merges the two vectors of strings, removing duplicate entries from the second vector. The resulting vector contains items from a_Strings1 first, then from a_Strings2. The order of items doesn't change, only the duplicates are removed. If a_Strings1 contains duplicates, the result will still contain those duplicates. */ extern AStringVector MergeStringVectors(const AStringVector & a_Strings1, const AStringVector & a_Strings2); /** Concatenates the specified strings into a single string, separated by the specified separator character. Use StringJoin() if you need multiple separator characters. */ extern AString StringsConcat(const AStringVector & a_Strings, char a_Separator); /** Converts a string into a float. Returns false if the conversion fails. */ extern bool StringToFloat(const AString & a_String, float & a_Num); /** Returns true if only whitespace characters are present in the string */ bool IsOnlyWhitespace(const AString & a_String); /** Parses any integer type. Checks bounds and returns errors out of band. */ template bool StringToInteger(const AString & a_str, T & a_Num) { size_t i = 0; bool positive = true; T result = 0; if (a_str[0] == '+') { i++; } else if (a_str[0] == '-') { i++; positive = false; } if (positive) { for (size_t size = a_str.size(); i < size; i++) { if ((a_str[i] < '0') || (a_str[i] > '9')) { return false; } if (std::numeric_limits::max() / 10 < result) { return false; } result *= 10; T digit = static_cast(a_str[i] - '0'); if (std::numeric_limits::max() - digit < result) { return false; } result += digit; } } else { // Unsigned result cannot be signed! if (!std::numeric_limits::is_signed) { return false; } for (size_t size = a_str.size(); i < size; i++) { if ((a_str[i] < '0') || (a_str[i] > '9')) { return false; } if (std::numeric_limits::min() / 10 > result) { return false; } result *= 10; T digit = static_cast(a_str[i] - '0'); if (std::numeric_limits::min() + digit > result) { return false; } result -= digit; } } a_Num = result; return true; } /** Returns a number (of any integer type T) from a key-value string map. Returns a_Default if the key is not present or the value is not a number representable in type T. */ template T GetStringMapInteger(const AStringMap & a_Map, const AString & a_Key, T a_Default) { // Try to locate the key: auto itr = a_Map.find(a_Key); if (itr == a_Map.end()) { return a_Default; } // Try to convert the value to a number: T res = a_Default; if (!StringToInteger(itr->second, res)) { return a_Default; } return res; } // If you have any other string helper functions, declare them here ================================================ FILE: src/UI/AnvilWindow.cpp ================================================ // AnvilWindow.cpp // Representing the UI window for the anvil block #include "Globals.h" #include "AnvilWindow.h" #include "SlotArea.h" cAnvilWindow::cAnvilWindow(Vector3i a_BlockPos) : cWindow(wtAnvil, "Repair"), m_RepairedItemName(), m_BlockPos(a_BlockPos) { m_AnvilSlotArea = new cSlotAreaAnvil(*this); m_SlotAreas.push_back(m_AnvilSlotArea); m_SlotAreas.push_back(new cSlotAreaInventory(*this)); m_SlotAreas.push_back(new cSlotAreaHotBar(*this)); } AString cAnvilWindow::GetRepairedItemName(void) const { return m_RepairedItemName; } void cAnvilWindow::SetRepairedItemName(const AString & a_Name, cPlayer * a_Player) { m_RepairedItemName = a_Name; if (a_Player != nullptr) { m_AnvilSlotArea->UpdateResult(*a_Player); } } void cAnvilWindow::DistributeStack(cItem & a_ItemStack, int a_Slot, cPlayer & a_Player, cSlotArea * a_ClickedArea, bool a_ShouldApply) { cSlotAreas AreasInOrder; if (a_ClickedArea == m_SlotAreas[0]) { // Anvil Slot AreasInOrder.push_back(m_SlotAreas[1]); /* Inventory */ AreasInOrder.push_back(m_SlotAreas[2]); /* Hotbar */ } else { // Inventory or Hotbar AreasInOrder.push_back(m_SlotAreas[0]); /* Anvil */ } Super::DistributeStackToAreas(a_ItemStack, a_Player, AreasInOrder, a_ShouldApply, false); } ================================================ FILE: src/UI/AnvilWindow.h ================================================ // AnvilWindow.h // Representing the UI window for the anvil block #pragma once #include "Window.h" class cAnvilWindow: public cWindow { using Super = cWindow; public: cAnvilWindow(Vector3i a_BlockPos); /** Gets the repaired item name. */ AString GetRepairedItemName(void) const; /** Set the repaired item name. */ void SetRepairedItemName(const AString & a_Name, cPlayer * a_Player); /** Gets the Position from the Anvil */ const Vector3i & GetBlockPos() { return m_BlockPos; } virtual void DistributeStack(cItem & a_ItemStack, int a_Slot, cPlayer & a_Player, cSlotArea * a_ClickedArea, bool a_ShouldApply) override; protected: cSlotAreaAnvil * m_AnvilSlotArea; AString m_RepairedItemName; Vector3i m_BlockPos; }; ================================================ FILE: src/UI/BeaconWindow.cpp ================================================ // BeaconWindow.cpp // Representing the UI window for the beacon block #include "Globals.h" #include "BeaconWindow.h" #include "SlotArea.h" #include "../BlockEntities/BeaconEntity.h" #include "../ClientHandle.h" cBeaconWindow::cBeaconWindow(cBeaconEntity * a_Beacon): cWindow(wtBeacon, "Beacon"), m_Beacon(a_Beacon) { m_SlotAreas.push_back(new cSlotAreaBeacon(m_Beacon, *this)); m_SlotAreas.push_back(new cSlotAreaInventory(*this)); m_SlotAreas.push_back(new cSlotAreaHotBar(*this)); } void cBeaconWindow::DistributeStack(cItem & a_ItemStack, int a_Slot, cPlayer & a_Player, cSlotArea * a_ClickedArea, bool a_ShouldApply) { cSlotAreas AreasInOrder; if (a_ClickedArea == m_SlotAreas[0]) { // Beacon Area AreasInOrder.push_back(m_SlotAreas[2]); /* Hotbar */ AreasInOrder.push_back(m_SlotAreas[1]); /* Inventory */ Super::DistributeStackToAreas(a_ItemStack, a_Player, AreasInOrder, a_ShouldApply, true); } else { if (cSlotAreaBeacon::IsPlaceableItem(a_ItemStack.m_ItemType) && (a_ItemStack.m_ItemCount == 1)) { AreasInOrder.push_back(m_SlotAreas[0]); /* Beacon */ } if (a_ClickedArea == m_SlotAreas[1]) { // Inventory Area AreasInOrder.push_back(m_SlotAreas[2]); /* Hotbar */ } else { // Hotbar Area AreasInOrder.push_back(m_SlotAreas[1]); /* Inventory */ } Super::DistributeStackToAreas(a_ItemStack, a_Player, AreasInOrder, a_ShouldApply, false); } } void cBeaconWindow::OpenedByPlayer(cPlayer & a_Player) { Super::OpenedByPlayer(a_Player); a_Player.GetClientHandle()->SendWindowProperty(*this, 0, m_Beacon->GetBeaconLevel()); a_Player.GetClientHandle()->SendWindowProperty(*this, 1, static_cast(m_Beacon->GetPrimaryEffect())); a_Player.GetClientHandle()->SendWindowProperty(*this, 2, static_cast(m_Beacon->GetSecondaryEffect())); } ================================================ FILE: src/UI/BeaconWindow.h ================================================ // BeaconWindow.h // Representing the UI window for the beacon block #pragma once #include "Window.h" #include "../Entities/Player.h" class cBeaconWindow : public cWindow { using Super = cWindow; public: cBeaconWindow(cBeaconEntity * a_Beacon); cBeaconEntity * GetBeaconEntity(void) const { return m_Beacon; } virtual void DistributeStack(cItem & a_ItemStack, int a_Slot, cPlayer & a_Player, cSlotArea * a_ClickedArea, bool a_ShouldApply) override; // cWindow Overrides: virtual void OpenedByPlayer(cPlayer & a_Player) override; protected: cBeaconEntity * m_Beacon; }; ================================================ FILE: src/UI/BrewingstandWindow.cpp ================================================ // BrewingstandWindow.cpp // Representing the UI window for the brewing stand block #include "Globals.h" #include "BrewingstandWindow.h" #include "SlotArea.h" #include "../BrewingRecipes.h" #include "../Root.h" cBrewingstandWindow::cBrewingstandWindow(cBrewingstandEntity * a_Brewingstand): Super(wtBrewery, "Brewingstand") { m_SlotAreas.push_back(new cSlotAreaBrewingstand(a_Brewingstand, *this)); m_SlotAreas.push_back(new cSlotAreaInventory(*this)); m_SlotAreas.push_back(new cSlotAreaHotBar(*this)); } void cBrewingstandWindow::DistributeStack(cItem & a_ItemStack, int a_Slot, cPlayer & a_Player, cSlotArea * a_ClickedArea, bool a_ShouldApply) { cSlotAreas AreasInOrder; if (a_ClickedArea == m_SlotAreas[0]) { if ((a_Slot >= 0) && (a_Slot <= 4)) { // Brewing stand Area AreasInOrder.push_back(m_SlotAreas[2]); /* Hotbar */ AreasInOrder.push_back(m_SlotAreas[1]); /* Inventory */ Super::DistributeStackToAreas(a_ItemStack, a_Player, AreasInOrder, a_ShouldApply, true); } else { AreasInOrder.push_back(m_SlotAreas[1]); /* Inventory */ AreasInOrder.push_back(m_SlotAreas[2]); /* Hotbar */ Super::DistributeStackToAreas(a_ItemStack, a_Player, AreasInOrder, a_ShouldApply, false); } } else { cBrewingRecipes * BR = cRoot::Get()->GetBrewingRecipes(); if ((BR->IsBottle(a_ItemStack)) || (BR->IsIngredient(a_ItemStack)) || BR->IsFuel(a_ItemStack)) { AreasInOrder.push_back(m_SlotAreas[0]); /* brewing stand Area */ } else if (a_ClickedArea == m_SlotAreas[1]) { // Inventory Area AreasInOrder.push_back(m_SlotAreas[2]); /* Hotbar */ } else { // Hotbar Area AreasInOrder.push_back(m_SlotAreas[1]); /* Inventory */ } Super::DistributeStackToAreas(a_ItemStack, a_Player, AreasInOrder, a_ShouldApply, false); } } ================================================ FILE: src/UI/BrewingstandWindow.h ================================================ // BrewingstandWindow.h // Representing the UI window for the brewing stand block #pragma once #include "Window.h" class cBrewingstandWindow : public cWindow { using Super = cWindow; public: cBrewingstandWindow(cBrewingstandEntity * a_Brewingstand); virtual void DistributeStack(cItem & a_ItemStack, int a_Slot, cPlayer & a_Player, cSlotArea * a_ClickedArea, bool a_ShouldApply) override; }; ================================================ FILE: src/UI/CMakeLists.txt ================================================ target_sources( ${CMAKE_PROJECT_NAME} PRIVATE SlotArea.cpp Window.cpp AnvilWindow.cpp BeaconWindow.cpp BrewingstandWindow.cpp ChestWindow.cpp CraftingWindow.cpp DropSpenserWindow.cpp EnchantingWindow.cpp EnderChestWindow.cpp FurnaceWindow.cpp HopperWindow.cpp HorseWindow.cpp InventoryWindow.cpp SlotArea.h Window.h AnvilWindow.h BeaconWindow.h BrewingstandWindow.h ChestWindow.h CraftingWindow.h DropSpenserWindow.h EnchantingWindow.h EnderChestWindow.h FurnaceWindow.h HopperWindow.h HorseWindow.h InventoryWindow.h MinecartWithChestWindow.h WindowOwner.h ) ================================================ FILE: src/UI/ChestWindow.cpp ================================================ // ChestWindow.cpp // Representing the UI window for the chest block #include "Globals.h" #include "ChestWindow.h" #include "../BlockEntities/ChestEntity.h" #include "../Entities/Player.h" #include "SlotArea.h" cChestWindow::cChestWindow(cChestEntity * a_Chest): cWindow(wtChest, (a_Chest->GetBlockType() == E_BLOCK_CHEST) ? "Chest" : "Trapped Chest"), m_World(a_Chest->GetWorld()), m_BlockPos(a_Chest->GetPos()), m_PrimaryChest(a_Chest), m_SecondaryChest(nullptr) { m_SlotAreas.push_back(new cSlotAreaChest(a_Chest, *this)); m_SlotAreas.push_back(new cSlotAreaInventory(*this)); m_SlotAreas.push_back(new cSlotAreaHotBar(*this)); // Play the opening sound: m_World->BroadcastSoundEffect("block.chest.open", m_BlockPos, 1, 1); // Send out the chest-open packet: m_World->BroadcastBlockAction(m_BlockPos, 1, 1, a_Chest->GetBlockType()); } cChestWindow::cChestWindow(cChestEntity * a_PrimaryChest, cChestEntity * a_SecondaryChest) : cWindow(wtChest, (a_PrimaryChest->GetBlockType() == E_BLOCK_CHEST) ? "Double Chest" : "Double Trapped Chest"), m_World(a_PrimaryChest->GetWorld()), m_BlockPos(a_PrimaryChest->GetPos()), m_PrimaryChest(a_PrimaryChest), m_SecondaryChest(a_SecondaryChest) { m_SlotAreas.push_back(new cSlotAreaDoubleChest(a_PrimaryChest, a_SecondaryChest, *this)); m_SlotAreas.push_back(new cSlotAreaInventory(*this)); m_SlotAreas.push_back(new cSlotAreaHotBar(*this)); // Play the opening sound: m_World->BroadcastSoundEffect("block.chest.open", m_BlockPos, 1, 1); // Send out the chest-open packet: m_World->BroadcastBlockAction(m_BlockPos, 1, 1, a_PrimaryChest->GetBlockType()); } cChestWindow::~cChestWindow() { // Send out the chest-close packet: m_World->BroadcastBlockAction(m_BlockPos, 1, 0, m_PrimaryChest->GetBlockType()); m_World->BroadcastSoundEffect("block.chest.close", m_BlockPos, 1, 1); } bool cChestWindow::ClosedByPlayer(cPlayer & a_Player, bool a_CanRefuse) { m_PrimaryChest->SetNumberOfPlayers(m_PrimaryChest->GetNumberOfPlayers() - 1); m_PrimaryChest->GetWorld()->WakeUpSimulators(m_PrimaryChest->GetPos()); if (m_SecondaryChest != nullptr) { m_SecondaryChest->SetNumberOfPlayers(m_SecondaryChest->GetNumberOfPlayers() - 1); m_SecondaryChest->GetWorld()->WakeUpSimulators(m_SecondaryChest->GetPos()); } cWindow::ClosedByPlayer(a_Player, a_CanRefuse); return true; } void cChestWindow::OpenedByPlayer(cPlayer & a_Player) { m_PrimaryChest->SetNumberOfPlayers(m_PrimaryChest->GetNumberOfPlayers() + 1); m_PrimaryChest->GetWorld()->WakeUpSimulators(m_PrimaryChest->GetPos()); if (m_SecondaryChest != nullptr) { m_SecondaryChest->SetNumberOfPlayers(m_SecondaryChest->GetNumberOfPlayers() + 1); m_SecondaryChest->GetWorld()->WakeUpSimulators(m_SecondaryChest->GetPos()); } cWindow::OpenedByPlayer(a_Player); } void cChestWindow::DistributeStack(cItem & a_ItemStack, int a_Slot, cPlayer & a_Player, cSlotArea * a_ClickedArea, bool a_ShouldApply) { cSlotAreas AreasInOrder; if (a_ClickedArea == m_SlotAreas[0]) { // Chest Area AreasInOrder.push_back(m_SlotAreas[2]); /* Hotbar */ AreasInOrder.push_back(m_SlotAreas[1]); /* Inventory */ Super::DistributeStackToAreas(a_ItemStack, a_Player, AreasInOrder, a_ShouldApply, true); } else { // Hotbar or Inventory AreasInOrder.push_back(m_SlotAreas[0]); /* Chest */ Super::DistributeStackToAreas(a_ItemStack, a_Player, AreasInOrder, a_ShouldApply, false); } } ================================================ FILE: src/UI/ChestWindow.h ================================================ // ChestWindow.h // Representing the UI window for the chest block #pragma once #include "Window.h" class cChestWindow: public cWindow { using Super = cWindow; public: cChestWindow(cChestEntity * a_Chest); cChestWindow(cChestEntity * a_PrimaryChest, cChestEntity * a_SecondaryChest); virtual ~cChestWindow() override; virtual bool ClosedByPlayer(cPlayer & a_Player, bool a_CanRefuse) override; virtual void OpenedByPlayer(cPlayer & a_Player) override; virtual void DistributeStack(cItem & a_ItemStack, int a_Slot, cPlayer & a_Player, cSlotArea * a_ClickedArea, bool a_ShouldApply) override; protected: cWorld * m_World; Vector3i m_BlockPos; // Position of the chest, for the window-close packet cChestEntity * m_PrimaryChest; cChestEntity * m_SecondaryChest; }; ================================================ FILE: src/UI/CraftingWindow.cpp ================================================ // CraftingWindow.cpp // Representing the UI window for the crafting block #include "Globals.h" #include "CraftingWindow.h" #include "SlotArea.h" cCraftingWindow::cCraftingWindow() : cWindow(wtWorkbench, "Crafting Table") { m_SlotAreas.push_back(new cSlotAreaCrafting(3, *this)); m_SlotAreas.push_back(new cSlotAreaInventory(*this)); m_SlotAreas.push_back(new cSlotAreaHotBar(*this)); } void cCraftingWindow::DistributeStack(cItem & a_ItemStack, int a_Slot, cPlayer & a_Player, cSlotArea * a_ClickedArea, bool a_ShouldApply) { cSlotAreas AreasInOrder; if (a_ClickedArea == m_SlotAreas[0]) { // Crafting Area if (a_Slot == 0) { // Result Slot AreasInOrder.push_back(m_SlotAreas[2]); /* Hotbar */ AreasInOrder.push_back(m_SlotAreas[1]); /* Inventory */ } else { AreasInOrder.push_back(m_SlotAreas[1]); /* Inventory */ AreasInOrder.push_back(m_SlotAreas[2]); /* Hotbar */ } Super::DistributeStackToAreas(a_ItemStack, a_Player, AreasInOrder, a_ShouldApply, (a_Slot == 0)); } else if (a_ClickedArea == m_SlotAreas[1]) { // Inventory Area AreasInOrder.push_back(m_SlotAreas[2]); /* Hotbar */ Super::DistributeStackToAreas(a_ItemStack, a_Player, AreasInOrder, a_ShouldApply, false); } else { // Hotbar AreasInOrder.push_back(m_SlotAreas[1]); /* Inventory */ Super::DistributeStackToAreas(a_ItemStack, a_Player, AreasInOrder, a_ShouldApply, false); } } void cCraftingWindow::LoadRecipe(cPlayer & a_Player, UInt32 a_RecipeId) { auto slotAreaCrafting = static_cast(m_SlotAreas[0]); slotAreaCrafting->LoadRecipe(a_Player, a_RecipeId); } ================================================ FILE: src/UI/CraftingWindow.h ================================================ // CraftingWindow.h // Representing the UI window for the crafting block #pragma once #include "Window.h" class cCraftingWindow: public cWindow { using Super = cWindow; public: cCraftingWindow(); virtual void DistributeStack(cItem & a_ItemStack, int a_Slot, cPlayer & a_Player, cSlotArea * a_ClickedArea, bool a_ShouldApply) override; /** Loads the given Recipe into the crafting grid */ void LoadRecipe(cPlayer & a_Player, UInt32 a_RecipeId); }; ================================================ FILE: src/UI/DropSpenserWindow.cpp ================================================ // DropSpenserWindow.cpp // Representing the UI window for the dropper / dispenser block #include "Globals.h" #include "DropSpenserWindow.h" #include "SlotArea.h" cDropSpenserWindow::cDropSpenserWindow(cDropSpenserEntity * a_DropSpenser): Super(wtDropSpenser, (a_DropSpenser->GetBlockType() == E_BLOCK_DISPENSER) ? "Dispenser" : "Dropper") { m_SlotAreas.push_back(new cSlotAreaItemGrid(a_DropSpenser->GetContents(), *this)); m_SlotAreas.push_back(new cSlotAreaInventory(*this)); m_SlotAreas.push_back(new cSlotAreaHotBar(*this)); } void cDropSpenserWindow::DistributeStack(cItem & a_ItemStack, int a_Slot, cPlayer & a_Player, cSlotArea * a_ClickedArea, bool a_ShouldApply) { cSlotAreas AreasInOrder; if (a_ClickedArea == m_SlotAreas[0]) { // DropSpenser Area AreasInOrder.push_back(m_SlotAreas[2]); /* Hotbar */ AreasInOrder.push_back(m_SlotAreas[1]); /* Inventory */ Super::DistributeStackToAreas(a_ItemStack, a_Player, AreasInOrder, a_ShouldApply, true); } else { // Inventory or Hotbar AreasInOrder.push_back(m_SlotAreas[0]); /* DropSpenser */ Super::DistributeStackToAreas(a_ItemStack, a_Player, AreasInOrder, a_ShouldApply, false); } } ================================================ FILE: src/UI/DropSpenserWindow.h ================================================ // DropSpenserWindow.h // Representing the UI window for the dropper / dispenser block #pragma once #include "Window.h" #include "../BlockEntities/DropSpenserEntity.h" class cDropSpenserWindow : public cWindow { using Super = cWindow; public: cDropSpenserWindow(cDropSpenserEntity * a_DropSpenser); virtual void DistributeStack(cItem & a_ItemStack, int a_Slot, cPlayer & a_Player, cSlotArea * a_ClickedArea, bool a_ShouldApply) override; }; ================================================ FILE: src/UI/EnchantingWindow.cpp ================================================ // EnchantingWindow.cpp // Representing the UI window for the enchanting block #include "Globals.h" #include "EnchantingWindow.h" #include "SlotArea.h" cEnchantingWindow::cEnchantingWindow(Vector3i a_BlockPos, const AString & a_Title) : cWindow(wtEnchantment, a_Title), m_SlotArea(), m_BlockPos(a_BlockPos) { m_SlotArea = new cSlotAreaEnchanting(*this, m_BlockPos); m_SlotAreas.push_back(m_SlotArea); m_SlotAreas.push_back(new cSlotAreaInventory(*this)); m_SlotAreas.push_back(new cSlotAreaHotBar(*this)); } void cEnchantingWindow::SetProperty(size_t a_Property, short a_Value) { if (a_Property < m_PropertyValue.size()) { m_PropertyValue[a_Property] = a_Value; } Super::SetProperty(a_Property, a_Value); } short cEnchantingWindow::GetProperty(size_t a_Property) { ASSERT(a_Property < m_PropertyValue.size()); return m_PropertyValue[a_Property]; } void cEnchantingWindow::DistributeStack(cItem & a_ItemStack, int a_Slot, cPlayer & a_Player, cSlotArea * a_ClickedArea, bool a_ShouldApply) { cSlotAreas AreasInOrder; if (a_ClickedArea == m_SlotAreas[0]) { // Enchanting Area AreasInOrder.push_back(m_SlotAreas[2]); /* Hotbar */ AreasInOrder.push_back(m_SlotAreas[1]); /* Inventory */ Super::DistributeStackToAreas(a_ItemStack, a_Player, AreasInOrder, a_ShouldApply, true); } else { // Inventory or Hotbar AreasInOrder.push_back(m_SlotAreas[0]); /* Enchanting */ Super::DistributeStackToAreas(a_ItemStack, a_Player, AreasInOrder, a_ShouldApply, false); } } ================================================ FILE: src/UI/EnchantingWindow.h ================================================ // EnchantingWindow.h // Representing the UI window for the enchanting block #pragma once #include "Window.h" class cSlotAreaEnchanting; class cEnchantingWindow final : public cWindow { using Super = cWindow; public: cEnchantingWindow(Vector3i a_BlockPos, const AString & a_Title); /** Sends enchantment properties to the client. If the property represents a level requirement, stores it for later GetProperty retrieval. */ virtual void SetProperty(size_t a_Property, short a_Value) override; /** Return the level requirement of the given enchantment slot. */ short GetProperty(size_t a_Property); virtual void DistributeStack(cItem & a_ItemStack, int a_Slot, cPlayer & a_Player, cSlotArea * a_ClickedArea, bool a_ShouldApply) override; cSlotAreaEnchanting * m_SlotArea; protected: std::array m_PropertyValue; Vector3i m_BlockPos; }; ================================================ FILE: src/UI/EnderChestWindow.cpp ================================================ // EnderChestWindow.cpp // Representing the UI window for the enderchest block #include "Globals.h" #include "../World.h" #include "EnderChestWindow.h" #include "SlotArea.h" cEnderChestWindow::cEnderChestWindow(cEnderChestEntity * a_EnderChest): cWindow(wtChest, "Ender Chest"), m_World(a_EnderChest->GetWorld()), m_BlockPos(a_EnderChest->GetPos()) { m_SlotAreas.push_back(new cSlotAreaEnderChest(a_EnderChest, *this)); m_SlotAreas.push_back(new cSlotAreaInventory(*this)); m_SlotAreas.push_back(new cSlotAreaHotBar(*this)); // Play the opening sound: m_World->BroadcastSoundEffect( "block.enderchest.open", m_BlockPos, 1, 1 ); // Send out the chest-open packet: m_World->BroadcastBlockAction(m_BlockPos, 1, 1, E_BLOCK_ENDER_CHEST); } cEnderChestWindow::~cEnderChestWindow() { // Send out the chest-close packet: m_World->BroadcastBlockAction(m_BlockPos, 1, 0, E_BLOCK_ENDER_CHEST); // Play the closing sound m_World->BroadcastSoundEffect( "block.enderchest.close", m_BlockPos, 1, 1 ); } void cEnderChestWindow::DistributeStack(cItem & a_ItemStack, int a_Slot, cPlayer & a_Player, cSlotArea * a_ClickedArea, bool a_ShouldApply) { cSlotAreas AreasInOrder; if (a_ClickedArea == m_SlotAreas[0]) { // Chest Area AreasInOrder.push_back(m_SlotAreas[2]); /* Hotbar */ AreasInOrder.push_back(m_SlotAreas[1]); /* Inventory */ Super::DistributeStackToAreas(a_ItemStack, a_Player, AreasInOrder, a_ShouldApply, true); } else { // Hotbar or Inventory AreasInOrder.push_back(m_SlotAreas[0]); /* Chest */ Super::DistributeStackToAreas(a_ItemStack, a_Player, AreasInOrder, a_ShouldApply, false); } } ================================================ FILE: src/UI/EnderChestWindow.h ================================================ // EnderChestWindow.h // Representing the UI window for the enderchest block #pragma once #include "Window.h" #include "../BlockEntities/EnderChestEntity.h" class cEnderChestWindow: public cWindow { using Super = cWindow; public: cEnderChestWindow(cEnderChestEntity * a_EnderChest); virtual ~cEnderChestWindow() override; virtual void DistributeStack(cItem & a_ItemStack, int a_Slot, cPlayer & a_Player, cSlotArea * a_ClickedArea, bool a_ShouldApply) override; protected: cWorld * m_World; Vector3i m_BlockPos; // Position of the enderchest, for the window-close packet }; ================================================ FILE: src/UI/FurnaceWindow.cpp ================================================ // FurnaceWindow.cpp // Representing the UI window for the furnace block #include "Globals.h" #include "FurnaceWindow.h" #include "SlotArea.h" #include "../FurnaceRecipe.h" #include "../Root.h" cFurnaceWindow::cFurnaceWindow(cFurnaceEntity * a_Furnace): cWindow(wtFurnace, "Furnace") { m_SlotAreas.push_back(new cSlotAreaFurnace(a_Furnace, *this)); m_SlotAreas.push_back(new cSlotAreaInventory(*this)); m_SlotAreas.push_back(new cSlotAreaHotBar(*this)); } void cFurnaceWindow::DistributeStack(cItem & a_ItemStack, int a_Slot, cPlayer & a_Player, cSlotArea * a_ClickedArea, bool a_ShouldApply) { cSlotAreas AreasInOrder; if (a_ClickedArea == m_SlotAreas[0]) { // Furnace Area if (a_Slot == 2) { // Result Slot AreasInOrder.push_back(m_SlotAreas[2]); /* Hotbar */ AreasInOrder.push_back(m_SlotAreas[1]); /* Inventory */ Super::DistributeStackToAreas(a_ItemStack, a_Player, AreasInOrder, a_ShouldApply, true); } else { // Furnace Input / Fuel Slot AreasInOrder.push_back(m_SlotAreas[1]); /* Inventory */ AreasInOrder.push_back(m_SlotAreas[2]); /* Hotbar */ Super::DistributeStackToAreas(a_ItemStack, a_Player, AreasInOrder, a_ShouldApply, false); } } else { cFurnaceRecipe * FurnaceRecipes = cRoot::Get()->GetFurnaceRecipe(); if ((FurnaceRecipes->GetRecipeFrom(a_ItemStack) != nullptr) || (FurnaceRecipes->IsFuel(a_ItemStack))) { // The item is a valid input item or fuel AreasInOrder.push_back(m_SlotAreas[0]); /* Furnace Area */ } else if (a_ClickedArea == m_SlotAreas[1]) { // Inventory Area AreasInOrder.push_back(m_SlotAreas[2]); /* Hotbar */ } else { // Hotbar Area AreasInOrder.push_back(m_SlotAreas[1]); /* Inventory */ } Super::DistributeStackToAreas(a_ItemStack, a_Player, AreasInOrder, a_ShouldApply, false); } } ================================================ FILE: src/UI/FurnaceWindow.h ================================================ // FurnaceWindow.h // Representing the UI window for the furnace block #pragma once #include "Window.h" class cFurnaceWindow : public cWindow { using Super = cWindow; public: cFurnaceWindow(cFurnaceEntity * a_Furnace); virtual void DistributeStack(cItem & a_ItemStack, int a_Slot, cPlayer & a_Player, cSlotArea * a_ClickedArea, bool a_ShouldApply) override; }; ================================================ FILE: src/UI/HopperWindow.cpp ================================================ // HopperWindow.cpp // Representing the UI window for the hopper block #include "Globals.h" #include "../BlockEntities/HopperEntity.h" #include "HopperWindow.h" #include "../BlockEntities/DropperEntity.h" #include "SlotArea.h" cHopperWindow::cHopperWindow(cHopperEntity * a_Hopper): Super(wtHopper, "Hopper") { m_SlotAreas.push_back(new cSlotAreaItemGrid(a_Hopper->GetContents(), *this)); m_SlotAreas.push_back(new cSlotAreaInventory(*this)); m_SlotAreas.push_back(new cSlotAreaHotBar(*this)); } void cHopperWindow::DistributeStack(cItem & a_ItemStack, int a_Slot, cPlayer & a_Player, cSlotArea * a_ClickedArea, bool a_ShouldApply) { cSlotAreas AreasInOrder; if (a_ClickedArea == m_SlotAreas[0]) { // Hopper Area AreasInOrder.push_back(m_SlotAreas[2]); /* Hotbar */ AreasInOrder.push_back(m_SlotAreas[1]); /* Inventory */ Super::DistributeStackToAreas(a_ItemStack, a_Player, AreasInOrder, a_ShouldApply, true); } else { // Inventory or Hotbar AreasInOrder.push_back(m_SlotAreas[0]); /* Hopper */ Super::DistributeStackToAreas(a_ItemStack, a_Player, AreasInOrder, a_ShouldApply, false); } } ================================================ FILE: src/UI/HopperWindow.h ================================================ // HopperWindow.h // Representing the UI window for the hopper block #pragma once #include "Window.h" class cHopperWindow: public cWindow { using Super = cWindow; public: cHopperWindow(cHopperEntity * a_Hopper); virtual void DistributeStack(cItem & a_ItemStack, int a_Slot, cPlayer & a_Player, cSlotArea * a_ClickedArea, bool a_ShouldApply) override; }; ================================================ FILE: src/UI/HorseWindow.cpp ================================================ // HorseWindow.cpp // Representing the UI window for a horse entity #include "Globals.h" #include "../Mobs/Horse.h" #include "../UI/HorseWindow.h" #include "../UI/SlotArea.h" cHorseWindow::cHorseWindow(cHorse & a_Horse): Super(wtAnimalChest, "Horse"), m_Horse(a_Horse) { m_SlotAreas.push_back(new cSlotAreaHorse(a_Horse, *this)); m_SlotAreas.push_back(new cSlotAreaInventory(*this)); m_SlotAreas.push_back(new cSlotAreaHotBar(*this)); } void cHorseWindow::DistributeStack(cItem & a_ItemStack, int a_Slot, cPlayer & a_Player, cSlotArea * a_ClickedArea, bool a_ShouldApply) { cSlotAreas AreasInOrder; if (a_ClickedArea == m_SlotAreas[0]) { // Horse Area AreasInOrder.push_back(m_SlotAreas[2]); /* Hotbar */ AreasInOrder.push_back(m_SlotAreas[1]); /* Inventory */ Super::DistributeStackToAreas(a_ItemStack, a_Player, AreasInOrder, a_ShouldApply, true); } else { // Inventory or Hotbar if (ItemCategory::IsHorseArmor(a_ItemStack.m_ItemType) || (a_ItemStack.m_ItemType == E_ITEM_SADDLE)) { AreasInOrder.push_back(m_SlotAreas[0]); /* Horse */ Super::DistributeStackToAreas(a_ItemStack, a_Player, AreasInOrder, a_ShouldApply, false); } } } UInt32 cHorseWindow::GetHorseID() const { return m_Horse.GetUniqueID(); } ================================================ FILE: src/UI/HorseWindow.h ================================================ // HorseWindow.h // Representing the UI window for a horse entity #pragma once #include "Window.h" class cHorse; class cHorseWindow : public cWindow { using Super = cWindow; public: cHorseWindow(cHorse & a_Horse); virtual void DistributeStack(cItem & a_ItemStack, int a_Slot, cPlayer & a_Player, cSlotArea * a_ClickedArea, bool a_ShouldApply) override; /** Returns the horse's entity ID. */ UInt32 GetHorseID() const; private: cHorse & m_Horse; }; ================================================ FILE: src/UI/InventoryWindow.cpp ================================================ // InventoryWindow.cpp // Representing the UI window for the player inventory #include "Globals.h" #include "InventoryWindow.h" #include "SlotArea.h" cInventoryWindow::cInventoryWindow(cPlayer & a_Player) : cWindow(wtInventory, "Inventory"), m_Player(a_Player) { m_SlotAreas.push_back(new cSlotAreaCrafting(2, *this)); // The creative inventory doesn't display it, but it's still counted into slot numbers m_SlotAreas.push_back(new cSlotAreaArmor(*this)); m_SlotAreas.push_back(new cSlotAreaInventory(*this)); m_SlotAreas.push_back(new cSlotAreaHotBar(*this)); m_SlotAreas.push_back(new cSlotAreaShield(*this)); } void cInventoryWindow::DistributeStack(cItem & a_ItemStack, int a_Slot, cPlayer & a_Player, cSlotArea * a_ClickedArea, bool a_ShouldApply) { cSlotAreas AreasInOrder; if (a_ClickedArea == m_SlotAreas[0]) { // Crafting Area if (a_Slot == 0) { // Result Slot AreasInOrder.push_back(m_SlotAreas[3]); /* Hotbar */ AreasInOrder.push_back(m_SlotAreas[2]); /* Inventory */ } else { AreasInOrder.push_back(m_SlotAreas[2]); /* Inventory */ AreasInOrder.push_back(m_SlotAreas[3]); /* Hotbar */ } Super::DistributeStackToAreas(a_ItemStack, a_Player, AreasInOrder, a_ShouldApply, (a_Slot == 0)); } else if (a_ClickedArea == m_SlotAreas[1]) { // Armor Area AreasInOrder.push_back(m_SlotAreas[2]); /* Inventory */ AreasInOrder.push_back(m_SlotAreas[3]); /* Hotbar */ Super::DistributeStackToAreas(a_ItemStack, a_Player, AreasInOrder, a_ShouldApply, false); } else if (a_ClickedArea == m_SlotAreas[2]) { // Inventory Area AreasInOrder.push_back(m_SlotAreas[1]); /* Armor */ AreasInOrder.push_back(m_SlotAreas[3]); /* Hotbar */ Super::DistributeStackToAreas(a_ItemStack, a_Player, AreasInOrder, a_ShouldApply, false); } else { // Hotbar AreasInOrder.push_back(m_SlotAreas[1]); /* Armor */ AreasInOrder.push_back(m_SlotAreas[2]); /* Inventory */ Super::DistributeStackToAreas(a_ItemStack, a_Player, AreasInOrder, a_ShouldApply, false); } } void cInventoryWindow::LoadRecipe(cPlayer & a_Player, UInt32 a_RecipeId) { auto slotAreaCrafting = static_cast(m_SlotAreas[0]); slotAreaCrafting->LoadRecipe(a_Player, a_RecipeId); } ================================================ FILE: src/UI/InventoryWindow.h ================================================ // InventoryWindow.h // Representing the UI window for the player inventory #pragma once #include "Window.h" class cInventoryWindow: public cWindow { using Super = cWindow; public: cInventoryWindow(cPlayer & a_Player); virtual void DistributeStack(cItem & a_ItemStack, int a_Slot, cPlayer & a_Player, cSlotArea * a_ClickedArea, bool a_ShouldApply) override; /** Loads the given Recipe into the crafting grid */ void LoadRecipe(cPlayer & a_Player, UInt32 a_RecipeId); protected: cPlayer & m_Player; }; ================================================ FILE: src/UI/MinecartWithChestWindow.h ================================================ // MinecartWithChestWindow.h // Representing the UI window for the minecart chest entity #pragma once #include "Window.h" #include "../Entities/Minecart.h" class cMinecartWithChestWindow: public cWindow { using Super = cWindow; public: cMinecartWithChestWindow(cMinecartWithChest * a_ChestCart) : cWindow(wtChest, "Minecart with Chest"), m_ChestCart(a_ChestCart) { m_SlotAreas.push_back(new cSlotAreaMinecartWithChest(a_ChestCart, *this)); m_SlotAreas.push_back(new cSlotAreaInventory(*this)); m_SlotAreas.push_back(new cSlotAreaHotBar(*this)); a_ChestCart->GetWorld()->BroadcastSoundEffect("block.chest.open", a_ChestCart->GetPosition(), 1, 1); } virtual void DistributeStack(cItem & a_ItemStack, int a_Slot, cPlayer & a_Player, cSlotArea * a_ClickedArea, bool a_ShouldApply) override { cSlotAreas AreasInOrder; if (a_ClickedArea == m_SlotAreas[0]) { // Chest Area AreasInOrder.push_back(m_SlotAreas[2]); /* Hotbar */ AreasInOrder.push_back(m_SlotAreas[1]); /* Inventory */ Super::DistributeStackToAreas(a_ItemStack, a_Player, AreasInOrder, a_ShouldApply, true); } else { // Hotbar or Inventory AreasInOrder.push_back(m_SlotAreas[0]); /* Chest */ Super::DistributeStackToAreas(a_ItemStack, a_Player, AreasInOrder, a_ShouldApply, false); } } virtual ~cMinecartWithChestWindow() override { m_ChestCart->GetWorld()->BroadcastSoundEffect("block.chest.close", m_ChestCart->GetPosition(), 1, 1); } private: cMinecartWithChest * m_ChestCart; }; ================================================ FILE: src/UI/SlotArea.cpp ================================================ // SlotArea.cpp // Implements the cSlotArea class and its descendants #include "Globals.h" #include "SlotArea.h" #include "../Entities/Player.h" #include "../BlockEntities/BeaconEntity.h" #include "../BlockEntities/BrewingstandEntity.h" #include "../BlockEntities/ChestEntity.h" #include "../BlockEntities/DropSpenserEntity.h" #include "../BlockEntities/EnderChestEntity.h" #include "../BlockEntities/FurnaceEntity.h" #include "../Entities/Minecart.h" #include "../Items/ItemHandler.h" #include "AnvilWindow.h" #include "../CraftingRecipes.h" #include "../Root.h" #include "../FastRandom.h" #include "../BlockArea.h" #include "../EffectID.h" #include "../ClientHandle.h" #include "../Mobs/Horse.h" //////////////////////////////////////////////////////////////////////////////// // cSlotArea: cSlotArea::cSlotArea(int a_NumSlots, cWindow & a_ParentWindow) : m_NumSlots(a_NumSlots), m_ParentWindow(a_ParentWindow) { } void cSlotArea::Clicked(cPlayer & a_Player, int a_SlotNum, eClickAction a_ClickAction, const cItem & a_ClickedItem) { /* LOGD("Slot area with %d slots clicked at slot number %d, clicked item %s, slot item %s", GetNumSlots(), a_SlotNum, ItemToFullString(a_ClickedItem).c_str(), ItemToFullString(*GetSlot(a_SlotNum, a_Player)).c_str() ); */ ASSERT((a_SlotNum >= 0) && (a_SlotNum < GetNumSlots())); bool bAsync = false; if (GetSlot(a_SlotNum, a_Player) == nullptr) { LOGWARNING("GetSlot(%d) returned nullptr! Ignoring click", a_SlotNum); return; } if (a_Player.IsGameModeSpectator()) { // Block the action of the player and make sure, the inventory doesn't get out of sync a_Player.GetClientHandle()->SendInventorySlot(-1, -1, cItem()); // Reset the dragged item SetSlot(a_SlotNum, a_Player, *GetSlot(a_SlotNum, a_Player)); // Update the current slot return; } switch (a_ClickAction) { case caShiftLeftClick: case caShiftRightClick: { ShiftClicked(a_Player, a_SlotNum, a_ClickedItem); return; } case caDblClick: { DblClicked(a_Player, a_SlotNum); return; } case caMiddleClick: { MiddleClicked(a_Player, a_SlotNum); return; } case caDropKey: case caCtrlDropKey: { DropClicked(a_Player, a_SlotNum, (a_ClickAction == caCtrlDropKey)); return; } case caNumber1: case caNumber2: case caNumber3: case caNumber4: case caNumber5: case caNumber6: case caNumber7: case caNumber8: case caNumber9: { NumberClicked(a_Player, a_SlotNum, a_ClickAction); return; } default: { break; } } cItem Slot(*GetSlot(a_SlotNum, a_Player)); if (!Slot.IsSameType(a_ClickedItem)) { LOGWARNING("*** Window lost sync at item %d in SlotArea with %d items ***", a_SlotNum, m_NumSlots); LOGWARNING("My item: %s", ItemToFullString(Slot).c_str()); LOGWARNING("Their item: %s", ItemToFullString(a_ClickedItem).c_str()); bAsync = true; } cItem & DraggingItem = a_Player.GetDraggingItem(); switch (a_ClickAction) { case caRightClick: { if (DraggingItem.m_ItemType <= 0) // Empty-handed? { DraggingItem = Slot.CopyOne(); // Obtain copy of slot to preserve lore, enchantments, etc. DraggingItem.m_ItemCount = static_cast(static_cast(Slot.m_ItemCount) / 2.f + 0.5f); Slot.m_ItemCount -= DraggingItem.m_ItemCount; if (Slot.m_ItemCount <= 0) { Slot.Empty(); } } else if ((Slot.m_ItemType <= 0) || DraggingItem.IsEqual(Slot)) { // Drop one item in slot if ((DraggingItem.m_ItemCount > 0) && (Slot.m_ItemCount < Slot.GetMaxStackSize())) { char OldSlotCount = Slot.m_ItemCount; Slot = DraggingItem.CopyOne(); // See above OldSlotCount++; Slot.m_ItemCount = OldSlotCount; DraggingItem.m_ItemCount--; } if (DraggingItem.m_ItemCount <= 0) { DraggingItem.Empty(); } } else if (!DraggingItem.IsEqual(Slot)) { // Swap contents cItem tmp(DraggingItem); DraggingItem = Slot; Slot = tmp; } break; } case caLeftClick: { // Left-clicked if (!DraggingItem.IsEqual(Slot)) { // Switch contents cItem tmp(DraggingItem); DraggingItem = Slot; Slot = tmp; } else { // Same type, add items: int FreeSlots = DraggingItem.GetMaxStackSize() - Slot.m_ItemCount; if (FreeSlots < 0) { ASSERT(!"Bad item stack size - where did we get more items in a slot than allowed?"); FreeSlots = 0; } char Filling = static_cast((FreeSlots > DraggingItem.m_ItemCount) ? DraggingItem.m_ItemCount : FreeSlots); Slot.m_ItemCount += Filling; DraggingItem.m_ItemCount -= Filling; if (DraggingItem.m_ItemCount <= 0) { DraggingItem.Empty(); } } break; } default: { LOGWARNING("SlotArea: Unhandled click action: %d (%s)", a_ClickAction, ClickActionToString(a_ClickAction)); m_ParentWindow.BroadcastWholeWindow(); return; } } // switch (a_ClickAction SetSlot(a_SlotNum, a_Player, Slot); if (bAsync) { m_ParentWindow.BroadcastWholeWindow(); } } void cSlotArea::ShiftClicked(cPlayer & a_Player, int a_SlotNum, const cItem & a_ClickedItem) { // Make a copy of the slot, distribute it among the other areas, then update the slot to contain the leftover: cItem Slot(*GetSlot(a_SlotNum, a_Player)); m_ParentWindow.DistributeStack(Slot, a_SlotNum, a_Player, this, true); if (Slot.IsEmpty()) { // Empty the slot completely, the client doesn't like left-over ItemType with zero count Slot.Empty(); } SetSlot(a_SlotNum, a_Player, Slot); // Some clients try to guess our actions and not always right (armor slots in 1.2.5), so we fix them: m_ParentWindow.BroadcastWholeWindow(); } void cSlotArea::DblClicked(cPlayer & a_Player, int a_SlotNum) { cItem & Dragging = a_Player.GetDraggingItem(); if (Dragging.IsEmpty()) { // Move the item in the dblclicked slot into hand: Dragging = *GetSlot(a_SlotNum, a_Player); cItem EmptyItem; SetSlot(a_SlotNum, a_Player, EmptyItem); } if (Dragging.IsEmpty()) { LOGD("%s DblClicked with an empty hand over empty slot, ignoring", a_Player.GetName().c_str()); return; } // Add as many items from the surrounding area into hand as possible: // First skip full stacks, then if there's still space, process full stacks as well: if (!m_ParentWindow.CollectItemsToHand(Dragging, *this, a_Player, false)) { m_ParentWindow.CollectItemsToHand(Dragging, *this, a_Player, true); } m_ParentWindow.BroadcastWholeWindow(); // We need to broadcast, in case the window was a chest opened by multiple players } void cSlotArea::MiddleClicked(cPlayer & a_Player, int a_SlotNum) { cItem Slot(*GetSlot(a_SlotNum, a_Player)); cItem & DraggingItem = a_Player.GetDraggingItem(); if (!a_Player.IsGameModeCreative() || Slot.IsEmpty() || !DraggingItem.IsEmpty()) { return; } DraggingItem = Slot; DraggingItem.m_ItemCount = DraggingItem.GetMaxStackSize(); } void cSlotArea::DropClicked(cPlayer & a_Player, int a_SlotNum, bool a_DropStack) { cItem Slot(*GetSlot(a_SlotNum, a_Player)); if (Slot.IsEmpty()) { return; } cItem ItemToDrop = Slot.CopyOne(); if (a_DropStack) { ItemToDrop.m_ItemCount = Slot.m_ItemCount; } Slot.m_ItemCount -= ItemToDrop.m_ItemCount; if (Slot.m_ItemCount <= 0) { Slot.Empty(); } SetSlot(a_SlotNum, a_Player, Slot); a_Player.TossPickup(ItemToDrop); } void cSlotArea::NumberClicked(cPlayer & a_Player, int a_SlotNum, eClickAction a_ClickAction) { if ((a_ClickAction < caNumber1) || (a_ClickAction > caNumber9)) { return; } int HotbarSlot = static_cast(a_ClickAction - caNumber1); cItem ItemInHotbar(a_Player.GetInventory().GetHotbarSlot(HotbarSlot)); cItem ItemInSlot(*GetSlot(a_SlotNum, a_Player)); // The items are equal. Do nothing. if (ItemInHotbar.IsEqual(ItemInSlot)) { return; } a_Player.GetInventory().SetHotbarSlot(HotbarSlot, ItemInSlot); SetSlot(a_SlotNum, a_Player, ItemInHotbar); } void cSlotArea::OnPlayerAdded(cPlayer & a_Player) { UNUSED(a_Player); } void cSlotArea::OnPlayerRemoved(cPlayer & a_Player) { UNUSED(a_Player); } void cSlotArea::DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bool a_ShouldApply, bool a_KeepEmptySlots, bool a_BackFill) { for (int i = 0; i < m_NumSlots; i++) { int SlotNum = (a_BackFill) ? (m_NumSlots - 1 - i) : i; const cItem * Slot = GetSlot(SlotNum, a_Player); if (!Slot->IsEqual(a_ItemStack) && (!Slot->IsEmpty() || a_KeepEmptySlots)) { // Different items continue; } char NumFit = Slot->GetMaxStackSize() - Slot->m_ItemCount; if (NumFit <= 0) { // Full stack already continue; } NumFit = std::min(NumFit, a_ItemStack.m_ItemCount); if (a_ShouldApply) { cItem NewSlot(a_ItemStack); NewSlot.m_ItemCount = Slot->m_ItemCount + NumFit; SetSlot(SlotNum, a_Player, NewSlot); } a_ItemStack.m_ItemCount -= NumFit; if (a_ItemStack.IsEmpty()) { return; } } // for i - Slots } bool cSlotArea::CollectItemsToHand(cItem & a_Dragging, cPlayer & a_Player, bool a_CollectFullStacks) { int NumSlots = GetNumSlots(); for (int i = 0; i < NumSlots; i++) { const cItem & SlotItem = *GetSlot(i, a_Player); if (!SlotItem.IsEqual(a_Dragging)) { continue; } char ToMove = a_Dragging.GetMaxStackSize() - a_Dragging.m_ItemCount; if (ToMove > SlotItem.m_ItemCount) { ToMove = SlotItem.m_ItemCount; } a_Dragging.m_ItemCount += ToMove; cItem NewSlot(SlotItem); NewSlot.m_ItemCount -= ToMove; SetSlot(i, a_Player, NewSlot); if (!NewSlot.IsEmpty()) { // There are leftovers in the slot, so a_Dragging must be full return true; } } // for i - Slots[] // a_Dragging may be full if there were exactly the number of items needed to fill it return a_Dragging.IsFullStack(); } //////////////////////////////////////////////////////////////////////////////// // cSlotAreaChest: cSlotAreaChest::cSlotAreaChest(cChestEntity * a_Chest, cWindow & a_ParentWindow) : cSlotArea(27, a_ParentWindow), m_Chest(a_Chest) { } const cItem * cSlotAreaChest::GetSlot(int a_SlotNum, cPlayer & a_Player) const { // a_SlotNum ranges from 0 to 26, use that to index the chest entity's inventory directly: return &(m_Chest->GetSlot(a_SlotNum)); } void cSlotAreaChest::SetSlot(int a_SlotNum, cPlayer & a_Player, const cItem & a_Item) { m_Chest->SetSlot(a_SlotNum, a_Item); } //////////////////////////////////////////////////////////////////////////////// // cSlotAreaDoubleChest: cSlotAreaDoubleChest::cSlotAreaDoubleChest(cChestEntity * a_TopChest, cChestEntity * a_BottomChest, cWindow & a_ParentWindow) : cSlotArea(54, a_ParentWindow), m_TopChest(a_TopChest), m_BottomChest(a_BottomChest) { } const cItem * cSlotAreaDoubleChest::GetSlot(int a_SlotNum, cPlayer & a_Player) const { // a_SlotNum ranges from 0 to 53, use that to index the correct chest's inventory: if (a_SlotNum < 27) { return &(m_TopChest->GetSlot(a_SlotNum)); } else { return &(m_BottomChest->GetSlot(a_SlotNum - 27)); } } void cSlotAreaDoubleChest::SetSlot(int a_SlotNum, cPlayer & a_Player, const cItem & a_Item) { if (a_SlotNum < 27) { m_TopChest->SetSlot(a_SlotNum, a_Item); } else { m_BottomChest->SetSlot(a_SlotNum - 27, a_Item); } } //////////////////////////////////////////////////////////////////////////////// // cSlotAreaCrafting: cSlotAreaCrafting::cSlotAreaCrafting(int a_GridSize, cWindow & a_ParentWindow) : cSlotAreaTemporary(1 + a_GridSize * a_GridSize, a_ParentWindow), m_GridSize(a_GridSize) { ASSERT((a_GridSize == 2) || (a_GridSize == 3)); } void cSlotAreaCrafting::Clicked(cPlayer & a_Player, int a_SlotNum, eClickAction a_ClickAction, const cItem & a_ClickedItem) { if (a_ClickAction == caMiddleClick) { MiddleClicked(a_Player, a_SlotNum); return; } // Override for craft result slot if (a_SlotNum == 0) { if ((a_ClickAction == caShiftLeftClick) || (a_ClickAction == caShiftRightClick)) { ShiftClickedResult(a_Player); } else if ((a_ClickAction == caDropKey) || (a_ClickAction == caCtrlDropKey)) { DropClickedResult(a_Player); } else { ClickedResult(a_Player); } return; } Super::Clicked(a_Player, a_SlotNum, a_ClickAction, a_ClickedItem); UpdateRecipe(a_Player); } void cSlotAreaCrafting::DblClicked(cPlayer & a_Player, int a_SlotNum) { if (a_SlotNum == 0) { // Dbl-clicking the crafting result slot shouldn't collect items to hand return; } Super::DblClicked(a_Player, a_SlotNum); } void cSlotAreaCrafting::OnPlayerRemoved(cPlayer & a_Player) { // Toss all items on the crafting grid: TossItems(a_Player, 1, m_NumSlots); // Remove the current recipe from the player -> recipe map: for (cRecipeMap::iterator itr = m_Recipes.begin(), end = m_Recipes.end(); itr != end; ++itr) { if (itr->first == a_Player.GetUniqueID()) { // Remove the player from the recipe map: m_Recipes.erase(itr); return; } } // for itr - m_Recipes[] // Player not found - that is acceptable } void cSlotAreaCrafting::SetSlot(int a_SlotNum, cPlayer & a_Player, const cItem & a_Item) { // Update the recipe after setting the slot, if the slot is not the result slot: Super::SetSlot(a_SlotNum, a_Player, a_Item); if (a_SlotNum != 0) { UpdateRecipe(a_Player); } } void cSlotAreaCrafting::DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bool a_ShouldApply, bool a_KeepEmptySlots, bool a_BackFill) { UNUSED(a_ItemStack); UNUSED(a_Player); UNUSED(a_ShouldApply); UNUSED(a_KeepEmptySlots); UNUSED(a_BackFill); } void cSlotAreaCrafting::ClickedResult(cPlayer & a_Player) { cItem & DraggingItem = a_Player.GetDraggingItem(); // Get the current recipe: cCraftingRecipe & Recipe = GetRecipeForPlayer(a_Player); const cItem & Result = Recipe.GetResult(); cItem * PlayerSlots = GetPlayerSlots(a_Player) + 1; cCraftingGrid Grid(PlayerSlots, m_GridSize, m_GridSize); // If possible, craft: if (DraggingItem.IsEmpty()) { DraggingItem = Result; Recipe.ConsumeIngredients(Grid); Grid.CopyToItems(PlayerSlots); HandleCraftItem(Result, a_Player); } else if (DraggingItem.IsEqual(Result)) { if (DraggingItem.m_ItemCount + Result.m_ItemCount <= Result.GetMaxStackSize()) { DraggingItem.m_ItemCount += Result.m_ItemCount; Recipe.ConsumeIngredients(Grid); Grid.CopyToItems(PlayerSlots); HandleCraftItem(Result, a_Player); } } // Get the new recipe and update the result slot: UpdateRecipe(a_Player); // We're done. Send all changes to the client and bail out: m_ParentWindow.BroadcastWholeWindow(); } void cSlotAreaCrafting::ShiftClickedResult(cPlayer & a_Player) { cItem Result(*GetSlot(0, a_Player)); if (Result.IsEmpty()) { return; } a_Player.AddKnownItem(Result); cItem * PlayerSlots = GetPlayerSlots(a_Player) + 1; for (;;) { // Try distributing the result. If it fails, bail out: cItem ResultCopy(Result); m_ParentWindow.DistributeStack(ResultCopy, 0, a_Player, this, false); if (!ResultCopy.IsEmpty()) { // Couldn't distribute all of it. Bail out return; } // Distribute the result, this time for real: ResultCopy = Result; m_ParentWindow.DistributeStack(ResultCopy, 0, a_Player, this, true); // Remove the ingredients from the crafting grid and update the recipe: cCraftingRecipe & Recipe = GetRecipeForPlayer(a_Player); cCraftingGrid Grid(PlayerSlots, m_GridSize, m_GridSize); Recipe.ConsumeIngredients(Grid); Grid.CopyToItems(PlayerSlots); UpdateRecipe(a_Player); // Broadcast the window, we sometimes move items to different locations than Vanilla, causing needless desyncs: m_ParentWindow.BroadcastWholeWindow(); // Added achievements processing HandleCraftItem(Result, a_Player); // If the recipe has changed, bail out: if (!Recipe.GetResult().IsEqual(Result)) { return; } } } void cSlotAreaCrafting::DropClickedResult(cPlayer & a_Player) { // Get the current recipe: cCraftingRecipe & Recipe = GetRecipeForPlayer(a_Player); const cItem & Result = Recipe.GetResult(); cItem * PlayerSlots = GetPlayerSlots(a_Player) + 1; cCraftingGrid Grid(PlayerSlots, m_GridSize, m_GridSize); a_Player.TossPickup(Result); Recipe.ConsumeIngredients(Grid); Grid.CopyToItems(PlayerSlots); HandleCraftItem(Result, a_Player); UpdateRecipe(a_Player); } void cSlotAreaCrafting::UpdateRecipe(cPlayer & a_Player) { cCraftingGrid Grid(GetPlayerSlots(a_Player) + 1, m_GridSize, m_GridSize); cCraftingRecipe & Recipe = GetRecipeForPlayer(a_Player); cRoot::Get()->GetCraftingRecipes()->GetRecipe(a_Player, Grid, Recipe); SetSlot(0, a_Player, Recipe.GetResult()); } cCraftingRecipe & cSlotAreaCrafting::GetRecipeForPlayer(cPlayer & a_Player) { for (cRecipeMap::iterator itr = m_Recipes.begin(), end = m_Recipes.end(); itr != end; ++itr) { if (itr->first == a_Player.GetUniqueID()) { return itr->second; } } // for itr - m_Recipes[] // Not found. Add a new one: cCraftingGrid Grid(GetPlayerSlots(a_Player) + 1, m_GridSize, m_GridSize); cCraftingRecipe Recipe(Grid); cRoot::Get()->GetCraftingRecipes()->GetRecipe(a_Player, Grid, Recipe); m_Recipes.emplace_back(a_Player.GetUniqueID(), Recipe); return m_Recipes.back().second; } void cSlotAreaCrafting::HandleCraftItem(const cItem & a_Result, cPlayer & a_Player) { switch (a_Result.m_ItemType) { case E_BLOCK_WORKBENCH: a_Player.AwardAchievement(CustomStatistic::AchBuildWorkBench); break; case E_BLOCK_FURNACE: a_Player.AwardAchievement(CustomStatistic::AchBuildFurnace); break; case E_BLOCK_CAKE: a_Player.AwardAchievement(CustomStatistic::AchBakeCake); break; case E_BLOCK_ENCHANTMENT_TABLE: a_Player.AwardAchievement(CustomStatistic::AchEnchantments); break; case E_BLOCK_BOOKCASE: a_Player.AwardAchievement(CustomStatistic::AchBookcase); break; case E_ITEM_WOODEN_PICKAXE: a_Player.AwardAchievement(CustomStatistic::AchBuildPickaxe); break; case E_ITEM_WOODEN_SWORD: a_Player.AwardAchievement(CustomStatistic::AchBuildSword); break; case E_ITEM_STONE_PICKAXE: a_Player.AwardAchievement(CustomStatistic::AchBuildBetterPickaxe); break; case E_ITEM_WOODEN_HOE: a_Player.AwardAchievement(CustomStatistic::AchBuildHoe); break; case E_ITEM_BREAD: a_Player.AwardAchievement(CustomStatistic::AchMakeBread); break; default: break; } } void cSlotAreaCrafting::LoadRecipe(cPlayer & a_Player, UInt32 a_RecipeId) { if (a_RecipeId == 0) { return; } auto Recipe = cRoot::Get()->GetCraftingRecipes()->GetRecipeById(a_RecipeId); int NumItems = 0; ClearCraftingGrid(a_Player); for (auto itrS = Recipe->m_Ingredients.begin(); itrS != Recipe->m_Ingredients.end(); ++itrS) { cItem * FoundItem = a_Player.GetInventory().FindItem(itrS->m_Item); if (FoundItem == nullptr) { ClearCraftingGrid(a_Player); break; } cItem Item = FoundItem->CopyOne(); ++NumItems; int pos = 1 + itrS->x + m_GridSize * itrS->y; // Assuming there are ether shaped or unshaped recipes, no mixed ones if ((itrS->x == -1) && (itrS->y == -1)) { pos = NumItems; } // Handle x wildcard else if (itrS->x == -1) { for (int i = 0; i < m_GridSize; i++) { pos = 1 + i + m_GridSize * itrS->y; auto itemCheck = GetSlot(pos, a_Player); if (itemCheck->IsEmpty()) { break; } } } SetSlot(pos, a_Player, Item); a_Player.GetInventory().RemoveItem(Item); } } void cSlotAreaCrafting::ClearCraftingGrid(cPlayer & a_Player) { for (int pos = 1; pos <= m_GridSize * m_GridSize; pos++) { auto Item = GetSlot(pos, a_Player); if (Item->m_ItemCount > 0) { a_Player.GetInventory().AddItem(*Item); SetSlot(pos, a_Player, cItem()); } } } //////////////////////////////////////////////////////////////////////////////// // cSlotAreaAnvil: cSlotAreaAnvil::cSlotAreaAnvil(cWindow & a_ParentWindow) : cSlotAreaTemporary(3, a_ParentWindow), m_MaximumCost(0), m_StackSizeToBeUsedInRepair(0) { } void cSlotAreaAnvil::Clicked(cPlayer & a_Player, int a_SlotNum, eClickAction a_ClickAction, const cItem & a_ClickedItem) { ASSERT((a_SlotNum >= 0) && (a_SlotNum < GetNumSlots())); if (a_SlotNum != 2) { Super::Clicked(a_Player, a_SlotNum, a_ClickAction, a_ClickedItem); UpdateResult(a_Player); return; } bool bAsync = false; if (GetSlot(a_SlotNum, a_Player) == nullptr) { LOGWARNING("GetSlot(%d) returned nullptr! Ignoring click", a_SlotNum); return; } switch (a_ClickAction) { case caDblClick: { return; } case caShiftLeftClick: case caShiftRightClick: { ShiftClicked(a_Player, a_SlotNum, a_ClickedItem); return; } case caMiddleClick: { MiddleClicked(a_Player, a_SlotNum); return; } case caDropKey: case caCtrlDropKey: { if (CanTakeResultItem(a_Player)) { DropClicked(a_Player, a_SlotNum, true); OnTakeResult(a_Player); } return; } default: { break; } } cItem Slot(*GetSlot(a_SlotNum, a_Player)); if (!Slot.IsSameType(a_ClickedItem)) { LOGWARNING("*** Window lost sync at item %d in SlotArea with %d items ***", a_SlotNum, m_NumSlots); LOGWARNING("My item: %s", ItemToFullString(Slot).c_str()); LOGWARNING("Their item: %s", ItemToFullString(a_ClickedItem).c_str()); bAsync = true; } cItem & DraggingItem = a_Player.GetDraggingItem(); if (Slot.IsEmpty()) { return; } if (!DraggingItem.IsEmpty()) { if (!(DraggingItem.IsEqual(Slot) && ((DraggingItem.m_ItemCount + Slot.m_ItemCount) <= Slot.GetMaxStackSize()))) { return; } } if (!CanTakeResultItem(a_Player)) { return; } cItem NewItem = cItem(Slot); NewItem.m_ItemCount += DraggingItem.m_ItemCount; Slot.Empty(); DraggingItem.Empty(); SetSlot(a_SlotNum, a_Player, Slot); DraggingItem = NewItem; OnTakeResult(a_Player); if (bAsync) { m_ParentWindow.BroadcastWholeWindow(); } } void cSlotAreaAnvil::ShiftClicked(cPlayer & a_Player, int a_SlotNum, const cItem & a_ClickedItem) { if (a_SlotNum != 2) { Super::ShiftClicked(a_Player, a_SlotNum, a_ClickedItem); UpdateResult(a_Player); return; } // Make a copy of the slot, distribute it among the other areas, then update the slot to contain the leftover: cItem Slot(*GetSlot(a_SlotNum, a_Player)); if (Slot.IsEmpty() || !CanTakeResultItem(a_Player)) { return; } m_ParentWindow.DistributeStack(Slot, a_SlotNum, a_Player, this, true); if (Slot.IsEmpty()) { Slot.Empty(); OnTakeResult(a_Player); } SetSlot(a_SlotNum, a_Player, Slot); // Some clients try to guess our actions and not always right (armor slots in 1.2.5), so we fix them: m_ParentWindow.BroadcastWholeWindow(); } void cSlotAreaAnvil::DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bool a_ShouldApply, bool a_KeepEmptySlots, bool a_BackFill) { for (int i = 0; i < 2; i++) { int SlotNum = (a_BackFill) ? (2 - 1 - i) : i; const cItem * Slot = GetSlot(SlotNum, a_Player); if (!Slot->IsEqual(a_ItemStack) && (!Slot->IsEmpty() || a_KeepEmptySlots)) { // Different items continue; } char NumFit = Slot->GetMaxStackSize() - Slot->m_ItemCount; if (NumFit <= 0) { // Full stack already continue; } NumFit = std::min(NumFit, a_ItemStack.m_ItemCount); if (a_ShouldApply) { cItem NewSlot(a_ItemStack); NewSlot.m_ItemCount = Slot->m_ItemCount + NumFit; SetSlot(SlotNum, a_Player, NewSlot); } a_ItemStack.m_ItemCount -= NumFit; if (a_ItemStack.IsEmpty()) { UpdateResult(a_Player); return; } } // for i - Slots UpdateResult(a_Player); } void cSlotAreaAnvil::OnTakeResult(cPlayer & a_Player) { if (!a_Player.IsGameModeCreative()) { a_Player.DeltaExperience(-cPlayer::XpForLevel(m_MaximumCost)); } SetSlot(0, a_Player, cItem()); if (m_StackSizeToBeUsedInRepair > 0) { const cItem * Item = GetSlot(1, a_Player); if (!Item->IsEmpty() && (Item->m_ItemCount > m_StackSizeToBeUsedInRepair)) { cItem NewSecondItem(*Item); NewSecondItem.m_ItemCount -= m_StackSizeToBeUsedInRepair; m_StackSizeToBeUsedInRepair = 0; SetSlot(1, a_Player, NewSecondItem); } else { SetSlot(1, a_Player, cItem()); } } else { SetSlot(1, a_Player, cItem()); } m_ParentWindow.SetProperty(0, static_cast(m_MaximumCost)); m_MaximumCost = 0; static_cast(m_ParentWindow).SetRepairedItemName("", nullptr); const Vector3i BlockPos = static_cast(m_ParentWindow).GetBlockPos(); BLOCKTYPE Block; NIBBLETYPE BlockMeta; if ( a_Player.GetWorld()->GetBlockTypeMeta(BlockPos, Block, BlockMeta) && !a_Player.IsGameModeCreative() && (Block == E_BLOCK_ANVIL) && GetRandomProvider().RandBool(0.12) ) { NIBBLETYPE Orientation = BlockMeta & 0x3; NIBBLETYPE AnvilDamage = BlockMeta >> 2; ++AnvilDamage; if (AnvilDamage > 2) { // Anvil will break a_Player.GetWorld()->SetBlock(BlockPos, E_BLOCK_AIR, 0); a_Player.GetWorld()->BroadcastSoundParticleEffect(EffectID::SFX_RANDOM_ANVIL_BREAK, BlockPos, 0); a_Player.CloseWindow(false); } else { a_Player.GetWorld()->SetBlockMeta(BlockPos, static_cast(Orientation | (AnvilDamage << 2))); a_Player.GetWorld()->BroadcastSoundParticleEffect(EffectID::SFX_RANDOM_ANVIL_USE, BlockPos, 0); } } else { a_Player.GetWorld()->BroadcastSoundParticleEffect(EffectID::SFX_RANDOM_ANVIL_USE, BlockPos, 0); } } bool cSlotAreaAnvil::CanTakeResultItem(cPlayer & a_Player) { return ( ( a_Player.IsGameModeCreative() || // Is the player in gamemode? (a_Player.GetXpLevel() >= m_MaximumCost) // or the player have enough exp? ) && (!GetSlot(2, a_Player)->IsEmpty()) && // Is a item in the result slot? (m_MaximumCost > 0) // When no maximum cost is set, the item isn't set from the UpdateResult() method and can't be a valid enchanting result. ); } void cSlotAreaAnvil::OnPlayerRemoved(cPlayer & a_Player) { TossItems(a_Player, 0, 2); Super::OnPlayerRemoved(a_Player); } void cSlotAreaAnvil::UpdateResult(cPlayer & a_Player) { const cItem Target(*GetSlot(0, a_Player)); const cItem Sacrifice(*GetSlot(1, a_Player)); // Output initialised as copy of target. cItem Output(Target); if (Target.IsEmpty()) { Output.Empty(); SetSlot(2, a_Player, Output); m_ParentWindow.SetProperty(0, 0); m_MaximumCost = 0; return; } m_MaximumCost = 0; m_StackSizeToBeUsedInRepair = 0; int RepairCost = Target.m_RepairCost; int NeedExp = 0; if (!Sacrifice.IsEmpty()) { RepairCost += Sacrifice.m_RepairCost; // Can we repair with sacrifce material? if (Target.IsDamageable() && Target.GetHandler().CanRepairWithRawMaterial(Sacrifice.m_ItemType)) { // Tool and armor repair with special item (iron / gold / diamond / ...) int DamageDiff = std::min(static_cast(Target.m_ItemDamage), static_cast(Target.GetMaxDamage()) / 4); if (DamageDiff <= 0) { // No enchantment Output.Empty(); SetSlot(2, a_Player, Output); m_ParentWindow.SetProperty(0, 0); m_MaximumCost = 0; return; } char NumItemsConsumed = 0; // Repair until out of materials, or fully repaired: while ((DamageDiff > 0) && (NumItemsConsumed < Sacrifice.m_ItemCount)) { Output.m_ItemDamage -= static_cast(DamageDiff); NeedExp += std::max(1, DamageDiff / 100) + static_cast(Target.m_Enchantments.Count()); DamageDiff = std::min(static_cast(Output.m_ItemDamage), static_cast(Target.GetMaxDamage()) / 4); ++NumItemsConsumed; } m_StackSizeToBeUsedInRepair = NumItemsConsumed; } else // Combining tools / armour { const bool IsEnchantBook = (Sacrifice.m_ItemType == E_ITEM_ENCHANTED_BOOK); // No result if we can't combine the items if (!IsEnchantBook && (!Target.IsSameType(Sacrifice) || !Target.IsDamageable())) { // No enchantment Output.Empty(); SetSlot(2, a_Player, Output); m_ParentWindow.SetProperty(0, 0); m_MaximumCost = 0; return; } // Can we repair with sacrifice tool / armour? if (Target.IsDamageable() && !IsEnchantBook && (Target.m_ItemDamage!=0)) { // Durability = MaxDamage - m_ItemDamage = how far from broken const short TargetDurability = Target.GetMaxDamage() - Target.m_ItemDamage; const short SacrificeDurability = Sacrifice.GetMaxDamage() - Sacrifice.m_ItemDamage; // How much durability to repair by. const short RepairDurability = SacrificeDurability + Target.GetMaxDamage() * 12 / 100; // Don't give item a negative damage: short NewItemDamage = std::max(Target.GetMaxDamage() - (TargetDurability + RepairDurability), 0); if (NewItemDamage < Target.m_ItemDamage) { Output.m_ItemDamage = NewItemDamage; NeedExp += std::max(1, RepairDurability / 100); } } // Add the enchantments from the sacrifice to the target int EnchantmentCost = Output.AddEnchantmentsFromItem(Sacrifice); NeedExp += EnchantmentCost; } } int NameChangeExp = 0; const AString & RepairedItemName = static_cast(&m_ParentWindow)->GetRepairedItemName(); if (RepairedItemName.empty()) { // Remove custom name if (!Target.m_CustomName.empty()) { NameChangeExp = (Target.IsDamageable()) ? 7 : (Target.m_ItemCount * 5); NeedExp += NameChangeExp; Output.m_CustomName = ""; } } else if (RepairedItemName != Target.m_CustomName) { // Change custom name NameChangeExp = (Target.IsDamageable()) ? 7 : (Target.m_ItemCount * 5); NeedExp += NameChangeExp; if (!Target.m_CustomName.empty()) { RepairCost += NameChangeExp / 2; } Output.m_CustomName = RepairedItemName; } m_MaximumCost = RepairCost + NeedExp; if (NeedExp < 0) { Output.Empty(); } if ((NameChangeExp == NeedExp) && (NameChangeExp > 0) && (m_MaximumCost >= 40)) { m_MaximumCost = 39; } if ((m_MaximumCost >= 40) && !a_Player.IsGameModeCreative()) { Output.Empty(); } if (!Output.IsEmpty()) { RepairCost = std::max(Target.m_RepairCost, Sacrifice.m_RepairCost); if (!Output.m_CustomName.empty()) { RepairCost -= 9; } RepairCost = std::max(RepairCost, 0); RepairCost += 2; Output.m_RepairCost = RepairCost; } // If after everything, output will be the same then no point enchanting: if (Target.IsEqual(Output)) { Output.Empty(); m_MaximumCost = 0; } SetSlot(2, a_Player, Output); m_ParentWindow.SetProperty(0, static_cast(m_MaximumCost)); } //////////////////////////////////////////////////////////////////////////////// // cSlotAreaBeacon: cSlotAreaBeacon::cSlotAreaBeacon(cBeaconEntity * a_Beacon, cWindow & a_ParentWindow) : cSlotArea(1, a_ParentWindow), m_Beacon(a_Beacon) { m_Beacon->GetContents().AddListener(*this); } cSlotAreaBeacon::~cSlotAreaBeacon() { m_Beacon->GetContents().RemoveListener(*this); } bool cSlotAreaBeacon::IsPlaceableItem(short a_ItemType) { switch (a_ItemType) { case E_ITEM_EMERALD: case E_ITEM_DIAMOND: case E_ITEM_GOLD: case E_ITEM_IRON: { return true; } default: { return false; } } } void cSlotAreaBeacon::Clicked(cPlayer & a_Player, int a_SlotNum, eClickAction a_ClickAction, const cItem & a_ClickedItem) { ASSERT((a_SlotNum >= 0) && (a_SlotNum < GetNumSlots())); bool bAsync = false; if (GetSlot(a_SlotNum, a_Player) == nullptr) { LOGWARNING("GetSlot(%d) returned nullptr! Ignoring click", a_SlotNum); return; } switch (a_ClickAction) { case caShiftLeftClick: case caShiftRightClick: { ShiftClicked(a_Player, a_SlotNum, a_ClickedItem); return; } case caMiddleClick: { MiddleClicked(a_Player, a_SlotNum); return; } case caDropKey: case caCtrlDropKey: { DropClicked(a_Player, a_SlotNum, false); return; } case caNumber1: case caNumber2: case caNumber3: case caNumber4: case caNumber5: case caNumber6: case caNumber7: case caNumber8: case caNumber9: { NumberClicked(a_Player, a_SlotNum, a_ClickAction); return; } default: { break; } } cItem Slot(*GetSlot(a_SlotNum, a_Player)); if (!Slot.IsSameType(a_ClickedItem)) { LOGWARNING("*** Window lost sync at item %d in SlotArea with %d items ***", a_SlotNum, m_NumSlots); LOGWARNING("My item: %s", ItemToFullString(Slot).c_str()); LOGWARNING("Their item: %s", ItemToFullString(a_ClickedItem).c_str()); bAsync = true; } cItem & DraggingItem = a_Player.GetDraggingItem(); if (DraggingItem.IsEmpty()) { DraggingItem = Slot; Slot.Empty(); } else if (Slot.IsEmpty()) { if (!IsPlaceableItem(DraggingItem.m_ItemType)) { return; } Slot = DraggingItem.CopyOne(); DraggingItem.m_ItemCount -= 1; if (DraggingItem.m_ItemCount <= 0) { DraggingItem.Empty(); } } else if (DraggingItem.m_ItemCount == 1) { if (!IsPlaceableItem(DraggingItem.m_ItemCount)) { return; } // Switch contents cItem tmp(DraggingItem); DraggingItem = Slot; Slot = tmp; } SetSlot(a_SlotNum, a_Player, Slot); if (bAsync) { m_ParentWindow.BroadcastWholeWindow(); } } void cSlotAreaBeacon::DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bool a_ShouldApply, bool a_KeepEmptySlots, bool a_BackFill) { const cItem * Slot = GetSlot(0, a_Player); if (!Slot->IsEmpty() || !IsPlaceableItem(a_ItemStack.m_ItemType) || (a_ItemStack.m_ItemCount != 1)) { return; } if (a_ShouldApply) { SetSlot(0, a_Player, a_ItemStack.CopyOne()); } a_ItemStack.Empty(); } const cItem * cSlotAreaBeacon::GetSlot(int a_SlotNum, cPlayer & a_Player) const { UNUSED(a_Player); return &(m_Beacon->GetSlot(a_SlotNum)); } void cSlotAreaBeacon::SetSlot(int a_SlotNum, cPlayer & a_Player, const cItem & a_Item) { UNUSED(a_Player); m_Beacon->SetSlot(a_SlotNum, a_Item); } void cSlotAreaBeacon::OnSlotChanged(cItemGrid * a_ItemGrid, int a_SlotNum) { UNUSED(a_SlotNum); // Something has changed in the window, broadcast the entire window to all clients ASSERT(a_ItemGrid == &(m_Beacon->GetContents())); m_ParentWindow.BroadcastWholeWindow(); } //////////////////////////////////////////////////////////////////////////////// // cSlotAreaEnchanting: cSlotAreaEnchanting::cSlotAreaEnchanting(cWindow & a_ParentWindow, Vector3i a_BlockPos) : cSlotAreaTemporary(2, a_ParentWindow), m_BlockPos(a_BlockPos) { } void cSlotAreaEnchanting::Clicked(cPlayer & a_Player, int a_SlotNum, eClickAction a_ClickAction, const cItem & a_ClickedItem) { ASSERT((a_SlotNum >= 0) && (a_SlotNum < GetNumSlots())); bool bAsync = false; if (GetSlot(a_SlotNum, a_Player) == nullptr) { LOGWARNING("GetSlot(%d) returned nullptr! Ignoring click", a_SlotNum); return; } switch (a_ClickAction) { case caShiftLeftClick: case caShiftRightClick: { ShiftClicked(a_Player, a_SlotNum, a_ClickedItem); return; } case caDblClick: { DblClicked(a_Player, a_SlotNum); return; } case caMiddleClick: { MiddleClicked(a_Player, a_SlotNum); return; } case caDropKey: case caCtrlDropKey: { DropClicked(a_Player, a_SlotNum, false); return; } case caNumber1: case caNumber2: case caNumber3: case caNumber4: case caNumber5: case caNumber6: case caNumber7: case caNumber8: case caNumber9: { NumberClicked(a_Player, a_SlotNum, a_ClickAction); return; } default: { break; } } cItem Slot(*GetSlot(a_SlotNum, a_Player)); if (!Slot.IsSameType(a_ClickedItem)) { LOGWARNING("*** Window lost sync at item %d in SlotArea with %d items ***", a_SlotNum, m_NumSlots); LOGWARNING("My item: %s", ItemToFullString(Slot).c_str()); LOGWARNING("Their item: %s", ItemToFullString(a_ClickedItem).c_str()); bAsync = true; } cItem & DraggingItem = a_Player.GetDraggingItem(); if (a_SlotNum == 1) { // Lapis slot can have a full stack handle it normally, also check for empty hand if ((DraggingItem.IsEmpty()) || ((DraggingItem.m_ItemType == E_ITEM_DYE) && (DraggingItem.m_ItemDamage == E_META_DYE_BLUE))) { return cSlotArea::Clicked(a_Player, a_SlotNum, a_ClickAction, a_ClickedItem); } if (bAsync) { m_ParentWindow.BroadcastWholeWindow(); } return; } // Slot 0 is where the item to enhance goes. if (DraggingItem.IsEmpty()) { // DraggingItem is empty -> Switch draggingitem and slot if (!Slot.IsEmpty()) { std::swap(DraggingItem, Slot); } } else if (Slot.IsEmpty()) { // DraggingItem isn't empty and slot is empty -> Set one dragging item in the slot Slot = DraggingItem.CopyOne(); DraggingItem.m_ItemCount -= 1; if (DraggingItem.m_ItemCount <= 0) { DraggingItem.Empty(); } } else if ((DraggingItem.m_ItemCount == 1) && !DraggingItem.IsEqual(Slot)) { // DraggingItem and slot aren't empty -> Switch items std::swap(DraggingItem, Slot); } SetSlot(a_SlotNum, a_Player, Slot); if (bAsync) { m_ParentWindow.BroadcastWholeWindow(); } } void cSlotAreaEnchanting::DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bool a_Apply, bool a_KeepEmptySlots, bool a_BackFill) { if ((a_ItemStack.m_ItemType == E_ITEM_DYE) && (a_ItemStack.m_ItemDamage == E_META_DYE_BLUE)) { // It's lapis, put it in the lapis spot. const cItem * Slot = GetSlot(1, a_Player); char NumFit = Slot->GetMaxStackSize() - Slot->m_ItemCount; if (NumFit <= 0) { // Full stack already return; } NumFit = std::min(NumFit, a_ItemStack.m_ItemCount); if (a_Apply) { cItem NewSlot(a_ItemStack); NewSlot.m_ItemCount = Slot->m_ItemCount + NumFit; SetSlot(1, a_Player, NewSlot); } a_ItemStack.m_ItemCount -= NumFit; // Return so we don't put overflow into the enchantment slot return; } const cItem * Slot = GetSlot(0, a_Player); if (!Slot->IsEmpty()) { return; } if (a_Apply) { SetSlot(0, a_Player, a_ItemStack.CopyOne()); } a_ItemStack.m_ItemCount -= 1; if (a_ItemStack.m_ItemCount <= 0) { a_ItemStack.Empty(); } } void cSlotAreaEnchanting::OnPlayerAdded(cPlayer & a_Player) { Super::OnPlayerAdded(a_Player); UpdateResult(a_Player); } void cSlotAreaEnchanting::OnPlayerRemoved(cPlayer & a_Player) { // Toss the item in the enchanting slot, as well as lapis TossItems(a_Player, 0, m_NumSlots); Super::OnPlayerRemoved(a_Player); } void cSlotAreaEnchanting::SetSlot(int a_SlotNum, cPlayer & a_Player, const cItem & a_Item) { Super::SetSlot(a_SlotNum, a_Player, a_Item); UpdateResult(a_Player); } void cSlotAreaEnchanting::UpdateResult(cPlayer & a_Player) { cItem Item = *GetSlot(0, a_Player); if (!cItem::IsEnchantable(Item.m_ItemType) || !Item.m_Enchantments.IsEmpty()) { return; } // Pseudocode found at: https://minecraft.wiki/w/Enchanting_mechanics const auto Bookshelves = std::min(GetBookshelvesCount(*a_Player.GetWorld()), 15U); // A PRNG initialised using the player's enchantment seed. auto Random = a_Player.GetEnchantmentRandomProvider(); // Calculate the levels for the offered enchantment options: const auto Base = (Random.RandInt(1U, 8U) + (Bookshelves / 2) + Random.RandInt(0U, Bookshelves)); const std::array OptionLevels { std::max(Base / 3, 1U), (Base * 2) / 3 + 1, std::max(Base, Bookshelves * 2) }; // Properties set according to: https://wiki.vg/Protocol#Window_Property // Fake a "seed" for the client to draw Standard Galactic Alphabet glyphs: m_ParentWindow.SetProperty(3, Random.RandInt()); // Calculate an enchanting possibility for each option (top, middle and bottom) and send details to window: for (size_t i = 0; i != OptionLevels.size(); i++) { // A copy of the item. cItem EnchantedItem = Item.CopyOne(); // Enchant based on the number of levels: EnchantedItem.EnchantByXPLevels(OptionLevels[i], Random); LOGD("Generated enchanted item %d with enchantments: %s", i, EnchantedItem.m_Enchantments.ToString()); // Send the level requirement for the enchantment option: m_ParentWindow.SetProperty(i, static_cast(OptionLevels[i])); // Get the first enchantment ID, which must exist: ASSERT(EnchantedItem.m_Enchantments.begin() != EnchantedItem.m_Enchantments.end()); const auto EnchantmentID = static_cast(EnchantedItem.m_Enchantments.begin()->first); // Send the enchantment ID of the first enchantment on our item: m_ParentWindow.SetProperty(4 + i, EnchantmentID); const auto EnchantmentLevel = static_cast(EnchantedItem.m_Enchantments.GetLevel(EnchantmentID)); ASSERT(EnchantmentLevel > 0); // Send the level for the first enchantment on our item: m_ParentWindow.SetProperty(7 + i, EnchantmentLevel); // Store the item we've enchanted as an option to be retrieved later: m_EnchantedItemOptions[i] = std::move(EnchantedItem); } } unsigned cSlotAreaEnchanting::GetBookshelvesCount(cWorld & a_World) { cBlockArea Area; Area.Read(a_World, m_BlockPos - Vector3i(2, 0, 2), m_BlockPos + Vector3i(2, 1, 2)); static const struct { int m_BookX, m_BookY, m_BookZ; // Coords to check for bookcases int m_AirX, m_AirY, m_AirZ; // Coords to check for air; if not air, the bookcase won't be counted } CheckCoords[] = { { 0, 0, 0, 1, 0, 1 }, // Bookcase at {0, 0, 0}, air at {1, 0, 1} { 0, 0, 1, 1, 0, 1 }, // Bookcase at {0, 0, 1}, air at {1, 0, 1} { 0, 0, 2, 1, 0, 2 }, // Bookcase at {0, 0, 2}, air at {1, 0, 2} { 0, 0, 3, 1, 0, 3 }, // Bookcase at {0, 0, 3}, air at {1, 0, 3} { 0, 0, 4, 1, 0, 3 }, // Bookcase at {0, 0, 4}, air at {1, 0, 3} { 1, 0, 4, 1, 0, 3 }, // Bookcase at {1, 0, 4}, air at {1, 0, 3} { 2, 0, 4, 2, 0, 3 }, // Bookcase at {2, 0, 4}, air at {2, 0, 3} { 3, 0, 4, 3, 0, 3 }, // Bookcase at {3, 0, 4}, air at {3, 0, 3} { 4, 0, 4, 3, 0, 3 }, // Bookcase at {4, 0, 4}, air at {3, 0, 3} { 4, 0, 3, 3, 0, 3 }, // Bookcase at {4, 0, 3}, air at {3, 0, 3} { 4, 0, 2, 3, 0, 2 }, // Bookcase at {4, 0, 2}, air at {3, 0, 2} { 4, 0, 1, 3, 0, 1 }, // Bookcase at {4, 0, 1}, air at {3, 0, 1} { 4, 0, 0, 3, 0, 1 }, // Bookcase at {4, 0, 0}, air at {3, 0, 1} { 3, 0, 0, 3, 0, 1 }, // Bookcase at {3, 0, 0}, air at {3, 0, 1} { 2, 0, 0, 2, 0, 1 }, // Bookcase at {2, 0, 0}, air at {2, 0, 1} { 1, 0, 0, 1, 0, 1 }, // Bookcase at {1, 0, 0}, air at {1, 0, 1} { 0, 1, 0, 1, 1, 1 }, // Bookcase at {0, 1, 0}, air at {1, 1, 1} { 0, 1, 1, 1, 1, 1 }, // Bookcase at {0, 1, 1}, air at {1, 1, 1} { 0, 1, 2, 1, 1, 2 }, // Bookcase at {0, 1, 2}, air at {1, 1, 2} { 0, 1, 3, 1, 1, 3 }, // Bookcase at {0, 1, 3}, air at {1, 1, 3} { 0, 1, 4, 1, 1, 3 }, // Bookcase at {0, 1, 4}, air at {1, 1, 3} { 1, 1, 4, 1, 1, 3 }, // Bookcase at {1, 1, 4}, air at {1, 1, 3} { 2, 1, 4, 2, 1, 3 }, // Bookcase at {2, 1, 4}, air at {2, 1, 3} { 3, 1, 4, 3, 1, 3 }, // Bookcase at {3, 1, 4}, air at {3, 1, 3} { 4, 1, 4, 3, 1, 3 }, // Bookcase at {4, 1, 4}, air at {3, 1, 3} { 4, 1, 3, 3, 1, 3 }, // Bookcase at {4, 1, 3}, air at {3, 1, 3} { 4, 1, 2, 3, 1, 2 }, // Bookcase at {4, 1, 2}, air at {3, 1, 2} { 4, 1, 1, 3, 1, 1 }, // Bookcase at {4, 1, 1}, air at {3, 1, 1} { 4, 1, 0, 3, 1, 1 }, // Bookcase at {4, 1, 0}, air at {3, 1, 1} { 3, 1, 0, 3, 1, 1 }, // Bookcase at {3, 1, 0}, air at {3, 1, 1} { 2, 1, 0, 2, 1, 1 }, // Bookcase at {2, 1, 0}, air at {2, 1, 1} { 1, 1, 0, 1, 1, 1 }, // Bookcase at {1, 1, 0}, air at {1, 1, 1} }; unsigned Bookshelves = 0; for (size_t i = 0; i < ARRAYCOUNT(CheckCoords); i++) { if ( (Area.GetRelBlockType(CheckCoords[i].m_AirX, CheckCoords[i].m_AirY, CheckCoords[i].m_AirZ) == E_BLOCK_AIR) && // There's air in the checkspot (Area.GetRelBlockType(CheckCoords[i].m_BookX, CheckCoords[i].m_BookY, CheckCoords[i].m_BookZ) == E_BLOCK_BOOKCASE) // There's bookcase in the wanted place ) { Bookshelves++; } } // for i - CheckCoords return Bookshelves; } cItem cSlotAreaEnchanting::SelectEnchantedOption(size_t a_EnchantOption) { ASSERT(a_EnchantOption < m_EnchantedItemOptions.size()); return std::move(m_EnchantedItemOptions[a_EnchantOption]); } //////////////////////////////////////////////////////////////////////////////// // cSlotAreaEnderChest: cSlotAreaEnderChest::cSlotAreaEnderChest(cEnderChestEntity * a_EnderChest, cWindow & a_ParentWindow) : cSlotArea(27, a_ParentWindow), m_EnderChest(a_EnderChest) { } const cItem * cSlotAreaEnderChest::GetSlot(int a_SlotNum, cPlayer & a_Player) const { return &(a_Player.GetEnderChestContents().GetSlot(a_SlotNum)); } void cSlotAreaEnderChest::SetSlot(int a_SlotNum, cPlayer & a_Player, const cItem & a_Item) { a_Player.GetEnderChestContents().SetSlot(a_SlotNum, a_Item); } //////////////////////////////////////////////////////////////////////////////// // cSlotAreaFurnace: cSlotAreaFurnace::cSlotAreaFurnace(cFurnaceEntity * a_Furnace, cWindow & a_ParentWindow) : cSlotArea(3, a_ParentWindow), m_Furnace(a_Furnace) { m_Furnace->GetContents().AddListener(*this); } cSlotAreaFurnace::~cSlotAreaFurnace() { m_Furnace->GetContents().RemoveListener(*this); } void cSlotAreaFurnace::Clicked(cPlayer & a_Player, int a_SlotNum, eClickAction a_ClickAction, const cItem & a_ClickedItem) { if (m_Furnace == nullptr) { LOGERROR("cSlotAreaFurnace::Clicked(): m_Furnace == nullptr"); ASSERT(!"cSlotAreaFurnace::Clicked(): m_Furnace == nullptr"); return; } if (a_SlotNum == 1) { cItem & DraggingItem = a_Player.GetDraggingItem(); cFurnaceRecipe * FurnaceRecipes = cRoot::Get()->GetFurnaceRecipe(); // Do not allow non-fuels to be placed in the fuel slot: if (!DraggingItem.IsEmpty() && !FurnaceRecipes->IsFuel(DraggingItem) && (a_ClickAction != caShiftLeftClick) && (a_ClickAction != caShiftRightClick)) { return; } } else if (a_SlotNum == 2) { bool bAsync = false; if (GetSlot(a_SlotNum, a_Player) == nullptr) { LOGWARNING("GetSlot(%d) returned nullptr! Ignoring click", a_SlotNum); return; } cItem Slot(*GetSlot(a_SlotNum, a_Player)); if (!Slot.IsSameType(a_ClickedItem)) { LOGWARNING("*** Window lost sync at item %d in SlotArea with %d items ***", a_SlotNum, m_NumSlots); LOGWARNING("My item: %s", ItemToFullString(Slot).c_str()); LOGWARNING("Their item: %s", ItemToFullString(a_ClickedItem).c_str()); bAsync = true; } switch (a_ClickAction) { case caShiftLeftClick: case caShiftRightClick: { HandleSmeltItem(Slot, a_Player); ShiftClicked(a_Player, a_SlotNum, Slot); return; } case caMiddleClick: { MiddleClicked(a_Player, a_SlotNum); return; } case caDropKey: case caCtrlDropKey: { DropClicked(a_Player, a_SlotNum, (a_SlotNum == caCtrlDropKey)); Slot.m_ItemCount = Slot.m_ItemCount - GetSlot(a_SlotNum, a_Player)->m_ItemCount; HandleSmeltItem(Slot, a_Player); return; } default: { break; } } cItem & DraggingItem = a_Player.GetDraggingItem(); if (!DraggingItem.IsEmpty()) { if (a_ClickAction == caDblClick) { return; } if (!DraggingItem.IsEqual(Slot)) { return; } if ((DraggingItem.m_ItemCount + Slot.m_ItemCount) > Slot.GetMaxStackSize()) { return; } DraggingItem.m_ItemCount += Slot.m_ItemCount; HandleSmeltItem(Slot, a_Player); Slot.Empty(); } else { switch (a_ClickAction) { case caDblClick: { DblClicked(a_Player, a_SlotNum); return; } case caLeftClick: { DraggingItem = Slot; HandleSmeltItem(Slot, a_Player); Slot.Empty(); break; } case caRightClick: { DraggingItem = Slot.CopyOne(); DraggingItem.m_ItemCount = static_cast(static_cast(Slot.m_ItemCount) / 2.f + 0.5f); Slot.m_ItemCount -= DraggingItem.m_ItemCount; if (Slot.m_ItemCount <= 0) { Slot.Empty(); } HandleSmeltItem(DraggingItem, a_Player); break; } default: { ASSERT(!"Unhandled click type!"); } } } SetSlot(a_SlotNum, a_Player, Slot); if (bAsync) { m_ParentWindow.BroadcastWholeWindow(); } return; } Super::Clicked(a_Player, a_SlotNum, a_ClickAction, a_ClickedItem); } void cSlotAreaFurnace::DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bool a_ShouldApply, bool a_KeepEmptySlots, bool a_BackFill) { int SlotNum; cFurnaceRecipe * FurnaceRecipes = cRoot::Get()->GetFurnaceRecipe(); if (FurnaceRecipes->GetRecipeFrom(a_ItemStack) != nullptr) { SlotNum = 0; } else if (FurnaceRecipes->IsFuel(a_ItemStack)) { SlotNum = 1; } else { return; } const cItem * Slot = GetSlot(SlotNum, a_Player); if (!Slot->IsEqual(a_ItemStack) && (!Slot->IsEmpty() || a_KeepEmptySlots)) { // Different items return; } char NumFit = Slot->GetMaxStackSize() - Slot->m_ItemCount; if (NumFit <= 0) { // Full stack already return; } NumFit = std::min(NumFit, a_ItemStack.m_ItemCount); if (a_ShouldApply) { cItem NewSlot(a_ItemStack); NewSlot.m_ItemCount = Slot->m_ItemCount + NumFit; SetSlot(SlotNum, a_Player, NewSlot); } a_ItemStack.m_ItemCount -= NumFit; if (a_ItemStack.IsEmpty()) { return; } } const cItem * cSlotAreaFurnace::GetSlot(int a_SlotNum, cPlayer & a_Player) const { UNUSED(a_Player); // a_SlotNum ranges from 0 to 2, query the items from the underlying furnace: return &(m_Furnace->GetSlot(a_SlotNum)); } void cSlotAreaFurnace::SetSlot(int a_SlotNum, cPlayer & a_Player, const cItem & a_Item) { m_Furnace->SetSlot(a_SlotNum, a_Item); } void cSlotAreaFurnace::OnSlotChanged(cItemGrid * a_ItemGrid, int a_SlotNum) { UNUSED(a_SlotNum); // Something has changed in the window, broadcast the entire window to all clients ASSERT(a_ItemGrid == &(m_Furnace->GetContents())); m_ParentWindow.BroadcastWholeWindow(); } void cSlotAreaFurnace::HandleSmeltItem(const cItem & a_Result, cPlayer & a_Player) { int Reward = m_Furnace->GetAndResetReward(); if (Reward > 0) { a_Player.GetWorld()->SpawnSplitExperienceOrbs(a_Player.GetPosX(), a_Player.GetPosY(), a_Player.GetPosZ(), Reward); } /** TODO 2014-05-12 xdot: Figure out when to call this method. */ switch (a_Result.m_ItemType) { case E_ITEM_IRON: a_Player.AwardAchievement(CustomStatistic::AchAcquireIron); break; case E_ITEM_COOKED_FISH: a_Player.AwardAchievement(CustomStatistic::AchCookFish); break; default: break; } } //////////////////////////////////////////////////////////////////////////////// // cSlotAreaBrewingstand: cSlotAreaBrewingstand::cSlotAreaBrewingstand(cBrewingstandEntity * a_Brewingstand, cWindow & a_ParentWindow) : cSlotArea(5, a_ParentWindow), m_Brewingstand(a_Brewingstand) { m_Brewingstand->GetContents().AddListener(*this); } cSlotAreaBrewingstand::~cSlotAreaBrewingstand() { m_Brewingstand->GetContents().RemoveListener(*this); } void cSlotAreaBrewingstand::Clicked(cPlayer & a_Player, int a_SlotNum, eClickAction a_ClickAction, const cItem & a_ClickedItem) { if (m_Brewingstand == nullptr) { LOGERROR("cSlotAreaBrewingstand::Clicked(): m_Brewingstand == nullptr"); ASSERT(!"cSlotAreaBrewingstand::Clicked(): m_Brewingstand == nullptr"); return; } if (GetSlot(a_SlotNum, a_Player) == nullptr) { LOGWARNING("GetSlot(%d) returned nullptr! Ignoring click", a_SlotNum); return; } cItem Slot(*GetSlot(a_SlotNum, a_Player)); cItem & DraggingItem = a_Player.GetDraggingItem(); cBrewingRecipes * BR = cRoot::Get()->GetBrewingRecipes(); if ((a_SlotNum >= 0) && (a_SlotNum <= 2)) { // Bottle slots switch (a_ClickAction) { case caLeftClick: case caRightClick: { if (BR->IsBottle(Slot)) { HandleBrewedItem(a_Player, Slot); } if (!DraggingItem.IsEmpty() && !BR->IsBottle(DraggingItem)) { // Deny placing a invalid item into the bottle slot return; } break; } case caShiftLeftClick: case caShiftRightClick: { if (BR->IsBottle(Slot)) { HandleBrewedItem(a_Player, Slot); } Super::ShiftClicked(a_Player, a_SlotNum, Slot); break; } default: { if (!DraggingItem.IsEmpty() && !BR->IsBottle(DraggingItem)) { // Deny placing a invalid item into the bottle slot return; } break; } } } if ((a_SlotNum == 3) && !DraggingItem.IsEmpty()) { // Ingredient slot switch (a_ClickAction) { case caShiftLeftClick: case caShiftRightClick: { Super::ShiftClicked(a_Player, a_SlotNum, Slot); break; } default: { if (!BR->IsIngredient(DraggingItem)) { // Deny placing a invalid item into the ingredient slot return; } break; } } } if ((a_SlotNum == 4) && !DraggingItem.IsEmpty()) { // Fuel slot switch (a_ClickAction) { case caShiftLeftClick: case caShiftRightClick: { Super::ShiftClicked(a_Player, a_SlotNum, Slot); break; } default: { if (!BR->IsFuel(DraggingItem)) { // Deny placing a invalid item into the fuel slot return; } break; } } } Super::Clicked(a_Player, a_SlotNum, a_ClickAction, a_ClickedItem); } void cSlotAreaBrewingstand::HandleBrewedItem(cPlayer & a_Player, const cItem & a_ClickedItem) { // Award an achievement if the item is not a water bottle (is a real brewed potion) if (a_ClickedItem.m_ItemDamage > 0) { a_Player.AwardAchievement(CustomStatistic::AchPotion); } } void cSlotAreaBrewingstand::DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bool a_ShouldApply, bool a_KeepEmptySlots, bool a_BackFill) { int SlotNum = -1; cBrewingRecipes * BR = cRoot::Get()->GetBrewingRecipes(); if (BR->IsBottle(a_ItemStack)) { for (int i = 0;i < 3;i++) { if (GetSlot(i, a_Player)->IsEmpty()) { SlotNum = i; break; } } if (SlotNum == -1) { // All slots are full return; } } else if (BR->IsIngredient(a_ItemStack)) { SlotNum = 3; } else { return; } const cItem * Slot = GetSlot(SlotNum, a_Player); if (!Slot->IsEqual(a_ItemStack) && (!Slot->IsEmpty() || a_KeepEmptySlots)) { // Different items return; } char NumFit = Slot->GetMaxStackSize() - Slot->m_ItemCount; if (NumFit <= 0) { // Full stack already return; } NumFit = std::min(NumFit, a_ItemStack.m_ItemCount); if (a_ShouldApply) { cItem NewSlot(a_ItemStack); NewSlot.m_ItemCount = Slot->m_ItemCount + NumFit; SetSlot(SlotNum, a_Player, NewSlot); } a_ItemStack.m_ItemCount -= NumFit; if (a_ItemStack.IsEmpty()) { return; } } const cItem * cSlotAreaBrewingstand::GetSlot(int a_SlotNum, cPlayer & a_Player) const { UNUSED(a_Player); // a_SlotNum ranges from 0 to 3, query the items from the underlying brewing stand: return &(m_Brewingstand->GetSlot(a_SlotNum)); } void cSlotAreaBrewingstand::SetSlot(int a_SlotNum, cPlayer & a_Player, const cItem & a_Item) { UNUSED(a_Player); m_Brewingstand->SetSlot(a_SlotNum, a_Item); } void cSlotAreaBrewingstand::OnSlotChanged(cItemGrid * a_ItemGrid, int a_SlotNum) { UNUSED(a_SlotNum); // Something has changed in the window, broadcast the entire window to all clients ASSERT(a_ItemGrid == &(m_Brewingstand->GetContents())); m_ParentWindow.BroadcastWholeWindow(); } //////////////////////////////////////////////////////////////////////////////// // cSlotAreaMinecartWithChest: cSlotAreaMinecartWithChest::cSlotAreaMinecartWithChest(cMinecartWithChest * a_Chest, cWindow & a_ParentWindow) : cSlotArea(27, a_ParentWindow), m_Chest(a_Chest) { } const cItem * cSlotAreaMinecartWithChest::GetSlot(int a_SlotNum, cPlayer & a_Player) const { // a_SlotNum ranges from 0 to 26, use that to index the minecart chest entity's inventory directly: UNUSED(a_Player); return &(m_Chest->GetSlot(a_SlotNum)); } void cSlotAreaMinecartWithChest::SetSlot(int a_SlotNum, cPlayer & a_Player, const cItem & a_Item) { UNUSED(a_Player); m_Chest->SetSlot(a_SlotNum, a_Item); } //////////////////////////////////////////////////////////////////////////////// // cSlotAreaInventoryBase: cSlotAreaInventoryBase::cSlotAreaInventoryBase(int a_NumSlots, int a_SlotOffset, cWindow & a_ParentWindow) : cSlotArea(a_NumSlots, a_ParentWindow), m_SlotOffset(a_SlotOffset) { } void cSlotAreaInventoryBase::Clicked(cPlayer & a_Player, int a_SlotNum, eClickAction a_ClickAction, const cItem & a_ClickedItem) { if (a_Player.IsGameModeCreative() && (m_ParentWindow.GetWindowType() == cWindow::wtInventory)) { if ((a_ClickAction == caDropKey) || (a_ClickAction == caCtrlDropKey)) { DropClicked(a_Player, a_SlotNum, (a_ClickAction == caCtrlDropKey)); return; } // Creative inventory must treat a_ClickedItem as a DraggedItem instead, replacing the inventory slot with it SetSlot(a_SlotNum, a_Player, a_ClickedItem); return; } // Survival inventory and all other windows' inventory has the same handling as normal slot areas Super::Clicked(a_Player, a_SlotNum, a_ClickAction, a_ClickedItem); } const cItem * cSlotAreaInventoryBase::GetSlot(int a_SlotNum, cPlayer & a_Player) const { // a_SlotNum ranges from 0 to 35, map that to the player's inventory slots according to the internal offset return &a_Player.GetInventory().GetSlot(a_SlotNum + m_SlotOffset); } void cSlotAreaInventoryBase::SetSlot(int a_SlotNum, cPlayer & a_Player, const cItem & a_Item) { a_Player.GetInventory().SetSlot(a_SlotNum + m_SlotOffset, a_Item); } //////////////////////////////////////////////////////////////////////////////// // cSlotAreaArmor: void cSlotAreaArmor::DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bool a_ShouldApply, bool a_KeepEmptySlots, bool a_BackFill) { if (ItemCategory::IsHelmet(a_ItemStack.m_ItemType) && GetSlot(0, a_Player)->IsEmpty()) { if (a_ShouldApply) { SetSlot(0, a_Player, a_ItemStack.CopyOne()); } a_ItemStack.m_ItemCount -= 1; } else if (ItemCategory::IsChestPlate(a_ItemStack.m_ItemType) && GetSlot(1, a_Player)->IsEmpty()) { if (a_ShouldApply) { SetSlot(1, a_Player, a_ItemStack.CopyOne()); } a_ItemStack.m_ItemCount -= 1; } else if (ItemCategory::IsLeggings(a_ItemStack.m_ItemType) && GetSlot(2, a_Player)->IsEmpty()) { if (a_ShouldApply) { SetSlot(2, a_Player, a_ItemStack.CopyOne()); } a_ItemStack.m_ItemCount -= 1; } else if (ItemCategory::IsBoots(a_ItemStack.m_ItemType) && GetSlot(3, a_Player)->IsEmpty()) { if (a_ShouldApply) { SetSlot(3, a_Player, a_ItemStack.CopyOne()); } a_ItemStack.m_ItemCount -= 1; } } void cSlotAreaArmor::Clicked(cPlayer & a_Player, int a_SlotNum, eClickAction a_ClickAction, const cItem & a_ClickedItem) { ASSERT((a_SlotNum >= 0) && (a_SlotNum < GetNumSlots())); // When the player is in creative mode, the client sends the new item as a_ClickedItem, not the current item in the slot. if (a_Player.IsGameModeCreative() && (m_ParentWindow.GetWindowType() == cWindow::wtInventory)) { if ((a_ClickAction == caDropKey) || (a_ClickAction == caCtrlDropKey)) { DropClicked(a_Player, a_SlotNum, (a_ClickAction == caCtrlDropKey)); return; } SetSlot(a_SlotNum, a_Player, a_ClickedItem); return; } bool bAsync = false; if (GetSlot(a_SlotNum, a_Player) == nullptr) { LOGWARNING("GetSlot(%d) returned nullptr! Ignoring click", a_SlotNum); return; } switch (a_ClickAction) { case caDblClick: { // Armors haven't a dbl click return; } case caShiftLeftClick: case caShiftRightClick: { ShiftClicked(a_Player, a_SlotNum, a_ClickedItem); return; } case caMiddleClick: { MiddleClicked(a_Player, a_SlotNum); return; } default: { break; } } cItem Slot(*GetSlot(a_SlotNum, a_Player)); if (!Slot.IsSameType(a_ClickedItem)) { LOGWARNING("*** Window lost sync at item %d in SlotArea with %d items ***", a_SlotNum, m_NumSlots); LOGWARNING("My item: %s", ItemToFullString(Slot).c_str()); LOGWARNING("Their item: %s", ItemToFullString(a_ClickedItem).c_str()); bAsync = true; } cItem & DraggingItem = a_Player.GetDraggingItem(); if ((a_ClickAction != caRightClick) && (a_ClickAction != caLeftClick)) { LOGWARNING("SlotArea: Unhandled click action: %d (%s)", a_ClickAction, ClickActionToString(a_ClickAction)); m_ParentWindow.BroadcastWholeWindow(); return; } if (DraggingItem.IsEmpty() || CanPlaceArmorInSlot(a_SlotNum, DraggingItem)) { // Swap contents cItem tmp(DraggingItem); DraggingItem = Slot; Slot = tmp; } SetSlot(a_SlotNum, a_Player, Slot); if (bAsync) { m_ParentWindow.BroadcastWholeWindow(); } } bool cSlotAreaArmor::CanPlaceArmorInSlot(int a_SlotNum, const cItem & a_Item) { switch (a_SlotNum) { case 0: return (ItemCategory::IsHelmet(a_Item.m_ItemType) || (a_Item.m_ItemType == E_BLOCK_PUMPKIN)); case 1: return ItemCategory::IsChestPlate(a_Item.m_ItemType); case 2: return ItemCategory::IsLeggings(a_Item.m_ItemType); case 3: return ItemCategory::IsBoots(a_Item.m_ItemType); default: return false; } } //////////////////////////////////////////////////////////////////////////////// // cSlotAreaItemGrid: cSlotAreaItemGrid::cSlotAreaItemGrid(cItemGrid & a_ItemGrid, cWindow & a_ParentWindow) : Super(a_ItemGrid.GetNumSlots(), a_ParentWindow), m_ItemGrid(a_ItemGrid) { m_ItemGrid.AddListener(*this); } cSlotAreaItemGrid::~cSlotAreaItemGrid() { m_ItemGrid.RemoveListener(*this); } const cItem * cSlotAreaItemGrid::GetSlot(int a_SlotNum, cPlayer & a_Player) const { return &m_ItemGrid.GetSlot(a_SlotNum); } void cSlotAreaItemGrid::SetSlot(int a_SlotNum, cPlayer & a_Player, const cItem & a_Item) { m_ItemGrid.SetSlot(a_SlotNum, a_Item); } void cSlotAreaItemGrid::OnSlotChanged(cItemGrid * a_ItemGrid, int a_SlotNum) { ASSERT(a_ItemGrid == &m_ItemGrid); m_ParentWindow.BroadcastSlot(this, a_SlotNum); } //////////////////////////////////////////////////////////////////////////////// // cSlotAreaTemporary: cSlotAreaTemporary::cSlotAreaTemporary(int a_NumSlots, cWindow & a_ParentWindow) : cSlotArea(a_NumSlots, a_ParentWindow) { } const cItem * cSlotAreaTemporary::GetSlot(int a_SlotNum, cPlayer & a_Player) const { cItemMap::const_iterator itr = m_Items.find(a_Player.GetUniqueID()); if (itr == m_Items.end()) { LOGERROR("cSlotAreaTemporary: player \"%s\" not found for slot %d!", a_Player.GetName().c_str(), a_SlotNum); ASSERT(!"cSlotAreaTemporary: player not found!"); // Player not found, this should not happen, ever! Return nullptr, but things may break by this. return nullptr; } if (a_SlotNum >= static_cast(itr->second.size())) { LOGERROR("cSlotAreaTemporary: asking for more slots than actually stored!"); ASSERT(!"cSlotAreaTemporary: asking for more slots than actually stored!"); return nullptr; } return &(itr->second[static_cast(a_SlotNum)]); } void cSlotAreaTemporary::SetSlot(int a_SlotNum, cPlayer & a_Player, const cItem & a_Item) { cItemMap::iterator itr = m_Items.find(a_Player.GetUniqueID()); if (itr == m_Items.end()) { // Player not found LOGWARNING("cSlotAreaTemporary: player not found!"); return; } if (a_SlotNum >= static_cast(itr->second.size())) { LOGERROR("cSlotAreaTemporary: asking for more slots than actually stored!"); return; } itr->second[static_cast(a_SlotNum)] = a_Item; m_ParentWindow.SendSlot(a_Player, this, a_SlotNum); } void cSlotAreaTemporary::OnPlayerAdded(cPlayer & a_Player) { ASSERT(m_Items.find(a_Player.GetUniqueID()) == m_Items.end()); // The player shouldn't be in the itemmap, otherwise we probably have a leak m_Items[a_Player.GetUniqueID()].resize(static_cast(m_NumSlots)); // Make the vector the specified size of empty items } void cSlotAreaTemporary::OnPlayerRemoved(cPlayer & a_Player) { cItemMap::iterator itr = m_Items.find(a_Player.GetUniqueID()); ASSERT(itr != m_Items.end()); // The player should be in the list, otherwise a call to OnPlayerAdded() was mismatched m_Items.erase(itr); } void cSlotAreaTemporary::TossItems(cPlayer & a_Player, int a_Begin, int a_End) { cItemMap::iterator itr = m_Items.find(a_Player.GetUniqueID()); if (itr == m_Items.end()) { LOGWARNING("Player tossing items (%s) not found in the item map", a_Player.GetName().c_str()); return; } cItems Drops; for (int i = a_Begin; i < a_End; i++) { cItem & Item = itr->second[static_cast(i)]; if (!Item.IsEmpty()) { Drops.push_back(Item); } Item.Empty(); } // for i - itr->second[] a_Player.TossItems(Drops); } cItem * cSlotAreaTemporary::GetPlayerSlots(cPlayer & a_Player) { cItemMap::iterator itr = m_Items.find(a_Player.GetUniqueID()); if (itr == m_Items.end()) { return nullptr; } return itr->second.data(); } //////////////////////////////////////////////////////////////////////////////// // cSlotAreaHorse: cSlotAreaHorse::cSlotAreaHorse(cHorse & a_Horse, cWindow & a_ParentWindow) : cSlotArea(2, a_ParentWindow), m_Horse(a_Horse) { } void cSlotAreaHorse::Clicked(cPlayer & a_Player, int a_SlotNum, eClickAction a_ClickAction, const cItem & a_ClickedItem) { cItem & DraggingItem = a_Player.GetDraggingItem(); switch (a_ClickAction) { case caLeftClick: case caRightClick: case caDblClick: { // Check for invalid item types if (DraggingItem.IsEmpty()) { break; } switch (a_SlotNum) { case SaddleSlot: { if (DraggingItem.m_ItemType != E_ITEM_SADDLE) { return; } break; } case ArmorSlot: { if (!ItemCategory::IsHorseArmor(DraggingItem.m_ItemType)) { return; } break; } default: break; } } default: break; } cSlotArea::Clicked(a_Player, a_SlotNum, a_ClickAction, a_ClickedItem); } const cItem * cSlotAreaHorse::GetSlot(int a_SlotNum, cPlayer & a_Player) const { static const cItem InvalidItem; switch (a_SlotNum) { case SaddleSlot: return &m_Horse.GetHorseSaddle(); case ArmorSlot: return &m_Horse.GetHorseArmorItem(); default: { LOGWARN("cSlotAreaHorse::GetSlot: Invalid slot number %d", a_SlotNum); return &InvalidItem; } } } void cSlotAreaHorse::SetSlot(int a_SlotNum, cPlayer & a_Player, const cItem & a_Item) { switch (a_SlotNum) { case SaddleSlot: m_Horse.SetHorseSaddle(a_Item); break; case ArmorSlot: m_Horse.SetHorseArmor(a_Item); break; default: { LOGWARN("cSlotAreaHorse::SetSlot: Invalid slot number %d", a_SlotNum); } } } void cSlotAreaHorse::DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bool a_ShouldApply, bool a_KeepEmptySlots, bool a_BackFill) { if (ItemCategory::IsHorseArmor(a_ItemStack.m_ItemType) && m_Horse.GetHorseArmorItem().IsEmpty()) { if (a_ShouldApply) { m_Horse.SetHorseArmor(a_ItemStack.CopyOne()); } --a_ItemStack.m_ItemCount; } else if ((a_ItemStack.m_ItemType == E_ITEM_SADDLE) && !m_Horse.IsSaddled()) { if (a_ShouldApply) { m_Horse.SetHorseSaddle(a_ItemStack.CopyOne()); } --a_ItemStack.m_ItemCount; } } ================================================ FILE: src/UI/SlotArea.h ================================================ // SlotArea.h // Interfaces to the cSlotArea class representing a contiguous area of slots in a UI window #pragma once #include "../Inventory.h" class cHorse; class cWindow; class cPlayer; class cBeaconEntity; class cBrewingstandEntity; class cChestEntity; class cEnderChestEntity; class cFurnaceEntity; class cMinecartWithChest; class cCraftingRecipe; class cWorld; class cSlotArea { public: cSlotArea(int a_NumSlots, cWindow & a_ParentWindow); virtual ~cSlotArea() {} // force a virtual destructor in all subclasses int GetNumSlots(void) const { return m_NumSlots; } /** Called to retrieve an item in the specified slot for the specified player. Must return a valid cItem. */ virtual const cItem * GetSlot(int a_SlotNum, cPlayer & a_Player) const = 0; /** Called to set an item in the specified slot for the specified player */ virtual void SetSlot(int a_SlotNum, cPlayer & a_Player, const cItem & a_Item) = 0; /** Called when a player clicks in the window. Parameters taken from the click packet. */ virtual void Clicked(cPlayer & a_Player, int a_SlotNum, eClickAction a_ClickAction, const cItem & a_ClickedItem); /** Called from Clicked when the action is a shiftclick (left or right) */ virtual void ShiftClicked(cPlayer & a_Player, int a_SlotNum, const cItem & a_ClickedItem); /** Called from Clicked when the action is a caDblClick */ virtual void DblClicked(cPlayer & a_Player, int a_SlotNum); /** Called from Clicked when the action is a middleclick */ virtual void MiddleClicked(cPlayer & a_Player, int a_SlotNum); /** Called from Clicked when the action is a drop click. */ virtual void DropClicked(cPlayer & a_Player, int a_SlotNum, bool a_DropStack); /** Called from Clicked when the action is a number click. */ virtual void NumberClicked(cPlayer & a_Player, int a_SlotNum, eClickAction a_ClickAction); /** Called when a new player opens the same parent window. The window already tracks the player. CS-locked. */ virtual void OnPlayerAdded(cPlayer & a_Player); /** Called when one of the players closes the parent window. The window already doesn't track the player. CS-locked. */ virtual void OnPlayerRemoved(cPlayer & a_Player); /** Called to store as much of a_ItemStack in the area as possible. a_ItemStack is modified to reflect the change. The default implementation searches each slot for available space and distributes the stack there. if a_ShouldApply is true, the changes are written into the slots; if a_ShouldApply is false, only a_ItemStack is modified to reflect the number of fits (for fit-testing purposes) If a_KeepEmptySlots is true, empty slots will be skipped and won't be filled */ virtual void DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bool a_ShouldApply, bool a_KeepEmptySlots, bool a_BackFill); /** Called on DblClicking to collect all stackable items into hand. The items are accumulated in a_Dragging and removed from the slots immediately. If a_CollectFullStacks is false, slots with full stacks are skipped while collecting. Returns true if full stack has been collected in a_Dragging, false if there's space remaining to fill. */ virtual bool CollectItemsToHand(cItem & a_Dragging, cPlayer & a_Player, bool a_CollectFullStacks); protected: int m_NumSlots; cWindow & m_ParentWindow; } ; /** Handles any part of the inventory, using parameters in constructor to distinguish between the parts */ class cSlotAreaInventoryBase: public cSlotArea { using Super = cSlotArea; public: cSlotAreaInventoryBase(int a_NumSlots, int a_SlotOffset, cWindow & a_ParentWindow); // Creative inventory's click handling is somewhat different from survival inventory's, handle that here: virtual void Clicked(cPlayer & a_Player, int a_SlotNum, eClickAction a_ClickAction, const cItem & a_ClickedItem) override; virtual const cItem * GetSlot(int a_SlotNum, cPlayer & a_Player) const override; virtual void SetSlot(int a_SlotNum, cPlayer & a_Player, const cItem & a_Item) override; protected: int m_SlotOffset; // Index that this area's slot 0 has in the underlying cInventory } ; /** Handles the main inventory of each player, excluding the armor and hotbar */ class cSlotAreaInventory: public cSlotAreaInventoryBase { using Super = cSlotAreaInventoryBase; public: cSlotAreaInventory(cWindow & a_ParentWindow): Super(cInventory::invInventoryCount, cInventory::invInventoryOffset, a_ParentWindow) { } } ; /** Handles the hotbar of each player */ class cSlotAreaHotBar: public cSlotAreaInventoryBase { using Super = cSlotAreaInventoryBase; public: cSlotAreaHotBar(cWindow & a_ParentWindow): Super(cInventory::invHotbarCount, cInventory::invHotbarOffset, a_ParentWindow) { } } ; /** Handles the shield of each player */ class cSlotAreaShield: public cSlotAreaInventoryBase { using Super = cSlotAreaInventoryBase; public: cSlotAreaShield(cWindow & a_ParentWindow): Super(cInventory::invShieldCount, cInventory::invShieldOffset, a_ParentWindow) { } }; /** Handles the armor area of the player's inventory */ class cSlotAreaArmor: public cSlotAreaInventoryBase { using Super = cSlotAreaInventoryBase; public: cSlotAreaArmor(cWindow & a_ParentWindow): Super(cInventory::invArmorCount, cInventory::invArmorOffset, a_ParentWindow) { } /** Distributing the stack is allowed only for compatible items (helmets into helmet slot etc.) */ virtual void DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bool a_ShouldApply, bool a_KeepEmptySlots, bool a_BackFill) override; /** Called when a player clicks in the window. Parameters taken from the click packet. */ virtual void Clicked(cPlayer & a_Player, int a_SlotNum, eClickAction a_ClickAction, const cItem & a_ClickedItem) override; static bool CanPlaceArmorInSlot(int a_SlotNum, const cItem & a_Item); } ; /** Handles any slot area that is representing a cItemGrid; same items for all the players */ class cSlotAreaItemGrid: public cSlotArea, public cItemGrid::cListener { using Super = cSlotArea; public: cSlotAreaItemGrid(cItemGrid & a_ItemGrid, cWindow & a_ParentWindow); virtual ~cSlotAreaItemGrid() override; virtual const cItem * GetSlot(int a_SlotNum, cPlayer & a_Player) const override; virtual void SetSlot(int a_SlotNum, cPlayer & a_Player, const cItem & a_Item) override; protected: cItemGrid & m_ItemGrid; // cItemGrid::cListener overrides: virtual void OnSlotChanged(cItemGrid * a_ItemGrid, int a_SlotNum) override; } ; /** A cSlotArea with items layout that is private to each player and is temporary, such as a crafting grid or an enchantment table. This common ancestor stores the items in a per-player map. It also implements tossing items from the map. */ class cSlotAreaTemporary: public cSlotArea { using Super = cSlotArea; public: cSlotAreaTemporary(int a_NumSlots, cWindow & a_ParentWindow); // cSlotArea overrides: virtual const cItem * GetSlot (int a_SlotNum, cPlayer & a_Player) const override; virtual void SetSlot (int a_SlotNum, cPlayer & a_Player, const cItem & a_Item) override; virtual void OnPlayerAdded (cPlayer & a_Player) override; virtual void OnPlayerRemoved(cPlayer & a_Player) override; /** Tosses the player's items in slots [a_Begin, a_End) (ie. incl. a_Begin, but excl. a_End) */ void TossItems(cPlayer & a_Player, int a_Begin, int a_End); protected: using cItemMap = std::map >; // Maps EntityID -> items cItemMap m_Items; /** Returns the pointer to the slot array for the player specified. */ cItem * GetPlayerSlots(cPlayer & a_Player); } ; class cSlotAreaCrafting: public cSlotAreaTemporary { using Super = cSlotAreaTemporary; public: /** a_GridSize is allowed to be only 2 or 3 */ cSlotAreaCrafting(int a_GridSize, cWindow & a_ParentWindow); // cSlotAreaTemporary overrides: virtual void Clicked (cPlayer & a_Player, int a_SlotNum, eClickAction a_ClickAction, const cItem & a_ClickedItem) override; virtual void DblClicked (cPlayer & a_Player, int a_SlotNum) override; virtual void OnPlayerRemoved(cPlayer & a_Player) override; virtual void SetSlot (int a_SlotNum, cPlayer & a_Player, const cItem & a_Item) override; // Distributing items into this area is completely disabled virtual void DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bool a_ShouldApply, bool a_KeepEmptySlots, bool a_BackFill) override; /** Clear the crafting grid */ void ClearCraftingGrid(cPlayer & a_Player); /** Loads the given Recipe into the crafting grid */ void LoadRecipe(cPlayer & a_Player, UInt32 a_RecipeId); protected: /** Maps player's EntityID -> current recipe. Not a std::map because cCraftingGrid needs proper constructor params. */ typedef std::list > cRecipeMap; int m_GridSize; cRecipeMap m_Recipes; /** Handles a click in the result slot. Crafts using the current recipe, if possible. */ void ClickedResult(cPlayer & a_Player); /** Handles a shift-click in the result slot. Crafts using the current recipe until it changes or no more space for result. */ void ShiftClickedResult(cPlayer & a_Player); /** Handles a drop-click in the result slot. */ void DropClickedResult(cPlayer & a_Player); /** Updates the current recipe and result slot based on the ingredients currently in the crafting grid of the specified player. */ void UpdateRecipe(cPlayer & a_Player); /** Retrieves the recipe for the specified player from the map, or creates one if not found. */ cCraftingRecipe & GetRecipeForPlayer(cPlayer & a_Player); /** Called after an item has been crafted to handle statistics e.t.c. */ void HandleCraftItem(const cItem & a_Result, cPlayer & a_Player); } ; class cSlotAreaAnvil: public cSlotAreaTemporary { using Super = cSlotAreaTemporary; public: cSlotAreaAnvil(cWindow & a_ParentWindow); // cSlotArea overrides: virtual void Clicked(cPlayer & a_Player, int a_SlotNum, eClickAction a_ClickAction, const cItem & a_ClickedItem) override; virtual void ShiftClicked(cPlayer & a_Player, int a_SlotNum, const cItem & a_ClickedItem) override; virtual void DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bool a_ShouldApply, bool a_KeepEmptySlots, bool a_BackFill) override; // cSlotAreaTemporary overrides: virtual void OnPlayerRemoved(cPlayer & a_Player) override; /** Can the player take the item from the slot? */ bool CanTakeResultItem(cPlayer & a_Player); /** This function will call, when the player take the item from the slot. */ void OnTakeResult(cPlayer & a_Player); /** Handles a click in the item slot. */ void UpdateResult(cPlayer & a_Player); protected: /** The maximum cost of repairing / renaming in the anvil. */ int m_MaximumCost; /** The stack size of the second item where was used for repair */ char m_StackSizeToBeUsedInRepair; } ; class cSlotAreaBeacon: public cSlotArea, public cItemGrid::cListener { using Super = cSlotArea; public: cSlotAreaBeacon(cBeaconEntity * a_Beacon, cWindow & a_ParentWindow); virtual ~cSlotAreaBeacon() override; static bool IsPlaceableItem(short a_ItemType); virtual void Clicked(cPlayer & a_Player, int a_SlotNum, eClickAction a_ClickAction, const cItem & a_ClickedItem) override; virtual void DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bool a_ShouldApply, bool a_KeepEmptySlots, bool a_BackFill) override; virtual const cItem * GetSlot(int a_SlotNum, cPlayer & a_Player) const override; virtual void SetSlot(int a_SlotNum, cPlayer & a_Player, const cItem & a_Item) override; protected: cBeaconEntity * m_Beacon; // cItemGrid::cListener overrides: virtual void OnSlotChanged(cItemGrid * a_ItemGrid, int a_SlotNum) override; } ; class cSlotAreaEnchanting final : public cSlotAreaTemporary { using Super = cSlotAreaTemporary; public: cSlotAreaEnchanting(cWindow & a_ParentWindow, Vector3i a_BlockPos); // cSlotArea overrides: virtual void Clicked(cPlayer & a_Player, int a_SlotNum, eClickAction a_ClickAction, const cItem & a_ClickedItem) override; virtual void DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bool a_ShouldApply, bool a_KeepEmptySlots, bool a_BackFill) override; virtual void SetSlot(int a_SlotNum, cPlayer & a_Player, const cItem & a_Item) override; // cSlotAreaTemporary overrides: virtual void OnPlayerAdded (cPlayer & a_Player) override; virtual void OnPlayerRemoved(cPlayer & a_Player) override; /* Get the number of bookshelves which are near the enchanting table */ unsigned GetBookshelvesCount(cWorld & a_World); /* Return the enchanted item matching the chosen option (0, 1, 2) Ownership of the cItem is transferred to the caller. */ cItem SelectEnchantedOption(size_t a_EnchantOption); protected: /** Handles a click in the item slot. */ void UpdateResult(cPlayer & a_Player); Vector3i m_BlockPos; std::array m_EnchantedItemOptions; }; class cSlotAreaChest : public cSlotArea { public: cSlotAreaChest(cChestEntity * a_Chest, cWindow & a_ParentWindow); virtual const cItem * GetSlot(int a_SlotNum, cPlayer & a_Player) const override; virtual void SetSlot(int a_SlotNum, cPlayer & a_Player, const cItem & a_Item) override; protected: cChestEntity * m_Chest; } ; class cSlotAreaDoubleChest : public cSlotArea { public: cSlotAreaDoubleChest(cChestEntity * a_TopChest, cChestEntity * a_BottomChest, cWindow & a_ParentWindow); virtual const cItem * GetSlot(int a_SlotNum, cPlayer & a_Player) const override; virtual void SetSlot(int a_SlotNum, cPlayer & a_Player, const cItem & a_Item) override; protected: cChestEntity * m_TopChest; cChestEntity * m_BottomChest; } ; class cSlotAreaEnderChest : public cSlotArea { public: cSlotAreaEnderChest(cEnderChestEntity * a_EnderChest, cWindow & a_ParentWindow); virtual const cItem * GetSlot(int a_SlotNum, cPlayer & a_Player) const override; virtual void SetSlot(int a_SlotNum, cPlayer & a_Player, const cItem & a_Item) override; protected: cEnderChestEntity * m_EnderChest; }; class cSlotAreaFurnace: public cSlotArea, public cItemGrid::cListener { using Super = cSlotArea; public: cSlotAreaFurnace(cFurnaceEntity * a_Furnace, cWindow & a_ParentWindow); virtual ~cSlotAreaFurnace() override; virtual void Clicked(cPlayer & a_Player, int a_SlotNum, eClickAction a_ClickAction, const cItem & a_ClickedItem) override; virtual void DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bool a_ShouldApply, bool a_KeepEmptySlots, bool a_BackFill) override; virtual const cItem * GetSlot(int a_SlotNum, cPlayer & a_Player) const override; virtual void SetSlot(int a_SlotNum, cPlayer & a_Player, const cItem & a_Item) override; protected: cFurnaceEntity * m_Furnace; // cItemGrid::cListener overrides: virtual void OnSlotChanged(cItemGrid * a_ItemGrid, int a_SlotNum) override; /** Called after an item has been smelted to handle statistics etc. */ void HandleSmeltItem(const cItem & a_Result, cPlayer & a_Player); } ; class cSlotAreaBrewingstand: public cSlotArea, public cItemGrid::cListener { using Super = cSlotArea; public: cSlotAreaBrewingstand(cBrewingstandEntity * a_Brewingstand, cWindow & a_ParentWindow); virtual ~cSlotAreaBrewingstand() override; virtual void Clicked(cPlayer & a_Player, int a_SlotNum, eClickAction a_ClickAction, const cItem & a_ClickedItem) override; virtual void DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bool a_ShouldApply, bool a_KeepEmptySlots, bool a_BackFill) override; virtual const cItem * GetSlot(int a_SlotNum, cPlayer & a_Player) const override; virtual void SetSlot(int a_SlotNum, cPlayer & a_Player, const cItem & a_Item) override; protected: cBrewingstandEntity * m_Brewingstand; // cItemGrid::cListener overrides: virtual void OnSlotChanged(cItemGrid * a_ItemGrid, int a_SlotNum) override; /** Called after an item has been brewed to handle statistics etc. */ void HandleBrewedItem(cPlayer & a_Player, const cItem & a_ClickedItem); } ; class cSlotAreaMinecartWithChest : public cSlotArea { public: cSlotAreaMinecartWithChest(cMinecartWithChest * a_ChestCart, cWindow & a_ParentWindow); virtual const cItem * GetSlot(int a_SlotNum, cPlayer & a_Player) const override; virtual void SetSlot(int a_SlotNum, cPlayer & a_Player, const cItem & a_Item) override; protected: cMinecartWithChest * m_Chest; }; /** Slot area holding horse saddle and armor. */ class cSlotAreaHorse: public cSlotArea { public: enum { SaddleSlot, ArmorSlot }; cSlotAreaHorse(cHorse & a_Horse, cWindow & a_ParentWindow); virtual void Clicked(cPlayer & a_Player, int a_SlotNum, eClickAction a_ClickAction, const cItem & a_ClickedItem) override; virtual const cItem * GetSlot(int a_SlotNum, cPlayer & a_Player) const override; virtual void SetSlot(int a_SlotNum, cPlayer & a_Player, const cItem & a_Item) override; virtual void DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bool a_ShouldApply, bool a_KeepEmptySlots, bool a_BackFill) override; private: cHorse & m_Horse; }; ================================================ FILE: src/UI/Window.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "Window.h" #include "WindowOwner.h" #include "SlotArea.h" #include "../Item.h" #include "../ClientHandle.h" #include "../Entities/Player.h" #include "../Entities/Pickup.h" #include "../Inventory.h" #include "../Items/ItemHandler.h" #include "../BlockEntities/BeaconEntity.h" #include "../BlockEntities/ChestEntity.h" #include "../BlockEntities/DropSpenserEntity.h" #include "../BlockEntities/EnderChestEntity.h" #include "../BlockEntities/HopperEntity.h" #include "../Entities/Minecart.h" #include "../Root.h" #include "../Bindings/PluginManager.h" Byte cWindow::m_WindowIDCounter = 0; cWindow::cWindow(WindowType a_WindowType, const AString & a_WindowTitle) : m_WindowID(((++m_WindowIDCounter) % 127) + 1), m_WindowType(a_WindowType), m_WindowTitle(a_WindowTitle), m_IsDestroyed(false), m_Owner(nullptr) { ASSERT((m_WindowID > 0) && (m_WindowID <= 127)); if (a_WindowType == wtInventory) { m_WindowID = 0; } } cWindow::~cWindow() { for (cSlotAreas::iterator itr = m_SlotAreas.begin(), end = m_SlotAreas.end(); itr != end; ++itr) { delete *itr; } m_SlotAreas.clear(); } const AString cWindow::GetWindowTypeName(void) const { switch (m_WindowType) { case wtChest: return "minecraft:chest"; case wtWorkbench: return "minecraft:crafting_table"; case wtFurnace: return "minecraft:furnace"; case wtDropSpenser: return "minecraft:dispenser"; case wtEnchantment: return "minecraft:enchanting_table"; case wtBrewery: return "minecraft:brewing_stand"; case wtNPCTrade: return "minecraft:villager"; case wtBeacon: return "minecraft:beacon"; case wtAnvil: return "minecraft:anvil"; case wtHopper: return "minecraft:hopper"; case wtDropper: return "minecraft:dropper"; case wtAnimalChest: return "EntityHorse"; default: { ASSERT(!"Unknown inventory type!"); return ""; } } } int cWindow::GetNumSlots(void) const { int res = 0; for (const auto & itr : m_SlotAreas) { res += itr->GetNumSlots(); } // for itr - m_SlotAreas[] return res; } const cItem * cWindow::GetSlot(cPlayer & a_Player, int a_SlotNum) const { // Return the item at the specified slot for the specified player int LocalSlotNum = 0; const cSlotArea * Area = GetSlotArea(a_SlotNum, LocalSlotNum); if (Area == nullptr) { LOGWARNING("%s: requesting item from an invalid SlotArea (SlotNum %d), returning nullptr.", __FUNCTION__, a_SlotNum); return nullptr; } return Area->GetSlot(LocalSlotNum, a_Player); } void cWindow::SetSlot(cPlayer & a_Player, int a_SlotNum, const cItem & a_Item) { // Set the item to the specified slot for the specified player int LocalSlotNum = 0; cSlotArea * Area = GetSlotArea(a_SlotNum, LocalSlotNum); if (Area == nullptr) { LOGWARNING("%s: requesting write to an invalid SlotArea (SlotNum %d), ignoring.", __FUNCTION__, a_SlotNum); return; } Area->SetSlot(LocalSlotNum, a_Player, a_Item); } bool cWindow::IsSlotInPlayerMainInventory(int a_SlotNum) const { // Returns true if the specified slot is in the Player Main Inventory slotarea // The player main inventory is always 27 slots, 9 slots from the end of the inventory return ((a_SlotNum >= GetNumSlots() - 36) && (a_SlotNum < GetNumSlots() - 9)); } bool cWindow::IsSlotInPlayerHotbar(int a_SlotNum) const { // Returns true if the specified slot is in the Player Hotbar slotarea // The hotbar is always the last 9 slots return ((a_SlotNum >= GetNumSlots() - 9) && (a_SlotNum < GetNumSlots())); } bool cWindow::IsSlotInPlayerInventory(int a_SlotNum) const { // Returns true if the specified slot is in the Player Main Inventory or Hotbar slotareas. Note that returns false for Armor. // The player combined inventory is always the last 36 slots return ((a_SlotNum >= GetNumSlots() - 36) && (a_SlotNum < GetNumSlots())); } void cWindow::GetSlots(cPlayer & a_Player, cItems & a_Slots) const { a_Slots.clear(); a_Slots.reserve(static_cast(GetNumSlots())); for (cSlotAreas::const_iterator itr = m_SlotAreas.begin(), end = m_SlotAreas.end(); itr != end; ++itr) { int NumSlots = (*itr)->GetNumSlots(); for (int i = 0; i < NumSlots; i++) { const cItem * Item = (*itr)->GetSlot(i, a_Player); if (Item == nullptr) { a_Slots.push_back(cItem()); } else { a_Slots.push_back(*Item); } } } // for itr - m_SlotAreas[] } void cWindow::Clicked( cPlayer & a_Player, int a_WindowID, short a_SlotNum, eClickAction a_ClickAction, const cItem & a_ClickedItem ) { cPluginManager * PlgMgr = cRoot::Get()->GetPluginManager(); if (a_WindowID != m_WindowID) { LOGWARNING("%s: Wrong window ID (exp %d, got %d) received from \"%s\"; ignoring click.", __FUNCTION__, m_WindowID, a_WindowID, a_Player.GetName().c_str()); return; } switch (a_ClickAction) { case caLeftClickOutside: case caRightClickOutside: { if (PlgMgr->CallHookPlayerTossingItem(a_Player)) { // A plugin doesn't agree with the tossing. The plugin itself is responsible for handling the consequences (possible inventory mismatch) return; } if (a_Player.IsGameModeCreative()) { a_Player.TossPickup(a_ClickedItem); } if (a_ClickAction == caLeftClickOutside) { // Toss all dragged items: a_Player.TossHeldItem(a_Player.GetDraggingItem().m_ItemCount); } else { // Toss one of the dragged items: a_Player.TossHeldItem(); } return; } case caLeftClickOutsideHoldNothing: case caRightClickOutsideHoldNothing: { // Nothing needed return; } case caLeftPaintBegin: OnPaintBegin (a_Player); return; case caRightPaintBegin: OnPaintBegin (a_Player); return; case caMiddlePaintBegin: OnPaintBegin (a_Player); return; case caLeftPaintProgress: OnPaintProgress (a_Player, a_SlotNum); return; case caRightPaintProgress: OnPaintProgress (a_Player, a_SlotNum); return; case caMiddlePaintProgress: OnPaintProgress (a_Player, a_SlotNum); return; case caLeftPaintEnd: OnLeftPaintEnd (a_Player); return; case caRightPaintEnd: OnRightPaintEnd (a_Player); return; case caMiddlePaintEnd: OnMiddlePaintEnd(a_Player); return; default: { break; } } if (a_SlotNum < 0) { // TODO: Other click actions with irrelevant slot number (FS #371) return; } int LocalSlotNum = a_SlotNum; for (const auto & itr : m_SlotAreas) { if (LocalSlotNum < itr->GetNumSlots()) { itr->Clicked(a_Player, LocalSlotNum, a_ClickAction, a_ClickedItem); return; } LocalSlotNum -= itr->GetNumSlots(); } LOGWARNING("Slot number higher than available window slots: %d, max %d received from \"%s\"; ignoring.", a_SlotNum, GetNumSlots(), a_Player.GetName().c_str() ); } void cWindow::OpenedByPlayer(cPlayer & a_Player) { { cCSLock Lock(m_CS); // If player is already in OpenedBy remove player first m_OpenedBy.remove(&a_Player); // Then add player m_OpenedBy.push_back(&a_Player); for (cSlotAreas::iterator itr = m_SlotAreas.begin(), end = m_SlotAreas.end(); itr != end; ++itr) { (*itr)->OnPlayerAdded(a_Player); } // for itr - m_SlotAreas[] } a_Player.GetClientHandle()->SendWindowOpen(*this); } bool cWindow::ClosedByPlayer(cPlayer & a_Player, bool a_CanRefuse) { // Checks whether the player is still holding an item if (!a_Player.GetDraggingItem().IsEmpty()) { LOGD("Player is holding an item while closing their window, dropping it as a pickup..."); a_Player.TossHeldItem(a_Player.GetDraggingItem().m_ItemCount); } cClientHandle * ClientHandle = a_Player.GetClientHandle(); if (ClientHandle != nullptr) { ClientHandle->SendWindowClose(*this); } { cCSLock Lock(m_CS); for (cSlotAreas::iterator itr = m_SlotAreas.begin(), end = m_SlotAreas.end(); itr != end; ++itr) { (*itr)->OnPlayerRemoved(a_Player); } // for itr - m_SlotAreas[] if (m_WindowType != wtInventory) { m_OpenedBy.remove(&a_Player); if (m_OpenedBy.empty()) { Destroy(); } } } if (m_IsDestroyed) { delete this; } return true; } void cWindow::BroadcastSlot(cSlotArea * a_Area, int a_LocalSlotNum) { // Translate local slot num into global slot num: int SlotNum = 0; bool HasFound = false; for (cSlotAreas::const_iterator itr = m_SlotAreas.begin(), end = m_SlotAreas.end(); itr != end; ++itr) { if (a_Area == *itr) { SlotNum += a_LocalSlotNum; HasFound = true; break; } SlotNum += (*itr)->GetNumSlots(); } // for itr - m_SlotAreas[] if (!HasFound) { LOGWARNING("%s: Invalid slot area parameter", __FUNCTION__); ASSERT(!"Invalid slot area"); return; } // Broadcast the update packet: cCSLock Lock(m_CS); for (cPlayerList::iterator itr = m_OpenedBy.begin(); itr != m_OpenedBy.end(); ++itr) { (*itr)->GetClientHandle()->SendInventorySlot(m_WindowID, static_cast(SlotNum), *a_Area->GetSlot(a_LocalSlotNum, **itr)); } // for itr - m_OpenedBy[] } void cWindow::SendWholeWindow(cClientHandle & a_Client) { a_Client.SendWholeInventory(*this); } void cWindow::BroadcastWholeWindow(void) { cCSLock Lock(m_CS); for (auto Player : m_OpenedBy) { SendWholeWindow(*Player->GetClientHandle()); } } void cWindow::SetProperty(size_t a_Property, short a_Value) { cCSLock Lock(m_CS); for (auto Player : m_OpenedBy) { Player->GetClientHandle()->SendWindowProperty(*this, a_Property, a_Value); } } void cWindow::OwnerDestroyed() { // Close window for each player. Note that the last one needs special handling while (m_OpenedBy.size() > 1) { (*m_OpenedBy.begin())->CloseWindow(); } (*m_OpenedBy.begin())->CloseWindow(); } bool cWindow::ForEachPlayer(cPlayerListCallback a_Callback) { cCSLock Lock(m_CS); for (auto & Player : m_OpenedBy) { if (a_Callback(*Player)) { return false; } } // for itr - m_OpenedBy[] return true; } bool cWindow::ForEachClient(cClientHandleCallback a_Callback) { cCSLock Lock(m_CS); for (auto & Player : m_OpenedBy) { if (a_Callback(*Player->GetClientHandle())) { return false; } } // for itr - m_OpenedBy[] return true; } void cWindow::DistributeStackToAreas(cItem & a_ItemStack, cPlayer & a_Player, cSlotAreas & a_AreasInOrder, bool a_ShouldApply, bool a_BackFill) { /* Ask each slot area to take as much of the stack as it can. First ask only slots that already have the same kind of item Then ask any remaining slots */ for (size_t Pass = 0; Pass < 2; Pass++) { for (auto SlotArea : a_AreasInOrder) { SlotArea->DistributeStack(a_ItemStack, a_Player, a_ShouldApply, (Pass == 0), a_BackFill); if (a_ItemStack.IsEmpty()) { // Distributed it all return; } } } } bool cWindow::CollectItemsToHand(cItem & a_Dragging, cSlotArea & a_Area, cPlayer & a_Player, bool a_CollectFullStacks) { // Ask to collect items from each slot area in order: for (auto Area : m_SlotAreas) { if (Area->CollectItemsToHand(a_Dragging, a_Player, a_CollectFullStacks)) { return true; // a_Dragging is full } } return false; // All areas processed } void cWindow::SendSlot(cPlayer & a_Player, cSlotArea * a_SlotArea, int a_RelativeSlotNum) { int SlotBase = 0; bool Found = false; for (cSlotAreas::iterator itr = m_SlotAreas.begin(), end = m_SlotAreas.end(); itr != end; ++itr) { if (*itr == a_SlotArea) { Found = true; break; } SlotBase += (*itr)->GetNumSlots(); } // for itr - m_SlotAreas[] if (!Found) { LOGERROR("cWindow::SendSlot(): unknown a_SlotArea"); ASSERT(!"cWindow::SendSlot(): unknown a_SlotArea"); return; } a_Player.GetClientHandle()->SendInventorySlot( m_WindowID, static_cast(a_RelativeSlotNum + SlotBase), *(a_SlotArea->GetSlot(a_RelativeSlotNum, a_Player)) ); } void cWindow::Destroy(void) { if (m_Owner != nullptr) { m_Owner->CloseWindow(); m_Owner = nullptr; } m_IsDestroyed = true; } cSlotArea * cWindow::GetSlotArea(int a_GlobalSlotNum, int & a_LocalSlotNum) { if ((a_GlobalSlotNum < 0) || (a_GlobalSlotNum >= GetNumSlots())) { LOGWARNING("%s: requesting an invalid SlotNum: %d out of %d slots", __FUNCTION__, a_GlobalSlotNum, GetNumSlots() - 1); ASSERT(!"Invalid SlotNum"); return nullptr; } // Iterate through all the SlotAreas, find the correct one int LocalSlotNum = a_GlobalSlotNum; for (cSlotAreas::iterator itr = m_SlotAreas.begin(), end = m_SlotAreas.end(); itr != end; ++itr) { if (LocalSlotNum < (*itr)->GetNumSlots()) { a_LocalSlotNum = LocalSlotNum; return *itr; } LocalSlotNum -= (*itr)->GetNumSlots(); } // for itr - m_SlotAreas[] // We shouldn't be here - the check at the beginnning should prevent this. Log and assert LOGWARNING("%s: GetNumSlots() is out of sync: %d; LocalSlotNum = %d", __FUNCTION__, GetNumSlots(), LocalSlotNum); ASSERT(!"Invalid GetNumSlots"); return nullptr; } const cSlotArea * cWindow::GetSlotArea(int a_GlobalSlotNum, int & a_LocalSlotNum) const { if ((a_GlobalSlotNum < 0) || (a_GlobalSlotNum >= GetNumSlots())) { LOGWARNING("%s: requesting an invalid SlotNum: %d out of %d slots", __FUNCTION__, a_GlobalSlotNum, GetNumSlots() - 1); ASSERT(!"Invalid SlotNum"); return nullptr; } // Iterate through all the SlotAreas, find the correct one int LocalSlotNum = a_GlobalSlotNum; for (cSlotAreas::const_iterator itr = m_SlotAreas.begin(), end = m_SlotAreas.end(); itr != end; ++itr) { if (LocalSlotNum < (*itr)->GetNumSlots()) { a_LocalSlotNum = LocalSlotNum; return *itr; } LocalSlotNum -= (*itr)->GetNumSlots(); } // for itr - m_SlotAreas[] // We shouldn't be here - the check at the beginnning should prevent this. Log and assert LOGWARNING("%s: GetNumSlots() is out of sync: %d; LocalSlotNum = %d", __FUNCTION__, GetNumSlots(), LocalSlotNum); ASSERT(!"Invalid GetNumSlots"); return nullptr; } void cWindow::OnPaintBegin(cPlayer & a_Player) { // Prepares the internal structures for inventory painting from the specified player a_Player.ClearInventoryPaintSlots(); } void cWindow::OnPaintProgress(cPlayer & a_Player, int a_SlotNum) { // Add the slot to the internal structures for inventory painting by the specified player a_Player.AddInventoryPaintSlot(a_SlotNum); } void cWindow::OnLeftPaintEnd(cPlayer & a_Player) { // Process the entire action stored in the internal structures for inventory painting // distribute as many items as possible const cSlotNums & SlotNums = a_Player.GetInventoryPaintSlots(); cItem ToDistribute(a_Player.GetDraggingItem()); char ToEachSlot = ToDistribute.m_ItemCount / static_cast(SlotNums.size()); char NumDistributed = DistributeItemToSlots(a_Player, ToDistribute, ToEachSlot, SlotNums); // Remove the items distributed from the dragging item: a_Player.GetDraggingItem().m_ItemCount -= NumDistributed; if (a_Player.GetDraggingItem().m_ItemCount == 0) { a_Player.GetDraggingItem().Empty(); } SendWholeWindow(*a_Player.GetClientHandle()); // To fix #2345 (custom recipes don't work when inventory-painting), we send the result slot explicitly once again // This is a fix for what seems like a client-side bug a_Player.GetClientHandle()->SendInventorySlot(m_WindowID, 0, *GetSlot(a_Player, 0)); } void cWindow::OnRightPaintEnd(cPlayer & a_Player) { // Process the entire action stored in the internal structures for inventory painting // distribute one item into each slot const cSlotNums & SlotNums = a_Player.GetInventoryPaintSlots(); cItem ToDistribute(a_Player.GetDraggingItem()); char NumDistributed = DistributeItemToSlots(a_Player, ToDistribute, 1, SlotNums); // Remove the items distributed from the dragging item: a_Player.GetDraggingItem().m_ItemCount -= NumDistributed; if (a_Player.GetDraggingItem().m_ItemCount == 0) { a_Player.GetDraggingItem().Empty(); } SendWholeWindow(*a_Player.GetClientHandle()); // To fix #2345 (custom recipes don't work when inventory-painting), we send the result slot explicitly once again // This is a fix for what seems like a client-side bug a_Player.GetClientHandle()->SendInventorySlot(m_WindowID, 0, *GetSlot(a_Player, 0)); } void cWindow::OnMiddlePaintEnd(cPlayer & a_Player) { if (!a_Player.IsGameModeCreative()) { // Midle click paint is only valid for creative mode return; } // Fill available slots with full stacks of the dragging item const auto & DraggingItem = a_Player.GetDraggingItem(); auto StackSize = DraggingItem.GetMaxStackSize(); if (0 < DistributeItemToSlots(a_Player, DraggingItem, StackSize, a_Player.GetInventoryPaintSlots(), false)) { // If any items were distibuted, set dragging item empty a_Player.GetDraggingItem().Empty(); } SendWholeWindow(*a_Player.GetClientHandle()); } char cWindow::DistributeItemToSlots(cPlayer & a_Player, const cItem & a_Item, char a_NumToEachSlot, const cSlotNums & a_SlotNums, bool a_LimitItems) { if (a_LimitItems && (static_cast(a_Item.m_ItemCount) < a_SlotNums.size())) { LOGWARNING("%s: Distributing less items (%d) than slots (%zu)", __FUNCTION__, static_cast(a_Item.m_ItemCount), a_SlotNums.size()); // This doesn't seem to happen with the 1.5.1 client, so we don't worry about it for now return 0; } // Distribute to individual slots, keep track of how many items were actually distributed (full stacks etc.) char NumDistributed = 0; for (cSlotNums::const_iterator itr = a_SlotNums.begin(), end = a_SlotNums.end(); itr != end; ++itr) { int LocalSlotNum = 0; cSlotArea * Area = GetSlotArea(*itr, LocalSlotNum); if (Area == nullptr) { LOGWARNING("%s: Bad SlotArea for slot %d", __FUNCTION__, *itr); continue; } // Modify the item at the slot cItem AtSlot(*Area->GetSlot(LocalSlotNum, a_Player)); char MaxStack = AtSlot.GetMaxStackSize(); if (AtSlot.IsEmpty()) { // Empty, just move all of it there: cItem ToStore(a_Item); ToStore.m_ItemCount = std::min(a_NumToEachSlot, MaxStack); Area->SetSlot(LocalSlotNum, a_Player, ToStore); NumDistributed += ToStore.m_ItemCount; } else if (AtSlot.IsEqual(a_Item)) { // Occupied, add and cap at MaxStack: char CanStore = std::min(a_NumToEachSlot, MaxStack - AtSlot.m_ItemCount); AtSlot.m_ItemCount += CanStore; Area->SetSlot(LocalSlotNum, a_Player, AtSlot); NumDistributed += CanStore; } } // for itr - SlotNums[] return NumDistributed; } ================================================ FILE: src/UI/Window.h ================================================ // Window.h // Interfaces to the cWindow class representing a UI window for a specific block #pragma once #include "../FunctionRef.h" #include "../ItemGrid.h" class cPlayer; class cWindowOwner; class cClientHandle; class cBrewingstandEntity; class cChestEntity; class cEnderChestEntity; class cFurnaceEntity; class cHopperEntity; class cMinecartWithChest; class cBeaconEntity; class cSlotArea; class cSlotAreaAnvil; class cWorld; typedef std::list cPlayerList; typedef std::vector cSlotAreas; using cPlayerListCallback = cFunctionRef; using cClientHandleCallback = cFunctionRef; // tolua_begin /** Represents a UI window. Each window has a list of players that are currently using it When there's no player using a window, it is destroyed. A window consists of several areas of slots with similar functionality - for example the crafting grid area, or the inventory area. Each area knows what its slots are (GetSlot() function) and can handle mouse clicks. The window acts only as a top-level container for those areas, redirecting the click events to the correct areas. Inventory painting, introduced in 1.5, is handled by the window, too */ class cWindow { public: enum WindowType { wtInventory = -1, // This value is never actually sent to a client wtChest = 0, wtWorkbench = 1, wtFurnace = 2, wtDropSpenser = 3, // Dropper or Dispenser wtEnchantment = 4, wtBrewery = 5, wtNPCTrade = 6, wtBeacon = 7, wtAnvil = 8, wtHopper = 9, wtDropper = 10, wtAnimalChest = 11, }; // tolua_end static const int c_NumInventorySlots = 36; cWindow(WindowType a_WindowType, const AString & a_WindowTitle); virtual ~cWindow(); char GetWindowID(void) const { return m_WindowID; } // tolua_export int GetWindowType(void) const { return m_WindowType; } // tolua_export /** Returns the textual representation of the window's type, such as "minecraft:chest". */ const AString GetWindowTypeName(void) const; // tolua_export cWindowOwner * GetOwner(void) { return m_Owner; } void SetOwner( cWindowOwner * a_Owner) { m_Owner = a_Owner; } /** Returns the total number of slots */ int GetNumSlots(void) const; /** Returns the number of slots, excluding the player's inventory (used for network protocols) */ int GetNumNonInventorySlots(void) const { return GetNumSlots() - c_NumInventorySlots; } // tolua_begin /** Returns the item at the specified slot for the specified player. Returns nullptr if invalid SlotNum requested */ const cItem * GetSlot(cPlayer & a_Player, int a_SlotNum) const; /** Sets the item to the specified slot for the specified player */ void SetSlot(cPlayer & a_Player, int a_SlotNum, const cItem & a_Item); /** Returns true if the specified slot is in the Player Main Inventory slotarea */ bool IsSlotInPlayerMainInventory(int a_SlotNum) const; /** Returns true if the specified slot is in the Player Hotbar slotarea */ bool IsSlotInPlayerHotbar(int a_SlotNum) const; /** Returns true if the specified slot is in the Player Main Inventory or Hotbar slotareas. Note that returns false for Armor. */ bool IsSlotInPlayerInventory(int a_SlotNum) const; // tolua_end /** Fills a_Slots with the slots read from m_SlotAreas[], for the specified player */ void GetSlots(cPlayer & a_Player, cItems & a_Slots) const; /** Handles a click event from a player */ virtual void Clicked( cPlayer & a_Player, int a_WindowID, short a_SlotNum, eClickAction a_ClickAction, const cItem & a_ClickedItem ); virtual void OpenedByPlayer(cPlayer & a_Player); /** Called when a player closes this window; notifies all slot areas. Returns true if close accepted */ virtual bool ClosedByPlayer(cPlayer & a_Player, bool a_CanRefuse); /** Sends the specified slot's contents to all clients of this window; the slot is specified as local in an area */ void BroadcastSlot(cSlotArea * a_Area, int a_LocalSlotNum); /** Sends the contents of the whole window to the specified client */ void SendWholeWindow(cClientHandle & a_Client); /** Sends the contents of the whole window to all clients of this window. */ void BroadcastWholeWindow(void); // tolua_begin const AString & GetWindowTitle() const { return m_WindowTitle; } void SetWindowTitle(const AString & a_WindowTitle) { m_WindowTitle = a_WindowTitle; } /** Updates a numerical property associated with the window. Typically used for furnace progressbars. Sends the UpdateWindowProperty packet to all clients of the window */ virtual void SetProperty(size_t a_Property, short a_Value); // tolua_end void OwnerDestroyed(void); /** Calls the callback safely for each player that has this window open; returns true if all players have been enumerated */ bool ForEachPlayer(cPlayerListCallback a_Callback); /** Calls the callback safely for each client that has this window open; returns true if all clients have been enumerated */ bool ForEachClient(cClientHandleCallback a_Callback); /** Called on shift-clicking to distribute the stack into other areas; Modifies a_ItemStack as it is distributed! if a_ShouldApply is true, the changes are written into the slots; if a_ShouldApply is false, only a_ItemStack is modified to reflect the number of fits (for fit-testing purposes) */ virtual void DistributeStack(cItem & a_ItemStack, int a_Slot, cPlayer & a_Player, cSlotArea * a_ClickedArea, bool a_ShouldApply) = 0; /** Called from DistributeStack() to distribute the stack into a_AreasInOrder; Modifies a_ItemStack as it is distributed! If a_ShouldApply is true, the changes are written into the slots; if a_ShouldApply is false, only a_ItemStack is modified to reflect the number of fits (for fit-testing purposes) If a_BackFill is true, the areas will be filled from the back (right side). (Example: Empty Hotbar -> Item get in slot 8, not slot 0) */ void DistributeStackToAreas(cItem & a_ItemStack, cPlayer & a_Player, cSlotAreas & a_AreasInOrder, bool a_ShouldApply, bool a_BackFill); /** Called on DblClicking to collect all stackable items from all areas into hand. The items are accumulated in a_Dragging and removed from the SlotAreas immediately. If a_CollectFullStacks is false, slots with full stacks in the area are skipped while collecting. Returns true if full stack has been collected, false if there's space remaining to fill. */ bool CollectItemsToHand(cItem & a_Dragging, cSlotArea & a_Area, cPlayer & a_Player, bool a_CollectFullStacks); /** Used by cSlotAreas to send individual slots to clients, a_RelativeSlotNum is the slot number relative to a_SlotArea */ void SendSlot(cPlayer & a_Player, cSlotArea * a_SlotArea, int a_RelativeSlotNum); protected: cSlotAreas m_SlotAreas; char m_WindowID; int m_WindowType; AString m_WindowTitle; cCriticalSection m_CS; cPlayerList m_OpenedBy; bool m_IsDestroyed; cWindowOwner * m_Owner; static Byte m_WindowIDCounter; /** Sets the internal flag as "destroyed"; notifies the owner that the window is destroying */ virtual void Destroy(void); /** Returns the correct slot area for the specified window-global SlotNum Also returns the area-local SlotNum corresponding to the GlobalSlotNum If the global SlotNum is out of range, returns nullptr */ cSlotArea * GetSlotArea(int a_GlobalSlotNum, int & a_LocalSlotNum); /** Returns the correct slot area for the specified window-global SlotNum Also returns the area-local SlotNum corresponding to the GlobalSlotNum If the global SlotNum is out of range, returns nullptr. Const version. */ const cSlotArea * GetSlotArea(int a_GlobalSlotNum, int & a_LocalSlotNum) const; /** Prepares the internal structures for inventory painting from the specified player */ void OnPaintBegin(cPlayer & a_Player); /** Adds the slot to the internal structures for inventory painting by the specified player */ void OnPaintProgress(cPlayer & a_Player, int a_SlotNum); /** Processes the entire action stored in the internal structures for inventory painting; distributes as many items as possible */ void OnLeftPaintEnd(cPlayer & a_Player); /** Processes the entire action stored in the internal structures for inventory painting; distributes one item into each slot */ void OnRightPaintEnd(cPlayer & a_Player); /** Processes the entire action stored in the internal structures for inventory painting; distributes a full stack into each slot */ void OnMiddlePaintEnd(cPlayer & a_Player); /** Distributes a_NumToEachSlot items into the slots specified in a_SlotNums; returns the total number of items distributed. @param a_LimitItems if false, no checks are performed on a_Item.m_ItemCount. */ char DistributeItemToSlots(cPlayer & a_Player, const cItem & a_Item, char a_NumToEachSlot, const cSlotNums & a_SlotNums, bool a_LimitItems = true); } ; // tolua_export ================================================ FILE: src/UI/WindowOwner.h ================================================ #pragma once #include "../BlockEntities/BlockEntity.h" #include "../Entities/Entity.h" #include "Window.h" /* Being a descendant of cWindowOwner means that the class can own one window. That window can be queried, opened by other players, closed by players and finally destroyed. Also, a cWindowOwner can be queried for the block coords where the window is displayed. That will be used for entities / players in motion to close their windows when they get too far away from the window "source". */ /** Base class for the window owning */ class cWindowOwner { public: cWindowOwner() : m_Window(nullptr) { } virtual ~cWindowOwner() { } void CloseWindow(void) { m_Window = nullptr; } void OpenWindow(cWindow * a_Window) { m_Window = a_Window; m_Window->SetOwner(this); } cWindow * GetWindow(void) const { return m_Window; } /** Returns the block position at which the element owning the window is */ virtual Vector3i GetBlockPos(void) = 0; private: cWindow * m_Window; }; /** Window owner that is associated with a block entity (chest, furnace, ...) */ class cBlockEntityWindowOwner : public cWindowOwner { public: cBlockEntityWindowOwner(cBlockEntity * a_BlockEntity) : m_BlockEntity(a_BlockEntity) { } virtual Vector3i GetBlockPos(void) override { return Vector3i(m_BlockEntity->GetPosX(), m_BlockEntity->GetPosY(), m_BlockEntity->GetPosZ()); } private: cBlockEntity * m_BlockEntity; }; /** Window owner that is associated with an entity (chest minecart etc.) */ class cEntityWindowOwner : public cWindowOwner { public: cEntityWindowOwner(cEntity * a_Entity) : m_Entity(a_Entity) { } virtual Vector3i GetBlockPos(void) override { return m_Entity->GetPosition().Floor(); } private: cEntity * m_Entity; }; ================================================ FILE: src/UUID.cpp ================================================ // UUID.h // Defines the cUUID class representing a Universally Unique Identifier #include "Globals.h" #include "UUID.h" #include "mbedtls/md5.h" /** UUID normalised in textual form. */ struct sShortUUID { char Data[32]{}; bool IsValid = false; }; /** Returns the given UUID in shortened form with IsValid indicating success. Doesn't check digits are hexadecimal but does check dashes if long form. */ static sShortUUID ShortenUUID(const AString & a_StringUUID) { sShortUUID UUID; switch (a_StringUUID.size()) { case 32: { // Already a short UUID std::memcpy(UUID.Data, a_StringUUID.data(), 32); UUID.IsValid = true; break; } case 36: { // Long UUID, confirm dashed if ( (a_StringUUID[ 8] != '-') || (a_StringUUID[13] != '-') || (a_StringUUID[18] != '-') || (a_StringUUID[23] != '-') ) { break; } // Copy everying but the dashes from the string std::memcpy(UUID.Data, a_StringUUID.data(), 8); std::memcpy(UUID.Data + 8, a_StringUUID.data() + 9, 4); std::memcpy(UUID.Data + 12, a_StringUUID.data() + 14, 4); std::memcpy(UUID.Data + 16, a_StringUUID.data() + 19, 4); std::memcpy(UUID.Data + 20, a_StringUUID.data() + 24, 12); UUID.IsValid = true; } default: break; } return UUID; } /** Returns the integer value of the hex digit or 0xff if invalid. */ static Byte FromHexDigit(char a_Hex) { if (('0' <= a_Hex) && (a_Hex <= '9')) { return static_cast(a_Hex - '0'); } if (('a' <= a_Hex) && (a_Hex <= 'f')) { return static_cast(10 + (a_Hex - 'a')); } if (('A' <= a_Hex) && (a_Hex <= 'F')) { return static_cast(10 + (a_Hex - 'A')); } return 0xff; } /** From a number in the range [0, 16), returns the corresponding hex digit in lowercase. */ static char ToHexDigit(UInt8 a_Nibble) { ASSERT((a_Nibble & 0xf0) == 0); return static_cast( (a_Nibble < 10) ? ('0' + a_Nibble) : ('a' + (a_Nibble - 10)) ); } //////////////////////////////////////////////////////////////////////////////// // cUUID: bool cUUID::FromString(const AString & a_StringUUID) { sShortUUID Norm = ShortenUUID(a_StringUUID); if (!Norm.IsValid) { return false; } std::array ParsedUUID{{0}}; for (size_t i = 0; i != m_UUID.size(); ++i) { Byte HighNibble = FromHexDigit(Norm.Data[2 * i ]); Byte LowNibble = FromHexDigit(Norm.Data[2 * i + 1]); if ((HighNibble > 0x0f) || (LowNibble > 0x0f)) { // Invalid hex digit return false; } ParsedUUID[i] = static_cast((HighNibble << 4) | LowNibble); } // Parsed successfully m_UUID = ParsedUUID; return true; } AString cUUID::ToShortString() const { AString ShortString(32, '\0'); for (size_t i = 0; i != m_UUID.size(); ++i) { Byte HighNibble = (m_UUID[i] >> 4) & 0x0f; Byte LowNibble = m_UUID[i] & 0x0f; ShortString[2 * i ] = ToHexDigit(HighNibble); ShortString[2 * i + 1] = ToHexDigit(LowNibble); } return ShortString; } AString cUUID::ToLongString() const { AString LongString = ToShortString(); LongString.reserve(36); // Convert to long form by inserting the dashes auto First = LongString.begin(); LongString.insert(First + 8, '-'); LongString.insert(First + 13, '-'); LongString.insert(First + 18, '-'); LongString.insert(First + 23, '-'); return LongString; } UInt8 cUUID::Version() const { return static_cast((m_UUID[6] >> 4) & 0x0f); } UInt8 cUUID::Variant() const { const Byte VariantBits = static_cast((m_UUID[8] >> 5) & 0x07); /* Variant bits format: bits | variant | Description -----|---------|---------------------- 0xx | 0 | Obsolete 10x | 1 | Standard UUID 110 | 2 | Microsoft Legacy GUID 111 | 3 | Reserved */ if ((VariantBits & 0x04) == 0) { return 0; } else if ((VariantBits & 0x02) == 0) { return 1; } else if ((VariantBits & 0x01) == 0) { return 2; } else { return 3; } } std::array cUUID::ToRaw() const { std::array Raw(m_UUID); if (Variant() == 2) { // Convert to microsoft mixed-endian format // First 3 components are host-endian, last 2 are network auto First = reinterpret_cast(Raw.data()); *First = ntohl(*First); auto Second = reinterpret_cast(&Raw[4]); *Second = ntohs(*Second); auto Third = Second + 1; *Third = ntohs(*Third); } return Raw; } void cUUID::FromRaw(const std::array & a_Raw) { m_UUID = a_Raw; if (Variant() != 2) { // Standard big-endian formats return; } // Convert from microsoft mixed-endian format // First 3 components are host-endian, last 2 are network auto First = reinterpret_cast(m_UUID.data()); *First = htonl(*First); auto Second = reinterpret_cast(&m_UUID[4]); *Second = htons(*Second); auto Third = Second + 1; *Third = htons(*Third); } cUUID cUUID::GenerateVersion3(const AString & a_Name) { cUUID UUID; // Generate an md5 checksum, and use it as base for the ID: const Byte * ByteString = reinterpret_cast(a_Name.data()); mbedtls_md5(ByteString, a_Name.length(), UUID.m_UUID.data()); // Insert version number UUID.m_UUID[6] = (UUID.m_UUID[6] & 0x0f) | 0x30; // Insert variant number UUID.m_UUID[8] = (UUID.m_UUID[8] & 0x3f) | 0x80; return UUID; } ================================================ FILE: src/UUID.h ================================================ // UUID.h // Declares the cUUID class representing a Universally Unique Identifier #pragma once // tolua_begin class cUUID { public: /** Default constructed "nil" UUID */ cUUID(): m_UUID() { } /** Lexicographically compare bytes with another UUID. Returns: 0 when equal to a_Other, < 0 when less than a_Other, > 0 when greater than a_Other */ int Compare(const cUUID & a_Other) const { return std::memcmp(m_UUID.data(), a_Other.m_UUID.data(), m_UUID.size()); } /** Returns true if this contains the "nil" UUID with all bits set to 0 */ bool IsNil() const { return (m_UUID == std::array{{0}}); } /** Tries to interpret the string as a short or long form UUID and assign from it. On error, returns false and does not set the value. */ bool FromString(const AString & a_StringUUID); /** Converts the UUID to a short form string (i.e without dashes). */ AString ToShortString() const; /** Converts the UUID to a long form string (i.e. with dashes). */ AString ToLongString() const; /** Returns the version number of the UUID. */ UInt8 Version() const; /** Returns the variant number of the UUID. */ UInt8 Variant() const; /** Generates a version 3, variant 1 UUID based on the md5 hash of a_Name. */ static cUUID GenerateVersion3(const AString & a_Name); // tolua_end /** Converts UUID to raw memory representation, respecting UUID variant. */ std::array ToRaw() const; /** Assigns from raw memory representation, respecting UUID variant. */ void FromRaw(const std::array & a_Raw); private: /** Binary UUID stored big-endian. */ std::array m_UUID; }; // tolua_export // Comparison operators: inline bool operator == (const cUUID & a_Lhs, const cUUID & a_Rhs) { return (a_Lhs.Compare(a_Rhs) == 0); } inline bool operator != (const cUUID & a_Lhs, const cUUID & a_Rhs) { return (a_Lhs.Compare(a_Rhs) != 0); } inline bool operator < (const cUUID & a_Lhs, const cUUID & a_Rhs) { return (a_Lhs.Compare(a_Rhs) < 0); } inline bool operator <= (const cUUID & a_Lhs, const cUUID & a_Rhs) { return (a_Lhs.Compare(a_Rhs) <= 0); } inline bool operator > (const cUUID & a_Lhs, const cUUID & a_Rhs) { return (a_Lhs.Compare(a_Rhs) > 0); } inline bool operator >= (const cUUID & a_Lhs, const cUUID & a_Rhs) { return (a_Lhs.Compare(a_Rhs) >= 0); } ================================================ FILE: src/Vector3.h ================================================ #pragma once template // tolua_begin class Vector3 { TOLUA_TEMPLATE_BIND((T, int, float, double)) public: T x, y, z; constexpr Vector3(void) : x(0), y(0), z(0) {} constexpr Vector3(T a_x, T a_y, T a_z) : x(a_x), y(a_y), z(a_z) {} #ifdef TOLUA_EXPOSITION // Hardcoded copy constructors (tolua++ does not support function templates .. yet) Vector3(const Vector3 & a_Rhs); Vector3(const Vector3 & a_Rhs); Vector3(const Vector3 & a_Rhs); #endif // tolua_end // Conversion constructors where U is not the same as T leaving the copy-constructor implicitly generated template ::value) && ((!std::is_integral::value) || (std::is_integral::value)), bool> = true> constexpr Vector3(const Vector3 & a_Rhs): x(static_cast(a_Rhs.x)), y(static_cast(a_Rhs.y)), z(static_cast(a_Rhs.z)) { } template ::value) && ((std::is_integral::value) && (!std::is_integral::value)), bool> = true> constexpr Vector3(const Vector3 & a_Rhs): x(static_cast(std::floor(a_Rhs.x))), y(static_cast(std::floor(a_Rhs.y))), z(static_cast(std::floor(a_Rhs.z))) { } // tolua_begin inline void Set(T a_x, T a_y, T a_z) { x = a_x; y = a_y; z = a_z; } inline void Normalize(void) { double Len = 1.0 / Length(); x = static_cast(x * Len); y = static_cast(y * Len); z = static_cast(z * Len); } inline Vector3 NormalizeCopy(void) const { double Len = 1.0 / Length(); return Vector3( static_cast(x * Len), static_cast(y * Len), static_cast(z * Len) ); } // tolua_end /** Sets the given vector to the normalized version of this vector. Removed from LuaAPI, because Lua doesn't need distinguishing from the other overload. */ inline void NormalizeCopy(Vector3 & a_Rhs) const { double Len = 1.0 / Length(); a_Rhs.Set( static_cast(x * Len), static_cast(y * Len), static_cast(z * Len) ); } // tolua_begin inline bool HasNonZeroLength(void) const { #ifdef __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wfloat-equal" #endif return ((x != 0) || (y != 0) || (z != 0)); #ifdef __clang__ #pragma clang diagnostic pop #endif } inline double Length(void) const { return sqrt(static_cast(x * x + y * y + z * z)); } inline double SqrLength(void) const { return x * x + y * y + z * z; } inline T Dot(const Vector3 & a_Rhs) const { return x * a_Rhs.x + y * a_Rhs.y + z * a_Rhs.z; } /** Updates each coord to its absolute value */ inline void Abs() { x = std::abs(x); y = std::abs(y); z = std::abs(z); } /** Clamps each coord into the specified range. */ inline void Clamp(T a_Min, T a_Max) { x = ::Clamp(x, a_Min, a_Max); y = ::Clamp(y, a_Min, a_Max); z = ::Clamp(z, a_Min, a_Max); } inline Vector3 Cross(const Vector3 & a_Rhs) const { return Vector3( y * a_Rhs.z - z * a_Rhs.y, z * a_Rhs.x - x * a_Rhs.z, x * a_Rhs.y - y * a_Rhs.x ); } inline bool Equals(const Vector3 & a_Rhs) const { // Perform a strict comparison of the contents - we want to know whether this object is exactly equal // To perform EPS-based comparison, use the EqualsEps() function #ifdef __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wfloat-equal" #endif return !((x != a_Rhs.x) || (y != a_Rhs.y) || (z != a_Rhs.z)); #ifdef __clang__ #pragma clang diagnostic pop #endif } inline bool EqualsEps(const Vector3 & a_Rhs, T a_Eps) const { return (std::abs(x - a_Rhs.x) < a_Eps) && (std::abs(y - a_Rhs.y) < a_Eps) && (std::abs(z - a_Rhs.z) < a_Eps); } inline void Move(T a_X, T a_Y, T a_Z) { x += a_X; y += a_Y; z += a_Z; } inline void Move(const Vector3 & a_Diff) { x += a_Diff.x; y += a_Diff.y; z += a_Diff.z; } /** Returns a new Vector3i with coords set to std::floor() of this vector's coords. */ inline Vector3 Floor(void) const { return Vector3( FloorC(x), FloorC(y), FloorC(z) ); } /** Returns a new Vector3i with coords set to std::ceil() of this vector's coords. */ inline Vector3 Ceil() const { return Vector3( CeilC(x), CeilC(y), CeilC(z) ); } // tolua_end inline bool operator != (const Vector3 & a_Rhs) const { return !Equals(a_Rhs); } inline bool operator == (const Vector3 & a_Rhs) const { return Equals(a_Rhs); } inline bool operator > (const Vector3 & a_Rhs) const { return (SqrLength() > a_Rhs.SqrLength()); } inline bool operator < (const Vector3 & a_Rhs) const { return (SqrLength() < a_Rhs.SqrLength()); } inline void operator += (const Vector3 & a_Rhs) { x += a_Rhs.x; y += a_Rhs.y; z += a_Rhs.z; } inline void operator -= (const Vector3 & a_Rhs) { x -= a_Rhs.x; y -= a_Rhs.y; z -= a_Rhs.z; } inline void operator *= (const Vector3 & a_Rhs) { x *= a_Rhs.x; y *= a_Rhs.y; z *= a_Rhs.z; } inline void operator *= (T a_v) { x *= a_v; y *= a_v; z *= a_v; } // tolua_begin inline Vector3 operator + (const Vector3& a_Rhs) const { return Vector3( x + a_Rhs.x, y + a_Rhs.y, z + a_Rhs.z ); } inline Vector3 operator - (const Vector3& a_Rhs) const { return Vector3( x - a_Rhs.x, y - a_Rhs.y, z - a_Rhs.z ); } inline Vector3 operator - (void) const { return Vector3(-x, -y, -z); } inline Vector3 operator * (const Vector3& a_Rhs) const { return Vector3( x * a_Rhs.x, y * a_Rhs.y, z * a_Rhs.z ); } inline Vector3 operator / (const Vector3 & a_Rhs) { return Vector3( x / a_Rhs.x, y / a_Rhs.y, z / a_Rhs.z ); } inline Vector3 operator * (T a_v) const { return Vector3( x * a_v, y * a_v, z * a_v ); } inline Vector3 operator / (T a_v) const { return Vector3( x / a_v, y / a_v, z / a_v ); } /** Returns a copy of this vector moved by the specified amount on the X axis. */ inline Vector3 addedX(T a_AddX) const { return Vector3(x + a_AddX, y, z); } /** Returns a copy of this vector moved by the specified amount on the y axis. */ inline Vector3 addedY(T a_AddY) const { return Vector3(x, y + a_AddY, z); } /** Returns a copy of this vector moved by the specified amount on the Z axis. */ inline Vector3 addedZ(T a_AddZ) const { return Vector3(x, y, z + a_AddZ); } /** Returns a copy of this vector moved by the specified amount on the X and Z axes. */ inline Vector3 addedXZ(T a_AddX, T a_AddZ) const { return Vector3(x + a_AddX, y, z + a_AddZ); } /** Returns the coefficient for the (a_OtherEnd - this) line to reach the specified Z coord. The result satisfies the following equation: (*this + Result * (a_OtherEnd - *this)).z = a_Z If the line is too close to being parallel, this function returns NO_INTERSECTION */ inline double LineCoeffToXYPlane(const Vector3 & a_OtherEnd, T a_Z) const { if (std::abs(z - a_OtherEnd.z) < EPS) { return NO_INTERSECTION; } return (a_Z - z) / (a_OtherEnd.z - z); } /** Returns the coefficient for the (a_OtherEnd - this) line to reach the specified Y coord. The result satisfies the following equation: (*this + Result * (a_OtherEnd - *this)).y = a_Y If the line is too close to being parallel, this function returns NO_INTERSECTION */ inline double LineCoeffToXZPlane(const Vector3 & a_OtherEnd, T a_Y) const { if (std::abs(y - a_OtherEnd.y) < EPS) { return NO_INTERSECTION; } return (a_Y - y) / (a_OtherEnd.y - y); } /** Returns the coefficient for the (a_OtherEnd - this) line to reach the specified X coord. The result satisfies the following equation: (*this + Result * (a_OtherEnd - *this)).x = a_X If the line is too close to being parallel, this function returns NO_INTERSECTION */ inline double LineCoeffToYZPlane(const Vector3 & a_OtherEnd, T a_X) const { if (std::abs(x - a_OtherEnd.x) < EPS) { return NO_INTERSECTION; } return (a_X - x) / (a_OtherEnd.x - x); } /** Rotates the vector 90 degrees clockwise around the vertical axis. Note that this is specific to minecraft's axis ordering, which is X+ left, Z+ down. */ inline void TurnCW(void) { std::swap(x, z); x = -x; } /** Rotates the vector 90 degrees counterclockwise around the vertical axis. Note that this is specific to minecraft's axis ordering, which is X+ left, Z+ down. */ inline void TurnCCW(void) { std::swap(x, z); z = -z; } /** The max difference between two coords for which the coords are assumed equal. */ static const double EPS; /** Return value of LineCoeffToPlane() if the line is parallel to the plane. */ static const double NO_INTERSECTION; }; // tolua_end /** Allows formatting a Vector using the same format specifiers as for T e.g. `fmt::format("{0:0.2f}", Vector3f{0.0231f, 1.2146f, 1.0f}) == "{0.02, 1.21, 1.00}"` */ template class fmt::formatter> : public fmt::formatter { using Super = fmt::formatter; template void Write(FormatContext & a_Ctx, const char (& a_Str)[Len]) { const auto Itr = std::copy_n(&a_Str[0], Len - 1, a_Ctx.out()); a_Ctx.advance_to(Itr); } template void Write(FormatContext & a_Ctx, const What & a_Arg) { const auto Itr = Super::format(a_Arg, a_Ctx); a_Ctx.advance_to(Itr); } public: template auto format(const Vector3 & a_Vec, FormatContext & a_Ctx) { Write(a_Ctx, "{"); Write(a_Ctx, a_Vec.x); Write(a_Ctx, ", "); Write(a_Ctx, a_Vec.y); Write(a_Ctx, ", "); Write(a_Ctx, a_Vec.z); Write(a_Ctx, "}"); return a_Ctx.out(); } }; template <> inline Vector3 Vector3::Floor(void) const { return *this; } template class VectorHasher { public: /** Provides a hash of a vector's contents */ size_t operator()(const Vector3 & a_Vector) const { // Guaranteed to have non repeating hashes for any 128x128x128 area size_t Hash = static_cast(a_Vector.y); Hash <<= 16; Hash ^= static_cast(a_Vector.x); Hash ^= static_cast(a_Vector.z) << 8; return Hash; } }; template const double Vector3::EPS = 0.000001; template const double Vector3::NO_INTERSECTION = 1e70; // tolua_begin typedef Vector3 Vector3d; typedef Vector3 Vector3f; typedef Vector3 Vector3i; // tolua_end typedef std::vector cVector3iArray; ================================================ FILE: src/VoronoiMap.cpp ================================================ // VoronoiMap.cpp // Implements the cVoronoiMap class that implements a Voronoi algorithm over a noise to produce a map #include "Globals.h" #include "VoronoiMap.h" cVoronoiMap::cVoronoiMap(int a_Seed, int a_CellSize, int a_JitterSize) : m_Noise1(a_Seed + 1), m_Noise2(a_Seed + 2), m_Noise3(a_Seed + 3), m_CellSize(std::max(a_CellSize, 2)), m_JitterSize(Clamp(a_JitterSize, 1, a_CellSize)), m_OddRowOffset(0), m_CurrentCellX(9999999), // Cell coords that are definitely out of the range for normal generator, so that the first query will overwrite them m_CurrentCellZ(9999999) { } void cVoronoiMap::SetCellSize(int a_CellSize) { a_CellSize = std::max(a_CellSize, 2); // Cell size must be at least 2 m_CellSize = a_CellSize; // For compatibility with previous version, which didn't have the jitter, we set jitter here as well. m_JitterSize = a_CellSize; } void cVoronoiMap::SetJitterSize(int a_JitterSize) { m_JitterSize = Clamp(a_JitterSize, 1, m_CellSize); } void cVoronoiMap::SetOddRowOffset(int a_OddRowOffset) { m_OddRowOffset = Clamp(a_OddRowOffset, -m_CellSize, m_CellSize); } int cVoronoiMap::GetValueAt(int a_X, int a_Y) { int SeedX, SeedY, MinDist2; return GetValueAt(a_X, a_Y, SeedX, SeedY, MinDist2); } int cVoronoiMap::GetValueAt(int a_X, int a_Y, int & a_MinDist) { int SeedX, SeedY, MinDist2; int res = GetValueAt(a_X, a_Y, SeedX, SeedY, MinDist2); a_MinDist = (a_X - SeedX) * (a_X - SeedX) + (a_Y - SeedY) * (a_Y - SeedY); return res; } int cVoronoiMap::GetValueAt( int a_X, int a_Y, // Coords to query int & a_NearestSeedX, int & a_NearestSeedY, // Coords of the closest cell int & a_MinDist2 // Distance to the second closest cell ) { int CellX = a_X / m_CellSize; int CellY = a_Y / m_CellSize; UpdateCell(CellX, CellY); // Get 5x5 neighboring cell seeds, compare distance to each. Return the value in the minumim-distance cell int NearestSeedX = 0, NearestSeedY = 0; int MinDist = m_CellSize * m_CellSize * 16; // There has to be a cell closer than this int MinDist2 = MinDist; int res = 0; // Will be overriden for (int x = 0; x < 5; x++) { for (int y = 0; y < 5; y++) { int SeedX = m_SeedX[x][y]; int SeedY = m_SeedZ[x][y]; int Dist = (SeedX - a_X) * (SeedX - a_X) + (SeedY - a_Y) * (SeedY - a_Y); if (Dist < MinDist) { NearestSeedX = SeedX; NearestSeedY = SeedY; MinDist2 = MinDist; MinDist = Dist; res = m_Noise3.IntNoise2DInt(x + CellX - 2, y + CellY - 2); } else if (Dist < MinDist2) { MinDist2 = Dist; } } // for z } // for x a_NearestSeedX = NearestSeedX; a_NearestSeedY = NearestSeedY; a_MinDist2 = MinDist2; return res; } void cVoronoiMap::FindNearestSeeds( int a_X, int a_Y, int & a_NearestSeedX, int & a_NearestSeedY, int & a_SecondNearestSeedX, int & a_SecondNearestSeedY ) { int CellX = a_X / m_CellSize; int CellY = a_Y / m_CellSize; UpdateCell(CellX, CellY); // Get 5x5 neighboring cell seeds, compare distance to each. Return the value in the minumim-distance cell int NearestSeedX = 0, NearestSeedY = 0; int SecondNearestSeedX = 0, SecondNearestSeedY = 0; int MinDist = m_CellSize * m_CellSize * 16; // There has to be a cell closer than this int MinDist2 = MinDist; for (int x = 0; x < 5; x++) { for (int y = 0; y < 5; y++) { int SeedX = m_SeedX[x][y]; int SeedY = m_SeedZ[x][y]; int Dist = (SeedX - a_X) * (SeedX - a_X) + (SeedY - a_Y) * (SeedY - a_Y); if (Dist < MinDist) { SecondNearestSeedX = NearestSeedX; SecondNearestSeedY = NearestSeedY; MinDist2 = MinDist; NearestSeedX = SeedX; NearestSeedY = SeedY; MinDist = Dist; } else if (Dist < MinDist2) { SecondNearestSeedX = SeedX; SecondNearestSeedY = SeedY; MinDist2 = Dist; } } // for z } // for x a_NearestSeedX = NearestSeedX; a_NearestSeedY = NearestSeedY; a_SecondNearestSeedX = SecondNearestSeedX; a_SecondNearestSeedY = SecondNearestSeedY; } void cVoronoiMap::UpdateCell(int a_CellX, int a_CellZ) { // If the specified cell is currently cached, bail out: if ((a_CellX == m_CurrentCellX) && (a_CellZ == m_CurrentCellZ)) { return; } // Update the cell cache for the new cell position: int NoiseBaseX = a_CellX - 2; int NoiseBaseZ = a_CellZ - 2; for (int x = 0; x < 5; x++) { int BaseX = (NoiseBaseX + x) * m_CellSize; int OddRowOffset = ((NoiseBaseX + x) & 0x01) * m_OddRowOffset; for (int z = 0; z < 5; z++) { int OffsetX = (m_Noise1.IntNoise2DInt(NoiseBaseX + x, NoiseBaseZ + z) / 8) % m_JitterSize; int OffsetZ = (m_Noise2.IntNoise2DInt(NoiseBaseX + x, NoiseBaseZ + z) / 8) % m_JitterSize; m_SeedX[x][z] = BaseX + OffsetX; m_SeedZ[x][z] = (NoiseBaseZ + z) * m_CellSize + OddRowOffset + OffsetZ; } // for z } // for x m_CurrentCellX = a_CellX; m_CurrentCellZ = a_CellZ; } ================================================ FILE: src/VoronoiMap.h ================================================ // VoronoiMap.h // Declares the cVoronoiMap class that implements a Voronoi algorithm over a noise to produce a map #pragma once #include "Noise/Noise.h" class cVoronoiMap { public: cVoronoiMap(int a_Seed, int a_CellSize = 128, int a_JitterSize = 128); /** Sets both the cell size and jitter size used for generating the Voronoi seeds. */ void SetCellSize(int a_CellSize); /** Sets the jitter size. Clamps it to current cell size. */ void SetJitterSize(int a_JitterSize); /** Sets the offset that is added to each odd row of cells. This offset makes the voronoi cells align to a non-grid. Clamps the value to [-m_CellSize, +m_CellSize]. */ void SetOddRowOffset(int a_OddRowOffset); /** Returns the value in the cell into which the specified point lies. */ int GetValueAt(int a_X, int a_Y); /** Returns the value in the cell into which the specified point lies, and the distance to the nearest Voronoi seed. */ int GetValueAt(int a_X, int a_Y, int & a_MinDistance); /** Returns the value in the cell into which the specified point lies, and the distances to the 2 nearest Voronoi seeds. Uses a cache. */ int GetValueAt( int a_X, int a_Y, // Coords to query int & a_NearestSeedX, int & a_NearestSeedY, // Coords of the closest cell's seed int & a_MinDist2 // Distance to the second closest cell's seed ); /** Finds the nearest and second nearest seeds, returns their coords. */ void FindNearestSeeds( int a_X, int a_Y, int & a_NearestSeedX, int & a_NearestSeedY, int & a_SecondNearestSeedX, int & a_SecondNearestSeedY ); protected: /** The noise used for generating Voronoi seeds */ cNoise m_Noise1; cNoise m_Noise2; cNoise m_Noise3; /** Size of the Voronoi cells (avg X / Y distance between the seeds). Expected to be at least 2. */ int m_CellSize; /** The amount that the cell seeds may be offset from the grid. Expected to be at least 1 and less than m_CellSize. */ int m_JitterSize; /** The constant amount that the cell seeds of every odd row will be offset from the grid. This allows us to have non-rectangular grids. Expected to be between -m_CellSize and +m_CellSize. */ int m_OddRowOffset; /** The X coordinate of the currently cached cell neighborhood */ int m_CurrentCellX; /** The Z coordinate of the currently cached cell neighborhood */ int m_CurrentCellZ; /** The seeds of cells around m_CurrentCellX, m_CurrentCellZ, X-coords */ int m_SeedX[5][5]; /** The seeds of cells around m_CurrentCellX, m_CurrentCellZ, X-coords */ int m_SeedZ[5][5]; /** Updates the cached cell seeds to match the specified cell. Noop if cell pos already matches. Updates m_SeedX and m_SeedZ. */ void UpdateCell(int a_CellX, int a_CellZ); } ; ================================================ FILE: src/WebAdmin.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "WebAdmin.h" #include "World.h" #include "Entities/Player.h" #include "Server.h" #include "Root.h" #include "HTTP/HTTPServerConnection.h" #include "HTTP/HTTPFormParser.h" static const char DEFAULT_WEBADMIN_PORTS[] = "8080"; //////////////////////////////////////////////////////////////////////////////// // cWebadminRequestData /** The form parser callbacks for requests in the "/webadmin" and "/~webadmin" paths */ class cWebadminRequestData : public cHTTPFormParser::cCallbacks, public cHTTPIncomingRequest::cUserData { public: cHTTPFormParser m_Form; cWebadminRequestData(const cHTTPIncomingRequest & a_Request): m_Form(a_Request, *this) { } // cHTTPFormParser::cCallbacks overrides. Files are ignored: virtual void OnFileStart(cHTTPFormParser &, const AString & a_FileName) override { UNUSED(a_FileName); } virtual void OnFileData(cHTTPFormParser &, const char * a_Data, size_t a_Size) override { UNUSED(a_Data); UNUSED(a_Size); } virtual void OnFileEnd(cHTTPFormParser &) override {} } ; //////////////////////////////////////////////////////////////////////////////// // cWebAdmin: cWebAdmin::cWebAdmin(void) : m_TemplateScript(""), m_IsInitialized(false), m_IsRunning(false) { } cWebAdmin::~cWebAdmin() { ASSERT(!m_IsRunning); // Was the HTTP server stopped properly? } bool cWebAdmin::Init(void) { if (!LoadIniFile()) { // WebAdmin is disabled, bail out faking a success return true; } LOGD("Initialising WebAdmin..."); Reload(); // Read the ports to be used: // Note that historically the ports were stored in the "Port" and "PortsIPv6" values m_Ports = ReadUpgradeIniPorts(m_IniFile, "WebAdmin", "Ports", "Port", "PortsIPv6", DEFAULT_WEBADMIN_PORTS); if (!m_HTTPServer.Initialize()) { return false; } m_IsInitialized = true; m_IniFile.WriteFile("webadmin.ini"); return true; } bool cWebAdmin::Start(void) { if (!m_IsInitialized) { // Not initialized return false; } LOGD("Starting WebAdmin..."); m_IsRunning = m_HTTPServer.Start(*this, m_Ports); return m_IsRunning; } void cWebAdmin::Stop(void) { if (!m_IsRunning) { return; } LOGD("Stopping WebAdmin..."); m_HTTPServer.Stop(); m_IsRunning = false; } bool cWebAdmin::LoadLoginPage(void) { cFile File("webadmin/login_template.html", cFile::fmRead); if (!File.IsOpen()) { return false; } AString TemplateContent; if (File.ReadRestOfFile(TemplateContent) == -1) { return false; } cCSLock Lock(m_CS); m_LoginPage = TemplateContent; return true; } void cWebAdmin::RemoveAllPluginWebTabs(const AString & a_PluginName) { cCSLock lock(m_CS); m_WebTabs.erase(std::remove_if(m_WebTabs.begin(), m_WebTabs.end(), [=](const cWebTabPtr & a_CBWebTab) { return (a_CBWebTab->m_PluginName == a_PluginName); }), m_WebTabs.end() ); } void cWebAdmin::Reload(void) { cCSLock lock(m_CS); if (!LoadIniFile()) { // We are asked to disable the webadmin, cannot do that, so warn the admin: LOGWARNING( "WebAdmin was previously enabled and now the settings say to disable it." " This will not take effect until you restart the server." ); } else if (!HasUsers()) { LOGWARNING( "The webadmin is enabled but has no users configured." " To add new users, edit webadmin.ini" ); } // Initialize the WebAdmin template script and reload the file: if (m_TemplateScript.IsValid()) { m_TemplateScript.Close(); } m_TemplateScript.Create(); m_TemplateScript.RegisterAPILibs(); if (!m_TemplateScript.LoadFile("webadmin/template.lua")) { LOGWARN("Could not load WebAdmin template \"%s\". WebAdmin will not work properly!", "webadmin/template.lua"); m_TemplateScript.Close(); } // Load the login template, provide a fallback default if not found: if (!LoadLoginPage()) { LOGWARN("Could not load WebAdmin login page \"%s\", using fallback template.", "webadmin/login_template.html"); // Set the fallback: m_LoginPage = \ "

    Cuberite WebAdmin

    " \ "
    " \ "
    " \ "" \ "" \ "
    "; } } bool cWebAdmin::LoadIniFile(void) { m_IniFile.Clear(); if (!m_IniFile.ReadFile("webadmin.ini")) { LOGWARN("Regenerating webadmin.ini, all settings will be reset"); m_IniFile.AddHeaderComment(" This file controls the webadmin feature of Cuberite"); m_IniFile.AddHeaderComment(" It specifies whether webadmin is enabled, and what logins are allowed. "); m_IniFile.AddHeaderComment(" Username format: [User:*username*]"); m_IniFile.AddHeaderComment(" Password format: Password=*password*; for example:"); m_IniFile.AddHeaderComment(" [User:admin]"); m_IniFile.AddHeaderComment(" Password=admin"); m_IniFile.AddHeaderComment(" Please restart Cuberite to apply changes made in this file!"); m_IniFile.SetValue("WebAdmin", "Ports", DEFAULT_WEBADMIN_PORTS); m_IniFile.WriteFile("webadmin.ini"); } return m_IniFile.GetValueSetB("WebAdmin", "Enabled", true); } bool cWebAdmin::HasUsers() { for (int i = 0; i < m_IniFile.GetNumKeys(); i++) { AString key = m_IniFile.GetKeyName(i); if (key.rfind("User:", 0) == 0) { return true; } } return false; } void cWebAdmin::HandleWebadminRequest(cHTTPServerConnection & a_Connection, cHTTPIncomingRequest & a_Request) { if (!a_Request.HasAuth()) { a_Connection.SendNeedAuth("Cuberite WebAdmin"); return; } // Check auth: { cCSLock Lock(m_CS); AString UserPassword = m_IniFile.GetValue("User:" + a_Request.GetAuthUsername(), "Password", ""); if ((UserPassword == "") || (a_Request.GetAuthPassword() != UserPassword)) { a_Connection.SendNeedAuth("Cuberite WebAdmin - bad username or password"); return; } } // Check if the contents should be wrapped in the template: auto BareURL = a_Request.GetURLPath(); ASSERT(BareURL.length() > 0); bool ShouldWrapInTemplate = (!BareURL.empty() && (BareURL[1] != '~')); // Retrieve the request data: auto Data = std::static_pointer_cast(a_Request.GetUserData()); if (Data == nullptr) { a_Connection.SendStatusAndReason(500, "Bad UserData"); return; } // Wrap it all up for the Lua call: AString Template; HTTPTemplateRequest TemplateRequest; TemplateRequest.Request.URL = a_Request.GetURL(); TemplateRequest.Request.Username = a_Request.GetAuthUsername(); TemplateRequest.Request.Method = a_Request.GetMethod(); TemplateRequest.Request.Path = BareURL.substr(1); if (Data->m_Form.Finish()) { for (cHTTPFormParser::const_iterator itr = Data->m_Form.begin(), end = Data->m_Form.end(); itr != end; ++itr) { HTTPFormData HTTPfd; HTTPfd.Value = itr->second; HTTPfd.Type = ""; HTTPfd.Name = itr->first; TemplateRequest.Request.FormData[itr->first] = HTTPfd; TemplateRequest.Request.PostParams[itr->first] = itr->second; } // for itr - Data->m_Form[] // Parse the URL into individual params: const AString & URL = a_Request.GetURL(); size_t idxQM = URL.find('?'); if (idxQM != AString::npos) { cHTTPFormParser URLParams(cHTTPFormParser::fpkURL, URL.c_str() + idxQM + 1, URL.length() - idxQM - 1, *Data); URLParams.Finish(); for (cHTTPFormParser::const_iterator itr = URLParams.begin(), end = URLParams.end(); itr != end; ++itr) { TemplateRequest.Request.Params[itr->first] = itr->second; } // for itr - URLParams[] } } // Try to get the template from the Lua template script if (ShouldWrapInTemplate) { cCSLock LockSelf(m_CS); cLuaState::cLock LockTemplate(m_TemplateScript); if (m_TemplateScript.Call("ShowPage", this, &TemplateRequest, cLuaState::Return, Template)) { cHTTPOutgoingResponse Resp; Resp.SetContentType("text/html"); a_Connection.Send(Resp); a_Connection.Send(Template.c_str(), Template.length()); a_Connection.FinishResponse(); return; } a_Connection.SendStatusAndReason(500, "m_TemplateScript failed"); return; } // Send the un-decorated page content: auto page = GetPage(TemplateRequest.Request); cHTTPOutgoingResponse resp; resp.SetContentType(page.ContentType); a_Connection.Send(resp); a_Connection.Send(page.Content.c_str(), page.Content.length()); a_Connection.FinishResponse(); } void cWebAdmin::HandleRootRequest(cHTTPServerConnection & a_Connection, cHTTPIncomingRequest & a_Request) { UNUSED(a_Request); cHTTPOutgoingResponse Resp; Resp.SetContentType("text/html"); a_Connection.Send(Resp); a_Connection.Send(m_LoginPage); a_Connection.FinishResponse(); } void cWebAdmin::HandleFileRequest(cHTTPServerConnection & a_Connection, cHTTPIncomingRequest & a_Request) { AString FileURL = a_Request.GetURL(); std::replace(FileURL.begin(), FileURL.end(), '\\', '/'); // Remove all leading backslashes: if (!FileURL.empty() && (FileURL[0] == '/')) { size_t FirstCharToRead = FileURL.find_first_not_of('/'); if (FirstCharToRead != AString::npos) { FileURL = FileURL.substr(FirstCharToRead); } } // Read the file contents and guess its mime-type, based on the extension: AString Content = "

    404 Not Found

    "; AString ContentType = "text/html"; AString Path = "webadmin/files/" + FileURL; // Return 404 if the file is not found, or the URL contains '../' (for security reasons) if ((FileURL.find("../") == AString::npos) && cFile::IsFile(Path)) { cFile File(Path, cFile::fmRead); AString FileContent; if (File.IsOpen() && (File.ReadRestOfFile(FileContent) != -1)) { std::swap(Content, FileContent); size_t LastPointPosition = Path.find_last_of('.'); if (LastPointPosition != AString::npos) { ContentType = GetContentTypeFromFileExt(Path.substr(LastPointPosition + 1)); } } if (ContentType.empty()) { ContentType = "application/unknown"; } } // Send the response: cHTTPOutgoingResponse Resp; Resp.SetContentType(ContentType); a_Connection.Send(Resp); a_Connection.Send(Content); a_Connection.FinishResponse(); } AString cWebAdmin::GetContentTypeFromFileExt(const AString & a_FileExtension) { static bool IsInitialized = false; static AStringMap ContentTypeMap; if (!IsInitialized) { // Initialize the ContentTypeMap: ContentTypeMap["png"] = "image/png"; ContentTypeMap["fif"] = "image/fif"; ContentTypeMap["gif"] = "image/gif"; ContentTypeMap["jpeg"] = "image/jpeg"; ContentTypeMap["jpg"] = "image/jpeg"; ContentTypeMap["jpe"] = "image/jpeg"; ContentTypeMap["tiff"] = "image/tiff"; ContentTypeMap["ico"] = "image/ico"; ContentTypeMap["csv"] = "text/csv"; ContentTypeMap["css"] = "text/css"; ContentTypeMap["js"] = "text/javascript"; ContentTypeMap["txt"] = "text/plain"; ContentTypeMap["rtx"] = "text/richtext"; ContentTypeMap["rtf"] = "text/richtext"; ContentTypeMap["xml"] = "text/xml"; ContentTypeMap["html"] = "text/html"; ContentTypeMap["htm"] = "text/html"; ContentTypeMap["xhtml"] = "application/xhtml+xml"; // Not recomended for IE6, but no-one uses that anymore } auto itr = ContentTypeMap.find(StrToLower(a_FileExtension)); if (itr == ContentTypeMap.end()) { return AString(); } return itr->second; } sWebAdminPage cWebAdmin::GetPage(const HTTPRequest & a_Request) { sWebAdminPage page; auto split = StringSplit(a_Request.Path, "/"); // If no specific page was requested, return an empty object: if (split.size() <= 2) { return page; } // Find the WebTab handler responsible for the request: cWebTabPtr tab; { cCSLock Lock(m_CS); for (auto & wt: m_WebTabs) { if ( (wt->m_PluginName == split[1]) && (wt->m_UrlPath == split[2]) ) { tab = wt; break; } } // for wt - m_WebTabs[] } // If a WebTab handler was found, call it: if (tab != nullptr) { page.ContentType = "text/html"; // Default to HTML content type, unless overridden by a plugin if (!tab->m_Callback->Call(a_Request, split[1], page.Content, page.ContentType)) { page.Content = GetHTMLEscapedString(fmt::format( FMT_STRING("WebTab callback for plugin {}, page {} has failed."), tab->m_PluginName, tab->m_Title )); } page.PluginName = tab->m_PluginName; page.TabTitle = tab->m_Title; page.TabUrlPath = split[1]; } return page; } AString cWebAdmin::GetBaseURL(const AString & a_URL) { return GetBaseURL(StringSplit(a_URL, "/")); } void cWebAdmin::AddWebTab( const AString & a_Title, const AString & a_UrlPath, const AString & a_PluginName, std::shared_ptr a_Callback ) { cCSLock lock(m_CS); m_WebTabs.emplace_back(std::make_shared(a_Title, a_UrlPath, a_PluginName, std::move(a_Callback))); } bool cWebAdmin::DelWebTab(const AString & a_UrlPath) { cCSLock lock(m_CS); for (auto itr = m_WebTabs.begin(), end = m_WebTabs.end(); itr != end; ++itr) { if ((*itr)->m_UrlPath == a_UrlPath) { m_WebTabs.erase(itr); return true; } } // for itr - m_WebTabs[] // Not found: return false; } AString cWebAdmin::GetHTMLEscapedString(const AString & a_Input) { AString dst; dst.reserve(a_Input.length()); // Loop over input and substitute HTML characters for their alternatives: size_t len = a_Input.length(); for (size_t i = 0; i < len; i++) { switch (a_Input[i]) { case '&': dst.append("&"); break; case '\'': dst.append("'"); break; case '"': dst.append("""); break; case '<': dst.append("<"); break; case '>': dst.append(">"); break; default: { dst.push_back(a_Input[i]); break; } } // switch (a_Input[i]) } // for i - a_Input[] return dst; } AString cWebAdmin::GetURLEncodedString(const AString & a_Input) { return URLEncode(a_Input); } AString cWebAdmin::GetBaseURL(const AStringVector & a_URLSplit) { AString BaseURL = "./"; if (a_URLSplit.size() > 1) { for (unsigned int i = 0; i < a_URLSplit.size(); i++) { BaseURL += "../"; } BaseURL += "webadmin/"; } return BaseURL; } void cWebAdmin::OnRequestBegun(cHTTPServerConnection & a_Connection, cHTTPIncomingRequest & a_Request) { UNUSED(a_Connection); const AString & URL = a_Request.GetURL(); if ( (strncmp(URL.c_str(), "/webadmin", 9) == 0) || (strncmp(URL.c_str(), "/~webadmin", 10) == 0) ) { a_Request.SetUserData(std::make_shared(a_Request)); return; } if (URL == "/") { // The root needs no body handler and is fully handled in the OnRequestFinished() call return; } // TODO: Handle other requests } void cWebAdmin::OnRequestBody(cHTTPServerConnection & a_Connection, cHTTPIncomingRequest & a_Request, const char * a_Data, size_t a_Size) { UNUSED(a_Connection); auto Data = std::static_pointer_cast(a_Request.GetUserData()); if (Data == nullptr) { return; } Data->m_Form.Parse(a_Data, a_Size); } void cWebAdmin::OnRequestFinished(cHTTPServerConnection & a_Connection, cHTTPIncomingRequest & a_Request) { const AString & URL = a_Request.GetURL(); if ( (strncmp(URL.c_str(), "/webadmin", 9) == 0) || (strncmp(URL.c_str(), "/~webadmin", 10) == 0) ) { HandleWebadminRequest(a_Connection, a_Request); } else if (URL == "/") { // The root needs no body handler and is fully handled in the OnRequestFinished() call HandleRootRequest(a_Connection, a_Request); } else { HandleFileRequest(a_Connection, a_Request); } } ================================================ FILE: src/WebAdmin.h ================================================ // WebAdmin.h // Declares the cWebAdmin class representing the admin interface over http protocol, and related services (API) #pragma once #include "Bindings/LuaState.h" #include "IniFile.h" #include "HTTP/HTTPServer.h" #include "HTTP/HTTPMessage.h" // Disable MSVC warnings: #if defined(_MSC_VER) #pragma warning(push) #pragma warning(disable:4355) // 'this' : used in base member initializer list #endif // tolua_begin struct HTTPFormData { std::string Name; std::string Value; std::string Type; } ; // tolua_end // tolua_begin struct HTTPRequest { typedef std::map< std::string, std::string > StringStringMap; typedef std::map< std::string, HTTPFormData > FormDataMap; /** The entire URL presented to the HTTP server. */ AString URL; /** HTTP method used for the request ("GET", "POST" etc.) */ AString Method; /** The Path part of the request's URL (excluding GET params). */ AString Path; /** Name of the logged-in user. Empty if not logged in. */ AString Username; // tolua_end /** Parameters given in the URL, after the questionmark */ StringStringMap Params; // >> EXPORTED IN MANUALBINDINGS << /** Parameters posted as a part of a form - either in the URL (GET method) or in the body (POST method) */ StringStringMap PostParams; // >> EXPORTED IN MANUALBINDINGS << /** Same as PostParams */ FormDataMap FormData; // >> EXPORTED IN MANUALBINDINGS << } ; // tolua_export // tolua_begin struct HTTPTemplateRequest { HTTPRequest Request; } ; // tolua_end struct sWebAdminPage { AString Content; AString PluginName; AString TabTitle; AString TabUrlPath; AString ContentType; }; // tolua_begin class cWebAdmin : // tolua_end public cHTTPServer::cCallbacks // tolua_begin { public: // tolua_end /** Interface for getting the content of a single WebTab. */ class cWebTabCallback abstract { public: // Force a virtual destructor in descendants virtual ~cWebTabCallback() {} /** Returns the contents for the specified request. Returns true if the call was successful, false on an error. a_Request is the full HTTP request object, as received from the client. a_UrlPath is the UrlPath of the WebTab registered for this request, as parsed from a_Request. Descendants should fill a_Content with the page contents and optionally set a_ContentType [defaults to "text/html"] */ virtual bool Call( const HTTPRequest & a_Request, const AString & a_UrlPath, AString & a_Content, AString & a_ContentType ) = 0; }; /** Container for a single web tab. Each web tab has a title, URL path and an associated plugin's name. Each web tab is registered with a callback to provide the content. */ class cWebTab { public: AString m_Title; AString m_UrlPath; AString m_PluginName; std::shared_ptr m_Callback; cWebTab(const AString & a_Title, const AString & a_UrlPath, const AString & a_PluginName, std::shared_ptr a_Callback): m_Title(a_Title), m_UrlPath(a_UrlPath), m_PluginName(a_PluginName), m_Callback(std::move(a_Callback)) { } }; typedef std::shared_ptr cWebTabPtr; typedef std::vector cWebTabPtrs; cWebAdmin(void); virtual ~cWebAdmin() override; /** Initializes the object. Returns true if successfully initialized and ready to start */ bool Init(void); /** Starts the HTTP server taking care of the webadmin. Returns true if successful */ bool Start(void); /** Stops the HTTP server, if it was started. */ void Stop(void); /** Loads the login template into m_LoginPage. Returns true if the loading succeeds, false if not. */ bool LoadLoginPage(void); /** Returns a copy of all the registered web tabs. Exported to Lua in ManualBindings.cpp. */ cWebTabPtrs GetAllWebTabs(void) { return m_WebTabs; } /** Removes all WebTabs registered by the specified plugin. */ void RemoveAllPluginWebTabs(const AString & a_PluginName); /** Returns the (inner) page contents for the specified request. Calls the appropriate WebTab handler to get the contents. Exported to Lua in ManualBindings.cpp. */ sWebAdminPage GetPage(const HTTPRequest & a_Request); // tolua_begin /** Reloads m_IniFile, m_LoginPage and m_TemplateScript. Note that reloading will not change the "enabled" state of the server, and it will not update listening ports. */ void Reload(void); /** Returns the list of ports on which the webadmin is configured to listen. */ AString GetPorts(void) const { return StringsConcat(m_Ports, ','); } /** Returns the prefix needed for making a link point to the webadmin root from the given URL ("../../../webadmin"-style). */ static AString GetBaseURL(const AString & a_URL); /** Returns the content type from the file extension. If the extension isn't in the list, the function returns an empty string. */ static AString GetContentTypeFromFileExt(const AString & a_FileExtension); /** Escapes text passed into it, so it can be embedded into html. */ static AString GetHTMLEscapedString(const AString & a_Input); // tolua_end /** Adds a new WebTab handler. a_Title is the display title of the tab a_UrlPath is the part of the URL that uniquely identifies this tab. a_PluginName is the display name of the plugin creating this tab. a_Callback is used to provide the actual WebTab contents, when requested. Exported in ManualBindings.cpp. */ void AddWebTab( const AString & a_Title, const AString & a_UrlPath, const AString & a_PluginName, std::shared_ptr a_Callback ); /** Removes the WebTab with the specified URL path. Returns true if WebTab was found and removed, false if not found. Exported in ManualBindings.cpp */ bool DelWebTab(const AString & a_UrlPath); /** Escapes the string for use in an URL Exported to Lua in ManualBindings.cpp. */ static AString GetURLEncodedString(const AString & a_Input); /** Returns the prefix needed for making a link point to the webadmin root from the given URL ("../../../webadmin"-style) */ static AString GetBaseURL(const AStringVector & a_URLSplit); protected: /** Protects m_WebTabs, m_TemplateScript, m_LoginTemplate and m_IniFile against multithreaded access. */ cCriticalSection m_CS; /** All registered WebTab handlers. Protected against multithreaded access by m_CS. */ cWebTabPtrs m_WebTabs; /** The Lua template script to provide templates. Protected against multithreaded access by m_CS. */ cLuaState m_TemplateScript; /** The HTML page that provides the login. Protected against multithreaded access by m_CS. */ AString m_LoginPage; /** The webadmin.ini file, used for the settings and allowed logins. Protected against multithreaded access by m_CS. */ cIniFile m_IniFile; /** Set to true if Init() succeeds and the webadmin isn't to be disabled */ bool m_IsInitialized; /** Set to true if Start() succeeds in starting the server, reset back to false in Stop(). */ bool m_IsRunning; /** The ports on which the webadmin is running. */ AStringVector m_Ports; /** The HTTP server which provides the underlying HTTP parsing, serialization and events */ cHTTPServer m_HTTPServer; /** Loads webadmin.ini into m_IniFile. Creates a default file if it doesn't exist. Returns true if webadmin is enabled, false if disabled. */ bool LoadIniFile(void); /** Checks inside the webadmin.ini file if there are users configured. */ bool HasUsers(); /** Handles requests coming to the "/webadmin" or "/~webadmin" URLs */ void HandleWebadminRequest(cHTTPServerConnection & a_Connection, cHTTPIncomingRequest & a_Request); /** Handles requests for the root page */ void HandleRootRequest(cHTTPServerConnection & a_Connection, cHTTPIncomingRequest & a_Request); /** Handles requests for a file */ void HandleFileRequest(cHTTPServerConnection & a_Connection, cHTTPIncomingRequest & a_Request); // cHTTPServer::cCallbacks overrides: virtual void OnRequestBegun (cHTTPServerConnection & a_Connection, cHTTPIncomingRequest & a_Request) override; virtual void OnRequestBody (cHTTPServerConnection & a_Connection, cHTTPIncomingRequest & a_Request, const char * a_Data, size_t a_Size) override; virtual void OnRequestFinished(cHTTPServerConnection & a_Connection, cHTTPIncomingRequest & a_Request) override; } ; // tolua_export // Revert MSVC warnings back to orignal state: #if defined(_MSC_VER) #pragma warning(pop) #endif ================================================ FILE: src/World.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "World.h" #include "BlockInfo.h" #include "ClientHandle.h" #include "Physics/Explodinator.h" #include "Server.h" #include "Root.h" #include "IniFile.h" #include "Generating/ChunkDesc.h" #include "Generating/ComposableGenerator.h" #include "SetChunkData.h" #include "DeadlockDetect.h" #include "LineBlockTracer.h" #include "UUID.h" #include "BlockInServerPluginInterface.h" // Serializers #include "WorldStorage/ScoreboardSerializer.h" // Entities (except mobs): #include "Entities/EnderCrystal.h" #include "Entities/ExpOrb.h" #include "Entities/FallingBlock.h" #include "Entities/Minecart.h" #include "Entities/Pickup.h" #include "Entities/Player.h" #include "Entities/TNTEntity.h" #include "BlockEntities/CommandBlockEntity.h" #include "BlockEntities/SignEntity.h" // Simulators: #include "Simulator/FloodyFluidSimulator.h" #include "Simulator/FluidSimulator.h" #include "Simulator/FireSimulator.h" #include "Simulator/NoopFluidSimulator.h" #include "Simulator/NoopRedstoneSimulator.h" #include "Simulator/IncrementalRedstoneSimulator/IncrementalRedstoneSimulator.h" #include "Simulator/SandSimulator.h" #include "Simulator/VanillaFluidSimulator.h" #include "Simulator/VaporizeFluidSimulator.h" // Mobs: #include "Mobs/IncludeAllMonsters.h" #include "MobCensus.h" #include "MobSpawner.h" #include "Generating/Trees.h" #include "Bindings/PluginManager.h" #include "Blocks/BlockHandler.h" #ifndef _WIN32 #include #endif #include "SpawnPrepare.h" #include "FastRandom.h" #include "OpaqueWorld.h" namespace World { // Implement conversion functions from OpaqueWorld.h cBroadcastInterface * GetBroadcastInterface(cWorld * a_World) { return a_World; } cForEachChunkProvider * GetFECProvider (cWorld * a_World) { return a_World; } cWorldInterface * GetWorldInterface (cWorld * a_World) { return a_World; } cChunkInterface GetChunkInterface(cWorld & a_World) { return { a_World.GetChunkMap() }; } } //////////////////////////////////////////////////////////////////////////////// // cWorld::cLock: cWorld::cLock::cLock(const cWorld & a_World) : Super(&(a_World.m_ChunkMap.GetCS())) { } //////////////////////////////////////////////////////////////////////////////// // cWorld::cTickThread: cWorld::cTickThread::cTickThread(cWorld & a_World): Super(fmt::format(FMT_STRING("World Ticker ({})"), a_World.GetName())), m_World(a_World) { } void cWorld::cTickThread::Execute() { auto LastTime = std::chrono::steady_clock::now(); auto TickTime = std::chrono::duration_cast(1_tick); while (!m_ShouldTerminate) { auto NowTime = std::chrono::steady_clock::now(); auto WaitTime = std::chrono::duration_cast(NowTime - LastTime); m_World.Tick(WaitTime, TickTime); TickTime = std::chrono::duration_cast(std::chrono::steady_clock::now() - NowTime); if (TickTime < 1_tick) { // Stretch tick time until it's at least 1 tick: std::this_thread::sleep_for(1_tick - TickTime); } LastTime = NowTime; } } //////////////////////////////////////////////////////////////////////////////// // cWorld: cWorld::cWorld( const AString & a_WorldName, const AString & a_DataPath, cDeadlockDetect & a_DeadlockDetect, const AStringVector & a_WorldNames, eDimension a_Dimension, const AString & a_LinkedOverworldName ): m_WorldName(a_WorldName), m_DataPath(a_DataPath), m_LinkedOverworldName(a_LinkedOverworldName), m_IniFileName(m_DataPath + "/world.ini"), m_StorageSchema("Default"), #ifdef __arm__ m_StorageCompressionFactor(0), #else m_StorageCompressionFactor(6), #endif m_IsSavingEnabled(true), m_Dimension(a_Dimension), m_IsSpawnExplicitlySet(false), m_SpawnX(0), m_SpawnY(cChunkDef::Height), m_SpawnZ(0), m_BroadcastDeathMessages(true), m_BroadcastAchievementMessages(true), m_IsDaylightCycleEnabled(true), m_WorldAge(0), m_WorldDate(0), m_WorldTickAge(0), m_LastChunkCheck(0), m_LastSave(0), m_SkyDarkness(0), m_GameMode(gmSurvival), m_bEnabledPVP(false), m_bFarmlandTramplingEnabled(false), m_IsDeepSnowEnabled(false), m_ShouldLavaSpawnFire(true), m_VillagersShouldHarvestCrops(true), m_SimulatorManager(), m_SandSimulator(), m_WaterSimulator(nullptr), m_LavaSimulator(nullptr), m_FireSimulator(), m_RedstoneSimulator(nullptr), m_MaxPlayers(10), m_ChunkMap(this), m_bAnimals(true), m_Weather(eWeather_Sunny), m_WeatherInterval(24000), // Guaranteed 1 game-day of sunshine at server start :) m_MaxSunnyTicks(180000), // 150 real-world minutes -+ m_MinSunnyTicks(12000), // 10 real-world minutes | m_MaxRainTicks(24000), // 20 real-world minutes +- all values adapted from Vanilla 1.7.2 m_MinRainTicks(12000), // 10 real-world minutes | m_MaxThunderStormTicks(15600), // 13 real-world minutes | m_MinThunderStormTicks(3600), // 3 real-world minutes -+ m_MaxCactusHeight(3), m_MaxSugarcaneHeight(4), /* TODO: Enable when functionality exists again m_IsBeetrootsBonemealable(true), m_IsCactusBonemealable(false), m_IsCarrotsBonemealable(true), m_IsCropsBonemealable(true), m_IsGrassBonemealable(true), m_IsMelonStemBonemealable(true), m_IsMelonBonemealable(true), m_IsPotatoesBonemealable(true), m_IsPumpkinStemBonemealable(true), m_IsPumpkinBonemealable(true), m_IsSaplingBonemealable(true), m_IsSugarcaneBonemealable(false), m_IsBigFlowerBonemealable(true), m_IsTallGrassBonemealable(true), */ m_bCommandBlocksEnabled(true), m_bUseChatPrefixes(false), m_TNTShrapnelLevel(slNone), m_MaxViewDistance(12), m_Scoreboard(this), m_MapManager(this), m_GeneratorCallbacks(*this), m_ChunkSender(*this), m_Lighting(*this), m_TickThread(*this) { LOGD("cWorld::cWorld(\"%s\")", a_WorldName); cFile::CreateFolderRecursive(m_DataPath); m_ChunkMap.TrackInDeadlockDetect(a_DeadlockDetect, m_WorldName); // Load the scoreboard cScoreboardSerializer Serializer(m_DataPath, &m_Scoreboard); Serializer.Load(); // Track the CSs used by this world in the deadlock detector: a_DeadlockDetect.TrackCriticalSection(m_CSTasks, fmt::format(FMT_STRING("World {} tasks"), m_WorldName)); // Load world settings from the ini file cIniFile IniFile; if (!IniFile.ReadFile(m_IniFileName)) { LOGWARNING("Cannot read world settings from \"%s\", defaults will be used.", m_IniFileName); // TODO: More descriptions for each key IniFile.AddHeaderComment(" This is the per-world configuration file, managing settings such as generators, simulators, and spawn points"); IniFile.AddKeyComment(" LinkedWorlds", "This section governs portal world linkage; leave a value blank to disabled that associated method of teleportation"); } // The presence of a configuration value overrides everything // If no configuration value is found, GetDimension() is written to file and the variable is written to again to ensure that cosmic rays haven't sneakily changed its value m_Dimension = StringToDimension(IniFile.GetValueSet("General", "Dimension", DimensionToString(GetDimension()))); int UnusedDirtyChunksCap = IniFile.GetValueSetI("General", "UnusedChunkCap", 1000); if (UnusedDirtyChunksCap < 0) { UnusedDirtyChunksCap *= -1; IniFile.SetValueI("General", "UnusedChunkCap", UnusedDirtyChunksCap); } m_UnusedDirtyChunksCap = static_cast(UnusedDirtyChunksCap); m_BroadcastDeathMessages = IniFile.GetValueSetB("Broadcasting", "BroadcastDeathMessages", true); m_BroadcastAchievementMessages = IniFile.GetValueSetB("Broadcasting", "BroadcastAchievementMessages", true); SetMaxViewDistance(IniFile.GetValueSetI("SpawnPosition", "MaxViewDistance", cClientHandle::DEFAULT_VIEW_DISTANCE)); // Try to find the "SpawnPosition" key and coord values in the world configuration, set the flag if found int KeyNum = IniFile.FindKey("SpawnPosition"); m_IsSpawnExplicitlySet = ( (KeyNum >= 0) && ( (IniFile.FindValue(KeyNum, "X") >= 0) && (IniFile.FindValue(KeyNum, "Y") >= 0) && (IniFile.FindValue(KeyNum, "Z") >= 0) ) ); if (m_IsSpawnExplicitlySet) { LOGD("Spawnpoint explicitly set!"); m_SpawnX = IniFile.GetValueI("SpawnPosition", "X", m_SpawnX); m_SpawnY = IniFile.GetValueI("SpawnPosition", "Y", m_SpawnY); m_SpawnZ = IniFile.GetValueI("SpawnPosition", "Z", m_SpawnZ); } m_StorageSchema = IniFile.GetValueSet ("Storage", "Schema", m_StorageSchema); m_StorageCompressionFactor = IniFile.GetValueSetI("Storage", "CompressionFactor", m_StorageCompressionFactor); m_MaxCactusHeight = IniFile.GetValueSetI("Plants", "MaxCactusHeight", 3); m_MaxSugarcaneHeight = IniFile.GetValueSetI("Plants", "MaxSugarcaneHeight", 3); /* TODO: Enable when functionality exists again m_IsBeetrootsBonemealable = IniFile.GetValueSetB("Plants", "IsBeetrootsBonemealable", true); m_IsCactusBonemealable = IniFile.GetValueSetB("Plants", "IsCactusBonemealable", false); m_IsCarrotsBonemealable = IniFile.GetValueSetB("Plants", "IsCarrotsBonemealable", true); m_IsCropsBonemealable = IniFile.GetValueSetB("Plants", "IsCropsBonemealable", true); m_IsGrassBonemealable = IniFile.GetValueSetB("Plants", "IsGrassBonemealable", true); m_IsMelonStemBonemealable = IniFile.GetValueSetB("Plants", "IsMelonStemBonemealable", true); m_IsMelonBonemealable = IniFile.GetValueSetB("Plants", "IsMelonBonemealable", false); m_IsPotatoesBonemealable = IniFile.GetValueSetB("Plants", "IsPotatoesBonemealable", true); m_IsPumpkinStemBonemealable = IniFile.GetValueSetB("Plants", "IsPumpkinStemBonemealable", true); m_IsPumpkinBonemealable = IniFile.GetValueSetB("Plants", "IsPumpkinBonemealable", false); m_IsSaplingBonemealable = IniFile.GetValueSetB("Plants", "IsSaplingBonemealable", true); m_IsSugarcaneBonemealable = IniFile.GetValueSetB("Plants", "IsSugarcaneBonemealable", false); m_IsBigFlowerBonemealable = IniFile.GetValueSetB("Plants", "IsBigFlowerBonemealable", true); m_IsTallGrassBonemealable = IniFile.GetValueSetB("Plants", "IsTallGrassBonemealable", true); */ m_IsDeepSnowEnabled = IniFile.GetValueSetB("Physics", "DeepSnow", true); m_ShouldLavaSpawnFire = IniFile.GetValueSetB("Physics", "ShouldLavaSpawnFire", true); int TNTShrapnelLevel = IniFile.GetValueSetI("Physics", "TNTShrapnelLevel", static_cast(slAll)); m_bCommandBlocksEnabled = IniFile.GetValueSetB("Mechanics", "CommandBlocksEnabled", false); m_bEnabledPVP = IniFile.GetValueSetB("Mechanics", "PVPEnabled", true); m_bFarmlandTramplingEnabled = IniFile.GetValueSetB("Mechanics", "FarmlandTramplingEnabled", true); m_bUseChatPrefixes = IniFile.GetValueSetB("Mechanics", "UseChatPrefixes", true); m_MinNetherPortalWidth = IniFile.GetValueSetI("Mechanics", "MinNetherPortalWidth", 2); m_MaxNetherPortalWidth = IniFile.GetValueSetI("Mechanics", "MaxNetherPortalWidth", 21); m_MinNetherPortalHeight = IniFile.GetValueSetI("Mechanics", "MinNetherPortalHeight", 3); m_MaxNetherPortalHeight = IniFile.GetValueSetI("Mechanics", "MaxNetherPortalHeight", 21); m_VillagersShouldHarvestCrops = IniFile.GetValueSetB("Monsters", "VillagersShouldHarvestCrops", true); m_IsDaylightCycleEnabled = IniFile.GetValueSetB("General", "IsDaylightCycleEnabled", true); int GameMode = IniFile.GetValueSetI("General", "Gamemode", static_cast(m_GameMode)); int Weather = IniFile.GetValueSetI("General", "Weather", static_cast(m_Weather)); m_WorldAge = std::chrono::milliseconds(IniFile.GetValueSetI("General", "WorldAgeMS", 0LL)); // Load the weather frequency data: if (m_Dimension == dimOverworld) { m_MaxSunnyTicks = IniFile.GetValueSetI("Weather", "MaxSunnyTicks", m_MaxSunnyTicks); m_MinSunnyTicks = IniFile.GetValueSetI("Weather", "MinSunnyTicks", m_MinSunnyTicks); m_MaxRainTicks = IniFile.GetValueSetI("Weather", "MaxRainTicks", m_MaxRainTicks); m_MinRainTicks = IniFile.GetValueSetI("Weather", "MinRainTicks", m_MinRainTicks); m_MaxThunderStormTicks = IniFile.GetValueSetI("Weather", "MaxThunderStormTicks", m_MaxThunderStormTicks); m_MinThunderStormTicks = IniFile.GetValueSetI("Weather", "MinThunderStormTicks", m_MinThunderStormTicks); if (m_MaxSunnyTicks < m_MinSunnyTicks) { std::swap(m_MaxSunnyTicks, m_MinSunnyTicks); } if (m_MaxRainTicks < m_MinRainTicks) { std::swap(m_MaxRainTicks, m_MinRainTicks); } if (m_MaxThunderStormTicks < m_MinThunderStormTicks) { std::swap(m_MaxThunderStormTicks, m_MinThunderStormTicks); } } auto WorldExists = [&](const AString & a_CheckWorldName) { return (std::find(a_WorldNames.begin(), a_WorldNames.end(), a_CheckWorldName) != a_WorldNames.end()); }; if (a_Dimension == dimOverworld) { AString MyNetherName = GetName() + "_nether"; AString MyEndName = GetName() + "_the_end"; if (!WorldExists(MyNetherName)) { MyNetherName.clear(); } if (!WorldExists(MyEndName)) { MyEndName = GetName() + "_end"; if (!WorldExists(MyEndName)) { MyEndName.clear(); } } m_LinkedNetherWorldName = IniFile.GetValueSet("LinkedWorlds", "NetherWorldName", MyNetherName); m_LinkedEndWorldName = IniFile.GetValueSet("LinkedWorlds", "EndWorldName", MyEndName); } else { m_LinkedOverworldName = IniFile.GetValueSet("LinkedWorlds", "OverworldName", GetLinkedOverworldName()); } // If we are linked to one or more worlds that do not exist, unlink them if (a_Dimension == dimOverworld) { if (!m_LinkedNetherWorldName.empty() && !WorldExists(m_LinkedNetherWorldName)) { IniFile.SetValue("LinkedWorlds", "NetherWorldName", ""); LOG("%s Is linked to a nonexisting nether world called \"%s\". The server has modified \"%s/world.ini\" and removed this invalid link.", GetName().c_str(), m_LinkedNetherWorldName.c_str(), GetName().c_str()); m_LinkedNetherWorldName.clear(); } if (!m_LinkedEndWorldName.empty() && !WorldExists(m_LinkedEndWorldName)) { IniFile.SetValue("LinkedWorlds", "EndWorldName", ""); LOG("%s Is linked to a nonexisting end world called \"%s\". The server has modified \"%s/world.ini\" and removed this invalid link.", GetName().c_str(), m_LinkedEndWorldName.c_str(), GetName().c_str()); m_LinkedEndWorldName.clear(); } } else { if (!m_LinkedOverworldName.empty() && !WorldExists(m_LinkedOverworldName)) { IniFile.SetValue("LinkedWorlds", "OverworldName", ""); LOG("%s Is linked to a nonexisting overworld called \"%s\". The server has modified \"%s/world.ini\" and removed this invalid link.", GetName().c_str(), m_LinkedOverworldName.c_str(), GetName().c_str()); m_LinkedOverworldName.clear(); } } // Adjust the enum-backed variables into their respective bounds: m_GameMode = static_cast (Clamp(GameMode, gmSurvival, gmSpectator)); m_TNTShrapnelLevel = static_cast(Clamp(TNTShrapnelLevel, slNone, slAll)); m_Weather = static_cast (Clamp(Weather, wSunny, wStorm)); cComposableGenerator::InitializeGeneratorDefaults(IniFile, m_Dimension); InitializeAndLoadMobSpawningValues(IniFile); m_WorldDate = cTickTime(IniFile.GetValueSetI("General", "TimeInTicks", GetWorldDate().count())); // preallocate some memory for ticking blocks so we don't need to allocate that often m_BlockTickQueue.reserve(1000); m_BlockTickQueueCopy.reserve(1000); // Simulators: m_SimulatorManager = std::make_unique(*this); m_WaterSimulator = InitializeFluidSimulator(IniFile, "Water", E_BLOCK_WATER, E_BLOCK_STATIONARY_WATER); m_LavaSimulator = InitializeFluidSimulator(IniFile, "Lava", E_BLOCK_LAVA, E_BLOCK_STATIONARY_LAVA); m_SandSimulator = std::make_unique(*this, IniFile); m_FireSimulator = std::make_unique(*this, IniFile); m_RedstoneSimulator = InitializeRedstoneSimulator(IniFile); // Water, Lava and Redstone simulators get registered in their initialize function. m_SimulatorManager->RegisterSimulator(m_SandSimulator.get(), 1); m_SimulatorManager->RegisterSimulator(m_FireSimulator.get(), 1); m_Storage.Initialize(*this, m_StorageSchema, m_StorageCompressionFactor); m_Generator.Initialize(m_GeneratorCallbacks, m_GeneratorCallbacks, IniFile); m_MapManager.LoadMapData(); // Save any changes that the defaults may have done to the ini file: if (!IniFile.WriteFile(m_IniFileName)) { LOGWARNING("Could not write world config to %s", m_IniFileName.c_str()); } // Init of the spawn monster time (as they are supposed to have different spawn rate) m_LastSpawnMonster.emplace(cMonster::mfHostile, 0_tick); m_LastSpawnMonster.emplace(cMonster::mfPassive, 0_tick); m_LastSpawnMonster.emplace(cMonster::mfAmbient, 0_tick); m_LastSpawnMonster.emplace(cMonster::mfWater, 0_tick); } cWorld::~cWorld() { delete m_WaterSimulator; m_WaterSimulator = nullptr; delete m_LavaSimulator; m_LavaSimulator = nullptr; delete m_RedstoneSimulator; m_RedstoneSimulator = nullptr; } void cWorld::CastThunderbolt(int a_BlockX, int a_BlockY, int a_BlockZ) { LOG("CastThunderbolt(int, int, int) is deprecated, use CastThunderbolt(Vector3i) instead"); CastThunderbolt({a_BlockX, a_BlockY, a_BlockZ}); } void cWorld::CastThunderbolt(Vector3i a_Block) { BroadcastThunderbolt(a_Block); BroadcastSoundEffect("entity.lightning.thunder", a_Block, 50, 1); } cTickTime cWorld::GetTimeOfDay(void) const { using namespace std::chrono_literals; return std::chrono::duration_cast(m_WorldDate % 20min); } cTickTimeLong cWorld::GetWorldAge(void) const { return std::chrono::duration_cast(m_WorldAge); } cTickTimeLong cWorld::GetWorldDate() const { return std::chrono::duration_cast(m_WorldDate); } cTickTimeLong cWorld::GetWorldTickAge() const { return m_WorldTickAge; } void cWorld::SetTimeOfDay(const cTickTime a_TimeOfDay) { using namespace std::chrono_literals; m_WorldDate = (m_WorldDate / 20min) * 20min + a_TimeOfDay; UpdateSkyDarkness(); BroadcastTimeUpdate(); } int cWorld::GetDefaultWeatherInterval(eWeather a_Weather) const { auto & Random = GetRandomProvider(); switch (a_Weather) { case eWeather_Sunny: { return Random.RandInt(m_MinSunnyTicks, m_MaxSunnyTicks); } case eWeather_Rain: { return Random.RandInt(m_MinRainTicks, m_MaxRainTicks); } case eWeather_ThunderStorm: { return Random.RandInt(m_MinThunderStormTicks, m_MaxThunderStormTicks); } } UNREACHABLE("Unsupported weather"); } void cWorld::SetWeather(eWeather a_NewWeather) { // Do the plugins agree? Do they want a different weather? if (cRoot::Get()->GetPluginManager()->CallHookWeatherChanging(*this, a_NewWeather)) { m_WeatherInterval = GetDefaultWeatherInterval(m_Weather); return; } // Set new period for the selected weather: m_WeatherInterval = GetDefaultWeatherInterval(a_NewWeather); // The weather can't be found: if (m_WeatherInterval < 0) { return; } m_Weather = a_NewWeather; BroadcastWeather(m_Weather); // Let the plugins know about the change: cPluginManager::Get()->CallHookWeatherChanged(*this); } void cWorld::ChangeWeather(void) { // In the next tick the weather will be changed m_WeatherInterval = 0; } bool cWorld::IsWeatherSunnyAt(int a_BlockX, int a_BlockZ) const { return m_ChunkMap.IsWeatherSunnyAt(a_BlockX, a_BlockZ); } bool cWorld::IsWeatherWetAt(int a_BlockX, int a_BlockZ) { return m_ChunkMap.IsWeatherWetAt(a_BlockX, a_BlockZ); } bool cWorld::IsWeatherWetAtXYZ(const Vector3i a_Position) { return m_ChunkMap.IsWeatherWetAt(a_Position); } void cWorld::SetNextBlockToTick(const Vector3i a_BlockPos) { return m_ChunkMap.SetNextBlockToTick(a_BlockPos); } bool cWorld::SetSpawn(int a_X, int a_Y, int a_Z) { cIniFile IniFile; IniFile.ReadFile(m_IniFileName); IniFile.SetValueI("SpawnPosition", "X", a_X); IniFile.SetValueI("SpawnPosition", "Y", a_Y); IniFile.SetValueI("SpawnPosition", "Z", a_Z); if (IniFile.WriteFile(m_IniFileName)) { m_SpawnX = a_X; m_SpawnY = a_Y; m_SpawnZ = a_Z; FLOGD("Spawn set at {}", Vector3i{m_SpawnX, m_SpawnY, m_SpawnZ}); return true; } else { LOGWARNING("Couldn't write new spawn settings to \"%s\".", m_IniFileName.c_str()); } return false; } void cWorld::InitializeSpawn(void) { // For the debugging builds, don't make the server build too much world upon start: #if !defined(NDEBUG) || defined(ANDROID) const int DefaultViewDist = 9; #else const int DefaultViewDist = 20; // Always prepare an area 20 chunks across, no matter what the actual cClientHandle::VIEWDISTANCE is #endif // !NDEBUG if (!m_IsSpawnExplicitlySet) { // Spawn position wasn't already explicitly set, enumerate random solid-land coordinate and then write it to the world configuration: GenerateRandomSpawn(DefaultViewDist); } cIniFile IniFile; IniFile.ReadFile(m_IniFileName); int ViewDist = IniFile.GetValueSetI("SpawnPosition", "PregenerateDistance", DefaultViewDist); IniFile.WriteFile(m_IniFileName); int ChunkX = 0, ChunkZ = 0; cChunkDef::BlockToChunk(m_SpawnX, m_SpawnZ, ChunkX, ChunkZ); cSpawnPrepare::PrepareChunks(*this, ChunkX, ChunkZ, ViewDist); } void cWorld::Start() { m_Lighting.Start(); m_Storage.Start(); m_Generator.Start(); m_ChunkSender.Start(); m_TickThread.Start(); } void cWorld::GenerateRandomSpawn(int a_MaxSpawnRadius) { LOGD("Generating random spawnpoint..."); // Number of checks to make sure we have a valid biome // 100 checks will check across 400 chunks, we should have // a valid biome by then. static const int BiomeCheckCount = 100; // Make sure we are in a valid biome Vector3i BiomeOffset = Vector3i(0, 0, 0); for (int BiomeCheckIndex = 0; BiomeCheckIndex < BiomeCheckCount; ++BiomeCheckIndex) { EMCSBiome Biome = GetBiomeAt(BiomeOffset.x, BiomeOffset.z); if ((Biome != EMCSBiome::biOcean) && (Biome != EMCSBiome::biFrozenOcean)) { // Found a usable biome break; } BiomeOffset.x += cChunkDef::Width * 4; } // Check 0, 0 first. Vector3i BiomeSpawn = BiomeOffset; if (CanSpawnAt(BiomeSpawn.x, BiomeSpawn.y, BiomeSpawn.z)) { SetSpawn(BiomeSpawn.x, BiomeSpawn.y, BiomeSpawn.z); auto ChunkPos = cChunkDef::BlockToChunk(BiomeSpawn); cSpawnPrepare::PrepareChunks(*this, ChunkPos, a_MaxSpawnRadius); FLOGINFO("World \"{}\": Generated spawnpoint position at {}", m_WorldName, BiomeSpawn); return; } // A search grid (searches clockwise around the origin) static const int HalfChunk = cChunkDef::Width / 2; static const Vector3i ChunkOffset[] = { Vector3i(0, 0, HalfChunk), Vector3i(HalfChunk, 0, HalfChunk), Vector3i(HalfChunk, 0, 0), Vector3i(HalfChunk, 0, -HalfChunk), Vector3i(0, 0, -HalfChunk), Vector3i(-HalfChunk, 0, -HalfChunk), Vector3i(-HalfChunk, 0, 0), Vector3i(-HalfChunk, 0, HalfChunk), }; static const int PerRadiSearchCount = ARRAYCOUNT(ChunkOffset); for (int RadiusOffset = 1; RadiusOffset < (a_MaxSpawnRadius * 2); ++RadiusOffset) { for (int SearchGridIndex = 0; SearchGridIndex < PerRadiSearchCount; ++SearchGridIndex) { auto PotentialSpawn = BiomeOffset + (ChunkOffset[SearchGridIndex] * RadiusOffset); if (CanSpawnAt(PotentialSpawn.x, PotentialSpawn.y, PotentialSpawn.z)) { SetSpawn(PotentialSpawn.x, PotentialSpawn.y, PotentialSpawn.z); auto ChunkPos = cChunkDef::BlockToChunk(PotentialSpawn); cSpawnPrepare::PrepareChunks(*this, ChunkPos, a_MaxSpawnRadius); FLOGINFO("World \"{}\":Generated spawnpoint position at {}", m_WorldName, PotentialSpawn); return; } } } SetSpawn(BiomeSpawn.x, BiomeSpawn.y, BiomeSpawn.z); auto ChunkPos = cChunkDef::BlockToChunk(BiomeSpawn); cSpawnPrepare::PrepareChunks(*this, ChunkPos, a_MaxSpawnRadius); FLOGWARNING("World \"{}\": Did not find an acceptable spawnpoint. Generated a random spawnpoint position at {}", m_WorldName, BiomeSpawn); } bool cWorld::CanSpawnAt(int a_X, int & a_Y, int a_Z) { // All this blocks can only be found above ground. // Apart from netherrack (as the Nether is technically a massive cave) static const BLOCKTYPE ValidSpawnBlocks[] = { E_BLOCK_GRASS, E_BLOCK_SAND, E_BLOCK_SNOW, E_BLOCK_SNOW_BLOCK, E_BLOCK_NETHERRACK }; class cCanSpawnChunkStay: public cChunkStay { cEvent m_ChunksReady; public: cCanSpawnChunkStay(double a_WorldX, double a_WorldZ) { auto Chunk = cChunkDef::BlockToChunk(Vector3d{a_WorldX, 0.0, a_WorldZ}.Floor()); for (int XOffset = -1; XOffset != 2; ++XOffset) { for (int ZOffset = -1; ZOffset != 2; ++ZOffset) { Add(Chunk.m_ChunkX + XOffset, Chunk.m_ChunkZ + ZOffset); } } } virtual ~cCanSpawnChunkStay() override { Disable(); } virtual bool OnAllChunksAvailable() override { m_ChunksReady.Set(); return false; // Keep chunk stay active } virtual void OnChunkAvailable(int, int) override {} virtual void OnDisabled() override {} void Wait() { m_ChunksReady.Wait(); } }; // Use chunk stay to load 3x3 chunk area around a_X, a_Z cCanSpawnChunkStay ChunkStay(a_X, a_Z); ChunkStay.Enable(m_ChunkMap); ChunkStay.Wait(); static const int ValidSpawnBlocksCount = ARRAYCOUNT(ValidSpawnBlocks); // Increase this by two, because we need two more blocks for body and head auto Height = GetHeight(static_cast(a_X), static_cast(a_Z)); ASSERT(Height.has_value()); static const int HighestSpawnPoint = *Height + 2; static const int LowestSpawnPoint = static_cast(HighestSpawnPoint / 2.0f); for (int PotentialY = HighestSpawnPoint; PotentialY > LowestSpawnPoint; --PotentialY) { BLOCKTYPE HeadBlock = GetBlock({ a_X, PotentialY, a_Z }); // Is this block safe for spawning if (HeadBlock != E_BLOCK_AIR) { continue; } BLOCKTYPE BodyBlock = GetBlock({ a_X, PotentialY - 1, a_Z }); // Is this block safe for spawning if (BodyBlock != E_BLOCK_AIR) { continue; } BLOCKTYPE FloorBlock = GetBlock({ a_X, PotentialY - 2, a_Z }); // Early out - Is the floor block air if (FloorBlock == E_BLOCK_AIR) { continue; } // Is the floor block ok bool ValidSpawnBlock = false; for (int BlockIndex = 0; BlockIndex < ValidSpawnBlocksCount; ++BlockIndex) { ValidSpawnBlock |= (ValidSpawnBlocks[BlockIndex] == FloorBlock); } if (!ValidSpawnBlock) { continue; } if (!CheckPlayerSpawnPoint(a_X, PotentialY - 1, a_Z)) { continue; } a_Y = PotentialY - 1; return true; } // Always set a_Y so it can be used when we fail to find any spawn point a_Y = HighestSpawnPoint - 2; return false; } bool cWorld::CheckPlayerSpawnPoint(Vector3i a_Pos) { // Check height bounds if (!cChunkDef::IsValidHeight(a_Pos)) { return false; } // Check that surrounding blocks are neither solid or liquid constexpr std::array SurroundingCoords = { { {0, 0, 1}, {1, 0, 1}, {1, 0, 0}, {1, 0, -1}, {0, 0, -1}, {-1, 0, -1}, {-1, 0, 0}, {-1, 0, 1}, } }; for (const auto & Offset : SurroundingCoords) { const BLOCKTYPE BlockType = GetBlock(a_Pos + Offset); if (cBlockInfo::IsSolid(BlockType) || IsBlockLiquid(BlockType)) { return true; } } return false; } eWeather cWorld::ChooseNewWeather() { // Pick a new weather. Only reasonable transitions allowed: switch (m_Weather) { case eWeather_Sunny: case eWeather_ThunderStorm: { return eWeather_Rain; } case eWeather_Rain: { // 1 / 8 chance of turning into a thunderstorm return GetRandomProvider().RandBool(0.125) ? eWeather_ThunderStorm : eWeather_Sunny; } } UNREACHABLE("Unsupported weather"); } void cWorld::InitializeAndLoadMobSpawningValues(cIniFile & a_IniFile) { AString DefaultMonsters; switch (m_Dimension) { case dimOverworld: DefaultMonsters = "bat, cavespider, chicken, cow, creeper, guardian, horse, mooshroom, ocelot, pig, rabbit, sheep, silverfish, skeleton, slime, spider, squid, wolf, zombie"; break; // TODO Re-add Enderman when bugs are fixed case dimNether: DefaultMonsters = "blaze, ghast, magmacube, witherskeleton, zombiepigman"; break; case dimEnd: DefaultMonsters = ""; break; // TODO Re-add Enderman when bugs are fixed case dimNotSet: ASSERT(!"Dimension not set"); break; } m_bAnimals = a_IniFile.GetValueSetB("Monsters", "AnimalsOn", true); AString AllMonsters = a_IniFile.GetValueSet("Monsters", "Types", DefaultMonsters); if (!m_bAnimals) { return; } AStringVector SplitList = StringSplitAndTrim(AllMonsters, ","); for (AStringVector::const_iterator itr = SplitList.begin(), end = SplitList.end(); itr != end; ++itr) { eMonsterType ToAdd = cMonster::StringToMobType(*itr); if (ToAdd != mtInvalidType) { m_AllowedMobs.insert(ToAdd); LOGD("Allowed mob: %s", itr->c_str()); } else { LOG("World \"%s\": Unknown mob type: %s", m_WorldName.c_str(), itr->c_str()); } } } void cWorld::Stop(cDeadlockDetect & a_DeadlockDetect) { // Write settings to file; these are all plugin changeable values - keep updated! cIniFile IniFile; IniFile.ReadFile(m_IniFileName); if (GetDimension() == dimOverworld) { IniFile.SetValue("LinkedWorlds", "NetherWorldName", m_LinkedNetherWorldName); IniFile.SetValue("LinkedWorlds", "EndWorldName", m_LinkedEndWorldName); } else { IniFile.SetValue("LinkedWorlds", "OverworldName", m_LinkedOverworldName); } IniFile.SetValueI("Physics", "TNTShrapnelLevel", static_cast(m_TNTShrapnelLevel)); IniFile.SetValueB("Mechanics", "CommandBlocksEnabled", m_bCommandBlocksEnabled); IniFile.SetValueB("Mechanics", "UseChatPrefixes", m_bUseChatPrefixes); IniFile.SetValueB("General", "IsDaylightCycleEnabled", m_IsDaylightCycleEnabled); IniFile.SetValueI("General", "Weather", static_cast(m_Weather)); IniFile.SetValueI("General", "TimeInTicks", GetWorldDate().count()); IniFile.SetValueI("General", "WorldAgeMS", static_cast(m_WorldAge.count())); IniFile.WriteFile(m_IniFileName); m_TickThread.Stop(); m_Lighting.Stop(); m_Generator.Stop(); m_ChunkSender.Stop(); m_Storage.Stop(); // Waits for thread to finish a_DeadlockDetect.UntrackCriticalSection(m_CSTasks); m_ChunkMap.UntrackInDeadlockDetect(a_DeadlockDetect); if (IsSavingEnabled()) { // Unload the scoreboard cScoreboardSerializer Serializer(m_DataPath, &m_Scoreboard); Serializer.Save(); m_MapManager.SaveMapData(); } } void cWorld::Tick(std::chrono::milliseconds a_Dt, std::chrono::milliseconds a_LastTickDurationMSec) { // Notify the plugins: cPluginManager::Get()->CallHookWorldTick(*this, a_Dt, a_LastTickDurationMSec); m_WorldAge += a_Dt; m_WorldTickAge++; if (m_IsDaylightCycleEnabled) { m_WorldDate += a_Dt; // Updates the sky darkness based on current time of day: UpdateSkyDarkness(); // Broadcast time update every 64 ticks (3.2 seconds): if ((m_WorldTickAge % 64_tick) == 0_tick) { BroadcastTimeUpdate(); } } // Broadcast player list pings every 256 ticks (12.8 seconds): if ((m_WorldTickAge % 256_tick) == 0_tick) { BroadcastPlayerListUpdatePing(); } // Process all clients' buffered actions: for (const auto Player : m_Players) { Player->GetClientHandle()->ProcessProtocolIn(); } TickClients(a_Dt); TickQueuedChunkDataSets(); TickQueuedBlocks(); m_ChunkMap.Tick(a_Dt); TickMobs(a_Dt); TickQueuedEntityAdditions(); m_MapManager.TickMaps(); TickQueuedTasks(); TickWeather(static_cast(a_Dt.count())); GetSimulatorManager()->Simulate(static_cast(a_Dt.count())); // Flush out all clients' buffered data: for (const auto Player : m_Players) { Player->GetClientHandle()->ProcessProtocolOut(); } if (m_WorldAge - m_LastChunkCheck > std::chrono::seconds(10)) { // Unload every 10 seconds UnloadUnusedChunks(); if (m_WorldAge - m_LastSave > std::chrono::minutes(5)) { // Save every 5 minutes SaveAllChunks(); } else if (GetNumUnusedDirtyChunks() > m_UnusedDirtyChunksCap) { // Save if we have too many dirty unused chunks SaveAllChunks(); } } } void cWorld::TickClients(const std::chrono::milliseconds a_Dt) { for (const auto Player : m_Players) { Player->GetClientHandle()->Tick(a_Dt); } } void cWorld::TickWeather(float a_Dt) { UNUSED(a_Dt); // There are no weather changes anywhere but in the Overworld: if (GetDimension() != dimOverworld) { return; } if (m_WeatherInterval > 0) { // Not yet, wait for the weather period to end m_WeatherInterval--; } else { // Change weather: SetWeather(ChooseNewWeather()); } if (m_Weather == eWeather_ThunderStorm) { // 0.5% chance per tick of thunderbolt if (GetRandomProvider().RandBool(0.005)) { CastThunderbolt({0, 0, 0}); // TODO: find random positions near players to cast thunderbolts. } } } void cWorld::TickMobs(std::chrono::milliseconds a_Dt) { // _X 2013_10_22: This is a quick fix for #283 - the world needs to be locked while ticking mobs cWorld::cLock Lock(*this); // before every Mob action, we have to count them depending on the distance to players, on their family ... cMobCensus MobCensus; m_ChunkMap.CollectMobCensus(MobCensus); if (m_bAnimals) { // Spawning is enabled, spawn now: static const cMonster::eFamily AllFamilies[] = { cMonster::mfHostile, cMonster::mfPassive, cMonster::mfAmbient, cMonster::mfWater, } ; for (size_t i = 0; i < ARRAYCOUNT(AllFamilies); i++) { cMonster::eFamily Family = AllFamilies[i]; if ( (m_LastSpawnMonster[Family] > (m_WorldTickAge - cMonster::GetSpawnDelay(Family))) || // Not reached the needed ticks before the next round MobCensus.IsCapped(Family) ) { continue; } m_LastSpawnMonster[Family] = m_WorldTickAge; cMobSpawner Spawner(Family, m_AllowedMobs); if (Spawner.CanSpawnAnything()) { m_ChunkMap.SpawnMobs(Spawner); // do the spawn for (auto & Mob : Spawner.getSpawned()) { SpawnMobFinalize(std::move(Mob)); } } } // for i - AllFamilies[] } // if (Spawning enabled) ForEachEntity([=](cEntity & a_Entity) { if (!a_Entity.IsMob()) { return false; } if (!a_Entity.IsTicking()) { return false; } auto & Monster = static_cast(a_Entity); ASSERT(Monster.GetParentChunk() != nullptr); // A ticking entity must have a valid parent chunk // Tick close mobs if (Monster.GetParentChunk()->HasAnyClients()) { Monster.Tick(a_Dt, *(a_Entity.GetParentChunk())); } // Destroy far hostile mobs except if last target was a player else if ((Monster.GetMobFamily() == cMonster::eFamily::mfHostile) && !Monster.WasLastTargetAPlayer()) { if (Monster.GetMobType() != eMonsterType::mtWolf) { Monster.Destroy(); } else { auto & Wolf = static_cast(Monster); if (!Wolf.IsAngry() && !Wolf.IsTame()) { Monster.Destroy(); } } } return false; } ); } void cWorld::TickQueuedChunkDataSets() { decltype(m_SetChunkDataQueue) SetChunkDataQueue; { cCSLock Lock(m_CSSetChunkDataQueue); SetChunkDataQueue = std::move(m_SetChunkDataQueue); } // Set any chunk data that has been queued for setting: for (auto & Item : SetChunkDataQueue) { // A copy of the chunk coordinates since we're moving Item. const auto Chunk = Item.Chunk; // Set the data: m_ChunkMap.SetChunkData(std::move(Item)); // If a client is requesting this chunk, send it to them: cChunkSender & ChunkSender = m_ChunkSender; DoWithChunk( Chunk.m_ChunkX, Chunk.m_ChunkZ, [&ChunkSender](cChunk & a_Chunk) { if (a_Chunk.HasAnyClients()) { ChunkSender.QueueSendChunkTo( a_Chunk.GetPosX(), a_Chunk.GetPosZ(), cChunkSender::Priority::Medium, a_Chunk.GetAllClients() ); } return true; } ); } // for itr - SetChunkDataQueue[] } void cWorld::TickQueuedEntityAdditions(void) { decltype(m_EntitiesToAdd) EntitiesToAdd; { cCSLock Lock(m_CSEntitiesToAdd); std::swap(EntitiesToAdd, m_EntitiesToAdd); } // Ensures m_Players manipulation happens under the chunkmap lock. cLock Lock(*this); // Add entities waiting in the queue to be added: for (auto & Item: EntitiesToAdd) { const auto Entity = Item.first.get(); if (Entity->IsPlayer()) { const auto Player = static_cast(Entity); LOGD("Adding player %s to world \"%s\".", Player->GetName().c_str(), m_WorldName.c_str()); ASSERT(std::find(m_Players.begin(), m_Players.end(), Player) == m_Players.end()); // Is it already in the list? HOW? m_Players.push_back(Player); } m_ChunkMap.AddEntity(std::move(Item.first)); if (const auto OldWorld = Item.second; OldWorld != nullptr) { cRoot::Get()->GetPluginManager()->CallHookEntityChangedWorld(*Entity, *OldWorld); } } } void cWorld::TickQueuedTasks(void) { // Move the tasks to be executed to a seperate vector to avoid deadlocks on accessing m_Tasks decltype(m_Tasks) Tasks; { cCSLock Lock(m_CSTasks); if (m_Tasks.empty()) { return; } // Partition everything to be executed by returning false to move to end of list if time reached auto MoveBeginIterator = std::partition(m_Tasks.begin(), m_Tasks.end(), [this](const decltype(m_Tasks)::value_type & a_Task) { return a_Task.first >= m_WorldAge; }); // Cut all the due tasks from m_Tasks into Tasks: Tasks.insert( Tasks.end(), std::make_move_iterator(MoveBeginIterator), std::make_move_iterator(m_Tasks.end()) ); m_Tasks.erase(MoveBeginIterator, m_Tasks.end()); } // Execute each task: for (const auto & Task : Tasks) { Task.second(*this); } // for itr - m_Tasks[] } void cWorld::UpdateSkyDarkness(void) { const auto TIME_SUNSET = 12000_tick; const auto TIME_NIGHT_START = 13187_tick; const auto TIME_NIGHT_END = 22812_tick; const auto TIME_SUNRISE = 23999_tick; const auto TIME_SPAWN_DIVISOR = 148_tick; const auto TempTime = GetTimeOfDay(); if (TempTime <= TIME_SUNSET) { m_SkyDarkness = 0; } else if (TempTime <= TIME_NIGHT_START) { m_SkyDarkness = static_cast((TIME_NIGHT_START - TempTime) / TIME_SPAWN_DIVISOR); } else if (TempTime <= TIME_NIGHT_END) { m_SkyDarkness = 8; } else { m_SkyDarkness = static_cast((TIME_SUNRISE - TempTime) / TIME_SPAWN_DIVISOR); } } void cWorld::WakeUpSimulators(Vector3i a_Block) { return m_ChunkMap.WakeUpSimulators(a_Block); } void cWorld::WakeUpSimulatorsInArea(const cCuboid & a_Area) { m_SimulatorManager->WakeUp(a_Area); } bool cWorld::ForEachBlockEntityInChunk(int a_ChunkX, int a_ChunkZ, cBlockEntityCallback a_Callback) { return m_ChunkMap.ForEachBlockEntityInChunk(a_ChunkX, a_ChunkZ, a_Callback); } void cWorld::DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_BlockY, double a_BlockZ, bool a_CanCauseFire, eExplosionSource a_Source, void * a_SourceData) { cLock Lock(*this); if (!cPluginManager::Get()->CallHookExploding(*this, a_ExplosionSize, a_CanCauseFire, a_BlockX, a_BlockY, a_BlockZ, a_Source, a_SourceData) && (a_ExplosionSize > 0)) { // TODO: CanCauseFire gets reset to false for some reason, (plugin has ability to change it, might be related) const cEntity * Entity; switch (a_Source) { case eExplosionSource::esEnderCrystal: case eExplosionSource::esGhastFireball: case eExplosionSource::esMonster: case eExplosionSource::esPrimedTNT: case eExplosionSource::esTNTMinecart: case eExplosionSource::esWitherBirth: case eExplosionSource::esWitherSkull: { Entity = static_cast(a_SourceData); break; } default: { Entity = nullptr; } } Explodinator::Kaboom(*this, Vector3d(a_BlockX, a_BlockY, a_BlockZ), FloorC(a_ExplosionSize), a_CanCauseFire, Entity); cPluginManager::Get()->CallHookExploded(*this, a_ExplosionSize, a_CanCauseFire, a_BlockX, a_BlockY, a_BlockZ, a_Source, a_SourceData); } } bool cWorld::DoWithBlockEntityAt(const Vector3i a_Position, cBlockEntityCallback a_Callback) { return m_ChunkMap.DoWithBlockEntityAt(a_Position, a_Callback); } bool cWorld::GetSignLines(int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4) { return DoWithBlockEntityAt({ a_BlockX, a_BlockY, a_BlockZ }, [&a_Line1, &a_Line2, &a_Line3, &a_Line4](cBlockEntity & a_BlockEntity) { if ((a_BlockEntity.GetBlockType() != E_BLOCK_WALLSIGN) && (a_BlockEntity.GetBlockType() != E_BLOCK_SIGN_POST)) { return false; // Not a sign } const auto & Sign = static_cast(a_BlockEntity); a_Line1 = Sign.GetLine(0); a_Line2 = Sign.GetLine(1); a_Line3 = Sign.GetLine(2); a_Line4 = Sign.GetLine(3); return true; }); } bool cWorld::DoWithChunk(int a_ChunkX, int a_ChunkZ, cChunkCallback a_Callback) { return m_ChunkMap.DoWithChunk(a_ChunkX, a_ChunkZ, a_Callback); } bool cWorld::DoWithChunkAt(Vector3i a_BlockPos, cChunkCallback a_Callback) { return m_ChunkMap.DoWithChunkAt(a_BlockPos, a_Callback); } bool cWorld::GrowTree(const Vector3i a_BlockPos) { if (GetBlock(a_BlockPos) == E_BLOCK_SAPLING) { // There is a sapling here, grow a tree according to its type: return GrowTreeFromSapling(a_BlockPos); } else { // There is nothing here, grow a tree based on the current biome here: return GrowTreeByBiome(a_BlockPos); } } bool cWorld::GrowTreeFromSapling(Vector3i a_BlockPos) { cNoise Noise(m_Generator.GetSeed()); sSetBlockVector Logs, Other; auto WorldAge = static_cast(m_WorldTickAge.count() & 0xffffffff); auto SaplingMeta = GetBlockMeta(a_BlockPos); switch (SaplingMeta & 0x07) { case E_META_SAPLING_APPLE: GetAppleTreeImage (a_BlockPos, Noise, WorldAge, Logs, Other); break; case E_META_SAPLING_BIRCH: GetBirchTreeImage (a_BlockPos, Noise, WorldAge, Logs, Other); break; case E_META_SAPLING_CONIFER: { bool IsLarge = GetLargeTreeAdjustment(a_BlockPos, SaplingMeta); GetConiferTreeImage(a_BlockPos, Noise, WorldAge, Logs, Other, IsLarge); break; } case E_META_SAPLING_ACACIA: GetAcaciaTreeImage (a_BlockPos, Noise, WorldAge, Logs, Other); break; case E_META_SAPLING_JUNGLE: { bool IsLarge = GetLargeTreeAdjustment(a_BlockPos, SaplingMeta); GetJungleTreeImage(a_BlockPos, Noise, WorldAge, Logs, Other, IsLarge); break; } case E_META_SAPLING_DARK_OAK: { if (!GetLargeTreeAdjustment(a_BlockPos, SaplingMeta)) { return false; } GetDarkoakTreeImage(a_BlockPos, Noise, WorldAge, Logs, Other); break; } } Other.insert(Other.begin(), Logs.begin(), Logs.end()); Logs.clear(); return GrowTreeImage(Other); } bool cWorld::GetLargeTreeAdjustment(Vector3i & a_BlockPos, NIBBLETYPE a_Meta) { bool IsLarge = true; a_Meta = a_Meta & 0x07; // Check to see if we are the northwest corner for (int x = 0; x < 2; ++x) { for (int z = 0; z < 2; ++z) { NIBBLETYPE meta; BLOCKTYPE type; IsLarge = IsLarge && GetBlockTypeMeta(a_BlockPos.addedXZ(x, z), type, meta) && (type == E_BLOCK_SAPLING) && ((meta & 0x07) == a_Meta); } } if (IsLarge) { return true; } IsLarge = true; // Check to see if we are the southwest corner for (int x = 0; x < 2; ++x) { for (int z = 0; z > -2; --z) { NIBBLETYPE meta; BLOCKTYPE type; IsLarge = IsLarge && GetBlockTypeMeta(a_BlockPos.addedXZ(x, z), type, meta) && (type == E_BLOCK_SAPLING) && ((meta & 0x07) == a_Meta); } } if (IsLarge) { --a_BlockPos.z; return true; } IsLarge = true; // Check to see if we are the southeast corner for (int x = 0; x > -2; --x) { for (int z = 0; z > -2; --z) { NIBBLETYPE meta; BLOCKTYPE type; IsLarge = IsLarge && GetBlockTypeMeta(a_BlockPos.addedXZ(x, z), type, meta) && (type == E_BLOCK_SAPLING) && ((meta & 0x07) == a_Meta); } } if (IsLarge) { --a_BlockPos.x; --a_BlockPos.z; return true; } IsLarge = true; // Check to see if we are the northeast corner for (int x = 0; x > -2; --x) { for (int z = 0; z < 2; ++z) { NIBBLETYPE meta; BLOCKTYPE type; IsLarge = IsLarge && GetBlockTypeMeta(a_BlockPos.addedXZ(x, z), type, meta) && (type == E_BLOCK_SAPLING) && ((meta & 0x07) == a_Meta); } } if (IsLarge) { --a_BlockPos.x; } return IsLarge; } bool cWorld::GrowTreeByBiome(const Vector3i a_BlockPos) { cNoise Noise(m_Generator.GetSeed()); sSetBlockVector Logs, Other; auto seq = static_cast(m_WorldTickAge.count() & 0xffffffff); GetTreeImageByBiome(a_BlockPos, Noise, seq, GetBiomeAt(a_BlockPos.x, a_BlockPos.z), Logs, Other); Other.insert(Other.begin(), Logs.begin(), Logs.end()); Logs.clear(); return GrowTreeImage(Other); } bool cWorld::GrowTreeImage(const sSetBlockVector & a_Blocks) { // Check that the tree has place to grow // Make a copy of the log blocks: sSetBlockVector b2; for (sSetBlockVector::const_iterator itr = a_Blocks.begin(); itr != a_Blocks.end(); ++itr) { if (itr->m_BlockType == E_BLOCK_LOG) { b2.push_back(*itr); } } // for itr - a_Blocks[] // Query blocktypes and metas at those log blocks: if (!GetBlocks(b2, false)) { return false; } // Check that at each log's coord there's an block allowed to be overwritten: for (sSetBlockVector::const_iterator itr = b2.begin(); itr != b2.end(); ++itr) { switch (itr->m_BlockType) { CASE_TREE_ALLOWED_BLOCKS: { break; } default: { return false; } } } // for itr - b2[] // All ok, replace blocks with the tree image: m_ChunkMap.ReplaceTreeBlocks(a_Blocks); return true; } int cWorld::GrowPlantAt(Vector3i a_BlockPos, int a_NumStages) { return m_ChunkMap.GrowPlantAt(a_BlockPos, a_NumStages); } bool cWorld::GrowRipePlant(Vector3i a_BlockPos) { return (GrowPlantAt(a_BlockPos, 16) > 0); } EMCSBiome cWorld::GetBiomeAt (int a_BlockX, int a_BlockZ) { return m_ChunkMap.GetBiomeAt(a_BlockX, a_BlockZ); } bool cWorld::SetBiomeAt(int a_BlockX, int a_BlockZ, EMCSBiome a_Biome) { return m_ChunkMap.SetBiomeAt(a_BlockX, a_BlockZ, a_Biome); } bool cWorld::SetAreaBiome(int a_MinX, int a_MaxX, int a_MinZ, int a_MaxZ, EMCSBiome a_Biome) { return m_ChunkMap.SetAreaBiome(a_MinX, a_MaxX, a_MinZ, a_MaxZ, a_Biome); } bool cWorld::SetAreaBiome(const cCuboid & a_Area, EMCSBiome a_Biome) { return SetAreaBiome( std::min(a_Area.p1.x, a_Area.p2.x), std::max(a_Area.p1.x, a_Area.p2.x), std::min(a_Area.p1.z, a_Area.p2.z), std::max(a_Area.p1.z, a_Area.p2.z), a_Biome ); } void cWorld::SetMaxViewDistance(int a_MaxViewDistance) { m_MaxViewDistance = Clamp(a_MaxViewDistance, cClientHandle::MIN_VIEW_DISTANCE, cClientHandle::MAX_VIEW_DISTANCE); } void cWorld::SetBlock(Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) { m_ChunkMap.SetBlock(a_BlockPos, a_BlockType, a_BlockMeta); } void cWorld::SetBlockMeta(Vector3i a_BlockPos, NIBBLETYPE a_MetaData) { m_ChunkMap.SetBlockMeta(a_BlockPos, a_MetaData); } NIBBLETYPE cWorld::GetBlockSkyLight(Vector3i a_BlockPos) const { return m_ChunkMap.GetBlockSkyLight(a_BlockPos); } NIBBLETYPE cWorld::GetBlockBlockLight(Vector3i a_BlockPos) const { return m_ChunkMap.GetBlockBlockLight(a_BlockPos); } bool cWorld::GetBlockTypeMeta(Vector3i a_BlockPos, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta) const { return m_ChunkMap.GetBlockTypeMeta(a_BlockPos, a_BlockType, a_BlockMeta); } bool cWorld::GetBlockInfo(Vector3i a_BlockPos, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_Meta, NIBBLETYPE & a_SkyLight, NIBBLETYPE & a_BlockLight) const { return m_ChunkMap.GetBlockInfo(a_BlockPos, a_BlockType, a_Meta, a_SkyLight, a_BlockLight); } bool cWorld::WriteBlockArea(cBlockArea & a_Area, int a_MinBlockX, int a_MinBlockY, int a_MinBlockZ, int a_DataTypes) { return m_ChunkMap.WriteBlockArea(a_Area, a_MinBlockX, a_MinBlockY, a_MinBlockZ, a_DataTypes); } void cWorld::SpawnItemPickups(const cItems & a_Pickups, Vector3i a_BlockPos, double a_FlyAwaySpeed, bool a_IsPlayerCreated) { auto & random = GetRandomProvider(); auto microX = random.RandReal(0, 1); auto microZ = random.RandReal(0, 1); return SpawnItemPickups(a_Pickups, Vector3d(microX, 0, microZ) + a_BlockPos, a_FlyAwaySpeed, a_IsPlayerCreated); } void cWorld::SpawnItemPickups(const cItems & a_Pickups, Vector3d a_Pos, double a_FlyAwaySpeed, bool a_IsPlayerCreated) { auto & Random = GetRandomProvider(); a_FlyAwaySpeed /= 100; // Pre-divide, so that we don't have to divide each time inside the loop for (cItems::const_iterator itr = a_Pickups.begin(); itr != a_Pickups.end(); ++itr) { if (!IsValidItem(itr->m_ItemType) || (itr->m_ItemType == E_BLOCK_AIR)) { // Don't spawn pickup if item isn't even valid; should prevent client crashing too continue; } float SpeedX = static_cast(a_FlyAwaySpeed * Random.RandInt(-10, 10)); float SpeedY = static_cast(a_FlyAwaySpeed * Random.RandInt(40, 50)); float SpeedZ = static_cast(a_FlyAwaySpeed * Random.RandInt(-10, 10)); auto Pickup = std::make_unique(a_Pos, *itr, a_IsPlayerCreated, Vector3f{SpeedX, SpeedY, SpeedZ}); auto PickupPtr = Pickup.get(); PickupPtr->Initialize(std::move(Pickup), *this); } } void cWorld::SpawnItemPickups(const cItems & a_Pickups, Vector3d a_Pos, Vector3d a_Speed, bool a_IsPlayerCreated) { for (cItems::const_iterator itr = a_Pickups.begin(); itr != a_Pickups.end(); ++itr) { if (!IsValidItem(itr->m_ItemType) || (itr->m_ItemType == E_BLOCK_AIR)) { continue; } auto pickup = std::make_unique(a_Pos, *itr, a_IsPlayerCreated, a_Speed); auto pickupPtr = pickup.get(); pickupPtr->Initialize(std::move(pickup), *this); } } UInt32 cWorld::SpawnItemPickup(Vector3d a_Pos, const cItem & a_Item, Vector3f a_Speed, int a_LifetimeTicks, bool a_CanCombine) { auto pickup = std::make_unique(a_Pos, a_Item, false, a_Speed, a_LifetimeTicks, a_CanCombine); auto pickupPtr = pickup.get(); if (!pickupPtr->Initialize(std::move(pickup), *this)) { return cEntity::INVALID_ID; } return pickupPtr->GetUniqueID(); } UInt32 cWorld::SpawnFallingBlock(Vector3d a_Pos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) { auto fallingBlock = std::make_unique(a_Pos, a_BlockType, a_BlockMeta); auto fallingBlockPtr = fallingBlock.get(); auto ID = fallingBlock->GetUniqueID(); if (!fallingBlockPtr->Initialize(std::move(fallingBlock), *this)) { return cEntity::INVALID_ID; } return ID; } UInt32 cWorld::SpawnExperienceOrb(Vector3d a_Pos, int a_Reward) { if (a_Reward < 1) { LOGWARNING("%s: Attempting to create an experience orb with non-positive reward!", __FUNCTION__); return cEntity::INVALID_ID; } auto expOrb = std::make_unique(a_Pos, a_Reward); auto expOrbPtr = expOrb.get(); if (!expOrbPtr->Initialize(std::move(expOrb), *this)) { return cEntity::INVALID_ID; } return expOrbPtr->GetUniqueID(); } std::vector cWorld::SpawnSplitExperienceOrbs(Vector3d a_Pos, int a_Reward) { std::vector OrbsID; if (a_Reward < 1) { LOGWARNING("%s: Attempting to create an experience orb with non-positive reward!", __FUNCTION__); return OrbsID; } std::vector Rewards = cExpOrb::Split(a_Reward); // Check generate number to decide speed limit (distribute range) float SpeedLimit = static_cast((Rewards.size() / 2) + 5); if (SpeedLimit > 10) { SpeedLimit = 10; } auto & Random = GetRandomProvider(); for (auto Reward : Rewards) { auto ExpOrb = std::make_unique(a_Pos, Reward); auto ExpOrbPtr = ExpOrb.get(); double SpeedX = Random.RandReal(-SpeedLimit, SpeedLimit); double SpeedY = Random.RandReal(0.5); double SpeedZ = Random.RandReal(-SpeedLimit, SpeedLimit); ExpOrbPtr->SetSpeed(SpeedX, SpeedY, SpeedZ); UInt32 Id = ExpOrbPtr->GetUniqueID(); if (ExpOrbPtr->Initialize(std::move(ExpOrb), *this)) { OrbsID.push_back(Id); } } return OrbsID; } UInt32 cWorld::SpawnMinecart(Vector3d a_Pos, int a_MinecartType, const cItem & a_Content, int a_BlockHeight) { std::unique_ptr Minecart; switch (a_MinecartType) { case E_ITEM_MINECART: Minecart = std::make_unique (a_Pos, a_Content, a_BlockHeight); break; case E_ITEM_CHEST_MINECART: Minecart = std::make_unique (a_Pos); break; case E_ITEM_FURNACE_MINECART: Minecart = std::make_unique(a_Pos); break; case E_ITEM_MINECART_WITH_TNT: Minecart = std::make_unique (a_Pos); break; case E_ITEM_MINECART_WITH_HOPPER: Minecart = std::make_unique (a_Pos); break; default: { return cEntity::INVALID_ID; } } // switch (a_MinecartType) auto MinecartPtr = Minecart.get(); if (!MinecartPtr->Initialize(std::move(Minecart), *this)) { return cEntity::INVALID_ID; } return MinecartPtr->GetUniqueID(); } UInt32 cWorld::SpawnBoat(Vector3d a_Pos, cBoat::eMaterial a_Material) { auto Boat = std::make_unique(a_Pos, a_Material); auto BoatPtr = Boat.get(); if (!BoatPtr->Initialize(std::move(Boat), *this)) { return cEntity::INVALID_ID; } return BoatPtr->GetUniqueID(); } UInt32 cWorld::SpawnPrimedTNT(Vector3d a_Pos, int a_FuseTicks, double a_InitialVelocityCoeff, bool a_ShouldPlayFuseSound) { auto TNT = std::make_unique(a_Pos, a_FuseTicks); auto TNTPtr = TNT.get(); if (!TNTPtr->Initialize(std::move(TNT), *this)) { return cEntity::INVALID_ID; } if (a_ShouldPlayFuseSound) { BroadcastSoundEffect("entity.tnt.primed", a_Pos, 1.0f, 1.0f); } auto & Random = GetRandomProvider(); TNTPtr->SetSpeed( a_InitialVelocityCoeff * Random.RandReal(-0.5f, 0.5f), a_InitialVelocityCoeff * 2, a_InitialVelocityCoeff * Random.RandReal(-0.5f, 0.5f) ); return TNTPtr->GetUniqueID(); } UInt32 cWorld::SpawnEnderCrystal(Vector3d a_Pos, bool a_ShowBottom) { auto EnderCrystal = std::make_unique(a_Pos, a_ShowBottom); auto EnderCrystalPtr = EnderCrystal.get(); if (!EnderCrystalPtr->Initialize(std::move(EnderCrystal), *this)) { return cEntity::INVALID_ID; } return EnderCrystalPtr->GetUniqueID(); } void cWorld::PlaceBlock(const Vector3i a_Position, const BLOCKTYPE a_BlockType, const NIBBLETYPE a_BlockMeta) { BLOCKTYPE BlockType; NIBBLETYPE BlockMeta; if (!GetBlockTypeMeta(a_Position, BlockType, BlockMeta)) { return; } SetBlock(a_Position, a_BlockType, a_BlockMeta); cChunkInterface ChunkInterface(GetChunkMap()); cBlockHandler::For(BlockType).OnBroken(ChunkInterface, *this, a_Position, BlockType, BlockMeta, nullptr); cBlockHandler::For(a_BlockType).OnPlaced(ChunkInterface, *this, a_Position, a_BlockType, a_BlockMeta); } bool cWorld::GetBlocks(sSetBlockVector & a_Blocks, bool a_ContinueOnFailure) { return m_ChunkMap.GetBlocks(a_Blocks, a_ContinueOnFailure); } bool cWorld::DigBlock(Vector3i a_BlockPos, const cEntity * a_Digger) { BLOCKTYPE BlockType; NIBBLETYPE BlockMeta; if (!GetBlockTypeMeta(a_BlockPos, BlockType, BlockMeta)) { return false; } if (!m_ChunkMap.DigBlock(a_BlockPos)) { return false; } cChunkInterface ChunkInterface(GetChunkMap()); cBlockHandler::For(BlockType).OnBroken(ChunkInterface, *this, a_BlockPos, BlockType, BlockMeta, a_Digger); return true; } bool cWorld::DropBlockAsPickups(Vector3i a_BlockPos, const cEntity * a_Digger, const cItem * a_Tool) { auto pickups = PickupsFromBlock(a_BlockPos, a_Digger, a_Tool); if (!DigBlock(a_BlockPos, a_Digger)) { return false; } SpawnItemPickups(pickups, Vector3d(0.5, 0.5, 0.5) + a_BlockPos, 10); return true; } cItems cWorld::PickupsFromBlock(Vector3i a_BlockPos, const cEntity * a_Digger, const cItem * a_Tool) { return m_ChunkMap.PickupsFromBlock(a_BlockPos, a_Digger, a_Tool); } void cWorld::SendBlockTo(int a_X, int a_Y, int a_Z, const cPlayer & a_Player) { m_ChunkMap.SendBlockTo(a_X, a_Y, a_Z, a_Player); } std::optional cWorld::GetHeight(int a_X, int a_Z) { return m_ChunkMap.GetHeight(a_X, a_Z); } void cWorld::SendBlockEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cClientHandle & a_Client) { m_ChunkMap.SendBlockEntity(a_BlockX, a_BlockY, a_BlockZ, a_Client); } void cWorld::MarkChunkDirty(int a_ChunkX, int a_ChunkZ) { m_ChunkMap.MarkChunkDirty(a_ChunkX, a_ChunkZ); } void cWorld::MarkChunkSaving(int a_ChunkX, int a_ChunkZ) { m_ChunkMap.MarkChunkSaving(a_ChunkX, a_ChunkZ); } void cWorld::MarkChunkSaved (int a_ChunkX, int a_ChunkZ) { m_ChunkMap.MarkChunkSaved (a_ChunkX, a_ChunkZ); } void cWorld::QueueSetChunkData(struct SetChunkData && a_SetChunkData) { // Store a copy of the data in the queue: // TODO: If the queue is too large, wait for it to get processed. Not likely, though. cCSLock Lock(m_CSSetChunkDataQueue); m_SetChunkDataQueue.emplace_back(std::move(a_SetChunkData)); } void cWorld::ChunkLighted( int a_ChunkX, int a_ChunkZ, const cChunkDef::BlockNibbles & a_BlockLight, const cChunkDef::BlockNibbles & a_SkyLight ) { m_ChunkMap.ChunkLighted(a_ChunkX, a_ChunkZ, a_BlockLight, a_SkyLight); } bool cWorld::GetChunkData(cChunkCoords a_Coords, cChunkDataCallback & a_Callback) const { return m_ChunkMap.GetChunkData(a_Coords, a_Callback); } bool cWorld::IsChunkQueued(int a_ChunkX, int a_ChunkZ) const { return m_ChunkMap.IsChunkQueued(a_ChunkX, a_ChunkZ); } bool cWorld::IsChunkValid(int a_ChunkX, int a_ChunkZ) const { return m_ChunkMap.IsChunkValid(a_ChunkX, a_ChunkZ); } bool cWorld::HasChunkAnyClients(int a_ChunkX, int a_ChunkZ) const { return m_ChunkMap.HasChunkAnyClients(a_ChunkX, a_ChunkZ); } void cWorld::UnloadUnusedChunks(void) { m_LastChunkCheck = m_WorldAge; m_ChunkMap.UnloadUnusedChunks(); } void cWorld::QueueUnloadUnusedChunks(void) { QueueTask([](cWorld & a_World) { a_World.UnloadUnusedChunks(); }); } void cWorld::CollectPickupsByEntity(cEntity & a_Entity) { m_ChunkMap.CollectPickupsByEntity(a_Entity); } bool cWorld::ForEachPlayer(cPlayerListCallback a_Callback) { // Calls the callback for each player in the list cLock Lock(*this); for (auto & Player : m_Players) { if (Player->IsTicking() && a_Callback(*Player)) { return false; } } // for itr - m_Players[] return true; } bool cWorld::DoWithPlayer(const AString & a_PlayerName, cPlayerListCallback a_Callback) { // Calls the callback for the specified player in the list cLock Lock(*this); for (auto & Player : m_Players) { if (Player->IsTicking() && (NoCaseCompare(Player->GetName(), a_PlayerName) == 0)) { a_Callback(*Player); return true; } } // for itr - m_Players[] return false; } bool cWorld::FindAndDoWithPlayer(const AString & a_PlayerNameHint, cPlayerListCallback a_Callback) { cPlayer * BestMatch = nullptr; size_t BestRating = 0; size_t NameLength = a_PlayerNameHint.length(); cLock Lock(*this); for (const auto Player : m_Players) { if (!Player->IsTicking()) { continue; } size_t Rating = RateCompareString (a_PlayerNameHint, Player->GetName()); if (Rating >= BestRating) { BestMatch = Player; BestRating = Rating; } if (Rating == NameLength) // Perfect match { break; } } // for itr - m_Players[] if (BestMatch != nullptr) { return a_Callback(*BestMatch); } return false; } bool cWorld::DoWithPlayerByUUID(const cUUID & a_PlayerUUID, cPlayerListCallback a_Callback) { cLock Lock(*this); for (auto & Player : m_Players) { if (Player->IsTicking() && (Player->GetUUID() == a_PlayerUUID)) { return a_Callback(*Player); } } return false; } bool cWorld::DoWithNearestPlayer(Vector3d a_Pos, double a_RangeLimit, cPlayerListCallback a_Callback, bool a_CheckLineOfSight, bool a_IgnoreSpectator) { double ClosestDistance = a_RangeLimit; cPlayer * ClosestPlayer = nullptr; cLock Lock(*this); for (const auto Player : m_Players) { if (!Player->IsTicking()) { continue; } if (a_IgnoreSpectator && Player->IsGameModeSpectator()) { continue; } Vector3f Pos = Player->GetPosition(); double Distance = (Pos - a_Pos).Length(); // If the player is too far, skip them: if (Distance > ClosestDistance) { continue; } // Check LineOfSight, if requested: if ( a_CheckLineOfSight && !cLineBlockTracer::LineOfSightTrace(*this, a_Pos, Pos, cLineBlockTracer::losAirWater) ) { continue; } ClosestDistance = Distance; ClosestPlayer = Player; } if (ClosestPlayer) { return a_Callback(*ClosestPlayer); } else { return false; } } void cWorld::SendPlayerList(cPlayer * a_DestPlayer) { // Sends the playerlist to a_DestPlayer cLock Lock(*this); for (const auto & Player : m_Players) { if (!Player->GetClientHandle()->IsDestroyed()) { a_DestPlayer->GetClientHandle()->SendPlayerListAddPlayer(*Player); } } } bool cWorld::ForEachEntity(cEntityCallback a_Callback) { return m_ChunkMap.ForEachEntity(a_Callback); } bool cWorld::ForEachEntityInChunk(int a_ChunkX, int a_ChunkZ, cEntityCallback a_Callback) { return m_ChunkMap.ForEachEntityInChunk(a_ChunkX, a_ChunkZ, a_Callback); } bool cWorld::ForEachEntityInBox(const cBoundingBox & a_Box, cEntityCallback a_Callback) { return m_ChunkMap.ForEachEntityInBox(a_Box, a_Callback); } size_t cWorld::GetPlayerCount() const { cLock Lock(*this); return m_Players.size(); } bool cWorld::DoWithEntityByID(UInt32 a_UniqueID, cEntityCallback a_Callback) { // First check the entities-to-add: { cCSLock Lock(m_CSEntitiesToAdd); for (const auto & Item : m_EntitiesToAdd) { if (Item.first->GetUniqueID() == a_UniqueID) { a_Callback(*Item.first); return true; } } // for ent - m_EntitiesToAdd[] } // Then check the chunkmap: return m_ChunkMap.DoWithEntityByID(a_UniqueID, a_Callback); } void cWorld::CompareChunkClients(int a_ChunkX1, int a_ChunkZ1, int a_ChunkX2, int a_ChunkZ2, cClientDiffCallback & a_Callback) { m_ChunkMap.CompareChunkClients(a_ChunkX1, a_ChunkZ1, a_ChunkX2, a_ChunkZ2, a_Callback); } bool cWorld::AddChunkClient(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Client) { return m_ChunkMap.AddChunkClient(a_ChunkX, a_ChunkZ, a_Client); } void cWorld::RemoveChunkClient(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Client) { m_ChunkMap.RemoveChunkClient(a_ChunkX, a_ChunkZ, a_Client); } void cWorld::RemoveClientFromChunks(cClientHandle * a_Client) { m_ChunkMap.RemoveClientFromChunks(a_Client); } void cWorld::SendChunkTo(int a_ChunkX, int a_ChunkZ, cChunkSender::Priority a_Priority, cClientHandle * a_Client) { m_ChunkSender.QueueSendChunkTo(a_ChunkX, a_ChunkZ, a_Priority, a_Client); } void cWorld::ForceSendChunkTo(int a_ChunkX, int a_ChunkZ, cChunkSender::Priority a_Priority, cClientHandle * a_Client) { a_Client->AddWantedChunk(a_ChunkX, a_ChunkZ); m_ChunkSender.QueueSendChunkTo(a_ChunkX, a_ChunkZ, a_Priority, a_Client); } void cWorld::PrepareChunk(int a_ChunkX, int a_ChunkZ, std::unique_ptr a_CallAfter) { m_ChunkMap.PrepareChunk(a_ChunkX, a_ChunkZ, std::move(a_CallAfter)); } void cWorld::ChunkLoadFailed(int a_ChunkX, int a_ChunkZ) { m_ChunkMap.ChunkLoadFailed(a_ChunkX, a_ChunkZ); } bool cWorld::SetSignLines(Vector3i a_BlockPos, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4, cPlayer * a_Player) { // TODO: rvalue these strings AString Line1(a_Line1); AString Line2(a_Line2); AString Line3(a_Line3); AString Line4(a_Line4); if (cRoot::Get()->GetPluginManager()->CallHookUpdatingSign(*this, a_BlockPos, Line1, Line2, Line3, Line4, a_Player)) { return false; } if ( DoWithBlockEntityAt(a_BlockPos, [&Line1, &Line2, &Line3, &Line4](cBlockEntity & a_BlockEntity) { if ((a_BlockEntity.GetBlockType() != E_BLOCK_WALLSIGN) && (a_BlockEntity.GetBlockType() != E_BLOCK_SIGN_POST)) { return false; // Not a sign } static_cast(a_BlockEntity).SetLines(Line1, Line2, Line3, Line4); return true; }) ) { cRoot::Get()->GetPluginManager()->CallHookUpdatedSign(*this, a_BlockPos, Line1, Line2, Line3, Line4, a_Player); return true; } return false; } bool cWorld::SetCommandBlockCommand(int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Command) { return DoWithBlockEntityAt({ a_BlockX, a_BlockY, a_BlockZ }, [&](cBlockEntity & a_BlockEntity) { if (a_BlockEntity.GetBlockType() != E_BLOCK_COMMAND_BLOCK) { return false; } static_cast(a_BlockEntity).SetCommand(a_Command); return true; }); } bool cWorld::IsTrapdoorOpen(int a_BlockX, int a_BlockY, int a_BlockZ) { BLOCKTYPE Block; NIBBLETYPE Meta; if (!GetBlockTypeMeta({ a_BlockX, a_BlockY, a_BlockZ }, Block, Meta)) { return false; } if ((Block != E_BLOCK_TRAPDOOR) && (Block != E_BLOCK_IRON_TRAPDOOR)) { return false; } return (Meta & 0x4) > 0; } bool cWorld::SetTrapdoorOpen(int a_BlockX, int a_BlockY, int a_BlockZ, bool a_Open) { BLOCKTYPE Block; NIBBLETYPE Meta; if (!GetBlockTypeMeta({ a_BlockX, a_BlockY, a_BlockZ }, Block, Meta)) { return false; } if ((Block != E_BLOCK_TRAPDOOR) && (Block != E_BLOCK_IRON_TRAPDOOR)) { return false; } bool IsOpen = (Meta & 0x4) != 0; if (a_Open != IsOpen) { SetBlockMeta({ a_BlockX, a_BlockY, a_BlockZ }, Meta ^ 0x4); BroadcastSoundParticleEffect(EffectID::SFX_RANDOM_WOODEN_TRAPDOOR_OPEN, { a_BlockX, a_BlockY, a_BlockZ }, 0); return true; } return false; } void cWorld::RegenerateChunk(int a_ChunkX, int a_ChunkZ) { m_ChunkMap.MarkChunkRegenerating(a_ChunkX, a_ChunkZ); m_Generator.QueueGenerateChunk({a_ChunkX, a_ChunkZ}, true); } void cWorld::GenerateChunk(int a_ChunkX, int a_ChunkZ) { m_ChunkMap.GenerateChunk(a_ChunkX, a_ChunkZ); } void cWorld::QueueLightChunk(int a_ChunkX, int a_ChunkZ, std::unique_ptr a_Callback) { m_Lighting.QueueChunk(a_ChunkX, a_ChunkZ, std::move(a_Callback)); } bool cWorld::IsChunkLighted(int a_ChunkX, int a_ChunkZ) { return m_ChunkMap.IsChunkLighted(a_ChunkX, a_ChunkZ); } bool cWorld::ForEachChunkInRect(int a_MinChunkX, int a_MaxChunkX, int a_MinChunkZ, int a_MaxChunkZ, cChunkDataCallback & a_Callback) { return m_ChunkMap.ForEachChunkInRect(a_MinChunkX, a_MaxChunkX, a_MinChunkZ, a_MaxChunkZ, a_Callback); } bool cWorld::ForEachLoadedChunk(cFunctionRef a_Callback) { return m_ChunkMap.ForEachLoadedChunk(a_Callback); } void cWorld::SaveAllChunks(void) { if (IsSavingEnabled()) { m_LastSave = m_WorldAge; m_ChunkMap.SaveAllChunks(); } } void cWorld::QueueSaveAllChunks(void) { QueueTask([](cWorld & a_World) { a_World.SaveAllChunks(); }); } void cWorld::QueueTask(std::function a_Task) { cCSLock Lock(m_CSTasks); m_Tasks.emplace_back(0, std::move(a_Task)); } void cWorld::ScheduleTask(const cTickTime a_DelayTicks, std::function a_Task) { const auto TargetTick = a_DelayTicks + m_WorldAge; // Insert the task into the list of scheduled tasks { cCSLock Lock(m_CSTasks); m_Tasks.emplace_back(TargetTick, std::move(a_Task)); } } void cWorld::AddEntity(OwnedEntity a_Entity, cWorld * a_OldWorld) { cCSLock Lock(m_CSEntitiesToAdd); m_EntitiesToAdd.emplace_back(std::move(a_Entity), a_OldWorld); } OwnedEntity cWorld::RemoveEntity(cEntity & a_Entity) { // Remove players from the player list: if (a_Entity.IsPlayer()) { cLock Lock(*this); const auto Player = static_cast(&a_Entity); LOGD("Removing player %s from world \"%s\"", Player->GetName().c_str(), m_WorldName.c_str()); m_Players.erase(std::remove(m_Players.begin(), m_Players.end(), Player), m_Players.end()); } // Check if the entity is in the chunkmap: auto Entity = m_ChunkMap.RemoveEntity(a_Entity); if (Entity != nullptr) { Entity->OnRemoveFromWorld(*this); return Entity; } // Check if the entity is in the queue to be added to the world: cCSLock Lock(m_CSEntitiesToAdd); auto itr = std::find_if(m_EntitiesToAdd.begin(), m_EntitiesToAdd.end(), [&a_Entity](const auto & Item) { return (Item.first.get() == &a_Entity); } ); if (itr != m_EntitiesToAdd.end()) { Entity = std::move(itr->first); m_EntitiesToAdd.erase(itr); } return Entity; } size_t cWorld::GetNumChunks(void) const { return m_ChunkMap.GetNumChunks(); } size_t cWorld::GetNumUnusedDirtyChunks(void) const { return m_ChunkMap.GetNumUnusedDirtyChunks(); } void cWorld::GetChunkStats(int & a_NumValid, int & a_NumDirty, int & a_NumInLightingQueue) { m_ChunkMap.GetChunkStats(a_NumValid, a_NumDirty); a_NumInLightingQueue = static_cast(m_Lighting.GetQueueLength()); } void cWorld::TickQueuedBlocks(void) { if (m_BlockTickQueue.empty()) { return; } m_BlockTickQueueCopy.clear(); m_BlockTickQueue.swap(m_BlockTickQueueCopy); for (std::vector::iterator itr = m_BlockTickQueueCopy.begin(); itr != m_BlockTickQueueCopy.end(); ++itr) { BlockTickQueueItem * Block = (*itr); Block->TicksToWait -= 1; if (Block->TicksToWait <= 0) { // TODO: Handle the case when the chunk is already unloaded m_ChunkMap.TickBlock({Block->X, Block->Y, Block->Z}); delete Block; // We don't have to remove it from the vector, this will happen automatically on the next tick } else { m_BlockTickQueue.push_back(Block); // Keep the block in the queue } } // for itr - m_BlockTickQueueCopy[] } void cWorld::QueueBlockForTick(int a_BlockX, int a_BlockY, int a_BlockZ, int a_TicksToWait) { BlockTickQueueItem * Block = new BlockTickQueueItem; Block->X = a_BlockX; Block->Y = a_BlockY; Block->Z = a_BlockZ; Block->TicksToWait = a_TicksToWait; m_BlockTickQueue.push_back(Block); } bool cWorld::IsBlockDirectlyWatered(int a_BlockX, int a_BlockY, int a_BlockZ) { return ( IsBlockWater(GetBlock({ a_BlockX - 1, a_BlockY, a_BlockZ })) || IsBlockWater(GetBlock({ a_BlockX + 1, a_BlockY, a_BlockZ })) || IsBlockWater(GetBlock({ a_BlockX, a_BlockY, a_BlockZ - 1 })) || IsBlockWater(GetBlock({ a_BlockX, a_BlockY, a_BlockZ + 1 })) ); } UInt32 cWorld::SpawnMob(double a_PosX, double a_PosY, double a_PosZ, eMonsterType a_MonsterType, bool a_Baby) { auto Monster = cMonster::NewMonsterFromType(a_MonsterType); if (Monster == nullptr) { return cEntity::INVALID_ID; } Monster->SetPosition(a_PosX, a_PosY, a_PosZ); if (a_Baby) { Monster->SetAge(-1); } return SpawnMobFinalize(std::move(Monster)); } UInt32 cWorld::SpawnMobFinalize(std::unique_ptr a_Monster) { ASSERT(a_Monster != nullptr); // Give the mob full health. a_Monster->SetHealth(a_Monster->GetMaxHealth()); // A plugin doesn't agree with the spawn. bail out. if (cPluginManager::Get()->CallHookSpawningMonster(*this, *a_Monster)) { return cEntity::INVALID_ID; } auto & Monster = *a_Monster; // Initialize the monster into the current world. if (!Monster.Initialize(std::move(a_Monster), *this)) { return cEntity::INVALID_ID; } cPluginManager::Get()->CallHookSpawnedMonster(*this, Monster); return Monster.GetUniqueID(); } UInt32 cWorld::CreateProjectile(Vector3d a_Pos, cProjectileEntity::eKind a_Kind, cEntity * a_Creator, const cItem * a_Item, const Vector3d * a_Speed) { auto Projectile = cProjectileEntity::Create(a_Kind, a_Creator, a_Pos, a_Item, a_Speed); if (Projectile == nullptr) { return cEntity::INVALID_ID; } auto ProjectilePtr = Projectile.get(); if (!ProjectilePtr->Initialize(std::move(Projectile), *this)) { return cEntity::INVALID_ID; } return ProjectilePtr->GetUniqueID(); } UInt32 cWorld::CreateProjectile(double a_PosX, double a_PosY, double a_PosZ, cProjectileEntity::eKind a_Kind, cEntity * a_Creator, const cItem * a_Item, const Vector3d * a_Speed) { return CreateProjectile({a_PosX, a_PosY, a_PosZ}, a_Kind, a_Creator, a_Item, a_Speed); } int cWorld::GetTickRandomNumber(int a_Range) { return GetRandomProvider().RandInt(a_Range); } void cWorld::TabCompleteUserName(const AString & a_Text, AStringVector & a_Results) { typedef std::pair pair_t; size_t LastSpace = a_Text.find_last_of(" "); // Find the position of the last space AString LastWord = a_Text.substr(LastSpace + 1, a_Text.length()); // Find the last word if (LastWord.empty()) { return; } std::vector UsernamesByWeight; cLock Lock(*this); for (const auto Player : m_Players) { AString PlayerName = Player->HasCustomName() ? Player->GetCustomName() : Player->GetName(); AString::size_type Found = StrToLower(PlayerName).find(StrToLower(LastWord)); // Try to find last word in playername if (Found == AString::npos) { continue; // No match } UsernamesByWeight.push_back(std::make_pair(Found, PlayerName)); // Match! Store it with the position of the match as a weight } Lock.Unlock(); std::sort(UsernamesByWeight.begin(), UsernamesByWeight.end()); // Sort lexicographically (by the first value, then second), so higher weights (usernames with match closer to start) come first (#1274) /* TODO: Uncomment once migrated to C++11 std::transform( UsernamesByWeight.begin(), UsernamesByWeight.end(), std::back_inserter(a_Results), [](const pair_t & p) { return p.first; } ); */ a_Results.reserve(UsernamesByWeight.size()); for (std::vector::const_iterator itr = UsernamesByWeight.begin(); itr != UsernamesByWeight.end(); ++itr) { a_Results.push_back(itr->second); } } void cWorld::SetChunkAlwaysTicked(int a_ChunkX, int a_ChunkZ, bool a_AlwaysTicked) { m_ChunkMap.SetChunkAlwaysTicked(a_ChunkX, a_ChunkZ, a_AlwaysTicked); } cRedstoneSimulator * cWorld::InitializeRedstoneSimulator(cIniFile & a_IniFile) { AString SimulatorName = a_IniFile.GetValueSet("Physics", "RedstoneSimulator", "Incremental"); if (SimulatorName.empty()) { LOGWARNING("[Physics] RedstoneSimulator not present or empty in %s, using the default of \"Incremental\".", GetIniFileName().c_str()); SimulatorName = "Incremental"; } cRedstoneSimulator * res = nullptr; if (NoCaseCompare(SimulatorName, "Incremental") == 0) { res = new cIncrementalRedstoneSimulator(*this); } else if (NoCaseCompare(SimulatorName, "noop") == 0) { res = new cRedstoneNoopSimulator(*this); } else { LOGWARNING("[Physics] Unknown RedstoneSimulator \"%s\" in %s, using the default of \"Incremental\".", SimulatorName.c_str(), GetIniFileName().c_str()); res = new cIncrementalRedstoneSimulator(*this); } m_SimulatorManager->RegisterSimulator(res, 2 /* Two game ticks is a redstone tick */); return res; } cFluidSimulator * cWorld::InitializeFluidSimulator(cIniFile & a_IniFile, const char * a_FluidName, BLOCKTYPE a_SimulateBlock, BLOCKTYPE a_StationaryBlock) { auto SimulatorNameKey = fmt::format(FMT_STRING("{}Simulator"), a_FluidName); auto SimulatorSectionName = fmt::format(FMT_STRING("{}Simulator"), a_FluidName); bool IsWater = (strcmp(a_FluidName, "Water") == 0); // Used for defaults AString DefaultSimulatorName = ((GetDimension() == dimNether) && IsWater) ? "Vaporise" : "Vanilla"; AString SimulatorName = a_IniFile.GetValueSet("Physics", SimulatorNameKey, DefaultSimulatorName); if (SimulatorName.empty()) { LOGWARNING("[Physics] %s not present or empty in %s, using the default of \"%s\".", SimulatorNameKey, GetIniFileName(), DefaultSimulatorName); SimulatorName = DefaultSimulatorName; } cFluidSimulator * res = nullptr; int Rate = 1; if ( (NoCaseCompare(SimulatorName, "vaporize") == 0) || (NoCaseCompare(SimulatorName, "vaporise") == 0) ) { res = new cVaporizeFluidSimulator(*this, a_SimulateBlock, a_StationaryBlock); } else if ( (NoCaseCompare(SimulatorName, "noop") == 0) || (NoCaseCompare(SimulatorName, "nop") == 0) || (NoCaseCompare(SimulatorName, "null") == 0) || (NoCaseCompare(SimulatorName, "nil") == 0) ) { res = new cNoopFluidSimulator(*this, a_SimulateBlock, a_StationaryBlock); } else { int Falloff = a_IniFile.GetValueSetI(SimulatorSectionName, "Falloff", IsWater ? 1 : 2); int TickDelay = a_IniFile.GetValueSetI(SimulatorSectionName, "TickDelay", IsWater ? 5 : 30); int NumNeighborsForSource = a_IniFile.GetValueSetI(SimulatorSectionName, "NumNeighborsForSource", IsWater ? 2 : -1); if ((Falloff > 15) || (Falloff < 0)) { LOGWARNING("Falloff for %s simulator is out of range, assuming default of %d", a_FluidName, IsWater ? 1 : 2); Falloff = IsWater ? 1 : 2; } if (NoCaseCompare(SimulatorName, "floody") == 0) { res = new cFloodyFluidSimulator(*this, a_SimulateBlock, a_StationaryBlock, static_cast(Falloff), TickDelay, NumNeighborsForSource); } else if (NoCaseCompare(SimulatorName, "vanilla") == 0) { res = new cVanillaFluidSimulator(*this, a_SimulateBlock, a_StationaryBlock, static_cast(Falloff), TickDelay, NumNeighborsForSource); } else { // The simulator name doesn't match anything we have, issue a warning: LOGWARNING("%s [Physics]:%s specifies an unknown simulator, using the default \"Vanilla\".", GetIniFileName().c_str(), SimulatorNameKey.c_str()); res = new cVanillaFluidSimulator(*this, a_SimulateBlock, a_StationaryBlock, static_cast(Falloff), TickDelay, NumNeighborsForSource); } } m_SimulatorManager->RegisterSimulator(res, Rate); return res; } //////////////////////////////////////////////////////////////////////////////// // cWorld::cChunkGeneratorCallbacks: cWorld::cChunkGeneratorCallbacks::cChunkGeneratorCallbacks(cWorld & a_World) : m_World(&a_World) { } void cWorld::cChunkGeneratorCallbacks::OnChunkGenerated(cChunkDesc & a_ChunkDesc) { cChunkDef::BlockNibbles BlockMetas; a_ChunkDesc.CompressBlockMetas(BlockMetas); struct SetChunkData Data({ a_ChunkDesc.GetChunkX(), a_ChunkDesc.GetChunkZ() }); { Data.BlockData.SetAll(a_ChunkDesc.GetBlockTypes(), BlockMetas); std::copy(a_ChunkDesc.GetBiomeMap(), a_ChunkDesc.GetBiomeMap() + std::size(a_ChunkDesc.GetBiomeMap()), Data.BiomeMap); std::copy(a_ChunkDesc.GetHeightMap(), a_ChunkDesc.GetHeightMap() + std::size(a_ChunkDesc.GetHeightMap()), Data.HeightMap); Data.Entities = std::move(a_ChunkDesc.GetEntities()); Data.BlockEntities = std::move(a_ChunkDesc.GetBlockEntities()); Data.IsLightValid = false; } m_World->QueueSetChunkData(std::move(Data)); } bool cWorld::cChunkGeneratorCallbacks::IsChunkValid(cChunkCoords a_Coords) { return m_World->IsChunkValid(a_Coords.m_ChunkX, a_Coords.m_ChunkZ); } bool cWorld::cChunkGeneratorCallbacks::IsChunkQueued(cChunkCoords a_Coords) { return m_World->IsChunkQueued(a_Coords.m_ChunkX, a_Coords.m_ChunkZ); } bool cWorld::cChunkGeneratorCallbacks::HasChunkAnyClients(cChunkCoords a_Coords) { return m_World->HasChunkAnyClients(a_Coords.m_ChunkX, a_Coords.m_ChunkZ); } void cWorld::cChunkGeneratorCallbacks::CallHookChunkGenerating(cChunkDesc & a_ChunkDesc) { cPluginManager::Get()->CallHookChunkGenerating( *m_World, a_ChunkDesc.GetChunkX(), a_ChunkDesc.GetChunkZ(), &a_ChunkDesc ); } void cWorld::cChunkGeneratorCallbacks::CallHookChunkGenerated (cChunkDesc & a_ChunkDesc) { cPluginManager::Get()->CallHookChunkGenerated( *m_World, a_ChunkDesc.GetChunkX(), a_ChunkDesc.GetChunkZ(), &a_ChunkDesc ); } bool cWorld::IsSlimeChunk(int a_ChunkX, int a_ChunkZ) const { cNoise Noise(GetSeed()); return (Noise.IntNoise2DInt(a_ChunkX, a_ChunkZ) / 8) % 10 == 0; // 10% chance } ================================================ FILE: src/World.h ================================================ #pragma once #include #include "Simulator/SimulatorManager.h" #include "ChunkMap.h" #include "WorldStorage/WorldStorage.h" #include "ChunkGeneratorThread.h" #include "ChunkSender.h" #include "Defines.h" #include "LightingThread.h" #include "IniFile.h" #include "Item.h" #include "Mobs/Monster.h" #include "Entities/ProjectileEntity.h" #include "Entities/Boat.h" #include "ForEachChunkProvider.h" #include "Scoreboard.h" #include "MapManager.h" #include "Blocks/WorldInterface.h" #include "Blocks/BroadcastInterface.h" #include "EffectID.h" class cFireSimulator; class cFluidSimulator; class cSandSimulator; class cRedstoneSimulator; class cItem; class cPlayer; class cClientHandle; class cEntity; class cChunkGenerator; // The thread responsible for generating chunks class cCuboid; class cCompositeChat; class cDeadlockDetect; class cUUID; struct SetChunkData; class cWorld // tolua_export final: public cForEachChunkProvider, public cWorldInterface, public cBroadcastInterface // tolua_begin { public: // tolua_end /** A simple RAII locker for the chunkmap - locks the chunkmap in its constructor, unlocks it in the destructor */ class cLock: public cCSLock { using Super = cCSLock; public: cLock(const cWorld & a_World); }; /** Construct the world and read settings from its ini file. @param a_DeadlockDetect is used for tracking this world's age, detecting a possible deadlock. @param a_WorldNames is a list of all world names, used to validate linked worlds */ cWorld( const AString & a_WorldName, const AString & a_DataPath, cDeadlockDetect & a_DeadlockDetect, const AStringVector & a_WorldNames, eDimension a_Dimension = dimOverworld, const AString & a_LinkedOverworldName = {} ); virtual ~cWorld() override; // tolua_begin /** Get whether saving chunks is enabled */ bool IsSavingEnabled(void) const { return m_IsSavingEnabled; } /** Set whether saving chunks is enabled */ void SetSavingEnabled(bool a_IsSavingEnabled) { m_IsSavingEnabled = a_IsSavingEnabled; } int GetTicksUntilWeatherChange(void) const { return m_WeatherInterval; } /** Is the daylight cycle enabled? */ virtual bool IsDaylightCycleEnabled(void) const { return m_IsDaylightCycleEnabled; } /** Sets the daylight cycle to true / false. */ virtual void SetDaylightCycleEnabled(bool a_IsDaylightCycleEnabled) { m_IsDaylightCycleEnabled = a_IsDaylightCycleEnabled; BroadcastTimeUpdate(); } void SetTicksUntilWeatherChange(int a_WeatherInterval) { m_WeatherInterval = a_WeatherInterval; } /** Returns the default weather interval for the specific weather type. Returns -1 for any unknown weather. */ int GetDefaultWeatherInterval(eWeather a_Weather) const; /** Returns the current game mode. Partly OBSOLETE, you should use IsGameModeXXX() functions wherever applicable */ eGameMode GetGameMode(void) const { return m_GameMode; } /** Returns true if the world is in Creative mode */ bool IsGameModeCreative(void) const { return (m_GameMode == gmCreative); } /** Returns true if the world is in Survival mode */ bool IsGameModeSurvival(void) const { return (m_GameMode == gmSurvival); } /** Returns true if the world is in Adventure mode */ bool IsGameModeAdventure(void) const { return (m_GameMode == gmAdventure); } /** Returns true if the world is in Spectator mode */ bool IsGameModeSpectator(void) const { return (m_GameMode == gmSpectator); } bool IsPVPEnabled(void) const { return m_bEnabledPVP; } /** Returns true if farmland trampling is enabled */ bool IsFarmlandTramplingEnabled(void) const { return m_bFarmlandTramplingEnabled; } bool IsDeepSnowEnabled(void) const { return m_IsDeepSnowEnabled; } bool ShouldLavaSpawnFire(void) const { return m_ShouldLavaSpawnFire; } bool VillagersShouldHarvestCrops(void) const { return m_VillagersShouldHarvestCrops; } virtual eDimension GetDimension(void) const override { return m_Dimension; } // tolua_end virtual cTickTime GetTimeOfDay(void) const override; virtual cTickTimeLong GetWorldAge(void) const override; cTickTimeLong GetWorldDate() const; cTickTimeLong GetWorldTickAge() const; virtual void SetTimeOfDay(cTickTime a_TimeOfDay) override; /** Retrieves the world height at the specified coords; returns nullopt if chunk not loaded / generated */ virtual std::optional GetHeight(int a_BlockX, int a_BlockZ) override; // Exported in ManualBindings.cpp // Broadcast respective packets to all clients of the chunk where the event is taking place // Implemented in Broadcaster.cpp // (Please keep these alpha-sorted) virtual void BroadcastAttachEntity (const cEntity & a_Entity, const cEntity & a_Vehicle) override; virtual void BroadcastBlockAction (Vector3i a_BlockPos, Byte a_Byte1, Byte a_Byte2, BLOCKTYPE a_BlockType, const cClientHandle * a_Exclude = nullptr) override; // Exported in ManualBindings_World.cpp virtual void BroadcastBlockBreakAnimation(UInt32 a_EntityID, Vector3i a_BlockPos, Int8 a_Stage, const cClientHandle * a_Exclude = nullptr) override; virtual void BroadcastBlockEntity (Vector3i a_BlockPos, const cClientHandle * a_Exclude = nullptr) override; ///< If there is a block entity at the specified coods, sends it to all clients except a_Exclude virtual void BroadcastBossBarUpdateHealth(const cEntity & a_Entity, UInt32 a_UniqueID, float a_FractionFilled) override; // tolua_begin virtual void BroadcastChat (const AString & a_Message, const cClientHandle * a_Exclude = nullptr, eMessageType a_ChatPrefix = mtCustom) override; virtual void BroadcastChatInfo (const AString & a_Message, const cClientHandle * a_Exclude = nullptr) override { BroadcastChat(a_Message, a_Exclude, mtInformation); } virtual void BroadcastChatFailure(const AString & a_Message, const cClientHandle * a_Exclude = nullptr) override { BroadcastChat(a_Message, a_Exclude, mtFailure); } virtual void BroadcastChatSuccess(const AString & a_Message, const cClientHandle * a_Exclude = nullptr) override { BroadcastChat(a_Message, a_Exclude, mtSuccess); } virtual void BroadcastChatWarning(const AString & a_Message, const cClientHandle * a_Exclude = nullptr) override { BroadcastChat(a_Message, a_Exclude, mtWarning); } virtual void BroadcastChatFatal (const AString & a_Message, const cClientHandle * a_Exclude = nullptr) override { BroadcastChat(a_Message, a_Exclude, mtFailure); } virtual void BroadcastChatDeath (const AString & a_Message, const cClientHandle * a_Exclude = nullptr) override { BroadcastChat(a_Message, a_Exclude, mtDeath); } virtual void BroadcastChat (const cCompositeChat & a_Message, const cClientHandle * a_Exclude = nullptr) override; // tolua_end virtual void BroadcastCollectEntity (const cEntity & a_Collected, const cEntity & a_Collector, unsigned a_Count, const cClientHandle * a_Exclude = nullptr) override; virtual void BroadcastDestroyEntity (const cEntity & a_Entity, const cClientHandle * a_Exclude = nullptr) override; virtual void BroadcastDetachEntity (const cEntity & a_Entity, const cEntity & a_PreviousVehicle) override; virtual void BroadcastEntityEffect (const cEntity & a_Entity, int a_EffectID, int a_Amplifier, int a_Duration, const cClientHandle * a_Exclude = nullptr) override; virtual void BroadcastEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item, const cClientHandle * a_Exclude = nullptr) override; virtual void BroadcastEntityHeadLook (const cEntity & a_Entity, const cClientHandle * a_Exclude = nullptr) override; virtual void BroadcastEntityLook (const cEntity & a_Entity, const cClientHandle * a_Exclude = nullptr) override; virtual void BroadcastEntityMetadata (const cEntity & a_Entity, const cClientHandle * a_Exclude = nullptr) override; virtual void BroadcastEntityPosition (const cEntity & a_Entity, const cClientHandle * a_Exclude = nullptr) override; void BroadcastEntityProperties (const cEntity & a_Entity); virtual void BroadcastEntityVelocity (const cEntity & a_Entity, const cClientHandle * a_Exclude = nullptr) override; virtual void BroadcastEntityAnimation (const cEntity & a_Entity, EntityAnimation a_Animation, const cClientHandle * a_Exclude = nullptr) override; // tolua_export virtual void BroadcastLeashEntity (const cEntity & a_Entity, const cEntity & a_EntityLeashedTo) override; virtual void BroadcastParticleEffect (const AString & a_ParticleName, Vector3f a_Src, Vector3f a_Offset, float a_ParticleData, int a_ParticleAmount, const cClientHandle * a_Exclude = nullptr) override; // Exported in ManualBindings_World.cpp virtual void BroadcastParticleEffect (const AString & a_ParticleName, Vector3f a_Src, Vector3f a_Offset, float a_ParticleData, int a_ParticleAmount, std::array a_Data, const cClientHandle * a_Exclude = nullptr) override; // Exported in ManualBindings_World.cpp virtual void BroadcastPlayerListAddPlayer (const cPlayer & a_Player, const cClientHandle * a_Exclude = nullptr) override; virtual void BroadcastPlayerListHeaderFooter (const cCompositeChat & a_Header, const cCompositeChat & a_Footer) override; // tolua_export virtual void BroadcastPlayerListRemovePlayer (const cPlayer & a_Player, const cClientHandle * a_Exclude = nullptr) override; virtual void BroadcastPlayerListUpdateDisplayName(const cPlayer & a_Player, const AString & a_CustomName, const cClientHandle * a_Exclude = nullptr) override; virtual void BroadcastPlayerListUpdateGameMode (const cPlayer & a_Player, const cClientHandle * a_Exclude = nullptr) override; virtual void BroadcastPlayerListUpdatePing () override; virtual void BroadcastRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID, const cClientHandle * a_Exclude = nullptr) override; virtual void BroadcastScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) override; virtual void BroadcastScoreUpdate (const AString & a_Objective, const AString & a_Player, cObjective::Score a_Score, Byte a_Mode) override; virtual void BroadcastDisplayObjective (const AString & a_Objective, cScoreboard::eDisplaySlot a_Display) override; virtual void BroadcastSoundEffect (const AString & a_SoundName, Vector3d a_Position, float a_Volume, float a_Pitch, const cClientHandle * a_Exclude = nullptr) override; // Exported in ManualBindings_World.cpp virtual void BroadcastSoundParticleEffect (const EffectID a_EffectID, Vector3i a_SrcPos, int a_Data, const cClientHandle * a_Exclude = nullptr) override; // Exported in ManualBindings_World.cpp virtual void BroadcastSpawnEntity (cEntity & a_Entity, const cClientHandle * a_Exclude = nullptr) override; virtual void BroadcastThunderbolt (Vector3i a_BlockPos, const cClientHandle * a_Exclude = nullptr) override; virtual void BroadcastTimeUpdate (const cClientHandle * a_Exclude = nullptr) override; virtual void BroadcastUnleashEntity (const cEntity & a_Entity) override; virtual void BroadcastWeather (eWeather a_Weather, const cClientHandle * a_Exclude = nullptr) override; virtual cBroadcastInterface & GetBroadcastManager(void) override { return *this; } /** If there is a block entity at the specified coords, sends it to the client specified */ void SendBlockEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cClientHandle & a_Client); void MarkChunkDirty (int a_ChunkX, int a_ChunkZ); void MarkChunkSaving(int a_ChunkX, int a_ChunkZ); void MarkChunkSaved (int a_ChunkX, int a_ChunkZ); /** Puts the chunk data into a queue to be set into the chunkmap in the tick thread. Modifies the a_SetChunkData - moves the entities contained in it into the queue. */ void QueueSetChunkData(SetChunkData && a_SetChunkData); void ChunkLighted( int a_ChunkX, int a_ChunkZ, const cChunkDef::BlockNibbles & a_BlockLight, const cChunkDef::BlockNibbles & a_SkyLight ); /** Calls the callback with the chunk's data, if available (with ChunkCS locked). Returns true if the chunk was reported successfully, false if not (chunk not present or callback failed). */ bool GetChunkData(cChunkCoords a_Coords, cChunkDataCallback & a_Callback) const; /** Returns true iff the chunk is in the loader / generator queue. */ bool IsChunkQueued(int a_ChunkX, int a_ChunkZ) const; /** Returns true iff the chunk is present and valid. */ bool IsChunkValid(int a_ChunkX, int a_ChunkZ) const; bool HasChunkAnyClients(int a_ChunkX, int a_ChunkZ) const; /** Queues a task to unload unused chunks onto the tick thread. The prefferred way of unloading. */ void QueueUnloadUnusedChunks(void); // tolua_export void CollectPickupsByEntity(cEntity & a_Entity); /** Calls the callback for each player in the list; returns true if all players processed, false if the callback aborted by returning true */ virtual bool ForEachPlayer(cPlayerListCallback a_Callback) override; // >> EXPORTED IN MANUALBINDINGS << /** Calls the callback for the player of the given name; returns true if the player was found and the callback called, false if player not found. Callback return value is ignored. If there are multiple players of the same name, only (random) one is processed by the callback. */ bool DoWithPlayer(const AString & a_PlayerName, cPlayerListCallback a_Callback); // >> EXPORTED IN MANUALBINDINGS << /** Finds a player from a partial or complete player name and calls the callback - case-insensitive */ bool FindAndDoWithPlayer(const AString & a_PlayerNameHint, cPlayerListCallback a_Callback); // >> EXPORTED IN MANUALBINDINGS << /** Calls the callback for nearest player for given position, Returns false if player not found, otherwise returns the same value as the callback */ bool DoWithNearestPlayer(Vector3d a_Pos, double a_RangeLimit, cPlayerListCallback a_Callback, bool a_CheckLineOfSight = true, bool a_IgnoreSpectator = true); /** Finds the player over his uuid and calls the callback */ bool DoWithPlayerByUUID(const cUUID & a_PlayerUUID, cPlayerListCallback a_Callback); // >> EXPORTED IN MANUALBINDINGS << void SendPlayerList(cPlayer * a_DestPlayer); // Sends playerlist to the player /** Adds the entity into its appropriate chunk; takes ownership of the entity ptr. The entity is added lazily - this function only puts it in a queue that is then processed by the Tick thread. If a_OldWorld is provided, a corresponding ENTITY_CHANGED_WORLD event is triggerred after the addition. */ void AddEntity(OwnedEntity a_Entity, cWorld * a_OldWorld = nullptr); /** Removes the entity from the world. Returns an owning reference to the found entity. */ OwnedEntity RemoveEntity(cEntity & a_Entity); /** Calls the callback for each entity in the entire world; returns true if all entities processed, false if the callback aborted by returning true */ bool ForEachEntity(cEntityCallback a_Callback); // Exported in ManualBindings.cpp /** Calls the callback for each entity in the specified chunk; returns true if all entities processed, false if the callback aborted by returning true */ bool ForEachEntityInChunk(int a_ChunkX, int a_ChunkZ, cEntityCallback a_Callback); // Exported in ManualBindings.cpp /** Calls the callback for each entity that has a nonempty intersection with the specified boundingbox. Returns true if all entities processed, false if the callback aborted by returning true. If any chunk in the box is missing, ignores the entities in that chunk silently. */ virtual bool ForEachEntityInBox(const cBoundingBox & a_Box, cEntityCallback a_Callback) override; // Exported in ManualBindings.cpp /** Returns the number of players currently in this world. */ size_t GetPlayerCount() const; /** Calls the callback if the entity with the specified ID is found, with the entity object as the callback param. Returns true if entity found and callback returned false. */ bool DoWithEntityByID(UInt32 a_UniqueID, cEntityCallback a_Callback); // Exported in ManualBindings.cpp /** Compares clients of two chunks, calls the callback accordingly */ void CompareChunkClients(int a_ChunkX1, int a_ChunkZ1, int a_ChunkX2, int a_ChunkZ2, cClientDiffCallback & a_Callback); /** Adds client to a chunk, if not already present; returns true if added, false if present */ bool AddChunkClient(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Client); /** Removes client from the chunk specified */ void RemoveChunkClient(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Client); /** Removes the client from all chunks it is present in */ void RemoveClientFromChunks(cClientHandle * a_Client); /** Sends the chunk to the client specified, if the client doesn't have the chunk yet. If chunk not valid, the request is postponed (ChunkSender will send that chunk when it becomes valid + lighted). */ void SendChunkTo(int a_ChunkX, int a_ChunkZ, cChunkSender::Priority a_Priority, cClientHandle * a_Client); /** Sends the chunk to the client specified, even if the client already has the chunk. If the chunk's not valid, the request is postponed (ChunkSender will send that chunk when it becomes valid + lighted). */ void ForceSendChunkTo(int a_ChunkX, int a_ChunkZ, cChunkSender::Priority a_Priority, cClientHandle * a_Client); /** Queues the chunk for preparing - making sure that it's generated and lit. The specified chunk is queued to be loaded or generated, and lit if needed. The specified callback is called after the chunk has been prepared. If there's no preparation to do, only the callback is called. It is legal to call with no callback. */ void PrepareChunk(int a_ChunkX, int a_ChunkZ, std::unique_ptr a_CallAfter = {}); /** Marks the chunk as failed-to-load: */ void ChunkLoadFailed(int a_ChunkX, int a_ChunkZ); /** Sets the sign text, asking plugins for permission first. a_Player is the player who this change belongs to, may be nullptr. Returns true if sign text changed. */ bool SetSignLines(Vector3i a_BlockPos, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4, cPlayer * a_Player = nullptr); // Exported in ManualBindings.cpp /** Sets the command block command. Returns true if command changed. */ bool SetCommandBlockCommand(int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Command); // tolua_export bool SetCommandBlockCommand(Vector3i a_BlockPos, const AString & a_Command) { return SetCommandBlockCommand(a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, a_Command); } /** Is the trapdoor open? Returns false if there is no trapdoor at the specified coords. */ bool IsTrapdoorOpen(int a_BlockX, int a_BlockY, int a_BlockZ); // tolua_export /** Set the state of a trapdoor. Returns true if the trapdoor was updated, false if there was no trapdoor at those coords. */ bool SetTrapdoorOpen(int a_BlockX, int a_BlockY, int a_BlockZ, bool a_Open); // tolua_export /** Regenerate the given chunk. */ void RegenerateChunk(int a_ChunkX, int a_ChunkZ); // tolua_export /** Generates the given chunk. */ void GenerateChunk(int a_ChunkX, int a_ChunkZ); // tolua_export /** Queues a chunk for lighting; a_Callback is called after the chunk is lighted */ void QueueLightChunk(int a_ChunkX, int a_ChunkZ, std::unique_ptr a_Callback = {}); bool IsChunkLighted(int a_ChunkX, int a_ChunkZ); /** Calls the callback for each chunk in the coords specified (all cords are inclusive). Returns true if all chunks have been processed successfully */ virtual bool ForEachChunkInRect(int a_MinChunkX, int a_MaxChunkX, int a_MinChunkZ, int a_MaxChunkZ, cChunkDataCallback & a_Callback) override; /** Calls the callback for each loaded chunk. Returns true if all chunks have been processed successfully */ bool ForEachLoadedChunk(cFunctionRef a_Callback); /** Sets the block at the specified coords to the specified value. Full processing, incl. updating neighbors, is performed. */ void SetBlock(Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta); /** Sets the block at the specified coords to the specified value. The replacement doesn't trigger block updates, nor wake up simulators. The replaced blocks aren't checked for block entities (block entity is leaked if it exists at this block) */ void FastSetBlock(Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) { m_ChunkMap.FastSetBlock(a_BlockPos, a_BlockType, a_BlockMeta); } /** Returns the block type at the specified position. Returns 0 if the chunk is not valid. */ BLOCKTYPE GetBlock(Vector3i a_BlockPos) const { return m_ChunkMap.GetBlock(a_BlockPos); } /** Returns the block meta at the specified position. Returns 0 if the chunk is not valid. */ NIBBLETYPE GetBlockMeta(Vector3i a_BlockPos) const { return m_ChunkMap.GetBlockMeta(a_BlockPos); } /** Sets the meta for the specified block, while keeping the blocktype. Ignored if the chunk is invalid. */ void SetBlockMeta(Vector3i a_BlockPos, NIBBLETYPE a_MetaData); /** Returns the sky light value at the specified block position. The sky light is "raw" - not affected by time-of-day. Returns 0 if chunk not valid. */ NIBBLETYPE GetBlockSkyLight(Vector3i a_BlockPos) const; /** Returns the block-light value at the specified block position. Returns 0 if chunk not valid. */ NIBBLETYPE GetBlockBlockLight(Vector3i a_BlockPos) const; /** Retrieves the block type and meta at the specified coords. Stores the result into a_BlockType and a_BlockMeta. Returns true if successful, false if chunk not present. TODO: Export in ManualBindings_World.cpp. */ bool GetBlockTypeMeta(Vector3i a_BlockPos, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta) const; /** Queries the whole block specification from the world. Returns true if all block info was retrieved successfully, false if not (invalid chunk / bad position). Exported in ManualBindings_World.cpp. */ bool GetBlockInfo(Vector3i a_BlockPos, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_Meta, NIBBLETYPE & a_SkyLight, NIBBLETYPE & a_BlockLight) const; // TODO: NIBBLETYPE GetBlockActualLight(int a_BlockX, int a_BlockY, int a_BlockZ); /** Writes the block area into the specified coords. Returns true if all chunks have been processed. Prefer cBlockArea::Write() instead, this is the internal implementation; cBlockArea does error checking, too. a_DataTypes is a bitmask of cBlockArea::baXXX constants ORed together. Doesn't wake up simulators, use WakeUpSimulatorsInArea() for that. */ virtual bool WriteBlockArea(cBlockArea & a_Area, int a_MinBlockX, int a_MinBlockY, int a_MinBlockZ, int a_DataTypes) override; // tolua_begin /** Spawns item pickups for each item in the list. The initial position of the pickups is at the center of the specified block, with a small random offset. May compress pickups if too many entities. */ void SpawnItemPickups(const cItems & a_Pickups, Vector3i a_BlockPos, double a_FlyAwaySpeed = 1.0, bool a_IsPlayerCreated = false); /** Spawns item pickups for each item in the list. May compress pickups if too many entities. */ void SpawnItemPickups(const cItems & a_Pickups, Vector3d a_Pos, double a_FlyAwaySpeed = 1.0, bool a_IsPlayerCreated = false); /** OBSOLETE, use the Vector3d-based overload instead. Spawns item pickups for each item in the list. May compress pickups if too many entities. */ virtual void SpawnItemPickups(const cItems & a_Pickups, double a_BlockX, double a_BlockY, double a_BlockZ, double a_FlyAwaySpeed = 1.0, bool a_IsPlayerCreated = false) override { return SpawnItemPickups(a_Pickups, Vector3d{a_BlockX, a_BlockY, a_BlockZ}, a_FlyAwaySpeed, a_IsPlayerCreated); } /** Spawns item pickups for each item in the list. May compress pickups if too many entities. All pickups get the speed specified. */ void SpawnItemPickups(const cItems & a_Pickups, Vector3d a_Pos, Vector3d a_Speed, bool a_IsPlayerCreated = false); /** OBSOLETE, use the Vector3d-based overload instead. Spawns item pickups for each item in the list. May compress pickups if too many entities. All pickups get the speed specified. */ virtual void SpawnItemPickups(const cItems & a_Pickups, double a_BlockX, double a_BlockY, double a_BlockZ, double a_SpeedX, double a_SpeedY, double a_SpeedZ, bool a_IsPlayerCreated = false) override { return SpawnItemPickups(a_Pickups, {a_BlockX, a_BlockY, a_BlockZ}, {a_SpeedX, a_SpeedY, a_SpeedZ}, a_IsPlayerCreated); } /** Spawns a single pickup containing the specified item. */ UInt32 SpawnItemPickup(Vector3d a_Pos, const cItem & a_Item, Vector3f a_Speed, int a_LifetimeTicks = 6000, bool a_CanCombine = true); /** OBSOLETE, use the Vector3d-based overload instead. Spawns a single pickup containing the specified item. */ virtual UInt32 SpawnItemPickup(double a_PosX, double a_PosY, double a_PosZ, const cItem & a_Item, float a_SpeedX = 0.f, float a_SpeedY = 0.f, float a_SpeedZ = 0.f, int a_LifetimeTicks = 6000, bool a_CanCombine = true) override { return SpawnItemPickup({a_PosX, a_PosY, a_PosZ}, a_Item, {a_SpeedX, a_SpeedY, a_SpeedZ}, a_LifetimeTicks, a_CanCombine); } /** Spawns an falling block entity at the given position. Returns the UniqueID of the spawned falling block, or cEntity::INVALID_ID on failure. */ UInt32 SpawnFallingBlock(Vector3d a_Pos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta); /** Spawns an falling block entity at the given position. Returns the UniqueID of the spawned falling block, or cEntity::INVALID_ID on failure. */ UInt32 SpawnFallingBlock(Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) { // When creating from a block position (Vector3i), move the spawn point to the middle of the block by adding (0.5, 0, 0.5) return SpawnFallingBlock(Vector3d(0.5, 0, 0.5) + a_BlockPos, a_BlockType, a_BlockMeta); } /** OBSOLETE, use the Vector3-based overload instead. Spawns an falling block entity at the given position. Returns the UniqueID of the spawned falling block, or cEntity::INVALID_ID on failure. */ UInt32 SpawnFallingBlock(int a_X, int a_Y, int a_Z, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) { return SpawnFallingBlock(Vector3i{a_X, a_Y, a_Z}, a_BlockType, a_BlockMeta); } /** Spawns an minecart at the given coordinates. Returns the UniqueID of the spawned minecart, or cEntity::INVALID_ID on failure. */ UInt32 SpawnMinecart(Vector3d a_Pos, int a_MinecartType, const cItem & a_Content = cItem(), int a_BlockHeight = 1); /** OBSOLETE, use the Vector3d-based overload instead. Spawns an minecart at the given coordinates. Returns the UniqueID of the spawned minecart, or cEntity::INVALID_ID on failure. */ UInt32 SpawnMinecart(double a_X, double a_Y, double a_Z, int a_MinecartType, const cItem & a_Content = cItem(), int a_BlockHeight = 1) { return SpawnMinecart({a_X, a_Y, a_Z}, a_MinecartType, a_Content, a_BlockHeight); } // DEPRECATED, use the vector-parametered version instead. UInt32 SpawnBoat(double a_X, double a_Y, double a_Z, cBoat::eMaterial a_Material) { LOGWARNING("cWorld::SpawnBoat(double, double, double) is deprecated, use cWorld::SpawnBoat(Vector3d) instead."); return SpawnBoat({a_X, a_Y, a_Z}, a_Material); } /** Spawns a boat at the given coordinates. Returns the UniqueID of the spawned boat, or cEntity::INVALID_ID on failure. */ UInt32 SpawnBoat(Vector3d a_Pos, cBoat::eMaterial a_Material); /** Spawns an experience orb at the given location with the given reward. Returns the UniqueID of the spawned experience orb, or cEntity::INVALID_ID on failure. */ UInt32 SpawnExperienceOrb(Vector3d a_Pos, int a_Reward); /** OBSOLETE, use the Vector3d-based overload instead. Spawns an experience orb at the given location with the given reward. Returns the UniqueID of the spawned experience orb, or cEntity::INVALID_ID on failure. */ virtual UInt32 SpawnExperienceOrb(double a_X, double a_Y, double a_Z, int a_Reward) override { return SpawnExperienceOrb({a_X, a_Y, a_Z}, a_Reward); } // tolua_end /** Spawns experience orbs of the specified total value at the given location. The orbs' values are split according to regular Minecraft rules. Returns an vector of UniqueID of all the orbs. */ virtual std::vector SpawnSplitExperienceOrbs(Vector3d a_Pos, int a_Reward) override; // Exported in ManualBindings_World.cpp /** OBSOLETE, use the Vector3d-based overload instead. Spawns experience orbs of the specified total value at the given location. The orbs' values are split according to regular Minecraft rules. Returns an vector of UniqueID of all the orbs. */ std::vector SpawnSplitExperienceOrbs(double a_X, double a_Y, double a_Z, int a_Reward) { return SpawnSplitExperienceOrbs({a_X, a_Y, a_Z}, a_Reward); } // tolua_begin // DEPRECATED, use the vector-parametered version instead. UInt32 SpawnPrimedTNT(double a_X, double a_Y, double a_Z, int a_FuseTimeInSec = 80, double a_InitialVelocityCoeff = 1, bool a_ShouldPlayFuseSound = true) { LOGWARNING("cWorld::SpawnPrimedTNT(double, double, double) is deprecated, use cWorld::SpawnPrimedTNT(Vector3d) instead."); return SpawnPrimedTNT({a_X, a_Y, a_Z}, a_FuseTimeInSec, a_InitialVelocityCoeff, a_ShouldPlayFuseSound); } /** Spawns a new primed TNT entity at the specified block coords and specified fuse duration. Initial velocity is given based on the relative coefficient provided. Returns the UniqueID of the created entity, or cEntity::INVALID_ID on failure. */ UInt32 SpawnPrimedTNT(Vector3d a_Pos, int a_FuseTimeInSec = 80, double a_InitialVelocityCoeff = 1, bool a_ShouldPlayFuseSound = true); /** Spawns a new ender crystal at the specified block coords. Returns the UniqueID of the created entity, or cEntity::INVALID_ID on failure. */ UInt32 SpawnEnderCrystal(Vector3d a_Pos, bool a_ShowBottom); // tolua_end /** Replaces the specified block with another, and calls the OnPlaced block handler. The OnBroken block handler is called for the replaced block. Wakes up the simulators. If the chunk for any of the blocks is not loaded, the set operation is ignored silently. */ void PlaceBlock(const Vector3i a_Position, const BLOCKTYPE a_BlockType, const NIBBLETYPE a_BlockMeta); /** Retrieves block types of the specified blocks. If a chunk is not loaded, doesn't modify the block. Returns true if all blocks were read. */ bool GetBlocks(sSetBlockVector & a_Blocks, bool a_ContinueOnFailure); using cWorldInterface::SendBlockTo; // tolua_begin /** Replaces the specified block with air, and calls the OnBroken block handler. Wakes up the simulators. Doesn't produce pickups, use DropBlockAsPickups() for that instead. Returns true on success, false if the chunk is not loaded. */ bool DigBlock(Vector3i a_BlockPos, const cEntity * a_Digger = nullptr); /** OBSOLETE, use the Vector3-based overload instead. Replaces the specified block with air, and calls the apropriate block handlers (OnBreaking(), OnBroken()). Wakes up the simulators. Doesn't produce pickups, use DropBlockAsPickups() for that instead. Returns true on success, false if the chunk is not loaded. */ bool DigBlock(int a_X, int a_Y, int a_Z, cEntity * a_Digger = nullptr) { return DigBlock({a_X, a_Y, a_Z}, a_Digger); } /** Digs the specified block, and spawns the appropriate pickups for it. a_Digger is an optional entity causing the digging, usually the player. a_Tool is an optional item used to dig up the block, used by the handlers (empty hand vs shears produce different pickups from leaves). An empty hand is assumed if a_Tool is nullptr. Returns true on success, false if the chunk is not loaded. */ bool DropBlockAsPickups(Vector3i a_BlockPos, const cEntity * a_Digger = nullptr, const cItem * a_Tool = nullptr); /** Returns all the pickups that would result if the a_Digger dug up the block at a_BlockPos using a_Tool a_Digger is usually a player, but can be nullptr for natural causes. a_Tool is an optional item used to dig up the block, used by the handlers (empty hand vs shears produce different pickups from leaves). An empty hand is assumed if a_Tool is nullptr. Returns an empty cItems object if the chunk is not present. */ cItems PickupsFromBlock(Vector3i a_BlockPos, const cEntity * a_Digger = nullptr, const cItem * a_Tool = nullptr); /** Sends the block at the specified coords to the player. Used mainly when plugins disable block-placing or block-breaking, to restore the previous block. */ virtual void SendBlockTo(int a_X, int a_Y, int a_Z, const cPlayer & a_Player) override; /** Set default spawn at the given coordinates. Returns false if the new spawn couldn't be stored in the INI file. */ bool SetSpawn(int a_X, int a_Y, int a_Z); int GetSpawnX(void) const { return m_SpawnX; } int GetSpawnY(void) const { return m_SpawnY; } int GetSpawnZ(void) const { return m_SpawnZ; } Vector3i GetSpawnPos() const { return {m_SpawnX, m_SpawnY, m_SpawnZ}; } /** Wakes up the simulators for the specified block */ virtual void WakeUpSimulators(Vector3i a_Block) override; /** Wakes up the simulators for the specified area of blocks */ void WakeUpSimulatorsInArea(const cCuboid & a_Area); // tolua_end inline cSimulatorManager * GetSimulatorManager(void) { return m_SimulatorManager.get(); } inline cFluidSimulator * GetWaterSimulator(void) { return m_WaterSimulator; } inline cFluidSimulator * GetLavaSimulator (void) { return m_LavaSimulator; } inline cRedstoneSimulator * GetRedstoneSimulator(void) { return m_RedstoneSimulator; } /** Calls the callback for each block entity in the specified chunk; returns true if all block entities processed, false if the callback aborted by returning true */ bool ForEachBlockEntityInChunk(int a_ChunkX, int a_ChunkZ, cBlockEntityCallback a_Callback); // Exported in ManualBindings.cpp /** Does an explosion with the specified strength at the specified coordinates. Executes the HOOK_EXPLODING and HOOK_EXPLODED hooks as part of the processing. a_SourceData exact type depends on the a_Source, see the declaration of the esXXX constants in Defines.h for details. Exported to Lua manually in ManualBindings_World.cpp in order to support the variable a_SourceData param. */ virtual void DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_BlockY, double a_BlockZ, bool a_CanCauseFire, eExplosionSource a_Source, void * a_SourceData) override; /** Calls the callback for the block entity at the specified coords; returns false if there's no block entity at those coords, and whatever the callback returns if found. */ virtual bool DoWithBlockEntityAt(Vector3i a_Position, cBlockEntityCallback a_Callback) override; // Exported in ManualBindings.cpp /** Retrieves the test on the sign at the specified coords; returns false if there's no sign at those coords, true if found */ bool GetSignLines (int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4); // Exported in ManualBindings.cpp /** a_Player is using block entity at [x, y, z], handle that: */ void UseBlockEntity(cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ) { m_ChunkMap.UseBlockEntity(a_Player, a_BlockX, a_BlockY, a_BlockZ); } // tolua_export /** Calls the callback for the chunk specified, with ChunkMapCS locked. Returns false if the chunk doesn't exist, otherwise returns the same value as the callback */ bool DoWithChunk(int a_ChunkX, int a_ChunkZ, cChunkCallback a_Callback); /** Calls the callback for the chunk at the block position specified, with ChunkMapCS locked. Returns false if the chunk isn't loaded, otherwise returns the same value as the callback */ bool DoWithChunkAt(Vector3i a_BlockPos, cChunkCallback a_Callback); /** Imprints the specified blocks into the world, as long as each log block replaces only allowed blocks. a_Blocks specifies the logs, leaves, vines and possibly other blocks that comprise a single tree. Returns true if the tree is imprinted successfully, false otherwise. */ bool GrowTreeImage(const sSetBlockVector & a_Blocks); /** Grows a tree at the specified coords. If the specified block is a sapling, the tree is grown from that sapling. Otherwise a tree is grown based on the biome. Returns true if the tree was grown, false if not (invalid chunk, insufficient space). Exported in DeprecatedBindings due to the obsolete int-based overload. */ bool GrowTree(Vector3i a_BlockPos); /** Grows a tree from the sapling at the specified coords. If the sapling is a part of a large-tree sapling (2x2), a large tree growth is attempted. Returns true if the tree was grown, false if not (invalid chunk, insufficient space). Exported in DeprecatedBindings due to the obsolete int-based overload and obsolete additional SaplingMeta param. */ bool GrowTreeFromSapling(Vector3i a_BlockPos); /** Grows a tree at the specified coords, based on the biome in the place. Returns true if the tree was grown, false if not (invalid chunk, insufficient space). Exported in DeprecatedBindings due to the obsolete int-based overload. */ bool GrowTreeByBiome(Vector3i a_BlockPos); // tolua_begin /** Grows the plant at the specified position by at most a_NumStages. The block's Grow handler is invoked. Returns the number of stages the plant has grown, 0 if not a plant. */ int GrowPlantAt(Vector3i a_BlockPos, int a_NumStages = 1); /** Grows the plant at the specified block to its ripe stage. Returns true if grown, false if not (invalid chunk, non-growable block, already ripe). */ bool GrowRipePlant(Vector3i a_BlockPos); /** OBSOLETE, use the Vector3-based overload instead. Grows the plant at the specified block to its ripe stage. a_IsByBonemeal is obsolete, do not use. Returns true if grown, false if not (invalid chunk, non-growable block, already ripe). */ bool GrowRipePlant(int a_BlockX, int a_BlockY, int a_BlockZ, bool a_IsByBonemeal = false) { UNUSED(a_IsByBonemeal); LOGWARNING("Warning: cWorld:GrowRipePlant function expects Vector3i-based coords rather than int-based coords. Emulating old-style call."); return GrowRipePlant({ a_BlockX, a_BlockY, a_BlockZ }); } /** Returns the biome at the specified coords. Reads the biome from the chunk, if loaded, otherwise uses the world generator to provide the biome value */ EMCSBiome GetBiomeAt(int a_BlockX, int a_BlockZ); /** Sets the biome at the specified coords. Returns true if successful, false if not (chunk not loaded). Doesn't resend the chunk to clients, use ForceSendChunkTo() for that. */ bool SetBiomeAt(int a_BlockX, int a_BlockZ, EMCSBiome a_Biome); /** Sets the biome at the area. Returns true if successful, false if any subarea failed (chunk not loaded). (Re)sends the chunks to their relevant clients if successful. */ bool SetAreaBiome(int a_MinX, int a_MaxX, int a_MinZ, int a_MaxZ, EMCSBiome a_Biome); /** Sets the biome at the area. Returns true if successful, false if any subarea failed (chunk not loaded). (Re)sends the chunks to their relevant clients if successful. The cuboid needn't be sorted. */ bool SetAreaBiome(const cCuboid & a_Area, EMCSBiome a_Biome); /** Returns the name of the world */ const AString & GetName(void) const { return m_WorldName; } /** Returns the data path to the world data */ const AString & GetDataPath(void) const { return m_DataPath; } /** Returns the name of the world.ini file used by this world */ const AString & GetIniFileName(void) const {return m_IniFileName; } /** Returns the associated scoreboard instance. */ cScoreboard & GetScoreBoard(void) { return m_Scoreboard; } /** Returns the associated map manager instance. */ cMapManager & GetMapManager(void) { return m_MapManager; } bool AreCommandBlocksEnabled(void) const { return m_bCommandBlocksEnabled; } void SetCommandBlocksEnabled(bool a_Flag) { m_bCommandBlocksEnabled = a_Flag; } eShrapnelLevel GetTNTShrapnelLevel(void) const { return m_TNTShrapnelLevel; } void SetTNTShrapnelLevel(eShrapnelLevel a_Flag) { m_TNTShrapnelLevel = a_Flag; } int GetMaxViewDistance(void) const { return m_MaxViewDistance; } void SetMaxViewDistance(int a_MaxViewDistance); bool ShouldUseChatPrefixes(void) const { return m_bUseChatPrefixes; } void SetShouldUseChatPrefixes(bool a_Flag) { m_bUseChatPrefixes = a_Flag; } bool ShouldBroadcastDeathMessages(void) const { return m_BroadcastDeathMessages; } bool ShouldBroadcastAchievementMessages(void) const { return m_BroadcastAchievementMessages; } AString GetLinkedNetherWorldName(void) const { return m_LinkedNetherWorldName; } void SetLinkedNetherWorldName(const AString & a_Name) { m_LinkedNetherWorldName = a_Name; } AString GetLinkedEndWorldName(void) const { return m_LinkedEndWorldName; } void SetLinkedEndWorldName(const AString & a_Name) { m_LinkedEndWorldName = a_Name; } AString GetLinkedOverworldName(void) const { return m_LinkedOverworldName; } void SetLinkedOverworldName(const AString & a_Name) { m_LinkedOverworldName = a_Name; } /** Returns or sets the minumim or maximum netherportal width */ virtual int GetMinNetherPortalWidth(void) const override { return m_MinNetherPortalWidth; } virtual int GetMaxNetherPortalWidth(void) const override { return m_MaxNetherPortalWidth; } virtual void SetMinNetherPortalWidth(int a_NewMinWidth) override { m_MinNetherPortalWidth = a_NewMinWidth; } virtual void SetMaxNetherPortalWidth(int a_NewMaxWidth) override { m_MaxNetherPortalWidth = a_NewMaxWidth; } /** Returns or sets the minumim or maximum netherportal height */ virtual int GetMinNetherPortalHeight(void) const override { return m_MinNetherPortalHeight; } virtual int GetMaxNetherPortalHeight(void) const override { return m_MaxNetherPortalHeight; } virtual void SetMinNetherPortalHeight(int a_NewMinHeight) override { m_MinNetherPortalHeight = a_NewMinHeight; } virtual void SetMaxNetherPortalHeight(int a_NewMaxHeight) override { m_MaxNetherPortalHeight = a_NewMaxHeight; } // tolua_end /** Saves all chunks immediately. Dangerous interface, may deadlock, use QueueSaveAllChunks() instead */ void SaveAllChunks(void); /** Queues a task to save all chunks onto the tick thread. The prefferred way of saving chunks from external sources */ void QueueSaveAllChunks(void); // tolua_export /** Queues a task onto the tick thread. The task object will be deleted once the task is finished */ void QueueTask(std::function a_Task); // Exported in ManualBindings.cpp /** Queues a lambda task onto the tick thread, with the specified delay. */ void ScheduleTask(cTickTime a_DelayTicks, std::function a_Task); /** Returns the number of chunks loaded */ size_t GetNumChunks() const; // tolua_export /** Returns the number of unused dirty chunks. That's the number of chunks that we can save and then unload. */ size_t GetNumUnusedDirtyChunks(void) const; // tolua_export /** Returns the number of chunks loaded and dirty, and in the lighting queue */ void GetChunkStats(int & a_NumValid, int & a_NumDirty, int & a_NumInLightingQueue); // Various queues length queries (cannot be const, they lock their CS): inline size_t GetGeneratorQueueLength (void) { return m_Generator.GetQueueLength(); } // tolua_export inline size_t GetLightingQueueLength (void) { return m_Lighting.GetQueueLength(); } // tolua_export inline size_t GetStorageLoadQueueLength(void) { return m_Storage.GetLoadQueueLength(); } // tolua_export inline size_t GetStorageSaveQueueLength(void) { return m_Storage.GetSaveQueueLength(); } // tolua_export cLightingThread & GetLightingThread(void) { return m_Lighting; } void InitializeSpawn(void); /** Starts threads that belong to this world. */ void Start(); /** Stops threads that belong to this world (part of deinit). a_DeadlockDetect is used for tracking this world's age, detecting a possible deadlock. */ void Stop(cDeadlockDetect & a_DeadlockDetect); /** Processes the blocks queued for ticking with a delay (m_BlockTickQueue[]) */ void TickQueuedBlocks(void); struct BlockTickQueueItem { int X; int Y; int Z; int TicksToWait; }; /** Queues the block to be ticked after the specified number of game ticks */ void QueueBlockForTick(int a_BlockX, int a_BlockY, int a_BlockZ, int a_TicksToWait); // tolua_export // tolua_begin /** Casts a thunderbolt at the specified coords */ void CastThunderbolt(Vector3i a_Block); void CastThunderbolt(int a_BlockX, int a_BlockY, int a_BlockZ); // DEPRECATED, use vector-parametered version instead /** Sets the specified weather; resets weather interval; asks and notifies plugins of the change */ void SetWeather(eWeather a_NewWeather); /** Forces a weather change in the next game tick */ void ChangeWeather(void); /** Returns the current weather. Instead of comparing values directly to the weather constants, use IsWeatherXXX() functions, if possible */ eWeather GetWeather(void) const { return m_Weather; } /** Returns true if the current weather is sunny. */ bool IsWeatherSunny(void) const { return (m_Weather == wSunny); } /** Returns true if it is sunny at the specified location. This takes into account biomes. */ bool IsWeatherSunnyAt(int a_BlockX, int a_BlockZ) const; /** Returns true if the current weather is rainy. */ bool IsWeatherRain(void) const { return (m_Weather == wRain); } /** Returns true if it is raining at the specified location. This takes into account biomes. */ bool IsWeatherRainAt(int a_BlockX, int a_BlockZ) { return (IsWeatherRain() && !IsBiomeNoDownfall(GetBiomeAt(a_BlockX, a_BlockZ))); } /** Returns true if the current weather is stormy. */ bool IsWeatherStorm(void) const { return (m_Weather == wStorm); } /** Returns true if the weather is stormy at the specified location. This takes into account biomes. */ bool IsWeatherStormAt(int a_BlockX, int a_BlockZ) { return (IsWeatherStorm() && !IsBiomeNoDownfall(GetBiomeAt(a_BlockX, a_BlockZ))); } /** Returns true if the world currently has any precipitation - rain, storm or snow. */ bool IsWeatherWet(void) const { return !IsWeatherSunny(); } /** Returns true if it is raining or storming at the specified location. This takes into account biomes. */ virtual bool IsWeatherWetAt(int a_BlockX, int a_BlockZ) override; /** Returns true if it is raining or storming at the specified location, and the rain reaches (the bottom of) the specified block position. */ virtual bool IsWeatherWetAtXYZ(Vector3i a_Position) override; /** Returns the seed of the world. */ int GetSeed(void) const { return m_Generator.GetSeed(); } // tolua_end cChunkGeneratorThread & GetGenerator(void) { return m_Generator; } cWorldStorage & GetStorage (void) { return m_Storage; } cChunkMap * GetChunkMap (void) { return &m_ChunkMap; } /** Causes the specified block to be ticked on the next Tick() call. Only one block coord per chunk may be set, a second call overwrites the first call */ void SetNextBlockToTick(const Vector3i a_BlockPos); // tolua_export int GetMaxSugarcaneHeight(void) const { return m_MaxSugarcaneHeight; } // tolua_export int GetMaxCactusHeight (void) const { return m_MaxCactusHeight; } // tolua_export bool IsBlockDirectlyWatered(int a_BlockX, int a_BlockY, int a_BlockZ); // tolua_export /** Spawns a mob of the specified type. Returns the mob's UniqueID if recognized and spawned, cEntity::INVALID_ID otherwise */ virtual UInt32 SpawnMob(double a_PosX, double a_PosY, double a_PosZ, eMonsterType a_MonsterType, bool a_Baby = false) override; // tolua_export /** Wraps cEntity::Initialize, doing Monster-specific things before spawning the monster. Takes ownership of the given Monster reference. */ UInt32 SpawnMobFinalize(std::unique_ptr a_Monster); /** Creates a projectile of the specified type. Returns the projectile's UniqueID if successful, cEntity::INVALID_ID otherwise Item parameter is currently used for Fireworks to correctly set entity metadata based on item metadata. */ UInt32 CreateProjectile(Vector3d a_Pos, cProjectileEntity::eKind a_Kind, cEntity * a_Creator, const cItem * a_Item, const Vector3d * a_Speed = nullptr); // tolua_export /** OBSOLETE, use the Vector3d-based overload instead. Creates a projectile of the specified type. Returns the projectile's UniqueID if successful, cEntity::INVALID_ID otherwise Item parameter is currently used for Fireworks to correctly set entity metadata based on item metadata. */ UInt32 CreateProjectile(double a_PosX, double a_PosY, double a_PosZ, cProjectileEntity::eKind a_Kind, cEntity * a_Creator, const cItem * a_Item, const Vector3d * a_Speed = nullptr); // tolua_export /** Returns a random number in range [0 .. a_Range]. */ int GetTickRandomNumber(int a_Range); /** Appends all usernames starting with a_Text (case-insensitive) into Results */ void TabCompleteUserName(const AString & a_Text, AStringVector & a_Results); /** Get the current darkness level based on the time */ NIBBLETYPE GetSkyDarkness() { return m_SkyDarkness; } /** Increments (a_AlwaysTicked == true) or decrements (false) the m_AlwaysTicked counter for the specified chunk. If the m_AlwaysTicked counter is greater than zero, the chunk is ticked in the tick-thread regardless of whether it has any clients or not. This function allows nesting and task-concurrency (multiple separate tasks can request ticking and as long as at least one requests is active the chunk will be ticked). */ void SetChunkAlwaysTicked(int a_ChunkX, int a_ChunkZ, bool a_AlwaysTicked = true); // tolua_export /** Returns true if slimes should spawn in the chunk. */ bool IsSlimeChunk(int a_ChunkX, int a_ChunkZ) const; // tolua_export private: class cTickThread: public cIsThread { using Super = cIsThread; public: cTickThread(cWorld & a_World); protected: cWorld & m_World; // cIsThread overrides: virtual void Execute(void) override; } ; /** Implementation of the callbacks that the ChunkGenerator uses to store new chunks and interface to plugins */ class cChunkGeneratorCallbacks : public cChunkGeneratorThread::cChunkSink, public cChunkGeneratorThread::cPluginInterface { cWorld * m_World; // cChunkSink overrides: virtual void OnChunkGenerated (cChunkDesc & a_ChunkDesc) override; virtual bool IsChunkValid (cChunkCoords a_Coords) override; virtual bool HasChunkAnyClients(cChunkCoords a_Coords) override; virtual bool IsChunkQueued (cChunkCoords a_Coords) override; // cPluginInterface overrides: virtual void CallHookChunkGenerating(cChunkDesc & a_ChunkDesc) override; virtual void CallHookChunkGenerated (cChunkDesc & a_ChunkDesc) override; public: cChunkGeneratorCallbacks(cWorld & a_World); } ; /** The maximum number of allowed unused dirty chunks for this world. Loaded from config, enforced every 10 seconds by freeing some unused dirty chunks if this was exceeded. */ size_t m_UnusedDirtyChunksCap; AString m_WorldName; /** The path to the root directory for the world files. Does not including trailing path specifier. */ AString m_DataPath; /** The name of the overworld that portals in this world should link to. Only has effect if this world is a Nether or End world. */ AString m_LinkedOverworldName; AString m_IniFileName; /** Name of the storage schema used to load and save chunks */ AString m_StorageSchema; int m_StorageCompressionFactor; /** Whether or not writing chunks to disk is currently enabled */ std::atomic m_IsSavingEnabled; /** The dimension of the world, used by the client to provide correct lighting scheme */ eDimension m_Dimension; bool m_IsSpawnExplicitlySet; int m_SpawnX; int m_SpawnY; int m_SpawnZ; // Variables defining the minimum and maximum size for a nether portal int m_MinNetherPortalWidth; int m_MaxNetherPortalWidth; int m_MinNetherPortalHeight; int m_MaxNetherPortalHeight; bool m_BroadcastDeathMessages; bool m_BroadcastAchievementMessages; bool m_IsDaylightCycleEnabled; /** The age of the world. Monotonic, always increasing each game tick, persistent across server restart. We need sub-tick precision here, that's why we store the time in milliseconds and calculate ticks off of it. */ std::chrono::milliseconds m_WorldAge; /** The fully controllable age of the world. A value used to calculate the current day, and time of day. Settable by plugins and players, and persistent. We need sub-tick precision here, that's why we store the time in milliseconds and calculate ticks off of it. */ std::chrono::milliseconds m_WorldDate; /** The time since this world began, in ticks. Monotonic, but does not persist across restarts. Used for less important but heavy tasks that run periodically. These tasks don't need to follow wallclock time, and slowing their rate down if TPS drops is desirable. */ cTickTimeLong m_WorldTickAge; std::chrono::milliseconds m_LastChunkCheck; // The last WorldAge in which unloading and possibly saving was triggered. std::chrono::milliseconds m_LastSave; // The last WorldAge in which save-all was triggerred. std::map m_LastSpawnMonster; // The last WorldAge (in ticks) in which a monster was spawned (for each megatype of monster) // MG TODO : find a way to optimize without creating unmaintenability (if mob IDs are becoming unrowed) NIBBLETYPE m_SkyDarkness; eGameMode m_GameMode; bool m_bEnabledPVP; bool m_bFarmlandTramplingEnabled; bool m_IsDeepSnowEnabled; bool m_ShouldLavaSpawnFire; bool m_VillagersShouldHarvestCrops; std::vector m_BlockTickQueue; std::vector m_BlockTickQueueCopy; // Second is for safely removing the objects from the queue std::unique_ptr m_SimulatorManager; std::unique_ptr m_SandSimulator; cFluidSimulator * m_WaterSimulator; cFluidSimulator * m_LavaSimulator; std::unique_ptr m_FireSimulator; cRedstoneSimulator * m_RedstoneSimulator; // Protect with chunk map CS std::vector m_Players; cWorldStorage m_Storage; unsigned int m_MaxPlayers; cChunkMap m_ChunkMap; bool m_bAnimals; std::set m_AllowedMobs; eWeather m_Weather; int m_WeatherInterval; int m_MaxSunnyTicks, m_MinSunnyTicks; int m_MaxRainTicks, m_MinRainTicks; int m_MaxThunderStormTicks, m_MinThunderStormTicks; int m_MaxCactusHeight; int m_MaxSugarcaneHeight; /* TODO: Enable when functionality exists again bool m_IsBeetrootsBonemealable; bool m_IsCactusBonemealable; bool m_IsCarrotsBonemealable; bool m_IsCropsBonemealable; bool m_IsGrassBonemealable; bool m_IsMelonStemBonemealable; bool m_IsMelonBonemealable; bool m_IsPotatoesBonemealable; bool m_IsPumpkinStemBonemealable; bool m_IsPumpkinBonemealable; bool m_IsSaplingBonemealable; bool m_IsSugarcaneBonemealable; bool m_IsBigFlowerBonemealable; bool m_IsTallGrassBonemealable; */ /** Whether command blocks are enabled or not */ bool m_bCommandBlocksEnabled; /** Whether prefixes such as [INFO] are prepended to SendMessageXXX() / BroadcastChatXXX() functions */ bool m_bUseChatPrefixes; /** The level of DoExplosionAt() projecting random affected blocks as FallingBlock entities See the eShrapnelLevel enumeration for details */ eShrapnelLevel m_TNTShrapnelLevel; /** The maximum view distance that a player can have in this world. */ int m_MaxViewDistance; /** Name of the nether world - where Nether portals should teleport. Only used when this world is an Overworld. */ AString m_LinkedNetherWorldName; /** Name of the End world - where End portals should teleport. Only used when this world is an Overworld. */ AString m_LinkedEndWorldName; /** The thread responsible for generating chunks. */ cChunkGeneratorThread m_Generator; cScoreboard m_Scoreboard; cMapManager m_MapManager; /** The callbacks that the ChunkGenerator uses to store new chunks and interface to plugins */ cChunkGeneratorCallbacks m_GeneratorCallbacks; cChunkSender m_ChunkSender; cLightingThread m_Lighting; cTickThread m_TickThread; /** Guards the m_Tasks */ cCriticalSection m_CSTasks; /** Tasks that have been queued onto the tick thread, possibly to be executed at target tick in the future; guarded by m_CSTasks */ std::vector>> m_Tasks; /** Guards m_EntitiesToAdd */ cCriticalSection m_CSEntitiesToAdd; /** List of entities that are scheduled for adding, waiting for the Tick thread to add them. */ std::vector> m_EntitiesToAdd; /** CS protecting m_SetChunkDataQueue. */ cCriticalSection m_CSSetChunkDataQueue; /** Queue for the chunk data to be set into m_ChunkMap by the tick thread. Protected by m_CSSetChunkDataQueue */ std::vector m_SetChunkDataQueue; void Tick(std::chrono::milliseconds a_Dt, std::chrono::milliseconds a_LastTickDurationMSec); /** Ticks all clients that are in this world. */ void TickClients(std::chrono::milliseconds a_Dt); /** Handles the weather in each tick */ void TickWeather(float a_Dt); /** Handles the mob spawning / moving / destroying each tick */ void TickMobs(std::chrono::milliseconds a_Dt); /** Sets the chunk data queued in the m_SetChunkDataQueue queue into their chunk. */ void TickQueuedChunkDataSets(); /** Adds the entities queued in the m_EntitiesToAdd queue into their chunk. If the entity was a player, he is also added to the m_Players list. */ void TickQueuedEntityAdditions(void); /** Executes all tasks queued onto the tick thread */ void TickQueuedTasks(void); /** Unloads all chunks immediately. */ void UnloadUnusedChunks(void); void UpdateSkyDarkness(void); /** Generates a random spawnpoint on solid land by walking chunks and finding their biomes */ void GenerateRandomSpawn(int a_MaxSpawnRadius); /** Can the specified coordinates be used as a spawn point? Returns true if spawn position is valid and sets a_Y to the valid spawn height */ bool CanSpawnAt(int a_X, int & a_Y, int a_Z); /** Check if player starting point is acceptable */ bool CheckPlayerSpawnPoint(int a_PosX, int a_PosY, int a_PosZ) { return CheckPlayerSpawnPoint({a_PosX, a_PosY, a_PosZ}); } bool CheckPlayerSpawnPoint(Vector3i a_Pos); /** Chooses a reasonable transition from the current weather to a new weather */ eWeather ChooseNewWeather(void); /** Creates a new fluid simulator, loads its settings from the inifile (a_FluidName section) */ cFluidSimulator * InitializeFluidSimulator(cIniFile & a_IniFile, const char * a_FluidName, BLOCKTYPE a_SimulateBlock, BLOCKTYPE a_StationaryBlock); /** Creates a new redstone simulator. */ cRedstoneSimulator * InitializeRedstoneSimulator(cIniFile & a_IniFile); /** Sets mob spawning values if nonexistant to their dimension specific defaults */ void InitializeAndLoadMobSpawningValues(cIniFile & a_IniFile); /** Checks if the sapling at the specified block coord is a part of a large-tree sapling (2x2). If so, adjusts the coords so that they point to the northwest (XM ZM) corner of the sapling area and returns true. Returns false if not a part of large-tree sapling. */ bool GetLargeTreeAdjustment(Vector3i & a_BlockPos, NIBBLETYPE a_SaplingMeta); }; // tolua_export ================================================ FILE: src/WorldStorage/CMakeLists.txt ================================================ target_sources( ${CMAKE_PROJECT_NAME} PRIVATE EnchantmentSerializer.cpp FastNBT.cpp FireworksSerializer.cpp MapSerializer.cpp NamespaceSerializer.cpp NBTChunkSerializer.cpp SchematicFileSerializer.cpp ScoreboardSerializer.cpp StatisticsSerializer.cpp WSSAnvil.cpp WorldStorage.cpp EnchantmentSerializer.h FastNBT.h FireworksSerializer.h MapSerializer.h NamespaceSerializer.h NBTChunkSerializer.h SchematicFileSerializer.h ScoreboardSerializer.h StatisticsSerializer.h WSSAnvil.h WorldStorage.h ) ================================================ FILE: src/WorldStorage/EnchantmentSerializer.cpp ================================================ #include "Globals.h" #include "EnchantmentSerializer.h" #include "FastNBT.h" #include "../Enchantments.h" void EnchantmentSerializer::WriteToNBTCompound(const cEnchantments & a_Enchantments, cFastNBTWriter & a_Writer, const AString & a_ListTagName) { // Write the enchantments into the specified NBT writer // begin with the LIST tag of the specified name ("ench" or "StoredEnchantments") a_Writer.BeginList(a_ListTagName, TAG_Compound); for (cEnchantments::cMap::const_iterator itr = a_Enchantments.m_Enchantments.begin(), end = a_Enchantments.m_Enchantments.end(); itr != end; ++itr) { a_Writer.BeginCompound(""); a_Writer.AddShort("id", static_cast(itr->first)); a_Writer.AddShort("lvl", static_cast(itr->second)); a_Writer.EndCompound(); } // for itr - m_Enchantments[] a_Writer.EndList(); } void EnchantmentSerializer::ParseFromNBT(cEnchantments & a_Enchantments, const cParsedNBT & a_NBT, int a_EnchListTagIdx) { // Read the enchantments from the specified NBT list tag (ench or StoredEnchantments) // Verify that the tag is a list: if (a_NBT.GetType(a_EnchListTagIdx) != TAG_List) { LOGWARNING("%s: Invalid EnchListTag type: exp %d, got %d. Enchantments not parsed", __FUNCTION__, TAG_List, a_NBT.GetType(a_EnchListTagIdx) ); ASSERT(!"Bad EnchListTag type"); return; } // Verify that the list is of Compounds: if (a_NBT.GetChildrenType(a_EnchListTagIdx) != TAG_Compound) { LOGWARNING("%s: Invalid NBT list children type: exp %d, got %d. Enchantments not parsed", __FUNCTION__, TAG_Compound, a_NBT.GetChildrenType(a_EnchListTagIdx) ); ASSERT(!"Bad EnchListTag children type"); return; } a_Enchantments.Clear(); // Iterate over all the compound children, parse an enchantment from each: for (int tag = a_NBT.GetFirstChild(a_EnchListTagIdx); tag >= 0; tag = a_NBT.GetNextSibling(tag)) { // tag is the compound inside the "ench" list tag ASSERT(a_NBT.GetType(tag) == TAG_Compound); // Search for the id and lvl tags' values: int id = -1, lvl = -1; for (int ch = a_NBT.GetFirstChild(tag); ch >= 0; ch = a_NBT.GetNextSibling(ch)) { if (a_NBT.GetType(ch) != TAG_Short) { continue; } if (a_NBT.GetName(ch) == "id") { id = a_NBT.GetShort(ch); } else if (a_NBT.GetName(ch) == "lvl") { lvl = a_NBT.GetShort(ch); } } // for ch - children of the compound tag if ((id == -1) || (lvl <= 0)) { // Failed to parse either the id or the lvl, skip this compound continue; } // Store the enchantment: a_Enchantments.m_Enchantments[id] = static_cast(lvl); } // for tag - children of the ench list tag } ================================================ FILE: src/WorldStorage/EnchantmentSerializer.h ================================================ #pragma once class cEnchantments; class cFastNBTWriter; class cParsedNBT; namespace EnchantmentSerializer { /** Writes the enchantments into the specified NBT writer; begins with the LIST tag of the specified name ("ench" or "StoredEnchantments") */ void WriteToNBTCompound(const cEnchantments & a_Enchantments, cFastNBTWriter & a_Writer, const AString & a_ListTagName); /** Reads the enchantments from the specified NBT list tag (ench or StoredEnchantments) */ void ParseFromNBT(cEnchantments & a_Enchantments, const cParsedNBT & a_NBT, int a_EnchListTagIdx); }; ================================================ FILE: src/WorldStorage/FastNBT.cpp ================================================ // FastNBT.cpp // Implements the fast NBT parser and writer #include "Globals.h" #include "FastNBT.h" // The number of NBT tags that are reserved when an NBT parsing is started. // You can override this by using a cmdline define #ifndef NBT_RESERVE_SIZE #define NBT_RESERVE_SIZE 200 #endif // NBT_RESERVE_SIZE #ifdef _MSC_VER // Dodge a C4127 (conditional expression is constant) for this specific macro usage #define PROPAGATE_ERROR(X) do { auto Err = (X); if (Err != eNBTParseError::npSuccess) return Err; } while ((false, false)) #else #define PROPAGATE_ERROR(X) do { auto Err = (X); if (Err != eNBTParseError::npSuccess) return Err; } while (false) #endif //////////////////////////////////////////////////////////////////////////////// // cNBTParseErrorCategory: namespace { class cNBTParseErrorCategory final : public std::error_category { cNBTParseErrorCategory() = default; public: /** Category name */ virtual const char * name() const noexcept override { return "NBT parse error"; } /** Maps a parse error code to an error message */ virtual AString message(int a_Condition) const override; /** Returns the canonical error category instance. */ static const cNBTParseErrorCategory & Get() noexcept { static cNBTParseErrorCategory Category; return Category; } }; AString cNBTParseErrorCategory::message(int a_Condition) const { switch (static_cast(a_Condition)) { case eNBTParseError::npSuccess: { return "Parsing succeded"; } case eNBTParseError::npNeedBytes: { return "Expected more data"; } case eNBTParseError::npNoTopLevelCompound: { return "No top level compound tag"; } case eNBTParseError::npStringMissingLength: { return "Expected a string length but had insufficient data"; } case eNBTParseError::npStringInvalidLength: { return "String length invalid"; } case eNBTParseError::npCompoundImbalancedTag: { return "Compound tag was unmatched at end of file"; } case eNBTParseError::npListMissingType: { return "Expected a list type but had insuffiecient data"; } case eNBTParseError::npListMissingLength: { return "Expected a list length but had insufficient data"; } case eNBTParseError::npListInvalidLength: { return "List length invalid"; } case eNBTParseError::npSimpleMissing: { return "Expected a numeric type but had insufficient data"; } case eNBTParseError::npArrayMissingLength: { return "Expected an array length but had insufficient data"; } case eNBTParseError::npArrayInvalidLength: { return "Array length invalid"; } case eNBTParseError::npUnknownTag: { return "Unknown tag"; } } UNREACHABLE("Unsupported nbt parse error"); } } // namespace (anonymous) std::error_code make_error_code(eNBTParseError a_Err) noexcept { return { static_cast(a_Err), cNBTParseErrorCategory::Get() }; } //////////////////////////////////////////////////////////////////////////////// // cParsedNBT: #define NEEDBYTES(N, ERR) \ do { \ if (m_Data.size() - m_Pos < static_cast(N)) \ { \ return ERR; \ } \ } while (false) cParsedNBT::cParsedNBT(const ContiguousByteBufferView a_Data) : m_Data(a_Data), m_Pos(0) { m_Error = Parse(); } eNBTParseError cParsedNBT::Parse(void) { if (m_Data.size() < 3) { // Data too short return eNBTParseError::npNeedBytes; } if (m_Data[0] != std::byte(TAG_Compound)) { // The top-level tag must be a Compound return eNBTParseError::npNoTopLevelCompound; } m_Tags.reserve(NBT_RESERVE_SIZE); m_Tags.emplace_back(TAG_Compound, -1); m_Pos = 1; PROPAGATE_ERROR(ReadString(m_Tags.back().m_NameStart, m_Tags.back().m_NameLength)); return ReadCompound(); } eNBTParseError cParsedNBT::ReadString(size_t & a_StringStart, size_t & a_StringLen) { NEEDBYTES(2, eNBTParseError::npStringMissingLength); a_StringStart = m_Pos + 2; a_StringLen = static_cast(NetworkBufToHost(m_Data.data() + m_Pos)); NEEDBYTES(2 + a_StringLen, eNBTParseError::npStringInvalidLength); m_Pos += 2 + a_StringLen; return eNBTParseError::npSuccess; } eNBTParseError cParsedNBT::ReadCompound(void) { ASSERT(m_Tags.size() > 0); // Reads the latest tag as a compound size_t ParentIdx = m_Tags.size() - 1; int PrevSibling = -1; for (;;) { NEEDBYTES(1, eNBTParseError::npCompoundImbalancedTag); const auto TagTypeNum = m_Data[m_Pos]; if ((TagTypeNum < std::byte(TAG_Min)) || (TagTypeNum > std::byte(TAG_Max))) { return eNBTParseError::npUnknownTag; } eTagType TagType = static_cast(TagTypeNum); m_Pos++; if (TagType == TAG_End) { break; } m_Tags.emplace_back(TagType, static_cast(ParentIdx), PrevSibling); if (PrevSibling >= 0) { m_Tags[static_cast(PrevSibling)].m_NextSibling = static_cast(m_Tags.size()) - 1; } else { m_Tags[ParentIdx].m_FirstChild = static_cast(m_Tags.size()) - 1; } PrevSibling = static_cast(m_Tags.size()) - 1; PROPAGATE_ERROR(ReadString(m_Tags.back().m_NameStart, m_Tags.back().m_NameLength)); PROPAGATE_ERROR(ReadTag()); } // while (true) m_Tags[ParentIdx].m_LastChild = PrevSibling; return eNBTParseError::npSuccess; } eNBTParseError cParsedNBT::ReadList(eTagType a_ChildrenType) { // Reads the latest tag as a list of items of type a_ChildrenType // Read the count: NEEDBYTES(4, eNBTParseError::npListMissingLength); int Count = NetworkBufToHost(m_Data.data() + m_Pos); m_Pos += 4; auto MinChildSize = GetMinTagSize(a_ChildrenType); if ((Count < 0) || (Count > static_cast((m_Data.size() - m_Pos) / MinChildSize))) { return eNBTParseError::npListInvalidLength; } // Read items: ASSERT(m_Tags.size() > 0); size_t ParentIdx = m_Tags.size() - 1; int PrevSibling = -1; for (int i = 0; i < Count; i++) { m_Tags.emplace_back(a_ChildrenType, static_cast(ParentIdx), PrevSibling); if (PrevSibling >= 0) { m_Tags[static_cast(PrevSibling)].m_NextSibling = static_cast(m_Tags.size()) - 1; } else { m_Tags[ParentIdx].m_FirstChild = static_cast(m_Tags.size()) - 1; } PrevSibling = static_cast(m_Tags.size()) - 1; PROPAGATE_ERROR(ReadTag()); } // for (i) m_Tags[ParentIdx].m_LastChild = PrevSibling; return eNBTParseError::npSuccess; } #define CASE_SIMPLE_TAG(TAGTYPE, LEN) \ case TAG_##TAGTYPE: \ { \ NEEDBYTES(LEN, eNBTParseError::npSimpleMissing); \ Tag.m_DataStart = m_Pos; \ Tag.m_DataLength = LEN; \ m_Pos += LEN; \ return eNBTParseError::npSuccess; \ } eNBTParseError cParsedNBT::ReadTag(void) { cFastNBTTag & Tag = m_Tags.back(); switch (Tag.m_Type) { CASE_SIMPLE_TAG(Byte, 1) CASE_SIMPLE_TAG(Short, 2) CASE_SIMPLE_TAG(Int, 4) CASE_SIMPLE_TAG(Long, 8) CASE_SIMPLE_TAG(Float, 4) CASE_SIMPLE_TAG(Double, 8) case TAG_String: { return ReadString(Tag.m_DataStart, Tag.m_DataLength); } case TAG_ByteArray: { NEEDBYTES(4, eNBTParseError::npArrayMissingLength); int len = NetworkBufToHost(m_Data.data() + m_Pos); m_Pos += 4; if (len < 0) { // Invalid length return eNBTParseError::npArrayInvalidLength; } NEEDBYTES(len, eNBTParseError::npArrayInvalidLength); Tag.m_DataLength = static_cast(len); Tag.m_DataStart = m_Pos; m_Pos += static_cast(len); return eNBTParseError::npSuccess; } case TAG_List: { NEEDBYTES(1, eNBTParseError::npListMissingType); eTagType ItemType = static_cast(m_Data[m_Pos]); m_Pos++; PROPAGATE_ERROR(ReadList(ItemType)); return eNBTParseError::npSuccess; } case TAG_Compound: { PROPAGATE_ERROR(ReadCompound()); return eNBTParseError::npSuccess; } case TAG_IntArray: { NEEDBYTES(4, eNBTParseError::npArrayMissingLength); int len = NetworkBufToHost(m_Data.data() + m_Pos); m_Pos += 4; if (len < 0) { // Invalid length return eNBTParseError::npArrayInvalidLength; } len *= 4; NEEDBYTES(len, eNBTParseError::npArrayInvalidLength); Tag.m_DataLength = static_cast(len); Tag.m_DataStart = m_Pos; m_Pos += static_cast(len); return eNBTParseError::npSuccess; } case TAG_Min: { return eNBTParseError::npUnknownTag; } } // switch (iType) UNREACHABLE("Unsupported nbt tag type"); } #undef CASE_SIMPLE_TAG int cParsedNBT::FindChildByName(int a_Tag, const char * a_Name, size_t a_NameLength) const { if (a_Tag < 0) { return -1; } if (m_Tags[static_cast(a_Tag)].m_Type != TAG_Compound) { return -1; } if (a_NameLength == 0) { a_NameLength = strlen(a_Name); } for (int Child = m_Tags[static_cast(a_Tag)].m_FirstChild; Child != -1; Child = m_Tags[static_cast(Child)].m_NextSibling) { if ( (m_Tags[static_cast(Child)].m_NameLength == a_NameLength) && (memcmp(m_Data.data() + m_Tags[static_cast(Child)].m_NameStart, a_Name, a_NameLength) == 0) ) { return Child; } } // for Child - children of a_Tag return -1; } int cParsedNBT::FindTagByPath(int a_Tag, const AString & a_Path) const { if (a_Tag < 0) { return -1; } size_t Begin = 0; size_t Length = a_Path.length(); int Tag = a_Tag; for (size_t i = 0; i < Length; i++) { if (a_Path[i] != '\\') { continue; } Tag = FindChildByName(Tag, a_Path.c_str() + Begin, i - Begin); if (Tag < 0) { return -1; } Begin = i + 1; } // for i - a_Path[] if (Begin < Length) { Tag = FindChildByName(Tag, a_Path.c_str() + Begin, Length - Begin); } return Tag; } size_t cParsedNBT::GetMinTagSize(eTagType a_TagType) { switch (a_TagType) { case TAG_End: return 1; case TAG_Byte: return 1; case TAG_Short: return 2; case TAG_Int: return 4; case TAG_Long: return 8; case TAG_Float: return 4; case TAG_Double: return 8; case TAG_String: return 2; // 2 bytes for the string length case TAG_ByteArray: return 4; // 4 bytes for the count case TAG_List: return 5; // 1 byte list type + 4 bytes count case TAG_Compound: return 1; // Single TAG_End byte case TAG_IntArray: return 4; // 4 bytes for the count } UNREACHABLE("Unsupported nbt tag type"); } //////////////////////////////////////////////////////////////////////////////// // cFastNBTWriter: cFastNBTWriter::cFastNBTWriter(const AString & a_RootTagName) : m_CurrentStack(0) { m_Stack[0].m_Type = TAG_Compound; m_Result.reserve(100 KiB); m_Result.push_back(std::byte(TAG_Compound)); WriteString(a_RootTagName); } void cFastNBTWriter::BeginCompound(const AString & a_Name) { if (m_CurrentStack >= MAX_STACK - 1) { ASSERT(!"Stack overflow"); return; } TagCommon(a_Name, TAG_Compound); ++m_CurrentStack; m_Stack[m_CurrentStack].m_Type = TAG_Compound; } void cFastNBTWriter::EndCompound(void) { ASSERT(m_CurrentStack > 0); ASSERT(IsStackTopCompound()); m_Result.push_back(std::byte(TAG_End)); --m_CurrentStack; } void cFastNBTWriter::BeginList(const AString & a_Name, eTagType a_ChildrenType) { if (m_CurrentStack >= MAX_STACK - 1) { ASSERT(!"Stack overflow"); return; } TagCommon(a_Name, TAG_List); m_Result.push_back(std::byte(a_ChildrenType)); m_Result.append(4, std::byte(0)); ++m_CurrentStack; m_Stack[m_CurrentStack].m_Type = TAG_List; m_Stack[m_CurrentStack].m_Pos = static_cast(m_Result.size()) - 4; m_Stack[m_CurrentStack].m_Count = 0; m_Stack[m_CurrentStack].m_ItemType = a_ChildrenType; } void cFastNBTWriter::EndList(void) { ASSERT(m_CurrentStack > 0); ASSERT(m_Stack[m_CurrentStack].m_Type == TAG_List); // Update the list count: auto Value = HostToNetwork(m_Stack[m_CurrentStack].m_Count); std::copy(Value.begin(), Value.end(), m_Result.data() + m_Stack[m_CurrentStack].m_Pos); --m_CurrentStack; } void cFastNBTWriter::AddByte(const AString & a_Name, unsigned char a_Value) { TagCommon(a_Name, TAG_Byte); m_Result.push_back(std::byte(a_Value)); } void cFastNBTWriter::AddShort(const AString & a_Name, Int16 a_Value) { TagCommon(a_Name, TAG_Short); auto Value = HostToNetwork(a_Value); m_Result.append(Value.begin(), Value.end()); } void cFastNBTWriter::AddInt(const AString & a_Name, Int32 a_Value) { TagCommon(a_Name, TAG_Int); auto Value = HostToNetwork(a_Value); m_Result.append(Value.begin(), Value.end()); } void cFastNBTWriter::AddLong(const AString & a_Name, Int64 a_Value) { TagCommon(a_Name, TAG_Long); auto Value = HostToNetwork(a_Value); m_Result.append(Value.begin(), Value.end()); } void cFastNBTWriter::AddFloat(const AString & a_Name, float a_Value) { TagCommon(a_Name, TAG_Float); auto Value = HostToNetwork(a_Value); m_Result.append(Value.begin(), Value.end()); } void cFastNBTWriter::AddDouble(const AString & a_Name, double a_Value) { TagCommon(a_Name, TAG_Double); auto Value = HostToNetwork(a_Value); m_Result.append(Value.begin(), Value.end()); } void cFastNBTWriter::AddString(const AString & a_Name, const std::string_view a_Value) { TagCommon(a_Name, TAG_String); auto Length = HostToNetwork(static_cast(a_Value.size())); m_Result.append(Length.begin(), Length.end()); m_Result.append({ reinterpret_cast(a_Value.data()), a_Value.size() }); } void cFastNBTWriter::AddByteArray(const AString & a_Name, const char * a_Value, size_t a_NumElements) { TagCommon(a_Name, TAG_ByteArray); auto Length = HostToNetwork(static_cast(a_NumElements)); m_Result.append(Length.begin(), Length.end()); m_Result.append(reinterpret_cast(a_Value), a_NumElements); } void cFastNBTWriter::AddByteArray(const AString & a_Name, size_t a_NumElements, unsigned char a_Value) { TagCommon(a_Name, TAG_ByteArray); auto Length = HostToNetwork(static_cast(a_NumElements)); m_Result.append(Length.begin(), Length.end()); m_Result.append(a_NumElements, std::byte(a_Value)); } void cFastNBTWriter::AddIntArray(const AString & a_Name, const Int32 * a_Value, size_t a_NumElements) { TagCommon(a_Name, TAG_IntArray); auto Length = HostToNetwork(static_cast(a_NumElements)); size_t cap = m_Result.capacity(); size_t size = m_Result.length(); if ((cap - size) < (4 + a_NumElements * 4)) { m_Result.reserve(size + 4 + (a_NumElements * 4)); } m_Result.append(Length.begin(), Length.end()); for (size_t i = 0; i < a_NumElements; i++) { auto Element = HostToNetwork(a_Value[i]); m_Result.append(Element.begin(), Element.end()); } } void cFastNBTWriter::Finish(void) { ASSERT(m_CurrentStack == 0); m_Result.push_back(std::byte(TAG_End)); } void cFastNBTWriter::WriteString(const std::string_view a_Data) { // TODO check size <= short max auto Length = HostToNetwork(static_cast(a_Data.size())); m_Result.append(Length.begin(), Length.end()); m_Result.append(reinterpret_cast(a_Data.data()), a_Data.size()); } ================================================ FILE: src/WorldStorage/FastNBT.h ================================================ // FastNBT.h // Interfaces to the fast NBT parser and writer /* The fast parser parses the data into a vector of cFastNBTTag structures. These structures describe the NBT tree, but themselves are allocated in a vector, thus minimizing reallocation. The structures have a minimal constructor, setting all member "pointers" to "invalid". The fast writer doesn't need a NBT tree structure built beforehand, it is commanded to open, append and close tags (just like XML); it keeps the internal tag stack and reports errors in usage. It directly outputs a string containing the serialized NBT data. */ #pragma once #include #include "../Endianness.h" enum eTagType { TAG_Min = 0, // The minimum value for a tag type TAG_End = 0, TAG_Byte = 1, TAG_Short = 2, TAG_Int = 3, TAG_Long = 4, TAG_Float = 5, TAG_Double = 6, TAG_ByteArray = 7, TAG_String = 8, TAG_List = 9, TAG_Compound = 10, TAG_IntArray = 11, TAG_Max = 11, // The maximum value for a tag type } ; /** This structure is used for all NBT tags. It contains indices to the parent array of tags, building the NBT tree this way. Also contains indices into the data stream being parsed, used for values; NO dynamically allocated memory is used! Structure (all with the tree structure it describes) supports moving in memory (std::vector reallocation) */ struct cFastNBTTag { public: eTagType m_Type; // The following members are indices into the data stream. m_DataLength == 0 if no data available // They must not be pointers, because the datastream may be copied into another AString object in the meantime. size_t m_NameStart; size_t m_NameLength; size_t m_DataStart; size_t m_DataLength; // The following members are indices into the array returned; -1 if not valid // They must not be pointers, because pointers would not survive std::vector reallocation int m_Parent; int m_PrevSibling; int m_NextSibling; int m_FirstChild; int m_LastChild; cFastNBTTag(eTagType a_Type, int a_Parent) : m_Type(a_Type), m_NameStart(0), m_NameLength(0), m_DataStart(0), m_DataLength(0), m_Parent(a_Parent), m_PrevSibling(-1), m_NextSibling(-1), m_FirstChild(-1), m_LastChild(-1) { } cFastNBTTag(eTagType a_Type, int a_Parent, int a_PrevSibling) : m_Type(a_Type), m_NameStart(0), m_NameLength(0), m_DataStart(0), m_DataLength(0), m_Parent(a_Parent), m_PrevSibling(a_PrevSibling), m_NextSibling(-1), m_FirstChild(-1), m_LastChild(-1) { } } ; enum class eNBTParseError { npSuccess = 0, npNeedBytes, npNoTopLevelCompound, npCompoundImbalancedTag, npStringMissingLength, npStringInvalidLength, npListMissingType, npListMissingLength, npListInvalidLength, npSimpleMissing, npArrayMissingLength, npArrayInvalidLength, npUnknownTag, }; // The following is required to make an error_code constructible from an eNBTParseError std::error_code make_error_code(eNBTParseError a_Err) noexcept; namespace std { template <> struct is_error_code_enum: public std::true_type { }; } /** Parses and contains the parsed data Also implements data accessor functions for tree traversal and value getters The data pointer passed in the constructor is assumed to be valid throughout the object's life. Care must be taken not to initialize from a temporary. The parser decomposes the input data into a tree of tags that is stored as an array of cFastNBTTag items, and accessing the tree is done by using the array indices for tags. Each tag stores the indices for its parent, first child, last child, prev sibling and next sibling, a value of -1 indicates that the indice is not valid. Each primitive tag also stores the length of the contained data, in bytes. */ class cParsedNBT { public: cParsedNBT(ContiguousByteBufferView a_Data); bool IsValid(void) const { return (m_Error == eNBTParseError::npSuccess); } /** Returns the error code for the parsing of the NBT data. */ std::error_code GetErrorCode() const { return m_Error; } /** Returns the position where an error occurred while parsing. */ size_t GetErrorPos() const { return m_Pos; } /** Returns the root tag of the hierarchy. */ int GetRoot(void) const { return 0; } /** Returns the first child of the specified tag, or -1 if none / not applicable. */ int GetFirstChild (int a_Tag) const { return m_Tags[static_cast(a_Tag)].m_FirstChild; } /** Returns the last child of the specified tag, or -1 if none / not applicable. */ int GetLastChild (int a_Tag) const { return m_Tags[static_cast(a_Tag)].m_LastChild; } /** Returns the next sibling of the specified tag, or -1 if none. */ int GetNextSibling(int a_Tag) const { return m_Tags[static_cast(a_Tag)].m_NextSibling; } /** Returns the previous sibling of the specified tag, or -1 if none. */ int GetPrevSibling(int a_Tag) const { return m_Tags[static_cast(a_Tag)].m_PrevSibling; } /** Returns the length of the tag's data, in bytes. Not valid for Compound or List tags! */ size_t GetDataLength(int a_Tag) const { ASSERT(m_Tags[static_cast(a_Tag)].m_Type != TAG_List); ASSERT(m_Tags[static_cast(a_Tag)].m_Type != TAG_Compound); return m_Tags[static_cast(a_Tag)].m_DataLength; } /** Returns the data stored in this tag. Not valid for Compound or List tags! */ const std::byte * GetData(int a_Tag) const { ASSERT(m_Tags[static_cast(a_Tag)].m_Type != TAG_List); ASSERT(m_Tags[static_cast(a_Tag)].m_Type != TAG_Compound); return m_Data.data() + m_Tags[static_cast(a_Tag)].m_DataStart; } /** Returns the direct child tag of the specified name, or -1 if no such tag. */ int FindChildByName(int a_Tag, const AString & a_Name) const { return FindChildByName(a_Tag, a_Name.c_str(), a_Name.length()); } /** Returns the direct child tag of the specified name, or -1 if no such tag. */ int FindChildByName(int a_Tag, const char * a_Name, size_t a_NameLength = 0) const; /** Returns the child tag of the specified path (Name1 / Name2 / Name3...), or -1 if no such tag. */ int FindTagByPath(int a_Tag, const AString & a_Path) const; eTagType GetType(int a_Tag) const { return m_Tags[static_cast(a_Tag)].m_Type; } /** Returns the children type for a List tag; undefined on other tags. If list empty, returns TAG_End. */ eTagType GetChildrenType(int a_Tag) const { ASSERT(m_Tags[static_cast(a_Tag)].m_Type == TAG_List); return (m_Tags[static_cast(a_Tag)].m_FirstChild < 0) ? TAG_End : m_Tags[static_cast(m_Tags[static_cast(a_Tag)].m_FirstChild)].m_Type; } /** Returns the value stored in a Byte tag. Not valid for any other tag type. */ inline unsigned char GetByte(int a_Tag) const { ASSERT(m_Tags[static_cast(a_Tag)].m_Type == TAG_Byte); return static_cast(m_Data[static_cast(m_Tags[static_cast(a_Tag)].m_DataStart)]); } /** Returns the value stored in a Short tag. Not valid for any other tag type. */ inline Int16 GetShort(int a_Tag) const { ASSERT(m_Tags[static_cast(a_Tag)].m_Type == TAG_Short); return NetworkBufToHost(GetData(a_Tag)); } /** Returns the value stored in an Int tag. Not valid for any other tag type. */ inline Int32 GetInt(int a_Tag) const { ASSERT(m_Tags[static_cast(a_Tag)].m_Type == TAG_Int); return NetworkBufToHost(GetData(a_Tag)); } /** Returns the value stored in a Long tag. Not valid for any other tag type. */ inline Int64 GetLong(int a_Tag) const { ASSERT(m_Tags[static_cast(a_Tag)].m_Type == TAG_Long); return NetworkBufToHost(GetData(a_Tag)); } /** Returns the value stored in a Float tag. Not valid for any other tag type. */ inline float GetFloat(int a_Tag) const { ASSERT(m_Tags[static_cast(a_Tag)].m_Type == TAG_Float); // Cause a compile-time error if sizeof(float) != 4 // If your platform produces a compiler error here, you'll need to add code that manually decodes 32-bit floats char Check1[5 - sizeof(float)]; // Fails if sizeof(float) > 4 char Check2[sizeof(float) - 3]; // Fails if sizeof(float) < 4 UNUSED_VAR(Check1); UNUSED_VAR(Check2); return NetworkBufToHost(GetData(a_Tag)); } /** Returns the value stored in a Double tag. Not valid for any other tag type. */ inline double GetDouble(int a_Tag) const { // Cause a compile-time error if sizeof(double) != 8 // If your platform produces a compiler error here, you'll need to add code that manually decodes 64-bit doubles char Check1[9 - sizeof(double)]; // Fails if sizeof(double) > 8 char Check2[sizeof(double) - 7]; // Fails if sizeof(double) < 8 UNUSED_VAR(Check1); UNUSED_VAR(Check2); ASSERT(m_Tags[static_cast(a_Tag)].m_Type == TAG_Double); return NetworkBufToHost(GetData(a_Tag)); } /** Returns the value stored in a String tag. Not valid for any other tag type. */ inline AString GetString(int a_Tag) const { return AString(GetStringView(a_Tag)); } /** Returns the value stored in a String tag. Not valid for any other tag type. */ inline std::string_view GetStringView(int a_Tag) const { ASSERT(m_Tags[static_cast(a_Tag)].m_Type == TAG_String); return { reinterpret_cast(GetData(a_Tag)), GetDataLength(a_Tag) }; } /** Returns the tag's name. For tags that are not named, returns an empty string. */ inline AString GetName(int a_Tag) const { AString res; res.assign(reinterpret_cast(m_Data.data()) + m_Tags[static_cast(a_Tag)].m_NameStart, static_cast(m_Tags[static_cast(a_Tag)].m_NameLength)); return res; } protected: ContiguousByteBufferView m_Data; std::vector m_Tags; eNBTParseError m_Error; // npSuccess if parsing succeeded // Used while parsing: size_t m_Pos; eNBTParseError Parse(void); eNBTParseError ReadString(size_t & a_StringStart, size_t & a_StringLen); // Reads a simple string (2 bytes length + data), sets the string descriptors eNBTParseError ReadCompound(void); // Reads the latest tag as a compound eNBTParseError ReadList(eTagType a_ChildrenType); // Reads the latest tag as a list of items of type a_ChildrenType eNBTParseError ReadTag(void); // Reads the latest tag, depending on its m_Type setting /** Returns the minimum size, in bytes, of the specified tag type. Used for sanity-checking. */ static size_t GetMinTagSize(eTagType a_TagType); } ; class cFastNBTWriter { public: cFastNBTWriter(const AString & a_RootTagName = ""); void BeginCompound(const AString & a_Name); void EndCompound(void); void BeginList(const AString & a_Name, eTagType a_ChildrenType); void EndList(void); void AddByte (const AString & a_Name, unsigned char a_Value); void AddShort (const AString & a_Name, Int16 a_Value); void AddInt (const AString & a_Name, Int32 a_Value); void AddLong (const AString & a_Name, Int64 a_Value); void AddFloat (const AString & a_Name, float a_Value); void AddDouble (const AString & a_Name, double a_Value); void AddString (const AString & a_Name, std::string_view a_Value); void AddByteArray(const AString & a_Name, const char * a_Value, size_t a_NumElements); void AddByteArray(const AString & a_Name, size_t a_NumElements, unsigned char a_Value); void AddIntArray (const AString & a_Name, const Int32 * a_Value, size_t a_NumElements); void AddByteArray(const AString & a_Name, const AString & a_Value) { AddByteArray(a_Name, a_Value.data(), a_Value.size()); } ContiguousByteBufferView GetResult(void) const { return m_Result; } void Finish(void); protected: struct sParent { int m_Type; // TAG_Compound or TAG_List int m_Pos; // for TAG_List, the position of the list count int m_Count; // for TAG_List, the element count eTagType m_ItemType; // for TAG_List, the element type } ; static const int MAX_STACK = 50; // Highly doubtful that an NBT would be constructed this many levels deep // These two fields emulate a stack. A raw array is used due to speed issues - no reallocations are allowed. sParent m_Stack[MAX_STACK]; int m_CurrentStack; ContiguousByteBuffer m_Result; bool IsStackTopCompound(void) const { return (m_Stack[m_CurrentStack].m_Type == TAG_Compound); } void WriteString(std::string_view a_Data); inline void TagCommon(const AString & a_Name, eTagType a_Type) { // If we're directly inside a list, check that the list is of the correct type: ASSERT((m_Stack[m_CurrentStack].m_Type != TAG_List) || (m_Stack[m_CurrentStack].m_ItemType == a_Type)); if (IsStackTopCompound()) { // Compound: add the type and name: m_Result.push_back(std::byte(a_Type)); WriteString(a_Name); } else { // List: add to the counter m_Stack[m_CurrentStack].m_Count++; } } } ; ================================================ FILE: src/WorldStorage/FireworksSerializer.cpp ================================================ #include "Globals.h" #include "FireworksSerializer.h" #include "../WorldStorage/FastNBT.h" #include "../BlockType.h" void cFireworkItem::WriteToNBTCompound(const cFireworkItem & a_FireworkItem, cFastNBTWriter & a_Writer, const ENUM_ITEM_TYPE a_Type) { switch (a_Type) { case E_ITEM_FIREWORK_ROCKET: { a_Writer.BeginCompound("Fireworks"); a_Writer.AddByte("Flight", static_cast(a_FireworkItem.m_FlightTimeInTicks / 20)); a_Writer.BeginList("Explosions", TAG_Compound); a_Writer.BeginCompound(""); a_Writer.AddByte("Flicker", a_FireworkItem.m_HasFlicker); a_Writer.AddByte("Trail", a_FireworkItem.m_HasTrail); a_Writer.AddByte("Type", a_FireworkItem.m_Type); if (!a_FireworkItem.m_Colours.empty()) { a_Writer.AddIntArray("Colors", a_FireworkItem.m_Colours.data(), a_FireworkItem.m_Colours.size()); } if (!a_FireworkItem.m_FadeColours.empty()) { a_Writer.AddIntArray("FadeColors", a_FireworkItem.m_FadeColours.data(), a_FireworkItem.m_FadeColours.size()); } a_Writer.EndCompound(); a_Writer.EndList(); a_Writer.EndCompound(); break; } case E_ITEM_FIREWORK_STAR: { a_Writer.BeginCompound("Explosion"); a_Writer.AddByte("Flicker", a_FireworkItem.m_HasFlicker); a_Writer.AddByte("Trail", a_FireworkItem.m_HasTrail); a_Writer.AddByte("Type", a_FireworkItem.m_Type); if (!a_FireworkItem.m_Colours.empty()) { a_Writer.AddIntArray("Colors", a_FireworkItem.m_Colours.data(), a_FireworkItem.m_Colours.size()); } if (!a_FireworkItem.m_FadeColours.empty()) { a_Writer.AddIntArray("FadeColors", a_FireworkItem.m_FadeColours.data(), a_FireworkItem.m_FadeColours.size()); } a_Writer.EndCompound(); break; } default: ASSERT(!"Unhandled firework item!"); break; } } void cFireworkItem::ParseFromNBT(cFireworkItem & a_FireworkItem, const cParsedNBT & a_NBT, int a_TagIdx, const ENUM_ITEM_TYPE a_Type) { if (a_TagIdx < 0) { return; } switch (a_Type) { case E_ITEM_FIREWORK_STAR: { for (int explosiontag = a_NBT.GetFirstChild(a_TagIdx); explosiontag >= 0; explosiontag = a_NBT.GetNextSibling(explosiontag)) { eTagType TagType = a_NBT.GetType(explosiontag); if (TagType == TAG_Byte) // Custon name tag { AString ExplosionName = a_NBT.GetName(explosiontag); if (ExplosionName == "Flicker") { a_FireworkItem.m_HasFlicker = (a_NBT.GetByte(explosiontag) == 1); } else if (ExplosionName == "Trail") { a_FireworkItem.m_HasTrail = (a_NBT.GetByte(explosiontag) == 1); } else if (ExplosionName == "Type") { a_FireworkItem.m_Type = a_NBT.GetByte(explosiontag); } } else if (TagType == TAG_IntArray) { AString ExplosionName = a_NBT.GetName(explosiontag); if (ExplosionName == "Colors") { // Divide by four as data length returned in bytes size_t DataLength = a_NBT.GetDataLength(explosiontag); // round to the next highest multiple of four DataLength -= DataLength % 4; if (DataLength == 0) { continue; } const auto * ColourData = (a_NBT.GetData(explosiontag)); for (size_t i = 0; i < DataLength; i += 4) { a_FireworkItem.m_Colours.push_back(NetworkBufToHost(ColourData + i)); } } else if (ExplosionName == "FadeColors") { size_t DataLength = a_NBT.GetDataLength(explosiontag) / 4; // round to the next highest multiple of four DataLength -= DataLength % 4; if (DataLength == 0) { continue; } const auto * FadeColourData = (a_NBT.GetData(explosiontag)); for (size_t i = 0; i < DataLength; i += 4) { a_FireworkItem.m_FadeColours.push_back(NetworkBufToHost(FadeColourData + i)); } } } } break; } case E_ITEM_FIREWORK_ROCKET: { for (int fireworkstag = a_NBT.GetFirstChild(a_TagIdx); fireworkstag >= 0; fireworkstag = a_NBT.GetNextSibling(fireworkstag)) { eTagType TagType = a_NBT.GetType(fireworkstag); if (TagType == TAG_Byte) // Custon name tag { if (a_NBT.GetName(fireworkstag) == "Flight") { a_FireworkItem.m_FlightTimeInTicks = a_NBT.GetByte(fireworkstag) * 20; } } else if ((TagType == TAG_List) && (a_NBT.GetName(fireworkstag) == "Explosions")) { int ExplosionsChild = a_NBT.GetFirstChild(fireworkstag); if ((a_NBT.GetType(ExplosionsChild) == TAG_Compound) && (a_NBT.GetName(ExplosionsChild).empty())) { ParseFromNBT(a_FireworkItem, a_NBT, ExplosionsChild, E_ITEM_FIREWORK_STAR); } } } break; } default: ASSERT(!"Unhandled firework item!"); break; } } AString cFireworkItem::ColoursToString(const cFireworkItem & a_FireworkItem) { AString Result; for (const auto col: a_FireworkItem.m_Colours) { Result.append(fmt::format(FMT_STRING("{};"), col)); } return Result; } void cFireworkItem::ColoursFromString(const AString & a_String, cFireworkItem & a_FireworkItem) { AStringVector Split = StringSplit(a_String, ";"); for (size_t itr = 0; itr < Split.size(); ++itr) { if (Split[itr].empty()) { continue; } a_FireworkItem.m_Colours.push_back(atoi(Split[itr].c_str())); } } AString cFireworkItem::FadeColoursToString(const cFireworkItem & a_FireworkItem) { AString Result; for (const auto col: a_FireworkItem.m_FadeColours) { Result.append(fmt::format(FMT_STRING("{};"), col)); } return Result; } void cFireworkItem::FadeColoursFromString(const AString & a_String, cFireworkItem & a_FireworkItem) { AStringVector Split = StringSplit(a_String, ";"); for (size_t itr = 0; itr < Split.size(); ++itr) { if (Split[itr].empty()) { continue; } a_FireworkItem.m_FadeColours.push_back(atoi(Split[itr].c_str())); } } int cFireworkItem::GetVanillaColourCodeFromDye(NIBBLETYPE a_DyeMeta) { /* Colours are supposed to be calculated via: R << 16 + G << 8 + B However, the RGB values fireworks use aren't the same as the ones for dyes (the ones listed in the MC Wiki) Therefore, here is a list of numbers gotten via the Protocol Proxy */ switch (a_DyeMeta) { case E_META_DYE_BLACK: return 0x1E1B1B; case E_META_DYE_RED: return 0xB3312C; case E_META_DYE_GREEN: return 0x3B511A; case E_META_DYE_BROWN: return 0x51301A; case E_META_DYE_BLUE: return 0x253192; case E_META_DYE_PURPLE: return 0x7B2FBE; case E_META_DYE_CYAN: return 0x287697; case E_META_DYE_LIGHTGRAY: return 0xABABAB; case E_META_DYE_GRAY: return 0x434343; case E_META_DYE_PINK: return 0xD88198; case E_META_DYE_LIGHTGREEN: return 0x41CD34; case E_META_DYE_YELLOW: return 0xDECF2A; case E_META_DYE_LIGHTBLUE: return 0x6689D3; case E_META_DYE_MAGENTA: return 0xC354CD; case E_META_DYE_ORANGE: return 0xEB8844; case E_META_DYE_WHITE: return 0xF0F0F0; default: ASSERT(!"Unhandled dye meta whilst trying to get colour code for fireworks!"); return 0; } } ================================================ FILE: src/WorldStorage/FireworksSerializer.h ================================================ // FireworksSerializer.h // Declares the cFireworkItem class representing a firework or firework star #pragma once #include "../BlockType.h" class cFastNBTWriter; class cParsedNBT; class cFireworkItem { public: cFireworkItem(void) : m_HasFlicker(false), m_HasTrail(false), m_Type(0), m_FlightTimeInTicks(0) { } inline void CopyFrom(const cFireworkItem & a_Item) { m_FlightTimeInTicks = a_Item.m_FlightTimeInTicks; m_HasFlicker = a_Item.m_HasFlicker; m_HasTrail = a_Item.m_HasTrail; m_Type = a_Item.m_Type; m_Colours = a_Item.m_Colours; m_FadeColours = a_Item.m_FadeColours; } inline void EmptyData(void) { m_FlightTimeInTicks = 0; m_HasFlicker = false; m_Type = 0; m_HasTrail = false; m_Colours.clear(); m_FadeColours.clear(); } inline bool IsEqualTo(const cFireworkItem & a_Item) const { return ( (m_FlightTimeInTicks == a_Item.m_FlightTimeInTicks) && (m_HasFlicker == a_Item.m_HasFlicker) && (m_HasTrail == a_Item.m_HasTrail) && (m_Type == a_Item.m_Type) && (m_Colours == a_Item.m_Colours) && (m_FadeColours == a_Item.m_FadeColours) ); } /** Writes firework NBT data to a Writer object */ static void WriteToNBTCompound(const cFireworkItem & a_FireworkItem, cFastNBTWriter & a_Writer, const ENUM_ITEM_TYPE a_Type); /** Reads NBT data from a NBT object and populates a FireworkItem with it */ static void ParseFromNBT(cFireworkItem & a_FireworkItem, const cParsedNBT & a_NBT, int a_TagIdx, const ENUM_ITEM_TYPE a_Type); /** Converts the firework's vector of colours into a string of values separated by a semicolon */ static AString ColoursToString(const cFireworkItem & a_FireworkItem); /** Parses a string containing encoded firework colours and populates a FireworkItem with it */ static void ColoursFromString(const AString & a_String, cFireworkItem & a_FireworkItem); /** Converts the firework's vector of fade colours into a string of values separated by a semicolon */ static AString FadeColoursToString(const cFireworkItem & a_FireworkItem); /** Parses a string containing encoded firework fade colours and populates a FireworkItem with it */ static void FadeColoursFromString(const AString & a_String, cFireworkItem & a_FireworkItem); /** Returns a colour code for fireworks used by the network code */ static int GetVanillaColourCodeFromDye(NIBBLETYPE a_DyeMeta); bool m_HasFlicker; bool m_HasTrail; NIBBLETYPE m_Type; short m_FlightTimeInTicks; std::vector m_Colours; std::vector m_FadeColours; }; ================================================ FILE: src/WorldStorage/MapSerializer.cpp ================================================ // MapSerializer.cpp #include "Globals.h" #include "MapSerializer.h" #include "OSSupport/GZipFile.h" #include "FastNBT.h" #include "../Map.h" #include "../World.h" cMapSerializer::cMapSerializer(const AString & a_WorldName, cMap * a_Map): m_Map(a_Map) { auto DataPath = fmt::format(FMT_STRING("{}{}data"), a_WorldName, cFile::PathSeparator()); m_Path = fmt::format(FMT_STRING("{}{}map_{}.dat"), DataPath, cFile::PathSeparator(), a_Map->GetID()); cFile::CreateFolder(DataPath); } bool cMapSerializer::Load() { const auto Data = GZipFile::ReadRestOfFile(m_Path); const cParsedNBT NBT(Data.GetView()); if (!NBT.IsValid()) { // NBT Parsing failed return false; } return LoadMapFromNBT(NBT); } bool cMapSerializer::Save(void) { cFastNBTWriter Writer; SaveMapToNBT(Writer); Writer.Finish(); #ifndef NDEBUG cParsedNBT TestParse(Writer.GetResult()); ASSERT(TestParse.IsValid()); #endif // !NDEBUG GZipFile::Write(m_Path, Writer.GetResult()); return true; } void cMapSerializer::SaveMapToNBT(cFastNBTWriter & a_Writer) { a_Writer.BeginCompound("data"); a_Writer.AddByte("scale", static_cast(m_Map->GetScale())); a_Writer.AddByte("dimension", static_cast(m_Map->GetDimension())); a_Writer.AddShort("width", static_cast(m_Map->GetWidth())); a_Writer.AddShort("height", static_cast(m_Map->GetHeight())); a_Writer.AddInt("xCenter", m_Map->GetCenterX()); a_Writer.AddInt("zCenter", m_Map->GetCenterZ()); const cMap::cColorList & Data = m_Map->GetData(); a_Writer.AddByteArray("colors", reinterpret_cast(Data.data()), Data.size()); a_Writer.EndCompound(); } bool cMapSerializer::LoadMapFromNBT(const cParsedNBT & a_NBT) { int Data = a_NBT.FindChildByName(0, "data"); if (Data < 0) { return false; } int CurrLine = a_NBT.FindChildByName(Data, "scale"); if ((CurrLine >= 0) && (a_NBT.GetType(CurrLine) == TAG_Byte)) { unsigned int Scale = static_cast(a_NBT.GetByte(CurrLine)); m_Map->SetScale(Scale); } CurrLine = a_NBT.FindChildByName(Data, "dimension"); if ((CurrLine >= 0) && (a_NBT.GetType(CurrLine) == TAG_Byte)) { eDimension Dimension = static_cast(a_NBT.GetByte(CurrLine)); if (Dimension != m_Map->m_World->GetDimension()) { // TODO 2014-03-20 xdot: We should store nether maps in nether worlds, e.t.c. return false; } } CurrLine = a_NBT.FindChildByName(Data, "width"); if ((CurrLine >= 0) && (a_NBT.GetType(CurrLine) == TAG_Short)) { unsigned int Width = static_cast(a_NBT.GetShort(CurrLine)); if (Width != 128) { return false; } m_Map->m_Width = Width; } CurrLine = a_NBT.FindChildByName(Data, "height"); if ((CurrLine >= 0) && (a_NBT.GetType(CurrLine) == TAG_Short)) { unsigned int Height = static_cast(a_NBT.GetShort(CurrLine)); if (Height >= cChunkDef::Height) { return false; } m_Map->m_Height = Height; } CurrLine = a_NBT.FindChildByName(Data, "xCenter"); if ((CurrLine >= 0) && (a_NBT.GetType(CurrLine) == TAG_Int)) { int CenterX = a_NBT.GetInt(CurrLine); m_Map->m_CenterX = CenterX; } CurrLine = a_NBT.FindChildByName(Data, "zCenter"); if ((CurrLine >= 0) && (a_NBT.GetType(CurrLine) == TAG_Int)) { int CenterZ = a_NBT.GetInt(CurrLine); m_Map->m_CenterZ = CenterZ; } unsigned int NumPixels = m_Map->GetNumPixels(); m_Map->m_Data.resize(NumPixels); CurrLine = a_NBT.FindChildByName(Data, "colors"); if ((CurrLine >= 0) && (a_NBT.GetType(CurrLine) == TAG_ByteArray)) { memcpy(m_Map->m_Data.data(), a_NBT.GetData(CurrLine), NumPixels); } return true; } cIDCountSerializer::cIDCountSerializer(const AString & a_WorldName) : m_MapCount(0) { auto DataPath = fmt::format(FMT_STRING("{}{}data"), a_WorldName, cFile::PathSeparator()); m_Path = fmt::format(FMT_STRING("{}{}idcounts.dat"), DataPath, cFile::PathSeparator()); cFile::CreateFolder(DataPath); } bool cIDCountSerializer::Load() { AString Data = cFile::ReadWholeFile(m_Path); if (Data.empty()) { return false; } // NOTE: idcounts.dat is not compressed (raw format) // Parse the NBT data: cParsedNBT NBT({ reinterpret_cast(Data.data()), Data.size() }); if (!NBT.IsValid()) { // NBT Parsing failed return false; } int CurrLine = NBT.FindChildByName(0, "map"); if (CurrLine >= 0) { m_MapCount = static_cast(NBT.GetShort(CurrLine) + 1); } else { m_MapCount = 0; } return true; } bool cIDCountSerializer::Save(void) { cFastNBTWriter Writer; if (m_MapCount > 0) { Writer.AddShort("map", static_cast(m_MapCount - 1)); } Writer.Finish(); #ifndef NDEBUG cParsedNBT TestParse(Writer.GetResult()); ASSERT(TestParse.IsValid()); #endif // !NDEBUG cFile File; if (!File.Open(m_Path, cFile::fmWrite)) { return false; } // NOTE: idcounts.dat is not compressed (raw format) File.Write(Writer.GetResult().data(), Writer.GetResult().size()); File.Close(); return true; } ================================================ FILE: src/WorldStorage/MapSerializer.h ================================================ // MapSerializer.h // Declares the cMapSerializer class that is used for saving maps into NBT format used by Anvil #pragma once // fwd: class cFastNBTWriter; class cParsedNBT; class cMap; /** Utility class used to serialize maps. */ class cMapSerializer { public: cMapSerializer(const AString & a_WorldName, cMap * a_Map); /** Try to load the map */ bool Load(void); /** Try to save the map */ bool Save(void); private: void SaveMapToNBT(cFastNBTWriter & a_Writer); bool LoadMapFromNBT(const cParsedNBT & a_NBT); cMap * m_Map; AString m_Path; } ; /** Utility class used to serialize item ID counts. In order to perform bounds checking (while loading), the last registered ID of each item is serialized to an NBT file. */ class cIDCountSerializer { public: cIDCountSerializer(const AString & a_WorldName); /** Try to load the ID counts */ bool Load(void); /** Try to save the ID counts */ bool Save(void); inline unsigned int GetMapCount(void) const { return m_MapCount; } inline void SetMapCount(unsigned int a_MapCount) { m_MapCount = a_MapCount; } private: AString m_Path; unsigned int m_MapCount; }; ================================================ FILE: src/WorldStorage/NBTChunkSerializer.cpp ================================================ // NBTChunkSerializer.cpp #include "Globals.h" #include "NBTChunkSerializer.h" #include "EnchantmentSerializer.h" #include "NamespaceSerializer.h" #include "../ChunkDataCallback.h" #include "../ItemGrid.h" #include "../StringCompression.h" #include "../UUID.h" #include "FastNBT.h" #include "../BlockEntities/BannerEntity.h" #include "../BlockEntities/BeaconEntity.h" #include "../BlockEntities/BedEntity.h" #include "../BlockEntities/BrewingstandEntity.h" #include "../BlockEntities/ChestEntity.h" #include "../BlockEntities/CommandBlockEntity.h" #include "../BlockEntities/DispenserEntity.h" #include "../BlockEntities/DropperEntity.h" #include "../BlockEntities/EnchantingTableEntity.h" #include "../BlockEntities/EnderChestEntity.h" #include "../BlockEntities/EndPortalEntity.h" #include "../BlockEntities/FurnaceEntity.h" #include "../BlockEntities/HopperEntity.h" #include "../BlockEntities/JukeboxEntity.h" #include "../BlockEntities/MobSpawnerEntity.h" #include "../BlockEntities/NoteEntity.h" #include "../BlockEntities/SignEntity.h" #include "../BlockEntities/MobHeadEntity.h" #include "../BlockEntities/FlowerPotEntity.h" #include "../Entities/Entity.h" #include "../Entities/EnderCrystal.h" #include "../Entities/FallingBlock.h" #include "../Entities/Boat.h" #include "../Entities/Minecart.h" #include "../Entities/Pickup.h" #include "../Entities/ArrowEntity.h" #include "../Entities/SplashPotionEntity.h" #include "../Entities/TNTEntity.h" #include "../Entities/ExpOrb.h" #include "../Entities/HangingEntity.h" #include "../Entities/ItemFrame.h" #include "../Entities/LeashKnot.h" #include "../Entities/Painting.h" #include "../Mobs/IncludeAllMonsters.h" /** Collects and stores the chunk data via the cChunkDataCallback interface */ class SerializerCollector final : public cChunkDataCopyCollector { public: // The data collected from the chunk: UInt8 Biomes[cChunkDef::Width * cChunkDef::Width]; int Heights[cChunkDef::Width * cChunkDef::Width]; /** True if a tag has been opened in the callbacks and not yet closed. */ bool mIsTagOpen; /** True if any Entity has already been received and processed. */ bool mHasHadEntity; /** True if any BlockEntity has already been received and processed. */ bool mHasHadBlockEntity; /** True if the chunk lighting is valid. */ bool mIsLightValid; /** The NBT writer used to store the data. */ cFastNBTWriter & mWriter; SerializerCollector(cFastNBTWriter & aWriter): mIsTagOpen(false), mHasHadEntity(false), mHasHadBlockEntity(false), mIsLightValid(false), mWriter(aWriter) { } virtual void LightIsValid(bool a_IsLightValid) override { mIsLightValid = a_IsLightValid; } virtual void HeightMap(const cChunkDef::HeightMap & a_HeightMap) override { for (int RelZ = 0; RelZ < cChunkDef::Width; RelZ++) { for (int RelX = 0; RelX < cChunkDef::Width; RelX++) { Heights[RelX + RelZ * cChunkDef::Width] = cChunkDef::GetHeight(a_HeightMap, RelX, RelZ); } } } virtual void BiomeMap(const cChunkDef::BiomeMap & a_BiomeMap) override { for (size_t i = 0; i < ARRAYCOUNT(Biomes); i++) { if (a_BiomeMap[i] < 255) { // Normal MC biome, copy as-is: Biomes[i] = static_cast(a_BiomeMap[i]); } else { // TODO: MCS-specific biome, need to map to some basic MC biome: ASSERT(!"Unimplemented MCS-specific biome"); return; } } // for i - mBiomeMap[] } virtual void Entity(cEntity * a_Entity) override { // Add entity into NBT: if (mIsTagOpen) { if (!mHasHadEntity) { mWriter.EndList(); mWriter.BeginList("Entities", TAG_Compound); } } else { mWriter.BeginList("Entities", TAG_Compound); } mIsTagOpen = true; mHasHadEntity = true; switch (a_Entity->GetEntityType()) { case cEntity::etBoat: AddBoatEntity (static_cast (a_Entity)); break; case cEntity::etEnderCrystal: AddEnderCrystalEntity(static_cast (a_Entity)); break; case cEntity::etFallingBlock: AddFallingBlockEntity(static_cast (a_Entity)); break; case cEntity::etMinecart: AddMinecartEntity (static_cast (a_Entity)); break; case cEntity::etMonster: AddMonsterEntity (static_cast (a_Entity)); break; case cEntity::etPickup: AddPickupEntity (static_cast (a_Entity)); break; case cEntity::etProjectile: AddProjectileEntity (static_cast(a_Entity)); break; case cEntity::etTNT: AddTNTEntity (static_cast (a_Entity)); break; case cEntity::etExpOrb: AddExpOrbEntity (static_cast (a_Entity)); break; case cEntity::etItemFrame: AddItemFrameEntity (static_cast (a_Entity)); break; case cEntity::etLeashKnot: AddLeashKnotEntity (static_cast (a_Entity)); break; case cEntity::etPainting: AddPaintingEntity (static_cast (a_Entity)); break; case cEntity::etPlayer: return; // Players aren't saved into the world case cEntity::etFloater: return; // Floaters aren't saved either default: { ASSERT(!"Unhandled entity type is being saved"); break; } } } virtual void BlockEntity(cBlockEntity * a_Entity) override { if (mIsTagOpen) { if (!mHasHadBlockEntity) { mWriter.EndList(); mWriter.BeginList("TileEntities", TAG_Compound); } } else { mWriter.BeginList("TileEntities", TAG_Compound); } mIsTagOpen = true; // Add tile-entity into NBT: switch (a_Entity->GetBlockType()) { // Banners: case E_BLOCK_STANDING_BANNER: case E_BLOCK_WALL_BANNER: AddBannerEntity (static_cast (a_Entity)); break; // Others: case E_BLOCK_BEACON: AddBeaconEntity (static_cast (a_Entity)); break; case E_BLOCK_BED: AddBedEntity (static_cast (a_Entity)); break; case E_BLOCK_BREWING_STAND: AddBrewingstandEntity (static_cast (a_Entity)); break; case E_BLOCK_CHEST: AddChestEntity (static_cast (a_Entity), a_Entity->GetBlockType()); break; case E_BLOCK_COMMAND_BLOCK: AddCommandBlockEntity (static_cast (a_Entity)); break; case E_BLOCK_DISPENSER: AddDispenserEntity (static_cast (a_Entity)); break; case E_BLOCK_DROPPER: AddDropperEntity (static_cast (a_Entity)); break; case E_BLOCK_ENCHANTMENT_TABLE: AddEnchantingTableEntity(static_cast(a_Entity)); break; case E_BLOCK_ENDER_CHEST: AddEnderchestEntity (static_cast (a_Entity)); break; case E_BLOCK_END_PORTAL: AddEndPortalEntity (static_cast (a_Entity)); break; case E_BLOCK_FLOWER_POT: AddFlowerPotEntity (static_cast (a_Entity)); break; case E_BLOCK_FURNACE: AddFurnaceEntity (static_cast (a_Entity)); break; case E_BLOCK_HEAD: AddMobHeadEntity (static_cast (a_Entity)); break; case E_BLOCK_HOPPER: AddHopperEntity (static_cast (a_Entity)); break; case E_BLOCK_JUKEBOX: AddJukeboxEntity (static_cast (a_Entity)); break; case E_BLOCK_LIT_FURNACE: AddFurnaceEntity (static_cast (a_Entity)); break; case E_BLOCK_MOB_SPAWNER: AddMobSpawnerEntity (static_cast (a_Entity)); break; case E_BLOCK_NOTE_BLOCK: AddNoteEntity (static_cast (a_Entity)); break; case E_BLOCK_SIGN_POST: AddSignEntity (static_cast (a_Entity)); break; case E_BLOCK_TRAPPED_CHEST: AddChestEntity (static_cast (a_Entity), a_Entity->GetBlockType()); break; case E_BLOCK_WALLSIGN: AddSignEntity (static_cast (a_Entity)); break; default: { ASSERT(!"Unhandled block entity saved into Anvil"); } } mHasHadBlockEntity = true; } void Finish(void) { if (mIsTagOpen) { mWriter.EndList(); } // Check if "Entity" and "TileEntities" lists exists. MCEdit requires this. if (!mHasHadEntity) { mWriter.BeginList("Entities", TAG_Compound); mWriter.EndList(); } if (!mHasHadBlockEntity) { mWriter.BeginList("TileEntities", TAG_Compound); mWriter.EndList(); } } /** Writes an item into the writer. If aSlot >= 0, adds the Slot tag. The compound is named as requested (empty name by default). */ void AddItem(const cItem & a_Item, int a_Slot, const AString & a_CompoundName = AString()) { mWriter.BeginCompound(a_CompoundName); mWriter.AddShort("id", static_cast(a_Item.m_ItemType)); mWriter.AddShort("Damage", static_cast((a_Item.m_ItemDamage))); mWriter.AddByte ("Count", static_cast(a_Item.m_ItemCount)); if (a_Slot >= 0) { mWriter.AddByte ("Slot", static_cast(a_Slot)); } // Write the tag compound (for enchantment, firework, custom name and repair cost): if ( (!a_Item.m_Enchantments.IsEmpty()) || ((a_Item.m_ItemType == E_ITEM_FIREWORK_ROCKET) || (a_Item.m_ItemType == E_ITEM_FIREWORK_STAR)) || (a_Item.m_RepairCost > 0) || (a_Item.m_CustomName != "") || (!a_Item.m_LoreTable.empty()) ) { mWriter.BeginCompound("tag"); if (a_Item.m_RepairCost > 0) { mWriter.AddInt("RepairCost", a_Item.m_RepairCost); } if ((a_Item.m_CustomName != "") || (!a_Item.m_LoreTable.empty())) { mWriter.BeginCompound("display"); if (a_Item.m_CustomName != "") { mWriter.AddString("Name", a_Item.m_CustomName); } if (!a_Item.m_LoreTable.empty()) { mWriter.BeginList("Lore", TAG_String); for (const auto & Line : a_Item.m_LoreTable) { mWriter.AddString("", Line); } mWriter.EndList(); } mWriter.EndCompound(); } if ((a_Item.m_ItemType == E_ITEM_FIREWORK_ROCKET) || (a_Item.m_ItemType == E_ITEM_FIREWORK_STAR)) { cFireworkItem::WriteToNBTCompound(a_Item.m_FireworkItem, mWriter, static_cast(a_Item.m_ItemType)); } if (!a_Item.m_Enchantments.IsEmpty()) { const char * TagName = (a_Item.m_ItemType == E_ITEM_BOOK) ? "StoredEnchantments" : "ench"; EnchantmentSerializer::WriteToNBTCompound(a_Item.m_Enchantments, mWriter, TagName); } mWriter.EndCompound(); } mWriter.EndCompound(); } /** Writes an item grid into the writer. Begins the stored slot numbers with a_BeginSlotNum. Note that it doesn't begin nor end the list tag, so that multiple grids may be concatenated together using this function. */ void AddItemGrid(const cItemGrid & a_Grid, int a_BeginSlotNum = 0) { int NumSlots = a_Grid.GetNumSlots(); for (int i = 0; i < NumSlots; i++) { const cItem & Item = a_Grid.GetSlot(i); if (Item.IsEmpty()) { continue; } AddItem(Item, i + a_BeginSlotNum); } // for i - slots[] } void AddBasicTileEntity(cBlockEntity * a_Entity, const char * a_EntityTypeID) { mWriter.AddInt ("x", a_Entity->GetPosX()); mWriter.AddInt ("y", a_Entity->GetPosY()); mWriter.AddInt ("z", a_Entity->GetPosZ()); mWriter.AddString("id", a_EntityTypeID); } void AddBannerEntity(cBannerEntity * a_Entity) { mWriter.BeginCompound(""); AddBasicTileEntity(a_Entity,"Banner"); mWriter.AddInt("Base", static_cast(a_Entity->GetBaseColor())); if (!a_Entity->GetCustomName().empty()) { mWriter.AddString("CustomName", a_Entity->GetCustomName()); } mWriter.EndCompound(); } void AddBeaconEntity(cBeaconEntity * a_Entity) { mWriter.BeginCompound(""); AddBasicTileEntity(a_Entity, "Beacon"); mWriter.AddInt("Levels", a_Entity->GetBeaconLevel()); mWriter.AddInt("Primary", static_cast(a_Entity->GetPrimaryEffect())); mWriter.AddInt("Secondary", static_cast(a_Entity->GetSecondaryEffect())); mWriter.BeginList("Items", TAG_Compound); AddItemGrid(a_Entity->GetContents()); mWriter.EndList(); mWriter.EndCompound(); } void AddBedEntity(cBedEntity * a_Entity) { mWriter.BeginCompound(""); AddBasicTileEntity(a_Entity, "Bed"); mWriter.AddInt("color", a_Entity->GetColor()); mWriter.EndCompound(); } void AddBrewingstandEntity(cBrewingstandEntity * a_Brewingstand) { mWriter.BeginCompound(""); AddBasicTileEntity(a_Brewingstand, "Brewingstand"); mWriter.BeginList("Items", TAG_Compound); AddItemGrid(a_Brewingstand->GetContents()); mWriter.EndList(); mWriter.AddShort("BrewTime", a_Brewingstand->GetTimeBrewed()); mWriter.AddShort("Fuel", a_Brewingstand->GetRemainingFuel()); mWriter.EndCompound(); } void AddChestEntity(cChestEntity * a_Entity, BLOCKTYPE a_ChestType) { mWriter.BeginCompound(""); AddBasicTileEntity(a_Entity, "Chest"); mWriter.BeginList("Items", TAG_Compound); AddItemGrid(a_Entity->GetContents()); mWriter.EndList(); mWriter.EndCompound(); } void AddDispenserEntity(cDispenserEntity * a_Entity) { mWriter.BeginCompound(""); AddBasicTileEntity(a_Entity, "Trap"); mWriter.BeginList("Items", TAG_Compound); AddItemGrid(a_Entity->GetContents()); mWriter.EndList(); mWriter.EndCompound(); } void AddDropperEntity(cDropperEntity * a_Entity) { mWriter.BeginCompound(""); AddBasicTileEntity(a_Entity, "Dropper"); mWriter.BeginList("Items", TAG_Compound); AddItemGrid(a_Entity->GetContents()); mWriter.EndList(); mWriter.EndCompound(); } void AddEnchantingTableEntity(cEnchantingTableEntity * a_Entity) { mWriter.BeginCompound(""); AddBasicTileEntity(a_Entity, "EnchantingTable"); if (!a_Entity->GetCustomName().empty()) { mWriter.AddString("CustomName", a_Entity->GetCustomName()); } mWriter.EndCompound(); } void AddEnderchestEntity(cEnderChestEntity * a_Entity) { mWriter.BeginCompound(""); AddBasicTileEntity(a_Entity, "EnderChest"); mWriter.EndCompound(); } void AddEndPortalEntity(cEndPortalEntity * a_Entity) { mWriter.BeginCompound(""); AddBasicTileEntity(a_Entity, "EndPortal"); mWriter.EndCompound(); } void AddFurnaceEntity(cFurnaceEntity * a_Furnace) { mWriter.BeginCompound(""); AddBasicTileEntity(a_Furnace, "Furnace"); mWriter.BeginList("Items", TAG_Compound); AddItemGrid(a_Furnace->GetContents()); mWriter.EndList(); mWriter.AddShort("BurnTime", static_cast(a_Furnace->GetFuelBurnTimeLeft())); mWriter.AddShort("CookTime", static_cast(a_Furnace->GetTimeCooked())); mWriter.EndCompound(); } void AddHopperEntity(cHopperEntity * a_Entity) { mWriter.BeginCompound(""); AddBasicTileEntity(a_Entity, "Hopper"); mWriter.BeginList("Items", TAG_Compound); AddItemGrid(a_Entity->GetContents()); mWriter.EndList(); mWriter.EndCompound(); } void AddJukeboxEntity(cJukeboxEntity * a_Jukebox) { mWriter.BeginCompound(""); AddBasicTileEntity(a_Jukebox, "RecordPlayer"); mWriter.AddInt("Record", a_Jukebox->GetRecord()); mWriter.EndCompound(); } void AddMobSpawnerEntity(cMobSpawnerEntity * a_MobSpawner) { mWriter.BeginCompound(""); AddBasicTileEntity(a_MobSpawner, "MobSpawner"); mWriter.AddString("EntityId", NamespaceSerializer::From(a_MobSpawner->GetEntity())); mWriter.AddShort("SpawnCount", a_MobSpawner->GetSpawnCount()); mWriter.AddShort("SpawnRange", a_MobSpawner->GetSpawnRange()); mWriter.AddShort("Delay", a_MobSpawner->GetSpawnDelay()); mWriter.AddShort("MinSpawnDelay", a_MobSpawner->GetMinSpawnDelay()); mWriter.AddShort("MaxSpawnDelay", a_MobSpawner->GetMaxSpawnDelay()); mWriter.AddShort("MaxNearbyEntities", a_MobSpawner->GetMaxNearbyEntities()); mWriter.AddShort("RequiredPlayerRange", a_MobSpawner->GetRequiredPlayerRange()); mWriter.EndCompound(); } void AddNoteEntity(cNoteEntity * a_Note) { mWriter.BeginCompound(""); AddBasicTileEntity(a_Note, "Music"); mWriter.AddByte("note", static_cast(a_Note->GetNote())); mWriter.EndCompound(); } void AddCommandBlockEntity(cCommandBlockEntity * a_CmdBlock) { mWriter.BeginCompound(""); AddBasicTileEntity(a_CmdBlock, "Control"); mWriter.AddString("Command", a_CmdBlock->GetCommand()); mWriter.AddInt ("SuccessCount", a_CmdBlock->GetResult()); mWriter.AddString("LastOutput", a_CmdBlock->GetLastOutput()); mWriter.AddByte ("TrackOutput", 1); // TODO 2014-01-18 xdot: Figure out what TrackOutput is and save it. mWriter.EndCompound(); } void AddSignEntity(cSignEntity * a_Sign) { mWriter.BeginCompound(""); AddBasicTileEntity(a_Sign, "Sign"); mWriter.AddString("Text1", a_Sign->GetLine(0)); mWriter.AddString("Text2", a_Sign->GetLine(1)); mWriter.AddString("Text3", a_Sign->GetLine(2)); mWriter.AddString("Text4", a_Sign->GetLine(3)); mWriter.EndCompound(); } void AddMobHeadEntity(cMobHeadEntity * a_MobHead) { mWriter.BeginCompound(""); AddBasicTileEntity(a_MobHead, "Skull"); mWriter.AddByte ("SkullType", a_MobHead->GetType() & 0xFF); mWriter.AddByte ("Rot", a_MobHead->GetRotation() & 0xFF); // The new Block Entity format for a Mob Head. See: https://minecraft.wiki/w/Head#Block_entity mWriter.BeginCompound("Owner"); mWriter.AddString("Id", a_MobHead->GetOwnerUUID().ToShortString()); mWriter.AddString("Name", a_MobHead->GetOwnerName()); mWriter.BeginCompound("Properties"); mWriter.BeginList("textures", TAG_Compound); mWriter.BeginCompound(""); mWriter.AddString("Signature", a_MobHead->GetOwnerTextureSignature()); mWriter.AddString("Value", a_MobHead->GetOwnerTexture()); mWriter.EndCompound(); mWriter.EndList(); mWriter.EndCompound(); mWriter.EndCompound(); mWriter.EndCompound(); } void AddFlowerPotEntity(cFlowerPotEntity * a_FlowerPot) { mWriter.BeginCompound(""); AddBasicTileEntity(a_FlowerPot, "FlowerPot"); mWriter.AddInt ("Item", static_cast(a_FlowerPot->GetItem().m_ItemType)); mWriter.AddInt ("Data", static_cast(a_FlowerPot->GetItem().m_ItemDamage)); mWriter.EndCompound(); } void AddBasicEntity(cEntity * a_Entity, const std::string_view a_ClassName) { mWriter.AddString("id", a_ClassName); mWriter.BeginList("Pos", TAG_Double); mWriter.AddDouble("", a_Entity->GetPosX()); mWriter.AddDouble("", a_Entity->GetPosY()); mWriter.AddDouble("", a_Entity->GetPosZ()); mWriter.EndList(); mWriter.BeginList("Motion", TAG_Double); mWriter.AddDouble("", a_Entity->GetSpeedX()); mWriter.AddDouble("", a_Entity->GetSpeedY()); mWriter.AddDouble("", a_Entity->GetSpeedZ()); mWriter.EndList(); mWriter.BeginList("Rotation", TAG_Double); mWriter.AddDouble("", a_Entity->GetYaw()); mWriter.AddDouble("", a_Entity->GetPitch()); mWriter.EndList(); mWriter.AddFloat("Health", a_Entity->GetHealth()); } void AddBoatEntity(cBoat * a_Boat) { mWriter.BeginCompound(""); AddBasicEntity(a_Boat, "Boat"); mWriter.AddString("Type", cBoat::MaterialToString(a_Boat->GetMaterial())); mWriter.EndCompound(); } void AddEnderCrystalEntity(cEnderCrystal * a_EnderCrystal) { mWriter.BeginCompound(""); AddBasicEntity(a_EnderCrystal, "EnderCrystal"); mWriter.AddByte("ShowBottom", a_EnderCrystal->ShowsBottom() ? 1 : 0); if (a_EnderCrystal->DisplaysBeam()) { mWriter.BeginCompound("BeamTarget"); const auto & BeamTarget = a_EnderCrystal->GetBeamTarget(); mWriter.AddInt("X", BeamTarget.x); mWriter.AddInt("Y", BeamTarget.y); mWriter.AddInt("Z", BeamTarget.z); mWriter.EndCompound(); } mWriter.EndCompound(); } void AddFallingBlockEntity(cFallingBlock * a_FallingBlock) { mWriter.BeginCompound(""); AddBasicEntity(a_FallingBlock, "FallingSand"); mWriter.AddInt("TileID", a_FallingBlock->GetBlockType()); mWriter.AddByte("Data", a_FallingBlock->GetBlockMeta()); mWriter.AddByte("Time", 1); // Unused in Cuberite, Vanilla said to need nonzero mWriter.AddByte("DropItem", 1); mWriter.AddByte("HurtEntities", a_FallingBlock->GetBlockType() == E_BLOCK_ANVIL); mWriter.EndCompound(); } void AddMinecartEntity(cMinecart * a_Minecart) { mWriter.BeginCompound(""); switch (a_Minecart->GetPayload()) { case cMinecart::mpChest: { AddBasicEntity(a_Minecart, "MinecartChest"); // Add chest contents into the Items tag: AddMinecartChestContents(static_cast(a_Minecart)); break; } case cMinecart::mpFurnace: { AddBasicEntity(a_Minecart, "MinecartFurnace"); // TODO: Add "Push" and "Fuel" tags break; } case cMinecart::mpHopper: { AddBasicEntity(a_Minecart, "MinecartHopper"); // TODO: Add hopper contents? break; } case cMinecart::mpTNT: { AddBasicEntity(a_Minecart, "MinecartTNT"); break; } case cMinecart::mpNone: { AddBasicEntity(a_Minecart, "MinecartRideable"); break; } } // switch (Payload) mWriter.EndCompound(); } void AddMonsterEntity(cMonster * a_Monster) { mWriter.BeginCompound(""); AddBasicEntity(a_Monster, NamespaceSerializer::From(a_Monster->GetMobType())); mWriter.BeginList("DropChances", TAG_Float); mWriter.AddFloat("", a_Monster->GetDropChanceWeapon()); mWriter.AddFloat("", a_Monster->GetDropChanceHelmet()); mWriter.AddFloat("", a_Monster->GetDropChanceChestplate()); mWriter.AddFloat("", a_Monster->GetDropChanceLeggings()); mWriter.AddFloat("", a_Monster->GetDropChanceBoots()); mWriter.EndList(); mWriter.AddByte("CanPickUpLoot", (a_Monster->CanPickUpLoot())? 1 : 0); mWriter.AddString("CustomName", a_Monster->GetCustomName()); mWriter.AddByte("CustomNameVisible", static_cast(a_Monster->IsCustomNameAlwaysVisible())); // Mob was leashed if (a_Monster->IsLeashed() || (a_Monster->GetLeashToPos() != nullptr)) { mWriter.AddByte("Leashed", 1); const Vector3d * LeashedToPos = nullptr; if (a_Monster->GetLeashToPos() != nullptr) { LeashedToPos = a_Monster->GetLeashToPos(); } else if (a_Monster->GetLeashedTo()->IsLeashKnot()) { LeashedToPos = & a_Monster->GetLeashedTo()->GetPosition(); } if (LeashedToPos != nullptr) { mWriter.BeginCompound("Leash"); mWriter.AddDouble("X", LeashedToPos->x); mWriter.AddDouble("Y", LeashedToPos->y); mWriter.AddDouble("Z", LeashedToPos->z); mWriter.EndCompound(); } } switch (a_Monster->GetMobType()) { case mtBat: { mWriter.AddByte("BatFlags", static_cast(a_Monster)->IsHanging()); break; } case mtCreeper: { const cCreeper *Creeper = static_cast(a_Monster); mWriter.AddByte("powered", Creeper->IsCharged()); mWriter.AddByte("ignited", Creeper->IsBlowing()); break; } case mtEnderman: { const cEnderman *Enderman = static_cast(a_Monster); mWriter.AddShort("carried", static_cast(Enderman->GetCarriedBlock())); mWriter.AddShort("carriedData", static_cast(Enderman->GetCarriedMeta())); break; } case mtHorse: { const cHorse *Horse = static_cast(a_Monster); mWriter.AddByte("ChestedHorse", Horse->IsChested()? 1 : 0); mWriter.AddByte("EatingHaystack", Horse->IsEating()? 1 : 0); mWriter.AddByte("Tame", Horse->IsTame()? 1: 0); mWriter.AddInt ("Type", Horse->GetHorseType()); mWriter.AddInt ("Color", Horse->GetHorseColor()); mWriter.AddInt ("Style", Horse->GetHorseStyle()); mWriter.AddInt ("ArmorType", Horse->GetHorseArmour()); mWriter.AddByte("Saddle", Horse->IsSaddled()? 1 : 0); mWriter.AddInt ("Age", Horse->GetAge()); break; } case mtMagmaCube: { mWriter.AddInt("Size", static_cast(a_Monster)->GetSize()); break; } case mtOcelot: { const auto *Ocelot = static_cast(a_Monster); if (!Ocelot->GetOwnerName().empty()) { mWriter.AddString("Owner", Ocelot->GetOwnerName()); } if (!Ocelot->GetOwnerUUID().IsNil()) { mWriter.AddString("OwnerUUID", Ocelot->GetOwnerUUID().ToShortString()); } mWriter.AddByte("Sitting", Ocelot->IsSitting() ? 1 : 0); mWriter.AddInt("CatType", Ocelot->GetOcelotType()); mWriter.AddInt("Age", Ocelot->GetAge()); break; } case mtPig: { mWriter.AddInt("Age", static_cast(a_Monster)->GetAge()); break; } case mtRabbit: { const cRabbit * Rabbit = static_cast(a_Monster); mWriter.AddInt("RabbitType", static_cast(Rabbit->GetRabbitType())); mWriter.AddInt("MoreCarrotTicks", Rabbit->GetMoreCarrotTicks()); mWriter.AddInt("Age", Rabbit->GetAge()); break; } case mtSheep: { const cSheep *Sheep = static_cast(a_Monster); mWriter.AddByte("Sheared", Sheep->IsSheared()? 1 : 0); mWriter.AddByte("Color", static_cast(Sheep->GetFurColor())); mWriter.AddInt ("Age", Sheep->GetAge()); break; } case mtSlime: { mWriter.AddInt("Size", static_cast(a_Monster)->GetSize()); break; } case mtVillager: { const cVillager *Villager = static_cast(a_Monster); mWriter.AddInt("Profession", Villager->GetVilType()); mWriter.AddInt("Age", Villager->GetAge()); mWriter.BeginList("Inventory", TAG_Compound); AddItemGrid(Villager->GetInventory()); mWriter.EndList(); break; } case mtWither: { mWriter.AddInt("Invul", static_cast(static_cast(a_Monster)->GetWitherInvulnerableTicks())); break; } case mtWolf: { const cWolf *Wolf = static_cast(a_Monster); if (!Wolf->GetOwnerName().empty()) { mWriter.AddString("Owner", Wolf->GetOwnerName()); } if (!Wolf->GetOwnerUUID().IsNil()) { mWriter.AddString("OwnerUUID", Wolf->GetOwnerUUID().ToShortString()); } mWriter.AddByte("Sitting", Wolf->IsSitting() ? 1 : 0); mWriter.AddByte("Angry", Wolf->IsAngry() ? 1 : 0); mWriter.AddByte("CollarColor", static_cast(Wolf->GetCollarColor())); mWriter.AddInt ("Age", Wolf->GetAge()); break; } case mtZombie: { mWriter.AddInt("Age", static_cast(a_Monster)->GetAge()); break; } case mtZombiePigman: { mWriter.AddInt("Age", static_cast(a_Monster)->GetAge()); break; } case mtZombieVillager: { const cZombieVillager *ZombieVillager = reinterpret_cast(a_Monster); mWriter.AddInt("Profession", ZombieVillager->GetProfession()); mWriter.AddInt("ConversionTime", ZombieVillager->ConversionTime()); mWriter.AddInt("Age", ZombieVillager->GetAge()); break; } case mtBlaze: case mtCaveSpider: case mtChicken: case mtCow: case mtEnderDragon: case mtGhast: case mtGiant: case mtGuardian: case mtIronGolem: case mtMooshroom: case mtSilverfish: case mtSkeleton: case mtSnowGolem: case mtSpider: case mtSquid: case mtWitch: case mtWitherSkeleton: { // Other mobs have no special tags. break; } case mtCat: case mtCod: case mtDolphin: case mtDonkey: case mtDrowned: case mtElderGuardian: case mtEndermite: case mtEvoker: case mtFox: case mtHoglin: case mtHusk: case mtIllusioner: case mtLlama: case mtMule: case mtPanda: case mtParrot: case mtPhantom: case mtPiglin: case mtPiglinBrute: case mtPillager: case mtPolarBear: case mtPufferfish: case mtRavager: case mtSalmon: case mtShulker: case mtSkeletonHorse: case mtStray: case mtStrider: case mtTraderLlama: case mtTropicalFish: case mtTurtle: case mtVex: case mtVindicator: case mtWanderingTrader: case mtZoglin: case mtZombieHorse: { // All the entities not added LOGD("Saving unimplemented entity type: %d", NamespaceSerializer::From(a_Monster->GetMobType())); break; } case mtInvalidType: { ASSERT(!"NBTChunkSerializer::SerializerCollector::AddMonsterEntity: Recieved mob of invalid type"); break; } } mWriter.EndCompound(); } void AddPickupEntity(cPickup * a_Pickup) { mWriter.BeginCompound(""); AddBasicEntity(a_Pickup, "Item"); AddItem(a_Pickup->GetItem(), -1, "Item"); mWriter.AddShort("Age", static_cast(a_Pickup->GetAge())); mWriter.EndCompound(); } void AddProjectileEntity(cProjectileEntity * a_Projectile) { mWriter.BeginCompound(""); AddBasicEntity(a_Projectile, a_Projectile->GetMCAClassName()); mWriter.AddByte("inGround", a_Projectile->IsInGround() ? 1 : 0); switch (a_Projectile->GetProjectileKind()) { case cProjectileEntity::pkArrow: { cArrowEntity * Arrow = static_cast(a_Projectile); mWriter.AddShort("xTile", static_cast(Arrow->GetBlockHit().x)); mWriter.AddShort("yTile", static_cast(Arrow->GetBlockHit().y)); mWriter.AddShort("zTile", static_cast(Arrow->GetBlockHit().z)); mWriter.AddByte("pickup", static_cast(Arrow->GetPickupState())); mWriter.AddDouble("damage", Arrow->GetDamageCoeff()); break; } case cProjectileEntity::pkSplashPotion: { cSplashPotionEntity * Potion = static_cast(a_Projectile); mWriter.AddInt("EffectType", static_cast(Potion->GetEntityEffectType())); mWriter.AddInt("EffectDuration", static_cast(Potion->GetEntityEffect().GetDuration())); mWriter.AddShort("EffectIntensity", Potion->GetEntityEffect().GetIntensity()); mWriter.AddDouble("EffectDistanceModifier", Potion->GetEntityEffect().GetDistanceModifier()); mWriter.AddInt("PotionName", Potion->GetPotionColor()); break; } case cProjectileEntity::pkGhastFireball: { mWriter.AddInt("ExplosionPower", 1); break; } case cProjectileEntity::pkFireCharge: case cProjectileEntity::pkWitherSkull: case cProjectileEntity::pkEnderPearl: case cProjectileEntity::pkSnowball: { break; } default: { ASSERT(!"Unsaved projectile entity!"); } } // switch (ProjectileKind) if (!a_Projectile->GetCreatorName().empty()) { mWriter.AddString("ownerName", a_Projectile->GetCreatorName()); } mWriter.EndCompound(); } void AddHangingEntity(cHangingEntity * a_Hanging) { mWriter.AddInt("TileX", FloorC(a_Hanging->GetPosX())); mWriter.AddInt("TileY", FloorC(a_Hanging->GetPosY())); mWriter.AddInt("TileZ", FloorC(a_Hanging->GetPosZ())); mWriter.AddByte("Facing", a_Hanging->GetProtocolFacing()); } void AddTNTEntity(cTNTEntity * a_TNT) { mWriter.BeginCompound(""); AddBasicEntity(a_TNT, "PrimedTnt"); mWriter.AddByte("Fuse", static_cast(a_TNT->GetFuseTicks())); mWriter.EndCompound(); } void AddExpOrbEntity(cExpOrb * a_ExpOrb) { mWriter.BeginCompound(""); AddBasicEntity(a_ExpOrb, "XPOrb"); mWriter.AddShort("Age", static_cast(a_ExpOrb->GetAge())); mWriter.AddShort("Value", static_cast(a_ExpOrb->GetReward())); mWriter.EndCompound(); } void AddItemFrameEntity(cItemFrame * a_ItemFrame) { mWriter.BeginCompound(""); AddBasicEntity(a_ItemFrame, "ItemFrame"); AddHangingEntity(a_ItemFrame); AddItem(a_ItemFrame->GetItem(), -1, "Item"); mWriter.AddByte("ItemRotation", static_cast(a_ItemFrame->GetItemRotation())); mWriter.AddFloat("ItemDropChance", 1.0F); mWriter.EndCompound(); } void AddLeashKnotEntity(cLeashKnot * a_LeashKnot) { mWriter.BeginCompound(""); AddBasicEntity(a_LeashKnot, "LeashKnot"); AddHangingEntity(a_LeashKnot); mWriter.EndCompound(); } void AddPaintingEntity(cPainting * a_Painting) { mWriter.BeginCompound(""); AddBasicEntity(a_Painting, "Painting"); AddHangingEntity(a_Painting); mWriter.AddString("Motive", a_Painting->GetName()); mWriter.EndCompound(); } void AddMinecartChestContents(cMinecartWithChest * a_Minecart) { mWriter.BeginList("Items", TAG_Compound); for (int i = 0; i < cMinecartWithChest::ContentsHeight * cMinecartWithChest::ContentsWidth; i++) { const cItem & Item = a_Minecart->GetSlot(i); if (Item.IsEmpty()) { continue; } AddItem(Item, i); } mWriter.EndList(); } }; // SerializerCollector //////////////////////////////////////////////////////////////////////////////// // NBTChunkSerializer: void NBTChunkSerializer::Serialize(const cWorld & aWorld, cChunkCoords aCoords, cFastNBTWriter & aWriter) { SerializerCollector serializer(aWriter); aWriter.BeginCompound("Level"); aWriter.AddInt("xPos", aCoords.m_ChunkX); aWriter.AddInt("zPos", aCoords.m_ChunkZ); [[maybe_unused]] const bool Result = aWorld.GetChunkData(aCoords, serializer); // Chunk must be present in order to save ASSERT(Result); serializer.Finish(); // Close NBT tags // Save biomes: aWriter.AddByteArray("Biomes", reinterpret_cast(serializer.Biomes), ARRAYCOUNT(serializer.Biomes)); // Save heightmap (Vanilla require this): aWriter.AddIntArray("HeightMap", reinterpret_cast(serializer.Heights), ARRAYCOUNT(serializer.Heights)); // Save blockdata: aWriter.BeginList("Sections", TAG_Compound); ChunkDef_ForEachSection(serializer.m_BlockData, serializer.m_LightData, { aWriter.BeginCompound(""); if (Blocks != nullptr) { aWriter.AddByteArray("Blocks", reinterpret_cast(Blocks->data()), Blocks->size()); } else { aWriter.AddByteArray("Blocks", ChunkBlockData::SectionBlockCount, ChunkBlockData::DefaultValue); } if (Metas != nullptr) { aWriter.AddByteArray("Data", reinterpret_cast(Metas->data()), Metas->size()); } else { aWriter.AddByteArray("Data", ChunkBlockData::SectionMetaCount, ChunkBlockData::DefaultMetaValue); } if (BlockLights != nullptr) { aWriter.AddByteArray("BlockLight", reinterpret_cast(BlockLights->data()), BlockLights->size()); } else { aWriter.AddByteArray("BlockLight", ChunkLightData::SectionLightCount, ChunkLightData::DefaultBlockLightValue); } if (SkyLights != nullptr) { aWriter.AddByteArray("SkyLight", reinterpret_cast(SkyLights->data()), SkyLights->size()); } else { aWriter.AddByteArray("SkyLight", ChunkLightData::SectionLightCount, ChunkLightData::DefaultSkyLightValue); } aWriter.AddByte("Y", static_cast(Y)); aWriter.EndCompound(); }); aWriter.EndList(); // "Sections" // Store the information that the lighting is valid. // For compatibility reason, the default is "invalid" (missing) - this means older data is re-lighted upon loading. if (serializer.mIsLightValid) { aWriter.AddByte("MCSIsLightValid", 1); } // Save the world age to the chunk data. Required by vanilla and mcedit. aWriter.AddLong("LastUpdate", aWorld.GetWorldAge().count()); // Store the flag that the chunk has all the ores, trees, dungeons etc. Cuberite chunks are always complete. aWriter.AddByte("TerrainPopulated", 1); aWriter.EndCompound(); // "Level" } ================================================ FILE: src/WorldStorage/NBTChunkSerializer.h ================================================ // NBTChunkSerializer.h #pragma once #include "ChunkDef.h" // fwd: class cFastNBTWriter; class cWorld; /** Saves the chunk data into a NBT format, used by the Anvil storage. The Writer is expected to be set up so that the serializer can write the chunk's top level "Level" NBT tag immediately. Provides a single static entry point that does all the work, through a hidden worker class in the CPP file. */ class NBTChunkSerializer { public: /** Serializes the chunk into the specified writer. The chunk must be present. */ static void Serialize(const cWorld & aWorld, cChunkCoords aCoords, cFastNBTWriter & aWriter); }; ================================================ FILE: src/WorldStorage/NamespaceSerializer.cpp ================================================ #include "Globals.h" #include "NamespaceSerializer.h" #include unsigned NamespaceSerializer::DataVersion() { return 2566; } std::string_view NamespaceSerializer::From(const CustomStatistic a_ID) { switch (a_ID) { case CustomStatistic::AnimalsBred: return "animals_bred"; case CustomStatistic::AviateOneCm: return "aviate_one_cm"; case CustomStatistic::BellRing: return "bell_ring"; case CustomStatistic::BoatOneCm: return "boat_one_cm"; case CustomStatistic::CleanArmor: return "clean_armor"; case CustomStatistic::CleanBanner: return "clean_banner"; case CustomStatistic::CleanShulkerBox: return "clean_shulker_box"; case CustomStatistic::ClimbOneCm: return "climb_one_cm"; case CustomStatistic::CrouchOneCm: return "crouch_one_cm"; case CustomStatistic::DamageAbsorbed: return "damage_absorbed"; case CustomStatistic::DamageBlockedByShield: return "damage_blocked_by_shield"; case CustomStatistic::DamageDealt: return "damage_dealt"; case CustomStatistic::DamageDealtAbsorbed: return "damage_dealt_absorbed"; case CustomStatistic::DamageDealtResisted: return "damage_dealt_resisted"; case CustomStatistic::DamageResisted: return "damage_resisted"; case CustomStatistic::DamageTaken: return "damage_taken"; case CustomStatistic::Deaths: return "deaths"; case CustomStatistic::Drop: return "drop"; case CustomStatistic::EatCakeSlice: return "eat_cake_slice"; case CustomStatistic::EnchantItem: return "enchant_item"; case CustomStatistic::FallOneCm: return "fall_one_cm"; case CustomStatistic::FillCauldron: return "fill_cauldron"; case CustomStatistic::FishCaught: return "fish_caught"; case CustomStatistic::FlyOneCm: return "fly_one_cm"; case CustomStatistic::HorseOneCm: return "horse_one_cm"; case CustomStatistic::InspectDispenser: return "inspect_dispenser"; case CustomStatistic::InspectDropper: return "inspect_dropper"; case CustomStatistic::InspectHopper: return "inspect_hopper"; case CustomStatistic::InteractWithAnvil: return "interact_with_anvil"; case CustomStatistic::InteractWithBeacon: return "interact_with_beacon"; case CustomStatistic::InteractWithBlastFurnace: return "interact_with_blast_furnace"; case CustomStatistic::InteractWithBrewingstand: return "interact_with_brewingstand"; case CustomStatistic::InteractWithCampfire: return "interact_with_campfire"; case CustomStatistic::InteractWithCartographyTable: return "interact_with_cartography_table"; case CustomStatistic::InteractWithCraftingTable: return "interact_with_crafting_table"; case CustomStatistic::InteractWithFurnace: return "interact_with_furnace"; case CustomStatistic::InteractWithGrindstone: return "interact_with_grindstone"; case CustomStatistic::InteractWithLectern: return "interact_with_lectern"; case CustomStatistic::InteractWithLoom: return "interact_with_loom"; case CustomStatistic::InteractWithSmithingTable: return "interact_with_smithing_table"; case CustomStatistic::InteractWithSmoker: return "interact_with_smoker"; case CustomStatistic::InteractWithStonecutter: return "interact_with_stonecutter"; case CustomStatistic::Jump: return "jump"; case CustomStatistic::LeaveGame: return "leave_game"; case CustomStatistic::MinecartOneCm: return "minecart_one_cm"; case CustomStatistic::MobKills: return "mob_kills"; case CustomStatistic::OpenBarrel: return "open_barrel"; case CustomStatistic::OpenChest: return "open_chest"; case CustomStatistic::OpenEnderchest: return "open_enderchest"; case CustomStatistic::OpenShulkerBox: return "open_shulker_box"; case CustomStatistic::PigOneCm: return "pig_one_cm"; case CustomStatistic::PlayNoteblock: return "play_noteblock"; case CustomStatistic::PlayOneMinute: return "play_one_minute"; case CustomStatistic::PlayRecord: return "play_record"; case CustomStatistic::PlayerKills: return "player_kills"; case CustomStatistic::PotFlower: return "pot_flower"; case CustomStatistic::RaidTrigger: return "raid_trigger"; case CustomStatistic::RaidWin: return "raid_win"; case CustomStatistic::SleepInBed: return "sleep_in_bed"; case CustomStatistic::SneakTime: return "sneak_time"; case CustomStatistic::SprintOneCm: return "sprint_one_cm"; case CustomStatistic::StriderOneCm: return "strider_one_cm"; case CustomStatistic::SwimOneCm: return "swim_one_cm"; case CustomStatistic::TalkedToVillager: return "talked_to_villager"; case CustomStatistic::TargetHit: return "target_hit"; case CustomStatistic::TimeSinceDeath: return "time_since_death"; case CustomStatistic::TimeSinceRest: return "time_since_rest"; case CustomStatistic::TradedWithVillager: return "traded_with_villager"; case CustomStatistic::TriggerTrappedChest: return "trigger_trapped_chest"; case CustomStatistic::TuneNoteblock: return "tune_noteblock"; case CustomStatistic::UseCauldron: return "use_cauldron"; case CustomStatistic::WalkOnWaterOneCm: return "walk_on_water_one_cm"; case CustomStatistic::WalkOneCm: return "walk_one_cm"; case CustomStatistic::WalkUnderWaterOneCm: return "walk_under_water_one_cm"; // Old ones just for compatibility case CustomStatistic::JunkFished: return "junk_fished"; case CustomStatistic::TreasureFished: return "treasure_fished"; // The old advancements case CustomStatistic::AchOpenInventory: return "cuberite:achievement.openInventory"; case CustomStatistic::AchMineWood: return "cuberite:achievement.mineWood"; case CustomStatistic::AchBuildWorkBench: return "cuberite:achievement.buildWorkBench"; case CustomStatistic::AchBuildPickaxe: return "cuberite:achievement.buildPickaxe"; case CustomStatistic::AchBuildFurnace: return "cuberite:achievement.buildFurnace"; case CustomStatistic::AchAcquireIron: return "cuberite:achievement.acquireIron"; case CustomStatistic::AchBuildHoe: return "cuberite:achievement.buildHoe"; case CustomStatistic::AchMakeBread: return "cuberite:achievement.makeBread"; case CustomStatistic::AchBakeCake: return "cuberite:achievement.bakeCake"; case CustomStatistic::AchBuildBetterPickaxe: return "cuberite:achievement.buildBetterPickaxe"; case CustomStatistic::AchCookFish: return "cuberite:achievement.cookFish"; case CustomStatistic::AchOnARail: return "cuberite:achievement.onARail"; case CustomStatistic::AchBuildSword: return "cuberite:achievement.buildSword"; case CustomStatistic::AchKillEnemy: return "cuberite:achievement.killEnemy"; case CustomStatistic::AchKillCow: return "cuberite:achievement.killCow"; case CustomStatistic::AchFlyPig: return "cuberite:achievement.flyPig"; case CustomStatistic::AchSnipeSkeleton: return "cuberite:achievement.snipeSkeleton"; case CustomStatistic::AchDiamonds: return "cuberite:achievement.diamonds"; case CustomStatistic::AchPortal: return "cuberite:achievement.portal"; case CustomStatistic::AchGhast: return "cuberite:achievement.ghast"; case CustomStatistic::AchBlazeRod: return "cuberite:achievement.blazeRod"; case CustomStatistic::AchPotion: return "cuberite:achievement.potion"; case CustomStatistic::AchTheEnd: return "cuberite:achievement.theEnd"; case CustomStatistic::AchTheEnd2: return "cuberite:achievement.theEnd2"; case CustomStatistic::AchEnchantments: return "cuberite:achievement.enchantments"; case CustomStatistic::AchOverkill: return "cuberite:achievement.overkill"; case CustomStatistic::AchBookcase: return "cuberite:achievement.bookcase"; case CustomStatistic::AchExploreAllBiomes: return "cuberite:achievement.exploreAllBiomes"; case CustomStatistic::AchSpawnWither: return "cuberite:achievement.spawnWither"; case CustomStatistic::AchKillWither: return "cuberite:achievement.killWither"; case CustomStatistic::AchFullBeacon: return "cuberite:achievement.fullBeacon"; case CustomStatistic::AchBreedCow: return "cuberite:achievement.breedCow"; case CustomStatistic::AchDiamondsToYou: return "cuberite:achievement.diamondsToYou"; } UNREACHABLE("Tried to save unhandled statistic"); } std::string_view NamespaceSerializer::From(const eMonsterType a_ID) { switch (a_ID) { case mtBat: return "bat"; case mtBlaze: return "blaze"; case mtCat: return "cat"; case mtCaveSpider: return "cave_spider"; case mtChicken: return "chicken"; case mtCod: return "cod"; case mtCow: return "cow"; case mtCreeper: return "creeper"; case mtDolphin: return "dolphin"; case mtDonkey: return "donkey"; case mtDrowned: return "drowned"; case mtElderGuardian: return "elder_guardian"; case mtEnderDragon: return "ender_dragon"; case mtEnderman: return "enderman"; case mtEndermite: return "endermite"; case mtEvoker: return "evoker"; case mtFox: return "fox"; case mtGhast: return "ghast"; case mtGiant: return "giant"; case mtGuardian: return "guardian"; case mtHorse: return "horse"; case mtHoglin: return "hoglin"; case mtHusk: return "husk"; case mtIllusioner: return "illusioner"; case mtIronGolem: return "iron_golem"; case mtLlama: return "llama"; case mtMagmaCube: return "magma_cube"; case mtMooshroom: return "mooshroom"; case mtMule: return "mule"; case mtOcelot: return "ocelot"; case mtPanda: return "panda"; case mtParrot: return "parrot"; case mtPhantom: return "phantom"; case mtPig: return "pig"; case mtPiglin: return "piglin"; case mtPiglinBrute: return "piglin_brute"; case mtPillager: return "pillager"; case mtPolarBear: return "polar_bear"; case mtPufferfish: return "pufferfish"; case mtRabbit: return "rabbit"; case mtRavager: return "ravager"; case mtSalmon: return "salmon"; case mtSheep: return "sheep"; case mtShulker: return "shulker"; case mtSilverfish: return "silverfish"; case mtSkeleton: return "skeleton"; case mtSkeletonHorse: return "skeleton_horse"; case mtSlime: return "slime"; case mtSnowGolem: return "snow_golem"; case mtSpider: return "spider"; case mtSquid: return "squid"; case mtStray: return "stray"; case mtStrider: return "strider"; case mtTraderLlama: return "trader_llama"; case mtTropicalFish: return "tropical_fish"; case mtTurtle: return "turtle"; case mtVex: return "vex"; case mtVillager: return "villager"; case mtVindicator: return "vindicator"; case mtWanderingTrader:return "wandering_trader"; case mtWitch: return "witch"; case mtWither: return "wither"; case mtWitherSkeleton: return "wither_skeleton"; case mtWolf: return "wolf"; case mtZoglin: return "zoglin"; case mtZombie: return "zombie"; case mtZombieHorse: return "zombie_horse"; case mtZombiePigman: return "zombified_piglin"; case mtZombieVillager: return "zombie_villager"; case mtInvalidType: break; } UNREACHABLE("Tried to save unknown monster type"); } std::string_view NamespaceSerializer::From(const BannerPattern a_Pattern) { switch (a_Pattern) { case BannerPattern::BottomStripe: return "bs"; case BannerPattern::TopStripe: return "ts"; case BannerPattern::LeftStripe: return "ls"; case BannerPattern::RightStripe: return "rs"; case BannerPattern::CenterStripeVertical: return "cs"; case BannerPattern::MiddleStripeHorizontal: return "ms"; case BannerPattern::DownRightStripe: return "drs"; case BannerPattern::DownLeftStripe: return "dls"; case BannerPattern::SmallVerticalStripes: return "ss"; case BannerPattern::DiagonalCross: return "cr"; case BannerPattern::SquareCross: return "sc"; case BannerPattern::LeftOfDiagonal: return "ld"; case BannerPattern::RightOfUpsideDownDiagonal: return "rud"; case BannerPattern::LeftOfUpsideDownDiagonal: return "lud"; case BannerPattern::RightOfDiagonal: return "rd"; case BannerPattern::VerticalHalfLeft: return "vh"; case BannerPattern::VerticalHalfRight: return "vhr"; case BannerPattern::HorizontalHalfTop: return "hh"; case BannerPattern::HorizontalHalfBottom: return "hhb"; case BannerPattern::BottomLeftCorner: return "bl"; case BannerPattern::BottomRightCorner: return "br"; case BannerPattern::TopLeftCorner: return "tl"; case BannerPattern::TopRightCorner: return "tr"; case BannerPattern::BottomTriangle: return "bt"; case BannerPattern::TopTriangle: return "tt"; case BannerPattern::BottomTriangleSawtooth: return "bts"; case BannerPattern::TopTriangleSawtooth: return "tts"; case BannerPattern::MiddleCircle: return "mc"; case BannerPattern::MiddleRhombus: return "mr"; case BannerPattern::Border: return "bo"; case BannerPattern::CurlyBorder: return "cbo"; case BannerPattern::Brick: return "bri"; case BannerPattern::Gradient: return "gra"; case BannerPattern::GradientUpsideDown: return "gru"; case BannerPattern::Creeper: return "cre"; case BannerPattern::Skull: return "sku"; case BannerPattern::Flower: return "flo"; case BannerPattern::Mojang: return "moj"; case BannerPattern::Globe: return "glb"; case BannerPattern::Piglin: return "pig"; } UNREACHABLE("Unsupported banner pattern"); } CustomStatistic NamespaceSerializer::ToCustomStatistic(const std::string_view ID) { static const std::unordered_map CustomStatistics { { "animals_bred", CustomStatistic::AnimalsBred }, { "aviate_one_cm", CustomStatistic::AviateOneCm }, { "bell_ring", CustomStatistic::BellRing }, { "boat_one_cm", CustomStatistic::BoatOneCm }, { "clean_armor", CustomStatistic::CleanArmor }, { "clean_banner", CustomStatistic::CleanBanner }, { "clean_shulker_box", CustomStatistic::CleanShulkerBox }, { "climb_one_cm", CustomStatistic::ClimbOneCm }, { "crouch_one_cm", CustomStatistic::CrouchOneCm }, { "damage_absorbed", CustomStatistic::DamageAbsorbed }, { "damage_blocked_by_shield", CustomStatistic::DamageBlockedByShield }, { "damage_dealt", CustomStatistic::DamageDealt }, { "damage_dealt_absorbed", CustomStatistic::DamageDealtAbsorbed }, { "damage_dealt_resisted", CustomStatistic::DamageDealtResisted }, { "damage_resisted", CustomStatistic::DamageResisted }, { "damage_taken", CustomStatistic::DamageTaken }, { "deaths", CustomStatistic::Deaths }, { "drop", CustomStatistic::Drop }, { "eat_cake_slice", CustomStatistic::EatCakeSlice }, { "enchant_item", CustomStatistic::EnchantItem }, { "fall_one_cm", CustomStatistic::FallOneCm }, { "fill_cauldron", CustomStatistic::FillCauldron }, { "fish_caught", CustomStatistic::FishCaught }, { "fly_one_cm", CustomStatistic::FlyOneCm }, { "horse_one_cm", CustomStatistic::HorseOneCm }, { "inspect_dispenser", CustomStatistic::InspectDispenser }, { "inspect_dropper", CustomStatistic::InspectDropper }, { "inspect_hopper", CustomStatistic::InspectHopper }, { "interact_with_anvil", CustomStatistic::InteractWithAnvil }, { "interact_with_beacon", CustomStatistic::InteractWithBeacon }, { "interact_with_blast_furnace", CustomStatistic::InteractWithBlastFurnace }, { "interact_with_brewingstand", CustomStatistic::InteractWithBrewingstand }, { "interact_with_campfire", CustomStatistic::InteractWithCampfire }, { "interact_with_cartography_table", CustomStatistic::InteractWithCartographyTable }, { "interact_with_crafting_table", CustomStatistic::InteractWithCraftingTable }, { "interact_with_furnace", CustomStatistic::InteractWithFurnace }, { "interact_with_grindstone", CustomStatistic::InteractWithGrindstone }, { "interact_with_lectern", CustomStatistic::InteractWithLectern }, { "interact_with_loom", CustomStatistic::InteractWithLoom }, { "interact_with_smithing_table", CustomStatistic::InteractWithSmithingTable }, { "interact_with_smoker", CustomStatistic::InteractWithSmoker }, { "interact_with_stonecutter", CustomStatistic::InteractWithStonecutter }, { "jump", CustomStatistic::Jump }, { "leave_game", CustomStatistic::LeaveGame }, { "minecart_one_cm", CustomStatistic::MinecartOneCm }, { "mob_kills", CustomStatistic::MobKills }, { "open_barrel", CustomStatistic::OpenBarrel }, { "open_chest", CustomStatistic::OpenChest }, { "open_enderchest", CustomStatistic::OpenEnderchest }, { "open_shulker_box", CustomStatistic::OpenShulkerBox }, { "pig_one_cm", CustomStatistic::PigOneCm }, { "play_noteblock", CustomStatistic::PlayNoteblock }, { "play_one_minute", CustomStatistic::PlayOneMinute }, { "play_record", CustomStatistic::PlayRecord }, { "player_kills", CustomStatistic::PlayerKills }, { "pot_flower", CustomStatistic::PotFlower }, { "raid_trigger", CustomStatistic::RaidTrigger }, { "raid_win", CustomStatistic::RaidWin }, { "sleep_in_bed", CustomStatistic::SleepInBed }, { "sneak_time", CustomStatistic::SneakTime }, { "sprint_one_cm", CustomStatistic::SprintOneCm }, { "strider_one_cm", CustomStatistic::StriderOneCm }, { "swim_one_cm", CustomStatistic::SwimOneCm }, { "talked_to_villager", CustomStatistic::TalkedToVillager }, { "target_hit", CustomStatistic::TargetHit }, { "time_since_death", CustomStatistic::TimeSinceDeath }, { "time_since_rest", CustomStatistic::TimeSinceRest }, { "traded_with_villager", CustomStatistic::TradedWithVillager }, { "trigger_trapped_chest", CustomStatistic::TriggerTrappedChest }, { "tune_noteblock", CustomStatistic::TuneNoteblock }, { "use_cauldron", CustomStatistic::UseCauldron }, { "walk_on_water_one_cm", CustomStatistic::WalkOnWaterOneCm }, { "walk_one_cm", CustomStatistic::WalkOneCm }, { "walk_under_water_one_cm", CustomStatistic::WalkUnderWaterOneCm }, // Old ones just for compatibility { "junk_fished", CustomStatistic::JunkFished }, { "treasure_fished", CustomStatistic::TreasureFished }, // The old advancements { "cuberite:achievement.openInventory", CustomStatistic::AchOpenInventory }, { "cuberite:achievement.mineWood", CustomStatistic::AchMineWood }, { "cuberite:achievement.buildWorkBench", CustomStatistic::AchBuildWorkBench }, { "cuberite:achievement.buildPickaxe", CustomStatistic::AchBuildPickaxe }, { "cuberite:achievement.buildFurnace", CustomStatistic::AchBuildFurnace }, { "cuberite:achievement.acquireIron", CustomStatistic::AchAcquireIron }, { "cuberite:achievement.buildHoe", CustomStatistic::AchBuildHoe }, { "cuberite:achievement.makeBread", CustomStatistic::AchMakeBread }, { "cuberite:achievement.bakeCake", CustomStatistic::AchBakeCake }, { "cuberite:achievement.buildBetterPickaxe", CustomStatistic::AchBuildBetterPickaxe }, { "cuberite:achievement.cookFish", CustomStatistic::AchCookFish }, { "cuberite:achievement.onARail", CustomStatistic::AchOnARail }, { "cuberite:achievement.buildSword", CustomStatistic::AchBuildSword }, { "cuberite:achievement.killEnemy", CustomStatistic::AchKillEnemy }, { "cuberite:achievement.killCow", CustomStatistic::AchKillCow }, { "cuberite:achievement.flyPig", CustomStatistic::AchFlyPig }, { "cuberite:achievement.snipeSkeleton", CustomStatistic::AchSnipeSkeleton }, { "cuberite:achievement.diamonds", CustomStatistic::AchDiamonds }, { "cuberite:achievement.portal", CustomStatistic::AchPortal }, { "cuberite:achievement.ghast", CustomStatistic::AchGhast }, { "cuberite:achievement.blazeRod", CustomStatistic::AchBlazeRod }, { "cuberite:achievement.potion", CustomStatistic::AchPotion }, { "cuberite:achievement.theEnd", CustomStatistic::AchTheEnd }, { "cuberite:achievement.theEnd2", CustomStatistic::AchTheEnd2 }, { "cuberite:achievement.enchantments", CustomStatistic::AchEnchantments }, { "cuberite:achievement.overkill", CustomStatistic::AchOverkill }, { "cuberite:achievement.bookcase", CustomStatistic::AchBookcase }, { "cuberite:achievement.exploreAllBiomes", CustomStatistic::AchExploreAllBiomes }, { "cuberite:achievement.spawnWither", CustomStatistic::AchSpawnWither }, { "cuberite:achievement.killWither", CustomStatistic::AchKillWither }, { "cuberite:achievement.fullBeacon", CustomStatistic::AchFullBeacon }, { "cuberite:achievement.breedCow", CustomStatistic::AchBreedCow }, { "cuberite:achievement.diamondsToYou", CustomStatistic::AchDiamondsToYou} }; return CustomStatistics.at(ID); } std::pair NamespaceSerializer::SplitNamespacedID(const std::string_view ID) { const auto NamespaceIndex = ID.find(':'); if (NamespaceIndex == std::string_view::npos) { // No explicit namespace defaults to the Minecraft namespace: return { Namespace::Minecraft, ID }; } const auto Namespace = ID.substr(0, NamespaceIndex); if (Namespace == "minecraft") { // An unprefixed ID in the vanilla Minecraft namespace. const auto Value = ID.substr(NamespaceIndex + 1); return { Namespace::Minecraft, Value }; } if (Namespace == "cuberite") { return { Namespace::Cuberite, ID }; } return { Namespace::Unknown, ID }; } eMonsterType NamespaceSerializer::ToMonsterType(const std::string_view a_ID) { static const std::unordered_map MonsterTypes { { "bat", mtBat }, { "blaze", mtBlaze }, { "cat", mtCat }, { "cave_spider", mtCaveSpider }, { "chicken", mtChicken }, { "cod", mtCod }, { "cow", mtCow }, { "creeper", mtCreeper }, { "dolphin", mtDolphin }, { "donkey", mtDonkey }, { "drowned", mtDrowned }, { "elder_guardian", mtElderGuardian }, { "ender_dragon", mtEnderDragon }, { "enderman", mtEnderman }, { "endermite", mtEndermite }, { "evoker", mtEvoker }, { "fox", mtFox }, { "ghast", mtGhast }, { "giant", mtGiant }, { "guardian", mtGuardian }, { "horse", mtHorse }, { "hoglin", mtHoglin }, { "husk", mtHusk }, { "illusioner", mtIllusioner }, { "iron_golem", mtIronGolem }, { "llama", mtLlama }, { "magma_cube", mtMagmaCube }, { "mooshroom", mtMooshroom }, { "mule", mtMule }, { "ocelot", mtOcelot }, { "panda", mtPanda }, { "parrot", mtParrot }, { "phantom", mtPhantom }, { "pig", mtPig }, { "piglin", mtPiglin }, { "piglin_brute", mtPiglinBrute }, { "pillager", mtPillager }, { "polar_bear", mtPolarBear }, { "pufferfish", mtPufferfish }, { "rabbit", mtRabbit }, { "ravager", mtRavager }, { "salmon", mtSalmon }, { "sheep", mtSheep }, { "shulker", mtShulker }, { "silverfish", mtSilverfish }, { "skeleton", mtSkeleton }, { "skeleton_horse", mtSkeletonHorse }, { "slime", mtSlime }, { "snow_golem", mtSnowGolem }, { "spider", mtSpider }, { "squid", mtSquid }, { "stray", mtStray }, { "strider", mtStrider }, { "trader_llama", mtTraderLlama }, { "tropical_fish", mtTropicalFish }, { "turtle", mtTurtle }, { "vex", mtVex }, { "villager", mtVillager }, { "vindicator", mtVindicator }, { "wandering_trader", mtWanderingTrader }, { "witch", mtWitch }, { "wither", mtWither }, { "wither_skeleton", mtWitherSkeleton }, { "wolf", mtWolf }, { "zoglin", mtZoglin }, { "zombie", mtZombie }, { "zombie_horse", mtZombieHorse }, { "zombified_piglin", mtZombiePigman }, { "zombie_villager", mtZombieVillager }, { "snowman", mtSnowGolem }, { "villager_golem", mtIronGolem }, { "zombie_pigman", mtZombiePigman }, // Old names: { "Bat", mtBat }, { "Blaze", mtBlaze }, { "CaveSpider", mtCaveSpider }, { "Chicken", mtChicken }, { "Cow", mtCow }, { "Creeper", mtCreeper }, { "EnderDragon", mtEnderDragon }, { "Enderman", mtEnderman }, { "Ghast", mtGhast }, { "Giant", mtGiant }, { "Guardian", mtGuardian }, { "Horse", mtHorse }, { "VillagerGolem", mtIronGolem }, { "LavaSlime", mtMagmaCube }, { "MushroomCow", mtMooshroom }, { "Ozelot", mtOcelot }, { "Pig", mtPig }, { "Rabbit", mtRabbit }, { "Sheep", mtSheep }, { "Silverfish", mtSilverfish }, { "Skeleton", mtSkeleton }, { "Slime", mtSlime }, { "SnowMan", mtSnowGolem }, { "Spider", mtSpider }, { "Squid", mtSquid }, { "Villager", mtVillager }, { "Witch", mtWitch }, { "WitherBoss", mtWither }, { "WitherSkeleton", mtWitherSkeleton }, { "Wolf", mtWolf }, { "Zombie", mtZombie }, { "PigZombie", mtZombiePigman }, { "ZombieVillager", mtZombieVillager } }; return MonsterTypes.at(a_ID); } AString NamespaceSerializer::Prettify(AString a_ID) { bool NextLetterCapitalized = true; std::for_each(a_ID.begin(), a_ID.end(), [&](char & a_Letter) { if (NextLetterCapitalized) { a_Letter = static_cast(std::toupper(a_Letter)); NextLetterCapitalized = false; } else if (a_Letter == '_') { a_Letter = ' '; NextLetterCapitalized = true; } }); return a_ID; } AString NamespaceSerializer::PrettifyEntityName(const AString & a_ID, const bool a_IsTamed) { // In older vanilla Minecraft version (before 1.14) ocelots and cats were the same mob. // So after killing a tamed ocelot without a custom name the message will say "Cat was slain by [PlayerName]". if ((a_ID == "ocelot") && a_IsTamed) { return "Cat"; } return Prettify(a_ID); } ================================================ FILE: src/WorldStorage/NamespaceSerializer.h ================================================ #pragma once #include "Defines.h" #include "Mobs/MonsterTypes.h" #include "Registries/CustomStatistics.h" namespace NamespaceSerializer { enum class Namespace { Minecraft, Cuberite, Unknown }; unsigned DataVersion(); std::string_view From(CustomStatistic a_ID); std::string_view From(eMonsterType a_ID); std::string_view From(BannerPattern a_ID); CustomStatistic ToCustomStatistic(std::string_view a_ID); eMonsterType ToMonsterType(std::string_view a_ID); std::pair SplitNamespacedID(std::string_view ID); // Examples: Input: "wolf" -> Output: "Wolf", Input: "iron_golem" -> Output: "Iron Golem" AString Prettify(AString a_ID); AString PrettifyEntityName(const AString & a_ID, const bool a_IsTamed = false); } ================================================ FILE: src/WorldStorage/SchematicFileSerializer.cpp ================================================ // SchematicFileSerializer.cpp // Implements the cSchematicFileSerializer class representing the interface to load and save cBlockArea to a .schematic file #include "Globals.h" #include "FastNBT.h" #include "SchematicFileSerializer.h" #include "../OSSupport/GZipFile.h" //////////////////////////////////////////////////////////////////////////////// // cSchematicFileSerializer: void cSchematicFileSerializer::LoadFromSchematicFile(cBlockArea & a_BlockArea, const std::string & a_FileName) { const auto Data = GZipFile::ReadRestOfFile(a_FileName); const cParsedNBT NBT(Data.GetView()); if (!NBT.IsValid()) { throw std::runtime_error(fmt::format("Cannot parse the NBT in the schematic file \"{}\".", a_FileName)); } LoadFromSchematicNBT(a_BlockArea, NBT); } void cSchematicFileSerializer::LoadFromSchematicString(cBlockArea & a_BlockArea, const ContiguousByteBufferView a_SchematicData) { const auto Extracted = Compression::Extractor().ExtractGZip(a_SchematicData); const cParsedNBT NBT(Extracted.GetView()); if (!NBT.IsValid()) { throw std::runtime_error("Cannot parse the NBT in the schematic data."); } LoadFromSchematicNBT(a_BlockArea, NBT); } void cSchematicFileSerializer::SaveToSchematicFile(const cBlockArea & a_BlockArea, const std::string & a_FileName) { GZipFile::Write(a_FileName, SaveToSchematicNBT(a_BlockArea)); } Compression::Result cSchematicFileSerializer::SaveToSchematicString(const cBlockArea & a_BlockArea) { return Compression::Compressor().CompressGZip(SaveToSchematicNBT(a_BlockArea)); } void cSchematicFileSerializer::LoadFromSchematicNBT(cBlockArea & a_BlockArea, const cParsedNBT & a_NBT) { int TMaterials = a_NBT.FindChildByName(a_NBT.GetRoot(), "Materials"); if ((TMaterials > 0) && (a_NBT.GetType(TMaterials) == TAG_String)) { AString Materials = a_NBT.GetString(TMaterials); if (Materials.compare("Alpha") != 0) { throw std::runtime_error(fmt::format("Materials tag is present and \"{}\" instead of \"Alpha\". Possibly a wrong-format schematic file.", Materials)); } } int TSizeX = a_NBT.FindChildByName(a_NBT.GetRoot(), "Width"); int TSizeY = a_NBT.FindChildByName(a_NBT.GetRoot(), "Height"); int TSizeZ = a_NBT.FindChildByName(a_NBT.GetRoot(), "Length"); if ( (TSizeX < 0) || (TSizeY < 0) || (TSizeZ < 0) || (a_NBT.GetType(TSizeX) != TAG_Short) || (a_NBT.GetType(TSizeY) != TAG_Short) || (a_NBT.GetType(TSizeZ) != TAG_Short) ) { throw std::runtime_error(fmt::format( "Dimensions are missing from the schematic file ({}, {}, {}), ({}, {}, {})", TSizeX, TSizeY, TSizeZ, (TSizeX >= 0) ? a_NBT.GetType(TSizeX) : -1, (TSizeY >= 0) ? a_NBT.GetType(TSizeY) : -1, (TSizeZ >= 0) ? a_NBT.GetType(TSizeZ) : -1 )); } int SizeX = a_NBT.GetShort(TSizeX); int SizeY = a_NBT.GetShort(TSizeY); int SizeZ = a_NBT.GetShort(TSizeZ); if ((SizeX < 1) || (SizeX > 65535) || (SizeY < 1) || (SizeY > 65535) || (SizeZ < 1) || (SizeZ > 65535)) { throw std::runtime_error(fmt::format("Dimensions are invalid in the schematic file: {}, {}, {}", SizeX, SizeY, SizeZ)); } int TBlockTypes = a_NBT.FindChildByName(a_NBT.GetRoot(), "Blocks"); int TBlockMetas = a_NBT.FindChildByName(a_NBT.GetRoot(), "Data"); if ((TBlockTypes < 0) || (a_NBT.GetType(TBlockTypes) != TAG_ByteArray)) { throw std::runtime_error(fmt::format("BlockTypes are invalid in the schematic file: {}", TBlockTypes)); } bool AreMetasPresent = (TBlockMetas > 0) && (a_NBT.GetType(TBlockMetas) == TAG_ByteArray); a_BlockArea.Clear(); a_BlockArea.SetSize(SizeX, SizeY, SizeZ, AreMetasPresent ? (cBlockArea::baTypes | cBlockArea::baMetas) : cBlockArea::baTypes); int TOffsetX = a_NBT.FindChildByName(a_NBT.GetRoot(), "WEOffsetX"); int TOffsetY = a_NBT.FindChildByName(a_NBT.GetRoot(), "WEOffsetY"); int TOffsetZ = a_NBT.FindChildByName(a_NBT.GetRoot(), "WEOffsetZ"); if ( (TOffsetX < 0) || (TOffsetY < 0) || (TOffsetZ < 0) || (a_NBT.GetType(TOffsetX) != TAG_Int) || (a_NBT.GetType(TOffsetY) != TAG_Int) || (a_NBT.GetType(TOffsetZ) != TAG_Int) ) { // Not every schematic file has an offset, so we shoudn't give a warn message. a_BlockArea.SetWEOffset(0, 0, 0); } else { a_BlockArea.SetWEOffset(a_NBT.GetInt(TOffsetX), a_NBT.GetInt(TOffsetY), a_NBT.GetInt(TOffsetZ)); } // Copy the block types and metas: size_t NumTypeBytes = a_BlockArea.GetBlockCount(); if (a_NBT.GetDataLength(TBlockTypes) < NumTypeBytes) { LOG("BlockTypes truncated in the schematic file (exp %u, got %u bytes). Loading partial.", static_cast(NumTypeBytes), static_cast(a_NBT.GetDataLength(TBlockTypes)) ); NumTypeBytes = a_NBT.GetDataLength(TBlockTypes); } memcpy(a_BlockArea.GetBlockTypes(), a_NBT.GetData(TBlockTypes), NumTypeBytes); if (AreMetasPresent) { size_t NumMetaBytes = a_BlockArea.GetBlockCount(); if (a_NBT.GetDataLength(TBlockMetas) < NumMetaBytes) { LOG("BlockMetas truncated in the schematic file (exp %u, got %u bytes). Loading partial.", static_cast(NumMetaBytes), static_cast(a_NBT.GetDataLength(TBlockMetas)) ); NumMetaBytes = a_NBT.GetDataLength(TBlockMetas); } memcpy(a_BlockArea.GetBlockMetas(), a_NBT.GetData(TBlockMetas), NumMetaBytes); } } ContiguousByteBuffer cSchematicFileSerializer::SaveToSchematicNBT(const cBlockArea & a_BlockArea) { cFastNBTWriter Writer("Schematic"); Writer.AddShort("Width", static_cast(a_BlockArea.m_Size.x)); Writer.AddShort("Height", static_cast(a_BlockArea.m_Size.y)); Writer.AddShort("Length", static_cast(a_BlockArea.m_Size.z)); Writer.AddString("Materials", "Alpha"); if (a_BlockArea.HasBlockTypes()) { Writer.AddByteArray("Blocks", reinterpret_cast(a_BlockArea.GetBlockTypes()), a_BlockArea.GetBlockCount()); } else { AString Dummy(a_BlockArea.GetBlockCount(), 0); Writer.AddByteArray("Blocks", Dummy.data(), Dummy.size()); } if (a_BlockArea.HasBlockMetas()) { Writer.AddByteArray("Data", reinterpret_cast(a_BlockArea.GetBlockMetas()), a_BlockArea.GetBlockCount()); } else { AString Dummy(a_BlockArea.GetBlockCount(), 0); Writer.AddByteArray("Data", Dummy.data(), Dummy.size()); } Writer.AddInt("WEOffsetX", a_BlockArea.m_WEOffset.x); Writer.AddInt("WEOffsetY", a_BlockArea.m_WEOffset.y); Writer.AddInt("WEOffsetZ", a_BlockArea.m_WEOffset.z); // TODO: Save entities and block entities Writer.BeginList("Entities", TAG_Compound); Writer.EndList(); Writer.BeginList("TileEntities", TAG_Compound); Writer.EndList(); Writer.Finish(); return ContiguousByteBuffer(Writer.GetResult()); } ================================================ FILE: src/WorldStorage/SchematicFileSerializer.h ================================================ // SchematicFileSerializer.h // Declares the cSchematicFileSerializer class representing the interface to load and save cBlockArea to a .schematic file #pragma once #include "../BlockArea.h" #include "../StringCompression.h" // fwd: FastNBT.h class cParsedNBT; class cSchematicFileSerializer { public: /** Loads an area from a .schematic file. */ static void LoadFromSchematicFile(cBlockArea & a_BlockArea, const std::string & a_FileName); /** Loads an area from a string containing the .schematic file data. */ static void LoadFromSchematicString(cBlockArea & a_BlockArea, ContiguousByteBufferView a_SchematicData); /** Saves the area into a .schematic file. */ static void SaveToSchematicFile(const cBlockArea & a_BlockArea, const std::string & a_FileName); /** Saves the area into a string containing the .schematic file data. */ static Compression::Result SaveToSchematicString(const cBlockArea & a_BlockArea); private: /** Loads the area from a schematic file uncompressed and parsed into a NBT tree. */ static void LoadFromSchematicNBT(cBlockArea & a_BlockArea, const cParsedNBT & a_NBT); /** Saves the area into a NBT representation and returns the NBT data as a string. */ static ContiguousByteBuffer SaveToSchematicNBT(const cBlockArea & a_BlockArea); }; ================================================ FILE: src/WorldStorage/ScoreboardSerializer.cpp ================================================ // ScoreboardSerializer.cpp #include "Globals.h" #include "ScoreboardSerializer.h" #include "OSSupport/GZipFile.h" #include "FastNBT.h" #include "../Scoreboard.h" cScoreboardSerializer::cScoreboardSerializer(const AString & a_WorldName, cScoreboard * a_ScoreBoard): m_ScoreBoard(a_ScoreBoard) { auto DataPath = fmt::format(FMT_STRING("{}{}data"), a_WorldName, cFile::PathSeparator()); m_Path = DataPath + cFile::PathSeparator() + "scoreboard.dat"; cFile::CreateFolder(DataPath); } bool cScoreboardSerializer::Load() { try { const auto Data = GZipFile::ReadRestOfFile(m_Path); const cParsedNBT NBT(Data.GetView()); if (!NBT.IsValid()) { // NBT Parsing failed return false; } return LoadScoreboardFromNBT(NBT); } catch (const std::exception & Oops) { LOGWARNING("Failed to load scoreboard from \"%s\": %s", m_Path.c_str(), Oops.what()); return false; } } bool cScoreboardSerializer::Save(void) { cFastNBTWriter Writer; SaveScoreboardToNBT(Writer); Writer.Finish(); #ifndef NDEBUG cParsedNBT TestParse(Writer.GetResult()); ASSERT(TestParse.IsValid()); #endif // !NDEBUG GZipFile::Write(m_Path, Writer.GetResult()); return true; } void cScoreboardSerializer::SaveScoreboardToNBT(cFastNBTWriter & a_Writer) { a_Writer.BeginCompound("data"); a_Writer.BeginList("Objectives", TAG_Compound); for (cScoreboard::cObjectiveMap::const_iterator it = m_ScoreBoard->m_Objectives.begin(); it != m_ScoreBoard->m_Objectives.end(); ++it) { const cObjective & Objective = it->second; a_Writer.BeginCompound(""); a_Writer.AddString("CriteriaName", cObjective::TypeToString(Objective.GetType())); a_Writer.AddString("DisplayName", Objective.GetDisplayName()); a_Writer.AddString("Name", it->first); a_Writer.EndCompound(); } a_Writer.EndList(); // Objectives a_Writer.BeginList("PlayerScores", TAG_Compound); for (cScoreboard::cObjectiveMap::const_iterator it = m_ScoreBoard->m_Objectives.begin(); it != m_ScoreBoard->m_Objectives.end(); ++it) { const cObjective & Objective = it->second; for (cObjective::cScoreMap::const_iterator it2 = Objective.m_Scores.begin(); it2 != Objective.m_Scores.end(); ++it2) { a_Writer.BeginCompound(""); a_Writer.AddInt("Score", it2->second); a_Writer.AddString("Name", it2->first); a_Writer.AddString("Objective", it->first); a_Writer.EndCompound(); } } a_Writer.EndList(); // PlayerScores a_Writer.BeginList("Teams", TAG_Compound); for (cScoreboard::cTeamMap::const_iterator it = m_ScoreBoard->m_Teams.begin(); it != m_ScoreBoard->m_Teams.end(); ++it) { const cTeam & Team = it->second; a_Writer.BeginCompound(""); a_Writer.AddByte("AllowFriendlyFire", Team.AllowsFriendlyFire() ? 1 : 0); a_Writer.AddByte("SeeFriendlyInvisibles", Team.CanSeeFriendlyInvisible() ? 1 : 0); a_Writer.AddString("DisplayName", Team.GetDisplayName()); a_Writer.AddString("Name", it->first); a_Writer.AddString("Prefix", Team.GetPrefix()); a_Writer.AddString("Suffix", Team.GetSuffix()); a_Writer.BeginList("Players", TAG_String); for (cTeam::cPlayerNameSet::const_iterator it2 = Team.m_Players.begin(); it2 != Team.m_Players.end(); ++it2) { a_Writer.AddString("", *it2); } a_Writer.EndList(); a_Writer.EndCompound(); } a_Writer.EndList(); // Teams a_Writer.BeginCompound("DisplaySlots"); cObjective * Objective = m_ScoreBoard->GetObjectiveIn(cScoreboard::dsList); a_Writer.AddString("slot_0", (Objective == nullptr) ? "" : Objective->GetName()); Objective = m_ScoreBoard->GetObjectiveIn(cScoreboard::dsSidebar); a_Writer.AddString("slot_1", (Objective == nullptr) ? "" : Objective->GetName()); Objective = m_ScoreBoard->GetObjectiveIn(cScoreboard::dsName); a_Writer.AddString("slot_2", (Objective == nullptr) ? "" : Objective->GetName()); a_Writer.EndCompound(); // DisplaySlots a_Writer.EndCompound(); // Data } bool cScoreboardSerializer::LoadScoreboardFromNBT(const cParsedNBT & a_NBT) { int Data = a_NBT.FindChildByName(0, "data"); if (Data < 0) { return false; } int Objectives = a_NBT.FindChildByName(Data, "Objectives"); if (Objectives < 0) { return false; } for (int Child = a_NBT.GetFirstChild(Objectives); Child >= 0; Child = a_NBT.GetNextSibling(Child)) { AString CriteriaName, DisplayName, Name; int CurrLine = a_NBT.FindChildByName(Child, "CriteriaName"); if (CurrLine >= 0) { CriteriaName = a_NBT.GetString(CurrLine); } CurrLine = a_NBT.FindChildByName(Child, "DisplayName"); if (CurrLine >= 0) { DisplayName = a_NBT.GetString(CurrLine); } CurrLine = a_NBT.FindChildByName(Child, "Name"); if (CurrLine >= 0) { Name = a_NBT.GetString(CurrLine); } cObjective::eType Type = cObjective::StringToType(CriteriaName); m_ScoreBoard->RegisterObjective(Name, DisplayName, Type); } int PlayerScores = a_NBT.FindChildByName(Data, "PlayerScores"); if (PlayerScores < 0) { return false; } for (int Child = a_NBT.GetFirstChild(PlayerScores); Child >= 0; Child = a_NBT.GetNextSibling(Child)) { AString Name, ObjectiveName; cObjective::Score Score = 0; int CurrLine = a_NBT.FindChildByName(Child, "Score"); if (CurrLine >= 0) { Score = a_NBT.GetInt(CurrLine); } CurrLine = a_NBT.FindChildByName(Child, "Name"); if (CurrLine >= 0) { Name = a_NBT.GetString(CurrLine); } CurrLine = a_NBT.FindChildByName(Child, "Objective"); if (CurrLine >= 0) { ObjectiveName = a_NBT.GetString(CurrLine); } cObjective * Objective = m_ScoreBoard->GetObjective(ObjectiveName); if (Objective) { Objective->SetScore(Name, Score); } } int Teams = a_NBT.FindChildByName(Data, "Teams"); if (Teams < 0) { return false; } for (int Child = a_NBT.GetFirstChild(Teams); Child >= 0; Child = a_NBT.GetNextSibling(Child)) { AString Name, DisplayName, Prefix, Suffix; bool AllowsFriendlyFire = true, CanSeeFriendlyInvisible = false; int CurrLine = a_NBT.FindChildByName(Child, "Name"); if ((CurrLine >= 0) && (a_NBT.GetType(CurrLine) == TAG_String)) { Name = a_NBT.GetString(CurrLine); } CurrLine = a_NBT.FindChildByName(Child, "DisplayName"); if ((CurrLine >= 0) && (a_NBT.GetType(CurrLine) == TAG_String)) { DisplayName = a_NBT.GetString(CurrLine); } CurrLine = a_NBT.FindChildByName(Child, "Prefix"); if ((CurrLine >= 0) && (a_NBT.GetType(CurrLine) == TAG_String)) { Prefix = a_NBT.GetString(CurrLine); } CurrLine = a_NBT.FindChildByName(Child, "Suffix"); if ((CurrLine >= 0) && (a_NBT.GetType(CurrLine) == TAG_String)) { Suffix = a_NBT.GetString(CurrLine); } CurrLine = a_NBT.FindChildByName(Child, "AllowFriendlyFire"); if ((CurrLine >= 0) && (a_NBT.GetType(CurrLine) == TAG_Int)) { AllowsFriendlyFire = (a_NBT.GetInt(CurrLine) != 0); } CurrLine = a_NBT.FindChildByName(Child, "SeeFriendlyInvisibles"); if ((CurrLine >= 0) && (a_NBT.GetType(CurrLine) == TAG_Int)) { CanSeeFriendlyInvisible = (a_NBT.GetInt(CurrLine) != 0); } cTeam * Team = m_ScoreBoard->RegisterTeam(Name, DisplayName, Prefix, Suffix); Team->SetFriendlyFire(AllowsFriendlyFire); Team->SetCanSeeFriendlyInvisible(CanSeeFriendlyInvisible); int Players = a_NBT.FindChildByName(Child, "Players"); if (Players < 0) { continue; } for (int ChildB = a_NBT.GetFirstChild(Players); ChildB >= 0; ChildB = a_NBT.GetNextSibling(ChildB)) { Team->AddPlayer(a_NBT.GetString(ChildB)); } } int DisplaySlots = a_NBT.FindChildByName(Data, "DisplaySlots"); if (DisplaySlots < 0) { return false; } int CurrLine = a_NBT.FindChildByName(DisplaySlots, "slot_0"); if (CurrLine >= 0) { AString Name = a_NBT.GetString(CurrLine); m_ScoreBoard->SetDisplay(Name, cScoreboard::dsList); } CurrLine = a_NBT.FindChildByName(DisplaySlots, "slot_1"); if (CurrLine >= 0) { AString Name = a_NBT.GetString(CurrLine); m_ScoreBoard->SetDisplay(Name, cScoreboard::dsSidebar); } CurrLine = a_NBT.FindChildByName(DisplaySlots, "slot_2"); if (CurrLine >= 0) { AString Name = a_NBT.GetString(CurrLine); m_ScoreBoard->SetDisplay(Name, cScoreboard::dsName); } return true; } ================================================ FILE: src/WorldStorage/ScoreboardSerializer.h ================================================ // ScoreboardSerializer.h // Declares the cScoreboardSerializer class that is used for saving scoreboards into NBT format used by Anvil #pragma once // fwd: class cFastNBTWriter; class cParsedNBT; class cScoreboard; class cScoreboardSerializer { public: cScoreboardSerializer(const AString & a_WorldName, cScoreboard * a_ScoreBoard); /** Try to load the scoreboard */ bool Load(void); /** Try to save the scoreboard */ bool Save(void); private: void SaveScoreboardToNBT(cFastNBTWriter & a_Writer); bool LoadScoreboardFromNBT(const cParsedNBT & a_NBT); cScoreboard * m_ScoreBoard; AString m_Path; } ; ================================================ FILE: src/WorldStorage/StatisticsSerializer.cpp ================================================ // StatisticsSerializer.cpp #include "Globals.h" #include "StatisticsManager.h" #include "StatisticsSerializer.h" #include "NamespaceSerializer.h" #include static auto MakeStatisticsDirectory(const std::string & WorldPath, std::string && FileName) { // Even though stats are shared between worlds, they are (usually) saved // inside the folder of the default world. // Path to the world's statistics folder. const auto Path = WorldPath + cFile::GetPathSeparator() + "stats"; // Ensure that the directory exists. cFile::CreateFolder(Path); return Path + cFile::GetPathSeparator() + std::move(FileName) + ".json"; } static void SaveStatToJSON(const StatisticsManager & Manager, Json::Value & a_Out) { if (Manager.Custom.empty()) { // Avoid saving "custom": null to disk: return; } auto & Custom = a_Out["custom"]; for (const auto & [Statistic, Value] : Manager.Custom) { Custom[NamespaceSerializer::From(Statistic).data()] = Value; } } static void LoadCustomStatFromJSON(StatisticsManager & Manager, const Json::Value & a_In) { for (auto it = a_In.begin(); it != a_In.end(); ++it) { const auto & Key = it.key().asString(); const auto & [Namespace, Name] = NamespaceSerializer::SplitNamespacedID(Key); if (Namespace == NamespaceSerializer::Namespace::Unknown) { // Ignore non-Vanilla, non-Cuberite namespaces for now: continue; } Manager.Custom[NamespaceSerializer::ToCustomStatistic(Name)] = it->asUInt(); } } void StatisticsSerializer::Load(StatisticsManager & Manager, const std::string & WorldPath, std::string && FileName) { Json::Value Root; InputFileStream(MakeStatisticsDirectory(WorldPath, std::move(FileName))) >> Root; LoadCustomStatFromJSON(Manager, Root["stats"]["custom"]); } void StatisticsSerializer::Save(const StatisticsManager & Manager, const std::string & WorldPath, std::string && FileName) { Json::Value Root; SaveStatToJSON(Manager, Root["stats"]); Root["DataVersion"] = NamespaceSerializer::DataVersion(); OutputFileStream(MakeStatisticsDirectory(WorldPath, std::move(FileName))) << Root; } ================================================ FILE: src/WorldStorage/StatisticsSerializer.h ================================================ // StatisticsSerializer.h // Declares the cStatSerializer class that is used for saving stats into JSON #pragma once struct StatisticsManager; namespace Json { class Value; } namespace StatisticsSerializer { /* Try to load the player statistics. */ void Load(StatisticsManager & Manager, const std::string & WorldPath, std::string && FileName); /* Try to save the player statistics. */ void Save(const StatisticsManager & Manager, const std::string & WorldPath, std::string && FileName); } ================================================ FILE: src/WorldStorage/WSSAnvil.cpp ================================================ #include "Globals.h" #include "WSSAnvil.h" #include "NBTChunkSerializer.h" #include "EnchantmentSerializer.h" #include "NamespaceSerializer.h" #include "json/json.h" #include "OSSupport/GZipFile.h" #include "../World.h" #include "../Item.h" #include "../ItemGrid.h" #include "../StringCompression.h" #include "../SetChunkData.h" #include "../Root.h" #include "../BlockType.h" #include "../JsonUtils.h" #include "../BlockEntities/BannerEntity.h" #include "../BlockEntities/BeaconEntity.h" #include "../BlockEntities/BedEntity.h" #include "../BlockEntities/BrewingstandEntity.h" #include "../BlockEntities/ChestEntity.h" #include "../BlockEntities/CommandBlockEntity.h" #include "../BlockEntities/DispenserEntity.h" #include "../BlockEntities/DropperEntity.h" #include "../BlockEntities/EnchantingTableEntity.h" #include "../BlockEntities/EnderChestEntity.h" #include "../BlockEntities/EndPortalEntity.h" #include "../BlockEntities/FurnaceEntity.h" #include "../BlockEntities/HopperEntity.h" #include "../BlockEntities/JukeboxEntity.h" #include "../BlockEntities/NoteEntity.h" #include "../BlockEntities/SignEntity.h" #include "../BlockEntities/MobHeadEntity.h" #include "../BlockEntities/MobSpawnerEntity.h" #include "../BlockEntities/FlowerPotEntity.h" #include "../Mobs/IncludeAllMonsters.h" #include "../Entities/Boat.h" #include "../Entities/EnderCrystal.h" #include "../Entities/FallingBlock.h" #include "../Entities/Minecart.h" #include "../Entities/Pickup.h" #include "../Entities/ArrowEntity.h" #include "../Entities/SplashPotionEntity.h" #include "../Entities/ThrownEggEntity.h" #include "../Entities/ThrownEnderPearlEntity.h" #include "../Entities/ThrownSnowballEntity.h" #include "../Entities/FireChargeEntity.h" #include "../Entities/GhastFireballEntity.h" #include "../Entities/TNTEntity.h" #include "../Entities/ExpOrb.h" #include "../Entities/HangingEntity.h" #include "../Entities/ItemFrame.h" #include "../Entities/LeashKnot.h" #include "../Entities/Painting.h" #include "../Protocol/MojangAPI.h" #include "../Server.h" #include "../BoundingBox.h" /** If defined, the BlockSkyLight values will be copied over to BlockLight upon chunk saving, thus making skylight visible in Minutor's Lighting mode */ // #define DEBUG_SKYLIGHT /** Maximum number of MCA files that are cached in memory. Since only the header is actually in the memory, this number can be high, but still, each file means an OS FS handle. */ #define MAX_MCA_FILES 32 //////////////////////////////////////////////////////////////////////////////// // cWSSAnvil: cWSSAnvil::cWSSAnvil(cWorld * a_World, int a_CompressionFactor): Super(a_World), m_Compressor(a_CompressionFactor) { // Create a level.dat file for mapping tools, if it doesn't already exist: auto fnam = fmt::format(FMT_STRING("{}{}level.dat"), a_World->GetDataPath(), cFile::PathSeparator()); if (!cFile::Exists(fnam)) { cFastNBTWriter Writer; Writer.BeginCompound("Data"); Writer.AddByte("allowCommands", 1); Writer.AddByte("Difficulty", 2); Writer.AddByte("hardcore", cRoot::Get()->GetServer()->IsHardcore() ? 1 : 0); Writer.AddByte("initialized", 1); Writer.AddByte("MapFeatures", 1); Writer.AddByte("raining", a_World->IsWeatherRain() ? 1 : 0); Writer.AddByte("thundering", a_World->IsWeatherStorm() ? 1 : 0); Writer.AddInt("GameType", static_cast(a_World->GetGameMode())); Writer.AddInt("generatorVersion", 1); Writer.AddInt("SpawnX", a_World->GetSpawnX()); Writer.AddInt("SpawnY", a_World->GetSpawnY()); Writer.AddInt("SpawnZ", a_World->GetSpawnZ()); Writer.AddInt("version", 19133); Writer.AddLong("DayTime", a_World->GetWorldDate().count()); Writer.AddLong("Time", a_World->GetWorldAge().count()); Writer.AddLong("SizeOnDisk", 0); Writer.AddString("generatorName", "default"); Writer.AddString("generatorOptions", ""); Writer.AddString("LevelName", a_World->GetName()); Writer.EndCompound(); Writer.Finish(); GZipFile::Write(fnam, Writer.GetResult()); } } cWSSAnvil::~cWSSAnvil() { cCSLock Lock(m_CS); m_Files.clear(); } bool cWSSAnvil::LoadChunk(const cChunkCoords & a_Chunk) { ContiguousByteBuffer ChunkData; if (!GetChunkData(a_Chunk, ChunkData)) { // The reason for failure is already printed in GetChunkData() return false; } return LoadChunkFromData(a_Chunk, ChunkData); } bool cWSSAnvil::SaveChunk(const cChunkCoords & a_Chunk) { try { if (!SetChunkData(a_Chunk, SaveChunkToData(a_Chunk).GetView())) { LOGWARNING("Cannot store chunk [%d, %d] data", a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ); return false; } } catch (const std::exception & Oops) { LOGWARNING("Cannot serialize chunk [%d, %d] into data: %s", a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ, Oops.what()); return false; } // Everything successful return true; } void cWSSAnvil::ChunkLoadFailed(const cChunkCoords a_ChunkCoords, const AString & a_Reason, const ContiguousByteBufferView a_ChunkDataToSave) { // Construct the filename for offloading: auto OffloadFileName = fmt::format(FMT_STRING("{0}{1}region{1}badchunks"), m_World->GetDataPath(), cFile::PathSeparator()); cFile::CreateFolder(OffloadFileName); auto t = time(nullptr); struct tm stm; #ifdef _MSC_VER localtime_s(&stm, &t); #else localtime_r(&t, &stm); #endif OffloadFileName.append(fmt::format( FMT_STRING("{}ch.{}.{}.{}-{:02d}-{:02d}-{:02d}-{:02d}-{:02d}.dat"), cFile::PathSeparator(), a_ChunkCoords.m_ChunkX, a_ChunkCoords.m_ChunkZ, stm.tm_year + 1900, stm.tm_mon + 1, stm.tm_mday, stm.tm_hour, stm.tm_min, stm.tm_sec )); // Log the warning to console: const int RegionX = FAST_FLOOR_DIV(a_ChunkCoords.m_ChunkX, 32); const int RegionZ = FAST_FLOOR_DIV(a_ChunkCoords.m_ChunkZ, 32); auto Info = fmt::format( FMT_STRING("Loading chunk {} for world {} from file r.{}.{}.mca failed: {} Offloading old chunk data to file {} and regenerating chunk."), a_ChunkCoords, m_World->GetName(), RegionX, RegionZ, a_Reason, OffloadFileName ); LOGWARNING("%s", Info); // Write the data: cFile f; if (!f.Open(OffloadFileName, cFile::fmWrite)) { LOGWARNING("Cannot open file %s for writing! Old chunk data is lost.", OffloadFileName); return; } f.Write(a_ChunkDataToSave.data(), a_ChunkDataToSave.size()); f.Close(); // Write a description file: if (!f.Open(OffloadFileName + ".info", cFile::fmWrite)) { LOGWARNING("Cannot open file %s.info for writing! The information about the failed chunk will not be written.", OffloadFileName); return; } f.Write(Info.c_str(), Info.size()); f.Close(); } bool cWSSAnvil::GetChunkData(const cChunkCoords & a_Chunk, ContiguousByteBuffer & a_Data) { cCSLock Lock(m_CS); auto File = LoadMCAFile(a_Chunk); if (File == nullptr) { return false; } return File->GetChunkData(a_Chunk, a_Data); } bool cWSSAnvil::SetChunkData(const cChunkCoords & a_Chunk, const ContiguousByteBufferView a_Data) { cCSLock Lock(m_CS); auto File = LoadMCAFile(a_Chunk); if (File == nullptr) { return false; } return File->SetChunkData(a_Chunk, a_Data); } std::shared_ptr cWSSAnvil::LoadMCAFile(const cChunkCoords & a_Chunk) { // ASSUME m_CS is locked ASSERT(m_CS.IsLocked()); const int RegionX = FAST_FLOOR_DIV(a_Chunk.m_ChunkX, 32); const int RegionZ = FAST_FLOOR_DIV(a_Chunk.m_ChunkZ, 32); ASSERT(a_Chunk.m_ChunkX - RegionX * 32 >= 0); ASSERT(a_Chunk.m_ChunkZ - RegionZ * 32 >= 0); ASSERT(a_Chunk.m_ChunkX - RegionX * 32 < 32); ASSERT(a_Chunk.m_ChunkZ - RegionZ * 32 < 32); // Is it already cached? for (auto itr = m_Files.begin(); itr != m_Files.end(); ++itr) { if (((*itr) != nullptr) && ((*itr)->GetRegionX() == RegionX) && ((*itr)->GetRegionZ() == RegionZ)) { // Move the file to front and return it: auto f = *itr; if (itr != m_Files.begin()) { m_Files.erase(itr); m_Files.push_front(f); } return f; } } // Load it anew: auto FileName = fmt::format(FMT_STRING("{}{}region"), m_World->GetDataPath(), cFile::PathSeparator()); cFile::CreateFolder(FileName); FileName.append(fmt::format(FMT_STRING("/r.{}.{}.mca"), RegionX, RegionZ)); auto f = std::make_shared(*this, FileName, RegionX, RegionZ); if (f == nullptr) { return nullptr; } m_Files.push_front(f); // If there are too many MCA files cached, delete the last one used: if (m_Files.size() > MAX_MCA_FILES) { m_Files.pop_back(); } return f; } bool cWSSAnvil::LoadChunkFromData(const cChunkCoords & a_Chunk, const ContiguousByteBufferView a_Data) { try { const auto Extracted = m_Extractor.ExtractZLib(a_Data); cParsedNBT NBT(Extracted.GetView()); if (!NBT.IsValid()) { // NBT Parsing failed: throw std::runtime_error(fmt::format("NBT parsing failed. {} at position {}.", NBT.GetErrorCode().message(), NBT.GetErrorPos())); } // Load the data from NBT: return LoadChunkFromNBT(a_Chunk, NBT, a_Data); } catch (const std::exception & Oops) { ChunkLoadFailed(a_Chunk, Oops.what(), a_Data); return false; } } Compression::Result cWSSAnvil::SaveChunkToData(const cChunkCoords & a_Chunk) { cFastNBTWriter Writer; NBTChunkSerializer::Serialize(*m_World, a_Chunk, Writer); Writer.Finish(); return m_Compressor.CompressZLib(Writer.GetResult()); } bool cWSSAnvil::LoadChunkFromNBT(const cChunkCoords & a_Chunk, const cParsedNBT & a_NBT, const ContiguousByteBufferView a_RawChunkData) { struct SetChunkData Data(a_Chunk); // Load the blockdata, blocklight and skylight: int Level = a_NBT.FindChildByName(0, "Level"); if (Level < 0) { ChunkLoadFailed(a_Chunk, "Missing NBT tag: Level", a_RawChunkData); return false; } int Sections = a_NBT.FindChildByName(Level, "Sections"); if ((Sections < 0) || (a_NBT.GetType(Sections) != TAG_List)) { ChunkLoadFailed(a_Chunk, "Missing NBT tag: Sections", a_RawChunkData); return false; } eTagType SectionsType = a_NBT.GetChildrenType(Sections); if ((SectionsType != TAG_Compound) && (SectionsType != TAG_End)) { ChunkLoadFailed(a_Chunk, "NBT tag has wrong type: Sections", a_RawChunkData); return false; } for (int Child = a_NBT.GetFirstChild(Sections); Child >= 0; Child = a_NBT.GetNextSibling(Child)) { const int SectionYTag = a_NBT.FindChildByName(Child, "Y"); if ((SectionYTag < 0) || (a_NBT.GetType(SectionYTag) != TAG_Byte)) { ChunkLoadFailed(a_Chunk, "NBT tag missing or has wrong: Y", a_RawChunkData); return false; } const int Y = a_NBT.GetByte(SectionYTag); if ((Y < 0) || (Y > static_cast(cChunkDef::NumSections - 1))) { ChunkLoadFailed(a_Chunk, "NBT tag exceeds chunk bounds: Y", a_RawChunkData); return false; } const auto BlockData = GetSectionData(a_NBT, Child, "Blocks", ChunkBlockData::SectionBlockCount), MetaData = GetSectionData(a_NBT, Child, "Data", ChunkBlockData::SectionMetaCount), BlockLightData = GetSectionData(a_NBT, Child, "BlockLight", ChunkLightData::SectionLightCount), SkyLightData = GetSectionData(a_NBT, Child, "SkyLight", ChunkLightData::SectionLightCount); if ((BlockData != nullptr) && (MetaData != nullptr) && (SkyLightData != nullptr) && (BlockLightData != nullptr)) { Data.BlockData.SetSection(*reinterpret_cast(BlockData), *reinterpret_cast(MetaData), static_cast(Y)); Data.LightData.SetSection(*reinterpret_cast(BlockLightData), *reinterpret_cast(SkyLightData), static_cast(Y)); } else { ChunkLoadFailed(a_Chunk, "Missing chunk block/light data", a_RawChunkData); return false; } } // for itr - LevelSections[] // Load the biomes from NBT, if present and valid: if (!LoadBiomeMapFromNBT(Data.BiomeMap, a_NBT, a_NBT.FindChildByName(Level, "Biomes"))) { ChunkLoadFailed(a_Chunk, "Missing chunk biome data", a_RawChunkData); return false; } // Load the Height map, if it fails, recalculate it: if (!LoadHeightMapFromNBT(Data.HeightMap, a_NBT, a_NBT.FindChildByName(Level, "HeightMap"))) { Data.UpdateHeightMap(); } // Load the entities from NBT: LoadEntitiesFromNBT (Data.Entities, a_NBT, a_NBT.FindChildByName(Level, "Entities")); LoadBlockEntitiesFromNBT(Data.BlockEntities, a_NBT, a_NBT.FindChildByName(Level, "TileEntities"), Data.BlockData); Data.IsLightValid = (a_NBT.FindChildByName(Level, "MCSIsLightValid") > 0); /* // Uncomment this block for really cool stuff :) // DEBUG magic: Invert the underground, so that we can see the MC generator in action :) bool ShouldInvert[cChunkDef::Width * cChunkDef::Width]; memset(ShouldInvert, 0, sizeof(ShouldInvert)); for (int y = cChunkDef::Height - 1; y >= 0; y--) { for (int x = 0; x < cChunkDef::Width; x++) for (int z = 0; z < cChunkDef::Width; z++) { const auto Index = cChunkDef::MakeIndex(x, y, z); if (ShouldInvert[x + cChunkDef::Width * z]) { BlockTypes[Index] = (BlockTypes[Index] == E_BLOCK_AIR) ? E_BLOCK_STONE : E_BLOCK_AIR; } else { switch (BlockTypes[Index]) { case E_BLOCK_AIR: case E_BLOCK_LEAVES: case E_BLOCK_NEW_LEAVES: { // nothing needed break; } default: { ShouldInvert[x + cChunkDef::Width * z] = true; } } BlockTypes[Index] = E_BLOCK_AIR; } } } // for y //*/ m_World->QueueSetChunkData(std::move(Data)); return true; } bool cWSSAnvil::LoadBiomeMapFromNBT(cChunkDef::BiomeMap & a_BiomeMap, const cParsedNBT & a_NBT, const int a_TagIdx) { if ( (a_TagIdx < 0) || (a_NBT.GetType(a_TagIdx) != TAG_ByteArray) || (a_NBT.GetDataLength(a_TagIdx) != std::size(a_BiomeMap)) ) { return false; } const auto * const BiomeData = a_NBT.GetData(a_TagIdx); for (size_t i = 0; i < ARRAYCOUNT(a_BiomeMap); i++) { if (BiomeData[i] > std::byte(EMCSBiome::biMaxVariantBiome)) { // Unassigned biomes: return false; } a_BiomeMap[i] = static_cast(BiomeData[i]); } return true; } bool cWSSAnvil::LoadHeightMapFromNBT(cChunkDef::HeightMap & a_HeightMap, const cParsedNBT & a_NBT, const int a_TagIdx) { if ( (a_TagIdx < 0) || (a_NBT.GetType(a_TagIdx) != TAG_IntArray) || (a_NBT.GetDataLength(a_TagIdx) != (4 * std::size(a_HeightMap))) ) { return false; } const auto * const HeightData = a_NBT.GetData(a_TagIdx); for (int RelZ = 0; RelZ < cChunkDef::Width; RelZ++) { for (int RelX = 0; RelX < cChunkDef::Width; RelX++) { const int Index = 4 * (RelX + RelZ * cChunkDef::Width); const int Height = NetworkBufToHost(HeightData + Index); if (Height > std::numeric_limits::max()) { // Invalid data: return false; } cChunkDef::SetHeight(a_HeightMap, RelX, RelZ, static_cast(Height)); } } return true; } void cWSSAnvil::LoadEntitiesFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx) { if ((a_TagIdx < 0) || (a_NBT.GetType(a_TagIdx) != TAG_List)) { return; } for (int Child = a_NBT.GetFirstChild(a_TagIdx); Child != -1; Child = a_NBT.GetNextSibling(Child)) { if (a_NBT.GetType(Child) != TAG_Compound) { continue; } int sID = a_NBT.FindChildByName(Child, "id"); if (sID < 0) { continue; } try { LoadEntityFromNBT(a_Entities, a_NBT, Child, a_NBT.GetStringView(sID)); } catch (...) { continue; } } // for Child - a_NBT[] } void cWSSAnvil::LoadBlockEntitiesFromNBT(cBlockEntities & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx, const ChunkBlockData & a_BlockData) { if ((a_TagIdx < 0) || (a_NBT.GetType(a_TagIdx) != TAG_List)) { return; } for (int Child = a_NBT.GetFirstChild(a_TagIdx); Child != -1; Child = a_NBT.GetNextSibling(Child)) { if (a_NBT.GetType(Child) != TAG_Compound) { continue; } // Get the BlockEntity's position Vector3i absPos; if (!GetBlockEntityNBTPos(a_NBT, Child, absPos) || (absPos.y < 0) || (absPos.y >= cChunkDef::Height)) { LOGWARNING("Bad block entity, missing the coords. Will be ignored."); continue; } const auto relPos = cChunkDef::AbsoluteToRelative(absPos); // Load the proper BlockEntity type based on the block type: const auto BlockType = a_BlockData.GetBlock(relPos); const auto BlockMeta = a_BlockData.GetMeta(relPos); OwnedBlockEntity Entity; try { Entity = LoadBlockEntityFromNBT(a_NBT, Child, absPos, BlockType, BlockMeta); } catch (...) { continue; } // TODO: exception-ify the failure case if (Entity == nullptr) { continue; } // Index computed before Entity moved. const auto Index = cChunkDef::MakeIndex(Entity->GetRelPos()); // Add the BlockEntity to the loaded data: a_BlockEntities.emplace(Index, std::move(Entity)); } // for Child - tag children } OwnedBlockEntity cWSSAnvil::LoadBlockEntityFromNBT(const cParsedNBT & a_NBT, int a_Tag, Vector3i a_Pos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) { ASSERT((a_Pos.y >= 0) && (a_Pos.y < cChunkDef::Height)); // Load the specific BlockEntity type: switch (a_BlockType) { // Banners: case E_BLOCK_STANDING_BANNER: case E_BLOCK_WALL_BANNER: return LoadBannerFromNBT (a_NBT, a_Tag, a_BlockType, a_BlockMeta, a_Pos); // Others: case E_BLOCK_BEACON: return LoadBeaconFromNBT (a_NBT, a_Tag, a_BlockType, a_BlockMeta, a_Pos); case E_BLOCK_BED: return LoadBedFromNBT (a_NBT, a_Tag, a_BlockType, a_BlockMeta, a_Pos); case E_BLOCK_BREWING_STAND: return LoadBrewingstandFromNBT (a_NBT, a_Tag, a_BlockType, a_BlockMeta, a_Pos); case E_BLOCK_CHEST: return LoadChestFromNBT (a_NBT, a_Tag, a_BlockType, a_BlockMeta, a_Pos); case E_BLOCK_COMMAND_BLOCK: return LoadCommandBlockFromNBT (a_NBT, a_Tag, a_BlockType, a_BlockMeta, a_Pos); case E_BLOCK_DISPENSER: return LoadDispenserFromNBT (a_NBT, a_Tag, a_BlockType, a_BlockMeta, a_Pos); case E_BLOCK_DROPPER: return LoadDropperFromNBT (a_NBT, a_Tag, a_BlockType, a_BlockMeta, a_Pos); case E_BLOCK_ENCHANTMENT_TABLE: return LoadEnchantingTableFromNBT (a_NBT, a_Tag, a_BlockType, a_BlockMeta, a_Pos); case E_BLOCK_ENDER_CHEST: return LoadEnderChestFromNBT (a_NBT, a_Tag, a_BlockType, a_BlockMeta, a_Pos); case E_BLOCK_END_PORTAL: return LoadEndPortalFromNBT (a_NBT, a_Tag, a_BlockType, a_BlockMeta, a_Pos); case E_BLOCK_FLOWER_POT: return LoadFlowerPotFromNBT (a_NBT, a_Tag, a_BlockType, a_BlockMeta, a_Pos); case E_BLOCK_FURNACE: return LoadFurnaceFromNBT (a_NBT, a_Tag, a_BlockType, a_BlockMeta, a_Pos); case E_BLOCK_HEAD: return LoadMobHeadFromNBT (a_NBT, a_Tag, a_BlockType, a_BlockMeta, a_Pos); case E_BLOCK_HOPPER: return LoadHopperFromNBT (a_NBT, a_Tag, a_BlockType, a_BlockMeta, a_Pos); case E_BLOCK_JUKEBOX: return LoadJukeboxFromNBT (a_NBT, a_Tag, a_BlockType, a_BlockMeta, a_Pos); case E_BLOCK_LIT_FURNACE: return LoadFurnaceFromNBT (a_NBT, a_Tag, a_BlockType, a_BlockMeta, a_Pos); case E_BLOCK_MOB_SPAWNER: return LoadMobSpawnerFromNBT (a_NBT, a_Tag, a_BlockType, a_BlockMeta, a_Pos); case E_BLOCK_NOTE_BLOCK: return LoadNoteBlockFromNBT (a_NBT, a_Tag, a_BlockType, a_BlockMeta, a_Pos); case E_BLOCK_SIGN_POST: return LoadSignFromNBT (a_NBT, a_Tag, a_BlockType, a_BlockMeta, a_Pos); case E_BLOCK_TRAPPED_CHEST: return LoadChestFromNBT (a_NBT, a_Tag, a_BlockType, a_BlockMeta, a_Pos); case E_BLOCK_WALLSIGN: return LoadSignFromNBT (a_NBT, a_Tag, a_BlockType, a_BlockMeta, a_Pos); default: { // All the other blocktypes should have no entities assigned to them. Report an error: // Get the "id" tag: int TagID = a_NBT.FindChildByName(a_Tag, "id"); FLOGINFO("WorldLoader({0}): Block entity mismatch: block type {1} ({2}), type \"{3}\", at {4}; the entity will be lost.", m_World->GetName(), ItemTypeToString(a_BlockType), a_BlockType, (TagID >= 0) ? a_NBT.GetStringView(TagID) : "unknown", a_Pos ); return nullptr; } } } bool cWSSAnvil::LoadItemFromNBT(cItem & a_Item, const cParsedNBT & a_NBT, int a_TagIdx) { int Type = a_NBT.FindChildByName(a_TagIdx, "id"); if (Type <= 0) { return false; } if (a_NBT.GetType(Type) == TAG_String) { if (!StringToItem(a_NBT.GetString(Type), a_Item)) { // Can't resolve item type return false; } } else if (a_NBT.GetType(Type) == TAG_Short) { a_Item.m_ItemType = a_NBT.GetShort(Type); } else { return false; } if (a_Item.m_ItemType < 0) { a_Item.Empty(); return true; } int Damage = a_NBT.FindChildByName(a_TagIdx, "Damage"); if ((Damage > 0) && (a_NBT.GetType(Damage) == TAG_Short)) { a_Item.m_ItemDamage = a_NBT.GetShort(Damage); } int Count = a_NBT.FindChildByName(a_TagIdx, "Count"); if ((Count > 0) && (a_NBT.GetType(Count) == TAG_Byte)) { a_Item.m_ItemCount = static_cast(a_NBT.GetByte(Count)); } // Find the "tag" tag, used for enchantments and other extra data int TagTag = a_NBT.FindChildByName(a_TagIdx, "tag"); if (TagTag <= 0) { // No extra data return true; } // Load repair cost: int RepairCost = a_NBT.FindChildByName(TagTag, "RepairCost"); if ((RepairCost > 0) && (a_NBT.GetType(RepairCost) == TAG_Int)) { a_Item.m_RepairCost = a_NBT.GetInt(RepairCost); } // Load display name: int DisplayTag = a_NBT.FindChildByName(TagTag, "display"); if (DisplayTag > 0) { int DisplayName = a_NBT.FindChildByName(DisplayTag, "Name"); if ((DisplayName > 0) && (a_NBT.GetType(DisplayName) == TAG_String)) { a_Item.m_CustomName = a_NBT.GetString(DisplayName); } int Lore = a_NBT.FindChildByName(DisplayTag, "Lore"); if ((Lore > 0) && (a_NBT.GetType(Lore) == TAG_String)) { // Legacy string lore a_Item.m_LoreTable = StringSplit(a_NBT.GetString(Lore), "`"); } else if ((Lore > 0) && (a_NBT.GetType(Lore) == TAG_List)) { // Lore table a_Item.m_LoreTable.clear(); for (int loretag = a_NBT.GetFirstChild(Lore); loretag >= 0; loretag = a_NBT.GetNextSibling(loretag)) // Loop through array of strings { a_Item.m_LoreTable.push_back(a_NBT.GetString(loretag)); } } } // Load enchantments: const char * EnchName = (a_Item.m_ItemType == E_ITEM_BOOK) ? "StoredEnchantments" : "ench"; int EnchTag = a_NBT.FindChildByName(TagTag, EnchName); if (EnchTag > 0) { EnchantmentSerializer::ParseFromNBT(a_Item.m_Enchantments, a_NBT, EnchTag); } // Load firework data: int FireworksTag = a_NBT.FindChildByName(TagTag, ((a_Item.m_ItemType == E_ITEM_FIREWORK_STAR) ? "Explosion" : "Fireworks")); if (FireworksTag > 0) { cFireworkItem::ParseFromNBT(a_Item.m_FireworkItem, a_NBT, FireworksTag, static_cast(a_Item.m_ItemType)); } return true; } void cWSSAnvil::LoadItemGridFromNBT(cItemGrid & a_ItemGrid, const cParsedNBT & a_NBT, int a_ItemsTagIdx, int a_SlotOffset) { int NumSlots = a_ItemGrid.GetNumSlots(); for (int Child = a_NBT.GetFirstChild(a_ItemsTagIdx); Child != -1; Child = a_NBT.GetNextSibling(Child)) { int SlotTag = a_NBT.FindChildByName(Child, "Slot"); if ((SlotTag < 0) || (a_NBT.GetType(SlotTag) != TAG_Byte)) { continue; } int SlotNum = static_cast(a_NBT.GetByte(SlotTag)) - a_SlotOffset; if ((SlotNum < 0) || (SlotNum >= NumSlots)) { // SlotNum outside of the range continue; } cItem Item; if (LoadItemFromNBT(Item, a_NBT, Child)) { a_ItemGrid.SetSlot(SlotNum, Item); } } // for itr - ItemDefs[] } AString cWSSAnvil::DecodeSignLine(const AString & a_Line) { if (a_Line.empty()) { return AString(); } if (a_Line[0] != '{') { return a_Line; } // Try to parse the JSON: Json::Value root; if (!JsonUtils::ParseString(a_Line, root) || !root.isObject()) { return a_Line; } const auto & txt = root["text"]; if (txt.isString()) { return txt.asString(); } return a_Line; } bool cWSSAnvil::CheckBlockEntityType(const cParsedNBT & a_NBT, int a_TagIdx, const AStringVector & a_ExpectedTypes, Vector3i a_Pos) { // Check if the given tag is a compound: if (a_NBT.GetType(a_TagIdx) != TAG_Compound) { return false; } // Get the "id" tag: int TagID = a_NBT.FindChildByName(a_TagIdx, "id"); if (TagID < 0) { return false; } // Check if the "id" tag is a string: if (a_NBT.GetType(TagID) != eTagType::TAG_String) { return false; } // Compare the value: for (const auto & et: a_ExpectedTypes) { if (a_NBT.GetStringView(TagID) == et) { return true; } } // Expectation not met, output an error into the log: AString expectedTypes; for (const auto & et : a_ExpectedTypes) { expectedTypes.append(", \""); expectedTypes.append(et); expectedTypes.push_back('\"'); } FLOGWARNING("Block entity type mismatch: exp {0}, got \"{1}\". The block entity at {2} will lose all its properties.", expectedTypes.c_str() + 2, // Skip the first ", " that is extra in the string a_NBT.GetStringView(TagID), a_Pos ); return false; } OwnedBlockEntity cWSSAnvil::LoadBannerFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos) { static const AStringVector expectedTypes({"Banner", "minecraft:standingbanner","minecraft:wallbanner"}); if (!CheckBlockEntityType(a_NBT, a_TagIdx, expectedTypes, a_Pos)) { return nullptr; } unsigned char Color = 15; AString CustomName; // Reads base color from NBT int CurrentLine = a_NBT.FindChildByName(a_TagIdx, "Base"); if (CurrentLine >= 0) { Color = static_cast(a_NBT.GetInt(CurrentLine)); } CurrentLine = a_NBT.FindChildByName(a_TagIdx, "CustomName"); if ((CurrentLine >= 0) && (a_NBT.GetType(CurrentLine) == TAG_String)) { CustomName = a_NBT.GetString(CurrentLine); } return std::make_unique(a_BlockType, a_BlockMeta, a_Pos, m_World, Color, CustomName); } OwnedBlockEntity cWSSAnvil::LoadBeaconFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos) { // Check if the data has a proper type: static const AStringVector expectedTypes({"Beacon", "minecraft:beacon"}); if (!CheckBlockEntityType(a_NBT, a_TagIdx, expectedTypes, a_Pos)) { return nullptr; } auto Beacon = std::make_unique(a_BlockType, a_BlockMeta, a_Pos, m_World); int CurrentLine = a_NBT.FindChildByName(a_TagIdx, "Levels"); if (CurrentLine >= 0) { Beacon->SetBeaconLevel(static_cast(a_NBT.GetInt(CurrentLine))); } CurrentLine = a_NBT.FindChildByName(a_TagIdx, "Primary"); if (CurrentLine >= 0) { Beacon->SetPrimaryEffect(static_cast(a_NBT.GetInt(CurrentLine))); } CurrentLine = a_NBT.FindChildByName(a_TagIdx, "Secondary"); if (CurrentLine >= 0) { Beacon->SetSecondaryEffect(static_cast(a_NBT.GetInt(CurrentLine))); } // We are better than mojang, we load / save the beacon inventory! int Items = a_NBT.FindChildByName(a_TagIdx, "Items"); if ((Items >= 0) && (a_NBT.GetType(Items) == TAG_List)) { LoadItemGridFromNBT(Beacon->GetContents(), a_NBT, Items); } return Beacon; } OwnedBlockEntity cWSSAnvil::LoadBedFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos) { // Check if the data has a proper type: static const AStringVector expectedTypes({ "Bed", "minecraft:bed" }); if (!CheckBlockEntityType(a_NBT, a_TagIdx, expectedTypes, a_Pos)) { return nullptr; } // Use color red as default short Color = E_META_WOOL_RED; int ColorIDx = a_NBT.FindChildByName(a_TagIdx, "color"); if (ColorIDx >= 0) { Color = static_cast(a_NBT.GetInt(ColorIDx)); } return std::make_unique(a_BlockType, a_BlockMeta, a_Pos, m_World, Color); } OwnedBlockEntity cWSSAnvil::LoadBrewingstandFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos) { // Check if the data has a proper type: static const AStringVector expectedTypes({ "Brewingstand", "minecraft:brewing_stand" }); if (!CheckBlockEntityType(a_NBT, a_TagIdx, expectedTypes, a_Pos)) { return nullptr; } int Items = a_NBT.FindChildByName(a_TagIdx, "Items"); if ((Items < 0) || (a_NBT.GetType(Items) != TAG_List)) { return nullptr; // Make it an empty brewingstand - the chunk loader will provide an empty cBrewingstandEntity for this } auto Brewingstand = std::make_unique(a_BlockType, a_BlockMeta, a_Pos, m_World); // Fuel has to be loaded at first, because of slot events: int Fuel = a_NBT.FindChildByName(a_TagIdx, "Fuel"); if (Fuel >= 0) { Int16 tb = a_NBT.GetShort(Fuel); Brewingstand->SetRemainingFuel(tb); } // Load slots: for (int Child = a_NBT.GetFirstChild(Items); Child != -1; Child = a_NBT.GetNextSibling(Child)) { int Slot = a_NBT.FindChildByName(Child, "Slot"); if ((Slot < 0) || (a_NBT.GetType(Slot) != TAG_Byte)) { continue; } cItem Item; if (LoadItemFromNBT(Item, a_NBT, Child)) { Brewingstand->SetSlot(a_NBT.GetByte(Slot), Item); } } // for itr - ItemDefs[] // Load brewing time: int BrewTime = a_NBT.FindChildByName(a_TagIdx, "BrewTime"); if (BrewTime >= 0) { Int16 tb = a_NBT.GetShort(BrewTime); Brewingstand->SetTimeBrewed(tb); } // Restart brewing: Brewingstand->LoadRecipes(); Brewingstand->ContinueBrewing(); return Brewingstand; } OwnedBlockEntity cWSSAnvil::LoadChestFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos) { // Check if the data has a proper type: // Note that older Cuberite code used "TrappedChest" for trapped chests; new code mimics vanilla and uses "Chest" throughout, but we allow migration here: static const AStringVector expectedTypes({ "Chest", "TrappedChest", "minecraft:chest" }); if (!CheckBlockEntityType(a_NBT, a_TagIdx, expectedTypes, a_Pos)) { return nullptr; } int Items = a_NBT.FindChildByName(a_TagIdx, "Items"); if ((Items < 0) || (a_NBT.GetType(Items) != TAG_List)) { return nullptr; // Make it an empty chest - the chunk loader will provide an empty cChestEntity for this } auto Chest = std::make_unique(a_BlockType, a_BlockMeta, a_Pos, m_World); LoadItemGridFromNBT(Chest->GetContents(), a_NBT, Items); return Chest; } OwnedBlockEntity cWSSAnvil::LoadCommandBlockFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos) { // Check if the data has a proper type: static const AStringVector expectedTypes({ "Control", "minecraft:command_block" }); if (!CheckBlockEntityType(a_NBT, a_TagIdx, expectedTypes, a_Pos)) { return nullptr; } auto CmdBlock = std::make_unique(a_BlockType, a_BlockMeta, a_Pos, m_World); int currentLine = a_NBT.FindChildByName(a_TagIdx, "Command"); if (currentLine >= 0) { CmdBlock->SetCommand(a_NBT.GetString(currentLine)); } currentLine = a_NBT.FindChildByName(a_TagIdx, "SuccessCount"); if (currentLine >= 0) { CmdBlock->SetResult(static_cast(a_NBT.GetInt(currentLine))); } currentLine = a_NBT.FindChildByName(a_TagIdx, "LastOutput"); if (currentLine >= 0) { CmdBlock->SetLastOutput(a_NBT.GetString(currentLine)); } // TODO 2014-01-18 xdot: Figure out what TrackOutput is and parse it. return CmdBlock; } OwnedBlockEntity cWSSAnvil::LoadDispenserFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos) { // Check if the data has a proper type: static const AStringVector expectedTypes({ "Trap", "minecraft:dispenser" }); if (!CheckBlockEntityType(a_NBT, a_TagIdx, expectedTypes, a_Pos)) { return nullptr; } int Items = a_NBT.FindChildByName(a_TagIdx, "Items"); if ((Items < 0) || (a_NBT.GetType(Items) != TAG_List)) { return nullptr; // Make it an empty dispenser - the chunk loader will provide an empty cDispenserEntity for this } auto Dispenser = std::make_unique(a_BlockType, a_BlockMeta, a_Pos, m_World); LoadItemGridFromNBT(Dispenser->GetContents(), a_NBT, Items); return Dispenser; } OwnedBlockEntity cWSSAnvil::LoadDropperFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos) { // Check if the data has a proper type: static const AStringVector expectedTypes({ "Dropper", "minecraft:dropper" }); if (!CheckBlockEntityType(a_NBT, a_TagIdx, expectedTypes, a_Pos)) { return nullptr; } int Items = a_NBT.FindChildByName(a_TagIdx, "Items"); if ((Items < 0) || (a_NBT.GetType(Items) != TAG_List)) { return nullptr; // Make it an empty dropper - the chunk loader will provide an empty cDropperEntity for this } auto Dropper = std::make_unique(a_BlockType, a_BlockMeta, a_Pos, m_World); LoadItemGridFromNBT(Dropper->GetContents(), a_NBT, Items); return Dropper; } OwnedBlockEntity cWSSAnvil::LoadEnchantingTableFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos) { // Check if the data has a proper type: static const AStringVector expectedTypes({ "EnchantingTable", "minecraft:enchanting_table" }); if (!CheckBlockEntityType(a_NBT, a_TagIdx, expectedTypes, a_Pos)) { return nullptr; } AString CustomName; int currentLine = a_NBT.FindChildByName(a_TagIdx, "CustomName"); if (currentLine >= 0) { if (a_NBT.GetType(currentLine) == TAG_String) { CustomName = a_NBT.GetString(currentLine); } } return std::make_unique(a_BlockType, a_BlockMeta, a_Pos, m_World, CustomName); } OwnedBlockEntity cWSSAnvil::LoadEnderChestFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos) { // Check if the data has a proper type: static const AStringVector expectedTypes({ "EnderChest", "minecraft:ender_chest" }); if (!CheckBlockEntityType(a_NBT, a_TagIdx, expectedTypes, a_Pos)) { return nullptr; } return std::make_unique(a_BlockType, a_BlockMeta, a_Pos, m_World); } OwnedBlockEntity cWSSAnvil::LoadEndPortalFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos) { // Check if the data has a proper type: static const AStringVector expectedTypes({ "EndPortal", "minecraft:end_portal" }); if (!CheckBlockEntityType(a_NBT, a_TagIdx, expectedTypes, a_Pos)) { return nullptr; } return std::make_unique(a_BlockType, a_BlockMeta, a_Pos, m_World); } OwnedBlockEntity cWSSAnvil::LoadFlowerPotFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos) { // Check if the data has a proper type: static const AStringVector expectedTypes({ "FlowerPot", "minecraft:flower_pot" }); if (!CheckBlockEntityType(a_NBT, a_TagIdx, expectedTypes, a_Pos)) { return nullptr; } auto FlowerPot = std::make_unique(a_BlockType, a_BlockMeta, a_Pos, m_World); cItem Item; int currentLine = a_NBT.FindChildByName(a_TagIdx, "Item"); if (currentLine >= 0) { if (a_NBT.GetType(currentLine) == TAG_String) { StringToItem(a_NBT.GetString(currentLine), Item); } else if (a_NBT.GetType(currentLine) == TAG_Int) { Item.m_ItemType = static_cast(a_NBT.GetInt(currentLine)); } } currentLine = a_NBT.FindChildByName(a_TagIdx, "Data"); if ((currentLine >= 0) && (a_NBT.GetType(currentLine) == TAG_Int)) { Item.m_ItemDamage = static_cast(a_NBT.GetInt(currentLine)); } FlowerPot->SetItem(Item); return FlowerPot; } OwnedBlockEntity cWSSAnvil::LoadFurnaceFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos) { // Check if the data has a proper type: static const AStringVector expectedTypes({ "Furnace", "minecraft:furnace" }); if (!CheckBlockEntityType(a_NBT, a_TagIdx, expectedTypes, a_Pos)) { return nullptr; } int Items = a_NBT.FindChildByName(a_TagIdx, "Items"); if ((Items < 0) || (a_NBT.GetType(Items) != TAG_List)) { return nullptr; // Make it an empty furnace - the chunk loader will provide an empty cFurnaceEntity for this } auto Furnace = std::make_unique(a_BlockType, a_BlockMeta, a_Pos, m_World); Furnace->SetLoading(true); // Load slots: for (int Child = a_NBT.GetFirstChild(Items); Child != -1; Child = a_NBT.GetNextSibling(Child)) { int Slot = a_NBT.FindChildByName(Child, "Slot"); if ((Slot < 0) || (a_NBT.GetType(Slot) != TAG_Byte)) { continue; } cItem Item; if (LoadItemFromNBT(Item, a_NBT, Child)) { Furnace->SetSlot(a_NBT.GetByte(Slot), Item); } } // for itr - ItemDefs[] // Load burn time: int BurnTime = a_NBT.FindChildByName(a_TagIdx, "BurnTime"); if (BurnTime >= 0) { Int16 bt = a_NBT.GetShort(BurnTime); // Anvil doesn't store the time that the fuel can burn. We simply "reset" the current value to be the 100% Furnace->SetBurnTimes(bt, 0); } // Load cook time: int CookTime = a_NBT.FindChildByName(a_TagIdx, "CookTime"); if (CookTime >= 0) { Int16 ct = a_NBT.GetShort(CookTime); // Anvil doesn't store the time that an item takes to cook. We simply use the default - 10 seconds (200 ticks) Furnace->SetCookTimes(200, ct); } // Restart cooking: Furnace->ContinueCooking(); Furnace->SetLoading(false); return Furnace; } OwnedBlockEntity cWSSAnvil::LoadHopperFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos) { // Check if the data has a proper type: static const AStringVector expectedTypes({ "Hopper", "minecraft:hopper" }); if (!CheckBlockEntityType(a_NBT, a_TagIdx, expectedTypes, a_Pos)) { return nullptr; } int Items = a_NBT.FindChildByName(a_TagIdx, "Items"); if ((Items < 0) || (a_NBT.GetType(Items) != TAG_List)) { return nullptr; // Make it an empty hopper - the chunk loader will provide an empty cHopperEntity for this } auto Hopper = std::make_unique(a_BlockType, a_BlockMeta, a_Pos, m_World); LoadItemGridFromNBT(Hopper->GetContents(), a_NBT, Items); return Hopper; } OwnedBlockEntity cWSSAnvil::LoadJukeboxFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos) { // Check if the data has a proper type: static const AStringVector expectedTypes({ "RecordPlayer", "minecraft:jukebox" }); if (!CheckBlockEntityType(a_NBT, a_TagIdx, expectedTypes, a_Pos)) { return nullptr; } auto Jukebox = std::make_unique(a_BlockType, a_BlockMeta, a_Pos, m_World); int Record = a_NBT.FindChildByName(a_TagIdx, "Record"); if (Record >= 0) { Jukebox->SetRecord(a_NBT.GetInt(Record)); } return Jukebox; } OwnedBlockEntity cWSSAnvil::LoadMobSpawnerFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos) { // Check if the data has a proper type: static const AStringVector expectedTypes({ "MobSpawner", "minecraft:mob_spawner" }); if (!CheckBlockEntityType(a_NBT, a_TagIdx, expectedTypes, a_Pos)) { return nullptr; } auto MobSpawner = std::make_unique(a_BlockType, a_BlockMeta, a_Pos, m_World); // Load entity type int Type = a_NBT.FindChildByName(a_TagIdx, "EntityId"); if ((Type >= 0) && (a_NBT.GetType(Type) == TAG_String)) { const auto StatInfo = NamespaceSerializer::SplitNamespacedID(a_NBT.GetStringView(Type)); if (StatInfo.first == NamespaceSerializer::Namespace::Unknown) { return nullptr; } eMonsterType MonsterType = NamespaceSerializer::ToMonsterType(StatInfo.second); if (MonsterType != eMonsterType::mtInvalidType) { MobSpawner->SetEntity(MonsterType); } } // Load spawn count: int CurrentLine = a_NBT.FindChildByName(a_TagIdx, "SpawnCount"); if ((CurrentLine >= 0) && (a_NBT.GetType(CurrentLine) == TAG_Short)) { MobSpawner->SetSpawnCount(a_NBT.GetShort(CurrentLine)); } // Load spawn range: CurrentLine = a_NBT.FindChildByName(a_TagIdx, "SpawnRange"); if ((CurrentLine >= 0) && (a_NBT.GetType(CurrentLine) == TAG_Short)) { MobSpawner->SetSpawnRange(a_NBT.GetShort(CurrentLine)); } // Load delay: CurrentLine = a_NBT.FindChildByName(a_TagIdx, "Delay"); if ((CurrentLine >= 0) && (a_NBT.GetType(CurrentLine) == TAG_Short)) { MobSpawner->SetSpawnDelay(a_NBT.GetShort(CurrentLine)); } // Load delay range: CurrentLine = a_NBT.FindChildByName(a_TagIdx, "MinSpawnDelay"); if ((CurrentLine >= 0) && (a_NBT.GetType(CurrentLine) == TAG_Short)) { MobSpawner->SetMinSpawnDelay(a_NBT.GetShort(CurrentLine)); } CurrentLine = a_NBT.FindChildByName(a_TagIdx, "MaxSpawnDelay"); if ((CurrentLine >= 0) && (a_NBT.GetType(CurrentLine) == TAG_Short)) { MobSpawner->SetMaxSpawnDelay(a_NBT.GetShort(CurrentLine)); } // Load MaxNearbyEntities: CurrentLine = a_NBT.FindChildByName(a_TagIdx, "MaxNearbyEntities"); if ((CurrentLine >= 0) && (a_NBT.GetType(CurrentLine) == TAG_Short)) { MobSpawner->SetMaxNearbyEntities(a_NBT.GetShort(CurrentLine)); } // Load RequiredPlayerRange: CurrentLine = a_NBT.FindChildByName(a_TagIdx, "RequiredPlayerRange"); if ((CurrentLine >= 0) && (a_NBT.GetType(CurrentLine) == TAG_Short)) { MobSpawner->SetRequiredPlayerRange(a_NBT.GetShort(CurrentLine)); } return MobSpawner; } OwnedBlockEntity cWSSAnvil::LoadMobHeadFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos) { // Check if the data has a proper type: static const AStringVector expectedTypes({ "Skull", "minecraft:skull" }); if (!CheckBlockEntityType(a_NBT, a_TagIdx, expectedTypes, a_Pos)) { return nullptr; } auto MobHead = std::make_unique(a_BlockType, a_BlockMeta, a_Pos, m_World); int currentLine = a_NBT.FindChildByName(a_TagIdx, "SkullType"); if (currentLine >= 0) { MobHead->SetType(static_cast(a_NBT.GetByte(currentLine))); } currentLine = a_NBT.FindChildByName(a_TagIdx, "Rot"); if (currentLine >= 0) { MobHead->SetRotation(static_cast(a_NBT.GetByte(currentLine))); } int ownerLine = a_NBT.FindChildByName(a_TagIdx, "Owner"); if (ownerLine >= 0) { AString OwnerName, OwnerTexture, OwnerTextureSignature; cUUID OwnerUUID; currentLine = a_NBT.FindChildByName(ownerLine, "Id"); if (currentLine >= 0) { OwnerUUID.FromString(a_NBT.GetString(currentLine)); } currentLine = a_NBT.FindChildByName(ownerLine, "Name"); if (currentLine >= 0) { OwnerName = a_NBT.GetString(currentLine); } int textureLine = a_NBT.GetFirstChild( // The first texture of a_NBT.FindChildByName( // The texture list of a_NBT.FindChildByName( // The Properties compound of ownerLine, // The Owner compound "Properties" ), "textures" ) ); if (textureLine >= 0) { currentLine = a_NBT.FindChildByName(textureLine, "Signature"); if (currentLine >= 0) { OwnerTextureSignature = a_NBT.GetString(currentLine); } currentLine = a_NBT.FindChildByName(textureLine, "Value"); if (currentLine >= 0) { OwnerTexture = a_NBT.GetString(currentLine); } } MobHead->SetOwner(OwnerUUID, OwnerName, OwnerTexture, OwnerTextureSignature); } return MobHead; } OwnedBlockEntity cWSSAnvil::LoadNoteBlockFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos) { // Check if the data has a proper type: static const AStringVector expectedTypes({ "Music", "minecraft:noteblock" }); if (!CheckBlockEntityType(a_NBT, a_TagIdx, expectedTypes, a_Pos)) { return nullptr; } auto NoteBlock = std::make_unique(a_BlockType, a_BlockMeta, a_Pos, m_World); int note = a_NBT.FindChildByName(a_TagIdx, "note"); if (note >= 0) { NoteBlock->SetNote(a_NBT.GetByte(note)); } return NoteBlock; } OwnedBlockEntity cWSSAnvil::LoadSignFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos) { // Check if the data has a proper type: static const AStringVector expectedTypes({ "Sign", "minecraft:sign" }); if (!CheckBlockEntityType(a_NBT, a_TagIdx, expectedTypes, a_Pos)) { return nullptr; } auto Sign = std::make_unique(a_BlockType, a_BlockMeta, a_Pos, m_World); int currentLine = a_NBT.FindChildByName(a_TagIdx, "Text1"); if (currentLine >= 0) { Sign->SetLine(0, DecodeSignLine(a_NBT.GetString(currentLine))); } currentLine = a_NBT.FindChildByName(a_TagIdx, "Text2"); if (currentLine >= 0) { Sign->SetLine(1, DecodeSignLine(a_NBT.GetString(currentLine))); } currentLine = a_NBT.FindChildByName(a_TagIdx, "Text3"); if (currentLine >= 0) { Sign->SetLine(2, DecodeSignLine(a_NBT.GetString(currentLine))); } currentLine = a_NBT.FindChildByName(a_TagIdx, "Text4"); if (currentLine >= 0) { Sign->SetLine(3, DecodeSignLine(a_NBT.GetString(currentLine))); } return Sign; } void cWSSAnvil::LoadEntityFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_EntityTagIdx, const std::string_view a_EntityName) { typedef void (cWSSAnvil::*EntityLoaderFunc)(cEntityList &, const cParsedNBT &, int a_EntityTagIdx); typedef std::map EntityLoaderMap; static const EntityLoaderMap EntityTypeToFunction { { "Boat", &cWSSAnvil::LoadBoatFromNBT }, { "minecraft:boat", &cWSSAnvil::LoadBoatFromNBT }, { "EnderCrystal", &cWSSAnvil::LoadEnderCrystalFromNBT }, { "minecraft:ender_crystal", &cWSSAnvil::LoadEnderCrystalFromNBT }, { "FallingBlock", &cWSSAnvil::LoadFallingBlockFromNBT }, { "minecraft:falling_block", &cWSSAnvil::LoadFallingBlockFromNBT }, { "Minecart", &cWSSAnvil::LoadOldMinecartFromNBT }, { "MinecartChest", &cWSSAnvil::LoadMinecartCFromNBT }, { "minecraft:chest_minecart", &cWSSAnvil::LoadMinecartCFromNBT }, { "MinecartFurnace", &cWSSAnvil::LoadMinecartFFromNBT }, { "minecraft:furnace_minecart", &cWSSAnvil::LoadMinecartFFromNBT }, { "MinecartTNT", &cWSSAnvil::LoadMinecartTFromNBT }, { "minecraft:tnt_minecart", &cWSSAnvil::LoadMinecartTFromNBT }, { "MinecartHopper", &cWSSAnvil::LoadMinecartHFromNBT }, { "minecraft:hopper_minecart", &cWSSAnvil::LoadMinecartHFromNBT }, { "MinecartRideable", &cWSSAnvil::LoadMinecartRFromNBT }, { "minecraft:minecart", &cWSSAnvil::LoadMinecartRFromNBT }, { "Item", &cWSSAnvil::LoadPickupFromNBT }, { "minecraft:item", &cWSSAnvil::LoadPickupFromNBT }, { "Painting", &cWSSAnvil::LoadPaintingFromNBT }, { "minecraft:painting", &cWSSAnvil::LoadPaintingFromNBT }, { "PrimedTnt", &cWSSAnvil::LoadTNTFromNBT }, { "minecraft:tnt", &cWSSAnvil::LoadTNTFromNBT }, { "XPOrb", &cWSSAnvil::LoadExpOrbFromNBT }, { "minecraft:xp_orb", &cWSSAnvil::LoadExpOrbFromNBT }, { "ItemFrame", &cWSSAnvil::LoadItemFrameFromNBT }, { "minecraft:item_frame", &cWSSAnvil::LoadItemFrameFromNBT }, { "LeashKnot", &cWSSAnvil::LoadLeashKnotFromNBT }, { "minecraft:leash_knot", &cWSSAnvil::LoadLeashKnotFromNBT }, { "Arrow", &cWSSAnvil::LoadArrowFromNBT }, { "minecraft:arrow", &cWSSAnvil::LoadArrowFromNBT }, { "SplashPotion", &cWSSAnvil::LoadSplashPotionFromNBT }, { "minecraft:potion", &cWSSAnvil::LoadSplashPotionFromNBT }, { "Snowball", &cWSSAnvil::LoadSnowballFromNBT }, { "minecraft:snowball", &cWSSAnvil::LoadSnowballFromNBT }, { "Egg", &cWSSAnvil::LoadEggFromNBT }, { "minecraft:egg", &cWSSAnvil::LoadEggFromNBT }, { "Fireball", &cWSSAnvil::LoadFireballFromNBT }, { "minecraft:fireball", &cWSSAnvil::LoadFireballFromNBT }, { "SmallFireball", &cWSSAnvil::LoadFireChargeFromNBT }, { "minecraft:small_fireball", &cWSSAnvil::LoadFireChargeFromNBT }, { "ThrownEnderpearl", &cWSSAnvil::LoadThrownEnderpearlFromNBT }, { "minecraft:ender_pearl", &cWSSAnvil::LoadThrownEnderpearlFromNBT } }; // TODO: flatten monster\projectile into one entity type enum const auto it = EntityTypeToFunction.find(a_EntityName); if (it != EntityTypeToFunction.end()) { (this->*it->second)(a_Entities, a_NBT, a_EntityTagIdx); return; } const auto StatInfo = NamespaceSerializer::SplitNamespacedID(a_EntityName); if (StatInfo.first == NamespaceSerializer::Namespace::Unknown) { return; } switch (NamespaceSerializer::ToMonsterType(StatInfo.second)) { case mtBat: return LoadBatFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtBlaze: return LoadBlazeFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtCat: return LoadCatFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtCaveSpider: return LoadCaveSpiderFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtChicken: return LoadChickenFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtCod: return LoadCodFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtCow: return LoadCowFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtCreeper: return LoadCreeperFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtDolphin: return LoadDolphinFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtDonkey: return LoadDonkeyFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtDrowned: return LoadDrownedFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtElderGuardian: return LoadElderGuardianFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtEnderDragon: return LoadEnderDragonFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtEnderman: return LoadEndermanFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtEndermite: return LoadEndermiteFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtEvoker: return LoadEvokerFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtFox: return LoadFoxFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtGhast: return LoadGhastFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtGiant: return LoadGiantFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtGuardian: return LoadGuardianFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtHorse: return LoadHorseFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtHoglin: return LoadHoglinFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtHusk: return LoadHuskFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtIllusioner: return LoadIllusionerFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtIronGolem: return LoadIronGolemFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtLlama: return LoadLlamaFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtMagmaCube: return LoadMagmaCubeFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtMooshroom: return LoadMooshroomFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtMule: return LoadMuleFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtOcelot: return LoadOcelotFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtPanda: return LoadPandaFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtParrot: return LoadParrotFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtPhantom: return LoadPhantomFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtPig: return LoadPigFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtPiglin: return LoadPiglinFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtPiglinBrute: return LoadPiglinBruteFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtPillager: return LoadPillagerFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtPolarBear: return LoadPolarBearFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtPufferfish: return LoadPufferfishFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtRabbit: return LoadRabbitFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtRavager: return LoadRavagerFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtSalmon: return LoadSalmonFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtSheep: return LoadSheepFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtShulker: return LoadShulkerFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtSilverfish: return LoadSilverfishFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtSkeleton: return LoadSkeletonFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtSkeletonHorse: return LoadSkeletonHorseFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtSlime: return LoadSlimeFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtSnowGolem: return LoadSnowGolemFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtSpider: return LoadSpiderFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtSquid: return LoadSquidFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtStray: return LoadStrayFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtStrider: return LoadStriderFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtTraderLlama: return LoadTraderLlamaFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtTropicalFish: return LoadTropicalFishFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtTurtle: return LoadTurtleFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtVex: return LoadVexFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtVillager: return LoadVillagerFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtVindicator: return LoadVindicatorFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtWanderingTrader: return LoadWanderingTraderFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtWitch: return LoadWitchFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtWither: return LoadWitherFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtWitherSkeleton: return LoadWitherSkeletonFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtWolf: return LoadWolfFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtZoglin: return LoadZoglinFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtZombie: return LoadZombieFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtZombieHorse: return LoadZombieHorseFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtZombifiedPiglin: return LoadZombifiedPiglinFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtZombieVillager: return LoadZombieVillagerFromNBT(a_Entities, a_NBT, a_EntityTagIdx); case mtInvalidType: break; } } void cWSSAnvil::LoadOldMinecartFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx) { // It is a minecart, old style, find out the type: int TypeTag = a_NBT.FindChildByName(a_TagIdx, "Type"); if ((TypeTag < 0) || (a_NBT.GetType(TypeTag) != TAG_Int)) { return; } int MinecartType = a_NBT.GetInt(TypeTag); switch (MinecartType) { case 0: LoadMinecartRFromNBT(a_Entities, a_NBT, a_TagIdx); break; // Rideable minecart case 1: LoadMinecartCFromNBT(a_Entities, a_NBT, a_TagIdx); break; // Minecart with chest case 2: LoadMinecartFFromNBT(a_Entities, a_NBT, a_TagIdx); break; // Minecart with furnace case 3: LoadMinecartTFromNBT(a_Entities, a_NBT, a_TagIdx); break; // Minecart with TNT case 4: LoadMinecartHFromNBT(a_Entities, a_NBT, a_TagIdx); break; // Minecart with Hopper default: LOGWARNING("cWSSAnvil::LoadOldMinecartFromNBT: Unhandled minecart type (%d)", MinecartType); break; } } void cWSSAnvil::LoadBoatFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx) { auto Boat = std::make_unique(Vector3d(), cBoat::bmOak); if (!LoadEntityBaseFromNBT(*Boat.get(), a_NBT, a_TagIdx)) { return; } int TypeIdx = a_NBT.FindChildByName(a_TagIdx, "Type"); if (TypeIdx > 0) { Boat->SetMaterial(cBoat::StringToMaterial(a_NBT.GetString(TypeIdx))); } a_Entities.emplace_back(std::move(Boat)); } void cWSSAnvil::LoadEnderCrystalFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx) { bool DisplayBeam = false, ShowBottom = false; Vector3i BeamTarget; int CurrentLine = a_NBT.FindChildByName(a_TagIdx, "BeamTarget"); if (CurrentLine > 0) { DisplayBeam = true; if (a_NBT.GetType(CurrentLine) == TAG_Compound) { int CoordinateLine = a_NBT.FindChildByName(CurrentLine, "X"); if (CoordinateLine > 0) { BeamTarget.x = a_NBT.GetInt(CoordinateLine); } CoordinateLine = a_NBT.FindChildByName(CurrentLine, "Y"); if (CoordinateLine > 0) { BeamTarget.y = a_NBT.GetInt(CoordinateLine); } CoordinateLine = a_NBT.FindChildByName(CurrentLine, "Z"); if (CoordinateLine > 0) { BeamTarget.z = a_NBT.GetInt(CoordinateLine); } } } CurrentLine = a_NBT.FindChildByName(a_TagIdx, "ShowBottom"); if (CurrentLine > 0) { ShowBottom = a_NBT.GetByte(CurrentLine) == 1; } auto EnderCrystal = std::make_unique(Vector3d(), BeamTarget, DisplayBeam, ShowBottom); if (!LoadEntityBaseFromNBT(*EnderCrystal.get(), a_NBT, a_TagIdx)) { return; } a_Entities.emplace_back(std::move(EnderCrystal)); } void cWSSAnvil::LoadFallingBlockFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx) { int TypeIdx = a_NBT.FindChildByName(a_TagIdx, "TileID"); int MetaIdx = a_NBT.FindChildByName(a_TagIdx, "Data"); if ((TypeIdx < 0) || (MetaIdx < 0)) { return; } BLOCKTYPE Type = static_cast(a_NBT.GetInt(TypeIdx)); NIBBLETYPE Meta = static_cast(a_NBT.GetByte(MetaIdx)); auto FallingBlock = std::make_unique(Vector3i(0, 0, 0), Type, Meta); if (!LoadEntityBaseFromNBT(*FallingBlock.get(), a_NBT, a_TagIdx)) { return; } a_Entities.emplace_back(std::move(FallingBlock)); } void cWSSAnvil::LoadMinecartRFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx) { auto Minecart = std::make_unique(Vector3d(), cItem(), 1); // TODO: Load the block and the height if (!LoadEntityBaseFromNBT(*Minecart.get(), a_NBT, a_TagIdx)) { return; } a_Entities.emplace_back(std::move(Minecart)); } void cWSSAnvil::LoadMinecartCFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx) { int Items = a_NBT.FindChildByName(a_TagIdx, "Items"); if ((Items < 0) || (a_NBT.GetType(Items) != TAG_List)) { return; // Make it an empty chest - the chunk loader will provide an empty cChestEntity for this } auto Minecart = std::make_unique(Vector3d()); if (!LoadEntityBaseFromNBT(*Minecart.get(), a_NBT, a_TagIdx)) { return; } for (int Child = a_NBT.GetFirstChild(Items); Child != -1; Child = a_NBT.GetNextSibling(Child)) { int Slot = a_NBT.FindChildByName(Child, "Slot"); if ((Slot < 0) || (a_NBT.GetType(Slot) != TAG_Byte)) { continue; } cItem Item; if (LoadItemFromNBT(Item, a_NBT, Child)) { Minecart->SetSlot(a_NBT.GetByte(Slot), Item); } } // for itr - ItemDefs[] a_Entities.emplace_back(std::move(Minecart)); } void cWSSAnvil::LoadMinecartFFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx) { auto Minecart = std::make_unique(Vector3d()); if (!LoadEntityBaseFromNBT(*Minecart.get(), a_NBT, a_TagIdx)) { return; } // TODO: Load the Push and Fuel tags a_Entities.emplace_back(std::move(Minecart)); } void cWSSAnvil::LoadMinecartTFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx) { auto Minecart = std::make_unique(Vector3d()); if (!LoadEntityBaseFromNBT(*Minecart.get(), a_NBT, a_TagIdx)) { return; } // TODO: Everything to do with TNT carts a_Entities.emplace_back(std::move(Minecart)); } void cWSSAnvil::LoadMinecartHFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx) { auto Minecart = std::make_unique(Vector3d()); if (!LoadEntityBaseFromNBT(*Minecart.get(), a_NBT, a_TagIdx)) { return; } // TODO: Everything to do with hopper carts a_Entities.emplace_back(std::move(Minecart)); } void cWSSAnvil::LoadPickupFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx) { // Load item: int ItemTag = a_NBT.FindChildByName(a_TagIdx, "Item"); if ((ItemTag < 0) || (a_NBT.GetType(ItemTag) != TAG_Compound)) { return; } cItem Item; if (!LoadItemFromNBT(Item, a_NBT, ItemTag)) { return; } auto Pickup = std::make_unique(Vector3d(), Item, false); // Pickup delay doesn't matter, just say false if (!LoadEntityBaseFromNBT(*Pickup.get(), a_NBT, a_TagIdx)) { return; } // Load age: int Age = a_NBT.FindChildByName(a_TagIdx, "Age"); if (Age > 0) { Pickup->SetAge(a_NBT.GetShort(Age)); } a_Entities.emplace_back(std::move(Pickup)); } void cWSSAnvil::LoadTNTFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx) { auto TNT = std::make_unique(Vector3d(), 0); if (!LoadEntityBaseFromNBT(*TNT.get(), a_NBT, a_TagIdx)) { return; } // Load Fuse Ticks: int FuseTicks = a_NBT.FindChildByName(a_TagIdx, "Fuse"); if (FuseTicks > 0) { TNT->SetFuseTicks(a_NBT.GetByte(FuseTicks)); } a_Entities.emplace_back(std::move(TNT)); } void cWSSAnvil::LoadExpOrbFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx) { auto ExpOrb = std::make_unique(Vector3d(), 0); if (!LoadEntityBaseFromNBT(*ExpOrb.get(), a_NBT, a_TagIdx)) { return; } // Load Age: int Age = a_NBT.FindChildByName(a_TagIdx, "Age"); if (Age > 0) { ExpOrb->SetAge(a_NBT.GetShort(Age)); } // Load Reward (Value): int Reward = a_NBT.FindChildByName(a_TagIdx, "Value"); if (Reward > 0) { ExpOrb->SetReward(a_NBT.GetShort(Reward)); } a_Entities.emplace_back(std::move(ExpOrb)); } void cWSSAnvil::LoadHangingFromNBT(cHangingEntity & a_Hanging, const cParsedNBT & a_NBT, int a_TagIdx) { // "Facing" tag is the prime source of the Facing; if not available, translate from older "Direction" or "Dir" int Facing = a_NBT.FindChildByName(a_TagIdx, "Facing"); if (Facing < 0) { return; } a_Hanging.SetProtocolFacing(a_NBT.GetByte(Facing)); int TileX = a_NBT.FindChildByName(a_TagIdx, "TileX"); int TileY = a_NBT.FindChildByName(a_TagIdx, "TileY"); int TileZ = a_NBT.FindChildByName(a_TagIdx, "TileZ"); if ((TileX > 0) && (TileY > 0) && (TileZ > 0)) { a_Hanging.SetPosition( static_cast(a_NBT.GetInt(TileX)), static_cast(a_NBT.GetInt(TileY)), static_cast(a_NBT.GetInt(TileZ)) ); } } void cWSSAnvil::LoadItemFrameFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx) { // Load item: int ItemTag = a_NBT.FindChildByName(a_TagIdx, "Item"); if ((ItemTag < 0) || (a_NBT.GetType(ItemTag) != TAG_Compound)) { return; } cItem Item; if (!LoadItemFromNBT(Item, a_NBT, ItemTag)) { return; } auto ItemFrame = std::make_unique(BLOCK_FACE_NONE, Vector3d()); if (!LoadEntityBaseFromNBT(*ItemFrame.get(), a_NBT, a_TagIdx)) { return; } ItemFrame->SetItem(Item); LoadHangingFromNBT(*ItemFrame.get(), a_NBT, a_TagIdx); // Load Rotation: int Rotation = a_NBT.FindChildByName(a_TagIdx, "ItemRotation"); if (Rotation > 0) { ItemFrame->SetItemRotation(static_cast(a_NBT.GetByte(Rotation))); } a_Entities.emplace_back(std::move(ItemFrame)); } void cWSSAnvil::LoadLeashKnotFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx) { auto LeashKnot = std::make_unique(BLOCK_FACE_NONE, Vector3d()); if (!LoadEntityBaseFromNBT(*LeashKnot.get(), a_NBT, a_TagIdx)) { return; } LoadHangingFromNBT(*LeashKnot.get(), a_NBT, a_TagIdx); a_Entities.emplace_back(std::move(LeashKnot)); } void cWSSAnvil::LoadPaintingFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx) { // Load painting name: int MotiveTag = a_NBT.FindChildByName(a_TagIdx, "Motive"); if ((MotiveTag < 0) || (a_NBT.GetType(MotiveTag) != TAG_String)) { return; } auto Painting = std::make_unique(a_NBT.GetString(MotiveTag), BLOCK_FACE_NONE, Vector3d()); if (!LoadEntityBaseFromNBT(*Painting.get(), a_NBT, a_TagIdx)) { return; } LoadHangingFromNBT(*Painting.get(), a_NBT, a_TagIdx); a_Entities.emplace_back(std::move(Painting)); } void cWSSAnvil::LoadArrowFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx) { auto Arrow = std::make_unique(nullptr, Vector3d(), Vector3d()); if (!LoadProjectileBaseFromNBT(*Arrow.get(), a_NBT, a_TagIdx)) { return; } // Load pickup state: int PickupIdx = a_NBT.FindChildByName(a_TagIdx, "pickup"); if ((PickupIdx > 0) && (a_NBT.GetType(PickupIdx) == TAG_Byte)) { Arrow->SetPickupState(static_cast(a_NBT.GetByte(PickupIdx))); } else { // Try the older "player" tag: int PlayerIdx = a_NBT.FindChildByName(a_TagIdx, "player"); if ((PlayerIdx > 0) && (a_NBT.GetType(PlayerIdx) == TAG_Byte)) { Arrow->SetPickupState((a_NBT.GetByte(PlayerIdx) == 0) ? cArrowEntity::psNoPickup : cArrowEntity::psInSurvivalOrCreative); } } // Load damage: int DamageIdx = a_NBT.FindChildByName(a_TagIdx, "damage"); if ((DamageIdx > 0) && (a_NBT.GetType(DamageIdx) == TAG_Double)) { Arrow->SetDamageCoeff(a_NBT.GetDouble(DamageIdx)); } // Load block hit: int InBlockXIdx = a_NBT.FindChildByName(a_TagIdx, "xTile"); int InBlockYIdx = a_NBT.FindChildByName(a_TagIdx, "yTile"); int InBlockZIdx = a_NBT.FindChildByName(a_TagIdx, "zTile"); if ((InBlockXIdx > 0) && (InBlockYIdx > 0) && (InBlockZIdx > 0)) { eTagType typeX = a_NBT.GetType(InBlockXIdx); if ((typeX == a_NBT.GetType(InBlockYIdx)) && (typeX == a_NBT.GetType(InBlockZIdx))) { switch (typeX) { case TAG_Int: { // Old MCS code used this, keep reading it for compatibility reasons: Arrow->SetBlockHit(Vector3i(a_NBT.GetInt(InBlockXIdx), a_NBT.GetInt(InBlockYIdx), a_NBT.GetInt(InBlockZIdx))); break; } case TAG_Short: { // Vanilla uses this Arrow->SetBlockHit(Vector3i(a_NBT.GetShort(InBlockXIdx), a_NBT.GetShort(InBlockYIdx), a_NBT.GetShort(InBlockZIdx))); break; } default: { // No hit block, the arrow is still flying? break; } } } } // Store the new arrow in the entities list: a_Entities.emplace_back(std::move(Arrow)); } void cWSSAnvil::LoadSplashPotionFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx) { auto SplashPotion = std::make_unique(nullptr, Vector3d(), Vector3d(), cItem()); if (!LoadProjectileBaseFromNBT(*SplashPotion.get(), a_NBT, a_TagIdx)) { return; } int EffectDuration = a_NBT.FindChildByName(a_TagIdx, "EffectDuration"); int EffectIntensity = a_NBT.FindChildByName(a_TagIdx, "EffectIntensity"); int EffectDistanceModifier = a_NBT.FindChildByName(a_TagIdx, "EffectDistanceModifier"); SplashPotion->SetEntityEffectType(static_cast(a_NBT.FindChildByName(a_TagIdx, "EffectType"))); SplashPotion->SetEntityEffect(cEntityEffect(EffectDuration, static_cast(EffectIntensity), EffectDistanceModifier)); SplashPotion->SetPotionColor(a_NBT.FindChildByName(a_TagIdx, "PotionName")); // Store the new splash potion in the entities list: a_Entities.emplace_back(std::move(SplashPotion)); } void cWSSAnvil::LoadSnowballFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx) { auto Snowball = std::make_unique(nullptr, Vector3d(), Vector3d()); if (!LoadProjectileBaseFromNBT(*Snowball.get(), a_NBT, a_TagIdx)) { return; } // Store the new snowball in the entities list: a_Entities.emplace_back(std::move(Snowball)); } void cWSSAnvil::LoadEggFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx) { auto Egg = std::make_unique(nullptr, Vector3d(), Vector3d()); if (!LoadProjectileBaseFromNBT(*Egg.get(), a_NBT, a_TagIdx)) { return; } // Store the new egg in the entities list: a_Entities.emplace_back(std::move(Egg)); } void cWSSAnvil::LoadFireballFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx) { auto Fireball = std::make_unique(nullptr, Vector3d(), Vector3d()); if (!LoadProjectileBaseFromNBT(*Fireball.get(), a_NBT, a_TagIdx)) { return; } // Store the new fireball in the entities list: a_Entities.emplace_back(std::move(Fireball)); } void cWSSAnvil::LoadFireChargeFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx) { auto FireCharge = std::make_unique(nullptr, Vector3d(), Vector3d()); if (!LoadProjectileBaseFromNBT(*FireCharge.get(), a_NBT, a_TagIdx)) { return; } // Store the new FireCharge in the entities list: a_Entities.emplace_back(std::move(FireCharge)); } void cWSSAnvil::LoadThrownEnderpearlFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx) { auto Enderpearl = std::make_unique(nullptr, Vector3d(), Vector3d()); if (!LoadProjectileBaseFromNBT(*Enderpearl.get(), a_NBT, a_TagIdx)) { return; } // Store the new enderpearl in the entities list: a_Entities.emplace_back(std::move(Enderpearl)); } void cWSSAnvil::LoadBatFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx) { auto Monster = std::make_unique(); if (!LoadEntityBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) { return; } if (!LoadMonsterBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) { return; } a_Entities.emplace_back(std::move(Monster)); } void cWSSAnvil::LoadBlazeFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx) { std::unique_ptr Monster = std::make_unique(); if (!LoadEntityBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) { return; } if (!LoadMonsterBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) { return; } a_Entities.emplace_back(std::move(Monster)); } void cWSSAnvil::LoadCatFromNBT(cEntityList &a_Entities, const cParsedNBT &a_NBT, int a_TagIdx) { // TODO } void cWSSAnvil::LoadCaveSpiderFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx) { std::unique_ptr Monster = std::make_unique(); if (!LoadEntityBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) { return; } if (!LoadMonsterBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) { return; } a_Entities.emplace_back(std::move(Monster)); } void cWSSAnvil::LoadChickenFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx) { std::unique_ptr Monster = std::make_unique(); if (!LoadEntityBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) { return; } if (!LoadMonsterBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) { return; } a_Entities.emplace_back(std::move(Monster)); } void cWSSAnvil::LoadCodFromNBT(cEntityList &a_Entities, const cParsedNBT &a_NBT, int a_TagIdx) { // TODO } void cWSSAnvil::LoadCowFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx) { std::unique_ptr Monster = std::make_unique(); if (!LoadEntityBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) { return; } if (!LoadMonsterBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) { return; } a_Entities.emplace_back(std::move(Monster)); } void cWSSAnvil::LoadCreeperFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx) { std::unique_ptr Monster = std::make_unique(); if (!LoadEntityBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) { return; } if (!LoadMonsterBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) { return; } a_Entities.emplace_back(std::move(Monster)); } void cWSSAnvil::LoadDolphinFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx) { // TODO } void cWSSAnvil::LoadDonkeyFromNBT(cEntityList &a_Entities, const cParsedNBT &a_NBT, int a_TagIdx) { // TODO } void cWSSAnvil::LoadDrownedFromNBT(cEntityList &a_Entities, const cParsedNBT &a_NBT, int a_TagIdx) { // TODO } void cWSSAnvil::LoadElderGuardianFromNBT(cEntityList &a_Entities, const cParsedNBT &a_NBT, int a_TagIdx) { // TODO } void cWSSAnvil::LoadEnderDragonFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx) { std::unique_ptr Monster = std::make_unique(); if (!LoadEntityBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) { return; } if (!LoadMonsterBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) { return; } a_Entities.emplace_back(std::move(Monster)); } void cWSSAnvil::LoadEndermanFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx) { std::unique_ptr Monster = std::make_unique(); if (!LoadEntityBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) { return; } if (!LoadMonsterBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) { return; } a_Entities.emplace_back(std::move(Monster)); } void cWSSAnvil::LoadEndermiteFromNBT(cEntityList &a_Entities, const cParsedNBT &a_NBT, int a_TagIdx) { // TODO } void cWSSAnvil::LoadEvokerFromNBT(cEntityList &a_Entities, const cParsedNBT &a_NBT, int a_TagIdx) { // TODO } void cWSSAnvil::LoadFoxFromNBT(cEntityList &a_Entities, const cParsedNBT &a_NBT, int a_TagIdx) { // TODO } void cWSSAnvil::LoadGhastFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx) { std::unique_ptr Monster = std::make_unique(); if (!LoadEntityBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) { return; } if (!LoadMonsterBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) { return; } a_Entities.emplace_back(std::move(Monster)); } void cWSSAnvil::LoadGiantFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx) { std::unique_ptr Monster = std::make_unique(); if (!LoadEntityBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) { return; } if (!LoadMonsterBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) { return; } a_Entities.emplace_back(std::move(Monster)); } void cWSSAnvil::LoadGuardianFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx) { std::unique_ptr Monster = std::make_unique(); if (!LoadEntityBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) { return; } if (!LoadMonsterBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) { return; } a_Entities.emplace_back(std::move(Monster)); } void cWSSAnvil::LoadHorseFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx) { int TypeIdx = a_NBT.FindChildByName(a_TagIdx, "Type"); int ColorIdx = a_NBT.FindChildByName(a_TagIdx, "Color"); int StyleIdx = a_NBT.FindChildByName(a_TagIdx, "Style"); if ((TypeIdx < 0) || (ColorIdx < 0) || (StyleIdx < 0)) { return; } int Type = a_NBT.GetInt(TypeIdx); int Color = a_NBT.GetInt(ColorIdx); int Style = a_NBT.GetInt(StyleIdx); std::unique_ptr Monster = std::make_unique(Type, Color, Style, 1); if (!LoadEntityBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) { return; } if (!LoadMonsterBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) { return; } int AgeableIdx = a_NBT.FindChildByName(a_TagIdx, "Age"); if (AgeableIdx > 0) { int Age; switch (a_NBT.GetType(AgeableIdx)) { case TAG_Byte: Age = static_cast(a_NBT.GetByte(AgeableIdx)); break; case TAG_Int: Age = a_NBT.GetInt (AgeableIdx); break; default: Age = 0; break; } Monster->SetAge(Age); } a_Entities.emplace_back(std::move(Monster)); } void cWSSAnvil::LoadHoglinFromNBT(cEntityList &a_Entities, const cParsedNBT &a_NBT, int a_TagIdx) { // TODO } void cWSSAnvil::LoadHuskFromNBT(cEntityList &a_Entities, const cParsedNBT &a_NBT, int a_TagIdx) { // TODO } void cWSSAnvil::LoadIllusionerFromNBT(cEntityList &a_Entities, const cParsedNBT &a_NBT, int a_TagIdx) { // TODO } void cWSSAnvil::LoadIronGolemFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx) { std::unique_ptr Monster = std::make_unique(); if (!LoadEntityBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) { return; } if (!LoadMonsterBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) { return; } a_Entities.emplace_back(std::move(Monster)); } void cWSSAnvil::LoadLlamaFromNBT(cEntityList &a_Entities, const cParsedNBT &a_NBT, int a_TagIdx) { // TODO } void cWSSAnvil::LoadMagmaCubeFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx) { int SizeIdx = a_NBT.FindChildByName(a_TagIdx, "Size"); if (SizeIdx < 0) { return; } int Size = a_NBT.GetInt(SizeIdx); std::unique_ptr Monster = std::make_unique(Size); if (!LoadEntityBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) { return; } if (!LoadMonsterBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) { return; } a_Entities.emplace_back(std::move(Monster)); } void cWSSAnvil::LoadMooshroomFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx) { std::unique_ptr Monster = std::make_unique(); if (!LoadEntityBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) { return; } if (!LoadMonsterBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) { return; } a_Entities.emplace_back(std::move(Monster)); } void cWSSAnvil::LoadMuleFromNBT(cEntityList &a_Entities, const cParsedNBT &a_NBT, int a_TagIdx) { // TODO } void cWSSAnvil::LoadOcelotFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx) { std::unique_ptr Monster = std::make_unique(); if (!LoadEntityBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) { return; } if (!LoadMonsterBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) { return; } auto OwnerInfo = LoadEntityOwner(a_NBT, a_TagIdx); if (!OwnerInfo.first.empty() && !OwnerInfo.second.IsNil()) { Monster->SetOwner(OwnerInfo.first, OwnerInfo.second); Monster->SetIsTame(true); } int TypeIdx = a_NBT.FindChildByName(a_TagIdx, "CatType"); if (TypeIdx > 0) { int Type = a_NBT.GetInt(TypeIdx); Monster->SetCatType(static_cast(Type)); } int SittingIdx = a_NBT.FindChildByName(a_TagIdx, "Sitting"); if ((SittingIdx > 0) && (a_NBT.GetType(SittingIdx) == TAG_Byte)) { bool Sitting = (a_NBT.GetByte(SittingIdx) == 1); Monster->SetIsSitting(Sitting); } int AgeableIdx = a_NBT.FindChildByName(a_TagIdx, "Age"); if (AgeableIdx > 0) { int Age; switch (a_NBT.GetType(AgeableIdx)) { case TAG_Byte: Age = static_cast(a_NBT.GetByte(AgeableIdx)); break; case TAG_Int: Age = a_NBT.GetInt (AgeableIdx); break; default: Age = 0; break; } Monster->SetAge(Age); } a_Entities.emplace_back(std::move(Monster)); } void cWSSAnvil::LoadPandaFromNBT(cEntityList &a_Entities, const cParsedNBT &a_NBT, int a_TagIdx) { // TODO } void cWSSAnvil::LoadParrotFromNBT(cEntityList &a_Entities, const cParsedNBT &a_NBT, int a_TagIdx) { // TODO } void cWSSAnvil::LoadPhantomFromNBT(cEntityList &a_Entities, const cParsedNBT &a_NBT, int a_TagIdx) { // TODO } void cWSSAnvil::LoadPigFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx) { std::unique_ptr Monster = std::make_unique(); if (!LoadEntityBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) { return; } if (!LoadMonsterBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) { return; } int AgeableIdx = a_NBT.FindChildByName(a_TagIdx, "Age"); if (AgeableIdx > 0) { int Age; switch (a_NBT.GetType(AgeableIdx)) { case TAG_Byte: Age = static_cast(a_NBT.GetByte(AgeableIdx)); break; case TAG_Int: Age = a_NBT.GetInt (AgeableIdx); break; default: Age = 0; break; } Monster->SetAge(Age); } a_Entities.emplace_back(std::move(Monster)); } void cWSSAnvil::LoadPiglinFromNBT(cEntityList &a_Entities, const cParsedNBT &a_NBT, int a_TagIdx) { // TODO } void cWSSAnvil::LoadPiglinBruteFromNBT(cEntityList &a_Entities, const cParsedNBT &a_NBT, int a_TagIdx) { // TODO } void cWSSAnvil::LoadPillagerFromNBT(cEntityList &a_Entities, const cParsedNBT &a_NBT, int a_TagIdx) { // TODO } void cWSSAnvil::LoadPolarBearFromNBT(cEntityList &a_Entities, const cParsedNBT &a_NBT, int a_TagIdx) { // TODO } void cWSSAnvil::LoadPufferfishFromNBT(cEntityList &a_Entities, const cParsedNBT &a_NBT, int a_TagIdx) { // TODO } void cWSSAnvil::LoadRabbitFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx) { int TypeIdx = a_NBT.FindChildByName(a_TagIdx, "RabbitType"); int MoreCarrotTicksIdx = a_NBT.FindChildByName(a_TagIdx, "MoreCarrotTicks"); if ((TypeIdx < 0) || (MoreCarrotTicksIdx < 0)) { return; } int Type = a_NBT.GetInt(TypeIdx); int MoreCarrotTicks = a_NBT.GetInt(MoreCarrotTicksIdx); std::unique_ptr Monster = std::make_unique(static_cast(Type), MoreCarrotTicks); if (!LoadEntityBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) { return; } if (!LoadMonsterBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) { return; } int AgeableIdx = a_NBT.FindChildByName(a_TagIdx, "Age"); if (AgeableIdx > 0) { int Age; switch (a_NBT.GetType(AgeableIdx)) { case TAG_Byte: Age = static_cast(a_NBT.GetByte(AgeableIdx)); break; case TAG_Int: Age = a_NBT.GetInt (AgeableIdx); break; default: Age = 0; break; } Monster->SetAge(Age); } a_Entities.emplace_back(std::move(Monster)); } void cWSSAnvil::LoadRavagerFromNBT(cEntityList &a_Entities, const cParsedNBT &a_NBT, int a_TagIdx) { // TODO } void cWSSAnvil::LoadSalmonFromNBT(cEntityList &a_Entities, const cParsedNBT &a_NBT, int a_TagIdx) { // TODO } void cWSSAnvil::LoadSheepFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx) { int ColorIdx = a_NBT.FindChildByName(a_TagIdx, "Color"); int Color = -1; if (ColorIdx > 0) { Color = static_cast(a_NBT.GetByte(ColorIdx)); } std::unique_ptr Monster = std::make_unique(Color); if (!LoadEntityBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) { return; } if (!LoadMonsterBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) { return; } int ShearedIdx = a_NBT.FindChildByName(a_TagIdx, "Sheared"); if (ShearedIdx > 0) { Monster->SetSheared(a_NBT.GetByte(ShearedIdx) != 0); } int AgeableIdx = a_NBT.FindChildByName(a_TagIdx, "Age"); if (AgeableIdx > 0) { int Age; switch (a_NBT.GetType(AgeableIdx)) { case TAG_Byte: Age = static_cast(a_NBT.GetByte(AgeableIdx)); break; case TAG_Int: Age = a_NBT.GetInt (AgeableIdx); break; default: Age = 0; break; } Monster->SetAge(Age); } a_Entities.emplace_back(std::move(Monster)); } void cWSSAnvil::LoadShulkerFromNBT(cEntityList &a_Entities, const cParsedNBT &a_NBT, int a_TagIdx) { // TODO } void cWSSAnvil::LoadSilverfishFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx) { std::unique_ptr Monster = std::make_unique(); if (!LoadEntityBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) { return; } if (!LoadMonsterBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) { return; } a_Entities.emplace_back(std::move(Monster)); } void cWSSAnvil::LoadSkeletonFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx) { // Wither skeleton is a separate mob in Minecraft 1.11+, but we need this to // load them from older worlds where wither skeletons were only a skeleton with a flag int TypeIdx = a_NBT.FindChildByName(a_TagIdx, "SkeletonType"); std::unique_ptr Monster; if ((TypeIdx > 0) && (a_NBT.GetByte(TypeIdx) == 1)) { Monster = std::make_unique(); } else { Monster = std::make_unique(); } if (!LoadEntityBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) { return; } if (!LoadMonsterBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) { return; } a_Entities.emplace_back(std::move(Monster)); } void cWSSAnvil::LoadSkeletonHorseFromNBT(cEntityList &a_Entities, const cParsedNBT &a_NBT, int a_TagIdx) { // TODO } void cWSSAnvil::LoadSlimeFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx) { int SizeIdx = a_NBT.FindChildByName(a_TagIdx, "Size"); if (SizeIdx < 0) { return; } int Size = a_NBT.GetInt(SizeIdx); std::unique_ptr Monster = std::make_unique(Size); if (!LoadEntityBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) { return; } if (!LoadMonsterBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) { return; } a_Entities.emplace_back(std::move(Monster)); } void cWSSAnvil::LoadSnowGolemFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx) { std::unique_ptr Monster = std::make_unique(); if (!LoadEntityBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) { return; } if (!LoadMonsterBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) { return; } a_Entities.emplace_back(std::move(Monster)); } void cWSSAnvil::LoadSpiderFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx) { std::unique_ptr Monster = std::make_unique(); if (!LoadEntityBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) { return; } if (!LoadMonsterBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) { return; } a_Entities.emplace_back(std::move(Monster)); } void cWSSAnvil::LoadSquidFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx) { std::unique_ptr Monster = std::make_unique(); if (!LoadEntityBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) { return; } if (!LoadMonsterBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) { return; } a_Entities.emplace_back(std::move(Monster)); } void cWSSAnvil::LoadStrayFromNBT(cEntityList &a_Entities, const cParsedNBT &a_NBT, int a_TagIdx) { // TODO } void cWSSAnvil::LoadStriderFromNBT(cEntityList &a_Entities, const cParsedNBT &a_NBT, int a_TagIdx) { // TODO } void cWSSAnvil::LoadTraderLlamaFromNBT(cEntityList &a_Entities, const cParsedNBT &a_NBT, int a_TagIdx) { // TODO } void cWSSAnvil::LoadTropicalFishFromNBT(cEntityList &a_Entities, const cParsedNBT &a_NBT, int a_TagIdx) { // TODO } void cWSSAnvil::LoadTurtleFromNBT(cEntityList &a_Entities, const cParsedNBT &a_NBT, int a_TagIdx) { // TODO } void cWSSAnvil::LoadVexFromNBT(cEntityList &a_Entities, const cParsedNBT &a_NBT, int a_TagIdx) { // TODO } void cWSSAnvil::LoadVillagerFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx) { int TypeIdx = a_NBT.FindChildByName(a_TagIdx, "Profession"); if (TypeIdx < 0) { return; } int Type = a_NBT.GetInt(TypeIdx); std::unique_ptr Monster = std::make_unique(cVillager::eVillagerType(Type)); if (!LoadEntityBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) { return; } if (!LoadMonsterBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) { return; } int AgeableIdx = a_NBT.FindChildByName(a_TagIdx, "Age"); if (AgeableIdx > 0) { int Age; switch (a_NBT.GetType(AgeableIdx)) { case TAG_Byte: Age = static_cast(a_NBT.GetByte(AgeableIdx)); break; case TAG_Int: Age = a_NBT.GetInt (AgeableIdx); break; default: Age = 0; break; } Monster->SetAge(Age); } int InventoryIdx = a_NBT.FindChildByName(a_TagIdx, "Inventory"); if (InventoryIdx > 0) { LoadItemGridFromNBT(Monster->GetInventory(), a_NBT, InventoryIdx); } a_Entities.emplace_back(std::move(Monster)); } void cWSSAnvil::LoadVindicatorFromNBT(cEntityList &a_Entities, const cParsedNBT &a_NBT, int a_TagIdx) { // TODO } void cWSSAnvil::LoadWanderingTraderFromNBT(cEntityList &a_Entities, const cParsedNBT &a_NBT, int a_TagIdx) { // TODO } void cWSSAnvil::LoadWitchFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx) { std::unique_ptr Monster = std::make_unique(); if (!LoadEntityBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) { return; } if (!LoadMonsterBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) { return; } a_Entities.emplace_back(std::move(Monster)); } void cWSSAnvil::LoadWitherFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx) { std::unique_ptr Monster = std::make_unique(); if (!LoadEntityBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) { return; } if (!LoadMonsterBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) { return; } int CurrLine = a_NBT.FindChildByName(a_TagIdx, "Invul"); if (CurrLine > 0) { Monster->SetWitherInvulnerableTicks(static_cast(a_NBT.GetInt(CurrLine))); } a_Entities.emplace_back(std::move(Monster)); } void cWSSAnvil::LoadWitherSkeletonFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx) { auto Monster = std::make_unique(); if (!LoadEntityBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) { return; } if (!LoadMonsterBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) { return; } a_Entities.emplace_back(std::move(Monster)); } void cWSSAnvil::LoadWolfFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx) { std::unique_ptr Monster = std::make_unique(); if (!LoadEntityBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) { return; } if (!LoadMonsterBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) { return; } auto OwnerInfo = LoadEntityOwner(a_NBT, a_TagIdx); if (!OwnerInfo.first.empty() && !OwnerInfo.second.IsNil()) { Monster->SetOwner(OwnerInfo.first, OwnerInfo.second); Monster->SetIsTame(true); } int SittingIdx = a_NBT.FindChildByName(a_TagIdx, "Sitting"); if ((SittingIdx > 0) && (a_NBT.GetType(SittingIdx) == TAG_Byte)) { bool Sitting = (a_NBT.GetByte(SittingIdx) == 1); Monster->SetIsSitting(Sitting); } int AngryIdx = a_NBT.FindChildByName(a_TagIdx, "Angry"); if ((AngryIdx > 0) && (a_NBT.GetType(AngryIdx) == TAG_Byte)) { bool Angry = (a_NBT.GetByte(AngryIdx) == 1); Monster->SetIsAngry(Angry); } int CollarColorIdx = a_NBT.FindChildByName(a_TagIdx, "CollarColor"); if (CollarColorIdx > 0) { switch (a_NBT.GetType(CollarColorIdx)) { case TAG_Byte: { // Vanilla uses this Monster->SetCollarColor(a_NBT.GetByte(CollarColorIdx)); break; } case TAG_Int: { // Old MCS code used this, keep reading it for compatibility reasons: Monster->SetCollarColor(a_NBT.GetInt(CollarColorIdx)); break; } default: { // No other values are interpreted break; } } } int AgeableIdx = a_NBT.FindChildByName(a_TagIdx, "Age"); if (AgeableIdx > 0) { int Age; switch (a_NBT.GetType(AgeableIdx)) { case TAG_Byte: Age = static_cast(a_NBT.GetByte(AgeableIdx)); break; case TAG_Int: Age = a_NBT.GetInt (AgeableIdx); break; default: Age = 0; break; } Monster->SetAge(Age); } a_Entities.emplace_back(std::move(Monster)); } void cWSSAnvil::LoadZoglinFromNBT(cEntityList &a_Entities, const cParsedNBT &a_NBT, int a_TagIdx) { // TODO } void cWSSAnvil::LoadZombieFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx) { std::unique_ptr Monster = std::make_unique(); if (!LoadEntityBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) { return; } if (!LoadMonsterBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) { return; } int AgeableIdx = a_NBT.FindChildByName(a_TagIdx, "Age"); if (AgeableIdx > 0) { int Age; switch (a_NBT.GetType(AgeableIdx)) { case TAG_Byte: Age = static_cast(a_NBT.GetByte(AgeableIdx)); break; case TAG_Int: Age = a_NBT.GetInt(AgeableIdx); break; default: Age = 0; break; } Monster->SetAge(Age); } a_Entities.emplace_back(std::move(Monster)); } void cWSSAnvil::LoadZombieHorseFromNBT(cEntityList &a_Entities, const cParsedNBT &a_NBT, int a_TagIdx) { // TODO } void cWSSAnvil::LoadZombifiedPiglinFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx) { std::unique_ptr Monster = std::make_unique(); if (!LoadEntityBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) { return; } if (!LoadMonsterBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) { return; } int AgeableIdx = a_NBT.FindChildByName(a_TagIdx, "Age"); if (AgeableIdx > 0) { int Age; switch (a_NBT.GetType(AgeableIdx)) { case TAG_Byte: Age = static_cast(a_NBT.GetByte(AgeableIdx)); break; case TAG_Int: Age = a_NBT.GetInt (AgeableIdx); break; default: Age = 0; break; } Monster->SetAge(Age); } a_Entities.emplace_back(std::move(Monster)); } void cWSSAnvil::LoadZombieVillagerFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx) { int ProfessionIdx = a_NBT.FindChildByName(a_TagIdx, "Profession"); if (ProfessionIdx < 0) { return; } cVillager::eVillagerType Profession = static_cast(a_NBT.GetInt(ProfessionIdx)); std::unique_ptr Monster = std::make_unique(Profession); if (!LoadEntityBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) { return; } if (!LoadMonsterBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) { return; } // TODO: Conversion time int AgeableIdx = a_NBT.FindChildByName(a_TagIdx, "Age"); if (AgeableIdx > 0) { int Age; switch (a_NBT.GetType(AgeableIdx)) { case TAG_Byte: Age = static_cast(a_NBT.GetByte(AgeableIdx)); break; case TAG_Int: Age = a_NBT.GetInt (AgeableIdx); break; default: Age = 0; break; } Monster->SetAge(Age); } a_Entities.emplace_back(std::move(Monster)); } std::pair cWSSAnvil::LoadEntityOwner(const cParsedNBT & a_NBT, int a_TagIdx) { // Load the owner information. OwnerUUID or Owner may be specified, possibly both: AString OwnerName; cUUID OwnerUUID; int OwnerUUIDIdx = a_NBT.FindChildByName(a_TagIdx, "OwnerUUID"); if (OwnerUUIDIdx > 0) { OwnerUUID.FromString(a_NBT.GetString(OwnerUUIDIdx)); } int OwnerIdx = a_NBT.FindChildByName(a_TagIdx, "Owner"); if (OwnerIdx > 0) { OwnerName = a_NBT.GetString(OwnerIdx); } if (OwnerName.empty() && OwnerUUID.IsNil()) { // There is no owner, bail out: return {}; } // Convert name to UUID, if needed: if (OwnerUUID.IsNil()) { // This entity has only playername stored (pre-1.7.6), look up the UUID // The lookup is blocking, but we're running in a separate thread, so it's ok OwnerUUID = cRoot::Get()->GetMojangAPI().GetUUIDFromPlayerName(OwnerName); if (OwnerUUID.IsNil()) { // Not a known player, un-tame the entity by bailing out return {}; } } // Convert UUID to name, if needed: if (OwnerName.empty()) { // The lookup is blocking, but we're running in a separate thread, so it's ok OwnerName = cRoot::Get()->GetMojangAPI().GetPlayerNameFromUUID(OwnerUUID); if (OwnerName.empty()) { // Not a known player, un-tame the entity by bailing out return {}; } } return { OwnerName, OwnerUUID }; } bool cWSSAnvil::LoadEntityBaseFromNBT(cEntity & a_Entity, const cParsedNBT & a_NBT, int a_TagIdx) { double Pos[3]; if (!LoadDoublesListFromNBT(Pos, 3, a_NBT, a_NBT.FindChildByName(a_TagIdx, "Pos"))) { return false; } a_Entity.SetPosition(Pos[0], Pos[1], Pos[2]); double Speed[3]; if (!LoadDoublesListFromNBT(Speed, 3, a_NBT, a_NBT.FindChildByName(a_TagIdx, "Motion"))) { // Provide default speed: Speed[0] = 0; Speed[1] = 0; Speed[2] = 0; } a_Entity.SetSpeed(Speed[0], Speed[1], Speed[2]); double Rotation[3]; if (!LoadDoublesListFromNBT(Rotation, 2, a_NBT, a_NBT.FindChildByName(a_TagIdx, "Rotation"))) { // Provide default rotation: Rotation[0] = 0; Rotation[1] = 0; } a_Entity.SetYaw(Rotation[0]); a_Entity.SetPitch(Rotation[1]); // Depending on the Minecraft version, the entity's health is // stored either as a float Health tag (HealF prior to 1.9) or // as a short Health tag. The float tags should be preferred. int Health = a_NBT.FindChildByName(a_TagIdx, "Health"); int HealF = a_NBT.FindChildByName(a_TagIdx, "HealF"); if (Health > 0 && a_NBT.GetType(Health) == TAG_Float) { a_Entity.SetHealth(a_NBT.GetFloat(Health)); } else if (HealF > 0) { a_Entity.SetHealth(a_NBT.GetFloat(HealF)); } else if (Health > 0) { a_Entity.SetHealth(static_cast(a_NBT.GetShort(Health))); } else { a_Entity.SetHealth(a_Entity.GetMaxHealth()); } return true; } bool cWSSAnvil::LoadMonsterBaseFromNBT(cMonster & a_Monster, const cParsedNBT & a_NBT, int a_TagIdx) { float DropChance[5]; if (LoadFloatsListFromNBT(DropChance, 5, a_NBT, a_NBT.FindChildByName(a_TagIdx, "DropChances"))) { a_Monster.SetDropChanceWeapon(DropChance[0]); a_Monster.SetDropChanceHelmet(DropChance[1]); a_Monster.SetDropChanceChestplate(DropChance[2]); a_Monster.SetDropChanceLeggings(DropChance[3]); a_Monster.SetDropChanceBoots(DropChance[4]); } if (LoadFloatsListFromNBT(DropChance, 2, a_NBT, a_NBT.FindChildByName(a_TagIdx, "HandDropChances"))) { a_Monster.SetDropChanceWeapon(DropChance[0]); } if (LoadFloatsListFromNBT(DropChance, 4, a_NBT, a_NBT.FindChildByName(a_TagIdx, "ArmorDropChances"))) { a_Monster.SetDropChanceHelmet(DropChance[0]); a_Monster.SetDropChanceChestplate(DropChance[1]); a_Monster.SetDropChanceLeggings(DropChance[2]); a_Monster.SetDropChanceBoots(DropChance[3]); } int LootTag = a_NBT.FindChildByName(a_TagIdx, "CanPickUpLoot"); if (LootTag > 0) { bool CanPickUpLoot = (a_NBT.GetByte(LootTag) == 1); a_Monster.SetCanPickUpLoot(CanPickUpLoot); } int CustomNameTag = a_NBT.FindChildByName(a_TagIdx, "CustomName"); if ((CustomNameTag > 0) && (a_NBT.GetType(CustomNameTag) == TAG_String)) { a_Monster.SetCustomName(a_NBT.GetString(CustomNameTag)); } int CustomNameVisibleTag = a_NBT.FindChildByName(a_TagIdx, "CustomNameVisible"); if ((CustomNameVisibleTag > 0) && (a_NBT.GetType(CustomNameVisibleTag) == TAG_Byte)) { bool CustomNameVisible = (a_NBT.GetByte(CustomNameVisibleTag) == 1); a_Monster.SetCustomNameAlwaysVisible(CustomNameVisible); } // Leashed to a knot int LeashedIdx = a_NBT.FindChildByName(a_TagIdx, "Leashed"); if ((LeashedIdx >= 0) && a_NBT.GetByte(LeashedIdx)) { LoadLeashToPosition(a_Monster, a_NBT, a_TagIdx); } return true; } void cWSSAnvil::LoadLeashToPosition(cMonster & a_Monster, const cParsedNBT & a_NBT, int a_TagIdx) { int LeashIdx = a_NBT.FindChildByName(a_TagIdx, "Leash"); if (LeashIdx < 0) { return; } double PosX = 0.0, PosY = 0.0, PosZ = 0.0; bool KnotPosPresent = true; int LeashDataLine = a_NBT.FindChildByName(LeashIdx, "X"); if (LeashDataLine >= 0) { PosX = a_NBT.GetDouble(LeashDataLine); } else { KnotPosPresent = false; } LeashDataLine = a_NBT.FindChildByName(LeashIdx, "Y"); if (LeashDataLine >= 0) { PosY = a_NBT.GetDouble(LeashDataLine); } else { KnotPosPresent = false; } LeashDataLine = a_NBT.FindChildByName(LeashIdx, "Z"); if (LeashDataLine >= 0) { PosZ = a_NBT.GetDouble(LeashDataLine); } else { KnotPosPresent = false; } if (KnotPosPresent) { // Set leash pos for the mob a_Monster.SetLeashToPos(new Vector3d(PosX, PosY, PosZ)); } } bool cWSSAnvil::LoadProjectileBaseFromNBT(cProjectileEntity & a_Entity, const cParsedNBT & a_NBT, int a_TagIdx) { if (!LoadEntityBaseFromNBT(a_Entity, a_NBT, a_TagIdx)) { return false; } bool IsInGround = false; int InGroundIdx = a_NBT.FindChildByName(a_TagIdx, "inGround"); if (InGroundIdx > 0) { IsInGround = (a_NBT.GetByte(InGroundIdx) != 0); } a_Entity.SetIsInGround(IsInGround); return true; } bool cWSSAnvil::LoadDoublesListFromNBT(double * a_Doubles, int a_NumDoubles, const cParsedNBT & a_NBT, int a_TagIdx) { if ((a_TagIdx < 0) || (a_NBT.GetType(a_TagIdx) != TAG_List) || (a_NBT.GetChildrenType(a_TagIdx) != TAG_Double)) { return false; } int idx = 0; for (int Tag = a_NBT.GetFirstChild(a_TagIdx); (Tag > 0) && (idx < a_NumDoubles); Tag = a_NBT.GetNextSibling(Tag), ++idx) { a_Doubles[idx] = a_NBT.GetDouble(Tag); } // for Tag - PosTag[] return (idx == a_NumDoubles); // Did we read enough doubles? } bool cWSSAnvil::LoadFloatsListFromNBT(float * a_Floats, int a_NumFloats, const cParsedNBT & a_NBT, int a_TagIdx) { if ((a_TagIdx < 0) || (a_NBT.GetType(a_TagIdx) != TAG_List) || (a_NBT.GetChildrenType(a_TagIdx) != TAG_Float)) { return false; } int idx = 0; for (int Tag = a_NBT.GetFirstChild(a_TagIdx); (Tag > 0) && (idx < a_NumFloats); Tag = a_NBT.GetNextSibling(Tag), ++idx) { a_Floats[idx] = a_NBT.GetFloat(Tag); } // for Tag - PosTag[] return (idx == a_NumFloats); // Did we read enough doubles? } bool cWSSAnvil::GetBlockEntityNBTPos(const cParsedNBT & a_NBT, int a_TagIdx, Vector3i & a_AbsPos) { int x = a_NBT.FindChildByName(a_TagIdx, "x"); if ((x < 0) || (a_NBT.GetType(x) != TAG_Int)) { return false; } int y = a_NBT.FindChildByName(a_TagIdx, "y"); if ((y < 0) || (a_NBT.GetType(y) != TAG_Int)) { return false; } int z = a_NBT.FindChildByName(a_TagIdx, "z"); if ((z < 0) || (a_NBT.GetType(z) != TAG_Int)) { return false; } a_AbsPos.Set( Clamp(a_NBT.GetInt(x), -40000000, 40000000), // World is limited to 30M blocks in XZ, we clamp to 40M Clamp(a_NBT.GetInt(y), -10000, 10000), // Y is limited to 0 .. 255, we clamp to 10K Clamp(a_NBT.GetInt(z), -40000000, 40000000) ); return true; } //////////////////////////////////////////////////////////////////////////////// // cWSSAnvil::cMCAFile: cWSSAnvil::cMCAFile::cMCAFile(cWSSAnvil & a_ParentSchema, const AString & a_FileName, int a_RegionX, int a_RegionZ) : m_ParentSchema(a_ParentSchema), m_RegionX(a_RegionX), m_RegionZ(a_RegionZ), m_FileName(a_FileName) { } bool cWSSAnvil::cMCAFile::OpenFile(bool a_IsForReading) { bool writeOutNeeded = false; if (m_File.IsOpen()) { // Already open return true; } if (a_IsForReading) { if (!cFile::Exists(m_FileName)) { // We want to read and the file doesn't exist. Fail. return false; } } if (!m_File.Open(m_FileName, cFile::fmReadWrite)) { // The file failed to open return false; } // Load the header: if (m_File.Read(m_Header, sizeof(m_Header)) != sizeof(m_Header)) { // Cannot read the header - perhaps the file has just been created? // Try writing a nullptr header for chunk offsets: memset(m_Header, 0, sizeof(m_Header)); writeOutNeeded = true; } // Load the TimeStamps: if (m_File.Read(m_TimeStamps, sizeof(m_TimeStamps)) != sizeof(m_TimeStamps)) { // Cannot read the time stamps - perhaps the file has just been created? // Try writing a nullptr header for timestamps: memset(m_TimeStamps, 0, sizeof(m_TimeStamps)); writeOutNeeded = true; } if (writeOutNeeded) { m_File.Seek(0); if ( (m_File.Write(m_Header, sizeof(m_Header)) != sizeof(m_Header)) || // Write chunk offsets (m_File.Write(m_TimeStamps, sizeof(m_TimeStamps)) != sizeof(m_TimeStamps)) // Write chunk timestamps ) { LOGWARNING("Cannot process MCA header in file \"%s\", chunks in that file will be lost", m_FileName.c_str()); m_File.Close(); return false; } } return true; } bool cWSSAnvil::cMCAFile::GetChunkData(const cChunkCoords & a_Chunk, ContiguousByteBuffer & a_Data) { if (!OpenFile(true)) { return false; } int LocalX = a_Chunk.m_ChunkX % 32; if (LocalX < 0) { LocalX = 32 + LocalX; } int LocalZ = a_Chunk.m_ChunkZ % 32; if (LocalZ < 0) { LocalZ = 32 + LocalZ; } unsigned ChunkLocation = ntohl(m_Header[LocalX + 32 * LocalZ]); unsigned ChunkOffset = ChunkLocation >> 8; if (ChunkOffset < 2) { return false; } m_File.Seek(static_cast(ChunkOffset * 4096)); UInt32 ChunkSize = 0; if (m_File.Read(&ChunkSize, 4) != 4) { m_ParentSchema.ChunkLoadFailed(a_Chunk, "Cannot read chunk size", {}); return false; } ChunkSize = ntohl(ChunkSize); if (ChunkSize < 1) { // Chunk size too small m_ParentSchema.ChunkLoadFailed(a_Chunk, "Chunk size too small", {}); return false; } char CompressionType = 0; if (m_File.Read(&CompressionType, 1) != 1) { m_ParentSchema.ChunkLoadFailed(a_Chunk, "Cannot read chunk compression", {}); return false; } ChunkSize--; a_Data = m_File.Read(ChunkSize); if (a_Data.size() != ChunkSize) { m_ParentSchema.ChunkLoadFailed(a_Chunk, "Cannot read entire chunk data", a_Data); return false; } if (CompressionType != 2) { // Chunk is in an unknown compression m_ParentSchema.ChunkLoadFailed(a_Chunk, fmt::format(FMT_STRING("Unknown chunk compression: {}"), CompressionType), a_Data); return false; } return true; } const std::byte * cWSSAnvil::GetSectionData(const cParsedNBT & a_NBT, int a_Tag, const AString & a_ChildName, size_t a_Length) { int Child = a_NBT.FindChildByName(a_Tag, a_ChildName); if ((Child >= 0) && (a_NBT.GetType(Child) == TAG_ByteArray) && (a_NBT.GetDataLength(Child) == a_Length)) { return a_NBT.GetData(Child); } return nullptr; } bool cWSSAnvil::cMCAFile::SetChunkData(const cChunkCoords & a_Chunk, const ContiguousByteBufferView a_Data) { if (!OpenFile(false)) { LOGWARNING("Cannot save chunk [%d, %d], opening file \"%s\" failed", a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ, GetFileName().c_str()); return false; } int LocalX = a_Chunk.m_ChunkX % 32; if (LocalX < 0) { LocalX = 32 + LocalX; } int LocalZ = a_Chunk.m_ChunkZ % 32; if (LocalZ < 0) { LocalZ = 32 + LocalZ; } unsigned ChunkSector = FindFreeLocation(LocalX, LocalZ, a_Data.size()); // Store the chunk data: m_File.Seek(static_cast(ChunkSector * 4096)); UInt32 ChunkSize = htonl(static_cast(a_Data.size() + 1)); if (m_File.Write(&ChunkSize, 4) != 4) { LOGWARNING("Cannot save chunk [%d, %d], writing(1) data to file \"%s\" failed", a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ, GetFileName().c_str()); return false; } char CompressionType = 2; if (m_File.Write(&CompressionType, 1) != 1) { LOGWARNING("Cannot save chunk [%d, %d], writing(2) data to file \"%s\" failed", a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ, GetFileName().c_str()); return false; } if (m_File.Write(a_Data.data(), a_Data.size()) != static_cast(a_Data.size())) { LOGWARNING("Cannot save chunk [%d, %d], writing(3) data to file \"%s\" failed", a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ, GetFileName().c_str()); return false; } // Add padding to 4K boundary: size_t BytesWritten = a_Data.size() + MCA_CHUNK_HEADER_LENGTH; if (BytesWritten % 4096 != 0) { static const char Padding[4095] = {0}; m_File.Write(Padding, 4096 - (BytesWritten % 4096)); } // Store the header: ChunkSize = (static_cast(a_Data.size()) + MCA_CHUNK_HEADER_LENGTH + 4095) / 4096; // Round data size up to nearest 4KB sector, make it a sector number if (ChunkSize > 255) { LOGWARNING("Cannot save chunk [%d, %d], the data is too large (%u KiB, maximum is 1024 KiB). Remove some entities and retry.", a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ, static_cast(ChunkSize * 4) ); return false; } // Store the header info in the table m_Header[LocalX + 32 * LocalZ] = htonl(static_cast((ChunkSector << 8) | ChunkSize)); // Set the modification time m_TimeStamps[LocalX + 32 * LocalZ] = htonl(static_cast(time(nullptr))); if (m_File.Seek(0) < 0) { LOGWARNING("Cannot save chunk [%d, %d], seeking in file \"%s\" failed", a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ, GetFileName().c_str()); return false; } if (m_File.Write(m_Header, sizeof(m_Header)) != sizeof(m_Header)) { LOGWARNING("Cannot save chunk [%d, %d], writing header to file \"%s\" failed", a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ, GetFileName().c_str()); return false; } if (m_File.Write(m_TimeStamps, sizeof(m_TimeStamps)) != sizeof(m_TimeStamps)) { LOGWARNING("Cannot save chunk [%d, %d], writing timestamps to file \"%s\" failed", a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ, GetFileName().c_str()); return false; } return true; } unsigned cWSSAnvil::cMCAFile::FindFreeLocation(int a_LocalX, int a_LocalZ, const size_t a_DataSize) { // See if it fits the current location: unsigned ChunkLocation = ntohl(m_Header[a_LocalX + 32 * a_LocalZ]); unsigned ChunkLen = ChunkLocation & 0xff; if (a_DataSize + MCA_CHUNK_HEADER_LENGTH <= (ChunkLen * 4096)) { return ChunkLocation >> 8; } // Doesn't fit, append to the end of file (we're wasting a lot of space, TODO: fix this later) unsigned MaxLocation = 2 << 8; // Minimum sector is #2 - after the headers for (size_t i = 0; i < ARRAYCOUNT(m_Header); i++) { ChunkLocation = ntohl(m_Header[i]); ChunkLocation = ChunkLocation + ((ChunkLocation & 0xff) << 8); // Add the number of sectors used; don't care about the 4th byte if (MaxLocation < ChunkLocation) { MaxLocation = ChunkLocation; } } // for i - m_Header[] return MaxLocation >> 8; } ================================================ FILE: src/WorldStorage/WSSAnvil.h ================================================ #pragma once #include "../BlockEntities/BlockEntity.h" #include "WorldStorage.h" #include "FastNBT.h" #include "StringCompression.h" // fwd: class cItem; class cItemGrid; class cMonster; class cProjectileEntity; class cHangingEntity; class cUUID; class ChunkBlockData; /** Implements the Anvil world storage schema. */ class cWSSAnvil: public cWSSchema { using Super = cWSSchema; public: cWSSAnvil(cWorld * a_World, int a_CompressionFactor); virtual ~cWSSAnvil() override; protected: enum { /** Maximum number of chunks in an MCA file - also the count of the header items */ MCA_MAX_CHUNKS = 32 * 32, /** The MCA header is 8 KiB */ MCA_HEADER_SIZE = MCA_MAX_CHUNKS * 8, /** There are 5 bytes of header in front of each chunk */ MCA_CHUNK_HEADER_LENGTH = 5, } ; class cMCAFile { public: cMCAFile(cWSSAnvil & a_ParentSchema, const AString & a_FileName, int a_RegionX, int a_RegionZ); bool GetChunkData (const cChunkCoords & a_Chunk, ContiguousByteBuffer & a_Data); bool SetChunkData (const cChunkCoords & a_Chunk, ContiguousByteBufferView a_Data); int GetRegionX () const {return m_RegionX; } int GetRegionZ () const {return m_RegionZ; } const AString & GetFileName() const {return m_FileName; } protected: cWSSAnvil & m_ParentSchema; int m_RegionX; int m_RegionZ; cFile m_File; AString m_FileName; // The header, copied from the file so we don't have to seek to it all the time // First 1024 entries are chunk locations - the 3 + 1 byte sector-offset and sector-count unsigned m_Header[MCA_MAX_CHUNKS]; // Chunk timestamps, following the chunk headers unsigned m_TimeStamps[MCA_MAX_CHUNKS]; /** Finds a free location large enough to hold a_Data. Returns the sector number. */ unsigned FindFreeLocation(int a_LocalX, int a_LocalZ, size_t a_DataSize); /** Opens a MCA file either for a Read operation (fails if doesn't exist) or for a Write operation (creates new if not found) */ bool OpenFile(bool a_IsForReading); } ; /** Protects m_Files against multithreaded access. */ cCriticalSection m_CS; /** A MRU cache of MCA files. Protected against multithreaded access by m_CS. */ std::list> m_Files; Compression::Extractor m_Extractor; Compression::Compressor m_Compressor; /** Reports that the specified chunk failed to load and saves the chunk data to an external file. */ void ChunkLoadFailed(const cChunkCoords a_ChunkCoords, const AString & a_Reason, ContiguousByteBufferView a_ChunkDataToSave); /** Gets chunk data from the correct file; locks file CS as needed */ bool GetChunkData(const cChunkCoords & a_Chunk, ContiguousByteBuffer & a_Data); /** Copies a_Length bytes of data from the specified NBT Tag's Child into the a_Destination buffer */ const std::byte * GetSectionData(const cParsedNBT & a_NBT, int a_Tag, const AString & a_ChildName, size_t a_Length); /** Sets chunk data into the correct file; locks file CS as needed */ bool SetChunkData(const cChunkCoords & a_Chunk, ContiguousByteBufferView a_Data); /** Loads the chunk from the data (no locking needed) */ bool LoadChunkFromData(const cChunkCoords & a_Chunk, ContiguousByteBufferView a_Data); /** Saves the chunk into datastream (no locking needed) */ Compression::Result SaveChunkToData(const cChunkCoords & a_Chunk); /** Loads the chunk from NBT data (no locking needed). a_RawChunkData is the raw (compressed) chunk data, used for offloading when chunk loading fails. */ bool LoadChunkFromNBT(const cChunkCoords & a_Chunk, const cParsedNBT & a_NBT, ContiguousByteBufferView a_RawChunkData); /** Loads the chunk's biome map into a_BiomeMap if biomes present and valid; returns false otherwise. */ bool LoadBiomeMapFromNBT(cChunkDef::BiomeMap & a_BiomeMap, const cParsedNBT & a_NBT, int a_TagIdx); /** Loads the chunk's height map into a_HeightMap if heights present and valid; returns false otherwise. */ bool LoadHeightMapFromNBT(cChunkDef::HeightMap & a_HeightMap, const cParsedNBT & a_NBT, int a_TagIdx); /** Loads the chunk's entities from NBT data (a_Tag is the Level\\Entities list tag; may be -1) */ void LoadEntitiesFromNBT(cEntityList & a_Entitites, const cParsedNBT & a_NBT, int a_Tag); /** Loads the chunk's BlockEntities from NBT data (a_Tag is the Level\\TileEntities list tag; may be -1) */ void LoadBlockEntitiesFromNBT(cBlockEntities & a_BlockEntitites, const cParsedNBT & a_NBT, int a_Tag, const ChunkBlockData & a_BlockData); /** Loads the data for a block entity from the specified NBT tag. Returns the loaded block entity, or nullptr upon failure. */ OwnedBlockEntity LoadBlockEntityFromNBT(const cParsedNBT & a_NBT, int a_Tag, Vector3i a_Pos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta); /** Loads a cItem contents from the specified NBT tag; returns true if successful. Doesn't load the Slot tag */ bool LoadItemFromNBT(cItem & a_Item, const cParsedNBT & a_NBT, int a_TagIdx); /** Loads contentents of an Items[] list tag into a cItemGrid ItemGrid begins at the specified slot offset Slots outside the ItemGrid range are ignored */ void LoadItemGridFromNBT(cItemGrid & a_ItemGrid, const cParsedNBT & a_NBT, int a_ItemsTagIdx, int s_SlotOffset = 0); /** Decodes the text contained within a sign. Older versions used direct string representation, newer versions use JSON-formatted string. This function extracts the text from either version. */ AString DecodeSignLine(const AString & a_Line); /** Returns true iff the "id" child tag inside the specified tag equals (case-sensitive) any of the specified expected types. Logs a warning to the console on mismatch. The coordinates are used only for the log message. */ bool CheckBlockEntityType(const cParsedNBT & a_NBT, int a_TagIdx, const AStringVector & a_ExpectedTypes, Vector3i a_Pos); OwnedBlockEntity LoadBannerFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos); OwnedBlockEntity LoadBeaconFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos); OwnedBlockEntity LoadBedFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos); OwnedBlockEntity LoadBrewingstandFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos); OwnedBlockEntity LoadChestFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos); OwnedBlockEntity LoadCommandBlockFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos); OwnedBlockEntity LoadDispenserFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos); OwnedBlockEntity LoadDropperFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos); OwnedBlockEntity LoadEnchantingTableFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos); OwnedBlockEntity LoadEnderChestFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos); OwnedBlockEntity LoadEndPortalFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos); OwnedBlockEntity LoadFlowerPotFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos); OwnedBlockEntity LoadFurnaceFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos); OwnedBlockEntity LoadHopperFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos); OwnedBlockEntity LoadJukeboxFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos); OwnedBlockEntity LoadMobHeadFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos); OwnedBlockEntity LoadMobSpawnerFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos); OwnedBlockEntity LoadNoteBlockFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos); OwnedBlockEntity LoadSignFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos); void LoadEntityFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_EntityTagIdx, std::string_view a_EntityName); void LoadBoatFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadEnderCrystalFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadFallingBlockFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadPickupFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadTNTFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadExpOrbFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadHangingFromNBT (cHangingEntity & a_Hanging, const cParsedNBT & a_NBT, int a_TagIdx); void LoadItemFrameFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadLeashKnotFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadPaintingFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadOldMinecartFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadMinecartRFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadMinecartCFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadMinecartFFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadMinecartTFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadMinecartHFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadArrowFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadSplashPotionFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadSnowballFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadEggFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadFireballFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadFireChargeFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadThrownEnderpearlFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadBatFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadBlazeFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadCatFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadCaveSpiderFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadChickenFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadCodFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadCowFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadCreeperFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadDolphinFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadDonkeyFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadDrownedFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadElderGuardianFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadEnderDragonFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadEndermanFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadEndermiteFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadEvokerFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadFoxFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadGhastFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadGiantFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadGuardianFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadHorseFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadHoglinFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadHuskFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadIllusionerFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadIronGolemFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadLlamaFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadMagmaCubeFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadMooshroomFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadMuleFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadOcelotFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadPandaFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadParrotFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadPhantomFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadPigFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadPiglinFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadPiglinBruteFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadPillagerFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadPolarBearFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadPufferfishFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadRabbitFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadRavagerFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadSalmonFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadSheepFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadShulkerFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadSilverfishFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadSkeletonFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadSkeletonHorseFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadSlimeFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadSnowGolemFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadSpiderFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadSquidFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadStrayFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadStriderFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadTraderLlamaFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadTropicalFishFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadTurtleFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadVexFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadVillagerFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadVindicatorFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadWanderingTraderFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadWitchFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadWitherFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadWitherSkeletonFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadWolfFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadZoglinFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadZombieFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadZombieHorseFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadZombifiedPiglinFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadZombieVillagerFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); /** Loads the owner name and UUID from the entity at the specified NBT tag. Returns a pair of {name, uuid}. If the entity is not owned, name is an empty string and uuid is nil. */ std::pair LoadEntityOwner(const cParsedNBT & a_NBT, int a_TagIdx); /** Loads entity common data from the NBT compound; returns true if successful */ bool LoadEntityBaseFromNBT(cEntity & a_Entity, const cParsedNBT & a_NBT, int a_TagIdx); /** Loads monster common data from the NBT compound; returns true if successful */ bool LoadMonsterBaseFromNBT(cMonster & a_Monster, const cParsedNBT & a_NBT, int a_TagIdx); /** Loads the position to where is leashed the monster */ void LoadLeashToPosition(cMonster & a_Monster, const cParsedNBT & a_NBT, int a_TagIdx); /** Loads projectile common data from the NBT compound; returns true if successful */ bool LoadProjectileBaseFromNBT(cProjectileEntity & a_Entity, const cParsedNBT & a_NBT, int a_TagIx); /** Loads an array of doubles of the specified length from the specified NBT list tag a_TagIdx; returns true if successful */ bool LoadDoublesListFromNBT(double * a_Doubles, int a_NumDoubles, const cParsedNBT & a_NBT, int a_TagIdx); /** Loads an array of floats of the specified length from the specified NBT list tag a_TagIdx; returns true if successful */ bool LoadFloatsListFromNBT(float * a_Floats, int a_NumFloats, const cParsedNBT & a_NBT, int a_TagIdx); /** Helper function for extracting the X, Y, and Z int subtags of a NBT compound; returns true if successful */ bool GetBlockEntityNBTPos(const cParsedNBT & a_NBT, int a_TagIdx, Vector3i & a_AbsPos); /** Gets the correct MCA file either from cache or from disk, manages the m_MCAFiles cache; assumes m_CS is locked */ std::shared_ptr LoadMCAFile(const cChunkCoords & a_Chunk); // cWSSchema overrides: virtual bool LoadChunk(const cChunkCoords & a_Chunk) override; virtual bool SaveChunk(const cChunkCoords & a_Chunk) override; virtual const AString GetName() const override {return "anvil"; } } ; ================================================ FILE: src/WorldStorage/WorldStorage.cpp ================================================ // WorldStorage.cpp // Implements the cWorldStorage class representing the chunk loading / saving thread // To add a new storage schema, implement a cWSSchema descendant and add it to cWorldStorage::InitSchemas() #include "Globals.h" #include "WorldStorage.h" #include "WSSAnvil.h" #include "../World.h" #include "../Generating/ChunkGenerator.h" #include "../Entities/Entity.h" #include "../BlockEntities/BlockEntity.h" /** Example storage schema - forgets all chunks */ class cWSSForgetful : public cWSSchema { public: cWSSForgetful(cWorld * a_World) : cWSSchema(a_World) {} protected: // cWSSchema overrides: virtual bool LoadChunk(const cChunkCoords & a_Chunk) override {return false; } virtual bool SaveChunk(const cChunkCoords & a_Chunk) override {return true; } virtual const AString GetName(void) const override {return "forgetful"; } } ; //////////////////////////////////////////////////////////////////////////////// // cWorldStorage: cWorldStorage::cWorldStorage(void) : Super("World Storage Executor"), m_World(nullptr), m_SaveSchema(nullptr) { } cWorldStorage::~cWorldStorage() { for (cWSSchemaList::iterator itr = m_Schemas.begin(); itr != m_Schemas.end(); ++itr) { delete *itr; } // for itr - m_Schemas[] } void cWorldStorage::Initialize(cWorld & a_World, const AString & a_StorageSchemaName, int a_StorageCompressionFactor) { m_World = &a_World; m_StorageSchemaName = a_StorageSchemaName; InitSchemas(a_StorageCompressionFactor); } void cWorldStorage::Stop(void) { WaitForFinish(); } void cWorldStorage::WaitForFinish(void) { LOGD("Waiting for the world storage to finish saving"); { m_LoadQueue.Clear(); } // Wait for the saving to finish: WaitForSaveQueueEmpty(); // Wait for the thread to finish: m_ShouldTerminate = true; m_Event.Set(); // Wake up the thread if waiting Super::Stop(); LOGD("World storage thread finished"); } void cWorldStorage::WaitForLoadQueueEmpty(void) { m_LoadQueue.BlockTillEmpty(); } void cWorldStorage::WaitForSaveQueueEmpty(void) { m_SaveQueue.BlockTillEmpty(); } size_t cWorldStorage::GetLoadQueueLength(void) { return m_LoadQueue.Size(); } size_t cWorldStorage::GetSaveQueueLength(void) { return m_SaveQueue.Size(); } void cWorldStorage::QueueLoadChunk(int a_ChunkX, int a_ChunkZ) { ASSERT((a_ChunkX > -0x08000000) && (a_ChunkX < 0x08000000)); ASSERT((a_ChunkZ > -0x08000000) && (a_ChunkZ < 0x08000000)); ASSERT(m_World->IsChunkQueued(a_ChunkX, a_ChunkZ)); m_LoadQueue.EnqueueItem({ a_ChunkX, a_ChunkZ }); m_Event.Set(); } void cWorldStorage::QueueSaveChunk(int a_ChunkX, int a_ChunkZ) { ASSERT(m_World->IsChunkValid(a_ChunkX, a_ChunkZ)); m_SaveQueue.EnqueueItem({ a_ChunkX, a_ChunkZ }); m_Event.Set(); } void cWorldStorage::InitSchemas(int a_StorageCompressionFactor) { // The first schema added is considered the default m_Schemas.push_back(new cWSSAnvil (m_World, a_StorageCompressionFactor)); m_Schemas.push_back(new cWSSForgetful(m_World)); // Add new schemas here if (NoCaseCompare(m_StorageSchemaName, "default") == 0) { m_SaveSchema = m_Schemas.front(); return; } for (cWSSchemaList::iterator itr = m_Schemas.begin(); itr != m_Schemas.end(); ++itr) { if (NoCaseCompare((*itr)->GetName(), m_StorageSchemaName) == 0) { m_SaveSchema = *itr; return; } } // for itr - m_Schemas[] // Unknown schema selected, let the admin know: LOGWARNING("Unknown storage schema name \"%s\". Using default (\"%s\"). Available schemas:", m_StorageSchemaName.c_str(), m_SaveSchema->GetName().c_str() ); for (cWSSchemaList::iterator itr = m_Schemas.begin(); itr != m_Schemas.end(); ++itr) { LOGWARNING("\t\"%s\"", (*itr)->GetName().c_str()); } m_SaveSchema = m_Schemas.front(); } void cWorldStorage::Execute(void) { while (!m_ShouldTerminate) { m_Event.Wait(); // Process both queues until they are empty again: bool Success; do { if (m_ShouldTerminate) { return; } Success = LoadOneChunk(); Success |= SaveOneChunk(); } while (Success); } } bool cWorldStorage::LoadOneChunk(void) { // Dequeue an item, bail out if there's none left: cChunkCoords ToLoad(0, 0); bool ShouldLoad = m_LoadQueue.TryDequeueItem(ToLoad); if (!ShouldLoad) { return false; } // Load the chunk: LoadChunk(ToLoad.m_ChunkX, ToLoad.m_ChunkZ); return true; } bool cWorldStorage::SaveOneChunk(void) { // Dequeue one chunk to save: cChunkCoords ToSave(0, 0); bool ShouldSave = m_SaveQueue.TryDequeueItem(ToSave); if (!ShouldSave) { return false; } // Save the chunk, if it's valid: if (m_World->IsChunkValid(ToSave.m_ChunkX, ToSave.m_ChunkZ)) { m_World->MarkChunkSaving(ToSave.m_ChunkX, ToSave.m_ChunkZ); if (m_SaveSchema->SaveChunk(cChunkCoords(ToSave.m_ChunkX, ToSave.m_ChunkZ))) { m_World->MarkChunkSaved(ToSave.m_ChunkX, ToSave.m_ChunkZ); } } return true; } bool cWorldStorage::LoadChunk(int a_ChunkX, int a_ChunkZ) { ASSERT(m_World->IsChunkQueued(a_ChunkX, a_ChunkZ)); cChunkCoords Coords(a_ChunkX, a_ChunkZ); // First try the schema that is used for saving if (m_SaveSchema->LoadChunk(Coords)) { return true; } // If it didn't have the chunk, try all the other schemas: for (cWSSchemaList::iterator itr = m_Schemas.begin(); itr != m_Schemas.end(); ++itr) { if (((*itr) != m_SaveSchema) && (*itr)->LoadChunk(Coords)) { return true; } } // Notify the chunk owner that the chunk failed to load (sets cChunk::m_HasLoadFailed to true): m_World->ChunkLoadFailed(a_ChunkX, a_ChunkZ); return false; } ================================================ FILE: src/WorldStorage/WorldStorage.h ================================================ // WorldStorage.h // Interfaces to the cWorldStorage class representing the chunk loading / saving thread // This class decides which storage schema to use for saving; it queries all available schemas for loading // Also declares the base class for all storage schemas, cWSSchema // Helper serialization class cJsonChunkSerializer is declared as well #pragma once #include "../OSSupport/IsThread.h" #include "../OSSupport/Queue.h" #include "ChunkDef.h" // fwd: class cWorld; /** Interface that all the world storage schemas need to implement */ class cWSSchema abstract { public: cWSSchema(cWorld * a_World) : m_World(a_World) {} virtual ~cWSSchema() {} // Force the descendants' destructors to be virtual virtual bool LoadChunk(const cChunkCoords & a_Chunk) = 0; virtual bool SaveChunk(const cChunkCoords & a_Chunk) = 0; virtual const AString GetName(void) const = 0; protected: cWorld * m_World; } ; typedef std::list cWSSchemaList; /** The actual world storage class */ class cWorldStorage: public cIsThread { using Super = cIsThread; public: cWorldStorage(); virtual ~cWorldStorage() override; /** Queues a chunk to be loaded, asynchronously. */ void QueueLoadChunk(int a_ChunkX, int a_ChunkZ); /** Queues a chunk to be saved, asynchronously. */ void QueueSaveChunk(int a_ChunkX, int a_ChunkZ); /** Initializes the storage schemas, ready to be started. */ void Initialize(cWorld & a_World, const AString & a_StorageSchemaName, int a_StorageCompressionFactor); void Stop(void); // Hide the cIsThread's Stop() method, we need to signal the event void WaitForFinish(void); void WaitForLoadQueueEmpty(void); void WaitForSaveQueueEmpty(void); size_t GetLoadQueueLength(void); size_t GetSaveQueueLength(void); protected: cWorld * m_World; AString m_StorageSchemaName; cQueue m_LoadQueue; cQueue m_SaveQueue; /** All the storage schemas (all used for loading) */ cWSSchemaList m_Schemas; /** The one storage schema used for saving */ cWSSchema * m_SaveSchema; /** Set when there's any addition to the queues */ cEvent m_Event; /** Loads the chunk specified; returns true on success, false on failure */ bool LoadChunk(int a_ChunkX, int a_ChunkZ); void InitSchemas(int a_StorageCompressionFactor); virtual void Execute(void) override; /** Loads one chunk from the queue (if any queued); returns true if there was a chunk in the queue to load */ bool LoadOneChunk(void); /** Saves one chunk from the queue (if any queued); returns true if there was a chunk in the queue to save */ bool SaveOneChunk(void); } ; ================================================ FILE: src/XMLParser.h ================================================ // XMLParser.h // Interfaces to the CXMLParser class representing the base class for XML parsing // To use, derive a class from this base and override its OnStartElement(), OnEndElement() and OnCharacters() functions #pragma once #include "expat/expat.h" class CXMLParser { public: CXMLParser(void); virtual ~CXMLParser(); // The actual parsing, may be called several times; the last time needs iIsFinal == true (-> flush) int Parse(const char * iData, size_t iLength, bool iIsFinal = false); private: // LibExpat stuff: XML_Parser mParser; static void StartElementHandler(void * iContext, const XML_Char * iElement, const XML_Char ** iAttributes) { ((CXMLParser *)iContext)->OnStartElement(iElement, iAttributes); } static void EndElementHandler (void * iContext, const XML_Char * iElement) { ((CXMLParser *)iContext)->OnEndElement(iElement); } static void CharacterDataHandler (void * iContext, const XML_Char * iData, int iLength) { ((CXMLParser *)iContext)->OnCharacters(iData, iLength); } protected: virtual void OnStartElement(const XML_Char * iElement, const XML_Char ** iAttributes) = 0; virtual void OnEndElement (const XML_Char * iElement) = 0; virtual void OnCharacters (const XML_Char * iCharacters, int iLength) = 0; } ; //////////////////////////////////////////////////////////////////////////////// // The following template has been modified from code available at // https://www.codeproject.com/Articles/1847/C-Wrappers-for-the-Expat-XML-Parser // It uses templates to remove the virtual function call penalty (both size and speed) for each callback /* Usage: 1, Declare a subclass: class CMyParser : public CExpatImpl 2, Declare handlers that you want in that subclass: void CMyParser::OnEndElement(const XML_Char * iTagName); 3, Create an instance of your class: CMyParser Parser; 4, Call Create(): Parser.Create(nullptr, nullptr); 4, Call Parse(), repeatedly: Parser.Parse(Buffer, Length); */ template class CExpatImpl { // @access Constructors and destructors public: // @cmember General constructor CExpatImpl () { m_p = nullptr; } // @cmember Destructor ~CExpatImpl () { Destroy (); } // @access Parser creation and deletion methods public: // @cmember Create a parser bool Create (const XML_Char * pszEncoding = nullptr, const XML_Char * pszSep = nullptr) { // Destroy the old parser Destroy (); // If the encoding or seperator are empty, then nullptr if ((pszEncoding != nullptr) && (pszEncoding[0] == 0)) { pszEncoding = nullptr; } if ((pszSep != nullptr) && (pszSep[0] == 0)) { pszSep = nullptr; } // Create the new parser m_p = XML_ParserCreate_MM (pszEncoding, nullptr, pszSep); if (m_p == nullptr) { return false; } // Invoke the post create routine _T * pThis = static_cast <_T *> (this); pThis ->OnPostCreate (); // Set the user data used in callbacks XML_SetUserData (m_p, (void *) this); return true; } // @cmember Destroy the parser void Destroy (void) { if (m_p != nullptr) { XML_ParserFree (m_p); } m_p = nullptr; } // @cmember Parse a block of data bool Parse (const char *pszBuffer, int nLength, bool fIsFinal = true) { assert (m_p != nullptr); return (XML_Parse (m_p, pszBuffer, nLength, fIsFinal) != 0); } // @cmember Parse internal buffer bool ParseBuffer (int nLength, bool fIsFinal = true) { assert (m_p != nullptr); return XML_ParseBuffer (m_p, nLength, fIsFinal) != 0; } // @cmember Get the internal buffer void *GetBuffer (int nLength) { assert (m_p != nullptr); return XML_GetBuffer (m_p, nLength); } protected: // Parser callback enable / disable methods: // @cmember Enable / Disable the start element handler void EnableStartElementHandler (bool fEnable = true) { assert (m_p != nullptr); XML_SetStartElementHandler (m_p, fEnable ? StartElementHandler : nullptr); } // @cmember Enable / Disable the end element handler void EnableEndElementHandler (bool fEnable = true) { assert (m_p != nullptr); XML_SetEndElementHandler (m_p, fEnable ? EndElementHandler : nullptr); } // @cmember Enable / Disable the element handlers void EnableElementHandler (bool fEnable = true) { assert (m_p != nullptr); EnableStartElementHandler (fEnable); EnableEndElementHandler (fEnable); } // @cmember Enable / Disable the character data handler void EnableCharacterDataHandler (bool fEnable = true) { assert (m_p != nullptr); XML_SetCharacterDataHandler (m_p, fEnable ? CharacterDataHandler : nullptr); } // @cmember Enable / Disable the processing instruction handler void EnableProcessingInstructionHandler (bool fEnable = true) { assert (m_p != nullptr); XML_SetProcessingInstructionHandler (m_p, fEnable ? ProcessingInstructionHandler : nullptr); } // @cmember Enable / Disable the comment handler void EnableCommentHandler (bool fEnable = true) { assert (m_p != nullptr); XML_SetCommentHandler (m_p, fEnable ? CommentHandler : nullptr); } // @cmember Enable / Disable the start CDATA section handler void EnableStartCdataSectionHandler (bool fEnable = true) { assert (m_p != nullptr); XML_SetStartCdataSectionHandler (m_p, fEnable ? StartCdataSectionHandler : nullptr); } // @cmember Enable / Disable the end CDATA section handler void EnableEndCdataSectionHandler (bool fEnable = true) { assert (m_p != nullptr); XML_SetEndCdataSectionHandler (m_p, fEnable ? EndCdataSectionHandler : nullptr); } // @cmember Enable / Disable the CDATA section handlers void EnableCdataSectionHandler (bool fEnable = true) { assert (m_p != nullptr); EnableStartCdataSectionHandler (fEnable); EnableEndCdataSectionHandler (fEnable); } // @cmember Enable / Disable default handler void EnableDefaultHandler (bool fEnable = true, bool fExpand = true) { assert (m_p != nullptr); if (fExpand) { XML_SetDefaultHandlerExpand (m_p, fEnable ? DefaultHandler : nullptr); } else { XML_SetDefaultHandler (m_p, fEnable ? DefaultHandler : nullptr); } } // @cmember Enable / Disable external entity ref handler void EnableExternalEntityRefHandler (bool fEnable = true) { assert (m_p != nullptr); XML_SetExternalEntityRefHandler (m_p, fEnable ? ExternalEntityRefHandler : nullptr); } // @cmember Enable / Disable unknown encoding handler void EnableUnknownEncodingHandler (bool fEnable = true) { assert (m_p != nullptr); XML_SetUnknownEncodingHandler (m_p, fEnable ? UnknownEncodingHandler : nullptr); } // @cmember Enable / Disable start namespace handler void EnableStartNamespaceDeclHandler (bool fEnable = true) { assert (m_p != nullptr); XML_SetStartNamespaceDeclHandler (m_p, fEnable ? StartNamespaceDeclHandler : nullptr); } // @cmember Enable / Disable end namespace handler void EnableEndNamespaceDeclHandler (bool fEnable = true) { assert (m_p != nullptr); XML_SetEndNamespaceDeclHandler (m_p, fEnable ? EndNamespaceDeclHandler : nullptr); } // @cmember Enable / Disable namespace handlers void EnableNamespaceDeclHandler (bool fEnable = true) { EnableStartNamespaceDeclHandler (fEnable); EnableEndNamespaceDeclHandler (fEnable); } // @cmember Enable / Disable the XML declaration handler void EnableXmlDeclHandler (bool fEnable = true) { assert (m_p != nullptr); XML_SetXmlDeclHandler (m_p, fEnable ? XmlDeclHandler : nullptr); } // @cmember Enable / Disable the start DOCTYPE declaration handler void EnableStartDoctypeDeclHandler (bool fEnable = true) { assert (m_p != nullptr); XML_SetStartDoctypeDeclHandler (m_p, fEnable ? StartDoctypeDeclHandler : nullptr); } // @cmember Enable / Disable the end DOCTYPE declaration handler void EnableEndDoctypeDeclHandler (bool fEnable = true) { assert (m_p != nullptr); XML_SetEndDoctypeDeclHandler (m_p, fEnable ? EndDoctypeDeclHandler : nullptr); } // @cmember Enable / Disable the DOCTYPE declaration handler void EnableDoctypeDeclHandler (bool fEnable = true) { assert (m_p != nullptr); EnableStartDoctypeDeclHandler (fEnable); EnableEndDoctypeDeclHandler (fEnable); } public: // Parser error reporting methods // @cmember Get last error enum XML_Error GetErrorCode () { assert (m_p != nullptr); return XML_GetErrorCode (m_p); } // @cmember Get the current byte index long GetCurrentByteIndex () { assert (m_p != nullptr); return XML_GetCurrentByteIndex (m_p); } // @cmember Get the current line number int GetCurrentLineNumber () { assert (m_p != nullptr); return XML_GetCurrentLineNumber (m_p); } // @cmember Get the current column number int GetCurrentColumnNumber () { assert (m_p != nullptr); return XML_GetCurrentColumnNumber (m_p); } // @cmember Get the current byte count int GetCurrentByteCount () { assert (m_p != nullptr); return XML_GetCurrentByteCount (m_p); } // @cmember Get the input context const char *GetInputContext (int *pnOffset, int *pnSize) { assert (m_p != nullptr); return XML_GetInputContext (m_p, pnOffset, pnSize); } // @cmember Get last error string const XML_LChar *GetErrorString () { return XML_ErrorString (GetErrorCode ()); } // @cmember Return the version string static const XML_LChar *GetExpatVersion () { return XML_ExpatVersion (); } // @cmember Get the version information static void GetExpatVersion (int *pnMajor, int *pnMinor, int *pnMicro) { XML_expat_version v = XML_ExpatVersionInfo (); if (pnMajor) { *pnMajor = v .major; } if (pnMinor) { *pnMinor = v .minor; } if (pnMicro) { *pnMicro = v .micro; } } // @cmember Get last error string static const XML_LChar *GetErrorString (enum XML_Error nError) { return XML_ErrorString (nError); } // Public handler methods: // The template parameter should provide their own implementation for those handlers that they want // @cmember Start element handler void OnStartElement (const XML_Char *pszName, const XML_Char **papszAttrs) { return; } // @cmember End element handler void OnEndElement (const XML_Char *pszName) { return; } // @cmember Character data handler void OnCharacterData (const XML_Char *pszData, int nLength) { return; } // @cmember Processing instruction handler void OnProcessingInstruction (const XML_Char *pszTarget, const XML_Char *pszData) { return; } // @cmember Comment handler void OnComment (const XML_Char *pszData) { return; } // @cmember Start CDATA section handler void OnStartCdataSection () { return; } // @cmember End CDATA section handler void OnEndCdataSection () { return; } // @cmember Default handler void OnDefault (const XML_Char *pszData, int nLength) { return; } // @cmember External entity ref handler bool OnExternalEntityRef (const XML_Char *pszContext, const XML_Char *pszBase, const XML_Char *pszSystemID, const XML_Char *pszPublicID) { return false; } // @cmember Unknown encoding handler bool OnUnknownEncoding (const XML_Char *pszName, XML_Encoding *pInfo) { return false; } // @cmember Start namespace declaration handler void OnStartNamespaceDecl (const XML_Char *pszPrefix, const XML_Char *pszURI) { return; } // @cmember End namespace declaration handler void OnEndNamespaceDecl (const XML_Char *pszPrefix) { return; } // @cmember XML declaration handler void OnXmlDecl (const XML_Char *pszVersion, const XML_Char *pszEncoding, bool fStandalone) { return; } // @cmember Start DOCTYPE declaration handler void OnStartDoctypeDecl (const XML_Char *pszDoctypeName, const XML_Char *pszSysID, const XML_Char *pszPubID, bool fHasInternalSubset) { return; } // @cmember End DOCTYPE declaration handler void OnEndDoctypeDecl () { return; } // @access Protected methods protected: // @cmember Handle any post creation void OnPostCreate () { } // @access Protected static methods protected: // @cmember Start element handler wrapper static void __cdecl StartElementHandler (void *pUserData, const XML_Char *pszName, const XML_Char **papszAttrs) { _T *pThis = static_cast <_T *> ((CExpatImpl <_T> *) pUserData); pThis ->OnStartElement (pszName, papszAttrs); } // @cmember End element handler wrapper static void __cdecl EndElementHandler (void *pUserData, const XML_Char *pszName) { _T *pThis = static_cast <_T *> ((CExpatImpl <_T> *) pUserData); pThis ->OnEndElement (pszName); } // @cmember Character data handler wrapper static void __cdecl CharacterDataHandler (void *pUserData, const XML_Char *pszData, int nLength) { _T *pThis = static_cast <_T *> ((CExpatImpl <_T> *) pUserData); pThis ->OnCharacterData (pszData, nLength); } // @cmember Processing instruction handler wrapper static void __cdecl ProcessingInstructionHandler (void *pUserData, const XML_Char *pszTarget, const XML_Char *pszData) { _T *pThis = static_cast <_T *> ((CExpatImpl <_T> *) pUserData); pThis ->OnProcessingInstruction (pszTarget, pszData); } // @cmember Comment handler wrapper static void __cdecl CommentHandler (void *pUserData, const XML_Char *pszData) { _T *pThis = static_cast <_T *> ((CExpatImpl <_T> *) pUserData); pThis ->OnComment (pszData); } // @cmember Start CDATA section wrapper static void __cdecl StartCdataSectionHandler (void *pUserData) { _T *pThis = static_cast <_T *> ((CExpatImpl <_T> *) pUserData); pThis ->OnStartCdataSection (); } // @cmember End CDATA section wrapper static void __cdecl EndCdataSectionHandler (void *pUserData) { _T *pThis = static_cast <_T *> ((CExpatImpl <_T> *) pUserData); pThis ->OnEndCdataSection (); } // @cmember Default wrapper static void __cdecl DefaultHandler (void *pUserData, const XML_Char *pszData, int nLength) { _T *pThis = static_cast <_T *> ((CExpatImpl <_T> *) pUserData); pThis ->OnDefault (pszData, nLength); } // @cmember External entity ref wrapper static int __cdecl ExternalEntityRefHandler (void *pUserData, const XML_Char *pszContext, const XML_Char *pszBase, const XML_Char *pszSystemID, const XML_Char *pszPublicID) { _T *pThis = static_cast <_T *> ((CExpatImpl <_T> *) pUserData); return pThis ->OnExternalEntityRef (pszContext, pszBase, pszSystemID, pszPublicID) ? 1 : 0; } // @cmember Unknown encoding wrapper static int __cdecl UnknownEncodingHandler (void * pUserData, const XML_Char * pszName, XML_Encoding * pInfo) { _T *pThis = static_cast <_T *> ((CExpatImpl <_T> *) pUserData); return pThis ->OnUnknownEncoding (pszName, pInfo) ? 1 : 0; } // @cmember Start namespace decl wrapper static void __cdecl StartNamespaceDeclHandler (void * pUserData, const XML_Char * pszPrefix, const XML_Char * pszURI) { _T *pThis = static_cast <_T *> ((CExpatImpl <_T> *) pUserData); pThis ->OnStartNamespaceDecl (pszPrefix, pszURI); } // @cmember End namespace decl wrapper static void __cdecl EndNamespaceDeclHandler (void * pUserData, const XML_Char * pszPrefix) { _T *pThis = static_cast <_T *> ((CExpatImpl <_T> *) pUserData); pThis ->OnEndNamespaceDecl (pszPrefix); } // @cmember XML declaration wrapper static void __cdecl XmlDeclHandler (void *pUserData, const XML_Char *pszVersion, const XML_Char *pszEncoding, int nStandalone) { _T *pThis = static_cast <_T *> ((CExpatImpl <_T> *) pUserData); pThis ->OnXmlDecl (pszVersion, pszEncoding, nStandalone != 0); } // @cmember Start Doctype declaration wrapper static void __cdecl StartDoctypeDeclHandler ( void *pUserData, const XML_Char *pszDoctypeName, const XML_Char *pszSysID, const XML_Char *pszPubID, int nHasInternalSubset ) { _T *pThis = static_cast <_T *> ((CExpatImpl <_T> *) pUserData); pThis ->OnStartDoctypeDecl (pszDoctypeName, pszSysID, pszPubID, nHasInternalSubset != 0); } // @cmember End Doctype declaration wrapper static void __cdecl EndDoctypeDeclHandler (void *pUserData) { _T *pThis = static_cast <_T *> ((CExpatImpl <_T> *) pUserData); pThis ->OnEndDoctypeDecl (); } protected: XML_Parser m_p; /** Returns the value of the specified attribute, if found; nullptr otherwise */ static const XML_Char * FindAttr(const XML_Char ** iAttrs, const XML_Char * iAttrToFind) { for (const XML_Char ** Attr = iAttrs; *Attr != nullptr; Attr += 2) { if (strcmp(*Attr, iAttrToFind) == 0) { return *(Attr + 1); } } // for Attr - iAttrs[] return nullptr; } } ; ================================================ FILE: src/fmt.h ================================================ #pragma once #ifdef __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wsign-conversion" #pragma clang diagnostic ignored "-Wsigned-enum-bitfield" #endif #include #include #ifdef __clang__ #pragma clang diagnostic pop #endif ================================================ FILE: src/main.cpp ================================================ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "main.h" #include "BuildInfo.h" #include "Logger.h" #include "MemorySettingsRepository.h" #include "Root.h" #include "tclap/CmdLine.h" #include "OSSupport/ConsoleSignalHandler.h" #include "OSSupport/NetworkSingleton.h" #include "OSSupport/MiniDumpWriter.h" #include "OSSupport/SleepResolutionBooster.h" #include "OSSupport/StartAsService.h" #include bool g_ShouldLogCommIn; bool g_ShouldLogCommOut; bool g_RunAsService; bool g_DetachedStdin; //////////////////////////////////////////////////////////////////////////////// // ParseArguments - Read the startup arguments and store into a settings object static void ParseArguments(int argc, char ** argv, cMemorySettingsRepository & a_Settings) { // Parse the comand line args: TCLAP::CmdLine cmd("Cuberite"); TCLAP::ValueArg slotsArg ("s", "max-players", "Maximum number of slots for the server to use, overrides setting in setting.ini", false, -1, "number", cmd); TCLAP::ValueArg confArg ("c", "config-file", "Config file to use", false, "settings.ini", "string", cmd); TCLAP::MultiArg portsArg ("p", "port", "The port number the server should listen to", false, "port", cmd); TCLAP::SwitchArg commLogArg ("", "log-comm", "Log server client communications to file", cmd); TCLAP::SwitchArg commLogInArg ("", "log-comm-in", "Log inbound server client communications to file", cmd); TCLAP::SwitchArg commLogOutArg ("", "log-comm-out", "Log outbound server client communications to file", cmd); TCLAP::SwitchArg crashDumpFull ("", "crash-dump-full", "Crashdumps created by the server will contain full server memory", cmd); TCLAP::SwitchArg crashDumpGlobals("", "crash-dump-globals", "Crashdumps created by the server will contain the global variables' values", cmd); TCLAP::SwitchArg noBufArg ("", "no-output-buffering", "Disable output buffering", cmd); TCLAP::SwitchArg noFileLogArg ("", "no-log-file", "Disable logging to file", cmd); TCLAP::SwitchArg runAsServiceArg ("d", "service", "Run as a service on Windows, or daemon on UNIX like systems", cmd); TCLAP::SwitchArg runDetached ("", "detached", "Run with detached stdin (useful for container/docker)", cmd); cmd.parse(argc, argv); // Copy the parsed args' values into a settings repository: if (runDetached.getValue()) { g_DetachedStdin = true; } if (confArg.isSet()) { AString conf_file = confArg.getValue(); a_Settings.AddValue("Server", "ConfigFile", conf_file); } if (slotsArg.isSet()) { int slots = slotsArg.getValue(); a_Settings.AddValue("Server", "MaxPlayers", static_cast(slots)); } if (portsArg.isSet()) { for (auto port: portsArg.getValue()) { a_Settings.AddValue("Server", "Ports", std::to_string(port)); } } if (noFileLogArg.getValue()) { a_Settings.AddValue("Server", "DisableLogFile", true); } if (commLogArg.getValue()) { g_ShouldLogCommIn = true; g_ShouldLogCommOut = true; } else { g_ShouldLogCommIn = commLogInArg.getValue(); g_ShouldLogCommOut = commLogOutArg.getValue(); } if (noBufArg.getValue()) { setvbuf(stdout, nullptr, _IONBF, 0); } a_Settings.SetReadOnly(); if (runAsServiceArg.getValue()) { g_RunAsService = true; } // Apply the CrashDump flags for platforms that support them: if (crashDumpGlobals.getValue()) { MiniDumpWriter::AddDumpFlags(MiniDumpFlags::WithDataSegments); } if (crashDumpFull.getValue()) { MiniDumpWriter::AddDumpFlags(MiniDumpFlags::WithFullMemory); } } //////////////////////////////////////////////////////////////////////////////// // UniversalMain - Main startup logic for both standard running and as a service static int UniversalMain(int argc, char * argv[], const bool a_RunningAsService) { const struct MiniDumpWriterRAII { MiniDumpWriterRAII() { // Registers a last chance exception handler to write a minidump on crash: MiniDumpWriter::Register(); } ~MiniDumpWriterRAII() { MiniDumpWriter::Unregister(); } } MiniDumpWriter; const struct SleepResolutionBoosterRAII { SleepResolutionBoosterRAII() { // Boost timer resolution to keep TPS high: SleepResolutionBooster::Register(); } ~SleepResolutionBoosterRAII() { SleepResolutionBooster::Unregister(); } } SleepResolutionBooster; // Register signal handlers, enabling graceful shutdown from the terminal: ConsoleSignalHandler::Register(); // Initialize logging subsystem: cLogger::InitiateMultithreading(); try { cMemorySettingsRepository Settings; ParseArguments(argc, argv, Settings); // Make sure g_RunAsService is set correctly before checking its value. // Attempt to run as a service: if (g_RunAsService && !a_RunningAsService) { // This will either fork or call UniversalMain again: if (StartAsService::MakeIntoService<&UniversalMain>()) { return EXIT_SUCCESS; } } while (true) { const struct NetworkRAII { NetworkRAII() { // Initialize LibEvent: cNetworkSingleton::Get().Initialise(); } ~NetworkRAII() { // Shutdown all of LibEvent: cNetworkSingleton::Get().Terminate(); } } LibEvent; cRoot Root; if (!Root.Run(Settings)) { break; } } return EXIT_SUCCESS; } catch (const fmt::format_error & Oops) { std::cerr << "Formatting exception: " << Oops.what() << '\n'; } catch (const TCLAP::ArgException & Oops) { std::cerr << fmt::sprintf("Error reading command line {} for argument {}\n", Oops.error(), Oops.argId()); } catch (const std::exception & Oops) { std::cerr << "Standard exception: " << Oops.what() << '\n'; } catch (...) { std::cerr << "Unknown exception!\n"; } return EXIT_FAILURE; } int main(int argc, char ** argv) { #if !defined(NDEBUG) && defined(_MSC_VER) _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); // _X: The simple built-in CRT leak finder - simply break when allocating the Nth block ({N} is listed in the leak output) // Only useful when the leak is in the same sequence all the time // _CrtSetBreakAlloc(85950); #endif // !NDEBUG && _MSC_VER return UniversalMain(argc, argv, false); } ================================================ FILE: src/main.h ================================================ #pragma once /** If set to true, the protocols will log each player's incoming (C->S) communication to a per-connection logfile. */ extern bool g_ShouldLogCommIn; /** If set to true, the protocols will log each player's outgoing (S->C) communication to a per-connection logfile. */ extern bool g_ShouldLogCommOut; /** If set to true, binary will attempt to run as a service. */ extern bool g_RunAsService; /** If set to true, binary runs in foreground without cstding handles */ extern bool g_DetachedStdin; ================================================ FILE: src/mbedTLS++/AesCfb128Decryptor.cpp ================================================ // AesCfb128Decryptor.cpp // Implements the cAesCfb128Decryptor class decrypting data using AES CFB-128 #include "Globals.h" #include "AesCfb128Decryptor.h" cAesCfb128Decryptor::cAesCfb128Decryptor(void) : m_IsValid(false) { #if PLATFORM_CRYPTOGRAPHY && defined(_WIN32) if (!CryptAcquireContext(&m_Aes, nullptr, nullptr, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) { throw std::system_error(GetLastError(), std::system_category()); } #else mbedtls_aes_init(&m_Aes); #endif } cAesCfb128Decryptor::~cAesCfb128Decryptor() { // Clear the leftover in-memory data, so that they can't be accessed by a backdoor: #if PLATFORM_CRYPTOGRAPHY && defined(_WIN32) CryptReleaseContext(m_Aes, 0); #else mbedtls_aes_free(&m_Aes); #endif } void cAesCfb128Decryptor::Init(const Byte a_Key[16], const Byte a_IV[16]) { ASSERT(!IsValid()); // Cannot Init twice #if PLATFORM_CRYPTOGRAPHY && defined(_WIN32) struct Key { PUBLICKEYSTRUC Header; DWORD Length; Byte Key[16]; } Key; const DWORD Mode = CRYPT_MODE_CFB; Key.Header = { PLAINTEXTKEYBLOB, CUR_BLOB_VERSION, 0, CALG_AES_128 }; Key.Length = 16; std::copy_n(a_Key, 16, Key.Key); CryptImportKey(m_Aes, reinterpret_cast(&Key), sizeof(Key), 0, 0, &m_Key); CryptSetKeyParam(m_Key, KP_MODE, reinterpret_cast(&Mode), 0); CryptSetKeyParam(m_Key, KP_IV, a_IV, 0); #else std::copy_n(a_IV, 16, m_IV); mbedtls_aes_setkey_enc(&m_Aes, a_Key, 128); #endif m_IsValid = true; } void cAesCfb128Decryptor::ProcessData(std::byte * const a_EncryptedIn, const size_t a_Length) { ASSERT(IsValid()); // Must Init() first #if PLATFORM_CRYPTOGRAPHY && defined(_WIN32) ASSERT(a_Length <= std::numeric_limits::max()); DWORD Length = static_cast(a_Length); CryptDecrypt(m_Key, 0, FALSE, 0, reinterpret_cast(a_EncryptedIn), &Length); #else mbedtls_aes_crypt_cfb8(&m_Aes, MBEDTLS_AES_DECRYPT, a_Length, m_IV, reinterpret_cast(a_EncryptedIn), reinterpret_cast(a_EncryptedIn)); #endif } ================================================ FILE: src/mbedTLS++/AesCfb128Decryptor.h ================================================ // AesCfb128Decryptor.h // Declares the cAesCfb128Decryptor class decrypting data using AES CFB-128 #pragma once #if PLATFORM_CRYPTOGRAPHY && defined(_WIN32) #include #else #include "mbedtls/aes.h" #endif /** Decrypts data using the AES / CFB 128 algorithm */ class cAesCfb128Decryptor { public: cAesCfb128Decryptor(void); ~cAesCfb128Decryptor(); /** Initializes the decryptor with the specified Key / IV */ void Init(const Byte a_Key[16], const Byte a_IV[16]); /** Decrypts a_Length bytes of the encrypted data in-place; produces a_Length output bytes */ void ProcessData(std::byte * a_EncryptedIn, size_t a_Length); /** Returns true if the object has been initialized with the Key / IV */ bool IsValid(void) const { return m_IsValid; } protected: #if PLATFORM_CRYPTOGRAPHY && defined(_WIN32) HCRYPTPROV m_Aes; HCRYPTKEY m_Key; #else mbedtls_aes_context m_Aes; #endif /** The InitialVector, used by the CFB mode decryption */ Byte m_IV[16]; /** Indicates whether the object has been initialized with the Key / IV */ bool m_IsValid; } ; ================================================ FILE: src/mbedTLS++/AesCfb128Encryptor.cpp ================================================ // AesCfb128Encryptor.cpp // Implements the cAesCfb128Encryptor class encrypting data using AES CFB-128 #include "Globals.h" #include "AesCfb128Encryptor.h" cAesCfb128Encryptor::cAesCfb128Encryptor(void): m_IsValid(false) { mbedtls_aes_init(&m_Aes); } cAesCfb128Encryptor::~cAesCfb128Encryptor() { // Clear the leftover in-memory data, so that they can't be accessed by a backdoor mbedtls_aes_free(&m_Aes); } void cAesCfb128Encryptor::Init(const Byte a_Key[16], const Byte a_IV[16]) { ASSERT(!IsValid()); // Cannot Init twice memcpy(m_IV, a_IV, 16); mbedtls_aes_setkey_enc(&m_Aes, a_Key, 128); m_IsValid = true; } void cAesCfb128Encryptor::ProcessData(std::byte * const a_PlainIn, const size_t a_Length) { ASSERT(IsValid()); // Must Init() first mbedtls_aes_crypt_cfb8(&m_Aes, MBEDTLS_AES_ENCRYPT, a_Length, m_IV, reinterpret_cast(a_PlainIn), reinterpret_cast(a_PlainIn)); } ================================================ FILE: src/mbedTLS++/AesCfb128Encryptor.h ================================================ // AesCfb128Encryptor.h // Declares the cAesCfb128Encryptor class encrypting data using AES CFB-128 #pragma once #include "mbedtls/aes.h" /** Encrypts data using the AES / CFB (128) algorithm */ class cAesCfb128Encryptor { public: cAesCfb128Encryptor(void); ~cAesCfb128Encryptor(); /** Initializes the decryptor with the specified Key / IV */ void Init(const Byte a_Key[16], const Byte a_IV[16]); /** Encrypts a_Length bytes of the plain data in-place; produces a_Length output bytes */ void ProcessData(std::byte * a_PlainIn, size_t a_Length); /** Returns true if the object has been initialized with the Key / IV */ bool IsValid(void) const { return m_IsValid; } protected: mbedtls_aes_context m_Aes; /** The InitialVector, used by the CFB mode encryption */ Byte m_IV[16]; /** Indicates whether the object has been initialized with the Key / IV */ bool m_IsValid; } ; ================================================ FILE: src/mbedTLS++/BlockingSslClientSocket.cpp ================================================ // BlockingSslClientSocket.cpp // Implements the cBlockingSslClientSocket class representing a blocking TCP socket with client SSL encryption over it #include "Globals.h" #include "BlockingSslClientSocket.h" //////////////////////////////////////////////////////////////////////////////// // cBlockingSslClientSocketConnectCallbacks: class cBlockingSslClientSocketConnectCallbacks: public cNetwork::cConnectCallbacks { /** The socket object that is using this instance of the callbacks. */ cBlockingSslClientSocket & m_Socket; virtual void OnConnected(cTCPLink & a_Link) override { m_Socket.OnConnected(); } virtual void OnError(int a_ErrorCode, const AString & a_ErrorMsg) override { m_Socket.OnConnectError(a_ErrorMsg); } public: cBlockingSslClientSocketConnectCallbacks(cBlockingSslClientSocket & a_Socket): m_Socket(a_Socket) { } }; //////////////////////////////////////////////////////////////////////////////// // cBlockingSslClientSocketLinkCallbacks: class cBlockingSslClientSocketLinkCallbacks: public cTCPLink::cCallbacks { cBlockingSslClientSocket & m_Socket; virtual void OnLinkCreated(cTCPLinkPtr a_Link) override { m_Socket.SetLink(a_Link); } virtual void OnReceivedData(const char * a_Data, size_t a_Length) override { m_Socket.OnReceivedData(a_Data, a_Length); } virtual void OnRemoteClosed(void) override { m_Socket.OnDisconnected(); } virtual void OnError(int a_ErrorCode, const AString & a_ErrorMsg) override { m_Socket.OnDisconnected(); } public: cBlockingSslClientSocketLinkCallbacks(cBlockingSslClientSocket & a_Socket): m_Socket(a_Socket) { } }; //////////////////////////////////////////////////////////////////////////////// // cBlockingSslClientSocket: cBlockingSslClientSocket::cBlockingSslClientSocket(void) : m_Ssl(*this), m_IsConnected(false) { // Nothing needed yet } bool cBlockingSslClientSocket::Connect(const AString & a_ServerName, UInt16 a_Port) { // If already connected, report an error: if (m_IsConnected) { // TODO: Handle this better - if connected to the same server and port, and the socket is alive, return success m_LastErrorText = "Already connected"; return false; } // Connect the underlying socket: m_ServerName = a_ServerName; if (!cNetwork::Connect(a_ServerName, a_Port, std::make_shared(*this), std::make_shared(*this)) ) { return false; } // Wait for the connection to succeed or fail: m_Event.Wait(); if (!m_IsConnected) { return false; } // Initialize the SSL: int ret = 0; if (m_Config != nullptr) { ret = m_Ssl.Initialize(m_Config); } else { ret = m_Ssl.Initialize(true); } if (ret != 0) { m_LastErrorText = fmt::format(FMT_STRING("SSL initialization failed: -0x{:x}"), -ret); return false; } // If we have been assigned a trusted CA root cert store, push it into the SSL context: if (!m_ExpectedPeerName.empty()) { m_Ssl.SetExpectedPeerName(m_ExpectedPeerName); } ret = m_Ssl.Handshake(); if (ret != 0) { m_LastErrorText = fmt::format(FMT_STRING("SSL handshake failed: -0x{:x}"), -ret); return false; } return true; } void cBlockingSslClientSocket::SetExpectedPeerName(AString a_ExpectedPeerName) { ASSERT(!m_IsConnected); // Must be called before connect // Warn if used multiple times, but don't signal an error: if (!m_ExpectedPeerName.empty()) { LOGWARNING( "SSL: Trying to set multiple expected peer names, only the last one will be used. %s overwriting the previous %s", a_ExpectedPeerName, m_ExpectedPeerName ); } m_ExpectedPeerName = std::move(a_ExpectedPeerName); } void cBlockingSslClientSocket::SetSslConfig(std::shared_ptr a_Config) { ASSERT(!m_IsConnected); // Must be called before connect // Warn if used multiple times, but don't signal an error: if (m_Config != nullptr) { LOGWARNING("SSL: Trying to set multiple configurations, only the last one will be used."); } m_Config = std::move(a_Config); } bool cBlockingSslClientSocket::Send(const void * a_Data, size_t a_NumBytes) { if (!m_IsConnected) { m_LastErrorText = "Socket is closed"; return false; } // Keep sending the data until all of it is sent: const char * Data = static_cast(a_Data); size_t NumBytes = a_NumBytes; for (;;) { int res = m_Ssl.WritePlain(Data, a_NumBytes); if (res < 0) { ASSERT(res != MBEDTLS_ERR_SSL_WANT_READ); // This should never happen with callback-based SSL ASSERT(res != MBEDTLS_ERR_SSL_WANT_WRITE); // This should never happen with callback-based SSL m_LastErrorText = fmt::format(FMT_STRING("Data cannot be written to SSL context: -0x{:x}"), -res); return false; } else { Data += res; NumBytes -= static_cast(res); if (NumBytes == 0) { return true; } } } } int cBlockingSslClientSocket::Receive(void * a_Data, size_t a_MaxBytes) { // Even if m_IsConnected is false (socket disconnected), the SSL context may have more data in the queue int res = m_Ssl.ReadPlain(a_Data, a_MaxBytes); if (res < 0) { m_LastErrorText = fmt::format(FMT_STRING("Data cannot be read from SSL context: -0x{:x}"), -res); } return res; } void cBlockingSslClientSocket::Disconnect() { // Ignore if not connected if (!m_IsConnected) { return; } m_Ssl.NotifyClose(); m_IsConnected = false; // Grab a copy of the socket so that we know it doesn't change under our hands: auto socket = m_Socket; if (socket != nullptr) { socket->Close(); } m_Socket.reset(); } int cBlockingSslClientSocket::ReceiveEncrypted(unsigned char * a_Buffer, size_t a_NumBytes) { // Wait for any incoming data, if there is none: cCSLock Lock(m_CSIncomingData); while (m_IsConnected && m_IncomingData.empty()) { cCSUnlock Unlock(Lock); m_Event.Wait(); } // If we got disconnected, report an error after processing all data: if (!m_IsConnected && m_IncomingData.empty()) { return MBEDTLS_ERR_NET_RECV_FAILED; } // Copy the data from the incoming buffer into the specified space: size_t NumToCopy = std::min(a_NumBytes, m_IncomingData.size()); memcpy(a_Buffer, m_IncomingData.data(), NumToCopy); m_IncomingData.erase(0, NumToCopy); return static_cast(NumToCopy); } int cBlockingSslClientSocket::SendEncrypted(const unsigned char * a_Buffer, size_t a_NumBytes) { cTCPLinkPtr Socket(m_Socket); // Make a copy so that multiple threads don't race on deleting the socket. if (Socket == nullptr) { return MBEDTLS_ERR_NET_SEND_FAILED; } if (!Socket->Send(a_Buffer, a_NumBytes)) { // mbedTLS's net routines distinguish between connection reset and general failure, we don't need to return MBEDTLS_ERR_NET_SEND_FAILED; } return static_cast(a_NumBytes); } void cBlockingSslClientSocket::OnConnected(void) { m_IsConnected = true; m_Event.Set(); } void cBlockingSslClientSocket::OnConnectError(const AString & a_ErrorMsg) { LOG("Cannot connect to %s: \"%s\"", m_ServerName.c_str(), a_ErrorMsg.c_str()); m_Event.Set(); } void cBlockingSslClientSocket::OnReceivedData(const char * a_Data, size_t a_Size) { { cCSLock Lock(m_CSIncomingData); m_IncomingData.append(a_Data, a_Size); } m_Event.Set(); } void cBlockingSslClientSocket::SetLink(cTCPLinkPtr a_Link) { m_Socket = std::move(a_Link); } void cBlockingSslClientSocket::OnDisconnected(void) { m_IsConnected = false; m_Socket.reset(); m_Event.Set(); } ================================================ FILE: src/mbedTLS++/BlockingSslClientSocket.h ================================================ // BlockingSslClientSocket.h // Declares the cBlockingSslClientSocket class representing a blocking TCP socket with client SSL encryption over it #pragma once #include "../OSSupport/Network.h" #include "CallbackSslContext.h" class cBlockingSslClientSocket : protected cCallbackSslContext::cDataCallbacks { public: cBlockingSslClientSocket(void); virtual ~cBlockingSslClientSocket(void) override { Disconnect(); } /** Connects to the specified server and performs SSL handshake. Returns true if successful, false on failure. Sets internal error text on failure. */ bool Connect(const AString & a_ServerName, UInt16 a_Port); /** Sends the specified data over the connection. Returns true if successful, false on failure. Sets the internal error text on failure. */ bool Send(const void * a_Data, size_t a_NumBytes); /** Receives data from the connection. Blocks until there is any data available, then returns as much as possible. Returns the number of bytes actually received, negative number on failure. Sets the internal error text on failure. */ int Receive(void * a_Data, size_t a_MaxBytes); /** Disconnects the connection gracefully, if possible. Note that this also frees the internal SSL context, so all the certificates etc. are lost. */ void Disconnect(void); /** Sets the Expected peer name. Needs to be used before calling Connect(). \param a_ExpectedPeerName Name that we expect to receive in the SSL peer's cert; verification will fail if the presented name is different (possible MITM). */ void SetExpectedPeerName(AString a_ExpectedPeerName); /** Set the config to be used by the SSL context. Config must not be modified after calling connect. */ void SetSslConfig(std::shared_ptr a_Config); /** Returns the text of the last error that has occurred in this instance. */ const AString & GetLastErrorText(void) const { return m_LastErrorText; } protected: friend class cBlockingSslClientSocketConnectCallbacks; friend class cBlockingSslClientSocketLinkCallbacks; /** The SSL context used for the socket */ cCallbackSslContext m_Ssl; /** The underlying socket to the SSL server */ cTCPLinkPtr m_Socket; /** The object used to signal state changes in the socket (the cause of the blocking). */ cEvent m_Event; /** The configuration to be used by the SSL context. Set by SetSslConfig(). */ std::shared_ptr m_Config; /** The expected SSL peer's name, if we are to verify the cert strictly. Set by SetExpectedPeerName(). */ AString m_ExpectedPeerName; /** The hostname to which the socket is connecting (stored for error reporting). */ AString m_ServerName; /** Text of the last error that has occurred. */ AString m_LastErrorText; /** Set to true if the connection established successfully. */ std::atomic m_IsConnected; /** Protects m_IncomingData against multithreaded access. */ cCriticalSection m_CSIncomingData; /** Buffer for the data incoming on the network socket. Protected by m_CSIncomingData. */ AString m_IncomingData; /** Called when the connection is established successfully. */ void OnConnected(void); /** Called when an error occurs while connecting the socket. */ void OnConnectError(const AString & a_ErrorMsg); /** Called when there's incoming data from the socket. */ void OnReceivedData(const char * a_Data, size_t a_Size); /** Called when the link for the connection is created. */ void SetLink(cTCPLinkPtr a_Link); /** Called when the link is disconnected, either gracefully or by an error. */ void OnDisconnected(void); // cCallbackSslContext::cDataCallbacks overrides: virtual int ReceiveEncrypted(unsigned char * a_Buffer, size_t a_NumBytes) override; virtual int SendEncrypted(const unsigned char * a_Buffer, size_t a_NumBytes) override; } ; ================================================ FILE: src/mbedTLS++/BufferedSslContext.cpp ================================================ // BufferedSslContext.cpp // Implements the cBufferedSslContext class representing a SSL context with the SSL peer data backed by a cByteBuffer #include "Globals.h" #include "BufferedSslContext.h" cBufferedSslContext::cBufferedSslContext(size_t a_BufferSize): m_OutgoingData(a_BufferSize), m_IncomingData(a_BufferSize) { } size_t cBufferedSslContext::WriteIncoming(const void * a_Data, size_t a_NumBytes) { size_t NumBytes = std::min(m_IncomingData.GetFreeSpace(), a_NumBytes); if (NumBytes > 0) { m_IncomingData.Write(a_Data, NumBytes); return NumBytes; } return 0; } size_t cBufferedSslContext::ReadOutgoing(void * a_Data, size_t a_DataMaxSize) { size_t NumBytes = std::min(m_OutgoingData.GetReadableSpace(), a_DataMaxSize); if (NumBytes > 0) { m_OutgoingData.ReadBuf(a_Data, NumBytes); m_OutgoingData.CommitRead(); return NumBytes; } return 0; } int cBufferedSslContext::ReceiveEncrypted(unsigned char * a_Buffer, size_t a_NumBytes) { // Called when mbedTLS wants to read encrypted data from the SSL peer // Read the data from the buffer inside this object, where the owner has stored them using WriteIncoming(): size_t NumBytes = std::min(a_NumBytes, m_IncomingData.GetReadableSpace()); if (NumBytes == 0) { return MBEDTLS_ERR_SSL_WANT_READ; } if (!m_IncomingData.ReadBuf(a_Buffer, NumBytes)) { m_IncomingData.ResetRead(); return MBEDTLS_ERR_NET_RECV_FAILED; } m_IncomingData.CommitRead(); return static_cast(NumBytes); } int cBufferedSslContext::SendEncrypted(const unsigned char * a_Buffer, size_t a_NumBytes) { // Called when mbedTLS wants to write encrypted data to the SSL peer // Write the data into the buffer inside this object, where the owner can later read them using ReadOutgoing(): if (!m_OutgoingData.CanWriteBytes(a_NumBytes)) { return MBEDTLS_ERR_SSL_WANT_WRITE; } if (!m_OutgoingData.Write(reinterpret_cast(a_Buffer), a_NumBytes)) { return MBEDTLS_ERR_NET_SEND_FAILED; } return static_cast(a_NumBytes); } ================================================ FILE: src/mbedTLS++/BufferedSslContext.h ================================================ // BufferedSslContext.h // Declares the cBufferedSslContext class representing a SSL context with the SSL peer data backed by a cByteBuffer #pragma once #include "SslContext.h" #include "ErrorCodes.h" class cBufferedSslContext: public cSslContext { using Super = cSslContext; public: /** Creates a new context with the buffers of specified size for the encrypted / decrypted data. */ cBufferedSslContext(size_t a_BufferSize = 64000); /** Stores the specified data in the "incoming" buffer, to be process by the SSL decryptor. This is the data received from the SSL peer. Returns the number of bytes actually stored. If 0 is returned, owner should check the error state. */ size_t WriteIncoming(const void * a_Data, size_t a_NumBytes); /** Retrieves data from the "outgoing" buffer, after being processed by the SSL encryptor. This is the data to be sent to the SSL peer. Returns the number of bytes actually retrieved. */ size_t ReadOutgoing(void * a_Data, size_t a_DataMaxSize); protected: /** Buffer for the data that has been encrypted into the SSL stream and should be sent out. */ cByteBuffer m_OutgoingData; /** Buffer for the data that has come in and needs to be decrypted from the SSL stream. */ cByteBuffer m_IncomingData; // cSslContext overrides: virtual int ReceiveEncrypted(unsigned char * a_Buffer, size_t a_NumBytes) override; virtual int SendEncrypted(const unsigned char * a_Buffer, size_t a_NumBytes) override; } ; ================================================ FILE: src/mbedTLS++/CMakeLists.txt ================================================ target_sources( ${CMAKE_PROJECT_NAME} PRIVATE AesCfb128Decryptor.cpp AesCfb128Encryptor.cpp BlockingSslClientSocket.cpp BufferedSslContext.cpp CallbackSslContext.cpp CtrDrbgContext.cpp CryptoKey.cpp EntropyContext.cpp RsaPrivateKey.cpp Sha1Checksum.cpp SslConfig.cpp SslContext.cpp X509Cert.cpp AesCfb128Decryptor.h AesCfb128Encryptor.h BlockingSslClientSocket.h BufferedSslContext.h CallbackSslContext.h CtrDrbgContext.h CryptoKey.h EntropyContext.h ErrorCodes.h RsaPrivateKey.h SslConfig.h SslContext.h Sha1Checksum.h X509Cert.h ) ================================================ FILE: src/mbedTLS++/CallbackSslContext.cpp ================================================ // CallbackSslContext.cpp // Declares the cCallbackSslContext class representing a SSL context wrapper that uses callbacks to read and write SSL peer data #include "Globals.h" #include "CallbackSslContext.h" cCallbackSslContext::cCallbackSslContext(void) : m_Callbacks(nullptr) { // Nothing needed, but the constructor needs to exist so } cCallbackSslContext::cCallbackSslContext(cCallbackSslContext::cDataCallbacks & a_Callbacks) : m_Callbacks(&a_Callbacks) { } int cCallbackSslContext::ReceiveEncrypted(unsigned char * a_Buffer, size_t a_NumBytes) { if (m_Callbacks == nullptr) { LOGWARNING("SSL: Trying to receive data with no callbacks, aborting."); return MBEDTLS_ERR_NET_RECV_FAILED; } return m_Callbacks->ReceiveEncrypted(a_Buffer, a_NumBytes); } int cCallbackSslContext::SendEncrypted(const unsigned char * a_Buffer, size_t a_NumBytes) { if (m_Callbacks == nullptr) { LOGWARNING("SSL: Trying to send data with no callbacks, aborting."); return MBEDTLS_ERR_NET_SEND_FAILED; } return m_Callbacks->SendEncrypted(a_Buffer, a_NumBytes); } ================================================ FILE: src/mbedTLS++/CallbackSslContext.h ================================================ // CallbackSslContext.h // Declares the cCallbackSslContext class representing a SSL context wrapper that uses callbacks to read and write SSL peer data #pragma once #include "SslContext.h" #include "ErrorCodes.h" class cCallbackSslContext : public cSslContext { public: /** Interface used as a data sink for the SSL peer data. */ class cDataCallbacks { public: // Force a virtual destructor in descendants: virtual ~cDataCallbacks() {} /** Called when mbedTLS wants to read encrypted data from the SSL peer. The returned value is the number of bytes received, or a mbedTLS error on failure. The implementation can return MBEDTLS_ERR_SSL_WANT_READ or MBEDTLS_ERR_SSL_WANT_WRITE to indicate that there's currently no more data and that there might be more data in the future. In such cases the SSL operation that invoked this call will terminate with the same return value, so that the owner is notified of this condition and can potentially restart the operation later on. */ virtual int ReceiveEncrypted(unsigned char * a_Buffer, size_t a_NumBytes) = 0; /** Called when mbedTLS wants to write encrypted data to the SSL peer. The returned value is the number of bytes sent, or a mbedTLS error on failure. The implementation can return MBEDTLS_ERR_SSL_WANT_READ or MBEDTLS_ERR_SSL_WANT_WRITE to indicate that there's currently no more data and that there might be more data in the future. In such cases the SSL operation that invoked this call will terminate with the same return value, so that the owner is notified of this condition and can potentially restart the operation later on. */ virtual int SendEncrypted(const unsigned char * a_Buffer, size_t a_NumBytes) = 0; } ; /** Creates a new SSL context with no callbacks assigned */ cCallbackSslContext(void); /** Creates a new SSL context with the specified callbacks */ cCallbackSslContext(cDataCallbacks & a_Callbacks); protected: /** The callbacks to use to send and receive SSL peer data */ cDataCallbacks * m_Callbacks; // cSslContext overrides: virtual int ReceiveEncrypted(unsigned char * a_Buffer, size_t a_NumBytes) override; virtual int SendEncrypted(const unsigned char * a_Buffer, size_t a_NumBytes) override; }; ================================================ FILE: src/mbedTLS++/CryptoKey.cpp ================================================ // CryptoKey.cpp // Implements the cCryptoKey class representing a RSA public key in mbedTLS #include "Globals.h" #include "CryptoKey.h" cCryptoKey::cCryptoKey(void) { mbedtls_pk_init(&m_Pk); m_CtrDrbg.Initialize("rsa_pubkey", 10); } cCryptoKey::cCryptoKey(const AString & a_PublicKeyData) { mbedtls_pk_init(&m_Pk); m_CtrDrbg.Initialize("rsa_pubkey", 10); int res = ParsePublic(a_PublicKeyData.data(), a_PublicKeyData.size()); if (res != 0) { LOGWARNING("Failed to parse public key: -0x%x", res); ASSERT(!"Cannot parse PubKey"); return; } } cCryptoKey::cCryptoKey(const AString & a_PrivateKeyData, const AString & a_Password) { mbedtls_pk_init(&m_Pk); m_CtrDrbg.Initialize("rsa_privkey", 11); int res = ParsePrivate(a_PrivateKeyData.data(), a_PrivateKeyData.size(), a_Password); if (res != 0) { LOGWARNING("Failed to parse private key: -0x%x", res); ASSERT(!"Cannot parse PrivKey"); return; } } cCryptoKey::~cCryptoKey() { mbedtls_pk_free(&m_Pk); } int cCryptoKey::Decrypt(const Byte * a_EncryptedData, size_t a_EncryptedLength, Byte * a_DecryptedData, size_t a_DecryptedMaxLength) { ASSERT(IsValid()); size_t DecryptedLen = a_DecryptedMaxLength; int res = mbedtls_pk_decrypt(&m_Pk, a_EncryptedData, a_EncryptedLength, a_DecryptedData, &DecryptedLen, a_DecryptedMaxLength, mbedtls_ctr_drbg_random, m_CtrDrbg.GetInternal() ); if (res != 0) { return res; } return static_cast(DecryptedLen); } int cCryptoKey::Encrypt(const Byte * a_PlainData, size_t a_PlainLength, Byte * a_EncryptedData, size_t a_EncryptedMaxLength) { ASSERT(IsValid()); size_t EncryptedLength = a_EncryptedMaxLength; int res = mbedtls_pk_encrypt(&m_Pk, a_PlainData, a_PlainLength, a_EncryptedData, &EncryptedLength, a_EncryptedMaxLength, mbedtls_ctr_drbg_random, m_CtrDrbg.GetInternal() ); if (res != 0) { return res; } return static_cast(EncryptedLength); } int cCryptoKey::ParsePublic(const void * a_Data, size_t a_NumBytes) { ASSERT(!IsValid()); // Cannot parse a second key return mbedtls_pk_parse_public_key(&m_Pk, static_cast(a_Data), a_NumBytes); } int cCryptoKey::ParsePrivate(const void * a_Data, size_t a_NumBytes, const AString & a_Password) { ASSERT(!IsValid()); // Cannot parse a second key // mbedTLS requires that PEM-encoded data is passed including the terminating NUL byte, // and DER-encoded data is decoded properly even with an extra trailing NUL byte, so we simply add one to everything: AString keyData(static_cast(a_Data), a_NumBytes); if (a_Password.empty()) { return mbedtls_pk_parse_key( &m_Pk, reinterpret_cast(keyData.data()), a_NumBytes + 1, nullptr, 0, mbedtls_ctr_drbg_random, m_CtrDrbg.GetInternal()); } else { return mbedtls_pk_parse_key( &m_Pk, reinterpret_cast(keyData.data()), a_NumBytes + 1, reinterpret_cast(a_Password.c_str()), a_Password.size(), mbedtls_ctr_drbg_random, m_CtrDrbg.GetInternal() ); } } bool cCryptoKey::IsValid(void) const { return (mbedtls_pk_get_type(&m_Pk) != MBEDTLS_PK_NONE); } ================================================ FILE: src/mbedTLS++/CryptoKey.h ================================================ // CryptoKey.h // Declares the cCryptoKey class representing a RSA public key in mbedTLS #pragma once #include "CtrDrbgContext.h" #include "mbedtls/pk.h" class cCryptoKey { friend class cSslConfig; public: /** Constructs an empty key instance. Before use, it needs to be filled by ParsePublic() or ParsePrivate() */ cCryptoKey(void); /** Constructs the public key out of the DER- or PEM-encoded pubkey data */ cCryptoKey(const AString & a_PublicKeyData); /** Constructs the private key out of the DER- or PEM-encoded privkey data, with the specified password. If a_Password is empty, no password is assumed. */ cCryptoKey(const AString & a_PrivateKeyData, const AString & a_Password); ~cCryptoKey(); /** Decrypts the data using the stored public key Both a_EncryptedData and a_DecryptedData must be at least bytes large. Returns the number of bytes decrypted, or negative number for error. */ int Decrypt(const Byte * a_EncryptedData, size_t a_EncryptedLength, Byte * a_DecryptedData, size_t a_DecryptedMaxLength); /** Encrypts the data using the stored public key Both a_EncryptedData and a_DecryptedData must be at least bytes large. Returns the number of bytes decrypted, or negative number for error. */ int Encrypt(const Byte * a_PlainData, size_t a_PlainLength, Byte * a_EncryptedData, size_t a_EncryptedMaxLength); /** Parses the specified data into a public key representation. The key can be DER- or PEM-encoded. Returns 0 on success, mbedTLS error code on failure. */ int ParsePublic(const void * a_Data, size_t a_NumBytes); /** Parses the specified data into a private key representation. If a_Password is empty, no password is assumed. The key can be DER- or PEM-encoded. Returns 0 on success, mbedTLS error code on failure. */ int ParsePrivate(const void * a_Data, size_t a_NumBytes, const AString & a_Password); /** Returns true if the contained key is valid. */ bool IsValid(void) const; protected: /** The mbedTLS representation of the key data */ mbedtls_pk_context m_Pk; /** The random generator used in encryption and decryption */ cCtrDrbgContext m_CtrDrbg; /** Returns the internal context ptr. Only use in mbedTLS API calls. */ mbedtls_pk_context * GetInternal(void) { return &m_Pk; } } ; typedef std::shared_ptr cCryptoKeyPtr; ================================================ FILE: src/mbedTLS++/CtrDrbgContext.cpp ================================================ // CtrDrbgContext.cpp // Implements the cCtrDrbgContext class representing a wrapper over CTR-DRBG implementation in mbedTLS #include "Globals.h" #include "CtrDrbgContext.h" #include "EntropyContext.h" cCtrDrbgContext::cCtrDrbgContext(void) : m_EntropyContext(std::make_shared()), m_IsValid(false) { mbedtls_ctr_drbg_init(&m_CtrDrbg); } cCtrDrbgContext::cCtrDrbgContext(const std::shared_ptr & a_EntropyContext) : m_EntropyContext(a_EntropyContext), m_IsValid(false) { mbedtls_ctr_drbg_init(&m_CtrDrbg); } int cCtrDrbgContext::Initialize(const void * a_Custom, size_t a_CustomSize) { if (m_IsValid) { // Already initialized return 0; } int res = mbedtls_ctr_drbg_seed(&m_CtrDrbg, mbedtls_entropy_func, &(m_EntropyContext->m_Entropy), static_cast(a_Custom), a_CustomSize); m_IsValid = (res == 0); return res; } ================================================ FILE: src/mbedTLS++/CtrDrbgContext.h ================================================ // CtrDrbgContext.h // Declares the cCtrDrbgContext class representing a wrapper over CTR-DRBG implementation in mbedTLS #pragma once #include "mbedtls/ctr_drbg.h" // fwd: EntropyContext.h class cEntropyContext; class cCtrDrbgContext { friend class cSslConfig; friend class cRsaPrivateKey; friend class cCryptoKey; public: /** Constructs the context with a new entropy context. */ cCtrDrbgContext(void); /** Constructs the context with the specified entropy context. */ cCtrDrbgContext(const std::shared_ptr & a_EntropyContext); /** Initializes the context. a_Custom is optional additional data to use for entropy, nullptr is accepted. Returns 0 if successful, mbedTLS error code on failure. */ int Initialize(const void * a_Custom, size_t a_CustomSize); /** Returns true if the object is valid (has been initialized properly) */ bool IsValid(void) const { return m_IsValid; } protected: /** The entropy source used for generating the random */ std::shared_ptr m_EntropyContext; /** The random generator context */ mbedtls_ctr_drbg_context m_CtrDrbg; /** Set to true if the object is valid (has been initialized properly) */ bool m_IsValid; /** Returns the internal context ptr. Only use in mbedTLS API calls. */ mbedtls_ctr_drbg_context * GetInternal(void) { return &m_CtrDrbg; } } ; ================================================ FILE: src/mbedTLS++/EntropyContext.cpp ================================================ // EntropyContext.cpp // Implements the cEntropyContext class representing a wrapper over entropy contexts in mbedTLS #include "Globals.h" #include "EntropyContext.h" cEntropyContext::cEntropyContext(void) { mbedtls_entropy_init(&m_Entropy); } cEntropyContext::~cEntropyContext() { mbedtls_entropy_free(&m_Entropy); } ================================================ FILE: src/mbedTLS++/EntropyContext.h ================================================ // EntropyContext.h // Declares the cEntropyContext class representing a wrapper over entropy contexts in mbedTLS #pragma once #include "mbedtls/entropy.h" class cEntropyContext { friend class cCtrDrbgContext; public: cEntropyContext(void); ~cEntropyContext(); protected: mbedtls_entropy_context m_Entropy; } ; ================================================ FILE: src/mbedTLS++/ErrorCodes.h ================================================ /** Error codes from mbedtls net_sockets.h */ // TODO: Replace with std::error_code #define MBEDTLS_ERR_NET_SOCKET_FAILED -0x0042 /**< Failed to open a socket. */ #define MBEDTLS_ERR_NET_CONNECT_FAILED -0x0044 /**< The connection to the given server / port failed. */ #define MBEDTLS_ERR_NET_BIND_FAILED -0x0046 /**< Binding of the socket failed. */ #define MBEDTLS_ERR_NET_LISTEN_FAILED -0x0048 /**< Could not listen on the socket. */ #define MBEDTLS_ERR_NET_ACCEPT_FAILED -0x004A /**< Could not accept the incoming connection. */ #define MBEDTLS_ERR_NET_RECV_FAILED -0x004C /**< Reading information from the socket failed. */ #define MBEDTLS_ERR_NET_SEND_FAILED -0x004E /**< Sending information through the socket failed. */ #define MBEDTLS_ERR_NET_CONN_RESET -0x0050 /**< Connection was reset by peer. */ #define MBEDTLS_ERR_NET_UNKNOWN_HOST -0x0052 /**< Failed to get an IP address for the given hostname. */ #define MBEDTLS_ERR_NET_BUFFER_TOO_SMALL -0x0043 /**< Buffer is too small to hold the data. */ #define MBEDTLS_ERR_NET_INVALID_CONTEXT -0x0045 /**< The context is invalid, eg because it was free()ed. */ ================================================ FILE: src/mbedTLS++/RsaPrivateKey.cpp ================================================ // RsaPrivateKey.cpp #include "Globals.h" #include "RsaPrivateKey.h" #include "mbedtls/pk.h" cRsaPrivateKey::cRsaPrivateKey(void) { mbedtls_rsa_init(&m_Rsa); m_CtrDrbg.Initialize("RSA", 3); } cRsaPrivateKey::cRsaPrivateKey(const cRsaPrivateKey & a_Other) { mbedtls_rsa_init(&m_Rsa); mbedtls_rsa_copy(&m_Rsa, &a_Other.m_Rsa); m_CtrDrbg.Initialize("RSA", 3); } cRsaPrivateKey::~cRsaPrivateKey() { mbedtls_rsa_free(&m_Rsa); } bool cRsaPrivateKey::Generate(unsigned a_KeySizeBits) { int res = mbedtls_rsa_gen_key(&m_Rsa, mbedtls_ctr_drbg_random, m_CtrDrbg.GetInternal(), a_KeySizeBits, 65537); if (res != 0) { LOG("RSA key generation failed: -0x%x", -res); return false; } return true; } ContiguousByteBuffer cRsaPrivateKey::GetPubKeyDER(void) { class cPubKey { public: cPubKey(mbedtls_rsa_context * a_Rsa) : m_IsValid(false) { mbedtls_pk_init(&m_Key); if (mbedtls_pk_setup(&m_Key, mbedtls_pk_info_from_type(MBEDTLS_PK_RSA)) != 0) { ASSERT(!"Cannot init PrivKey context"); return; } if (mbedtls_rsa_copy(mbedtls_pk_rsa(m_Key), a_Rsa) != 0) { ASSERT(!"Cannot copy PrivKey to PK context"); return; } m_IsValid = true; } ~cPubKey() { if (m_IsValid) { mbedtls_pk_free(&m_Key); } } operator mbedtls_pk_context * (void) { return &m_Key; } protected: bool m_IsValid; mbedtls_pk_context m_Key; } PkCtx(&m_Rsa); unsigned char buf[3000]; int res = mbedtls_pk_write_pubkey_der(PkCtx, buf, sizeof(buf)); if (res < 0) { return {}; } return { reinterpret_cast(buf + sizeof(buf) - res), static_cast(res) }; } int cRsaPrivateKey::Decrypt(const ContiguousByteBufferView a_EncryptedData, Byte * a_DecryptedData, size_t a_DecryptedMaxLength) { const auto KeyLength = mbedtls_rsa_get_len(&m_Rsa); if (a_EncryptedData.size() < KeyLength) { LOGD("%s: Invalid a_EncryptedLength: got %zu, exp at least %zu", __FUNCTION__, a_EncryptedData.size(), KeyLength); ASSERT(!"Invalid a_DecryptedMaxLength!"); return -1; } if (a_DecryptedMaxLength < KeyLength) { LOGD("%s: Invalid a_DecryptedMaxLength: got %zu, exp at least %zu", __FUNCTION__, a_DecryptedMaxLength, KeyLength); ASSERT(!"Invalid a_DecryptedMaxLength!"); return -1; } size_t DecryptedLength; int res = mbedtls_rsa_pkcs1_decrypt( &m_Rsa, mbedtls_ctr_drbg_random, m_CtrDrbg.GetInternal(), &DecryptedLength, reinterpret_cast(a_EncryptedData.data()), a_DecryptedData, a_DecryptedMaxLength ); if (res != 0) { return -1; } return static_cast(DecryptedLength); } ================================================ FILE: src/mbedTLS++/RsaPrivateKey.h ================================================ // RsaPrivateKey.h // Declares the cRsaPrivateKey class representing a private key for RSA operations. #pragma once #include "CtrDrbgContext.h" #include "mbedtls/rsa.h" /** Encapsulates an RSA private key used in PKI cryptography */ class cRsaPrivateKey { friend class cSslContext; public: /** Creates a new empty object, the key is not assigned */ cRsaPrivateKey(void); /** Deep-copies the key from a_Other */ cRsaPrivateKey(const cRsaPrivateKey & a_Other); ~cRsaPrivateKey(); /** Generates a new key within this object, with the specified size in bits. Returns true on success, false on failure. */ bool Generate(unsigned a_KeySizeBits = 1024); /** Returns the public key part encoded in ASN1 DER encoding */ ContiguousByteBuffer GetPubKeyDER(void); /** Decrypts the data using RSAES-PKCS#1 algorithm. Both a_EncryptedData and a_DecryptedData must be at least bytes large. Returns the number of bytes decrypted, or negative number for error. */ int Decrypt(ContiguousByteBufferView a_EncryptedData, Byte * a_DecryptedData, size_t a_DecryptedMaxLength); protected: /** The mbedTLS key context */ mbedtls_rsa_context m_Rsa; /** The random generator used for generating the key and encryption / decryption */ cCtrDrbgContext m_CtrDrbg; /** Returns the internal context ptr. Only use in mbedTLS API calls. */ mbedtls_rsa_context * GetInternal(void) { return &m_Rsa; } } ; typedef std::shared_ptr cRsaPrivateKeyPtr; ================================================ FILE: src/mbedTLS++/Sha1Checksum.cpp ================================================ // Sha1Checksum.cpp // Declares the cSha1Checksum class representing the SHA-1 checksum calculator #include "Globals.h" #include "Sha1Checksum.h" /* // Self-test the hash formatting for known values: // sha1(Notch) : 4ed1f46bbe04bc756bcb17c0c7ce3e4632f06a48 // sha1(jeb_) : -7c9d5b0044c130109a5d7b5fb5c317c02b4e28c1 // sha1(simon) : 88e16a1019277b15d58faf0541e11910eb756f6 static class Test { public: Test(void) { AString DigestNotch, DigestJeb, DigestSimon; Byte Digest[20]; cSha1Checksum Checksum; Checksum.Update((const Byte *)"Notch", 5); Checksum.Finalize(Digest); cSha1Checksum::DigestToJava(Digest, DigestNotch); Checksum.Restart(); Checksum.Update((const Byte *)"jeb_", 4); Checksum.Finalize(Digest); cSha1Checksum::DigestToJava(Digest, DigestJeb); Checksum.Restart(); Checksum.Update((const Byte *)"simon", 5); Checksum.Finalize(Digest); cSha1Checksum::DigestToJava(Digest, DigestSimon); printf("Notch: \"%s\"\n", DigestNotch.c_str()); printf("jeb_: \"%s\"\n", DigestJeb.c_str()); printf("simon: \"%s\"\n", DigestSimon.c_str()); assert(DigestNotch == "4ed1f46bbe04bc756bcb17c0c7ce3e4632f06a48"); assert(DigestJeb == "-7c9d5b0044c130109a5d7b5fb5c317c02b4e28c1"); assert(DigestSimon == "88e16a1019277b15d58faf0541e11910eb756f6"); } } test; */ //////////////////////////////////////////////////////////////////////////////// // cSha1Checksum: cSha1Checksum::cSha1Checksum(void) : m_DoesAcceptInput(true) { mbedtls_sha1_starts(&m_Sha1); } void cSha1Checksum::Update(const Byte * a_Data, size_t a_Length) { ASSERT(m_DoesAcceptInput); // Not Finalize()-d yet, or Restart()-ed mbedtls_sha1_update(&m_Sha1, a_Data, a_Length); } void cSha1Checksum::Finalize(cSha1Checksum::Checksum & a_Output) { ASSERT(m_DoesAcceptInput); // Not Finalize()-d yet, or Restart()-ed mbedtls_sha1_finish(&m_Sha1, a_Output); m_DoesAcceptInput = false; } void cSha1Checksum::DigestToHex(const Checksum & a_Digest, AString & a_Out) { a_Out.clear(); a_Out.reserve(40); for (int i = 0; i < 20; i++) { a_Out.append(fmt::format(FMT_STRING("{:02x}"), a_Digest[i])); } } void cSha1Checksum::DigestToJava(const Checksum & a_Digest, AString & a_Out) { Checksum Digest; memcpy(Digest, a_Digest, sizeof(Digest)); bool IsNegative = (Digest[0] >= 0x80); if (IsNegative) { // Two's complement: bool carry = true; // Add one to the whole number for (int i = 19; i >= 0; i--) { Digest[i] = ~Digest[i]; if (carry) { carry = (Digest[i] == 0xff); Digest[i]++; } } } a_Out.clear(); a_Out.reserve(40); for (int i = 0; i < 20; i++) { a_Out.append(fmt::format(FMT_STRING("{:02x}"), Digest[i])); } while ((a_Out.length() > 0) && (a_Out[0] == '0')) { a_Out.erase(0, 1); } if (IsNegative) { a_Out.insert(0, "-"); } } void cSha1Checksum::Restart(void) { mbedtls_sha1_starts(&m_Sha1); m_DoesAcceptInput = true; } ================================================ FILE: src/mbedTLS++/Sha1Checksum.h ================================================ // Sha1Checksum.h // Declares the cSha1Checksum class representing the SHA-1 checksum calculator #pragma once #include "mbedtls/sha1.h" /** Calculates a SHA1 checksum for data stream */ class cSha1Checksum { public: typedef Byte Checksum[20]; // The type used for storing the checksum cSha1Checksum(void); /** Adds the specified data to the checksum */ void Update(const Byte * a_Data, size_t a_Length); /** Calculates and returns the final checksum */ void Finalize(Checksum & a_Output); /** Returns true if the object is accepts more input data, false if Finalize()-d (need to Restart()) */ bool DoesAcceptInput(void) const { return m_DoesAcceptInput; } /** Converts a SHA1 digest into hex */ static void DigestToHex(const Checksum & a_Digest, AString & a_Out); /** Converts a raw 160-bit SHA1 digest into a Java Hex representation According to http://wiki.vg/Protocol_Encryption */ static void DigestToJava(const Checksum & a_Digest, AString & a_Out); /** Clears the current context and start a new checksum calculation */ void Restart(void); protected: /** True if the object is accepts more input data, false if Finalize()-d (need to Restart()) */ bool m_DoesAcceptInput; mbedtls_sha1_context m_Sha1; } ; ================================================ FILE: src/mbedTLS++/SslConfig.cpp ================================================ #include "Globals.h" #include "mbedTLS++/SslConfig.h" #include "mbedTLS++/CryptoKey.h" #include "mbedTLS++/EntropyContext.h" #include "mbedTLS++/X509Cert.h" // This allows us to debug SSL and certificate problems, but produce way too much output, // so it's disabled until someone needs it // #define ENABLE_SSL_DEBUG_MSG #if !defined(NDEBUG) && defined(ENABLE_SSL_DEBUG_MSG) #include "mbedtls/debug.h" namespace { void SSLDebugMessage(void * a_UserParam, int a_Level, const char * a_Filename, int a_LineNo, const char * a_Text) { if (a_Level > 3) { // Don't want the trace messages return; } // Remove the terminating LF: size_t len = strlen(a_Text) - 1; while ((len > 0) && (a_Text[len] <= 32)) { len--; } AString Text(a_Text, len + 1); LOGD("SSL (%d): %s", a_Level, Text.c_str()); } int SSLVerifyCert(void * a_This, mbedtls_x509_crt * a_Crt, int a_Depth, uint32_t * a_Flags) { char buf[1024]; UNUSED(a_This); LOG("Verify requested for (Depth %d):", a_Depth); mbedtls_x509_crt_info(buf, sizeof(buf) - 1, "", a_Crt); LOG("%s", buf); uint32_t Flags = *a_Flags; if ((Flags & MBEDTLS_X509_BADCERT_EXPIRED) != 0) { LOG(" ! server certificate has expired"); } if ((Flags & MBEDTLS_X509_BADCERT_REVOKED) != 0) { LOG(" ! server certificate has been revoked"); } if ((Flags & MBEDTLS_X509_BADCERT_CN_MISMATCH) != 0) { LOG(" ! CN mismatch"); } if ((Flags & MBEDTLS_X509_BADCERT_NOT_TRUSTED) != 0) { LOG(" ! self-signed or not signed by a trusted CA"); } if ((Flags & MBEDTLS_X509_BADCRL_NOT_TRUSTED) != 0) { LOG(" ! CRL not trusted"); } if ((Flags & MBEDTLS_X509_BADCRL_EXPIRED) != 0) { LOG(" ! CRL expired"); } if ((Flags & MBEDTLS_X509_BADCERT_OTHER) != 0) { LOG(" ! other (unknown) flag"); } if (Flags == 0) { LOG(" This certificate has no flags"); } return 0; } } #endif // !defined(NDEBUG) && defined(ENABLE_SSL_DEBUG_MSG) //////////////////////////////////////////////////////////////////////////////// // cSslConfig: cSslConfig::cSslConfig() { mbedtls_ssl_config_init(&m_Config); } cSslConfig::~cSslConfig() { mbedtls_ssl_config_free(&m_Config); } int cSslConfig::InitDefaults(const bool a_IsClient) { return mbedtls_ssl_config_defaults( &m_Config, a_IsClient ? MBEDTLS_SSL_IS_CLIENT : MBEDTLS_SSL_IS_SERVER, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT ); } void cSslConfig::SetAuthMode(const eSslAuthMode a_AuthMode) { const int Mode = [=]() { switch (a_AuthMode) { case eSslAuthMode::None: return MBEDTLS_SSL_VERIFY_NONE; case eSslAuthMode::Optional: return MBEDTLS_SSL_VERIFY_OPTIONAL; case eSslAuthMode::Required: return MBEDTLS_SSL_VERIFY_REQUIRED; case eSslAuthMode::Unset: return MBEDTLS_SSL_VERIFY_UNSET; } UNREACHABLE("Unsupported SSL auth mode"); }(); mbedtls_ssl_conf_authmode(&m_Config, Mode); } void cSslConfig::SetRng(cCtrDrbgContextPtr a_CtrDrbg) { ASSERT(a_CtrDrbg != nullptr); m_CtrDrbg = std::move(a_CtrDrbg); mbedtls_ssl_conf_rng(&m_Config, mbedtls_ctr_drbg_random, &m_CtrDrbg->m_CtrDrbg); } void cSslConfig::SetDebugCallback(cDebugCallback a_CallbackFun, void * a_CallbackData) { mbedtls_ssl_conf_dbg(&m_Config, a_CallbackFun, a_CallbackData); } void cSslConfig::SetOwnCert(cX509CertPtr a_OwnCert, cCryptoKeyPtr a_OwnCertPrivKey) { ASSERT(a_OwnCert != nullptr); ASSERT(a_OwnCertPrivKey != nullptr); // Make sure we have the cert stored for later, mbedTLS only uses the cert later on m_OwnCert = std::move(a_OwnCert); m_OwnCertPrivKey = std::move(a_OwnCertPrivKey); // Set into the config: mbedtls_ssl_conf_own_cert(&m_Config, m_OwnCert->GetInternal(), m_OwnCertPrivKey->GetInternal()); } void cSslConfig::SetVerifyCallback(cVerifyCallback a_CallbackFun, void * a_CallbackData) { mbedtls_ssl_conf_verify(&m_Config, a_CallbackFun, a_CallbackData); } void cSslConfig::SetCipherSuites(std::vector a_CipherSuites) { m_CipherSuites = std::move(a_CipherSuites); m_CipherSuites.push_back(0); // Must be null terminated mbedtls_ssl_conf_ciphersuites(&m_Config, m_CipherSuites.data()); } void cSslConfig::SetCACerts(cX509CertPtr a_CACert) { m_CACerts = std::move(a_CACert); mbedtls_ssl_conf_ca_chain(&m_Config, m_CACerts->GetInternal(), nullptr); } std::shared_ptr cSslConfig::MakeDefaultConfig(bool a_IsClient) { auto Ret = std::make_shared(); Ret->InitDefaults(a_IsClient); { auto CtrDrbg = std::make_shared(); CtrDrbg->Initialize("Cuberite", 8); Ret->SetRng(std::move(CtrDrbg)); } // By default we have no root CAs, so no cert verification can be done: Ret->SetAuthMode(eSslAuthMode::None); #ifndef NDEBUG #ifdef ENABLE_SSL_DEBUG_MSG Ret->SetDebugCallback(&SSLDebugMessage, nullptr); Ret->SetVerifyCallback(SSLVerifyCert, nullptr); mbedtls_debug_set_threshold(2); #endif /* // Set ciphersuite to the easiest one to decode, so that the connection can be wireshark-decoded: Ret->SetCipherSuites( { MBEDTLS_TLS_RSA_WITH_RC4_128_MD5, MBEDTLS_TLS_RSA_WITH_RC4_128_SHA, MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA } ); */ #endif return Ret; } std::shared_ptr cSslConfig::GetDefaultClientConfig() { static const std::shared_ptr ClientConfig = MakeDefaultConfig(true); return ClientConfig; } std::shared_ptr cSslConfig::GetDefaultServerConfig() { static const std::shared_ptr ServerConfig = MakeDefaultConfig(false); return ServerConfig; } ================================================ FILE: src/mbedTLS++/SslConfig.h ================================================ #pragma once #include "mbedtls/ssl.h" // fwd: class cCryptoKey; class cCtrDrbgContext; class cX509Cert; using cCryptoKeyPtr = std::shared_ptr; using cCtrDrbgContextPtr = std::shared_ptr; using cX509CertPtr = std::shared_ptr; enum class eSslAuthMode { None = 0, // MBEDTLS_SSL_VERIFY_NONE Optional = 1, // MBEDTLS_SSL_VERIFY_OPTIONAL Required = 2, // MBEDTLS_SSL_VERIFY_REQUIRED Unset = 3, // MBEDTLS_SSL_VERIFY_UNSET }; class cSslConfig { friend class cSslContext; public: /** Type of the SSL debug callback. Parameters are: void * Opaque context for the callback int Debug level const char * File name int Line number const char * Message */ using cDebugCallback = void(*)(void *, int, const char *, int, const char *); /** Type of the SSL certificate verify callback. Parameters are: void * Opaque context for the callback mbedtls_x509_crt * Current cert int Cert chain depth uint32_t * Verification flags */ using cVerifyCallback = int(*)(void *, mbedtls_x509_crt *, int, uint32_t *); cSslConfig(); ~cSslConfig(); /** Initialize with mbedTLS default settings. */ int InitDefaults(bool a_IsClient); /** Set the authorization mode. */ void SetAuthMode(eSslAuthMode a_AuthMode); /** Set the random number generator. */ void SetRng(cCtrDrbgContextPtr a_CtrDrbg); /** Set the debug callback. */ void SetDebugCallback(cDebugCallback a_CallbackFun, void * a_CallbackData); /** Set the certificate verify callback. */ void SetVerifyCallback(cVerifyCallback a_CallbackFun, void * a_CallbackData); /** Set the enabled cipher suites. */ void SetCipherSuites(std::vector a_CipherSuites); /** Set the certificate to use for connections. */ void SetOwnCert(cX509CertPtr a_OwnCert, cCryptoKeyPtr a_OwnCertPrivKey); /** Set the trusted certificate authority chain. */ void SetCACerts(cX509CertPtr a_CACert); /** Creates a new config with some sensible defaults on top of mbedTLS basic settings. */ static std::shared_ptr MakeDefaultConfig(bool a_IsClient); /** Returns the default config for client connections. */ static std::shared_ptr GetDefaultClientConfig(); /** Returns the default config for server connections. */ static std::shared_ptr GetDefaultServerConfig(); private: /** Returns a pointer to the wrapped mbedtls representation. */ const mbedtls_ssl_config * GetInternal() const { return &m_Config; } mbedtls_ssl_config m_Config; cCtrDrbgContextPtr m_CtrDrbg; cX509CertPtr m_OwnCert; cCryptoKeyPtr m_OwnCertPrivKey; cX509CertPtr m_CACerts; std::vector m_CipherSuites; }; ================================================ FILE: src/mbedTLS++/SslContext.cpp ================================================ // SslContext.cpp // Implements the cSslContext class that holds everything a single SSL context needs to function #include "Globals.h" #include "../mbedTLS++/SslContext.h" #include "../mbedTLS++/SslConfig.h" cSslContext::cSslContext(void) : m_IsValid(false), m_HasHandshaken(false) { mbedtls_ssl_init(&m_Ssl); } cSslContext::~cSslContext() { mbedtls_ssl_free(&m_Ssl); } int cSslContext::Initialize(std::shared_ptr a_Config) { // Check double-initialization: if (m_IsValid) { LOGWARNING("SSL: Double initialization is not supported."); return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; // There is no return value well-suited for this, reuse this one. } // Check the Config: m_Config = std::move(a_Config); if (m_Config == nullptr) { ASSERT(!"Config must not be nullptr"); return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } // Apply the configuration to the ssl context int res = mbedtls_ssl_setup(&m_Ssl, m_Config->GetInternal()); if (res != 0) { return res; } // Set the io callbacks mbedtls_ssl_set_bio(&m_Ssl, this, SendEncrypted, ReceiveEncrypted, nullptr); m_IsValid = true; return 0; } int cSslContext::Initialize(bool a_IsClient) { if (a_IsClient) { return Initialize(cSslConfig::GetDefaultClientConfig()); } else { return Initialize(cSslConfig::GetDefaultServerConfig()); } } void cSslContext::SetExpectedPeerName(const std::string_view a_ExpectedPeerName) { ASSERT(m_IsValid); // Call Initialize() first mbedtls_ssl_set_hostname(&m_Ssl, a_ExpectedPeerName.data()); } int cSslContext::WritePlain(const void * a_Data, size_t a_NumBytes) { ASSERT(m_IsValid); // Need to call Initialize() first if (!m_HasHandshaken) { int res = Handshake(); if (res != 0) { return res; } } return mbedtls_ssl_write(&m_Ssl, static_cast(a_Data), a_NumBytes); } int cSslContext::ReadPlain(void * a_Data, size_t a_MaxBytes) { ASSERT(m_IsValid); // Need to call Initialize() first if (!m_HasHandshaken) { int res = Handshake(); if (res != 0) { return res; } } return mbedtls_ssl_read(&m_Ssl, static_cast(a_Data), a_MaxBytes); } int cSslContext::Handshake(void) { ASSERT(m_IsValid); // Need to call Initialize() first ASSERT(!m_HasHandshaken); // Must not call twice int res = mbedtls_ssl_handshake(&m_Ssl); if (res == 0) { m_HasHandshaken = true; } return res; } int cSslContext::NotifyClose(void) { return mbedtls_ssl_close_notify(&m_Ssl); } ================================================ FILE: src/mbedTLS++/SslContext.h ================================================ // SslContext.h // Declares the cSslContext class that holds everything a single SSL context needs to function #pragma once #include "mbedtls/ssl.h" #include "../ByteBuffer.h" // fwd: class cCtrDrbgContext; class cSslConfig; /** Acts as a generic SSL encryptor / decryptor between the two endpoints. The "owner" of this class is expected to create it, initialize it and then provide the means of reading and writing data through the SSL link. This is an abstract base class, there are descendants that handle the specific aspects of how the SSL peer data comes into the system: - cBufferedSslContext uses a cByteBuffer to read and write the data - cCallbackSslContext uses callbacks to provide the data */ class cSslContext abstract { public: /** Creates a new uninitialized context */ cSslContext(void); virtual ~cSslContext(); /** Initializes the context for use as a server or client. a_Config must not be nullptr and the config must not be changed after this call. Returns 0 on success, mbedTLS error on failure. */ int Initialize(std::shared_ptr a_Config); /** Initializes the context using the default config. */ int Initialize(bool a_IsClient); /** Returns true if the object has been initialized properly. */ bool IsValid(void) const { return m_IsValid; } /** Sets the SSL peer name expected for this context. This is used both for TLS SNI and for certificate validation. Must be called after Initialize(). \param a_ExpectedPeerName CommonName that we expect the SSL peer to have in its cert, if it is different, the verification will fail. An empty string will disable the CN check. */ void SetExpectedPeerName(const std::string_view a_ExpectedPeerName); /** Writes data to be encrypted and sent to the SSL peer. Will perform SSL handshake, if needed. Returns the number of bytes actually written, or mbedTLS error code. If the return value is MBEDTLS_ERR_SSL_WANT_READ or MBEDTLS_ERR_SSL_WANT_WRITE, the owner should send any cached outgoing data to the SSL peer and write any incoming data received from the SSL peer and then call this function again with the same parameters. Note that this may repeat a few times before the data is actually written, mainly due to initial handshake. */ int WritePlain(const void * a_Data, size_t a_NumBytes); /** Reads data decrypted from the SSL stream. Will perform SSL handshake, if needed. Returns the number of bytes actually read, or mbedTLS error code. If the return value is MBEDTLS_ERR_SSL_WANT_READ or MBEDTLS_ERR_SSL_WANT_WRITE, the owner should send any cached outgoing data to the SSL peer and write any incoming data received from the SSL peer and then call this function again with the same parameters. Note that this may repeat a few times before the data is actually read, mainly due to initial handshake. */ int ReadPlain(void * a_Data, size_t a_MaxBytes); /** Performs the SSL handshake. Returns zero on success, mbedTLS error code on failure. If the return value is MBEDTLS_ERR_SSL_WANT_READ or MBEDTLS_ERR_SSL_WANT_WRITE, the owner should send any cached outgoing data to the SSL peer and write any incoming data received from the SSL peer and then call this function again. Note that this may repeat a few times before the handshake is completed. */ int Handshake(void); /** Returns true if the SSL handshake has been completed. */ bool HasHandshaken(void) const { return m_HasHandshaken; } /** Notifies the SSL peer that the connection is being closed. Returns 0 on success, mbedTLS error code on failure. */ int NotifyClose(void); protected: /** Configuration of the SSL context. */ std::shared_ptr m_Config; /** The SSL context that mbedTLS uses. */ mbedtls_ssl_context m_Ssl; /** True if the object has been initialized properly. */ bool m_IsValid; /** True if the SSL handshake has been completed. */ bool m_HasHandshaken; /** The callback used by mbedTLS when it wants to read encrypted data. */ static int ReceiveEncrypted(void * a_This, unsigned char * a_Buffer, size_t a_NumBytes) { return (static_cast(a_This))->ReceiveEncrypted(a_Buffer, a_NumBytes); } /** The callback used by mbedTLS when it wants to write encrypted data. */ static int SendEncrypted(void * a_This, const unsigned char * a_Buffer, size_t a_NumBytes) { return (static_cast(a_This))->SendEncrypted(a_Buffer, a_NumBytes); } /** Called when mbedTLS wants to read encrypted data. */ virtual int ReceiveEncrypted(unsigned char * a_Buffer, size_t a_NumBytes) = 0; /** Called when mbedTLS wants to write encrypted data. */ virtual int SendEncrypted(const unsigned char * a_Buffer, size_t a_NumBytes) = 0; } ; ================================================ FILE: src/mbedTLS++/X509Cert.cpp ================================================ // X509Cert.cpp // Implements the cX509Cert class representing a wrapper over X509 certs in mbedTLS #include "Globals.h" #include "X509Cert.h" cX509Cert::cX509Cert(void) { mbedtls_x509_crt_init(&m_Cert); } cX509Cert::~cX509Cert() { mbedtls_x509_crt_free(&m_Cert); } int cX509Cert::Parse(const void * a_CertContents, size_t a_Size) { // mbedTLS requires that PEM-encoded data is passed including the terminating NUL byte, // and DER-encoded data is decoded properly even with an extra trailing NUL byte, so we simply add one to everything: AString certContents(static_cast(a_CertContents), a_Size); return mbedtls_x509_crt_parse(&m_Cert, reinterpret_cast(certContents.data()), a_Size + 1); } ================================================ FILE: src/mbedTLS++/X509Cert.h ================================================ // X509Cert.h // Declares the cX509Cert class representing a wrapper over X509 certs in mbedTLS #pragma once #include "mbedtls/x509_crt.h" class cX509Cert { friend class cSslConfig; public: cX509Cert(void); ~cX509Cert(void); /** Parses the certificate chain data into the context. The certificate can be DER- or PEM-encoded. Returns 0 on succes, or mbedTLS error code on failure. */ int Parse(const void * a_CertContents, size_t a_Size); protected: mbedtls_x509_crt m_Cert; /** Returns the internal cert ptr. Only use in mbedTLS API calls. */ mbedtls_x509_crt * GetInternal(void) { return &m_Cert; } } ; typedef std::shared_ptr cX509CertPtr; ================================================ FILE: stats.cmd ================================================ cloc --by-file-by-lang --exclude-dir=lib --exclude-list-file=cloc-exclude.txt --xml --xsl=1 --report-file=cloc.xml --ignored=cloc-ignored.txt . ================================================ FILE: tests/BlockTypeRegistry/BlockStateTest.cpp ================================================ #include "Globals.h" #include "Bindings/BlockState.h" #include "../TestHelpers.h" /** Tests the class constructors with static (hard-coded) data. */ static void testStaticCreation() { LOGD("Testing BlockState creation from static data..."); // Create a few BlockStates using the static-data constructors: BlockState bs1v1; BlockState bs2v1("property", "value"); BlockState bs3v1({{"property1", "value1"}, {"property2", "value2"}}); BlockState bs1v2(bs1v1); BlockState bs2v2(bs2v1); BlockState bs3v2(bs3v1); BlockState bs1v3(bs1v2, {{"added property", "value1"}}); BlockState bs2v3(bs2v2, {{"added property", "value2"}}); BlockState bs3v3(bs3v2, {{"added property", "value3"}}); // Test (in-)equality (v1 = v2 != v3): TEST_EQUAL(bs1v1, bs1v2); TEST_EQUAL(bs2v1, bs2v2); TEST_EQUAL(bs3v1, bs3v2); TEST_NOTEQUAL(bs1v1, bs1v3); TEST_NOTEQUAL(bs2v1, bs2v3); TEST_NOTEQUAL(bs3v1, bs3v3); TEST_NOTEQUAL(bs1v2, bs1v3); TEST_NOTEQUAL(bs2v2, bs2v3); TEST_NOTEQUAL(bs3v2, bs3v3); // Test that the values are actually stored: TEST_EQUAL(bs1v1.value("property"), ""); TEST_EQUAL(bs2v1.value("property"), "value"); TEST_EQUAL(bs2v1.value("property1"), ""); TEST_EQUAL(bs3v1.value("property1"), "value1"); TEST_EQUAL(bs3v1.value("property2"), "value2"); TEST_EQUAL(bs1v3.value("added property"), "value1"); TEST_EQUAL(bs2v3.value("added property"), "value2"); TEST_EQUAL(bs3v3.value("added property"), "value3"); } /** Tests the dynamic-data constructors (map param, deep-copy). */ static void testDynamicCreation() { LOGD("Testing BlockState creation from dynamic data..."); using Map = std::map; // Construct from scratch: { BlockState bs1a({{"property", "value"}}); Map map1({{"property", "value"}}); BlockState bs1b(map1); TEST_EQUAL(bs1a, bs1b); // Creation works map1.clear(); TEST_EQUAL(bs1a, bs1b); // Created a copy independent of map1 } // Construct by moving: { BlockState bs2a({{"property", "value"}}); Map map2({{"property", "value"}}); BlockState bs2b(std::move(map2)); TEST_EQUAL(bs2a, bs2b); // Creation works } // Construct by modifying: { BlockState bsSrc("property1", "value1"); BlockState bs3a(bsSrc, {{"property2", "value2"}}); Map map3({{"property2", "value2"}}); BlockState bs3b(bsSrc, map3); TEST_EQUAL(bs3a, bs3b); map3.clear(); TEST_EQUAL(bs3a, bs3b); } } /** Tests replacing the properties in the copy-and-modify constructors. */ static void testReplacing() { LOGD("Testing replacing / removing properties in BlockState copies..."); // Test replacing: BlockState bs1("property1", "value1v1"); BlockState bs2(bs1, {{"property1", "value1v2"}}); TEST_EQUAL(bs2.value("property1"), "value1v2"); // Stored the new one TEST_EQUAL(bs1.value("property1"), "value1v1"); // Didn't replace in the original // Test removing: BlockState bs3(bs1, {{"property1", ""}}); BlockState bsEmpty; TEST_EQUAL(bs3, bsEmpty); } /** Tests the comparison operator. */ static void testComparison() { LOGD("Testing comparison of BlockStates..."); // Simple property value tests TEST_FALSE((BlockState({{"a", "a"}}) < BlockState({{"a", "a"}}))); TEST_FALSE((BlockState() < BlockState())); TEST_TRUE((BlockState() < BlockState({{"foo", "bar"}}))); TEST_FALSE((BlockState({{"foo", "bar"}}) < BlockState())); } /** Tests the comparison operator using crafted data to defeat the checksum. */ static void testComparison2() { /* The following test ensures that items inserted in different order result in the same map. I.e. that the < operator is stable. */ std::vector v; std::map map1; std::map map2; for (int i = 0; i < 128; ++i) { v.push_back(BlockState({{std::string(1, static_cast(0x1F)), std::string(1, static_cast(i))}})); v.push_back(BlockState({{std::string(1, static_cast(0x10)), std::string(1, static_cast(i | 0x80))}, {std::string(1, static_cast(0x0F)), std::string(1, static_cast(0x80))}})); } for (size_t i = 0; i < v.size(); ++i) { map1[v[i]] = true; } for (auto i = v.size(); i > 0; --i) { map2[v[i - 1]] = true; } // Check result TEST_EQUAL(v.size(), 2 * 128); TEST_EQUAL(map1.size(), v.size()); TEST_EQUAL(map1.size(), map2.size()); for (const auto & item: map1) { TEST_EQUAL(map1[item.first], map2[item.first]); } } IMPLEMENT_TEST_MAIN("BlockStateTest", testStaticCreation(); testDynamicCreation(); testReplacing(); testComparison(); testComparison2(); ) ================================================ FILE: tests/BlockTypeRegistry/BlockTypePaletteTest.cpp ================================================ #include "Globals.h" #include "../TestHelpers.h" #include "Bindings/BlockTypePalette.h" #include "OSSupport/Stopwatch.h" /** Tests the BlockTypePalette's basic APIs - creation, addition, querying. */ static void testBasic() { LOGD("Testing the basic BlockTypePalette's APIs..."); // Check inserting different block type names: BlockTypePalette pal; TEST_EQUAL(pal.index("testblock", BlockState()), 0); // Insert the first entry TEST_EQUAL(pal.index("testblock", BlockState()), 0); // Check that it's not inserted again TEST_EQUAL(pal.maybeIndex("testblock", BlockState()), (std::make_pair(0, true))); TEST_EQUAL(pal.maybeIndex("nonexistent", BlockState()).second, false); TEST_EQUAL(pal.index("another", BlockState()), 1); // Insert the second entry TEST_EQUAL(pal.index("another", BlockState()), 1); // Check that it's not inserted twice TEST_EQUAL(pal.maybeIndex("another", BlockState()), (std::make_pair(1, true))); TEST_EQUAL(pal.maybeIndex("testblock", BlockState()), (std::make_pair(0, true))); // The first one stayed // Check same block type name, different BlockState: BlockState bs1; BlockState bs2("key1", "value1"); BlockState bs3({{"key1", "value1"}, {"key2", "value2"}}); BlockState bs2Copy(bs2); TEST_EQUAL(pal.index("multistate", bs1), 2); TEST_EQUAL(pal.index("multistate", bs2), 3); TEST_EQUAL(pal.index("multistate", bs3), 4); TEST_EQUAL(pal.index("multistate", bs2Copy), 3); // Different BlockState instance, but same content TEST_EQUAL(pal.count(), 5); // Check the entry() API: TEST_EQUAL(pal.entry(0), (std::make_pair("testblock", BlockState()))); TEST_EQUAL(pal.entry(1), (std::make_pair("another", BlockState()))); TEST_EQUAL(pal.entry(2), (std::make_pair("multistate", BlockState(bs1)))); // make_pair requires a copy of the state TEST_EQUAL(pal.entry(3), (std::make_pair("multistate", BlockState(bs2)))); TEST_EQUAL(pal.entry(4), (std::make_pair("multistate", BlockState(bs3)))); TEST_THROWS(pal.entry(5), BlockTypePalette::NoSuchIndexException); } /** Tests creating the transform map between two palettes. */ static void testTransformAddMissing() { LOGD("Testing the createTransformMapAddMissing API..."); // Create two palettes with some overlap: BlockTypePalette pal1, pal2; /* 0 */ pal1.index("block1", BlockState()); /* 1 */ pal1.index("block2", BlockState()); /* 2 */ pal1.index("block3", BlockState()); /* 3 */ pal1.index("block4", BlockState()); /* 4 */ pal1.index("block5", BlockState("key1", "value1")); /* 0 */ pal2.index("block0", BlockState()); /* 1 */ pal2.index("block2", BlockState()); // overlap /* 2 */ pal2.index("block4", BlockState()); // overlap /* 3 */ pal2.index("block4", BlockState("key1", "value1")); /* 4 */ pal2.index("block5", BlockState("key1", "value1")); // overlap /* 5 */ pal2.index("block6", BlockState("key1", "value1")); // Check the transform map: auto trans = pal1.createTransformMapAddMissing(pal2); TEST_EQUAL(pal1.maybeIndex("block1", BlockState()), (std::make_pair(0, true))); TEST_EQUAL(pal1.maybeIndex("block2", BlockState()), (std::make_pair(1, true))); TEST_EQUAL(pal1.maybeIndex("block3", BlockState()), (std::make_pair(2, true))); TEST_EQUAL(pal1.maybeIndex("block4", BlockState()), (std::make_pair(3, true))); TEST_EQUAL(pal1.maybeIndex("block5", BlockState("key1", "value1")), (std::make_pair(4, true))); TEST_EQUAL(pal1.maybeIndex("block0", BlockState()), (std::make_pair(5, true))); TEST_EQUAL(pal1.maybeIndex("block4", BlockState("key1", "value1")), (std::make_pair(6, true))); TEST_EQUAL(pal1.maybeIndex("block6", BlockState("key1", "value1")), (std::make_pair(7, true))); TEST_EQUAL(trans.size(), 6); TEST_EQUAL(trans[0], 5); // Added TEST_EQUAL(trans[1], 1); // Mapped TEST_EQUAL(trans[2], 3); // Mapped TEST_EQUAL(trans[3], 6); // Added TEST_EQUAL(trans[4], 4); // Mapped TEST_EQUAL(trans[5], 7); // Added } /** Tests creating the transform map between two palettes, with fallback. */ static void testTransformWithFallback() { LOGD("Testing the createTransformMapWithFallback API..."); // Create two palettes with some overlap: BlockTypePalette pal1, pal2; /* 0 */ pal1.index("block1", BlockState()); /* 1 */ pal1.index("block2", BlockState()); /* 2 */ pal1.index("block3", BlockState()); /* 3 */ pal1.index("block4", BlockState()); /* 4 */ pal1.index("block5", BlockState("key1", "value1")); /* 0 */ pal2.index("block0", BlockState()); /* 1 */ pal2.index("block2", BlockState()); // overlap /* 2 */ pal2.index("block4", BlockState()); // overlap /* 3 */ pal2.index("block4", BlockState("key1", "value1")); /* 4 */ pal2.index("block5", BlockState("key1", "value1")); // overlap /* 5 */ pal2.index("block6", BlockState("key1", "value1")); // Check the transform map: auto trans = pal1.createTransformMapWithFallback(pal2, 0); TEST_EQUAL(trans.size(), 6); TEST_EQUAL(trans[0], 0); // Fallback TEST_EQUAL(trans[1], 1); // Mapped TEST_EQUAL(trans[2], 3); // Mapped TEST_EQUAL(trans[3], 0); // Fallback TEST_EQUAL(trans[4], 4); // Mapped TEST_EQUAL(trans[5], 0); // Fallback } /** Tests that loading fails for nonsense input */ static void testLoadErrors(void) { LOG("Testing palette load error reporting."); BlockTypePalette palette; TEST_THROWS(palette.loadFromString(""), BlockTypePalette::LoadFailedException); TEST_THROWS(palette.loadFromString("[]"), BlockTypePalette::LoadFailedException); TEST_THROWS(palette.loadFromString("a = {}"), BlockTypePalette::LoadFailedException); TEST_THROWS(palette.loadFromString("{x = 1}"), BlockTypePalette::LoadFailedException); // Lua style TEST_THROWS(palette.loadFromString("$#^%&"), BlockTypePalette::LoadFailedException); } /** Tests that loading a simple JSON palette succeeds. */ static void testLoadJsonSimple(void) { LOG("Testing loading a simple JSON palette"); BlockTypePalette palette; auto example = " \ { \ \"minecraft:air\": { \ \"states\": [ \ { \ \"id\": 0, \ \"default\": true \ } \ ] \ } \ }"; palette.loadFromString(example); TEST_EQUAL(palette.maybeIndex("minecraft:air", BlockState()), (std::make_pair(0, true))); TEST_EQUAL(palette.maybeIndex("minecraft:air", BlockState({{"foo", "baz"}})).second, false); TEST_EQUAL(palette.maybeIndex("minecraft:a", BlockState()).second, false); } /** Tests loading a complex block with multiple states and duplicates. */ static void testLoadJsonComplex(void) { LOG("Testing loading a complex JSON palette"); BlockTypePalette palette; auto str = " \ { \ \"minecraft:oak_sapling\": { \ \"properties\": { \ \"stage\": [ \ \"0\", \ \"1\" \ ] \ }, \ \"states\": [ \ { \ \"properties\": { \ \"stage\": \"0\" \ }, \ \"id\" : 21, \ \"default\" : true \ }, \ { \ \"properties\": { \ \"stage\": \"1\" \ }, \ \"id\" : 22 \ }, \ { \ \"properties\": { \ \"stage\": \"1\" \ }, \ \"id\" : 23 \ }\ ] \ } \ }"; // Note: The palette has a duplicate entry with differrent IDs, the latter ID wins palette.loadFromString(str); TEST_EQUAL(palette.maybeIndex("minecraft:oak_sapling", {{"stage", "10"}}).second, false); TEST_EQUAL(palette.maybeIndex("minecraft:oak_sapling", {{"stage", "0"}}), (std::make_pair(21, true))); TEST_EQUAL(palette.maybeIndex("minecraft:oak_sapling", {{"stage", "1"}}), (std::make_pair(23, true))); TEST_EQUAL(palette.maybeIndex("minecraft:oak_sapling", {{"foo", "baz"}}).second, false); TEST_EQUAL(palette.maybeIndex("minecraft:oak_sap", {{"stage", "0"}}).second, false); } /** Tests loading a palette from simple regular TSV text data. */ static void testLoadTsvRegular(void) { LOG("Testing loading a simple regular TSV palette"); BlockTypePalette palette; auto str = "\ BlockTypePalette\r\n\ FileVersion\t1\n\ CommonPrefix\tminecraft:\n\ \r\n\ 0\tair\r\n\ 1\tstone\n\ 2\tgrass\tsnow_covered\t0\n\ 3\tgrass\tsnow_covered\t1\n\ "; palette.loadFromString(str); TEST_EQUAL(palette.maybeIndex("minecraft:air", BlockState()), (std::make_pair(0, true))); TEST_EQUAL(palette.maybeIndex("minecraft:stone", BlockState()), (std::make_pair(1, true))); TEST_EQUAL(palette.maybeIndex("minecraft:grass", BlockState({{"snow_covered", "0"}})), (std::make_pair(2, true))); TEST_EQUAL(palette.maybeIndex("minecraft:grass", BlockState({{"snow_covered", "1"}})), (std::make_pair(3, true))); TEST_EQUAL(palette.maybeIndex("minecraft:air", BlockState({{"snow_covered", "0"}})).second, false); TEST_EQUAL(palette.maybeIndex("minecraft:grass", BlockState({{"snow_covered", "2"}})).second, false); TEST_EQUAL(palette.maybeIndex("minecraft:grass", BlockState()).second, false); } /** Tests loading a palette from simple upgrade TSV text data. */ static void testLoadTsvUpgrade(void) { LOG("Testing loading a simple upgrade TSV palette"); BlockTypePalette palette; auto str = "\ UpgradeBlockTypePalette\r\n\ FileVersion\t1\n\ CommonPrefix\tminecraft:\r\n\ \n\ 0\t0\tair\r\n\ 1\t0\tstone\n\ 2\t0\tgrass\tsnow_covered\t0\n\ 2\t1\tgrass\tsnow_covered\t1\n\ "; palette.loadFromString(str); TEST_EQUAL(palette.maybeIndex("minecraft:air", BlockState()), (std::make_pair(0, true))); TEST_EQUAL(palette.maybeIndex("minecraft:stone", BlockState()), (std::make_pair(16, true))); TEST_EQUAL(palette.maybeIndex("minecraft:grass", BlockState({{"snow_covered", "0"}})), (std::make_pair(32, true))); TEST_EQUAL(palette.maybeIndex("minecraft:grass", BlockState({{"snow_covered", "1"}})), (std::make_pair(33, true))); TEST_EQUAL(palette.maybeIndex("minecraft:air", BlockState({{"snow_covered", "0"}})).second, false); TEST_EQUAL(palette.maybeIndex("minecraft:grass", BlockState({{"snow_covered", "2"}})).second, false); TEST_EQUAL(palette.maybeIndex("minecraft:grass", BlockState()).second, false); } /** Tests loading a palette from a real-life protocol base file (1.13). */ static void testLoadFromBaseFile(void) { LOG("Testing loading a palette from file \"base.btp.txt\" (1.13)"); BlockTypePalette palette; { auto fileContents = cFile::ReadWholeFile("base.btp.txt"); cStopwatch sw("Loading palette"); palette.loadFromString(fileContents); } TEST_EQUAL(palette.maybeIndex("minecraft:air", BlockState()), (std::make_pair(0, true))); TEST_EQUAL(palette.maybeIndex("minecraft:stone", BlockState()), (std::make_pair(1, true))); TEST_EQUAL( palette.maybeIndex( "minecraft:dark_oak_leaves", BlockState({{"persistent", "false"}, {"distance", "6"}}) ), (std::make_pair(225, true)) ); TEST_EQUAL( palette.maybeIndex( "minecraft:dark_oak_leaves", BlockState({{"persistent", "false"}}) ).second, false ); } /** Tests loading an upgrade-palette from a real-life upgrade file. */ static void testLoadFromUpgradeFile(void) { LOG("Testing loading an upgrade palette from file \"UpgradeBlockTypePalette.txt\"."); BlockTypePalette palette; { auto fileContents = cFile::ReadWholeFile("UpgradeBlockTypePalette.txt"); cStopwatch sw("Loading upgrade palette"); palette.loadFromString(fileContents); } TEST_EQUAL(palette.entry(0), (std::make_pair("minecraft:air", {}))); TEST_EQUAL(palette.entry(44 * 16 + 8), (std::make_pair("minecraft:stone_slab", {{"type", "top"}}))); } IMPLEMENT_TEST_MAIN("BlockTypePalette", testBasic(); testTransformAddMissing(); testTransformWithFallback(); testLoadErrors(); testLoadJsonSimple(); testLoadJsonComplex(); testLoadTsvRegular(); testLoadTsvUpgrade(); testLoadFromBaseFile(); testLoadFromUpgradeFile(); ) ================================================ FILE: tests/BlockTypeRegistry/BlockTypeRegistryTest.cpp ================================================ #include "Globals.h" #include "Bindings/BlockTypeRegistry.h" #include "../TestHelpers.h" /** Dummy BlockState implementation */ class BlockState { public: BlockState() = default; }; /** Dummy cBlockHandler implementation that allows simple checking for equality through mIdent. */ class cBlockHandler { public: cBlockHandler(UInt32 aIdent): mIdent(aIdent) { } UInt32 mIdent; }; /** Tests simple block type name registration. Registers a block type, checks that the type is then registered. */ static void testSimpleReg() { LOGD("Testing simple registration..."); // Register the block type: BlockTypeRegistry reg; AString blockTypeName("test:block1"); AString pluginName("testPlugin"); AString hint1("testHint1"); AString hint1Value("value1"); std::shared_ptr handler(new cBlockHandler(0x12345678)); std::map hints = {{hint1, hint1Value}, {"testHint2", "value2"}}; std::map hintCallbacks; reg.registerBlockType(pluginName, blockTypeName, handler, hints, hintCallbacks); // Query the registration: auto blockInfo = reg.blockInfo(blockTypeName); TEST_NOTEQUAL(blockInfo, nullptr); TEST_EQUAL(blockInfo->blockTypeName(), blockTypeName); TEST_EQUAL(blockInfo->pluginName(), pluginName); TEST_EQUAL(blockInfo->handler(), handler); TEST_EQUAL(blockInfo->hintValue(hint1, BlockState()), hint1Value); TEST_EQUAL(blockInfo->hintValue("nonexistent", BlockState()), ""); } /** Tests setting and removing a BlockType hint. */ static void testHintSetRemove() { LOGD("Testing hint addition and removal..."); // Register the block type: BlockTypeRegistry reg; AString blockTypeName("test:block1"); AString pluginName("testPlugin"); AString hint1("testHint1"); AString hint1Value("value1"); AString hint2("testHint2"); AString hint2Value("value2"); std::shared_ptr handler(new cBlockHandler(0x12345678)); std::map hints = {{hint1, hint1Value}}; std::map hintCallbacks; reg.registerBlockType(pluginName, blockTypeName, handler, hints, hintCallbacks); // Modify the hints: auto blockInfo = reg.blockInfo(blockTypeName); reg.setBlockTypeHint(blockTypeName, hint2, hint2Value); TEST_EQUAL(blockInfo->hintValue(hint2, BlockState()), hint2Value); // Was created successfully reg.setBlockTypeHint(blockTypeName, hint1, "testValue2"); TEST_EQUAL(blockInfo->hintValue(hint1, BlockState()), "testValue2"); // Was updated successfully reg.removeBlockTypeHint(blockTypeName, hint2); TEST_EQUAL(blockInfo->hintValue(hint2, BlockState()), ""); // Was removed successfully // Test the error reporting: TEST_THROWS(reg.setBlockTypeHint("nonexistent", "hint", "value"), BlockTypeRegistry::NotRegisteredException); reg.removeBlockTypeHint(blockTypeName, "nonexistent"); // Should fail silently } /** Tests that the plugin-based information is used correctly for registration. Registers two different block types with two different plugins, then tries to re-register them from a different plugin. Finally removes the registration through removeAllByPlugin() and checks its success. */ static void testPlugins() { LOGD("Testing plugin-based checks / removal..."); // Register the block types: BlockTypeRegistry reg; AString blockTypeName1("test:block1"); AString pluginName1("testPlugin1"); AString hint1("testHint1"); AString hint1Value("value1"); std::shared_ptr handler1(new cBlockHandler(1)); std::map hints = {{hint1, hint1Value}, {"testHint2", "value2"}}; std::map hintCallbacks; reg.registerBlockType(pluginName1, blockTypeName1, handler1, hints, hintCallbacks); AString blockTypeName2("test:block2"); AString pluginName2("testPlugin2"); std::shared_ptr handler2(new cBlockHandler(2)); reg.registerBlockType(pluginName2, blockTypeName2, handler2, hints, hintCallbacks); // Test the refusal to register under a different plugin: TEST_THROWS(reg.registerBlockType(pluginName2, blockTypeName1, handler2, hints, hintCallbacks), BlockTypeRegistry::AlreadyRegisteredException); TEST_EQUAL(reg.blockInfo(blockTypeName1)->handler()->mIdent, 1); // Did we overwrite the old registration? reg.registerBlockType(pluginName1, blockTypeName1, handler1, hints, hintCallbacks); // Re-registering must succeed // Unregister by plugin, then re-register from a different plugin: reg.removeAllByPlugin(pluginName1); TEST_EQUAL(reg.blockInfo(blockTypeName1), nullptr); // Unregistered successfully TEST_NOTEQUAL(reg.blockInfo(blockTypeName2), nullptr); // Didn't unregister from the other plugin std::shared_ptr handler3(new cBlockHandler(3)); reg.registerBlockType(pluginName2, blockTypeName1, handler3, hints, hintCallbacks); TEST_NOTEQUAL(reg.blockInfo(blockTypeName1), nullptr); // Registered successfully TEST_EQUAL(reg.blockInfo(blockTypeName1)->pluginName(), pluginName2); TEST_EQUAL(reg.blockInfo(blockTypeName1)->handler()->mIdent, 3); TEST_EQUAL(reg.blockInfo(blockTypeName2)->handler()->mIdent, 2); reg.removeAllByPlugin(pluginName2); TEST_EQUAL(reg.blockInfo(blockTypeName1), nullptr); // Unregistered successfully TEST_EQUAL(reg.blockInfo(blockTypeName2), nullptr); // Unregistered successfully } /** Tests that the callback-based hints work properly. */ static void testHintCallbacks() { LOGD("Testing hint callbacks..."); // Register the block type: BlockTypeRegistry reg; AString blockTypeName("test:block1"); AString pluginName("testPlugin"); AString hint1("testHint1"); AString hint1Value("value1"); AString hc1("hintCallback1"); int callbackCount = 0; auto callback1 = [&callbackCount](const AString & aBlockType, const BlockState & aBlockState) { callbackCount = callbackCount + 1; return aBlockType + "_hint"; }; std::shared_ptr handler(new cBlockHandler(0x12345678)); std::map hints = {{hint1, hint1Value}, {"testHint2", "value2"}}; std::map hintCallbacks = {{hc1, callback1}}; reg.registerBlockType(pluginName, blockTypeName, handler, hints, hintCallbacks); // Check that querying the hint using a callback works: TEST_EQUAL(reg.blockInfo(blockTypeName)->hintValue(hc1, BlockState()), blockTypeName + "_hint"); TEST_EQUAL(callbackCount, 1); // Called exactly once } /** Tests whether thread-locking works properly by running two threads, one constantly (re-)registering and the other one constantly querying the same block type. */ static void testThreadLocking() { LOGD("Testing thread locking..."); // Register the block type: BlockTypeRegistry reg; AString blockTypeName("test:block1"); AString pluginName("testPlugin"); AString hint1("testHint1"); AString hint1Value("value1"); std::shared_ptr handler(new cBlockHandler(0x12345678)); std::map hints = {{hint1, hint1Value}, {"testHint2", "value2"}}; std::map hintCallbacks; reg.registerBlockType(pluginName, blockTypeName, handler, hints, hintCallbacks); // Run the two threads for at least a second: auto endTime = time(nullptr) + 2; auto keepRegistering = [&]() { while (time(nullptr) < endTime) { reg.registerBlockType(pluginName, blockTypeName, handler, hints, hintCallbacks); } }; auto keepQuerying = [&]() { unsigned numQueries = 0; while (time(nullptr) < endTime) { TEST_NOTEQUAL(reg.blockInfo(blockTypeName), nullptr); numQueries += 1; } LOGD("%u queries have been executed", numQueries); }; std::thread thr1(keepRegistering); std::thread thr2(keepQuerying); thr1.join(); thr2.join(); } static void testBlockTypeRegistry() { testSimpleReg(); testHintSetRemove(); testPlugins(); testHintCallbacks(); testThreadLocking(); } IMPLEMENT_TEST_MAIN("BlockTypeRegistryTest", testBlockTypeRegistry(); ) ================================================ FILE: tests/BlockTypeRegistry/CMakeLists.txt ================================================ find_package(Threads REQUIRED) include_directories(${PROJECT_SOURCE_DIR}/src/) # Define individual test executables: # BlockStateTest: Verify that the BlockState class works as intended: add_executable(BlockStateTest BlockStateTest.cpp ../TestHelpers.h ${PROJECT_SOURCE_DIR}/src/Bindings/BlockState.cpp ${PROJECT_SOURCE_DIR}/src/StringUtils.cpp ${PROJECT_SOURCE_DIR}/src/OSSupport/CriticalSection.cpp ) target_link_libraries(BlockStateTest fmt::fmt) if (WIN32) target_link_libraries(BlockStateTest ws2_32) endif() add_executable(BlockTypePaletteTest BlockTypePaletteTest.cpp ../TestHelpers.h ${PROJECT_SOURCE_DIR}/src/Bindings/BlockState.cpp ${PROJECT_SOURCE_DIR}/src/Bindings/BlockTypePalette.cpp ${PROJECT_SOURCE_DIR}/src/JsonUtils.cpp ${PROJECT_SOURCE_DIR}/src/StringUtils.cpp ${PROJECT_SOURCE_DIR}/src/OSSupport/CriticalSection.cpp ${PROJECT_SOURCE_DIR}/src/OSSupport/File.cpp ) target_link_libraries(BlockTypePaletteTest fmt::fmt jsoncpp_static) if (WIN32) target_link_libraries(BlockTypePaletteTest ws2_32) endif() # BlockTypeRegistryTest: Verify that the BlockTypeRegistry class works as intended: add_executable(BlockTypeRegistryTest BlockTypeRegistryTest.cpp ../TestHelpers.h ${PROJECT_SOURCE_DIR}/src/Bindings/BlockTypeRegistry.cpp ${PROJECT_SOURCE_DIR}/src/StringUtils.cpp ${PROJECT_SOURCE_DIR}/src/OSSupport/CriticalSection.cpp ) target_link_libraries(BlockTypeRegistryTest fmt::fmt Threads::Threads) if (WIN32) target_link_libraries(BlockTypeRegistryTest ws2_32) endif() # PalettedBlockAreaTest: Verify that the PalettedBlockArea class works as intended: add_executable(PalettedBlockAreaTest PalettedBlockAreaTest.cpp ../TestHelpers.h ${PROJECT_SOURCE_DIR}/src/Bindings/BlockState.cpp ${PROJECT_SOURCE_DIR}/src/Bindings/BlockTypeRegistry.cpp ${PROJECT_SOURCE_DIR}/src/Bindings/BlockTypePalette.cpp ${PROJECT_SOURCE_DIR}/src/Cuboid.cpp ${PROJECT_SOURCE_DIR}/src/JsonUtils.cpp ${PROJECT_SOURCE_DIR}/src/PalettedBlockArea.cpp ${PROJECT_SOURCE_DIR}/src/StringUtils.cpp ${PROJECT_SOURCE_DIR}/src/OSSupport/CriticalSection.cpp ) target_link_libraries(PalettedBlockAreaTest fmt::fmt jsoncpp_static) if (WIN32) target_link_libraries(PalettedBlockAreaTest ws2_32) endif() # Extra files for BlockTypePalette test: file (COPY ../../Server/Protocol/1.13/base.btp.txt ../../Server/Protocol/UpgradeBlockTypePalette.txt DESTINATION ./ ) # Define individual tests: add_test(NAME BlockStateTest COMMAND BlockStateTest) add_test(NAME BlockTypeRegistryTest COMMAND BlockTypeRegistryTest) add_test(NAME BlockTypePaletteTest COMMAND BlockTypePaletteTest) add_test(NAME PalettedBlockAreaTest COMMAND PalettedBlockAreaTest) # Put all the tests into a solution folder (MSVC): set_target_properties( BlockStateTest BlockTypeRegistryTest BlockTypePaletteTest PalettedBlockAreaTest PROPERTIES FOLDER Tests/BlockTypeRegistry ) ================================================ FILE: tests/BlockTypeRegistry/PalettedBlockAreaTest.cpp ================================================ #include "Globals.h" #include "PalettedBlockArea.h" #include "../TestHelpers.h" /** Tests creating a PBA. */ static void testCreation() { LOG("Testing PBA creation..."); // Check failures: TEST_ASSERTS(PalettedBlockArea::createFilled({-2, 3, 4}, "block", BlockState())); // Negative coords TEST_THROWS(PalettedBlockArea::createFilled({4096, 4096, 4096}, "block", BlockState()), std::runtime_error); // Size too large for UInt32 // Check that a created area really is filled: auto pba = PalettedBlockArea::createFilled({2, 3, 4}, "block", BlockState()); TEST_EQUAL(pba.size(), Vector3i(2, 3, 4)); TEST_EQUAL(pba.whole(), cCuboid({0, 0, 0}, {2, 3, 4})); TEST_EQUAL(pba.palette().count(), 1); TEST_EQUAL(pba.maybePaletteIndex("block", BlockState()), (std::make_pair(0, true))); TEST_EQUAL(pba.maybePaletteIndex("nonexistentBlock", BlockState()).second, false); for (int x = 0; x < 2; ++x) { for (int y = 0; y < 3; ++y) { for (int z = 0; z < 4; ++z) { TEST_EQUAL(pba.blockPaletteIndex({x, y, z}), 0); } } } } /** Tests setting and getting blocks. */ static void testSetting() { LOG("Testing PBA's set and get APIs..."); auto pba = PalettedBlockArea::createFilled({2, 3, 4}, "block1", BlockState()); pba.setBlock({0, 0, 0}, "block2", BlockState()); pba.setBlock({1, 0, 0}, "block2", BlockState("key1", "value1")); TEST_ASSERTS(pba.setBlock({2, 0, 0}, "block2", BlockState())); // Invalid coords pba.setBlock({0, 1, 0}, 1); TEST_ASSERTS(pba.setBlock({1, 1, 0}, 100)); // Invalid palette index // Check that the blocks have been set: TEST_EQUAL(pba.palette().count(), 3); TEST_EQUAL(pba.block({0, 0, 0}), (std::make_pair("block2", BlockState()))); TEST_EQUAL(pba.block({1, 0, 0}), (std::make_pair("block2", BlockState("key1", "value1")))); TEST_ASSERTS(pba.block({2, 0, 0})); // Invalid coords TEST_EQUAL(pba.block({0, 1, 0}), (std::make_pair("block2", BlockState()))); TEST_EQUAL(pba.block({1, 1, 0}), (std::make_pair("block1", BlockState()))); // Didn't overwrite with invalid palette index TEST_EQUAL(pba.blockPaletteIndex({0, 0, 0}), 1); TEST_EQUAL(pba.blockPaletteIndex({1, 0, 0}), 2); TEST_ASSERTS(pba.blockPaletteIndex({2, 0, 0})); // Invalid coords TEST_EQUAL(pba.blockPaletteIndex({0, 1, 0}), 1); TEST_EQUAL(pba.blockPaletteIndex({1, 1, 0}), 0); // Didn't overwrite with invalid palette index // Test filling: LOG("Testing PBA's fill API..."); pba.fill("block3", BlockState("key1", "value1")); TEST_EQUAL(pba.palette().count(), 1); TEST_EQUAL(pba.paletteEntry(0), (std::make_pair("block3", BlockState("key1", "value1")))); for (int x = 0; x < 2; ++x) { for (int y = 0; y < 2; ++y) { for (int z = 0; z < 2; ++z) { TEST_EQUAL(pba.blockPaletteIndex({x, y, z}), 0); } } } } /** Creates pbaA and pbaB that are pre-filled with known content. The PBAs are then used for paste()-testing. Used to be a function, but clang-3.5 didn't like it ("error: debug information for auto is not yet supported"). */ #define PREPARE_PASTING_PBAS \ auto pbaA = PalettedBlockArea::createFilled({5, 5, 5}, "blockA", BlockState()); \ for (int x = 0; x < 5; ++x) \ { \ for (int y = 0; y < 5; ++y) \ { \ for (int z = 0; z < 5; ++z) \ { \ pbaA.setBlock({x, y, z}, fmt::format(FMT_STRING("A-{}-{}-{}"), x, y, z), BlockState()); \ } \ } \ } \ auto pbaB = PalettedBlockArea::createFilled({6, 6, 6}, "blockB", BlockState()); \ for (int x = 0; x < 6; ++x) \ { \ for (int y = 0; y < 6; ++y) \ { \ for (int z = 0; z < 6; ++z) \ { \ pbaB.setBlock({x, y, z}, fmt::format(FMT_STRING("B-{}-{}-{}"), x, y, z), BlockState()); \ } \ } \ } \ do { } while (false) // This is the data for the original PBA, before the paste() operations. // It is included here so that when adding new paste() tests we can simply copy it // into the test function and modify for the test. /* static const AString expected[5][5][5] = { { {"A-0-0-0", "A-1-0-0", "A-2-0-0", "A-3-0-0", "A-4-0-0"}, {"A-0-1-0", "A-1-1-0", "A-2-1-0", "A-3-1-0", "A-4-1-0"}, {"A-0-2-0", "A-1-2-0", "A-2-2-0", "A-3-2-0", "A-4-2-0"}, {"A-0-3-0", "A-1-3-0", "A-2-3-0", "A-3-3-0", "A-4-3-0"}, {"A-0-4-0", "A-1-4-0", "A-2-4-0", "A-3-4-0", "A-4-4-0"}, }, { {"A-0-0-1", "A-1-0-1", "A-2-0-1", "A-3-0-1", "A-4-0-1"}, {"A-0-1-1", "A-1-1-1", "A-2-1-1", "A-3-1-1", "A-4-1-1"}, {"A-0-2-1", "A-1-2-1", "A-2-2-1", "A-3-2-1", "A-4-2-1"}, {"A-0-3-1", "A-1-3-1", "A-2-3-1", "A-3-3-1", "A-4-3-1"}, {"A-0-4-1", "A-1-4-1", "A-2-4-1", "A-3-4-1", "A-4-4-1"}, }, { {"A-0-0-2", "A-1-0-2", "A-2-0-2", "A-3-0-2", "A-4-0-2"}, {"A-0-1-2", "A-1-1-2", "A-2-1-2", "A-3-1-2", "A-4-1-2"}, {"A-0-2-2", "A-1-2-2", "A-2-2-2", "A-3-2-2", "A-4-2-2"}, {"A-0-3-2", "A-1-3-2", "A-2-3-2", "A-3-3-2", "A-4-3-2"}, {"A-0-4-2", "A-1-4-2", "A-2-4-2", "A-3-4-2", "A-4-4-2"}, }, { {"A-0-0-3", "A-1-0-3", "A-2-0-3", "A-3-0-3", "A-4-0-3"}, {"A-0-1-3", "A-1-1-3", "A-2-1-3", "A-3-1-3", "A-4-1-3"}, {"A-0-2-3", "A-1-2-3", "A-2-2-3", "A-3-2-3", "A-4-2-3"}, {"A-0-3-3", "A-1-3-3", "A-2-3-3", "A-3-3-3", "A-4-3-3"}, {"A-0-4-3", "A-1-4-3", "A-2-4-3", "A-3-4-3", "A-4-4-3"}, }, { {"A-0-0-4", "A-1-0-4", "A-2-0-4", "A-3-0-4", "A-4-0-4"}, {"A-0-1-4", "A-1-1-4", "A-2-1-4", "A-3-1-4", "A-4-1-4"}, {"A-0-2-4", "A-1-2-4", "A-2-2-4", "A-3-2-4", "A-4-2-4"}, {"A-0-3-4", "A-1-3-4", "A-2-3-4", "A-3-3-4", "A-4-3-4"}, {"A-0-4-4", "A-1-4-4", "A-2-4-4", "A-3-4-4", "A-4-4-4"}, }, }; */ /** Tests the "paste()" operation with the pasted region being completely inside the destination PBA. */ static void testPastingCompletelyInside() { LOG("Testing the paste() API with destination completely inside (with cropping)..."); PREPARE_PASTING_PBAS; pbaA.paste(pbaB, cCuboid({1, 1, 1}, {4, 4, 4}), {1, 0, 0}); // Paste the 3x3x3 inside area from pbaB to pbaA, starting at {1, 0, 0} static const AString expected[5][5][5] = { { {"A-0-0-0", "B-1-1-1", "B-2-1-1", "B-3-1-1", "A-4-0-0"}, {"A-0-1-0", "B-1-2-1", "B-2-2-1", "B-3-2-1", "A-4-1-0"}, {"A-0-2-0", "B-1-3-1", "B-2-3-1", "B-3-3-1", "A-4-2-0"}, {"A-0-3-0", "A-1-3-0", "A-2-3-0", "A-3-3-0", "A-4-3-0"}, {"A-0-4-0", "A-1-4-0", "A-2-4-0", "A-3-4-0", "A-4-4-0"}, }, { {"A-0-0-1", "B-1-1-2", "B-2-1-2", "B-3-1-2", "A-4-0-1"}, {"A-0-1-1", "B-1-2-2", "B-2-2-2", "B-3-2-2", "A-4-1-1"}, {"A-0-2-1", "B-1-3-2", "B-2-3-2", "B-3-3-2", "A-4-2-1"}, {"A-0-3-1", "A-1-3-1", "A-2-3-1", "A-3-3-1", "A-4-3-1"}, {"A-0-4-1", "A-1-4-1", "A-2-4-1", "A-3-4-1", "A-4-4-1"}, }, { {"A-0-0-2", "B-1-1-3", "B-2-1-3", "B-3-1-3", "A-4-0-2"}, {"A-0-1-2", "B-1-2-3", "B-2-2-3", "B-3-2-3", "A-4-1-2"}, {"A-0-2-2", "B-1-3-3", "B-2-3-3", "B-3-3-3", "A-4-2-2"}, {"A-0-3-2", "A-1-3-2", "A-2-3-2", "A-3-3-2", "A-4-3-2"}, {"A-0-4-2", "A-1-4-2", "A-2-4-2", "A-3-4-2", "A-4-4-2"}, }, { {"A-0-0-3", "A-1-0-3", "A-2-0-3", "A-3-0-3", "A-4-0-3"}, {"A-0-1-3", "A-1-1-3", "A-2-1-3", "A-3-1-3", "A-4-1-3"}, {"A-0-2-3", "A-1-2-3", "A-2-2-3", "A-3-2-3", "A-4-2-3"}, {"A-0-3-3", "A-1-3-3", "A-2-3-3", "A-3-3-3", "A-4-3-3"}, {"A-0-4-3", "A-1-4-3", "A-2-4-3", "A-3-4-3", "A-4-4-3"}, }, { {"A-0-0-4", "A-1-0-4", "A-2-0-4", "A-3-0-4", "A-4-0-4"}, {"A-0-1-4", "A-1-1-4", "A-2-1-4", "A-3-1-4", "A-4-1-4"}, {"A-0-2-4", "A-1-2-4", "A-2-2-4", "A-3-2-4", "A-4-2-4"}, {"A-0-3-4", "A-1-3-4", "A-2-3-4", "A-3-3-4", "A-4-3-4"}, {"A-0-4-4", "A-1-4-4", "A-2-4-4", "A-3-4-4", "A-4-4-4"}, }, }; for (int x = 0; x < 5; ++x) { for (int y = 0; y < 5; ++y) { for (int z = 0; z < 5; ++z) { auto got = pbaA.block({x, y, z}).first; TEST_EQUAL_MSG( pbaA.block({x, y, z}).first, expected[z][y][x], fmt::format(FMT_STRING("{{{}, {}, {}}}, exp {}, got {}"), x, y, z, expected[z][y][x], pbaA.block({x, y, z}).first) ); } } } } /** Tests the "paste()" operation with the pasted region overflowing the destination PBA into the positive coords. */ static void testPastingPositiveOverflow() { LOG("Testing the paste() API with positive overflow..."); PREPARE_PASTING_PBAS; pbaA.paste(pbaB, Vector3i{3, 2, 1}); // Paste the entire pbaB to pbaA, starting at {3, 2, 1} static const AString expected[5][5][5] = { { {"A-0-0-0", "A-1-0-0", "A-2-0-0", "A-3-0-0", "A-4-0-0"}, {"A-0-1-0", "A-1-1-0", "A-2-1-0", "A-3-1-0", "A-4-1-0"}, {"A-0-2-0", "A-1-2-0", "A-2-2-0", "A-3-2-0", "A-4-2-0"}, {"A-0-3-0", "A-1-3-0", "A-2-3-0", "A-3-3-0", "A-4-3-0"}, {"A-0-4-0", "A-1-4-0", "A-2-4-0", "A-3-4-0", "A-4-4-0"}, }, { {"A-0-0-1", "A-1-0-1", "A-2-0-1", "A-3-0-1", "A-4-0-1"}, {"A-0-1-1", "A-1-1-1", "A-2-1-1", "A-3-1-1", "A-4-1-1"}, {"A-0-2-1", "A-1-2-1", "A-2-2-1", "B-0-0-0", "B-1-0-0"}, {"A-0-3-1", "A-1-3-1", "A-2-3-1", "B-0-1-0", "B-1-1-0"}, {"A-0-4-1", "A-1-4-1", "A-2-4-1", "B-0-2-0", "B-1-2-0"}, }, { {"A-0-0-2", "A-1-0-2", "A-2-0-2", "A-3-0-2", "A-4-0-2"}, {"A-0-1-2", "A-1-1-2", "A-2-1-2", "A-3-1-2", "A-4-1-2"}, {"A-0-2-2", "A-1-2-2", "A-2-2-2", "B-0-0-1", "B-1-0-1"}, {"A-0-3-2", "A-1-3-2", "A-2-3-2", "B-0-1-1", "B-1-1-1"}, {"A-0-4-2", "A-1-4-2", "A-2-4-2", "B-0-2-1", "B-1-2-1"}, }, { {"A-0-0-3", "A-1-0-3", "A-2-0-3", "A-3-0-3", "A-4-0-3"}, {"A-0-1-3", "A-1-1-3", "A-2-1-3", "A-3-1-3", "A-4-1-3"}, {"A-0-2-3", "A-1-2-3", "A-2-2-3", "B-0-0-2", "B-1-0-2"}, {"A-0-3-3", "A-1-3-3", "A-2-3-3", "B-0-1-2", "B-1-1-2"}, {"A-0-4-3", "A-1-4-3", "A-2-4-3", "B-0-2-2", "B-1-2-2"}, }, { {"A-0-0-4", "A-1-0-4", "A-2-0-4", "A-3-0-4", "A-4-0-4"}, {"A-0-1-4", "A-1-1-4", "A-2-1-4", "A-3-1-4", "A-4-1-4"}, {"A-0-2-4", "A-1-2-4", "A-2-2-4", "B-0-0-3", "B-1-0-3"}, {"A-0-3-4", "A-1-3-4", "A-2-3-4", "B-0-1-3", "B-1-1-3"}, {"A-0-4-4", "A-1-4-4", "A-2-4-4", "B-0-2-3", "B-1-2-3"}, }, }; for (int x = 0; x < 5; ++x) { for (int y = 0; y < 5; ++y) { for (int z = 0; z < 5; ++z) { auto got = pbaA.block({x, y, z}).first; TEST_EQUAL_MSG( pbaA.block({x, y, z}).first, expected[z][y][x], fmt::format(FMT_STRING("{{{}, {}, {}}}, exp {}, got {}"), x, y, z, expected[z][y][x], pbaA.block({x, y, z}).first) ); } } } } /** Tests the "paste()" operation with the pasted region overflowing the destination PBA into the negative coords. */ static void testPastingNegativeOverflow() { LOG("Testing the paste() API with negative overflow..."); PREPARE_PASTING_PBAS; pbaA.paste(pbaB, Vector3i{-4, -3, -2}); // Paste the entire pbaB to pbaA, starting at {-4, -3, -2} static const AString expected[5][5][5] = { { {"B-4-3-2", "B-5-3-2", "A-2-0-0", "A-3-0-0", "A-4-0-0"}, {"B-4-4-2", "B-5-4-2", "A-2-1-0", "A-3-1-0", "A-4-1-0"}, {"B-4-5-2", "B-5-5-2", "A-2-2-0", "A-3-2-0", "A-4-2-0"}, {"A-0-3-0", "A-1-3-0", "A-2-3-0", "A-3-3-0", "A-4-3-0"}, {"A-0-4-0", "A-1-4-0", "A-2-4-0", "A-3-4-0", "A-4-4-0"}, }, { {"B-4-3-3", "B-5-3-3", "A-2-0-1", "A-3-0-1", "A-4-0-1"}, {"B-4-4-3", "B-5-4-3", "A-2-1-1", "A-3-1-1", "A-4-1-1"}, {"B-4-5-3", "B-5-5-3", "A-2-2-1", "A-3-2-1", "A-4-2-1"}, {"A-0-3-1", "A-1-3-1", "A-2-3-1", "A-3-3-1", "A-4-3-1"}, {"A-0-4-1", "A-1-4-1", "A-2-4-1", "A-3-4-1", "A-4-4-1"}, }, { {"B-4-3-4", "B-5-3-4", "A-2-0-2", "A-3-0-2", "A-4-0-2"}, {"B-4-4-4", "B-5-4-4", "A-2-1-2", "A-3-1-2", "A-4-1-2"}, {"B-4-5-4", "B-5-5-4", "A-2-2-2", "A-3-2-2", "A-4-2-2"}, {"A-0-3-2", "A-1-3-2", "A-2-3-2", "A-3-3-2", "A-4-3-2"}, {"A-0-4-2", "A-1-4-2", "A-2-4-2", "A-3-4-2", "A-4-4-2"}, }, { {"B-4-3-5", "B-5-3-5", "A-2-0-3", "A-3-0-3", "A-4-0-3"}, {"B-4-4-5", "B-5-4-5", "A-2-1-3", "A-3-1-3", "A-4-1-3"}, {"B-4-5-5", "B-5-5-5", "A-2-2-3", "A-3-2-3", "A-4-2-3"}, {"A-0-3-3", "A-1-3-3", "A-2-3-3", "A-3-3-3", "A-4-3-3"}, {"A-0-4-3", "A-1-4-3", "A-2-4-3", "A-3-4-3", "A-4-4-3"}, }, { {"A-0-0-4", "A-1-0-4", "A-2-0-4", "A-3-0-4", "A-4-0-4"}, {"A-0-1-4", "A-1-1-4", "A-2-1-4", "A-3-1-4", "A-4-1-4"}, {"A-0-2-4", "A-1-2-4", "A-2-2-4", "A-3-2-4", "A-4-2-4"}, {"A-0-3-4", "A-1-3-4", "A-2-3-4", "A-3-3-4", "A-4-3-4"}, {"A-0-4-4", "A-1-4-4", "A-2-4-4", "A-3-4-4", "A-4-4-4"}, }, }; for (int x = 0; x < 5; ++x) { for (int y = 0; y < 5; ++y) { for (int z = 0; z < 5; ++z) { auto got = pbaA.block({x, y, z}).first; TEST_EQUAL_MSG( pbaA.block({x, y, z}).first, expected[z][y][x], fmt::format(FMT_STRING("{{{}, {}, {}}}, exp {}, got {}"), x, y, z, expected[z][y][x], pbaA.block({x, y, z}).first) ); } } } } /** Tests the "paste()" operation with the pasted region overflowing the destination PBA into mixed positive and negative coords. */ static void testPastingMixedOverflow() { LOG("Testing the paste() API with mixed positive and negative overflow..."); PREPARE_PASTING_PBAS; pbaA.paste(pbaB, Vector3i{-4, -3, 2}); // Paste the entire pbaB to pbaA, starting at {-4, -3, 2} static const AString expected[5][5][5] = { { {"A-0-0-0", "A-1-0-0", "A-2-0-0", "A-3-0-0", "A-4-0-0"}, {"A-0-1-0", "A-1-1-0", "A-2-1-0", "A-3-1-0", "A-4-1-0"}, {"A-0-2-0", "A-1-2-0", "A-2-2-0", "A-3-2-0", "A-4-2-0"}, {"A-0-3-0", "A-1-3-0", "A-2-3-0", "A-3-3-0", "A-4-3-0"}, {"A-0-4-0", "A-1-4-0", "A-2-4-0", "A-3-4-0", "A-4-4-0"}, }, { {"A-0-0-1", "A-1-0-1", "A-2-0-1", "A-3-0-1", "A-4-0-1"}, {"A-0-1-1", "A-1-1-1", "A-2-1-1", "A-3-1-1", "A-4-1-1"}, {"A-0-2-1", "A-1-2-1", "A-2-2-1", "A-3-2-1", "A-4-2-1"}, {"A-0-3-1", "A-1-3-1", "A-2-3-1", "A-3-3-1", "A-4-3-1"}, {"A-0-4-1", "A-1-4-1", "A-2-4-1", "A-3-4-1", "A-4-4-1"}, }, { {"B-4-3-0", "B-5-3-0", "A-2-0-2", "A-3-0-2", "A-4-0-2"}, {"B-4-4-0", "B-5-4-0", "A-2-1-2", "A-3-1-2", "A-4-1-2"}, {"B-4-5-0", "B-5-5-0", "A-2-2-2", "A-3-2-2", "A-4-2-2"}, {"A-0-3-2", "A-1-3-2", "A-2-3-2", "A-3-3-2", "A-4-3-2"}, {"A-0-4-2", "A-1-4-2", "A-2-4-2", "A-3-4-2", "A-4-4-2"}, }, { {"B-4-3-1", "B-5-3-1", "A-2-0-3", "A-3-0-3", "A-4-0-3"}, {"B-4-4-1", "B-5-4-1", "A-2-1-3", "A-3-1-3", "A-4-1-3"}, {"B-4-5-1", "B-5-5-1", "A-2-2-3", "A-3-2-3", "A-4-2-3"}, {"A-0-3-3", "A-1-3-3", "A-2-3-3", "A-3-3-3", "A-4-3-3"}, {"A-0-4-3", "A-1-4-3", "A-2-4-3", "A-3-4-3", "A-4-4-3"}, }, { {"B-4-3-2", "B-5-3-2", "A-2-0-4", "A-3-0-4", "A-4-0-4"}, {"B-4-4-2", "B-5-4-2", "A-2-1-4", "A-3-1-4", "A-4-1-4"}, {"B-4-5-2", "B-5-5-2", "A-2-2-4", "A-3-2-4", "A-4-2-4"}, {"A-0-3-4", "A-1-3-4", "A-2-3-4", "A-3-3-4", "A-4-3-4"}, {"A-0-4-4", "A-1-4-4", "A-2-4-4", "A-3-4-4", "A-4-4-4"}, }, }; for (int x = 0; x < 5; ++x) { for (int y = 0; y < 5; ++y) { for (int z = 0; z < 5; ++z) { auto got = pbaA.block({x, y, z}).first; TEST_EQUAL_MSG( pbaA.block({x, y, z}).first, expected[z][y][x], fmt::format(FMT_STRING("{{{}, {}, {}}}, exp {}, got {}"), x, y, z, expected[z][y][x], pbaA.block({x, y, z}).first) ); } } } } IMPLEMENT_TEST_MAIN("PalettedBlockArea", testCreation(); testSetting(); testPastingCompletelyInside(); testPastingPositiveOverflow(); testPastingNegativeOverflow(); testPastingMixedOverflow(); ) ================================================ FILE: tests/BoundingBox/BoundingBoxTest.cpp ================================================ // ByteBufferTest.cpp // Implements the main app entrypoint for the cByteBuffer class test #include "Globals.h" #include "BoundingBox.h" /** Runs the tests, returns the number of failed tests. */ static int Test(void) { int NumFailed = 0; Vector3d Min(1, 1, 1); Vector3d Max(2, 2, 2); Vector3d LineDefs[] = { Vector3d(1.5, 4, 1.5), Vector3d(1.5, 3, 1.5), // Should intersect at 2, face 1 (YP) Vector3d(1.5, 0, 1.5), Vector3d(1.5, 4, 1.5), // Should intersect at 0.25, face 0 (YM) Vector3d(0, 0, 0), Vector3d(2, 2, 2), // Should intersect at 0.5, face 0, 3 or 5 (anyM) Vector3d(0.999, 0, 1.5), Vector3d(0.999, 4, 1.5), // Should not intersect Vector3d(1.999, 0, 1.5), Vector3d(1.999, 4, 1.5), // Should intersect at 0.25, face 0 (YM) Vector3d(2.001, 0, 1.5), Vector3d(2.001, 4, 1.5), // Should not intersect } ; bool Results[] = {true, true, true, false, true, false}; double LineCoeffs[] = {2, 0.25, 0.5, 0, 0.25, 0}; for (size_t i = 0; i < ARRAYCOUNT(LineDefs) / 2; i++) { double LineCoeff; eBlockFace Face; Vector3d Line1 = LineDefs[2 * i]; Vector3d Line2 = LineDefs[2 * i + 1]; bool res = cBoundingBox::CalcLineIntersection(Min, Max, Line1, Line2, LineCoeff, Face); if (res != Results[i]) { LOGERROR("LineIntersection({%.02f, %.02f, %.02f}, {%.02f, %.02f, %.02f}) -> %d, %.05f, %d", Line1.x, Line1.y, Line1.z, Line2.x, Line2.y, Line2.z, res ? 1 : 0, LineCoeff, Face ); NumFailed += 1; } if (res) { if (std::abs(LineCoeff - LineCoeffs[i]) > 0.0000001) { LOGERROR("LineIntersection({%.02f, %.02f, %.02f}, {%.02f, %.02f, %.02f}) -> %d, %.05f, %d", Line1.x, Line1.y, Line1.z, Line2.x, Line2.y, Line2.z, res ? 1 : 0, LineCoeff, Face ); NumFailed += 1; } } } // for i - LineDefs[] return 0; } int main(int argc, char * argv[]) { LOGD("Test started"); LOGD("Running test"); auto NumFailed = Test(); LOG("BoundingBox test finished, number of failed tests: %d", NumFailed); return NumFailed; } ================================================ FILE: tests/BoundingBox/CMakeLists.txt ================================================ include_directories(${PROJECT_SOURCE_DIR}/src/) set (SHARED_SRCS ${PROJECT_SOURCE_DIR}/src/BoundingBox.cpp ${PROJECT_SOURCE_DIR}/src/OSSupport/StackTrace.cpp ${PROJECT_SOURCE_DIR}/src/OSSupport/WinStackWalker.cpp ) set (SHARED_HDRS ${PROJECT_SOURCE_DIR}/src/BoundingBox.h ${PROJECT_SOURCE_DIR}/src/OSSupport/StackTrace.h ${PROJECT_SOURCE_DIR}/src/OSSupport/WinStackWalker.h ) set (SRCS BoundingBoxTest.cpp ) source_group("Shared" FILES ${SHARED_SRCS} ${SHARED_HDRS}) source_group("Sources" FILES ${SRCS}) add_executable(BoundingBox-exe ${SRCS} ${SHARED_SRCS} ${SHARED_HDRS}) target_link_libraries(BoundingBox-exe fmt::fmt) add_test(NAME BoundingBox-test COMMAND BoundingBox-exe) # Put the projects into solution folders (MSVC): set_target_properties( BoundingBox-exe PROPERTIES FOLDER Tests ) ================================================ FILE: tests/ByteBuffer/ByteBufferTest.cpp ================================================ // ByteBufferTest.cpp // Implements the main app entrypoint for the cByteBuffer class test #include "Globals.h" #include "../TestHelpers.h" #include "ByteBuffer.h" static void TestRead(void) { cByteBuffer buf(50); buf.Write("\x05\xac\x02\x00", 4); UInt32 v1; TEST_TRUE(buf.ReadVarInt(v1)); TEST_EQUAL(v1, 5); UInt32 v2; TEST_TRUE(buf.ReadVarInt(v2)); TEST_EQUAL(v2, 300); UInt32 v3; TEST_TRUE(buf.ReadVarInt(v3)); TEST_EQUAL(v3, 0); } static void TestWrite(void) { cByteBuffer buf(50); buf.WriteVarInt32(5); buf.WriteVarInt32(300); buf.WriteVarInt32(0); ContiguousByteBuffer All; buf.ReadAll(All); TEST_EQUAL(All.size(), 4); TEST_EQUAL(memcmp(All.data(), "\x05\xac\x02\x00", All.size()), 0); } static void TestWrap(void) { cByteBuffer buf(3); for (int i = 0; i < 1000; i++) { size_t FreeSpace = buf.GetFreeSpace(); TEST_EQUAL(buf.GetReadableSpace(), 0); TEST_GREATER_THAN_OR_EQUAL(FreeSpace, 1); TEST_TRUE(buf.Write("a", 1)); TEST_TRUE(buf.CanReadBytes(1)); TEST_EQUAL(buf.GetReadableSpace(), 1); UInt8 v = 0; TEST_TRUE(buf.ReadBEUInt8(v)); TEST_EQUAL(v, 'a'); TEST_EQUAL(buf.GetReadableSpace(), 0); buf.CommitRead(); TEST_EQUAL(buf.GetFreeSpace(), FreeSpace); // We're back to normal } } static void TestXYZPositionRoundtrip(void) { cByteBuffer buf(50); buf.WriteXYZPosition64(-33554432, -2048, -33554432); // Testing the minimun values int x, y, z; TEST_TRUE(buf.ReadXYZPosition64(x, y, z)); TEST_EQUAL(x, -33554432); TEST_EQUAL(y, -2048); TEST_EQUAL(z, -33554432); } static void TestXZYPositionRoundtrip(void) { cByteBuffer buf(50); buf.WriteXZYPosition64(-33554432, -2048, -33554432); // Testing the minimun values int x, y, z; TEST_TRUE(buf.ReadXZYPosition64(x, y, z)); TEST_EQUAL(x, -33554432); TEST_EQUAL(y, -2048); TEST_EQUAL(z, -33554432); } IMPLEMENT_TEST_MAIN("ByteBuffer", TestRead(); TestWrite(); TestWrap(); TestXYZPositionRoundtrip(); TestXZYPositionRoundtrip(); ) ================================================ FILE: tests/ByteBuffer/CMakeLists.txt ================================================ include_directories(${PROJECT_SOURCE_DIR}/src/) set (SHARED_SRCS ${PROJECT_SOURCE_DIR}/src/ByteBuffer.cpp ${PROJECT_SOURCE_DIR}/src/StringUtils.cpp ) set (SHARED_HDRS ../TestHelpers.h ${PROJECT_SOURCE_DIR}/src/ByteBuffer.h ${PROJECT_SOURCE_DIR}/src/StringUtils.h ) set (SRCS ByteBufferTest.cpp Stubs.cpp ) source_group("Shared" FILES ${SHARED_SRCS} ${SHARED_HDRS}) source_group("Sources" FILES ${SRCS}) add_executable(ByteBuffer-exe ${SRCS} ${SHARED_SRCS} ${SHARED_HDRS}) target_link_libraries(ByteBuffer-exe fmt::fmt) if (WIN32) target_link_libraries(ByteBuffer-exe ws2_32) endif() add_test(NAME ByteBuffer-test COMMAND ByteBuffer-exe) # Put the projects into solution folders (MSVC): set_target_properties( ByteBuffer-exe PROPERTIES FOLDER Tests ) ================================================ FILE: tests/ByteBuffer/Stubs.cpp ================================================ // Stubs.cpp // Implements stubs of various Cuberite methods that are needed for linking but not for runtime // This is required so that we don't bring in the entire Cuberite via dependencies #include "Globals.h" #include "UUID.h" void cUUID::FromRaw(const std::array &){} ================================================ FILE: tests/CMakeLists.txt ================================================ if (CMAKE_BUILD_TYPE STREQUAL "COVERAGE") setup_target_for_coverage("${PROJECT_NAME}_coverage" "ctest" coverage) endif() add_compile_definitions(TEST_GLOBALS) add_subdirectory(BlockTypeRegistry) add_subdirectory(BoundingBox) add_subdirectory(ByteBuffer) add_subdirectory(ChunkData) add_subdirectory(CompositeChat) add_subdirectory(FastRandom) add_subdirectory(Generating) add_subdirectory(HTTP) add_subdirectory(LuaThreadStress) add_subdirectory(Network) add_subdirectory(OSSupport) add_subdirectory(SchematicFileSerializer) add_subdirectory(UUID) ================================================ FILE: tests/ChunkData/ArraytoCoord.cpp ================================================ #include "Globals.h" #include "../TestHelpers.h" #include "ChunkData.h" /** Performs the entire ArrayToCoords test. */ static void test() { { // Test first segment (blocks) ChunkBlockData buffer; BLOCKTYPE SrcBlockBuffer[16 * 16 * 256]; memset(SrcBlockBuffer, 0x00, sizeof(SrcBlockBuffer)); SrcBlockBuffer[7 + (4 * 16) + (5 * 16 * 16)] = 0xcd; NIBBLETYPE SrcNibbleBuffer[16 * 16 * 256 / 2]; memset(SrcNibbleBuffer, 0x00, sizeof(SrcNibbleBuffer)); SrcNibbleBuffer[(6 + (1 * 16) + (2 * 16 * 16)) / 2] = 0xe; buffer.SetAll(SrcBlockBuffer, SrcNibbleBuffer); TEST_EQUAL(buffer.GetBlock({ 7, 5, 4 }), 0xcd); TEST_EQUAL(buffer.GetMeta({ 6, 2, 1 }), 0xe); } { // Test first segment (lights) ChunkLightData buffer; NIBBLETYPE SrcNibbleBuffer[16 * 16 * 256 / 2]; memset(SrcNibbleBuffer, 0x00, sizeof(SrcNibbleBuffer)); SrcNibbleBuffer[(6 + (1 * 16) + (2 * 16 * 16)) / 2] = 0xe; buffer.SetAll(SrcNibbleBuffer, SrcNibbleBuffer); TEST_EQUAL(buffer.GetBlockLight({ 6, 2, 1 }), 0xe); TEST_EQUAL(buffer.GetSkyLight({ 6, 2, 1 }), 0xe); } { // test following segment (blocks) ChunkBlockData buffer; BLOCKTYPE SrcBlockBuffer[16 * 16 * 256]; memset(SrcBlockBuffer, 0x00, sizeof(SrcBlockBuffer)); SrcBlockBuffer[7 + (4 * 16) + (24 * 16 * 16)] = 0xcd; NIBBLETYPE SrcNibbleBuffer[16 * 16 * 256 / 2]; memset(SrcNibbleBuffer, 0x00, sizeof(SrcNibbleBuffer)); SrcNibbleBuffer[(6 + (1 * 16) + (24 * 16 * 16)) / 2] = 0xe; buffer.SetAll(SrcBlockBuffer, SrcNibbleBuffer); TEST_EQUAL(buffer.GetBlock({ 7, 24, 4 }), 0xcd); TEST_EQUAL(buffer.GetMeta({ 6, 24, 1 }), 0xe); } { // test following segment (lights) ChunkLightData buffer; NIBBLETYPE SrcNibbleBuffer[16 * 16 * 256 / 2]; memset(SrcNibbleBuffer, 0x00, sizeof(SrcNibbleBuffer)); SrcNibbleBuffer[(6 + (1 * 16) + (24 * 16 * 16)) / 2] = 0xe; buffer.SetAll(SrcNibbleBuffer, SrcNibbleBuffer); TEST_EQUAL(buffer.GetBlockLight({ 6, 24, 1 }), 0xe); TEST_EQUAL(buffer.GetSkyLight({ 6, 24, 1 }), 0xe); } { // test zeros (blocks) ChunkBlockData buffer; BLOCKTYPE SrcBlockBuffer[16 * 16 * 256]; memset(SrcBlockBuffer, 0x00, sizeof(SrcBlockBuffer)); NIBBLETYPE SrcNibbleBuffer[16 * 16 * 256 / 2]; memset(SrcNibbleBuffer, 0x00, sizeof(SrcNibbleBuffer)); buffer.SetAll(SrcBlockBuffer, SrcNibbleBuffer); TEST_EQUAL(buffer.GetBlock({ 7, 24, 4 }), 0x00); TEST_EQUAL(buffer.GetMeta({ 6, 24, 1 }), 0x0); } { // test zeros (lights) ChunkLightData buffer; NIBBLETYPE SrcNibbleBuffer[16 * 16 * 256 / 2]; memset(SrcNibbleBuffer, 0x00, sizeof(SrcNibbleBuffer)); NIBBLETYPE SrcNibbleBuffer2[16 * 16 * 256 / 2]; memset(SrcNibbleBuffer2, 0xff, sizeof(SrcNibbleBuffer2)); buffer.SetAll(SrcNibbleBuffer, SrcNibbleBuffer2); TEST_EQUAL(buffer.GetBlockLight({ 6, 24, 1 }), 0x0); TEST_EQUAL(buffer.GetSkyLight({ 6, 24, 1 }), 0xf); } } IMPLEMENT_TEST_MAIN("ChunkData ArrayToCoord", test(); ) ================================================ FILE: tests/ChunkData/CMakeLists.txt ================================================ include_directories(${PROJECT_SOURCE_DIR}/src/) add_library(ChunkBuffer ${PROJECT_SOURCE_DIR}/src/ChunkData.cpp ${PROJECT_SOURCE_DIR}/src/StringUtils.cpp) target_link_libraries(ChunkBuffer PUBLIC fmt::fmt) 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) # Put all test projects into a separate folder: set_target_properties( arraystocoords-exe coordinates-exe copies-exe creatable-exe PROPERTIES FOLDER Tests/ChunkData ) set_target_properties( ChunkBuffer PROPERTIES FOLDER Tests/Libraries ) ================================================ FILE: tests/ChunkData/Coordinates.cpp ================================================ #include "Globals.h" #include "../TestHelpers.h" #include "ChunkData.h" /** Performs the entire cChunkData coordinates test. */ static void test() { { ChunkBlockData buffer; // Empty chunks buffer.SetBlock({ 0, 0, 0 }, 0xAB); TEST_EQUAL(buffer.GetBlock({ 0, 0, 0 }), 0xAB); buffer.SetMeta({ 0, 16, 0 }, 0xC); TEST_EQUAL(buffer.GetMeta({ 0, 16, 0 }), 0xC); // loaded but not written segments TEST_EQUAL(buffer.GetBlock({ 1, 0, 0 }), 0x0); TEST_EQUAL(buffer.GetMeta({ 1, 16, 0 }), 0x0); // Notloaded segments TEST_EQUAL(buffer.GetBlock({ 0, 32, 0 }), 0x0); TEST_EQUAL(buffer.GetMeta({ 0, 48, 0 }), 0x0); // Out of range GetBlock TEST_ASSERTS( buffer.GetBlock({ -1, 0, 0 }); ); TEST_ASSERTS( buffer.GetBlock({ 0, -1, 0 }); ); TEST_ASSERTS( buffer.GetBlock({ 0, 0, -1 }); ); TEST_ASSERTS( buffer.GetBlock({ 256, 0, 0 }); ); TEST_ASSERTS( buffer.GetBlock({ 0, 256, 0 }); ); TEST_ASSERTS( buffer.GetBlock({ 0, 0, 256 }); ); // Out of range SetBlock TEST_ASSERTS( buffer.SetBlock({ -1, 0, 0 }, 0) ); TEST_ASSERTS( buffer.SetBlock({ 0, -1, 0 }, 0) ); TEST_ASSERTS( buffer.SetBlock({ 0, 0, -1 }, 0) ); TEST_ASSERTS( buffer.SetBlock({ 256, 0, 0 }, 0) ); TEST_ASSERTS( buffer.SetBlock({ 0, 256, 0 }, 0) ); TEST_ASSERTS( buffer.SetBlock({ 0, 0, 256 }, 0) ); // Out of range GetMeta TEST_ASSERTS( buffer.GetMeta({ -1, 0, 0 }); ); TEST_ASSERTS( buffer.GetMeta({ 0, -1, 0 }); ); TEST_ASSERTS( buffer.GetMeta({ 0, 0, -1 }); ); TEST_ASSERTS( buffer.GetMeta({ 256, 0, 0 }); ); TEST_ASSERTS( buffer.GetMeta({ 0, 256, 0 }); ); TEST_ASSERTS( buffer.GetMeta({ 0, 0, 256 }); ); // Out of range SetMeta TEST_ASSERTS( buffer.SetMeta({ -1, 0, 0 }, 0) ); TEST_ASSERTS( buffer.SetMeta({ 0, -1, 0 }, 0) ); TEST_ASSERTS( buffer.SetMeta({ 0, 0, -1 }, 0) ); TEST_ASSERTS( buffer.SetMeta({ 256, 0, 0 }, 0) ); TEST_ASSERTS( buffer.SetMeta({ 0, 256, 0 }, 0) ); TEST_ASSERTS( buffer.SetMeta({ 0, 0, 256 }, 0) ); } { ChunkBlockData buffer; // Zero's buffer.SetBlock({ 0, 0, 0 }, 0x0); buffer.SetBlock({ 0, 0, 1 }, 0xab); TEST_EQUAL(buffer.GetBlock({ 0, 0, 0 }), 0x0); TEST_EQUAL(buffer.GetBlock({ 0, 0, 1 }), 0xab); buffer.SetMeta({ 0, 16, 0 }, 0x0); buffer.SetMeta({ 0, 16, 1 }, 0xc); TEST_EQUAL(buffer.GetMeta({ 0, 16, 0 }), 0x0); TEST_EQUAL(buffer.GetMeta({ 0, 16, 1 }), 0xc); } { // Operator = ChunkBlockData buffer; buffer.SetBlock({ 0, 0, 0 }, 0x42); ChunkBlockData copy; copy = std::move(buffer); TEST_EQUAL(copy.GetBlock({ 0, 0, 0 }), 0x42); } } IMPLEMENT_TEST_MAIN("ChunkData Coordinates", test(); ) ================================================ FILE: tests/ChunkData/Copies.cpp ================================================ #include "Globals.h" #include "../TestHelpers.h" #include "ChunkData.h" /** Helper that copies a data store into a contiguous flat array, filling in a default value for sections that aren't present. */ template static void CopyAll(const StoreType & Data, GetType Getter, DefaultType Default, OutType & Out) { constexpr auto SectionCount = std::extent_v / 16; for (size_t Y = 0; Y != 16; Y++) { const auto Section = (Data.*Getter)(Y); static_assert(SectionCount == std::tuple_size>::value, "Output array has wrong size"); if (Section == nullptr) { std::fill_n(Out + Y * SectionCount, SectionCount, Default); } else { std::copy(Section->begin(), Section->end(), Out + Y * SectionCount); } } } /** Performs the entire Copies test. */ static void Test() { LOGD("Test started"); { ChunkBlockData buffer; buffer.SetBlock({ 3, 1, 4 }, 0xDE); buffer.SetMeta({ 3, 1, 4 }, 0xA); ChunkBlockData copy; copy.Assign(buffer); TEST_EQUAL(copy.GetBlock({ 3, 1, 4 }), 0xDE); TEST_EQUAL(copy.GetMeta({ 3, 1, 4 }), 0xA); BLOCKTYPE SrcBlockBuffer[16 * 16 * 256]; NIBBLETYPE SrcNibbleBuffer[16 * 16 * 256 / 2]{}; 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.SetAll(SrcBlockBuffer, SrcNibbleBuffer); BLOCKTYPE DstBlockBuffer[16 * 16 * 256]; CopyAll(buffer, &ChunkBlockData::GetSection, ChunkBlockData::DefaultValue, DstBlockBuffer); TEST_EQUAL(memcmp(SrcBlockBuffer, DstBlockBuffer, (16 * 16 * 256) - 1), 0); memset(SrcBlockBuffer, 0x00, 16 * 16 * 256); buffer.SetAll(SrcBlockBuffer, SrcNibbleBuffer); CopyAll(buffer, &ChunkBlockData::GetSection, ChunkBlockData::DefaultValue, DstBlockBuffer); TEST_EQUAL(memcmp(SrcBlockBuffer, DstBlockBuffer, (16 * 16 * 256) - 1), 0); } { ChunkBlockData buffer; BLOCKTYPE SrcBlockBuffer[16 * 16 * 256]{}; 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.SetAll(SrcBlockBuffer, SrcNibbleBuffer); NIBBLETYPE DstNibbleBuffer[16 * 16 * 256/ 2]; CopyAll(buffer, &ChunkBlockData::GetMetaSection, ChunkBlockData::DefaultMetaValue, DstNibbleBuffer); TEST_EQUAL(memcmp(SrcNibbleBuffer, DstNibbleBuffer, (16 * 16 * 256 / 2) - 1), 0); memset(SrcNibbleBuffer, 0x00, 16 * 16 * 256 /2); buffer.SetAll(SrcBlockBuffer, SrcNibbleBuffer); CopyAll(buffer, &ChunkBlockData::GetMetaSection, ChunkBlockData::DefaultMetaValue, DstNibbleBuffer); TEST_EQUAL(memcmp(SrcNibbleBuffer, DstNibbleBuffer, (16 * 16 * 256 / 2) - 1), 0); } { ChunkLightData 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.SetAll(SrcNibbleBuffer, SrcNibbleBuffer); NIBBLETYPE DstNibbleBuffer[16 * 16 * 256 / 2]; CopyAll(buffer, &ChunkLightData::GetBlockLightSection, ChunkLightData::DefaultBlockLightValue, DstNibbleBuffer); TEST_EQUAL(memcmp(SrcNibbleBuffer, DstNibbleBuffer, (16 * 16 * 256 /2) - 1), 0); memset(SrcNibbleBuffer, 0x00, 16 * 16 * 256 /2); buffer.SetAll(SrcNibbleBuffer, SrcNibbleBuffer); CopyAll(buffer, &ChunkLightData::GetBlockLightSection, ChunkLightData::DefaultBlockLightValue, DstNibbleBuffer); TEST_EQUAL(memcmp(SrcNibbleBuffer, DstNibbleBuffer, (16 * 16 * 256 /2) - 1), 0); } { ChunkLightData 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.SetAll(SrcNibbleBuffer, SrcNibbleBuffer); NIBBLETYPE DstNibbleBuffer[16 * 16 * 256/ 2]; CopyAll(buffer, &ChunkLightData::GetSkyLightSection, ChunkLightData::DefaultSkyLightValue, DstNibbleBuffer); TEST_EQUAL(memcmp(SrcNibbleBuffer, DstNibbleBuffer, (16 * 16 * 256 / 2) - 1), 0); memset(SrcNibbleBuffer, 0xFF, 16 * 16 * 256 / 2); buffer.SetAll(SrcNibbleBuffer, SrcNibbleBuffer); CopyAll(buffer, &ChunkLightData::GetSkyLightSection, ChunkLightData::DefaultSkyLightValue, DstNibbleBuffer); TEST_EQUAL(memcmp(SrcNibbleBuffer, DstNibbleBuffer, (16 * 16 * 256 / 2) - 1), 0); } { ChunkBlockData buffer; BLOCKTYPE SrcBlockBuffer[16 * 16 * 256]; memset(SrcBlockBuffer, 0x00, 16 * 16 * 256); BLOCKTYPE DstBlockBuffer[16 * 16 * 256]; CopyAll(buffer, &ChunkBlockData::GetSection, ChunkBlockData::DefaultValue, DstBlockBuffer); TEST_EQUAL(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]; CopyAll(buffer, &ChunkBlockData::GetMetaSection, ChunkBlockData::DefaultMetaValue, DstNibbleBuffer); TEST_EQUAL(memcmp(SrcNibbleBuffer, DstNibbleBuffer, (16 * 16 * 256 / 2) - 1), 0); } { ChunkLightData buffer; NIBBLETYPE SrcNibbleBuffer[16 * 16 * 256 / 2]; memset(SrcNibbleBuffer, 0x00, 16 * 16 * 256 / 2); NIBBLETYPE DstNibbleBuffer[16 * 16 * 256 / 2]; CopyAll(buffer, &ChunkLightData::GetBlockLightSection, ChunkLightData::DefaultBlockLightValue, DstNibbleBuffer); TEST_EQUAL(memcmp(SrcNibbleBuffer, DstNibbleBuffer, (16 * 16 * 256 / 2) - 1), 0); memset(SrcNibbleBuffer, 0xFF, 16 * 16 * 256 / 2); CopyAll(buffer, &ChunkLightData::GetSkyLightSection, ChunkLightData::DefaultSkyLightValue, DstNibbleBuffer); TEST_EQUAL(memcmp(SrcNibbleBuffer, DstNibbleBuffer, (16 * 16 * 256 / 2) - 1), 0); } } IMPLEMENT_TEST_MAIN("ChunkData Copies", Test() ) ================================================ FILE: tests/ChunkData/Creatable.cpp ================================================ #include "Globals.h" #include "../TestHelpers.h" #include "ChunkData.h" static void Test() { LOGD("Test started"); ChunkBlockData train; ChunkLightData buffer; /* /-|===D / |===D /---| / | ====/=====|=============== */ } IMPLEMENT_TEST_MAIN("ChunkData Creatable", Test() ); ================================================ FILE: tests/CompositeChat/CMakeLists.txt ================================================ include_directories(${CMAKE_CURRENT_SOURCE_DIR}) include_directories(${PROJECT_SOURCE_DIR}/src/) include_directories(${PROJECT_SOURCE_DIR}/lib/jsoncpp/include) set (SHARED_SRCS ${PROJECT_SOURCE_DIR}/src/CompositeChat.cpp ${PROJECT_SOURCE_DIR}/src/JsonUtils.cpp ${PROJECT_SOURCE_DIR}/src/StringUtils.cpp ) set (SHARED_HDRS ../TestHelpers.h ${PROJECT_SOURCE_DIR}/src/CompositeChat.h ${PROJECT_SOURCE_DIR}/src/JsonUtils.h ${PROJECT_SOURCE_DIR}/src/StringUtils.h ) set (SRCS CompositeChatTest.cpp ClientHandle.cpp ) source_group("Shared" FILES ${SHARED_SRCS} ${SHARED_HDRS}) source_group("Sources" FILES ${SRCS}) add_executable(CompositeChat-exe ${SRCS} ${SHARED_SRCS} ${SHARED_HDRS}) target_link_libraries(CompositeChat-exe jsoncpp_static fmt::fmt) if (WIN32) target_link_libraries(CompositeChat-exe ws2_32) endif() add_test(NAME CompositeChat-test COMMAND CompositeChat-exe) # Put the projects into solution folders (MSVC): set_target_properties( CompositeChat-exe PROPERTIES FOLDER Tests ) ================================================ FILE: tests/CompositeChat/ClientHandle.cpp ================================================ // ClientHandle.cpp // Mocks the cClientHandle class used by the tests #include "Globals.h" #include "ClientHandle.h" AString cClientHandle::FormatMessageType(bool a_ShouldShowPrefixes, eMessageType a_MsgType, const AString & a_AdditionalData) { return ""; } ================================================ FILE: tests/CompositeChat/CompositeChatTest.cpp ================================================ // CompositeChatTest.cpp // Implements the main app entrypoint for the cCompositeChat class test #include "Globals.h" #include "../TestHelpers.h" #include "CompositeChat.h" static void TestParser1(void) { cCompositeChat Msg; Msg.ParseText("Testing &2color codes and http://links parser"); const auto & Parts = Msg.GetParts(); TEST_EQUAL(Parts.size(), 4); TEST_TRUE(std::holds_alternative(Parts[0])); TEST_EQUAL(std::get(Parts[0]).Style, ""); TEST_TRUE(std::holds_alternative(Parts[1])); TEST_EQUAL(std::get(Parts[1]).Style, "2"); TEST_TRUE(std::holds_alternative(Parts[2])); TEST_EQUAL(std::get(Parts[2]).Style, "2"); TEST_TRUE(std::holds_alternative(Parts[3])); TEST_EQUAL(std::get(Parts[3]).Style, "2"); } static void TestParser2(void) { cCompositeChat Msg; Msg.ParseText("&3Advanced stuff: &5overriding color codes and http://links.with/&4color-in-them handling"); const auto & Parts = Msg.GetParts(); TEST_EQUAL(Parts.size(), 4); TEST_TRUE(std::holds_alternative(Parts[0])); TEST_EQUAL(std::get(Parts[0]).Style, "3"); TEST_TRUE(std::holds_alternative(Parts[1])); TEST_EQUAL(std::get(Parts[1]).Style, "35"); TEST_TRUE(std::holds_alternative(Parts[2])); TEST_EQUAL(std::get(Parts[2]).Style, "35"); TEST_TRUE(std::holds_alternative(Parts[3])); TEST_EQUAL(std::get(Parts[3]).Style, "35"); } static void TestParser3(void) { cCompositeChat Msg; Msg.ParseText("http://links.starting the text"); const auto & Parts = Msg.GetParts(); TEST_EQUAL(Parts.size(), 2); TEST_TRUE(std::holds_alternative(Parts[0])); TEST_EQUAL(std::get(Parts[0]).Style, ""); TEST_TRUE(std::holds_alternative(Parts[1])); TEST_EQUAL(std::get(Parts[1]).Style, ""); } static void TestParser4(void) { cCompositeChat Msg; Msg.ParseText("links finishing the text: http://some.server"); const auto & Parts = Msg.GetParts(); TEST_EQUAL(Parts.size(), 2); TEST_TRUE(std::holds_alternative(Parts[0])); TEST_EQUAL(std::get(Parts[0]).Style, ""); TEST_TRUE(std::holds_alternative(Parts[1])); TEST_EQUAL(std::get(Parts[1]).Style, ""); } static void TestParser5(void) { cCompositeChat Msg; Msg.ParseText("http://only.links"); const auto & Parts = Msg.GetParts(); TEST_EQUAL(Parts.size(), 1); TEST_TRUE(std::holds_alternative(Parts[0])); TEST_EQUAL(std::get(Parts[0]).Style, ""); } static void TestParser6(void) { cCompositeChat Msg; Msg.ParseText("Hello World"); const auto & Parts = Msg.GetParts(); TEST_EQUAL(Parts.size(), 1); TEST_TRUE(std::holds_alternative(Parts[0])); TEST_EQUAL(std::get(Parts[0]).Style, ""); } IMPLEMENT_TEST_MAIN("CompositeChat", TestParser1(); TestParser2(); TestParser3(); TestParser4(); TestParser5(); TestParser6(); ) ================================================ FILE: tests/ConsoleColors/ConsoleColors.cpp ================================================ // ConsoleColors.cpp // Tests the various console color combinations #include #include /// Evaluates to the number of elements in an array (compile-time!) #define ARRAYCOUNT(X) (sizeof(X) / sizeof(*(X))) int main(void) { static const char * Attribs[] = { "0", // All attribs off "1", // bold "2", // faint "7", // inverse "1;7", // bold inverse "2;7", // faint inverse } ; for (int i = 0; i < ARRAYCOUNT(Attribs); i++) { const char * Attrib = Attribs[i]; for (int fg = 30; fg <= 37; fg++) { for (int bg = 40; bg <= 47; bg++) { printf("\x1b[%s;%d;%dm %s;%d;%d ", Attrib, fg, bg, Attrib, fg, bg); } // for bg puts("\x1b[0m"); // Reset terminal back to normal colors for the newline } // for fg } // for i - Attribs[] for (int i = 1; i < ARRAYCOUNT(Attribs); i++) { const char * Attrib = Attribs[i]; for (int fg = 30; fg <= 37; fg++) { for (int bg = 40; bg <= 47; bg++) { printf("\x1b[%d;%d;%sm %d;%d;%s ", fg, bg, Attrib, fg, bg, Attrib); } // for bg puts("\x1b[0m"); // Reset terminal back to normal colors for the newline } // for fg } // for i - Attribs[] return 0; } ================================================ FILE: tests/FastRandom/CMakeLists.txt ================================================ include_directories(${PROJECT_SOURCE_DIR}/src/) set (SHARED_SRCS ${PROJECT_SOURCE_DIR}/src/FastRandom.cpp ${PROJECT_SOURCE_DIR}/src/StringUtils.cpp ) set (SHARED_HDRS ../TestHelpers.h ${PROJECT_SOURCE_DIR}/src/FastRandom.h ${PROJECT_SOURCE_DIR}/src/StringUtils.h ) set (SRCS FastRandomTest.cpp ) source_group("Shared" FILES ${SHARED_SRCS} ${SHARED_HDRS}) source_group("Sources" FILES ${SRCS}) add_executable(FastRandom-exe ${SRCS} ${SHARED_SRCS} ${SHARED_HDRS}) target_link_libraries(FastRandom-exe fmt::fmt) if (WIN32) target_link_libraries(FastRandom-exe ws2_32) endif() add_test(NAME FastRandom-test COMMAND FastRandom-exe) # Put the projects into solution folders (MSVC): set_target_properties( FastRandom-exe PROPERTIES FOLDER Tests ) ================================================ FILE: tests/FastRandom/FastRandomTest.cpp ================================================ // FastRandomTest.cpp // Tests the randomness of cFastRandom #include "Globals.h" #include "../TestHelpers.h" #include "FastRandom.h" static void TestInts(void) { cFastRandom rnd; int sum = 0; const int BUCKETS = 8; int Counts[BUCKETS] = {0}; const int ITER = 10000; for (int i = 0; i < ITER; i++) { int v = rnd.RandInt(1000); TEST_GREATER_THAN_OR_EQUAL(v, 0); TEST_LESS_THAN_OR_EQUAL(v, 1000); Counts[v % BUCKETS]++; sum += v; } double avg = static_cast(sum) / ITER; LOG("avg: %f", avg); for (int i = 0; i < BUCKETS; i++) { LOG(" bucket %d: %d", i, Counts[i]); } } static void TestFloats(void) { cFastRandom rnd; float sum = 0; const int BUCKETS = 8; int Counts[BUCKETS] = {0}; const int ITER = 10000; for (int i = 0; i < ITER; i++) { float v = rnd.RandReal(1000.0f); TEST_GREATER_THAN_OR_EQUAL(v, 0); TEST_LESS_THAN_OR_EQUAL(v, 1000); Counts[static_cast(v) % BUCKETS]++; sum += v; } sum = sum / ITER; LOG("avg: %f", sum); for (int i = 0; i < BUCKETS; i++) { LOG(" bucket %d: %d", i, Counts[i]); } } /** Checks whether re-creating the cFastRandom class produces the same initial number over and over (#2935) */ static void TestReCreation(void) { const int ITER = 10000; int lastVal = 0; int numSame = 0; int maxNumSame = 0; for (int i = 0; i < ITER; ++i) { cFastRandom rnd; int val = rnd.RandInt(9); if (val == lastVal) { numSame += 1; } else { if (numSame > maxNumSame) { maxNumSame = numSame; } numSame = 0; lastVal = val; } } if (numSame > maxNumSame) { maxNumSame = numSame; } LOG("Out of %d creations, there was a chain of at most %d same numbers generated.", ITER, maxNumSame); } IMPLEMENT_TEST_MAIN("FastRandom", TestInts(); TestFloats(); TestReCreation(); ) ================================================ FILE: tests/Generating/BasicGeneratorTest.cpp ================================================ #include "Globals.h" #include "Generating/ChunkGenerator.h" #include "Generating/ChunkDesc.h" #include "../TestHelpers.h" #include "IniFile.h" #include "mbedTLS++/Sha1Checksum.h" /** Checks that the chunk's heightmap corresponds to the chunk contents. */ static void verifyChunkDescHeightmap(const cChunkDesc & a_ChunkDesc) { for (int x = 0; x < cChunkDef::Width; x++) { for (int z = 0; z < cChunkDef::Width; z++) { for (int y = cChunkDef::Height - 1; y > 0; y--) { BLOCKTYPE BlockType = a_ChunkDesc.GetBlockType(x, y, z); if (BlockType != E_BLOCK_AIR) { int Height = a_ChunkDesc.GetHeight(x, z); TEST_EQUAL_MSG(Height, y, fmt::format(FMT_STRING("Chunk height at <{}, {}>: exp {}, got {}"), x, z, y, Height)); break; } } // for y } // for z } // for x } static AString chunkSHA1(const cChunkDesc & a_ChunkDesc) { cSha1Checksum cs; cs.Update(a_ChunkDesc.GetBlockTypes(), cChunkDef::Width * cChunkDef::Width * cChunkDef::Height); cSha1Checksum::Checksum digest; cs.Finalize(digest); AString res; cSha1Checksum::DigestToJava(digest, res); return res; } /** Prints out the entire column from the chunk, one block type per line. */ static void printChunkColumn(const cChunkDesc & a_ChunkDesc, int a_X, int a_Z) { auto prevBlockType = a_ChunkDesc.GetBlockType(a_X, cChunkDef::Height - 1, a_Z); int count = 1; LOG("Column {%d, %d}:", a_X, a_Z); LOG("Yfrom\tYto\tcnt\ttype\ttypeStr"); for (int y = cChunkDef::Height - 2; y >= 0; --y) { auto blockType = a_ChunkDesc.GetBlockType(a_X, y, a_Z); if (blockType != prevBlockType) { LOG("%d\t%d\t%d\t%d\t%s", y + 1, y + count, count, prevBlockType, ItemTypeToString(prevBlockType)); prevBlockType = blockType; count = 1; } else { count += 1; } } LOG("%d\t%d\t%d\t%s", 0, count, prevBlockType, ItemTypeToString(prevBlockType)); } /** Tests that the default Overworld generator generates a few chunks that have the Overworld look: - bedrock at their bottom - a valid overworld block at their height's top - air at their top, unless the height at that point is equal to full chunk height. - valid heightmap Multiple chunks are tested. */ static void testGenerateOverworld(cChunkGenerator & aDefaultOverworldGen) { LOG("Testing Overworld generator..."); for (int chunkX = 0; chunkX < 50; ++chunkX) { // Generate a chunk: cChunkDesc chd({chunkX, 0}); aDefaultOverworldGen.Generate(chd); verifyChunkDescHeightmap(chd); // Check that it has bedrock at the bottom: for (int x = 0; x < cChunkDef::Width; ++x) { for (int z = 0; z < cChunkDef::Width; ++z) { TEST_EQUAL_MSG(chd.GetBlockType(x, 0, z), E_BLOCK_BEDROCK, fmt::format(FMT_STRING("Bedrock floor at {{{}, {}, {}}}"), x, 0, z)); } } // Check that the blocks on the top are valid Overworld blocks: static std::set validOverworldBlockTypes = { E_BLOCK_STONE, E_BLOCK_GRASS, E_BLOCK_WATER, E_BLOCK_STATIONARY_WATER, E_BLOCK_LAVA, E_BLOCK_STATIONARY_LAVA, E_BLOCK_SAND, E_BLOCK_GRAVEL, E_BLOCK_LEAVES, E_BLOCK_NEW_LEAVES, }; for (int x = 0; x < cChunkDef::Width; ++x) { for (int z = 0; z < cChunkDef::Width; ++z) { auto y = chd.GetHeight(x, z); auto blockType = chd.GetBlockType(x, y, z); TEST_EQUAL_MSG(validOverworldBlockTypes.count(blockType), 1, fmt::format(FMT_STRING("Block at {{{}, {}, {}}}: {}"), x, y, z, blockType) ); if (y < cChunkDef::Height - 1) { TEST_EQUAL_MSG(chd.GetBlockType(x, cChunkDef::Height - 1, z), E_BLOCK_AIR, fmt::format(FMT_STRING("Air at {{{}, {}, {}}}"), x, cChunkDef::Height - 1, z) ); } } } } } /** Tests that the default Nether generator generates a chunk that has the Nether look: - bedrock at the bottom - bedrock at the height's top - at least one Nether-native block in each column - valid heightmap Multiple chunks are tested. */ static void testGenerateNether(cChunkGenerator & aDefaultNetherGen) { LOG("Testing Nether generator..."); for (int chunkX = 0; chunkX < 50; ++chunkX) { // Generate a chunk: cChunkDesc chd({chunkX, 0}); aDefaultNetherGen.Generate(chd); verifyChunkDescHeightmap(chd); // Check that the biome is Nether everywhere: for (int x = 0; x < cChunkDef::Width; ++x) { for (int z = 0; z < cChunkDef::Width; ++z) { TEST_EQUAL_MSG(chd.GetBiome(x, z), biNether, fmt::format(FMT_STRING("Nether biome at <{}, {}>"), x, z)); } } // Check that it has bedrock at the bottom and height: int prevHeight = chd.GetHeight(0, 0); for (int x = 0; x < cChunkDef::Width; ++x) { for (int z = 0; z < cChunkDef::Width; ++z) { TEST_EQUAL_MSG(chd.GetBlockType(x, 0, z), E_BLOCK_BEDROCK, fmt::format(FMT_STRING("Bedrock floor at {{{}, {}, {}}}"), x, 0, z)); auto y = chd.GetHeight(x, z); auto topBlockType = chd.GetBlockType(x, y, z); // Skip the mushrooms generated on the top bedrock layer: if ( (topBlockType == E_BLOCK_BROWN_MUSHROOM) || (topBlockType == E_BLOCK_RED_MUSHROOM) ) { y -= 1; } TEST_EQUAL_MSG(y, prevHeight, fmt::format( FMT_STRING("Failed: Same height across the entire chunk, at <{}, {}>: exp {}, got {}; top block: {}"), x, z, prevHeight, y, chd.GetBlockType(x, y, z) )); auto blockType = chd.GetBlockType(x, y, z); TEST_EQUAL_MSG(blockType, E_BLOCK_BEDROCK, fmt::format(FMT_STRING("Bedrock ceiling at {{{}, {}, {}}}: {}"), x, y, z, blockType) ); } } // Check that each column contains at least one Nether-native block: for (int x = 0; x < cChunkDef::Width; ++x) { for (int z = 0; z < cChunkDef::Width; ++z) { bool hasSuitableBlockType = false; for (int y = chd.GetHeight(x, z); y > 0; --y) { switch (chd.GetBlockType(x, y, z)) { case E_BLOCK_NETHERRACK: case E_BLOCK_NETHER_QUARTZ_ORE: case E_BLOCK_LAVA: case E_BLOCK_STATIONARY_LAVA: case E_BLOCK_SOULSAND: { hasSuitableBlockType = true; break; } } } // for y if (!hasSuitableBlockType) { printChunkColumn(chd, x, z); TEST_FAIL(fmt::format(FMT_STRING("!hasSuitableBlockType at column <{}, {}> of chunk [{}, 0]"), x, z, chunkX)); } } } } } /** Storage for checksums with chunk coords. */ struct CoordsWithChecksum { cChunkCoords mCoords; AString mChecksum; CoordsWithChecksum(int aChunkX, int aChunkZ, const AString & aChecksum): mCoords(aChunkX, aChunkZ), mChecksum(aChecksum) {} }; /** Checks that the specified generator generates chunk that match the specified checksums. */ static void checkChunkChecksums( cChunkGenerator & aGenerator, const std::vector & aCoordsWithChecksum, const AString & aDimension ) { LOG("Testing the repeatability of the %s generator", aDimension); for (const auto & coords: aCoordsWithChecksum) { cChunkDesc chd(coords.mCoords); aGenerator.Generate(chd); /* cFile f(Printf("Repeatability_%s-%02d-%02d.raw", aDimension, coords.mCoords.m_ChunkX, coords.mCoords.m_ChunkZ), cFile::fmWrite); f.Write(chd.GetBlockTypes(), sizeof(chd.GetBlockTypes())); f.Close(); */ auto checksum = chunkSHA1(chd); TEST_EQUAL_MSG(checksum, coords.mChecksum, fmt::format(FMT_STRING("{} chunk {} SHA1: expected {}, got {}"), aDimension, coords.mCoords.ToString(), coords.mChecksum, checksum) ); } } /** Checks that the generated chunks look the same across all builds on all platforms. This is done by SHA1-ing the blocks for known chunks and comparing against known values. If the generator defaults change, this test will likely break, just update the SHA1s. */ static void testRepeatability(cChunkGenerator & aDefaultOverworldGenerator, cChunkGenerator & aDefaultNetherGenerator) { // Test the default Overworld generator: std::vector overworldChecksums = { {0, 0, "-380dace6af9e653a2c68a51779cf5b8ff521cde1"}, {1, 0, "-651dfec5a64b7adccf6bf2845396e27f53c6c4c0"}, {1, 1, "-621454452edeb0ac369fea520fee3d80a5ecae49"}, {8, 1024, "5ed38ba7ffee6b29f774ad24820ad3ca1ff058bf"}, }; checkChunkChecksums(aDefaultOverworldGenerator, overworldChecksums, "Overworld"); // Test the default Nether generator: std::vector netherChecksums = { { 0, 0, "-487001a1ada9cdd7c8b557d3ff7081881f57c660"}, { 1, 0, "a074ac7a1f2fbf4173324e5edd792197d6a29c2"}, { 1, 1, "5867c5121f2a259ebc2aa53ecafed93dd3d6de95"}, {17, 0, "-300191cee5b30592f7b61cd22ea08669eba3f569"}, { 8, 1024, "69bbda09be981f5e3adc53d0a49995aff43f1290"}, }; checkChunkChecksums(aDefaultNetherGenerator, netherChecksums, "Nether"); } IMPLEMENT_TEST_MAIN("BasicGeneratorTest", // Create a default Overworld generator: cIniFile iniOverworld; iniOverworld.AddValue("General", "Dimension", "Overworld"); iniOverworld.AddValueI("Seed", "Seed", 1); iniOverworld.AddValue("Generator", "Finishers", ""); // Use no finishers, so that we don't have to check too many blocktypes auto defaultOverworldGen = cChunkGenerator::CreateFromIniFile(iniOverworld); TEST_NOTEQUAL(defaultOverworldGen, nullptr); // Create a default Nether generator: cIniFile iniNether; iniNether.AddValue("General", "Dimension", "Nether"); iniNether.AddValueI("Seed", "Seed", 1); auto defaultNetherGen = cChunkGenerator::CreateFromIniFile(iniNether); TEST_NOTEQUAL(defaultNetherGen, nullptr); // Run the tests on the generators: testGenerateOverworld(*defaultOverworldGen); testGenerateNether(*defaultNetherGen); testRepeatability(*defaultOverworldGen, *defaultNetherGen); ) ================================================ FILE: tests/Generating/Bindings.h ================================================ // Bindings.h // Dummy include file needed for LuaState to compile successfully struct lua_State; int tolua_AllToLua_open(lua_State * a_LuaState); ================================================ FILE: tests/Generating/CMakeLists.txt ================================================ include_directories(${PROJECT_SOURCE_DIR}/src/) include_directories(SYSTEM ${PROJECT_SOURCE_DIR}/lib/) include_directories(SYSTEM ${PROJECT_SOURCE_DIR}/lib/mbedtls/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}) set (SHARED_SRCS ${PROJECT_SOURCE_DIR}/src/BiomeDef.cpp ${PROJECT_SOURCE_DIR}/src/BlockArea.cpp ${PROJECT_SOURCE_DIR}/src/BlockInfo.cpp ${PROJECT_SOURCE_DIR}/src/BlockType.cpp ${PROJECT_SOURCE_DIR}/src/Cuboid.cpp ${PROJECT_SOURCE_DIR}/src/ChunkData.cpp ${PROJECT_SOURCE_DIR}/src/Defines.cpp ${PROJECT_SOURCE_DIR}/src/Enchantments.cpp ${PROJECT_SOURCE_DIR}/src/FastRandom.cpp ${PROJECT_SOURCE_DIR}/src/IniFile.cpp ${PROJECT_SOURCE_DIR}/src/ProbabDistrib.cpp ${PROJECT_SOURCE_DIR}/src/StringCompression.cpp ${PROJECT_SOURCE_DIR}/src/StringUtils.cpp ${PROJECT_SOURCE_DIR}/src/VoronoiMap.cpp ${PROJECT_SOURCE_DIR}/src/Bindings/LuaState.cpp # Needed for PrefabPiecePool loading ${PROJECT_SOURCE_DIR}/src/Noise/Noise.cpp ${PROJECT_SOURCE_DIR}/src/OSSupport/CriticalSection.cpp # Needed for LuaState ${PROJECT_SOURCE_DIR}/src/OSSupport/File.cpp ${PROJECT_SOURCE_DIR}/src/OSSupport/GZipFile.cpp ${PROJECT_SOURCE_DIR}/src/OSSupport/StackTrace.cpp ${PROJECT_SOURCE_DIR}/src/OSSupport/WinStackWalker.cpp ${PROJECT_SOURCE_DIR}/src/WorldStorage/FastNBT.cpp ${PROJECT_SOURCE_DIR}/src/WorldStorage/SchematicFileSerializer.cpp ) set (GENERATING_SRCS ${PROJECT_SOURCE_DIR}/src/Generating/BioGen.cpp ${PROJECT_SOURCE_DIR}/src/Generating/Caves.cpp ${PROJECT_SOURCE_DIR}/src/Generating/ChunkDesc.cpp ${PROJECT_SOURCE_DIR}/src/Generating/ChunkGenerator.cpp ${PROJECT_SOURCE_DIR}/src/Generating/CompoGen.cpp ${PROJECT_SOURCE_DIR}/src/Generating/CompoGenBiomal.cpp ${PROJECT_SOURCE_DIR}/src/Generating/ComposableGenerator.cpp ${PROJECT_SOURCE_DIR}/src/Generating/DistortedHeightmap.cpp ${PROJECT_SOURCE_DIR}/src/Generating/DungeonRoomsFinisher.cpp ${PROJECT_SOURCE_DIR}/src/Generating/EndGen.cpp ${PROJECT_SOURCE_DIR}/src/Generating/EnderDragonFightStructuresGen.cpp ${PROJECT_SOURCE_DIR}/src/Generating/FinishGen.cpp ${PROJECT_SOURCE_DIR}/src/Generating/GridStructGen.cpp ${PROJECT_SOURCE_DIR}/src/Generating/HeiGen.cpp ${PROJECT_SOURCE_DIR}/src/Generating/MineShafts.cpp ${PROJECT_SOURCE_DIR}/src/Generating/Noise3DGenerator.cpp ${PROJECT_SOURCE_DIR}/src/Generating/PieceGeneratorBFSTree.cpp ${PROJECT_SOURCE_DIR}/src/Generating/PieceModifier.cpp ${PROJECT_SOURCE_DIR}/src/Generating/PiecePool.cpp ${PROJECT_SOURCE_DIR}/src/Generating/PieceStructuresGen.cpp ${PROJECT_SOURCE_DIR}/src/Generating/Prefab.cpp ${PROJECT_SOURCE_DIR}/src/Generating/PrefabPiecePool.cpp ${PROJECT_SOURCE_DIR}/src/Generating/PrefabStructure.cpp ${PROJECT_SOURCE_DIR}/src/Generating/Ravines.cpp ${PROJECT_SOURCE_DIR}/src/Generating/RoughRavines.cpp ${PROJECT_SOURCE_DIR}/src/Generating/SinglePieceStructuresGen.cpp ${PROJECT_SOURCE_DIR}/src/Generating/StructGen.cpp ${PROJECT_SOURCE_DIR}/src/Generating/Trees.cpp ${PROJECT_SOURCE_DIR}/src/Generating/TwoHeights.cpp ${PROJECT_SOURCE_DIR}/src/Generating/VerticalLimit.cpp ${PROJECT_SOURCE_DIR}/src/Generating/VerticalStrategy.cpp ${PROJECT_SOURCE_DIR}/src/Generating/VillageGen.cpp ) set (SHARED_HDRS ${PROJECT_SOURCE_DIR}/src/BiomeDef.h ${PROJECT_SOURCE_DIR}/src/BlockArea.h ${PROJECT_SOURCE_DIR}/src/BlockInfo.h ${PROJECT_SOURCE_DIR}/src/BlockType.h ${PROJECT_SOURCE_DIR}/src/Cuboid.h ${PROJECT_SOURCE_DIR}/src/ChunkData.h ${PROJECT_SOURCE_DIR}/src/ChunkDef.h ${PROJECT_SOURCE_DIR}/src/Defines.h ${PROJECT_SOURCE_DIR}/src/Enchantments.h ${PROJECT_SOURCE_DIR}/src/FastRandom.h ${PROJECT_SOURCE_DIR}/src/Globals.h ${PROJECT_SOURCE_DIR}/src/IniFile.h ${PROJECT_SOURCE_DIR}/src/ProbabDistrib.h ${PROJECT_SOURCE_DIR}/src/StringCompression.h ${PROJECT_SOURCE_DIR}/src/StringUtils.h ${PROJECT_SOURCE_DIR}/src/VoronoiMap.h ${PROJECT_SOURCE_DIR}/src/Bindings/LuaState.h ${PROJECT_SOURCE_DIR}/src/Noise/Noise.h ${PROJECT_SOURCE_DIR}/src/OSSupport/CriticalSection.h ${PROJECT_SOURCE_DIR}/src/OSSupport/Event.h ${PROJECT_SOURCE_DIR}/src/OSSupport/File.h ${PROJECT_SOURCE_DIR}/src/OSSupport/GZipFile.h ${PROJECT_SOURCE_DIR}/src/OSSupport/StackTrace.h ${PROJECT_SOURCE_DIR}/src/OSSupport/WinStackWalker.h ${PROJECT_SOURCE_DIR}/src/WorldStorage/FastNBT.h ${PROJECT_SOURCE_DIR}/src/WorldStorage/SchematicFileSerializer.h ) set (GENERATING_HDRS ${PROJECT_SOURCE_DIR}/src/Generating/BioGen.h ${PROJECT_SOURCE_DIR}/src/Generating/Caves.h ${PROJECT_SOURCE_DIR}/src/Generating/ChunkDesc.h ${PROJECT_SOURCE_DIR}/src/Generating/ChunkGenerator.h ${PROJECT_SOURCE_DIR}/src/Generating/CompoGen.h ${PROJECT_SOURCE_DIR}/src/Generating/CompoGenBiomal.h ${PROJECT_SOURCE_DIR}/src/Generating/ComposableGenerator.h ${PROJECT_SOURCE_DIR}/src/Generating/CompositedHeiGen.h ${PROJECT_SOURCE_DIR}/src/Generating/DistortedHeightmap.h ${PROJECT_SOURCE_DIR}/src/Generating/DungeonRoomsFinisher.h ${PROJECT_SOURCE_DIR}/src/Generating/EndGen.h ${PROJECT_SOURCE_DIR}/src/Generating/FinishGen.h ${PROJECT_SOURCE_DIR}/src/Generating/GridStructGen.h ${PROJECT_SOURCE_DIR}/src/Generating/HeiGen.h ${PROJECT_SOURCE_DIR}/src/Generating/IntGen.h ${PROJECT_SOURCE_DIR}/src/Generating/MineShafts.h ${PROJECT_SOURCE_DIR}/src/Generating/Noise3DGenerator.h ${PROJECT_SOURCE_DIR}/src/Generating/PieceGeneratorBFSTree.h ${PROJECT_SOURCE_DIR}/src/Generating/PieceModifier.h ${PROJECT_SOURCE_DIR}/src/Generating/PiecePool.h ${PROJECT_SOURCE_DIR}/src/Generating/PieceStructuresGen.h ${PROJECT_SOURCE_DIR}/src/Generating/Prefab.h ${PROJECT_SOURCE_DIR}/src/Generating/PrefabPiecePool.h ${PROJECT_SOURCE_DIR}/src/Generating/PrefabStructure.h ${PROJECT_SOURCE_DIR}/src/Generating/ProtIntGen.h ${PROJECT_SOURCE_DIR}/src/Generating/Ravines.h ${PROJECT_SOURCE_DIR}/src/Generating/RoughRavines.h ${PROJECT_SOURCE_DIR}/src/Generating/ShapeGen.cpp ${PROJECT_SOURCE_DIR}/src/Generating/SinglePieceStructuresGen.h ${PROJECT_SOURCE_DIR}/src/Generating/StructGen.h ${PROJECT_SOURCE_DIR}/src/Generating/Trees.h ${PROJECT_SOURCE_DIR}/src/Generating/TwoHeights.h ${PROJECT_SOURCE_DIR}/src/Generating/VerticalLimit.h ${PROJECT_SOURCE_DIR}/src/Generating/VerticalStrategy.h ${PROJECT_SOURCE_DIR}/src/Generating/VillageGen.h ) set (STUBS Stubs.cpp LuaState_Typedefs.inc LuaState_Declaration.inc Bindings.h ) if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") add_compile_options("-Wno-error=global-constructors") add_compile_options("-Wno-error=switch-enum") endif() add_library(GeneratorTestingSupport STATIC ${SHARED_SRCS} ${SHARED_HDRS} ${GENERATING_SRCS} ${GENERATING_HDRS} ${STUBS} ) target_link_libraries(GeneratorTestingSupport fmt::fmt jsoncpp_static libdeflate lsqlite luaexpat tolualib) source_group("Stubs" FILES ${STUBS}) source_group("Generating" FILES ${GENERATING_HDRS} ${GENERATING_SRCS}) # BasicGeneratingTest: add_executable(BasicGeneratorTest BasicGeneratorTest.cpp ${PROJECT_SOURCE_DIR}/src/IniFile.cpp ${PROJECT_SOURCE_DIR}/src/mbedTLS++/Sha1Checksum.cpp ) target_link_libraries(BasicGeneratorTest GeneratorTestingSupport mbedtls) file(COPY "${PROJECT_SOURCE_DIR}/Server/items.ini" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}") add_test( NAME BasicGeneratorTest COMMAND BasicGeneratorTest ) # LoadablePieces test: source_group("Data files" FILES Test.cubeset Test1.schematic) add_executable(LoadablePieces LoadablePieces.cpp Test.cubeset Test1.schematic ) target_link_libraries(LoadablePieces GeneratorTestingSupport) if (WIN32) target_link_libraries(LoadablePieces ws2_32) endif() add_test( NAME LoadablePieces-test WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMAND LoadablePieces ) # PieceRotation test: add_executable(PieceRotation PieceRotationTest.cpp ) target_link_libraries(PieceRotation GeneratorTestingSupport mbedtls) if (WIN32) target_link_libraries(PieceRotation ws2_32) endif() add_test( NAME PieceRotation-test WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMAND PieceRotation ) # PieceGeneratorBFSTree test: add_executable(PieceGeneratorBFSTree PieceGeneratorBFSTreeTest.cpp ) target_link_libraries(PieceGeneratorBFSTree GeneratorTestingSupport mbedtls) if (WIN32) target_link_libraries(PieceGeneratorBFSTree ws2_32) endif() add_test( NAME PieceGeneratorBFSTree-test WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/Server/Prefabs/PieceStructures COMMAND PieceGeneratorBFSTree ) # Put the projects into solution folders (MSVC): set_target_properties( BasicGeneratorTest GeneratorTestingSupport LoadablePieces PieceGeneratorBFSTree PieceRotation PROPERTIES FOLDER Tests/Generating ) ================================================ FILE: tests/Generating/LoadablePieces.cpp ================================================ // LoadablePieces.cpp // Implements the LoadablePieces test main entrypoint #include "Globals.h" #ifdef _WIN32 #include #define GetCurrentFolder _getcwd #else #include #define GetCurrentFolder getcwd #endif #include "../TestHelpers.h" #include "Generating/PrefabPiecePool.h" static int DoLoaderTest(void) { cPrefabPiecePool test; auto res = test.LoadFromFile("Test.cubeset", true); if (!res) { LOGWARNING("Loading from file \"Test.cubeset\" failed."); return 1; } LOG("Loaded %u regular pieces and %u starting pieces", static_cast(test.GetAllPiecesCount()), static_cast(test.GetStartingPiecesCount())); // Check that we loaded all the pieces: TEST_EQUAL(test.GetAllPiecesCount(), 1); TEST_EQUAL(test.GetStartingPiecesCount(), 1); return 0; } static int DoParserTest(void) { // Create one static prefab to test the parser: static const cPrefab::sDef testPrefabDef = { // Size: 7, 6, 7, // SizeX = 7, SizeY = 6, SizeZ = 7 // Hitbox (relative to bounding box): 0, 0, 0, // MinX, MinY, MinZ 6, 5, 6, // MaxX, MaxY, MaxZ // Block definitions: ".: 0: 0\n" /* 0 */ "a:112: 0\n" /* netherbrick */ "b:113: 0\n" /* netherbrickfence */, // Block data: // Level 1 "aaaaaaa" "aaaaaaa" "aaaaaaa" "aaaaaaa" "aaaaaaa" "aaaaaaa" "aaaaaaa" // Level 2 "aa...aa" "a.....a" "......." "......." "......." "a.....a" "aa...aa" // Level 3 "aa...aa" "a.....a" "......." "......." "......." "a.....a" "aa...aa" // Level 4 "aa...aa" "a.....a" "......." "......." "......." "a.....a" "aa...aa" // Level 5 "aabbbaa" "a.....a" "b.....b" "b.....b" "b.....b" "a.....a" "aabbbaa" // Level 6 "aaaaaaa" "a.....a" "a.....a" "a.....a" "a.....a" "a.....a" "aaaaaaa", // Connections: "0: 0, 3, 2: 4\n" "0: 2, 3, 0: 2\n", // AllowedRotations: 7, /* 1, 2, 3 CCW rotations */ // Merge strategy: cBlockArea::msImprint, // ExtendFloorStrategy: cPrefab::efsNone, // DefaultWeight: 10, // DepthWeight: "", // AddWeightIfSame: 1000, // MoveToGround: false, }; cPrefab testPrefab(testPrefabDef); cPiece & prefabAsPiece(testPrefab); // GetConnectors() is private in cPrefab, need to cast to parent cPiece where it is public if (prefabAsPiece.GetConnectors().size() != 2) { LOGWARNING("Piece parsing failed, connectors not parsed properly. Expected 2 connectors, got %u", static_cast(prefabAsPiece.GetConnectors().size())); } return 0; } int main(int argc, char * argv[]) { LOGD("Test started"); // Print the current directory for reference: char folder[FILENAME_MAX]; GetCurrentFolder(folder, sizeof(folder)); LOG("Running cPrefabPiecePool test from folder \"%s\".", folder); // Run the Loader test: int res = DoLoaderTest(); LOG("cPrefabPiecePool loading test done: %s", (res == 0) ? "success" : "failure"); if (res != 0) { return res; } // Run the Parser test: res = DoParserTest(); LOG("cPrefab parser test done: %s", (res == 0) ? "success" : "failure"); return res; } ================================================ FILE: tests/Generating/LuaState_Declaration.inc ================================================ // LuaState_Declaration.inc // Dummy include file needed for LuaState to compile successfully bool GetStackValue(int, cUUID *&); ================================================ FILE: tests/Generating/LuaState_Typedefs.inc ================================================ // LuaState_Typedefs.inc // Dummy include file needed for LuaState to compile successfully // Forward-declare classes that are used in the API but never called: struct HTTPRequest; struct HTTPTemplateRequest; class cPluginLua; class cBoundingBox; template class cItemCallback; class cEntity; class cUUID; ================================================ FILE: tests/Generating/PieceGeneratorBFSTreeTest.cpp ================================================ // PieceGeneratorBFSTreeTest.cpp // Implements the test for the cPieceGeneratorBFSTree class /* Unlike most tests, this is actually not meant as much for unit-testing, but more like performance-testing. Compile this project in Release mode, then run it in folder that has NetherFort.cubeset prefabs, too, using a higher number of repetitions (each repetition takes time on the order of a second); investigate the runtime performance with a profiler. The syntax to execute this test: PieceGeneratorBFSTreeTest [] numRepetitions is the number of NetherFort structures to be generated (default = 1) */ #include "Globals.h" #include "Generating/PrefabPiecePool.h" #include "Generating/PieceGeneratorBFSTree.h" static int test(int a_NumRepetitions) { // Load the piece pool: cPrefabPiecePool pool; if (!pool.LoadFromFile("NetherFort.cubeset", true)) { LOGERROR("Cannot load the NetherFort cubeset. Please make sure that the NetherFort.cubeset file is present in the current dir and that it is a valid .cubeset file."); return -1; } auto & generatorParams = pool.GetAllMetadata(); auto maxDepth = GetStringMapInteger(generatorParams, "MaxDepth", 5); // Perform repeated test of the generator: auto start = std::chrono::high_resolution_clock::now(); cPieceGeneratorBFSTree pg(pool, 1); for (int i = 0; i < a_NumRepetitions; ++i) { cPlacedPieces placedPieces; pg.PlacePieces(i * 512, 0, maxDepth, placedPieces); placedPieces.clear(); } // for i - numRepetitions auto end = std::chrono::high_resolution_clock::now(); auto dur = std::chrono::duration_cast(end - start).count(); LOG("Performed %d repetition(s), took %.3f seconds", a_NumRepetitions, static_cast(dur) / 1000); return 0; } int main(int argc, char * argv[]) { LOGD("Starting the PieceGeneratorBFSTree test."); // Parse the cmdline parameters: int numRepetitions = 1; for (int i = 1; i < argc; ++i) { int rep = atoi(argv[i]); if (rep > 0) { numRepetitions = rep; } } LOGD("Performing %d repetitions", numRepetitions); auto res = test(numRepetitions); if (res != 0) { LOGD("Test failed."); return res; } LOGD("The PieceGeneratorBFSTree test competed successfully."); return 0; } ================================================ FILE: tests/Generating/PieceRotationTest.cpp ================================================ // PieceRotation.cpp // Implements the tests for cPiece::cConnector::eDirection rotations #include "Globals.h" #include #include #include "Generating/PiecePool.h" static cPiece::cConnector::eDirection g_AllDirections[] = { cPiece::cConnector::dirXM, cPiece::cConnector::dirXP, cPiece::cConnector::dirYM, cPiece::cConnector::dirYP, cPiece::cConnector::dirZM, cPiece::cConnector::dirZP, cPiece::cConnector::dirYM_XM_ZM, cPiece::cConnector::dirYM_XM_ZP, cPiece::cConnector::dirYM_XP_ZM, cPiece::cConnector::dirYM_XP_ZP, cPiece::cConnector::dirYP_XM_ZM, cPiece::cConnector::dirYP_XM_ZP, cPiece::cConnector::dirYP_XP_ZM, cPiece::cConnector::dirYP_XP_ZP, }; class cTestFailure: public std::exception { public: cTestFailure(const char * a_Expression, const char * a_FileName, const int a_Line): std::exception(), m_Expression(a_Expression), m_FileName(a_FileName), m_Line(a_Line) { } const std::string m_Expression; const std::string m_FileName; const int m_Line; }; #define EXPECT(X) \ do { \ if (!(X)) \ { \ ASSERT(X); \ throw cTestFailure(#X, __FILE__, __LINE__); \ } \ } while (false) /** Tests that rotating a direction in one way and then the opposite way produces the original direction. */ static void testBackAndForth() { for (size_t i = 0; i < ARRAYCOUNT(g_AllDirections); ++i) { auto rotated = cPiece::cConnector::RotateDirectionCW(g_AllDirections[i]); auto back = cPiece::cConnector::RotateDirectionCCW(rotated); EXPECT(back == g_AllDirections[i]); } for (size_t i = 0; i < ARRAYCOUNT(g_AllDirections); ++i) { auto rotated = cPiece::cConnector::RotateDirectionCCW(g_AllDirections[i]); auto back = cPiece::cConnector::RotateDirectionCW(rotated); EXPECT(back == g_AllDirections[i]); } } /** Tests rotating the direction 360 degrees. */ static void testFullRotation() { // Rotate 90 degrees CCW four times: for (size_t i = 0; i < ARRAYCOUNT(g_AllDirections); ++i) { auto d = g_AllDirections[i]; for (int j = 0; j < 4; ++j) { d = cPiece::cConnector::RotateDirectionCCW(d); } EXPECT(d == g_AllDirections[i]); } // Rotate 90 degrees CW four times: for (size_t i = 0; i < ARRAYCOUNT(g_AllDirections); ++i) { auto d = g_AllDirections[i]; for (int j = 0; j < 4; ++j) { d = cPiece::cConnector::RotateDirectionCW(d); } EXPECT(d == g_AllDirections[i]); } // Rotate 180 degrees twice: for (size_t i = 0; i < ARRAYCOUNT(g_AllDirections); ++i) { auto d = g_AllDirections[i]; d = cPiece::cConnector::RotateDirection(d); d = cPiece::cConnector::RotateDirection(d); EXPECT(d == g_AllDirections[i]); } } /** Tests that no two values are rotated onto the same destination value. */ template static void testPermutation(Fn & a_Fn) { std::map numDest; for (size_t i = 0; i < ARRAYCOUNT(g_AllDirections); ++i) { auto d = a_Fn(g_AllDirections[i]); EXPECT(numDest[d] == 0); numDest[d] = 1; } } int main(void) { LOG("PieceRotation test starting."); try { testBackAndForth(); testFullRotation(); testPermutation(cPiece::cConnector::RotateDirection); testPermutation(cPiece::cConnector::RotateDirectionCW); testPermutation(cPiece::cConnector::RotateDirectionCCW); } catch (const cTestFailure & f) { LOGERROR("Test failed:\tExpression: %s\n\tFile: %s (%d)", f.m_Expression.c_str(), f.m_FileName.c_str(), f.m_Line); return 1; } catch (const std::exception & exc) { LOGERROR("Exception caught: %s", exc.what()); return 2; } LOG("PieceRotation test succeeded."); return 0; } ================================================ FILE: tests/Generating/Stubs.cpp ================================================ // Stubs.cpp // Implements stubs of various Cuberite methods that are needed for linking but not for runtime // This is required so that we don't bring in the entire Cuberite via dependencies #include "Globals.h" #include "BlockInfo.h" #include "UUID.h" #include "Bindings.h" #include "Bindings/DeprecatedBindings.h" #include "Bindings/LuaJson.h" #include "Bindings/LuaState.h" #include "Bindings/ManualBindings.h" #include "BlockEntities/BlockEntity.h" #include "Blocks/BlockHandler.h" #include "Generating/ChunkDesc.h" #include "DeadlockDetect.h" #include "Entities/Entity.h" #include "Entities/EnderCrystal.h" #include "Mobs/Monster.h" #include "Mobs/EnderDragon.h" #include "Simulator/FluidSimulator.h" #include "Simulator/FireSimulator.h" #include "MobSpawner.h" #include "ItemGrid.h" // fwd: struct lua_State; // Prototypes, needed by clang: extern "C" int luaopen_lsqlite3(lua_State * a_LuaState); extern "C" int luaopen_lxp(lua_State * a_LuaState); void cManualBindings::Bind(lua_State * a_LuaState) { } void DeprecatedBindings::Bind(lua_State * a_LuaState) { } void cLuaJson::Bind(cLuaState & a_LuaState) { } int tolua_AllToLua_open(lua_State * a_LuaState) { return 0; } extern "C" int luaopen_lsqlite3(lua_State * a_LuaState) { return 0; } extern "C" int luaopen_lxp(lua_State * a_LuaState) { return 0; } cBoundingBox::cBoundingBox(double, double, double, double, double, double) { } cBoundingBox cBlockHandler::GetPlacementCollisionBox(BLOCKTYPE a_XM, BLOCKTYPE a_XP, BLOCKTYPE a_YM, BLOCKTYPE a_YP, BLOCKTYPE a_ZM, BLOCKTYPE a_ZP) const { return cBoundingBox(0, 0, 0, 0, 0, 0); } void cBlockHandler::OnUpdate(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cBlockPluginInterface & a_PluginInterface, cChunk & a_Chunk, const Vector3i a_RelPos) const { } void cBlockHandler::OnNeighborChanged(cChunkInterface & a_ChunkInterface, Vector3i a_BlockPos, eBlockFace a_WhichNeighbor) const { } void cBlockHandler::NeighborChanged(cChunkInterface & a_ChunkInterface, Vector3i a_BlockPos, eBlockFace a_WhichNeighbor) { } cItems cBlockHandler::ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const { return cItems(); } bool cBlockHandler::CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const { return true; } bool cBlockHandler::IsUseable() const { return false; } bool cBlockHandler::DoesIgnoreBuildCollision(const cWorld & a_World, const cItem & a_HeldItem, Vector3i a_Position, NIBBLETYPE a_Meta, eBlockFace a_ClickedBlockFace, bool a_ClickedDirectly) const { return m_BlockType == E_BLOCK_AIR; } void cBlockHandler::Check(cChunkInterface & a_ChunkInterface, cBlockPluginInterface & a_PluginInterface, Vector3i a_RelPos, cChunk & a_Chunk) const { } ColourID cBlockHandler::GetMapBaseColourID(NIBBLETYPE a_Meta) const { return 0; } bool cBlockHandler::IsInsideBlock(Vector3d a_Position, const NIBBLETYPE a_BlockMeta) const { return true; } const cBlockHandler & cBlockHandler::For(BLOCKTYPE a_BlockType) { // Dummy handler. static cBlockHandler Handler(E_BLOCK_AIR); return Handler; } OwnedBlockEntity cBlockEntity::CreateByBlockType(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World) { return nullptr; } void cDeadlockDetect::TrackCriticalSection(cCriticalSection & a_CS, const AString & a_Name) { } void cDeadlockDetect::UntrackCriticalSection(cCriticalSection & a_CS) { } void cBlockEntity::SetPos(Vector3i a_NewPos) { } bool cBlockEntity::IsBlockEntityBlockType(BLOCKTYPE a_BlockType) { return false; } OwnedBlockEntity cBlockEntity::Clone(Vector3i a_Pos) { return nullptr; } bool cLuaState::GetStackValue(int, cUUID *&) { return false; } bool cUUID::FromString(const AString&) { return false; } void cEntity::SetPosition(const Vector3d & a_Position) { } void cEntity::SetHealth(float a_NewHealth) { } cMonster::eFamily cMonster::FamilyFromType(eMonsterType a_Type) { return cMonster::mfAmbient; } std::unique_ptr cMonster::NewMonsterFromType(eMonsterType a_Type) { return nullptr; } void cMonster::CheckEventLostPlayer(std::chrono::milliseconds a_Dt) { } bool cFluidSimulator::CanWashAway(BLOCKTYPE a_BlockType) { return false; } bool cFireSimulator::DoesBurnForever(BLOCKTYPE a_BlockType) { return false; } void cItemGrid::GenerateRandomLootWithBooks(const cLootProbab * a_LootProbabs, size_t a_CountLootProbabs, int a_NumSlots, int a_Seed) { } std::set cMobSpawner::GetAllowedMobTypes(EMCSBiome a_Biome) { return {}; } cItem::cItem() { } cItem::cItem( short a_ItemType, char a_ItemCount, short a_ItemDamage, const AString & a_Enchantments, const AString & a_CustomName, const AStringVector & a_LoreTable ) { } void cItem::Empty() { } cEnderCrystal::cEnderCrystal(Vector3d a_Pos, bool a_ShowBottom): Super(etEnderCrystal, a_Pos, 1.0, 1.0) { } void cEnderCrystal::SpawnOn(class cClientHandle & a_ClientHandle) { } void cEnderCrystal::Tick(std::chrono::milliseconds a_Dt, class cChunk & a_Chunk) { } void cEnderCrystal::KilledBy(struct TakeDamageInfo & a_TakeDamageInfo) { } cEntity::cEntity(enum cEntity::eEntityType a_EntityType, class Vector3 a_Pos, float a_Height, float a_Width) { } bool cEntity::Initialize(class std::unique_ptr > a_Entity,class cWorld & a_World) { return true; } void cEntity::OnAddToWorld(class cWorld & a_World) { } void cEntity::OnRemoveFromWorld(class cWorld & a_World) { } bool cEntity::IsA(char const * a_Type)const { return true; } char const * cEntity::GetParentClass(void) const { return ""; } void cEntity::HandleSpeedFromAttachee(float a_SpeedX,float a_SpeedZ) { } void cEntity::Destroy(void) { } bool cEntity::DoTakeDamage(struct TakeDamageInfo & a_TakeDamageInfo) { return true; } int cEntity::GetRawDamageAgainst(class cEntity const & a_Entity) { return 0; } bool cEntity::ArmorCoversAgainst(enum eDamageType a_DamageType) { return true; } float cEntity::GetArmorCoverAgainst(class cEntity const * a_Entity,enum eDamageType a_DamageType,int a_Value) { return 0.0f; } char const * cEntity::GetClass(void) const { return ""; } float cEntity::GetEnchantmentCoverAgainst(class cEntity const * a_Entity,enum eDamageType a_DamageType,int a_Value) { return 0.0f; } float cEntity::GetEnchantmentBlastKnockbackReduction(void) { return 0.0f; } double cEntity::GetKnockbackAmountAgainst(class cEntity const & a_Entity) { return 0.0f; } void cEntity::ApplyArmorDamage(int) { } void cEntity::KilledBy(struct TakeDamageInfo & a_TakeDamageInfo) { } void cEntity::Heal(int a_Value) { } void cEntity::Tick(std::chrono::milliseconds a_Dt, class cChunk & a_Chunk) { } void cEntity::HandlePhysics(std::chrono::milliseconds a_Dt, class cChunk & a_Chunk) { } void cEntity::TickBurning(class cChunk & a_Chunk) { } void cEntity::DetectCacti(void) { } bool cEntity::DetectPortal(void) { return true; } void cEntity::TickInVoid(class cChunk & a_Chunk) { } void cEntity::OnStartedBurning(void) { } void cEntity::OnFinishedBurning(void) { } void cEntity::TeleportToEntity(class cEntity & a_Entity) { } void cEntity::TeleportToCoords(double a_XPos, double a_YPos, double a_ZPos) { } void cEntity::BroadcastMovementUpdate(class cClientHandle const * a_ClientHandle) { } void cEntity::AttachTo(class cEntity & a_Entity) { } void cEntity::Detach(void) { } void cEntity::SetSpeed(double a_XSpeed, double a_YSpeed, double a_ZSpeed) { } void cEntity::DetectMagma(void) { } bool cEntity::MoveToWorld(cWorld & a_World, Vector3d a_NewPosition, bool a_SetPortalCooldown, bool a_ShouldSendRespawn) { return false; } void cEntity::HandleAir(void) { } void cEntity::SetSwimState(class cChunk & a_Chunk) { } void cEntity::ResetPosition(class Vector3 a_Pos) { } void cEntity::OnDetach() { } cPawn::cPawn(enum cEntity::eEntityType, float a_Width, float a_Height) : cEntity(etMonster, Vector3d(), a_Height, a_Width) { } bool cPawn::IsFireproof(void) const { return true; } bool cPawn::IsInvisible(void) const { return true; } void cPawn::HandleAir(void) { } void cPawn::HandleFalling() { } void cPawn::KilledBy(struct TakeDamageInfo & a_TakeDamageInfo) { } void cPawn::OnRemoveFromWorld(cWorld & a_World) { } void cPawn::ResetPosition(class Vector3) { } void cPawn::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { } cMonster::cMonster(const AString & a_StringA, enum eMonsterType a_MonsterType, const AString & a_StringB, const AString & a_StringC, const AString & a_StringD, float a_Width, float a_Height) : cPawn(etMonster, a_Width, a_Height), m_PathFinder(a_Width, a_Height) { } cPathFinder::cPathFinder(float a_Width, float a_Height) { } void cMonster::OnRemoveFromWorld(class cWorld & a_World) { } void cMonster::Tick(std::chrono::milliseconds a_Dt, class cChunk & a_Chunk) { } void cMonster::EventSeePlayer(cPlayer * a_Player, cChunk & a_Chunk) { } void cMonster::InStateChasing(std::chrono::milliseconds a_Dt, class cChunk & a_Chunk) { } void cMonster::SpawnOn(class cClientHandle & a_ClientHandle) { } bool cMonster::DoTakeDamage(struct TakeDamageInfo & a_TakeDamageInfo) { return true; } void cMonster::KilledBy(struct TakeDamageInfo & a_TakeDamageInfo) { } void cMonster::OnRightClicked(class cPlayer & a_Player) { } void cMonster::HandleFalling(void) { } void cMonster::MoveToPosition(class Vector3 const & a_Pos) { } void cMonster::CheckEventSeePlayer(class cChunk & a_Chunk) { } bool cMonster::IsNetherNative(void) { return false; } bool cMonster::IsUndead(void) { return false; } void cMonster::EventLosePlayer(void) { } void cMonster::InStateIdle(std::chrono::milliseconds a_Dt ,class cChunk & a_Chunk) { } void cMonster::InStateEscaping(std::chrono::milliseconds a_Dt ,class cChunk & a_Chunk) { } cAggressiveMonster::cAggressiveMonster(const AString & a_StringA, enum eMonsterType a_MonsterType, const AString & a_StringB, const AString & a_StringC, const AString & a_StringD, float a_Width, float a_Height) : cMonster(a_StringA, a_MonsterType, a_StringB, a_StringC, a_StringD, a_Width, a_Height) { } void cAggressiveMonster::Tick(std::chrono::milliseconds a_Dt, class cChunk & a_Chunk) { } void cAggressiveMonster::InStateChasing(std::chrono::milliseconds a_Dt, class cChunk & a_Chunk) { } void cAggressiveMonster::EventSeePlayer(class cPlayer *,class cChunk &) { } bool cAggressiveMonster::Attack(std::chrono::milliseconds a_Dt) { return true; } ================================================ FILE: tests/Generating/Test.cubeset ================================================ -- Test.cubeset -- This simple cubeset file is used for testing the cPrefabPiecePool loader. Cubeset = { Metadata = { CubesetFormatVersion = 1, }, Pieces = { -- One piece with inline definition: { Size = { x = 4, y = 4, z = 4, }, Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 3, MaxY = 3, MaxZ = 3, }, BlockDefinitions = { ".: 0: 0", -- air "a: 1: 0", -- stone "b: 24: 0", -- sandstone "c: 8: 0", -- water "d: 85: 0", -- fence "m: 19: 0", -- sponge }, BlockData = { -- Level 0 "aaaa", -- 0 "aaaa", -- 1 "aaaa", -- 2 "aaaa", -- 3 -- Level 1 "bbbb", -- 0 "bccb", -- 1 "bccb", -- 2 "bbbb", -- 3 -- Level 2 "bbbb", -- 0 "bccb", -- 1 "bccb", -- 2 "bbbb", -- 3 -- Level 3 "bbbb", -- 0 "bccb", -- 1 "bccb", -- 2 "bbbb", -- 3 }, Connectors = { { Type = 2, RelX = 2, RelY = 2, RelZ = 0, Direction = 2, -- Z- }, { Type = 2, RelX = 0, RelY = 2, RelZ = 1, Direction = 4, -- X- }, { Type = 2, RelX = 1, RelY = 2, RelZ = 3, Direction = 3, -- Z+ }, { Type = 2, RelX = 3, RelY = 2, RelZ = 2, Direction = 5, -- X+ }, }, Metadata = { ["DefaultWeight"] = "100", ["AllowedRotations"] = "7", ["MergeStrategy"] = "msSpongePrint", ["IsStarting"] = "1", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "None", ["MoveToGround"] = "1", ["AddWeightIfSame"] = "0", ["VerticalStrategy"] = "Fixed|150", }, }, -- One piece with external definition: { Hitbox = { MinX = 0, MinY = 0, MinZ = 0, MaxX = 3, MaxY = 3, MaxZ = 3, }, SchematicFileName = "Test1.schematic", Connectors = { { Type = 2, RelX = 2, RelY = 2, RelZ = 0, Direction = 2, -- Z- }, }, Metadata = { ["DefaultWeight"] = "100", ["AllowedRotations"] = "7", ["MergeStrategy"] = "msSpongePrint", ["IsStarting"] = "0", ["DepthWeight"] = "", ["ExpandFloorStrategy"] = "None", ["MoveToGround"] = "0", ["AddWeightIfSame"] = "0", }, }, }, -- Pieces } ================================================ FILE: tests/HTTP/CMakeLists.txt ================================================ include_directories(${PROJECT_SOURCE_DIR}/src/) include_directories(SYSTEM ${PROJECT_SOURCE_DIR}/lib/mbedtls/include) # Create a single HTTP library that contains all the HTTP code: set (HTTP_SRCS ${PROJECT_SOURCE_DIR}/src/HTTP/EnvelopeParser.cpp ${PROJECT_SOURCE_DIR}/src/HTTP/HTTPMessage.cpp ${PROJECT_SOURCE_DIR}/src/HTTP/HTTPMessageParser.cpp ${PROJECT_SOURCE_DIR}/src/HTTP/TransferEncodingParser.cpp ${PROJECT_SOURCE_DIR}/src/HTTP/UrlClient.cpp ${PROJECT_SOURCE_DIR}/src/HTTP/UrlParser.cpp ${PROJECT_SOURCE_DIR}/src/OSSupport/StackTrace.cpp ${PROJECT_SOURCE_DIR}/src/OSSupport/WinStackWalker.cpp ${PROJECT_SOURCE_DIR}/src/StringUtils.cpp ) set (HTTP_HDRS ${PROJECT_SOURCE_DIR}/src/HTTP/EnvelopeParser.h ${PROJECT_SOURCE_DIR}/src/HTTP/HTTPMessage.h ${PROJECT_SOURCE_DIR}/src/HTTP/HTTPMessageParser.h ${PROJECT_SOURCE_DIR}/src/HTTP/TransferEncodingParser.h ${PROJECT_SOURCE_DIR}/src/HTTP/UrlClient.h ${PROJECT_SOURCE_DIR}/src/HTTP/UrlParser.h ${PROJECT_SOURCE_DIR}/src/OSSupport/StackTrace.h ${PROJECT_SOURCE_DIR}/src/OSSupport/WinStackWalker.h ${PROJECT_SOURCE_DIR}/src/StringUtils.h ) set (SHARED_SRCS ${PROJECT_SOURCE_DIR}/src/OSSupport/Event.cpp ) add_library(HTTP ${HTTP_SRCS} ${HTTP_HDRS} ) target_link_libraries(HTTP Network OSSupport) set (TEST_DATA_FILES HTTPRequest1.data HTTPRequest2.data HTTPResponse1.data HTTPResponse2.data ) source_group("Data Files" FILES ${TEST_DATA_FILES}) # Define individual test executables: # HTTPMessageParser_file: Feed file contents into a cHTTPResponseParser and print the callbacks as they're called: add_executable(HTTPMessageParser_file-exe HTTPMessageParser_file.cpp ${TEST_DATA_FILES}) target_link_libraries(HTTPMessageParser_file-exe HTTP Network OSSupport fmt::fmt) # UrlClientTest: Tests the UrlClient class by requesting a few things off the internet: add_executable(UrlClientTest-exe UrlClientTest.cpp) target_link_libraries(UrlClientTest-exe HTTP fmt::fmt) # Define individual tests: # Test parsing the response file in 2-byte chunks (should go from response line parsing through headers parsing to body parsing, each within a different step): add_test(NAME HTTPMessageParser_file-test1-2 COMMAND HTTPMessageParser_file-exe ${CMAKE_CURRENT_SOURCE_DIR}/HTTPResponse1.data 2) # Test parsing the response file in 128-byte chunks (should parse response line and part of headers in one step, the rest in another step): add_test(NAME HTTPMessageParser_file-test1-128 COMMAND HTTPMessageParser_file-exe ${CMAKE_CURRENT_SOURCE_DIR}/HTTPResponse1.data 128) # Test parsing a chunked-encoding response: add_test(NAME HTTPMessageParser_file-test2 COMMAND HTTPMessageParser_file-exe ${CMAKE_CURRENT_SOURCE_DIR}/HTTPResponse2.data) # Test parsing the request file in 2-byte chunks (should go from request line parsing through headers parsing to body parsing, each within a different step): add_test(NAME HTTPMessageParser_file-test3-2 COMMAND HTTPMessageParser_file-exe ${CMAKE_CURRENT_SOURCE_DIR}/HTTPRequest1.data 2) # Test parsing the request file in 512-byte chunks (should process everything in a single call): add_test(NAME HTTPMessageParser_file-test4-512 COMMAND HTTPMessageParser_file-exe ${CMAKE_CURRENT_SOURCE_DIR}/HTTPRequest1.data 512) # Test the URLClient add_test(NAME UrlClient-test COMMAND UrlClientTest-exe) # Put all the tests into a solution folder (MSVC): set_target_properties( HTTPMessageParser_file-exe UrlClientTest-exe PROPERTIES FOLDER Tests/HTTP ) set_target_properties( HTTP PROPERTIES FOLDER Tests/Libraries ) ================================================ FILE: tests/HTTP/HTTPMessageParser_file.cpp ================================================ // HTTPMessageParser_file.cpp // Implements a test that feeds file contents into a cHTTPMessageParser instance and prints all callbacks #include "Globals.h" #include "HTTP/HTTPMessageParser.h" /** Maximum size of the input buffer, through which the file is read */ static const size_t MAX_BUF = 4096; class cCallbacks: public cHTTPMessageParser::cCallbacks { typedef cHTTPMessageParser::cCallbacks Super; public: cCallbacks(void) { printf("cCallbacks created\n"); } // cHTTPResponseParser::cCallbacks overrides: virtual void OnError(const AString & a_ErrorDescription) override { printf("Error: \"%s\"\n", a_ErrorDescription.c_str()); } /** Called when the first line (request / status) is fully parsed. */ virtual void OnFirstLine(const AString & a_FirstLine) override { printf("First line: \"%s\"\n", a_FirstLine.c_str()); } /** Called when a single header line is parsed. */ virtual void OnHeaderLine(const AString & a_Key, const AString & a_Value) override { printf("Header line: \"%s\": \"%s\"\n", a_Key.c_str(), a_Value.c_str()); } /** Called when all the headers have been parsed. */ virtual void OnHeadersFinished(void) override { printf("Headers finished\n"); } /** Called for each chunk of the incoming body data. */ virtual void OnBodyData(const void * a_Data, size_t a_Size) override { AString hexDump; CreateHexDump(hexDump, a_Data, a_Size, 16); printf("Body data: %u bytes\n%s", static_cast(a_Size), hexDump.c_str()); } virtual void OnBodyFinished(void) override { printf("Body finished\n"); } }; int main(int argc, char * argv[]) { LOGD("Test started"); // Open the input file: if (argc <= 1) { printf("Usage: %s []\n", argv[0]); return 1; } FILE * f; if (strcmp(argv[1], "-") == 0) { f = stdin; } else { f = fopen(argv[1], "rb"); if (f == nullptr) { printf("Cannot open file \"%s\". Aborting.\n", argv[1]); return 2; } } // If a third param is present, use it as the buffer size size_t bufSize = MAX_BUF; if (argc >= 3) { if (!StringToInteger(argv[2], bufSize) || (bufSize == 0)) { bufSize = MAX_BUF; printf("\"%s\" is not a valid buffer size, using the default of %u instead.\n", argv[2], static_cast(bufSize)); } if (bufSize > MAX_BUF) { bufSize = MAX_BUF; printf("\"%s\" is too large, maximum buffer size is %u. Using the size %u instead.\n", argv[2], static_cast(bufSize), static_cast(bufSize)); } } // Feed the file contents into the parser: cCallbacks callbacks; cHTTPMessageParser parser(callbacks); while (true) { char buf[MAX_BUF]; auto numBytes = fread(buf, 1, bufSize, f); if (numBytes == 0) { printf("Read 0 bytes from file (EOF?), terminating\n"); break; } auto numConsumed = parser.Parse(buf, numBytes); if (numConsumed == AString::npos) { printf("Parser indicates there was an error, terminating parsing.\n"); break; } ASSERT(numConsumed <= numBytes); if (numConsumed < numBytes) { printf("Parser indicates stream end, but there's more data (at least %u bytes) in the file.\n", static_cast(numBytes - numConsumed)); } } if (!parser.IsFinished()) { printf("Parser indicates an incomplete stream.\n"); } // Close the input file: if (f != stdin) { fclose(f); } return 0; } ================================================ FILE: tests/HTTP/HTTPRequest1.data ================================================ GET /some/url HTTP/1.1 Note: This is a test of a regular request Content-Length: 3 Empty-Header: Almost-Empty-Header: a Two-Char-Header: 12 bla ================================================ FILE: tests/HTTP/HTTPRequest2.data ================================================ GET /some/url HTTP/1.1 Note: This is a test of a regular body-less request ================================================ FILE: tests/HTTP/HTTPRequestParser_file.cpp ================================================ // HTTPResponseParser_file.cpp // Implements a test that feeds file contents into a cHTTPResponseParser instance and prints all callbacks #include "Globals.h" #include "HTTP/HTTPRequestParser.h" /** Maximum size of the input buffer, through which the file is read */ static const size_t MAX_BUF = 4096; class cCallbacks: public cHTTPRequestParser::cCallbacks { typedef cHTTPResponseParser::cCallbacks Super; public: cCallbacks(void) { printf("cCallbacks created\n"); } // cHTTPResponseParser::cCallbacks overrides: virtual void OnError(const AString & a_ErrorDescription) override { printf("Error: \"%s\"\n", a_ErrorDescription.c_str()); } /** Called when the status line is fully parsed. */ virtual void OnStatusLine(const AString & a_StatusLine) override { printf("Status line: \"%s\"\n", a_StatusLine.c_str()); } /** Called when a single header line is parsed. */ virtual void OnHeaderLine(const AString & a_Key, const AString & a_Value) override { printf("Header line: \"%s\": \"%s\"\n", a_Key.c_str(), a_Value.c_str()); } /** Called when all the headers have been parsed. */ virtual void OnHeadersFinished(void) override { printf("Headers finished\n"); } /** Called for each chunk of the incoming body data. */ virtual void OnBodyData(const void * a_Data, size_t a_Size) override { AString hexDump; CreateHexDump(hexDump, a_Data, a_Size, 16); printf("Body data: %u bytes\n%s", static_cast(a_Size), hexDump.c_str()); } virtual void OnBodyFinished(void) override { printf("Body finished\n"); } }; int main(int argc, char * argv[]) { printf("HTTPResponseParser_file beginning\n"); // Open the input file: if (argc <= 1) { printf("Usage: %s []\n", argv[0]); return 1; } FILE * f; if (strcmp(argv[1], "-") == 0) { f = stdin; } else { f = fopen(argv[1], "rb"); if (f == nullptr) { printf("Cannot open file \"%s\". Aborting.\n", argv[1]); return 2; } } // If a third param is present, use it as the buffer size size_t bufSize = MAX_BUF; if (argc >= 3) { if (!StringToInteger(argv[2], bufSize) || (bufSize == 0)) { bufSize = MAX_BUF; printf("\"%s\" is not a valid buffer size, using the default of %u instead.\n", argv[2], static_cast(bufSize)); } if (bufSize > MAX_BUF) { bufSize = MAX_BUF; printf("\"%s\" is too large, maximum buffer size is %u. Using the size %u instead.\n", argv[2], static_cast(bufSize), static_cast(bufSize)); } } // Feed the file contents into the parser: cCallbacks callbacks; cHTTPResponseParser parser(callbacks); while (!feof(f)) { char buf[MAX_BUF]; auto numBytes = fread(buf, 1, bufSize, f); if (numBytes == 0) { printf("Read 0 bytes from file (EOF?), terminating\n"); break; } auto numConsumed = parser.Parse(buf, numBytes); if (numConsumed == AString::npos) { printf("Parser indicates there was an error, terminating parsing.\n"); break; } ASSERT(numConsumed <= numBytes); if (numConsumed < numBytes) { printf("Parser indicates stream end, but there's more data (at least %u bytes) in the file.\n", static_cast(numBytes - numConsumed)); } } if (!parser.IsFinished()) { printf("Parser indicates an incomplete stream.\n"); } // Close the input file: if (f != stdin) { fclose(f); } return 0; } ================================================ FILE: tests/HTTP/HTTPResponse1.data ================================================ HTTP/1.0 200 OK Note: This is a test of a regular response with Content-Length set (identity transfer encoding) Note2: The above header also tests multi-line header lines Note3: The data is 2 bytes longer than the actual request, parser should indicate 2 extra bytes at the end Header1: Value1 Header2: Value2 Content-Length: 3 Empty-Header: bla ================================================ FILE: tests/HTTP/HTTPResponse2.data ================================================ HTTP/1.0 200 OK Note: This is a Chunked transfer encoding test Header2: Value2 Transfer-Encoding: chunked Empty-Header: 4 Wiki 5 pedia e in chunks. 0 ================================================ FILE: tests/HTTP/HTTPResponseParser_file.cpp ================================================ // HTTPResponseParser_file.cpp // Implements a test that feeds file contents into a cHTTPResponseParser instance and prints all callbacks #include "Globals.h" #include "HTTP/HTTPResponseParser.h" /** Maximum size of the input buffer, through which the file is read */ static const size_t MAX_BUF = 4096; class cCallbacks: public cHTTPResponseParser::cCallbacks { typedef cHTTPResponseParser::cCallbacks Super; public: cCallbacks(void) { printf("cCallbacks created\n"); } // cHTTPResponseParser::cCallbacks overrides: virtual void OnError(const AString & a_ErrorDescription) override { printf("Error: \"%s\"\n", a_ErrorDescription.c_str()); } /** Called when the status line is fully parsed. */ virtual void OnStatusLine(const AString & a_StatusLine) override { printf("Status line: \"%s\"\n", a_StatusLine.c_str()); } /** Called when a single header line is parsed. */ virtual void OnHeaderLine(const AString & a_Key, const AString & a_Value) override { printf("Header line: \"%s\": \"%s\"\n", a_Key.c_str(), a_Value.c_str()); } /** Called when all the headers have been parsed. */ virtual void OnHeadersFinished(void) override { printf("Headers finished\n"); } /** Called for each chunk of the incoming body data. */ virtual void OnBodyData(const void * a_Data, size_t a_Size) override { AString hexDump; CreateHexDump(hexDump, a_Data, a_Size, 16); printf("Body data: %u bytes\n%s", static_cast(a_Size), hexDump.c_str()); } virtual void OnBodyFinished(void) override { printf("Body finished\n"); } }; int main(int argc, char * argv[]) { printf("HTTPResponseParser_file beginning\n"); // Open the input file: if (argc <= 1) { printf("Usage: %s []\n", argv[0]); return 1; } FILE * f; if (strcmp(argv[1], "-") == 0) { f = stdin; } else { f = fopen(argv[1], "rb"); if (f == nullptr) { printf("Cannot open file \"%s\". Aborting.\n", argv[1]); return 2; } } // If a third param is present, use it as the buffer size size_t bufSize = MAX_BUF; if (argc >= 3) { if (!StringToInteger(argv[2], bufSize) || (bufSize == 0)) { bufSize = MAX_BUF; printf("\"%s\" is not a valid buffer size, using the default of %u instead.\n", argv[2], static_cast(bufSize)); } if (bufSize > MAX_BUF) { bufSize = MAX_BUF; printf("\"%s\" is too large, maximum buffer size is %u. Using the size %u instead.\n", argv[2], static_cast(bufSize), static_cast(bufSize)); } } // Feed the file contents into the parser: cCallbacks callbacks; cHTTPResponseParser parser(callbacks); while (!feof(f)) { char buf[MAX_BUF]; auto numBytes = fread(buf, 1, bufSize, f); if (numBytes == 0) { printf("Read 0 bytes from file (EOF?), terminating\n"); break; } auto numConsumed = parser.Parse(buf, numBytes); if (numConsumed == AString::npos) { printf("Parser indicates there was an error, terminating parsing.\n"); break; } ASSERT(numConsumed <= numBytes); if (numConsumed < numBytes) { printf("Parser indicates stream end, but there's more data (at least %u bytes) in the file.\n", static_cast(numBytes - numConsumed)); } } if (!parser.IsFinished()) { printf("Parser indicates an incomplete stream.\n"); } // Close the input file: if (f != stdin) { fclose(f); } return 0; } ================================================ FILE: tests/HTTP/UrlClientTest.cpp ================================================ #include "Globals.h" #include "../TestHelpers.h" #include "HTTP/UrlClient.h" #include "OSSupport/NetworkSingleton.h" namespace { // When under debugger, set timeouts to practically "never" so that there's time to step through the code: #ifdef NDEBUG static const UInt32 TIMEOUT = 10000; // 10 seconds #else static const UInt32 TIMEOUT = 0xffffffff; // ~4.3M seconds / ~49 days #endif /** Track number of cCallbacks instances alive. */ std::atomic g_ActiveCallbacks{ 0 }; /** Simple callbacks that dump the events to the console and signalize a cEvent when the request is finished. */ class cCallbacks: public cUrlClient::cCallbacks { public: cCallbacks(std::shared_ptr a_Event): m_Event(std::move(a_Event)) { ++g_ActiveCallbacks; LOGD("Created a cCallbacks instance at %p", reinterpret_cast(this)); } virtual ~cCallbacks() override { --g_ActiveCallbacks; LOGD("Deleting the cCallbacks instance at %p", reinterpret_cast(this)); } virtual void OnConnected(cTCPLink & a_Link) override { LOG("Link connected to %s:%u", a_Link.GetRemoteIP().c_str(), a_Link.GetRemotePort()); } virtual bool OnCertificateReceived() override { LOG("Server certificate received"); return true; } virtual void OnTlsHandshakeCompleted() override { LOG("TLS handshake has completed."); } virtual void OnRequestSent() override { LOG("Request has been sent"); } virtual void OnHeader(const AString & a_Key, const AString & a_Value) override { LOG("HTTP Header: \"%s\" -> \"%s\"", a_Key.c_str(), a_Value.c_str()); } virtual void OnHeadersFinished() override { LOG("HTTP headers finished."); } virtual void OnBodyData(const void * a_Data, size_t a_Size) override { #if 0 // Output the whole received data blob: AString body(reinterpret_cast(a_Data), a_Size); LOG("Body part:\n%s", body.c_str()); #else // Output only the data size, to keep the log short: LOG("Body part: %u bytes", static_cast(a_Size)); #endif } virtual void OnBodyFinished() override { LOG("Body finished."); m_Event->Set(); } virtual void OnRedirecting(const AString & a_RedirectUrl) override { LOG("Redirecting to \"%s\".", a_RedirectUrl.c_str()); } virtual void OnError(const AString & a_ErrorMsg) override { LOG("Error: %s", a_ErrorMsg.c_str()); m_Event->Set(); } protected: std::shared_ptr m_Event; }; /** The trusted root CAs for individual servers. */ namespace TrustedCAs { // DigiCert Global Root CA (sessionserver.mojang.com) // Downloaded from https://www.digicert.com/kb/digicert-root-certificates.htm // DigiCert Global Root CA static const char MojangComSessionServer[] = "-----BEGIN CERTIFICATE-----\n" "MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBh\n" "MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\n" "d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH\n" "MjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVT\n" "MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j\n" "b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkqhkiG\n" "9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI\n" "2/Ou8jqJkTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx\n" "1x7e/dfgy5SDN67sH0NO3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQ\n" "q2EGnI/yuum06ZIya7XzV+hdG82MHauVBJVJ8zUtluNJbd134/tJS7SsVQepj5Wz\n" "tCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyMUNGPHgm+F6HmIcr9g+UQ\n" "vIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQABo0IwQDAP\n" "BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV\n" "5uNu5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY\n" "1Yl9PMWLSn/pvtsrF9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4\n" "NeF22d+mQrvHRAiGfzZ0JFrabA0UWTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NG\n" "Fdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBHQRFXGU7Aj64GxJUTFy8bJZ91\n" "8rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/iyK5S9kJRaTe\n" "pLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl\n" "MrY=\n" "-----END CERTIFICATE-----\n"; // DigiCert Global Root G2 (api.mojang.com) // Downloaded from https://www.digicert.com/kb/digicert-root-certificates.htm // DigiCert Global Root G2 static const char MojangComAPIMojang[] = "-----BEGIN CERTIFICATE-----\n" "MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBh\n" "MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\n" "d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH\n" "MjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVT\n" "MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j\n" "b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkqhkiG\n" "9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI\n" "2/Ou8jqJkTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx\n" "1x7e/dfgy5SDN67sH0NO3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQ\n" "q2EGnI/yuum06ZIya7XzV+hdG82MHauVBJVJ8zUtluNJbd134/tJS7SsVQepj5Wz\n" "tCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyMUNGPHgm+F6HmIcr9g+UQ\n" "vIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQABo0IwQDAP\n" "BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV\n" "5uNu5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY\n" "1Yl9PMWLSn/pvtsrF9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4\n" "NeF22d+mQrvHRAiGfzZ0JFrabA0UWTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NG\n" "Fdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBHQRFXGU7Aj64GxJUTFy8bJZ91\n" "8rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/iyK5S9kJRaTe\n" "pLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl\n" "MrY=\n" "-----END CERTIFICATE-----\n"; // The root cert used by github.com static const char GithubCom[] = "-----BEGIN CERTIFICATE-----\n" "MIICjzCCAhWgAwIBAgIQXIuZxVqUxdJxVt7NiYDMJjAKBggqhkjOPQQDAzCBiDEL\n" "MAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNl\n" "eSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMT\n" "JVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAwMjAx\n" "MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgT\n" "Ck5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVUaGUg\n" "VVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlm\n" "aWNhdGlvbiBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQarFRaqflo\n" "I+d61SRvU8Za2EurxtW20eZzca7dnNYMYf3boIkDuAUU7FfO7l0/4iGzzvfUinng\n" "o4N+LZfQYcTxmdwlkWOrfzCjtHDix6EznPO/LlxTsV+zfTJ/ijTjeXmjQjBAMB0G\n" "A1UdDgQWBBQ64QmG1M8ZwpZ2dEl23OA1xmNjmjAOBgNVHQ8BAf8EBAMCAQYwDwYD\n" "VR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjA2Z6EWCNzklwBBHU6+4WMB\n" "zzuqQhFkoJ2UOQIReVx7Hfpkue4WQrO/isIJxOzksU0CMQDpKmFHjFJKS04YcPbW\n" "RNZu9YO6bVi9JNlWSOrvxKJGgYhqOkbRqZtNyWHa0V1Xahg=\n" "-----END CERTIFICATE-----\n"; // The root cert used by github.com in the past (no longer used) static const char GithubComOld[] = "-----BEGIN CERTIFICATE-----\n" "MIIEFzCCAv+gAwIBAgIQB/LzXIeod6967+lHmTUlvTANBgkqhkiG9w0BAQwFADBh\n" "MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\n" "d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD\n" "QTAeFw0yMTA0MTQwMDAwMDBaFw0zMTA0MTMyMzU5NTlaMFYxCzAJBgNVBAYTAlVT\n" "MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxMDAuBgNVBAMTJ0RpZ2lDZXJ0IFRMUyBI\n" "eWJyaWQgRUNDIFNIQTM4NCAyMDIwIENBMTB2MBAGByqGSM49AgEGBSuBBAAiA2IA\n" "BMEbxppbmNmkKaDp1AS12+umsmxVwP/tmMZJLwYnUcu/cMEFesOxnYeJuq20ExfJ\n" "qLSDyLiQ0cx0NTY8g3KwtdD3ImnI8YDEe0CPz2iHJlw5ifFNkU3aiYvkA8ND5b8v\n" "c6OCAYIwggF+MBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFAq8CCkXjKU5\n" "bXoOzjPHLrPt+8N6MB8GA1UdIwQYMBaAFAPeUDVW0Uy7ZvCj4hsbw5eyPdFVMA4G\n" "A1UdDwEB/wQEAwIBhjAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwdgYI\n" "KwYBBQUHAQEEajBoMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5j\n" "b20wQAYIKwYBBQUHMAKGNGh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdp\n" "Q2VydEdsb2JhbFJvb3RDQS5jcnQwQgYDVR0fBDswOTA3oDWgM4YxaHR0cDovL2Ny\n" "bDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0R2xvYmFsUm9vdENBLmNybDA9BgNVHSAE\n" "NjA0MAsGCWCGSAGG/WwCATAHBgVngQwBATAIBgZngQwBAgEwCAYGZ4EMAQICMAgG\n" "BmeBDAECAzANBgkqhkiG9w0BAQwFAAOCAQEAR1mBf9QbH7Bx9phdGLqYR5iwfnYr\n" "6v8ai6wms0KNMeZK6BnQ79oU59cUkqGS8qcuLa/7Hfb7U7CKP/zYFgrpsC62pQsY\n" "kDUmotr2qLcy/JUjS8ZFucTP5Hzu5sn4kL1y45nDHQsFfGqXbbKrAjbYwrwsAZI/\n" "BKOLdRHHuSm8EdCGupK8JvllyDfNJvaGEwwEqonleLHBTnm8dqMLUeTF0J5q/hos\n" "Vq4GNiejcxwIfZMy0MJEGdqN9A57HSgDKwmKdsp33Id6rHtSJlWncg+d0ohP/rEh\n" "xRqhqjn1VtvChMQ1H3Dau0bwhr9kAMQ+959GG50jBbl9s08PqUU643QwmA==\n" "-----END CERTIFICATE-----\n"; // The root cert used by cuberite.org static const char CuberiteOrg[] = "-----BEGIN CERTIFICATE-----\n" "MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw\n" "TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh\n" "cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4\n" "WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu\n" "ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY\n" "MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc\n" "h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+\n" "0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U\n" "A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW\n" "T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH\n" "B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC\n" "B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv\n" "KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn\n" "OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn\n" "jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw\n" "qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI\n" "rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV\n" "HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq\n" "hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL\n" "ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ\n" "3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK\n" "NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5\n" "ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur\n" "TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC\n" "jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc\n" "oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq\n" "4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA\n" "mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d\n" "emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=\n" "-----END CERTIFICATE-----\n"; } int TestRequest1() { LOG("Running test 1 - fetch http://github.com without redirects"); auto evtFinished = std::make_shared(); auto callbacks = std::make_unique(evtFinished); AStringMap options; options["MaxRedirects"] = "0"; auto res = cUrlClient::Get("http://github.com", std::move(callbacks), AStringMap(), AString(), std::move(options)); if (res.first) { if (!evtFinished->Wait(TIMEOUT)) { LOG("Aborting the wait for response; failing the test."); return 1; } } else { LOG("Immediate error: %s", res.second.c_str()); return 1; } return 0; } int TestRequest2() { LOG("Running test 2 - default fetch http://github.com"); auto evtFinished = std::make_shared(); auto callbacks = std::make_unique(evtFinished); auto res = cUrlClient::Get("http://github.com", std::move(callbacks)); if (res.first) { if (!evtFinished->Wait(TIMEOUT)) { LOG("Aborting the wait for response; failing the test."); return 1; } } else { LOG("Immediate error: %s", res.second.c_str()); return 1; } return 0; } int TestRequest3() { LOG("Running test 3 - fetch https://github.com without redirects"); auto evtFinished = std::make_shared(); auto callbacks = std::make_unique(evtFinished); AStringMap options; options["MaxRedirects"] = "0"; auto res = cUrlClient::Get("https://github.com", std::move(callbacks), AStringMap(), AString(), std::move(options)); if (res.first) { if (!evtFinished->Wait(TIMEOUT)) { LOG("Aborting the wait for response; failing the test."); return 1; } } else { LOG("Immediate error: %s", res.second.c_str()); return 1; } return 0; } int TestRequest4() { LOG("Running test 4 - fetch https://github.com with GitHub trusted root CA"); auto evtFinished = std::make_shared(); auto callbacks = std::make_unique(evtFinished); AStringMap options; options["TrustedRootCAs"] = TrustedCAs::GithubCom; auto res = cUrlClient::Get("https://github.com", std::move(callbacks), {}, {}, options); if (res.first) { if (!evtFinished->Wait(TIMEOUT)) { LOG("Aborting the wait for response; failing the test."); return 1; } } else { LOG("Immediate error: %s", res.second.c_str()); return 1; } return 0; } int TestRequest5() { LOG("Running test 5 - fetch https://cuberite.org with Cuberite trusted root CA"); auto evtFinished = std::make_shared(); auto callbacks = std::make_unique(evtFinished); AStringMap options; options["TrustedRootCAs"] = TrustedCAs::CuberiteOrg; auto res = cUrlClient::Get("https://cuberite.org", std::move(callbacks), {}, {}, options); if (res.first) { if (!evtFinished->Wait(TIMEOUT)) { LOG("Aborting the wait for response; failing the test."); return 1; } } else { LOG("Immediate error: %s", res.second.c_str()); return 1; } return 0; } int TestRequest6() { LOG("Running test 6 - fetch https://sessionserver.mojang.com with Mojang trusted root CA"); auto evtFinished = std::make_shared(); auto callbacks = std::make_unique(evtFinished); AStringMap options; options["TrustedRootCAs"] = TrustedCAs::MojangComSessionServer; auto res = cUrlClient::Get("https://sessionserver.mojang.com", std::move(callbacks), {}, {}, options); if (res.first) { if (!evtFinished->Wait(TIMEOUT)) { LOG("Aborting the wait for response; failing the test."); return 1; } } else { LOG("Immediate error: %s", res.second.c_str()); return 1; } return 0; } int TestRequest7() { LOG("Running test 7 - fetch https://api.mojang.com with Mojang trusted root CA"); auto evtFinished = std::make_shared(); auto callbacks = std::make_unique(evtFinished); AStringMap options; options["TrustedRootCAs"] = TrustedCAs::MojangComAPIMojang; auto res = cUrlClient::Get("https://api.mojang.com", std::move(callbacks), {}, {}, options); if (res.first) { if (!evtFinished->Wait(TIMEOUT)) { LOG("Aborting the wait for response; failing the test."); return 1; } } else { LOG("Immediate error: %s", res.second.c_str()); return 1; } return 0; } int TestRequest8() { LOG("Running test 8 - fetch https://api.mojang.com with GitHub trusted root CA (testing CA verification rejection)"); auto evtFinished = std::make_shared(); auto callbacks = std::make_unique(evtFinished); AStringMap options; options["TrustedRootCAs"] = TrustedCAs::GithubCom; auto [isSuccess, response] = cUrlClient::BlockingGet("https://api.mojang.com", {}, {}, options); if (isSuccess) { LOG("CA verification failure, should have rejected the connection due to bad root CA."); return 1; } return 0; } int TestRequests() { using func_t = int(void); func_t * tests[] = { &TestRequest1, &TestRequest2, &TestRequest3, &TestRequest4, &TestRequest5, &TestRequest6, &TestRequest7, &TestRequest8, }; for (auto test: tests) { LOG("%s", AString(60, '-').c_str()); auto res = test(); if (res != 0) { return res; } } return 0; } } // namespace (anonymous) IMPLEMENT_TEST_MAIN("UrlClient", LOG("Initializing cNetwork..."); cNetworkSingleton::Get().Initialise(); LOG("Testing..."); TEST_EQUAL(TestRequests(), 0); LOG("Terminating cNetwork..."); cNetworkSingleton::Get().Terminate(); // No leaked callback instances LOG("cCallback instances still alive: %d", g_ActiveCallbacks.load()); TEST_EQUAL(g_ActiveCallbacks, 0); ) ================================================ FILE: tests/LoadablePieces/CMakeLists.txt ================================================ include_directories(${PROJECT_SOURCE_DIR}/src/) include_directories(SYSTEM ${PROJECT_SOURCE_DIR}/lib/) include_directories(${CMAKE_CURRENT_SOURCE_DIR}) set (SHARED_SRCS ${PROJECT_SOURCE_DIR}/src/BiomeDef.cpp ${PROJECT_SOURCE_DIR}/src/BlockArea.cpp ${PROJECT_SOURCE_DIR}/src/Cuboid.cpp ${PROJECT_SOURCE_DIR}/src/ChunkData.cpp ${PROJECT_SOURCE_DIR}/src/StringCompression.cpp ${PROJECT_SOURCE_DIR}/src/StringUtils.cpp ${PROJECT_SOURCE_DIR}/src/Bindings/LuaState.cpp ${PROJECT_SOURCE_DIR}/src/Generating/ChunkDesc.cpp ${PROJECT_SOURCE_DIR}/src/Generating/PiecePool.cpp ${PROJECT_SOURCE_DIR}/src/Generating/Prefab.cpp ${PROJECT_SOURCE_DIR}/src/Generating/PrefabPiecePool.cpp ${PROJECT_SOURCE_DIR}/src/Generating/VerticalLimit.cpp ${PROJECT_SOURCE_DIR}/src/Generating/VerticalStrategy.cpp ${PROJECT_SOURCE_DIR}/src/Noise/Noise.cpp ${PROJECT_SOURCE_DIR}/src/OSSupport/CriticalSection.cpp ${PROJECT_SOURCE_DIR}/src/OSSupport/Event.cpp ${PROJECT_SOURCE_DIR}/src/OSSupport/File.cpp ${PROJECT_SOURCE_DIR}/src/OSSupport/GZipFile.cpp ${PROJECT_SOURCE_DIR}/src/OSSupport/StackTrace.cpp ${PROJECT_SOURCE_DIR}/src/WorldStorage/FastNBT.cpp ${PROJECT_SOURCE_DIR}/src/WorldStorage/SchematicFileSerializer.cpp ) set (SHARED_HDRS ${PROJECT_SOURCE_DIR}/src/BiomeDef.h ${PROJECT_SOURCE_DIR}/src/BlockArea.h ${PROJECT_SOURCE_DIR}/src/Cuboid.h ${PROJECT_SOURCE_DIR}/src/ChunkData.h ${PROJECT_SOURCE_DIR}/src/Globals.h ${PROJECT_SOURCE_DIR}/src/StringCompression.h ${PROJECT_SOURCE_DIR}/src/StringUtils.h ${PROJECT_SOURCE_DIR}/src/Bindings/LuaState.h ${PROJECT_SOURCE_DIR}/src/Generating/ChunkDesc.h ${PROJECT_SOURCE_DIR}/src/Generating/PiecePool.h ${PROJECT_SOURCE_DIR}/src/Generating/Prefab.h ${PROJECT_SOURCE_DIR}/src/Generating/PrefabPiecePool.h ${PROJECT_SOURCE_DIR}/src/Generating/VerticalLimit.h ${PROJECT_SOURCE_DIR}/src/Generating/VerticalStrategy.h ${PROJECT_SOURCE_DIR}/src/Noise/Noise.h ${PROJECT_SOURCE_DIR}/src/OSSupport/CriticalSection.h ${PROJECT_SOURCE_DIR}/src/OSSupport/Event.h ${PROJECT_SOURCE_DIR}/src/OSSupport/File.h ${PROJECT_SOURCE_DIR}/src/OSSupport/GZipFile.h ${PROJECT_SOURCE_DIR}/src/OSSupport/StackTrace.h ${PROJECT_SOURCE_DIR}/src/WorldStorage/FastNBT.h ${PROJECT_SOURCE_DIR}/src/WorldStorage/SchematicFileSerializer.h ) set (SRCS LoadablePieces.cpp Stubs.cpp LuaState_Typedefs.inc LuaState_Declaration.inc Bindings.h ) if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") add_compile_options("-Wno-error=global-constructors") add_compile_options("-Wno-error=switch-enum") endif() if (MSVC) # Add the MSVC-specific LeakFinder sources: list (APPEND SHARED_SRCS ${PROJECT_SOURCE_DIR}/src/LeakFinder.cpp ${PROJECT_SOURCE_DIR}/src/StackWalker.cpp) list (APPEND SHARED_HDRS ${PROJECT_SOURCE_DIR}/src/LeakFinder.h ${PROJECT_SOURCE_DIR}/src/StackWalker.h) endif() source_group("Shared" FILES ${SHARED_SRCS} ${SHARED_HDRS}) source_group("Sources" FILES ${SRCS}) source_group("Data files" FILES Test.cubeset Test1.schematic) add_executable(LoadablePieces ${SRCS} ${SHARED_SRCS} ${SHARED_HDRS} Test.cubeset Test1.schematic) target_link_libraries(LoadablePieces libdeflate tolualib) add_test(NAME LoadablePieces-test WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMAND LoadablePieces) # Put the projects into solution folders (MSVC): set_target_properties( LoadablePieces PROPERTIES FOLDER Tests ) ================================================ FILE: tests/LuaThreadStress/Bindings.h ================================================ // Bindings.h // Dummy include file needed for LuaState to compile successfully struct lua_State; int tolua_AllToLua_open(lua_State * a_LuaState); ================================================ FILE: tests/LuaThreadStress/CMakeLists.txt ================================================ find_package(Threads REQUIRED) include_directories(${PROJECT_SOURCE_DIR}/src/) include_directories(SYSTEM ${PROJECT_SOURCE_DIR}/lib/) include_directories(${CMAKE_CURRENT_SOURCE_DIR}) set (SHARED_SRCS ${PROJECT_SOURCE_DIR}/src/BiomeDef.cpp ${PROJECT_SOURCE_DIR}/src/BlockArea.cpp ${PROJECT_SOURCE_DIR}/src/Cuboid.cpp ${PROJECT_SOURCE_DIR}/src/ChunkData.cpp ${PROJECT_SOURCE_DIR}/src/StringCompression.cpp ${PROJECT_SOURCE_DIR}/src/StringUtils.cpp ${PROJECT_SOURCE_DIR}/src/Bindings/LuaState.cpp ${PROJECT_SOURCE_DIR}/src/Generating/ChunkDesc.cpp ${PROJECT_SOURCE_DIR}/src/Generating/PieceModifier.cpp ${PROJECT_SOURCE_DIR}/src/Generating/PiecePool.cpp ${PROJECT_SOURCE_DIR}/src/Generating/Prefab.cpp ${PROJECT_SOURCE_DIR}/src/Generating/PrefabPiecePool.cpp ${PROJECT_SOURCE_DIR}/src/Generating/VerticalLimit.cpp ${PROJECT_SOURCE_DIR}/src/Generating/VerticalStrategy.cpp ${PROJECT_SOURCE_DIR}/src/Noise/Noise.cpp ${PROJECT_SOURCE_DIR}/src/OSSupport/CriticalSection.cpp ${PROJECT_SOURCE_DIR}/src/OSSupport/Event.cpp ${PROJECT_SOURCE_DIR}/src/OSSupport/File.cpp ${PROJECT_SOURCE_DIR}/src/OSSupport/GZipFile.cpp ${PROJECT_SOURCE_DIR}/src/OSSupport/StackTrace.cpp ${PROJECT_SOURCE_DIR}/src/OSSupport/WinStackWalker.cpp ${PROJECT_SOURCE_DIR}/src/WorldStorage/FastNBT.cpp ${PROJECT_SOURCE_DIR}/src/WorldStorage/SchematicFileSerializer.cpp ) set (SHARED_HDRS ${PROJECT_SOURCE_DIR}/src/BiomeDef.h ${PROJECT_SOURCE_DIR}/src/BlockArea.h ${PROJECT_SOURCE_DIR}/src/Cuboid.h ${PROJECT_SOURCE_DIR}/src/ChunkData.h ${PROJECT_SOURCE_DIR}/src/Globals.h ${PROJECT_SOURCE_DIR}/src/StringCompression.h ${PROJECT_SOURCE_DIR}/src/StringUtils.h ${PROJECT_SOURCE_DIR}/src/Bindings/LuaState.h ${PROJECT_SOURCE_DIR}/src/Generating/ChunkDesc.h ${PROJECT_SOURCE_DIR}/src/Generating/PieceModifier.h ${PROJECT_SOURCE_DIR}/src/Generating/PiecePool.h ${PROJECT_SOURCE_DIR}/src/Generating/Prefab.h ${PROJECT_SOURCE_DIR}/src/Generating/PrefabPiecePool.h ${PROJECT_SOURCE_DIR}/src/Generating/VerticalLimit.h ${PROJECT_SOURCE_DIR}/src/Generating/VerticalStrategy.h ${PROJECT_SOURCE_DIR}/src/Noise/Noise.h ${PROJECT_SOURCE_DIR}/src/OSSupport/CriticalSection.h ${PROJECT_SOURCE_DIR}/src/OSSupport/Event.h ${PROJECT_SOURCE_DIR}/src/OSSupport/File.h ${PROJECT_SOURCE_DIR}/src/OSSupport/GZipFile.h ${PROJECT_SOURCE_DIR}/src/OSSupport/StackTrace.h ${PROJECT_SOURCE_DIR}/src/OSSupport/WinStackWalker.h ${PROJECT_SOURCE_DIR}/src/WorldStorage/FastNBT.h ${PROJECT_SOURCE_DIR}/src/WorldStorage/SchematicFileSerializer.h ) set (SRCS LuaThreadStress.cpp Stubs.cpp LuaState_Typedefs.inc LuaState_Declaration.inc Bindings.h ) source_group("Shared" FILES ${SHARED_SRCS} ${SHARED_HDRS}) source_group("Sources" FILES ${SRCS}) source_group("Lua files" FILES Test.lua) add_executable(LuaThreadStress ${SRCS} ${SHARED_SRCS} ${SHARED_HDRS} Test.lua) target_link_libraries(LuaThreadStress fmt::fmt libdeflate lsqlite luaexpat Threads::Threads tolualib) if (WIN32) target_link_libraries(LuaThreadStress ws2_32) endif() add_test(NAME LuaThreadStress-test WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMAND LuaThreadStress) # Necessary for the test to run. # Otherwise they crash with the error STATUS_DLL_NOT_FOUND (0xC0000135) because they can't find the lua51.dll if(WIN32) add_custom_command( TARGET LuaThreadStress POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/Server/lua51.dll # Source ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${CMAKE_BUILD_TYPE}/) # Destination message("Copying lua51.dll from " ${CMAKE_BINARY_DIR}/Server/lua51.dll " to " ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${CMAKE_BUILD_TYPE}/) endif() # Put the projects into solution folders (MSVC): set_target_properties( LuaThreadStress PROPERTIES FOLDER Tests ) ================================================ FILE: tests/LuaThreadStress/LuaState_Declaration.inc ================================================ // LuaState_Declaration.inc // Dummy include file needed for LuaState to compile successfully bool GetStackValue(int, cUUID *&); ================================================ FILE: tests/LuaThreadStress/LuaState_Typedefs.inc ================================================ // LuaState_Typedefs.inc // Dummy include file needed for LuaState to compile successfully // Forward-declare classes that are used in the API but never called: struct HTTPRequest; struct HTTPTemplateRequest; class cPluginLua; class cBoundingBox; template class cItemCallback; class cEntity; class cUUID; ================================================ FILE: tests/LuaThreadStress/LuaThreadStress.cpp ================================================ // LuaThreadStress.cpp // Implements a stress-test of cLuaState under several threads #include "Globals.h" #include "Bindings/LuaState.h" #include #include /** How long the threading test should run. */ static const int NUM_SECONDS_TO_TEST = 10; /** Retrieves a callback from the Lua state that can be later called. Calls the Lua function getCallback with a_Seed param to retrieve the callback. */ static cLuaState::cCallbackPtr getCallback(cLuaState & a_LuaState, unsigned a_Seed) { cLuaState::cLock lock(a_LuaState); cLuaState::cCallbackPtr res; a_LuaState.Call("getCallback", a_Seed, cLuaState::Return, res); return res; } /** Runs a single thread that stress-tests the cLuaState object. a_LuaState is the Lua state on which to operate. a_Seed is the seed for the random number generator for this thread. a_ShouldTerminate is a bool flag that another thread sets to ask this thread to terminate. a_FailResult is a shared result state that is written by any thread upon failure (so if it contains nonzero, at least one thread has failed). */ static void runStress(cLuaState * a_LuaState, unsigned a_Seed, std::atomic * a_ShouldTerminate, std::atomic * a_FailResult) { std::minstd_rand rnd; rnd.seed(a_Seed); auto callbackSeed = static_cast(rnd()); auto callback = getCallback(*a_LuaState, callbackSeed); while (!a_ShouldTerminate->load()) { // Pick a random operation on the Lua state and peform it: switch (rnd() % 4) { case 0: { // Get a new callback: callbackSeed = callbackSeed + 1; callback = getCallback(*a_LuaState, callbackSeed); break; } default: { // Call the callback, if still available: auto param = static_cast(rnd()); unsigned returnValue; if (callback->Call(param, cLuaState::Return, returnValue)) { if (returnValue != param + callbackSeed) { LOGWARNING("Bad value returned from the callback"); *a_FailResult = 2; a_ShouldTerminate->store(true); return; } } break; } } // switch (random) // Once in every ~10k operations, reload the lua state completely: if ((rnd() % 10000) == 0) { cLuaState::cLock lock(*a_LuaState); a_LuaState->Close(); a_LuaState->Create(); if (!a_LuaState->LoadFile("Test.lua")) { *a_FailResult = 3; a_ShouldTerminate->store(true); return; } } } // while (!a_ShouldTerminate) } static int DoTest(void) { cLuaState L("LuaThreadStress test"); L.Create(); if (!L.LoadFile("Test.lua")) { return 1; } // Start the concurrect threads: std::atomic shouldTerminate(false); std::atomic failResult(0); std::thread threads[] = { std::thread(runStress, &L, 0, &shouldTerminate, &failResult), std::thread(runStress, &L, 1, &shouldTerminate, &failResult), std::thread(runStress, &L, 2, &shouldTerminate, &failResult), std::thread(runStress, &L, 3, &shouldTerminate, &failResult), }; // Let the threads run wild: for (int i = 1; i <= NUM_SECONDS_TO_TEST; ++i) { std::this_thread::sleep_for(std::chrono::seconds(1)); LOG("Testing (%d out of %d seconds)...", i, NUM_SECONDS_TO_TEST); } // Terminate everything: LOG("Terminating the threads"); shouldTerminate = true; for (auto & t: threads) { t.join(); } LOG("Threads terminated."); return failResult.load(); } int main() { LOG("LuaThreadStress starting."); int res = DoTest(); LOG("LuaThreadStress test done: %s", (res == 0) ? "success" : "failure"); if (res != 0) { return res; } LOG("LuaThreadStress finished."); return 0; } ================================================ FILE: tests/LuaThreadStress/Stubs.cpp ================================================ // Stubs.cpp // Implements stubs of various Cuberite methods that are needed for linking but not for runtime // This is required so that we don't bring in the entire Cuberite via dependencies #include "Globals.h" #include "BlockInfo.h" #include "Bindings.h" #include "DeadlockDetect.h" #include "UUID.h" #include "Bindings/DeprecatedBindings.h" #include "Bindings/LuaJson.h" #include "Bindings/ManualBindings.h" #include "BlockEntities/BlockEntity.h" #include "Blocks/BlockHandler.h" #include "Generating/ChunkDesc.h" // fwd: struct lua_State; // Prototypes, needed by clang: extern "C" int luaopen_lsqlite3(lua_State * a_LuaState); extern "C" int luaopen_lxp(lua_State * a_LuaState); void cManualBindings::Bind(lua_State * a_LuaState) { } void DeprecatedBindings::Bind(lua_State * a_LuaState) { } void cLuaJson::Bind(cLuaState & a_LuaState) { } int tolua_AllToLua_open(lua_State * a_LuaState) { return 0; } extern "C" int luaopen_lsqlite3(lua_State * a_LuaState) { return 0; } extern "C" int luaopen_lxp(lua_State * a_LuaState) { return 0; } bool cBlockInfo::IsSolid(BLOCKTYPE) { return false; } cBoundingBox::cBoundingBox(double, double, double, double, double, double) { } cBoundingBox cBlockHandler::GetPlacementCollisionBox(BLOCKTYPE a_XM, BLOCKTYPE a_XP, BLOCKTYPE a_YM, BLOCKTYPE a_YP, BLOCKTYPE a_ZM, BLOCKTYPE a_ZP) const { return cBoundingBox(0, 0, 0, 0, 0, 0); } void cBlockHandler::OnUpdate(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cBlockPluginInterface & a_PluginInterface, cChunk & a_Chunk, const Vector3i a_RelPos) const { } void cBlockHandler::OnNeighborChanged(cChunkInterface & a_ChunkInterface, Vector3i a_BlockPos, eBlockFace a_WhichNeighbor) const { } void cBlockHandler::NeighborChanged(cChunkInterface & a_ChunkInterface, Vector3i a_BlockPos, eBlockFace a_WhichNeighbor) { } cItems cBlockHandler::ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const { return cItems(); } bool cBlockHandler::CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const { return true; } bool cBlockHandler::IsUseable() const { return false; } bool cBlockHandler::DoesIgnoreBuildCollision(const cWorld & a_World, const cItem & a_HeldItem, Vector3i a_Position, NIBBLETYPE a_Meta, eBlockFace a_ClickedBlockFace, bool a_ClickedDirectly) const { return m_BlockType == E_BLOCK_AIR; } void cBlockHandler::Check(cChunkInterface & a_ChunkInterface, cBlockPluginInterface & a_PluginInterface, Vector3i a_RelPos, cChunk & a_Chunk) const { } ColourID cBlockHandler::GetMapBaseColourID(NIBBLETYPE a_Meta) const { return 0; } bool cBlockHandler::IsInsideBlock(Vector3d a_Position, const NIBBLETYPE a_BlockMeta) const { return true; } const cBlockHandler & cBlockHandler::For(BLOCKTYPE a_BlockType) { // Dummy handler. static cBlockHandler Handler(E_BLOCK_AIR); return Handler; } OwnedBlockEntity cBlockEntity::CreateByBlockType(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World) { return nullptr; } void cDeadlockDetect::TrackCriticalSection(cCriticalSection & a_CS, const AString & a_Name) { } void cDeadlockDetect::UntrackCriticalSection(cCriticalSection & a_CS) { } void cBlockEntity::SetPos(Vector3i a_NewPos) { } bool cBlockEntity::IsBlockEntityBlockType(BLOCKTYPE a_BlockType) { return false; } OwnedBlockEntity cBlockEntity::Clone(Vector3i a_Pos) { return nullptr; } bool cLuaState::GetStackValue(int, cUUID *&) { return false; } bool cUUID::FromString(const AString &) { return true; } int BlockStringToType(const AString &) { return 0; } ================================================ FILE: tests/LuaThreadStress/Test.lua ================================================ -- Test.lua -- Implements the test support functions -- This file is loaded into the cLuaState used for stress-testing --- Returns a function that the C++ code can call -- The callback takes a single number as param and returns the sum of the param and the seed, given to this factory function (for verification) function getCallback(a_Seed) return function (a_Param) -- print("Callback " .. a_Seed .. " called with param " .. a_Param) return a_Param + a_Seed end end ================================================ FILE: tests/Network/CMakeLists.txt ================================================ include_directories(${PROJECT_SOURCE_DIR}/src/) include_directories(SYSTEM ${PROJECT_SOURCE_DIR}/lib/mbedtls/include) find_package(Threads REQUIRED) # Create a single Network library that contains all the networking code: set (Network_SRCS ${PROJECT_SOURCE_DIR}/src/OSSupport/CriticalSection.cpp ${PROJECT_SOURCE_DIR}/src/OSSupport/Event.cpp ${PROJECT_SOURCE_DIR}/src/OSSupport/HostnameLookup.cpp ${PROJECT_SOURCE_DIR}/src/OSSupport/IPLookup.cpp ${PROJECT_SOURCE_DIR}/src/OSSupport/IsThread.cpp ${PROJECT_SOURCE_DIR}/src/OSSupport/NetworkInterfaceEnum.cpp ${PROJECT_SOURCE_DIR}/src/OSSupport/NetworkLookup.cpp ${PROJECT_SOURCE_DIR}/src/OSSupport/NetworkSingleton.cpp ${PROJECT_SOURCE_DIR}/src/OSSupport/ServerHandleImpl.cpp ${PROJECT_SOURCE_DIR}/src/OSSupport/StackTrace.cpp ${PROJECT_SOURCE_DIR}/src/OSSupport/TCPLinkImpl.cpp ${PROJECT_SOURCE_DIR}/src/OSSupport/WinStackWalker.cpp ${PROJECT_SOURCE_DIR}/src/mbedTLS++/CtrDrbgContext.cpp ${PROJECT_SOURCE_DIR}/src/mbedTLS++/CryptoKey.cpp ${PROJECT_SOURCE_DIR}/src/mbedTLS++/EntropyContext.cpp ${PROJECT_SOURCE_DIR}/src/mbedTLS++/SslConfig.cpp ${PROJECT_SOURCE_DIR}/src/mbedTLS++/SslContext.cpp ${PROJECT_SOURCE_DIR}/src/mbedTLS++/X509Cert.cpp ${PROJECT_SOURCE_DIR}/src/StringUtils.cpp ) set (Network_HDRS ${PROJECT_SOURCE_DIR}/src/OSSupport/CriticalSection.h ${PROJECT_SOURCE_DIR}/src/OSSupport/Event.h ${PROJECT_SOURCE_DIR}/src/OSSupport/GetAddressInfoError.h ${PROJECT_SOURCE_DIR}/src/OSSupport/HostnameLookup.h ${PROJECT_SOURCE_DIR}/src/OSSupport/IPLookup.h ${PROJECT_SOURCE_DIR}/src/OSSupport/IsThread.h ${PROJECT_SOURCE_DIR}/src/OSSupport/Network.h ${PROJECT_SOURCE_DIR}/src/OSSupport/NetworkLookup.h ${PROJECT_SOURCE_DIR}/src/OSSupport/NetworkSingleton.h ${PROJECT_SOURCE_DIR}/src/OSSupport/ServerHandleImpl.h ${PROJECT_SOURCE_DIR}/src/OSSupport/StackTrace.h ${PROJECT_SOURCE_DIR}/src/OSSupport/TCPLinkImpl.h ${PROJECT_SOURCE_DIR}/src/OSSupport/Queue.h ${PROJECT_SOURCE_DIR}/src/OSSupport/WinStackWalker.h ${PROJECT_SOURCE_DIR}/src/mbedTLS++/CtrDrbgContext.h ${PROJECT_SOURCE_DIR}/src/mbedTLS++/CryptoKey.h ${PROJECT_SOURCE_DIR}/src/mbedTLS++/EntropyContext.h ${PROJECT_SOURCE_DIR}/src/mbedTLS++/SslConfig.h ${PROJECT_SOURCE_DIR}/src/mbedTLS++/SslContext.h ${PROJECT_SOURCE_DIR}/src/mbedTLS++/X509Cert.h ${PROJECT_SOURCE_DIR}/src/StringUtils.h ) add_library(Network ${Network_SRCS} ${Network_HDRS} ) target_link_libraries(Network event_core event_extra fmt::fmt mbedtls) if(NOT WIN32) target_link_libraries(Network event_pthreads Threads::Threads) endif() # Define individual tests: # Google: download the google.com frontpage using http client socket: add_executable(Google-exe Google.cpp) target_link_libraries(Google-exe Network) add_test(NAME Google-test COMMAND Google-exe) # EchoServer: Listen on port 9876, echo everything back: add_executable(EchoServer EchoServer.cpp) target_link_libraries(EchoServer Network) # NameLookup: Lookup hostname-to-IP and IP-to-hostname: add_executable(NameLookup NameLookup.cpp) target_link_libraries(NameLookup Network) # EnumInterfaces: List all network interfaces: add_executable(EnumInterfaces-exe EnumInterfaces.cpp) target_link_libraries(EnumInterfaces-exe Network) add_test(NAME EnumInterfaces-test COMMAND EnumInterfaces-exe) # Put all the tests into a solution folder (MSVC): set_target_properties( EchoServer Google-exe NameLookup EnumInterfaces-exe PROPERTIES FOLDER Tests/Network ) set_target_properties( Network PROPERTIES FOLDER Tests/Libraries ) ================================================ FILE: tests/Network/EchoServer.cpp ================================================ // EchoServer.cpp // Implements an Echo server using the LibEvent-based cNetwork API, as a test of that API #include "Globals.h" #include #include #include "OSSupport/Network.h" #include "OSSupport/NetworkSingleton.h" /** cTCPLink callbacks that echo everything they receive back to the remote peer. */ class cEchoLinkCallbacks: public cTCPLink::cCallbacks { // cTCPLink::cCallbacks overrides: virtual void OnLinkCreated(cTCPLinkPtr a_Link) override { ASSERT(m_Link == nullptr); m_Link = a_Link; } virtual void OnReceivedData(const char * a_Data, size_t a_Size) override { ASSERT(m_Link != nullptr); // Echo the incoming data back to outgoing data: LOGD("%p (%s:%d): Data received (%u bytes), echoing back.", static_cast(m_Link.get()), m_Link->GetRemoteIP().c_str(), m_Link->GetRemotePort(), static_cast(a_Size)); m_Link->Send(a_Data, a_Size); LOGD("Echo queued"); // Search for a Ctrl+Z, if found, drop the connection: for (size_t i = 0; i < a_Size; i++) { if (a_Data[i] == '\x1a') { m_Link->Close(); m_Link.reset(); return; } } } virtual void OnRemoteClosed(void) override { ASSERT(m_Link != nullptr); LOGD("%p (%s:%d): Remote has closed the connection.", static_cast(m_Link.get()), m_Link->GetRemoteIP().c_str(), m_Link->GetRemotePort()); m_Link.reset(); } virtual void OnError(int a_ErrorCode, const AString & a_ErrorMsg) override { ASSERT(m_Link != nullptr); LOGD("%p (%s:%d): Error %d in the cEchoLinkCallbacks: %s", static_cast(m_Link.get()), m_Link->GetRemoteIP().c_str(), m_Link->GetRemotePort(), a_ErrorCode, a_ErrorMsg.c_str()); m_Link.reset(); } /** The link attached to this callbacks instance. */ cTCPLinkPtr m_Link; }; class cEchoServerCallbacks: public cNetwork::cListenCallbacks { virtual cTCPLink::cCallbacksPtr OnIncomingConnection(const AString & a_RemoteIPAddress, UInt16 a_RemotePort) override { LOGD("New incoming connection(%s:%d).", a_RemoteIPAddress.c_str(), a_RemotePort); return std::make_shared(); } virtual void OnAccepted(cTCPLink & a_Link) override { LOGD("New client accepted (%s:%d), sending welcome message.", a_Link.GetRemoteIP().c_str(), a_Link.GetRemotePort()); // Send a welcome message to each connecting client: a_Link.Send("Welcome to the simple echo server.\r\n"); LOGD("Welcome message queued."); } virtual void OnError(int a_ErrorCode, const AString & a_ErrorMsg) override { LOGWARNING("An error occured while listening for connections: %d (%s).", a_ErrorCode, a_ErrorMsg.c_str()); } }; static void DoTest(void) { LOGD("EchoServer: starting up"); cServerHandlePtr Server = cNetwork::Listen(9876, std::make_shared()); if (!Server->IsListening()) { LOGWARNING("Cannot listen on port 9876"); abort(); } ASSERT(Server->IsListening()); // Wait for the user to terminate the server: printf("Press enter to close the server.\n"); AString line; std::getline(std::cin, line); // Close the server and all its active connections: LOG("Server terminating."); Server->Close(); ASSERT(!Server->IsListening()); Server.reset(); LOGD("Server has been closed."); } int main() { DoTest(); printf("Press enter to exit test.\n"); AString line; std::getline(std::cin, line); cNetworkSingleton::Get().Terminate(); LOG("Network test finished."); return 0; } ================================================ FILE: tests/Network/EnumInterfaces.cpp ================================================ // EnumInterfaces.cpp // Implements the main app entrypoint for the EnumInterfaces network test // Lists all network interfaces to the console #include "Globals.h" #include "OSSupport/Network.h" #include "OSSupport/NetworkSingleton.h" int main(int argc, char * argv[]) { // Initialize the cNetwork subsystem: LOGD("Initializing cNetwork..."); cNetworkSingleton::Get().Initialise(); // Enumerate all the addresses: printf("Enumerating all IP addresses...\n"); auto IPs = cNetwork::EnumLocalIPAddresses(); for (auto & ip: IPs) { LOGD(" %s", ip.c_str()); } LOGD("All addresses enumerated."); // Terminate the cNetwork subsystem: cNetworkSingleton::Get().Terminate(); LOGD("Test finished."); return 0; } ================================================ FILE: tests/Network/Google.cpp ================================================ // Google.cpp // Implements a HTTP download of the google's front page using the LibEvent-based cNetwork API #include "Globals.h" #include #include "OSSupport/Event.h" #include "OSSupport/Network.h" #include "OSSupport/NetworkSingleton.h" /** Connect callbacks that send a HTTP GET request for google.com when connected. */ class cHTTPConnectCallbacks: public cNetwork::cConnectCallbacks { cEvent & m_Event; virtual void OnConnected(cTCPLink & a_Link) override { LOGD("Connected, sending HTTP GET"); if (!a_Link.Send("GET / HTTP/1.0\r\nHost:google.com\r\n\r\n")) { LOGWARNING("Sending HTTP GET failed"); } LOGD("HTTP GET queued."); } virtual void OnError(int a_ErrorCode, const AString & a_ErrorMsg) override { LOGD("Error while connecting HTTP: %d (%s)", a_ErrorCode, a_ErrorMsg.c_str()); m_Event.Set(); } public: cHTTPConnectCallbacks(cEvent & a_Event): m_Event(a_Event) { } }; /** cTCPLink callbacks that dump everything it received to the log. */ class cDumpCallbacks: public cTCPLink::cCallbacks { cEvent & m_Event; cTCPLinkPtr m_Link; virtual void OnLinkCreated(cTCPLinkPtr a_Link) override { ASSERT(m_Link == nullptr); m_Link = a_Link; } virtual void OnReceivedData(const char * a_Data, size_t a_Size) override { ASSERT(m_Link != nullptr); // Log the incoming data size: AString Hex; CreateHexDump(Hex, a_Data, a_Size, 16); LOGD("Incoming data: %u bytes:\n%s", static_cast(a_Size), Hex.c_str()); } virtual void OnRemoteClosed(void) override { ASSERT(m_Link != nullptr); LOGD("Remote has closed the connection."); m_Link.reset(); m_Event.Set(); } virtual void OnError(int a_ErrorCode, const AString & a_ErrorMsg) override { ASSERT(m_Link != nullptr); LOGD("Error %d (%s) in the cDumpCallbacks.", a_ErrorCode, a_ErrorMsg.c_str()); m_Link.reset(); m_Event.Set(); } public: cDumpCallbacks(cEvent & a_Event): m_Event(a_Event) { } }; static void DoTest(void) { cEvent evtFinish; LOGD("Network test: Connecting to google.com:80, reading front page via HTTP."); if (!cNetwork::Connect("google.com", 80, std::make_shared(evtFinish), std::make_shared(evtFinish))) { LOGWARNING("Cannot queue connection to google.com"); abort(); } LOGD("Connect request has been queued."); evtFinish.Wait(); } int main() { LOGD("Initializing cNetwork...\n"); cNetworkSingleton::Get().Initialise(); LOGD("Testing..."); DoTest(); cNetworkSingleton::Get().Terminate(); LOGD("Network test finished"); return 0; } ================================================ FILE: tests/Network/NameLookup.cpp ================================================ // NameLookup.cpp // Implements a DNS name lookup using the LibEvent-based cNetwork API #include "Globals.h" #include #include "OSSupport/Event.h" #include "OSSupport/Network.h" #include "OSSupport/NetworkSingleton.h" class cFinishLookupCallbacks: public cNetwork::cResolveNameCallbacks { cEvent & m_Event; virtual void OnNameResolved(const AString & a_Name, const AString & a_IP) override { LOGD("%s resolves to IP %s", a_Name.c_str(), a_IP.c_str()); } virtual void OnError(int a_ErrorCode, const AString & a_ErrorMsg) override { LOGD("Error %d (%s) while performing lookup!", a_ErrorCode, a_ErrorMsg.c_str()); exit(a_ErrorCode); } virtual void OnFinished(void) override { LOGD("Resolving finished."); m_Event.Set(); } public: cFinishLookupCallbacks(cEvent & a_Event): m_Event(a_Event) { } }; static void DoTest(void) { cEvent evtFinish; // Look up google.com (has multiple IP addresses): LOGD("Network test: Looking up google.com"); if (!cNetwork::HostnameToIP("google.com", std::make_shared(evtFinish))) { LOGWARNING("Cannot resolve google.com to IP"); abort(); } LOGD("Name lookup has been successfully queued"); evtFinish.Wait(); LOGD("Lookup finished."); // Look up 8.8.8.8 (Google free DNS): LOGD("Network test: Looking up IP 8.8.8.8"); if (!cNetwork::IPToHostName("8.8.8.8", std::make_shared(evtFinish))) { LOGWARNING("Cannot resolve 8.8.8.8 to name"); abort(); } LOGD("IP lookup has been successfully queued"); evtFinish.Wait(); LOGD("IP lookup finished."); } int main() { LOGD("Initializing cNetwork..."); cNetworkSingleton::Get().Initialise(); LOGD("Running test..."); DoTest(); cNetworkSingleton::Get().Terminate(); LOGD("Network test finished"); return 0; } ================================================ FILE: tests/NoiseTest/GNUmakefile ================================================ ################################################### # # Makefile for NoiseTest # Creator: xoft # ################################################### # # Usage: # To make a release build, call "make" # To make a debug build, call "make debug=1" # ################################################### # # Macros # CC = /usr/bin/g++ all: NoiseTest ################################################### # 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 https://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 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 gdb support ################ CC_OPTIONS = -s -g -O3 -DNDEBUG CXX_OPTIONS = -s -g -O3 -DNDEBUG LNK_OPTIONS = -pthread -O3 BUILDDIR = build/release/ endif endif endif ################################################### # INCLUDE directories # INCLUDE = -I.\ -I../../source\ ################################################### # Build NoiseTest # SOURCES = NoiseTest.cpp SHAREDSOURCES = \ source/Log.cpp \ source/MCLogger.cpp \ source/Noise.cpp \ source/StringUtils.cpp \ source/OSSupport/CriticalSection.cpp \ source/OSSupport/File.cpp \ source/OSSupport/IsThread.cpp \ source/OSSupport/MakeDir.cpp \ 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)) NoiseTest : $(OBJECTS) $(SHAREDOBJECTS) $(CC) $(LNK_OPTIONS) $(OBJECTS) $(SHAREDOBJECTS) $(LNK_LIBS) -o NoiseTest clean : rm -rf $(BUILDDIR) NoiseTest ################################################### # Build the parts of Cuberite # # 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 ================================================ FILE: tests/NoiseTest/NoiseTest.cpp ================================================ // NoiseTest.cpp // Implements the main app entrypoint #include "Globals.h" #include #include "Noise.h" void SaveValues(NOISE_DATATYPE * a_Values, const AString & a_FileName) { cFile f; if (!f.Open(a_FileName, cFile::fmWrite)) { LOGWARNING("Cannot write file %s", a_FileName.c_str()); return; } for (int y = 0; y < 256; y++) { unsigned char val[256]; for (int x = 0; x < 256; x++) { val[x] = std::min(255, std::max(0, (int)(256 * a_Values[x + 256 * y]))); } f.Write(val, 256); } } clock_t TestCubicNoise(void) { cCubicNoise Cubic(0); NOISE_DATATYPE Values[256 * 256]; // Do a speed test: clock_t Begin = clock(); for (int i = 0; i < 1000; i++) { Cubic.Generate2D(Values, 256, 256, 0, (NOISE_DATATYPE)25.6, 0, (NOISE_DATATYPE)25.6); } clock_t Ticks = clock() - Begin; LOG("cCubicNoise generating 1000 * 256x256 values took %d ticks (%.02f sec)", Ticks, (double)Ticks / CLOCKS_PER_SEC); // Save the results into a file for visual comparison: SaveValues(Values, "NoiseCubic.raw"); return Ticks; } clock_t TestOldNoise(void) { cNoise Noise(0); NOISE_DATATYPE Values[256 * 256]; // Do a speed test: clock_t Begin = clock(); for (int i = 0; i < 1000; i++) { for (int y = 0; y < 256; y++) { float fy = (float)y / 10; for (int x = 0; x < 256; x++) { Values[x + 256 * y] = Noise.CubicNoise2D((float)x / 10, fy); } // for x } // for y } clock_t Ticks = clock() - Begin; LOG("cNoise generating 1000 * 256x256 values took %d ticks (%.02f sec)", Ticks, (double)Ticks / CLOCKS_PER_SEC); // Save the results into a file for visual comparison: SaveValues(Values, "NoiseOld.raw"); return Ticks; } int main(int argc, char * argv[]) { new cMCLogger(); // Create a logger (will set itself as the main instance clock_t NewTicks = TestCubicNoise(); clock_t OldTicks = TestOldNoise(); LOG("New method is %.02fx faster", (double)OldTicks / NewTicks); LOG("Press Enter to quit program"); getchar(); } ================================================ FILE: tests/OSSupport/CMakeLists.txt ================================================ find_package(Threads REQUIRED) include_directories(${PROJECT_SOURCE_DIR}/src/) # Create a single OSSupport library that contains all the OSSupport code used in the tests: set (OSSupport_SRCS ${PROJECT_SOURCE_DIR}/src/OSSupport/CriticalSection.cpp ${PROJECT_SOURCE_DIR}/src/OSSupport/Event.cpp ${PROJECT_SOURCE_DIR}/src/StringUtils.cpp ) set (OSSupport_HDRS ${PROJECT_SOURCE_DIR}/src/OSSupport/CriticalSection.h ${PROJECT_SOURCE_DIR}/src/OSSupport/Event.h ${PROJECT_SOURCE_DIR}/src/StringUtils.h ${PROJECT_SOURCE_DIR}/src/Globals.h ) add_library(OSSupport ${OSSupport_SRCS} ${OSSupport_HDRS} ) target_link_libraries(OSSupport PUBLIC fmt::fmt) # Define individual tests: # StressEvent: Stress-test the cEvent implementation: add_executable(StressEvent-exe StressEvent.cpp) target_link_libraries(StressEvent-exe OSSupport fmt::fmt Threads::Threads) add_test(NAME StressEvent-test COMMAND StressEvent-exe) # Put all the tests into a solution folder (MSVC): set_target_properties( StressEvent-exe PROPERTIES FOLDER Tests/OSSupport ) set_target_properties( OSSupport PROPERTIES FOLDER Tests/Libraries ) ================================================ FILE: tests/OSSupport/StressEvent.cpp ================================================ // StressEvent.cpp // Stress-tests the cEvent implementation #include "Globals.h" #include /** Number of repetitions of the thread loops. */ const int NUM_REPETITIONS = 5000; // Forward declarations are needed for clang void runThread(cEvent * a_Event1, cEvent * a_Event2, const char * a_ThreadName); /** Function that runs in a separate thread, notifies event1 and waits for event2, in a loop, NUM_REPETITIONS times. This basically simulates a producer / consumer pattern with 2 events, one for "queue empty", the other for "queue full". */ void runThread(cEvent * a_Event1, cEvent * a_Event2, const char * a_ThreadName) { LOG("Thread %s started", a_ThreadName); for (int i = 0; i < NUM_REPETITIONS; ++i) { // LOGD("%s: Waiting for event %p (%d)", a_ThreadName, a_Event2, i); a_Event2->Wait(); // LOGD("%s: Setting event %p (%d)", a_ThreadName, a_Event1, i); a_Event1->SetAll(); } LOG("Thread %s finished", a_ThreadName); } int main() { LOG("Test started"); cEvent event1, event2; event1.Set(); std::thread thread1(&runThread, &event1, &event2, "A"); std::thread thread2(&runThread, &event2, &event1, "B"); thread1.join(); thread2.join(); LOG("Test finished"); return 0; } ================================================ FILE: tests/SchematicFileSerializer/CMakeLists.txt ================================================ include_directories(${PROJECT_SOURCE_DIR}/src/) include_directories(SYSTEM ${PROJECT_SOURCE_DIR}/lib/) include_directories(${CMAKE_CURRENT_SOURCE_DIR}) set (SHARED_SRCS ${PROJECT_SOURCE_DIR}/src/BiomeDef.cpp ${PROJECT_SOURCE_DIR}/src/BlockArea.cpp ${PROJECT_SOURCE_DIR}/src/Cuboid.cpp ${PROJECT_SOURCE_DIR}/src/ChunkData.cpp ${PROJECT_SOURCE_DIR}/src/StringCompression.cpp ${PROJECT_SOURCE_DIR}/src/StringUtils.cpp ${PROJECT_SOURCE_DIR}/src/Noise/Noise.cpp ${PROJECT_SOURCE_DIR}/src/OSSupport/CriticalSection.cpp ${PROJECT_SOURCE_DIR}/src/OSSupport/Event.cpp ${PROJECT_SOURCE_DIR}/src/OSSupport/File.cpp ${PROJECT_SOURCE_DIR}/src/OSSupport/GZipFile.cpp ${PROJECT_SOURCE_DIR}/src/OSSupport/StackTrace.cpp ${PROJECT_SOURCE_DIR}/src/OSSupport/WinStackWalker.cpp ${PROJECT_SOURCE_DIR}/src/WorldStorage/FastNBT.cpp ${PROJECT_SOURCE_DIR}/src/WorldStorage/SchematicFileSerializer.cpp ) set (SHARED_HDRS ${PROJECT_SOURCE_DIR}/src/BiomeDef.h ${PROJECT_SOURCE_DIR}/src/BlockArea.h ${PROJECT_SOURCE_DIR}/src/Cuboid.h ${PROJECT_SOURCE_DIR}/src/ChunkData.h ${PROJECT_SOURCE_DIR}/src/Globals.h ${PROJECT_SOURCE_DIR}/src/StringCompression.h ${PROJECT_SOURCE_DIR}/src/StringUtils.h ${PROJECT_SOURCE_DIR}/src/Bindings/LuaState.h ${PROJECT_SOURCE_DIR}/src/Generating/ChunkDesc.h ${PROJECT_SOURCE_DIR}/src/Generating/PiecePool.h ${PROJECT_SOURCE_DIR}/src/Generating/Prefab.h ${PROJECT_SOURCE_DIR}/src/Generating/PrefabPiecePool.h ${PROJECT_SOURCE_DIR}/src/Generating/VerticalLimit.h ${PROJECT_SOURCE_DIR}/src/Generating/VerticalStrategy.h ${PROJECT_SOURCE_DIR}/src/Noise/Noise.h ${PROJECT_SOURCE_DIR}/src/OSSupport/CriticalSection.h ${PROJECT_SOURCE_DIR}/src/OSSupport/Event.h ${PROJECT_SOURCE_DIR}/src/OSSupport/File.h ${PROJECT_SOURCE_DIR}/src/OSSupport/GZipFile.h ${PROJECT_SOURCE_DIR}/src/OSSupport/StackTrace.h ${PROJECT_SOURCE_DIR}/src/OSSupport/WinStackWalker.h ${PROJECT_SOURCE_DIR}/src/WorldStorage/FastNBT.h ${PROJECT_SOURCE_DIR}/src/WorldStorage/SchematicFileSerializer.h ) set (SRCS SchematicFileSerializerTest.cpp Stubs.cpp ) if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") add_compile_options("-Wno-error=global-constructors") endif() source_group("Shared" FILES ${SHARED_SRCS} ${SHARED_HDRS}) source_group("Sources" FILES ${SRCS}) add_executable(SchematicFileSerializer-exe ${SRCS} ${SHARED_SRCS} ${SHARED_HDRS}) target_link_libraries(SchematicFileSerializer-exe fmt::fmt libdeflate) if (WIN32) target_link_libraries(SchematicFileSerializer-exe ws2_32) endif() add_test(NAME SchematicFileSerializer-test WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMAND SchematicFileSerializer-exe) # Put the projects into solution folders (MSVC): set_target_properties( SchematicFileSerializer-exe PROPERTIES FOLDER Tests ) ================================================ FILE: tests/SchematicFileSerializer/SchematicFileSerializerTest.cpp ================================================ // SchematicFileSerializerTest.cpp // Implements the SchematicFileSerializer test main entrypoint #include "Globals.h" #include "../TestHelpers.h" #include "WorldStorage/SchematicFileSerializer.h" static void DoTest(void) { cBlockArea ba; ba.Create(21, 256, 21); ba.RelLine(0, 0, 0, 9, 8, 7, cBlockArea::baTypes | cBlockArea::baMetas, E_BLOCK_WOODEN_STAIRS, 1); const auto Schematic = cSchematicFileSerializer::SaveToSchematicString(ba); cBlockArea ba2; cSchematicFileSerializer::LoadFromSchematicString(ba2, Schematic.GetView()); } IMPLEMENT_TEST_MAIN("SchematicFileSerializer", DoTest(); ) ================================================ FILE: tests/SchematicFileSerializer/Stubs.cpp ================================================ // Stubs.cpp // Implements stubs of various Cuberite methods that are needed for linking but not for runtime // This is required so that we don't bring in the entire Cuberite via dependencies #include "Globals.h" #include "BlockInfo.h" #include "Blocks/BlockHandler.h" #include "BlockEntities/BlockEntity.h" cBoundingBox::cBoundingBox(double, double, double, double, double, double) { } cBoundingBox cBlockHandler::GetPlacementCollisionBox(BLOCKTYPE a_XM, BLOCKTYPE a_XP, BLOCKTYPE a_YM, BLOCKTYPE a_YP, BLOCKTYPE a_ZM, BLOCKTYPE a_ZP) const { return cBoundingBox(0, 0, 0, 0, 0, 0); } void cBlockHandler::OnUpdate(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cBlockPluginInterface & a_PluginInterface, cChunk & a_Chunk, const Vector3i a_RelPos) const { } void cBlockHandler::OnNeighborChanged(cChunkInterface & a_ChunkInterface, Vector3i a_BlockPos, eBlockFace a_WhichNeighbor) const { } void cBlockHandler::NeighborChanged(cChunkInterface & a_ChunkInterface, Vector3i a_BlockPos, eBlockFace a_WhichNeighbor) { } cItems cBlockHandler::ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const { return cItems(); } bool cBlockHandler::CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta) const { return true; } bool cBlockHandler::IsUseable() const { return false; } bool cBlockHandler::DoesIgnoreBuildCollision(const cWorld & a_World, const cItem & a_HeldItem, Vector3i a_Position, NIBBLETYPE a_Meta, eBlockFace a_ClickedBlockFace, bool a_ClickedDirectly) const { return m_BlockType == E_BLOCK_AIR; } void cBlockHandler::Check(cChunkInterface & a_ChunkInterface, cBlockPluginInterface & a_PluginInterface, Vector3i a_RelPos, cChunk & a_Chunk) const { } ColourID cBlockHandler::GetMapBaseColourID(NIBBLETYPE a_Meta) const { return 0; } bool cBlockHandler::IsInsideBlock(Vector3d a_Position, const NIBBLETYPE a_BlockMeta) const { return true; } const cBlockHandler & cBlockHandler::For(BLOCKTYPE a_BlockType) { // Dummy handler. static cBlockHandler Handler(E_BLOCK_AIR); return Handler; } bool cBlockEntity::IsBlockEntityBlockType(BLOCKTYPE a_BlockType) { return false; } void cBlockEntity::SetPos(Vector3i a_NewPos) { } OwnedBlockEntity cBlockEntity::Clone(Vector3i a_Pos) { return nullptr; } OwnedBlockEntity cBlockEntity::CreateByBlockType(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World) { return nullptr; } ================================================ FILE: tests/TestHelpers.h ================================================ // Helper macros for writing exception-based tests /* The tests are supposed to be contained in small static functions that get called from a main function provided by this framework: static void test1() { // Perform the test } ... IMPLEMENT_TEST_MAIN("TestName", test1(); ... ) */ /** The exception that is thrown if a test fails. It doesn't inherit from any type so that it is not possible to catch it by a mistake, it needs to be caught explicitly (used in the TEST_THROWS). It bears a single message that is to be displayed to stderr. */ class TestException { public: TestException(const AString & aFileName, int aLineNumber, const AString & aFunctionName, const AString & aMessage): mFileName(aFileName), mLineNumber(aLineNumber), mFunctionName(aFunctionName), mMessage(aMessage) { } AString mFileName; int mLineNumber; AString mFunctionName; AString mMessage; }; /** Checks that the two values are equal; if not, throws a TestException. */ #define TEST_EQUAL(VAL1, VAL2) \ do { \ if (VAL1 != VAL2) \ { \ throw TestException( \ __FILE__, __LINE__, __FUNCTION__, \ fmt::format(FMT_STRING("Equality test failed: {} != {}"), #VAL1, #VAL2) \ ); \ } \ } while (false) /** Checks that the two values are equal; if not, throws a TestException, includes the specified message. */ #define TEST_EQUAL_MSG(VAL1, VAL2, MSG) \ do { \ if (VAL1 != VAL2) \ { \ throw TestException( \ __FILE__, __LINE__, __FUNCTION__, \ fmt::format(FMT_STRING("Equality test failed: {} != {} ({})"), #VAL1, #VAL2, MSG) \ ); \ } \ } while (false) /** Checks that the two values are not equal; if they are, throws a TestException. */ #define TEST_NOTEQUAL(VAL1, VAL2) \ do { \ if (VAL1 == VAL2) \ { \ throw TestException( \ __FILE__, __LINE__, __FUNCTION__, \ fmt::format(FMT_STRING("Inequality test failed: {} == {}"), #VAL1, #VAL2) \ ); \ } \ } while (false) /** Checks that the statement evaluates to true. */ #define TEST_TRUE(X) TEST_EQUAL(X, true) /** Checks that the statement evaluates to false. */ #define TEST_FALSE(X) TEST_EQUAL(X, false) /** Checks that the statement returns a value greater than or equal to the specified value. */ #define TEST_GREATER_THAN_OR_EQUAL(Stmt, Val) \ do { \ if (Stmt < Val) \ { \ throw TestException(__FILE__, __LINE__, __FUNCTION__, fmt::format(FMT_STRING("Comparison failed: {} < {}"), #Stmt, #Val)); \ } \ } while (false) /** Checks that the statement returns a value less than or equal to the specified value. */ #define TEST_LESS_THAN_OR_EQUAL(Stmt, Val) \ do { \ if (Stmt > Val) \ { \ throw TestException(__FILE__, __LINE__, __FUNCTION__, fmt::format(FMT_STRING("Comparison failed: {} > {}"), #Stmt, #Val)); \ } \ } while (false) /** Checks that the statement throws an exception of the specified class. */ #define TEST_THROWS(Stmt, ExcClass) \ do { \ try \ { \ Stmt; \ throw TestException( \ __FILE__, __LINE__, __FUNCTION__, \ fmt::format(FMT_STRING("Failed to throw an exception of type {}"), #ExcClass) \ ); \ } \ catch (const ExcClass &) \ { \ /* This is the expected case. */ \ } \ catch (const std::exception & exc) \ { \ throw TestException( \ __FILE__, __LINE__, __FUNCTION__, \ fmt::format( \ FMT_STRING("An unexpected std::exception descendant was thrown, was expecting type {}. Message is: {}"), \ #ExcClass, exc.what() \ ) \ ); \ } \ catch (...)\ { \ throw TestException( \ __FILE__, __LINE__, __FUNCTION__, \ fmt::format(FMT_STRING("An unexpected unknown exception object was thrown, was expecting type {}"), #ExcClass) \ ); \ } \ } while (false) /** Checks that the statement throws an exception of any type. */ #define TEST_THROWS_ANY(Stmt) \ do { \ try \ { \ Stmt; \ throw TestException( \ __FILE__, __LINE__, __FUNCTION__, \ "Failed to throw an exception of any type" \ ); \ } \ catch (const TestException & exc) \ { \ throw exc; \ } \ catch (...)\ { \ /* This is the expected case */ \ } \ } while (false) /** Fails the test unconditionally, with the specified message. */ #define TEST_FAIL(MSG) \ throw TestException(__FILE__, __LINE__, __FUNCTION__, MSG) /** Checks that the statement causes an ASSERT trigger. */ #ifdef NDEBUG #define TEST_ASSERTS(Stmt) LOG("Skipped, cannot test in Release mode: TEST_ASSERT(%s); (%s:%d)", #Stmt, __FILE__, __LINE__) #else #define TEST_ASSERTS(Stmt) TEST_THROWS(Stmt, cAssertFailure) #endif // else NDEBUG /** Used to implement the main() function for tests. */ #define IMPLEMENT_TEST_MAIN(TestName, TestCode) \ int main() \ { \ LOG("Test started: %s", TestName); \ \ try \ { \ TestCode; \ } \ catch (const TestException & exc) \ { \ LOGERROR("Test has failed at file %s, line %d, function %s: %s", \ exc.mFileName.c_str(), \ exc.mLineNumber, \ exc.mFunctionName.c_str(), \ exc.mMessage.c_str() \ ); \ return 1; \ } \ catch (const std::exception & exc) \ { \ LOGERROR("Test has failed, an exception was thrown: %s", exc.what()); \ return 1; \ } \ catch (const cAssertFailure & exc) \ { \ LOGERROR("Test has failed, an unexpected ASSERT was triggered at %s:%d: %s", \ exc.fileName().c_str(), exc.lineNumber(), exc.expression().c_str() \ ); \ return 1; \ } \ catch (...) \ { \ LOGERROR("Test has failed, an unhandled exception was thrown."); \ return 1; \ } \ \ LOG("Test finished"); \ return 0; \ } ================================================ FILE: tests/UUID/CMakeLists.txt ================================================ set (SHARED_SRCS ${PROJECT_SOURCE_DIR}/src/UUID.cpp ${PROJECT_SOURCE_DIR}/src/StringUtils.cpp ) set (SHARED_HDRS ${PROJECT_SOURCE_DIR}/src/UUID.h ${PROJECT_SOURCE_DIR}/src/StringUtils.h ) set (SRCS UUIDTest.cpp ) source_group("Shared" FILES ${SHARED_SRCS} ${SHARED_HDRS}) source_group("Sources" FILES ${SRCS}) add_executable(UUIDTest ${SRCS} ${SHARED_SRCS} ${SHARED_HDRS}) target_link_libraries(UUIDTest mbedcrypto fmt::fmt) target_compile_definitions(UUIDTest PRIVATE TEST_GLOBALS=1) target_include_directories(UUIDTest PRIVATE ${PROJECT_SOURCE_DIR}/src/ ${PROJECT_SOURCE_DIR}/lib/mbedtls/include ) add_test(NAME UUID-test COMMAND UUIDTest) # Put the projects into solution folders (MSVC): set_target_properties( UUIDTest PROPERTIES FOLDER Tests ) ================================================ FILE: tests/UUID/UUIDTest.cpp ================================================ // UUIDTest.cpp #include "Globals.h" #include "../TestHelpers.h" #include "UUID.h" #include // for std::iota /** Test that FromString -> ToShortString preserves the original value for short UUIDs. */ static void UUIDFromStringToShortString() { const char TestStrings[][33] { "0123456789abcdef0123456789ABCDEF", "d188b2648cc311e7bb31be2e44b06b34", "e760d270d8b34288b895d9f78a31e083", "7052f2f2594246abb8e3fed602158870", "7f14d4b60cd84ba7885c8301b67ce891", "57be7039250548b590af272291fabcfa" }; for (auto TestString : TestStrings) { cUUID UUID; TEST_TRUE(UUID.FromString(TestString)); auto ResultString = UUID.ToShortString(); // Result should be equivalent to original TEST_EQUAL(NoCaseCompare(ResultString, TestString), 0); // And should be all lower case TEST_EQUAL(ResultString, StrToLower(ResultString)); } } /** Test that FromString -> ToLongString preserves the original value for long UUIDs. */ static void UUIDFromStringToLongString() { const char TestStrings[][37] { "01234567-89ab-cdef-0123-456789ABCDEF", "d188b264-8cc3-11e7-bb31-be2e44b06b34", "e760d270-d8b3-4288-b895-d9f78a31e083", "7052f2f2-5942-46ab-b8e3-fed602158870", "7f14d4b6-0cd8-4ba7-885c-8301b67ce891", "57be7039-2505-48b5-90af-272291fabcfa" }; for (auto TestString : TestStrings) { cUUID UUID; TEST_TRUE(UUID.FromString(TestString)); auto ResultString = UUID.ToLongString(); // Result should be equivalent to original TEST_EQUAL(NoCaseCompare(ResultString, TestString), 0); // And should be all lower case TEST_EQUAL(ResultString, StrToLower(ResultString)); } } /** Test that FromRaw -> ToRaw preserves the original value. */ static void UUIDFromRawToRaw() { std::array TestData[16]{}; // Fill test data with all values 0 - 255 for (int i = 0; i != 16; ++i) { std::iota(begin(TestData[i]), end(TestData[i]), i * 16); } for (const auto & TestRaw : TestData) { cUUID UUID; UUID.FromRaw(TestRaw); auto ResultRaw = UUID.ToRaw(); TEST_EQUAL(ResultRaw, TestRaw); } } /** Test that IsNil correctly identifies nil UUIDs. */ static void UUIDNil() { const auto NilString = "00000000-0000-0000-0000-000000000000"; const auto NonNilString = "e760d270-d8b3-4288-b895-d9f78a31e083"; { cUUID UUID; TEST_TRUE(UUID.FromString(NilString)); TEST_TRUE(UUID.IsNil()); } { cUUID UUID; TEST_TRUE(UUID.FromString(NonNilString)); TEST_TRUE(!UUID.IsNil()); } } /** Test that variant and version numbers are read correctly. */ static void UUIDType() { // From issue #4209 const char TestStrings[][33] { "31cfcbeea8f2324a86dbccb1d5aaa6f8", "3f2e1dd234a03b6b824c5a0e74083b1e" }; for (const auto & String : TestStrings) { cUUID UUID; TEST_TRUE(UUID.FromString(String)); TEST_EQUAL(UUID.Variant(), 1); TEST_EQUAL(UUID.Version(), 3); } } IMPLEMENT_TEST_MAIN("UUID", UUIDFromStringToShortString(); UUIDFromStringToLongString(); UUIDFromRawToRaw(); UUIDNil(); UUIDType(); )